[
  {
    "path": "Code/Core/Debug/Assert.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDebug (DBG)\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tassert.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tAssert support code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdio.h>\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/debug.h>\r\n\r\n#include <sys/config/config.h>\r\n\r\n#ifndef __PLAT_WN32__\r\n#include <gfx/gfxman.h>\r\n#endif // __PLAT_WN32__\r\n\r\n#ifdef __PLAT_NGPS__\r\nint DumpUnwindStack( int iMaxDepth, int *pDest );\r\n#include <libdev.h>\r\n#endif\r\n\r\n#ifdef __PLAT_NGC__\r\n#include <dolphin.h>\r\n#define _output OSReport\r\n#else\r\n#define _output printf\r\n#endif\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Dbg\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic const int vASSERT_BUFFER_SIZE = 512;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic \tAssertTrap*\t\tassert_trap_handler = NULL;\r\nstatic \tbool\t\t\tscreen_assert_active = false;\r\n\r\n// made public for Dbg_ Macros\r\nchar*\t\t\tmsg_null_pointer\t\t= \"Null Pointer\";\r\nchar*\t\t\tmsg_misaligned_pointer\t= \"Pointer not aligned\";\t\t\t \r\nchar*\t\t\tmsg_pointer_to_free_mem\t= \"Pointer to free mem\";\r\nchar*\t\t\tmsg_unknown_reason\t\t= \"No reason supplied\";\r\nchar*\t\t\tmsg_type_mismatch\t\t= \"Type Mismatch: \\\"%s\\\" is of type \\\"%s\\\" - not a valid \\\"%s\\\"\";\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tset_trap( AssertTrap* trap ) \r\n{\r\n\tassert_trap_handler = trap;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tscreen_assert( bool on ) \r\n{\r\n\tscreen_assert_active = on;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef\t__NOPT_DEBUG__\r\nvoid\t\tAssert( char* file, uint line, Signature& sig, char* reason )\r\n#else\r\nvoid\t\tAssert( char* file, uint line, char* reason )\r\n#endif\r\n{\r\n\tstatic\tchar\t\tassert_buffer1[vASSERT_BUFFER_SIZE];\r\n#ifdef\t__NOPT_DEBUG\r\n\tstatic\tchar\t\tassert_buffer2[vASSERT_BUFFER_SIZE];\r\n#endif\t\r\n\tstatic\tchar\t\tassert_buffer3[vASSERT_BUFFER_SIZE];\r\n\tstatic\tchar*\t\ttmp1 = assert_buffer1; \r\n#ifdef\t__NOPT_DEBUG\r\n\tstatic\tchar*\t\ttmp2 = assert_buffer2; \r\n#endif\t\r\n\tstatic\tchar*\t\ttmp3 = assert_buffer3; \r\n\r\n\r\n#if !( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))\r\n\t\r\n\tstatic int again = 0;\r\n\tif (again) \r\n\t{\r\n\t\t_output (\"MEM CONTEXT: %s\\n\",Mem::Manager::sHandle().GetContextName());\r\n\t\t\t\t\r\n\t\t_output( \"LOOPED ASSERTION: %s(%d)\\n%s\\n\\n\", \r\n\t\t\tfile, line, reason );\r\n\t\t_output (\"Real Assertion: %s\\n%s\\n\",tmp1,tmp3);\r\n\t\twhile (1);\t\t\t// and hang... \r\n\t}\r\n\tagain = 1;\r\n\t\r\n\t_output (\"\\n--------------------------------------------------\\nPLEASE COPY FROM A FEW LINES ABOVE HERE\\n\\nCURRENT MEM CONTEXT: %s\\n\\n\"\r\n\t\t\t,Mem::Manager::sHandle().GetContextName());\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n//\tMem::Heap* heap = mem_man.TopDownHeap();\r\n//\tMem::Region* region = heap->ParentRegion();\r\n//\t_output (\"TopDown  Fragmentation %7dK, in %5d Blocks\\n\",heap->mFreeMem.m_count / 1024, heap->mFreeBlocks.m_count);\r\n//\t_output (\"         used          %7dK, in %5d Blocks\\n\",heap->mUsedMem.m_count / 1024, heap->mUsedBlocks.m_count);\r\n//\theap = mem_man.BottomUpHeap();\r\n//\t_output (\"BottomUp Fragmentation %7dK, in %5d Blocks\\n\",heap->mFreeMem.m_count / 1024, heap->mFreeBlocks.m_count);\r\n//\t_output (\"         used          %7dK, in %5d Blocks\\n\",heap->mUsedMem.m_count / 1024, heap->mUsedBlocks.m_count);\r\n//\t_output (\"Shared Region %dK free out of %d K available\\n\", region->MemAvailable() / 1024, region->TotalSize() / 1024 );\r\n\r\n\t_output(\"Name            Used  Frag  Free   Min  Blocks\\n\");\r\n\t_output(\"--------------- ----- ----- ---- ------ ------\\n\");\r\n\tMem::Heap* heap;\r\n\tfor (heap = mem_man.FirstHeap(); heap != NULL; heap = mem_man.NextHeap(heap))\r\n\t{\t\t\r\n\t\t\tMem::Region* region = heap->ParentRegion();\t\t\t\r\n\t\t\t_output( \"%12s: %5dK %4dK %4dK %4dK  %5d \\n\",\r\n\t\t\t\t\theap->GetName(),\r\n\t\t\t\t\theap->mUsedMem.m_count / 1024,\r\n\t\t\t\t\theap->mFreeMem.m_count / 1024,\r\n\t\t\t\t\tregion->MemAvailable() / 1024,\r\n\t\t\t\t\tregion->MinMemAvailable() / 1024,\r\n\t\t\t\t\theap->mUsedBlocks.m_count\r\n\t\t\t\t\t);\t\t\t\t\t\t\t\t\t\t\r\n\t}\r\n\t\r\n\t_output( \"FILE:      %s(%d)\\nASSERTION: %s\\n\\n\", \r\n\t\tfile, line, reason ); \r\n\t_output( tmp1, \"FILE:      %s(%d) \", file, line ); \r\n\t_output( tmp3, \"ASSERTION: %s\", reason ); \r\n\t// attempt to dump the call stack\r\n\t// requires that you have the correct .map file, along with the executable\r\n\t#ifndef __PLAT_WN32__\r\n\tMemView_FindLeaks();\r\n\t#endif\r\n\t\t\r\n\t_output( \"\\nCALL STACK ..........................\\n\\n\");\r\n\t\r\n\t#ifdef __PLAT_NGPS__\r\n\tDumpUnwindStack( 40, NULL );\r\n\t#endif\r\n\t\t\r\n\t\r\n#endif\r\n\r\n\tsprintf( tmp1, \"FILE:      %s(%d) \", file, line ); \r\n\tsprintf( tmp3, \"ASSERTION: %s\", reason ); \r\n\r\n#ifndef __PLAT_NGC__\r\n#ifndef __PLAT_WN32__\r\n// Mick: Attempt to save a screenshot\r\n//\tDbg_Printf(\"Attempting to save screenshot 'screens\\\\Assert???.bmp'\\n\");\r\n\tif (!Config::CD())\r\n\t{\r\n\t\tGfx::Manager * gfx_manager = Gfx::Manager::Instance();\r\n\t\tgfx_manager->ScreenShot( \"Assert\" );\r\n\t}\r\n#endif\r\n\r\n\tif ( screen_assert_active )\r\n\t{\r\n\t\tscreen_assert_active = false;\r\n\r\n#ifndef __PLAT_WN32__\r\n\t\tGfx::Manager* gfx_man = Gfx::Manager::Instance();\r\n\r\n\t\tgfx_man->AssertText ( 0, tmp1 );\r\n\r\n#ifdef\t__NOPT_DEBUG\r\n\t\tsprintf( tmp2, \"%s\", &sig.GetName() ); \r\n\t\tgfx_man->AssertText ( 1, tmp2 );\r\n#endif\r\n\t\tgfx_man->AssertText ( 2, tmp3 );\r\n\r\n\t\tgfx_man->AssertFlush();\r\n#endif\t// __PLAT_WN32__\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n#ifdef\t__NOPT_DEBUG\r\n\tsprintf( tmp1, \"ASSERTION: %s(%d) %s\\n%s\\n\\n\", \r\n\t\tfile, line, &sig.GetName(), reason ); \r\n#else\r\n\tsprintf( tmp1, \"FILE:      %s(%d)\\nASSERTION: %s\\n\\n\", \r\n\t\tfile, line, reason ); \r\n#endif\r\n\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#if 0 \t// does not seem to output anything...\r\n\tsceDevConsInit(); // Initialise screen console output\r\n\tint console = sceDevConsOpen(\r\n\t(2048 - 640/2 + 20) << 4, // top left GS X primitive coord\r\n\t(2048 - 448/2 + 20) << 4, // top left GS Y primitive coord\r\n\t80, // Number of chars (X)\r\n\t5); // Number of chars (Y)\r\n\tsceDevConsAttribute(console, 7); // Output in white (default colours can be\r\n\t\t\t\t\t\t\t\t\t// redefined by sceDevConsSetColor)\r\n\tsceDevConsClear(console);\r\n\tsceDevConsPrintf(console,\ttmp1);\r\n\tsceDevConsPrintf(console,\t\"blah \\n\");\r\n\tsceDevConsPrintf(console,\t\"blah2 \\n\");\r\n\tsceDevConsPrintf(console,\t\"blah3 \\n\");\r\n\tsceDevConsDraw(console);\t\r\n#endif\r\n#endif\r\n\r\n\r\n\tif ( assert_trap_handler != NULL )\r\n\t{\r\n\t\t_output (\"MEM CONTEXT: %s\\n\",Mem::Manager::sHandle().GetContextName());\r\n\r\n\t\tDbg_Printf( \"%s\\n\", tmp1 );\r\n\t\tassert_trap_handler( tmp1 );\r\n\t}\r\n\telse\r\n\t{\t\t\t\t\t\t   \r\n\t\tDbg_Printf( \"%s\\n\", tmp1 );\r\n\t\tDbg_Printf( \"!!NO TRAP HANDLER SET!!\\n\" );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))\r\nvoid\t\tassert_vcc( char* file, uint line, char* reason )\r\n{\r\n\tstatic\tchar\t\tassert_buffer[vASSERT_BUFFER_SIZE];\r\n\tstatic\tchar*\t\ttmp = assert_buffer; \r\n\r\n\tsprintf( tmp, \"ASSERTION: %s(%d)\\n%s\\n\\n\", \r\n\t\tfile, line, reason ); \r\n\r\n\tif ( assert_trap_handler != NULL )\r\n\t{\r\n\t\tDbg_Printf( \"%s\\n\", tmp );\r\n\t\tassert_trap_handler( tmp );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Printf( \"%s\\n\", tmp );\r\n\t\tDbg_Printf( \"!!NO TRAP HANDLER SET!!\\n\" );\r\n\t}\r\n}\r\n#endif // #ifdef __PLAT_XBOX__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Dbg\r\n\r\n#endif\t//__NOPT_DEBUG__\r\n"
  },
  {
    "path": "Code/Core/Debug/Checks.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDebug (Dbg_)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\tmjb\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/debug/checks.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEBUG_CHECKS_H\r\n#define __CORE_DEBUG_CHECKS_H\r\n\r\n#ifndef __CORE_DEBUG_LOG_H\r\n#include <core/log.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include \"signatrs.h\"\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Dbg\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntypedef void ( AssertTrap ) ( char* message );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern\tchar*\t\tmsg_unknown_reason;\t\t\t// message strings \r\nextern\tchar*\t\tmsg_null_pointer;\t\t\t \r\nextern\tchar*\t\tmsg_misaligned_pointer;\t\t\t \r\nextern\tchar*\t\tmsg_pointer_to_free_mem;\r\nextern\tchar*\t\tmsg_type_mismatch;\t\t\t \r\n\r\nextern \tAssertTrap\tdefault_trap;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __NOPT_DEBUG__\r\nvoid\tAssert ( char* file, uint line, Signature& sig, char* reason = msg_unknown_reason );\r\n#else\r\nvoid\tAssert ( char* file, uint line, char* reason = msg_unknown_reason );\r\n#endif\r\n\r\nvoid\tpad_printf ( const char* text, ... );\r\nvoid\tset_trap( AssertTrap* trap = default_trap );\r\nvoid\tscreen_assert( bool on = false );\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Dbg\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define Dbg_SetTrap(A)\t\t\t{ Dbg::set_trap(A); } \r\n#define Dbg_SetScreenAssert(A)\t{ Dbg::screen_assert(A); }\r\n\r\n/******************************************************************/\r\n/*                     Assertions                                 */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\r\n\r\n#define Dbg_Assert(_c)  \t\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\nif ( !(_c))\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tDbg::Assert( __FILE__, __LINE__, Dbg_signature );\t\t\t\\\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#define Dbg_MsgAssert( _c, _params )\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\nif( !( _c ))\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tDbg::pad_printf _params;\t\t\t\t\t\t\t\t\t\\\r\n\tDbg::Assert( __FILE__, __LINE__,\tDbg_signature,\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\tDbg::sprintf_pad );\t\t\\\r\n}\r\n\r\n#else   // __NOPT_DEBUG__\r\n\r\n// Mick:  If we have assertions, but are not in DEBUG mode\r\n// then we don not have the Dbg_signature thing\r\n// so we just pass NULL to assert()\r\n\r\n#define Dbg_Assert(_c)  \t\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\nif ( !(_c))\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tDbg::Assert ( __FILE__, __LINE__, NULL );\t\t\t\t\t\\\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef __PLAT_WN32__\r\n\r\n#ifdef _CONSOLE\r\n#define Dbg_MsgAssert( _c, _params )\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\nif( !( _c ))\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tprintf(\"\\nGame code assert!\\n\");\t\t\t\t\t\t\t\\\r\n\tprintf(\"File %s, line %d\\n\",__FILE__,__LINE__);\t\t\t\t\\\r\n\tprintf _params;\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tprintf(\"\\nPress CTRL-C to quit ... \");\t\t\t\t\t\t\\\r\n\twhile(1);\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n}\r\n#else\r\n#define Dbg_MsgAssert( _c, _params )\r\n#endif\r\n\r\n#else\r\n\r\n#define Dbg_MsgAssert( _c, _params )\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\nif( !( _c ))\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tDbg::pad_printf _params;\t\t\t\t\t\t\t\t\t\\\r\n\tDbg::Assert( __FILE__, __LINE__, Dbg::sprintf_pad );\t\t\\\r\n}\r\n#endif\r\n\r\n#endif\t// __NOPT_DEBUG__\r\n\r\n#ifdef __PLAT_NGPS__\r\n#define Dbg_MsgLog( _params )\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tDbg::pad_printf _params;\t\t\t\t\t\t\t\\\r\n\tLog::AddEntry(__FILE__,__LINE__,__PRETTY_FUNCTION__,Dbg::sprintf_pad);\t\t\\\r\n}\r\n\t\r\n#define Dbg_Log( )\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tLog::AddEntry(__FILE__,__LINE__,__PRETTY_FUNCTION__);\t\t\t\\\r\n}\r\n#else\r\n#define Dbg_MsgLog( _params )\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tDbg::pad_printf _params;\t\t\t\t\t\t\t\\\r\n\tLog::AddEntry(__FILE__,__LINE__,__FUNCTION__,Dbg::sprintf_pad);\t\t\\\r\n}\r\n\t\r\n#define Dbg_Log( )\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tLog::AddEntry(__FILE__,__LINE__,__FUNCTION__);\t\t\t\\\r\n}\r\n#endif\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef __NOPT_MEM_DEBUG__\r\n\r\n#define Dbg_AssertPtr(_p)\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tif ((_p) == NULL )\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\tDbg::Assert ( __FILE__,\t__LINE__,\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t Dbg_signature, Dbg::msg_null_pointer );\t\t\\\r\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\telse if ( *((uint64*)(nAlignDown(_p))) == Mem::vFREE_BLOCK )\t\\\r\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\tDbg::Assert ( __FILE__,\t__LINE__,\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t Dbg_signature, Dbg::msg_pointer_to_free_mem );\t\\\r\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n}\r\n\r\n\r\n#else // __NOPT_MEM_DEBUG__\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\r\n#define Dbg_AssertPtr(_p)\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tif ((_p) == NULL )\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\tDbg::Assert ( __FILE__,\t__LINE__,\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t Dbg_signature, Dbg::msg_null_pointer );\t\t\\\r\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n}\r\n\r\n#else\r\n\r\n\r\n#define Dbg_AssertPtr(_p)\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tif ((_p) == NULL )\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\tDbg::Assert ( __FILE__,\t__LINE__,\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t Dbg::msg_null_pointer );\t\t\\\r\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n}\r\n\r\n#endif //__NOPT_DEBUG__\r\n\r\n#endif // __NOPT_MEM_DEBUG__\r\n\r\n/******************************************************************/\r\n/*                     Type Checking                              */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef __NOPT_FULL_DEBUG__\r\n\r\n#define Dbg_AssertType(_c,_t)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tDbg_AssertPtr(_c);       \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tDbg_MsgAssert( nAligned(_c), Dbg::msg_misaligned_pointer );\t\t\t\t\t\t\t\t\\\r\n\tDbg_MsgAssert(((_c)->classStamp != Spt::Class::vDELETED_CLASS ),\"Deleted Class\" );\t\t\\\r\n\tDbg_MsgAssert(((_c)->classStamp == Spt::Class::vREGISTERED_CLASS ), \"Corrupt Class\" );\t\\\r\n\tDbg_MsgAssert(((_c)->vClassNode()->IsDerivedOrSame(*_t::sClassNode())),\t\t\t\t\t\\\r\n\t\tDbg::msg_type_mismatch,#_c,(_c)->vClassNode()->GetName(),#_t);\t\t\t\t\t\t\\\r\n}\r\n\r\n#define Dbg_AssertThis\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tDbg_AssertPtr(this);       \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tDbg_MsgAssert( nAligned(this), Dbg::msg_misaligned_pointer );\t\t\t\t\t\t\t\\\r\n\tDbg_MsgAssert((classStamp != Spt::Class::vDELETED_CLASS ),\"Deleted Class\" );\t\t\t\\\r\n\tDbg_MsgAssert((classStamp == Spt::Class::vREGISTERED_CLASS ), \"Corrupt Class\" );\t\t\\\r\n\tDbg_MsgAssert((vClassNode()->IsDerivedOrSame(*sClassNode())),\t\t\t\t\t\t\t\\\r\n\t\tDbg::msg_type_mismatch,\"this\", vClassNode()->GetName(),sClassNode()->GetName());\t\\\r\n}\r\n\r\n#else // __NOPT_FULL_DEBUG__\r\n\r\n#define Dbg_AssertType(_c,_t)\tDbg_AssertPtr(_c)\r\n#define Dbg_AssertThis\t\t\tDbg_AssertPtr(this)\r\n\r\n#endif // __NOPT_FULL_DEBUG__\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tStubs\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#else\r\n\r\n#define Dbg_MsgAssert( _c, _params )\r\n\r\n#define Dbg_SetTrap(_f)\r\n\r\n#ifdef __NOPT_ASSERT__\r\n#define Dbg_SetScreenAssert(A)\t{ Dbg::screen_assert(A); }\r\n#else\r\n#define Dbg_SetScreenAssert(_b)\r\n#endif\r\n\r\n#define Dbg_Assert(_c)\r\n#define Dbg_AssertPtr(_p)\r\n#define Dbg_AssertType(_c,_t)\r\n#define Dbg_AssertThis\r\n\r\n#define Dbg_MsgLog( _params )\r\n#define Dbg_Log( )\r\n\r\n\r\n#endif\t// __NOPT_ASSERT__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#endif\t// __CORE_DEBUG_CHECKS_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Debug/Debug.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDebug (DBG)\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tdebug.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tDebug message support.\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define __ERROR_STRINGS__\r\n\r\n#include <stdio.h>\r\n#include <stdarg.h>\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <sys/config/config.h>\r\n#include <sys/timer.h>\r\n#include <sys/mem/memman.h>\r\n\r\n#ifdef\t__PLAT_NGC__\r\n#include <dolphin.h>\r\n#endif\t__PLAT_NGC__\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDbg_DefineProject( Core, \"Core Library\")\r\n\r\n\r\n\r\nnamespace Dbg\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern void\t\t\t\t\tset_up ( void );\r\nextern void\t\t\t\t\tclose_down ( void );\r\nextern OutputCode\t\t\tdefault_print;\r\nextern AssertTrap\t\t\tdefault_trap;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic const int vBUFFER_SIZE = 512;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic\tchar\t\t\t\t\ts_sprintf_buffer[vBUFFER_SIZE];\r\nstatic\tchar\t\t\t\t\ts_printf_buffer[vBUFFER_SIZE];\r\nstatic\tFlags< Level >\t\t\ts_level_mask = mNONE;\r\n\r\n#ifdef\t__NOPT_DEBUG__\r\nstatic\tchar*\ts_typename[] =\r\n{\r\n\t\"ERROR!!\",\r\n\t\"WARNING\",\r\n\t\"Notify \",\r\n\t\"Message\"\r\n};\r\n#endif\r\n\r\nstatic \tOutputCode*\t\toutput;\r\n\r\n\r\n// public for Dbg_ Macros\r\nchar*\t\t\tsprintf_pad\t=  s_sprintf_buffer;\r\nchar*\t\t\tprintf_pad\t=  s_printf_buffer;\r\n#ifdef\t__NOPT_DEBUG__\r\nSignature*\t\tcurrent_sig;\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef\t__NOPT_DEBUG__\r\nProject*\t\tRegisteredProjects = NULL;\r\nModule*\t\t\tRegisteredModules = NULL;\r\n#endif\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tprint( char* text );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic void\t\ts_prefixed_output( Level level, char* text, va_list args )\r\n{\t\r\n\t\r\n\r\n\tDbg_AssertPtr( text );\r\n\tDbg_Assert( level >= vERROR );\r\n\tDbg_Assert( level <= vMESSAGE );\r\n\r\n\tif ( s_level_mask.Test( level ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n#ifdef\t__NOPT_DEBUG__\r\n\tprintf( \"[%s] %s - \", \r\n\t\ts_typename[level], \r\n\t\t&current_sig->GetName());\r\n#endif\r\n\r\n\tvsprintf( printf_pad, text, args);\r\n\r\n\tDbg::print( printf_pad );\r\n\tDbg::print( \"\\n\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tpad_printf( const char* text, ... )\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr( text );\r\n\r\n\tva_list args;\r\n\r\n\tva_start( args, text );\r\n\r\n\tvsprintf( sprintf_pad, text, args);\r\n\t\r\n\tva_end( args );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tprint( char* text )\r\n{\r\n\t\r\n\r\n\tif ( output )\r\n\t{\r\n\t\toutput( text );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tmessage ( char *text, ... )\r\n{\t\r\n\t\r\n\r\n\tDbg_AssertPtr( text );\r\n\t\r\n\r\n\tif ( s_level_mask.TestMask ( mMESSAGE ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tva_list args;\r\n\t\r\n\tva_start( args, text );\r\n\ts_prefixed_output( vMESSAGE, text, args );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tnotify( char *text, ... )\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr( text );\r\n\t\r\n\tif ( s_level_mask.TestMask ( mNOTIFY ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tva_list args;\r\n\t\r\n\tva_start( args, text );\r\n\ts_prefixed_output( vNOTIFY, text, args );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\twarning( char *text, ... )\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr( text );\r\n\t\r\n\tif ( s_level_mask.TestMask ( mWARNING ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tva_list args;\r\n\t\r\n\tva_start( args, text );\r\n\ts_prefixed_output( vWARNING, text, args );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\terror( char *text, ... )\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr( text );\r\n\t\r\n\tif ( s_level_mask.TestMask ( mERROR ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tva_list args;\r\n\t\r\n\tva_start( args, text );\r\n\ts_prefixed_output( vERROR, text, args );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tset_output( OutputCode* handler )\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr( handler );\r\n\r\n\toutput = handler;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tlevel_mask( Flags< Mask > mask )\r\n{\r\n\t\r\n\r\n\ts_level_mask.SetMask( mask );\r\n}\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\t\tSetUp( void )\r\n{\r\n\t\r\n\r\n\tset_trap( default_trap );\r\n\tset_output( Dbg::default_print ); \t\t  \t\r\n#ifdef\t__NOPT_DEBUG__\r\n\tset_up();\t\t\t\t\t\t// platform specific setup\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCloseDown( void )\r\n{\r\n\t\r\n\r\n#ifdef\t__NOPT_DEBUG__\r\n\tclose_down();\t\t\t\t\t// platform specific closedown\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n} // namespace Dbg\r\n\r\n#endif\t//\t__NOPT_DEBUG__\r\n\r\n#ifdef\t__PLAT_NGPS__\r\nextern \"C\"\r\n{\r\nint snputs(const char* pszStr);\r\n}\r\n#endif\r\n\r\n// Need to do this, cos otherwise the printf inside OurPrintf will get converted to\r\n// an OurPrintf, & it will infinitely recurse.\r\n#undef printf\r\n\r\nint OurPrintf ( const char* fmt, ... )\r\n{\r\n\t// Don't want printf's in some builds.\r\n#\tif defined( __PLAT_XBOX__ ) && !defined( __NOPT_ASSERT__ )\r\n\treturn 0;\r\n#\tendif\r\n\t\r\n\tint ret=-1;\r\n\t\r\n\tchar p_buffer[1024];\r\n\t\r\n\tchar *p_buf = p_buffer;\r\n\r\n\t#if 1\t\t\r\n\tp_buf[0]=0;\r\n\t#else\r\n\tsprintf (p_buf,\"%6d: \",(int)Tmr::GetRenderFrame());\r\n\tp_buf+=strlen(p_buf);\r\n\t#endif\r\n\t\r\n\t\r\n\tva_list args;\r\n\tva_start( args, fmt );\t\r\n\tvsprintf(p_buf,fmt,args);\r\n\tva_end( args );\r\n\t\r\n\tswitch (Config::GetHardware())\r\n\t{\r\n\t#ifdef\t__PLAT_NGPS__\r\n\tcase Config::HARDWARE_PS2_PROVIEW:\r\n\t\tret=snputs(p_buffer);\r\n\t\tbreak;\r\n\tcase Config::HARDWARE_PS2_DEVSYSTEM:\r\n\tcase Config::HARDWARE_PS2:\r\n\t\t// If we are capturing to a file, then redirect there\r\n\t\tif (dumping_printfs == 1)\r\n\t\t{\r\n\t\t\t dump_printf(p_buffer);\r\n\t\t}\r\n\t\r\n\t\tprintf(\"%s\",p_buffer);\r\n\t\t\r\n\t\tbreak;\r\n\t#endif\r\n\t\r\n\t#ifdef\t__PLAT_NGC__\r\n\tcase Config::HARDWARE_NGC:\r\n\t\tOSReport(\"%s\",p_buffer);\r\n\t\tbreak;\r\n\t#endif\r\n\t\t\r\n\t#ifdef\t__PLAT_XBOX__\r\n\tcase Config::HARDWARE_XBOX:\r\n\t\tOutputDebugString(p_buffer);\r\n\t\tbreak;\r\n\t#endif\r\n\t\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\t\r\n\treturn ret;\r\n}\r\n\r\n\r\nuint32\tquick_check_checksum(uint32 _i, const char *_s, const char *f, int line);\r\n\t\t\t\t\t  \r\nuint32\tcheck_checksum(uint32 _i, const char *_s, const char *f, int line)\r\n{\r\n\t#ifdef\t__PLAT_NGPS__\r\n\tuint32* ra;\t\t\t\t\t\t\t\t\t\t\t\r\n\tasm ( \"daddu %0, $31, $0\" : \"=r\" (ra) );\t\t\t\r\n\t\r\n\tDbg_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)));\r\n\r\n\t// After the assert has been run once, there is no need to run it again, so\r\n\t// patch up the calling code to call quick_check_checksum instead \t\r\n\t// we just need to inspect the code just before ra, \r\n\t// make sure it contains the instructions for calling \"check_checksum\"\r\n\t// and replace it with the equivalent for \"quick_check_checksum\"\r\n\t// This will still all get compiled out for the release build\r\n\t// but this method lets us validata all usages of CRCD that get called.\t\r\n\r\n\t// Note, due to I-Cache, this code might still be executed several times\r\n\t// as the routine will continue to be called until the cache entry for the\r\n\t// call is overwritten\r\n\r\n\r\n\tuint32\tJAL_check_checksum  = 0x0c000000 + ((uint32)check_checksum >> 2);\r\n\tuint32\tJAL_quick_check_checksum  = 0x0c000000 + ((uint32)quick_check_checksum >> 2);\r\n\r\n\tif (ra[-2] == JAL_check_checksum)\r\n\t{\r\n\t\tra[-2] = JAL_quick_check_checksum;\r\n\t}\r\n\t\r\n\treturn\tquick_check_checksum(_i,_s,f,line); \r\n\t#else\r\n\treturn _i;\r\n\t#endif\r\n}\r\n\t\t\t\t\t  \r\nuint32\tquick_check_checksum(uint32 _i, const char *_s, const char *f, int line)\r\n{\r\n\treturn\t_i; \r\n}\r\n\t\t\t\t\t  \r\n\t\t\t\t\t  \r\n"
  },
  {
    "path": "Code/Core/Debug/Mem_stat.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tHost (HOST_)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/host.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEBUG_MEM_STAT_H\r\n#define __CORE_DEBUG_MEM_STAT_H\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Dbg_MEMORY_STATS\r\n{\r\n\r\npublic :\r\n\r\n\tDbg_MEMORY_STATS (  uint total = 0,\tuint spike = 0,\r\n\t\t\t\t\t\tuint system = 0,\tuint fixed = 0 );\r\n\r\nprivate :\r\n\r\n\tuint\t\ttotal;\t\t// total memory currently allocated on behalf of this module/project\r\n\tuint\t\tspike;\t\t// peak total memory allocated on behalf of this module/project\r\n\tuint\t\tsystem;\t\t// current module/project private memory that is adjustable by the user\r\n\tuint\t\tfixed;\t\t// current module/project private memory that is a fixed overhead\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\t\t\t\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline Dbg_MEMORY_STATS::Dbg_MEMORY_STATS ( uint total,  uint spike, \r\n\t\t\t\t\t\t\t\t\t\t\tuint system, uint fixed )\r\n\t:\ttotal ( total ), spike ( spike ), \r\n\t\tsystem ( system ), fixed ( fixed )\r\n{\r\n}\r\n\r\n#endif\t// __NOPT_DEBUG__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#endif\t// __CORE_DEBUG_SIGNATRS_H\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Debug/Messages.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDebug (Dbg_)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/debug/messages.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEBUG_MESSAGES_H\r\n#define __CORE_DEBUG_MESSAGES_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/flags.h>\r\n\r\n#include <core/debug/signatrs.h>\r\n#include <core/debug/project.h>\r\n#include <core/debug/module.h>\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\nnamespace Dbg\r\n{\r\n\r\n\r\nenum Level\r\n{\r\n\tvERROR,\r\n\tvWARNING,\r\n\tvNOTIFY,\r\n\tvMESSAGE,\r\n\tvPRINTF\r\n};\r\n\r\nenum Mask\r\n{\r\n\tmERROR\t\t=\t(1<<vERROR),\r\n\tmWARNING\t= \t(1<<vWARNING),\r\n\tmNOTIFY\t\t=\t(1<<vNOTIFY),\r\n\tmMESSAGE\t=\t(1<<vMESSAGE),\r\n\tmPRINTF\t\t=\t(1<<vPRINTF),\r\n\tmALL\t\t=\t( mERROR\t|\r\n\t\t\t\t\t  mWARNING\t|\r\n\t\t\t\t\t  mNOTIFY\t|\r\n\t\t\t\t\t  mMESSAGE\t|\r\n\t\t\t\t\t  mPRINTF ),\r\n\tmNONE\t\t=\t0\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntypedef void ( OutputCode )( char* );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern \tchar*\t\t\t\tsprintf_pad;\r\n#ifdef\t__NOPT_DEBUG__\r\nextern\tSignature*\t\t\tcurrent_sig;\r\n#endif\r\nextern\tOutputCode\t\t\tdefault_print;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tset_output( OutputCode* handler = default_print );\r\nvoid\tlevel_mask( Flags< Mask > mask );\r\nvoid\tmessage( char* text, ...);\r\nvoid\tnotify ( char* text, ...);\r\nvoid\twarning( char* text, ...);\r\nvoid\terror  ( char* text, ...);\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Dbg\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#if (defined ( __PLAT_XBOX__ ) || defined( __PLAT_WN32__ ))\r\n\r\ninline void Dbg_SetOutput( const char* A ... )\t{};\r\n#define\tDbg_LevelMask(A)\t\t\t\t\t\t{ Dbg::level_mask(A); }\r\n\r\ninline void Dbg_Printf( const char* A ... )\t\t{};\r\ninline void Dbg_Message( const char* A ... )\t{};\r\ninline void Dbg_Notify( const char* A ... )\t\t{};\r\ninline void Dbg_Warning( const char* A ... )\t{};\r\ninline void Dbg_Error( const char* A ... )\t\t{};\r\n\r\n#else\r\n\r\n#define\tDbg_SetOutput(A...)\t\t{ Dbg::set_output(##A); \t}\r\n#define\tDbg_LevelMask(A)\t\t{ Dbg::level_mask(A); \t\t}\r\n\r\n\r\n#ifdef\t__NOPT_DEBUG__\r\n#define Dbg_Printf(A...)\t\t{ printf(##A); \t\t}\r\n#define Dbg_Message(A...) \t\t{ Dbg::current_sig = &Dbg_signature; Dbg::message(##A);\t}\r\n#define Dbg_Notify(A...) \t\t{ Dbg::current_sig = &Dbg_signature; Dbg::notify(##A);\t}\r\n#define Dbg_Warning(A...) \t\t{ Dbg::current_sig = &Dbg_signature; Dbg::warning(##A);\t}\r\n#define Dbg_Error(A...) \t\t{ Dbg::current_sig = &Dbg_signature; Dbg::error(##A);\t}\r\n#else\r\n#define Dbg_Printf(A...)\t\t{ printf(##A); \t\t}\r\n#define Dbg_Message(A...) \t\t{ Dbg::message(##A);\t}\r\n#define Dbg_Notify(A...) \t\t{ Dbg::notify(##A);\t}\r\n#define Dbg_Warning(A...) \t\t{ Dbg::warning(##A);\t}\r\n#define Dbg_Error(A...) \t\t{ Dbg::error(##A);\t}\r\n#endif\r\n\r\n#endif\t// __PLAT_XBOX__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tStubs\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#else\r\n\r\n#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))\r\ninline void Dbg_SetOutput( const char* A ... )\t{};\r\n#define\tDbg_LevelMask(A)\r\ninline void Dbg_Printf( const char* A ... )\t\t{};\r\ninline void Dbg_Message( const char* A ... )\t{};\r\ninline void Dbg_Notify( const char* A ... )\t\t{};\r\ninline void Dbg_Warning( const char* A ... )\t{};\r\ninline void Dbg_Error( const char* A ... )\t\t{};\r\n#else\r\n#define\tDbg_SetOutput(A...)\r\n#define\tDbg_LevelMask(A)\r\n#define Dbg_Printf(A...)\r\n#define Dbg_Message(A...)\r\n#define Dbg_Notify(A...)\r\n#define Dbg_Warning(A...)\r\n#define Dbg_Error(A...)\r\n#endif\r\n\r\n#endif\t// __NOPT_MESSAGES__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// A special printf function that only works for Ryan\r\n// (since I love them so much)\r\n\r\n#if defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ )\r\ninline void Ryan(const char* A ...) {};\r\ninline void Ken(const char* A ...) {};\r\ninline void Matt(const char* A ...) {};\r\n#else\r\n\r\n#ifdef __USER_RYAN__\r\n#define Ryan(A...)  printf(##A) \t\t\r\n#else\r\n#define Ryan(A...)\r\n#endif\r\n\r\n#if defined(__USER_KEN__) && defined(__NOPT_DEBUG__)\r\n#define Ken(A...)  printf(##A) \t\t\r\n#else\r\n#define Ken(A...)\r\n#endif\r\n\r\n#if  defined(__USER_MATT__) && defined(__NOPT_DEBUG__)\r\n#define Matt(A...)  printf(##A) \t\t\r\n#else\r\n#define Matt(A...)\r\n#endif\r\n\r\n#endif\r\n\r\n#endif\t// __CORE_DEBUG_MESSAGES_H\r\n"
  },
  {
    "path": "Code/Core/Debug/Module.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t\t\t   Confidential Information\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDebug (Dbg_)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/debug/module.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEBUG_MODULE_H\r\n#define __CORE_DEBUG_MODULE_H\r\n\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include \"mem_stat.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Unfortunately, Visual C++ does not support the __PRETTY_FUNCTION__ predefined\r\n// name. The most information we can get at is __FILE__.\r\n#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))\r\n#define __PRETTY_FUNCTION__\t__FILE__\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Dbg\r\n{\r\n\r\nclass Project;\r\n\r\nclass Module\r\n{\r\n\r\npublic :\r\n\r\n\t\t\t\t\t\tModule ( Project& proj, const char& prefix, const char& description );\r\n\t\r\n\tvoid\t\t\t\tSetNext ( const Module* next );\r\n\tvoid\t\t\t\tSetSibling ( const Module* sibling );\r\n\r\n\tconst Module*\t\tGetNext ( void )\tconst;\r\n\tconst Module*\t\tGetSibling ( void ) const;\r\n\r\nprivate :\r\n\r\n\tconst Module*\t\tm_next;\t\t\t// pointer to next registered module\r\n\tconst Module*\t\tm_sibling;\t\t// pointer to next module in same project\r\n\r\n\tconst char&\t\t\tm_prefix;\t\t// module prefix\r\n\tconst char&\t\t\tm_description;\t// module description\r\n\t\r\n\tProject&\t\t\tm_project;\t\t// project that this modules belongs to\r\n\tDbg_MEMORY_STATS\tm_stats;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern\tModule*\t\tRegisteredModules;\r\n\r\n} // namespace Dbg\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Dbg\r\n{\r\n\r\ninline\tModule::Module( Project& proj, const char& pref, const char& desc )\r\n:\tm_prefix ( pref ),\r\n\tm_description ( desc ),\r\n\tm_project ( proj )\r\n\t\t\t\t\r\n{\r\n\tm_next = Dbg::RegisteredModules;\t\t// add module to main registration list\r\n\tDbg::RegisteredModules = this;\r\n\r\n\tm_sibling = m_project.GetChildren();\t// add module to its project parent\r\n\tm_project.SetChildren( this );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\t\t\tModule::SetNext( const Module* next )\r\n{\r\n\tm_next = next;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\t\t\tModule::SetSibling( const Module* sibling )\r\n{\r\n\tm_sibling = sibling;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tconst Module*\t\tModule::GetNext( void ) const\r\n{\r\n\treturn m_next;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tconst Module*\t\tModule::GetSibling( void ) const\r\n{\r\n\treturn m_sibling;\r\n}\r\n\r\n} // namespace Dbg\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tStubs\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#else\r\n\r\n#endif\t//__NOPT_DEBUG__\t\t\t\t\t\t\t\t\t\t\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#endif\t// __CORE_DEBUG_MODULE_H\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Debug/NGPS/P_debug.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDebug (DBG)\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_debug.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPlatform specific debug code\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdio.h>\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/debug.h>\r\n\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern char _dbg_start[];\r\nextern char _dbg_end[];\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Dbg\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __NOPT_FULL_DEBUG__\r\n\r\nenum\r\n{\r\n\tvMAX_CLASS_NODES\t= 28000,\r\n\tvMAX_INSTANCE_NODES\t= 100000\r\n};\r\n\r\nstatic const int vFREE_CLASS_BLOCK_ID \t= 0x02030405;\r\nstatic const int vFREE_INST_BLOCK_ID \t= 0x27354351;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\nstruct FreeNode\r\n{\r\n\tFreeNode* \tnext;\r\n\tint\t\t\tid;\r\n\r\n} ;\r\n\r\nunion ClassNodeBlock\r\n{\r\n\tchar\t\t\tpad[sizeof(Spt::ClassNode)];\r\n\tFreeNode\t\tfree_node;\r\n\r\n};\r\n  \r\nunion InstanceNodeBlock\r\n{\r\n\tchar\t\t\tpad[sizeof(Spt::ClassNode::InstanceNode)];\r\n\tFreeNode\t\tfree_node;\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic ClassNodeBlock*\t\tspClassNodeFreeList = NULL;\r\nstatic InstanceNodeBlock*\tspInstanceNodeFreeList = NULL;\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\t\tset_up( void )\r\n{\r\n\t\r\n\r\n\tspClassNodeFreeList = (ClassNodeBlock*)_dbg_start;\r\n\r\n\tClassNodeBlock* p_class_node = spClassNodeFreeList;\r\n\r\n\tfor( int i = 0;  i < ( vMAX_CLASS_NODES - 1 ); i++ )\r\n\t{\r\n\t\tp_class_node->free_node.id = vFREE_CLASS_BLOCK_ID;\r\n\t\tp_class_node->free_node.next = (FreeNode*)(++p_class_node);\r\n\t}\r\n\r\n\tp_class_node->free_node.id = vFREE_CLASS_BLOCK_ID;\r\n\t(p_class_node++)->free_node.next = (FreeNode*)spClassNodeFreeList;\r\n\r\n\r\n\tspInstanceNodeFreeList = (InstanceNodeBlock*)(++p_class_node);\r\n\tInstanceNodeBlock* p_inst_node = spInstanceNodeFreeList;\r\n\r\n\tfor( int i = 0; i < ( vMAX_INSTANCE_NODES - 1 ) ; i++ )\r\n\t{\r\n\t\tp_inst_node->free_node.id = vFREE_INST_BLOCK_ID;\r\n\t\tp_inst_node->free_node.next = (FreeNode*)(++p_inst_node);\r\n\t}\r\n\tp_inst_node->free_node.id = vFREE_INST_BLOCK_ID;\r\n\t(p_inst_node++)->free_node.next = (FreeNode*)spInstanceNodeFreeList;\r\n\r\n\r\n\tDbg_MsgAssert( (int)p_inst_node <= (int)_dbg_end, \r\n\t\t\"Dbg Mem Block not big enough (%d bytes too small)\", (int)p_inst_node - (int)_dbg_end );\r\n\r\n\tif ( (int)p_inst_node < ((int)_dbg_end))\r\n\t{\r\n\t\tDbg_Warning ( \"%dbytes unused in Dbg mem block\",((int)_dbg_end - (int)p_inst_node));\r\n\t}\r\n\r\n\tDbg_Notify ( \"Dbg Mem Block Allocated successfully\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tclose_down( void )\r\n{\r\n\t\r\n\r\n\tint \t\t\t\tcount \t\t\t= 0;\t\r\n\tClassNodeBlock* \tp_class_node \t= spClassNodeFreeList;\t\r\n\tInstanceNodeBlock* \tp_inst_node \t= spInstanceNodeFreeList; \r\n\r\n\tdo\r\n\t{\r\n\t\tDbg_MsgAssert ( p_class_node->free_node.id == vFREE_CLASS_BLOCK_ID, \"Block not free\" );\r\n\t\tp_class_node = (ClassNodeBlock*)p_class_node->free_node.next;\r\n\t\tcount++;\r\n\t} while ( p_class_node != spClassNodeFreeList );\r\n\r\n\tDbg_MsgAssert ( count == vMAX_CLASS_NODES,\r\n\t\t\"%d Class Nodes still registered\", vMAX_CLASS_NODES - count );\r\n\r\n\tcount = 0;\r\n\r\n\tdo\r\n\t{\t\t\r\n\t\tDbg_MsgAssert ( p_inst_node->free_node.id == vFREE_INST_BLOCK_ID, \"Block not free\" );\r\n\t\tp_inst_node = (InstanceNodeBlock*)p_inst_node->free_node.next;\r\n\t\tcount++;\r\n\t} while ( p_inst_node != spInstanceNodeFreeList );\r\n\r\n\tDbg_MsgAssert ( count == vMAX_INSTANCE_NODES,\r\n\t\t\"%d Instance Nodes still registered\", vMAX_INSTANCE_NODES - count );\r\n\r\n\tDbg_Notify ( \"Dbg Mem Block Released successfully\" );\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nvoid*\t\tNewClassNode( size_t size )\r\n{\r\n\t\t\r\n\r\n\tvoid* p_ret = (void*)spClassNodeFreeList;\r\n\t\r\n\tDbg_MsgAssert ( (int)spClassNodeFreeList != (int)(spClassNodeFreeList->free_node.next), \r\n\t\t\t\t\t\"ClassNode pool full\" );\r\n\r\n\tDbg_MsgAssert ( spClassNodeFreeList->free_node.id == vFREE_CLASS_BLOCK_ID, \"Not a Free Class Node\" ); \r\n\r\n\tspClassNodeFreeList = (ClassNodeBlock*)spClassNodeFreeList->free_node.next;\r\n//\tprintf(\"NewClassNode %p  next %p\\n\",p_ret, spClassNodeFreeList);\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tDeleteClassNode( void* pMem )\r\n{\r\n\t\r\n\r\n \tDbg_MsgAssert ( (((int)pMem >= (int)_dbg_start ) && (((int)pMem < (int)_dbg_end ))),\r\n\t\t\t\t\t \"Memory not in Debug block (%p)\",pMem );\r\n\t\r\n\tClassNodeBlock* p_freeblock = (ClassNodeBlock*)pMem;\r\n\tp_freeblock->free_node.next = (FreeNode*)spClassNodeFreeList;\r\n\tspClassNodeFreeList = (ClassNodeBlock*)p_freeblock;\r\n\r\n\tspClassNodeFreeList->free_node.id = vFREE_CLASS_BLOCK_ID;\r\n\r\n\r\n//\tprintf(\"DeleteClassNode %p  next %p\\n\",spClassNodeFreeList, p_freeblock->free_node.next);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid*\t\tNewInstanceNode( size_t size )\r\n{\r\n\t\t\r\n\r\n\tvoid* p_ret = (void*)spInstanceNodeFreeList;\r\n\t\r\n\tDbg_MsgAssert ( (int)spInstanceNodeFreeList != (int)(spInstanceNodeFreeList->free_node.next), \r\n\t\t\t\t\t\"InstanceNode pool full\" );\r\n\r\n\tDbg_MsgAssert ( spInstanceNodeFreeList->free_node.id == vFREE_INST_BLOCK_ID, \"Not a Free Instance Node\" ); \r\n\r\n\tspInstanceNodeFreeList = (InstanceNodeBlock*)spInstanceNodeFreeList->free_node.next;\r\n\r\n\r\n\r\n//\tprintf(\"NewInstanceNode %p  next %p\\n\",p_ret, spInstanceNodeFreeList);\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tDeleteInstanceNode( void* pMem )\r\n{\r\n\t\r\n\r\n \tDbg_MsgAssert ( (((int)pMem >= (int)_dbg_start ) && (((int)pMem < (int)_dbg_end ))),\r\n\t\t\t\t\t \"Memory not in Debug block (%p)\",pMem );\r\n\r\n\tInstanceNodeBlock* p_freeblock = (InstanceNodeBlock*)pMem;\r\n\tp_freeblock->free_node.next = (FreeNode*)spInstanceNodeFreeList;\r\n\tspInstanceNodeFreeList = (InstanceNodeBlock*)p_freeblock;\r\n\r\n\tspInstanceNodeFreeList->free_node.id = vFREE_INST_BLOCK_ID;\r\n\r\n\r\n//\tprintf(\"DeleteInstanceNode %p  next %p\\n\",spInstanceNodeFreeList, p_freeblock->free_node.next);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#else // __NOPT_FULL_DEBUG__\r\n\r\nvoid\t\tset_up( void )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tclose_down( void )\r\n{\r\n\t\r\n}\r\n\r\n#endif // __NOPT_FULL_DEBUG__\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Dbg\r\n\r\n#endif // __NOPT_DEBUG__\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\r\nnamespace Dbg\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tdefault_print( char *text )\r\n{\r\n\tstd::printf( text );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tdefault_trap( char* mess )\r\n{\r\n\tuint*\tptr = reinterpret_cast< uint* >( 0x00000001 );\r\n\r\n\t*ptr = 0;\r\n}\r\n} // namespace Dbg\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Core/Debug/Project.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t\t\t   Confidential Information\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDebug (Dbg_)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/debug/project.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#ifndef __CORE_DEBUG_PROJECT_H\r\n#define __CORE_DEBUG_PROJECT_H\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include \"mem_stat.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Dbg\r\n{\r\n\r\nclass Project\r\n{\r\n\r\npublic :\r\n\r\n\t\t\t\t\tProject ( const char& name, const char& description );\r\n\r\n\tvoid\t\t\tSetChildren ( Dbg::Module* children );\r\n\tDbg::Module*\t\tGetChildren ( void ) const;\r\n\r\nprivate :\r\n\r\n\tconst char&\t\t\tname;\r\n\tconst char&\t\t\tdescription;\r\n\r\n\tProject*\t\t\tnext;\t\t\t\t// pointer to next registered project\r\n\tDbg::Module*\t\t\tchildren;\t\t\t// pointer to children modules \r\n\r\n\tDbg_MEMORY_STATS\tstats;\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern\tDbg::Project*\tRegisteredProjects;\r\n\r\n} // namespace Dbg\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define\tDbg_DefineProject(proj,des)\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\nDbg::Project&\tDbg_project_##proj ( void )\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tstatic Dbg::Project project ( *#proj, *des );\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\treturn project;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Dbg\r\n{\r\n\r\ninline\tProject::Project ( const char& name, const char& description )\r\n:\tname ( name ), description ( description )\r\n{\r\n\tnext = RegisteredProjects;\r\n\tRegisteredProjects = this;\r\n\tchildren = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\t\tProject::SetChildren ( Dbg::Module* children_in )\r\n{\r\n\tchildren = children_in;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tDbg::Module*\t\tProject::GetChildren ( void ) const\r\n{\r\n\treturn children;\r\n}\r\n\r\n} // namespace Dbg\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tStubs\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#else\r\n\r\n#define\tDbg_DefineProject(proj,des)\r\n\r\n#endif\t//__NOPT_DEBUG__\t\t\t\t\t\t\t\t\t\t\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#endif\t// __CORE_DEBUG_PROJECT_H\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Debug/Signatrs.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDebug (Dbg_)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/debug/signatrs.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEBUG_SIGNATRS_H\r\n#define __CORE_DEBUG_SIGNATRS_H\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Dbg\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Module;\r\n\r\nclass Signature\r\n{\r\n\r\npublic :\r\n\t\t\t\t\t\t\tSignature( char* name, const Module& module );\r\n\t\t\t\t\t\t\tSignature( const char* cl, char* name, const Module& module );\r\n\r\n\tconst char&\t\t\t\tGetName( void ) const ;\r\n\t\t\r\nprivate :\r\n\r\n\tchar*\t\t\t\t\tm_name;\t\t\t// function's name\r\n\tconst Module&\t\t\tm_module;\t\t// function's module\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline\tSignature::Signature( char* name, const Module& module )\r\n:\tm_name ( name ), \r\n\tm_module ( module )\r\n{\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tconst char&\tSignature::GetName( void ) const\r\n{\r\n\r\n\treturn *m_name;\r\n}\r\n\r\n} // namespace Dbg\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __PLAT_NGC__\r\nextern\t\tDbg::Module&\tDbg_module;\r\nextern\t\tDbg::Signature\tDbg_signature;\r\n#endif\r\n\r\n#ifndef __NOPT_STRICT_SIGNATURES__\r\n\r\nextern\t\tDbg::Module&\tDbg_module;\r\nextern\t\tDbg::Signature\tDbg_signature;\r\n\r\n#endif\r\n\r\n#endif\t// __NOPT_DEBUG__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#endif\t// __CORE_DEBUG_SIGNATRS_H\r\n"
  },
  {
    "path": "Code/Core/Debug/Wn32/P_debug.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDebug (DBG)\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_debug.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPlatform specific debug code\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdlib.h>\r\n#include <stdio.h>\r\n#include <windows.h>\r\n#include <core/defines.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Dbg\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n#ifdef __NOPT_DEBUG__\r\n\r\nvoid\t\tset_up ( void )\r\n{\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tclose_down ( void )\r\n{\r\n\r\n}\r\n#endif // __NOPT_DEBUG__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tdefault_print ( char *text )\r\n{\r\n\r\n#ifdef __PLAT_WN32__\r\n\t\r\n\tOutputDebugString ( text );\r\n\r\n#else\r\n\r\n\tprintf ( text );\r\n\r\n#endif // __CC_VISUALC__\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tdefault_trap ( char* message )\r\n{\r\n\r\n#ifdef __CC_VISUALC__\r\n#ifdef __ALLOW_CONTINUE__\r\n\r\n\tswitch ( MessageBox ( GetActiveWindow(), message, \"Assertion Failure - Trigger Debugger ?\",\r\n\t\t\t\t\t\t\tMB_DEFBUTTON1 | MB_YESNO | MB_ICONEXCLAMATION ))\r\n\t{\r\n\t\tcase IDYES:\r\n\r\n\t\t\t__asm int 3;\t\t// trigger the debugger\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\r\n\t}\r\n\r\n#else\t// __ALLOW_CONTINUE__\r\n\t\r\n\tMessageBox ( GetActiveWindow(), message, \"Assertion Failure\",\r\n\t\t\t\t\t\t\tMB_DEFBUTTON1 | MB_ICONEXCLAMATION );\r\n\r\n\t__asm int 3;\r\n\r\n#endif\t// __ALLOW_CONTINUE__\r\n\r\n\r\n\r\n#else\t// __CC_VISUALC__\r\n\r\n\texit(-10);\r\n\r\n#endif\t// __CC_VISUALC__\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Core/Debug/XBox/p_debug.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDebug (DBG)\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_debug.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t09/25/00\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPlatform specific debug code\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/debug.h>\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern char _dbg_start[];\r\nextern char _dbg_end[];\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Dbg\r\n{\r\n\r\nDbg_Module\t\t\t\t\t\t\t// module this code belongs to\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __NOPT_FULL_DEBUG__\r\n\r\nenum\r\n{\r\n\tvMAX_CLASS_NODES\t= 28000,\r\n\tvMAX_INSTANCE_NODES\t= 100000\r\n};\r\n\r\nstatic const int vFREE_CLASS_BLOCK_ID \t= 0x02030405;\r\nstatic const int vFREE_INST_BLOCK_ID \t= 0x27354351;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\nstruct FreeNode\r\n{\r\n\tFreeNode* \tnext;\r\n\tint\t\t\tid;\r\n\r\n} ;\r\n\r\nunion ClassNodeBlock\r\n{\r\n\tchar\t\t\tpad[sizeof(Spt::ClassNode)];\r\n\tFreeNode\t\tfree_node;\r\n\r\n};\r\n  \r\nunion InstanceNodeBlock\r\n{\r\n\tchar\t\t\tpad[sizeof(Spt::ClassNode::InstanceNode)];\r\n\tFreeNode\t\tfree_node;\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic ClassNodeBlock*\t\tspClassNodeFreeList = NULL;\r\nstatic InstanceNodeBlock*\tspInstanceNodeFreeList = NULL;\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\t\tset_up( void )\r\n{\r\n\tDbg_Function;\r\n\r\n\tspClassNodeFreeList = (ClassNodeBlock*)_dbg_start;\r\n\r\n\tClassNodeBlock* p_class_node = spClassNodeFreeList;\r\n\r\n\tfor( int i = 0;  i < ( vMAX_CLASS_NODES - 1 ); i++ )\r\n\t{\r\n\t\tp_class_node->free_node.id = vFREE_CLASS_BLOCK_ID;\r\n\t\tp_class_node->free_node.next = (FreeNode*)(++p_class_node);\r\n\t}\r\n\r\n\tp_class_node->free_node.id = vFREE_CLASS_BLOCK_ID;\r\n\t(p_class_node++)->free_node.next = (FreeNode*)spClassNodeFreeList;\r\n\r\n\r\n\tspInstanceNodeFreeList = (InstanceNodeBlock*)(++p_class_node);\r\n\tInstanceNodeBlock* p_inst_node = spInstanceNodeFreeList;\r\n\r\n\tfor( int i = 0; i < ( vMAX_INSTANCE_NODES - 1 ) ; i++ )\r\n\t{\r\n\t\tp_inst_node->free_node.id = vFREE_INST_BLOCK_ID;\r\n\t\tp_inst_node->free_node.next = (FreeNode*)(++p_inst_node);\r\n\t}\r\n\tp_inst_node->free_node.id = vFREE_INST_BLOCK_ID;\r\n\t(p_inst_node++)->free_node.next = (FreeNode*)spInstanceNodeFreeList;\r\n\r\n\r\n\tDbg_MsgAssert( (int)p_inst_node <= (int)_dbg_end, \r\n\t\t\"Dbg Mem Block not big enough (%d bytes too small)\", (int)p_inst_node - (int)_dbg_end );\r\n\r\n\tif ( (int)p_inst_node < ((int)_dbg_end))\r\n\t{\r\n\t\tDbg_Warning ( \"%dbytes unused in Dbg mem block\",((int)_dbg_end - (int)p_inst_node));\r\n\t}\r\n\r\n\tDbg_Notify ( \"Dbg Mem Block Allocated successfully\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tclose_down( void )\r\n{\r\n\tDbg_Function;\r\n\r\n\tint \t\t\t\tcount \t\t\t= 0;\t\r\n\tClassNodeBlock* \tp_class_node \t= spClassNodeFreeList;\t\r\n\tInstanceNodeBlock* \tp_inst_node \t= spInstanceNodeFreeList; \r\n\r\n\tdo\r\n\t{\r\n\t\tDbg_MsgAssert ( p_class_node->free_node.id == vFREE_CLASS_BLOCK_ID, \"Block not free\" );\r\n\t\tp_class_node = (ClassNodeBlock*)p_class_node->free_node.next;\r\n\t\tcount++;\r\n\t} while ( p_class_node != spClassNodeFreeList );\r\n\r\n\tDbg_MsgAssert ( count == vMAX_CLASS_NODES,\r\n\t\t\"%d Class Nodes still registered\", vMAX_CLASS_NODES - count );\r\n\r\n\tcount = 0;\r\n\r\n\tdo\r\n\t{\t\t\r\n\t\tDbg_MsgAssert ( p_inst_node->free_node.id == vFREE_INST_BLOCK_ID, \"Block not free\" );\r\n\t\tp_inst_node = (InstanceNodeBlock*)p_inst_node->free_node.next;\r\n\t\tcount++;\r\n\t} while ( p_inst_node != spInstanceNodeFreeList );\r\n\r\n\tDbg_MsgAssert ( count == vMAX_INSTANCE_NODES,\r\n\t\t\"%d Instance Nodes still registered\", vMAX_INSTANCE_NODES - count );\r\n\r\n\tDbg_Notify ( \"Dbg Mem Block Released successfully\" );\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nvoid*\t\tNewClassNode( size_t size )\r\n{\r\n\tDbg_Function;\t\r\n\r\n\tvoid* p_ret = (void*)spClassNodeFreeList;\r\n\t\r\n\tDbg_MsgAssert ( (int)spClassNodeFreeList != (int)(spClassNodeFreeList->free_node.next), \r\n\t\t\t\t\t\"ClassNode pool full\" );\r\n\r\n\tDbg_MsgAssert ( spClassNodeFreeList->free_node.id == vFREE_CLASS_BLOCK_ID, \"Not a Free Class Node\" ); \r\n\r\n\tspClassNodeFreeList = (ClassNodeBlock*)spClassNodeFreeList->free_node.next;\r\n//\tprintf(\"NewClassNode %p  next %p\\n\",p_ret, spClassNodeFreeList);\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tDeleteClassNode( void* pMem )\r\n{\r\n\tDbg_Function;\r\n\r\n \tDbg_MsgAssert ( (((int)pMem >= (int)_dbg_start ) && (((int)pMem < (int)_dbg_end ))),\r\n\t\t\t\t\t \"Memory not in Debug block (%p)\",pMem );\r\n\t\r\n\tClassNodeBlock* p_freeblock = (ClassNodeBlock*)pMem;\r\n\tp_freeblock->free_node.next = (FreeNode*)spClassNodeFreeList;\r\n\tspClassNodeFreeList = (ClassNodeBlock*)p_freeblock;\r\n\r\n\tspClassNodeFreeList->free_node.id = vFREE_CLASS_BLOCK_ID;\r\n\r\n\r\n//\tprintf(\"DeleteClassNode %p  next %p\\n\",spClassNodeFreeList, p_freeblock->free_node.next);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid*\t\tNewInstanceNode( size_t size )\r\n{\r\n\tDbg_Function;\t\r\n\r\n\tvoid* p_ret = (void*)spInstanceNodeFreeList;\r\n\t\r\n\tDbg_MsgAssert ( (int)spInstanceNodeFreeList != (int)(spInstanceNodeFreeList->free_node.next), \r\n\t\t\t\t\t\"InstanceNode pool full\" );\r\n\r\n\tDbg_MsgAssert ( spInstanceNodeFreeList->free_node.id == vFREE_INST_BLOCK_ID, \"Not a Free Instance Node\" ); \r\n\r\n\tspInstanceNodeFreeList = (InstanceNodeBlock*)spInstanceNodeFreeList->free_node.next;\r\n\r\n\r\n\r\n//\tprintf(\"NewInstanceNode %p  next %p\\n\",p_ret, spInstanceNodeFreeList);\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tDeleteInstanceNode( void* pMem )\r\n{\r\n\tDbg_Function;\r\n\r\n \tDbg_MsgAssert ( (((int)pMem >= (int)_dbg_start ) && (((int)pMem < (int)_dbg_end ))),\r\n\t\t\t\t\t \"Memory not in Debug block (%p)\",pMem );\r\n\r\n\tInstanceNodeBlock* p_freeblock = (InstanceNodeBlock*)pMem;\r\n\tp_freeblock->free_node.next = (FreeNode*)spInstanceNodeFreeList;\r\n\tspInstanceNodeFreeList = (InstanceNodeBlock*)p_freeblock;\r\n\r\n\tspInstanceNodeFreeList->free_node.id = vFREE_INST_BLOCK_ID;\r\n\r\n\r\n//\tprintf(\"DeleteInstanceNode %p  next %p\\n\",spInstanceNodeFreeList, p_freeblock->free_node.next);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#else // __NOPT_FULL_DEBUG__\r\n\r\nvoid\t\tset_up( void )\r\n{\r\n\tDbg_Function;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tclose_down( void )\r\n{\r\n\tDbg_Function;\r\n}\r\n\r\n#endif // __NOPT_FULL_DEBUG__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Dbg\r\n\r\n#endif // __NOPT_DEBUG__\r\n\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\r\nnamespace Dbg\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid default_print( char *text )\r\n{\r\n\tOutputDebugString( text );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid default_trap( char* message )\r\n{\r\n\tOutputDebugString( message );\r\n\tuint*\tptr = reinterpret_cast< uint* >( 0x00000001 );\r\n\t*ptr = NULL;\r\n}\r\n} // namespace Dbg\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Core/Debug/log.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDebug (DBG)\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tlog.cpp\t\t\t   \t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t09/25/02\t-\tksh\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tLogging code\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdio.h>\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/debug.h>\r\n\r\n\r\n#include <sys/config/config.h>\r\n\r\n#ifndef __PLAT_WN32__\r\n#include <gfx/gfxman.h>\r\n#endif // __PLAT_WN32__\r\n\r\n#ifdef __PLAT_NGC__\r\n#include <dolphin.h>\r\n#define _output OSReport\r\n#else\r\n#define _output printf\r\n#endif\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n// 128 bytes each (sizeof(SLogEntry)) and they come off the debug heap.\r\n#define MAX_LOG_ENTRIES 20000\r\n\r\nextern char _log_info_start[];\r\nextern char _log_info_end[];\r\n\r\nnamespace Log\r\n{\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Chosen just to make sizeof(SLogEntry) a nice round 128\r\n#define MAX_MESSAGE_LENGTH 107\r\nstruct SLogEntry\r\n{\r\n\tTmr::CPUCycles mCPUTime;\r\n\tconst char *mpSourceFileName;\r\n\tconst char *mpFunctionName;\r\n\tint mLineNumber;\r\n\tchar mpMessage[MAX_MESSAGE_LENGTH+1];\r\n};\r\n//char p_foo[sizeof(SLogEntry)/0];\r\n\r\nstruct SLogBufferInfo\r\n{\r\n\t// Pointer to the start of the big log buffer, which will be in the debug heap somewhere. \r\n\tSLogEntry *mpBuffer;\r\n\t// The total number of entries in the buffer.\r\n\tint mTotalEntries;\r\n\t// The number of entries written to so far. This starts at 0 when the game starts,\r\n\t// and increases till it hits mTotalEntries, then stays at that value.\r\n\tint mNumEntries;\r\n\t\r\n\t// Points to just after the last entry that got added to the buffer.\r\n\t// So it may not point to a valid SLogEntry, for example when the buffer is filling\r\n\t// up, or when pTop points to the end of pBuffer.\r\n\tSLogEntry *mpTop;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\nstatic bool sInitialised=false;\r\nstatic SLogBufferInfo *spLogInfo=NULL;\r\nstatic SLogEntry *spNotALeak=NULL;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid Init()\r\n{\r\n\t\r\n\tif (Config::GotExtraMemory())\r\n\t{\r\n\t\tDbg_MsgAssert(!sInitialised,(\"Tried to call Log::Init twice\"));\r\n\t\t\r\n\t\tDbg_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)));\r\n\t\tspLogInfo=(SLogBufferInfo*)_log_info_start;\r\n\t\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t\t\r\n\t\tspLogInfo->mNumEntries=0;\r\n\t\tspLogInfo->mTotalEntries=MAX_LOG_ENTRIES;\r\n\t\tspLogInfo->mpBuffer=(SLogEntry*)Mem::Malloc(MAX_LOG_ENTRIES*sizeof(SLogEntry));\r\n\t\tspNotALeak=spLogInfo->mpBuffer;\r\n\t\tspLogInfo->mpTop=spLogInfo->mpBuffer;\r\n\t\r\n\t\tuint32 *p_long=(uint32*)spLogInfo->mpBuffer;\r\n\t\tDbg_MsgAssert((sizeof(SLogEntry)&3)==0,(\"sizeof(SLogEntry) not a multiple of 4\"));\r\n\t\tfor (uint32 i=0; i<MAX_LOG_ENTRIES*sizeof(SLogEntry)/4; ++i)\r\n\t\t{\r\n\t\t\t*p_long++=0;\r\n\t\t}\r\n\t\t\t\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\tsInitialised=true;\r\n\t}\r\n}\r\n\r\nvoid AddEntry(char *p_fileName, int lineNumber, char *p_functionName, char *p_message)\r\n{\r\n\tif (Config::GotExtraMemory())\r\n\t{\r\n\t\tDbg_MsgAssert(sInitialised,(\"Log::AddEntry called before Log::Init called\"));\r\n\t\t\r\n\t\tSLogEntry *p_new=NULL;\r\n\t\tif (spLogInfo->mNumEntries < MAX_LOG_ENTRIES)\r\n\t\t{\r\n\t\t\tp_new=spLogInfo->mpTop++;\r\n\t\t\t++spLogInfo->mNumEntries;\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (spLogInfo->mpTop >= spLogInfo->mpBuffer+MAX_LOG_ENTRIES)\r\n\t\t\t{\r\n\t\t\t\tspLogInfo->mpTop=spLogInfo->mpBuffer;\r\n\t\t\t}\r\n\t\t\tp_new=spLogInfo->mpTop++;\r\n\t\t}\r\n\t\t\r\n\t\tp_new->mCPUTime=Tmr::GetTimeInCPUCycles();\r\n\t\tp_new->mLineNumber=lineNumber;\r\n\t\tp_new->mpFunctionName=p_functionName;\r\n\t\tp_new->mpSourceFileName=p_fileName;\r\n\t\tif (p_message)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(strlen(p_message)<=MAX_MESSAGE_LENGTH,(\"Log message '%s' too long\",p_message));\r\n\t\t\tstrcpy(p_new->mpMessage,p_message);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_new->mpMessage[0]=0;\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n} // namespace Log\r\n\r\n#else\r\nnamespace Log\r\n{\r\nvoid Init()\r\n{\r\n}\r\n\r\nvoid AddEntry(char *p_fileName, int lineNumber, char *p_functionName, char *p_message)\r\n{\r\n}\r\n} // namespace Log\r\n#endif // #ifdef __PLAT_NGPS__\r\n\r\n#endif\t//__NOPT_ASSERT__\r\n\r\n"
  },
  {
    "path": "Code/Core/Debug/ngc/P_debug.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDebug (DBG)\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_debug.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPlatform specific debug code\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdio.h>\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/debug.h>\r\n#include <libsn.h>\r\n\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern char _dbg_start[];\r\nextern char _dbg_end[];\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Dbg\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __NOPT_FULL_DEBUG__\r\n\r\nenum\r\n{\r\n\tvMAX_CLASS_NODES\t= 28000,\r\n\tvMAX_INSTANCE_NODES\t= 100000\r\n};\r\n\r\nstatic const int vFREE_CLASS_BLOCK_ID \t= 0x02030405;\r\nstatic const int vFREE_INST_BLOCK_ID \t= 0x27354351;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\nstruct FreeNode\r\n{\r\n\tFreeNode* \tnext;\r\n\tint\t\t\tid;\r\n\r\n} ;\r\n\r\nunion ClassNodeBlock\r\n{\r\n\tchar\t\t\tpad[sizeof(Spt::ClassNode)];\r\n\tFreeNode\t\tfree_node;\r\n\r\n};\r\n  \r\nunion InstanceNodeBlock\r\n{\r\n\tchar\t\t\tpad[sizeof(Spt::ClassNode::InstanceNode)];\r\n\tFreeNode\t\tfree_node;\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic ClassNodeBlock*\t\tspClassNodeFreeList = NULL;\r\nstatic InstanceNodeBlock*\tspInstanceNodeFreeList = NULL;\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\t\tset_up( void )\r\n{\r\n\tspClassNodeFreeList = (ClassNodeBlock*)_dbg_start;\r\n\r\n\tClassNodeBlock* p_class_node = spClassNodeFreeList;\r\n\r\n\tfor( int i = 0;  i < ( vMAX_CLASS_NODES - 1 ); i++ )\r\n\t{\r\n\t\tp_class_node->free_node.id = vFREE_CLASS_BLOCK_ID;\r\n\t\tp_class_node->free_node.next = (FreeNode*)(++p_class_node);\r\n\t}\r\n\r\n\tp_class_node->free_node.id = vFREE_CLASS_BLOCK_ID;\r\n\t(p_class_node++)->free_node.next = (FreeNode*)spClassNodeFreeList;\r\n\r\n\r\n\tspInstanceNodeFreeList = (InstanceNodeBlock*)(++p_class_node);\r\n\tInstanceNodeBlock* p_inst_node = spInstanceNodeFreeList;\r\n\r\n\tfor( int i = 0; i < ( vMAX_INSTANCE_NODES - 1 ) ; i++ )\r\n\t{\r\n\t\tp_inst_node->free_node.id = vFREE_INST_BLOCK_ID;\r\n\t\tp_inst_node->free_node.next = (FreeNode*)(++p_inst_node);\r\n\t}\r\n\tp_inst_node->free_node.id = vFREE_INST_BLOCK_ID;\r\n\t(p_inst_node++)->free_node.next = (FreeNode*)spInstanceNodeFreeList;\r\n\r\n\r\n\tDbg_MsgAssert( (int)p_inst_node <= (int)_dbg_end, \r\n\t\t\"Dbg Mem Block not big enough (%d bytes too small)\", (int)p_inst_node - (int)_dbg_end );\r\n\r\n\tif ( (int)p_inst_node < ((int)_dbg_end))\r\n\t{\r\n\t\tDbg_Warning ( \"%dbytes unused in Dbg mem block\",((int)_dbg_end - (int)p_inst_node));\r\n\t}\r\n\r\n\tDbg_Notify ( \"Dbg Mem Block Allocated successfully\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tclose_down( void )\r\n{\r\n\tint \t\t\t\tcount \t\t\t= 0;\t\r\n\tClassNodeBlock* \tp_class_node \t= spClassNodeFreeList;\t\r\n\tInstanceNodeBlock* \tp_inst_node \t= spInstanceNodeFreeList; \r\n\r\n\tdo\r\n\t{\r\n\t\tDbg_MsgAssert ( p_class_node->free_node.id == vFREE_CLASS_BLOCK_ID, \"Block not free\" );\r\n\t\tp_class_node = (ClassNodeBlock*)p_class_node->free_node.next;\r\n\t\tcount++;\r\n\t} while ( p_class_node != spClassNodeFreeList );\r\n\r\n\tDbg_MsgAssert ( count == vMAX_CLASS_NODES,\r\n\t\t\"%d Class Nodes still registered\", vMAX_CLASS_NODES - count );\r\n\r\n\tcount = 0;\r\n\r\n\tdo\r\n\t{\t\t\r\n\t\tDbg_MsgAssert ( p_inst_node->free_node.id == vFREE_INST_BLOCK_ID, \"Block not free\" );\r\n\t\tp_inst_node = (InstanceNodeBlock*)p_inst_node->free_node.next;\r\n\t\tcount++;\r\n\t} while ( p_inst_node != spInstanceNodeFreeList );\r\n\r\n\tDbg_MsgAssert ( count == vMAX_INSTANCE_NODES,\r\n\t\t\"%d Instance Nodes still registered\", vMAX_INSTANCE_NODES - count );\r\n\r\n\tDbg_Notify ( \"Dbg Mem Block Released successfully\" );\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nvoid*\t\tNewClassNode( size_t size )\r\n{\r\n\tvoid* p_ret = (void*)spClassNodeFreeList;\r\n\t\r\n\tDbg_MsgAssert ( (int)spClassNodeFreeList != (int)(spClassNodeFreeList->free_node.next), \r\n\t\t\t\t\t\"ClassNode pool full\" );\r\n\r\n\tDbg_MsgAssert ( spClassNodeFreeList->free_node.id == vFREE_CLASS_BLOCK_ID, \"Not a Free Class Node\" ); \r\n\r\n\tspClassNodeFreeList = (ClassNodeBlock*)spClassNodeFreeList->free_node.next;\r\n//\tprintf(\"NewClassNode %p  next %p\\n\",p_ret, spClassNodeFreeList);\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tDeleteClassNode( void* pMem )\r\n{\r\n \tDbg_MsgAssert ( (((int)pMem >= (int)_dbg_start ) && (((int)pMem < (int)_dbg_end ))),\r\n\t\t\t\t\t \"Memory not in Debug block (%p)\",pMem );\r\n\t\r\n\tClassNodeBlock* p_freeblock = (ClassNodeBlock*)pMem;\r\n\tp_freeblock->free_node.next = (FreeNode*)spClassNodeFreeList;\r\n\tspClassNodeFreeList = (ClassNodeBlock*)p_freeblock;\r\n\r\n\tspClassNodeFreeList->free_node.id = vFREE_CLASS_BLOCK_ID;\r\n\r\n\r\n//\tprintf(\"DeleteClassNode %p  next %p\\n\",spClassNodeFreeList, p_freeblock->free_node.next);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid*\t\tNewInstanceNode( size_t size )\r\n{\r\n\tvoid* p_ret = (void*)spInstanceNodeFreeList;\r\n\t\r\n\tDbg_MsgAssert ( (int)spInstanceNodeFreeList != (int)(spInstanceNodeFreeList->free_node.next), \r\n\t\t\t\t\t\"InstanceNode pool full\" );\r\n\r\n\tDbg_MsgAssert ( spInstanceNodeFreeList->free_node.id == vFREE_INST_BLOCK_ID, \"Not a Free Instance Node\" ); \r\n\r\n\tspInstanceNodeFreeList = (InstanceNodeBlock*)spInstanceNodeFreeList->free_node.next;\r\n\r\n\r\n\r\n//\tprintf(\"NewInstanceNode %p  next %p\\n\",p_ret, spInstanceNodeFreeList);\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tDeleteInstanceNode( void* pMem )\r\n{\r\n \tDbg_MsgAssert ( (((int)pMem >= (int)_dbg_start ) && (((int)pMem < (int)_dbg_end ))),\r\n\t\t\t\t\t \"Memory not in Debug block (%p)\",pMem );\r\n\r\n\tInstanceNodeBlock* p_freeblock = (InstanceNodeBlock*)pMem;\r\n\tp_freeblock->free_node.next = (FreeNode*)spInstanceNodeFreeList;\r\n\tspInstanceNodeFreeList = (InstanceNodeBlock*)p_freeblock;\r\n\r\n\tspInstanceNodeFreeList->free_node.id = vFREE_INST_BLOCK_ID;\r\n\r\n\r\n//\tprintf(\"DeleteInstanceNode %p  next %p\\n\",spInstanceNodeFreeList, p_freeblock->free_node.next);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#else // __NOPT_FULL_DEBUG__\r\n\r\nvoid\t\tset_up( void )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tclose_down( void )\r\n{\r\n}\r\n\r\n#endif // __NOPT_FULL_DEBUG__\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Dbg\r\n\r\n#endif // __NOPT_DEBUG__\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\r\nnamespace Dbg\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tdefault_print( char *text )\r\n{\r\n\tstd::printf( text );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tdefault_trap( char* message )\r\n{\r\n//\tuint*\tptr = reinterpret_cast< uint* >( 0x00000001 );\r\n//\r\n//\t*ptr = NULL;\r\n\r\n\tsnPause();\r\n}\r\n} // namespace Dbg\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Core/Debug.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDebug (DBG)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\tmjb\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/debug.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEBUG_H\r\n#define __CORE_DEBUG_H\r\n\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\r\n// for now - always turn on messages and assertion\r\n#define\t__NOPT_MESSAGES__\r\n#define\t__NOPT_ASSERT__\r\n\r\n#else\r\n\r\n// Mick - added assertions always on, regardless of debug mode.\r\n#define\t__NOPT_ASSERT__\r\n\r\n// Gary - ...  unless you're working on the tools, \r\n// in which case the asserts prevent the code from compiling...\r\n#ifdef __PLAT_WN32__\r\n#ifndef _CONSOLE // Ken: Asserts now compile for console apps. (see levelassetlister project)\r\n\t#undef __NOPT_ASSERT__\r\n#endif\t\r\n#endif\r\n\r\n#endif\t// __NOPT_DEBUG__\r\n\r\n#ifdef __NOPT_CDROM__OLD\r\n#undef __NOPT_ASSERT__\r\n#endif\r\n\r\n// Temporary switch off assertions flag\t\t\t\t \r\n#ifdef __NOPT_NOASSERTIONS__\r\n#undef __NOPT_ASSERT__\r\n#endif\r\n\r\n// no assertions on final build (\"final=\")\r\n#ifdef __NOPT_FINAL__\r\n#undef __NOPT_ASSERT__\r\n#endif\r\n\r\n\r\n#ifdef __NOPT_ASSERT__\r\n#define\t__DEBUG_CODE__\r\n#endif\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sys/mem/memdbg.h>\r\n\r\n#include \"debug/messages.h\"\r\n#include \"debug/checks.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Dbg\r\n{\r\n\r\n\r\n\r\n#ifdef __NOPT_DEBUG__\r\n \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tSetUp( void );\r\nvoid\tCloseDown( void );\r\n\r\n#ifdef __NOPT_FULL_DEBUG__\r\nvoid*\tNewClassNode( size_t size );\r\nvoid\tDeleteClassNode( void* pMem );\r\nvoid*\tNewInstanceNode( size_t size );\r\nvoid\tDeleteInstanceNode( void* pMem );\r\n#endif // __NOPT_FULL_DEBUG__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define Dbg_Code(X)\t\tX\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tStubs\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#else\t// __NOPT_DEBUG__ \r\n\r\n#ifndef\t__NOPT_ASSERT__\r\ninline void SetUp( void ) {};\r\ninline void CloseDown( void ) {};\r\n#else\r\nvoid\tSetUp( void );\r\nvoid\tCloseDown( void );\r\n#endif // __NOPT_ASSERT\r\n\r\n#define Dbg_Code(X)\r\n\r\n\r\n#endif\t// __NOPT_DEBUG__\r\n\r\n} // namespace Dbg\r\n\r\n#endif\t// __CORE_DEBUG_H\r\n"
  },
  {
    "path": "Code/Core/Defines.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tStandard Header\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/defines.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tAll code depends on the definitions in this files\t\t\t\t\t\t**\r\n**\tIt should be included in every file\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#define __CORE_DEFINES_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#ifdef __PLAT_WN32__\r\n//#include <strstream>\r\n//#include <fstream.h>\r\n#ifdef __USE_OLD_STREAMS__\r\n#include <iostream.h>\r\n#else\r\n#include <iostream>\r\nusing namespace std;\r\n#endif\r\n#include <stdio.h>\r\n#include <string.h>\r\n\r\n#pragma warning( disable : 4800 ) \r\n#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list\r\n#pragma warning( disable : 4291 ) // no matching operator delete found\r\n\r\n\r\n\r\n#else\r\n#ifdef __PLAT_NGPS__\r\n#include <stdio.h>\r\n#include <eetypes.h>\r\n//#include <iostream.h>\r\n#include <string.h>\r\n#include <stdlib.h>\r\n#else\r\n#ifdef __PLAT_NGC__\r\n#include <stdlib.h>\r\n#include <stdio.h>\r\n#include <string.h>\r\n#include <typeinfo>  \r\n#else\r\n#ifdef __PLAT_XBOX__\r\n#include <stdio.h>\r\n//#include <iostream.h>\r\n#include <string.h>\r\n#include <stdlib.h>\r\n\r\n#pragma warning( disable : 4800 ) \r\n#pragma warning( disable : 4291 ) // no matching operator delete found\r\n#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list\r\n#pragma warning( disable : 4995 ) // name was marked as #pragma deprecated\r\n\r\n#endif\r\n#endif\r\n#endif\r\n#endif\r\n\r\n#ifndef __PLAT_WN32__\r\n//#ifdef __NOPT_ASSERT__\r\n#ifdef __PLAT_NGC__\r\n#ifdef __NOPT_FINAL__\r\n\t#define printf(A...)\r\n#else\r\n\tint OurPrintf(const char *fmt, ...);\r\n\t#define printf OurPrintf\r\n#endif\r\n#else\r\n\tint OurPrintf(const char *fmt, ...);\r\n\t#define printf OurPrintf\r\n#endif\t\r\n\r\n//#else\r\n//\tinline void NullPrintf(const char *fmt, ...){}\r\n//\t#define printf NullPrintf\t\r\n//#endif\r\n#endif\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define vINT8_MAX   \t\t0x7F\r\n#define vINT8_MIN   \t\t0x81\r\n#define vINT16_MAX   \t\t0x7FFF\r\n#define vINT16_MIN   \t\t0x8001\r\n#define vINT32_MAX   \t\t0x7FFFFFFF\r\n#define vINT32_MIN   \t\t0x80000001\r\n#define vINT64_MAX   \t\t0x7FFFFFFFFFFFFFFF\r\n#define vINT64_MIN   \t\t0x8000000000000001\r\n\r\n#define vUINT8_MAX   \t\t0xFF\r\n#define vUINT16_MAX   \t\t0xFFFF\r\n#define vUINT32_MAX   \t\t0xFFFFFFFF\r\n#define vUINT64_MAX   \t\t0xFFFFFFFFFFFFFFFF\r\n\r\n#ifndef TRUE\r\n#define FALSE\t\t\t\t0\r\n#define TRUE\t\t\t\t(!FALSE)\r\n#endif\r\n\r\n#ifndef NULL\r\n#define NULL\t\t\t\t0\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntypedef char\t\t\t\tint8;\r\ntypedef short\t\t\t\tint16;\r\n\r\ntypedef unsigned int\t\tuint;\r\ntypedef unsigned char\t\tuint8;\r\ntypedef unsigned short\t\tuint16;\r\n\r\ntypedef signed int\t\t\tsint;\r\ntypedef signed char\t\t\tsint8;\r\ntypedef signed short\t\tsint16;\r\n\r\n#define vINT_MAX\t\t\tvINT32_MAX\r\n#define vINT_MIN\t\t\tvINT32_MIN\r\n#define vUINT_MAX\t\t\tvUINT32_MAX\r\n\r\n#ifdef __PLAT_WN32__\r\ntypedef long\t\t\t\tint32;\r\ntypedef unsigned long\t\tuint32;\r\ntypedef signed long\t\t\tsint32;\r\ntypedef __int64\t\t\t\tint64;\r\ntypedef unsigned __int64\tuint64;\r\ntypedef signed __int64\t\tsint64;\r\n\r\n#endif\r\n\r\n#ifdef __PLAT_NGPS__\r\ntypedef int\t\t\t\t\tint32;\r\ntypedef unsigned int\t\tuint32;\r\ntypedef signed int\t\t\tsint32;\r\ntypedef long\t\t\t\tint64;\r\ntypedef unsigned long\t\tuint64;\r\ntypedef signed long\t\t\tsint64;\r\ntypedef long128\t\t\t\tint128;\r\ntypedef u_long128\t\t\tuint128;\r\ntypedef long128\t\t\t\tsint128;\r\n\r\n#endif\r\n\r\n#ifdef __PLAT_XBOX__\r\ntypedef long\t\t\t\tint32;\r\ntypedef unsigned long\t\tuint32;\r\ntypedef signed long\t\t\tsint32;\r\ntypedef __int64\t\t\t\tint64;\r\ntypedef unsigned __int64\tuint64;\r\ntypedef signed __int64\t\tsint64;\r\n\r\n#endif\r\n\r\n#ifdef __PLAT_NGC__\r\ntypedef int\t\t\t\t\tint32;\r\ntypedef unsigned int\t\tuint32;\r\ntypedef signed int\t\t\tsint32;\r\ntypedef long long\t\t\tint64;\r\ntypedef unsigned long long\tuint64;\r\ntypedef signed long long\tsint64;\r\n// Paul: No GameCube 128-bit types.\r\n//typedef long128\t\t\t\tint128;\r\n//typedef u_long128\t\t\tuint128;\r\n//typedef long128\t\t\t\tsint128;\r\ntypedef long long\t\t\tint128;\r\ntypedef unsigned long long\tuint128;\r\ntypedef signed long long\tsint128;\r\n\r\n#endif\r\n\r\n#if defined(__PLAT_NGPS__) || defined(__PLAT_XBOX__) || defined(__PLAT_NGC__)\r\n\r\nclass ostream\r\n{\r\npublic:\r\n\tostream& operator<< ( char* str ) \t\t{ printf ( str ); return *this; }\r\n\tostream& operator<< ( const char* str ) { printf ( str ); return *this; }\r\n\tostream& operator<< ( sint i ) \t\t\t{ printf ( \"%d\", i ); return *this; }\r\n\tostream& operator<< ( uint i ) \t\t\t{ printf ( \"%u\", i ); return *this; }\r\n\tostream& operator<< ( float f ) \t\t{ printf ( \"%f\", f ); return *this; }\r\n\tostream& operator<< ( void* p ) \t\t{ printf ( \"%p\", p ); return *this; }\r\n\tostream& operator<< ( const void* p )\t{ printf ( \"%p\", p ); return *this; }\r\n};\r\n\r\n#endif \r\n\r\n#define\tvINT_BITS\t\t\t32\r\n#define\tvPTR_BITS\t\t\t32\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Alignment macros\r\n\r\n\r\n#ifdef __PLAT_NGPS__\r\n#define nAlign(bits)\t__attribute__((aligned((bits>>3))))\r\n#else\r\n#define nAlign(bits)\r\n#endif\r\n\r\n#define\tnPad64(X)\tuint64\t\t_pad##X;\r\n#define\tnPad32(X)\tuint32\t\t_pad##X;\r\n#define\tnPad16(X)\tuint16\t\t_pad##X;\r\n#define\tnPad8(X)\tuint8\t\t_pad##X;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// version stamping\r\n\r\n#define __nTIME__\t\t__TIME__\r\n#define __nDATE__\t\t__DATE__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#define nBit(b)\t\t\t\t( 1 << (b) )\r\n\r\ntypedef\tsint\t\t\t\tnID;\r\ntypedef\tsint8\t\t\t\tnID8;\r\ntypedef\tsint16\t\t\t\tnID16;\r\ntypedef\tsint32\t\t\t\tnID32;\r\ntypedef\tsint64\t\t\t\tnID64;\r\n\r\n#define\tnMakeID(a,b,c,d)\t\t( (nID) ( ( (nID) (a) ) << 24 | ( (nID) (b) ) << 16 |\t\\\r\n\t\t\t\t\t\t\t\t( (nID) (c) ) << 8 | ( (nID) (d) ) ) )\r\n\r\n\r\n//\tnMakeStructID() differs from nMakeID in that struct IDs are always\r\n//\treadable from a memory dump, where as IDs would be reversed on little\r\n//\tendian machines\r\n\r\n#if\t\t__CPU_BIG_ENDIAN__\r\n#define\tnMakeStructID(a,b,c,d) ( (nID) ( ((nID)(a))<<24 | ((nID)(b))<<16 | \\\r\n\t\t\t\t\t\t\t\t\t\t  ((nID)(c))<<8  | ((nID)(d)) ))\r\n#else\r\n#define\tnMakeStructID(a,b,c,d) ( (ID) ( ((nID)(d))<<24 | ((nID)(c))<<16 | \\\r\n\t\t\t\t\t\t\t\t\t\t  ((nID)(b))<<8  | ((nID)(a)) ))\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define\tnReverse32(L)\t( (( (L)>>24 ) & 0xff) | (((L)>>8) &0xff00) | (((L)<<8)&0xff0000) | (((L)<<24)&0xff000000))\r\n#define\tnReverse16(L)\t( (( (L)>>8 ) & 0xff) | (((L)<<8)&0xff00) )\r\n\r\n#if\t__CPU_BIG_ENDIAN__\r\n\r\n#define\tnBgEn32(L) \t(L)\r\n#define\tnBgEn16(L) \t(L)\r\n\r\n#define\tnLtEn32(L)\tnReverse32(L)\r\n#define\tnLtEn16(L)\tnReverse16(L)\r\n\r\n#else\r\n\r\n#define\tnBgEn32(L) \tnReverse32(L)\r\n#define\tnBgEn16(L) \tnReverse16(L)\r\n\r\n#define\tnLtEn32(L)\t(L)\r\n#define\tnLtEn16(L)\t(L)\r\n\r\n#endif\r\n\r\n#ifdef __PLAT_XBOX__\r\n#define __PRETTY_FUNCTION__ \"?\"\r\n\r\n#define isnanf\t_isnan\r\n#define isinff\t_isnan\r\n\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#define __CPU_WORD_BALIGN__    4\t\t// Memory word byte alignment\r\n\r\n#define PTR_ALIGNMASK\t ( vUINT_MAX << __CPU_WORD_BALIGN__)\r\n\r\n// The alignment macros align elements for fastest access\r\n\r\n#define nAligned(P) \t\t( !( (uint) (P) & (~PTR_ALIGNMASK) ) )\r\n#define nAlignDown(P) \t\t(void*)( (uint) (P) & PTR_ALIGNMASK )\r\n#define nAlignUp(P)\t\t\t(void*)( ( (uint) (P) + ( 1 << __CPU_WORD_BALIGN__ ) - 1 ) & PTR_ALIGNMASK )\r\n#define nAlignedBy(P,A) \t( !( (uint) (P) & ( ~(vUINT_MAX << (A) ) ) ) )\r\n#define nAlignDownBy(P,A) \t(void*)( (uint) (P) & (vUINT_MAX << (A) ) )\r\n#define nAlignUpBy(P,A)\t\t(void*)( ( (uint) (P) + ( 1 << (A) ) - 1 ) & ( vUINT_MAX <<( A ) ) )\r\n#define nStorage(X)\t\t\tnAlignUp ( (X) + 1 )\r\n\r\n/****************************************************************************/\r\n\r\n#define\tnAddPointer(P,X)\t\t(void*) ( (uint) (P) + (uint) (X) )\r\n#define\tnSubPointer(P,X)\t\t(void*) ( (uint) (P) - (uint) (X) )\r\n\r\n/****************************************************************************/\r\n\r\n// Converts a string into a checksum. This macro can be used for readability.\r\n// Later, for speed, some application can scan all .cpp and .h files, and\r\n// replace all instances of CRCX(...) with corresponding CRCD(...) instances\r\n//\r\n// Example: CRCX(\"object_id\")\r\n#define CRCX(_s)\t\t\tScript::GenerateCRC(_s)\r\n// This macro exists simply for readability. Whenever you see a CRCD(...) instance,\r\n// you will know what string the checksum maps to. CRCD(...) instances in the code\r\n// can be generated from CRCX(...), and can be reverse mapped if desired.\r\n//\r\n// Example: CRCD(0xdcd2a9d4, \"object_id\")\r\n\r\n#include <core/debug.h>\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n\r\n#include <core/support.h>\r\n#include <sys/mem/memman.h>\r\n\r\n#include <core/crc.h>\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#include <gfx/ngps/p_memview.h>\r\n#include \"libsn.h\"\r\n#elif defined( __PLAT_NGC__ )\r\n#include <gfx/ngc/p_memview.h>\r\n//#include \"libsn.h\"\r\n#elif defined( __PLAT_XBOX__ )\r\n#include <gfx/xbox/p_memview.h>\r\n#endif\r\n\r\n\r\n// Mick:  This check slows the game down quite a bit\r\n#if  1 && \tdefined( __NOPT_ASSERT__ )\r\n\r\nextern  uint32\tcheck_checksum(uint32 _i, const char *_s, const char *f, int line);\r\n\r\n#define CRCD(_i, _s)\t\tcheck_checksum(_i, _s, __FILE__, __LINE__)\r\n#else\r\n#define CRCD(_i, _s)\t\t_i\r\n#endif\r\n\r\n// CRC-C, for use only in switch statements, where you want to use the same syntax as CRCD\r\n#define CRCC(_i, _s)\t\t_i\r\n\r\n\r\n\r\n//#ifdef __PLAT_NGC__\r\n//class TCPPInit\r\n//{\r\n//public:\r\n//  static bool IsHeapInitialized ;\r\n//} ;\r\n//\r\n//// these definitions override the new and delete operators.\r\n//\r\n#ifdef __PLAT_NGC__\r\nstatic inline void* operator new       ( size_t blocksize ) ;\r\n\r\nstatic inline void* operator new[]     ( size_t blocksize ) ;\r\n\r\nstatic inline void operator delete     ( void* block ) ;\r\n\r\nstatic inline void operator delete[]   ( void* block ) ;\r\n#endif\t\t// __PLAT_NGC__\r\n//\r\n//#else\r\n\r\n#ifdef __PLAT_WN32__\r\ninline void* \toperator new( size_t size, bool assert_on_fail )\r\n{\r\n\treturn new char[size];\r\n}\r\n\r\n#else\r\n#ifndef __PLAT_NGC__\r\n/******************************************************************/\r\n/* Global new/delete operators                                    */\r\n/*                                                                */\r\n/******************************************************************/\r\ninline void* \toperator new( size_t size )\r\n{\r\n\treturn Mem::Manager::sHandle().New( size, true );\r\n}\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void* \toperator new[] ( size_t size )\r\n{\r\n\treturn Mem::Manager::sHandle().New( size, true );\r\n}\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void* \toperator new( size_t size, bool assert_on_fail )\r\n{\r\n\treturn Mem::Manager::sHandle().New( size, assert_on_fail );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void* \toperator new[] ( size_t size, bool assert_on_fail )\r\n{\r\n\treturn Mem::Manager::sHandle().New( size, assert_on_fail );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void*\toperator new( size_t size, Mem::Allocator* pAlloc, bool assert_on_fail = true )\r\n{\r\n\treturn Mem::Manager::sHandle().New( size, assert_on_fail, pAlloc );\r\n}\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void*\toperator new[]( size_t size, Mem::Allocator* pAlloc, bool assert_on_fail = true )\r\n{\r\n\treturn Mem::Manager::sHandle().New( size, assert_on_fail, pAlloc );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void* \toperator new( size_t size, void* pLocation )\r\n{\r\n\treturn pLocation;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void* \toperator new[]( size_t size, void* pLocation )\r\n{\r\n\treturn pLocation;\r\n}\r\n\r\n#ifndef __PLAT_NGC__\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void \toperator delete( void* pAddr )\r\n{\r\n\tMem::Manager::sHandle().Delete( pAddr );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void \toperator delete[]( void* pAddr )\r\n{\r\n\tMem::Manager::sHandle().Delete( pAddr );\r\n}\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n//#ifdef __PLAT_NGC__\r\n/******************************************************************/\r\n/* only used when exception is thrown in constructor              */\r\n/*                                                                */\r\n/******************************************************************\r\n\r\ninline void\toperator delete( void* pAddr, Mem::Allocator* pAlloc )\r\n{\r\n\tMem::Manager * mem_man = Mem::Manager::Instance();\r\n\tMem::Manager::sHandle().Delete( pAddr );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************\r\n\r\ninline void\toperator delete[]( void* pAddr, Mem::Allocator* pAlloc )\r\n{\r\n\tMem::Manager * mem_man = Mem::Manager::Instance();\r\n\tMem::Manager::sHandle().Delete( pAddr );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************\r\n\r\ninline void \toperator delete( void*, void* pLocation )\r\n{\r\n\treturn;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n//#endif\t\t// __PLAT_NGC__\r\n#endif\t// __PLAT_WN32__\r\n#endif\t//\t__CORE_DEFINES_H\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/DynamicTable.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tList                                                    **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t\t\t\t\t\t\t\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t\t                                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/DynamicTable.h>\r\n\r\n//\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Lst\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************************\r\n *\r\n * Function:\t\r\n *\r\n * Description: Default constructor\t\t\t\r\n *\r\n * Parameters:\t\r\n * \r\n *****************************************************************************/\r\n\r\n\r\n} // namespace Lst\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/DynamicTable.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tDynamicTable      \t\t\t \t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCore\\DynamicTable.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t12/14/2000 - rjm\t\t\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tA handy DynamicTable class\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_LIST_DYNAMICTABLE_H\r\n#define __CORE_LIST_DYNAMICTABLE_H\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Lst\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnTemplateBaseClass(_V, DynamicTable)\r\n{\r\n    Dbg_TemplateBaseClass(_V, DynamicTable);\r\n\r\npublic:\r\n\tDynamicTable(int size, int grow_increment = 8);\r\n\t~DynamicTable();\r\n\r\n\t// it goes on the end of the table\r\n\tvoid Add(_V *pItem);\r\n\tint GetSize();\r\n\tvoid Reset();\r\n\r\n\t_V &Last();\r\n\r\n\tvoid Replace(int index, _V *pNewItem);\r\n\tvoid Remove(int index);\r\n\r\n/*\t\r\n\tbool IsEmpty(int index);\r\n*/\r\n\r\n\t_V &operator[](int index);\r\n\t\r\nprivate:\r\n\t_V **\t\t\tmpp_table;\r\n\tint \t\t\tm_size;\r\n\tint\t\t\t\tm_entriesFilled;\r\n\tint \t\t\tm_growIncrement;\r\n};\r\n\r\n\r\n\r\ntemplate<class _V>\r\nclass DynamicTableDestroyer\r\n{\r\npublic:\r\n\tDynamicTableDestroyer(DynamicTable<_V> *pTable);\r\n\r\n\tvoid DeleteTableContents();\r\n\r\nprivate:\r\n\tDynamicTable<_V> *\t\t\tmp_table;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate<class _V> \r\nDynamicTable<_V>::DynamicTable(int size, int grow_increment)\r\n{\r\n    m_size = size;\r\n\tm_growIncrement = grow_increment;\r\n\tmpp_table = (_V**) Mem::Malloc(sizeof(_V *) * m_size);\r\n\t//mpp_table = new _V*[m_size];\r\n\tfor (int i = 0; i < m_size; i++)\r\n\t\tmpp_table[i] = NULL;\r\n\t\r\n\tm_entriesFilled = 0;\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> \r\nDynamicTable<_V>::~DynamicTable()\r\n{\r\n    Mem::Free(mpp_table);\r\n\t//delete [] mpp_table;\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> \r\nvoid DynamicTable<_V>::Add(_V* pItem)\r\n{\r\n\t\r\n\tDbg_MsgAssert(pItem,( \"can't add NULL item to table\"));\r\n\r\n\t// do we need to create a new table?\r\n\tif (m_size <= m_entriesFilled)\r\n\t{\r\n\t\t// create new table\r\n\t\tint new_size = m_size + m_growIncrement;\r\n\t\t_V **ppTemp = (_V**) Mem::Malloc(sizeof(_V *) * new_size);\r\n\t\t//_V **ppTemp = new _V*[new_size];\r\n\r\n\t\t// copy contents of old one\r\n\t\tint i;\r\n\t\tfor (i = 0; i < m_size; i++)\r\n\t\t\tppTemp[i] = mpp_table[i];\r\n\t\tfor (i = m_size; i < new_size; i++)\r\n\t\t\tppTemp[i] = NULL;\r\n\r\n\t\tMem::Free(mpp_table);\r\n\t\t//delete [] mpp_table;\r\n\t\tmpp_table = ppTemp;\r\n\t\tm_size = new_size;\r\n\t}\r\n\t\r\n\tmpp_table[m_entriesFilled++] = pItem;\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> \r\nint DynamicTable<_V>::GetSize()\r\n{\r\n\treturn m_entriesFilled;\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> \r\nvoid DynamicTable<_V>::Reset()\r\n{\r\n\tm_entriesFilled = 0;\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> \r\nvoid DynamicTable<_V>::Replace(int index, _V *pNewItem)\r\n{\r\n\t\r\n\tDbg_MsgAssert(index >= 0 && index < m_entriesFilled,( \"index out of bounds in DynamicTable\"));\r\n\tDbg_AssertPtr(pNewItem);\r\n\tmpp_table[index] = pNewItem;\r\n}\r\n\r\n\r\ntemplate<class _V> \r\nvoid DynamicTable<_V>::Remove(int index)\r\n{\r\n\tDbg_MsgAssert(index >= 0 && index < m_entriesFilled,( \"index out of bounds in DynamicTable\"));\r\n\t\r\n\tdelete mpp_table[index];\r\n\t\r\n\tfor ( int i = index; i < m_entriesFilled-1; i++ )\r\n\t{\r\n\t\tmpp_table[i] = mpp_table[i+1];\r\n\t}\r\n\tmpp_table[m_entriesFilled-1] = NULL;\r\n\tm_entriesFilled--;\r\n}\r\n\r\n/*\r\ntemplate<class _V> \r\nbool DynamicTable<_V>::IsEmpty(int index)\r\n{\r\n\t\r\n\tDbg_MsgAssert(index >= 0 && index < m_entriesFilled,( \"index out of bounds in DynamicTable\"));\r\n\tif (mpp_table[index]) return false;\r\n\treturn true;\r\n}\r\n*/\r\n\r\n\r\n\r\ntemplate<class _V> \r\n_V &DynamicTable<_V>::operator[](int index)\r\n{\r\n\t\r\n\tDbg_MsgAssert(index >= 0 && index < m_entriesFilled,( \"index %d out of bounds in DynamicTable\", index));\r\n\tDbg_MsgAssert(mpp_table[index],( \"table entry is NULL\"));\r\n\tDbg_AssertPtr(mpp_table[index]);\r\n\r\n\treturn *mpp_table[index];\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> \r\n_V &DynamicTable<_V>::Last()\r\n{\r\n\t\r\n\tDbg_MsgAssert(m_entriesFilled > 0,( \"empty list\"));\r\n\r\n\treturn *mpp_table[m_entriesFilled-1];\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> \r\nDynamicTableDestroyer<_V>::DynamicTableDestroyer(DynamicTable<_V> *pTable)\r\n{\r\n\tmp_table = pTable;\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> \r\nvoid DynamicTableDestroyer<_V>::DeleteTableContents()\r\n{\r\n\tint size = mp_table->GetSize();\r\n\tfor (int i = 0; i < size; i++)\r\n\t{\r\n\t\t//if (!mp_table->IsEmpty())\r\n\t\t\tdelete &(*mp_table)[i];\r\n\t}\r\n\tmp_table->Reset();\r\n}\r\n\r\n\r\n\r\n} // namespace Lst\r\n\r\n#endif\t// __CORE_LIST_DYNAMICTABLE_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/HashTable.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tHashTable      \t\t\t \t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCore\\HashTable.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t9/22/2000 - rjm\t\t\t\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tA handy Hashtable class\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_LIST_HASHTABLE_H\r\n#define __CORE_LIST_HASHTABLE_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n\t#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __PLAT_WN32__\r\n\t#include <sys/mem/PoolManager.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Lst\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\ntemplate< class _V > class HashTable;\r\n\r\n\t\r\ntemplate< class _V > class HashItem\r\n{\r\n\tfriend class HashTable<_V>;\r\n\r\nprivate:\r\n\tHashItem();\r\n\tvoid\t\t\t\tInit();\r\n\r\n\tuint32 \t\t\t\tm_key;\r\n\t_V *\t\t\t\tmp_value;\r\n\tHashItem<_V> *\t\tmp_next;\r\n};\r\n\r\n\r\ntemplate <class _V> class HashTable\r\n{\r\n\ttypedef void (*HashCallback)(_V*, void*);\r\n\r\npublic:\r\n\t\t\t\t\t\t\t\t\tHashTable(uint32 numBits);\r\n\t\t\t\t\t\t\t\t\t~HashTable();\r\n\r\n\t// if any item exists with the same key, replace it\r\n\tbool \t\t\t\t\t\t\tPutItem(const uint32 &key, _V *item);\r\n\t// delete the item, and remove it from the table\r\n\tvoid \t\t\t\t\t\t\tFlushItem(const uint32 &key);\r\n\t// print all instances of an item (debugging)\r\n\tvoid \t\t\t\t\t\t\tPrintItem(const uint32 &key);\r\n\t// gets a pointer to requested item, returns NULL if item not in table\r\n\t_V *\t\t\t\t\t\t\tGetItem(const uint32 &key, bool assert_if_clash = true);\r\n\t_V *\t\t\t\t\t\t\tGetNextItemWithSameKey(const uint32 &key, _V *p_item);\r\n\tvoid \t\t\t\t\t\t\tFlushAllItems(void);\r\n\tvoid \t\t\t\t\t\t\tHandleCallback(HashCallback, void* pData);\r\n\tint\t\t\t\t\t\t\t\tGetSize(){return m_size;}\r\n\r\n\tvoid\t\t\t\t\t\t\tIterateStart();\r\n\t_V *\t\t\t\t\t\t\tIterateNext(uint32 *pRetKey = NULL);\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tvoid\t\t\t\t\t\t\tPrintContents();\r\n#endif\r\n\r\n\tvoid\t\t\t\t\t\t\tAllowDuplicateKeys(bool allowed)\r\n\t{\r\n\t\tm_allowDuplicateKeys = allowed;\r\n\t}\r\n\r\nprotected:\r\n\tuint32\t\t\t\t\t\t\tm_numBits; // resolution of hash table\r\n\tHashItem<_V> *\t\t\t\t\tmp_hash_table;\r\n\tint\t\t\t\t\t\t\t\tm_size;\t// number of entries in the table\r\n\r\n\tint\t\t\t\t\t\t\t\tm_iterator_index;\r\n\tHashItem<_V> *\t\t\t\t\tmp_iterator_item;\r\n\tbool\t\t\t\t\t\t\tm_allowDuplicateKeys;\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate<class _V> //inline\r\nHashTable<_V>::HashTable(uint32 numBits) \r\n{    \r\n    //Ryan(\"Creating HashTable\");\r\n\r\n\tm_numBits = numBits;\r\n\tmp_hash_table = new HashItem<_V>[1<<m_numBits];\r\n\tm_size = 0;\r\n\tm_allowDuplicateKeys = false;\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nHashTable<_V>::~HashTable()\r\n{\r\n    \r\n    //Ryan(\"Destroying HashTable\");\r\n\r\n\tDbg_AssertPtr( mp_hash_table );\r\n\tif (!mp_hash_table)\r\n\t\treturn;\r\n\t\r\n\tFlushAllItems();\r\n\r\n\t// Remove the table.\r\n//\tMem::Free(mp_hash_table);\r\n\tdelete[] mp_hash_table;\r\n\tmp_hash_table=NULL;\r\n}\r\n\r\ntemplate<class _V> //inline\r\nbool HashTable<_V>::PutItem(const uint32 &key, _V *item)\r\n{    \r\n    Dbg_AssertPtr(item);\r\n    //Ryan(\"putting item in Hash table\\n\");\r\n\r\n\tDbg_AssertPtr( mp_hash_table );\r\n\r\n\t// sometimes, we want to allow checksum conflicts\r\n\t// (for instance, ConvertAssets' file database)\r\n\tif ( !m_allowDuplicateKeys )\r\n\t{\r\n\t\tDbg_MsgAssert(!GetItem(key), (\"item 0x%x already in hash table\", key));\r\n\t}\r\n\r\n\t// can't add an item of 0,NULL, as that is used to indicate an empty head slot\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\tDbg_MsgAssert(key || item, (\"Both key and item are 0 (NULL) in hash table\"));\r\n\t// can have a value of NULL either, as the the test below uses  pEntry->mp_value == NULL \r\n\t// to indicate an an empty head slot\r\n\t// We could just change it to ( pEntry->mp_value || pEntry->m_key ) if NULL values are desirable\r\n\tDbg_MsgAssert( item, (\"NULL item added to hash table\"));\r\n\r\n\tHashItem<_V> *pEntry=&mp_hash_table[key&((1<<m_numBits)-1)];\r\n\tif ( pEntry->mp_value )\r\n\t{\r\n\t\t// The main table entry is already occupied, so create a new HashEntry and\r\n\t\t// link it in between the first and the rest.\r\n#ifndef __PLAT_WN32__\r\n\t\tHashItem<_V> *pNew = new (Mem::PoolManager::SCreateItem(Mem::PoolManager::vHASH_ITEM_POOL)) HashItem<_V>();\r\n#else\r\n\t\tHashItem<_V> *pNew = new HashItem<_V>;\r\n#endif\r\n\t\tpNew->m_key = key;\r\n\t\tpNew->mp_value = item;\r\n\t\tpNew->mp_next = pEntry->mp_next;\r\n\t\tpEntry->mp_next = pNew;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Main table entry is not occupied, so wack it in there.\r\n\t\tpEntry->m_key = key;\r\n\t\tpEntry->mp_value = item;\r\n\t\t// leave pEntry->mp_next untouched\r\n\t}\r\n\r\n\tm_size++;\t\r\n\treturn true;\r\n}\r\n\r\n\r\ntemplate<class _V> //inline\r\n_V *HashTable<_V>::GetNextItemWithSameKey(const uint32 &key, _V *p_item)\r\n{\r\n    Dbg_AssertPtr( mp_hash_table );\r\n\r\n\t// Jump to the linked list of all entries with similar checksums.\t\r\n\tHashItem<_V> *pEntry=&mp_hash_table[key&((1<<m_numBits)-1)];\r\n\r\n\t// Look for p_item\r\n\twhile (pEntry)\r\n\t{\r\n\t\tif (pEntry->m_key == key && pEntry->mp_value==p_item)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tpEntry=pEntry->mp_next;\r\n\t}\r\n\tif (!pEntry)\r\n\t{\r\n\t\t// p_item was not found.\r\n\t\treturn NULL;\r\n\t}\t\r\n\r\n\t// Found p_item, so search the rest of the list for the next element with the same key.\r\n\tpEntry=pEntry->mp_next;\r\n\twhile (pEntry)\r\n\t{\r\n\t\tif (pEntry->m_key == key && pEntry->mp_value)\r\n\t\t{\r\n\t\t\treturn pEntry->mp_value;\r\n\t\t}\t\r\n\t\tpEntry=pEntry->mp_next;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\ntemplate<class _V> //inline\r\n_V *HashTable<_V>::GetItem(const uint32 &key, bool assert_if_clash)\r\n{\r\n    Dbg_AssertPtr( mp_hash_table );\r\n\r\n\t// Jump to the linked list of all entries with similar checksums.\t\r\n\tHashItem<_V> *pEntry=&mp_hash_table[key&((1<<m_numBits)-1)];\r\n\t// Scan through the small list until the matching entry is found.\r\n\r\n\t// Note: the main table entry might be empty, so we still want to scan\r\n\t// the linked ones\r\n\r\n\twhile (pEntry)\r\n\t{\r\n\t\tif (pEntry->m_key == key && pEntry->mp_value)\r\n\t\t{\r\n\t\t\treturn (_V *) pEntry->mp_value;\r\n\t\t}\t\r\n\t\tpEntry=pEntry->mp_next;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n\r\ntemplate<class _V> //inline\r\nvoid HashTable<_V>::PrintItem(const uint32 &key)\r\n{\r\n    Dbg_AssertPtr( mp_hash_table );\r\n\r\n\t// Jump to the linked list of all entries with similar checksums.\t\r\n\tHashItem<_V> *pEntry=&mp_hash_table[key&((1<<m_numBits)-1)];\r\n\t// Scan through the small list until the matching entry is found.\r\n\r\n\tint n =0;\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t// Note: the main table entry might be empty, so we still want to scan\r\n\t// the linked ones\r\n\r\n\twhile (pEntry)\r\n\t{\r\n\t\tif (pEntry->m_key == key && pEntry->mp_value)\r\n\t\t{\r\n\t\t\tprintf (\"%d: Entry for 0x%x at %p\\n\", n ,key,(_V *) pEntry->mp_value);\r\n\t\t\tn++;\r\n\t\t}\t\r\n\t\tpEntry=pEntry->mp_next;\r\n\t}\r\n\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nvoid HashTable<_V>::FlushItem(const uint32 &key)\r\n{\r\n\r\n\tDbg_AssertPtr( mp_hash_table );\r\n\tif (!mp_hash_table)\r\n\t\treturn;\r\n\r\n\t// Jump to the linked list of all entries with similar checksums.\t\r\n\tHashItem<_V> *pEntry=&mp_hash_table[key&((1<<m_numBits)-1)];\r\n\tHashItem<_V> *pLast = NULL;\r\n\t\r\n\t// Scan through the small list until the matching entry is found.\r\n\twhile (pEntry)\r\n\t{\r\n\t\tHashItem<_V> *p_next_entry = pEntry->mp_next;\r\n\t\tif (pEntry->m_key==key && pEntry->mp_value)\t\t// to allow keys of value 0, we have to skip head nodes that are 0,NULL\r\n\t\t{\r\n\t\t\tif (pLast)\r\n\t\t\t{\r\n\t\t\t\t// this is not a main table entry; this is a linked entry\r\n\t\t\t\tpLast->mp_next = pEntry->mp_next;\r\n#ifndef __PLAT_WN32__\r\n\t\t\t\tMem::PoolManager::SFreeItem(Mem::PoolManager::vHASH_ITEM_POOL, pEntry);\r\n#else\r\n\t\t\t\tdelete pEntry;\r\n#endif\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// this is a main table entry, it still might be linked to something\r\n\t\t\t\t// clear the entry to 0,NULL (see comment above about keys of value 0)\r\n\t\t\t\tpEntry->m_key = 0;\r\n\t\t\t\tpEntry->mp_value = NULL;\r\n\t\t\t}\r\n\t\t\tm_size--;\r\n\t\t\treturn;\r\n\t\t}\t\r\n\t\tpLast = pEntry;\r\n\t\tpEntry = p_next_entry;\r\n\t}\r\n\treturn;\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nvoid HashTable<_V>::FlushAllItems()\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr( mp_hash_table );\r\n\tif (!mp_hash_table)\r\n\t\treturn;\r\n\r\n\t// Run through the table and delete any of the extra\r\n\t// HashItem<_V>s.\r\n\tHashItem<_V> *pMainEntry = mp_hash_table;\r\n\tuint32 hashTableSize = (1<<m_numBits);\r\n\tfor (uint32 i=0; i<hashTableSize; ++i)\r\n\t{\r\n\t\tHashItem<_V> *pLinkedEntry = pMainEntry->mp_next;\r\n\t\twhile (pLinkedEntry)\r\n\t\t{\r\n\t\t\tHashItem<_V> *pNext = pLinkedEntry->mp_next;\r\n#ifndef __PLAT_WN32__\r\n\t\t\tMem::PoolManager::SFreeItem(Mem::PoolManager::vHASH_ITEM_POOL, pLinkedEntry);\r\n#else\r\n\t\t\tdelete pLinkedEntry;\r\n#endif\r\n\t\t\tpLinkedEntry = pNext;\r\n\t\t}\r\n\t\tpMainEntry->Init();\r\n\t\t++pMainEntry;\r\n\t}\t\r\n\tm_size = 0;\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nvoid HashTable<_V>::HandleCallback(HashCallback hashCallback, void* pData)\r\n{\r\n\tHashItem<_V> *pMainEntry = mp_hash_table;\r\n\tuint32 hashTableSize=(1<<m_numBits);\r\n\tfor (uint32 i=0; i<hashTableSize; ++i)\r\n\t{\r\n\t\tHashItem<_V> *pLinkedEntry = pMainEntry->mp_next;\r\n\t\twhile (pLinkedEntry)\r\n\t\t{\r\n\t\t\tHashItem<_V> *pNext = pLinkedEntry->mp_next;\r\n//\t\t\tMem::Free(pLinkedEntry);\r\n\t\t\tif (pLinkedEntry->mp_value)\r\n\t\t\t\t(hashCallback)((_V *) pLinkedEntry->mp_value, pData);\r\n\t\t\tpLinkedEntry = pNext;\r\n\t\t}\r\n\t\tif (pMainEntry->mp_value)\r\n\t\t\t(hashCallback)((_V *) pMainEntry->mp_value, pData);\r\n\t\t++pMainEntry;\r\n\t}\t\r\n\r\n}\r\n\r\n\r\n\r\n\t\r\ntemplate<class _V> //inline\r\nvoid HashTable<_V>::IterateStart()\r\n{\r\n\tm_iterator_index = -1;\r\n\tmp_iterator_item = NULL;\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\n_V * HashTable<_V>::IterateNext(uint32 *pRetKey)\r\n{\r\n\tuint32 hashTableSize=(1<<m_numBits);\r\n\t\r\n\t// time to go to the next entry, or the first if we're just starting\r\n\t\r\n\tif (mp_iterator_item)\r\n\t\t// next entry in list\r\n\t\tmp_iterator_item = mp_iterator_item->mp_next;\r\n\telse if (m_iterator_index >= 0)\r\n\t\t// we've exhausted all the lists\r\n\t\treturn NULL;\r\n\t\r\n\tif (!mp_iterator_item)\r\n\t{\r\n\t\t// no entry in list, move on to next list\r\n\t\tdo\r\n\t\t{\r\n\t\t\tm_iterator_index++;\t\r\n\t\t\tif (m_iterator_index >= (int) hashTableSize)\r\n\t\t\t\treturn NULL;\r\n\t\t\tmp_iterator_item = mp_hash_table + m_iterator_index;\r\n\t\t} \t// main entry has to contain something, or be part of a list\r\n\t\twhile (!mp_iterator_item->mp_value && !mp_iterator_item->mp_next);\r\n\t\tif (!mp_iterator_item->mp_value)\r\n\t\t\t// this must be an empty main entry, skip ahead\r\n\t\t\tmp_iterator_item = mp_iterator_item->mp_next;\r\n\t}\r\n\t\r\n\t// Ken: Added this because it was hanging here once when loading the junkyard\r\n\t// off CD. It was trying to dereference mp_iterator_item. Added the printf\r\n\t// so we can at least see when it happens without having to go into the debugger.\r\n\tif (!mp_iterator_item)\r\n\t{\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tprintf(\"Error!! NULL mp_iterator_item in IterateNext()\\n\");\r\n\t\t#endif\r\n\t\treturn NULL;\r\n\t}\t\r\n\tif (pRetKey)\r\n\t\t*pRetKey = mp_iterator_item->m_key;\r\n\treturn mp_iterator_item->mp_value;\r\n}\r\n\r\n\r\n\r\n\r\n#ifdef __NOPT_ASSERT__\r\ntemplate<class _V> //inline\r\nvoid HashTable<_V>::PrintContents()\r\n{\r\n\tprintf(\"Items in Hash Table:\\n\");\r\n\tuint32 hashTableSize=(1<<m_numBits);\r\n\tfor (uint32 i = 0; i < hashTableSize; ++i)\r\n\t{\r\n\t\tHashItem<_V> *pEntry = mp_hash_table + i;\r\n\t\twhile(pEntry)\r\n\t\t{\r\n\t\t\tif (pEntry->mp_value)\t\t\t\r\n\t\t\t\tprintf(\"    0x%x [%d]\\n\", pEntry->m_key, i);\r\n\t\t\tpEntry = pEntry->mp_next;\r\n\t\t}\r\n\t}\t\t\r\n}\r\n#endif\r\n\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nHashItem<_V>::HashItem<_V>()\r\n{\r\n\tInit();\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nvoid HashItem<_V>::Init()\r\n{\r\n\tm_key = 0;\r\n\tmp_value = NULL;\r\n\tmp_next = NULL;\r\n}\r\n\r\n} // namespace Lst\r\n\r\n#endif\t// __CORE_LIST_HASHTABLE_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/List/Head.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tList (LST_)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/list/head.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__CORE_LIST_HEAD_H\r\n#define\t__CORE_LIST_HEAD_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/list/node.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Lst\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/***********************************************************************\r\n *\r\n * Class:\t\t\tHead\r\n *\r\n * Description:\t\tLinked-list head node. \r\n *\r\n ***********************************************************************/\r\n\r\nnTemplateSubClass( _T, Head, Node< _T > )\r\n{\r\n\r\npublic:\r\n\t\t\t\t\tHead( void );\r\n\tvirtual\t\t\t~Head( void );\r\n\r\n\tvoid\t\t\tMerge( Head< _T >* dest );\t\t// Source list will be empty after merge\r\n\tuint\t\t\tCountItems( void );\r\n\tNode< _T >*\t\tGetItem( uint number );\t\t\t// Zero-based ( 0 will return first node )\r\n\t\r\n\tvoid\t\t\tAddNode( Node< _T >* node );\t// Using priority\r\n\tvoid\t\t\tAddNodeFromTail( Node< _T >* node );\t// Using priority, search backwards from tail (i.e same-priorties are appended rather than pre-pended)\r\n\tbool\t\t\tAddUniqueSequence( Node< _T >* node );\t// Only add if priority is unique\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// and priority decreases\r\n\tvoid\t\t\tAddToTail( Node< _T >* node );\r\n\tvoid\t\t\tAddToHead( Node< _T >* node );\r\n\r\n\tvoid\t\t\tRemoveAllNodes( void );\r\n\tvoid\t\t\tDestroyAllNodes( void );  \t\t// ONLY USE FOR INHERITED LISTS\r\n\tbool\t\t\tIsEmpty( void );\r\n\r\n\tNode< _T >*\t\tFirstItem();\t\t\t\t\t// get first node, or NULL if none \r\n\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nHead< _T >::Head( void )\r\n: Node< _T > ( reinterpret_cast < _T* >( vHEAD_NODE ) ) \r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nHead< _T >::~Head( void )\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert( IsEmpty(),( \"List is not empty\" ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nvoid\tHead< _T >::AddNode( Node< _T >* node )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( node, Node< _T > );\r\n\tDbg_MsgAssert( this->is_head (),( \"Object is not a list\" ));\r\n\tDbg_MsgAssert( !node->InList (),( \"Object is already in a list\" ));\r\n\r\n\tNode< _T >*\t\tnode_ptr =\tthis;\r\n\tPriority\t\tnew_pri\t =\tnode->GetPri();\r\n\r\n\twhile (( node_ptr = node_ptr->GetNext() ))\r\n\t{\r\n\t\tif ( node_ptr->GetPri() <= new_pri )\r\n\t\t{\r\n\t\t\tnode_ptr->Insert( node );\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tInsert( node );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nvoid\tHead< _T >::AddNodeFromTail( Node< _T >* node )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( node, Node< _T > );\r\n\tDbg_MsgAssert( this->is_head (),( \"Object is not a list\" ));\r\n\tDbg_MsgAssert( !node->InList (),( \"Object is already in a list\" ));\r\n\r\n\tNode< _T >*\t\tnode_ptr =\tthis;\r\n\tPriority\t\tnew_pri\t =\tnode->GetPri();\r\n\r\n\twhile (( node_ptr = node_ptr->GetPrev() ))\r\n\t{\r\n\t\tif ( node_ptr->GetPri() >= new_pri )\r\n\t\t{\r\n\t\t\tnode_ptr->Append( node );\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tAppend( node );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nbool\tHead< _T >::AddUniqueSequence( Node< _T >* node )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( node, Node< _T > );\r\n\tDbg_MsgAssert( this->is_head (),( \"Object is not a list\" ));\r\n\tDbg_MsgAssert( !node->InList (),( \"Object is already in a list\" ));\r\n\r\n\tNode< _T >*\t\tnode_ptr =\tthis;\r\n\tPriority\t\tnew_pri\t =\tnode->GetPri();\r\n\r\n\twhile (( node_ptr = node_ptr->GetNext() ))\r\n\t{\r\n\t\tif ( node_ptr->GetPri() == new_pri )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\telse if ( node_ptr->GetPri() > new_pri )\r\n\t\t{\r\n\t\t\tnode_ptr->Insert( node );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tInsert( node );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nvoid\t\tHead< _T >::Merge( Head< _T >* dest )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( dest, Head< _T > );\r\n\tDbg_MsgAssert( this->is_head (),( \"Object is not a list\" ));\r\n\tDbg_MsgAssert( dest->is_head (),( \"Object is not a list\" ));\r\n\r\n\tNode< _T >*\t\tfirst = next;\t\r\n\tNode< _T >*\t\tlast = prev;\r\n\tNode< _T >*\t\tnode = dest->GetPrev();\r\n\t\r\n\tif ( this == first )\t\t\t// source list is empty\r\n\t{\r\n\t   \treturn;\r\n\t}\r\n\t\r\n\tnode->SetNext( first );\r\n\tfirst->SetPrev( node );\r\n\r\n\tlast->SetNext( dest );\r\n\tdest->SetPrev( last );\r\n\t\r\n\tnode_init();\t\t\t\t\t// make the source list empty\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nNode< _T >*\t\tHead< _T >::GetItem( uint number )\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert( this->is_head (),( \"Object is not a list\" ));\r\n\r\n\tNode< _T >*\t\tnode = GetNext();\r\n\r\n\twhile ( node )\r\n\t{\r\n\t\tif ( number-- == 0 )\r\n\t\t{\r\n\t\t\treturn node;\r\n\t\t}\r\n\r\n\t\tnode = node->GetNext();\r\n\t}\r\n\r\n\tDbg_Warning( \"Item requested (%d) out of range (%d)\", number, CountItems() );\r\n\r\n\treturn NULL;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Return the firs node in the list that this is the head of\r\n\r\ntemplate < class _T > inline\t\r\nNode< _T >*\t\tHead< _T >::FirstItem( )\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert( this->is_head (),( \"Object is not a list\" ));\r\n\r\n\treturn GetNext();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate <class _T > inline\t\r\nuint\t\tHead< _T >::CountItems( void )\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert( this->is_head (),( \"Object is not a list\" ));\r\n\r\n\tuint\t\t\tcount = 0;\r\n\tNode< _T >*\tnode = GetNext();\r\n\r\n\twhile ( node )\r\n\t{\r\n\t\tcount++;\r\n\t\tnode = node->GetNext();\r\n\t}\r\n\r\n\treturn count;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate <class _T> inline\t\r\nvoid\t\tHead< _T >::RemoveAllNodes( void )\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert( this->is_head (),( \"Object is not a list\" ));\r\n\r\n\tNode< _T >*\t\tnext_nd;\r\n\tNode< _T >*\t\tnode = GetNext();\r\n\r\n\twhile ( node )\r\n\t{\r\n\t\tnext_nd = node->GetNext();\r\n\t\tnode->Remove();\r\n\t\tnode = next_nd;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate <class _T> inline\t\r\nvoid\t\tHead< _T >::DestroyAllNodes( void )\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert( this->is_head (),( \"Object is not a list\" ));\r\n\r\n\tNode< _T >*\t\tnext_nd;\r\n\tNode< _T >*\t\tnode = GetNext();\r\n\r\n\twhile ( node )\r\n\t{\r\n\t\tnext_nd = node->GetNext();\r\n//\t\tnode->Remove();\r\n\t\tdelete node;\r\n\t\tnode = next_nd;\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ntemplate <class _T> inline\t\r\nvoid\t\tHead< _T >::AddToTail( Node< _T >* node )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( node, Node< _T > );\r\n\tDbg_MsgAssert( this->is_head (),( \"Object is not a list\" ));\r\n\tDbg_MsgAssert( !node->InList (),( \"Node is already in a list\" ));\r\n\r\n\tInsert ( node );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate <class _T> inline\t\r\nvoid\t\tHead< _T >::AddToHead ( Node< _T >* node )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( node, Node< _T > );\r\n\tDbg_MsgAssert( this->is_head(),(( \"Object is not a list\" )));\r\n\tDbg_MsgAssert( !node->InList(),(( \"Node is already in a list\" )));\r\n\r\n\tAppend( node );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate <class _T> inline\r\nbool\t\tHead< _T >::IsEmpty( void )\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert ( this->is_head(),( \"Object is not a list\" ));\r\n\r\n\treturn ( !InList() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Lst\r\n\r\n#endif\t//\t__CORE_LIST_HEAD_H\r\n"
  },
  {
    "path": "Code/Core/List/Node.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tList (LST_)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/list/node.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__CORE_LIST_Node_H\r\n#define\t__CORE_LIST_Node_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/support.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Lst\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/***********************************************************************\r\n *\r\n * Class:\t\t\tLst::Node\r\n *\r\n * Description:\t\tLinked-list node. \r\n *\r\n ***********************************************************************/\r\n\r\nnTemplateBaseClass( _T, Node )\r\n{\r\n\t\r\n\r\npublic:\r\n\r\n\t// GJ:  Note we have to cast vINT_MIN to an sint\r\n\t// ( ((sint)vINT_MIN) / 2 ) ends up positive.\r\n\t\t\r\n\tenum \r\n\t{\r\n\t\tvNORMAL_PRIORITY\t= 0,\r\n\t\tvHEAD_NODE\t\t\t= vUINT32_MAX\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n\t\tvSYSTEM_TASK_PRIORITY_PROCESS_MODULES\t\t= -1000,\r\n\t\tvSYSTEM_TASK_PRIORITY_FLUSH_DEAD_OBJECTS\t= 1000,\r\n\t};\r\n\t\r\n\tenum\r\n\t{\r\n\t\tvLOGIC_TASK_PRIORITY_REPLAY_END_FRAME\t\t\t\t= -3000,\r\n\t\tvLOGIC_TASK_PRIORITY_PROCESS_NETWORK_METRICS\t\t= -2500,\r\n\t\tvLOGIC_TASK_PRIORITY_SERVER_SEND_NETWORK_DATA\t\t= -2000,\r\n\t\tvLOGIC_TASK_PRIORITY_CLIENT_SEND_NETWORK_DATA\t    = -2000,\r\n\t\tvLOGIC_TASK_PRIORITY_TIMEOUT_CONNECTIONS\t\t\t= -2000,\r\n\t\tvLOGIC_TASK_PRIORITY_CLIENT_ADD_NEW_PLAYERS\t\t\t= -2000,\r\n\t\tvLOGIC_TASK_PRIORITY_SERVER_ADD_NEW_PLAYERS\t\t    = -2000,\r\n\t\tvLOGIC_TASK_PRIORITY_FRONTEND\t\t\t\t\t    = -2000,\r\n\t\tvLOGIC_TASK_PRIORITY_SCRIPT_DEBUGGER\t\t\t\t= -1500,\r\n\t\tvLOGIC_TASK_PRIORITY_LOCKED_OBJECT_MANAGER_LOGIC    = -1100,\r\n\t\tvLOGIC_TASK_PRIORITY_PARTICLE_MANAGER_LOGIC\t\t    = -1000,\r\n\t\tvLOGIC_TASK_PRIORITY_HANDLE_KEYBOARD\t\t\t    = -1000,\r\n\t\tvLOGIC_TASK_PRIORITY_OBJECT_UPDATE\t\t\t\t    = -1000,\r\n\t\tvLOGIC_TASK_PRIORITY_SCORE_UPDATE\t\t\t\t    = -1000,\r\n        vLOGIC_TASK_PRIORITY_COMPOSITE_MANAGER              = -900,\r\n\t\tvLOGIC_TASK_PRIORITY_PROCESS_NETWORK_DATA\t    \t= 0,\r\n\t\tvLOGIC_TASK_PRIORITY_SKATER_SERVER\t\t\t\t    = 1000,\r\n\t\tvLOGIC_TASK_PRIORITY_TRANSFER_NETWORK_DATA\t\t    = 1000,\r\n\t\tvLOGIC_TASK_PRIORITY_RECEIVE_NETWORK_DATA\t\t    = 1000,\r\n\t\tvLOGIC_TASK_PRIORITY_PROCESS_HANDLERS\t\t\t    = 2000,\r\n\t\tvLOGIC_TASK_PRIORITY_REPLAY_START_FRAME\t\t\t\t= 3000,\r\n    };\r\n\t\r\n\tenum\r\n\t{\r\n\t\tvDISPLAY_TASK_PRIORITY_PARK_EDITOR_DISPLAY\t= -1000,\r\n\t\tvDISPLAY_TASK_PRIORITY_CPARKEDITOR_DISPLAY\t= -1000,\r\n\t\tvDISPLAY_TASK_PRIORITY_IMAGE_VIEWER_DISPLAY\t= -1000,\r\n\t\tvDISPLAY_TASK_PRIORITY_PANEL_DISPLAY\t\t= -500,\r\n\t};\r\n\t\t\r\n\tenum\r\n\t{\r\n\t\tvHANDLER_PRIORITY_OBSERVER_INPUT_LOGIC\t\t= -1000,\r\n\t\tvHANDLER_PRIORITY_FRONTEND_INPUT_LOGIC0\t\t= -1000,\r\n\t\tvHANDLER_PRIORITY_FRONTEND_INPUT_LOGIC1\t\t= -1000,\r\n\t\tvHANDLER_PRIORITY_IMAGE_VIEWER_INPUT_LOGIC\t= 1000,\r\n\t\tvHANDLER_PRIORITY_VIEWER_SHIFT_INPUT_LOGIC\t= 1000,\r\n\t};\r\n\t\t\r\n\ttypedef sint\t\tPriority;\r\n\r\n\t\t\t\t\t\tNode ( _T* d, Priority p = vNORMAL_PRIORITY );\r\n\tvirtual\t\t\t\t~Node ( void );\r\n\r\n\tvoid\t\t\t\tInsert ( Node< _T >* node );\r\n\tvoid\t\t\t\tAppend ( Node< _T >* node );\r\n\tvoid \t\t\t\tRemove ( void );\t\r\n\t\r\n\tvoid\t\t\t\tSetPri  ( const Priority priority );\r\n\tvoid\t\t\t\tSetNext ( Node< _T >* node );\r\n\tvoid\t\t\t\tSetPrev ( Node< _T >* node );\r\n\r\n\tPriority\t\t\tGetPri  ( void ) const;\r\n\tNode< _T >*\t\t\tGetNext ( void ) const;\r\n\tNode< _T >*\t\t\tGetPrev ( void ) const;\r\n\t_T*\t\t\t\t\tGetData ( void ) const;\t\r\n\r\n\tNode< _T >*\t\t\tLoopNext ( void ) const;\r\n\tNode< _T >*\t\t\tLoopPrev ( void ) const;\r\n\r\n\tbool\t\t\t\tInList ( void ) const;\r\n\r\nprotected:\r\n\r\n\tbool\t\t\t\tis_head ( void ) const;\r\n\tvoid\t\t\t\tnode_init ( void );\r\n\r\nprivate:\r\n\r\n\t_T*\t\t\t\t\tdata;\r\n\tPriority\t\t\tpri;\r\n\tNode< _T >*\t\t\tnext; \r\n\tNode< _T >*\t\t\tprev;\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tPrivate Inline Functions\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntemplate < class _T > inline\r\nvoid\t\tNode< _T >::node_init( void )\r\n{\r\n\t\r\n\t\r\n\tnext = this;\r\n\tprev = this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nbool\t\tNode< _T >::is_head( void ) const\r\n{\r\n\t\r\n\r\n\treturn ( data == reinterpret_cast<void*>( vHEAD_NODE ));\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tPublic Inline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntemplate < class _T > inline\r\nNode< _T >::Node( _T* d, Priority p )\r\n: data( d ), pri( p )\r\n{\r\n\t\r\n\r\n\tnode_init();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Must define inline functions before they are used\r\ntemplate < class _T > inline\t\r\nvoid \tNode< _T >::Remove( void )\r\n{\r\n\t\r\n\r\n\tprev->next = next;\r\n\tnext->prev = prev;\r\n\t\r\n\tnode_init();\t\t// so we know that the node is not in a list\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nNode< _T >::~Node( void )\r\n{\r\n\t\r\n\r\n\tRemove();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Mick:  Moved this here from the end of the file\r\n// as it's intended to b inline\r\n// yet it is used by other functions below\r\n\r\ntemplate < class _T > inline\t\r\nbool\t\tNode< _T >::InList( void ) const\r\n{\r\n\t\r\n\r\n\treturn ( prev != this );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nvoid\tNode< _T >::Insert ( Node< _T >* node )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( node, Node< _T > );\r\n\tDbg_MsgAssert( !node->InList(),(\"node is already in a list\" ));\r\n\r\n\tnode->prev = prev;\r\n\tnode->next = this;\r\n\tprev->next = node;\r\n\tprev = node;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nvoid\tNode< _T >::Append( Node< _T >* node )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( node, Node< _T > );\r\n\tDbg_MsgAssert( !node->InList(),( \"node is already in a list\" ));\r\n\r\n\tnode->prev = this;\r\n\tnode->next = next;\r\n\tnext->prev = node;\r\n\tnext = node;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nvoid\tNode< _T >::SetPri( const Priority priority )\r\n{\r\n\t\r\n\r\n\tpri = priority;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nvoid\tNode< _T >::SetNext( Node< _T >* node )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( node, Node< _T > );\r\n\r\n\tnext = node;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nvoid\tNode< _T >::SetPrev( Node< _T >* node )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( node, Node< _T > );\r\n\r\n\tprev = node;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\ntypename Node< _T >::Priority Node< _T >::GetPri( void ) const\r\n{\r\n\treturn pri;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nNode< _T >*\t\tNode< _T >::GetNext( void ) const\r\n{\r\n\t\r\n\t\r\n\tif ( next->is_head() )\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\treturn next;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nNode< _T >*\t\tNode< _T >::GetPrev( void ) const\r\n{\r\n\t\r\n\r\n\tif ( prev->is_head() )\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\treturn prev;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\n_T*\t\tNode< _T >::GetData( void ) const\r\n{\r\n\t\r\n\t\r\n\treturn data;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nNode< _T >*\t\tNode< _T >::LoopNext( void ) const\r\n{\r\n\t\r\n\r\n\tNode< _T >*\t\tnext_node = next;\r\n\r\n\tif ( next_node->is_head() )\r\n\t{\r\n\t\tnext_node = next_node->next;\t// skip head node\r\n\t\r\n\t\tif ( next_node->is_head() )\r\n\t\t{\r\n\t\t\treturn NULL;\t\t\t\t// list is empty\r\n\t\t}\r\n\t}\r\n\r\n\treturn next_node;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nNode< _T >*\t\tNode< _T >::LoopPrev( void ) const\r\n{\r\n\t\r\n\r\n\tNode< _T >*\t\tprev_node = prev;\r\n\r\n\tif ( prev_node->is_head() )\r\n\t{\r\n\t\tprev_node = prev_node->prev;\t// skip head node\r\n\t\r\n\t\tif ( prev_node->is_head() )\r\n\t\t{\r\n\t\t\treturn NULL;\t\t\t\t// list is empty\r\n\t\t}\r\n\t}\r\n\r\n\treturn prev_node;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Lst\r\n\r\n#endif\t//\t__CORE_LIST_Node_H\r\n"
  },
  {
    "path": "Code/Core/List/Search.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tList (LST_)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/list/search.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t04/02/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__CORE_LIST_SEARCH_H\r\n#define\t__CORE_LIST_SEARCH_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/list/node.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Lst\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnTemplateBaseClass ( _T, Search )\r\n{\r\n\t\r\n\r\npublic:\r\n\t\t\t\t\tSearch ( void );\r\n\tvirtual\t\t\t~Search ( void );\r\n\r\n\r\n\t_T*\t\t\t\tFirstItem ( Head<_T>& head );\r\n\t_T*\t\t\t\tLastItem ( Head<_T>& head );\r\n\t_T*\t\t\t\tNextItem ( void );\r\n\t_T*\t\t\t\tPrevItem ( void );\r\n\r\nprivate:\r\n\r\n\tNode< _T >*\tnode;\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntemplate <class _T> inline \r\nSearch<_T>::Search ( void )\r\n: node ( NULL )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate <class _T> inline \r\nSearch<_T>::~Search ( void )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate <class _T> inline \r\n_T*\tSearch<_T>::FirstItem ( Head<_T>& head )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType ( &head, Head<_T> );\r\n\r\n\tnode = &head;\r\n\r\n\treturn ( NextItem () );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate <class _T> inline \r\n_T*\tSearch<_T>::LastItem ( Head<_T>& head )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType ( &head, Head<_T> );\r\n\r\n\tnode = &head;\r\n\r\n\treturn ( PrevItem () );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate <class _T> inline \r\n_T*\tSearch<_T>::NextItem ( void )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType ( node, Node< _T > );\r\n\r\n\tnode = node->GetNext();\r\n\r\n\tif ( !node )\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tDbg_AssertType ( node, Node<_T> );\r\n\r\n\treturn ( node->GetData() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate <class _T> inline \r\n_T*\tSearch<_T>::PrevItem ( void )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType ( node, Node< _T > );\r\n\r\n\tnode = node->GetPrev();\r\n\r\n\tif ( !node )\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tDbg_AssertType ( node, Node<_T> );\r\n\r\n\treturn ( node->GetData() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Lst\r\n\r\n#endif\t//\t__CORE_LIST_SEARCH_H \r\n"
  },
  {
    "path": "Code/Core/List/list.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tList (Lst)\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tlist.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tList management code\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/List.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tList (Lst)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/list.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__CORE_LIST_H\r\n#define\t__CORE_LIST_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/list/node.h>\r\n#include <core/list/head.h>\r\n#include <core/list/search.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#endif\t//\t__CORE_LIST_H\r\n"
  },
  {
    "path": "Code/Core/LookupTable.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tList                                                    **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCore\\List\\LookupTable.cpp\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t9/22/2000 - rjm\t\t\t\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tA Lookuptable\t\t\t                                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/string/cstring.h>\r\n#include <core/lookuptable.h>\r\n\r\n//\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Lst\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************************\r\n *\r\n * Function:\t\r\n *\r\n * Description: Default constructor\t\t\t\r\n *\r\n * Parameters:\t\r\n * \r\n *****************************************************************************/\r\n\r\n\r\n} // namespace Lst\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/LookupTable.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tLookupTable      \t\t\t \t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCore\\LookupTable.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t9/22/2000 - rjm\t\t\t\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tA handy Lookuptable class\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_LIST_LOOKUPTABLE_H\r\n#define __CORE_LIST_LOOKUPTABLE_H\r\n\r\n#ifndef __CORE_CRC_H\r\n#include <core/crc.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Lst\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/****************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n * Class:\t\t\tLookupItem\r\n *\r\n * Description:\t\tUsed to represent an item in a Lookup table.\r\n *\r\n *                  Usage:  \r\n *                          \r\n *                          \r\n *\r\n ****************************************************************************/\r\n\r\n// forward declaration\r\ntemplate< class _V > class LookupTable;\r\n\r\n//nTemplateBaseClass2(_K, _V, LookupItem)\r\ntemplate< class _V > class LookupItem\r\n{\r\n//    Dbg_TemplateBaseClass2(_K, _V, LookupItem);\r\n\r\n\tfriend class LookupTable<_V>;\r\n\t\r\nprivate:\r\n\tLookupItem();\r\n\r\n\tint \t\t\t\tm_key;\r\n\t_V *\t\t\t\tmp_value;\r\n\tLookupItem<_V> *\tmp_next;\r\n};\r\n    \r\n\r\n\r\nnTemplateBaseClass(_V, LookupTable)\r\n{\r\n    Dbg_TemplateBaseClass(_V, LookupTable);\r\n\r\npublic:\r\n\tLookupTable(int size=0);\t   \t// Mick, size is not used, so give it default until we get rid of it\r\n\t~LookupTable();\r\n\r\n\t// if any item exists with the same key, replace it\r\n\tbool PutItem(const int &key, _V *item);\r\n\t// gets a pointer to requested item, returns NULL if item not in table\r\n\t_V *GetItem(const int &key);\r\n\t// gets a pointer to requested item, returns NULL if item not in table\r\n\t_V *GetItemByIndex(const int &index, int *pKey = NULL);\r\n\tint getSize() {return m_size;}\r\n\r\n    // removes item from table, calls its destructor if requested\r\n    void FlushItem(const int &key);\r\n\tvoid flushAllItems();\r\n\r\nprivate:\r\n\tint \t\t\t\tm_size;\r\n\tLookupItem<_V> *\tmp_list;\t\t  // first item in list\r\n\tLookupItem<_V> *\tmp_last;\t\t  // last item in list\r\n\tLookupItem<_V> *    mp_current;\t\t  // Pointer to current item in this table, NULL if invalid\r\n\tint\t\t\t\t\tm_currentIndex;\t  // the index of this item. Only valid if mp_current is not NULL \r\n};\r\n\r\n\r\n\r\ntemplate<class _V>\r\nclass StringLookupTable : public LookupTable<_V>\r\n{\r\n    //Dbg_TemplateBaseClass2(_K, _V, LookupItem);\r\n\r\npublic:\r\n    StringLookupTable(int size);\r\n\r\n    bool PutItem(const char *stringKey, _V *item);\r\n    _V *GetItem(const char *stringKey);\r\n    void FlushItem(const char *stringKey);\r\n};\r\n\r\n\r\n\r\ntemplate<class _V>\r\nclass LookupTableDestroyer\r\n{\r\npublic:\r\n\tLookupTableDestroyer(LookupTable<_V> *pTable);\r\n\r\n\tvoid DeleteTableContents();\r\n\r\nprivate:\r\n\tLookupTable<_V> *\t\t\tmp_table;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate<class _V> //inline\r\nLookupItem<_V>::LookupItem()\r\n{\r\n    mp_value = NULL;\r\n\tmp_next = NULL;\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nLookupTable<_V>::LookupTable(int size=0) \r\n{\r\n    m_size = 0;\r\n\tmp_list = NULL;\r\n\tmp_current = NULL;\t   \t\t\t// initialized invalid, so we don't try to use it\r\n}\r\n\r\n\t\r\n\r\ntemplate<class _V> //inline\r\nLookupTable<_V>::~LookupTable()\r\n{\r\n\tflushAllItems();\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nbool LookupTable<_V>::PutItem(const int &key, _V *item)\r\n{\r\n    \r\n    Dbg_AssertPtr(item);\r\n    //Ryan(\"putting item in lookup table\\n\");\r\n\r\n#\tifdef __NOPT_DEBUG__\r\n\tif (GetItem(key)) return false;\r\n#\tendif\r\n\t\r\n\tLookupItem<_V> *pItem = new LookupItem<_V>;\r\n\tpItem->mp_value = item;\r\n\tpItem->m_key = key;\r\n\r\n\tif (!mp_list)\r\n\t\tmp_list = pItem;\r\n\telse\r\n\t\tmp_last->mp_next = pItem;\r\n\tmp_last = pItem;\t\r\n\tm_size++;\r\n\tmp_current = NULL;\t\t\t\t\t\t// no longer valid\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\n_V *LookupTable<_V>::GetItem(const int &key)\r\n{\r\n    \r\n    \r\n\tLookupItem<_V> *pItem = mp_list;\r\n\tmp_current = NULL;\t\t\t\t  \t\t\t// set invalid now, so if not found, then it will be correctly invalid  \t\r\n\tm_currentIndex = 0;\t\t\t\t\t\t\t// index should be 0, for the first item\r\n\twhile(pItem)\r\n\t{\r\n\t\tif (pItem->m_key == key)\r\n\t\t{\r\n\t\t\tmp_current = pItem;\t\t\t \t\t// we have a valid current, and hence index\r\n\t\t\treturn pItem->mp_value;\r\n\t\t}\r\n\t\tm_currentIndex++;\t\t\t\t\t    // update index, in case we find the item \r\n\t\tpItem = pItem->mp_next;\r\n\t}\r\n    \r\n\t//printf(\"returning NULL from GetItem()\\n\");\r\n\t\r\n\t// warning should be given by calling function, if necessary\r\n    //Dbg_Warning(\"Item not found in lookup table\");\r\n    return NULL;\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\n_V *LookupTable<_V>::GetItemByIndex(const int &index, int *pKey)\r\n{\r\n    \r\n\t// size must be at least 1\r\n\tDbg_MsgAssert(index >= 0 && index < m_size,( \"bad index %d\", index));\r\n\r\n\t// if we have a valid mp_current, then check if we can use that (for speed)\r\n\tif (mp_current)\r\n\t{\r\n\t\t// is it the same as last time?\r\n\t\tif (m_currentIndex == index)\r\n\t\t{\r\n\t\t\t// It's this one, so just leave it alone\r\n\t\t}\r\n\t\telse if (m_currentIndex < index)\r\n\t\t{\r\n\t\t\t// need to step forward until we find the correct one\r\n\t\t\t// this is the most likely scenario if\r\n\t\t\t// we are using GetItemByIndex in a for loop\r\n\t\t\t// really we need an interator access class\r\n\t\t\t// but this should be similar, in terms of code speed\r\n\t\t\twhile (m_currentIndex < index)\r\n\t\t\t{\r\n\t\t\t\tm_currentIndex++;\r\n\t\t\t\tmp_current = mp_current->mp_next;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// otherwise, we need to start again, so invalidate mp_current\r\n\t\t\tmp_current = NULL;\r\n\t\t}\r\n\t}\r\n\r\n\t// if we don't have a valid mp_current at this point, then we need\r\n\t// to start searching from the start again\r\n\tif (!mp_current)\r\n\t{\r\n\t\tLookupItem<_V> *pItem = mp_list;\r\n\t\tfor (int i = 0; i < index; i++)\r\n\t\t{\r\n\t\t\tpItem = pItem->mp_next;\r\n\t\t}\r\n\t\tm_currentIndex = index;\r\n\t\tmp_current = pItem;\r\n\t}\r\n\r\n\t// if they want us to returnt he key, then poke it into the supplied destination\t\t\r\n\tif ( pKey )\r\n\t\t*pKey = mp_current->m_key;\r\n\r\n\t// the current value is correct\t\r\n\treturn mp_current->mp_value;\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nvoid LookupTable<_V>::FlushItem(const int &key)\r\n{\r\n    \r\n\r\n\tmp_current = NULL;\t\t\t   \t\t\t\t\t// No longer valid\r\n    \r\n\tLookupItem<_V> *pItem = mp_list;\r\n\tLookupItem<_V> *prev = NULL; \r\n\twhile(pItem)\r\n\t{\r\n\t\tif (pItem->m_key == key)\r\n\t\t{\r\n\t\t\tif (prev)\r\n\t\t\t\tprev->mp_next = pItem->mp_next;\r\n\t\t\telse\r\n\t\t\t\tmp_list = pItem->mp_next;\r\n\t\t\t\r\n\t\t\tif (mp_last == pItem)\r\n\t\t\t\tmp_last = prev;\r\n\t\t\t\r\n\t\t\tdelete pItem;\r\n\t\t\tm_size--;\r\n\t\t\t\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tprev = pItem;\r\n\t\tpItem = pItem->mp_next;\r\n\t}\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nvoid LookupTable<_V>::flushAllItems()\r\n{\r\n    \r\n    \r\n\tLookupItem<_V> *pItem = mp_list;\r\n\twhile(pItem)\r\n\t{\r\n\t\tLookupItem<_V> *pNext = pItem->mp_next;\r\n\t\tdelete pItem;\r\n\t\tpItem = pNext;\r\n\t}\r\n\tmp_list = NULL;\r\n\tmp_current = NULL;\t\r\n\tm_size = 0;\r\n}\r\n\r\n/*\r\nint m_size;\r\nLookupItem<_K, _V> *m_array;\r\n\r\n_K m_key;\r\n_V *mp_value;\r\n*/\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nStringLookupTable<_V>::StringLookupTable(int size) :\r\n    LookupTable<_V>(size)\r\n{\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nbool StringLookupTable<_V>::PutItem(const char *stringKey, _V *item)\r\n{\r\n    int key = Crc::GenerateCRCFromString(stringKey);\r\n    return LookupTable<_V>::PutItem(key, item);\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\n_V *StringLookupTable<_V>::GetItem(const char *stringKey)\r\n{\r\n    int key = Crc::GenerateCRCFromString(stringKey);\r\n    return LookupTable<_V>::GetItem(key);\r\n}\r\n\r\n\r\ntemplate<class _V> //inline\r\nvoid StringLookupTable<_V>::FlushItem(const char *stringKey)\r\n{\r\n    int key = Crc::GenerateCRCFromString(stringKey);\r\n    LookupTable<_V>::FlushItem(key);\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nLookupTableDestroyer<_V>::LookupTableDestroyer(LookupTable<_V> *pTable)\r\n{\r\n\tmp_table = pTable;\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> inline\r\nvoid LookupTableDestroyer<_V>::DeleteTableContents()\r\n{\r\n\tint num_items = mp_table->getSize();\r\n\t\r\n\tfor (int i = 0; i < num_items; i++)\r\n\t{\r\n\t\tint key;\r\n\t\t// since we are flushing items out of the table as we go, \r\n\t\t// we should always grab the first one\r\n\t\t_V *pItem = mp_table->GetItemByIndex(0, &key);\r\n\t\tmp_table->FlushItem(key);\r\n\t\tif (pItem) delete pItem;\r\n\t}\r\n}\r\n\r\n\r\n\r\n} // namespace Lst\r\n\r\n#endif\t// __CORE_LIST_LOOKUPTABLE_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Math/Xbox/sse.h",
    "content": "//-----------------------------------------------------------------------------\r\n// File: SSE.h\r\n//\r\n// Desc: P3 SSE conversions and estimates\r\n//\r\n// Hist: 1.7.03 - Created\r\n//\r\n// Copyright (c) Microsoft Corporation. All rights reserved.\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifndef P3_SSE\r\n#define P3_SSE\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Ftoi_ASM\r\n// Desc: SSE float to int conversion.  Note that no control word needs to be\r\n//       set to round down\r\n//-----------------------------------------------------------------------------\r\n__forceinline int Ftoi_ASM( const float f )\r\n{\r\n    __asm cvttss2si eax, f        // return int(f)\r\n}\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ReciprocalEstimate_ASM\r\n// Desc: SSE reciprocal estimate, accurate to 12 significant bits of\r\n//       the mantissa\r\n//-----------------------------------------------------------------------------\r\n__forceinline float ReciprocalEstimate_ASM( const float f )\r\n{\r\n    float rec;\r\n    __asm rcpss xmm0, f             // xmm0 = rcpss(f)\r\n    __asm movss rec , xmm0          // return xmm0\r\n    return rec;\r\n}\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ReciprocalSqrtEstimate_ASM\r\n// Desc: SSE reciprocal square root estimate, accurate to 12 significant\r\n//       bits of the mantissa\r\n//-----------------------------------------------------------------------------\r\n__forceinline float ReciprocalSqrtEstimate_ASM( const float f )\r\n{\r\n    float recsqrt;\r\n    __asm rsqrtss xmm0, f           // xmm0 = rsqrtss(f)\r\n    __asm movss recsqrt, xmm0       // return xmm0\r\n    return recsqrt;\r\n}\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: SqrtEstimae_ASM\r\n// Desc: SSE square root estimate, accurate to 12 significant bits of\r\n//       the mantissa.  Note that a check for zero must be made since\r\n//       sqrt(0) == 0 but 1/sqrt(0) = inf\r\n//-----------------------------------------------------------------------------\r\n__forceinline float SqrtEstimate_ASM( const float f )\r\n{\r\n    float recsqrt;\r\n    __asm movss xmm0,f              // xmm0 = f\r\n    __asm rsqrtss xmm1, xmm0        // xmm1 = rsqrtss(f)\r\n    __asm mulss xmm1, xmm0          // xmm1 = rsqrtss(f) * f = sqrt(f)\r\n    __asm xorps xmm2, xmm2          // xmm2 = 0\r\n    __asm cmpneqss xmm2, xmm0       // xmm2 = (f != 0 ? 1s : 0s)\r\n    __asm andps xmm1, xmm2          // xmm1 = xmm1 & xmm2 \r\n    __asm movss recsqrt, xmm1       // return xmm1\r\n    return recsqrt;\r\n}\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ReciprocalEstimateNR_ASM\r\n// Desc: SSE Newton-Raphson reciprocal estimate, accurate to 23 significant\r\n//       bits of the mantissa\r\n//       One Newtown-Raphson Iteration:\r\n//           f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)\r\n//-----------------------------------------------------------------------------\r\n__forceinline float ReciprocalEstimateNR_ASM( const float f )\r\n{\r\n    float rec;\r\n    __asm rcpss xmm0, f               // xmm0 = rcpss(f)\r\n    __asm movss xmm1, f               // xmm1 = f\r\n    __asm mulss xmm1, xmm0            // xmm1 = f * rcpss(f)\r\n    __asm mulss xmm1, xmm0            // xmm2 = f * rcpss(f) * rcpss(f)\r\n    __asm addss xmm0, xmm0            // xmm0 = 2 * rcpss(f)\r\n    __asm subss xmm0, xmm1            // xmm0 = 2 * rcpss(f) \r\n                                      //        - f * rcpss(f) * rcpss(f)\r\n    __asm movss rec, xmm0             // return xmm0\r\n    return rec;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Newton-Rapson square root iteration constants\r\n//-----------------------------------------------------------------------------\r\nconst float g_SqrtNRConst[2] = {0.5f, 3.0f};\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ReciprocalSqrtEstimateNR_ASM\r\n// Desc: SSE Newton-Raphson reciprocal square root estimate, accurate to 23\r\n//       significant bits of the mantissa\r\n//       One Newtown-Raphson Iteration:\r\n//          f(i+1) = 0.5 * rsqrtss(f) * (3.0 - (f * rsqrtss(f) * rsqrtss(f))\r\n//       NOTE: rsqrtss(f) * rsqrtss(f) != rcpss(f) (presision is not maintained)\r\n//-----------------------------------------------------------------------------\r\n__forceinline float ReciprocalSqrtEstimateNR_ASM( const float f )\r\n{\r\n    float recsqrt;\r\n    __asm rsqrtss xmm0, f             // xmm0 = rsqrtss(f)\r\n    __asm movss xmm1, f               // xmm1 = f\r\n    __asm mulss xmm1, xmm0            // xmm1 = f * rsqrtss(f)\r\n    __asm movss xmm2, g_SqrtNRConst+4 // xmm2 = 3.0f\r\n    __asm mulss xmm1, xmm0            // xmm1 = f * rsqrtss(f) * rsqrtss(f)\r\n    __asm mulss xmm0, g_SqrtNRConst   // xmm0 = 0.5f * rsqrtss(f)\r\n    __asm subss xmm2, xmm1            // xmm2 = 3.0f -\r\n                                      //  f * rsqrtss(f) * rsqrtss(f)\r\n    __asm mulss xmm0, xmm2            // xmm0 = 0.5 * rsqrtss(f)\r\n                                      //  * (3.0 - (f * rsqrtss(f) * rsqrtss(f))\r\n    __asm movss recsqrt, xmm0         // return xmm0\r\n    return recsqrt;\r\n}\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: SqrtEstimateNR_ASM\r\n// Desc: SSE Newton-Raphson square root estimate, accurate to 23 significant\r\n//       bits of the mantissa\r\n//       NOTE: x/sqrt(x) = sqrt(x)\r\n// One Newtown-Raphson Iteration (for 1/sqrt(x)) :\r\n//      f(i+1) = 0.5 * rsqrtss(f) * (3.0 - (f * rsqrtss(f) * rsqrtss(f))\r\n//      NOTE: rsqrtss(f) * rsqrtss(f) != rcpss(f) (presision is not maintained)\r\n//-----------------------------------------------------------------------------\r\n__forceinline float SqrtEstimateNR_ASM( const float f )\r\n{\r\n    float recsqrt;\r\n    __asm rsqrtss xmm0, f             // xmm0 = rsqrtss(f)\r\n    __asm movss xmm1, f               // xmm1 = f\r\n    __asm mulss xmm1, xmm0            // xmm1 = f * rsqrtss(f)\r\n    __asm movss xmm2, g_SqrtNRConst+4 // xmm2 = 3.0f\r\n    __asm mulss xmm1, xmm0            // xmm1 = f * rsqrtss(f) * rsqrtss(f)\r\n    __asm mulss xmm0, g_SqrtNRConst   // xmm0 = 0.5f * rsqrtss(f)\r\n    __asm subss xmm2, xmm1            // xmm2 = 3.0f -\r\n                                      //   f * rsqrtss(f) * rsqrtss(f)\r\n    __asm mulss xmm0, xmm2            // xmm0 = 0.5 * rsqrtss(f)\r\n                                      //  * (3.0 - (f * rsqrtss(f) * rsqrtss(f))\r\n    __asm xorps xmm1, xmm1            // xmm1 = 0\r\n    __asm mulss xmm0, f               // xmm0 = sqrt(f)\r\n    __asm cmpneqss xmm1, f            // xmm1 = (f != 0 ? 1s : 0s)\r\n    __asm andps xmm0, xmm1            // xmm0 = xmm1 & xmm2 \r\n    __asm movss recsqrt, xmm0         // return xmm0\r\n    return recsqrt;\r\n}\r\n\r\n\r\n#endif // P3_SSE\r\n"
  },
  {
    "path": "Code/Core/Math/geometry.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGeometry (MTH)\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tGeometry.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t11/14/00\t-\tMick\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMath \t\t\t\t\t\t\t\t\t**\r\n// This module handles the representation and manipulation of line segements\r\n// and planes\r\n// \r\n// a line segment (Mth::Line) is defined by two points, m_start and m_end\r\n//\r\n// a plane is defined by a point and a normal\r\n\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n\r\n#include <gfx/debuggfx.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mth\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nLine::Line()\r\n{\r\n}\r\n\r\nLine::Line ( const Vector &start, const Vector &end )\t\t\t\r\n{\r\n\t\tm_start = start;\r\n\t\tm_end = end;\r\n}\r\n\r\nPlane::Plane()\r\n{\r\n} \r\n \r\nPlane::Plane (const Vector &point, const Vector &normal)\r\n{\r\n\t\tm_point = point;\r\n\t\tm_normal = normal;\r\n}\t\t\r\n\r\nRectangle::Rectangle()\r\n{\r\n}\r\n\r\nRectangle::Rectangle ( const Vector& corner, const Vector& first_edge, const Vector& second_edge )\r\n{\r\n\tm_corner = corner;\r\n\tm_first_edge = first_edge;\r\n\tm_second_edge = second_edge;\r\n}\r\n\r\n/*\r\n   Calculate the line segment PaPb that is the shortest route between\r\n   two lines P1P2 and P3P4. Calculate also the values of mua and mub where\r\n      Pa = P1 + mua (P2 - P1)\r\n      Pb = P3 + mub (P4 - P3)\r\n   Return FALSE if no solution exists.\r\n   original algorithm from  http://www.swin.edu.au/astronomy/pbourke/geometry/lineline3d/\r\n   note that I (Mick) modified it to clamp the points to within the line segments\r\n   if you remove the \"Clamp\" calls below, then the lines will be assumed to be\r\n   of infinite length \r\n*/\r\n\r\n#define EPS  0.00001f\r\n\r\nbool LineLineIntersect( Line & l1, Line & l2, Vector *pa, Vector *pb, float *mua, float *mub, bool clamp )\r\n{\r\n\r\n\tVector &p1 = l1.m_start;\r\n\tVector &p2 = l1.m_end;\r\n\tVector &p3 = l2.m_start;\r\n\tVector &p4 = l2.m_end;\r\n   \r\n\tVector p13,p43,p21;\r\n\t  \r\n\tfloat d1343,d4321,d1321,d4343,d2121;\r\n\tfloat numer,denom;\r\n\t\r\n\tp13 = p1 - p3;\r\n\tp43 = p4 - p3;\r\n\t\r\n\tif (Abs(p43[X])  < EPS && Abs(p43[Y])  < EPS && Abs(p43[Z])  < EPS)\r\n\t  return(false);\r\n\t\r\n\tp21 = p2 - p1;  \r\n\t\t  \r\n\tif (Abs(p21[X])  < EPS && Abs(p21[Y])  < EPS && Abs(p21[Z])  < EPS)\r\n\t  return(false);\r\n\r\n\td1343 = DotProduct(p13,p43);\r\n\td4321 = DotProduct(p43,p21);\r\n\td1321 = DotProduct(p13,p21);\r\n\td4343 = DotProduct(p43,p43);\r\n\td2121 = DotProduct(p21,p21);\r\n\t\r\n\tdenom = d2121 * d4343 - d4321 * d4321;\r\n\tif (Abs(denom) < EPS)\r\n\t  return(false);\r\n\tnumer = d1343 * d4321 - d1321 * d4343;\r\n\t\r\n\t*mua = numer / denom;\r\n\tif( clamp )\r\n\t{\r\n\t\t*mua = Clamp(*mua,0.0f,1.0f);\r\n\t}\r\n\t*mub = (d1343 + d4321 * (*mua)) / d4343;\r\n\r\n\tif( clamp )\r\n\t{\r\n\t\t*mub = Clamp(*mub,0.0f,1.0f);\r\n\t}\r\n\t\r\n\t*pa = p1 + (*mua * p21);     \r\n\t*pb = p3 + (*mub * p43);     \r\n\t\r\n\treturn(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBBox::CBBox()\r\n{\r\n\tReset();\r\n}\r\n\r\nCBBox::CBBox(const Vector &point)   \r\n{\r\n\tSet(point, point);\r\n}\r\n\r\nCBBox::CBBox(const Vector &min, const Vector &max)\t\t\t\r\n{\r\n\tSet(min, max);\r\n}\r\n\r\nvoid CBBox::AddPoint(const Vector &point)   \r\n{\r\n\t// Adjust min/max points\r\n\tif (point[X] < m_min[X])\r\n\t\tm_min[X] = point[X];\r\n\tif (point[Y] < m_min[Y])\r\n\t\tm_min[Y] = point[Y];\r\n\tif (point[Z] < m_min[Z])\r\n\t\tm_min[Z] = point[Z];\r\n\r\n\tif (point[X] > m_max[X])\r\n\t\tm_max[X] = point[X];\r\n\tif (point[Y] > m_max[Y])\r\n\t\tm_max[Y] = point[Y];\r\n\tif (point[Z] > m_max[Z])\r\n\t\tm_max[Z] = point[Z];\r\n}\r\n\r\n// Returns number of axes within and flags for which ones\r\nint CBBox::WithinAxes(const Vector &point, uint32 &axis_flags) const\r\n{\r\n\tint number_of_axes = 0;\r\n\taxis_flags = 0;\r\n\r\n\tif ((point[X] >= m_min[X]) && (point[X] <= m_max[X]))\r\n\t{\r\n\t\tnumber_of_axes++;\r\n\t\taxis_flags |= 1 << X;\r\n\t}\r\n\r\n\tif ((point[Y] >= m_min[Y]) && (point[Y] <= m_max[Y]))\r\n\t{\r\n\t\tnumber_of_axes++;\r\n\t\taxis_flags |= 1 << Y;\r\n\t}\r\n\r\n\tif ((point[Z] >= m_min[Z]) && (point[Z] <= m_max[Z]))\r\n\t{\r\n\t\tnumber_of_axes++;\r\n\t\taxis_flags |= 1 << Z;\r\n\t}\r\n\r\n\treturn number_of_axes;\r\n}\r\n\r\nvoid CBBox::DebugRender(uint32 rgba, int frames) const\r\n{\r\n\t// Min YZ square\r\n\tGfx::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);\r\n\tGfx::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);\r\n\tGfx::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);\r\n\tGfx::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);\r\n\r\n\t// Max YZ square\r\n\tGfx::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);\r\n\tGfx::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);\r\n\tGfx::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);\r\n\tGfx::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);\r\n\r\n\t// lines joining corners\r\n\tGfx::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);\r\n\tGfx::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);\r\n\tGfx::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);\r\n\tGfx::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);\r\n}\r\n\r\nvoid CBBox::DebugRender(const Mth::Matrix & transform, uint32 rgba, int frames) const\r\n{\r\n\tuint32 rgba_min = 0xFF000080;\r\n\tuint32 rgba_max = 0x0000FF80;\r\n\r\n\tMth::Vector min_yz_1(m_min[X], m_min[Y], m_min[Z]);\r\n\tMth::Vector min_yz_2(m_min[X], m_min[Y], m_max[Z]);\r\n\tMth::Vector min_yz_3(m_min[X], m_max[Y], m_max[Z]);\r\n\tMth::Vector min_yz_4(m_min[X], m_max[Y], m_min[Z]);\r\n\r\n\tMth::Vector max_yz_1(m_max[X], m_min[Y], m_min[Z]);\r\n\tMth::Vector max_yz_2(m_max[X], m_min[Y], m_max[Z]);\r\n\tMth::Vector max_yz_3(m_max[X], m_max[Y], m_max[Z]);\r\n\tMth::Vector max_yz_4(m_max[X], m_max[Y], m_min[Z]);\r\n\r\n\t// Transform\r\n\tmin_yz_1 = transform.Transform(min_yz_1);\r\n\tmin_yz_2 = transform.Transform(min_yz_2);\r\n\tmin_yz_3 = transform.Transform(min_yz_3);\r\n\tmin_yz_4 = transform.Transform(min_yz_4);\r\n\r\n\tmax_yz_1 = transform.Transform(max_yz_1);\r\n\tmax_yz_2 = transform.Transform(max_yz_2);\r\n\tmax_yz_3 = transform.Transform(max_yz_3);\r\n\tmax_yz_4 = transform.Transform(max_yz_4);\r\n\r\n\t// Min YZ square\r\n\tGfx::AddDebugLine(min_yz_1, min_yz_2,rgba_min,rgba_min,frames);\r\n\tGfx::AddDebugLine(min_yz_2, min_yz_3,rgba_min,rgba_min,frames);\r\n\tGfx::AddDebugLine(min_yz_3, min_yz_4,rgba_min,rgba_min,frames);\r\n\tGfx::AddDebugLine(min_yz_4, min_yz_1,rgba_min,rgba_min,frames);\r\n\r\n\t// Max YZ square\r\n\tGfx::AddDebugLine(max_yz_1, max_yz_2,rgba_max,rgba_max,frames);\r\n\tGfx::AddDebugLine(max_yz_2, max_yz_3,rgba_max,rgba_max,frames);\r\n\tGfx::AddDebugLine(max_yz_3, max_yz_4,rgba_max,rgba_max,frames);\r\n\tGfx::AddDebugLine(max_yz_4, max_yz_1,rgba_max,rgba_max,frames);\r\n\r\n\t// lines joining corners\r\n\tGfx::AddDebugLine(min_yz_1, max_yz_1,rgba,rgba,frames);\r\n\tGfx::AddDebugLine(min_yz_2, max_yz_2,rgba,rgba,frames);\r\n\tGfx::AddDebugLine(min_yz_3, max_yz_3,rgba,rgba,frames);\r\n\tGfx::AddDebugLine(min_yz_4, max_yz_4,rgba,rgba,frames);\r\n}\r\n\r\nbool CBBox::LineIntersect( const Mth::Line &line, Mth::Vector &point, Mth::Vector &normal ) const\r\n{\r\n\tbool start_point_within = Within(line.m_start);\r\n\tbool end_point_within = Within(line.m_end);\r\n\r\n\t// Doesn't intersect side if both points within\r\n\tif (start_point_within && end_point_within)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Trivial rejection.\r\n\tif ((line.m_start[Y] > m_max[Y]) && (line.m_end[Y] > m_max[Y])) return false;\r\n\tif ((line.m_start[Y] < m_min[Y]) && (line.m_end[Y] < m_min[Y])) return false;\r\n\tif ((line.m_start[X] > m_max[X]) && (line.m_end[X] > m_max[X])) return false;\r\n\tif ((line.m_start[X] < m_min[X]) && (line.m_end[X] < m_min[X])) return false;\r\n\tif ((line.m_start[Z] > m_max[Z]) && (line.m_end[Z] > m_max[Z])) return false;\r\n\tif ((line.m_start[Z] < m_min[Z]) && (line.m_end[Z] < m_min[Z])) return false;\r\n\r\n\tfloat dx = line.m_end[X] - line.m_start[X];\r\n\tfloat dy = line.m_end[Y] - line.m_start[Y];\r\n\tfloat dz = line.m_end[Z] - line.m_start[Z];\r\n\t\r\n\t// avoid divide by zeros.\r\n\tif ( !dx )\r\n\t{\r\n\t\tdx = ( 0.000001f );\r\n\t}\r\n\tif ( !dy )\r\n\t{\r\n\t\tdy = ( 0.000001f );\r\n\t}\r\n\tif ( !dz )\r\n\t{\r\n\t\tdz = ( 0.000001f );\r\n\t}\r\n\r\n\t//\r\n\t// Garrett: I back-face cull 3 of the sides to reduce the calculations and keep\r\n\t// the collisions down to one side.\r\n\r\n\t// Check the max-x face.\r\n\tif (line.m_start[X] > m_max[X] && line.m_end[X] < m_max[X] && (dx < 0.0f))\r\n\t{\r\n\t\t// It crosses the plane of the face, so calculate the y & z coords\r\n\t\t// of the intersection and see if they are in the face,\r\n\t\tfloat d=m_max[X] - line.m_start[X];\r\n\t\tfloat y=d*dy/dx + line.m_start[Y];\r\n\t\tfloat z=d*dz/dx + line.m_start[Z];\r\n\t\tif (y < m_max[Y] && y > m_min[Y] && z < m_max[Z] && z > m_min[Z])\r\n\t\t{\r\n\t\t\t// It does collide!\r\n\t\t\tpoint = Mth::Vector(m_max[X], y, z, 1.0f);\r\n\t\t\tnormal = Mth::Vector(1.0f, 0.0f, 0.0f, 0.0f);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Check the min-x face.\r\n\tif (line.m_start[X] < m_min[X] && line.m_end[X] > m_min[X] && (dx > 0.0f))\r\n\t{\r\n\t\t// It crosses the plane of the face, so calculate the y & z coords\r\n\t\t// of the intersection and see if they are in the face,\r\n\t\tfloat d=m_min[X] - line.m_start[X];\r\n\t\tfloat y=d*dy/dx + line.m_start[Y];\r\n\t\tfloat z=d*dz/dx + line.m_start[Z];\r\n\t\tif (y < m_max[Y] && y > m_min[Y] && z < m_max[Z] && z > m_min[Z])\r\n\t\t{\r\n\t\t\t// It does collide!\r\n\t\t\tpoint = Mth::Vector(m_min[X], y, z, 1.0f);\r\n\t\t\tnormal = Mth::Vector(-1.0f, 0.0f, 0.0f, 0.0f);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Check the max-y face.\r\n\tif (line.m_start[Y] > m_max[Y] && line.m_end[Y] < m_max[Y] && (dy < 0.0f))\r\n\t{\r\n\t\t// It crosses the plane of the face, so calculate the x & z coords\r\n\t\t// of the intersection and see if they are in the face,\r\n\t\tfloat d=m_max[Y] - line.m_start[Y];\r\n\t\tfloat x=d*dx/dy + line.m_start[X];\r\n\t\tfloat z=d*dz/dy + line.m_start[Z];\r\n\t\tif (x < m_max[X] && x > m_min[X] && z < m_max[Z] && z > m_min[Z])\r\n\t\t{\r\n\t\t\t// It does collide!\r\n\t\t\tpoint = Mth::Vector(x, m_max[Y], z, 1.0f);\r\n\t\t\tnormal = Mth::Vector(0.0f, 1.0f, 0.0f, 0.0f);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Check the min-y face.\r\n\tif (line.m_start[Y] < m_min[Y] && line.m_end[Y] > m_min[Y] && (dy > 0.0f))\r\n\t{\r\n\t\t// It crosses the plane of the face, so calculate the x & z coords\r\n\t\t// of the intersection and see if they are in the face,\r\n\t\tfloat d=m_min[Y] - line.m_start[Y];\r\n\t\tfloat x=d*dx/dy + line.m_start[X];\r\n\t\tfloat z=d*dz/dy + line.m_start[Z];\r\n\t\tif (x < m_max[X] && x > m_min[X] && z < m_max[Z] && z > m_min[Z])\r\n\t\t{\r\n\t\t\t// It does collide!\r\n\t\t\tpoint = Mth::Vector(x, m_min[Y], z, 1.0f);\r\n\t\t\tnormal = Mth::Vector(0.0f, -1.0f, 0.0f, 0.0f);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Check the max-z face.\r\n\tif (line.m_start[Z] > m_max[Z] && line.m_end[Z] < m_max[Z] && (dz < 0.0f))\r\n\t{\r\n\t\t// It crosses the plane of the face, so calculate the x & y coords\r\n\t\t// of the intersection and see if they are in the face,\r\n\t\tfloat d=m_max[Z] - line.m_start[Z];\r\n\t\tfloat x=d*dx/dz + line.m_start[X];\r\n\t\tfloat y=d*dy/dz + line.m_start[Y];\r\n\t\tif (x < m_max[X] && x > m_min[X] && y < m_max[Y] && y > m_min[Y])\r\n\t\t{\r\n\t\t\t// It does collide!\r\n\t\t\tpoint = Mth::Vector(x, y, m_max[Z], 1.0f);\r\n\t\t\tnormal = Mth::Vector(0.0f, 0.0f, 1.0f, 0.0f);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t// Check the min-z face.\r\n\tif (line.m_start[Z] < m_min[Z] && line.m_end[Z] > m_min[Z] && (dz > 0.0f))\r\n\t{\r\n\t\t// It crosses the plane of the face, so calculate the x & y coords\r\n\t\t// of the intersection and see if they are in the face,\r\n\t\tfloat d=m_min[Z] - line.m_start[Z];\r\n\t\tfloat x=d*dx/dz + line.m_start[X];\r\n\t\tfloat y=d*dy/dz + line.m_start[Y];\r\n\t\tif (x < m_max[X] && x > m_min[X] && y < m_max[Y] && y > m_min[Y])\r\n\t\t{\r\n\t\t\t// It does collide!\r\n\t\t\tpoint = Mth::Vector(x, y, m_min[Z], 1.0f);\r\n\t\t\tnormal = Mth::Vector(0.0f, 0.0f, -1.0f, 0.0f);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid CBBox::GetClosestIntersectPoint(const Mth::Vector &pos, Mth::Vector &point) const\r\n{\r\n\tuint32 axes_within_flags;\r\n\tint axes_within = WithinAxes(pos, axes_within_flags);\r\n\r\n\tif (axes_within == 3)\r\n\t{\r\n\t\tfloat closest_dist = -1.0f;\r\n\t\tint closest_axis = -1;\r\n\t\tfloat closest_axis_coord = 0.0f;\t\t// Value of the minimum axis coordinate\r\n\r\n\t\t// Find the closest rectangle and move the point to that rectangle to find the intersection\r\n\t\t// point.\r\n\t\tfor (int axis = X; axis <= Z; axis++)\r\n\t\t{\r\n\t\t\tfloat min_to_pos_dist = pos[axis] - m_min[axis];\r\n\t\t\tfloat max_to_pos_dist = m_max[axis] - pos[axis];\r\n\r\n\t\t\tDbg_Assert(min_to_pos_dist >= 0.0f);\r\n\t\t\tDbg_Assert(max_to_pos_dist >= 0.0f);\r\n\r\n\t\t\tfloat min_dist;\r\n\t\t\tfloat min_coord;\r\n\r\n\t\t\t// Figure out the closest distance\r\n\t\t\tif (min_to_pos_dist < max_to_pos_dist)\r\n\t\t\t{\r\n\t\t\t\tmin_dist = min_to_pos_dist;\r\n\t\t\t\tmin_coord = m_min[axis];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmin_dist = max_to_pos_dist;\r\n\t\t\t\tmin_coord = m_max[axis];\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// See if this is the first axis or if this one is closer\r\n\t\t\tif ((axis == X) || (min_dist < closest_dist))\r\n\t\t\t{\r\n\t\t\t\tclosest_axis = axis;\r\n\t\t\t\tclosest_dist = min_dist;\r\n\t\t\t\tclosest_axis_coord = min_coord;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tDbg_Assert((closest_axis >= X) && (closest_axis <= Z));\r\n\t\tDbg_Assert(closest_dist >= 0.0f);\r\n\r\n\t\t// Calc the intersection point\r\n\t\tpoint = pos;\t\t\t\t// Start with position\r\n\t\tpoint[closest_axis] = closest_axis_coord;\r\n\r\n#if 0\r\n\t\tstatic int print_now;\r\n\t\tif ((print_now++ % 60) == 0)\r\n\t\t{\r\n\t\t\tDbg_Message(\"Closest axis %d, (min - max) pos (%f - %f) %f, closest dist %f, closest coord %f\", closest_axis,\r\n\t\t\t\t\t\tm_min[closest_axis], m_max[closest_axis], pos[closest_axis], closest_dist, closest_axis_coord);\r\n\t\t}\r\n#endif\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpoint[W] = 1.0f;\t\t\t// Homogeneous\r\n\r\n\t\t// Go through each axis.  If the pos coordinate is between the min and max, use that\r\n\t\t// coordinate.  Otherwise, use the min or max coordinate that is closest.\r\n\t\tfor (int axis = X; axis <= Z; axis++)\r\n\t\t{\r\n\t\t\tif (axes_within_flags & (1 << axis))\r\n\t\t\t{\r\n\t\t\t\t// Within, use pos coord\r\n\t\t\t\tpoint[axis] = pos[axis];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Figure out which end we need\r\n\t\t\t\tif (pos[axis] <= m_min[axis])\r\n\t\t\t\t{\r\n\t\t\t\t\tpoint[axis] = m_min[axis];\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpoint[axis] = m_max[axis];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n}\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Math/geometry.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (MTH)\t\t\t   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/math/geometry.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t11/29/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tVector Math Class\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_MATH_GEOMETRY_H\r\n#define __CORE_MATH_GEOMETRY_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/math.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Mth\r\n{\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/****************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n * Class:\t\t\tVector\r\n *\r\n * Description:\t\tVector math class\r\n *\r\n ****************************************************************************/\r\n\r\nclass Plane;\r\n\r\nclass  Line\r\n{\r\n\t\r\n\t\r\n\tfriend class Plane;\r\n\r\npublic:\r\n\r\n\t\t\tLine();\r\n\t\t\tLine ( const Vector &start, const Vector &end );\t\t\t\r\n//        \tLine&\t\t\toperator+=\t( const Vector& v );\t\t\t\r\n\r\n\t\t\tinline void\t\t\tMirrorAboutStart();\r\n\t\t\tinline void\t\t\tFlipDirection();\r\n\r\n\t\t\tbool\t\t\toperator==  ( const Line& l ) const;\r\n\t\t\tbool\t\t\toperator!=  ( const Line& l ) const;\r\n        \tLine&\t\t\toperator+=\t( const Vector& v );\r\n        \tLine&\t\t\toperator-=\t( const Vector& v );\r\n\r\n\t\t\tfloat\t\t\tLength() const {return (m_end-m_start).Length();}\t\t\t\r\n\t\t\t\r\n\t\t\tVector m_start, m_end;\r\nprivate:\r\n};\r\n\r\n\r\nclass  Plane\r\n{\r\n\t\r\n\t\r\n\tfriend class Line;\r\n\r\npublic:\r\n\t\tPlane();\r\n\t\tPlane (const Vector &point, const Vector &normal);\r\n\t\tVector\tm_point, m_normal;\r\nprivate: \r\n};\r\n\r\nclass\tRectangle\r\n{\r\npublic:\r\n\t\tRectangle (   );\r\n\t\tRectangle ( const Vector& corner, const Vector& first_edge, const Vector& second_edge );\r\n\t\tVector m_corner, m_first_edge, m_second_edge;\r\nprivate:\r\n};\r\n\r\n\r\n/****************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n * Class:\t\t\tCBBox\r\n *\r\n * Description:\t\tAxis-aligned Bounding Box\r\n *\r\n ****************************************************************************/\r\n\r\nclass CBBox\r\n{\r\npublic:\r\n\t// Constructors\r\n\tCBBox();\r\n\tCBBox(const Vector &point);\r\n\tCBBox(const Vector &min, const Vector &max);\r\n\r\n\t//\r\n\tinline void Set(const Vector &min, const Vector &max);\r\n\tinline void Reset();\r\n\r\n    //\r\n    inline const Vector &GetMin() const;\r\n    inline const Vector &GetMax() const;\r\n    inline void SetMin(const Vector &min);\r\n    inline void SetMax(const Vector &max);\r\n\r\n\t//\r\n\tvoid AddPoint(const Vector &point);\r\n\tinline bool Intersect(const CBBox &bbox) const;\r\n\tinline bool CouldIntersect(const Vector &v0, const Vector &v1, const Vector &v2) const;\t// Intersect w/ triangle\r\n\tinline bool Within(const Vector &point) const;\r\n\tinline bool Within(const CBBox &bbox) const;\r\n\tint WithinAxes(const Vector &point, uint32 &axis_flags) const;\t\t// Returns number of axes within and flags for which ones\r\n\r\n\t// Checks to see if the line intersects any of the sides\r\n\tbool LineIntersect( const Mth::Line &line, Mth::Vector &point, Mth::Vector &normal ) const;\r\n\r\n\t// Finds the closest point on the bounding box to a position\r\n\tvoid GetClosestIntersectPoint(const Mth::Vector &pos, Mth::Vector &point) const;\r\n\r\n\tvoid DebugRender(uint32 rgba, int frames = 0) const;\r\n\tvoid DebugRender(const Mth::Matrix & transform, uint32 rgba, int frames = 0) const;\r\n\r\nprivate:\r\n\t//\r\n\tVector m_min, m_max;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool LineLineIntersect( Line & l1, Line & l2, Vector *pa, Vector *pb, float *mua, float *mub, bool clamp = true );\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\t\tLine::operator== ( const Line& l ) const\r\n{\t\r\n\t\r\n\r\n\treturn  ( m_start == l.m_start) && ( m_end == l.m_end );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\t\tLine::operator!= ( const Line& l ) const\r\n{\t\r\n\t\r\n\r\n\treturn !( *this == l );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Line&\t\tLine::operator+= ( const Vector& v )\r\n{\r\n\t\r\n\r\n\tm_start += v;\r\n\tm_end += v;\t\t\r\n\t\r\n\treturn *this;\r\n}\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Line&\t\tLine::operator-= ( const Vector& v )\r\n{\r\n\t\r\n\r\n\tm_start -= v;\r\n\tm_end -= v;\t\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n\r\n\r\n// A->B becomes B<-A, where A is unchanged\r\ninline void  Line::MirrorAboutStart()\r\n{\r\n\tm_end = m_start - 2.0f * ( m_end - m_start );\t\r\n}\r\n\r\n// A->B becores B->A  (A and B swap positions)\r\ninline void Line::FlipDirection()\r\n{\r\n\tMth::Vector temp = m_end;\r\n\tm_end = m_start;\r\n\tm_start = temp;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CBBox::Reset()   \r\n{\r\n//\tm_min = Vector( (float)HUGE_VAL,  (float)HUGE_VAL,  (float)HUGE_VAL);\r\n//\tm_max = Vector((float)-HUGE_VAL, (float)-HUGE_VAL, (float)-HUGE_VAL);\r\n\tm_min = Vector( 10000000.0f,  10000000.0f,  10000000.0f);\r\n\tm_max = Vector(-10000000.0f, -10000000.0f, -10000000.0f);\r\n}\r\n\r\ninline void CBBox::Set(const Vector &min, const Vector &max)\t\t\t\r\n{\r\n\tm_min = min;\r\n\tm_max = max;\r\n}\r\n\r\ninline const Vector &CBBox::GetMin() const\r\n{ \r\n\treturn m_min;\r\n}\r\n\r\ninline const Vector &CBBox::GetMax() const\r\n{ \r\n\treturn m_max;\r\n}\r\n\r\ninline void CBBox::SetMin(const Vector &min)\r\n{\r\n\tm_min = min;\r\n}\r\n\r\ninline void CBBox::SetMax(const Vector &max)\r\n{\r\n\tm_max = max;\r\n}\r\n\r\n// for intersection test, we do X and Z first, \r\n// as we war aer more likely to be intersecting in the Y\r\n// as everyhting is about the same height\r\n// so this eliminates thigns quicker\r\ninline bool CBBox::Intersect(const CBBox &bbox) const\r\n{\r\n\tif ((m_min[X] > bbox.m_max[X]) || (bbox.m_min[X] > m_max[X]) ||\r\n\t\t(m_min[Z] > bbox.m_max[Z]) || (bbox.m_min[Z] > m_max[Z]) ||\r\n\t\t(m_min[Y] > bbox.m_max[Y]) || (bbox.m_min[Y] > m_max[Y]))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\ninline bool CBBox::Within(const Vector &point) const\r\n{\r\n\treturn ((point[X] >= m_min[X]) && (point[Y] >= m_min[Y]) && (point[Z] >= m_min[Z]) &&\r\n\t\t\t(point[X] <= m_max[X]) && (point[Y] <= m_max[Y]) && (point[Z] <= m_max[Z]));\r\n}\r\n\r\ninline bool CBBox::Within(const CBBox &bbox) const\r\n{\r\n\tif ((bbox.m_min[X] >= m_min[X]) && (bbox.m_max[X] <= m_max[X]) &&\r\n\t\t(bbox.m_min[Y] >= m_min[Y]) && (bbox.m_max[Y] <= m_max[Y]) &&\r\n\t\t(bbox.m_min[Z] >= m_min[Z]) && (bbox.m_max[Z] <= m_max[Z]))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n// Not So Quick & Dirty Intersection w/ Triangle\r\ninline bool CBBox::CouldIntersect(const Vector &v0, const Vector &v1, const Vector &v2) const\r\n{\r\n\tif ( ( v0[X] > m_max[X] ) &&\r\n\t\t ( v1[X] > m_max[X] ) &&\r\n\t\t ( v2[X] > m_max[X] ) ) return false;\r\n\tif ( ( v0[X] < m_min[X] ) &&\r\n\t\t ( v1[X] < m_min[X] ) &&\r\n\t\t ( v2[X] < m_min[X] ) ) return false;\r\n\tif ( ( v0[Y] > m_max[Y] ) &&\r\n\t\t ( v1[Y] > m_max[Y] ) &&\r\n\t\t ( v2[Y] > m_max[Y] ) ) return false;\r\n\tif ( ( v0[Y] < m_min[Y] ) &&\r\n\t\t ( v1[Y] < m_min[Y] ) &&\r\n\t\t ( v2[Y] < m_min[Y] ) ) return false;\r\n\tif ( ( v0[Z] > m_max[Z] ) &&\r\n\t\t ( v1[Z] > m_max[Z] ) &&\r\n\t\t ( v2[Z] > m_max[Z] ) ) return false;\r\n\tif ( ( v0[Z] < m_min[Z] ) &&\r\n\t\t ( v1[Z] < m_min[Z] ) &&\r\n\t\t ( v2[Z] < m_min[Z] ) ) return false;\r\n\r\n\treturn true;\r\n\r\n}\r\n\r\n} // namespace Mth\r\n\r\n#endif // __CORE_MATH_GEOMETRY_H\r\n\r\n"
  },
  {
    "path": "Code/Core/Math/math.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (MTH)\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmath.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t11/24/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMath Library code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#ifdef __PLAT_WN32__\r\n#include <math.h>\r\n#endif\r\n#ifdef __PLAT_XBOX__\r\n#include <math.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/math/math.h>\r\n\r\n#if DEBUGGING_REPLAY_RND\r\n\r\n#include <sys\\timer.h>\r\n\r\n#include <string.h>\r\n\r\nextern int *gReplayTestRndLine;\r\nextern uint64 *gReplayTestRndFunc;\r\nstatic int gRndIndex = 0;\r\nstatic int gTestMode = 0;\r\n#define MAX_RND_TEST_INDEX  3666\r\n#endif\r\n\r\n\r\n\r\nnamespace Mth\r\n{\r\n\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic int RandSeed;\r\nstatic int RandA;\r\nstatic int RandB;\r\n\r\nstatic int RandSeed2;\r\nstatic int RandC;\r\nstatic int RandD;\r\n\r\nvoid InitialRand(int a)\r\n{\r\n   RandSeed = a;\r\n   RandA = 314159265;\r\n   RandB = 178453311;\r\n   RandSeed2 = a;\r\n   RandC = 314159265;\r\n   RandD = 178453311;\r\n}\r\n\r\n#if DEBUGGING_REPLAY_RND\r\n\r\nstatic bool gFuckedUp = false;\r\n\r\nbool RndFuckedUp( void )\r\n{\r\n\tif ( gTestMode != 2 )\r\n\t\treturn ( false );\r\n\treturn ( gFuckedUp );\r\n}\r\n\r\nint Rnd_DbgVersion(int n, int line, char *file)\r\n{\r\n\t\r\n\tif ( gRndIndex < MAX_RND_TEST_INDEX )\r\n\t{\r\n\t\tif ( gTestMode == 1 )\r\n\t\t{\r\n\t\t\t// record:\r\n\t\t\tgReplayTestRndLine[ gRndIndex ] = line;\r\n\t\t\tstrncpy( ( char * )( &gReplayTestRndFunc[ gRndIndex ] ), file, 8 );\r\n\t\t\tgRndIndex++;\r\n\t\t}\r\n\t\telse if ( gTestMode == 2 )\r\n\t\t{\r\n\t\t\t// compare:\r\n\t\t\tif ( line != gReplayTestRndLine[ gRndIndex ] )\r\n\t\t\t{\r\n\t\t\t\tchar temp[ 9 ];\r\n\t\t\t\tstrncpy( temp, ( char * )( &gReplayTestRndFunc[ gRndIndex ] ), 8 );\r\n\t\t\t\ttemp[ 8 ] = '\\0';\r\n\t\t\t\tDbg_Message( \"********Rnd Fuckup!********* num %d time %d\\ncurrent line %d file %s conflicts with prev line %d file %s\",\r\n\t\t\t\t\tTmr::GetTime( ), gRndIndex, line, file, gReplayTestRndLine[ gRndIndex ], temp );\r\n\t\t\t\tgFuckedUp = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tgFuckedUp = false;\r\n\t\t\t}\r\n\t\t\tgRndIndex++;\r\n\t\t}\r\n\t}\r\n\tRandSeed=RandSeed*RandA+RandB;\r\n\tRandA = (RandA ^ RandSeed) + (RandSeed>>4);\r\n\tRandB += (RandSeed>>3) - 0x10101010L;\r\n\treturn (int)((RandSeed&0xffff) * n)>>16;\r\n}\r\n\r\nvoid SetRndTestMode( int mode )\r\n{\r\n\tgTestMode = mode;\r\n\tgRndIndex = 0;\r\n}\r\n\r\n#else\r\nint Rnd(int n)\r\n{\r\n   RandSeed=RandSeed*RandA+RandB;\r\n   RandA = (RandA ^ RandSeed) + (RandSeed>>4);\r\n   RandB += (RandSeed>>3) - 0x10101010L;\r\n   return (int)((RandSeed&0xffff) * n)>>16;\r\n}\r\n#endif\r\n\r\nint Rnd2(int n)\r\n{\r\n   RandSeed2=RandSeed2*RandC+RandD;\r\n   RandC = (RandC ^ RandSeed2) + (RandSeed2>>4);\r\n   RandD += (RandSeed2>>3) - 0x10101010L;\r\n   return (int)((RandSeed2&0xffff) * n)>>16;\r\n}\r\n\r\n// Return a random number in the range +/- n\r\nfloat PlusOrMinus(float n)\r\n{\r\n\tfloat range = (float)(Rnd(10000));\r\n\trange -= 5000.0f;\r\n\treturn n * range / 5000.0f;\r\n}\r\n\r\n#if 0\r\n// 8192 makes Kensinf and sinf match to all 6 decimal places, (when x is in the range -2pi to 2pi)\r\n// apart from very occassionally where there might be a .000001 difference.\r\n// The table size must be a power of two.\r\n#define SINF_NUM_DIVISIONS 8192\r\nstatic float pSinLookup[SINF_NUM_DIVISIONS+5]; // +5 for good measure, since sometimes we look one beyond the end.\r\nvoid InitSinLookupTable()\r\n{\r\n\t// The lookup table covers a whole period (0 to 2pi) of the sin function.\r\n\t// This saves a few if's in the sin function.\r\n\tfor (int i=0; i<SINF_NUM_DIVISIONS+5; ++i)\r\n\t{\r\n\t\tpSinLookup[i]=sinf(i*2.0f*3.141592654f/SINF_NUM_DIVISIONS); // Mth::PI won't compile for some reason??\r\n\t}\r\n}\r\n\r\n\r\nfloat Kensinf(float x)\r\n{\r\n\t// Get the index into the table as a floating point value. This value may be negative\r\n\t// or out of bounds of the array, but don't worry about that yet.\r\n\tfloat r=(x*(SINF_NUM_DIVISIONS/2))/3.141592654f;\r\n\t// Get the integer part.\r\n\tint i=(int)r;\r\n\t// Make r be the fractional part, so that r is a value between 0 and 1 (or 0 and -1) \r\n\t// that indicates how far we are between the two adjacent entries in the table.\r\n\tr-=i;\r\n\t\r\n\t// Make i be in range, which can be done with an integer 'and' because the table size\r\n\t// is chosen to be a power of two.\r\n\t// Note that this still works the way we want it to if i is negative.\r\n\t// If i is a certain distance below 0, anding it will map it to that distance below the\r\n\t// end of the table, which is what we want because the lookup table covers a whole\r\n\t// period of the sine function.\r\n\t// (Generally, -x & (n-1) is n-x when n is a power of 2, eg -3&7 = 5 = (8-3) )\r\n\ti&=(SINF_NUM_DIVISIONS-1);\r\n\t\r\n\tfloat *pPoo=pSinLookup+i;\r\n\t\r\n\t// Hmmm, the following is technically wrong, it should be -- not ++ for when x is negative.\r\n\t// However, always using ++ does not appear to affect the accuracy at all, so there's no need to fix it!\r\n\t// Doing a -- for when x is negative would mean having to do another if, and yet another to\r\n\t// check in case pPoo points to the first element, yuk.\r\n\t// Using ++ even when x is negative works because the gradient does not change\r\n\t// much between points. When x is negative, r will be negative, and using the next gradient\r\n\t// to move back gives roughly the same answer as using the previous gradient. Wahay!!\r\n\tfloat a=*pPoo++;\r\n\tfloat b=*pPoo;\r\n\treturn a+(b-a)*r;\r\n}\r\n\r\nfloat Kencosf(float x)\r\n{\r\n\tfloat r=(x*(SINF_NUM_DIVISIONS/2))/3.141592654f;\r\n\tint i=(int)r;\r\n\tr-=i;\r\n\r\n\t// This is the only difference from Kensinf.\r\n\ti+=(SINF_NUM_DIVISIONS/4); // Add a quarter period.\r\n\t\r\n\ti&=(SINF_NUM_DIVISIONS-1);\r\n\t\r\n\tfloat *pPoo=pSinLookup+i;\r\n\t\r\n\tfloat a=*pPoo++;\r\n\tfloat b=*pPoo;\r\n\treturn a+(b-a)*r;\r\n\t/*\r\n    float sqr = x*x;\r\n    float result = 0.03705f;\r\n    result *= sqr;\r\n    result -= 0.4967;\r\n    result *= sqr;\r\n    result += 1.0f;\r\n    return result;\r\n\t*/\r\n}\r\n#endif\r\n\r\nfloat Kenacosf(float x)\r\n{\r\n\t// Got this formula off the internet, forgot where though ...\r\n\tif (x<0.0f)\r\n\t{\r\n\t\tx=-x;\r\n\t\tfloat root = sqrtf(1.0f-x);\r\n\t\r\n\t\tfloat  result = -0.0187293f;\r\n\t\tresult *= x;\r\n\t\tresult += 0.0742610f;\r\n\t\tresult *= x;\r\n\t\tresult -= 0.2121144f;\r\n\t\tresult *= x;\r\n\t\tresult += 1.5707288f;\r\n\t\tresult *= root;\r\n\t\treturn 3.141592654f-result;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfloat root = sqrtf(1.0f-x);\r\n\t\r\n\t\tfloat  result = -0.0187293f;\r\n\t\tresult *= x;\r\n\t\tresult += 0.0742610f;\r\n\t\tresult *= x;\r\n\t\tresult -= 0.2121144f;\r\n\t\tresult *= x;\r\n\t\tresult += 1.5707288f;\r\n\t\tresult *= root;\r\n\t\treturn result;\r\n\t}\t\t\r\n}\r\n\r\nfloat FRunFilter( float target, float current, float delta )\r\n{\r\n\t\r\n\tif ( target < current )\r\n\t{\r\n\t\tif ( ( current - target ) > fabsf( delta ) )\r\n\t\t{\r\n\t\t\treturn ( current - fabsf( delta ) );\r\n\t\t}\r\n\t   \treturn ( target );\r\n\t}\r\n\tif ( ( target - current ) > fabsf( delta ) )\r\n\t{\r\n\t\treturn ( current + fabsf( delta ) );\r\n\t}\r\n\treturn ( target );\r\n}\r\n\r\nint RunFilter( int target, int current, int delta )\r\n{\r\n\tif ( target < current )\r\n\t{\r\n\t\tif ( current - target > abs( delta ) )\r\n\t\t\treturn ( target );\r\n\t\treturn ( current - abs( delta ) );\r\n\t}\r\n\tif ( target - current > abs( delta ) )\r\n\t\treturn ( target );\r\n\treturn ( current + abs( delta ) );\r\n}\r\n\r\n\r\n// returns atan(y/x) with appropiate sign determinations\r\n// although it does not work, as we cant; find atan ..... \r\n\r\n/*\r\nfloat Atan2 (float y, float x)\r\n{\r\n\r\n    if (x == 0.0f)\r\n\t{\r\n        if (y < 0.0f)     return(-PI/2.0f);\r\n\r\n        else             return( PI/2.0f);\r\n\r\n    }\r\n\telse\r\n\t{\r\n\t\t\r\n\t\r\n        if (x < 0.0f) {\r\n            if (y < 0.0f)\r\n\t\t\t\treturn(atan(y/x)-PI);\r\n            else\r\n\t\t\t\treturn(atan(y/x)+PI);\r\n        }\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn(atan(y/x));\r\n\t\t}\r\n\r\n    }\r\n\r\n}\r\n*/\r\n\r\n} // namespace Mth\r\n"
  },
  {
    "path": "Code/Core/Math/math.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (MTH)\t\t\t   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/math/math.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t11/23/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMath Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_MATH_MATH_H\r\n#define __CORE_MATH_MATH_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __PLAT_XBOX__\r\n#include <math.h>\t\t// Required for fabsf().\r\n#include <core\\math\\xbox\\sse.h>\r\n#endif\r\n\r\n#ifdef __PLAT_WN32__\r\n#include <math.h>\t\t// Required for fabsf().\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __USER_MATT__\r\n#define DEBUGGING_REPLAY_RND 0\r\n#else\r\n#define DEBUGGING_REPLAY_RND 0\r\n#endif\r\n\r\n#if DEBUGGING_REPLAY_RND\r\n\r\n#define Rnd( x ) Rnd_DbgVersion( ( x ), __LINE__, __FILE__ )\r\n\r\n#else\r\n#define Rnd( x ) Rnd( x )\r\n#endif\r\n\r\nnamespace Mth\r\n{\r\n\t\t\t\t\t\t   \r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Type Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid InitialRand(int a);\r\n\r\n#if DEBUGGING_REPLAY_RND\r\n\r\nint Rnd_DbgVersion(int n, int line, char *file);\r\nvoid SetRndTestMode( int mode );\r\nbool RndFuckedUp( void );\r\n\r\n#else\r\n\r\nint Rnd(int n);\r\n\r\n#endif\r\n\r\n// use for non-deterministic things\r\n// especially for CD-timing reliant stuff that would throw off our random number dealy whopper.\r\nint Rnd2(int n);\r\n\r\nfloat PlusOrMinus(float n);\r\nvoid InitSinLookupTable();\r\nfloat Kensinf(float x);\r\nfloat Kencosf(float x);\r\nfloat Kenacosf(float x);\r\nfloat Atan2 (float y, float x);\t\t\t// replaces atan2, much faster\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline\tint Abs ( int x )\r\n{\r\n\treturn ( x>=0?x:-x);\r\n}\r\n\r\n\r\ninline\tfloat\tAbs ( float x )\r\n{\r\n\treturn float ( fabsf ( x ));\r\n}\r\n\r\n// round down to nearest whole number\r\ninline\tfloat\tWhole ( float x )\r\n{\r\n\treturn (float) ( (int) ( x ));\r\n}\r\n\r\n// round to nearest whole number\r\ninline\tfloat\tRound ( float x )\r\n{\r\n\t\treturn (float) ( (int) ( x + 0.499999f));\r\n}\r\n\r\n\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// Calculate the \"Parabolic Lerp\" value for a set of parameters\r\n// (Note:  made-up name, by Mick)\r\n//\r\n// A lerp (Linear intERPalotion) value is always in the range 0.0 to 1.0\r\n// and is used to move one value (A) towards another (B)\r\n// usually the lerp value is fixed.\r\n//\r\n// A new value C is calculated as C = A + lerp * (B - A)\r\n//\r\n// a \"ParaLerp\" is a lerp value that varies based on the distance apart of the two values\r\n//\r\n// The purpose of this function\tis to be able to smoothly change a value\r\n// that really only needs lerping when the values are within a small range\r\n// The result of this equation is a parabolic curve that quickly tends \r\n// towards lerp = 1.0, as x increases\r\n// The valeu \"Rate\" is the value of x for which lerp half way between Min and 1.0\r\n// Min is the value of lerp when x is 0 \r\ninline float ParaLerp(float x, float Rate = 1.0f, float Minimum = 0.0f)\r\n{\r\n\tfloat lerp = Minimum + (1 - 1 / (1 + x / Rate) ) * (1 - Minimum);\r\n\treturn lerp; \r\n\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tClampMin ( float v, float min )\r\n{\r\n\tif ( v < min )\r\n\t{\r\n\t\treturn min;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn v;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tClampMax ( float v, float max )\r\n{\r\n\tif ( v > max )\r\n\t{\r\n\t\treturn max;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn v;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tClamp ( float v, float min, float max )\r\n{\r\n\treturn ClampMin ( ClampMax ( v, max ), min );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tLerp ( float a, float b, float value )\r\n{\r\n\treturn a + ( b - a ) * value;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tLinearMap ( float a, float b, float value, float value_min, float value_max )\r\n{\r\n\treturn Lerp(a, b, (value - value_min) / (value_max - value_min));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tSmoothStep ( float value )\r\n{\r\n\t// interpolates from zero to one with a zero derivative at the end-points\r\n\treturn -2.0f * value * value * ( value - (3.0f / 2.0f) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tSmoothInterp ( float a, float b, float value )\r\n{\r\n\treturn Lerp(a, b, SmoothStep(value));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tSmoothMap ( float a, float b, float value, float value_min, float value_max )\r\n{\r\n\treturn Lerp(a, b, SmoothStep((value - value_min) / (value_max - value_min)));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tMax ( float a, float b )\r\n{\r\n\treturn ( a > b ) ? a : b;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tMin ( float a, float b )\r\n{\r\n\treturn ( a < b ) ? a : b;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tSgn ( float x )\r\n{\r\n\tif ( x < 0.f )\r\n\t{\r\n\t\treturn -1.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 1.0f;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tSqr ( float x )\r\n{\r\n\treturn ( x * x );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\tSwap ( float& a, float& b )\r\n{\r\n\tfloat\tt = a;\r\n\ta = b; \r\n\tb = t;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tbool\tEqual ( const float a, const float b, const float perc )\r\n{\r\n\treturn ( Abs ( a - b ) <= (( Abs ( a ) + Abs ( b )) * perc ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tsint\tMax ( sint a, sint b )\r\n{\r\n\treturn ( a > b ) ? a : b;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tsint\tMin ( sint a, sint b )\r\n{\r\n\treturn ( a < b ) ? a : b;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tMax3 ( float a, float b, float c )\r\n{\r\n\treturn Max(a, Max(b,c));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tMin3 ( float a, float b, float c )\r\n{\r\n\treturn Min(a, Min(b,c));\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tDeterminant\t( float a, float b, float c, float d )\r\n{\r\n\treturn ( a * d ) - ( b * c );\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tDeterminant3  ( float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3 )\r\n{\r\n\treturn \ta1 * (b2 * c3 - b3 * c2) - \r\n\t\t\tb1 * (a2 * c3 - a3 * c2) + \r\n\t\t\tc1 * (a2 * b3 - a3 * b2);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tint\t\tWeightedRnd  ( float min_val, float max_val )\r\n{\r\n\t// This random function uses the West distribution\r\n\t// to return values that favor the midpoint.\r\n\r\n\t// For example, WeightedRnd( 10, 20 ) returns:\r\n\t// Bucket[10] = 2.12 percent\r\n\t// Bucket[11] = 5.72 percent\r\n\t// Bucket[12] = 9.44 percent\r\n\t// Bucket[13] = 13.87 percent\r\n\t// Bucket[14] = 18.16 percent\r\n\t// Bucket[15] = 15.70 percent\r\n\t// Bucket[16] = 14.52 percent\r\n\t// Bucket[17] = 10.16 percent\r\n\t// Bucket[18] = 6.05 percent\r\n\t// Bucket[19] = 2.26 percent\r\n\t// Bucket[20] = 2.00 percent\r\n\t\r\n\tfloat range = ( max_val - min_val ) / 2;\r\n\tfloat midpoint = min_val + range;\r\n\r\n\tfloat random_val = range - (float)sqrtf((float)Rnd( (int)(range * range) ) );\r\n\r\n\t// negate it half of the time\r\n\tif ( Rnd(2) )\r\n\t{\r\n\t\trandom_val = -random_val;\r\n\t}\r\n\r\n\treturn (int)( random_val + midpoint );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n// Trig\r\n\r\nconst\tfloat\tEPSILON \t= 0.000001f;\r\nconst\tfloat\tPI\t\t\t= 3.141592654f;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tDegToRad ( float degrees )\r\n{\r\n\treturn degrees * ( PI / 180.0f);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tRadToDeg ( float radians )\r\n{\r\n\treturn radians * ( 180.0f / PI );\r\n}\r\n\r\n\t\t\t\t\t\t\t\r\nint\t\tRunFilter( int target, int current, int delta );\r\nfloat\tFRunFilter( float target, float current, float delta );\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mth\r\n\r\n#endif // __CORE_MATH_MATH_H\r\n"
  },
  {
    "path": "Code/Core/Math/matrix.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (MTH)\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmatrix.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t10/03/2000\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMatrix Math Library code\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mth\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t   \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMatrix::Matrix( float p, float h, float r)\r\n{\r\n\t\r\n\t// Algorithm from http://www.flipcode.com/documents/matrfaq.html#Q37\r\n\tfloat A,B,C,D,E,F,AD,BD;\r\n\r\n\tA = cosf( p );\r\n    B = sinf( p );\r\n    C = cosf( h );\r\n    D = sinf( h );\r\n    E = cosf( r );\r\n    F = sinf( r );\r\n\r\n    AD =   A * D;\r\n    BD =   B * D;\r\n\r\n    row[0][0] =   C * E;\r\n    row[0][1] =  -C * F;\r\n    row[0][2] =  -D;\r\n    row[1][0] = -BD * E + A * F;\r\n    row[1][1] =  BD * F + A * E;\r\n    row[1][2] =  -B * C;\r\n    row[2][0] =  AD * E + B * F;\r\n    row[2][1] = -AD * F + B * E;\r\n    row[2][2] =   A * C;\r\n\r\n    row[0][3] = row[1][3] = row[2][3] = row[3][0] = row[3][1] = row[3][2] = 0.0f;\r\n    row[3][3] = 1.0f;\r\n}\r\n\r\n#ifdef\t__PLAT_NGPS__\r\nvoid xsceVu0MulMatrix(Mth::Matrix* m0, Mth::Matrix* m1, const Mth::Matrix* m2)\r\n{\r\n\r\n\tasm __volatile__(\"\r\n\tlqc2    vf4,0x0(%2)\r\n\tlqc2    vf5,0x10(%2)\r\n\tlqc2    vf6,0x20(%2)\r\n\tlqc2    vf7,0x30(%2)\r\n\tli    $7,4\r\n_loopMulMatrix:\r\n\tlqc2    vf8,0x0(%1)\r\n\tvmulax.xyzw\tACC,   vf4,vf8\r\n\tvmadday.xyzw\tACC,   vf5,vf8\r\n\tvmaddaz.xyzw\tACC,   vf6,vf8\r\n\tvmaddw.xyzw\tvf9,vf7,vf8\r\n\tsqc2    vf9,0x0(%0)\r\n\taddi    $7,-1\r\n\taddi    %1,0x10\r\n\taddi    %0,0x10\r\n\tbne    $0,$7,_loopMulMatrix\r\n\t\": : \"r\" (m0), \"r\" (m2), \"r\" (m1) : \"$7\");\r\n}\r\n#endif\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Ken: Faster version of atan2f, using the same algorithm used by VU1\r\n// (Coeefficients got from the VU manual, from documentation of EATANxy function, p130\r\n// SPEEDOPT: This could probably be made even faster using a less accurate approx with few coeffs.\r\nfloat katan(float y, float x)\r\n{\r\n\tif (fabs(y)>fabs(x))\r\n\t{\r\n\t\t// The approximation only works for y<=x, bummer!\r\n\t\treturn atan2f(y,x);\r\n\t}\r\n\tregister bool x_negative=false;\r\n\tregister bool y_negative=false;\r\n\tif (x<0.0f)\r\n\t{\r\n\t\tx=-x;\r\n\t\tx_negative=true;\r\n\t}\t\r\n\tif (y<=-0.0f)\r\n\t{\r\n\t\ty=-y;\r\n\t\ty_negative=true;\r\n\t}\t\r\n\r\n\t// Use the non-ratio version, because the ratio version goes \r\n\t// all innaccurate for some values ... don't know why ...\r\n\ty=y/x;\r\n\t\r\n\tregister float t1=0.999999344348907f;\r\n\tregister float t2=-0.333298563957214f;\r\n\tregister float t3=0.199465364217758f;\r\n\tregister float t4=-0.139085337519646f;\r\n\tregister float t5=0.096420042216778f;\r\n\tregister float t6=-0.055909886956215f;\r\n\tregister float t7=0.021861229091883f;\r\n\tregister float t8=-0.004054057877511f;\r\n\t\r\n\tregister float t=(y-1.0f)/(y+1.0f);\r\n\tregister float tt=t*t;\r\n\tregister float s=t8*t;\r\n\ts=s*tt+t7*t;\r\n\ts=s*tt+t6*t;\r\n\ts=s*tt+t5*t;\r\n\ts=s*tt+t4*t;\r\n\ts=s*tt+t3*t;\r\n\ts=s*tt+t2*t;\r\n\ts=s*tt+t1*t;\r\n\tif (x_negative)\r\n\t{\r\n\t\tif (y_negative)\r\n\t\t{\r\n\t\t\treturn s+0.785398185253143f-3.141592653589793f;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn 3.141592653589793f-0.785398185253143f-s;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (y_negative)\r\n\t\t{\r\n\t\t\treturn -0.785398185253143f-s;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn s+0.785398185253143f;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Matrix::GetEulers( Vector& euler ) const\r\n{\r\n\t\r\n\r\n\t// Algorithm from http://www.flipcode.com/documents/matrfaq.html#Q37\r\n\tfloat C, D;\r\n\tfloat tr_x, tr_y;\r\n\r\n#ifdef __PLAT_NGC__\r\n\tfloat\tang = row[0][2];\r\n\tif ( ang > 1.0f ) ang = 1.0f;\r\n\tif ( ang < -1.0f ) ang = -1.0f;\r\n\teuler[Y] = D = -asinf( ang );        /* Calculate Y-axis angle */\r\n#else\r\n\tfloat\tang = row[0][2];\r\n\tif ( ang > 1.0f ) ang = 1.0f;\r\n\tif ( ang < -1.0f ) ang = -1.0f;\r\n\teuler[Y] = D = -asinf( ang );        /* Calculate Y-axis angle */\r\n//\teuler[Y] = D = -asinf( row[0][2]);        /* Calculate Y-axis angle */\r\n#endif\t\t// __PLAT_NGC__\r\n    C =  cosf( euler[Y] );\r\n    \t\r\n\tif( fabsf( C ) > 0.005f )             /* Gimball lock? */\r\n\t{\r\n\t\ttr_x      =  row[2][2] / C;           /* No, so get X-axis angle */\r\n\t\ttr_y      = -row[1][2] / C;\r\n\t\r\n\t\teuler[X]  = katan( tr_y, tr_x );\r\n\t\r\n\t\ttr_x      =  row[0][0] / C;            /* Get Z-axis angle */\r\n\t\ttr_y      = -row[0][1] / C;\r\n\t\r\n\t\teuler[Z]  = katan( tr_y, tr_x );\r\n\t}\r\n\telse                                 /* Gimball lock has occurred */\r\n\t{\r\n\t\teuler[X]  = 0;                      /* Set X-axis angle to zero */\r\n\t\r\n\t\ttr_x      = row[1][1];                 /* And calculate Z-axis angle */\r\n\t\ttr_y      = row[1][0];\r\n\t\r\n\t\teuler[Z]  = katan( tr_y, tr_x );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Matrix::PrintContents() const\r\n{\r\n\tprintf( \"-----------------\\n\" );\r\n\tprintf( \"%f %f %f %f\\n\", row[RIGHT][X], row[RIGHT][Y], row[RIGHT][Z], row[RIGHT][W] );\r\n\tprintf( \"%f %f %f %f\\n\", row[UP][X], row[UP][Y], row[UP][Z], row[UP][W] );\r\n\tprintf( \"%f %f %f %f\\n\", row[AT][X], row[AT][Y], row[AT][Z], row[AT][W] );\r\n\tprintf( \"%f %f %f %f\\n\", row[POS][X], row[POS][Y], row[POS][Z], row[POS][W] );\r\n\tprintf( \"-----------------\\n\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\n// Original source of the optimized fromToRoation function\r\n\r\n#include <math.h>\r\n\r\n#define EPSILON 0.000001\r\n\r\n#define CROSS(dest, v1, v2){                 \\\r\n          dest[0] = v1[1] * v2[2] - v1[2] * v2[1]; \\\r\n          dest[1] = v1[2] * v2[0] - v1[0] * v2[2]; \\\r\n          dest[2] = v1[0] * v2[1] - v1[1] * v2[0];}\r\n\r\n#define DOT(v1, v2) (v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2])\r\n\r\n#define SUB(dest, v1, v2){       \\\r\n          dest[0] = v1[0] - v2[0]; \\\r\n          dest[1] = v1[1] - v2[1]; \\\r\n          dest[2] = v1[2] - v2[2];}\r\n\r\n//\r\n// * A function for creating a rotation matrix that rotates a vector called\r\n// * \"from\" into another vector called \"to\".\r\n// * Input : from[3], to[3] which both must be *normalized* non-zero vectors\r\n// * Output: mtx[3][3] -- a 3x3 matrix in colum-major form\r\n// * Authors: Tomas Mller, John Hughes 1999\r\n// \r\nvoid fromToRotation(float from[3], float to[3], float mtx[3][3])\r\n{\r\n  float v[3];\r\n  float e, h, f;\r\n\r\n  CROSS(v, from, to);\r\n  e = DOT(from, to);\r\n  f = (e < 0)? -e:e;\r\n  if (f > 1.0 - EPSILON)     // \"from\" and \"to\"-vector almost parallel \r\n  {\r\n    float u[3], v[3]; // temporary storage vectors \r\n    float x[3];       // vector most nearly orthogonal to \"from\" \r\n    float c1, c2, c3; // coefficients for later use \r\n    int i, j;\r\n\r\n    x[0] = (from[0] > 0.0)? from[0] : -from[0];\r\n    x[1] = (from[1] > 0.0)? from[1] : -from[1];\r\n    x[2] = (from[2] > 0.0)? from[2] : -from[2];\r\n\r\n    if (x[0] < x[1]) \r\n    {\r\n      if (x[0] < x[2]) \r\n      {\r\n        x[0] = 1.0; x[1] = x[2] = 0.0;\r\n      }\r\n      else \r\n      {\r\n        x[2] = 1.0; x[0] = x[1] = 0.0;\r\n      }\r\n    }\r\n    else \r\n    {\r\n      if (x[1] < x[2]) \r\n      {\r\n        x[1] = 1.0; x[0] = x[2] = 0.0;\r\n      }\r\n      else \r\n      {\r\n        x[2] = 1.0; x[0] = x[1] = 0.0;\r\n      }\r\n    }\r\n\r\n    u[0] = x[0] - from[0]; u[1] = x[1] - from[1]; u[2] = x[2] - from[2];\r\n    v[0] = x[0] - to[0];   v[1] = x[1] - to[1];   v[2] = x[2] - to[2];\r\n\r\n    c1 = 2.0 / DOT(u, u);\r\n    c2 = 2.0 / DOT(v, v);\r\n    c3 = c1 * c2  * DOT(u, v);\r\n    \r\n    for (i = 0; i < 3; i++) {\r\n      for (j = 0; j < 3; j++) {\r\n        mtx[i][j] =  - c1 * u[i] * u[j]\r\n                     - c2 * v[i] * v[j]\r\n                     + c3 * v[i] * u[j];\r\n      }\r\n      mtx[i][i] += 1.0;\r\n    }\r\n  }\r\n  else  // the most common case, unless \"from\"=\"to\", or \"from\"=-\"to\" \r\n  {\r\n#if 0\r\n    // unoptimized version - a good compiler will optimize this. \r\n    h = (1.0 - e)/DOT(v, v);\r\n    mtx[0][0] = e + h * v[0] * v[0];  \r\n    mtx[0][1] = h * v[0] * v[1] - v[2]; \r\n    mtx[0][2] = h * v[0] * v[2] + v[1];\r\n    \r\n    mtx[1][0] = h * v[0] * v[1] + v[2]; \r\n    mtx[1][1] = e + h * v[1] * v[1];    \r\n    mtx[1][2] = h * v[1] * v[2] - v[0];\r\n\r\n    mtx[2][0] = h * v[0] * v[2] - v[1]; \r\n    mtx[2][1] = h * v[1] * v[2] + v[0]; \r\n    mtx[2][2] = e + h * v[2] * v[2];\r\n#else\r\n    // ...otherwise use this hand optimized version (9 mults less) \r\n    float hvx, hvz, hvxy, hvxz, hvyz;\r\n    h = (1.0 - e)/DOT(v, v);\r\n    hvx = h * v[0];\r\n    hvz = h * v[2];\r\n    hvxy = hvx * v[1];\r\n    hvxz = hvx * v[2];\r\n    hvyz = hvz * v[1];\r\n    mtx[0][0] = e + hvx * v[0]; \r\n    mtx[0][1] = hvxy - v[2];     \r\n    mtx[0][2] = hvxz + v[1];\r\n\r\n    mtx[1][0] = hvxy + v[2];  \r\n    mtx[1][1] = e + h * v[1] * v[1]; \r\n    mtx[1][2] = hvyz - v[0];\r\n\r\n    mtx[2][0] = hvxz - v[1];  \r\n    mtx[2][1] = hvyz + v[0];     \r\n    mtx[2][2] = e + hvz * v[2];\r\n#endif\r\n  }\r\n}\r\n*/\r\n\r\n\r\n#define FROMTO_EPSILON 0.000001f\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////\r\n//Matrix&\t\t CreateFromToMatrix( Matrix &mtx, Vector from, Vector to )\r\n//\r\n// * A function for creating a rotation matrix that rotates a vector called\r\n// * \"from\" into another vector called \"to\".\r\n// * Input : from[3], to[3] which both must be *normalized* non-zero vectors\r\n// * Output: mtx[3][3] -- a 3x3 matrix in colum-major form\r\n// * Authors: Tomas Mller, John Hughes 1999\r\n// \r\n//\r\n// Micknote .. on testing this, it seems like it produces the inverse of what we want\r\n// possibly just need to swap the from/to vectors, but for now I'm just inverting it\r\n// at the end of the function, before it returns the matrix\r\n//\r\n// Sample usage:\r\n//\t\t\tMth::Matrix  rotate;\r\n//\t\t\tMth::CreateFromToMatrix(rotate,m_matrix[Y],m_normal);\r\n//\t\t\tm_matrix *= rotate;\r\n//\r\n// will rotate m_matrix, so the Y component is coincident with m_normal\r\n// (this is used to align the skater to a surface, given the surface normal)\r\n//\r\n\r\nMatrix&\t\t CreateFromToMatrix( Matrix &mtx, Vector from, Vector to )\r\n{\r\n  Vector cross;\r\n  float e, h, f;\r\n  \r\n  \r\n  mtx.Ident();\t\t\t \t\t\t// clean up W rows and cols\r\n  \r\n\r\n  cross = CrossProduct(from,to);\t\t//  CROSS(v, from, to);\r\n  e = DotProduct(from,to);\t\t\t//  e = DOT(from, to);\r\n  f = (e < 0.0f)? -e:e;\r\n  if (f > 1.0f - FROMTO_EPSILON)     \t\t// \"from\" and \"to\"-vector almost parallel \r\n  {\r\n    Vector u, v; // temporary storage vectors \r\n    Vector x;       // vector most nearly orthogonal to \"from\" \r\n    float c1, c2, c3; // coefficients for later use \r\n    int i, j;\r\n\r\n    x[0] = (from[0] >= 0.0f)? from[0] : -from[0];\r\n    x[1] = (from[1] >= 0.0f)? from[1] : -from[1];\r\n    x[2] = (from[2] >= 0.0f)? from[2] : -from[2];\r\n\r\n    if (x[0] < x[1]) \r\n    {\r\n      if (x[0] < x[2]) \r\n      {\r\n        x[0] = 1.0f; x[1] = x[2] = 0.0f;\r\n      }\r\n      else \r\n      {\r\n        x[2] = 1.0f; x[0] = x[1] = 0.0f;\r\n      }\r\n    }\r\n    else \r\n    {\r\n      if (x[1] < x[2]) \r\n      {\r\n        x[1] = 1.0f; x[0] = x[2] = 0.0f;\r\n      }\r\n      else \r\n      {\r\n        x[2] = 1.0f; x[0] = x[1] = 0.0f;\r\n      }\r\n    }\r\n\r\n    u[0] = x[0] - from[0]; u[1] = x[1] - from[1]; u[2] = x[2] - from[2];\r\n    v[0] = x[0] - to[0];   v[1] = x[1] - to[1];   v[2] = x[2] - to[2];\r\n\r\n    c1 = 2.0f / DotProduct(u, u);\r\n    c2 = 2.0f / DotProduct(v, v);\r\n    c3 = c1 * c2  * DotProduct(u, v);\r\n    \r\n    for (i = 0; i < 3; i++) \r\n\t{\r\n      for (j = 0; j < 3; j++)\r\n\t  {\r\n        mtx[i][j] =  - c1 * u[i] * u[j]\r\n                     - c2 * v[i] * v[j]\r\n                     + c3 * v[i] * u[j];\r\n      }\r\n      mtx[i][i] += 1.0f;\r\n    }\r\n  }\r\n  else  // the most common case, unless \"from\"=\"to\", or \"from\"=-\"to\" \r\n  {\r\n#if 0\r\n    // unoptimized version - a good compiler will optimize this. \r\n    h = (1.0f - e)/DOT(v, v);\r\n    mtx[0][0] = e + h * v[0] * v[0];  \r\n    mtx[0][1] = h * v[0] * v[1] - v[2]; \r\n    mtx[0][2] = h * v[0] * v[2] + v[1];\r\n    \r\n    mtx[1][0] = h * v[0] * v[1] + v[2]; \r\n    mtx[1][1] = e + h * v[1] * v[1];    \r\n    mtx[1][2] = h * v[1] * v[2] - v[0];\r\n\r\n    mtx[2][0] = h * v[0] * v[2] - v[1]; \r\n    mtx[2][1] = h * v[1] * v[2] + v[0]; \r\n    mtx[2][2] = e + h * v[2] * v[2];\r\n#else\r\n    // ...otherwise use this hand optimized version (9 mults less) \r\n    float hvx, hvz, hvxy, hvxz, hvyz;\r\n    h = (1.0f - e)/DotProduct(cross, cross);\r\n    hvx = h * cross[0];\r\n    hvz = h * cross[2];\r\n    hvxy = hvx * cross[1];\r\n    hvxz = hvx * cross[2];\r\n    hvyz = hvz * cross[1];\r\n    mtx[0][0] = e + hvx * cross[0]; \r\n    mtx[0][1] = hvxy - cross[2];     \r\n    mtx[0][2] = hvxz + cross[1];\r\n\r\n    mtx[1][0] = hvxy + cross[2];  \r\n    mtx[1][1] = e + h * cross[1] * cross[1]; \r\n    mtx[1][2] = hvyz - cross[0];\r\n\r\n    mtx[2][0] = hvxz - cross[1];  \r\n    mtx[2][1] = hvyz + cross[0];     \r\n    mtx[2][2] = e + hvz * cross[2];\r\n#endif\r\n  }\r\n  \r\n  \r\n  \tmtx.Invert();\t \t\t// Micknote: not sure why we need to invert it, but let it be for now\r\n\t\r\n\t \r\n\treturn mtx;\r\n}\r\n\t\t\t\r\n\t\t\t\r\nMatrix&\t\tCreateRotateMatrix ( Matrix& mat, const Vector& axis, const float angle )\r\n{\r\n\t\r\n\r\n    Vector\tunitAxis = axis;\r\n\tunitAxis.Normalize();\r\n\t\r\n\tfloat oneMinusCosine = 1.0f - cosf( angle );\r\n\t\r\n\tVector\tleading;\r\n\r\n\tleading[X] = 1.0f - ( unitAxis[X] * unitAxis[X] );\r\n\tleading[Y] = 1.0f - ( unitAxis[Y] * unitAxis[Y] );\r\n\tleading[Z] = 1.0f - ( unitAxis[Z] * unitAxis[Z] );\r\n\tleading *= oneMinusCosine; \r\n\t\r\n\tVector\tcrossed;\r\n\r\n\tcrossed[X] = ( unitAxis[Y] * unitAxis[Z] );\r\n\tcrossed[Y] = ( unitAxis[Z] * unitAxis[X] );\r\n\tcrossed[Z] = ( unitAxis[X] * unitAxis[Y] );\r\n\tcrossed *= oneMinusCosine;\r\n\t\r\n\tunitAxis *= sinf( angle );\r\n\t\t\r\n\tmat[RIGHT][X] = 1.0f - leading[X];\r\n\tmat[RIGHT][Y] = crossed[Z] + unitAxis[Z];\r\n\tmat[RIGHT][Z] = crossed[Y] - unitAxis[Y];\r\n\tmat[RIGHT][W] = 0.0f;\r\n\t\r\n\tmat[UP][X] = crossed[Z] - unitAxis[Z];\r\n\tmat[UP][Y] = 1.0f - leading[Y];\r\n\tmat[UP][Z] = crossed[X] + unitAxis[X];\r\n\tmat[UP][W] = 0.0f;\r\n\t\r\n\tmat[AT][X] = crossed[Y] + unitAxis[Y];\r\n\tmat[AT][Y] = crossed[X] - unitAxis[X];\r\n\tmat[AT][Z] = 1.0f - leading[Z];\r\n\tmat[AT][W] = 0.0f;\r\n\t\r\n\tmat[POS][X] = 0.0f;\r\n\tmat[POS][Y] = 0.0f;\r\n\tmat[POS][Z] = 0.0f;\r\n\tmat[POS][W] = 1.0f;\r\n\r\n\treturn mat;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nMatrix& CreateRotateXMatrix( Matrix& rotX, float angle )\r\n{\r\n\t\r\n\r\n\tfloat\ts = sinf( angle );\r\n\tfloat\tc = cosf( angle );\r\n\r\n\trotX[RIGHT][X] = 1.0f;\r\n\trotX[RIGHT][Y] = 0.0f;\r\n\trotX[RIGHT][Z] = 0.0f;\r\n\trotX[RIGHT][W] = 0.0f;\r\n\t\r\n\trotX[UP][X] = 0.0f;\r\n\trotX[UP][Y] = c;\r\n\trotX[UP][Z] = s;\r\n\trotX[UP][W] = 0.0f;\r\n\t\r\n\trotX[AT][X] = 0.0f;\r\n\trotX[AT][Y] = -s;\r\n\trotX[AT][Z] = c;\r\n\trotX[AT][W] = 0.0f;\r\n\t\r\n\trotX[POS][X] = 0.0f;\r\n\trotX[POS][Y] = 0.0f;\r\n\trotX[POS][Z] = 0.0f;\r\n\trotX[POS][W] = 1.0f;\r\n\r\n\treturn rotX;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nMatrix& CreateRotateYMatrix( Matrix& rotY, float angle )\r\n{\r\n\t\r\n\r\n\tfloat\ts = sinf( angle );\r\n\tfloat\tc = cosf( angle );\r\n\r\n\trotY[RIGHT][X] = c;\r\n\trotY[RIGHT][Y] = 0.0f;\r\n\trotY[RIGHT][Z] = -s;\r\n\trotY[RIGHT][W] = 0.0f;\r\n\t\r\n\trotY[UP][X] = 0.0f;\r\n\trotY[UP][Y] = 1.0f;\r\n\trotY[UP][Z] = 0.0f;\r\n\trotY[UP][W] = 0.0f;\r\n\t\r\n\trotY[AT][X] = s;\r\n\trotY[AT][Y] = 0.0f;\r\n\trotY[AT][Z] = c;\r\n\trotY[AT][W] = 0.0f;\r\n\t\r\n\trotY[POS][X] = 0.0f;\r\n\trotY[POS][Y] = 0.0f;\r\n\trotY[POS][Z] = 0.0f;\r\n\trotY[POS][W] = 1.0f;\r\n\r\n\treturn rotY;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nMatrix& CreateRotateZMatrix( Matrix& rotZ, float angle )\r\n{\r\n\t\r\n\r\n\tfloat\ts = sinf( angle );\r\n\tfloat\tc = cosf( angle );\r\n\r\n\trotZ[RIGHT][X] = c;\r\n\trotZ[RIGHT][Y] = s;\r\n\trotZ[RIGHT][Z] = 0.0f;\r\n\trotZ[RIGHT][W] = 0.0f;\r\n\t\r\n\trotZ[UP][X] = -s;\r\n\trotZ[UP][Y] = c;\r\n\trotZ[UP][Z] = 0;\r\n\trotZ[UP][W] = 0.0f;\r\n\t\r\n\trotZ[AT][X] = 0.0f;\r\n\trotZ[AT][Y] = 0.0f;\r\n\trotZ[AT][Z] = 1.0f;\r\n\trotZ[AT][W] = 0.0f;\r\n\t\r\n\trotZ[POS][X] = 0.0f;\r\n\trotZ[POS][Y] = 0.0f;\r\n\trotZ[POS][Z] = 0.0f;\r\n\trotZ[POS][W] = 1.0f;\r\n\r\n\treturn rotZ;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMatrix& CreateRotateMatrix( Matrix &rot, int axis, const float angle )\r\n{\r\n\tint\t\ta = (axis + 1) % (Z + 1);\r\n\tint\t\tb = (axis + 2) % (Z + 1);\r\n\r\n\tfloat\ts = sinf( angle );\r\n\tfloat\tc = cosf( angle );\r\n\t\r\n\trot.Ident();\r\n\t\r\n\trot[a][a] = c;\r\n\trot[a][b] = s;\r\n\trot[b][a] = -s;\r\n\trot[b][b] = c;\r\n\t\r\n\treturn rot;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nMatrix& CreateMatrixLookAt( Matrix& mat, const Vector& pos, const Vector& lookat, const Vector& up )\r\n{\r\n\t// Create Z axis\r\n\tMth::Vector z_axis(lookat - pos);\r\n\tz_axis.Normalize();\r\n\t//mat[Z] = z_axis;\r\n\r\n\t// Create X from Z and up (up assumed to be normalized)\r\n\tMth::Vector x_axis(Mth::CrossProduct(z_axis, up));\r\n\t//mat[X] = x_axis;\r\n\r\n\t// Create Y from Z and X\r\n\tMth::Vector y_axis(Mth::CrossProduct(x_axis, z_axis));\r\n\t//mat[Y] = y_axis;\r\n\r\n\t// Orientation needs transposing (since we want the inverse orientation)\r\n\t//mat.Transpose();\r\n\tmat[X][X] = x_axis[X];\r\n\tmat[Y][X] = x_axis[Y];\r\n\tmat[Z][X] = x_axis[Z];\r\n\r\n\tmat[X][Y] = y_axis[X];\r\n\tmat[Y][Y] = y_axis[Y];\r\n\tmat[Z][Y] = y_axis[Z];\r\n\r\n\tmat[X][Z] = z_axis[X];\r\n\tmat[Y][Z] = z_axis[Y];\r\n\tmat[Z][Z] = z_axis[Z];\r\n\r\n\t// These may not be zero, but should be\r\n\tmat[X][W] = 0.0f;\r\n\tmat[Y][W] = 0.0f;\r\n\tmat[Z][W] = 0.0f;\r\n\r\n\t// Create inverse translation\r\n\tmat[POS][X] = -Mth::DotProduct(x_axis, pos);\r\n\tmat[POS][Y] = -Mth::DotProduct(y_axis, pos);\r\n\tmat[POS][Z] = -Mth::DotProduct(z_axis, pos);\r\n\tmat[POS][W] = 1.0f;\r\n\r\n\t//Dbg_Message(\"LookAt matrix:\");\r\n\t//Dbg_Message(\"[ %f, %f, %f, %f ]\", mat[X][X], mat[X][Y], mat[X][Z], mat[X][W]);\r\n\t//Dbg_Message(\"[ %f, %f, %f, %f ]\", mat[Y][X], mat[Y][Y], mat[Y][Z], mat[Y][W]);\r\n\t//Dbg_Message(\"[ %f, %f, %f, %f ]\", mat[Z][X], mat[Z][Y], mat[Z][Z], mat[Z][W]);\r\n\t//Dbg_Message(\"[ %f, %f, %f, %f ]\", mat[W][X], mat[W][Y], mat[W][Z], mat[W][W]);\r\n\r\n\treturn mat;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nMatrix& CreateMatrixOrtho( Matrix& mat, float width, float height, float f_near, float f_far )\r\n{\r\n\tmat[X] = Mth::Vector(2.0f / width, 0.0f, 0.0f, 0.0f);\r\n\tmat[Y] = Mth::Vector(0.0f, 2.0f / height, 0.0f, 0.0f);\r\n\tmat[Z] = Mth::Vector(0.0f, 0.0f, 2.0f / (f_far - f_near), 0.0f);\r\n\tmat[W] = Mth::Vector(0.0f, 0.0f, -(f_far + f_near) / (f_far - f_near), 1.0f);\r\n\r\n\t//Dbg_Message(\"Orthographic matrix:\");\r\n\t//Dbg_Message(\"[ %f, %f, %f, %f ]\", mat[X][X], mat[X][Y], mat[X][Z], mat[X][W]);\r\n\t//Dbg_Message(\"[ %f, %f, %f, %f ]\", mat[Y][X], mat[Y][Y], mat[Y][Z], mat[Y][W]);\r\n\t//Dbg_Message(\"[ %f, %f, %f, %f ]\", mat[Z][X], mat[Z][Y], mat[Z][Z], mat[Z][W]);\r\n\t//Dbg_Message(\"[ %f, %f, %f, %f ]\", mat[W][X], mat[W][Y], mat[W][Z], mat[W][W]);\r\n\r\n\treturn mat;\r\n}\r\n\t\t\r\n// Orthonormalize a matrix keeping one row r0 unchanged \r\n// (Mick accepts responsibility for this).\t\t\t\t\t   \r\nMatrix&\tMatrix::OrthoNormalizeAbout(int r0)\r\n{\r\n\tint r1, r2;\r\n\tr1 = r0+1;\r\n\tif (r1 == 3)\r\n\t{ \r\n\t\tr1 = 0;\r\n\t}\r\n\tr2 = r1+1;\r\n\tif (r2 == 3)\r\n\t{\r\n\t\tr2 = 0;\r\n\t}\r\n\t// Now regarding Rows r0,r1,r2\r\n\t// r0 = r1 x r2\t   (implied)\r\n\t// r1 = r2 x r0\t   (calculate this)\r\n\t// r2 = r0 x r1\t   (and this)\r\n\t//\r\n\t// We need to recalculate rows r1 and r2 using the above cross produces\r\n\t// however if r0 is close to r2, then the calculation of r1 will be off\r\n\t// so it's better to calulate r2 and then r1 \r\n\t// the first pair to do will be whichever has the smaller dot product\r\n\r\n\tif (Abs(DotProduct(*(Vector*)(row[r2]),*(Vector*)(row[r0]))) < Abs(DotProduct(*(Vector*)(row[r0]),*(Vector*)(row[r1]))))\r\n\t{\t\t\r\n\t\t*(Vector*)(row[r1]) = Mth::CrossProduct(*(Vector*)(row[r2]),*(Vector*)(row[r0]));\r\n\t\t(*(Vector*)(row[r1])).Normalize();\r\n\t\t*(Vector*)(row[r2]) = Mth::CrossProduct(*(Vector*)(row[r0]),*(Vector*)(row[r1]));\r\n\t\t(*(Vector*)(row[r2])).Normalize();\r\n\t}\r\n\telse\r\n\t{\t\t\r\n\t\t*(Vector*)(row[r2]) = Mth::CrossProduct(*(Vector*)(row[r0]),*(Vector*)(row[r1]));\r\n\t\t(*(Vector*)(row[r2])).Normalize();\r\n\t\t*(Vector*)(row[r1]) = Mth::CrossProduct(*(Vector*)(row[r2]),*(Vector*)(row[r0]));\r\n\t\t(*(Vector*)(row[r1])).Normalize();\r\n\t}\r\n\r\n\treturn *this;\r\n\t\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Matrix::GetRotationAxisAndAngle( Vector* pAxis, float* pRadians )\r\n{\r\n\t// Given a transform matrix (end = start * xform)\r\n\t// this will return its rotation axis and angle\r\n\r\n\tDbg_Assert( pAxis );\r\n\tDbg_Assert( pRadians );\r\n\r\n    float\t\tnTwoSinTheta, nTwoCosTheta;\r\n    Mth::Vector\tvTwoSinThetaAxis;\r\n\r\n    nTwoCosTheta = row[Mth::RIGHT][X] + row[Mth::UP][Y] + row[Mth::AT][Z] - 1.0f;\r\n\r\n\tvTwoSinThetaAxis[X] = row[Mth::UP][Z] - row[Mth::AT][Y];\r\n    vTwoSinThetaAxis[Y] = row[Mth::AT][X] - row[Mth::RIGHT][Z];\r\n    vTwoSinThetaAxis[Z] = row[Mth::RIGHT][Y] - row[Mth::UP][X];\r\n    vTwoSinThetaAxis[W] = 1.0f;\r\n  \r\n\t// Gary:  There used to be a magic patch added by Dave\r\n\t// (basically negating the axis) which made it work with\r\n\t// the RW-based Slerp object.  This doesn't seem to be\r\n\t// necessary any more, but I'm going to leave it\r\n\t// in the code just in case our Slerp stops working...\r\n//  vTwoSinThetaAxis[X] = row[Mth::AT][Y] - row[Mth::UP][Z];\r\n//  vTwoSinThetaAxis[Y] = row[Mth::RIGHT][Z] - row[Mth::AT][X];\r\n//  vTwoSinThetaAxis[Z] = row[Mth::UP][X] - row[Mth::RIGHT][Y];\r\n//  vTwoSinThetaAxis[W] = 1.0f;\r\n\t\r\n\tnTwoSinTheta = vTwoSinThetaAxis.Length();\r\n    \r\n    if (nTwoSinTheta > 0.0f)\r\n    {\r\n        float  recipLength = (1.0f / (nTwoSinTheta));\r\n\r\n        *pAxis = vTwoSinThetaAxis;\r\n        pAxis->Scale( recipLength );\r\n    }\r\n    else\r\n    {\r\n        pAxis->Set( 0.0f, 0.0f, 0.0f );\r\n    }\r\n    \r\n\t(*pRadians) = (float)atan2(nTwoSinTheta, nTwoCosTheta);\r\n    if ((nTwoSinTheta <= 0.01f) && (nTwoCosTheta <= 0.0f))\r\n    {\r\n        /*\r\n         * sin theta is 0; cos theta is -1; theta is 180 degrees\r\n         * vTwoSinThetaAxis was degenerate\r\n         * axis will have to be found another way.\r\n         */\r\n\r\n\t\t//Vector\tvTwoSinThetaAxis;\r\n\r\n\t\t/*\r\n\t\t * Matrix is:\r\n\t\t * [ [ 2 a_x^2 - 1,  2 a_x a_y,   2 a_x a_z,  0 ]\r\n\t\t *   [  2 a_x a_y,  2 a_y^2 - 1,  2 a_y a_z,  0 ]\r\n\t\t *   [  2 a_x a_z,   2 a_y a_z,  2 a_z^2 - 1, 0 ]\r\n\t\t *   [      0,           0,           0,      1 ] ]\r\n\t\t * Build axis scaled by 4 * component of maximum absolute value\r\n\t\t */\r\n\t    if (row[Mth::RIGHT][X] > row[Mth::UP][Y])\r\n\t    {\r\n\t        if (row[Mth::RIGHT][X] > row[Mth::AT][Z])\r\n\t        {\r\n\t            vTwoSinThetaAxis[X] = 1.0f + row[Mth::RIGHT][X];\r\n\t            vTwoSinThetaAxis[X] = vTwoSinThetaAxis[X] + vTwoSinThetaAxis[X];\r\n\t            vTwoSinThetaAxis[Y] = row[Mth::RIGHT][Y] + row[Mth::UP][X];\r\n\t            vTwoSinThetaAxis[Z] = row[Mth::RIGHT][Z] + row[Mth::AT][X];\r\n\t        }\r\n\t        else\r\n\t        {\r\n\t            vTwoSinThetaAxis[Z] = 1.0f + row[Mth::AT][Z];\r\n\t            vTwoSinThetaAxis[Z] = vTwoSinThetaAxis[Z] + vTwoSinThetaAxis[Z];\r\n\t            vTwoSinThetaAxis[X] = row[Mth::AT][X] + row[Mth::RIGHT][Z];\r\n\t            vTwoSinThetaAxis[Y] = row[Mth::AT][Y] + row[Mth::UP][Z];\r\n\t        }\r\n\t    }\r\n\t    else\r\n\t    {\r\n\t        if (row[Mth::UP][Y] > row[Mth::AT][Z])\r\n\t        {\r\n\t            vTwoSinThetaAxis[Y] = 1.0f + row[Mth::UP][Y];\r\n\t            vTwoSinThetaAxis[Y] = vTwoSinThetaAxis[Y] + vTwoSinThetaAxis[Y];\r\n\t            vTwoSinThetaAxis[Z] = row[Mth::UP][Z] + row[Mth::AT][Y];\r\n\t            vTwoSinThetaAxis[X] = row[Mth::UP][X] + row[Mth::RIGHT][Y];\r\n\t        }\r\n\t        else\r\n\t        {\r\n\t            vTwoSinThetaAxis[Z] = 1.0f + row[Mth::AT][Z];\r\n\t            vTwoSinThetaAxis[Z] = vTwoSinThetaAxis[Z] + vTwoSinThetaAxis[Z];\r\n\t            vTwoSinThetaAxis[X] = row[Mth::AT][X] + row[Mth::RIGHT][Z];\r\n\t            vTwoSinThetaAxis[Y] = row[Mth::AT][Y] + row[Mth::UP][Z];\r\n\t        }\r\n\t    }\r\n\r\n\t\t/*\r\n\t\t * and normalize the axis\r\n\t\t */\r\n\r\n        *pAxis = vTwoSinThetaAxis;\r\n        pAxis->Normalize();\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Matrix::RotateLocal( const Vector &rot )\r\n{\r\n\tif ( rot[ X ] )\r\n\t{\r\n\t\tRotateXLocal( rot[ X ] );\r\n\t}\r\n\tif ( rot[ Y ] )\r\n\t{\r\n\t\tRotateYLocal( rot[ Y ] );\r\n\t}\r\n\tif ( rot[ Z ] )\r\n\t{\r\n\t\tRotateZLocal( rot[ Z ] );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Matrix::PatchOrthogonality (   )\r\n{\r\n\t// Given a matrix m which is assumed to be orthonormal, check to see if it is, and if not then fix it up\r\n\t// returns true if any patching was done\r\n\t\r\n\tfloat lx,ly,lz;\r\n\tlx = (*(Vector*)(row[X])).Length();\r\n\tly = (*(Vector*)(row[Y])).Length();\r\n\tlz = (*(Vector*)(row[Z])).Length();\r\n\r\n\tconst float\tnear1 = 0.99;\r\n\t\r\n\tif (lx < near1)\r\n\t{\r\n\t\tif (ly < near1)\r\n\t\t{\r\n\t\t\tif (lz < near1)\r\n\t\t\t{\r\n\t\t\t\t// everything collapsing to a point!!!\r\n\t\t\t\t// just reset to the identity matrix\r\n\t\t\t\tIdent();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t   // x and y have collapsed, but Z is okay \r\n\t\t\t\tIdent();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (lz < near1)\r\n\t\t\t{\r\n\t\t\t\t// x and z have collapsed, y is okay (most likely situation)\t\t\t\r\n\t\t\t\tIdent();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t   // just x has collapsed, y and z are okay\r\n\t\t\t\t*(Vector*)(row[X]) = Mth::CrossProduct(*(Vector*)(row[Y]),*(Vector*)(row[Z]));\r\n\t\t\t\t(*(Vector*)(row[X])).Normalize();\r\n\t\t\t}\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (ly < near1)\r\n\t\t{\r\n\t\t\tif (lz < near1)\r\n\t\t\t{\r\n\t\t\t\t// y and z collapsed, x is okay\r\n\t\t\t\tIdent();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t   // y has collapsed, x and Z are okay \r\n\t\t\t\t*(Vector*)(row[Y]) = Mth::CrossProduct(*(Vector*)(row[Z]),*(Vector*)(row[X]));\t\r\n\t\t\t\t(*(Vector*)(row[Y])).Normalize();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (lz < near1)\r\n\t\t\t{\r\n\t\t\t\t// just z has collapsed, x and y is okay\r\n\t\t\t\t*(Vector*)(row[Z]) = Mth::CrossProduct(*(Vector*)(row[X]),*(Vector*)(row[Y]));\r\n\t\t\t\t(*(Vector*)(row[Z])).Normalize();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t   // nothing has collapsed\r\n\t\t\t   return false;\r\n\t\t\t}\r\n\t\t}\t\r\n\t}\r\n\t\t\t\t\t\t\t\t\t\t\t  \r\n\treturn true;\t\t\t\t\t\t\t\t\t\t\t  \r\n}\r\n\r\n} // namespace Mth\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Math/matrix.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (MTH)\t\t\t   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/math/Matrix.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t11/29/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t4x4 Matrix Math Class\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_MATH_MATRIX_H\r\n#define __CORE_MATH_MATRIX_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mth\r\n{\r\n\r\n\r\n\r\n\r\nenum\r\n{\r\n\tRIGHT, UP, AT, POS\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/****************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n * Class:\t\t\tMatrix\r\n *\r\n * Description:\t\t4x4 Matrix math class\r\n *\r\n ****************************************************************************/\r\n\r\nclass  Matrix\r\n{\r\n\t\r\n\r\npublic:\r\n\t\t\t\t\tMatrix\t\t\t( void );\r\n\t\t\t\t\tMatrix\t\t\t( const Matrix& src );\r\n\t\t\t\t\tMatrix\t\t\t( const Vector& axis, const float angle );\r\n\t\t\t\t\tMatrix\t\t\t( int axis, const float angle );\r\n\t\t\t\t\tMatrix\t\t\t( float p, float h, float r );\t// Euler to Matrix\r\n                    Matrix          ( const Mth::Quat& orientaion );\r\n\t\t\t\t\t\t\r\n\tMatrix& \t\toperator=\t\t( const Matrix& src );\r\n\tMatrix&\t\t\toperator+=\t\t( const Matrix& n );\r\n\tMatrix&\t\t\toperator*=\t\t( const Matrix& n );\r\n\tMatrix&\t\t\toperator*=\t\t( const float f );\r\n\tbool\t\t\toperator==\t\t( const Matrix& n ) const;\r\n\tbool\t\t\toperator!=\t\t( const Matrix& n ) const;\r\n\r\n\tfloat\t\t\tDeterminant\t\t( void ) const;\r\n\tbool\t\t\tIsIdent\t\t\t( void ) const;\r\n\tMatrix&\t\t\tIdent\t\t\t( void );\t\t\t\t\t// set to 4x4 identity\r\n\tMatrix&\t\t\tIdentity\t\t( void );\t\t\t\t\t// same, but better name\r\n\tMatrix&\t\t\tZero\t\t\t( void );\t\t\t\t\t// set to all 0's\r\n\tMatrix&\t\t\tAdjoint\t\t\t( const Matrix& src );\r\n\tMatrix&\t\t\tInvert\t\t\t( const Matrix& src );\t\t// this = Invert ( src )\r\n\tMatrix&\t\t\tInvert\t\t\t( void );\t\t\t \t  \t// this = Invert ( this )\r\n\tMatrix&\t\t\tInvertUniform \t( void );\r\n\tMatrix&\t\t\tTranspose\t\t( const Matrix& src );\r\n\tMatrix&\t\t\tTranspose\t\t( void );\r\n\r\n\tVector\t\t\tTransform\t\t( const Vector& src ) const;\r\n\tVector\t\t\tTransformAsPos\t( const Vector& src ) const;\r\n\tVector\t\t\tRotate\t\t\t( const Vector& src ) const;\r\n\r\n\tMatrix&\t\t\tOrthoNormalize\t( const Matrix& src );\t\t// this = OrthoNornalize ( src )\r\n\tMatrix&\t\t\tOrthoNormalize\t( void );\t\t\t\t\t// this = OrthoNormalize ( this )\r\n\r\n\tvoid\t\t\tRotateLocal\t\t( const Vector& src );\r\n\tMatrix&\t\t\tTranslate\t\t( const Vector& trans );\r\n\tMatrix&\t\t\tTranslateLocal\t( const Vector& trans );\r\n\t\r\n\tMatrix&\t\t\tRotate\t\t\t( const Vector& axis, const float angle );\r\n\tMatrix&\t\t\tRotateLocal\t\t( const Vector& axis, const float angle );\r\n\tMatrix&\t\t\tRotateLocal\t\t( int axis, float angle );\r\n\tMatrix&\t\t\tRotateX\t\t\t( const float angle );\r\n\tMatrix&\t\t\tRotateXLocal\t( const float angle );\r\n\tMatrix&\t\t\tRotateY\t\t\t( const float angle );\r\n\tMatrix&\t\t\tRotateYLocal\t( const float angle );\r\n\tMatrix&\t\t\tRotateZ\t\t\t( const float angle );\r\n\tMatrix&\t\t\tRotateZLocal\t( const float angle );\r\n\r\n\tMatrix&\t\t\tScale\t\t\t( const Vector& scale );\r\n\tMatrix&\t\t\tScaleLocal\t\t( const Vector& scale );\r\n\t\r\n\tVector&\t\t\tGetRight\t\t( void ) { return *(Vector*)(&row[RIGHT]); }\r\n\tVector&\t\t\tGetUp\t\t\t( void ) { return *(Vector*)(&row[UP]); }\r\n\tVector&\t\t\tGetAt\t\t\t( void ) { return *(Vector*)(&row[AT]); }\r\n\tVector&\t\t\tGetPos\t\t\t( void ) { return *(Vector*)(&row[POS]); }\r\n\tvoid\t\t\tSetPos\t\t\t( const Vector& trans );\r\n\r\n\r\n\tMatrix&\t\t\tSetColumn\t\t( sint i, const Vector& v );\r\n\tVector\t\t\tGetColumn\t\t( sint i ) const;\r\n\tconst Vector&\toperator[]\t\t( sint i ) const;\r\n\tVector&\t\t\toperator[]\t\t( sint i );\r\n\r\n\tMatrix&\t\t\tOrthoNormalizeAbout(int r0);\r\n\tvoid\t\t\tPrintContents() const;\r\n\r\n\tvoid\t\t\tGetEulers( Vector& euler ) const;\r\n\tvoid\t\t\tGetRotationAxisAndAngle( Vector* pAxis, float* pRadians );\r\n\t\r\n\tbool\t\t\tPatchOrthogonality (   );\r\n\t\r\n\tMatrix&\t\t\tSetFromAngles\t( const Vector& angles );\r\n\r\nprivate:\r\n\r\n\t\t\t\tenum\r\n\t\t\t\t{\r\n\t\t\t\t\tNUM_ELEMENTS = 4\r\n\t\t\t\t};\r\n\r\n//\tVector\t\trow[NUM_ELEMENTS];\t   \t\t// Old style, an array of vectors\r\n\tfloat\t\trow[NUM_ELEMENTS][4];\t\t// New style, an array of float, for constructor optimization\r\n\r\n} nAlign(128);\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Inline Functions  \t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef\t__PLAT_NGPS__\r\nvoid xsceVu0MulMatrix(Mth::Matrix* m0, Mth::Matrix* m1, const Mth::Matrix* m2);\r\n#endif\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\t\tSwap ( Matrix& a, Matrix& b );\r\nvoid\t\tSlerp ( Matrix& result, const Matrix& s1, const Matrix& s2, float t );\r\nMatrix\t\toperator* ( const Matrix& m1, const Matrix& m2 );\r\nostream& \toperator<< ( ostream& os, const Matrix& m );\r\n\r\nMatrix&\t\tCreateRotateMatrix ( Matrix& mat, const Vector& axis, const float angle );\r\nMatrix&\t\tCreateRotateMatrix ( Matrix& mat, int axis, const float angle );\r\nMatrix&\t\tCreateRotateXMatrix ( Matrix& mat, const float angle );\r\nMatrix&\t\tCreateRotateYMatrix ( Matrix& mat, const float angle );\r\nMatrix&\t\tCreateRotateZMatrix ( Matrix& mat, const float angle );\r\nMatrix&\t\tCreateFromToMatrix( Matrix &mtx, Vector from, Vector to );\r\n\r\nMatrix&\t\tCreateMatrixLookAt( Matrix& mat, const Vector& pos, const Vector& lookat, const Vector& up );\r\nMatrix&\t\tCreateMatrixOrtho( Matrix& mat, float width, float height, float f_near, float f_far );\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Mth\r\n\r\n#endif // __CORE_MATH_MATRIX_H\r\n\r\n"
  },
  {
    "path": "Code/Core/Math/matrix.inl",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (Mth)\t\t\t   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/math/Matrix.inl\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t11/23/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t4x4 Matrix Math Class\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_MATH_MATRIX_INL\r\n#define __CORE_MATH_MATRIX_INL\r\n\r\nnamespace Mth\r\n{\r\n\t\t\t\t\t\t  \r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Inline Functions  \t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tPublic Inline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\tMatrix::Ident ( void )\r\n{\r\n\trow[X][X] = 1.0f;\r\n\trow[X][Y] = 0.0f;\r\n\trow[X][Z] = 0.0f;\r\n\trow[X][W] = 0.0f;\r\n\r\n\trow[Y][X] = 0.0f;\r\n\trow[Y][Y] = 1.0f;\r\n\trow[Y][Z] = 0.0f;\r\n\trow[Y][W] = 0.0f;\r\n\r\n\trow[Z][X] = 0.0f;\r\n\trow[Z][Y] = 0.0f;\r\n\trow[Z][Z] = 1.0f;\r\n\trow[Z][W] = 0.0f;\r\n\r\n\trow[W][X] = 0.0f;\r\n\trow[W][Y] = 0.0f;\r\n\trow[W][Z] = 0.0f;\r\n\trow[W][W] = 1.0f;\r\n\r\n\treturn *this;\r\n}\r\n\r\n\r\ninline Matrix::Matrix( void )\r\n{\r\n\r\n#ifdef\t\tDEBUG_UNINIT_VECTORS\r\n// For debugging uninitialized vectors, we set them to a magic value\r\n// and then the vector code should assert when they are accessed\r\n// via the [] operator, which casts a row to a vector\t\r\n\t*((uint32*)(&row[X][X])) = 0x7F800010;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[X][Y])) = 0x7F800011;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[X][Z])) = 0x7F800012;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[X][W])) = 0x7F800013;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[Y][X])) = 0x7F800014;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[Y][Y])) = 0x7F800015;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[Y][Z])) = 0x7F800016;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[Y][W])) = 0x7F800017;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[Z][X])) = 0x7F800018;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[Z][Y])) = 0x7F800019;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[Z][Z])) = 0x7F80001a;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[Z][W])) = 0x7F80001b;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[W][X])) = 0x7F80001c;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[W][Y])) = 0x7F80001d;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[W][Z])) = 0x7F80001e;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n\t*((uint32*)(&row[W][W])) = 0x7F80001f;\t\t\t\t// Positive NANS (Not A Number - Signaling)\t\r\n#else\r\n#ifdef\t__INITIALIZE_VECTORS__\r\n\tIdent();\t\r\n\r\n#endif\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix::Matrix( const Vector& axis, const float angle )\r\n{\r\n\t\r\n\r\n\tCreateRotateMatrix( *this, axis, angle );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix::Matrix( int axis, const float angle )\r\n{\r\n\t\r\n\r\n\tCreateRotateMatrix( *this, axis, angle );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix::Matrix( const Mth::Quat &orientation )\r\n{\r\n    orientation.GetMatrix(*this);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Vector&\tMatrix::operator[] ( sint i ) const\r\n{ \r\n//\tDbg_MsgAssert (( i >= X && i < NUM_ELEMENTS ),( \"index out of range\" ));\r\n\treturn *(Vector*)(row[i]);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\t\tMatrix::operator[] ( sint i )\r\n{ \r\n//\tDbg_MsgAssert (( i >= X && i < NUM_ELEMENTS ),( \"index out of range\" ));\r\n\treturn *(Mth::Vector*)(&row[i]);\r\n}\r\n\r\n\r\n/*\r\n#ifdef\t__USE_VU0__\r\ninline void asm_copy(void* m0, void* m1)\r\n{\r\n\tasm __volatile__(\"\r\n\tlq    $6,0x0(%1)\r\n\tlq    $7,0x10(%1)\r\n\tlq    $8,0x20(%1)\r\n\tlq    $9,0x30(%1)\r\n\tsq    $6,0x0(%0)\r\n\tsq    $7,0x10(%0)\r\n\tsq    $8,0x20(%0)\r\n\tsq    $9,0x30(%0)\r\n\t\": : \"r\" (m0) , \"r\" (m1):\"$6\",\"$7\",\"$8\",\"$9\");\r\n}\r\n#endif\r\n*/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t\t\r\ninline Matrix& \t\tMatrix::operator= ( const Matrix& src )\r\n{\r\n#ifdef\t__USE_VU0__\r\n// Mick:  This actually is faster than the asm_copy method as\r\n// the compiler can optimize it better\t\r\n\t*((uint128 *)&row[0])=*((uint128 *)&src[0]);\r\n\t*((uint128 *)&row[1])=*((uint128 *)&src[1]);\r\n\t*((uint128 *)&row[2])=*((uint128 *)&src[2]);\r\n\t*((uint128 *)&row[3])=*((uint128 *)&src[3]);\r\n\t// asm_copy(this,(void*)&src[0]);\r\n#else\r\n\t*(Vector*)row[X]\t= *(Vector*)src.row[X];\r\n\t*(Vector*)row[Y]\t= *(Vector*)src.row[Y];\r\n\t*(Vector*)row[Z] \t= *(Vector*)src.row[Z]; \r\n\t*(Vector*)row[W]\t= *(Vector*)src.row[W];\r\n#endif\r\n\treturn *this;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix::Matrix( const Matrix& src )\r\n{\r\n\t*this = src;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\tSwap ( Matrix& a, Matrix& b )\r\n{\r\n\tMatrix t = a;\r\n\ta = b;\r\n\tb = t;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\tMatrix::operator*= ( const Matrix& n )\r\n{\t\r\n#\tifdef __PLAT_XBOX__\r\n\tD3DXMatrixMultiply((D3DXMATRIX*)this, (D3DXMATRIX*)this, (D3DXMATRIX*)&n );\r\n#\telse\r\n#ifdef\t__USE_VU0__\r\n\tsceVu0MulMatrix((sceVu0FVECTOR*)this,(sceVu0FVECTOR*)&n,(sceVu0FVECTOR*)this);\t\r\n#\telse\r\n\r\n\tVector\tvec;\r\n\r\n\tvec[X] = row[X][X] * n[X][X] + row[X][Y] * n[Y][X] + row[X][Z] * n[Z][X] + row[X][W] * n[W][X];\r\n\tvec[Y] = row[X][X] * n[X][Y] + row[X][Y] * n[Y][Y] + row[X][Z] * n[Z][Y] + row[X][W] * n[W][Y];\r\n\tvec[Z] = row[X][X] * n[X][Z] + row[X][Y] * n[Y][Z] + row[X][Z] * n[Z][Z] + row[X][W] * n[W][Z];\r\n\tvec[W] = row[X][X] * n[X][W] + row[X][Y] * n[Y][W] + row[X][Z] * n[Z][W] + row[X][W] * n[W][W];\r\n\t*(Vector*)row[X] = vec;\r\n\r\n\tvec[X] = row[Y][X] * n[X][X] + row[Y][Y] * n[Y][X] + row[Y][Z] * n[Z][X] + row[Y][W] * n[W][X];\r\n\tvec[Y] = row[Y][X] * n[X][Y] + row[Y][Y] * n[Y][Y] + row[Y][Z] * n[Z][Y] + row[Y][W] * n[W][Y];\r\n\tvec[Z] = row[Y][X] * n[X][Z] + row[Y][Y] * n[Y][Z] + row[Y][Z] * n[Z][Z] + row[Y][W] * n[W][Z];\r\n\tvec[W] = row[Y][X] * n[X][W] + row[Y][Y] * n[Y][W] + row[Y][Z] * n[Z][W] + row[Y][W] * n[W][W];\r\n\t*(Vector*)row[Y] = vec;\r\n\r\n\tvec[X] = row[Z][X] * n[X][X] + row[Z][Y] * n[Y][X] + row[Z][Z] * n[Z][X] + row[Z][W] * n[W][X];\r\n\tvec[Y] = row[Z][X] * n[X][Y] + row[Z][Y] * n[Y][Y] + row[Z][Z] * n[Z][Y] + row[Z][W] * n[W][Y];\r\n\tvec[Z] = row[Z][X] * n[X][Z] + row[Z][Y] * n[Y][Z] + row[Z][Z] * n[Z][Z] + row[Z][W] * n[W][Z];\r\n\tvec[W] = row[Z][X] * n[X][W] + row[Z][Y] * n[Y][W] + row[Z][Z] * n[Z][W] + row[Z][W] * n[W][W];\r\n\t*(Vector*)row[Z] = vec;\r\n\r\n\tvec[X] = row[W][X] * n[X][X] + row[W][Y] * n[Y][X] + row[W][Z] * n[Z][X] + row[W][W] * n[W][X];\r\n\tvec[Y] = row[W][X] * n[X][Y] + row[W][Y] * n[Y][Y] + row[W][Z] * n[Z][Y] + row[W][W] * n[W][Y];\r\n\tvec[Z] = row[W][X] * n[X][Z] + row[W][Y] * n[Y][Z] + row[W][Z] * n[Z][Z] + row[W][W] * n[W][Z];\r\n\tvec[W] = row[W][X] * n[X][W] + row[W][Y] * n[Y][W] + row[W][Z] * n[Z][W] + row[W][W] * n[W][W];\r\n\t*(Vector*)row[W] = vec;\r\n#\tendif\r\n#\tendif\r\n\r\n\treturn *this;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix\toperator* ( const Matrix& m1, const Matrix& m2 )\r\n{\r\n\t\r\n\t\r\n\tMatrix\tresult = m1;\r\n\tresult *= m2;\r\n\r\n\treturn result;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix& \t\tMatrix::operator*= ( const float s )\r\n{\t\r\n\t\r\n\t\r\n\tif ( s != 1.0f )\r\n\t{\r\n\t\t*(Vector*)(row[X]) *= s;\r\n\t\t*(Vector*)(row[Y]) *= s;\r\n\t\t*(Vector*)(row[Z]) *= s;\r\n\t\t*(Vector*)(row[W]) *= s;\r\n\t}\r\n\r\n\treturn *this;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix& \t\tMatrix::operator+= ( const Matrix& n )\r\n{\t\r\n\trow[X][X] += n[X][X];\r\n\trow[X][Y] += n[X][Y];\r\n\trow[X][Z] += n[X][Z];\r\n\trow[X][W] += n[X][W];\r\n\r\n\trow[Y][X] += n[Y][X];\r\n\trow[Y][Y] += n[Y][Y];\r\n\trow[Y][Z] += n[Y][Z];\r\n\trow[Y][W] += n[Y][W];\r\n\r\n\trow[Z][X] += n[Z][X];\r\n\trow[Z][Y] += n[Z][Y];\r\n\trow[Z][Z] += n[Z][Z];\r\n\trow[Z][W] += n[Z][W];\r\n\r\n\trow[W][X] += n[W][X];\r\n\trow[W][Y] += n[W][Y];\r\n\trow[W][Z] += n[W][Z];\r\n\trow[W][W] += n[W][W];\r\n\r\n\treturn *this;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\tMatrix::operator== ( const Matrix& n ) const\r\n{\r\n\t\r\n\r\n\tfor ( sint i = 0; i < NUM_ELEMENTS; i++ )\r\n\t{\r\n\t\tfor ( sint j = 0; j < NUM_ELEMENTS; j++ )\r\n\t\t{\r\n\t\t\tif ( row[i][j] != n[i][j] )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\tMatrix::operator!= ( const Matrix& n ) const\r\n{\r\n\t\r\n\r\n\treturn !( *this == n );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float\t\t\tMatrix::Determinant ( void ) const\r\n{\r\n\t\r\n\r\n    return row[X][X] * Determinant3 ( row[Y][Y], row[Z][Y], row[W][Y], row[Y][Z], row[Z][Z], row[W][Z], row[Y][W], row[Z][W], row[W][W] )\r\n         - row[X][Y] * Determinant3 ( row[Y][X], row[Z][X], row[W][X], row[Y][Z], row[Z][Z], row[W][Z], row[Y][W], row[Z][W], row[W][W] )\r\n         + row[X][Z] * Determinant3 ( row[Y][X], row[Z][X], row[W][X], row[Y][Y], row[Z][Y], row[W][Y], row[Y][W], row[Z][W], row[W][W] )\r\n         - row[X][W] * Determinant3 ( row[Y][X], row[Z][X], row[W][X], row[Y][Y], row[Z][Y], row[W][Y], row[Y][Z], row[Z][Z], row[W][Z] );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\tMatrix::IsIdent\t( void ) const\r\n{\r\n\t\r\n\r\n\treturn ( row[X][X] == 1.0f && row[X][Y] == 0.0f && row[X][Z] == 0.0f && row[X][W] == 0.0f &&\r\n\t\t     row[Y][X] == 0.0f && row[Y][Y] == 1.0f && row[Y][Z] == 0.0f && row[Y][W] == 0.0f &&\r\n\t\t     row[Z][X] == 0.0f && row[Z][Y] == 0.0f && row[Z][Z] == 1.0f && row[Z][W] == 0.0f &&\r\n\t\t     row[W][X] == 0.0f && row[W][Y] == 0.0f && row[W][Z] == 0.0f && row[W][W] == 1.0f );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\tMatrix::Identity ( void )\r\n{\r\n\trow[X][X] = 1.0f;\r\n\trow[X][Y] = 0.0f;\r\n\trow[X][Z] = 0.0f;\r\n\trow[X][W] = 0.0f;\r\n\r\n\trow[Y][X] = 0.0f;\r\n\trow[Y][Y] = 1.0f;\r\n\trow[Y][Z] = 0.0f;\r\n\trow[Y][W] = 0.0f;\r\n\r\n\trow[Z][X] = 0.0f;\r\n\trow[Z][Y] = 0.0f;\r\n\trow[Z][Z] = 1.0f;\r\n\trow[Z][W] = 0.0f;\r\n\r\n\trow[W][X] = 0.0f;\r\n\trow[W][Y] = 0.0f;\r\n\trow[W][Z] = 0.0f;\r\n\trow[W][W] = 1.0f;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\tMatrix::Zero ( void )\r\n{\r\n\trow[X][X] = 0.0f;\r\n\trow[X][Y] = 0.0f;\r\n\trow[X][Z] = 0.0f;\r\n\trow[X][W] = 0.0f;\r\n\r\n\trow[Y][X] = 0.0f;\r\n\trow[Y][Y] = 0.0f;\r\n\trow[Y][Z] = 0.0f;\r\n\trow[Y][W] = 0.0f;\r\n\r\n\trow[Z][X] = 0.0f;\r\n\trow[Z][Y] = 0.0f;\r\n\trow[Z][Z] = 0.0f;\r\n\trow[Z][W] = 0.0f;\r\n\r\n\trow[W][X] = 0.0f;\r\n\trow[W][Y] = 0.0f;\r\n\trow[W][Z] = 0.0f;\r\n\trow[W][W] = 0.0f;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\tMatrix::Adjoint ( const Matrix& src )\r\n{\r\n\t\r\n\r\n    row[X][X]  =  Determinant3 ( src[Y][Y], src[Z][Y], src[W][Y], src[Y][Z], src[Z][Z], src[W][Z], src[Y][W], src[Z][W], src[W][W] );\r\n    row[Y][X]  = -Determinant3 ( src[Y][X], src[Z][X], src[W][X], src[Y][Z], src[Z][Z], src[W][Z], src[Y][W], src[Z][W], src[W][W] );\r\n    row[Z][X]  =  Determinant3 ( src[Y][X], src[Z][X], src[W][X], src[Y][Y], src[Z][Y], src[W][Y], src[Y][W], src[Z][W], src[W][W] );\r\n    row[W][X]  = -Determinant3 ( src[Y][X], src[Z][X], src[W][X], src[Y][Y], src[Z][Y], src[W][Y], src[Y][Z], src[Z][Z], src[W][Z] );\r\n     \r\n    row[X][Y]  = -Determinant3 ( src[X][Y], src[Z][Y], src[W][Y], src[X][Z], src[Z][Z], src[W][Z], src[X][W], src[Z][W], src[W][W] );\r\n    row[Y][Y]  =  Determinant3 ( src[X][X], src[Z][X], src[W][X], src[X][Z], src[Z][Z], src[W][Z], src[X][W], src[Z][W], src[W][W] );\r\n    row[Z][Y]  = -Determinant3 ( src[X][X], src[Z][X], src[W][X], src[X][Y], src[Z][Y], src[W][Y], src[X][W], src[Z][W], src[W][W] );\r\n    row[W][Y]  =  Determinant3 ( src[X][X], src[Z][X], src[W][X], src[X][Y], src[Z][Y], src[W][Y], src[X][Z], src[Z][Z], src[W][Z] );\r\n        \r\n    row[X][Z]  =  Determinant3 ( src[X][Y], src[Y][Y], src[W][Y], src[X][Z], src[Y][Z], src[W][Z], src[X][W], src[Y][W], src[W][W] );\r\n    row[Y][Z]  = -Determinant3 ( src[X][X], src[Y][X], src[W][X], src[X][Z], src[Y][Z], src[W][Z], src[X][W], src[Y][W], src[W][W] );\r\n    row[Z][Z]  =  Determinant3 ( src[X][X], src[Y][X], src[W][X], src[X][Y], src[Y][Y], src[W][Y], src[X][W], src[Y][W], src[W][W] );\r\n    row[W][Z]  = -Determinant3 ( src[X][X], src[Y][X], src[W][X], src[X][Y], src[Y][Y], src[W][Y], src[X][Z], src[Y][Z], src[W][Z] );\r\n        \r\n    row[X][W]  = -Determinant3 ( src[X][Y], src[Y][Y], src[Z][Y], src[X][Z], src[Y][Z], src[Z][Z], src[X][W], src[Y][W], src[Z][W] );\r\n    row[Y][W]  =  Determinant3 ( src[X][X], src[Y][X], src[Z][X], src[X][Z], src[Y][Z], src[Z][Z], src[X][W], src[Y][W], src[Z][W] );\r\n    row[Z][W]  = -Determinant3 ( src[X][X], src[Y][X], src[Z][X], src[X][Y], src[Y][Y], src[Z][Y], src[X][W], src[Y][W], src[Z][W] );\r\n    row[W][W]  =  Determinant3 ( src[X][X], src[Y][X], src[Z][X], src[X][Y], src[Y][Y], src[Z][Y], src[X][Z], src[Y][Z], src[Z][Z] );\r\n\r\n\treturn *this;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\tMatrix::Invert ( const Matrix& src )\r\n{\r\n\t\r\n\r\n\tAdjoint (src);\r\n\r\n    float det = src.Determinant();\r\n\r\n\tif ( det != 1.0f )\r\n\t{\r\n\t\t*this *= ( 1.0f / det );\r\n\t}\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\tMatrix::Invert ( void )\r\n{\r\n\t\r\n\t\r\n\tMatrix\td;\r\n\r\n\td.Invert( *this );\r\n\r\n\t*this = d;\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef\t__USE_VU0__\r\n// K: Copied from sceVu0InversMatrix, just tweaked to take one param & be inline.\r\n// This is about 18% faster than in C. (1000000 calls take .121 s instead of .148)\r\ninline void Vu0Invert(sceVu0FMATRIX m0)\r\n{\r\n\tasm __volatile__(\"\r\n\tlq $8,0x0000(%0)\r\n\tlq $9,0x0010(%0)\r\n\tlq $10,0x0020(%0)\r\n\tlqc2 vf4,0x0030(%0)\r\n\r\n\tvmove.xyzw vf5,vf4\r\n\tvsub.xyz vf4,vf4,vf4\t\t#vf4.xyz=0;\r\n\tvmove.xyzw vf9,vf4\r\n\tqmfc2    $11,vf4\r\n\r\n\t#]u\r\n\tpextlw     $12,$9,$8\r\n\tpextuw     $13,$9,$8\r\n\tpextlw     $14,$11,$10\r\n\tpextuw     $15,$11,$10\r\n\tpcpyld     $8,$14,$12\r\n\tpcpyud     $9,$12,$14\r\n\tpcpyld     $10,$15,$13\r\n\r\n\tqmtc2    $8,vf6\r\n\tqmtc2    $9,vf7\r\n\tqmtc2    $10,vf8\r\n\r\n\t#\r\n\tvmulax.xyz\tACC,   vf6,vf5\r\n\tvmadday.xyz\tACC,   vf7,vf5\r\n\tvmaddz.xyz\tvf4,vf8,vf5\r\n\tvsub.xyz\tvf4,vf9,vf4\r\n\r\n\tsq $8,0x0000(%0)\r\n\tsq $9,0x0010(%0)\r\n\tsq $10,0x0020(%0)\r\n\tsqc2 vf4,0x0030(%0)\r\n\t\": : \"r\" (m0) :\"$8\",\"$9\",\"$10\",\"$11\",\"$12\",\"$13\",\"$14\",\"$15\");\r\n}\r\n#endif\r\n\r\ninline Matrix&\t\tMatrix::InvertUniform ()\r\n{\r\n\t\r\n\t\r\n\t// Only works for orthonormal Matrix\r\n\t\t\t\r\n\t#if 0\t// (Mike) this version is buggy!\r\n\t\r\n\tTranspose ( src );\r\n\t\r\n\trow[POS][X] = -DotProduct ( src[POS], src[RIGHT] );\r\n\trow[POS][Y] = -DotProduct ( src[POS], src[UP] );\r\n\trow[POS][Z] = -DotProduct ( src[POS], src[AT] );\r\n\t\r\n\treturn *this;\r\n\r\n\t#else\t// (Mike) try this one instead...\r\n\t\r\n\t// (Dan) actually, don't use the vu0; it returns before the correct values are safely stored in memory; if you access the results too\r\n\t// quickly, you get the wrong answers; this is because the compiler may reorder instructions\r\n\t#if 0\r\n\t// (Ken) or try this one, uses vu0 \r\n\tVu0Invert((sceVu0FMATRIX)this);\r\n\treturn *this;\r\n\t#else\r\n\t\r\n\t// need to copy the old row,\r\n\t// or else it will change on us as we're doing\r\n\t// our dot products...\r\n\t\r\n\tMth::Vector oldPos = *(Vector*)row[POS];\r\n\r\n\trow[POS][X] = -DotProduct ( oldPos, *(Vector*)row[RIGHT] );\r\n\trow[POS][Y] = -DotProduct ( oldPos, *(Vector*)row[UP] );\r\n\trow[POS][Z] = -DotProduct ( oldPos, *(Vector*)row[AT] );\r\n\r\n\tSwap ( row[X][Y], row[Y][X] );\r\n\tSwap ( row[X][Z], row[Z][X] );\r\n\tSwap ( row[Y][Z], row[Z][Y] );\r\n\r\n\treturn *this;\r\n\t\r\n\t#endif\r\n\t\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline Matrix&\t\t\tMatrix::Transpose ( void )\r\n{\r\n\t\r\n\r\n\tSwap ( row[X][Y], row[Y][X] );\r\n\tSwap ( row[X][Z], row[Z][X] );\r\n\tSwap ( row[X][W], row[W][X] );\r\n\tSwap ( row[Y][Z], row[Z][Y] );\r\n\tSwap ( row[Y][W], row[W][Y] );\r\n\tSwap ( row[Z][W], row[W][Z] );\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline Matrix&\t\t\tMatrix::Transpose ( const Matrix& src )\r\n{\r\n\t\r\n\r\n\tif ( &src == this )\r\n\t{\r\n\t\treturn Transpose();\r\n\t}\r\n\r\n\trow[X][X] = src[X][X];\r\n\trow[X][Y] = src[Y][X];\r\n\trow[X][Z] = src[Z][X];\r\n\trow[X][W] = src[W][X];\r\n\trow[Y][X] = src[X][Y];\r\n\trow[Y][Y] = src[Y][Y];\r\n\trow[Y][Z] = src[Z][Y];\r\n\trow[Y][W] = src[W][Y];\r\n\trow[Z][X] = src[X][Z];\r\n\trow[Z][Y] = src[Y][Z];\r\n\trow[Z][Z] = src[Z][Z];\r\n\trow[Z][W] = src[W][Z];\r\n\trow[W][X] = src[X][W];\r\n\trow[W][Y] = src[Y][W];\r\n\trow[W][Z] = src[Z][W];\r\n\trow[W][W] = src[W][W];\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline Vector\t\t\tMatrix::Transform ( const Vector& src ) const\r\n{\r\n\t\r\n\t\t\r\n\tVector\tv;\r\n\r\n\t#ifdef\t__USE_VU0__\r\n\tsceVu0ApplyMatrix((float*)&v,(sceVu0FVECTOR*)this,(float*)&src);\r\n\t#else\r\n\r\n\tv[X] = src[X] * row[RIGHT][X] + src[Y] * row[UP][X] + src[Z] * row[AT][X] + src[W] * row[POS][X];\r\n\tv[Y] = src[X] * row[RIGHT][Y] + src[Y] * row[UP][Y] + src[Z] * row[AT][Y] + src[W] * row[POS][Y];\r\n\tv[Z] = src[X] * row[RIGHT][Z] + src[Y] * row[UP][Z] + src[Z] * row[AT][Z] + src[W] * row[POS][Z];\r\n\tv[W] = src[X] * row[RIGHT][W] + src[Y] * row[UP][W] + src[Z] * row[AT][W] + src[W] * row[POS][W];\r\n\r\n\t#endif\r\n\t\r\n\treturn v;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline Vector\t\t\tMatrix::TransformAsPos ( const Vector& src ) const\r\n{\r\n\t\r\n\tVector\tv;\r\n\r\n\tv[X] = src[X] * row[RIGHT][X] + src[Y] * row[UP][X] + src[Z] * row[AT][X] + row[POS][X];\r\n\tv[Y] = src[X] * row[RIGHT][Y] + src[Y] * row[UP][Y] + src[Z] * row[AT][Y] + row[POS][Y];\r\n\tv[Z] = src[X] * row[RIGHT][Z] + src[Y] * row[UP][Z] + src[Z] * row[AT][Z] + row[POS][Z];\r\n\tv[W] = src[X] * row[RIGHT][W] + src[Y] * row[UP][W] + src[Z] * row[AT][W] + row[POS][W];\r\n\r\n\treturn v;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline Vector\t\t\tMatrix::Rotate ( const Vector& src ) const\r\n{\r\n\t\r\n\t\t\r\n\tVector\tv;\r\n\r\n\tv[X] = src[X] * row[RIGHT][X] + src[Y] * row[UP][X] + src[Z] * row[AT][X];\r\n\tv[Y] = src[X] * row[RIGHT][Y] + src[Y] * row[UP][Y] + src[Z] * row[AT][Y];\r\n\tv[Z] = src[X] * row[RIGHT][Z] + src[Y] * row[UP][Z] + src[Z] * row[AT][Z];\r\n\tv[W] = src[W];\r\n\t\r\n\treturn v;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline Matrix&\t\t\tMatrix::Translate( const Vector& trans )\r\n{\r\n\t\r\n\r\n\t*(Vector*)(row[POS]) += trans;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Ken: Added cos I needed it.\r\ninline void\tMatrix::SetPos( const Vector& trans )\r\n{\r\n\t*(Vector*)(row[POS]) = trans;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline Matrix&\t\t\tMatrix::TranslateLocal( const Vector& trans )\r\n{\r\n\t\r\n\r\n\tVector&\tvec = *(Vector*)(row[POS]);\r\n\r\n\tvec[X] +=  (( trans[X] * row[RIGHT][X] ) +\r\n\t\t\t\t( trans[Y] * row[UP][X] ) +\r\n\t\t\t\t( trans[Z] * row[AT][X] ));\r\n\r\n\tvec[Y] +=  (( trans[X] * row[RIGHT][Y] ) +\r\n\t\t\t\t( trans[Y] * row[UP][Y] ) +\r\n\t\t\t\t( trans[Z] * row[AT][Y] ));\r\n\r\n\tvec[Z] +=  (( trans[X] * row[RIGHT][Z] ) +\r\n\t\t\t\t( trans[Y] * row[UP][Z] ) +\r\n\t\t\t\t( trans[Z] * row[AT][Z] ));\r\n\r\n\treturn *this;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\t\tMatrix::Rotate( const Vector& axis, const float angle )\r\n{\r\n\t\r\n\r\n\tMatrix\trot_mat( axis, angle );\r\n\r\n\t*this *= rot_mat;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\t\tMatrix::RotateLocal( const Vector& axis, const float angle )\r\n{\r\n\t\r\n\r\n\tMatrix\trot_mat( axis, angle );\r\n\r\n\t*this = rot_mat * *this;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\t\tMatrix::RotateLocal( int axis, const float angle )\r\n{\r\n\t\r\n\r\n\tMatrix\trot_mat( axis, angle );\r\n\r\n\t*this = rot_mat * *this;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\tMatrix::RotateX( const float angle )\r\n{\r\n\t\r\n\tMatrix rotX;\r\n\r\n\t*this *= CreateRotateXMatrix( rotX, angle );\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\tMatrix::RotateXLocal( const float angle )\r\n{\r\n\t\r\n\tMatrix rotX;\r\n\r\n\t*this = CreateRotateXMatrix( rotX, angle ) * *this;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\tMatrix::RotateY( const float angle )\r\n{\r\n\t\r\n\tMatrix rotY;\r\n\r\n\t*this *= CreateRotateYMatrix( rotY, angle );\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\tMatrix::RotateYLocal( const float angle )\r\n{\r\n\t\r\n\t#ifdef\t__USE_VU0__\r\n\t\r\n\t// Use the end of SCache for a quick and easy speed increase.\r\n\t// (Mick, changed to use the end, so start can be used for permanent stuff)\r\n\tMatrix *p_rot_y=(Matrix*)(0x70004000-4*4*4);\r\n\r\n\t*this = CreateRotateYMatrix( *p_rot_y, angle ) * *this;\r\n\t\r\n\t#else\r\n\t\r\n\tMatrix rotY;\r\n\t*this = CreateRotateYMatrix( rotY, angle ) * *this;\r\n\t\r\n\t#endif\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\tMatrix::RotateZ( const float angle )\r\n{\r\n\t\r\n\r\n\tMatrix rotZ;\r\n\r\n\t*this *= CreateRotateZMatrix( rotZ, angle );\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\tMatrix::RotateZLocal( const float angle )\r\n{\r\n\t\r\n\r\n\tMatrix rotZ;\r\n\r\n\t*this = CreateRotateZMatrix( rotZ, angle ) * *this;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline Matrix& Matrix::Scale( const Vector& scale )\r\n{\r\n\t\r\n\t\r\n\t*(Vector*)(row[RIGHT]) *= scale;\r\n\t*(Vector*)(row[UP]) *= scale;\r\n\t*(Vector*)(row[AT]) *= scale;\r\n\t*(Vector*)(row[POS]) *= scale;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline Matrix& Matrix::ScaleLocal( const Vector& scale )\r\n{\r\n\t\r\n\r\n\t*(Vector*)(row[RIGHT]) *= scale[X];\r\n\t*(Vector*)(row[UP]) *= scale[Y];\r\n\t*(Vector*)(row[AT]) *= scale[Z];\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline Matrix&\t\t\tMatrix::SetColumn ( sint i,  const Vector& v )\r\n{\r\n\t\r\n\t\r\n//\tDbg_MsgAssert (( i >= X && i < NUM_ELEMENTS ),( \"index out of range\" ));\r\n\t\r\n\trow[X][i] = v[X]; \r\n\trow[Y][i] = v[Y]; \r\n\trow[Z][i] = v[Z]; \r\n\trow[W][i] = v[W];\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector\t\t\tMatrix::GetColumn ( sint i ) const\t\r\n{\r\n\t\r\n\t\r\n//\tDbg_MsgAssert (( i >= X && i < NUM_ELEMENTS ),( \"index out of range\" ));\r\n\t\r\n\treturn Vector ( row[X][i], row[Y][i], row[Z][i], row[W][i] );\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline ostream& operator<<\t( ostream& os, const Matrix& m )\r\n{\r\n\treturn os << \"{ \" << m[X] << \",\\n \" << m[Y] << \",\\n \" << m[Z] << \",\\n \" << m[W] << \" }\";\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Matrix&\t\t\tMatrix::SetFromAngles ( const Vector& angles )\r\n{\r\n\tIdentity();\r\n\tif (angles[X] != 0.0f || angles[Y] != 0.0f || angles[Z] != 0.0f)\r\n\t{\r\n\t\tRotateX(angles[X]);\r\n\t\tRotateY(angles[Y]);\r\n\t\tRotateZ(angles[Z]);\r\n\t}\r\n\treturn *this;\r\n}\r\n\r\n} // namespace Mth\r\n\r\n#endif // __CORE_MATH_MATRIX_INL\r\n\r\n"
  },
  {
    "path": "Code/Core/Math/quat.h",
    "content": "/*****************************************************************************\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (MTH)\t\t\t   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/math/Quat.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t11/23/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tQuaternion Math Class\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_MATH_QUAT_H\r\n#define __CORE_MATH_QUAT_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/math/vector.h>\t\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mth\r\n{\r\n \r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Matrix;\t// forward declaration\r\n\r\n/****************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n * Class:\t\t\tQuat\r\n *\r\n * Description:\t\tQuaternion math class\r\n *\r\n ****************************************************************************/\r\n\r\nclass  Quat  //: public Spt::Class\r\n{\r\n\t\r\n\r\npublic:\r\n\r\n\tfriend\tbool\tquat_equal ( const Quat& q1, const Quat& q2, const float tol );\r\n\r\n\t\t\t\t\tQuat ( float cx = 0.0f, float cy = 0.0f, float cz = 0.0f, float cw = 1.0f ); \r\n\r\n\t\t\t\t\tQuat ( const Vector& axis, float angle );\r\n\t\t\t\t\tQuat ( const Matrix& mat );\r\n\r\n\t\t\tQuat&\tInvert ( void );\r\n\t\t\tQuat&\tInvert ( const Quat& src );\r\n\t\t\tfloat\tModulus\t( void );\r\n\t\t\tfloat\tModulusSqr ( void ) const;\r\n\t\t\tQuat&\tNormalize\t( float len = 1.0f );\r\n\t\t\tVector\tRotate\t( const Vector& vec ) const;\r\n\t\t\t\r\n\t\t\tvoid\tSetScalar ( const float w );\r\n\t\t\tvoid\tSetVector ( const float x, const float y, const float z );\r\n\t\t\tvoid\tSetVector ( const Vector& v );\r\n\tconst\tfloat&\tGetScalar ( void ) const;\r\n\tconst\tVector&\tGetVector ( void ) const { return quat;\t}\r\n\t\t\r\n\t\t\tvoid\tGetMatrix ( Matrix& mat ) const;\r\n\r\n\t\t\tQuat&\toperator= ( const Quat& q );\r\n\t\t\tQuat&\toperator+= ( const Quat& q );\r\n\t\t\tQuat&\toperator-= ( const Quat& q );\r\n\t\t\tQuat&\toperator*= ( const Quat& q );\r\n\t\t\tQuat&\toperator*= ( float s );\r\n\t\t\tQuat&\toperator/= ( float s );\r\n\tconst\tfloat&\toperator[] ( sint i ) const;\r\n\t\t\tfloat&\toperator[] ( sint i );\r\n\r\n\t\t\t\r\nprivate:\r\n\r\n\t\t\tVector\tquat; \t\t// X,Y,Z : Imaginary (Vector) component\r\n\t\t\t\t\t\t\t\t// W\t : Real (Scalar) component\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Inline Functions  \t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nQuat\t\toperator+\t( const Quat& q1, const Quat& q2 );\r\nQuat\t\toperator-\t( const Quat& q1, const Quat& q2 );\r\nQuat\t\toperator* ( const Quat& q1, const Quat& q2 );\r\nQuat\t\toperator* ( const Quat& q, const float s );\r\nQuat\t\toperator* ( const float s, const Quat& q );\t  \r\nQuat\t\toperator- ( const Quat& q ); // negate all elements -> equilavent rotation\r\nfloat\t\tDotProduct ( const Quat& v1, const Quat& v2 );\r\nQuat\t\tSlerp ( const Quat& q1, const Quat& q2, const float t );\r\nQuat\t\tFastSlerp( Quat& qIn1, Quat& qIn2, const float t );\r\nbool\t\tEqual ( const Quat& q1, const Quat& q2, const float tol = 0.0001f );\r\nostream& \toperator<< ( ostream& os, const Quat& v );\r\nQuat\t\tEulerToQuat( const Vector& v );\r\n\r\n// converts a quat+vector xform into a matrix xform\r\nvoid QuatVecToMatrix( Mth::Quat* pQ, Mth::Vector* pT, Mth::Matrix* pMatrix );\r\nvoid SCacheQuatVecToMatrix( Mth::Quat* pQ, Mth::Vector* pT, Mth::Matrix* pMatrix );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Mth\r\n\r\n#endif // __CORE_MATH_QUAT_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Math/quat.inl",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (Mth)\t\t\t   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/math/Quat.inl\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t11/23/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tQuaternion Math Class\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_MATH_QUAT_INL\r\n#define __CORE_MATH_QUAT_INL\r\n\r\nnamespace Mth\r\n{\r\n\t\t\t\t\t\t\t  \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const float&\t\tQuat::operator[] ( sint i ) const\r\n{\r\n\t\r\n\t\r\n\treturn quat[i];\r\n}\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Inline Functions  \t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline\tbool\t\tquat_equal( const Quat& q1, const Quat& q2, const float tol )\r\n{\t\r\n\t\r\n\t\r\n\treturn ( Equal( q1.quat, q2.quat, tol ));\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tPublic Inline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline Quat::Quat( float cx, float cy, float cz, float cw )\r\n: quat( cx, cy, cz, cw )\r\n{\r\n\t\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Quat::Quat( const Vector& axis, float angle )\r\n{\r\n\t\r\n\r\n\tfloat\tmod = axis.Length();\r\n\tfloat\tang = angle / 2.0f;\r\n\r\n\tmod  = ( mod > 0.0f ) ? ( 1.0f / mod ) : 0.0f;\r\n\tmod *= sinf( ang );\r\n\t\r\n\tSetVector( mod * axis[X], mod * axis[Y], mod * axis[Z] );\r\n\tSetScalar( cosf ( ang ));\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float&\t\t\tQuat::operator[] ( sint i )\r\n{\r\n\t\r\n\t\r\n\treturn quat[i];\r\n}\r\n\r\n\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\r\ninline Quat::Quat( const Matrix& m )\r\n{\r\n\t\r\n\t\r\n\tfloat t = m[X][X] + m[Y][Y] + m[Z][Z];\t\r\n\tfloat trace;\r\n\r\n\tif ( t > 0.0f )\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t{\r\n\t\ttrace = sqrtf( t + 1.0f );\r\n\t\t\r\n\t\tSetScalar( trace * 0.5f );\r\n\t\ttrace = 0.5f / trace;\r\n\t\t\r\n\t\tSetVector(( m[Z][Y] - m[Y][Z] ) * trace,\r\n\t\t\t\t  ( m[X][Z] - m[Z][X] ) * trace,\r\n\t\t\t\t  ( m[Y][X] - m[X][Y] ) * trace );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// find greatest element in Matrix diagonal\r\n\t\tsint i = X;\r\n\t\tif ( m[Y][Y] > m[X][X] ) i = Y;\r\n\t\tif ( m[Z][Z] > m[i][i] ) i = Z;\r\n\t\t\r\n\t\tsint j = ( i + 1 ) % W;\r\n\t\tsint k = ( j + 1 ) % W;\r\n\r\n\t\ttrace = sqrtf(( m[i][i] - (m[j][j] + m[k][k] )) + 1.0f );\r\n\t\t\r\n\t\tquat[i]\t= ( trace * 0.5f );\r\n\t\ttrace\t= 0.5f / trace;\r\n\t\tquat[j]\t= ( m[j][i] + m[i][j] ) * trace;\r\n\t\tquat[k]\t= ( m[k][i] + m[i][k] ) * trace;\t\t\r\n\t\tquat[W]\t= ( m[k][j] - m[j][k] ) * trace;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Quat&\tQuat::Invert( void ) \t\t\t\t\t\t\t// this = Invert ( this )\r\n{\r\n\t\r\n\r\n\tquat.Negate();\r\n\r\n\treturn\t*this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Quat&\tQuat::Invert( const Quat& src ) \t\t\t// this = Invert ( src )\r\n{\r\n\t\r\n\r\n\tquat.Negate( src.quat );\r\n\tquat[W] = src.quat[W];\r\n\r\n\treturn\t*this;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\t\tQuat::Modulus( void )\r\n{\r\n\t\r\n\t\r\n\treturn sqrtf( ModulusSqr () );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\t\tQuat::ModulusSqr ( void ) const\r\n{\r\n\t\r\n\t\r\n\treturn (( quat[X] * quat[X] ) +\r\n\t\t\t( quat[Y] * quat[Y] ) +\r\n\t\t\t( quat[Z] * quat[Z] ) +\r\n\t\t\t( quat[W] * quat[W] ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tQuat&\tQuat::Normalize( float len )\r\n{\r\n\t\r\n\t\r\n\tfloat\tmod = Modulus();\r\n\t\t\r\n\tif ( mod > 0.0f ) \r\n\t{\r\n\t\tmod = len / mod;\r\n\t\t\r\n\t\tquat *= mod;\r\n\t}\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\tQuat::Rotate( const Vector& vec ) const\r\n{\r\n\t\r\n\r\n\tQuat\tinv;\r\n//\tQuat \tpt( vec[X], vec[Y], vec[Z], vec[W] );\r\n\tQuat \tpt( vec[X], vec[Y], vec[Z], 1.0f );\t\t// Mick: Setting W to sensible value, otherwise can cause overflow\r\n\tQuat \tres = *this;\r\n\t\r\n\tinv.Invert( *this );\t\r\n\tres *= pt;\r\n\tres *= inv;\r\n\r\n\treturn Vector( res[X], res[Y], res[Z], res[W] );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\r\ninline void\t\tQuat::SetScalar( const float w )\r\n{\r\n\t\r\n\t\r\n\tquat[W] = w;\r\n};\r\n\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\tQuat::SetVector( const float x, const float y, const float z )\r\n{\r\n\t\r\n\t\r\n\tquat[X] = x;\r\n\tquat[Y] = y;\r\n\tquat[Z] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\tQuat::SetVector( const Vector& v )\r\n{\r\n\t\r\n\t\r\n\tquat[X] = v[X];\r\n\tquat[Y] = v[Y];\r\n\tquat[Z] = v[Z];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Quat& Quat::operator= ( const Quat& q )\r\n{\t\r\n\t\r\n\t\r\n\tquat = q.quat;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Quat& Quat::operator+= ( const Quat& q )\r\n{\t\r\n\t\r\n\t\r\n\tquat += q.quat;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Quat& Quat::operator-= ( const Quat& q )\r\n{\t\r\n\t\r\n\t\r\n\tquat -= q.quat;\r\n\r\n\treturn *this;\r\n}\r\n\r\n\r\ninline const\tfloat&\tQuat::GetScalar ( void ) const\r\n{\r\n\treturn quat[W];\r\n} \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Quat& Quat::operator*= ( const Quat& q )\r\n{\t\r\n\t\r\n\t\r\n\tfloat s1 = GetScalar();\r\n\tfloat s2 = q.GetScalar();\r\n\r\n\tVector v1 = GetVector();\r\n\tVector v2 = q.GetVector();\r\n\r\n\tSetVector (( v2 * s1 ) + ( v1 * s2 ) + CrossProduct ( v1, v2 ));\r\n\tSetScalar (( s1 * s2 ) - DotProduct ( v1, v2 ));\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tQuat&\tQuat::operator*= ( float s )\r\n{\r\n\t\r\n\t\r\n\tquat *= s;\r\n\t\r\n\treturn\t*this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tQuat&\tQuat::operator/= ( float s )\r\n{\r\n\t\r\n\t\r\n\tquat /= s;\r\n\t\r\n\treturn\t*this;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\tQuat::GetMatrix ( Matrix& mat ) const\r\n{\r\n\t\r\n\r\n\tfloat \txs, ys, zs,\r\n\t\t\twx,\twy,\twz,\r\n\t\t\txx,\txy,\txz,\r\n\t\t\tyy,\tyz,\tzz, ss;\r\n\r\n\r\n#if 0 \r\n\t// our original version.  Seems essentially broken, as LengthSqr ignores W\t\t\t\t  \r\n\tss = 2.0f / quat.LengthSqr();\r\n#else\t\t\t\t\t\t\t  \r\n\t// version suggested by Andre at Left Field\r\n\t// uses proper Modulus, and clamps 2.0/0.0f to zero\r\n\tss = ModulusSqr();\r\n\tss = ( ss>0.0f ? 2.0f/ss : 0.0f);\r\n#endif\r\n\r\n\txs = quat[X] * ss;\t\r\n\tys = quat[Y] * ss;\t\r\n\tzs = quat[Z] * ss;\r\n\r\n\twx = quat[W] * xs;\r\n\twy = quat[W] * ys;\t\r\n\twz = quat[W] * zs;\r\n\r\n\txx = quat[X] * xs;\t\r\n\txy = quat[X] * ys;\t\r\n\txz = quat[X] * zs;\r\n\r\n\tyy = quat[Y] * ys;\t\r\n\tyz = quat[Y] * zs;\t\r\n\r\n\tzz = quat[Z] * zs;\r\n\r\n\tmat[X][X] = 1.0f - (yy + zz);\r\n\tmat[Y][X] = xy + wz;\r\n\tmat[Z][X] = xz - wy;\r\n\r\n\tmat[X][Y] = xy - wz;\r\n\tmat[Y][Y] = 1.0f - (xx + zz);\r\n\tmat[Z][Y] = yz + wx;\r\n\r\n\tmat[X][Z] = xz + wy;\r\n\tmat[Y][Z] = yz - wx;\r\n\tmat[Z][Z] = 1.0f - (xx + yy );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Quat\toperator+\t( const Quat& q1, const Quat& q2 )\r\n{\r\n\t\r\n\t\t\r\n\tQuat\tsum = q1;\r\n\r\n\tsum += q2;\r\n\r\n\treturn sum;\r\n}    \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Quat\toperator-\t( const Quat& q1, const Quat& q2 )\r\n{\r\n\t\r\n\t\t\r\n\tQuat\tdiff = q1;\r\n\r\n\tdiff -= q2;\r\n\r\n\treturn diff;\r\n}    \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Quat\toperator*\t( const Quat& q1, const Quat& q2 )\r\n{\r\n\t\r\n\t\t\r\n\tQuat\tprod = q1;\r\n\r\n\tprod *=\tq2;\r\n\r\n\treturn prod;\r\n}    \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Quat\toperator*\t( const Quat& q, const float s )\r\n{\r\n\tQuat\tprod = q;\r\n\r\n\tprod *=\ts;\r\n\r\n\treturn prod;\r\n} \r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Quat\toperator*\t( const float s, const Quat& q )\t\t\t\r\n{\r\n\treturn q * s; \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tQuat operator-\t( const Quat& q )\r\n{\r\n\t\r\n\t\r\n\treturn Quat ( -q[X], -q[Y], -q[Z], -q[W] );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tDotProduct ( const Quat& v1, const Quat& v2 ) \r\n{\r\n\t\r\n\t\r\n\treturn ( v1[X] * v2[X] ) + ( v1[Y] * v2[Y] ) + ( v1[Z] * v2[Z] ) + ( v1[W] * v2[W] );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Quat Slerp ( const Quat& q1, const Quat& q3, float t )\r\n{\r\n\tfloat\tsclp, sclq;\r\n\t\t\r\n\t// GJ:  Need to possibly negate the second quaternion,\r\n\t// to avoid spinning in the wrong direction.\r\n\tQuat q2 = q3;\r\n\tif ( DotProduct( q1, q3 ) < 0.0f )\r\n\t{\r\n\t\tq2 = -q2;\r\n\t}\r\n\r\n\tfloat\tcoso = q1.GetScalar() * q2.GetScalar() + \r\n\t\t\t\t   DotProduct ( q1.GetVector(), q2.GetVector());\r\n\r\n\tQuat\tq;\r\n\r\n\tif (( 1.0f + coso + 1.0f ) > EPSILON )\r\n\t{ \r\n\t\tif (( 1.0f - coso ) > EPSILON )   \t// slerp\r\n\t\t{  \r\n\t\t\tfloat \tomega = acosf ( coso );\r\n\t\t\tfloat\tsino  = sinf ( omega );\r\n\r\n\t\t\tsclp  = sinf (( 1.0f - t ) * omega ) / sino;\r\n\t\t\tsclq  = sinf ( t * omega ) / sino;\r\n\t\t}\r\n\t\telse   \t\t\t\t\t\t\t\t\t// lerp ( angle tends to 0 )\r\n\t\t{  \r\n\t\t\tsclp = 1.0f - t;\r\n\t\t\tsclq = t;\r\n\t\t}\r\n\r\n\t\tq = ( sclp * q1 ) + ( sclq * q2 );\r\n\t}\r\n\telse \t\t\t\t\t\t\t\t\t\t// angle tends to 2*PI\r\n\t{ \r\n\t\tq.SetVector ( -q1[Y], q1[X], -q1[W] );\r\n\t\tq.SetScalar ( q1[Z] );\r\n\r\n\t\tsclp = sinf (( 1.0f - t ) * PI / 2.0f );\r\n\t\tsclq = sinf ( t * PI / 2.0f );\r\n\r\n\t\tq.SetVector (( sclp * q1.GetVector()) + ( sclq * q.GetVector()));\r\n\t}\r\n\r\n\treturn q;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tbool\t\tEqual ( const Quat& q1, const Quat& q2, const float tol )\r\n{\t\r\n\t\r\n\t\r\n\tif (( quat_equal (  q1, q2, tol )) ||\r\n\t\t( quat_equal ( -q1, q2, tol )))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline ostream& operator<< ( ostream& os, const Quat& q ) \r\n{\r\n\treturn os << \"(( \" << q[X] << \", \" << q[Y] << \", \" << q[Z] << \") , \" << q[W] << \" )\";\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void QuatVecToMatrix( Mth::Quat* pQ, Mth::Vector* pT, Mth::Matrix* pMatrix )\r\n{\r\n\tDbg_Assert( pQ );\r\n   \tDbg_Assert( pT );\r\n\tDbg_Assert( pMatrix );\r\n\r\n\tpQ->Invert();\r\n\r\n\tMth::Vector\t\tsquare;\r\n\tMth::Vector\t\tcross;\r\n\tMth::Vector\t\twimag;\r\n\r\n\tsquare[X] = (*pQ)[X] * (*pQ)[X];\r\n\tsquare[Y] = (*pQ)[Y] * (*pQ)[Y];\r\n\tsquare[Z] = (*pQ)[Z] * (*pQ)[Z];\r\n\r\n\tcross[X] = (*pQ)[Y] * (*pQ)[Z];\r\n\tcross[Y] = (*pQ)[Z] * (*pQ)[X];\r\n\tcross[Z] = (*pQ)[X] * (*pQ)[Y];\r\n\r\n\twimag[X] = (*pQ)[W] * (*pQ)[X];\r\n\twimag[Y] = (*pQ)[W] * (*pQ)[Y];\r\n\twimag[Z] = (*pQ)[W] * (*pQ)[Z];\r\n\r\n\t(*pMatrix)[Mth::RIGHT][X] = 1 - 2 * (square[Y] + square[Z]);\r\n\t(*pMatrix)[Mth::RIGHT][Y] = 2 * (cross[Z] + wimag[Z]);\r\n\t(*pMatrix)[Mth::RIGHT][Z] = 2 * (cross[Y] - wimag[Y]);\r\n\t(*pMatrix)[Mth::RIGHT][W] = 0.0f;\r\n\r\n\t(*pMatrix)[Mth::UP][X] = 2 * (cross[Z] - wimag[Z]);\r\n\t(*pMatrix)[Mth::UP][Y] = 1 - 2 * (square[X] + square[Z]);\r\n\t(*pMatrix)[Mth::UP][Z] = 2 * (cross[X] + wimag[X]);\r\n\t(*pMatrix)[Mth::UP][W] = 0.0f;\r\n\r\n\t(*pMatrix)[Mth::AT][X] = 2 * (cross[Y] + wimag[Y]);\r\n\t(*pMatrix)[Mth::AT][Y] = 2 * (cross[X] - wimag[X]);\r\n\t(*pMatrix)[Mth::AT][Z] = 1 - 2 * (square[X] + square[Y]);\r\n\t(*pMatrix)[Mth::AT][W] = 0.0f;\r\n\r\n\t(*pMatrix)[Mth::POS] = *pT;\r\n\t(*pMatrix)[Mth::POS][W] = 1.0f;\r\n}\r\n\r\ninline void SCacheQuatVecToMatrix( Mth::Quat* pQ, Mth::Vector* pT, Mth::Matrix* pMatrix )\r\n{\r\n\tDbg_Assert( pQ );\r\n   \tDbg_Assert( pT );\r\n\tDbg_Assert( pMatrix );\r\n\r\n\tpQ->Invert();\r\n\r\n\tMth::Vector\t*p_square = ((Mth::Vector*)0x7000000)+0;\r\n\tMth::Vector\t*p_cross  = ((Mth::Vector*)0x7000000)+1;\r\n\tMth::Vector\t*p_wimag  = ((Mth::Vector*)0x7000000)+2;\r\n\r\n\t(*p_square)[X] = (*pQ)[X] * (*pQ)[X];\r\n\t(*p_square)[Y] = (*pQ)[Y] * (*pQ)[Y];\r\n\t(*p_square)[Z] = (*pQ)[Z] * (*pQ)[Z];\r\n\r\n\t(*p_cross)[X] = (*pQ)[Y] * (*pQ)[Z];\r\n\t(*p_cross)[Y] = (*pQ)[Z] * (*pQ)[X];\r\n\t(*p_cross)[Z] = (*pQ)[X] * (*pQ)[Y];\r\n\r\n\t(*p_wimag)[X] = (*pQ)[W] * (*pQ)[X];\r\n\t(*p_wimag)[Y] = (*pQ)[W] * (*pQ)[Y];\r\n\t(*p_wimag)[Z] = (*pQ)[W] * (*pQ)[Z];\r\n\r\n\t(*pMatrix)[Mth::RIGHT][X] = 1 - 2 * ((*p_square)[Y] + (*p_square)[Z]);\r\n\t(*pMatrix)[Mth::RIGHT][Y] = 2 * ((*p_cross)[Z] + (*p_wimag)[Z]);\r\n\t(*pMatrix)[Mth::RIGHT][Z] = 2 * ((*p_cross)[Y] - (*p_wimag)[Y]);\r\n\t(*pMatrix)[Mth::RIGHT][W] = 0.0f;\r\n\r\n\t(*pMatrix)[Mth::UP][X] = 2 * ((*p_cross)[Z] - (*p_wimag)[Z]);\r\n\t(*pMatrix)[Mth::UP][Y] = 1 - 2 * ((*p_square)[X] + (*p_square)[Z]);\r\n\t(*pMatrix)[Mth::UP][Z] = 2 * ((*p_cross)[X] + (*p_wimag)[X]);\r\n\t(*pMatrix)[Mth::UP][W] = 0.0f;\r\n\r\n\t(*pMatrix)[Mth::AT][X] = 2 * ((*p_cross)[Y] + (*p_wimag)[Y]);\r\n\t(*pMatrix)[Mth::AT][Y] = 2 * ((*p_cross)[X] - (*p_wimag)[X]);\r\n\t(*pMatrix)[Mth::AT][Z] = 1 - 2 * ((*p_square)[X] + (*p_square)[Y]);\r\n\t(*pMatrix)[Mth::AT][W] = 0.0f;\r\n\r\n\t(*pMatrix)[Mth::POS] = *pT;\r\n\t(*pMatrix)[Mth::POS][W] = 1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\tSlerp ( Matrix& result, const Matrix& s1, const Matrix& s2, float t )\r\n{\r\n\tSlerp ( Quat(s1), Quat(s2), t).GetMatrix ( result );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float counter_warp(float t, float cos_alpha) \r\n{\r\n    const float ATTENUATION = 0.82279687f;\r\n    const float WORST_CASE_SLOPE = 0.58549219f;\r\n\r\n    float factor = 1.0f - ATTENUATION * cos_alpha;\r\n    factor *= factor;\r\n    float k = WORST_CASE_SLOPE * factor;\r\n\r\n    return t*(k*t*(2.0f*t - 3.0f) + 1.0f + k);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Mth::Quat FastSlerp( Mth::Quat& qIn1, Mth::Quat& qIn2, const float t )\r\n{\r\n\tif ( Mth::DotProduct( qIn1, qIn2 ) < 0.0f )\r\n\t{\r\n\t\tqIn2 = -qIn2;\r\n\t}\r\n\r\n#\tif 0\r\n\tfloat cos_a = v1[X]*v2[X] + v1[Y]*v2[Y] + v1[Z]*v2[Z] + v1[W]*v2[W];\r\n\tif (t <= 0.5f)\r\n\t{\r\n\t\tt = counter_warp(t, cos_a);\r\n\t} \r\n\telse\r\n\t{\r\n\t\tt = 1.0f - counter_warp(1.0f - t, cos_a);\r\n\t}\r\n#\tendif\t\r\n\r\n\tfloat\txxx_x\t= qIn1[X] + ( qIn2[X] - qIn1[X] ) * t;\r\n\tfloat\txxx_y\t= qIn1[Y] + ( qIn2[Y] - qIn1[Y] ) * t;\r\n\tfloat\txxx_z\t= qIn1[Z] + ( qIn2[Z] - qIn1[Z] ) * t;\r\n\tfloat\txxx_w\t= qIn1[W] + ( qIn2[W] - qIn1[W] ) * t;\r\n\r\n\tfloat\tlen\t\t= 1.0f / sqrtf( xxx_x * xxx_x + xxx_y * xxx_y + xxx_z * xxx_z + xxx_w * xxx_w );\r\n\r\n\tqIn2.SetVector( xxx_x * len, xxx_y * len, xxx_z * len );\r\n\tqIn2.SetScalar( xxx_w * len );\r\n\r\n\treturn qIn2;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Mth::Quat EulerToQuat( const Mth::Vector& euler )\r\n{\r\n\t// This code is a modified version of Left Field's\r\n\t// MakeQuatFromEuler() function.\r\n\r\n\tMth::Quat q;\r\n\r\n\tfloat roll = euler[X];\r\n\tfloat pitch = euler[Y];\r\n\tfloat yaw = euler[Z];\r\n\r\n\tfloat cyaw, cpitch, croll, syaw, spitch, sroll;\r\n\tfloat cyawcpitch, syawspitch, cyawspitch, syawcpitch;\r\n\r\n\tcyaw = cosf(0.5f * yaw);\r\n\tcpitch = cosf(0.5f * pitch);\r\n\tcroll = cosf(0.5f * roll);\r\n\r\n\tsyaw = sinf(0.5f * yaw);\r\n\tspitch = sinf(0.5f * pitch);\r\n\tsroll = sinf(0.5f * roll);\r\n\r\n\tcyawcpitch = cyaw * cpitch;\r\n\tsyawspitch = syaw * spitch;\r\n\tcyawspitch = cyaw * spitch;\r\n\tsyawcpitch = syaw * cpitch;\r\n\r\n\tq[W] = cyawcpitch * croll + syawspitch * sroll;\r\n\tq[X] = cyawcpitch * sroll - syawspitch * croll;\r\n\tq[Y] = cyawspitch * croll + syawcpitch * sroll;\r\n\tq[Z] = syawcpitch * croll - cyawspitch * sroll;\r\n\r\n\treturn q;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mth\r\n\r\n#endif // __CORE_MATH_QUAT_INL\r\n\r\n"
  },
  {
    "path": "Code/Core/Math/rect.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (MTH)\t\t\t   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/math/Rect.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/31/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMath Library Rectangle class\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_MATH_RECT_H\r\n#define __CORE_MATH_RECT_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mth\r\n{\r\n\t\t\t\t\t\t   \r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnTemplateBaseClass ( _T, _Rect )\r\n{\r\n\t\r\n\r\npublic:\r\n\t\t\t\t_Rect ( const _T x, const _T y, const _T w, const _T h );\r\n\t\t\t\t~_Rect ( );\r\n\t\r\n\tvoid\t\tSetOriginX ( const _T ) ;\r\n\tvoid\t\tSetOriginY ( const _T ) ;\r\n\tvoid\t\tSetWidth ( const _T ) ;\r\n\tvoid\t\tSetHeight ( const _T ) ;\r\n\t\r\n\tconst _T\tGetOriginX ( void ) const;\r\n\tconst _T\tGetOriginY ( void ) const;\r\n\tconst _T\tGetWidth ( void ) const;\r\n\tconst _T\tGetHeight ( void ) const;\r\n\r\nprivate:\r\n\r\n\t_T \t\t\tx, y, w, h;\r\n\t\t\t\t\t\t\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Type Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntypedef _Rect < float > Rect;\r\ntypedef _Rect < sint > \tIRect;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntemplate < class _T > inline\r\n_Rect< _T >::_Rect ( const _T _x, const _T _y, const _T _w, const _T _h )\r\n: x (_x), y (_y), w(_w), h(_h)\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\n_Rect< _T >::~_Rect ( void )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nvoid\t_Rect< _T >::SetOriginX ( const _T xval )\r\n{\r\n\t\r\n\r\n\tx = xval;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nvoid\t_Rect< _T >::SetOriginY ( const _T yval )\r\n{\r\n\t\r\n\r\n\ty = yval;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nvoid\t_Rect< _T >::SetWidth ( const _T width )\r\n{\r\n\t\r\n\r\n\tw = width;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nvoid\t_Rect< _T >::SetHeight ( const _T height )\r\n{\r\n\t\r\n\r\n\th = height;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nconst _T\t_Rect< _T >::GetOriginX ( void ) const\r\n{\r\n\t\r\n\r\n\treturn x;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nconst _T\t_Rect< _T >::GetOriginY ( void )\tconst\r\n{\r\n\t\r\n\r\n\treturn y;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nconst _T\t_Rect< _T >::GetWidth ( void ) const\r\n{\r\n\t\r\n\r\n\treturn w;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nconst _T\t_Rect< _T >::GetHeight ( void ) const\r\n{\r\n\t\r\n\r\n\treturn h;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nostream& operator<< ( ostream& str, const _Rect< _T >& r )\r\n{\r\n\tstr << \"(( \" << r.GetOriginX() << \", \" << r.GetOriginY() << \" ),( \" \r\n\t\t\t\t\t<< r.GetWidth() << \", \" << r.GetHeight() << \" ))\"; \r\n\treturn str;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mth\r\n\r\n#endif // __CORE_MATH_RECT_H\r\n"
  },
  {
    "path": "Code/Core/Math/rot90.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (MTH)\t\t\t   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/math/rot90.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t07/17/02\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tRotation 90 Math Class\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/math.h>\r\n#include <core/math/rot90.h>\r\n\r\nnamespace Mth\r\n{\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tRotateY90( ERot90 angle, int32& x, int32& y, int32& z )\r\n{\r\n\tint32 temp;\r\n\r\n\tswitch (angle)\r\n\t{\r\n\tcase ROT_0:\r\n\t\tbreak;\r\n\r\n\tcase ROT_90:\r\n\t\ttemp = x;\r\n\t\tx = z;\r\n\t\tz = -temp;\r\n\t\tbreak;\r\n\r\n\tcase ROT_180:\r\n\t\tx = -x;\r\n\t\tz = -z;\r\n\t\tbreak;\r\n\r\n\tcase ROT_270:\r\n\t\ttemp = x;\r\n\t\tx = -z;\r\n\t\tz = temp;\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0, (\"RotateY90() out of range: %d\", angle));\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n} // namespace Mth\r\n\r\n"
  },
  {
    "path": "Code/Core/Math/rot90.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n// rot90.h\r\n//\r\n\r\n#ifndef\t__CORE_ROT90_H\r\n#define\t__CORE_ROT90_H\r\n\r\nnamespace Mth\r\n{\r\n\r\n// Rotation values for 90 degree increment Rotation (uses no multiplication)\r\nenum ERot90 {\r\n\tROT_0 = 0,\r\n\tROT_90,\r\n\tROT_180,\r\n\tROT_270,\r\n\tNUM_ROTS\r\n};\r\n\r\n// Integer rotate\r\nvoid\t\t\tRotateY90( ERot90 angle, int32& x, int32& y, int32& z );\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Core/Math/slerp.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (MTH)\t\t\t   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/math/slerp.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t12/20/01\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSlerp Interpolator Math Class\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/math.h>\r\n#include <core/math/slerp.h>\r\n\r\nnamespace Mth\r\n{\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nconst float USE_LERP_INSTEAD_DEGREES = 2.0f;\r\nconst float USE_LERP_INSTEAD_RADIANS = USE_LERP_INSTEAD_DEGREES * PI / 180.0f;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSlerpInterpolator::SlerpInterpolator()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSlerpInterpolator::SlerpInterpolator( const Matrix * start, const Matrix * end )\r\n{\r\n\tsetMatrices( start, end );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid SlerpInterpolator::setMatrices( const Matrix * start, const Matrix * end )\r\n{\r\n\tMatrix\tinv;\r\n\r\n    m_start = *start;\r\n    m_end = *end;\r\n\r\n\t// Calculate the inverse transformation.\r\n    inv = m_start;\r\n    inv.Invert();\r\n    inv = inv * m_end;\r\n\t\r\n    // Get the axis and angle.\r\n    inv.GetRotationAxisAndAngle( &m_axis, &m_radians );\r\n    \r\n#if 0    \r\n    // Debugging stuff\r\n    static int print_x_times = 50;\r\n\r\n    if ( print_x_times > 0 )\r\n    {\r\n        print_x_times--;\r\n        printf(\"Start mat\\n\");\r\n        m_start.PrintContents();\r\n        printf(\"Inv mat\\n\");\r\n        inv.PrintContents();\r\n        printf(\"End mat\\n\");\r\n        m_end.PrintContents();\r\n        printf(\"Start * Inv mat\\n\");\r\n        Mth::Matrix siMat = m_start;\r\n        siMat = siMat * inv;\r\n        siMat.PrintContents();\r\n        {\r\n            printf(\"Rotated mat w=0\\n\");\r\n            Mth::Matrix tempMatrix = m_start;\r\n            m_axis[W] = 0.0f;\r\n            tempMatrix.Rotate( m_axis, m_radians );\r\n            tempMatrix.PrintContents();\r\n        }\r\n        {\r\n            printf(\"Rotated mat w=1\\n\");\r\n            Mth::Matrix tempMatrix2 = m_start;\r\n            m_axis[W] = 1.0f;\r\n            tempMatrix2.Rotate( m_axis, m_radians );\r\n            tempMatrix2.PrintContents();\r\n        }\r\n        {\r\n            printf(\"Rotated local mat w=0\\n\");\r\n            Mth::Matrix tempMatrix = m_start;\r\n            m_axis[W] = 0.0f;\r\n            tempMatrix.RotateLocal( m_axis, m_radians );\r\n            tempMatrix.PrintContents();\r\n        }\r\n        {\r\n            printf(\"Rotated local mat w=1\\n\");\r\n            Mth::Matrix tempMatrix2 = m_start;\r\n            m_axis[W] = 1.0f;\r\n            tempMatrix2.RotateLocal( m_axis, m_radians );\r\n            tempMatrix2.PrintContents();\r\n        }\r\n        printf( \"Slerp axis=(%f %f %f %f) angle=%f\\n\", m_axis[X], m_axis[Y], m_axis[Z], m_axis[W], m_radians );\r\n    }\r\n    else\r\n    {\r\n        Dbg_Assert( 0 );\r\n    }\r\n#endif    \r\n\r\n\t// If angle is too small, use lerp.\r\n\tm_useLerp = m_radians < USE_LERP_INSTEAD_RADIANS;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid SlerpInterpolator::getMatrix( Matrix * result, float delta )\r\n{\r\n    /* Cap and floor the delta */\r\n    /* If we are at one end the solution is easy */\r\n    if (delta <= 0.0f)\r\n    {\r\n        // delta = 0.0f;\r\n        *result = m_start;\r\n\t\treturn;\r\n    }\r\n    else if (delta >= 1.0f)\r\n    {\r\n        // delta = 1.0f;\r\n        *result = m_end;\r\n\t\treturn;\r\n    }\r\n\r\n#if 0\r\n    // GJ:  always lerp, used while slerp was being debugged\r\n//    m_useLerp = true;\r\n#endif\r\n\r\n    /* Do the lerp if we are, else... */\r\n    if ( m_useLerp )\r\n    {\r\n        /* Get the lerp matrix */\r\n\t\tMatrix\tlerp;\r\n\t\tVector\tlpos;\r\n\t\tVector\tspos;\r\n\t\tVector\tepos;\r\n\t\tVector\trpos;\r\n\r\n\t\tlerp.Ident();\r\n\t\t\r\n\t\tspos = m_start[Mth::POS];\r\n        epos = m_end[Mth::POS];\r\n\r\n        lerp[Mth::RIGHT] = m_end[Mth::RIGHT] - m_start[Mth::RIGHT];\r\n        lerp[Mth::UP] = m_end[Mth::UP] - m_start[Mth::UP];\r\n        lerp[Mth::AT] = m_end[Mth::AT] - m_start[Mth::AT];\r\n        lpos = epos - spos;\r\n\r\n        /* Do lerp */\r\n        lerp[Mth::RIGHT].Scale( delta );\r\n        lerp[Mth::UP].Scale( delta );\r\n        lerp[Mth::AT].Scale( delta );\r\n        lpos.Scale( delta );        \r\n\r\n        (*result)[Mth::RIGHT] = m_start[Mth::RIGHT] + lerp[Mth::RIGHT];\r\n        (*result)[Mth::UP] = m_start[Mth::UP] + lerp[Mth::UP];\r\n        (*result)[Mth::AT] = m_start[Mth::AT] + lerp[Mth::AT];        \r\n        rpos = spos + lpos;        \r\n        \r\n\t\t(*result)[Mth::RIGHT].Normalize();\r\n\t\t(*result)[Mth::UP].Normalize();\r\n\t\t(*result)[Mth::AT].Normalize();        \r\n        \r\n        (*result)[Mth::POS] = rpos;  \r\n    }\r\n    else\r\n    {\r\n\t\tVector\trpos;\r\n\t\tVector\tspos;\r\n\t\tVector\tepos;\r\n        Vector  lpos;\r\n\r\n\t\tspos = m_start[Mth::POS];\r\n        epos = m_end[Mth::POS];\r\n\r\n        /* Remove the translation for now */\r\n        *result = m_start;\r\n        (*result)[Mth::POS] = Mth::Vector( 0.0f, 0.0f, 0.0f );\r\n\r\n        /* Rotate the new matrix */\r\n//      m_axis[W] = 0.0f;\r\n        result->Rotate( m_axis, m_radians * delta );\r\n\r\n        /* Do linear interpolation on position */\r\n        lpos = epos - spos;\r\n        lpos.Scale( delta );        \r\n        rpos = spos + lpos;        \r\n\r\n        (*result)[Mth::POS] = rpos;\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid SlerpInterpolator::invertDirection (   )\r\n{\r\n\tm_axis = -m_axis;\r\n\tm_radians = (2.0f * Mth::PI) - m_radians;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n"
  },
  {
    "path": "Code/Core/Math/slerp.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (MTH)\t\t\t   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/math/slerp.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t12/20/01\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSlerp Interpolator Math Class\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_MATH_SLERP_H\r\n#define __CORE_MATH_SLERP_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/math/vector.h>\r\n#include <core/math/matrix.h>\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mth\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/****************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n * Class:\t\t\tSlerp Interpolator\r\n *\r\n * Description:\t\tSlerp Interpolator math class\r\n *\r\n ****************************************************************************/\r\n\r\nclass SlerpInterpolator\r\n{\r\npublic:\r\n\t\t\t\tSlerpInterpolator();\r\n\t\t\t\tSlerpInterpolator( const Matrix* pStart, const Matrix* pEnd );\r\n\r\npublic:\r\n\tvoid\t\tsetMatrices( const Matrix* pStart, const Matrix* pEnd );\t\r\n\tvoid\t\tgetMatrix( Matrix* result, float delta );\r\n\t\r\n\tvoid\t\tinvertDirection (   );\r\n\t\t\t\t\t  \r\n\tfloat\t\tgetRadians (   ) { return m_radians; }\r\n\tconst Mth::Vector&\tgetAxis (   ) { return m_axis; }\r\n\r\nprotected:\r\n\tMatrix\t    m_start;\r\n\tMatrix\t    m_end;\r\n\tVector\t    m_axis;\r\n\tfloat\t\tm_radians;\r\n\tbool\t\tm_useLerp;  // do linear-interpolation, rather than slerping\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Mth\r\n\r\n#endif // __CORE_MATH_SLERP_H\r\n"
  },
  {
    "path": "Code/Core/Math/vector.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tVector (MTH)\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tvector.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t11/24/99\t-\tMick\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMath Library code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#include <core/math.h>\r\n#include <core/defines.h>\r\n//#include <core/math.h>\r\n#include <core/math/math.h>\r\n#include <core/math/vector.h>\r\n#include <core/math/matrix.h>\r\n#include <core/macros.h>\r\n\r\n#include <core/math/quat.h>\r\n#include <core/math/vector.inl>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mth\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nVector&\t\t\tVector::RotateY90( ERot90 angle )\r\n{\t\r\n\tfloat temp;\r\n\r\n\tswitch (angle)\r\n\t{\r\n\tcase ROT_0:\r\n\t\tbreak;\r\n\r\n\tcase ROT_90:\r\n\t\ttemp = col[X];\r\n\t\tcol[X] = col[Z];\r\n\t\tcol[Z] = -temp;\r\n\t\tbreak;\r\n\r\n\tcase ROT_180:\r\n\t\tcol[X] = -col[X];\r\n\t\tcol[Z] = -col[Z];\r\n\t\tbreak;\r\n\r\n\tcase ROT_270:\r\n\t\ttemp = col[X];\r\n\t\tcol[X] = -col[Z];\r\n\t\tcol[Z] = temp;\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0, (\"Vector::RotateY90() out of range: %d\", angle));\r\n\t\tbreak;\r\n\t}\r\n\r\n\treturn *this;\r\n}\r\n\r\n/*****************************************************************************\r\n// Project the vector onto the plane define by a normal\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\t\t\r\nVector&\t\t\tVector::ProjectToPlane(const Vector& normal)\r\n{\r\n\r\n\t\r\n\tfloat perp_component = Mth::DotProduct(*this,normal);\t\r\n\t\r\n\t*this -= normal * perp_component;\t\r\n\t\r\n\treturn *this;\t\r\n\r\n}\r\n\r\nVector&\t\t\tVector::RotateToPlane(const Vector& normal)\r\n{\r\n\t// get the length of the vector\r\n\tfloat length = Length();\r\n\t\r\n\t// Project the vector onto the plane\r\n\tProjectToPlane(normal);\r\n\t\r\n\t// now we've projected it ontot he plane\r\n\t// we need to handle the case where it dissapears into a point\r\n\t// which would indicate that we were perpendicular to the plane\r\n\t// so need to get an arbitary vector in the plane\t\r\n\tfloat  projected_length = Length();\r\n\tif (projected_length == 0.0f) \t\t// is this a valid comparision?\r\n\t{\r\n\t\t// Rotate vector through -90 degrees about Y then +90 about X\r\n\t\tcol[X] = -normal[Z];\r\n\t\tcol[Y] =  normal[X];\r\n\t\tcol[Z] = -normal[Y];\t\r\n\t}\r\n\t\r\n\t// get unit vector in this direction\r\n\tNormalize();\t\r\n\t\r\n\t// multiply by original speed to rotate velocity onto plane\r\n\t*this *= length;\t\t\t\t\t\t \r\n\r\n\tcol[W] = 0.0f; \t\t\t// clean up W, otherwise multilications will accumelate over time...\r\n\t\r\n\treturn *this;\t\r\n}\t\r\n\t\r\nVector&\t\t\tVector::RotateToNormal(const Vector& normal)\r\n{\r\n\r\n\t*this  = normal*Length();\r\n\r\n\treturn *this;\r\n}\r\n\r\nVector&\t\t\tVector::ProjectToNormal(const Vector& normal)\r\n{\r\n\r\n\tfloat dot = Mth::DotProduct(*this,normal); \t\t\t\t\t\t\t   \r\n\t*this  = normal * dot;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/* Finds the largest contributor to the length of the vector...\r\n   If you pass in whichAxis, it will fill it in with which axis\r\n   is the max...\r\n*/\r\nfloat\tVector::GetMaxAxis( int *whichAxis )\r\n{\r\n\tint which_axis;\r\n\tif ( !whichAxis )\r\n\t{\r\n\t\twhichAxis = &which_axis;\r\n\t}\r\n\t\r\n\t*whichAxis = X;\r\n\t\r\n\tif ( Abs( this->col[ Y ] ) > Abs( this->col[ X ] ) )\r\n\t{\r\n\t\tif ( Abs( this->col[ Z ] ) > Abs( this->col[ Y ] ) )\r\n\t\t\t*whichAxis = Z;\r\n\t\telse\r\n\t\t\t*whichAxis = Y;\r\n\t}\r\n\telse if ( Abs( this->col[ Z ] ) > Abs( this->col[ X ] ) )\r\n\t{\r\n\t\t*whichAxis = Z;\r\n\t}\r\n\treturn ( this->col[ *whichAxis ] );\r\n}\r\n\r\nvoid Vector::DegreesToRadians( void )\r\n{\r\n\tthis->col[ X ] = DEGREES_TO_RADIANS( this->col[ X ] );\r\n\tthis->col[ Y ] = DEGREES_TO_RADIANS( this->col[ Y ] );\r\n\tthis->col[ Z ] = DEGREES_TO_RADIANS( this->col[ Z ] );\r\n}\r\n\r\nvoid Vector::RadiansToDegrees( void )\r\n{\r\n\tthis->col[ X ] = RADIANS_TO_DEGREES( this->col[ X ] );\r\n\tthis->col[ Y ] = RADIANS_TO_DEGREES( this->col[ Y ] );\r\n\tthis->col[ Z ] = RADIANS_TO_DEGREES( this->col[ Z ] );\r\n}\r\n\r\nvoid Vector::FeetToInches( void )\r\n{\r\n\tthis->col[ X ] = FEET_TO_INCHES( this->col[ X ] );\r\n\tthis->col[ Y ] = FEET_TO_INCHES( this->col[ Y ] );\r\n\tthis->col[ Z ] = FEET_TO_INCHES( this->col[ Z ] );\r\n}\r\n\r\n// convert to 3d studio max coords ( Z+ up, Y- forward, X to the right... )\r\nvoid Vector::ConvertToMaxCoords( void )\r\n{\r\n\tthis->col[ X ] = -this->col[ X ];\r\n\tfloat temp = this->col[ Y ];\r\n\tthis->col[ Y ] = -this->col[ Z ];\r\n\tthis->col[ Z ] = temp;\r\n}\r\n\r\n// convert to 3d studio max coords ( Z+ up, Y- forward, X to the right... )\r\nvoid Vector::ConvertFromMaxCoords( void )\r\n{\r\n\tthis->col[ X ] = -this->col[ X ];\r\n\tfloat temp = this->col[ Y ];\r\n\tthis->col[ Y ] = this->col[ Z ];\r\n\tthis->col[ Z ] = -temp;\r\n}\r\n\r\nfloat GetAngle( const Matrix &currentOrientation, const Vector &desiredHeading, int headingAxis, int rotAxis )\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert( headingAxis == X || headingAxis == Y || headingAxis == Z,( \"Improper heading axis.\" ));\r\n\tDbg_MsgAssert( rotAxis == X || rotAxis == Y || rotAxis == Z,( \"Improper rot axis.\" ));\r\n\tDbg_MsgAssert( rotAxis != headingAxis,( \"Can't use heading axis as rot axis.\" ));\r\n\r\n\tMth::Vector tempHeading = desiredHeading;\r\n\ttempHeading.ProjectToPlane( currentOrientation[ rotAxis ] );\r\n\tif ( !tempHeading.Length( ) )\r\n\t{\r\n\t\t// If our rot axis is along Y, for example, the\r\n\t\t// target heading is right above us... Can't pick\r\n\t\t// a rotation!\r\n\t\treturn ( 0.0f );\r\n\t}\r\n\ttempHeading.Normalize( );\r\n\r\n\t// while we have these two vectors, find the angle between them...\r\n\tfloat angCos = DotProduct( currentOrientation[ headingAxis ], tempHeading );\r\n\t\r\n\t// Mick:  contrain Dot product to range -1.0f to +1.0f, since FP innacuracies might\r\n\t// make it go outside this range\r\n\t// (previously this was done only on NGC.  Not sure why it has started failing now\r\n\t// but it seems logical that it would fail occasionally, so this check is necessary) \t\r\n\tfloat\tang = angCos;\r\n\tif ( ang > 1.0f ) ang = 1.0f;\r\n\tif ( ang < -1.0f ) ang = -1.0f;\r\n\tfloat retVal = -acosf( ang );\r\n\r\n\tMth::Vector temp = Mth::CrossProduct( currentOrientation[ headingAxis ], tempHeading );\r\n\r\n\t// check to see if the cross product is in the same quatrant as our rot axis...\r\n\t// if so, gots to rotate the other way and shit like that...\r\n\tint whichAxis;\r\n\tfloat tempMax = temp.GetMaxAxis( &whichAxis );\r\n\tif ( ( tempMax > 0 ) == ( currentOrientation[ rotAxis ][ whichAxis ] > 0 ) )\r\n\t{\r\n\t\treturn ( -retVal );\r\n\t}\r\n\treturn ( retVal );\r\n}\r\n\r\nfloat GetAngle(Vector &v1, Vector &v2)\r\n{\r\n\tVector a=v1;\r\n\tVector b=v2;\r\n\ta.Normalize();\r\n\tb.Normalize();\r\n\tfloat dot = Mth::DotProduct(a,b);\t\r\n\tif ( dot > 1.0f ) dot = 1.0f;\r\n\tif ( dot < -1.0f ) dot = -1.0f;\r\n\treturn Mth::RadToDeg(acosf(dot));\r\n}\r\n\r\n// Returns true if the angle between a and b is greater than the passed Angle.\r\nbool AngleBetweenGreaterThan(const Vector& a, const Vector& b, float Angle)\r\n{\r\n\tfloat dot=Mth::DotProduct(a,b);\r\n\tfloat len=a.Length();\r\n\tif (len<0.5f)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\tdot/=len;\r\n\t\r\n\tlen=b.Length();\r\n\tif (len<0.5f)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\tdot/=len;\r\n\t\r\n\tfloat TestAngleCosine=cosf(Mth::DegToRad(Angle));\r\n\t\r\n\tif (dot>=0.0f)\r\n\t{\r\n\t\treturn dot<TestAngleCosine;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (TestAngleCosine>=0.0f)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn dot<TestAngleCosine;\r\n\t\t}\r\n\t}\t\t\r\n}\r\n\r\n// Mick:\r\n// Given two vectors, v1 and v2 and an Axis vector\r\n// return the amount that v1 would have to rotate about the Axis\r\n// in order to be pointing in the same direction as v2\r\n// when viewed along the Axis\r\n//\r\n// Typically, \"Axis\" will be the Y axis of the object (Like the skater)\r\n// and v1 will be the Z direction\r\n// which we want to rotate toward v2 (about Y)\r\n// \r\n// retunr value will be in the range -PI .. PI   (-180 to 180 degrees)\r\nfloat GetAngleAbout(Vector &v1, Vector &v2, Vector &Axis)\r\n{\r\n\tAxis.Normalize();\r\n\tv1.ProjectToPlane(Axis);\r\n\tv2.ProjectToPlane(Axis);\r\n\tv1.Normalize();\r\n\tv2.Normalize();\r\n\tVector v3 = Mth::CrossProduct(Axis,v1);\r\n\tfloat v1_dot = Mth::DotProduct(v1,v2);\r\n\tfloat v3_dot = Mth::DotProduct(v3,v2);\r\n\r\n\tfloat angle = acosf(Mth::Clamp(v1_dot, -1.0f, 1.0f));\r\n\r\n\tif (v3_dot < 0.0f)\r\n\t{\r\n\t\tangle = -angle;\r\n\t}\r\n\treturn angle;\r\n}\r\n\r\n#ifdef\t\tDEBUG_OVERFLOW_VECTORS\r\n\r\nconst float&\t\tVector::operator[] ( sint i ) const\r\n{\r\n//\tDbg_MsgAssert (Abs(col[i]) < 1000000000.0f  || col[i]==1.0e+30f,(\"vector component (%f) over a billion!!!\",col[i]));\r\n\tDbg_MsgAssert (!isnanf(col[i]),(\"vector component [%d] (%f) not a number!!!!\",i,col[i]));\r\n//\tDbg_MsgAssert (!isinff(col[i]),(\"vector component [%d] (%f) infinite!!!!\",i,col[i]));\r\n\treturn col[i];\r\n}\r\n#endif\r\n\r\n#ifdef\t\tDEBUG_UNINIT_VECTORS\r\n\r\nconst float&\t\tVector::operator[] ( sint i ) const\r\n{\r\n// This assertion will catch any of the predefined NaN values that we initilize the vectors and matrix to\r\n// when DEBUG_UNINIT_VECTORS is defined.\r\n\tDbg_MsgAssert ( (*(uint32*)(&col[i]) & 0xffffff00) != 0x7F800000,(\"uninitialized vector[%d] = 0x%x\",i,(*(uint32*)(&col[i]))));\r\n\treturn col[i];\r\n}\r\n\r\n\r\n// for debugging purposes, this function is not inline when we want the \r\n// uninitialized vector debugging\r\n// as it makes it easier to track down wehre the problem is\r\nVector&\t\tVector::operator=\t( const Vector& v )\r\n{\t\r\n\r\n\tcol[X] = v[X];\r\n\tcol[Y] = v[Y];\r\n\tcol[Z] = v[Z];\r\n\tcol[W] = v[W];\r\n\treturn *this;\r\n}\r\n\r\n\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Vector::PrintContents() const\r\n{\r\n//\tprintf( \"-----------------\\n\" );\r\n\tprintf( \"[%f %f %f %f]\\n\", col[X], col[Y], col[Z], col[W] );\r\n//\tprintf( \"-----------------\\n\" );\r\n}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Core/Math/vector.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (MTH)\t\t\t   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/math/Vector.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t11/29/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tVector Math Class\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_MATH_VECTOR_H\r\n#define __CORE_MATH_VECTOR_H\r\n\r\n// (Mick) If this is defined, then vectors will be initialized to (0,0,0,1), and\r\n// matrices to:\r\n// (1,0,0,0)\r\n// (0,1,0,0)\r\n// (0,0,1,0)\r\n// (0,0,0,1)\r\n// This is sligtly differnet to before, where mats were intialized to all (0,0,0,1)\r\n// since they were defined as an Array of vecotors\r\n// This makes the code run about 3% slower (on PS2), which is why we don't use it\r\n//#define\t\t__INITIALIZE_VECTORS__\r\n\r\n// you can catch code that used to rely on this (and other bugs)\r\n// by uncommenting the following line\r\n// this will initilize the vectors to garbage values\r\n// and check all accesses of vectors to see if these values\r\n// have been left before using....\r\n// (this requires a full recompile, and makes the code run really slow)\r\n//#define\t\tDEBUG_UNINIT_VECTORS\r\n\r\n\r\n// we also might want to catch situations where a component of a vector is very large\r\n// which could indicate some potential overflow, especially if the W components is \r\n// accumalating errors, getting unseemly large, then getting incorporated\r\n// into an equation that involves X,Y,Z\r\n// (see Quat::Rotate for an example)\r\n//#define\t\tDEBUG_OVERFLOW_VECTORS\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/math/rot90.h>\r\n\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nenum\r\n{\r\n\tX, Y, Z, W\r\n};\r\n\r\nnamespace Mth\r\n{\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Quat;\t\t// forward refs\r\nclass Matrix;\r\n\r\n/****************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n * Class:\t\t\tVector\r\n *\r\n * Description:\t\tVector math class\r\n *\r\n ****************************************************************************/\r\n\r\nclass  Vector\r\n{\r\n\t\r\n\r\npublic:\r\n\t\t\t// Made special enum so we can have a constructor that does not initialize\r\n\t\t\tenum ENoInitType\r\n\t\t\t{\r\n\t\t\t\tNO_INIT\r\n\t\t\t};\r\n\r\n\t\t\tVector ( );\r\n\t\t\tVector ( ENoInitType ); \t\t\t/// A constructor that doesn't init the members.\r\n\t\t\tVector ( float cx, float cy, float cz );\r\n\t\t\tVector ( float cx, float cy, float cz, float cw );\r\n//\t\t\tVector ( float cx = 0.0f, float cy = 0.0f, float cz = 0.0f, float cw = 1.0f );\r\n\t\t\tVector ( const Vector& v );\r\n\t\r\n\r\n\t\t\tVector& \t\toperator=\t( const Vector& v );\r\n\t\t\tbool\t\t\toperator==  ( const Vector& v ) const;\r\n\t\t\tbool\t\t\toperator!=  ( const Vector& v ) const;\r\n        \tVector&\t\t\toperator+=\t( const Vector& v );\r\n        \tVector&\t\t\toperator-=\t( const Vector& v );\r\n        \tVector&\t\t\toperator*=\t( const float s );\r\n\t\t\tVector&\t\t\toperator/=\t( float s );\r\n\t\t\tVector&\t\t\toperator*=\t( const Vector& v );\r\n\t\t\tVector&\t\t\toperator/=\t( const Vector& v );\r\n\t\t\tVector&\t\t\toperator*=\t( const Matrix& mat );\r\n\tconst\tfloat&\t\t\toperator[]\t( sint i ) const;\r\n\t\t\tfloat&\t\t\toperator[]\t( sint i );\r\n\t\r\n\t\t\tVector&\t\t\tSet \t\t( float cx = 0.0f, float cy = 0.0f, float cz = 0.0f, float cw = 1.0f );\r\n\t\t\tfloat\t\t\tLength\t\t( void ) const;\r\n\t\t\tfloat\t\t\tLengthSqr\t( void ) const;\r\n        \tVector&\t\t\tNegate\t\t( void );\t\t\t\t\t\t// this = -this\r\n\t\t\tVector&\t\t\tNegate \t\t( const Vector& src ); \t\t\t// this = -src\r\n        \tVector&\t\t\tNormalize\t( );\t\t\t\t\t\t\t// faster version normlaizes to 1\r\n        \tVector&\t\t\tNormalize\t( float len);\r\n\r\n\t\t\tVector&\t\t\tShearX\t\t( float shy, float shz );\r\n\t\t\tVector&\t\t\tShearY\t\t( float shx, float shz );\r\n\t\t\tVector&\t\t\tShearZ\t\t( float shx, float shy );\r\n\r\n\t\t\tVector&\t\t\tRotateX\t\t( float s, float c );\r\n\t\t\tVector&\t\t\tRotateY\t\t( float s, float c );\r\n\t\t\tVector&\t\t\tRotateZ\t\t( float s, float c );\r\n\r\n\t\t\tVector&\t\t\tRotateX\t\t( float angle );\r\n\t\t\tVector&\t\t\tRotateY\t\t( float angle );\r\n\t\t\tVector&\t\t\tRotateZ\t\t( float angle );\r\n\t\t\t\r\n\t\t\tVector&\t\t\tRotate\t\t( const Quat& quat );\r\n\t\t\tVector&\t\t\tRotate\t\t( const Matrix& matrix );\r\n\t\t\tVector&\t\t\tRotate\t\t( const Vector& axis, const float angle );\r\n\t\t\t\r\n\t\t\t// 90 degree increment Rotation (uses no multiplication)\r\n\t\t\tVector&\t\t\tRotateY90\t( ERot90 angle );\r\n\r\n\t\t\tVector&\t\t\tScale\t\t( float scale );\r\n\t\t\tVector&\t\t\tScale\t\t( const Vector& scale );\r\n\r\n\t\t\tVector&\t\t\tRotateToPlane(const Vector& normal);\r\n\t\t\tVector&\t\t\tRotateToNormal(const Vector& normal);\r\n\t\t\tVector&\t\t\tProjectToPlane(const Vector& normal);\r\n\t\t\tVector&\t\t\tProjectToNormal(const Vector& normal);\r\n\r\n\t\t\tVector&\t\t\tZeroIfShorterThan\t( float length );\t\t\t\t \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\tVector&\t\t\tClampMin\t( float min );\r\n\t\t\tVector&\t\t\tClampMax\t( float max );\r\n\t\t\tVector&\t\t\tClamp\t\t( float min = 0.0f, float max = 1.0f );\r\n\t\t\tVector&\t\t\tClampMin\t( Vector& min );\r\n\t\t\tVector&\t\t\tClampMax\t( Vector& max );\r\n\t\t\tVector&\t\t\tClamp\t\t( Vector& min, Vector& max );\r\n\r\n\t\t\tfloat\t\t\tGetX\t\t( void ) const;\r\n\t\t\tfloat\t\t\tGetY\t\t( void ) const;\r\n\t\t\tfloat\t\t\tGetZ\t\t( void ) const;\r\n\t\t\tfloat \t\t\tGetW\t\t( void ) const;\r\n\t\t\tfloat\t\t\tGetMaxAxis\t( int *whichAxis = NULL );\r\n\r\n\t\t\tvoid\t\t\tDegreesToRadians( void );\r\n\t\t\tvoid\t\t\tRadiansToDegrees( void );\r\n\t\t\tvoid\t\t\tFeetToInches( void );\r\n\t\t\t// convert to 3d studio max coords ( Z+ up, Y- forward, X to the right... )\r\n\t\t\tvoid\t\t\tConvertToMaxCoords( void );\r\n\t\t\tvoid\t\t\tConvertFromMaxCoords( void );\r\n\t\t\t\r\n\t\t\t// debug info\r\n\t\t\tvoid\t\t\tPrintContents() const;\r\n\t\t\t\r\nprivate:\r\n\r\n\t\t\tenum\r\n\t\t\t{\r\n\t\t\t\tNUM_ELEMENTS = 4\r\n\t\t\t};\r\n\t\t\r\n\t\t\tfloat\t\t\t\tcol[NUM_ELEMENTS];\r\n} nAlign(128);\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nVector\t\toperator+ ( const Vector& v1, const Vector& v2 );\r\nVector\t\toperator- ( const Vector& v1, const Vector& v2 );\r\nVector\t\toperator* ( const Vector& v, const float s );\r\nVector\t\toperator* ( const float s, const Vector& v );\r\nVector\t\toperator* ( const Vector& v, const Matrix& m );\r\nVector\t\toperator/ ( const Vector& v, const float s );\r\nVector\t\toperator- ( const Vector& v );\r\nfloat\t\tDotProduct ( const Vector& v1, const Vector& v2 );\r\nVector\t\tCrossProduct ( const Vector& v1, const Vector& v2 );\r\nVector\t\tClamp ( const Vector& v, float min = 0.0f, float max = 1.0f );\r\nVector\t\tClamp ( const Vector& v, Vector& min, Vector& max );\r\nfloat\t\tDistance ( const Vector& v1, const Vector& v2 );\r\nfloat\t\tDistanceSqr ( const Vector& v1, const Vector& v2 );\r\nfloat  \t\tGetAngle\t( const Matrix &currentOrientation, const Vector &desiredHeading, int headingAxis = Z, int rotAxis = Y );\r\nfloat\t\tGetAngle(Vector &v1, Vector &v2);\r\nbool \t\tAngleBetweenGreaterThan(const Vector& a, const Vector& b, float Angle);\r\nfloat \t\tGetAngleAbout(Vector &v1, Vector &v2, Vector &Axis);\r\nbool\t\tEqual ( const Vector& v1, const Vector& v2, const float tol = 0.0001f );\r\nVector\t\tLerp ( const Vector& v1, const Vector& v2, const float val );\r\nVector\t\tMin ( const Vector& v1, const Vector& v2 );\r\nVector\t\tMax ( const Vector& v1, const Vector& v2 );\r\nVector\t\tMin ( const Vector& v, float c );\r\nVector\t\tMax ( const Vector& v, float c );\r\nvoid\t\tSwap ( Vector& a, Vector& b );\r\nostream& \toperator<< ( ostream& os, const Vector& v );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Mth\r\n\r\n#endif // __CORE_MATH_VECTOR_H\r\n\r\n"
  },
  {
    "path": "Code/Core/Math/vector.inl",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (Mth)\t\t\t   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/math/Vector.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t11/29/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tVector Math Class\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_MATH_VECTOR_INL\r\n#define __CORE_MATH_VECTOR_INL\r\n\r\n#ifdef __PLAT_NGPS__\r\n#include <libvu0.h>\r\n\r\n\t \r\n#define\t__USE_VU0__\r\n\t \r\n#ifdef\t\tDEBUG_UNINIT_VECTORS\r\n#undef\t__USE_VU0__\r\n#endif\r\n\r\n#ifdef\t\tDEBUG_OVERFLOW_VECTORS\r\n#undef\t__USE_VU0__\r\n#endif\r\n\r\n#endif\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tPrivate Inline Functions\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mth\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tPublic Inline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Unitialized vectors always need overwriting\r\n// for now we debug this by setting them to a NaN value\r\n// which we can check for later (and some platforms will check automatically)\r\n\r\n\r\n#ifdef\t__INITIALIZE_VECTORS__\r\ninline Vector::Vector (  )\r\n{\t\r\n\tcol[X] = 0.0f;\r\n\tcol[Y] = 0.0f;\r\n\tcol[Z] = 0.0f;\r\n\tcol[W] = 1.0f;\r\n}\r\n#else\r\n#ifdef\t\tDEBUG_UNINIT_VECTORS\r\ninline Vector::Vector (  )\r\n{\t\r\n\t*((uint32*)(&col[X])) = 0x7F800001;\t\t\t\t// Positive NANS (Not A Number - Signaling)\r\n\t*((uint32*)(&col[Y])) = 0x7F800002;\t\t\t\t// Positive NANS (Not A Number - Signaling)\r\n\t*((uint32*)(&col[Z])) = 0x7F800003;\t\t\t\t// Positive NANS (Not A Number - Signaling)\r\n\t*((uint32*)(&col[W])) = 0x7F800004;\t\t\t\t// Positive NANS (Not A Number - Signaling)\r\n}\r\n#else\r\ninline Vector::Vector (  )\r\n{\t\r\n}\r\n\r\n#endif\r\n#endif\r\n\r\n\r\n\r\ninline Vector::Vector ( ENoInitType )\r\n{\r\n    // DO NOTHING\r\n}\r\n\r\ninline Vector::Vector ( float cx, float cy, float cz)\r\n{\t\r\n\tcol[X] = cx;\r\n\tcol[Y] = cy;\r\n\tcol[Z] = cz;\r\n\tcol[W] = 1.0f;\r\n}\r\n\r\n\r\ninline Vector::Vector ( float cx, float cy, float cz, float cw )\r\n{\t\t\t\r\n\tcol[X] = cx;\r\n\tcol[Y] = cy;\r\n\tcol[Z] = cz;\r\n\tcol[W] = cw;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifndef\t\tDEBUG_UNINIT_VECTORS\r\n#ifndef\t\tDEBUG_OVERFLOW_VECTORS\r\n\r\ninline const float&\t\tVector::operator[] ( sint i ) const\r\n{\r\n\treturn col[i];\r\n}\r\n\r\n#endif\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float&\t\t\tVector::operator[] ( sint i )\r\n{\r\n\t\r\n\t\r\n//\tDbg_MsgAssert (( i >= X && i < NUM_ELEMENTS ),( \"index out of range\" ));\r\n\t\r\n\treturn col[i];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifndef\t\tDEBUG_UNINIT_VECTORS\r\n\r\ninline Vector&\t\tVector::operator=\t( const Vector& v )\r\n{\t\r\n\r\n#ifdef\t__USE_VU0__\r\n\t// Not really VU0, but it's hardware specific\r\n\t*(uint128*)(this) = *(uint128*)(&v);\r\n#else\r\n\t\r\n\tcol[X] = v[X];\r\n\tcol[Y] = v[Y];\r\n\tcol[Z] = v[Z];\r\n\tcol[W] = v[W];\r\n#endif\t\r\n\treturn *this;\r\n}\r\n\r\n#endif\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector::Vector ( const Vector& v ) \r\n{\r\n\t\r\n\t\r\n\t*this = v;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\t\tVector::operator== ( const Vector& v ) const\r\n{\t\r\n\t\r\n\r\n\treturn (( col[X] == v[X] ) && \r\n\t\t\t( col[Y] == v[Y] ) &&\r\n\t\t\t( col[Z] == v[Z] ) &&\r\n\t\t\t( col[W] == v[W] ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\t\tVector::operator!= ( const Vector& v ) const\r\n{\t\r\n\t\r\n\r\n\treturn !( *this == v );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::operator+= ( const Vector& v )\r\n{\r\n\t\r\n\t\r\n\tcol[X] += v[X];\r\n\tcol[Y] += v[Y];\r\n\tcol[Z] += v[Z];\r\n\tcol[W] += v[W];\r\n\t\r\n\treturn *this;\r\n}\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::operator-= ( const Vector& v )\r\n{\r\n\t\r\n\t\r\n\tcol[X] -= v[X];\r\n\tcol[Y] -= v[Y];\r\n\tcol[Z] -= v[Z];\r\n\tcol[W] -= v[W];\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::operator*= ( const float s )\r\n{\r\n\t\r\n\t\r\n\tcol[X] *= s;\r\n\tcol[Y] *= s;\r\n\tcol[Z] *= s;\r\n\tcol[W] *= s;\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::operator/= ( float s )\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert( s != 0,( \"Divide by zero\" ));\r\n\r\n\ts = 1.0f / s;\r\n\t\r\n\tcol[X] *= s;\r\n\tcol[Y] *= s;\r\n\tcol[Z] *= s;\r\n\tcol[W] *= s;\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef\t__USE_VU0__\r\ninline void xsceVu0MulVector(sceVu0FVECTOR v0, sceVu0FVECTOR v1, sceVu0FVECTOR v2)\r\n{\r\n\tasm __volatile__(\"\r\n\t.set noreorder\r\n\tlqc2    vf4,0x0(%1)\r\n\tlqc2    vf5,0x0(%2)\r\n\tvmul.xyzw\tvf6,vf4,vf5\r\n\tsqc2    vf6,0x0(%0)\r\n\t.set reorder\r\n\t\": : \"r\" (v0) , \"r\" (v1), \"r\" (v2));\r\n}\r\n#endif\r\n\r\ninline Vector&\t\tVector::operator*= ( const Vector& v )\r\n{\r\n#ifndef\t__USE_VU0__\r\n\t\r\n\tcol[X] *= v[X];\r\n\tcol[Y] *= v[Y];\r\n\tcol[Z] *= v[Z];\r\n\tcol[W] *= v[W];\r\n#\telse\r\n\txsceVu0MulVector(col,(float*)v.col,col);\t\r\n#\tendif\r\n\treturn *this;\r\n\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::operator/= ( const Vector& v )\r\n{\r\n\t\r\n\t\r\n\r\n\tDbg_MsgAssert( v[X] != 0,( \"Divide by zero X\" ));\r\n\tDbg_MsgAssert( v[Y] != 0,( \"Divide by zero Y\" ));\r\n\tDbg_MsgAssert( v[Z] != 0,( \"Divide by zero Z\" ));\r\n\tDbg_MsgAssert( v[W] != 0,( \"Divide by zero W\" ));\r\n\r\n\tcol[X] /= v[X];\r\n\tcol[Y] /= v[Y];\r\n\tcol[Z] /= v[Z];\r\n\tcol[W] /= v[W];\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::operator*= ( const Matrix& mat )\r\n{\t\r\n\r\n\t#ifdef\t__USE_VU0__\r\n\tsceVu0ApplyMatrix((sceVu0FVECTOR)this,(sceVu0FMATRIX)&mat,(sceVu0FVECTOR)this);\r\n\t#else\t\t\r\n\t\r\n\tVector\tv=*this;\r\n\r\n\tcol[X] = v[X] * mat[X][X] + v[Y] * mat[Y][X] + v[Z] * mat[Z][X] + v[W] * mat[W][X];\r\n\tcol[Y] = v[X] * mat[X][Y] + v[Y] * mat[Y][Y] + v[Z] * mat[Z][Y] + v[W] * mat[W][Y];\r\n\tcol[Z] = v[X] * mat[X][Z] + v[Y] * mat[Y][Z] + v[Z] * mat[Z][Z] + v[W] * mat[W][Z];\r\n\tcol[W] = v[X] * mat[X][W] + v[Y] * mat[Y][W] + v[Z] * mat[Z][W] + v[W] * mat[W][W];\r\n\r\n\t#endif\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::Set ( float cx, float cy, float cz, float cw )\r\n{\r\n\t\r\n\t\r\n\tcol[X] = cx;\r\n\tcol[Y] = cy;\r\n\tcol[Z] = cz;\r\n\tcol[W] = cw;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float\t\t\tVector::LengthSqr\t( void ) const\r\n{\r\n\t\r\n\r\n\treturn (( col[X] * col[X] ) + \r\n\t\t\t( col[Y] * col[Y] ) +\r\n\t\t\t( col[Z] * col[Z] ));\r\n}\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float\t\t\tVector::Length ( void ) const\r\n{\r\n\t\r\n\t\r\n\treturn sqrtf ( LengthSqr ());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::Negate ( void )\r\n{\r\n\t\r\n\r\n\tcol[X] = -col[X];\r\n\tcol[Y] = -col[Y];\r\n\tcol[Z] = -col[Z];\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::Negate ( const Vector& src )\r\n{\r\n\t\r\n\r\n\tcol[X] = -src[X];\r\n\tcol[Y] = -src[Y];\r\n\tcol[Z] = -src[Z];\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef\t__USE_VU0__\r\n// currenntly this version seems to have problems with instrcutionre-ordering,\r\n// so don't use it unless you figure it out.\r\n// Note:  it was originally a non-inline library function, so those problems would not occur\r\ninline void xsceVu0Normalize(sceVu0FVECTOR v0, sceVu0FVECTOR v1)\r\n{\r\n        asm __volatile__(\"\r\n\t\t.set noreorder\r\n        lqc2    vf4,0x0(%1)\r\n        vmul.xyz vf5,vf4,vf4\r\n        vaddy.x vf5,vf5,vf5\r\n        vaddz.x vf5,vf5,vf5\r\n\r\n        vsqrt Q,vf5x\r\n        vwaitq\r\n        vaddq.x vf5x,vf0x,Q\r\n        vdiv    Q,vf0w,vf5x\r\n        vsub.xyzw vf6,vf0,vf0           #vf6.xyzw=0;\r\n        vwaitq\r\n\r\n        vmulq.xyz  vf6,vf4,Q\r\n        sqc2    vf6,0x0(%0)\r\n\t\t.set reorder\r\n        \": : \"r\" (v0) , \"r\" (v1));\r\n}\r\n#endif\r\n\r\ninline Vector&\t\tVector::Normalize( )\r\n{\t\r\n\t\r\n\r\n//#\tif 0\t\t\t\r\n#ifdef\t__USE_VU0__\r\n// currenntly inline (xsce) version seems to have problems with instrcutionre-ordering,\r\n// so don't use it unless you figure it out.\r\n\tsceVu0Normalize(col,col);\t\t// NOTE::: using the non-inline version  (not xsce....)\r\n#\telse\r\n\tfloat l = Length();\r\n\tif ( l > 0.0f ) \r\n\t{\r\n\t\tl = 1.0f / l;\r\n\r\n\t\tcol[X] *= l;\r\n\t\tcol[Y] *= l;\r\n\t\tcol[Z] *= l;\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tDbg_MsgAssert(0,(\"Normalizing vector of zero length\"));\r\n\t}\r\n#\tendif\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::Normalize\t( float len )\r\n{\t\r\n\t\r\n\r\n\tfloat l = Length();\r\n\tif ( l > 0.0f ) \r\n\t{\r\n\t\tl = len / l;\r\n\r\n\t\tcol[X] *= l;\r\n\t\tcol[Y] *= l;\r\n\t\tcol[Z] *= l;\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tDbg_MsgAssert(0,(\"Normalizing vector of zero length\"));\r\n\t}\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::ShearX ( float shy, float shz )\r\n{\t\r\n\t\r\n\t\r\n\tcol[X] += (( col[Y] * shy ) + ( col[Z] * shz ));\r\n\t\r\n\treturn *this;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::ShearY ( float shx, float shz )\r\n{\t\r\n\t\r\n\r\n\tcol[Y] += (( col[X] * shx ) + ( col[Z] * shz ));\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::ShearZ ( float shx, float shy )\r\n{\t\r\n\t\r\n\r\n\tcol[Z] += (( col[X] * shx ) + ( col[Y] * shy ));\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::RotateX ( float s, float c )\r\n{\t\r\n\t\r\n\r\n\tfloat y = ( c * col[Y] ) - ( s * col[Z] );\r\n\tfloat z = ( s * col[Y] ) + ( c * col[Z] );\r\n\t\r\n\tcol[Y] = y;\r\n\tcol[Z] = z;\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::RotateY ( float s, float c )\r\n{\t\r\n\t\r\n\r\n\tfloat x = (  c * col[X] ) + ( s * col[Z] );\r\n\tfloat z = ( -s * col[X] ) + ( c * col[Z] );\r\n\t\r\n\tcol[X] = x;\r\n\tcol[Z] = z;\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::RotateZ ( float s, float c )\r\n{\r\n\t\r\n\t\r\n\tfloat x = ( c * col[X] ) - ( s * col[Y] );\r\n\tfloat y = ( s * col[X] ) + ( c * col[Y] );\r\n\t\r\n\tcol[X] = x;\r\n\tcol[Y] = y;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::RotateX\t( float angle )\t\r\n{\t\r\n\t\r\n\r\n\treturn RotateX ( sinf ( angle ), cosf ( angle ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::RotateY\t( float angle )\t\r\n{\r\n\t\r\n\t\r\n\treturn RotateY ( sinf ( angle ), cosf ( angle ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::RotateZ\t( float angle )\t\r\n{\r\n\t\r\n\t\r\n\treturn RotateZ ( sinf ( angle ), cosf ( angle ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::Rotate ( const Quat& quat )\t\r\n{\r\n\t\r\n\t\r\n\t*this = quat.Rotate ( *this );\r\n\r\n  \treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::Rotate ( const Matrix& mat )\t\r\n{\r\n\t\r\n\t\r\n\t*this = mat.Rotate ( *this );\r\n\r\n  \treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::Rotate ( const Vector& axis, const float angle )\t\r\n{\r\n\t\r\n#if 0\r\n\tMatrix\tmat( axis, angle );\r\n\t*this = mat.Rotate( *this );\r\n#else\r\n\tQuat\tquat( axis, angle );\r\n\t*this = quat.Rotate( *this );\r\n#endif\r\n\r\n  \treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::Scale ( float scale )\r\n{\r\n\tcol[X] *= scale;\r\n\tcol[Y] *= scale;\r\n\tcol[Z] *= scale;\r\n\tcol[W] *= scale;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::Scale ( const Vector& scale )\r\n{\r\n\tcol[X] *= scale[X];\r\n\tcol[Y] *= scale[Y];\r\n\tcol[Z] *= scale[Z];\r\n\tcol[W] *= scale[W];\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::ClampMin\t( float min )\r\n{\r\n\t\r\n\r\n\tcol[X] = Mth::ClampMin ( col[X], min );\r\n\tcol[Y] = Mth::ClampMin ( col[Y], min );\r\n\tcol[Z] = Mth::ClampMin ( col[Z], min );\r\n\tcol[W] = Mth::ClampMin ( col[W], min );\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::ClampMax\t( float max )\r\n{\r\n\t\r\n\r\n\tcol[X] = Mth::ClampMax ( col[X], max );\r\n\tcol[Y] = Mth::ClampMax ( col[Y], max );\r\n\tcol[Z] = Mth::ClampMax ( col[Z], max );\r\n\tcol[W] = Mth::ClampMax ( col[W], max );\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::Clamp\t( float min, float max )\r\n{\r\n\t\r\n\r\n\tcol[X] = Mth::ClampMin ( Mth::ClampMax ( col[X], max ), min );\r\n\tcol[Y] = Mth::ClampMin ( Mth::ClampMax ( col[Y], max ), min );\r\n\tcol[Z] = Mth::ClampMin ( Mth::ClampMax ( col[Z], max ), min );\r\n\tcol[W] = Mth::ClampMin ( Mth::ClampMax ( col[W], max ), min );\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::ClampMin\t( Vector& min )\r\n{\r\n\t\r\n\r\n\tcol[X] = Mth::ClampMin ( col[X], min[X] );\r\n\tcol[Y] = Mth::ClampMin ( col[Y], min[Y] );\r\n\tcol[Z] = Mth::ClampMin ( col[Z], min[Z] );\r\n\tcol[W] = Mth::ClampMin ( col[W], min[W] );\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::ClampMax\t( Vector& max )\r\n{\r\n\t\r\n\r\n\tcol[X] = Mth::ClampMax ( col[X], max[X] );\r\n\tcol[Y] = Mth::ClampMax ( col[Y], max[Y] );\r\n\tcol[Z] = Mth::ClampMax ( col[Z], max[Z] );\r\n\tcol[W] = Mth::ClampMax ( col[W], max[W] );\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::Clamp\t( Vector& min, Vector& max )\r\n{\r\n\t\r\n\r\n\tcol[X] = Mth::ClampMin ( Mth::ClampMax ( col[X], max[X] ), min[X] );\r\n\tcol[Y] = Mth::ClampMin ( Mth::ClampMax ( col[Y], max[Y] ), min[Y] );\r\n\tcol[Z] = Mth::ClampMin ( Mth::ClampMax ( col[Z], max[Z] ), min[Z] );\r\n\tcol[W] = Mth::ClampMin ( Mth::ClampMax ( col[W], max[W] ), min[W] );\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tVector::GetX( void ) const\r\n{\r\n\t\r\n\r\n\treturn col[X];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tVector::GetY( void ) const\r\n{\r\n\t\r\n\t\r\n\treturn col[Y];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tVector::GetZ( void ) const\r\n{\r\n\t\r\n\t\r\n\treturn col[Z];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tVector::GetW( void ) const\r\n{\r\n\t\r\n\t\r\n\treturn col[W];\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\toperator+\t( const Vector& v1, const Vector& v2 )\r\n{\t\r\n\t\r\n\t\r\n\treturn Vector ( v1[X] + v2[X], v1[Y] + v2[Y], v1[Z] + v2[Z], v1[W] + v2[W] );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\toperator-\t( const Vector& v1, const Vector& v2 )\r\n{\r\n\t\r\n\r\n\treturn Vector ( v1[X] - v2[X], v1[Y] - v2[Y], v1[Z] - v2[Z], v1[W] - v2[W] );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\toperator*\t( const Vector& v, const float s )\r\n{\r\n\t\r\n\t\r\n\treturn Vector ( v[X] * s, v[Y] * s, v[Z] * s, v[W] * s );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\toperator*\t( const float s, const Vector& v )\r\n{\r\n\t\r\n\r\n\treturn v * s;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector\toperator* ( const Vector& v, const Matrix& m )\r\n{\t\r\n\r\n\t#ifdef\t__USE_VU0__\r\n\t// Mick:\r\n\tMth::Vector\tresult;\r\n\tsceVu0ApplyMatrix((sceVu0FVECTOR)&result,(sceVu0FMATRIX)&m,(sceVu0FVECTOR)&v);\r\n\treturn result;\r\n\t#else\t\r\n\t// Mick:  This is REALLY SLOW, as it calls Mth::Matrix operator[]\t\r\n\treturn Vector ( v[X] * m[X][X] + v[Y] * m[Y][X] + v[Z] * m[Z][X] + v[W] * m[W][X],\r\n\t\t\t\t\tv[X] * m[X][Y] + v[Y] * m[Y][Y] + v[Z] * m[Z][Y] + v[W] * m[W][Y],\r\n\t\t\t\t\tv[X] * m[X][Z] + v[Y] * m[Y][Z] + v[Z] * m[Z][Z] + v[W] * m[W][Z],\r\n\t\t\t\t\tv[X] * m[X][W] + v[Y] * m[Y][W] + v[Z] * m[Z][W] + v[W] * m[W][W]);\r\n\t#endif\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\toperator/\t( const Vector& v, const float s )\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert (( s != 0.0f ),( \"Divide by Zero\" ));\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\tfloat r = 1.0f / s; \r\n\t\r\n\treturn v * r;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\toperator-\t( const Vector& v )\r\n{\r\n\t\r\n\t\r\n\treturn Vector ( -v[X], -v[Y], -v[Z], -v[W] );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tDotProduct ( const Vector& v1, const Vector& v2 ) \r\n{\r\n\t\r\n\t\r\n\treturn ( v1[X] * v2[X] ) + ( v1[Y] * v2[Y] ) + ( v1[Z] * v2[Z] );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\tCrossProduct ( const Vector& v1, const Vector& v2 ) \r\n{\t\r\n\treturn Vector (( v1[Y] * v2[Z] ) - ( v1[Z] * v2[Y] ),\r\n\t\t\t\t   ( v1[Z] * v2[X] ) - ( v1[X] * v2[Z] ),\r\n\t\t\t\t   ( v1[X] * v2[Y] ) - ( v1[Y] * v2[X] ),\r\n\t\t\t\t   0.0f );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\tClamp ( const Vector& v, float min, float max )\r\n{\t\r\n\t\r\n\r\n\tVector f = v;\r\n\t\r\n\tf.Clamp ( min, max );\r\n\r\n\treturn f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\tClamp ( const Vector& v, Vector& min, Vector& max )\r\n{\t\r\n\t\r\n\r\n\tVector f = v;\r\n\t\r\n\tf.Clamp ( min, max );\r\n\r\n\treturn f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tDistance ( const Vector& v1, const Vector& v2 )\r\n{\t\r\n\t\r\n\t\r\n\tVector d = v1 - v2;\r\n\t\r\n\treturn sqrtf ( DotProduct ( d, d ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tfloat\tDistanceSqr ( const Vector& v1, const Vector& v2 )\r\n{\r\n\t\r\n\r\n\tVector d = v1 - v2;\r\n\t\r\n\treturn ( DotProduct ( d, d ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tbool\tEqual ( const Vector& v1, const Vector& v2, const float tol )\r\n{\t\r\n\t\r\n\r\n\treturn ( Equal ( v1[X], v2[X], tol ) && \r\n\t\t\t Equal ( v1[Y], v2[Y], tol ) && \r\n\t\t\t Equal ( v1[Z], v2[Z], tol ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\tLerp ( const Vector& v1, const Vector& v2, const float val )\r\n{\t\r\n\t\r\n\t\r\n\treturn Vector ( v1 + ( v2 - v1 ) * val );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\tLinearMap ( const Vector& v1, const Vector& v2, float value, float value_min, float value_max )\r\n{\r\n\treturn Vector ( v1 + ( v2 - v1 ) * ( (value - value_min) / (value_max - value_min) ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\tMin ( const Vector& v1, const Vector& v2 )\r\n{\r\n\t\r\n\t\r\n\treturn Vector ( Min ( v1[X], v2[X] ), \r\n\t\t\t\t\tMin ( v1[Y], v2[Y] ),\r\n\t\t\t\t\tMin ( v1[Z], v2[Z] ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\tMax ( const Vector& v1, const Vector& v2 )\r\n{\t\r\n\t\r\n\t\r\n\treturn Vector ( Max ( v1[X], v2[X] ), \r\n\t\t\t\t\tMax ( v1[Y], v2[Y] ),\r\n\t\t\t\t\tMax ( v1[Z], v2[Z] ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\tMin ( const Vector& v, float c )\t\r\n{\t\r\n\t\r\n\t\r\n\treturn Min ( v, Vector ( c, c, c, 1.0f ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tVector\tMax ( const Vector& v, float c )\t\r\n{\r\n\t\r\n\t\r\n\treturn Max ( v, Vector ( c, c, c, 0.0f ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\tSwap ( Vector& a, Vector& b )\r\n{\r\n\t\r\n\t\r\n\tVector t = a;\r\n\t\r\n\ta = b;\r\n\tb = t;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Vector&\t\tVector::ZeroIfShorterThan ( float length )\t\r\n{\r\n\t\r\n\r\n\tif (LengthSqr() < length *length)\r\n\t{\r\n\t\tSet(0.0f,0.0f,0.0f,0.0f);\t\t\r\n\t}\r\n\t\r\n  \treturn *this;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline ostream& operator<< ( ostream& os, const Vector& v )\r\n{\r\n\treturn os << \"( \" << v[X] << \", \" << v[Y] << \", \" << v[Z] << \", \" << v[W] << \" )\";\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mth\r\n\r\n#endif // __CORE_MATH_VECTOR_INL   \r\n\r\n"
  },
  {
    "path": "Code/Core/String/CString.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tString      \t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCore\\String\\CString.cpp\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t9/20/2000 - rjm\t\t\t\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tA handy, safe class to represent a string\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/string/cstring.h>\r\n#include <sys/mem/memman.h>\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Str\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nconst int String::s_max_size = 256;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint String::sDumbCount = 0;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************************\r\n *\r\n * Function:\t\r\n *\r\n * Description: Default constructor\t\t\t\r\n *\r\n * Parameters:\t\r\n * \r\n *****************************************************************************/\r\n\r\n\r\nString::String( void )\r\n: mp_string( NULL )\r\n{\r\n//    \r\n    \r\n    \r\n    m_dumbNum = sDumbCount;\r\n\tsDumbCount++;    \r\n}\r\n\r\n\r\n\r\n/******************************************************************************\r\n *\r\n * Description: First copy constructor\t\r\n *              (called by: String x = \"blah\";) \t\t\r\n * \r\n *****************************************************************************/\r\n\r\nString::String( const char* string )\r\n: mp_string ( NULL )\r\n{\r\n//    \r\n    \r\n    \r\n    \r\n    m_dumbNum = sDumbCount;\r\n\tsDumbCount++;\r\n    \r\n\t// call operator= function\r\n    *this = string;\r\n\r\n\t//Ryan(\"copy successful\\n\");\r\n}\r\n\r\n\r\n\r\n/******************************************************************************\r\n *\r\n * Description: Second copy constructor\t\t\t\r\n * \r\n *****************************************************************************/\r\n\r\nString::String( const String& string )\r\n: mp_string ( NULL )\r\n{\r\n//    \r\n    \r\n    \r\n    // call operator= function\r\n    *this = string;\r\n\r\n    m_dumbNum = sDumbCount;\r\n\tsDumbCount++;\r\n}\r\n\r\n\r\n\r\n/******************************************************************************\r\n *\r\n * Description: destructor\t\t\t\r\n * \r\n *****************************************************************************/\r\n\r\nString::~String( void )\r\n{\r\n//    \r\n    \r\n    \r\n\t//Ryan(\"Am deleting string\");\r\n\t\r\n\tif (mp_string)\r\n\t{\r\n\t\tdelete [] mp_string;\r\n\t\tmp_string = NULL;\r\n\t}\r\n\r\n\t//Ryan(\"\\n\");\r\n\tsDumbCount--;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nString & String::operator= (const char * string)\r\n{\r\n//    \r\n    \r\n    \r\n    int last_char = 0;\r\n\tif ( string )\r\n\t{\r\n\t\tlast_char = strlen(string) - 1;\r\n\r\n\t\t// Fix the case where \"string\" is the empty string\r\n\t\tif( last_char < 0 )\r\n\t\t{\r\n\t\t\tlast_char = 0;\r\n\t\t}\r\n\t}\r\n\tcopy(string, 0, last_char);\r\n\r\n    //Ryan(\"Copying %s to String\\n\", mp_string);\r\n    \r\n    return *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nString & String::operator= (const String & string)\r\n{\r\n//    \r\n    \r\n    \r\n    Dbg_MsgAssert(this != &string,( \"can't assign a String to itself\"));\r\n\t\r\n\t// call other operator= function\r\n    *this = string.mp_string;\r\n    return *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool String::operator== (const char * string)\r\n{\r\n//    \r\n    \r\n    \r\n    //Ryan(\"comparing String to string: %s to %s\\n\", mp_string, string);\r\n    if (mp_string && string)\r\n\t{\r\n\t\treturn (strcmp(mp_string, string) == 0); \r\n\t}\r\n\r\n\treturn (!mp_string && !string);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool String::operator== (const String & string)\r\n{\r\n//    \r\n    \r\n    \r\n    //Ryan(\"comparing String to String: %s to %s\\n\", mp_string, string.mp_string);\r\n    return (*this == string.mp_string);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool String::operator!()\r\n{\r\n\treturn (mp_string == NULL);\r\n}\r\n\r\n/******************************************************************************\r\n *\r\n * Description: Returns pointer to internal char * array. Maybe should be const.\t\t\t\r\n * \r\n *****************************************************************************/\r\n\r\nconst char * String::getString() const\r\n{\r\n//    \r\n    \r\n    \r\n    return mp_string;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid String::copy(const char *pChar, int first_char, int last_char)\r\n{\r\n    \r\n\t\r\n\tif ( pChar && last_char >= first_char)\r\n\t{\r\n// GJ: The following handles 1-byte long strings incorrectly:\r\n//\t\tif ( first_char == last_char )\r\n\t\t\t\r\n\t\tif ( pChar[first_char] == 0 )\r\n\t\t{\r\n\t\t\tif (mp_string)\r\n\t\t\t{\r\n\t\t\t\tdelete [] mp_string;\t\t\r\n\t\t\t}\r\n\t\t\tmp_string = new char[1];\r\n\t\t\tmp_string[0] = 0;\r\n\t\t\tm_length = 2;\t\t\t\t// MICK-GJ:  Set length to 2, so it matches what we have below\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tint length = last_char - first_char + 2;\r\n\t\t\tif (length < 4) length = 4;\r\n\t\t\tDbg_MsgAssert (length <= s_max_size,( \"string too long for String object\"));\r\n\r\n\t\t\t// if current string exists and is smaller than new string, delete it\r\n\t\t\tif ( mp_string && ( length > m_length ))\r\n\t\t\t{\r\n\t\t\t\tdelete [] mp_string;\r\n\t\t\t\tmp_string = NULL;\r\n\t\t\t}\r\n\r\n\t\t\t// if current string doesn't exist, or has been deleted, make a new one\r\n\t\t\tif ( !mp_string )\r\n\t\t\t{\r\n\t\t\t\tm_length = length;\r\n\t\t\t\tmp_string = new char[m_length];\r\n\t\t\t}\r\n\r\n\t\t\t// perform string copy\r\n\t\t\tint i = 0;\r\n\t\t\tint j;\r\n\t\t\tfor (j = first_char; j <= last_char; j++)\r\n\t\t\t{\r\n\t\t\t\tmp_string[i] = pChar[j];\r\n\t\t\t\ti++;\r\n\t\t\t}\r\n\t\t\tmp_string[i] = '\\0';\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( mp_string )\r\n\t\t{\r\n\t\t\tdelete [] mp_string;\r\n\t\t\tmp_string = NULL;\r\n\t\t}\r\n\t}\r\n\t\r\n\t//Ryan(\"copied string %s\\n\", pChar);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace String\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/String/CString.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tString      \t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCore\\String\\CString.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t9/20/2000 - rjm\t\t\t\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tA handy, safe class to represent a string\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_STRING_STRING_H\r\n#define __CORE_STRING_STRING_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_SUPPORT_CLASS_H\r\n    #include <core/support/class.h>\r\n#endif\r\n        \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Str\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/****************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n * Class:\t\t\tString\r\n *\r\n * Description:\t\tA handy, safe class for representing a string.\r\n *\r\n *                  Usage:  String x = \"try our new diet of pinecones\";\r\n *                          String y = x;                          \r\n *                          printf(\"%s\\n\", y.getString());\r\n *\r\n ****************************************************************************/\r\n\r\nclass String : public Spt::Class\t\t// fix bug delete[] !!!\r\n{\r\n\r\npublic:\r\n\t\t\t\tString();\r\n\t\t\t\tString(const char *string);\r\n\t\t\t\tString(const String &string);\r\n\t~String();\r\n\r\n    String& \toperator= (const char * string);\r\n    String& \toperator= (const String & string);\r\n    bool \t\toperator== (const char * string);\r\n    bool \t\toperator== (const String & string);\r\n\tbool\t\toperator!();\r\n\r\n    const char*\tgetString() const;\r\n\tvoid\t\tcopy(const char *pChar, int first_char, int last_char);\r\n    \r\n\tint\t\t\tm_dumbNum;\r\n\tstatic int \tsDumbCount;\r\n\r\nprivate:\r\n    char*\t\tmp_string;\r\n    int\t\t\tm_length;\r\n\r\n\r\n    static const int s_max_size;\r\n};\r\n    \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace String\r\n\r\n#endif\t// __CORE_STRING_STRING_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/String/stringutils.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tString\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tstringutils.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t05/31/01\t-\tMick\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tuseful string (char *) utilities\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <sys/config/config.h>\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Str\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define\tCaseless(letter) (((letter)>='A' && (letter)<='Z')?((letter)+'a'-'A'):letter)\t\t\t \r\n\r\n// Returns location of Needle in the Haystack\t\t\t \r\nconst char * StrStr (const char *pHay, const char *pNeedle)\r\n{\r\n\tregister char First = *pNeedle++;\t\t// get first letter in needle\r\n\tif (!First) return 0;\t\t\t\t\t// if end of needle, then return NULL\r\n\tFirst = Caseless(First);\r\n\r\n\twhile (1)\r\n\t{\r\n\t\twhile (1)\t\t\t\t\t\t\t// scan Haystack one letter at a time \r\n\t\t{\r\n\t\t\tchar FirstHay = *pHay++;\t\t// get first letter of haystack\r\n\t\t\tFirstHay = Caseless(FirstHay);\r\n\t\t\tif (FirstHay == First) break;\t// first letter matches, so drop into other code\r\n\t\t\tif (!FirstHay) return 0;\t\t// if end of haystack, then return NULL\r\n\t\t}\r\n\r\n\t\tconst char *pH = pHay;\t\t\t\t\t// second letter of hay\r\n\t\tconst char *pN = pNeedle;\t\t\t\t\t// second letter of needle\r\n\t\twhile (1)\r\n\t\t{\r\n\t\t\tchar n = *pN++;\t\t\t\t\t// get a needle letter\r\n\t\t\tif (!n) return pHay-1;\t\t\t// end of needle, so return pointer to start of string in haystack\r\n\t\t\tchar h = *pH++;\t\t\t\t\t// get a hay letter\r\n\t\t\tif (Caseless(n) != Caseless(h)) break;\t\t\t\t// difference, so stop looping (could be end of haystack, which is valid)\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid LowerCase(char *p)\r\n{\r\n\twhile (*p)\r\n\t{\r\n\t\tchar letter = *p;\r\n\t\tif (letter>='A' && letter<='Z')\r\n\t\t\tletter+='a'-'A';\r\n\t\t*p++ = letter;\r\n\t}\r\n}\r\n\r\nvoid UpperCase(char *p)\r\n{\r\n\twhile (*p)\r\n\t{\r\n\t\tchar letter = *p;\r\n\t\tif (letter>='a' && letter<='z')\r\n\t\t\tletter-='a'-'A';\r\n\t\t*p++ = letter;\r\n\t}\r\n}\r\n\r\n\r\nint WhiteSpace(char *p)\r\n{\r\n\tif (*p == 0x20 || *p== 0x09)\r\n\t\treturn 1;\r\n\telse\r\n\t\treturn 0;\r\n}\r\n\r\nchar *PrintThousands(int n, char c)\r\n{\r\n\tstatic\tchar buffer[32];\t\t// enough for any int\r\n\tchar\tnormal[32];\t\t\t\t// printf in here without commas\t\r\n\tchar *p = buffer;\r\n\r\n\tif (n<0)\r\n\t{\r\n\t\t*p++ = '-';\r\n\t\tn = -n;\r\n\t}\r\n\tsprintf (normal, \"%d\", n);\r\n\tint digits = strlen(normal);\r\n\tchar *p_digit = normal;\r\n\t\r\n\t// Since other countries deliminate their successive kilos differently\r\n\tswitch (Config::GetLanguage())\r\n\t{\r\n\tcase Config::LANGUAGE_FRENCH:\r\n\t\tc=' ';\r\n\t\tbreak;\r\n\tcase Config::LANGUAGE_SPANISH:\r\n\t\tc='.';\r\n\t\tbreak;\r\n\tcase Config::LANGUAGE_GERMAN:\r\n\t\tc='.';\r\n\t\tbreak;\r\n\tcase Config::LANGUAGE_ITALIAN:\r\n\t\tc='.';\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tc=',';\r\n\t\tbreak;\r\n\t}\r\n\r\n\twhile (digits)\r\n\t{\r\n\t\t*p++ = *p_digit++;\r\n\t\tdigits--;\r\n\t\tif ( digits && ( digits % 3) == 0)\r\n\t\t{\r\n\t\t\t*p++ = c;\r\n\t\t}\t\t\r\n\t}\r\n\t*p++ = 0;\r\n//\tprintf (\"%s\\n\",buffer);\r\n\treturn buffer;\t\r\n}\r\n\r\n\r\n// helper function for SText::Draw(), SFont::QueryString()\r\nuint DehexifyDigit(const char *pLetter)\r\n{\r\n\tuint digit = 0;\r\n\tif (*pLetter >= '0' && *pLetter <= '9')\r\n\t\tdigit = *pLetter - '0';\r\n\telse if (*pLetter >= 'a' && *pLetter <= 'v')\r\n\t\tdigit = *pLetter - 'a' + 10;\r\n\telse if (*pLetter >= 'A' && *pLetter <= 'V')\r\n\t\tdigit = *pLetter - 'A' + 10;\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Non Hex digit\"));\r\n\t}\r\n\treturn digit;\r\n}\r\n\r\n// Returns\r\n// -1 if a<b\r\n//  0 -f a==b\r\n//  1 if a>b\r\n//\r\n//\r\n// if      \r\nint Compare(const char *p_a, const char *p_b)\r\n{\r\n\tfor (;;)\r\n\t{\r\n\t\tchar a = *p_a++;\r\n\t\tchar b = *p_b++;\r\n\t\ta = Caseless(a);\r\n\t\tb = Caseless(b);\r\n\t\tif (a < b)\r\n\t\t{\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t\tif (a > b)\r\n\t\t{\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t\tif (!a && !b)\r\n\t\t{\r\n\t\t\t// strings are identical\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\tif (!a)\r\n\t\t{\r\n\t\t\t// a is shorter, so a < b\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t\tif (!b)\r\n\t\t{\r\n\t\t\t// b is shorter, so b < a\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Str\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/String/stringutils.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tString\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tstringutils.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t05/31/01\t-\tMick\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tuseful string (char *) utilities\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_STRING_STRINGUTILS_H\r\n#define __CORE_STRING_STRINGUTILS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Str\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nconst char*\tStrStr(const char* pHay, const char* pNeedle);\r\nvoid\t\tLowerCase(char* p);\r\nvoid\t\tUpperCase(char* p);\r\nint\t\t\tWhiteSpace(char* p);\r\nchar *\t\tPrintThousands(int n, char c = ',');\r\nuint \t\tDehexifyDigit(const char *pLetter);\r\nint \t\tCompare(const char *p_a, const char *p_b);\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Str\r\n\r\n#endif\t// __DIR_SUBDIR_FILE_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/StringHashTable.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tHashTable      \t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCore\\HashTable.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t9/22/2000 - rjm\t\t\t\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tA handy Hashtable class\t\t\t\t                \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_LIST_STRINGHASHTABLE_H\r\n#define __CORE_LIST_STRINGHASHTABLE_H\r\n\r\n#ifndef __PLAT_WN32__\r\n\t#include <sys/mem/PoolManager.h>\r\n#endif\r\n\r\n#include \"HashTable.h\"\r\n\r\nnamespace Crc\r\n{\r\n\tuint32 GenerateCRCFromString( const char *pName );\r\n}\r\n\r\nnamespace Script\r\n{\r\n\t// So as not to require inclusion of checksum.h\r\n#ifdef __NOPT_ASSERT__\t\r\n\tconst char *FindChecksumName(uint32 checksum);\r\n#endif\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Lst\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntemplate<class _V>\r\nclass StringHashTable : public HashTable<_V>\r\n{\r\n\r\npublic:\r\n\t\t\t\t\t\t\t\t\tStringHashTable(int numBits);\r\n\r\n    bool \t\t\t\t\t\t\tPutItem(const char *stringKey, _V *item);\r\n    _V *\t\t\t\t\t\t\tGetItem(const char *stringKey, bool assert_if_clash = true);\r\n    void \t\t\t\t\t\t\tFlushItem(const char *stringKey);\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntemplate<class _V> //inline\r\nStringHashTable<_V>::StringHashTable(int numBits) :\r\n    HashTable<_V>(numBits)\r\n{\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\nbool StringHashTable<_V>::PutItem(const char *stringKey, _V *item)\r\n{\r\n    uint32 key = Crc::GenerateCRCFromString(stringKey);\r\n    return HashTable<_V>::PutItem(key, item);\r\n}\r\n\r\n\r\n\r\ntemplate<class _V> //inline\r\n_V *StringHashTable<_V>::GetItem(const char *stringKey, bool assert_if_clash)\r\n{\r\n    uint32 key = Crc::GenerateCRCFromString(stringKey);\r\n    return HashTable<_V>::GetItem(key, assert_if_clash);\r\n}\r\n\r\n\r\ntemplate<class _V> //inline\r\nvoid StringHashTable<_V>::FlushItem(const char *stringKey)\r\n{\r\n    uint32 key = Crc::GenerateCRCFromString(stringKey);\r\n    HashTable<_V>::FlushItem(key);\r\n}\r\n\r\n} // namespace Lst\r\n\r\n#endif\t// __CORE_LIST_STRINGHASHTABLE_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Support/Lock.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSupport\t(SPT)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/support/lock.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_LOCK_H\r\n#define __CORE_LOCK_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/support.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Spt\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  Access  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic :\r\n\r\n\t\t\t\tAccess();\r\n\r\n\tvoid\t\tForbid( void );\r\n\tvoid\t\tPermit( void );\r\n\tvoid\t\tEnable( void );\r\n\tbool\t\tHaveAccess( void );\r\n\r\nprivate :\r\n\r\n\tsint\t\tm_count;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline\tAccess::Access()\r\n: m_count( 0 )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tAccess::Forbid( void )\r\n{\r\n\t\r\n\r\n\tm_count++;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tAccess::Permit( void )\r\n{\r\n\t\r\n\r\n\tm_count--;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tAccess::Enable( void )\r\n{\r\n\t\r\n\r\n\tm_count = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tbool\t\tAccess::HaveAccess ( void )\r\n{\r\n\t\r\n\r\n\treturn( m_count == 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Spt\r\n\r\n#endif\t// __CORE_LOCK_H\r\n\r\n"
  },
  {
    "path": "Code/Core/Support/Ref.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSupport\t(SPT)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/support/lock.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t03/16/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_REF_H\r\n#define __CORE_REF_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/support.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Spt\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  Ref  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic :\r\n\r\n\t\t\t\tRef();\r\n\t\t\t\tRef( const Ref& rhs );\r\n\r\n\tvoid\t\tAcquire( void );\r\n\tvoid\t\tRelease( void );\r\n\tbool\t\tInUse( void );\r\n\r\nprivate :\r\n\r\n\tsint\t\tm_count;\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline\tRef::Ref ()\r\n: m_count( 0 )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\ninline\tRef::Ref( const Ref& rhs )\r\n: m_count( 0 )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tRef::Acquire ( void )\r\n{\r\n\t\r\n\r\n\tm_count++;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tRef::Release ( void )\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert(m_count>0,(\"Tried to call Release when m_count was already zero\"));\r\n\tm_count--;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tbool\t\tRef::InUse ( void )\r\n{\r\n\t\r\n\r\n\treturn ( m_count != 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Spt\r\n\r\n#endif\t// __CORE_REF_H\r\n\r\n"
  },
  {
    "path": "Code/Core/Support/class.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSupport (SPT) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tclass.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t06/10/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tBase class from which all other classes are derived.\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdio.h>\r\n#include <string.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <sys/mem/memman.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define NUM_ADDRESS 0\t\t// Change this to 8 to have a handy list of addresses to check.\r\n\t\t\t\t\t\t\t// If set to 0, no extra code/data will be generated.\r\n\t\t\t\t\t\t\t// Remember to change to 8, compile, then get the addresses in question\r\n\t\t\t\t\t\t\t// as the act of adding this code/data will change your addresses.\r\n#if NUM_ADDRESS > 0\r\nuint32 gAddress[NUM_ADDRESS] =\r\n{\r\n\t0x81701061,\r\n\t0x81700ee1,\r\n\t0x81700d61,\r\n\t0x81700be1,\r\n\t0x81700a61,\r\n\t0x817008e1,\r\n\t0x81700761,\r\n\t0x817005e1\r\n};\r\n\r\nstatic void check_address( void * p, int size )\r\n{\r\n\tfor ( int lp = 0; lp < 8; lp++ )\r\n\t{\r\n\t\tif ( gAddress[lp] == ((uint32)p) ) {\r\n\t\t\tDbg_Message( \"We found the address we're looing for: 0x%08x (%d)\\n\", (uint32)p, size );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n#else\r\n#define check_address(a,b)\r\n#endif\r\n\r\n#ifdef __PLAT_NGC__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline void* \toperator new( size_t size )\r\n{\r\n//\tDbg_SetPlacementNew( false );\r\n\tvoid * rv = Mem::Manager::sHandle().New( size, true );\r\n\tcheck_address( rv, size );\r\n\treturn rv;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline void* \toperator new[] ( size_t size )\r\n{\r\n//\tDbg_SetPlacementNew( false );\r\n\tvoid * rv = Mem::Manager::sHandle().New( size, true );\r\n\tcheck_address( rv, size );\r\n\treturn rv;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline void \toperator delete( void* pAddr )\r\n{\r\n\tMem::Manager::sHandle().Delete( pAddr );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline void \toperator delete[]( void* pAddr )\r\n{\r\n\tMem::Manager::sHandle().Delete( pAddr );\r\n}\r\n\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\r\n\r\nnamespace Spt\r\n{\r\n\r\n/******************************************************************/\r\n/* new operators - same as global + zero-ed memory                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#if (defined ( ZERO_CLASS_MEM ) && !defined ( __PLAT_WN32__ ))\r\n\r\nvoid* \tClass::operator new( size_t size )\r\n{\r\n\tvoid*\t\tp_ret = Mem::Manager::sHandle().New( size );\r\n\r\n\tif ( p_ret )\r\n\t{\r\n\t\tmemset ( p_ret, 0, size );\r\n\t}\r\n\t\r\n\tcheck_address( p_ret, size );\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid* \tClass::operator new[] ( size_t size )\r\n{\r\n\tvoid*\t\tp_ret = Mem::Manager::sHandle().New( size );\r\n\r\n\tif ( p_ret )\r\n\t{\r\n\t\tmemset ( p_ret, 0, size );\r\n\t}\r\n\r\n\t\r\n\tcheck_address( p_ret, size );\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid* \tClass::operator new( size_t size, bool assert_on_fail )\r\n{\r\n\tvoid*\t\tp_ret = Mem::Manager::sHandle().New( size, assert_on_fail );\r\n\r\n\tif ( p_ret )\r\n\t{\r\n\t\tmemset ( p_ret, 0, size );\r\n\t}\r\n\r\n\t\r\n\tcheck_address( p_ret, size );\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid* \tClass::operator new[] ( size_t size, bool assert_on_fail )\r\n{\r\n\tvoid*\tp_ret = Mem::Manager::sHandle().New( size, assert_on_fail );\r\n\r\n\tif ( p_ret )\r\n\t{\r\n\t\tmemset ( p_ret, 0, size );\r\n\t}\r\n\r\n\t\r\n\tcheck_address( p_ret, size );\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid*\tClass::operator new( size_t size, Mem::Allocator* pAlloc, bool assert_on_fail )\r\n{\r\n\tvoid*\tp_ret = Mem::Manager::sHandle().New( size, assert_on_fail, pAlloc );\r\n\r\n\tif ( p_ret )\r\n\t{\r\n\t\tmemset ( p_ret, 0, size );\r\n\t}\r\n\t\r\n\t\r\n\tcheck_address( p_ret, size );\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid*\tClass::operator new[]( size_t size, Mem::Allocator* pAlloc, bool assert_on_fail )\r\n{       \r\n\tvoid*\tp_ret = Mem::Manager::sHandle().New( size, assert_on_fail, pAlloc );\r\n\r\n\tif ( p_ret )\r\n\t{\r\n\t\tmemset ( p_ret, 0, size );\r\n\t}\r\n\r\n\tcheck_address( p_ret, size );\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid* \tClass::operator new( size_t size, void* pLocation )\r\n{\r\n\r\n\tif ( pLocation )\r\n\t{\r\n\t\tmemset ( pLocation, 0, size );\r\n\t}\r\n\r\n\r\n\treturn pLocation;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid* \tClass::operator new[]( size_t size, void* pLocation )\r\n{\r\n\r\n\tif ( pLocation )\r\n\t{\r\n\t\tmemset ( pLocation, 0, size );\r\n\t}\r\n\r\n\t\r\n\treturn pLocation;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#endif\r\n} // namespace Spt\r\n\r\n"
  },
  {
    "path": "Code/Core/Support/class.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSupport (SPT)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t06/10/99\tmjb\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/support/class.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tBase class from which  classes are derived if they want\t**\r\n**                  their memory zeroed\twhen instantiated (via new)        \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_SUPPORT_CLASS_H\r\n#define __CORE_SUPPORT_CLASS_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define ZERO_CLASS_MEM\tTRUE\r\n \r\nnamespace Mem\r\n{\r\n\tclass Allocator;\r\n}\r\n\r\nnamespace Spt\r\n{\r\n\r\nclass Class\r\n{\r\n\tpublic:\r\n\t\r\n\t#if (defined ( ZERO_CLASS_MEM ) && !defined ( __PLAT_WN32__ ))\r\n\t\tvoid*\t\t\toperator new( size_t size );\r\n\t\tvoid*\t\t\toperator new[] ( size_t size );\r\n\t\tvoid*\t\t\toperator new( size_t size, bool assert_on_fail );\r\n\t\tvoid*\t\t\toperator new[] ( size_t size, bool assert_on_fail );\r\n\t\tvoid*\t\t\toperator new( size_t size, Mem::Allocator* pAlloc, bool assert_on_fail = true );\r\n\t\tvoid*\t\t\toperator new[]( size_t size, Mem::Allocator* pAlloc, bool assert_on_fail = true );\r\n\t\tvoid*\t\t\toperator new( size_t size, void* pLocation );\r\n\t\tvoid*\t\t\toperator new[]( size_t size, void* pLocation );\r\n\t\r\n\t#endif // ZERO_CLASS_MEM\r\n};\r\n\r\n} // namespace Spt\r\n\r\n#endif // __CORE_SUPPORT_CLASS_H\r\n\r\n"
  },
  {
    "path": "Code/Core/Support/support.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSupport (SPT)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t06/10/99\tmjb\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/support/support.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\ttemplate class for tracking class hierarchy\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_SUPPORT_SUPPORT_H\r\n#define __CORE_SUPPORT_SUPPORT_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n#ifdef __PLAT_XBOX__\r\n#include <typeinfo.h>\r\n#else\r\n#include <typeinfo>\r\n#endif\r\n#include <core/support/class.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#define class _c : public Spt::Class\t\t\t\t\tclass _c : public Spt::Class\r\n//#define class _c : public _b\t\t\t\tclass _c : public _b\r\n\r\n#define nTemplateBaseClass(_t,_c)\t\t\t\t\\\r\n\ttemplate< class _t >\t\t\t\t\t\t\\\r\n\tclass _c : public Spt::Class\t\t\t\t\t\t\t\t\\\r\n\r\n#define nTemplateBaseClass2(_t1,_t2,_c)\t\t\t\\\r\n\ttemplate< class _t1, class _t2 >\t\t\t\\\r\n\tclass _c : public Spt::Class\t\t\t\t\t\t\t\t\\\r\n\r\n#define nTemplateBaseClass3(_t1,_t2,_t3,_c)\t\t\\\r\n\ttemplate< class _t1, class _t2, class _t3 >\t\\\r\n\tclass _c : public Spt::Class\t\t\t\t\t\t\t\t\\\r\n\r\n#define nTemplateSubClass(_t,_c,_b)\t\t\t\t\\\r\n\ttemplate< class _t >\t\t\t\t\t\t\\\r\n\tclass _c : public _b\t\t\t\t\t\t\t\\\r\n\r\n#define nTemplateSubClass2(_t1,_t2,_c,_b)\t\t\\\r\n\ttemplate< class _t1, class _t2 >\t\t\t\\\r\n\tclass _c : public _b\t\t\t\t\t\t\t\\\r\n\r\n#define nTemplateSubClass3(_t1,_t2,_t3,_c,_b)\t\\\r\n\ttemplate< class _t1, class _t2, class _t3 >\t\\\r\n\tclass _c : public _b\t\t\t\t\t\t\t\\\r\n\r\n\r\n#define Dbg_TemplateBaseClass(_t1,_c)\r\n#define Dbg_TemplateSubClass(_t1,_c,_b)\t\r\n\r\n#define Dbg_TemplateBaseClass(_t1,_c)\r\n#define Dbg_TemplateSubClass(_t1,_c,_b)\t\r\n\r\n#define Dbg_TemplateBaseClass2(_t1,_t2,_c)\r\n#define Dbg_TemplateSubClass2(_t1,_t2,_c,_b)\t\r\n\r\n\r\n#endif // __CORE_SUPPORT_SUPPORT_H\r\n"
  },
  {
    "path": "Code/Core/Task/Hook.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTask (TSK_)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/task/hook.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__CORE_TASK_HOOK_H\r\n#define\t__CORE_TASK_HOOK_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Tsk\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/***********************************************************************\r\n *\r\n * Class:\t\t\tBaseHook\r\n *\r\n * Description:\t\tabstract base class for code hook \r\n *\t\t\t\t\tdefines minimal interface\r\n *\r\n ***********************************************************************/\r\n\r\nclass  BaseHook  : public Spt::Class\t\t\t\t\t\r\n{\r\n\t\r\n\r\npublic :\r\n\t\r\n\tvirtual void\tCall( void ) const = 0;\r\n\r\nprotected :\r\n\r\n\t\t\t\t\tBaseHook( void ) {}\r\n\r\n};\r\n\r\n/***********************************************************************\r\n *\r\n * Class:\t\t\tHook< _T >\r\n *\r\n * Description:\t\tderived template class for hook with typed data field\r\n *\r\n ***********************************************************************/\r\n\r\nnTemplateSubClass( _T, Hook, BaseHook )\r\n{\r\n\t\r\n\r\npublic :\r\n\r\n\ttypedef void\t( Code )( const Hook< _T >& );\r\n\r\n\t\t\t\t\tHook( Code* code, _T& data );\r\n\t\r\n\tvoid\t\t\tCall( void ) const;\r\n\t_T&\t\t\t\tGetData( void ) const;\r\n\r\nprivate :\r\n\r\n\tCode* const\t\tcode;\r\n\t_T&\t\t\t\tdata;\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntemplate < class _T > inline \r\nHook< _T >::Hook( Code* _code, _T& _data )\r\n: code( _code ), data( _data )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline \r\nvoid\tHook< _T >::Call( void ) const\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertPtr( code );\r\n\tcode( *this );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline \r\n_T&\t\tHook< _T >::GetData( void ) const\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( &data, _T );\r\n\treturn data;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Tsk\r\n\r\n#endif\t// __CORE_TASK_HOOK_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Task/List.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTask (TSK_)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/task/list.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__CORE_TASK_LIST_H\r\n#define\t__CORE_TASK_LIST_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/list.h>\r\n#include \"core/support/lock.h\"\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Tsk\r\n{\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass BaseTask;\t\t// forward declaration\r\n\r\nclass  List : public  Spt::Access \r\n{\r\n\t\r\n\r\npublic :\r\n\t\t\t\t\t\t\tList ( void );\r\n\t\t\t\t\t\t\t~List ( void );\r\n\t\r\n\tvoid\t\t\t\t\tRemoveAllTasks ( void );\r\n\tvoid\t\t\t\t\tProcess ( bool time, uint mask );\r\n\tvoid\t\t\t\t\tDump ( void );\t   \t\r\n\tvoid\t\t\t\t\tAddTask ( BaseTask& task );\r\n\tbool\t\t\t\t\tIsEmpty ( void );\r\n\tvoid\t\t\t\t\tSignalListChange( void );\r\n\r\nprivate :\r\n\r\n\tLst::Head<BaseTask>\t\tlist;\r\n\tuint\t\t\t\t\tstamp;\r\n\tbool\t\t\t\t\tlist_changed;\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n \r\ninline bool\t\t\tList::IsEmpty ( void )\r\n{\r\n\t\r\n\r\n\treturn list.IsEmpty();\r\n}\r\n\r\n\r\n} // namespace Tsk\r\n\r\n#endif\t// __CORE_TASK_LIST_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Task/Stack.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTask (TSK_)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/task/stack.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__CORE_TASK_STACK_H\r\n#define\t__CORE_TASK_STACK_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/task/task.h>\r\n#include <core/task/list.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Tsk\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  Stack : public  Spt::Access \r\n{\r\n\t\r\n\r\npublic :\r\n\t\t\t\t\t\t\tStack ( void );\r\n\t\t\t\t\t\t\t~Stack ( void );\r\n\r\n\tvoid\t\t\t\t\tPush ( void );\r\n\tvoid\t\t\t\t\tPop ( void );\r\n\tvoid\t\t\t\t\tProcess ( bool time = false);\r\n\tvoid\t\t\t\t\tDump ( void );\r\n\tvoid\t\t\t\t\tAddTask ( BaseTask& task );\r\n\tvoid\t\t\t\t\tAddPushTask ( BaseTask& task );\r\n\tvoid\t\t\t\t\tRemoveAllPushTasks ( void );\r\n\tvoid\t\t\t\t\tRemoveAllTasks ( void );\r\n\tvoid \t\t\t\t\tSetMask(uint mask);\r\n\r\nprivate :\r\n\r\n\tuint\t\t\t\t\tm_mask_off; \t\t\t// mask to supress execution of tasks \r\n\r\n\tvoid\t\t\t\t\tremove_dead_entries( void );\r\n\r\n\tclass StackElement;\t\t\t\t\t// forward declaration\r\n\r\n\tLst::Head< StackElement >\tm_stack;\r\n\tLst::Head< StackElement >\tm_dead;\t// dead element list\r\n\tStackElement*\t\t\t\tm_run;\t// current run task list\r\n\tStackElement*\t\t\t\tm_add;\t// current add task list\r\n\r\n\t// these get reset when Process() is called\r\n\tbool\t\t\t\t\tm_pushedList;\r\n\tbool\t\t\t\t\tm_poppedList;\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline void Stack::SetMask(uint mask)\r\n{\r\n\tm_mask_off = mask;\r\n}\r\n\r\n} // namespace Tsk\r\n\r\n#endif\t// __CORE_TASK_STACK_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Task/Task.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTask Manager (TSK)\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\ttask.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tTask Support\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/task.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Tsk\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Externals\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nBaseTask::BaseTask( Node::Priority priority )\r\n: tlist(NULL), stamp(0)\r\n{\r\n\t\r\n\r\n\tm_mask = 0;\t\t\t\t\t\t\t// default to \"No type of thing\", so it will always run\r\n\tnode = new Node( this, priority );\r\n\tDbg_AssertType( node, Node );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nBaseTask::~BaseTask ()\r\n{\r\n\t\r\n\t\r\n\tif ( tlist )\r\n\t{   \r\n\t\tRemove();\r\n\t}\r\n\r\n\tDbg_AssertType( node, Node );\r\n\tdelete node;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBaseTask::Remove( void )\r\n{\r\n\t\r\n\t\r\n\tif ( tlist )\r\n\t{\r\n\t\ttlist->Forbid();\r\n\r\n\t\ttlist->SignalListChange();\r\n\t\tnode->Remove();\r\n\r\n\t\ttlist->Permit();\r\n\t\ttlist = NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Warning( \"Task is not in a List\" );\r\n\t}\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n \r\nbool\t\tBaseTask::InList( void ) const\r\n{\r\n\t\r\n\r\n\treturn\tnode->InList();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tBaseTask::SetPriority( Node::Priority pri ) const\r\n{\r\n\t\r\n\r\n\tnode->SetPri( pri );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Tsk\r\n"
  },
  {
    "path": "Code/Core/Task/Task.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTask (TSK_)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/task/task.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__CORE_TASK_TASK_H\r\n#define\t__CORE_TASK_TASK_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/list.h>\r\n#include <core/task/list.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Tsk\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nclass  BaseTask : public  Spt::Access \r\n{\r\n\t\r\n\r\n\tfriend class List;\r\n\r\n\r\npublic:\r\n\r\n\ttypedef Lst::Node< BaseTask >\tNode;\r\n\t\r\n\tbool\t\t\tInList( void ) const;\r\n\tvoid\t\t\tRemove( void );\r\n\t\r\n\tvirtual\tvoid\tvCall( void ) const = 0;\r\n\tvirtual void *\tGetCode(void) const = 0;\r\n\r\n\tvoid\t\t\tSetPriority( Node::Priority pri ) const;\r\n\tvirtual\t\t\t~BaseTask( void );\r\n\tvoid\t\t\tSetMask(uint mask);\r\n\tuint\t\t\tGetMask();\r\n\r\nprotected:\r\n\t\t\t\t\tBaseTask( Node::Priority pri );\r\n\t\r\n\tNode*\t\t\tnode;\t\t\t// link node\r\n\r\nprivate:\r\n\r\n\tList*\t\t\ttlist;\t\t\t// task list to which we belong\r\n\tuint\t\t\tstamp;\t\t\t// process stamp\r\n\tuint\t\t\tm_mask;\t \t\t// mask indicating what types of thing this is\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nnTemplateSubClass( _T, Task, BaseTask )\r\n{\r\n\t\r\n\r\npublic:\r\n\r\n\ttypedef void\t(Code)( const Task< _T >& );\r\n\r\n\tTask( Code* const code, _T& data, Node::Priority pri = Lst::Node< BaseTask >::vNORMAL_PRIORITY );\r\n\t\t\r\n\tvirtual void\tvCall( void ) const;\r\n\t_T&\t\t\t\tGetData( void ) const;\r\n\tvirtual void *\tGetCode(void) const;\r\n\t\r\nprivate :\r\n\tCode* const\t\tcode;\t\t\t// tasks entry point\r\n\t_T&\t\t\t\tdata;\t\t\t// task defined data\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntemplate < class _T > inline \r\nTask< _T >::Task ( Code* const _code, _T& _data, Node::Priority pri )\r\n: BaseTask( pri ), code( _code ), data( _data )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline \r\nvoid\t\tTask< _T >::vCall( void ) const\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertPtr( code );\r\n\tcode( *this );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline \r\n_T&\t\tTask< _T >::GetData( void ) const\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( &data, _T );\r\n\treturn data;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n\r\ntemplate < class _T > inline \r\nvoid *\t\tTask< _T >::GetCode( void ) const\r\n{\r\n\t\r\n\t\r\n\treturn (void*)code;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\tBaseTask::SetMask( uint mask )\r\n{\r\n\t\r\n\tm_mask = mask;\r\n}\r\n\r\ninline uint\t\tBaseTask::GetMask( void )\r\n{\r\n\t\r\n\treturn m_mask;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Tsk\r\n\r\n#endif\t// __CORE_TASK_TASK_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Task/Tlist.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTask Manager (TSK)\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\ttlist.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tTask List Support\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/task.h>\r\n\r\n#include <sys/profiler.h>\t\t\t// Including for debugging\r\n#include <sys/timer.h>\t\t\t\t// Including for debugging\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Tsk\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Externals\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nList*\tTSK_BkGndTasks = NULL;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nList::List( void )\r\n: stamp( 0 ), list_changed( false )\r\n{\r\n\t\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nList::~List ( void )\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert( list.IsEmpty(),( \"Task List Not Empty\" ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tList::Process( bool time, uint mask )\r\n{\r\n\t\r\n\r\n\tif ( !HaveAccess ())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tstamp++;\r\n\t\r\n\tdo\r\n\t{\r\n\t\tLst::Search<BaseTask>\titerator;\r\n\t\tBaseTask*\t\t\t\tnext = iterator.FirstItem( list );\r\n\r\n\t\tlist_changed = false; \r\n\t\r\n\t\twhile ( next )\r\n\t\t{\r\n\t\t\tBaseTask*\ttask = next;\r\n\r\n\t\t\tDbg_AssertType( task, BaseTask );\r\n\t\t\tDbg_AssertPtr( task );\r\n\t\t\tDbg_AssertPtr( task->node );\r\n\t\t\tDbg_MsgAssert( task->node->InList(),( \"Task was removed from list by previous task\" ));\r\n\t\t\t\r\n\t\t\tnext = iterator.NextItem();\t\t// get next task before we execute the current \t\r\n\t\t\t\t\t\t\t\t\t\t\t// one as the task might remove itself\r\n\t\t\t\r\n\t\t\tDbg_MsgAssert(!list_changed,( \"list changed, you fucker\"));\r\n\r\n\t\t\tif ( task->HaveAccess() )\r\n\t\t\t{\r\n\t\t\t\tif ( task->stamp != stamp )\r\n\t\t\t\t{\r\n\t\t\t\t\ttask->stamp = stamp;\r\n\t\t\t\t\t\r\n#ifdef\t\t__USE_PROFILER__\t\t\t\r\n\t\t\t\t\tTmr::MicroSeconds start_time=0;\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t\t\tTmr::MicroSeconds end_time=0;\r\n#endif\r\n\t\t\t\t\tif (time)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstart_time =  Tmr::GetTimeInUSeconds();\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\t// only call the task if it is not masked off\r\n\t\t\t\t\tif (! (task->GetMask() & mask))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttask->vCall();\r\n\t\t\t\t\t}\r\n#ifdef\t\t__USE_PROFILER__\t\t\t\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t\t\tif (time)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tend_time = Tmr::GetTimeInUSeconds();\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tint length = (int)(end_time - start_time);\r\n\t\t\t\t\t\tint\tsize;\r\n\t\t\t\t\t\tprintf (\"%6d %s\\n\",length,MemView_GetFunctionName((int)task->GetCode(), &size));\r\n\t\t\t\t\t}\r\n#endif\r\n#endif\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif ( list_changed )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} while ( list_changed );\r\n\r\n}\r\n\r\n\r\n/******************************************************************/\r\n// Mick Debugging: Dump out the contents of the task list\r\n// \r\n/******************************************************************/\r\n\r\nvoid\t\tList::Dump( void )\r\n{\r\n\t\r\n\r\n\tLst::Search<BaseTask>\titerator;\r\n\tBaseTask*\t\t\t\tnext = iterator.FirstItem( list );\r\n\r\n\tlist_changed = false; \r\n\r\n\twhile ( next )\r\n\t{\r\n\t\tBaseTask*\ttask = next;\r\n\r\n\t\tDbg_AssertType( task, BaseTask );\r\n\t\tDbg_AssertPtr( task );\r\n\t\tDbg_AssertPtr( task->node );\r\n\t\t\r\n\t\tnext = iterator.NextItem();\t\t// get next task before we execute the current \t\r\n\t\t\t\t\t\t\t\t\t\t// one as the task might remove itself\r\n#ifdef __PLAT_NGPS__\r\n\t\tif ( task->HaveAccess() )\r\n\t\t{\r\n//\t\t\t\tchar *MemView_GetFunctionName(int pc, int *p_size);\t\t\t\t\r\n//\t\t\t\ttask->vCall();\r\n\t\t\t\tint size;\r\n\t\t\t\tprintf (\"Task %p %s\\n\",task->GetCode(),\r\n\t\t\t\tMemView_GetFunctionName((int)task->GetCode(), &size));\r\n\t\t}\r\n#elif defined( __PLAT_NGC__ )\r\n\t\tif ( task->HaveAccess() )\r\n\t\t{\r\n//\t\t\t\tchar *MemView_GetFunctionName(int pc, int *p_size);\t\t\t\t\r\n//\t\t\t\ttask->vCall();\r\n\t\t\t\tDbg_Printf (\"Task %p\\n\",task->GetCode() );\r\n//\t\t\t\tMemView_GetFunctionName((int)task->GetCode(), &size));\r\n\t\t}\r\n#endif\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tList::AddTask( BaseTask& task )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( &task, BaseTask );\r\n\tDbg_MsgAssert( !task.node->InList(),( \"Task is already in a list\" ));\r\n\r\n\tForbid ();\t\t\t// stop any processing while list is modified\r\n\t\r\n\tlist.AddNode( task.node );\r\n\ttask.tlist = this;\r\n\ttask.stamp = stamp - 1;\r\n\tlist_changed = true;\r\n\r\n\tPermit();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tList::RemoveAllTasks( void )\r\n{\r\n\t\r\n\r\n\tLst::Search<BaseTask>\titerator;\r\n\tBaseTask*\t\t\t\tnext;\r\n\r\n\tForbid();\r\n\t\r\n\twhile (( next = iterator.FirstItem( list ) ))\r\n\t{\r\n\t\tnext->Remove();\r\n\t\tlist_changed = true;\r\n\t}\r\n\t\t\r\n\tPermit();\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tList::SignalListChange( void )\r\n{\r\n\tlist_changed = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n} // namespace Tsk\r\n\r\n"
  },
  {
    "path": "Code/Core/Task/Tstack.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTask Manager (TSK)\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\ttstack.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tTask Stack Support\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/task.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Tsk\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  Stack::StackElement : public  List \r\n{\r\n\t\r\n\r\n\tfriend class Stack;\r\n\r\npublic :\r\n\r\n\t\t\t\t\t\t\tStackElement( void );\r\n\t\t\t\t\t\t\t~StackElement( void );\r\n\r\nprivate:\r\n\r\n\tLst::Node< StackElement >*\tm_node;\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nvoid Stack::remove_dead_entries( void )\r\n{\r\n\t\r\n\r\n\tLst::Search< StackElement >\titerator;\r\n\tStackElement*\tdead_entry;\r\n\t \r\n\tDbg_MsgAssert( HaveAccess(),( \"List currently being processed\" ));\r\n\r\n\twhile (( dead_entry = iterator.FirstItem( m_dead )))\r\n\t{\r\n\t\tdelete dead_entry;\r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nStack::StackElement::StackElement( void )\r\n{\r\n\t\r\n\r\n\tm_node = new Lst::Node< StackElement >( this );\r\n\tDbg_AssertType( m_node, Lst::Node< StackElement > );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStack::StackElement::~StackElement ( void )\r\n{\r\n\t\r\n\r\n\tDbg_AssertType( m_node, Lst::Node< StackElement > );\r\n\tdelete m_node;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStack::Stack ( void )\r\n{\r\n\t\r\n\r\n\tm_pushedList = false;\r\n\tm_poppedList = false;\r\n\r\n\tPush();\t\t\t\t\t\t\t\t// create initial list\r\n\tm_add = m_run;\t\r\n\r\n\tm_pushedList = false;\r\n\tm_poppedList = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStack::~Stack ( void )\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert( HaveAccess(),( \"List currently being processed\" ));\r\n\t\r\n\tDbg_Code\r\n\t(\r\n\t\tif ( m_stack.CountItems() != 1 )\r\n\t\t{\r\n\t\t\tDbg_Warning( \"Task Stack contains %d Task Lists\", m_stack.CountItems());\r\n\t\t}\r\n\t)\r\n\r\n\twhile ( m_stack.CountItems() )\r\n\t{\r\n\t\tPop ();\r\n\t}\r\n\r\n\tremove_dead_entries();\r\n\r\n\tDbg_MsgAssert (( m_run == NULL ),( \"Task Stack not empty\" ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tStack::Push( void )\r\n{\r\n\t/*\r\n\t\tOn entry:\r\n\t\tm_add -> top list on stack (the one being processed)\r\n\t\tm_run -> probably the same\r\n\t\t\r\n\t\tOn exit:\t\t\r\n\t\tm_run -> new top list\r\n\t\tm_add -> old top list (the one being processed)\r\n\t*/\r\n\t\r\n\t\r\n\tDbg_MsgAssert(!m_pushedList,( \"push already called this frame\"));\r\n\r\n\tm_run = new StackElement;\r\n\r\n\tDbg_AssertType( m_run, StackElement );\r\n\r\n\tm_stack.AddToHead( m_run->m_node ); // deferred push\r\n\tm_pushedList = true;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tStack::Pop( void )\r\n{\r\n\t/*\r\n\t\tOn entry:\r\n\t\tm_add -> top list on stack (the one being processed)\r\n\t\tm_run -> top list on stack\r\n\t\t\r\n\t\tOn exit:\t\t\r\n\t\tm_run and m_add -> the new top list (originally second to top)\r\n\t\tm_dead -> list to be destroyed (still being processed)\r\n\t*/\r\n\r\n\t\t\r\n\tDbg_AssertType( m_run, StackElement );\r\n\t// this assert is problematic because the task system does not call Process() on the input\r\n\t// task list stacks for inactive devices, though Push() and Pop() are called\r\n\t//Dbg_MsgAssert(!m_poppedList,( \"pop already called this frame\"));\r\n\t\r\n\t// remove item\r\n\t\r\n\tLst::Search< StackElement >\titerator;\r\n\titerator.FirstItem( m_stack );\r\n\r\n\t// must use this test, m_pushedList is not reliable\r\n\tif (m_add == m_run)\r\n\t\tm_add = iterator.NextItem();\r\n\telse\r\n\t{\r\n\t\t// otherwise, current list is retained, m_add stays the same\r\n\t\tm_pushedList = false;\r\n\t}\r\n\r\n\r\n\t// m_run may have been just added this frame, but that shouldn't matter\r\n\tDbg_MsgAssert( m_run->IsEmpty(),( \"Tasks List not Empty\" )); \t\r\n\tif( HaveAccess() )\r\n\t{\r\n\t\tdelete m_run;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_run->m_node->Remove();\r\n\t\tm_dead.AddToHead( m_run->m_node ); // deferred kill\r\n\t}\r\n\r\n\tm_run = m_add;\r\n\tm_poppedList = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tStack::Process( bool time )\r\n{\r\n\t\r\n\t\r\n\tForbid();\r\n\r\n\tDbg_AssertType( m_run, StackElement );\r\n\r\n\tm_add = m_run;\t\t\t\t\t\t\t// push now in effect \r\n\tm_run->Process( time, m_mask_off );\r\n\r\n\tPermit();\r\n\t\r\n\tremove_dead_entries();\r\n\t\r\n\tm_pushedList = false;\r\n\tm_poppedList = false;\r\n}\r\n\r\nvoid\t\tStack::Dump( void )\r\n{\r\n\t\r\n\t\r\n\tForbid();\r\n\r\n\tDbg_AssertType( m_run, StackElement );\r\n\r\n\tm_add = m_run;\t\t\t\t\t\t\t// push now in effect \r\n\tm_run->Dump();\r\n\r\n\tPermit();\r\n\t\r\n\tremove_dead_entries();\r\n\t\r\n\tm_pushedList = false;\r\n\tm_poppedList = false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tStack::AddTask( BaseTask& task )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( &task, BaseTask );\r\n\tDbg_AssertType( m_add, StackElement );\r\n\r\n\tm_add->AddTask( task );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tStack::AddPushTask( BaseTask& task )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( &task, BaseTask );\r\n\tDbg_AssertType( m_run, StackElement );\r\n\r\n\tm_run->AddTask( task );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tStack::RemoveAllTasks( void )\r\n{\r\n\t\r\n\t\r\n\t// we may really be removing all tasks in list about to be pushed\r\n\tif (m_pushedList)\r\n\t{\r\n\t\tRemoveAllPushTasks();\r\n\t\tDbg_MsgAssert( m_run->IsEmpty(),( \"should now be empty\" )); \t\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tDbg_AssertType( m_add, StackElement );\r\n\r\n\tm_add->RemoveAllTasks();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tStack::RemoveAllPushTasks( void )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( m_run, StackElement );\r\n\r\n\tm_run->RemoveAllTasks();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Tsk\r\n\r\n"
  },
  {
    "path": "Code/Core/Task.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTask (TSK)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/task.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__CORE_TASK_H\r\n#define\t__CORE_TASK_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/task/task.h>\r\n#include <core/task/list.h>\r\n#include <core/task/stack.h>\r\n#include <core/task/hook.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#endif\t// __CORE_TASK_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Thread/ngc/t_thread.cpp",
    "content": "///******************************************************************\r\n//*\r\n//*    DESCRIPTION: thread/ngps/t_thread.cpp\r\n//*\r\n//*    AUTHOR:\tJAB\r\n//*\r\n//*    HISTORY:\t\r\n//*\r\n//*    DATE:9/1/2000\r\n//*\r\n//*******************************************************************/\r\n//\r\n///** include files **/\r\n//\r\n//#include <core/defines.h>\r\n//#include <core/target.h>\r\n//#include <core/task.h>\r\n////#include <eekernel.h>\r\n//\r\n//#include \"t_thread.h\"\r\n//\r\n////#ifdef __NOPT_STD_MEM__\r\n//extern \"C\" int _std_stack[1];\r\n//static int* _stack = _std_stack;\r\n////#else\r\n////extern \"C\" int _dbg_stack[1];\r\n////static int* _stack = _dbg_stack;\r\n////#endif\r\n//\r\n//extern \"C\" int _stack_size[1];\r\n//extern \"C\" int _start(void);\r\n//\r\n//Thread::PerThreadStruct _rootThreadStruct =\r\n//{\r\n//\t\"ROOT\",\r\n//\t0,\r\n//\t0,\r\n//\t_start,\t\t\t\t// m_pEntry\r\n//\t_stack,\t\t\t\t// m_pStackBase\r\n//\t(int)_stack_size,\t// m_iStackSize\r\n//\t0,\r\n//\t0\r\n//};\r\n//\r\n//int Thread::dummy = -1;\r\n//\r\n//\r\n//namespace Thread\r\n//{\r\n//\tDbg_Module\r\n//\t\r\n//// PJR - Commented out.\t\r\n////\tHTHREAD CreateThread( PerThreadStruct* pPTS )\r\n////\t{\r\n////\t\tThreadParam sParam;\r\n////\t\tsParam.entry = pPTS->m_pEntry;\r\n////\t\tsParam.stack = pPTS->m_pStackBase;\r\n////\t\tsParam.stackSize = pPTS->m_iStackSize;\r\n////\t\t//ps2memset( pPTS->m_pStackBase, 0xca, pPTS->m_iStackSize);\r\n////\t\tsParam.initPriority = pPTS->m_iInitialPriority;\r\n////\t\tsParam.gpReg = pPTS;\r\n////#ifdef __THREAD_DEBUGGING_PRINTS__\r\n////\t\tDbg_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 );\r\n////#endif\r\n////\t\tpPTS->m_osId = ::CreateThread( &sParam );\r\n////\t\treturn (HTHREAD) pPTS;\r\n////\t}\r\n//}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Thread/ngc/t_thread.h",
    "content": "/*******************************************************************\r\n*\r\n*    DESCRIPTION: thread/ngc/t_thread.h\r\n*\r\n*    AUTHOR:\tJAB\r\n*\r\n*    HISTORY:\t\r\n*\r\n*    DATE:9/1/2000\r\n*\r\n*******************************************************************/\r\n\r\n/** include files **/\r\n#ifndef __CORE_THREAD_NGC_T_THREAD_H__\r\n#define __CORE_THREAD_NGC_T_THREAD_H__\r\n\r\n#include <core/support.h>\r\n//#include <eekernel.h>\r\n\r\nnamespace Thread {\r\n\ttypedef int\tTHREADID;\t\t\t// Id for use and assigned by application\r\n\ttypedef int\tOSTHREADID;\t\t\t// Id assigned by the OS.\r\n\ttypedef unsigned int HTHREAD;\t// A value that is easy to determine from the OS\r\n\t\r\n\tclass PerThreadStruct {\r\n\tpublic:\r\n\t\tchar\t\tm_cID[16];\t\t\t// a text name so its easy to \r\n\t\tTHREADID \tm_utid;\t\t\t\t// an id that the use can assign\r\n\t\tOSTHREADID\tm_osId;\t\t\t\t// an id that the OS assigns\r\n\t\tvoid*\t\tm_pEntry;\r\n\t\tvoid*\t\tm_pStackBase;\r\n\t\tint\t\t\tm_iStackSize;\r\n\t\tint\t\t\tm_iInitialPriority;\r\n\t\tvoid*\t\tm_pRpcData;\t\t\t// ptr to rpc specific data.\r\n\t};\r\n\r\n// PJR - Not sure...\r\n//\tregister PerThreadStruct*\tg_pCurrThread asm (\"gp\");\t// Gotta fucking love that, eh?\r\n\r\n//\tinline THREADID\t\t\tGetCurrentThreadId() \t{ return (g_pCurrThread) ?  g_pCurrThread->m_utid : 0; }\r\n//\tinline HTHREAD\t\t\tGetCurrentHandle() \t\t{ return (HTHREAD) g_pCurrThread; }\t// This is fastest, so use it if you want to get data fast;\r\n\t//inline void\t\t\t\tStartThread( HTHREAD hthr, void* arg = NULL )  { ::StartThread( ((PerThreadStruct*)hthr)->m_osId, arg ); }\r\n\t// So you must set up the stack, and the perthreadstruct.\r\n\tHTHREAD CreateThread( PerThreadStruct* pPTS );\r\n\r\n\t/*\r\n\tCommentary on data for submodules (eg m_pRpcData):\r\n\tYes there are less data dependent ways of doing this. For example,\r\n\tby having an array of pointers and the subsystem requests an index\r\n\tthat it can use. But the extra work (small tho it is) seems a bit\r\n\tpointless when the penalty for hardcoding it is having to recompile\r\n\tlots of things if it changes. Not a big deal.\r\n\t*/\r\n\textern int dummy;\r\n};\r\n\r\nstruct PTS{\r\n\tchar\t\tm_cID[16];\t\t\t// a text name so its easy to \r\n\tThread::THREADID \tm_utid;\t\t\t\t// an id that the use can assign\r\n\tThread::OSTHREADID\tm_osId;\t\t\t\t// an id that the OS assigns\r\n\tvoid*\t\tm_pEntry;\r\n\tvoid*\t\tm_pStackBase;\r\n\tint\t\t\tm_iStackSize;\r\n\tint\t\t\tm_iInitialPriority;\r\n\tvoid*\t\tm_pRpcData;\t\t\t// ptr to rpc specific data.\r\n};\r\n\r\nextern \"C\" Thread::PerThreadStruct _rootThreadStruct;\r\n\r\n#endif\t// __CORE_THREAD_NGC_T_THREAD_H__\r\n"
  },
  {
    "path": "Code/Core/Thread/ngps/t_thread.cpp",
    "content": "/*******************************************************************\r\n*\r\n*    DESCRIPTION: thread/ngps/t_thread.cpp\r\n*\r\n*    AUTHOR:\tJAB\r\n*\r\n*    HISTORY:\t\r\n*\r\n*    DATE:9/1/2000\r\n*\r\n*******************************************************************/\r\n\r\n/** include files **/\r\n\r\n#include <core/defines.h>\r\n#include <core/task.h>\r\n#include <eekernel.h>\r\n\r\n#include \"t_thread.h\"\r\n\r\nextern \"C\" int _std_stack[8];\r\nstatic int* _stack = _std_stack;\r\n\r\nextern \"C\" int _stack_size[8];\r\nextern \"C\" int _start(void);\r\n\r\nThread::PerThreadStruct _rootThreadStruct =\r\n{\r\n\t\"ROOT\",\r\n\t0,\r\n\t0,\r\n\t_start,\t\t\t\t// m_pEntry\r\n\t_stack,\t\t\t\t// m_pStackBase\r\n\t(int)_stack_size,\t// m_iStackSize\r\n\t0,\r\n\t0\r\n};\r\n\r\nint Thread::dummy = -1;\r\n\r\n\r\n\t\t\t\t\t\t\t\t   \r\ntypedef\tvoid (*VOID_CB)(void*);\t\t// pointer to function that takes a void pointer\r\n\t\t\t\t\t\t\t\t   \r\n\r\n\r\nnamespace Thread\r\n{\r\n\t\r\n\t\r\n\t\r\n\tHTHREAD CreateThread( PerThreadStruct* pPTS )\r\n\t{\r\n\t\t\r\n\t\tThreadParam sParam;\r\n\t\t/*sParam.entry = pPTS->m_pEntry;*/\r\n\t\tsParam.entry = (VOID_CB) (pPTS->m_pEntry);\r\n\t\tsParam.stack = pPTS->m_pStackBase;\r\n\t\tsParam.stackSize = pPTS->m_iStackSize;\r\n\t\t//ps2memset( pPTS->m_pStackBase, 0xca, pPTS->m_iStackSize);\r\n\t\tsParam.initPriority = pPTS->m_iInitialPriority;\r\n\t\tsParam.gpReg = &_gp;\r\n#ifdef __THREAD_DEBUGGING_PRINTS__\r\n\t\tDbg_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 );\r\n#endif\r\n\t\tpPTS->m_osId = ::CreateThread( &sParam );\r\n\t\treturn (HTHREAD) pPTS;\r\n\t}\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/Thread/ngps/t_thread.h",
    "content": "/*******************************************************************\r\n*\r\n*    DESCRIPTION: thread/ngps/t_thread.h\r\n*\r\n*    AUTHOR:\tJAB\r\n*\r\n*    HISTORY:\t\r\n*\r\n*    DATE:9/1/2000\r\n*\r\n*******************************************************************/\r\n\r\n/** include files **/\r\n#ifndef __CORE_THREAD_NGPS_T_THREAD_H__\r\n#define __CORE_THREAD_NGPS_T_THREAD_H__\r\n\r\n#include <core/support.h>\r\n#include <eekernel.h>\r\n\r\nnamespace Thread {\r\n\t\r\n\r\n\ttypedef int\tTHREADID;\t\t\t// Id for use and assigned by application\r\n\ttypedef int\tOSTHREADID;\t\t\t// Id assigned by the OS.\r\n\ttypedef unsigned int HTHREAD;\t// A value that is easy to determine from the OS\r\n\t\r\n\tclass PerThreadStruct {\r\n\tpublic:\r\n\t\tchar\t\tm_cID[16];\t\t\t// a text name so its easy to \r\n\t\tTHREADID \tm_utid;\t\t\t\t// an id that the use can assign\r\n\t\tOSTHREADID\tm_osId;\t\t\t\t// an id that the OS assigns\r\n\t\tvoid*\t\tm_pEntry;\r\n\t\tvoid*\t\tm_pStackBase;\r\n\t\tint\t\t\tm_iStackSize;\r\n\t\tint\t\t\tm_iInitialPriority;\r\n\t\tvoid*\t\tm_pRpcData;\t\t\t// ptr to rpc specific data.\r\n\t};\r\n\r\n\t//inline void\t\t\t\tStartThread( HTHREAD hthr, void* arg = NULL )  { ::StartThread( ((PerThreadStruct*)hthr)->m_osId, arg ); }\r\n\t// So you must set up the stack, and the perthreadstruct.\r\n\tHTHREAD CreateThread( PerThreadStruct* pPTS );\r\n\r\n\t/*\r\n\tCommentary on data for submodules (eg m_pRpcData):\r\n\tYes there are less data dependent ways of doing this. For example,\r\n\tby having an array of pointers and the subsystem requests an index\r\n\tthat it can use. But the extra work (small tho it is) seems a bit\r\n\tpointless when the penalty for hardcoding it is having to recompile\r\n\tlots of things if it changes. Not a big deal.\r\n\t*/\r\n\textern int dummy;\r\n};\r\n\r\nstruct PTS{\r\n\tchar\t\tm_cID[16];\t\t\t// a text name so its easy to \r\n\tThread::THREADID \tm_utid;\t\t\t\t// an id that the use can assign\r\n\tThread::OSTHREADID\tm_osId;\t\t\t\t// an id that the OS assigns\r\n\tvoid*\t\tm_pEntry;\r\n\tvoid*\t\tm_pStackBase;\r\n\tint\t\t\tm_iStackSize;\r\n\tint\t\t\tm_iInitialPriority;\r\n\tvoid*\t\tm_pRpcData;\t\t\t// ptr to rpc specific data.\r\n};\r\n\r\nextern \"C\" Thread::PerThreadStruct _rootThreadStruct;\r\n\r\n#endif\t// __CORE_THREAD_NGPS_T_THREAD_H__\r\n"
  },
  {
    "path": "Code/Core/Thread/wn32/t_thread.cpp",
    "content": "/*******************************************************************\r\n*\r\n*    DESCRIPTION: t_target.h\r\n*\r\n*    AUTHOR:\tJAB\r\n*\r\n*    HISTORY:\r\n*\r\n*    DATE:9/5/2000\r\n*\r\n\r\n\t\tThis is a dummy file, because its in the NGPS version\r\n\t\tit has to be here too.\r\n\r\n*******************************************************************/\r\n\r\n/** include files **/\r\n\r\n/** local definitions **/\r\n\r\n/* default settings */\r\n\r\n/** external functions **/\r\n\r\n/** external data **/\r\n\r\n/** internal functions **/\r\n\r\n/** public data **/\r\n\r\n/** private data **/\r\n\r\n/** public functions **/\r\n\r\n/** private functions **/\r\n\r\n"
  },
  {
    "path": "Code/Core/Thread/wn32/t_thread.h",
    "content": "/*******************************************************************\r\n*\r\n*    DESCRIPTION: t_target.h\r\n*\r\n*    AUTHOR:\tJAB\r\n*\r\n*    HISTORY:\r\n*\r\n*    DATE:9/5/2000\r\n*\r\n\r\n\t\tThis is a dummy file, because its in the NGPS version\r\n\t\tit has to be here too.\r\n\r\n*******************************************************************/\r\n\r\n/** include files **/\r\n\r\n/** local definitions **/\r\n\r\n/* default settings */\r\n\r\n/** external functions **/\r\n\r\n/** external data **/\r\n\r\n/** internal functions **/\r\n\r\n/** public data **/\r\n\r\n/** private data **/\r\n\r\n/** public functions **/\r\n\r\n/** private functions **/\r\n\r\n"
  },
  {
    "path": "Code/Core/TimestampedFlag.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tStandard Header\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/TimestampedFlag.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t3/3/3\t-\tDan\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_TIMESTAMPEDFLAG_H\r\n#define __CORE_TIMESTAMPEDFLAG_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n#include <sys/timer.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n * Class:\t\t\tTimestampedFlag\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n * Description:\t\tFlag which remembers the time of its last\t\t\t*\r\n *\t\t\t\t\tmodification \t\t\t\t\t\t \t\t\t\t*\r\n *\t\t\t\t\tExtracted from skater.h\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ***********************************************************************/\r\n\r\nclass CTimestampedFlag : public Spt::Class\r\n{\r\npublic:\r\n\tvoid\t\t\tSet ( bool state );\r\n\tvoid\t\t\tSetTrue (   );\r\n\tvoid\t\t\tSetFalse (   );\r\n\tvoid\t\t\tToggle (   );\r\n\t\r\n\tbool\t\t\tGet (   );\r\n\tTmr::Time\t\tGetTime (   );\r\n\tTmr::Time\t\tGetElapsedTime (   );\r\n\t\r\n\t\t\t\t\toperator bool (   ) { return Get(); }\r\n\t\r\nprivate:\r\n\tbool\t\t\tm_state;\t\t// flag state\r\n\tTmr::Time\t\tm_time;\t\t\t// time of last state change\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\tCTimestampedFlag::Set ( bool state )\r\n{\r\n\tif (m_state == state)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tm_state = state;\r\n\tm_time  = Tmr::GetTime();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\tCTimestampedFlag::SetTrue (   )\r\n{\r\n\tSet(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\tCTimestampedFlag::SetFalse (   )\r\n{\r\n\tSet(false);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\tCTimestampedFlag::Toggle (   )\r\n{\r\n\tSet(!m_state);\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\tCTimestampedFlag::Get (   )\r\n{\r\n\treturn m_state;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Tmr::Time\tCTimestampedFlag::GetTime (   )\r\n{\r\n\treturn m_time;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Tmr::Time\tCTimestampedFlag::GetElapsedTime (   )\r\n{\r\n\treturn Tmr::GetTime() - GetTime();\r\n\t\r\n}\r\n\r\n#endif\t//\t__CORE_TIMESTAMPEDFLAG_H\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/compress.cpp",
    "content": "#include <core/compress.h>\r\n\r\n#define N\t\t 4096\t/* size of ring buffer */\r\n#define F\t\t   18\t/* upper limit for match_length */\r\n#define THRESHOLD\t2   /* encode string into position and length\r\n\t\t\t\t\t\t   if match_length is greater than this */\r\n#define NIL\t\t\tN\t/* index for root of binary search trees */\r\n\r\nunsigned long int\r\ntextsize = 0,\t/* text size counter */\r\ncodesize = 0,\t/* code size counter */\r\nprintcount = 0;\t/* counter for reporting progress every 1K bytes */\r\n\r\n\r\n//unsigned char text_buf[N + F - 1];\t \t//ring buffer of size N, with extra F-1 bytes to facilitate string comparison \r\nint     match_position, match_length;\t// of longest match.  These are \tset by the InsertNode() procedure. \r\n//int\t\tlson[N + 1], rson[N + 257], dad[N + 1];   // left & right children & parents -- These constitute binary search trees.\r\n\r\n\r\nunsigned char *text_buf;\r\nint *lson;\r\nint *rson;\r\nint *dad;\r\n\r\n\r\n#define readc()\t\t*pIn++\r\n#define writec(x)\t*pOut++ = x\r\n\r\n\r\nvoid InitTree(void)\t /* initialize trees */\r\n{\r\n\tint  i;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap()); \r\n\ttext_buf = new unsigned char[N + F - 1];\r\n\tlson = new int[N+1];\r\n\trson = new int[N+257];\r\n\tdad  = new int[N+1];\r\n\tMem::Manager::sHandle().PopContext(); //Mem::Manager::sHandle().TopDownHeap());\t\r\n\r\n\r\n\r\n\t/* For i = 0 to N - 1, rson[i] and lson[i] will be the right and\r\n\t   left children of node i.  These nodes need not be initialized.\r\n\t   Also, dad[i] is the parent of node i.  These are initialized to\r\n\t   NIL (= N), which stands for 'not used.'\r\n\t   For i = 0 to 255, rson[N + i + 1] is the root of the tree\r\n\t   for strings that begin with character i.  These are initialized\r\n\t   to NIL.  Note there are 256 trees. */\r\n\r\n\tfor ( i = N + 1; i <= N + 256; i++ ) rson[i] = NIL;\r\n\tfor ( i = 0; i < N; i++ ) dad[i] = NIL;\r\n}\r\n\r\nvoid    DeInitTree(void)  /* free up the memory */\r\n{\r\n\tdelete [] text_buf;\r\n\tdelete [] lson;\r\n\tdelete [] rson;\r\n\tdelete [] dad;\r\n\r\n}\r\n\r\nvoid InsertNode(int r)\r\n/* Inserts string of length F, text_buf[r..r+F-1], into one of the\r\n   trees (text_buf[r]'th tree) and returns the longest-match position\r\n   and length via the global variables match_position and match_length.\r\n   If match_length = F, then removes the old node in favor of the new\r\n   one, because the old one will be deleted sooner.\r\n   Note r plays double role, as tree node and position in buffer. */\r\n{\r\n\tint  i, p, cmp;\r\n\tunsigned char  *key;\r\n\r\n\tcmp = 1;  key = &text_buf[r];  p = N + 1 + key[0];\r\n\trson[r] = lson[r] = NIL;  match_length = 0;\r\n\tfor ( ; ; )\r\n\t{\r\n\t\tif ( cmp >= 0 )\r\n\t\t{\r\n\t\t\tif ( rson[p] != NIL )\r\n\t\t\t{\r\n\t\t\t\tp = rson[p];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\trson[p] = r;  dad[r] = p;  return;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( lson[p] != NIL )\r\n\t\t\t{\r\n\t\t\t\tp = lson[p];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tlson[p] = r;  dad[r] = p;  return;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tfor ( i = 1; i < F; i++ )\r\n\t\t{\r\n\t\t\tif ( (cmp = key[i] - text_buf[p + i]) != 0 )  break;\r\n\t\t}\r\n\t\t\r\n\t\tif ( i > match_length )\r\n\t\t{\r\n\t\t\tmatch_position = p;\r\n\t\t\tif ( (match_length = i) >= F )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tdad[r] = dad[p];  lson[r] = lson[p];  rson[r] = rson[p];\r\n\tdad[lson[p]] = r;  dad[rson[p]] = r;\r\n\tif ( rson[dad[p]] == p )\r\n\t{\r\n\t\trson[dad[p]] = r;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tlson[dad[p]]\t= r;\r\n\t}\r\n\tdad[p] = NIL;  /* remove p */\r\n}\r\n\r\nvoid DeleteNode(int p)\t/* deletes node p from tree */\r\n{\r\n\tint  q;\r\n\r\n\tif ( dad[p] == NIL ) return;  /* not in tree */\r\n\tif ( rson[p] == NIL ) q = lson[p];\r\n\telse if ( lson[p] == NIL ) q = rson[p];\r\n\telse\r\n\t{\r\n\t\tq = lson[p];\r\n\t\tif ( rson[q] != NIL )\r\n\t\t{\r\n\t\t\tdo\r\n\t\t\t{\r\n\t\t\t\tq = rson[q];\r\n\t\t\t} while ( rson[q] != NIL );\r\n\t\t\trson[dad[q]] = lson[q];  dad[lson[q]] = dad[q];\r\n\t\t\tlson[q] = lson[p];  dad[lson[p]] = q;\r\n\t\t}\r\n\t\trson[q] = rson[p];  dad[rson[p]] = q;\r\n\t}\r\n\tdad[q] = dad[p];\r\n\tif ( rson[dad[p]] == p ) rson[dad[p]] = q;\r\n\telse lson[dad[p]] = q;\r\n\tdad[p] = NIL;\r\n}\r\n\r\nint Encode(char *pIn, char *pOut, int bytes_to_read, bool print_progress)\r\n{\r\n\tint  i, c, len, r, s, last_match_length, code_buf_ptr;\r\n\tunsigned char  code_buf[17], mask;\r\n\r\n\ttextsize = 0;\t/* text size counter */\r\n\tcodesize = 0;\t/* code size counter */\r\n\tprintcount = 0;\t/* counter for reporting progress every 1K bytes */\r\n\r\n\tInitTree();\t /* initialize trees */\r\n\tcode_buf[0] = 0;  /* code_buf[1..16] saves eight units of code, and\r\n\t\tcode_buf[0] works as eight flags, \"1\" representing that the unit\r\n\t\tis an unencoded letter (1 byte), \"0\" a position-and-length pair\r\n\t\t(2 bytes).  Thus, eight units require at most 16 bytes of code. */\r\n\tcode_buf_ptr = mask = 1;\r\n\ts = 0;  r = N - F;\r\n\tfor ( i = s; i < r; i++ ) text_buf[i] = ' ';  /* Clear the buffer with\r\n\t\t  any character that will appear often. */\r\n\tfor ( len = 0; len < F && bytes_to_read; len++ )\r\n\t{\r\n\t\tc = readc();\r\n\t\tbytes_to_read--;\r\n\t\ttext_buf[r + len] = c;\t/* Read F bytes into the last F bytes of\r\n\t\t\tthe buffer */\r\n\t}\r\n\tif ( (textsize = len) == 0 )\r\n\t{\r\n\t\tDeInitTree();\r\n\t\treturn 0;  /* text of size zero */\r\n\t}\r\n\tfor ( i = 1; i <= F; i++ ) InsertNode(r - i);  /* Insert the F strings,\r\n\t\t  each of which begins with one or more 'space' characters.  Note\r\n\t\t  the order in which these strings are inserted.  This way,\r\n\t\t  degenerate trees will be less likely to occur. */\r\n\tInsertNode(r);\t/* Finally, insert the whole string just read.  The\r\n\t\tglobal variables match_length and match_position are set. */\r\n\tdo\r\n\t{\r\n\t\tif ( match_length > len ) match_length = len;  /* match_length\r\n\t\t\t  may be spuriously long near the end of text. */\r\n\t\tif ( match_length <= THRESHOLD )\r\n\t\t{\r\n\t\t\tmatch_length = 1;  /* Not long enough match.  Send one byte. */\r\n\t\t\tcode_buf[0] |= mask;  /* 'send one byte' flag */\r\n\t\t\tcode_buf[code_buf_ptr++] = text_buf[r];\t /* Send uncoded. */\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcode_buf[code_buf_ptr++] = (unsigned char) match_position;\r\n\t\t\tcode_buf[code_buf_ptr++] = (unsigned char)\r\n\t\t\t\t\t\t\t\t\t   (((match_position >> 4) & 0xf0)\r\n\t\t\t\t\t\t\t\t\t\t| (match_length - (THRESHOLD + 1)));  /* Send position and\r\n\t\t\t\t\t\t\t\t\t\t\t  length pair. Note match_length > THRESHOLD. */\r\n\t\t}\r\n\t\tif ( (mask <<= 1) == 0 )\r\n\t\t{  /* Shift mask left one bit. */\r\n\t\t\tfor ( i = 0; i < code_buf_ptr; i++ )  /* Send at most 8 units of */\r\n\t\t\t\twritec(code_buf[i]);\t /* code together */\r\n\t\t\tcodesize += code_buf_ptr;\r\n\t\t\tcode_buf[0] = 0;  code_buf_ptr = mask = 1;\r\n\t\t}\r\n\t\tlast_match_length = match_length;\r\n\t\tfor ( i = 0; i < last_match_length &&\r\n\t\t\tbytes_to_read; i++ )\r\n\t\t{\r\n\t\t\tc = readc();\r\n\t\t\tbytes_to_read--;\r\n\t\t\tDeleteNode(s);\t\t/* Delete old strings and */\r\n\t\t\ttext_buf[s] = c;\t/* read new bytes */\r\n\t\t\tif ( s < F - 1 ) text_buf[s + N] = c;  /* If the position is\r\n\t\t\t\t  near the end of buffer, extend the buffer to make\r\n\t\t\t\t  string comparison easier. */\r\n\t\t\ts = (s + 1) & (N - 1);  r = (r + 1) & (N - 1);\r\n\t\t\t/* Since this is a ring buffer, increment the position\r\n\t\t\t   modulo N. */\r\n\t\t\tInsertNode(r);\t/* Register the string in text_buf[r..r+F-1] */\r\n\t\t}\r\n\t\tif ( (textsize += i) > printcount )\r\n\t\t{\r\n//\t\t\tprintf(\"%12ld\\r\", textsize);  printcount += 1024;\r\n\t\t\t/* Reports progress each time the textsize exceeds\r\n\t\t\t   multiples of 1024. */\r\n\t\t}\r\n\t\twhile ( i++ < last_match_length )\r\n\t\t{\t/* After the end of text, */\r\n\t\t\tDeleteNode(s);\t\t\t\t\t/* no need to read, but */\r\n\t\t\ts = (s + 1) & (N - 1);  r = (r + 1) & (N - 1);\r\n\t\t\tif ( --len ) InsertNode(r);\t\t  /* buffer may not be empty. */\r\n\t\t}\r\n\t} while ( len > 0 );  /* until length of string to be processed is zero */\r\n\tif ( code_buf_ptr > 1 )\r\n\t{\t  /* Send remaining code. */\r\n\t\tfor ( i = 0; i < code_buf_ptr; i++ ) writec(code_buf[i]);\r\n\t\tcodesize += code_buf_ptr;\r\n\t}\r\n\r\n\tif ( print_progress )\r\n\t{\r\n\t\tprintf(\"     In : %ld bytes\\n\", textsize);\t/* Encoding is done. */\r\n\t\tprintf(\"     Out: %ld bytes\\n\", codesize);\r\n\t\tprintf(\"     Out/In: %.3f\\n\", (double)codesize / textsize);\r\n\t}\r\n\r\n\tDeInitTree();\r\n\treturn codesize;\r\n}\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Decompression code, cut & pasted from pre.cpp\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#define RINGBUFFERSIZE\t\t 4096\t/* N size of ring buffer */\r\n#define MATCHLIMIT\t\t   18\t/* F upper limit for match_length */\r\n#define THRESHOLD\t2   /* encode string into position and length */\r\n\r\n//#define WriteOut(x) \t{Dbg_MsgAssert(pOut<pIn,(\"Oops! Decompression overlap!\\nIncrease IN_PLACE_DECOMPRESSION_MARGIN in sys\\\\file\\\\pip.cpp\")); *pOut++ = x;}\r\n#define WriteOut(x) \t{*pOut++ = x;}\r\n\r\n#define USE_BUFFER\t1\t\t // we don't need no stinking buffer!!!!\r\n\r\n#if USE_BUFFER\r\n\t#ifdef\t__PLAT_NGPS__\r\n// ring buffer is just over 4K 4096+17),\r\n// so fits nicely in the PS2's 8K scratchpad\r\nstatic unsigned char    sTextBuf[RINGBUFFERSIZE + MATCHLIMIT - 1];\r\n// Note:  if we try to use the scratchpad, like this\r\n// then the code actually runs slower\r\n// if we want to optimize this, then it should\r\n// be hand crafted in assembly, using 128bit registers\r\n//\tconst unsigned char * sTextBuf = (unsigned char*) 0x70000000;\r\n\t#else\r\nstatic unsigned char\r\nsTextBuf[RINGBUFFERSIZE + MATCHLIMIT - 1];\t/* ring buffer of size N,\r\n\twith extra F-1 bytes to facilitate string comparison */\r\n\t#endif\r\n#endif\r\n\r\n\r\n#define\tReadInto(x)\t\tif (!Len) break; Len--; x = *pIn++\r\n#define\tReadInto2(x)\tLen--; x = *pIn++ \t  // version that knows Len is Ok\r\n\r\n\r\n// Decode an LZSS encoded stream\r\n// Runs at approx 12MB/s on PS2\t without scratchpad (which slows it down in C)\r\n// a 32x CD would run at 4.8MB/sec, although we seem to get a lot less than this\r\n// with our current file system, more like 600K per seconds.....\r\n// Need to write a fast streaming file system....\r\n\r\n// Ken: Made this return the new pOut so I can do some asserts to make sure it has\r\n// written the expected number of bytes.\r\nunsigned char *DecodeLZSS(unsigned char *pIn, unsigned char *pOut, int Len)\t/* Just the reverse of Encode(). */\r\n{\r\n\tint  i, j, k, r, c;\r\n//\tuint64\tLongWord;\r\n//\tint bytes = 0;\r\n//\tunsigned char *pScratch;\r\n\tunsigned int  flags;\r\n\r\n\r\n\r\n//\tint basetime =  (int) Tmr::ElapsedTime(0);\r\n//\tint len = Len;\r\n\r\n//\tint\tOutBytes = 4;\r\n//\tint\tOutWord = 0;\r\n\r\n#if USE_BUFFER\r\n\tfor ( i = 0; i < RINGBUFFERSIZE - MATCHLIMIT; i++ )\r\n\t\tsTextBuf[i] = ' ';\r\n\tr = RINGBUFFERSIZE - MATCHLIMIT;\r\n#else\r\n\tr = RINGBUFFERSIZE - MATCHLIMIT;\r\n#endif\r\n\tflags = 0;\r\n\tfor ( ; ; )\r\n\t{\r\n\t\tif ( ((flags >>= 1) & 256) == 0 )\r\n\t\t{\r\n\t\t\tReadInto(c);\r\n\t\t\tflags = c | 0xff00;\t\t\t/* uses higher byte cleverly */\r\n\t\t}\t\t\t\t\t\t\t\t\t\t/* to count eight */\r\n\t\tif ( flags & 1 )\r\n\t\t{\r\n\t\t\tReadInto(c);\r\n\t\t\t//\t\t\tputc(c, outfile);\r\n\t\t\tWriteOut(c);\r\n#if USE_BUFFER\r\n\t\t\tsTextBuf[r++] = c;\r\n\t\t\tr &= (RINGBUFFERSIZE - 1);\r\n#else\r\n\t\t\tr++;\r\n//\t\t\tr &= (RINGBUFFERSIZE - 1);\t  // don't need to wrap r until it is used\r\n#endif\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tReadInto(i);\r\n\t\t\tReadInto2(j);\t\t\t// note, don't need to check len on this one....\r\n\r\n\t\t\ti |= ((j & 0xf0) << 4);\t\t\t\t\t\t// i is 12 bit offset\r\n\r\n#if !USE_BUFFER\r\n\t\t\tj = (j & 0x0f) + THRESHOLD+1;\t\t\t\t// j is 4 bit length (above the threshold)\r\n\t\t\tunsigned char *pStream;\r\n\t\t\tr &= (RINGBUFFERSIZE - 1);\t\t\t\t\t// wrap r around before it is used\r\n\t\t\tpStream = pOut - r;\t\t\t\t\t\t\t// get base of block\r\n\t\t\tif ( i>=r )\t\t\t\t\t\t\t\t\t\t  // if offset > r, then\r\n\t\t\t\tpStream -= RINGBUFFERSIZE;\t\t\t\t// it's the previous block\r\n\t\t\tpStream += i;\t\t\t\t\t\t\t\t\t// add in the offset to the base\r\n\t\t\tr+=j;\t\t\t\t\t\t\t\t\t\t\t\t// add size to r\r\n\t\t\twhile ( j-- )\t\t\t\t\t\t\t\t\t  // copy j bytes\r\n\t\t\t\tWriteOut(*pStream++);\r\n#else\r\n\r\n\t\t\tj = (j & 0x0f) + THRESHOLD;\t\t\t\t// j is 4 bit length (above the threshold)\r\n\t\t\tfor ( k = 0; k <= j; k++ )\t\t\t\t\t  // just copy the bytes\r\n\t\t\t{\r\n\t\t\t\tc =  sTextBuf[(i+k) & (RINGBUFFERSIZE - 1)];\r\n\t\t\t\tWriteOut(c);\r\n\t\t\t\tsTextBuf[r++] = c;\r\n\t\t\t\tr &= (RINGBUFFERSIZE - 1);\r\n\t\t\t}\r\n#endif\r\n\t\t}\r\n\t}\r\n\r\n//\tint Time = (int) Tmr::ElapsedTime(basetime);\r\n//\tif (Time > 5)\r\n//\t{\r\n//\t\tprintf(\"decomp time is %d ms, for %d bytes,  %d bytes/second\\n\", Time,len, len * 1000 /Time );\r\n//\t}\r\n\treturn pOut;\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Core/compress.h",
    "content": "#ifndef __CORE_COMPRESS_H\r\n#define __CORE_COMPRESS_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\nint Encode(char *pIn, char *pOut, int bytes_to_read, bool print_progress);\r\nunsigned char *DecodeLZSS(unsigned char *pIn, unsigned char *pOut, int Len);\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Core/crc.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tCore                   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCore/crc.cpp           \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/05/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tCrc functionality      \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Crc\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic uint32 CRCTable[256] = // CRC polynomial 0xedb88320\r\n{\r\n      0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,\r\n      0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,\r\n      0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,\r\n      0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,\r\n      0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,\r\n      0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,\r\n      0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,\r\n      0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,\r\n      0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,\r\n      0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,\r\n      0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,\r\n      0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,\r\n      0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,\r\n      0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,\r\n      0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,\r\n      0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,\r\n      0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,\r\n      0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,\r\n      0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,\r\n      0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,\r\n      0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,\r\n      0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,\r\n      0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,\r\n      0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,\r\n      0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,\r\n      0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,\r\n      0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,\r\n      0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,\r\n      0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,\r\n      0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\r\n      0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,\r\n      0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,\r\n      0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,\r\n      0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,\r\n      0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,\r\n      0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,\r\n      0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,\r\n      0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,\r\n      0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,\r\n      0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,\r\n      0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,\r\n      0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\r\n      0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,\r\n      0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,\r\n      0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,\r\n      0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,\r\n      0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,\r\n      0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,\r\n      0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,\r\n      0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,\r\n      0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,\r\n      0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,\r\n      0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,\r\n      0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,\r\n      0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,\r\n      0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,\r\n      0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,\r\n      0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,\r\n      0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,\r\n      0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\r\n      0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,\r\n      0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,\r\n      0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,\r\n      0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n////////////////////////////////////////////////////////////////////////////////\r\n// Generates a checksum from raw data, given  pointer to that data, and the size\r\n//\r\n// input:\r\n//        const char *stream  = pointer to data\r\n//\t\t  int size            = number of bytes to CRC\r\n//\r\n// output:\r\n//\t\t returns uint32 = checksum of the data\r\n//       if NULL pointer passed in, or zero size is given, then will return 0\r\n//\r\nuint32 GenerateCRCCaseSensitive( const char *stream, int size )\r\n{\r\n    \r\n    \r\n\t// A checksum of zero is used to mean no name.\r\n    if(( !stream ) || ( size <= 0 )) \r\n\t{\r\n\t\treturn 0;\r\n\t}\t\r\n    \r\n    // Initializing the CRC to all one bits avoids failure of detection\r\n\t// should entire data stream get cyclically bit-shifted by one position.\r\n\t// The calculation of the probability of this happening is left as\r\n\t// an exercise for the reader.\r\n\tuint32 rc = 0xffffffff;\r\n    for (int i=0; i<size; i++)\r\n    {\r\n        rc = CRCTable[(rc^stream[i]) & 0xff] ^ ((rc>>8) & 0x00ffffff);\r\n    }\r\n\r\n\treturn rc;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// For use when calculating a total checksum of a bunch of chunks of data.\r\n// Currently used when saving out the replay buffer to mem card.\r\nuint32 UpdateCRC( const char *p_stream, int size, uint32 rc )\r\n{\r\n\tDbg_MsgAssert(p_stream,(\"NULL p_stream\"));\t\r\n    \r\n    for (int i=0; i<size; i++)\r\n    {\r\n        rc = CRCTable[(rc^p_stream[i]) & 0xff] ^ ((rc>>8) & 0x00ffffff);\r\n    }\r\n\r\n\treturn rc;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Generates a checksum from a name, case insensitive.\r\nuint32 GenerateCRC( const char *stream, int size )\r\n{\r\n    \r\n    \r\n\t// A checksum of zero is used to mean no name.\r\n    if(( !stream ) || ( size <= 0 )) \r\n\t{\r\n\t\treturn 0;\r\n\t}\t\r\n    \r\n    // Initializing the CRC to all one bits avoids failure of detection\r\n\t// should entire data stream get cyclically bit-shifted by one position.\r\n\t// The calculation of the probability of this happening is left as\r\n\t// an exercise for the reader.\r\n\tuint32 rc = 0xffffffff;\r\n    for (int i=0; i<size; i++)\r\n    {\r\n        char ch=stream[i];\r\n        // Convert to lower case.\r\n        if (ch>='A' && ch<='Z') \r\n\t\t{\r\n\t\t\tch='a'+ch-'A';\r\n\t\t}\t\r\n\t\t// Convert forward slashes to backslashes, otherwise two filenames which are\r\n\t\t// effectively the same but with different slashes will give different checksums.\r\n\t\tif (ch=='/')\r\n\t\t{\r\n\t\t\tch='\\\\';\r\n\t\t}\t\r\n\t\t\r\n        rc = CRCTable[(rc^ch) & 0xff] ^ ((rc>>8) & 0x00ffffff);\r\n    }\r\n\r\n\treturn rc;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 GenerateCRCFromString( const char *pName )\r\n{\r\n\t\r\n    // A checksum of zero is used to mean no name.\r\n    if (!pName) \r\n\t{\r\n\t\treturn 0;\r\n\t}\t\r\n\r\n    // Initializing the CRC to all one bits avoids failure of detection\r\n\t// should entire data stream get cyclically bit-shifted by one position.\r\n\t// The calculation of the probability of this happening is left as\r\n\t// an exercise for the reader.\r\n\tuint32 rc = 0xffffffff;\r\n\tconst char *pCh=pName;\r\n    while (true)\r\n    {\r\n        char ch=*pCh++;\r\n\t\tif (!ch)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        // Convert to lower case.\r\n        if (ch>='A' && ch<='Z') \r\n\t\t{\r\n\t\t\tch='a'+ch-'A';\r\n\t\t}\t\r\n\t\t// Convert forward slashes to backslashes, otherwise two filenames which are\r\n\t\t// effectively the same but with different slashes will give different checksums.\r\n\t\tif (ch=='/')\r\n\t\t{\r\n\t\t\tch='\\\\';\r\n\t\t}\t\r\n\t\t\r\n        rc = CRCTable[(rc^ch) & 0xff] ^ ((rc>>8) & 0x00ffffff);\r\n    }\r\n\r\n\treturn rc;\r\n}\r\n\r\n\r\n// Same as above, but it's calculating the CRC of two strings added together\r\n// but the first string is already CRCed\r\n// essentially it's like jumping into GenerateGRCFromString halfway through\r\nuint32 ExtendCRCWithString( uint32 rc, const char *pName )\r\n{\r\n\t\r\n    if (!pName) \r\n\t{\r\n\t\treturn rc;\r\n\t}\t\r\n\r\n\tconst char *pCh=pName;\r\n    while (true)\r\n    {\r\n        char ch=*pCh++;\r\n\t\tif (!ch)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        // Convert to lower case.\r\n        if (ch>='A' && ch<='Z') \r\n\t\t{\r\n\t\t\tch='a'+ch-'A';\r\n\t\t}\t\r\n\t\t// Convert forward slashes to backslashes, otherwise two filenames which are\r\n\t\t// effectively the same but with different slashes will give different checksums.\r\n\t\tif (ch=='/')\r\n\t\t{\r\n\t\t\tch='\\\\';\r\n\t\t}\t\r\n\t\t\r\n        rc = CRCTable[(rc^ch) & 0xff] ^ ((rc>>8) & 0x00ffffff);\r\n    }\r\n\r\n\treturn rc;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 GetCRCTableEntry( int entry )\r\n{\r\n\t\r\n\r\n\tDbg_Assert(( entry < 256 ) && ( entry >= 0 ));\r\n\r\n\treturn CRCTable[entry];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Crc\r\n\r\n"
  },
  {
    "path": "Code/Core/crc.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tCrc (CRC)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/05/01\tspg\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/crc.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tCrc Functionality\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_CRC_H\r\n#define __CORE_CRC_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Crc\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nuint32 GenerateCRC( const char *stream, int size );\r\nuint32 GenerateCRCCaseSensitive( const char *stream, int size );\r\nuint32 UpdateCRC( const char *p_stream, int size, uint32 rc=0xffffffff );\r\nuint32 GenerateCRCFromString( const char *pName );\r\nuint32 ExtendCRCWithString( uint32 rc, const char *pName );\r\nuint32 GetCRCTableEntry( int entry );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Crc\r\n\r\n#endif // __CORE_CRC_H\r\n\r\n"
  },
  {
    "path": "Code/Core/flags.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tStandard Header\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/flags.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t10/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_FLAGS_H\r\n#define __CORE_FLAGS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n * Class:\t\t\tflags\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n * Description:\t\tTemplate class for flags. \t\t\t\t\t\t \t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ***********************************************************************/\r\n\r\ntemplate < class _T >\r\nclass Flags\r\n{\r\n\r\npublic:\r\n\t\t\t\t\t\r\n\t\t\t\tFlags ( void );\r\n\t\t\t\tFlags ( const uint val );\r\n\r\n\tvoid\t\tClearAll ( void );\r\n\tvoid\t\tClear ( _T flag_index );\r\n\tvoid\t\tClearMask ( const uint& f );\r\n\tvoid\t\tSet ( _T flag_index, bool on = true );\t\r\n\tvoid\t\tSetAll ( void );\r\n\tvoid\t\tSetMask ( const uint& mask );\r\n\tvoid\t\tSetVal ( const uint& f );\r\n\tbool\t\tTestAny ( void ) const;\r\n\tbool\t\tTest ( _T flag_index ) const;\r\n\tbool\t\tTestMask ( const uint& mask ) const;\r\n\tbool\t\tTestMaskAny ( const uint& mask ) const;\r\n\tbool\t\tTestMaskAll ( const uint& mask ) const;\r\n\tvoid\t\tToggle ( _T flag_index );\r\n\t\r\n\t\t\t\toperator uint (void) const;\r\n\tFlags&\t\toperator= ( const Flags& src );\r\n\tFlags&\t\toperator= ( const uint& val );\r\n\r\nprivate:\r\n\r\n\tuint\t\tflag;\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntemplate < class _T > inline\r\nFlags< _T >::Flags ( void )\r\n: flag ( 0 )\r\n{\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\ntemplate < class _T > inline\r\nFlags< _T >::Flags ( const uint val ) \r\n: flag ( val )\r\n{\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nvoid\tFlags< _T >::ClearAll ( void )\r\n{\r\n\tflag = 0;\r\n}\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nvoid\tFlags< _T >::Clear ( _T flag_index )\r\n{\r\n\tflag &= ~( 1 << static_cast< uint >( flag_index ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nvoid\tFlags< _T >::ClearMask ( const uint& f )\r\n{\r\n\tflag &= ~f;\r\n}\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nvoid\tFlags< _T >::Set ( _T flag_index, bool on )\r\n{\r\n\tif ( on )\r\n\t{\r\n\t\tflag |= ( 1 << static_cast< uint >( flag_index ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tflag &= ~( 1 << static_cast< uint >( flag_index ));\r\n\t}\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nvoid\tFlags< _T >::SetAll ( void )\r\n{\r\n\tflag = vUINT_MAX;\r\n}                   \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nvoid\tFlags< _T >::SetMask ( const uint& mask )\r\n{\r\n\tflag |= mask;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nvoid\tFlags< _T >::SetVal ( const uint& f )\r\n{\r\n\tflag = f;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nbool\tFlags< _T >::TestAny ( void ) const\r\n{\r\n\treturn ( flag != 0 );\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nbool\tFlags< _T >::Test ( _T flag_index ) const\r\n{\r\n\treturn  (( flag & ( 1 << static_cast< uint >( flag_index ))) != 0 );\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nbool\tFlags< _T >::TestMask ( const uint& mask ) const\r\n{\r\n\treturn TestMaskAny(mask);\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nbool\tFlags< _T >::TestMaskAny ( const uint& mask ) const\r\n{\r\n\treturn (( flag & mask ) != 0 );\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nbool\tFlags< _T >::TestMaskAll ( const uint& mask ) const\r\n{\r\n\treturn (( flag & mask ) == mask );\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nvoid\tFlags< _T >::Toggle ( _T flag_index )\r\n{\r\n\tflag ^= ( 1 << static_cast< uint >( flag_index ));\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nFlags< _T >::operator uint (void) const\r\n{\r\n\treturn flag;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nFlags< _T >&\tFlags< _T >::operator= ( const Flags< _T >& src )\r\n{\r\n\tflag = static_cast< uint >( src.flag );\r\n\t\r\n\treturn *this;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nFlags< _T >&\tFlags< _T >::operator= ( const uint& val )\r\n{\r\n\tflag = val;\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\ntemplate < class _T > inline\r\nostream& operator<< ( ostream& os, const Flags< _T >& src )\r\n{\r\n\treturn os << static_cast< uint >( src );\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#endif\t//\t__CORE_FLAGS_H\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/glue.h",
    "content": "#ifndef __GLUE_H__\r\n#define __GLUE_H__\r\n\r\n\r\n#endif\t\t// __GLUE_H__\r\n"
  },
  {
    "path": "Code/Core/log.h",
    "content": "#ifndef __CORE_DEBUG_LOG_H\r\n#define __CORE_DEBUG_LOG_H\r\n\r\nnamespace Log\r\n{\r\nvoid Init();\r\nvoid AddEntry(char *p_fileName, int lineNumber, char *p_functionName, char *p_message=NULL);\r\n}\r\n\r\n#endif // #ifndef __CORE_DEBUG_LOG_H\r\n\r\n"
  },
  {
    "path": "Code/Core/macros.h",
    "content": "/*\tUseful little macros...\r\n\t\r\n\tAdd any macros you want into this:\r\n*/\r\n\r\n#ifndef __USEFUL_LITTLE_MACROS_H__\r\n#define __USEFUL_LITTLE_MACROS_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/support.h>\r\n\r\n#define PERCENT_MULT\t\t\t( ( 1.0f ) / 100.0f )\r\n#define PERCENT( x, percent )\t( ( ( ( ( float )( x ) ) * ( ( float )( percent ) ) ) * PERCENT_MULT ) )\r\n\r\n#define\t\tIPU\t\t\t(1.0f)\t\t\t// Inches per unit\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n#define\t\tINCHES(x)\t\t\t\t\t\t((float)(x))\r\n#define\t\tINCHES_PER_SECOND(x)\t\t\t((float)(x))\r\n#define\t\tINCHES_PER_SECOND_SQUARED(x)\t((float)(x))\r\n\r\n#define \tFEET_TO_INCHES( x )\t\t\t\t( x * 12.0f )\r\n#define\t\tFEET(x)\t\t\t\t\t\t\t((float)(x*12.0f))\t\t\t\t\t  \r\n\r\n#define \tFEET_PER_MILE\t\t\t\t\t5280.0f\r\n#define \tMPH_TO_INCHES_PER_SECOND( x )\t( ( ( x ) * FEET_PER_MILE * 12.0f ) / ( 60.0f * 60.0f ) )\r\n#define\t\tMPH_TO_IPS( x )\t\t\t\t\tMPH_TO_INCHES_PER_SECOND( x )\r\n#define\t\tINCHES_PER_SECOND_TO_MPH( x )\t( ( x ) / 12.0f / FEET_PER_MILE * 60.0f * 60.0f )\r\n#define\t\tIPS_TO_MPH( x )\t\t\t\t\tINCHES_PER_SECOND_TO_MPH( x )\r\n\r\n#define\t\tRADIANS_PER_SECOND_TO_RPM( x )\t(9.5496f * ( x ))\r\n#define\t\tRPM_TO_RADIANS_PER_SECOND( x )\t(0.10472f * ( x ))\r\n\r\n#define\t\tDEGREES_TO_RADIANS( x ) \t\t( ( x ) * ( 2.0f * Mth::PI / 360.0f ) )\r\n#define\t\tRADIANS_TO_DEGREES( x ) \t\t( ( x ) / ( DEGREES_TO_RADIANS( 1.0f ) ) )\r\n#define\t\tTHE_NUMBER_OF_THE_BEAST\t\t\t666\r\n\r\n\r\n\r\n// Takes screen coordinates in 'default' screen space - 640x448 - and converts them based on PAL and system defines.\r\n\r\n// Convert from logical to SCREEN coordinates\r\n#ifdef __PLAT_XBOX__\r\n// Unfortunately, this has to be a platform-specific macro, since it references Xbox specific global structures to determine\r\n// the width and height of the back buffer.\r\n#include <gfx/xbox/nx/nx_init.h>\r\n#define\t\tSCREEN_CONV_X( x )\t\t\t\t((( x ) * NxXbox::EngineGlobals.screen_conv_x_multiplier ) + NxXbox::EngineGlobals.screen_conv_x_offset )\r\n#define\t\tSCREEN_CONV_Y( y )\t\t\t\t((( y ) * NxXbox::EngineGlobals.screen_conv_y_multiplier ) + NxXbox::EngineGlobals.screen_conv_y_offset )\r\n#else\r\n#define\t\tSCREEN_CONV_X( x )\t\t\t\t(Config::GetHardware()==Config::HARDWARE_XBOX ? (int)((( x ) * ( 640.0f / 704.0f )) + 32 )\t: Config::PAL() ? (( x ) * 512 ) / 640 : (x) )\r\n#define\t\tSCREEN_CONV_Y( y )\t\t\t\t(Config::GetHardware()==Config::HARDWARE_XBOX ? (( y ) + 16 )\t\t\t\t\t\t\t\t: Config::PAL() ? (( y ) * 512 ) / 448 : (y) )\r\n#endif // __PLAT_XBOX__\r\n\r\n// Convert from screen to LOGICAL coordinates\r\n#define\t\tLOGICAL_CONV_X( x )\t\t\t\t(Config::GetHardware()==Config::HARDWARE_XBOX ? (x) : Config::PAL() ? (( x ) * 640 ) / 512 : (x) )\r\n#define\t\tLOGICAL_CONV_Y( y )\t\t\t\t(Config::GetHardware()==Config::HARDWARE_XBOX ? (y) : Config::PAL() ? (( y ) * 448 ) / 512 : (y) )\r\n\r\n#endif // __USEFUL_LITTLE_MACROS_H__\r\n\r\n"
  },
  {
    "path": "Code/Core/math.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMath (MTH)\t\t\t   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/math.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t11/23/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMath Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_MATH_H\r\n#define __CORE_MATH_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <math.h>\r\n\r\n\r\n// The following overlaoded functions will make sure that if you accidently call a double version of\r\n// a trig function with a float argument, then it will simply call the float version\r\n// (double precision is very very slow on the PS2)\r\n#ifndef __PLAT_XBOX__\r\ninline  float  acos( float x ) {return acosf( x );}          \r\ninline  float  asin( float x ) {return asinf( x );}          \r\ninline  float  atan( float x ) {return atanf( x );}          \r\ninline  float  atan2( float x, float y){return  atan2f( x , y );} \r\ninline  float   cos( float x ) {return cosf( x );}           \r\ninline  float   sin( float x ) {return sinf( x );}           \r\ninline  float   tan( float x ) {return tanf( x );}           \r\ninline  float   fabs( float x ) {return fabsf( x );}           \r\n#endif // ifndef __PLAT_XBOX__\r\n\r\n\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/support.h>\r\n#include <core/math/math.h>\r\n#include <core/math/vector.h>\r\n#include <core/math/matrix.h>\r\n#include <core/math/quat.h>\t\t  \t\t// need quat.h before matrix, but after vector (for the GetScalar function)\r\n\r\n#include <core/math/vector.inl>\r\n#include <core/math/matrix.inl>\r\n#include <core/math/quat.inl>\r\n#include <core/math/rect.h>\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n#endif // __CORE_MATH_H\r\n"
  },
  {
    "path": "Code/Core/singleton.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTemplate Singleton class\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/singleton.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t10/17/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_SINGLETON_H\r\n#define __CORE_SINGLETON_H\r\n\r\n/*\r\n\r\nSingletons\r\n(Documentation by Mick)\r\n\r\nA singleton is a single instance of a class which is dynamically\r\nallocated just once.\r\n\r\nTo make a class such as CStats a singleton class, you do this:\r\n\t\r\n\t\r\n\tclass CStats\r\n\t{\r\n\t\t// Normal Class definition goes here...\r\n\t\t...\r\n\t\t\r\n\t\t// Constructor and destructor MUST BE PRIVATE, for it to be a singleton\r\n\t\tprivate:\r\n\t\t\t CStats( void ); \t\t\r\n\t\t\t~CStats( void );\r\n\t\t\r\n\t\t// Macro to include the singleton code \t\t\r\n\t\tDeclareSingletonClass( CStats );\t\r\n\t}\r\n\r\nThis macro just places some static functions in the class, and a static pointer to \r\nthe single instance of class itself (initially NULL)\r\n\r\nYou can then initialize the singleton by the line\r\n\r\n\tSpt::SingletonPtr< CStats >\tp_stats( true );\r\n\r\nThis is somewhere at a high level in the code (currently they are all in main())\r\n\r\nThe original design of our singletons had in mind that there would be reference counting\r\nof the references tot he singleton, and when it was no longer referenced, it would\r\ndelete itself.  So, in many places in the code, the singletons are reference by creating a\r\n\"Spt::SingletonPtr\", which is a smart pointer to the instance of the singleton.  \r\n\r\nFor example:\r\n\r\n\tSpt::SingletonPtr< CStats > p_stats;\r\n\tp_stats->Update();\t\t\t\t \r\n\r\nIn the ultimate version of this idea, the game would be comprised of many modules,\r\nsystems and subsystems.  Each would be a singleton.  Each could be dependent on\r\nother singletons, but more that one module could depend on a particular singleton,\r\nso you coudl not rely on a module to de-initialize the singletons it needed\r\nas they might be needed elsewhere.\r\n\r\nSo, each module would include a Spt::SingletonPtr for each of the modules that it\r\nneeded, so when a module was created it would increase the reference on the singletons\r\nand create any that did not exists.  Then when it shut down, the pointers would automatically\r\ngo out of scope, and any singleton that was not referenced would automatically be deleted,\r\nso there would never be more systems active than there needed to be.\r\n\t\t\t\t \r\nHowever, it turned out that this was generally overkill.  Most systems were initialized at the start,\r\nand those that were not, we wanted to have control over the initialization of them.\r\nThe use of smart pointers here also obfuscated the code, and introduced a significant\r\nexecution overhead that was totally unnecessary.\r\n\r\nSo, the prefered method to access a singleton now is:\r\n\r\n\tCStats::Instance()->Update();\r\n\r\nThis simply references the instance directly (as it's inline), and so\r\ndoes no addition processing.  It's easier to type as well.\r\n\r\n\r\n*/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/support.h>\r\n\r\n#ifndef\t__SYS_MEM_MEMPTR_H\r\n#include <sys/mem/memptr.h>\r\n#endif\r\n\t\t  \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Spt\r\n{\r\n\t\t  \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\t\t\t  \r\ntemplate< class _T >\r\nclass SingletonPtr : public Spt::Class\t\t\t\t\t\t\t\r\n{\r\n\r\npublic:\r\n\r\n\t\t\t\t\t\t\tSingletonPtr( bool create = false );\r\n\tvirtual\t\t\t\t\t~SingletonPtr( void );\r\n\r\n\r\n#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))\r\n\t\t\t\t\t\t\tSingletonPtr( const SingletonPtr< _T > & rhs );\r\n\tSingletonPtr< _T >&\t\toperator= ( const SingletonPtr< _T >& rhs );\r\n\r\n#else\r\n\r\ntemplate < class _NewT >\t\t\t\t\t\t                    \t\t\t// template copy contructor\r\n\t\t\t\t\t\t\tSingletonPtr( const SingletonPtr< _NewT >& rhs ); \t// needed to support inheritance correctly\r\n\r\ntemplate < class _NewT > \t\r\n\tSingletonPtr< _T >&\t\toperator= ( const SingletonPtr< _NewT >& rhs );\t\t// template assignment operator\r\n\r\n#endif\r\n\r\n\t_T*\t\t\t\t\t\toperator-> () const;\r\n\t_T&\t\t\t\t\t\toperator* () const;\r\n\r\nprivate:\r\n\t\r\n\tMem::Ptr< _T >\t\t\tmp_instance;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ntemplate < class _T > inline\r\nSingletonPtr< _T >::SingletonPtr( bool create )\r\n: mp_instance ( _T::sSgltnInstance( create ) )\r\n{\r\n\t\r\n#ifdef __NOPT_FULL_DEBUG__\r\n\tSetName( const_cast< char* >( sClassNode()->GetName() ));\r\n#endif\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ntemplate < class _T > inline\r\nSingletonPtr< _T >::~SingletonPtr()\r\n{\r\n\t\r\n\t\r\n\tmp_instance->sSgltnDelete();\r\n}\r\n\r\n#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))\r\n   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ntemplate < class _T > inline\r\nSingletonPtr< _T >::SingletonPtr ( const SingletonPtr< _T >& rhs )\r\n: mp_instance ( _T::sSgltnInstance() )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ntemplate < class _T > inline\r\nSingletonPtr< _T >& SingletonPtr< _T >::operator= ( const SingletonPtr< _T >& rhs )\r\n{\r\n\t\r\n\t\r\n\treturn\t*this;\r\n}\r\n\r\n#else\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ntemplate < class _T > template < class _NewT > inline\r\nSingletonPtr< _T >::SingletonPtr< _T >( const SingletonPtr< _NewT >& rhs )\r\n: mp_instance ( _NewT::sSgltnInstance() )\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert( false,( \"Microsoft VC++ sucks - don't do this (yet)\" ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > template < class _NewT > inline\r\nSingletonPtr< _T >&\tSingletonPtr< _T >::operator= ( const SingletonPtr< _NewT >& rhs ) \r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert( false,( \"Microsoft VC++ sucks - don't do this (yet)\" ));\r\n\r\n\treturn *this;\t\r\n}\r\n\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ntemplate < class _T > inline\r\n_T*\tSingletonPtr< _T >::operator-> () const\r\n{\r\n\t\r\n\r\n\treturn\tmp_instance.Addr();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ntemplate < class _T > inline\r\n_T& SingletonPtr< _T >::operator* () const\r\n{\r\n\t\r\n\r\n\treturn\t*mp_instance;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n#define\tDeclareSingletonClass(_T)\t\t\t\t\t\t\t\t\t\t\t\\\r\nprivate:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tstatic _T*\tsSgltnInstance( bool create = false );\t\t\t\t\t\t\\\r\n\tstatic void sSgltnDelete( void );  \t\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tstatic _T* \t\tsp_sgltn_instance;\t\t\t\t\t\t\t\t\t\t\\\r\n\tstatic uint \ts_sgltn_count;\t\t\t\t\t\t\t\t\t\t\t\\\r\npublic:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tinline static void\tCreate(void) {sp_sgltn_instance = new _T;}\t\t\t\\\r\n\tinline static _T*\tInstance(void) {return sp_sgltn_instance;}\t\t\t\\\r\n\tinline bool\tInitilized(void) {return (sp_sgltn_instance!=NULL);}\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tfriend class Spt::SingletonPtr< _T >;\t\t\t\t\t\t\t\t\t\\\r\n\r\n\r\n#define DefinePlacementSingletonClass(_T, _P, _N )\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n_T*\t\t_T::sp_sgltn_instance = NULL;\t\t\t\t\t\t\t\t\t\t\\\r\nuint\t_T::s_sgltn_count = 0;\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n_T*\t_T::sSgltnInstance( bool create )\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tif ( !sp_sgltn_instance && create ) \t\t\t\t\t\t\t\t\t\\\r\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\tsp_sgltn_instance = new (_P) _T;\t\t\t\t\t\t\t\t\t\\\r\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tDbg_AssertType( sp_sgltn_instance, _T );\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t++s_sgltn_count;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\treturn\tsp_sgltn_instance;\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\nvoid _T::sSgltnDelete( void )\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tDbg_MsgAssert(( s_sgltn_count > 0 ),( \"Reference count imbalance\" ));\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tif ( s_sgltn_count > 1 )\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\ts_sgltn_count--;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\treturn;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tdelete sp_sgltn_instance;\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tsp_sgltn_instance = NULL;\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\ts_sgltn_count = 0;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n#define\tDefineSingletonClass(_T,_N)\t\t\\\r\n\t\tDefinePlacementSingletonClass(_T, (Mem::Allocator*)NULL, _N )\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Spt\r\n\r\n#endif\t//\t__CORE_SINGLETON_H\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/support.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tCore Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSupport (SPT)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/support.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__CORE_SUPPORT_H\r\n#define\t__CORE_SUPPORT_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/support/class.h>\r\n#include <core/support/support.h>\r\n#include \"sk/language.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// #define PAL for PAL mode build.\r\n#define PALx\r\n\r\n\r\n#endif\t// __CORE_TASK_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Core/thread.h",
    "content": "/*******************************************************************\r\n*\r\n*    DESCRIPTION: thread.h\r\n*\r\n*    AUTHOR:\tJAB\r\n*\r\n*    HISTORY:\t\r\n*\r\n*    DATE:9/1/2000\r\n*\r\n*******************************************************************/\r\n\r\n/** include files **/\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\t  \r\n#ifdef __PLAT_WN32__\r\n#else\r\n#\tifdef __PLAT_XBOX__\r\n#\telse\r\n#\t\tifdef __PLAT_NGPS__\r\n#\t\t\tinclude \"thread/ngps/t_thread.h\"\r\n#\t\telif defined( __PLAT_NGC__ )\r\n#\t\t\tinclude \"thread/ngc/t_thread.h\"\r\n#\t\telse\r\n#\t\t\terror Unsupported Platform\r\n#\t\tendif\r\n#\tendif\r\n#endif\r\n\r\n\r\n"
  },
  {
    "path": "Code/GameFlow.txt",
    "content": "Flow of control\r\n=====================================\r\n\r\n\"autolaunch level=Load_Sch game=career\"\r\n\r\nscript autolaunch\r\n\tscript request_level level=<level>\r\n\t\tScriptRequestLevel\r\n\t\t\t-set Skate::m_requested_level\r\n\tscript cleanup_before_loading_level\r\n\t\tScriptCleanup\r\n\t\t\t-skate_mod->Cleanup( )\r\n\t\t\t-skate_mod->GetGoalManager()->RemoveAllGoals()\r\n\t\t\t-particle_manager->DestroyAllSystems();\r\n\t\t\t-ParticleFX::BloodSplatDestroy();\r\n\t\t\t-SkateScript::ClearNodeNameHashTable();\r\n\t\t\t-ParticleFX::DestroyTerrainEffectProperties();\r\n\t\t\t-gfx_man->DisableFog();\r\n\t\t\t-Script::KillStoppedScripts();\r\n\t\t\t-sk3_sfx_manager->Reset( );\r\n\r\n\t\t\t-sfx_manager->CleanUp( );\r\n\r\n\t\t\t-ass_manager->UnloadAllTables( );\r\n\r\n\t\t\t-Script::CSymbolTableEntry *p_sym=Script::LookUpSymbol(\"NodeArray\");\r\n\t\t\t-if (p_sym)\r\n\t\t\t\tSkateScript::UnloadQB(p_sym->mSourceFileNameChecksum);\r\n\t\r\n\t\t\t-SkateScript::UnloadQB(s_level_specific_qb);\r\n\t\t\t-ScriptUnloadAllLevelGeometry(NULL,NULL);\r\n\r\n\t\t\t-skate_mod->UnloadSkaters();\r\n\t\t\t-Mem::Manager::sHandle().DeleteSkaterHeaps();\r\n\r\n\tscript load_requested_level level=load_sch\r\n\t\tscript LoadLevel\r\n    \t\t\tscript PreLevelLoad \r\n\t\t\t\t-does nothing\r\n    \t\t\tScriptLaunchLevel level=load_sch\r\n\t\t\t\t-Skate::OpenLevel()\r\n\t\t\t\t\t-Script::RunScript(level_script);\r\n\t\t\t\t\t\tscript Load_Sch\r\n\t\t\t\t\t\t\tscript load_level level_sch\r\n\t\t\t\t\t\t\t\t-see below....\r\n    \t\t\tPostLevelLoad\r\n\t\t\t\t-does nothing\r\n\tgameflow StandardGameFlow\r\n\t\tskate_mod->mp_gameFlow->Reset( ScriptChecksum )\r\n\t\t\t-set m_requestedScript\r\n\t\t\t\r\nLater...\r\n\r\nCGameFlow::Update()\r\n\tGameFlow_Startup\r\n\t\t-reset panel, sound stuff\r\n\t\t-maybe enter free skate in network game\r\n\t\t-choose game mode\r\n\t\t-Put skaters in world\r\n\t\t-Set screen mode\r\n\t\t-Run intro script\r\n\t-repeat:\r\n\t\tGameFlow_StartRun\r\n\t\tGameFlow_PlayRun\r\n\t\tGameFlow_WaitEnd\r\n\t\t-and other shit\r\n\r\n=====================================\r\n\r\n-----------------------\r\n\"load_level level_sch\"\r\n\r\nLevel_Sch = {\r\n    loading_screen  =   \"loadscrn_generic\"\r\n    pre             =   \"sch.pre\"\r\n    scnpre          =   \"schscn.pre\"\r\n    Level           =   \"sch\"\r\n    Sky             =   \"sf2_Sky\"\r\n    qb              =   \"levels\\sch\\sch.qb\"\r\n    colpre          =   \"schcol.pre\"\r\n    level_qb        =   \"levels\\sch\\sch_scripts.qb\"\r\n    startup_script  =   sch_Startup\r\n    default_stats   =   5\r\n}\r\n\r\nLevel_Sk4Ed = {\r\n    loading_screen  =   \"loadscrn_generic\"\r\n    pre             =   \"sk4ed.pre\"\r\n    scnpre          =   \"sk4edscn.pre\"\r\n    Level           =   \"sk4ed\"\r\n    Sky             =   \"can_Sky\"\r\n    qb              =   \"levels\\sk4ed\\sk4ed.qb\"\r\n    colpre          =   \"sk4edcol.pre\"\r\n    level_qb        =   \"levels\\sk4ed\\sk4ed_scripts.qb\"\r\n    startup_script  =   Sk4Ed_Startup\r\n    default_stats   =   8\r\n    level_number    =   LevelNum_Lon\r\n    park_editor\r\n}\r\n-----------------------\r\n\r\n\r\nscript load_level level_sch\t\r\n\tDisplayLoadingScreen <loading_screen>\r\n\t\r\n\t*** Park editor yes ***\r\n\tscript LoadLevelPreFile\t<scnpre>\r\n\t\tScriptLoadPreFile\r\n\t*** Park editor, need special flag ***\r\n\tScriptLoadScene scene=<level> (for sky, then world)\r\n\t\tNx::CTexDictManager::sLoadTextureDictionary(p_scene_name)\r\n\t\tNx::CEngine::sLoadScene(p_scene_name, p_tex_dict);\r\n\tScriptUnloadPreFile\r\n\t\r\n\t*** Park editor maybe ***\r\n\tscript LoadLevelPreFile <colpre>\r\n\tScriptLoadCollision scene=<level>\r\n\t\tp_scene->LoadCollision(p_scene_name)\r\n\tScriptUnloadPreFile\r\n\t\r\n\t*** Park editor yes ***\r\n\tscript LoadLevelPreFile <pre>\r\n\tScriptLoadQB <level_qb>\r\n\t\tSkateScript::LoadQB\r\n\t\t\tScript::LoadQB\r\n\t\t\t\t-load it into memory\r\n\t\t\t\tParseQB()\r\n\t\t\t\t-restart all scripts referring to symbols\r\n\t\t\t-do symbol table processing\r\n\t\t\t\t-do following just for NodeArray symbol\r\n\t\t\t\t- can reference nodes by name or prefix\r\n\t\t\t\tCreateNodeNameHashTab\r\n\t\t\t\tGeneratePrefixInfo();\r\n\t*** don't call ScriptParseNodeArray for park editor, I don't think ***\r\n\t*** duplicate some functionality ***\r\n\tScriptLoadNodeArray <qb>\r\n\t\tSkateScript::LoadQB (see above)\r\n\t\tScriptParseNodeArray\r\n\t\t\t-does a lot of stuff...\r\n\tLoadTerrain\r\n\t\t-doesn't seem to exist\r\n\tCC_Startup\r\n\t\t-loads some test camera stuff\r\n\trun <startup_script> (sch_startup)       \r\n\tScriptUnloadPreFile\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/AssMan/AssMan.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/AssMan\r\n//* FILENAME:       AssMan.cpp\r\n//* OWNER:          Matt Duncan\r\n//* CREATION DATE:  11/17/2000\r\n//****************************************************************************\r\n\r\n// start autoduck documentation\r\n// @DOC Assman\r\n// @module Assman | None\r\n// @subindex Scripting Database\r\n// @index script | Assman\r\n\r\n/*\r\n\r\n\tAssets are generally binary files that are processed in some way when loaded\r\n\t(although they might simply be loaded).\r\n\t\r\n\tThey are always referenced by the 32-bit checksum of the name of the file\r\n\r\n\tDesign and art guidelines already require that all filenames in the project \r\n\tare unique names.\r\n\r\n\tThe asset manager should handle generic assets...  (it shouldn't need\r\n\tto know anything about texture dictionaries or clumps or anims...)\r\n*/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gel/assman/assman.h>\r\n\r\n#include <core/singleton.h>\r\n#include <core/string/stringutils.h>\r\n\r\n#include <sys/file/AsyncFilesys.h>\r\n\r\n#include <gel/assman/assettypes.h>\r\n#include <gel/assman/animasset.h>\r\n#include <gel/assman/cutsceneasset.h>\r\n#include <gel/assman/skeletonasset.h>\r\n#include <gel/assman/skinasset.h>\r\n#include <gel/assman/refasset.h>\r\n#include <gel/assman/nodearrayasset.h>\r\n\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\t\t\t\t\t\t\t\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Ass\r\n{\r\n\r\nDefineSingletonClass( CAssMan, \"Shared Asset Manager\" );\r\n\r\nstruct SAssetLookup\r\n{\r\n   \tchar*\t\tp_extension;\r\n\tEAssetType\ttype;\r\n};\r\n\r\nstatic SAssetLookup s_asset_lookup[] = \r\n{\r\n\t{\"BIN\",\t\tASSET_BINARY},\r\n\t{\"CLD\",\t\tASSET_COLLISION},\r\n\t{\"SCN\",\t\tASSET_SCENE},\r\n\t{\"MDL\",\t\tASSET_SKIN},\r\n\t{\"SKA\",\t\tASSET_ANIM},\r\n\t{\"FAM\",\t\tASSET_ANIM}, \t// facial anims\r\n    {\"SKE\",\t\tASSET_SKELETON},\r\n\t{\"SKIN\",\tASSET_SKIN},\r\n\t{\"TEX\",\t\tASSET_TEXTURES},\r\n\t{\"CUT\",\t\tASSET_CUTSCENE},\r\n\t{\"QB\",\t\tASSET_NODEARRAY},\r\n\t\r\n// Insert new types above this line\t\r\n\t{NULL,\t\tASSET_UNKNOWN}\t\t   \t\t\t\t// terminator;\r\n};\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCAssMan::CAssMan()\r\n{\r\n\tmp_asset_table = new Lst::HashTable<Ass::CAsset>( 10 );\r\n\r\n\t// for debugging\r\n\tmp_assetlist_head = new CAsset;\r\n\tmp_assetlist_head->SetText(\"Asset List Head (Possible error here?)\");\t\r\n\t\r\n\tmp_assetlist_head->mp_next = mp_assetlist_head;\r\n\tmp_assetlist_head->mp_prev = mp_assetlist_head;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCAssMan::~CAssMan()\r\n{\t\r\n\tUnloadAllTables( true );\r\n\r\n\tdelete mp_asset_table;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nEAssetType CAssMan::FindAssetType( const char *p_assetName )\r\n{\r\n\t// given a file name, then find the type of asset that this represents\r\n\t\r\n\t// the asset type is determined by the file extension\r\n\t// so first, find the last . in the assetName\r\n\tconst char *p_ext = p_assetName + strlen(p_assetName);\r\n\twhile ( p_ext > p_assetName && *p_ext != '.' )\r\n\t{\r\n\t\tp_ext--;\r\n\t}\r\n\t\r\n\tif ( *p_ext != '.' )\r\n\t{\r\n\t\treturn ASSET_UNKNOWN;\r\n\t}\r\n\t\r\n\tp_ext++;\r\n\t// p_ext now points to the extension for the file name\r\n\r\n\tSAssetLookup *p_lookup = &s_asset_lookup[0];\r\n\twhile ( p_lookup->p_extension != NULL )\r\n\t{\r\n\t\t// note, ignoring case\r\n\t\tif ( strcmpi( p_lookup->p_extension, p_ext ) == 0 )\t\r\n\t\t{\r\n\t\t\treturn p_lookup->type;\r\n\t\t}\r\n\t\tp_lookup++;\r\n\t}\r\n\t\r\n\treturn ASSET_UNKNOWN;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid* CAssMan::LoadAssetFromStream(uint32 asset_name, uint32 asset_type, uint32* p_data, int data_size, bool permanent, uint32 group)\r\n{\r\n\t// Note:  There's no reason to support async loads when\r\n\t// loading an asset from a data stream...\r\n\r\n\t// load an asset, and return a pointer to the asset data\r\n\r\n\t// given an asset name checksum, find the type of the asset, and then load it\r\n\r\n\tDbg_MsgAssert(!AssetAllocated(asset_name),(\"Asset %08x already loaded\",asset_name));\r\n\r\n\tCAsset* p_asset = NULL;\t\r\n\t\t\r\n\t// based on the asset type, create an asset of the correct type\t\r\n\tswitch (asset_type)\r\n\t{\r\n\t\tcase ASSET_ANIM:\r\n\t\t\tp_asset = new CAnimAsset;\r\n\t\t\tbreak;\r\n\r\n\t\tcase ASSET_SKIN:\r\n\t\t\tp_asset = new CSkinAsset;\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\t// right now, the only file type that's supported\r\n\t\t\t// for data streams is the \"cutscene model\"\r\n\t\t\tDbg_MsgAssert(0,(\"Asset %08x is of unsupported type %d\",asset_name,asset_type));   \t\t\r\n\t}\r\n\r\n\tp_asset->m_permanent = permanent;\r\n\tp_asset->m_group = group;\r\n\tp_asset->m_dead = false;\t  \t\t\t// it is not dead\t\r\n\r\n\t// fake an asset name for debugging\r\n\tchar pDebugAssetString[256];\r\n\tsprintf( pDebugAssetString, \"%08x from data stream\", asset_name );\r\n\tp_asset->SetText(pDebugAssetString);\t\t\t\r\n\t\r\n\t// finally, call the asset's Load member function to load it\r\n\tint error = p_asset->Load(p_data, data_size);\t\r\n\tif ( error != 0 )\r\n\t{\r\n\t\tif ( Script::GetInteger( CRCD(0x25dc7904,\"AssertOnMissingAssets\") ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"Loading asset %08x returned error %d\",asset_name,error));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tdelete p_asset;\r\n\t\t\tp_asset = NULL;\r\n\t\t}\r\n\t\treturn NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// only add it to the table once we're sure there's no error\r\n\t\tuint32 checksum = asset_name;\r\n\t\tDbg_MsgAssert(!mp_asset_table->GetItem( checksum ),(\"Asset %08x already in table\",asset_name));\t\r\n\t\tmp_asset_table->PutItem( checksum,  p_asset);\r\n\t\tp_asset->SetID(checksum);\r\n\r\n\t\t// link in at the end, so things are added in order\r\n\t\tp_asset->mp_next = mp_assetlist_head;\r\n\t\tp_asset->mp_prev = mp_assetlist_head->mp_prev;\r\n\t\tmp_assetlist_head->mp_prev->mp_next = p_asset;\r\n\t\tmp_assetlist_head->mp_prev = p_asset;\r\n\r\n\t\tDbg_MsgAssert(mp_asset_table->GetItem( checksum ) == p_asset,(\"Asset does not match entry in table\"));\r\n\t\tDbg_Assert( p_asset );\r\n\t\treturn p_asset->GetData();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid* CAssMan::LoadAsset(const char *p_assetName, bool async_load, bool use_pip, bool permanent, uint32 group, void* pExtraData, Script::CStruct *pParams)\r\n{\r\n\t// load an asset, and return a pointer to the asset data\r\n\r\n\t// given an asset filename, find the type of the asset, and then load it\r\n\r\n\tDbg_MsgAssert(!AssetAllocated(p_assetName),(\"Asset %s already loaded\",p_assetName));\r\n\r\n\tCAsset\t* p_asset = NULL;\t\r\n\t\r\n// Find the asset type\t\r\n\tEAssetType\tasset_type = FindAssetType(p_assetName); \r\n\tDbg_MsgAssert(asset_type != ASSET_UNKNOWN,(\"Asset %s is of unknown type\",p_assetName));\r\n\t\r\n// based on that, create an asset of the correct type\t\r\n\tswitch (asset_type)\r\n\t{\r\n\t\tcase ASSET_ANIM:\r\n\t\t\tp_asset = new CAnimAsset;\r\n\t\t\tbreak;\r\n\r\n        case ASSET_SKELETON:\r\n            p_asset = new CSkeletonAsset;\r\n            break;\r\n\r\n\t\tcase ASSET_SKIN:\r\n\t\t\tp_asset = new CSkinAsset;\r\n\t\t\tbreak;\r\n\r\n\t\tcase ASSET_CUTSCENE:\r\n\t\t\tp_asset = new CCutsceneAsset;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ASSET_NODEARRAY:\r\n\t\t\tp_asset = new CNodeArrayAsset;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ASSET_SCENE:\r\n\t\tcase ASSET_TEXTURES:\r\n\t\tcase ASSET_COLLISION:\r\n\t\tcase ASSET_BINARY:\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Asset %s is of unsupported type %d\",p_assetName,asset_type));   \t\t\r\n\t}\r\n\r\n\tp_asset->m_permanent = permanent;\r\n\tp_asset->m_group = group;\r\n\tp_asset->m_dead = false;\t  \t\t\t// it is not dead\t\r\n\r\n\tp_asset->SetText(p_assetName);\t\t\t// record asset name for debugging\r\n\t\r\n\t// Garrett: Make sure that we only set async on the things that can handle them\r\n\tif (async_load)\r\n\t{\r\n\t\tDbg_MsgAssert(asset_type == ASSET_ANIM, (\"Can't load this asset type asynchronously: %d\", asset_type));\r\n\t}\r\n\r\n\t// finally, call the asset's Load member function to load it\r\n\tint\terror = p_asset->Load(p_assetName, async_load, use_pip, pExtraData, pParams);\t\r\n\tif ( error != 0 )\r\n\t{\r\n\t\tif ( Script::GetInteger( CRCD(0x25dc7904,\"AssertOnMissingAssets\") ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"Loading asset %s returned error %d\",p_assetName,error));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tdelete p_asset;\r\n\t\t\tp_asset = NULL;\r\n\t\t}\r\n\t\treturn NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// only add it to the table once we're sure there's no error\r\n\t\tuint32 checksum = Script::GenerateCRC( p_assetName );\r\n\t\tDbg_MsgAssert(!mp_asset_table->GetItem( checksum ),(\"Asset %s already in table\",p_assetName));\t\r\n\t\tmp_asset_table->PutItem( checksum,  p_asset);\r\n\t\tp_asset->SetID(checksum);\r\n\r\n\t\t// link in at the end, so things are added in order\r\n\t\tp_asset->mp_next = mp_assetlist_head;\r\n\t\tp_asset->mp_prev = mp_assetlist_head->mp_prev;\r\n\t\tmp_assetlist_head->mp_prev->mp_next = p_asset;\r\n\t\tmp_assetlist_head->mp_prev = p_asset;\r\n\r\n\t\tDbg_MsgAssert(mp_asset_table->GetItem( Script::GenerateCRC( p_assetName )) == p_asset,(\"Asset does not match entry in table\"));\r\n\t\tDbg_Assert( p_asset );\r\n\t\treturn p_asset->GetData();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid* CAssMan::GetFirstInGroup( uint32 group )\r\n{\r\n\t// return the first asset in the asset manager that is in this group\r\n\t// will return NULL if there are none of teh specified group\r\n\t\r\n\treturn GetNthInGroup(group,0);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid* CAssMan::GetNthInGroup( uint32 group, int n )\r\n{\r\n\t// return the nth asset in the asset manager that is in this group\r\n\t// will return NULL if there are none of the specified group\r\n\t\r\n\tCAsset* p_asset = mp_assetlist_head->mp_next;\r\n\twhile (p_asset != mp_assetlist_head)\r\n\t{\r\n//\t\tprintf (\"%d: Checkingfor %x, group = %x\\n\",n,group,p_asset->m_group); \r\n\t\tCAsset *p_next = p_asset->mp_next;\t\r\n\t\tif (p_asset->m_group == group)\r\n\t\t{\r\n//\t\t\tprintf (\"%d: GROUP MATCH %x, group = %x\\n\",n,group,p_asset->m_group); \r\n\t\t\tif (n==0)\r\n\t\t\t{\r\n//\t\t\t\tprintf (\"%d: COUNT MATCH %x, group = %x\\n\",n,group,p_asset->m_group); \r\n\t\t\t\treturn\tp_asset->GetData();\t\t\t\t\r\n\t\t\t}\r\n\t\t\tn--;\r\n\t\t}\t\t\t\r\n\t\tp_asset = p_next;\t\t\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CAssMan::GetGroup(uint32 checksum)\r\n{\r\n\tCAsset* p_actual = mp_asset_table->GetItem(checksum);\r\n\tDbg_MsgAssert(p_actual, (\"GetIndexInGroup with asset not found\\n\")); \r\n\treturn p_actual->GetGroup();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CAssMan::GetIndexInGroup(uint32 checksum)\r\n{\r\n\t// find this entry, and see which number it is in the group\r\n\t// i.e, returns the intex into the group\r\n\t\r\n\tCAsset* p_actual = mp_asset_table->GetItem(checksum);\r\n\tDbg_MsgAssert(p_actual, (\"GetIndexInGroup with asset not found\\n\")); \r\n\t\r\n\tint n = 0;\t\t\t\t\t\t\t\t\t\t  \t// index starts at 0\r\n\tCAsset* p_asset = mp_assetlist_head->mp_next;\r\n\twhile (p_asset != mp_assetlist_head)\r\n\t{\r\n\t\tCAsset *p_next = p_asset->mp_next;\t\r\n\t\tif (p_asset == p_actual)\r\n\t\t{\r\n\t\t\treturn n;\t\t\t\t\t\t  \t\t\t// if we've found it, then return the asset\r\n\t\t}\r\n\t\tif (p_asset->m_group == p_actual->m_group)\t \t// if in same group\r\n\t\t{\r\n\t\t\tn++;\t\t\t\t\t\t\t\t\t\t// increment index\r\n\t\t}\r\n\t\tp_asset = p_next;\t\t\r\n\t}\r\n\tDbg_MsgAssert(0, (\"ERROR IN GetIndexInGroup\\n\")); \r\n\treturn 0;\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CAssMan::CountGroup(uint32 group)\r\n{\r\n\tint n = 0;\t\t\t\t\t\t\t\t\t\t  \t// index starts at 0\r\n\tCAsset* p_asset = mp_assetlist_head->mp_next;\r\n\twhile (p_asset != mp_assetlist_head)\r\n\t{\r\n\t\tCAsset *p_next = p_asset->mp_next;\t\r\n\t\tif (p_asset->m_group == group)\t \t// if in same group\r\n\t\t{\r\n\t\t\tn++;\t\t\t\t\t\t\t\t\t\t// increment index\r\n\t\t}\r\n\t\tp_asset = p_next;\t\t\r\n\t}\r\n\treturn n;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CAssMan::CountSameGroup(uint32 checksum)\r\n{\r\n\t// a utility function to count the assets in the same group as another asset\r\n\t\r\n\treturn CountGroup(GetGroup(checksum));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t   \r\nvoid CAssMan::DestroyReferences( CAsset* pAsset )\r\n{\r\n\t// Destroys an asset's references\r\n\t\r\n\tDbg_Assert( pAsset );\r\n\t\t\r\n\twhile (pAsset->mp_ref_asset)\r\n\t{\r\n\t\t// destroying a reference is similar to an asset, except we\r\n\t\t// do not need to call unload\r\n\r\n//\t\tprintf (\"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());\r\n\t\tuint32 id = pAsset->mp_ref_asset->m_id;\r\n\t\tpAsset->mp_ref_asset->Unlink();\r\n\t\tdelete pAsset->mp_ref_asset; \r\n\t\tmp_asset_table->FlushItem(id);\t\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAssMan::UnloadAsset( CAsset* pAsset )\r\n{\r\n\t// Unload an asset and delete it\r\n\t// note the current pairing of create/load,  and unload/delete\r\n\t// in the future, we might need to seperate them out into two distinct stages \r\n\t\r\n\tDbg_Assert( pAsset );\r\n\r\n\tuint32 id = pAsset->m_id;\r\n\r\n\tDbg_MsgAssert(pAsset->LoadFinished(), (\"UnloadAsset(): Asset not finished loading\"));\r\n\r\n\tpAsset->Unlink();\r\n\tpAsset->Unload();\r\n\tdelete pAsset;\t\t\t\t\r\n\tmp_asset_table->FlushItem(id);\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAssMan::ReloadAsset( uint32 assetID, const char* pFileName, bool assertOnFail )\r\n{\r\n\tAss::CAsset* pAsset;\r\n\r\n\tpAsset = this->GetAssetNode( assetID, assertOnFail );\r\n\r\n\tif ( pAsset )\r\n\t{\r\n\t\tDbg_MsgAssert(pAsset->LoadFinished(), (\"ReloadAsset(): Asset not finished loading\"));\r\n\r\n\t\treturn pAsset->Reload( pFileName );\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCAsset*\tCAssMan::GetAssetNode( uint32 assetID, bool assertOnFail )\r\n{\r\n\tCAsset *p_asset = mp_asset_table->GetItem(assetID);\r\n\t\t\r\n\tif ( assertOnFail )\r\n\t{\r\n\t\tDbg_MsgAssert(p_asset, (\"Asset Not found <%s>\", Script::FindChecksumName(assetID)));\r\n\t\t//Dbg_MsgAssert(p_asset->LoadFinished(), (\"Asset not finished loading (%s)\", Script::FindChecksumName(assetID)));\r\n\t}\r\n\r\n\t// Don't return pointer if it isn't done loading\r\n\tif ( p_asset && !p_asset->LoadFinished() )\r\n\t{\r\n\t\t//p_asset = NULL;\r\n\r\n\t\t// Wait if not done loading\r\n\t\twhile (!p_asset->LoadFinished())\r\n\t\t{\r\n\t\t\tDbg_Message(\"Waiting for async asset load to finish...\");\r\n\t\t\tFile::CAsyncFileLoader::sWaitForIOEvent(false);\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn p_asset;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid* CAssMan::GetAsset(uint32 assetID, bool assertOnFail )\t\r\n{\r\n\t// Return a pointer to the asset data, or NULL if not found\r\n\t\r\n\tCAsset *p_asset = mp_asset_table->GetItem(assetID);\r\n\r\n\tif (p_asset /*&& p_asset->LoadFinished()*/)\r\n\t{\r\n\t\t// Wait if not done loading\r\n\t\twhile (!p_asset->LoadFinished())\r\n\t\t{\r\n\t\t\tDbg_Message(\"Waiting for async asset load to finish...\");\r\n\t\t\tFile::CAsyncFileLoader::sWaitForIOEvent(false);\r\n\t\t}\r\n\r\n\t\tvoid *p_asset_data = p_asset->GetData();\r\n\t\tDbg_MsgAssert(p_asset_data,(\"Asset has no data\"));\r\n\t\treturn\tp_asset_data;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( assertOnFail )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(p_asset, (\"Asset 0x%x Not found (%s)\",assetID,Script::FindChecksumName(assetID)));\r\n\t\t\t//Dbg_MsgAssert(p_asset->LoadFinished(), (\"Asset 0x%x not finished loading (%s)\",assetID,Script::FindChecksumName(assetID)));\r\n\t\t}\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid* CAssMan::GetAsset(const char *p_assetName, bool assertOnFail)\r\n{\r\n\t//returns a pointer to the asset data, does not load it if not found\r\n\t\r\n\tif ( assertOnFail )\r\n\t{\r\n\t\tDbg_MsgAssert(AssetAllocated(p_assetName),(\"asset %s is not loaded in GetAsset\",p_assetName));\r\n\t}\r\n\tvoid *p_asset_data = GetAsset(Script::GenerateCRC( p_assetName ), assertOnFail );\r\n\t\r\n\tif ( assertOnFail )\r\n\t{\r\n\t\tDbg_MsgAssert(p_asset_data,(\"Asset has NULL data %s\",p_assetName));\r\n\t}\r\n\treturn p_asset_data;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid* CAssMan::LoadOrGetAsset(const char *p_assetName, bool async_load, bool use_pip, bool permanent, uint32 group, void* pExtraData, Script::CStruct * pParams)\r\n{\r\n\t//returns a pointer to the asset data, and loads the asset if not found\r\n\t\r\n\tvoid *p_asset_data;\r\n\tCAsset *p_asset = mp_asset_table->GetItem(Script::GenerateCRC( p_assetName ));\r\n\tif (p_asset)\r\n\t{\r\n\t\tp_asset_data = p_asset->GetData();\r\n\t\tDbg_MsgAssert(p_asset_data,(\"Asset has NULL data %s\",p_assetName));\r\n\t\t//Dbg_MsgAssert(p_asset->LoadFinished(), (\"Asset not finished loading (%s)\", p_assetName));\r\n\r\n\t\t// Wait if not done loading\r\n\t\twhile (!p_asset->LoadFinished())\r\n\t\t{\r\n\t\t\tDbg_Message(\"Waiting for async asset load to finish...\");\r\n\t\t\tFile::CAsyncFileLoader::sWaitForIOEvent(false);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_asset_data = LoadAsset(p_assetName, async_load, use_pip, permanent, 0, pExtraData,pParams);\t\r\n\t}\r\n\t\r\n\tif ( Script::GetInteger( CRCD(0x25dc7904,\"AssertOnMissingAssets\") ) )\r\n\t{\r\n\t\t// do some extra checks here if we're asserting on missing assets\r\n\t\tDbg_MsgAssert(p_asset_data,(\"Could not load asset %s\",p_assetName));\r\n\t\tDbg_MsgAssert(AssetAllocated(p_assetName),(\"asset %s is not loaded after LoadOrGetAsset\",p_assetName));\r\n\t}\r\n\r\n\treturn p_asset_data;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAssMan::AssetAllocated(uint32 assetID)\r\n{\r\n\t//  Return true if the asset has at least started loading\r\n\t\r\n\treturn (NULL != mp_asset_table->GetItem(assetID));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAssMan::AssetAllocated(const char *p_assetName)\r\n{\r\n\t//  Return true if the asset has at least started loading\r\n\t\r\n\treturn (AssetAllocated(Script::GenerateCRC( p_assetName )));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAssMan::AssetLoaded(uint32 assetID)\r\n{\r\n\t//  Return true if the asset is done loading\r\n\tCAsset *p_asset = mp_asset_table->GetItem(assetID);\r\n\r\n\tif (p_asset && p_asset->LoadFinished())\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAssMan::AssetLoaded(const char *p_assetName)\r\n{\r\n\t//  Return true if the asset is done loading\r\n\t\r\n\treturn (AssetLoaded(Script::GenerateCRC( p_assetName )));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAssMan::AddRef(uint32 asset_id, uint32 ref_id, uint32 group)\r\n{\r\n\t// Add a reference to an asset, so we can access it via a new id\r\n\r\n\tDbg_MsgAssert(AssetAllocated(asset_id),(\"Adding ref to unloaded asset\\n\"));\r\n\tCAsset *p_asset = new CRefAsset(mp_asset_table->GetItem(asset_id));\r\n\tDbg_MsgAssert(!mp_asset_table->GetItem( ref_id ),(\"ref already in table/n\"));\t\r\n\tmp_asset_table->PutItem( ref_id,  p_asset);\r\n\tp_asset->SetID(ref_id);\r\n\tp_asset->SetGroup(group);\r\n\r\n\t// link it to the end of the list\r\n\tp_asset->mp_next = mp_assetlist_head;\r\n\tp_asset->mp_prev = mp_assetlist_head->mp_prev;\r\n\tmp_assetlist_head->mp_prev->mp_next = p_asset;\r\n\tmp_assetlist_head->mp_prev = p_asset;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAssMan::AddRef(const char *p_assetName, uint32 ref_id, uint32 group)\r\n{\r\n\tDbg_MsgAssert(!mp_asset_table->GetItem( ref_id ),(\"ref %lx already in table\\nwhen adding to %s\\n\",ref_id,p_assetName));\t\r\n\tDbg_MsgAssert(AssetAllocated(p_assetName),(\"Adding ref to unloaded asset %s\\n\",p_assetName));\r\n\tuint32\tchecksum = Script::GenerateCRC( p_assetName );\r\n\tAddRef(checksum,ref_id, group);\t\r\n}\r\n\t\t\t\t\t\t\t\t\t\t\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAssMan::UnloadAllTables( bool destroy_permanent )\r\n{\r\n//\tprintf ( \"Unloading all tables\" );\r\n\t\r\n\tCAsset* p_asset;\r\n\t \r\n\tp_asset = mp_assetlist_head->mp_next;\r\n\twhile (p_asset != mp_assetlist_head)\r\n\t{\r\n\t\tCAsset *p_next = p_asset->mp_next;\t\r\n\t\tif ( destroy_permanent || !p_asset->m_permanent )\r\n\t\t{\r\n\t\t\t// First destroy any references to this asset\r\n\t\t\tDestroyReferences( p_asset );\r\n\t\t\t\r\n\t\t\t// Need to update p_next, in case it was change by destroying above code\r\n\t\t\tp_next = p_asset->mp_next;\t\r\n\t\r\n\t\t\tUnloadAsset( p_asset );\r\n\t\t}\r\n\t\tp_asset = p_next;\t\t\r\n\t}\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAssMan::SetDefaultPermanent(bool permanent)\r\n{\r\n\t// set the default permanent state of loaded assets\r\n\t// (generally this will be false)\r\n\t\r\n\tm_default_permanent = permanent;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAssMan::GetDefaultPermanent() const\r\n{\r\n\treturn m_default_permanent;\r\n}\r\n\r\n// The following functions are kind of kludge for referencing anims\r\n// Ideally, I'd like to remove these kludges and simplify the\r\n// asset manager\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAssMan::LoadAnim(const char* pFileName, uint32 animName, uint32 referenceChecksum, bool async_load, bool use_pip)\r\n{\r\n\t// If the asset was previously loaded, then we are just creating a reference to it\r\n\t// so the m_permanent flag should be set based on m_default_permanent, and NOT INHERITED\r\n\t\t\t\r\n\tif (AssetAllocated(pFileName))\r\n\t{\r\n\t\t// if descChecksum was supplied, then adding a reference\r\n\t\tif (animName && !AssetAllocated(animName + referenceChecksum))\r\n\t\t{\r\n\t\t\t// adding a reference\r\n\t\t\tAddRef(pFileName, animName + referenceChecksum, referenceChecksum);\t \r\n\t\t\t// the m_permanent will have been inherited from the parent asset\r\n\t\t\t// Now get the reference asset, and set the permanent flag to m_defualt_permanet\r\n\t\t\tCAsset *p_asset = mp_asset_table->GetItem(animName + referenceChecksum);\r\n\t\t\tDbg_MsgAssert(p_asset,(\"(Mick) Error re-getting asset ref for %s\\n\",pFileName));\r\n\t\t\t//p_asset->SetPermanent(m_default_permanent);  // <<<< this would also set the perm flag on the parent\r\n\r\n\t\t\tp_asset->m_permanent = m_default_permanent;\t\t// just in the reference!!!\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t//Dbg_MsgAssert( 0, ( \"This file was already loaded %s\", pFileName ) );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (!LoadOrGetAsset(pFileName, async_load, use_pip, m_default_permanent, 0))\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"Failed to load anim %s\",pFileName));\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// Now add the reference to it, if one was requested\r\n\t\t// this gets combined with the \"reference checksum\"\r\n\t\tif (animName && !AssetAllocated(animName + referenceChecksum))\r\n\t\t{\r\n\t\t\tAddRef(pFileName, animName + referenceChecksum, referenceChecksum);\t \r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAssMan::SetReferenceChecksum(uint32 reference_checksum)\t   \r\n{\r\n\t// kind of a kludge for anims\r\n\r\n\tm_reference_checksum = reference_checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CAssMan::GetReferenceChecksum() const\r\n{\r\n\treturn m_reference_checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Ass\r\n\r\n#if 0\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAssMan::DumpAssets()\r\n{\r\n\tCAsset * p_asset = mp_assetlist_head->mp_next;\r\n\tint i=0;\r\n\twhile (p_asset != mp_assetlist_head)\r\n\t{\r\n\t\tCAsset *p_next = p_asset->mp_next;\t\r\n\t\tprintf (\"Asset %3d: perm=%d %s\\n\",i,p_asset->m_permanent, p_asset->GetText());\r\n\t\ti++;\r\n\t\tp_asset = p_next;\t\t\r\n\t}\t\r\n}\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/AssMan/AssMan.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/AssMan\r\n//* FILENAME:       AssMan.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  11/17/2000\r\n//****************************************************************************\r\n\r\n#ifndef __GEL_ASSMAN_H\r\n#define __GEL_ASSMAN_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <core/hashtable.h>\r\n\r\n#include <gel/assman/assettypes.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Lst\r\n{\r\n\ttemplate<class _V> class HashTable;\r\n}\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Ass\r\n{\r\n\tclass CAsset;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n   \r\nclass CAssMan : public Spt::Class \r\n{\t\r\n\tDeclareSingletonClass( CAssMan );\r\n\r\npublic:\r\n    \r\n\tCAssMan( void );\r\n    ~CAssMan( void );\r\n\r\n\t// New generic functions\r\n\tEAssetType\tFindAssetType(const char *p_assetName);\r\n\r\n\tvoid*\t\tLoadAssetFromStream(uint32 asset_name, uint32 asset_type, uint32* p_data, int data_size, bool permanent, uint32 group);\r\n\tvoid*\t\tLoadAsset(const char *p_assetName, bool async_load, bool use_pip = false, bool permanent = false, uint32 group = 0, void* pExtraData = NULL, Script::CStruct * pParams = NULL);\r\n\tbool\t\tReloadAsset( uint32 assetID, const char* pFileName, bool assertOnFail );\r\n\tvoid*\t\tGetAsset(const char *p_assetName, bool assertOnFail = true);\t\r\n\tvoid*\t\tGetAsset(uint32\tassetID, bool assertOnFail = true);\t\r\n\tvoid*\t\tLoadOrGetAsset(const char *p_assetName, bool async_load, bool use_pip, bool permanent = false, uint32 group = 0, void* pExtraData = NULL, Script::CStruct *pParams = NULL);\t\r\n\t\r\n\tbool\t\tAssetAllocated(uint32\tassetID);\r\n\tbool\t\tAssetAllocated(const char *p_assetName);\r\n\r\n\tbool\t\tAssetLoaded(uint32\tassetID);\r\n\tbool\t\tAssetLoaded(const char *p_assetName);\r\n\t\r\n\tvoid\t\tAddRef(uint32 asset_id, uint32 ref_id, uint32 group = 0);\r\n\tvoid\t\tAddRef(const char *p_assetName, uint32 ref_id, uint32 group = 0);\r\n\t\r\n\tvoid\t\tSetReferenceChecksum(uint32 reference_checksum);\t   \r\n\tuint32\t\tGetReferenceChecksum() const;\r\n\t\r\n\tvoid\t\tSetDefaultPermanent(bool permanent);\r\n\tbool\t\tGetDefaultPermanent() const;\r\n\r\n\tvoid* \t\tGetFirstInGroup(uint32 group);\r\n\tvoid* \t\tGetNthInGroup(uint32 group, int n);\r\n\r\n\tint \t\tGetIndexInGroup(uint32 checksum);\r\n\tint \t\tGetGroup(uint32 checksum);\r\n\tint \t\tCountGroup(uint32 group);\r\n\tint \t\tCountSameGroup(uint32 checksum);\r\n\r\n\tvoid\t\tUnloadAllTables( bool destroy_permanent = false );\r\n\tvoid\t\tDestroyReferences( CAsset* pAsset );\r\n\tvoid\t\tUnloadAsset( CAsset* pAsset );\r\n\tCAsset*\t\tGetAssetNode( uint32 assetID, bool assertOnFail );\r\n\t\r\n\t// ideally, the LoadAnim function should be made more generic\r\n\tbool\t\tLoadAnim(const char* pFileName, uint32 animName, uint32 referenceChecksum, bool async_load, bool use_pip);\r\n\t\r\nprivate:\r\n\r\n\tbool\t\t\t\t\t\t\tm_default_permanent;\r\n\tuint32 \t\t\t\t\t\t\tm_reference_checksum;\t// used for anims, bit of a patch\r\n\tLst::HashTable<Ass::CAsset>*\tmp_asset_table;\r\n\tCAsset*\t\t\t\t\t\t\tmp_assetlist_head;\t\t   \r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Ass\r\n\r\n#endif\t// __GEL_ASSMAN_H\r\n\r\n"
  },
  {
    "path": "Code/Gel/AssMan/NodeArrayAsset.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////\r\n// NodeArrayAsset.cpp\r\n//\r\n// Asset depended code for loading, unloading and reloading a node array\r\n//\r\n// Dave\r\n//\r\n\r\n\r\n#include\t<gel/assman/nodearrayasset.h>\r\n#include\t<gel/assman/assettypes.h>\r\n#include\t<gfx/nx.h>\r\n#include\t<gel/scripting/symboltable.h>\r\n#include\t<gel/scripting/script.h>\r\n#include\t<sk/scripting/gs_file.h>\r\n\r\nnamespace Ass\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CNodeArrayAsset::Load( const char* p_file, bool async_load, bool use_pip, void* pExtraData , Script::CStruct *pStruct)\r\n{\r\n\tSkateScript::LoadQB( p_file, Script::ASSERT_IF_DUPLICATE_SYMBOLS);\r\n\tm_qb_checksum = Script::GenerateCRC( p_file );\r\n\r\n\tchar nodearrayname[128];\r\n\r\n\t// Skip back to the backslash.\r\n\tconst char *p = &p_file[strlen( p_file ) - 1];\r\n\twhile( *p != '\\\\' && *p != '/') p--;\r\n\tp++;\r\n\r\n\tstrcpy( nodearrayname, p );\t\t\t\t\t\t\t\t\t\t\t\t// nodearrayname is now \"name.qb\"\r\n\tsprintf( &nodearrayname[strlen( nodearrayname ) - 3], \"_nodearray\" );\t// nodearrayname is now \"name_nodearray\"\r\n\tvoid *p_data = Script::GetArray( nodearrayname );\r\n\r\n\t// Set the array as the data returned when queried,\r\n\tSetData( p_data );\r\n\r\n\tDbg_MsgAssert( p_data, ( \"Could not find nodearray %s in %s\", nodearrayname, p_file ));\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CNodeArrayAsset::Unload()                     \r\n{\r\n\t// Unload the asset.\r\n\tSkateScript::UnloadQB( m_qb_checksum );\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CNodeArrayAsset::Reload( const char* p_file )\r\n{\r\n\tDbg_Message( \"Reloading %s\", p_file );\r\n\t\r\n\tUnload();\r\n\r\n\treturn( Load( p_file, false, 0, NULL, NULL ) == 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CNodeArrayAsset::LoadFinished()\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char* CNodeArrayAsset::Name()            \r\n{\r\n\t// Printable name, for debugging.\r\n\treturn \"Node Array\";\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nEAssetType CNodeArrayAsset::GetType()         \r\n{\r\n\t// type is hard wired into asset class \r\n\treturn ASSET_NODEARRAY;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/AssMan/NodeArrayAsset.h",
    "content": "////////////////////////////////////////////////////////////////////////////\r\n// animasset.h - interface between asset manager, and the actual animation\r\n// provides a common interface to the \r\n#ifndef\t__GEL_NODEARRAYASSET_H__\r\n#define\t__GEL_NODEARRAYASSET_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include\t<gel/assman/asset.h>\r\n\r\nnamespace Ass\r\n{\r\n\r\nclass \tCNodeArrayAsset : public CAsset\r\n{\r\n\r\npublic:\r\n\tvirtual int \t\t\t\tLoad( const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct );\t// create or load the asset\r\n\tvirtual int \t\t\t\tUnload();\t\t\t\t\t\t\t\t\t\t// Unload the asset\r\n\tvirtual int \t\t\t\tReload( const char *p_file);\r\n\tvirtual bool\t\t\t\tLoadFinished();\t\t\t\t\t\t\t\t\t// Check to make sure asset is actually there\r\n\tvirtual const char *  \t\tName();\t\t\t\t\t\t\t\t\t\t\t// printable name, for debugging\r\n\tvirtual EAssetType \t\t\tGetType();\t\t\t\t\t\t\t\t\t\t// type is hard wired into asset class\r\nprivate:\r\n\r\n\r\n\tuint32\t\t\t\t\t\tm_qb_checksum;\r\n};\r\n\r\n\r\n} // end namespace Ass\r\n\r\n#endif\t\t\t// #ifndef\t__GEL_ASSET_H__\r\n\r\n"
  },
  {
    "path": "Code/Gel/AssMan/animasset.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////\r\n// AnimAsset.cpp\r\n//\r\n// Asset depended code for loading, unloading and reloading an animation\r\n//\r\n// Mick\r\n//\r\n\r\n\r\n#include\t<gel/assman/animasset.h>\r\n\r\n#include\t<gel/assman/assettypes.h>\r\n\r\n#include\t<gfx/bonedanim.h>\r\n#include\t<gfx/nx.h>\r\n\r\n#include\t<gel/scripting/symboltable.h>\r\n\r\n\r\nnamespace Ass\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CAnimAsset::Load(const char* p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct)     // create or load the asset\r\n{\r\n\tint errorCode = -1;\r\n\r\n\tMem::PushMemProfile((char*)p_file);\r\n\t\r\n\tGfx::CBonedAnimFrameData* pSeq = new Gfx::CBonedAnimFrameData;\r\n\r\n\tchar fullName[256];\r\n\t\r\n\t// add extension to create name of platform-specific SKA file\r\n\tsprintf( fullName, \"%s.%s\", p_file, Nx::CEngine::sGetPlatformExtension() );\r\n\t\r\n\t// Load the data\r\n\tif ( !pSeq->Load(fullName, true, async_load, use_pip) )\r\n\t{\r\n\t\tif ( Script::GetInteger( CRCD(0x25dc7904,\"AssertOnMissingAssets\") ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"Anim %s doesn't exist.\", fullName ) );\r\n\t\t}\r\n\t\tdelete pSeq;\r\n\t\tpSeq = NULL;\r\n\t\tgoto failure;\r\n\t}\r\n\r\n\t// if we get this far, then it's successful\r\n\terrorCode = 0;\r\n\r\nfailure:\r\n\t// Add it to the list:\r\n\tSetData( (void*)pSeq );\r\n\tMem::PopMemProfile(/*(char*)p_file*/);\r\n\treturn errorCode;\r\n}\r\n\r\nint CAnimAsset::Load(uint32* p_data, int data_size)     // create or load the asset\r\n{\r\n\tint errorCode = -1;\r\n\r\n\tchar pDebugAssetString[256];\r\n\tsprintf( pDebugAssetString, \"anim from data stream\" );\r\n\t\r\n\tMem::PushMemProfile((char*)pDebugAssetString);\r\n\r\n\tGfx::CBonedAnimFrameData* pSeq = new Gfx::CBonedAnimFrameData;\r\n\r\n\t// Load the data\r\n\tif ( !pSeq->Load(p_data, data_size, true ) )\r\n\t{\r\n\t\tif ( Script::GetInteger( CRCD(0x25dc7904,\"AssertOnMissingAssets\") ) )\r\n\t\t{\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t}\r\n\t\tdelete pSeq;\r\n\t\tpSeq = NULL;\r\n\t\tgoto failure;\r\n\t}\r\n\r\n\t// if we get this far, then it's successful\r\n\terrorCode = 0;\r\n\r\nfailure:\r\n\t// Add it to the list:\r\n\tSetData( (void*)pSeq );\r\n\tMem::PopMemProfile(/*(char*)p_file*/);\r\n\treturn errorCode;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CAnimAsset::Unload()                     \r\n{\r\n\t// Unload the asset\r\n\t\r\n\tif (GetData())\r\n\t{\r\n        delete (Gfx::CBonedAnimFrameData*) GetData();\r\n\t\t\r\n        SetData(NULL);\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CAnimAsset::Reload(const char* p_file)\r\n{\r\n\tDbg_Message( \"Reloading %s\", p_file );\r\n\t\r\n\tUnload();\r\n\r\n\treturn ( Load(p_file, false, 0, NULL, NULL ) == 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAnimAsset::LoadFinished()\r\n{\r\n\tGfx::CBonedAnimFrameData * p_anim = (Gfx::CBonedAnimFrameData*) GetData();\r\n\tDbg_MsgAssert(p_anim, (\"LoadFinished(): Data pointer NULL (load probably was never started)\"));\r\n\r\n\treturn p_anim->LoadFinished();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char* CAnimAsset::Name()            \r\n{\r\n\t// printable name, for debugging\r\n\treturn \"Animation\";\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nEAssetType CAnimAsset::GetType()         \r\n{\r\n\t// type is hard wired into asset class \r\n\treturn ASSET_ANIM;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/AssMan/animasset.h",
    "content": "////////////////////////////////////////////////////////////////////////////\r\n// animasset.h - interface between asset manager, and the actual animation\r\n// provides a common interface to the \r\n#ifndef\t__GEL_ANIMASSET_H__\r\n#define\t__GEL_ANIMASSET_H__\r\n\r\n\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include\t<gel/assman/asset.h>\r\n\r\nnamespace Ass\r\n{\r\n\r\n\r\n\r\nclass \tCAnimAsset : public CAsset\r\n{\r\n\r\npublic:\r\n        virtual int \t\t\t\tLoad(const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct);\t// create or load the asset\r\n\t\tvirtual int \t\t\t\tLoad(uint32* p_data, int data_size);\t// create or load the asset\r\n        virtual int \t\t\t\tUnload();                     // Unload the asset\r\n        virtual int \t\t\t\tReload(const char *p_file);\r\n\t\tvirtual bool\t\t\t\tLoadFinished();    // Check to make sure asset is actually there\r\n     \tvirtual const char *  \t\tName();            // printable name, for debugging\r\n\t\tvirtual EAssetType \t\t\tGetType();         // type is hard wired into asset class \r\nprivate:\r\n\t\t\r\n\r\n};\r\n\r\n\r\n} // end namespace Ass\r\n\r\n#endif\t\t\t// #ifndef\t__GEL_ASSET_H__\r\n\r\n"
  },
  {
    "path": "Code/Gel/AssMan/asset.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////\r\n// Asset.cpp\r\n//\r\n// Mick\r\n//\r\n// Base class of all assets\r\n// provides basic interface to them\r\n\r\n\r\n#include\t<gel/assman/asset.h>\r\n#include \t<gel/assman/assettypes.h>\r\n\r\n\r\nnamespace Ass\r\n{\r\n\r\n// when destroying an asset, we also unload it\r\n// this should only be done via the asset manager\r\n\r\nCAsset::CAsset()\r\n{\r\n}\r\n\r\nCAsset::~CAsset()\r\n{\r\n}\r\n\r\n// Unlink for the doubly linked list\r\nvoid CAsset::Unlink()\r\n{\r\n\tmp_next->mp_prev = mp_prev;\r\n\tmp_prev->mp_next = mp_next;\r\n\tmp_prev = this;\r\n\tmp_next = this;\r\n}\r\n\r\nint CAsset::Load(const char *p_file, bool async_load, bool use_pip, void* pExtraData , Script::CStruct *pParams)\r\n{\r\n\tDbg_MsgAssert(0,(\"CAsset::Load() should not be called\"));\r\n\treturn 0;\r\n}  \t\r\n\r\nint CAsset::Load(uint32* p_data, int data_size)\r\n{\r\n\tDbg_MsgAssert(0,(\"CAsset::Load() from data buffer should not be called\"));\r\n\treturn 0;\r\n}\r\n\r\nint CAsset::Reload(const char *p_file)   \r\n{\r\n\tDbg_MsgAssert(0,(\"CAsset::Reload() should not be called\"));\r\n\treturn 0;\r\n}\r\n\r\nint \tCAsset::Unload()                  \r\n{\r\n\tDbg_MsgAssert(0,(\"CAsset::Unload() should not be called\"));\r\n\treturn 0;\r\n}\r\n\r\nbool\tCAsset::LoadFinished()\r\n{\r\n\tDbg_MsgAssert(0,(\"CAsset::LoadFinished() should not be called\"));\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\nconst char *  CAsset::Name()            // printable name, for debugging\r\n{\r\n\treturn\t\"Unnamed Asset\";\t\r\n}\r\n\r\nvoid * \tCAsset::GetData()             // return a pointer to the asset's data\r\n{\r\n\treturn mp_data;\t\t\t\t\t\r\n}\r\n\r\nvoid  \tCAsset::SetData(void *p_data)             \r\n{\r\n\tmp_data = p_data;\t\t\t\t   \r\n}\r\n\r\n\r\n//----------------------------------------------------\r\n\r\nvoid   CAsset::SetID(uint32 id)         \r\n{\r\n\tm_id = id;\r\n}\r\n\r\nuint32 CAsset::GetID()\r\n{\r\n\treturn m_id;\r\n}\r\n\r\nvoid   CAsset::SetGroup(uint32 group)     \r\n{\r\n\tm_group = group;\r\n}\r\n\r\nuint32 CAsset::GetGroup()\r\n{\r\n\treturn m_group;\r\n}\r\n\r\n\r\nEAssetType CAsset::GetType()         // type is hard wired into asset class \r\n{\r\n\treturn ASSET_UNKNOWN; \t\t// for now return 0, not sure if this should return the EAssetType\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/AssMan/asset.h",
    "content": "///////////////////////////////////////////////////////////\r\n// asset.h - base class for managed assets\r\n\r\n#ifndef\t__GEL_ASSET_H__\r\n#define\t__GEL_ASSET_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <gel/assman/assettypes.h>\r\n#include <core/string/cstring.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n}\r\n\r\n\r\nnamespace Ass\r\n{\r\nclass \tCAsset : public Spt::Class\r\n{\r\n\tfriend class CAssMan;\r\n\tfriend class CRefAsset;\r\n\r\nprotected:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\tCAsset();\t  \t\t\t\t// constructor is private, so only CAssMan can create them\r\n\t\tvirtual ~CAsset(); \t\t\t//\r\n\r\n\t\tvirtual    \tint \t\tLoad(const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pParams);\t// create or load the asset\r\n\t\tvirtual\t\tint\t\t\tLoad(uint32* p_data, int data_size);\r\n\t\tvirtual    \tint \t\tUnload();                  \t// Unload the asset\r\n\t\tvirtual    \tint \t\tReload(const char *p_file);\r\n\t\tvirtual\t\tbool\t\tLoadFinished();\t\t\t\t// Check to make sure asset is actually there\r\n\r\n\r\n\t\t\t\t\tvoid \t\tUnlink();                  \t// Unlink the asset\r\n\r\n// Some acessor functions for memory usage metrics\t\t\t\t\t\r\n\t\tvirtual   \tconst char* Name();          \t// printable name, for debugging\r\n\r\n// acessors for seting the low level id stuff \r\n// maybe this should just be derived from CObject?    \r\n\t\tvoid      \t\t\t   \tSetID(uint32 id);           \t// Unique asset ID\r\n\t\tuint32    \t\t\t   \tGetID();\r\n\t\tvirtual void      \t\tSetGroup(uint32 group);     \t// Unique group ID\r\n\t\tvirtual uint32    \t\tGetGroup();\r\n\t\t\r\n\t\tvirtual EAssetType\t  \tGetType();         \t\t\t\t// type is hard wired into asset class \r\n\t\tvirtual void     \t\tSetData(void *p_data);          // return a pointer to the asset.\r\n\t\tvirtual void *    \t\tGetData();             \t\t\t// return a pointer to the asset.\r\n\t\tvirtual\tvoid\t\t\tSetPermanent(bool perm);\r\n\r\n\t\tvoid \t\t\t\t\tSetText(const char *p_text);\r\n\t\tconst char *\t\t\tGetText();\r\n\r\nprivate:\r\n\t\tuint32\t\t\t\t   \tm_id;\r\n\t\tuint32\t\t\t\t   \tm_group;\r\n\t\t\r\n\t\tchar\t\t\t\t   \tm_permanent;  \t\t\t\t\t// should it stay in memory after a cleanup\r\n\t\tchar\t\t\t\t\tm_dead;\t\t\t\t\t\t\t// asset is dead, remove it \t\t\r\n\t\t\r\n\t\tvoid *\t\t\t\t\tmp_data;   \t\t\t\t\t\t// pointer to the asset data\r\n\r\n//\t\tStr::String\t\t\t\tm_text;\r\n\r\nprotected:\r\n\t\tCRefAsset\t*\t\t\tmp_ref_asset;\t\t\t\t\t// pointer to first CRefAsset that points to this \r\n\r\n// The assets are also stored in a simple doubly linked list with a head node\r\n// this is to simplify the \r\n\t\tCAsset  *\t\t\t\tmp_prev;\r\n\t\tCAsset  *\t\t\t\tmp_next;\r\n\t\r\n};\r\n\r\n\r\n\r\n//////////////////////////////////////////////////////////////////////////\r\n// Inline member functions\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\r\n\r\ninline\t\tvoid \t\t\t\t\tCAsset::SetText(const char *p_text)\r\n{\r\n//\tm_text = p_text;\r\n}\r\n\r\ninline \t\tconst char *\t\t\tCAsset::GetText()\r\n{\r\n//\treturn m_text.getString();\r\n\treturn \"names removed\";\r\n}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\ninline\tvoid\tCAsset::SetPermanent(bool perm) {m_permanent = perm;}\r\n\r\n\r\n} // end namespace Ass\r\n\r\n#endif\t\t\t// #ifndef\t__GEL_ASSET_H__\r\n\r\n"
  },
  {
    "path": "Code/Gel/AssMan/assettypes.h",
    "content": "// asset types for the asset manager\r\n\r\n#ifndef __GEL_ASSETTYPES_H\r\n#define __GEL_ASSETTYPES_H\r\n\r\nnamespace Ass\r\n{\r\n\r\nenum\tEAssetType {\r\n\tASSET_UNKNOWN,\t\t\t\t\t\t\t// unknown, needs to be determined by inspection\r\n\tASSET_BINARY,\t\t\t\t\t\t\t// binary file\r\n\tASSET_SCENE,\t\t\t\t\t\t\t// world_geometry\r\n\tASSET_TEXTURES,\t\t\t\t\t\t\t// Texture file\r\n\tASSET_COLLISION,\t\t\t\t\t\t// collision file\r\n\tASSET_ANIM,\t\t\t\t\t\t\t\t// animation\r\n    ASSET_SKELETON,                         // skeleton\r\n\tASSET_SKIN,\t\t\t\t\t\t\t\t// skin\r\n\tASSET_CUTSCENE,\t\t\t\t\t\t\t// cutscene\r\n\tASSET_NODEARRAY,\t\t\t\t\t\t// model node array\r\n};\r\n\r\n} // namespace Ass\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/AssMan/cutsceneasset.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Ass\r\n//* FILENAME:       cutsceneasset.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  01/13/2003\r\n//****************************************************************************\r\n\r\n#include <gel/assman/cutsceneasset.h>\r\n\r\n#include <gel/assman/assettypes.h>\r\n#include <gfx/nx.h>\r\n#include <sk/objects/cutscenedetails.h>\r\n\r\nnamespace Ass\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CCutsceneAsset::Load( const char* p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct )     // create or load the asset\r\n{\r\n\tMem::PushMemProfile( (char*)p_file );\r\n\t\r\n\tObj::CCutsceneData* p_cutsceneData = new Obj::CCutsceneData;\r\n\r\n\t// get the platform-specific CUT file name\r\n\tchar platFileName[256];\r\n\tsprintf( platFileName, \"%s.%s\", p_file, Nx::CEngine::sGetPlatformExtension() );\r\n\t\r\n\t// load the data\r\n\tif ( !p_cutsceneData->Load( platFileName, true, async_load ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Cutscene %s doesn't exist.\", platFileName ) );\r\n\t\treturn -1;\r\n\t}\r\n\t\r\n\t// add it to the list:\r\n\tSetData( (void*)p_cutsceneData );\r\n\r\n\tMem::PopMemProfile(/*(char*)p_file*/);\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CCutsceneAsset::Unload()                     \r\n{\r\n\t// Unload the asset\r\n\tObj::CCutsceneData* pData = (Obj::CCutsceneData*)GetData();\r\n\tif ( pData )\r\n\t{\r\n        delete pData;\r\n        SetData(NULL);\r\n\t}\r\n\t\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CCutsceneAsset::Reload(const char* p_file)\r\n{\r\n\tDbg_Message( \"Reloading %s...\", p_file );\r\n\t\r\n\tUnload();\r\n\r\n\treturn ( Load( p_file, false, 0, NULL, NULL ) == 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCutsceneAsset::LoadFinished()\r\n{\r\n\tObj::CCutsceneData* p_cutsceneData = (Obj::CCutsceneData*)GetData();\r\n\tDbg_MsgAssert( p_cutsceneData, ( \"LoadFinished(): Data pointer NULL (load probably was never started)\" ) );\r\n\treturn p_cutsceneData->LoadFinished();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char* CCutsceneAsset::Name()            \r\n{\r\n\t// printable name, for debugging\r\n\treturn \"Cutscene\";\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nEAssetType CCutsceneAsset::GetType()         \r\n{\r\n\t// type is hard wired into asset class \r\n\treturn ASSET_CUTSCENE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/AssMan/cutsceneasset.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Ass\r\n//* FILENAME:       cutsceneasset.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  01/13/2003\r\n//****************************************************************************\r\n\r\n// interface between asset manager, and the actual cutscene\r\n\r\n#ifndef\t__GEL_CUTSCENEASSET_H__\r\n#define\t__GEL_CUTSCENEASSET_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/assman/asset.h>\r\n\r\nnamespace Ass\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nclass CCutsceneAsset : public CAsset\r\n{\r\n\r\npublic:\r\n        virtual int \t\t\t\tLoad(const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct);\t// create or load the asset\r\n        virtual int \t\t\t\tUnload();                     \t\t\t\t// unload the asset\r\n        virtual int \t\t\t\tReload(const char *p_file);\r\n\t\tvirtual bool\t\t\t\tLoadFinished();    \t\t\t\t\t\t\t// check to make sure asset is actually there\r\n     \tvirtual const char *  \t\tName();            \t\t\t\t\t\t\t// printable name, for debugging\r\n\t\tvirtual EAssetType \t\t\tGetType();         \t\t\t\t\t\t\t// type is hard wired into asset class \r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gel/AssMan/refasset.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////\r\n// RefAsset.cpp\r\n//\r\n// Mick\r\n//\r\n// Type of asset that just refers to another asset\r\n// so you can have multiple indicies to reference an asset\r\n\r\n\r\n#include\t<gel/assman/asset.h>\r\n#include\t<gel/assman/refasset.h>\r\n\r\n\r\nnamespace Ass\r\n{\r\n\r\nCRefAsset::CRefAsset(CAsset *p_asset)\r\n{\r\n\r\n\tmp_asset = p_asset;\r\n\tmp_sibling = NULL;\r\n\tif (p_asset->mp_ref_asset == NULL)\r\n\t{\r\n\t\t// this is the first reference, so just stick it in mp_ref_asset\r\n\t\tp_asset->mp_ref_asset = this;\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// it's a new asset, so insert it as the head\r\n\t\t// of siblings that refer to this\r\n\t\tCRefAsset *p_other_ref = p_asset->mp_ref_asset;\r\n\t\tp_asset->mp_ref_asset = this;\r\n\t\tmp_sibling = p_other_ref;\r\n\t}\r\n\tmp_data = NULL;\t\t\t\t\t\t\t// Ref Assets explicitly have no data\r\n\tm_permanent = p_asset->m_permanent;\t\t// inherit the permanence flag\r\n}\r\n\r\n\r\n\r\nCRefAsset::~CRefAsset()\r\n{\r\n\r\n// unhook the references\r\n// from the assman table, the asset it refers to, and other assets\r\n\t\r\n\tif (mp_asset)\r\n\t{\r\n\t\tCRefAsset * p_prev = mp_asset->mp_ref_asset;\r\n\t\tif (p_prev == this)\r\n\t\t{\r\n\t\t\tmp_asset->mp_ref_asset = mp_sibling;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\twhile (p_prev && p_prev->mp_sibling  != this)\r\n\t\t\t{\r\n\t\t\t\tp_prev = p_prev->mp_sibling;\r\n\t\t\t}\r\n\t\t\tDbg_MsgAssert(p_prev,(\"Reference not listed in its parent asset\")); \r\n\t\t\tp_prev->mp_sibling = mp_sibling;\r\n\t\t}\t\r\n\t\tmp_asset = NULL;\t\r\n\t\tmp_sibling = NULL;\r\n\t}\t\t\t\t\t\r\n\t\r\n\r\n\tDbg_MsgAssert(mp_asset == NULL,(\"Destroying ref with non-null asset\"));\t\r\n\tDbg_MsgAssert(mp_sibling == NULL,(\"Destroying ref with non-null sibling\"));\t\r\n\tDbg_MsgAssert(mp_data == NULL,(\"Ref Asset has data!\"));\r\n\r\n}\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// all other functions simply call the appropiate function on the referenced asset\r\n// (might want to make these inline later)\r\n\r\nint \t\t\tCRefAsset::Load(const char *p_file, bool async_load, bool use_pip, void* pExtraData)  \t// create or load the asset\r\n{\r\n\tDbg_MsgAssert(!async_load, (\"Async load not supported on CRefAsset\"));\r\n\r\n//\treturn mp_asset->Load(p_file);\r\n\treturn 0;\r\n}\r\n\r\n\r\nint \t\t\tCRefAsset::Unload()                  \t// Unload the asset\r\n{\r\n//\treturn mp_asset->Unload();\r\n\treturn 0;\r\n}\r\n\r\n\r\nint \t\t\tCRefAsset::Reload(const char *p_file)\r\n{\r\n//\tprintf(\"Reloading dereferenced asset with %s\\n\", p_file);\r\n\r\n\treturn mp_asset->Reload(p_file);\r\n}\r\n\r\nbool\t\t\tCRefAsset::LoadFinished()\r\n{\r\n\tDbg_MsgAssert(GetData(), (\"LoadFinished(): Data pointer NULL (load probably was never started)\"));\r\n\r\n\treturn mp_asset->LoadFinished();\r\n}\r\n\r\n\r\n\r\nconst char* \tCRefAsset::Name()          \t\t\t// printable name, for debugging\r\n{\r\n\treturn mp_asset->Name();\r\n}\r\n\r\n\r\nvoid      \t\tCRefAsset::SetGroup(uint32 group)     // Unique group ID\r\n{\r\n//\tmp_asset->SetGroup(group);\r\n\tm_group = group;\r\n}\r\n\r\n\r\nuint32    \t\tCRefAsset::GetGroup()\r\n{\r\n//\treturn mp_asset->GetGroup();\r\n\treturn m_group;\r\n}\r\n\r\n\r\nEAssetType\t  \tCRefAsset::GetType()         \t\t\t// type is hard wired into asset class \r\n{\r\n\treturn mp_asset->GetType();\r\n}\r\n\r\n\r\nvoid     \t\tCRefAsset::SetData(void *p_data)      // return a pointer to the asset.\r\n{\r\n\tmp_asset->SetData(p_data);\r\n}\r\n\r\n\r\nvoid *    \t\tCRefAsset::GetData()             \t\t// return a pointer to the asset.\r\n{\r\n\treturn mp_asset->GetData();\r\n}\r\n\r\n\r\nvoid\t\t\tCRefAsset::SetPermanent(bool perm)\r\n{\r\n\tm_permanent = perm;\r\n\tmp_asset->SetPermanent(perm);\r\n}\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/AssMan/refasset.h",
    "content": "///////////////////////////////////////////////////////////\r\n// asset.h - base class for managed assets\r\n\r\n#ifndef\t__GEL_REFASSET_H__\r\n#define\t__GEL_REFASSET_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <gel/assman/assettypes.h>\r\n\r\nnamespace Ass\r\n{\r\n\r\n\r\n\r\nclass \tCRefAsset : public CAsset\r\n{\r\n\t\tfriend class CAssMan;\r\nprotected:\r\n\t\t\t\t\t\tCRefAsset(CAsset *p_asset);\r\n\t\t\t\t\t\t~CRefAsset();\r\n\t\t\r\n\t\tint \t\t\tLoad(const char *p_file, bool async_load, bool use_pip, void* pExtraData);\t// create or load the asset\r\n\t\tint \t\t\tUnload();                  \t// Unload the asset\r\n\t\tint \t\t\tReload(const char *p_file);\r\n\t\tbool\t\t\tLoadFinished();\t\t\t\t// Check to make sure asset is actually there\r\n\t\tint  \t\t\tRamUsage();\r\n\t\tint  \t\t\tVramUsage();\r\n\t\tint  \t\t\tSramUsage();\r\n\t\tconst char* \tName();          \t\t\t// printable name, for debugging\r\n\t\tvoid      \t\tSetGroup(uint32 group);     // Unique group ID\r\n\t\tuint32    \t\tGetGroup();\r\n\t\tEAssetType\t  \tGetType();         \t\t\t// type is hard wired into asset class \r\n\t\tvoid     \t\tSetData(void *p_data);      // return a pointer to the asset.\r\n\t\tvoid *    \t\tGetData();             \t\t// return a pointer to the asset.\r\n\t\tvoid\t\t\tSetPermanent(bool perm);\r\n\r\nprivate:\r\n\t\tCAsset\t*\t\t\t\tmp_asset;\t\t\t// pointer to the actual asset \r\n\t\tCRefAsset\t*\t\t\tmp_sibling;\t\t\t// pointer to other CRefAsset that references mp_asset \t\r\n};\r\n\r\n//////////////////////////////////////////////////////////////////////////\r\n// Inline member functions\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\r\n\r\n} // end namespace Ass\r\n\r\n#endif\t\t\t// #ifndef\t__GEL_REFASSET_H__\r\n\r\n"
  },
  {
    "path": "Code/Gel/AssMan/skeletonasset.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Ass\r\n//* FILENAME:       skeletonasset.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  ??/??/????\r\n//****************************************************************************\r\n\r\n#include <gel/assman/skeletonasset.h>\r\n\r\n#include <gel/assman/assettypes.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/skeleton.h>\r\n\r\nnamespace Ass\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CSkeletonAsset::Load( const char *p_file, bool async_load, bool use_pip, void* pExtraData , Script::CStruct *pStruct)     // create or load the asset\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\tDbg_MsgAssert( !async_load, ( \"Async load not supported on CSkeletonAsset\" ) );\r\n\r\n\t// Load the data, add it to the list:\r\n\tGfx::CSkeletonData* pSkeletonData = new Gfx::CSkeletonData;\r\n\t\r\n\tchar fullName[256];\r\n\t\r\n\t// add extension to create name of platform-specific SKE file\r\n\tsprintf( fullName, \"%s.%s\", p_file, Nx::CEngine::sGetPlatformExtension() );\r\n\t\r\n\tif ( !pSkeletonData->Load( fullName, true ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"File %s doesn't exist.\", fullName ));\r\n\t\treturn -1;\r\n\t}\r\n\tSetData( (void*)pSkeletonData );\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CSkeletonAsset::Load( uint32* p_data, int data_size )\r\n{\r\n\tchar pDebugAssetString[256];\r\n\tsprintf( pDebugAssetString, \"skeleton from data stream\" );\r\n\t\r\n\tMem::PushMemProfile((char*)pDebugAssetString);\r\n\r\n\t// Load the data, add it to the list:\r\n\tGfx::CSkeletonData* pSkeletonData = new Gfx::CSkeletonData;\r\n\t\r\n\tif ( !pSkeletonData->Load( p_data, data_size, true ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Couldn't create skeleton from data stream.\" ));\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tSetData((void*)pSkeletonData);\r\n\r\n\tMem::PopMemProfile(/*\"skeleton from data stream\"*/);\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CSkeletonAsset::Unload()                     // Unload the asset\r\n{\r\n\tGfx::CSkeletonData* pData = (Gfx::CSkeletonData*)GetData();\r\n\tif ( pData )\r\n\t{\r\n        delete pData;\r\n        SetData(NULL);\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CSkeletonAsset::Reload( const char *p_file )\r\n{\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CSkeletonAsset::LoadFinished()\r\n{\r\n\tDbg_MsgAssert( GetData(), ( \"LoadFinished(): Data pointer NULL (load probably was never started)\" ) );\r\n\r\n\t// Since we don't support async, this is always true\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nconst char *  CSkeletonAsset::Name()            // printable name, for debugging\r\n{\r\n\treturn \"Skeleton\";\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nEAssetType CSkeletonAsset::GetType()         // type is hard wired into asset class \r\n{\r\n\treturn ASSET_SKELETON; \t\t\t\t\t// for now return 0, not sure if this should return the EAssetType\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/AssMan/skeletonasset.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Ass\r\n//* FILENAME:       skeletonasset.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  ??/??/????\r\n//****************************************************************************\r\n\r\n// interface between asset manager, and the actual skeleton data\r\n// provides a common interface to the skeleton data\r\n\r\n#ifndef\t__GEL_SKELETONASSET_H__\r\n#define\t__GEL_SKELETONASSET_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/assman/asset.h>\r\n\r\nnamespace Ass\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nclass CSkeletonAsset : public CAsset\r\n{\r\n\r\npublic:\r\n        virtual int \t\t\t\tLoad(const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct);\t// create or load the asset\r\n\t\tvirtual int \t\t\t\tLoad(uint32* p_data, int data_size);\t\t// create or load the asset from data stream\r\n        virtual int \t\t\t\tUnload();                     \t\t\t\t// unload the asset\r\n        virtual int \t\t\t\tReload(const char *p_file);\r\n\t\tvirtual bool\t\t\t\tLoadFinished();    \t\t\t\t\t\t\t// check to make sure asset is actually there\r\n     \tvirtual const char *  \t\tName();            \t\t\t\t\t\t\t// printable name, for debugging\r\n\t\tvirtual EAssetType \t\t\tGetType();         \t\t\t\t\t\t\t// type is hard wired into asset class \r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n\r\n#endif"
  },
  {
    "path": "Code/Gel/AssMan/skinasset.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////\r\n// SkinAsset.cpp\r\n//\r\n// Asset depended code for loading, unloading and reloading a skin\r\n//\r\n// Mick\r\n//\r\n\r\n\r\n#include\t<gel/assman/skinasset.h>\r\n\r\n#include\t<core/string/stringutils.h>\r\n\t\t\t\t\t\t   \r\n#include\t<gel/assman/assettypes.h>\r\n\r\n#include\t<gfx/nx.h>\r\n#include\t<gfx/nxmesh.h>\r\n\r\nnamespace Ass\r\n{\r\n\r\nint CSkinAsset::Load(const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct)     // create or load the asset\r\n{\r\n\tDbg_MsgAssert(!async_load, (\"Async load not supported on CSkinAsset\"));\r\n\r\n\tMem::PushMemProfile((char*)p_file);\r\n\r\n\tSSkinAssetLoadContext theContext;\r\n\ttheContext.forceTexDictLookup = false;\r\n\ttheContext.doShadowVolume = false;\r\n\ttheContext.texDictOffset = 0;\r\n\r\n\t// GJ:  kludge to prevent tex dict offset clashes\r\n\t// in bail board asset...  i will remove this\r\n\t// after i figure out why the tex dict offsets\r\n\t// are clashing in the first place...\r\n//\tif ( strstr(p_file,\"board_default\") )\r\n//\t{\r\n//\t\ttexDictOffset = -1;\r\n//\t}\r\n\r\n\tif ( pExtraData )\r\n\t{\r\n\t\ttheContext = *(SSkinAssetLoadContext*)pExtraData;\r\n\t}\r\n\t\r\n\tNx::CMesh* pMesh = Nx::CEngine::sLoadMesh( p_file, theContext.texDictOffset, theContext.forceTexDictLookup, theContext.doShadowVolume );\r\n\tif ( !pMesh )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"mesh %s doesn't exist.\", p_file ));\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tSetData((void*)pMesh);\r\n\r\n\t// make sure the filename is in lower-case\r\n\tchar msg[128];\r\n\tstrcpy( msg, p_file );\r\n\tStr::LowerCase( msg );\r\n\r\n\t// only MDL files should load their collision data\r\n\tif ( strstr( msg, \".mdl\" ) )\r\n\t{\r\n\t\t// Might be overrided by having a \"nocollision=1\" as a parameter\r\n\t\tint no_collision = 0;\r\n\t\tif (pStruct)\r\n\t\t{\r\n\t\t\tpStruct->GetInteger(CRCD(0xbf29bc0,\"nocollision\"),&no_collision);\r\n\t\t}\r\n\t\tif (!no_collision)\r\n\t\t{\r\n\t\t\tpMesh->LoadCollision(p_file);\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Model node arrays are now loaded via the NodeArrayComponent.\r\n//\tpMesh->LoadModelNodeArray(p_file);\r\n\r\n\tMem::PopMemProfile(/*\"Skin\"*/);\r\n\r\n\treturn 0;\r\n}\r\n\r\nint CSkinAsset::Load(uint32* p_data, int data_size)     // create or load the asset\r\n{\r\n\tchar pDebugAssetString[256];\r\n\tsprintf( pDebugAssetString, \"skin from data stream\" );\r\n\t\r\n\tMem::PushMemProfile((char*)pDebugAssetString);\r\n\r\n\t// GJ:  for now, we need to access 3 pointers for the MDL, TEX, and CAS\r\n\t// data...  eventually, i'd like to store each of the 3 files\r\n\t// separately in the asset manager, in which case we wouldn't\r\n\t// have to do this clumsy hack of sending 3 pointers wrapped up\r\n\t// in a struct...\r\n\tSCutsceneModelDataInfo* p_cutscene_data = (SCutsceneModelDataInfo*)p_data;\r\n\r\n\tNx::CMesh* pMesh = Nx::CEngine::sLoadMesh( p_cutscene_data->modelChecksum,\r\n\t\t\t\t\t\t\t\t\t\t\t   p_cutscene_data->pModelData,\r\n\t\t\t\t\t\t\t\t\t\t\t   p_cutscene_data->modelDataSize,\r\n\t\t\t\t\t\t\t\t\t\t\t   p_cutscene_data->pCASData,\r\n\t\t\t\t\t\t\t\t\t\t\t   p_cutscene_data->texDictChecksum,\r\n\t\t\t\t\t\t\t\t\t\t\t   p_cutscene_data->pTextureData,\r\n\t\t\t\t\t\t\t\t\t\t\t   p_cutscene_data->textureDataSize,\r\n\t\t\t\t\t\t\t\t\t\t\t   p_cutscene_data->texDictOffset,\r\n\t\t\t\t\t\t\t\t\t\t\t   p_cutscene_data->isSkin,\r\n\t\t\t\t\t\t\t\t\t\t\t   p_cutscene_data->doShadowVolume );\r\n\tif ( !pMesh )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Couldn't create mesh from data stream.\" ));\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tSetData((void*)pMesh);\r\n\r\n\t// for now, we're going to assume that data loaded in through\r\n\t// a data stream will not have collision or a node array,\r\n\t// since we're only using this for cutscene assets right \r\n\t// now...  this can be changed very easily...\r\n\r\n\tMem::PopMemProfile(/*\"skin from data stream\"*/);\r\n\r\n\treturn 0;\r\n}\r\n\r\nint CSkinAsset::Unload()                     // Unload the asset\r\n{\r\n\tif (GetData())\r\n\t{\r\n\t\tNx::CEngine::sUnloadMesh( (Nx::CMesh*) GetData() );\r\n\r\n        SetData(NULL);\r\n\t}\r\n\t\r\n\treturn 0;\r\n}\r\n\r\nint CSkinAsset::Reload(const char *p_file)\r\n{\r\n\treturn 0;\r\n}\r\n\r\nbool CSkinAsset::LoadFinished()\r\n{\r\n\tDbg_MsgAssert(GetData(), (\"LoadFinished(): Data pointer NULL (load probably was never started)\"));\r\n\r\n\t// Since we don't support async, this is always true\r\n\treturn true;\r\n}\r\n\r\nconst char *  CSkinAsset::Name()            // printable name, for debugging\r\n{\r\n\treturn \"Skin\";\t\r\n}\r\n\r\nEAssetType CSkinAsset::GetType()         // type is hard wired into asset class \r\n{\r\n\treturn ASSET_SKIN; \t\t\t\t\t// for now return 0, not sure if this should return the EAssetType\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/AssMan/skinasset.h",
    "content": "////////////////////////////////////////////////////////////////////////////\r\n// skinasset.h - interface between asset manager, and the actual skin\r\n// provides a common interface to the asset manager\r\n#ifndef\t__GEL_SKINASSET_H__\r\n#define\t__GEL_SKINASSET_H__\r\n\r\n\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include\t<gel/assman/asset.h>\r\n\r\nnamespace Ass\r\n{\r\n\r\nstruct SCutsceneModelDataInfo\r\n{\r\n\tuint32\t\tmodelChecksum;\r\n\tuint32*\t\tpModelData;\r\n\tint\t\t\tmodelDataSize;\r\n\tuint32*\t\tpTextureData;\r\n\tint\t\t\ttextureDataSize;\r\n\tuint8*\t\tpCASData;\r\n\tuint32\t\ttexDictChecksum;\r\n\tint\t\t\ttexDictOffset;\r\n\tbool\t\tisSkin;\r\n\tbool\t\tdoShadowVolume;\r\n};\r\n\r\nstruct SSkinAssetLoadContext\r\n{\r\n\tint\t\t\tforceTexDictLookup;\r\n\tbool\t\tdoShadowVolume;\r\n\tint\t\t\ttexDictOffset;\r\n};\r\n\r\nclass \tCSkinAsset : public CAsset\r\n{\r\n\r\npublic:\r\n        virtual int \t\t\t\tLoad(const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct);\t// create or load the asset\r\n\t\tvirtual int \t\t\t\tLoad(uint32* p_data, int data_size);\t// create or load the asset\r\n        virtual int \t\t\t\tUnload();                     // Unload the asset\r\n        virtual int \t\t\t\tReload(const char *p_file);\r\n\t\tvirtual bool\t\t\t\tLoadFinished();    // Check to make sure asset is actually there\r\n     \tvirtual const char *  \t\tName();            // printable name, for debugging\r\n\t\tvirtual EAssetType \t\t\tGetType();         // type is hard wired into asset class \r\nprivate:\r\n\t\t\r\n\r\n};\r\n\r\n\r\n} // end namespace Ass\r\n\r\n#endif\t\t\t// #ifndef\t__GEL_SKINASSET_H__\r\n\r\n"
  },
  {
    "path": "Code/Gel/Collision/BatchTriColl.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNx\t\t\t\t\t\t\t\t \t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel\\collision\\BatchTriColl.cpp \t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t04/12/02\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gel/collision/BatchTriColl.h>\r\n#include <gel/collision/collision.h>\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#include <libdma.h>\r\n#include <devvu0.h>\r\n#include <gfx/ngps/nx/interrupts.h>\r\n#include <gfx/ngps/nx/resource.h>\r\n#endif //__PLAT_NGPS__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n#ifdef BATCH_TRI_COLLISION\r\n\r\nCollData *\t\tCBatchTriColl::sp_coll_data;\r\n\r\nvolatile bool\tCBatchTriCollMan::s_processing = false;\r\nvolatile bool\tCBatchTriCollMan::s_result_processing = false;\r\nvolatile int\tCBatchTriCollMan::s_nested = 0;\r\nvolatile bool\tCBatchTriCollMan::s_found_collision = false;\r\nCBatchTriColl \tCBatchTriCollMan::s_tri_collision_array[MAX_BATCH_COLLISIONS][2];\r\nint\t\t\t\tCBatchTriCollMan::s_current_array = 0;\r\nint\t\t\t\tCBatchTriCollMan::s_array_size = 0;\r\nint\t\t\t\tCBatchTriCollMan::s_next_idx_to_batch = 0;\r\nint\t\t\t\tCBatchTriCollMan::s_num_collisions = 0;\r\n#ifdef __PLAT_NGPS__\r\nint \t\t\tCBatchTriCollMan::s_collision_handler_id = -1;\r\nbool \t\t\tCBatchTriCollMan::s_use_vu0_micro = false;\r\n#endif\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\n\r\n#ifdef\t__PLAT_NGPS__\r\nbool vu0RayTriangleCollision(const Mth::Vector *rayStart, const Mth::Vector *rayDir,\r\n\t\t\t\t\t\t\t Mth::Vector *v0, Mth::Vector *v1, Mth::Vector *v2, float *t)\r\n{\r\n\tregister bool result;\r\n\r\n\tasm __volatile__(\r\n\t\"\r\n\t.set noreorder\r\n\tlqc2    vf06,0x0(%4)\t\t# v0\r\n\tlqc2    vf08,0x0(%6)\t\t# v2\r\n\tlqc2    vf07,0x0(%5)\t\t# v1\r\n\tlqc2    vf04,0x0(%2)\t\t# rayStart\r\n\tlqc2    vf05,0x0(%3)\t\t# rayDir\r\n\r\n\tvcallms\tRayTriangleCollision\t# call microsubroutine\r\n\tvnop\t\t\t\t\t\t\t# interlocking instruction, waits for vu0 completion\r\n\r\n\tcfc2\t%0,$vi02\t\t\t# get boolean result from vu0\r\n\t#li\t\t%0,1\t\t\t\t# store 1 for return value\r\n\r\n\tbeq\t\t%0, $0, vu0RayTriDone\t# skip copy of t if not needed\r\n\tnop\r\n\r\n\tqmfc2\t$8, $vf17\t\t\t# move t to $8\r\n\tsw\t\t$8, 0(%1)\t\t\t# and write out\r\n\r\nvu0RayTriDone:\r\n\r\n\t.set reorder\r\n\t\": \"=r\" (result), \"+r\" (t) : \"r\" (rayStart), \"r\" (rayDir), \"r\" (v0), \"r\" (v1) , \"r\" (v2) : \"$8\", \"$9\" );\r\n\r\n\treturn result;\r\n}\r\n#endif //\t__PLAT_NGPS__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCBatchTriCollMan::sInit(CollData *p_coll_data)\r\n{\r\n\t// Check for nesting; abort if true\r\n\tif (s_processing)\r\n\t{\r\n\t\ts_nested++;\r\n\t\treturn false;\r\n\t}\r\n\r\n\tDbg_Assert(s_processing == false);\r\n\r\n\ts_array_size = 0;\r\n\ts_next_idx_to_batch = 0;\r\n\ts_found_collision = false;\r\n\r\n\tCBatchTriColl::sp_coll_data = p_coll_data;\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n    // install interrupt handler for render completion\r\n\tif (s_collision_handler_id == -1)\r\n\t{\r\n\t\ts_collision_handler_id = AddIntcHandler(INTC_VU0, s_collision_done, 0);\r\n\t\tEnableIntc(INTC_VU0);\r\n\t\tsceDevVu0PutTBit(1);\t\t// Use T-bit interrupt\r\n\t}\r\n#endif //\t__PLAT_NGPS__\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCBatchTriCollMan::sFinish()\r\n{\r\n\tif (s_nested)\r\n\t{\r\n\t\ts_nested--;\r\n\t\tDbg_Assert(s_nested >= 0);\r\n\t\treturn;\r\n\t}\r\n\r\n\t// For now, don't wait for collision to finish, since we\r\n\t// are trying to avoid a stall here.  But this will probably\r\n\t// cause deadlock situations once it is on the VU0.\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCBatchTriCollMan::sAddTriCollision(const Mth::Line &test_line, const Mth::Vector &test_line_dir,\r\n\t\t\t\t\t\t\t\t\t\t   CCollObj *p_collision_obj, FaceIndex face_index)\r\n{\r\n\tDbg_Assert(s_nested == 0);\r\n\r\n\tCBatchTriColl *p_tri_collision;\r\n\tp_tri_collision = &(s_tri_collision_array[s_array_size++][s_current_array]);\r\n\r\n\tp_tri_collision->m_test_line = test_line;\r\n\tp_tri_collision->m_test_line_dir = test_line_dir;\r\n\tp_tri_collision->mp_collision_obj = p_collision_obj;\r\n\tp_tri_collision->m_face_index = face_index;\r\n\r\n\t//Dbg_Assert(s_array_size <= MAX_BATCH_COLLISIONS);\r\n\tif (s_array_size == MAX_BATCH_COLLISIONS)\r\n\t{\r\n//\t\tsWaitTriCollisions();\t\t// make sure were done working\r\n\t\tsStartNewTriCollisions();\r\n\r\n\t\t//s_switch_buffers();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCBatchTriCollMan::sRemoveTriCollision(CBatchTriColl *p_tri_collision)\r\n{\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCBatchTriCollMan::sStartNewTriCollisions()\r\n{\r\n\tDbg_Assert(s_nested == 0);\r\n\r\n\tsWaitTriCollisions();\t\t// make sure were done working\r\n\tDbg_Assert(!s_processing);\r\n\r\n\t// Check if we have anything to do\r\n\tif (s_next_idx_to_batch >= s_array_size)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\ts_processing = true;\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n\tif(s_use_vu0_micro)\r\n\t{\r\n\t\tuint128 *p_vu0_mem = (uint128*)0x11004000;\t\t// VU0 data memory\r\n\r\n\t\t// Write out sizes first\r\n\t\tuint32 *p_vu0_word_mem = (uint32 *) (p_vu0_mem++);\r\n\t\t*(p_vu0_word_mem++) = s_next_idx_to_batch;\r\n\t\t*(p_vu0_word_mem++) = s_array_size;\r\n\r\n\t\tfor (int i = s_next_idx_to_batch; i < s_array_size; i++)\r\n\t\t{\r\n\t\t\tconst CBatchTriColl &tri_coll = s_tri_collision_array[i][s_current_array];\r\n\r\n\t\t\tMth::Vector *v0, *v1, *v2;\r\n\t\t\tif (tri_coll.mp_collision_obj->mp_coll_tri_data->m_use_face_small)\r\n\t\t\t{\r\n\t\t\t\tCCollObjTriData::SFaceSmall *face = &(tri_coll.mp_collision_obj->mp_coll_tri_data->mp_face_small[tri_coll.m_face_index]);\r\n\r\n\t\t\t\tv0 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];\r\n\t\t\t\tv1 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];\r\n\t\t\t\tv2 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];\r\n\t\t\t} else {\r\n\t\t\t\tCCollObjTriData::SFace *face = &(tri_coll.mp_collision_obj->mp_coll_tri_data->mp_faces[tri_coll.m_face_index]);\r\n\r\n\t\t\t\tv0 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];\r\n\t\t\t\tv1 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];\r\n\t\t\t\tv2 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];\r\n\t\t\t}\r\n\r\n\t\t\t*(p_vu0_mem++) = *((uint128*) &(tri_coll.m_test_line.m_start));\r\n\t\t\t*(p_vu0_mem++) = *((uint128*) &(tri_coll.m_test_line_dir));\r\n\t\t\t*(p_vu0_mem++) = *((uint128*) v0);\r\n\t\t\t*(p_vu0_mem++) = *((uint128*) v1);\r\n\t\t\t*(p_vu0_mem++) = *((uint128*) v2);\r\n\t\t}\r\n\r\n\t\t//FlushCache(WRITEBACK_DCACHE);\r\n\r\n\t\t//sceDevVu0PutTBit(1);\t\t// Use T-bit interrupt\r\n\r\n\t\t// Switch the buffers before we make the call (in case it finishes immediately)\r\n\t\ts_switch_buffers();\r\n\r\n\t\tasm __volatile__(\r\n\t\t\"\r\n\t\t.set noreorder\r\n\t\tsync.l\r\n\t\tvcallms\tBatchRayTriangleCollision\t# call microsubroutine\r\n\r\n\t\t.set reorder\r\n\t\t\");\r\n\t}\r\n\telse\r\n#endif //\t__PLAT_NGPS__\r\n\t{\r\n\t\t// Just do it manually now\r\n\t\tfor (int i = s_next_idx_to_batch; i < s_array_size; i++)\r\n\t\t{\r\n\t\t\tconst CBatchTriColl &tri_coll = s_tri_collision_array[i][s_current_array];\r\n\r\n\t\t\tMth::Vector *v0, *v1, *v2;\r\n\t\t\tif (tri_coll.mp_collision_obj->mp_coll_tri_data->m_use_face_small)\r\n\t\t\t{\r\n\t\t\t\tCCollObjTriData::SFaceSmall *face = &(tri_coll.mp_collision_obj->mp_coll_tri_data->mp_face_small[tri_coll.m_face_index]);\r\n\r\n\t\t\t\tv0 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];\r\n\t\t\t\tv1 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];\r\n\t\t\t\tv2 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];\r\n\t\t\t} else {\r\n\t\t\t\tCCollObjTriData::SFace *face = &(tri_coll.mp_collision_obj->mp_coll_tri_data->mp_faces[tri_coll.m_face_index]);\r\n\r\n\t\t\t\tv0 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];\r\n\t\t\t\tv1 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];\r\n\t\t\t\tv2 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];\r\n\t\t\t}\r\n\r\n\t\t\tfloat distance;\r\n#ifdef\t__PLAT_NGPS__\r\n\t\t\tif (vu0RayTriangleCollision(&tri_coll.m_test_line.m_start, &tri_coll.m_test_line_dir, v0, v1, v2, &distance))\r\n#else\r\n\t\t\tif (CCollObj::sRayTriangleCollision(&tri_coll.m_test_line.m_start, &tri_coll.m_test_line_dir,\r\n\t\t\t\t\t\t\t\t\t\t\t\tv0, v1, v2, &distance))\r\n#endif\r\n\t\t\t{\r\n\t\t\t\tSCollSurface collisionSurface;\r\n\r\n\t\t\t\t/* We've got one */\r\n\t\t\t\tcollisionSurface.point = (*v0);\r\n\t\t\t\tcollisionSurface.index = tri_coll.m_face_index;\r\n\r\n\t\t\t\t// Find normal\r\n\t\t\t\tMth::Vector vTmp1(*v1 - *v0);\r\n\t\t\t\tMth::Vector vTmp2(*v2 - *v0);\r\n\t\t\t\tcollisionSurface.normal = Mth::CrossProduct(vTmp1, vTmp2);\r\n\t\t\t\tcollisionSurface.normal.Normalize();\r\n\r\n\t\t\t\tif (CCollObj::s_found_collision(&tri_coll.m_test_line, tri_coll.mp_collision_obj, &collisionSurface, distance, CBatchTriColl::sp_coll_data))\r\n\t\t\t\t{\r\n\t\t\t\t\ts_found_collision = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\ts_processing = false;\t\t// Just for manual version\r\n\r\n\t\ts_switch_buffers();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tCBatchTriCollMan::s_collision_done(int arg)\r\n{\r\n#ifdef\t__PLAT_NGPS__\r\n\t// We should check to see if this is the T-bit first (instead of the debug D bit)\r\n\tuint32 stat;\r\n    asm( \"cfc2 %0, $vi29\" :\"=r\"( stat ) : );\r\n    if ( !(stat & 0x4) )\r\n\t{\r\n\t\tExitHandler();\r\n\t\treturn 0;\r\n    }\r\n\r\n\t// Save floats\r\n    //unsigned int floatBuffer[32];\r\n    //saveFloatRegs(floatBuffer);\r\n\r\n\tasm __volatile__(\r\n\t\"\r\n\t.set noreorder\r\n\tcfc2\t%0,$vi01\t\t\t\t\t# get number of collisions result from vu0\r\n\r\n\t.set reorder\r\n\t\": \"=r\" (s_num_collisions) );\r\n\r\n\ts_processing = false;\t\t// Tell that we are done\r\n\r\n\tif (s_num_collisions > 0)\r\n\t{\r\n\t\ts_result_processing = true;\r\n\t}\r\n\r\n    // restore floats\r\n    //restoreFloatRegs(floatBuffer);\r\n\r\n\tExitHandler();\r\n#endif //\t__PLAT_NGPS__\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCBatchTriCollMan::s_process_results()\r\n{\r\n#ifdef\t__PLAT_NGPS__\r\n\tSCollOutput *p_output = (SCollOutput*)0x11004010;\t\t// VU0 data memory\r\n\tint previous_array = s_current_array ^ 1;\r\n\tfor (int i = 0; i < s_num_collisions; i++)\r\n\t{\r\n\t\tconst CBatchTriColl &tri_coll = s_tri_collision_array[p_output->index][previous_array];\r\n\r\n\t\tMth::Vector *v0, *v1, *v2;\r\n\t\tif (tri_coll.mp_collision_obj->mp_coll_tri_data->m_use_face_small)\r\n\t\t{\r\n\t\t\tCCollObjTriData::SFaceSmall *face = &(tri_coll.mp_collision_obj->mp_coll_tri_data->mp_face_small[tri_coll.m_face_index]);\r\n\r\n\t\t\tv0 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];\r\n\t\t\tv1 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];\r\n\t\t\tv2 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];\r\n\t\t} else {\r\n\t\t\tCCollObjTriData::SFace *face = &(tri_coll.mp_collision_obj->mp_coll_tri_data->mp_faces[tri_coll.m_face_index]);\r\n\r\n\t\t\tv0 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];\r\n\t\t\tv1 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];\r\n\t\t\tv2 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];\r\n\t\t}\r\n\r\n\t\tSCollSurface collisionSurface;\r\n\r\n\t\t/* We've got one */\r\n\t\tcollisionSurface.point = (*v0);\r\n\t\tcollisionSurface.index = tri_coll.m_face_index;\r\n\r\n\t\t// Find normal\r\n\t\tMth::Vector vTmp1(*v1 - *v0);\r\n\t\tMth::Vector vTmp2(*v2 - *v0);\r\n\t\tcollisionSurface.normal = Mth::CrossProduct(vTmp1, vTmp2);\r\n\t\tcollisionSurface.normal.Normalize();\r\n\r\n\t\tif (CCollObj::s_found_collision(&tri_coll.m_test_line, tri_coll.mp_collision_obj, &collisionSurface, p_output->distance, CBatchTriColl::sp_coll_data))\r\n\t\t{\r\n\t\t\ts_found_collision = true;\r\n\t\t}\r\n\r\n\t\tp_output++;\r\n\t}\r\n\r\n\ts_result_processing = false;\r\n#else\r\n\tDbg_Assert(s_result_processing);\r\n#endif //\t__PLAT_NGPS__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCBatchTriCollMan::sWaitTriCollisions()\r\n{\r\n\t// Wait for collision to finish\r\n\twhile (s_processing)\r\n\t\t;\r\n\r\n\tif (s_result_processing)\r\n\t{\r\n\t\ts_process_results();\r\n\t}\r\n\r\n\treturn s_found_collision;\r\n}\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCBatchTriCollMan::sUseVU0Micro()\r\n{\r\n\t// Make sure we're not in the middle of something\r\n\tDbg_Assert(!s_processing);\r\n\tDbg_Assert(!s_result_processing);\r\n\r\n\treturn s_use_vu0_micro = NxPs2::CSystemResources::sRequestResource(NxPs2::CSystemResources::vVU0_MEMORY);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCBatchTriCollMan::sDisableVU0Micro()\r\n{\r\n\t// Make sure we're not in the middle of something\r\n\tDbg_Assert(!s_processing);\r\n\tDbg_Assert(!s_result_processing);\r\n\r\n\tif (s_use_vu0_micro)\r\n\t{\r\n\t\tNxPs2::CSystemResources::sFreeResource(NxPs2::CSystemResources::vVU0_MEMORY);\r\n\t\ts_use_vu0_micro = false;\r\n\t}\r\n}\r\n#endif\t//\t__PLAT_NGPS__\r\n\r\n#endif\t// BATCH_TRI_COLLISION\r\n\r\n} // namespace Nx\r\n\r\n"
  },
  {
    "path": "Code/Gel/Collision/BatchTriColl.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNx\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tBatchTriColl.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t04/12/2002\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__GEL_BATCHTRICOLL_H\r\n#define\t__GEL_BATCHTRICOLL_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n\r\n#include <gel/collision/collenums.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __PLAT_NGPS__\r\n//#define BATCH_TRI_COLLISION\r\n#endif\r\n\r\nnamespace Nx\r\n{\r\n\r\n#ifdef BATCH_TRI_COLLISION\r\n\r\nclass CCollObj;\r\nclass CollData;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CBatchTriColl\r\n{\r\npublic:\r\n\tMth::Line\t\t\t\t\tm_test_line;\r\n\tMth::Vector\t\t\t\t\tm_test_line_dir;\r\n\tCCollObj *\t\t\t\t\tmp_collision_obj;\r\n\tfloat\t\t\t\t\t\tm_distance;\r\n\tFaceIndex\t\t\t\t\tm_face_index;\r\n\r\n\tstatic CollData *\t\t\tsp_coll_data;\t\t\t// We should only have one at a time\r\n};\r\n\r\n// Results from collision\r\nstruct SCollOutput\r\n{\r\n\tfloat distance;\r\n\tint pad1;\r\n\tint pad2;\r\n\tint index;\r\n};\r\n\r\nclass CBatchTriCollMan\r\n{\r\npublic:\r\n\tstatic bool\t\t\t\t\tsInit(CollData *p_coll_data);\r\n\tstatic void\t\t\t\t\tsFinish();\r\n\r\n\tstatic void\t\t\t\t\tsAddTriCollision(const Mth::Line &test_line, const Mth::Vector &test_line_dir,\r\n\t\t\t\t\t\t\t\t\t\t\t\t CCollObj *p_collision_obj, FaceIndex face_index);\r\n\tstatic bool\t\t\t\t\tsRemoveTriCollision(CBatchTriColl *p_tri_collsion);\r\n\r\n\tstatic void\t\t\t\t\tsStartNewTriCollisions();\r\n\tstatic volatile bool\t\tsIsTriCollisionDone();\r\n\tstatic volatile bool\t\tsIsNested();\r\n\tstatic bool\t\t\t\t\tsWaitTriCollisions();\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tstatic bool\t\t\t\t\tsUseVU0Micro();\r\n\tstatic void\t\t\t\t\tsDisableVU0Micro();\r\n#endif\r\n\r\nprotected:\r\n\tenum\r\n\t{\r\n\t\tMAX_BATCH_COLLISIONS = 40,\r\n\t};\r\n\r\n\t// Collision callback\r\n\tstatic int\t\t\t\t\ts_collision_done(int);\r\n\tstatic void\t\t\t\t\ts_process_results();\r\n\r\n\tstatic void\t\t\t\t\ts_switch_buffers();\r\n\r\n\tstatic volatile bool\t\ts_processing;\r\n\tstatic volatile bool\t\ts_result_processing;\r\n\tstatic volatile int\t\t\ts_nested;\t\t\t\t// Indicates nesting level, so normal collision must be used\r\n\tstatic volatile bool\t\ts_found_collision;\r\n\r\n\tstatic CBatchTriColl\t\ts_tri_collision_array[MAX_BATCH_COLLISIONS][2];\t\t// Double buffered\r\n\tstatic int\t\t\t\t\ts_current_array;\r\n\tstatic int\t\t\t\t\ts_array_size;\r\n\tstatic int\t\t\t\t\ts_next_idx_to_batch;\r\n\r\n\tstatic int\t\t\t\t\ts_num_collisions;\r\n\tstatic SCollOutput\t\t\ts_collision_results[MAX_BATCH_COLLISIONS];\r\n\r\nprivate:\r\n#ifdef __PLAT_NGPS__\r\n\tstatic int \t\t\t\t\ts_collision_handler_id;// for interrupt callback\r\n\tstatic bool\t\t\t\t\ts_use_vu0_micro;\r\n#endif\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline volatile bool\t\t\tCBatchTriCollMan::sIsTriCollisionDone()\r\n{\r\n\treturn !s_processing;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline volatile bool\t\t\tCBatchTriCollMan::sIsNested()\r\n{\r\n\treturn s_nested > 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\t\tCBatchTriCollMan::s_switch_buffers()\r\n{\r\n\ts_array_size = 0;\r\n\ts_next_idx_to_batch = 0;\r\n\ts_current_array = s_current_array ^ 1;\r\n}\r\n\r\n#endif // BATCH_TRI_COLLISION\r\n\r\n} // namespace Nx\r\n\r\n#endif\t//\t__GEL_BATCHTRICOLL_H\r\n"
  },
  {
    "path": "Code/Gel/Collision/CollCache.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNx\t\t\t\t\t\t\t\t \t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel\\collision\\collcache.cpp   \t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t08/16/02\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gel/collision/collision.h>\r\n#include <gel/collision/movcollman.h>\r\n#include <gel/collision/collcache.h>\r\n#include <engine/SuperSector.h>\r\n\r\n#include <gfx/nx.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#define PRINT_TIMES 0\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCCollCache::CCollCache()\r\n{\r\n\tClear();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCCollCache::~CCollCache()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollCache::Clear()\r\n{\r\n\tm_bbox.Reset();\r\n\r\n\tm_array_size = 0;\r\n\tm_num_static_coll = 0;\r\n\tm_num_movable_coll = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollCache::Update(const Mth::CBBox &bbox)\r\n{\r\n#if PRINT_TIMES\r\n\tstatic uint64 s_total_time = 0, s_num_collisions = 0;\r\n\tuint64 start_time = Tmr::GetTimeInUSeconds();\r\n#endif\r\n\r\n\t// Clear old cache first\r\n\tClear();\r\n\r\n\t// Make line\r\n\tMth::Line is(bbox.GetMin(), bbox.GetMax());\r\n\r\n\t// initialize starting \"max\" distance to be max collision distance\r\n\tSSec::Manager *ss_man;\r\n\tss_man = Nx::CEngine::sGetNearestSuperSectorManager(is);\r\n//\tDbg_Assert(ss_man);\r\n   \tif (!ss_man)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n \r\n\t// Copy bounding box\r\n\tm_bbox = bbox;\r\n\r\n\r\n\r\n\tCCollStatic** p_coll_obj_list = ss_man->GetIntersectingCollSectors( is );\r\n\t\r\n\t// Bloat the collision line only for the purposes of deciding against which world \r\n\t// sectors to test the actual collision line\r\n\tMth::CBBox line_bbox;\r\n\tMth::Vector extend;\r\n\r\n\textend = bbox.GetMax();\r\n\textend[X] += CCollObj::sLINE_BOX_EXTENT;\r\n\textend[Y] += CCollObj::sLINE_BOX_EXTENT;\r\n\textend[Z] += CCollObj::sLINE_BOX_EXTENT;\r\n\tline_bbox.AddPoint(extend);\r\n\r\n\textend = bbox.GetMin();\r\n\textend[X] -= CCollObj::sLINE_BOX_EXTENT;\r\n\textend[Y] -= CCollObj::sLINE_BOX_EXTENT;\r\n\textend[Z] -= CCollObj::sLINE_BOX_EXTENT;\r\n\tline_bbox.AddPoint(extend);\r\n\r\n\t// Look for static collision\r\n    CCollStatic* p_coll_obj;\r\n\twhile((p_coll_obj = *p_coll_obj_list))\r\n\t{\r\n\t\t// TODO: Come up with a cleaner BBox check\r\n\t\t//Dbg_Assert(p_coll_obj->GetGeometry());\r\n\t\t//if(line_bbox.Intersect(p_coll_obj->GetGeometry()->GetBBox()))\r\n\t\tif (p_coll_obj->WithinBBox(line_bbox))\r\n\t\t{\r\n\t\t\tadd_static_collision(p_coll_obj);\r\n\t\t}\r\n\t\tp_coll_obj_list++;\r\n\t}\r\n\r\n\t// Now look for movable collision\r\n\tLst::Node< CCollObj > *p_movable_node = CMovableCollMan::sGetCollisionList()->GetNext();\r\n\twhile(p_movable_node)\r\n\t{\r\n\t\tCCollObj *p_coll_obj = p_movable_node->GetData();\r\n\t\tif (p_coll_obj && !(p_coll_obj->m_Flags & (mSD_NON_COLLIDABLE | mSD_KILLED )))\r\n\t\t{\r\n\t\t\tif (p_coll_obj->WithinBBox(line_bbox))\r\n\t\t\t{\r\n\t\t\t\tadd_movable_collision(p_coll_obj);\r\n\t\t\t}\r\n\t\t}\r\n\t\tp_movable_node = p_movable_node->GetNext();\r\n\t}\r\n\r\n#if PRINT_TIMES\r\n\tuint64 end_time = Tmr::GetTimeInUSeconds();\r\n\ts_total_time += end_time - start_time;\r\n\r\n\tif (++s_num_collisions >= 1000)\r\n\t{\r\n\t\tDbg_Message(\"Cache Update time %d us\", s_total_time);\r\n\t\ts_total_time = s_num_collisions = 0;\r\n\t}\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollCache::add_static_collision(CCollStatic *p_collision)\r\n{\r\n\tDbg_Assert(p_collision);\r\n\tDbg_MsgAssert(m_num_movable_coll == 0, (\"Can't add static collision to cache after movable collision\"));\r\n\tDbg_MsgAssert(m_array_size < MAX_COLLISION_OBJECTS, (\"Collision cache full.\"));\r\n\r\n\tm_collision_array[m_array_size].mp_bbox = &(p_collision->GetGeometry()->GetBBox());\r\n\tDbg_MsgAssert(m_collision_array[m_array_size].mp_bbox, (\"No bounding box found for the static collision\"));\r\n\r\n\tm_collision_array[m_array_size++].mp_coll_obj = p_collision;\r\n\t\r\n\tm_num_static_coll++;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollCache::add_movable_collision(CCollObj *p_collision)\r\n{\r\n\tDbg_Assert(p_collision);\r\n\tDbg_MsgAssert(m_array_size < MAX_COLLISION_OBJECTS, (\"Collision cache full.\"));\r\n\r\n\tm_collision_array[m_array_size].mp_bbox = p_collision->get_bbox();\r\n\t//Dbg_MsgAssert(m_collision_array[m_array_size].mp_bbox, (\"No bounding box found for the movable collision\"));\r\n\r\n\tm_collision_array[m_array_size++].mp_coll_obj = p_collision;\r\n\r\n\tm_num_movable_coll++;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollCache::delete_static_collision(CCollStatic *p_collision)\r\n{\r\n\tfor (int i = 0; i < m_num_static_coll; i++)\r\n\t{\r\n\t\tif (m_collision_array[i].mp_coll_obj == p_collision)\r\n\t\t{\r\n\t\t\t// Must copy the whole block down\r\n\t\t\tfor (int j = i + 1; j < m_array_size; j++)\r\n\t\t\t{\r\n\t\t\t\tm_collision_array[j - 1] = m_collision_array[j];\r\n\t\t\t}\r\n\t\t\tm_num_static_coll--;\r\n\t\t\tm_array_size--;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollCache::delete_movable_collision(CCollObj *p_collision)\r\n{\r\n\tfor (int i = m_num_static_coll; i < m_array_size; i++)\r\n\t{\r\n\t\tif (m_collision_array[i].mp_coll_obj == p_collision)\r\n\t\t{\r\n\t\t\tm_collision_array[i] = m_collision_array[--m_array_size];\r\n\t\t\tm_num_movable_coll--;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollCache::delete_collision(CCollObj *p_collision)\r\n{\r\n\tdelete_static_collision(static_cast<CCollStatic *>(p_collision));\r\n\tdelete_movable_collision(p_collision);\r\n}\r\n\r\n////////////////////////////////////\r\n\r\nCCollCache *\tCCollCacheManager::sp_coll_cache_array[MAX_COLLISION_CACHES];\r\nint\t\t\t\tCCollCacheManager::s_num_coll_caches = 0;\r\n\r\nbool\t\t\tCCollCacheManager::s_assert_on_cache_miss;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollCache *\tCCollCacheManager::sCreateCollCache()\r\n{\r\n\tDbg_MsgAssert(s_num_coll_caches < MAX_COLLISION_CACHES, (\"Too many collision caches\"));\r\n\tsp_coll_cache_array[s_num_coll_caches] = new CCollCache;\r\n\r\n\treturn sp_coll_cache_array[s_num_coll_caches++];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCCollCacheManager::sDestroyCollCache(CCollCache *p_cache)\r\n{\r\n\tbool found = false;\r\n\r\n\t// Take entry out of array\r\n\tfor (int i = 0; i < s_num_coll_caches; i++)\r\n\t{\r\n\t\tif (sp_coll_cache_array[i] == p_cache)\r\n\t\t{\r\n\t\t\t// Move last in array to here\r\n\t\t\tsp_coll_cache_array[i] = sp_coll_cache_array[--s_num_coll_caches];\r\n\r\n\t\t\tfound = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// And do the actual deletion\r\n\tdelete p_cache;\r\n\r\n\tDbg_Assert(found);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCCollCacheManager::sDeleteMovableCollision(CCollObj *p_collision)\r\n{\r\n\t// Check each cache\r\n\tfor (int i = 0; i < s_num_coll_caches; i++)\r\n\t{\r\n\t\tsp_coll_cache_array[i]->delete_movable_collision(p_collision);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCCollCacheManager::sDeleteCollision(CCollObj *p_collision)\r\n{\r\n\t// Check each cache\r\n\tfor (int i = 0; i < s_num_coll_caches; i++)\r\n\t{\r\n\t\tsp_coll_cache_array[i]->delete_collision(p_collision);\r\n\t}\r\n}\r\n\r\n} // namespace Nx\r\n\r\n"
  },
  {
    "path": "Code/Gel/Collision/CollCache.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNx\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCollCache.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t08/16/2002\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__GEL_COLLCACHE_H\r\n#define\t__GEL_COLLCACHE_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\nclass CCollObj;\r\nclass CCollStatic;\r\nclass CCollObjTriData;\r\nclass CCollCacheManager;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\nstruct SCollCacheNode\r\n{\r\n\tCCollObj\t\t\t*mp_coll_obj;\t\t// Collision object\r\n\tconst Mth::CBBox\t*mp_bbox;\t\t\t// Current bounding box\r\n};\r\n\r\n////////////////////////////////////\r\n\r\nclass CCollCache\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCCollCache();\r\n\t\t\t\t\t\t\t~CCollCache();\r\n\r\n\tvoid\t\t\t\t\tClear();\r\n\r\n\t// WARNING: The Update() function takes just as long as a normal collision call.  Make sure you\r\n\t// plan on using the cache multiple times.\r\n\tvoid\t\t\t\t\tUpdate(const Mth::CBBox &bbox);\r\n\r\n\t// Checks to see if this cache can be used\r\n\tbool\t\t\t\t\tContains(const Mth::CBBox &test_bbox) const;\r\n\tbool\t\t\t\t\tContains(const Mth::Line &test_line) const;\r\n\r\n\tconst SCollCacheNode *\tGetCollisionArray() const;\r\n\tint\t\t\t\t\t\tGetNumCollisions() const;\r\n\tconst SCollCacheNode *\tGetStaticCollisionArray() const;\r\n\tint\t\t\t\t\t\tGetNumStaticCollisions() const;\r\n\tconst SCollCacheNode *\tGetMovableCollisionArray() const;\r\n\tint\t\t\t\t\t\tGetNumMovableCollisions() const;\r\n\r\nprotected:\r\n\tenum\r\n\t{\r\n\t\tMAX_COLLISION_OBJECTS = 500,\r\n\t};\r\n\r\n\tvoid\t\t\t\t\tadd_static_collision(CCollStatic *p_collision);\r\n\tvoid\t\t\t\t\tadd_movable_collision(CCollObj *p_collision);\r\n\tvoid\t\t\t\t\tdelete_static_collision(CCollStatic *p_collision);\r\n\tvoid\t\t\t\t\tdelete_movable_collision(CCollObj *p_collision);\r\n\tvoid\t\t\t\t\tdelete_collision(CCollObj *p_collision);\t\t\t// In case we don't know what type (less efficient)\r\n\r\n\tMth::CBBox\t\t\t\tm_bbox;\t\t\t\t// bounding box where cache is valid\r\n\tSCollCacheNode\t\t\tm_collision_array[MAX_COLLISION_OBJECTS];\r\n\tint\t\t\t\t\t\tm_array_size;\r\n\tint\t\t\t\t\t\tm_num_static_coll;\r\n\tint\t\t\t\t\t\tm_num_movable_coll;\r\n\r\n\t// Friends\r\n\tfriend CCollCacheManager;\r\n};\r\n\r\n////////////////////////////////////\r\n\r\nclass CCollCacheManager\r\n{\r\npublic:\r\n\r\n\t// Allocation functions\r\n\tstatic CCollCache *\t\tsCreateCollCache();\r\n\tstatic void\t\t\t\tsDestroyCollCache(CCollCache *p_cache);\r\n\r\n\t// Collision deletion functions\r\n\tstatic void\t\t\t\tsDeleteStaticCollision(CCollStatic *p_collision);\r\n\tstatic void\t\t\t\tsDeleteMovableCollision(CCollObj *p_collision);\r\n\tstatic void\t\t\t\tsDeleteCollision(CCollObj *p_collision);\t\t\t// In case we don't know what type (less efficient)\r\n\t\r\n\tstatic void\t\t\t\tsSetAssertOnCacheMiss ( bool state ) { s_assert_on_cache_miss = state; }\r\n\tstatic bool\t\t\t\tsGetAssertOnCacheMiss (   ) { return s_assert_on_cache_miss; }\r\n\r\nprotected:\r\n\tenum\r\n\t{\r\n\t\tMAX_COLLISION_CACHES = 8,\r\n\t};\r\n\t\r\n\tstatic CCollCache *\t\tsp_coll_cache_array[MAX_COLLISION_CACHES];\r\n\tstatic int\t\t\t\ts_num_coll_caches;\r\n\t\r\n\tstatic bool\t\t\t\ts_assert_on_cache_miss;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\t\tCCollCache::Contains(const Mth::CBBox &test_bbox) const\r\n{\r\n\treturn m_bbox.Within(test_bbox);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\t\tCCollCache::Contains(const Mth::Line &test_line) const\r\n{\r\n\treturn (m_bbox.Within(test_line.m_start) && m_bbox.Within(test_line.m_end));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const SCollCacheNode *CCollCache::GetCollisionArray() const\r\n{\r\n\treturn m_collision_array;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline int\t\t\t\t\tCCollCache::GetNumCollisions() const\r\n{\r\n\treturn m_array_size;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const SCollCacheNode *CCollCache::GetStaticCollisionArray() const\r\n{\r\n\treturn m_collision_array;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline int\t\t\t\t\tCCollCache::GetNumStaticCollisions() const\r\n{\r\n\treturn m_num_static_coll;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const SCollCacheNode *CCollCache::GetMovableCollisionArray() const\r\n{\r\n\treturn &(m_collision_array[m_num_static_coll]);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline int\t\t\t\t\tCCollCache::GetNumMovableCollisions() const\r\n{\r\n\treturn m_num_movable_coll;\r\n}\r\n\r\n} // namespace Nx\r\n\r\n#endif\t//\t__GEL_COLLCACHE_H\r\n"
  },
  {
    "path": "Code/Gel/Collision/CollEnums.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNx\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCollEnums.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t02/27/2002\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__GEL_COLLENUMS_H\r\n#define\t__GEL_COLLENUMS_H\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n////////////////////////////////////////////////////////////////\r\n// Types of collision\r\nenum CollType\r\n{\r\n\tvCOLL_TYPE_NONE = 0,\r\n\tvCOLL_TYPE_BBOX,\r\n\tvCOLL_TYPE_SPHERE,\r\n\tvCOLL_TYPE_CYLINDRICAL,\r\n\tvCOLL_TYPE_GEOM,\r\n};\r\n\r\n// Typedefs\r\ntypedef uint16 FaceIndex;\r\ntypedef uint8  FaceByteIndex;\r\n\r\n} // namespace Nx\r\n\r\n#endif  //\t__GEL_COLLENUMS_H\r\n"
  },
  {
    "path": "Code/Gel/Collision/CollTriData.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNx\t\t\t\t\t\t\t\t \t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel\\collision\\collide.cpp      \t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/20/02\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gel/collision/collision.h>\r\n#include <gel/collision/colltridata.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/nxflags.h>\t// for face flag stuff\r\n#include <gfx/debuggfx.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n\r\n\r\n// For debugging rendering\r\n#include <gfx/nxviewman.h>\r\n#include <gfx/camera.h>\r\n\r\n#ifdef\t__PLAT_NGPS__\t\r\n#include <gfx/ngps/nx/line.h>\r\n#include <gfx/ngps/p_nxsector.h>\r\n#include <gfx/ngps/nx/geomnode.h>\r\n#include <gfx/ngps/nx/render.h>\r\nnamespace\tNxPs2\r\n{\r\n\tbool TestSphereAgainstOccluders( Mth::Vector *p_center, float radius, uint32 meshes = 1 );\r\n\tbool\tIsInFrame(Mth::Vector &center, float radius);\r\n}\r\n\r\n#endif\r\n\r\n#ifdef\t__PLAT_NGC__\r\n#include <gfx/ngc/nx/scene.h>\r\n#include <gfx/ngc/p_nxscene.h>\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\nFaceIndex\tCCollObjTriData::s_face_index_buffer[MAX_FACE_INDICIES];\r\nFaceIndex\tCCollObjTriData::s_seq_face_index_buffer[MAX_FACE_INDICIES] = { 0xFFFF }; // Set to uninitialized\r\nuint\t\tCCollObjTriData::s_num_face_indicies;\r\n\r\nconst uint\tCCollObjTriData::s_max_face_per_leaf = 20;\t\t// maximum number faces per leaf\r\nconst uint\tCCollObjTriData::s_max_tree_levels = 7;\t\t\t// maximum number of levels in a tree\r\n\r\n#define USE_BSP_CLONE\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollObjTriData::CCollObjTriData()\r\n{\r\n#ifdef __PLAT_NGC__\r\n\tmp_cloned_vert_pos = NULL;\r\n#endif\t\t// __PLAT_NGC__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollObjTriData::~CCollObjTriData()\r\n{\r\n\t// Clones are the only types that should make it here\r\n\t// Remove vertices\r\n#ifdef __PLAT_NGC__\r\n\tif ( mp_cloned_vert_pos )\r\n\t{\r\n\t\tdelete [] mp_cloned_vert_pos;\r\n\t}\r\n#else\r\n#ifdef FIXED_POINT_VERTICES\r\n\tif (mp_float_vert)\r\n\t{\r\n\t\tdelete [] mp_float_vert;\r\n\t}\r\n#else\r\n\tif (mp_vert_pos)\r\n\t{\r\n\t\tdelete[] mp_vert_pos;\r\n\t}\r\n#endif // FIXED_POINT_VERTICES\r\n#endif\t\t// __PLAT_NGC__\r\n\tif (mp_intensity)\r\n\t{\r\n\t\tdelete[] mp_intensity;\r\n\t}\r\n\r\n\t// Remove faces\r\n\tif (mp_faces)\r\n\t{\r\n\t\tif (m_use_face_small)\r\n\t\t{\r\n\t\t\tdelete[] mp_face_small;\r\n\t\t} else{\r\n\t\t\tdelete[] mp_faces;\r\n\t\t}\r\n\t}\r\n\r\n\tDeleteBSPTree();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCollObjTriData::InitCollObjTriData(CScene * p_scene, void *p_base_vert_addr, void *p_base_intensity_addr,\r\n\t\t\t\t\t\t\t\t\t\t\tvoid *p_base_face_addr, void *p_base_node_addr, void *p_base_face_idx_addr)\r\n{\r\n\t// Set base addr\r\n#ifdef __PLAT_NGC__\r\n\tNxNgc::sScene *p_engine_scene = ( static_cast<CNgcScene*>( p_scene ))->GetEngineScene();\r\n\tmp_raw_vert_pos = (NsVector*)p_engine_scene->mp_pos_pool;\r\n\tmp_intensity = (unsigned char *) ((int) p_base_vert_addr + (int)mp_intensity); \r\n\tmp_cloned_vert_pos = NULL;\r\n#else\r\n#ifdef FIXED_POINT_VERTICES\r\n\t// Get indexes\r\n\tint start_vert_pos_offset = (int) mp_float_vert;\r\n\tint start_intensity_index = (int) mp_intensity;\r\n\r\n\t// Find first element\r\n\tmp_float_vert = (SFloatVert *) ((int) p_base_vert_addr + start_vert_pos_offset);\r\n\tmp_intensity = (uint8 *) p_base_intensity_addr;\r\n\tmp_intensity += start_intensity_index;\r\n#else\r\n\t// Get indexes\r\n\tint start_vert_pos_offset = (int) mp_vert_pos;\r\n\r\n\t// Find first element\r\n\tmp_vert_pos = (Mth::Vector *) ((int) p_base_vert_addr + start_vert_pos_offset);\r\n\r\n\tmp_intensity = NULL;\r\n#endif // FIXED_POINT_VERTICES\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\tmp_faces = (SFace *)((int) mp_faces + (int) p_base_face_addr);\r\n\r\n\t//Dbg_Message ( \"Object has %d verts sizeof %d\", m_num_verts, sizeof(SReadVertex));\r\n\t//Dbg_Message ( \"Object has %d faces sizeof %d\", m_num_faces, sizeof(SReadFace) );\r\n#ifndef FIXED_POINT_VERTICES\r\n\tDbg_Assert(!m_use_fixed_verts)\r\n#endif\r\n\r\n\t// Init BSP tree\r\n\tmp_bsp_tree = (CCollBSPNode *)((int) mp_bsp_tree + (int) p_base_node_addr);\r\n\ts_init_tree(mp_bsp_tree, p_base_node_addr, p_base_face_idx_addr);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollBSPNode::CCollBSPNode()\r\n{\r\n\t//m_node.m_split_axis = 0;\r\n\tm_node.m_split_point = 0; \t\t// This is so we know it is a node\r\n\tm_node.m_children.Init();\r\n\t//mp_greater_branch = NULL;\r\n}\r\n\r\nCCollBSPNode::~CCollBSPNode()\r\n{\r\n#ifdef USE_BSP_CLONE\r\n\t// Since the cloned BSP tree is allocated as one big buffer, these calls shouldn't\r\n\t// be necessary.\r\n\treturn;\r\n\r\n#else\r\n\tDbg_MsgAssert(IsNode(), (\"Called ~CCollBSPNode() on CCollBSPLeaf()\"));\r\n\r\n\tDbg_MsgAssert(0, (\"Only cloned collision should get to the BSP destructor\"));\r\n#endif // USE_BSP_CLONE\r\n\r\n\tif (GetLessBranch())\r\n\t{\r\n\t\tdelete GetLessBranch();\r\n\t}\r\n\r\n\tif (GetGreaterBranch())\r\n\t{\r\n\t\tdelete GetGreaterBranch();\r\n\t}\r\n\r\n\tif (GetFaceIndexArray())\r\n\t{\r\n\t\tdelete GetFaceIndexArray();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCCollBSPNode::SetSplitAxis(int axis)\r\n{\r\n\tDbg_Assert(IsNode());\r\n\t\r\n\tm_node.m_split_point = m_node.m_split_point & ~((1 << NUM_AXIS_BITS) - 1);\t\t// Clear out old axis\r\n\tm_node.m_split_point = m_node.m_split_point | (axis & ((1 << NUM_AXIS_BITS) - 1));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Garrett: This is an unconventional way of cloning the data.  We are assuming that all the\r\n// tree nodes are in one contiguous block of memory.  I normally wouldn't write code like\r\n// this, but we need to avoid lots of small allocations.\r\nCCollBSPNode * CCollBSPNode::clone(bool instance)\r\n{\r\n\tDbg_MsgAssert(!instance, (\"CCollBSPNode::clone() with instances not implemented yet\"));\r\n\t//Dbg_MsgAssert(IsNode(), (\"Called CCollBSPNode::clone() on CCollBSPLeaf()\"));\r\n\r\n\t// So that we don't make lots of little allocations, allocate the whole BSP array at once\r\n\tint num_nodes = count_bsp_nodes();\r\n\tint num_face_indices = count_bsp_face_indices();\r\n\tif (num_nodes > 0)\r\n\t{\r\n\t\tDbg_MsgAssert(num_face_indices, (\"Didn't find any face indices in the BSP tree\"));\r\n\t\tFaceIndex *\t\tp_orig_face_index_array = find_bsp_face_index_array_start();\r\n\r\n\t\tCCollBSPNode *\tp_new_bsp_array = new CCollBSPNode[num_nodes];\r\n\t\tFaceIndex *\t\tp_new_face_index_array = new FaceIndex[num_face_indices];\r\n\r\n\t\t// Just memcpy it first, since we know the source tree is in an array\r\n\t\tmemcpy(p_new_bsp_array, this, num_nodes * sizeof(CCollBSPNode));\r\n\t\tmemcpy(p_new_face_index_array, p_orig_face_index_array, num_face_indices * sizeof(FaceIndex));\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\t\t// Look through new bsp array that still has the old face index pointers in it.\r\n\t\tfor (int node_idx = 0; node_idx < num_nodes; node_idx++)\r\n\t\t{\r\n\t\t\tif (p_new_bsp_array[node_idx].IsLeaf())\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(p_orig_face_index_array <= p_new_bsp_array[node_idx].GetFaceIndexArray(), (\"find_bsp_face_index_array_start() failed\"));\r\n\t\t\t}\r\n\t\t}\r\n#endif //\t__NOPT_ASSERT__\r\n\r\n\t\t// Now adjust the pointers by finding the differences\r\n\t\tint node_address_diff = (int) p_new_bsp_array - (int) this;\r\n\t\tint face_address_diff = (int) p_new_face_index_array - (int) p_orig_face_index_array;\r\n\t\tfor (int i = 0; i < num_nodes; i++)\r\n\t\t{\r\n\t\t\tif (p_new_bsp_array[i].IsNode())\r\n\t\t\t{\r\n\t\t\t\t// Adjust branch pointers\r\n\t\t\t\tp_new_bsp_array[i].m_node.m_children.SetBasePointer((CCollBSPNode *)((int) p_new_bsp_array[i].m_node.m_children.GetBasePointer() + node_address_diff));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Adjust face index pointer\r\n\t\t\t\tp_new_bsp_array[i].m_leaf.mp_face_idx_array = (FaceIndex *) ((int) p_new_bsp_array[i].m_leaf.mp_face_idx_array + face_address_diff);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn p_new_bsp_array;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\tCCollBSPNode::count_bsp_nodes()\r\n{\r\n\tif (IsLeaf())\r\n\t{\r\n\t\treturn 1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 1 + GetLessBranch()->count_bsp_nodes() + GetGreaterBranch()->count_bsp_nodes();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\tCCollBSPNode::count_bsp_face_indices()\r\n{\r\n\tif (IsLeaf())\r\n\t{\r\n\t\treturn m_leaf.m_num_faces;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn GetLessBranch()->count_bsp_face_indices() + GetGreaterBranch()->count_bsp_face_indices();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nFaceIndex *\t\tCCollBSPNode::find_bsp_face_index_array_start()\r\n{\r\n\tif (IsLeaf())\r\n\t{\r\n\t\treturn m_leaf.mp_face_idx_array;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tFaceIndex *p_index1 = GetLessBranch()->find_bsp_face_index_array_start();\r\n\t\tFaceIndex *p_index2 = GetGreaterBranch()->find_bsp_face_index_array_start();\r\n\r\n\t\tif (p_index1 < p_index2)\r\n\t\t\treturn p_index1;\r\n\t\telse\r\n\t\t\treturn p_index2;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCCollBSPNode::CCollBSPChildren::SetLeftGreater(bool greater)\r\n{\r\n\t if (greater)\r\n\t {\r\n\t\t m_left_child_and_flags |= mLEFT_IS_GREATER;\r\n\t }\r\n\t else\r\n\t {\r\n\t\t m_left_child_and_flags &= ~mLEFT_IS_GREATER;\r\n\t }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCCollBSPNode::translate(const Mth::Vector & delta_trans)\r\n{\r\n\t// Translate node\r\n\tif (IsNode())\r\n\t{\r\n\t\tint axis = GetSplitAxis();\r\n\r\n\t\tSetFSplitPoint(GetFSplitPoint() + delta_trans[axis]);\r\n\r\n\t\t// Traverse the tree\r\n\t\tGetLessBranch()->translate(delta_trans);\r\n\t\tGetGreaterBranch()->translate(delta_trans);\r\n\t}\r\n\r\n\t// Leaf does nothing\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCCollBSPNode::rotate_y(const Mth::Vector & world_origin, Mth::ERot90 rot_y, bool root_node)\r\n{\r\n\t// Take it to the origin\r\n\tif (root_node)\r\n\t{\r\n\t\ttranslate(-world_origin);\r\n\t}\r\n\r\n\t// Rotate node\r\n\tif (IsNode())\r\n\t{\r\n\t\tint axis = GetSplitAxis();\r\n\r\n\t\tif (axis != Y)\t\t// Y won't change\r\n\t\t{\r\n\t\t\tint other_axis = (axis == X) ? Z : X;\t\t// So we know what axis we potentially flip to\r\n\r\n\t\t\tswitch (rot_y)\r\n\t\t\t{\r\n\t\t\tcase Mth::ROT_0:\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase Mth::ROT_90:\r\n\t\t\t\tif (axis == X)\r\n\t\t\t\t{\r\n\t\t\t\t\tSetSplitPoint(-GetSplitPoint());\r\n\t\t\t\t\tm_node.m_children.SetLeftGreater(!m_node.m_children.IsLeftGreater());\r\n\t\t\t\t}\r\n\t\t\t\tSetSplitAxis(other_axis);\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase Mth::ROT_180:\r\n\t\t\t\tSetSplitPoint(-GetSplitPoint());\r\n\t\t\t\tm_node.m_children.SetLeftGreater(!m_node.m_children.IsLeftGreater());\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase Mth::ROT_270:\r\n\t\t\t\tif (axis == Z)\r\n\t\t\t\t{\r\n\t\t\t\t\tSetSplitPoint(-GetSplitPoint());\r\n\t\t\t\t\tm_node.m_children.SetLeftGreater(!m_node.m_children.IsLeftGreater());\r\n\t\t\t\t}\r\n\t\t\t\tSetSplitAxis(other_axis);\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(0, (\"CCollBSPNode::rotate_y() out of range: %d\", rot_y));\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Traverse the tree\r\n\t\tGetLessBranch()->rotate_y(world_origin, rot_y, false);\r\n\t\tGetGreaterBranch()->rotate_y(world_origin, rot_y, false);\r\n\t}\r\n\t// Leaf does nothing\r\n\r\n\t// Put it back\r\n\tif (root_node)\r\n\t{\r\n\t\ttranslate(world_origin);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCCollBSPNode::scale(const Mth::Vector & world_origin, const Mth::Vector & scale, bool root_node)\r\n{\r\n\t// Take it to the origin\r\n\tif (root_node)\r\n\t{\r\n\t\ttranslate(-world_origin);\r\n\t}\r\n\r\n\t// Scale node\r\n\tif (IsNode())\r\n\t{\r\n\t\tint axis = GetSplitAxis();\r\n\r\n\t\tSetFSplitPoint(GetFSplitPoint() * scale[axis]);\r\n\r\n\t\t// Traverse the tree\r\n\t\tGetLessBranch()->scale(world_origin, scale, false);\r\n\t\tGetGreaterBranch()->scale(world_origin, scale, false);\r\n\t}\r\n\t// Leaf does nothing\r\n\r\n\t// Put it back\r\n\tif (root_node)\r\n\t{\r\n\t\ttranslate(world_origin);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCollObjTriData::s_init_tree(CCollBSPNode *p_tree, void *p_base_node_addr, void *p_base_face_idx_addr)\r\n{\r\n\tif (p_tree->IsLeaf())\r\n\t{\r\n\t\t// Set face index array pointer\r\n\t\tint face_idx = (int) p_tree->m_leaf.mp_face_idx_array;\r\n\t\tp_tree->m_leaf.mp_face_idx_array = (FaceIndex *) p_base_face_idx_addr;\r\n\t\tp_tree->m_leaf.mp_face_idx_array += face_idx;\r\n\r\n\t\t//Dbg_Assert(((int) p_leaf->mp_less_branch) == -1);\r\n\t\t//Dbg_Assert(((int) p_leaf->mp_greater_branch) == -1);\r\n\r\n\t\t//p_leaf->mp_less_branch = NULL;\r\n\t\t//p_leaf->mp_greater_branch = NULL;\r\n\t} else {\r\n\t\tDbg_MsgAssert(p_tree->GetSplitAxis() < 3, (\"BSP split axis is %d\", p_tree->GetSplitAxis()));\r\n\t\t// Set branch pointers\r\n\t\tp_tree->m_node.m_children.SetBasePointer((CCollBSPNode *)((int) p_tree->m_node.m_children.GetBasePointer() + (int) p_base_node_addr));\r\n\r\n\t\t// And init branches\r\n\t\ts_init_tree(p_tree->GetLessBranch(), p_base_node_addr, p_base_face_idx_addr);\r\n\t\ts_init_tree(p_tree->GetGreaterBranch(), p_base_node_addr, p_base_face_idx_addr);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCollObjTriData::InitBSPTree()\r\n{\r\n\t// Initialize sequence face index list, if not done yet\r\n\tif (s_seq_face_index_buffer[0] != 0)\r\n\t{\r\n\t\tfor (int i = 0; i < MAX_FACE_INDICIES; i++)\r\n\t\t{\r\n\t\t\ts_seq_face_index_buffer[i] = i;\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert(m_num_faces < MAX_FACE_INDICIES, (\"Too many polys in a collision sector: %d\", m_num_faces));\r\n\r\n\t//Dbg_MsgAssert(0, (\"Node size %d; Leaf size %d\", sizeof(CCollBSPNode), sizeof(CCollBSPLeaf)));\r\n\r\n\t// Create the tree\r\n   \t// Don't use this since it is pip-ed\r\n\t//mp_bsp_tree = create_bsp_tree(m_bbox, s_seq_face_index_buffer, m_num_faces);\r\n\r\n\treturn mp_bsp_tree != NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCollObjTriData::DeleteBSPTree()\r\n{\r\n#ifndef USE_BSP_CLONE\r\n   \t// Don't use this since it is pip-ed\r\n\treturn false;\r\n\r\n\tDbg_MsgAssert(0, (\"This should only be called on clones\"));\r\n#endif\r\n\r\n\tif (mp_bsp_tree)\r\n\t{\r\n#ifndef USE_BSP_CLONE\r\n\t\t// Recursively delete\r\n\t\tdelete mp_bsp_tree;\r\n#else\r\n\t\t// Delete as array\r\n\t\tFaceIndex *p_face_index_array = mp_bsp_tree->find_bsp_face_index_array_start();\r\n\t\tif (p_face_index_array)\r\n\t\t{\r\n\t\t\tdelete [] p_face_index_array;\r\n\t\t}\r\n\t\tdelete [] mp_bsp_tree;\r\n#endif\r\n\t\tmp_bsp_tree = NULL;\r\n\r\n\t\treturn true;\r\n\t} else {\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCollObjTriData::calc_split_faces(uint axis, float axis_distance, FaceIndex *p_face_indexes,\r\n\t\t\t\t\t\t\t\t\t\t  uint num_faces, uint & less_faces, uint & greater_faces,\r\n\t\t\t\t\t\t\t\t\t\t  FaceIndex *p_less_face_indexes, FaceIndex *p_greater_face_indexes)\r\n{\r\n\tless_faces = greater_faces = 0;\r\n\r\n\tfor (uint i = 0; i < num_faces; i++)\r\n\t{\r\n\t\tbool less = false, greater = false;\r\n\r\n\t\t// Check the face\r\n\t\tfor (uint j = 0; j < 3; j++)\r\n\t\t{\r\n\t\t\tuint vidx = GetFaceVertIndex(i, j);\r\n#if defined(FIXED_POINT_VERTICES) || defined(__PLAT_NGC__)\r\n\t\t\tif (GetRawVertexPos(vidx)[axis] < axis_distance)\r\n\t\t\t{\r\n\t\t\t\tless = true;\r\n\t\t\t} else if (GetRawVertexPos(vidx)[axis] >= axis_distance)\r\n\t\t\t{\r\n\t\t\t\tgreater = true;\r\n\t\t\t}\r\n#else\r\n\t\t\tif (mp_vert_pos[vidx][axis] < axis_distance)\r\n\t\t\t{\r\n\t\t\t\tless = true;\r\n\t\t\t} else if (mp_vert_pos[vidx][axis] >= axis_distance)\r\n\t\t\t{\r\n\t\t\t\tgreater = true;\r\n\t\t\t}\r\n#endif\r\n\t\t}\r\n\r\n\t\tDbg_Assert(less || greater);\r\n\r\n\t\t// Increment counts and possibly put in new array\r\n\t\tif (less)\r\n\t\t{\r\n\t\t\tif (p_less_face_indexes)\r\n\t\t\t{\r\n\t\t\t\tp_less_face_indexes[less_faces] = p_face_indexes[i];\r\n\t\t\t}\r\n\t\t\tless_faces++;\r\n\t\t}\r\n\t\tif (greater)\r\n\t\t{\r\n\t\t\tif (p_greater_face_indexes)\r\n\t\t\t{\r\n\t\t\t\tp_greater_face_indexes[greater_faces] = p_face_indexes[i];\r\n\t\t\t}\r\n\t\t\tgreater_faces++;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#if 0\r\nCCollBSPLeaf * CCollObjTriData::create_bsp_leaf(FaceIndex *p_face_indexes, uint num_faces)\r\n{\r\n\tCCollBSPLeaf *p_bsp_leaf = new CCollBSPLeaf;\r\n\tp_bsp_leaf->m_split_axis = -1;\r\n\tp_bsp_leaf->mp_less_branch = NULL;\r\n\tp_bsp_leaf->mp_greater_branch = NULL;\r\n\r\n\t// Make new array in BottomUp memory\r\n\tp_bsp_leaf->m_num_faces = num_faces;\r\n\tp_bsp_leaf->mp_face_idx_array = new FaceIndex[num_faces];\r\n\tfor (uint i = 0; i < num_faces; i++)\r\n\t{\r\n\t\tp_bsp_leaf->mp_face_idx_array[i] = p_face_indexes[i];\r\n\t}\r\n\r\n\treturn p_bsp_leaf;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollBSPNode * CCollObjTriData::create_bsp_tree(const Mth::CBBox & bbox, FaceIndex *p_face_indexes, uint num_faces, uint level)\r\n{\r\n\tif ((num_faces <= s_max_face_per_leaf) || (level == s_max_tree_levels)) // Check if this should be a leaf\r\n\t{\r\n\t\treturn create_bsp_leaf(p_face_indexes, num_faces);\r\n\t} else {\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Create Node\r\n\r\n\t\t// Find initial splits on the three axis\r\n\t\tMth::Vector mid_width((bbox.GetMax() - bbox.GetMin()) * 0.5f);\r\n\t\tMth::Vector mid_split(mid_width + bbox.GetMin());\r\n\r\n\t\t// Find the weighting of the three potential splits\r\n\t\tuint less_faces[3], greater_faces[3];\r\n\t\tcalc_split_faces(X, mid_split[X], p_face_indexes, num_faces, less_faces[X], greater_faces[X]);\r\n\t\tcalc_split_faces(Y, mid_split[Y], p_face_indexes, num_faces, less_faces[Y], greater_faces[Y]);\r\n\t\tcalc_split_faces(Z, mid_split[Z], p_face_indexes, num_faces, less_faces[Z], greater_faces[Z]);\r\n\r\n\t\t// Figure out best split\r\n\t\tint best_axis = -1;\r\n\t\tfloat best_diff = -1;\r\n\t\tconst int duplicate_threshold = (num_faces * 7) / 10;\t// tunable\r\n\t\tfor (uint axis = X; axis <= Z; axis++)\r\n\t\t{\r\n\t\t\tfloat new_diff = (float)fabs((float)(less_faces[axis] - greater_faces[axis]));\r\n\t\t\tint duplicates = less_faces[axis] + greater_faces[axis] - num_faces;\r\n\r\n\t\t\tif (duplicates >= duplicate_threshold)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tnew_diff += duplicates;\t\t\t\t// tunable\r\n\t\t\tnew_diff /= mid_width[axis];\t\t// tunable\r\n\r\n\t\t\tif ((best_axis < 0) || (new_diff < best_diff))\r\n\t\t\t{\r\n\t\t\t\tbest_axis = axis;\r\n\t\t\t\tbest_diff = new_diff;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (best_axis < 0)\t\t\t// Couldn't make a good split, give up\r\n\t\t{\r\n\t\t\treturn create_bsp_leaf(p_face_indexes, num_faces);\r\n\t\t}\r\n\r\n\t\t// We need to allocate temp arrays\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n\t\t// Allocate new temp arrays for the face indexes\r\n\t\tFaceIndex *p_less_face_indexes = new FaceIndex[less_faces[best_axis]];\r\n\t\tFaceIndex *p_greater_face_indexes = new FaceIndex[greater_faces[best_axis]];\r\n\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t// Now fill in the array\r\n\t\tcalc_split_faces(best_axis, mid_split[best_axis], p_face_indexes, num_faces, \r\n\t\t\t\t\t\t less_faces[best_axis], greater_faces[best_axis],\r\n\t\t\t\t\t\t p_less_face_indexes, p_greater_face_indexes);\r\n\r\n\t\t// And the new bboxes\r\n\t\tMth::CBBox less_bbox(bbox), greater_bbox(bbox);\r\n\t\tMth::Vector less_max = less_bbox.GetMax();\r\n\t\tMth::Vector greater_min = greater_bbox.GetMin();\r\n\t\tless_max[best_axis] = mid_split[best_axis];\r\n\t\tgreater_min[best_axis] = mid_split[best_axis];\r\n\t\tless_bbox.SetMax(less_max);\r\n\t\tgreater_bbox.SetMin(greater_min);\r\n\t\r\n\t\t// And now calculate the branches\r\n\t\tCCollBSPNode *p_bsp_tree = new CCollBSPNode;\r\n\t\tp_bsp_tree->m_split_axis = best_axis;\r\n\t\tp_bsp_tree->m_split_point = mid_split[best_axis];\r\n\t\tp_bsp_tree->mp_less_branch = create_bsp_tree(less_bbox, p_less_face_indexes, less_faces[best_axis], level + 1);\r\n\t\tp_bsp_tree->mp_greater_branch = create_bsp_tree(greater_bbox, p_greater_face_indexes, greater_faces[best_axis], level + 1);\r\n\r\n\t\t// Free temp arrays\r\n\t\tdelete p_less_face_indexes;\r\n\t\tdelete p_greater_face_indexes;\r\n\r\n\t\treturn p_bsp_tree;\r\n\t}\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCCollObjTriData::find_faces(CCollBSPNode *p_bsp_node, const Mth::CBBox & bbox)\r\n{\r\n\tint axis = p_bsp_node->GetSplitAxis();\r\n\r\n\tif (axis == 3)\t// Leaf\r\n\t{\r\n\t\t//CCollBSPLeaf *p_bsp_leaf = static_cast<CCollBSPLeaf *>(p_bsp_node);\t\t// We are certain that it is this type\r\n\t\tuint num_faces = p_bsp_node->m_leaf.m_num_faces;\r\n\t\tFaceIndex *p_dest_buffer = &(s_face_index_buffer[s_num_face_indicies]);\r\n\t\tFaceIndex *p_src_buffer = p_bsp_node->m_leaf.mp_face_idx_array;\r\n\r\n\t\tfor (uint i = 0; i < num_faces; i++)\r\n\t\t{\r\n\t\t\t//s_face_index_buffer[s_num_face_indicies++] = p_bsp_leaf->mp_face_idx_array[i];\r\n\t\t\t*(p_dest_buffer++) = *(p_src_buffer++);\r\n\t\t}\r\n\r\n\t\ts_num_face_indicies += num_faces;\r\n\t\tDbg_Assert(s_num_face_indicies < MAX_FACE_INDICIES);\r\n\t} else {\t\t\t\t\t\t\t// Node\r\n\t\tfloat f_split_point = p_bsp_node->GetFSplitPoint();\r\n\r\n\t\tif (bbox.GetMin()[axis] < f_split_point)\r\n\t\t{\r\n\t\t\tfind_faces(p_bsp_node->GetLessBranch(), bbox);\r\n\t\t}\r\n\r\n\t\tif (bbox.GetMax()[axis] >= f_split_point)\r\n\t\t{\r\n\t\t\tfind_faces(p_bsp_node->GetGreaterBranch(), bbox);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n// Calculate the normal of a face\r\n// this is rather expensive if doing a lot of processing, so don't call\r\n// this function more than you need to.\r\nconst Mth::Vector CCollObjTriData::GetFaceNormal(int face_idx) const\r\n{\r\n\t\tMth::Vector v0 = GetRawVertexPos(GetFaceVertIndex(face_idx,0));\r\n\t\tMth::Vector v1 = GetRawVertexPos(GetFaceVertIndex(face_idx,1));\r\n\t\tMth::Vector v2 = GetRawVertexPos(GetFaceVertIndex(face_idx,2));\r\n\r\n\t\t// Find normal\r\n\t\tMth::Vector vTmp1(v1 - v0);\r\n\t\tMth::Vector vTmp2(v2 - v0);\r\n\t\tMth::Vector normal = Mth::CrossProduct(vTmp1, vTmp2);\r\n\t\tnormal.Normalize();\r\n\t\treturn normal;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nFaceIndex *\t\t\tCCollObjTriData::FindIntersectingFaces(const Mth::CBBox & line_bbox, uint & num_faces)\r\n{\r\n\t// Make sure we have a tree\r\n\tif (!mp_bsp_tree)\r\n\t{\r\n\t\tnum_faces = m_num_faces;\r\n\t\tDbg_Assert(num_faces < MAX_FACE_INDICIES);\r\n\t\treturn s_seq_face_index_buffer;\r\n\t}\r\n\r\n\t// Search tree\r\n\ts_num_face_indicies = 0;\r\n\tfind_faces(mp_bsp_tree, line_bbox);\r\n\r\n\tnum_faces = s_num_face_indicies;\r\n\r\n\t#if 0\t\r\n\t// see if there are any duplicates....\r\n\tint dups = 0;\r\n\tif (num_faces)\r\n\t{\r\n\t\tfor (uint i = 0;i<num_faces-1;i++)\r\n\t\t{\r\n\t\t\tFaceIndex x = s_face_index_buffer[i];\r\n\t\t\tfor (uint j = i+1; j<num_faces;j++)\r\n\t\t\t{\r\n\t\t\t\tif (s_face_index_buffer[j] == x)\r\n\t\t\t\t{\r\n\t\t\t\t\tdups++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tprintf (\"%d/%d/%d\\n\",dups,num_faces,m_num_faces);\r\n\t#endif\r\n\t\r\n\treturn s_face_index_buffer;\r\n}\r\n\r\n//************************************************************************************\r\n//\r\n// End of BSP code\r\n//\r\n//************************************************************************************\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollObjTriData *\tCCollObjTriData::Clone(bool instance, bool skip_no_verts)\r\n{\r\n\t// Don't clone when there is no geometry and skip_no_verts is set\r\n\tif (skip_no_verts && (m_num_verts == 0))\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tint intensity_array_size;\r\n\tCCollObjTriData *m_new_coll = new CCollObjTriData(*this);\r\n\r\n\tDbg_MsgAssert(!instance, (\"CCollObjTriData::Clone() with instances not implemented yet\"));\r\n\tDbg_MsgAssert(m_num_verts, (\"CCollObjTriData::Clone() with no geometry not implemented yet\"));\r\n\tDbg_Assert(m_num_faces);\r\n\r\n#ifdef __PLAT_NGC__\r\n//\tm_new_coll->mp_vert_pos\t= (NsVector*)new char[CCollObjTriData::GetVertElemSize()*m_num_verts];\r\n\tm_new_coll->mp_raw_vert_pos\t= mp_raw_vert_pos;\r\n\tintensity_array_size = m_num_faces * 3;\r\n#else\r\n\tif (m_use_fixed_verts)\r\n\t{\r\n\t\tm_new_coll->mp_fixed_vert = new SFixedVert[m_num_verts];\r\n\t}\r\n\telse\r\n\t{\r\n#ifdef FIXED_POINT_VERTICES\r\n\t\tm_new_coll->mp_float_vert = new SFloatVert[m_num_verts];\r\n#else\r\n\t\tm_new_coll->mp_vert_pos\t= new Mth::Vector[m_num_verts];\r\n#endif\r\n\t}\r\n\tintensity_array_size = m_num_verts;\r\n#endif\t\t// __PLAT_NGC__\r\n\tif (m_use_face_small)\r\n\t{\r\n\t\tm_new_coll->mp_face_small = new SFaceSmall[m_num_faces];\r\n\t} else {\r\n\t\tm_new_coll->mp_faces = new SFace[m_num_faces];\r\n\t}\r\n\r\n#ifdef FIXED_POINT_VERTICES\r\n\tif (m_new_coll->mp_float_vert && m_new_coll->mp_faces)\r\n#else\r\n\tif (m_new_coll->mp_raw_vert_pos && m_new_coll->mp_faces)\r\n#endif\r\n\t{\r\n#ifdef __PLAT_NGC__\r\n\t\tmemcpy(m_new_coll->mp_faces,\t\tmp_faces\t\t, m_num_faces * sizeof(SFace));\r\n#else\r\n\t\tif (m_use_fixed_verts)\r\n\t\t{\r\n\t\t\tmemcpy(m_new_coll->mp_fixed_vert,\tmp_fixed_vert\t, m_num_verts * CCollObjTriData::GetVertSmallElemSize());\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n#ifdef FIXED_POINT_VERTICES\r\n\t\t\tmemcpy(m_new_coll->mp_float_vert,\tmp_float_vert\t, m_num_verts * CCollObjTriData::GetVertElemSize());\r\n#else\r\n\t\t\tmemcpy(m_new_coll->mp_vert_pos,\t\tmp_vert_pos\t\t, m_num_verts * CCollObjTriData::GetVertElemSize());\r\n#endif\r\n\t\t}\r\n\t\tif (m_use_face_small)\r\n\t\t{\r\n\t\t\tmemcpy(m_new_coll->mp_face_small,\tmp_face_small\t, m_num_faces * sizeof(SFaceSmall));\r\n\t\t} else {\r\n\t\t\tmemcpy(m_new_coll->mp_faces,\t\tmp_faces\t\t, m_num_faces * sizeof(SFace));\r\n\t\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\t} else {\r\n\t\tDbg_Error(\"Can't allocate new collision data\");\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\t// Copy intensity array if there is one\r\n\tif (mp_intensity)\r\n\t{\r\n\t\tm_new_coll->mp_intensity = new uint8[intensity_array_size];\r\n\t\tmemcpy(m_new_coll->mp_intensity, mp_intensity , intensity_array_size * sizeof(uint8));\r\n\t}\r\n\r\n\t// Set BSP tree to NULL for now until we come up with a method to copy and translate\r\n#ifdef USE_BSP_CLONE\r\n\tm_new_coll->mp_bsp_tree = mp_bsp_tree->clone(instance);\r\n#else\r\n\tm_new_coll->mp_bsp_tree = NULL;\r\n#endif // USE_BSP_CLONE\r\n\r\n\treturn m_new_coll;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollObjTriData::Translate(const Mth::Vector & delta_pos)\r\n{\r\n\tMth::Vector min_point, max_point;\r\n\tint i;\r\n\r\n\r\n\t// Translate BSP tree\r\n\tif (mp_bsp_tree)\r\n\t{\r\n\t\t//printf (\"WARNING:  moving colision geometry that contains a BSP tree.  *** CLEARING ***\\n\");\r\n\t\t//mp_bsp_tree = NULL;\r\n\t\tmp_bsp_tree->translate(delta_pos);\r\n\t}\r\n\r\n\t#ifdef __PLAT_NGC__\r\n\t// Get Verts\r\n\tMth::Vector *p_float_verts = NULL;\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tp_float_verts = new Mth::Vector[m_num_verts];\r\n\tMem::Manager::sHandle().PopContext();\r\n\tget_float_array_from_data(p_float_verts);\r\n\t\r\n\t// Translate\r\n\tfor ( i = 0; i < m_num_verts; i++ )\r\n\t{\r\n\t\tp_float_verts[i] += delta_pos;\r\n\t}\r\n\r\n\t// Put Verts\r\n\tput_float_array_into_data(p_float_verts);\r\n\tdelete [] p_float_verts;\r\n\r\n\r\n//\tif ( !mp_offset ) mp_offset = new Mth::Vector;\r\n//\tmp_offset[0][X] += delta_pos[X];\r\n//\tmp_offset[0][Y] += delta_pos[Y];\r\n//\tmp_offset[0][Z] += delta_pos[Z];\r\n\t#else\r\n\t// Pos (don't touch W since the color is there)\r\n\tif (!m_use_fixed_verts)\r\n\t{\r\n\t\tfor (i = 0; i < m_num_verts; i++)\r\n\t\t{\r\n\t#ifdef FIXED_POINT_VERTICES\r\n\t\t\tmp_float_vert[i].m_pos[X] += delta_pos[X];\r\n\t\t\tmp_float_vert[i].m_pos[Y] += delta_pos[Y];\r\n\t\t\tmp_float_vert[i].m_pos[Z] += delta_pos[Z];\r\n\t#else\r\n\t\t\tmp_vert_pos[i][X] += delta_pos[X];\r\n\t\t\tmp_vert_pos[i][Y] += delta_pos[Y];\r\n\t\t\tmp_vert_pos[i][Z] += delta_pos[Z];\r\n\t#endif // FIXED_POINT_VERTICES\r\n\t\t}\r\n\t}\r\n\t#endif\t\t// __PLAT_NGC__\r\n\r\n\t// BBox\r\n\tmin_point = m_bbox.GetMin() + delta_pos;\r\n\tmax_point = m_bbox.GetMax() + delta_pos;\r\n\tm_bbox.Set(min_point, max_point);\r\n\r\n\t//Dbg_Message(\"Min BBox (%f, %f, %f)\", m_bbox.GetMin()[X], m_bbox.GetMin()[Y], m_bbox.GetMin()[Z]);\r\n\t//Dbg_Message(\"Max BBox (%f, %f, %f)\", m_bbox.GetMax()[X], m_bbox.GetMax()[Y], m_bbox.GetMax()[Z]);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollObjTriData::RotateY(const Mth::Vector & world_origin, Mth::ERot90 rot_y)\r\n{\r\n\tMth::Vector min_point, max_point;\r\n\tint i;\r\n\r\n\t// Put object at origin\r\n\tTranslate(-world_origin);\r\n\r\n\t// Rotate BSP tree\r\n\tif (mp_bsp_tree)\r\n\t{\r\n\t\tmp_bsp_tree->rotate_y(world_origin, rot_y, false);\t\t// Don't allow it to do another translation\r\n\t}\r\n\r\n\t// Convert to floating point, if fixed point data\r\n\tMth::Vector *p_float_verts = NULL;\r\n\t#ifndef __PLAT_NGC__\r\n\tif (m_use_fixed_verts)\r\n\t#endif\t\t// __PLAT_NGC__\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\tp_float_verts = new Mth::Vector[m_num_verts];\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\tget_float_array_from_data(p_float_verts);\r\n\t}\r\n\r\n\t// Rotate\r\n\tfor (i = 0; i < m_num_verts; i++)\r\n\t{\r\n\r\n\t\tif (p_float_verts)\r\n\t\t{\r\n\t\t\tp_float_verts[i].RotateY90(rot_y);\r\n\t\t}\r\n\t\t#ifndef __PLAT_NGC__\r\n\t\telse\r\n\t\t{\r\n\t\t#ifdef FIXED_POINT_VERTICES\r\n\t\t\tMth::Vector pos(Mth::Vector::NO_INIT);\r\n\t\t\tGetRawVertexPos(i, pos);\r\n\t\t\tpos.RotateY90(rot_y);\r\n\t\t\tmp_float_vert[i].m_pos[X] = pos[X];\r\n\t\t\tmp_float_vert[i].m_pos[Y] = pos[Y];\r\n\t\t\tmp_float_vert[i].m_pos[Z] = pos[Z];\r\n\t\t#else\r\n\t\t\tmp_vert_pos[i].RotateY90(rot_y);\r\n\t\t#endif\r\n\t\t}\r\n\t\t#endif\t\t// __PLAT_NGC__\r\n\t}\r\n\r\n\t// BBox rotate\r\n\tmin_point = m_bbox.GetMin();\r\n\tmax_point = m_bbox.GetMax();\r\n\tmin_point.RotateY90(rot_y);\r\n\tmax_point.RotateY90(rot_y);\r\n\tm_bbox.Reset();\r\n\tm_bbox.AddPoint(min_point);\r\n\tm_bbox.AddPoint(max_point);\r\n\r\n\t// Convert back to fixed point, if necessary\r\n\tif (p_float_verts)\r\n\t{\r\n\t\tput_float_array_into_data(p_float_verts);\r\n\t\tdelete [] p_float_verts;\r\n\t}\r\n\r\n\t// Put object back\r\n\tTranslate(world_origin);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollObjTriData::Scale(const Mth::Vector & world_origin, const Mth::Vector & scale)\r\n{\r\n\t// Put object at origin\r\n\tTranslate(-world_origin);\r\n\r\n\t// Scale BSP tree\r\n\tif (mp_bsp_tree)\r\n\t{\r\n\t\tmp_bsp_tree->scale(world_origin, scale, false);\t\t// Don't allow it to do another translation\r\n\t}\r\n\r\n\t// Convert to floating point, if fixed point data\r\n\tMth::Vector *p_float_verts = NULL;\r\n\t#ifndef __PLAT_NGC__\r\n\tif (m_use_fixed_verts)\r\n\t#endif\t\t// __PLAT_NGC__\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\tp_float_verts = new Mth::Vector[m_num_verts];\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\tget_float_array_from_data(p_float_verts);\r\n\t}\r\n\r\n\t// Pos (don't touch W since the color is there)\r\n\tfor (int i = 0; i < m_num_verts; i++)\r\n\t{\r\n\t\tif (p_float_verts)\r\n\t\t{\r\n\t\t\tp_float_verts[i][X] *= scale[X];\r\n\t\t\tp_float_verts[i][Y] *= scale[Y];\r\n\t\t\tp_float_verts[i][Z] *= scale[Z];\r\n\t\t}\r\n\t\t#ifndef __PLAT_NGC__\r\n\t\telse\r\n\t\t{\r\n\t\t#ifdef FIXED_POINT_VERTICES\r\n\t\t\tmp_float_vert[i].m_pos[X] *= scale[X];\r\n\t\t\tmp_float_vert[i].m_pos[Y] *= scale[Y];\r\n\t\t\tmp_float_vert[i].m_pos[Z] *= scale[Z];\r\n\t\t#else\r\n\t\t\tmp_vert_pos[i][X] *= scale[X];\r\n\t\t\tmp_vert_pos[i][Y] *= scale[Y];\r\n\t\t\tmp_vert_pos[i][Z] *= scale[Z];\r\n\t\t#endif\r\n\t\t}\r\n\t\t#endif\t\t// __PLAT_NGC__\r\n\t}\r\n\r\n\t// BBox\r\n\tMth::Vector min_point(m_bbox.GetMin()), max_point(m_bbox.GetMax());\r\n\r\n\tmin_point[X] *= scale[X];\r\n\tmin_point[Y] *= scale[Y];\r\n\tmin_point[Z] *= scale[Z];\r\n\r\n\tmax_point[X] *= scale[X];\r\n\tmax_point[Y] *= scale[Y];\r\n\tmax_point[Z] *= scale[Z];\r\n\r\n\tm_bbox.Set(min_point, max_point);\r\n\r\n\t// Convert back to fixed point, if necessary\r\n\tif (p_float_verts)\r\n\t{\r\n\t\tput_float_array_into_data(p_float_verts);\r\n\t\tdelete [] p_float_verts;\r\n\t}\r\n\r\n\t// Put object back\r\n\tTranslate(world_origin);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollObjTriData::SetRawVertexPos(int vert_idx, const Mth::Vector & pos)\r\n{\r\n\tDbg_MsgAssert(mp_bsp_tree == NULL, (\"Cannot change a vertex within a BSP Tree\"));\r\n\r\n\tset_vertex_pos(vert_idx, pos);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollObjTriData::set_vertex_pos(int vert_idx, const Mth::Vector & pos)\r\n{\r\n#ifndef __PLAT_NGC__\t// Since they are shared with the render data\r\n\tif (m_use_fixed_verts)\r\n\t{\r\n\t\tMth::Vector rel_pos(pos - m_bbox.GetMin());\r\n\r\n\t\tDbg_MsgAssert((rel_pos[X] >= 0.0f) && (rel_pos[Y] >= 0.0f) && (rel_pos[Z] >= 0.0f), (\"Adding a vert that is outside of bounding box\"));\r\n\r\n\t\tmp_fixed_vert[vert_idx].m_pos[X] = (uint16) (rel_pos[X] * COLLISION_SUB_INCH_PRECISION);\r\n\t\tmp_fixed_vert[vert_idx].m_pos[Y] = (uint16) (rel_pos[Y] * COLLISION_SUB_INCH_PRECISION);\r\n\t\tmp_fixed_vert[vert_idx].m_pos[Z] = (uint16) (rel_pos[Z] * COLLISION_SUB_INCH_PRECISION);\r\n\t}\r\n\telse\r\n\t{\r\n#ifdef FIXED_POINT_VERTICES\r\n\t\tmp_float_vert[vert_idx].m_pos[X] = pos[X];\r\n\t\tmp_float_vert[vert_idx].m_pos[Y] = pos[Y];\r\n\t\tmp_float_vert[vert_idx].m_pos[Z] = pos[Z];\r\n#else\r\n\t\tmp_vert_pos[vert_idx][X] = pos[X];\r\n\t\tmp_vert_pos[vert_idx][Y] = pos[Y];\r\n\t\tmp_vert_pos[vert_idx][Z] = pos[Z];\r\n#endif\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollObjTriData::GetRawVertices(Mth::Vector *p_vert_array) const\r\n{\r\n\tget_float_array_from_data(p_vert_array);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollObjTriData::SetRawVertices(const Mth::Vector *p_vert_array)\r\n{\r\n\t// Must set the bounding box first in case data is in fixed point\r\n\tm_bbox.Reset();\r\n\tfor (int i = 0; i < m_num_verts; i++)\r\n\t{\r\n\t\tm_bbox.AddPoint(p_vert_array[i]);\r\n\t}\r\n\r\n\tput_float_array_into_data(p_vert_array);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#define MAX_USED 80000\r\n\r\nvoid\tCCollObjTriData::get_float_array_from_data(Mth::Vector *p_float_array) const\r\n{\r\n#ifdef __PLAT_NGC__\r\n\tif ( mp_cloned_vert_pos )\r\n\t{\r\n\t\t// Already cloned, just copy.\r\n\t\tfor ( int i = 0; i < m_num_verts; i++ )\r\n\t\t{\r\n\t\t\tp_float_array[i][X] = mp_cloned_vert_pos[i].x;\r\n\t\t\tp_float_array[i][Y] = mp_cloned_vert_pos[i].y;\r\n\t\t\tp_float_array[i][Z] = mp_cloned_vert_pos[i].z;\r\n\t\t\tp_float_array[i][W] = 0.0f;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// We need to pull the verts out of the main render vert list.\r\n\t\tint lp;\r\n\t\tint lp2;\r\n\t\tint index;\r\n\t\tunsigned char used[(MAX_USED/8)];\r\n\r\n\t\t// Build a bit list of used verts.\r\n\t\tfor ( lp = 0; lp < (MAX_USED/8); lp++ ) used[lp] = 0;\r\n\r\n\t\tfor ( lp = 0; lp < m_num_faces; lp++ )\r\n\t\t{\r\n\t\t\tindex = mp_faces[lp].m_vertex_index[0];\r\n\t\t\tused[(index>>3)] |= (1<<(index&7));\r\n\t\t\tindex = mp_faces[lp].m_vertex_index[1];\r\n\t\t\tused[(index>>3)] |= (1<<(index&7));\r\n\t\t\tindex = mp_faces[lp].m_vertex_index[2];\r\n\t\t\tused[(index>>3)] |= (1<<(index&7));\r\n\t\t}\r\n\r\n\t\t// Copy verts out in order.\r\n\t\tint num_copied = 0;\r\n\t\tfor ( lp = 0; lp < (MAX_USED/8); lp++ )\r\n\t\t{\r\n\t\t\tif ( used[lp] )\r\n\t\t\t{\r\n\t\t\t\tfor ( lp2 = 0; lp2 < 8; lp2++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( used[lp] & (1<<lp2) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tindex = (lp<<3) + lp2;\r\n\t\t\t\t\t\tp_float_array[num_copied] = GetRawVertexPos(index);\r\n\t\t\t\t\t\tnum_copied++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#else\r\n\tfor (int i = 0; i < m_num_verts; i++)\r\n\t{\r\n\t\tp_float_array[i] = GetRawVertexPos(i);\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollObjTriData::put_float_array_into_data(const Mth::Vector *p_float_array)\r\n{\r\n#ifdef __PLAT_NGC__\r\n\t// Need to change mp_mod to a modified collision vert pointer and alloc new space here.\r\n\t// the header getpos functions need to check that & pull from there if necessary.\r\n\t// Also need to remap the face array when we do this.\r\n\t// Ugh.\r\n\r\n\r\n\r\n\tif ( mp_cloned_vert_pos )\r\n\t{\r\n\t\t// Already cloned, just copy.\r\n\t\tfor ( int i = 0; i < m_num_verts; i++ )\r\n\t\t{\r\n\t\t\tmp_cloned_vert_pos[i].x = p_float_array[i][X];\r\n\t\t\tmp_cloned_vert_pos[i].y = p_float_array[i][Y];\r\n\t\t\tmp_cloned_vert_pos[i].z = p_float_array[i][Z];\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Allocate space for verts & copy over.\r\n\t\tmp_cloned_vert_pos = (NsVector*)new float[m_num_verts*3];\r\n\r\n\t\tfor ( int i = 0; i < m_num_verts; i++ )\r\n\t\t{\r\n\t\t\tmp_cloned_vert_pos[i].x = p_float_array[i][X];\r\n\t\t\tmp_cloned_vert_pos[i].y = p_float_array[i][Y];\r\n\t\t\tmp_cloned_vert_pos[i].z = p_float_array[i][Z];\r\n\t\t}\r\n\r\n\t\t// Need to remap existing face map.\r\n\t\tint lp;\r\n\t\tint lp2;\r\n\t\tint index;\r\n\t\tunsigned char used[(MAX_USED/8)];\r\n\r\n\t\t// Build a bit list of used verts.\r\n\t\tfor ( lp = 0; lp < (MAX_USED/8); lp++ ) used[lp] = 0;\r\n\r\n\t\tfor ( lp = 0; lp < m_num_faces; lp++ )\r\n\t\t{\r\n\t\t\tindex = mp_faces[lp].m_vertex_index[0];\r\n\t\t\tused[(index>>3)] |= (1<<(index&7));\r\n\t\t\tindex = mp_faces[lp].m_vertex_index[1];\r\n\t\t\tused[(index>>3)] |= (1<<(index&7));\r\n\t\t\tindex = mp_faces[lp].m_vertex_index[2];\r\n\t\t\tused[(index>>3)] |= (1<<(index&7));\r\n\t\t}\r\n\r\n\t\t// Remap faces.\r\n\t\tint num_copied = 0;\r\n\t\tfor ( lp = 0; lp < (MAX_USED/8); lp++ )\r\n\t\t{\r\n\t\t\tif ( used[lp] )\r\n\t\t\t{\r\n\t\t\t\tfor ( lp2 = 0; lp2 < 8; lp2++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( used[lp] & (1<<lp2) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tindex = (lp<<3) + lp2;\r\n\r\n\t\t\t\t\t\t// See if any face indices match this one & remap if so.\r\n\t\t\t\t\t\tfor ( int f = 0; f < m_num_faces; f++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tfor ( int v = 0; v < 3; v++ )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif ( mp_faces[f].m_vertex_index[v] == index )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tmp_faces[f].m_vertex_index[v] = num_copied;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tnum_copied++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#else\r\n\tfor (int i = 0; i < m_num_verts; i++)\r\n\t{\r\n\t\tset_vertex_pos(i, p_float_array[i]);\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n}\r\n\r\n// This is called once when a scene is first loaded, from ScriptParseNodeArray\r\n// and only if the OCCLUDER flag is set in the object's node\r\n// here we loop over the polgons in the object\r\n// and create a single occluder polygon\r\n// which is added to the world\r\n//\r\n// (these will need to be deleted when the scene is unloaded)\r\nvoid CCollObjTriData::ProcessOcclusion( void )\r\n{\r\n\t// Scan through and find pairs of triangles that share 2 verts - i.e. that form quads.\r\n\tfor( int fidx0 = 0; fidx0 < m_num_faces - 1; ++fidx0 )\r\n\t{\r\n\t\tSFaceInfo *p_face0 = get_face_info(fidx0);\r\n\r\n\t\t// Check we haven't already used this face.\r\n\t\tif( p_face0->m_flags & ( 1 << 31 ))\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tMth::Vector\tv[4];\r\n\t\tv[0] = GetRawVertexPos(GetFaceVertIndex(fidx0, 0));\r\n\t\tv[1] = GetRawVertexPos(GetFaceVertIndex(fidx0, 1));\r\n\t\tv[2] = GetRawVertexPos(GetFaceVertIndex(fidx0, 2));\r\n//\t\tprintf( \"Occlusion Triangle %d\\n(%f,%f,%f)\\n(%f,%f,%f)\\n(%f,%f,%f)\\n\",fidx0,v[0][X],v[0][Y],v[0][Z],v[1][X],v[1][Y],v[1][Z],v[2][X],v[2][Y],v[2][Z] );\r\n\r\n\t\tfor( int fidx1 = fidx0 + 1; fidx1 < m_num_faces; ++fidx1 )\r\n\t\t{\r\n\t\t\tSFaceInfo *p_face1 = get_face_info(fidx1);\r\n\r\n\t\t\t// Check we haven't already used this face.\r\n\t\t\tif( p_face1->m_flags & ( 1 << 31 ))\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tv[0] = GetRawVertexPos(GetFaceVertIndex(fidx1, 0));\r\n\t\t\tv[1] = GetRawVertexPos(GetFaceVertIndex(fidx1, 1));\r\n\t\t\tv[2] = GetRawVertexPos(GetFaceVertIndex(fidx1, 2));\r\n//\t\t\tprintf( \"Occlusion Triangle %d\\n(%f,%f,%f)\\n(%f,%f,%f)\\n(%f,%f,%f)\\n\",fidx1,v[0][X],v[0][Y],v[0][Z],v[1][X],v[1][Y],v[1][Z],v[2][X],v[2][Y],v[2][Z] );\r\n\r\n\t\t\tint indices_matched0[3]\t= { -1, -1, -1 };\r\n\t\t\tint indices_matched1[3]\t= { -1, -1, -1 };\r\n\t\t\tint num_indices_matched\t= 0;\r\n\r\n\t\t\tfor( int i = 0; i < 3; ++i )\r\n\t\t\t{\r\n\t\t\t\tif( GetFaceVertIndex(fidx0, i) == GetFaceVertIndex(fidx1, 0) )\r\n\t\t\t\t{\r\n\t\t\t\t\tindices_matched0[i] = GetFaceVertIndex(fidx0, i);\r\n\t\t\t\t\tindices_matched1[0] = GetFaceVertIndex(fidx1, 0);\r\n\t\t\t\t\t++num_indices_matched;\r\n\t\t\t\t}\r\n\t\t\t\telse if( GetFaceVertIndex(fidx0, i) == GetFaceVertIndex(fidx1, 1) )\r\n\t\t\t\t{\r\n\t\t\t\t\tindices_matched0[i] = GetFaceVertIndex(fidx0, i);\r\n\t\t\t\t\tindices_matched1[1] = GetFaceVertIndex(fidx1, 1);\r\n\t\t\t\t\t++num_indices_matched;\r\n\t\t\t\t}\r\n\t\t\t\telse if( GetFaceVertIndex(fidx0, i) == GetFaceVertIndex(fidx1, 2) )\r\n\t\t\t\t{\r\n\t\t\t\t\tindices_matched0[i] = GetFaceVertIndex(fidx0, i);\r\n\t\t\t\t\tindices_matched1[2] = GetFaceVertIndex(fidx1, 2);\r\n\t\t\t\t\t++num_indices_matched;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Three indices matched is just plain wrong.\r\n\t\t\tDbg_Assert( num_indices_matched < 3 );\r\n\r\n\t\t\t// Two indices matched is just what we want.\r\n\t\t\tif( num_indices_matched == 2 )\r\n\t\t\t{\r\n\t\t\t\t// Make sure that the 2 tris lie in the same plane, which is no longer necessarily the case since they could be\r\n\t\t\t\t// tris which adjoin at a right angle.\r\n\t\t\t\tv[0]\t\t\t\t= GetRawVertexPos(GetFaceVertIndex( fidx0, 0 ));\r\n\t\t\t\tv[1]\t\t\t\t= GetRawVertexPos(GetFaceVertIndex( fidx0, 1 ));\r\n\t\t\t\tv[2]\t\t\t\t= GetRawVertexPos(GetFaceVertIndex( fidx0, 2 ));\r\n\t\t\t\tMth::Vector norm0\t= Mth::CrossProduct( v[1] - v[0], v[2] - v[0] );\r\n\t\t\t\tv[0]\t\t\t\t= GetRawVertexPos(GetFaceVertIndex( fidx1, 0 ));\r\n\t\t\t\tv[1]\t\t\t\t= GetRawVertexPos(GetFaceVertIndex( fidx1, 1 ));\r\n\t\t\t\tv[2]\t\t\t\t= GetRawVertexPos(GetFaceVertIndex( fidx1, 2 ));\r\n\t\t\t\tMth::Vector norm1\t= Mth::CrossProduct( v[1] - v[0], v[2] - v[0] );\r\n\t\t\t\tnorm0.Normalize();\r\n\t\t\t\tnorm1.Normalize();\r\n\t\t\t\t\r\n\t\t\t\tif(( fabs( norm1[X]-norm0[X]) <= 0.05f ) && ( fabs( norm1[Y]-norm0[Y]) <= 0.05f ) && ( fabs( norm1[Z]-norm0[Z]) <= 0.05f ))\r\n\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t// These two tris are coplanar.\r\n\t\t\t\t\r\n\t\t\t\t\t// Get the index from tri1 that isn't shared with tri0.\r\n\t\t\t\t\tint unshared_tri1_index = -1;\r\n\t\t\t\t\tfor( int i = 0; i < 3; ++i )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( indices_matched1[i] == -1 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tunshared_tri1_index = GetFaceVertIndex(fidx1, i);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tDbg_Assert( unshared_tri1_index >= 0 );\r\n\t\t\t\t\r\n\t\t\t\t\t// Fill in the missing 2 verts, one from each tri. What is important here is which side of triangle0 that\r\n\t\t\t\t\t// that triangle1 shares, since this will determine the overall order of the quad abcd.\r\n\t\t\t\t\tif(( indices_matched0[0] >= 0 ) && ( indices_matched0[1] >= 0 ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// They share side 0->1. Thus the quad will be t0(0), t1(unshared), t0(1), t0(2).\r\n\t\t\t\t\t\tv[0] = GetRawVertexPos(GetFaceVertIndex(fidx0, 0));\r\n\t\t\t\t\t\tv[1] = GetRawVertexPos(unshared_tri1_index);\r\n\t\t\t\t\t\tv[2] = GetRawVertexPos(GetFaceVertIndex(fidx0, 1));\r\n\t\t\t\t\t\tv[3] = GetRawVertexPos(GetFaceVertIndex(fidx0, 2));\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(( indices_matched0[1] >= 0 ) && ( indices_matched0[2] >= 0 ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// They share side 1->2. Thus the quad will be t0(0), t0(1), t1(unshared), t0(2).\r\n\t\t\t\t\t\tv[0] = GetRawVertexPos(GetFaceVertIndex(fidx0, 0));\r\n\t\t\t\t\t\tv[1] = GetRawVertexPos(GetFaceVertIndex(fidx0, 1));\r\n\t\t\t\t\t\tv[2] = GetRawVertexPos(unshared_tri1_index);\r\n\t\t\t\t\t\tv[3] = GetRawVertexPos(GetFaceVertIndex(fidx0, 2));\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(( indices_matched0[0] >= 0 ) && ( indices_matched0[2] >= 0 ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// They share side 2->0. Thus the quad will be t0(0), t0(1), t0(2), t1(unshared).\r\n\t\t\t\t\t\tv[0] = GetRawVertexPos(GetFaceVertIndex(fidx0, 0));\r\n\t\t\t\t\t\tv[1] = GetRawVertexPos(GetFaceVertIndex(fidx0, 1));\r\n\t\t\t\t\t\tv[2] = GetRawVertexPos(GetFaceVertIndex(fidx0, 2));\r\n\t\t\t\t\t\tv[3] = GetRawVertexPos(unshared_tri1_index);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t\t}\r\n\r\n//\t\t\t\t\tprintf( \"Occlusion Quad\\n(%f,%f,%f)\\n(%f,%f,%f)\\n(%f,%f,%f)\\n(%f,%f,%f)\\n\",v[0][X],v[0][Y],v[0][Z],v[1][X],v[1][Y],v[1][Z],v[2][X],v[2][Y],v[2][Z],v[3][X],v[3][Y],v[3][Z] );\r\n\r\n\t\t\t\t\t// Register this quad with the engine.\r\n\t\t\t\t\tNx::CEngine::sAddOcclusionPoly( 4, v, m_checksum );\r\n\t\t\t\t\r\n\t\t\t\t\t// Flag the two tris as having been used.\r\n\t\t\t\t\tDbg_Assert(( p_face0->m_flags & ( 1 << 31 )) == 0 );\r\n\t\t\t\t\tDbg_Assert(( p_face1->m_flags & ( 1 << 31 )) == 0 );\r\n\t\t\t\t\tp_face0->m_flags |= ( 1 << 31 );\r\n\t\t\t\t\tp_face1->m_flags |= ( 1 << 31 );\r\n\t\t\t\t\r\n\t\t\t\t\t// Break out of this inner loop now since we have found a pair.\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Scan through and clear 'used' flag on faces.\r\n\tfor( int fidx0 = 0; fidx0 < m_num_faces; ++fidx0 )\r\n\t{\r\n\t\tSFaceInfo *p_face0 = get_face_info(fidx0);\r\n\t\tp_face0->m_flags &= ~( 1 << 31 );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef\t__DEBUG_CODE__\r\n\r\nvoid\tCCollObjTriData::DebugRender(uint32 ignore_1, uint32 ignore_0)\r\n{\r\n#ifdef\t__NOPT_ASSERT__\r\n\tstatic Mth::Matrix ident_matrix(0.0f, 0.0f, 0.0f);\t// static so it doesn't waste time in the constuctor\r\n\r\n\t// simple culling based on the world bbox\r\n\tMth::Vector mid = (GetBBox().GetMax() + GetBBox().GetMin())/2.0f;\r\n\tfloat\tradius = (mid - GetBBox().GetMin()).Length();\r\n\r\n\tif (Nx::CEngine::GetWireframeMode() == 6)\t // 6 = occlusion\t  \r\n\t{\r\n\t\t// Rendering as 2d, to demontrate occlusion\r\n\t\t// we try to get the visibility flag from the engine\r\n\r\n#if\t0\t\t//def\t__PLAT_NGPS__\t\r\n\tbool\tdrawn = true;\r\n\r\n\tNx::CPs2Sector* p_sector = (Nx::CPs2Sector*)Nx::CEngine::sGetSector(m_checksum);\r\n\tif (p_sector)\r\n\t{\r\n\t\r\n\t\tNxPs2::CGeomNode *p_node = (p_sector->GetEngineObject());\r\n\t\tif (p_node)\r\n\t\t{\r\n\t\t\tdrawn = p_node->WasRendered();\t\t\r\n\t\t}\r\n\t}\r\n\r\n\r\n//\r\n\tif (drawn)\r\n#else\r\n\t\tif ( Nx::CEngine::sIsVisible(mid,radius))\r\n#endif\t\r\n\t\t{\r\n\t\t\tNx::CSector* p_sector = Nx::CEngine::sGetSector(m_checksum); // SLOWWWWWWWWWWWWW\r\n\t\t\tif (p_sector && !p_sector->GetVisibility())\r\n\t\t\t{\r\n\t\t\t\tDebugRender2D(ignore_1, ignore_0,0x000080);   \t\t\t// red = hidden\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDebugRender2D(ignore_1, ignore_0,0x808080);   \t\t\t// grey = visible\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t#ifdef\t__PLAT_NGPS__\r\n\t\t\t// Mick:  Should be abel to use the actual Occluded bits here....\r\n\t\t\tif (NxPs2::IsInFrame( mid, radius ) && NxPs2::TestSphereAgainstOccluders(&mid,radius,0))\r\n\t\t\t\tDebugRender2D(ignore_1, ignore_0,0x40c040);\t   // green = occluded \r\n\t\t\telse\r\n\t\t\t#endif\r\n\t\t\t{\r\n\t\t\t\tDebugRender2DBBox(ignore_1, ignore_0,0x003030);\t\t// dk yellow box and \r\n\t\t\t\tDebugRender2DOct(ignore_1, ignore_0,0x003000);\t\t// dark green ocotogon off camera\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n//\t    if ( Nx::CEngine::sIsVisible(mid,radius))\r\n#\t\tifdef __PLAT_NGPS__\t\r\n   \t\tif (NxPs2::IsInFrame( mid, radius ))\r\n\t\t\tDebugRender(ident_matrix, ignore_1, ignore_0, false);\r\n#\t\tendif\r\n\t}\r\n#endif\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollObjTriData::DebugRender(const Mth::Matrix & transform, uint32 ignore_1, uint32 ignore_0, bool do_transform)\r\n{\r\n#ifdef\t__PLAT_NGPS__\t\r\n\r\n\tuint32\trgb = 0x000000;\r\n\tint n = m_num_faces;\t\r\n\tint r=0;\r\n\tint g=0;\r\n\tint b=0;\r\n\t\r\n\tNxPs2::DMAOverflowOK = 2;\r\n\r\n\r\n\tswitch (Nx::CEngine::GetWireframeMode())\r\n\t{\r\n\t\tcase 1:\t// Polygon density, red = high, white=higher \r\n\t\t{\r\n\t\t\t#define\tpeak 500\t\r\n\t\t\tif (n <= peak )\r\n\t\t\t{\r\n\t\t\t\tr = (255 * (n)) / peak;  \t// r ramps up (black to red)\t\r\n\t\t\t}\r\n\t\t\telse if (n <= peak * 2)\r\n\t\t\t{\r\n\t\t\t\tr = 255;\r\n\t\t\t\tb = (255 * (n - peak) / (peak));\t// b&g ramps up (to white)\r\n\t\t\t\tg = b;\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tr = g = b = 255;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 2:\t// Low Polygon density, red = high, white=higher \r\n\t\t{\r\n\t\t\t#define\tpeak 500\t\r\n\t\t\tif (n <= 2 )\r\n\t\t\t{\r\n\t\t\t\tr = g = b = 255;\t\t\t// White = two or less\r\n\t\t\t}\r\n\t\t\telse if (n <= 4)\r\n\t\t\t{\r\n\t\t\t\tg = 255;\t\t\t\t   // Green = 4 or less\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse if (n <= 8)\r\n\t\t\t{\r\n\t\t\t\tb = 255;\t\t\t\t   // blue = 8 or less\r\n\t\t\t}\r\n\t\t\telse if (n <= 16)\t\t\t   \r\n\t\t\t{\r\n\t\t\t\tr = b = 255;\t\t\t   // Magenta = 16 or less\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 3:\t   \t// Each object a different color, based on checksum\r\n\t\t{\r\n\t\t\tr = (m_checksum >>16) & 0xff;\r\n\t\t\tg = (m_checksum >>8) & 0xff;\r\n\t\t\tb = (m_checksum ) & 0xff;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tbreak;\t\r\n\t}\r\n\r\n\r\n\t// fix up anything I did stupid\r\n\tif (r<0) r=0;\r\n\tif (r>255) r=255;\r\n\tif (g<0) g=0;\r\n\tif (g>255) g=255;\r\n\tif (b<0) b=0;\r\n\tif (b>255) b=255;\r\n\r\n\trgb = (b<<16)|(g<<8)|r;\t\r\n\t\r\n\tuint32 current = 12345678;\r\n\r\n\r\n\t\t#if 0\r\n\t\t// scan through all verts, and see if any are close, but not close enough....\r\n\t\t// obviously this will be somewhat slow\r\n\t\tNxPs2::BeginLines3D(0x80000000 + (0x00ff00ff));\t\t// Magenta = unwelded verts\r\n\r\n\t\tfor (int i=0;i<m_num_verts-1;i++)\r\n\t\t{\r\n\t\t\tfor (int j = i+1; j<m_num_verts;j++)\r\n\t\t\t{\r\n\t\t\t\tfloat len = (mp_vert_pos[i]-mp_vert_pos[j]).LengthSqr();\r\n\t\t\t\tif ( len >0.0000001f && len < 1.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\r\n\t\t\t\t\tMth::Vector *v0,*v1;\r\n\t\t\t\t\tv0 = &mp_vert_pos[i];\r\n\t\t\t\t\tv1 = &mp_vert_pos[j];\r\n\t\t\t\t\tNxPs2::DrawLine3D((*v0)[X],(*v0)[Y],(*v0)[Z],(*v0)[X],(*v0)[Y]+100.0f,(*v0)[Z]);\t\t\t\t\t\t\t\t\r\n\t\t\t\t\tNxPs2::DrawLine3D((*v1)[X],(*v1)[Y],(*v1)[Z],(*v1)[X],(*v1)[Y]+100.0f,(*v1)[Z]);\t\t\t\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tNxPs2::EndLines3D();\r\n\t\treturn;\r\n\r\n\t\t\r\n\t\t#endif\r\n\r\n\r\n\tMth::Vector v0, v1, v2;\r\n\t\r\n\r\n\tfor (int fidx = 0; fidx < m_num_faces; fidx++)\r\n\t{\r\n\t\tSFaceInfo *face = get_face_info(fidx);\r\n\r\n\t\tif (!(face->m_flags & ignore_1) && !(~face->m_flags & ignore_0))\r\n\t\t{\r\n\t\t\r\n\t\tif (Nx::CEngine::GetWireframeMode() == 0)   // face flags\r\n\t\t{\r\n\t\t\trgb = 0xffffff;\t\t\t\t\t\t// white = no flags\r\n\t\t\tif (face->m_flags & mFD_VERT)\r\n\t\t\t{\r\n\t\t\t\trgb = 0x4040ff;\t\t\t   \t\t// red = vert\r\n\t\t\t}\t\t\t\t\r\n\t\t\tif (face->m_flags & mFD_TRIGGER)\r\n\t\t\t{\r\n\t\t\t\trgb = 0xff4040;\t\t\t\t    // blue = trigger\r\n\t\t\t}\t\t\t\t\r\n\t\t\tif (face->m_flags & mFD_WALL_RIDABLE)\r\n\t\t\t{\r\n\t\t\t\trgb = 0x00ffff;\t\t\t\t   // yellow = wallride\r\n\t\t\t}\t\t\t\t\r\n\t\t}\t\t\t   \r\n\t\t\t\t   \r\n\t\t\t// check for context changes\r\n\t\t\tif (current != rgb)\r\n\t\t\t{\r\n\t\t\t\tif (current == 12345678)\r\n\t\t\t\t{\r\n\t\t\t\t\tNxPs2::BeginLines3D(0x80000000 + (0x00ffffff & rgb));\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t    \t\tNxPs2::ChangeLineColor(0x80000000 + (0x00ffffff & rgb));\r\n\t\t\t\t}\r\n\t\t\t\tcurrent = rgb;\r\n\t\t\t}\r\n\r\n#ifdef FIXED_POINT_VERTICES\r\n\t\t\tif (do_transform)\r\n\t\t\t{\r\n\t\t\t\tv0 = transform.TransformAsPos(GetRawVertexPos(GetFaceVertIndex(fidx, 0)));\r\n\t\t\t\tv1 = transform.TransformAsPos(GetRawVertexPos(GetFaceVertIndex(fidx, 1)));\r\n\t\t\t\tv2 = transform.TransformAsPos(GetRawVertexPos(GetFaceVertIndex(fidx, 2)));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tv0 = GetRawVertexPos(GetFaceVertIndex(fidx, 0));\r\n\t\t\t\tv1 = GetRawVertexPos(GetFaceVertIndex(fidx, 1));\r\n\t\t\t\tv2 = GetRawVertexPos(GetFaceVertIndex(fidx, 2));\r\n\t\t\t}\r\n#else\r\n\t\t\tif (do_transform)\r\n\t\t\t{\r\n\t\t\t\tv0 = transform.TransformAsPos(mp_vert_pos[GetFaceVertIndex(fidx, 0)]);\r\n\t\t\t\tv1 = transform.TransformAsPos(mp_vert_pos[GetFaceVertIndex(fidx, 1)]);\r\n\t\t\t\tv2 = transform.TransformAsPos(mp_vert_pos[GetFaceVertIndex(fidx, 2)]);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tv0 = mp_vert_pos[GetFaceVertIndex(fidx, 0)];\r\n\t\t\t\tv1 = mp_vert_pos[GetFaceVertIndex(fidx, 1)];\r\n\t\t\t\tv2 = mp_vert_pos[GetFaceVertIndex(fidx, 2)];\r\n\t\t\t}\r\n#endif // FIXED_POINT_VERTICES\r\n\r\n\t\t\tNxPs2::DrawLine3D(v0[X], v0[Y], v0[Z], v1[X], v1[Y], v1[Z]);\r\n\t\t\tNxPs2::DrawLine3D(v0[X], v0[Y], v0[Z], v2[X], v2[Y], v2[Z]);\r\n\t\t\tNxPs2::DrawLine3D(v2[X], v2[Y], v2[Z], v1[X], v1[Y], v1[Z]);\r\n\t\t}\r\n\t}\r\n\t// only if we actually drew some\r\n\tif ( current != 12345678)\r\n\t{\r\n\t\tNxPs2::EndLines3D();\r\n\t}\r\n#else\r\n\tconst uint32 rgba = 0x0000FF80;\r\n\r\n\tfor (int fidx = 0; fidx < m_num_faces; fidx++)\r\n\t{\r\n\t\tMth::Vector v0, v1, v2;\r\n\r\n\t\tif (do_transform)\r\n\t\t{\r\n#if defined(FIXED_POINT_VERTICES) || defined(__PLAT_NGC__)\r\n\t\t\tv0 = transform.TransformAsPos(GetRawVertexPos(GetFaceVertIndex(fidx, 0)));\r\n\t\t\tv1 = transform.TransformAsPos(GetRawVertexPos(GetFaceVertIndex(fidx, 1)));\r\n\t\t\tv2 = transform.TransformAsPos(GetRawVertexPos(GetFaceVertIndex(fidx, 2)));\r\n#else\r\n\t\t\tv0 = transform.TransformAsPos(mp_vert_pos[GetFaceVertIndex(fidx, 0)]);\r\n\t\t\tv1 = transform.TransformAsPos(mp_vert_pos[GetFaceVertIndex(fidx, 1)]);\r\n\t\t\tv2 = transform.TransformAsPos(mp_vert_pos[GetFaceVertIndex(fidx, 2)]);\r\n#endif // FIXED_POINT_VERTICES\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n#if defined(FIXED_POINT_VERTICES) || defined(__PLAT_NGC__)\r\n\t\t\tv0 = GetRawVertexPos(GetFaceVertIndex(fidx, 0));\r\n\t\t\tv1 = GetRawVertexPos(GetFaceVertIndex(fidx, 1));\r\n\t\t\tv2 = GetRawVertexPos(GetFaceVertIndex(fidx, 2));\r\n#else\r\n\t\t\tv0 = mp_vert_pos[GetFaceVertIndex(fidx, 0)];\r\n\t\t\tv1 = mp_vert_pos[GetFaceVertIndex(fidx, 1)];\r\n\t\t\tv2 = mp_vert_pos[GetFaceVertIndex(fidx, 2)];\r\n#endif // FIXED_POINT_VERTICES\r\n\t\t}\t\t\r\n\t\t// Draw Triangle\r\n\t\tGfx::AddDebugLine(v0, v1, rgba, rgba, 1);\r\n\t\tGfx::AddDebugLine(v1, v2, rgba, rgba, 1);\r\n\t\tGfx::AddDebugLine(v2, v0, rgba, rgba, 1);\r\n\t}\r\n#endif //\t__PLAT_NGPS__\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic Mth::Vector x;\r\nstatic Mth::Vector y;\r\n\r\ninline void rot(Mth::Vector &v)\r\n{\r\n\tfloat vx = v[X];\r\n\tfloat vy = v[Z];\r\n\tv[X] = vx * x[X] + vy * x[Z];\r\n\tv[Z] = vx * y[X] + vy * y[Z];\r\n}\r\n\r\n\r\n\r\n\r\nstatic float\tdebug_2d_scale =  0.02f;\r\nstatic Mth::Vector s_overhead_cam_pos;\r\n\r\nvoid\t_debug_change_2d_scale(float x)\r\n{\r\n\tdebug_2d_scale *= x;\r\n\tif (debug_2d_scale > 0.5f) debug_2d_scale = 0.5f;\r\n\tif (debug_2d_scale < 0.002f) debug_2d_scale = 0.002f;\r\n\t\r\n}\r\n\r\nvoid\tOverheadLine(Mth::Vector v0, Mth::Vector v1)\r\n{\r\n#ifdef\t__PLAT_NGPS__\t\r\n\r\n\tMth::Vector offset;\r\n\toffset.Set(320.0f,0.0f,224.0f);\r\n\r\n\tv0 -= s_overhead_cam_pos;\r\n\tv1 -= s_overhead_cam_pos;\r\n\r\n\tv0 *= debug_2d_scale;\r\n\tv1 *= debug_2d_scale;\r\n\r\n\trot(v0);\r\n\trot(v1);\r\n\r\n\tv0 += offset;\r\n\tv1 += offset;\r\n\t\r\n\tif (v0[X] < 0 && v1[X] < 0) return;\r\n\tif (v0[Z] < 0 && v1[Z] < 0) return;\r\n\tif (v0[X] > 639 && v1[X] >639) return;\r\n\tif (v0[Z] > 447 && v1[Z] > 447) return;\r\n\r\n\r\n\t// Some simple clipping\r\n\r\n\tNxPs2::DrawLine2D(v0[X], v0[Z], 0.0f, v1[X],  v1[Z],0.0f);\r\n\r\n#endif\r\n}\r\n\r\n\r\nvoid\tCCollObjTriData::DebugRender2D(uint32 ignore_1, uint32 ignore_0, uint32 visible)\r\n{\r\n#ifdef\t__PLAT_NGPS__\t\r\n\r\n\r\n\tGfx::Camera *cur_camera = Nx::CViewportManager::sGetCamera( 0 );\r\n\ts_overhead_cam_pos = cur_camera->GetPos();\r\n\r\n\t// get orientation from the camere\r\n\ty = cur_camera->GetMatrix()[Z];\r\n\ty[Y] = 0.0f;\r\n\ty.Normalize();\r\n\tx[X] =   y[Z];\r\n\tx[Y] = 0.0f;\r\n\tx[Z] = - y[X];\r\n\r\n\tuint32\trgb = visible;\t\t \t\t// blue = visible\r\n\tMth::Vector v0, v1, v2;\r\n\tNxPs2::BeginLines2D(0x80000000 + (0x00ffffff & rgb));\r\n\tfor (int fidx = 0; fidx < m_num_faces; fidx++)\r\n\t{\r\n\t\tSFaceInfo *face = get_face_info(fidx);\r\n\t\tif (!(face->m_flags & ignore_1) && !(~face->m_flags & ignore_0))\r\n\t\t{\r\n\t\t\tGetRawVertexPos(GetFaceVertIndex(fidx, 0), v0);\r\n\t\t\tGetRawVertexPos(GetFaceVertIndex(fidx, 1), v1);\r\n\t\t\tGetRawVertexPos(GetFaceVertIndex(fidx, 2), v2);\r\n\t\t\tOverheadLine(v0,v1);\r\n\t\t\tOverheadLine(v1,v2);\r\n\t\t\tOverheadLine(v2,v0);\r\n\t\t}\r\n\t}\r\n\tNxPs2::EndLines2D();\r\n#endif\r\n}\r\n\r\nvoid\tCCollObjTriData::DebugRender2DBBox(uint32 ignore_1, uint32 ignore_0, uint32 visible)\r\n{\r\n#ifdef\t__PLAT_NGPS__\t\r\n\r\n\r\n\tGfx::Camera *cur_camera = Nx::CViewportManager::sGetCamera( 0 );\r\n\r\n\t// get orientation from the camere\r\n\ty = cur_camera->GetMatrix()[Z];\r\n\ty[Y] = 0.0f;\r\n\ty.Normalize();\r\n\tx[X] =   y[Z];\r\n\tx[Y] = 0.0f;\r\n\tx[Z] = - y[X];\r\n\r\n\tuint32\trgb = visible;\t\t \t\t// blue = visible\r\n\t\r\n\tMth::Vector v0, v1, v2,v3;\r\n\t\r\n\tNxPs2::BeginLines2D(0x80000000 + (0x00ffffff & rgb));\r\n\tv0 = GetBBox().GetMax();\r\n\tv2 = GetBBox().GetMin();\r\n\tv1[X] = v2[X];\r\n\tv1[Z] = v0[Z];\r\n\tv3[X] = v0[X];\r\n\tv3[Z] = v2[Z];\r\n\t\r\n\tOverheadLine(v0,v1);\r\n\tOverheadLine(v1,v2);\r\n\tOverheadLine(v2,v3);\r\n\tOverheadLine(v3,v0);\r\n\tNxPs2::EndLines2D();\r\n#endif\r\n}\r\n\r\n// draw as an octagon, to simultate the bounding sphere\t\t\t\t\t\t\t\t\t   \r\nvoid\tCCollObjTriData::DebugRender2DOct(uint32 ignore_1, uint32 ignore_0, uint32 visible)\r\n{\r\n#ifdef\t__PLAT_NGPS__\t\r\n\r\n\r\n\tGfx::Camera *cur_camera = Nx::CViewportManager::sGetCamera( 0 );\r\n\r\n\t// get orientation from the camere\r\n\ty = cur_camera->GetMatrix()[Z];\r\n\ty[Y] = 0.0f;\r\n\ty.Normalize();\r\n\tx[X] =   y[Z];\r\n\tx[Y] = 0.0f;\r\n\tx[Z] = - y[X];\r\n\r\n\tuint32\trgb = visible;\t\t \t\t// blue = visible\r\n\t\r\n\tMth::Vector v[8];\r\n\t\r\n\tMth::Vector offset;\r\n\t\r\n\toffset.Set(320.0f,0.0f,224.0f);\r\n\r\n\r\n\t// simple culling based on the world bbox\r\n\tMth::Vector mid = (GetBBox().GetMax() + GetBBox().GetMin())/2.0f;\r\n\tfloat\tradius = (mid - GetBBox().GetMin()).Length();\r\n\t\r\n\tfloat\thalf = radius * 0.707106f;\t\t\r\n\r\n\r\n\tv[0].Set(-half,0,-half);\r\n\tv[2].Set( half,0,-half);\r\n\tv[4].Set( half,0, half);\r\n\tv[6].Set(-half,0, half);\r\n\tv[1].Set( 0     ,0,-radius);\r\n\tv[3].Set( radius,0, 0     );\r\n\tv[5].Set( 0     ,0, radius);\r\n\tv[7].Set(-radius,0, 0     );\r\n\r\n\tNxPs2::BeginLines2D(0x80000000 + (0x00ffffff & rgb));\r\n\tfor (int i=0;i<8;i++)\r\n\t{\r\n\t\tv[i] += mid;\r\n\t}\r\n\tfor (int i=0;i<8;i++)\r\n\t{\r\n\t\tOverheadLine(v[i], v[(i+1)&7]);\r\n\t}\r\n\tNxPs2::EndLines2D();\r\n#endif\r\n}\r\n\r\n#else\r\n// Stub function for\r\nvoid\tCCollObjTriData::DebugRender(uint32 ignore_1, uint32 ignore_0) {}\r\nvoid\tCCollObjTriData::DebugRender(const Mth::Matrix & transform, uint32 ignore_1, uint32 ignore_0, bool do_transform) {}\r\n\r\n#endif\r\n\r\n// Checks to see if a coll sector has any potential \"Uberfrig\" holes or seams\r\n// that would be where there is NO ground beneath a point\r\n// Algorithm:\r\n// for each edge or each triangle\r\n//  find the midpoint of the edge\r\n//  for left and right sides\r\n//   check if there is a hole at either of 0.000001, 0.0001, 0.1, 1.0 inches away (perp to edge)\r\n//\t if hole, then check six feet away\r\n//     if collision six feet away, then we classify this as a hole, and flag it in the level \r\n//\t\t                                (flag the edge, and the point with a hole)\r\n//\r\n// Note: the checks encompass the whole world, not just this sector\r\n#ifdef\t__DEBUG_CODE__\r\n\r\nbool CheckEdgeAt(Mth::Vector& mid, Mth::Vector& left, float dist, CFeeler& feeler)\r\n{\r\n\r\n\tfloat up = 1000.0f;\r\n\r\n/*\r\n\t// if we are next to a wall, then we need to check from a much greater height\r\n\tfeeler.SetLine(mid + left * 10.0f + up, mid - left * 10.0f + up);\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tup = 1000.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// need to check for wall from both directions, I think\r\n\t\tfeeler.FlipDirection();\r\n\t\tif (feeler.GetCollision())\r\n\t\t{\r\n\t\t\tup = 1000.0f;\t\t\r\n\t\t}\r\n\t}\r\n*/\r\n\t\r\n\tfeeler.SetLine(mid + left * dist + Mth::Vector(0.0f,up,0.0f),\r\n\t\t\t\t   mid + left * dist + Mth::Vector(0.0f,-1000.0f,0.0f));\r\n//\t\t\t\t   mid + left * dist + Mth::Vector(0.0f,-5800.0f,0.0f));\r\n\t\t\t\t   \r\n//\tfeeler.DebugLine(0,255,0);\t\t\t\t   \r\n\t\t\t\t   \r\n\treturn feeler.GetCollision(false);\t\r\n}\t\t\t\t\t\t\t\t\t  \r\n\t\t\t\t\t\t\t\t\t  \r\nvoid\t\t\tCheckEdgeForHoles(Mth::Vector v0, Mth::Vector v1)\r\n{\r\n\tMth::Vector\tmid = (v0 + v1) / 2.0f;\r\n\tMth::Vector left = v1 - v0;\r\n\tleft.Normalize();\r\n\tif (left[X] == 0.0f && left[Z] == 0.0f)\r\n\t{\r\n\t\t// edge is perfectly vertical, so return\r\n\t\treturn;\r\n\t}\r\n\r\n\t// make left vector be at right angles to the edge in the XZ plane\t\r\n\tfloat x = left[X];\r\n\tleft[X] = left[Z];\r\n\tleft[Z] = -x;\r\n\tleft[Y] = 0;\r\n\r\n\tCFeeler\tfeeler;\r\n\t\r\n\t// first check six feet away, to eliminate around the edge of the level \r\n\r\n\tif (!CheckEdgeAt(mid, left, 72.0f,feeler))\r\n\t{\r\n\t\t// hole six feet away, so return\r\n//\t\tGfx::AddDebugLine(mid+left*60.0f, mid+left*60.0f * 10.0f,0xff0000);\r\n\t\treturn;\r\n\t}\r\n\r\n\r\n\tfor (float x = 0.001f; x<0.0015f; x *= 10.0f)   // does 0.001, 0.01, 0.10\r\n\t{\r\n\t\tif (!CheckEdgeAt(mid,left,x,feeler))\r\n\t\t{\r\n\t\t\t// Found a hole!!!\r\n\t\t\t// we draw bunch of lines of differning length, so we can see it when we zoom in\r\n\t\t\t\r\n\t\t\tGfx::AddDebugLine(v0, v1,0xff00ff);  // magenta = bad edge\r\n\r\n//\t\t\tfeeler.DebugLine(0,0,255);\t\t\t// blue = actual collision line\t\t\t\r\n\t\t\tGfx::AddDebugLine(mid+left*x, mid+left*x + Mth::Vector(0,40,0),0xffff);  \r\n\t\t\tGfx::AddDebugLine(mid+left*x, mid+left*x + Mth::Vector(0,200,0),0xffff); \r\n\t\t\tGfx::AddDebugLine(mid+left*x, mid+left*x + Mth::Vector(0,1000,0),0xffff);\r\n\t\t}\r\n\t}\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollObjTriData::CheckForHoles()\r\n{\r\n\r\n\tprintf (\"\\nChecking for unvelded verts in object with %d verts\\n\",m_num_verts);\r\n\r\n\tfor (int i=0;i<m_num_verts-1;i++)\r\n\t{\r\n\t\tfor (int j = i+1; j<m_num_verts;j++)\r\n\t\t{\r\n\t\t\tfloat len = (GetRawVertexPos(i)-GetRawVertexPos(j)).LengthSqr();\r\n\t\t\tif ( len >0.0000001f && len < 0.1f)\r\n\t\t\t{\r\n\t\t\t\r\n#ifndef __PLAT_NGC__\r\n\t\t\t\tGfx::AddDebugLine(GetRawVertexPos(i), GetRawVertexPos(i) + Mth::Vector(0,400,0),0xff00ff);  \r\n\t\t\t\tGfx::AddDebugLine(GetRawVertexPos(i), GetRawVertexPos(i) + Mth::Vector(0,40,0),0xff00ff);  \r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\t\tprintf (\"Found one, at dist %f,m check the magenta lines\\n\",len);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\r\n\tprintf (\"Then Checking for holes in object with %d faces\\n\",m_num_faces);\r\n\tfor (int fidx = 0; fidx < m_num_faces; fidx++)\r\n\t{\r\n\t\t\r\n\t\tSFaceInfo *face = get_face_info(fidx);\r\n\t\tif (!(face->m_flags & mFD_NON_COLLIDABLE))\r\n\t\t{\r\n\t\t\tCheckEdgeForHoles(GetRawVertexPos(GetFaceVertIndex(fidx, 0)),GetRawVertexPos(GetFaceVertIndex(fidx, 1)));\r\n\t\t\tCheckEdgeForHoles(GetRawVertexPos(GetFaceVertIndex(fidx, 1)),GetRawVertexPos(GetFaceVertIndex(fidx, 2)));\r\n\t\t\tCheckEdgeForHoles(GetRawVertexPos(GetFaceVertIndex(fidx, 2)),GetRawVertexPos(GetFaceVertIndex(fidx, 0)));\r\n\t\t}\r\n\t}\r\n\r\n}\r\n#endif\r\n\r\n} // namespace Nx\r\n\r\n"
  },
  {
    "path": "Code/Gel/Collision/CollTriData.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNx\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCollTriData.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t02/27/2002\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__GEL_COLLTRIDATA_H\r\n#define\t__GEL_COLLTRIDATA_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n\r\n#include <gfx/Image/ImageBasic.h>\r\n\r\n#include <gel/collision/collenums.h>\r\n\r\n#ifdef __PLAT_NGC__\r\n#include <sys/ngc/p_vector.h>\r\n#include <sys/ngc/p_gx.h>\r\n#endif\r\n\r\n#include <gfx/nxscene.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Precision for fixed point split point value\r\n#define COLLISION_SUB_INCH_PRECISION 16.0f\r\n#define COLLISION_RECIPROCAL_SUB_INCH_PRECISION 0.0625f\r\n\r\nnamespace Nx\r\n{\r\n\r\nclass CCollStatic;\r\nclass CCollMovable;\r\nclass CCollStaticTri;\r\nclass CCollMovTri;\r\nclass CCollObjTriData;\r\nstruct CollData;\r\nclass CBatchTriCollMan;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n////////////////////////////////////////////////////////////////\r\n// Axis-Aligned BSP tree node\r\n//\r\nclass CCollBSPNode\r\n{\r\npublic:\r\n\t\t\t\t\t\tCCollBSPNode();\r\n\r\n\t// These functions allow us to have \"virtual\" functionality with an instance.  We can safely\r\n\t// cast a pointer to CCollBSPLeaf if isLeaf() returns true.\r\n\tuint8\t\t\t\tGetSplitAxis() const { return m_leaf.m_split_axis & 0x3; }\r\n\tvoid\t\t\t\tSetSplitAxis(int axis);\r\n\tbool\t\t\t\tIsNode() const { return (GetSplitAxis() != 3); }\r\n\tbool\t\t\t\tIsLeaf() const { return (GetSplitAxis() == 3); }\r\n\r\n\tCCollBSPNode *\t\tGetLessBranch() { Dbg_Assert(IsNode()); return m_node.m_children.GetLessBranch(); }\r\n\tCCollBSPNode *\t\tGetGreaterBranch() { Dbg_Assert(IsNode()); return m_node.m_children.GetGreaterBranch(); }\r\n\r\n\tFaceIndex *\t\t\tGetFaceIndexArray() { Dbg_Assert(IsLeaf()); return m_leaf.mp_face_idx_array; }\r\n\r\n\tint\t\t\t\t\tGetSplitPoint() const { return m_node.m_split_point >> NUM_AXIS_BITS; }\r\n\tvoid\t\t\t\tSetSplitPoint(int ipoint) { m_node.m_split_point = (ipoint << NUM_AXIS_BITS) | GetSplitAxis(); }\r\n\tfloat\t\t\t\tGetFSplitPoint() const { return ((float) GetSplitPoint()) * COLLISION_RECIPROCAL_SUB_INCH_PRECISION; }\r\n\tvoid\t\t\t\tSetFSplitPoint(float point) { SetSplitPoint(point * COLLISION_SUB_INCH_PRECISION); }\r\n\r\nprivate:\r\n\t////////////////////////////////////////////////////////////////\r\n\t// Basically, a class for a pointer that uses the lowest two bits for flags.\r\n\t// It also assumes that the pointer points to two consecutive nodes: the left\r\n\t// node and the right node.\r\n\t//\r\n\tclass CCollBSPChildren\r\n\t{\r\n\tpublic:\r\n\r\n\t\tvoid\t\t\tInit() { m_left_child_and_flags = 0; }\r\n\r\n\t\t// Actual branches\r\n\t\tCCollBSPNode *\tGetLeftBranch() const { return GetBasePointer(); }\r\n\t\tCCollBSPNode *\tGetRightBranch() const { return GetBasePointer() + 1; }\r\n\r\n\t\t// Figures out which branch is which\r\n\t\tCCollBSPNode *\tGetLessBranch() const { return IsLeftGreater() ? GetRightBranch() : GetLeftBranch(); }\r\n\t\tCCollBSPNode *\tGetGreaterBranch() const { return IsLeftGreater() ? GetLeftBranch() : GetRightBranch(); }\r\n\r\n\t\t// These two are needed for the cloning function\r\n\t\tCCollBSPNode *\tGetBasePointer() const { return (CCollBSPNode *) (m_left_child_and_flags & ~0x3); }\r\n\t\tvoid\t\t\tSetBasePointer(CCollBSPNode *p_base) { m_left_child_and_flags = ((uint32) p_base) | (m_left_child_and_flags & 0x3); }\r\n\r\n\t\tbool\t\t\tIsLeftGreater() const { return m_left_child_and_flags & mLEFT_IS_GREATER; }\r\n\t\tvoid\t\t\tSetLeftGreater(bool greater);\r\n\r\n\tprivate:\r\n\r\n\t\t// Constants\r\n\t\tenum\r\n\t\t{\r\n\t\t\tmLEFT_IS_GREATER = 0x01,\t\t\t// Indicates that the left branch is the greater branch\r\n\t\t};\r\n\r\n\t\tuint32\t\t\tm_left_child_and_flags; // points to left branch, right branch one node over\r\n\t};\t\t\r\n\r\nprotected:\r\n\r\n   \t// Constants\r\n\tenum\r\n\t{\r\n\t\tNUM_AXIS_BITS = 2,\t\t\t// Number of bits used in fixed split_point for the axis identification\r\n\t};\r\n\r\n\t\t\t\t\t\t~CCollBSPNode();\r\n\r\n\t// m_split axis must always be in line with the low byte of m_split_point\r\n\tstruct SNode\r\n\t{\r\n\t\tint32\t\t\t\tm_split_point;\t\t// the point on the axis (low 2 bits is the axis itself)\r\n\t\tCCollBSPChildren\tm_children;\t\t\t// 32-bit value points to left branch, right branch one node over\r\n\t};\r\n\r\n\tstruct SLeaf\r\n\t{\r\n#ifdef __PLAT_NGC__\t\t// Big endian on NGC\r\n\t\tuint16\t\t\t\tm_num_faces;\t\t// number in faces in face array\r\n\t\tuint8\t\t\t\tm_pad1;\r\n\t\tuint8\t\t\t\tm_split_axis;\t\t// the axis it is split on (0 = X, 1 = Y, 2 = Z, 3 = Leaf)\r\n#else\r\n\t\tuint8\t\t\t\tm_split_axis;\t\t// the axis it is split on (0 = X, 1 = Y, 2 = Z, 3 = Leaf)\r\n\t\tuint8\t\t\t\tm_pad1;\r\n\t\tuint16\t\t\t\tm_num_faces;\t\t// number in faces in face array\r\n#endif __PLAT_NGC__\r\n\t\tFaceIndex *\t\t\tmp_face_idx_array;\t// leaf\r\n\t};\r\n\r\n\t// Clone functions\r\n\tCCollBSPNode *\t\tclone(bool instance = false);\r\n\tint\t\t\t\t\tcount_bsp_nodes();\r\n\tint\t\t\t\t\tcount_bsp_face_indices();\r\n\tFaceIndex *\t\t\tfind_bsp_face_index_array_start();\r\n\r\n\t// Modify functions\r\n\tvoid\t\t\t\ttranslate(const Mth::Vector & delta_trans);\t\t// delta since we don't store the original pos\r\n\tvoid\t\t\t\trotate_y(const Mth::Vector & world_origin, Mth::ERot90 rot_y, bool root_node = true);\r\n\tvoid\t\t\t\tscale(const Mth::Vector & world_origin, const Mth::Vector & scale, bool root_node = true);\r\n\r\n\t// The split axis data MUST be in the same place in both SNode and SLeaf\r\n\tunion\r\n\t{\r\n\t\tSNode\t\t\tm_node;\r\n\t\tSLeaf\t\t\tm_leaf;\r\n\t};\r\n\r\n\t// Friends\r\n\tfriend CCollObjTriData;\r\n};\r\n\r\n#ifndef __PLAT_NGC__\r\n#define FIXED_POINT_VERTICES\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n////////////////////////////////////////////////////////////////\r\n// Collision data for an object\r\n//\r\nclass CCollObjTriData\r\n{\r\npublic:\r\n\t////////////////////////////////////////////////////////////\r\n\t// The following structure represent the disk format of\r\n\t// the collision data with the correct padding.  If the\r\n\t// disk format changes, these structures MUST change, too.\r\n\t//\r\n   \tstruct SReadHeader\r\n\t{\r\n\t\tint \tm_version;\r\n\t\tint \tm_num_objects;\r\n\t\tint \tm_total_num_verts;\r\n#ifdef __PLAT_NGC__\r\n\t\tint \tm_total_num_faces;\r\n#else\r\n\t\tint \tm_total_num_faces_large;\r\n\t\tint \tm_total_num_faces_small;\r\n\t\tint\t\tm_total_num_verts_large;\r\n\t\tint\t\tm_total_num_verts_small;\r\n\t\tint\t\tm_pad3;\r\n#endif\r\n\t};\r\n\r\n\t//\r\n\t\t\t\t\t\tCCollObjTriData();\r\n\t\t\t\t\t\t~CCollObjTriData();\r\n\r\n\tbool\t\t\t\tInitCollObjTriData(CScene * p_scene, void *p_base_vert_addr, void *p_base_intensity_addr, // Init collision sector after read from file\r\n\t\t\t\t\t\t\t\t\t\t   void *p_base_face_addr, void *p_base_node_addr, void *p_base_face_idx_addr);\r\n\tbool\t\t\t\tInitBSPTree();\t\t\t\t\t// Generate the BSP Tree\r\n\tbool\t\t\t\tDeleteBSPTree();\t\t\t\t// Delete the BSP Tree\r\n\r\n\tuint32\t\t\t\tGetChecksum() const;\r\n\tvoid\t\t\t\tSetChecksum(uint32 checksum);\t// For cloning\r\n\tuint16\t\t\t\tGetSectorFlags() const;\r\n\tvoid\t\t\t\tSetSectorFlags(uint16 flags);\r\n\tvoid\t\t\t\tClearSectorFlags(uint16 flags);\r\n\tconst Mth::CBBox &\tGetBBox() const;\r\n\tint\t\t\t\t\tGetNumVerts() const;\r\n\tint\t\t\t\t\tGetNumFaces() const;\r\n\r\n\t// Vertex functions\r\n#ifdef __PLAT_NGC__\r\n\tconst unsigned char GetVertexIntensity(int face_idx, int vert_idx) const;\r\n\tvoid\t\t\t\tSetVertexIntensity(int face_idx, int vert_idx, unsigned char intensity);\r\n\r\n\tvoid\t\t\t\tSetVertexPointer( NsVector * p_vertex ) { mp_raw_vert_pos = p_vertex; }\r\n\tNsVector *\t\t\tGetVertexPointer() { return mp_raw_vert_pos; }\r\n#else\r\n\tconst unsigned char GetVertexIntensity(int vert_idx) const;\r\n\tvoid\t\t\t\tSetVertexIntensity(int vert_idx, unsigned char intensity);\r\n#endif\t\t//__PLAT_NGC__ \r\n\r\n\t// Face functions\r\n\tuint16\t\t\t\tGetFaceTerrainType(int face_idx) const;\r\n\tuint32\t\t\t\tGetFaceFlags(int face_idx) const;\r\n\tuint16\t\t\t\tGetFaceVertIndex(int face_idx, int vert_num) const;\r\n\tconst Mth::Vector \tGetFaceNormal(int face_idx) const;\r\n\tMth::Vector\t\t\tGetRawVertexPos(int vert_idx) const;\t\t// Must copy data for fixed point\r\n\tvoid\t\t\t\tGetRawVertexPos(int vert_idx, Mth::Vector & pos) const;\r\n\tvoid\t\t\t\tSetRawVertexPos(int vert_idx, const Mth::Vector & pos);\r\n\tvoid\t\t\t\tGetRawVertices(Mth::Vector *p_vert_array) const;\r\n\tvoid\t\t\t\tSetRawVertices(const Mth::Vector *p_vert_array);\r\n\r\n\t// Collision functions\r\n\tFaceIndex *\t\t\tFindIntersectingFaces(const Mth::CBBox & line_bbox, uint & num_faces);\r\n\r\n\t// Clone and move functions\r\n\tCCollObjTriData *\tClone(bool instance = false, bool skip_no_verts = false);\r\n\tvoid\t\t\t\tTranslate(const Mth::Vector & delta_trans);\t\t// delta since we don't store the original pos\r\n\tvoid\t\t\t\tRotateY(const Mth::Vector & world_origin, Mth::ERot90 rot_y);\r\n\tvoid\t\t\t\tScale(const Mth::Vector & world_origin, const Mth::Vector & scale);\r\n\r\n\tvoid\t\t\t\tProcessOcclusion();\r\n\r\n\t// Debug functions\r\n\tvoid\t\t\t\tDebugRender(uint32 ignore_1, uint32 ignore_0);\r\n\tvoid\t\t\t\tDebugRender2D(uint32 ignore_1, uint32 ignore_0, uint32 visible);\r\n\tvoid\t\t\t\tDebugRender2DBBox(uint32 ignore_1, uint32 ignore_0, uint32 visible);\r\n\tvoid\t\t\t\tDebugRender2DOct(uint32 ignore_1, uint32 ignore_0, uint32 visible);\r\n\tvoid\t\t\t\tDebugRender(const Mth::Matrix & transform, uint32 ignore_1, uint32 ignore_0, bool do_transfrom = true);\r\n\tvoid\t\t\t\tCheckForHoles();\r\n\r\n\t// Element size functions for init\r\n\tstatic uint\t\t\tGetVertElemSize();\r\n\tstatic uint\t\t\tGetVertSmallElemSize();\r\n\tstatic uint\t\t\tGetFaceElemSize();\r\n\tstatic uint\t\t\tGetFaceSmallElemSize();\r\n\r\nprotected:\r\n\t//////////////////////////////////////////////////\r\n\t// All of the following member variables and structures\r\n\t// match the output of SceneConv.exe EXACTLY.\r\n\t// Do not change these without changing SceneConv.\r\n\r\n\t//////////////////////////////////////////////////\r\n\t// Internal structures for the faces (note its size isn't a qword multiple)\r\n\tstruct SFaceInfo\r\n\t{\r\n\t\tuint16\t\t\tm_flags;\t\t\t\t// collision attributes\r\n\t\tuint16\t\t\tm_terrain_type;\t\t\t// terrain type\r\n\t};\r\n\r\n\t// Everything in SFace and SFaceSmall before the vert indexes MUST be the same.\r\n\tstruct SFace\r\n\t{\r\n\t\tSFaceInfo\t\tm_info;\t\t\t\t\t// face info\r\n\t\tFaceIndex\t\tm_vertex_index[3];\t\t// indexes into the corresponding vertex array\r\n\t};\r\n\r\n\tstruct SFaceSmall\r\n\t{\r\n\t\tSFaceInfo\t\tm_info;\t\t\t\t\t// face info\r\n\t\tFaceByteIndex\tm_vertex_index[3];\t\t// indexes into the corresponding vertex array\r\n#ifndef __PLAT_NGC__\r\n\t\tuint8\t\t\tm_pad;\r\n#endif\t\t// __PLAT_NGC__\r\n\t};\r\n\r\n\t// Use this structure to shove the rgba value into the W value of a Vector\r\n\tstruct SOverlay\r\n\t{\r\n\t\tuint32\t\t\tm_dont_touch_X;\t\t\t// equivalent to Mth::Vector X\r\n\t\tuint32\t\t\tm_dont_touch_Y;\t\t\t// equivalent to Mth::Vector Y\r\n\t\tuint32\t\t\tm_dont_touch_Z;\t\t\t// equivalent to Mth::Vector Z\r\n\t\tuint8\t\t\tm_type;\t\t\t\t\t// equivalent to Mth::Vector W\r\n\t\tuint8\t\t\tm_intensity;\r\n\t\tuint8\t\t\tm_pad[2];\r\n\t};\r\n\r\n\t// This structure is used for 16-bit fixed point vertices\r\n\tstruct SFloatVert\r\n\t{\r\n\t\tfloat\t\t\tm_pos[3];\r\n//\t\tuint8\t\t\tm_type;\r\n//\t\tuint8\t\t\tm_intensity;\r\n//\t\tuint8\t\t\tm_pad[2];\r\n\t};\r\n\r\n\t// This structure is used for 16-bit fixed point vertices\r\n\tstruct SFixedVert\r\n\t{\r\n\t\tuint16\t\t\tm_pos[3];\t\t\t// Relative to min point of bounding box\r\n//\t\tuint8\t\t\tm_pad;\r\n//\t\tuint8\t\t\tm_intensity;\r\n\t};\r\n\r\n\t//////////////////////////////////////////////////\r\n\t// Members\r\n\tuint32\t\t\t\tm_checksum;\t\t\t// checksum of sector\r\n\tuint16\t\t\t\tm_Flags;\t\t\t// Sector-level flags\r\n\tuint16\t\t\t\tm_num_verts;\r\n\tuint16\t\t\t\tm_num_faces;\r\n\tuint8\t\t\t\tm_use_face_small;\t// Set to 1 if using SFaceSmall below\r\n\tuint8\t\t\t\tm_use_fixed_verts;\r\n\r\n\tunion {\r\n\t\tSFace *\t\t\tmp_faces;\t\t\t// array of faces\r\n\t\tSFaceSmall *\tmp_face_small;\t\t// array of small faces\r\n\t};\r\n\r\n\tMth::CBBox\t\t\tm_bbox;\t\t\t\t// bounding box of sector\r\n\r\n#ifdef __PLAT_NGC__\r\n\tNsVector *\t\t\tmp_raw_vert_pos;\r\n#else\r\n\tunion {\r\n#ifndef FIXED_POINT_VERTICES\r\n\t\tMth::Vector *\tmp_vert_pos;\t\t\t// array of 32-bit vertices\r\n\t\tSOverlay *\t\tmp_vert_rgba_overlay;\t// overlay array of vertex colors for 32-bit vertices\r\n#endif\r\n\t\tSFloatVert *\tmp_float_vert;\t\t\t// array of 32-bit vertices\r\n\t\tSFixedVert *\tmp_fixed_vert;\t\t\t// array of 16-bit vertices\r\n\t};\r\n#endif\r\n\r\n\tCCollBSPNode *\t\tmp_bsp_tree;\t\t// head of BSP tree\r\n\tuint8 *\t\t\t\tmp_intensity;\t\t// Intensity list\r\n#ifdef __PLAT_NGC__\r\n\tNsVector *\t\t\tmp_cloned_vert_pos;\r\n#else\r\n\tuint32\t\t\t\tm_pad1;\t\t\t\t// padding\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\tSFaceInfo *\t\t\tget_face_info(int face_idx) const;\r\n\r\nprivate:\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tMAX_FACE_INDICIES = 6000 //2048\r\n\t};\r\n\r\n\t// Gets and puts float data (converting to and from fixed point if necessary)\r\n\tvoid\t\t\t\tget_float_array_from_data(Mth::Vector *p_float_array) const;\r\n\tvoid\t\t\t\tput_float_array_into_data(const Mth::Vector *p_float_array);\r\n\r\n\tvoid\t\t\t\tset_vertex_pos(int vert_idx, const Mth::Vector & pos);\r\n\r\n\tCCollBSPNode *\t\tcreate_bsp_tree(const Mth::CBBox & bbox, FaceIndex *p_face_indexes, uint num_faces, uint level = 1);\r\n\tCCollBSPNode *\t\tcreate_bsp_leaf(FaceIndex *p_face_indexes, uint num_faces);\r\n\tbool\t\t\t\tcalc_split_faces(uint axis, float axis_distance, FaceIndex *p_face_indexes,\r\n\t\t\t\t\t\t\t\t\t\t uint num_faces, uint & less_faces, uint & greater_faces, \r\n\t\t\t\t\t\t\t\t\t\t FaceIndex *p_less_face_indexes = NULL, FaceIndex *p_greater_face_indexes = NULL);\r\n\r\n\tvoid\t\t\t\tfind_faces(CCollBSPNode *p_bsp_node, const Mth::CBBox & bbox);\t\t// recursively search for faces\r\n\r\n\tstatic bool\t\t\ts_init_tree(CCollBSPNode *p_tree, void *p_base_node_addr, void *p_base_face_idx_addr);\r\n\r\n\tstatic const uint\ts_max_face_per_leaf;// maximum number faces per leaf\r\n\tstatic const uint\ts_max_tree_levels;\t// maximum number of levels in a tree\r\n\r\n\tstatic FaceIndex\ts_face_index_buffer[MAX_FACE_INDICIES];\r\n\tstatic FaceIndex\ts_seq_face_index_buffer[MAX_FACE_INDICIES];\r\n\tstatic uint\t\t\ts_num_face_indicies;\r\n\r\n\t// Should be readable by all the CCollObj classes\r\n\tfriend CCollStatic;\r\n\tfriend CCollMovable;\r\n\tfriend CCollStaticTri;\r\n\tfriend CCollMovTri;\r\n\tfriend CBatchTriCollMan;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCCollObjTriData::SetChecksum(uint32 checksum)\r\n{\r\n\tm_checksum = checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint32\t\t\t\tCCollObjTriData::GetChecksum() const\r\n{\r\n\treturn m_checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline int\t\t\t\t\tCCollObjTriData::GetNumVerts() const\r\n{\r\n\treturn m_num_verts;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline int\t\t\t\t\tCCollObjTriData::GetNumFaces() const\r\n{\r\n\treturn m_num_faces;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::CBBox &\tCCollObjTriData::GetBBox() const\r\n{\r\n\treturn m_bbox;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint\t\t\t\t\tCCollObjTriData::GetVertElemSize()\r\n{\r\n#ifdef __PLAT_NGC__\r\n\treturn 1 * 3;\r\n#else\r\n#ifdef FIXED_POINT_VERTICES\r\n\treturn sizeof(SFloatVert);\r\n#else\r\n\treturn sizeof(Mth::Vector);\r\n#endif // FIXED_POINT_VERTICES\r\n#endif\t\t// __PLAT_NGC__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint\t\t\t\t\tCCollObjTriData::GetVertSmallElemSize()\r\n{\r\n\treturn sizeof(SFixedVert);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint\t\t\t\t\tCCollObjTriData::GetFaceElemSize()\r\n{\r\n\treturn sizeof(SFace);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint\t\t\t\t\tCCollObjTriData::GetFaceSmallElemSize()\r\n{\r\n\treturn sizeof(SFaceSmall);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint16\t\t\t\tCCollObjTriData::GetFaceTerrainType(int face_idx) const\r\n{\r\n\treturn (m_use_face_small) ? mp_face_small[face_idx].m_info.m_terrain_type : mp_faces[face_idx].m_info.m_terrain_type;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint32\t\t\t\tCCollObjTriData::GetFaceFlags(int face_idx) const\r\n{\r\n\treturn (m_use_face_small) ? mp_face_small[face_idx].m_info.m_flags : mp_faces[face_idx].m_info.m_flags;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint16\t\t\t\tCCollObjTriData::GetFaceVertIndex(int face_idx, int vert_num) const\r\n{\r\n\treturn (m_use_face_small) ? mp_face_small[face_idx].m_vertex_index[vert_num] : mp_faces[face_idx].m_vertex_index[vert_num];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Mth::Vector\t\t \tCCollObjTriData::GetRawVertexPos(int vert_idx) const\r\n{\r\n#if !defined(FIXED_POINT_VERTICES)\r\n\r\n#ifdef __PLAT_NGC__\r\n\tMth::Vector v;\r\n\r\n\tif ( mp_cloned_vert_pos )\r\n\t{\r\n\t\tv[X] = mp_cloned_vert_pos[vert_idx].x;\r\n\t\tv[Y] = mp_cloned_vert_pos[vert_idx].y;\r\n\t\tv[Z] = mp_cloned_vert_pos[vert_idx].z;\r\n\t\tv[W] = 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tv[X] = mp_raw_vert_pos[vert_idx].x;\r\n\t\tv[Y] = mp_raw_vert_pos[vert_idx].y;\r\n\t\tv[Z] = mp_raw_vert_pos[vert_idx].z;\r\n\t\tv[W] = 0.0f;\r\n\t}\r\n\r\n\treturn v;\r\n#else\r\n\treturn mp_vert_pos[vert_idx];\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n#else\r\n\r\n\tif (m_use_fixed_verts)\r\n\t{\r\n\t\tMth::Vector pos(m_bbox.GetMin());\r\n\r\n\t\tpos[X] += ((float) mp_fixed_vert[vert_idx].m_pos[X]) * COLLISION_RECIPROCAL_SUB_INCH_PRECISION;\r\n\t\tpos[Y] += ((float) mp_fixed_vert[vert_idx].m_pos[Y]) * COLLISION_RECIPROCAL_SUB_INCH_PRECISION;\r\n\t\tpos[Z] += ((float) mp_fixed_vert[vert_idx].m_pos[Z]) * COLLISION_RECIPROCAL_SUB_INCH_PRECISION;\r\n\t\tpos[W]\t= 0.0f;\r\n\r\n\t\treturn pos;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMth::Vector pos(Mth::Vector::NO_INIT);\r\n\t\tpos[X]\t\t\t= mp_float_vert[vert_idx].m_pos[X];\r\n\t\tpos[Y]\t\t\t= mp_float_vert[vert_idx].m_pos[Y];\r\n\t\tpos[Z]\t\t\t= mp_float_vert[vert_idx].m_pos[Z];\r\n\t\tpos[W]\t\t\t= 0.0f;\r\n\t\treturn pos;\r\n\t}\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCCollObjTriData::GetRawVertexPos(int vert_idx, Mth::Vector & pos) const\r\n{\r\n#ifdef __PLAT_NGC__\r\n\r\n\tif ( mp_cloned_vert_pos )\r\n\t{\r\n\t\tpos[X] = mp_cloned_vert_pos[vert_idx].x;\r\n\t\tpos[Y] = mp_cloned_vert_pos[vert_idx].y;\r\n\t\tpos[Z] = mp_cloned_vert_pos[vert_idx].z;\r\n\t\tpos[W] = 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpos[X] = mp_raw_vert_pos[vert_idx].x;\r\n\t\tpos[Y] = mp_raw_vert_pos[vert_idx].y;\r\n\t\tpos[Z] = mp_raw_vert_pos[vert_idx].z;\r\n\t\tpos[W] = 0.0f;\r\n\t}\r\n#else\r\n\tif (m_use_fixed_verts)\r\n\t{\r\n\t\tpos = m_bbox.GetMin();\r\n\t\tpos[X] += ((float) mp_fixed_vert[vert_idx].m_pos[X]) * COLLISION_RECIPROCAL_SUB_INCH_PRECISION;\r\n\t\tpos[Y] += ((float) mp_fixed_vert[vert_idx].m_pos[Y]) * COLLISION_RECIPROCAL_SUB_INCH_PRECISION;\r\n\t\tpos[Z] += ((float) mp_fixed_vert[vert_idx].m_pos[Z]) * COLLISION_RECIPROCAL_SUB_INCH_PRECISION;\r\n\t\tpos[W]\t= 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n#ifdef FIXED_POINT_VERTICES\r\n\t\tpos[X]\t= mp_float_vert[vert_idx].m_pos[X];\r\n\t\tpos[Y]\t= mp_float_vert[vert_idx].m_pos[Y];\r\n\t\tpos[Z]\t= mp_float_vert[vert_idx].m_pos[Z];\r\n#else\r\n\t\tpos\t\t= mp_vert_pos[vert_idx];\r\n#endif\r\n\t\tpos[W]\t= 0.0f;\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef __PLAT_NGC__\r\ninline const unsigned char CCollObjTriData::GetVertexIntensity(int face_idx, int vert_idx) const\r\n{\r\n\treturn mp_intensity[(face_idx * 3) + vert_idx];\r\n}\r\n#else\r\ninline const unsigned char CCollObjTriData::GetVertexIntensity(int vert_idx) const\r\n{\r\n#ifdef FIXED_POINT_VERTICES\r\n\treturn mp_intensity[vert_idx];\r\n\t//if (m_use_fixed_verts)\r\n\t//{\r\n\t//\treturn mp_fixed_vert[vert_idx].m_intensity;\r\n\t//}\r\n\t//else\r\n\t//{\r\n\t//\treturn mp_float_vert[vert_idx].m_intensity;\r\n\t//}\r\n#else\r\n\t{\r\n\t\treturn mp_vert_rgba_overlay[vert_idx].m_intensity;\r\n\t}\r\n#endif // FIXED_POINT_VERTICES\r\n}\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef __PLAT_NGC__\r\ninline void\t\t\t\t\tCCollObjTriData::SetVertexIntensity(int face_idx, int vert_idx, unsigned char intensity)\r\n{\r\n\tmp_intensity[(face_idx * 3) + vert_idx] = intensity; \r\n}\r\n#else\r\ninline void\t\t\t\t\tCCollObjTriData::SetVertexIntensity(int vert_idx, unsigned char intensity)\r\n{\r\n#ifdef FIXED_POINT_VERTICES\r\n\tmp_intensity[vert_idx] = intensity;\r\n\t//if (m_use_fixed_verts)\r\n\t//{\r\n\t//\tmp_fixed_vert[vert_idx].m_intensity = intensity;\r\n\t//}\r\n\t//else\r\n\t//{\r\n\t//\tmp_float_vert[vert_idx].m_intensity = intensity;\r\n\t//}\r\n#else\r\n\t{\r\n\t\tmp_vert_rgba_overlay[vert_idx].m_intensity = intensity;\r\n\t}\r\n#endif // FIXED_POINT_VERTICES\r\n}\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline CCollObjTriData::SFaceInfo *\tCCollObjTriData::get_face_info(int face_idx) const\r\n{\r\n\treturn (m_use_face_small) ? &(mp_face_small[face_idx].m_info) : &(mp_faces[face_idx].m_info);\r\n}\r\n\r\n} // namespace Nx\r\n\r\n#endif  //\t__GEL_COLLTRIDATA_H\r\n"
  },
  {
    "path": "Code/Gel/Collision/Collision.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNx\t\t\t\t\t\t\t\t \t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel\\collision\\collide.cpp      \t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/20/02\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gel/collision/collision.h>\r\n#include <gel/collision/colltridata.h>\r\n#include <gel/collision/movcollman.h>\r\n#include <gel/collision/collcache.h>\r\n#include <gel/collision/batchtricoll.h>\r\n#include <engine/SuperSector.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/nxflags.h>\t// for face flag stuff\r\n#include <gfx/debuggfx.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#define USE_VU0_MICROMODE\r\n#endif\r\n\r\n#define PRINT_CACHE_HITS 0\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nMth::Matrix\t\tCCollStatic::sOrient;\r\nMth::Vector\t\tCCollStatic::sWorldPos;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic bool s_check_for_far = false;\t\t\t// if true then we return the farthest result\r\n\r\nbool CCollObj::s_found_collision(const Mth::Line *p_is, CCollObj *p_coll_object, SCollSurface *p_collSurface,\r\n\t\t\t\t\t\t\t\t float distance, CollData *p_collData)\r\n{\r\n\tDbg_Assert( p_collData );\r\n\t\r\n\tbool good = false;\r\n\tbool updated = false;\r\n\r\n\tif (s_check_for_far)\r\n\t{\r\n\t\tif( distance >= p_collData->dist )\r\n\t\t{\r\n\t\t\tgood = true;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//Dbg_Message(\"Checking new dist %f against old dist %f\", distance, p_collData->dist);\r\n\t\tif( distance <= p_collData->dist )\r\n\t\t{\r\n\t\t\tgood = true;\r\n\t\t}\r\n\t}\r\n\tCollData \told;\r\n\t\r\n\t\r\n\tif (!good)\r\n\t{\r\n\t\told = *p_collData;\t\t\t\t \r\n\t}\r\n\t\t\t \r\n\r\n\t// Get the user plugin offset\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tint index = p_collSurface->index;\t\t// the index of the surface in the object\r\n\t\r\n\t// get the face flags from within this\r\n\t// note that this uses the \"index\" field, which is\r\n\t// an index of a face within the sector\r\n\tuint32  flags = p_coll_object->GetFaceFlags(index);\r\n\t\r\n\t// Test flags against the ignore_1 (ignore if a bit is set in flags)\r\n\t// and against ignore_0 (ignore if the bit is clear in flags)\r\n\t\t\t\t\t\r\n\t//Dbg_Message(\"*Flags %x ignore_0 %x ignore_1 %x\", flags, p_collData->ignore_0, p_collData->ignore_1);\r\n\tif (!(flags & p_collData->ignore_1) && !(~flags & p_collData->ignore_0))\r\n\t{\r\n\t\t// Setup the collData members\t\t\r\n\t\t\r\n\t\tp_collData->coll_found = true;     \t\t// found at least one (might be overrridden, but found at least one)\r\n\t\tp_collData->surface = *p_collSurface;\t// Store the collision surface\r\n\t\tp_collData->dist = distance;\t\t\t// set distance (will end up being the smallest dist)\r\n\t\tp_collData->flags = flags; \t\t\t\t// Store face flags\r\n\t\tp_collData->terrain = (ETerrainType) p_coll_object->GetFaceTerrainType(index);\r\n\t\tp_collData->p_coll_object = p_coll_object;\r\n\t\tp_collData->trigger = (flags& mFD_TRIGGER);\t// set flag if it's a trigger\r\n\r\n\t\tp_collData->node_name =  p_coll_object->GetChecksum();\r\n\t\t// Determine the point of intersection on the triangle\r\n\t\t// which will be in the direction of the line's vector at \"distance\" length\r\n\t\tMth::Vector coll_point, line_vec;\r\n\t\tline_vec = p_is->m_end - p_is->m_start;\r\n\r\n\t\tcoll_point = line_vec.Scale(distance);\r\n\t\tcoll_point = p_is->m_start + coll_point;\r\n\t\tcoll_point[W] = 1.0f;\t\t\t\t\t// Hack to force into homogenious space.  Even though the math is correct here,\r\n\t\t\t\t\t\t\t\t\t\t\t\t// many times the line data fed to it isn't.\r\n\t\tp_collData->surface.point = coll_point;\t// After looking at their implementation, I don't\r\n\t\t\t\t\t\t\t\t\t\t\t\t// trust \"point\" so I recalculate it\r\n\r\n\t\t// check for additional per-face callback\r\n\t\t\r\n\t\tif (p_collData->callback)\r\n\t\t{\r\n\t\t\t// call the callback function, and pass it this col data \r\n\t\t\tp_collData->callback(p_collData);\r\n\t\t}\r\n\t\r\n\t\tupdated = true;\r\n\t}\r\n\t\t\r\n\tif (!good)\r\n\t{\r\n\t\t*p_collData = old;\t\t\t\t \r\n\t}\r\n\r\n\treturn (good && updated);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCollObj::sRayTriangleCollision(const Mth::Vector *rayStart, const Mth::Vector *rayDir,\r\n\t\t\t\t\t\t\t\t\t Mth::Vector *v0, Mth::Vector *v1, Mth::Vector *v2, float *t)\r\n{\r\n#if 0\r\n// #ifdef\t__PLAT_NGPS__\r\n// Turned off assem versions to test correction to false positive issue as discussed in C code below.  Dan - 1/21/3\r\n#ifdef\tUSE_VU0_MICROMODE\r\n\tregister bool result;\r\n\r\n\tasm __volatile__(\r\n\t\"\r\n\t.set noreorder\r\n\tlqc2    vf06,%4\t\t\t\t# v0\r\n\tlqc2    vf08,%6\t\t\t\t# v2\r\n\tlqc2    vf07,%5\t\t\t\t# v1\r\n\tlqc2    vf04,%2\t\t\t\t# rayStart\r\n\tlqc2    vf05,%3\t\t\t\t# rayDir\r\n\r\n\tvcallms\tRayTriangleCollision\t# call microsubroutine\r\n\tvnop\t\t\t\t\t\t\t# interlocking instruction, waits for vu0 completion\r\n\r\n\tcfc2\t%0,$vi02\t\t\t# get boolean result from vu0\r\n\r\n\tbeq\t\t%0, $0, vu0RayTriDone\t# skip copy of t if not needed\r\n\tnop\r\n\r\n\tqmfc2\t$12, $vf17\t\t\t# move t to $8\r\n\tsw\t\t$12, %1\t\t\t\t# and write out\r\n\r\nvu0RayTriDone:\r\n\r\n\t.set reorder\r\n\t\": \"=&r\" (result), \"=m\" (*t) : \"m\" (*rayStart), \"m\" (*rayDir), \"m\" (*v0), \"m\" (*v1) , \"m\" (*v2) : \"$12\" );\r\n\r\n\treturn result;\r\n#else\r\n    //*t = 2.0f;\r\n\tbool result;\r\n\r\n\tasm __volatile__(\r\n\t\"\r\n\t.set noreorder\r\n\tlqc2    vf06,0x0(%4)\t\t# v0\r\n\tlqc2    vf08,0x0(%6)\t\t# v2\r\n\tlqc2    vf07,0x0(%5)\t\t# v1\r\n\tlqc2    vf04,0x0(%2)\t\t# rayStart\r\n\tlqc2    vf05,0x0(%3)\t\t# rayDir\r\n\r\n\tvsub.xyz vf10, vf08, vf06    # edge2 = v2 - v0\r\n\tvsub.xyz vf09, vf07, vf06    # edge1 = v1 - v0 \r\n\tvsub.xyz vf13, vf04, vf06    # tvec = rayStart - v0\r\n   \tli.s     $f4,0.00001\t\t # EPSILON\r\n\tvaddw.x  vf02, vf00, vf00w   # Load 1.0f to VF02x\r\n\r\n\tvopmula.xyz  ACC,vf05,vf10   # Cross product of ray normal and edge2 (pvec)\r\n\tvopmsub.xyz  vf12,vf10,vf05  # Second part of cross product\r\n   \tmfc1         $8,$f4\r\n\tli\t\t     %0,0\t\t\t # store 0 for return value\r\n\t#li      $9,0x80\t \t\t # Set the mask X sign flag\r\n\t#li      $10,0x10\t\t\t # Set the mask W sign flag\r\n\r\n\tvmul.xyz  vf11,vf09,vf12     # det = edge1 * pvec [start]\r\n\tvmulax.x  ACC,vf09,vf12x\r\n\tvmul.xyz  vf15,vf13,vf12     # u = tvec * pvec [start]\r\n\tqmtc2\t$8, $vf03\r\n\tvmadday.x ACC,vf02,vf11y\r\n\tvmaddz.x  vf11,vf02,vf11z    # det = edge1 * pvec [ready]\r\n\tvmulax.x  ACC,vf02,vf15x\r\n\tvmadday.x ACC,vf02,vf15y\r\n\tvmaddz.x  vf15,vf02,vf15z    # u = tvec * pvec [ready]\r\n\tvdiv \t  Q,vf00w,vf11x      # Q = 1.0f / det\r\n\r\n\tvopmula.xyz ACC,vf13,vf09    # qvec = crossProd(tvec, edge1);\r\n\tvopmsub.xyz vf14,vf09,vf13\r\n\tvsub.x      vf01,vf11,vf03   # If det < EPSILON\r\n\t\tvnop\r\n\t\tvnop\r\n\t\tvnop\r\n\t\tvnop\r\n\t\tvnop\r\n\tcfc2    $8,$vi17\t\t\t # transfer if det result (MAC register)\r\n\tvmulq.x vf15,vf15,Q          # u = (tvec * pvec) / det\r\n\tvnop\r\n\tvnop\r\n\tvnop\r\n\t\tvnop\r\n\t\tandi\t$8, $8, 0x80\t\t # check result\r\n\tcfc2    $9,$vi17\t\t\t # transfer u result (MAC register)\r\n\tbne\t\t$8, $0, vu0RayTriDone\r\n\tvaddx.w vf03, vf00, vf03x\t # put 1 + EPSILON in VF03w\r\n\tandi\t$9, $9, 0x80\t\t # check result (u < 0) fail\r\n\tbne\t\t$9, $0, vu0RayTriDone\r\n\t#vaddq.x vf20,vf00,Q          \r\n\r\n    vsubw.x vf00,vf15,vf03w\t\t # if u > 1 + EPSILON\r\n\t\tvnop\r\n\t\tvnop\r\n\t\tvnop\r\n\t\tvnop\r\n\t\tvnop\r\n\tcfc2    $8,$vi17\t\t\t # transfer if u > 1 + EPSILON result (MAC register)\r\n    vmul.xyz vf16,vf05,vf14      # v = rayDir * qvec [start] \r\n    vmulax.x ACC,vf05,vf14x\r\n\tandi\t$8, $8, 0x80\t\t # check result (u > 1) fail\r\n\tbeq\t\t$8, $0, vu0RayTriDone\r\n\tvnop\r\n\r\n    vmadday.x ACC,vf02,vf16\r\n    vmaddz.x vf16,vf02,vf16z     # v = rayDir * qvec [ready]\r\n\tvnop\r\n    vmul.xyz vf17,vf10,vf14      # t = edge2 * qvec [start]\r\n    vmulax.x ACC,vf10,vf14x\r\n    vmulq.x   vf16,vf16,Q        # v = (rayDir * qvec) / det;\r\n\tvnop\r\n\t\tvnop\r\n\t\tvnop\r\n\t\tvnop\r\n\t\tvnop\r\n\tcfc2    $8,$vi17\t\t\t # transfer if v < 0 result (MAC register)\r\n\r\n\tvmadday.x ACC,vf02,vf17\r\n\tvmaddz.x  vf17,vf02,vf17z    # t = edge2 * qvec [ready]\r\n\tvadd.x    vf01,vf15,vf16\r\n\tandi\t  $8, $8, 0x80\t\t # check result (v < 0) fail\r\n\tbne\t\t  $8, $0, vu0RayTriDone\r\n    vmulq.x    vf17,vf17,Q       # t = (edge2 * qvec) / det\r\n\r\n    vsubw.x vf31,vf01,vf03w      # if (u+v) > 1 + EPSILON [start]\r\n\tvnop\r\n\tvnop\r\n\tvnop\r\n\t\tvnop\r\n\t\tvnop\r\n\tcfc2    $8,$vi17\t\t\t # transfer if u+v > 1 + EPSILON result (MAC register)\r\n    vsub.x vf00,vf17,vf00\r\n\tvnop\r\n\t\tvnop\r\n\t\tvnop\r\n\t\tvnop\r\n\tandi\t$8, $8, 0x80\t\t # check result (u+v > 1 + EPSILON) fail\r\n\tcfc2    $9,$vi17\t\t\t # transfer if t < 0 result (MAC register)\r\n\tvsubx.w vf00,vf00,vf17       # if t > 1 [start]\r\n\tvnop\r\n\t\tvnop\r\n\t\t#vnop\r\n\t\t#vnop\r\n\t\t#vnop\r\n\tbeq\t\t$8, $0, vu0RayTriDone\r\n\tandi\t$9, $9, 0x80\t\t # check result (t < 0) fail\r\n\tbne\t\t$9, $0, vu0RayTriDone\r\n\tcfc2    $8,$vi17\t\t\t # transfer if t > 1 result (MAC register)\r\n\tandi\t$8, $8, 0x10\t\t # check result (t > 1) fail\r\n\tbne\t\t$8, $0, vu0RayTriDone\r\n\tqmfc2\t$9, $vf17\t\t\t # move t to $9\r\n\tsw\t\t$9, 0(%1)\t\t\t # and write out\r\n\tli\t\t%0,1\t\t\t\t # store 1 for return value\r\n\r\n\r\nvu0RayTriDone:\r\n\t.set reorder\r\n\t\": \"=r\" (result), \"+r\" (t) : \"r\" (rayStart), \"r\" (rayDir), \"r\" (v0), \"r\" (v1) , \"r\" (v2) : \"$8\", \"$9\");\r\n\t//return *t <= 1.0f;\r\n\treturn result;\r\n#endif //\tUSE_VU0_MICROMODE\r\n#else\r\n    const float EPSILON = 0.00001f;\r\n\r\n    /* find vectors for two edges sharing vert0 */\r\n    Mth::Vector edge1 = *v1 - *v0;\r\n    Mth::Vector edge2 = *v2 - *v0;\r\n    \r\n    /* begin calculating determinant - also used to calculate U parameter */\r\n    Mth::Vector pvec = Mth::CrossProduct(*rayDir, edge2);\r\n\r\n    /* if determinant is near zero, ray lies in plane of triangle */\r\n    const float det = Mth::DotProduct(edge1, pvec);\r\n\r\n#if 1 // Dan - 1/21/3\r\n\t// Moved division below several false returns and reduced mult count.  This probably removed the need for adding EPSILON to 1.0f for the u and v test,\r\n\t// but I don't know this for sure, so left it in.\r\n\t// Also, added EPSILON_2.  EPSILON is of appropriate scale for comparing floats of order one to zero, but is too small for comparing floats\r\n\t// on the order of the cube of a typical vertex edge.  In certain special cases the dot product in the calculation of det will require the\r\n\t// cancelation of very large floats, resulting in a zero which is larger than EPSILON.  This was causing false positives.\r\n\t// It is possible that this new larger EPSILON_2 will cause false negatives.  I suppose we shall see.\r\n\t// These changes HAVE NOT BEEN MADE to the assembler code versions.  They continue to suffer from the over-small EPSILON issue.\r\n\r\n    const float EPSILON_2 = 0.03f;\r\n    \r\n\t// We are back-facing, so also throw away negative\r\n    if (det < EPSILON_2)\r\n\t{\r\n        return false;\r\n    }\r\n\r\n\tconst float adjusted_det = (1.0f + EPSILON) * det;\r\n\r\n    /* calculate distance from vert0 to ray origin */\r\n    const Mth::Vector tvec = *rayStart - *v0;\r\n    \r\n    /* calculate U parameter and test bounds */\r\n    float u = Mth::DotProduct(tvec, pvec);\r\n\r\n    if (u < 0.0f || u > adjusted_det) {\r\n        return false;\r\n    }\r\n    \r\n    /* prepare to test V parameter */\r\n    const Mth::Vector qvec = Mth::CrossProduct(tvec, edge1);\r\n    \r\n    /* calculate V parameter and test bounds */\r\n    float v = Mth::DotProduct(*rayDir, qvec);\r\n\r\n    if (v < 0.0f || u + v > adjusted_det) {\r\n        return false;\r\n    }\r\n\r\n\tconst float inv_det = 1.0f / det;\r\n\r\n    /* calculate t, ray intersects triangle */\r\n    *t = Mth::DotProduct(edge2, qvec) * inv_det;\r\n\r\n\t// And update u & v, although we don't seem to use it now.\r\n\t//u *= inv_det;\r\n\t//v *= inv_det;\r\n\r\n#else\r\n\t// We are back-facing, so also throw away negative\r\n    if (det < EPSILON)\r\n\t{\r\n        return false;\r\n    }\r\n\r\n\tconst float inv_det = 1.0f / det;\r\n\r\n    /* calculate distance from vert0 to ray origin */\r\n    const Mth::Vector tvec = *rayStart - *v0;\r\n    \r\n    /* calculate U parameter and test bounds */\r\n    float u = Mth::DotProduct(tvec, pvec) * inv_det;\r\n\r\n    if (u < 0.0f || u > (1.0f + EPSILON)) {\r\n        return false;\r\n    }\r\n    \r\n    /* prepare to test V parameter */\r\n    const Mth::Vector qvec = Mth::CrossProduct(tvec, edge1);\r\n    \r\n    /* calculate V parameter and test bounds */\r\n    float v = Mth::DotProduct(*rayDir, qvec) * inv_det;\r\n\r\n    if (v < 0.0f || u + v > (1.0f + EPSILON)) {\r\n        return false;\r\n    }\r\n    \r\n    /* calculate t, ray intersects triangle */\r\n    *t = Mth::DotProduct(edge2, qvec) * inv_det;\r\n\r\n\t// And update u & v, although we don't seem to use it now.\r\n\t//u *= inv_det;\r\n\t//v *= inv_det;\r\n#endif\r\n\r\n    return (*t <= 1.0f) && (*t >= 0.0f);\r\n#endif\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCollObj::s2DLineLineCollision ( float p_start_X, float p_start_Y, float p_delta_X, float p_delta_Y, float q_start_X, float q_start_Y, float q_delta_X, float q_delta_Y, float *s )\r\n{\r\n\t// determines collision between two lines (p and q) in 2D; reports the interval along p at which the collision occurs\r\n\t\r\n\t// Antonio's method; Real-Time Rendering, p 337\r\n\t\r\n    const float EPSILON = 0.00000000001f;\r\n\t\r\n\tfloat a_X = q_delta_X;\r\n\tfloat a_Y = q_delta_Y;\r\n\t\r\n\tfloat b_X = p_delta_X;\r\n\tfloat b_Y = p_delta_Y;\r\n\t\r\n\tfloat c_X = p_start_X - q_start_X;\r\n\tfloat c_Y = p_start_Y - q_start_Y;\r\n\t\r\n\tfloat d = c_X * -a_Y + c_Y * a_X;\r\n\t\r\n\tfloat e = c_X * -b_Y + c_Y * b_X;\r\n\t\r\n\tfloat f = a_X * -b_Y + a_Y * b_X;\r\n\t\r\n\tif (f > 0.0f)\r\n\t{\r\n\t\tif (d < 0.0f || d > f) return false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (d > 0.0f || d < f) return false;\r\n\t}\r\n\t\r\n\tif (f > 0.0f)\r\n\t{\r\n\t\tif (e < 0.0f || e > f) return false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (e > 0.0f || e < f) return false;\r\n\t}\r\n\t\r\n\tif (Mth::Abs(f) < EPSILON)\r\n\t{\r\n\t\t*s = 0.0f;\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\t*s = d / f;\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCollObj::sRectangleTriangleCollision(const Mth::Rectangle *rect, const Mth::Vector *v0, const Mth::Vector *v1, const Mth::Vector *v2, Mth::Vector p_collision_endpoints[2], ETriangleEdgeType p_collision_triangle_edges[2] )\r\n{\r\n\t// ERIT method; Real-Time Rendering, p 317\r\n\t\r\n    const float EPSILON = 0.00001f;\r\n\t\r\n\t// calculate the plane equation of the rectangle\r\n\tMth::Vector rectangle_n = Mth::CrossProduct(rect->m_first_edge, rect->m_second_edge);\r\n\tfloat rectangle_d = -Mth::DotProduct(rectangle_n, rect->m_corner);\r\n\t\r\n\t// calculate the distance (times rectangle_n squared) of the triangle vertices from the rectangle's plane\r\n\tfloat d0 = Mth::DotProduct(rectangle_n, *v0) + rectangle_d; \r\n\tfloat d1 = Mth::DotProduct(rectangle_n, *v1) + rectangle_d; \r\n\tfloat d2 = Mth::DotProduct(rectangle_n, *v2) + rectangle_d;\r\n\t \r\n\t// if all vertices are on the same side of the plane, we reject\r\n\tif (d0 > 0.0f && d1 > 0.0f && d2 > 0.0f) return false;\r\n\tif (d0 < 0.0f && d1 < 0.0f && d2 < 0.0f) return false;\r\n\t\r\n\t// snap verticies near the plane to the plane\r\n\tif (Mth::Abs(d0) < EPSILON)\r\n\t{\r\n\t\td0 = 0.0f;\r\n\t}\r\n\tif (Mth::Abs(d1) < EPSILON)\r\n\t{\r\n\t\td1 = 0.0f;\r\n\t}\r\n\tif (Mth::Abs(d2) < EPSILON)\r\n\t{\r\n\t\td2 = 0.0f;\r\n\t}\r\n\t\r\n\t// find the two points (p and q) on the plane of the rectangle which are the endpoints of the triangle's interception with the rectangle's plane\r\n\tMth::Vector p, q;\r\n\tETriangleEdgeType p_edge, q_edge;\r\n\tif ((d0 <= 0.0f && d1 >= 0.0f) || (d0 >= 0.0f && d1 <= 0.0f))\r\n\t{\r\n\t\tp_edge = TRIANGLE_EDGE_V0_V1;\r\n\t\tif (Mth::Abs(d0 - d1) > EPSILON)\r\n\t\t{\r\n\t\t\tp = *v0 + (*v1 - *v0) * d0 / (d0 - d1);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp = *v0;\r\n\t\t}\r\n\t\t\r\n\t\tif ((d1 <= 0.0f && d2 >= 0.0f) || (d1 >= 0.0f && d2 <= 0.0f))\r\n\t\t{\r\n\t\t\tq_edge = TRIANGLE_EDGE_V1_V2;\r\n\t\t\tif (Mth::Abs(d1 - d2) > EPSILON)\r\n\t\t\t{\r\n\t\t\t\tq = *v1 + (*v2 - *v1) * d1 / (d1 - d2);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tq = *v1;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tq_edge = TRIANGLE_EDGE_V2_V0;\r\n\t\t\tif (Mth::Abs(d2 - d0) > EPSILON)\r\n\t\t\t{\r\n\t\t\t\tq = *v2 + (*v0 - *v2) * d2 / (d2 - d0);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tq = *v2;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_edge = TRIANGLE_EDGE_V1_V2;\r\n\t\tif (Mth::Abs(d1 - d2) > EPSILON)\r\n\t\t{\r\n\t\t\tp = *v1 + (*v2 - *v1) * d1 / (d1 - d2);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp = *v1;\r\n\t\t}\r\n\t\t\r\n\t\tq_edge = TRIANGLE_EDGE_V2_V0;\r\n\t\tif (Mth::Abs(d0 - d2) > EPSILON)\r\n\t\t{\r\n\t\t\tq = *v0 + (*v2 - *v0) * d0 / (d0 - d2);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tq = *v0;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// project the rectangle and the intersection endpoints into the coordinate plane which maximizes the area of the rectangle's projection\r\n\t\r\n\tfloat r_corner_S, r_corner_T;\r\n\tfloat r_first_edge_S, r_first_edge_T;\r\n\tfloat r_second_edge_S, r_second_edge_T;\r\n\tfloat p_S, p_T;\r\n\tfloat q_S, q_T;\r\n\t\r\n\tif (Mth::Abs(rectangle_n[X]) < Mth::Abs(rectangle_n[Z]) && Mth::Abs(rectangle_n[Y]) < Mth::Abs(rectangle_n[Z]))\r\n\t{\r\n\t\t// project onto XY plane\r\n\t\tr_corner_S = rect->m_corner[X];\r\n\t\tr_corner_T = rect->m_corner[Y];\r\n\t\tr_first_edge_S = rect->m_first_edge[X];\r\n\t\tr_first_edge_T = rect->m_first_edge[Y];\r\n\t\tr_second_edge_S = rect->m_second_edge[X];\r\n\t\tr_second_edge_T = rect->m_second_edge[Y];\r\n\t\tp_S = p[X];\r\n\t\tp_T = p[Y];\r\n\t\tq_S = q[X];\r\n\t\tq_T = q[Y];\r\n\t}\r\n\telse if (Mth::Abs(rectangle_n[X]) < Mth::Abs(rectangle_n[Y]) && Mth::Abs(rectangle_n[Z]) < Mth::Abs(rectangle_n[Y]))\r\n\t{\r\n\t\t// project onto XZ plane\r\n\t\tr_corner_S = rect->m_corner[X];\r\n\t\tr_corner_T = rect->m_corner[Z];\r\n\t\tr_first_edge_S = rect->m_first_edge[X];\r\n\t\tr_first_edge_T = rect->m_first_edge[Z];\r\n\t\tr_second_edge_S = rect->m_second_edge[X];\r\n\t\tr_second_edge_T = rect->m_second_edge[Z];\r\n\t\tp_S = p[X];\r\n\t\tp_T = p[Z];\r\n\t\tq_S = q[X];\r\n\t\tq_T = q[Z];\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// project onto YZ plane\r\n\t\tr_corner_S = rect->m_corner[Y];\r\n\t\tr_corner_T = rect->m_corner[Z];\r\n\t\tr_first_edge_S = rect->m_first_edge[Y];\r\n\t\tr_first_edge_T = rect->m_first_edge[Z];\r\n\t\tr_second_edge_S = rect->m_second_edge[Y];\r\n\t\tr_second_edge_T = rect->m_second_edge[Z];\r\n\t\tp_S = p[Y];\r\n\t\tp_T = p[Z];\r\n\t\tq_S = q[Y];\r\n\t\tq_T = q[Z];\r\n\t}\r\n\t\r\n\t// test p and q against the four edges of the rectangle; if both lie outside any edge, we reject\r\n\t\r\n\t// these variables define a rectangle's edge in 2D; as + bt + c = 0\r\n\tfloat a, b, c;\r\n\t\r\n\tfloat pd, qd;\r\n\tfloat inside_sign;\r\n\t\r\n\t// not really convinced that this bitmap method of faster \r\n\t// char within = 0;\r\n\t// enum\r\n\t// {\r\n\t\t// P_TRIANGLE_EDGE_0_MASK = 1 << 0,\r\n\t\t// Q_TRIANGLE_EDGE_0_MASK = 1 << 1,\r\n\t\t// P_TRIANGLE_EDGE_1_MASK = 1 << 2,\r\n\t\t// Q_TRIANGLE_EDGE_1_MASK = 1 << 3,\r\n\t\t// P_TRIANGLE_EDGE_2_MASK = 1 << 4,\r\n\t\t// Q_TRIANGLE_EDGE_2_MASK = 1 << 5,\r\n\t\t// P_TRIANGLE_EDGE_3_MASK = 1 << 6,\r\n\t\t// Q_TRIANGLE_EDGE_3_MASK = 1 << 7,\r\n\t\t// ALL_P_MASKS = P_TRIANGLE_EDGE_0_MASK | P_TRIANGLE_EDGE_1_MASK | P_TRIANGLE_EDGE_2_MASK | P_TRIANGLE_EDGE_3_MASK,\r\n\t\t// ALL_Q_MASKS = Q_TRIANGLE_EDGE_0_MASK | Q_TRIANGLE_EDGE_1_MASK | Q_TRIANGLE_EDGE_2_MASK | Q_TRIANGLE_EDGE_3_MASK\r\n\t// };\r\n\tbool p_within[4] = { false, false, false, false };\r\n\tbool q_within[4] = { false, false, false, false };\r\n\t\r\n\t// edge 0: corner to corner + first_edge\r\n\t// second_edge defines inside direction\r\n\ta = r_first_edge_T;\r\n\tb = -r_first_edge_S;\r\n\tc = r_corner_T * r_first_edge_S - r_corner_S * r_first_edge_T;\r\n\tpd = a * p_S + b * p_T + c;\r\n\tqd = a * q_S + b * q_T + c;\r\n\tinside_sign = a * r_second_edge_S + b * r_second_edge_T;\r\n\tif (inside_sign > 0.0f)\r\n\t{\r\n\t\t// within = (P_TRIANGLE_EDGE_0_MASK * (pd >= 0.0f)) | (Q_TRIANGLE_EDGE_0_MASK * (qd >= 0.0f));\r\n\t\tp_within[0] = pd >= 0.0f;\r\n\t\tq_within[0] = qd >= 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// within = (P_TRIANGLE_EDGE_0_MASK * (pd <= 0.0f)) | (Q_TRIANGLE_EDGE_0_MASK * (qd <= 0.0f));\r\n\t\tp_within[0] = pd <= 0.0f;\r\n\t\tq_within[0] = qd <= 0.0f;\r\n\t}\r\n\t// if (!(within & (P_TRIANGLE_EDGE_0_MASK | Q_TRIANGLE_EDGE_0_MASK))) return false;\r\n\tif (!p_within[0] && !q_within[0]) return false;\r\n\t\t\r\n\t// edge 1: corner + second_edge to corner + first_edge + second_edge\r\n\t// second_edge defines outside direction\r\n\tc = (r_corner_T + r_second_edge_T) * r_first_edge_S - (r_corner_S + r_second_edge_S) * r_first_edge_T;\r\n\tpd = a * p_S + b * p_T + c;\r\n\tqd = a * q_S + b * q_T + c;\r\n\tif (inside_sign < 0.0f)\r\n\t{\r\n\t\t// within |= (P_TRIANGLE_EDGE_1_MASK * (pd >= 0.0f)) | (Q_TRIANGLE_EDGE_1_MASK * (qd >= 0.0f));\r\n\t\tp_within[1] = pd >= 0.0f;\r\n\t\tq_within[1] = qd >= 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// within |= (P_TRIANGLE_EDGE_1_MASK * (pd <= 0.0f)) | (Q_TRIANGLE_EDGE_1_MASK * (qd <= 0.0f));\r\n\t\tp_within[1] = pd <= 0.0f;\r\n\t\tq_within[1] = qd <= 0.0f;\r\n\t}\r\n\t// if (!(within & (P_TRIANGLE_EDGE_1_MASK | Q_TRIANGLE_EDGE_1_MASK))) return false;\r\n\tif (!p_within[1] && !q_within[1]) return false;\r\n\t\r\n\t// edge 2: corner to corner + second_edge\r\n\t// first_edge defines inside direction\r\n\ta = r_second_edge_T;\r\n\tb = -r_second_edge_S;\r\n\tc = r_corner_T * r_second_edge_S - r_corner_S * r_second_edge_T;\r\n\tpd = a * p_S + b * p_T + c;\r\n\tqd = a * q_S + b * q_T + c;\r\n\tinside_sign = a * r_first_edge_S + b * r_first_edge_T;\r\n\tif (inside_sign > 0.0f)\r\n\t{\r\n\t\t// within |= (P_TRIANGLE_EDGE_2_MASK * (pd >= 0.0f)) | (Q_TRIANGLE_EDGE_2_MASK * (qd >= 0.0f));\r\n\t\tp_within[2] = pd >= 0.0f;\r\n\t\tq_within[2] = qd >= 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// within |= (P_TRIANGLE_EDGE_2_MASK * (pd <= 0.0f)) | (Q_TRIANGLE_EDGE_2_MASK * (qd <= 0.0f));\r\n\t\tp_within[2] = pd <= 0.0f;\r\n\t\tq_within[2] = qd <= 0.0f;\r\n\t}\r\n\t// if (!(within & (P_TRIANGLE_EDGE_2_MASK | Q_TRIANGLE_EDGE_2_MASK))) return false;\r\n\tif (!p_within[2] && !q_within[2]) return false;\r\n\t\r\n\t// edge 3: corner + first_edge to corner + first_edge + second_edge\r\n\t// first_edge defines outside direction\r\n\tc = (r_corner_T + r_first_edge_T) * r_second_edge_S - (r_corner_S + r_first_edge_S) * r_second_edge_T;\r\n\tpd = a * p_S + b * p_T + c;\r\n\tqd = a * q_S + b * q_T + c;\r\n\tif (inside_sign < 0.0f)\r\n\t{\r\n\t\t// within |= (P_TRIANGLE_EDGE_3_MASK * (pd >= 0.0f)) | (Q_TRIANGLE_EDGE_3_MASK * (qd >= 0.0f));\r\n\t\tp_within[3] = pd >= 0.0f;\r\n\t\tq_within[3] = qd >= 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// within |= (P_TRIANGLE_EDGE_3_MASK * (pd <= 0.0f)) | (Q_TRIANGLE_EDGE_3_MASK * (qd <= 0.0f));\r\n\t\tp_within[3] = pd <= 0.0f;\r\n\t\tq_within[3] = qd <= 0.0f;\r\n\t}\r\n\t// if (!(within & (P_TRIANGLE_EDGE_3_MASK | Q_TRIANGLE_EDGE_3_MASK))) return false;\r\n\tif (!p_within[3] && !q_within[3]) return false;\r\n\t\r\n\tint next_collision_endpoint_idx;\r\n\t\r\n\t// if p or q is within all edges, it is the endpoint of the collision\r\n\t// if ((within & ALL_P_MASKS) == ALL_P_MASKS)\r\n\tif (p_within[0] && p_within[1] && p_within[2] && p_within[3])\r\n\t{\r\n        p_collision_endpoints[0] = p;\r\n\t\tp_collision_triangle_edges[0] = p_edge;\r\n\t\t// if ((within & ALL_Q_MASKS) == ALL_Q_MASKS)\r\n\t\tif (q_within[0] && q_within[1] && q_within[2] && q_within[3])\r\n\t\t{\r\n\t\t\tp_collision_endpoints[1] = q;\r\n\t\t\tp_collision_triangle_edges[1] = q_edge;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tnext_collision_endpoint_idx = 1;\r\n\t}\r\n\t// else if ((within & ALL_Q_MASKS) == ALL_Q_MASKS)\r\n\telse if (q_within[0] && q_within[1] && q_within[2] && q_within[3])\r\n\t{\r\n\t\tp_collision_endpoints[0] = q;\r\n\t\tp_collision_triangle_edges[0] = q_edge;\r\n\t\tnext_collision_endpoint_idx = 1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tnext_collision_endpoint_idx = 0;\r\n\t}\r\n\t\r\n\t// we've found any endpoints of the collision which are within the rectangle; further collision endpoints will lie on the edges of the rectangle;\r\n\t \r\n\t// we check each edge of the rectangle for intersection with the triangle's plane-intersection line segment\r\n\t\r\n\tfloat s;\r\n\t\r\n\t// edge 0: corner to corner + first_edge\r\n\tif (s2DLineLineCollision(r_corner_S, r_corner_T, r_first_edge_S, r_first_edge_T, p_S, p_T, q_S - p_S, q_T - p_T, &s))\r\n\t{\r\n\t\tp_collision_endpoints[next_collision_endpoint_idx] = rect->m_first_edge;\r\n\t\tp_collision_endpoints[next_collision_endpoint_idx] *= s;\r\n\t\tp_collision_endpoints[next_collision_endpoint_idx] += rect->m_corner;\r\n\t\tp_collision_triangle_edges[next_collision_endpoint_idx] = NO_TRIANGLE_EDGE;\r\n\t\tif (next_collision_endpoint_idx == 1) return true;\r\n\t\tnext_collision_endpoint_idx = 1;\r\n\t}\r\n\t\r\n\t// edge 1: corner + second_edge to corner + first_edge + second_edge\r\n\tif (s2DLineLineCollision(r_corner_S + r_second_edge_S, r_corner_T + r_second_edge_T, r_first_edge_S, r_first_edge_T, p_S, p_T, q_S - p_S, q_T - p_T, &s))\r\n\t{\r\n\t\tp_collision_endpoints[next_collision_endpoint_idx] = rect->m_first_edge;\r\n\t\tp_collision_endpoints[next_collision_endpoint_idx] *= s;\r\n\t\tp_collision_endpoints[next_collision_endpoint_idx] += rect->m_corner;\r\n\t\tp_collision_endpoints[next_collision_endpoint_idx] += rect->m_second_edge;\r\n\t\tp_collision_triangle_edges[next_collision_endpoint_idx] = NO_TRIANGLE_EDGE;\r\n\t\tif (next_collision_endpoint_idx == 1) return true;\r\n\t\tnext_collision_endpoint_idx = 1;\r\n\t}\r\n\t\r\n\t// edge 2: corner to corner + second_edge\r\n\tif (s2DLineLineCollision(r_corner_S, r_corner_T, r_second_edge_S, r_second_edge_T, p_S, p_T, q_S - p_S, q_T - p_T, &s))\r\n\t{\r\n\t\tp_collision_endpoints[next_collision_endpoint_idx] = rect->m_second_edge;\r\n\t\tp_collision_endpoints[next_collision_endpoint_idx] *= s;\r\n\t\tp_collision_endpoints[next_collision_endpoint_idx] += rect->m_corner;\r\n\t\tp_collision_triangle_edges[next_collision_endpoint_idx] = NO_TRIANGLE_EDGE;\r\n\t\tif (next_collision_endpoint_idx == 1) return true;\r\n\t\tnext_collision_endpoint_idx = 1;\r\n\t}\r\n\t\r\n\t// edge 3: corner + first_edge to corner + first_edge + second_edge\r\n\tif (s2DLineLineCollision(r_corner_S + r_first_edge_S, r_corner_T + r_first_edge_T, r_second_edge_S, r_second_edge_T, p_S, p_T, q_S - p_S, q_T - p_T, &s))\r\n\t{\r\n\t\tif (next_collision_endpoint_idx == 1)\r\n\t\t{\r\n\t\t\tp_collision_endpoints[next_collision_endpoint_idx] = rect->m_second_edge;\r\n\t\t\tp_collision_endpoints[next_collision_endpoint_idx] *= s;\r\n\t\t\tp_collision_endpoints[next_collision_endpoint_idx] += rect->m_corner;\r\n\t\t\tp_collision_endpoints[next_collision_endpoint_idx] += rect->m_first_edge;\r\n\t\t\tp_collision_triangle_edges[next_collision_endpoint_idx] = NO_TRIANGLE_EDGE;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// no collision could be found\r\n\treturn false;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// CCollObj member functions\r\n//\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollObj::CCollObj() : m_Flags(0), mp_coll_tri_data(NULL)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollObj::~CCollObj()\r\n{\r\n\t// this should only be done on clones\r\n\tif (mp_coll_tri_data && (m_Flags & mSD_CLONE))\r\n\t{\r\n\t\tdelete mp_coll_tri_data;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\t\tCCollObj::SetChecksum(uint32 checksum)\r\n{\r\n\tm_checksum = checksum;\r\n\tif (mp_coll_tri_data)\r\n\t{\r\n\t\tmp_coll_tri_data->SetChecksum(checksum);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCCollObj::SetMovingObject(Obj::CCompositeObject *p_movable_object)\r\n{\r\n\tDbg_MsgAssert(0, (\"Can't call SetMovingObject() on a non-moving collision type\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CCompositeObject * CCollObj::GetMovingObject() const\r\n{\r\n\treturn NULL;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define PRINT_RECT_COLLISION_DEBUG\r\nconst float CCollObj::sLINE_BOX_EXTENT = 0.5f;\t// Extent of box around collision line\r\n\r\nbool\t\t\t\t\tCCollObj::sFindRectangleStaticCollision ( Mth::Rectangle& rect, S2DCollData* p_2D_coll_data, CCollCache *p_cache )\r\n{\r\n#if PRINT_CACHE_HITS\r\n\tstatic uint s_rect_cache_hits = 0, s_num_rect_collisions = 0;\r\n#endif\r\n\r\n\tDbg_Assert(p_2D_coll_data);\r\n\t\r\n\tMth::CBBox rect_bbox(rect.m_corner);\r\n\trect_bbox.AddPoint(rect.m_corner + rect.m_first_edge);\r\n\trect_bbox.AddPoint(rect.m_corner + rect.m_second_edge);\r\n\trect_bbox.AddPoint(rect.m_corner + rect.m_first_edge + rect.m_second_edge);\r\n\t\r\n\tbool use_cache = p_cache;\r\n\tif (use_cache)\r\n\t{\r\n\t\tuse_cache = p_cache->Contains(rect_bbox);\r\n#if PRINT_CACHE_HITS\r\n\t\tif (use_cache)\r\n\t\t{\r\n\t\t\ts_rect_cache_hits++;\r\n\t\t}\r\n\t\tif (++s_num_rect_collisions >= 500)\r\n\t\t{\r\n\t\t\tDbg_Message(\"Static Rect Cache Hits %d/500\", s_rect_cache_hits);\r\n\t\t\ts_rect_cache_hits = s_num_rect_collisions = 0;\r\n\t\t}\r\n#endif\r\n\t}\r\n\t\r\n\tCCollStatic** p_coll_obj_list = NULL;\r\n\tif (!use_cache)\r\n\t{\r\n\t\tSSec::Manager* ss_man = Nx::CEngine::sGetNearestSuperSectorManager(rect.m_corner);\r\n\t\tif (!ss_man) return false;\r\n\t\t\r\n\t\t// get a list of sectors within the super sectors cut by the rectangle\r\n\t\tp_coll_obj_list = ss_man->GetIntersectingCollSectors(rect_bbox);\r\n\t}\r\n\t\r\n\t// bloat the rectangle bounding box for comparison to sector bounding boxes\r\n\tMth::Vector extension(sLINE_BOX_EXTENT, sLINE_BOX_EXTENT, sLINE_BOX_EXTENT);\r\n\trect_bbox.Set(rect_bbox.GetMin() - extension, rect_bbox.GetMax() + extension);\r\n\t\r\n\tp_2D_coll_data->num_surfaces = 0;\r\n\t\r\n\tif (use_cache)\r\n\t{\r\n\t\tint num_collisions = p_cache->GetNumStaticCollisions();\r\n\t\tconst SCollCacheNode* p_coll_node = p_cache->GetStaticCollisionArray();\r\n\t\t\r\n\t\t// loop over sectors in the cache\r\n\t\tfor (int i = num_collisions; i--; )\r\n\t\t{\r\n\t\t\t// check to see if the sector's bounding box intersects with the rectangle's bounding box\r\n\t\t\tif (rect_bbox.Intersect(*(p_coll_node->mp_bbox)))\r\n\t\t\t{\r\n\t\t\t\t// check the sector's trangle's for collision with the rectangle\r\n\t\t\t\tp_coll_node->mp_coll_obj->CollisionWithRectangle(rect, rect_bbox, p_2D_coll_data);\r\n\t\t\t}\r\n\r\n\t\t\tp_coll_node++;\r\n\t\t} // END loop over sectors in the cache\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// loop over potentially collided with sectors\r\n\t\tCCollStatic* p_coll_obj;\r\n\t\twhile ((p_coll_obj = *p_coll_obj_list))\r\n\t\t{\r\n\t\t\tDbg_Assert(p_coll_obj->GetGeometry());\r\n\t\t\t\r\n\t\t\t// check to see if the sector's bounding box intersects with the rectangle's bounding box\r\n\t\t\tif (p_coll_obj->WithinBBox(rect_bbox))\r\n\t\t\t{\r\n\t\t\t\t// check the sector's trangle's for collision with the rectangle\r\n\t\t\t\tp_coll_obj->CollisionWithRectangle(rect, rect_bbox, p_2D_coll_data);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tp_coll_obj_list++;\r\n\t\t} // END loop over potentially collided with sectors\r\n\t}\r\n\t\r\n\treturn p_2D_coll_data->num_surfaces > 0;\r\n}\r\n\r\nbool GPrintCollisionData = false;\r\n\r\nbool\t\t\t\t\tCCollObj::sFindNearestStaticCollision( Mth::Line &is, CollData *p_data, void *p_callback, CCollCache *p_cache)\r\n{\r\n#if PRINT_CACHE_HITS\r\n\tstatic uint s_cache_hits = 0, s_num_collisions = 0;\r\n#endif\r\n\r\n    Dbg_Assert(p_data);\r\n    Dbg_Assert(p_data->coll_found == false);\r\n\r\n\tp_data->callback = (void (*)( CollData*)) p_callback;\r\n\r\n\t// Make initial line bounding box\r\n\tMth::CBBox line_bbox(is.m_start);\r\n\tline_bbox.AddPoint(is.m_end);\r\n\r\n\tif (GPrintCollisionData)\r\n\t{\r\n\t\tDbg_Message(\"Inited line BBox (%f, %f, %f), (%f, %f, %f)\",\r\n\t\t\t\t\tline_bbox.GetMin()[X], line_bbox.GetMin()[Y], line_bbox.GetMin()[Z],\r\n\t\t\t\t\tline_bbox.GetMax()[X], line_bbox.GetMax()[Y], line_bbox.GetMax()[Z]);\r\n\t}\r\n\r\n\t// Check to see if we can use the cache\r\n\tbool use_cache = p_cache != NULL;\r\n\tif (use_cache)\r\n\t{\r\n\t\tuse_cache = p_cache->Contains(line_bbox);\r\n\t\t\r\n\t\tif (CCollCacheManager::sGetAssertOnCacheMiss())\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(use_cache, (\"Collision cache miss\"));\r\n\t\t}\r\n#if PRINT_CACHE_HITS\r\n\t\tif (use_cache) s_cache_hits++;\r\n\t\tif (++s_num_collisions >= 5000)\r\n\t\t{\r\n\t\t\tDbg_Message(\"Static Cache Hits %d/5000\", s_cache_hits);\r\n\t\t\ts_cache_hits = s_num_collisions = 0;\r\n\t\t}\r\n#endif\r\n\t}\r\n\r\n\t// initialize starting \"max\" distance to be max collision distance\r\n\tCCollStatic** p_coll_obj_list = NULL;\r\n\tif (!use_cache)\r\n\t{\r\n\t\tSSec::Manager *ss_man;\r\n\r\n\t\tss_man = Nx::CEngine::sGetNearestSuperSectorManager(is);\r\n\t\tif (!ss_man)\r\n\t\t\treturn NULL;\r\n\r\n\t\tp_coll_obj_list = ss_man->GetIntersectingCollSectors( is );\r\n\t}\r\n\t\r\n\t// For a line, the dist is returned as a fraction of the line length\r\n\t// so we set the dist field to just over 1.0, any found collision\r\n\t// will be less than this\r\n\tif (s_check_for_far)\r\n\t{\r\n\t\tp_data->dist = -0.01f; \t\t// but if checking in the other direction, we need to to reverse the check\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_data->dist = 1.01f;\r\n\t}\r\n\r\n\t// Bloat the collision line only for the purposes of deciding against which world \r\n\t// sectors to test the actual collision line\r\n\tMth::Vector extend;\r\n\r\n\textend = line_bbox.GetMax();\r\n\textend[X] += sLINE_BOX_EXTENT;\r\n\textend[Y] += sLINE_BOX_EXTENT;\r\n\textend[Z] += sLINE_BOX_EXTENT;\r\n\tline_bbox.AddPoint(extend);\r\n\r\n\textend = line_bbox.GetMin();\r\n\textend[X] -= sLINE_BOX_EXTENT;\r\n\textend[Y] -= sLINE_BOX_EXTENT;\r\n\textend[Z] -= sLINE_BOX_EXTENT;\r\n\tline_bbox.AddPoint(extend);\r\n\r\n\t// Calculate ray\r\n\tMth::Vector line_dir(is.m_end - is.m_start);\r\n\r\n\tif (GPrintCollisionData)\r\n\t{\r\n\t\tDbg_Message(\"Starting collision check with line BBox (%f, %f, %f), (%f, %f, %f)\",\r\n\t\t\t\t\tline_bbox.GetMin()[X], line_bbox.GetMin()[Y], line_bbox.GetMin()[Z],\r\n\t\t\t\t\tline_bbox.GetMax()[X], line_bbox.GetMax()[Y], line_bbox.GetMax()[Z]);\r\n\t\tDbg_Message(\"Line start (%f, %f, %f)\", is.m_start[X], is.m_start[Y], is.m_start[Z]);\r\n\t\tDbg_Message(\"Line end (%f, %f, %f)\", is.m_end[X], is.m_end[Y], is.m_end[Z]);\r\n\t}\r\n\r\n\tbool new_coll_found = false;\r\n\r\n\tif (use_cache)\r\n\t{\r\n\t\tint num_collisions = p_cache->GetNumStaticCollisions();\r\n\t\tconst SCollCacheNode *p_coll_node = p_cache->GetStaticCollisionArray();\r\n\t\tfor (int i = 0; i < num_collisions; i++)\r\n\t\t{\r\n\t\t\tif(line_bbox.Intersect(*(p_coll_node->mp_bbox)))\r\n\t\t\t{\r\n\t\t\t\t/* It's a world sector, call the callback */\r\n\t\t\t\tif (p_coll_node->mp_coll_obj->CollisionWithLine( is, line_dir, p_data, &line_bbox ))\r\n\t\t\t\t{\r\n\t\t\t\t\tnew_coll_found = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tp_coll_node++;\r\n\t\t}\r\n\t} else {\r\n\t\tCCollStatic* p_coll_obj;\r\n\r\n\t#ifdef BATCH_TRI_COLLISION\r\n\t\t// Init batch manager\r\n\t\tbool do_batch;\r\n\t\tdo_batch = CBatchTriCollMan::sInit(p_data);\r\n\t#endif\r\n\r\n\t\t/* Start at the top */\r\n\t\twhile((p_coll_obj = *p_coll_obj_list))\r\n\t\t{\r\n\t\t\t// TODO: Come up with a cleaner BBox check\r\n\t\t\tDbg_Assert(p_coll_obj->GetGeometry());\r\n\t\t\t//if(line_bbox.Intersect(p_coll_obj->GetGeometry()->GetBBox()))\r\n\t\t\tif (p_coll_obj->WithinBBox(line_bbox))\r\n\t\t\t{\r\n\t\t\t\t// this line will display the bounding box of the potential collidable object\r\n\t\t\t\t// useful to make sure we are only colliding with the minimum necessary objects\r\n\t\t\t\t// p_coll_obj->mp_coll_tri_data->GetBBox().DebugRender(0xfffff,1);\r\n\r\n\t\t\t\t/* It's a world sector, call the callback */\r\n\t\t\t\tif (p_coll_obj->CollisionWithLine( is, line_dir, p_data, &line_bbox ))\r\n\t\t\t\t{\r\n\t\t\t\t\tnew_coll_found = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tp_coll_obj_list++;\r\n\t\t}\r\n\r\n\t#ifdef BATCH_TRI_COLLISION\r\n\t\t// Wait for tri collision to finish first\r\n\t\tif (do_batch)\r\n\t\t{\r\n\t\t\tnew_coll_found = CBatchTriCollMan::sWaitTriCollisions();\r\n\t\t}\r\n\t\tCBatchTriCollMan::sFinish();\t\t\t\t// This should really be in the CFeeler code\r\n\t#endif\r\n\t}\r\n\r\n    /* All done */\r\n\tif (p_data->coll_found)\r\n\t{\r\n\t\tif ((p_data->dist > 1.0f) || (p_data->dist < 0.0f))\r\n\t\t{\r\n\t\t\tDbg_Message(\"Static Collision distance too big: %f\", p_data->dist);\r\n\t\t}\r\n\t}\r\n\r\n\t// return true if we found something\t\t\t\r\n\treturn( new_coll_found );\r\n}\r\n\r\n\r\nbool\t\t\t\t\tCCollObj::sFindFarStaticCollision( Mth::Line &is, CollData *p_data, void *p_callback, CCollCache *p_cache)\r\n{\r\n\ts_check_for_far = true;\r\n\tbool result = sFindNearestStaticCollision(is,p_data,p_callback,p_cache);\r\n\ts_check_for_far = false;\r\n\treturn result;\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Note, p_data is assumed to be already initialized\r\n// either it is set to default values, or we have\r\n// come here after using it to check for static collision\r\n// and the results of that are in there\r\n// - see below, we don't set \"dist\" if we've previously found a collision\r\n// (stops you snapping through walls onto cars)\r\n\t\t\t\t  \r\nObj::CCompositeObject *\tCCollObj::sFindNearestMovableCollision( Mth::Line &is, CollData *p_data, void *p_callback, CCollCache *p_cache)\r\n{\r\n#if PRINT_CACHE_HITS\r\n\tstatic uint s_cache_hits = 0, s_num_collisions = 0;\r\n#endif\r\n\r\n    Dbg_Assert(p_data);\r\n\r\n\tObj::CCompositeObject *p_collision_obj = NULL;\r\n\r\n\tp_data->callback = (void (*)( CollData*)) p_callback;\r\n\r\n\t\r\n\t// initialize starting \"max\" distance to be max collision distance\r\n\t// actually this\t\r\n\tif (!p_data->coll_found)\r\n\t{\r\n\t\t// For a line, the dist is returned as a fraction of the line length\r\n\t\t// so we set the dist field to just over 1.0, any found collision\r\n\t\t// will be less than this\r\n\t\tif (s_check_for_far)\r\n\t\t{\r\n\t\t\tp_data->dist = -0.01f; \t\t// but if checking in the other direction, we need to to reverse the check\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_data->dist = 1.01f;\r\n\t\t}\r\n\t}\r\n\r\n\t// Make initial line bounding box\r\n\tMth::CBBox line_bbox(is.m_start);\r\n\tline_bbox.AddPoint(is.m_end);\r\n\r\n\t// Check to see if we can use the cache\r\n\tbool use_cache = p_cache != NULL;\r\n\tif (use_cache)\r\n\t{\r\n\t\tuse_cache = p_cache->Contains(line_bbox);\r\n#if PRINT_CACHE_HITS\r\n\t\tif (use_cache) s_cache_hits++;\r\n\t\tif (++s_num_collisions >= 5000)\r\n\t\t{\r\n\t\t\tDbg_Message(\"Movable Cache Hits %d/5000\", s_cache_hits);\r\n\t\t\ts_cache_hits = s_num_collisions = 0;\r\n\t\t}\r\n#endif\r\n\t}\r\n\r\n\tif (0 && GPrintCollisionData)\r\n\t{\r\n\t\tDbg_Message(\"Inited line BBox (%f, %f, %f), (%f, %f, %f)\",\r\n\t\t\t\t\tline_bbox.GetMin()[X], line_bbox.GetMin()[Y], line_bbox.GetMin()[Z],\r\n\t\t\t\t\tline_bbox.GetMax()[X], line_bbox.GetMax()[Y], line_bbox.GetMax()[Z]);\r\n\t}\r\n\r\n\t// Bloat the collision line only for the purposes of deciding against which world \r\n\t// sectors to test the actual collision line\r\n\tMth::Vector extend;\r\n\r\n\textend = line_bbox.GetMax();\r\n\textend[X] += sLINE_BOX_EXTENT;\r\n\textend[Y] += sLINE_BOX_EXTENT;\r\n\textend[Z] += sLINE_BOX_EXTENT;\r\n\tline_bbox.AddPoint(extend);\r\n\r\n\textend = line_bbox.GetMin();\r\n\textend[X] -= sLINE_BOX_EXTENT;\r\n\textend[Y] -= sLINE_BOX_EXTENT;\r\n\textend[Z] -= sLINE_BOX_EXTENT;\r\n\tline_bbox.AddPoint(extend);\r\n\r\n\t// Calculate ray\r\n\tMth::Vector line_dir(is.m_end - is.m_start);\r\n\r\n\tif (0 && GPrintCollisionData)\r\n\t{\r\n\t\tDbg_Message(\"Starting collision check with line BBox (%f, %f, %f), (%f, %f, %f)\",\r\n\t\t\t\t\tline_bbox.GetMin()[X], line_bbox.GetMin()[Y], line_bbox.GetMin()[Z],\r\n\t\t\t\t\tline_bbox.GetMax()[X], line_bbox.GetMax()[Y], line_bbox.GetMax()[Z]);\r\n\t\tDbg_Message(\"Line start (%f, %f, %f)\", is.m_start[X], is.m_start[Y], is.m_start[Z]);\r\n\t\tDbg_Message(\"Line end (%f, %f, %f)\", is.m_end[X], is.m_end[Y], is.m_end[Z]);\r\n\t}\r\n\r\n//\tDbg_Message(\"Size of movable list %d\", Nx::CEngine::sGetMovableObjects().CountItems());\r\n//\tDbg_Message(\"Size of movable collision list %d\", CMovableCollMan::sGetCollisionList()->CountItems());\r\n//\tDbg_Assert(0);\r\n\r\n\tif (use_cache)\r\n\t{\r\n\t\tint num_collisions = p_cache->GetNumMovableCollisions();\r\n\t\tconst SCollCacheNode *p_coll_node = p_cache->GetMovableCollisionArray();\r\n\t\tfor (int i = 0; i < num_collisions; i++)\r\n\t\t{\r\n\t\t\tif(p_coll_node->mp_bbox && line_bbox.Intersect(*(p_coll_node->mp_bbox)))\r\n\t\t\t{\r\n\t\t\t\t// Set the callback_object, so any callback will know\r\n\t\t\t\t// what object we were colliding with\r\n\t\t\t\tp_data->mp_callback_object = p_coll_node->mp_coll_obj->GetMovingObject();\r\n\r\n\t\t\t\t/* It's a world sector, call the callback */\r\n\t\t\t\tif (p_coll_node->mp_coll_obj->CollisionWithLine( is, line_dir, p_data, &line_bbox ))\r\n\t\t\t\t{\r\n\t\t\t\t\tp_collision_obj = p_coll_node->mp_coll_obj->GetMovingObject();\r\n\t\t\t\t\tDbg_Assert(p_collision_obj);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// the callback object is only valid for the duration of a possible callback\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\tp_data->mp_callback_object = NULL;\r\n\t\t\t}\r\n\t\t\tp_coll_node++;\r\n\t\t}\r\n\t} else {\r\n\t#if 0 //def BATCH_TRI_COLLISION\r\n\t\t// Init batch manager\r\n\t\tbool do_batch;\r\n\t\tdo_batch = CBatchTriCollMan::sInit(p_data);\r\n\t#endif\r\n\r\n\r\n\t\tLst::Node< CCollObj > *p_movable_node = CMovableCollMan::sGetCollisionList()->GetNext();\r\n\t\t//CCollObj **p_movable_node = CMovableCollMan::sGetCollisionArray();\r\n\r\n\t\twhile(p_movable_node)\r\n\t\t{\r\n\t\t\tCCollObj *p_coll_obj = p_movable_node->GetData();\r\n\t\t\t//CCollObj *p_coll_obj = *p_movable_node;\r\n\r\n\t\t\tif (p_coll_obj && !(p_coll_obj->m_Flags & (mSD_NON_COLLIDABLE | mSD_KILLED )))\r\n\t\t\t{\r\n\t\t\r\n\t\t\t\t/* It's a collision object, call the callback */\r\n\t\t\t\t//if (p_coll_obj->CollisionWithLine( is, line_dir, p_data , &line_bbox))\r\n\t\t\t\tif (p_coll_obj->WithinBBox(line_bbox))\r\n\t\t\t\t{\r\n\t\t\t\t\t// Set the callback_object, so any callback will know\r\n\t\t\t\t\t// what object we were colliding with\r\n\t\t\t\t\tp_data->mp_callback_object = p_coll_obj->GetMovingObject();\r\n\t\t\t\t\r\n\t\t\t\t\tif (p_coll_obj->CollisionWithLine( is, line_dir, p_data, &line_bbox ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_collision_obj = p_coll_obj->GetMovingObject();\r\n\t\t\t\t\t\tDbg_Assert(p_collision_obj);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// the callback object is only valid for the duration of a possible callback\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\t\tp_data->mp_callback_object = NULL;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t}\r\n\r\n\t\t\tp_movable_node = p_movable_node->GetNext();\r\n\t\t\t//p_movable_node++;\r\n\t\t}\r\n\r\n\t#if 0 //def BATCH_TRI_COLLISION\r\n\t\t// Wait for tri collision to finish first\r\n\t\tif (do_batch)\r\n\t\t{\r\n\t\t\tnew_coll_found = CBatchTriCollMan::sWaitTriCollisions();\r\n\t\t}\r\n\t\tCBatchTriCollMan::sFinish();\t\t\t\t// This should really be in the CFeeler code\r\n\t#endif\r\n\t}\r\n\r\n    /* All done */\r\n\tif (p_collision_obj)\r\n\t{\r\n\r\n\t\tif ((p_data->dist > 1.0f) || (p_data->dist < 0.0f))\r\n\t\t{\r\n\t\t\tDbg_Message(\"Movable Collision distance too big: %f\", p_data->dist);\r\n\t\t}\r\n\t}\r\n\r\n\treturn p_collision_obj;\r\n}\r\n\r\nObj::CCompositeObject *\tCCollObj::sFindFarMovableCollision( Mth::Line &is, CollData *p_data, void *p_callback, CCollCache *p_cache)\r\n{\r\n\ts_check_for_far = true;\r\n\tObj::CCompositeObject *result = sFindNearestMovableCollision(is,p_data,p_callback,p_cache);\r\n\ts_check_for_far = false;\r\n\treturn result;\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCollType\tCCollObj::sConvertTypeChecksum(uint32 checksum)\r\n{\r\n\tCollType c_type;\r\n\r\n\tswitch (checksum)\r\n\t{\r\n\tcase 0x6aadf154: // Geometry\r\n\t\tc_type = vCOLL_TYPE_GEOM;\r\n\t\tbreak;\r\n\r\n\tcase 0xe460abde: // BoundingBox\r\n\tcase 0x2ba71070: // Spherical\r\n\tcase 0xdd42aa66: // Cylindrical\r\n\t\tc_type =  vCOLL_TYPE_BBOX;\r\n\t\tbreak;\r\n\r\n\tcase 0x806fff30: // None\r\n\tdefault:\r\n\t\tc_type = vCOLL_TYPE_NONE;\r\n\t\tbreak;\r\n\t}\r\n\r\n\treturn c_type;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollObj *\tCCollObj::sCreateMovableCollision(CollType type, Nx::CCollObjTriData *p_coll_obj_data, int num_coll_objects, Obj::CCompositeObject *p_object)\r\n{\r\n\tCCollObj *p_collision;\r\n\r\n\tswitch (type)\r\n\t{\r\n\tcase vCOLL_TYPE_BBOX:\r\n\t\t{\r\n\t\t\tCCollMovBBox *p_coll_bbox = new Nx::CCollMovBBox;\r\n\r\n\t\t\t// TODO: determine if we should make more than one collision object\r\n\t\t\tif (num_coll_objects >= 1) {\r\n\t\t\t\tMth::CBBox bbox/*(Mth::Vector(0.0f, 0.0f, 0.0f))*/;\t// Add origin for now\r\n\r\n\t\t\t\tfor (int i = 0; i < num_coll_objects; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tbbox.AddPoint(p_coll_obj_data[i].GetBBox().GetMin());\r\n\t\t\t\t\tbbox.AddPoint(p_coll_obj_data[i].GetBBox().GetMax());\r\n\t\t\t\t}\r\n\r\n\t\t\t\tp_coll_bbox->SetBoundingBox(bbox);\r\n\t\t\t}\r\n\r\n\t\t\tp_collision = p_coll_bbox;\r\n\t\t\tbreak;\r\n\t\t}\r\n\tcase vCOLL_TYPE_GEOM:\r\n\t\tif (num_coll_objects == 1)\t\t\t\t// one node\r\n\t\t{\r\n\t\t\tp_collision = new CCollMovTri(p_coll_obj_data);\r\n\t\t} else if (num_coll_objects > 1) {\t\t// multi nodes\r\n\t\t\tCCollMulti *p_coll_multi = new Nx::CCollMulti;\r\n\r\n\t\t\tfor (int i = 0; i < num_coll_objects; i++)\r\n\t\t\t{\r\n\t\t\t\tCCollObj *p_coll_tri;\r\n\r\n\t\t\t\tp_coll_tri = new CCollMovTri(&(p_coll_obj_data[i]));\r\n\t\t\t\tp_coll_multi->AddCollision(p_coll_tri);\r\n\t\t\t}\r\n\r\n\t\t\tp_collision = p_coll_multi;\r\n\t\t} else {\r\n\t\t\tp_collision = NULL;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\tp_collision = NULL;\t\t\t\t\t\t// default to no collision\r\n\t\tbreak;\r\n\t}\r\n\r\n\t// Add to movable collision manager\r\n\tif (p_collision)\r\n\t{\r\n\t\tp_collision->SetMovingObject(p_object);\r\n\t\tCMovableCollMan::sAddCollision(p_collision, p_object);\r\n\t}\r\n\r\n\treturn p_collision;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollMulti::CCollMulti()\r\n{\r\n\tmp_collision_list = new Lst::Head< CCollObj >;\r\n\tm_movement_changed = true;\r\n\tmp_movable_object = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollMulti::~CCollMulti()\r\n{\r\n\tif (mp_collision_list)\r\n\t{\r\n\t\tLst::Node< CCollObj > *obj_node, *next;\r\n\r\n\t\tfor(obj_node = mp_collision_list->GetNext(); obj_node; obj_node = next)\r\n\t\t{\r\n\t\t\tnext = obj_node->GetNext();\r\n\r\n\t\t\tdelete obj_node->GetData();\r\n\t\t\tdelete obj_node;\r\n\t\t}\r\n\r\n\t\tdelete mp_collision_list;\r\n\t}\r\n\r\n\t// Take out of caches\r\n\tCCollCacheManager::sDeleteCollision(this);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCCollMulti::AddCollision(CCollObj *p_collision)\r\n{\r\n\tLst::Node< CCollObj > *node = new Lst::Node< CCollObj > (p_collision);\r\n\tmp_collision_list->AddToTail(node);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCCollMulti::SetWorldPosition(const Mth::Vector & pos)\r\n{\r\n\tLst::Node< CCollObj > *obj_node;\r\n\r\n\tfor(obj_node = mp_collision_list->GetNext(); obj_node; obj_node = obj_node->GetNext())\r\n\t{\r\n\t\tobj_node->GetData()->SetWorldPosition(pos);\r\n\t}\r\n\r\n\tm_movement_changed = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCCollMulti::SetOrientation(const Mth::Matrix & orient)\r\n{\r\n\tLst::Node< CCollObj > *obj_node;\r\n\r\n\tfor(obj_node = mp_collision_list->GetNext(); obj_node; obj_node = obj_node->GetNext())\r\n\t{\r\n\t\tobj_node->GetData()->SetOrientation(orient);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCCollMulti::SetGeometry(CCollObjTriData *p_geom_data)\r\n{\r\n\tLst::Node< CCollObj > *obj_node;\r\n\r\n\tfor(obj_node = mp_collision_list->GetNext(); obj_node; obj_node = obj_node->GetNext())\r\n\t{\r\n\t\tobj_node->GetData()->SetGeometry(p_geom_data);\r\n\t}\r\n\r\n\tm_movement_changed = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCCollMulti::SetMovingObject(Obj::CCompositeObject *p_movable_object)\r\n{\r\n\tmp_movable_object = p_movable_object;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CCompositeObject * CCollMulti::GetMovingObject() const\r\n{\r\n\treturn mp_movable_object;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollObj * \tCCollMulti::Clone(bool instance)\r\n{\r\n\tDbg_MsgAssert(!instance, (\"CCollMulti::Clone() with instances not implemented yet\"));\r\n\tDbg_Assert(mp_coll_tri_data == NULL);\r\n\r\n\tCCollMulti *m_new_coll = new CCollMulti(*this);\r\n\r\n\tm_new_coll->m_Flags |=  mSD_CLONE;\r\n\r\n\tLst::Node< CCollObj > *obj_node;\r\n\r\n\t// Clone List\r\n\tm_new_coll->mp_collision_list = new Lst::Head< CCollObj >;\r\n\tfor(obj_node = mp_collision_list->GetNext(); obj_node; obj_node = obj_node->GetNext())\r\n\t{\r\n\t\tLst::Node< CCollObj > *node = new Lst::Node< CCollObj > (obj_node->GetData()->Clone(instance));\r\n\t\tm_new_coll->mp_collision_list->AddToTail(node);\r\n\t}\r\n\r\n\treturn m_new_coll;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCCollMulti::IsTriangleCollision() const\r\n{\r\n\tLst::Node< CCollObj > *obj_node;\r\n\tbool ret_val = true;\r\n\r\n\tfor(obj_node = mp_collision_list->GetNext(); obj_node; obj_node = obj_node->GetNext())\r\n\t{\r\n\t\tret_val = ret_val && obj_node->GetData()->IsTriangleCollision();\r\n\t}\r\n\r\n\treturn ret_val;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCCollMulti::update_world_bbox()\r\n{\r\n\tLst::Node< CCollObj > *obj_node;\r\n\r\n\tm_world_bbox_valid = true;\r\n\tm_world_bbox.Reset();\r\n\tfor(obj_node = mp_collision_list->GetNext(); obj_node; obj_node = obj_node->GetNext())\r\n\t{\r\n\t\tMth::CBBox *obj_bbox;\r\n\t\tif ((obj_bbox = obj_node->GetData()->get_bbox()))\r\n\t\t{\r\n\t\t\tm_world_bbox.AddPoint(obj_bbox->GetMin());\r\n\t\t\tm_world_bbox.AddPoint(obj_bbox->GetMax());\r\n\t\t} else {\r\n\t\t\tm_world_bbox_valid = false;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::CBBox *CCollMulti::get_bbox()\r\n{\r\n\tif (m_movement_changed)\r\n\t{\r\n\t\tupdate_world_bbox();\r\n\t\tm_movement_changed = false;\r\n\t}\r\n\r\n\tif (m_world_bbox_valid)\r\n\t{\r\n\t\treturn &m_world_bbox;\r\n\t} else {\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCCollMulti::WithinBBox(const Mth::CBBox & testBBox)\r\n{\r\n\tif (m_movement_changed)\r\n\t{\r\n\t\tupdate_world_bbox();\r\n\t\tm_movement_changed = false;\r\n\t}\r\n\r\n\treturn !m_world_bbox_valid || testBBox.Intersect(m_world_bbox);\r\n\t//return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCCollMulti::CollisionWithLine(const Mth::Line & testLine, const Mth::Vector & lineDir, CollData *p_data, Mth::CBBox * p_bbox)\r\n{\r\n\tLst::Node< CCollObj > *obj_node;\r\n\tbool ret_val = false;\r\n\r\n\tfor(obj_node = mp_collision_list->GetNext(); obj_node; obj_node = obj_node->GetNext())\r\n\t{\r\n\t\tret_val = obj_node->GetData()->CollisionWithLine(testLine, lineDir, p_data, p_bbox) || ret_val;\r\n\t}\r\n\r\n\treturn ret_val;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCCollMulti::CollisionWithRectangle(const Mth::Rectangle& rect, const Mth::CBBox& rect_bbox, S2DCollData* p_data)\r\n{\r\n\tDbg_MsgAssert(false, (\"CCollMulti::CollisionWithRecangle is not implemented\"));\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCCollMulti::DebugRender(uint32 ignore_1, uint32 ignore_0)\r\n{\r\n\tLst::Node< CCollObj > *obj_node;\r\n\r\n\tfor(obj_node = mp_collision_list->GetNext(); obj_node; obj_node = obj_node->GetNext())\r\n\t{\r\n\t\tobj_node->GetData()->DebugRender(ignore_1, ignore_0);\r\n\t}\r\n}\r\n\r\n// Don't call these!\r\n\r\nconst Mth::Vector &\tCCollMulti::GetWorldPosition() const\r\n{\r\n\tDbg_MsgAssert(0, (\"Don't call CCollMulti::GetWorldPosition()\"));\r\n\treturn mp_collision_list->GetNext()->GetData()->GetWorldPosition();\r\n}\r\n\r\nconst Mth::Matrix &\tCCollMulti::GetOrientation() const\r\n{\r\n\tDbg_MsgAssert(0, (\"Don't call CCollMulti::GetOrientation()\"));\r\n\treturn mp_collision_list->GetNext()->GetData()->GetOrientation();\r\n}\r\n\r\nuint32 \t\tCCollMulti::GetFaceFlags(int face_idx) const\r\n{\r\n\tDbg_MsgAssert(0, (\"Don't call CCollMulti::GetFaceFlags()\"));\r\n\treturn 0;\r\n}\r\n\r\nuint16 \t\tCCollMulti::GetFaceTerrainType(int face_idx) const\r\n{\r\n\tDbg_MsgAssert(0, (\"Don't call CCollMulti::GetFaceTerrainType()\"));\r\n\treturn 0;\r\n}\r\n\r\nMth::Vector\tCCollMulti::GetVertexPos(int vert_idx) const\r\n{\r\n\tDbg_MsgAssert(0, (\"Don't call CCollMulti::GetVertexPos()\"));\r\n\treturn Mth::Vector(0, 0, 0, 0);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollMovable::CCollMovable() : \r\n\tm_world_pos(0, 0, 0, 1),\r\n\tm_orient(0, 0, 0),\r\n\tm_orient_transpose(0, 0, 0),\r\n\tmp_movable_object(NULL)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollMovable::~CCollMovable()\r\n{\r\n\t// Take out of caches\r\n\tCCollCacheManager::sDeleteMovableCollision(this);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector\tCCollMovable::GetVertexPos(int vert_idx) const\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\r\n\tMth::Vector pos(mp_coll_tri_data->GetRawVertexPos(vert_idx));\r\n\r\n\tpos[W] = 0.0f;\t\t\t\t// start as vector\r\n\tpos.Rotate(m_orient);\r\n\tpos += m_world_pos;\r\n\r\n\treturn pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCCollMovable::SetMovingObject(Obj::CCompositeObject *p_movable_object)\r\n{\r\n\tmp_movable_object = p_movable_object;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CCompositeObject * CCollMovable::GetMovingObject() const\r\n{\r\n\treturn mp_movable_object;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCCollMovable::convert_line_to_local(const Mth::Line &world_line, Mth::Line &local_line)\r\n{\r\n\tlocal_line = world_line;\r\n\r\n\t// First, translate back\r\n\tlocal_line -= m_world_pos;\r\n\r\n\t// And then do a reverse rotation\r\n\tlocal_line.m_start.Rotate(m_orient_transpose);\r\n\tlocal_line.m_end.Rotate(m_orient_transpose);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollStatic::CCollStatic() //: \r\n//\tm_world_pos(0, 0, 0, 1)//,\r\n//\tm_orient(0, 0, 0)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollStatic::~CCollStatic()\r\n{\r\n\t// Take out of caches\r\n\t//CCollCacheManager::sDeleteStaticCollision(this);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector\tCCollStatic::GetVertexPos(int vert_idx) const\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\r\n\tMth::Vector pos(mp_coll_tri_data->GetRawVertexPos(vert_idx));\r\n\r\n\tpos[W] = 1.0f;\t\t\t\t// make a point\r\n\r\n\treturn pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollMovBBox::CCollMovBBox() :\r\n\tm_flags(0),\r\n\tm_terrain_type(0)\r\n{\r\n\t// Sets a default bounding box, if nothing loaded\r\n\t//m_bbox.Set(Mth::Vector(-60, -20, -60, 1), Mth::Vector(60, 36, 60, 1));\r\n\tm_bbox.Set(Mth::Vector(-50, -20, -90, 1), Mth::Vector(30, 36, 90, 1));\t\t// size of car\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollMovBBox::CCollMovBBox(CCollObjTriData *p_geom_data) :\r\n\tm_flags(0),\r\n\tm_terrain_type(0)\r\n{\r\n\tSetGeometry(p_geom_data);\r\n\tDbg_Assert(mp_coll_tri_data);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollMovBBox::~CCollMovBBox()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCCollMovBBox::SetGeometry(CCollObjTriData *p_geom_data)\r\n{\r\n\tCCollObj::SetGeometry(p_geom_data);\r\n\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\tSetBoundingBox(mp_coll_tri_data->GetBBox());\r\n}\r\n\r\n// Temp functions\r\nuint32 CCollMovBBox::GetFaceFlags(int face_idx) const\r\n{\r\n\treturn m_flags;\r\n}\r\n\r\nuint16 CCollMovBBox::GetFaceTerrainType(int face_idx) const\r\n{\r\n\treturn m_terrain_type;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollObj * \tCCollMovBBox::Clone(bool instance)\r\n{\r\n\tDbg_MsgAssert(!instance, (\"CCollMovBBox::Clone() with instances not implemented yet\"));\r\n\r\n\tCCollMovBBox *m_new_coll = new CCollMovBBox(*this);\r\n\r\n\tm_new_coll->m_Flags |=  mSD_CLONE;\r\n\r\n\tm_new_coll->mp_coll_tri_data = NULL;\t\t// We don't need to clone the data since we have the bbox\r\n\r\n\treturn m_new_coll;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCollMovBBox::CollisionWithLine(const Mth::Line & testLine, const Mth::Vector & lineDir, CollData *p_data, Mth::CBBox *p_bbox)\r\n{\r\n\tDbg_Assert(p_data);\r\n\r\n\t// Find line in local space\r\n\tMth::Line local_line;\r\n\tconvert_line_to_local(testLine, local_line);\r\n\r\n\r\n\tif (0 && GPrintCollisionData)\r\n\t{\r\n\t\tDbg_Message(\"Testing ray with start (%f, %f, %f)\", testLine.m_start[X], testLine.m_start[Y], testLine.m_start[Z]);\r\n\t\tDbg_Message(\"and end (%f, %f, %f)\", testLine.m_end[X], testLine.m_end[Y], testLine.m_end[Z]);\r\n\t\tDbg_Message(\"with the direction (%f, %f, %f)\", lineDir[X], lineDir[Y], lineDir[Z]);\r\n\t}\r\n\r\n\r\n\t// Mick: temp optimization, generate a bounding box for the line\r\n\t// so it can be tested against the collision bounding box\r\n\tMth::CBBox line_bbox(local_line.m_start);\r\n\tline_bbox.AddPoint(local_line.m_end);\r\n\r\n\r\n\t// Do collision\r\n\tif (m_bbox.Intersect(line_bbox))\r\n\t{\r\n\t\tMth::Vector local_point, local_normal;\r\n\r\n\t\tif (m_bbox.LineIntersect(local_line, local_point, local_normal))\r\n\t\t{\r\n\t\t\tfloat distance = Mth::Vector(local_point - local_line.m_start).Length() / \t\t\t// gotta be a faster way\r\n\t\t\t\t\t\t\t Mth::Vector(local_line.m_end - local_line.m_start).Length();\r\n\r\n\t\t\tSCollSurface collisionSurface;\r\n\r\n\t\t\tif (GPrintCollisionData)\r\n\t\t\t{\r\n\t\t\t\tDbg_Message(\"\\n*Start point (%f, %f, %f)\", testLine.m_start[X], testLine.m_start[Y], testLine.m_start[Z]);\r\n\t\t\t\tDbg_Message(\"*End point (%f, %f, %f)\", testLine.m_end[X], testLine.m_end[Y], testLine.m_end[Z]);\r\n\t\t\t\tDbg_Message(\"*Start local point (%f, %f, %f)\", local_line.m_start[X], local_line.m_start[Y], local_line.m_start[Z]);\r\n\t\t\t\tDbg_Message(\"*End local point (%f, %f, %f)\", local_line.m_end[X], local_line.m_end[Y], local_line.m_end[Z]);\r\n\t\t\t\tDbg_Message(\"*World pos (%f, %f, %f)\", m_world_pos[X], m_world_pos[Y], m_world_pos[Z]);\r\n\t\t\t\tDbg_Message(\"*Local collision pos (%f, %f, %f)\", local_point[X], local_point[Y], local_point[Z]);\r\n\t\t\t\tDbg_Message(\"*Local Normal (%f, %f, %f)\", local_normal[X], local_normal[Y], local_normal[Z]);\r\n\t\t\t\tDbg_Message(\"*Orientation [%f, %f, %f]\", m_orient[X][X], m_orient[X][Y], m_orient[X][Z]);\r\n\t\t\t\tDbg_Message(\"*            [%f, %f, %f]\", m_orient[Y][X], m_orient[Y][Y], m_orient[Y][Z]);\r\n\t\t\t\tDbg_Message(\"*            [%f, %f, %f]\", m_orient[Z][X], m_orient[Z][Y], m_orient[Z][Z]);\r\n\t\t\t}\r\n\r\n\t\t\t// Convert to world coordinates\r\n\t\t\tcollisionSurface.point = local_point.Rotate(m_orient);\r\n\t\t\tcollisionSurface.point += m_world_pos;\r\n\t\t\tcollisionSurface.normal = local_normal.Rotate(m_orient);\r\n\r\n\t\t\tif (GPrintCollisionData)\r\n\t\t\t{\r\n\t\t\t\tDbg_Message(\"*Collision pos (%f, %f, %f)\", collisionSurface.point[X], collisionSurface.point[Y], collisionSurface.point[Z]);\r\n\t\t\t\tDbg_Message(\"*Normal (%f, %f, %f)\", collisionSurface.normal[X], collisionSurface.normal[Y], collisionSurface.normal[Z]);\r\n\t\t\t\tDbg_Message(\"*distance %f\", distance);\r\n\t\t\t}\r\n\r\n\t\t\treturn s_found_collision(&testLine, this, &collisionSurface, distance, p_data);\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCollMovBBox::CollisionWithRectangle(const Mth::Rectangle& rect, const Mth::CBBox& rect_bbox, S2DCollData* p_data)\r\n\r\n{\r\n\tDbg_MsgAssert(false, (\"CCollMovBBox::CollisionWithRecangle is not implemented\"));\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollMovBBox::DebugRender(uint32 ignore_1, uint32 ignore_0)\r\n{\r\n\t// Debug box\r\n\tMth::Matrix total_mat = m_orient;\r\n\ttotal_mat[W] = m_world_pos;\r\n\tm_bbox.DebugRender(total_mat, 0x80808080, 1);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollStaticTri::CCollStaticTri()\r\n{\r\n\t// This instance can't be used until someone sets the geometry data\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollStaticTri::~CCollStaticTri()\r\n{\r\n\t// Don't delete the Tri Data\r\n}\r\n\r\n// Temp functions\r\nuint32 CCollStaticTri::GetFaceFlags(int face_idx) const\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\treturn mp_coll_tri_data->GetFaceFlags(face_idx);\r\n}\r\n\r\nuint16 CCollStaticTri::GetFaceTerrainType(int face_idx) const\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\treturn mp_coll_tri_data->GetFaceTerrainType(face_idx);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollStaticTri::SetWorldPosition(const Mth::Vector & pos)\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\tmp_coll_tri_data->Translate(pos - GetWorldPosition());\r\n\r\n\tCCollStatic::SetWorldPosition(pos);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \tCCollStaticTri::SetOrientation(const Mth::Matrix & orient)\r\n{\r\n\tCCollStatic::SetOrientation(orient);\r\n\r\n\tDbg_MsgAssert(0, (\"CCollStaticTri::SetOrientation() not implemented yet\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollObj * \tCCollStaticTri::Clone(bool instance)\r\n{\r\n\tDbg_MsgAssert(!instance, (\"CCollStaticTri::Clone() with instances not implemented yet\"));\r\n\r\n\t// Clone only if there is geometry\r\n\tCCollObjTriData *p_new_tri_data = mp_coll_tri_data->Clone(instance, true);\r\n\tif (!p_new_tri_data)\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tCCollStaticTri *p_new_coll = new CCollStaticTri(*this);\r\n\r\n\tp_new_coll->m_Flags |=  mSD_CLONE;\r\n\r\n\tp_new_coll->mp_coll_tri_data = p_new_tri_data;\r\n\r\n\treturn p_new_coll;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollStaticTri::RotateY(const Mth::Vector & world_origin, Mth::ERot90 rot_y)\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\r\n\tmp_coll_tri_data->RotateY(world_origin, rot_y);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollStaticTri::Scale(const Mth::Vector & world_origin, const Mth::Vector & scale)\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\r\n\tmp_coll_tri_data->Scale(world_origin, scale);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCollStaticTri::WithinBBox(const Mth::CBBox & testBBox)\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\treturn testBBox.Intersect(mp_coll_tri_data->GetBBox());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCollStaticTri::CollisionWithLine(const Mth::Line & testLine, const Mth::Vector & lineDir, CollData *p_data, Mth::CBBox *p_bbox)\r\n{\r\n\tDbg_Assert(p_data);\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\r\n\tbool best_collision = false;\r\n\r\n\t// Generate a bounding box for the line\r\n\t// so it can be tested against the BSP tree.\t  \r\n\t// (Should we just pass along the one we had before, even though it won't work with movables?)\r\n//\tMth::CBBox line_bbox(testLine.m_start);\r\n//\tline_bbox.AddPoint(testLine.m_end);\r\n\r\n\tuint num_faces;\r\n\tFaceIndex *p_face_indexes;\r\n\tp_face_indexes = mp_coll_tri_data->FindIntersectingFaces(*p_bbox, num_faces);\r\n\tDbg_Assert(p_face_indexes);\r\n\r\n#ifdef BATCH_TRI_COLLISION\r\n\tbool do_batch = !CBatchTriCollMan::sIsNested();\r\n#endif\r\n\r\n\tfor (uint fidx = 0; fidx < num_faces; fidx++, p_face_indexes++)\r\n\t{\r\n#ifdef BATCH_TRI_COLLISION\r\n\t\tif (do_batch)\r\n\t\t{\r\n\t\t\tCBatchTriCollMan::sAddTriCollision(testLine, lineDir, this, *p_face_indexes);\r\n\t\t\tcontinue;\r\n\t\t}\r\n#endif // BATCH_TRI_COLLISION\r\n\r\n#if defined(FIXED_POINT_VERTICES) || defined(__PLAT_NGC__)\r\n\t\tMth::Vector v0, v1, v2;\r\n\t\tif (mp_coll_tri_data->m_use_face_small)\r\n\t\t{\r\n\t\t\tCCollObjTriData::SFaceSmall *face = &(mp_coll_tri_data->mp_face_small[*p_face_indexes]);\r\n\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[0], v0);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[1], v1);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[2], v2);\r\n\t\t} else {\r\n\t\t\tCCollObjTriData::SFace *face = &(mp_coll_tri_data->mp_faces[*p_face_indexes]);\r\n\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[0], v0);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[1], v1);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[2], v2);\r\n\t\t}\r\n#else\r\n\t\tMth::Vector *v0, *v1, *v2;\r\n\t\tif (mp_coll_tri_data->m_use_face_small)\r\n\t\t{\r\n\t\t\tCCollObjTriData::SFaceSmall *face = &(mp_coll_tri_data->mp_face_small[*p_face_indexes]);\r\n\r\n\t\t\tv0 = &mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];\r\n\t\t\tv1 = &mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];\r\n\t\t\tv2 = &mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];\r\n\t\t} else {\r\n\t\t\tCCollObjTriData::SFace *face = &(mp_coll_tri_data->mp_faces[*p_face_indexes]);\r\n\r\n\t\t\tv0 = &mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];\r\n\t\t\tv1 = &mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];\r\n\t\t\tv2 = &mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];\r\n\t\t}\r\n#endif // FIXED_POINT_VERTICES\r\n\r\n#if 0\r\n\t\tuint32 coll_color = (uint32) MAKE_RGB(200, 200, 200);\r\n\t\tif (coll_color != (uint32) MAKE_RGB( 0, 200, 0 ))\r\n\t\t{\r\n\t\t\tGfx::AddDebugLine(*v0,*v1,coll_color,1);\r\n\t\t\tGfx::AddDebugLine(*v1,*v2,coll_color,1);\r\n\t\t\tGfx::AddDebugLine(*v2,*v0,coll_color,1);\r\n\t\t}\r\n#endif\r\n\r\n\t\tfloat distance;\r\n#if defined(FIXED_POINT_VERTICES) || defined(__PLAT_NGC__)\r\n\t\tif (sRayTriangleCollision(&testLine.m_start, &lineDir, &v0, &v1, &v2, &distance))\r\n#else\r\n\t\tif (sRayTriangleCollision(&testLine.m_start, &lineDir, v0, v1, v2, &distance))\r\n#endif\r\n\t\t{\r\n\t\t\tSCollSurface collisionSurface;\r\n\r\n\t\t\t/* We've got one */\r\n#if defined(FIXED_POINT_VERTICES) || defined(__PLAT_NGC__)\r\n\t\t\tcollisionSurface.point = v0;\r\n\t\t\tcollisionSurface.index = *p_face_indexes;\r\n\r\n\t\t\t// Find normal\r\n\t\t\tMth::Vector vTmp1(v1 - v0);\r\n\t\t\tMth::Vector vTmp2(v2 - v0);\r\n#else\r\n\t\t\tcollisionSurface.point = (*v0);\r\n\t\t\tcollisionSurface.index = *p_face_indexes;\r\n\r\n\t\t\t// Find normal\r\n\t\t\tMth::Vector vTmp1(*v1 - *v0);\r\n\t\t\tMth::Vector vTmp2(*v2 - *v0);\r\n#endif // FIXED_POINT_VERTICES\r\n\t\t\tcollisionSurface.normal = Mth::CrossProduct(vTmp1, vTmp2);\r\n\t\t\tcollisionSurface.normal.Normalize();\r\n\r\n\t\t\tif (s_found_collision(&testLine, this, &collisionSurface, distance, p_data))\r\n\t\t\t{\r\n\t\t\t\tbest_collision = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n#ifdef BATCH_TRI_COLLISION\r\n\tif (do_batch)\r\n\t{\r\n\t\tCBatchTriCollMan::sStartNewTriCollisions();\r\n\t}\r\n#endif // BATCH_TRI_COLLISION\r\n\r\n\treturn best_collision;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCollStaticTri::CollisionWithRectangle(const Mth::Rectangle& testRect, const Mth::CBBox& testRectBBox, S2DCollData *p_coll_data)\r\n{\r\n\tDbg_Assert(p_coll_data);\r\n\t\r\n\tuint num_faces;\r\n\tFaceIndex* p_face_indexes = mp_coll_tri_data->FindIntersectingFaces(testRectBBox, num_faces);\r\n\tDbg_Assert(p_face_indexes);\r\n\t\r\n\t// loop over the relavent faces of the sector\r\n\tfor (uint fidx = 0; fidx < num_faces; fidx++, p_face_indexes++)\r\n\t{\r\n\t\tuint32 face_flags = GetFaceFlags(fidx);\r\n\t\tif ((face_flags & p_coll_data->ignore_1) || (~face_flags & p_coll_data->ignore_0)) continue;\r\n\r\n#if defined(FIXED_POINT_VERTICES) || defined(__PLAT_NGC__)\r\n\t\tMth::Vector v0, v1, v2;\r\n\t\tif (mp_coll_tri_data->m_use_face_small)\r\n\t\t{\r\n\t\t\tCCollObjTriData::SFaceSmall *face = &(mp_coll_tri_data->mp_face_small[*p_face_indexes]);\r\n\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[0], v0);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[1], v1);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[2], v2);\r\n\t\t} else {\r\n\t\t\tCCollObjTriData::SFace *face = &(mp_coll_tri_data->mp_faces[*p_face_indexes]);\r\n\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[0], v0);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[1], v1);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[2], v2);\r\n\t\t}\r\n#else\r\n\t\tMth::Vector v0, v1, v2;\r\n\t\tif (mp_coll_tri_data->m_use_face_small)\r\n\t\t{\r\n\t\t\tCCollObjTriData::SFaceSmall *face = &(mp_coll_tri_data->mp_face_small[*p_face_indexes]);\r\n\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[0], v0);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[1], v1);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[2], v2);\r\n\t\t} else {\r\n\t\t\tCCollObjTriData::SFace *face = &(mp_coll_tri_data->mp_faces[*p_face_indexes]);\r\n\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[0], v0);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[1], v1);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[2], v2);\r\n\t\t}\r\n\t\t\r\n#endif // FIXED_POINT_VERTICES\r\n\r\n\t\tMth::Vector p_coll_point[2];\r\n\t\tETriangleEdgeType p_triangle_edge[2];\r\n\r\n\t\tif (sRectangleTriangleCollision(&testRect, &v0, &v1, &v2, p_coll_point, p_triangle_edge))\r\n\t\t{\r\n\t\t\tif (p_coll_data->num_surfaces == MAX_NUM_2D_COLLISIONS_REPORTED)\r\n\t\t\t{\r\n\t\t\t\tDbg_Message(\"Number of faces colliding with rectangle exceeds static maximum; dropping additional collisions\");\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// add the face to the collided surface list\r\n\t\t\tS2DCollSurface& surface = p_coll_data->p_surfaces[p_coll_data->num_surfaces];\r\n\t\t\tsurface.normal = Mth::CrossProduct(v1 - v0, v2 - v0).Normalize();\r\n\r\n\t\t\t// ignore triangles with zero area\r\n\t\t\tif (surface.normal.LengthSqr() <= 0.0f)\tcontinue;\r\n\t\t\t\r\n\t\t\tsurface.trigger = (face_flags & mFD_TRIGGER);\r\n\t\t\tsurface.node_name = this->GetChecksum();\r\n\t\t\t\r\n\t\t\tsurface.ends[0].point = p_coll_point[0];\r\n\t\t\tsurface.ends[1].point = p_coll_point[1];\r\n\r\n\t\t\tfor (int end_idx = 2; end_idx--; )\r\n\t\t\t{\r\n\t\t\t\tsurface.ends[end_idx].tangent_exists = p_triangle_edge[end_idx] != NO_TRIANGLE_EDGE;\r\n\t\t\t\tswitch (p_triangle_edge[end_idx])\r\n\t\t\t\t{\r\n\t\t\t\t\tcase TRIANGLE_EDGE_V0_V1:\r\n\t\t\t\t\t\tsurface.ends[end_idx].tangent = (v1 - v0).Normalize();\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase TRIANGLE_EDGE_V1_V2:\r\n\t\t\t\t\t\tsurface.ends[end_idx].tangent = (v2 - v1).Normalize();\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase TRIANGLE_EDGE_V2_V0:\r\n\t\t\t\t\t\tsurface.ends[end_idx].tangent = (v0 - v2).Normalize();\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase NO_TRIANGLE_EDGE:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tp_coll_data->num_surfaces++;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn p_coll_data->num_surfaces > 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollStaticTri::DebugRender(uint32 ignore_1, uint32 ignore_0)\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\tmp_coll_tri_data->DebugRender(ignore_1, ignore_0);\r\n}\r\n\r\nvoid\tCCollStaticTri::ProcessOcclusion()\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\tmp_coll_tri_data->ProcessOcclusion();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollStaticTri::CheckForHoles()\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n#ifdef\t__DEBUG_CODE__\r\n\tmp_coll_tri_data->CheckForHoles();\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollMovTri::CCollMovTri()\r\n{\r\n\t// This instance can't be used until someone sets the geometry data\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollMovTri::CCollMovTri(CCollObjTriData *p_coll_data) :\r\n\tCCollMovable()\r\n{\r\n\tSetGeometry(p_coll_data);\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\r\n\t//m_movement_changed = false;\r\n\tm_movement_changed = true;\t\t// to update m_world_bbox\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollMovTri::~CCollMovTri()\r\n{\r\n\t// Don't delete the Tri Data\r\n}\r\n\r\n// Temp functions\r\nuint32 CCollMovTri::GetFaceFlags(int face_idx) const\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\treturn mp_coll_tri_data->GetFaceFlags(face_idx);\r\n}\r\n\r\nuint16 CCollMovTri::GetFaceTerrainType(int face_idx) const\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\treturn mp_coll_tri_data->GetFaceTerrainType(face_idx);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCCollMovTri::SetGeometry(CCollObjTriData *p_geom_data)\r\n{\r\n\tCCollObj::SetGeometry(p_geom_data);\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\t\r\n\t// Re-calculate radius\r\n\tfloat new_length;\r\n\tm_max_radius = 0.0f;\r\n\tfor (int i = 0; i < mp_coll_tri_data->m_num_verts; i++)\r\n\t{\r\n\t\tnew_length = mp_coll_tri_data->GetRawVertexPos(i).Length();\r\n\t\tif (new_length > m_max_radius)\r\n\t\t{\r\n\t\t\tm_max_radius = new_length;\r\n\t\t}\r\n\t}\r\n\r\n\tm_movement_changed = true;\t\t// to update m_world_bbox\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollObj * \tCCollMovTri::Clone(bool instance)\r\n{\r\n\tDbg_MsgAssert(!instance, (\"CCollMovTri::Clone() with instances not implemented yet\"));\r\n\r\n\tCCollMovTri *m_new_coll = new CCollMovTri(*this);\r\n\r\n\tm_new_coll->m_Flags |=  mSD_CLONE;\r\n\r\n\tm_new_coll->mp_coll_tri_data = mp_coll_tri_data->Clone(instance);\r\n\r\n\treturn m_new_coll;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCollMovTri::WithinBBox(const Mth::CBBox & testBBox)\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\r\n\tif (m_movement_changed)\r\n\t{\r\n\t\tupdate_world_bbox();\r\n\t\tm_movement_changed = false;\r\n\t}\r\n\r\n\treturn testBBox.Intersect(m_world_bbox);\r\n\t//return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCollMovTri::CollisionWithLine(const Mth::Line & testLine, const Mth::Vector & lineDir, CollData *p_data, Mth::CBBox *p_bbox)\r\n{\r\n\tDbg_Assert(p_data);\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\r\n\tbool best_collision = false;\r\n\r\n\t// Find line in local space\r\n\tMth::Line local_line;\r\n\tconvert_line_to_local(testLine, local_line);\r\n\tMth::Vector local_line_dir(local_line.m_end - local_line.m_start);\r\n\r\n\t// Generate a bounding box for the line\r\n\t// so it can be tested against the BSP tree\r\n\tMth::CBBox line_bbox(local_line.m_start);\r\n\tline_bbox.AddPoint(local_line.m_end);\r\n\r\n\tuint num_faces;\r\n\tFaceIndex *p_face_indexes;\r\n\tp_face_indexes = mp_coll_tri_data->FindIntersectingFaces(line_bbox, num_faces);\r\n\r\n\tfor (uint fidx = 0; fidx < num_faces; fidx++, p_face_indexes++)\r\n\t{\r\n#if defined(FIXED_POINT_VERTICES) || defined(__PLAT_NGC__)\r\n\t\tMth::Vector v0, v1, v2;\r\n\t\tif (mp_coll_tri_data->m_use_face_small)\r\n\t\t{\r\n\t\t\tCCollObjTriData::SFaceSmall *face = &(mp_coll_tri_data->mp_face_small[*p_face_indexes]);\r\n\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[0], v0);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[1], v1);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[2], v2);\r\n\t\t} else {\r\n\t\t\tCCollObjTriData::SFace *face = &(mp_coll_tri_data->mp_faces[*p_face_indexes]);\r\n\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[0], v0);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[1], v1);\r\n\t\t\tmp_coll_tri_data->GetRawVertexPos(face->m_vertex_index[2], v2);\r\n\t\t}\r\n#else\r\n\t\tMth::Vector *v0, *v1, *v2;\r\n\t\tif (mp_coll_tri_data->m_use_face_small)\r\n\t\t{\r\n\t\t\tCCollObjTriData::SFaceSmall *face = &(mp_coll_tri_data->mp_face_small[*p_face_indexes]);\r\n\r\n\t\t\tv0 = &mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];\r\n\t\t\tv1 = &mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];\r\n\t\t\tv2 = &mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];\r\n\t\t} else {\r\n\t\t\tCCollObjTriData::SFace *face = &(mp_coll_tri_data->mp_faces[*p_face_indexes]);\r\n\r\n\t\t\tv0 = &mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];\r\n\t\t\tv1 = &mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];\r\n\t\t\tv2 = &mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];\r\n\t\t}\r\n#endif // FIXED_POINT_VERTICES\r\n\r\n\t\tfloat distance;\r\n#if defined(FIXED_POINT_VERTICES) || defined(__PLAT_NGC__)\r\n\t\tif (sRayTriangleCollision(&local_line.m_start, &local_line_dir, &v0, &v1, &v2, &distance))\r\n#else\r\n\t\tif (sRayTriangleCollision(&local_line.m_start, &local_line_dir, v0, v1, v2, &distance))\r\n#endif\r\n\t\t{\r\n\t\t\tSCollSurface collisionSurface;\r\n\r\n\t\t\t/* We've got one */\r\n#if defined(FIXED_POINT_VERTICES) || defined(__PLAT_NGC__)\r\n\t\t\tcollisionSurface.point = v0;\r\n\t\t\tcollisionSurface.index = *p_face_indexes;\r\n\r\n\t\t\t// Find normal\r\n\t\t\tMth::Vector vTmp1(v1 - v0);\r\n\t\t\tMth::Vector vTmp2(v2 - v0);\r\n#else\r\n\t\t\tcollisionSurface.point = (*v0);\r\n\t\t\tcollisionSurface.index = *p_face_indexes;\r\n\r\n\t\t\t// Find normal\r\n\t\t\tMth::Vector vTmp1(*v1 - *v0);\r\n\t\t\tMth::Vector vTmp2(*v2 - *v0);\r\n#endif // FIXED_POINT_VERTICES\r\n\t\t\tcollisionSurface.normal = Mth::CrossProduct(vTmp1, vTmp2);\r\n\t\t\tcollisionSurface.normal.Normalize();\r\n\r\n\t\t\t// Convert to world coordinates\r\n\t\t\tcollisionSurface.point.Rotate(m_orient);\r\n\t\t\tcollisionSurface.point += m_world_pos;\r\n\t\t\tcollisionSurface.normal.Rotate(m_orient);\r\n\r\n\t\t\tif (s_found_collision(&testLine, this, &collisionSurface, distance, p_data))\r\n\t\t\t{\r\n\t\t\t\tbest_collision = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn best_collision;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCollMovTri::CollisionWithRectangle(const Mth::Rectangle& rect, const Mth::CBBox& rect_bbox, S2DCollData* p_data)\r\n{\r\n\tDbg_MsgAssert(false, (\"CCollMovTri::CollisionWithRecangle is not implemented\"));\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollMovTri::DebugRender(uint32 ignore_1, uint32 ignore_0)\r\n{\r\n\t// Debug box\r\n\tMth::Matrix total_mat = m_orient;\r\n\ttotal_mat[W] = m_world_pos;\r\n\tmp_coll_tri_data->DebugRender(total_mat, ignore_1, ignore_0);\r\n}\r\n\r\n} // namespace Nx\r\n\r\n"
  },
  {
    "path": "Code/Gel/Collision/Collision.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNx\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCollision.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t02/15/2002\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__GEL_COLLISION_H\r\n#define\t__GEL_COLLISION_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n\r\n#include <gfx/Image/ImageBasic.h>\r\n#include <gfx/nxflags.h>\r\n\r\n#include <gel/collision/collenums.h>\r\n#include <gel/collision/colltridata.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\tclass CCompositeObject;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\t\r\nconst int MAX_NUM_2D_COLLISIONS_REPORTED = 32;\r\n\r\n\r\n// Forward declarations\r\nclass CCollObj;\r\nclass CCollMulti;\r\nclass CCollStatic;\r\nstruct CollData;\r\nclass CBatchTriCollMan;\r\nclass CCollCache;\r\n\r\nstruct SCollSurface\r\n{\r\n    Mth::Vector\tnormal;\t\t\t/**< Triangle normal */\r\n    Mth::Vector\tpoint;\t\t\t/**< First triangle vertex */\r\n    int\t\t\tindex;\t\t\t/**< Index of surface in object (if applicable) */\r\n    //Mth::Vector * vertices[3];\t/**< Pointers to three triangle vertices */\r\n};\r\n\r\n// structure used to record the collision of a single triangle with a 2D object; a collision test for a 2D object will generate a set of these\r\nstruct S2DCollSurface\r\n{\r\n\tstruct S2DCollEndpoint\r\n\t{\r\n\t\tMth::Vector point;\t\t\t// endpoint position\r\n\t\tMth::Vector tangent;\t\t// normalized tangent vector to the endpoint\r\n\t\tchar tangent_exists;\t\t// if a tangent of the endpoint is defined\r\n\t};\r\n\t\r\n\tS2DCollEndpoint ends[2];\t\t// endpoints of the line cut through the triangle by the collision\r\n\t\r\n\tMth::Vector\tnormal;\t\t\t\t// normal of the collided triangle\r\n\t\r\n\tuint32 node_name;\r\n\tchar trigger;\r\n};\r\n\r\nstruct CollData\r\n{\r\n\tSCollSurface\tsurface;\r\n\tfloat\tdist;   \r\n\tuint16\tignore_1;\t\t\t// bitmask, ignore poly if flags matching tis mask are 1\r\n\tuint16\tignore_0;\t\t\t// ditto, but for flags that are 0\r\n\tuint16\tflags;\r\n\tETerrainType terrain;\r\n\tCCollObj *p_coll_object;\t// the sector (object) with which we collided\r\n\tuint32\tnode_name;\t\t\t// checsum of name of node associated with this object\r\n\tuint32\tscript;\t\t\t\t// set to the script checksum of the object (or NULL if none)\r\n\tvoid\t(*callback)( CollData* p_col_data);\t   // a callback called every frame\r\n\tvoid \t*p_callback_data;\t\t// \tpointer to some data the callback can use\r\n\r\n\tObj::CCompositeObject *mp_callback_object;\t// set only during callbacks\r\n\t\r\n\tchar \tcoll_found;\r\n\tchar\ttrigger;\t\t\t// true if it was a trigger\t(if mFD_TRIGGER flag is set on the colliding face)\r\n};\r\n\r\n// collision data generated by a collision test for a 2D object\r\nstruct S2DCollData\r\n{\r\n\tS2DCollSurface\tp_surfaces[MAX_NUM_2D_COLLISIONS_REPORTED];\t// surfaces collided with\r\n\tint \t\t\tnum_surfaces;\t\t\t\t\t\t\t\t// number of surfaces collided with\r\n\tuint16\t\t\tignore_1;\r\n\tuint16\t\t\tignore_0;\r\n};\r\n\r\n// enum used internally by the rectangle collision code to keep track of which triangle edge a collision line endpoint is at\r\nenum ETriangleEdgeType\r\n{\r\n\tNO_TRIANGLE_EDGE, TRIANGLE_EDGE_V0_V1, TRIANGLE_EDGE_V1_V2, TRIANGLE_EDGE_V2_V0\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n////////////////////////////////////////////////////////////////\r\n// The base class for collision\r\nclass CCollObj\r\n{\r\npublic:\r\n\t\t\t\t\t\tCCollObj();\r\n\tvirtual\t\t\t\t~CCollObj();\r\n\r\n\tuint32\t\t\t\tGetChecksum() const;\r\n\tvoid\t\t\t\tSetChecksum(uint32 checksum);\t// For cloning\r\n\tuint16\t\t\t\tGetObjectFlags() const;\r\n\tvoid\t\t\t\tSetObjectFlags(uint16 flags);\r\n\tvoid\t\t\t\tClearObjectFlags(uint16 flags);\r\n\r\n\t//\r\n\tvirtual bool\t\tIsTriangleCollision() const { return false; }\t// by default, no triangle collision\r\n\r\n\t//\r\n\tvirtual uint32\t\tGetFaceFlags(int face_idx) const = 0;\r\n\tvirtual uint16\t\tGetFaceTerrainType(int face_idx) const = 0;\r\n\r\n\t//\r\n\tvirtual void\t\tSetGeometry(CCollObjTriData *p_geom_data);\r\n\tCCollObjTriData *\tGetGeometry() const;\r\n\r\n\t//\r\n\tvirtual void\t\tSetWorldPosition(const Mth::Vector & pos) = 0;\r\n\tvirtual void\t\tSetOrientation(const Mth::Matrix & orient) = 0;\r\n\r\n\t// The Get functions are virtual in case Static and Movable differ at a later point\r\n\tvirtual const Mth::Vector &\tGetWorldPosition() const = 0;\r\n\tvirtual const Mth::Matrix &\tGetOrientation() const = 0;\r\n\tvirtual Mth::Vector GetVertexPos(int vert_idx) const = 0;\r\n\r\n\tvirtual Obj::CCompositeObject *GetMovingObject() const;\r\n\tvirtual void\t\t\t\tSetMovingObject(Obj::CCompositeObject *p_movable_object);\r\n\r\n\t// Clone\r\n\tvirtual CCollObj *\tClone(bool instance = false) = 0;\r\n\r\n\t// The virtual collision functions\r\n\tvirtual bool\t\tWithinBBox(const Mth::CBBox & testBBox) = 0;\t\t// VERY quick test to see if we're in bbox range.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Derived class may always return TRUE if it isn't\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// worth checking.\r\n\tvirtual bool\t\tCollisionWithLine(const Mth::Line & testLine, const Mth::Vector & lineDir, CollData *p_data,  Mth::CBBox *p_bbox) = 0;\r\n\tvirtual bool\t\tCollisionWithRectangle(const Mth::Rectangle& testRect, const Mth::CBBox& testRectBBox, S2DCollData *p_coll_data) = 0;\r\n\r\n\t// Wireframe drawing\r\n\tvirtual void\t\tDebugRender(uint32 ignore_1, uint32 ignore_0) = 0;\r\n\r\n\t// Conversion functions\r\n\tstatic CollType\t\tsConvertTypeChecksum(uint32 checksum);\r\n\r\n\t// Collision creation\r\n\tstatic CCollObj *\tsCreateStaticCollision(CollType type, Nx::CCollObjTriData *p_coll_obj_data, int num_coll_objects);\r\n\tstatic CCollObj *\tsCreateMovableCollision(CollType type, Nx::CCollObjTriData *p_coll_obj_data, int num_coll_objects,\r\n\t\t\t\t\t\t\t\t\t\t\t\tObj::CCompositeObject *p_object);\r\n\r\n\t// Does collision against all the static collision in the SuperSectors\r\n\tstatic bool\t\t\tsFindNearestStaticCollision(Mth::Line &is, CollData *p_data, void *p_callback = NULL, CCollCache *p_cache = NULL);\r\n\tstatic bool\t\t\tsFindFarStaticCollision(Mth::Line &is, CollData *p_data, void *p_callback = NULL, CCollCache *p_cache = NULL);\r\n\r\n\t// Does collision against all the movable collision\r\n\tstatic Obj::CCompositeObject *\tsFindNearestMovableCollision(Mth::Line &is, CollData *p_data, void *p_callback = NULL, CCollCache *p_cache = NULL);\r\n\tstatic Obj::CCompositeObject *\tsFindFarMovableCollision(Mth::Line &is, CollData *p_data, void *p_callback = NULL, CCollCache *p_cache = NULL);\r\n\r\n\t// Does rect collision against all the static collision\r\n\tstatic bool\t\t\tsFindRectangleStaticCollision(Mth::Rectangle& rect, S2DCollData* p_coll_data, CCollCache* p_cache = NULL);\r\n\t\r\n\t// Triangle collision function\r\n\tstatic bool\t\t\tsRayTriangleCollision(const Mth::Vector *rayStart, const Mth::Vector *rayDir,\r\n\t\t\t\t\t\t\t\t\t\t\t  Mth::Vector *v0, Mth::Vector *v1, Mth::Vector *v2, float *distance);\r\n\t\r\n\tstatic bool\t\t\tsRectangleTriangleCollision(const Mth::Rectangle *rect,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst Mth::Vector *v0, const Mth::Vector *v1, const Mth::Vector *v2,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tMth::Vector p_collision_endpoints[2], ETriangleEdgeType p_collision_triangle_edges[2] );\r\n\t\r\n\t// 2D line-line collision function\r\n\tstatic bool\t\t\ts2DLineLineCollision ( float p_start_X, float p_start_Y, float p_delta_X, float p_delta_Y,\r\n\t\t\t\t\t\t\t\t\t\t\t   float q_start_X, float q_start_Y, float q_delta_X, float q_delta_Y, float *s );\r\n\t\r\nprotected:\r\n\tvirtual Mth::CBBox *get_bbox();\t\t\t\t\t\t\t\t\t\t\t// Gets the quick bbox\r\n\r\n\t// Called on every collision found.  Returns true if this was the best collision so far.\r\n\tstatic bool\t\t\ts_found_collision(const Mth::Line *p_is, CCollObj *p_coll_object, SCollSurface *p_collSurface,\r\n\t\t\t\t\t\t\t\t\t\t  float distance, CollData *p_collData);\r\n\r\n\tuint32\t\t\t\tm_checksum;\r\n\tuint16\t\t\t\tm_Flags;\r\n\r\n\t// Triangle data, similar to CCollSector's\r\n\tCCollObjTriData\t\t*mp_coll_tri_data;\r\n\r\n\tstatic const float\tsLINE_BOX_EXTENT;\t\t\t\t // Extent of box around collision line\r\n\r\n\t// Friends\r\n\tfriend CCollMulti;\r\n\tfriend CBatchTriCollMan;\r\n\tfriend CCollCache;\r\n};\r\n\r\n////////////////////////////////////////////////////////////////\r\n// Collision List\r\nclass CCollMulti : public CCollObj\r\n{\r\npublic:\r\n\t\t\t\t\t\tCCollMulti();\r\n\tvirtual\t\t\t\t~CCollMulti();\r\n\r\n\t//\r\n\tvirtual bool\t\tIsTriangleCollision() const;\r\n\r\n\t//\r\n\tvirtual void\t\tSetWorldPosition(const Mth::Vector & pos);\r\n\tvirtual void\t\tSetOrientation(const Mth::Matrix & orient);\r\n\t// The following Get functions must be defined, but should never be called\r\n\tvirtual void\t\tSetGeometry(CCollObjTriData *p_geom_data);\r\n\tvirtual const Mth::Vector &\tGetWorldPosition() const;\r\n\tvirtual const Mth::Matrix &\tGetOrientation() const;\r\n\tvirtual uint32\t\tGetFaceFlags(int face_idx) const;\r\n\tvirtual uint16\t\tGetFaceTerrainType(int face_idx) const;\r\n\tvirtual Mth::Vector GetVertexPos(int vert_idx) const;\r\n\r\n\tvirtual Obj::CCompositeObject *GetMovingObject() const;\r\n\tvirtual void\t\tSetMovingObject(Obj::CCompositeObject *p_movable_object);\r\n\r\n\t// Add to collision list\r\n\tvoid\t\t\t\tAddCollision(CCollObj *p_collision);\r\n\r\n\t// Clone\r\n\tvirtual CCollObj *\tClone(bool instance = false);\r\n\r\n\t// The virtual collision functions\r\n\tvirtual bool\t\tWithinBBox(const Mth::CBBox & testBBox);\t\t\t// VERY quick test to see if we're in bbox range.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Derived class may always return TRUE if it isn't\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// worth checking.\r\n\tvirtual bool\t\tCollisionWithLine(const Mth::Line & testLine, const Mth::Vector & lineDir, CollData *p_data, Mth::CBBox *p_bbox);\r\n\tvirtual bool\t\tCollisionWithRectangle(const Mth::Rectangle& testRect, const Mth::CBBox& testRectBBox, S2DCollData *p_coll_data);\r\n\r\n\t// Wireframe drawing\r\n\tvirtual void\t\tDebugRender(uint32 ignore_1, uint32 ignore_0);\r\n\r\nprotected:\r\n\tvirtual Mth::CBBox *get_bbox();\t\t\t\t\t\t\t\t\t\t\t// Gets the quick bbox\r\n\r\nprivate:\r\n\tvoid\t\t\t\tupdate_world_bbox();\r\n\r\n\t// \r\n\tLst::Head<CCollObj> *mp_collision_list;\r\n\tMth::CBBox\t\t\tm_world_bbox;\r\n\tbool\t\t\t\tm_movement_changed;\t\t\t\t// Set to true every time SetWorldPosition() is called\r\n\tbool\t\t\t\tm_world_bbox_valid;\r\n\r\n\t// Pointer to moving object\r\n\tObj::CCompositeObject\t*mp_movable_object;\r\n};\r\n\r\n////////////////////////////////////////////////////////////////\r\n// Static object collision\r\nclass CCollStatic : public CCollObj\r\n{\r\npublic:\r\n\tvirtual\t\t\t\t~CCollStatic();\r\n\r\n\t//\r\n\tvirtual void\t\tSetWorldPosition(const Mth::Vector & pos);\r\n\tvirtual void\t\tSetOrientation(const Mth::Matrix & orient);\r\n\tvirtual const Mth::Vector &\tGetWorldPosition() const;\r\n\tvirtual const Mth::Matrix &\tGetOrientation() const;\r\n\tvirtual Mth::Vector GetVertexPos(int vert_idx) const;\r\n\r\n\t// SuperSector ID access\r\n\tuint8\t\t\t\tGetSuperSectorID() const;\r\n\tvoid\t\t\t\tSetSuperSectorID(uint8);\r\n\r\n\tvirtual void\t\tRotateY(const Mth::Vector & world_origin, Mth::ERot90 rot_y) = 0;\r\n\tvirtual void\t\tScale(const Mth::Vector & world_origin, const Mth::Vector& scale) = 0;\r\n\r\n\r\nprotected:\r\n\t\t\t\t\t\tCCollStatic();\t// Only the derived classes should call this\r\n\r\n\t// The position and orientation are already factored into the collision\r\n\t// data, unlike the Movable counterpart.\r\n//\tMth::Vector\t\t\tm_world_pos;\r\n//\tMth::Matrix\t\t\tm_orient;\r\n\tstatic\tMth::Vector\tsWorldPos;\t\t// just a dummy for now....\r\n\tstatic\tMth::Matrix\tsOrient;\t\t// just a dummy for now....\r\n\r\n\t//\r\n\tuint8\t\t\t\tm_op_id;\t\t// SuperSector ID\r\n};\r\n\r\n////////////////////////////////////////////////////////////////\r\n// Movable object collision\r\nclass CCollMovable : public CCollObj\r\n{\r\npublic:\r\n\tvirtual\t\t\t\t~CCollMovable();\r\n\r\n\t//\r\n\tvirtual void\t\tSetWorldPosition(const Mth::Vector & pos);\r\n\tvirtual void\t\tSetOrientation(const Mth::Matrix & orient);\r\n\tvirtual const Mth::Vector &\tGetWorldPosition() const;\r\n\tvirtual const Mth::Matrix &\tGetOrientation() const;\r\n\tvirtual Mth::Vector GetVertexPos(int vert_idx) const;\r\n\r\n\tvirtual Obj::CCompositeObject *GetMovingObject() const;\r\n\tvirtual void\t\t\t\tSetMovingObject(Obj::CCompositeObject *p_movable_object);\r\n\r\nprotected:\r\n\t\t\t\t\t\tCCollMovable();\t// Only the derived classes should call this\r\n\r\n\tvoid\t\t\t\tconvert_line_to_local(const Mth::Line &world_line, Mth::Line &local_line);\r\n\r\n\t// These will be set by the CMovableObject\r\n\tMth::Vector\t\t\tm_world_pos;\r\n\tMth::Matrix\t\t\tm_orient;\r\n\tMth::Matrix\t\t\tm_orient_transpose;\r\n\r\n\t// Pointer to moving object\r\n\tObj::CCompositeObject\t*mp_movable_object;\r\n};\r\n\r\n////////////////////////////////////////////////////////////////\r\n// Movable collision using axis-aligned bounding box data\r\nclass CCollMovBBox : public CCollMovable\r\n{\r\npublic:\r\n\t\t\t\t\t\tCCollMovBBox();\r\n\t\t\t\t\t\tCCollMovBBox(CCollObjTriData *p_coll_data);\r\n\tvirtual\t\t\t\t~CCollMovBBox();\r\n\r\n\tvirtual void\t\tSetGeometry(CCollObjTriData *p_geom_data);\t// Also sets the bounding box based on it\r\n\tvoid\t\t\t\tSetBoundingBox(const Mth::CBBox & bbox);\t// Sets bounding box (will go away)\r\n\r\n\tvirtual uint32\t\tGetFaceFlags(int face_idx) const;\r\n\tvirtual uint16\t\tGetFaceTerrainType(int face_idx) const;\r\n\r\n\t// Clone\r\n\tvirtual CCollObj *\tClone(bool instance = false);\r\n\r\n\t// The virtual collision functions\r\n\tvirtual bool\t\tWithinBBox(const Mth::CBBox & testBBox); \t\t\t// Will always return TRUE because it isn't\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// worth checking.\r\n\tvirtual bool\t\tCollisionWithLine(const Mth::Line & testLine, const Mth::Vector & lineDir, CollData *p_data, Mth::CBBox *p_bbox);\r\n\tvirtual bool\t\tCollisionWithRectangle(const Mth::Rectangle& testRect, const Mth::CBBox& testRectBBox, S2DCollData *p_coll_data);\r\n\r\n\t// Wireframe drawing\r\n\tvirtual void\t\tDebugRender(uint32 ignore_1, uint32 ignore_0);\r\n\r\nprivate:\r\n\tMth::CBBox\t\t\tm_bbox;\r\n\r\n\t// Face data (bbox is considered one face)\r\n\tuint32\t\t\t\tm_flags;\r\n\tuint16\t\t\t\tm_terrain_type;\t\t\t// terrain type\r\n\tImage::RGBA\t\t\tm_rgba;\t\t\t\t\t// just one color\r\n};\r\n\r\n////////////////////////////////////////////////////////////////\r\n// Movable collision using triangles\r\nclass CCollStaticTri : public CCollStatic\r\n{\r\npublic:\r\n\t\t\t\t\t\tCCollStaticTri();\r\n\t\t\t\t\t\tCCollStaticTri(CCollObjTriData *p_coll_data);\r\n\tvirtual\t\t\t\t~CCollStaticTri();\r\n\r\n\t//\r\n\tvirtual bool\t\tIsTriangleCollision() const { return true; }\r\n\r\n\t//virtual void\t\tSetGeometry(CCollObjTriData *p_geom_data);\r\n\tvirtual void\t\tSetWorldPosition(const Mth::Vector & pos);\r\n\tvirtual void\t\tSetOrientation(const Mth::Matrix & orient);\r\n\r\n\tvirtual uint32\t\tGetFaceFlags(int face_idx) const;\r\n\tvirtual uint16\t\tGetFaceTerrainType(int face_idx) const;\r\n\r\n\t// Clone\r\n\tvirtual CCollObj *\tClone(bool instance = false);\r\n\r\n\tvirtual void\t\tRotateY(const Mth::Vector & world_origin, Mth::ERot90 rot_y);\r\n\tvirtual void\t\tScale(const Mth::Vector & world_origin, const Mth::Vector& scale);\r\n\r\n\t// The virtual collision functions\r\n\tvirtual bool\t\tWithinBBox(const Mth::CBBox & testBBox);\t\t\t// VERY quick test to see if we're in bbox range.\r\n\tvirtual bool\t\tCollisionWithLine(const Mth::Line & testLine, const Mth::Vector & lineDir, CollData *p_data, Mth::CBBox *p_bbox);\r\n\tvirtual bool\t\tCollisionWithRectangle(const Mth::Rectangle& testRect, const Mth::CBBox& testRectBBox, S2DCollData *p_coll_data);\r\n\r\n\tvoid\t\t\t\tProcessOcclusion();\t\t\t  \r\n\t\t\t  \r\n\t// Wireframe drawing\r\n\tvirtual void\t\tDebugRender(uint32 ignore_1, uint32 ignore_0);\r\n\tvoid\t\t\t\tCheckForHoles();\r\n\t\r\n\r\nprivate:\r\n};\r\n\r\n////////////////////////////////////////////////////////////////\r\n// Movable collision using triangles\r\nclass CCollMovTri : public CCollMovable\r\n{\r\npublic:\r\n\t\t\t\t\t\tCCollMovTri();\r\n\t\t\t\t\t\tCCollMovTri(CCollObjTriData *p_coll_data);\r\n\tvirtual\t\t\t\t~CCollMovTri();\r\n\r\n\t//\r\n\tvirtual bool\t\tIsTriangleCollision() const { return true; }\r\n\r\n\tvirtual void\t\tSetGeometry(CCollObjTriData *p_geom_data);\r\n\tvirtual void\t\tSetWorldPosition(const Mth::Vector & pos);\r\n\tvirtual void\t\tSetOrientation(const Mth::Matrix & orient);\r\n\r\n\tvirtual uint32\t\tGetFaceFlags(int face_idx) const;\r\n\tvirtual uint16\t\tGetFaceTerrainType(int face_idx) const;\r\n\r\n\t// Clone\r\n\tvirtual CCollObj *\tClone(bool instance = false);\r\n\r\n\t// The virtual collision functions\r\n\tvirtual bool\t\tWithinBBox(const Mth::CBBox & testBBox);\t\t\t// VERY quick test to see if we're in bbox range.\r\n\tvirtual bool\t\tCollisionWithLine(const Mth::Line & testLine, const Mth::Vector & lineDir, CollData *p_data, Mth::CBBox *p_bbox);\r\n\tvirtual bool\t\tCollisionWithRectangle(const Mth::Rectangle& testRect, const Mth::CBBox& testRectBBox, S2DCollData* p_coll_data);\r\n\r\n\t// Wireframe drawing\r\n\tvirtual void\t\tDebugRender(uint32 ignore_1, uint32 ignore_0);\r\n\r\nprotected:\r\n\tvirtual Mth::CBBox *get_bbox();\t\t\t\t\t\t\t\t\t\t\t// Gets the quick bbox\r\n\r\nprivate:\r\n\tvoid\t\t\t\tupdate_world_bbox();\r\n\r\n\tfloat\t\t\t\tm_max_radius;\t\t\t\t\t// maximum radius that encompases geometry around the origin\r\n\tbool\t\t\t\tm_movement_changed;\t\t\t\t// Set to true every time SetWorldPosition() is called\r\n\tMth::CBBox\t\t\tm_world_bbox;\t\t\t\t\t// approx bbox in world space that is guaranteed to encompass geometry\r\n};\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////\r\n//\r\n// Inline functions\r\n//\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint32\t\t\tCCollObj::GetChecksum() const\r\n{\r\n\treturn m_checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint16\t\t\tCCollObj::GetObjectFlags() const\r\n{\r\n\treturn m_Flags;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\tCCollObj::SetGeometry(CCollObjTriData *p_geom_data)\r\n{\r\n\tmp_coll_tri_data = p_geom_data;\r\n\t// This only works for non-instanced collision\r\n\tif (p_geom_data) m_checksum = p_geom_data->GetChecksum();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline CCollObjTriData *CCollObj::GetGeometry() const\r\n{\r\n\treturn mp_coll_tri_data;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\tCCollObj::SetObjectFlags(uint16 flags)\r\n{\r\n\tm_Flags |= flags;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\tCCollObj::ClearObjectFlags(uint16 flags)\r\n{\r\n\tm_Flags &= ~flags;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Mth::CBBox *\t\tCCollObj::get_bbox()\r\n{\r\n\treturn NULL;\t\t// default is none\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\tCCollStatic::SetWorldPosition(const Mth::Vector & pos)\r\n{\r\n//\tm_world_pos = pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Vector &\tCCollStatic::GetWorldPosition() const\r\n{\r\n//\treturn m_world_pos;\r\n\treturn sWorldPos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\tCCollStatic::SetOrientation(const Mth::Matrix & orient)\r\n{\r\n//\tm_orient[X] = orient[X];\t// Just the 3x3\r\n//\tm_orient[Y] = orient[Y];\r\n//\tm_orient[Z] = orient[Z];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Matrix &\tCCollStatic::GetOrientation() const\r\n{\r\n//\treturn m_orient;\r\n\treturn sOrient;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint8\t\t\t\tCCollStatic::GetSuperSectorID() const\r\n{\r\n\treturn m_op_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCCollStatic::SetSuperSectorID(uint8 id)\r\n{\r\n\tm_op_id = id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\tCCollMovable::SetWorldPosition(const Mth::Vector & pos)\r\n{\r\n\tm_world_pos = pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Vector &\tCCollMovable::GetWorldPosition() const\r\n{\r\n\treturn m_world_pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\tCCollMovable::SetOrientation(const Mth::Matrix & orient)\r\n{\r\n\tm_orient[X] = orient[X];\t// Just the 3x3\r\n\tm_orient[Y] = orient[Y];\r\n\tm_orient[Z] = orient[Z];\r\n\r\n\tm_orient_transpose.Transpose(m_orient);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Matrix &\tCCollMovable::GetOrientation() const\r\n{\r\n\treturn m_orient;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCCollMovBBox::SetBoundingBox(const Mth::CBBox & bbox)\r\n{\r\n\tm_bbox = bbox;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\t\tCCollMovBBox::WithinBBox(const Mth::CBBox & testBBox)\r\n{\r\n\t// Will always return TRUE because it isn't worth checking\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCCollMovTri::SetWorldPosition(const Mth::Vector & pos)\r\n{\r\n\tCCollMovable::SetWorldPosition(pos);\r\n\tm_movement_changed = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCCollMovTri::SetOrientation(const Mth::Matrix & orient)\r\n{\r\n\tCCollMovable::SetOrientation(orient);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCCollMovTri::update_world_bbox()\r\n{\r\n\tm_world_bbox.SetMin(Mth::Vector(-m_max_radius + m_world_pos[X], -m_max_radius + m_world_pos[Y], -m_max_radius + m_world_pos[Z]));\r\n\tm_world_bbox.SetMax(Mth::Vector( m_max_radius + m_world_pos[X],  m_max_radius + m_world_pos[Y],  m_max_radius + m_world_pos[Z]));\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Mth::CBBox *\t\t\tCCollMovTri::get_bbox()\r\n{\r\n\tif (m_movement_changed)\r\n\t{\r\n\t\tupdate_world_bbox();\r\n\t\tm_movement_changed = false;\r\n\t}\r\n\r\n\treturn &m_world_bbox;\r\n}\r\n\r\n\r\n} // namespace Nx\r\n\r\n#endif  //\t__GEL_COLLISION_H\r\n"
  },
  {
    "path": "Code/Gel/Collision/MovCollMan.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNx\t\t\t\t\t\t\t\t \t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel\\collision\\movcollman.cpp   \t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t04/08/02\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gel/collision/collision.h>\r\n#include <gel/collision/movcollman.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\nLst::Head<CCollObj> CMovableCollMan::s_collision_list;\r\n//CCollObj * CMovableCollMan::s_collision_array[MAX_COLLISION_OBJECTS];\r\n//int CMovableCollMan::s_array_size = 0;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCMovableCollMan::sAddCollision(CCollObj *p_collision, Obj::CCompositeObject *p_object)\r\n{\r\n\tLst::Node<CCollObj> *node = new Lst::Node<CCollObj>(p_collision);\r\n\ts_collision_list.AddToTail(node);\r\n\t//s_collision_array[s_array_size++] = p_collision;\r\n\t//Dbg_Assert(s_array_size <= MAX_COLLISION_OBJECTS);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCMovableCollMan::sRemoveCollision(CCollObj *p_collision)\r\n{\r\n\tLst::Node<Nx::CCollObj> *node_coll, *node_next;\r\n\r\n\tfor(node_coll = s_collision_list.GetNext(); node_coll; node_coll = node_next)\r\n\t{\r\n\t\tnode_next = node_coll->GetNext();\r\n\r\n\t\tif (node_coll->GetData() == p_collision)\r\n\t\t{\r\n\t\t\tdelete node_coll;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n} // namespace Nx\r\n\r\n"
  },
  {
    "path": "Code/Gel/Collision/MovCollMan.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNx\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tMovCollMan.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t04/08/2002\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__GEL_MOVCOLLMAN_H\r\n#define\t__GEL_MOVCOLLMAN_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n\r\n#include <gel/collision/collenums.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\nclass CCollObj;\r\nclass CCollObjTriData;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CMovableCollMan\r\n{\r\npublic:\r\n\t//static void\t\t\t\tsInit();\r\n\t//static void\t\t\t\tsCleanup();\r\n\r\n\tstatic void\t\t\t\tsAddCollision(CCollObj *p_collsion, Obj::CCompositeObject *p_object);\r\n\tstatic void\t\t\t\tsRemoveCollision(CCollObj *p_collsion);\r\n\r\n\tstatic Lst::Head<CCollObj> *sGetCollisionList();\r\n\tstatic CCollObj **\t\t\tsGetCollisionArray();\r\n\r\nprotected:\r\n\tenum\r\n\t{\r\n\t\tMAX_COLLISION_OBJECTS = 100,\r\n\t};\r\n\r\n\tstatic Lst::Head<CCollObj>\ts_collision_list;\r\n\tstatic CCollObj *\t\t\ts_collision_array[MAX_COLLISION_OBJECTS];\t\t// If the speed is needed\r\n\tstatic int\t\t\t\t\ts_array_size;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Lst::Head<CCollObj> *CMovableCollMan::sGetCollisionList()\r\n{\r\n\treturn &s_collision_list;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline CCollObj **\t\t\tCMovableCollMan::sGetCollisionArray()\r\n{\r\n\treturn s_collision_array;\r\n}\r\n\r\n} // namespace Nx\r\n\r\n#endif\t//\t__GEL_MOVCOLLMAN_H\r\n"
  },
  {
    "path": "Code/Gel/Components/BouncyComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       BouncyComponent.h\r\n//* OWNER:          Mick West\r\n//* CREATION DATE:  10/22/2002\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_BOUNCYCOMPONENT_H__\r\n#define __COMPONENTS_BOUNCYCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/math.h>\r\n#include <gel/object/basecomponent.h>\r\n\r\n\r\n#define\t\tCRC_BOUNCY CRCD(0x69c257e9,\"Bouncy\")\r\n#define\t\tGetBouncyComponent() ((Obj::CBouncyComponent*)GetComponent(CRC_BOUNCY))\r\n\r\nnamespace Mth\r\n{\r\n    class SlerpInterpolator;\r\n};\r\n\r\n\r\n#define BOUNCYOBJ_FLAG_PLAYER_COLLISION_OFF\t\t\t( 1 << 0 )\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n// These are in the Obj:: namespace, whilse we are sperating the bouncy componet from the bouncy object\r\nenum\r\n{\r\n\tBOUNCYOBJ_STATE_INIT,\r\n\tBOUNCYOBJ_STATE_IDLE,\r\n\tBOUNCYOBJ_STATE_BOUNCING,\r\n};\r\n\r\nclass CBouncyComponent : public CBaseComponent\r\n{\r\n\t\r\npublic:\r\n// Functions common to components - the interface to the outside world\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tCBouncyComponent();\r\n    virtual         \t\t\t~CBouncyComponent();\r\n    virtual void    \t\t\tUpdate();\r\n    virtual void    \t\t\tInitFromStructure( Script::CStruct* pParams );\r\n\tstatic CBaseComponent *\t\ts_create();\r\n\tCBaseComponent::EMemberFunctionResult\tCallMemberFunction( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript );\r\n\tvirtual void \t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n// private functions - indirectly called from the above functions\t\r\nprivate:\r\n\tvoid\t\t\t\t\t\tbounce( const Mth::Vector &vel );\r\n\tvoid \t\t\t\t\t\tbounce_from_object_vel( const Mth::Vector &vel, const Mth::Vector &pos );\r\n\tvoid\t\t\t\t\t\tdo_bounce( void );\r\n\tbool \t\t\t\t\t\trotate_to_quat( void );\r\n\tvoid \t\t\t\t\t\tset_up_quats( void );\r\n\r\n\tvoid \t\t\t\t\t\tland_on_any_face( Mth::Vector &rot );\r\n\tvoid \t\t\t\t\t\tland_on_top_or_bottom( Mth::Vector &rot );\r\n\tvoid \t\t\t\t\t\tland_traffic_cone( Mth::Vector &rot );\r\n\r\n\tint\t\t\t\t\t\t\tm_bouncyobj_flags;\r\n\tMth::Vector \t\t\t\tm_rotation;\r\n\tint\t\t\t\t\t\t\tm_rot_per_axis;\r\n\tint\t\t\t\t\t\t\tm_bounce_rot;\r\n\tfloat\t\t\t\t\t\tm_min_bounce_vel;\r\n\t// should the object come to rest flat (90 degree oriented?)\r\n\tint\t\t\t\t\t\t\tm_rest_orientation_type;\r\n\t// percent of bounce vel maintained ( 1.0 would make it bounce the same height )\r\n\tfloat\t\t\t\t\t\tm_bounce_mult;\r\n\tfloat\t\t\t\t\t\tm_up_mag; // this will be the upward velocity (varies depending on initial vel)\r\n\tint\t\t\t\t\t\t\tm_bounce_count;\r\n\tbool\t\t\t\t\t\tm_quat_initialized;\r\n\tfloat\t\t\t\t\t\tm_quatrot_time_elapsed;\r\n\tfloat\t\t\t\t\t\tm_gravity;\r\n\tfloat\t\t\t\t\t\tm_bounciness;\r\n\tfloat\t\t\t\t\t\tm_min_initial_vel;\r\n\tint\t\t\t\t\t\t\tm_random_dir; // on bounce, change direction by this much...\r\n\tMth::SlerpInterpolator *\tmp_bounce_slerp;\r\n\tuint32\t\t\t\t\t\tm_bounce_sound;\r\n\tuint32\t\t\t\t\t\tm_hit_sound;\r\n\t\t\t\t\t\r\n\tfloat\t\t\t\t\t\tm_bounce_collision_radius;\r\n\tfloat\t\t\t\t\t\tm_skater_collision_radius_squared;\r\n\t\t\t\t\t\t\r\n\tbool\t\t\t\t\t\tm_destroy_when_done;\r\n\r\n    // logic states...\r\n    short \t\t\t\t\t\tm_state;\r\n    short \t\t\t\t\t\tm_substate;\r\n\r\n\t// \r\n\tuint32\t\t\t\t\t\tm_collide_script;\r\n\tScript::CStruct*\t\t\tmp_collide_script_params;\t\r\n\tuint32\t\t\t\t\t\tm_bounce_script;\r\n\tScript::CStruct*\t\t\tmp_bounce_script_params;\t\r\n\t\r\n\t// The following is stuff that might be better off in the composite object, or some general physics component?\r\n\t// or perhaps a \"simplephysics\" base compoennt\r\n\t\r\n\tMth::Vector\t\t\t\t\tm_pos;\r\n\tMth::Vector\t\t\t\t\tm_old_pos;\r\n\tMth::Vector\t\t\t\t\tm_vel;\r\n\tMth::Matrix\t\t\t\t\tm_matrix;\r\n\tfloat\t\t\t\t\t\tm_time;\r\n\r\n\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/CameraComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       CameraComponent.cpp\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/21/03\r\n//****************************************************************************\r\n\r\n#include <gel/components/cameracomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCBaseComponent* CCameraComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CCameraComponent );\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCCameraComponent::CCameraComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_CAMERA );\r\n\r\n\t// Enabled by default.\r\n\tm_enabled = true;\r\n\r\n\t// Create and attach a Gfx::Camera.\r\n\tmp_camera = new Gfx::Camera();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCCameraComponent::~CCameraComponent()\r\n{\r\n\t// Destroy the Gfx::Camera.\r\n\tdelete mp_camera;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CCameraComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// cameras must have a very low priority to insure that all objects update before they do (most importantly, the skater)\r\n\tCCompositeObjectManager::Instance()->SetObjectPriority(*GetObject(), -1000);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CCameraComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CCameraComponent::Update()\r\n{\r\n\tif( m_enabled )\r\n\t{\r\n\t\t// Use the position and orientation of the parent object to position and orient the attached camera.\r\n\t\tMth::Vector pos = GetObject()->GetPos();\r\n\t\tMth::Matrix mat = GetObject()->GetMatrix();\r\n\r\n\t\t// Set the Display pos of the object to the actual pos, so we can attach a model\r\n\t\t// to the camera\r\n\t\tGetObject()->SetDisplayMatrix(mat);\r\n\r\n\t\tmp_camera->SetPos( pos );\r\n\t\tmp_camera->SetMatrix( mat );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCBaseComponent::EMemberFunctionResult CCameraComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n/*\r\n        // @script | DoSomething | does some functionality\r\n\t\tcase 0xbb4ad101:\t\t// DoSomething\r\n\t\t\tDoSomething();\r\n\t\t\tbreak;\r\n\r\n        // @script | ValueIsTrue | returns a boolean value\r\n\t\tcase 0x769260f7:\t\t// ValueIsTrue\r\n\t\t{\r\n\t\t\treturn ValueIsTrue() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\tbreak;\r\n*/\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CCameraComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CCameraComponent::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\t/*\tExample:\r\n\tp_info->AddInteger(\"m_never_suspend\",m_never_suspend);\r\n\tp_info->AddFloat(\"m_suspend_distance\",m_suspend_distance);\r\n\t*/\r\n\t\r\n\t// We call the base component's GetDebugInfo, so we can add info from the common base component.\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CCameraComponent::Enable( bool enable )\r\n{\r\n\tm_enabled = enable;\r\n\r\n\t// Go through and enable other attached components?\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::Vector &CCameraComponent::GetPosition( void ) const\r\n{\r\n\treturn GetObject()->GetPos();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CCameraComponent::SetPosition( Mth::Vector& pos )\r\n{\r\n \tGetObject()->SetPos( pos );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nMth::Matrix& CCameraComponent::GetMatrix( void )\r\n{\r\n\treturn GetObject()->GetMatrix();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CCameraComponent::StoreOldPosition( void )\r\n{\r\n\tif( mp_camera )\r\n\t{\r\n\t\tmp_camera->StoreOldPos();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CCameraComponent::SetHFOV( float hfov )\r\n{\r\n\tif( mp_camera )\r\n\t{\r\n\t\tmp_camera->SetHFOV( hfov );\r\n\t}\r\n}\r\n\r\n\r\n\r\n}"
  },
  {
    "path": "Code/Gel/Components/CameraComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       CameraComponent.h\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/21/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_CAMERACOMPONENT_H__\r\n#define __COMPONENTS_CAMERACOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gfx/camera.h>\r\n\r\n// Replace this with the CRCD of the component you are adding.\r\n#define\t\tCRC_CAMERA\t\t\t\t\t\t\t\tCRCD( 0xc4e311fa, \"Camera\" )\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or given an object.\r\n#define\t\tGetCameraComponent()\t\t\t\t\t((Obj::CCameraComponent*)GetComponent( CRC_CAMERA ))\r\n#define\t\tGetCameraComponentFromObject( pObj )\t((Obj::CCameraComponent*)(pObj)->GetComponent( CRC_CAMERA ))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CCameraComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CCameraComponent();\r\n    virtual ~CCameraComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\n\tvoid\t\t\t\t\t\t\tSetHFOV( float hfov );\r\n\r\n\tvoid\t\t\t\t\t\t\tEnable( bool enable );\r\n\tGfx::Camera*\t\t\t\t\tGetCamera( void )\t\t{ return mp_camera; }\r\n\tconst Mth::Vector &\t\t\t\tGetPosition( void ) const ;\r\n\tvoid\t\t\t\t\t\t\tSetPosition( Mth::Vector& pos );\r\n\tvoid\t\t\t\t\t\t\tStoreOldPosition( void );\r\n\tMth::Matrix&\t\t\t\t\tGetMatrix( void );\r\n\r\nprivate:\r\n\r\n\tbool\t\t\t\t\t\t\tm_enabled;\r\n\tGfx::Camera*\t\t\t\t\tmp_camera;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/CameraLookAroundComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       CameraLookAroundComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  4/14/3\r\n//****************************************************************************\r\n\r\n#ifdef TESTING_GUNSLINGER\r\n\r\n#include <gel/components/gunslingercameralookaroundcomponent.cpp>\r\n\r\n#else\r\n\r\n#include <gel/components/cameralookaroundcomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/debuggfx.h>\r\n\t\t\t\t\t\t   \r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CCameraLookAroundComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CCameraLookAroundComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCameraLookAroundComponent::CCameraLookAroundComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_CAMERALOOKAROUND );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCameraLookAroundComponent::~CCameraLookAroundComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCameraLookAroundComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tmLookaroundTilt\t\t\t\t\t= 0.0f;\r\n\tmLookaroundHeading\t\t\t\t= 0.0f;\r\n\tmLookaroundZoom\t\t\t\t\t= 1.0f;\r\n\t\r\n\tmLookaroundLock\t\t\t\t\t= false;\r\n\tmLookaroundOverride\t\t\t\t= false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCameraLookAroundComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCameraLookAroundComponent::Finalize (   )\r\n{\r\n\tmp_input_component = GetInputComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_input_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCameraLookAroundComponent::Update()\r\n{\r\n\tCControlPad * p_control_pad;\r\n\t\r\n\tif (Script::GetInt(CRCD(0x702247a5,\"Viewer_controller\"), false))\r\n\t{\r\n\t\tp_control_pad = &mp_input_component->GetControlPad2();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_control_pad = &mp_input_component->GetControlPad();\r\n\t}\r\n\t\r\n\r\n\t// Handle pressing of \"Select\" button\r\n\t// \t\r\n\tif (!Script::GetInt(CRCD(0xf3e055e1,\"select_shift\")))\r\n\t{\r\n\t\tif (p_control_pad->m_select.GetTriggered())\r\n\t\t{\r\n\t\t\tprintf (\"Camera Detected Select Pressed\\n\");\r\n\t\t\tp_control_pad->m_select.ClearTrigger();\r\n\t\t\t// Depending on which skatercam we are, run one of the UserSelectSelect scripts\r\n\t\t\tif (GetObject()->GetID() == CRCD(0x967c138c,\"SkaterCam0\"))\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript(CRCD(0x60871393,\"UserSelectSelect\"));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript(CRCD(0xa1b1146d,\"UserSelectSelect2\"));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (p_control_pad->m_R3.GetTriggered())\r\n\t{\r\n\t\tmLookaroundLock = !mLookaroundLock;\r\n\t\tp_control_pad->m_R3.ClearTrigger();\r\n\t}\r\n\t\r\n\tfloat frame_length = Tmr::FrameLength();\r\n\t\r\n\tif (!mLookaroundLock && !mLookaroundOverride)\r\n\t{\r\n\t\tfloat target = p_control_pad->m_scaled_rightY;\r\n\t\ttarget = -1.4f * (target < 0.0f ? (0.7f * target) : (0.5f * target));\r\n\t\tif (Mth::Abs(target - mLookaroundTilt) > 0.001f)\r\n\t\t{\r\n\t\t\tmLookaroundTilt += (target - mLookaroundTilt) * 3.75f * frame_length;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmLookaroundTilt = target;\r\n\t\t}\r\n\t\t\r\n\t\ttarget = 3.0f * p_control_pad->m_scaled_rightX;\r\n\t\tif (Mth::Abs(target - mLookaroundHeading) > 0.001f)\r\n\t\t{\r\n\t\t\tmLookaroundHeading += (target - mLookaroundHeading) * 3.75f * frame_length;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmLookaroundHeading = target;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfloat delta_time = Tmr::FrameLength();\r\n\r\n\tif (mLookaroundOverride)\r\n\t{\r\n\t\tif (mLookaroundDeltaTimer > 0.0f)\r\n\t\t{\r\n\t\t\tif (mLookaroundDeltaTimer > delta_time)\r\n\t\t\t{\r\n\t\t\t\tmLookaroundHeading\t\t+= mLookaroundHeadingDelta * delta_time;\r\n\t\t\t\tmLookaroundTilt\t\t\t+= mLookaroundTiltDelta * delta_time;\r\n\t\t\t\tmLookaroundDeltaTimer\t-= delta_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmLookaroundHeading\t\t= mLookaroundHeadingTarget;\r\n\t\t\t\tmLookaroundTilt\t\t\t= mLookaroundTiltTarget;\r\n\t\t\t\tmLookaroundDeltaTimer\t= 0.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CCameraLookAroundComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | SC_SetSkaterCamOverride | \r\n        // @parm float | heading |\r\n        // @parm float | tilt | \r\n        // @parm float | time | \r\n        // @parm float | zoom | \r\n\t\tcase 0xb8f23899:\t// SC_SetSkaterCamOverride\r\n\t\t{\r\n\t\t\tfloat heading, tilt, time;\r\n\t\t\tfloat zoom = 1.0f;\r\n\t\t\tpParams->GetFloat( CRCD(0xfd4bc03e,\"heading\"), &heading, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0xe3c07609,\"tilt\"), &tilt, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0x906b67ba,\"time\"), &time, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0x48d4868b,\"zoom\"), &zoom );\r\n\r\n\t\t\tSetLookaround( heading, tilt, time, zoom );\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | SC_ClearSkaterCamOverride |\r\n\t\tcase 0xe3b327c0:\t// SC_ClearSkaterCamOverride\r\n\t\t\tClearLookaround();\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCameraLookAroundComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CCameraLookAroundComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCameraLookAroundComponent::SetLookaround( float heading, float tilt, float time, float zoom )\r\n{\r\n\tmLookaroundOverride\t\t\t\t= true;\r\n\r\n\tmLookaroundHeadingTarget\t\t= heading;\r\n\tmLookaroundTiltTarget\t\t\t= tilt;\r\n\r\n\t// Calculate delta - the amount to move in 1 second.\r\n\tif (time > 0.0f)\r\n\t{\r\n\t\tmLookaroundHeadingDelta\t\t= (heading - mLookaroundHeading) / time;\r\n\t\tmLookaroundTiltDelta\t\t= (tilt - mLookaroundTilt) / time;\r\n\t}\r\n\r\n\tmLookaroundDeltaTimer\t\t\t= time;\r\n\tmLookaroundZoom\t\t\t\t\t= zoom;\r\n}\r\n\r\n#if 0 // old control input checking code\r\n\r\nchar touched[256 * 256 / 8];\r\nbool initialized = false;\r\n\r\nvoid MapInput (   )\r\n{\r\n\tif (!initialized)\r\n\t{\r\n\t\tfor (int n = 255 * 255; n--; )\r\n\t\t{\r\n\t\t\ttouched[n / 8] = 0;\r\n\t\t}\r\n\t\tinitialized = true;\r\n\t}\r\n\t\r\n\tCControlPad& pad = mp_input_component->GetControlPad();\r\n\t\r\n\tint x = static_cast< int >(pad.m_rightX) + 128;\r\n\tint y = static_cast< int >(pad.m_rightY) + 128;\r\n\t\r\n\t// printf(\"x = %i; y = %i\\n\", x, y);\r\n\t\r\n\tint index = (x * 256) + y;\r\n\t\r\n\t// printf(\"index / 8 = %i\\n\", index / 8);\r\n\t// printf(\"MAX = %i\\n\", 256 * 256 / 8);\r\n\t\r\n\ttouched[index / 8] |= (1 << (index % 8));\r\n}\r\n\r\n\r\nvoid DrawMap (   )\r\n{\r\n\tMth::Vector pos = GetObject()->GetPos();\r\n\tMth::Matrix matrix = GetObject()->GetMatrix();\r\n\t\r\n\tMth::Vector center = pos - 300.0f * matrix[Z];\r\n\tMth::Vector up = matrix[Y];\r\n\tMth::Vector left = -matrix[X];\r\n\t\r\n\tfor (int n = 255 * 255; n--; )\r\n\t{\r\n\t\tif (!(touched[n / 8] & (1 << (n % 8)))) continue;\r\n\t\t\r\n\t\tint x = n / 256;\r\n\t\tint y = n % 256;\r\n\t\t\r\n\t\tMth::Vector point = center + up * (y - 128) + left * (x - 128);\r\n\t\t\r\n\t\tGfx::AddDebugLine(point + up + left, point - up - left, MAKE_RGB(255, 255, 255), 0, 1);\r\n\t\tGfx::AddDebugLine(point + up - left, point - up + left, MAKE_RGB(255, 255, 255), 0, 1);\r\n\t}\r\n}\r\n\r\n#endif\r\n\r\n}\r\n\r\n#endif // TESTING_GUNSLINGER\r\n"
  },
  {
    "path": "Code/Gel/Components/CameraLookAroundComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       CameraLookAroundComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  4/14/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_CAMERALOOKAROUNDCOMPONENT_H__\r\n#define __COMPONENTS_CAMERALOOKAROUNDCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n\r\n#define\t\tCRC_CAMERALOOKAROUND CRCD(0x81c7122d, \"CameraLookAround\")\r\n\r\n#define\t\tGetCameraLookAroundComponent() ((Obj::CCameraLookAroundComponent*)GetComponent(CRC_CAMERALOOKAROUND))\r\n#define\t\tGetCameraLookAroundComponentFromObject(pObj) ((Obj::CCameraLookAroundComponent*)(pObj)->GetComponent(CRC_CAMERALOOKAROUND))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CInputComponent;\r\n\r\nclass CCameraLookAroundComponent : public CBaseComponent\r\n{\r\n\tfriend class CSkaterCameraComponent;\r\n\tfriend class CWalkCameraComponent;\r\n\tfriend class CVehicleCameraComponent;\r\n\t\r\npublic:\r\n    CCameraLookAroundComponent();\r\n    virtual ~CCameraLookAroundComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetLookaroundHeadingExtra( float lookaround_heading_extra );\r\n\tvoid\t\t\t\t\t\t\tClearLookaround( void );\r\n\tvoid\t\t\t\t\t\t\tSetLookaround( float heading, float tilt, float time, float zoom );\r\n\t\r\n\tbool\t\t\t\t\t\t\tIsHeadingTargetZero (   );\r\n\tbool\t\t\t\t\t\t\tIsTiltTargetZero (   );\r\n\tbool\t\t\t\t\t\t\tIsLookaroundActive ( void );\r\n\t\r\nprivate:\r\n\tbool\t\t\t\t\t\t\tmLookaroundLock;\r\n\tbool\t\t\t\t\t\t\tmLookaroundOverride;\t// For when the designer is scripting the lookaround values.\r\n\tfloat\t\t\t\t\t\t\tmLookaroundZoom;\t\t// Allows designers to adjust the zoom when overrideing the lookaround values.\r\n\tfloat\t\t\t\t\t\t\tmLookaroundTilt;\r\n\tfloat\t\t\t\t\t\t\tmLookaroundHeading;\r\n\tfloat\t\t\t\t\t\t\tmLookaroundHeadingStartingPoint;\r\n\tfloat\t\t\t\t\t\t\tmLookaroundTiltTarget;\r\n\tfloat\t\t\t\t\t\t\tmLookaroundHeadingTarget;\r\n\tfloat\t\t\t\t\t\t\tmLookaroundTiltDelta;\r\n\tfloat\t\t\t\t\t\t\tmLookaroundHeadingDelta;\r\n\tfloat\t\t\t\t\t\t\tmLookaroundDeltaTimer;\r\n\r\n\tCInputComponent*\t\t\t\tmp_input_component;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CCameraLookAroundComponent::ClearLookaround( void )\r\n{\r\n\tmLookaroundOverride\t\t\t\t= false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CCameraLookAroundComponent::IsHeadingTargetZero ( void )\r\n{\r\n\treturn mp_input_component->GetControlPad().m_scaled_rightX == 0.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CCameraLookAroundComponent::IsTiltTargetZero ( void )\r\n{\r\n\treturn mp_input_component->GetControlPad().m_scaled_rightY == 0.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CCameraLookAroundComponent::IsLookaroundActive ( void )\r\n{\r\n\treturn mLookaroundHeading != 0.0f || !IsHeadingTargetZero()\r\n\t\t|| mLookaroundTilt != 0.0f || !IsTiltTargetZero();\r\n}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/CameraUtil.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       CameraUtil.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  4/10/3\r\n//****************************************************************************\r\n\r\n/*\r\n * Utility functions for camera behavior components.\r\n */\r\n\r\n#include <gel/components/camerautil.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*******************************************************************************************************\r\nlogic for getTimeAdjustedSlerp()\r\n\r\nIf the camera is lagging a distance D behind the target, and the target is moving with velocity V, and the lerp is set to L.\r\nThen when the camera is stable, it will be moving at the same rate as the target (V), and since the distance it will move is\r\nequal to the lerp multiplied by the distance from the target (which will be the old distance plus the new movement of the\r\ntarget V)\r\n\r\nThen:\r\n\r\nL*(D+V) = V \r\nL*D + L*V = V\r\nD = V * (1 - L) / L\r\n\r\nAssuming in the above T = 1, then if we have a variable T, the speed of the skater will be T*V, yet we want the distance (Dt)\r\nmoved to remain unchanged (D), so for a time adjusted lerp Lt\r\n\r\nDt = T * V * (1-Lt)/Lt\r\n\r\nSince D = Dt\r\n\r\nV * (1 - L) / L = T * V * (1-Lt)/Lt\r\n\r\nV cancels out, and we get\r\n\r\nLt = TL / (1 - L + TL)\r\n\r\nSanity check,  \r\n\r\nif L is 0.25, and T is 1, then Lt = 1*0.25 / (1 - 0.25 + 1*0.25)  = 0.25\r\nif L is 0.25, and T is 2, then Lt = 2*0.25 / (1 - 0.25 + 2*0.25)  = 0.5 / 1.25 = 0.40\r\nif L is 0.25, and T is 5, then Lt = 5*0.25 / (1 - 0.25 + 5*0.25)  = 1.25 / 2 = 0.625\r\n\r\nSounds about right.\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat GetTimeAdjustedSlerp( float slerp, float delta )\r\n{\r\n\t// Mick's method, tries to guarantee that the distance from the target point\r\n\t// will never alter at constant velocity, with changing frame rate\r\n\t// Lt = TL / (1 - L + TL)\r\n\tfloat t\t\t= delta * 60.0f;\r\n\tfloat Lt\t= t * slerp / ( 1.0f - slerp + t * slerp );\r\n\treturn Lt;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#define vMIN_WALL_DISTANCE (2.0f)\r\n\r\nvoid ApplyCameraCollisionDetection ( Mth::Vector& camera_pos, Mth::Matrix& camera_matrix, const Mth::Vector& target_pos, const Mth::Vector& focus_pos, bool side_feelers, bool refocus )\r\n{\r\n\t// camera collision detection\r\n\t\r\n\tMth::Vector target_to_camera_direction = camera_pos - target_pos;\r\n\ttarget_to_camera_direction.Normalize();\r\n\t\r\n\tCFeeler feeler;\r\n\t\r\n\t// Ignore faces based on face falgs\r\n\tfeeler.SetIgnore(IGNORE_FACE_FLAGS_1, IGNORE_FACE_FLAGS_0);\r\n\tfeeler.SetLine(target_pos, camera_pos + vMIN_WALL_DISTANCE * target_to_camera_direction);\r\n\tbool collision = feeler.GetCollision(true);\r\n\tif( collision )\r\n\t{\r\n//\t\t\tGfx::AddDebugLine( at_pos, cam_pos, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 2000 );\r\n\r\n\t\t// Limits the camera to getting nearer than 11.9 inches to the focus point.\r\n\t\tfloat distance = feeler.GetDist();\r\n\t\tfloat length = feeler.Length();\r\n\t\tif( length * distance < 11.9f + vMIN_WALL_DISTANCE )\r\n\t\t{\r\n\t\t\tdistance = (11.9f + vMIN_WALL_DISTANCE) / length;\r\n\t\t}\r\n\t\tcamera_pos = target_pos + (distance * length - vMIN_WALL_DISTANCE) * target_to_camera_direction;\r\n\t}\r\n\t\r\n\tif (!side_feelers) return;\r\n\r\n//#\tif defined( __PLAT_NGPS__ ) || defined ( __PLAT_XBOX__ )\r\n\t// Now do two additional checks 1 foot to either side of the camera.\r\n\tMth::Vector\tleft( camera_matrix[X][X], 0.0f, camera_matrix[X][Z], 0.0f );\r\n\tleft.Normalize( 8.0f );\r\n\tleft += camera_pos;\r\n\r\n\tcollision = feeler.GetCollision(camera_pos, left, true);\r\n\tif( collision )\r\n\t{\r\n\t\tleft\t\t   -= feeler.GetPoint();\r\n\t\tcamera_pos\t\t   -= left;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMth::Vector\tright( -camera_matrix[X][X], 0.0f, -camera_matrix[X][Z], 0.0f );\r\n\t\tright.Normalize( 8.0f );\r\n\t\tright += camera_pos;\r\n\r\n\t\tcollision = feeler.GetCollision(camera_pos, right, true);\r\n\t\tif( collision )\r\n\t\t{\r\n\t\t\tright\t\t   -= feeler.GetPoint();\r\n\t\t\tcamera_pos\t\t   -= right;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (!refocus) return;\r\n\r\n\tif( collision )\r\n\t{\r\n\t\t// Re-orient the camera again.\r\n\t\tcamera_matrix[Z].Set( focus_pos.GetX() - camera_pos.GetX(), focus_pos.GetY() - camera_pos.GetY(), focus_pos.GetZ() - camera_pos.GetZ());\r\n\t\tcamera_matrix[Z].Normalize();\r\n\r\n\t\t// Read back the Y from the current matrix.\r\n//\t\t\ttarget[Y][0]\t= p_frame_matrix->up.x;\r\n//\t\t\ttarget[Y][1]\t= p_frame_matrix->up.y;\r\n//\t\t\ttarget[Y][2]\t= p_frame_matrix->up.z;\r\n\r\n\t\t// Generate new orthonormal X and Y axes.\r\n\t\tcamera_matrix[X]\t\t= Mth::CrossProduct( camera_matrix[Y], camera_matrix[Z] );\r\n\t\tcamera_matrix[X].Normalize();\r\n\t\tcamera_matrix[Y]\t\t= Mth::CrossProduct( camera_matrix[Z], camera_matrix[X] );\r\n\t\tcamera_matrix[Y].Normalize();\r\n\r\n\t\t// Write back into camera matrix.\r\n\t\tcamera_matrix[X]\t\t= -camera_matrix[X];\r\n\t\tcamera_matrix[Z]\t\t= -camera_matrix[Z];\r\n\t\t\r\n\t\t// Fix the final column\r\n\t\tcamera_matrix[X][W] = 0.0f;\r\n\t\tcamera_matrix[Y][W] = 0.0f;\r\n\t\tcamera_matrix[Z][W] = 0.0f;\r\n\t\tcamera_matrix[W][W] = 1.0f;\r\n\t\t\r\n\t}\r\n//#endif\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/CameraUtil.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       CameraUtil.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  4/10/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_CAMERAUTIL_H__\r\n#define __COMPONENTS_CAMERAUTIL_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/math.h>\r\n\r\n#define SKATERCAMERACOMPONENT_PERFECT_ABOVE\t\t\t(3.0f)\r\n\t\t\t\r\n#if 0\r\n// Ignore faces that are NOT flagged as camera collidable\r\n#define IGNORE_FACE_FLAGS_1 \t(0)\r\n#define IGNORE_FACE_FLAGS_0 \t(mFD_CAMERA_COLLIDABLE)\r\n#endif\r\n\r\n#if 0\r\n// ignore faces that ARE flagged as camera collidable\r\n#define IGNORE_FACE_FLAGS_1 \t(0)\r\n#define IGNORE_FACE_FLAGS_0 \t(mFD_CAMERA_COLLIDABLE)\r\n#endif\r\n\r\n#if 1\r\n// ignore faces that are non-collidable or invisible\r\n//#define IGNORE_FACE_FLAGS_1 \t(mFD_NON_COLLIDABLE | mFD_INVISIBLE)\r\n#define IGNORE_FACE_FLAGS_1 \t(mFD_NON_COLLIDABLE | mFD_CAMERA_COLLIDABLE)\r\n#define IGNORE_FACE_FLAGS_0 \t(0)\r\n#endif\r\n\r\n#\tdefine CAMERA_SLERP_STOP 0.9999f\r\n\t   \r\nnamespace Obj\r\n{\r\n\tfloat\t\t\tGetTimeAdjustedSlerp ( float slerp, float delta );\r\n\tvoid\t\t\tApplyCameraCollisionDetection ( Mth::Vector& camera_pos,  Mth::Matrix& camera_matrix, const Mth::Vector& target_pos, const Mth::Vector& forcus_pos, bool side_feelers = true, bool refocus = true );\r\n\t\r\n\tstruct SCameraState\r\n\t{\r\n\t\tMth::Matrix lastActualMatrix;\r\n\t\tMth::Vector lastTripodPos;\r\n\t\tfloat lastDot;\r\n\t\tfloat lastZoom;\r\n\t};\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/CollideAndDieComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       CollideAndDieComponent.cpp\r\n//* OWNER:          SPG\r\n//* CREATION DATE:  7/10/03\r\n//****************************************************************************\r\n\r\n// The CEmptyComponent class is an skeletal version of a component\r\n// It is intended that you use this as the basis for creating new\r\n// components.  \r\n// To create a new component called \"Watch\", (CWatchComponent):\r\n//  - copy emptycomponent.cpp/.h to watchcomponent.cpp/.h\r\n//  - in both files, search and replace \"Empty\" with \"Watch\", preserving the case\r\n//  - in WatchComponent.h, update the CRCD value of CRC_WATCH\r\n//  - in CompositeObjectManager.cpp, in the CCompositeObjectManager constructor, add:\r\n//\t\t  \tRegisterComponent(CRC_WATCH,\t\t\tCWatchComponent::s_create); \r\n//  - and add the include of the header\r\n//\t\t\t#include <gel/components/watchcomponent.h> \r\n//  - Add it to build\\gel.mkf, like:\r\n//          $(NGEL)/components/WatchComponent.cpp\\\r\n//  - Fill in the OWNER (yourself) and the CREATION DATE (today's date) in the .cpp and the .h files\r\n//\t- Insert code as needed and remove generic comments\r\n//  - remove these comments\r\n//  - add comments specfic to the component, explaining its usage\r\n\r\n#include <gel/components/CollideAndDieComponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <sk/components/ProjectileCollisionComponent.h>\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#define vFIREBALL_LIFETIME \tTmr::Seconds( 10 )\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\n\r\nCBaseComponent* CCollideAndDieComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CCollideAndDieComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCCollideAndDieComponent::CCollideAndDieComponent() : CBaseComponent()\r\n{\r\n    SetType( CRC_COLLIDEANDDIE );\r\n\tm_radius = 0.0f;\r\n\tm_scale = 0;\r\n\tm_birth_time = Tmr::GetTime();\r\n\tm_death_script = 0;\r\n\tm_dying = false;\r\n\tm_first_frame = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCollideAndDieComponent::~CCollideAndDieComponent()\r\n{   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCollideAndDieComponent::SetCollisionRadius( float radius )\r\n{\r\n\tm_radius = radius;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CCollideAndDieComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tpParams->GetFloat(CRCD(0xc48391a5,\"radius\"), &m_radius, Script::ASSERT);\r\n\tpParams->GetFloat(CRCD(0x13b9da7b,\"scale\"), &m_scale, Script::ASSERT);\r\n\t\r\n\tpParams->GetChecksum(CRCD(0x6647adc3,\"death_script\"), &m_death_script, Script::ASSERT);\r\n\r\n    m_vel.Set( 0, 0, 1 );\r\n\tpParams->GetVector(CRCD(0xc4c809e, \"vel\"), &m_vel, Script::ASSERT);\r\n\tm_vel.Normalize();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CCollideAndDieComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calline InitFromStructure()\r\n\t// but if that does not handle it, then will need to write a specific \r\n\t// function here. \r\n\t// The user might only want to update a single field in the structure\r\n\t// and we don't want to be asserting becasue everything is missing \r\n\t\r\n\t//InitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCollideAndDieComponent::Finalize()\r\n{\r\n\tmp_suspend_component =  GetSuspendComponentFromObject( GetObject() );\r\n}\r\n\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCollideAndDieComponent::Hide( bool should_hide )\r\n{\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CCollideAndDieComponent::Update()\r\n{\r\n\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tif (gamenet_man->InNetGame() || !mp_suspend_component->SkipLogic())\r\n\t{\r\n\t\tif(( Tmr::GetTime() - m_birth_time ) > vFIREBALL_LIFETIME )\r\n\t\t{\r\n\t\t\tGetObject()->MarkAsDead();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif( m_dying )\r\n\t\t\t{\r\n\t\t\t\tif( Tmr::GetTime() > m_death_time )\r\n\t\t\t\t{\r\n\t\t\t\t\tGetObject()->MarkAsDead();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vel, start, end;\r\n\t\t\t\tCFeeler feeler;\r\n\t\t\r\n\t\t\t\tvel = GetObject()->GetVel();\r\n\t\t\t\tvel.Normalize();\r\n\t\t\t\tif( m_first_frame )\r\n\t\t\t\t{\r\n\t\t\t\t\tstart = GetObject()->GetPos();\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tstart = m_last_pos;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tstart[Y] += FEET( 2 );\r\n\t\t\t\tend = GetObject()->GetPos();\r\n\t\t\t\tend[Y] += FEET( 2 );\r\n\t\t\t\tend += ( vel * m_radius );\r\n\t\t\t\tfeeler.SetStart( start );\r\n\t\t\t\tfeeler.SetEnd( end );\r\n\t\t\r\n\t\t\t\tif( feeler.GetCollision())\r\n\t\t\t\t{\r\n\t\t\t\t\tif( m_dying == false )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tCProjectileCollisionComponent* proj_comp;\r\n\r\n\t\t\t\t\t\tproj_comp = GetProjectileCollisionComponentFromObject( GetObject());\r\n\t\t\t\t\t\tif( proj_comp )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tproj_comp->MarkAsDying();\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tm_dying = true;\r\n\t\t\t\t\t\tm_death_time = Tmr::GetTime() + Tmr::Seconds( 1 );\r\n\t\t\t\t\t\tif( m_death_script != 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tScript::CStruct* params;\r\n\t\t\t\t\t\t\tMth::Vector pos;\r\n\r\n\t\t\t\t\t\t\tpos = feeler.GetPoint();\r\n\t\t\t\t\t\t\tparams = new Script::CStruct;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tparams->AddVector( CRCD(0x7f261953,\"pos\"), pos );\r\n\t\t\t\t\t\t\tparams->AddVector( CRCD(0xc4c809e,\"vel\"), m_vel );\r\n\t\t\t\t\t\t\tparams->AddFloat( CRCD(0x13b9da7b,\"scale\"), m_scale );\r\n\r\n\t\t\t\t\t\t\tScript::RunScript( m_death_script, params );\r\n\r\n\t\t\t\t\t\t\tdelete params;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tm_last_pos = GetObject()->GetPos();\r\n\t\tm_first_frame = false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CCollideAndDieComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCollideAndDieComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CCollideAndDieComponent::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\t\r\n\r\n// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/CollideAndDieComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       VelocityComponent.h\r\n//* OWNER:          SPG\r\n//* CREATION DATE:  07/10/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_COLLIDEANDDIECOMPONENT_H__\r\n#define __COMPONENTS_COLLIDEANDDIECOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/components/suspendcomponent.h>\r\n\r\n// Replace this with the CRCD of the component you are adding\r\n#define\t\tCRC_COLLIDEANDDIE CRCD(0x6259b52b,\"CollideAndDie\")\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or \r\n//  given an object\t\t\t\t \r\n#define\t\tGetCollideAndDieComponent() ((Obj::CCollideAndDieComponent*)GetComponent(CRC_COLLIDE_AND_DIE))\r\n#define\t\tGetCollideAndDieComponentFromObject(pObj) ((Obj::CCollideAndDieComponent*)(pObj)->GetComponent(CRC_COLLIDE_AND_DIE))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CCollideAndDieComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CCollideAndDieComponent();\r\n    virtual ~CCollideAndDieComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void\t\t\t\t\tHide( bool should_hide );\r\n\tvirtual void\t\t\t\t\tFinalize();\r\n\t\t\r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\n\tvoid\t\t\t\t\t\t\tSetCollisionRadius( float radius );\r\n\r\nprivate:\r\n\tCSuspendComponent*\tmp_suspend_component;\r\n\r\n\tfloat\t\t\t\tm_radius;\t// Radius for spherical collision detection\r\n\tfloat\t\t\t\tm_scale;\r\n\tTmr::Time\t\t\tm_birth_time;\r\n\tuint32\t\t\t\tm_death_script;\r\n\tTmr::Time\t\t\tm_death_time;\r\n\tbool\t\t\t\tm_dying;\r\n\tbool\t\t\t\tm_first_frame;\r\n\tMth::Vector\t\t\tm_vel;\r\n\tMth::Vector\t\t\tm_last_pos;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/FloatingLabelComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       FloatingLabelComponent.h\r\n//* OWNER:\t\t\tDan\r\n//* CREATION DATE:  3/13/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/floatinglabelcomponent.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n\r\n#include <gfx/2d/screenelement2.h>\r\n#include <gfx/2d/screenelemman.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent* CFloatingLabelComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CFloatingLabelComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCFloatingLabelComponent::CFloatingLabelComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_FLOATINGLABEL );\r\n\t\r\n\tstrcpy(m_string, \"Unset Label\");\r\n\tm_color_index = 2;\r\n\tm_y_offset = 10.0f * 12.0f;\r\n\tm_screen_element_id = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCFloatingLabelComponent::~CFloatingLabelComponent()\r\n{\r\n\tScript::CStruct* pParams = pParams = new Script::CStruct;\r\n\tpParams->AddChecksum(CRCD(0x40c698af, \"id\"), m_screen_element_id);\r\n\t\r\n\tScript::RunScript(CRCD(0x2575b406, \"destroy_object_label\"), pParams);\r\n\t\r\n\tdelete pParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFloatingLabelComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tconst char* string;\r\n\tif (pParams->GetString(CRCD(0x61414d56, \"string\"), &string))\r\n\t{\r\n\t\tstrncpy(m_string, string, 64);\r\n\t}\r\n\tpParams->GetInteger(CRCD(0x99a9b716, \"color\"), &m_color_index);\r\n\tpParams->GetFloat(CRCD(0x14975800, \"y_offset\"), &m_y_offset);\r\n\tpParams->GetChecksum(CRCD(0x727f9552, \"screen_element_id\"), &m_screen_element_id);\r\n\t\r\n\tDbg_MsgAssert(m_screen_element_id, (\"FloatingLabelComponent has bad screen_elemend_id\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFloatingLabelComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFloatingLabelComponent::Update()\r\n{\r\n\tScript::CStruct* pParams = new Script::CStruct;\r\n\tpParams->AddChecksum(CRCD(0x40c698af, \"id\"), m_screen_element_id);\r\n\t\r\n\tchar text[64];\r\n\tsprintf(text, \"\\\\c%d%s\", m_color_index, m_string);\r\n\r\n\tpParams->AddString(CRCD(0xc4745838, \"text\"), text);\r\n\tpParams->AddVector(CRCD(0x4b491900, \"pos3D\"), GetObject()->m_pos[X], GetObject()->m_pos[Y] + m_y_offset, GetObject()->m_pos[Z]);\r\n\r\n\tFront::CScreenElement *p_name_elem = Front::CScreenElementManager::Instance()->GetElement(m_screen_element_id);\r\n\tif (p_name_elem)\r\n\t{\r\n\t\tp_name_elem->SetProperties(pParams);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tScript::RunScript(CRCD(0x6a060cf0, \"create_object_label\"), pParams);\r\n\t}\r\n\t\r\n\tdelete pParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CFloatingLabelComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFloatingLabelComponent::GetDebugInfo ( Script::CStruct *p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CFloatingLabelComponent::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddString(CRCD(0x2bd21fa8, \"m_string\"), m_string);\r\n\tp_info->AddInteger(CRCD(0x6d83427f, \"m_color_index\"), m_color_index);\r\n\tp_info->AddFloat(CRCD(0x1bcdee78, \"m_y_offset\"), m_y_offset);\r\n\tp_info->AddChecksum(CRCD(0x5f6e2f93, \"m_screen_element_id\"), m_screen_element_id);\r\n\t\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/FloatingLabelComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       FloatingLabelComponent.h\r\n//* OWNER:\t\t\tDan\r\n//* CREATION DATE:  3/13/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_FLOATINGLABELCOMPONENT_H__\r\n#define __COMPONENTS_FLOATINGLABELCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_FLOATINGLABEL CRCD(0xeada1621, \"FloatingLabel\")\r\n\r\n#define\t\tGetFloatingLabelComponent() ((Obj::CFloatingLabelComponent*)GetComponent(CRC_FLOATINGLABEL))\r\n#define\t\tGetFloatingLabelComponentFromObject(pObj) ((Obj::CFloatingLabelComponent*)(pObj)->GetComponent(CRC_FLOATINGLABEL))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CFloatingLabelComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CFloatingLabelComponent();\r\n    virtual ~CFloatingLabelComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetColor ( int color_index ) { m_color_index = color_index; }\r\n\tvoid\t\t\t\t\t\t\tSetString ( char* string ) { strncpy(m_string, string, 64); }\r\n\t\r\nprivate:\r\n\tchar\t\t\t\t\t\t\tm_string[64];\r\n\tint\t\t\t\t\t\t\t\tm_color_index;\r\n\tfloat\t\t\t\t\t\t\tm_y_offset;\r\n\tuint32\t\t\t\t\t\t\tm_screen_element_id;\r\n};\r\n\r\n\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/GunslingerCameraLookAroundComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       GunslingerCameraLookAroundComponent.cpp\r\n//* OWNER:          Dave\r\n//* CREATION DATE:  5/13/03\r\n//****************************************************************************\r\n\r\n#include <gel/components/cameralookaroundcomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/nxviewman.h>\r\n\r\n#include <gfx/debuggfx.h>\r\n\t\t\t\t\t\t   \r\nfloat\tspin_modulator\t\t\t= 1.0f;\r\nfloat\ttilt_modulator\t\t\t= 1.0f;\r\nfloat\tlast_heading_change\t\t= 0.0f;\r\nfloat\tlast_tilt_change\t\t= 0.0f;\r\nbool\tgun_fired\t\t\t\t= false;\r\nbool\tallow_strafe_locking\t= false;\r\n\r\nfloat\tscreen_angle\t\t\t= 72.0f;\t\t// Test value for setting field of view.\r\n\r\nfloat\tlookaround_tilt_angular_speed\t\t= 0.0f;\r\nfloat\tlookaround_heading_angular_speed\t= 0.0f;\r\n\r\n\r\n\r\nnamespace Obj\r\n{\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CCameraLookAroundComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CCameraLookAroundComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCameraLookAroundComponent::CCameraLookAroundComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_CAMERALOOKAROUND );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCameraLookAroundComponent::~CCameraLookAroundComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCameraLookAroundComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCameraLookAroundComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCameraLookAroundComponent::Finalize (   )\r\n{\r\n\tmp_input_component = GetInputComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_input_component);\r\n\r\n\tmLookaroundTilt\t\t\t\t\t= 0.0f;\r\n\tmLookaroundHeading\t\t\t\t= 0.0f;\r\n\tmLookaroundZoom\t\t\t\t\t= 1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CCameraLookAroundComponent::Update()\r\n{\r\n\tCControlPad * p_control_pad;\r\n\t\r\n\tif (Script::GetInt(CRCD(0x702247a5,\"Viewer_controller\"), false))\r\n\t{\r\n\t\tp_control_pad = &mp_input_component->GetControlPad2();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_control_pad = &mp_input_component->GetControlPad();\r\n\t}\r\n\r\n\tif( p_control_pad->m_up.GetTriggered())\r\n\t{\r\n\t\tp_control_pad->m_up.ClearTrigger();\r\n\r\n\t\t// Unfortunately, pressing up on the left control stick will also cause m_up to be triggered, so check this\r\n\t\t// is really the d-pad press.\r\n\t\tif( p_control_pad->GetScaledLeftAnalogStickMagnitude() == 0.0f )\r\n\t\t{\r\n\t\t\t// This would be a good place to put the field of view setting code for the sniper rifle.\r\n\t\t\tif( screen_angle == 72.0f )\r\n\t\t\t{\r\n\t\t\t\tscreen_angle = 25.0f;\r\n\t\t\t}\r\n\t\t\telse if( screen_angle == 25.0f )\r\n\t\t\t{\r\n\t\t\t\tscreen_angle = 7.5f;\r\n\t\t\t}\r\n\t\t\telse if( screen_angle == 7.5f )\r\n\t\t\t{\r\n\t\t\t\tscreen_angle = 72.0f;\r\n\t\t\t}\r\n\t\t\tNx::CViewportManager::sSetScreenAngle( screen_angle );\r\n\t\t}\r\n\t}\r\n\t\r\n\tfloat frame_length = Tmr::FrameLength();\r\n\t\r\n\t// Strafe locking is allowed by default.\r\n\tallow_strafe_locking = true;\r\n\r\n\t// Shouldn't really do this here. Disable strafe locking if not strafing, or if moving forward or backwards.\r\n\tfloat fb = p_control_pad->m_scaled_leftY;\r\n\tfloat lr = p_control_pad->m_scaled_leftX;\r\n\r\n\tif( Mth::Abs( fb ) > 0.0f )\r\n\t{\r\n\t\tallow_strafe_locking = false;\r\n\t}\r\n\r\n\tif( Mth::Abs( lr ) < 0.2f )\r\n\t{\r\n\t\tallow_strafe_locking = false;\r\n\t}\r\n\r\n\tif (!mLookaroundLock && !mLookaroundOverride)\r\n\t{\r\n\t\tfloat target = p_control_pad->m_scaled_rightY;\r\n\r\n\t\t// Modulate with the variable used to damp cursor movement when aiming at a target.\r\n\t\ttarget = target * tilt_modulator;\r\n\r\n#\t\tif 1\r\n//\t\tif( target != 0.0f )\r\n\t\t{\r\n\t\t\tallow_strafe_locking = false;\r\n\r\n\t\t\tif( Script::GetInteger( CRCD( 0x9edfc7af, \"GunslingerInvertAiming\" )) == 0 )\r\n\t\t\t{\r\n\t\t\t\t// Negate value if vertical aiming invert is not enabled.\r\n\t\t\t\ttarget = -target;\r\n\t\t\t}\r\n\r\n\t\t\t// Get script values.\r\n\t\t\tfloat tilt_ka = Script::GetFloat( CRCD( 0xcac0c1d4, \"GunslingerLookaroundTiltKa\" ), Script::ASSERT );\r\n\t\t\tfloat tilt_ea = Script::GetFloat( CRCD( 0x5443ec5a, \"GunslingerLookaroundTiltEa\" ), Script::ASSERT );\r\n\r\n\t\t\tfloat tilt_ks = Script::GetFloat( CRCD( 0x3979b09c, \"GunslingerLookaroundTiltKs\" ), Script::ASSERT );\r\n\t\t\tfloat tilt_es = Script::GetFloat( CRCD( 0xa7fa9d12, \"GunslingerLookaroundTiltEs\" ), Script::ASSERT );\r\n\r\n\t\t\t// Calculate acceleration.\r\n\t\t\tfloat a = tilt_ka * powf( Mth::Abs( target ), tilt_ea ) * (( target > 0.0f ) ? 1.0f : ( target < 0.0f ) ? -1.0f : 0.0f );\r\n\r\n\t\t\t// Calculate max speed.\r\n\t\t\tfloat s = tilt_ks * powf( Mth::Abs( target ), tilt_es ) * (( target > 0.0f ) ? 1.0f : ( target < 0.0f ) ? -1.0f : 0.0f );\r\n\r\n\t\t\tlookaround_tilt_angular_speed += a;\r\n\r\n\t\t\tif( s == 0.0f )\r\n\t\t\t{\r\n\t\t\t\tlookaround_tilt_angular_speed = 0.0f;\r\n\t\t\t}\r\n\t\t\telse if((( s > 0.0f ) && ( lookaround_tilt_angular_speed > s )) || (( s < 0.0f ) && ( lookaround_tilt_angular_speed < s )))\r\n\t\t\t{\r\n\t\t\t\t\tlookaround_tilt_angular_speed = s;\r\n\t\t\t}\r\n\r\n\t\t\tfloat lookaround_tilt_speed = Script::GetFloat( CRCD( 0x67796648, \"GunslingerLookaroundTiltSpeed\" ), Script::ASSERT );\r\n\t\t\tmLookaroundTilt += lookaround_tilt_angular_speed * lookaround_tilt_speed * frame_length;\r\n\r\n\t\t\tlast_tilt_change = lookaround_tilt_angular_speed * lookaround_tilt_speed * frame_length;\r\n\r\n\t\t\tif( mLookaroundTilt > 1.1f )\r\n\t\t\t\tmLookaroundTilt = 1.1f;\r\n\t\t\telse if( mLookaroundTilt < -0.85f )\r\n\t\t\t\tmLookaroundTilt = -0.85f;\r\n\t\t}\r\n#\t\telse\r\n\t\t// This calculation is different for Gunslinger, since we want to be able to look up higher.\r\n//\t\ttarget = -1.4f * (target < 0.0f ? (0.7f * target) : (0.4f * target));\r\n\t\ttarget = -1.4f * ( target < 0.0f ? ( 0.7f * target ) : ( 0.7f * target ));\r\n\r\n\t\tif( Mth::Abs( target - mLookaroundTilt ) > 0.001f )\r\n\t\t{\r\n\t\t\t// Ditto for this calc.\r\n//\t\t\tmLookaroundTilt += (target - mLookaroundTilt) * 3.75f * frame_length;\r\n\t\t\tmLookaroundTilt += (target - mLookaroundTilt) * 6.0f * frame_length;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmLookaroundTilt = target;\r\n\t\t}\r\n#\t\tendif\r\n\t\t\r\n#\t\tif 1\r\n\t\ttarget = p_control_pad->m_scaled_rightX;\r\n\r\n\t\t// Modulate with the variable used to damp cursor movement when aiming at a target.\r\n\t\ttarget = target * spin_modulator;\r\n\t\t\r\n//\t\tif( target != 0.0f )\r\n\t\t{\r\n\t\t\tallow_strafe_locking = false;\r\n\r\n\t\t\t// Get script values.\r\n\t\t\tfloat heading_ka = Script::GetFloat( CRCD( 0x6fd803d9, \"GunslingerLookaroundHeadingKa\" ), Script::ASSERT );\r\n\t\t\tfloat heading_ea = Script::GetFloat( CRCD( 0xf15b2e57, \"GunslingerLookaroundHeadingEa\" ), Script::ASSERT );\r\n\r\n\t\t\tfloat heading_ks = Script::GetFloat( CRCD( 0x9c617291, \"GunslingerLookaroundHeadingKs\" ), Script::ASSERT );\r\n\t\t\tfloat heading_es = Script::GetFloat( CRCD( 0x2e25f1f, \"GunslingerLookaroundHeadingEs\" ), Script::ASSERT );\r\n\r\n\t\t\t// Calculate acceleration.\r\n\t\t\tfloat a = heading_ka * powf( Mth::Abs( target ), heading_ea ) * (( target > 0.0f ) ? 1.0f : ( target < 0.0f ) ? -1.0f : 0.0f );\r\n\r\n\t\t\t// Calculate max speed.\r\n\t\t\tfloat s = heading_ks * powf( Mth::Abs( target ), heading_es ) * (( target > 0.0f ) ? 1.0f : ( target < 0.0f ) ? -1.0f : 0.0f );\r\n\r\n\t\t\tlookaround_heading_angular_speed += a;\r\n\r\n\t\t\tif( s == 0.0f )\r\n\t\t\t{\r\n\t\t\t\tlookaround_heading_angular_speed = 0.0f;\r\n\t\t\t}\r\n\t\t\telse if((( s > 0.0f ) && ( lookaround_heading_angular_speed > s )) || (( s < 0.0f ) && ( lookaround_heading_angular_speed < s )))\r\n\t\t\t{\r\n\t\t\t\t\tlookaround_heading_angular_speed = s;\r\n\t\t\t}\r\n\r\n\t\t\tfloat lookaround_heading_speed = Script::GetFloat( CRCD( 0x8501d824, \"GunslingerLookaroundHeadingSpeed\" ), Script::ASSERT );\r\n\r\n\t\t\t// Control stick left - reticle should move left.\r\n\t\t\tmLookaroundHeading -= lookaround_heading_angular_speed * lookaround_heading_speed * frame_length;\r\n\r\n\t\t\tlast_heading_change\t= lookaround_heading_angular_speed * lookaround_heading_speed * frame_length;\r\n\r\n\t\t\tif( mLookaroundHeading > ( 2 * Mth::PI ))\r\n\t\t\t\tmLookaroundHeading -= ( 2 * Mth::PI );\r\n\t\t\telse if( mLookaroundHeading < 0.0f )\r\n\t\t\t\tmLookaroundHeading += 2 * Mth::PI;\r\n\t\t}\r\n#\t\telse\r\n\t\ttarget = 3.0f * p_control_pad->m_scaled_rightX;\r\n\t\tif (Mth::Abs(target - mLookaroundHeading) > 0.001f)\r\n\t\t{\r\n\t\t\tmLookaroundHeading += (target - mLookaroundHeading) * 3.75f * frame_length;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmLookaroundHeading = target;\r\n\t\t}\r\n#\t\tendif\r\n\t}\r\n\t\r\n\tfloat delta_time = Tmr::FrameLength();\r\n\r\n\tif (mLookaroundOverride)\r\n\t{\r\n\t\tif (mLookaroundDeltaTimer > 0.0f)\r\n\t\t{\r\n\t\t\tif (mLookaroundDeltaTimer > delta_time)\r\n\t\t\t{\r\n\t\t\t\tmLookaroundHeading\t\t+= mLookaroundHeadingDelta * delta_time;\r\n\t\t\t\tmLookaroundTilt\t\t\t+= mLookaroundTiltDelta * delta_time;\r\n\t\t\t\tmLookaroundDeltaTimer\t-= delta_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmLookaroundHeading\t\t= mLookaroundHeadingTarget;\r\n\t\t\t\tmLookaroundTilt\t\t\t= mLookaroundTiltTarget;\r\n\t\t\t\tmLookaroundDeltaTimer\t= 0.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Total hack to simulate shooting for now.\r\n\tgun_fired = false;\r\n\tif( p_control_pad->m_R1.GetTriggered())\r\n\t{\r\n\t\tgun_fired = true;\r\n\t\tp_control_pad->m_R1.ClearTrigger();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CCameraLookAroundComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | SC_SetSkaterCamOverride | \r\n        // @parm float | heading |\r\n        // @parm float | tilt | \r\n        // @parm float | time | \r\n        // @parm float | zoom | \r\n\t\tcase 0xb8f23899:\t// SC_SetSkaterCamOverride\r\n\t\t{\r\n\t\t\tfloat heading, tilt, time;\r\n\t\t\tfloat zoom = 1.0f;\r\n\t\t\tpParams->GetFloat( CRCD(0xfd4bc03e,\"heading\"), &heading, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0xe3c07609,\"tilt\"), &tilt, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0x906b67ba,\"time\"), &time, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0x48d4868b,\"zoom\"), &zoom );\r\n\r\n\t\t\tSetLookaround( heading, tilt, time, zoom );\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | SC_ClearSkaterCamOverride |\r\n\t\tcase 0xe3b327c0:\t// SC_ClearSkaterCamOverride\r\n\t\t\tClearLookaround();\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCameraLookAroundComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CCameraLookAroundComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCameraLookAroundComponent::SetLookaround( float heading, float tilt, float time, float zoom )\r\n{\r\n\tmLookaroundOverride\t\t\t\t= true;\r\n\r\n\tmLookaroundHeadingTarget\t\t= heading;\r\n\tmLookaroundTiltTarget\t\t\t= tilt;\r\n\r\n\t// Calculate delta - the amount to move in 1 second.\r\n\tif (time > 0.0f)\r\n\t{\r\n\t\tmLookaroundHeadingDelta\t\t= (heading - mLookaroundHeading) / time;\r\n\t\tmLookaroundTiltDelta\t\t= (tilt - mLookaroundTilt) / time;\r\n\t}\r\n\r\n\tmLookaroundDeltaTimer\t\t\t= time;\r\n\tmLookaroundZoom\t\t\t\t\t= zoom;\r\n}\r\n\r\n#if 0 // old control input checking code\r\n\r\nchar touched[256 * 256 / 8];\r\nbool initialized = false;\r\n\r\nvoid MapInput (   )\r\n{\r\n\tif (!initialized)\r\n\t{\r\n\t\tfor (int n = 255 * 255; n--; )\r\n\t\t{\r\n\t\t\ttouched[n / 8] = 0;\r\n\t\t}\r\n\t\tinitialized = true;\r\n\t}\r\n\t\r\n\tCControlPad& pad = mp_input_component->GetControlPad();\r\n\t\r\n\tint x = static_cast< int >(pad.m_rightX) + 128;\r\n\tint y = static_cast< int >(pad.m_rightY) + 128;\r\n\t\r\n\t// printf(\"x = %i; y = %i\\n\", x, y);\r\n\t\r\n\tint index = (x * 256) + y;\r\n\t\r\n\t// printf(\"index / 8 = %i\\n\", index / 8);\r\n\t// printf(\"MAX = %i\\n\", 256 * 256 / 8);\r\n\t\r\n\ttouched[index / 8] |= (1 << (index % 8));\r\n}\r\n\r\n\r\nvoid DrawMap (   )\r\n{\r\n\tMth::Vector pos = GetObject()->GetPos();\r\n\tMth::Matrix matrix = GetObject()->GetMatrix();\r\n\t\r\n\tMth::Vector center = pos - 300.0f * matrix[Z];\r\n\tMth::Vector up = matrix[Y];\r\n\tMth::Vector left = -matrix[X];\r\n\t\r\n\tfor (int n = 255 * 255; n--; )\r\n\t{\r\n\t\tif (!(touched[n / 8] & (1 << (n % 8)))) continue;\r\n\t\t\r\n\t\tint x = n / 256;\r\n\t\tint y = n % 256;\r\n\t\t\r\n\t\tMth::Vector point = center + up * (y - 128) + left * (x - 128);\r\n\t\t\r\n\t\tGfx::AddDebugLine(point + up + left, point - up - left, MAKE_RGB(255, 255, 255), 0, 1);\r\n\t\tGfx::AddDebugLine(point + up - left, point - up + left, MAKE_RGB(255, 255, 255), 0, 1);\r\n\t}\r\n}\r\n\r\n#endif\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/GunslingerWalkCameraComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       GunslingerWalkCameraComponent.cpp\r\n//* OWNER:          Dave\r\n//* CREATION DATE:  5/13/03\r\n//****************************************************************************\r\n\r\n#include <gel/components/walkcameracomponent.h>\r\n#include <core/math/slerp.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/components/walkcomponent.h>\r\n#include <gel/components/camerautil.h>\r\n#include <gel/components/cameralookaroundcomponent.h>\r\n#include <gel/components/cameracomponent.h>\r\n#include <gel/components/pedlogiccomponent.h>\t\t\t\t// Messy, but for now used to obtain ped positions etc.\r\n#include <gel/components/weaponcomponent.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gfx/debuggfx.h>\r\n\r\n// These should be members in the cameralookaroundcomponent.\r\nextern float\t\t\tspin_modulator;\r\nextern float\t\t\ttilt_modulator;\r\nextern float\t\t\tlast_heading_change;\r\nextern float\t\t\tlast_tilt_change;\r\nextern bool\t\t\t\tgun_fired;\r\nextern bool\t\t\t\tallow_strafe_locking;\r\n\r\nint\t\t\t\t\t\tbest_ped_timer\t\t\t= 0;\r\nObj::CCompositeObject*\tp_selected_target\t\t= NULL;\r\nfloat\t\t\t\t\ttarget_selection_timer\t= 0.0f;\t\t// Times how long the selected target has been targeted for.\r\n\r\nnamespace Obj\r\n{\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic float s_get_gunslinger_param( uint32 checksum )\r\n{\r\n\tScript::CStruct* p_cam_params = Script::GetStructure( CRCD( 0xa13ff9ae,\"GunslingerCameraParameters\" ));\r\n\tDbg_Assert( p_cam_params );\r\n\r\n\tfloat param;\r\n\tp_cam_params->GetFloat( checksum, &param, Script::ASSERT );\r\n\treturn param;\r\n}\r\n\r\n\t\r\n\t\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CWalkCameraComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CWalkCameraComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCWalkCameraComponent::CWalkCameraComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_WALKCAMERA );\r\n\r\n\tm_last_actual_matrix.Ident();\r\n\tm_last_tripod_pos.Set( 0.0f, 0.0f, 0.0f, 1.0f );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCWalkCameraComponent::~CWalkCameraComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tuint32 target_id = 0 ;\r\n\tpParams->GetChecksum(\"CameraTarget\", &target_id, Script::ASSERT);\r\n\t\r\n\tCCompositeObject* p_target = static_cast< CCompositeObject* >(CCompositeObjectManager::Instance()->GetObjectByID(target_id));\r\n\tDbg_MsgAssert(p_target, (\"Bad CameraTarget given to WalkCameraComponent\"));\r\n\t\t\r\n\tset_target(p_target);\r\n\t\r\n\tm_last_dot = 1.0f;\r\n\tm_current_zoom = 1.0f;\r\n\t\r\n\tm_last_actual_matrix = GetObject()->GetMatrix();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::Finalize()\r\n{\r\n\tmp_lookaround_component = GetCameraLookAroundComponentFromObject(GetObject());\r\n\tmp_camera_component = GetCameraComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_lookaround_component);\r\n\tDbg_Assert(mp_camera_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::Update()\r\n{\r\n\t// optimization KLUDGE\r\n//\tif (Script::GetInteger(CRCD(0x1aa88b08, \"vehicle_mode\")))\r\n//\t{\r\n//\t\tGetObject()->Pause(true);\r\n//\t\treturn;\r\n//\t}\r\n\t\r\n\tif (mp_target->HasTeleported())\r\n\t{\r\n\t\tm_instant_count = 3;\r\n\t}\r\n\r\n\tbool instantly;\r\n\tif (m_instant_count > 0)\r\n\t{\r\n\t\t--m_instant_count;\r\n\t\tinstantly = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tinstantly = false;\r\n\t}\r\n\t\r\n\tmp_camera_component->StoreOldPosition();\r\n\r\n\tfloat frame_length = Tmr::FrameLength();\r\n\t\r\n\t// get input\r\n//\tfloat horiz_control = GetInputComponentFromObject( GetObject())->GetControlPad().m_scaled_rightX;\r\n\tfloat horiz_control = mp_lookaround_component->mLookaroundHeading;\r\n\r\n\t// Restore camera position from last frame, previous to refocusing, lookaround and collision detection.\r\n\tGetObject()->GetMatrix() = m_last_actual_matrix;\r\n\r\n\tMth::Vector\ttarget_facing = -GetObject()->GetMatrix()[Z];\r\n\ttarget_facing[Y] = 0.0f;\r\n\ttarget_facing.Normalize();\r\n\t\r\n\tMth::Vector subject_facing = mp_target->GetMatrix()[Z];\r\n\tsubject_facing[Y] = 0.0f;\r\n\tsubject_facing.Normalize();\r\n\t\r\n\t// two options; we either use our old facing as the target facing or use the subject's facing as the target facing\r\n\tbool use_subject_facing = true;\r\n\t\r\n\t// if in a flush request\r\n\tif (m_flush_request_active)\r\n\t{\r\n\t\t// always use the subject's matrix\r\n\t}\r\n\t// if controlling camera\r\n\telse if (horiz_control != 0.0f)\r\n\t{\r\n\t\tuse_subject_facing = false;\r\n\t}\r\n\t// if the subject's facing is towards the camera\r\n\telse if (Mth::DotProduct(target_facing, subject_facing) < cosf(Mth::DegToRad(s_get_gunslinger_param(CRCD(0xb8da8a73, \"lock_angle\")))))\r\n\t{\r\n\t\tuse_subject_facing = false;\r\n\t}\r\n\t// if the subject is moving very slowly\r\n\telse // if (!mp_target_walk_component->UseDPadCamera())\r\n\t{\r\n\t\tfloat full_slerp_speed;\r\n\t\tfloat min_slerp_speed;\r\n\t\tif (!mp_target_walk_component->UseDPadCamera())\r\n\t\t{\r\n\t\t\tfull_slerp_speed = s_get_gunslinger_param(CRCD(0xbcef6dda, \"full_slerp_speed\"));\r\n\t\t\tmin_slerp_speed = s_get_gunslinger_param(CRCD(0x824349e5, \"min_slerp_speed\"));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfull_slerp_speed = s_get_gunslinger_param(CRCD(0x73da1ec0, \"dpad_full_slerp_speed\"));\r\n\t\t\tmin_slerp_speed = s_get_gunslinger_param(CRCD(0xda5cad3, \"dpad_min_slerp_speed\"));\r\n\t\t}\r\n\t\t\r\n\t\tfloat target_vel = mp_target->GetVel().Length();\r\n\t\tif (target_vel < full_slerp_speed)\r\n\t\t{\r\n\t\t\tuse_subject_facing = false;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Never want to use the subject facing camera.\r\n\tuse_subject_facing = false;\r\n\r\n\tif (use_subject_facing)\r\n\t{\r\n\t\ttarget_facing = subject_facing;\r\n\t}\r\n\t\r\n\t// Build target matrix.\r\n\tMth::Matrix target_matrix;\r\n\ttarget_matrix[W].Set( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\ttarget_matrix[Z] = target_facing;\r\n\ttarget_matrix[Y].Set( 0.0f, 1.0f, 0.0f );\r\n\ttarget_matrix[X].Set( target_facing[Z], 0.0f, -target_facing[X] );\r\n\r\n\t// Dave note - testing default value for now.\r\n\tfloat slerp = 0.06f;\r\n\r\n\ttarget_matrix[X] = -target_matrix[X];\r\n\ttarget_matrix[Z] = -target_matrix[Z];\r\n\r\n\t// use later for camera position\r\n\tMth::Vector up = mp_target->GetMatrix()[Y];\r\n\t\r\n\tif (!instantly)\r\n\t{\r\n\t\tif( Mth::DotProduct(target_matrix[X], GetObject()->GetMatrix()[X]) > CAMERA_SLERP_STOP &&\r\n\t\t\tMth::DotProduct(target_matrix[Y], GetObject()->GetMatrix()[Y]) > CAMERA_SLERP_STOP &&\r\n\t\t\tMth::DotProduct(target_matrix[Z], GetObject()->GetMatrix()[Z]) > CAMERA_SLERP_STOP )\r\n\t\t{\r\n\t\t\t// we're already at our target, so don't do anything\r\n\t\t\t\r\n\t\t\t// turn off any flush request\r\n\t\t\tif (m_flush_request_active)\r\n\t\t\t{\r\n\t\t\t\tm_flush_request_active = false;\r\n\t\t\t\tmp_target_walk_component->SetForwardControlLock(false);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Slerp to the target matrix.\r\n\t\t\tMth::SlerpInterpolator slerper( &GetObject()->GetMatrix(), &target_matrix );\r\n\t\t\t\r\n\t\t\t// Apply the slerping.\r\n\t\t\tslerper.getMatrix( &GetObject()->GetMatrix(), GetTimeAdjustedSlerp( slerp, frame_length ));\r\n\r\n\t\t\t// Calculate for the skater camera.\r\n\t\t\tm_last_dot = Mth::DotProduct(m_last_actual_matrix[Z], GetObject()->GetMatrix()[Z]);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGetObject()->GetMatrix() = target_matrix;\r\n\t}\r\n\r\n\t// At this point, GetObject()->GetMatrix() is valid to store.\r\n\tm_last_actual_matrix = GetObject()->GetMatrix();\r\n\r\n\t// Now apply the lookaround adjustments to the matrix.\r\n\t// Control over target facing.\r\n\tif( horiz_control != 0.0f && !m_flush_request_active )\r\n\t{\r\n\t\t// The horiz_control value needs to be damped when there is an item of interest within the reticle area.\r\n\t\tGetObject()->GetMatrix().RotateYLocal( horiz_control );\r\n\t}\r\n\r\n\tfloat tilt = s_get_gunslinger_param( CRCD( 0xe3c07609, \"tilt\" ));\r\n\tGetObject()->GetMatrix().RotateXLocal( tilt + mp_lookaround_component->mLookaroundTilt );\r\n\r\n\tMth::Vector\tcamera_pos = get_tripod_pos( instantly );\r\n\r\n\t// Test the weapon component to generate the 'sticky' targetting behavior.\r\n\tif( mp_target && p_selected_target )\r\n\t{\r\n\t\tCWeaponComponent* p_weapon = GetWeaponComponentFromObject( mp_target );\r\n\r\n\t\tp_weapon->SetCurrentTarget( p_selected_target );\r\n\t\tp_weapon->SetSightPos( camera_pos );\r\n\t\tp_weapon->SetSightMatrix( GetObject()->GetMatrix());\r\n\r\n\t\tfloat extra_heading_change, extra_tilt_change;\r\n\t\tp_weapon->ProcessStickyTarget( last_heading_change, last_tilt_change, &extra_heading_change, &extra_tilt_change );\r\n\r\n\t\tif(( extra_heading_change != 0.0f ) || ( extra_tilt_change != 0.0f ))\r\n\t\t{\r\n\t\t\t// Reset the matrix to what it was prior to the heading and tilt adjustments.\r\n\t\t\tGetObject()->SetMatrix( m_last_actual_matrix );\r\n\r\n\t\t\tmp_lookaround_component->mLookaroundHeading += extra_heading_change;\r\n\t\t\thoriz_control += extra_heading_change;\r\n\t\t\tGetObject()->GetMatrix().RotateYLocal( horiz_control );\r\n\r\n\t\t\tmp_lookaround_component->mLookaroundTilt += extra_tilt_change;\r\n\t\t\tGetObject()->GetMatrix().RotateXLocal( tilt + mp_lookaround_component->mLookaroundTilt );\r\n\t\t}\r\n\t}\r\n\r\n\t// Calculate zoom\r\n\tfloat above, behind;\r\n\tcalculate_zoom( above, behind );\r\n\t\r\n\tcamera_pos += GetObject()->GetMatrix()[Z] * behind + up * above;\r\n\t\r\n\tMth::Vector\tfocus_pos = mp_target_walk_component->GetEffectivePos() + up * above;\r\n\t\r\n\t// Focus the camera directly on the target object\r\n\ttarget_matrix[Z] = focus_pos - camera_pos;\r\n\ttarget_matrix[Z].Normalize();\r\n\r\n\t// Read back the Y from the current matrix.\r\n//\ttarget_matrix[Y] = GetObject()->GetMatrix()[Y];\r\n\ttarget_matrix[Y] = Mth::Vector( 0.0f, 1.0f, 0.0f );\r\n\r\n\t// Generate new orthonormal X and Y axes.\r\n\ttarget_matrix[X] = Mth::CrossProduct(target_matrix[Y], target_matrix[Z]);\r\n\ttarget_matrix[X].Normalize();\r\n\r\n\ttarget_matrix[Y] = Mth::CrossProduct(target_matrix[Z], target_matrix[X]);\r\n\ttarget_matrix[Y].Normalize();\r\n\r\n\t// Write back into camera matrix.\r\n\t// Since camera points in -Z, but player in +Z, we must negate the X and Z axes\r\n\tGetObject()->GetMatrix()[X]\t= -target_matrix[X];\r\n\tGetObject()->GetMatrix()[Y] = target_matrix[Y];\r\n\tGetObject()->GetMatrix()[Z] = -target_matrix[Z];\r\n\t\r\n\t// clean up matrix\r\n\tGetObject()->GetMatrix()[X][W] = 0.0f;\r\n\tGetObject()->GetMatrix()[Y][W] = 0.0f;\r\n\tGetObject()->GetMatrix()[Z][W] = 0.0f;\r\n\tGetObject()->GetMatrix()[W].Set(0.0f, 0.0f, 0.0f, 1.0f);\r\n\r\n\t// Now do collision detection.\r\n\tApplyCameraCollisionDetection( camera_pos, GetObject()->GetMatrix(), camera_pos - GetObject()->GetMatrix()[Z] * behind,\tfocus_pos );\r\n\t\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tGfx::AddDebugStar(focus_pos, 24.0f, MAKE_RGB(255, 200, 0), 1);\r\n\t}\r\n\t#endif\r\n\t\r\n\tcamera_pos[W] = 1.0f;\r\n\tGetObject()->SetPos( camera_pos );\r\n\r\n\t// Do the target selection.\r\n\tif( mp_target )\r\n\t{\r\n\t\tMth::Vector reticle_min\t= camera_pos;\r\n\t\tMth::Vector reticle_max;\r\n\r\n\t\tCWeaponComponent* p_weapon = GetWeaponComponentFromObject( mp_target );\r\n\r\n\t\tp_weapon->SetSightMatrix( GetObject()->GetMatrix());\r\n\t\tp_selected_target = p_weapon->GetCurrentTarget( reticle_min, &reticle_max );\r\n\r\n\t\tif( gun_fired )\r\n\t\t{\r\n\t\t\tp_weapon->Fire();\r\n\t\t}\r\n\r\n\t\tspin_modulator = p_weapon->GetSpinModulator();\r\n\t\ttilt_modulator = p_weapon->GetTiltModulator();\r\n\r\n\t\tp_weapon->DrawReticle();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CWalkCameraComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | WalkCamera_FlushRequest | Force the camera to lerp quickly to behind the walker\r\n\t\tcase CRCC(0x73febd0f, \"WalkCamera_FlushRequest\"):\r\n\t\t\tFlushRequest();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CWalkCameraComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::ReadyForActivation ( const SCameraState& state )\r\n{\r\n\tm_last_tripod_pos = state.lastTripodPos;\r\n\tm_last_actual_matrix = state.lastActualMatrix;\r\n\tm_last_dot = state.lastDot;\r\n\tm_current_zoom = state.lastZoom;\r\n\tm_flush_request_active = false;\r\n\t\r\n\tmp_lookaround_component->mLookaroundTilt = 0.0f;\r\n\tmp_lookaround_component->mLookaroundHeading = 0.0f;\r\n\tmp_lookaround_component->mLookaroundZoom = 1.0f;\r\n\tmp_lookaround_component->mLookaroundLock = false;\r\n\t\r\n\tm_override_active = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::GetCameraState ( SCameraState& state )\r\n{\r\n\tstate.lastActualMatrix = m_last_actual_matrix;\r\n\tstate.lastTripodPos = m_last_tripod_pos;\r\n\tstate.lastDot = m_last_dot;\r\n\tstate.lastZoom = m_current_zoom;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::FlushRequest (   )\r\n{\r\n\tm_flush_request_active = true;\r\n\tmp_target_walk_component->SetForwardControlLock(true);\r\n\t\r\n\t// flush requests zero skater cam lookaround\r\n\tmp_lookaround_component->mLookaroundHeading = 0.0f;\r\n\tmp_lookaround_component->mLookaroundTilt = 0.0f;\r\n\tmp_lookaround_component->mLookaroundZoom = 1.0f;\r\n\tmp_lookaround_component->mLookaroundLock = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::set_target ( CCompositeObject* p_target )\r\n{\r\n\tmp_target = p_target;\r\n\tDbg_Assert(mp_target);\r\n\t\r\n\tmp_target_walk_component = GetWalkComponentFromObject(mp_target);\r\n\tDbg_Assert(mp_target_walk_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CWalkCameraComponent::get_tripod_pos( bool instantly )\r\n{\r\n\tif (instantly)\r\n\t{\r\n\t\tm_last_tripod_pos = mp_target_walk_component->GetEffectivePos();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfloat lerp_xz = GetTimeAdjustedSlerp(s_get_gunslinger_param(CRCD(0xae47899b, \"lerp_xz\")), Tmr::FrameLength());\r\n\t\tfloat lerp_y = GetTimeAdjustedSlerp(s_get_gunslinger_param(CRCD(0xe1e4e104, \"lerp_y\")), Tmr::FrameLength());\r\n\t\t\r\n\t\tconst Mth::Vector& target_pos = mp_target_walk_component->GetEffectivePos();\r\n\r\n\t\tm_last_tripod_pos.Set(\r\n\t\t\tMth::Lerp(m_last_tripod_pos[X], target_pos[X], lerp_xz),\r\n\t\t\tMth::Lerp(m_last_tripod_pos[Y], target_pos[Y], lerp_y),\r\n\t\t\tMth::Lerp(m_last_tripod_pos[Z], target_pos[Z], lerp_xz)\r\n\t\t);\r\n\t}\r\n\r\n\treturn m_last_tripod_pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::calculate_zoom ( float& above, float& behind )\r\n{\r\n\tfloat target_zoom = 1.0f;\r\n\r\n\t// If lookaround override is set, factor in the lookaround override zoom.\r\n\tif (mp_lookaround_component->mLookaroundOverride && mp_lookaround_component->mLookaroundZoom != 1.0f)\r\n\t{\r\n\t\ttarget_zoom *= mp_lookaround_component->mLookaroundZoom;\r\n\t}\r\n\t\r\n//\tm_current_zoom += (( target_zoom - m_current_zoom ) * s_get_gunslinger_param( CRCD( 0x748743a7, \"zoom_lerp\" )));\r\n\tm_current_zoom += (( target_zoom - m_current_zoom ) * s_get_gunslinger_param( CRCD( 0x748743a7, \"zoom_lerp\" )));\r\n\t\r\n//\tbehind = s_get_gunslinger_param(CRCD(0x52e6c41b, \"behind\")) * m_current_zoom;\r\n\tbehind = s_get_gunslinger_param(CRCD(0x52e6c41b, \"behind\")) * m_current_zoom;\r\n\r\n\t// Behind is also shortened when the lookaround camera is tilting upwards.\r\n\tif( mp_lookaround_component->mLookaroundTilt < 0.0f )\r\n\t{\r\n\t\tfloat max_tilt = -0.9f;\r\n//\t\tbehind = behind * (0.4f + (0.6f * ((max_tilt + mp_lookaround_component->mLookaroundTilt) / max_tilt)));\r\n\t\tbehind = behind * ( 0.0f + ( 1.0f * (( max_tilt - mp_lookaround_component->mLookaroundTilt ) / max_tilt )));\r\n\t}\r\n\telse if( mp_lookaround_component->mLookaroundTilt > 0.0f )\r\n\t{\r\n\t\tfloat max_tilt = 1.4f;\r\n\t\tbehind = behind * ( 0.0f + ( 1.0f * (( max_tilt - mp_lookaround_component->mLookaroundTilt ) / max_tilt )));\r\n\t}\r\n\r\n\t// Use lip_trick_above when doing a lip trick.\r\n//\tfloat above_val = s_get_gunslinger_param(CRCD(0xb96ae2d, \"above\"));\r\n\tfloat above_val = s_get_gunslinger_param( CRCD( 0xb96ae2d, \"above\" ));\r\n\t\r\n\t// Figure above tending towards the perfect above, if zoom is < 1.0.\r\n\tif( m_current_zoom < 1.0f )\r\n\t{\r\n\t\tabove = SKATERCAMERACOMPONENT_PERFECT_ABOVE + ((above_val - SKATERCAMERACOMPONENT_PERFECT_ABOVE) * m_current_zoom);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tabove = above_val;\r\n\t}\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/GunslingerWalkComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       WalkComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  4/2/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/walkcomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/walkcameracomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/triggercomponent.h>\r\n#include <gel/components/movablecontactcomponent.h>\r\n#include <gel/components/railmanagercomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/collision/collcache.h>\r\n\r\n#include <sk/objects/rail.h>\r\n#include <sk/engine/feeler.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n\r\n\r\n/*\r\n * - Take out manual, take out manual, take out manual.\r\n * - Switch over to no-origin-teleport animations.\r\n * - Catching on curbs right after jump (use snap up code from skater)\r\n * - Moving contacts (and sticking to moving rails).\r\n * - Control Feel\r\n *    - Perhaps X equals run only during run outs.\r\n * - Camera\r\n *    - Flush requests don't quite complete using the timer method.  Perhaps with forward control locking, the goal method may once again be useful.\r\n *    - Transition out of vert facing camera.  Perhaps flush camera at first landing after an air transition.\r\n *    - Rewrite camera with \"forward locking\" affecting target matrix instead of turning off lerping.  Lookaround when walking shouldn't reset to behind\r\n *      during walking.\r\n * - Shadow update.\r\n * - Height update.\r\n * - Enter/exit walk behavior (always rotates to along slope, run out to walk behavior still looks odd).\r\n * - Turn off stance panel nollie.\r\n * - Step up/down (use feeler to look ahead).  Delay WalkOffEdge animation change.\r\n * - Animations:\r\n *    - Pull-up-from-hang has no feet!\r\n *    - Trot walking animation.\r\n *    - Drop-to-hang animation.\r\n *    - Hop-to-hang animation.\r\n *    - Three walk/run-to-stand animations.\r\n *    - Rotate walk/run animation.\r\n *    - Two ladder idle animations.\r\n *    - Onto-ladder-top animation. \r\n *    - Off-ladder-bottom animation.\r\n *    - Ladder-to-hang/hang-to-ladder animations.\r\n *    - idle skater to stand\r\n *    - land to walk issues\r\n *    - special pull-up-to-wire anim\r\n *    - off-ladder-bottom anim to allow blending at anim start / teleport at anim end\r\n *    - onto-ladder-top anim to allow blending at anim start / teleport at anim end\r\n *    - grab-to-hang swing and wall anims suck\r\n *    - grab-to-hang sideways swing\r\n *    - Onto-ladder-top animation.  Currently play Off-ladder-top backwards.\r\n *    - Fall-air before jump-air anim.\r\n * - Animation comments:\r\n *    - running land doesn't really work (no weight), especially when you land and then immediately run off an edge and then land again\r\n *    - full run is odd looking\r\n * - Walk to stand animation will require at least three versions.\r\n * - Hang\r\n *    - Rail-to-rail ledge transition issues.\r\n *    - Jerky rail corners.\r\n *    - Non horizontal hang movement animations.\r\n *    - Camera pop during pull-up (caused by camera collision).\r\n *    - Jump off hang.\r\n * - Ladder\r\n *    - Jump off ladder.\r\n *    - Jump onto ladder.\r\n *    - You can grind ladders.\r\n * - Grab rail in air.\r\n * - Little talkie boxes don't always work.\r\n * - Gaps still trigger, but based on skate state.  Maybe run gap component while walking and include walking gap flag.\r\n * - How can we deal with a low snap-up height, yet allow for steep slope walking?\r\n * - Grind transition animation in Grind script (check to see if its playing).\r\n * - Clean 1/3 second delay before X running.\r\n * - Upper body interpenetrates stuff.\r\n * - Hang from bottom of ladder.\r\n * - Pull up collision restrictions are too restrictive (use push feeler distance?).\r\n * - Make it easier to grab a rail when you walk off an edge.\r\n * - Ladder to rail across top.  Rail across top to ladder.\r\n * - Hand-plants, drop-ins, etc.\r\n * BUGS:\r\n * - Snap to hangs can cause the origin to go to bad places?  NJ by your roof.\r\n * - Fall through verts with low frame rate.\r\n * - Pop in transition from last to first frames of slow cycling walk animations.\r\n */\r\n\r\nnamespace Obj\r\n{\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic float s_get_gunslinger_param( uint32 checksum )\r\n{\r\n\tScript::CStruct* p_walk_params = Script::GetStructure( CRCD( 0x1c33e162, \"GunslingerWalkParameters\" ));\r\n\tDbg_Assert(p_walk_params);\r\n\t\r\n\tfloat param;\r\n\tp_walk_params->GetFloat(checksum, &param, Script::ASSERT);\r\n\treturn param;\r\n}\r\n\r\n\t\r\n\t\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CWalkComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CWalkComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCWalkComponent::CWalkComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_WALK );\r\n\t\r\n\tmp_collision_cache = Nx::CCollCacheManager::sCreateCollCache();\r\n\t\r\n\tmp_input_component = NULL;\r\n\tmp_animation_component = NULL;\r\n\tmp_movable_contact_component = NULL;\r\n\r\n\tm_facing.Set( 0.0f, 0.0f, 0.0f, 0.0f );\r\n\tm_control_direction.Set( 0.0f, 0.0f, 0.0f, 0.0f );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCWalkComponent::~CWalkComponent()\r\n{\r\n\tNx::CCollCacheManager::sDestroyCollCache(mp_collision_cache);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::Finalize()\r\n{\r\n\tmp_input_component = GetInputComponentFromObject(GetObject());\r\n\tmp_animation_component = GetAnimationComponentFromObject(GetObject());\r\n\tmp_model_component = GetModelComponentFromObject(GetObject());\r\n\tmp_trigger_component = GetTriggerComponentFromObject(GetObject());\r\n\tmp_physics_control_component = GetSkaterPhysicsControlComponentFromObject(GetObject());\r\n\tmp_movable_contact_component = GetMovableContactComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_input_component);\r\n\tDbg_Assert(mp_animation_component);\r\n\tDbg_Assert(mp_model_component);\r\n\tDbg_Assert(mp_trigger_component);\r\n\tDbg_Assert(mp_physics_control_component);\r\n\tDbg_Assert(mp_movable_contact_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tuint32 camera_id;\r\n\tif (pParams->GetChecksum(CRCD(0xc4e311fa, \"camera\"), &camera_id))\r\n\t{\r\n\t\tCCompositeObject* p_camera = static_cast< CCompositeObject* >(CCompositeObjectManager::Instance()->GetObjectByID(camera_id));\r\n\t\tDbg_MsgAssert(mp_camera, (\"No such camera object\"));\r\n\t\tSetAssociatedCamera(p_camera);\r\n\t}\r\n}\r\n\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::Update()\r\n{\r\n\t// TEMP: debounce R1 after a transition\r\n\tif (m_ignore_grab_button && !mp_input_component->GetControlPad().m_R1.GetPressed())\r\n\t{\r\n\t\tm_ignore_grab_button = false;\r\n\t}\r\n\r\n\t// zero the frame event\r\n\tm_last_frame_event = m_frame_event;\r\n\tm_frame_event = 0;\r\n\t\r\n\t// get input\r\n    get_controller_input();\r\n\t\r\n\t// extract initial state for this frame from the object\r\n\t\r\n\tm_frame_start_pos = m_pos = GetObject()->GetPos();\r\n\t\r\n\tm_horizontal_vel = GetObject()->GetVel();\r\n\tm_horizontal_vel[Y] = 0.0f;\r\n\tm_vertical_vel = GetObject()->GetVel()[Y];\r\n\t\r\n\t// note that m_facing and m_upward will often not be orthogonal, but will always span a plan\r\n\t\r\n\t// generally straight up, but now after a transition from skating\r\n\tm_upward = GetObject()->GetMatrix()[Y];\r\n\t\r\n\tm_facing = GetObject()->GetMatrix()[Z];\r\n\tm_facing[Y] = 0.0f;\r\n\tfloat length = m_facing.Length();\r\n\tif (length < 0.001f)\r\n\t{\r\n\t\t// upward facing orientation matrix\r\n\t\tm_facing = -GetObject()->GetMatrix()[Y];\r\n\t\tm_facing[Y] = 0.0f;\r\n\t\tm_facing.Normalize();\r\n\t\t\r\n\t\t// since m_upward is now in the same plan as m_facing, push m_upward up a touch\r\n\t\tm_upward[Y] += 0.01f;\r\n\t\tm_upward.Normalize();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_facing /= length;\r\n\t}\r\n\t\r\n\t// set the frame length\r\n\tm_frame_length = Tmr::FrameLength();\r\n\t\r\n\t// go to our true Y position\r\n\tm_curb_float_height_adjusted = false;\r\n\tm_pos[Y] -= m_curb_float_height;\r\n\t\r\n\t// switch logic based on walking state\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase WALKING_GROUND:\r\n\t\t\tgo_on_ground_state();\r\n\t\t\tbreak;\r\n\r\n\t\tcase WALKING_AIR:\r\n\t\t\tgo_in_air_state();\r\n\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n//\t\tcase WALKING_HOP:\r\n//\t\t\tgo_hop_state();\r\n//\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\tcase WALKING_HANG:\r\n\t\t\tgo_hang_state();\r\n\t\t\tbreak;\r\n            \r\n\t\tcase WALKING_LADDER:\r\n\t\t\tgo_ladder_state();\r\n            break;\r\n\t\t\t\r\n\t\tcase WALKING_ANIMWAIT:\r\n\t\t\tgo_anim_wait_state (   );\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\t// the there's no curb to adjust due to, lerp down to zero\r\n\tif (!m_curb_float_height_adjusted)\r\n\t{\r\n\t\tm_curb_float_height = Mth::Lerp(m_curb_float_height, 0.0f, s_get_gunslinger_param(CRCD(0x9b3388fa, \"curb_float_lerp_down_rate\")) * m_frame_length);\r\n\t}\r\n\t\r\n\t// adjust back to our curb float Y position\r\n\tm_pos[Y] += m_curb_float_height;\r\n\t\r\n\t// scripts may have restarted us / switched us to skating\r\n//\tif (should_bail_from_frame()) return;\r\n\t\r\n\t// keep the object from falling through holes in the geometry\r\n\tif (m_state == WALKING_GROUND || m_state == WALKING_AIR)\r\n\t{\r\n\t\tuber_frig();\r\n\t}\r\n\t\r\n\t// rotate to upright\r\n\tlerp_upright();\r\n\t\r\n\t// setup the object based on this frame's walking\r\n\tcopy_state_into_object();\r\n\t\r\n\tDbg_Assert(m_frame_event);\r\n\tGetObject()->SelfEvent(m_frame_event);\r\n\t\r\n\t// set the animation speeds\r\n\tswitch (m_anim_scale_speed)\r\n\t{\r\n\t\tcase RUNNING:\r\n\t\t\tif (m_anim_standard_speed > 0.0f)\r\n\t\t\t{\r\n\t\t\t\tmp_animation_component->SetAnimSpeed(m_anim_effective_speed / m_anim_standard_speed, false, false);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase HANGMOVE:\r\n\t\t\tmp_animation_component->SetAnimSpeed(m_anim_effective_speed / s_get_gunslinger_param(CRCD(0xd77ee881, \"hang_move_speed\")), false, false);\r\n\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\tcase LADDERMOVE:\r\n\t\t\tmp_animation_component->SetAnimSpeed(m_anim_effective_speed / s_get_gunslinger_param(CRCD(0xab2db54, \"ladder_move_speed\")), false, false);\r\n\t\t\tbreak;\r\n\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\t// camera controls\r\n\t// NOTE: script parameters\r\n\tswitch (m_frame_event)\r\n\t{\r\n\t\tcase CRCC(0xf41aba21, \"Hop\"):\r\n\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase CRCC(0x2d9815c3, \"HangMoveLeft\"):\r\n\t\t{\r\n\t\t\tMth::Vector facing = m_facing;\r\n\t\t\tfacing.RotateY(-0.95f);\r\n\t\t\tmp_camera_component->SetOverrides(facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase CRCC(0x279b1f0b, \"HangMoveRight\"):\r\n\t\t{\r\n\t\t\tMth::Vector facing = m_facing;\r\n\t\t\tfacing.RotateY(0.95f);\r\n\t\t\tmp_camera_component->SetOverrides(facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\t\r\n\t\tcase CRCC(0x4194ecca, \"Hang\"):\r\n\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase CRCC(0xc84243da, \"Ladder\"):\r\n\t\tcase CRCC(0xaf5abc82, \"LadderMoveUp\"):\r\n\t\tcase CRCC(0xfec9dded, \"LadderMoveDown\"):\r\n\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\tcase CRCC(0x4fe6069c, \"AnimWait\"):\r\n\t\t\tif (m_anim_wait_camera_mode == AWC_CURRENT)\r\n\t\t\t{\r\n\t\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmp_camera_component->SetOverrides(m_drift_goal_facing, 0.05f);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\r\n\t\tdefault:\r\n\t\t\tmp_camera_component->UnsetOverrides();\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tGfx::AddDebugStar(GetObject()->GetPos(), 36.0f, MAKE_RGB(255, 255, 255), 1);\r\n\t}\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CWalkComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | Walk_Ground |\r\n\t\tcase CRCC(0x893213e5, \"Walk_Ground\"):\r\n\t\t\treturn m_state == WALKING_GROUND ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Walk_Air |\r\n\t\tcase CRCC(0x5012082e, \"Walk_Air\"):\r\n\t\t\treturn m_state == WALKING_AIR ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Walk_Hang |\r\n\t\tcase CRCC(0x9a3ca853, \"Walk_Hang\"):\r\n\t\t\treturn m_state == WALKING_HANG ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Walk_Ladder |\r\n\t\tcase CRCC(0x19702ca8, \"Walk_Ladder\"):\r\n\t\t\treturn m_state == WALKING_LADDER ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Walk_GetStateTime | Loads the time in milliseconds since last state change.\r\n\t\tcase CRCC(0xce64576c, \"Walk_GetStateTime\"):\r\n\t\t\tpScript->GetParams()->AddInteger(CRCD(0x5ab23cc9, \"StateTime\"), Tmr::ElapsedTime(m_state_timestamp));\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | Walk_Jump |\r\n\t\tcase CRCC(0x83e4bd70, \"Walk_Jump\"):\r\n\t\t{\r\n\t\t\t// jump strength scales with the length the jump button has been held\r\n\t\t\tjump();\r\n//\t\t\tjump(Mth::Lerp(\r\n//\t\t\t\ts_get_gunslinger_param(CRCD(0x246d0bf3, \"min_jump_factor\")), \r\n//\t\t\t\t1.0f,\r\n//\t\t\t\tMth::ClampMax(mp_input_component->GetControlPad().m_x.GetPressedTime() / s_get_gunslinger_param(CRCD(0x12333ebd, \"hold_time_for_max_jump\")), 1.0f)\r\n//\t\t\t));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n//\t\tcase CRCC(0xeb0d763b, \"Walk_HangJump\"):\r\n//\t\t{\r\n//\t\t\t// jump strength scales with the length the jump button has been held\r\n//\t\t\tjump(s_get_gunslinger_param(CRCD(0xf2fa5845, \"hang_jump_factor\")), true);\r\n//\t\t\tbreak;\r\n//\t\t}\r\n\t\t\r\n\t\t// @script | Walk_SetDragFactor |\r\n\t\tcase CRCC(0xc6100a7d, \"Walk_SetDragFactor\"):\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x4e4fae43, \"Walk_ResetDragFactor\"):\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0xaf04b983, \"Walk_GetSpeedScale\"):\r\n\t\t{\r\n\t\t\tuint32 checksum;\r\n\t\t\tif (m_anim_effective_speed < s_get_gunslinger_param(CRCD(0xf3649996, \"max_slow_walk_speed\")))\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x1150cabb, \"WALK_SLOW\");\r\n\t\t\t}\r\n\t\t\telse if (m_anim_effective_speed < s_get_gunslinger_param(CRCD(0x6a5805d8, \"max_fast_walk_speed\")))\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x131f2a2, \"WALK_FAST\");\r\n\t\t\t}\r\n\t\t\telse if (m_anim_effective_speed < s_get_gunslinger_param(CRCD(0x1c94cc9c, \"max_slow_run_speed\")))\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x5606d106, \"RUN_SLOW\");\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x4667e91f, \"RUN_FAST\");\r\n\t\t\t}\r\n\t\t\tpScript->GetParams()->AddChecksum(CRCD(0x92c388f, \"SpeedScale\"), checksum);\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | Walk_ScaleAnimSpeed | Sets the manner in which the walk animations speeds should be scaled.\r\n\t\t// @flag Off | No animation speed scaling.\r\n\t\t// @flag Run | Scale animation speeds against running speed.\r\n\t\t// @flag Walk | Scale animation speeds against walking speed.\r\n\t\tcase CRCC(0x56112c03, \"Walk_ScaleAnimSpeed\"):\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0xd443a2bc, \"Off\")))\r\n\t\t\t{\r\n\t\t\t\tif (m_anim_scale_speed != OFF)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_anim_scale_speed = OFF;\r\n\t\t\t\t\tmp_animation_component->SetAnimSpeed(1.0f, false, true);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0xaf895b3f, \"Run\")))\r\n\t\t\t{\r\n\t\t\t\tm_anim_scale_speed = RUNNING;\r\n\t\t\t}\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0x6384f1da, \"HangMove\")))\r\n\t\t\t{\r\n\t\t\t\tm_anim_scale_speed = HANGMOVE;\r\n\t\t\t}\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0xa2bfe505, \"LadderMove\")))\r\n\t\t\t{\r\n\t\t\t\tm_anim_scale_speed = LADDERMOVE;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(false, (\"Walk_ScaleAnimSpeed requires Off, Run, or Walk flag\"));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tpParams->GetFloat(CRCD(0xb2d59baf, \"StandardSpeed\"), &m_anim_standard_speed);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | Walk_AnimWaitComplete | Signal from script that the walk component should leave its animation wait\r\n\t\tcase CRCC(0x9d3eebe8, \"Walk_AnimWaitComplete\"):\r\n\t\t\tanim_wait_complete();\r\n\t\t\tbreak;\r\n\t\t\t\t   \t\t\t\r\n\t\t// @script | Walk_GetHangInitAnimType | Determine which type of initial hang animation should be played\r\n\t\tcase CRCC(0xc6cd659e, \"Walk_GetHangInitAnimType\"):\r\n\t\t\t// m_initial_hang_animation is set when the hang rail is filtered\r\n\t\t\tpScript->GetParams()->AddChecksum(CRCD(0x85fa9ac4, \"HangInitAnimType\"), m_initial_hang_animation);\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CWalkComponent::GetDebugInfo\"));\r\n\t\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase WALKING_GROUND:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0x58007c97, \"GROUND\"));\r\n\t\t\tbreak;\r\n\t\tcase WALKING_AIR:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0x439f4704, \"AIR\"));\r\n\t\t\tbreak;\r\n//\t\tcase WALKING_HOP:\r\n//\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0xf41aba21, \"HOP\"));\r\n//\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t \r\n\t\tcase WALKING_HANG:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0x4194ecca, \"HANG\"));\r\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t \r\n        case WALKING_LADDER:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0xc84243da, \"LADDER\"));\r\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t \r\n        case WALKING_ANIMWAIT:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0x4fe6069c, \"ANIMWAIT\"));\r\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t \r\n\t}\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::SetAssociatedCamera ( CCompositeObject* camera_obj )\r\n{\r\n\tmp_camera = camera_obj;\r\n\tDbg_Assert(mp_camera);\r\n\tmp_camera_component = GetWalkCameraComponentFromObject(mp_camera);\r\n\tDbg_MsgAssert(mp_camera_component, (\"No WalkCameraComponent in camera object\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::ReadyWalkState ( bool to_ground_state )\r\n{\r\n\t// setup the state in preparation for being in walking mode next object update\r\n\tMARK;\r\n\t\r\n    // always reset the state timestamp\r\n    m_state_timestamp = Tmr::GetTime();\r\n\r\n\tif (to_ground_state)\r\n\t{\r\n\t\tset_state(WALKING_GROUND);\r\n\t\t\r\n\t\t// will be incorrect for one frame\r\n\t\tm_ground_normal.Set(0.0f, 1.0f, 0.0);\r\n\t\t\r\n\t\tm_last_ground_feeler_valid = false;\r\n\t\t\r\n\t\tGetObject()->GetVel()[Y] = 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tset_state(WALKING_AIR);\r\n\t\t\r\n\t\t// set primary air direction in the direction of velocity\r\n\t\tm_primary_air_direction = GetObject()->GetVel();\r\n\t\tm_primary_air_direction[Y] = 0.0f;\r\n\t\tfloat length = m_primary_air_direction.Length();\r\n\t\tif (length < 0.001f)\r\n\t\t{\r\n\t\t\t// or facing\r\n\t\t\tm_primary_air_direction = GetObject()->GetMatrix()[Z];\r\n\t\t\tm_primary_air_direction[Y] = 0.0f;\r\n\t\t\tlength = m_primary_air_direction.Length();\r\n\t\t\tif (length < 0.001f)\r\n\t\t\t{\r\n\t\t\t\t// or future facing\r\n\t\t\t\tm_primary_air_direction = -GetObject()->GetMatrix()[Y];\r\n\t\t\t\tm_primary_air_direction[Y] = 0.0f;\r\n\t\t\t\tlength = m_primary_air_direction.Length();\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_primary_air_direction /= length;\r\n\t\t\r\n\t\tleave_movable_contact_for_air(GetObject()->GetVel(), GetObject()->GetVel()[Y]);\r\n\t}\r\n\r\n\tm_curb_float_height = 0.0f;\r\n\t\r\n\tm_last_frame_event = 0;\r\n\t\r\n\t// TEMP: debounce R1 after a transition\r\n\tm_ignore_grab_button = true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::CleanUpWalkState (   )\r\n{\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::go_on_ground_state( void )\r\n{\r\n\t// Check for trying to mount a horse, triggered on triangle.\r\n\tif( mp_input_component->GetControlPad().m_triangle.GetTriggered())\r\n\t{\r\n\t\tmp_input_component->GetControlPad().m_triangle.ClearTrigger();\r\n\r\n\t\t// Get the control component.\r\n\t\tCSkaterPhysicsControlComponent*\tp_control_component = GetSkaterPhysicsControlComponentFromObject( GetObject());\r\n\t\tp_control_component->CallMemberFunction( CRCD( 0x14c4f16b, \"SkaterPhysicsControl_SwitchWalkingToRiding\"), NULL, NULL );\r\n\r\n\t\t// Send the 'Ride' exception.\r\n\t\tm_frame_event = CRCD( 0x64c2832f, \"Ride\" );\r\n\t\tGetObject()->SelfEvent( m_frame_event );\r\n\t\treturn;\r\n\t}\r\n\r\n\taccount_for_movable_contact();\r\n\t\r\n\tsetup_collision_cache();\r\n\t\r\n\t// calculate initial horizontal speed\r\n\tfloat horizontal_speed = m_horizontal_vel.Length();\r\n\t\r\n\tcalculate_horizontal_speed_and_facing(horizontal_speed);\r\n\t\r\n\t// calculate this frame's movement\r\n\tm_horizontal_vel = horizontal_speed * m_facing;\r\n\t\r\n\t// prevent movement into walls\r\n\tif (adjust_horizonal_vel_for_environment())\r\n\t{\r\n\t\t// turn to face newly adjusted velocity\r\n\t\tadjust_facing_for_adjusted_horizontal_vel();\r\n\t}\r\n\t\r\n\t// if we are wall pushing, we may have decided to switch states during adjust_horizonal_vel_for_environment based on our environment\r\n\tif (m_state != WALKING_GROUND /*|| should_bail_from_frame()*/)\r\n\t{\r\n\t\tCFeeler::sClearDefaultCache();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// apply movement for this frame\r\n\tm_pos += m_horizontal_vel * m_frame_length;\r\n\t\r\n\t// snap up and down curbs and perhaps switch to air\r\n\trespond_to_ground();\r\n\tif (m_state != WALKING_GROUND /*|| should_bail_from_frame()*/)\r\n\t{\r\n\t\tCFeeler::sClearDefaultCache();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tadjust_curb_float_height();\r\n\t\r\n\t// insure that we do not slip through the cracks in the collision geometry which are a side-effect of moving collidable objects\r\n\tif (CCompositeObject* p_inside_object = mp_movable_contact_component->CheckInsideObjects(m_pos, m_frame_start_pos))\r\n\t{\r\n\t\tMESSAGE(\"WALKING_GROUND, within moving object\");\r\n\t\t\r\n\t\t// allow it to push us forward, causing a bit of a stumble\r\n\t\tm_horizontal_vel = p_inside_object->GetVel();\r\n\t\tm_horizontal_vel[Y] = 0.0f;\r\n\t\tm_vertical_vel = 0.0f;\r\n\t\t\r\n\t\tfloat speed_sqr = m_horizontal_vel.LengthSqr();\r\n\t\tif (speed_sqr > (10.0f * 10.0f))\r\n\t\t{\r\n\t\t\tm_facing = m_horizontal_vel * (1.0f / sqrtf(speed_sqr));\r\n\t\t}\r\n\t}\r\n\t\r\n\tCFeeler::sClearDefaultCache();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::CollideWithOtherSkaterLost ( CCompositeObject* p_other_skater )\r\n{\r\n\tset_state(WALKING_AIR);\r\n\tm_primary_air_direction = m_facing;\r\n\t\r\n\tleave_movable_contact_for_air(GetObject()->GetVel(), GetObject()->GetVel()[Y]);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::calculate_horizontal_speed_and_facing ( float &horizontal_speed )\r\n{\r\n\t// calculate user's desired speed\r\n\tfloat desired_speed = calculate_desired_speed();\r\n\t\t\t   \t\r\n\t// setup frame's event\r\n\tif (desired_speed <= s_get_gunslinger_param(CRCD(0x74e8227d, \"max_stand_speed\")))\r\n\t{\r\n\t\tm_frame_event = CRCD(0x9b46e749, \"Stand\");\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_frame_event = CRCD(0xaf895b3f, \"Run\");\r\n\t}\r\n\r\n\tbool special_acceleration = false;\r\n\t\r\n\t// adjust facing based on input\r\n\t\r\n\tif( m_control_magnitude > 0.0f )\r\n\t{\r\n\t\tfloat dot = Mth::DotProduct( m_facing, m_control_direction );\r\n\t\t\r\n\t\tif (horizontal_speed < s_get_gunslinger_param(CRCD(0x52582d5b, \"max_rotate_in_place_speed\")) && dot < cosf(Mth::DegToRad(s_get_gunslinger_param(CRCD(0x5dff96a4, \"max_rotate_in_place_angle\")))))\r\n\t\t{\r\n\t\t\t// low speed rotate to desired orientation with no speed change\r\n\t\t\t\r\n\t\t\tfloat delta_angle = Mth::DegToRad(s_get_gunslinger_param(CRCD(0xb557804b, \"rotate_in_place_rate\"))) * m_control_magnitude * m_frame_length;\r\n\t\t\tbool left_turn = -m_facing[Z] * m_control_direction[X] + m_facing[X] * m_control_direction[Z] < 0.0f;\r\n\t\t\t\r\n\t\t\tif (!m_run_toggle)\r\n\t\t\t{\r\n\t\t\t\tdelta_angle *= s_get_gunslinger_param(CRCD(0x7b446c98, \"walk_rotate_factor\"));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tfloat cos_delta_angle = cosf(left_turn ? delta_angle : -delta_angle);\r\n\t\t\tfloat sin_delta_angle = sinf(left_turn ? delta_angle : -delta_angle);\r\n\t\t\tfloat adjusted_vel = cos_delta_angle * m_facing[X] + sin_delta_angle * m_facing[Z];\r\n\t\t\tm_facing[Z] = -sin_delta_angle * m_facing[X] + cos_delta_angle * m_facing[Z];\r\n\t\t\tm_facing[X] = adjusted_vel;\r\n\t\t\t\r\n\t\t\t// check for overturn\r\n\t\t\tif (left_turn != (-m_facing[Z] * m_control_direction[X] + m_facing[X] * m_control_direction[Z] < 0.0f))\r\n\t\t\t{\r\n\t\t\t\tm_facing = m_control_direction;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// no acceleration until we reach the desired orientation\r\n\t\t\tspecial_acceleration = true;\r\n\t\t\t\r\n\t\t\t// setup the event\r\n\t\t\tm_frame_event = left_turn ? CRCD(0xf28adbfc, \"RotateLeft\") : CRCD(0x912220f8, \"RotateRight\");\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (dot > -cosf(Mth::DegToRad(s_get_gunslinger_param(CRCD(0x2d571c0f, \"max_reverse_angle\")))))\r\n\t\t\t{\r\n\t\t\t\t// if the turn angle is soft\r\n\t\t\t\t\r\n\t\t\t\t// below a speed threshold, scale up the turn rate\r\n\t\t\t\tfloat turn_factor;\r\n\t\t\t\tif (horizontal_speed < s_get_gunslinger_param(CRCD(0x27815f69, \"max_pop_speed\")))\r\n\t\t\t\t{\r\n\t\t\t\t\t// quick turn\r\n\t\t\t\t\tturn_factor = Mth::Lerp(s_get_gunslinger_param(CRCD(0xb278405d, \"best_turn_factor\")), s_get_gunslinger_param(CRCD(0x6cb2e5de, \"worse_turn_factor\")), horizontal_speed / s_get_gunslinger_param(CRCD(0x27815f69, \"max_pop_speed\"))); \r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// slower turn\r\n\t\t\t\t\tturn_factor = s_get_gunslinger_param(CRCD(0x6cb2e5de, \"worse_turn_factor\"));\r\n\t\t\t\t}\r\n\t\t\t\tturn_factor *= m_control_magnitude;\r\n\t\t\t\t\r\n\t\t\t\t// exponentially approach the new facing\r\n\t\t\t\tfloat turn_ratio = turn_factor * m_frame_length;\r\n\t\t\t\tif (turn_ratio >= 1.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_facing = m_control_direction;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_facing = Mth::Lerp(m_facing, m_control_direction, turn_ratio);\r\n\t\t\t\t\tm_facing.Normalize();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// the turn angle is hard\r\n\t\t\t\t\r\n\t\t\t\tif (horizontal_speed > s_get_gunslinger_param(CRCD(0xf1e97e45, \"min_skid_speed\")))\r\n\t\t\t\t{\r\n\t\t\t\t\t// if moving fast enough to require a skidding stop\r\n\t\t\t\t\tspecial_acceleration = true;\r\n\t\t\t\t\thorizontal_speed -= s_get_gunslinger_param(CRCD(0x9661ed7, \"skid_accel\")) * m_frame_length;\r\n\t\t\t\t\thorizontal_speed = Mth::ClampMin(horizontal_speed, 0.0f);\r\n\t\t\t\t\tm_frame_event = CRCD(0x1d537eff, \"Skid\");\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// if max_rotate_in_place_speed is larger than min_skid_speed and max_reverse_angle points farther in reverse than\r\n\t\t\t\t\t// max_rotate_in_place_angle, as they should, then this code should never be run\r\n\t\t\t\t\tDbg_Message(\"Unexpected state in CWalkComponent::calculate_horizontal_speed_and_facing\");\r\n\t\t\t\t\t\r\n\t\t\t\t\t// to be safe, pop to the new facing\r\n\t\t\t\t\tm_facing = m_control_direction;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (special_acceleration) return;\r\n\t\r\n\t// store desired speed for animation speed scaling\r\n\tm_anim_effective_speed = desired_speed;\r\n\t\r\n\t// adjust desired speed for slope\r\n\tdesired_speed = adjust_desired_speed_for_slope(desired_speed);\r\n\t\r\n\t// linear acceleration; exponential deceleration\r\n\tif (horizontal_speed > desired_speed)\r\n\t{\r\n\t\thorizontal_speed = Mth::Lerp(horizontal_speed, desired_speed, s_get_gunslinger_param(CRCD(0xacfa4e0c, \"decel_factor\")) * m_frame_length);\r\n\t\t\r\n\t\tif (desired_speed == 0.0f)\r\n\t\t{\r\n\t\t\tif (horizontal_speed > s_get_gunslinger_param(CRCD(0x79d182ad, \"walk_speed\")))\r\n\t\t\t{\r\n\t\t\t\tm_frame_event = CRCD(0x1d537eff, \"Skid\");\r\n\t\t\t}\r\n\t\t\telse if (m_last_frame_event == CRCD(0x1d537eff, \"Skid\") && horizontal_speed > s_get_gunslinger_param(CRCD(0x311d02b2, \"stop_skidding_speed\")))\r\n\t\t\t{\r\n\t\t\t\tm_frame_event = CRCD(0x1d537eff, \"Skid\");\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (m_run_toggle)\r\n\t\t{\r\n\t\t\thorizontal_speed += s_get_gunslinger_param(CRCD(0x4f47c998, \"run_accel_rate\")) * m_frame_length;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\thorizontal_speed += s_get_gunslinger_param(CRCD(0x6590a49b, \"walk_accel_rate\")) * m_frame_length;\r\n\t\t}\r\n\t\tif (horizontal_speed > desired_speed)\r\n\t\t{\r\n\t\t\thorizontal_speed = desired_speed;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool  CWalkComponent::adjust_horizonal_vel_for_environment ( void )\r\n{\r\n\t// We send out feeler rays to find nearby walls.  We limit velocity to be flush with the first wall found.  If two or more non-parallel walls\r\n\t// are found, velocity is zeroed.\r\n\t\r\n\tfloat feeler_length = s_get_gunslinger_param(CRCD(0x99978d2b, \"feeler_length\"));\r\n\tfloat feeler_height = s_get_gunslinger_param(CRCD(0x6da7f696, \"feeler_height\"));\r\n\t\r\n\tCFeeler feeler;\r\n\t\r\n\tbool contact = false;\r\n\tfor (int n = 0; n < vNUM_FEELERS + 1; n++)\r\n\t{\r\n\t\t// setup the the feeler\r\n\t\t\r\n\t\tif (n == vNUM_FEELERS)\r\n\t\t{\r\n\t\t\t// final feeler is for air state only and is at the feet; solves situations in which the feet impact with vertical surfaces which the\r\n\t\t\t// wall feelers are too high to touch\r\n\t\t\tif (m_state != WALKING_AIR)\r\n\t\t\t{\r\n\t\t\t\tmp_contacts[vNUM_FEELERS].in_collision = false;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tfeeler.m_start = m_pos;\r\n\t\t\tfeeler.m_end = m_pos + m_horizontal_vel * m_frame_length;\r\n\t\t\tfeeler.m_end[Y] += m_vertical_vel * m_frame_length + 0.5f * -s_get_gunslinger_param(CRCD(0xa5e2da58, \"gravity\")) * Mth::Sqr(m_frame_length);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfeeler.m_start = m_pos;\r\n\t\t\tfeeler.m_start[Y] += feeler_height;\r\n\t\t\tfeeler.m_end = m_pos + feeler_length * calculate_feeler_offset_direction(n);\r\n\t\t\tfeeler.m_end[Y] += feeler_height;\r\n\t\t}\r\n\t\t\r\n\t\tmp_contacts[n].in_collision = feeler.GetCollision();\r\n\t\t\r\n\t\tif (!mp_contacts[n].in_collision)\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t{\r\n\t\t\t\tfeeler.DebugLine(0, 0, 255, 1);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tcontact = true;\r\n\t\t\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(255, 0, 0, 1);\r\n\t\t}\r\n\t\t#endif\r\n\r\n\t\t// grab the horizontal normal of the contacted wall\r\n\t\tmp_contacts[n].normal = feeler.GetNormal();\r\n\t\tmp_contacts[n].normal[Y] = 0.0f;\r\n\t\tmp_contacts[n].normal.Normalize();\r\n\t\t\r\n\t\t// if we're on the moving object, don't count its movement when doing collision detection, as the walker's velocity is already measured\r\n\t\t// relative to its movable contact's\r\n\t\tif (feeler.IsMovableCollision()\r\n\t\t\t&& (!mp_movable_contact_component->HaveContact() || mp_movable_contact_component->GetContact()->GetObject() != feeler.GetMovingObject()))\r\n\t\t{\r\n\t\t\tmp_contacts[n].movement = Mth::DotProduct(feeler.GetMovingObject()->GetVel(), mp_contacts[n].normal);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_contacts[n].movement = 0.0f;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// check for wall push\r\n\tif (m_state == WALKING_GROUND)\r\n\t{\r\n\t\tif (check_for_wall_push())\r\n\t\t{\r\n\t\t\t// if we're wall pushing, we may decide to switch states based on our environment\r\n\t\t\t\r\n\t\t\tif (Tmr::ElapsedTime(m_wall_push_test.test_start_time) > s_get_gunslinger_param(CRCD(0x928e6775, \"hop_delay\")))\r\n\t\t\t{\r\n\t\t\t\tif (maybe_climb_up_ladder() || /*maybe_hop_to_hang() ||*/ maybe_jump_low_barrier()) return false;\r\n\t\t\t}\r\n\t\t\telse if (Tmr::ElapsedTime(m_wall_push_test.test_start_time) > s_get_gunslinger_param(CRCD(0x38d36700, \"barrier_jump_delay\")))\r\n\t\t\t{\r\n\t\t\t\tif (maybe_climb_up_ladder() || maybe_jump_low_barrier()) return false;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if (mp_input_component->GetControlPad().m_R1.GetPressed() && !m_ignore_grab_button)\r\n\t\t{\r\n\t\t\tif (maybe_climb_up_ladder(true)) return false;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (!contact) return false;\r\n\t\r\n\t// push away from walls\r\n\tfor (int n = 0; n < vNUM_FEELERS + 1; n++)\r\n\t{\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\t                \r\n\t\tif (mp_contacts[n].feeler.GetDist() < s_get_param(CRCD(0xa20c43b7, \"push_feeler_length\")) / feeler_length)\r\n\t\t{\r\n\t\t\tm_pos += s_get_param(CRCD(0x4d16f37d, \"push_strength\")) * m_frame_length * mp_contacts[n].normal;\r\n\t\t}\r\n\t}\r\n\r\n\t// from here on we ignore collisions we're moving out of\r\n\tcontact = false;\r\n\tfor (int n = 0; n < vNUM_FEELERS + 1; n++)\r\n\t{\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\t\r\n\t\t// don't count collisions we're moving out of\r\n\t\tif (Mth::DotProduct(mp_contacts[n].normal, m_horizontal_vel) >= mp_contacts[n].movement)\r\n\t\t{\r\n\t\t\tmp_contacts[n].in_collision = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcontact = true;\r\n\t\t}\r\n\t}\r\n\tif (!contact) return false;\r\n\t\r\n\t// Now we calculate how our movement is effected by our collisions.  The movement must have a non-negative dot product with all collision normals.\r\n\t// The algorithm used should be valid for all convex environments.\r\n\t\r\n\t// if any of the colllision normals are more than right angles to one another, no movement is possible\r\n\t// NOTE: not valid with movable contacts; could cause jerky movement in corners where walls are movable\r\n\tfor (int n = 0; n < vNUM_FEELERS + 1; n++)\r\n\t{\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\tfor (int m = n + 1; m < vNUM_FEELERS + 1; m++)\r\n\t\t{\r\n\t\t\tif (!mp_contacts[m].in_collision) continue;\r\n\t\t\tif (Mth::DotProduct(mp_contacts[n].normal, mp_contacts[m].normal) <= 0.0f)\r\n\t\t\t{\r\n\t\t\t\tm_horizontal_vel.Set();\r\n\t\t\t\tm_anim_effective_speed = Mth::Min(s_get_gunslinger_param(CRCD(0xbd6a05d, \"min_anim_run_speed\")), m_anim_effective_speed);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// direction of proposed movement\r\n\tMth::Vector movement_direction = m_horizontal_vel;\r\n\tmovement_direction.Normalize();\r\n\t\r\n\tMth::Vector adjusted_vel = m_horizontal_vel;\r\n\t\r\n\t// loop over the contacts (from backward to forward)\r\n\tconst int contact_idxs[] = { 7, 4, 3, 5, 2, 6, 1, 0 };\r\n\tfor (int i = 0; i < vNUM_FEELERS + 1; i++)\r\n\t{\r\n\t\tint n = contact_idxs[i];\r\n\t\t\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\t\r\n\t\t// check to see if the movement still violates this constraint\r\n\t\tfloat normal_vel = Mth::DotProduct(adjusted_vel, mp_contacts[n].normal);\r\n\t\tif (normal_vel >= mp_contacts[n].movement) continue;\r\n\t\t\r\n\t\t// adjust the movement to the closest direction allowed by this contraint\r\n\t\tadjusted_vel -= (normal_vel - mp_contacts[n].movement) * mp_contacts[n].normal;\r\n\t\t\r\n\t\t// if the mvoement direction no longer points in the direction of the proposed movement, no movement occurs\r\n\t\tif (Mth::DotProduct(adjusted_vel, m_horizontal_vel) <= 0.0f)\r\n\t\t{\r\n\t\t\tm_horizontal_vel.Set();\r\n\t\t\tm_anim_effective_speed = Mth::Min(s_get_gunslinger_param(CRCD(0xbd6a05d, \"min_anim_run_speed\")), m_anim_effective_speed);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// insure that the adjusted velocity in the final direction is not larger than the projection of the initial velocity into that direction\r\n\tfloat adjusted_speed = adjusted_vel.Length();\r\n\tMth::Vector adjusted_vel_direction = adjusted_vel;\r\n\tadjusted_vel_direction *= 1.0f / adjusted_speed;\r\n\tfloat projected_vel = Mth::DotProduct(m_horizontal_vel, adjusted_vel_direction);\r\n\t\r\n\tif (adjusted_speed > projected_vel)\r\n\t{\r\n\t\tadjusted_vel = adjusted_vel_direction * projected_vel;\r\n\t}\r\n\t\r\n\t// only the velocity along the movement direction is retained\r\n\tm_horizontal_vel = adjusted_vel;\r\n\t\r\n\tfloat final_horiz_vel = m_horizontal_vel.Length();\r\n\tif (m_anim_effective_speed > s_get_gunslinger_param(CRCD(0xbd6a05d, \"min_anim_run_speed\")))\r\n\t{\r\n\t\tm_anim_effective_speed = final_horiz_vel;\r\n\t\tm_anim_effective_speed = Mth::Max(s_get_gunslinger_param(CRCD(0xbd6a05d, \"min_anim_run_speed\")), m_anim_effective_speed);\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::adjust_facing_for_adjusted_horizontal_vel (   )\r\n{\r\n\t// We adjust facing due to adjustment in horizontal velocity due to environment.  Basically, we want to object to turn to face the velocity\r\n\t// that the environment has forced upon it.\r\n\t\r\n\t// IDEA: shift to basing turn amount on angle difference and not speed\r\n\t\r\n\tfloat horizontal_speed = m_horizontal_vel.Length();\r\n\t\r\n\tif (horizontal_speed < s_get_gunslinger_param(CRCD(0x515a933, \"wall_turn_speed_threshold\"))) return;\r\n\t\r\n\t// the new facing is in the direction of our adjusted velocity\r\n\tMth::Vector new_facing = m_horizontal_vel;\r\n\tnew_facing.Normalize();\r\n\t\r\n\t// smoothly transition between no wall turning to full wall turning\r\n\tfloat turn_ratio;\r\n\tif (horizontal_speed > s_get_gunslinger_param(CRCD(0xe6c1cd0d, \"max_wall_turn_speed_threshold\")))\r\n\t{\r\n\t\tturn_ratio = s_get_gunslinger_param(CRCD(0x7a583b9b, \"wall_turn_factor\")) * m_frame_length;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tturn_ratio = Mth::LinearMap(\r\n\t\t\t0.0f,\r\n\t\t\ts_get_gunslinger_param(CRCD(0x7a583b9b, \"wall_turn_factor\")) * m_frame_length,\r\n\t\t\thorizontal_speed,\r\n\t\t\ts_get_gunslinger_param(CRCD(0x0515a933, \"wall_turn_speed_threshold\")),\r\n\t\t\ts_get_gunslinger_param(CRCD(0xe6c1cd0d, \"max_wall_turn_speed_threshold\"))\r\n\t\t);\r\n\t}\r\n\t\r\n\t// exponentially approach new facing\r\n\tif (turn_ratio >= 1.0f)\r\n\t{\r\n\t\tm_facing = new_facing;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_facing = Mth::Lerp(m_facing, new_facing, turn_ratio);\r\n\t\tm_facing.Normalize();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CWalkComponent::adjust_desired_speed_for_slope ( float desired_speed )\r\n{\r\n\t// Slow velocity up and down slopes.\r\n\t\r\n\t// skip if there is no appreciable slope\r\n\tif (m_ground_normal[Y] > 0.95f) return desired_speed;\r\n\t\r\n\t// skip if not running\r\n\tif (desired_speed <= s_get_gunslinger_param(CRCD(0x79d182ad, \"walk_speed\"))) return desired_speed;\r\n\t\r\n\t// calculate a horizontal vector up the slope\r\n\tMth::Vector up_slope = m_ground_normal;\r\n\tup_slope[Y] = 0.0f;\r\n\tup_slope.Normalize();\r\n\t\r\n\t// horizontal factor of velocity if the velocity were pointing along the slope (instead of along the horizontal)\r\n\tfloat movement_factor = m_ground_normal[Y];\r\n\t\r\n\t// factor of velocity pointing up the slope\r\n\tfloat dot = Mth::Abs(Mth::DotProduct(m_facing, up_slope));\r\n\t\r\n\t// scale the up-the-slope element of velocity based on the slope strength\r\n\treturn (1.0f - dot) * desired_speed + dot * movement_factor * desired_speed;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::respond_to_ground (   )\r\n{\r\n\t// Look for the ground below us.  If we find it, snap to it.  If not, go to air state.\r\n\t\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_start[Y] += s_get_gunslinger_param(CRCD(0xcee3a3e1, \"snap_up_height\"));\r\n\tfeeler.m_end = m_pos;\r\n\tfeeler.m_end[Y] -= s_get_gunslinger_param(CRCD(0xaf3e4251, \"snap_down_height\"));\r\n\t\r\n\tif (!feeler.GetCollision())\r\n\t{\r\n\t\t// no ground\r\n\t\t\r\n\t\tif (m_last_ground_feeler_valid)\r\n\t\t{\r\n\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_OFF_EDGE, m_last_ground_feeler);\r\n//\t\t\tif (should_bail_from_frame()) return;\r\n\t\t}\r\n\t\t\r\n\t\tif (mp_input_component->GetControlPad().m_triangle.GetPressed())\r\n\t\t{\r\n\t\t\t// need to give the player a change to rail before climbing down ladders and such\r\n\t\t\t\r\n\t\t\t// if we just climbed up to a rail and are immediately falling, we need some minute amount of movement in order to find a rail\r\n\t\t\tif (m_pos == m_frame_start_pos)\r\n\t\t\t{\r\n\t\t\t\tm_frame_start_pos[Y] += 0.001f;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (maybe_stick_to_rail()) return;\r\n\t\t}\r\n\t\t\r\n\t\tif (maybe_climb_down_ladder() || maybe_drop_to_hang()) return;\r\n\t\t\r\n\t\t// go to air state\r\n\t\tset_state(WALKING_AIR);\r\n\t\tm_primary_air_direction = m_facing;\r\n\t\tleave_movable_contact_for_air(m_horizontal_vel, m_vertical_vel);\r\n\t\tm_frame_event = CRCD(0xabf1f6ac, \"WalkOffEdge\");\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tfloat snap_distance = feeler.GetPoint()[Y] - m_pos[Y];\r\n\t\r\n\t// no not send event for very small snaps\r\n\tif (Mth::Abs(snap_distance) > s_get_gunslinger_param(CRCD(0xd3193d8e, \"max_unnoticed_ground_snap\")))\r\n\t{\r\n\t\tGetObject()->SelfEvent(snap_distance > 0.0f ? CRCD(0x93fcf3ed, \"SnapUpEdge\") : CRCD(0x56e21153, \"SnapDownEdge\"));\r\n\t}\r\n\t\r\n\t// snap position to the ground\r\n\tm_pos[Y] = feeler.GetPoint()[Y];\r\n\t\r\n\t// adjust stair float distance\r\n\tm_curb_float_height = Mth::ClampMin(m_curb_float_height - snap_distance, 0.0f);\r\n\t\r\n\t// see if we've changed sectors\r\n\tif (m_last_ground_feeler.GetSector() != feeler.GetSector())\r\n\t{\r\n\t\tif (m_last_ground_feeler_valid)\r\n\t\t{\r\n\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_OFF, m_last_ground_feeler);\r\n//\t\t\tif (should_bail_from_frame()) return;\r\n\t\t}\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_ONTO, feeler);\r\n//\t\tif (should_bail_from_frame()) return;\r\n\t}\r\n\t\r\n\t// stash the ground feeler so that we can trip the group's triggers at a later time\r\n\tm_last_ground_feeler = feeler;\r\n\tm_last_ground_feeler_valid = true;\r\n\t\r\n\t// set the ground normal for next frame's velocity slope adjustment\r\n\tm_ground_normal = feeler.GetNormal();\r\n\t\r\n\t// NOTE: need to repeat this code anywhere we enter the ground state\r\n\tmp_movable_contact_component->CheckForMovableContact(feeler);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::adjust_curb_float_height (   )\r\n{\r\n\t// adjust m_curb_float_height to smooth out moving up stairs\r\n\t\r\n\t// When facing a curb, we smoothly increase m_curb_float_height to the height of the curb.  When we snap up the curb, m_curb_float_height is then\r\n\t// reduced by an amount equal to the snap distance.\r\n\t// When we snap down a curb, m_curb_float_height is increased by the snap distance.  We then drop m_curb_float_height smoothly to zero.\r\n\t\r\n\t// determine appropriate direction to search for a curb\r\n\tMth::Vector feeler_direction = m_facing;\r\n\tfeeler_direction.ProjectToPlane(m_ground_normal);\r\n\tfeeler_direction[Y] = Mth::ClampMin(feeler_direction[Y], 0.0f);\r\n\tfeeler_direction.Normalize();\r\n\t\r\n\t// look for a curb\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_start[Y] += 0.5f;\r\n\tfeeler.m_end = m_pos + s_get_gunslinger_param(CRCD(0x11edcc52, \"curb_float_feeler_length\")) * feeler_direction;\r\n    feeler.m_end[Y] += 0.5f;\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(0, 255, 0, 1);\r\n\t}\r\n\t#endif\r\n\t\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t// grab the distance to the curb\r\n\t\tfloat distance_to_curb = feeler.GetDist();\r\n\t\t\r\n\t\t// look up from the curb to find the curb height\r\n\t\tfeeler.m_end = feeler.GetPoint() + 0.5f * feeler_direction;\r\n\t\tfeeler.m_start = feeler.m_end;\r\n\t\tfeeler.m_start[Y] = m_pos[Y] + s_get_gunslinger_param(CRCD(0xcee3a3e1, \"snap_up_height\"));\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(0, 255, 255, 1);\r\n\t\t}\r\n\t\t#endif\r\n\t\t\r\n\t\tif (feeler.GetCollision())\r\n\t\t{\r\n\t\t\t// calculate the m_curb_float_height we should have based on the curb height and distance\r\n\t\t\tfloat appropriate_curb_float_height = (1.0f - distance_to_curb) * (feeler.GetPoint()[Y] - m_pos[Y]);\r\n\t\t\t\r\n\t\t\tif (Mth::Abs(m_curb_float_height) < 0.01f && m_control_magnitude == 0.0f && m_horizontal_vel.LengthSqr() < Mth::Sqr(s_get_gunslinger_param(CRCD(0x227d72ee, \"min_curb_height_adjust_vel\"))))\r\n\t\t\t{\r\n\t\t\t\t// don't update the curb height if we're on the ground and standing still; this is mostly to prevent snapping up right after landing a jump\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// lerp to the appropriate height\r\n\t\t\t\tm_curb_float_height = Mth::Lerp(m_curb_float_height, appropriate_curb_float_height, s_get_gunslinger_param(CRCD(0x856a80d3, \"curb_float_lerp_up_rate\")) * m_frame_length);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tm_curb_float_height_adjusted = true;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::account_for_movable_contact (   )\r\n{\r\n\tif (!mp_movable_contact_component->UpdateContact(m_pos)) return;\r\n\t\r\n\tm_pos += mp_movable_contact_component->GetContact()->GetMovement();\r\n\t\r\n\tif (mp_movable_contact_component->GetContact()->IsRotated())\r\n\t{\r\n\t\tm_facing = mp_movable_contact_component->GetContact()->GetRotation().Rotate(m_facing);\r\n\t\tif (m_facing[Y] != 0.0f)\r\n\t\t{\r\n\t\t\tDUMPF(m_facing[Y]);\r\n\t\t\tm_facing[Y] = 0.0f;\r\n\t\t\tm_facing.Normalize();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::jump (   )\r\n{\r\n\t// switch to air state and give the object an upwards velocity\r\n\t\r\n\tfloat strength = 0.0f;\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase WALKING_GROUND:\r\n\t\tcase WALKING_AIR:\r\n\t\t\t// jump strength scales with the length the jump button has been held\r\n\t\t\tstrength = Mth::Lerp(\r\n\t\t\t\ts_get_param(CRCD(0x246d0bf3, \"min_jump_factor\")), \r\n\t\t\t\t1.0f,\r\n\t\t\t\tMth::ClampMax(mp_input_component->GetControlPad().m_x.GetPressedTime() / s_get_param(CRCD(0x12333ebd, \"hold_time_for_max_jump\")), 1.0f)\r\n\t\t\t);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase WALKING_HANG:\r\n\t\tcase WALKING_LADDER:\r\n\t\tcase WALKING_ANIMWAIT:\r\n\t\t\tstrength = s_get_param(CRCD(0xf2fa5845, \"hang_jump_factor\"));\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\t// if we're jumping from the ground, trip the ground's triggers\r\n\tif (m_state == WALKING_GROUND && m_last_ground_feeler_valid)\r\n\t{\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_JUMP_OFF, m_last_ground_feeler);\r\n\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t}\r\n\t\r\n\t// Called by script from outside of the component update, so m_vertical_vel is not used.\r\n\tGetObject()->GetVel()[Y] = strength * s_get_param(CRCD(0x63d62a21, \"jump_velocity\"));\r\n\t\r\n\t// jumps for ladders and hanging get a backwards velocity\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase WALKING_GROUND:\r\n\t\tcase WALKING_AIR:\r\n\t\t{\r\n//\t\t\textract_state_from_object();\r\n\t\r\n\t\t\tif (m_control_magnitude)\r\n\t\t\t{\r\n\t\t\t\tfloat min_launch_speed = calculate_desired_speed()\r\n\t\t\t\t\t* s_get_param(CRCD(0x839fe542, \"jump_horiz_speed\")) / get_run_speed();\r\n\t\t\t\t\r\n\t\t\t\tif (Mth::DotProduct(m_horizontal_vel, m_control_direction) > 0.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_horizontal_vel.ProjectToNormal(m_control_direction);\r\n\t\t\t\t\tif (m_horizontal_vel.Length() < min_launch_speed)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_horizontal_vel.Normalize(min_launch_speed);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_horizontal_vel = min_launch_speed * m_control_direction;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tm_primary_air_direction = m_control_direction;\r\n\t\t\t\tm_facing = m_control_direction;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_primary_air_direction = m_facing;\r\n\t\t\t}\r\n\t\t\t\r\n//\t\t\tadjust_jump_for_ceiling_obstructions();\r\n\t\t\t\r\n\t\t\t// setup primary air direction\r\n\t\t\tfloat length_sqr = m_horizontal_vel.LengthSqr();\r\n\t\t\tif (length_sqr > 0.01f)\r\n\t\t\t{\r\n\t\t\t\tm_primary_air_direction = m_horizontal_vel;\r\n\t\t\t\tm_primary_air_direction /= sqrtf(length_sqr);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_primary_air_direction = m_facing;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcopy_state_into_object();\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase WALKING_ANIMWAIT:\r\n\t\t\tm_false_wall.active = true;\r\n\t\t\tm_false_wall.distance = Mth::DotProduct(m_false_wall.normal, m_pos + m_critical_point_offset);\r\n\t\t\t\r\n\t\t\tGetObject()->GetVel()[X] = 0.0f;\r\n\t\t\tGetObject()->GetVel()[Z] = 0.0f;\r\n\t\t\tm_primary_air_direction = m_facing;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase WALKING_HANG:\r\n\t\t\tm_false_wall.active = true;\r\n\t\t\tm_false_wall.normal = m_facing;\r\n\t\t\tm_false_wall.distance = Mth::DotProduct(m_false_wall.normal, m_pos + m_critical_point_offset);\r\n\t\t\tm_false_wall.cancel_height = m_pos[Y] - m_vertical_hang_offset;\r\n\t\t\t\r\n\t\t\tGetObject()->GetVel()[X] = 0.0f;\r\n\t\t\tGetObject()->GetVel()[Z] = 0.0f;\r\n\t\t\tm_primary_air_direction = m_facing;\r\n\t\t\tbreak;\r\n\r\n\t\tcase WALKING_LADDER:\r\n\t\t\tGetObject()->GetVel()[X] = 0.0f;\r\n\t\t\tGetObject()->GetVel()[Z] = 0.0f;\r\n\t\t\tm_primary_air_direction = m_facing;\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\tleave_movable_contact_for_air(GetObject()->GetVel(), GetObject()->GetVel()[Y]);\r\n\t\r\n\tset_state(WALKING_AIR);\r\n\t\r\n\tGetObject()->BroadcastEvent(CRCD(0x8687163a, \"SkaterJump\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::go_in_air_state (   )\r\n{\r\n\tsetup_collision_cache();\r\n\t\r\n\t// default air event\r\n\tm_frame_event = CRCD(0x439f4704, \"Air\");\r\n\t\r\n\t// user control of horizontal velocity\r\n\tcontrol_horizontal_vel();\r\n\t\r\n\t// prevent movement into walls\r\n\tadjust_horizonal_vel_for_environment();\r\n//\tif (should_bail_from_frame()) return;\r\n\t\r\n\t// check for head bonking\r\n\tadjust_vertical_vel_for_ceiling();\r\n\t\r\n\t// apply movement and acceleration for this frame\r\n\tm_pos += m_horizontal_vel * m_frame_length;\r\n\tm_pos[Y] += m_vertical_vel * m_frame_length + 0.5f * -s_get_gunslinger_param(CRCD(0xa5e2da58, \"gravity\")) * Mth::Sqr(m_frame_length);\r\n\t\r\n\tm_vertical_vel += -s_get_gunslinger_param(CRCD(0xa5e2da58, \"gravity\")) * m_frame_length;\r\n\t\r\n\t// see if we've landed yet\r\n\tcheck_for_landing(m_frame_start_pos, m_pos);\r\n\tif (m_state != WALKING_AIR /*|| should_bail_from_frame()*/) return;\r\n\t\r\n\t// maybe grab a rail; delay regrabbing of hang rails\r\n\tif (mp_input_component->GetControlPad().m_R1.GetPressed() && !m_ignore_grab_button\r\n\t\t&& ((m_previous_state != WALKING_HANG && m_previous_state != WALKING_LADDER) || Tmr::ElapsedTime(m_state_timestamp) > s_get_gunslinger_param(CRCD(0xe6e0c0a4, \"rehang_delay\"))))\r\n\t{\r\n\t\tif (m_previous_state == WALKING_LADDER)\r\n\t\t{\r\n\t\t\t// can't regrab ladders\r\n\t\t\tif (maybe_grab_to_hang(m_frame_start_pos, m_pos))\r\n\t\t\t{\r\n\t\t\t\tCFeeler::sClearDefaultCache();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (maybe_grab_to_hang(m_frame_start_pos, m_pos) || maybe_grab_to_ladder(m_frame_start_pos, m_pos))\r\n\t\t\t{\r\n\t\t\t\tCFeeler::sClearDefaultCache();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (mp_input_component->GetControlPad().m_triangle.GetPressed())\r\n\t{\r\n\t\tif (maybe_stick_to_rail())\r\n\t\t{\r\n\t\t\tCFeeler::sClearDefaultCache();\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// insure that we do not slip through the cracks in the collision geometry which are a side-effect of moving collidable objects\r\n\tMth::Vector previous_pos = m_pos;\r\n\tif (CCompositeObject* p_inside_object = mp_movable_contact_component->CheckInsideObjects(m_pos, m_frame_start_pos))\r\n\t{\r\n\t\tMESSAGE(\"WALKING_AIR, within moving object\");\r\n\t\t\r\n\t\tm_horizontal_vel.Set();\r\n\t\tm_vertical_vel = 0.0f;\r\n\t\tcheck_for_landing(m_pos, previous_pos);\r\n\t}\r\n\t\r\n\tCFeeler::sClearDefaultCache();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::control_horizontal_vel (   )\r\n{\r\n\t// We allow user control over the object's in air velocity.  The algorithm is complicated by the fact that the forward velocity of the jump needs\r\n\t// to be accounted for when allowing for velocity adjustment.  It is assumed that the jump direction is the same as the facing.\r\n\t\r\n\t// remove uncontrollable velocity term\r\n\tm_horizontal_vel -= m_uncontrollable_air_horizontal_vel;\r\n\t\r\n\t// forced run still works in the air\r\n\tadjust_control_for_forced_run();\r\n\t\r\n\t// adjust speed by the script set drag factor\r\n\tfloat adjust_magnitude = m_control_magnitude;\r\n\t\r\n\t// adjust velocity perpendicular to jump direction\r\n\t\r\n\t// direction perpendicular to jump direction\r\n\tMth::Vector perp_direction(-m_primary_air_direction[Z], 0.0f, m_primary_air_direction[X]);\r\n\t\r\n\t// desired perpendicular velocity\r\n\tfloat perp_desired_vel = s_get_gunslinger_param(CRCD(0x896c8888, \"jump_adjust_speed\")) * adjust_magnitude * Mth::DotProduct(m_control_direction, perp_direction);\r\n\t\r\n\t// current perpendicular velocity\r\n\tfloat perp_vel = Mth::DotProduct(m_horizontal_vel, perp_direction);\r\n\t\r\n\t// exponentially approach desired velocity\r\n\tperp_vel = Mth::Lerp(perp_vel, perp_desired_vel, s_get_gunslinger_param(CRCD(0xf085443b, \"jump_accel_factor\")) * m_frame_length);\r\n\t\t\r\n\t// adjust velocity parallel to jump direction\r\n\t\r\n\t// desired parallel velocity\r\n\tfloat para_desired_vel = s_get_gunslinger_param(CRCD(0x896c8888, \"jump_adjust_speed\")) * adjust_magnitude * Mth::DotProduct(m_control_direction, m_primary_air_direction);\r\n\t\r\n\t// current parallel velocity\r\n\tfloat para_vel = Mth::DotProduct(m_horizontal_vel, m_primary_air_direction);\r\n\t\r\n    // if desired velocity if forward and forward velocity already exceeds adjustment velocity\r\n\tif (para_desired_vel >= 0.0f && para_vel > para_desired_vel)\r\n\t{\r\n\t\t// do nothing; don't slow down the jump\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// adjust desired velocity to center around current velocity to insure that our in air stopping ability is not too amazing\r\n\t\tif (para_desired_vel < 0.0f && para_vel > 0.0f)\r\n\t\t{\r\n\t\t\tpara_desired_vel += para_vel;\r\n\t\t}\r\n\t\t\r\n\t\t// expondentially approach desired velocity\r\n\t\tpara_vel = Mth::Lerp(para_vel, para_desired_vel, s_get_gunslinger_param(CRCD(0xf085443b, \"jump_accel_factor\")) * m_frame_length);\r\n\t}\r\n\t\t\r\n\t// rebuild horizontal velocity from parallel and perpendicular components\r\n\tm_horizontal_vel = para_vel * m_primary_air_direction + perp_vel * perp_direction;\r\n\t\r\n\t// reinstitute uncontrollable velocity term\r\n\tm_horizontal_vel += m_uncontrollable_air_horizontal_vel;\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::adjust_vertical_vel_for_ceiling (   )\r\n{\r\n\t// If we hit our head, zero vertical velocity\r\n\t\r\n\t// only worry about the ceiling if we're moving upwards\r\n\tif (m_vertical_vel <= 0.0f) return;\r\n\t\r\n\t// look for a collision up through the body to the head\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_end = m_pos;\r\n\tfeeler.m_end[Y] += s_get_gunslinger_param(CRCD(0x9ea1974a, \"walker_height\"));\r\n\tif (!feeler.GetCollision()) return;\r\n\t\r\n\t// zero upward velocity\r\n\tm_vertical_vel = 0.0f;\r\n\t\r\n\tGetObject()->SelfEvent(CRCD(0x6e84acf3, \"HitCeiling\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::check_for_landing ( const Mth::Vector& previous_pos, const Mth::Vector& final_pos )\r\n{\r\n\t// See if our feet have passed through geometry.  If so, snap to it and go to ground state.\r\n\t\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = previous_pos;\r\n\tfeeler.m_end = final_pos;\r\n\tif (!feeler.GetCollision()) return;\r\n\t\r\n\t// snap to the collision point\r\n\tm_pos = feeler.GetPoint();\r\n\t\r\n\t// zero vertical velocity\r\n\tm_vertical_vel = 0.0f;\r\n\t\r\n\t// change to ground state\r\n\tset_state(WALKING_GROUND);\r\n\t\r\n\t// stash the feeler\r\n\tm_last_ground_feeler = feeler;\r\n\tm_last_ground_feeler_valid = true;\r\n\t\r\n\t// trip any land trigger\r\n\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_LAND_ON, m_last_ground_feeler);\r\n//\tif (should_bail_from_frame()) return;\r\n\t\r\n\t// setup our ground normal for next frames velocity slope adjustment\r\n\tm_ground_normal = feeler.GetNormal();\r\n\t\r\n\t// check for a moving contact\r\n\tmp_movable_contact_component->CheckForMovableContact(feeler);\r\n\tif (mp_movable_contact_component->HaveContact())\r\n\t{\r\n\t\tm_horizontal_vel -= mp_movable_contact_component->GetContact()->GetObject()->GetVel();\r\n\t\tm_horizontal_vel[Y] = 0.0f;\r\n\t}\r\n\t\r\n\t// retain only that velocity which is parallel to our facing and forward\r\n\tif (Mth::DotProduct(m_horizontal_vel, m_facing) > 0.0f)\r\n\t{\r\n\t\tm_horizontal_vel.ProjectToNormal(m_facing);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_horizontal_vel.Set();\r\n\t}\r\n\t\r\n\t// clear any jump requests\r\n\tmp_input_component->GetControlPad().m_x.ClearRelease();\r\n\t\r\n\tm_frame_event = CRCD(0x57ff2a27, \"Land\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::uber_frig (   )\r\n{\r\n\t// insure that we don't fall to the center of the earth, even if there are holes in the geometry; also, do lighting since we've got the feeler anyway\r\n\t\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_start[Y] += 1.0f;\r\n\tfeeler.m_end = m_pos;\r\n\tfeeler.m_end[Y] -= FEET(400);\r\n\t\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tmp_model_component->ApplyLightingFromCollision(feeler);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tMESSAGE(\"applying uber frig\");\r\n\t\r\n\t// teleport us back to our position at the frame's start; not pretty, but this isn't supposed to be\r\n\tm_pos = m_frame_start_pos;\r\n\t\r\n\t// zero our velocity too\r\n\tm_horizontal_vel.Set();\r\n\tm_vertical_vel = 0.0f;\r\n\t\r\n\t// set our state to ground\r\n\tset_state(WALKING_GROUND);\r\n\t\t\t  \t\r\n\tm_last_ground_feeler_valid = false;\r\n\t\r\n\tm_ground_normal.Set(0.0f, 1.0f, 0.0f);\r\n\r\n\t// reset our script state\r\n\tm_frame_event = CRCD(0x57ff2a27, \"Land\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::lerp_upright (   )\t\t\t\t\t\t\t\t\t\t \r\n{\r\n    if (m_upward[Y] == 1.0f) return;\r\n\t\r\n\tif (m_upward[Y] > 0.999f)\r\n\t{\r\n\t\tm_upward.Set(0.0f, 1.0f, 0.0f);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tm_upward = Mth::Lerp(m_upward, Mth::Vector(0.0f, 1.0f, 0.0f), s_get_gunslinger_param(CRCD(0xf22c135, \"lerp_upright_rate\")) * Tmr::FrameLength());\r\n\tm_upward.Normalize();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::check_for_wall_push (   )\r\n{\r\n\t// ensure we have a forward contact\r\n\tif (!mp_contacts[0].in_collision && !mp_contacts[1].in_collision && !mp_contacts[vNUM_FEELERS - 1].in_collision)\r\n\t{\r\n\t\treturn m_wall_push_test.active = false;\r\n\t}\r\n\t\r\n\t// ensure that control is maxed out\r\n\tif (!m_control_pegged)\r\n\t{\r\n\t\treturn m_wall_push_test.active = false;\r\n\t}\r\n\t\r\n\tif (!m_wall_push_test.active)\r\n\t{\r\n\t\t// if we're not testing, simply start the test\r\n\t\tm_wall_push_test.test_start_time = Tmr::GetTime();\r\n\t\tm_wall_push_test.active = true;\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::maybe_jump_low_barrier (   )\r\n{\r\n\t// For each forward contact in collision, we check to see if any lacks a collision at the maximum jump height.  For any that do, we find the first height\r\n\t// at which they are in contact.  The lowest such height is used at the target jump height.\r\n\t\r\n\tconst int p_forward_contact_idxs[] = { 0, 1, vNUM_FEELERS - 1 };\r\n\t\r\n\t// we use the lowest hang height as the maximum autojump barrier height\r\n\tfloat top_feeler_height = s_get_gunslinger_param(CRCD(0x2c942693, \"lowest_hang_height\"));\r\n\tfloat feeler_length = 2.0f * s_get_gunslinger_param(CRCD(0x99978d2b, \"feeler_length\"));\r\n\tfloat height_increment = (top_feeler_height - s_get_gunslinger_param(CRCD(0x6da7f696, \"feeler_height\"))) / vNUM_BARRIER_HEIGHT_FEELERS;\r\n\t\r\n\tCFeeler feeler;\r\n\t\r\n\t// setup collision cache\r\n\tMth::CBBox bbox(\r\n\t\tm_pos - Mth::Vector(feeler_length + 1.0f, 0.0f, feeler_length + 1.0f),\r\n\t\tm_pos + Mth::Vector(feeler_length + 1.0f, top_feeler_height + 1.0f, feeler_length + 1.0f)\r\n\t);\r\n\tNx::CCollCache* p_coll_cache = Nx::CCollCacheManager::sCreateCollCache();\r\n\tp_coll_cache->Update(bbox);\r\n\tfeeler.SetCache(p_coll_cache);\r\n\t\r\n\t// loop over forward collisions and check to see if the barrier in each of their directions is jumpable\r\n\tbool jumpable = false;\r\n\tfor (int i = 0; i < 3; i++)\r\n\t{\r\n\t\tint n = p_forward_contact_idxs[i];\r\n\t\t\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\t\r\n\t\t// first check to see if the collision normal is not too transverse to the control direction, making a autojump unlikely to succeed\r\n\t\tif (Mth::DotProduct(mp_contacts[n].normal, m_control_direction) > -cosf(Mth::DegToRad(s_get_gunslinger_param(CRCD(0x78e6a5ec, \"barrier_jump_max_angle\")))))\r\n\t\t{\r\n\t\t\tmp_contacts[n].jumpable = false;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tfeeler.m_start = m_pos;\r\n\t\tfeeler.m_start[Y] += top_feeler_height;\r\n\t\tfeeler.m_end = feeler.m_start + feeler_length * calculate_feeler_offset_direction(n);\r\n\t\t\r\n\t\tmp_contacts[n].jumpable = !feeler.GetCollision();\r\n\t\t\r\n        if (mp_contacts[n].jumpable)\r\n\t\t{\r\n\t\t\tjumpable = true;\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t{\r\n\t\t\t\tfeeler.DebugLine(0, 0, 255, 0);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t{\r\n\t\t\t\tfeeler.DebugLine(255, 0, 0, 0);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t}\r\n\t}\r\n\t\r\n\t// if the barrier is not jumpable\r\n\tif (!jumpable)\r\n\t{\r\n\t\t// no autojump\r\n\t\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// loop over the jumpable collision directions\r\n\tfloat lowest_height = m_pos[Y] + top_feeler_height;\r\n\tfor (int i = 0; i < 3; i++)\r\n\t{\r\n\t\tint n = p_forward_contact_idxs[i];\r\n\t\t\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\tif (!mp_contacts[n].jumpable) continue;\r\n\t\t\r\n\t\tfeeler.m_start = m_pos;\r\n\t\tfeeler.m_start[Y] += top_feeler_height;\r\n\t\tfeeler.m_end = feeler.m_start + feeler_length * calculate_feeler_offset_direction(n);\r\n\t\t\r\n\t\t// look for the barrier height\r\n\t\tfor (int h = vNUM_BARRIER_HEIGHT_FEELERS - 1; h--; )\r\n\t\t{\r\n\t\t\tfeeler.m_start[Y] -= height_increment;\r\n\t\t\tfeeler.m_end[Y] -= height_increment;\r\n\t\t\tif (feeler.GetCollision())\r\n\t\t\t{\r\n\t\t\t\t#ifdef __USER_DAN__\r\n\t\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t\t{\r\n\t\t\t\t\tfeeler.DebugLine(255, 0, 0, 0);\r\n\t\t\t\t}\r\n\t\t\t\t#endif\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t#ifdef __USER_DAN__\r\n\t\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t\t{\r\n\t\t\t\t\tfeeler.DebugLine(0, 255, 0, 0);\r\n\t\t\t\t}\r\n\t\t\t\t#endif\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// find the lowest barrier of the jumpable directions\r\n\t\tif (lowest_height > feeler.m_start[Y])\r\n\t\t{\r\n\t\t\tlowest_height = feeler.m_start[Y];\r\n\t\t}\r\n\t}\r\n\t\r\n\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\r\n\t// caluclate the velocity required to clear the barrier\r\n\tfloat jump_height = lowest_height + height_increment + s_get_gunslinger_param(CRCD(0x72660978, \"barrier_jump_min_clearance\")) - m_pos[Y];\r\n\tfloat required_vertical_velocity = sqrtf(2.0f * s_get_gunslinger_param(CRCD(0xa5e2da58, \"gravity\")) * jump_height);\r\n\t\r\n\t// setup the new walking state\r\n\t\r\n\tm_vertical_vel = required_vertical_velocity;\r\n\t\r\n\tset_state(WALKING_AIR);\r\n\t\r\n\tm_primary_air_direction = m_facing;\r\n\tleave_movable_contact_for_air(m_horizontal_vel, m_vertical_vel);\r\n\t\r\n\tm_frame_event = CRCD(0x584cf9e9, \"Jump\");\r\n\t\r\n\t\r\n\t// stop late jumps after an autojump\r\n\tGetObject()->RemoveEventHandler(CRCD(0x6b9ca247, \"JumpRequested\"));\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::leave_movable_contact_for_air ( Mth::Vector& horizontal_vel, float& vertical_vel )\r\n{\r\n\t// use movement from the latest movable contact update call\r\n\t\r\n\tif (mp_movable_contact_component->HaveContact())\r\n\t{\r\n\t\t// keep track of the horizontal velocity due to our old contact\r\n\t\tm_uncontrollable_air_horizontal_vel = mp_movable_contact_component->GetContact()->GetObject()->GetVel();\r\n\r\n\t\tif (Mth::DotProduct(m_uncontrollable_air_horizontal_vel, horizontal_vel) > 0.0f)\r\n\t\t{\r\n\t\t\t// extra kicker; dangerous as there's no collision detection; without this slight extra movement, when we walk off the front of a movable object,\r\n\t\t\t// the object will move back under us before our next frame, and we will clip its edge and land on it\r\n\t\t\tm_pos += m_uncontrollable_air_horizontal_vel * m_frame_length;\r\n\t\t}\r\n\t\t\r\n\t\t// add movable contact's velocity into our launch velocity\r\n\t\tvertical_vel += m_uncontrollable_air_horizontal_vel[Y];\r\n\t\tm_uncontrollable_air_horizontal_vel[Y] = 0.0f;\r\n\t\thorizontal_vel += m_uncontrollable_air_horizontal_vel;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_uncontrollable_air_horizontal_vel.Set();\r\n\t}\r\n\t\r\n\tmp_movable_contact_component->LoseAnyContact();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::calculate_anim_wait_facing_drift_parameters ( const Mth::Vector& goal_facing )\r\n{\r\n\tfloat initial_angle = atan2f(m_facing[X], m_facing[Z]);\r\n\tfloat goal_angle = atan2f(goal_facing[X], goal_facing[Z]);\r\n\t\r\n\tm_drift_angle = goal_angle - initial_angle;\r\n\tif (Mth::Abs(m_drift_angle) > Mth::PI)\r\n\t{\r\n\t\tm_drift_angle -= Mth::Sgn(m_drift_angle) * (2.0f * Mth::PI);\r\n\t}\r\n\t\r\n\tm_drift_goal_facing = goal_facing;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::go_anim_wait_state (   )\r\n{\r\n\tif (mp_movable_contact_component->UpdateContact(m_pos))\r\n\t{\r\n\t\tm_offset_due_to_movable_contact += mp_movable_contact_component->GetContact()->GetMovement();\r\n\t\tif (mp_movable_contact_component->GetContact()->IsRotated())\r\n\t\t{\r\n\t\t\tm_drift_goal_facing = mp_movable_contact_component->GetContact()->GetRotation().Rotate(m_drift_goal_facing);\r\n\t\t\tif (m_drift_goal_facing[Y] != 0.0f)\r\n\t\t\t{\r\n\t\t\t\tm_drift_goal_facing[Y] = 0.0f;\r\n\t\t\t\tm_drift_goal_facing.Normalize();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t}\r\n\t}\r\n\t\r\n\tfloat start, current, end;\r\n\tmp_animation_component->GetPrimaryAnimTimes(&start, &current, &end);\r\n    float animation_completion_factor = Mth::LinearMap(0.0f, 1.0f, current, start, end);\r\n\t\r\n\t// smoothly drift the position\r\n\tm_pos = m_offset_due_to_movable_contact + Mth::Lerp(m_anim_wait_initial_pos, m_anim_wait_goal_pos, animation_completion_factor);\r\n\t\r\n\tfloat angle = Mth::Lerp(-m_drift_angle, 0.0f, animation_completion_factor);\r\n\tm_facing = m_drift_goal_facing;\r\n\tm_facing.RotateY(angle);\r\n\t\r\n\tm_frame_event = CRCD(0x4fe6069c, \"AnimWait\");\r\n}\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::anim_wait_complete (   )\r\n{\r\n\tGetObject()->SetPos(m_anim_wait_goal_pos + m_offset_due_to_movable_contact);\r\n    \r\n    Mth::Matrix matrix;\r\n    matrix[Z] = m_drift_goal_facing;\r\n    matrix[Y].Set(0.0f, 1.0f, 0.0f);\r\n    matrix[X].Set(m_drift_goal_facing[Z], 0.0f, -m_drift_goal_facing[X]);\r\n\tGetObject()->SetMatrix(matrix);\r\n\t\r\n    if (mp_anim_wait_complete_callback)\r\n    {\r\n        (this->*mp_anim_wait_complete_callback)();\r\n    }\r\n}\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::maybe_stick_to_rail (   )\r\n{\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n\t\r\nvoid CWalkComponent::setup_collision_cache (   )\r\n{\r\n\tfloat horizontal_reach = 1.0f + s_get_gunslinger_param(CRCD(0x99978d2b, \"feeler_length\"));\r\n\tfloat vertical_height = 1.0f + s_get_gunslinger_param(CRCD(0x9ea1974a, \"walker_height\"));;\r\n\tfloat vertical_depth = 1.0f + s_get_gunslinger_param(CRCD(0xaf3e4251, \"snap_down_height\"));\r\n\t\r\n\tMth::CBBox bbox(\r\n\t\tGetObject()->GetPos() - Mth::Vector(horizontal_reach, vertical_depth, horizontal_reach, 0.0f),\r\n\t\tGetObject()->GetPos() + Mth::Vector(horizontal_reach, vertical_height, horizontal_reach, 0.0f)\r\n\t);\r\n\t\r\n\tmp_collision_cache->Update(bbox);\r\n\tCFeeler::sSetDefaultCache(mp_collision_cache);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::copy_state_into_object (   )\r\n{\r\n\t// build the object's matrix based on our facing\r\n\tMth::Matrix matrix;\r\n\t\r\n\t// basically, rotate Z upward to perpendicular with m_upward\r\n\tmatrix[X] = Mth::CrossProduct(m_upward, m_facing);\r\n\tmatrix[X].Normalize();\r\n\tmatrix[Y] = m_upward;\r\n\tmatrix[Z] = Mth::CrossProduct(matrix[X], matrix[Y]);\r\n\tmatrix[W].Set( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\t\r\n\tGetObject()->SetPos( m_pos );\r\n\tGetObject()->SetMatrix( matrix );\r\n\tGetObject()->SetDisplayMatrix( matrix );\r\n\t\r\n\t// construct the object's velocity\r\n\tGetObject()->SetVel(m_horizontal_vel);\r\n\tGetObject()->GetVel()[Y] = m_vertical_vel;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::get_controller_input (   )\r\n{\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\r\n\tDbg_Assert(mp_camera);\r\n\t\r\n\t// rotate controller direction into camera's frame\r\n\t\r\n\tMth::Vector camera_forward = -mp_camera->m_matrix[Z];\r\n\tcamera_forward[Y] = 0.0f;\r\n\tcamera_forward.Normalize();\r\n\t\r\n\t// allow a tolerance range for pressing directly forward\r\n\tfloat angle = control_pad.m_leftAngle;\r\n\tif (Mth::Abs(angle) < Mth::DegToRad(s_get_gunslinger_param(CRCD(0x4676a268, \"forward_tolerance\"))))\r\n\t{\r\n\t\tangle = 0.0f;\r\n\t}\r\n\t\r\n\tfloat sin_angle = sinf(angle);\r\n\tfloat cos_angle = cosf(angle);\r\n\tm_control_direction[X] = cos_angle * camera_forward[X] - sin_angle * camera_forward[Z];\r\n\tm_control_direction[Z] = sin_angle * camera_forward[X] + cos_angle * camera_forward[Z];\r\n\t\r\n\t// different control schemes for analog stick and d-pad\r\n#\tif 0\r\n\tif (control_pad.m_leftX == 0.0f && control_pad.m_leftY == 0.0f)\r\n\t{\r\n\t\t// d-pad control\r\n\t\tif (control_pad.m_leftLength == 0.0f)\r\n\t\t{\r\n\t\t\tm_control_magnitude = 0.0f;\r\n\t\t\tm_control_pegged = false;\r\n\t\t\t\r\n\t\t\t// don't reset dpad in the air\r\n\t\t\tif (m_state != WALKING_AIR)\r\n\t\t\t{\r\n\t\t\t\tm_dpad_used_last_frame = false;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (!m_dpad_used_last_frame)\r\n\t\t\t{\r\n\t\t\t\tm_dpad_use_time_stamp = Tmr::GetTime();\r\n\t\t\t}\r\n\t\t\tm_dpad_used_last_frame = true;\r\n\t\t\t\r\n\t\t\tif (m_state == WALKING_GROUND)\r\n\t\t\t{\r\n\t\t\t\t// slowly ramp up to a full run\r\n\t\t\t\t\r\n\t\t\t\tTmr::Time elapsed_time = Tmr::ElapsedTime(m_dpad_use_time_stamp);\r\n\t\t\t\t\r\n\t\t\t\tTmr::Time full_run_dpad_delay = static_cast< Tmr::Time >(s_get_gunslinger_param(CRCD(0x1832588c, \"full_run_dpad_delay\")));\r\n\t\t\t\tTmr::Time start_run_dpad_delay = static_cast< Tmr::Time >(s_get_gunslinger_param(CRCD(0x2c386a43, \"start_run_dpad_delay\")));\r\n\t\t\t\t\r\n\t\t\t\tif (elapsed_time < start_run_dpad_delay)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_control_magnitude = s_get_gunslinger_param(CRCD(0xc1528f7f, \"walk_point\"));\r\n\t\t\t\t}\r\n\t\t\t\telse if (elapsed_time < full_run_dpad_delay)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_control_magnitude = Mth::SmoothMap(\r\n\t\t\t\t\t\ts_get_gunslinger_param(CRCD(0xc1528f7f, \"walk_point\")),\r\n\t\t\t\t\t\t1.0f,\r\n\t\t\t\t\t\telapsed_time,\r\n\t\t\t\t\t\tstart_run_dpad_delay,\r\n\t\t\t\t\t\tfull_run_dpad_delay\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_control_magnitude = 1.0f;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_control_magnitude = 1.0f;\r\n\t\t\t}\r\n            m_control_pegged = true;\r\n\t\t}\r\n        \r\n\t\t// damp dpad control directions towards forward when running\r\n        if (m_state == WALKING_GROUND && Mth::Abs(angle) < Mth::DegToRad(90.0f + 5.0f) && (forced_run() || m_control_magnitude > s_get_gunslinger_param(CRCD(0xc1528f7f, \"walk_point\"))))\r\n        {\r\n\t\t\tif (forced_run() || m_control_magnitude == 1.0f)\r\n\t\t\t{\r\n\t\t\t\tm_control_direction += s_get_gunslinger_param(CRCD(0x3c581621, \"dpad_control_damping_factor\")) * camera_forward;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// smoothly interpolate between damping and no damping\r\n\t\t\t\tm_control_direction += Mth::SmoothMap(0.0f, s_get_gunslinger_param(CRCD(0x3c581621, \"dpad_control_damping_factor\")), m_control_magnitude, s_get_gunslinger_param(CRCD(0xc1528f7f, \"walk_point\")), 1.0f)\r\n\t\t\t\t\t* camera_forward;\r\n\t\t\t}\r\n\t\t\tm_control_direction.Normalize();\r\n        }\r\n\t}\r\n\telse\r\n#\tendif\r\n\t{\r\n\t\t// analog stick control\r\n\t\tm_control_magnitude = control_pad.GetScaledLeftAnalogStickMagnitude() / 0.85f;\r\n\t\tif (m_control_magnitude >= 1.0f)\r\n\t\t{\r\n\t\t\tm_control_magnitude = 1.0f;\r\n\t\t\tm_control_pegged = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_control_pegged = false;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// during a forward control lock, ignore all input not in the forward direction\r\n\tif (m_state == WALKING_GROUND && m_forward_control_lock)\r\n\t{\r\n\t\tm_control_magnitude = Mth::ClampMin(m_control_magnitude * Mth::DotProduct(m_control_direction, m_facing), 0.0f);\r\n\t\tm_control_direction = m_facing;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::adjust_control_for_forced_run (   )\r\n{\r\n\tif (!forced_run()) return;\r\n\t\r\n\t// if no direction is pressed\r\n\tif (m_control_magnitude == 0.0f)\r\n\t{\r\n\t\t// run in the direction of our current facing\r\n\t\tm_control_direction = m_facing;\r\n\t}\r\n\r\n\t// run full speed\r\n\tm_control_magnitude = 1.0f;\r\n\tm_control_pegged = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CWalkComponent::calculate_desired_speed (   )\r\n{\r\n\t// forced run\r\n\tadjust_control_for_forced_run();\r\n\t\r\n\tif (m_control_magnitude == 0.0f) return 0.0f;\r\n\t\r\n\tfloat walk_point = s_get_gunslinger_param(CRCD(0xc1528f7f, \"walk_point\"));\r\n\tif (m_control_magnitude <= walk_point)\r\n\t{\r\n\t\tm_run_toggle = false;\r\n\t\treturn Mth::LinearMap(0.0f, s_get_gunslinger_param(CRCD(0x79d182ad, \"walk_speed\")), m_control_magnitude, 0.3f, walk_point);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_run_toggle = true;\r\n\t\treturn Mth::LinearMap(s_get_gunslinger_param(CRCD(0x79d182ad, \"walk_speed\")), s_get_gunslinger_param(CRCD(0xcc461b87, \"run_speed\")), m_control_magnitude, walk_point, 1.0f);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CWalkComponent::calculate_feeler_offset_direction ( int contact )\r\n{\r\n\tfloat angle = contact * (2.0f * Mth::PI / vNUM_FEELERS);\r\n\tfloat cos_angle = cosf(angle);\r\n\tfloat sin_angle = sinf(angle);\r\n\r\n\tMth::Vector end_offset_direction;\r\n\tend_offset_direction[X] = cos_angle * m_facing[X] - sin_angle * m_facing[Z];\r\n\tend_offset_direction[Y] = 0.0f;\r\n\tend_offset_direction[Z] = sin_angle * m_facing[X] + cos_angle * m_facing[Z];\r\n\tend_offset_direction[W] = 1.0f;\r\n\t\r\n\treturn end_offset_direction;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::determine_stand_pos ( const Mth::Vector& proposed_stand_pos, Mth::Vector& stand_pos, CFeeler& feeler )\r\n{\r\n\t// upward offset of standing position at maximum standable slope\r\n\tfloat max_height_adjustment = s_get_gunslinger_param(CRCD(0x6da7f696, \"feeler_height\")) / s_get_gunslinger_param(CRCD(0xa20c43b7, \"push_feeler_length\")) * s_get_gunslinger_param(CRCD(0x21dfbe77, \"pull_up_offset_forward\"));\r\n\t\r\n\tfeeler.m_start = proposed_stand_pos;\r\n\tfeeler.m_start[Y] += max_height_adjustment;\r\n\tfeeler.m_end = proposed_stand_pos;\r\n\tfeeler.m_end[Y] -= max_height_adjustment;\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(255, 255, 0, 0);\r\n\t}\r\n\t#endif\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tstand_pos = feeler.GetPoint();\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tstand_pos = proposed_stand_pos;\r\n\treturn false;\r\n}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gel/Components/HorseCameraComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       HorseCameraComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  2/10/3\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n\t\t\t\t\t\t\t\t\t \r\n#include <gel/components/horsecameracomponent.h>\r\n#include <gel/components/horsecomponent.h>\r\n#include <gel/components/camerautil.h>\r\n#include <gel/components/pedlogiccomponent.h>\r\n#include <gel/components/weaponcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <gfx/NxViewMan.h>\r\n\r\n\r\n#define MESSAGE(a) { printf(\"M:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPI(a) { printf(\"D:%s:%i: \" #a \" = %i\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPB(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, a ? \"true\" : \"false\"); }\r\n#define DUMPF(a) { printf(\"D:%s:%i: \" #a \" = %g\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPE(a) { printf(\"D:%s:%i: \" #a \" = %e\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPS(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPP(a) { printf(\"D:%s:%i: \" #a \" = %p\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPV(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z]); }\r\n#define DUMP4(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z], (a)[W]); }\r\n#define DUMPM(a) { DUMP4(a[X]); DUMP4(a[Y]); DUMP4(a[Z]); DUMP4(a[W]); }\r\n#define MARK { printf(\"K:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, __PRETTY_FUNCTION__); }\r\n#define PERIODIC(n) for (static int p__ = 0; (p__ = ++p__ % (n)) == 0; )\r\n\r\n#define vVELOCITY_WEIGHT_DROP_THRESHOLD\t\t\t\tMPH_TO_IPS(15.0f)\r\n// #define vLOCK_ATTRACTOR_VELOCITY_THRESHOLD\t\t\tMPH_TO_IPS(5.0f)\r\n#define vLOCK_ATTRACTOR_VELOCITY_THRESHOLD\t\t\tMPH_TO_IPS(5000000.0f)\r\n#define vSTATE_CHANGE_DELAY (1.0f)\r\n\r\nextern float\tscreen_angle;\r\nextern bool\t\tgun_fired;\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CHorseCameraComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CHorseCameraComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCHorseCameraComponent::CHorseCameraComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_HORSECAMERA );\r\n\t\r\n\tm_state\t\t\t\t= STATE_NORMAL;\r\n\tm_offset_height\t\t= FEET(5.0f);\r\n\tm_offset_distance\t= FEET(12.0f);\r\n\tm_offset_tilt\t\t= 0.0f;\r\n\tm_alignment_rate\t= 3.0f;\r\n\r\n\tm_orientation_matrix.Ident();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCHorseCameraComponent::~CHorseCameraComponent()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseCameraComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tuint32 subject_id;\r\n\t\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x431c185, \"subject\")))\r\n\t{\r\n\t\tpParams->GetChecksum(CRCD(0x431c185, \"subject\"), &subject_id, Script::ASSERT);\r\n\t\tmp_subject = static_cast< CCompositeObject* >(CCompositeObjectManager::Instance()->GetObjectByID(subject_id));\r\n\t\tDbg_MsgAssert(mp_subject, (\"Vehicle camera given subject which is not a composite object\"));\r\n\t\tmp_subject_vehicle_component = static_cast< CHorseComponent* >(mp_subject->GetComponent(CRC_HORSE));\r\n\t\tDbg_MsgAssert(mp_subject_vehicle_component, (\"HorseCameraComponent given subject which contains no HorseComponent\"));\r\n\t}\r\n\t\t\r\n\tpParams->GetFloat( CRCD( 0x9213625f, \"alignment_rate\" ), &m_alignment_rate);\r\n\tpParams->GetFloat( CRCD( 0x14849b6d, \"offset_height\" ), &m_offset_height);\r\n\tpParams->GetFloat( CRCD( 0xbd3d3ca9, \"offset_distance\" ), &m_offset_distance);\r\n\r\n\tif( pParams->GetFloat( CRCD( 0x480e14e2, \"offset_tilt\"), &m_offset_tilt ))\r\n\t{\r\n\t\t// Convert tilt from degrees to radians.\r\n\t\tm_offset_tilt = Mth::DegToRad( m_offset_tilt );\r\n\t}\r\n\t\r\n\treset_camera();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseCameraComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure( pParams );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseCameraComponent::Finalize( void )\r\n{\r\n\tmp_input_component = GetInputComponentFromObject( GetObject());\r\n\tDbg_Assert( mp_input_component );\r\n}\r\n\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseCameraComponent::Update()\r\n{\r\n\t// Decide whether we want to be active right now.\r\n\tif( mp_subject_vehicle_component )\r\n\t{\r\n\t\tif( !mp_subject_vehicle_component->ShouldUpdateCamera())\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tm_frame_length = Tmr::FrameLength();\r\n\r\n\tget_controller_input();\r\n\r\n\tcalculate_attractor_direction();\r\n\t\r\n\t// Due to rounding errors this can sometimes be > |1|, which hoses acosf(), so limit here.\r\n\tfloat angular_distance = acosf( Mth::Clamp( Mth::DotProduct( m_direction, m_attractor_direction ), -1.0f, 1.0f ));\r\n\tif( angular_distance > Mth::PI / 2.0f )\r\n\t{\r\n\t\tangular_distance = Mth::PI - angular_distance;\r\n\t}\r\n\t\r\n\tbool\tsign = Mth::CrossProduct( m_direction, m_attractor_direction )[Y] > 0.0f;\r\n\tfloat\tstep = m_alignment_rate * angular_distance * Tmr::FrameLength();\r\n\tif( step > angular_distance )\r\n\t{\r\n\t\tstep = angular_distance;\r\n\t}\r\n\t\r\n\tm_direction.RotateY(( sign ? 1.0f : -1.0f ) * step );\r\n\t\r\n\tm_direction.Normalize();\r\n\tcalculate_orientation_matrix();\r\n\t\r\n\t// Save off the orientation matrix at this point.\r\n\tMth::Matrix saved_mat = m_orientation_matrix;\r\n\r\n\tm_orientation_matrix.RotateYLocal( m_lookaround_heading );\r\n\tm_orientation_matrix.RotateXLocal( m_lookaround_tilt - m_offset_tilt );\r\n\r\n\t// Test the weapon component to generate the 'sticky' targetting behavior.\r\n\tif( mp_best_target )\r\n\t{\r\n\t\t// Need to get the rider so we can get the base object and then the weapon component (messy).\r\n\t\tCCompositeObject*\tp_obj\t\t= mp_subject_vehicle_component->GetRider();\r\n\t\tif( p_obj )\r\n\t\t{\r\n\t\t\tCWeaponComponent* p_weapon\t= GetWeaponComponentFromObject( p_obj );\r\n\t\t\tp_weapon->SetCurrentTarget( mp_best_target );\r\n\t\t\tMth::Vector sight_pos = mp_subject->GetPos() + Mth::Vector( 0.0f, m_offset_height, 0.0f, 0.0f );\r\n\t\t\tp_weapon->SetSightPos( sight_pos );\r\n\t\t\tp_weapon->SetSightMatrix( m_orientation_matrix );\r\n\r\n\t\t\tfloat extra_heading_change, extra_tilt_change;\r\n\t\t\tp_weapon->ProcessStickyTarget( m_lookaround_heading_delta, m_lookaround_tilt_delta, &extra_heading_change, &extra_tilt_change );\r\n\r\n\t\t\tif(( extra_heading_change != 0.0f ) || ( extra_tilt_change != 0.0f ))\r\n\t\t\t{\r\n\t\t\t\t// Reset the matrix to what it was prior to the heading and tilt adjustments.\r\n\t\t\t\tm_orientation_matrix = saved_mat;\r\n\r\n\t\t\t\tm_lookaround_heading += extra_heading_change;\r\n\t\t\t\tm_orientation_matrix.RotateYLocal( m_lookaround_heading );\r\n\r\n\t\t\t\tm_lookaround_tilt += extra_tilt_change;\r\n\t\t\t\tm_orientation_matrix.RotateXLocal( m_lookaround_tilt - m_offset_tilt );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tcalculate_position();\r\n\r\n\tApplyCameraCollisionDetection(\r\n\t\tm_pos, \r\n\t\tm_orientation_matrix, \r\n\t\tm_pos - m_offset_distance * m_orientation_matrix[Z], \r\n\t\tm_pos - m_offset_distance * m_orientation_matrix[Z], \r\n\t\tfalse, \r\n\t\tfalse\r\n\t);\r\n\t\r\n\tm_pos[W] = 1.0f;\r\n\tm_orientation_matrix[X][W] = 0.0f;\r\n\tm_orientation_matrix[Y][W] = 0.0f;\r\n\tm_orientation_matrix[Z][W] = 0.0f;\r\n\r\n\tdo_reticle();\r\n\r\n\tGetObject()->SetPos( m_pos );\r\n\tGetObject()->SetMatrix( m_orientation_matrix );\r\n\tGetObject()->SetDisplayMatrix( m_orientation_matrix );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CHorseCameraComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tcase CRCC(0x469fd, \"VehicleCamera_Reset\"):\r\n\t\t\tRefreshFromStructure(pParams);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseCameraComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to C......Component::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddChecksum(\"mp_subject\", mp_subject->GetID());\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseCameraComponent::get_controller_input( void )\r\n{\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\r\n\t// Switch the aiming state if triggered.\r\n\tif( control_pad.m_R3.GetTriggered())\r\n\t{\r\n\t\tcontrol_pad.m_R3.ClearTrigger();\r\n\r\n\t\t// Restore screen angle.\r\n\t\tscreen_angle = 72.0f;\r\n\t\tNx::CViewportManager::sSetScreenAngle( screen_angle );\r\n\r\n\t\tif( m_state == STATE_NORMAL )\r\n\t\t\tm_state = STATE_AIMING;\r\n\t\telse if( m_state == STATE_AIMING )\r\n\t\t\tm_state = STATE_NORMAL;\r\n\t}\r\n\r\n\t// Fire if triggered.\r\n\tgun_fired = false;\r\n\tif( control_pad.m_R1.GetTriggered())\r\n\t{\r\n\t\tgun_fired = true;\r\n\t\tcontrol_pad.m_R1.ClearTrigger();\r\n\t}\r\n\r\n\t// Switch sniper mode if triggered and in aiming mode.\r\n\tif( control_pad.m_up.GetTriggered())\r\n\t{\r\n\t\tcontrol_pad.m_up.ClearTrigger();\r\n\r\n\t\t// Unfortunately, pressing up on the left control stick will also cause m_up to be triggered, so check this\r\n\t\t// is really the d-pad press.\r\n\t\tif( control_pad.GetScaledLeftAnalogStickMagnitude() == 0.0f )\r\n\t\t{\r\n\t\t\tif( m_state == STATE_AIMING )\r\n\t\t\t{\r\n\t\t\t\t// This would be a good place to put the field of view setting code for the sniper rifle.\r\n\t\t\t\tif( screen_angle == 72.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tscreen_angle = 25.0f;\r\n\t\t\t\t}\r\n\t\t\t\telse if( screen_angle == 25.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tscreen_angle = 7.5f;\r\n\t\t\t\t}\r\n\t\t\t\telse if( screen_angle == 7.5f )\r\n\t\t\t\t{\r\n\t\t\t\t\tscreen_angle = 72.0f;\r\n\t\t\t\t}\r\n\t\t\t\tNx::CViewportManager::sSetScreenAngle( screen_angle );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Deal with adjusting aim direction.\r\n\tfloat tilt_target\t\t= control_pad.m_scaled_rightY;\r\n\tfloat heading_target\t= control_pad.m_scaled_rightX;\r\n\r\n\tif( m_state == STATE_NORMAL )\r\n\t{\r\n\t\t// Aiming input should be ignored.\r\n\t\ttilt_target\t\t= 0.0f;\r\n\t\theading_target\t= 0.0f;\r\n\t}\r\n\r\n\t// Modulate with the variable used to damp cursor movement when aiming at a heading_target.\r\n\theading_target\t= heading_target * m_spin_modulator;\r\n\ttilt_target\t\t= tilt_target * m_tilt_modulator;\r\n\t\t\r\n\t// Get script values.\r\n\tfloat heading_ka = Script::GetFloat( CRCD( 0xe31bc279, \"GunslingerHorseLookaroundHeadingKa\" ), Script::ASSERT );\r\n\tfloat heading_ea = Script::GetFloat( CRCD( 0x7d98eff7, \"GunslingerHorseLookaroundHeadingEa\" ), Script::ASSERT );\r\n\tfloat heading_ks = Script::GetFloat( CRCD( 0x10a2b331, \"GunslingerHorseLookaroundHeadingKs\" ), Script::ASSERT );\r\n\tfloat heading_es = Script::GetFloat( CRCD( 0x8e219ebf, \"GunslingerHorseLookaroundHeadingEs\" ), Script::ASSERT );\r\n\r\n\t// Calculate acceleration.\r\n\tfloat a = heading_ka * powf( Mth::Abs( heading_target ), heading_ea ) * (( heading_target > 0.0f ) ? 1.0f : ( heading_target < 0.0f ) ? -1.0f : 0.0f );\r\n\r\n\t// Calculate max speed.\r\n\tfloat s = heading_ks * powf( Mth::Abs( heading_target ), heading_es ) * (( heading_target > 0.0f ) ? 1.0f : ( heading_target < 0.0f ) ? -1.0f : 0.0f );\r\n\r\n\tm_lookaround_heading_angular_speed += a;\r\n\r\n\tif( s == 0.0f )\r\n\t{\r\n\t\tm_lookaround_heading_angular_speed = 0.0f;\r\n\t}\r\n\telse if((( s > 0.0f ) && ( m_lookaround_heading_angular_speed > s )) || (( s < 0.0f ) && ( m_lookaround_heading_angular_speed < s )))\r\n\t{\r\n\t\tm_lookaround_heading_angular_speed = s;\r\n\t}\r\n\r\n\tfloat lookaround_heading_speed = Script::GetFloat( CRCD( 0x8cf5f0cd, \"GunslingerHorseLookaroundHeadingSpeed\" ), Script::ASSERT );\r\n\r\n\t// Control stick left - reticle should move left.\r\n\tm_lookaround_heading_delta\t= -m_lookaround_heading_angular_speed * lookaround_heading_speed * m_frame_length;\r\n\tm_lookaround_heading\t   += m_lookaround_heading_delta;\r\n\r\n\tif( m_lookaround_heading > Mth::PI )\r\n\t\tm_lookaround_heading = m_lookaround_heading - ( 2 * Mth::PI );\r\n\telse if( m_lookaround_heading <= -Mth::PI )\r\n\t\tm_lookaround_heading = ( 2 * Mth::PI ) + m_lookaround_heading;\r\n\r\n\tif( Script::GetInteger( CRCD( 0x9edfc7af, \"GunslingerInvertAiming\" )) == 0 )\r\n\t{\r\n\t\t// Negate value if vertical aiming invert is not enabled.\r\n\t\ttilt_target = -tilt_target;\r\n\t}\r\n\r\n\t// Get script values.\r\n\tfloat tilt_ka = Script::GetFloat( CRCD( 0x3e8e974f, \"GunslingerHorseLookaroundTiltKa\" ), Script::ASSERT );\r\n\tfloat tilt_ea = Script::GetFloat( CRCD( 0xa00dbac1, \"GunslingerHorseLookaroundTiltEa\" ), Script::ASSERT );\r\n\tfloat tilt_ks = Script::GetFloat( CRCD( 0xcd37e607, \"GunslingerHorseLookaroundTiltKs\" ), Script::ASSERT );\r\n\tfloat tilt_es = Script::GetFloat( CRCD( 0x53b4cb89, \"GunslingerHorseLookaroundTiltEs\" ), Script::ASSERT );\r\n\r\n\t// Calculate acceleration.\r\n\ta = tilt_ka * powf( Mth::Abs( tilt_target ), tilt_ea ) * (( tilt_target > 0.0f ) ? 1.0f : ( tilt_target < 0.0f ) ? -1.0f : 0.0f );\r\n\r\n\t// Calculate max speed.\r\n\ts = tilt_ks * powf( Mth::Abs( tilt_target ), tilt_es ) * (( tilt_target > 0.0f ) ? 1.0f : ( tilt_target < 0.0f ) ? -1.0f : 0.0f );\r\n\r\n\tm_lookaround_tilt_angular_speed += a;\r\n\r\n\tif( s == 0.0f )\r\n\t{\r\n\t\tm_lookaround_tilt_angular_speed = 0.0f;\r\n\t}\r\n\telse if((( s > 0.0f ) && ( m_lookaround_tilt_angular_speed > s )) || (( s < 0.0f ) && ( m_lookaround_tilt_angular_speed < s )))\r\n\t{\r\n\t\tm_lookaround_tilt_angular_speed = s;\r\n\t}\r\n\r\n\tfloat lookaround_tilt_speed = Script::GetFloat( CRCD( 0xebbaa7e8, \"GunslingerHorseLookaroundTiltSpeed\" ), Script::ASSERT );\r\n\tm_lookaround_tilt_delta\t= m_lookaround_tilt_angular_speed * lookaround_tilt_speed * m_frame_length;\r\n\tm_lookaround_tilt\t   += m_lookaround_tilt_delta;\r\n\r\n\tif( m_lookaround_tilt > 1.1f )\r\n\t\tm_lookaround_tilt = 1.1f;\r\n\telse if( m_lookaround_tilt < -0.85f )\r\n\t\tm_lookaround_tilt = -0.85f;\r\n\r\n\tif( m_state == STATE_NORMAL )\r\n\t{\r\n\t\t// Smoothly move the lookaround values back to zero.\r\n\r\n\t\tm_lookaround_tilt\t\t-= ( m_lookaround_tilt * 0.05f );\r\n\t\tm_lookaround_heading\t-= ( m_lookaround_heading * 0.05f );\r\n\t}\r\n}\r\n\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseCameraComponent::reset_camera( void )\r\n{\r\n\tm_state\t= STATE_NORMAL;\r\n\r\n\tm_attractor_direction = -mp_subject->GetMatrix()[Z];\r\n\tm_attractor_direction[Y] = 0.0f;\r\n\tm_attractor_direction.Normalize();\r\n\t\r\n\tcalculate_attractor_direction();\r\n\t\r\n\tm_direction = m_attractor_direction;\r\n\t\r\n\tcalculate_orientation_matrix();\r\n\tcalculate_position();\r\n\t\r\n\tGetObject()->SetPos( m_pos );\r\n\tGetObject()->SetMatrix( m_orientation_matrix );\r\n\tGetObject()->SetDisplayMatrix(m_orientation_matrix);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseCameraComponent::calculate_attractor_direction( void )\r\n{\r\n\tif( m_state == STATE_NORMAL )\r\n\t{\r\n\t\tMth::Vector vel_direction = -mp_subject_vehicle_component->GetVel();\r\n\t\tvel_direction[Y] = 0.0f;\r\n\t\tfloat vel = vel_direction.Length();\r\n\t\tvel_direction.Normalize();\r\n\t\r\n\t\tfloat vel_weight = Mth::ClampMax(vel / vVELOCITY_WEIGHT_DROP_THRESHOLD, 1.0f) * Mth::DotProduct(vel_direction, -mp_subject->GetMatrix()[Z]);\r\n\t\t\r\n\t\tm_attractor_direction = -mp_subject->GetMatrix()[Z];\r\n\t\tm_attractor_direction[Y] = 0.0f;\r\n\t\tm_attractor_direction.Normalize();\r\n\t\t\r\n\t\tif (vel_weight > 0.0f)\r\n\t\t{\r\n\t\t\tm_attractor_direction += vel_weight * vel_direction;\r\n\t\t\tm_attractor_direction.Normalize();\r\n\t\t}\r\n\t}\r\n\telse if( m_state == STATE_AIMING )\r\n\t{\r\n\t\tm_attractor_direction = m_direction;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseCameraComponent::calculate_orientation_matrix( void )\r\n{\r\n\tm_orientation_matrix[Z] = m_direction;\r\n\tm_orientation_matrix[X] = Mth::CrossProduct( Mth::Vector( 0.0f, 1.0f, 0.0f, 0.0f ), m_orientation_matrix[Z] ).Normalize();\r\n\tm_orientation_matrix[Y] = Mth::CrossProduct( m_orientation_matrix[Z], m_orientation_matrix[X] );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseCameraComponent::calculate_position( void )\r\n{\r\n\tMth::Vector direction = m_orientation_matrix[Z];\r\n\tm_pos = mp_subject->GetPos() + Mth::Vector( m_offset_distance * direction[X], m_offset_height + ( m_offset_distance * direction[Y] ), m_offset_distance * direction[Z], 0.0f );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseCameraComponent::do_reticle( void )\r\n{\r\n\t// Need to get the rider so we can get the base object and then the weapon component (messy).\r\n\tCCompositeObject*\tp_obj\t\t= mp_subject_vehicle_component->GetRider();\r\n\tif( p_obj )\r\n\t{\r\n\t\tMth::Vector reticle_min\t= m_pos;\r\n\t\tMth::Vector reticle_max;\r\n\r\n\t\tCWeaponComponent* p_weapon\t= GetWeaponComponentFromObject( p_obj );\r\n\r\n\t\tp_weapon->SetSightMatrix( m_orientation_matrix );\r\n\t\tmp_best_target = p_weapon->GetCurrentTarget( reticle_min, &reticle_max );\r\n\r\n\t\tif( gun_fired )\r\n\t\t{\r\n\t\t\tp_weapon->Fire();\r\n\t\t}\r\n\r\n\t\tm_spin_modulator = p_weapon->GetSpinModulator();\r\n\t\tm_tilt_modulator = p_weapon->GetTiltModulator();\r\n\r\n\t\tp_weapon->DrawReticle();\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/HorseCameraComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       HorseCameraComponent.h\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ??/??/??\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_HORSECAMERACOMPONENT_H__\r\n#define __COMPONENTS_HORSECAMERACOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/components/horsecomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_HORSECAMERA CRCD(0xf1593757,\"HorseCamera\")\r\n#define\t\tGetHorseCameraComponent() ((Obj::CHorseCameraComponent*)GetComponent(CRC_HORSECAMERA))\r\n#define\t\tGetHorseCameraComponentFromObject(pObj) ((Obj::CHorseCameraComponent*)(pObj)->GetComponent(CRC_HORSECAMERA))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CHorseCameraComponent : public CBaseComponent\r\n{\r\npublic:\r\n\r\n\tenum EStateType\r\n\t{\r\n\t\tSTATE_NORMAL,\r\n\t\tSTATE_AIMING,\r\n\t};\r\n\t\r\n\t\t\t\t\t\t\t\t\tCHorseCameraComponent();\r\n    virtual\t\t\t\t\t\t\t~CHorseCameraComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tEStateType\t\t\t\t\t\tGetState( void )\t{ return m_state; }\r\n\tCHorseComponent*\t\t\t\tGetSubject( void )\t{ return mp_subject_vehicle_component; }\r\n\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\treset_camera( void );\r\n\tvoid\t\t\t\t\t\t\tcalculate_attractor_direction( void );\r\n\tvoid\t\t\t\t\t\t\tcalculate_orientation_matrix( void );\r\n\tvoid\t\t\t\t\t\t\tcalculate_position( void );\r\n\tvoid\t\t\t\t\t\t\tget_controller_input( void );\r\n\tvoid\t\t\t\t\t\t\tdo_reticle( void );\r\n\r\nprivate:\r\n\r\n\tEStateType\t\t\t\t\t\tm_state;\r\n\r\n\tfloat\t\t\t\t\t\t\tm_frame_length;\r\n\r\n\tfloat\t\t\t\t\t\t\tm_spin_modulator;\r\n\tfloat\t\t\t\t\t\t\tm_tilt_modulator;\r\n\r\n\tfloat\t\t\t\t\t\t\tm_lookaround_heading;\r\n\tfloat\t\t\t\t\t\t\tm_lookaround_heading_delta;\r\n\tfloat\t\t\t\t\t\t\tm_lookaround_heading_angular_speed;\r\n\tfloat\t\t\t\t\t\t\tm_lookaround_tilt;\r\n\tfloat\t\t\t\t\t\t\tm_lookaround_tilt_delta;\r\n\tfloat\t\t\t\t\t\t\tm_lookaround_tilt_angular_speed;\r\n\r\n\tCCompositeObject*\t\t\t\tmp_subject;\r\n\r\n\tCCompositeObject*\t\t\t\tmp_best_target;\r\n\r\n\t// Peer components.\r\n\tCInputComponent*\t\t\t\tmp_input_component;\r\n\tCHorseComponent*\t\t\t\tmp_subject_vehicle_component;\r\n\t\r\n\tMth::Vector\t\t   \t\t\t\tm_direction;\r\n\tMth::Vector\t\t   \t\t\t\tm_attractor_direction;\r\n\t\r\n\tMth::Vector\t\t\t\t\t\tm_pos;\r\n\tMth::Matrix\t\t\t\t\t\tm_orientation_matrix;\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_offset_height;\r\n\tfloat\t\t\t\t\t\t\tm_offset_distance;\r\n\tfloat\t\t\t\t\t\t\tm_offset_tilt;\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_alignment_rate;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/HorseComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       HorseComponent.cpp\r\n//* OWNER:          Dan Nelson\r\n//* CREATION DATE:  1/31/3\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <core/math/slerp.h>\r\n\t\t\t\t\t\t\t\t\t\t\r\n#include <gel/components/horsecomponent.h>\r\n#include <gel/components/floatinglabelcomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/camerautil.h>\r\n#include <gel/components/horsecameracomponent.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/collision/collcache.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/nxhierarchy.h>\r\n#include <gfx/skeleton.h>\r\n#include <gfx/camera.h>\r\n#include <gfx/nxviewman.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <sk/modules/viewer/viewer.h>\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\n#define MESSAGE(a) { printf(\"M:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPI(a) { printf(\"D:%s:%i: \" #a \" = %i\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPF(a) { printf(\"D:%s:%i: \" #a \" = %g\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPE(a) { printf(\"D:%s:%i: \" #a \" = %e\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPS(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPP(a) { printf(\"D:%s:%i: \" #a \" = %p\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPV(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z]); }\r\n#define DUMP4(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z], (a)[W]); }\r\n#define DUMPM(a) { DUMP4(a[X]); DUMP4(a[Y]); DUMP4(a[Z]); DUMP4(a[W]); }\r\n#define MARK { printf(\"K:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, __PRETTY_FUNCTION__); }\r\n#define PERIODIC(n) for (static int p__ = 0; (p__ = ++p__ % (n)) == 0; )\r\n\r\n// THOUGHTS:\r\n//\r\n// - BUG: solve negative collision depth issue for rect collisions; must project collision normal into rect plane before calculating depth (i think)\r\n// - BUG: bad wipeout behavior; IDEAS:\r\n//   - use only line feelers\r\n//   - turn off graivty with > 2 contacts\r\n//   - sleep like a rigidbody\r\n//   - compare algorithm with rigidbody\r\n// - Triggers.\r\n// - Lock motion if very slow and there's no input.\r\n// - Vehicle camera needs to reports its old position to get sounds' pitch correctly.\r\n//\r\n// - two center of masses (collision at zero and suspension) is an issue; actual rotation is done around zero; what sort of poor behavior does this cause\r\n//   when the car is on two wheels? what way is there to retain stable suspension behavior but use a common center of mass?\tperhaps simply damp rotational\r\n//   impulses due to the suspension; this may help with the \"vert, linear-to-angular energy\" freak-out issue as well\r\n// - body-body collisions; treat as boxes\r\n// - prehaps reduce wheel friction when very near vertical to prevent wall riding\r\n// - states: ASLEEP, AWAKE (full brake; rigidbody), DRIVEN, DRONE (?)\r\n// - vertical side rectangle feelers\r\n// - wheel camber <sp> extracted from model\r\n// - side slippage when stopped on hills\r\n\r\nnamespace Obj\r\n{\r\n\t\r\nCHorseComponent::SCollisionPoint CHorseComponent::sp_collision_points[4 * (Nx::MAX_NUM_2D_COLLISIONS_REPORTED + 1)];\r\n\t\t\t\t\t\t\t\t   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CHorseComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CHorseComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCHorseComponent::CHorseComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_HORSE );\r\n\t\r\n\tmp_input_component\t\t\t\t= NULL;\r\n\tmp_animation_component\t\t\t= NULL;\r\n\tmp_movable_contact_component\t= NULL;\r\n\r\n\tmp_collision_cache = Nx::CCollCacheManager::sCreateCollCache();\r\n\t\r\n\tm_draw_debug_lines = 0;\r\n\r\n\tmp_rider\t\t\t\t\t\t= NULL;\r\n\r\n\tm_vel.Set( 0.0f, 0.0f, 0.0f, 0.0f );\r\n\tm_upward.Set( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\tm_horizontal_vel.Set( 0.0f, 0.0f, 0.0f, 0.0f );\r\n\tm_control_direction\t\t\t\t\t= m_horizontal_vel;\r\n\tm_primary_air_direction\t\t\t\t= m_horizontal_vel;\r\n\tm_uncontrollable_air_horizontal_vel = m_horizontal_vel;\r\n\r\n\tm_orientation_matrix.Ident();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCHorseComponent::~CHorseComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tm_script_drag_factor\t= 1.0f;\r\n\r\n\t// extract constant parameters from struct; parameters not included in the script are left unchanged\r\n\t\r\n\t// toggles through the debug line drawing states\r\n\tif (pParams->ContainsFlag(CRCD(0x935ab858, \"debug\")))\r\n\t{\r\n\t\tm_draw_debug_lines = ++m_draw_debug_lines % 3;\r\n\t}\r\n\telse if (pParams->ContainsFlag(CRCD(0x751da48b, \"no_debug\")))\r\n\t{\r\n\t\tm_draw_debug_lines = 0;\r\n\t}\r\n\r\n\tm_pos = GetObject()->GetPos();\r\n\r\n\tif( pParams->ContainsComponentNamed(CRCD(0x7f261953, \"pos\" )))\r\n\t{\r\n\t\tpParams->GetVector(CRCD(0x7f261953, \"pos\"), &m_pos);\r\n\t\tGetObject()->SetPos(m_pos);\r\n\t}\r\n\r\n\t// Grab a pointer to the skeleton.\r\n\tmp_skeleton_component = static_cast< CSkeletonComponent* >(GetObject()->GetComponent(CRC_SKELETON));\r\n\tDbg_MsgAssert(mp_skeleton_component, (\"HorseComponent has no peer skeleton component.\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure( pParams );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::Finalize( void )\r\n{\r\n\tmp_model_component\t\t\t\t= GetModelComponentFromObject( GetObject());\r\n\tmp_input_component\t\t\t\t= GetInputComponentFromObject( GetObject());\r\n\tmp_animation_component\t\t\t= GetAnimationComponentFromObject( GetObject());\r\n\tmp_movable_contact_component\t= GetMovableContactComponentFromObject( GetObject());\r\n\r\n\tDbg_Assert( mp_model_component );\r\n\tDbg_Assert( mp_input_component );\r\n\tDbg_Assert( mp_animation_component );\r\n\tDbg_Assert( mp_movable_contact_component );\r\n\r\n\t// Enable blending for the Horse by default.\r\n\tmp_animation_component->EnableBlending( true );\r\n\r\n\tm_display_slerp_matrix = GetObject()->GetMatrix();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::Update( void )\r\n{\r\n\t// zero the frame event\r\n\tm_last_frame_event = m_frame_event;\r\n\tm_frame_event = 0;\r\n\t\r\n\t// get input\r\n    get_controller_input();\r\n\t\r\n\t// extract initial state for this frame from the object\r\n\tm_frame_start_pos = m_pos = GetObject()->GetPos();\r\n\t\r\n\tm_horizontal_vel = GetObject()->GetVel();\r\n\tm_horizontal_vel[Y] = 0.0f;\r\n\tm_vertical_vel = GetObject()->GetVel()[Y];\r\n\t\r\n\t// note that m_facing and m_upward will often not be orthogonal, but will always span a plan\r\n\t\r\n\t// generally straight up, but now after a transition from skating\r\n\tm_upward = GetObject()->GetMatrix()[Y];\r\n\t\r\n\tm_facing = GetObject()->GetMatrix()[Z];\r\n\tm_facing[Y] = 0.0f;\r\n\tfloat length = m_facing.Length();\r\n\tif (length < 0.001f)\r\n\t{\r\n\t\t// upward facing orientation matrix\r\n\t\tm_facing = -GetObject()->GetMatrix()[Y];\r\n\t\tm_facing[Y] = 0.0f;\r\n\t\tm_facing.Normalize();\r\n\t\t\r\n\t\t// since m_upward is now in the same plan as m_facing, push m_upward up a touch\r\n\t\tm_upward[Y] += 0.01f;\r\n\t\tm_upward.Normalize();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_facing /= length;\r\n\t}\r\n\t\r\n\t// Set the frame length.\r\n\tm_frame_length = Tmr::FrameLength();\r\n\t\r\n\t// go to our true Y position\r\n\tm_curb_float_height_adjusted = false;\r\n\tm_pos[Y] -= m_curb_float_height;\r\n\t\r\n\t// switch logic based on walking state\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase WALKING_GROUND:\r\n\t\t\tgo_on_ground_state();\r\n\t\t\tbreak;\r\n\r\n\t\tcase WALKING_AIR:\r\n\t\t\tgo_in_air_state();\r\n\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\tcase WALKING_HOP:\r\n//\t\t\tgo_hop_state();\r\n\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\tcase WALKING_HANG:\r\n//\t\t\tgo_hang_state();\r\n\t\t\tbreak;\r\n            \r\n\t\tcase WALKING_LADDER:\r\n//\t\t\tgo_ladder_state();\r\n            break;\r\n\t\t\t\r\n\t\tcase WALKING_ANIMWAIT:\r\n//\t\t\tgo_anim_wait_state();\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\t// the there's no curb to adjust due to, lerp down to zero\r\n\tif (!m_curb_float_height_adjusted)\r\n\t{\r\n\t\tm_curb_float_height = Mth::Lerp(m_curb_float_height, 0.0f, s_get_param(CRCD(0x9b3388fa, \"curb_float_lerp_down_rate\")) * m_frame_length);\r\n\t}\r\n\t\r\n\t// adjust back to our curb float Y position\r\n\tm_pos[Y] += m_curb_float_height;\r\n\t\r\n\t// scripts may have restarted us / switched us to skating\r\n//\tif (should_bail_from_frame()) return;\r\n\t\r\n\t// Keep the object from falling through holes in the geometry.\r\n\tif( m_state == WALKING_GROUND || m_state == WALKING_AIR )\r\n\t{\r\n\t\tuber_frig();\r\n\t}\r\n\t\r\n\t// rotate to upright\r\n\tlerp_upright();\r\n\t\r\n\t// setup the object based on this frame's walking\r\n\tcopy_state_into_object();\r\n\t\r\n\t// Position the rider correctly, if one exists.\r\n\tposition_rider();\r\n\r\n\tDbg_Assert(m_frame_event);\r\n\tGetObject()->SelfEvent(m_frame_event);\r\n\t\r\n\t// set the animation speeds\r\n/*\tswitch (m_anim_scale_speed)\r\n\t{\r\n\t\tcase RUNNING:\r\n\t\t\tif (m_anim_standard_speed > 0.0f)\r\n\t\t\t{\r\n\t\t\t\tmp_animation_component->SetAnimSpeed(m_anim_effective_speed / m_anim_standard_speed, false, false);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase HANGMOVE:\r\n\t\t\tmp_animation_component->SetAnimSpeed(m_anim_effective_speed / s_get_param(CRCD(0xd77ee881, \"hang_move_speed\")), false, false);\r\n\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\tcase LADDERMOVE:\r\n\t\t\tmp_animation_component->SetAnimSpeed(m_anim_effective_speed / s_get_param(CRCD(0xab2db54, \"ladder_move_speed\")), false, false);\r\n\t\t\tbreak;\r\n\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n*/\r\n\t\r\n\t// camera controls\r\n\t// NOTE: script parameters\r\n/*\r\n\tswitch (m_frame_event)\r\n\t{\r\n\t\tcase CRCC(0xf41aba21, \"Hop\"):\r\n\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase CRCC(0x2d9815c3, \"HangMoveLeft\"):\r\n\t\t{\r\n\t\t\tMth::Vector facing = m_facing;\r\n\t\t\tfacing.RotateY(-0.95f);\r\n\t\t\tmp_camera_component->SetOverrides(facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase CRCC(0x279b1f0b, \"HangMoveRight\"):\r\n\t\t{\r\n\t\t\tMth::Vector facing = m_facing;\r\n\t\t\tfacing.RotateY(0.95f);\r\n\t\t\tmp_camera_component->SetOverrides(facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\t\r\n\t\tcase CRCC(0x4194ecca, \"Hang\"):\r\n\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase CRCC(0xc84243da, \"Ladder\"):\r\n\t\tcase CRCC(0xaf5abc82, \"LadderMoveUp\"):\r\n\t\tcase CRCC(0xfec9dded, \"LadderMoveDown\"):\r\n\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\tcase CRCC(0x4fe6069c, \"AnimWait\"):\r\n\t\t\tif (m_anim_wait_camera_mode == AWC_CURRENT)\r\n\t\t\t{\r\n\t\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmp_camera_component->SetOverrides(m_drift_goal_facing, 0.05f);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\r\n\t\tdefault:\r\n\t\t\tmp_camera_component->UnsetOverrides();\r\n\t\t\tbreak;\r\n\t}\r\n*/\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCBaseComponent::EMemberFunctionResult CHorseComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | Walk_Ground |\r\n\t\tcase CRCC( 0x893213e5, \"Walk_Ground\" ):\r\n\t\t{\r\n\t\t\treturn m_state == WALKING_GROUND ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\r\n\t\tcase CRCC( 0x88bd4924, \"Horse_GetSpeedScale\" ):\r\n\t\t{\r\n\t\t\tuint32 checksum;\r\n\t\t\tif( m_anim_effective_speed < s_get_param( CRCD(0xf3649996, \"max_slow_walk_speed\")))\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x20c5a299,\"HORSE_WALK\");\r\n\t\t\t}\r\n\t\t\telse if( m_anim_effective_speed < s_get_param( CRCD(0x6a5805d8, \"max_fast_walk_speed\")))\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x8a354e68,\"HORSE_TROT\");\r\n\t\t\t}\r\n\t\t\telse if( m_anim_effective_speed < s_get_param( CRCD(0x1c94cc9c, \"max_slow_run_speed\")))\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x1bee30eb,\"HORSE_CANTER\");\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x2ca2c118,\"HORSE_GALLOP\");\r\n\t\t\t}\r\n\t\t\tpScript->GetParams()->AddChecksum( CRCD( 0x92c388f, \"SpeedScale\" ), checksum );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | Horse_Jump |\r\n\t\tcase CRCC( 0xae7deda, \"Horse_Jump\" ):\r\n\t\t{\r\n\t\t\t// Jump strength scales with the length the jump button has been held.\r\n\t\t\tjump( Mth::Lerp( s_get_param( CRCD( 0x246d0bf3, \"min_jump_factor\" )), 1.0f,\tMth::ClampMax( mp_input_component->GetControlPad().m_x.GetPressedTime() / s_get_param( CRCD( 0x12333ebd, \"hold_time_for_max_jump\" )), 1.0f )));\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | Vehicle_Kick | kicks the vehicle with a force and torque\r\n\t\tcase CRCC(0x93b713a6, \"Vehicle_Kick\"):\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script : Vehicle_Reset | reset any parameters of the vehicle\r\n\t\tcase CRCC(0xcdcdc05e, \"Vehicle_Reset\"):\r\n\t\t\tRefreshFromStructure(pParams);\r\n\t\t\tFinalize();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script : Vehicle_MoveToRestart | teleport the vehicle to the restart node\r\n\t\tcase CRCC(0x4b0b27dd, \"Vehicle_MoveToRestart\"):\r\n\t\t{\r\n\t\t\tuint32 node_name_checksum;\r\n\t\t\tpParams->GetChecksum(NO_NAME, &node_name_checksum, Script::ASSERT);\r\n\t\t\tMoveToNode(SkateScript::GetNode(SkateScript::FindNamedNode(node_name_checksum, Script::ASSERT)));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script : Vehicle_PlaceBeforeCamera | moves the object before the active camera\r\n\t\tcase CRCC(0xc33608e4, \"Vehicle_PlaceBeforeCamera\"):\r\n\t\t{\r\n\t\t\tGfx::Camera* camera = Nx::CViewportManager::sGetActiveCamera(0);\r\n\t\t\tif (camera)\r\n\t\t\t{\r\n\t\t\t\tMth::Vector& cam_pos = camera->GetPos();\r\n\t\t\t\tMth::Matrix& cam_mat = camera->GetMatrix();\r\n\r\n\t\t\t\tm_pos = cam_pos;\r\n\t\t\t\tm_pos += cam_mat[Y] * 12.0f * 12.0f;\r\n\t\t\t\tm_pos -= cam_mat[Z] * 12.0f * 12.0f;\r\n\t\t\t\tGetObject()->SetPos(m_pos);\r\n\t\t\t\t\r\n\t\t\t\tm_orientation_matrix[X] = -cam_mat[X];\r\n\t\t\t\tm_orientation_matrix[Y] = cam_mat[Y];\r\n\t\t\t\tm_orientation_matrix[Z] = -cam_mat[Z];\r\n\t\t\t\tGetObject()->SetMatrix( m_orientation_matrix );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CHorseComponent::GetDebugInfo ( Script::CStruct *p_info )\r\n{\r\n\tDbg_MsgAssert(p_info, (\"NULL p_info sent to CHorseComponent::GetDebugInfo\"));\r\n\r\n\t// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::MoveToNode( Script::CStruct* p_node )\r\n{\r\n\t// move to the position relative to the given node that a ped car would be at\r\n\tMth::Vector restart_pos;\r\n\tSkateScript::GetPosition(p_node, &restart_pos);\r\n\t\r\n\tMth::Vector restart_angles;\r\n\tSkateScript::GetAngles( p_node, &restart_angles );\r\n\tMth::Matrix restart_matrix;\r\n\trestart_matrix.SetFromAngles( restart_angles );\r\n\t\r\n\t// find ground hieght\r\n\tCFeeler feeler( restart_pos + Mth::Vector( 0.0f, 24.0f, 0.0f, 0.0f ), restart_pos + Mth::Vector( 0.0f, -800.0f, 0.0f, 0.0f ));\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\trestart_pos[Y] = feeler.GetPoint()[Y];\r\n\t}\r\n\t\r\n\t// move the car to the restart position and allow it to settle on its suspension\r\n\tm_pos = restart_pos;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 CHorseComponent::GetAnimation( void )\r\n{\r\n\treturn mp_animation_component->GetCurrentSequence();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CHorseComponent::AcceptRiderMount( CCompositeObject* p_rider )\r\n{\r\n\t// This is where we want to enable the associated camera.\r\n\tCHorseCameraComponent*\tp_cam_component = GetHorseCameraComponentFromObject( GetObject());\r\n\tif( p_cam_component )\r\n\t{\r\n\t\tp_cam_component->Suspend( false );\r\n\t}\r\n\r\n\t// Also want to set the horse camera as active.\r\n\tScript::RunScript( CRCD( 0xb08469a2, \"MountHorse\" ));\r\n\r\n\tmp_rider = p_rider;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CHorseComponent::ShouldUpdateCamera( void )\r\n{\r\n\tif( mp_rider )\r\n\t\treturn true;\r\n\telse\r\n\t\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CHorseComponent::AcceptRiderDismount( CCompositeObject* p_rider )\r\n{\r\n\t// This is where we want to disable the associated camera.\r\n\tCHorseCameraComponent*\tp_cam_component = GetHorseCameraComponentFromObject( GetObject());\r\n\tif( p_cam_component )\r\n\t{\r\n\t\tp_cam_component->Suspend( true );\r\n\t}\r\n\r\n\t// Also want to set the horse camera as inactive.\r\n\tScript::RunScript( CRCD( 0x400b95f5, \"DismountHorse\" ));\r\n\r\n\tmp_rider = NULL;\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::draw_debug_rendering (   ) const\r\n{\r\n\tif (m_draw_debug_lines)\r\n\t{\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::account_for_movable_contact( void )\r\n{\r\n/*\r\n\tif (!mp_movable_contact_component->UpdateContact(m_pos))\r\n\t\treturn;\r\n\t\r\n\tm_pos += mp_movable_contact_component->GetContact()->GetMovement();\r\n\t\r\n\tif (mp_movable_contact_component->GetContact()->IsRotated())\r\n\t{\r\n\t\tm_facing = mp_movable_contact_component->GetContact()->GetRotation().Rotate(m_facing);\r\n\t\tif (m_facing[Y] != 0.0f)\r\n\t\t{\r\n\t\t\tDUMPF(m_facing[Y]);\r\n\t\t\tm_facing[Y] = 0.0f;\r\n\t\t\tm_facing.Normalize();\r\n\t\t}\r\n\t}\r\n*/\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::jump( float strength )\r\n{\r\n\t// switch to air state and give the object an upwards velocity\r\n\t\r\n\t// if we're jumping from the ground, trip the ground's triggers\r\n\tif (m_state == WALKING_GROUND && m_last_ground_feeler_valid)\r\n\t{\r\n//\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_JUMP_OFF, m_last_ground_feeler);\r\n//\t\tif (should_bail_from_frame()) return;\r\n\t}\r\n\t\r\n\tm_primary_air_direction = m_facing;\r\n\t\r\n\t// Called by script from outside of the component update, so m_vertical_vel is not used.\r\n\tGetObject()->GetVel()[Y] = strength * s_get_param( CRCD( 0x63d62a21, \"jump_velocity\" ));\r\n\t\r\n\tleave_movable_contact_for_air( GetObject()->GetVel(), GetObject()->GetVel()[Y] );\r\n\t\r\n\tset_state( WALKING_AIR );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::setup_collision_cache( void )\r\n{\r\n\tfloat horizontal_reach = 1.0f + s_get_param(CRCD(0x99978d2b, \"feeler_length\"));\r\n\tfloat vertical_height = 1.0f + s_get_param(CRCD(0x9ea1974a, \"walker_height\"));;\r\n\tfloat vertical_depth = 1.0f + s_get_param(CRCD(0xaf3e4251, \"snap_down_height\"));\r\n\t\r\n\tMth::CBBox bbox(\r\n\t\tGetObject()->GetPos() - Mth::Vector(horizontal_reach, vertical_depth, horizontal_reach, 0.0f),\r\n\t\tGetObject()->GetPos() + Mth::Vector(horizontal_reach, vertical_height, horizontal_reach, 0.0f)\r\n\t);\r\n\t\r\n\tmp_collision_cache->Update(bbox);\r\n\tCFeeler::sSetDefaultCache(mp_collision_cache);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nfloat CHorseComponent::calculate_desired_speed( void )\r\n{\r\n\t// forced run\r\n//\tadjust_control_for_forced_run();\r\n\t\r\n//\tfloat walk_point = s_get_param(CRCD(0xc1528f7f, \"walk_point\"));\r\n\r\n\tif( m_control_magnitude > 0.0f )\r\n\t{\r\n\t\t// Stick is in non-zero position, so adjust target speed.\r\n\t\t// We may want two sets of these, one for speeding up, one for slowing down.\r\n\t\tfloat speed_ka = 1.0f; /* Script::GetFloat( CRCD( 0xcac0c1d4, \"GunslingerLookaroundTiltKa\" ), Script::ASSERT ); */\r\n\t\tfloat speed_ea = 2.0f; /* Script::GetFloat( CRCD( 0x5443ec5a, \"GunslingerLookaroundTiltEa\" ), Script::ASSERT ); */\r\n\r\n\t\tfloat speed_ks = 1.0f; /* Script::GetFloat( CRCD( 0x3979b09c, \"GunslingerLookaroundTiltKs\" ), Script::ASSERT ); */\r\n\t\tfloat speed_es = 1.0f; /* Script::GetFloat( CRCD( 0xa7fa9d12, \"GunslingerLookaroundTiltEs\" ), Script::ASSERT ); */\r\n\r\n\t\tfloat target = m_control_direction[X] * m_control_magnitude;\r\n\r\n\t\t// Calculate acceleration.\r\n\t\tfloat a = speed_ka * powf( Mth::Abs( target ), speed_ea ) * (( target > 0.0f ) ? 1.0f : ( target < 0.0f ) ? -1.0f : 0.0f );\r\n\r\n\t\t// Calculate max speed.\r\n\t\tfloat s = speed_ks * powf( Mth::Abs( target ), speed_es ) * (( target > 0.0f ) ? 1.0f : ( target < 0.0f ) ? -1.0f : 0.0f );\r\n\r\n\t\tm_target_speed_adjustment += a;\r\n\r\n\t\tif( s == 0.0f )\r\n\t\t{\r\n\t\t\tm_target_speed_adjustment = 0.0f;\r\n\t\t}\r\n\t\telse if((( s > 0.0f ) && ( m_target_speed_adjustment > s )) || (( s < 0.0f ) && ( m_target_speed_adjustment < s )))\r\n\t\t{\r\n\t\t\tm_target_speed_adjustment = s;\r\n\t\t}\r\n\r\n\t\tm_target_speed += m_target_speed_adjustment * m_frame_length;\r\n\r\n\t\t// Constrain to [0.0, 1.0] limits.\r\n\t\tm_target_speed = ( m_target_speed < 0.0f ) ? 0.0f : (( m_target_speed > 1.0f ) ? 1.0f : m_target_speed );\r\n\t}\r\n\r\n\treturn s_get_param( CRCD( 0xcc461b87, \"run_speed\" )) * m_target_speed;\r\n\r\n/*\r\n\t{\r\n\t\tfloat walk_point\t\t\t= s_get_param(CRCD(0xc1528f7f, \"walk_point\"));\r\n\t\tfloat velocity_magnitude\t= m_control_direction[X] * m_control_magnitude;\r\n\r\n\t\tif( velocity_magnitude <= walk_point )\r\n\t\t{\r\n\t\t\tm_run_toggle = false;\r\n\t\t\treturn Mth::LinearMap( 0.0f, s_get_param( CRCD( 0x79d182ad, \"walk_speed\" )), velocity_magnitude, 0.3f, walk_point );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_run_toggle = true;\r\n\t\t\treturn Mth::LinearMap( s_get_param( CRCD( 0x79d182ad, \"walk_speed\" )), s_get_param( CRCD( 0xcc461b87, \"run_speed\" )), velocity_magnitude, walk_point, 1.0f );\r\n\t\t}\r\n\t}\r\n*/\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nfloat CHorseComponent::adjust_desired_speed_for_slope( float desired_speed )\r\n{\r\n\t// Slow velocity up and down slopes.\r\n\t\r\n\t// skip if there is no appreciable slope\r\n\tif (m_ground_normal[Y] > 0.95f) return desired_speed;\r\n\t\r\n\t// skip if not running\r\n\tif (desired_speed <= s_get_param(CRCD(0x79d182ad, \"walk_speed\"))) return desired_speed;\r\n\t\r\n\t// calculate a horizontal vector up the slope\r\n\tMth::Vector up_slope = m_ground_normal;\r\n\tup_slope[Y] = 0.0f;\r\n\tup_slope.Normalize();\r\n\t\r\n\t// horizontal factor of velocity if the velocity were pointing along the slope (instead of along the horizontal)\r\n\tfloat movement_factor = m_ground_normal[Y];\r\n\t\r\n\t// factor of velocity pointing up the slope\r\n\tfloat dot = Mth::Abs(Mth::DotProduct(m_facing, up_slope));\r\n\t\r\n\t// scale the up-the-slope element of velocity based on the slope strength\r\n\treturn (1.0f - dot) * desired_speed + dot * movement_factor * desired_speed;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::calculate_horizontal_speed_and_facing( float &horizontal_speed )\r\n{\r\n\t// calculate user's desired speed\r\n\tfloat desired_speed = calculate_desired_speed();\r\n\t\r\n\t// adjust speed by the script set drag factor\r\n\tdesired_speed *= m_script_drag_factor;\r\n\t\t\t   \t\r\n\t// setup frame's event\r\n\tif (desired_speed <= s_get_param(CRCD(0x74e8227d, \"max_stand_speed\")))\r\n\t{\r\n\t\tm_frame_event = CRCD(0x9b46e749, \"Stand\");\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_frame_event = CRCD(0xaf895b3f, \"Run\");\r\n\t}\r\n\r\n\tbool special_acceleration = false;\r\n\t\r\n\t// HorseComponent version.\r\n\t// The required rate of turn depends on the x axis component of the control direction.\r\n//\tif( horizontal_speed < s_get_param( CRCD( 0x52582d5b, \"max_rotate_in_place_speed\" )))\r\n\tif( 1 )\r\n\t{\r\n\t\t// Low speed rotate to desired orientation with no speed change.\r\n\t\tm_delta_angle = Mth::DegToRad( s_get_param( CRCD( 0xb557804b, \"rotate_in_place_rate\" ))) * -m_control_direction[Z] * m_control_magnitude * m_frame_length;\r\n\t\tif( !m_run_toggle )\r\n\t\t{\r\n\t\t\tm_delta_angle *= s_get_param( CRCD( 0x7b446c98, \"walk_rotate_factor\" ));\r\n\t\t}\r\n\t\t\t\r\n\t\tif( m_delta_angle != 0.0f )\r\n\t\t{\r\n\t\t\tfloat cos_delta_angle\t= cosf( m_delta_angle );\r\n\t\t\tfloat sin_delta_angle\t= sinf( m_delta_angle );\r\n\t\t\tfloat adjusted_vel\t\t= cos_delta_angle * m_facing[X] + sin_delta_angle * m_facing[Z];\r\n\r\n\t\t\tm_facing[Z]\t\t\t\t= -sin_delta_angle * m_facing[X] + cos_delta_angle * m_facing[Z];\r\n\t\t\tm_facing[X]\t\t\t\t= adjusted_vel;\r\n\t\t\t\r\n\t\t\t// check for overturn\r\n//\t\t\tif (left_turn != (-m_facing[Z] * m_control_direction[X] + m_facing[X] * m_control_direction[Z] < 0.0f))\r\n//\t\t\t{\r\n//\t\t\t\tm_facing = m_control_direction;\r\n//\t\t\t}\r\n\t\t\t\r\n\t\t\t// no acceleration until we reach the desired orientation\r\n//\t\t\tspecial_acceleration = true;\r\n\t\t\t\r\n\t\t\t// setup the event\r\n\t\t\tm_frame_event = ( m_delta_angle < 0.0f ) ? CRCD( 0xf28adbfc, \"RotateLeft\" ) : CRCD( 0x912220f8, \"RotateRight\" );\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (special_acceleration) return;\r\n\t\r\n\t// Store desired speed for animation speed scaling.\r\n\tm_anim_effective_speed = desired_speed;\r\n\t\r\n\t// adjust desired speed for slope\r\n\tdesired_speed = adjust_desired_speed_for_slope( desired_speed );\r\n\t\r\n\t// linear acceleration; exponential deceleration\r\n\tif (horizontal_speed > desired_speed)\r\n\t{\r\n\t\thorizontal_speed = Mth::Lerp(horizontal_speed, desired_speed, s_get_param(CRCD(0xacfa4e0c, \"decel_factor\")) * m_frame_length);\r\n\t\t\r\n\t\tif (desired_speed == 0.0f)\r\n\t\t{\r\n\t\t\tif (horizontal_speed > s_get_param(CRCD(0x79d182ad, \"walk_speed\")))\r\n\t\t\t{\r\n\t\t\t\tm_frame_event = CRCD(0x1d537eff, \"Skid\");\r\n\t\t\t}\r\n\t\t\telse if (m_last_frame_event == CRCD(0x1d537eff, \"Skid\") && horizontal_speed > s_get_param(CRCD(0x311d02b2, \"stop_skidding_speed\")))\r\n\t\t\t{\r\n\t\t\t\tm_frame_event = CRCD(0x1d537eff, \"Skid\");\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (m_run_toggle)\r\n\t\t{\r\n\t\t\thorizontal_speed += s_get_param(CRCD(0x4f47c998, \"run_accel_rate\")) * m_frame_length;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\thorizontal_speed += s_get_param(CRCD(0x6590a49b, \"walk_accel_rate\")) * m_frame_length;\r\n\t\t}\r\n\t\tif (horizontal_speed > desired_speed)\r\n\t\t{\r\n\t\t\thorizontal_speed = desired_speed;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CHorseComponent::adjust_horizontal_vel_for_environment( bool wall_push_active )\r\n{\r\n\t// We send out feeler rays to find nearby walls.  We limit velocity to be flush with the first wall found.  If two or more non-parallel walls\r\n\t// are found, velocity is zeroed.\r\n\t\r\n\tfloat feeler_length = s_get_param(CRCD(0x99978d2b, \"feeler_length\"));\r\n\tfloat feeler_height = s_get_param(CRCD(0x6da7f696, \"feeler_height\"));\r\n\t\r\n\tCFeeler feeler;\r\n\t\r\n\tbool contact = false;\r\n\tfor (int n = 0; n < vNUM_FEELERS + 1; n++)\r\n\t{\r\n\t\t// setup the the feeler\r\n\t\t\r\n\t\tif (n == vNUM_FEELERS)\r\n\t\t{\r\n\t\t\t// final feeler is for air state only and is at the feet; solves situations in which the feet impact with vertical surfaces which the\r\n\t\t\t// wall feelers are too high to touch\r\n\t\t\tif (m_state != WALKING_AIR)\r\n\t\t\t{\r\n\t\t\t\tmp_contacts[vNUM_FEELERS].in_collision = false;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tfeeler.m_start = m_pos;\r\n\t\t\tfeeler.m_end = m_pos + m_horizontal_vel * m_frame_length;\r\n\t\t\tfeeler.m_end[Y] += m_vertical_vel * m_frame_length + 0.5f * -s_get_param(CRCD(0xa5e2da58, \"gravity\")) * Mth::Sqr(m_frame_length);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfeeler.m_start = m_pos;\r\n\t\t\tfeeler.m_start[Y] += feeler_height;\r\n\t\t\tfeeler.m_end = m_pos + feeler_length * calculate_feeler_offset_direction(n);\r\n\t\t\tfeeler.m_end[Y] += feeler_height;\r\n\t\t}\r\n\t\t\r\n\t\tmp_contacts[n].in_collision = feeler.GetCollision();\r\n\t\t\r\n\t\tif (!mp_contacts[n].in_collision)\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t{\r\n\t\t\t\tfeeler.DebugLine(0, 0, 255, 1);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tcontact = true;\r\n\t\t\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(255, 0, 0, 1);\r\n\t\t}\r\n\t\t#endif\r\n\r\n\t\t// grab the horizontal normal of the contacted wall\r\n\t\tmp_contacts[n].normal = feeler.GetNormal();\r\n\t\tmp_contacts[n].normal[Y] = 0.0f;\r\n\t\tmp_contacts[n].normal.Normalize();\r\n\t\t\r\n\t\t// grab the distance of the contact from the object\r\n\t\tmp_contacts[n].distance = feeler.GetDist();\r\n\t\t\r\n\t\t// if we're on the moving object, don't count its movement when doing collision detection, as the walker's velocity is already measured\r\n\t\t// relative to its movable contact's\r\n\t\tif (feeler.IsMovableCollision()\r\n\t\t\t&& (!mp_movable_contact_component->HaveContact() || mp_movable_contact_component->GetContact()->GetObject() != feeler.GetMovingObject()))\r\n\t\t{\r\n\t\t\tmp_contacts[n].movement = Mth::DotProduct(feeler.GetMovingObject()->GetVel(), mp_contacts[n].normal);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_contacts[n].movement = 0.0f;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// check for wall push\r\n\tif (m_state == WALKING_GROUND)\r\n\t{\r\n//\t\tif (wall_push_active && check_for_wall_push())\r\n\t\tif (false)\r\n\t\t{\r\n\t\t\t// if we're wall pushing, we may decide to switch states based on our environment\r\n\t\t\t\r\n\t\t\tif (Tmr::ElapsedTime(m_wall_push_test.test_start_time) > s_get_param(CRCD(0x928e6775, \"hop_delay\")))\r\n\t\t\t{\r\n//\t\t\t\tif (maybe_climb_up_ladder() || maybe_hop_to_hang() || maybe_jump_low_barrier()) return false;\r\n\t\t\t}\r\n\t\t\telse if (Tmr::ElapsedTime(m_wall_push_test.test_start_time) > s_get_param(CRCD(0x38d36700, \"barrier_jump_delay\")))\r\n\t\t\t{\r\n//\t\t\t\tif (maybe_climb_up_ladder() || maybe_jump_low_barrier()) return false;\r\n\t\t\t}\r\n\t\t}\r\n//\t\telse if (mp_input_component->GetControlPad().m_R1.GetPressed() && !m_ignore_grab_button)\r\n//\t\t{\r\n//\t\t\tif (maybe_climb_up_ladder(true)) return false;\r\n//\t\t}\r\n\t}\r\n\t\r\n\tif (!contact) return false;\r\n\t\r\n\t// push away from walls\r\n\tfor (int n = 0; n < vNUM_FEELERS + 1; n++)\r\n\t{\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\t                \r\n\t\tif (mp_contacts[n].distance < s_get_param(CRCD(0xa20c43b7, \"push_feeler_length\")) / feeler_length)\r\n\t\t{\r\n\t\t\tm_pos += s_get_param(CRCD(0x4d16f37d, \"push_strength\")) * m_frame_length * mp_contacts[n].normal;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// from here on we ignore collisions we're moving out of\r\n\tcontact = false;\r\n\tfor (int n = 0; n < vNUM_FEELERS + 1; n++)\r\n\t{\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\t\r\n\t\t// don't count collisions we're moving out of\r\n\t\tif (Mth::DotProduct(mp_contacts[n].normal, m_horizontal_vel) >= mp_contacts[n].movement)\r\n\t\t{\r\n\t\t\tmp_contacts[n].in_collision = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcontact = true;\r\n\t\t}\r\n\t}\r\n\tif (!contact) return false;\r\n\t\r\n\t// Now we calculate how our movement is effected by our collisions.  The movement must have a non-negative dot product with all collision normals.\r\n\t// The algorithm used should be valid for all convex environments.\r\n\t\r\n\t// if any of the colllision normals are more than right angles to one another, no movement is possible\r\n\t// NOTE: not valid with movable contacts; could cause jerky movement in corners where walls are movable\r\n\tfor (int n = 0; n < vNUM_FEELERS + 1; n++)\r\n\t{\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\tfor (int m = n + 1; m < vNUM_FEELERS + 1; m++)\r\n\t\t{\r\n\t\t\tif (!mp_contacts[m].in_collision) continue;\r\n\t\t\tif (Mth::DotProduct(mp_contacts[n].normal, mp_contacts[m].normal) <= 0.0f)\r\n\t\t\t{\r\n\t\t\t\tm_horizontal_vel.Set();\r\n\t\t\t\tm_anim_effective_speed = Mth::Min(s_get_param(CRCD(0xbd6a05d, \"min_anim_run_speed\")), m_anim_effective_speed);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// direction of proposed movement\r\n\tMth::Vector movement_direction = m_horizontal_vel;\r\n\tmovement_direction.Normalize();\r\n\t\r\n\tMth::Vector adjusted_vel = m_horizontal_vel;\r\n\t\r\n\t// loop over the contacts (from backward to forward)\r\n\tconst int contact_idxs[] = { 7, 4, 3, 5, 2, 6, 1, 0 };\r\n\tfor (int i = 0; i < vNUM_FEELERS + 1; i++)\r\n\t{\r\n\t\tint n = contact_idxs[i];\r\n\t\t\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\t\r\n\t\t// check to see if the movement still violates this constraint\r\n\t\tfloat normal_vel = Mth::DotProduct(adjusted_vel, mp_contacts[n].normal);\r\n\t\tif (normal_vel >= mp_contacts[n].movement) continue;\r\n\t\t\r\n\t\t// adjust the movement to the closest direction allowed by this contraint\r\n\t\tadjusted_vel -= (normal_vel - mp_contacts[n].movement) * mp_contacts[n].normal;\r\n\t\t\r\n\t\t// if the mvoement direction no longer points in the direction of the proposed movement, no movement occurs\r\n\t\tif (Mth::DotProduct(adjusted_vel, m_horizontal_vel) <= 0.0f)\r\n\t\t{\r\n\t\t\tm_horizontal_vel.Set();\r\n\t\t\tm_anim_effective_speed = Mth::Min(s_get_param(CRCD(0xbd6a05d, \"min_anim_run_speed\")), m_anim_effective_speed);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// insure that the adjusted velocity in the final direction is not larger than the projection of the initial velocity into that direction\r\n\tfloat adjusted_speed = adjusted_vel.Length();\r\n\tMth::Vector adjusted_vel_direction = adjusted_vel;\r\n\tadjusted_vel_direction *= 1.0f / adjusted_speed;\r\n\tfloat projected_vel = Mth::DotProduct(m_horizontal_vel, adjusted_vel_direction);\r\n\t\r\n\tif (adjusted_speed > projected_vel)\r\n\t{\r\n\t\tadjusted_vel = adjusted_vel_direction * projected_vel;\r\n\t}\r\n\t\r\n\t// only the velocity along the movement direction is retained\r\n\tm_horizontal_vel = adjusted_vel;\r\n\t\r\n\tfloat final_horiz_vel = m_horizontal_vel.Length();\r\n\tif (m_anim_effective_speed > s_get_param(CRCD(0xbd6a05d, \"min_anim_run_speed\")))\r\n\t{\r\n\t\tm_anim_effective_speed = final_horiz_vel;\r\n\t\tm_anim_effective_speed = Mth::Max(s_get_param(CRCD(0xbd6a05d, \"min_anim_run_speed\")), m_anim_effective_speed);\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::adjust_facing_for_adjusted_horizontal_vel( void  )\r\n{\r\n\t// We adjust facing due to adjustment in horizontal velocity due to environment.\r\n\t// Basically, we want to object to turn to face the velocity that the environment has forced upon it.\r\n\t\r\n\t// IDEA: shift to basing turn amount on angle difference and not speed\r\n\t\r\n\tfloat horizontal_speed = m_horizontal_vel.Length();\r\n\t\r\n\t// the new facing is in the direction of our adjusted velocity\r\n\tMth::Vector new_facing = m_horizontal_vel;\r\n\tnew_facing.Normalize();\r\n\t\r\n\t// Smoothly transition between no wall turning to full wall turning.\r\n\tfloat turn_ratio;\r\n\tif( horizontal_speed > s_get_param( CRCD( 0xe6c1cd0d, \"max_wall_turn_speed_threshold\" )))\r\n\t{\r\n\t\tturn_ratio = s_get_param( CRCD( 0x7a583b9b, \"wall_turn_factor\" )) * m_frame_length;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tturn_ratio = Mth::LinearMap(\t0.0f,\r\n\t\t\t\t\t\t\t\t\t\ts_get_param( CRCD( 0x7a583b9b, \"wall_turn_factor\")) * m_frame_length,\r\n\t\t\t\t\t\t\t\t\t\thorizontal_speed,\r\n//\t\t\t\t\t\t\t\t\t\ts_get_param( CRCD( 0x0515a933, \"wall_turn_speed_threshold\")),\r\n\t\t\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\t\t\ts_get_param( CRCD( 0xe6c1cd0d, \"max_wall_turn_speed_threshold\" )));\r\n\t}\r\n\t\r\n\t// Exponentially approach new facing.\r\n\tif( turn_ratio >= 1.0f )\r\n\t{\r\n\t\tm_facing = new_facing;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_facing = Mth::Lerp( m_facing, new_facing, turn_ratio );\r\n\t\tm_facing.Normalize();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::go_on_ground_state( void )\r\n{\r\n\taccount_for_movable_contact();\r\n\t\r\n\tsetup_collision_cache();\r\n\t\r\n\t// Calculate initial horizontal speed.\r\n\tfloat horizontal_speed = m_horizontal_vel.Length();\r\n\t\r\n\tcalculate_horizontal_speed_and_facing( horizontal_speed );\r\n\t\r\n\t// Calculate this frame's movement.\r\n\tm_horizontal_vel = horizontal_speed * m_facing;\r\n\t\r\n\t// Prevent movement into walls.\r\n\tif( adjust_horizontal_vel_for_environment( true ))\r\n\t{\r\n\t\t// Turn to face newly adjusted velocity.\r\n\t\tadjust_facing_for_adjusted_horizontal_vel();\r\n\t}\r\n\t\r\n\t// If we are wall pushing, we may have decided to switch states during adjust_horizontal_vel_for_environment based on our environment.\r\n//\tif (m_state != WALKING_GROUND || should_bail_from_frame())\r\n\tif( m_state != WALKING_GROUND )\r\n\t{\r\n\t\tCFeeler::sClearDefaultCache();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// Apply movement for this frame.\r\n\tm_pos += m_horizontal_vel * m_frame_length;\r\n\t\r\n\t// Snap up and down curbs and perhaps switch to air.\r\n\trespond_to_ground();\r\n\r\n//\tif (m_state != WALKING_GROUND || should_bail_from_frame())\r\n\tif( m_state != WALKING_GROUND )\r\n\t{\r\n\t\tCFeeler::sClearDefaultCache();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tadjust_curb_float_height();\r\n\t\r\n\t// Deal with intelligent path following.\r\n\tdo_path_following();\r\n\r\n\t// Ensure that we do not slip through the cracks in the collision geometry which are a side-effect of moving collidable objects.\r\n\tif (CCompositeObject* p_inside_object = mp_movable_contact_component->CheckInsideObjects(m_pos, m_frame_start_pos))\r\n\t{\r\n\t\tMESSAGE(\"WALKING_GROUND, within moving object\");\r\n\t\t\r\n\t\t// allow it to push us forward, causing a bit of a stumble\r\n\t\tm_horizontal_vel = p_inside_object->GetVel();\r\n\t\tm_horizontal_vel[Y] = 0.0f;\r\n\t\tm_vertical_vel = 0.0f;\r\n\t\t\r\n\t\tfloat speed_sqr = m_horizontal_vel.LengthSqr();\r\n\t\tif (speed_sqr > (10.0f * 10.0f))\r\n\t\t{\r\n\t\t\tm_facing = m_horizontal_vel * (1.0f / sqrtf(speed_sqr));\r\n\t\t}\r\n\t}\r\n\t\r\n\tCFeeler::sClearDefaultCache();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::go_in_air_state( void )\r\n{\r\n\tsetup_collision_cache();\r\n\t\r\n\t// default air event\r\n\tm_frame_event = CRCD(0x439f4704, \"Air\");\r\n\t\r\n\t// user control of horizontal velocity\r\n\tcontrol_horizontal_vel();\r\n\t\r\n\t// prevent movement into walls\r\n\tadjust_horizontal_vel_for_environment(false);\r\n//\tif (should_bail_from_frame()) return;\r\n\t\r\n\t// check for head bonking\r\n\tadjust_vertical_vel_for_ceiling();\r\n\t\r\n\t// apply movement and acceleration for this frame\r\n\tm_pos += m_horizontal_vel * m_frame_length;\r\n\tm_pos[Y] += m_vertical_vel * m_frame_length + 0.5f * -s_get_param(CRCD(0xa5e2da58, \"gravity\")) * Mth::Sqr(m_frame_length);\r\n\t\r\n\tm_vertical_vel += -s_get_param(CRCD(0xa5e2da58, \"gravity\")) * m_frame_length;\r\n\t\r\n\t// see if we've landed yet\r\n\tcheck_for_landing(m_frame_start_pos, m_pos);\r\n//\tif (m_state != WALKING_AIR || should_bail_from_frame()) return;\r\n\tif (m_state != WALKING_AIR ) return;\r\n\t\r\n\t// maybe grab a rail; delay regrabbing of hang rails\r\n//\tif (mp_input_component->GetControlPad().m_R1.GetPressed() && !m_ignore_grab_button\r\n//\t\t&& ((m_previous_state != WALKING_HANG && m_previous_state != WALKING_LADDER) || Tmr::ElapsedTime(m_state_timestamp) > s_get_param(CRCD(0xe6e0c0a4, \"rehang_delay\"))))\r\n//\t{\r\n//\t\tif (m_previous_state == WALKING_LADDER)\r\n//\t\t{\r\n//\t\t\t// can't regrab ladders\r\n//\t\t\tif (maybe_grab_to_hang(m_frame_start_pos, m_pos))\r\n//\t\t\t{\r\n//\t\t\t\tCFeeler::sClearDefaultCache();\r\n//\t\t\t\treturn;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tif (maybe_grab_to_hang(m_frame_start_pos, m_pos) || maybe_grab_to_ladder(m_frame_start_pos, m_pos))\r\n//\t\t\t{\r\n//\t\t\t\tCFeeler::sClearDefaultCache();\r\n//\t\t\t\treturn;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n\t\r\n//\tif (mp_input_component->GetControlPad().m_triangle.GetPressed())\r\n//\t{\r\n//\t\tif (maybe_stick_to_rail())\r\n//\t\t{\r\n//\t\t\tCFeeler::sClearDefaultCache();\r\n//\t\t\treturn;\r\n//\t\t}\r\n//\t}\r\n\t\r\n\t// insure that we do not slip through the cracks in the collision geometry which are a side-effect of moving collidable objects\r\n\tMth::Vector previous_pos = m_pos;\r\n\tif (CCompositeObject* p_inside_object = mp_movable_contact_component->CheckInsideObjects(m_pos, m_frame_start_pos))\r\n\t{\r\n\t\tMESSAGE(\"WALKING_AIR, within moving object\");\r\n\t\t\r\n\t\tm_horizontal_vel.Set();\r\n\t\tm_vertical_vel = 0.0f;\r\n\t\tcheck_for_landing(m_pos, previous_pos);\r\n\t}\r\n\t\r\n\tCFeeler::sClearDefaultCache();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::get_controller_input( void )\r\n{\r\n\t// If no rider, ignore input.\r\n\tif( mp_rider == NULL )\r\n\t{\r\n\t\t// Set it as if we are trying to slow downn to the max.\r\n\t\tm_control_direction[X]\t= -1.0f;\r\n\t\tm_control_direction[Z]\t= 0.0f;\r\n\t\tm_control_magnitude\t\t= 1.0f;\r\n\t\treturn;\r\n\t}\r\n\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\r\n//\tDbg_Assert(mp_camera);\r\n\t\r\n\t// rotate controller direction into camera's frame\r\n//\tMth::Vector camera_forward = -mp_camera->m_matrix[Z];\r\n//\tcamera_forward[Y] = 0.0f;\r\n//\tcamera_forward.Normalize();\r\n\t\r\n\t// allow a tolerance range for pressing directly forward\r\n\tfloat angle = control_pad.m_leftAngle;\r\n\tif (Mth::Abs(angle) < Mth::DegToRad(s_get_param(CRCD(0x4676a268, \"forward_tolerance\"))))\r\n\t{\r\n\t\tangle = 0.0f;\r\n\t}\r\n\t\r\n\tfloat sin_angle = sinf(angle);\r\n\tfloat cos_angle = cosf(angle);\r\n//\tm_control_direction[X] = cos_angle * camera_forward[X] - sin_angle * camera_forward[Z];\r\n//\tm_control_direction[Z] = sin_angle * camera_forward[X] + cos_angle * camera_forward[Z];\r\n\tm_control_direction[X] = cos_angle;\r\n\tm_control_direction[Z] = sin_angle;\r\n\t\r\n\t// different control schemes for analog stick and d-pad\r\n#\tif 0\r\n\tif (control_pad.m_leftX == 0.0f && control_pad.m_leftY == 0.0f)\r\n\t{\r\n\t\t// d-pad control\r\n\t\tif (control_pad.m_leftLength == 0.0f)\r\n\t\t{\r\n\t\t\tm_control_magnitude = 0.0f;\r\n\t\t\tm_control_pegged = false;\r\n\t\t\t\r\n\t\t\t// don't reset dpad in the air\r\n\t\t\tif (m_state != WALKING_AIR)\r\n\t\t\t{\r\n\t\t\t\tm_dpad_used_last_frame = false;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (!m_dpad_used_last_frame)\r\n\t\t\t{\r\n\t\t\t\tm_dpad_use_time_stamp = Tmr::GetTime();\r\n\t\t\t}\r\n\t\t\tm_dpad_used_last_frame = true;\r\n\t\t\t\r\n\t\t\tif (m_state == WALKING_GROUND)\r\n\t\t\t{\r\n\t\t\t\t// slowly ramp up to a full run\r\n\t\t\t\t\r\n\t\t\t\tTmr::Time elapsed_time = Tmr::ElapsedTime(m_dpad_use_time_stamp);\r\n\t\t\t\t\r\n\t\t\t\tTmr::Time full_run_dpad_delay = static_cast< Tmr::Time >(s_get_param(CRCD(0x1832588c, \"full_run_dpad_delay\")));\r\n\t\t\t\tTmr::Time start_run_dpad_delay = static_cast< Tmr::Time >(s_get_param(CRCD(0x2c386a43, \"start_run_dpad_delay\")));\r\n\t\t\t\t\r\n\t\t\t\tif (elapsed_time < start_run_dpad_delay)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_control_magnitude = s_get_param(CRCD(0xc1528f7f, \"walk_point\"));\r\n\t\t\t\t}\r\n\t\t\t\telse if (elapsed_time < full_run_dpad_delay)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_control_magnitude = Mth::SmoothMap(\r\n\t\t\t\t\t\ts_get_param(CRCD(0xc1528f7f, \"walk_point\")),\r\n\t\t\t\t\t\t1.0f,\r\n\t\t\t\t\t\telapsed_time,\r\n\t\t\t\t\t\tstart_run_dpad_delay,\r\n\t\t\t\t\t\tfull_run_dpad_delay\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_control_magnitude = 1.0f;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_control_magnitude = 1.0f;\r\n\t\t\t}\r\n            m_control_pegged = true;\r\n\t\t}\r\n        \r\n\t\t// damp dpad control directions towards forward when running\r\n        if (m_state == WALKING_GROUND && Mth::Abs(angle) < Mth::DegToRad(90.0f + 5.0f) && (forced_run() || m_control_magnitude > s_get_param(CRCD(0xc1528f7f, \"walk_point\"))))\r\n        {\r\n//\t\t\tif (forced_run() || m_control_magnitude == 1.0f)\r\n//\t\t\t{\r\n//\t\t\t\tm_control_direction += s_get_param(CRCD(0x3c581621, \"dpad_control_damping_factor\")) * camera_forward;\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\t// smoothly interpolate between damping and no damping\r\n//\t\t\t\tm_control_direction += Mth::SmoothMap(0.0f, s_get_param(CRCD(0x3c581621, \"dpad_control_damping_factor\")), m_control_magnitude, s_get_param(CRCD(0xc1528f7f, \"walk_point\")), 1.0f)\r\n//\t\t\t\t\t* camera_forward;\r\n//\t\t\t}\r\n\t\t\tm_control_direction.Normalize();\r\n        }\r\n\t}\r\n\telse\r\n#\tendif\r\n\t{\r\n\t\t// analog stick control\r\n\t\tm_control_magnitude = control_pad.GetScaledLeftAnalogStickMagnitude() / 0.85f;\r\n\t\tif (m_control_magnitude >= 1.0f)\r\n\t\t{\r\n\t\t\tm_control_magnitude = 1.0f;\r\n\t\t\tm_control_pegged = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_control_pegged = false;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// during a forward control lock, ignore all input not in the forward direction\r\n\tif (m_state == WALKING_GROUND && m_forward_control_lock)\r\n\t{\r\n\t\tm_control_magnitude = Mth::ClampMin(m_control_magnitude * Mth::DotProduct(m_control_direction, m_facing), 0.0f);\r\n\t\tm_control_direction = m_facing;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::uber_frig( void )\r\n{\r\n\t// Ensure that we don't fall to the center of the earth, even if there are holes in the geometry.\r\n\t// Also, do lighting since we've got the feeler anyway.\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_start[Y] += 1.0f;\r\n\tfeeler.m_end = m_pos;\r\n\tfeeler.m_end[Y] -= FEET(400);\r\n\t\r\n\tif( feeler.GetCollision())\r\n\t{\r\n\t\tmp_model_component->ApplyLightingFromCollision( feeler );\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// Teleport us back to our position at the frame's start; not pretty, but this isn't supposed to be.\r\n\tm_pos = m_frame_start_pos;\r\n\t\r\n\t// Zero our velocity too.\r\n\tm_horizontal_vel.Set();\r\n\tm_vertical_vel = 0.0f;\r\n\t\r\n\t// Set our state to ground\r\n\tset_state( WALKING_GROUND );\r\n\t\t\t  \t\r\n\tm_last_ground_feeler_valid = false;\r\n\t\r\n\tm_ground_normal.Set(0.0f, 1.0f, 0.0f);\r\n\r\n\t// Reset our script state.\r\n\tm_frame_event = CRCD(0x57ff2a27, \"Land\");\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::lerp_upright( void )\r\n{\r\n//    if (m_upward[Y] == 1.0f) return;\r\n\t\r\n//\tif (m_upward[Y] > 0.999f)\r\n//\t{\r\n//\t\tm_upward.Set(0.0f, 1.0f, 0.0f);\r\n//\t\treturn;\r\n//\t}\r\n\t\r\n//\tm_upward = Mth::Lerp(m_upward, Mth::Vector(0.0f, 1.0f, 0.0f), s_get_param(CRCD(0xf22c135, \"lerp_upright_rate\")) * Tmr::FrameLength());\r\n//\tm_upward.Normalize();\r\n\r\n\tm_upward = m_ground_normal;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::copy_state_into_object( void )\r\n{\r\n\t// Build the object's matrix based on our facing.\r\n\tMth::Matrix matrix;\r\n\t\r\n\t// A horse requires special consideration, since it will necessarily tilt to match it's environment along it's long axis,\r\n\t// but will need to remain upright (or very nearly so) along it's shortest axis, since otherwise given it's high center\r\n\t// of gravity, it would topple over when standing sideways on a steep slope.\r\n\tmatrix[X]\t\t= Mth::CrossProduct( m_upward, m_facing );\r\n\tmatrix[X][Y]\t= 0.0f;\r\n\tmatrix[X].Normalize();\r\n\r\n\tmatrix[Y]\t\t= m_upward;\r\n\tmatrix[Z]\t\t= Mth::CrossProduct( matrix[X], matrix[Y] );\r\n\tmatrix[Z].Normalize();\r\n\r\n\tmatrix[Y]\t\t= Mth::CrossProduct( matrix[Z], matrix[X] );\r\n\r\n\tmatrix[W].Set( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\r\n\tGetObject()->SetPos( m_pos );\r\n\tGetObject()->SetMatrix( matrix );\r\n\r\n\t// The display matrix is slerped towards the current matrix.\r\n\tMth::SlerpInterpolator slerper( &m_display_slerp_matrix, &matrix );\r\n\t\t\t\r\n\t// Apply the slerping.\r\n\tslerper.getMatrix( &m_display_slerp_matrix, GetTimeAdjustedSlerp( 0.1f, m_frame_length ));\r\n\t\r\n\tGetObject()->SetDisplayMatrix( m_display_slerp_matrix );\r\n\r\n\t// Construct the object's velocity.\r\n\tGetObject()->SetVel( m_horizontal_vel );\r\n\tGetObject()->GetVel()[Y] = m_vertical_vel;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nMth::Vector CHorseComponent::calculate_feeler_offset_direction( int contact )\r\n{\r\n\tfloat angle = contact * (2.0f * Mth::PI / vNUM_FEELERS);\r\n\tfloat cos_angle = cosf(angle);\r\n\tfloat sin_angle = sinf(angle);\r\n\r\n\tMth::Vector end_offset_direction;\r\n\tend_offset_direction[X] = cos_angle * m_facing[X] - sin_angle * m_facing[Z];\r\n\tend_offset_direction[Y] = 0.0f;\r\n\tend_offset_direction[Z] = sin_angle * m_facing[X] + cos_angle * m_facing[Z];\r\n\tend_offset_direction[W] = 0.0f;\r\n\t\r\n\treturn end_offset_direction;\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::adjust_curb_float_height( void )\r\n{\r\n\t// adjust m_curb_float_height to smooth out moving up stairs\r\n\t\r\n\t// When facing a curb, we smoothly increase m_curb_float_height to the height of the curb.  When we snap up the curb, m_curb_float_height is then\r\n\t// reduced by an amount equal to the snap distance.\r\n\t// When we snap down a curb, m_curb_float_height is increased by the snap distance.  We then drop m_curb_float_height smoothly to zero.\r\n\t\r\n\t// determine appropriate direction to search for a curb\r\n\tMth::Vector feeler_direction = m_facing;\r\n\tfeeler_direction.ProjectToPlane(m_ground_normal);\r\n\tfeeler_direction[Y] = Mth::ClampMin(feeler_direction[Y], 0.0f);\r\n\tfeeler_direction.Normalize();\r\n\t\r\n\t// look for a curb\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_start[Y] += 0.5f;\r\n\tfeeler.m_end = m_pos + s_get_param(CRCD(0x11edcc52, \"curb_float_feeler_length\")) * feeler_direction;\r\n    feeler.m_end[Y] += 0.5f;\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(0, 255, 0, 1);\r\n\t}\r\n\t#endif\r\n\t\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t// grab the distance to the curb\r\n\t\tfloat distance_to_curb = feeler.GetDist();\r\n\t\t\r\n\t\t// look up from the curb to find the curb height\r\n\t\tfeeler.m_end = feeler.GetPoint() + 0.5f * feeler_direction;\r\n\t\tfeeler.m_start = feeler.m_end;\r\n\t\tfeeler.m_start[Y] = m_pos[Y] + s_get_param(CRCD(0xcee3a3e1, \"snap_up_height\"));\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(0, 255, 255, 1);\r\n\t\t}\r\n\t\t#endif\r\n\t\t\r\n\t\tif (feeler.GetCollision())\r\n\t\t{\r\n\t\t\t// calculate the m_curb_float_height we should have based on the curb height and distance\r\n\t\t\tfloat appropriate_curb_float_height = (1.0f - distance_to_curb) * (feeler.GetPoint()[Y] - m_pos[Y]);\r\n\t\t\t\r\n\t\t\tif (Mth::Abs(m_curb_float_height) < 0.01f && m_control_magnitude == 0.0f && m_horizontal_vel.LengthSqr() < Mth::Sqr(s_get_param(CRCD(0x227d72ee, \"min_curb_height_adjust_vel\"))))\r\n\t\t\t{\r\n\t\t\t\t// don't update the curb height if we're on the ground and standing still; this is mostly to prevent snapping up right after landing a jump\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// lerp to the appropriate height\r\n\t\t\t\tm_curb_float_height = Mth::Lerp(m_curb_float_height, appropriate_curb_float_height, s_get_param(CRCD(0x856a80d3, \"curb_float_lerp_up_rate\")) * m_frame_length);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tm_curb_float_height_adjusted = true;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::respond_to_ground( void )\r\n{\r\n\t// Reset ground normal to straight up.\r\n\tm_ground_normal.Set( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t// Look for the ground below us.  If we find it, snap to it.  If not, go to air state.\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_start[Y] += s_get_param(CRCD(0xcee3a3e1, \"snap_up_height\"));\r\n\tfeeler.m_end = m_pos;\r\n\tfeeler.m_end[Y] -= s_get_param(CRCD(0xaf3e4251, \"snap_down_height\"));\r\n\t\r\n\tif (!feeler.GetCollision())\r\n\t{\r\n\t\t// no ground\r\n\t\t\r\n//\t\tif (m_last_ground_feeler_valid)\r\n//\t\t{\r\n//\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_OFF_EDGE, m_last_ground_feeler);\r\n//\t\t\tif (should_bail_from_frame()) return;\r\n//\t\t}\r\n\t\t\r\n\t\t// go to air state\r\n\t\tset_state(WALKING_AIR);\r\n\t\tm_primary_air_direction = m_facing;\r\n\t\tleave_movable_contact_for_air(m_horizontal_vel, m_vertical_vel);\r\n\t\tm_frame_event = CRCD(0xabf1f6ac, \"WalkOffEdge\");\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tfloat snap_distance = feeler.GetPoint()[Y] - m_pos[Y];\r\n\t\r\n\t// no not send event for very small snaps\r\n\tif (Mth::Abs(snap_distance) > s_get_param(CRCD(0xd3193d8e, \"max_unnoticed_ground_snap\")))\r\n\t{\r\n\t\tGetObject()->SelfEvent(snap_distance > 0.0f ? CRCD(0x93fcf3ed, \"SnapUpEdge\") : CRCD(0x56e21153, \"SnapDownEdge\"));\r\n\t}\r\n\t\r\n\t// snap position to the ground\r\n\tm_pos[Y] = feeler.GetPoint()[Y];\r\n\t\r\n\t// adjust stair float distance\r\n\tm_curb_float_height = Mth::ClampMin(m_curb_float_height - snap_distance, 0.0f);\r\n\t\r\n\t// see if we've changed sectors\r\n\tif (m_last_ground_feeler.GetSector() != feeler.GetSector())\r\n\t{\r\n//\t\tif (m_last_ground_feeler_valid)\r\n//\t\t{\r\n//\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_OFF, m_last_ground_feeler);\r\n//\t\t\tif (should_bail_from_frame()) return;\r\n//\t\t}\r\n//\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_ONTO, feeler);\r\n//\t\tif (should_bail_from_frame()) return;\r\n\t}\r\n\t\r\n\t// stash the ground feeler so that we can trip the group's triggers at a later time\r\n\tm_last_ground_feeler = feeler;\r\n\tm_last_ground_feeler_valid = true;\r\n\t\r\n\t// set the ground normal for next frame's velocity slope adjustment\r\n\tm_ground_normal = feeler.GetNormal();\r\n\r\n\t// NOTE: need to repeat this code anywhere we enter the ground state\r\n\tmp_movable_contact_component->CheckForMovableContact(feeler);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::leave_movable_contact_for_air( Mth::Vector& horizontal_vel, float& vertical_vel )\r\n{\r\n\t// use movement from the latest movable contact update call\r\n\tif (mp_movable_contact_component->HaveContact())\r\n\t{\r\n\t\t// keep track of the horizontal velocity due to our old contact\r\n\t\tm_uncontrollable_air_horizontal_vel = mp_movable_contact_component->GetContact()->GetObject()->GetVel();\r\n\r\n\t\tif (Mth::DotProduct(m_uncontrollable_air_horizontal_vel, horizontal_vel) > 0.0f)\r\n\t\t{\r\n\t\t\t// extra kicker; dangerous as there's no collision detection; without this slight extra movement, when we walk off the front of a movable object,\r\n\t\t\t// the object will move back under us before our next frame, and we will clip its edge and land on it\r\n\t\t\tm_pos += m_uncontrollable_air_horizontal_vel * m_frame_length;\r\n\t\t}\r\n\t\t\r\n\t\t// add movable contact's velocity into our launch velocity\r\n\t\tvertical_vel += m_uncontrollable_air_horizontal_vel[Y];\r\n\t\tm_uncontrollable_air_horizontal_vel[Y] = 0.0f;\r\n\t\thorizontal_vel += m_uncontrollable_air_horizontal_vel;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_uncontrollable_air_horizontal_vel.Set();\r\n\t}\r\n\r\n\tmp_movable_contact_component->LoseAnyContact();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::control_horizontal_vel( void )\r\n{\r\n\t// We allow user control over the object's in air velocity.  The algorithm is complicated by the fact that the forward velocity of the jump needs\r\n\t// to be accounted for when allowing for velocity adjustment.  It is assumed that the jump direction is the same as the facing.\r\n\t\r\n\t// remove uncontrollable velocity term\r\n\tm_horizontal_vel -= m_uncontrollable_air_horizontal_vel;\r\n\t\r\n\t// forced run still works in the air\r\n//\tadjust_control_for_forced_run();\r\n\t\r\n\t// adjust speed by the script set drag factor\r\n\tfloat adjust_magnitude = m_control_magnitude * m_script_drag_factor;\r\n\t\r\n\t// adjust velocity perpendicular to jump direction\r\n\t\r\n\t// direction perpendicular to jump direction\r\n\tMth::Vector perp_direction( -m_primary_air_direction[Z], 0.0f, m_primary_air_direction[X], 0.0f );\r\n\t\r\n\t// desired perpendicular velocity\r\n\tfloat perp_desired_vel = s_get_param(CRCD(0x896c8888, \"jump_adjust_speed\")) * adjust_magnitude * Mth::DotProduct(m_control_direction, perp_direction);\r\n\t\r\n\t// current perpendicular velocity\r\n\tfloat perp_vel = Mth::DotProduct(m_horizontal_vel, perp_direction);\r\n\t\r\n\t// exponentially approach desired velocity\r\n\tperp_vel = Mth::Lerp(perp_vel, perp_desired_vel, s_get_param(CRCD(0xf085443b, \"jump_accel_factor\")) * m_frame_length);\r\n\t\t\r\n\t// adjust velocity parallel to jump direction\r\n\t\r\n\t// desired parallel velocity\r\n\tfloat para_desired_vel = s_get_param(CRCD(0x896c8888, \"jump_adjust_speed\")) * adjust_magnitude * Mth::DotProduct(m_control_direction, m_primary_air_direction);\r\n\t\r\n\t// current parallel velocity\r\n\tfloat para_vel = Mth::DotProduct(m_horizontal_vel, m_primary_air_direction);\r\n\t\r\n    // if desired velocity if forward and forward velocity already exceeds adjustment velocity\r\n\tif (para_desired_vel >= 0.0f && para_vel > para_desired_vel)\r\n\t{\r\n\t\t// do nothing; don't slow down the jump\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// adjust desired velocity to center around current velocity to insure that our in air stopping ability is not too amazing\r\n\t\tif (para_desired_vel < 0.0f && para_vel > 0.0f)\r\n\t\t{\r\n\t\t\tpara_desired_vel += para_vel;\r\n\t\t}\r\n\t\t\r\n\t\t// expondentially approach desired velocity\r\n\t\tpara_vel = Mth::Lerp(para_vel, para_desired_vel, s_get_param(CRCD(0xf085443b, \"jump_accel_factor\")) * m_frame_length);\r\n\t}\r\n\t\t\r\n\t// rebuild horizontal velocity from parallel and perpendicular components\r\n\t// Dave note - not sure about controlling the horse velocity in midair, so disable for now.\r\n//\tm_horizontal_vel = para_vel * m_primary_air_direction + perp_vel * perp_direction;\r\n\t\r\n\t// reinstitute uncontrollable velocity term\r\n\tm_horizontal_vel += m_uncontrollable_air_horizontal_vel;\r\n\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::check_for_landing( const Mth::Vector& previous_pos, const Mth::Vector& final_pos )\r\n{\r\n\t// See if our feet have passed through geometry.  If so, snap to it and go to ground state.\r\n\t\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = previous_pos;\r\n\tfeeler.m_end = final_pos;\r\n\tif (!feeler.GetCollision()) return;\r\n\t\r\n\t// snap to the collision point\r\n\tm_pos = feeler.GetPoint();\r\n\t\r\n\t// zero vertical velocity\r\n\tm_vertical_vel = 0.0f;\r\n\t\r\n\t// change to ground state\r\n\tset_state(WALKING_GROUND);\r\n\t\r\n\t// stash the feeler\r\n\tm_last_ground_feeler = feeler;\r\n\tm_last_ground_feeler_valid = true;\r\n\t\r\n\t// trip any land trigger\r\n//\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_LAND_ON, m_last_ground_feeler);\r\n//\tif (should_bail_from_frame()) return;\r\n\t\r\n\t// setup our ground normal for next frames velocity slope adjustment\r\n\tm_ground_normal = feeler.GetNormal();\r\n\t\r\n\t// check for a moving contact\r\n\tmp_movable_contact_component->CheckForMovableContact(feeler);\r\n\tif (mp_movable_contact_component->HaveContact())\r\n\t{\r\n\t\tm_horizontal_vel -= mp_movable_contact_component->GetContact()->GetObject()->GetVel();\r\n\t\tm_horizontal_vel[Y] = 0.0f;\r\n\t}\r\n\t\r\n\t// retain only that velocity which is parallel to our facing and forward\r\n\tif (Mth::DotProduct(m_horizontal_vel, m_facing) > 0.0f)\r\n\t{\r\n\t\tm_horizontal_vel.ProjectToNormal(m_facing);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_horizontal_vel.Set();\r\n\t}\r\n\t\r\n\t// clear any jump requests\r\n\tmp_input_component->GetControlPad().m_x.ClearRelease();\r\n\t\r\n\tm_frame_event = CRCD(0x57ff2a27, \"Land\");\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::adjust_vertical_vel_for_ceiling( void )\r\n{\r\n\t// If we hit our head, zero vertical velocity\r\n\t\r\n\t// only worry about the ceiling if we're moving upwards\r\n\tif (m_vertical_vel <= 0.0f) return;\r\n\t\r\n\t// look for a collision up through the body to the head\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_end = m_pos;\r\n\tfeeler.m_end[Y] += s_get_param(CRCD(0x9ea1974a, \"walker_height\"));\r\n\tif (!feeler.GetCollision()) return;\r\n\t\r\n\t// zero upward velocity\r\n\tm_vertical_vel = 0.0f;\r\n\t\r\n\tGetObject()->SelfEvent(CRCD(0x6e84acf3, \"HitCeiling\"));\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::position_rider( void )\r\n{\r\n\t// HACK: get player proximity checks, triggers, and the like working\r\n//\tCCompositeObject* p_skater = static_cast< CCompositeObject* >(CCompositeObjectManager::Instance()->GetObjectByID( 0 ));\r\n//\tp_skater->SetPos( GetObject()->GetPos());\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool get_collision( Mth::Vector& start, Mth::Vector& direction, float length, float* p_worst_length )\r\n{\r\n\tCFeeler feeler;\r\n\t\r\n\tfeeler.m_start\t\t\t= start;\r\n\tfeeler.m_end\t\t\t= start + length * direction;\r\n\r\n\t// No collision as yet.\r\n\tbool collision\t= false;\r\n\t*p_worst_length\t= length;\r\n\r\n\tGfx::AddDebugLine( feeler.m_start, feeler.m_end, MAKE_RGB( 0, 128, 0 ), MAKE_RGB( 0, 128, 0 ), 1 );\r\n\r\n\tif( feeler.GetCollision())\r\n\t{\r\n\t\tif( Mth::Abs( feeler.GetNormal()[Y] ) < 0.2f )\r\n\t\t{\r\n\t\t\tcollision = true;\r\n\t\t\t*p_worst_length = length * feeler.GetDist();\r\n\t\t\tGfx::AddDebugLine( feeler.m_start, feeler.m_end, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 1 );\r\n\t\t}\r\n\t}\r\n\r\n\tMth::Vector offset( -direction[Z], 0.0f, direction[X], 0.0f );\r\n\r\n\t// Try 4 inches to the left.\r\n\tfeeler.m_start\t\t\t+= offset * 4.0f;\r\n\tfeeler.m_end\t\t\t+= offset * 4.0f;\r\n\tif( feeler.GetCollision())\r\n\t{\r\n\t\tif( Mth::Abs( feeler.GetNormal()[Y] ) < 0.2f )\r\n\t\t{\r\n\t\t\tcollision = true;\r\n\t\t\tif(( length * feeler.GetDist()) < *p_worst_length )\r\n\t\t\t{\r\n\t\t\t\t*p_worst_length = length * feeler.GetDist();\r\n\t\t\t\tGfx::AddDebugLine( feeler.m_start, feeler.m_end, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 1 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Try 8 inches to the left.\r\n\tfeeler.m_start\t\t\t+= offset * 4.0f;\r\n\tfeeler.m_end\t\t\t+= offset * 4.0f;\r\n\tif( feeler.GetCollision())\r\n\t{\r\n\t\tif( Mth::Abs( feeler.GetNormal()[Y] ) < 0.2f )\r\n\t\t{\r\n\t\t\tcollision = true;\r\n\t\t\tif(( length * feeler.GetDist()) < *p_worst_length )\r\n\t\t\t{\r\n\t\t\t\t*p_worst_length = length * feeler.GetDist();\r\n\t\t\t\tGfx::AddDebugLine( feeler.m_start, feeler.m_end, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 1 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Try 12 inches to the left.\r\n\tfeeler.m_start\t\t\t+= offset * 4.0f;\r\n\tfeeler.m_end\t\t\t+= offset * 4.0f;\r\n\tif( feeler.GetCollision())\r\n\t{\r\n\t\tif( Mth::Abs( feeler.GetNormal()[Y] ) < 0.2f )\r\n\t\t{\r\n\t\t\tcollision = true;\r\n\t\t\tif(( length * feeler.GetDist()) < *p_worst_length )\r\n\t\t\t{\r\n\t\t\t\t*p_worst_length = length * feeler.GetDist();\r\n\t\t\t\tGfx::AddDebugLine( feeler.m_start, feeler.m_end, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 1 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Try 4 inches to the right.\r\n\tfeeler.m_start\t\t\t-= offset * 16.0f;\r\n\tfeeler.m_end\t\t\t-= offset * 16.0f;\r\n\tif( feeler.GetCollision())\r\n\t{\r\n\t\tif( Mth::Abs( feeler.GetNormal()[Y] ) < 0.2f )\r\n\t\t{\r\n\t\t\tcollision = true;\r\n\t\t\tif(( length * feeler.GetDist()) < *p_worst_length )\r\n\t\t\t{\r\n\t\t\t\t*p_worst_length = length * feeler.GetDist();\r\n\t\t\t\tGfx::AddDebugLine( feeler.m_start, feeler.m_end, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 1 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Try 8 inches to the right.\r\n\tfeeler.m_start\t\t\t-= offset * 4.0f;\r\n\tfeeler.m_end\t\t\t-= offset * 4.0f;\r\n\tif( feeler.GetCollision())\r\n\t{\r\n\t\tif( Mth::Abs( feeler.GetNormal()[Y] ) < 0.2f )\r\n\t\t{\r\n\t\t\tcollision = true;\r\n\t\t\tif(( length * feeler.GetDist()) < *p_worst_length )\r\n\t\t\t{\r\n\t\t\t\t*p_worst_length = length * feeler.GetDist();\r\n\t\t\t\tGfx::AddDebugLine( feeler.m_start, feeler.m_end, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 1 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Try 12 inches to the right.\r\n\tfeeler.m_start\t\t\t-= offset * 4.0f;\r\n\tfeeler.m_end\t\t\t-= offset * 4.0f;\r\n\tif( feeler.GetCollision())\r\n\t{\r\n\t\tif( Mth::Abs( feeler.GetNormal()[Y] ) < 0.2f )\r\n\t\t{\r\n\t\t\tcollision = true;\r\n\t\t\tif(( length * feeler.GetDist()) < *p_worst_length )\r\n\t\t\t{\r\n\t\t\t\t*p_worst_length = length * feeler.GetDist();\r\n\t\t\t\tGfx::AddDebugLine( feeler.m_start, feeler.m_end, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 1 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn collision;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst float AVOID_COLLISION_SCORE\t\t\t= 1000.0f;\r\nconst float\tTURN_ANGLE_SCORE_MULT\t\t\t= 1.0f;\r\nconst float DISTANCE_PERCENTAGE_SCORE_MULT\t= 0.1f;\r\n\r\nconst float\tPANIC_SCORE\t\t\t\t\t\t= 900.0f;\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::do_path_following( void )\r\n{\r\n\t// Get the horse camera component for this horse. Messy.\r\n\tObj::CHorseCameraComponent* p_cam_component = static_cast<Obj::CHorseCameraComponent*>( Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType( CRC_HORSECAMERA ));\r\n\twhile( p_cam_component )\r\n\t{\r\n\t\tif( p_cam_component->GetSubject() == this )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tp_cam_component = static_cast<Obj::CHorseCameraComponent*>( p_cam_component->GetNextSameType());\r\n\t}\r\n\r\n\tif( p_cam_component )\r\n\t{\r\n\t\tif( p_cam_component->GetState() == CHorseCameraComponent::STATE_NORMAL )\r\n\t\t{\r\n\t\t\t// No path following in normal state. Cleanup if we were doing path following.\r\n\t\t\tif( mp_nav_nodes )\r\n\t\t\t{\r\n\t\t\t\tcleanup_node_based_path_following();\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Did we turn this frame? If so, all bets are off...\r\n\t\tif( m_delta_angle != 0.0f )\r\n\t\t{\r\n\t\t\t// Cleanup if we were doing path following.\r\n\t\t\tif( mp_nav_nodes )\r\n\t\t\t{\r\n\t\t\t\tcleanup_node_based_path_following();\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Are we path following? In which case, follow the path.\r\n\t\tif( mp_nav_nodes )\r\n\t\t{\r\n\t\t\tdo_node_based_path_following();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// See if we are going to hit something soon if we stay on this course.\r\n\t\tfloat feeler_height = 36.0f;\r\n\t\tfloat feeler_length\t= 50.0f * 12.0f;\r\n\r\n\t\tfloat\t\tangle\t\t= 0.0f;\r\n\t\tfloat\t\tcos_angle\t= cosf( angle );\r\n\t\tfloat\t\tsin_angle\t= sinf( angle );\r\n\t\tfloat\t\tworst_length;\r\n\r\n\t\tMth::Vector\tfeeler_start;\r\n\t\tMth::Vector\tfeeler_end;\r\n\t\tMth::Vector\tend_offset_direction;\r\n\r\n\t\tend_offset_direction[X] = cos_angle * m_facing[X] - sin_angle * m_facing[Z];\r\n\t\tend_offset_direction[Y] = 0.0f;\r\n\t\tend_offset_direction[Z] = sin_angle * m_facing[X] + cos_angle * m_facing[Z];\r\n\t\tend_offset_direction[W] = 0.0f;\r\n\r\n\t\tfeeler_start\t\t\t= Mth::Vector( m_pos[X], m_pos[Y] + feeler_height, m_pos[Z], m_pos[W] );\r\n\t\tfeeler_end\t\t\t\t= feeler_start + feeler_length * end_offset_direction;\r\n\t\t\r\n\t\tif( get_collision( feeler_start, end_offset_direction, feeler_length, &worst_length ))\r\n//\t\tif( feeler.GetCollision())\r\n\t\t{\r\n\t\t\tfloat dist = worst_length;\r\n\r\n\t\t\t// We need to figure out if turning a few degrees will enable us to obtain a clear path for\r\n\t\t\t// a significantly further distance.\r\n\t\t\tfeeler_length *= 2.0f;\r\n\r\n\t\t\tfloat\tbest_score\t\t\t\t\t= 0.0f;\r\n\t\t\tfloat\tbest_angle\t\t\t\t\t= Mth::DegToRad( 90.0f );\r\n\r\n\t\t\t// Scan through angles from +9 degrees to -9 degrees in 3 degree steps.\r\n\t\t\tfloat step_angle = Mth::DegToRad( -9.0f );\r\n\t\t\twhile( step_angle <= Mth::DegToRad( 9.0f ))\r\n\t\t\t{\r\n\t\t\t\tfloat score = 0.0f;\r\n\r\n\t\t\t\tcos_angle\t= cosf( step_angle );\r\n\t\t\t\tsin_angle\t= sinf( step_angle );\r\n\r\n\t\t\t\tend_offset_direction[X] = cos_angle * m_facing[X] - sin_angle * m_facing[Z];\r\n\t\t\t\tend_offset_direction[Y] = 0.0f;\r\n\t\t\t\tend_offset_direction[Z] = sin_angle * m_facing[X] + cos_angle * m_facing[Z];\r\n\t\t\t\tend_offset_direction[W] = 0.0f;\r\n\r\n\t\t\t\tfeeler_end\t\t\t\t= feeler_start + feeler_length * end_offset_direction;\r\n\r\n\t\t\t\t// Score for avoiding collision.\r\n\t\t\t\tbool collision = get_collision( feeler_start, end_offset_direction, feeler_length, &worst_length );\r\n\r\n\t\t\t\tif( !collision )\r\n\t\t\t\t{\r\n\t\t\t\t\tscore += AVOID_COLLISION_SCORE;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Score for minimal turn distance.\r\n\t\t\t\tscore -= Mth::Abs( step_angle ) * TURN_ANGLE_SCORE_MULT;\r\n\r\n\t\t\t\tif( collision )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Score for larger distances, use the percentage of this distance over the original collision distance.\r\n\t\t\t\t\tfloat this_dist\t= worst_length;\r\n\t\t\t\t\tif( this_dist > dist )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfloat pc = ( this_dist / dist ) * 100.0f;\r\n\t\t\t\t\t\tscore += pc * DISTANCE_PERCENTAGE_SCORE_MULT;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Score for being a turn in the same direction as last time.\r\n\r\n\t\t\t\t// Is this the best score yet?\r\n\t\t\t\tif( score > best_score )\r\n\t\t\t\t{\r\n\t\t\t\t\tbest_score = score;\r\n\t\t\t\t\tbest_angle = step_angle;\r\n\t\t\t\t}\r\n\t\t\t\tstep_angle += Mth::DegToRad( 3.0f );\r\n\t\t\t}\r\n\r\n\t\t\t// Check for being in a potentially nasty situation.\r\n\t\t\tif( best_score < PANIC_SCORE )\r\n\t\t\t{\r\n\t\t\t\t// Increment panic counter, give a small chance to fix itself.\r\n\t\t\t\t++m_path_follow_panic_counter;\r\n\t\t\t\tif( m_path_follow_panic_counter > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_path_follow_panic_counter = 0;\r\n\t\t\t\t\tswitch_to_node_based_path_following();\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Test - Immediately snap the direction to the best alternative.\r\n\t\t\tif( best_score > 0.0f )\r\n\t\t\t{\r\n\t\t\t\tcos_angle\t= cosf( best_angle );\r\n\t\t\t\tsin_angle\t= sinf( best_angle );\r\n\r\n\t\t\t\tend_offset_direction[X] = cos_angle * m_facing[X] - sin_angle * m_facing[Z];\r\n\t\t\t\tend_offset_direction[Z] = sin_angle * m_facing[X] + cos_angle * m_facing[Z];\r\n\r\n\t\t\t\tprintf( \"Changing heading by %f degrees\\n\", best_angle );\r\n\r\n\t\t\t\tm_facing[X]\t\t\t\t= end_offset_direction[X];\r\n\t\t\t\tm_facing[Z]\t\t\t\t= end_offset_direction[Z];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::cleanup_node_based_path_following( void )\r\n{\r\n\tdelete [] mp_nav_nodes;\r\n\tmp_nav_nodes = NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::switch_to_node_based_path_following( void )\r\n{\r\n\t// Try various distances, the further the better.\r\n\tfloat target_distance = FEET_TO_INCHES( 500.0f );\r\n\r\n\twhile( target_distance > FEET_TO_INCHES( 50.0f ))\r\n\t{\r\n\t\t// Generate a distant target position.\r\n\t\tMth::Vector start_pos\t= m_pos + Mth::Vector( 0.0f, 60.0f, 0.0f, 0.0f );\r\n\t\tMth::Vector target_pos\t= start_pos + ( m_facing * target_distance );\r\n\r\n\t\tCFeeler feeler;\r\n\t\tfeeler.m_start\t= target_pos + Mth::Vector( 0.0f, 12000.0f, 0.0f, 0.0f );\r\n\t\tfeeler.m_end\t= target_pos - Mth::Vector( 0.0f, 12000.0f, 0.0f, 0.0f );\r\n\r\n\t\tif( feeler.GetCollision())\r\n\t\t{\r\n\t\t\t// Adjust the target position to be 5 feet above ground level.\r\n\t\t\ttarget_pos = feeler.GetPoint() + Mth::Vector(  0.0f, 60.0f, 0.0f, 0.0f );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Hmm, maybe should try different distances here.\r\n\t\t\t// For now, Just go with what we started with.\r\n\t\t}\r\n\r\n\t\tCNavNode* p_target_node = CalculateNodePath( start_pos, target_pos );\r\n\r\n\t\tif( p_target_node == NULL )\r\n\t\t{\r\n\t\t\t// Try with a shorter distance.\r\n\t\t\ttarget_distance -= FEET_TO_INCHES( 50.0f );\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\t// A path was found, so set up the state accordingly. First count how many nodes on the path.\r\n\t\tCNavNode*\tp_node_counter\t= p_target_node;\r\n\t\tint\t\t\tnum_nodes\t\t= 1;\r\n\t\twhile( p_node_counter->GetAStarNode()->mp_parent != NULL )\r\n\t\t{\r\n\t\t\t++num_nodes;\r\n\t\t\tp_node_counter = p_node_counter->GetAStarNode()->mp_parent;\r\n\t\t}\r\n\r\n\t\t// Allocate memory for the path.\r\n\t\tif( mp_nav_nodes )\r\n\t\t{\r\n\t\t\tdelete [] mp_nav_nodes;\r\n\t\t}\r\n\t\tmp_nav_nodes = new CNavNode*[num_nodes];\r\n\r\n\t\t// Fill in the array.\r\n\t\tm_nav_node_index = 0;\r\n\t\twhile( p_target_node )\r\n\t\t{\r\n\t\t\tmp_nav_nodes[m_nav_node_index++] = p_target_node;\r\n\t\t\tp_target_node = p_target_node->GetAStarNode()->mp_parent;\r\n\t\t}\r\n\t\t--m_nav_node_index;\r\n\r\n\t\t// mp_nav_nodes[m_nav_node_index] now points to the first node we need to visit.\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CHorseComponent::do_node_based_path_following( void )\r\n{\r\n\t// Are we within a reasonable distance of our current node?\r\n\tMth::Vector target_node_pos = mp_nav_nodes[m_nav_node_index]->GetPos() + Mth::Vector( 0.0f, 36.0f, 0.0f, 0.0f );\r\n\tfloat dist = Mth::Distance( m_pos, target_node_pos );\r\n\tif( dist < ( 12.0f * 6.0f ))\r\n\t{\r\n\t\t// Yes we are. Exit if no more nodes.\r\n\t\tif( m_nav_node_index == 0 )\r\n\t\t{\r\n\t\t\tcleanup_node_based_path_following();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Switch to the next node.\r\n\t\t--m_nav_node_index;\r\n\t}\r\n\r\n\r\n\tfor( int l = m_nav_node_index; l >= 0; --l )\r\n\t{\r\n\t\tGfx::AddDebugStar( mp_nav_nodes[l]->GetPos(), 12.0f, MAKE_RGB( 255, 200, 0 ), 1 );\r\n\r\n\t\tif( l > 0 )\r\n\t\t{\r\n\t\t\tGfx::AddDebugLine( mp_nav_nodes[l]->GetPos(), mp_nav_nodes[l - 1]->GetPos(), MAKE_RGB( 255, 255, 255 ), MAKE_RGB( 255, 255, 255 ), 1 );\r\n\t\t}\r\n\t}\r\n\r\n\t// Head to the next node.\r\n\tMth::Vector heading = mp_nav_nodes[m_nav_node_index]->GetPos() - m_pos;\r\n\theading[Y] = 0.0f;\r\n\theading[W] = 0.0f;\r\n\theading.Normalize();\r\n\r\n\tm_facing[X]\t= heading[X];\r\n\tm_facing[Z]\t= heading[Z];\r\n}\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/HorseComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       HorseComponent.h\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ??/??/??\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_HORSECOMPONENT_H__\r\n#define __COMPONENTS_HORSECOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/collision/collcache.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/movablecontactcomponent.h>\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <sk/engine/rectfeeler.h>\r\n#include <sk/engine/feeler.h>\r\n#include <sk/objects/navigation.h>\r\n\r\n#define\t\tCRC_HORSE CRCD(0x9d65d0e7,\"Horse\")\r\n#define\t\tGetHorseComponent() ((Obj::CHorseComponent*)GetComponent(CRC_HORSE))\r\n#define\t\tGetHorseComponentFromObject(pObj) ((Obj::CHorseComponent*)(pObj)->GetComponent(CRC_HORSE))\r\n\t\t \r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CInputComponent;\r\n\r\n#define vVP_GRAVITATIONAL_ACCELERATION\t\t\t\t\t\t\t\t(386.4f)\r\n#define vVP_MAX_NUM_GEARS\t\t\t\t\t\t\t\t\t\t\t(6)\r\n#define vVP_NUM_COLLIDERS\t\t\t\t\t\t\t\t\t\t\t(2)\r\n\r\nclass CHorseComponent : public CBaseComponent\r\n{\r\n\tenum EStateType\r\n\t{\r\n\t\tWALKING_GROUND,\r\n\t\tWALKING_AIR,\r\n\t\tWALKING_HOP,\r\n\t\tWALKING_HANG,\r\n\t\tWALKING_LADDER,\r\n\t\tWALKING_ANIMWAIT\r\n\t};\r\n\r\n\tenum EAnimScaleSpeed\r\n\t{\r\n\t\tOFF,\r\n\t\tRUNNING,\r\n        HANGMOVE,\r\n\t\tLADDERMOVE\r\n\t};\r\n\r\n\t// inorder to interface with models and skeletons, the number of wheels must be hardcoded to four\r\n\tenum { vVP_NUM_WHEELS = 4 };\r\n\t\r\n\t// HACK for control\r\n\tstruct SControls {\r\n\t\t// steering; between -1.0 and 1.0\r\n\t\tfloat steering;\r\n\t\t\r\n\t\t// Spurring the horse on, or reining it in, values in range [-1.0, 1.0].\r\n\t\tfloat spur_rein;\r\n\r\n\t\t// throttle\r\n\t\tbool throttle;\r\n\t\t\r\n\t\t// brake\r\n\t\tbool brake;\r\n\t\t\r\n\t\t// handbrake\r\n\t\tbool handbrake;\r\n\t\t\r\n\t\t// reverse\r\n\t\tbool reverse;\r\n\t};\r\n\t\r\n\t\r\n\tstruct SCollisionPoint\r\n\t{\r\n\t\t// world position\r\n\t\tMth::Vector pos;\r\n\t\t\r\n\t\t// impact normal\r\n\t\tMth::Vector normal;\r\n\t\t\r\n\t\t// depth of collision as defined as the dot between the displacement from the nearest collider corner and the collision normal\r\n\t\tfloat depth;\r\n\t\t\r\n\t\t// normal impulse accumulator; used to set the maximum friction\r\n\t\tfloat normal_impulse;\r\n\t\t\r\n\t\tbool line;\r\n\t};\r\n\t\r\n\tstruct SCollider\r\n\t{\r\n\t\t// the rectangle defining the collider in body space\r\n\t\tMth::Rectangle body;\r\n\t\t\r\n\t\t// that rectangle transformed into world space\r\n\t\tMth::Rectangle world;\r\n\t\tMth::Vector first_edge_direction_world;\r\n\t\tMth::Vector second_edge_direction_world;\r\n\t\t\r\n\t\t// a few precomputable values\r\n\t\tfloat first_edge_length;\r\n\t\tfloat second_edge_length;\r\n\t};\r\n\t\r\npublic:\r\n    CHorseComponent();\r\n    virtual ~CHorseComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tFinalize (   );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tMoveToNode ( Script::CStruct* p_node );\r\n\t\r\n\tconst Mth::Vector&\t\t\t\tGetPos( void )\t\t\t\t\t\t{ return GetObject()->GetPos(); }\r\n\tconst Mth::Vector&\t\t\t\tGetVel( void )\t\t\t\tconst\t{ return m_vel; }\r\n\r\n\tMth::Matrix&\t\t\t\t\tGetMatrix( void )\t\t\t\t\t{ return GetObject()->GetMatrix(); }\r\n\tMth::Matrix&\t\t\t\t\tGetDisplayMatrix( void )\t\t\t{ return GetObject()->GetDisplayMatrix(); }\r\n\r\n\tbool\t\t\t\t\t\t\tAcceptRiderMount( CCompositeObject*\tp_rider );\r\n\tbool\t\t\t\t\t\t\tAcceptRiderDismount( CCompositeObject*\tp_rider );\r\n\tbool\t\t\t\t\t\t\tShouldUpdateCamera( void );\r\n\tCCompositeObject*\t\t\t\tGetRider( void )\t\t\t\t\t{ return mp_rider; }\r\n\r\n\tuint32\t\t\t\t\t\t\tGetAnimation( void );\r\n\r\nprivate:\r\n\t\r\n    void\t\t\t\t\t\t\tdraw_debug_rendering (   ) const;\r\n\t\r\nprivate:\r\n\t\r\n\tObj::CNavNode**\t\t\t\t\tmp_nav_nodes;\t\t\t// List of pointers to navigation nodes if following a path.\r\n\tint\t\t\t\t\t\t\t\tm_nav_node_index;\t\t// Current index within the list (moves to zero as path progesses).\r\n\r\n\t// dynamic state variables\r\n\t\r\n\t// dependent state variables\r\n\t\r\n\t// angular orientation in 3x3 matrix form\r\n\tMth::Matrix m_orientation_matrix;\r\n\t\r\n\t// linear velocity\r\n\tMth::Vector m_vel;\r\n\t\r\n\t// rotational velocity\r\n\tMth::Vector m_rotvel;\r\n\t\r\n\t// accumulators\r\n\t\r\n\t\r\n\t// length of current frame\r\n\tfloat m_time_step;\r\n\t\r\n\t// constant characteristics\r\n\t\r\n\t\r\n\t// subelements\r\n\t\r\n\t// input state\r\n//\tSControls m_controls;\r\n\t\r\n\t// collision cache\r\n\tNx::CCollCache m_collision_cache;\r\n\t\r\n\t\r\n\t// shared objects\r\n\t\r\n\t// shared collision point array\r\n\tstatic SCollisionPoint sp_collision_points[4 * (Nx::MAX_NUM_2D_COLLISIONS_REPORTED + 1)];\r\n\t\r\n\tCCompositeObject*\t\t\t\tmp_rider;\r\n\r\n\t// peer components\r\n\tCSkeletonComponent*\t\t\t\tmp_skeleton_component;\r\n\tCInputComponent*\t\t\t\tmp_input_component;\r\n\tCModelComponent*\t\t\t\tmp_model_component;\r\n\tCAnimationComponent*\t\t\tmp_animation_component;\r\n\tCMovableContactComponent*\t\tmp_movable_contact_component;\r\n\t\r\n\t// debug\r\n\tint m_draw_debug_lines;\r\n\r\n\t// Stuff from CWalkComponent.\r\n\r\n\tstatic float\t\t\t\t\ts_get_param ( uint32 checksum );\r\n\r\n\r\n\tenum\r\n\t{\r\n\t\tvNUM_FEELERS = 7,\r\n\t\tvNUM_BARRIER_HEIGHT_FEELERS = 7\r\n\t};\r\n\r\n\tstruct SContact\r\n\t{\r\n\t\t// If this contact is in collision with the environment.\r\n\t\tbool\t\t\t\t\t\tin_collision;\r\n\t\t\r\n\t\t// The horizontal normal of the collided geometry.\r\n\t\tMth::Vector\t\t\t\t\tnormal;\r\n\t\t\r\n\t\t// Distance from the collision as a factor of the feeler length.\r\n\t\tfloat\t\t\t\t\t\tdistance;\r\n\t\t\r\n\t\t// If the collision in this direction is determined to be low enough to jump.\r\n\t\tbool\t\t\t\t\t\tjumpable;\r\n\t\t\r\n\t\t// Movement of the object we're in contact with (not accounting for its rotation) along its horizontal normal.\r\n\t\tfloat\t\t\t\t\t\tmovement;\r\n\t\t\r\n\t// The walker looks around him in vNUM_FEELERS directions and stores the results here.  The final contact is felt for along the movement of\r\n\t// the origin, and is only used while in the air.\r\n\t} mp_contacts [ vNUM_FEELERS + 1 ];\r\n\r\n\t/////////////////////////////////\r\n\t// WALKING_AIR state variables\r\n\t\r\n\t// The forward horizontal direction of the jump which, when coming out of skating or because of in-air velocity control, diverges from the direction of velocity\r\n\tMth::Vector\t\t\t\t\t\tm_primary_air_direction;\r\n\t\r\n\t// This term of our horizontal velocity is due to leaping from a movable contact, and is not adjustable via in-air control.\r\n\tMth::Vector\t\t\t\t\t\tm_uncontrollable_air_horizontal_vel;\r\n\r\n\tvoid\t\t\t\t\t\t\tget_controller_input( void );\r\n\tvoid\t\t\t\t\t\t\tgo_on_ground_state( void );\r\n\tvoid\t\t\t\t\t\t\tgo_in_air_state( void );\r\n\tvoid\t\t\t\t\t\t\tlerp_upright( void );\r\n\tvoid\t\t\t\t\t\t\tuber_frig( void );\r\n\tvoid\t\t\t\t\t\t\taccount_for_movable_contact( void );\r\n\tvoid\t\t\t\t\t\t\tsetup_collision_cache( void );\r\n\tfloat\t\t\t\t\t\t\tcalculate_desired_speed( void );\r\n\tfloat\t\t\t\t\t\t\tadjust_desired_speed_for_slope( float desired_speed );\r\n\tbool\t\t\t\t\t\t\tadjust_horizontal_vel_for_environment( bool wall_push_active );\r\n\tvoid\t\t\t\t\t\t\tcopy_state_into_object( void );\r\n\tvoid\t\t\t\t\t\t\tadjust_facing_for_adjusted_horizontal_vel( void );\r\n\tvoid\t\t\t\t\t\t\tcalculate_horizontal_speed_and_facing( float &horizontal_speed );\r\n\tMth::Vector\t\t\t\t\t\tcalculate_feeler_offset_direction ( int contact );\r\n\tvoid\t\t\t\t\t\t\tadjust_curb_float_height( void );\r\n\tbool\t\t\t\t\t\t\tforced_run( void );\r\n\tvoid\t\t\t\t\t\t\trespond_to_ground( void );\r\n\tvoid\t\t\t\t\t\t\tleave_movable_contact_for_air( Mth::Vector& horizontal_vel, float& vertical_vel );\r\n\tvoid\t\t\t\t\t\t\tjump( float strength );\r\n\tvoid\t\t\t\t\t\t\tset_state( EStateType state );\r\n\tvoid\t\t\t\t\t\t\tcontrol_horizontal_vel( void );\r\n\tvoid\t\t\t\t\t\t\tcheck_for_landing( const Mth::Vector& previous_pos, const Mth::Vector& final_pos );\r\n\tvoid\t\t\t\t\t\t\tadjust_vertical_vel_for_ceiling( void );\r\n\tvoid\t\t\t\t\t\t\tposition_rider( void );\r\n\r\n\tvoid\t\t\t\t\t\t\tdo_path_following( void );\r\n\tvoid\t\t\t\t\t\t\tswitch_to_node_based_path_following( void );\r\n\tvoid\t\t\t\t\t\t\tcleanup_node_based_path_following( void );\r\n\tvoid\t\t\t\t\t\t\tdo_node_based_path_following( void );\r\n\r\n\tint\t\t\t\t\t\t\t\tm_path_follow_panic_counter;\r\n\r\n\t// Accumulates position offset due to a movable contact during an animation wait.\r\n\tMth::Vector\t\t\t\t\t\tm_offset_due_to_movable_contact;\r\n\r\n\tEStateType\t\t\t\t\t\tm_state;\r\n\r\n\t// Time stamp of when our state last changed.\r\n\tTmr::Time\t\t\t\t\t\tm_state_timestamp;\r\n\t\r\n\t// State we changed from when m_state_timestamp was last set.\r\n\tEStateType\t\t\t\t\t\tm_previous_state;\r\n\r\n\t// Certain things such as rotation rate and camera lerp are increased when this is set.\r\n\tbool\t\t\t\t\t\t\tm_run_toggle;\r\n\r\n\tstruct SWallPushTest\r\n\t{\r\n\t\t// Whether we currently testing.\r\n\t\tbool\t\t\t\t\t\tactive;\r\n\t\t\r\n\t\t// Time at which this test began.\r\n\t\tTmr::Time\t\t\t\t\ttest_start_time;\r\n\t\t\r\n\t// Data used to detect when a player is pushing into a wall in order to climb it.\r\n\t}\t\t\t\t\t\t\t\tm_wall_push_test;\r\n\r\n\t// Normal of the ground on which we are standing.  Only meaningful when on the ground.  Set the previous frame.\r\n\tMth::Vector\t\t\t\t\t\tm_ground_normal;\r\n\r\n\t// Used to slerp the display matrix towards the actual matrix (can't use CCompositeObject::m_display_matrix since that is reset every frame).\r\n\tMth::Matrix\t\t\t\t\t\tm_display_slerp_matrix;\r\n\r\n\t// The collision cache used.\r\n\tNx::CCollCache*\t\t\t\t\tmp_collision_cache;\r\n\r\n\t// When doing anim speed scaling when running, this is set to the run speed which corresponds to the current animation playing at standard speed.\r\n\tfloat\t\t\t\t\t\t\tm_anim_standard_speed;\r\n\t\r\n\t// A copy of the latest feeler which contacted the groud under us.\r\n\tCFeeler\t\t\t\t\t\t\tm_last_ground_feeler;\r\n\tbool\t\t\t\t\t\t\tm_last_ground_feeler_valid;\r\n\r\n\t// The target fraction of maximum speed [0.0, 1.0] as modified by let analog stick up down movement.\r\n\tfloat\t\t\t\t\t\t\tm_target_speed;\r\n\tfloat\t\t\t\t\t\t\tm_target_speed_adjustment;\r\n\r\n\t// Extracted from the object at frame start and back into the object at frame end.\r\n\tMth::Vector\t\t\t\t\t\tm_pos;\r\n\tMth::Vector\t\t\t\t\t\tm_horizontal_vel;\r\n\tfloat\t\t\t\t\t\t\tm_vertical_vel;\r\n\tMth::Vector\t\t\t\t\t\tm_facing;\r\n\tMth::Vector\t\t\t\t\t\tm_upward;\r\n\r\n\t// The control-based change in heading this frame. Used mainly for path following decisions.\r\n\tfloat\t\t\t\t\t\t\tm_delta_angle;\r\n\r\n\t// Type of animation speed scaling to do.\r\n\tEAnimScaleSpeed\t\t\t\t\tm_anim_scale_speed;\r\n\t\r\n\t// Horizontal speed for the purposes of animation speed scaling.\r\n\tfloat\t\t\t\t\t\t\tm_anim_effective_speed;\r\n\t\r\n\t// Factor multiplied by all velocities.  Set by script.\r\n\tfloat\t\t\t\t\t\t\tm_script_drag_factor;\r\n\r\n\t// Current frame's frame length.\r\n\tfloat\t\t\t\t\t\t\tm_frame_length;\r\n\r\n\t// Current frame's control input.\r\n\tMth::Vector\t\t\t\t\t\tm_control_direction;\r\n\tfloat\t\t\t\t\t\t\tm_control_magnitude;\r\n\tbool\t\t\t\t\t\t\tm_control_pegged;\r\n\r\n \t// Keep track of the previous state of the dpad controls so that we can ramp up to a run speed over time.\r\n\tbool\t\t\t\t\t\t\tm_dpad_used_last_frame;\r\n\t\r\n\t// Keep track of when we first started using the dpad so that we can ramp up to a run speed over time.\r\n\tTmr::Time\t\t\t\t\t\tm_dpad_use_time_stamp;\r\n\r\n\t// Cache our position at the frame's start\r\n\tMth::Vector\t\t\t\t\t\tm_frame_start_pos;\r\n\t\r\n\t// Script event reporting our current state.  Set during each frame update and sent at the end of the update.\r\n\tuint32\t\t\t\t\t\t\tm_frame_event;\r\n\t\r\n\t// Last frame's frame event.\r\n\tuint32\t\t\t\t\t\t\tm_last_frame_event;\r\n\r\n\t// Used to lock control in the forward direction (during a camera flush request)\r\n\tbool\t\t\t\t\t\t\tm_forward_control_lock;\r\n\r\n\t// When on ground, the walker is often floated above the ground in an attempt to smooth out stair/curb climbs.\r\n\tfloat\t\t\t\t\t\t\tm_curb_float_height;\r\n\t\r\n\t// If m_curb_float_height was adjusted this frame.  If not, we lerp it to zero.\r\n\tbool\t\t\t\t\t\t\tm_curb_float_height_adjusted;\r\n\r\n};\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ninline float CHorseComponent::s_get_param( uint32 checksum )\r\n{\r\n\tScript::CStruct* p_params = Script::GetStructure(CRCD(0x1b38036f,\"GunslingerHorseParameters\"));\r\n\tDbg_Assert(p_params);\r\n\t\r\n\tfloat param;\r\n\tp_params->GetFloat(checksum, &param, Script::ASSERT);\r\n\treturn param;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ninline bool CHorseComponent::forced_run( void )\r\n{\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ninline void CHorseComponent::set_state ( EStateType state )\r\n{\r\n    if (state == m_state) return;\r\n\t\r\n\tm_previous_state = m_state;\r\n    \r\n    if (m_state == WALKING_GROUND)\r\n    {\r\n        m_wall_push_test.active = false;\r\n\t\tm_run_toggle = false;\r\n    }\r\n\t\r\n\tif (m_state != WALKING_GROUND && m_state != WALKING_AIR)\r\n\t{\r\n\t\tm_dpad_used_last_frame = false;\r\n\t}\r\n\t\r\n\tm_state = state;\r\n\tm_state_timestamp = Tmr::GetTime();\r\n\t\r\n\tif (m_state == WALKING_ANIMWAIT)\r\n\t{\r\n\t\tm_offset_due_to_movable_contact.Set();\r\n\t}\r\n}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/InputComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       InputComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/18/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/vibrationcomponent.h>\r\n#include <gel/components/trickcomponent.h>\r\n\r\n#include <gfx/2d/screenelemman.h>\r\n\t\t\t\t\t\t\t\t\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <sk/modules/frontend/frontend.h>\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#include <gel/objtrack.h>\r\n\r\nnamespace Obj\r\n{\r\n\textern bool DebugSkaterScripts;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CInputComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CInputComponent);\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCInputComponent::CInputComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_INPUT);\r\n\t\r\n\tm_input_handler = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCInputComponent::~CInputComponent()\r\n{\r\n\tif (m_input_handler)\r\n\t{\r\n\t\tif (m_input_handler->InList())\r\n\t\t{\r\n\t\t\tm_input_handler->Remove();\r\n\t\t}\r\n\t\tdelete m_input_handler;\r\n\t}\r\n\tif (m_input_handler2)\r\n\t{\r\n\t\tif (m_input_handler2->InList())\r\n\t\t{\r\n\t\t\tm_input_handler2->Remove();\r\n\t\t}\r\n\t\tdelete m_input_handler2;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CInputComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tint i;\r\n\tif (pParams->GetInteger(CRCD(0x67e6859a, \"player\"), &i))\r\n\t{\r\n\t\tBindToController(Mdl::Skate::Instance()->m_device_server_map[i]);\r\n\t}\r\n\telse if (pParams->GetInteger(CRCD(0xb30d9965, \"controller\"), &i))\r\n\t{\r\n\t\tBindToController(i);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CInputComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CInputComponent::Update()\r\n{\r\n\t// Doing nothing, so tell code to do nothing next time around\r\n\tSuspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CInputComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | Input_Debounce | \r\n\t\tcase CRCC(0xbf7d6c46, \"Input_Debounce\"):\r\n\t\t{\r\n\t\t\tuint32 ButtonChecksum = 0;\r\n\t\t\tif (!pParams->GetChecksum(NO_NAME, &ButtonChecksum)) break;\r\n\r\n\t\t\tfloat time = 1.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0x906b67ba, \"time\"), &time);\r\n\t\t\tDUMPF(time);\r\n\r\n\t\t\tint\tclear = 0;\r\n\t\t\tpParams->GetInteger(CRCD(0x1a4e0ef9, \"clear\"), &clear);\r\n\r\n\t\t\tDebounce(ButtonChecksum, time, clear);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | DisablePlayerInput | \r\n\t\tcase CRCC(0x6e24f5fd, \"DisablePlayerInput\"):\r\n\t\t\tDisableInput();\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | EnablePlayerInput | \r\n\t\tcase CRCC(0x56c6c0cd, \"EnablePlayerInput\"):\t  \r\n\t\t\tEnableInput();\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | NetDisablePlayerInput | \r\n\t\tcase CRCC(0x6df51774, \"NetDisablePlayerInput\"):\r\n\t\t\tNetDisableInput();\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | NetEnablePlayerInput | \r\n\t\tcase CRCC(0x31c6454f, \"NetEnablePlayerInput\"):\t  \r\n\t\t\tNetEnableInput();\r\n\t\t\tbreak;\r\n\t\t\t\t\r\n\t\t// @script | PlayerInputIsDisabled\t| return true if the player input is disabled\r\n\t\tcase CRCC(0x660746a, \"PlayerInputIsDisabled\"):\r\n\t\t\treturn IsInputDisabled() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\t\r\n\r\n        // @script | LeftPressed | true if left is being pressed on the pad\r\n\t\tcase CRCC(0x78238598, \"LeftPressed\"):\r\n\t\t\treturn m_pad.m_left.GetPressed() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | RightPressed | true if right is being pressed on the pad\r\n\t\tcase CRCC(0x1d604a9d, \"RightPressed\"):\r\n\t\t\treturn m_pad.m_right.GetPressed() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | UpPressed | true if up is being pressed on the pad\r\n\t\tcase CRCC(0x89aa9b5f, \"UpPressed\"):\r\n\t\t\treturn m_pad.m_up.GetPressed() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | DownPressed | true if down is being pressed on the pad\r\n\t\tcase CRCC(0x83028fc5, \"DownPressed\"):\r\n\t\t\treturn m_pad.m_down.GetPressed() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | HeldLongerThan | true if the specified button has been\r\n        // held longer than the specified amount of time\r\n        // @parm name | Button | button name\r\n        // @uparm 1.0 | time value (default is milliseconds)\r\n        // @flag seconds | time in seconds\r\n        // @flag frames | time in frames\r\n\t\tcase CRCC(0x2366469c, \"HeldLongerThan\"):\r\n\t\t{\r\n\t\t\tuint32 ButtonChecksum;\r\n\t\t\tpParams->GetChecksum(CRCD(0xc5f953c2, \"Button\"), &ButtonChecksum, Script::ASSERT);\r\n\t\t\t\t\r\n\t\t\tfloat time;\r\n\t\t\tpParams->GetFloat(NO_NAME, &time, Script::ASSERT);\r\n\t\r\n\t\t\tTmr::Time TestTime = 0;\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0xd029f619, \"seconds\")) || pParams->ContainsFlag(CRCD(0x49e0ee96, \"second\")))\r\n\t\t\t{\r\n\t\t\t\tTestTime = static_cast< Tmr::Time >(time * 1000.0f);\r\n\t\t\t}\t\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0x19176c5, \"frames\")) || pParams->ContainsFlag(CRCD(0x4a07c332, \"frame\")))\r\n\t\t\t{\r\n\t\t\t\tTestTime =static_cast< Tmr::Time >(time * (1000.0f / 60.0f));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tTestTime =static_cast< Tmr::Time >(time);\t\r\n\t\t\t}\r\n\r\n\t\t\tCSkaterButton* pButt = m_pad.GetButton(ButtonChecksum);\r\n\t\t\tif (pButt)\r\n\t\t\t{\r\n\t\t\t\treturn (pButt->GetPressed() && pButt->GetPressedTime() > TestTime) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        // @script | EnableInputEvents |  Enable the sending of TRIGGER_ and RELEASE events from an Input component\r\n\t\tcase\tCRCC(0x1090a150,\"EnableInputEvents\"):\r\n\t\t{\r\n\t\t\tm_input_events_enabled = true;\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        // @script | DisableInputEvents |  Disable the sending of TRIGGER_ and RELEASE events from an Input component\r\n\t\tcase\tCRCC(0x28729460,\"DisableInputEvents\"):\r\n\t\t{\r\n\t\t\tm_input_events_enabled = false;\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CInputComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CInputComponent::GetDebugInfo\"));\r\n\t\r\n\tif (m_input_handler && m_input_handler->m_Device)\r\n\t{\r\n\t\tp_info->AddInteger(\"port\", m_input_handler->m_Device->GetPort());\r\n\t\tp_info->AddInteger(\"slot\", m_input_handler->m_Device->GetSlot());\r\n\t\tp_info->AddInteger(\"index\", m_input_handler->m_Device->GetIndex());\r\n\t\tp_info->AddInteger(\"m_input_events_enabled\",m_input_events_enabled);\r\n\t}\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CInputComponent::BindToController ( int controller )\r\n{\r\n\tif (!m_input_handler)\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\t\tm_input_handler = new Inp::Handler< CInputComponent >(0, CInputComponent::s_input_logic_code, *this, Tsk::BaseTask::Node::vNORMAL_PRIORITY - 1);\r\n\t\tInp::Manager::Instance()->AddHandler(*m_input_handler);\r\n\t\tm_input_handler2 = new Inp::Handler< CInputComponent >(1, CInputComponent::s_input_logic_code2, *this, Tsk::BaseTask::Node::vNORMAL_PRIORITY - 1);\r\n\t\tInp::Manager::Instance()->AddHandler(*m_input_handler2);\r\n\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\r\n\tInp::Manager::Instance()->ReassignHandler(*m_input_handler, controller);\r\n\tInp::Manager::Instance()->ReassignHandler(*m_input_handler2, 1);\r\n\t\r\n\tif (CVibrationComponent* p_vibration_component = GetVibrationComponentFromObject(GetObject()))\r\n\t{\r\n\t\tp_vibration_component->SetDevice(m_input_handler->m_Device);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CInputComponent::Debounce ( uint32 Checksum, float time, bool clear )\r\n{\r\n\tCSkaterButton* button = m_pad.GetButton(Checksum);\r\n\t\r\n\tfloat debounce_time = Tmr::GetTime() + (time * 1000.0f);\r\n\t\r\n\tif (CTrickComponent* p_trick_component = GetTrickComponentFromObject(GetObject()))\r\n\t{\r\n\t\tp_trick_component->Debounce(Inp::GetButtonIndex(Checksum), debounce_time);\r\n\t}\r\n\t\r\n\tbutton->SetDebounce(static_cast< int >(debounce_time));\r\n\t\r\n\tif (clear)\r\n\t{\r\n\t\tbutton->SetPressed(false);\r\n\t\tbutton->ClearTrigger();\r\n\t\tbutton->ClearRelease();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CInputComponent::ignore_button_presses (   )\r\n{\r\n\t// if any operable menus are up in net games, ignore input\r\n\tif( !GameNet::Manager::Instance()->InNetGame()) return false;\r\n\t\r\n\tif (Front::CScreenElementManager::Instance()->GetElement(CRCD(0x2edb780f, \"controller_unplugged_dialog_anchor\"))) return true;\r\n\t\r\n\tFront::CScreenElement* p_root_window\r\n\t\t= Front::CScreenElementManager::Instance()->GetElement(CRCD(0x56a1eae3, \"root_window\"));\r\n\t\r\n\tif (p_root_window)\r\n\t{\r\n\t\tScript::CStruct* pTags = new Script::CStruct();\r\n\t\tp_root_window->CopyTagsToScriptStruct(pTags);\r\n\t\t\r\n\t\tuint32 menu_state;\r\n\t\tpTags->GetChecksum(CRCD(0xcdc00e63, \"menu_state\"), &menu_state);\r\n\t\tdelete pTags;\r\n\t\t\r\n\t\tif (menu_state == CRCD(0xf649d637, \"on\")) return true;\r\n\t}\r\n\r\n\tif (Front::CScreenElementManager::Instance()->GetElement(CRCD(0x31631b98, \"keyboard_anchor\"))) return true;\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CInputComponent::handle_input ( Inp::Data* input )\r\n{\r\n\tif (GetObject()->IsPaused()) return;\r\n\t\r\n\tbuild_input_mask(input);\r\n\r\n\tbool ignore = ignore_button_presses();\r\n\tif (IsInputDisabled() || ignore)\r\n\t{\r\n\t\tm_pad.Zero();\r\n\t\tif (ignore)\r\n\t\t{\r\n\t\t\tm_input_mask = 0;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tm_pad.Update(input, DebugSkaterScripts && GetObject()->GetID() == 0);\r\n\t\t#else\r\n\t\tm_pad.Update(input);\r\n\t\t#endif\r\n\t}\r\n}\r\n\r\n\r\nvoid CInputComponent::handle_input2 ( Inp::Data* input )\r\n{\r\n\tif (GetObject()->IsPaused()) return;\r\n\t\r\n//\tbuild_input_mask(input);\r\n\r\n\tbool ignore = ignore_button_presses();\r\n\tif (IsInputDisabled() || ignore)\r\n\t{\r\n\t\tm_pad2.Zero();\r\n\t\tif (ignore)\r\n\t\t{\r\n\t\t\tm_input_mask = 0;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tm_pad2.Update(input, DebugSkaterScripts && GetObject()->GetID() == 0);\r\n\t\t#else\r\n\t\tm_pad2.Update(input);\r\n\t\t#endif\r\n\t}\r\n}\r\n\r\n\r\n\t\r\nvoid CInputComponent::update_input_mask ( Inp::Data* input, Inp::Data::AnalogButtonIndex button, Inp::Data::AnalogButtonMask mask, uint32 trigger_event, uint32 release_event, CSkaterButton* skater_button )\r\n{\r\n\tif (skater_button && Tmr::GetTime() < skater_button->GetDebounceTime()) return;\r\n\t\r\n\tif (input->m_Event[button])\r\n\t{\r\n\t\tif (!(m_last_mask & mask))\r\n\t\t{\r\n\t\t\t\t// Fire Event to self, trigger_event\r\n\t\t\tif (m_input_events_enabled && !m_input_disabled && !m_net_input_disabled)\r\n\t\t\t{\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t//uint32\tid = GetObject()->GetID();\r\n\t\t\t\t\t\t//Obj::CTracker::Instance()->LaunchEvent(trigger_event, id, id);\r\n\t\t\t\t\t\tGetObject()->SelfEvent(trigger_event);\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_input_mask |= mask;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ((m_last_mask & mask))\r\n\t\t{\r\n\t\t\tif (m_input_events_enabled && !m_input_disabled && !m_net_input_disabled)\r\n\t\t\t{\r\n\t\t\t\t\t\t// Fire Event to self, release_event\r\n\t\t\t\t\t\t//uint32\tid = GetObject()->GetID();\r\n\t\t\t\t\t\t//Obj::CTracker::Instance()->LaunchEvent(release_event, id, id);\r\n\t\t\t\t\t\tGetObject()->SelfEvent(release_event);\t\t\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CInputComponent::build_input_mask ( Inp::Data* input )\r\n\t{\r\n\tm_last_mask = m_input_mask;\r\n\tm_input_mask = 0;\r\n\tupdate_input_mask(input, Inp::Data::vA_UP,\t\t\tInp::Data::mA_UP, \t\tCRCD(0x5c8faa09,\"Trigger_UP\"),        CRCD(0xb27804a2,\"Release_UP\"),\t\t&m_pad.m_up\t\t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_DOWN,\t\tInp::Data::mA_DOWN, \tCRCD(0xd26adae9,\"Trigger_DOWN\"),      CRCD(0xaef7dfd3,\"Release_DOWN\"),      &m_pad.m_down\t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_LEFT,\t\tInp::Data::mA_LEFT, \tCRCD(0xb4f2adba,\"Trigger_LEFT\"),      CRCD(0xc86fa880,\"Release_LEFT\"),      &m_pad.m_left\t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_RIGHT,\t\tInp::Data::mA_RIGHT, \tCRCD(0xedbbc2b,\"Trigger_RIGHT\"),      CRCD(0xc8abf89c,\"Release_RIGHT\"),     &m_pad.m_right \t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_CIRCLE,\t\tInp::Data::mA_CIRCLE, \tCRCD(0xb069b600,\"Trigger_CIRCLE\"),    CRCD(0xe5aae06b,\"Release_CIRCLE\"),    &m_pad.m_circle\t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_SQUARE,\t\tInp::Data::mA_SQUARE, \tCRCD(0xa93dbbd0,\"Trigger_SQUARE\"),    CRCD(0xfcfeedbb,\"Release_SQUARE\"),    &m_pad.m_square\t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_TRIANGLE,\tInp::Data::mA_TRIANGLE, CRCD(0x7f695a77,\"Trigger_TRIANGLE\"),  CRCD(0x7b684919,\"Release_TRIANGLE\"),  &m_pad.m_triangle\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_X,\t\t\tInp::Data::mA_X, \t\tCRCD(0x42717176,\"Trigger_X\"),         CRCD(0xbbbef674,\"Release_X\"),         &m_pad.m_x\t \t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_L1,\t\t\tInp::Data::mA_L1, \t\tCRCD(0xc6547217,\"Trigger_L1\"),        CRCD(0x28a3dcbc,\"Release_L1\"),        &m_pad.m_L1\t \t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_L2,\t\t\tInp::Data::mA_L2, \t\tCRCD(0x5f5d23ad,\"Trigger_L2\"),        CRCD(0xb1aa8d06,\"Release_L2\"),        &m_pad.m_L2 \t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_L3,\t\t\tInp::Data::mA_L3, \t\tCRCD(0x285a133b,\"Trigger_L3\"),        CRCD(0xc6adbd90,\"Release_L3\"),        &m_pad.m_L3\t \t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_R1,\t\t\tInp::Data::mA_R1, \t\tCRCD(0x12154dc8,\"Trigger_R1\"),        CRCD(0xfce2e363,\"Release_R1\"),        &m_pad.m_R1 \t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_R2,\t\t\tInp::Data::mA_R2, \t\tCRCD(0x8b1c1c72,\"Trigger_R2\"),        CRCD(0x65ebb2d9,\"Release_R2\"),        &m_pad.m_R2 \t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_R3,\t\t\tInp::Data::mA_R3, \t\tCRCD(0xfc1b2ce4,\"Trigger_R3\"),        CRCD(0x12ec824f,\"Release_R3\"),        &m_pad.m_R3\t\t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_BLACK,\t\tInp::Data::mA_BLACK, \tCRCD(0x33947317,\"Trigger_BLACK\"),     CRCD(0xf5e437a0,\"Release_BLACK\"),     NULL\t\t\t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_WHITE,\t\tInp::Data::mA_WHITE, \tCRCD(0xf8de049b,\"Trigger_WHITE\"),     CRCD(0x3eae402c,\"Release_WHITE\"),     NULL\t\t \t\t);\t\r\n\tupdate_input_mask(input, Inp::Data::vA_Z,\t\t\tInp::Data::mA_Z,\t \tCRCD(0xac7f105a,\"Trigger_Z\"),         CRCD(0x55b09758,\"Release_Z\"),     \tNULL\t\t \t\t);\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CInputComponent::s_input_logic_code ( const Inp::Handler < CInputComponent >& handler )\r\n{\r\n\thandler.GetData().handle_input(handler.m_Input);\r\n}\r\n\r\nvoid CInputComponent::s_input_logic_code2 ( const Inp::Handler < CInputComponent >& handler )\r\n{\r\n\thandler.GetData().handle_input2(handler.m_Input);\r\n}\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/InputComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       InputComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/18/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_INPUTCOMPONENT_H__\r\n#define __COMPONENTS_INPUTCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/inpman.h>\r\n\r\n#include <sk/objects/skaterpad.h>\r\n\r\n#define\t\tCRC_INPUT CRCD(0x27d7cd28, \"Input\")\r\n\r\n#define\t\tGetInputComponent() ((Obj::CInputComponent*)GetComponent(CRC_INPUT))\r\n#define\t\tGetInputComponentFromObject(pObj) ((Obj::CInputComponent*)(pObj)->GetComponent(CRC_INPUT))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\t\r\nclass CInputComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CInputComponent();\r\n    virtual ~CInputComponent();\r\n\r\npublic:\r\n    virtual void            \t\t\tUpdate();\r\n    virtual void            \t\t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   \tCallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\t\ts_create();\r\n\t\r\n\tuint32\t\t\t\t\t\t\t\tGetInputMask (   ) const { return m_input_mask; }\r\n\tCControlPad&\t\t\t\t\t\tGetControlPad (   ) { return m_pad; }\r\n\tCControlPad&\t\t\t\t\t\tGetControlPad2 (   ) { return m_pad2; }\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\tDisableInput (   ) { m_input_disabled = true; }\r\n\tvoid\t\t\t\t\t\t\t\tEnableInput (   ) { m_input_disabled = false; }\r\n\tvoid\t\t\t\t\t\t\t\tNetDisableInput (   ) { m_net_input_disabled = true; }\r\n\tvoid\t\t\t\t\t\t\t\tNetEnableInput (   ) { m_net_input_disabled = false; }\r\n\tbool\t\t\t\t\t\t\t\tIsInputDisabled (   ) { return m_input_disabled || m_net_input_disabled; }\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\tBindToController ( int controller );\r\n\tInp::Handler< CInputComponent >*\tGetInputHandler (   ) { return m_input_handler; }\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\tDebounce ( uint32 Checksum, float time, bool clear );\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\tPauseDevice (   ) { m_input_handler->m_Device->Pause(); }\r\n\tvoid\t\t\t\t\t\t\t\tUnPauseDevice (   ) { m_input_handler->m_Device->UnPause(); }\r\n\tSIO::Device*\t\t\t\t\t\tGetDevice (   ) { return m_input_handler->m_Device; }\r\n\t\r\nprivate:\r\n\tstatic void\t\t\t\t\t\t\ts_input_logic_code ( const Inp::Handler < CInputComponent >& handler );\r\n\tstatic void\t\t\t\t\t\t\ts_input_logic_code2 ( const Inp::Handler < CInputComponent >& handler );\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\thandle_input ( Inp::Data* input );\r\n\tvoid\t\t\t\t\t\t\t\thandle_input2 ( Inp::Data* input );\r\n\tvoid\t\t\t\t\t\t\t\tbuild_input_mask ( Inp::Data* input );\r\n\tvoid \t\t\t\t\t\t\t\tupdate_input_mask ( Inp::Data* input, Inp::Data::AnalogButtonIndex button, Inp::Data::AnalogButtonMask mask, uint32 trigger_event, uint32 release_event, CSkaterButton* skater_button  );\r\n\t\r\n\tbool\t\t\t\t\t\t\t\tignore_button_presses (   );\r\n\t\r\nprivate:\r\n\tuint32\t\t\t\t\t\t\t\tm_last_mask;\r\n\tuint32\t\t\t\t\t\t\t\tm_input_mask;\r\n\tCControlPad\t\t\t\t\t\t\tm_pad;\r\n\tCControlPad\t\t\t\t\t\t\tm_pad2;\r\n\t\r\n\tInp::Handler< CInputComponent >*\tm_input_handler;\r\n\tInp::Handler< CInputComponent >*\tm_input_handler2;\r\n\t\r\n\tbool\t\t\t\t\t\t\t\tm_input_disabled;\r\n\tbool\t\t\t\t\t\t\t\tm_net_input_disabled;\r\n\t\r\n\tbool\t\t\t\t\t\t\t\tm_input_events_enabled;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/ModelLightUpdateComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       ModelLightUpdateComponent.cpp\r\n//* OWNER:          Garrett\r\n//* CREATION DATE:  07/10/03\r\n//****************************************************************************\r\n\r\n// The CModelLightUpdateComponent class is used to update the brightness of\r\n// the model lights if nothing else is currently doing it.  Because it has\r\n// to do extra collision checks, this component should only be used if there\r\n// is no other way to get the brightness from an existing feeler.  For now,\r\n// all you need to do is create the component on an object that already has\r\n// a ModelComponent with \"UseModelLights\" set in the InitStructure.\r\n\r\n#include <gel/components/ModelLightUpdateComponent.h>\r\n#include <gel/components/ModelComponent.h>\r\n\r\n#include <gfx/nxlight.h>\r\n#include <gfx/nxmodel.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CModelLightUpdateComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CModelLightUpdateComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModelLightUpdateComponent::CModelLightUpdateComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_MODELLIGHTUPDATE );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCModelLightUpdateComponent::~CModelLightUpdateComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelLightUpdateComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// ** Add code to parse the structure, and initialize the component\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelLightUpdateComponent::Finalize()\r\n{\r\n\tmp_model_component =  GetModelComponentFromObject( GetObject() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelLightUpdateComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelLightUpdateComponent::Update()\r\n{\r\n\t// Find the closest ground collision and extract the brightness from it.\r\n\t// logic extracted from CAdjustComponent::uber_frig\r\n\r\n\tCFeeler feeler;\r\n\t\r\n\tfeeler.m_start = GetObject()->m_pos;\r\n\tfeeler.m_end = GetObject()->m_pos;\r\n\r\n\t// Very minor adjustment to move origin away from vert walls\r\n\tfeeler.m_start += GetObject()->m_matrix[Y] * 0.001f;\r\n\t\r\n\tfeeler.m_start[Y] += 8.0f;\r\n\tfeeler.m_end[Y] -= FEET(400);\r\n\t\t   \r\n\tif (!feeler.GetCollision()) return;\r\n\r\n\tDbg_Assert(mp_model_component);\r\n\r\n\tif (feeler.IsBrightnessAvailable())\r\n\t{\r\n\t\tNx::CModelLights *p_model_lights = mp_model_component->GetModel()->GetModelLights();\r\n\t\tif (p_model_lights)\r\n\t\t{\r\n\t\t\tp_model_lights->SetBrightness(feeler.GetBrightness());\r\n\t\t} \r\n\t}\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CModelLightUpdateComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n/*\r\n        // @script | DoSomething | does some functionality\r\n\t\tcase 0xbb4ad101:\t\t// DoSomething\r\n\t\t\tDoSomething();\r\n\t\t\tbreak;\r\n\r\n        // @script | ValueIsTrue | returns a boolean value\r\n\t\tcase 0x769260f7:\t\t// ValueIsTrue\r\n\t\t{\r\n\t\t\treturn ValueIsTrue() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\tbreak;\r\n*/\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelLightUpdateComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CModelLightUpdateComponent::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\t/*\tExample:\r\n\tp_info->AddInteger(CRCD(0x7cf2a233,\"m_never_suspend\"),m_never_suspend);\r\n\tp_info->AddFloat(CRCD(0x519ab8e0,\"m_suspend_distance\"),m_suspend_distance);\r\n\t*/\r\n\t\r\n// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/ModelLightUpdateComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       ModelLightUpdateComponent.h\r\n//* OWNER:          Garrett\r\n//* CREATION DATE:  07/10/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_MODELLIGHTUPDATECOMPONENT_H__\r\n#define __COMPONENTS_MODELLIGHTUPDATECOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_MODELLIGHTUPDATE CRCD(0xe3fca939,\"ModelLightUpdate\")\r\n#define\t\tGetModelLightUpdateComponent() ((Obj::CModelLightUpdateComponent*)GetComponent(CRC_MODELLIGHTUPDATE))\r\n#define\t\tGetModelLightUpdateComponentFromObject(pObj) ((Obj::CModelLightUpdateComponent*)(pObj)->GetComponent(CRC_MODELLIGHTUPDATE))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\n\tclass CModelComponent;\r\n\r\nclass CModelLightUpdateComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CModelLightUpdateComponent();\r\n    virtual ~CModelLightUpdateComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual\tvoid \t\t\t\t\tFinalize();\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\nprotected:\r\n\tCModelComponent *\t\t\t\tmp_model_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/MovableContactComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       MovableContactComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  5/19/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/movablecontactcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CMovableContactComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CMovableContactComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMovableContactComponent::CMovableContactComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_MOVABLECONTACT );\r\n\t\r\n\tmp_contact = NULL;\r\n\t\r\n\tm_lost_contact_timestamp = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCMovableContactComponent::~CMovableContactComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovableContactComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovableContactComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovableContactComponent::Update()\r\n{\r\n\tSuspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CMovableContactComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovableContactComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CMovableContactComponent::GetDebugInfo\"));\r\n\t\r\n\tif (mp_contact && mp_contact->GetObject())\r\n\t{\r\n\t\tp_info->AddChecksum(CRCD(0xb39d19c7, \"contact\"), mp_contact->GetObject()->GetID());\r\n\t}\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovableContactComponent::CheckForMovableContact ( CFeeler& feeler )\r\n{\r\n\t// we might now be in contact with something new\r\n\tif (feeler.IsMovableCollision())\r\n\t{\r\n\t\tif (HaveContact())\r\n\t\t{\r\n\t\t\tif (mp_contact->GetObject() != feeler.GetMovingObject())\r\n\t\t\t{\r\n\t\t\t\tLoseAnyContact();\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif (!HaveContact())\r\n\t\t{\r\n\t\t\t// only create a new contact point if there was not one before, or if we just deleted one\r\n\t\t\tmp_contact = new CContact(feeler.GetMovingObject());\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// when we land on the ground, then we can't be in contact with anything, so delete any existing contact\r\n\t\tif (HaveContact())\r\n\t\t{\r\n\t\t\tLoseAnyContact();\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCompositeObject* CMovableContactComponent::CheckInsideObjectsToTop ( Mth::Vector& pos )\r\n{\r\n\tMth::Vector top;\r\n\tCCompositeObject *p_object = find_inside_object(pos, top);\r\n\tif (!p_object) return NULL;\r\n\t\r\n\tpos = top;\r\n\tpos[Y] += 1.0f;\r\n\treturn p_object;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCompositeObject* CMovableContactComponent::CheckInsideObjects ( Mth::Vector& pos, const Mth::Vector& safe_pos )\r\n{\r\n\t// not movable contact functionality per say, but useful a service related to movable collision nonetheless\r\n\t\r\n\t// Check to see if the skater is inside any moving object and move him outside\r\n\t// Algorithm\r\n\t// start at a point 100 feet above the skater\r\n\t// check collision down to the skater\r\n\t// while there is a collision if skater has a moving object collision in the 100 feet above him\r\n\t// and no collisions (with that object) going up to that point, then we are inside the object\r\n\r\n\tMth::Vector top;\r\n\tCCompositeObject *p_object = find_inside_object(pos, top);\r\n\tif (!p_object) return NULL;\r\n\t\r\n\t// check if the last position is now fine...\r\n\tMth::Vector dummy;\r\n\tif (!find_inside_object(safe_pos, dummy))\r\n\t{\r\n\t\t// first choice: move back to old pos\r\n\t\tpos = safe_pos;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// recheck last position here, like adding in the contact movement\r\n\t\r\n\t\tMth::Vector test = pos + p_object->GetVel() * Tmr::FrameLength() * 2.0f;  \r\n\t\t\r\n\t\tif (!find_inside_object(test, dummy))\r\n\t\t{\r\n\t\t\t// first choice: move back to old pos\r\n\t\t\tpos = test;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// last resort, snap up \r\n\t\t\tpos = top;\r\n\t\t\t\r\n\t\t\t// when snapping up, put him an inch above the object; otherwise, you will not hit it next frame, as the point will be in the plane\r\n\t\t\tpos[Y] += 1.0f;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn p_object;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCompositeObject* CMovableContactComponent::find_inside_object ( const Mth::Vector& pos, Mth::Vector& p_return_pos )\r\n{\r\n\t// \tGiven a position (pos), then find out if this position is inside this moving object\r\n\t//  Assumes anything within 6 inches below the top of the object is actually outside as the code assumes \r\n\r\n\t// create a line that goes from 400 inches above this point to six inches above\r\n\tCFeeler\tdown_feeler;\r\n\tdown_feeler.m_start = pos;\r\n\tdown_feeler.m_start[Y] += 400.0f;\r\n\tdown_feeler.m_end = pos;\r\n\tdown_feeler.m_end[Y] += 6.0f;\r\n\t\r\n\tCFeeler\tup_feeler;\r\n\tint loop_detect = 0;\r\n\twhile (true)\r\n\t{\r\n\t\t// return on final builds to handle highly obscure cases I've not forseen....\r\n\t\tif (++loop_detect == 10) return NULL;\r\n\t\t\r\n\t\t// nothing above\r\n\t\tif (!down_feeler.GetCollision()) return NULL;\r\n\t\t\r\n\t\t// something above, but not movable\r\n\t\tif (!down_feeler.IsMovableCollision()) return NULL;\r\n\t\t\r\n\t\t// something movable above\r\n\t\t\r\n\t\t// Now we get the collision point, and check UP to that point from m_pos to a point just above that\t\t\r\n\t\tup_feeler.m_start = pos;\r\n\t\tup_feeler.m_end = down_feeler.GetPoint();\r\n\t\tup_feeler.m_end[Y] += 0.1f;\r\n\t\t\r\n\t\tif (!up_feeler.GetCollision())\r\n\t\t{\r\n\t\t\tp_return_pos = down_feeler.GetPoint();\r\n\t\t\treturn down_feeler.GetMovingObject(); \r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tdown_feeler.m_start = down_feeler.GetPoint();\r\n\t\t\tdown_feeler.m_start[Y] -= 0.1f;\r\n\t\t}\r\n\t}\r\n}\t\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/MovableContactComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       MovableContactComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  5/19/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_MOVABLECONTACTCOMPONENT_H__\r\n#define __COMPONENTS_MOVABLECONTACTCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/engine/contact.h>\r\n\r\n#define\t\tCRC_MOVABLECONTACT CRCD(0x408d2aa9, \"MovableContact\")\r\n\r\n#define\t\tGetMovableContactComponent() ((Obj::CMovableContactComponent*)GetComponent(CRC_MOVABLECONTACT))\r\n#define\t\tGetMovableContactComponentFromObject(pObj) ((Obj::CMovableContactComponent*)(pObj)->GetComponent(CRC_MOVABLECONTACT))\r\n\r\nclass CFeeler;\r\n \r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CMovableContactComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CMovableContactComponent();\r\n    virtual ~CMovableContactComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tbool\t\t\t\t\t\t\tCheckForMovableContact ( CFeeler& feeler );\r\n\tvoid\t\t\t\t\t\t\tObtainContact ( CCompositeObject* p_composite_object );\r\n\tbool\t\t\t\t\t\t\tHaveContact (   );\r\n\tvoid\t\t\t\t\t\t\tLoseAnyContact (   );\r\n\tbool\t\t\t\t\t\t\tUpdateContact ( const Mth::Vector& pos);\r\n\tCContact*\t\t\t\t\t\tGetContact (   ) { return mp_contact; }\r\n\tCCompositeObject*\t\t\t\tCheckInsideObjectsToTop ( Mth::Vector& pos );\r\n\tCCompositeObject*\t\t\t\tCheckInsideObjects ( Mth::Vector& pos, const Mth::Vector& safe_pos );\r\n\t\r\n\tTmr::Time\t\t\t\t\t\tGetTimeSinceLastLostContact (   ) { return Tmr::ElapsedTime(m_lost_contact_timestamp); }\r\n\t\r\nprivate:\t\t\r\n\tCCompositeObject*\t\t\t\tfind_inside_object ( const Mth::Vector& pos, Mth::Vector& p_return_pos );\r\n\r\n\tCContact*\t\t\t\t\t\tmp_contact;\t\t\t\t\t\t// contact point (NULL if no current contact)\r\n\t\r\n\tTmr::Time\t\t\t\t\t\tm_lost_contact_timestamp;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CMovableContactComponent::LoseAnyContact (   )\r\n{\r\n\tif (mp_contact)\r\n\t{\r\n\t\tdelete mp_contact;\r\n\t\tmp_contact = NULL;\r\n\t\t\r\n\t\tm_lost_contact_timestamp = Tmr::GetTime();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CMovableContactComponent::HaveContact (   )\r\n{\r\n\tif (!mp_contact) return false;\r\n\t\r\n\tif (mp_contact->GetObject()) return true;\r\n\t\r\n\tLoseAnyContact();\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CMovableContactComponent::ObtainContact ( CCompositeObject* p_composite_object )\r\n{\r\n\tLoseAnyContact();\r\n\tmp_contact = new CContact(p_composite_object);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CMovableContactComponent::UpdateContact ( const Mth::Vector& pos)\r\n{\r\n\tif (!HaveContact()) return false;\r\n\t\r\n\tif (mp_contact->Update(pos)) return true;\r\n\t\r\n\tLoseAnyContact();\r\n\treturn false;\r\n}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/NearComponent.cpp",
    "content": "#if 0\r\n\r\n//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       NearComponent.cpp\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/19/03\r\n//****************************************************************************\r\n\r\n#include <gel/components/nearcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Obj\r\n{\r\n\t\r\nsSweepPruneArray CNearComponent::m_sweep_prune_array[3]\t= { sSweepPruneArray( 0 ), sSweepPruneArray( 1 ), sSweepPruneArray( 2 ) };\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCBaseComponent* CNearComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CNearComponent );\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNearComponent::CNearComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_NEAR );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNearComponent::~CNearComponent()\r\n{\r\n\t// Remove from the axis arrays.\r\n\tfor( int axis = 0; axis < 3; ++axis )\r\n\t{\r\n\t\tm_sweep_prune_array[axis].RemoveComponent( this );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNearComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Not sure where bounding box dimensions will come from.\r\n\tm_untransformed_bbox.SetMin( Mth::Vector( -120.0f, -120.0f, -120.0f ));\r\n\tm_untransformed_bbox.SetMax( Mth::Vector(  120.0f,  120.0f,  120.0f ));\r\n\r\n\t// Obtain the position of the parent object, and build the transformed bounding box.\r\n\tif( GetObject())\r\n\t{\r\n\t\tMth::Vector t;\r\n\r\n\t\tt = m_untransformed_bbox.GetMin() + GetObject()->GetPos();\r\n\t\tm_transformed_bbox.SetMin( t );\r\n\r\n\t\tt = m_untransformed_bbox.GetMax() + GetObject()->GetPos();\r\n\t\tm_transformed_bbox.SetMax( t );\r\n\t}\r\n\r\n\t// Now add this component to the axis arrays.\r\n\tfor( int axis = 0; axis < 3; ++axis )\r\n\t{\r\n\t\tm_sweep_prune_array[axis].InsertComponent( this );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNearComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Remove from axis arrays, then reinitialise.\r\n\tfor( int axis = 0; axis < 3; ++axis )\r\n\t{\r\n\t\tm_sweep_prune_array[axis].RemoveComponent( this );\r\n\t}\r\n\r\n\tInitFromStructure( pParams );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNearComponent::Update()\r\n{\r\n\t// Re-calculate the bounding box position.\r\n\tif( GetObject())\r\n\t{\r\n\t\tMth::Vector t;\r\n\r\n\t\tt = m_untransformed_bbox.GetMin() + GetObject()->GetPos();\r\n\t\tm_transformed_bbox.SetMin( t );\r\n\r\n\t\tt = m_untransformed_bbox.GetMax() + GetObject()->GetPos();\r\n\t\tm_transformed_bbox.SetMax( t );\r\n\r\n\t\t// Resort the component.\r\n\t\tfor( int axis = 0; axis < 3; ++axis )\r\n\t\t{\r\n\t\t\tm_sweep_prune_array[axis].ResortComponent( this );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCBaseComponent::EMemberFunctionResult CNearComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n/*\r\n        // @script | DoSomething | does some functionality\r\n\t\tcase 0xbb4ad101:\t\t// DoSomething\r\n\t\t\tDoSomething();\r\n\t\t\tbreak;\r\n\r\n        // @script | ValueIsTrue | returns a boolean value\r\n\t\tcase 0x769260f7:\t\t// ValueIsTrue\r\n\t\t{\r\n\t\t\treturn ValueIsTrue() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\tbreak;\r\n*/\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNearComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert( p_info, ( \"NULL p_info sent to CNearComponent::GetDebugInfo\" ));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\t/*\tExample:\r\n\tp_info->AddInteger(\"m_never_suspend\",m_never_suspend);\r\n\tp_info->AddFloat(\"m_suspend_distance\",m_suspend_distance);\r\n\t*/\r\n\t\r\n\t// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n\r\n\r\n#define MAX_COMPONENTS_PER_WORKSPACE_ARRAY\t\t64\r\nstatic int\t\t\t\tperAxisIntersections[3];\r\nstatic CNearComponent*\tperAxisWorkspace[3][MAX_COMPONENTS_PER_WORKSPACE_ARRAY];\r\nstatic CNearComponent*\tcombinedAxisWorkspace[MAX_COMPONENTS_PER_WORKSPACE_ARRAY];\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint sSweepPruneArray::BinarySearchFirstBigger( float value )\r\n{\r\n\tint first_bigger\t= -1;\r\n\tint l\t\t\t\t= 0;\r\n\tint u\t\t\t\t= m_num_entries - 1;\r\n\twhile( l <= u )\r\n\t{\r\n\t\tint m = ( l + u ) / 2;\r\n\t\tif( m_array[m].GetValue( m_axis ) <= value )\r\n\t\t{\r\n\t\t\t// x[m] <= t\r\n\t\t\tl = m + 1;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// x[m] > t\r\n\t\t\tfirst_bigger = m;\r\n\t\t\tu = m - 1;\r\n\t\t}\r\n\t}\r\n\treturn first_bigger;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint sSweepPruneArray::BinarySearchLastSmaller( float value )\r\n{\r\n\tint last_smaller\t= -1;\r\n\tint l\t\t\t\t= 0;\r\n\tint u\t\t\t\t= m_num_entries - 1;\r\n\twhile( l <= u )\r\n\t{\r\n\t\tint m = ( l + u ) / 2;\r\n\t\tif( m_array[m].GetValue( m_axis ) <= value )\r\n\t\t{\r\n\t\t\t// x[m] <= t\r\n\t\t\tlast_smaller = m;\r\n\t\t\tl = m + 1;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// x[m] > t\r\n\t\t\tu = m - 1;\r\n\t\t}\r\n\t}\r\n\treturn last_smaller;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint sSweepPruneArray::BuildCompositeIntersectingArray( void )\r\n{\r\n\t// Now build the composite array of intersections that appear in all three axis lists.\r\n\tint final_intersections\t= 0;\r\n\tint source, check1, check2;\r\n\r\n\t// Use the smallest list to check against.\r\n\tif(( perAxisIntersections[0] <= perAxisIntersections[1] ) && ( perAxisIntersections[0] <= perAxisIntersections[2] ))\r\n\t{\r\n\t\tsource\t= 0;\r\n\t\tcheck1\t= 1;\r\n\t\tcheck2\t= 2;\r\n\t}\r\n\telse if(( perAxisIntersections[1] <= perAxisIntersections[0] ) && ( perAxisIntersections[1] <= perAxisIntersections[2] ))\r\n\t{\r\n\t\tsource\t= 1;\r\n\t\tcheck1\t= 0;\r\n\t\tcheck2\t= 2;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsource\t= 2;\r\n\t\tcheck1\t= 0;\r\n\t\tcheck2\t= 1;\r\n\t}\r\n\r\n\tfor( int i = 0; i < perAxisIntersections[source]; ++i )\r\n\t{\r\n\t\tbool found;\r\n\t\t\r\n\t\t// Is this intersection also in the first check list?\r\n\t\tfound = false;\r\n\t\tfor( int j = 0; j < perAxisIntersections[check1]; ++j )\r\n\t\t{\r\n\t\t\tif( perAxisWorkspace[source][i] == perAxisWorkspace[check1][j] )\r\n\t\t\t{\r\n\t\t\t\tfound = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If it wasn't in the first check list, there's no intersection.\r\n\t\tif( !found )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// Is this intersection also in the second check list?\r\n\t\tfound = false;\r\n\t\tfor( int j = 0; j < perAxisIntersections[check2]; ++j )\r\n\t\t{\r\n\t\t\tif( perAxisWorkspace[source][i] == perAxisWorkspace[check2][j] )\r\n\t\t\t{\r\n\t\t\t\tfound = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If it wasn't in the second check list, there's no intersection.\r\n\t\tif( !found )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// At this stage the intersection appeared in all three axis lists, so it is a valid intersection.\r\n\t\t// As a final check, make sure it isn't already in the final list.\r\n\t\tfound = false;\r\n\t\tfor( int j = 0; j < final_intersections; ++j )\r\n\t\t{\r\n\t\t\tif( combinedAxisWorkspace[j] == perAxisWorkspace[source][i] )\r\n\t\t\t{\r\n\t\t\t\tfound = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( !found )\r\n\t\t{\r\n\t\t\tcombinedAxisWorkspace[final_intersections] = perAxisWorkspace[source][i];\r\n\t\t\t++final_intersections;\r\n\t\t}\r\n\t}\r\n\treturn final_intersections;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNearComponent** CNearComponent::GetIntersectingNearComponents( Mth::Vector &bbmin, Mth::Vector &bbmax, int *p_num_intersecting )\r\n{\r\n\t// Zero axis intersection count array.\r\n\tperAxisIntersections[0] = perAxisIntersections[1] = perAxisIntersections[2] = 0;\r\n\r\n\tfor( int axis = 0; axis < 3; ++axis )\r\n\t{\r\n\t\t// Find the start index.\r\n\t\tint start_index = m_sweep_prune_array[axis].BinarySearchFirstBigger( bbmin[axis] );\r\n\t\tif( start_index == -1 )\r\n\t\t{\r\n\t\t\t// Nothing was found, therefore there can be no intersections.\r\n\t\t\t*p_num_intersecting = 0;\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\r\n\t\t// Find the end index.\r\n\t\tint end_index = m_sweep_prune_array[axis].BinarySearchLastSmaller( bbmax[axis] );\r\n\t\tif( end_index == -1 )\r\n\t\t{\r\n\t\t\t// Nothing was found, therefore there can be no intersections.\r\n\t\t\t*p_num_intersecting = 0;\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\r\n\t\tDbg_Assert( end_index > start_index );\r\n\r\n\t\t// Build up the workspace array for this axis.\r\n\t\tint intersections_for_this_axis = 0;\r\n\t\tfor( int i = start_index; i <= end_index; ++i )\r\n\t\t{\r\n\t\t\t// Don't want to include the calling component in the list.\r\n\t\t\tif( m_sweep_prune_array[axis].m_array[i].mp_component != this )\r\n\t\t\t{\r\n\t\t\t\tperAxisWorkspace[axis][intersections_for_this_axis++] = m_sweep_prune_array[axis].m_array[i].mp_component;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If we found no intersections for this axis, there can be no components that intersect.\r\n\t\tif( intersections_for_this_axis == 0 )\r\n\t\t{\r\n\t\t\t*p_num_intersecting = 0;\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\r\n\t\t// Store off the number of intersections for this axis.\r\n\t\tperAxisIntersections[axis] = intersections_for_this_axis;\r\n\r\n\t}\r\n\r\n\t// Build the composite array.\r\n\tint final_intersections = sSweepPruneArray::BuildCompositeIntersectingArray();\r\n\r\n\t*p_num_intersecting = final_intersections;\r\n\treturn ( final_intersections > 0 ) ? &combinedAxisWorkspace[0] : NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNearComponent** CNearComponent::GetIntersectingNearComponents( int *p_num_intersecting )\r\n{\r\n\t// Zero axis intersection count array.\r\n\tperAxisIntersections[0] = perAxisIntersections[1] = perAxisIntersections[2] = 0;\r\n\r\n\t// Build up each workspace array.\r\n\tfor( int axis = 0; axis < 3; ++axis )\r\n\t{\r\n\t\tint i;\r\n\t\tfor( i = 0; i < m_sweep_prune_array[axis].m_num_entries; ++i )\r\n\t\t{\r\n\t\t\tif( m_sweep_prune_array[axis].m_array[i].mp_component == this )\r\n\t\t\t{\r\n\t\t\t\t// We have found the start of the span for this component.\r\n\t\t\t\tDbg_Assert( m_sweep_prune_array[axis].m_array[i].m_min_max == 0 );\r\n\t\t\t\t++i;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Now add any other components we come across before we hit the end of the span.\r\n\t\twhile(( i < m_sweep_prune_array[axis].m_num_entries ) && ( m_sweep_prune_array[axis].m_array[i].mp_component != this ))\r\n\t\t{\r\n\t\t\tperAxisWorkspace[axis][perAxisIntersections[axis]] = m_sweep_prune_array[axis].m_array[i].mp_component;\r\n\t\t\t++perAxisIntersections[axis];\r\n\t\t\t++i;\r\n\t\t}\r\n\r\n\t\t// If we found no intersections for this axis, there can be no components that intersect.\r\n\t\tif( perAxisIntersections[axis] == 0 )\r\n\t\t{\r\n\t\t\t*p_num_intersecting = 0;\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t}\r\n\r\n\t// Build the composite array.\r\n\tint final_intersections = sSweepPruneArray::BuildCompositeIntersectingArray();\r\n\r\n\t*p_num_intersecting = final_intersections;\r\n\treturn ( final_intersections > 0 ) ? &combinedAxisWorkspace[0] : NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sSweepPruneEntry::SetValues( void )\r\n{\r\n\tMth::Vector v\t= ( m_min_max ) ? mp_component->GetMax() : mp_component->GetMin();\r\n\tm_value[0]\t\t= v[0];\r\n\tm_value[1]\t\t= v[1];\r\n\tm_value[2]\t\t= v[2];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsSweepPruneArray::sSweepPruneArray( int axis )\r\n{\r\n\tm_axis\t\t\t= axis;\r\n\tm_num_entries\t= 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsSweepPruneArray::~sSweepPruneArray( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sSweepPruneArray::PushUp( int index )\r\n{\r\n\tDbg_MsgAssert( m_num_entries < MAX_SWEEP_PRUNE_ENTRIES_PER_AXIS, ( \"CNearComponent::SweepPruneList overflow\" ));\r\n\r\n\t// All array entries from index (inclusive) upwards are moved up one position.\r\n\tfor( int i = m_num_entries - 1; i >= index; --i )\r\n\t{\r\n\t\tm_array[i + 1] = m_array[i];\r\n\t}\r\n\t++m_num_entries;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sSweepPruneArray::PullDown( int index )\r\n{\r\n\tDbg_MsgAssert( m_num_entries > 0, ( \"CNearComponent::SweepPruneList underflow\" ));\r\n\r\n\t// All array entries from index (inclusive) upwards are moved down one position.\r\n\tfor( int i = index; i < ( m_num_entries - 1 ); ++i )\r\n\t{\r\n\t\tm_array[i] = m_array[i + 1];\r\n\t}\r\n\t--m_num_entries;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sSweepPruneArray::ResortComponent( CNearComponent *p_component )\r\n{\r\n\t// Does a simple check to see whether the component is still in the correct order.\r\n\t// If it isn't, sorting is applied.\r\n\r\n\t// Check min first.\r\n\tint i;\r\n\tfor( i = 0; i < m_num_entries; ++i )\r\n\t{\r\n\t\tif( m_array[i].mp_component == p_component )\r\n\t\t{\r\n\t\t\t// This should be the min entry.\r\n\t\t\tDbg_Assert( m_array[i].m_min_max == 0 );\r\n\r\n\t\t\t// Set the new min value.\r\n\t\t\tm_array[i].SetValues();\r\n\r\n\t\t\t// Check this is bigger than or equal to the previous value, if there is one.\r\n\t\t\twhile(( i > 0 ) && ( m_array[i].GetValue( m_axis ) < m_array[i - 1].GetValue( m_axis )))\r\n\t\t\t{\r\n\t\t\t\t// Move this entry down in the array.\r\n\t\t\t\tsSweepPruneEntry swap\t= m_array[i];\r\n\t\t\t\tm_array[i]\t\t\t\t= m_array[i - 1];\r\n\t\t\t\tm_array[i - 1]\t\t\t= swap;\r\n\t\t\t\t--i;\r\n\t\t\t}\r\n\r\n\t\t\t// Check this is smaller than or equal to the next value, if there is one.\r\n\t\t\twhile(( i < ( m_num_entries - 1)) && ( m_array[i].GetValue( m_axis ) > m_array[i + 1].GetValue( m_axis )))\r\n\t\t\t{\r\n\t\t\t\t// Move this entry up in the array.\r\n\t\t\t\tsSweepPruneEntry swap\t= m_array[i];\r\n\t\t\t\tm_array[i]\t\t\t\t= m_array[i + 1];\r\n\t\t\t\tm_array[i + 1]\t\t\t= swap;\r\n\t\t\t\t++i;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Now check max.\r\n\t++i;\r\n\tfor( ; i < m_num_entries; ++i )\r\n\t{\r\n\t\tif( m_array[i].mp_component == p_component )\r\n\t\t{\r\n\t\t\t// This should be the max entry.\r\n\t\t\tDbg_Assert( m_array[i].m_min_max == 1 );\r\n\r\n\t\t\t// Set the new max value.\r\n\t\t\tm_array[i].SetValues();\r\n\r\n\t\t\t// Check this is bigger than or equal to the previous value, if there is one.\r\n\t\t\twhile(( i > 0 ) && ( m_array[i].GetValue( m_axis ) < m_array[i - 1].GetValue( m_axis )))\r\n\t\t\t{\r\n\t\t\t\t// Move this entry down in the array.\r\n\t\t\t\tsSweepPruneEntry swap\t= m_array[i];\r\n\t\t\t\tm_array[i]\t\t\t\t= m_array[i - 1];\r\n\t\t\t\tm_array[i - 1]\t\t\t= swap;\r\n\t\t\t\t--i;\r\n\t\t\t}\r\n\r\n\t\t\t// Check this is smaller than or equal to the next value, if there is one.\r\n\t\t\twhile(( i < ( m_num_entries - 1)) && ( m_array[i].GetValue( m_axis ) > m_array[i + 1].GetValue( m_axis )))\r\n\t\t\t{\r\n\t\t\t\t// Move this entry up in the array.\r\n\t\t\t\tsSweepPruneEntry swap\t= m_array[i];\r\n\t\t\t\tm_array[i]\t\t\t\t= m_array[i + 1];\r\n\t\t\t\tm_array[i + 1]\t\t\t= swap;\r\n\t\t\t\t++i;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sSweepPruneArray::InsertComponent( CNearComponent *p_component )\r\n{\r\n\tfloat axis_min = p_component->GetMin()[m_axis];\r\n\tfloat axis_max = p_component->GetMax()[m_axis];\r\n\r\n\t// Scan through until we find an entry that is bigger than the minimum for this axis, or we come to the end of the list.\r\n\tfor( int i = 0; i <= m_num_entries; ++i )\r\n\t{\r\n\t\tif(( i == m_num_entries ) || ( m_array[i].mp_component->GetMin()[m_axis] > axis_min ))\r\n\t\t{\r\n\t\t\t// Insert this entry here.\r\n\t\t\tPushUp( i );\r\n\t\t\tm_array[i].m_min_max\t= 0;\r\n\t\t\tm_array[i].mp_component = p_component;\r\n\r\n\t\t\t// Set the new min value.\r\n\t\t\tm_array[i].SetValues();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// Now scan through until we find an entry that is bigger than the maximum for this axis, or we come to the end of the list.\r\n\tfor( int i = 0; i <= m_num_entries; ++i )\r\n\t{\r\n\t\tif(( i == m_num_entries ) || ( m_array[i].mp_component->GetMax()[m_axis] > axis_max ))\r\n\t\t{\r\n\t\t\t// Insert this entry here.\r\n\t\t\tPushUp( i );\r\n\t\t\tm_array[i].m_min_max\t= 1;\r\n\t\t\tm_array[i].mp_component = p_component;\r\n\r\n\t\t\t// Set the new min value.\r\n\t\t\tm_array[i].SetValues();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sSweepPruneArray::RemoveComponent( CNearComponent *p_component )\r\n{\r\n\t// The component should appear twice in the list.\r\n\tfor( int p = 0; p < 2; ++p )\r\n\t{\r\n\t\t// Scan through until we find this entry.\r\n\t\tfor( int i = 0; i < m_num_entries; ++i )\r\n\t\t{\r\n\t\t\tif( m_array[i].mp_component == p_component )\r\n\t\t\t{\r\n\t\t\t\t// Remove this entry.\r\n\t\t\t\tPullDown( i );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n}\r\n\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/NearComponent.h",
    "content": "#if 0\r\n//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       NearComponent.h\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ??/??/??\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_NEARCOMPONENT_H__\r\n#define __COMPONENTS_NEARCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n// Replace this with the CRCD of the component you are adding\r\n#define\t\tCRC_NEAR\t\t\t\t\t\t\tCRCD( 0x89b3e3ee, \"near\" )\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or given an object.\r\n#define\t\tGetNearComponent()\t\t\t\t\t((Obj::CNearComponent*)GetComponent(CRC_NEAR))\r\n#define\t\tGetNearComponentFromObject( pObj )\t((Obj::CNearComponent*)(pObj)->GetComponent(CRC_NEAR))\r\n\r\n#define\t\tMAX_SWEEP_PRUNE_ENTRIES_PER_AXIS\t512\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\t\r\nclass CNearComponent;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sSweepPruneEntry\r\n{\r\n\tuint32\t\t\t\tm_min_max;\t\t\t// 0 for min, 1 for max\r\n\tfloat\t\t\t\tm_value[3];\t\t\t// This proves much quicker than dereferencing the component and reading the bounding box.\r\n\tCNearComponent\t\t*mp_component;\t\t// Pointer to the actual component.\r\n\r\n\tinline float\t\tGetValue( int axis )\t{ return m_value[axis]; }\r\n\tvoid\t\t\t\tSetValues( void );\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sSweepPruneArray\r\n{\r\npublic:\r\n\tint\t\t\t\t\tm_axis;\r\n\tint\t\t\t\t\tm_num_entries;\r\n\tsSweepPruneEntry\tm_array[MAX_SWEEP_PRUNE_ENTRIES_PER_AXIS];\r\n\r\n\t\t\t\t\t\tsSweepPruneArray( int axis );\r\n\t\t\t\t\t\t~sSweepPruneArray( void );\r\n\r\n\tint\t\t\t\t\tBinarySearchFirstBigger( float value );\r\n\tint\t\t\t\t\tBinarySearchLastSmaller( float value );\r\n\tvoid\t\t\t\tResortComponent( CNearComponent *p_component );\r\n\tvoid\t\t\t\tInsertComponent( CNearComponent *p_component );\r\n\tvoid\t\t\t\tRemoveComponent( CNearComponent *p_component );\r\n\tstatic int\t\t\tBuildCompositeIntersectingArray( void );\r\n\r\nprivate:\r\n\tvoid\t\t\t\tPushUp( int index );\r\n\tvoid\t\t\t\tPullDown( int index );\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CNearComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CNearComponent();\r\n    virtual ~CNearComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tMth::Vector\t\t\t\t\t\tGetMin( void )\t{ return m_transformed_bbox.GetMin(); }\r\n\tMth::Vector\t\t\t\t\t\tGetMax( void )\t{ return m_transformed_bbox.GetMax(); }\r\n\tCNearComponent**\t\t\t\tGetIntersectingNearComponents( int *p_num_intersecting );\r\n\tCNearComponent**\t\t\t\tGetIntersectingNearComponents( Mth::Vector &bbmin, Mth::Vector &bbmax, int *p_num_intersecting );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\nprivate:\r\n\r\n\tMth::CBBox\t\t\t\t\t\tm_untransformed_bbox;\r\n\tMth::CBBox\t\t\t\t\t\tm_transformed_bbox;\r\n\tstatic sSweepPruneArray\t\t\tm_sweep_prune_array[3];\r\n};\r\n\r\n\r\n\r\n}\r\n\r\n#endif\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/NodeArrayComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       NodeArrayComponent.cpp\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/17/03\r\n//****************************************************************************\r\n\r\n// The CEmptyComponent class is an skeletal version of a component\r\n// It is intended that you use this as the basis for creating new\r\n// components.  \r\n// To create a new component called \"Watch\", (CWatchComponent):\r\n//  - copy emptycomponent.cpp/.h to watchcomponent.cpp/.h\r\n//  - in both files, search and replace \"Empty\" with \"Watch\", preserving the case\r\n//  - in WatchComponent.h, update the CRCD value of CRC_WATCH\r\n//  - in CompositeObjectManager.cpp, in the CCompositeObjectManager constructor, add:\r\n//\t\t  \tRegisterComponent(CRC_WATCH,\t\t\tCWatchComponent::s_create); \r\n//  - and add the include of the header\r\n//\t\t\t#include <gel/components/watchcomponent.h> \r\n//  - Add it to build\\gel.mkf, like:\r\n//          $(NGEL)/components/WatchComponent.cpp\\\r\n//  - Fill in the OWNER (yourself) and the CREATION DATE (today's date) in the .cpp and the .h files\r\n//\t- Insert code as needed and remove generic comments\r\n//  - remove these comments\r\n//  - add comments specfic to the component, explaining its usage\r\n#include <gel/components/nodearraycomponent.h>\r\n\r\n#include <gel/assman/assman.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\nCBaseComponent* CNodeArrayComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CNodeArrayComponent );\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCNodeArrayComponent::CNodeArrayComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_NODEARRAY );\r\n\r\n\tmp_node_array = NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNodeArrayComponent::~CNodeArrayComponent()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CNodeArrayComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Obtain the model name from the structure. At a later date, perhaps the node could override the .qb name.\r\n\tconst char *p_model_name = NULL;\r\n\tif( !pParams->GetText( 0x286a8d26, &p_model_name ))\r\n\t{\r\n\t\t// This is currently an error.\r\n\t\tDbg_MsgAssert( 0, ( \"Attempting to create NodeArrayComponent from node with no model name\" ));\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Generate the .qb name from the model name.\r\n\tchar nodearray_filename[256];\r\n\tstrcpy( nodearray_filename, \"models\\\\\" );\r\n\tstrcat( nodearray_filename, p_model_name );\r\n\tchar *p_ext = strstr( nodearray_filename, \".\" );\r\n\tif( p_ext )\r\n\t{\r\n\t\tstrcpy( p_ext, \".qb\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tstrcat( nodearray_filename, \".qb\" );\r\n\t}\r\n\r\n\t// Ask the Asset Manager for the .qb - it will be loaded if it is not yet memory resident.\r\n\tAss::CAssMan *p_ass_man = Ass::CAssMan::Instance();\r\n\tmp_node_array = (Script::CArray*)p_ass_man->LoadOrGetAsset( nodearray_filename, false, false, false, 0 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CNodeArrayComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Obtain the model name from the structure. At a later date, perhaps the node could override the .qb name.\r\n\tconst char *p_model_name = NULL;\r\n\tif( !pParams->GetText( 0x286a8d26, &p_model_name ))\r\n\t{\r\n\t\t// Not an error during a refresh, just exit with existing values maintained.\r\n\t\treturn;\r\n\t}\r\n\r\n\tInitFromStructure( pParams );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CNodeArrayComponent::Update()\r\n{\r\n\t// Doing nothing, so tell code to do nothing next time around\r\n\tSuspend(true);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CNodeArrayComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch( Checksum )\r\n\t{\r\n/*\r\n        // @script | DoSomething | does some functionality\r\n\t\tcase 0xbb4ad101:\t\t// DoSomething\r\n\t\t\tDoSomething();\r\n\t\t\tbreak;\r\n\r\n        // @script | ValueIsTrue | returns a boolean value\r\n\t\tcase 0x769260f7:\t\t// ValueIsTrue\r\n\t\t{\r\n\t\t\treturn ValueIsTrue() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\tbreak;\r\n*/\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNodeArrayComponent::GetDebugInfo( Script::CStruct *p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert( p_info, (\"NULL p_info sent to CNodeArrayComponent::GetDebugInfo\" ));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\tp_info->AddArray( \"mp_node_array\", mp_node_array );\r\n\r\n\t// We call the base component's GetDebugInfo, so we can add info from the common base component.\r\n\tCBaseComponent::GetDebugInfo( p_info );\r\n#endif\t\t\t\t \r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/NodeArrayComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       NodeArrayComponent.h\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/17/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_NODEARRAYCOMPONENT_H__\r\n#define __COMPONENTS_NODEARRAYCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_NODEARRAY\t\t\t\t\t\t\tCRCD( 0xc472ecc5, \"NodeArray\" )\r\n#define\t\tGetNodeArrayComponent()\t\t\t\t\t((Obj::CNodeArrayComponent*)GetComponent( CRC_NODEARRAY ))\r\n#define\t\tGetNodeArrayComponentFromObject( pObj )\t((Obj::CNodeArrayComponent*)(pObj)->GetComponent( CRC_NODEARRAY ))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CNodeArrayComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CNodeArrayComponent();\r\n    virtual ~CNodeArrayComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\n\tvirtual Script::CArray*\t\t\tGetNodeArray( void )\t{ return mp_node_array; }\r\n\r\nprivate:\r\n\tScript::CArray*\t\t\t\t\tmp_node_array;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/ObjectHookManagerComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       ObjectHookManagerComponent.cpp\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/18/03\r\n//****************************************************************************\r\n\r\n// The CEmptyComponent class is an skeletal version of a component\r\n// It is intended that you use this as the basis for creating new\r\n// components.  \r\n// To create a new component called \"Watch\", (CWatchComponent):\r\n//  - copy emptycomponent.cpp/.h to watchcomponent.cpp/.h\r\n//  - in both files, search and replace \"Empty\" with \"Watch\", preserving the case\r\n//  - in WatchComponent.h, update the CRCD value of CRC_WATCH\r\n//  - in CompositeObjectManager.cpp, in the CCompositeObjectManager constructor, add:\r\n//\t\t  \tRegisterComponent(CRC_WATCH,\t\t\tCWatchComponent::s_create); \r\n//  - and add the include of the header\r\n//\t\t\t#include <gel/components/watchcomponent.h> \r\n//  - Add it to build\\gel.mkf, like:\r\n//          $(NGEL)/components/WatchComponent.cpp\\\r\n//  - Fill in the OWNER (yourself) and the CREATION DATE (today's date) in the .cpp and the .h files\r\n//\t- Insert code as needed and remove generic comments\r\n//  - remove these comments\r\n//  - add comments specfic to the component, explaining its usage\r\n#include <gel/components/objecthookmanagercomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <gel/components/nodearraycomponent.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\nCBaseComponent* CObjectHookManagerComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CObjectHookManagerComponent );\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCObjectHookManagerComponent::CObjectHookManagerComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_OBJECTHOOKMANAGER );\r\n\tmp_object_hook_manager = NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCObjectHookManagerComponent::~CObjectHookManagerComponent()\r\n{\r\n\t// Remove the CObjectHookManager if present.\r\n\tif( mp_object_hook_manager )\r\n\t{\r\n\t\tdelete mp_object_hook_manager;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CObjectHookManagerComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// There needs to be a NodeArrayComponent attached for the ObjectHookManagerComponent to operate.\r\n\tCNodeArrayComponent *p_nodearray_component = GetNodeArrayComponentFromObject( GetObject());\r\n\tDbg_MsgAssert( p_nodearray_component, ( \"ObjectHookManagerComponent created without NodeArrayComponent\" ));\r\n\r\n\t// Remove the CObjectHookManager if present.\r\n\tif( mp_object_hook_manager )\r\n\t{\r\n\t\tdelete mp_object_hook_manager;\r\n\t}\r\n\r\n\t// Create a CObjectHookManager, and parse the node array for the hooks.\r\n\tmp_object_hook_manager = new Obj::CObjectHookManager();\r\n\tmp_object_hook_manager->AddObjectHooksFromNodeArray( p_nodearray_component->GetNodeArray());\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CObjectHookManagerComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure( pParams );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CObjectHookManagerComponent::Update()\r\n{\r\n\t// Doing nothing, so tell code to do nothing next time around\r\n\tSuspend(true);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CObjectHookManagerComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch( Checksum )\r\n\t{\r\n/*\r\n        // @script | DoSomething | does some functionality\r\n\t\tcase 0xbb4ad101:\t\t// DoSomething\r\n\t\t\tDoSomething();\r\n\t\t\tbreak;\r\n\r\n        // @script | ValueIsTrue | returns a boolean value\r\n\t\tcase 0x769260f7:\t\t// ValueIsTrue\r\n\t\t{\r\n\t\t\treturn ValueIsTrue() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\tbreak;\r\n*/\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CObjectHookManagerComponent::GetDebugInfo( Script::CStruct *p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert( p_info, (\"NULL p_info sent to CObjectHookManagerComponent::GetDebugInfo\" ));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\tif( mp_object_hook_manager )\r\n\t{\r\n\t\tp_info->AddString(\"ObjectHookManager.m_is_transformed\", mp_object_hook_manager->IsMoving() ? \"yes\" : \"no\" );\r\n\t}\r\n\t\r\n\t// We call the base component's GetDebugInfo, so we can add info from the common base component.\r\n\tCBaseComponent::GetDebugInfo( p_info );\r\n#endif\t\t\t\t \r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/ObjectHookManagerComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       ObjectHookManagerComponent.h\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/18/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_OBJECTHOOKMANAGERCOMPONENT_H__\r\n#define __COMPONENTS_OBJECTHOOKMANAGERCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <sk/objects/objecthook.h>\t\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_OBJECTHOOKMANAGER\t\t\t\t\t\t\tCRCD( 0x27443708, \"ObjectHookManager\" )\r\n#define\t\tGetObjectHookManagerComponent()\t\t\t\t\t((Obj::CObjectHookManagerComponent*)GetComponent( CRC_OBJECTHOOKMANAGER ))\r\n#define\t\tGetObjectHookManagerComponentFromObject( pObj )\t((Obj::CObjectHookManagerComponent*)(pObj)->GetComponent( CRC_OBJECTHOOKMANAGER ))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CObjectHookManagerComponent : public CBaseComponent\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\t\t\tCObjectHookManagerComponent();\r\n    virtual\t\t\t\t\t\t\t\t~CObjectHookManagerComponent();\r\n\r\npublic:\r\n    virtual void            \t\t\tUpdate();\r\n    virtual void            \t\t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult\t\tCallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\t\ts_create();\r\n\r\n\tvirtual Obj::CObjectHookManager*\tGetObjectHookManager( void )\t{ return mp_object_hook_manager; }\r\n\r\nprivate:\r\n\tObj::CObjectHookManager*\t\t\tmp_object_hook_manager;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/ParticleComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       ParticleComponent.cpp\r\n//* OWNER:          SPG\r\n//* CREATION DATE:  3/21/03\r\n//****************************************************************************\r\n\r\n// The CEmptyComponent class is an skeletal version of a component\r\n// It is intended that you use this as the basis for creating new\r\n// components.  \r\n// To create a new component called \"Watch\", (CWatchComponent):\r\n//  - copy emptycomponent.cpp/.h to watchcomponent.cpp/.h\r\n//  - in both files, search and replace \"Empty\" with \"Watch\", preserving the case\r\n//  - in WatchComponent.h, update the CRCD value of CRC_WATCH\r\n//  - in CompositeObjectManager.cpp, in the CCompositeObjectManager constructor, add:\r\n//\t\t  \tRegisterComponent(CRC_WATCH,\t\t\tCWatchComponent::s_create); \r\n//  - and add the include of the header\r\n//\t\t\t#include <gel/components/watchcomponent.h> \r\n//  - Add it to build\\gel.mkf, like:\r\n//          $(NGEL)/components/WatchComponent.cpp\\\r\n//  - Fill in the OWNER (yourself) and the CREATION DATE (today's date) in the .cpp and the .h files\r\n//\t- Insert code as needed and remove generic comments\r\n//  - remove these comments\r\n//  - add comments specfic to the component, explaining its usage\r\n\r\n#include <gel/components/ParticleComponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/nxnewparticle.h>\r\n#include <gfx/nxnewparticlemgr.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\n\r\nCBaseComponent* CParticleComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CParticleComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCParticleComponent::CParticleComponent() : CBaseComponent()\r\n{\r\n    SetType( CRC_PARTICLE );\r\n\r\n\tm_update_script = 0;\r\n\tmp_particle = NULL;\r\n\tm_system_lifetime = 0;\r\n\tm_birth_time = Tmr::GetTime();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCParticleComponent::~CParticleComponent()\r\n{\t\r\n\tif( mp_particle )\r\n\t{\r\n\t\t// Remove it from the particle manager\r\n\t\tNx::CEngine::sGetParticleManager()->KillParticle( mp_particle );\r\n\t\t// call the destroy function (platform specific cleanup)\r\n\t\tmp_particle->Destroy();\r\n\t\t// and delete it\r\n\t\tdelete mp_particle;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CParticleComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tint color;\r\n\tfloat scale;\r\n\tScript::CArray* array;\r\n\tNx::CParticleParams part;\r\n\tMth::Vector angles;\r\n\tbool generate_name;\r\n\tMth::Matrix orientation;\r\n\t// ** Add code to parse the structure, and initialize the component\r\n\r\n\tscale = 1.0f;\r\n\tgenerate_name = false;\r\n\tpParams->GetChecksum( CRCD(0x92276db,\"UpdateScript\"), &m_update_script );\r\n\t\r\n\tpParams->GetInteger( CRCD(0x5a235299,\"SystemLifetime\"), (int*) &m_system_lifetime );\r\n\tif( pParams->ContainsFlag(CRCD(0x18c671f0,\"noname\")))\r\n\t{\r\n\t\t// Generate a somewhat-unique id\r\n\t\tgenerate_name = true;\r\n\t\tpart.m_Name = Tmr::GetTime();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"Name\"), &part.m_Name );\r\n\t}\r\n\r\n\tpParams->GetChecksum( CRCD(0x7321a8d6,\"Type\"), &part.m_Type );\r\n\tpart.m_UseMidpoint = pParams->ContainsFlag(CRCD(0xa7a5bffb,\"UseMidPoint\"));\r\n\t\r\n\tpParams->GetFloat( CRCD(0x13b9da7b,\"scale\"), &scale, false );\r\n\r\n\tpParams->GetFloat( CRCD(0x3bee67c8,\"StartRadius\"), &part.m_Radius[Nx::vBOX_START] );\r\n\tpParams->GetFloat( CRCD(0x8e39913d,\"MidRadius\"), &part.m_Radius[Nx::vBOX_MID] );\r\n\tpParams->GetFloat( CRCD(0x3f243a3c,\"EndRadius\"), &part.m_Radius[Nx::vBOX_END] );\r\n\r\n\torientation.Ident();\r\n\tif( pParams->ContainsFlag( CRCD(0x7045843a,\"orient_to_vel\" )))\r\n\t{\r\n\t\tMth::Vector vel;\r\n\t\r\n        // Create a matrix with -vel as the AT vector of the matrix and transform the system\r\n\t\t// by that matrix\r\n\t\tpParams->GetVector(CRCD(0xc4c809e, \"vel\"), &vel, Script::ASSERT);\r\n\t\tvel.Normalize();\r\n\r\n\t\torientation[Mth::AT] = vel;\r\n\t\tif( orientation[Mth::AT] == Mth::Vector( 0, 1, 0 ))\r\n\t\t{\r\n\t\t\torientation[Mth::RIGHT] = Mth::CrossProduct( vel, Mth::Vector( 0, 0, -1 ));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\torientation[Mth::RIGHT] = Mth::CrossProduct( vel, Mth::Vector( 0, 1, 0 ));\r\n\t\t}\r\n\t\torientation[Mth::UP] = Mth::CrossProduct( orientation[Mth::AT], orientation[Mth::RIGHT] );\r\n\t}\r\n\r\n\tpart.m_Radius[Nx::vBOX_START] *= scale;\r\n\tpart.m_Radius[Nx::vBOX_MID] *= scale;\r\n\tpart.m_Radius[Nx::vBOX_END] *= scale;\r\n\r\n\tpParams->GetFloat( CRCD(0x5400a25,\"StartRadiusSpread\"), &part.m_RadiusSpread[Nx::vBOX_START] );\r\n\tpParams->GetFloat( CRCD(0xff7d9aa9,\"MidRadiusSpread\"), &part.m_RadiusSpread[Nx::vBOX_MID] );\r\n\tpParams->GetFloat( CRCD(0x5539fcee,\"EndRadiusSpread\"), &part.m_RadiusSpread[Nx::vBOX_END] );\r\n\r\n\tpart.m_RadiusSpread[Nx::vBOX_START] *= scale;\r\n\tpart.m_RadiusSpread[Nx::vBOX_MID] *= scale;\r\n\tpart.m_RadiusSpread[Nx::vBOX_END] *= scale;\r\n\r\n\tpParams->GetInteger( CRCD(0x9e52a20f,\"MaxStreams\"), &part.m_MaxStreams );\r\n\tpParams->GetFloat( CRCD(0x35b65bd4,\"EmitRate\"), &part.m_EmitRate );\r\n\tpParams->GetFloat( CRCD(0xc218cf77,\"Lifetime\"), &part.m_Lifetime );\r\n\tpParams->GetFloat( CRCD(0x520682c6,\"MidPointPCT\"), &part.m_MidpointPct );\r\n\t\r\n\tif( pParams->ContainsFlag(CRCD(0x64f194ed,\"UseStartPosition\")))\r\n\t{\r\n\t\tpParams->GetVector( CRCD(0x3d5ea6a4,\"StartPosition\"), &part.m_BoxPos[Nx::vBOX_START] );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpParams->GetVector( CRCD(0x7f261953,\"Pos\"), &part.m_BoxPos[Nx::vBOX_START] );\r\n\t}\r\n\t\r\n\tpParams->GetVector( CRCD(0x4b51a2,\"MidPosition\"), &part.m_BoxPos[Nx::vBOX_MID] );\r\n\tpParams->GetVector( CRCD(0x5854ab9e,\"EndPosition\"), &part.m_BoxPos[Nx::vBOX_END] );\r\n\r\n\tpart.m_BoxPos[Nx::vBOX_START] *= scale;\r\n\tpart.m_BoxPos[Nx::vBOX_MID] *= scale;\r\n\tpart.m_BoxPos[Nx::vBOX_END] *= scale;\r\n\r\n\tpart.m_BoxPos[Nx::vBOX_START] = orientation.Transform( part.m_BoxPos[Nx::vBOX_START] );\r\n\tpart.m_BoxPos[Nx::vBOX_MID] = orientation.Transform( part.m_BoxPos[Nx::vBOX_MID] );\r\n\tpart.m_BoxPos[Nx::vBOX_END] = orientation.Transform( part.m_BoxPos[Nx::vBOX_END] );\r\n\r\n\tpParams->GetVector( CRCD(0x9656f775,\"BoxDimsStart\"), &part.m_BoxDims[Nx::vBOX_START] );\r\n\tpParams->GetVector( CRCD(0xc3cd20a2,\"BoxDimsMid\"), &part.m_BoxDims[Nx::vBOX_MID] );\r\n\tpParams->GetVector( CRCD(0x829fe7dd,\"BoxDimsEnd\"), &part.m_BoxDims[Nx::vBOX_END] );\r\n\r\n\tpart.m_BoxDims[Nx::vBOX_START] *= scale;\r\n\tpart.m_BoxDims[Nx::vBOX_MID] *= scale;\r\n\tpart.m_BoxDims[Nx::vBOX_END] *= scale;\r\n\r\n\tpart.m_BoxDims[Nx::vBOX_START] = orientation.Transform( part.m_BoxDims[Nx::vBOX_START] );\r\n\tpart.m_BoxDims[Nx::vBOX_MID] = orientation.Transform( part.m_BoxDims[Nx::vBOX_MID] );\r\n\tpart.m_BoxDims[Nx::vBOX_END] = orientation.Transform( part.m_BoxDims[Nx::vBOX_END] );\r\n\r\n\tpart.m_UseMidcolor = pParams->ContainsFlag(CRCD(0x454962ef,\"UseColorMidTime\"));\r\n\r\n\tpParams->GetFloat( CRCD(0x59463c93,\"ColorMidTime\"), &part.m_MidpointPct );\r\n\r\n\tif( pParams->GetArray( CRCD(0xdab75b6c,\"StartRGB\"), &array ))\r\n\t{\r\n\t\tcolor = array->GetInt( 0 );\r\n\t\tpart.m_Color[Nx::vBOX_START].r = (uint8) color;\r\n\t\tcolor = array->GetInt( 1 );\r\n\t\tpart.m_Color[Nx::vBOX_START].g = (uint8) color;\r\n\t\tcolor = array->GetInt( 2 );\r\n\t\tpart.m_Color[Nx::vBOX_START].b = (uint8) color;\r\n\t}\r\n\tif( pParams->GetArray( CRCD(0x444769a,\"MidRGB\"), &array ))\r\n\t{\r\n\t\tcolor = array->GetInt( 0 );\r\n\t\tpart.m_Color[Nx::vBOX_MID].r = (uint8) color;\r\n\t\tcolor = array->GetInt( 1 );\r\n\t\tpart.m_Color[Nx::vBOX_MID].g = (uint8) color;\r\n\t\tcolor = array->GetInt( 2 );\r\n\t\tpart.m_Color[Nx::vBOX_MID].b = (uint8) color;\r\n\t}\r\n\tif( pParams->GetArray( CRCD(0x5a3728e7,\"EndRGB\"), &array ))\r\n\t{\r\n\t\tcolor = array->GetInt( 0 );\r\n\t\tpart.m_Color[Nx::vBOX_END].r = (uint8) color;\r\n\t\tcolor = array->GetInt( 1 );\r\n\t\tpart.m_Color[Nx::vBOX_END].g = (uint8) color;\r\n\t\tcolor = array->GetInt( 2 );\r\n\t\tpart.m_Color[Nx::vBOX_END].b = (uint8) color;\r\n\t}\r\n\r\n\tif( pParams->GetInteger( CRCD(0x4d83db4c,\"StartAlpha\"), &color ))\r\n\t{\r\n\t\tpart.m_Color[Nx::vBOX_START].a = (uint8) color;\r\n\t}\r\n\tif( pParams->GetInteger( CRCD(0x4aba1ff1,\"MidAlpha\"), &color ))\r\n\t{\r\n\t\tpart.m_Color[Nx::vBOX_MID].a = (uint8) color;\r\n\t}\r\n\tif( pParams->GetInteger( CRCD(0x5cf83aca,\"EndAlpha\"), &color ))\r\n\t{\r\n\t\tpart.m_Color[Nx::vBOX_END].a = (uint8) color;\r\n\t}\r\n\t\r\n\tpParams->GetChecksum( CRCD(0xdd6bb3d5,\"BlendMode\"), &part.m_BlendMode );\r\n\tpParams->GetInteger( CRCD(0x9f677d4e,\"AlphaCutoff\"), &part.m_AlphaCutoff );\r\n\tpParams->GetInteger( CRCD(0x13d0be1d,\"FixedAlpha\"), &part.m_FixedAlpha );\r\n\tpParams->GetChecksum( CRCD(0x7d99f28d,\"Texture\"), &part.m_Texture );\r\n\t\r\n\tpParams->GetInteger( CRCD(0x4eedfae7,\"lod_dist1\"), &part.m_LODDistance1 );\r\n\tpParams->GetInteger( CRCD(0xd7e4ab5d,\"lod_dist2\"), &part.m_LODDistance2 );\r\n\tpParams->GetInteger( CRCD(0xe4279ba2,\"SuspendDistance\"), &part.m_SuspendDistance );\r\n\r\n\tpart.m_RotMatrix.Ident();\t  // Mick: THis was missing before, so not sure how it could have worked\r\n\r\n\tangles.Set();\r\n\tpParams->GetVector( CRCD(0x9d2d0915,\"Angles\"), &angles );\r\n\r\n\tpart.m_RotMatrix.RotateX( angles[X] );\r\n\tpart.m_RotMatrix.RotateY( angles[Y] );\r\n\tpart.m_RotMatrix.RotateZ( angles[Z] );\r\n\t\r\n\r\n\tif (part.m_LocalCoord = pParams->ContainsFlag(CRCD(0xb7b7240d,\"LocalSpace\")))\r\n\t{\r\n\t\tfor (int i = 0; i < Nx::vNUM_BOXES; i++)\r\n\t\t{\r\n\t\t\tpart.m_LocalBoxPos[i] = part.m_BoxPos[i];\r\n\t\t}\r\n\t}\r\n\r\n\tmp_particle = Nx::CEngine::sGetParticleManager()->CreateParticle( &part, generate_name );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CParticleComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calline InitFromStructure()\r\n\t// but if that does not handle it, then will need to write a specific \r\n\t// function here. \r\n\t// The user might only want to update a single field in the structure\r\n\t// and we don't want to be asserting becasue everything is missing \r\n\t\r\n\t//InitFromStructure(pParams);\r\n\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CParticleComponent::Finalize()\r\n{\r\n\tmp_suspend_component =  GetSuspendComponentFromObject( GetObject() );\r\n}\r\n\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCParticleComponent::Hide( bool should_hide )\r\n{\r\n\r\n\tmp_particle->Hide(should_hide);\r\n\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CParticleComponent::Update()\r\n{\r\n\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\r\n\t// If it's a limited-time particle system in net games (like fireballs) never suspend the\r\n\t// logic\r\n\tif (!mp_suspend_component || !mp_suspend_component->SkipLogic() || \r\n\t\t( gamenet_man->InNetGame() && ( m_system_lifetime > 0 )))\r\n\t{\r\n\t\t// **  You would put in here the stuff that you would want to get run every frame\r\n\t\t// **  for example, a physics type component might update the position and orientation\r\n\t\t// **  and update the internal physics state \r\n\t\tif( m_update_script )\r\n\t\t{\r\n\t\t\tScript::RunScript( m_update_script, NULL, GetObject() );\r\n\t\t}\r\n\t\r\n\t\tif( m_system_lifetime > 0 )\r\n\t\t{\r\n\t\t\tif(( Tmr::GetTime() - m_birth_time ) > m_system_lifetime )\r\n\t\t\t{\r\n\t\t\t\tGetObject()->MarkAsDead();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\t// If we are using local coordinates, update all the world parameters in the\r\n\t\t// particle instance.\r\n\t\tif (mp_particle->GetParameters()->m_LocalCoord)\r\n\t\t{\r\n\t\t\tfor (int i = 0; i < Nx::vNUM_BOXES; i++)\r\n\t\t\t{\r\n\t\t\t\tMth::Vector world_pos(mp_particle->GetParameters()->m_LocalBoxPos[i] + GetObject()->m_pos );\r\n\t\t\t\t//Mth::Vector world_pos(mp_particle->GetParameters()->m_LocalBoxPos[i] + Mth::Vector(100.0f, 100.0f, 0.0f));\r\n\t\t\t\t\r\n\t\t\t\tmp_particle->SetBoxPos(i, &world_pos);\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CParticleComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tcase 0x88be2262:\t// SetStartPos\r\n\t\t{\r\n\t\t\tMth::Vector pos;\r\n\r\n\t\t\tpParams->GetVector( NONAME, &pos, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tmp_particle->SetBoxPos( Nx::vBOX_START, &pos );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n        case 0xbb6018f4:\t// SetMidPos\r\n\t\t{\r\n\t\t\tMth::Vector pos;\r\n\r\n\t\t\tpParams->GetVector( NONAME, &pos, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tmp_particle->SetBoxPos( Nx::vBOX_MID, &pos );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0xe5134689:\t// SetEndPos\r\n\t\t{\r\n\t\t\tMth::Vector pos;\r\n\r\n\t\t\tpParams->GetVector( NONAME, &pos, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tmp_particle->SetBoxPos( Nx::vBOX_END, &pos );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0xf71d696e:\t// SetStartBoxDimensions\r\n\t\t{\r\n\t\t\tMth::Vector dims;\r\n\r\n\t\t\tpParams->GetVector( NONAME, &dims, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tmp_particle->SetBoxDims( Nx::vBOX_START, &dims );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0xaab006d:\t\t// SetMidBoxDimensions\r\n\t\t{\r\n\t\t\tMth::Vector dims;\r\n\r\n\t\t\tpParams->GetVector( NONAME, &dims, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tmp_particle->SetBoxDims( Nx::vBOX_MID, &dims );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0xe2b99038:\t// SetEndBoxDimensions\r\n\t\t{\r\n\t\t\tMth::Vector dims;\r\n\r\n\t\t\tpParams->GetVector( NONAME, &dims, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tmp_particle->SetBoxDims( Nx::vBOX_END, &dims );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0xc036f4d0:\t// SetUpdateScript\r\n\t\t{\r\n\t\t\tpParams->GetChecksum( NONAME, &m_update_script, true );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0xc6525c4e:\t// SetEmitRate\r\n\t\t{\r\n\t\t\tfloat emit_rate;\r\n\r\n\t\t\tpParams->GetFloat( NONAME, &emit_rate, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tmp_particle->SetEmitRate( emit_rate );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0x31fcc8ed:\t// SetLifetime\r\n\t\t{\r\n\t\t\tfloat lifetime;\r\n\r\n\t\t\tpParams->GetFloat( NONAME, &lifetime, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tmp_particle->SetLifetime( lifetime );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0x19af74d1:\t// SetMidpointColorPct\r\n\t\t{\r\n\t\t\tfloat percent;\r\n\r\n\t\t\tpParams->GetFloat( NONAME, &percent, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tmp_particle->SetMidpointColorPct( percent );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0x4aa40fb5:\t// SetMidPointPCT\r\n\t\t{\r\n\t\t\tfloat percent;\r\n\r\n\t\t\tpParams->GetFloat( NONAME, &percent, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tmp_particle->SetMidpointPct( percent );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0x234ceabb:\t// SetStartRadius\r\n\t\t{\r\n\t\t\tfloat radius;\r\n\r\n\t\t\tpParams->GetFloat( NONAME, &radius, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tmp_particle->SetRadius( Nx::vBOX_START, radius );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0x9e100f60:\t// SetMidRadius\r\n\t\t{\r\n\t\t\tfloat radius;\r\n\r\n\t\t\tpParams->GetFloat( NONAME, &radius, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tmp_particle->SetRadius( Nx::vBOX_MID, radius );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0x2f0da461:\t// SetEndRadius\r\n\t\t{\r\n\t\t\tfloat radius;\r\n\r\n\t\t\tpParams->GetFloat( NONAME, &radius, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tmp_particle->SetRadius( Nx::vBOX_END, radius );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0xeeffae18:\t// SetStartColor\r\n\t\t{\r\n\t\t\tScript::CArray* array;\r\n\r\n\t\t\tpParams->GetArray( NONAME, &array, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tImage::RGBA color;\r\n\r\n\t\t\t\tcolor.r = array->GetInt( 0 );\r\n\t\t\t\tcolor.g = array->GetInt( 1 );\r\n\t\t\t\tcolor.b = array->GetInt( 2 );\r\n\t\t\t\tcolor.a = array->GetInt( 3 );\r\n\t\t\t\tmp_particle->SetColor( Nx::vBOX_START, &color );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0xfe869e8:\t\t// SetMidColor\r\n\t\t{\r\n\t\t\tScript::CArray* array;\r\n\r\n\t\t\tpParams->GetArray( NONAME, &array, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tImage::RGBA color;\r\n\r\n\t\t\t\tcolor.r = array->GetInt( 0 );\r\n\t\t\t\tcolor.g = array->GetInt( 1 );\r\n\t\t\t\tcolor.b = array->GetInt( 2 );\r\n\t\t\t\tcolor.a = array->GetInt( 3 );\r\n\t\t\t\tmp_particle->SetColor( Nx::vBOX_MID, &color );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0x19aa4cd3:\t// SetEndColor\r\n\t\t{\r\n\t\t\tScript::CArray* array;\r\n\r\n\t\t\tpParams->GetArray( NONAME, &array, true );\r\n\t\t\tif( mp_particle )\r\n\t\t\t{\r\n\t\t\t\tImage::RGBA color;\r\n\r\n\t\t\t\tcolor.r = array->GetInt( 0 );\r\n\t\t\t\tcolor.g = array->GetInt( 1 );\r\n\t\t\t\tcolor.b = array->GetInt( 2 );\r\n\t\t\t\tcolor.a = array->GetInt( 3 );\r\n\t\t\t\tmp_particle->SetColor( Nx::vBOX_END, &color );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CParticleComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tScript::CArray* array;\r\n\tNx::CParticleParams* part;\r\n\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CParticleComponent::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\tif( mp_particle )\r\n\t{\r\n\t\tpart = mp_particle->GetParameters();\r\n\r\n\t\tp_info->AddChecksum( CRCD(0x92276db,\"UpdateScript\"), m_update_script );\r\n\t\tp_info->AddChecksum( CRCD(0x7321a8d6,\"Type\"), part->m_Type );\r\n\t\tp_info->AddChecksum( CRCD(0xa7a5bffb,\"UseMidPoint\"), part->m_UseMidpoint );\r\n\t\t\r\n\t\tp_info->AddFloat(CRCD(0x3bee67c8,\"StartRadius\"), part->m_Radius[Nx::vBOX_START] );\r\n\t\tp_info->AddFloat(CRCD(0x8e39913d,\"MidRadius\"), part->m_Radius[Nx::vBOX_MID] );\r\n\t\tp_info->AddFloat(CRCD(0x3f243a3c,\"EndRadius\"), part->m_Radius[Nx::vBOX_END] );\r\n\t\r\n\t\tp_info->AddInteger(CRCD(0x9e52a20f,\"MaxStreams\"), part->m_MaxStreams );\r\n\t\tp_info->AddFloat(CRCD(0x35b65bd4,\"EmitRate\"), part->m_EmitRate );\r\n\t\tp_info->AddFloat(CRCD(0xc218cf77,\"Lifetime\"), part->m_Lifetime );\r\n\t\tp_info->AddFloat(CRCD(0x520682c6,\"MidPointPCT\"), part->m_MidpointPct );\r\n\t\t\r\n\t\tp_info->AddVector(CRCD(0x3d5ea6a4,\"StartPosition\"), part->m_BoxPos[Nx::vBOX_START] );\r\n\t\tp_info->AddVector(CRCD(0x4b51a2,\"MidPosition\"), part->m_BoxPos[Nx::vBOX_MID] );\r\n\t\tp_info->AddVector(CRCD(0x5854ab9e,\"EndPosition\"), part->m_BoxPos[Nx::vBOX_END] );\r\n\t\r\n\t\tp_info->AddVector(CRCD(0x9656f775,\"BoxDimsStart\"), part->m_BoxDims[Nx::vBOX_START] );\r\n\t\tp_info->AddVector(CRCD(0xc3cd20a2,\"BoxDimsMid\"), part->m_BoxDims[Nx::vBOX_MID] );\r\n\t\tp_info->AddVector(CRCD(0x829fe7dd,\"BoxDimsEnd\"), part->m_BoxDims[Nx::vBOX_END] );\r\n\t\r\n\t\tp_info->AddChecksum(CRCD(0x454962ef,\"UseColorMidTime\"), part->m_UseMidcolor );\r\n\t\t\r\n\t\tp_info->AddFloat(CRCD(0x59463c93,\"ColorMidTime\"), part->m_ColorMidpointPct );\r\n\t\r\n\t\tarray = new Script::CArray;\r\n\t\tarray->SetSizeAndType( 4, ESYMBOLTYPE_INTEGER );\r\n\t\tarray->SetInteger( 0, part->m_Color[Nx::vBOX_START].r );\r\n\t\tarray->SetInteger( 1, part->m_Color[Nx::vBOX_START].g );\r\n\t\tarray->SetInteger( 2, part->m_Color[Nx::vBOX_START].b );\r\n\t\tarray->SetInteger( 3, part->m_Color[Nx::vBOX_START].a );\r\n\t\tp_info->AddArray(CRCD(0xfb35aacf,\"StartColor\"), array );\r\n\t\tdelete array;\r\n\t\r\n\t\tarray = new Script::CArray;\r\n\t\tarray->SetSizeAndType( 4, ESYMBOLTYPE_INTEGER );\r\n\t\tarray->SetInteger( 0, part->m_Color[Nx::vBOX_MID].r );\r\n\t\tarray->SetInteger( 1, part->m_Color[Nx::vBOX_MID].g );\r\n\t\tarray->SetInteger( 2, part->m_Color[Nx::vBOX_MID].b );\r\n\t\tarray->SetInteger( 3, part->m_Color[Nx::vBOX_MID].a );\r\n\t\tp_info->AddArray(CRCD(0xfc0c6e72,\"MidColor\"), array );\r\n\t\tdelete array;\r\n\t\r\n\t\tarray = new Script::CArray;\r\n\t\tarray->SetSizeAndType( 4, ESYMBOLTYPE_INTEGER );\r\n\t\tarray->SetInteger( 0, part->m_Color[Nx::vBOX_END].r );\r\n\t\tarray->SetInteger( 1, part->m_Color[Nx::vBOX_END].g );\r\n\t\tarray->SetInteger( 2, part->m_Color[Nx::vBOX_END].b );\r\n\t\tarray->SetInteger( 3, part->m_Color[Nx::vBOX_END].a );\r\n\t\tp_info->AddArray(CRCD(0xea4e4b49,\"EndColor\"), array );\r\n\t\tdelete array;\r\n\t\r\n\t\tp_info->AddChecksum(CRCD(0xdd6bb3d5,\"BlendMode\"), part->m_BlendMode );\r\n\t\tp_info->AddInteger(CRCD(0x9f677d4e,\"AlphaCutoff\"), part->m_AlphaCutoff );\r\n\t\tp_info->AddChecksum(CRCD(0x7d99f28d,\"Texture\"), part->m_Texture );\r\n\t\t\r\n\t\tp_info->AddInteger(CRCD(0x4eedfae7,\"lod_dist1\"), part->m_LODDistance1 );\r\n\t\tp_info->AddInteger(CRCD(0xd7e4ab5d,\"lod_dist2\"), part->m_LODDistance2 );\r\n\t\tp_info->AddInteger(CRCD(0xe4279ba2,\"SuspendDistance\"), part->m_SuspendDistance );\r\n\t}\r\n\r\n// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/ParticleComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       ParticleComponent.h\r\n//* OWNER:          SPG\r\n//* CREATION DATE:  03/21/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_PARTICLECOMPONENT_H__\r\n#define __COMPONENTS_PARTICLECOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/components/suspendcomponent.h>\r\n#include <gfx/nxnewparticle.h>\r\n\r\n// Replace this with the CRCD of the component you are adding\r\n#define\t\tCRC_PARTICLE CRCD(0xa9db601e,\"Particle\")\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or \r\n//  given an object\t\t\t\t \r\n#define\t\tGetParticleComponent() ((Obj::CParticleComponent*)GetComponent(CRC_PARTICLE))\r\n#define\t\tGetParticleComponentFromObject(pObj) ((Obj::CParticleComponent*)(pObj)->GetComponent(CRC_PARTICLE))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CParticleComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CParticleComponent();\r\n    virtual ~CParticleComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void\t\t\t\t\tHide( bool should_hide );\r\n\tvirtual void\t\t\t\t\tFinalize();\r\n\t\t\r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\nprivate:\r\n\tuint32\t\t\t\tm_update_script;\r\n\tNx::CNewParticle*\tmp_particle;\r\n\tCSuspendComponent*\tmp_suspend_component;\r\n\tTmr::Time\t\t\tm_birth_time;\r\n\tuint32\t\t\t\tm_system_lifetime;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/PedLogicComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       PedLogicComponent.cpp\r\n//* OWNER:          Brad Bulkley\r\n//* CREATION DATE:  1/9/03\r\n//****************************************************************************\r\n\r\n// start autoduck documentation\r\n// @DOC pedlogiccomponent\r\n// @module pedlogiccomponent | None\r\n// @subindex Scripting Database\r\n// @index script | pedlogiccomponent\r\n\r\n#include <sk/components/skaterloopingsoundcomponent.h>\r\n#include <sk/components/skatersoundcomponent.h>\r\n\r\n#include <gel/components/pedlogiccomponent.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/motioncomponent.h>\r\n#include <gel/components/avoidcomponent.h>\r\n\r\n#include <gel/environment/terrain.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/pathob.h>\r\n#include <sk/objects/pathman.h>\r\n#include <sk/objects/skaterflags.h>\r\n#include <sk/engine/feeler.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n\r\n#include <sk/scripting/nodearray.h>\r\n\r\n#include <gfx/debuggfx.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n#define\tvDEFAULT_RANGE (10.0f)\r\n#define vACTION_WEIGHT_RESOLUTION (1000)\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CPedLogicComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CPedLogicComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPedLogicComponent::CPedLogicComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_PEDLOGIC );\r\n\r\n\t// reset whiskers\r\n\tfor ( int i = 0; i < vNUM_WHISKERS; i++ )\r\n\t\tm_whiskers[i] = 0.0;\r\n\r\n\tResetBias();\r\n\tm_turn_frames = 0;\r\n\tm_max_turn_frames = 0; // Script::GetInteger( CRCD( 0x793535f5, \"ped_turn_frames\" ), Script::ASSERT );\r\n\tmp_path_object_tracker = NULL;\r\n\r\n\tm_col_dist_above = Script::GetFloat( CRCD( 0x379d93d2, \"ped_skater_stick_dist_above\" ), Script::ASSERT );\r\n\tm_col_dist_below = Script::GetFloat( CRCD( 0x8715b7b2, \"ped_skater_stick_dist_below\" ), Script::ASSERT );\r\n\r\n\tm_flags = 0;\r\n\r\n\tm_original_max_vel = 0.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPedLogicComponent::~CPedLogicComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// ** Add code to parse the structure, and initialize the component\r\n\t// m_state = CRCD( 0x23db4aea, \"Idle\" );s\r\n\r\n\tpParams->GetInteger( CRCD( 0xe50d6573, \"nodeIndex\" ), &m_node_from, Script::ASSERT );\r\n\t// printf(\"m_node_from = %i\\n\", m_node_from);\r\n\tSkateScript::GetPosition( m_node_from, &m_wp_from );\r\n\tm_normal_lerp = 0.0f;\r\n\tm_display_normal = m_last_display_normal = m_current_normal = GetObject()->m_matrix[Y];\r\n\r\n\tpParams->GetFloat( CRCD( 0x367c4a1b, \"StickToGroundDistAbove\" ), &m_col_dist_above );\r\n\tpParams->GetFloat( CRCD( 0x86f46e7b, \"StickToGroundDistBelow\" ), &m_col_dist_below );\r\n\r\n\tm_current_display_matrix = GetObject()->GetDisplayMatrix();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::Update()\r\n{\t\r\n\tm_time = Tmr::FrameLength();\r\n\t\r\n\t// BB - Switch on the state and call the appropriate update function.\r\n\t// This step could be removed by having the logic for each state in \r\n\t// this function, but this will make it easier to split the component \r\n\t// if need be.  Plus it just looks cleaner.\r\n\tswitch ( m_state )\r\n\t{\r\n\t\tcase CRCC( 0x69b05e2c, \"generic\" ):\r\n\t\t\tGenericPedUpdate();\r\n\t\t\tbreak;\r\n\t\tcase CRCC( 0xa85af587, \"generic_skater\" ):\r\n\t\t\tGenericSkaterUpdate();\r\n\t\t\tbreak;\r\n\t\tcase CRCC(0x6367167b,\"lip_trick\"):\r\n\t\t\tUpdateLipDisplayMatrix();\r\n\t\t\tbreak;\r\n\t\tcase CRCC( 0x82b45a67, \"generic_standing\" ):\r\n\t\t\t// this is currently handled in script\r\n\t\t\tbreak;\r\n\tdefault:\r\n\t\t// Dbg_MsgAssert( 0, ( \"PedLogicComponent has unknown state %s\", Script::FindChecksumName( m_state ) ) );\r\n\t\tbreak;\r\n\t}\r\n\t// Gfx::AddDebugArrow( GetObject()->GetDisplayMatrix()[X] + GetObject()->m_pos, GetObject()->GetDisplayMatrix()[X] * 48 + GetObject()->m_pos, MAKE_RGB( 0, 0, 128 ), MAKE_RGB( 0, 0, 128 ), 1 );\r\n\t// Gfx::AddDebugArrow( GetObject()->GetDisplayMatrix()[Y] + GetObject()->m_pos, GetObject()->GetDisplayMatrix()[Y] * 48 + GetObject()->m_pos, MAKE_RGB( 0, 128, 0 ), MAKE_RGB( 0, 0, 128 ), 1 );\r\n\t// Gfx::AddDebugArrow( GetObject()->GetDisplayMatrix()[Z] + GetObject()->m_pos, GetObject()->GetDisplayMatrix()[Z] * 48 + GetObject()->m_pos, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 0, 0, 128 ), 1 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CPedLogicComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | Ped_SetLogicState | set the current state of the ped\r\n\t\t// @uparm name | state - eg, generic, generic_skater, etc.\r\n\t\tcase CRCC( 0x3685b765, \"Ped_SetLogicState\" ):\r\n\t\t\tpParams->GetChecksum( NONAME, &m_state, Script::ASSERT );\r\n\t\t\tbreak;\r\n\t\t// @script | Ped_InitPath | initializes the ped on his linked path and starts movement\r\n\t\tcase CRCC( 0xe9906815, \"Ped_InitPath\" ):\r\n\t\t{\r\n\t\t\tScript::CStruct* pNodeData = SkateScript::GetNode( m_node_from );\r\n\t\t\t// m_node_to = SkateScript::GetLink( pNodeData, Mth::Rnd( SkateScript::GetNumLinks( pNodeData ) ) );\r\n\t\t\t\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tint numLinks = SkateScript::GetNumLinks( m_node_from );\r\n\t\t\tDbg_MsgAssert( numLinks, ( \"Ped_InitPath called on %s, but path node %i has no links!\", Script::FindChecksumName( GetObject()->GetID() ), m_node_from ) );\r\n\t\t\t#endif\r\n\r\n\t\t\tm_node_to = SkateScript::GetLink( pNodeData, 0 );\r\n\t\t\tSkateScript::GetPosition( m_node_to, &m_wp_to );\r\n\t\t\tSelectNextWaypoint();\r\n\t\t\tm_flags |= PEDLOGIC_MOVING_ON_PATH;\r\n\t\t\tmp_path_object_tracker = Obj::CPathMan::Instance()->TrackPed( GetObject(), m_node_to );\r\n\t\t\t\r\n\t\t\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\t\t\tDbg_Assert( pMotionComp );\r\n\t\t\tpMotionComp->m_movingobj_status |= MOVINGOBJ_STATUS_ON_PATH;\r\n\r\n\t\t\t// turn the ped to face the right direction\r\n\t\t\tMth::Vector heading = ( m_wp_to - m_wp_from ).Normalize();\r\n\t\t\tMth::Matrix display_matrix = GetObject()->GetDisplayMatrix();\r\n\t\t\tdisplay_matrix[Z] = heading;\r\n\t\t\tdisplay_matrix.OrthoNormalizeAbout( Z );\r\n\t\t\tGetObject()->SetDisplayMatrix( display_matrix );\r\n\t\t\tm_current_display_matrix = display_matrix;\r\n\r\n\t\t\tMth::Vector current_pos = GetObject()->m_pos;\r\n\t\t\tfor ( int i = 0; i < vPOS_HISTORY_SIZE; i++ )\r\n\t\t\t\tm_pos_history[i] = current_pos;\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t// @script | Ped_StartMoving | start moving on path\r\n\t\tcase CRCC( 0xd711542, \"Ped_StartMoving\" ):\r\n\t\t{\r\n\t\t\tif ( m_flags & PEDLOGIC_STOPPED )\r\n\t\t\t{\r\n\t\t\t\tScript::CScript* pScript = Script::SpawnScript( CRCD( 0xbed339d4, \"ped_skater_start_moving\" ) );\r\n\t\t\t\tpScript->mpObject = GetObject();\r\n\t\t\t\tm_flags &= ~PEDLOGIC_STOPPED;\r\n\t\t\t}\r\n\t\t\tm_flags |= PEDLOGIC_MOVING_ON_PATH;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t// @script | Ped_StopMoving | stop moving on path\r\n\t\tcase CRCC( 0xcc85adfe, \"Ped_StopMoving\" ):\r\n\t\t\tm_flags &= ~PEDLOGIC_MOVING_ON_PATH;\r\n\t\t\tbreak;\r\n\t\t// @script | Ped_IsMoving | returns true if the ped is moving on the path\r\n\t\tcase CRCC(0x68d298b0,\"Ped_IsMoving\"):\r\n\t\t\treturn m_flags & PEDLOGIC_MOVING_ON_PATH ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\t\t// @script | Ped_SetStickToGroundDist | Set the distances the ped uses to check for ground\r\n\t\t// when sticking.  This check is not performed straight up and down, but at whatever\r\n\t\t// angle the ped is currently standing (his Y vector).\r\n\t\t// @parmopt float | StickToGroundDistAbove | | distance to check above the ped\r\n\t\t// @parmopt float | StickToGroundDistBelow | | distance to check below the ped\r\n\t\tcase CRCC( 0x2cc086dd, \"Ped_SetStickToGroundDist\" ):\r\n\t\t\tpParams->GetFloat( \"distAbove\", &m_col_dist_above );\r\n\t\t\tpParams->GetFloat( \"distBelow\", &m_col_dist_below );\r\n\t\t\tprintf(\"StickToGround distances set to %f (above), %f (below)\\n\", m_col_dist_above, m_col_dist_below);\r\n\t\t\tbreak;\r\n\t\t// @script | Ped_SetIsGrinding | used for manually setting the grind state on and off\r\n\t\t// @uparm 0 | 0 for off, anything else for on\r\n\t\tcase CRCC( 0xc643e8f5, \"Ped_SetIsGrinding\" ):\r\n\t\t{\r\n\t\t\tint is_grinding = 0;\r\n\t\t\tpParams->GetInteger( NONAME, &is_grinding, Script::ASSERT );\r\n\t\t\tif ( is_grinding != 0 )\r\n\t\t\t\tm_flags |= PEDLOGIC_GRINDING;\r\n\t\t\telse\r\n\t\t\t\tm_flags &= ~PEDLOGIC_GRINDING;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t// @script | Ped_GetCurrentVelocity | returns variable named velocity...\r\n\t\t// @flag max | get the maximum velocity, rather than the currnt velocity.\r\n\t\t// This is useful in case the ped is currently accelerating or decelerating \r\n\t\t// to achieve maximum velocity.\r\n\t\tcase CRCC( 0x13713760, \"Ped_GetCurrentVelocity\" ):\r\n\t\t{\r\n\t\t\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\t\t\tDbg_Assert( pMotionComp );\r\n\t\t\tpScript->GetParams()->AddFloat( CRCD( 0x41272956, \"velocity\" ), pMotionComp->m_vel_z );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t// @script | Ped_StoreMaxVelocity | stores the current max velocity, so you can\r\n\t\t// change it and restore it later\r\n\t\tcase CRCC( 0xf5627596, \"Ped_StoreMaxVelocity\" ):\r\n\t\t{\r\n\t\t\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\t\t\tDbg_Assert( pMotionComp );\r\n\t\t\tm_original_max_vel = pMotionComp->m_max_vel;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t// @script | Ped_GetOriginalMaxVelocity | returns original_max_velocity stored when \r\n\t\t// Ped_StoreMaxVelocity was called\r\n\t\tcase CRCC( 0xe575efa9, \"Ped_GetOriginalMaxVelocity\" ):\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddFloat( \"original_max_velocity\", m_original_max_vel );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t// @script | Ped_Bail |\r\n\t\tcase CRCC( 0xee24a410, \"Ped_Bail\" ):\r\n\t\t\tBail();\r\n\t\t\tbreak;\r\n\t\tcase CRCC( 0xc076d74, \"Ped_SetIsBailing\" ):\r\n\t\t{\r\n\t\t\tint v;\r\n\t\t\tpParams->GetInteger( NONAME, &v, Script::ASSERT );\r\n\t\t\tif ( pParams->ContainsFlag( CRCD( 0x255ed86f, \"grind\" ) ) )\r\n\t\t\t{\r\n\t\t\t\tif ( v == 0 )\r\n\t\t\t\t\tm_flags &= ~PEDLOGIC_GRIND_BAILING;\r\n\t\t\t\telse\r\n\t\t\t\t\tm_flags |= PEDLOGIC_GRIND_BAILING;\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( v == 0 )\r\n\t\t\t\t\tm_flags &= ~PEDLOGIC_BAILING;\r\n\t\t\t\telse\r\n\t\t\t\t\tm_flags |= PEDLOGIC_BAILING;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase CRCC( 0xda7be9e2, \"Ped_InitVertTrick\" ):\r\n\t\t{\r\n\t\t\t// get the height and gravity\r\n\t\t\tfloat height;\r\n\t\t\tpParams->GetFloat( CRCD( 0xab21af0, \"height\" ), &height, Script::ASSERT );\r\n\t\t\tfloat gravity;\r\n\t\t\tpParams->GetFloat( CRCD( 0xa5e2da58, \"gravity\" ), &gravity, Script::ASSERT );\r\n\t\t\tDbg_MsgAssert( gravity < 0.0f, ( \"Ped_InitVertTrick given positive number for gravity\" ) );\r\n\r\n\t\t\tMth::Vector pt = m_wp_to - GetObject()->m_pos;\r\n\t\t\t// adjust height to compensate for difference between ped height\r\n\t\t\t// and height of waypoint\r\n\t\t\t// height += pt[Y];\r\n\t\t\t// pt[Y] = 0.0f;\r\n\r\n\t\t\t// figure the time - the gravity is always expressed as negative \r\n\t\t\t// acceleration, but since we're figuring the time it will take to\r\n\t\t\t// fall from the top at velocity=0, we use positive\r\n\t\t\t// Multiply by 2 to get time up and down\r\n\t\t\t// d = vi*t + (a*t^2)/2\r\n\t\t\tfloat time = 2 * sqrtf( 2 * -height / gravity );\r\n\r\n\t\t\t// compute the inital y velocity, which equals the final y velocity when\r\n\t\t\t// falling back down (vf^2 = vi^2 + 2ad)\r\n\t\t\tfloat vi = sqrtf( 2 * gravity * -height );\r\n\t\t\tDbg_Assert( vi > 0 );\r\n\r\n\t\t\t// find the horizontal distance we need to travel\r\n\t\t\tfloat distance = pt.Length() / 2;\r\n\t\t\t// bump it up a bit so we don't miss landing\r\n\t\t\tdistance *= Script::GetFloat( CRCD( 0x2b5bedba, \"ped_skater_vert_jump_slop_distance\" ), Script::ASSERT );\r\n\r\n\t\t\t// horizontal velocity\r\n\t\t\tMth::Vector vh = ( distance / time ) * pt.Normalize();\r\n\r\n\t\t\t// vertical velocity\r\n\t\t\tMth::Vector vy = vi * Mth::Vector(0, 1, 0);\r\n\r\n\t\t\t// total speed and heading\r\n\t\t\t// float jump_speed = ( ( vh + vy ) * time ).Length();\r\n\t\t\tfloat jump_speed = ( vh + vy ).Length();\r\n\t\t\tMth::Vector heading = ( vh + vy ).Normalize();\r\n\r\n\t\t\tpScript->GetParams()->AddVector( CRCD( 0xfd4bc03e, \"heading\" ), heading );\r\n\t\t\tpScript->GetParams()->AddFloat( CRCD( 0x1c4c5690, \"jumpSpeed\" ), jump_speed );\r\n\t\t\tpScript->GetParams()->AddFloat( CRCD( 0x66ced87b, \"jumpTime\" ), time );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t// @script | Ped_HitWaypoint | force the ped to register a hit on the\r\n\t\t// to waypoint, regardless of his position.  Don't call this unless\r\n\t\t// you know exactly why you're doing it.\r\n\t\tcase CRCC( 0x1affffb3, \"Ped_HitWaypoint\" ):\r\n\t\t\tHitWaypoint();\r\n\t\t\tbreak;\r\n\t\t// @script | Ped_SetIsSkater | \r\n\t\t// @uparm 1 | 0 if not skater, anything else for skater\r\n\t\tcase CRCC( 0x5c794c57, \"Ped_SetIsSkater\" ):\r\n\t\t{\r\n\t\t\tint is_skater;\r\n\t\t\tpParams->GetInteger( NONAME, &is_skater, Script::ASSERT );\r\n\t\t\tif ( is_skater == 0 )\r\n\t\t\t\tm_flags &= ~PEDLOGIC_IS_SKATER;\r\n\t\t\telse\r\n\t\t\t\tm_flags |= PEDLOGIC_IS_SKATER;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t// @script | Ped_NearVertNode | true if the next node or the to node\r\n\t\t// is vert\r\n\t\tcase CRCC( 0x5bb23915, \"Ped_NearVertNode\" ):\r\n\t\t\treturn ( ( ( m_flags & PEDLOGIC_TO_NODE_IS_VERT )\r\n\t\t\t\t\t || ( m_flags & PEDLOGIC_NEXT_NODE_IS_VERT )\r\n\t\t\t\t\t || ( m_flags & PEDLOGIC_FROM_NODE_IS_VERT ) ) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE );\r\n\t\t\tbreak;\r\n\t\tcase CRCC( 0x56d9f55f, \"Ped_PlayJumpSound\" ):\r\n\t\t{\r\n\t\t\t//Dbg_MsgAssert( m_state == CRCD(0xa85af587,\"generic_skater\"), ( \"%s\\nPed_PlayJumpSound called on a non-skater ped %s\",pScript->GetScriptInfo(),Script::FindChecksumName(GetObject()->GetID()) ) );\r\n\t\t\tObj::CSkaterSoundComponent *pSoundComponent = GetSkaterSoundComponentFromObject( GetObject() );\r\n\t\t\tif ( pSoundComponent )\r\n\t\t\t\tpSoundComponent->PlayJumpSound(m_speed_fraction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase CRCC( 0x749de914, \"Ped_PlayLandSound\" ):\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( m_state == CRCD(0xa85af587,\"generic_skater\"), ( \"Ped_PlayLandSound called on a non-ped skater\" ) );\r\n\t\t\tObj::CSkaterSoundComponent *pSoundComponent = GetSkaterSoundComponentFromObject( GetObject() );\r\n\t\t\tif ( pSoundComponent )\r\n\t\t\t\tpSoundComponent->PlayLandSound(m_speed_fraction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase CRCC( 0x58a588b5, \"Ped_GetCurrentNodeNames\" ):\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddChecksum( CRCD( 0xd14cd5bc, \"node_to\" ), m_node_to );\r\n\t\t\tpScript->GetParams()->AddChecksum( CRCD( 0x8141d319, \"node_from\" ), m_node_from );\r\n\t\t\tpScript->GetParams()->AddChecksum( CRCD( 0x3c746255, \"node_next\" ), m_node_next );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to C......Component::GetDebugInfo\"));\r\n\tp_info->AddChecksum( \"m_state\", m_state );\r\n\t\r\n\tScript::CArray* pTempArray = new Script::CArray();\r\n\tpTempArray->SetSizeAndType( vNUM_WHISKERS, ESYMBOLTYPE_FLOAT );\r\n\tfor ( int i = 0; i < vNUM_WHISKERS; i++ )\r\n\t\tpTempArray->SetFloat( i, m_whiskers[i] );\r\n\tp_info->AddArray( \"m_whiskers\", pTempArray );\r\n\tfor ( int i = 0; i < vNUM_WHISKERS; i++ )\r\n\t\tpTempArray->SetFloat( i, m_bias[i] );\r\n\tp_info->AddArray( \"m_bias\", pTempArray );\r\n\tScript::CleanUpArray( pTempArray );\r\n\tdelete pTempArray;\r\n\r\n\tp_info->AddInteger( \"moving_on_path\", m_flags & PEDLOGIC_MOVING_ON_PATH );\r\n\r\n\tp_info->AddInteger( \"m_node_from\", m_node_from );\r\n\tp_info->AddInteger( \"m_node_to\", m_node_to );\r\n\tp_info->AddInteger( \"m_node_next\", m_node_next );\r\n\r\n\tp_info->AddVector( \"m_wp_from\", m_wp_from );\r\n\tp_info->AddVector( \"m_wp_to\", m_wp_to );\r\n\tp_info->AddVector( \"m_wp_next\", m_wp_next );\r\n\r\n\tp_info->AddInteger( \"m_turn_frames\", m_turn_frames );\r\n\tp_info->AddInteger( \"m_max_turn_frames\", m_max_turn_frames );\r\n\r\n\tp_info->AddInteger( \"m_is_grinding\", m_flags & PEDLOGIC_GRINDING );\r\n\r\n\tp_info->AddFloat( \"m_col_dist_above\", m_col_dist_above );\r\n\tp_info->AddFloat( \"m_col_dist_below\", m_col_dist_below );\r\n\t\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPedLogicComponent::GenericPedUpdate()\r\n{\t\r\n\tif ( !( m_flags & PEDLOGIC_MOVING_ON_PATH ) )\r\n\t\treturn;\r\n\r\n\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\tDbg_Assert( pMotionComp );\r\n\t// Obj::CPathObjectTracker* p_path_object_tracker = pMotionComp->mp_path_object_tracker;\r\n\r\n\tbool is_avoiding = CheckForOtherPeds();\t\r\n\tbool is_turning = UpdateTargetBias();\r\n\r\n\t// update bias based on path following\r\n\tif ( !is_turning && !is_avoiding )\r\n\t{\r\n\t\tUpdatePathBias();\r\n\t}\r\n\t\r\n\t// Gfx::AddDebugLine( m_wp_from, m_wp_to, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 1 );\r\n\t// Gfx::AddDebugLine( GetObject()->m_pos, m_wp_to, MAKE_RGB( 0, 0, 128 ), MAKE_RGB( 0, 0, 128 ), 1 );\r\n\r\n\t// move and decay\r\n\tpMotionComp->DoPathPhysics();\r\n\tUpdatePosition();\r\n\tDecayWhiskerBiases();\r\n\tpMotionComp->StickToGround();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::GenericSkaterUpdate()\r\n{\r\n\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\tDbg_Assert( pMotionComp );\r\n\tpMotionComp->DoPathPhysics();\r\n\tfloat distance = m_time * pMotionComp->m_vel_z;\r\n\tbool is_jumping = pMotionComp->m_movingobj_status & MOVINGOBJ_STATUS_JUMPING ? true : false;\r\n\r\n\t// Gfx::AddDebugLine( m_wp_from, m_wp_to, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 1 );\r\n\t// Gfx::AddDebugLine( GetObject()->m_pos, m_wp_to, MAKE_RGB( 0, 0, 128 ), MAKE_RGB( 0, 0, 128 ), 1 );\r\n\t// Gfx::AddDebugLine( m_pos_history[vPOS_HISTORY_SIZE - 2] + Mth::Vector( 0, 5, 1 ), m_pos_history[vPOS_HISTORY_SIZE - 1] + Mth::Vector( 0, 5, 1 ), MAKE_RGB( 0, 128, 0 ), MAKE_RGB( 0, 128, 0 ) );\r\n\t// Gfx::AddDebugArrow( GetObject()->GetDisplayMatrix()[Z] + GetObject()->m_pos, GetObject()->GetDisplayMatrix()[Z] * 24 + GetObject()->m_pos, MAKE_RGB( 0, 0, 128 ), MAKE_RGB( 0, 0, 128 ), 1 );\r\n\t\r\n\t// check for skater if we're grinding\r\n\tif ( m_flags & PEDLOGIC_GRINDING )\r\n\t{\r\n\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\tDbg_Assert( skate_mod );\r\n\t\tObj::CSkater* pSkater = skate_mod->GetLocalSkater();\r\n\t\tif ( pSkater )\r\n\t\t{\r\n\t\t\tfloat d = Mth::DistanceSqr( GetObject()->m_pos, pSkater->GetPos() );\r\n\t\t\t// printf(\"skater dist square = %f\\n\", d );\r\n\t\t\tif ( d < Script::GetFloat( CRCD( 0xbc2e678a, \"ped_skater_min_square_distance_to_skater\" ), Script::ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tGrindBail();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// see if we've hit the waypoint\r\n\tif ( ( m_flags & PEDLOGIC_MOVING_ON_PATH ) || is_jumping )\r\n\t{\r\n\t\tMth::Vector pt;\r\n\t\tif ( ( m_flags & PEDLOGIC_TO_NODE_IS_VERT ) || is_jumping )\r\n\t\t{\r\n\t\t\tpt = ( GetObject()->m_pos - m_wp_to );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tMth::Vector wp_to_no_y = m_wp_to;\r\n\t\t\twp_to_no_y[Y] = 0.0f;\r\n\t\t\tMth::Vector ped_pos_no_y = GetObject()->m_pos;\r\n\t\t\tped_pos_no_y[Y] = 0.0f;\r\n\t\t\tpt = ped_pos_no_y - wp_to_no_y;\r\n\t\t}\r\n\t\tfloat distance_to_target_square = pt.LengthSqr();\r\n\t\tint min_dist_square = Script::GetInteger( CRCD( 0xfb5d106f, \"ped_skater_min_square_distance_to_waypoint\" ), Script::ASSERT );\r\n\t\r\n\t\tif ( !( m_flags & PEDLOGIC_JUMPING_TO_NODE ) )\r\n\t\t{\r\n\t\t\tif ( distance_to_target_square < Mth::Sqr( distance ) )\r\n\t\t\t\tHitWaypoint();\r\n\t\t\telse if ( distance_to_target_square < min_dist_square )\r\n\t\t\t\tHitWaypoint();\r\n\t\t}\r\n\r\n\t\tif ( m_flags & PEDLOGIC_JUMP_AT_TO_NODE )\r\n\t\t{\r\n\t\t\tint dist_to_crouch = Script::GetInteger( CRCD( 0x52ec432f, \"ped_skater_min_square_distance_to_crouch_for_jump\" ), Script::ASSERT );\r\n\t\t\tif ( distance_to_target_square < dist_to_crouch )\r\n\t\t\t{\r\n\t\t\t\t// clear flag!\r\n\t\t\t\tm_flags &= ~PEDLOGIC_JUMP_AT_TO_NODE;\r\n\r\n\t\t\t\tScript::CScript* pScript = Script::SpawnScript( CRCD( 0x9c7ab5f5, \"ped_skater_crouch_for_jump\" ) );\r\n\t\t\t\tpScript->mpObject = GetObject();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// move\r\n\tif ( ( m_flags & PEDLOGIC_MOVING_ON_PATH ) && distance )\r\n\t{\r\n\t\tMth::Vector original_pos = GetObject()->m_pos;\r\n\t\tbool already_adjusted_heading = false;\r\n\t\tif ( ShouldUseBiases() )\r\n\t\t{\r\n\t\t\t// use biases to update position\r\n\t\t\tbool is_turning = UpdateTargetBias();\r\n\t\t\tif ( !is_turning )\r\n\t\t\t{\r\n\t\t\t\tUpdatePathBias();\r\n\t\t\t}\r\n\t\t\tUpdatePosition();\r\n\t\t\t\r\n\t\t\t// refresh the display matrix if we're jumping, as \r\n\t\t\t// AdjustHeading and AdjustNormal won't be called.\r\n\t\t\tif ( is_jumping )\r\n\t\t\t{\r\n\t\t\t\tRefreshDisplayMatrix();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// figure the new position\r\n\t\t\tMth::Vector new_pos = original_pos + ( distance * ( m_wp_to - GetObject()->m_pos ).Normalize() );\r\n\t\t\tUpdatePathBias();\r\n\t\t\tUpdatePosition();\t\t\t\r\n\t\t\tGetObject()->m_pos = new_pos;\r\n\t\t\tAdjustHeading( original_pos );\r\n\t\t\talready_adjusted_heading = true;\r\n\t\t}\r\n\r\n\t\t// stick to ground if we're not grinding or jumping\r\n\t\tif ( !( m_flags & PEDLOGIC_GRINDING )\r\n\t\t\t && !( m_flags & PEDLOGIC_GRIND_BAILING )\r\n\t\t\t && !is_jumping\r\n\t\t\t)\r\n\t\t{\r\n\t\t\tStickToGround();\r\n\t\t\t// update z vector\r\n\t\t\tif ( !already_adjusted_heading )\r\n\t\t\t\tAdjustHeading( original_pos );\r\n\t\t\tAdjustNormal();\r\n\t\t}\r\n\t}\r\n\telse // if ( !( pMotionComp->m_movingobj_status & MOVINGOBJ_STATUS_JUMPING ) )\r\n\t{\r\n\t\tRotatePosHistory();\r\n\t\tif ( m_flags & PEDLOGIC_TO_NODE_IS_VERT )\r\n\t\t{\r\n\t\t\t// AdjustHeading();\r\n\t\t}\r\n\t\tRefreshDisplayMatrix();\r\n\t\tif ( m_flags & PEDLOGIC_DOING_VERT_ROTATION || m_flags & PEDLOGIC_DOING_SPINE )\r\n\t\t{\r\n\t\t\tDoRotations();\r\n\t\t}\r\n\t}\r\n\r\n\t// update states for looping sounds\r\n\tif ( is_jumping )\r\n\t{\r\n\t\tUpdateSkaterSoundStates( AIR );\r\n\t}\r\n\telse if ( m_flags & PEDLOGIC_GRINDING )\r\n\t{\r\n\t\tUpdateSkaterSoundStates( RAIL );\r\n\t}\r\n\telse if ( m_flags & PEDLOGIC_MOVING_ON_PATH )\r\n\t{\r\n\t\tUpdateSkaterSoundStates( GROUND );\r\n\t}\r\n\telse if ( m_flags & PEDLOGIC_DOING_LIP_TRICK )\r\n\t{\r\n\t\tUpdateSkaterSoundStates( LIP );\r\n\t}\r\n \t\r\n\tif ( m_flags & PEDLOGIC_MOVING_ON_PATH )\r\n\t\tm_speed_fraction = ( pMotionComp->m_vel_z / pMotionComp->m_max_vel );\r\n\telse\r\n\t\tm_speed_fraction = 0.0f;\r\n\t\r\n\tObj::CSkaterLoopingSoundComponent* pLoopingSoundComp = GetSkaterLoopingSoundComponentFromObject( GetObject() );\r\n\tif ( pLoopingSoundComp )\r\n\t{\r\n\t\t// reset bailing flag\r\n\t\tpLoopingSoundComp->SetIsBailing( m_flags & PEDLOGIC_GRIND_BAILING || m_flags & PEDLOGIC_BAILING );\r\n\t\tpLoopingSoundComp->SetSpeedFraction( m_speed_fraction );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPedLogicComponent::CheckForOtherPeds()\r\n{\r\n\tbool is_avoiding = false;\r\n\tif ( mp_path_object_tracker )\r\n\t{\t\t\r\n\t\tconst CSmtPtr<CCompositeObject>* pp_object_list = mp_path_object_tracker->GetObjectList();\r\n\t\tMth::Matrix display_matrix = GetObject()->GetDisplayMatrix();\r\n\t\tfloat range = Script::GetFloat( CRCD( 0x7a78f471, \"ped_avoid_ped_range\" ) );\r\n\t\tfloat avoid_ped_bias = Script::GetFloat( CRCD( 0xd1e6177b, \"ped_avoid_ped_bias\" ) );\r\n\t\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\t\tDbg_Assert( pMotionComp );\r\n\r\n\t\tfor ( int i = 0; i < CPathObjectTracker::MAX_OBJECTS_PER_PATH; ++i )\r\n\t\t{\r\n\t\t\tif ( pp_object_list[i] )\r\n\t\t\t{\r\n\t\t\t\tCCompositeObject* p_ob=pp_object_list[i].Convert();\r\n\t\r\n\t\t\t\tif ( p_ob != GetObject() )\r\n\t\t\t\t{\r\n\t\t\t\t\t// ignore peds that are too far above or below\r\n\t\t\t\t\tfloat max_y_dist = Script::GetFloat( CRCD(0x21b13ffc,\"ped_max_y_distance_to_ignore\"), Script::ASSERT );\r\n\t\t\t\t\tif ( Mth::Abs( GetObject()->GetPos()[Y] - p_ob->GetPos()[Y] ) > max_y_dist )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t// ignore peds that are facing the opposite direction and walking away\r\n\t\t\t\t\tfloat z_dot = Mth::DotProduct( display_matrix[Z], p_ob->GetDisplayMatrix()[Z] );\r\n\t\t\t\t\tif ( z_dot <= 0.0f && Mth::DotProduct( display_matrix[Z], p_ob->GetPos() - GetObject()->GetPos() ) <= 0.0f )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// printf(\"walking away from each other\\n\");\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t// ignore peds that are facing the same direction and going faster than us\r\n\t\t\t\t\tObj::CMotionComponent* pObMotionComp = GetMotionComponentFromObject( p_ob );\r\n\t\t\t\t\tDbg_Assert( pObMotionComp );\r\n\t\t\t\t\tif ( z_dot > 0.0f && pObMotionComp->m_max_vel >= pMotionComp->m_max_vel )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// printf(\"he's going faster than me\\n\");\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tfloat d = Mth::Distance( GetObject()->GetPos(), p_ob->GetPos() );\t\t\t\t\t\r\n\t\t\t\t\tif ( d <= range )\r\n\t\t\t\t\t{\t\t\t\t\t\t\r\n\t\t\t\t\t\t// adjust whisker\r\n\t\t\t\t\t\t// find the heading\r\n\t\t\t\t\t\tfloat theta = acosf( z_dot / ( display_matrix[Z].Length() * p_ob->GetDisplayMatrix()[Z].Length() ) );\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// printf(\"theta = %f\\n\", theta);\r\n\t\t\t\t\t\t// reduce to less than 2pi.\r\n\t\t\t\t\t\tif ( theta > Mth::PI * 2 )\r\n\t\t\t\t\t\t\ttheta -= Mth::PI * 2 * (int)( theta / ( Mth::PI * 2 ) );\r\n\t\t\t\t\t\t// if they're coming straight at each other, we'll have to throw in some\r\n\t\t\t\t\t\t// sideways bias - we don't want them to stop moving or turn around\r\n\t\t\t\t\t\t// As they start to pass each other, the offset will naturally start\r\n\t\t\t\t\t\t// to create its own bias\r\n\t\t\t\t\t\tif ( fabs( theta - Mth::PI ) < Script::GetFloat( CRCD( 0xd2e22cec, \"ped_head_on_range\" ), Script::ASSERT ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// printf(\"he's coming right for me!\\n\");\r\n\t\t\t\t\t\t\t// left by default\r\n\t\t\t\t\t\t\ttheta = Mth::PI / 2;\r\n\t\t\t\t\t\t\t// see if we should push them right\r\n\t\t\t\t\t\t\t// if ( theta > Mth::PI )\r\n\t\t\t\t\t\t\tif ( ( Mth::CrossProduct( display_matrix[Z], p_ob->GetDisplayMatrix()[Z] ) )[Y] < 0 )\r\n\t\t\t\t\t\t\t\ttheta *= -1;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tis_avoiding = true;\r\n\t\t\t\t\t\tAddWhiskerBias( theta, avoid_ped_bias, d, range );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn is_avoiding;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::UpdatePathBias()\r\n{\r\n\tMth::Vector wp_from_no_y = m_wp_from;\r\n\twp_from_no_y[Y] = 0.0f;\r\n\tMth::Vector wp_to_no_y = m_wp_to;\r\n\twp_to_no_y[Y] = 0.0f;\r\n\tMth::Vector ped_pos_no_y = GetObject()->m_pos;\r\n\tped_pos_no_y[Y] = 0.0f;\r\n\r\n\tfloat max_dist_to_path = Script::GetFloat( CRCD( 0xa876aa2c, \"ped_max_distance_to_path\" ), Script::ASSERT );\r\n\tMth::Vector ft = wp_to_no_y - wp_from_no_y;\r\n\tMth::Vector fp = ped_pos_no_y - wp_from_no_y;\r\n\r\n\t// need to store this vector so we can check the sign of y...\r\n\t// if it's negative, we're on one side of the path, positive for the other\r\n\tMth::Vector ft_cross_fp = Mth::CrossProduct( ft, fp );\r\n\r\n\t// get the direction we want to push the ped\r\n\tMth::Vector closest_pos_on_path = ( ( Mth::DotProduct( fp, ft ) / ft.LengthSqr() ) * ft ) + m_wp_from;\r\n\tclosest_pos_on_path[Y] = 0.0f;\r\n\tMth::Vector pos_to_path = closest_pos_on_path - ped_pos_no_y;\r\n\r\n\t// Gfx::AddDebugArrow( GetObject()->m_pos, closest_pos_on_path, MAKE_RGB( 0, 128, 0 ), MAKE_RGB( 0, 128, 0 ), 1 );\r\n\r\n\t// Mth::Matrix ob_matrix = GetObject()->m_matrix;\r\n\tMth::Matrix display_matrix = GetObject()->GetDisplayMatrix();\r\n\tfloat angle_to_path = Mth::GetAngle( display_matrix[Z], pos_to_path );\r\n\tif ( angle_to_path > 360.0f )\r\n\t\tangle_to_path -= 360.0f * (int)( angle_to_path / 360.0f );\r\n\tif ( Mth::CrossProduct( display_matrix[Z], pos_to_path )[Y] > 0 )\r\n\t\tangle_to_path = 360.0f - angle_to_path;\r\n\r\n\t// float path_length = Mth::Distance( m_wp_from, m_wp_to );\r\n\tfloat path_length = Mth::Distance( wp_from_no_y, wp_to_no_y );\r\n\tfloat current_distance = ft_cross_fp.Length() / path_length;\r\n\r\n\t// the bias should get stronger as we get farther away, approaching 1 as we \r\n\t// approach the max distance from the path\r\n\tfloat path_bias;\r\n\tif ( current_distance > max_dist_to_path )\r\n\t\tpath_bias = 1;\r\n\telse\r\n\t\tpath_bias = 1 - ( ( max_dist_to_path - current_distance ) / max_dist_to_path );\r\n\r\n\t// reset the bias to get back on the path\r\n\tif ( current_distance > Script::GetFloat( CRCD( 0x81085734, \"ped_min_distance_to_path\" ) ) )\r\n\t\tAdjustBias( Mth::DegToRad( angle_to_path ), path_bias );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPedLogicComponent::UpdateTargetBias()\r\n{\r\n\tbool is_turning = false;\r\n\tMth::Vector wp_to_no_y = m_wp_to;\r\n\twp_to_no_y[Y] = 0.0f;\r\n\tMth::Vector ped_pos_no_y = GetObject()->m_pos;\r\n\tped_pos_no_y[Y] = 0.0f;\r\n\tMth::Vector pt = ped_pos_no_y - wp_to_no_y;\r\n\tfloat distance_to_target_square = pt.LengthSqr();\r\n\t\r\n\tfloat target_bias = Script::GetFloat( CRCD(0x57342672,\"ped_target_node_bias\"), Script::ASSERT );\r\n\tResetBias();\r\n\r\n\tif ( m_node_next == m_node_from )\r\n\t{\r\n\t\tfloat min_square_distance_to_dead_end = Script::GetFloat( CRCD( 0x65b46f32, \"ped_walker_min_square_distance_to_dead_end\" ), Script::ASSERT );\r\n\t\tif ( distance_to_target_square <= min_square_distance_to_dead_end )\r\n\t\t{\r\n\t\t\tHitWaypoint();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint fade_bias_max_distance_square;\r\n\t\tif ( m_flags & PEDLOGIC_IS_SKATER )\r\n\t\t\tfade_bias_max_distance_square = Script::GetInteger( CRCD( 0x354beda1, \"ped_skater_fade_target_bias_max_distance_square\" ), Script::ASSERT );\r\n\t\telse\r\n\t\t\tfade_bias_max_distance_square = Script::GetInteger( CRCD( 0x5b21ab0e, \"ped_fade_target_bias_max_distance_square\" ), Script::ASSERT );\r\n\r\n\t\tif ( m_max_turn_frames && m_turn_frames >= m_max_turn_frames )\r\n\t\t{\r\n\t\t\tHitWaypoint();\r\n\t\t}\r\n\t\telse if ( m_node_next != -1 && distance_to_target_square < fade_bias_max_distance_square )\r\n\t\t{\r\n\t\t\t// do we need to reset m_max_turn_frames?\r\n\t\t\tif ( !m_max_turn_frames )\r\n\t\t\t{\r\n\t\t\t\t// figure how long it will take to get there if we don't turn\r\n\t\t\t\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\t\t\t\tDbg_Assert( pMotionComp );\r\n\t\t\t\t\r\n\t\t\t\tMth::Vector wp_from_no_y = m_wp_from;\r\n\t\t\t\twp_from_no_y[Y] = 0.0f;\r\n\t\t\t\tMth::Vector wp_to_no_y = m_wp_to;\r\n\t\t\t\twp_to_no_y[Y] = 0.0f;\r\n\t\t\t\tMth::Vector wp_next_no_y = m_wp_next;\r\n\t\t\t\twp_next_no_y[Y] = 0.0f;\r\n\r\n\t\t\t\tMth::Vector ft = wp_to_no_y - wp_from_no_y;\r\n\t\t\t\tMth::Vector tn = wp_next_no_y - wp_to_no_y;\r\n\r\n\t\t\t\tfloat angle_between_waypoints = Mth::DegToRad( Mth::GetAngle( ft, tn ) );\r\n\t\t\t\tfloat distance_to_waypoint_switch = sqrtf( ( 2 * distance_to_target_square ) * ( 1 + cosf( angle_between_waypoints ) ) );\r\n\t\t\t\tint frames = (int)( ( sqrtf( distance_to_waypoint_switch ) / pMotionComp->m_max_vel ) * 60.0f );\r\n\t\t\t\t// printf(\"frames = %i\\n\", frames);\r\n\t\t\t\tm_max_turn_frames = frames;\r\n\t\t\t\tif ( m_max_turn_frames <= 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_max_turn_frames = 1;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// int frames = (int)( ( sqrtf( distance_to_target_square ) / pMotionComp->m_max_vel ) * 60.0f );\r\n\t\t\t\t// m_max_turn_frames = frames / 2;\r\n\t\t\t}\r\n\t\r\n\t\t\t// add bias for new waypoint and adjust current target bias\r\n\t\t\tis_turning = true;\r\n\r\n\t\t\t// Guard against potential division by zero here.\r\n\t\t\tfloat target_bias_turn_percent;\r\n\t\t\tif( m_max_turn_frames == 0 )\r\n\t\t\t\ttarget_bias_turn_percent = 0.0f;\r\n\t\t\telse\r\n\t\t\t\ttarget_bias_turn_percent = 0.5f * ( 1 - (float)( m_max_turn_frames - m_turn_frames ) / (float)m_max_turn_frames );\r\n\r\n\t\t\tm_turn_frames++;\r\n\t\t\tAddTargetBias( m_wp_next, target_bias * target_bias_turn_percent );\r\n\t\t\ttarget_bias -= target_bias * target_bias_turn_percent;\r\n\t\t}\r\n\t}\r\n\tAddTargetBias( m_wp_to, target_bias );\r\n\treturn is_turning;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::UpdatePosition()\r\n{\r\n\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\tDbg_Assert( pMotionComp );\r\n\r\n\tfloat x_bias = GetTotalXBias();\r\n\tfloat z_bias = GetTotalZBias();\r\n\t// printf(\"x_bias = %f, z_bias = %f\\n\", x_bias, z_bias );\r\n\r\n\tMth::Vector last_pos = GetObject()->m_pos;\r\n\t\r\n\tRotatePosHistory();\r\n\t\r\n\tfloat vel = pMotionComp->m_vel_z;\r\n\tfloat distance_to_travel = vel * m_time;\r\n\tfloat x_distance = distance_to_travel * x_bias;\r\n\tfloat z_distance = distance_to_travel * z_bias;\r\n/*\tfloat total_bias = x_bias + z_bias;\r\n\tif ( !total_bias )\r\n\t\treturn;\r\n\tfloat vel = pMotionComp->m_vel_z;\r\n\r\n\tfloat distance_to_travel = vel * m_time;\r\n\tfloat x_distance = distance_to_travel * ( ( total_bias - x_bias ) / total_bias );\r\n\tif ( x_bias < 0 )\r\n\t\tx_distance *= -1;\r\n\tfloat z_distance = distance_to_travel * ( ( total_bias - z_bias ) / total_bias );\r\n\tif ( z_bias < 0 )\r\n\t\tz_distance *= -1;\r\n*/   \r\n\t// printf(\"x_dist = %f, z_dist = %f\\n\", x_distance, z_distance);\r\n\t// Mth::Matrix mat0 = GetObject()->m_matrix;\r\n\tMth::Matrix mat0 = GetObject()->GetDisplayMatrix();\r\n\tMth::Vector z_vect = mat0[Z] * z_distance;\r\n\tMth::Vector x_vect = mat0[X] * x_distance;\r\n\t\r\n\t// GetObject()->GetDisplayMatrix()[Z] = new_heading;\r\n\t// GetObject()->GetDisplayMatrix().OrthoNormalizeAbout( Z );\r\n\tGetObject()->m_pos += x_vect;\r\n\tGetObject()->m_pos += z_vect;\r\n\t\r\n\t// skaters do their own headings\r\n\tif ( last_pos != GetObject()->m_pos && !( m_flags & PEDLOGIC_IS_SKATER ) )\r\n\t\tAdjustHeading( last_pos );\r\n\r\n/*\r\n\tfloat angle_to_new_heading = atan2( x_distance, z_distance );\r\n\tif ( fabs( angle_to_new_heading ) > Script::GetFloat( \"ped_max_angle_to_heading\", Script::ASSERT ) )\r\n\t{\r\n\t\tGetObject()->GetDisplayMatrix().Rotate( mat0[Y], angle_to_new_heading );\r\n\t\t// mat0.Rotate( mat0[Y], angle_to_new_heading );\r\n\t\t// GetObject()->m_matrix.Rotate( mat0[Y], angle_to_new_heading );\r\n\t\t// printf( \"angle_to_new_heading = %f\\n\", Mth::RadToDeg( angle_to_new_heading ) );\r\n\t}\r\n*/\r\n\t// GetObject()->SetDisplayMatrix( mat0 );\r\n\t// GetObject()->m_matrix = mat0;\r\n\t// GetObject()->m_pos += adjustment;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::RotatePosHistory()\r\n{\r\n\tfor ( int i = 0; i < vPOS_HISTORY_SIZE - 1; i++ )\r\n\t{\r\n\t\tm_pos_history[i] = m_pos_history[i + 1];\r\n\t}\r\n\tm_pos_history[vPOS_HISTORY_SIZE - 1] = GetObject()->m_pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::AddTargetBias( Mth::Vector target, float target_bias )\r\n{\r\n\tMth::Matrix display_matrix = GetObject()->GetDisplayMatrix();\r\n\t\r\n\tMth::Vector ped_pos_no_y = GetObject()->m_pos;\r\n\tped_pos_no_y[Y] = 0.0f;\r\n\ttarget[Y] = 0.0f;\r\n\r\n\t// Mth::Vector pt = GetObject()->m_pos - target;\r\n\tMth::Vector pt = ped_pos_no_y - target;\r\n\tfloat angle_to_target = Mth::GetAngle( display_matrix[Z], pt );\r\n\tangle_to_target += 180.0f;\r\n\tif ( angle_to_target > 360.0f )\r\n\t\tangle_to_target -= 360.0f * (int)( angle_to_target / 360.0f );\r\n\r\n\tif ( ( Mth::CrossProduct( display_matrix[Z], pt ) )[Y] > 0 )\r\n\t\tangle_to_target = 360.0f - angle_to_target;\r\n\r\n\t// printf(\"angle_to_target = %f\\n\", angle_to_target );\r\n\t\r\n\t// add bias to get to the target - the target_bias is constant\r\n\tAdjustBias( Mth::DegToRad( angle_to_target ), target_bias );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::AddWhiskerBias( float angle, float amount, float distance, float range )\r\n{\r\n\t// for now, linearly decrease the bias amount within the range\r\n\tamount *= ( range - distance ) / range;\r\n\r\n\tfloat segment_arc = Mth::DegToRad( 360 / vNUM_WHISKERS );\r\n\tfor ( int i = 0; i < vNUM_WHISKERS; i++ )\r\n\t{\r\n\t\tfloat angle_between = ( segment_arc * i ) - angle;\r\n\t\t// make sure this is in the right quandrant\r\n\t\tif ( fabs ( angle_between ) >= Mth::PI / 2 && fabs( angle_between ) <= 3 * Mth::PI / 2 )\r\n\t\t\tcontinue;\r\n\r\n\t\t// float adjusted_amount = fabs( amount * sinf( angle_between ) );\r\n\t\tfloat adjusted_amount = amount * cosf( angle_between );\r\n\t\t// printf(\"adding %f to m_whiskers[%i]\\n\", adjusted_amount, i );\r\n\t\t// add this bias to the whisker\r\n\t\tm_whiskers[i] += adjusted_amount;\r\n\r\n\t\t// cap absolute value to 1\r\n\t\tif ( m_whiskers[i] > 1 )\r\n\t\t\tm_whiskers[i] = 1;\r\n\t\tif ( m_whiskers[i] < -1 )\r\n\t\t\tm_whiskers[i] = -1;\r\n\t}\r\n/*\r\n\tfloat segment_arc = Mth::DegToRad( 360 / vNUM_WHISKERS );\r\n\tfor ( int i = 0; i < vNUM_WHISKERS; i++ )\r\n\t{\r\n\t\tfloat angle_between = fabs( ( segment_arc * i ) - angle );\r\n\t\t\r\n\t\t// make sure this is less than 180 from the angle we're looking at\r\n\t\tif ( angle_between >= Mth::PI )\r\n\t\t\tcontinue;\r\n\r\n\t\t// don't bother with maxed bias\r\n\t\tif ( m_whiskers[i] == 1 )\r\n\t\t\tcontinue;\r\n\t\t\r\n\t\t// add this bias to the whisker\r\n\t\tm_whiskers[i] += fabs( amount * cos( angle_between ) );\r\n\r\n\t\t// cap to 1\r\n\t\tif ( m_whiskers[i] > 1 )\r\n\t\t\tm_whiskers[i] = 1;\r\n\t}\r\n*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::AdjustBias( float angle, float amount )\r\n{\r\n\t// printf(\"AdjustBias( %f, %f )\\n\", angle, amount );\r\n\t// translate the bias to the whisker(s)\r\n\t// makes sure the angle isn't greater than 360\r\n\t// printf(\"angle = %f\\n\", Mth::RadToDeg( angle ) );\r\n\tfloat segment_arc = Mth::DegToRad( 360 / vNUM_WHISKERS );\r\n\tfor ( int i = 0; i < vNUM_WHISKERS; i++ )\r\n\t{\t\t\r\n\t\tfloat angle_between = ( segment_arc * i ) - angle;\r\n\t\t\r\n\t\t// make sure this is in the right quandrant\r\n\t\tif ( fabs ( angle_between ) >= Mth::PI / 2 && fabs( angle_between ) <= 3 * Mth::PI / 2 )\r\n\t\t\tcontinue;\r\n\r\n\t\t// float adjusted_amount = fabs( amount * sinf( angle_between ) );\r\n\t\tfloat adjusted_amount = amount * cosf( angle_between );\r\n\t\t// printf(\"adding %f to m_bias[%i]\\n\", adjusted_amount, i );\r\n\t\t// add this bias to the whisker\r\n\t\tm_bias[i] += adjusted_amount;\r\n\r\n\t\t// cap absolute value to 1\r\n\t\tif ( m_bias[i] > 1 )\r\n\t\t\tm_bias[i] = 1;\r\n\t\tif ( m_bias[i] < -1 )\r\n\t\t\tm_bias[i] = -1;\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DecayWhiskerBiases()\r\n{\r\n\t// multiply each whisker by the decay factor\r\n\tfloat decay_factor = Script::GetFloat( CRCD( 0x98cd0c8c, \"ped_whisker_decay_factor\" ), Script::ASSERT );\r\n\tfloat min_bias = Script::GetFloat( CRCD( 0x4aba9798, \"ped_min_bias\" ), Script::ASSERT );\r\n\tfor ( int i = 0; i < vNUM_WHISKERS; i++ )\r\n\t{\r\n\t\tm_whiskers[i] *= decay_factor;\r\n\t\tif ( m_whiskers[i] < min_bias )\r\n\t\t\tm_whiskers[i] = 0;\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CPedLogicComponent::GetTotalXBias()\r\n{\r\n\tfloat total = 0.0f;\r\n\tfloat segment_arc = Mth::DegToRad( 360 / vNUM_WHISKERS );\r\n\tfor ( int i = 0; i < vNUM_WHISKERS; i++ )\r\n\t{\r\n\t\t// float angle = Mth::PI - ( segment_arc * i );\r\n\t\tfloat angle = segment_arc * i;\r\n\t\t// phase shift 180\r\n\t\t// angle += Mth::PI;\r\n\t\tfloat whisker_total = m_whiskers[i] + m_bias[i];\r\n\t\t// float whisker_total = m_whiskers[i];\r\n\t\t// float whisker_total = m_bias[i];\r\n    \tif ( whisker_total > 1 )\r\n\t\t\twhisker_total = 1;\r\n\t\t\r\n\t\ttotal += -sinf( angle ) * whisker_total;\r\n\t\t\r\n\t\tif ( total >= 1 )\r\n\t\t\treturn 1;\r\n\t\tif ( total <= -1 )\r\n\t\t\treturn -1;\r\n\t}\r\n\tif ( fabs( total ) < Script::GetFloat( CRCD( 0x4aba9798, \"ped_min_bias\" ), Script::ASSERT ) )\r\n\t\ttotal = 0;\r\n\t// remember that we're 180 degrees out of phase\r\n\treturn total;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CPedLogicComponent::GetTotalZBias()\r\n{\r\n\tfloat total = 0.0f;\r\n\tfloat segment_arc = Mth::DegToRad( 360 / vNUM_WHISKERS );\r\n\tfor ( int i = 0; i < vNUM_WHISKERS; i++ )\r\n\t{\r\n\t\tfloat angle = segment_arc * i;\r\n\t\t// phase shift 180\r\n\t\t// angle += Mth::PI;\r\n\t\tfloat whisker_total = m_whiskers[i] + m_bias[i];\r\n\t\t// float whisker_total = m_whiskers[i];\r\n\t\t// float whisker_total = m_bias[i];\r\n\t\tif ( whisker_total > 1 )\r\n\t\t\twhisker_total = 1;\r\n\t\tif ( whisker_total < -1 )\r\n\t\t\twhisker_total = -1;\r\n\t\t// printf(\"whisker_total[%i] = %f, angle = %f\\n\", i, whisker_total, angle);\r\n\t\t// 90 degree phase shift\r\n\t\t// total += cosf( angle ) * whisker_total;\r\n\t\ttotal += cosf( angle ) * whisker_total;\r\n\t\tif ( total >= 1)\r\n\t\t\treturn 1;\r\n\t\tif ( total <= -1 )\r\n\t\t\treturn -1;\r\n\t}\r\n\tif ( fabs( total ) < Script::GetFloat( CRCD( 0x4aba9798, \"ped_min_bias\" ), Script::ASSERT ) )\r\n\t\ttotal = 0;\r\n\t// return total;\r\n\treturn total;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::ResetBias()\r\n{\r\n\tfor ( int i = 0; i < vNUM_WHISKERS; i++ )\r\n\t\tm_bias[i] = 0;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::HitWaypoint()\r\n{\r\n\t// printf( \"CPedLogicComponent::HitWaypoint\\n\" );\r\n\tint hit_node = m_node_to;\r\n\tint old_from_node = m_node_from;\r\n\t\r\n\tm_flags &= ~PEDLOGIC_FROM_NODE_IS_VERT;\r\n\tm_flags &= ~PEDLOGIC_NEXT_NODE_IS_VERT;\r\n\tif ( m_flags & PEDLOGIC_TO_NODE_IS_VERT )\r\n\t\tm_flags |= PEDLOGIC_FROM_NODE_IS_VERT;\r\n\r\n\tm_flags &= ~PEDLOGIC_JUMPING_TO_NODE;\r\n\r\n\tm_node_from = m_node_to;\r\n\tm_node_to = m_node_next;\r\n\tm_wp_from = m_wp_to;\r\n\tm_wp_to = m_wp_next;\r\n\t\r\n\t// handle dead ends for ped walkers\r\n\tif ( !( m_flags & PEDLOGIC_IS_SKATER ) && old_from_node == m_node_to )\r\n\t{\r\n\t\tScript::CScript* pDeadEndScript = Script::SpawnScript( CRCD( 0xa80f965e, \"ped_walker_hit_dead_end\" ) );\r\n\t\tpDeadEndScript->mpObject = GetObject();\r\n\t}\r\n\t\r\n\t// update m_to_node_is_vert for distance checks\r\n\tm_flags &= ~PEDLOGIC_TO_NODE_IS_VERT;\r\n\t// m_to_node_is_vert = false;\r\n\tScript::CStruct* pToNodeData = SkateScript::GetNode( m_node_to );\r\n\r\n\tm_flags &= ~PEDLOGIC_TO_NODE_IS_LIP;\r\n\r\n\tuint32 to_node_type;\r\n\tif ( pToNodeData->GetChecksum( CRCD( 0x17ea37fb, \"PedType\" ), &to_node_type, Script::NO_ASSERT )\r\n\t\t && to_node_type == CRCD( 0x54166acd, \"skate\" ) )\r\n\t{\r\n\t\tuint32 to_node_action;\r\n\t\tpToNodeData->GetChecksum( CRCD( 0x963dc198, \"SkateAction\" ), &to_node_action, Script::ASSERT );\r\n\t\tif ( WaypointIsVert( m_node_to ) )\r\n\t\t{\r\n\t\t\tm_flags |= PEDLOGIC_TO_NODE_IS_VERT;\r\n\t\t\t// m_to_node_is_vert = true;\r\n\t\t}\r\n\t\t\r\n\t\t// check for a jump next - we'll need to crouch if we're not\r\n\t\t// already doing some action\r\n\t\tif ( to_node_action == CRCD( 0x7d9d0008, \"vert_grab\" )\r\n\t\t\t || to_node_action == CRCD( 0x584cf9e9, \"jump\" ) )\r\n\t\t{\r\n\t\t\t// make sure we're not coming from an action\r\n\t\t\tScript::CStruct* pFromNodeData = SkateScript::GetNode( m_node_from );\r\n\t\t\tuint32 from_node_action;\r\n\t\t\tif ( pFromNodeData->GetChecksum( CRCD( 0x963dc198, \"SkateAction\" ), &from_node_action, Script::ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tif ( from_node_action != CRCD( 0x255ed86f, \"grind\" )\r\n\t\t\t\t\t && !( m_flags & PEDLOGIC_GRINDING )\r\n\t\t\t\t\t && !( m_flags & PEDLOGIC_FROM_NODE_IS_VERT ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_flags |= PEDLOGIC_JUMP_AT_TO_NODE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( to_node_action == CRCD( 0x554dbd64, \"vert_lip\" ) )\r\n\t\t{\r\n\t\t\tm_flags |= PEDLOGIC_TO_NODE_IS_LIP;\r\n\t\t}\r\n\t}\r\n\t\r\n\tSelectNextWaypoint();\r\n\tif ( WaypointIsVert( m_node_next ) )\r\n\t\tm_flags |= PEDLOGIC_NEXT_NODE_IS_VERT;\r\n\r\n\t// we don't want to do any actions if we just came from a vert_grab node\r\n\tScript::CStruct* pOldFromNodeData = SkateScript::GetNode( old_from_node );\r\n\tuint32 old_skate_action;\r\n\tScript::CStruct* pNodeData = SkateScript::GetNode( hit_node );\r\n\tDbg_Assert( pNodeData );\r\n\tDoGenericNodeActions( pNodeData );\r\n\r\n\tif ( !( pOldFromNodeData->GetChecksum( CRCD( 0x963dc198, \"skateAction\" ), &old_skate_action )\r\n\t\t && old_skate_action == CRCD( 0x7d9d0008, \"Vert_Grab\" ) ) )\r\n\t{\r\n\t\tuint32 waypoint_type;\r\n\t\tif ( pNodeData->GetChecksum( CRCD( 0x17ea37fb, \"PedType\" ), &waypoint_type, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tswitch ( waypoint_type )\r\n\t\t\t{\r\n\t\t\tcase CRCC( 0x726e85aa, \"walk\" ):\r\n\t\t\t\tDoWalkActions( pNodeData );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0x54166acd, \"skate\" ):\r\n\t\t\t\tDoSkateActions( pNodeData );\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"Waypoint has bad PedType %s\", Script::FindChecksumName( waypoint_type ) ) );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tm_turn_frames = m_max_turn_frames = 0;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPedLogicComponent::WaypointIsVert( int waypoint )\r\n{\r\n\tScript::CStruct* pNodeData = SkateScript::GetNode( waypoint );\r\n\tuint32 node_action;\r\n\tif ( pNodeData->GetChecksum( CRCD( 0x963dc198, \"SkateAction\" ), &node_action, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tif ( node_action == CRCD( 0x7d9d0008, \"vert_grab\" )\r\n\t\t\t || node_action == CRCD( 0x554dbd64, \"vert_lip\" )\r\n\t\t\t || node_action == CRCD( 0xe6dfaec7, \"vert_grind\" )\r\n\t\t\t || node_action == CRCD( 0xda0723da, \"vert_land\" )\r\n\t\t\t || node_action == CRCD( 0xe8f91257, \"vert_flip\" )\r\n\t\t\t || node_action == CRCD( 0xd5b4f014, \"vert_jump\" ) )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DoWalkActions( Script::CStruct* pNodeData )\r\n{\r\n\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DoGenericNodeActions( Script::CStruct* pNodeData )\r\n{\r\n\tDbg_Assert( pNodeData );\r\n\t// check for special things we should do at this node\r\n\tif ( pNodeData->ContainsFlag( CRCD( 0x74e4bba5, \"AdjustSpeed\" ) ) )\r\n\t{\r\n\t\tif ( ShouldExecuteAction( pNodeData, CRCD( 0x922c5b59, \"AdjustSpeedWeight\" ) ) )\r\n\t\t{\r\n\t\t\tfloat percent;\r\n\t\t\tpNodeData->GetFloat( CRCD( 0xa04d16ec, \"AdjustSpeedPercent\" ), &percent, Script::ASSERT );\r\n\t\t\tAdjustSpeed( percent );\r\n\t\t}\r\n\t}\r\n\tif ( pNodeData->ContainsFlag( CRCD( 0x55d98ed7, \"RunScript\" ) ) )\r\n\t{\r\n\t\tif ( ShouldExecuteAction( pNodeData, CRCD( 0x86c9ccce, \"RunScriptWeight\" ) ) )\r\n\t\t{\r\n\t\t\tuint32 script_name;\r\n\t\t\tpNodeData->GetChecksum( CRCD( 0x64b4cd9d, \"RunScriptName\" ), &script_name, Script::ASSERT );\r\n\t\t\tScript::CScript* pScript = Script::SpawnScript( script_name );\r\n\t\t\tpScript->mpObject = GetObject();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DoSkateActions( Script::CStruct* pNodeData )\r\n{\r\n\t// we don't want to do any actions if we're bailing\r\n\tif ( ( m_flags & PEDLOGIC_BAILING ) || ( m_flags & PEDLOGIC_GRIND_BAILING ) )\r\n\t\treturn;\r\n\t\r\n\tDbg_Assert( pNodeData );\r\n\tuint32 skate_action;\r\n\tif ( pNodeData->GetChecksum( CRCD( 0x963dc198, \"SkateAction\" ), &skate_action, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tswitch ( skate_action )\r\n\t\t{\r\n\t\t\tcase CRCC( 0xec1cd520, \"continue\" ):\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0x255ed86f, \"grind\" ):\r\n\t\t\tcase CRCC( 0xe6dfaec7, \"vert_grind\" ):\r\n\t\t\t\tDoGrind( pNodeData );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0xc870bce5, \"grind_off\" ):\r\n\t\t\t\tDoGrindOff( pNodeData );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC(0xe41199af,\"grind_bail\"):\r\n\t\t\t\t// ignore these nodes...we must have fallen here from a grind\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC(0xba1d1e94,\"flip_trick\"):\r\n\t\t\t\tDoFlipTrick( pNodeData );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0xe8f91257, \"vert_flip\" ):\r\n\t\t\t\tDoFlipTrick( pNodeData, true );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0x12797a1b, \"grab_trick\" ):\r\n\t\t\t\tDoGrab( pNodeData );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0x7d9d0008, \"vert_grab\" ):\r\n\t\t\t\tDoGrab( pNodeData, true );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0x554dbd64, \"vert_lip\" ):\r\n\t\t\t\tDoLipTrick( pNodeData );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0xda0723da, \"vert_land\" ):\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0x584cf9e9, \"jump\" ):\r\n\t\t\t\tDoJump( pNodeData );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0xd5b4f014, \"vert_jump\" ):\r\n\t\t\t\tDoJump( pNodeData, true );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0x6d3144bf, \"Roll_off\" ):\r\n\t\t\t\tDoRollOff( pNodeData );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0xef24413b, \"manual\" ):\r\n\t\t\t\tDoManual( pNodeData );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0x9403a0ed, \"manual_down\" ):\r\n\t\t\t\tDoManualDown( pNodeData );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC( 0x46a9e949, \"stop\" ):\r\n\t\t\t\tStop( pNodeData );\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"DoSkateActions found unknown action %s\\n\", Script::FindChecksumName( skate_action ) ) );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::SelectNextWaypoint()\r\n{\r\n\t// are we on a grind bail path?\r\n\tbool on_grind_bail_path = false;\r\n\tScript::CStruct* pNode = SkateScript::GetNode( m_node_from );\r\n\tuint32 skate_action;\r\n\tif ( pNode->GetChecksum( CRCD( 0x963dc198, \"SkateAction\" ), &skate_action )\r\n\t\t && skate_action == CRCD( 0xe41199af, \"Grind_Bail\" ) )\r\n\t{\r\n\t\ton_grind_bail_path = true;\r\n\t}\r\n\t\r\n\tint waypoint;\r\n\tint numLinks;\r\n\tnumLinks = SkateScript::GetNumLinks( m_node_to );\r\n\r\n\tif ( numLinks == 0 )\r\n\t{\r\n\t\t// turn around\r\n\t\twaypoint = m_node_from;\r\n\t}\r\n\telse if ( numLinks == 1 ) // shortcut if there's only one link\r\n\t{\r\n\t\twaypoint = SkateScript::GetLink( m_node_to, 0 );\r\n\t\t\r\n\t\t// special case for jumping straight up in a pipe...land where you started\r\n\t\tif ( waypoint == m_node_from )\r\n\t\t{\r\n\t\t\tScript::CStruct* pToNodeData = SkateScript::GetNode( m_node_to );\r\n\t\t\tuint32 skate_action;\r\n\t\t\tif ( pToNodeData->GetChecksum( CRCD( 0x963dc198, \"skateAction\" ), &skate_action )\r\n\t\t\t\t && skate_action == CRCD( 0x7d9d0008, \"Vert_Grab\" ) )\r\n\t\t\t{\r\n\t\t\t\twaypoint = m_node_to;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// sort the links by priority\r\n\t\tMth::Vector to_from_vector = m_wp_to - m_wp_from;\r\n\t\tint valid_high_priority_choices[20];\r\n\t\tint valid_low_priority_choices[20];\r\n\t\tDbg_MsgAssert( numLinks < 20, ( \"Too many links (max is 20) from node %i\\n\", m_node_to ) );\r\n\t\tfor ( int i = 0; i < numLinks; i++ )\r\n\t\t{\r\n\t\t\tvalid_high_priority_choices[i] = i;\r\n\t\t\tvalid_low_priority_choices[i] = i;\r\n\t\t}\r\n\t\r\n\t\tint num_valid_low_choices = 0;\r\n\t\tint num_valid_high_choices = 0;\r\n\t\tint min_inner_angle = Script::GetInteger( CRCD( 0xfe65d822, \"ped_min_inner_path_angle\" ), Script::ASSERT );\r\n\t\t\r\n\t\t// store the max angle, so we can return the best choice if we don't find any good ones\r\n\t\tfloat max_angle = 0.0f;\r\n\t\tint max_angle_index = 0;\r\n\t\tfor ( int i = 0; i < numLinks; i++ )\r\n\t\t{\r\n\t\t\tint test_node = SkateScript::GetLink( m_node_to, i );\r\n\t\r\n\t\t\tif ( test_node != m_node_from )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pNodeData = SkateScript::GetNode( test_node );\r\n\r\n\t\t\t\t// ignore nodes that aren't PedAI waypoints\r\n\t\t\t\tuint32 class_type = 0;\r\n\t\t\t\tuint32 waypoint_type = 0;\r\n\t\t\t\tpNodeData->GetChecksum( CRCD( 0x12b4e660, \"class\" ), &class_type );\r\n\t\t\t\tpNodeData->GetChecksum( CRCD( 0x7321a8d6, \"Type\" ), &waypoint_type );\r\n\t\t\t\tif ( class_type != CRCD( 0x4c23a77e, \"Waypoint\" ) || waypoint_type != CRCD( 0xcba10ffa, \"PedAI\" ) )\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t\r\n\t\t\t\t// ignore Grind_Bail nodes unless we're already on a grind_bail path\r\n\t\t\t\tif ( !on_grind_bail_path )\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 skate_action;\r\n\t\t\t\t\tif ( pNodeData->GetChecksum( CRCD( 0x963dc198, \"SkateAction\" ), &skate_action )\r\n\t\t\t\t\t\t && skate_action == CRCD( 0xe41199af, \"Grind_Bail\" ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tMth::Vector test_node_position;\r\n\t\t\t\tSkateScript::GetPosition( test_node, &test_node_position );\r\n\t\t\t\tMth::Vector to_test_vector = m_wp_to - test_node_position;\r\n\t\t\t\tfloat angle = Mth::GetAngle( to_from_vector, to_test_vector );\r\n\t\t\t\tif ( angle > 360.0f )\r\n\t\t\t\t\tangle -= 360.0f * (int)( angle / 360.0f );\r\n\t\r\n\t\t\t\t// update max angle\r\n\t\t\t\tif ( angle > max_angle )\r\n\t\t\t\t{\r\n\t\t\t\t\tmax_angle = angle;\r\n\t\t\t\t\tmax_angle_index = i;\r\n\t\t\t\t}\r\n\t\t\r\n\t\t\t\tif ( angle >= min_inner_angle )\r\n\t\t\t\t{\r\n\t\t\t\t\t// sort nodes by priority\r\n\t\t\t\t\tuint32 priority;\r\n\t\t\t\t\tpNodeData->GetChecksum( CRCD( 0x9d5923d8, \"priority\" ), &priority, Script::ASSERT );\r\n\t\t\t\t\tswitch ( priority )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcase CRCC( 0xde7a971b, \"normal\" ):\r\n\t\t\t\t\t\t\tvalid_high_priority_choices[num_valid_high_choices] = i;\r\n\t\t\t\t\t\t\tnum_valid_high_choices++;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase CRCC(0x6d77875e,\"low\"):\r\n\t\t\t\t\t\t\tvalid_low_priority_choices[num_valid_low_choices] = i;\r\n\t\t\t\t\t\t\tnum_valid_low_choices++;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tDbg_MsgAssert( 0, ( \"Ped node has invalid priority\" ) );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// if there weren't any good choices, pick the best one\r\n\t\tif ( !( num_valid_high_choices || num_valid_low_choices ) )\r\n\t\t{\r\n\t\t\twaypoint = SkateScript::GetLink( m_node_to, max_angle_index );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbool find_low_priority = false;\r\n\t\t\t// decide if we should pick from a low priority or high priority node\r\n\t\t\tif ( num_valid_high_choices && num_valid_low_choices )\r\n\t\t\t{\t\t\t\r\n\t\t\t\tfloat low_priority_probability = Script::GetFloat( \"ped_low_priority_waypoint_probability\", Script::ASSERT );\r\n\t\t\t\tDbg_MsgAssert( low_priority_probability < 1, ( \"ped_low_priority_waypoint_probability is %f\", low_priority_probability ) );\r\n\t\t\t\tif ( Mth::Rnd( 100 ) <= ( low_priority_probability * 100 ) )\r\n\t\t\t\t\tfind_low_priority = true;\r\n\t\t\t}\r\n\t\t\telse if ( num_valid_low_choices )\r\n\t\t\t\tfind_low_priority = true;\r\n\t\t\t\r\n\t\t\t// select random index from valid choices\r\n\t\t\tif ( find_low_priority )\r\n\t\t\t\twaypoint = SkateScript::GetLink( m_node_to, valid_low_priority_choices[Mth::Rnd( num_valid_low_choices )] );\r\n\t\t\telse\r\n\t\t\t\twaypoint = SkateScript::GetLink( m_node_to, valid_high_priority_choices[Mth::Rnd( num_valid_high_choices )] );\r\n\t\t}\r\n\t}\r\n\t\r\n\t// make sure we got something\r\n\tif ( waypoint == -1 )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"SelectNextWaypoint couldn't find a valid waypoint\" ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_node_next = waypoint;\r\n\t\tSkateScript::GetPosition( m_node_next, &m_wp_next );\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPedLogicComponent::ShouldExecuteAction( Script::CStruct* pNodeData, uint32 weight_name )\r\n{\r\n\tfloat weight;\r\n\tpNodeData->GetFloat( weight_name, &weight, Script::ASSERT );\r\n\tDbg_MsgAssert( weight > 0 && weight <= 1, ( \"Waypoint %s has a bad action weight of %f\\n\", Script::FindChecksumName( GetObject()->GetID() ), weight ) );\r\n\tif ( weight > 0.99f )\r\n\t\treturn true;\r\n\treturn ( Mth::Rnd( vACTION_WEIGHT_RESOLUTION ) < ( weight * vACTION_WEIGHT_RESOLUTION ) );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::AdjustSpeed( float percent )\r\n{\r\n\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\tpMotionComp->m_max_vel *= percent;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::AdjustNormal()\r\n{\r\n\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\tDbg_Assert( pMotionComp );\r\n\tif ( pMotionComp )\r\n\t{\r\n\t\tObj::STriangle last_triangle = pMotionComp->m_last_triangle;\r\n\t\tMth::Vector v1 = last_triangle.mpVertices[1] - last_triangle.mpVertices[0];\r\n\t\tMth::Vector v2 = last_triangle.mpVertices[2] - last_triangle.mpVertices[0];\r\n\t\tMth::Vector normal = ( Mth::CrossProduct( v1, v2 ) ).Normalize();\r\n\t\tif ( normal[Y] < 0.0f )\r\n\t\t\tnormal = -normal;\r\n\r\n\t\tif ( normal != m_current_normal )\r\n\t\t{\r\n\t\t\tm_current_normal = normal;\t// remember this, for detecting if it changes\r\n\t\t\tm_last_display_normal = m_display_normal;\t// remember start position for lerping\r\n\t\t\tm_normal_lerp = 1.0f;\t// set lerp counter\r\n\t\t}\r\n\r\n\t\t// if m_normal_lerp is 0.0, then we don't need to do anything, as\r\n\t\t// we should already be there\r\n\t\tif ( m_normal_lerp != 0.0f )\t   \t\t// if lerping\r\n\t\t{\t\t\t\r\n\t\t\t// If the last display normal is the same as the current normal\r\n\t\t\t// then we can't interpolate between them\r\n\t\t\tif ( m_last_display_normal == m_current_normal )\r\n\t\t\t{\r\n\t\t\t\tm_normal_lerp = 0.0f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// adjust lerp at constant speed from 1.0 to 0.0, accounting for framerate\r\n\t\t\t\t// m_normal_lerp -= NORMAL_LERP_SPEED * (mp_physics->m_time * 60.0f);\r\n\t\t\t\tm_normal_lerp -= 0.1f * m_time * 60.0f;\r\n\t\t\r\n\t\t\t\t// if gone all the way, then clear lerping values\r\n\t\t\t\t// and set m_display_normal to be the current face normal\r\n\t\t\t\tif (m_normal_lerp <= 0.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_normal_lerp = 0.0f;\r\n\t\t\t\t\tm_display_normal = m_current_normal;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Still between old and current normal, so\r\n\t\t\t\t\t// calculate intermediate normal\r\n\t\t\t\t\tm_display_normal = Mth::Lerp( m_current_normal, m_last_display_normal, m_normal_lerp );\r\n\t\t\t\t\tm_display_normal.Normalize();\t\t// Must be normalized...\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Now update the orientation matrix.\r\n\t\t// We need our up (Y) vector to be this vector\r\n\t\t// if it changes, rotate the X and Z vectors to match\r\n\t\tMth::Matrix display_matrix = GetObject()->GetDisplayMatrix();\r\n\t\tif ( display_matrix[Y] != m_display_normal )\r\n\t\t{\r\n\t\t\tdisplay_matrix[Y] = m_display_normal;\r\n\t\t\tdisplay_matrix.OrthoNormalizeAbout( Y );\r\n\t\t\tGetObject()->SetDisplayMatrix( display_matrix );\r\n\t\t\tm_current_display_matrix = display_matrix;\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// testing out positional history\r\nvoid CPedLogicComponent::AdjustHeading()\r\n{\r\n\tAdjustHeading( m_pos_history[0] );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::AdjustHeading( Mth::Vector original_pos )\r\n{\r\n\tMth::Matrix mat0 = GetObject()->GetDisplayMatrix();\r\n\tMth::Vector new_pos = GetObject()->m_pos;\r\n\tif ( m_flags & PEDLOGIC_TO_NODE_IS_LIP )\r\n\t{\r\n\t\toriginal_pos = m_wp_from;\r\n\t\tnew_pos = m_wp_to;\r\n\t}\r\n\r\n\t// Gfx::AddDebugLine( original_pos, new_pos, MAKE_RGB( 0, 128, 0 ), MAKE_RGB( 0, 128, 0 ) );\r\n\t\r\n\t// change z vector\r\n\tmat0[Z] = ( new_pos - original_pos ).Normalize();\r\n\t// get new X and Y vectors\r\n\tmat0[X] = Mth::CrossProduct( mat0[Y], mat0[Z] );\t\r\n\tmat0[Y] = Mth::CrossProduct( mat0[Z], mat0[X] );\r\n\tGetObject()->SetDisplayMatrix( mat0 );\r\n\tm_current_display_matrix = mat0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::RefreshDisplayMatrix()\r\n{\r\n\tGetObject()->SetDisplayMatrix( m_current_display_matrix );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPedLogicComponent::do_collision_check( Mth::Vector *p_v0, Mth::Vector *p_v1, Mth::Vector *p_collisionPoint, \r\n\t\t\t\t\t\t\t\t Obj::STriangle *p_lastTriangle )\r\n{\r\n\t// First, see if there is a collision with the last triangle, and if there is, use that.\r\n\tCFeeler feeler;\r\n\tif ( feeler.GetCollision( *p_v0, *p_v1, false ) )\r\n\t{\r\n\t\tNx::CCollObj* p_col_obj=feeler.GetSector();\r\n\t\tDbg_MsgAssert( p_col_obj->IsTriangleCollision(), ( \"Not triangle collision !!!\" ) );\r\n\r\n\t\tNx::CCollObjTriData* p_tri_data=p_col_obj->GetGeometry();\r\n\t\tDbg_MsgAssert( p_tri_data, ( \"NULL p_tri_data\" ) );\r\n\r\n\t\tint face_index=feeler.GetFaceIndex();\r\n\t\tp_lastTriangle->mpVertices[0]=p_col_obj->GetVertexPos(p_tri_data->GetFaceVertIndex(face_index, 0));\r\n\t\tp_lastTriangle->mpVertices[1]=p_col_obj->GetVertexPos(p_tri_data->GetFaceVertIndex(face_index, 1));\r\n\t\tp_lastTriangle->mpVertices[2]=p_col_obj->GetVertexPos(p_tri_data->GetFaceVertIndex(face_index, 2));\r\n\r\n\t\t// if there is a collision, then snap to it\r\n\t\t*p_collisionPoint = feeler.GetPoint();\r\n\r\n\t\tUpdateSkaterSoundTerrain( feeler.GetTerrain() );\r\n\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::StickToGround()\r\n{\r\n\t// stick to ground modified from the motion component...uses\r\n\t// the ped's normal instead of the world's Y\r\n\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\tDbg_Assert( pMotionComp );\r\n\t\r\n\tMth::Vector v0, v1;\r\n\r\n\t// make sure our X vector is correct (got Z from the nav matrix...)\r\n\tGetObject()->m_matrix[X] = Mth::CrossProduct( GetObject()->m_matrix[Y], GetObject()->m_matrix[Z] );\r\n\tGetObject()->m_matrix[X].Normalize();\r\n\r\n\tMth::Matrix display_matrix = GetObject()->GetDisplayMatrix();\r\n\tv0 = GetObject()->m_pos + ( display_matrix[Y] * m_col_dist_above );\r\n\tv1 = GetObject()->m_pos + ( -display_matrix[Y] * m_col_dist_below );\r\n\t\r\n\tMth::Vector collision_point;\r\n\tif ( do_collision_check( &v0, &v1, &collision_point, &( pMotionComp->m_last_triangle ) ) )\r\n\t{\r\n\t\tGetObject()->m_pos = collision_point;\r\n\t\t// GetObject()->GetDisplayMatrix()[Mth::POS] = collision_point;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::UpdateSkaterSoundStates( EStateType state )\r\n{\r\n\tDbg_MsgAssert( m_state == CRCD( 0xa85af587, \"generic_skater\" ), ( \"CPedLogicComponent::UpdateSkaterSoundStates called on a non-skater ped\" ) );\r\n\r\n\tObj::CSkaterLoopingSoundComponent *pLoopingSoundComponent = GetSkaterLoopingSoundComponentFromObject( GetObject() );\r\n\tif ( pLoopingSoundComponent )\r\n\t\tpLoopingSoundComponent->SetState( state );\r\n\r\n\tObj::CSkaterSoundComponent *pSoundComponent = GetSkaterSoundComponentFromObject( GetObject() );\r\n\tif ( pSoundComponent )\r\n\t\tpSoundComponent->SetState( state );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::UpdateSkaterSoundTerrain( ETerrainType terrain )\r\n{\r\n\tDbg_MsgAssert( m_state == CRCD(0xa85af587,\"generic_skater\"), ( \"CPedLogicComponent::UpdateSkaterSoundTerrain called on non-skater ped\" ) );\r\n\r\n\t// set the terrain type for looping sound\r\n\tObj::CSkaterLoopingSoundComponent* pLoopingSoundComp = GetSkaterLoopingSoundComponentFromObject( GetObject() );\r\n\tif ( pLoopingSoundComp )\r\n\t\tpLoopingSoundComp->SetTerrain( terrain );\r\n\r\n\tObj::CSkaterSoundComponent *pSoundComponent = GetSkaterSoundComponentFromObject( GetObject() );\r\n\tif ( pSoundComponent )\r\n\t{\r\n\t\tpSoundComponent->SetTerrain( terrain );\r\n\t\tpSoundComponent->SetLastTerrain( terrain );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPedLogicComponent::ShouldUseBiases()\r\n{\r\n\treturn ( m_flags & PEDLOGIC_IS_SKATER\r\n\t\t\t && !( m_flags & PEDLOGIC_GRINDING )\r\n\t\t\t && !( m_flags & PEDLOGIC_GRIND_BAILING )\r\n\t\t\t && !( m_flags & PEDLOGIC_TO_NODE_IS_VERT )\r\n\t\t\t && !( m_flags & PEDLOGIC_FROM_NODE_IS_VERT )\r\n\t\t\t && !( m_flags & PEDLOGIC_JUMPING_TO_NODE )\r\n\t\t   );\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*             \t\t\tSkate Actions!                            */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* CPedLogicComponent::GetSkateActionParams( Script::CStruct* pNodeData )\r\n{\r\n\tScript::CStruct* pScriptParams = new Script::CStruct();\r\n\t// give higher priority to ped skater data - should this be reversed?\t\r\n\tpScriptParams->AppendStructure( pNodeData );\r\n\tpScriptParams->AppendStructure( GetObject()->GetTags() );\r\n\treturn pScriptParams;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DoGrind( Script::CStruct* pNodeData )\r\n{\r\n\t// printf(\"CPedLogicComponent::DoGrind\\n\");\r\n\tStopSkateActions();\r\n\t\r\n\t// m_is_grinding = true;\r\n\tm_flags |= PEDLOGIC_GRINDING;\r\n\r\n\t// set the terrain\r\n\tuint32 terrain_checksum;\r\n\t// TODO: Assert if terrain missing\r\n\tif ( pNodeData->GetChecksum( CRCD( 0x54cf8532, \"TerrainType\" ), &terrain_checksum, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tUpdateSkaterSoundTerrain( Env::CTerrainManager::sGetTerrainFromChecksum( terrain_checksum ) );\r\n\t}\r\n\r\n\tScript::CStruct* pScriptParams = GetSkateActionParams( pNodeData );\r\n\tScript::CScript* pScript = Script::SpawnScript( CRCD( 0xb7fca430, \"ped_skater_grind\" ), pScriptParams );\r\n\tpScript->mpObject = GetObject();\r\n\tdelete pScriptParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nvoid CPedLogicComponent::GrindUpdate()\r\n{\r\n\tm_grind_wobble_frames--;\r\n\tif ( m_grind_wobble_frames <= 0 )\r\n\t{\r\n\t\tprintf(\"setting the wobble target to %f\\n\", m_grind_wobble_target);\r\n\t\t// set new wobble target\r\n\t\tObj::CAnimationComponent* pAnimComp = GetAnimationComponentFromObject( GetObject() );\r\n\t\tDbg_Assert( pAnimComp );\r\n\t\tpAnimComp->SetWobbleTarget( m_grind_wobble_target, false );\r\n\t\tm_grind_wobble_target = -m_grind_wobble_target;\r\n\t\tm_grind_wobble_frames = Script::GetInteger( \"ped_skater_grind_wobble_frames\", Script::ASSERT );\r\n\t}\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DoGrindOff( Script::CStruct* pNodeData )\r\n{\r\n\tif ( m_flags & PEDLOGIC_GRINDING )\r\n\t{\r\n\t\t// m_is_grinding = false;\r\n\t\tm_flags &= ~PEDLOGIC_GRINDING;\r\n\t\r\n\t\tScript::CScript* pScript = Script::SpawnScript( CRCD( 0x84c51e26, \"ped_skater_grind_off\" ) );\r\n\t\tpScript->mpObject = GetObject();\r\n\t\t// delete pScriptParams;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DoJump( Script::CStruct* pNodeData, bool is_vert )\r\n{\r\n\tStopSkateActions();\r\n\t\r\n\t// call Obj_Jump on the object\r\n\tScript::CStruct* pScriptParams;\r\n\tScript::CScript* pScript;\r\n\tif ( is_vert )\r\n\t{\r\n\t\tm_flags &= ~PEDLOGIC_MOVING_ON_PATH;\r\n\t\tpScriptParams = GetJumpParams( pNodeData, is_vert );\r\n\t\tpScript = Script::SpawnScript( CRCD( 0x990152d7, \"ped_skater_vert_jump\" ), pScriptParams );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( pNodeData->ContainsFlag( CRCD( 0xb02567ae, \"JumpToNextNode\" ) ) )\r\n\t\t{\r\n\t\t\tm_flags &= ~PEDLOGIC_MOVING_ON_PATH;\r\n\t\t\tpScriptParams = GetJumpParams( pNodeData, is_vert );\r\n\t\t\tm_flags |= PEDLOGIC_JUMPING_TO_NODE;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpScriptParams = GetSkateActionParams( pNodeData );\r\n\t\t}\r\n\t\tpScript = Script::SpawnScript( CRCD( 0x28be3d25, \"ped_skater_jump\" ), pScriptParams );\r\n\t}\r\n\tpScript->mpObject = GetObject();\r\n\tdelete pScriptParams;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DoLipTrick( Script::CStruct* pNodeData )\r\n{\r\n\tStopSkateActions();\r\n\t\r\n\t// stop moving on path\r\n\tm_flags &= ~PEDLOGIC_MOVING_ON_PATH;\r\n\r\n\tUpdateLipDisplayMatrix();\r\n\t\r\n\tScript::CStruct* pScriptParams = GetSkateActionParams( pNodeData );\r\n\tScript::CScript* pScript = Script::SpawnScript( CRCD( 0x2fd2b4b8, \"ped_skater_lip_trick\" ), pScriptParams );\r\n\tpScript->mpObject = GetObject();\r\n\tdelete pScriptParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::UpdateLipDisplayMatrix()\r\n{\r\n\t// set the display matrix\r\n\tMth::Matrix mat0 = GetObject()->GetDisplayMatrix();\t\r\n\t\r\n\t// change z vector\r\n\tmat0[Z] = Mth::Vector(0, 1, 0);\r\n\tmat0[Y] = m_last_display_normal.Normalize();\r\n\t// get new X and Y vectors\r\n\tmat0[X] = Mth::CrossProduct( mat0[Y], mat0[Z] ).Normalize();\r\n\tmat0[Y] = Mth::CrossProduct( mat0[Z], mat0[X] ).Normalize();\r\n\tGetObject()->SetDisplayMatrix( mat0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DoManual( Script::CStruct* pNodeData )\r\n{\r\n\tStopSkateActions();\r\n\t\r\n\tScript::CStruct* pScriptParams = GetSkateActionParams( pNodeData );\r\n\tScript::CScript* pScript = Script::SpawnScript( CRCD( 0x1462af22, \"ped_skater_manual\" ), pScriptParams );\r\n\tpScript->mpObject = GetObject();\r\n\tdelete pScriptParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DoManualDown( Script::CStruct* pNodeData )\r\n{\r\n\tStopSkateActions();\r\n\t\r\n\tScript::CStruct* pScriptParams = GetSkateActionParams( pNodeData );\r\n\tScript::CScript* pScript = Script::SpawnScript( CRCD( 0x4c0caa11, \"ped_skater_manual_down\" ), pScriptParams );\r\n\tpScript->mpObject = GetObject();\r\n\tdelete pScriptParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* CPedLogicComponent::GetJumpParams( Script::CStruct* pNodeData, bool is_vert )\r\n{\r\n\tStopSkateActions();\r\n\r\n\t// stop moving on path \r\n\tm_flags &= ~PEDLOGIC_DOING_VERT_ROTATION;\r\n\tm_flags &= ~PEDLOGIC_DOING_SPINE;\r\n\r\n\t// reset angles\r\n\tm_spine_current_angle = 0.0f;\r\n\tm_spine_start_angle = 0.0f;\r\n\tm_rot_current_angle = 0.0f;\r\n\r\n\tScript::CStruct* pScriptParams = GetSkateActionParams( pNodeData );\r\n\t\r\n\t// figure heading and time\r\n\t// get the height and gravity\r\n\tfloat height;\r\n\tpNodeData->GetFloat( CRCD( 0x838da447, \"jumpHeight\" ), &height, Script::ASSERT );\r\n\tfloat gravity = Script::GetFloat( CRCD( 0xe224a5d3, \"ped_skater_jump_gravity\" ), Script::ASSERT );\r\n\r\n\tfloat time_total;\r\n\r\n\tif ( is_vert || pNodeData->ContainsFlag( CRCD( 0xb02567ae, \"JumpToNextNode\" ) ) )\r\n\t{\r\n\t\tMth::Vector pt = m_wp_to - GetObject()->m_pos;\r\n\t\tpt[Y] = 0.0f;\r\n\t\t\r\n\t\tif ( GetObject()->m_pos[Y] + height < m_wp_to[Y] )\r\n\t\t{\r\n\t\t\theight = m_wp_to[Y] - GetObject()->m_pos[Y] + Script::GetFloat( CRCD( 0x23f14b13, \"ped_skater_jump_to_next_node_height_slop\" ), Script::ASSERT );\t\t\t\t\t\t\r\n\t\t\t// Script::PrintContents( pNodeData );\r\n\t\t\t// Dbg_MsgAssert( 0, ( \"JumpToNextNode selected but jumpHeight isn't enough to reach target node.\" ) );\r\n\t\t}\t\t\r\n\t\t\r\n\t\t// adjust height to compensate for difference between ped height\r\n\t\t// and height of waypoint\r\n\t\t// height += pt[Y];\r\n\t\t// pt[Y] = 0.0f;\r\n\t\t\r\n\t\t// figure the time to rise\r\n\t\t// d = vi*t + (a*t^2)/2\r\n\t\tDbg_Assert( gravity < 0 );\r\n\t\tfloat time_to_rise = sqrtf( 2 * -height / gravity );\r\n\t\r\n\t\t// figure the time to fall\r\n\t\tfloat time_to_fall = sqrtf( 2 * Mth::Abs( ( GetObject()->m_pos[Y] + height - m_wp_to[Y] ) / gravity ) );\r\n\t\r\n\t\t// compute the inital y velocity\r\n\t\tfloat vi = ( height / time_to_rise ) - ( 0.5f * gravity * time_to_rise );\r\n\t\tDbg_Assert( vi > 0 );\r\n\t\r\n\t\t// find the horizontal distance we need to travel\r\n\t\tfloat distance = pt.Length();\r\n\t\r\n\t\t// horizontal velocity\r\n\t\ttime_total = time_to_rise + time_to_fall;\r\n\t\tMth::Vector vh = ( distance / time_total ) * pt.Normalize();\r\n\t\r\n\t\t// vertical velocity\r\n\t\tMth::Vector vy = vi * Mth::Vector(0, 1, 0);\r\n\t\r\n\t\t// total speed and heading\r\n\t\tfloat jump_speed = ( vh + vy ).Length();\r\n\t\tMth::Vector heading = ( vh + vy ).Normalize();\r\n\t\r\n\t\tpScriptParams->AddVector( CRCD( 0xfd4bc03e, \"heading\" ), heading );\r\n\t\tpScriptParams->AddFloat( CRCD( 0x1c4c5690, \"jumpSpeed\" ), jump_speed );\r\n\t\tpScriptParams->AddFloat( CRCD( 0x66ced87b, \"jumpTime\" ), time_total );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// just use the jump height\r\n\t\tfloat jump_speed = sqrtf( 2 * gravity * -height );\r\n\t\tpScriptParams->AddFloat( CRCD(0x1c4c5690,\"jumpSpeed\"), jump_speed );\r\n\r\n\t\ttime_total = 2 * sqrtf( 2 * -height * gravity );\r\n\t}\r\n\r\n\t// setup any rotation\r\n\tint rot_angle = 0;\r\n\tfloat rot_float;\r\n\tif ( pNodeData->ContainsFlag( CRCD( 0xb4077854, \"RandomSpin\" ) ) )\r\n\t{\r\n\t\t// figure the spin angle based on the time we've got\r\n\t\tfloat min_180_time = Script::GetFloat( CRCD( 0x8b381ab1, \"ped_skater_min_180_spin_time\" ), Script::ASSERT );\r\n\t\r\n\t\tint mult = (int)( time_total / min_180_time );\r\n\t\t// cap the rotation to 720 degrees\r\n\t\tif ( mult > 4 )\r\n\t\t\tmult = 4;\r\n\t\r\n\t\trot_angle = 180 * Mth::Rnd( mult + 1 );\r\n\t}\r\n\telse if ( pNodeData->GetFloat( CRCD( 0x96fb50d9, \"SpinAngle\" ), &rot_float, Script::NO_ASSERT ) )\r\n\t{\r\n\t\t// cast to int but make sure it doesn't get rounded down\r\n\t\trot_angle = (int)( rot_float + 0.01f );\r\n\t}\r\n\t\r\n\trot_angle = abs( rot_angle );\r\n\tif ( rot_angle > 0 )\r\n\t{\r\n\t\t// figure fs or bs\r\n\t\tuint32 spin_direction;\r\n\t\tpNodeData->GetChecksum( CRCD( 0xef0b71a0, \"SpinDirection\" ), &spin_direction, Script::ASSERT );\r\n\t\t\r\n\t\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\t\tbool is_flipped = pAnimationComponent->IsFlipped();\r\n\t\t\r\n\t\tswitch ( spin_direction )\r\n\t\t{\r\n\t\t\tcase CRCC( 0x20e1c4a3, \"BS\" ):\r\n\t\t\t{\r\n\t\t\t\tif ( is_flipped )\r\n\t\t\t\t{\r\n\t\t\t\t\trot_angle *= -1;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase CRCC( 0x448d01a7, \"FS\" ):\r\n\t\t\t{\r\n\t\t\t\tif ( !is_flipped )\r\n\t\t\t\t{\r\n\t\t\t\t\trot_angle *= -1;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase CRCC( 0xe7390a8b, \"Rand\" ):\r\n\t\t\t{\r\n\t\t\t\t// randomly change direction\r\n\t\t\t\tint toggle = Mth::Rnd( 2 );\r\n\t\t\t\tif ( toggle == 1 )\r\n\t\t\t\t{\r\n\t\t\t\t\trot_angle *= -1;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"Unknown SpinDirection\" ) );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tm_rot_angle = rot_angle;\r\n\t\tm_flags |= PEDLOGIC_DOING_VERT_ROTATION;\r\n\t}\r\n\r\n\tbool is_spine = pNodeData->ContainsFlag( CRCD( 0x4aa0cff, \"SpineTransfer\" ) );\r\n\tif ( rot_angle % 360 == 0 )\r\n\t{\r\n\t\tif ( !is_spine )\r\n\t\t\tpScriptParams->AddChecksum( NONAME, CRCD( 0x8868e76a, \"should_flip\" ) );\r\n\t}\r\n\telse if ( is_spine )\r\n\t{\r\n\t\tpScriptParams->AddChecksum( NONAME, CRCD( 0x8868e76a, \"should_flip\" ) );\r\n\t}\r\n\r\n\t// setup any spine trasnfer\r\n\tif ( is_spine )\r\n\t{\r\n\t\tm_flags |= PEDLOGIC_DOING_SPINE;\r\n\t\t\r\n\t\t// initialize spine angle to current angle between ped and vert\r\n\t\tMth::Vector temp_y(0, 1, 0);\r\n\t\tfloat spine_start = Mth::GetAngle( m_current_display_matrix[Z], temp_y );\r\n\t\tm_spine_start_angle = spine_start + Script::GetFloat( CRCD(0x95e91d23,\"ped_skater_spine_rotation_slop\") );\r\n\t}\r\n\r\n\tif ( m_flags & PEDLOGIC_DOING_SPINE || m_flags & PEDLOGIC_DOING_VERT_ROTATION )\r\n\t{\r\n\t\tm_rot_start_matrix = m_current_display_matrix;\r\n\t\tm_rot_total_time = time_total * Script::GetFloat( CRCD( 0xc1dfc97b, \"ped_skater_vert_rotation_time_slop\" ), Script::ASSERT );\r\n\t\tm_rot_current_time = 0.0f;\r\n\t}\r\n\r\n\t// check if we're jumping to the next node\r\n\tif ( pNodeData->ContainsFlag( CRCD( 0xb02567ae, \"JumpToNextNode\" ) ) )\r\n\t{\r\n\t\tpScriptParams->AddFloat( CRCD( 0xa1810c27, \"land_height\" ), m_wp_to[Y] );\r\n\t}\r\n\t\r\n\treturn pScriptParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DoGrab( Script::CStruct* pNodeData, bool is_vert )\r\n{\r\n\tScript::CStruct* pScriptParams;\r\n\tif ( is_vert )\r\n\t{\r\n\t\t// Obj::CAnimationComponent* pAnimComp = GetAnimationComponentFromObject( GetObject() );\r\n\t\t// printf(\"flipped = %i\\n\", pAnimComp->IsFlipped() );\r\n\r\n\t\tm_flags &= ~PEDLOGIC_MOVING_ON_PATH;\r\n\t\tpScriptParams = GetJumpParams( pNodeData, is_vert );\r\n\t\tpScriptParams->AddChecksum( NONAME, CRCD( 0x1615618, \"is_vert\" ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpScriptParams = GetSkateActionParams( pNodeData );\r\n\r\n\t\t// see if we're already jumping\r\n\t\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\t\tif ( pMotionComp->m_movingobj_status & MOVINGOBJ_STATUS_JUMPING )\r\n\t\t\tpScriptParams->AddInteger( CRCD( 0x65b5788d, \"is_jumping\" ), 1 );\r\n\t\telse\r\n\t\t{\r\n\t\t\t// figure out how long before we start to fall\r\n\t\t\tfloat jumpSpeed = Script::GetFloat( CRCD( 0xf1ff758a, \"ped_skater_jump_speed\" ), Script::ASSERT );\r\n\t\t\tfloat jumpGravity = Script::GetFloat( CRCD( 0xe224a5d3, \"ped_skater_jump_gravity\" ), Script::ASSERT );\r\n\t\t\tfloat time = 2 * sqrtf( Mth::Sqr( jumpSpeed ) / Mth::Sqr( jumpGravity ) );\r\n\t\t\tpScriptParams->AddInteger( CRCD( 0x66ced87b, \"jumpTime\" ), time );\r\n\t\t\tpScriptParams->AddInteger( CRCD( 0x65b5788d, \"is_jumping\" ), 0 );\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tScript::CScript* pScript = Script::SpawnScript( CRCD( 0x10585cb3, \"ped_skater_grab_trick\" ), pScriptParams );\r\n\tpScript->mpObject = GetObject();\r\n\t\r\n\tdelete pScriptParams;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DoRotations()\r\n{\r\n\tm_rot_current_time += m_time;\r\n\r\n\tfloat percent = m_time / m_rot_total_time;\r\n\tif ( percent > 1.0f )\r\n\t\tpercent = 1.0f;\r\n\r\n\tfloat spine_target_angle = 180.0f - m_spine_start_angle;\r\n\t\r\n\tif ( m_flags & PEDLOGIC_DOING_VERT_ROTATION )\r\n\t\tm_rot_current_angle += percent * (float)m_rot_angle;\r\n\tif ( m_flags & PEDLOGIC_DOING_SPINE )\r\n\t\tm_spine_current_angle += percent * spine_target_angle;\r\n\t\r\n\tif ( m_rot_current_time >= m_rot_total_time || percent >= 1.0f )\r\n\t{\r\n\t\tif ( m_flags & PEDLOGIC_DOING_VERT_ROTATION )\r\n\t\t\tm_rot_current_angle = (float)m_rot_angle;\r\n\t\tif ( m_flags & PEDLOGIC_DOING_SPINE )\r\n\t\t\tm_spine_current_angle = spine_target_angle;\r\n\r\n\t\tm_flags &= ~PEDLOGIC_DOING_VERT_ROTATION;\r\n\t\tm_flags &= ~PEDLOGIC_DOING_SPINE;\r\n\t}\r\n\r\n\t// cap spine angle\r\n\tif ( m_flags & PEDLOGIC_DOING_SPINE && m_spine_current_angle > spine_target_angle )\r\n\t{\r\n\t\tm_spine_current_angle = spine_target_angle;\r\n\t}\r\n\r\n\tMth::Matrix temp = m_rot_start_matrix;\r\n\ttemp.RotateLocal( Mth::Vector( Mth::DegToRad( m_spine_current_angle ), Mth::DegToRad( m_rot_current_angle ), 0 ) );\r\n\tGetObject()->SetDisplayMatrix( temp );\r\n\tm_current_display_matrix = temp;\r\n\tm_display_normal = m_last_display_normal = m_current_normal = temp[Y];\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::Stop( Script::CStruct* pNodeData )\r\n{\r\n\tStopSkateActions();\r\n\r\n\tm_flags |= PEDLOGIC_STOPPED;\r\n\t\r\n\tScript::CStruct* pScriptParams = GetSkateActionParams( pNodeData );\r\n\tScript::CScript* pScript = Script::SpawnScript( CRCD( 0x365b2d85, \"ped_skater_stop\" ), pScriptParams );\r\n\tpScript->mpObject = GetObject();\r\n\tdelete pScriptParams;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::StopSkateActions()\r\n{\r\n\t// BB - I moved this from script because it was too damn slow!\r\n\tScript::CArray* p_scripts_to_stop = Script::GetArray( CRCD( 0x2ecd9f57, \"ped_skater_action_scripts\" ), Script::ASSERT );\r\n\tint array_size = p_scripts_to_stop->GetSize();\r\n\tObj::CObject* p_object = (Obj::CObject*)GetObject();\r\n\t\r\n\tfor ( int i = 0; i < array_size; i++ )\r\n\t{\r\n\t\tuint32 script_to_stop = p_scripts_to_stop->GetChecksum( i );\r\n\t\tScript::StopScriptsUsingThisObject_Proper( p_object, script_to_stop );\r\n\t}\r\n\r\n\t// m_is_grinding = false;\r\n\tm_flags &= ~PEDLOGIC_GRINDING;\r\n\r\n\tm_flags &= ~PEDLOGIC_DOING_VERT_ROTATION;\r\n\tm_flags &= ~PEDLOGIC_DOING_SPINE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::Bail()\r\n{\r\n\t// kill any running bail scripts\r\n\tScript::StopScriptsUsingThisObject_Proper( GetObject(), CRCD(0xe630bf07,\"ped_skater_grind_bail\") );\r\n\tScript::StopScriptsUsingThisObject_Proper( GetObject(), CRCD(0x78131e4f,\"ped_skater_generic_bail\") );\r\n\r\n\t// restore the max current velocity before calling this script again!\r\n\tif ( m_original_max_vel > 0 )\r\n\t{\r\n\t\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\t\tDbg_Assert( pMotionComp );\r\n\t\tpMotionComp->m_max_vel = m_original_max_vel;\r\n\t}\r\n\t\r\n\tScript::CScript* pScript;\r\n\tif ( m_flags & PEDLOGIC_GRINDING )\r\n\t{\t\t\r\n\t\tpScript = Script::SpawnScript( CRCD(0xe630bf07,\"ped_skater_grind_bail\") );\r\n\t}\r\n\telse \r\n\t{\r\n\t\tpScript = Script::SpawnScript( CRCD(0x78131e4f,\"ped_skater_generic_bail\") );\r\n\t}\r\n\tStopSkateActions();\r\n\tpScript->mpObject = GetObject();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::GrindBail()\r\n{\r\n\tif ( m_flags & PEDLOGIC_GRINDING )\r\n\t{\r\n\t\tm_flags &= ~PEDLOGIC_GRINDING;\r\n\t\tm_flags |= PEDLOGIC_GRIND_BAILING;\r\n\t\r\n\t\t// select a new next node\r\n\t\tint num_links = SkateScript::GetNumLinks( m_node_to );\r\n\t\r\n\t\t// if there's only one link, we have to keep going...shitty\r\n\t\tif ( num_links > 1 )\r\n\t\t{\r\n\t\t\t// find a grind_bail node!\r\n\t\t\tfor ( int i = 0; i < num_links; i++ )\r\n\t\t\t{\r\n\t\t\t\tint test_node = SkateScript::GetLink( m_node_to, i );\r\n\t\t\t\tScript::CStruct* pNodeData = SkateScript::GetNode( test_node );\r\n\r\n\t\t\t\tuint32 skate_action;\r\n\t\t\t\tif ( pNodeData->GetChecksum( CRCD( 0x963dc198, \"skateAction\" ), &skate_action )\r\n\t\t\t\t\t && skate_action == CRCD( 0xe41199af, \"grind_bail\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_node_next = test_node;\r\n\t\t\t\t\tSkateScript::GetPosition( m_node_next, &m_wp_next );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// run script!\r\n\t\tScript::CScript* pScript = Script::SpawnScript( CRCD( 0xe630bf07, \"ped_skater_grind_bail\" ) );\r\n\t\tpScript->mpObject = GetObject();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DoRollOff( Script::CStruct* pNodeData )\r\n{\r\n\tScript::CScript* pScript = Script::SpawnScript( CRCD( 0xb183d99e, \"ped_skater_roll_off\" ) );\r\n\tpScript->mpObject = GetObject();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPedLogicComponent::DoFlipTrick( Script::CStruct* pNodeData, bool is_vert )\r\n{\r\n\tStopSkateActions();\r\n\t\r\n\t// jump if we need to\r\n\tObj::CMotionComponent* pMotionComp = GetMotionComponentFromObject( GetObject() );\r\n\tDbg_Assert( pMotionComp );\r\n\tScript::CStruct* pScriptParams = GetSkateActionParams( pNodeData );\r\n\r\n\tScript::CStruct *pJumpParams = GetJumpParams( pNodeData, is_vert );\r\n\tpScriptParams->AppendStructure( pJumpParams );\r\n\tdelete pJumpParams;\r\n\r\n\tif ( is_vert )\r\n\t{\r\n\t\tm_flags &= ~PEDLOGIC_MOVING_ON_PATH;\t\t\r\n\t\tpScriptParams->AddChecksum( NONAME, CRCD( 0x1615618, \"is_vert\" ) );\r\n\t}\r\n\r\n\t// check jumping state\r\n\tif ( pMotionComp->m_movingobj_status & MOVINGOBJ_STATUS_JUMPING )\r\n\t\tpScriptParams->AddInteger( CRCD( 0x65b5788d, \"is_jumping\" ), 1 );\r\n\telse\r\n\t\tpScriptParams->AddInteger( CRCD( 0x65b5788d, \"is_jumping\" ), 0 );\r\n\r\n\tif ( pNodeData->ContainsFlag( CRCD( 0xb02567ae, \"JumpToNextNode\" ) ) )\r\n\t{\r\n\t\tm_flags &= ~PEDLOGIC_MOVING_ON_PATH;\r\n\t\tm_flags |= PEDLOGIC_JUMPING_TO_NODE;\r\n\t}\r\n\r\n\tScript::CScript *pScript = Script::SpawnScript( CRCD( 0xb83c383c, \"ped_skater_flip_trick\" ), pScriptParams );\r\n\tpScript->mpObject = GetObject();\r\n\tdelete pScriptParams;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/PedLogicComponent.h",
    "content": "\r\n//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       PedLogicComponent.h\r\n//* OWNER:          Brad Bulkley\r\n//* CREATION DATE:  1/9/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_PEDLOGICCOMPONENT_H__\r\n#define __COMPONENTS_PEDLOGICCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <core/math/slerp.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <gel/components/motioncomponent.h>\r\n\r\n#include <sk/objects/skaterflags.h>\r\n#include <gfx/nxflags.h>\r\n\r\n#define\t\tCRC_PEDLOGIC CRCD( 0x6efddfb8, \"PedLogic\" )\r\n#define\t\tGetPedLogicComponent() ((Obj::CPedLogicComponent*)GetComponent(CRC_PEDLOGIC))\r\n#define\t\tGetPedLogicComponentFromObject(pObj) ((Obj::CPedLogicComponent*)(pObj)->GetComponent(CRC_PEDLOGIC))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\n\t// flags\r\n\tenum\r\n\t{\r\n\t\tPEDLOGIC_IS_SKATER\t\t\t\t= ( 1 << 0\t),\r\n\t\tPEDLOGIC_MOVING_ON_PATH\t\t\t= ( 1 << 1\t),\r\n\t\tPEDLOGIC_GRINDING\t\t\t\t= ( 1 << 2\t),\r\n\t\tPEDLOGIC_TO_NODE_IS_VERT\t\t= ( 1 << 3\t),\r\n\t\tPEDLOGIC_FROM_NODE_IS_VERT\t\t= ( 1 << 4\t),\r\n\t\tPEDLOGIC_NEXT_NODE_IS_VERT\t\t= ( 1 << 5\t),\r\n\t\tPEDLOGIC_BAILING\t\t\t\t= ( 1 << 6\t),\r\n\t\tPEDLOGIC_GRIND_BAILING\t\t\t= ( 1 << 7\t),\r\n\t\tPEDLOGIC_JUMP_AT_TO_NODE\t\t= ( 1 << 8\t),\r\n\t\tPEDLOGIC_DOING_VERT_ROTATION\t= ( 1 << 9\t),\r\n\t\tPEDLOGIC_DOING_SPINE\t\t\t= ( 1 << 10\t),\r\n\t\tPEDLOGIC_JUMPING_TO_NODE\t\t= ( 1 << 11\t),\r\n\t\tPEDLOGIC_STOPPED\t\t\t\t= ( 1 << 12\t),\r\n\t\tPEDLOGIC_DOING_LIP_TRICK\t\t= ( 1 << 13\t),\r\n\t\tPEDLOGIC_DOING_MANUAL\t\t\t= ( 1 << 14 ),\r\n\t\tPEDLOGIC_TO_NODE_IS_LIP\t\t\t= ( 1 << 15 ),\r\n\t};\r\n\t\r\n\tconst int vPOS_HISTORY_SIZE = 5;\r\n\r\n\r\nclass CPathObjectTracker;\r\n\r\nenum\r\n{\r\n    vNUM_WHISKERS=4\r\n};\r\n\r\n\r\nclass CPedLogicComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CPedLogicComponent();\r\n    virtual ~CPedLogicComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\tSelectNextWaypoint();\r\n\tvoid\t\t\t\t\t\t\tHitWaypoint();\r\n\r\n\tbool\t\t\t\t\t\t\tWaypointIsVert( int waypoint );\r\n\t\r\n\tvirtual void\t\t\t\t\tGenericPedUpdate();\r\n\tvirtual void\t\t\t\t\tGenericSkaterUpdate();\r\n\tvoid\t\t\t\t\t\t\tUpdateLipDisplayMatrix();\r\n\r\n\t// new generic ped logic stuff\r\n\tbool\t\t\t\t\t\t\tCheckForOtherPeds();\r\n\tfloat\t\t\t\t\t\t\tGetTotalXBias();\r\n\tfloat\t\t\t\t\t\t\tGetTotalZBias();\r\n\tvoid\t\t\t\t\t\t\tUpdatePathBias();\r\n\tbool\t\t\t\t\t\t\tUpdateTargetBias();\r\n\tvoid\t\t\t\t\t\t\tAdjustBias( float angle, float bias );\r\n\tvoid\t\t\t\t\t\t\tAddWhiskerBias( float angle, float bias, float distance, float range );\r\n\tvoid\t\t\t\t\t\t\tDecayWhiskerBiases();\r\n\tvoid\t\t\t\t\t\t\tUpdatePosition();\r\n\tvoid\t\t\t\t\t\t\tRotatePosHistory();\r\n\tvoid\t\t\t\t\t\t\tResetBias();\r\n\tvoid\t\t\t\t\t\t\tAddTargetBias( Mth::Vector target, float target_bias );\r\n\r\n\tbool\t\t\t\t\t\t\tShouldExecuteAction( Script::CStruct* pNodeData, uint32 weight_name );\r\n\tvoid\t\t\t\t\t\t\tAdjustSpeed( float percent );\r\n\r\n\tvoid\t\t\t\t\t\t\tDoWalkActions( Script::CStruct* pNodeData );\r\n\tvoid\t\t\t\t\t\t\tDoSkateActions( Script::CStruct* pNodeData );\r\n\tvoid\t\t\t\t\t\t\tDoGenericNodeActions( Script::CStruct* pNodeData );\r\n\r\n\tvoid\t\t\t\t\t\t\tAdjustNormal();\r\n\tvoid\t\t\t\t\t\t\tAdjustHeading();\r\n\tvoid\t\t\t\t\t\t\tAdjustHeading( Mth::Vector original_pos );\r\n\tvoid\t\t\t\t\t\t\tRefreshDisplayMatrix();\r\n\tvoid\t\t\t\t\t\t\tStickToGround();\r\n\r\n\tbool\t\t\t\t\t\t\tdo_collision_check( Mth::Vector *p_v0, Mth::Vector *p_v1, Mth::Vector *p_collisionPoint, Obj::STriangle *p_lastTriangle );\r\n\r\n\tvoid\t\t\t\t\t\t\tUpdateSkaterSoundStates( EStateType state );\r\n\tvoid\t\t\t\t\t\t\tUpdateSkaterSoundTerrain( ETerrainType terrain );\r\n\r\n\tbool\t\t\t\t\t\t\tShouldUseBiases();\r\n\t\r\n\t// skate actions\r\n\tvoid\t\t\t\t\t\t\tDoGrind( Script::CStruct* pNodeData );\r\n\tvoid\t\t\t\t\t\t\tDoGrindOff( Script::CStruct* pNodeData );\r\n\t// void\t\t\t\t\t\t\tGrindUpdate();\r\n\t\r\n\tScript::CStruct*\t\t\t\tGetJumpParams( Script::CStruct* pNodeData, bool is_vert = false );\r\n\tvoid\t\t\t\t\t\t\tDoGrab( Script::CStruct* pNodeData, bool is_vert = false );\r\n\tvoid\t\t\t\t\t\t\tDoRotations();\r\n\r\n\tvoid\t\t\t\t\t\t\tDoLipTrick( Script::CStruct* pNodeData );\r\n\tvoid\t\t\t\t\t\t\tDoJump( Script::CStruct* pNodeData, bool is_vert = false );\r\n\tvoid\t\t\t\t\t\t\tDoManual( Script::CStruct* pNodeData );\r\n\tvoid\t\t\t\t\t\t\tDoManualDown( Script::CStruct* pNodeData );\r\n\tvoid\t\t\t\t\t\t\tStop( Script::CStruct* pNodeData );\r\n\tvoid\t\t\t\t\t\t\tBail();\r\n\tvoid\t\t\t\t\t\t\tGrindBail();\r\n\tvoid\t\t\t\t\t\t\tDoRollOff( Script::CStruct* pNodeData );\r\n\tvoid\t\t\t\t\t\t\tDoFlipTrick( Script::CStruct* pNodeData, bool is_vert = false );\r\n\r\n\tvoid\t\t\t\t\t\t\tStopSkateActions();\r\n\r\n\tScript::CStruct*\t\t\t\tGetSkateActionParams( Script::CStruct* pNodeData );\r\nprotected:\r\n\tuint32\t\t\t\t\t\t\tm_state;\r\n\r\n\tuint32\t\t\t\t\t\t\tm_flags;\r\n\t\r\n\t// new generic ped logic stuff\r\n\tfloat\t\t\t\t\t\t\tm_bias[vNUM_WHISKERS];\r\n\tfloat\t\t\t\t\t\t\tm_whiskers[vNUM_WHISKERS];\r\n\r\n\t// nodes\r\n\tint\t\t\t\t\t\t\t\tm_node_from;\r\n\tint\t\t\t\t\t\t\t\tm_node_to;\r\n\tint\t\t\t\t\t\t\t\tm_node_next;\r\n\r\n\t// waypoints of nodes\r\n\tMth::Vector\t\t\t\t\t\tm_wp_from;\r\n\tMth::Vector\t\t\t\t\t\tm_wp_to;\r\n\tMth::Vector\t\t\t\t\t\tm_wp_next;\r\n\r\n\tint\t\t\t\t\t\t\t\tm_turn_frames;\r\n\tint\t\t\t\t\t\t\t\tm_max_turn_frames;\r\n\r\n\tCPathObjectTracker*\t\t\t\tmp_path_object_tracker;\r\n\r\n\tfloat\t\t\t\t\t\t\tm_time;\r\n\r\n\t// normal lerp\r\n\tMth::Vector\t\t\t\t\t\tm_last_display_normal;\r\n\tMth::Vector\t\t\t\t\t\tm_current_normal;\r\n\tMth::Vector\t\t\t\t\t\tm_display_normal;\r\n\tfloat\t\t\t\t\t\t\tm_normal_lerp;\r\n\r\n\t// stick to ground\r\n\tfloat\t\t\t\t\t\t\tm_col_dist_above;\r\n\tfloat\t\t\t\t\t\t\tm_col_dist_below;\r\n\r\n\t// velocity\r\n\tfloat\t\t\t\t\t\t\tm_original_max_vel;\r\n\r\n\t// rotation\r\n\tint\t\t\t\t\t\t\t\tm_rot_angle;\r\n\tfloat\t\t\t\t\t\t\tm_rot_current_angle;\r\n\tfloat\t\t\t\t\t\t\tm_rot_total_time;\r\n\tfloat\t\t\t\t\t\t\tm_rot_current_time;\r\n\tMth::Matrix\t\t\t\t\t\tm_rot_start_matrix;\r\n\r\n\t// spine\r\n\tfloat\t\t\t\t\t\t\tm_spine_current_angle;\r\n\tfloat\t\t\t\t\t\t\tm_spine_start_angle;\r\n\t\r\n\t// display matrix as of last update\r\n\tMth::Matrix\t\t\t\t\t\tm_current_display_matrix;\r\n\r\n\tMth::Vector\t\t\t\t\t\tm_pos_history[vPOS_HISTORY_SIZE];\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_speed_fraction;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/ProximTriggerComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       ProximTriggerComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  2/28/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/proximtriggercomponent.h>\r\n\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <sk/objects/proxim.h>\r\n#include <sk/modules/skate/skate.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent* CProximTriggerComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CProximTriggerComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCProximTriggerComponent::CProximTriggerComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_PROXIMTRIGGER );\r\n\t\r\n\tif (!Mdl::Skate::Instance()->mpProximManager)\r\n\t{\r\n\t\tDbg_Message(\"ProximTriggerComponent created before ProximManager; ProximNodes will not work\");\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tDbg_MsgAssert(Mdl::Skate::Instance()->mpProximManager, (\"ProximTriggerComponent created before ProximManager\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCProximTriggerComponent::~CProximTriggerComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CProximTriggerComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x1313e3c, \"ProximTriggerTarget\")))\r\n\t{\r\n\t\tuint32 script_target_id;\r\n\t\tpParams->GetChecksum(CRCD(0x1313e3c, \"ProximTriggerTarget\"), &script_target_id);\r\n\t\t\r\n\t\tmp_script_target_object = static_cast< CCompositeObject* >(CCompositeObjectManager::Instance()->GetObjectByID(script_target_id));\r\n\t\tDbg_MsgAssert(mp_script_target_object, (\"ProximTriggerComponent given unidentifiable target object\"));\r\n\t}\r\n\t\r\n\tm_active = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CProximTriggerComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CProximTriggerComponent::Update()\r\n{\r\n\tif (!m_active) return;\r\n\tProximUpdate();\r\n}\r\n\r\nvoid CProximTriggerComponent::ProximUpdate()\r\n{\r\n\r\n\t#if 0\t\r\n\t\r\n\tDbg_Assert(mp_script_target_object);\r\n\t\r\n\tuint32 proxim_trigger_mask = Mdl::Skate::Instance()->mpProximManager->GetProximTriggerMask(m_viewport);\r\n\t\r\n\tProxim_Update(proxim_trigger_mask, mp_script_target_object, GetObject()->GetPos());\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CProximTriggerComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\t\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CProximTriggerComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info, (\"NULL p_info sent to CProximTriggerComponent::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddChecksum(\"mp_script_target_object\", mp_script_target_object->GetID());\r\n\tp_info->AddInteger(\"proxim_trigger_mask\", Mdl::Skate::Instance()->mpProximManager->GetProximTriggerMask(m_viewport));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProximTriggerComponent::SetScriptTarget ( CCompositeObject* p_script_target_object )\r\n{\r\n\tDbg_Assert(p_script_target_object);\r\n\tmp_script_target_object = p_script_target_object;\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/ProximTriggerComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       ProximTriggerComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  2/28/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_PROXIMTRIGGERCOMPONENT_H__\r\n#define __COMPONENTS_PROXIMTRIGGERCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_PROXIMTRIGGER CRCD(0x98952fb6, \"ProximTrigger\")\r\n\r\n#define\t\tGetProximTriggerComponent() ((Obj::CProximTriggerComponent*)GetComponent(CRC_PROXIMTRIGGER))\r\n#define\t\tGetProximTriggerComponentFromObject(pObj) ((Obj::CProximTriggerComponent*)(pObj)->GetComponent(CRC_PROXIMTRIGGER))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CCameraComponent;\r\n\r\nclass CProximTriggerComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CProximTriggerComponent();\r\n    virtual ~CProximTriggerComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetScriptTarget ( CCompositeObject* p_script_target_object );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetActive (   ) { m_active = true; }\r\n\tvoid\t\t\t\t\t\t\tSetInactive (   ) { m_active = false; }\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetViewport ( int viewport ) { m_viewport = viewport; }\r\n\tint\t\t\t\t\t\t\t\tGetViewport (   ) { return m_viewport; }\r\n\t\r\n\tvoid\t\t\t\t\t\t\tProximUpdate();\r\n\t\r\nprivate:\r\n\t// target of the scripts run by proxim nodes which do not have a proxim object ID\r\n\tCObject*                        mp_script_target_object;\r\n\t\r\n\t// if the trigger is active\r\n\tbool\t\t\t\t\t\t\tm_active;\r\n\t\r\n\t// the viewport which this component corresponds to; all proxim trigger components on a given viewport share a proxim trigger flag so that switching\r\n\t// camera will triggered inside/outside effects correctly; only one proxim trigger component with a given viewport should be active at any one time\r\n\tint\t\t\t\t\t\t\t\tm_viewport;\r\n\t\r\n\t// peer components\r\n\tCCameraComponent*\t\t\t\tmp_camera_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/RailManagerComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       RailManagerComponent.cpp\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/17/03\r\n//****************************************************************************\r\n\r\n// The CEmptyComponent class is an skeletal version of a component\r\n// It is intended that you use this as the basis for creating new\r\n// components.  \r\n// To create a new component called \"Watch\", (CWatchComponent):\r\n//  - copy emptycomponent.cpp/.h to watchcomponent.cpp/.h\r\n//  - in both files, search and replace \"Empty\" with \"Watch\", preserving the case\r\n//  - in WatchComponent.h, update the CRCD value of CRC_WATCH\r\n//  - in CompositeObjectManager.cpp, in the CCompositeObjectManager constructor, add:\r\n//\t\t  \tRegisterComponent(CRC_WATCH,\t\t\tCWatchComponent::s_create); \r\n//  - and add the include of the header\r\n//\t\t\t#include <gel/components/watchcomponent.h> \r\n//  - Add it to build\\gel.mkf, like:\r\n//          $(NGEL)/components/WatchComponent.cpp\\\r\n//  - Fill in the OWNER (yourself) and the CREATION DATE (today's date) in the .cpp and the .h files\r\n//\t- Insert code as needed and remove generic comments\r\n//  - remove these comments\r\n//  - add comments specfic to the component, explaining its usage\r\n#include <gel/components/railmanagercomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <gel/components/nodearraycomponent.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\nCBaseComponent* CRailManagerComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CRailManagerComponent );\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCRailManagerComponent::CRailManagerComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_RAILMANAGER );\r\n\tmp_rail_manager = NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCRailManagerComponent::~CRailManagerComponent()\r\n{\r\n\t// Remove the CRailManager if present.\r\n\tif( mp_rail_manager )\r\n\t{\r\n\t\tdelete mp_rail_manager;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CRailManagerComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// There needs to be a NodeArrayComponent attached for the RailManagerComponent to operate.\r\n\tCNodeArrayComponent *p_nodearray_component = GetNodeArrayComponentFromObject( GetObject());\r\n\tDbg_MsgAssert( p_nodearray_component, ( \"RailManagerComponent created without NodeArrayComponent\" ));\r\n\r\n\t// Remove any existing CRailManager.\r\n\tif( mp_rail_manager )\r\n\t{\r\n\t\tdelete mp_rail_manager;\r\n\t}\r\n\r\n\t// Create a rail manager, and parse the node array for the rails.\r\n\tmp_rail_manager = new Obj::CRailManager();\r\n\tmp_rail_manager->AddRailsFromNodeArray( p_nodearray_component->GetNodeArray());\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CRailManagerComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure( pParams );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CRailManagerComponent::Update()\r\n{\r\n\t// Doing nothing, so tell code to do nothing next time around\r\n\tSuspend(true);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CRailManagerComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch( Checksum )\r\n\t{\r\n/*\r\n        // @script | DoSomething | does some functionality\r\n\t\tcase 0xbb4ad101:\t\t// DoSomething\r\n\t\t\tDoSomething();\r\n\t\t\tbreak;\r\n\r\n        // @script | ValueIsTrue | returns a boolean value\r\n\t\tcase 0x769260f7:\t\t// ValueIsTrue\r\n\t\t{\r\n\t\t\treturn ValueIsTrue() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\tbreak;\r\n*/\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CRailManagerComponent::GetDebugInfo( Script::CStruct *p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert( p_info, (\"NULL p_info sent to CRailManagerComponent::GetDebugInfo\" ));\r\n\r\n\t// Add the number of Rail Manager nodes.\r\n\tif( mp_rail_manager )\r\n\t{\r\n\t\tp_info->AddInteger(\"RailManager.m_num_nodes\", mp_rail_manager->GetNumNodes());\r\n\t\tp_info->AddString(\"RailManager.m_is_transformed\", mp_rail_manager->IsMoving() ? \"yes\" : \"no\" );\r\n\t}\r\n\r\n\t// We call the base component's GetDebugInfo, so we can add info from the common base component.\r\n\tCBaseComponent::GetDebugInfo( p_info );\r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Matrix CRailManagerComponent::UpdateRailManager (   )\r\n{\r\n\tDbg_Assert(mp_rail_manager);\r\n\r\n\t// form a transformation matrix\r\n\tMth::Matrix total_mat = GetObject()->GetMatrix();\r\n\ttotal_mat[X][W] = 0.0f;\r\n\ttotal_mat[Y][W] = 0.0f;\r\n\ttotal_mat[Z][W] = 0.0f;\r\n\ttotal_mat[W] = GetObject()->GetPos();\r\n\ttotal_mat[W][W] = 1.0f;\r\n\r\n\tmp_rail_manager->UpdateTransform(total_mat);\r\n\t\r\n\treturn total_mat;\r\n}\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/RailManagerComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       RailManagerComponent.h\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/17/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_RAILMANAGERCOMPONENT_H__\r\n#define __COMPONENTS_RAILMANAGERCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/objects/rail.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_RAILMANAGER\t\t\t\t\t\t\t\tCRCD( 0x1cdfb2a3, \"RailManager\" )\r\n#define\t\tGetRailManagerComponent()\t\t\t\t\t((Obj::CRailManagerComponent*)GetComponent( CRC_RAILMANAGER ))\r\n#define\t\tGetRailManagerComponentFromObject( pObj )\t((Obj::CRailManagerComponent*)(pObj)->GetComponent( CRC_RAILMANAGER ))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CRailManagerComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CRailManagerComponent();\r\n    virtual ~CRailManagerComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tMth::Matrix\t\t\t\t\t\tUpdateRailManager (   );\r\n\r\n\tvirtual Obj::CRailManager*\t\tGetRailManager( void )\t{ return mp_rail_manager; }\r\n\r\nprivate:\r\n\tObj::CRailManager*\t\t\t\tmp_rail_manager;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/RibbonComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       RibbonComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  5/20/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/ribboncomponent.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n\r\n#include <gel/collision/collcache.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n\r\n#define MESSAGE(a) { printf(\"M:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPI(a) { printf(\"D:%s:%i: \" #a \" = %i\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPB(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, a ? \"true\" : \"false\"); }\r\n#define DUMPF(a) { printf(\"D:%s:%i: \" #a \" = %g\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPE(a) { printf(\"D:%s:%i: \" #a \" = %e\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPS(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPP(a) { printf(\"D:%s:%i: \" #a \" = %p\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPV(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z]); }\r\n#define DUMP4(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z], (a)[W]); }\r\n#define DUMPM(a) { DUMP4(a[X]); DUMP4(a[Y]); DUMP4(a[Z]); DUMP4(a[W]); }\r\n#define DUMP2(a) { printf(\"D:%s:%i \" #a \" = \", __FILE__ + 15, __LINE__); for (int n = 32; n--; ) { printf(\"%c\", ((a) & (1 << n)) ? '1' : '0'); } printf(\"\\n\"); }\r\n#define MARK { printf(\"K:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, __PRETTY_FUNCTION__); }\r\n#define PERIODIC(n) for (static int p__ = 0; (p__ = ++p__ % (n)) == 0; )\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CRibbonComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CRibbonComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCRibbonComponent::CRibbonComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_RIBBON );\r\n\t\r\n\tmp_links = NULL;\r\n\t\r\n\tm_last_frame_length = 0.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCRibbonComponent::~CRibbonComponent()\r\n{\r\n\tif (mp_links)\r\n\t{\r\n\t\tdelete mp_links;\r\n\t\tmp_links = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRibbonComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tpParams->GetChecksum(CRCD(0xcab94088, \"bone\"), &m_bone_name, Script::ASSERT);\r\n\tpParams->GetInteger(CRCD(0x69feef91, \"num_links\"), &m_num_links, Script::ASSERT);\r\n\tpParams->GetFloat(CRCD(0x9f4625c2, \"link_length\"), &m_link_length, Script::ASSERT);\r\n\tpParams->GetChecksum(CRCD(0x99a9b716, \"color\"), &m_color, Script::ASSERT);\r\n\t\r\n\tmp_links = new SLink [ m_num_links ];\r\n\tfor (int n = m_num_links; n--; )\r\n\t{\r\n\t\tmp_links[n].p.Set();\r\n\t\tmp_links[n].last_p.Set();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRibbonComponent::Finalize()\r\n{\r\n\tmp_skeleton_component = GetSkeletonComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_skeleton_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRibbonComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRibbonComponent::Update()\r\n{\r\n\tfloat frame_length = Tmr::FrameLength();\r\n\t\r\n\t// update link positions based on velocity\r\n\tfor (int n = m_num_links; n--; )\r\n\t{\r\n\t\tMth::Vector vel = mp_links[n].p - mp_links[n].last_p;\r\n\t\tvel *= 1.0f / m_last_frame_length;\r\n\t\t\r\n\t\t// damp\r\n\t\tvel -= 10.0f * frame_length * vel;\r\n\t\t\r\n\t\t// momentum\r\n\t\tmp_links[n].next_p = mp_links[n].p + frame_length * vel;\r\n\t\t\r\n\t\t// gravity\r\n\t\tmp_links[n].next_p[Y] -= 800.0f * frame_length * frame_length;\r\n\t}\r\n\t\r\n\t// fetch bone position\r\n\tMth::Vector bone_p;\r\n\tmp_skeleton_component->GetBonePosition(m_bone_name, &bone_p);\r\n\tbone_p = GetObject()->GetMatrix().Rotate(bone_p);\r\n\tbone_p += GetObject()->GetPos();\r\n\t\r\n\t// update link constraints\r\n\tfor (int c = 20; c--; )\r\n\t{\r\n\t\t// first link special case\r\n\t\tfloat length = (mp_links[0].next_p - bone_p).Length();\r\n\t\tMth::Vector axis = (mp_links[0].next_p - bone_p) * (1.0f / length);\r\n\t\tfloat adjustment = m_link_length - length;\r\n\t\tmp_links[0].next_p += adjustment * axis;\r\n\t\t\r\n\t\t// second and subsequent links\r\n\t\tfor (int n = 1; n < m_num_links; n++)\r\n\t\t{\r\n\t\t\tfloat length = (mp_links[n].next_p - mp_links[n - 1].next_p).Length();\r\n\t\t\tMth::Vector axis = (mp_links[n].next_p - mp_links[n - 1].next_p) * (1.0f / length);\r\n\t\t\t\r\n\t\t\tfloat adjustment = 0.5f * (m_link_length - length);\r\n\t\t\t\r\n\t\t\t// hack\r\n\t\t\tif (length > 20.0f * m_link_length)\r\n\t\t\t{\r\n\t\t\t\tCallMemberFunction(CRCD(0x796084f4, \"Ribbon_Reset\"), NULL, NULL);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tmp_links[n].next_p += adjustment * axis;\r\n\t\t\tmp_links[n - 1].next_p -= adjustment * axis;\r\n\t\t}\r\n\t}\r\n\t\r\n\t#if 0\r\n\t\r\n\t// cheap collision detection\r\n\tfloat min_y = GetObject()->GetPos()[Y] + 0.1f;\r\n\tfor (int n = m_num_links; n--; )\r\n\t{\r\n\t\tmp_links[n].next_p[Y] = Mth::ClampMin(mp_links[n].next_p[Y], min_y);\r\n\t}\r\n\t\r\n\t#else\r\n\t\r\n\tMth::CBBox bbox;\r\n\tNx::CCollCache* p_coll_cache = Nx::CCollCacheManager::sCreateCollCache();\r\n\tfor (int n = m_num_links; n--; )\r\n\t{\r\n\t\tbbox.AddPoint(mp_links[n].p);\r\n\t\tbbox.AddPoint(mp_links[n].next_p);\r\n\t}\r\n\tp_coll_cache->Update(bbox);\r\n\t\r\n\tCFeeler feeler;\r\n\tfeeler.SetCache(p_coll_cache);\r\n\t// real collision detection\r\n\tfor (int n = m_num_links; n--; )\r\n\t{\r\n\t\tfeeler.m_start = mp_links[n].p;\r\n\t\tfeeler.m_end = mp_links[n].next_p;\r\n\t\tif (!feeler.GetCollision()) continue;\r\n\t\t\r\n\t\tMth::Vector movement = mp_links[n].next_p - mp_links[n].p;\r\n\t\t\r\n\t\tmp_links[n].next_p = feeler.GetPoint() + 0.1f * feeler.GetNormal();\r\n\t\t\r\n\t\t// assume no additional collision\r\n\t\tmovement *= 1.0f - feeler.GetDist();\r\n\t\tmovement.ProjectToPlane(feeler.GetNormal());\r\n\t\t\r\n\t\tmp_links[n].next_p += movement;\r\n\t}\r\n\t\r\n\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\r\n\t#endif\r\n\t\r\n\t// update state\r\n\tfor (int n = m_num_links; n--; )\r\n\t{\r\n\t\tmp_links[n].last_p = mp_links[n].p;\r\n\t\tmp_links[n].p = mp_links[n].next_p;\r\n\t}\r\n\tm_last_frame_length = frame_length;\r\n\t\r\n\t// debug draw\r\n\tGfx::AddDebugLine(bone_p, mp_links[0].p, m_color, 0, 1);\r\n\tfor (int n = 1; n < m_num_links; n++)\r\n\t{\r\n\t\tGfx::AddDebugLine(mp_links[n].p, mp_links[n - 1].p, m_color, 0, 1);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CRibbonComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tcase CRCC(0x796084f4, \"Ribbon_Reset\"):\r\n\t\t{\r\n\t\t\tMESSAGE(\"Resetting\");\r\n\t\t\t\r\n\t\t\tMth::Vector bone_p;\r\n\t\t\tmp_skeleton_component->GetBonePosition(m_bone_name, &bone_p);\r\n\t\t\tbone_p = GetObject()->GetMatrix().Rotate(bone_p);\r\n\t\t\tbone_p += GetObject()->GetPos();\r\n\t\t\t\r\n\t\t\tfor (int n = m_num_links; n--; )\r\n\t\t\t{\r\n\t\t\t\tmp_links[n].p = bone_p;\r\n\t\t\t\tmp_links[n].last_p = bone_p;\r\n\t\t\t\tmp_links[n].p[Y] += 0.1f * n;\r\n\t\t\t\tmp_links[n].last_p[Y] += 0.1f * n;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRibbonComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CRibbonComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/RibbonComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       RibbonComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  5/20/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_RIBBONCOMPONENT_H__\r\n#define __COMPONENTS_RIBBONCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_RIBBON CRCD(0xee6fc5b, \"Ribbon\")\r\n\r\n#define\t\tGetRibbonComponent() ((Obj::CRibbonComponent*)GetComponent(CRC_RIBBON))\r\n#define\t\tGetRibbonComponentFromObject(pObj) ((Obj::CRibbonComponent*)(pObj)->GetComponent(CRC_RIBBON))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CSkeletonComponent;\r\n\r\nclass CRibbonComponent : public CBaseComponent\r\n{\r\n\tstruct SLink\r\n\t{\r\n\t\tMth::Vector\t\t\t\t\tp;\r\n\t\tMth::Vector\t\t\t\t\tlast_p;\r\n\t\tMth::Vector\t\t\t\t\tnext_p;\r\n\t};\r\n\t\r\npublic:\r\n    CRibbonComponent();\r\n    virtual ~CRibbonComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual\tvoid \t\t\t\t\tFinalize();\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\nprivate:\r\n\tuint32\t\t\t\t\t\t\tm_bone_name;\r\n\tint\t\t\t\t\t\t\t\tm_num_links;\r\n\tfloat\t\t\t\t\t\t\tm_link_length;\r\n\tuint32\t\t\t\t\t\t\tm_color;\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_last_frame_length;\r\n\t\r\n\tSLink*\t\t\t\t\t\t\tmp_links;\r\n\t\r\n\t// peer components\r\n\tCSkeletonComponent*\t\t\t\tmp_skeleton_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/RiderComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       RiderComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  4/2/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/ridercomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/triggercomponent.h>\r\n#include <gel/components/movablecontactcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/collision/collcache.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n\r\n\r\n\r\nnamespace Obj\r\n{\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCBaseComponent* CRiderComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CRiderComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCRiderComponent::CRiderComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_RIDER );\r\n\t\r\n\tmp_collision_cache = Nx::CCollCacheManager::sCreateCollCache();\r\n\t\r\n\tmp_input_component\t\t\t\t= NULL;\r\n\tmp_animation_component\t\t\t= NULL;\r\n\tmp_movable_contact_component\t= NULL;\r\n\tmp_horse_component\t\t\t\t= NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCRiderComponent::~CRiderComponent()\r\n{\r\n\tNx::CCollCacheManager::sDestroyCollCache(mp_collision_cache);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CRiderComponent::Finalize()\r\n{\r\n\tmp_input_component = GetInputComponentFromObject(GetObject());\r\n\tmp_animation_component = GetAnimationComponentFromObject(GetObject());\r\n\tmp_model_component = GetModelComponentFromObject(GetObject());\r\n\tmp_trigger_component = GetTriggerComponentFromObject(GetObject());\r\n\tmp_physics_control_component = GetSkaterPhysicsControlComponentFromObject(GetObject());\r\n\tmp_movable_contact_component = GetMovableContactComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_input_component);\r\n\tDbg_Assert(mp_animation_component);\r\n\tDbg_Assert(mp_model_component);\r\n\tDbg_Assert(mp_trigger_component);\r\n\tDbg_Assert(mp_physics_control_component);\r\n\tDbg_Assert(mp_movable_contact_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CRiderComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tuint32 camera_id;\r\n\tif (pParams->GetChecksum(CRCD(0xc4e311fa, \"camera\"), &camera_id))\r\n\t{\r\n\t\tCCompositeObject* p_camera = static_cast< CCompositeObject* >(CCompositeObjectManager::Instance()->GetObjectByID(camera_id));\r\n\t\tDbg_MsgAssert(mp_camera, (\"No such camera object\"));\r\n\t\tSetAssociatedCamera(p_camera);\r\n\t}\r\n\t\r\n\tm_script_drag_factor = 1.0f;\r\n}\r\n\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CRiderComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CRiderComponent::Update()\r\n{\r\n\tif( mp_horse_component == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// TEMP: debounce R1 after a transition\r\n//\tif (m_ignore_grab_button && !mp_input_component->GetControlPad().m_R1.GetPressed())\r\n//\t{\r\n//\t\tm_ignore_grab_button = false;\r\n//\t}\r\n\t\r\n\t// zero the frame event\r\n\tm_last_frame_event = m_frame_event;\r\n\tm_frame_event = 0;\r\n\t\r\n\t// get input\r\n//    get_controller_input();\r\n\t\r\n\t// extract initial state for this frame from the object\r\n\tm_frame_start_pos = m_pos = GetObject()->GetPos();\r\n\t\r\n\tm_horizontal_vel = GetObject()->GetVel();\r\n\tm_horizontal_vel[Y] = 0.0f;\r\n\tm_vertical_vel = GetObject()->GetVel()[Y];\r\n\t\r\n\t// note that m_facing and m_upward will often not be orthogonal, but will always span a plan\r\n\t\r\n\t// generally straight up, but now after a transition from skating\r\n\tm_upward = GetObject()->GetMatrix()[Y];\r\n\t\r\n\tm_facing = GetObject()->GetMatrix()[Z];\r\n\tm_facing[Y] = 0.0f;\r\n\tfloat length = m_facing.Length();\r\n\tif (length < 0.001f)\r\n\t{\r\n\t\t// upward facing orientation matrix\r\n\t\tm_facing = -GetObject()->GetMatrix()[Y];\r\n\t\tm_facing[Y] = 0.0f;\r\n\t\tm_facing.Normalize();\r\n\t\t\r\n\t\t// since m_upward is now in the same plan as m_facing, push m_upward up a touch\r\n\t\tm_upward[Y] += 0.01f;\r\n\t\tm_upward.Normalize();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_facing /= length;\r\n\t}\r\n\t\r\n\t// set the frame length\r\n\tm_frame_length = Tmr::FrameLength();\r\n\t\r\n\t// go to our true Y position\r\n\tm_curb_float_height_adjusted = false;\r\n\tm_pos[Y] -= m_curb_float_height;\r\n\t\r\n\t// switch logic based on walking state\r\n\tgo_on_horse_state();\r\n\t\r\n//\tswitch (m_state)\r\n//\t{\r\n//\t\tcase WALKING_GROUND:\r\n//\t\t\tgo_on_ground_state();\r\n//\t\t\tbreak;\r\n//\r\n//\t\tcase WALKING_AIR:\r\n//\t\t\tgo_in_air_state();\r\n//\t\t\tbreak;\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n//\t\tcase WALKING_HOP:\r\n//\t\t\tgo_hop_state();\r\n//\t\t\tbreak;\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n//\t\tcase WALKING_HANG:\r\n//\t\t\tgo_hang_state();\r\n//\t\t\tbreak;\r\n//            \r\n//\t\tcase WALKING_LADDER:\r\n//\t\t\tgo_ladder_state();\r\n//          break;\r\n//\t\t\t\r\n//\t\tcase WALKING_ANIMWAIT:\r\n//\t\t\tgo_anim_wait_state (   );\r\n//\t\t\tbreak;\r\n//\t}\r\n\t\r\n\t// the there's no curb to adjust due to, lerp down to zero\r\n//\tif (!m_curb_float_height_adjusted)\r\n//\t{\r\n//\t\tm_curb_float_height = Mth::Lerp(m_curb_float_height, 0.0f, s_get_param(CRCD(0x9b3388fa, \"curb_float_lerp_down_rate\")) * m_frame_length);\r\n//\t}\r\n\t\r\n\t// adjust back to our curb float Y position\r\n//\tm_pos[Y] += m_curb_float_height;\r\n\t\r\n\t// scripts may have restarted us / switched us to skating\r\n//\tif (should_bail_from_frame()) return;\r\n\t\r\n\t// keep the object from falling through holes in the geometry\r\n//\tif (m_state == WALKING_GROUND || m_state == WALKING_AIR)\r\n//\t{\r\n//\t\tuber_frig();\r\n//\t}\r\n\t\r\n\t// rotate to upright\r\n//\tlerp_upright();\r\n\t\r\n\t// setup the object based on this frame's walking\r\n//\tcopy_state_into_object();\r\n\t\r\n//\tDbg_Assert(m_frame_event);\r\n//\tGetObject()->SelfEvent(m_frame_event);\r\n\t\r\n\t// set the animation speeds\r\n//\tswitch (m_anim_scale_speed)\r\n//\t{\r\n//\t\tcase RUNNING:\r\n//\t\t\tif (m_anim_standard_speed > 0.0f)\r\n//\t\t\t{\r\n//\t\t\t\tmp_animation_component->SetAnimSpeed(m_anim_effective_speed / m_anim_standard_speed, false, false);\r\n//\t\t\t}\r\n//\t\t\tbreak;\r\n//\t\t\t\r\n//\t\tcase HANGMOVE:\r\n//\t\t\tmp_animation_component->SetAnimSpeed(m_anim_effective_speed / s_get_param(CRCD(0xd77ee881, \"hang_move_speed\")), false, false);\r\n//\t\t\tbreak;\r\n//\t\t\t\t\t\r\n//\t\tcase LADDERMOVE:\r\n//\t\t\tmp_animation_component->SetAnimSpeed(m_anim_effective_speed / s_get_param(CRCD(0xab2db54, \"ladder_move_speed\")), false, false);\r\n//\t\t\tbreak;\r\n//\t\r\n//\t\tdefault:\r\n//\t\t\tbreak;\r\n//\t}\r\n\t\r\n\t// camera controls\r\n\t// NOTE: script parameters\r\n//\tswitch (m_frame_event)\r\n//\t{\r\n//\t\tcase CRCC(0xf41aba21, \"Hop\"):\r\n//\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n//\t\t\tbreak;\r\n//\t\t\r\n//\t\tcase CRCC(0x2d9815c3, \"HangMoveLeft\"):\r\n//\t\t{\r\n//\t\t\tMth::Vector facing = m_facing;\r\n//\t\t\tfacing.RotateY(-0.95f);\r\n//\t\t\tmp_camera_component->SetOverrides(facing, 0.05f);\r\n//\t\t\tbreak;\r\n//\t\t}\r\n//\t\t\t\r\n//\t\tcase CRCC(0x279b1f0b, \"HangMoveRight\"):\r\n//\t\t{\r\n//\t\t\tMth::Vector facing = m_facing;\r\n//\t\t\tfacing.RotateY(0.95f);\r\n//\t\t\tmp_camera_component->SetOverrides(facing, 0.05f);\r\n//\t\t\tbreak;\r\n//\t\t}\r\n//\t\t\t\t\t\r\n//\t\tcase CRCC(0x4194ecca, \"Hang\"):\r\n//\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n//\t\t\tbreak;\r\n//\t\t\r\n//\t\tcase CRCC(0xc84243da, \"Ladder\"):\r\n//\t\tcase CRCC(0xaf5abc82, \"LadderMoveUp\"):\r\n//\t\tcase CRCC(0xfec9dded, \"LadderMoveDown\"):\r\n//\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n//\t\t\tbreak;\r\n//\t\t\t\t\t\r\n//\t\tcase CRCC(0x4fe6069c, \"AnimWait\"):\r\n//\t\t\tif (m_anim_wait_camera_mode == AWC_CURRENT)\r\n//\t\t\t{\r\n//\t\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\tmp_camera_component->SetOverrides(m_drift_goal_facing, 0.05f);\r\n//\t\t\t}\r\n//\t\t\tbreak;\r\n//\t\r\n//\t\tdefault:\r\n//\t\t\tmp_camera_component->UnsetOverrides();\r\n//\t\t\tbreak;\r\n//\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCBaseComponent::EMemberFunctionResult CRiderComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n#\t\tif 0\r\n\t\t// @script | Rider_Ground |\r\n\t\tcase CRCC(0x893213e5, \"Rider_Ground\"):\r\n\t\t\treturn m_state == WALKING_GROUND ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Rider_Air |\r\n\t\tcase CRCC(0x5012082e, \"Rider_Air\"):\r\n\t\t\treturn m_state == WALKING_AIR ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Rider_Hang |\r\n\t\tcase CRCC(0x9a3ca853, \"Rider_Hang\"):\r\n\t\t\treturn m_state == WALKING_HANG ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Rider_Ladder |\r\n\t\tcase CRCC(0x19702ca8, \"Rider_Ladder\"):\r\n\t\t\treturn m_state == WALKING_LADDER ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Rider_GetStateTime | Loads the time in milliseconds since last state change.\r\n\t\tcase CRCC(0xce64576c, \"Rider_GetStateTime\"):\r\n\t\t\tpScript->GetParams()->AddInteger(CRCD(0x5ab23cc9, \"StateTime\"), Tmr::ElapsedTime(m_state_timestamp));\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | Rider_Jump |\r\n\t\tcase CRCC(0x83e4bd70, \"Rider_Jump\"):\r\n\t\t{\r\n\t\t\t// jump strength scales with the length the jump button has been held\r\n\t\t\tjump(Mth::Lerp(\r\n\t\t\t\ts_get_param(CRCD(0x246d0bf3, \"min_jump_factor\")), \r\n\t\t\t\t1.0f,\r\n\t\t\t\tMth::ClampMax(mp_input_component->GetControlPad().m_x.GetPressedTime() / s_get_param(CRCD(0x12333ebd, \"hold_time_for_max_jump\")), 1.0f)\r\n\t\t\t));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase CRCC(0xeb0d763b, \"Rider_HangJump\"):\r\n\t\t{\r\n\t\t\t// jump strength scales with the length the jump button has been held\r\n\t\t\tjump(s_get_param(CRCD(0xf2fa5845, \"hang_jump_factor\")), true);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | Rider_SetDragFactor |\r\n\t\tcase CRCC(0xc6100a7d, \"Rider_SetDragFactor\"):\r\n\t\t\tpParams->GetFloat(NO_NAME, &m_script_drag_factor);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x4e4fae43, \"Rider_ResetDragFactor\"):\r\n\t\t\tm_script_drag_factor = 1.0f;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0xaf04b983, \"Rider_GetSpeedScale\"):\r\n\t\t{\r\n\t\t\tuint32 checksum;\r\n\t\t\tif (m_anim_effective_speed < s_get_param(CRCD(0xf3649996, \"max_slow_walk_speed\")))\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x1150cabb, \"WALK_SLOW\");\r\n\t\t\t}\r\n\t\t\telse if (m_anim_effective_speed < s_get_param(CRCD(0x6a5805d8, \"max_fast_walk_speed\")))\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x131f2a2, \"WALK_FAST\");\r\n\t\t\t}\r\n\t\t\telse if (m_anim_effective_speed < s_get_param(CRCD(0x1c94cc9c, \"max_slow_run_speed\")))\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x5606d106, \"RUN_SLOW\");\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x4667e91f, \"RUN_FAST\");\r\n\t\t\t}\r\n\t\t\tpScript->GetParams()->AddChecksum(CRCD(0x92c388f, \"SpeedScale\"), checksum);\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | Rider_ScaleAnimSpeed | Sets the manner in which the walk animations speeds should be scaled.\r\n\t\t// @flag Off | No animation speed scaling.\r\n\t\t// @flag Run | Scale animation speeds against running speed.\r\n\t\t// @flag Rider | Scale animation speeds against walking speed.\r\n\t\tcase CRCC(0x56112c03, \"Rider_ScaleAnimSpeed\"):\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0xd443a2bc, \"Off\")))\r\n\t\t\t{\r\n\t\t\t\tif (m_anim_scale_speed != OFF)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_anim_scale_speed = OFF;\r\n\t\t\t\t\tmp_animation_component->SetAnimSpeed(1.0f, false, true);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0xaf895b3f, \"Run\")))\r\n\t\t\t{\r\n\t\t\t\tm_anim_scale_speed = RUNNING;\r\n\t\t\t}\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0x6384f1da, \"HangMove\")))\r\n\t\t\t{\r\n\t\t\t\tm_anim_scale_speed = HANGMOVE;\r\n\t\t\t}\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0xa2bfe505, \"LadderMove\")))\r\n\t\t\t{\r\n\t\t\t\tm_anim_scale_speed = LADDERMOVE;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(false, (\"Rider_ScaleAnimSpeed requires Off, Run, or Rider flag\"));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tpParams->GetFloat(CRCD(0xb2d59baf, \"StandardSpeed\"), &m_anim_standard_speed);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | Rider_AnimWaitComplete | Signal from script that the walk component should leave its animation wait\r\n\t\tcase CRCC(0x9d3eebe8, \"Rider_AnimWaitComplete\"):\r\n\t\t\tanim_wait_complete();\r\n\t\t\tbreak;\r\n\t\t\t\t   \t\t\t\r\n\t\t// @script | Rider_GetHangInitAnimType | Determine which type of initial hang animation should be played\r\n\t\tcase CRCC(0xc6cd659e, \"Rider_GetHangInitAnimType\"):\r\n\t\t\t// m_initial_hang_animation is set when the hang rail is filtered\r\n\t\t\tpScript->GetParams()->AddChecksum(CRCD(0x85fa9ac4, \"HangInitAnimType\"), m_initial_hang_animation);\r\n\t\t\tbreak;\r\n#\t\tendif\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CRiderComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CRiderComponent::GetDebugInfo\"));\r\n\t\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase WALKING_GROUND:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0x58007c97, \"GROUND\"));\r\n\t\t\tbreak;\r\n\t\tcase WALKING_AIR:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0x439f4704, \"AIR\"));\r\n\t\t\tbreak;\r\n\t\tcase WALKING_HOP:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0xf41aba21, \"HOP\"));\r\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t \r\n\t\tcase WALKING_HANG:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0x4194ecca, \"HANG\"));\r\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t \r\n        case WALKING_LADDER:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0xc84243da, \"LADDER\"));\r\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t \r\n        case WALKING_ANIMWAIT:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0x4fe6069c, \"ANIMWAIT\"));\r\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t \r\n\t}\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CRiderComponent::SetAssociatedCamera( CCompositeObject* camera_obj )\r\n{\r\n//\tmp_camera = camera_obj;\r\n//\tDbg_Assert(mp_camera);\r\n//\tmp_camera_component = GetWalkCameraComponentFromObject(mp_camera);\r\n//\tDbg_MsgAssert(mp_camera_component, (\"No RiderCameraComponent in camera object\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CRiderComponent::ReadyRiderState( bool to_ground_state )\r\n{\r\n\t// setup the state in preparation for being in walking mode next object update\r\n\tMARK;\r\n\t\r\n\t// Firstly ensure that there is a valid horse nearby.\r\n\tmp_horse_component\t\t\t\t\t\t= NULL;\r\n\r\n\tObj::CHorseComponent* p_horse_component = static_cast<Obj::CHorseComponent*>( Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType( CRC_HORSE ));\r\n\twhile( p_horse_component )\r\n\t{\r\n\t\tObj::CCompositeObject*\tp_horse\t\t= p_horse_component->GetObject();\r\n\t\tMth::Vector\t\t\t\thorse_pos\t= p_horse->GetPos();\r\n\t\tfloat\t\t\t\t\tdist\t\t= Mth::Distance( GetObject()->GetPos(), horse_pos );\r\n\t\tif( dist < 60.0f )\r\n\t\t{\r\n\t\t\tmp_horse_component\t\t\t\t= p_horse_component;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tp_horse_component\t\t\t\t\t= static_cast<Obj::CHorseComponent*>( p_horse_component->GetNextSameType());\r\n\t}\r\n\r\n\tif( mp_horse_component == NULL )\r\n\t{\r\n\t\t// Don't want to proceed.\r\n\t\treturn false;\r\n\r\n\t}\r\n\t\r\n\tprintf( \"ReadyRiderState() found horse\\n\" );\r\n\r\n\tmp_horse_component->AcceptRiderMount( GetObject());\r\n\r\n\t// always reset the state timestamp\r\n    m_state_timestamp = Tmr::GetTime();\r\n\r\n\tif (to_ground_state)\r\n\t{\r\n\t\tset_state(WALKING_GROUND);\r\n\t\t\r\n\t\t// will be incorrect for one frame\r\n\t\tm_ground_normal.Set(0.0f, 1.0f, 0.0);\r\n\t\t\r\n\t\tm_last_ground_feeler_valid = false;\r\n\t\t\r\n\t\tGetObject()->GetVel()[Y] = 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tset_state(WALKING_AIR);\r\n\t\t\r\n\t\t// set primary air direction in the direction of velocity\r\n\t\tm_primary_air_direction = GetObject()->GetVel();\r\n\t\tm_primary_air_direction[Y] = 0.0f;\r\n\t\tfloat length = m_primary_air_direction.Length();\r\n\t\tif (length < 0.001f)\r\n\t\t{\r\n\t\t\t// or facing\r\n\t\t\tm_primary_air_direction = GetObject()->GetMatrix()[Z];\r\n\t\t\tm_primary_air_direction[Y] = 0.0f;\r\n\t\t\tlength = m_primary_air_direction.Length();\r\n\t\t\tif (length < 0.001f)\r\n\t\t\t{\r\n\t\t\t\t// or future facing\r\n\t\t\t\tm_primary_air_direction = -GetObject()->GetMatrix()[Y];\r\n\t\t\t\tm_primary_air_direction[Y] = 0.0f;\r\n\t\t\t\tlength = m_primary_air_direction.Length();\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_primary_air_direction /= length;\r\n\t\t\r\n//\t\tleave_movable_contact_for_air(GetObject()->GetVel(), GetObject()->GetVel()[Y]);\r\n\t}\r\n\r\n\tm_curb_float_height = 0.0f;\r\n\t\r\n\tm_last_frame_event = 0;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CRiderComponent::go_on_horse_state( void )\r\n{\r\n\tMth::Vector pos;\r\n\tMth::Matrix\tmat, display_mat;\r\n\r\n\tpos\t\t\t= mp_horse_component->GetPos();\r\n\tmat\t\t\t= mp_horse_component->GetMatrix();\r\n\tdisplay_mat\t= mp_horse_component->GetDisplayMatrix();\r\n\r\n\tGetObject()->SetPos( pos );\r\n\tGetObject()->SetMatrix( mat );\r\n\tGetObject()->SetDisplayMatrix( display_mat );\r\n\r\n\t// Check for trying to dismount a horse, triggered on triangle.\r\n\tif( mp_input_component->GetControlPad().m_triangle.GetTriggered())\r\n\t{\r\n\t\tmp_input_component->GetControlPad().m_triangle.ClearTrigger();\r\n\r\n\t\t// Get the control component.\r\n\t\tCSkaterPhysicsControlComponent*\tp_control_component = GetSkaterPhysicsControlComponentFromObject( GetObject());\r\n\t\tp_control_component->CallMemberFunction( CRCD( 0x82604c1e, \"SkaterPhysicsControl_SwitchRidingToWalking\"), NULL, NULL );\r\n\r\n\t\tmp_horse_component->AcceptRiderDismount( GetObject());\r\n\r\n\t\tm_frame_event = CRCD( 0x9b46e749, \"Stand\" );\r\n\t\tGetObject()->SelfEvent( m_frame_event );\r\n\t\treturn;\r\n\t}\r\n\r\n\tCAnimationComponent*\tp_anim_component\t= GetAnimationComponentFromObject( GetObject());\r\n\r\n\tScript::CStruct* p_temp_struct = new Script::CStruct();\r\n\r\n\t// Decide which animation to play.\r\n\tswitch( mp_horse_component->GetAnimation())\r\n\t{\r\n\t\tcase CRCC(0xae7deda,\"Horse_Jump\"):\r\n\t\t{\r\n\t\t\tp_temp_struct->AddChecksum( CRCD(0x98549ba4,\"Anim\"), CRCD(0xe978150a,\"Rider_Jump\"));\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0xfe09fe09/*\"NoRestart\"*/);\r\n\t\t\tp_anim_component->PlayAnim( p_temp_struct, NULL, 0.3f );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase CRCC( 0xa337737a, \"Horse_Airidle\" ):\r\n\t\t{\r\n\t\t\tp_temp_struct->AddChecksum( CRCD(0x98549ba4,\"Anim\"), CRCD(0x6600c6f9,\"Rider_Airidle\"));\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0xfe09fe09/*\"NoRestart\"*/);\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0x4f792e6c/*\"Cycle\"*/);\r\n\t\t\tp_anim_component->PlayAnim( p_temp_struct, NULL, 0.3f );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase CRCC( 0x5540d14, \"Horse_Land\" ):\r\n\t\t{\r\n\t\t\tp_temp_struct->AddChecksum( CRCD(0x98549ba4,\"Anim\"), CRCD(0xe6cbc6c4,\"Rider_Land\"));\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0xfe09fe09/*\"NoRestart\"*/);\r\n\t\t\tp_anim_component->PlayAnim( p_temp_struct, NULL, 0.3f );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase CRCC(0x20c5a299,\"Horse_Walk\"):\r\n\t\t{\r\n\t\t\tp_temp_struct->AddChecksum( CRCD(0x98549ba4,\"Anim\"), CRCD(0xc35a6949,\"Rider_Walk\"));\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0xfe09fe09/*\"NoRestart\"*/);\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0x4f792e6c/*\"Cycle\"*/);\r\n\t\t\tp_anim_component->PlayAnim( p_temp_struct, NULL, 0.3f );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase CRCC(0x8a354e68,\"Horse_Trot\"):\r\n\t\t{\r\n\t\t\tp_temp_struct->AddChecksum( CRCD(0x98549ba4,\"Anim\"), CRCD(0x69aa85b8,\"Rider_Trot\"));\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0xfe09fe09/*\"NoRestart\"*/);\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0x4f792e6c/*\"Cycle\"*/);\r\n\t\t\tp_anim_component->PlayAnim( p_temp_struct, NULL, 0.3f );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase CRCC(0x1bee30eb,\"Horse_Canter\"):\r\n\t\t{\r\n\t\t\tp_temp_struct->AddChecksum( CRCD(0x98549ba4,\"Anim\"), CRCD(0x96600d53,\"Rider_Canter\"));\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0xfe09fe09/*\"NoRestart\"*/);\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0x4f792e6c/*\"Cycle\"*/);\r\n\t\t\tp_anim_component->PlayAnim( p_temp_struct, NULL, 0.3f );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase CRCC(0x2ca2c118,\"Horse_Gallop\"):\r\n\t\t{\r\n\t\t\tp_temp_struct->AddChecksum( CRCD(0x98549ba4,\"Anim\"), CRCD(0xa12cfca0,\"Rider_Gallop\"));\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0xfe09fe09/*\"NoRestart\"*/);\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0x4f792e6c/*\"Cycle\"*/);\r\n\t\t\tp_anim_component->PlayAnim( p_temp_struct, NULL, 0.3f );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase CRCC(0xf0ebc152,\"Horse_StandIdle\"):\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tp_temp_struct->AddChecksum( CRCD(0x98549ba4,\"Anim\"), CRCD(0x5b4e88ee,\"Rider_StandIdle\"));\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0xfe09fe09/*\"NoRestart\"*/);\r\n\t\t\tp_temp_struct->AddChecksum( (uint32)0, 0x4f792e6c/*\"Cycle\"*/);\r\n\t\t\tp_anim_component->PlayAnim( p_temp_struct, NULL, 0.3f );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tdelete p_temp_struct;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRiderComponent::go_on_ground_state (   )\r\n{\r\n#\tif 0\r\n\r\n\taccount_for_movable_contact();\r\n\t\r\n\tsetup_collision_cache();\r\n\t\r\n\t// calculate initial horizontal speed\r\n\tfloat horizontal_speed = m_horizontal_vel.Length();\r\n\t\r\n\tcalculate_horizontal_speed_and_facing(horizontal_speed);\r\n\t\r\n\t// calculate this frame's movement\r\n\tm_horizontal_vel = horizontal_speed * m_facing;\r\n\t\r\n\t// prevent movement into walls\r\n\tif (adjust_horizonal_vel_for_environment(true))\r\n\t{\r\n\t\t// turn to face newly adjusted velocity\r\n\t\tadjust_facing_for_adjusted_horizontal_vel();\r\n\t}\r\n\t\r\n\t// if we are wall pushing, we may have decided to switch states during adjust_horizonal_vel_for_environment based on our environment\r\n\tif (m_state != WALKING_GROUND || should_bail_from_frame())\r\n\t{\r\n\t\tCFeeler::sClearDefaultCache();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// apply movement for this frame\r\n\tm_pos += m_horizontal_vel * m_frame_length;\r\n\t\r\n\t// snap up and down curbs and perhaps switch to air\r\n\trespond_to_ground();\r\n\tif (m_state != WALKING_GROUND || should_bail_from_frame())\r\n\t{\r\n\t\tCFeeler::sClearDefaultCache();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tadjust_curb_float_height();\r\n\t\r\n\t// insure that we do not slip through the cracks in the collision geometry which are a side-effect of moving collidable objects\r\n\tif (CCompositeObject* p_inside_object = mp_movable_contact_component->CheckInsideObjects(m_pos, m_frame_start_pos))\r\n\t{\r\n\t\tMESSAGE(\"WALKING_GROUND, within moving object\");\r\n\t\t\r\n\t\t// allow it to push us forward, causing a bit of a stumble\r\n\t\tm_horizontal_vel = p_inside_object->GetVel();\r\n\t\tm_horizontal_vel[Y] = 0.0f;\r\n\t\tm_vertical_vel = 0.0f;\r\n\t\t\r\n\t\tfloat speed_sqr = m_horizontal_vel.LengthSqr();\r\n\t\tif (speed_sqr > (10.0f * 10.0f))\r\n\t\t{\r\n\t\t\tm_facing = m_horizontal_vel * (1.0f / sqrtf(speed_sqr));\r\n\t\t}\r\n\t}\r\n\t\r\n\tCFeeler::sClearDefaultCache();\r\n#\tendif\r\n}\r\n\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gel/Components/RiderComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       RiderComponent.h\r\n//* OWNER:          Dave\r\n//* CREATION DATE:  5/30/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_RIDERCOMPONENT_H__\r\n#define __COMPONENTS_RIDERCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/timestampedflag.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/horsecomponent.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n#include <sk/engine/feeler.h>\r\n\r\n#define\t\tCRC_RIDER CRCD(0x15beefca,\"Rider\")\r\n\r\n#define\t\tGetRiderComponent()\t\t\t\t\t((Obj::CRiderComponent*)GetComponent(CRC_RIDER))\r\n#define\t\tGetRiderComponentFromObject(pObj)\t((Obj::CRiderComponent*)(pObj)->GetComponent(CRC_RIDER))\r\n\r\nclass CFeeler;\r\n\t\t\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\tclass CCollCache;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CAnimationComponent;\r\n\tclass CModelComponent;\r\n\tclass CTriggerComponent;\r\n\tclass CRiderCameraComponent;\r\n\tclass CSkaterPhysicsControlComponent;\r\n\tclass CMovableContactComponent;\r\n\t\r\nclass CRiderComponent : public CBaseComponent\r\n{\r\npublic:\r\n\tenum EStateType\r\n\t{\r\n\t\tWALKING_GROUND,\r\n\t\tWALKING_AIR,\r\n\t\tWALKING_HOP,\r\n\t\tWALKING_HANG,\r\n\t\tWALKING_LADDER,\r\n\t\tWALKING_ANIMWAIT\r\n\t};\r\n\t\r\n\tenum EAnimScaleSpeed\r\n\t{\r\n\t\tOFF,\r\n\t\tRUNNING,\r\n        HANGMOVE,\r\n\t\tLADDERMOVE\r\n\t};\r\n\t\r\n\tenum\r\n\t{\r\n\t\tvNUM_FEELERS = 7,\r\n\t\tvNUM_BARRIER_HEIGHT_FEELERS = 7\r\n\t};\r\n\t\r\n\ttypedef void (Obj::CRiderComponent::*AnimWaitCallbackPtr) (   );\r\n\t\r\npublic:\r\n    CRiderComponent();\r\n    virtual ~CRiderComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tEStateType\t\t\t\t\t\tGetState (   ) { return m_state; }\r\n\t\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\tset_state ( EStateType state );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tgo_on_horse_state( void );\r\n\r\n\tvoid\t\t\t\t\t\t\tgo_on_ground_state (   );\r\n\tvoid\t\t\t\t\t\t\tcalculate_horizontal_speed_and_facing ( float &horizontal_speed );\r\n\tbool\t\t\t\t\t\t\tadjust_horizonal_vel_for_environment ( bool wall_push_active );\r\n\tvoid\t\t\t\t\t\t\tadjust_facing_for_adjusted_horizontal_vel (   );\r\n\tfloat\t\t\t\t\t\t\tadjust_desired_speed_for_slope ( float desired_speed );\r\n\tvoid\t\t\t\t\t\t\trespond_to_ground (   );\r\n\tvoid\t\t\t\t\t\t\tadjust_curb_float_height (   );\r\n\tvoid\t\t\t\t\t\t\taccount_for_movable_contact (   );\r\n\tvoid\t\t\t\t\t\t\tjump ( float strength, bool hang_jump = false );\r\n\tvoid\t\t\t\t\t\t\tgo_in_air_state (   );\r\n\tvoid\t\t\t\t\t\t\tcontrol_horizontal_vel (   );\r\n\tvoid\t\t\t\t\t\t\tadjust_vertical_vel_for_ceiling (   );\r\n\tvoid\t\t\t\t\t\t\tcheck_for_landing ( const Mth::Vector& previous_pos, const Mth::Vector& final_pos );\r\n\tvoid\t\t\t\t\t\t\tuber_frig (   );\r\n\tvoid\t\t\t\t\t\t\tlerp_upright (   );\r\n\tbool\t\t\t\t\t\t\tcheck_for_wall_push (   );\r\n\tvoid\t\t\t\t\t\t\tleave_movable_contact_for_air ( Mth::Vector& horizontal_vel, float& vertical_vel );\r\n\tbool\t\t\t\t\t\t\tmaybe_hop_to_hang (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_drop_to_hang (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_grab_to_hang ( Mth::Vector start_pos, Mth::Vector end_pos );\r\n\tvoid\t\t\t\t\t\t\tgo_hop_state (   );\r\n\tvoid\t\t\t\t\t\t\tgo_hang_state (   );\r\n\tvoid\t\t\t\t\t\t\thang_movement (   );\r\n\tvoid\t\t\t\t\t\t\tfind_neighboring_hang_rail ( float movement, bool descending );\r\n\tvoid\t\t\t\t\t\t\tset_pos_from_hang_rail_state (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_pull_up_from_hang (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_jump_low_barrier (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_climb_up_ladder ( bool user_requested = false );\r\n\tbool\t\t\t\t\t\t\tmaybe_climb_down_ladder (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_grab_to_ladder ( const Mth::Vector& start_pos, const Mth::Vector& end_pos );\r\n\tvoid\t\t\t\t\t\t\tgo_ladder_state (   );\r\n\tvoid\t\t\t\t\t\t\tladder_movement (   );\r\n\tvoid\t\t\t\t\t\t\toff_ladder_bottom (   );\r\n\tvoid\t\t\t\t\t\t\toff_ladder_top (   );\r\n\tvoid\t\t\t\t\t\t\tcalculate_anim_wait_facing_drift_parameters ( const Mth::Vector& goal_facing );\r\n    void                            go_anim_wait_state (   );\r\n    void                            anim_wait_complete (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_stick_to_rail (   );\r\n\tvoid\t\t\t\t\t\t\tsetup_collision_cache (   );\r\n\tvoid\t\t\t\t\t\t\tcopy_state_into_object (   );\r\n\tvoid\t\t\t\t\t\t\tget_controller_input (   );\r\n\tvoid\t\t\t\t\t\t\tadjust_control_for_forced_run (   );\r\n\tfloat\t\t\t\t\t\t\tcalculate_desired_speed (   );\r\n\tMth::Vector\t\t\t\t\t\tcalculate_feeler_offset_direction ( int contact );\r\n\tbool\t\t\t\t\t\t\tforced_run (   );\r\n\tbool\t\t\t\t\t\t\tdetermine_stand_pos ( const Mth::Vector& proposed_stand_pos, Mth::Vector& stand_pos, CFeeler& feeler );\r\n\tbool\t\t\t\t\t\t\tshould_bail_from_frame (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tdrop_to_hang_complete (   );\r\n\tvoid\t\t\t\t\t\t\tpull_up_from_hang_complete (   );\r\n\tvoid\t\t\t\t\t\t\tmove_to_ladder_bottom_complete (   );\r\n\tvoid\t\t\t\t\t\t\tmove_to_ladder_top_complete (   );\r\n\tvoid\t\t\t\t\t\t\toff_ladder_bottom_complete (   );\r\n\tvoid\t\t\t\t\t\t\toff_ladder_top_to_ground_complete (   );\r\n\tvoid\t\t\t\t\t\t\toff_ladder_top_to_air_complete (   );\r\n\t\r\n\tstatic float\t\t\t\t\ts_get_param ( uint32 checksum );\r\n\t\r\npublic:\r\n\tbool\t\t\t\t\t\t\tIsRunning (   );\r\n\tbool\t\t\t\t\t\t\tUseDPadCamera (   );\r\n\tvoid\t\t\t\t\t\t\tSetForwardControlLock ( bool forward_control_lock );\r\n\tvoid\t\t\t\t\t\t\tSetAssociatedCamera ( CCompositeObject* camera_obj );\r\n    \r\n    const Mth::Vector&              GetEffectivePos (   );\r\n\t\r\n\tbool\t\t\t\t\t\t\tReadyRiderState ( bool to_ground_state );\r\n\t\r\nprivate:\r\n\tEStateType\t\t\t\t\t\tm_state;\r\n\t\r\n\t// Time stamp of when our state last changed.\r\n\tTmr::Time\t\t\t\t\t\tm_state_timestamp;\r\n\t\r\n\t// State we changed from when m_state_timestamp was last set.\r\n\tEStateType\t\t\t\t\t\tm_previous_state;\r\n\t\r\n\t// Extracted from the object at frame start and back into the object at frame end.\r\n\tMth::Vector\t\t\t\t\t\tm_pos;\r\n\tMth::Vector\t\t\t\t\t\tm_horizontal_vel;\r\n\tfloat\t\t\t\t\t\t\tm_vertical_vel;\r\n\tMth::Vector\t\t\t\t\t\tm_facing;\r\n\tMth::Vector\t\t\t\t\t\tm_upward;\r\n\t\r\n\t// Cache our position at the frame's start\r\n\tMth::Vector\t\t\t\t\t\tm_frame_start_pos;\r\n\t\r\n\t// Script event reporting our current state.  Set during each frame update and sent at the end of the update.\r\n\tuint32\t\t\t\t\t\t\tm_frame_event;\r\n\t\r\n\t// Last frame's frame event.\r\n\tuint32\t\t\t\t\t\t\tm_last_frame_event;\r\n\t\r\n\t// Current frame's frame length.\r\n\tfloat\t\t\t\t\t\t\tm_frame_length;\r\n\t\r\n\t// Current frame's control input.\r\n\tMth::Vector\t\t\t\t\t\tm_control_direction;\r\n\tfloat\t\t\t\t\t\t\tm_control_magnitude;\r\n\tbool\t\t\t\t\t\t\tm_control_pegged;\r\n\t\r\n\tstruct SContact\r\n\t{\r\n\t\t// If this contact is in collision with the environment.\r\n\t\tbool\t\t\t\t\t\tin_collision;\r\n\t\t\r\n\t\t// The horizontal normal of the collided geometry.\r\n\t\tMth::Vector\t\t\t\t\tnormal;\r\n\t\t\r\n\t\t// Distance from the collision as a factor of the feeler length.\r\n\t\tfloat\t\t\t\t\t\tdistance;\r\n\t\t\r\n\t\t// If the collision in this direction is determined to be low enough to jump.\r\n\t\tbool\t\t\t\t\t\tjumpable;\r\n\t\t\r\n\t\t// Movement of the object we're in contact with (not accounting for its rotation) along its horizontal normal.\r\n\t\tfloat\t\t\t\t\t\tmovement;\r\n\t\t\r\n\t// The walker looks around him in vNUM_FEELERS directions and stores the results here.  The final contact is felt for along the movement of\r\n\t// the origin, and is only used while in the air.\r\n\t} mp_contacts [ vNUM_FEELERS + 1 ];\r\n\t\r\n\t// Type of animation speed scaling to do.\r\n\tEAnimScaleSpeed\t\t\t\t\tm_anim_scale_speed;\r\n\t\r\n\t// Horizontal speed for the purposes of animation speed scaling.\r\n\tfloat\t\t\t\t\t\t\tm_anim_effective_speed;\r\n\t\r\n\t// Factor multiplied by all velocities.  Set by script.\r\n\tfloat\t\t\t\t\t\t\tm_script_drag_factor;\r\n\t\r\n\t// Used to lock control in the forward direction (during a camera flush request)\r\n\tbool\t\t\t\t\t\t\tm_forward_control_lock;\r\n\t\r\n\t// When on ground, the walker is often floated above the ground in an attempt to smooth out stair/curb climbs.\r\n\tfloat\t\t\t\t\t\t\tm_curb_float_height;\r\n\t\r\n\t// If m_curb_float_height was adjusted this frame.  If not, we lerp it to zero.\r\n\tbool\t\t\t\t\t\t\tm_curb_float_height_adjusted;\r\n\t\r\n\t// The collision cache used.\r\n\tNx::CCollCache*\t\t\t\t\tmp_collision_cache;\r\n\t\r\n\t// Associated camera.\r\n\tCCompositeObject*\t\t\t\tmp_camera;\r\n\tCRiderCameraComponent*\t\t\tmp_camera_component;\r\n\tCHorseComponent*\t\t\t\tmp_horse_component;\t\t// This points to the CHorseComponent in the separate CCompositeObject that is the horse being ridden.\r\n\t\r\n    // If associated with a rail, this is the rail node and rail manager.\r\n    const CRailNode*              \tmp_rail_node;\r\n    CRailManager*                   mp_rail_manager;\r\n\t\r\n\t// Peer components.\r\n\tCInputComponent*\t\t\t\tmp_input_component;\r\n\tCAnimationComponent*\t\t\tmp_animation_component;\r\n\tCModelComponent*\t\t\t\tmp_model_component;\r\n\tCTriggerComponent*\t\t\t\tmp_trigger_component;\r\n\tCSkaterPhysicsControlComponent*\tmp_physics_control_component;\r\n\tCMovableContactComponent*\t\tmp_movable_contact_component;\r\n    \r\n\t/////////////////////////////////\r\n\t// WALKING_GROUND state variables\r\n\t\r\n\t// Normal of the ground on which we are standing.  Only meaningful when on the ground.  Set the previous frame.\r\n\tMth::Vector\t\t\t\t\t\tm_ground_normal;\r\n\t\r\n\t// Certain things such as rotation rate and camera lerp are increased when this is set.\r\n\tbool\t\t\t\t\t\t\tm_run_toggle;\r\n\t\r\n\tstruct SWallPushTest\r\n\t{\r\n\t\t// Whether we currently testing.\r\n\t\tbool\t\t\t\t\t\tactive;\r\n\t\t\r\n\t\t// Time at which this test began.\r\n\t\tTmr::Time\t\t\t\t\ttest_start_time;\r\n\t\t\r\n\t// Data used to detect when a player is pushing into a wall in order to climb it.\r\n\t}\t\t\t\t\t\t\t\tm_wall_push_test;\r\n\t\r\n\t// When doing anim speed scaling when running, this is set to the run speed which corresponds to the current animation playing at standard speed.\r\n\tfloat\t\t\t\t\t\t\tm_anim_standard_speed;\r\n\t\r\n\t// A copy of the latest feeler which contacted the groud under us.\r\n\tCFeeler\t\t\t\t\t\t\tm_last_ground_feeler;\r\n\tbool\t\t\t\t\t\t\tm_last_ground_feeler_valid;\r\n\t\r\n\t/////////////////////////////////\r\n\t// WALKING_AIR state variables\r\n\t\r\n\t// The forward horizontal direction of the jump which, when coming out of skating or because of in-air velocity control, diverges from the direction of velocity\r\n\tMth::Vector\t\t\t\t\t\tm_primary_air_direction;\r\n\t\r\n\t// This term of our horizontal velocity is due to leaping from a movable contact, and is not adjustable via in-air control.\r\n\tMth::Vector\t\t\t\t\t\tm_uncontrollable_air_horizontal_vel;\r\n\t\r\n\t/////////////////////////////////\r\n\t// WALKING_HANG state variables\r\n\t\r\n\t// Measures our position along the current rail as a parameter running from 0.0 to 1.0.\r\n\tfloat\t\t\t\t\t\t\tm_along_rail_factor;\r\n\t\r\n\t// Measures the hang position offset from the actual rail we are hanging from.\r\n\tfloat\t\t\t\t\t\t\tm_vertical_hang_offset;\r\n\tfloat\t\t\t\t\t\t\tm_horizontal_hang_offset;\r\n\t\r\n\t// Checksum describing the type of initial hang animation to play.\r\n\tuint32\t\t\t\t\t\t\tm_initial_hang_animation;\r\n    \r\n\t/*\r\n\t/////////////////////////////////\r\n\t// WALKING_HOP state variables\r\n\t\r\n    // The position we will have at the end of the hop.\r\n    Mth::Vector                     m_goal_hop_pos;\r\n    \r\n    // The facing we will have at the end of the hop.\r\n    Mth::Vector                     m_goal_hop_facing;\r\n\t\r\n\t// Hang state variable.  Set at hop start.\r\n\t// float\t\t\t\t\t\tm_along_rail_factor;\r\n\t\r\n\t// Hang state variable.  Set at hop start.\r\n\t// uint32\t\t\t\t\t\t\tm_initial_hang_animation;\r\n\t*/\r\n    \r\n\t/////////////////////////////////\r\n\t// WALKING_LADDER state variables\r\n\t\r\n\t// Shared with hang state.\r\n\t// float\t\t\t\t\t\tm_along_rail_factor;\r\n    \r\n\t/////////////////////////////////\r\n\t// WALKING_ANIMWAIT state variables\r\n\t\r\n\t// Position at the start of the animation wait.\r\n\tMth::Vector\t\t\t\t\t\tm_anim_wait_initial_pos;\r\n\t\r\n\t// Facing at the start of the aniamtion wait.\r\n\tMth::Vector\t\t\t\t\t\tm_anim_wait_initial_facing;\r\n\t\r\n    // Amount to move the object at the end of the animation wait.\r\n    Mth::Vector                     m_anim_wait_goal_pos;\r\n\t\r\n\t// Goal facing of the position drift.\r\n\tMth::Vector\t\t\t\t\t\tm_drift_goal_facing;\r\n\t\r\n\t// The angle over which the facing must drift.\r\n\tfloat\t\t\t\t\t\t\tm_drift_angle;\r\n    \r\n\t// Accumulates position offset due to a movable contact during an animation wait.\r\n\tMth::Vector\t\t\t\t\t\tm_offset_due_to_movable_contact;\r\n\t\r\n\t// The behavior of the camera during the animation wait.\r\n\tenum EAnimWaitCameraModeType\t\t\t\r\n\t{\r\n\t\tAWC_CURRENT,\r\n\t\tAWC_GOAL\r\n\t}\t\t\t\t\t\t\t\tm_anim_wait_camera_mode;\r\n\t\r\n\t// Callback function to call upon completion of the animation wait.\r\n\tAnimWaitCallbackPtr\t\t\t\tmp_anim_wait_complete_callback;\r\n\t\r\n\t// WALKING_GROUND state variable sometimes set at start of animation wait based on the animation end ground situation\r\n\t// Mth::Vector\t\t\t\t\tm_ground_normal;\r\n\t// CFeeler\t\t\t\t\t\tm_last_ground_feeler;\r\n\t// bool\t\t\t\t\t\t\tm_last_ground_feeler_valid;\r\n\t\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CRiderComponent::set_state ( EStateType state )\r\n{\r\n    if (state == m_state) return;\r\n\t\r\n\tm_previous_state = m_state;\r\n    \r\n    if (m_state == WALKING_GROUND)\r\n    {\r\n        m_wall_push_test.active = false;\r\n\t\tm_run_toggle = false;\r\n    }\r\n\t\r\n\tm_state = state;\r\n\tm_state_timestamp = Tmr::GetTime();\r\n\t\r\n\tif (m_state == WALKING_ANIMWAIT)\r\n\t{\r\n\t\tm_offset_due_to_movable_contact.Set();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float CRiderComponent::s_get_param ( uint32 checksum )\r\n{\r\n\tScript::CStruct* p_walk_params = Script::GetStructure(CRCD(0x6775e538, \"walk_parameters\"));\r\n\tDbg_Assert(p_walk_params);\r\n\t\r\n\tfloat param;\r\n\tp_walk_params->GetFloat(checksum, &param, Script::ASSERT);\r\n\treturn param;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CRiderComponent::forced_run (   )\r\n{\r\n\treturn false;\r\n\tif (!mp_input_component->GetControlPad().m_x.GetPressed()) return false;\r\n\t\r\n\tuint32 pressed_time = mp_input_component->GetControlPad().m_x.GetPressedTime();\r\n\treturn pressed_time > m_state_timestamp || pressed_time > s_get_param(CRCD(0xa7f5ba13, \"forced_run_delay\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CRiderComponent::should_bail_from_frame (   )\r\n{\r\n\t// for now, all restarts switch us to skating; so, only bail from frame if we're ever switch out of walking via script\r\n//\treturn !mp_physics_control_component->IsWalking();\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CRiderComponent::IsRunning (   )\r\n{\r\n\treturn m_run_toggle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CRiderComponent::SetForwardControlLock ( bool forward_control_lock )\r\n{\r\n\tm_forward_control_lock = forward_control_lock;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Vector& CRiderComponent::GetEffectivePos (   )\r\n{\r\n    if (m_state != WALKING_ANIMWAIT)\r\n    {\r\n        return GetObject()->GetPos();\r\n    }\r\n    else\r\n    {\r\n        return GetObject()->GetPos();\r\n    }\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CRiderComponent::UseDPadCamera (   )\r\n{\r\n\t\r\n\treturn mp_input_component->GetControlPad().m_leftX == 0.0f && mp_input_component->GetControlPad().m_leftY == 0.0f && m_control_pegged;\r\n}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/SetDisplayMatrixComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SetDisplayMatrixComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  8/6/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/setdisplaymatrixcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSetDisplayMatrixComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSetDisplayMatrixComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSetDisplayMatrixComponent::CSetDisplayMatrixComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SETDISPLAYMATRIX );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSetDisplayMatrixComponent::~CSetDisplayMatrixComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSetDisplayMatrixComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSetDisplayMatrixComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSetDisplayMatrixComponent::Update()\r\n{\r\n\tGetObject()->SetDisplayMatrix(GetObject()->GetMatrix());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSetDisplayMatrixComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSetDisplayMatrixComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSetDisplayMatrixComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/SetDisplayMatrixComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SetDisplayMatrixComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  8/6/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SETDISPLAYMATRIXCOMPONENT_H__\r\n#define __COMPONENTS_SETDISPLAYMATRIXCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_SETDISPLAYMATRIX CRCD(0x1bbf844d,\"SetDisplayMatrix\")\r\n\r\n#define\t\tGetSetDisplayMatrixComponent() ((Obj::CSetDisplayMatrixComponent*)GetComponent(CRC_SETDISPLAYMATRIX))\r\n#define\t\tGetSetDisplayMatrixComponentFromObject(pObj) ((Obj::CSetDisplayMatrixComponent*)(pObj)->GetComponent(CRC_SETDISPLAYMATRIX))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CSetDisplayMatrixComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSetDisplayMatrixComponent();\r\n    virtual ~CSetDisplayMatrixComponent();\r\n\r\npublic:\r\n\tvirtual void\t\t\t\t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tUpdate();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/SkaterCameraComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SkaterCameraComponent.cpp\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/21/03\r\n//****************************************************************************\r\n\r\n#include <gel/components/skatercameracomponent.h>\r\n\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/components/cameracomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/camerautil.h>\r\n#include <gel/components/cameralookaroundcomponent.h>\r\n#include <gel/components/movablecontactcomponent.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/nxviewman.h>\r\n\r\n#include <sk/objects/proxim.h>\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skaterbalancetrickcomponent.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\nconst float SKATERCAMERACOMPONENT_LEAN_TO_SKATERCAM_LEAN\t= (( Mth::PI / 6.0f ) / -4096.0f );\r\n\t\r\nconst float\tSKATERCAMERACOMPONENT_INTERPOLATOR_TIMESTEP\t\t= ( 1.0f / 60.0f );\r\n\r\n// This is the value that mAbove should tend to when the behind value is closer than mBehind.\r\n\r\nconst float VERT_AIR_LANDED_TIME\t= 10.0f / 60.0f;\r\nconst float TILT_MAX\t\t\t\t= 0.34907f;\t\t\t\t\t\t// 20 degees.\r\nconst float TILT_MIN\t\t\t\t= -0.34907f;\t\t\t\t\t// -20 degees.\r\nconst float TILT_INCREMENT\t\t\t= 2.0f * ( TILT_MAX / 60.0f );\t// 40 degrees/second.\r\nconst float TILT_DECREMENT\t\t\t= 2.0f * ( TILT_MAX / 60.0f );\t// 40 degrees/second.\r\nconst float TILT_RESTORE\t\t\t= 8.0f * ( TILT_MAX / 60.0f );\t// 160 degrees/second.\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void _xrotlocal ( Mth::Matrix& m, float a )\r\n{\r\n\tm.RotateXLocal( a );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCBaseComponent* CSkaterCameraComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterCameraComponent );\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCSkaterCameraComponent::CSkaterCameraComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERCAMERA );\r\n\t\r\n\tmMode = SKATERCAM_MODE_UNDEFINED;\r\n\t\t\t\t  \r\n\t// Create the SLERP interpolator here.\r\n\tmpSlerp\t\t\t\t= new Mth::SlerpInterpolator;\r\n\r\n\t// Set current zoom and LERP rates.\r\n\tmCurrentZoom\t\t= 1.0f;\r\n\tmZoomLerp\t\t\t= 0.0625f;\r\n\tmLastDot\t\t\t= 1.0f;\r\n\r\n\tmLerpXZ\t\t\t\t= 0.25f;\r\n\tmLerpY\t\t\t\t= 0.5f;\r\n\tmVertAirLerpXZ\t\t= 1.0f;\r\n\tmVertAirLerpY\t\t= 1.0f;\r\n\tmGrindLerp\t\t\t= 0.1f;\r\n\t\r\n\tmpSkater= NULL;\r\n\tmpSkaterStateComponent = NULL;\r\n\tmpSkaterPhysicsControlComponent = NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCSkaterCameraComponent::~CSkaterCameraComponent()\r\n{\r\n\tdelete mpSlerp;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCameraComponent::Finalize (   )\r\n{\r\n\tmp_lookaround_component = GetCameraLookAroundComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_lookaround_component);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCameraComponent::Enable( bool enable )\r\n{\r\n\tCCameraComponent *p_cam_comp = GetCameraComponentFromObject( GetObject());\r\n\tDbg_MsgAssert( p_cam_comp, ( \"SkaterCameraComponent requires CameraComponent attached to parent\" ));\r\n\tp_cam_comp->Enable( enable );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nGfx::Camera* CSkaterCameraComponent::GetCamera( void )\r\n{\r\n\tCCameraComponent *p_cam_comp = GetCameraComponentFromObject( GetObject());\r\n\tDbg_MsgAssert( p_cam_comp, ( \"SkaterCameraComponent requires CameraComponent attached to parent\" ));\r\n\treturn p_cam_comp->GetCamera();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::Vector& CSkaterCameraComponent::GetPosition( void ) const \r\n{\r\n\tCCameraComponent *p_cam_comp = GetCameraComponentFromObject( GetObject());\r\n\tDbg_MsgAssert( p_cam_comp, ( \"SkaterCameraComponent requires CameraComponent attached to parent\" ));\r\n\treturn p_cam_comp->GetPosition();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCameraComponent::SetPosition( Mth::Vector& pos )\r\n{\r\n\tCCameraComponent *p_cam_comp = GetCameraComponentFromObject( GetObject());\r\n\tDbg_MsgAssert( p_cam_comp, ( \"SkaterCameraComponent requires CameraComponent attached to parent\" ));\r\n\tp_cam_comp->SetPosition( pos );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::Matrix& CSkaterCameraComponent::GetMatrix( void ) const\r\n{\r\n\tCCameraComponent *p_cam_comp = GetCameraComponentFromObject( GetObject());\r\n\tDbg_MsgAssert( p_cam_comp, ( \"SkaterCameraComponent requires CameraComponent attached to parent\" ));\r\n\treturn p_cam_comp->GetMatrix();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCameraComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\r\n// NOT We need a CCameraComponent attached in order to get camera details.\r\n//\tCCameraComponent *p_cam_comp\t= GetCameraComponentFromObject( GetObject());\r\n//\tDbg_MsgAssert( p_cam_comp, ( \"CSkaterCameraComponent needs CCameraComponent attached to parent\" ));\r\n\r\n\t// Clear the frame matrix, so that future slerps make sense.\r\n\t//Mth::Matrix& frame_matrix\t\t= p_cam_comp->GetMatrix();\r\n\tMth::Matrix& frame_matrix\t\t= GetObject()->GetMatrix();\r\n\tframe_matrix.Ident();\r\n\r\n\tmLastActualRight \t\t\t\t= frame_matrix[X];\r\n\tmLastActualUp \t\t\t\t\t= frame_matrix[Y];\r\n\tmLastActualAt \t\t\t\t\t= frame_matrix[Z];\r\n\r\n\r\n\t// The camera requires a \"CameraTarget\" checksum parameter\r\n\tuint32\ttarget_id = 0 ;\r\n\tpParams->GetChecksum(\"CameraTarget\", &target_id, true);\r\n\r\n\tDbg_MsgAssert(target_id >=0 && target_id <= 15,(\"Bad CameraTarget 0x%x in SkaterCameraComponent\",target_id));\r\n\r\n\tCSkater* p_skater = static_cast<CSkater*>(CCompositeObjectManager::Instance()->GetObjectByID(target_id)); \r\n\tDbg_MsgAssert(p_skater,(\"Can't find skater %d in SkaterCameraComponent\",target_id));\r\n\r\n\t\t\r\n\tSetSkater(p_skater);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCameraComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Reinitialise.\r\n\tInitFromStructure( pParams );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCameraComponent::Commit( void )\r\n{\r\n\t// Under the normal operation of components, the CSkaterCameraComponent updates the values\r\n\t// in CCameraComponent during its Update() function. The CCameraComponent in turn will set\r\n\t// the Gfx::CCamera values during it's Update() function.\r\n\t// In some cases however, we need the camera changes to be committed to the Gfx::Camera\r\n\t// immediately, usually when logic is paused, and the component Update()'s are not taking place.\r\n\tCCameraComponent *p_cam_component = GetCameraComponentFromObject( GetObject());\r\n\tif( p_cam_component )\r\n\t{\r\n\t\tp_cam_component->Update();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCameraComponent::ReadyForActivation ( const SCameraState& state )\r\n{\r\n\tDbg_MsgAssert(mpSkater, (\"Skater camera (%s) has NULL target\", Script::FindChecksumName(GetObject()->GetID())));\r\n\t\r\n\tmLastActualRight = state.lastActualMatrix[X];\r\n\tmLastActualUp = state.lastActualMatrix[Y];\r\n\tmLastActualAt = state.lastActualMatrix[Z];\r\n\tmLastTripodPos = state.lastTripodPos;\r\n\tmLastDot = state.lastDot;\r\n\tmCurrentZoom = state.lastZoom;\r\n\tmVertAirLandedTimer = 0.0f;\r\n\tmInstantCount = 0;\r\n\t\r\n\tmp_lookaround_component->mLookaroundHeading = 0.0f;\r\n\tmp_lookaround_component->mLookaroundLock = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCameraComponent::Update( void )\r\n{\r\n\tif( mpSkater == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// optimization KLUDGE\r\n\tif (mpSkaterPhysicsControlComponent && mpSkaterPhysicsControlComponent->IsDriving())\r\n\t{\r\n\t\tGetObject()->Pause(true);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// We need a CCameraComponent attached in order to get camera details.\r\n\tCCameraComponent *p_cam_comp = GetCameraComponentFromObject( GetObject());\r\n\tDbg_MsgAssert( p_cam_comp, ( \"CSkaterCameraComponent needs CCameraComponent attached to parent\" ));\r\n\r\n\t// This used to be passed in as a param for the old CSkaterCam::Update().\r\n\t// Now we get it from a flag in the skater\r\n\tbool instantly = false;\r\n\t\r\n\tDbg_Assert( mpSkater );\r\n\tif (mpSkater->HasTeleported())\r\n\t{\r\n\t\tinstantly = true;\r\n\t}\r\n\r\n\tif( instantly )\r\n\t{\r\n\t\tmInstantCount = 3;\r\n\t}\r\n\r\n\tif( mInstantCount > 0 )\r\n\t{\r\n\t\t--mInstantCount;\r\n\t\tinstantly = true;\r\n\t}\r\n\r\n\t\t\r\n//\tif (instantly)\r\n//\t{\r\n//\t\tprintf (\"%d: Instantly!\\n\",(int)Tmr::GetRenderFrame());\r\n//\t}\r\n\t\t\r\n\t// Length of last frame in seconds.\r\n\tfloat delta_time = Tmr::FrameLength();\r\n\r\n\t// Update any values we are currently interpolating.\r\n\tUpdateInterpolators();\r\n\r\n\t// Would have used a SetPos() function, but the camera update in rwviewer.cpp is spread out all over the place,\r\n\t// so it's not easy to do. We'll just store the old position before updating anything...\r\n//\tGfx::Camera::StoreOldPos();\r\n\tp_cam_comp->StoreOldPosition();\r\n\r\n//\tMth::Matrix& frame_matrix\t= Gfx::Camera::GetMatrix();\r\n\tMth::Matrix& frame_matrix\t= p_cam_comp->GetMatrix();\r\n\r\n\tframe_matrix[X]   \t\t= mLastActualRight;\r\n\tframe_matrix[Y]\t\t\t= mLastActualUp;\r\n\tframe_matrix[Z]\t\t\t= mLastActualAt;\r\n\r\n\tMth::Vector\tcurrent_at_vector( frame_matrix[Z][X], frame_matrix[Z][Y], frame_matrix[Z][Z] ); \r\n\r\n\t// Obtain skater state.\r\n\tEStateType\tstate\t\t\t= mpSkaterStateComponent->GetState();\r\n\tMth::Matrix target;\r\n\r\n\tif( state == WALL )\r\n\t{\r\n#\t\tifdef\tDEBUG_CAMERA\r\n\t\tprintf (\"SkaterCam Using mLastPreWallSkaterMatrix, as wallriding\\n\");\r\n#\t\tendif\r\n\t\ttarget\t\t\t\t\t\t= mLastPreWallSkaterMatrix;\r\n\t}\r\n\telse\r\n\t{\r\n#\t\tifdef\tDEBUG_CAMERA\r\n\t\tprintf (\"SkaterCam Using GetCameraDisplayMatrix\\n\");\r\n#\t\tendif\r\n\t\t// target\t\t\t\t\t\t= static_cast< CCompositeObject* >(mpSkater)->GetDisplayMatrix();\r\n\t\tif (mpSkater->IsLocalClient())\r\n\t\t{\r\n\t\t\ttarget\t\t\t\t\t\t= mpSkater->GetDisplayMatrix();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttarget\t\t\t\t\t\t= static_cast< CCompositeObject* >(mpSkater)->GetDisplayMatrix();\r\n\t\t}\r\n\t\tmLastPreWallSkaterMatrix\t= target;\r\n\t}\r\n\r\n\t// Lerp towards the required lean.\r\n\tfloat cam_lean = 0.0f;\r\n\tif( state == RAIL && mpSkater->IsLocalClient())\r\n\t{\t\t\r\n\t\t// Need to translate the lean value [-4096, 4096] into a reasonable camera lean angle.\r\n\t\tcam_lean = GetSkaterBalanceTrickComponentFromObject(mpSkater)->mGrind.mManualLean * SKATERCAMERACOMPONENT_LEAN_TO_SKATERCAM_LEAN;\r\n\t}\r\n\r\n\tif( cam_lean != mLean )\r\n\t{\r\n\t\tif( instantly )\r\n\t\t{\r\n\t\t\tmLean = cam_lean;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmLean += (( cam_lean - mLean ) * mGrindLerp );\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tMth::Vector skater_up;\r\n\t\t\t\t\t\r\n\tif (state != GROUND)\r\n\t{\r\n\t\tskater_up\t= target[Y];\r\n\t}\r\n\telse\r\n\t{\r\n\t\tskater_up\t= mpSkaterStateComponent->GetCameraDisplayNormal();\r\n\t}\r\n\r\n//\tGfx::AddDebugLine( p_skater->m_pos, ( target[X] * 72.0f ) + p_skater->m_pos, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 4 );\r\n//\tGfx::AddDebugLine( p_skater->m_pos, ( target[Y] * 72.0f ) + p_skater->m_pos, MAKE_RGB( 0, 128, 0 ), MAKE_RGB( 0, 128, 0 ), 4 );\r\n//\tGfx::AddDebugLine( p_skater->m_pos, ( target[Z] * 72.0f ) + p_skater->m_pos, MAKE_RGB( 0, 0, 128 ), MAKE_RGB( 0, 0, 128 ), 4 );\r\n\t\t\r\n\t// Use vel for forward facing, if moving in xz plane.\r\n\tMth::Vector vel_xz( mpSkater->GetVel().GetX(), 0.0f, mpSkater->GetVel().GetZ());\r\n\r\n\tbool use_vert_cam = UseVertCam();\r\n\t\r\n\t// use velocity if physics not paused, and if we are moving fast enough, or if we are doing vert cam\r\n\t// or if we are doing spine physics\r\n\tif(\r\n\t\t!(mpSkaterPhysicsControlComponent && mpSkaterPhysicsControlComponent->IsPhysicsSuspended()) && (vel_xz.Length() > 0.1f || use_vert_cam  || mpSkaterStateComponent->GetFlag( SPINE_PHYSICS ))\r\n\t   )\r\n\t{\r\n\t\tif( use_vert_cam )\r\n\t\t{\r\n\t\t\t// If it's vert, then set target direction to near straight down.\r\n\t\t\ttarget[Z].Set( 0.0f, -1.0f, 0.0f );\r\n\r\n\t\t\t// Zero lookaround when in vert air (and not in lookaround locked or override mode, or doing a lip trick).\r\n\t\t\tif( !mp_lookaround_component->mLookaroundLock && !mp_lookaround_component->mLookaroundOverride && ( state != LIP ))\r\n\t\t\t{\r\n\t\t\t\tmp_lookaround_component->mLookaroundTilt\t\t= 0.0f;\r\n\t\t\t\tmp_lookaround_component->mLookaroundHeading\t= 0.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttarget[Z]\t\t= mpSkater->GetVel();\r\n\t\t\t\r\n#\t\t\tif 1\t// for use with non-straight spine transfer physics\r\n\t\t\tif( mpSkaterStateComponent->GetFlag( SPINE_PHYSICS ))\r\n\t\t\t{\r\n\t\t\t\t// Just use the up velocity, plus the velocity over the spine will be straight down when coming down the other side.\r\n\t\t\t\ttarget[Z][X] = 0.0f;\r\n\t\t\t\ttarget[Z][Z] = 0.0f;\r\n\t\t\t\ttarget[Z] += mpSkaterStateComponent->GetSpineVel();\r\n\t\t\t}\r\n#\t\t\tendif\r\n\r\n\t\t\ttarget[Z].Normalize();\r\n\r\n//\t\t\tprintf (\"Using Velocity (%f, %f, %f)\\n\", target[Z][X],target[Z][Y], target[Z][Z]);\r\n\r\n//\t\t\tGfx::AddDebugLine( mpSkater->m_pos, ( target[Z] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 128, 128, 128 ), MAKE_RGB( 128, 128, 128 ), 4 );\r\n\r\n\t\t\t// Flatten out the velocity component perpendicular to the ground. However, if the skater is in the air, the\r\n\t\t\t// m_last_normal will contain the last ground normal, which we don't want, so set it to be 'up'.\r\n\t\t\tfloat\t\t\tdot;\r\n\t\t\tMth::Vector\t\tnormal;\r\n\r\n\t\t\tif( state == AIR )\r\n\t\t\t{\r\n\t\t\t\t// Patch for spine physics\r\n\t\t\t\t// only reduce component perpendicular to plane by 60%\r\n\t\t\t\t// so we still get some up/down camera movmeent \r\n\t\t\t\t// only do this when moving down though, otherwise it looks poo\r\n\t\t\t\tif (mpSkaterStateComponent->GetFlag(SPINE_PHYSICS) && target[Z][Y] < 0.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\tnormal.Set( 0.0f, 1.0f, 0.0f );\r\n\t\t\t\t\tdot =  0.7f * Mth::DotProduct(target[Z],normal);\t// change this to 0.8 to look down when coming down other side of a spine\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tnormal.Set( 0.0f, 1.0f, 0.0f );\r\n\t\t\t\t\tdot\t\t= target[Z].GetY();\r\n\t\t\t\t}\r\n\t\t\t\t// Set world up as the target vector.\r\n\t\t\t\ttarget[Y].Set( 0.0f, 1.0f, 0.0f );\r\n\t\t\t}\r\n\t\t\telse if( state == WALL )\r\n\t\t\t{\r\n\t\t\t\tnormal.Set( 0.0f, 1.0f, 0.0f );\r\n\t\t\t\tdot\t\t= target[Z].GetY();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tnormal\t= mpSkaterStateComponent->GetCameraCurrentNormal();\r\n\t\t\t\tdot =  0.8f * Mth::DotProduct(target[Z],normal);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\ttarget[Z] -= normal * dot;\r\n\t\t\ttarget[Z].Normalize();\r\n\t\t\t\r\n//\t\t\tGfx::AddDebugLine( mpSkater->m_pos, ( target[Z] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 256, 256, 256 ), MAKE_RGB( 256, 256, 256 ), 4 );\r\n\t\t}\r\n\r\n\t\t// We need to orthonormalize in a specific order, as when the velocity is going backwards, then \r\n\t\t// the X orient will be wrong, and so plonk the skater upside down.\r\n\t\ttarget[X]\t\t\t= Mth::CrossProduct( target[Y], target[Z] );\r\n\t\ttarget[X].Normalize();\r\n\t\t\r\n\t\ttarget[Y]\t\t\t= Mth::CrossProduct( target[Z], target[X] );\r\n\t\ttarget[Y].Normalize();\r\n\r\n//\t\tGfx::AddDebugLine( mpSkater->m_pos, ( target[X] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 4 );\r\n//\t\tGfx::AddDebugLine( mpSkater->m_pos, ( target[Y] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 0, 128, 0 ), MAKE_RGB( 0, 128, 0 ), 4 );\r\n//\t\tGfx::AddDebugLine( mpSkater->m_pos, ( target[Z] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 0, 0, 128 ), MAKE_RGB( 0, 0, 128 ), 4 );\r\n\t}\r\n\t\r\n\tif (mpSkater->IsLocalClient() && mpSkaterStateComponent->GetFlag(IN_ACID_DROP))\r\n\t{\r\n\t\tCSkaterCorePhysicsComponent* pSkaterPhysicsComponent = GetSkaterCorePhysicsComponentFromObject(mpSkater);\r\n\t\tDbg_Assert(pSkaterPhysicsComponent);\r\n\t\t\r\n\t\ttarget = pSkaterPhysicsComponent->m_acid_drop_camera_matrix;\r\n\t}\r\n\t\t\t\t\t\t\t\r\n\t// Tilt further if in regular air (going off a big jump, for example), or doing a lip trick.\r\n\tif( state == AIR )\r\n\t{\r\n\t\tmTiltAddition += TILT_INCREMENT * Tmr::FrameRatio();\r\n\t\tif( mTiltAddition > TILT_MAX )\r\n\t\t{\r\n\t\t\tmTiltAddition = TILT_MAX;\r\n\t\t}\t\t\t\t\r\n\t}\r\n\telse if( mTiltAddition > 0.0f )\r\n\t{\r\n\t\tmTiltAddition -= TILT_RESTORE * Tmr::FrameRatio();\r\n\t\tif( mTiltAddition < 0.0f )\r\n\t\t{\r\n\t\t\tmTiltAddition = 0.0f;\r\n\t\t}\t\t\t\t\r\n\t}\r\n\telse if( mTiltAddition < 0.0f )\r\n\t{\r\n\t\tmTiltAddition += TILT_RESTORE * Tmr::FrameRatio();\r\n\t\tif( mTiltAddition > 0.0f )\r\n\t\t{\r\n\t\t\tmTiltAddition = 0.0f;\r\n\t\t}\t\t\t\t\r\n\t}\r\n\r\n\t// PJR: Needed to do this to fix a compiler crash on NGC. Hopefully SN will\r\n\t// fix this & I can revert this hack...\r\n\ttarget.RotateYLocal( mp_lookaround_component->mLookaroundHeading + mp_lookaround_component->mLookaroundHeadingStartingPoint );\r\n\r\n\t// Now tilt the matrix down a bit.\r\n\tif( state == LIP )\r\n\t{\r\n//\t\ttarget.RotateYLocal( 0.8f );\r\n//\t\ttarget.RotateXLocal( mLipTrickTilt + mTiltAddition );\r\n\t\t_xrotlocal ( target, mLipTrickTilt + mTiltAddition );\r\n\t}\t\t\t\t\t\r\n\telse if( !(mpSkaterStateComponent->GetFlag( VERT_AIR ) && !mpSkaterStateComponent->GetFlag( CAN_BREAK_VERT )  && !mpSkaterStateComponent->GetFlag(SPINE_PHYSICS) ) /*|| !mpSkaterStateComponent->GetFlag(IN_ACID_DROP)*/)\r\n\t{\r\n//\t\ttarget.RotateXLocal( mTilt + mTiltAddition );\r\n\t\t_xrotlocal ( target, mTilt + mTiltAddition );\r\n\t}\r\n\t\r\n\t// Now adjust for 'lookaround'.\r\n//\ttarget.RotateXLocal( mLookaroundTilt );\r\n\t_xrotlocal( target, mp_lookaround_component->mLookaroundTilt );\r\n\t\r\n\tstatic float lip_rotate = 0.0f;\r\n\r\n\tif( state == LIP )\r\n\t{\r\n\t\tlip_rotate = Mth::PI / 2.0f;\r\n\r\n\t\tif( mLipSideDecided == 0 )\r\n\t\t{\r\n\t\t\ttarget.RotateY( lip_rotate );\r\n\r\n\t\t\t// Do collision check.\r\n\t\t\tCFeeler feeler;\r\n\r\n\t\t\tMth::Vector horiz_z( target[Z][X], 0.0f, target[Z][Z] );\r\n\t\t\thoriz_z.Normalize();\r\n\t\t\tMth::Vector a = mpSkater->m_pos - ( target[Z] * 3.0f );\r\n\t\t\tMth::Vector b = a - ( horiz_z * 72.0f );\r\n\r\n\t\t\tfeeler.SetIgnore(IGNORE_FACE_FLAGS_1, IGNORE_FACE_FLAGS_0);\r\n\t\t\tbool collision = feeler.GetCollision(a, b, true);\r\n\t\t\tif( !collision )\r\n\t\t\t{\r\n\t\t\t\t// Side 1 is fine.\r\n\t\t\t\tmLipSideDecided = 1;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfloat dist = feeler.GetDist();\r\n\t\t\t\ttarget.RotateY( -lip_rotate * 2.0f );\r\n\t\t\t\thoriz_z.Set( target[Z][X], 0.0f, target[Z][Z] );\r\n\t\t\t\thoriz_z.Normalize();\r\n\t\t\t\ta = mpSkater->m_pos - ( target[Z] * 3.0f );\r\n\t\t\t\tb = a - ( horiz_z * 72.0f );\r\n\r\n\t\t\t\tcollision = feeler.GetCollision(a, b, true);\r\n\t\t\t\tif( !collision )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Side 2 is fine.\r\n\t\t\t\t\tmLipSideDecided = 2;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif( feeler.GetDist() < dist )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Side 2 is better than side 1.\r\n\t\t\t\t\t\tmLipSideDecided = 2;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Side 1 is better than side 2.\r\n\t\t\t\t\t\ttarget.RotateY( lip_rotate * 2.0f );\r\n\t\t\t\t\t\tmLipSideDecided = 1;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif( mLipSideDecided == 1 )\r\n\t\t\t{\r\n\t\t\t\ttarget.RotateY( lip_rotate );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ttarget.RotateY( -lip_rotate );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmLipSideDecided = 0;\r\n\t}\t\t\t\t\t\r\n\r\n\t// Set skater flag to indicate when the liptrick camera has spun to the opposite side.\r\n\tif( mpSkater && ( mLipSideDecided == 2 ))\r\n\t{\r\n\t\tmpSkater->mScriptFlags |= ( 1 << Script::GetInteger( 0x16b8e4cb /* \"FLAG_SKATER_LIPTRICK_CAM_REVERSED\" */ ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmpSkater->mScriptFlags &= ~( 1 << Script::GetInteger( 0x16b8e4cb /* \"FLAG_SKATER_LIPTRICK_CAM_REVERSED\" */ ));\r\n\t}\r\n\t\r\n//\tGfx::AddDebugLine( mpSkater->m_pos, ( target[X] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 4 );\r\n//\tGfx::AddDebugLine( mpSkater->m_pos, ( target[Y] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 0, 128, 0 ), MAKE_RGB( 0, 128, 0 ), 4 );\r\n//\tGfx::AddDebugLine( mpSkater->m_pos, ( target[Z] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 0, 0, 128 ), MAKE_RGB( 0, 0, 128 ), 4 );\r\n\t\r\n\t// Why doing this, when setting below?\r\n\tMth::Matrix t_matrix(0.0f, 0.0f, 0.0f);\r\n\t\r\n\t// Since camera points in -Z, but player in +Z, we must negate the X and Z axes\r\n\tt_matrix[X][X]\t\t= -target[0][0];\r\n\tt_matrix[X][Y]\t\t= -target[0][1];\r\n\tt_matrix[X][Z]\t\t= -target[0][2];\r\n\tt_matrix[X][W]\t\t= 0.0f;\r\n\t\r\n\tt_matrix[Y][X]\t\t= target[1][0];\r\n\tt_matrix[Y][Y]\t\t= target[1][1];\r\n\tt_matrix[Y][Z]\t\t= target[1][2];\r\n\tt_matrix[Y][W]\t\t= 0.0f;\r\n\t\r\n\tt_matrix[Z][X]\t\t= -target[2][0];\r\n\tt_matrix[Z][Y]\t\t= -target[2][1];\r\n\tt_matrix[Z][Z]\t\t= -target[2][2];\r\n\tt_matrix[Z][W]\t\t= 0.0f;\r\n\t\t\t\r\n\tt_matrix[W][X]\t\t= 0.0f;\r\n\tt_matrix[W][Y]\t\t= 0.0f;\r\n\tt_matrix[W][Z]\t\t= 0.0f;\r\n\tt_matrix[W][W]\t\t= 1.0f;\r\n        \r\n\tframe_matrix[W][X]\t= 0.0f;\r\n\tframe_matrix[W][Y]\t= 0.0f;\r\n\tframe_matrix[W][Z]\t= 0.0f;\r\n\tframe_matrix[W][W]\t= 1.0f;\r\n\r\n\t// if we want an instant update, then just move it\r\n\tif (instantly)\r\n\t{\r\n\t\tframe_matrix = t_matrix;\r\n\t}\r\n\r\n\tfloat dotx = Mth::DotProduct( t_matrix[X], frame_matrix[X] );\r\n\tfloat doty = Mth::DotProduct( t_matrix[Y], frame_matrix[Y] );\r\n\tfloat dotz = Mth::DotProduct( t_matrix[Z], frame_matrix[Z] );\r\n\r\n\tif( dotx > CAMERA_SLERP_STOP && doty > CAMERA_SLERP_STOP && dotz > CAMERA_SLERP_STOP )\r\n\t{\r\n\t\t// Do nothing, camera has reached the target so we just leave the frame matrix exactly where it is.\r\n//\t    frame_matrix = t_matrix;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Initialise the SLERP interpolator, with the current matrix as the start, and the ideal\r\n\t\t// matrix as the end (target).\r\n\r\n\t\t// GARY:  is this right?  i assume p_matrix = &t_matrix\r\n\t\tmpSlerp->setMatrices( &frame_matrix, &t_matrix );\r\n\r\n\t\t// Copy flags and shit (why copying all this when most of the values will be overwritten?)\r\n\t\tMth::Matrix stored_frame;\r\n\t\tstored_frame = frame_matrix;\r\n\t\tframe_matrix = t_matrix;\t\t\t\r\n\r\n\t\t// Continue to slerp towards the target, updating frame_matrix with the slerped values.\r\n\t\tif( !(mpSkaterStateComponent->GetFlag( VERT_AIR ) && !mpSkaterStateComponent->GetFlag( CAN_BREAK_VERT ) && !mpSkaterStateComponent->GetFlag(SPINE_PHYSICS)))\r\n\t\t{\r\n\t\t\t// If the skater has just landed from big air, use the big air land slerp value.\r\n\t\t\tif(( mpSkaterStateComponent->GetState() == GROUND ) && ( mVertAirLandedTimer >= delta_time ))\r\n\t\t\t{\r\n\t\t\t\tmVertAirLandedTimer -= delta_time;\r\n\t\t\t\tmpSlerp->getMatrix( &frame_matrix, GetTimeAdjustedSlerp( mVertAirLandedSlerp, delta_time ));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Clear the vert air landed timer.\r\n\t\t\t\tmVertAirLandedTimer = 0.0f;\r\n\t\t\t\t\r\n\t\t\t\tmpSlerp->getMatrix( &frame_matrix, GetTimeAdjustedSlerp( mSlerp, delta_time ));\r\n\r\n\t\t\t\t// At this point we can check to see the angle that the camera's 'at' vector moved through this frame.\r\n\t\t\t\t// If this angle is too large, we need to limit it, regardless of the slerp. (This is primarily to avoid\r\n\t\t\t\t// the nasty jerk when transitioning rails etc.\r\n\t\t\t\tfloat this_dot = ( current_at_vector.GetX() * frame_matrix[Mth::AT][X] ) \r\n                       + ( current_at_vector.GetY() * frame_matrix[Mth::AT][Y] ) \r\n                       + ( current_at_vector.GetZ() * frame_matrix[Mth::AT][Z] ); \r\n\r\n\t\t\t\t// Dot values will be in the range [0,1], with 1 being no change.\r\n\t\t\t\tif( this_dot < ( mLastDot * 0.9998f ))\r\n\t\t\t\t{\r\n\t\t\t\t\t// The angular change this frame is too big. Need to recalculate with an adjusted slerp value.\r\n\t\t\t\t\tfloat new_slerp = mSlerp * ( this_dot / ( mLastDot * 0.9998f ));\r\n\t\t\t\t\tmpSlerp->setMatrices( &stored_frame, &t_matrix );\r\n\t\t\t\t\tmpSlerp->getMatrix( &frame_matrix, GetTimeAdjustedSlerp( new_slerp, delta_time ));\r\n\r\n\t\t\t\t\tthis_dot = mLastDot * 0.9998f;\r\n\t\t\t\t}\r\n\t\t\t\tmLastDot = this_dot;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmpSlerp->getMatrix( &frame_matrix, GetTimeAdjustedSlerp( mVertAirSlerp, delta_time ));\r\n\r\n\t\t\t// Set the vert air landed timer to the max, since the skater is in vert air.\r\n\t\t\tmVertAirLandedTimer = VERT_AIR_LANDED_TIME;\r\n\t\t}\t\t\t\t\t\t\r\n\t}\t\t\r\n\r\n\t// Mick:  This is a patch to allow the walk camera to override the updating of the camera frame\t\r\n\t// At this point, frame_matrix is valid to store.\r\n\tmLastActualRight\t= frame_matrix[X];\r\n\tmLastActualUp\t\t= frame_matrix[Y];\r\n\tmLastActualAt\t\t= frame_matrix[Z];\r\n\t\r\n\t// Set camera position to be the same as the skater.\r\n\tMth::Vector\tcam_pos = GetTripodPos( instantly );\r\n\t\r\n\t// If in the air doing a trick, we slowly reduce the behind value to 'zoom' in on the skater.\r\n\tfloat above, behind;\r\n\tif( instantly )\r\n\t{\r\n\t\tfloat temp = mZoomLerp;\r\n\t\tmZoomLerp = 1.0f;\t\t\t\t\t// fully lerp instantly\r\n\t\tCalculateZoom( &above, &behind );\r\n\t\tmZoomLerp = temp;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCalculateZoom( &above, &behind );\r\n\t}\r\n\t\r\n\t// Note we use the camera's at vector, as this will keep the skater in the middle of the frame.\r\n\t//cam_pos -= frame_matrix[Z] * behind;\r\n\tcam_pos += frame_matrix[Z] * behind;\r\n\t\t\r\n\t// Move camera along the Skater's up vector.\r\n\tcam_pos += skater_up * above;\r\n\t\r\n\tMth::Vector\tactual_focus_pos = mpSkater->m_pos + ( skater_up * above );\r\n\t\r\n//\tGfx::AddDebugLine( mpSkater->m_pos, actual_focus_pos, MAKE_RGB( 0, 0, 128 ), MAKE_RGB( 0, 0, 128 ), 4 );\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n//\tDbg_Message(\"Matrix Z  (%5.4f,%5.4f,%5.4f)\", frame_matrix[Z][X], frame_matrix[Z][Y], frame_matrix[Z][Z]);\r\n//\tDbg_Message(\"Matrix UP (%5.4f,%5.4f,%5.4f)\", skater_up[X], skater_up[Y], skater_up[Z]);\r\n//\tDbg_Message(\"Above %f Behind %f\", above, behind);\r\n//\tDbg_Message(\"focus pos (%5.1f,%5.1f,%5.1f)\", actual_focus_pos[X], actual_focus_pos[Y], actual_focus_pos[Z]);\r\n//\tDbg_Message(\"Camera after: pos (%5.1f,%5.1f,%5.1f)\", cam_pos[X], cam_pos[Y], cam_pos[Z]);\r\n\r\n\t// Reorient the camera to look directly at the skater. We don't want to look at the interpolated position,\r\n\t// since this can lead to nasty jerkiness, especially on rails etc.\r\n\ttarget[Z].Set( actual_focus_pos.GetX() - cam_pos.GetX(), actual_focus_pos.GetY() - cam_pos.GetY(), actual_focus_pos.GetZ() - cam_pos.GetZ());\r\n\ttarget[Z].Normalize();\r\n\r\n\t// Read back the Y from the current matrix.\r\n\ttarget[Y][0]\t= frame_matrix[Y][X];\r\n\ttarget[Y][1]\t= frame_matrix[Y][Y];\r\n\ttarget[Y][2]\t= frame_matrix[Y][Z];\r\n\r\n\t// Generate new orthonormal X and Y axes.\r\n\ttarget[X]\t\t= Mth::CrossProduct( target[Y], target[Z] );\r\n\ttarget[X].Normalize();\r\n\ttarget[Y]\t\t= Mth::CrossProduct( target[Z], target[X] );\r\n\ttarget[Y].Normalize();\r\n\r\n\t// Here is where lean may safely be applied without moving the focus position on screen.\r\n\tif( mLean != 0.0f )\r\n\t{\r\n\t\ttarget[Y].Rotate( target[Z], mLean );\r\n\t\ttarget[X].Rotate( target[Z], mLean );\r\n\t}\r\n\t\r\n\t// Write back into camera matrix.\r\n\t// Since camera points in -Z, but player in +Z, we must negate the X and Z axes\r\n\tframe_matrix[X][X]\t\t= -target[0][0];\r\n\tframe_matrix[X][Y]\t\t= -target[0][1];\r\n\tframe_matrix[X][Z]\t\t= -target[0][2];\r\n\tframe_matrix[X][W]\t\t= 0.0f;\r\n\r\n\tframe_matrix[Y][X]\t\t= target[1][0];\r\n\tframe_matrix[Y][Y]\t\t= target[1][1];\r\n\tframe_matrix[Y][Z]\t\t= target[1][2];\r\n\tframe_matrix[Y][W]\t\t= 0.0f;\r\n\r\n\tframe_matrix[Z][X]\t\t= -target[2][0];\r\n\tframe_matrix[Z][Y]\t\t= -target[2][1];\r\n\tframe_matrix[Z][Z]\t\t= -target[2][2];\r\n\tframe_matrix[Z][W]\t\t= 0.0f;\r\n\r\n\t// Update the position if there is a shake active.\r\n\tif(\tmShakeDuration > 0.0f )\r\n\t{\r\n\t\taddShake( cam_pos, frame_matrix );\r\n\t}\r\n\t\t\r\n\t// Now do collision detection.\r\n\t\r\n\tbool no_camera_collision;\r\n\tif (mpSkater->IsLocalClient())\r\n\t{\r\n\t\tCSkaterCorePhysicsComponent* pSkaterPhysicsComponent = GetSkaterCorePhysicsComponentFromObject(mpSkater);\r\n\t\tDbg_Assert(pSkaterPhysicsComponent);\r\n\t\t\r\n\t\tno_camera_collision = pSkaterPhysicsComponent->mp_movable_contact_component->GetContact() && state == LIP;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tno_camera_collision = false;\r\n\t}\r\n\t\r\n\tif (no_camera_collision)\r\n\t{\r\n\t\t// no camera collision if doing a lip trick on a moving object\r\n\t\t//printf (\"Lip trick on moving object\\n\");\r\n\t}\r\n\telse\r\n\t{\r\n\t\tApplyCameraCollisionDetection(cam_pos, frame_matrix, cam_pos - ((Mth::Vector)( frame_matrix[Z] )) * behind, actual_focus_pos);\r\n\t}\r\n\t\r\n\tcam_pos[W] = 1.0f;\r\n//\tGfx::Camera::SetPos( cam_pos );\r\n\tp_cam_comp->SetPosition( cam_pos );\r\n\t\r\n\t// reset old position if in instant update\r\n\tif (instantly)\r\n\t{\r\n\t\tp_cam_comp->StoreOldPosition();\r\n\t}\r\n\t\r\n//\tDbg_Message(\"Camera Final: pos (%5.1f,%5.1f,%5.1f)\", cam_pos[X], cam_pos[Y], cam_pos[Z]);\r\n\r\n\t// Store the position of the camera in CSkaterCam also (used for proximity nodes).\r\n\r\n\t// Dave - there is no m_pos anymore...\r\n//\tm_pos = cam_pos;\r\n\r\n\t// Dave - this used to return the value below when it was CSkaterCam::Update()\r\n//\tMth::Vector\tto_target = at_pos - cam_pos;\r\n//\treturn to_target.Length();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterCameraComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | SC_ShakeCamera | shake the skater camera\r\n        // @parm float | duration | duration of the shake (0 clears the shake)\r\n        // @parm float | vert_amp | maximum vertical amplidtude of the shake\r\n        // @parm float | horiz_amp | maximum horizontal amplidtude of the shake\r\n        // @parm float | vert_vel | vertical velocity factor (how many full cycles of movement in 1 second) \r\n        // @parm float | horiz_vel | horizontal velocity factor (how many full cycles of movement in 1 second) \r\n\t\tcase CRCC(0x75a516d3,\"SC_ShakeCamera\"):\r\n\t\t{\r\n\t\t\tfloat duration\t= 0.0f;\r\n\t\t\tfloat vert_amp\t= 0.0f;\r\n\t\t\tfloat horiz_amp\t= 0.0f;\r\n\t\t\tfloat vert_vel\t= 0.0f;\r\n\t\t\tfloat horiz_vel\t= 0.0f;\r\n\r\n\t\t\tpParams->GetFloat( \"duration\",\t&duration );\r\n\t\t\tpParams->GetFloat( \"vert_amp\",\t&vert_amp );\r\n\t\t\tpParams->GetFloat( \"horiz_amp\",\t&horiz_amp );\r\n\t\t\tpParams->GetFloat( \"vert_vel\",\t&vert_vel );\r\n\t\t\tpParams->GetFloat( \"horiz_vel\",\t&horiz_vel );\r\n\r\n\t\t\tSetShake( duration, vert_amp, horiz_amp, vert_vel, horiz_vel );\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t\t\t \r\n\t\t// @script | SC_SetMode | Set the mode of a skater camera\r\n        // @parm integer | mode | mode number 1-4, start out at 2 (normal_medium)\r\n\t\tcase CRCC(0xd7867ffe,\"SC_SetMode\"):\r\n\t\t{\r\n\t\t\r\n\t\t\tint mode = 0;\r\n\t\t\tpParams->GetInteger(CRCD(0x6835b854,\"mode\"),&mode, true);\r\n\t\t\tSetMode((ESkaterCamMode)mode);\t   \r\n\t\t\tbreak; \t\r\n\t\t}\r\n\r\n\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCameraComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterCameraComponent::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\t/*\tExample:\r\n\tp_info->AddInteger(\"m_never_suspend\",m_never_suspend);\r\n\tp_info->AddFloat(\"m_suspend_distance\",m_suspend_distance);\r\n\t*/\r\n\t\r\n\t// We call the base component's GetDebugInfo, so we can add info from the common base component.\r\n\tCBaseComponent::GetDebugInfo( p_info );\r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCameraComponent::ResetLookAround( void )\r\n{\r\n\tmp_lookaround_component->mLookaroundTilt\t\t= 0.0f;\r\n\tmp_lookaround_component->mLookaroundHeading\t= 0.0f;\r\n\tSetNoLerpUpdate( true );\r\n\tUpdate();\r\n\tCommit();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCameraComponent::ResetMode( )\r\n{\r\n\t// Just call SetMode() again with the current mode\r\n\tSetMode(mMode);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCameraComponent::SetMode( ESkaterCamMode mode, float time )\r\n{\r\n\t// We need a CCameraComponent attached in order to set camera details.\r\n\tCCameraComponent *p_cam_comp = GetCameraComponentFromObject(GetObject());\r\n\tDbg_MsgAssert( p_cam_comp, ( \"CSkaterCameraComponent needs CCameraComponent attached to parent\" ));\r\n\r\n\tDbg_MsgAssert( mode < SKATERCAM_NUM_MODES,( \"Bad mode\" ));\r\n\r\n\t// Obtain details for this mode.\r\n\tfloat h_fov, behind, above, tilt, origin_offset, zoom_lerp;\r\n\tconst char* p_name;\r\n\r\n\t// Obtain a pointer to the array entry for the desired mode. The array is now dependent\r\n\t// on which game mode is currently being played, 1 player, 2 player vert, or 2 player horiz.\r\n\tNx::ScreenMode screen_mode = Nx::CViewportManager::sGetScreenMode();\r\n\r\n\tScript::CArray* p_array;\r\n\r\n\tswitch( screen_mode )\r\n\t{\r\n\t\tcase Nx::vSPLIT_V:\r\n\t\t{\r\n\t\t\tp_array = Script::GetArray( \"Skater_Camera_2P_Vert_Array\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase Nx::vSPLIT_H:\r\n\t\t{\r\n\t\t\tp_array = Script::GetArray( \"Skater_Camera_2P_Horiz_Array\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t{\t\t\t\r\n\t\t\tp_array = Script::GetArray( \"Skater_Camera_Array\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t// Extra check here, since the array in physics.q may change.\r\n\tDbg_MsgAssert( mode < (int)p_array->GetSize(), ( \"Bad mode\" ));\r\n\r\n\tuint32 cs = p_array->GetNameChecksum( mode );\r\n\tScript::CScriptStructure* p_struct = Script::GetStructure( cs );\r\n\r\n\tmMode = mode;\r\n\r\n\tmLipTrickTilt = 0.0f;\r\n\r\n\t// Read the values from the array.\r\n\tp_struct->GetFloat( CRCD(0x94df1603,\"horiz_fov\"),\t\t\t\t&h_fov );\r\n\tp_struct->GetFloat( CRCD(0x52e6c41b,\"behind\"),\t\t\t\t\t&behind );\r\n\tp_struct->GetFloat( CRCD(0xb96ae2d,\"above\"),\t\t\t\t\t&above );\r\n\tp_struct->GetFloat( CRCD(0xe3c07609,\"tilt\"),\t\t\t\t\t\t&tilt );\r\n\tp_struct->GetFloat( CRCD(0x12f6992,\"origin_offset\"),\t\t\t&origin_offset );\r\n\tp_struct->GetFloat( CRCD(0x7f0032ac,\"lip_trick_tilt\"),\t\t\t&mLipTrickTilt );\r\n\tp_struct->GetFloat( CRCD(0xadb6390e,\"lip_trick_above\"),\t\t\t&mLipTrickAbove );\r\n\r\n\t// Get SLERP values.\r\n\tp_struct->GetFloat( CRCD(0xf54fb9c5,\"slerp\"),\t\t\t\t\t&mSlerp );\r\n\tp_struct->GetFloat( CRCD(0x2fa11029,\"vert_air_slerp\"),\t\t\t&mVertAirSlerp );\r\n\tp_struct->GetFloat( CRCD(0x42fd4a0,\"vert_air_landed_slerp\"),\t&mVertAirLandedSlerp );\r\n\r\n\t// Get LERP values.\r\n\tp_struct->GetFloat( CRCD(0xae47899b,\"lerp_xz\"),\t\t\t\t\t&mLerpXZ );\r\n\tp_struct->GetFloat( CRCD(0xe1e4e104,\"lerp_y\"),\t\t\t\t\t&mLerpY );\r\n\tp_struct->GetFloat( CRCD(0xf386f4d9,\"vert_air_lerp_xz\"),\t\t\t&mVertAirLerpXZ );\r\n\tp_struct->GetFloat( CRCD(0x4882a1fe,\"vert_air_lerp_y\"),\t\t\t&mVertAirLerpY );\r\n\tp_struct->GetFloat( CRCD(0xbef0d195,\"grind_lerp\"),\t\t\t\t&mGrindLerp );\r\n\r\n\t// Get zoom values.\r\n\tmGrindZoom\t\t\t= 1.0f;\r\n\tmLipTrickZoom\t\t= 1.0f;\r\n\tmBigAirTrickZoom\t= 1.0f;\r\n\r\n\tp_struct->GetFloat( CRCD(0x748743a7,\"zoom_lerp\"),\t\t\t&zoom_lerp );\r\n\tp_struct->GetFloat( CRCD(0x5a7f5cc5,\"grind_zoom\"),\t\t\t&mGrindZoom );\r\n\tp_struct->GetFloat( CRCD(0xd790b83d,\"big_air_trick_zoom\"),\t&mBigAirTrickZoom );\r\n\tp_struct->GetFloat( CRCD(0xd414c22e,\"lip_trick_zoom\"),\t\t&mLipTrickZoom );\r\n\tmZoomLerp\t\t\t= zoom_lerp;\r\n\r\n\t// Get camera style name.\r\n\tp_struct->GetText( CRCD(0xa1dc81f9,\"name\"), &p_name );\r\n\r\n\t// Send the new camera mode to console line 1.\r\n\t//HUD::PanelMgr* panelMgr = HUD::PanelMgr::Instance();\r\n\t//panelMgr->SendConsoleMessage( p_name, 1 );\r\n\r\n\t// Need to calculate interpolate timers here.\r\n\tmHorizFOV\t\t= h_fov;\r\n\tmTilt\t\t\t= tilt;\r\n\tmOriginOffset\t= FEET( origin_offset );\t\t// Convert to inches.\r\n\r\n\t// Set up interpolators for those values that require it.\r\n\tif( time > 0.0f )\r\n\t{\r\n\t\tbehind\t\t\t\t\t\t= FEET( behind );\t\t\t\t// Convert to inches.\r\n\t\tabove\t\t\t\t\t\t= FEET( above );\t\t\t\t// Convert to inches.\r\n\t\tmBehindInterpolatorTime\t\t= time;\r\n\t\tmBehindInterpolatorDelta\t= (( behind - mBehind ) * ( SKATERCAMERACOMPONENT_INTERPOLATOR_TIMESTEP\t/ time ));\r\n\t\tmAboveInterpolatorTime\t\t= time;\r\n\t\tmAboveInterpolatorDelta\t\t= (( above - mAbove ) * ( SKATERCAMERACOMPONENT_INTERPOLATOR_TIMESTEP / time ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmBehind\t\t\t\t\t\t= FEET( behind );\r\n\t\tmAbove\t\t\t\t\t\t= FEET( above );\r\n\t\tmBehindInterpolatorTime\t\t= 0.0f;\r\n\t\tmAboveInterpolatorTime\t\t= 0.0f;\r\n\t}\r\n\t\r\n\t// Set focal length immediately.\r\n\tswitch( screen_mode )\r\n\t{\r\n\t\tcase Nx::vSPLIT_V:\r\n\t\t{\r\n#\t\t\tifdef __PLAT_NGC__\r\n\t\t\tp_cam_comp->SetHFOV( Script::GetFloat( \"Skater_Cam_Horiz_FOV\" ) / 2.0f );\r\n#\t\t\telse\r\n\t\t\tp_cam_comp->SetHFOV( mHorizFOV / 2.0f );\r\n#\t\t\tendif\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase Nx::vSPLIT_H:\r\n\t\t{\r\n\t\t\tp_cam_comp->SetHFOV( mHorizFOV );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t{\t\t\t\r\n\t\t\tp_cam_comp->SetHFOV( mHorizFOV );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tswitch( mode )\r\n\t{\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_FRONT ):\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_FRONT_ZOOM ):\r\n\t\t\tmp_lookaround_component->mLookaroundHeadingStartingPoint = Mth::PI;\r\n\t\t\tbreak;\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_LEFT ):\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_LEFT_ZOOM ):\r\n\t\t\tmp_lookaround_component->mLookaroundHeadingStartingPoint = Mth::PI / 2.0f;\r\n\t\t\tbreak;\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_BEHIND ):\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_BEHIND_ZOOM ):\r\n\t\t\tmp_lookaround_component->mLookaroundHeadingStartingPoint = 0;\r\n\t\t\tbreak;\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_RIGHT ):\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_RIGHT_ZOOM ):\r\n\t\t\tmp_lookaround_component->mLookaroundHeadingStartingPoint = -( Mth::PI / 2.0f );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tmp_lookaround_component->mLookaroundHeadingStartingPoint = 0;\r\n\t\t\tbreak;\r\n\t}   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCameraComponent::ToggleMode()\r\n{\r\n\tif ( mMode >= SKATERCAM_NUM_NORMAL_MODES )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tmMode = (ESkaterCamMode)( mMode + 1);\r\n\tif( mMode >= SKATERCAM_NUM_NORMAL_MODES )\r\n\t{\r\n\t\tmMode = SKATERCAM_MODE_FIRST_VALID;\r\n\t}\r\n\r\n\tResetMode();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCameraComponent::SetShake( float duration, float vert_amp, float horiz_amp, float vert_vel, float horiz_vel )\r\n{\r\n\tmShakeDuration\t\t\t= duration;\r\n\tmShakeInitialDuration\t= duration;\r\n\tmShakeMaxVertAmp\t\t= vert_amp;\r\n\tmShakeMaxHorizAmp\t\t= horiz_amp;\r\n\tmShakeVertVel\t\t\t= vert_vel;\r\n\tmShakeHorizVel\t\t\t= horiz_vel;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CSkaterCameraComponent::UseVertCam( void )\r\n{   \r\n\tif( mpSkater == NULL )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// this logic is used only by cameras observing non-local clients; in all other cases, skating camera logic in suspended when viewing a walking\r\n\t// skater; when observing, skater camera logic is always used; this prevents the \"birds-eye-view\" issue when observing a skater who transitioned to\r\n\t// walking during vert air\r\n\tif( mpSkaterStateComponent->GetPhysicsState() == WALKING )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// Use vert cam when in the lip state.\r\n\tif( mpSkaterStateComponent->GetState() == LIP )\r\n\t{\r\n#\t\tifdef DEBUG_CAMERA\r\n\t\tprintf (\"SkaterCam Using Vert Cam as LIP\\n\");\r\n#\t\tendif\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tif( mpSkaterStateComponent->GetFlag( VERT_AIR ) && !mpSkaterStateComponent->GetFlag( CAN_BREAK_VERT )  && !mpSkaterStateComponent->GetFlag(SPINE_PHYSICS))\r\n\t{\r\n#\t\tifdef DEBUG_CAMERA\r\n\t\tprintf (\"SkaterCam Using Vert Cam as VERT_AIR\\n\");\r\n#\t\tendif\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tif( mpSkaterStateComponent->GetJumpedOutOfLipTrick())\r\n\t{\r\n#\t\tifdef DEBUG_CAMERA\r\n\t\tprintf (\"SkaterCam Using Vert Cam as Jumped out of lip trick\\n\");\r\n#\t\tendif\r\n\t\treturn true;\r\n\t}\r\n\r\n#\tifdef DEBUG_CAMERA\r\n\tprintf (\"Skatecam NOT using vert cam\\n\");\r\n#\tendif\r\n\r\n\treturn false;\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCameraComponent::addShake( Mth::Vector& cam, Mth::Matrix& frame )\r\n{\r\n\tfloat damping\t\t= mShakeDuration / mShakeInitialDuration;\r\n\tfloat vert_angle\t= mShakeDuration * mShakeVertVel * Mth::PI * 2.0f;\r\n\tfloat horiz_angle\t= mShakeDuration * mShakeHorizVel * Mth::PI * 2.0f;\r\n\tfloat vert_offset\t= mShakeMaxVertAmp * sinf( vert_angle ) * damping;\r\n\tfloat horiz_offset\t= mShakeMaxHorizAmp * sinf( horiz_angle ) * damping;\r\n\r\n\tcam += frame[X] * horiz_offset;\r\n\tcam += frame[Y] * vert_offset;\r\n\r\n\tmShakeDuration\t\t-= Tmr::FrameLength();\r\n\tif( mShakeDuration < 0.0f )\r\n\t\tmShakeDuration = 0.0f;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CSkaterCameraComponent::GetTripodPos( bool instantly )\r\n{\r\n\tfloat\t\tlerp_xz;\r\n\tfloat\t\tlerp_y;\r\n\tfloat\t\tdelta\t\t= Tmr::FrameLength();\r\n\r\n\tif( mpSkater == NULL )\r\n\t{\r\n\t\treturn Mth::Vector( 0.0f, 0.0f, 0.0f );\r\n\t}\r\n\r\n\tMth::Vector now\t\t\t= mpSkater->m_pos;\r\n\r\n\t// The tripod pos is always *tending* towards the skater position, but the rate at which it does so is\r\n\t// definable, to allow for some lag, which improves the feeling of speed.\r\n\tif( mLerpReductionTimer > 0.0f )\r\n\t{\r\n\t\tmLerpReductionTimer -= delta;\r\n\t\tif( mLerpReductionTimer > 0.0f )\r\n\t\t{\r\n\t\t\tmLerpReductionMult += ( mLerpReductionDelta * delta );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmLerpReductionMult\t= 1.0f;\r\n\t\t\tmLerpReductionTimer\t= 0.0f;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmLerpReductionMult\t= 1.0f;\r\n\t}\r\n\r\n\tDbg_Assert( mpSkaterStateComponent );\r\n\tif(( mpSkaterStateComponent->GetFlag( VERT_AIR ) && !mpSkaterStateComponent->GetFlag( CAN_BREAK_VERT ) && !mpSkaterStateComponent->GetFlag( SPINE_PHYSICS )))\r\n\t{\r\n\t\t#ifdef\tDEBUG_CAMERA\r\n\t\tprintf (\"Skatercam using mVertAirLerp\\n\");\r\n\t\t#endif\r\n\r\n\t\tlerp_xz\t= GetTimeAdjustedSlerp( mVertAirLerpXZ * mLerpReductionMult, delta );\r\n\t\tlerp_y\t= GetTimeAdjustedSlerp( mVertAirLerpY * mLerpReductionMult, delta );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tlerp_xz\t= GetTimeAdjustedSlerp( mLerpXZ * mLerpReductionMult, delta );\r\n\t\tlerp_y\t= GetTimeAdjustedSlerp( mLerpY * mLerpReductionMult, delta );\r\n\r\n\t\t// Added the following check (Dave 7/16/02) to help eliminate the camera rattle when snapping on/off a curb.\r\n\t\t// The flag is set for one frame only.\r\n\t\tif( mpSkaterStateComponent->GetFlag( SNAPPED_OVER_CURB ))\r\n\t\t{\r\n\t\t\tlerp_y = 1.0f;\r\n\t\t}\r\n\t\t\r\n\t\tif( mpSkaterStateComponent->GetFlag( SNAPPED ))\r\n\t\t{\r\n\t\t\tinstantly = true;\r\n\t\t}\r\n\t}\r\n\r\n\tif( instantly )\r\n\t{\r\n\t\tmLastTripodPos = now;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmLastTripodPos.Set( mLastTripodPos.GetX() + (( now.GetX() - mLastTripodPos.GetX() ) * lerp_xz ),\r\n\t\t\t\t\t\t\tmLastTripodPos.GetY() + (( now.GetY() - mLastTripodPos.GetY() ) * lerp_y ),\r\n\t\t\t\t\t\t\tmLastTripodPos.GetZ() + (( now.GetZ() - mLastTripodPos.GetZ() ) * lerp_xz ));\r\n\t}\r\n\r\n\treturn mLastTripodPos;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCameraComponent::CalculateZoom( float* p_above, float* p_behind )\r\n{\r\n\tif( mpSkater == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tmTargetZoom = 1.0f;\r\n\r\n\t// Deal with zoom for Big Air. Set the flag only when a trick is started.\r\n\tif( !mBigAirTrickZoomActive && ( mpSkaterStateComponent->GetFlag( VERT_AIR ) && !mpSkaterStateComponent->GetFlag( CAN_BREAK_VERT ) && !mpSkaterStateComponent->GetFlag(SPINE_PHYSICS)) && mpSkaterStateComponent->DoingTrick() )\r\n\t{\r\n\t\tmBigAirTrickZoomActive = true;\r\n\t}\r\n\telse if( !( mpSkaterStateComponent->GetFlag( VERT_AIR ) && !mpSkaterStateComponent->GetFlag( CAN_BREAK_VERT ) && !mpSkaterStateComponent->GetFlag( SPINE_PHYSICS )))\r\n\t{\r\n\t\t// Must have landed.\r\n\t\tmBigAirTrickZoomActive = false;\r\n\t}\r\n\r\n\tif( mBigAirTrickZoomActive )\r\n\t{\r\n\t\tmTargetZoom = mBigAirTrickZoom;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tEStateType state = mpSkaterStateComponent->GetState();\r\n\r\n\t\t// If the skater is grinding, zoom also.\r\n\t\tif( state == RAIL )\r\n\t\t{\r\n\t\t\tmTargetZoom = mGrindZoom;\r\n\t\t}\r\n\t\telse if( state == LIP )\r\n\t\t{\r\n\t\t\tmTargetZoom = mLipTrickZoom;\r\n\t\t}\r\n\t\telse if( state == LIP )\r\n\t\t{\r\n\t\t\tmTargetZoom = mLipTrickZoom;\r\n\t\t}\r\n\t}\r\n\r\n\t\r\n\t#if 0\r\n\t// If lookaround override is set, factor in the lookaround override zoom.\r\n\tif( mp_lookaround_component->mLookaroundOverride && ( mp_lookaround_component->mLookaroundZoom != 1.0f ))\r\n\t{\r\n\t\tmCurrentZoom = mTargetZoom;\r\n\t\tmCurrentZoom *= mp_lookaround_component->mLookaroundZoom;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmCurrentZoom += (( mTargetZoom - mCurrentZoom ) * mZoomLerp );\r\n\t}\r\n\t#else\r\n\t// If lookaround override is set, factor in the lookaround override zoom.\r\n\tif( mp_lookaround_component->mLookaroundOverride && ( mp_lookaround_component->mLookaroundZoom != 1.0f ))\r\n\t{\r\n\t\tmTargetZoom *= mp_lookaround_component->mLookaroundZoom;\r\n\t}\r\n\t\r\n\tmCurrentZoom += (( mTargetZoom - mCurrentZoom ) * mZoomLerp );\r\n\t#endif\r\n\t\r\n\t*p_behind = mBehind * mCurrentZoom;\r\n\r\n\t// Behind is also shortened when the lookaround camera is tilting upwards.\r\n\tif( mp_lookaround_component->mLookaroundTilt < 0.0f )\r\n\t{\r\n\t\tfloat max_tilt = 3.14f * 0.2f;\r\n\t\t*p_behind = *p_behind * ( 0.4f + ( 0.6f * (( max_tilt + mp_lookaround_component->mLookaroundTilt ) / max_tilt )));\r\n\t}\r\n\r\n\t// Use lip_trick_above when doing a lip trick.\r\n\tfloat above_val = mAbove;\r\n\tif( mpSkaterStateComponent->GetState() == LIP )\r\n\t{\r\n\t\tabove_val = mLipTrickAbove;\r\n\t}\r\n\t\r\n\t// Figure above tending towards the perfect above, if zoom is < 1.0.\r\n\tif( mCurrentZoom < 1.0f )\r\n\t{\r\n\t\t*p_above = SKATERCAMERACOMPONENT_PERFECT_ABOVE + (( above_val - SKATERCAMERACOMPONENT_PERFECT_ABOVE ) * mCurrentZoom );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t*p_above = above_val;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCameraComponent::UpdateInterpolators(   )\r\n{\r\n\tif( mBehindInterpolatorTime > 0.0f )\r\n\t{\r\n\t\tmBehindInterpolatorTime -= SKATERCAMERACOMPONENT_INTERPOLATOR_TIMESTEP;\r\n\t\tmBehind += mBehindInterpolatorDelta;\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmBehindInterpolatorTime = 0.0f;\r\n\t}\r\n\r\n\tif( mAboveInterpolatorTime > 0.0f )\r\n\t{\r\n\t\tmAboveInterpolatorTime -= SKATERCAMERACOMPONENT_INTERPOLATOR_TIMESTEP;\r\n\t\tmAbove += mAboveInterpolatorDelta;\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmAboveInterpolatorTime = 0.0f;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCameraComponent::SetLerpReductionTimer( float time )\r\n{\r\n\tif( time > 0.0f )\r\n\t{\r\n\t\tmLerpReductionTimer\t= time;\r\n\t\tmLerpReductionDelta\t= 1.0f / time;\r\n\t\tmLerpReductionMult\t= 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmLerpReductionTimer\t= 0.0f;\r\n\t\tmLerpReductionDelta\t= 0.0f;\r\n\t\tmLerpReductionMult\t= 1.0f;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCameraComponent::SetSkater( CSkater* p_skater )\r\n{\r\n\tmpSkater = p_skater;\r\n\t\r\n\tif( p_skater == NULL )\r\n\t{\r\n\t\tmpSkaterStateComponent = NULL;\r\n\t\tmpSkaterPhysicsControlComponent = NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmpSkaterStateComponent = GetSkaterStateComponentFromObject(mpSkater);\r\n\t\tDbg_Assert(mpSkaterStateComponent);\r\n\t\t\r\n\t\t// non-local clients will not have a CSkaterPhysicsControlComponent\r\n\t\tmpSkaterPhysicsControlComponent = GetSkaterPhysicsControlComponentFromObject(mpSkater);\r\n\t\t\r\n\t\tSetNoLerpUpdate(true);\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCSkater* CSkaterCameraComponent::GetSkater( void )\r\n{\r\n\treturn mpSkater;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCameraComponent::GetCameraState ( SCameraState& state )\r\n{\r\n\tstate.lastActualMatrix[X] = mLastActualRight;\r\n\tstate.lastActualMatrix[Y] = mLastActualUp;\r\n\tstate.lastActualMatrix[Z] = mLastActualAt;\r\n\tstate.lastActualMatrix[W].Set( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\tstate.lastTripodPos = mLastTripodPos;\r\n\tstate.lastDot = mLastDot;\r\n\tstate.lastZoom = mCurrentZoom;\r\n}\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/SkaterCameraComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SkaterCameraComponent.h\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/21/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERCAMERACOMPONENT_H__\r\n#define __COMPONENTS_SKATERCAMERACOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/math/slerp.h>\r\n\r\n#include <gel/inpman.h>\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/components/camerautil.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n// Replace this with the CRCD of the component you are adding.\r\n#define\t\tCRC_SKATERCAMERA\t\t\t\t\t\t\tCRCD( 0x5e43a604, \"SkaterCamera\" )\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or given an object.\r\n#define\t\tGetSkaterCameraComponent()\t\t\t\t\t((Obj::CSkaterCameraComponent*)GetComponent( CRC_SKATERCAMERA ))\r\n#define\t\tGetSkaterCameraComponentFromObject( pObj )\t((Obj::CSkaterCameraComponent*)(pObj)->GetComponent( CRC_SKATERCAMERA ))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CInputComponent;\r\n\tclass CSkaterStateComponent;\r\n\tclass CSkaterPhysicsControlComponent;\r\n\tclass CCameraLookAroundComponent;\r\n\r\nclass CSkaterCameraComponent : public CBaseComponent\r\n{\r\n\tfriend class CWalkCameraComponent;\r\n\t\r\npublic:\r\n\r\n\tenum ESkaterCamMode\r\n\t{\r\n\t\tSKATERCAM_MODE_UNDEFINED\t\t= 0,\r\n\t\tSKATERCAM_MODE_FIRST_VALID\t\t= 1,\r\n\t\tSKATERCAM_MODE_NORMAL_NEAR\t\t= 1,\r\n\t\tSKATERCAM_MODE_NORMAL_MEDIUM,\r\n\t\tSKATERCAM_MODE_NORMAL_FAR,\r\n\t\tSKATERCAM_MODE_NORMAL_MEDIUM_LTG,\r\n        SKATERCAM_NUM_NORMAL_MODES,\r\n\t\tSKATERCAM_FIRST_REPLAY_MODE = SKATERCAM_NUM_NORMAL_MODES,\r\n\t\tSKATERCAM_MODE_REPLAY_FRONT = SKATERCAM_NUM_NORMAL_MODES,\r\n\t\tSKATERCAM_MODE_REPLAY_FRONT_ZOOM,\r\n        SKATERCAM_MODE_REPLAY_LEFT,\r\n\t\tSKATERCAM_MODE_REPLAY_LEFT_ZOOM,\r\n\t\tSKATERCAM_MODE_REPLAY_BEHIND,\r\n\t\tSKATERCAM_MODE_REPLAY_BEHIND_ZOOM,\r\n\t\tSKATERCAM_MODE_REPLAY_RIGHT,\r\n\t\tSKATERCAM_MODE_REPLAY_RIGHT_ZOOM,\r\n\t\tSKATERCAM_LAST_REPLAY_MODE = SKATERCAM_MODE_REPLAY_RIGHT_ZOOM,\r\n\t\tSKATERCAM_NUM_MODES,\r\n\t\tSKATERCAM_MODE_ANIM_PLAYBACK,\r\n\t};\r\n\t\r\n\t\t\t\t\t\t\t\t\t\t\tCSkaterCameraComponent();\r\n    virtual\t\t\t\t\t\t\t\t\t~CSkaterCameraComponent();\r\n\r\npublic:\r\n    virtual void            \t\t\t\tUpdate();\r\n    virtual void            \t\t\t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\t\t\tRefreshFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\t\t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   \t\tCallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tMth::Vector\t\t\t\t\t\t\t\tGetTripodPos( bool instantly = false );\r\n\tvoid\t\t\t\t\t\t\t\t\tUpdateInterpolators(   );\r\n\tvoid\t\t\t\t\t\t\t\t\tCalculateZoom( float* p_above, float* p_behind );\r\n\tvoid\t\t\t\t\t\t\t\t\taddShake( Mth::Vector& cam, Mth::Matrix& frame );\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\tSetNoLerpUpdate( bool instant )\t{ if( instant ) mInstantCount = 3; }\r\n\tvoid\t\t\t\t\t\t\t\t\tCommit( void );\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\tSetShake( float duration, float vert_amp, float horiz_amp, float vert_vel, float horiz_vel );\r\n\tbool\t\t\t\t\t\t\t\t\tUseVertCam( void );\r\n\tvoid\t\t\t\t\t\t\t\t\tActivateLerpIntoBehavior ( float duration );\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\tResetLookAround( void );\r\n\tvoid\t\t\t\t\t\t\t\t\tResetMode( );\r\n\tvoid\t\t\t\t\t\t\t\t\tSetMode( ESkaterCamMode mode, float time = 1.0f );\r\n\tvoid\t\t\t\t\t\t\t\t\tToggleMode( );\r\n\tESkaterCamMode\t\t\t\t\t\t\tGetMode( void )\t\t\t\t\t\t\t\t{ return mMode; }\r\n\tvoid\t\t\t\t\t\t\t\t\tSetLerpReductionTimer( float time );\r\n\tvoid\t\t\t\t\t\t\t\t\tSetSkater( CSkater* p_skater );\r\n\tCSkater*\t\t\t\t\t\t\t\tGetSkater( void );\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\t\tReadyForActivation ( const SCameraState& state );\r\n\tvoid\t\t\t\t\t\t\t\t\tGetCameraState ( SCameraState& state );\r\n\r\n\tstatic CBaseComponent*\t\t\t\t\ts_create();\r\n\r\n\t// These functions access the CCameraComponent which is required to be attached.\r\n\tvoid\t\t\t\t\t\t\t\t\tEnable( bool enable );\r\n\tGfx::Camera*\t\t\t\t\t\t\tGetCamera( void );\r\n\tconst Mth::Vector &\t\t\t\t\t\tGetPosition( void ) const;\r\n\tvoid\t\t\t\t\t\t\t\t\tSetPosition( Mth::Vector& pos );\r\n\tconst Mth::Matrix&\t\t\t\t\t\tGetMatrix( void ) const;\r\n\r\n\tbool\t\t\t\t\t\t\t\t\tmSkipButton;\r\n\tbool\t\t\t\t\t\t\t\t\tmRightButton;\r\n\tint\t\t\t\t\t\t\t\t\t\tmRightX;\r\n\tint\t\t\t\t\t\t\t\t\t\tmRightY;\r\n\r\nprivate:\r\n\tESkaterCamMode\t\t\t\t\t\t\tmMode;\r\n\r\n\tint\t\t\t\t\t\t\t\t\t\tmInstantCount;\t\t\t\t// Used to maintain the 'instantly' flag during update for several frames.\r\n\r\n\tfloat\t\t\t\t\t\t\t\t\tmLastDot;\r\n\tMth::Vector\t\t\t\t\t\t\t\tmLastTripodPos;\r\n\tMth::Vector\t\t\t\t\t\t\t\tmLastActualRight;\t\t\t// Used because the frame is adjusted after focus LERPING.\r\n\tMth::Vector\t\t\t\t\t\t\t\tmLastActualUp;\r\n\tMth::Vector\t\t\t\t\t\t\t\tmLastActualAt;\r\n\r\n\tMth::Matrix\t\t\t\t\t\t\t\tmLastPreWallSkaterMatrix;\t// Used because we don't want to use the skater's matrix during wall rides.\r\n\r\n\tfloat\t\t\t\t\t\t\t\t\tmBehind;\r\n\tfloat\t\t\t\t\t\t\t\t\tmBehindInterpolatorTime;\r\n\tfloat\t\t\t\t\t\t\t\t\tmBehindInterpolatorDelta;\r\n\tfloat\t\t\t\t\t\t\t\t\tmAbove;\r\n\tfloat\t\t\t\t\t\t\t\t\tmAboveInterpolatorTime;\r\n\tfloat\t\t\t\t\t\t\t\t\tmAboveInterpolatorDelta;\r\n\r\n\tfloat\t\t\t\t\t\t\t\t\tmVertAirLandedTimer;\t\t// Defines for how long the vert air landed slerp gets applied.\r\n\r\n\tfloat\t\t\t\t\t\t\t\t\tmHorizFOV;\r\n\r\n\tfloat\t\t\t\t\t\t\t\t\tmLerpXZ;\r\n\tfloat\t\t\t\t\t\t\t\t\tmLerpY;\r\n\tfloat\t\t\t\t\t\t\t\t\tmVertAirLerpXZ;\r\n\tfloat\t\t\t\t\t\t\t\t\tmVertAirLerpY;\r\n\tfloat\t\t\t\t\t\t\t\t\tmGrindLerp;\r\n\r\n\tfloat\t\t\t\t\t\t\t\t\tmLerpReductionTimer;\r\n\tfloat\t\t\t\t\t\t\t\t\tmLerpReductionDelta;\r\n\tfloat\t\t\t\t\t\t\t\t\tmLerpReductionMult;\r\n\r\n\tbool\t\t\t\t\t\t\t\t\tmBigAirTrickZoomActive;\r\n\tfloat\t\t\t\t\t\t\t\t\tmCurrentZoom;\r\n\tfloat\t\t\t\t\t\t\t\t\tmTargetZoom;\r\n\tfloat\t\t\t\t\t\t\t\t\tmZoomLerp;\t\t\t\t// LERP rate for zoom.\r\n\tfloat\t\t\t\t\t\t\t\t\tmBigAirTrickZoom;\t\t// Target zoom for big air trick.\r\n\tfloat\t\t\t\t\t\t\t\t\tmGrindZoom;\t\t\t\t// Target zoom for grind.\r\n\tfloat\t\t\t\t\t\t\t\t\tmLipTrickZoom;\t\t\t// Target zoom for lip trick.\r\n\tint\t\t\t\t\t\t\t\t\t\tmLipSideDecided;\r\n\r\n\tfloat\t\t\t\t\t\t\t\t\tmLean;\t\t\t\t\t// For lean during grind imbalance.\r\n\r\n\tfloat\t\t\t\t\t\t\t\t\tmTilt;\r\n\tfloat\t\t\t\t\t\t\t\t\tmTiltAddition;\r\n\tfloat\t\t\t\t\t\t\t\t\tmLipTrickTilt;\r\n\tfloat\t\t\t\t\t\t\t\t\tmLipTrickAbove;\r\n\tfloat\t\t\t\t\t\t\t\t\tmWalkSlerp;\r\n\tfloat\t\t\t\t\t\t\t\t\tmSlerp;\r\n\tfloat\t\t\t\t\t\t\t\t\tmVertAirSlerp;\r\n\tfloat\t\t\t\t\t\t\t\t\tmVertAirLandedSlerp;\r\n\tfloat\t\t\t\t\t\t\t\t\tmOriginOffset;\r\n\r\n\tfloat\t\t\t\t\t\t\t\t\tmShakeDuration;\t\t\t// Shake duration in seconds (0.0 means no shake).\r\n\tfloat\t\t\t\t\t\t\t\t\tmShakeInitialDuration;\r\n\tfloat\t\t\t\t\t\t\t\t\tmShakeMaxVertAmp;\r\n\tfloat\t\t\t\t\t\t\t\t\tmShakeMaxHorizAmp;\r\n\tfloat\t\t\t\t\t\t\t\t\tmShakeVertVel;\r\n\tfloat\t\t\t\t\t\t\t\t\tmShakeHorizVel;\r\n\t\r\n\tCCameraLookAroundComponent*\t\t\t\tmp_lookaround_component;\r\n\r\n\tMth::SlerpInterpolator*\t\t\t\t\tmpSlerp;\r\n\tCSkater*\t\t\t\t\t\t\t\tmpSkater;\r\n\tCSkaterStateComponent*\t\t\t\t\tmpSkaterStateComponent;\r\n\tCSkaterPhysicsControlComponent*\t\t\tmpSkaterPhysicsControlComponent;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/SkitchComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SkitchComponent.cpp\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/19/03\r\n//****************************************************************************\r\n\r\n#include <gel/components/skitchcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCBaseComponent* CSkitchComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkitchComponent );\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCSkitchComponent::CSkitchComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKITCH );\r\n\r\n\t// Skitching allowed by default.\r\n\tm_skitch_allowed = true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCSkitchComponent::~CSkitchComponent()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkitchComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// There needs to be a ObjectHookManagerComponent attached for the SkitchComponent to operate.\r\n\tmp_object_hook_manager_component = GetObjectHookManagerComponentFromObject( GetObject());\r\n\tDbg_MsgAssert( mp_object_hook_manager_component, ( \"SkitchComponent created without ObjectHookManagerComponent\" ));\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkitchComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure( pParams );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkitchComponent::Update()\r\n{\r\n\t// Doing nothing, so tell code to do nothing next time around\r\n\tSuspend(true);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCBaseComponent::EMemberFunctionResult CSkitchComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | Obj_AllowSkitching | Enable skitching for this object \r\n\t\t// @flag off | disable skitching\r\n\t\tcase 0xc38cce3b:  // Obj_AllowSkitching\r\n\t\t{\r\n\t\t\tAllowSkitch(( pParams->ContainsFlag( \"off\" )) ? false : true );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkitchComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert( p_info, ( \"NULL p_info sent to CSkitchComponent::GetDebugInfo\" ));\r\n\t\r\n\tp_info->AddInteger( \"m_skitch_allowed\", m_skitch_allowed ? 1 : 0 );\r\n\r\n\t// we call the base component's GetDebugInfo, so we can add info from the common base component\r\n\tCBaseComponent::GetDebugInfo( p_info );\r\n#endif\t\t\t\t \r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CSkitchComponent::GetNearestSkitchPoint( Mth::Vector *p_point, Mth::Vector &pos )\r\n{\r\n\tint nearest_node_number = -1;\t// -1 means not found yet\r\n\r\n\t// Only continue if we have a parent object (we always should) and a object hook manager component.\r\n\tCCompositeObject *p_parent_object = GetObject();\r\n\tif( mp_object_hook_manager_component && p_parent_object )\r\n\t{\r\n\t\tObj::CObjectHookManager *p_object_hook_man = mp_object_hook_manager_component->GetObjectHookManager();\r\n\t\tif( p_object_hook_man )\r\n\t\t{\r\n\t\t\t// Form a transformation matrix.\r\n\t\t\tMth::Matrix total_mat\t= p_parent_object->GetMatrix();\r\n\t\t\ttotal_mat[X][W]\t\t\t= 0.0f;\r\n\t\t\ttotal_mat[Y][W]\t\t\t= 0.0f;\r\n\t\t\ttotal_mat[Z][W]\t\t\t= 0.0f;\r\n\t\t\ttotal_mat[W]\t\t\t= p_parent_object->GetPos();\r\n\t\t\ttotal_mat[W][W]\t\t\t= 1.0f;\r\n\r\n\t\t\tp_object_hook_man->UpdateTransform( total_mat );\r\n\r\n\t\t\tint node_number = 0;\r\n\t\t\tCObjectHookNode *p_node\t\t= p_object_hook_man->GetFirstNode();\r\n\t\t\tCObjectHookNode *p_nearest\t= p_node;\r\n\t\t\tfloat nearest_dist_squared\t= 100000000000000.0f;\t\r\n\t\t\tMth::Vector nearest_point(0.0f, 0.0f, 0.0f);\r\n\r\n\t\t\twhile( p_node )\r\n\t\t\t{\r\n\t\t\t\t// Get the postition of the hook.\r\n\t\t\t\tMth::Vector point = p_object_hook_man->GetPos( p_node );\r\n\r\n\t\t\t\t// Project the point onto the base plane of the object so we can ignore the height.\r\n\t\t\t\tpoint -= p_parent_object->GetPos();\r\n\t\t\t\tpoint.ProjectToPlane( p_parent_object->GetMatrix()[Y] );\r\n\t\t\t\tpoint += p_parent_object->GetPos();\r\n\t\t\t\r\n\t\t\t\tfloat dist_squared = ( point - pos ).LengthSqr();\r\n\t\t\t\tif( dist_squared < nearest_dist_squared )\r\n\t\t\t\t{\r\n\t\t\t\t\tnearest_dist_squared\t= dist_squared;\r\n\t\t\t\t\tnearest_point\t\t\t= point;\r\n\t\t\t\t\tp_nearest\t\t\t\t= p_node; \r\n\t\t\t\t\tnearest_node_number\t\t= node_number;\r\n\t\t\t\t}\r\n\t\t\t\tp_node = p_node->GetNext();\r\n\t\t\t\tnode_number++;\r\n\t\t\t}\t\t\r\n\t\t\t*p_point = nearest_point;\r\n\t\t }\r\n\t}\r\n\r\n\treturn nearest_node_number;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Given the index of a skitch point, then get the position of\t  */\r\n/* that point.\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Adjust the point to lay on the ground plane of the object.\t  */\r\n/* Returns the position in *p_point returns true if object still  */\r\n/* exists, and false otherwise.\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CSkitchComponent::GetIndexedSkitchPoint( Mth::Vector *p_point, int index )\r\n{\r\n\t// Only continue if we have a parent object (we always should) and a object hook manager component.\r\n\tCCompositeObject *p_parent_object = GetObject();\r\n\tif( mp_object_hook_manager_component && p_parent_object )\r\n\t{\r\n\t\tObj::CObjectHookManager *p_object_hook_man = mp_object_hook_manager_component->GetObjectHookManager();\r\n\t\tif( p_object_hook_man )\r\n\t\t{\r\n\t\t\t// Form a transformation matrix.\r\n\t\t\tMth::Matrix total_mat\t= p_parent_object->GetMatrix();\r\n\t\t\ttotal_mat[X][W]\t\t\t= 0.0f;\r\n\t\t\ttotal_mat[Y][W]\t\t\t= 0.0f;\r\n\t\t\ttotal_mat[Z][W]\t\t\t= 0.0f;\r\n\t\t\ttotal_mat[W]\t\t\t= p_parent_object->GetPos();\r\n\t\t\ttotal_mat[W][W]\t\t\t= 1.0f;\r\n\r\n\t\t\tp_object_hook_man->UpdateTransform( total_mat );\r\n\r\n\t\t\tint node_number = 0;\r\n\t\t\tCObjectHookNode *p_node = p_object_hook_man->GetFirstNode();\r\n\t\t\r\n\t\t\twhile( p_node )\r\n\t\t\t{\r\n\t\t\t\tif( node_number == index )\r\n\t\t\t\t{\r\n\t\t\t\t\tMth::Vector point = p_object_hook_man->GetPos( p_node );\r\n\r\n\t\t\t\t\t// Project the point onto the base plane of the object so we can ignore the height.\r\n\t\t\t\t\tpoint -= p_parent_object->GetPos();\r\n\t\t\t\t\tpoint.ProjectToPlane( p_parent_object->GetMatrix()[Y] );\r\n\t\t\t\t\tpoint += p_parent_object->GetPos();\r\n\r\n\t\t\t\t\t*p_point = point;\r\n\r\n\t\t\t\t\t// There was no break here in the original code in MovingObject, but I see no reason\r\n\t\t\t\t\t// to continue the loop iteration at this point.\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tp_node = p_node->GetNext();\r\n\t\t\t\tnode_number++;\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t }\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/SkitchComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SkitchComponent.h\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/19/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKITCHCOMPONENT_H__\r\n#define __COMPONENTS_SKITCHCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/components/objecthookmanagercomponent.h>\r\n\r\n// Replace this with the CRCD of the component you are adding\r\n#define\t\tCRC_SKITCH\t\t\t\t\t\t\t\tCRCD( 0x3506ce64, \"Skitch\" )\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or given an object\r\n#define\t\tGetSkitchComponent()\t\t\t\t\t((Obj::CSkitchComponent*)GetComponent( CRC_SKITCH ))\r\n#define\t\tGetSkitchComponentFromObject( pObj )\t((Obj::CSkitchComponent*)(pObj)->GetComponent( CRC_SKITCH ))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CSkitchComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkitchComponent();\r\n    virtual ~CSkitchComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\n\tbool\t\t\t\t\t\t\tCanSkitch( void )\t\t\t{ return m_skitch_allowed; }\r\n\tvoid\t\t\t\t\t\t\tAllowSkitch( bool allow )\t{ m_skitch_allowed = allow; }\r\n\tint\t\t\t\t\t\t\t\tGetNearestSkitchPoint( Mth::Vector *p_point, Mth::Vector &pos );\r\n\tbool\t\t\t\t\t\t\tGetIndexedSkitchPoint( Mth::Vector *p_point, int index );\r\n\r\nprivate:\r\n\tbool\t\t\t\t\t\t\tm_skitch_allowed;\r\n\tCObjectHookManagerComponent*\tmp_object_hook_manager_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/StaticVehicleComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       StaticVehicleComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  8/6/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/staticvehiclecomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <gfx/nxhierarchy.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/skeleton.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CStaticVehicleComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CStaticVehicleComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCStaticVehicleComponent::CStaticVehicleComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_STATICVEHICLE );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCStaticVehicleComponent::~CStaticVehicleComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStaticVehicleComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStaticVehicleComponent::Finalize()\r\n{\r\n\tCModelComponent* p_model_component = static_cast< CModelComponent* >(GetModelComponentFromObject(GetObject()));\r\n\tDbg_Assert(p_model_component);\r\n\tNx::CModel* p_model = p_model_component->GetModel();\r\n\tDbg_Assert(p_model);\r\n\tNx::CHierarchyObject* p_hierarchy_objects = p_model->GetHierarchy();\r\n\tDbg_Assert(p_hierarchy_objects);\r\n\t\r\n\tMth::Vector p_wheels [ CVehicleComponent::vVP_NUM_WHEELS ];\r\n\t\r\n\tfor (int n = CVehicleComponent::vVP_NUM_WHEELS; n--; )\r\n\t{\r\n\t\tMth::Vector& wheel_pos = p_wheels[n];\r\n\t\t\r\n\t\tMth::Matrix wheel_matrix = (p_hierarchy_objects + 2 + n)->GetSetupMatrix();\r\n\t\t\r\n\t\t// rotate out of max coordinate system\r\n\t\twheel_pos[X] = -wheel_matrix[W][X];\r\n\t\twheel_pos[Y] = wheel_matrix[W][Z];\r\n\t\twheel_pos[Z] = -wheel_matrix[W][Y];\r\n\t\twheel_pos[W] = 1.0f;\r\n\t}\r\n\t\r\n\tMth::Matrix body_matrix = (p_hierarchy_objects + 1)->GetSetupMatrix();\r\n\tMth::Vector body_pos;\r\n\tbody_pos[X] = -body_matrix[W][X];\r\n\tbody_pos[Y] = body_matrix[W][Z];\r\n\tbody_pos[Z] = -body_matrix[W][Y];\r\n\tbody_pos[W] = 1.0f;\r\n\t\r\n\tCSkeletonComponent* p_skeleton_component = static_cast< CSkeletonComponent* >(GetSkeletonComponentFromObject(GetObject()));\r\n\tDbg_Assert(p_skeleton_component);\r\n\tDbg_Assert(p_skeleton_component->GetSkeleton());\r\n\tMth::Matrix* p_matrices = p_skeleton_component->GetSkeleton()->GetMatrices();\r\n\tfor (int i = 0; i < p_skeleton_component->GetSkeleton()->GetNumBones(); i++)\r\n\t{\r\n\t\tMth::Matrix& matrix = p_matrices[i];\r\n\t\t\r\n\t\t// setup the matrix for each bone in the skeleton\r\n\t\t\r\n\t\t// shadow\r\n\t\tif (i == 0)\r\n\t\t{\r\n\t\t\tmatrix.Zero();\r\n\t\t}\r\n\t\t\r\n\t\t// body\r\n\t\telse if (i == 1)\r\n\t\t{\r\n\t\t\tmatrix.Zero();\r\n\t\t\tmatrix[X][X] = 1.0f;\r\n\t\t\tmatrix[Y][Z] = -1.0f;\r\n\t\t\tmatrix[Z][Y] = 1.0f;\r\n\t\t\tmatrix[W] = body_pos;\r\n\t\t}\r\n\t\t\r\n\t\t// wheel\r\n\t\telse\r\n\t\t{\r\n\t\t\tMth::Vector& wheel_pos = p_wheels[i - 2];\r\n\t\t\t\r\n\t\t\tmatrix.Zero();\r\n\t\t\tmatrix[X][X] = -1.0f;\r\n\t\t\tmatrix[Y][Z] = 1.0f;\r\n\t\t\tmatrix[Z][Y] = 1.0f;\r\n\t\t\tmatrix[W] = wheel_pos;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStaticVehicleComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStaticVehicleComponent::Update()\r\n{\r\n\tSuspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CStaticVehicleComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStaticVehicleComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CStaticVehicleComponent::GetDebugInfo\"));\r\n\t\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/StaticVehicleComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       StaticVehicleComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  8/6/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_STATICVEHICLECOMPONENT_H__\r\n#define __COMPONENTS_STATICVEHICLECOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <gel/components/vehiclecomponent.h>\r\n\r\n#define\t\tCRC_STATICVEHICLE CRCD(0x9649d4f9, \"StaticVehicle\")\r\n\r\n#define\t\tGetStaticVehicleComponent() ((Obj::CStaticVehicleComponent*)GetComponent(CRC_STATICVEHICLE))\r\n#define\t\tGetStaticVehicleComponentFromObject(pObj) ((Obj::CStaticVehicleComponent*)(pObj)->GetComponent(CRC_STATICVEHICLE))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CStaticVehicleComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CStaticVehicleComponent();\r\n    virtual ~CStaticVehicleComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual\tvoid \t\t\t\t\tFinalize();\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\nprivate:\r\n\tMth::Vector\t\t\t\t\t\tmp_wheels [ CVehicleComponent::vVP_NUM_WHEELS ];\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/StatsManagerComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       StatsManagerComponent.cpp\r\n//* OWNER:          Zac Drake\r\n//* CREATION DATE:  5/29/03\r\n//****************************************************************************\r\n\r\n//  This component watches the skater and checks if certain always active goals are met.\r\n//  When these goals are met, the skaters stats are increased. These goals are pulled from\r\n//  the stats_goals script array in stats.q\r\n\r\n#include <gel/components/statsmanagercomponent.h>\r\n\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h> \r\n#include <gel/scripting/checksum.h> \r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/utils.h>\r\n\r\n#include <core/math.h>\r\n#include <core/math/math.h>\r\n#include <core/flags.h>\r\n#include <sk/modules/skate/score.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skaterbalancetrickcomponent.h>\r\n\r\n#include <sk/objects/playerprofilemanager.h>\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\n\r\nCBaseComponent* CStatsManagerComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CStatsManagerComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCStatsManagerComponent::CStatsManagerComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_STATSMANAGER );\r\n    \r\n    mpSkater= NULL;\r\n    mpSkaterStateComponent = NULL;\r\n    mpSkaterPhysicsControlComponent = NULL;\r\n    mpSkaterCorePhysicsComponent = NULL;\r\n\r\n    vert_start_pos.Set( 0.0f, 0.0f, 0.0f, 0.0f );\r\n    vert_end_pos.Set( 0.0f, 0.0f, 0.0f, 0.0f );\r\n    jump_start_pos.Set( 0.0f, 0.0f, 0.0f, 0.0f );\r\n    jump_end_pos.Set( 0.0f, 0.0f, 0.0f, 0.0f );\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCStatsManagerComponent::~CStatsManagerComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CStatsManagerComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// ** Add code to parse the structure, and initialize the component\r\n    \r\n    showed_info = false;    // need to grab this from memcard eventually\r\n    stat_goals_on = false;\r\n    \r\n    new_event = NULL;\r\n    last_event = NULL;\r\n    \r\n    vert_set = 0;\r\n    vert_height = 0;\r\n    vert_score = 0;\r\n    vert_start_base=0;\r\n    vert_start_mult=0;\r\n    \r\n    jump_set = 0;\r\n    \r\n    num_fliptricks=0;\r\n    num_grabtricks=0;\r\n\r\n    air_combo_score=0;\r\n\r\n    m_restarted_this_frame = true;\r\n\r\n    // Set p_skater\r\n    uint32 target_id = Obj::CBaseComponent::GetObject()->GetID();\r\n    Dbg_MsgAssert(target_id >=0 && target_id <= 15,(\"Bad StatsManagerTarget 0x%x in SkaterStatsManagerComponent\",target_id));\r\n    \r\n\tCSkater* p_skater = static_cast<CSkater*>(CCompositeObjectManager::Instance()->GetObjectByID(target_id)); \r\n\tDbg_MsgAssert(p_skater,(\"Can't find skater %d in SkaterStatsManagerComponent\",target_id));\r\n    \r\n\tSetSkater(p_skater);\r\n\r\n    // get difficulty level\r\n    Game::CGoalManager* pGoalManager = Game::GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n    dif_level = (int)pGoalManager->GetDifficultyLevel(true);\r\n\r\n    printf(\"STATSManager: difficulty ====================== %i\\n\", dif_level );\r\n\r\n    // should bump stats?\r\n    int bump = Script::GetInteger( \"bump_stats\", Script::ASSERT );\r\n    if ( bump == 1 )\r\n    {\r\n        bump_stats=true;\r\n    }\r\n\r\n    // reset stats to defaults\r\n    /*Obj::CSkaterProfile* pProfile = Mdl::Skate::Instance()->GetProfile( 0 );\r\n    pProfile->SetPropertyValue( CRCD(0x439f4704,\"air\"), 3 );\r\n    pProfile->SetPropertyValue( CRCD(0x9016b4e7,\"switch\"), 3 );\r\n    pProfile->SetPropertyValue( CRCD(0xedf5db70,\"spin\"), 3 );\r\n    pProfile->SetPropertyValue( CRCD(0xaf895b3f,\"run\"), 3 );\r\n    pProfile->SetPropertyValue( CRCD(0xf0d90109,\"speed\"), 3 );\r\n    pProfile->SetPropertyValue( CRCD(0xae798769,\"lip_balance\"), 3 );\r\n    pProfile->SetPropertyValue( CRCD(0xf73a13e3,\"rail_balance\"), 3 );\r\n    pProfile->SetPropertyValue( CRCD(0xb1fc0722,\"manual_balance\"), 3 );\r\n    pProfile->SetPropertyValue( CRCD(0x6dcb497c,\"flip_speed\"), 3 );\r\n    pProfile->SetPropertyValue( CRCD(0x9b65d7b8,\"ollie\"), 3 );\r\n    */\r\n    \r\n    // get initial values from script\r\n    Script::CArray* p_array = Script::GetArray( \"stats_goals\", Script::ASSERT );\r\n    Dbg_MsgAssert( p_array->GetType() == ESYMBOLTYPE_STRUCTURE, ( \"This function only works on arrays of structures.\" ) );\r\n\r\n    int array_size = p_array->GetSize();\r\n    Script::CStruct* p_struct = NULL;\r\n    \r\n    //for( int index = 0; index < NUM_STATS_GOALS; index++)\r\n    for ( int index = 0; index < array_size; index++ )\r\n    {\r\n        p_struct = p_array->GetStructure( index );\r\n        if ( p_struct->ContainsComponentNamed( \"goaltype\" ) )\r\n        {\r\n            uint32 goal_value;\r\n            p_struct->GetChecksum( \"goaltype\", &goal_value, Script::ASSERT );\r\n            stat_goals[index].goaltype = goal_value;\r\n        }\r\n        if ( p_struct->ContainsComponentNamed( \"stattype\" ) )\r\n        {\r\n            uint32 stat_value;\r\n            p_struct->GetChecksum( \"stattype\", &stat_value, Script::ASSERT );\r\n            stat_goals[index].stattype = stat_value;\r\n        }\r\n        if ( p_struct->ContainsComponentNamed( \"value\" ) )\r\n        {\r\n            Script::CArray* value_array = NULL;\r\n            int value_value;\r\n            p_struct->GetArray( \"value\", &value_array, Script::ASSERT );\r\n            value_value = value_array->GetInteger(dif_level);\r\n            stat_goals[index].value = value_value;\r\n        }\r\n        if ( p_struct->ContainsComponentNamed( \"value_string\" ) )\r\n        {\r\n            Script::CArray* value_string_array = NULL;\r\n            const char*  value_vstring;\r\n            p_struct->GetArray( \"value_string\", &value_string_array, Script::ASSERT );\r\n            value_vstring = value_string_array->GetString(dif_level);\r\n            stat_goals[index].v_string = value_vstring;\r\n        }\r\n        if ( p_struct->ContainsComponentNamed( \"text\" ) )\r\n        {\r\n            const char* text_value=\"\";\r\n            p_struct->GetString( \"text\", &text_value, Script::ASSERT );\r\n            stat_goals[index].text = text_value;\r\n        }\r\n        if ( p_struct->ContainsComponentNamed( \"complete\" ) )\r\n        {\r\n            int complete_value;\r\n            p_struct->GetInteger( \"complete\", &complete_value, Script::ASSERT );\r\n            stat_goals[index].complete = complete_value;\r\n        }\r\n        if ( p_struct->ContainsComponentNamed( \"value_trick\" ) )\r\n        {\r\n            Script::CArray* value_trick_array = NULL;\r\n            uint32  value_vtrick;\r\n            p_struct->GetArray( \"value_trick\", &value_trick_array, Script::ASSERT );\r\n            value_vtrick = value_trick_array->GetChecksum(dif_level);\r\n            stat_goals[index].trick = value_vtrick;\r\n        }\r\n        if ( p_struct->ContainsComponentNamed( \"value_taps\" ) )\r\n        {\r\n            Script::CArray* value_taps_array = NULL;\r\n            uint32  value_vtaps;\r\n            p_struct->GetArray( \"value_taps\", &value_taps_array, Script::ASSERT );\r\n            value_vtaps = value_taps_array->GetInteger(dif_level);\r\n            stat_goals[index].taps = value_vtaps;\r\n        }\r\n        stat_goals[index].shown = false;\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*void CStatsManagerComponent::Finalize()\r\n{\r\n\t// Virtual function, can be overridden to provided finialization to \r\n\t// a component after all components have been added to an object\r\n\t// Usually this consists of getting pointers to other components\r\n\t// Note:  It is GUARENTEED (at time of writing) that\r\n\t// Finalize() will be called AFTER all components are added\r\n\t// and BEFORE the CCompositeObject::Update function is called\r\n\t\r\n\t// Example:\r\n\t// mp_suspend_component =  GetSuspendComponentFromObject( GetObject() );\r\n    \r\n}*/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CStatsManagerComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calling InitFromStructure()\r\n\t// but if that does not handle it, then will need to write a specific \r\n\t// function here. \r\n\t// The user might only want to update a single field in the structure\r\n\t// and we don't want to be asserting because everything is missing \r\n\t\r\n\tInitFromStructure(pParams);\r\n\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CStatsManagerComponent::Update()\r\n{\r\n\t// **  You would put in here the stuff that you would want to get run every frame\r\n\t// **  for example, a physics type component might update the position and orientation\r\n\t// **  and update the internal physics state\r\n\r\n    if( mpSkater == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n    // Return if not in career mode\r\n    Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n    if ( !skate_mod->GetGameMode()->IsTrue( CRCD(0x1ded1ea4,\"is_career\") ) )\r\n    {\r\n        return;\r\n    }\r\n    \r\n    // Return if stat goals turned off\r\n    if ( !stat_goals_on )\r\n    {\r\n        return;\r\n    }\r\n    \r\n    // Return if in frontend\r\n    if (skate_mod->m_cur_level == CRCD(0x9f2bafb7,\"load_skateshop\"))\r\n    {\r\n        return;\r\n    }\r\n\r\n    if (m_restarted_this_frame)\r\n    {\r\n        vert_set = 0;\r\n        jump_set = 0;\r\n\r\n        m_restarted_this_frame = false;\r\n\r\n        return;\r\n    }\r\n    \r\n    // Get current trick score this frame???\r\n    Mdl::Score *pScore = mpSkater->GetScoreObject();\r\n    Dbg_Assert( pScore );\r\n    current_score = pScore->GetScorePotValue();\r\n    current_mult = pScore->GetCurrentMult();\r\n    if ( current_mult != 0 )\r\n    {\r\n        current_base = (current_score / current_mult);\r\n    }\r\n    else\r\n    {\r\n        current_base = 0;\r\n    }\r\n    \r\n    // Get skater state\r\n    EStateType state = mpSkaterStateComponent->GetState();\r\n\r\n    // reset new event\r\n    new_event = CRCD(0x26a7cadf,\"other\");\r\n    \r\n    // check if skating\r\n    if (mpSkaterPhysicsControlComponent->IsSkating())\r\n    {\r\n        // check for vert airs and landings\r\n        if ( mpSkaterStateComponent->GetFlag( VERT_AIR ) )\r\n        {\r\n            new_event = CRCD(0xb39b4f1b,\"vert_air\");\r\n            if ( last_event != CRCD(0xb39b4f1b,\"vert_air\") )\r\n            {\r\n                // vert take off\r\n                vert_set = 1;\r\n                vert_height = 0;\r\n                vert_start_pos = GetObject()->GetPos();\r\n                vert_start_base = current_base;\r\n                vert_start_mult = current_mult;\r\n                printf(\"vert_start_score = %i\\n\", current_score );\r\n                vert_score = 0;\r\n            }\r\n            else\r\n            {\r\n                // vert in air\r\n                Mth::Vector new_pos = GetObject()->GetPos();\r\n                if ( ( new_pos[1] - vert_start_pos[1] ) > vert_height )\r\n                {\r\n                    vert_height = ( new_pos[1] - vert_start_pos[1] );\r\n                }\r\n\r\n                // the dif in base times the dif in multiplier\r\n                air_combo_score = ((current_base - vert_start_base) * (current_mult - vert_start_mult));\r\n\r\n                if ( air_combo_score >= vert_score )\r\n                {\r\n                    vert_score = air_combo_score;\r\n                }\r\n            }\r\n        }\r\n        else\r\n        {\r\n            // landed from vert ( not really landed... could still revert to manual )\r\n            if ( last_event == CRCD(0xb39b4f1b,\"vert_air\") )\r\n            {\r\n                int air_combo_mult=0;\r\n\r\n                if ( vert_set == 1 )\r\n                {\r\n                    vert_end_pos = GetObject()->GetPos();\r\n                    air_combo_score = ((current_base - vert_start_base) * (current_mult - vert_start_mult));\r\n                    air_combo_mult = (current_mult - vert_start_mult);\r\n                    vert_set = 2;\r\n                }\r\n\r\n                // air combo messages\r\n                if ( air_combo_mult > 1 )\r\n                {\r\n                    if ( air_combo_score != 0 )\r\n                    {\r\n                        Script::CStruct* p_params = new Script::CStruct();\r\n                        p_params->AddInteger( \"score\", air_combo_score );\r\n                        Script::RunScript( Script::GenerateCRC( \"show_vert_combo_message\" ), p_params );\r\n                        delete p_params;\r\n                    }\r\n                }\r\n                air_combo_score=0;\r\n            }\r\n            // not vert related\r\n            else\r\n            {\r\n                vert_set = 0;\r\n                vert_height = 0;\r\n                vert_score = 0;\r\n            }\r\n        }\r\n\r\n        // check for jump takeoffs and landings\r\n        if ( (state == AIR) && (!mpSkaterStateComponent->GetFlag( VERT_AIR )) )\r\n        {\r\n            new_event = CRCD(0x439f4704,\"air\");\r\n            if ( last_event != CRCD(0x439f4704,\"air\") )\r\n            {\r\n                if ( !mpSkaterStateComponent->GetFlag(IS_BAILING) )\r\n                {\r\n                    jump_set = 1;\r\n                    jump_start_pos = GetObject()->GetPos();\r\n                }\r\n            }\r\n        }\r\n        else\r\n        {\r\n            if ( last_event == CRCD(0x439f4704,\"air\") )\r\n            {\r\n                if ( jump_set == 1 )\r\n                {\r\n                    jump_end_pos = GetObject()->GetPos();\r\n                    jump_set = 2;\r\n                }\r\n            }\r\n            else\r\n            {\r\n                jump_set = 0;\r\n            }\r\n        }\r\n    }\r\n    else\r\n    {\r\n        jump_set = 0;\r\n    }\r\n    \r\n    // check for triggered goals\r\n    bool beat_one = false;\r\n    for (int i=0; i < NUM_STATS_GOALS; i++)\r\n    {\r\n        // Combo goals\r\n        if ( stat_goals[i].goaltype == CRCD(0x4ec3cfb5,\"combo\") )\r\n        {\r\n            if (!stat_goals[i].complete)\r\n            {\r\n                if (!stat_goals[i].shown)\r\n                {\r\n                    int value = stat_goals[i].value;\r\n                    if ( current_score >= value )\r\n                    {\r\n                        ShowStatsMessage(i);\r\n                        beat_one=true;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        // Multiplier goals\r\n        if ( stat_goals[i].goaltype == CRCD(0x5b6556a4,\"multiplier\") )\r\n        {\r\n            if (!stat_goals[i].complete)\r\n            {\r\n                if (!stat_goals[i].shown)\r\n                {\r\n                    int value = stat_goals[i].value;\r\n                    if ( current_mult >= value )\r\n                    {\r\n                        ShowStatsMessage(i);\r\n                        beat_one=true;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        // Vert Distance\r\n        if ( stat_goals[i].goaltype == CRCD(0xc3ec3eed,\"vertdist\") )\r\n        {\r\n            if (!stat_goals[i].complete)\r\n            {\r\n                if (!stat_goals[i].shown)\r\n                {\r\n                    if ( vert_set == 2 )\r\n                    {\r\n                        float value = float(stat_goals[i].value);\r\n                        float vert_dist = 1;\r\n                        \r\n                        // set Y values to zero\r\n                        vert_end_pos[1] = 0;\r\n                        vert_start_pos[1] = 0;\r\n    \r\n                        vert_dist = Mth::Distance(vert_end_pos, vert_start_pos);\r\n                        //printf(\"vert_dist = %f value = %f \\n\", (vert_dist/12), value );\r\n                        \r\n                        if ( vert_dist >= (12*value) ) // value is in feet, vert_dist is in inches\r\n                        {\r\n                            ShowStatsMessage(i);\r\n                            beat_one=true;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        // Vert Height\r\n        if ( stat_goals[i].goaltype == CRCD(0x430b80c4,\"vertheight\") )\r\n        {\r\n            if (!stat_goals[i].complete)\r\n            {\r\n                if (!stat_goals[i].shown)\r\n                {\r\n                    if ( vert_set != 0 )\r\n                    {\r\n                        float value = float(stat_goals[i].value);\r\n                        \r\n                        if ( vert_height >= (12*value) ) // value is in feet, vert_height is in inches\r\n                        {\r\n                            ShowStatsMessage(i);\r\n                            beat_one=true;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        // Vert Score\r\n        if ( stat_goals[i].goaltype == CRCD(0x1dbbb148,\"vertscore\") )\r\n        {\r\n            if (!stat_goals[i].complete)\r\n            {\r\n                if (!stat_goals[i].shown)\r\n                {\r\n                    if ( vert_set == 2 )\r\n                    {\r\n                        int value = stat_goals[i].value;\r\n                        \r\n                        if ( vert_score >= value )\r\n                        {\r\n                            ShowStatsMessage(i);\r\n                            beat_one=true;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        // Vert Spin\r\n        if ( stat_goals[i].goaltype == CRCD(0x509aca95,\"vertspin\") )\r\n        {\r\n            if (!stat_goals[i].complete)\r\n            {\r\n                if (!stat_goals[i].shown)\r\n                {\r\n                    if ( vert_set != 0 )\r\n                    {\r\n                        float value = float(stat_goals[i].value);\r\n                        \r\n                        if ( vert_spin >= value )\r\n                        {\r\n                            ShowStatsMessage(i);\r\n                            beat_one=true;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        // Jump Distance\r\n        if ( stat_goals[i].goaltype == CRCD(0x8f6f9f05,\"olliedist\") )\r\n        {\r\n            if (!stat_goals[i].complete)\r\n            {\r\n                if (!stat_goals[i].shown)\r\n                {\r\n                    if ( jump_set == 2 )\r\n                    {\r\n                        float value = float(stat_goals[i].value);\r\n                        float jump_dist = 1;\r\n                        Mth::Vector end;\r\n\t\t\t\t\t\tMth::Vector start;\r\n\t\t\t\t\t\t\r\n                        // grab start and end points minus Y values\r\n                        end[0] = jump_end_pos[0];\r\n                        end[1] = 0;\r\n                        end[2] = jump_end_pos[2];\r\n\t\t\tend[3] = 1.0f;\r\n\r\n                        start[0] = jump_start_pos[0];\r\n                        start[1] = 0;\r\n                        start[2] = jump_start_pos[2];\r\n                        start[3] = 1.0f;\r\n\r\n                        jump_dist = Mth::Distance(end, start);\r\n                        //printf(\"jump_dist = %f value = %f \\n\", (jump_dist/12), value );\r\n                        \r\n                        if ( jump_dist >= (12*value) ) // value is in feet, jump_dist is in inches\r\n                        {\r\n                            ShowStatsMessage(i);\r\n                            beat_one=true;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        // Jump Height\r\n        if ( stat_goals[i].goaltype == CRCD(0x39e7537b,\"highollie\") )\r\n        {\r\n            if (!stat_goals[i].complete)\r\n            {\r\n                if (!stat_goals[i].shown)\r\n                {\r\n                    if ( jump_set == 2 )\r\n                    {\r\n                        float value = float(stat_goals[i].value);\r\n                        float jump_high = 1;\r\n                        \r\n                        jump_high = ( jump_end_pos[1] - jump_start_pos[1] );\r\n                        \r\n                        if ( jump_high >= (12*value) ) // value is in feet, jump_high is in inches\r\n                        {\r\n                            ShowStatsMessage(i);\r\n                            beat_one=true;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        // Jump Drop\r\n        if ( stat_goals[i].goaltype == CRCD(0x7e064ad0,\"olliedrop\") )\r\n        {\r\n            if (!stat_goals[i].complete)\r\n            {\r\n                if (!stat_goals[i].shown)\r\n                {\r\n                    if ( jump_set == 2 )\r\n                    {\r\n                        float value = float(stat_goals[i].value);\r\n                        float jump_low = 1;\r\n                        \r\n                        jump_low = ( jump_start_pos[1] - jump_end_pos[1] );\r\n                        \r\n                        if ( jump_low >= (12*value) ) // value is in feet, jump_low is in inches\r\n                        {\r\n                            ShowStatsMessage(i);\r\n                            beat_one=true;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        // Num Fliptricks\r\n        if ( stat_goals[i].goaltype == CRCD(0x364e8c16,\"numfliptricks\") )\r\n        {\r\n            if (!stat_goals[i].complete)\r\n            {\r\n                if (!stat_goals[i].shown)\r\n                {\r\n                    int value = (stat_goals[i].value);\r\n                    \r\n                    if ( num_fliptricks >= value )\r\n                    {\r\n                        ShowStatsMessage(i);\r\n                        beat_one=true;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        // Num grabtricks\r\n        if ( stat_goals[i].goaltype == CRCD(0x68703ae9,\"numgrabs\") )\r\n        {\r\n            if (!stat_goals[i].complete)\r\n            {\r\n                if (!stat_goals[i].shown)\r\n                {\r\n                    int value = (stat_goals[i].value);\r\n                    \r\n                    if ( num_grabtricks >= value )\r\n                    {\r\n                        ShowStatsMessage(i);\r\n                        beat_one=true;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        // String Counter\r\n        if ( stat_goals[i].goaltype == CRCD(0x9068b4e5,\"stringcount\") )\r\n        {\r\n            if (!stat_goals[i].complete)\r\n            {\r\n                if (!stat_goals[i].shown)\r\n                {   \r\n                    int value = (stat_goals[i].value);\r\n                    const char* string = (stat_goals[i].v_string);\r\n                    //printf(\"%s\", string );\r\n\r\n                    if ( pScore->CountStringMatches(string) >= value )\r\n                    {\r\n                        ShowStatsMessage(i);\r\n                        beat_one=true;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        // Trick Counter\r\n        if ( stat_goals[i].goaltype == CRCD(0x69b0f836,\"trickcount\") )\r\n        {\r\n            if (!stat_goals[i].complete)\r\n            {\r\n                if (!stat_goals[i].shown)\r\n                {   \r\n                    int value = (stat_goals[i].value);\r\n                    uint32 trick = (stat_goals[i].trick);\r\n                    int num_taps = (stat_goals[i].taps);\r\n                    \r\n                    /*int tricktimes = pScore->GetCurrentNumberOfOccurrencesByName(trick, 0, false, num_taps);\r\n                    if ( tricktimes > 0)\r\n                    {\r\n                        printf(\"CountTrickMatches = %i\\n\", tricktimes );\r\n                    }*/\r\n                    \r\n                    if ( pScore->GetCurrentNumberOfOccurrencesByName(trick, 0, false, num_taps) >= value )\r\n                    {\r\n                        ShowStatsMessage(i);\r\n                        beat_one=true;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }\r\n    \r\n    if (beat_one)\r\n    {\r\n        Script::RunScript( Script::GenerateCRC( \"showed_stat_message_sound\" ) );\r\n    }\r\n\r\n    vert_spin = 0;\r\n    last_event = new_event;\r\n    last_score = current_score;\r\n    last_base = current_base;\r\n    last_mult = current_mult;\r\n    \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CStatsManagerComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n/*\r\n        // @script | DoSomething | does some functionality\r\n\t\tcase 0xbb4ad101:\t\t// DoSomething\r\n\t\t\tDoSomething();\r\n\t\t\tbreak;\r\n\r\n        // @script | ValueIsTrue | returns a boolean value\r\n\t\tcase 0x769260f7:\t\t// ValueIsTrue\r\n\t\t{\r\n\t\t\treturn ValueIsTrue() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\tbreak;\r\n*/\r\n        \r\n        // @script | StatsManager_ReInit | reinitializes stats manger. used when starting new career/story\r\n        case 0x82ce30ce: // StatsManager_ReInit\r\n\t\t{\r\n\t\t\tRefreshFromStructure( pParams );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n        // @script | StatsManager_Reset | resets stats manger. used when reinitializing skater\r\n        case 0x57879c96: //StatsManager_Reset\r\n\t\t{\r\n\t\t\tBail();\r\n\t\t}\r\n\t\tbreak;\r\n\r\n        // @script | StatsManager_ActivateGoals | activates stats goals\r\n        case 0xee59073c: // StatsManager_ActivateGoals\r\n\t\t{\r\n\t\t\tstat_goals_on = true;\r\n            Script::RunScript( Script::GenerateCRC( \"console_unhide\" ) );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n        // @script | StatsManager_DeactivateGoals | deactivates stats goals\r\n        case 0xf1745991: // StatsManager_DeactivateGoals\r\n\t\t{\r\n\t\t\tstat_goals_on = false;\r\n            Script::RunScript( Script::GenerateCRC( \"console_hide\" ) );\r\n\t\t}\r\n\t\tbreak;\r\n        \r\n        // @script | StatsManager_GetGoalStatus | returns status of stats goal with provided index\r\n        case 0x78e7d855: // StatsManager_GetGoalStatus\r\n        {\r\n            int index;\r\n            int status;\r\n            pParams->GetInteger( NONAME, &index, Script::ASSERT );\r\n            status = stat_goals[index].complete;\r\n            pScript->GetParams()->AddInteger( CRCD(0x84ff9ae3,\"status\"), status );\r\n        }\r\n        break;\r\n\r\n        // @script | StatsManager_UnlockAmGoals | unlocks amateur stats goals\r\n        case 0xb341b5a5: // StatsManager_UnlockAmGoals\r\n        {\r\n            for (int i=0; i < NUM_STATS_GOALS; i++)\r\n            {\r\n                if ( stat_goals[i].complete == 2 )\r\n                {\r\n                    stat_goals[i].complete = 0;\r\n                }\r\n            }\r\n        }\r\n        break;\r\n\r\n        // @script | StatsManager_UnlockProGoals | unlocks pro stats goals\r\n        case 0xb7fac894: // StatsManager_UnlockProGoals\r\n        {\r\n            for (int i=0; i < NUM_STATS_GOALS; i++)\r\n            {\r\n                if ( stat_goals[i].complete == 3 )\r\n                {\r\n                    stat_goals[i].complete = 0;\r\n                }\r\n            }\r\n        }\r\n        break;\r\n\r\n        default:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStatsManagerComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CStatsManagerComponent::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\t/*\tExample:\r\n\tp_info->AddInteger(CRCD(0x7cf2a233,\"m_never_suspend\"),m_never_suspend);\r\n\tp_info->AddFloat(CRCD(0x519ab8e0,\"m_suspend_distance\"),m_suspend_distance);\r\n\t*/\r\n\t\r\n// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CStatsManagerComponent::SetSkater( CSkater* p_skater )\r\n{\r\n\tmpSkater = p_skater;\r\n\t\r\n\tif( p_skater == NULL )\r\n\t{\r\n\t\tmpSkaterStateComponent = NULL;\r\n        mpSkaterPhysicsControlComponent = NULL;\r\n\t\t//mpSkaterPhysicsControlComponent = NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmpSkaterStateComponent = GetSkaterStateComponentFromObject(mpSkater);\r\n\t\tDbg_Assert(mpSkaterStateComponent);\r\n\r\n        mpSkaterPhysicsControlComponent = GetSkaterPhysicsControlComponentFromObject(mpSkater);\r\n\t\tDbg_Assert(mpSkaterPhysicsControlComponent);\r\n\t\t\r\n\t\t// non-local clients will not have a CSkaterPhysicsControlComponent\r\n\t\t//mpSkaterPhysicsControlComponent = GetSkaterPhysicsControlComponentFromObject(mpSkater);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CStatsManagerComponent::SetTrick( char *trick_name, int base_score, bool is_switch )\r\n{\r\n    if ( base_score != last_base_score )\r\n    {\r\n        last_trick_name = trick_name;\r\n//        printf(\"trick_name = %s\\n\", trick_name );\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStatsManagerComponent::CheckTimedRecord( uint32 checksum, float time, bool final )\r\n{\r\n    if ( !(Mdl::Skate::Instance()->GetGameMode()->IsTrue( CRCD(0x1ded1ea4,\"is_career\") )) )\r\n    {\r\n        return;\r\n    }\r\n\r\n    if ( !stat_goals_on )\r\n    {\r\n        return;\r\n    }\r\n    \r\n    bool beat_one = false;\r\n    for (int i=0; i < NUM_STATS_GOALS; i++)\r\n    {\r\n        if (!stat_goals[i].complete)\r\n        {\r\n            if (!stat_goals[i].shown)\r\n            {\r\n                int value = stat_goals[i].value;\r\n\r\n                switch ( checksum )\r\n                {\r\n                    case 0x0ac90769: //\"noseManual\"\r\n                    case 0xef24413b: //\"manual\"\r\n                        if ( stat_goals[i].goaltype == CRCD(0xd9ffc141,\"manualtime\") )\r\n                        {\r\n                            if ( time >= value )\r\n                            {\r\n                                ShowStatsMessage(i);\r\n                                beat_one=true;\r\n                            }\r\n                        }\r\n                        break;\r\n                    case 0x255ed86f: //\"grind\"\r\n                    case 0x8d10119d: //\"slide\"\r\n                        if ( stat_goals[i].goaltype == CRCD(0xc1336019,\"grindtime\") )\r\n                        {\r\n                            if ( time >= value )\r\n                            {\r\n                                ShowStatsMessage(i);\r\n                                beat_one=true;\r\n                            }\r\n                        }\r\n                        break;\r\n                    case 0xa549b57b: //\"lip\"\r\n                        if ( stat_goals[i].goaltype == CRCD(0xb67cff14,\"liptime\") )\r\n                        {\r\n                            if ( time >= value )\r\n                            {\r\n                                ShowStatsMessage(i);\r\n                                beat_one=true;\r\n                            }\r\n                        }\r\n                        break;\r\n                    default:\r\n                        break;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    if (beat_one)\r\n    {\r\n        Script::RunScript( Script::GenerateCRC( \"showed_stat_message_sound\" ) );\r\n    }\r\n    \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n                                                                    \r\nvoid CStatsManagerComponent::Bail()\r\n{\r\n    Script::RunScript( Script::GenerateCRC( \"stats_message_bail\" ) );\r\n\r\n    for (int i=0; i < NUM_STATS_GOALS; i++)\r\n    {\r\n        if (!stat_goals[i].complete)\r\n        {\r\n            if (stat_goals[i].shown)\r\n            {\r\n                stat_goals[i].shown = false;\r\n            }\r\n        }\r\n    }\r\n\r\n    vert_set = 0;\r\n    jump_set = 0;\r\n    num_fliptricks=0;\r\n    num_grabtricks=0;\r\n    jump_start_pos = jump_end_pos;\r\n    vert_start_pos = vert_end_pos;\r\n    \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStatsManagerComponent::Land()\r\n{\r\n    if ( !(Mdl::Skate::Instance()->GetGameMode()->IsTrue( CRCD(0x1ded1ea4,\"is_career\") )) )\r\n    {\r\n        return;\r\n    }\r\n\r\n    if ( !stat_goals_on )\r\n    {\r\n        return;\r\n    }\r\n    \r\n    Script::CStruct* p_params = new Script::CStruct();\r\n\r\n    Obj::CSkaterProfile* pProfile = Mdl::Skate::Instance()->GetProfile( 0 );\r\n\r\n    uint32 stat;\r\n    bool cleared=false;\r\n    \r\n    for (int i=0; i < NUM_STATS_GOALS; i++)\r\n    {\r\n        if (!stat_goals[i].complete)\r\n        {\r\n            if (stat_goals[i].shown)\r\n            {\r\n                if (!cleared)\r\n                {\r\n                    // clear current messages\r\n                    Script::RunScript( Script::GenerateCRC( \"stats_message_land\" ) );\r\n                    cleared = true;\r\n                }\r\n\r\n                // set goal as complete\r\n                stat_goals[i].complete = 1;\r\n\r\n                // increase proper stat\r\n                stat = ( stat_goals[i].stattype );\r\n\r\n                switch ( stat )\r\n                {\r\n                    case 0xb1fc0722: //\"manual_balance\"\r\n                        p_params->AddString( \"text\", Script::GetString( CRCD(0x69f2596,\"manual_increase_text\") ) );\r\n                        break;\r\n                    case 0xf73a13e3: //\"rail_balance\"\r\n                        p_params->AddString( \"text\", Script::GetString( CRCD(0x6e7a996d,\"rail_increase_text\") ) );\r\n                        break;\r\n                    case 0xae798769: //\"lip_balance\"\r\n                        p_params->AddString( \"text\", Script::GetString( CRCD(0x1f1bcdef,\"lip_increase_text\") ) );\r\n                        break;\r\n                    case 0xf0d90109: //\"speed\"\r\n                        p_params->AddString( \"text\", Script::GetString( CRCD(0x1686ebd3,\"speed_increase_text\") ) );\r\n                        break;\r\n                    case 0x9b65d7b8: //\"ollie\"\r\n                        p_params->AddString( \"text\", Script::GetString( CRCD(0xa8386951,\"ollie_increase_text\") ) );\r\n                        break;\r\n                    case 0x439f4704: //\"air\"\r\n                        p_params->AddString( \"text\", Script::GetString( CRCD(0xa523df6c,\"air_increase_text\") ) );\r\n                        break;\r\n                    case 0x6dcb497c: //\"flip_speed\"\r\n                        p_params->AddString( \"text\", Script::GetString( CRCD(0x585887ca,\"flip_increase_text\") ) );\r\n                        break;\r\n                    case 0x9016b4e7: //\"switch\"\r\n                        p_params->AddString( \"text\", Script::GetString( CRCD(0x1a6b74ea,\"switch_increase_text\") ) );\r\n                        break;\r\n                    case 0xedf5db70: //\"spin\"\r\n                        p_params->AddString( \"text\", Script::GetString( CRCD(0xb959cc23,\"spin_increase_text\") ) );\r\n                        break;\r\n                    case 0xaf895b3f: //\"run\"\r\n                        p_params->AddString( \"text\", Script::GetString( CRCD(0xa17ac668,\"run_increase_text\") ) );\r\n                        break;\r\n                    default:\r\n                        break;\r\n                }\r\n\r\n                // display message\r\n                p_params->AddInteger( \"got_it\", 1 );\r\n                Script::RunScript( Script::GenerateCRC( \"show_stats_message\" ), p_params );\r\n                \r\n                if ( bump_stats )\r\n                {\r\n                    // update skater stats\r\n                    int value = ( pProfile->GetStatValue( stat ) + 1 );\r\n                \tpProfile->SetPropertyValue( stat, value );\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    if (cleared)\r\n    {\r\n        printf(\"updating skater stats\\n\");\r\n        mpSkater->UpdateStats(pProfile);\r\n        \r\n        if (!showed_info)\r\n        {\r\n            Game::CGoalManager* pGoalManager = Game::GetGoalManager();\r\n            Dbg_Assert( pGoalManager );\r\n            if ( pGoalManager->CanStartGoal() )\r\n            {\r\n                Script::RunScript( Script::GenerateCRC( \"beat_first_stat_goal\" ) );\r\n                showed_info = true;\r\n            }\r\n        }\r\n        Script::RunScript( Script::GenerateCRC( \"stat_play_win_sound\" ) );\r\n    }\r\n    \r\n    delete p_params;\r\n    num_fliptricks=0;\r\n    num_grabtricks=0;\r\n    \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStatsManagerComponent::ShowStatsMessage( int index )\r\n{\r\n    Script::CStruct* p_params = new Script::CStruct();\r\n    p_params->AddString( \"string\", stat_goals[index].text );\r\n    p_params->AddInteger( \"value\", stat_goals[index].value );\r\n    if ( stat_goals[index].v_string )\r\n    {\r\n        p_params->AddString( \"vstring\", stat_goals[index].v_string );\r\n    }\r\n    p_params->AddInteger( \"index\", index );\r\n    \r\n    Script::RunScript( Script::GenerateCRC( \"show_stats_message\" ), p_params );\r\n    stat_goals[index].shown = true;\r\n    delete p_params;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStatsManagerComponent::SetSpin( float angle )\r\n{\r\n    //printf(\"angle = %f\\n\", angle);\r\n    vert_spin = angle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStatsManagerComponent::SetTrickType( uint32 type )\r\n{\r\n    switch ( type )\r\n    {\r\n        case 0xba15fc7f: //\"fliptrick\"\r\n            num_fliptricks++;\r\n//            printf(\"num_fliptricks = %i\\n\", num_fliptricks );\r\n            break;\r\n        case 0xb9ae26d2: //\"grabtrick\"\r\n            num_grabtricks++;\r\n//            printf(\"num_grabtricks = %i\\n\", num_grabtricks );\r\n            break;\r\n        default:\r\n            break;\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStatsManagerComponent::StatGoalsOn()\r\n{\r\n    stat_goals_on = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStatsManagerComponent::StatGoalsOff()\r\n{\r\n    stat_goals_on = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CStatsManagerComponent::StatGoalGetStatus(int index)\r\n{\r\n    return (stat_goals[index].complete);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStatsManagerComponent::StatGoalSetStatus(int index, int value)\r\n{\r\n    stat_goals[index].complete = value;\r\n    if ( value == 1 )\r\n    {\r\n        // This means we must be loading stats, so don't show the first stat message!\r\n        showed_info = true;\r\n    }\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/StatsManagerComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       StatsManagerComponent.h\r\n//* OWNER:          Zac Drake\r\n//* CREATION DATE:  5/29/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_STATSMANAGERCOMPONENT_H__\r\n#define __COMPONENTS_STATSMANAGERCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/modules/skate/score.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n// Replace this with the CRCD of the component you are adding\r\n#define\t\tCRC_STATSMANAGER CRCD(0x4ff8dac6,\"StatsManager\")\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or \r\n//  given an object\t\t\t\t \r\n#define\t\tGetStatsManagerComponent() ((Obj::CStatsManagerComponent*)GetComponent(CRC_STATSMANAGER))\r\n#define\t\tGetStatsManagerComponentFromObject(pObj) ((Obj::CStatsManagerComponent*)(pObj)->GetComponent(CRC_STATSMANAGER))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n    class CSkaterStateComponent;\r\n    class CSkaterPhysicsControlComponent;\r\n\r\nconst static int NUM_STATS_GOALS=70;\r\n\r\nstruct stat_goal {\r\n    uint32 goaltype;\r\n    uint32 stattype;\r\n    int value;\r\n    bool shown;\r\n    int complete;\r\n    const char* text;\r\n    const char* v_string;\r\n    uint32 trick;\r\n    int taps;\r\n};\r\n\r\n\r\nclass CStatsManagerComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CStatsManagerComponent();\r\n    virtual ~CStatsManagerComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n\t//virtual\tvoid \t\t\t\t\tFinalize();\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n    void\t\t\t\t\t\t\tSetSkater( CSkater* p_skater );\r\n\r\n    void\t\t\t\t\t\t\tSetTrick( char *trick_name, int base_score, bool is_switch );\r\n\r\n    void                            CheckTimedRecord( uint32 checksum, float time, bool final );\r\n    void                            Bail();\r\n    void                            Land();\r\n    void                            SetSpin( float angle );\r\n    void                            SetTrickType( uint32 type );\r\n    \r\n    int                             StatGoalGetStatus(int index);\r\n    void                            StatGoalSetStatus(int index, int value);\r\n\r\n    void                            StatGoalsOn();\r\n    void                            StatGoalsOff();\r\n    \r\n    bool                            m_restarted_this_frame;\r\n    \r\nprivate:\r\n    \r\n    stat_goal                       stat_goals[NUM_STATS_GOALS];\r\n    bool                            stat_goals_on;\r\n    bool                            bump_stats;\r\n    bool                            showed_info;\r\n\r\n    int                             current_score;\r\n    int                             last_score;\r\n    \r\n    int                             current_base;\r\n    int                             last_base;\r\n\r\n    int                             current_mult;\r\n    int                             last_mult;\r\n\r\n    char                            *last_trick_name;\r\n    int                             last_base_score;\r\n\r\n    int                             dif_level;\r\n\r\n    uint32                          new_event;\r\n    uint32                          last_event;\r\n\r\n    Mth::Vector                     vert_start_pos;\r\n    Mth::Vector                     vert_end_pos;\r\n    int                             vert_start_base;\r\n    int                             vert_start_mult;\r\n    int                             vert_score;\r\n    int                             vert_set;\r\n    float                           vert_height;\r\n\r\n    float                           vert_spin;\r\n\r\n    Mth::Vector                     jump_start_pos;\r\n    Mth::Vector                     jump_end_pos;\r\n    int                             jump_set;\r\n\r\n    int                             num_fliptricks;\r\n    int                             num_grabtricks;\r\n\r\n    int                             air_combo_score;\r\n\r\n    CSkater*\t\t\t\t\t\tmpSkater;\r\n    CSkaterStateComponent*\t\t\tmpSkaterStateComponent;\r\n    CSkaterPhysicsControlComponent* mpSkaterPhysicsControlComponent;\r\n    //CSkaterScoreComponent*\t\t\tmpSkaterScoreComponent;\r\n    CSkaterCorePhysicsComponent*\tmpSkaterCorePhysicsComponent;\r\n\r\n    void                            ShowStatsMessage( int index );\r\n    \r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/StreamComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       StreamComponent.cpp\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ???\r\n//****************************************************************************\r\n\r\n// The CStreamComponent class is an skeletal version of a component\r\n// It is intended that you use this as the basis for creating new\r\n// components.  \r\n// To create a new component called \"Watch\", (CWatchComponent):\r\n//  - copy streamcomponent.cpp/.h to watchcomponent.cpp/.h\r\n//  - in both files, search and replace \"Stream\" with \"Watch\", preserving the case\r\n//  - in WatchComponent.h, update the CRCD value of CRC_WATCH\r\n//  - in CompositeObjectManager.cpp, in the CCompositeObjectManager constructor, add:\r\n//\t\t  \tRegisterComponent(CRC_WATCH,\t\t\tCWatchComponent::s_create); \r\n//  - and add the include of the header\r\n//\t\t\t#include <gel/components/watchcomponent.h> \r\n//  - Add it to build\\gel.mkf, like:\r\n//          $(NGEL)/components/WatchComponent.cpp\\\r\n//  - Fill in the OWNER (yourself) and the CREATION DATE (today's date) in the .cpp and the .h files\r\n//\t- Insert code as needed and remove generic comments\r\n//  - remove these comments\r\n//  - add comments specfic to the component, explaining its usage\r\n\r\n#include <gel/components/streamcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <gel/music/music.h>\r\n\r\n#include <gfx/camera.h>\r\n\r\n// TODO:  Refactor this - \r\n#include <sk/objects/emitter.h>\r\n#include <sk/objects/proxim.h>\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\n\r\nCBaseComponent* CStreamComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CStreamComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCStreamComponent::CStreamComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_STREAM );\r\n\tmp_emitter = NULL;\r\n\tmp_proxim_node = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCStreamComponent::~CStreamComponent()\r\n{\r\n\t// If there is a streaming sound attached, remove it.\r\n\tint i;\r\n\tfor( i = 0; i < MAX_STREAMS_PER_OBJECT; i++ )\r\n\t{\r\n\t\tif( mStreamingID[i] )\r\n\t\t{\r\n\t\t\tPcm::StopStreamFromID( mStreamingID[i] );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CStreamComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tuint32 proxim_node_checksum;\r\n\r\n\tif (pParams->GetChecksum(\"ProximNode\", &proxim_node_checksum))\r\n\t{\r\n\t\t//Dbg_Message(\"StreamComponent: Looking for ProximNode %s\", Script::FindChecksumName(proxim_node_checksum));\r\n\t\tmp_proxim_node = CProximManager::sGetNode(proxim_node_checksum);\r\n\t\t//if (mp_proxim_node)\r\n\t\t//{\r\n\t\t//\tDbg_Message(\"Found ProximNode %s\", Script::FindChecksumName(mp_proxim_node->m_name));\r\n\t\t//}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CStreamComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calline InitFromStructure()\r\n\t// but if that does not handle it, then will need to write a specific \r\n\t// function here. \r\n\t// The user might only want to update a single field in the structure\r\n\t// and we don't want to be asserting becasue everything is missing \r\n\t\r\n\tInitFromStructure(pParams);\r\n\r\n\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CStreamComponent::Update()\r\n{\r\n\t// Doing nothing, so tell code to do nothing next time around\r\n\tSuspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CStreamComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\r\n\t\tcase 0xdb05a233:  // Obj_PlayStream\r\n\t\t\tPlayStream( pParams, pScript );\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase 0xa738aeb8:  // Obj_StopStream\r\n\t\t{\r\n\t\t\t// eventually want to be able to specify channel on here...\r\n\t\t\tint i;\r\n\t\t\tfor ( i = 0; i < MAX_STREAMS_PER_OBJECT; i++ )\r\n\t\t\t{\r\n\t\t\t\tif ( mStreamingID[ i ] )\r\n\t\t\t\t{\r\n\t\t\t\t\tPcm::StopStreamFromID( mStreamingID[ i ] );\r\n\t\t\t\t\tmStreamingID[ i ] = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CStreamComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to C......Component::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\t/*\tExample:\r\n\tp_info->AddInteger(\"m_never_suspend\",m_never_suspend);\r\n\tp_info->AddFloat(\"m_suspend_distance\",m_suspend_distance);\r\n\t*/\r\n\t\r\n// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector\tCStreamComponent::GetClosestEmitterPos( Gfx::Camera *pCamera )\r\n{\r\n\tif (mp_emitter && pCamera)\r\n\t{\r\n\t\treturn mp_emitter->GetClosestPoint(pCamera->GetPos());\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn GetObject()->m_pos;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCStreamComponent::GetClosestDropoffPos( Gfx::Camera *pCamera, Mth::Vector & dropoff_pos )\r\n{\r\n\tif (pCamera && mp_proxim_node)\r\n\t{\r\n\t\tdropoff_pos = mp_proxim_node->GetClosestIntersectionPoint(pCamera->GetPos());\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n// Returns 0 if no stream slots empty, or the index + 1\r\nint CStreamComponent::StreamSlotEmpty( void )\r\n{\r\n\tint j;\r\n\tfor ( j = 0; j < MAX_STREAMS_PER_OBJECT; j++ )\r\n\t{\r\n\t\tif ( !mStreamingID[ j ] )\r\n\t\t{\r\n\t\t\treturn ( j + 1 );\r\n\t\t}\r\n\t}\r\n\treturn ( 0 );\r\n}\r\n\r\n\r\nbool CStreamComponent::PlayStream( Script::CScriptStructure *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tif ( !StreamSlotEmpty( ) )\r\n\t{\r\n\t\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tprintf (\"Playing too many streams on object\\n\");\r\n\t\t#endif\r\n\t\t\t\t\t\t\t\t\t\t  \r\n\t\treturn ( false ); // can only play 3 stream on each object max!!!\r\n\t}\r\n\tuint32 streamChecksum;\r\n\tuint32 emitterChecksum;\r\n\tuint32 dropoffFuncChecksum;\r\n\tuint32 id = 0;\r\n\tfloat dropoff = 0.0f;\r\n\tfloat volume = 100.0f;\r\n\tfloat pitch = 100.0f;\r\n\tint priority = STREAM_DEFAULT_PRIORITY;\r\n\tEDropoffFunc dropoffFunction = DROPOFF_FUNC_STANDARD;\r\n\tpParams->GetFloat( 0xf6a36814, &volume ); // \"vol\"\r\n\tpParams->GetFloat( 0xd8604126, &pitch ); // \"pitch\"\r\n\tpParams->GetInteger( 0x9d5923d8, &priority ); // priority\r\n\tpParams->GetChecksum( 0x40c698af, &id ); // id\r\n\tif ( pParams->GetFloat( 0xff2020ec, &dropoff ) ) // \"dropoff\"\r\n\t{\r\n\t\tdropoff = FEET_TO_INCHES( dropoff );\r\n\t}\r\n\tif ( pParams->GetChecksum( 0xc6ac50a, &dropoffFuncChecksum ) ) // \"dropoff_function\"\r\n\t{\r\n\t\tdropoffFunction = Sfx::GetDropoffFunctionFromChecksum( dropoffFuncChecksum );\r\n\t}\r\n\tif (pParams->GetChecksum( 0x8a7132ce, &emitterChecksum ) ) // \"emitter\"\r\n\t{\r\n\t\tmp_emitter = CEmitterManager::sGetEmitter(emitterChecksum);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_emitter = NULL;\r\n\t}\r\n\tif ( pParams->GetChecksum( NONAME, &streamChecksum ) )\r\n\t{\r\n\t\tint use_pos_info = 1;\r\n\t\tpParams->GetInteger( \"use_pos_info\", &use_pos_info, Script::NO_ASSERT );\r\n\t\t//printf (\"Playing stream 0x%x on object %s\\n\",streamChecksum,Script::FindChecksumName(GetObject()->GetID()));\r\n\t\treturn ( Pcm::PlayStreamFromObject( this, streamChecksum, dropoff, volume, pitch, priority, use_pos_info, dropoffFunction, id ) );\r\n\t}\r\n\treturn ( false );\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/StreamComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       StreamComponent.h\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ??/??/??\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_STREAMCOMPONENT_H__\r\n#define __COMPONENTS_STREAMCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_STREAM CRCD(0xf1641e3,\"stream\")\r\n#define\t\tGetStreamComponent() ((Obj::CStreamComponent*)GetComponent(CRC_STREAM))\r\n#define\t\tGetStreamComponentFromObject(pObj) ((Obj::CStreamComponent*)(pObj)->GetComponent(CRC_STREAM))\r\n\r\n#define MAX_STREAMS_PER_OBJECT\t3\r\n\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Gfx\r\n{\r\n\tclass\tCamera;\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\t// Forward declarations\r\n\tclass CEmitterObject;\r\n\tclass CProximNode;\r\n\r\nclass CStreamComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CStreamComponent();\r\n    virtual ~CStreamComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tMth::Vector\t\t\t\t\t\tGetClosestEmitterPos( Gfx::Camera *pCamera );\r\n\r\n\tbool\t\t\t\t\t\t\tHasProximNode() const { return mp_proxim_node != NULL; }\r\n\tvoid\t\t\t\t\t\t\tClearProximNode() { mp_proxim_node = NULL; }\t\t\t\t\t\t\t\t// Needed for early proxim node cleanup\r\n\tbool\t\t\t\t\t\t\tGetClosestDropoffPos( Gfx::Camera *pCamera, Mth::Vector & dropoff_pos );\t// returns true if position defined\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\n\r\npublic:\r\n\t// PUBLIC FOR NOW!!!!\r\n\tuint32\t\tmStreamingID[ MAX_STREAMS_PER_OBJECT ];\r\n\r\n\t\r\nprivate:\t\r\n\tbool\t\tPlayStream( Script::CStruct *pParams, Script::CScript *pScript );\r\n\t// if this is non-zero, the object has streaming sound from the CD attached to it.\r\n\t// it is cleared and set in music.cpp.\r\n\t// Returns 0 if no stream slots empty, or the index + 1\r\n\tint\t\t\tStreamSlotEmpty();\r\n\r\n\tCEmitterObject *mp_emitter;\r\n\tCProximNode *\tmp_proxim_node;\r\n\r\n// End of Stream stuff\r\n////////////////////////////////////////////\r\n\t\r\n\t\r\n\t\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/SuspendComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SuspendComponent.cpp\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ??/??/??\r\n//****************************************************************************\r\n\r\n#include <gel/components/suspendcomponent.h>\r\n\r\n#include <gel/components/modelcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/mainloop.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/nxviewman.h>\r\n\r\n#include <sk/modules/skate/skate.h>\t\t// <<<<<<<<<<<   GET RID OF THIS, use the NX camera's directly\r\n#include <sk/objects/skatercareer.h>\t// <<<<<<<<<<<   GET RID OF THIS TOO!\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// This static function is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\nCBaseComponent* CSuspendComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSuspendComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// And this one is the optional \"register\" function that provides on-time initilization\r\n// usually of a component manager\r\nvoid\tCSuspendComponent::s_register()\r\n{\r\n\t// Create and initilize the manager\r\n\tSuspendManager::Manager::Create();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSuspendComponent::CSuspendComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SUSPEND );\r\n\t\r\n\tm_suspend_distance=Script::GetFloat(CRCD(0xad501995,\"DefaultMovingObjectSuspendDistance\")) * 12.0f;\r\n\tm_suspend_distance_squared=m_suspend_distance*m_suspend_distance;\r\n\tm_never_suspend=true;\r\n\tm_no_suspend_count = 3; // default to not allowing suspensions in the first 3 frames\r\n\r\n\t// Mick: We don't want to display things before they have done at least one frame of\r\n\t// animation, because they start out in their default position (the \"Blair Witch\" position)\r\n\t// so, we set a default number of animations that we MUST do before we are allowed to\r\n\t// not animate.\r\n\t// This also overrides the SkipLogic test, so we do a frame of logic\r\n\t// which fixes problems where something is moving to the first node of a path\r\n\t\r\n\t// Since the first couple of frames of the game are hidden behind the loading screen\r\n\t// we don't need to worry about framerate glitched due to the large \r\n\t// number of objects being created at start.\t\r\n\t\r\n\t// I Initially had this at 1, which seemed fine\r\n\t// however, when you change levels, it needs to be at 3\r\n\t// I'm not sure why - it might be good to look into this later.\r\n\tm_initial_animations = 3;\t \t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSuspendComponent::~CSuspendComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSuspendComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// anything that has a suspend distance will allow suspension\r\n\tif (pParams->GetFloat(CRCD(0xe4279ba2,\"SuspendDistance\"),&m_suspend_distance))\r\n\t{\r\n\t\tif (m_suspend_distance == 0.0f)\r\n\t\t{\r\n\t\t\t// if zero suspend dist, then try to get it from lod_dist1\r\n\t\t\tif (!pParams->GetFloat(CRCD(0x4eedfae7,\"Lod_dist1\"),&m_suspend_distance))\r\n\t\t\t{\r\n\t\t\t\t// else get the default distance\r\n\t\t\t\tm_suspend_distance=Script::GetFloat(CRCD(0xad501995,\"DefaultMovingObjectSuspendDistance\"));\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t\t// if we've got a suspend distance, then convert it into inches\r\n\t\tm_suspend_distance *= 12.0f;\r\n\t\tm_suspend_distance_squared=m_suspend_distance*m_suspend_distance;\r\n\t\tm_never_suspend=false;\r\n\t}\r\n\t\r\n\t// suspension can be overridden by the \"NeverSuspend\" flag\r\n\tif (pParams->ContainsFlag(CRCD(0xcb839dc1,\"NeverSuspend\")))\r\n\t{\r\n\t\tm_never_suspend=true;\r\n\t}\r\n\r\n\t// Get the LOD distances from the node\r\n\tif (Script::GetInt(CRCD(0x95edc6f6,\"NoLOD\"),false))\t\t\t\t\t \r\n\t{\r\n\t\tm_lod_dist[0] = 1000000;\r\n\t\tm_lod_dist[1] = 1000001;\r\n\t\tm_lod_dist[2] = 1000002;  // Note, this is used as a magic number to turn off the high level culling\r\n\t\tm_lod_dist[3] = 1000003;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Assert( pParams );\r\n\t\tm_lod_dist[0] = 50;\r\n\t\tm_lod_dist[2] = 1000001;\r\n\t\tm_lod_dist[3] = 1000002;\r\n\t\tpParams->GetFloat(CRCD(0x4eedfae7,\"lod_dist1\"),&m_lod_dist[0]);\r\n\t\tm_lod_dist[1] = m_lod_dist[0] + 75;\t\t\t\t\t\t// default for LOD dist 2 is 75 feet beyond 1\r\n\t\tpParams->GetFloat(CRCD(0xd7e4ab5d,\"lod_dist2\"),&m_lod_dist[1]);\r\n\t\tpParams->GetFloat(CRCD(0xa0e39bcb,\"lod_dist3\"),&m_lod_dist[2]);\r\n\t\tpParams->GetFloat(CRCD(0x3e870e68,\"lod_dist4\"),&m_lod_dist[3]);\r\n\t\t// LOD dist is in feet\r\n\t\tm_lod_dist[0] *= 12.0f;\r\n\t\tm_lod_dist[1] *= 12.0f;\r\n\t\tm_lod_dist[2] *= 12.0f;\r\n\t\tm_lod_dist[3] *= 12.0f;\r\n\t\tif ( m_lod_dist[0]>=m_lod_dist[1] )\r\n\t\t{\r\n\t\t\tScript::PrintContents( pParams );\r\n\t\t\tDbg_MsgAssert(0,(\"lod_dist1 (%f) >= lod_dist2 (%f) in node\",m_lod_dist[0],m_lod_dist[1]));\r\n\t\t}\r\n\t\tif ( m_lod_dist[1]>=m_lod_dist[2] )\r\n\t\t{\r\n\t\t\tScript::PrintContents( pParams );\r\n\t\t\tDbg_MsgAssert(0,(\"lod_dist2 (%f) >= lod_dist3 (%f) in node\",m_lod_dist[1],m_lod_dist[2]));\r\n\t\t}\r\n\t\tif ( m_lod_dist[2]>=m_lod_dist[3] )\r\n\t\t{\r\n\t\t\tScript::PrintContents( pParams );\r\n\t\t\tDbg_MsgAssert(0,(\"lod_dist3 (%f) >= lod_dist4 (%f) in node\",m_lod_dist[2],m_lod_dist[3]));\r\n\t\t}\r\n\r\n#if defined( __PLAT_XBOX__ ) || defined( __PLAT_NGC__ )\r\n\t\t// Some platform specific changes to the LOD stuff\r\n\t\tm_lod_dist[0]\t\t*= Script::GetFloat( 0xd3d072f9 /* LOD0DistanceMultiplier */ );\r\n\t\tm_lod_dist[1]\t\t*= Script::GetFloat( 0x0432f2a1 /* LOD1DistanceMultiplier */ );\r\n#endif\r\n\r\n\t}\r\n}\r\n\r\nvoid\tCSuspendComponent::Finalize()\r\n{\r\n\t// Might be NULL, if we don't have a model\r\n\tmp_model_component = GetModelComponentFromObject( GetObject() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSuspendComponent::Update()\r\n{\r\n\t// this funtion does not need to be called, so flag it as such\r\n\tCBaseComponent::Suspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent::EMemberFunctionResult CSuspendComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSuspendComponent::Suspend(bool suspend)\r\n{\r\n\t// does nothing, as we need to keep checking for unsuspension\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// returns true if we skip logic on this frame\r\n// this can be true for a number of reasons\r\n// but mostly boils down to LOD\r\nbool CSuspendComponent::SkipLogic()\r\n{\r\n\treturn m_skip_logic;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// returns true if we skip logic on this frame\r\n// this can be true for a number of reasons\r\n// but mostly boils down to LOD\r\nbool CSuspendComponent::SkipRender()\r\n{\r\n\t\t\r\n\tif ( m_camera_distance_squared > m_lod_dist[1]*m_lod_dist[1] )\r\n\t{\r\n\t\treturn true;\r\n\t}\t\r\n\t\r\n\treturn false;\r\n\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSuspendComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSuspendComponent::GetDebugInfo\"));\r\n\t// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t\r\n\r\n\tp_info->AddInteger(CRCD(0x7cf2a233,\"m_never_suspend\"),m_never_suspend);\r\n\tp_info->AddFloat(CRCD(0x519ab8e0,\"m_suspend_distance\"),m_suspend_distance);\r\n\tp_info->AddFloat(CRCD(0x340a53d3,\"distance_to_camera\"),sqrtf(m_camera_distance_squared));\r\n\tp_info->AddFloat(CRCD(0x266306b9,\"m_lod_dist_0\"),m_lod_dist[0]);\r\n\tp_info->AddFloat(CRCD(0x5164362f,\"m_lod_dist_1\"),m_lod_dist[1]);\r\n\tp_info->AddFloat(CRCD(0xc86d6795,\"m_lod_dist_2\"),m_lod_dist[2]);\r\n\tp_info->AddFloat(CRCD(0xbf6a5703,\"m_lod_dist_3\"),m_lod_dist[3]);\r\n\t\r\n\tp_info->AddInteger(CRCD(0xd9872f4b,\"SKIPLOGIC_RETURNS\"),SkipLogic());\r\n\tp_info->AddInteger(CRCD(0xd55771a6,\"SKIPRENDER_RETURNS\"),SkipRender());\r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSuspendComponent::should_animate( float *p_dist )\r\n{\r\n\tbool should_animate = true;  \r\n\r\n\t// Mick:  don't update the skeleton if it's a long way from the camera\r\n//\tGfx::Camera * p_camera = Nx::CViewportManager::sGetActiveCamera( 0 );\r\n//\tif (p_camera)\r\n\t{\r\n//\t\tMth::Vector cam_pos = p_camera->GetPos();\r\n//\t\tcam_pos = cam_pos - GetObject()->GetPos();\r\n//\t\tfloat dist = cam_pos.LengthSqr();\r\n\r\n\t\tfloat dist = m_camera_distance_squared;\r\n\r\n\t\t// Save this dist if a valid pointer was passed.\r\n\t\tif( p_dist )\r\n\t\t{\r\n\t\t\t*p_dist = dist;\r\n\t\t}\r\n\r\n\t\tif (dist > m_lod_dist[0] * m_lod_dist[0])\t\t// dist at what we stop animating\t\t\t\r\n\t\t{\r\n\t\t    should_animate = false;\r\n\t\t}\r\n\r\n\t\t// update animation intermittently\r\n\t\t// more so as distance from camera increases\r\n\r\n\t\telse\r\n\t\t{\r\n#ifndef TESTING_GUNSLINGER\r\n\r\n#if defined( __PLAT_XBOX__ ) || defined( __PLAT_NGC__ )\r\n\t\t\tfloat interleave2 = Script::GetFloat( 0xdb120fb5 /* AnimLODInterleave2 */ );\r\n\t\t\tfloat interleave4 = Script::GetFloat( 0x3271aa80 /* AnimLODInterleave4 */ );\r\n\t\t\tinterleave2 *= interleave2;\r\n\t\t\tinterleave4 *= interleave4;\r\n#else\r\n\t\t\tfloat interleave2 = 500.0f * 500.0f;\r\n\t\t\tfloat interleave4 = 800.0f * 800.0f;\r\n#endif\r\n\r\n\t\t\tm_interleave++;\r\n\t\t\tshould_animate = false;\t\t\t\t\r\n\t\t\tif (dist > interleave4)\t\t\t\t\t\t  \r\n\t\t\t{\r\n\t\t\t\t// 1 in 4 for distance 500-1000\r\n\t\t\t\tif (!(m_interleave&3))\r\n\t\t\t\t{\r\n\t\t\t\t\tshould_animate = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (dist > interleave2)\r\n\t\t\t{\r\n\t\t\t\t// 1 in 2 for 200 to 500\r\n\t\t\t\tif ((m_interleave&1))\r\n\t\t\t\t{\r\n\t\t\t\t\tshould_animate = true;\r\n\t\t\t\t}\r\n\t\t\t }\r\n\t\t\t else\r\n\t\t\t {\r\n\t\t\t\t// always animate if < 200\r\n\t\t\t\tshould_animate = true;\r\n\t\t\t }\r\n#endif\t\t\r\n\t\t}\r\n\r\n\t}\r\n\t\r\n\tif (m_initial_animations)\r\n\t{\r\n\t\tshould_animate = true;\r\n\t}\r\n\r\n\treturn should_animate;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Set Model's Active/Inactive flag based on other flags\r\n// and if the model is actually visible or not (with culling and occlusion)\r\n// and upon the load_dist2 distance  \r\nvoid CSuspendComponent::CheckModelActive()\r\n{\r\n\tif ( mp_model_component && mp_model_component->GetModel() )\r\n\t{\r\n\t\tbool active = false;\r\n\t\tif ( GetObject()->GetFlags() & CObject::vINVISIBLE )\r\n\t\t{\r\n\t\t\t// just leave it inactive\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// quick check for if the NoLOD flag is set\r\n\t\t\t// Note use of magic number (but this is only for debugging/screenshots)\r\n\t\t\tif ( m_lod_dist[2] == 1000002 )\r\n\t\t\t{\r\n\t\t\t\tactive =  true ;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// PATCH for multiple viewports\r\n\t\t\t\t// always return true, until we sort out the per-viewport visibility (which might not be needed)\t\t\t\t   \r\n\t\t\t\tif ( Nx::CViewportManager::sGetNumActiveViewports() > 1 )\r\n\t\t\t\t{\r\n\t\t\t\t\tactive = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( mp_model_component->HasRefObject() )\r\n\t\t\t\t{\r\n\t\t\t\t\t// GJ:  a ref model doesn't actually have a valid bounding sphere\r\n\t\t\t\t\t// so don't let Nx::CEngine::sIsVisible() be called...\r\n\t\t\t\t\t// (alternatively, we could fake a large bounding sphere\r\n\t\t\t\t\t// but that seems kludgy)\r\n\t\t\t\t\tactive = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tfloat dist = m_camera_distance_squared;\r\n\t\t\t\t\t\r\n\t\t\t\t\tif ( dist < m_lod_dist[1] * m_lod_dist[1] )\r\n\t\t\t\t\t{\t\t\r\n\t\t\t\t\t\tMth::Vector sphere = mp_model_component->GetModel()->GetBoundingSphere();\r\n\t\t\t\t\t\tMth::Vector position = sphere;\r\n\t\t\t\t\t\tposition[3] = 1.0f;\r\n\t\t\t\t\t\tposition *= GetObject()->GetMatrix();\r\n\t\t\t\t\t\tposition += GetObject()->GetPos();\r\n\t\t\t\t\t\tactive = ( Nx::CEngine::sIsVisible( position, sphere[3]) );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tactive = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tbool\twas_active = mp_model_component->GetModel()->GetActive();\r\n\t\tmp_model_component->GetModel()->SetActive( active);\t\t\r\n\t\t// If we've just turned the model component back on, then run the update on it\r\n\t\t// so we set it to the right place\r\n\t\t// otherwise it will be in the old place for a frame\r\n\t\t// TODO:  This all might be better IN the modelcomponent\r\n\t\tif (active && !was_active)\r\n\t\t{\r\n\t\t\tmp_model_component->Update();\t\t\t\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CSuspendComponent::GetDistanceSquaredToCamera()\r\n{\r\n\tGfx::Camera * p_camera = Nx::CViewportManager::sGetActiveCamera( 0 );\r\n\tif ( p_camera )\r\n\t{\r\n\t\treturn ( p_camera->GetPos() - GetObject()->GetPos() ).LengthSqr();\r\n\t}\r\n\r\n\tprintf( \"No active camera!\\n\" );\r\n\r\n\t// no camera?!?\r\n\treturn 0.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n\r\n// The following is the SuspendOb manager, which iterates over the suspendob components \r\n// to suspend them to whatever they are suspended to\r\n\r\nnamespace SuspendManager\r\n{\r\n// The purpose of this manager is just to update all the suspended objects, by calling\r\n// CMovingObject::SuspendToObject on all objects that have had Obj_SuspendToObject run on them.\r\n// It is a manager so that it can be given a task with a priority such that it is called\r\n// after all the objects are updated.\r\n// The reason the suspend logic cannot be done in the object update is because sometimes the parent's \r\n// update might happen after the child's, causing a frame lag. This was making the gorilla appear\r\n// behind the tram seat in the zoo when the tram was being skitched. (TT2324)\r\n\r\nDefineSingletonClass( Manager, \"Suspended object Manager\" )\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::Manager()\r\n{\r\n\tmp_task = new Tsk::Task< Manager > ( s_code, *this,\r\n\t\t\t\t\t\t\t\t\t\tTsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_LOCKED_OBJECT_MANAGER_LOGIC );\r\n\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\tmlp_manager->AddLogicTask( *mp_task );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager()\r\n{\r\n\tdelete mp_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::s_code( const Tsk::Task< Manager >& task )\r\n{\r\n\r\n\tMdl::SPreCalculatedObjectUpdateInfo* p_info = Mdl::Skate::Instance()->GetPreCalculatedObjectUpdateInfo();\r\n\t\r\n\tObj::CSuspendComponent *p_suspend_component = static_cast<Obj::CSuspendComponent*>( Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType( CRC_SUSPEND ));\r\n\twhile( p_suspend_component )\r\n\t{\r\n\r\n\t\t// Set camera dist to zero for the purposes of LOD\r\n\t\tp_suspend_component->m_camera_distance_squared = 0;\r\n\t\tp_suspend_component->m_skip_logic = false;\r\n\t\r\n\t\tif (p_suspend_component->m_no_suspend_count)\r\n\t\t{\r\n\t\t\tp_suspend_component->m_no_suspend_count--;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif ( p_info->mDoNotSuspendAnything )\r\n\t\t{\r\n\t\t}\t\r\n\t\telse if ( p_suspend_component->m_never_suspend )\r\n\t\t{\r\n\t\t}\r\n\t\telse if ( p_suspend_component->m_initial_animations )\r\n\t\t{\r\n\t\t\tp_suspend_component->m_initial_animations--;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_suspend_component->m_camera_distance_squared = Mth::DistanceSqr(p_suspend_component->GetObject()->GetPos(),p_info->mActiveCameraPosition);\r\n\t\t\r\n\t\t\tif ( p_suspend_component->m_camera_distance_squared > p_suspend_component->m_suspend_distance_squared )\r\n\t\t\t{\r\n\t\t\t\tp_suspend_component->m_skip_logic = true;\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_suspend_component->m_skip_logic = false;\r\n\t\t\t}\r\n\t\t}\r\n\t\t// suspend or unsuspend the object and its components\r\n\t\t// based on the new state of m_skip_logic\r\n\t\tif (p_suspend_component->m_skip_logic)\r\n\t\t{\r\n\t\t\tif (!p_suspend_component->GetObject()->IsSuspended())\r\n\t\t\t{\r\n\t\t\t\tp_suspend_component->GetObject()->Suspend(true);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (p_suspend_component->GetObject()->IsSuspended())\r\n\t\t\t{\r\n\t\t\t\tp_suspend_component->GetObject()->Suspend(false);\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t\t// If it has a model, then check for LOD to nothing\t\r\n\t\tif (p_suspend_component->mp_model_component)\r\n\t\t{\r\n\t\t\tif (p_suspend_component->m_initial_animations)\r\n\t\t\t{\r\n\t\t\t\tif (p_suspend_component->mp_model_component->GetModel())\r\n\t\t\t\t{\r\n\t\t\t\t\tp_suspend_component->mp_model_component->GetModel()->SetActive(true);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_suspend_component->CheckModelActive();\t\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tp_suspend_component = static_cast<Obj::CSuspendComponent*>( p_suspend_component->GetNextSameType());\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n\r\n}\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/SuspendComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SuspendComponent.h\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ??/??/??\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SUSPENDCOMPONENT_H__\r\n#define __COMPONENTS_SUSPENDCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/singleton.h>\r\n#include <core/task.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_SUSPEND CRCD(0xce0ca665,\"Suspend\")\r\n#define\t\tGetSuspendComponent() ((Obj::CSuspendComponent*)GetComponent(CRC_SUSPEND))\r\n#define\t\tGetSuspendComponentFromObject(pObj) ((Obj::CSuspendComponent*)(pObj)->GetComponent(CRC_SUSPEND))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n\r\n\r\n              \r\nnamespace Obj\r\n{\r\n\r\n\tclass\tCModelComponent;\r\n\r\n\r\nnamespace SuspendManager\r\n{\r\n\r\nclass Manager  : public Spt::Class\r\n{\r\n\tTsk::Task< Manager > *mp_task;\r\n\tstatic\tTsk::Task< Manager >::Code \ts_code;\r\n\r\npublic:\r\n\tManager();\r\n\t~Manager();\r\n\t\r\nprivate:\t\r\n\tDeclareSingletonClass( Manager );\r\n};\r\n\r\n}\r\n\r\n\r\n\r\nclass CSuspendComponent : public CBaseComponent\r\n{\r\n\tfriend class SuspendManager::Manager;\r\n\t \r\npublic:\r\n    CSuspendComponent();\r\n    virtual ~CSuspendComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual\tvoid\t\t\t\t\tFinalize();\t\r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual\tvoid\t\t\t\t\tSuspend(bool suspend);\r\n\t\r\n\r\n\tvoid \t\t\t\t\t\t\tGetDebugInfo(Script::CStruct *p_info);\r\n\tbool\t\t\t\t\t\t\tSkipLogic();\r\n\tbool \t\t\t\t\t\t\tSkipRender();\r\n\r\n\t\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\tstatic void\t\t\t\t\t\ts_register();\r\n\r\npublic:\t\t\r\n\tvoid \t\t\t\t\t\t\tCheckModelActive();\r\n\tfloat\t\t\t\t\t\t\tGetDistanceSquaredToCamera();\r\n\r\nprivate:\r\n\tbool\t\t\t\t\t\t\tm_never_suspend;\r\n\tfloat\t\t\t\t\t\t\tm_suspend_distance;\r\n\tfloat\t\t\t\t\t\t\tm_suspend_distance_squared; // K: For a fast distance-squared check\r\n\tfloat\t\t\t\t\t\t\tm_camera_distance_squared;  // current distance from camera\r\n\tint\t\t\t\t\t\t\t\tm_no_suspend_count;\t// number of initial frames we cannot suspend in\r\n\r\n\tCModelComponent* \t\t\t\tmp_model_component;\r\n\r\n\tbool\t\t\t\t\t\t\tm_skip_logic;\r\n\tbool\t\t\t\t\t\t\tm_skip_render;\r\n\t\r\n// public during the transition:\r\npublic:\r\n//protected:\r\n\tfloat\t\t\t\t\t\t\tm_lod_dist[4];\t\t// Mick: LOD is in the moving object for now....\t\r\n\tint\t\t\t\t\t\t\t\tm_initial_animations;\t\t// must do at least these initial animations\r\n\r\nprotected:\r\n\tint\t\t\t\t\t\t\t\tm_interleave;\t// Mick: counter for interleaving animation at a distance\r\npublic:  // just for now\t\r\n\tbool\t\t\t\t\t\t\tshould_animate( float *p_dist = NULL );\r\n};\r\n\r\n\r\n\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/TriggerComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       TriggerComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/3/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/triggercomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/components/nodearraycomponent.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <sk/modules/skate/skate.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CTriggerComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CTriggerComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTriggerComponent::CTriggerComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_TRIGGER );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCTriggerComponent::~CTriggerComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTriggerComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tm_pos_last_frame = GetObject()->GetPos();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTriggerComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTriggerComponent::Update()\r\n{\r\n\tif (m_pos_last_frame == GetObject()->GetPos()) return;\r\n\t\r\n\tif (GetObject()->HasTeleported())\r\n\t{\r\n\t\tm_pos_last_frame = GetObject()->GetPos();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tCFeeler feeler;\r\n\t\r\n\tfeeler.m_start = m_pos_last_frame;\r\n\tfeeler.m_end = GetObject()->GetPos();\r\n\t\r\n\tfeeler.SetIgnore(0, mFD_NON_COLLIDABLE | mFD_TRIGGER);\r\n\t\r\n\tfeeler.SetCallback(s_through_trigger_callback);\r\n\tfeeler.SetCallbackData(this);\r\n\t\r\n\tfeeler.GetCollision();\r\n\t\r\n\tm_pos_last_frame = GetObject()->GetPos();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CTriggerComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | TriggerType | checks if the trigger type is the \r\n        // same as the specified type.  can also accept an array of types\r\n        // to check\r\n        // @uparmopt name | trigger type\r\n        // @uparmopt [] | array of trigger types\r\n\t\tcase CRCC(0x3a717382, \"TriggerType\"):\r\n\t\t{\r\n\t\t\tScript::CArray* pArray = NULL;\r\n\t\t\tpParams->GetArray(NO_NAME, &pArray);\r\n\t\t\tif (pArray)\r\n\t\t\t{\r\n\t\t\t\tfor (int n = pArray->GetSize(); n--; )\r\n\t\t\t\t{\r\n\t\t\t\t\tif (m_latest_trigger_event_type == Script::GetInteger(pArray->GetChecksum(n))) return CBaseComponent::MF_TRUE;\r\n\t\t\t\t}\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tint type;\r\n\t\t\t\tpParams->GetInteger(NO_NAME, &type, Script::ASSERT);\r\n\t\t\t\treturn m_latest_trigger_event_type == type ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;   \r\n\t\t\t} \t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTriggerComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CTriggerComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTriggerComponent::CheckFeelerForTrigger ( TriggerEventType type, CLineFeeler& feeler )\r\n{\r\n\tif (!feeler.GetTrigger() || !feeler.GetNodeChecksum()) return;\r\n\r\n\tif (feeler.GetCallbackObject())\r\n\t{\r\n\t\tCNodeArrayComponent* p_node_array_component = GetNodeArrayComponentFromObject(feeler.GetCallbackObject());\r\n\t\t\r\n\t\tTripTrigger(type, feeler.GetNodeChecksum(), p_node_array_component ? p_node_array_component->GetNodeArray() : NULL, feeler.GetCallbackObject());\r\n\t}\r\n\telse if (feeler.IsMovableCollision())\r\n\t{\r\n\t\tif (feeler.GetMovingObject())\r\n\t\t{\r\n\t\t\tCNodeArrayComponent* p_node_array_component = GetNodeArrayComponentFromObject(feeler.GetMovingObject());\r\n\t\t\tTripTrigger(type, feeler.GetNodeChecksum(), p_node_array_component ? p_node_array_component->GetNodeArray() : NULL, feeler.GetMovingObject());\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tTripTrigger(type, feeler.GetNodeChecksum());\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTriggerComponent::CheckFeelerForTrigger ( TriggerEventType type, CRectFeeler& feeler )\r\n{\r\n\tfor (int n = feeler.GetNumCollisionSurfaces(); n--; )\r\n\t{\r\n\t\tconst Nx::S2DCollSurface& coll_surface = feeler.GetCollisionSurface(n);\r\n\t\tif (!coll_surface.trigger) continue;\r\n\t\t\r\n\t\t// only trip the node's trigger if we haven't yet\r\n\t\tint m;\r\n\t\tfor (m = n + 1; m < feeler.GetNumCollisionSurfaces(); m++)\r\n\t\t{\r\n\t\t\tconst Nx::S2DCollSurface& handled_coll_surface = feeler.GetCollisionSurface(m);\r\n\t\t\tif (!coll_surface.trigger) continue;\r\n\t\t\tif (coll_surface.node_name == handled_coll_surface.node_name) break;\r\n\t\t}\r\n\t\tif (m == feeler.GetNumCollisionSurfaces())\r\n\t\t{\r\n\t\t\tTripTrigger(type, coll_surface.node_name);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTriggerComponent::TripTrigger ( TriggerEventType type, uint32 node_checksum, Script::CArray* p_node_array, CCompositeObject* p_object)\r\n{\r\n\tint node;\r\n\tScript::CStruct* p_node = NULL;\r\n\t\r\n\t// find the triggered node\r\n\tif (!p_node_array)\r\n\t{\r\n\t\tnode = SkateScript::FindNamedNode(node_checksum);\r\n\t\tDbg_MsgAssert(node != -1, (\"Can't find node %s, maybe .SCN out of sync with .QN ?\",Script::FindChecksumName(node_checksum)));\r\n\t\tp_node_array = Script::GetArray(CRCD(0xc472ecc5, \"NodeArray\"));\r\n\t\tp_node = p_node_array->GetStructure(node);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor (node = p_node_array->GetSize(); node--; )\r\n\t\t{\r\n\t\t\tp_node = p_node_array->GetStructure(node);\r\n\t\t\t\r\n\t\t\tuint32 checksum;\r\n\t\t\tp_node->GetChecksum(CRCD(0xa1dc81f9, \"name\"), &checksum);\r\n\t\t\tif (checksum == node_checksum) break;\r\n\t\t}\r\n\t}\r\n\t\r\n\tDbg_MsgAssert(node != -1, (\"Cannot find node %s\", Script::FindChecksumName(node_checksum)));\r\n\t\r\n\t// get the triggered object's trigger script parameters\r\n\tScript::CStruct* p_model_trigger_script_params = NULL;\r\n\tif (p_object)\r\n\t{\r\n\t\tScript::CStruct* p_object_node = Script::GetArray(CRCD(0xc472ecc5, \"NodeArray\"))->GetStructure(SkateScript::FindNamedNode(p_object->GetID()));\r\n\t\tif (p_object_node)\r\n\t\t{\r\n\t\t\tp_object_node->GetStructure(CRCD(0x5180a4db, \"ModelTriggerScriptParams\"), &p_model_trigger_script_params);\r\n\t\t}\r\n\t}\r\n\t\r\n\t// get the trigger script\r\n\tuint32 script_checksum = 0;\r\n\tp_node->GetChecksum(CRCD(0x2ca8a299, \"TriggerScript\"), &script_checksum);\r\n\tif (script_checksum == 0) return;\r\n\t\r\n\t// if this is a net game, don't trigger things from \"Absent in netgame\" nodes\r\n\tif (Mdl::Skate::Instance()->ShouldBeAbsentNode(p_node)) return;\r\n\t\r\n\tm_latest_trigger_event_type = type;\r\n\t\r\n\tGetObject()->SpawnAndRunScript(\r\n\t\tscript_checksum,\r\n\t\tnode,\r\n\t\tp_node->ContainsFlag(CRCD(0x20209c31, \"NetEnabled\")),\r\n\t\tp_node->ContainsFlag(CRCD(0x23627fd7, \"Permanent\")),\r\n\t\tp_model_trigger_script_params\r\n\t);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTriggerComponent::s_through_trigger_callback ( CFeeler* p_feeler )\r\n{\r\n\tstatic_cast< CTriggerComponent* >(p_feeler->GetCallbackData())->CheckFeelerForTrigger(TRIGGER_THROUGH, *p_feeler);\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/TriggerComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       TriggerComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/3/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_TRIGGERCOMPONENT_H__\r\n#define __COMPONENTS_TRIGGERCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <sk/engine/rectfeeler.h>\r\n\r\n#define\t\tCRC_TRIGGER CRCD(0xe594f0a2, \"Trigger\")\r\n\r\n#define\t\tGetTriggerComponent() ((Obj::CTriggerComponent*)GetComponent(CRC_TRIGGER))\r\n#define\t\tGetTriggerComponentFromObject(pObj) ((Obj::CTriggerComponent*)(pObj)->GetComponent(CRC_TRIGGER))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\t// trigger types for skating/walking\r\n\tenum ESkaterTriggerType\r\n\t{\r\n\t\tTRIGGER_SKATE_OFF_EDGE = 1,\r\n\t\tTRIGGER_JUMP_OFF,\r\n\t\tTRIGGER_LAND_ON,\r\n\t\tTRIGGER_SKATE_OFF,\r\n\t\tTRIGGER_SKATE_ONTO,\r\n\t\tTRIGGER_BONK,\r\n\t\tTRIGGER_LIP_ON,\r\n\t\tTRIGGER_LIP_OFF,\r\n\t\tTRIGGER_LIP_JUMP,\r\n\t};\r\n\r\nclass CTriggerComponent : public CBaseComponent\r\n{\r\n\t// users of CTriggerComponent define their own trigger event types, however 0 is reserved for the event of passing through trigger polys\r\n\tenum\r\n\t{\r\n\t\tTRIGGER_THROUGH = 0\r\n\t};\r\n\r\npublic:\r\n\ttypedef int TriggerEventType;\r\n\t\r\npublic:\r\n    CTriggerComponent();\r\n    virtual ~CTriggerComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tCheckFeelerForTrigger ( TriggerEventType type, CLineFeeler& p_feeler );\r\n\tvoid\t\t\t\t\t\t\tCheckFeelerForTrigger ( TriggerEventType type, CRectFeeler& feeler );\r\n\tvoid\t\t\t\t\t\t\tTripTrigger ( TriggerEventType type, uint32 node_checksum, Script::CArray* p_node_array = NULL, CCompositeObject* p_object = NULL);\r\n\t\r\nprivate:\r\n\tstatic void\t\t\t\t\t\ts_through_trigger_callback ( CFeeler* p_feeler );\r\n\t\r\nprivate:\r\n\tMth::Vector\t\t\t\t\t\tm_pos_last_frame;\r\n\tTriggerEventType\t\t\t\tm_latest_trigger_event_type;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/VehicleSoundComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       VehicleSoundComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  7/2/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/vehiclesoundcomponent.h>\r\n#include <gel/components/vehiclecomponent.h>\r\n#include <gel/components/soundcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/parkeditor2/parked.h>\r\n\r\n#define MESSAGE(a) { printf(\"M:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPI(a) { printf(\"D:%s:%i: \" #a \" = %i\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPB(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, a ? \"true\" : \"false\"); }\r\n#define DUMPF(a) { printf(\"D:%s:%i: \" #a \" = %g\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPE(a) { printf(\"D:%s:%i: \" #a \" = %e\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPS(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPP(a) { printf(\"D:%s:%i: \" #a \" = %p\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPC(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, Script::FindChecksumName(a)); }\r\n#define DUMPV(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z]); }\r\n#define DUMP4(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z], (a)[W]); }\r\n#define DUMPM(a) { DUMP4((a)[X]); DUMP4((a)[Y]); DUMP4((a)[Z]); DUMP4((a)[W]); }\r\n#define DUMP2(a) { printf(\"D:%s:%i \" #a \" = \", __FILE__ + 15, __LINE__); for (int n = 32; n--; ) { printf(\"%c\", ((a) & (1 << n)) ? '1' : '0'); } printf(\"\\n\"); }\r\n#define MARK { printf(\"K:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, __PRETTY_FUNCTION__); }\r\n#define PERIODIC(n) for (static int p__ = 0; (p__ = ++p__ % (n)) == 0; )\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\t#define DEBUG_OUTPUT(a) \\\r\n\t\t{ \\\r\n\t\t\tif (Script::GetInteger(CRCD(0x54f22205, \"DebugPlayerVehicleEngineSound\")) \\\r\n\t\t\t\t|| Script::GetInteger(CRCD(0xdf03ebbf, \"DebugPlayerVehicleTireSound\"))) \\\r\n\t\t\t{ \\\r\n\t\t\t\tprintf(\"[DebugEngineSound]: \"); \\\r\n\t\t\t\tprintf a; \\\r\n\t\t\t\tprintf(\"\\n\"); \\\r\n\t\t\t} \\\r\n\t\t}\r\n\t#define DEBUG_ENGINE(a) \\\r\n\t\t{ \\\r\n\t\t\tif (Script::GetInteger(CRCD(0x54f22205, \"DebugPlayerVehicleEngineSound\"))) \\\r\n\t\t\t{ \\\r\n\t\t\t\tprintf(\"[DebugEngineSound]: \"); \\\r\n\t\t\t\tprintf a; \\\r\n\t\t\t\tprintf(\"\\n\"); \\\r\n\t\t\t} \\\r\n\t\t}\r\n\t#define DEBUG_TIRES(a) \\\r\n\t\t{ \\\r\n\t\t\tif (Script::GetInteger(CRCD(0xdf03ebbf, \"DebugPlayerVehicleTireSound\"))) \\\r\n\t\t\t{ \\\r\n\t\t\t\tprintf(\"[DebugTireSound]: \"); \\\r\n\t\t\t\tprintf a; \\\r\n\t\t\t\tprintf(\"\\n\"); \\\r\n\t\t\t} \\\r\n\t\t}\r\n\t#define DEBUG_COLLISION(a) \\\r\n\t\t{ \\\r\n\t\t\tif (Script::GetInteger(CRCD(0xc2ddef08, \"DebugPlayerVehicleCollisionSound\"))) \\\r\n\t\t\t{ \\\r\n\t\t\t\tprintf(\"[DebugCollisionSound]: \"); \\\r\n\t\t\t\tprintf a; \\\r\n\t\t\t\tprintf(\"\\n\"); \\\r\n\t\t\t} \\\r\n\t\t}\r\n#else\r\n\t#define DEBUG_OUTPUT(a)\r\n\t#define DEBUG_ENGINE(a)\r\n\t#define DEBUG_TIRES(a)\r\n\t#define DEBUG_COLLISION(a)\r\n#endif\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CVehicleSoundComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CVehicleSoundComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCVehicleSoundComponent::CVehicleSoundComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_VEHICLESOUND );\r\n\t\r\n\tmp_vehicle_component = NULL;\r\n\tmp_sound_component = NULL;\r\n\t\r\n\tm_sound_setup_struct = NULL;\r\n\t\r\n\tm_use_default_sounds = false;\r\n\t\r\n\tm_effective_speed = 0.0f;\r\n\tm_effective_gear = 0;\r\n\tm_gear_shift_time_stamp = 0;\r\n\tm_airborne_time_stamp = 0;\r\n\tm_effective_tire_slip_vel = 0.0f;\r\n\tm_latest_collision_sound_time_stamp = 0;\r\n\t\r\n\tm_engine_sound_id = 0;\r\n\tm_tire_sound_id = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCVehicleSoundComponent::~CVehicleSoundComponent()\r\n{\r\n\tif (m_engine_sound_id)\r\n\t{\r\n\t\tSfx::CSfxManager::Instance()->StopSound(m_engine_sound_id);\r\n\t\tm_engine_sound_id = 0;\r\n\t}\r\n\tif (m_tire_sound_id)\r\n\t{\r\n\t\tSfx::CSfxManager::Instance()->StopSound(m_tire_sound_id);\r\n\t\tm_tire_sound_id = 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleSoundComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tm_use_default_sounds = Ed::CParkEditor::Instance()->UsingCustomPark();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleSoundComponent::Finalize()\r\n{\r\n\tmp_vehicle_component = GetVehicleComponentFromObject(GetObject());\r\n\tmp_sound_component = GetSoundComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_vehicle_component);\r\n\tDbg_Assert(mp_sound_component);\r\n\t\r\n\tfetch_script_parameters();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleSoundComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleSoundComponent::Update()\r\n{\r\n\tDEBUG_OUTPUT((\"-- frame start --\"));\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (Script::GetInteger(CRCD(0xcf5f4e16, \"DynamicPlayerVehicleSound\")))\r\n\t{\r\n\t\tfetch_script_parameters();\r\n\t}\r\n\t#endif\r\n\t\r\n\tif (!m_sound_setup_struct) return;\r\n\t\r\n\tupdate_engine_sounds();\r\n\t\r\n\tupdate_tire_sounds();\r\n\t\r\n\tupdate_collision_sounds();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CVehicleSoundComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleSoundComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CVehicleSoundComponent::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddChecksum(CRCD(0x2a19e830, \"engine_sound\"), m_engine_sound_checksum);\r\n\tp_info->AddChecksum(CRCD(0xe798fe80, \"tire_sound\"), m_tire_sound_checksum);\r\n\tp_info->AddStructure(CRCD(0x36fa68d2, \"collide_sound\"), m_collide_sound_struct);\r\n\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleSoundComponent::update_engine_sounds (   )\r\n{\r\n\tfloat frame_length = Tmr::FrameLength();\r\n\t\r\n\tCVehicleComponent::SWheel* p_wheels = mp_vehicle_component->mp_wheels;\r\n\t\r\n\t// determine the smallest of all the drive wheels' rotational velocity\r\n\tfloat min_vel = 1e20f;\r\n\tfor (int n = CVehicleComponent::vVP_NUM_WHEELS; n--; )\r\n\t{\r\n\t\tif (!p_wheels[n].drive) continue;\r\n\t\tmin_vel = Mth::Min(min_vel, Mth::Abs(p_wheels[n].rotvel) * p_wheels[n].radius);\r\n\t}\r\n\tfloat frame_effective_speed = IPS_TO_MPH(min_vel);\r\n\t\r\n\t// adjust effective speed based on throttle position\r\n\tbool throttle = (mp_vehicle_component->m_controls.throttle || mp_vehicle_component->m_controls.reverse) && !mp_vehicle_component->m_controls.brake;\r\n\tif (!throttle)\r\n\t{\r\n\t\tframe_effective_speed *= get_global_param(CRCD(0xec67bc97, \"idle_engine_effective_speed_factor\"));\r\n\t}\r\n\t\r\n\t// smooth out frame-to-frame fluxuations\r\n\tm_effective_speed = Mth::Lerp(frame_effective_speed, m_effective_speed, get_global_param(CRCD(0x2a7095b, \"effective_speed_lerp_rate\")) * frame_length);\r\n\tif (m_effective_speed < frame_effective_speed)\r\n\t{\r\n\t\tm_effective_speed = Mth::ClampMax(m_effective_speed + get_global_param(CRCD(0xca5efd91, \"effective_speed_adjust_up_rate\")) * frame_length, m_effective_speed);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_effective_speed = Mth::ClampMin(m_effective_speed - get_global_param(CRCD(0x77c8e7c8, \"effective_speed_adjust_down_rate\")) * frame_length, m_effective_speed);\r\n\t}\r\n\tDEBUG_ENGINE((\"speed: %.2f mph\", m_effective_speed));\r\n\t\r\n\t// determine the appropriate gear for this frame\r\n\tif (mp_vehicle_component->m_num_wheels_in_contact != 0)\r\n\t{\r\n\t\tif (m_effective_gear < m_num_gears - 1 && m_effective_speed > m_gears[m_effective_gear].upshift_point)\r\n\t\t{\r\n\t\t\tm_effective_gear++;\r\n\t\t\tm_gear_shift_time_stamp = Tmr::GetTime();\r\n\t\t\tDEBUG_ENGINE((\"upshift to gear: %i\", m_effective_gear));\r\n\t\t}\r\n\t\telse if (m_effective_gear > 0 && m_effective_speed < m_gears[m_effective_gear].downshift_point)\r\n\t\t{\r\n\t\t\tm_effective_gear--;\r\n\t\t\tm_gear_shift_time_stamp = Tmr::GetTime();\r\n\t\t\tDEBUG_ENGINE((\"downshift to gear: %i\", m_effective_gear));\r\n\t\t}\r\n\t}\r\n\telse if (mp_vehicle_component->m_air_time > get_global_param(CRCD(0xc0f451d4, \"engine_airborne_delay\")))\r\n\t{\t \r\n\t\t// when airborne, drop to lowest gear and use no gear shift velocity damping\r\n\t\tm_effective_gear = 0;\r\n\t}\r\n\tDEBUG_ENGINE((\"gear: %i\", m_effective_gear + 1));\r\n\t\r\n\t// calculate a volume adjustment based on the time since the last gear shift\r\n\tfloat gear_shift_vol_factor = Mth::ClampMax(\r\n\t\tMth::LinearMap(\r\n\t\t\tget_global_param(CRCD(0xbfa32092, \"gear_shift_min_vol_factor\")),\r\n\t\t\t1.0f,\r\n\t\t\tTmr::ElapsedTime(m_gear_shift_time_stamp),\r\n\t\t\t0.0f,\r\n\t\t\tget_global_param(CRCD(0xfb6bd20e, \"gear_shift_vol_adjustment_duration\"))\r\n\t\t),\r\n\t\t1.0f\r\n\t);\r\n\t\t\r\n\t// calculate this frame's engine rpm based on the current gear and speed\r\n\tfloat frame_engine_rpm = Mth::LinearMap(\r\n\t\tm_gears[m_effective_gear].bottom_rpm,\r\n\t\tm_gears[m_effective_gear].top_rpm,\r\n\t\tm_effective_speed,\r\n\t\tm_effective_gear ? m_gears[m_effective_gear - 1].upshift_point : 0.0f,\r\n\t\tm_gears[m_effective_gear].upshift_point\r\n\t);\r\n\t// DEBUG_ENGINE((\"speed top: %.2f\", m_gears[m_effective_gear].upshift_point));\r\n\t// DEBUG_ENGINE((\"speed bottom: %.2f\", m_effective_gear ? m_gears[m_effective_gear - 1].upshift_point : 0.0f));\r\n\t// DEBUG_ENGINE((\"rpm top: %.2f\", m_gears[m_effective_gear].top_rpm));\r\n\t// DEBUG_ENGINE((\"rpm bottom: %.2f\", m_gears[m_effective_gear].bottom_rpm));\r\n\t\r\n\t// smooth out the engine rpm changes (causes nice shifting effects)\r\n\tm_effective_engine_rpm = Mth::Lerp(\r\n\t\tm_effective_engine_rpm,\r\n\t\tframe_engine_rpm,\r\n\t\tget_global_param(CRCD(0x3dd9c040, \"engine_rpm_lerp_rate\")) * frame_length\r\n\t);\r\n\tDEBUG_ENGINE((\"engine RPM: %.2f\", m_effective_engine_rpm));\r\n\t\r\n\t// calculate a number between 0.0f and 1.0f which will scale the engine sound's pitch and volume\r\n\tfloat sound_factor = Mth::Clamp(\r\n\t\tMth::LinearMap(\r\n\t\t\t0.0f,\r\n\t\t\t1.0f,\r\n\t\t\tm_effective_engine_rpm,\r\n\t\t\tget_param(CRCD(0x05ac84a3, \"MinEngineRPM\")),\r\n\t\t\tget_param(CRCD(0x95df9449, \"MaxEngineRPM\"))\r\n\t\t),\r\n\t\t0.0f,\r\n\t\t1.0f\r\n\t);\r\n\t\r\n\t// setup volume\r\n\tSfx::sVolume volume;\r\n\tSfx::CSfxManager::Instance()->SetVolumeFromPos(&volume, GetObject()->GetPos(), Sfx::CSfxManager::Instance()->GetDropoffDist(m_engine_sound_checksum));\r\n\tfloat volume_percent = gear_shift_vol_factor * Mth::Lerp(\r\n\t\tget_param(CRCD(0xb8f81277, \"MinEngineVol\")),\r\n\t\tget_param(CRCD(0x288b029d, \"MaxEngineVol\")),\r\n\t\tsound_factor\r\n\t);\r\n\tvolume.PercentageAdjustment(volume_percent);\r\n\tDEBUG_ENGINE((\"engine volume: %.0f\", volume_percent));\r\n\t\r\n\t// setup pitch\r\n\tfloat pitch = Mth::Lerp(\r\n\t\tget_param(CRCD(0x2660af3b, \"MinEnginePitch\")),\r\n\t\tget_param(CRCD(0x9f46344a, \"MaxEnginePitch\")),\r\n\t\tsound_factor\r\n\t);\r\n\tDEBUG_ENGINE((\"engine pitch: %.0f\", pitch));\r\n\t\r\n\t// play or adjust sound\r\n\tif (!m_engine_sound_id)\r\n\t{\r\n\t\tm_engine_sound_id = Sfx::CSfxManager::Instance()->PlaySound(m_engine_sound_checksum, &volume, pitch, NULL);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSfx::CSfxManager::Instance()->UpdateLoopingSound(m_engine_sound_id, &volume, pitch);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleSoundComponent::update_tire_sounds (   )\r\n{\r\n\tCVehicleComponent::SWheel* p_wheels = mp_vehicle_component->mp_wheels;\r\n\t\r\n\t// determine the largest of all the wheels' slip velocity\r\n\tfloat max_slip_vel = 0.0f;\r\n\t\r\n\tif (mp_vehicle_component->m_controls.brake || mp_vehicle_component->m_controls.handbrake)\r\n\t{\r\n\t\tfor (int n = CVehicleComponent::vVP_NUM_WHEELS; n--; )\r\n\t\t{\r\n\t\t\t// handbrake skid states do not depend on the tire's slip velocity, so we check the slip velocity ourselves\r\n\t\t\tif ((p_wheels[n].state == CVehicleComponent::SWheel::SLIPPING || p_wheels[n].state == CVehicleComponent::SWheel::SKIDDING)\r\n\t\t\t\t|| ((p_wheels[n].state == CVehicleComponent::SWheel::HANDBRAKE_LOCKED || p_wheels[n].state == CVehicleComponent::SWheel::HANDBRAKE_THROTTLE)\r\n\t\t\t\t&& p_wheels[n].slip_vel > p_wheels[n].max_static_velocity))\r\n\t\t\t{\r\n\t\t\t\tmax_slip_vel = Mth::Max(max_slip_vel, p_wheels[n].slip_vel);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tm_effective_tire_slip_vel = Mth::Lerp(\r\n\t\tm_effective_tire_slip_vel,\r\n\t\tmax_slip_vel,\r\n\t\tget_global_param(CRCD(0x95fbe774, \"tire_slip_lerp_rate\")) * Tmr::FrameLength()\r\n\t);\r\n\tDEBUG_TIRES((\"tire slip velocity: %.2f\", m_effective_tire_slip_vel));\r\n\t\r\n\tfloat sound_factor = Mth::Clamp(\r\n\t\tm_effective_tire_slip_vel / get_param(CRCD(0x28f1aad0, \"FullTireSlipVelocity\")),\r\n\t\t0.0f,\r\n\t\t1.0f\r\n\t);\r\n\t\r\n\t// setup volume\r\n\tSfx::sVolume volume;\r\n\tSfx::CSfxManager::Instance()->SetVolumeFromPos(&volume, GetObject()->GetPos(), Sfx::CSfxManager::Instance()->GetDropoffDist(m_tire_sound_checksum));\r\n\tfloat volume_percent = Mth::Lerp(\r\n\t\tget_param(CRCD(0x43e6cdf2, \"MinTireVol\")),\r\n\t\tget_param(CRCD(0x42ea5746, \"MaxTireVol\")),\r\n\t\tsound_factor\r\n\t);\r\n\tvolume.PercentageAdjustment(volume_percent);\r\n\tDEBUG_TIRES((\"tire volume: %.0f\", volume_percent));\r\n\t\r\n\t// setup pitch\r\n\tfloat pitch = Mth::Lerp(\r\n\t\tget_param(CRCD(0x76f8f76e, \"MinTirePitch\")),\r\n\t\tget_param(CRCD(0xe68be784, \"MaxTirePitch\")),\r\n\t\tsound_factor\r\n\t);\r\n\tDEBUG_TIRES((\"tire pitch: %.0f\", pitch));\r\n\t\r\n\tif (!volume.IsSilent())\r\n\t{\r\n\t\tif (!m_tire_sound_id)\r\n\t\t{\r\n\t\t\tm_tire_sound_id = Sfx::CSfxManager::Instance()->PlaySound(m_tire_sound_checksum, &volume, pitch, NULL);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tSfx::CSfxManager::Instance()->UpdateLoopingSound(m_tire_sound_id, &volume, pitch);\r\n\t\t}\r\n\t}\r\n\telse if (m_tire_sound_id)\r\n\t{\r\n\t\tSfx::CSfxManager::Instance()->StopSound(m_tire_sound_id);\r\n\t\tm_tire_sound_id = 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleSoundComponent::update_collision_sounds (   )\r\n{\r\n\tif (Tmr::ElapsedTime(m_latest_collision_sound_time_stamp) < get_global_param(CRCD(0x71b4b9fe, \"collision_mute_delay\"))) return;\r\n\t\r\n\tfloat sound_factor = mp_vehicle_component->m_max_normal_collision_impulse / get_param(CRCD(0xcea59d0b, \"FullCollision\"));\r\n\tif (sound_factor > get_global_param(CRCD(0xf6981837, \"collision_cutoff_factor\")))\r\n\t{\r\n\t\tDEBUG_COLLISION((\"collision: %.2f\", mp_vehicle_component->m_max_normal_collision_impulse));\r\n\t\t\r\n\t\tm_collide_sound_struct->AddFloat(CRCD(0x9e497fc6, \"Percent\"), 100.0f * sound_factor);\r\n\t\tmp_sound_component->PlayScriptedSound(m_collide_sound_struct);\r\n\t\t\r\n\t\tm_latest_collision_sound_time_stamp = Tmr::GetTime();\r\n\t\t\r\n\t\tScript::CStruct* p_params = new Script::CStruct;\r\n\t\tp_params->AddFloat(CRCD(0x29461e27, \"Strength\"), Mth::Clamp(sound_factor, 0.0f, 1.0f));\r\n\t\tmp_vehicle_component->mp_skater->SelfEvent(CRCD(0xc4a60423, \"Vehicle_BodyCollision\"), p_params);\r\n\t\tdelete p_params;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleSoundComponent::fetch_script_parameters (   )\r\n{\r\n\t// get sound setup structure\r\n\tScript::CStruct* sound_setups_struct = Script::GetStructure(CRCD(0x3c2da7f5, \"PlayerVehicleSounds\"), Script::ASSERT);\r\n\tsound_setups_struct->GetStructure(mp_vehicle_component->GetSoundSetupChecksum(), &m_sound_setup_struct, Script::ASSERT);\r\n\t\r\n\t// extract sound checksum\r\n\tm_sound_setup_struct->GetChecksum(CRCD(0x306f8a9f, \"EngineSound\"), &m_engine_sound_checksum);\r\n\tm_sound_setup_struct->GetChecksum(CRCD(0x667fa96a, \"TireSound\"), &m_tire_sound_checksum);\r\n\t\r\n\t// extract gear information\r\n\t\r\n\tScript::CArray* gear_array;\r\n\tm_sound_setup_struct->GetArray(CRCD(0x83273e6b, \"Gears\"), &gear_array, Script::ASSERT);\r\n\t\r\n\tm_num_gears = gear_array->GetSize();\r\n\tDbg_MsgAssert(m_num_gears <= vVS_MAX_NUM_GEARS, (\"PlayerVehicleSound '%s' exceeds the maximum number of %i allowed gears\", Script::FindChecksumName(mp_vehicle_component->GetSoundSetupChecksum()), vVS_MAX_NUM_GEARS));\r\n\tfor (int n = 0; n < m_num_gears; n++)\r\n\t{\r\n\t\tScript::CStruct* gear_struct = gear_array->GetStructure(n);\r\n\t\t\r\n\t\tgear_struct->GetFloat(CRCD(0xfad20901, \"UpshiftPoint\"), &m_gears[n].upshift_point, Script::ASSERT);\r\n\t\tgear_struct->GetFloat(CRCD(0xfcf5c8a2, \"DownshiftPoint\"), &m_gears[n].downshift_point, Script::ASSERT);\r\n        gear_struct->GetFloat(CRCD(0x735b5ce4, \"BottomRPM\"), &m_gears[n].bottom_rpm, Script::ASSERT);\r\n        gear_struct->GetFloat(CRCD(0xe59a89a6, \"TopRPM\"), &m_gears[n].top_rpm, Script::ASSERT);\r\n\t\t\r\n\t\tDbg_MsgAssert(m_gears[n].upshift_point > m_gears[n].downshift_point, (\"In gear %i of PlayerVehicleSound '%s,' DownshiftPoint exceeds UpshiftPoint\", n + 1, Script::FindChecksumName(mp_vehicle_component->GetSoundSetupChecksum())));\r\n\t\tDbg_MsgAssert(!n || m_gears[n].downshift_point < m_gears[n - 1].upshift_point, (\"In gear %i of PlayerVehicleSound '%s', DownshiftPoint exceeds lower gear's UpshiftPoint\", n + 1, Script::FindChecksumName(mp_vehicle_component->GetSoundSetupChecksum())));\r\n\t}\r\n\t\r\n\t// extract collision sound structure\r\n\tm_sound_setup_struct->GetStructure(CRCD(0xbf8e0ace, \"CollideSound\"), &m_collide_sound_struct, Script::ASSERT);\r\n\t\r\n\t// if we're in a create-a-goal, swap sound checksums for default sound checksums, as the true sounds may not be loaded\r\n\tif (m_use_default_sounds)\r\n\t{\r\n\t\tScript::CStruct* global_sound_setup = Script::GetStructure(CRCD(0x38ec37ac, \"PlayerVehicleSoundGlobalParameters\"), Script::ASSERT);\r\n\t\t\r\n\t\tglobal_sound_setup->GetChecksum(CRCD(0xf5406e1a, \"CAGEngineSound\"), &m_engine_sound_checksum, Script::ASSERT);\r\n\t\tglobal_sound_setup->GetChecksum(CRCD(0x60e93a2, \"CAGTireSound\"), &m_tire_sound_checksum, Script::ASSERT);\r\n\t\tglobal_sound_setup->GetStructure(CRCD(0x22995285, \"CAGCollideSound\"), &m_collide_sound_struct, Script::ASSERT);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CVehicleSoundComponent::get_param ( uint32 checksum )\r\n{\r\n\tDbg_Assert(m_sound_setup_struct);\r\n\t\r\n\tfloat value;\r\n\tm_sound_setup_struct->GetFloat(checksum, &value, Script::ASSERT);\r\n\treturn value;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CVehicleSoundComponent::get_global_param ( uint32 checksum )\r\n{\r\n\tScript::CStruct* global_sound_setup = Script::GetStructure(CRCD(0x38ec37ac, \"PlayerVehicleSoundGlobalParameters\"), Script::ASSERT);\r\n\t\r\n\tfloat value;\r\n\tglobal_sound_setup->GetFloat(checksum, &value, Script::ASSERT);\r\n\treturn value;\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/VehicleSoundComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       VehicleSoundComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  7/2/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_VEHICLESOUNDCOMPONENT_H__\r\n#define __COMPONENTS_VEHICLESOUNDCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_VEHICLESOUND CRCD(0x28c97f3c, \"VehicleSound\")\r\n\r\n#define\t\tGetVehicleSoundComponent() ((Obj::CVehicleSoundComponent*)GetComponent(CRC_VEHICLESOUND))\r\n#define\t\tGetVehicleSoundComponentFromObject(pObj) ((Obj::CVehicleSoundComponent*)(pObj)->GetComponent(CRC_VEHICLESOUND))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CVehicleComponent;\r\n\tclass CSoundComponent;\r\n\r\nclass CVehicleSoundComponent : public CBaseComponent\r\n{\r\nprivate:\r\n\tstatic const int vVS_MAX_NUM_GEARS = 6;\r\n\t\t\r\npublic:\r\n    CVehicleSoundComponent();\r\n    virtual ~CVehicleSoundComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual\tvoid \t\t\t\t\tFinalize();\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\tupdate_collision_sounds (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_tire_sounds (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_engine_sounds (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tfetch_script_parameters (   );\r\n\tfloat\t\t\t\t\t\t\tget_param ( uint32 checksum );\r\n\tfloat\t\t\t\t\t\t\tget_global_param ( uint32 checksum );\r\n\t\r\n\t\r\nprivate:\r\n\tScript::CStruct*\t\t\t\tm_sound_setup_struct;\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_use_default_sounds;\r\n\t\r\n\tuint32\t\t\t\t\t\t\tm_engine_sound_id;\r\n\tuint32\t\t\t\t\t\t\tm_tire_sound_id;\r\n\tScript::CStruct*\t\t\t\tm_collide_sound_struct;\r\n\t\r\n\tuint32\t\t\t\t\t\t\tm_engine_sound_checksum;\r\n\tuint32\t\t\t\t\t\t\tm_tire_sound_checksum;\r\n\t\r\n\tint\t\t\t\t\t\t\t\tm_num_gears;\r\n\tstruct SGear\r\n\t{\r\n\t\tfloat\t\t\t\t\t\tupshift_point;\r\n\t\tfloat\t\t\t\t\t\tdownshift_point;\r\n\t\tfloat\t\t\t\t\t\tbottom_rpm;\r\n\t\tfloat\t\t\t\t\t\ttop_rpm;\r\n\t}\t\t\t\t\t\t\t\tm_gears[vVS_MAX_NUM_GEARS];\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_effective_speed;\r\n\tint\t\t\t\t\t\t\t\tm_effective_gear;\r\n\tfloat\t\t\t\t\t\t\tm_effective_engine_rpm;\r\n\tTmr::Time\t\t\t\t\t\tm_gear_shift_time_stamp;\r\n\tTmr::Time\t\t\t\t\t\tm_airborne_time_stamp;\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_effective_tire_slip_vel;\r\n\t\r\n\tTmr::Time\t\t\t\t\t\tm_latest_collision_sound_time_stamp;\r\n\t\r\n\t// peer components\r\n\tCVehicleComponent*\t\t\t\tmp_vehicle_component;\r\n\tCSoundComponent*\t\t\t\tmp_sound_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/VelocityComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       VelocityComponent.cpp\r\n//* OWNER:          SPG\r\n//* CREATION DATE:  7/10/03\r\n//****************************************************************************\r\n\r\n// The CEmptyComponent class is an skeletal version of a component\r\n// It is intended that you use this as the basis for creating new\r\n// components.  \r\n// To create a new component called \"Watch\", (CWatchComponent):\r\n//  - copy emptycomponent.cpp/.h to watchcomponent.cpp/.h\r\n//  - in both files, search and replace \"Empty\" with \"Watch\", preserving the case\r\n//  - in WatchComponent.h, update the CRCD value of CRC_WATCH\r\n//  - in CompositeObjectManager.cpp, in the CCompositeObjectManager constructor, add:\r\n//\t\t  \tRegisterComponent(CRC_WATCH,\t\t\tCWatchComponent::s_create); \r\n//  - and add the include of the header\r\n//\t\t\t#include <gel/components/watchcomponent.h> \r\n//  - Add it to build\\gel.mkf, like:\r\n//          $(NGEL)/components/WatchComponent.cpp\\\r\n//  - Fill in the OWNER (yourself) and the CREATION DATE (today's date) in the .cpp and the .h files\r\n//\t- Insert code as needed and remove generic comments\r\n//  - remove these comments\r\n//  - add comments specfic to the component, explaining its usage\r\n\r\n#include <gel/components/VelocityComponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\n\r\nCBaseComponent* CVelocityComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CVelocityComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCVelocityComponent::CVelocityComponent() : CBaseComponent()\r\n{\r\n    SetType( CRC_VELOCITY );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCVelocityComponent::~CVelocityComponent()\r\n{   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CVelocityComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tMth::Vector vel;\r\n\t\r\n\tpParams->GetVector(CRCD(0xc4c809e, \"vel\"), &vel, Script::ASSERT);\r\n\tGetObject()->SetVel( vel );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CVelocityComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calline InitFromStructure()\r\n\t// but if that does not handle it, then will need to write a specific \r\n\t// function here. \r\n\t// The user might only want to update a single field in the structure\r\n\t// and we don't want to be asserting becasue everything is missing \r\n\t\r\n\t//InitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVelocityComponent::Finalize()\r\n{\r\n\tmp_suspend_component =  GetSuspendComponentFromObject( GetObject() );\r\n}\r\n\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCVelocityComponent::Hide( bool should_hide )\r\n{\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CVelocityComponent::Update()\r\n{\r\n\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tif (gamenet_man->InNetGame() || !mp_suspend_component->SkipLogic())\r\n\t{\r\n\t\tMth::Vector pos, cur_pos, vel;\r\n\r\n\t\tcur_pos = GetObject()->GetPos();\r\n\t\tvel = GetObject()->GetVel();\r\n\t\tpos = cur_pos + ( GetObject()->GetVel() * 0.5f * Tmr::FrameLength());\r\n\t\tGetObject()->SetPos( pos );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CVelocityComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVelocityComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CVelocityComponent::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\t\r\n\r\n// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/VelocityComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       VelocityComponent.h\r\n//* OWNER:          SPG\r\n//* CREATION DATE:  07/10/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_VELOCITYCOMPONENT_H__\r\n#define __COMPONENTS_VELOCITYCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/components/suspendcomponent.h>\r\n\r\n// Replace this with the CRCD of the component you are adding\r\n#define\t\tCRC_VELOCITY CRCD(0x41272956,\"Velocity\")\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or \r\n//  given an object\t\t\t\t \r\n#define\t\tGetVelocityComponent() ((Obj::CVelocityComponent*)GetComponent(CRC_VELOCITY))\r\n#define\t\tGetVelocityComponentFromObject(pObj) ((Obj::CVelocityComponent*)(pObj)->GetComponent(CRC_VELOCITY))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CVelocityComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CVelocityComponent();\r\n    virtual ~CVelocityComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void\t\t\t\t\tHide( bool should_hide );\r\n\tvirtual void\t\t\t\t\tFinalize();\r\n\t\t\r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\nprivate:\r\n\tCSuspendComponent*\tmp_suspend_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/VibrationComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       VibrationComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  2/25/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/vibrationcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n\r\n#include <sk/objects/skater.h>\r\n#include <sk/modules/frontend/frontend.h>\r\n\r\nnamespace Obj\r\n{\r\n\t\r\n// Component giving script control through a composite object over the input pad vibrators of the composite object's input handler.\r\n\t\r\n// Only composite objects corresponding to local clients should be given this component.\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CVibrationComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CVibrationComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCVibrationComponent::CVibrationComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_VIBRATION );\r\n\t\r\n\tm_active_state = false;\r\n\t\r\n\tfor (int n = vVB_NUM_ACTUATORS; n--; )\r\n\t{\r\n\t\tmp_vibration_timers[n].active = false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCVibrationComponent::~CVibrationComponent()\r\n{\r\n\tif (mp_input_device)\r\n\t{\r\n\t\t// turn off all vibration\r\n\t\tfor (int i = vVB_NUM_ACTUATORS; i--; )\r\n\t\t{\r\n\t\t\tmp_input_device->ActivateActuator(i, 0);\r\n\t\t}\r\n\t\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVibrationComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVibrationComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVibrationComponent::Update()\r\n{\r\n\tDbg_Assert(mp_input_device);\r\n\t\r\n\tif (!m_active_state)\r\n\t{\r\n\t\tSuspend(true);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// check the duration of active actuators\r\n\tfor (int i = vVB_NUM_ACTUATORS; i--; )\r\n\t{\r\n\t\t// actuator inactive or has no associated duration\r\n\t\tif (!mp_vibration_timers[i].active) continue;\r\n\t\t\r\n\t\t// duration not yet up\r\n\t\tif (Tmr::ElapsedTime(mp_vibration_timers[i].start_time) < mp_vibration_timers[i].duration) continue;\r\n\t\t\r\n\t\t// NOTE: ignoring all replay code in VibrationComponent for now\r\n\t\t// Replay::WritePadVibration(i, 0);\r\n\t\t\r\n\t\t// turn off actuator\r\n\t\tmp_input_device->ActivateActuator(i, 0);\r\n\t\t\r\n\t\tmp_vibration_timers[i].active = false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CVibrationComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | Vibrate | \r\n        // @parm int | Actuator | actuator num\r\n        // @parmopt float | Percent | 0 | \r\n        // @flag Off | turn off both actuators\r\n        // @parmopt float | Duration | 0 | time to vibrate\r\n\t\tcase CRCC(0xdf8a5f0a, \"Vibrate\"):\r\n\t\t{\r\n\t\t\t// NOTE: ignoring pause state in VibrationComponent for now\r\n\t\t\t// Don't let it be switched on if skater is paused\r\n\t\t\tif (!pParams->ContainsFlag(CRCD(0xd443a2bc, \"Off\")) && (Mdl::FrontEnd::Instance()->GamePaused() || GetObject()->IsPaused())) break;\r\n\t\t\r\n\t\t\tDbg_MsgAssert(mp_input_device, (\"No associated input device\"));\r\n\t\t\t\r\n\t\t\tif (!m_active_state) break;\r\n\t\t\t\r\n\t\t\tint actuator_idx = 0;\r\n\t\t\tpParams->GetInteger(CRCD(0x114fc131, \"actuator\"), &actuator_idx);\r\n\t\t\tDbg_MsgAssert(actuator_idx >= 0 && actuator_idx < vVB_NUM_ACTUATORS, (\"%s\\nActuator must be between 0 and %d\", pScript->GetScriptInfo(), vVB_NUM_ACTUATORS));\r\n\r\n\t\t\tfloat percent = 0;\r\n\t\t\tpParams->GetFloat(CRCD(0x9e497fc6, \"percent\"), &percent);\r\n\t\t\tDbg_MsgAssert(percent >= 0 && percent <= 100, (\"\\n%s\\nPercent must be between 0 and 100\", pScript->GetScriptInfo()));\r\n\t\t\r\n\t\t\tif (pParams->ContainsFlag(\"off\"))\r\n\t\t\t{\r\n\t\t\t\t// This will switch off vibration, including if the game is paused.\r\n\t\t\t\t// Ie, unpausing won't restore the old vibration. Hooray!\r\n\t\t\t\tmp_input_device->StopAllVibrationIncludingSaved();\r\n\t\t\t\t\r\n\t\t\t\tfor (int i = vVB_NUM_ACTUATORS; i--; )\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_vibration_timers[i].active = false;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// NOTE: ignoring all replay code in VibrationComponent for now\r\n\t\t\t\t// for (int i = vVB_NUM_ACTUATORS; i--; )\r\n\t\t\t\t// {\r\n\t\t\t\t\t// Replay::WritePadVibration(i, 0);\r\n\t\t\t\t// }\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// NOTE: ignoring all replay code in VibrationComponent for now\r\n\t\t\t\t// Replay::WritePadVibration(Actuator, (int)Percent);\r\n\t\t\t\tmp_input_device->ActivateActuator(actuator_idx, static_cast<int>(percent));\r\n\t\t\t}\t\r\n\t\t\r\n\t\t\t// record duration so that we can later turn off the actuator; a duration of 0 gives an unbounded duration\r\n\t\t\tfloat duration = 0;\r\n\t\t\tif (pParams->GetFloat(CRCD(0x79a07f3f, \"duration\"), &duration))\r\n\t\t\t{\r\n\t\t\t\tmp_vibration_timers[actuator_idx].active = true;\r\n\t\t\t\tmp_vibration_timers[actuator_idx].duration = static_cast<Tmr::Time>(1000.0f * duration);\r\n\t\t\t\tmp_vibration_timers[actuator_idx].start_time = Tmr::GetTime();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmp_vibration_timers[actuator_idx].active = false;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\t\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVibrationComponent::GetDebugInfo ( Script::CStruct *p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CVibrationComponent::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddInteger(\"m_active_state\", m_active_state);\r\n\tScript::CArray* p_timers_array = new Script::CArray;\r\n\tp_timers_array->SetArrayType(vVB_NUM_ACTUATORS, ESYMBOLTYPE_STRUCTURE);\r\n\tfor (int i = vVB_NUM_ACTUATORS; i--; )\r\n\t{\r\n\t\tScript::CStruct* p_timer_structure = new Script::CStruct;\r\n\t\tp_timer_structure->AddInteger(\"active\", mp_vibration_timers[i].active);\r\n\t\tp_timer_structure->AddInteger(\"duration\", mp_vibration_timers[i].duration);\r\n\t\tp_timers_array->SetStructure(i, p_timer_structure);\r\n\t}\r\n\tp_info->AddArray(\"mp_vibration_timers\", p_timers_array);\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVibrationComponent::StopAllVibration (   )\r\n{\r\n\tif (!m_active_state) return;\r\n\t\r\n\tDbg_Assert(mp_input_device);\r\n\t\r\n\t// NOTE: no real expanation for this, so I'm ignoring it until it breaks the code\t\r\n\t// #ifndef __PLAT_NGC__\r\n\tfor (int i = vVB_NUM_ACTUATORS; i--; )\r\n\t{\r\n\t\t// NOTE: ignoring all replay code in VibrationComponent for now\r\n\t\t// Replay::WritePadVibration(i, 0);\r\n\t\t\r\n\t\tmp_input_device->ActivateActuator(i, 0);\r\n\t\t\r\n\t\tmp_vibration_timers[i].active = false;\r\n\t}\r\n\t// #endif // __PLAT_NGC__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVibrationComponent::Reset (   )\r\n{\r\n\tDbg_Assert(mp_input_device);\r\n\t\r\n\tmp_input_device->ResetActuators();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVibrationComponent::SetActive (   )\r\n{\r\n\tif (m_active_state) return;\r\n\t\r\n\tm_active_state = true;\r\n\tSuspend(false);\r\n\t\r\n\tif (!mp_input_device) return;\r\n\tmp_input_device->EnableActuators();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVibrationComponent::SetInactive (   )\r\n{\r\n\tif (!m_active_state) return;\r\n\t\r\n\tm_active_state = false;\r\n\tSuspend(true);\r\n\t\r\n\tif (!mp_input_device) return;\r\n\tmp_input_device->StopAllVibrationIncludingSaved();\r\n\tmp_input_device->DisableActuators();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVibrationComponent::SetActiveState ( bool state )\r\n{\r\n\tif (state == m_active_state) return;\r\n\t\r\n\tif (state)\r\n\t{\r\n\t\tSetActive();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSetInactive();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVibrationComponent::SetDevice ( SIO::Device* p_input_device )\r\n{\r\n\tDbg_Assert(p_input_device);\r\n\t\r\n\tmp_input_device = p_input_device;\r\n\t\r\n\tif (m_active_state)\r\n\t{\r\n\t\tmp_input_device->EnableActuators();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_input_device->DisableActuators();\r\n\t}\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/VibrationComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       VibrationComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  2/25/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_VIBRATIONCOMPONENT_H__\r\n#define __COMPONENTS_VIBRATIONCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <sys/siodev.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_VIBRATION CRCD(0x404eb936, \"Vibration\")\r\n\r\n#define\t\tGetVibrationComponent() ((Obj::CVibrationComponent*)GetComponent(CRC_VIBRATION))\r\n#define\t\tGetVibrationComponentFromObject(pObj) ((Obj::CVibrationComponent*)(pObj)->GetComponent(CRC_VIBRATION))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CVibrationComponent : public CBaseComponent\r\n{\r\npublic:\r\n\tstatic const int vVB_NUM_ACTUATORS = 2;\r\n\t\r\nprivate:\t\r\n\t// contains the information which defines the state of a vibration actuator\r\n\tstruct SVibrationTimer\r\n\t{\r\n\t\tbool active;\r\n\t\tTmr::Time start_time;\r\n\t\tTmr::Time duration;\r\n\t};\r\n\t\r\npublic:\r\n    CVibrationComponent();\r\n    virtual ~CVibrationComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate (   );\r\n    virtual void            \t\tInitFromStructure ( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure ( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction ( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo ( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tStopAllVibration (   );\r\n\tvoid\t\t\t\t\t\t\tReset (   );\r\n\tvoid\t\t\t\t\t\t\tSetActive (   );\r\n\tvoid\t\t\t\t\t\t\tSetInactive (   );\r\n\tvoid\t\t\t\t\t\t\tSetActiveState ( bool state );\r\n\tvoid\t\t\t\t\t\t\tSetDevice ( SIO::Device* p_input_device );\r\n\t\r\nprivate:\r\n\tbool\t\t\t\t\t\t\tm_active_state;\r\n\t\r\n\tSVibrationTimer\t\t\t\t\tmp_vibration_timers[vVB_NUM_ACTUATORS];\r\n\t\r\n\tSIO::Device*\t\t\t\t\tmp_input_device;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/WalkCameraComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       WalkCameraComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  4/9/3\r\n//****************************************************************************\r\n\r\n#ifdef TESTING_GUNSLINGER\r\n\r\n// Replace the entire contents of this file with the new file.\r\n#include <gel/components/gunslingerwalkcameracomponent.cpp>\r\n\r\n#else\r\n\r\n#include <gel/components/walkcameracomponent.h>\r\n#include <core/math/slerp.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/components/walkcomponent.h>\r\n#include <gel/components/camerautil.h>\r\n#include <gel/components/cameralookaroundcomponent.h>\r\n#include <gel/components/cameracomponent.h>\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n#include <gel/components/skatercameracomponent.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gfx/debuggfx.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CWalkCameraComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CWalkCameraComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCWalkCameraComponent::CWalkCameraComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_WALKCAMERA );\r\n\tm_last_tripod_pos.Set();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCWalkCameraComponent::~CWalkCameraComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tuint32 target_id = 0 ;\r\n\tpParams->GetChecksum(\"CameraTarget\", &target_id, Script::ASSERT);\r\n\t\r\n\tCCompositeObject* p_target = static_cast< CCompositeObject* >(CCompositeObjectManager::Instance()->GetObjectByID(target_id));\r\n\tDbg_MsgAssert(p_target, (\"Bad CameraTarget given to WalkCameraComponent\"));\r\n\t\t\r\n\tset_target(p_target);\r\n\t\r\n\tm_last_dot = 1.0f;\r\n\tm_current_zoom = 1.0f;\r\n\t\r\n\tm_last_actual_matrix = GetObject()->GetMatrix();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::Finalize()\r\n{\r\n\tmp_lookaround_component = GetCameraLookAroundComponentFromObject(GetObject());\r\n\tmp_camera_component = GetCameraComponentFromObject(GetObject());\r\n\tmp_skater_camera_component = GetSkaterCameraComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_lookaround_component);\r\n\tDbg_Assert(mp_camera_component);\r\n\tDbg_Assert(mp_skater_camera_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::Update()\r\n{\r\n\tif (!mp_target) return;\r\n\t\r\n\t// optimization KLUDGE\r\n\tif (mp_target_physics_control_component && mp_target_physics_control_component->IsDriving())\r\n\t{\r\n\t\tGetObject()->Pause(true);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif (mp_target->HasTeleported())\r\n\t{\r\n\t\tm_instant_count = 3;\r\n\t}\r\n\r\n\tbool instantly;\r\n\tif (m_instant_count > 0)\r\n\t{\r\n\t\t--m_instant_count;\r\n\t\tinstantly = true;\r\n\t}\r\n\telse if (m_reset)\r\n\t{\r\n\t\tinstantly = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tinstantly = false;\r\n\t}\r\n\t\r\n\tmp_camera_component->StoreOldPosition();\r\n\r\n\tfloat frame_length = Tmr::FrameLength();\r\n\t\r\n\t// get input\r\n\tfloat horiz_control = GetInputComponentFromObject(GetObject())->GetControlPad().m_scaled_rightX;\r\n\r\n\t// restore camera position from last frame, previous to refocusing and collision detection\r\n\tGetObject()->GetMatrix() = m_last_actual_matrix;\r\n\r\n\tMth::Vector\ttarget_facing = -GetObject()->GetMatrix()[Z];\r\n\ttarget_facing[Y] = 0.0f;\r\n\ttarget_facing.Normalize();\r\n\t\r\n\tMth::Vector subject_facing = mp_target->GetMatrix()[Z];\r\n\tsubject_facing[Y] = 0.0f;\r\n\tsubject_facing.Normalize();\r\n\t\r\n\t// two options; we either use our old facing as the target facing or use the subject's facing as the target facing\r\n\tbool use_subject_facing = true;\r\n\t\r\n\t// if in a flush request\r\n\tif (m_flush_request_active)\r\n\t{\r\n\t\t// always use the subject's matrix\r\n\t}\r\n\t// if controlling camera\r\n\telse if (horiz_control != 0.0f)\r\n\t{\r\n\t\tuse_subject_facing = false;\r\n\t}\r\n\t// if the subject's facing is towards the camera\r\n\telse if (Mth::DotProduct(target_facing, subject_facing) < cosf(Mth::DegToRad(s_get_param(CRCD(0xb8da8a73, \"lock_angle\")))))\r\n\t{\r\n\t\tuse_subject_facing = false;\r\n\t}\r\n\t// if the subject is moving very slowly\r\n\telse // if (!mp_target_walk_component->UseDPadCamera())\r\n\t{\r\n\t\tfloat full_slerp_speed;\r\n\t\tfloat min_slerp_speed;\r\n\t\tif (!mp_target_walk_component->UseDPadCamera())\r\n\t\t{\r\n\t\t\tfull_slerp_speed = s_get_param(CRCD(0xbcef6dda, \"full_slerp_speed\"));\r\n\t\t\tmin_slerp_speed = s_get_param(CRCD(0x824349e5, \"min_slerp_speed\"));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfull_slerp_speed = s_get_param(CRCD(0x73da1ec0, \"dpad_full_slerp_speed\"));\r\n\t\t\tmin_slerp_speed = s_get_param(CRCD(0xda5cad3, \"dpad_min_slerp_speed\"));\r\n\t\t}\r\n\t\t\r\n\t\tfloat target_vel = sqrtf(mp_target->GetVel()[X] * mp_target->GetVel()[X] + mp_target->GetVel()[Z] * mp_target->GetVel()[Z]);\r\n\t\tif (target_vel < full_slerp_speed)\r\n\t\t{\r\n\t\t\tuse_subject_facing = false;\r\n\t\t\t\r\n\t\t\t// for a middle range of velocities, lerp to use of the subject's matrix\r\n\t\t\tif (target_vel > min_slerp_speed)\r\n\t\t\t{\r\n\t\t\t\ttarget_facing = Mth::LinearMap(\r\n\t\t\t\t\ttarget_facing,\r\n\t\t\t\t\tsubject_facing,\r\n\t\t\t\t\ttarget_vel,\r\n\t\t\t\t\tmin_slerp_speed,\r\n\t\t\t\t\tfull_slerp_speed\r\n\t\t\t\t);\r\n\t\t\t\ttarget_facing.Normalize();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (use_subject_facing || m_reset)\r\n\t{\r\n\t\ttarget_facing = subject_facing;\r\n\t}\r\n\t\r\n\t// control over target facing\r\n\tif (horiz_control != 0.0f && !m_flush_request_active)\r\n\t{\r\n\t\ttarget_facing.RotateY(s_get_param(CRCD(0xf6f69dc8, \"facing_control\")) * horiz_control);\r\n\t}\r\n\t\r\n\tif (m_override_active)\r\n\t{\r\n\t\ttarget_facing = m_override_facing;\r\n\t\ttarget_facing.RotateY(mp_lookaround_component->mLookaroundHeading);\r\n\t}\r\n\t\r\n\t// build target matrix\r\n\tMth::Matrix target_matrix;\r\n\ttarget_matrix[Z] = target_facing;\r\n\ttarget_matrix[Y].Set(0.0f, 1.0f, 0.0f);\r\n\ttarget_matrix[X].Set(target_facing[Z], 0.0f, -target_facing[X]);\r\n\ttarget_matrix[W].Set();\r\n\t\r\n\t// apply lookaround adjustments to the matrix\r\n\ttarget_matrix.RotateXLocal(mp_skater_camera_component->mTilt + mp_lookaround_component->mLookaroundTilt);\r\n\t\r\n\ttarget_matrix[X] = -target_matrix[X];\r\n\ttarget_matrix[Z] = -target_matrix[Z];\r\n\t\r\n\t// use later for camera position\r\n\tMth::Vector up = mp_target->GetMatrix()[Y];\r\n\t\r\n\tif (!instantly)\r\n\t{\r\n\t\tif (Mth::DotProduct(target_matrix[X], GetObject()->GetMatrix()[X]) > CAMERA_SLERP_STOP\r\n\t\t\t&& Mth::DotProduct(target_matrix[Y], GetObject()->GetMatrix()[Y]) > CAMERA_SLERP_STOP\r\n\t\t\t&& Mth::DotProduct(target_matrix[Z], GetObject()->GetMatrix()[Z]) > CAMERA_SLERP_STOP)\r\n\t\t{\r\n\t\t\t// we're already at our target, so don't do anything\r\n\t\t\t\r\n\t\t\t// turn off any flush request\r\n\t\t\tif (m_flush_request_active)\r\n\t\t\t{\r\n\t\t\t\tm_flush_request_active = false;\r\n\t\t\t\tmp_target_walk_component->SetForwardControlLock(false);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// slerp to the target matrix\r\n\t\t\t\r\n\t\t\tMth::SlerpInterpolator slerper(&GetObject()->GetMatrix(), &target_matrix);\r\n\t\t\t\r\n\t\t\t// standard slerp rate\r\n\t\t\tfloat slerp = s_get_param(CRCD(0xc39b639, \"matrix_slerp_rate\"));\r\n\t\t\t\r\n\t\t\t// running slerp rate adjustment\r\n\t\t\tif (mp_target_walk_component->IsRunning())\r\n\t\t\t{\r\n\t\t\t\tslerp *= s_get_param(CRCD(0xd25348eb, \"run_slerp_factor\"));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// animation wait and ladder slerp rate adjustment\r\n\t\t\t// NOTE: replace with target facing override?\r\n\t\t\tif (mp_target_walk_component->GetState() == CWalkComponent::WALKING_ANIMWAIT || mp_target_walk_component->GetState() == CWalkComponent::WALKING_LADDER)\r\n\t\t\t{\r\n\t\t\t\tslerp *= 2.0f;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// if controlling the facing\r\n\t\t\tif (horiz_control != 0.0f && !m_flush_request_active)\r\n\t\t\t{\r\n\t\t\t\tslerp *= s_get_param(CRCD(0xb2da3c87, \"control_slerp_factor\")) * Mth::Abs(horiz_control);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// flush request slerp adjustment\r\n\t\t\tif (m_flush_request_active)\r\n\t\t\t{\r\n\t\t\t\tslerp *= s_get_param(CRCD(0x7178e048, \"flush_slerp_factor\"));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (m_override_active)\r\n\t\t\t{\r\n\t\t\t\t// can't override flush speed\r\n\t\t\t\tif (m_flush_request_active)\r\n\t\t\t\t{\r\n\t\t\t\t\tslerp = s_get_param(CRCD(0xc39b639, \"matrix_slerp_rate\")) * s_get_param(CRCD(0x7178e048, \"flush_slerp_factor\"));\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tslerp = m_override_slerp_rate;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// apply the slerping\r\n\t\t\tslerper.getMatrix(&GetObject()->GetMatrix(), GetTimeAdjustedSlerp(slerp, frame_length));\r\n\r\n\t\t\t// calculate for the skater camera\r\n\t\t\tm_last_dot = Mth::DotProduct(m_last_actual_matrix[Z], GetObject()->GetMatrix()[Z]);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGetObject()->GetMatrix() = target_matrix;\r\n\t}\r\n\t\r\n\t// At this point, GetObject()->GetMatrix() is valid to store.\r\n\tm_last_actual_matrix = GetObject()->GetMatrix();\r\n\t\r\n\t// Set camera position to be the same as the skater.\r\n\tMth::Vector\tcamera_pos = get_tripod_pos(instantly);\r\n\t\r\n\t// Calculate zoom\r\n\tfloat above, behind;\r\n\tcalculate_zoom(above, behind);\r\n\t\r\n\tcamera_pos += GetObject()->GetMatrix()[Z] * behind + up * above;\r\n\t\r\n\tMth::Vector\tfocus_pos = mp_target->GetPos() + up * above;\r\n\t\r\n\t// Focus the camera directly on the target object\r\n\t\r\n\ttarget_matrix[Z] = focus_pos - camera_pos;\r\n\ttarget_matrix[Z].Normalize();\r\n\r\n\t// Read back the Y from the current matrix.\r\n\ttarget_matrix[Y] = GetObject()->GetMatrix()[Y];\r\n\r\n\t// Generate new orthonormal X and Y axes.\r\n\ttarget_matrix[X] = Mth::CrossProduct(target_matrix[Y], target_matrix[Z]);\r\n\ttarget_matrix[X].Normalize();\r\n\ttarget_matrix[Y] = Mth::CrossProduct(target_matrix[Z], target_matrix[X]);\r\n\ttarget_matrix[Y].Normalize();\r\n\r\n\t// Write back into camera matrix.\r\n\t// Since camera points in -Z, but player in +Z, we must negate the X and Z axes\r\n\tGetObject()->GetMatrix()[X]\t= -target_matrix[X];\r\n\tGetObject()->GetMatrix()[Y] = target_matrix[Y];\r\n\tGetObject()->GetMatrix()[Z] = -target_matrix[Z];\r\n\t\r\n\t// clean up matrix\r\n\tGetObject()->GetMatrix()[X][W] = 0.0f;\r\n\tGetObject()->GetMatrix()[Y][W] = 0.0f;\r\n\tGetObject()->GetMatrix()[Z][W] = 0.0f;\r\n\tGetObject()->GetMatrix()[W].Set(0.0f, 0.0f, 0.0f, 1.0f);\r\n\t\r\n\t// Now do collision detection.\r\n\tApplyCameraCollisionDetection(\r\n\t\tcamera_pos,\r\n\t\tGetObject()->GetMatrix(),\r\n\t\tcamera_pos - GetObject()->GetMatrix()[Z] * behind + mp_target_walk_component->GetCameraCollisionTargetOffset(),\r\n\t\tfocus_pos\r\n\t);\r\n\t\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tGfx::AddDebugStar(focus_pos, 24.0f, MAKE_RGB(255, 200, 0), 1);\r\n\t}\r\n\t#endif\r\n\t\r\n\tcamera_pos[W] = 1.0f;\r\n\tGetObject()->SetPos(camera_pos);\r\n\t\r\n\t// reset old position if in instant update\r\n\tif (instantly)\r\n\t{\r\n\t\tmp_camera_component->StoreOldPosition();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CWalkCameraComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | WalkCamera_FlushRequest | Force the camera to lerp quickly to behind the walker\r\n\t\tcase CRCC(0x73febd0f, \"WalkCamera_FlushRequest\"):\r\n\t\t\tFlushRequest();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | WalkCamera_Reset | Teleports the camera to behind the target\r\n\t\tcase CRCC(0xd1a485d1, \"WalkCamera_Reset\"):\r\n\t\t\tReset();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CWalkCameraComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::ReadyForActivation ( const SCameraState& state )\r\n{\r\n\tDbg_MsgAssert(mp_target, (\"Walk camera (%s) has NULL target\", Script::FindChecksumName(GetObject()->GetID())));\r\n\t\r\n\tm_last_tripod_pos = state.lastTripodPos;\r\n\tm_last_actual_matrix = state.lastActualMatrix;\r\n\tm_last_dot = state.lastDot;\r\n\tm_current_zoom = state.lastZoom;\r\n\tm_flush_request_active = false;\r\n\tmp_target_walk_component->SetForwardControlLock(false);\r\n\tm_instant_count = 0;\r\n\t\r\n\tmp_lookaround_component->mLookaroundHeading = 0.0f;\r\n\tmp_lookaround_component->mLookaroundLock = false;\r\n\t\r\n\tm_override_active = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::GetCameraState ( SCameraState& state )\r\n{\r\n\tstate.lastActualMatrix = m_last_actual_matrix;\r\n\tstate.lastTripodPos = m_last_tripod_pos;\r\n\tstate.lastDot = m_last_dot;\r\n\tstate.lastZoom = m_current_zoom;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::FlushRequest (   )\r\n{\r\n\tm_flush_request_active = true;\r\n\tmp_target_walk_component->SetForwardControlLock(true);\r\n\t\r\n\t// flush requests zero skater cam lookaround\r\n\tmp_lookaround_component->mLookaroundHeading = 0.0f;\r\n\tmp_lookaround_component->mLookaroundTilt = 0.0f;\r\n\tmp_lookaround_component->mLookaroundZoom = 1.0f;\r\n\tmp_lookaround_component->mLookaroundLock = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::Reset (   )\r\n{\r\n\tm_reset = true;\r\n\tUpdate();\r\n\tm_reset = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::set_target ( CCompositeObject* p_target )\r\n{\r\n\tif (p_target)\r\n\t{\r\n\t\tmp_target = p_target;\r\n\t\t\r\n\t\tmp_target_walk_component = GetWalkComponentFromObject(mp_target);\r\n\t\tDbg_Assert(mp_target_walk_component);\r\n\t\t\r\n\t\tmp_target_physics_control_component = GetSkaterPhysicsControlComponentFromObject(mp_target);\r\n\t\tDbg_Assert(mp_target_physics_control_component);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_target = NULL;\r\n\t\tmp_target_walk_component = NULL;\r\n\t\tmp_target_physics_control_component = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CWalkCameraComponent::get_tripod_pos( bool instantly )\r\n{\r\n\tif (instantly)\r\n\t{\r\n\t\tm_last_tripod_pos = mp_target->GetPos();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfloat lerp_xz = GetTimeAdjustedSlerp(mp_skater_camera_component->mLerpXZ, Tmr::FrameLength());\r\n\t\tfloat lerp_y = GetTimeAdjustedSlerp(mp_skater_camera_component->mLerpY, Tmr::FrameLength());\r\n\t\t\r\n\t\tconst Mth::Vector& target_pos = mp_target->GetPos();\r\n\r\n\t\tm_last_tripod_pos.Set(\r\n\t\t\tMth::Lerp(m_last_tripod_pos[X], target_pos[X], lerp_xz),\r\n\t\t\tMth::Lerp(m_last_tripod_pos[Y], target_pos[Y], lerp_y),\r\n\t\t\tMth::Lerp(m_last_tripod_pos[Z], target_pos[Z], lerp_xz)\r\n\t\t);\r\n\t}\r\n\r\n\treturn m_last_tripod_pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkCameraComponent::calculate_zoom ( float& above, float& behind )\r\n{\r\n\tfloat target_zoom = 1.0f;\r\n\r\n\t// If lookaround override is set, factor in the lookaround override zoom.\r\n\tif (mp_lookaround_component->mLookaroundOverride && mp_lookaround_component->mLookaroundZoom != 1.0f)\r\n\t{\r\n\t\ttarget_zoom *= mp_lookaround_component->mLookaroundZoom;\r\n\t}\r\n\t\r\n\tm_current_zoom += ((target_zoom - m_current_zoom) * mp_skater_camera_component->mZoomLerp);\r\n\t\r\n\tbehind = mp_skater_camera_component->mBehind * m_current_zoom;\r\n\r\n\t// Behind is also shortened when the lookaround camera is tilting upwards.\r\n\tif (mp_lookaround_component->mLookaroundTilt < 0.0f)\r\n\t{\r\n\t\tfloat max_tilt = 3.14f * 0.2f;\r\n\t\tbehind = behind * (0.4f + (0.6f * ((max_tilt + mp_lookaround_component->mLookaroundTilt) / max_tilt)));\r\n\t}\r\n\r\n\t// Use lip_trick_above when doing a lip trick.\r\n\tfloat above_val = mp_skater_camera_component->mAbove;\r\n\t\r\n\t// Figure above tending towards the perfect above, if zoom is < 1.0.\r\n\tif (m_current_zoom < 1.0f)\r\n\t{\r\n\t\tabove = SKATERCAMERACOMPONENT_PERFECT_ABOVE + ((above_val - SKATERCAMERACOMPONENT_PERFECT_ABOVE) * m_current_zoom);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tabove = above_val;\r\n\t}\r\n}\r\n\r\n}\r\n\r\n#endif // TESTING_GUNSLINGER\r\n"
  },
  {
    "path": "Code/Gel/Components/WalkCameraComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       WalkCameraComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  4/9/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_WALKCAMERACOMPONENT_H__\r\n#define __COMPONENTS_WALKCAMERACOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/components/camerautil.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#define\t\tCRC_WALKCAMERA CRCD(0xc7d37ec2, \"WalkCamera\")\r\n\r\n#define\t\tGetWalkCameraComponent() ((Obj::CWalkCameraComponent*)GetComponent(CRC_WALKCAMERA))\r\n#define\t\tGetWalkCameraComponentFromObject(pObj) ((Obj::CWalkCameraComponent*)(pObj)->GetComponent(CRC_WALKCAMERA))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CWalkComponent;\r\n\tclass CCameraLookAroundComponent;\r\n\tclass CCameraComponent;\r\n\tclass CSkaterCameraComponent;\r\n\tclass CSkaterPhysicsControlComponent;\r\n\t\r\nclass CWalkCameraComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CWalkCameraComponent();\r\n    virtual ~CWalkCameraComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tReadyForActivation ( const SCameraState& state );\r\n\tvoid\t\t\t\t\t\t\tGetCameraState ( SCameraState& state );\r\n\tvoid\t\t\t\t\t\t\tSetOverrides ( const Mth::Vector& facing, float slerp_rate );\r\n\tvoid\t\t\t\t\t\t\tUnsetOverrides (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tFlushRequest (   );\r\n\tvoid\t\t\t\t\t\t\tReset (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetSkater ( CCompositeObject* p_skater );\r\n\t\r\nprivate:\r\n\tMth::Vector\t\t\t\t\t\tget_tripod_pos( bool instantly );\r\n\tvoid\t\t\t\t\t\t\tcalculate_zoom ( float& above, float& behind );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tset_target ( CCompositeObject* p_target );\r\n\t\r\n\tfloat\t\t\t\t\t\t\ts_get_param ( uint32 checksum );\r\n\t\r\nprivate:\r\n\tint\t\t\t\t\t\t\t\tm_instant_count;\r\n\tbool\t\t\t\t\t\t\tm_flush_request_active;\r\n\tbool\t\t\t\t\t\t\tm_reset;\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_current_zoom;\r\n\t\r\n\tMth::Vector\t\t\t\t\t\tm_last_tripod_pos;\r\n\tMth::Matrix\t\t\t\t\t\tm_last_actual_matrix;\r\n\tfloat\t\t\t\t\t\t\tm_last_dot;\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_override_active;\r\n\tMth::Vector\t\t\t\t\t\tm_override_facing;\r\n\tfloat\t\t\t\t\t\t\tm_override_slerp_rate;\r\n\t\r\n\tCCameraLookAroundComponent*\t\tmp_lookaround_component;\r\n\tCCameraComponent*\t\t\t\tmp_camera_component;\r\n\tCSkaterCameraComponent*\t\t\tmp_skater_camera_component;\r\n\t\r\n\tCCompositeObject*\t\t\t\tmp_target;\r\n\tCWalkComponent*\t\t\t\t\tmp_target_walk_component;\r\n\tCSkaterPhysicsControlComponent*\tmp_target_physics_control_component;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float CWalkCameraComponent::s_get_param ( uint32 checksum )\r\n{\r\n\tScript::CStruct* p_walk_params = Script::GetStructure(CRCD(0x1cda02ae, \"walk_camera_parameters\"));\r\n\tDbg_Assert(p_walk_params);\r\n\t\r\n\tfloat param;\r\n\tp_walk_params->GetFloat(checksum, &param, Script::ASSERT);\r\n\treturn param;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CWalkCameraComponent::SetOverrides ( const Mth::Vector& facing, float slerp_rate )\r\n{\r\n\tm_override_active = true;\r\n\tm_override_facing = facing;\r\n\tm_override_slerp_rate = slerp_rate;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CWalkCameraComponent::UnsetOverrides (   )\r\n{\r\n\tm_override_active = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CWalkCameraComponent::SetSkater ( CCompositeObject* p_skater )\r\n{\r\n\tset_target(p_skater);\r\n\tm_instant_count = 3;\r\n}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/WalkComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       WalkComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  4/2/3\r\n//****************************************************************************\r\n\r\n#ifdef TESTING_GUNSLINGER\r\n\r\n// Replace the entire contents of this file with the new file.\r\n#include <gel/components/gunslingerwalkcomponent.cpp>\r\n\r\n#else\r\n\r\n#include <gel/components/walkcomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/walkcameracomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/triggercomponent.h>\r\n#include <gel/components/movablecontactcomponent.h>\r\n#include <gel/components/railmanagercomponent.h>\r\n#include <gel/components/trickcomponent.h>\r\n#include <gel/components/shadowcomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/collision/collcache.h>\r\n\r\n#include <sk/objects/rail.h>\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/engine/feeler.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n#include <sk/components/skaterscorecomponent.h>\r\n\t\r\n/*\r\n * - Camera needs to initialize correctly at restarts.\r\n * - Faster camera slerp, smaller no-slerp angle during run out.\r\n * - Retain momentum better when leaving skating.\r\n * - Accidental manuals when interacting with ledges and ladders.\r\n * - Catching on curbs right after jump (use snap up code from skater)\r\n * - Hang\r\n *    - Jerky rail corners.\r\n *    - Turn around on wire hangs.\r\n *    - Drift to next rung effect in hanging too.\r\n *    - Special pull up to wire animation.\r\n * - Ladder\r\n *    - Drift between rungs.\r\n *    - Match rungs when getting on from the top.\r\n *    - Match rungs when grabbing from air.\r\n * - Hang from bottom of ladder.\r\n * - Ladder to rail across top.  Rail across top to ladder.\r\n * - Hand-plants, drop-ins, etc.\r\n * BUGS:\r\n * - Fall through verts with low frame rate.\r\n * - Pop in transition from last to first frames of slow cycling (walk/climb) animations.\r\n */\r\n \r\nextern bool g_CheatsEnabled;\r\n\r\nnamespace Obj\r\n{\r\n\tconst uint32 CWalkComponent::sp_state_names [ CWalkComponent::NUM_WALKING_STATES ] =\r\n\t{\r\n\t\tCRCC(0x8cf3cb28, \"WALKING_GROUND\"),\r\n\t\tCRCC(0x9d1f1a2c, \"WALKING_AIR\"),\r\n\t\tCRCC(0x74ffc46d, \"WALKING_HANG\"),\r\n\t\tCRCC(0x1cb1f465, \"WALKING_LADDER\"),\r\n\t\tCRCC(0x79be4637, \"WALKING_ANIMWAIT\")\r\n\t};\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CWalkComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CWalkComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCWalkComponent::CWalkComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_WALK );\r\n\t\r\n\tmp_collision_cache = Nx::CCollCacheManager::sCreateCollCache();\r\n\t\r\n\tmp_input_component = NULL;\r\n\tmp_animation_component = NULL;\r\n\tmp_model_component = NULL;\r\n\tmp_trigger_component = NULL;\r\n\tmp_physics_control_component = NULL;\r\n\tmp_movable_contact_component = NULL;\r\n\tmp_state_component = NULL;\r\n\tmp_core_physics_component = NULL;\r\n\t\r\n\tm_control_direction.Set();\r\n\tm_in_air_drift_vel.Set();\r\n\tm_rotate_upright_timer = 0.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCWalkComponent::~CWalkComponent()\r\n{\r\n\tNx::CCollCacheManager::sDestroyCollCache(mp_collision_cache);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::Finalize()\r\n{\r\n\tmp_input_component = GetInputComponentFromObject(GetObject());\r\n\tmp_animation_component = GetAnimationComponentFromObject(GetObject());\r\n\tmp_model_component = GetModelComponentFromObject(GetObject());\r\n\tmp_trigger_component = GetTriggerComponentFromObject(GetObject());\r\n\tmp_physics_control_component = GetSkaterPhysicsControlComponentFromObject(GetObject());\r\n\tmp_movable_contact_component = GetMovableContactComponentFromObject(GetObject());\r\n\tmp_state_component = GetSkaterStateComponentFromObject(GetObject());\r\n\tmp_core_physics_component = GetSkaterCorePhysicsComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_input_component);\r\n\tDbg_Assert(mp_animation_component);\r\n\tDbg_Assert(mp_model_component);\r\n\tDbg_Assert(mp_trigger_component);\r\n\tDbg_Assert(mp_physics_control_component);\r\n\tDbg_Assert(mp_movable_contact_component);\r\n\tDbg_Assert(mp_state_component);\r\n\tDbg_Assert(mp_core_physics_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tuint32 camera_id;\r\n\tif (pParams->GetChecksum(CRCD(0xc4e311fa, \"camera\"), &camera_id))\r\n\t{\r\n\t\tCCompositeObject* p_camera = static_cast< CCompositeObject* >(CCompositeObjectManager::Instance()->GetObjectByID(camera_id));\r\n\t\tDbg_MsgAssert(mp_camera, (\"No such camera object\"));\r\n\t\tSetAssociatedCamera(p_camera);\r\n\t}\r\n\t\r\n\t#ifdef SCRIPT_WALK_DRAG\r\n\tm_script_drag_factor = 1.0f;\r\n\t#endif\r\n}\r\n\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::Update()\r\n{\r\n\tuint32 previous_frame_event = m_frame_event;\r\n\t\r\n\t// TEMP: debounce R1 after a transition\r\n\tif (m_ignore_grab_button && !mp_input_component->GetControlPad().m_R1.GetPressed())\r\n\t{\r\n\t\tm_ignore_grab_button = false;\r\n\t}\r\n\t\r\n\t// zero the frame event\r\n\tm_last_frame_event = m_frame_event;\r\n\tm_frame_event = 0;\r\n\t\r\n\t// get input\r\n    get_controller_input();\r\n\t\r\n\t// extract initial state for this frame from the object\r\n\textract_state_from_object();\r\n\t\r\n\tm_frame_start_pos = m_pos;\r\n\t\r\n\t// set the frame length\r\n\tm_frame_length = Tmr::FrameLength();\r\n\t\r\n\t// go to our true Y position\r\n\tm_curb_float_height_adjusted = false;\r\n\tm_pos[Y] -= m_curb_float_height;\r\n\tDUMP_WPOSITION\r\n\t\r\n\t// lerp down to standard run speed if we're not in a combo\r\n\tupdate_run_speed_factor();\r\n\t\r\n\t// switch logic based on walking state\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase WALKING_GROUND:\r\n\t\t\tgo_on_ground_state();\r\n\t\t\tbreak;\r\n\r\n\t\tcase WALKING_AIR:\r\n\t\t\tgo_in_air_state();\r\n\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\t// case WALKING_HOP:\r\n\t\t\t// go_hop_state();\r\n\t\t\t// break;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\tcase WALKING_HANG:\r\n\t\t\tgo_hang_state();\r\n\t\t\tbreak;\r\n            \r\n\t\tcase WALKING_LADDER:\r\n\t\t\tgo_ladder_state();\r\n            break;\r\n\t\t\t\r\n\t\tcase WALKING_ANIMWAIT:\r\n\t\t\tgo_anim_wait_state (   );\r\n\t\t\tbreak;\r\n\t}\r\n\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\r\n\t// the there's no curb to adjust due to, lerp down to zero\r\n\tif (!m_curb_float_height_adjusted)\r\n\t{\r\n\t\tm_curb_float_height = Mth::Lerp(m_curb_float_height, 0.0f, s_get_param(CRCD(0x9b3388fa, \"curb_float_lerp_down_rate\")) * m_frame_length);\r\n\t}\r\n\t\r\n\t// adjust back to our curb float Y position\r\n\tm_pos[Y] += m_curb_float_height;\r\n\tDUMP_WPOSITION\r\n\t\r\n\t// maybe transition into skating via an acid drop from the ground\r\n\tif (m_state == WALKING_GROUND)\r\n\t{\r\n\t\tmaybe_jump_to_acid_drop();\r\n\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t}\r\n\t\r\n\t// adjust critical point offset\r\n\tupdate_critical_point_offset();\r\n\t\r\n\t// adjust the display offset\r\n\tupdate_display_offset();\r\n\t\r\n\t// keep the object from falling through holes in the geometry\r\n\tif (m_state == WALKING_GROUND || m_state == WALKING_AIR)\r\n\t{\r\n\t\tuber_frig();\r\n\t}\r\n\t\r\n\t// rotate to upright -- non-transition\r\n\tlerp_upright();\r\n\t\r\n\t// setup the object based on this frame's walking\r\n\tcopy_state_into_object();\r\n\t\r\n\t// rotate to upright -- transition\r\n\ttransition_lerp_upright();\r\n\t\r\n\t// smooth out the anim speed over two frames to minimize poppy behavior\r\n\tsmooth_anim_speed(previous_frame_event);\r\n\t\r\n\tDbg_Assert(m_frame_event);\r\n\tGetObject()->SelfEvent(m_frame_event);\r\n\t\r\n\t// set the animation speeds\r\n\tupdate_anim_speeds();\r\n\t\r\n\t// camera controls\r\n\tset_camera_overrides();\r\n\t\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tGfx::AddDebugStar(GetObject()->GetPos(), 36.0f, MAKE_RGB(255, 255, 255), 1);\r\n\t\tif (m_critical_point_offset.LengthSqr() != 0.0f)\r\n\t\t{\r\n\t\t\tGfx::AddDebugStar(GetObject()->GetPos() + m_critical_point_offset, 36.0f, MAKE_RGB(150, 255, 100), 1);\r\n\t\t}\r\n\t}\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CWalkComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | Walk_Ground |\r\n\t\tcase CRCC(0x893213e5, \"Walk_Ground\"):\r\n\t\t\treturn m_state == WALKING_GROUND ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Walk_Air |\r\n\t\tcase CRCC(0x5012082e, \"Walk_Air\"):\r\n\t\t\treturn m_state == WALKING_AIR ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Walk_Hang |\r\n\t\tcase CRCC(0x9a3ca853, \"Walk_Hang\"):\r\n\t\t\treturn m_state == WALKING_HANG ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Walk_Ladder |\r\n\t\tcase CRCC(0x19702ca8, \"Walk_Ladder\"):\r\n\t\t\treturn m_state == WALKING_LADDER ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Walk_AnimWait |\r\n\t\tcase CRCC(0x8fe2b013, \"Walk_AnimWait\"):\r\n\t\t\treturn m_state == WALKING_ANIMWAIT ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Walk_GetStateTime | Loads the time in milliseconds since last state change.\r\n\t\tcase CRCC(0xce64576c, \"Walk_GetStateTime\"):\r\n\t\t\tpScript->GetParams()->AddInteger(CRCD(0x5ab23cc9, \"StateTime\"), Tmr::ElapsedTime(m_state_timestamp));\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | Walk_Jump |\r\n\t\tcase CRCC(0x83e4bd70, \"Walk_Jump\"):\r\n\t\t\tjump();\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t#ifdef SCRIPT_WALK_DRAG\r\n\t\t// @script | Walk_SetDragFactor |\r\n\t\tcase CRCC(0xc6100a7d, \"Walk_SetDragFactor\"):\r\n\t\t\tpParams->GetFloat(NO_NAME, &m_script_drag_factor);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x4e4fae43, \"Walk_ResetDragFactor\"):\r\n\t\t\tm_script_drag_factor = 1.0f;\r\n\t\t\tbreak;\r\n\t\t#endif\r\n\t\t\t\r\n\t\tcase CRCC(0xaf04b983, \"Walk_GetSpeedScale\"):\r\n\t\t{\r\n\t\t\tuint32 checksum;\r\n\t\t\tif (m_anim_effective_speed < s_get_param(CRCD(0xf3649996, \"max_slow_walk_speed\")))\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x1150cabb, \"WALK_SLOW\");\r\n\t\t\t}\r\n\t\t\telse if (m_anim_effective_speed < s_get_param(CRCD(0x6a5805d8, \"max_fast_walk_speed\")))\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x131f2a2, \"WALK_FAST\");\r\n\t\t\t}\r\n\t\t\telse if (m_anim_effective_speed < s_get_param(CRCD(0x1c94cc9c, \"max_slow_run_speed\")))\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x5606d106, \"RUN_SLOW\");\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tchecksum = CRCD(0x4667e91f, \"RUN_FAST\");\r\n\t\t\t}\r\n\t\t\tpScript->GetParams()->AddChecksum(CRCD(0x92c388f, \"SpeedScale\"), checksum);\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | Walk_ScaleAnimSpeed | Sets the manner in which the walk animations speeds should be scaled.\r\n\t\t// @flag Off | No animation speed scaling.\r\n\t\t// @flag Run | Scale animation speeds against running speed.\r\n\t\t// @flag Walk | Scale animation speeds against walking speed.\r\n\t\tcase CRCC(0x56112c03, \"Walk_ScaleAnimSpeed\"):\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0xd443a2bc, \"Off\")))\r\n\t\t\t{\r\n\t\t\t\tif (m_anim_scale_speed != OFF)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_anim_scale_speed = OFF;\r\n\t\t\t\t\tmp_animation_component->SetAnimSpeed(1.0f, false, true);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0xaf895b3f, \"Run\")))\r\n\t\t\t{\r\n\t\t\t\tm_anim_scale_speed = RUNNING;\r\n\t\t\t}\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0x6384f1da, \"HangMove\")))\r\n\t\t\t{\r\n\t\t\t\tm_anim_scale_speed = HANGMOVE;\r\n\t\t\t}\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0xa2bfe505, \"LadderMove\")))\r\n\t\t\t{\r\n\t\t\t\tm_anim_scale_speed = LADDERMOVE;\r\n\t\t\t\t\r\n\t\t\t\t// force a server anim speed update\r\n\t\t\t\tm_last_ladder_anim_speed = -1.0f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(false, (\"Walk_ScaleAnimSpeed requires Off, Run, or Walk flag\"));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tpParams->GetFloat(CRCD(0xb2d59baf, \"StandardSpeed\"), &m_anim_standard_speed);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | Walk_AnimWaitComplete | Signal from script that the walk component should leave its animation wait\r\n\t\tcase CRCC(0x9d3eebe8, \"Walk_AnimWaitComplete\"):\r\n\t\t\tanim_wait_complete();\r\n\t\t\tbreak;\r\n\t\t\t\t   \t\t\t\r\n\t\t// @script | Walk_GetHangInitAnimType | Determine which type of initial hang animation should be played\r\n\t\tcase CRCC(0xc6cd659e, \"Walk_GetHangInitAnimType\"):\r\n\t\t\t// m_initial_hang_animation is set when the hang rail is filtered\r\n\t\t\tpScript->GetParams()->AddChecksum(CRCD(0x85fa9ac4, \"HangInitAnimType\"), m_initial_hang_animation);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | Walk_GetStateDuration | Returns the duration of the current state in StateDuration\r\n\t\tcase CRCC(0x55bf1cd6, \"Walk_GetStateDuration\"):\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x4b88e4e4, \"StateDuration\"), (1.0f / 1000.0f) * Tmr::ElapsedTime(m_state_timestamp));\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | Walk_GetPreviousState | Returns the previous state in PreviousState\r\n\t\tcase CRCC(0xe9b1cde8, \"Walk_GetPreviousState\"):\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddChecksum(CRCD(0xf78635da, \"PreviousState\"), sp_state_names[m_previous_state]);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | Walk_GetPreviousState | Returns the current state in State\r\n\t\tcase CRCC(0xac7b36c8, \"Walk_GetState\"):\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddChecksum(CRCD(0x5c6c2d04, \"State\"), sp_state_names[m_state]);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | Walk_GetHangAngle | Returns the current angle of the hang rail\r\n\t\tcase CRCC(0x7e01b923, \"Walk_GetHangAngle\"):\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(mp_physics_control_component->IsWalking(), (\"Called Walk_GetHangAngle when not in walk mode\"));\r\n\t\t\tDbg_MsgAssert(m_state == WALKING_HANG, (\"Called Walk_GetHangAngle when not hanging\"));\r\n\t\t\t\r\n\t\t\tMth::Vector rail_direction = (mp_rail_manager->GetPos(mp_rail_end) - mp_rail_manager->GetPos(mp_rail_start)).Normalize();\r\n\t\t\tfloat angle = asinf(rail_direction[Y]);\r\n\t\t\tif (Mth::CrossProduct(rail_direction, m_facing)[Y] < 0.0f)\r\n\t\t\t{\r\n\t\t\t\tangle = -angle;\r\n\t\t\t}\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0xead7d286, \"HangAngle\"), Mth::RadToDeg(angle));\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t/*\r\n\t\tcase CRCC(0x14e4985b, \"Walk_CancelTransitionalMomentum\"):\r\n\t\t\tm_cancel_transition_momentum = true;\r\n\t\t\tbreak;\r\n\t\t*/\r\n\t\t\r\n\t\t/*\r\n\t\t// @script | Walk_SuppressInAirControl | turn off in air velocity control for some number of seconds\r\n\t\tcase CRCC(0x30a9de5c, \"Walk_SuppressInAirControl\"):\r\n\t\t\tpParams->GetFloat(NO_NAME, &m_in_air_control_suppression_timer, Script::ASSERT);\r\n\t\t\tbreak;\r\n\t\t*/\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CWalkComponent::GetDebugInfo\"));\r\n\t\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase WALKING_GROUND:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0x58007c97, \"GROUND\"));\r\n\t\t\tbreak;\r\n\t\tcase WALKING_AIR:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0x439f4704, \"AIR\"));\r\n\t\t\tbreak;\r\n\t\t// case WALKING_HOP:\r\n\t\t\t// p_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0xf41aba21, \"HOP\"));\r\n\t\t\t// break;\t\t\t\t\t\t\t\t\t\t \r\n\t\tcase WALKING_HANG:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0x4194ecca, \"HANG\"));\r\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t \r\n        case WALKING_LADDER:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0xc84243da, \"LADDER\"));\r\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t \r\n        case WALKING_ANIMWAIT:\r\n\t\t\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), CRCD(0x4fe6069c, \"ANIMWAIT\"));\r\n\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t \r\n\t}\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::SetAssociatedCamera ( CCompositeObject* camera_obj )\r\n{\r\n\tmp_camera = camera_obj;\r\n\tDbg_Assert(mp_camera);\r\n\tmp_camera_component = GetWalkCameraComponentFromObject(mp_camera);\r\n\tDbg_MsgAssert(mp_camera_component, (\"No WalkCameraComponent in camera object\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::ReadyWalkState ( bool to_ground_state )\r\n{\r\n\t// setup the state in preparation for being in walking mode next object update\r\n\t\r\n    // always reset the state timestamp\r\n    m_state_timestamp = Tmr::GetTime();\r\n\t\r\n\tif (GetObject()->GetMatrix()[Y][Y] > 0.999f)\r\n\t{\r\n\t\tm_rotate_upright_timer = 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// if we're not upright, get ready to rotate to upright\r\n\t\tif (GetObject()->GetMatrix()[Y][Y] > -0.999f)\r\n\t\t{\r\n\t\t\tm_rotate_upright_axis.Set(-GetObject()->GetMatrix()[Y][Z], 0.0f, GetObject()->GetMatrix()[Y][X]);\r\n\t\t\tm_rotate_upright_angle = acosf(Mth::Clamp(GetObject()->GetMatrix()[Y][Y], -1.0f, 1.0f));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_rotate_upright_axis = GetObject()->GetMatrix()[X];\r\n\t\t\tm_rotate_upright_angle = Mth::PI;\r\n\t\t}\r\n        \r\n\t\tm_rotate_upright_timer = s_get_param(CRCD(0xb0675803, \"rotate_upright_duration\"));\r\n\t\t\r\n\t\tif (GetObject()->GetMatrix()[Y][Y] < 0.0f)\r\n\t\t{\r\n\t\t\tGetObject()->SetPos(GetObject()->GetPos() + 6.0f * GetObject()->GetMatrix()[Y]);\r\n\t\t\tto_ground_state = false;\r\n\t\t}\r\n\t}\r\n\r\n\tif (to_ground_state)\r\n\t{\r\n\t\tset_state(WALKING_GROUND);\r\n\t\t\r\n\t\t// will be incorrect for one frame\r\n\t\tm_ground_normal.Set(0.0f, 1.0f, 0.0);\r\n\t\t\r\n\t\tm_last_ground_feeler_valid = false;\r\n\t\t\r\n\t\tGetObject()->GetVel()[Y] = 0.0f;\r\n\t\t\r\n\t\tm_disallow_acid_drops = false;\r\n\r\n\t\t/*\r\n\t\tif (GetObject()->GetVel().LengthSqr() > Mth::Sqr(450.0f))\r\n\t\t{\r\n\t\t\tm_cancel_transition_momentum = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_cancel_transition_momentum = true;\r\n\t\t}\r\n\t\t*/\r\n\t}\r\n\telse\r\n\t{\r\n\t\tset_state(WALKING_AIR);\r\n\t\t\r\n\t\t// give a slight velocity boost when transitioning from vert air\r\n\t\tif (mp_core_physics_component->GetFlag(VERT_AIR) && m_rotate_upright_timer != 0.0f)\r\n\t\t{\r\n\t\t\tMth::Vector target_facing = GetObject()->GetMatrix()[Z];\r\n\t\t\ttarget_facing.Rotate(m_rotate_upright_axis, m_rotate_upright_angle);\r\n\t\t\tGetObject()->GetVel() += s_get_param(CRCD(0x17b37748, \"initial_vert_vel_boost\")) * target_facing;\r\n\t\t}\r\n\t\t\r\n\t\t// set primary air direction in the direction of velocity\r\n\t\tm_primary_air_direction = GetObject()->GetVel();\r\n\t\tm_primary_air_direction[Y] = 0.0f;\r\n\t\tfloat length = m_primary_air_direction.Length();\r\n\t\tif (length < 0.001f)\r\n\t\t{\r\n\t\t\t// or facing\r\n\t\t\tm_primary_air_direction = GetObject()->GetMatrix()[Z];\r\n\t\t\tm_primary_air_direction[Y] = 0.0f;\r\n\t\t\tlength = m_primary_air_direction.Length();\r\n\t\t\tif (length < 0.001f)\r\n\t\t\t{\r\n\t\t\t\t// or future facing\r\n\t\t\t\tm_primary_air_direction = -GetObject()->GetMatrix()[Y];\r\n\t\t\t\tm_primary_air_direction[Y] = 0.0f;\r\n\t\t\t\tlength = m_primary_air_direction.Length();\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_primary_air_direction /= length;\r\n\t\t\r\n\t\tleave_movable_contact_for_air(GetObject()->GetVel(), GetObject()->GetVel()[Y]);\r\n\t\t\r\n\t\tm_in_air_control_suppression_timer = 0.0f;\r\n\t\t\r\n\t\tm_false_wall.active = false;\r\n\t\t\r\n\t\t// you have to touch the ground at least once before acid dropping out of walking\r\n\t\tm_disallow_acid_drops = mp_core_physics_component->GetFlag(VERT_AIR)\r\n\t\t\t|| mp_core_physics_component->GetFlag(AIR_ACID_DROP_DISALLOWED);\r\n\t\t\r\n\t\t// m_cancel_transition_momentum = true;\r\n\t}\r\n\r\n\tm_curb_float_height = 0.0f;\r\n\t\r\n\tm_special_transition_data.type = NO_SPECIAL_TRANSITION;\r\n\t\r\n\tm_last_frame_event = 0;\r\n\t\r\n\t// TEMP: debounce R1 after a transition\r\n\tm_ignore_grab_button = true;\r\n\t\r\n\tm_critical_point_offset.Set();\r\n\t\r\n\tm_display_offset = 0.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::CleanUpWalkState (   )\r\n{\r\n\tmp_model_component->SetDisplayOffset(Mth::Vector(0.0f, 0.0f, 0.0f));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::CollideWithOtherSkaterLost ( CCompositeObject* p_other_skater )\r\n{\r\n\tset_state(WALKING_AIR);\r\n\tm_primary_air_direction = GetObject()->GetVel();\r\n\tm_primary_air_direction[Y] = 0.0f;\r\n\tm_primary_air_direction.Normalize();\r\n\t\r\n\tleave_movable_contact_for_air(GetObject()->GetVel(), GetObject()->GetVel()[Y]);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::set_state ( EStateType state )\r\n{\r\n    if (state == m_state) return;\r\n\t\r\n\tm_previous_state = m_state;\r\n\tm_state = state;\r\n\tm_state_timestamp = Tmr::GetTime();\r\n\t\r\n    if (m_previous_state == WALKING_GROUND || m_previous_state == WALKING_AIR)\r\n    {\r\n        m_wall_push_test.active = false;\r\n\t\tm_run_toggle = false;\r\n    }\r\n\t\r\n\tif (m_previous_state == WALKING_AIR)\r\n\t{\r\n\t\tm_in_air_control_suppression_timer = 0.0f;\r\n\t}\r\n\r\n\tif (m_previous_state == WALKING_AIR)\r\n\t{\r\n\t\tm_in_air_drift_vel.Set();\r\n\t\t\r\n\t\tm_disallow_acid_drops = false;\r\n\t}\r\n\t\r\n\tif (m_state == WALKING_GROUND)\r\n\t{\r\n\t\tm_control_pegged_duration = 10000.0f;\r\n\t\tm_last_frame_controller_pegged = true;\r\n\t}\r\n\t\r\n\tif (m_state == WALKING_ANIMWAIT)\r\n\t{\r\n\t\tm_offset_due_to_movable_contact.Set();\r\n\t}\r\n\t\r\n\tif (m_state != WALKING_AIR)\r\n\t{\r\n\t\tm_false_wall.active = false;\r\n\t}\r\n\t\r\n\tif (m_state == WALKING_GROUND || m_previous_state != WALKING_AIR)\r\n\t{\r\n\t\tm_drop_rotation_rate = false;\r\n\t}\r\n\t\r\n\tif (m_state == WALKING_HANG)\r\n\t{\r\n\t\tm_hang_move_vel = 0.0f;\r\n\t}\r\n\t\r\n\tif (m_state == WALKING_HANG && m_previous_state == WALKING_AIR)\r\n\t{\r\n\t\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\tcontrol_pad.DebounceLeftAnalogUp(s_get_param(CRCD(0xac96d24b, \"hang_control_debounce_time\")));\r\n\t\tcontrol_pad.DebounceLeftAnalogDown(s_get_param(CRCD(0xac96d24b, \"hang_control_debounce_time\")));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::go_on_ground_state (   )\r\n{\r\n\taccount_for_movable_contact();\r\n\t\r\n\tsetup_collision_cache();\r\n\t\r\n\t// calculate initial horizontal speed\r\n\tfloat horizontal_speed = m_horizontal_vel.Length();\r\n\t\r\n\tcalculate_horizontal_speed_and_facing(horizontal_speed);\r\n\t\r\n\t// only skid if you've had the controller pegged for a minimum duration\r\n\tif (m_frame_event == CRCD(0x1d537eff, \"Skid\") && m_control_pegged_duration < s_get_param(CRCD(0x8e1cf27a, \"pegged_duration_for_skid\")))\r\n\t{\r\n\t\tm_frame_event = CRCD(0x9b46e749, \"Stand\");\r\n\t}\r\n\t\r\n\t// calculate this frame's movement\r\n\tm_horizontal_vel = horizontal_speed * m_facing;\r\n\t\r\n\t// prevent movement into walls\r\n\tif (adjust_horizonal_vel_for_environment())\r\n\t{\r\n\t\t// turn to face newly adjusted velocity\r\n\t\tadjust_facing_for_adjusted_horizontal_vel();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_drop_rotation_rate = false;\r\n\t}\r\n\t\r\n\t// if we are wall pushing, we may have decided to switch states during adjust_horizonal_vel_for_environment based on our environment\r\n\tif (m_state != WALKING_GROUND || mp_physics_control_component->HaveBeenReset())\r\n\t{\r\n\t\tCFeeler::sClearDefaultCache();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// apply movement for this frame\r\n\tm_pos += m_horizontal_vel * m_frame_length;\r\n\tDUMP_WPOSITION\r\n\t\r\n\t// snap up and down curbs and perhaps switch to air\r\n\trespond_to_ground();\r\n\tif (m_state != WALKING_GROUND || mp_physics_control_component->HaveBeenReset())\r\n\t{\r\n\t\tCFeeler::sClearDefaultCache();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tadjust_curb_float_height();\r\n\t\r\n\t// insure that we do not slip through the cracks in the collision geometry which are a side-effect of moving collidable objects\r\n\tif (CCompositeObject* p_inside_object = mp_movable_contact_component->CheckInsideObjects(m_pos, m_frame_start_pos))\r\n\t{\r\n\t\tMESSAGE(\"WALKING_GROUND, within moving object\");\r\n\t\t\r\n\t\t// allow it to push us forward, causing a bit of a stumble\r\n\t\tm_horizontal_vel = p_inside_object->GetVel();\r\n\t\tm_horizontal_vel[Y] = 0.0f;\r\n\t\tm_vertical_vel = 0.0f;\r\n\t\t\r\n\t\tfloat speed_sqr = m_horizontal_vel.LengthSqr();\r\n\t\tif (speed_sqr > (10.0f * 10.0f))\r\n\t\t{\r\n\t\t\tm_facing = m_horizontal_vel / sqrtf(speed_sqr);\r\n\t\t}\r\n\t}\r\n\t\r\n\tCFeeler::sClearDefaultCache();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::calculate_horizontal_speed_and_facing ( float &horizontal_speed )\r\n{\r\n\tif (m_control_pegged)\r\n\t{\r\n\t\tif (!m_last_frame_controller_pegged)\r\n\t\t{\r\n\t\t\tm_control_pegged_duration = 0.0f;\r\n\t\t}\r\n\t\tm_control_pegged_duration += m_frame_length;\r\n\t}\r\n\tm_last_frame_controller_pegged = m_control_pegged;\r\n\t\r\n\t// calculate user's desired speed\r\n\tfloat desired_speed = calculate_desired_speed();\r\n\t\r\n\t#ifdef SCRIPT_WALK_DRAG\r\n\t// adjust speed by the script set drag factor\r\n\tdesired_speed *= m_script_drag_factor;\r\n\t#endif\r\n\t\t\t   \t\r\n\t// setup frame's event\r\n\tif (desired_speed <= 0.0f)\r\n\t{\r\n\t\tm_frame_event = CRCD(0x9b46e749, \"Stand\");\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_frame_event = CRCD(0xaf895b3f, \"Run\");\r\n\t}\r\n\r\n\tbool special_acceleration = false;\r\n\t\r\n\t// adjust facing based on input\r\n\t\r\n\tif (m_control_magnitude > 0.0f)\r\n\t{\r\n\t\tfloat dot = Mth::DotProduct(m_facing, m_control_direction);\r\n\t\t\r\n\t\tif ((horizontal_speed < s_get_param(CRCD(0x52582d5b, \"max_rotate_in_place_speed\")) && dot < cosf(Mth::DegToRad(s_get_param(CRCD(0x5dff96a4, \"max_rotate_in_place_angle\")))))\r\n\t\t\t|| (horizontal_speed < s_get_param(CRCD(0xf1e97e45, \"min_skid_speed\")) && dot < -cosf(Mth::DegToRad(s_get_param(CRCD(0x2d571c0f, \"max_reverse_angle\"))))))\r\n\t\t{\r\n\t\t\t// low speed rotate to desired orientation with no speed change\r\n\t\t\t\r\n\t\t\tfloat delta_angle = Mth::DegToRad(s_get_param(CRCD(0xb557804b, \"rotate_in_place_rate\"))) * m_control_magnitude * m_frame_length;\r\n\t\t\tbool left_turn = -m_facing[Z] * m_control_direction[X] + m_facing[X] * m_control_direction[Z] < 0.0f;\r\n\t\t\t\r\n\t\t\tif (!m_run_toggle || m_drop_rotation_rate)\r\n\t\t\t{\r\n\t\t\t\tdelta_angle *= s_get_param(CRCD(0x7b446c98, \"walk_rotate_factor\"));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfloat cos_delta_angle = cosf(left_turn ? delta_angle : -delta_angle);\r\n\t\t\t\tfloat sin_delta_angle = sinf(left_turn ? delta_angle : -delta_angle);\r\n\t\t\t\tMth::Vector new_facing;\r\n\t\t\t\tnew_facing[X] = cos_delta_angle * m_facing[X] + sin_delta_angle * m_facing[Z];\r\n\t\t\t\tnew_facing[Y] = 0.0f;\r\n\t\t\t\tnew_facing[Z] = -sin_delta_angle * m_facing[X] + cos_delta_angle * m_facing[Z];\r\n\t\t\t\t\r\n\t\t\t\t// kludge to stop popping when running at a wall using the dpad\r\n\t\t\t\tCFeeler feeler;\r\n\t\t\t\tfeeler.m_start = m_pos;\r\n\t\t\t\tfeeler.m_start[Y] += s_get_param(CRCD(0x6da7f696, \"feeler_height\"));\r\n\t\t\t\tfeeler.m_end = feeler.m_start + s_get_param(CRCD(0x99978d2b, \"feeler_length\")) * new_facing;\r\n\t\t\t\tif (feeler.GetCollision(false))\r\n\t\t\t\t{\r\n\t\t\t\t\tdelta_angle *= s_get_param(CRCD(0x7b446c98, \"walk_rotate_factor\"));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tfloat cos_delta_angle = cosf(left_turn ? delta_angle : -delta_angle);\r\n\t\t\tfloat sin_delta_angle = sinf(left_turn ? delta_angle : -delta_angle);\r\n\t\t\tfloat adjusted_vel = cos_delta_angle * m_facing[X] + sin_delta_angle * m_facing[Z];\r\n\t\t\tm_facing[Z] = -sin_delta_angle * m_facing[X] + cos_delta_angle * m_facing[Z];\r\n\t\t\tm_facing[X] = adjusted_vel;\r\n\t\t\t\r\n\t\t\t// check for overturn\r\n\t\t\tif (left_turn != (-m_facing[Z] * m_control_direction[X] + m_facing[X] * m_control_direction[Z] < 0.0f))\r\n\t\t\t{\r\n\t\t\t\tm_facing = m_control_direction;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// no acceleration until we reach the desired orientation\r\n\t\t\tspecial_acceleration = true;\r\n\t\t\t\r\n\t\t\t// setup the event\r\n\t\t\tm_frame_event = left_turn ? CRCD(0xf28adbfc, \"RotateLeft\") : CRCD(0x912220f8, \"RotateRight\");\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (dot > -cosf(Mth::DegToRad(s_get_param(CRCD(0x2d571c0f, \"max_reverse_angle\")))))\r\n\t\t\t{\r\n\t\t\t\t// if the turn angle is soft\r\n\t\t\t\t\r\n\t\t\t\tfloat worse_factor = Mth::Lerp(\r\n\t\t\t\t\tm_analog_control\r\n\t\t\t\t\t\t? s_get_param(CRCD(0xa26760f5, \"worse_worse_turn_factor\"))\r\n\t\t\t\t\t\t: s_get_param(CRCD(0xab9015bc, \"dpad_worse_worse_turn_factor\")),\r\n\t\t\t\t\tm_analog_control\r\n\t\t\t\t\t\t? s_get_param(CRCD(0x6cb2e5de, \"worse_turn_factor\"))\r\n\t\t\t\t\t\t: s_get_param(CRCD(0x911f29d7, \"dpad_worse_turn_factor\")),\r\n\t\t\t\t\tMth::Clamp(2.0f * (1.0f - Mth::DotProduct(m_control_direction, m_facing)), 0.0f, 1.0f)\r\n\t\t\t\t);\r\n\t\t\t\t\r\n\t\t\t\t// below a speed threshold, scale up the turn rate\r\n\t\t\t\tfloat turn_factor;\r\n\t\t\t\tif (horizontal_speed < s_get_param(CRCD(0x27815f69, \"max_pop_speed\")))\r\n\t\t\t\t{\r\n\t\t\t\t\t// quick turn\r\n\t\t\t\t\tturn_factor = Mth::Lerp(\r\n\t\t\t\t\t\ts_get_param(CRCD(0xb278405d, \"best_turn_factor\")),\r\n\t\t\t\t\t\tworse_factor,\r\n\t\t\t\t\t\thorizontal_speed / s_get_param(CRCD(0x27815f69, \"max_pop_speed\"))\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// slower turn\r\n\t\t\t\t\tturn_factor = worse_factor;\r\n\t\t\t\t}\r\n\t\t\t\tturn_factor *= m_control_magnitude;\r\n\t\t\t\t\r\n\t\t\t\t// exponentially approach the new facing\r\n\t\t\t\tfloat turn_ratio = turn_factor * m_frame_length;\r\n\t\t\t\tif (turn_ratio >= 1.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_facing = m_control_direction;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_facing = Mth::Lerp(m_facing, m_control_direction, turn_ratio);\r\n\t\t\t\t\tm_facing.Normalize();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// the turn angle is hard\r\n\t\t\t\t\r\n\t\t\t\tif (horizontal_speed > s_get_param(CRCD(0xf1e97e45, \"min_skid_speed\")))\r\n\t\t\t\t{\r\n\t\t\t\t\t// if moving fast enough to require a skidding stop\r\n\t\t\t\t\tspecial_acceleration = true;\r\n\t\t\t\t\thorizontal_speed -= s_get_param(CRCD(0x9661ed7, \"skid_accel\")) * m_frame_length;\r\n\t\t\t\t\thorizontal_speed = Mth::ClampMin(horizontal_speed, 0.0f);\r\n\t\t\t\t\tm_frame_event = CRCD(0x1d537eff, \"Skid\");\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// if max_rotate_in_place_speed is larger than min_skid_speed and max_reverse_angle points farther in reverse than\r\n\t\t\t\t\t// max_rotate_in_place_angle, as they should, then this code should never be run\r\n\t\t\t\t\tDbg_Message(\"Unexpected state in CWalkComponent::calculate_horizontal_speed_and_facing\");\r\n\t\t\t\t\t\r\n\t\t\t\t\t// to be safe, pop to the new facing\r\n\t\t\t\t\tm_facing = m_control_direction;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (special_acceleration) return;\r\n\t\r\n\t// store desired speed for animation speed scaling\r\n\tm_anim_effective_speed = desired_speed;\r\n\t\r\n\t// adjust desired speed for slope\r\n\tdesired_speed = adjust_desired_speed_for_slope(desired_speed);\r\n\t\r\n\t// linear acceleration; exponential deceleration\r\n\tif (horizontal_speed > desired_speed)\r\n\t{\r\n\t\tfloat decel_factor = s_get_param(CRCD(0xacfa4e0c, \"decel_factor\"));\r\n\t\t\r\n\t\tif (desired_speed == 0.0f)\r\n\t\t{\r\n\t\t\tif (horizontal_speed > s_get_param(CRCD(0x79d182ad, \"walk_speed\")))\r\n\t\t\t{\r\n\t\t\t\tm_frame_event = CRCD(0x1d537eff, \"Skid\");\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (m_last_frame_event == CRCD(0x1d537eff, \"Skid\") && horizontal_speed > s_get_param(CRCD(0x311d02b2, \"stop_skidding_speed\")))\r\n\t\t\t\t{\r\n\t\t\t\t\tm_frame_event = CRCD(0x1d537eff, \"Skid\");\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tdecel_factor = s_get_param(CRCD(0xa2aa811, \"low_speed_decel_factor\"));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t/* needs reworked, at the least\r\n\t\tif (mp_physics_control_component->GetStateSwitchTime() == m_state_timestamp\r\n\t\t\t&& Tmr::ElapsedTime(mp_physics_control_component->GetStateSwitchTime()) < 400.0f\r\n\t\t\t&& !m_cancel_transition_momentum\r\n\t\t\t&& desired_speed < s_get_param(CRCD(0x79d182ad, \"walk_speed\")))\r\n\t\t{\r\n\t\t\tdecel_factor = 1.0f;\r\n\t\t\tif (horizontal_speed > Script::GetFloat(\"start_stand\"))\r\n\t\t\t{\r\n\t\t\t\tm_frame_event = CRCD(0x1d537eff, \"Skid\");\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_frame_event = CRCD(0x9b46e749, \"Stand\");\r\n\t\t\t}\r\n\t\t}\r\n\t\t*/\r\n\t\t\r\n\t\thorizontal_speed = Mth::Lerp(horizontal_speed, desired_speed, decel_factor * m_frame_length);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (m_run_toggle)\r\n\t\t{\r\n\t\t\thorizontal_speed += s_get_param(CRCD(0x4f47c998, \"run_accel_rate\")) * m_frame_length;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\thorizontal_speed += s_get_param(CRCD(0x6590a49b, \"walk_accel_rate\")) * m_frame_length;\r\n\t\t}\r\n\t\tif (horizontal_speed > desired_speed)\r\n\t\t{\r\n\t\t\thorizontal_speed = desired_speed;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool  CWalkComponent::adjust_horizonal_vel_for_environment (   )\r\n{\r\n\t// We send out feeler rays to find nearby walls.  We limit velocity to be flush with the first wall found.  If two or more non-parallel walls\r\n\t// are found, velocity is zeroed.\r\n\t\r\n\tfloat feeler_length = s_get_param(CRCD(0x99978d2b, \"feeler_length\"));\r\n\tfloat feeler_height = s_get_param(CRCD(0x6da7f696, \"feeler_height\"));\r\n\t\r\n\tCFeeler feeler;\r\n\t\r\n\tbool contact = false;\r\n\tfor (int n = 0; n < vNUM_FEELERS + 1; n++)\r\n\t{\r\n\t\t// setup the the feeler\r\n\t\t\r\n\t\tif (n == vNUM_FEELERS)\r\n\t\t{\r\n\t\t\t// final feeler is for air state only and is at the feet; solves situations in which the feet impact with vertical surfaces which the\r\n\t\t\t// wall feelers are too high to touch\r\n\t\t\tif (m_state != WALKING_AIR)\r\n\t\t\t{\r\n\t\t\t\tmp_contacts[vNUM_FEELERS].in_collision = false;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tfeeler.m_start = m_pos + m_critical_point_offset;\r\n\t\t\tfeeler.m_end = feeler.m_start + m_horizontal_vel * m_frame_length;\r\n\t\t\tfeeler.m_end[Y] += m_vertical_vel * m_frame_length + 0.5f * -get_gravity() * Mth::Sqr(m_frame_length);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfeeler.m_start = m_pos;\r\n\t\t\tfeeler.m_start[Y] += feeler_height;\r\n\t\t\tfeeler.m_end = m_pos + feeler_length * calculate_feeler_offset_direction(n);\r\n\t\t\tfeeler.m_end[Y] += feeler_height;\r\n\t\t}\r\n\t\t\r\n\t\tmp_contacts[n].in_collision = feeler.GetCollision();\r\n\t\t\r\n\t\tif (!mp_contacts[n].in_collision)\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t{\r\n\t\t\t\tfeeler.DebugLine(0, 0, 255, 1);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tif (n == vNUM_FEELERS)\r\n\t\t{\r\n\t\t\t// feet collisions only count for walls\r\n\t\t\tif (feeler.GetNormal()[Y] > 0.707f)\r\n\t\t\t{\r\n\t\t\t\tmp_contacts[n].in_collision = false;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// store the feeler\r\n\t\tmp_contacts[n].feeler = feeler;\r\n\t\t\r\n\t\tcontact = true;\r\n\t\t\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(255, 0, 0, 1);\r\n\t\t}\r\n\t\t#endif\r\n\r\n\t\t// grab the horizontal normal of the contacted wall\r\n\t\tmp_contacts[n].normal = feeler.GetNormal();\r\n\t\tmp_contacts[n].normal[Y] = 0.0f;\r\n\t\tmp_contacts[n].normal.Normalize();\r\n\t\t\r\n\t\t// if we're on the moving object, don't count its movement when doing collision detection, as the walker's velocity is already measured\r\n\t\t// relative to its movable contact's\r\n\t\tif (feeler.IsMovableCollision()\r\n\t\t\t&& (!mp_movable_contact_component->HaveContact() || mp_movable_contact_component->GetContact()->GetObject() != feeler.GetMovingObject()))\r\n\t\t{\r\n\t\t\tmp_contacts[n].movement = Mth::DotProduct(feeler.GetMovingObject()->GetVel(), mp_contacts[n].normal);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_contacts[n].movement = 0.0f;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// check for wall push\r\n\tif (m_state == WALKING_GROUND)\r\n\t{\r\n\t\tif (check_for_wall_push())\r\n\t\t{\r\n\t\t\t// if we're wall pushing, we may decide to switch states based on our environment\r\n\t\t\t\r\n\t\t\t/* no auto-hop-to-hang\r\n\t\t\tif (Tmr::ElapsedTime(m_wall_push_test.test_start_time) > s_get_param(CRCD(0x928e6775, \"hop_delay\")))\r\n\t\t\t{\r\n\t\t\t\tif (maybe_climb_up_ladder() || maybe_jump_low_barrier()) return false;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t*/\r\n\t\t\tif (Tmr::ElapsedTime(m_wall_push_test.test_start_time) > s_get_param(CRCD(0x38d36700, \"barrier_jump_delay\")))\r\n\t\t\t{\r\n\t\t\t\tif (maybe_climb_up_ladder() || maybe_jump_low_barrier()) return false;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif (mp_input_component->GetControlPad().m_R1.GetPressed() && !m_ignore_grab_button)\r\n\t\t{\r\n\t\t\tif (maybe_climb_up_ladder(true)/* || maybe_hop_to_hang()*/) return false;\r\n\t\t}\r\n\t\t\r\n\t\tif (mp_physics_control_component->HaveBeenReset()) return false;\r\n\t}\r\n\t\r\n\t// push down steep slopes\r\n\tif (m_state == WALKING_GROUND && m_ground_normal[Y] < 0.5f)\r\n\t{\r\n\t\tMth::Vector push_dir = m_ground_normal;\r\n\t\tpush_dir[Y] = 0.0f;\r\n\t\tpush_dir.Normalize();\r\n\t\tm_pos += s_get_param(CRCD(0x4d16f37d, \"push_strength\")) * m_frame_length * push_dir;\r\n\t\tDUMP_WPOSITION\r\n\t}\r\n\t\r\n\tif (!contact) return false;\r\n\t\r\n\t// push away from walls\r\n\tfor (int n = 0; n < vNUM_FEELERS + 1; n++)\r\n\t{\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\t                \r\n\t\tif (mp_contacts[n].feeler.GetDist() < s_get_param(CRCD(0xa20c43b7, \"push_feeler_length\")) / feeler_length)\r\n\t\t{\r\n\t\t\tm_pos += s_get_param(CRCD(0x4d16f37d, \"push_strength\")) * m_frame_length * mp_contacts[n].normal;\r\n\t\t\tDUMP_WPOSITION\r\n\t\t}\r\n\t}\r\n\t\r\n\t// from here on we ignore collisions we're moving out of\r\n\tcontact = false;\r\n\tfor (int n = 0; n < vNUM_FEELERS + 1; n++)\r\n\t{\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\t\r\n\t\t// don't count collisions we're moving out of\r\n\t\tif (Mth::DotProduct(mp_contacts[n].normal, m_horizontal_vel) >= mp_contacts[n].movement)\r\n\t\t{\r\n\t\t\tmp_contacts[n].in_collision = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcontact = true;\r\n\t\t}\r\n\t}\r\n\tif (!contact) return false;\r\n\t\r\n\t// Now we calculate how our movement is effected by our collisions.  The movement must have a non-negative dot product with all collision normals.\r\n\t// The algorithm used should be valid for all convex environments.\r\n\t\r\n\t// if any of the colllision normals are more than right angles to one another, no movement is possible\r\n\t// NOTE: not valid with movable contacts; could cause jerky movement in corners where walls are movable\r\n\tfor (int n = 0; n < vNUM_FEELERS + 1; n++)\r\n\t{\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\tfor (int m = n + 1; m < vNUM_FEELERS + 1; m++)\r\n\t\t{\r\n\t\t\tif (!mp_contacts[m].in_collision) continue;\r\n\t\t\tif (Mth::DotProduct(mp_contacts[n].normal, mp_contacts[m].normal) <= 0.0f)\r\n\t\t\t{\r\n\t\t\t\tm_horizontal_vel.Set();\r\n\t\t\t\tm_anim_effective_speed = Mth::Min(s_get_param(CRCD(0xbd6a05d, \"min_anim_run_speed\")), m_anim_effective_speed);\r\n\t\t\t\tm_drop_rotation_rate = true;\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// direction of proposed movement\r\n\tMth::Vector movement_direction = m_horizontal_vel;\r\n\tmovement_direction.Normalize();\r\n\t\r\n\tMth::Vector adjusted_vel = m_horizontal_vel;\r\n\t\r\n\t// loop over the contacts (from backward to forward)\r\n\tconst int p_contact_idxs [ vNUM_FEELERS + 1 ] = { 7, 4, 3, 5, 2, 6, 1, 0 };\r\n\tfor (int i = 0; i < vNUM_FEELERS + 1; i++)\r\n\t{\r\n\t\tint n = p_contact_idxs[i];\r\n\t\t\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\t\r\n\t\t// check to see if the movement still violates this constraint\r\n\t\tfloat normal_vel = Mth::DotProduct(adjusted_vel, mp_contacts[n].normal);\r\n\t\tif (normal_vel >= mp_contacts[n].movement) continue;\r\n\t\t\r\n\t\t// adjust the movement to the closest direction allowed by this contraint\r\n\t\tadjusted_vel -= (normal_vel - mp_contacts[n].movement) * mp_contacts[n].normal;\r\n\t\t\r\n\t\t// if the mvoement direction no longer points in the direction of the proposed movement, no movement occurs\r\n\t\tif (Mth::DotProduct(adjusted_vel, m_horizontal_vel) <= 0.0f)\r\n\t\t{\r\n\t\t\tm_horizontal_vel.Set();\r\n\t\t\tm_anim_effective_speed = Mth::Min(s_get_param(CRCD(0xbd6a05d, \"min_anim_run_speed\")), m_anim_effective_speed);\r\n\t\t\tm_drop_rotation_rate = true;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// insure that the adjusted velocity in the final direction is not larger than the projection of the initial velocity into that direction\r\n\tfloat adjusted_speed = adjusted_vel.Length();\r\n\tMth::Vector adjusted_vel_direction = adjusted_vel;\r\n\tadjusted_vel_direction *= 1.0f / adjusted_speed;\r\n\tfloat projected_vel = Mth::DotProduct(m_horizontal_vel, adjusted_vel_direction);\r\n\t\r\n\tif (adjusted_speed > projected_vel)\r\n\t{\r\n\t\tadjusted_vel = adjusted_vel_direction * projected_vel;\r\n\t}\r\n\t\r\n\tm_drop_rotation_rate = adjusted_vel.LengthSqr() / m_horizontal_vel.LengthSqr() < Mth::Sqr(0.5f);\r\n\t\r\n\t// only the velocity along the movement direction is retained\r\n\tm_horizontal_vel = adjusted_vel;\r\n\t\r\n\tfloat final_horiz_vel = m_horizontal_vel.Length();\r\n\tif (m_anim_effective_speed > s_get_param(CRCD(0xbd6a05d, \"min_anim_run_speed\")))\r\n\t{\r\n\t\tm_anim_effective_speed = final_horiz_vel;\r\n\t\tm_anim_effective_speed = Mth::Max(s_get_param(CRCD(0xbd6a05d, \"min_anim_run_speed\")), m_anim_effective_speed);\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::adjust_facing_for_adjusted_horizontal_vel (   )\r\n{\r\n\t// We adjust facing due to adjustment in horizontal velocity due to environment.  Basically, we want to object to turn to face the velocity\r\n\t// that the environment has forced upon it.\r\n\t\r\n\t// IDEA: shift to basing turn amount on angle difference and not speed\r\n\t\r\n\tfloat horizontal_speed = m_horizontal_vel.Length();\r\n\t\r\n\tif (horizontal_speed < s_get_param(CRCD(0x515a933, \"wall_turn_speed_threshold\"))) return;\r\n\t\r\n\t// the new facing is in the direction of our adjusted velocity\r\n\tMth::Vector new_facing = m_horizontal_vel;\r\n\tnew_facing.Normalize();\r\n\t\r\n\t// smoothly transition between no wall turning to full wall turning\r\n\tfloat turn_ratio;\r\n\tif (horizontal_speed > s_get_param(CRCD(0xe6c1cd0d, \"max_wall_turn_speed_threshold\")))\r\n\t{\r\n\t\tturn_ratio = s_get_param(CRCD(0x7a583b9b, \"wall_turn_factor\")) * m_frame_length;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tturn_ratio = Mth::LinearMap(\r\n\t\t\t0.0f,\r\n\t\t\ts_get_param(CRCD(0x7a583b9b, \"wall_turn_factor\")) * m_frame_length,\r\n\t\t\thorizontal_speed,\r\n\t\t\ts_get_param(CRCD(0x0515a933, \"wall_turn_speed_threshold\")),\r\n\t\t\ts_get_param(CRCD(0xe6c1cd0d, \"max_wall_turn_speed_threshold\"))\r\n\t\t);\r\n\t}\r\n\t\r\n\t// exponentially approach new facing\r\n\tif (turn_ratio >= 1.0f)\r\n\t{\r\n\t\tm_facing = new_facing;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_facing = Mth::Lerp(m_facing, new_facing, turn_ratio);\r\n\t\tm_facing.Normalize();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CWalkComponent::adjust_desired_speed_for_slope ( float desired_speed )\r\n{\r\n\t// Slow velocity up and down slopes.\r\n\t\r\n\t// skip if there is no appreciable slope\r\n\tif (m_ground_normal[Y] > 0.95f) return desired_speed;\r\n\t\r\n\t// skip if not running\r\n\tif (desired_speed <= s_get_param(CRCD(0x79d182ad, \"walk_speed\"))) return desired_speed;\r\n\t\r\n\t// calculate a horizontal vector up the slope\r\n\tMth::Vector up_slope = m_ground_normal;\r\n\tup_slope[Y] = 0.0f;\r\n\tup_slope.Normalize();\r\n\t\r\n\t// horizontal factor of velocity if the velocity were pointing along the slope (instead of along the horizontal)\r\n\tfloat movement_factor = m_ground_normal[Y];\r\n\t\r\n\t// factor of velocity pointing up the slope\r\n\tfloat dot = Mth::Abs(Mth::DotProduct(m_facing, up_slope));\r\n\t\r\n\t// scale the up-the-slope element of velocity based on the slope strength\r\n\treturn (1.0f - dot) * desired_speed + dot * movement_factor * desired_speed;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::respond_to_ground (   )\r\n{\r\n\t// Look for the ground below us.  If we find it, snap to it.  If not, go to air state.\r\n\t\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_start[Y] += s_get_param(CRCD(0xcee3a3e1, \"snap_up_height\"));\r\n\tfeeler.m_end = m_pos;\r\n\tfeeler.m_end[Y] -= s_get_param(CRCD(0xaf3e4251, \"snap_down_height\"));\r\n\t\r\n\tif (!feeler.GetCollision() || (feeler.GetFlags() & mFD_NOT_SKATABLE))\r\n\t{\r\n\t\tif (feeler.GetCollision())\r\n\t\t{\r\n\t\t\tm_pos = feeler.GetPoint() + 0.1f * feeler.GetNormal();\r\n\t\t\tDUMP_WPOSITION\r\n\t\t}\r\n\t\t\r\n\t\t// no ground\r\n\t\t\r\n\t\tif (m_last_ground_feeler_valid)\r\n\t\t{\r\n\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_OFF_EDGE, m_last_ground_feeler);\r\n\t\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\t}\r\n\t\t\r\n\t\tif (mp_input_component->GetControlPad().m_triangle.GetPressed())\r\n\t\t{\r\n\t\t\t// need to give the player a change to rail before climbing down ladders and such\r\n\t\t\t\r\n\t\t\t// if we just climbed up to a rail and are immediately falling, we need some minute amount of movement in order to find a rail\r\n\t\t\tif (m_pos == m_frame_start_pos)\r\n\t\t\t{\r\n\t\t\t\tm_frame_start_pos[Y] += 0.001f;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (maybe_stick_to_rail()) return;\r\n\t\t}\r\n\t\t\r\n\t\tif (maybe_climb_down_ladder() || maybe_drop_to_hang()) return;\r\n\t\t\r\n\t\t// go to air state\r\n\t\tset_state(WALKING_AIR);\r\n\t\tm_primary_air_direction = m_facing;\r\n\t\tleave_movable_contact_for_air(m_horizontal_vel, m_vertical_vel);\r\n\t\tm_frame_event = CRCD(0xabf1f6ac, \"WalkOffEdge\");\r\n\t\tGetObject()->BroadcastEvent(CRCD(0xd96f01f1, \"SkaterOffEdge\"));\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tfloat snap_distance = feeler.GetPoint()[Y] - m_pos[Y];\r\n\t\r\n\t// no not send event for very small snaps\r\n\tif (Mth::Abs(snap_distance) > s_get_param(CRCD(0xd3193d8e, \"max_unnoticed_ground_snap\")))\r\n\t{\r\n\t\tGetObject()->SelfEvent(snap_distance > 0.0f ? CRCD(0x93fcf3ed, \"SnapUpEdge\") : CRCD(0x56e21153, \"SnapDownEdge\"));\r\n\t}\r\n\t\r\n\t// snap position to the ground\r\n\tm_pos[Y] = feeler.GetPoint()[Y];\r\n\tDUMP_WPOSITION\r\n\t\r\n\t// adjust stair float distance\r\n\tif (snap_distance > 0.0f || snap_distance < -3.0f)\r\n\t{\r\n\t\tm_curb_float_height = Mth::ClampMin(m_curb_float_height - snap_distance, 0.0f);\r\n\t}\r\n\t\r\n\t// see if we've changed sectors\r\n\tif (m_last_ground_feeler.GetSector() != feeler.GetSector())\r\n\t{\r\n\t\tif (m_last_ground_feeler_valid)\r\n\t\t{\r\n\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_OFF, m_last_ground_feeler);\r\n\t\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\t}\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_ONTO, feeler);\r\n\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t}\r\n\t\r\n\t// stash the ground feeler so that we can trip the group's triggers at a later time\r\n\tm_last_ground_feeler = feeler;\r\n\tm_last_ground_feeler_valid = true;\r\n\t\r\n\t// set the ground normal for next frame's velocity slope adjustment\r\n\tm_ground_normal = feeler.GetNormal();\r\n\t\r\n\t// NOTE: need to repeat this code anywhere we enter the ground state\r\n\tmp_movable_contact_component->CheckForMovableContact(feeler);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::adjust_curb_float_height (   )\r\n{\r\n\t// adjust m_curb_float_height to smooth out moving up stairs\r\n\t\r\n\t// When facing a curb, we smoothly increase m_curb_float_height to the height of the curb.  When we snap up the curb, m_curb_float_height is then\r\n\t// reduced by an amount equal to the snap distance.\r\n\t// When we snap down a curb, m_curb_float_height is increased by the snap distance.  We then drop m_curb_float_height smoothly to zero.\r\n\t\r\n\t// determine appropriate direction to search for a curb\r\n\tMth::Vector feeler_direction = m_facing;\r\n\tfeeler_direction.ProjectToPlane(m_ground_normal);\r\n\tfeeler_direction[Y] = Mth::ClampMin(feeler_direction[Y], 0.0f);\r\n\tfeeler_direction.Normalize();\r\n\t\r\n\t// look for a curb\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_start[Y] += 0.5f;\r\n\tfeeler.m_end = m_pos + s_get_param(CRCD(0x11edcc52, \"curb_float_feeler_length\")) * feeler_direction;\r\n    feeler.m_end[Y] += 0.5f;\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(0, 255, 0, 1);\r\n\t}\r\n\t#endif\r\n\t\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t// grab the distance to the curb\r\n\t\tfloat distance_to_curb = feeler.GetDist();\r\n\t\t\r\n\t\t// look up from the curb to find the curb height\r\n\t\tfeeler.m_end = feeler.GetPoint() + 0.5f * feeler_direction;\r\n\t\tfeeler.m_start = feeler.m_end;\r\n\t\tfeeler.m_start[Y] = m_pos[Y] + s_get_param(CRCD(0xcee3a3e1, \"snap_up_height\"));\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(0, 255, 255, 1);\r\n\t\t}\r\n\t\t#endif\r\n\t\t\r\n\t\tif (feeler.GetCollision())\r\n\t\t{\r\n\t\t\t// calculate the m_curb_float_height we should have based on the curb height and distance\r\n\t\t\tfloat appropriate_curb_float_height = (1.0f - distance_to_curb) * (feeler.GetPoint()[Y] - m_pos[Y]);\r\n\t\t\t\r\n\t\t\tif (Mth::Abs(m_curb_float_height) < 0.01f && m_control_magnitude == 0.0f && m_horizontal_vel.LengthSqr() < Mth::Sqr(s_get_param(CRCD(0x227d72ee, \"min_curb_height_adjust_vel\"))))\r\n\t\t\t{\r\n\t\t\t\t// don't update the curb height if we're on the ground and standing still; this is mostly to prevent snapping up right after landing a jump\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// lerp to the appropriate height\r\n\t\t\t\tm_curb_float_height = Mth::Lerp(m_curb_float_height, appropriate_curb_float_height, s_get_param(CRCD(0x856a80d3, \"curb_float_lerp_up_rate\")) * m_frame_length);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tm_curb_float_height_adjusted = true;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::account_for_movable_contact (   )\r\n{\r\n\tif (!mp_movable_contact_component->UpdateContact(m_pos)) return;\r\n\t\r\n\tm_pos += mp_movable_contact_component->GetContact()->GetMovement();\r\n\tDUMP_WPOSITION\r\n\t\r\n\tif (mp_movable_contact_component->GetContact()->IsRotated())\r\n\t{\r\n\t\tm_facing = mp_movable_contact_component->GetContact()->GetRotation().Rotate(m_facing);\r\n\t\tif (m_facing[Y] != 0.0f)\r\n\t\t{\r\n\t\t\tm_facing[Y] = 0.0f;\r\n\t\t\tm_facing.Normalize();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::jump (   )\r\n{\r\n\t// switch to air state and give the object an upwards velocity\r\n\t\r\n\tfloat strength = 0.0f;\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase WALKING_GROUND:\r\n\t\tcase WALKING_AIR:\r\n\t\t\t// jump strength scales with the length the jump button has been held\r\n\t\t\tstrength = Mth::Lerp(\r\n\t\t\t\ts_get_param(CRCD(0x246d0bf3, \"min_jump_factor\")), \r\n\t\t\t\t1.0f,\r\n\t\t\t\tMth::ClampMax(mp_input_component->GetControlPad().m_x.GetPressedTime() / s_get_param(CRCD(0x12333ebd, \"hold_time_for_max_jump\")), 1.0f)\r\n\t\t\t);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase WALKING_HANG:\r\n\t\tcase WALKING_LADDER:\r\n\t\tcase WALKING_ANIMWAIT:\r\n\t\t\tstrength = s_get_param(CRCD(0xf2fa5845, \"hang_jump_factor\"));\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\t// if we're jumping from the ground, trip the ground's triggers\r\n\tif (m_state == WALKING_GROUND && m_last_ground_feeler_valid)\r\n\t{\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_JUMP_OFF, m_last_ground_feeler);\r\n\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t}\r\n\t\r\n\t// Called by script from outside of the component update, so m_vertical_vel is not used.\r\n\tGetObject()->GetVel()[Y] = strength * s_get_param(CRCD(0x63d62a21, \"jump_velocity\"));\r\n\t\r\n\t// jumps for ladders and hanging get a backwards velocity\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase WALKING_GROUND:\r\n\t\tcase WALKING_AIR:\r\n\t\t{\r\n\t\t\textract_state_from_object();\r\n\t\r\n\t\t\tif (m_control_magnitude)\r\n\t\t\t{\r\n\t\t\t\tfloat min_launch_speed = calculate_desired_speed()\r\n\t\t\t\t\t* s_get_param(CRCD(0x839fe542, \"jump_horiz_speed\")) / get_run_speed();\r\n\t\t\t\t\r\n\t\t\t\tif (Mth::DotProduct(m_horizontal_vel, m_control_direction) > 0.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_horizontal_vel.ProjectToNormal(m_control_direction);\r\n\t\t\t\t\tif (m_horizontal_vel.Length() < min_launch_speed)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_horizontal_vel.Normalize(min_launch_speed);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_horizontal_vel = min_launch_speed * m_control_direction;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tm_primary_air_direction = m_control_direction;\r\n\t\t\t\tm_facing = m_control_direction;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_primary_air_direction = m_facing;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tadjust_jump_for_ceiling_obstructions();\r\n\t\t\t\r\n\t\t\t// setup primary air direction\r\n\t\t\tfloat length_sqr = m_horizontal_vel.LengthSqr();\r\n\t\t\tif (length_sqr > 0.01f)\r\n\t\t\t{\r\n\t\t\t\tm_primary_air_direction = m_horizontal_vel;\r\n\t\t\t\tm_primary_air_direction /= sqrtf(length_sqr);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_primary_air_direction = m_facing;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcopy_state_into_object();\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase WALKING_ANIMWAIT:\r\n\t\t\tm_false_wall.active = true;\r\n\t\t\tm_false_wall.distance = Mth::DotProduct(m_false_wall.normal, m_pos + m_critical_point_offset);\r\n\t\t\t\r\n\t\t\tGetObject()->GetVel()[X] = 0.0f;\r\n\t\t\tGetObject()->GetVel()[Z] = 0.0f;\r\n\t\t\tm_primary_air_direction = m_facing;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase WALKING_HANG:\r\n\t\t\tm_false_wall.active = true;\r\n\t\t\tm_false_wall.normal = m_facing;\r\n\t\t\tm_false_wall.distance = Mth::DotProduct(m_false_wall.normal, m_pos + m_critical_point_offset);\r\n\t\t\tm_false_wall.cancel_height = m_pos[Y] - m_vertical_hang_offset;\r\n\t\t\t\r\n\t\t\tGetObject()->GetVel()[X] = 0.0f;\r\n\t\t\tGetObject()->GetVel()[Z] = 0.0f;\r\n\t\t\tm_primary_air_direction = m_facing;\r\n\t\t\tbreak;\r\n\r\n\t\tcase WALKING_LADDER:\r\n\t\t\tGetObject()->GetVel()[X] = 0.0f;\r\n\t\t\tGetObject()->GetVel()[Z] = 0.0f;\r\n\t\t\tm_primary_air_direction = m_facing;\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\tleave_movable_contact_for_air(GetObject()->GetVel(), GetObject()->GetVel()[Y]);\r\n\t\r\n\tset_state(WALKING_AIR);\r\n\t\r\n\tGetObject()->BroadcastEvent(CRCD(0x8687163a, \"SkaterJump\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::adjust_jump_for_ceiling_obstructions (   )\r\n{\r\n\t// check for obstructions above and drift backwards to avoid them if we can; this prevents us from banging our head on overhangs when we're up\r\n\t// against the wall and trying to jump to hang on them\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_start[Y] += s_get_param(CRCD(0x9ea1974a, \"walker_height\"));\r\n\tfeeler.m_end = feeler.m_start;\r\n\tfeeler.m_end[Y] += s_get_param(CRCD(0x48c0ac2a, \"jump_obstruction_check_height\"));\r\n\tif (feeler.GetCollision(false))\r\n\t{\r\n\t\tfloat jump_obstruction_check_back = s_get_param(CRCD(0x6ebbab7, \"jump_obstruction_check_back\"));\r\n\t\tfloat obstruction_height = feeler.GetPoint()[Y] - feeler.m_start[Y];\r\n\r\n\t\tfeeler.m_start -= m_facing * jump_obstruction_check_back;\r\n\t\tfeeler.m_end -= m_facing * jump_obstruction_check_back;\r\n\r\n\t\tif (!feeler.GetCollision(false))\r\n\t\t{\r\n\r\n\t\t\tfloat acceleration = get_gravity();\r\n\t\t\tfloat vel_sqr_at_obstruction_height = Mth::Sqr(m_vertical_vel) - 2.0f * acceleration * obstruction_height;\r\n\t\t\tif (vel_sqr_at_obstruction_height > 0.0f)\r\n\t\t\t{\r\n\t\t\t\tfloat time_to_height = (m_vertical_vel - sqrt(vel_sqr_at_obstruction_height)) / acceleration;\r\n\r\n\t\t\t\t// setup in air drift\r\n\t\t\t\tm_in_air_drift_vel = -jump_obstruction_check_back / time_to_height * m_facing;\r\n\t\t\t\tm_in_air_drift_stop_height = m_pos[Y] + obstruction_height;\r\n\r\n\t\t\t\t// suppress control until we return to this height from above\r\n\t\t\t\tm_in_air_control_suppression_timer = 2.0f * m_vertical_vel / acceleration - time_to_height;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::go_in_air_state (   )\r\n{\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\r\n\tsetup_collision_cache();\r\n\t\r\n\t// default air event\r\n\tm_frame_event = CRCD(0x439f4704, \"Air\");\r\n\t\r\n\t// user control of horizontal velocity\r\n\tcontrol_horizontal_vel();\r\n\t\r\n\t// prevent movement into walls\r\n\tif (!adjust_horizonal_vel_for_environment())\r\n\t{\r\n\t\tm_drop_rotation_rate = false;\r\n\t}\r\n\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\r\n\t// account for the in-air false wall\r\n\tadjust_pos_for_false_wall();\r\n\t\r\n\t// check for head bonking\r\n\tadjust_vertical_vel_for_ceiling();\r\n\t\r\n\t// apply movement and acceleration for this frame\r\n\tfloat acceleration = get_gravity();\r\n\tm_pos += m_horizontal_vel * m_frame_length;\r\n\tm_pos += m_in_air_drift_vel * m_frame_length;\r\n\tm_pos[Y] += m_vertical_vel * m_frame_length + 0.5f * -acceleration * Mth::Sqr(m_frame_length);\r\n\tDUMP_WPOSITION\r\n\tm_vertical_vel += -acceleration * m_frame_length;\r\n\t\r\n\tif (m_pos[Y] > m_in_air_drift_stop_height)\r\n\t{\r\n\t\tm_in_air_drift_vel.Set();\r\n\t}\r\n\t\r\n\t// see if we've landed yet\r\n\tcheck_for_landing(m_frame_start_pos, m_pos);\r\n\tif (m_state != WALKING_AIR || mp_physics_control_component->HaveBeenReset()) return;\r\n\t\r\n\t// maybe grab a rail; delay regrabbing of hang rails\r\n\tif (control_pad.m_R1.GetPressed() && !m_ignore_grab_button\r\n\t\t&& ((m_previous_state != WALKING_HANG && m_previous_state != WALKING_LADDER && m_previous_state != WALKING_ANIMWAIT)\r\n\t\t|| Tmr::ElapsedTime(m_state_timestamp) > s_get_param(CRCD(0xe6e0c0a4, \"rehang_delay\"))))\r\n\t{\r\n\t\tif (m_previous_state == WALKING_LADDER)\r\n\t\t{\r\n\t\t\t// can't regrab ladders\r\n\t\t\tif (maybe_grab_to_hang(m_frame_start_pos, m_pos))\r\n\t\t\t{\r\n\t\t\t\tCFeeler::sClearDefaultCache();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (maybe_grab_to_hang(m_frame_start_pos, m_pos) || maybe_grab_to_ladder(m_frame_start_pos, m_pos))\r\n\t\t\t{\r\n\t\t\t\tCFeeler::sClearDefaultCache();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tCFeeler::sClearDefaultCache();\r\n\t\r\n\tif (control_pad.m_triangle.GetPressed() && maybe_stick_to_rail()) return;\r\n\t\r\n\tif (maybe_in_air_acid_drop()) return;\r\n\t\r\n\tmaybe_wallplant();\r\n\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\r\n\t// insure that we do not slip through the cracks in the collision geometry which are a side-effect of moving collidable objects\r\n\tMth::Vector previous_pos = m_pos;\r\n\tMth::Vector critical_point = m_pos + m_critical_point_offset;\r\n\tMth::Vector frame_start_critical_point = m_frame_start_pos + m_critical_point_offset;\r\n\tif (CCompositeObject* p_inside_object = mp_movable_contact_component->CheckInsideObjects(critical_point, frame_start_critical_point))\r\n\t{\r\n\t\tm_pos = critical_point - m_critical_point_offset;\r\n\t\tDUMP_WPOSITION\r\n\t\t\r\n\t\tMESSAGE(\"WALKING_AIR, within moving object\");\r\n\t\t\r\n\t\tm_horizontal_vel.Set();\r\n\t\tm_vertical_vel = 0.0f;\r\n\t\tcheck_for_landing(m_pos, previous_pos);\r\n\t}\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::control_horizontal_vel (   )\r\n{\r\n\t// We allow user control over the object's in air velocity.  The algorithm is complicated by the fact that the forward velocity of the jump needs\r\n\t// to be accounted for when allowing for velocity adjustment.  It is assumed that the jump direction is the same as the facing.\r\n\t\r\n\tif (m_in_air_control_suppression_timer != 0.0f)\r\n\t{\r\n\t\tm_in_air_control_suppression_timer = Mth::ClampMin(m_in_air_control_suppression_timer - m_frame_length, 0.0f);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// remove uncontrollable velocity term\r\n\tm_horizontal_vel -= m_uncontrollable_air_horizontal_vel;\r\n\t\r\n\t#ifdef SCRIPT_WALK_DRAG\r\n\t// adjust speed by the script set drag factor\r\n\tfloat adjust_magnitude = m_control_magnitude * m_script_drag_factor;\r\n\t#else\r\n\tfloat adjust_magnitude = m_control_magnitude;\r\n\t#endif\r\n\t\r\n\t// adjust velocity perpendicular to jump direction\r\n\t\r\n\t// direction perpendicular to jump direction\r\n\tMth::Vector perp_direction(-m_primary_air_direction[Z], 0.0f, m_primary_air_direction[X]);\r\n\t\r\n\t// desired perpendicular velocity\r\n\tfloat perp_desired_vel = s_get_param(CRCD(0x896c8888, \"jump_adjust_speed\")) * adjust_magnitude * Mth::DotProduct(m_control_direction, perp_direction);\r\n\t\r\n\t// current perpendicular velocity\r\n\tfloat perp_vel = Mth::DotProduct(m_horizontal_vel, perp_direction);\r\n\t\r\n\t// exponentially approach desired velocity\r\n\tperp_vel = Mth::Lerp(perp_vel, perp_desired_vel, s_get_param(CRCD(0xf085443b, \"jump_accel_factor\")) * m_frame_length);\r\n\t\t\r\n\t// adjust velocity parallel to jump direction\r\n\t\r\n\t// desired parallel velocity\r\n\tfloat para_desired_vel = s_get_param(CRCD(0x896c8888, \"jump_adjust_speed\")) * adjust_magnitude * Mth::DotProduct(m_control_direction, m_primary_air_direction);\r\n\t\r\n\t// current parallel velocity\r\n\tfloat para_vel = Mth::DotProduct(m_horizontal_vel, m_primary_air_direction);\r\n\t\r\n    // if desired velocity if forward and forward velocity already exceeds adjustment velocity\r\n\tif (para_desired_vel >= 0.0f && para_vel > para_desired_vel)\r\n\t{\r\n\t\t// do nothing; don't slow down the jump\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// adjust desired velocity to center around current velocity to insure that our in air stopping ability is not too amazing\r\n\t\tif (para_desired_vel < 0.0f && para_vel > 0.0f)\r\n\t\t{\r\n\t\t\tpara_desired_vel += para_vel;\r\n\t\t}\r\n\t\t\r\n\t\t// exponentially approach desired velocity\r\n\t\tpara_vel = Mth::Lerp(para_vel, para_desired_vel, s_get_param(CRCD(0xf085443b, \"jump_accel_factor\")) * m_frame_length);\r\n\t}\r\n\t\t\r\n\t// rebuild horizontal velocity from parallel and perpendicular components\r\n\tm_horizontal_vel = para_vel * m_primary_air_direction + perp_vel * perp_direction;\r\n\t\r\n\t// reinstitute uncontrollable velocity term\r\n\tm_horizontal_vel += m_uncontrollable_air_horizontal_vel;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::adjust_vertical_vel_for_ceiling (   )\r\n{\r\n\t// if we hit our head, zero vertical velocity\r\n\t\r\n\t// no ceiling collisions when a false wall is active; otherwise, ceilings would kill our jump when we jump from hanging on a ledge which sticks out.\r\n\tif (m_false_wall.active) return;\r\n\t\r\n\tfloat walker_height = s_get_param(CRCD(0x9ea1974a, \"walker_height\"));\r\n\t\r\n\t// be more forgiving if we're moving down already\r\n\tif (m_vertical_vel < 0.0f)\r\n\t{\r\n\t\twalker_height -= 18.0f;\r\n\t}\r\n\t\r\n\t// look for a collision up through the body to the head\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_end = m_pos;\r\n\tfeeler.m_end[Y] += walker_height;\r\n\tif (!feeler.GetCollision()) return;\r\n\t\r\n\t// project velocity into plane\r\n\tm_horizontal_vel[Y] = m_vertical_vel;\r\n\tif (Mth::DotProduct(m_horizontal_vel, feeler.GetNormal()) < 0.0f)\r\n\t{\r\n\t\tm_horizontal_vel.ProjectToPlane(feeler.GetNormal());\r\n\t}\r\n\tm_vertical_vel = m_horizontal_vel[Y];\r\n\tm_horizontal_vel[Y] = 0.0f;\r\n\t\r\n\t// determine the displacement vector we must use to get out of the ceiling\r\n\tMth::Vector displacement = feeler.GetPoint() - feeler.m_end;\r\n\tdisplacement.ProjectToNormal(feeler.GetNormal());\r\n\t\r\n\t// insure there are no collisions along this displacement\r\n\tfeeler.m_end = m_pos + displacement;\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tm_pos = feeler.GetPoint() + feeler.GetNormal();\r\n\t\tDUMP_WPOSITION\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_pos = feeler.m_end;\r\n\t\tDUMP_WPOSITION\r\n\t}\r\n\t\r\n\tGetObject()->SelfEvent(CRCD(0x6e84acf3, \"HitCeiling\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::check_for_landing ( const Mth::Vector& previous_pos, const Mth::Vector& final_pos )\r\n{\r\n\t// See if our feet have passed through geometry.  If so, snap to it and go to ground state.\r\n\t\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = previous_pos;\r\n\tfeeler.m_end = final_pos;\r\n\tif (!feeler.GetCollision()) return;\r\n\t\r\n\tif (feeler.GetFlags() & mFD_NOT_SKATABLE)\r\n\t{\r\n        m_pos = feeler.GetPoint() + 0.1f * feeler.GetNormal();\r\n\t\tDUMP_WPOSITION\r\n\t\t\r\n\t\tMth::Vector remaining_movement = (1.0f - feeler.GetDist()) * (feeler.m_end - feeler.m_start);\r\n\t\tremaining_movement.ProjectToPlane(feeler.GetNormal());\r\n\t\t\r\n\t\t// slide along the surface, but stop at any new collision\r\n\t\tfeeler.m_start = m_pos;\r\n\t\tfeeler.m_end = m_pos + remaining_movement;\r\n\t\tif (feeler.GetCollision())\r\n\t\t{\r\n\t\t\tm_pos = feeler.GetPoint() + 0.05f * feeler.GetNormal();\r\n\t\t\tDUMP_WPOSITION\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_pos = feeler.m_end;\r\n\t\t\tDUMP_WPOSITION\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// snap to the collision point\r\n\tm_pos = feeler.GetPoint();\r\n\tDUMP_WPOSITION\r\n\t\r\n\t// zero vertical velocity\r\n\tm_vertical_vel = 0.0f;\r\n\t\r\n\t// change to ground state\r\n\tset_state(WALKING_GROUND);\r\n\t\r\n\t// stash the feeler\r\n\tm_last_ground_feeler = feeler;\r\n\tm_last_ground_feeler_valid = true;\r\n\t\r\n\t// trip any land trigger\r\n\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_LAND_ON, m_last_ground_feeler);\r\n\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\r\n\t// setup our ground normal for next frames velocity slope adjustment\r\n\tm_ground_normal = feeler.GetNormal();\r\n\t\r\n\t// check for a moving contact\r\n\tmp_movable_contact_component->CheckForMovableContact(feeler);\r\n\tif (mp_movable_contact_component->HaveContact())\r\n\t{\r\n\t\tm_horizontal_vel -= mp_movable_contact_component->GetContact()->GetObject()->GetVel();\r\n\t\tm_horizontal_vel[Y] = 0.0f;\r\n\t}\r\n\t\r\n\t// retain only that velocity which is parallel to our facing and forward\r\n\tif (Mth::DotProduct(m_horizontal_vel, m_facing) > 0.0f)\r\n\t{\r\n\t\tm_horizontal_vel.ProjectToNormal(m_facing);\r\n\t\t\r\n\t\tif (m_control_magnitude == 0.0f && m_horizontal_vel.Length() < s_get_param(CRCD(0x530dcf34, \"sticky_land_threshold_speed\")))\r\n\t\t{\r\n\t\t\tm_horizontal_vel.Set();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_horizontal_vel.Set();\r\n\t}\r\n\r\n\tm_critical_point_offset.Set();\r\n\r\n\t// clear any jump requests\r\n\tmp_input_component->GetControlPad().m_x.ClearRelease();\r\n\r\n\tm_frame_event = CRCD(0x57ff2a27, \"Land\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::maybe_wallplant (   )\r\n{\r\n\tif (!mp_input_component->GetControlPad().m_x.GetPressed()) return;\r\n\t\r\n\t// only wallplant on the way down\r\n\tif (m_vertical_vel > 0.0f) return;\r\n\t\t\t\t\t   \t\r\n\t// not when you're too near the ground\r\n\tif (mp_state_component->m_height < Script::GetFloat(CRCD(0xd5349cc6, \"Physics_Min_Wallplant_Height\"))) return;\r\n\r\n\t// if (Tmr::ElapsedTime(m_state_timestamp) < s_get_param(CRCD(0x2a2d65c, \"min_air_before_wallplant\"))) return;\r\n\t\r\n\t// last wallplant must not have been too recently\r\n\tif (Tmr::ElapsedTime(mp_core_physics_component->m_last_wallplant_time_stamp) < Script::GetFloat(CRCD(0x82135dd7, \"Physics_Disallow_Rewallplant_Duration\"))) return;\r\n\t\r\n\t// no wallplants immediately after you enter air; stops wallplants during the late jump period\r\n\tif (Tmr::ElapsedTime(m_state_timestamp) < Script::GetFloat(CRCD(0x4c2b6df3, \"Skater_Late_Jump_Slop\"))) return;\r\n\t\r\n\t// identify the primary contact wall; not that we are ignoring the \"feet feeler\"\r\n\tint n;\r\n\tint contact_idx;\r\n\tconst int p_contact_indxs[vNUM_FEELERS] = { 0, 1, 6, 2, 5, 3, 4 };\r\n\tfor (n = 0; n < vNUM_FEELERS; n++)\r\n\t{\r\n\t\tif (mp_contacts[contact_idx = p_contact_indxs[n]].in_collision) break;\r\n\t}\r\n\tif (n == vNUM_FEELERS) return;\r\n\t\r\n\t/*\r\n\t// here we attempt to stop wallplant when in is more likely that the player is going for a grind or wants to jump up over the wall\r\n\tif (GetObject()->m_vel[Y] > 0.0f)\r\n\t{\r\n\t\tMth::Vector wall_point = mp_contacts[contact_idx].feeler.GetPoint();\r\n\t\tMth::Vector\twall_normal = mp_contacts[contact_idx].feeler.GetNormal();\r\n\r\n\t\tMth::Vector wall_up_vel(0.0f, GetObject()->m_vel[Y] * 0.15f, 0.0f);\t\t// check 0.15 seconds ahead\r\n\t\twall_up_vel.RotateToPlane(wall_normal);  \r\n\r\n\t\t// check at what height will be in two frames\r\n\t\twall_point += wall_up_vel;\t\t\r\n\r\n\t\tCFeeler feeler(wall_point + wall_normal * 6.0f, wall_point - wall_normal * 6.0f);\r\n\t\tif (!feeler.GetCollision())\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t{\r\n\t\t\t\tfeeler.DebugLine(255, 255, 0, 0);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t\treturn;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t{\r\n\t\t\t\tfeeler.DebugLine(255, 0, 255, 0);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t}\r\n\t}\r\n\t*/\r\n\t\r\n\t// reflect the control direction off the wall and use it as our facing and boost direction\r\n\tMth::Vector exit_dir;\r\n\tif (m_control_magnitude == 0.0f)\r\n\t{\r\n\t\texit_dir = m_primary_air_direction;\r\n\t}\r\n\telse\r\n\t{\r\n\t\texit_dir = m_control_direction;\r\n\t}\r\n\tfloat dot = Mth::DotProduct(exit_dir, mp_contacts[contact_idx].normal);\r\n\tif (dot < 0.0f)\r\n\t{\r\n\t\texit_dir -= 2.0f * dot * mp_contacts[contact_idx].normal;\r\n\t}\r\n\t\r\n\t// set vertical velocity to the walking wallplant jump speed\r\n\tm_vertical_vel = s_get_param(CRCD(0x420d18bc, \"vert_wall_jump_speed\")) * Mth::Lerp(\r\n\t\ts_get_param(CRCD(0x246d0bf3, \"min_jump_factor\")), \r\n\t\t1.0f,\r\n\t\tMth::ClampMax(mp_input_component->GetControlPad().m_x.GetPressedTime() / s_get_param(CRCD(0x12333ebd, \"hold_time_for_max_jump\")), 1.0f)\r\n\t);\r\n\t\r\n\t// jump out from the wall\r\n\tm_horizontal_vel = s_get_param(CRCD(0x99510695, \"horiz_wall_jump_speed\")) * exit_dir;\r\n\tm_primary_air_direction = m_facing;\r\n\r\n\t// if the wall is moving, add on its velocity\r\n\tif (mp_contacts[contact_idx].feeler.IsMovableCollision())\r\n\t{\r\n\t\tMth::Vector movable_contact_vel = mp_contacts[contact_idx].feeler.GetMovingObject()->GetVel();\r\n\t\tm_vertical_vel += movable_contact_vel[Y];\r\n\t\tm_horizontal_vel[X] += movable_contact_vel[X];\r\n\t\tm_horizontal_vel[Z] += movable_contact_vel[Z];\r\n\t}\r\n\t\r\n\tadjust_jump_for_ceiling_obstructions();\r\n\t\r\n\t// trip any triggers\r\n\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_JUMP_OFF, mp_contacts[contact_idx].feeler);\r\n\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\r\n\t// graffiti the object\r\n\tGetTrickComponentFromObject(GetObject())->TrickOffObject(mp_contacts[contact_idx].feeler.GetNodeChecksum());\r\n\t\r\n\t// time stamp the wallplant\r\n\tmp_core_physics_component->m_last_wallplant_time_stamp = Tmr::GetTime();\r\n\t\r\n\tm_frame_event = CRCD(0xcf74f6b7, \"WallPlant\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::uber_frig (   )\r\n{\r\n\t// insure that we don't fall to the center of the earth, even if there are holes in the geometry; also, do lighting since we've got the feeler anyway\r\n\t\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos + m_critical_point_offset;\r\n\tfeeler.m_end = feeler.m_start;\r\n\tfeeler.m_start[Y] += 1.0f;\r\n\tfeeler.m_end[Y] -= FEET(400);\r\n\t\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t// set the height for script access\r\n\t\tmp_state_component->m_height = m_pos[Y] - feeler.GetPoint()[Y];\r\n\t\t\r\n\t\tmp_model_component->ApplyLightingFromCollision(feeler);\r\n\t\t\r\n\t\t// Store these values off for the simple shadow calculation.\r\n\t\tCShadowComponent* p_shadow_component = GetShadowComponentFromObject(GetObject());\r\n\t\tp_shadow_component->SetShadowPos(feeler.GetPoint());\r\n\t\tp_shadow_component->SetShadowNormal(feeler.GetNormal()); \r\n\t\t\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tMESSAGE(\"applying uber frig\");\r\n\t\r\n\t// teleport us back to our position at the frame's start; not pretty, but this isn't supposed to be\r\n\tm_pos = m_frame_start_pos;\r\n\tDUMP_WPOSITION\r\n\t\r\n\t// zero our velocity too\r\n\tm_horizontal_vel.Set();\r\n\tm_vertical_vel = 0.0f;\r\n\t\r\n\t// set our state to ground\r\n\tset_state(WALKING_GROUND);\r\n\t\t\t  \t\r\n\tm_last_ground_feeler_valid = false;\r\n\t\r\n\tm_ground_normal.Set(0.0f, 1.0f, 0.0f);\r\n\r\n\t// reset our script state\r\n\tm_frame_event = CRCD(0x57ff2a27, \"Land\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::lerp_upright (   )\r\n{\r\n    if (m_upward[Y] == 1.0f) return;\r\n\t\r\n\tif (m_upward[Y] > 0.999f)\r\n\t{\r\n\t\tm_upward.Set(0.0f, 1.0f, 0.0f);\r\n\t\tm_rotate_upright_timer = 0.0f;\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif (m_rotate_upright_timer == 0.0f)\r\n\t{\r\n\t\tm_upward = Mth::Lerp(m_upward, Mth::Vector(0.0f, 1.0f, 0.0f), s_get_param(CRCD(0xf22c135, \"lerp_upright_rate\")) * Tmr::FrameLength());\r\n\t\tm_upward.Normalize();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::transition_lerp_upright (   )\r\n{\r\n\tif (m_rotate_upright_timer != 0.0f)\r\n\t{\r\n\t\tfloat lerp_factor = Mth::LinearMap(0.0f, 1.0f, m_frame_length, 0.0f, s_get_param(CRCD(0xb0675803, \"rotate_upright_duration\")));\r\n\t\t\r\n\t\tGetObject()->GetMatrix().Rotate(m_rotate_upright_axis, m_rotate_upright_angle * lerp_factor);\r\n\t\tGetObject()->SetDisplayMatrix(GetObject()->GetMatrix());\r\n\t\t\r\n\t\tm_rotate_upright_timer -= m_frame_length;\r\n\t\tm_rotate_upright_timer = Mth::ClampMin(m_rotate_upright_timer, 0.0f);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::check_for_wall_push (   )\r\n{\r\n\t// ensure we have a forward contact\r\n\tif (!mp_contacts[0].in_collision && !mp_contacts[1].in_collision && !mp_contacts[vNUM_FEELERS - 1].in_collision)\r\n\t{\r\n\t\treturn m_wall_push_test.active = false;\r\n\t}\r\n\t\r\n\t// ensure that control is maxed out\r\n\tif (!m_control_pegged)\r\n\t{\r\n\t\treturn m_wall_push_test.active = false;\r\n\t}\r\n\t\r\n\tif (!m_wall_push_test.active)\r\n\t{\r\n\t\t// if we're not testing, simply start the test\r\n\t\tm_wall_push_test.test_start_time = Tmr::GetTime();\r\n\t\tm_wall_push_test.active = true;\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::maybe_jump_low_barrier (   )\r\n{\r\n\t// check to see if we're in a bail\r\n\tif (mp_core_physics_component->GetFlag(IS_BAILING)) return false;\r\n\t\r\n\t// For each forward contact in collision, we check to see if any lacks a collision at the maximum jump height.  For any that do, we find the first height\r\n\t// at which they are in contact.  The lowest such height is used at the target jump height.\r\n\t\r\n\tconst int p_forward_contact_idxs[] = { 0, 1, vNUM_FEELERS - 1 };\r\n\t\r\n\t// we use the lowest hang height as the maximum autojump barrier height\r\n\tfloat top_feeler_height = s_get_param(CRCD(0xda85f5ae, \"barrier_jump_highest_barrier\"));\r\n\tfloat feeler_length = 3.0f * s_get_param(CRCD(0x99978d2b, \"feeler_length\"));\r\n\tfloat height_increment = (top_feeler_height - s_get_param(CRCD(0x6da7f696, \"feeler_height\"))) / vNUM_BARRIER_HEIGHT_FEELERS;\r\n\t\r\n\tCFeeler feeler;\r\n\t\r\n\t// setup collision cache\r\n\tMth::CBBox bbox(\r\n\t\tm_pos - Mth::Vector(feeler_length + 1.0f, 0.0f, feeler_length + 1.0f),\r\n\t\tm_pos + Mth::Vector(feeler_length + 1.0f, top_feeler_height + 1.0f, feeler_length + 1.0f)\r\n\t);\r\n\tNx::CCollCache* p_coll_cache = Nx::CCollCacheManager::sCreateCollCache();\r\n\tp_coll_cache->Update(bbox);\r\n\tfeeler.SetCache(p_coll_cache);\r\n\t\r\n\t// loop over forward collisions and check to see if the barrier in each of their directions is jumpable\r\n\tbool jumpable = false;\r\n\tfor (int i = 0; i < 3; i++)\r\n\t{\r\n\t\tint n = p_forward_contact_idxs[i];\r\n\t\t\r\n\t\tif (!mp_contacts[n].in_collision || (mp_contacts[n].feeler.GetFlags() & mFD_NOT_SKATABLE)) continue;\r\n\t\t\r\n\t\t// first check to see if the collision normal is not too transverse to the control direction, making a autojump unlikely to succeed\r\n\t\tif (Mth::DotProduct(mp_contacts[n].normal, m_control_direction) > -cosf(Mth::DegToRad(s_get_param(CRCD(0x78e6a5ec, \"barrier_jump_max_angle\")))))\r\n\t\t{\r\n\t\t\tmp_contacts[n].jumpable = false;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tfeeler.m_start = m_pos;\r\n\t\tfeeler.m_start[Y] += top_feeler_height;\r\n\t\tfeeler.m_end = feeler.m_start + feeler_length * calculate_feeler_offset_direction(n);\r\n\t\t\r\n\t\tmp_contacts[n].jumpable = !feeler.GetCollision();\r\n\t\t\r\n        if (mp_contacts[n].jumpable)\r\n\t\t{\r\n\t\t\tjumpable = true;\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t{\r\n\t\t\t\tfeeler.DebugLine(0, 0, 255, 0);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t{\r\n\t\t\t\tfeeler.DebugLine(255, 0, 0, 0);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t}\r\n\t}\r\n\t\r\n\t// if the barrier is not jumpable\r\n\tif (!jumpable)\r\n\t{\r\n\t\t// no autojump\r\n\t\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// loop over the jumpable collision directions\r\n\tfloat lowest_height = m_pos[Y] + top_feeler_height;\r\n\tfor (int i = 0; i < 3; i++)\r\n\t{\r\n\t\tint n = p_forward_contact_idxs[i];\r\n\t\t\r\n\t\tif (!mp_contacts[n].in_collision) continue;\r\n\t\tif (!mp_contacts[n].jumpable) continue;\r\n\t\t\r\n\t\tfeeler.m_start = m_pos;\r\n\t\tfeeler.m_start[Y] += top_feeler_height;\r\n\t\tfeeler.m_end = feeler.m_start + feeler_length * calculate_feeler_offset_direction(n);\r\n\t\t\r\n\t\t// look for the barrier height\r\n\t\tfor (int h = vNUM_BARRIER_HEIGHT_FEELERS - 1; h--; )\r\n\t\t{\r\n\t\t\tfeeler.m_start[Y] -= height_increment;\r\n\t\t\tfeeler.m_end[Y] -= height_increment;\r\n\t\t\tif (feeler.GetCollision())\r\n\t\t\t{\r\n\t\t\t\t#ifdef __USER_DAN__\r\n\t\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t\t{\r\n\t\t\t\t\tfeeler.DebugLine(255, 0, 0, 0);\r\n\t\t\t\t}\r\n\t\t\t\t#endif\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t#ifdef __USER_DAN__\r\n\t\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t\t{\r\n\t\t\t\t\tfeeler.DebugLine(0, 255, 0, 0);\r\n\t\t\t\t}\r\n\t\t\t\t#endif\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// find the lowest barrier of the jumpable directions\r\n\t\tif (lowest_height > feeler.m_start[Y])\r\n\t\t{\r\n\t\t\tlowest_height = feeler.m_start[Y];\r\n\t\t}\r\n\t}\r\n\t\r\n\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\r\n\t// caluclate the velocity required to clear the barrier\r\n\tfloat jump_height = lowest_height + height_increment + s_get_param(CRCD(0x72660978, \"barrier_jump_min_clearance\")) - m_pos[Y];\r\n\tfloat required_vertical_velocity = sqrtf(2.0f * get_gravity() * jump_height);\r\n\t\r\n\tif (m_last_ground_feeler_valid)\r\n\t{\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_JUMP_OFF, m_last_ground_feeler);\r\n\t\tif (mp_physics_control_component->HaveBeenReset()) return true;\r\n\t}\r\n\t\r\n\t// setup the new walking state\r\n\t\r\n\tm_vertical_vel = required_vertical_velocity;\r\n\t\r\n\tset_state(WALKING_AIR);\r\n\t\r\n\tm_primary_air_direction = m_facing;\r\n\tleave_movable_contact_for_air(m_horizontal_vel, m_vertical_vel);\r\n\t\r\n\tm_frame_event = CRCD(0x584cf9e9, \"Jump\");\r\n\t\r\n\tGetObject()->BroadcastEvent(CRCD(0x8687163a, \"SkaterJump\"));\r\n\t\r\n\t// stop late jumps after an autojump\r\n\tGetObject()->RemoveEventHandler(CRCD(0x6b9ca247, \"JumpRequested\"));\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::maybe_in_air_acid_drop (   )\r\n{\r\n\tif (m_disallow_acid_drops) return false;\r\n\tif (mp_physics_control_component->IsBoardMissing()) return false;\r\n\t\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\tif (!WALK_SPINE_BUTTONS) return false;\r\n\t\r\n\tMth::Vector vel(m_horizontal_vel[X], m_vertical_vel, m_horizontal_vel[Z]);\r\n\tif (!mp_core_physics_component->maybe_acid_drop(false, m_pos, m_frame_start_pos, vel, m_special_transition_data.acid_drop_data)) return false;\r\n\t\r\n\tm_horizontal_vel = vel;\r\n\tm_horizontal_vel[Y] = 0.0f;\r\n\tm_vertical_vel = vel[Y];\r\n\tm_special_transition_data.type = ACID_DROP_TRANSITION;\r\n\tm_frame_event = CRCD(0x2eda83ea, \"AcidDrop\");\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::maybe_jump_to_acid_drop (   )\r\n{\r\n\t// we're on the ground; look ahead for acid drops to autojump into\r\n\t\r\n\tif (m_disallow_acid_drops) return false;\r\n\tif (mp_physics_control_component->IsBoardMissing()) return false;\r\n\t\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\tif (!WALK_SPINE_BUTTONS) return false;\r\n\t\r\n\tMth::Vector jump_vel = m_horizontal_vel;\r\n\tjump_vel[Y] = s_get_param(CRCD(0xc0491d2e, \"acid_drop_jump_velocity\"));\r\n\t\r\n\tif (!mp_core_physics_component->maybe_acid_drop(false, m_pos, m_frame_start_pos, jump_vel, m_special_transition_data.acid_drop_data)) return false;\r\n\t\r\n\tif (m_last_ground_feeler_valid)\r\n\t{\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_JUMP_OFF, m_last_ground_feeler);\r\n\t\tif (mp_physics_control_component->HaveBeenReset()) return true;\r\n\t}\r\n\t\r\n\tset_state(WALKING_AIR);\r\n\t\r\n\tm_horizontal_vel = jump_vel;\r\n\tm_horizontal_vel[Y] = 0.0f;\r\n\tm_vertical_vel = jump_vel[Y];\r\n\tm_special_transition_data.type = ACID_DROP_TRANSITION;\r\n\tm_frame_event = CRCD(0x2eda83ea, \"AcidDrop\");\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::leave_movable_contact_for_air ( Mth::Vector& horizontal_vel, float& vertical_vel )\r\n{\r\n\t// use movement from the latest movable contact update call\r\n\t\r\n\tif (mp_movable_contact_component->HaveContact())\r\n\t{\r\n\t\t// keep track of the horizontal velocity due to our old contact\r\n\t\tm_uncontrollable_air_horizontal_vel = mp_movable_contact_component->GetContact()->GetObject()->GetVel();\r\n\r\n\t\tif (Mth::DotProduct(m_uncontrollable_air_horizontal_vel, horizontal_vel) > 0.0f)\r\n\t\t{\r\n\t\t\t// extra kicker; dangerous as there's no collision detection; without this slight extra movement, when we walk off the front of a movable object,\r\n\t\t\t// the object will move back under us before our next frame, and we will clip its edge and land on it\r\n\t\t\tm_pos += m_uncontrollable_air_horizontal_vel * m_frame_length;\r\n\t\t\tDUMP_WPOSITION\r\n\t\t}\r\n\t\t\r\n\t\t// add movable contact's velocity into our launch velocity\r\n\t\tvertical_vel += m_uncontrollable_air_horizontal_vel[Y];\r\n\t\tm_uncontrollable_air_horizontal_vel[Y] = 0.0f;\r\n\t\thorizontal_vel += m_uncontrollable_air_horizontal_vel;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_uncontrollable_air_horizontal_vel.Set();\r\n\t}\r\n\t\r\n\tmp_movable_contact_component->LoseAnyContact();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::calculate_anim_wait_facing_drift_parameters ( const Mth::Vector& goal_facing, float rotate_factor )\r\n{\r\n\tfloat initial_angle = atan2f(m_facing[X], m_facing[Z]);\r\n\tfloat goal_angle = atan2f(goal_facing[X], goal_facing[Z]);\r\n\t\r\n\tm_drift_angle = goal_angle - initial_angle;\r\n\tif (Mth::Abs(m_drift_angle) > Mth::PI)\r\n\t{\r\n\t\tm_drift_angle -= Mth::Sgn(m_drift_angle) * (2.0f * Mth::PI);\r\n\t}\r\n\t\r\n\tm_drift_goal_facing = goal_facing;\r\n\t\r\n\tm_drift_goal_rotate_factor = rotate_factor;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::go_anim_wait_state (   )\r\n{\r\n\tif (mp_movable_contact_component->UpdateContact(m_pos))\r\n\t{\r\n\t\tm_offset_due_to_movable_contact += mp_movable_contact_component->GetContact()->GetMovement();\r\n\t\tif (mp_movable_contact_component->GetContact()->IsRotated())\r\n\t\t{\r\n\t\t\tm_drift_goal_facing = mp_movable_contact_component->GetContact()->GetRotation().Rotate(m_drift_goal_facing);\r\n\t\t\tif (m_drift_goal_facing[Y] != 0.0f)\r\n\t\t\t{\r\n\t\t\t\tm_drift_goal_facing[Y] = 0.0f;\r\n\t\t\t\tm_drift_goal_facing.Normalize();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t}\r\n\t}\r\n\t\r\n\tfloat start, current, end;\r\n\tmp_animation_component->GetPrimaryAnimTimes(&start, &current, &end);\r\n    float animation_completion_factor = Mth::LinearMap(0.0f, 1.0f, current, start, end);\r\n\t\r\n\t// smoothly drift the position\r\n\tm_pos = m_offset_due_to_movable_contact + Mth::Lerp(m_anim_wait_initial_pos, m_anim_wait_goal_pos, animation_completion_factor);\r\n\tDUMP_WPOSITION\r\n\t\r\n\tfloat angle = Mth::Lerp(-m_drift_angle, 0.0f, Mth::ClampMax(animation_completion_factor / m_drift_goal_rotate_factor, 1.0f));\r\n\tm_facing = m_drift_goal_facing;\r\n\tm_facing.RotateY(angle);\r\n\t\r\n\tm_display_offset = Mth::Lerp(m_drift_initial_display_offset, m_drift_goal_display_offset, animation_completion_factor);\r\n\t\r\n\tm_frame_event = CRCD(0x4fe6069c, \"AnimWait\");\r\n}\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::anim_wait_complete (   )\r\n{\r\n\tGetObject()->SetPos(m_anim_wait_goal_pos + m_offset_due_to_movable_contact);\r\n\t\r\n    Mth::Matrix matrix;\r\n    matrix[Z] = m_drift_goal_facing;\r\n    matrix[Y].Set(0.0f, 1.0f, 0.0f);\r\n    matrix[X].Set(m_drift_goal_facing[Z], 0.0f, -m_drift_goal_facing[X]);\r\n\tmatrix[W].Set();\r\n\tGetObject()->SetMatrix(matrix);\r\n\t\r\n\tm_display_offset = m_drift_goal_display_offset;\r\n\t\r\n    if (mp_anim_wait_complete_callback)\r\n    {\r\n        (this->*mp_anim_wait_complete_callback)();\r\n    }\r\n}\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::maybe_stick_to_rail (   )\r\n{\r\n\t// Look for rails.  If we find one, switch to skating and stash the rail data for the skating physics.\r\n\t\r\n\tif (mp_physics_control_component->IsBoardMissing()) return false;\r\n\t\r\n\tbool rail_found = false;\r\n\t\r\n\tif (rail_found = Mdl::Skate::Instance()->GetRailManager()->StickToRail(\r\n\t\tm_frame_start_pos,\r\n\t\tm_pos,\r\n\t\t&m_special_transition_data.rail_data.rail_pos,\r\n\t\t&m_special_transition_data.rail_data.p_node,\r\n\t\tNULL,\r\n\t\t1.0f\r\n\t))\r\n\t{\r\n\t\tm_special_transition_data.rail_data.p_rail_man = Mdl::Skate::Instance()->GetRailManager();\r\n\t\tm_special_transition_data.rail_data.p_movable_contact = NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// clean vectors\r\n\t\tm_frame_start_pos[W] = 1.0f;\r\n\t\tm_pos[W] = 1.0f;\r\n\t\t\r\n\t\tfor (CRailManagerComponent* p_rail_manager_component = static_cast< CRailManagerComponent* >(CCompositeObjectManager::Instance()->GetFirstComponentByType(CRC_RAILMANAGER));\r\n\t\t\tp_rail_manager_component && !rail_found;\r\n\t\t\tp_rail_manager_component = static_cast< CRailManagerComponent* >(p_rail_manager_component->GetNextSameType()))\r\n\t\t{\r\n\t\t\tMth::Matrix obj_matrix = p_rail_manager_component->UpdateRailManager();\r\n\t\t\tMth::Matrix obj_matrix_inv = obj_matrix;\r\n\t\t\tobj_matrix_inv.Invert();\r\n\r\n\t\t\t// transform into the frame of the moving object\r\n\t\t\tMth::Vector obj_frame_frame_start_pos = obj_matrix_inv.Transform(m_frame_start_pos);\r\n\t\t\tMth::Vector obj_frame_pos = obj_matrix_inv.Transform(m_pos);\r\n\r\n\t\t\tif (rail_found = p_rail_manager_component->GetRailManager()->StickToRail(\r\n\t\t\t\tobj_frame_frame_start_pos,\r\n\t\t\t\tobj_frame_pos,\r\n\t\t\t\t&m_special_transition_data.rail_data.rail_pos,\r\n\t\t\t\t&m_special_transition_data.rail_data.p_node,\r\n\t\t\t\tNULL,\r\n\t\t\t\t1.0f\r\n\t\t\t))\r\n\t\t\t{\r\n\t\t\t\tm_special_transition_data.rail_data.p_rail_man = p_rail_manager_component->GetRailManager();\r\n\t\t\t\tm_special_transition_data.rail_data.rail_pos = obj_matrix.Transform(m_special_transition_data.rail_data.rail_pos);\r\n\t\t\t\tm_special_transition_data.rail_data.p_movable_contact = p_rail_manager_component->GetObject();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tif (!rail_found || !mp_core_physics_component->will_take_rail(\r\n\t\tm_special_transition_data.rail_data.p_node,\r\n\t\tm_special_transition_data.rail_data.p_rail_man,\r\n\t\ttrue\r\n\t))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// no single node rails while walking\r\n\tif (!m_special_transition_data.rail_data.p_node->GetPrevLink() && !m_special_transition_data.rail_data.p_node->GetNextLink()) return false;\r\n\t\r\n\t// emulate feeler test in CSkaterCorePhysicsComponent::got_rail so that we don't transition to skating and then reject rail\r\n\tCFeeler feeler(m_pos, m_special_transition_data.rail_data.rail_pos);\r\n\tif (feeler.GetCollision() && (m_special_transition_data.rail_data.rail_pos - feeler.GetPoint()).LengthSqr() > 6.0f * 6.0f) return false;\r\n\t\r\n\tif (Script::GetInt(CRCD(0x19fb78fa, \"output_tracking_lines\")))\r\n\t{\r\n\t\tprintf (\"Tracking%d %.2f,%.2f,%.2f,%.2f,%.2f,%.2f\\n\", 2, m_frame_start_pos[X], m_frame_start_pos[Y], m_frame_start_pos[Z], m_pos[X], m_pos[Y], m_pos[Z]);\r\n\t}\r\n\t\r\n\t// we have stored the rail data so it can be passed on to the skating physics\r\n\t\r\n\tm_special_transition_data.type = RAIL_TRANSITION;\r\n\r\n\tm_frame_event = CRCD(0xa6a3147e, \"Rail\");\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::setup_collision_cache (   )\r\n{\r\n\tfloat horizontal_reach = 1.0f + s_get_param(CRCD(0x99978d2b, \"feeler_length\"));\r\n\tfloat vertical_height = 1.0f + s_get_param(CRCD(0x9ea1974a, \"walker_height\"));;\r\n\tfloat vertical_depth = 1.0f + s_get_param(CRCD(0xaf3e4251, \"snap_down_height\"));\r\n\t\r\n\tMth::CBBox bbox(\r\n\t\tGetObject()->GetPos() - Mth::Vector(horizontal_reach, vertical_depth, horizontal_reach, 0.0f),\r\n\t\tGetObject()->GetPos() + Mth::Vector(horizontal_reach, vertical_height, horizontal_reach, 0.0f)\r\n\t);\r\n\t\r\n\tmp_collision_cache->Update(bbox);\r\n\tCFeeler::sSetDefaultCache(mp_collision_cache);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::update_critical_point_offset (   )\r\n{\r\n\tfloat critical_point_offset_length_sqr = m_critical_point_offset.LengthSqr();\r\n\tif (critical_point_offset_length_sqr != 0.0f)\r\n\t{\r\n\t\tswitch (m_state)\r\n\t\t{\r\n\t\t\tcase WALKING_HANG:\r\n\t\t\t\tbreak;\r\n\t\t\t\t\r\n\t\t\tcase WALKING_ANIMWAIT:\r\n\t\t\t\tbreak;\r\n\t\t\t\t\r\n\t\t\tcase WALKING_LADDER:\r\n\t\t\tcase WALKING_GROUND:\r\n\t\t\tcase WALKING_AIR:\r\n\t\t\t{\r\n\t\t\t\tMth::Vector initial_offset = m_critical_point_offset;\r\n\t\t\t\t\r\n\t\t\t\t// float adjustment_length = 100.0f * m_frame_length;\r\n\t\t\t\tfloat adjustment_length = 1000.0f * m_frame_length;\r\n\t\t\t\tfloat offset_length = sqrtf(critical_point_offset_length_sqr);\r\n\t\t\t\tif (adjustment_length < offset_length)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_critical_point_offset -= (adjustment_length / offset_length) * m_critical_point_offset;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_critical_point_offset.Set();\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (m_state == WALKING_LADDER) break;\r\n\t\t\t\t\r\n\t\t\t\tCFeeler feeler;\r\n\t\t\t\tfeeler.m_start = m_frame_start_pos + initial_offset;\r\n\t\t\t\tfeeler.m_end = m_pos + m_critical_point_offset;\r\n\t\t\t\tif (feeler.GetCollision())\r\n\t\t\t\t{\r\n\t\t\t\t\tMth::Vector new_critical_point = feeler.GetPoint() + 0.1f * feeler.GetNormal();\r\n\t\t\t\t\tMth::Vector required_pos_adjustment = new_critical_point - feeler.m_end;\r\n\t\t\t\t\tm_pos += required_pos_adjustment;\r\n\t\t\t\t\tMESSAGE(\"adjusting position due to bad critical point\");\r\n\t\t\t\t\tDUMPV(required_pos_adjustment);\r\n\t\t\t\t\tDUMPV(m_critical_point_offset);\r\n\t\t\t\t\tDUMP_WPOSITION\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (m_false_wall.active)\r\n\t\t\t\t{\r\n\t\t\t\t\tfloat offset = Mth::DotProduct(m_pos + m_critical_point_offset, m_false_wall.normal) - m_false_wall.distance;\r\n\t\t\t\t\tif (offset > 0.0f)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_pos -= offset * m_false_wall.normal;\r\n\t\t\t\t\t\tDUMP_WPOSITION\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::update_display_offset (   )\r\n{\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase WALKING_ANIMWAIT:\r\n\t\tcase WALKING_HANG:\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tm_display_offset = Mth::Lerp(m_display_offset, 0.0f, Tmr::FrameLength() * s_get_param(CRCD(0xb32c972b, \"display_offset_restore_rate\")));\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::adjust_pos_for_false_wall (   )\r\n{\r\n\tif (!m_false_wall.active) return;\r\n\t\r\n\tif (m_pos[Y] > m_false_wall.cancel_height)\r\n\t{\r\n\t\tm_false_wall.active = false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfloat offset = Mth::DotProduct(m_false_wall.normal, m_pos) - m_false_wall.distance;\r\n\t\tif (offset > -s_get_param(CRCD(0xa20c43b7, \"push_feeler_length\")))\r\n\t\t{\r\n\t\t\tm_pos -= s_get_param(CRCD(0x4d16f37d, \"push_strength\")) * m_frame_length * m_false_wall.normal;\r\n\t\t\tDUMP_WPOSITION\r\n\t\t\tif (Mth::DotProduct(m_horizontal_vel, m_false_wall.normal))\r\n\t\t\t{\r\n\t\t\t\tm_horizontal_vel -= Mth::DotProduct(m_horizontal_vel, m_false_wall.normal) * m_false_wall.normal;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::extract_state_from_object (   )\r\n{\r\n\tm_pos = GetObject()->m_pos;\r\n\tDUMP_WPOSITION\r\n\t\r\n\tm_horizontal_vel = GetObject()->GetVel();\r\n\tm_horizontal_vel[Y] = 0.0f;\r\n\tm_vertical_vel = GetObject()->GetVel()[Y];\r\n\t\r\n\t// note that m_facing and m_upward will often not be orthogonal, but will always span a plan\r\n\t\r\n\t// generally straight up, but now after a transition from skating\r\n\tm_upward = GetObject()->GetMatrix()[Y];\r\n\t\r\n\tm_facing = GetObject()->GetMatrix()[Z];\r\n\tm_frame_initial_facing_Y = m_facing[Y];\r\n\tm_facing[Y] = 0.0f;\r\n\tfloat length = m_facing.Length();\r\n\tif (length < 0.001f)\r\n\t{\r\n\t\t// upward facing orientation matrix\r\n\t\tm_facing = -GetObject()->GetMatrix()[Y];\r\n\t\tm_facing[Y] = 0.0f;\r\n\t\tm_facing.Normalize();\r\n\t\t\r\n\t\t// since m_upward is now in the same plan as m_facing, push m_upward up a touch\r\n\t\tm_upward[Y] += 0.01f;\r\n\t\tm_upward.Normalize();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_facing /= length;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::copy_state_into_object (   )\r\n{\r\n\t// build the object's matrix based on our facing\r\n\tMth::Matrix matrix;\r\n\t\r\n\tm_facing *= sqrtf(1.0f - Mth::Sqr(m_frame_initial_facing_Y));\r\n\tm_facing[Y] = m_frame_initial_facing_Y;\r\n\t\r\n\t// basically, rotate Z upward to perpendicular with m_upward\r\n\tmatrix[X] = Mth::CrossProduct(m_upward, m_facing);\r\n\tmatrix[X].Normalize();\r\n\tmatrix[Y] = m_upward;\r\n\tmatrix[Z] = Mth::CrossProduct(matrix[X], matrix[Y]);\r\n\tmatrix[W].Set();\r\n\t\r\n\tDUMP_WPOSITION\r\n\tGetObject()->SetPos(m_pos);\r\n\tGetObject()->SetMatrix(matrix);\r\n\tGetObject()->SetDisplayMatrix(matrix);\r\n\t\r\n\t// construct the object's velocity\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase WALKING_GROUND:\r\n\t\tcase WALKING_AIR:\r\n\t\t\tGetObject()->SetVel(m_horizontal_vel);\r\n\t\t\tGetObject()->GetVel()[Y] = m_vertical_vel;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase WALKING_HANG:\r\n\t\t\tGetObject()->GetVel().Set(-m_facing[Z], 0.0f, m_facing[X]);\r\n\t\t\tGetObject()->GetVel() *= m_hang_move_vel;\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase WALKING_LADDER:\r\n\t\t\tGetObject()->GetVel().Set(0.0f, m_anim_effective_speed, 0.0f);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tGetObject()->GetVel().Set();\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\tmp_model_component->SetDisplayOffset(m_display_offset * matrix[Y]);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWalkComponent::get_controller_input (   )\r\n{\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\r\n\tDbg_Assert(mp_camera);\r\n\t\r\n\t// rotate controller direction into camera's frame\r\n\t\r\n\tMth::Vector camera_forward = -mp_camera->m_matrix[Z];\r\n\tcamera_forward[Y] = 0.0f;\r\n\tcamera_forward.Normalize();\r\n\t\r\n\t// allow a tolerance range for pressing directly forward\r\n\tfloat angle = control_pad.m_leftAngle;\r\n\tif (Mth::Abs(angle) < Mth::DegToRad(s_get_param(CRCD(0x4676a268, \"forward_tolerance\"))))\r\n\t{\r\n\t\tangle = 0.0f;\r\n\t}\r\n\t\r\n\tfloat sin_angle = sinf(angle);\r\n\tfloat cos_angle = cosf(angle);\r\n\tm_control_direction[X] = cos_angle * camera_forward[X] - sin_angle * camera_forward[Z];\r\n\tm_control_direction[Z] = sin_angle * camera_forward[X] + cos_angle * camera_forward[Z];\r\n\t\r\n\t// different control schemes for analog stick and d-pad\r\n\tif (control_pad.m_leftX == 0.0f && control_pad.m_leftY == 0.0f)\r\n\t{\r\n\t\t// d-pad control\r\n\t\tm_analog_control = false;\r\n\t\r\n\t\tif (control_pad.m_leftLength == 0.0f)\r\n\t\t{\r\n\t\t\tm_control_magnitude = 0.0f;\r\n\t\t\tm_control_pegged = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (m_state == WALKING_GROUND && !control_pad.m_x.GetPressed())\r\n\t\t\t{\r\n\t\t\t\tm_control_magnitude = s_get_param(CRCD(0xc1528f7f, \"walk_point\"));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_control_magnitude = 1.0f;\r\n\t\t\t}\r\n\t\t\t\r\n            m_control_pegged = true;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// analog stick control\r\n\t\tm_analog_control = true;\r\n\t\t\r\n\t\tm_control_magnitude = control_pad.GetScaledLeftAnalogStickMagnitude() / 0.85f;\r\n\t\tif (m_control_magnitude >= 1.0f)\r\n\t\t{\r\n\t\t\tm_control_magnitude = 1.0f;\r\n\t\t\tm_control_pegged = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_control_pegged = false;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// during a forward control lock, ignore all input not in the forward direction\r\n\tif (m_state == WALKING_GROUND && m_forward_control_lock)\r\n\t{\r\n\t\tm_control_magnitude = Mth::ClampMin(m_control_magnitude * Mth::DotProduct(m_control_direction, m_facing), 0.0f);\r\n\t\tm_control_direction = m_facing;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CWalkComponent::calculate_desired_speed (   )\r\n{\r\n\tfloat desired_speed;\r\n\t\r\n\tif (m_control_magnitude == 0.0f)\r\n\t{\r\n\t\tdesired_speed = 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfloat walk_point = s_get_param(CRCD(0xc1528f7f, \"walk_point\"));\r\n\t\tif (m_control_magnitude <= walk_point)\r\n\t\t{\r\n\t\t\tm_run_toggle = false;\r\n\t\t\tdesired_speed = Mth::LinearMap(0.0f, s_get_param(CRCD(0x79d182ad, \"walk_speed\")), m_control_magnitude, 0.3f, walk_point);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_run_toggle = true;\r\n\t\t\tdesired_speed = Mth::LinearMap(s_get_param(CRCD(0x79d182ad, \"walk_speed\")), get_run_speed(), m_control_magnitude, walk_point, 1.0f);\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn desired_speed;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CWalkComponent::calculate_feeler_offset_direction ( int contact )\r\n{\r\n\tfloat angle = contact * (2.0f * Mth::PI / vNUM_FEELERS);\r\n\tfloat cos_angle = cosf(angle);\r\n\tfloat sin_angle = sinf(angle);\r\n\r\n\tMth::Vector end_offset_direction;\r\n\tend_offset_direction[X] = cos_angle * m_facing[X] - sin_angle * m_facing[Z];\r\n\tend_offset_direction[Y] = 0.0f;\r\n\tend_offset_direction[Z] = sin_angle * m_facing[X] + cos_angle * m_facing[Z];\r\n\tend_offset_direction[W] = 1.0f;\r\n\t\r\n\treturn end_offset_direction;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::determine_stand_pos ( const Mth::Vector& proposed_stand_pos, Mth::Vector& stand_pos, CFeeler& feeler )\r\n{\r\n\t// upward offset of standing position at maximum standable slope\r\n\tfloat max_height_adjustment = 2.0f * s_get_param(CRCD(0x6da7f696, \"feeler_height\"));\r\n\t\r\n\tfeeler.m_start = proposed_stand_pos;\r\n\tfeeler.m_start[Y] += max_height_adjustment;\r\n\tfeeler.m_end = proposed_stand_pos;\r\n\tfeeler.m_end[Y] -= s_get_param(CRCD(0xaebfa9cd, \"stand_pos_search_depth\"));\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tstand_pos = feeler.GetPoint();\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(100, 100, 0, 0);\r\n\t\t}\r\n\t\t#endif\r\n\t\treturn true;\r\n\t}\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(255, 255, 0, 0);\r\n\t}\r\n\t#endif\r\n\t\r\n\tstand_pos = proposed_stand_pos;\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::update_run_speed_factor (   )\r\n{\r\n\tif (GetSkaterScoreComponentFromObject(GetObject())->GetScore()->GetScorePotValue() > 0)\r\n\t{\r\n\t\tm_run_speed_factor = 1.0f;\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tm_run_speed_factor = Mth::ClampMin(m_run_speed_factor - s_get_param(CRCD(0x3fb31dfc, \"run_adjust_rate\")) * Tmr::FrameLength(), 0.0f);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::smooth_anim_speed ( uint32 previous_frame_event )\r\n{\r\n\tif (m_state == WALKING_GROUND)\r\n\t{\r\n\t\tif (Tmr::ElapsedTime(m_state_timestamp)\t< 100)\r\n\t\t{\r\n\t\t\t// for the first few frames of the ground state, simply use this frame's anim speed\r\n\t\t\tm_last_frame_anim_effective_speed = m_anim_effective_speed;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// otherwise, use the smaller of the two anim speeds from this frame and the last\r\n\t\t\tfloat this_frame_anim_effective_speed = m_anim_effective_speed;\r\n\t\t\tm_anim_effective_speed = Mth::Min(m_anim_effective_speed, m_last_frame_anim_effective_speed);\r\n\t\t\tm_last_frame_anim_effective_speed = this_frame_anim_effective_speed;\r\n\t\t\t\r\n\t\t\t// adjust the frame event as appropriate\r\n\t\t\tif (m_frame_event == CRCD(0xaf895b3f, \"Run\") && m_anim_effective_speed == 0.0f)\r\n\t\t\t{\r\n\t\t\t\tswitch (previous_frame_event)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase CRCC(0x1d537eff, \"Skid\"):\r\n\t\t\t\t\tcase CRCC(0xf28adbfc, \"RotateLeft\"):\r\n\t\t\t\t\tcase CRCC(0x912220f8, \"RotateRight\"):\r\n\t\t\t\t\t\tm_frame_event = previous_frame_event;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tm_frame_event = CRCD(0x9b46e749, \"Stand\");\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::set_camera_overrides (   )\r\n{\r\n\tswitch (m_frame_event)\r\n\t{\r\n\t\t// case CRCC(0xf41aba21, \"Hop\"):\r\n\t\t\t// mp_camera_component->SetOverrides(m_facing, 0.05f);\r\n\t\t\t// break;\r\n\t\t\r\n\t\tcase CRCC(0x2d9815c3, \"HangMoveLeft\"):\r\n\t\t{\r\n\t\t\tMth::Vector facing = m_facing;\r\n\t\t\tfacing.RotateY(-0.95f);\r\n\t\t\tmp_camera_component->SetOverrides(facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase CRCC(0x279b1f0b, \"HangMoveRight\"):\r\n\t\t{\r\n\t\t\tMth::Vector facing = m_facing;\r\n\t\t\tfacing.RotateY(0.95f);\r\n\t\t\tmp_camera_component->SetOverrides(facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\t\r\n\t\tcase CRCC(0x4194ecca, \"Hang\"):\r\n\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase CRCC(0xc84243da, \"Ladder\"):\r\n\t\tcase CRCC(0xaf5abc82, \"LadderMoveUp\"):\r\n\t\tcase CRCC(0xfec9dded, \"LadderMoveDown\"):\r\n\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\tcase CRCC(0x4fe6069c, \"AnimWait\"):\r\n\t\t\tif (m_anim_wait_camera_mode == AWC_CURRENT)\r\n\t\t\t{\r\n\t\t\t\tmp_camera_component->SetOverrides(m_facing, 0.05f);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmp_camera_component->SetOverrides(m_drift_goal_facing, 0.05f);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tmp_camera_component->UnsetOverrides();\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::update_anim_speeds (   )\r\n{\r\n\tswitch (m_anim_scale_speed)\r\n\t{\r\n\t\tcase RUNNING:\r\n\t\t\tif (m_anim_standard_speed > 0.0f)\r\n\t\t\t{\r\n\t\t\t\tmp_animation_component->SetAnimSpeed(m_anim_effective_speed / m_anim_standard_speed, false, false);\r\n\t\t\t\t\r\n\t\t\t\t// if walking partial anims are active, update the partial anim speed too\r\n\t\t\t\tif (mp_physics_control_component->IsBoardMissing())\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct* pParams = new Script::CStruct;\r\n\t\t\t\t\tpParams->AddFloat(CRCD(0xf0d90109, \"Speed\"), m_anim_effective_speed / m_anim_standard_speed);\r\n\t\t\t\t\tmp_animation_component->CallMemberFunction(CRCD(0xbd4edd44, \"SetPartialAnimSpeed\"), pParams, NULL);\r\n\t\t\t\t\tdelete pParams;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase HANGMOVE:\r\n\t\t{\r\n\t\t\tfloat new_anim_speed = m_anim_effective_speed / s_get_param(CRCD(0x1a47ffab, \"hang_move_animation_speed\"));\r\n\t\t\t\r\n\t\t\tScript::CStruct* pParams = new Script::CStruct;\r\n\t\t\tpParams->AddFloat(CRCD(0xf0d90109, \"Speed\"), new_anim_speed);\r\n\t\t\tmp_animation_component->CallMemberFunction(CRCD(0xbd4edd44, \"SetPartialAnimSpeed\"), pParams, NULL);\r\n\t\t\tdelete pParams;\r\n\t\t\t\r\n\t\t\tmp_animation_component->SetAnimSpeed(new_anim_speed, false, false);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\t\r\n\t\tcase LADDERMOVE:\r\n\t\t{\r\n\t\t\tfloat new_anim_speed = m_anim_effective_speed / s_get_param(CRCD(0xab2db54, \"ladder_move_speed\"));\r\n\t\t\t\r\n\t\t\tScript::CStruct* pParams = new Script::CStruct;\r\n\t\t\tpParams->AddFloat(CRCD(0xf0d90109, \"Speed\"), new_anim_speed);\r\n\t\t\tmp_animation_component->CallMemberFunction(CRCD(0xbd4edd44, \"SetPartialAnimSpeed\"), pParams, NULL);\r\n\t\t\tdelete pParams;\r\n\t\t\t\r\n\t\t\t// Only ladder animation speed changes are sent to the server in net games.\r\n\t\t\tif (!GameNet::Manager::Instance()->InNetGame() || Mth::Abs(new_anim_speed - m_last_ladder_anim_speed) < 0.1f)\r\n\t\t\t{\r\n\t\t\t\tmp_animation_component->SetAnimSpeed(new_anim_speed, false, false);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_last_ladder_anim_speed = new_anim_speed;\r\n\t\t\t\tmp_animation_component->SetAnimSpeed(m_last_ladder_anim_speed, true, false);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CWalkComponent::get_gravity (   )\r\n{\r\n\tif (!Mdl::Skate::Instance()->GetCareer()->GetCheat(CRCD(0x9c8c6df1, \"CHEAT_MOON\")))\r\n\t{\r\n\t\treturn s_get_param(CRCD(0xa5e2da58, \"gravity\"));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMdl::Skate::Instance()->GetCareer()->SetGlobalFlag(Script::GetInteger(CRCD(0x9c8c6df1, \"CHEAT_MOON\")));\r\n\t\tg_CheatsEnabled = true;\r\n\t\treturn 0.5f * s_get_param(CRCD(0xa5e2da58, \"gravity\"));\r\n\t}\r\n}\r\n\r\n}\r\n\r\n#endif // TESTING_GUNSLINGER\r\n"
  },
  {
    "path": "Code/Gel/Components/WalkComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       WalkComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  4/2/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_WALKCOMPONENT_H__\r\n#define __COMPONENTS_WALKCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/timestampedflag.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n#include <sk/engine/feeler.h>\r\n\r\n#ifdef __NOPT_ASSERT__\r\n#define WHEADER { printf(\"%i:%s:%i: \", Tmr::GetRenderFrame(), __FILE__ + 15, __LINE__); }\r\n#define DUMP_WPOSITION { if (Script::GetInteger(CRCD(0x029ade47, \"debug_skater_pos\"))) { WHEADER; printf(\"m_pos = %g, %g, %g\\n\", m_pos[X], m_pos[Y], m_pos[Z]); } }\r\n#else\r\n#define DUMP_WPOSITION {   }\r\n#endif\r\n\r\n#define\t\tCRC_WALK CRCD(0x726e85aa, \"Walk\")\r\n\r\n#define\t\tGetWalkComponent() ((Obj::CWalkComponent*)GetComponent(CRC_WALK))\r\n#define\t\tGetWalkComponentFromObject(pObj) ((Obj::CWalkComponent*)(pObj)->GetComponent(CRC_WALK))\r\n\r\nclass CFeeler;\r\n\t\t\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\tclass CCollCache;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CAnimationComponent;\r\n\tclass CModelComponent;\r\n\tclass CTriggerComponent;\r\n\tclass CWalkCameraComponent;\r\n\tclass CSkaterPhysicsControlComponent;\r\n\tclass CSkaterStateComponent;\r\n\tclass CMovableContactComponent;\r\n    class CRailNode;\r\n    class CRailManager;\r\n\r\n\tstruct SHangRailData\r\n\t{\r\n\t\tMth::Vector\t\t\t\t\thang_point;\r\n\t\tMth::Vector\t\t\t\t\thang_facing;\r\n\t\tfloat\t\t\t\t\t\talong_rail_factor;\r\n\t\tfloat\t\t\t\t\t\thorizontal_hang_offset;\r\n\t\tfloat\t\t\t\t\t\tvertical_hang_offset;\r\n\t\tuint32\t\t\t\t\t\tinitial_animation;\r\n\t\tconst CRailNode*\t\t\tp_rail_node;\r\n\t};\r\n\t\r\n\tstruct SLadderRailData\r\n\t{\r\n\t\tMth::Vector\t\t\t\t\tclimb_point;\r\n\t\tMth::Vector\t\t\t\t\tclimb_facing;\r\n\t\tfloat\t\t\t\t\t\talong_rail_factor;\r\n\t};\r\n\t\r\nclass CWalkComponent : public CBaseComponent\r\n{\r\n\tfriend class CSkaterCorePhysicsComponent;\r\n\t\r\npublic:\r\n\tenum EStateType\r\n\t{\r\n\t\tWALKING_GROUND = 0,\r\n\t\tWALKING_AIR,\r\n\t\t// WALKING_HOP,\r\n\t\tWALKING_HANG,\r\n\t\tWALKING_LADDER,\r\n\t\tWALKING_ANIMWAIT,\r\n\t};\r\n\t\r\n\tenum { NUM_WALKING_STATES = 5 };\r\n\t\r\n\tenum EAnimScaleSpeed\r\n\t{\r\n\t\tOFF,\r\n\t\tRUNNING,\r\n        HANGMOVE,\r\n\t\tLADDERMOVE\r\n\t};\r\n\t\r\n\tenum\r\n\t{\r\n\t\tvNUM_FEELERS = 7,\r\n\t\tvNUM_BARRIER_HEIGHT_FEELERS = 9\r\n\t};\r\n\t\r\n\ttypedef void (Obj::CWalkComponent::*AnimWaitCallbackPtr) (   );\r\n\t\r\nprivate:\r\n\tstatic const uint32 sp_state_names [ NUM_WALKING_STATES ];\r\n\t\r\npublic:\r\n    CWalkComponent();\r\n    virtual ~CWalkComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tEStateType\t\t\t\t\t\tGetState (   ) { return m_state; }\r\n\t\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\tset_state ( EStateType state );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tgo_on_ground_state (   );\r\n\tvoid\t\t\t\t\t\t\tcalculate_horizontal_speed_and_facing ( float &horizontal_speed );\r\n\tbool\t\t\t\t\t\t\tadjust_horizonal_vel_for_environment (   );\r\n\tvoid\t\t\t\t\t\t\tadjust_facing_for_adjusted_horizontal_vel (   );\r\n\tfloat\t\t\t\t\t\t\tadjust_desired_speed_for_slope ( float desired_speed );\r\n\tvoid\t\t\t\t\t\t\trespond_to_ground (   );\r\n\tvoid\t\t\t\t\t\t\tadjust_curb_float_height (   );\r\n\tvoid\t\t\t\t\t\t\taccount_for_movable_contact (   );\r\n\tvoid\t\t\t\t\t\t\tjump (   );\r\n\tvoid\t\t\t\t\t\t\tadjust_jump_for_ceiling_obstructions (   );\r\n\tvoid\t\t\t\t\t\t\tgo_in_air_state (   );\r\n\tvoid\t\t\t\t\t\t\tcontrol_horizontal_vel (   );\r\n\tvoid\t\t\t\t\t\t\tadjust_vertical_vel_for_ceiling (   );\r\n\tvoid\t\t\t\t\t\t\tcheck_for_landing ( const Mth::Vector& previous_pos, const Mth::Vector& final_pos );\r\n\tvoid\t\t\t\t\t\t\tmaybe_wallplant (   );\r\n\tvoid\t\t\t\t\t\t\tuber_frig (   );\r\n\tvoid\t\t\t\t\t\t\tlerp_upright (   );\r\n\tvoid\t\t\t\t\t\t\ttransition_lerp_upright (   );\r\n\tbool\t\t\t\t\t\t\tcheck_for_wall_push (   );\r\n\tvoid\t\t\t\t\t\t\tleave_movable_contact_for_air ( Mth::Vector& horizontal_vel, float& vertical_vel );\r\n\tbool\t\t\t\t\t\t\tmaybe_hop_to_hang (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_drop_to_hang (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_grab_to_hang ( Mth::Vector start_pos, Mth::Vector end_pos );\r\n\tbool\t\t\t\t\t\t\tinvestigate_hang_rail_vicinity ( CFeeler& feeler, const Mth::Vector& preliminary_hang_point, SHangRailData& rail_data );\r\n\tbool\t\t\t\t\t\t\tvertical_hang_obstruction_check ( CFeeler& feeler, SHangRailData& rail_data, const Mth::Vector& check_offset_direction );\r\n\tvoid\t\t\t\t\t\t\tgo_hop_state (   );\r\n\tvoid\t\t\t\t\t\t\tgo_hang_state (   );\r\n\tvoid\t\t\t\t\t\t\thang_movement ( float movement );\r\n\tbool\t\t\t\t\t\t\tcheck_environment_for_hang_movement_collisions ( const Mth::Vector& facing, float along_rail_factor, const Mth::Vector& pos, bool left, const Mth::Vector& perp_facing, Mth::Vector rail, const CRailNode* p_rail_start, const CRailNode* p_rail_end );\r\n\tvoid\t\t\t\t\t\t\tmove_onto_neighboring_hang_rail ( float movement, bool descending, const Mth::Vector& old_rail );\r\n\tbool\t\t\t\t\t\t\tfind_next_rail ( float& along_rail_factor, const CRailNode* p_current_start, const CRailNode* p_current_end, const CRailNode*& p_new_start, const CRailNode*& p_new_end );\r\n\tvoid\t\t\t\t\t\t\tset_pos_from_hang_rail_state (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_pull_up_from_hang ( Mth::Vector& proposed_stand_pos );\r\n\tbool\t\t\t\t\t\t\tmaybe_jump_low_barrier (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_in_air_acid_drop (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_jump_to_acid_drop (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_climb_up_ladder ( bool user_requested = false );\r\n\tbool\t\t\t\t\t\t\tmaybe_climb_down_ladder (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_grab_to_ladder ( const Mth::Vector& start_pos, const Mth::Vector& end_pos );\r\n\tvoid\t\t\t\t\t\t\tgo_ladder_state (   );\r\n\tvoid\t\t\t\t\t\t\tladder_movement (   );\r\n\tvoid\t\t\t\t\t\t\toff_ladder_bottom (   );\r\n\tvoid\t\t\t\t\t\t\toff_ladder_top (   );\r\n\tvoid\t\t\t\t\t\t\tcalculate_anim_wait_facing_drift_parameters ( const Mth::Vector& goal_facing, float rotate_factor = 1.0f );\r\n    void                            go_anim_wait_state (   );\r\n    void                            anim_wait_complete (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_stick_to_rail (   );\r\n\tvoid\t\t\t\t\t\t\tsetup_collision_cache (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_critical_point_offset (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_display_offset (   );\r\n\tvoid\t\t\t\t\t\t\tadjust_pos_for_false_wall (   );\r\n\tvoid\t\t\t\t\t\t\textract_state_from_object (   );\r\n\tvoid\t\t\t\t\t\t\tcopy_state_into_object (   );\r\n\tvoid\t\t\t\t\t\t\tget_controller_input (   );\r\n\tfloat\t\t\t\t\t\t\tcalculate_desired_speed (   );\r\n\tMth::Vector\t\t\t\t\t\tcalculate_feeler_offset_direction ( int contact );\r\n\tbool\t\t\t\t\t\t\tdetermine_stand_pos ( const Mth::Vector& proposed_stand_pos, Mth::Vector& stand_pos, CFeeler& feeler );\r\n\tfloat\t\t\t\t\t\t\tget_run_speed (   );\r\n\tfloat\t\t\t\t\t\t\tget_gravity (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_run_speed (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_run_speed_factor (   );\r\n\tvoid\t\t\t\t\t\t\tsmooth_anim_speed ( uint32 previous_frame_event );\r\n\tvoid\t\t\t\t\t\t\tset_camera_overrides (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_anim_speeds (   );\r\n\tfloat\t\t\t\t\t\t\tget_hang_display_offset (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tdrop_to_hang_complete (   );\r\n\tvoid\t\t\t\t\t\t\tpull_up_from_hang_to_ground_complete (   );\r\n\tvoid\t\t\t\t\t\t\tpull_up_from_hang_to_air_complete (   );\r\n\tfloat\t\t\t\t\t\t\tget_hang_critical_point_vert_offset (   );\r\n\tvoid\t\t\t\t\t\t\tmove_to_ladder_bottom_complete (   );\r\n\tvoid\t\t\t\t\t\t\tmove_to_ladder_top_complete (   );\r\n\tvoid\t\t\t\t\t\t\toff_ladder_bottom_complete (   );\r\n\tvoid\t\t\t\t\t\t\toff_ladder_top_to_ground_complete (   );\r\n\tvoid\t\t\t\t\t\t\toff_ladder_top_to_air_complete (   );\r\n\t\r\n\tstatic float\t\t\t\t\ts_get_param ( uint32 checksum );\r\n\t\r\npublic:\r\n\tbool\t\t\t\t\t\t\tIsRunning (   );\r\n\tbool\t\t\t\t\t\t\tUseDPadCamera (   );\r\n\tvoid\t\t\t\t\t\t\tSetForwardControlLock ( bool forward_control_lock );\r\n\tvoid\t\t\t\t\t\t\tSetAssociatedCamera ( CCompositeObject* camera_obj );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tCollideWithOtherSkaterLost ( CCompositeObject* p_other_skater );\r\n    \r\n\tMth::Vector\t\t\t\t\t\tGetCameraCollisionTargetOffset (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tReadyWalkState ( bool to_ground_state );\r\n\tvoid\t\t\t\t\t\t\tCleanUpWalkState (   );\r\n\tconst SRailData*\t\t\t\tGetRailData (   );\r\n\tconst SAcidDropData*\t\t\tGetAcidDropData (   );\r\n    \r\n\tbool\t\t\t\t\t\t\tFilterHangRail ( const Mth::Vector& pos_a, const Mth::Vector& pos_b, const Mth::Vector& preliminary_hang_point, const Mth::Vector& grab_from_point, float along_rail_factor, SHangRailData& rail_data, bool drop_to_hang );\r\n\tbool\t\t\t\t\t\t\tFilterLadderUpRail ( const Mth::Vector& bottom_pos, const Mth::Vector& top_pos, const Mth::Matrix& orientation, SLadderRailData& rail_data );\r\n\tbool\t\t\t\t\t\t\tFilterLadderDownRail ( const Mth::Vector& bottom_pos, const Mth::Vector& top_pos, const Mth::Matrix& orientation, SLadderRailData& rail_data );\r\n\tbool\t\t\t\t\t\t\tFilterLadderAirGrabRail ( const Mth::Vector& bottom_pos, const Mth::Vector& top_pos, const Mth::Matrix& orientation, const Mth::Vector& preliminary_climb_point, float along_rail_factor, SLadderRailData& rail_data );\r\n\t\r\nprivate:\r\n\tEStateType\t\t\t\t\t\tm_state;\r\n\t\r\n\t// Time stamp of when our state last changed.\r\n\tTmr::Time\t\t\t\t\t\tm_state_timestamp;\r\n\t\r\n\t// State we changed from when m_state_timestamp was last set.\r\n\tEStateType\t\t\t\t\t\tm_previous_state;\r\n\t\r\n\t// Extracted from the object at frame start and back into the object at frame end.\r\n\tMth::Vector\t\t\t\t\t\tm_pos;\r\n\tMth::Vector\t\t\t\t\t\tm_horizontal_vel;\r\n\tfloat\t\t\t\t\t\t\tm_vertical_vel;\r\n\tMth::Vector\t\t\t\t\t\tm_facing;\r\n\tMth::Vector\t\t\t\t\t\tm_upward;\r\n\t\r\n\t// Cache our position at the frame's start\r\n\tMth::Vector\t\t\t\t\t\tm_frame_start_pos;\r\n\t\r\n\t// Script event reporting our current state.  Set during each frame update and sent at the end of the update.\r\n\tuint32\t\t\t\t\t\t\tm_frame_event;\r\n\t\r\n\t// Last frame's frame event.\r\n\tuint32\t\t\t\t\t\t\tm_last_frame_event;\r\n\t\r\n\t// Current frame's frame length.\r\n\tfloat\t\t\t\t\t\t\tm_frame_length;\r\n\t\r\n\t// Current frame's control input.\r\n\tMth::Vector\t\t\t\t\t\tm_control_direction;\r\n\tfloat\t\t\t\t\t\t\tm_control_magnitude;\r\n\tbool\t\t\t\t\t\t\tm_control_pegged;\r\n\tbool\t\t\t\t\t\t\tm_analog_control;\r\n\t\r\n\t// The grab button is the same as the transition button, and is thus ignored after a transition until it is released\r\n\tbool\t\t\t\t\t\t\tm_ignore_grab_button;\r\n\t\r\n\t// After transitioning from skating to walking in air, you are not allowed to acid drop until you first switch out of the air state.\r\n\tbool\t\t\t\t\t\t\tm_disallow_acid_drops;\r\n\t\r\n\t// The offset from the skater's true origin at which to display the skater.  Used to get CAS scaled skaters looking correct.\r\n\tfloat\t\t\t\t\t\t\tm_display_offset;\r\n\t\r\n\tstruct SContact\r\n\t{\r\n\t\t// If this contact is in collision with the environment.\r\n\t\tbool\t\t\t\t\t\tin_collision;\r\n\t\t\r\n\t\t// The horizontal normal of the collided geometry.\r\n\t\tMth::Vector\t\t\t\t\tnormal;\r\n\t\t\r\n\t\t// If the collision in this direction is determined to be low enough to jump.\r\n\t\tbool\t\t\t\t\t\tjumpable;\r\n\t\t\r\n\t\t// Movement of the object we're in contact with (not accounting for its rotation) along its horizontal normal.\r\n\t\tfloat\t\t\t\t\t\tmovement;\r\n\t\t\r\n\t\t// Must store the full feeler in order to trip triggers and get movable contact objects\r\n\t\tCFeeler\t\t\t\t\t\tfeeler;\r\n\t\t\r\n\t// The walker looks around him in vNUM_FEELERS directions and stores the results here.  The final contact is felt for along the movement of\r\n\t// the origin, and is only used while in the air.\r\n\t} mp_contacts [ vNUM_FEELERS + 1 ];\r\n\t\r\n\t// Type of animation speed scaling to do.\r\n\tEAnimScaleSpeed\t\t\t\t\tm_anim_scale_speed;\r\n\t\r\n\t// Horizontal speed for the purposes of animation speed scaling.\r\n\tfloat\t\t\t\t\t\t\tm_anim_effective_speed;\r\n\tfloat\t\t\t\t\t\t\tm_last_frame_anim_effective_speed;\r\n\t\r\n\t#ifdef SCRIPT_WALK_DRAG\r\n\t// Factor multiplied by all velocities.  Set by script.\r\n\tfloat\t\t\t\t\t\t\tm_script_drag_factor;\r\n\t#endif\r\n\t\r\n\t// Used to lock control in the forward direction (during a camera flush request)\r\n\tbool\t\t\t\t\t\t\tm_forward_control_lock;\r\n\t\r\n\t// When on ground, the walker is often floated above the ground in an attempt to smooth out stair/curb climbs.\r\n\tfloat\t\t\t\t\t\t\tm_curb_float_height;\r\n\t\r\n\t// If m_curb_float_height was adjusted this frame.  If not, we lerp it to zero.\r\n\tbool\t\t\t\t\t\t\tm_curb_float_height_adjusted;\r\n\t\r\n\t// The critical point is a position relative to the skater which MUST ALWAYS STAY ON THE CORRECT SIDE OF COLLIDABLE GEO.  Normally, this is simply the\r\n\t// origin.  However, sometimes this must be adjusted (during hanging).  Once hanging is over, the critical point is pushed back to the origin.\r\n\tMth::Vector\t\t\t\t\t\tm_critical_point_offset;\r\n\t\r\n\t// Counts down while we're slerping upright after a transition from skating\r\n\tfloat m_rotate_upright_timer;\r\n\t\r\n\t// Angle over and axis around which to slerp to upright\r\n\tfloat m_rotate_upright_angle;\r\n\tMth::Vector m_rotate_upright_axis;\r\n\t\r\n\t// The matrix's [Z][Y] component last time facing was extracted from the matrix.  Stored so it can be restored when rebuilding the matrix, thus\r\n\t// preventing unwanted rotations.\r\n\tfloat m_frame_initial_facing_Y;\r\n\t\r\n\tstruct SSpecialTransitionData\r\n\t{\r\n\t\t// The type of transition causing the switch to skating.\r\n\t\tESpecialTransitionType\t\ttype;\r\n\t\t\r\n\t\t// The state data for that transition.\r\n\t\tSRailData\t\t\t\t\trail_data;\r\n\t\tSAcidDropData\t\t\t\tacid_drop_data;\r\n\t\t\r\n\t// When the walker transitions to skating in some manner which requires additional state information, this structure holds that information before it\r\n\t// is passed off to the skate physics.\r\n\t}\t\t\t\t\t\t\t\tm_special_transition_data;\r\n\t\r\n\t// The collision cache used.\r\n\tNx::CCollCache*\t\t\t\t\tmp_collision_cache;\r\n\t\r\n\t// Associated camera.\r\n\tCCompositeObject*\t\t\t\tmp_camera;\r\n\tCWalkCameraComponent*\t\t\tmp_camera_component;\r\n\t\r\n    // If associated with a rail, this is the rail node and rail manager.\r\n    const CRailNode*              \tmp_rail_start;\r\n    const CRailNode*              \tmp_rail_end;\r\n    CRailManager*                   mp_rail_manager;\r\n\t\r\n\t// Peer components.\r\n\tCInputComponent*\t\t\t\tmp_input_component;\r\n\tCAnimationComponent*\t\t\tmp_animation_component;\r\n\tCModelComponent*\t\t\t\tmp_model_component;\r\n\tCTriggerComponent*\t\t\t\tmp_trigger_component;\r\n\tCSkaterPhysicsControlComponent*\tmp_physics_control_component;\r\n\tCMovableContactComponent*\t\tmp_movable_contact_component;\r\n\tCSkaterStateComponent*\t\t\tmp_state_component;\r\n\tCSkaterCorePhysicsComponent*\tmp_core_physics_component;\r\n    \r\n\t/////////////////////////////////\r\n\t// WALKING_GROUND state variables\r\n\t\r\n\t// Normal of the ground on which we are standing.  Only meaningful when on the ground.  Set the previous frame.\r\n\tMth::Vector\t\t\t\t\t\tm_ground_normal;\r\n\t\r\n\t// Certain things such as rotation rate and camera lerp are increased when this is set.\r\n\tbool\t\t\t\t\t\t\tm_run_toggle;\r\n\t\r\n\tstruct SWallPushTest\r\n\t{\r\n\t\t// Whether we currently testing.\r\n\t\tbool\t\t\t\t\t\tactive;\r\n\t\t\r\n\t\t// Time at which this test began.\r\n\t\tTmr::Time\t\t\t\t\ttest_start_time;\r\n\t\t\r\n\t// Data used to detect when a player is pushing into a wall in order to climb it.\r\n\t}\t\t\t\t\t\t\t\tm_wall_push_test;\r\n\t\r\n\t// When doing anim speed scaling when running, this is set to the run speed which corresponds to the current animation playing at standard speed.\r\n\tfloat\t\t\t\t\t\t\tm_anim_standard_speed;\r\n\t\r\n\t// A copy of the latest feeler which contacted the groud under us.\r\n\tCFeeler\t\t\t\t\t\t\tm_last_ground_feeler;\r\n\tbool\t\t\t\t\t\t\tm_last_ground_feeler_valid;\r\n\t\r\n\t// lerp factor between standard run speed and combo run speed\r\n\tfloat\t\t\t\t\t\t\tm_run_speed_factor;\r\n\t\r\n\t// If true, no transitional period of reduced deceleration is used from skating.\r\n\t// bool\t\t\t\t\t\t\tm_cancel_transition_momentum;\r\n\t\r\n\t// Set to true when the walker's speeds is significantly reduced due to interactions with walls.  Causes the rotation rate of the skater to be dropped\r\n\t// to walking levels next frame.  A beter solution would be to reduce rotation rate THIS frame.\r\n\tbool\t\t\t\t\t\t\tm_drop_rotation_rate;\r\n\t\r\n\t// Latest duration over which the controller has been continuously pegged.  Only used on the ground and reset to a large value whenever you enter ground.\r\n\tfloat\t\t\t\t\t\t\tm_control_pegged_duration;\r\n\t\r\n\t// True if the controller was pegged last frame.  Only updated while on the ground.\r\n\tbool\t\t\t\t\t\t\tm_last_frame_controller_pegged;\r\n\t\r\n\t/////////////////////////////////\r\n\t// WALKING_AIR state variables\r\n\t\r\n\t// The forward horizontal direction of the jump which, when coming out of skating or because of in-air velocity control, diverges from the direction of velocity\r\n\tMth::Vector\t\t\t\t\t\tm_primary_air_direction;\r\n\t\r\n\t// This term of our horizontal velocity is due to leaping from a movable contact, and is not adjustable via in-air control.\r\n\tMth::Vector\t\t\t\t\t\tm_uncontrollable_air_horizontal_vel;\r\n\t\r\n\t// When non-zero, it counts down and suppresses in air velocity control.\r\n\tfloat\t\t\t\t\t\t\tm_in_air_control_suppression_timer;\r\n\t\r\n\t// Extra drift velocity used while in the air.\r\n\tMth::Vector\t\t\t\t\t\tm_in_air_drift_vel;\r\n\t\r\n\t// Extra drift is turned off after the skater reaches this height.\r\n\tfloat\t\t\t\t\t\t\tm_in_air_drift_stop_height;\r\n\t\r\n\tstruct SFalseWall\r\n\t{\r\n\t\t// This tracks if a false wall is active.\r\n\t\tbool\t\t\t\t\t\tactive;\r\n\t\t\r\n\t\t// The false wall is defined by a normal.\r\n\t\tMth::Vector\t\t\t\t\tnormal;\r\n\t\t\r\n\t\t// And a scalar.\r\n\t\tfloat\t\t\t\t\t\tdistance;\r\n\t\t\r\n\t\t// The false wall is automatically turned off when this height is exceeded.\r\n\t\tfloat\t\t\t\t\t\tcancel_height;\r\n\t\t\r\n\t// A false wall is sometimes set up while in the air to prevent movement in a certain direction.\r\n\t}\t\t\t\t\t\t\t\tm_false_wall;\r\n\t\r\n\t/////////////////////////////////\r\n\t// WALKING_HANG state variables\r\n\t\r\n\t// Measures our position along the current rail as a parameter running from 0.0 to 1.0.\r\n\tfloat\t\t\t\t\t\t\tm_along_rail_factor;\r\n\t\r\n\t// Measures the hang position offset from the actual rail we are hanging from.\r\n\tfloat\t\t\t\t\t\t\tm_vertical_hang_offset;\r\n\tfloat\t\t\t\t\t\t\tm_horizontal_hang_offset;\r\n\t\r\n\t// Checksum describing the type of initial hang animation to play.\r\n\tuint32\t\t\t\t\t\t\tm_initial_hang_animation;\r\n\t\r\n\t// Speed the skater is shimmying at\r\n\tfloat\t\t\t\t\t\t\tm_hang_move_vel;\r\n    \r\n\t/////////////////////////////////\r\n\t// WALKING_HOP state variables\r\n\t\r\n    // The position we will have at the end of the hop.\r\n    // Mth::Vector                     m_goal_hop_pos;\r\n    \r\n    // The facing we will have at the end of the hop.\r\n    // Mth::Vector                     m_goal_hop_facing;\r\n\t\r\n\t// Hang state variable.  Set at hop start.\r\n\t// float\t\t\t\t\t\tm_along_rail_factor;\r\n\t\r\n\t// Hang state variable.  Set at hop start.\r\n\t// uint32\t\t\t\t\t\tm_initial_hang_animation;\r\n    \r\n\t/////////////////////////////////\r\n\t// WALKING_LADDER state variables\r\n\t\r\n\t// Shared with hang state.\r\n\t// float\t\t\t\t\t\tm_along_rail_factor;\r\n\t\r\n\t// Only ladder animation speed changes are sent to the server are updated in net games.  This holds the last animimation speed sent.\r\n\tfloat\t\t\t\t\t\t\tm_last_ladder_anim_speed;\r\n    \r\n\t/////////////////////////////////\r\n\t// WALKING_ANIMWAIT state variables\r\n\t\r\n\t// Position at the start of the animation wait.\r\n\tMth::Vector\t\t\t\t\t\tm_anim_wait_initial_pos;\r\n\t\r\n\t// Facing at the start of the aniamtion wait.\r\n\tMth::Vector\t\t\t\t\t\tm_anim_wait_initial_facing;\r\n\t\r\n    // Amount to move the object at the end of the animation wait.\r\n    Mth::Vector                     m_anim_wait_goal_pos;\r\n\t\r\n\t// Goal display offset of the animation wait.\r\n\tfloat\t\t\t\t\t\t\tm_drift_initial_display_offset;\r\n\tfloat\t\t\t\t\t\t\tm_drift_goal_display_offset;\r\n\t\r\n\t// Goal facing of the position drift.\r\n\tMth::Vector\t\t\t\t\t\tm_drift_goal_facing;\r\n\t\r\n\t// Factor of animation in which to do the rotation in.\r\n\tfloat\t\t\t\t\t\t\tm_drift_goal_rotate_factor;\r\n\t\r\n\t// The angle over which the facing must drift.\r\n\tfloat\t\t\t\t\t\t\tm_drift_angle;\r\n    \r\n\t// Accumulates position offset due to a movable contact during an animation wait.\r\n\tMth::Vector\t\t\t\t\t\tm_offset_due_to_movable_contact;\r\n\t\r\n\t// The behavior of the camera during the animation wait.\r\n\tenum EAnimWaitCameraModeType\t\t\t\r\n\t{\r\n\t\tAWC_CURRENT,\r\n\t\tAWC_GOAL\r\n\t}\t\t\t\t\t\t\t\tm_anim_wait_camera_mode;\r\n\t\r\n\t// Callback function to call upon completion of the animation wait.\r\n\tAnimWaitCallbackPtr\t\t\t\tmp_anim_wait_complete_callback;\r\n\t\r\n\t// WALKING_GROUND state variable sometimes set at start of animation wait based on the animation end ground situation\r\n\t// Mth::Vector\t\t\t\t\tm_ground_normal;\r\n\t// CFeeler\t\t\t\t\t\tm_last_ground_feeler;\r\n\t// bool\t\t\t\t\t\t\tm_last_ground_feeler_valid;\r\n\t\r\n\t// WALKING_AIR state variable partially setup at the start of an animation wait\r\n\t// struct SFalseWall\t\t\tm_false_wall;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float CWalkComponent::s_get_param ( uint32 checksum )\r\n{\r\n\tScript::CStruct* p_walk_params = Script::GetStructure(CRCD(0x6775e538, \"walk_parameters\"));\r\n\tDbg_Assert(p_walk_params);\r\n\t\r\n\tfloat param;\r\n\tp_walk_params->GetFloat(checksum, &param, Script::ASSERT);\r\n\treturn param;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float CWalkComponent::get_run_speed (   )\r\n{\r\n\treturn Mth::Lerp(s_get_param(CRCD(0xcc461b87, \"run_speed\")), s_get_param(CRCD(0x7213ef07, \"combo_run_speed\")), m_run_speed_factor);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CWalkComponent::IsRunning (   )\r\n{\r\n\treturn m_run_toggle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CWalkComponent::SetForwardControlLock ( bool forward_control_lock )\r\n{\r\n\tm_forward_control_lock = forward_control_lock;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const SRailData* CWalkComponent::GetRailData (   )\r\n{\r\n\treturn m_special_transition_data.type == RAIL_TRANSITION ? &m_special_transition_data.rail_data : NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const SAcidDropData* CWalkComponent::GetAcidDropData (   )\r\n{\r\n\treturn m_special_transition_data.type == ACID_DROP_TRANSITION ? &m_special_transition_data.acid_drop_data : NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CWalkComponent::UseDPadCamera (   )\r\n{\r\n\t\r\n\treturn mp_input_component->GetControlPad().m_leftX == 0.0f && mp_input_component->GetControlPad().m_leftY == 0.0f && m_control_pegged;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Mth::Vector CWalkComponent::GetCameraCollisionTargetOffset (   )\r\n{\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase WALKING_HANG:\r\n\t\tcase WALKING_LADDER:\r\n\t\tcase WALKING_ANIMWAIT:\r\n\t\t\treturn -18.0f * m_facing;\r\n\t\t\r\n\t\tcase WALKING_AIR:\r\n\t\t\tif ((m_previous_state == WALKING_HANG || m_previous_state ==WALKING_LADDER || m_previous_state ==WALKING_LADDER)\r\n\t\t\t\t&& Tmr::ElapsedTime(m_state_timestamp) < 150)\r\n\t\t\t{\r\n\t\t\t\treturn -18.0f * m_facing;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn Mth::Vector(0.0f, 0.0f, 0.0f);\r\n\t\t\t}\r\n\t\t\t\r\n\t\tcase WALKING_GROUND:\r\n\t\tdefault:\r\n\t\t\treturn Mth::Vector(0.0f, 0.0f, 0.0f);\r\n\t}\r\n}\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gel/Components/WalkHangUtil.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       WalkHangUtil.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  4/2/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/walkcomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/walkcameracomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/triggercomponent.h>\r\n#include <gel/components/movablecontactcomponent.h>\r\n#include <gel/components/railmanagercomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/collision/collcache.h>\r\n\r\n#include <sk/objects/rail.h>\r\n#include <sk/engine/feeler.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n\r\n#include <gfx/nxmodel.h>\r\n\r\n/*\r\n * Contains those CWalkComponent member functions which are concerned with hanging.\r\n */\r\n\r\nnamespace Obj\r\n{\r\n     \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\nbool CWalkComponent::maybe_hop_to_hang (   )\r\n{\r\n\tSHangRailData rail_data;\r\n\t\r\n\tMth::Vector search_start_pos = m_pos;\r\n\tsearch_start_pos[Y] += s_get_param(CRCD(0x2c942693, \"lowest_hang_height\"));\r\n\t\r\n\t// clean vectors; facing is a directional vector\r\n\tsearch_start_pos[W] = 1.0f;\r\n\tm_facing[W] = 0.0f;\r\n\t\r\n\tbool rail_found = false;\r\n\t\r\n\tfloat hop_to_hang_reach = s_get_param(CRCD(0x8b785f26, \"max_hop_to_hang_height\")) - s_get_param(CRCD(0x2c942693, \"lowest_hang_height\"));\r\n\tfloat max_hop_to_hang_forward_reach = s_get_param(CRCD(0x3b4ca389, \"max_hop_to_hang_forward_reach\"));\r\n\tfloat max_hop_to_hang_backward_reach = s_get_param(CRCD(0xae806bee, \"max_hop_to_hang_backward_reach\"));\r\n\t\r\n\t// check level for appropriate rails\r\n\tif (rail_found = Mdl::Skate::Instance()->GetRailManager()->CheckForHopToHangRail(\r\n\t\tsearch_start_pos,\r\n\t\thop_to_hang_reach,\r\n\t\tm_facing,\r\n\t\tmax_hop_to_hang_forward_reach,\r\n\t\tmax_hop_to_hang_backward_reach,\r\n\t\tthis,\r\n\t\trail_data,\r\n\t\t&mp_rail_node\r\n\t))\r\n\t{\r\n\t\tmp_rail_manager = Mdl::Skate::Instance()->GetRailManager();\r\n\t\tmp_movable_contact_component->LoseAnyContact();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfloat max_hop_to_movable_hang_vel_sqr = s_get_param(CRCD(0x511cb4, \"max_hop_to_movable_hang_vel\"));\r\n\t\tmax_hop_to_movable_hang_vel_sqr *= max_hop_to_movable_hang_vel_sqr;\r\n\t\t\r\n\t\t// check moving objects for appropriate rails\r\n\t\tfor (CRailManagerComponent* p_rail_manager_component = static_cast< CRailManagerComponent* >(CCompositeObjectManager::Instance()->GetFirstComponentByType(CRC_RAILMANAGER));\r\n\t\t\tp_rail_manager_component && !rail_found;\r\n\t\t\tp_rail_manager_component = static_cast< CRailManagerComponent* >(p_rail_manager_component->GetNextSameType()))\r\n\t\t{\r\n\t\t\t// only hop to moving hangs below a threshold velocity\r\n\t\t\tif (p_rail_manager_component->GetObject()->GetVel().LengthSqr() > max_hop_to_movable_hang_vel_sqr) continue;\r\n\t\t\t\r\n\t\t\tMth::Matrix obj_matrix_inv = p_rail_manager_component->UpdateRailManager();\r\n\t\t\tobj_matrix_inv.Invert();\r\n\r\n\t\t\t// transform into the frame of the moving object\r\n\t\t\tMth::Vector obj_frame_search_start_pos = obj_matrix_inv.Transform(search_start_pos);\r\n\t\t\tMth::Vector obj_frame_facing = obj_matrix_inv.Transform(m_facing);\r\n\r\n\t\t\tif (rail_found = p_rail_manager_component->GetRailManager()->CheckForHopToHangRail(\r\n\t\t\t\tobj_frame_search_start_pos,\r\n\t\t\t\thop_to_hang_reach,\r\n\t\t\t\tobj_frame_facing,\r\n\t\t\t\tmax_hop_to_hang_forward_reach,\r\n\t\t\t\tmax_hop_to_hang_backward_reach,\r\n\t\t\t\tthis,\r\n\t\t\t\trail_data,\r\n\t\t\t\t&mp_rail_node\r\n\t\t\t))\r\n\t\t\t{\r\n\t\t\t\tmp_rail_manager = p_rail_manager_component->GetRailManager();\r\n\t\t\t\tmp_movable_contact_component->ObtainContact(p_rail_manager_component->GetObject());\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (!rail_found) return false;\r\n\t\r\n\t// we've found a rail to hop up to\r\n\tm_goal_hop_pos = rail_data.hang_point;\r\n\tm_goal_hop_facing = rail_data.hang_facing;\r\n\tm_along_rail_factor = rail_data.along_rail_factor;\r\n\tm_vertical_hang_offset = rail_data.vertical_hang_offset;\r\n\tm_horizontal_hang_offset = rail_data.horizontal_hang_offset;\r\n\tm_initial_hang_animation = rail_data.initial_animation;\r\n\t\r\n\t// calculate the vertical velocity required to jump to the hang point\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (m_pos[Y] >= m_goal_hop_pos[Y])\r\n\t{\r\n\t\tDUMPV(m_pos);\r\n\t\tDUMPV(m_goal_hop_pos);\r\n\t}\r\n\tDbg_Assert(m_pos[Y] < m_goal_hop_pos[Y]);\r\n\t#endif\r\n\t\r\n\tfloat hop_target_vert_vel = s_get_param(CRCD(0x7aa618cc, \"hop_target_vert_vel\"));\r\n\tfloat gravity = s_get_param(CRCD(0xa5e2da58, \"gravity\"));\r\n\t\r\n\t// ready state for the hop to hang\r\n\t\r\n\t// calculate the required hop velocity\r\n\tm_vertical_vel = sqrtf(Mth::Sqr(hop_target_vert_vel) + 2.0f * gravity * (m_goal_hop_pos[Y] - m_pos[Y]));\r\n\t\r\n\t// calculate the required hop duration\r\n\tfloat duration = (m_vertical_vel + hop_target_vert_vel) / gravity;\r\n\t\r\n\t// not neccesarly exactly in the check_direction of the facing\r\n\tm_horizontal_vel = (1.0f / duration) * (m_goal_hop_pos - m_pos);\r\n\t\r\n\t// trip the ground's jump triggers\r\n\tif (m_last_ground_feeler_valid)\r\n\t{\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_JUMP_OFF, m_last_ground_feeler);\r\n\t\tif (should_bail_from_frame()) return true;\r\n\t}\r\n\t\r\n\tset_state(WALKING_HOP);\r\n    \r\n\tm_frame_event = CRCD(0xf41aba21, \"Hop\");\r\n\t\r\n\treturn true;\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::maybe_drop_to_hang (   )\r\n{\r\n\t// check to see if we're in a bail\r\n\tif (mp_core_physics_component->GetFlag(IS_BAILING)) return false;\r\n\t\r\n\t// only drop to hang when moving slowly\r\n\tif (m_horizontal_vel.LengthSqr() > Mth::Sqr(s_get_param(CRCD(0x1d1e6af, \"drop_to_hang_speed_factor\")) * get_run_speed())) return false;\r\n\t\r\n\t// clean vector\r\n\tm_frame_start_pos[W] = 1.0f;\r\n\tm_pos[W] = 1.0f;\r\n\t\r\n\tSHangRailData rail_data;\r\n\t\r\n\tbool rail_found = false;\r\n\t\r\n\t// check level for appropriate rails\r\n\tmp_rail_manager = Mdl::Skate::Instance()->GetRailManager();\r\n\tif (rail_found = mp_rail_manager->CheckForHangRail(\r\n\t\tm_frame_start_pos,\r\n\t\tm_pos,\r\n\t\t-m_facing,\r\n\t\tthis,\r\n\t\trail_data,\r\n\t\tScript::GetFloat(CRCD(0xa8276303, \"Drop_To_Climb_Max_Snap\"))\r\n\t))\r\n\t{\r\n\t\tmp_movable_contact_component->LoseAnyContact();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// check moving objects for appropriate rails\r\n\t\tfor (CRailManagerComponent* p_rail_manager_component = static_cast< CRailManagerComponent* >(CCompositeObjectManager::Instance()->GetFirstComponentByType(CRC_RAILMANAGER));\r\n\t\t\tp_rail_manager_component && !rail_found;\r\n\t\t\tp_rail_manager_component = static_cast< CRailManagerComponent* >(p_rail_manager_component->GetNextSameType()))\r\n\t\t{\r\n\t\t\tMth::Matrix obj_matrix_inv = p_rail_manager_component->UpdateRailManager();\r\n\t\t\tobj_matrix_inv.Invert();\r\n\r\n\t\t\t// transform into the frame of the moving object\r\n\t\t\tMth::Vector obj_frame_start_pos = obj_matrix_inv.Transform(m_frame_start_pos);\r\n\t\t\tMth::Vector obj_pos = obj_matrix_inv.Transform(m_pos);\r\n\r\n\t\t\tmp_rail_manager = p_rail_manager_component->GetRailManager();\r\n\t\t\tif (rail_found = mp_rail_manager->CheckForHangRail(\r\n\t\t\t\tobj_frame_start_pos,\r\n\t\t\t\tobj_pos,\r\n\t\t\t\t-m_facing,\r\n\t\t\t\tthis,\r\n\t\t\t\trail_data,\r\n\t\t\t\tScript::GetFloat(CRCD(0xa8276303, \"Drop_To_Climb_Max_Snap\"))\r\n\t\t\t))\r\n\t\t\t{\r\n\t\t\t\tmp_movable_contact_component->ObtainContact(p_rail_manager_component->GetObject());\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (!rail_found) return false;\r\n\t\r\n\t// we've found a rail to drop down to\r\n\t\r\n\tmp_rail_start = rail_data.p_rail_node;\r\n\tmp_rail_end = mp_rail_start->GetNextLink();\r\n\tDbg_Assert(mp_rail_end);\r\n\t\r\n\t// zero velocities\t\r\n\tm_vertical_vel = 0.0f;\r\n\tm_horizontal_vel.Set();\r\n\t\r\n\tm_along_rail_factor = rail_data.along_rail_factor;\r\n\tm_vertical_hang_offset = rail_data.vertical_hang_offset;\r\n\tm_horizontal_hang_offset = rail_data.horizontal_hang_offset;\r\n    \r\n    // setup an anim wait state\r\n\t\r\n\tm_anim_wait_initial_pos = m_pos;\r\n\tm_anim_wait_goal_pos = rail_data.hang_point;\r\n\t\r\n    mp_anim_wait_complete_callback = &Obj::CWalkComponent::drop_to_hang_complete;\r\n\t\r\n\tcalculate_anim_wait_facing_drift_parameters(rail_data.hang_facing, s_get_param(CRCD(0xfdc8aec0, \"drop_to_hang_rotate_factor\")));\r\n\t\r\n\tm_anim_wait_camera_mode = AWC_GOAL;\r\n\t\r\n\tm_critical_point_offset = s_get_param(CRCD(0xc3263e6e, \"hang_critical_point_horiz_offset\")) * rail_data.hang_facing;\r\n\t\r\n\t// setup the false wall incase the player jumps out of the animation wait\r\n\tm_false_wall.normal = rail_data.hang_facing;\r\n\tm_false_wall.cancel_height = m_pos[Y];\r\n\t\r\n\tm_drift_initial_display_offset = m_display_offset;\r\n\tm_drift_goal_display_offset = get_hang_display_offset();\r\n\r\n\tset_state(WALKING_ANIMWAIT);\r\n\r\n\tm_frame_event = CRCD(0xeb71d98e, \"DropToHang\");\r\n    \r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::drop_to_hang_complete (   )\r\n{\r\n\tm_critical_point_offset = s_get_param(CRCD(0xc3263e6e, \"hang_critical_point_horiz_offset\")) * m_facing;\r\n\tm_critical_point_offset[Y] = get_hang_critical_point_vert_offset();\r\n\t\r\n\tset_state(WALKING_HANG);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::maybe_grab_to_hang ( Mth::Vector start_pos, Mth::Vector end_pos )\r\n{\r\n\t// only grab to hang when moving down\r\n\tif (m_vertical_vel > 50.0f) return false;\r\n\t\r\n\tstart_pos[Y] += s_get_param(CRCD(0xa8c13e74, \"hang_vert_origin_offset\"));\r\n\tend_pos[Y] += s_get_param(CRCD(0xa8c13e74, \"hang_vert_origin_offset\"));\r\n\t\r\n\t// clean vectors\r\n\tstart_pos[W] = 1.0f;\r\n\tend_pos[W] = 1.0f;\r\n\t\r\n\tSHangRailData rail_data;\r\n\t\r\n\tbool rail_found = false;\r\n\t\r\n\t// check level for appropriate rails\r\n\tmp_rail_manager = Mdl::Skate::Instance()->GetRailManager();\r\n\tif (rail_found = mp_rail_manager->CheckForHangRail(\r\n\t\tstart_pos,\r\n\t\tend_pos,\r\n\t\tm_facing,\r\n\t\tthis,\r\n\t\trail_data,\r\n\t\tScript::GetFloat(CRCD(0x30ce7f2c, \"Climb_Max_Snap\"))\r\n\t))\r\n\t{\r\n\t\tmp_movable_contact_component->LoseAnyContact();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// check moving objects for appropriate rails\r\n\t\tfor (CRailManagerComponent* p_rail_manager_component = static_cast< CRailManagerComponent* >(CCompositeObjectManager::Instance()->GetFirstComponentByType(CRC_RAILMANAGER));\r\n\t\t\tp_rail_manager_component && !rail_found;\r\n\t\t\tp_rail_manager_component = static_cast< CRailManagerComponent* >(p_rail_manager_component->GetNextSameType()))\r\n\t\t{\r\n\t\t\tMth::Matrix obj_matrix_inv = p_rail_manager_component->UpdateRailManager();\r\n\t\t\tobj_matrix_inv.Invert();\r\n\t\t\t\r\n\t\t\t// transform into the frame of the moving object\r\n\t\t\tMth::Vector obj_frame_start_pos = obj_matrix_inv.Transform(start_pos);\r\n\t\t\tMth::Vector obj_frame_end_pos = obj_matrix_inv.Transform(end_pos);\r\n\t\t\t\r\n\t\t\tmp_rail_manager = p_rail_manager_component->GetRailManager();\r\n\t\t\tif (rail_found = mp_rail_manager->CheckForHangRail(\r\n\t\t\t\tobj_frame_start_pos,\r\n\t\t\t\tobj_frame_end_pos,\r\n\t\t\t\tm_facing,\r\n\t\t\t\tthis,\r\n\t\t\t\trail_data,\r\n\t\t\t\tScript::GetFloat(CRCD(0x30ce7f2c, \"Climb_Max_Snap\"))\r\n\t\t\t))\r\n\t\t\t{\r\n\t\t\t\tmp_movable_contact_component->ObtainContact(p_rail_manager_component->GetObject());\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (!rail_found) return false;\r\n\t\t\r\n\t// we've found a rail to hang onto\r\n\t\r\n\tmp_rail_start = rail_data.p_rail_node;\r\n\tmp_rail_end = mp_rail_start->GetNextLink();\r\n\tDbg_Assert(mp_rail_end);\r\n\t\r\n\tm_pos = rail_data.hang_point;\r\n\tDUMP_WPOSITION\r\n\tm_facing = rail_data.hang_facing;\r\n\tm_along_rail_factor = rail_data.along_rail_factor;\r\n\tm_vertical_hang_offset = rail_data.vertical_hang_offset;\r\n\tm_horizontal_hang_offset = rail_data.horizontal_hang_offset;\r\n\tm_initial_hang_animation = rail_data.initial_animation;\r\n\t\r\n\tm_critical_point_offset = s_get_param(CRCD(0xc3263e6e, \"hang_critical_point_horiz_offset\")) * m_facing;\r\n\tm_critical_point_offset[Y] = get_hang_critical_point_vert_offset();\r\n\t\r\n\tm_horizontal_vel.Set();\r\n\tm_vertical_vel = 0.0f;\r\n\t\r\n\tm_display_offset = get_hang_display_offset();\r\n\r\n\tset_state(WALKING_HANG);\r\n\r\n\tm_frame_event = CRCD(0x4194ecca, \"Hang\");\r\n\t\r\n\tmp_core_physics_component->SetFlagTrue(SNAPPED);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::FilterHangRail ( const Mth::Vector& pos_a, const Mth::Vector& pos_b, const Mth::Vector& preliminary_hang_point, const Mth::Vector& grab_from_point, float along_rail_factor, SHangRailData& rail_data, bool drop_to_hang )\r\n{\r\n\t// check this rail for potential hang use\r\n\t\r\n\tfloat hang_vert_origin_offset = s_get_param(CRCD(0xa8c13e74, \"hang_vert_origin_offset\")); \r\n\t\r\n\t// never snap upward to a hang rail\r\n\tif (m_state == WALKING_AIR && preliminary_hang_point[Y] > grab_from_point[Y]) return false;\r\n\t\r\n\t// never snap too far vertically to a hang rail\r\n\tif (m_state == WALKING_AIR && Mth::Abs(preliminary_hang_point[Y] - grab_from_point[Y]) > 12.0f) return false;\r\n\t\r\n\t// is the rail too steep\r\n\tMth::Vector rail = pos_b - pos_a;\r\n\tMth::Vector rail_direction = rail;\r\n\trail_direction.Normalize();\r\n\tif (Mth::Abs(rail_direction[Y]) > sinf(Mth::DegToRad(s_get_param(CRCD(0x98724ebc, \"hang_max_rail_ascent\"))))) return false;\r\n\t\r\n\t// calculate the facing we'd have while hanging\r\n\t\r\n\trail_data.hang_facing.Set(-(rail[Z]), 0.0f, rail[X]);\r\n\trail_data.hang_facing.Normalize();\r\n\tif (!drop_to_hang)\r\n\t{\r\n\t\t// normally, we attempt retain our current facing\r\n\t\tif (Mth::DotProduct(rail_data.hang_facing, m_facing) < 0.0f)\r\n\t\t{\r\n\t\t\trail_data.hang_facing.Negate();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// unless dropping to a hang\r\n\t\tif (Mth::DotProduct(rail_data.hang_facing, m_facing) > 0.0f)\r\n\t\t{\r\n\t\t\trail_data.hang_facing.Negate();\r\n\t\t}\r\n\t}\r\n\r\n\tbool rail_points_left = rail_data.hang_facing[Z] * rail_direction[X] - rail_data.hang_facing[X] * rail_direction[Z] > 0.0f;\r\n\tif ((rail_data.p_rail_node->GetFlag(NO_HANG_WITH_LEFT_ALONG_RAIL) && rail_points_left)\r\n\t\t|| (rail_data.p_rail_node->GetFlag(NO_HANG_WITH_RIGHT_ALONG_RAIL) && !rail_points_left))\r\n\t{\r\n\t\trail_data.hang_facing.Negate();\r\n\t\trail_points_left = !rail_points_left;\r\n\t}\r\n\t\r\n\t// investigate the hang point to see if its a good hang\r\n\t\r\n\tCFeeler feeler;\r\n\tNx::CCollCache* p_coll_cache = Nx::CCollCacheManager::sCreateCollCache();\r\n\tMth::CBBox bbox(\r\n\t\tpreliminary_hang_point - Mth::Vector(24.0f, 24.0f, 24.0f),\r\n\t\tpreliminary_hang_point + Mth::Vector(24.0f, 12.0f + hang_vert_origin_offset, 24.0f)\r\n\t);\r\n\tp_coll_cache->Update(bbox);\r\n\tfeeler.SetCache(p_coll_cache);\r\n\t\r\n\trail_data.along_rail_factor = along_rail_factor;\r\n\t\r\n\tif (!investigate_hang_rail_vicinity(feeler, preliminary_hang_point, rail_data))\r\n\t{\r\n\t\t// if we're attempting to grab a rail from the air, try both possible facings\r\n\t\tif (m_state == WALKING_AIR || !drop_to_hang)\r\n\t\t{\r\n\t\t\t// see if we're allowed to try the other facing\r\n\t\t\tif ((rail_data.p_rail_node->GetFlag(NO_HANG_WITH_LEFT_ALONG_RAIL) && !rail_points_left)\r\n\t\t\t\t|| (rail_data.p_rail_node->GetFlag(NO_HANG_WITH_RIGHT_ALONG_RAIL) && rail_points_left))\r\n\t\t\t{\r\n\t\t\t\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\trail_data.hang_facing.Negate();\r\n\t\t\tif (!investigate_hang_rail_vicinity(feeler, preliminary_hang_point, rail_data))\r\n\t\t\t{\r\n\t\t\t\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\r\n\trail_data.vertical_hang_offset = rail_data.hang_point[Y] - preliminary_hang_point[Y];\r\n\trail_data.horizontal_hang_offset = Mth::DotProduct(rail_data.hang_facing, rail_data.hang_point - preliminary_hang_point);\r\n\t\r\n\t// determine which sort of initial hang animation would be used\r\n\tfeeler.m_start = rail_data.hang_point + s_get_param(CRCD(0xc3263e6e, \"hang_critical_point_horiz_offset\")) * rail_data.hang_facing;\r\n\tfeeler.m_start[Y] += s_get_param(CRCD(0xdbb3d53e, \"hang_init_anim_feeler_height\"));\r\n\tfeeler.m_end = feeler.m_start;\r\n\tfeeler.m_end += s_get_param(CRCD(0x2f83ae83, \"hang_init_anim_feeler_length\")) * rail_data.hang_facing;\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(255, 0, 0, 0);\r\n\t\t}\r\n\t\t#endif\r\n\t\trail_data.initial_animation = CRCD(0xec0a1009, \"WALL\");\r\n\t}\r\n\telse\r\n\t{\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(0, 0, 255, 0);\r\n\t\t}\r\n\t\t#endif\r\n\t\trail_data.initial_animation = CRCD(0x1ee948a5, \"SWING\");\r\n\t}\r\n\t\r\n\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::investigate_hang_rail_vicinity ( CFeeler& feeler, const Mth::Vector& preliminary_hang_point, SHangRailData& rail_data )\r\n{\r\n\t/* turning off geo investigation for hang point adjustment\r\n\t// run a feeler up/down at the preliminary hang point to find the true top of the ledge\r\n\tfeeler.SetLine(preliminary_hang_point, preliminary_hang_point);\r\n\tfeeler.m_start[Y] += s_get_param(CRCD(0x1bc501ab, \"ledge_top_feeler_up\"));\r\n\tfeeler.m_end[Y] -= s_get_param(CRCD(0xf5f39a8, \"ledge_top_feeler_down\"));\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t// found a ledge top\r\n\t\trail_data.hang_point = feeler.GetPoint();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// use the prelimiary hang point\r\n\t\trail_data.hang_point = preliminary_hang_point;\r\n\t}\r\n\t\r\n\t// run a feeler in an inch below the hang point along the hang facing to find the front of the ledge\r\n\tfeeler.m_start = rail_data.hang_point - s_get_param(CRCD(0x95fd5dc5, \"ledge_front_feeler_back\")) * rail_data.hang_facing;\r\n\tfeeler.m_end = rail_data.hang_point + s_get_param(CRCD(0xccb4f5d2, \"ledge_front_feeler_forward\")) * rail_data.hang_facing;\r\n\tfeeler.m_start[Y] -= 1.0f;\r\n\tfeeler.m_end[Y] -= 1.0f;\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t// found a ledge front\r\n\t\trail_data.hang_point = feeler.GetPoint();\r\n\t\trail_data.hang_point[Y] += 1.0f;\r\n\t}\r\n\t// hang a touch outside of it\r\n\trail_data.hang_point -= 2.0f * rail_data.hang_facing;\r\n\t*/\r\n\t\r\n\trail_data.hang_point = preliminary_hang_point;\r\n\t\r\n\tMth::Vector left(-rail_data.hang_facing[Z], 0.0f, rail_data.hang_facing[X]);\r\n\t\r\n\tMth::Vector rail = mp_rail_manager->GetPos(rail_data.p_rail_node) - mp_rail_manager->GetPos(rail_data.p_rail_node->GetNextLink());\r\n\t\r\n\t// now that we have the hang position, run two feelers up and down the hang location to insure there is room\r\n\tif (!vertical_hang_obstruction_check(feeler, rail_data, left) || !vertical_hang_obstruction_check(feeler, rail_data, -left)) return false;\r\n\r\n\t// adjust the hang point for the origin of the hanging skater\r\n\trail_data.hang_point[Y] -= s_get_param(CRCD(0xa8c13e74, \"hang_vert_origin_offset\"));\r\n\trail_data.hang_point += s_get_param(CRCD(0x262a9467, \"hang_horiz_origin_offset\")) * rail_data.hang_facing;\r\n\t\r\n\t// use our move feelers for a look around\r\n\tif (check_environment_for_hang_movement_collisions(rail_data.hang_facing, rail_data.along_rail_factor, rail_data.hang_point, true, left, rail, rail_data.p_rail_node, rail_data.p_rail_node->GetNextLink())) return false;\r\n\tif (check_environment_for_hang_movement_collisions(rail_data.hang_facing, rail_data.along_rail_factor, rail_data.hang_point, false, left, rail, rail_data.p_rail_node, rail_data.p_rail_node->GetNextLink())) return false;\r\n\t\r\n\t// adjust the feeler target check point based on hanging's critical point offset\r\n\tMth::Vector critical_point = rail_data.hang_point + s_get_param(CRCD(0xc3263e6e, \"hang_critical_point_horiz_offset\")) * rail_data.hang_facing;\r\n\tcritical_point[Y] += get_hang_critical_point_vert_offset();\r\n\t\r\n\t// check for obstructions to our hang point; it is critical that our critical point remains on the happy side of collision geometry\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_end = critical_point;\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(255, 0, 255, 0);\r\n\t}\r\n\t#endif\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tif (m_state == WALKING_GROUND)\r\n\t\t{\r\n\t\t\t// we found an obstruction taking a direct route; if we'll be hopping to the rail, try an up-and-over route\r\n\t\t\t\r\n\t\t\tfeeler.m_end = m_pos;\r\n\t\t\tfeeler.m_end[Y] += s_get_param(CRCD(0xa85ec070, \"hop_obstruction_feeler_up\"));\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t{\r\n\t\t\t\tfeeler.DebugLine(255, 0, 255, 0);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t\tif (feeler.GetCollision())\r\n\t\t\t{\r\n\t\t\t\t#ifdef __USER_DAN__\r\n\t\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t\t{\r\n\t\t\t\t\tGfx::AddDebugStar(feeler.GetPoint(), 12.0f, MAKE_RGB(0, 255, 255), 0);\r\n\t\t\t\t}\r\n\t\t\t\t#endif\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tfeeler.m_start = feeler.m_end;\r\n\t\t\tfeeler.m_end = critical_point;\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t{\r\n\t\t\t\tfeeler.DebugLine(255, 0, 255, 0);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t\tif (feeler.GetCollision())\r\n\t\t\t{\r\n\t\t\t\t#ifdef __USER_DAN__\r\n\t\t\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t\t\t{\r\n\t\t\t\t\tGfx::AddDebugStar(feeler.GetPoint(), 12.0f, MAKE_RGB(0, 255, 255), 0);\r\n\t\t\t\t}\r\n\t\t\t\t#endif\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::vertical_hang_obstruction_check ( CFeeler& feeler, SHangRailData& rail_data, const Mth::Vector& check_offset_direction )\r\n{\r\n\tfeeler.m_start = rail_data.hang_point + s_get_param(CRCD(0xc3263e6e, \"hang_critical_point_horiz_offset\")) * rail_data.hang_facing\r\n\t\t+ s_get_param(CRCD(0xafbf7687, \"hang_obstruction_feeler_side\")) * check_offset_direction;\r\n\tfeeler.m_end = feeler.m_start;\r\n\tfeeler.m_start[Y] += -s_get_param(CRCD(0xa8c13e74, \"hang_vert_origin_offset\")) + get_hang_critical_point_vert_offset();\r\n\tfeeler.m_end[Y] += s_get_param(CRCD(0x8f35f29f, \"hang_obstruction_feeler_up\"));\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(255, 0, 50, 0);\r\n\t\t}\r\n\t\t#endif\r\n\t\treturn false;\r\n\t}\r\n\tMth::Swap(feeler.m_start, feeler.m_end);\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(0, 255, 50, 0);\r\n\t\t}\r\n\t\t#endif\r\n\t\treturn false;\r\n\t}\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(200, 200, 50, 0);\r\n\t}\r\n\t#endif\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\nvoid CWalkComponent::go_hop_state (   )\r\n{\r\n\t// During the hop to hang state, the player has no control.  We simply move the goal position.\r\n\t\r\n\tif (mp_movable_contact_component->UpdateContact(m_pos))\r\n\t{\r\n\t\tm_pos += mp_movable_contact_component->GetContact()->GetMovement();\r\n\t\t\r\n\t\tif (mp_movable_contact_component->GetContact()->IsRotated())\r\n\t\t{\r\n\t\t\tm_facing = mp_movable_contact_component->GetContact()->GetRotation().Rotate(m_facing);\r\n\t\t\tm_goal_hop_facing = mp_movable_contact_component->GetContact()->GetRotation().Rotate(m_goal_hop_facing);\r\n\t\t\tif (m_facing[Y] != 0.0f)\r\n\t\t\t{\r\n\t\t\t\tm_facing[Y] = 0.0f;\r\n\t\t\t\tm_facing.Normalize();\r\n\t\t\t}\r\n\t\t\tif (m_goal_hop_facing[Y] != 0.0f)\r\n\t\t\t{\r\n\t\t\t\tm_goal_hop_facing[Y] = 0.0f;\r\n\t\t\t\tm_goal_hop_facing.Normalize();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (m_vertical_vel > -s_get_param(CRCD(0x7aa618cc, \"hop_target_vert_vel\")))\r\n\t{\r\n\t\tm_pos += m_horizontal_vel * m_frame_length;\r\n\t\tm_pos[Y] += m_vertical_vel * m_frame_length + 0.5f * -s_get_param(CRCD(0xa5e2da58, \"gravity\")) * Mth::Sqr(m_frame_length);\r\n\t\t\r\n\t\tm_vertical_vel += -s_get_param(CRCD(0xa5e2da58, \"gravity\")) * m_frame_length;\r\n\t\t\r\n\t\t// BUG: we really want more control over this; this can cause pops; perhaps hold the hop duration and use the hop fraction complete\r\n\t\tm_facing = Mth::Lerp(m_facing, m_goal_hop_facing, 30.0f * Tmr::FrameLength()); \r\n\r\n\t\tm_frame_event = CRCD(0xf41aba21, \"Hop\");\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_horizontal_vel.Set();\r\n\t\tm_vertical_vel = 0.0f;\r\n\t\t\r\n\t\tm_pos = m_goal_hop_pos;\r\n\t\t\r\n\t\tm_facing = m_goal_hop_facing;\r\n\t\t\r\n\t\tset_state(WALKING_HANG);\r\n\t\t\r\n\t\tm_frame_event = CRCD(0x4194ecca, \"Hang\");\r\n\t}\r\n}\r\n*/\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::go_hang_state (   )\r\n{\r\n\t// Mth::Vector rail = (mp_rail_manager->GetPos(mp_rail_start) - mp_rail_manager->GetPos(mp_rail_end)).Normalize();\r\n\t// DUMPF(Mth::RadToDeg(asin(Mth::Abs(rail[Y]))));\r\n\t\r\n\tif (mp_movable_contact_component->UpdateContact(m_pos))\r\n\t{\r\n\t\tCRailManagerComponent* p_rail_manager_component = GetRailManagerComponentFromObject(mp_movable_contact_component->GetContact()->GetObject());\r\n\t\tDbg_Assert(p_rail_manager_component);\r\n\r\n\t\tp_rail_manager_component->UpdateRailManager();\r\n\t\t\r\n\t\t// calculate our new position\r\n\t\tset_pos_from_hang_rail_state();\r\n\t}\r\n\t\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0x1a5eab7, \"rail_highlights\")))\r\n\t{\r\n\t\tGfx::AddDebugLine(mp_rail_manager->GetPos(mp_rail_start), mp_rail_manager->GetPos(mp_rail_end), MAKE_RGB(Mth::Rnd(256), Mth::Rnd(256), Mth::Rnd(256)), 0, 1);\r\n\t\tGfx::AddDebugLine(mp_rail_manager->GetPos(mp_rail_start) + Mth::Vector(1.0f, 0.0f, 0.0f), mp_rail_manager->GetPos(mp_rail_end) + Mth::Vector(1.0f, 0.0f, 0.0f), MAKE_RGB(Mth::Rnd(256), Mth::Rnd(256), Mth::Rnd(256)), 0, 1);\r\n\t\tGfx::AddDebugLine(mp_rail_manager->GetPos(mp_rail_start) + Mth::Vector(0.0f, 1.0f, 0.0f), mp_rail_manager->GetPos(mp_rail_end) + Mth::Vector(0.0f, 1.0f, 0.0f), MAKE_RGB(Mth::Rnd(256), Mth::Rnd(256), Mth::Rnd(256)), 0, 1);\r\n\t\tGfx::AddDebugLine(mp_rail_manager->GetPos(mp_rail_start) + Mth::Vector(0.0f, 0.0f, 1.0f), mp_rail_manager->GetPos(mp_rail_end) + Mth::Vector(0.0f, 0.0f, 1.0f), MAKE_RGB(Mth::Rnd(256), Mth::Rnd(256), Mth::Rnd(256)), 0, 1);\r\n\t}\r\n\t#endif\r\n\t\r\n\t// only respond to full up/down controls and only after a frame delay (to allow the debounce a frame to kick in)\r\n\tif (m_control_pegged)\r\n\t{\r\n\t\t// up; IsLeftAnalogUpPressed allows for analog debouncing\r\n\t\tif (mp_input_component->GetControlPad().IsLeftAnalogUpPressed())\r\n\t\t{\r\n\t\t\t// potential standing position after pull up\r\n\t\t\tMth::Vector stand_pos = m_pos + s_get_param(CRCD(0x21dfbe77, \"pull_up_offset_forward\")) * m_facing;\r\n\t\t\tstand_pos[Y] += s_get_param(CRCD(0x52fa7ca6, \"pull_up_offset_up\"));\r\n\t\t\tif (maybe_pull_up_from_hang(stand_pos)) return;\r\n\t\t\t\r\n\t\t\t// try standing a little closer\r\n\t\t\tstand_pos = m_pos + 0.5f * s_get_param(CRCD(0x21dfbe77, \"pull_up_offset_forward\")) * m_facing;\r\n\t\t\tstand_pos[Y] += s_get_param(CRCD(0x52fa7ca6, \"pull_up_offset_up\"));\r\n\t\t\tif (maybe_pull_up_from_hang(stand_pos)) return;\r\n\t\t}\r\n\t\t// down; IsLeftAnalogDownPressed allows for analog debouncing\r\n\t\telse if (mp_input_component->GetControlPad().IsLeftAnalogDownPressed())\r\n\t\t{\r\n\t\t\t// drop\r\n\t\t\tset_state(WALKING_AIR);\r\n\t\t\tm_primary_air_direction = m_facing;\r\n\t\t\tleave_movable_contact_for_air(m_horizontal_vel, m_vertical_vel);\r\n\t\t\tm_frame_event = CRCD(0x439f4704, \"Air\");\r\n\t\t\t\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// left or right\r\n\tfloat control_vel;\r\n\tif (Mth::Abs((Mth::PI / 2.0f) - Mth::Abs(mp_input_component->GetControlPad().m_leftAngle)) < cosf(Mth::DegToRad(s_get_param(CRCD(0x1b877928, \"hang_vert_control_tolerance\")))))\r\n\t{\r\n\t\tcontrol_vel = s_get_param(CRCD(0xd77ee881, \"hang_move_speed\")) * m_control_magnitude\r\n\t\t\t* (mp_input_component->GetControlPad().m_leftAngle > 0.0f ? 1.0f : -1.0f);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcontrol_vel = 0.0f;\r\n\t}\r\n\tm_hang_move_vel = Mth::Lerp(m_hang_move_vel, control_vel, s_get_param(CRCD(0xc506a97c, \"hang_move_lerp_rate\")) * m_frame_length);\r\n\t\r\n\tif (Mth::Abs(m_hang_move_vel) > s_get_param(CRCD(0x228b5376, \"hang_move_cutoff\")))\r\n\t{\r\n\t\tm_anim_effective_speed = Mth::Abs(m_hang_move_vel);\r\n\t\r\n\t\thang_movement(m_hang_move_vel * m_frame_length);\r\n\r\n\t\t// calculate our new position\r\n\t\tset_pos_from_hang_rail_state();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_frame_event = CRCD(0x4194ecca, \"Hang\");\r\n\t}\r\n\t\r\n\t/* this doesn't make sense with the new higher critical point\r\n\t// run a feeler between our old and new position to insure that our position stays safe\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_frame_start_pos + s_get_param(CRCD(0xc3263e6e, \"hang_critical_point_horiz_offset\")) * m_facing;\r\n\tfeeler.m_end = m_pos + s_get_param(CRCD(0xc3263e6e, \"hang_critical_point_horiz_offset\")) * m_facing;\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t// our feet have hit something; often this means the rail has dropped to ground level; drop from our old position\r\n\t\tm_pos = m_frame_start_pos;\r\n\t\tset_state(WALKING_AIR);\r\n\t\tm_primary_air_direction = m_facing;\r\n\t\tleave_movable_contact_for_air(m_horizontal_vel, m_vertical_vel);\r\n\t\tm_frame_event = CRCD(0x439f4704, \"Air\");\r\n\t\treturn;\r\n\t}\r\n\t*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\r\nvoid CWalkComponent::hang_movement ( float movement )\r\n{\r\n\t// cache current critical point location and entire state\r\n\tMth::Vector initial_critical_point = m_pos + m_critical_point_offset;\r\n\tMth::Vector initial_pos = m_pos;\r\n\tfloat initial_along_rail_factor = m_along_rail_factor;\r\n\tconst CRailNode* p_initial_rail_start = mp_rail_start;\r\n\tconst CRailNode* p_initial_rail_end = mp_rail_end;\r\n\tMth::Vector initial_critical_point_offset = m_critical_point_offset; \r\n\tMth::Vector initial_facing = m_facing; \r\n\t\r\n\t// allow left/right movement along rail\r\n\t\r\n\tMth::Vector perp_facing(-m_facing[Z], 0.0f, m_facing[X]);\r\n\t\r\n\t// the offset from rail start to rail end\r\n\tMth::Vector rail = mp_rail_manager->GetPos(mp_rail_start) - mp_rail_manager->GetPos(mp_rail_end);\r\n\t\r\n\t// move left or right\r\n\tbool left = movement > 0.0f;\r\n\t\r\n\t// is rail fractional position parameter ascends or descends with the movement\r\n\tbool with_rail;\r\n\tif (Mth::DotProduct(perp_facing, rail) < 0.0f)\r\n\t{\r\n\t\twith_rail = left;\r\n\t}\r\n\telse\r\n\t{\r\n\t\twith_rail = !left;\r\n\t}\r\n\r\n\t// check for collisions\r\n\tif (check_environment_for_hang_movement_collisions(m_facing, m_along_rail_factor, m_pos, left, perp_facing, rail, mp_rail_start, mp_rail_end))\r\n\t{\r\n\t\tm_hang_move_vel = 0.0f;\r\n\t\tm_frame_event = CRCD(0x4194ecca, \"Hang\");\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// the movement in terms of the fraction of the rail\r\n\tfloat delta_factor = Mth::Abs(movement) / rail.Length();\r\n\t\r\n\t// move along the rail\r\n\tm_along_rail_factor += with_rail ? delta_factor : -delta_factor;\r\n\t\r\n\t// if we're moving off the rail\r\n\tif (m_along_rail_factor < 0.0f || m_along_rail_factor > 1.0f)\r\n\t{\r\n\t\tbool found_rail = find_next_rail(m_along_rail_factor, mp_rail_start, mp_rail_end, mp_rail_start, mp_rail_end);\r\n\t\t\t\r\n\t\t// there's no connecting rail\r\n\t\tif (!found_rail)\r\n\t\t{\r\n\t\t\t// clamp the movement\r\n\t\t\tm_hang_move_vel = 0.0f;\r\n\t\t\tm_along_rail_factor = Mth::Clamp(m_along_rail_factor, 0.0f, 1.0f);\r\n\t\t\tm_frame_event = CRCD(0x4194ecca, \"Hang\");\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// move onto the neighboring rail\r\n\t\t\tfloat remaining_movement = Mth::Abs(m_along_rail_factor - Mth::Clamp(m_along_rail_factor, 0.0f, 1.0f)) * rail.Length();\r\n\t\t\tmove_onto_neighboring_hang_rail(remaining_movement, m_along_rail_factor < 0.0f, with_rail ? rail : -rail);\r\n\t\t\tm_frame_event = left ? CRCD(0x2d9815c3, \"HangMoveLeft\") : CRCD(0x279b1f0b, \"HangMoveRight\");\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_frame_event = left ? CRCD(0x2d9815c3, \"HangMoveLeft\") : CRCD(0x279b1f0b, \"HangMoveRight\");\r\n\t}\r\n\t\r\n\t// check to see if the critical point has gone through geo\r\n\t\r\n\tMth::Vector critical_point = m_pos + m_critical_point_offset;\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = initial_critical_point;\r\n\tfeeler.m_end = critical_point;\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t// restore entire to state to initial state\r\n\t\tm_pos = initial_pos;\r\n\t\tDUMP_WPOSITION\r\n\t\tm_along_rail_factor = initial_along_rail_factor;\r\n\t\tmp_rail_start = p_initial_rail_start;\r\n\t\tmp_rail_end = p_initial_rail_end;\r\n\t\tm_critical_point_offset = initial_critical_point_offset;\r\n\t\tm_facing = initial_facing;\r\n\t\t\r\n\t\tm_hang_move_vel = 0.0f;\r\n\t\tm_frame_event = CRCD(0x4194ecca, \"Hang\");\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\r\nbool CWalkComponent::check_environment_for_hang_movement_collisions ( const Mth::Vector& facing, float along_rail_factor, const Mth::Vector& pos, bool left, const Mth::Vector& perp_facing, Mth::Vector rail, const CRailNode* p_rail_start, const CRailNode* p_rail_end )\r\n{\r\n\t// check environment in the appropriate check_direction for collisions which would prevent hanging movement\r\n\t// OPTIMIZATION: use a CCollCache here\r\n\t\r\n\tbool with_rail;\r\n\tif (Mth::DotProduct(perp_facing, rail) < 0.0f)\r\n\t{\r\n\t\twith_rail = left;\r\n\t}\r\n\telse\r\n\t{\r\n\t\twith_rail = !left;\r\n\t}\r\n\t\r\n\t// check_direction to the side to check for geo\r\n\tMth::Vector check_direction = left ? perp_facing : -perp_facing;\r\n\t\r\n\t// adjusted facing due to adjusted check_direction\r\n\tMth::Vector check_direction_facing = facing;\r\n\r\n\t// see if we're near the end of the rail; if so, we may want to angle our feelers out (so we can make inside turns while hanging)\r\n\tfloat distance_to_end_of_rail = rail.Length() * (with_rail ? 1.0f - along_rail_factor : along_rail_factor);\r\n\tif (distance_to_end_of_rail < s_get_param(CRCD(0x3344a6d0, \"hang_move_collision_side_length\")) + 1.0f)\r\n\t{\r\n\t\t// pretend we're past the rail when calling find_next_rail\r\n\t\talong_rail_factor += with_rail ? 2.0f : -2.0f;\r\n\t\t\r\n\t\tconst CRailNode* p_next_start;\r\n\t\tconst CRailNode* p_next_end;\r\n\t\tif (find_next_rail(along_rail_factor, p_rail_start, p_rail_end, p_next_start, p_next_end))\r\n\t\t{\r\n\t\t\tMth::Vector new_check_direction = (along_rail_factor > 0.5f ? -1.0f : 1.0f)\r\n\t\t\t\t* (mp_rail_manager->GetPos(p_next_start) - mp_rail_manager->GetPos(p_next_end));\r\n\t\t\tnew_check_direction[Y] = 0.0f;\r\n\t\t\tnew_check_direction.Normalize();\r\n\t\t\t\r\n\t\t\t// only use adjusted feelers for inside turns\r\n\t\t\tfloat dot = Mth::DotProduct(facing, new_check_direction);\r\n\t\t\tif (dot < 0.0f && dot > -0.87f)\r\n\t\t\t{\r\n\t\t\t\tcheck_direction = new_check_direction;\r\n\t\t\t\tif (left)\r\n\t\t\t\t{\r\n\t\t\t\t\tcheck_direction_facing[X] = check_direction[Z];\r\n\t\t\t\t\tcheck_direction_facing[Z] = -check_direction[X];\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tcheck_direction_facing[X] = -check_direction[Z];\r\n\t\t\t\t\tcheck_direction_facing[Z] = check_direction[X];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = pos;\r\n\tfeeler.m_start[Y] += s_get_param(CRCD(0x84ff931c, \"hang_move_collision_up\"));\r\n\tfeeler.m_start -= s_get_param(CRCD(0xcbeb3d89, \"hang_move_collision_back\")) * facing;\r\n\t\r\n\t// feel to the side\r\n\tfeeler.m_end = feeler.m_start;\r\n\tfeeler.m_end += s_get_param(CRCD(0x3344a6d0, \"hang_move_collision_side_length\")) * check_direction;\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(255, 0, 0, 1);\r\n\t\t}\r\n\t\t#endif\r\n\t\treturn true;\r\n\t}\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(0, 0, 255, 1);\r\n\t}\r\n\t#endif\r\n\t\r\n\t// feel up and to the side\r\n\tfeeler.m_end = feeler.m_start;\r\n\tfeeler.m_end[Y] += s_get_param(CRCD(0xc774dd6d, \"hang_move_collision_side_height\"));\r\n\tfeeler.m_end += s_get_param(CRCD(0x3344a6d0, \"hang_move_collision_side_length\")) * check_direction;\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(255, 0, 0, 1);\r\n\t\t}\r\n\t\t#endif\r\n\t\treturn true;\r\n\t}\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(0, 0, 255, 1);\r\n\t}\r\n\t#endif\r\n\t\r\n\t// feel half up and to the side\r\n\tfeeler.m_end = feeler.m_start;\r\n\tfeeler.m_end[Y] += 0.5f * s_get_param(CRCD(0xc774dd6d, \"hang_move_collision_side_height\"));\r\n\tfeeler.m_end += s_get_param(CRCD(0x3344a6d0, \"hang_move_collision_side_length\")) * check_direction;\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(255, 0, 0, 1);\r\n\t\t}\r\n\t\t#endif\r\n\t\treturn true;\r\n\t}\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(0, 0, 255, 1);\r\n\t}\r\n\t#endif\r\n\t\r\n\t// feel down (to critical point) and to the side and back to the critical point\r\n\tfeeler.m_end = feeler.m_start;\r\n\tfeeler.m_end[Y] += -s_get_param(CRCD(0x84ff931c, \"hang_move_collision_up\")) + get_hang_critical_point_vert_offset() - 1.0f;\r\n\tfeeler.m_end += s_get_param(CRCD(0xc3263e6e, \"hang_critical_point_horiz_offset\")) * check_direction_facing;\r\n\tfeeler.m_end += s_get_param(CRCD(0x3344a6d0, \"hang_move_collision_side_length\")) * check_direction;\r\n\t // add a touch along the rail so we don't get stuck with both directions feelers in the ground\r\n\tfeeler.m_end += with_rail ? -rail.Normalize() : rail.Normalize();\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(255, 0, 0, 1);\r\n\t\t}\r\n\t\t#endif\r\n\t\treturn true;\r\n\t}\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(0, 0, 255, 1);\r\n\t}\r\n\t#endif\r\n\t\r\n\t// feel half down and to the side and back to the critical point\r\n\tfeeler.m_end = feeler.m_start;\r\n\tfeeler.m_end[Y] -= 0.5f * s_get_param(CRCD(0xc774dd6d, \"hang_move_collision_side_height\"));\r\n\tfeeler.m_end += s_get_param(CRCD(0xc3263e6e, \"hang_critical_point_horiz_offset\")) * check_direction_facing;\r\n\tfeeler.m_end += s_get_param(CRCD(0x3344a6d0, \"hang_move_collision_side_length\")) * check_direction;\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(255, 0, 0, 1);\r\n\t\t}\r\n\t\t#endif\r\n\t\treturn true;\r\n\t}\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(0, 0, 255, 1);\r\n\t}\r\n\t#endif\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::move_onto_neighboring_hang_rail ( float movement, bool descending, const Mth::Vector& old_rail )\r\n{\r\n\tMth::Vector next_rail = mp_rail_manager->GetPos(mp_rail_start) - mp_rail_manager->GetPos(mp_rail_end);\r\n\tfloat next_rail_length = next_rail.Length();\r\n\t\r\n\t// if the next rail is shorter than our movement, just ditch the extra movement\r\n\tmovement = Mth::ClampMax(movement, next_rail_length);\r\n\t\r\n\t// we've found the appropriate neighbor rail to move on to, so set up our state\r\n\t\r\n\t// calculate our position along the rail\r\n\tm_along_rail_factor = movement / next_rail_length;\r\n\tif (descending)\r\n\t{\r\n\t\tm_along_rail_factor = 1.0f - m_along_rail_factor;\r\n\t}\r\n\t\r\n\t// calculate our next facing\r\n\tMth::Vector next_facing(-next_rail[Z], 0.0f, next_rail[X]);\r\n\tnext_facing.Normalize();\r\n\t\r\n\t// check its check_direction\r\n\tif (Mth::CrossProduct(old_rail, m_facing)[Y] * Mth::CrossProduct(descending ? -next_rail : next_rail, next_facing)[Y] < 0.0f)\r\n\t{\r\n\t\tnext_facing.Negate();\r\n\t}\r\n\t\r\n\tif (Mth::DotProduct(next_facing, m_facing) < cosf(Mth::DegToRad(60.0f)))\r\n\t{\r\n\t\t// move the camera behind us\r\n\t\tmp_camera_component->FlushRequest();\r\n\t}\r\n\tm_facing = next_facing;\r\n\t\r\n\tm_critical_point_offset = s_get_param(CRCD(0xc3263e6e, \"hang_critical_point_horiz_offset\")) * m_facing;\r\n\tm_critical_point_offset[Y] = get_hang_critical_point_vert_offset();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::set_pos_from_hang_rail_state (   )\r\n{\r\n\tm_pos = Mth::Lerp(mp_rail_manager->GetPos(mp_rail_start), mp_rail_manager->GetPos(mp_rail_end), m_along_rail_factor);\r\n\tm_pos[Y] += m_vertical_hang_offset;\r\n\tm_pos += m_horizontal_hang_offset * m_facing;\r\n\tDUMP_WPOSITION\r\n\t\r\n\tif (mp_movable_contact_component->HaveContact() && mp_movable_contact_component->GetContact()->IsRotated())\r\n\t{\r\n\t\t// recalculate facing\r\n\t\tMth::Vector new_facing = mp_rail_manager->GetPos(mp_rail_start) - mp_rail_manager->GetPos(mp_rail_end);\r\n\t\tnew_facing[Y] = 0.0f;\r\n\t\tnew_facing.Normalize();\r\n\t\tnew_facing.Set(-new_facing[Z], 0.0f, new_facing[X]);\r\n\t\tif (Mth::DotProduct(new_facing, m_facing) > 0.0f)\r\n\t\t{\r\n\t\t\tm_facing = new_facing;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_facing = -new_facing;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::find_next_rail ( float& along_rail_factor, const CRailNode* p_current_start, const CRailNode* p_current_end, const CRailNode*& p_new_start, const CRailNode*& p_new_end )\r\n{\r\n\t// find the neighboring rail, if there is one\r\n\t\r\n\tDbg_Assert(along_rail_factor < 0.0f || along_rail_factor > 1.0f);\r\n\t\r\n\tconst CRailNode* next_rail_node = NULL;\r\n\tif (along_rail_factor < 0.0f)\r\n\t{\r\n\t\t// look for a connection\r\n\t\tif (p_current_start->GetPrevLink() && p_current_start->GetPrevLink()->IsActive() && !p_current_start->GetPrevLink()->GetFlag(NO_CLIMBING)\r\n\t\t\t&& Rail_ValidInEditor(mp_rail_manager->GetPos(p_current_start->GetPrevLink()), mp_rail_manager->GetPos(p_current_start)))\r\n\t\t{\r\n\t\t\tp_new_end = p_current_start;\r\n\t\t\tp_new_start = p_current_start->GetPrevLink();\r\n\t\t\t// MESSAGE(\"FOUND CONNECTING RAIL\");\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\t\r\n\t\t// look for another node who's position corresponds to the current start node\r\n\t\tif (!mp_rail_manager->CheckForCoincidentRailNode(p_current_start, nBit(NO_CLIMBING) | nBit(LADDER), &next_rail_node))\r\n\t\t{\r\n\t\t\t// MESSAGE(\"NO COINCIDENT RAIL\");\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// look for a connection\r\n\t\tif (p_current_end->GetNextLink() && p_current_end->IsActive() && !p_current_end->GetFlag(NO_CLIMBING)\r\n\t\t\t&& Rail_ValidInEditor(mp_rail_manager->GetPos(p_current_end), mp_rail_manager->GetPos(p_current_end->GetNextLink())))\r\n\t\t{\r\n\t\t\tp_new_start = p_current_end;\r\n\t\t\tp_new_end = p_current_end->GetNextLink();\r\n\t\t\t// MESSAGE(\"FOUND CONNECTING RAIL\");\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\t\r\n\t\t// look for another node who's position corresponds a given node's position\r\n\t\tif (!mp_rail_manager->CheckForCoincidentRailNode(p_current_end, nBit(NO_CLIMBING) | nBit(LADDER), &next_rail_node))\r\n\t\t{\r\n\t\t\t// MESSAGE(\"NO COINCIDENT RAIL\");\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\r\n\tDbg_Assert(next_rail_node && next_rail_node->GetNextLink());\r\n\t\r\n\tbool rails_are_flush = mp_rail_manager->RailNodesAreCoincident(next_rail_node, p_current_end)\r\n\t\t|| mp_rail_manager->RailNodesAreCoincident(next_rail_node->GetNextLink(), p_current_start);\r\n    \r\n\tMth::Vector old_rail_dir = (mp_rail_manager->GetPos(p_current_end) - mp_rail_manager->GetPos(p_current_start)).Normalize();\r\n\tMth::Vector new_rail_dir = (mp_rail_manager->GetPos(next_rail_node->GetNextLink()) - mp_rail_manager->GetPos(next_rail_node)).Normalize();\r\n\tif (!rails_are_flush)\r\n\t{\r\n\t\tnew_rail_dir *= -1.0f;\r\n\t}\r\n\tif (Mth::DotProduct(old_rail_dir, new_rail_dir) < -0.866f)\r\n\t{\r\n\t\tMESSAGE(\"BAD ANGLE ON COINCIDENT RAIL\");\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tif (!rails_are_flush)\r\n\t{\r\n\t\talong_rail_factor = 1.0f - along_rail_factor;\r\n\t}\r\n\tp_new_start = next_rail_node;\r\n\tp_new_end = next_rail_node->GetNextLink();\r\n\tMESSAGE(\"FOUND COINCIDENT RAIL\");\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::maybe_pull_up_from_hang ( Mth::Vector& proposed_stand_pos )\r\n{\r\n\t// check to see if there's a good place for us to stand if we pull up; if so, do so\r\n\t\r\n\tMth::Vector stand_pos;\r\n\t\r\n\tCFeeler potential_ground_feeler;\r\n\tbool ground = determine_stand_pos(proposed_stand_pos, stand_pos, potential_ground_feeler);\r\n\t\r\n\tif (!ground)\r\n\t{\r\n\t\tMth::Vector initial_stand_pos = stand_pos;\r\n\t\tMth::Vector left(-m_facing[Z], 0.0f, m_facing[X]);\r\n\t\t\r\n\t\t// if we couldn't find the ground, we may be at the end of a rail which hangs over the geo; look for stand positions to the left and right\r\n\t\tconst float SIDEWAYS_SEARCH_DISTANCE = 12.0f;\r\n\t\tproposed_stand_pos += SIDEWAYS_SEARCH_DISTANCE * left;\r\n\t\tground = determine_stand_pos(proposed_stand_pos, stand_pos, potential_ground_feeler);\r\n\t\tif (!ground)\r\n\t\t{\r\n\t\t\tproposed_stand_pos -= (2.0f * SIDEWAYS_SEARCH_DISTANCE) * left;\r\n\t\t\tground = determine_stand_pos(proposed_stand_pos, stand_pos, potential_ground_feeler);\r\n\t\t\tif (!ground)\r\n\t\t\t{\r\n\t\t\t\tstand_pos = initial_stand_pos;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// check for walls around the standing position\r\n\tCFeeler feeler;\r\n\tfloat push_feeler_length = 0.5f * s_get_param(CRCD(0xa20c43b7, \"push_feeler_length\"));\r\n\tfloat feeler_height = s_get_param(CRCD(0x6da7f696, \"feeler_height\"));\r\n\tfor (int n = 0; n < vNUM_FEELERS; n++)\r\n\t{\r\n\t\tfloat angle = n * (2.0f * Mth::PI / vNUM_FEELERS);\r\n\t\t\r\n\t\tfloat cos_angle = cosf(angle);\r\n\t\tfloat sin_angle = sinf(angle);\r\n\t\t\r\n\t\tMth::Vector end_offset;\r\n\t\tend_offset[X] = cos_angle * m_facing[X] - sin_angle * m_facing[Z];\r\n\t\tend_offset[Y] = 0.0f;\r\n\t\tend_offset[Z] = sin_angle * m_facing[X] + cos_angle * m_facing[Z];\r\n\t\tend_offset[W] = 1.0f;\r\n\t\tend_offset *= push_feeler_length;\r\n\t\t\r\n\t\tfeeler.m_start = stand_pos;\r\n\t\tfeeler.m_start[Y] += feeler_height;\r\n\t\tfeeler.m_end = stand_pos + end_offset;\r\n\t\tfeeler.m_end[Y] += feeler_height;\r\n\t\t\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(0, 255, 255, 0);\r\n\t\t}\r\n\t\t#endif\r\n\t\tif (feeler.GetCollision()) return false;\r\n\t}\r\n\t\r\n\t// check line from hang point to standing position for obstructions\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_start += -6.0f * m_facing;\r\n\tfeeler.m_start[Y] += s_get_param(CRCD(0xa8c13e74, \"hang_vert_origin_offset\")) + s_get_param(CRCD(0x9b2818cf, \"pull_up_obstruction_height\"));\r\n\tfeeler.m_end = stand_pos;\r\n\tfeeler.m_end[Y] += 1.0f;\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t\t{\r\n\t\t\tfeeler.DebugLine(0, 100, 100, 0);\r\n\t\t}\r\n\t\t#endif\r\n\t\treturn false;\r\n\t}\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(100, 0, 100, 0);\r\n\t}\r\n\t#endif\r\n\t\r\n\t// pull up looks ok, so let's do it\r\n\t\r\n\tif (ground)\r\n\t{\r\n\t\tmp_anim_wait_complete_callback = &Obj::CWalkComponent::pull_up_from_hang_to_ground_complete;\r\n\t\t\r\n\t\tm_last_ground_feeler = potential_ground_feeler;\r\n\t\tm_last_ground_feeler_valid = true;\r\n\t\tm_ground_normal = potential_ground_feeler.GetNormal();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_anim_wait_complete_callback = &Obj::CWalkComponent::pull_up_from_hang_to_air_complete;\r\n\t}\r\n\t\r\n\tm_anim_wait_initial_pos = m_pos;\r\n\tm_anim_wait_goal_pos = stand_pos;\r\n\r\n\tcalculate_anim_wait_facing_drift_parameters(m_facing);\r\n\t\r\n\tm_anim_wait_camera_mode = AWC_GOAL;\r\n\t\r\n\tm_drift_initial_display_offset = m_display_offset;\r\n\tm_drift_goal_display_offset = 0.0f;\r\n\t\t\t\t\t\t \t\r\n\tm_critical_point_offset = -(6.0f + s_get_param(CRCD(0x21dfbe77, \"pull_up_offset_forward\"))) * m_facing;\r\n\tm_critical_point_offset[Y] = 1.0f;\r\n\t\r\n\t// setup the false wall incase the player jumps out of the animation wait\r\n\tm_false_wall.normal = m_facing;\r\n\tm_false_wall.cancel_height = m_pos[Y] - m_vertical_hang_offset;\r\n\r\n\tset_state(WALKING_ANIMWAIT);\r\n\r\n\tm_frame_event = CRCD(0x9ef9f8f1, \"PullUpFromHang\");\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::pull_up_from_hang_to_ground_complete (   )\r\n{\r\n    set_state(WALKING_GROUND);\r\n\t\r\n\tif (m_last_ground_feeler_valid)\r\n\t{\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_ONTO, m_last_ground_feeler);\r\n\r\n\t\t// check for a moving contact\r\n\t\tmp_movable_contact_component->CheckForMovableContact(m_last_ground_feeler);\r\n\t}\r\n\t\r\n\tm_critical_point_offset.Set();\r\n\t\r\n\tm_display_offset = m_drift_goal_display_offset;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::pull_up_from_hang_to_air_complete (   )\r\n{\r\n    set_state(WALKING_AIR);\r\n\t\r\n\tm_primary_air_direction = m_facing;\r\n\tleave_movable_contact_for_air(m_horizontal_vel, m_vertical_vel);\r\n\t\r\n\tm_display_offset = m_drift_goal_display_offset;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CWalkComponent::get_hang_display_offset (   )\r\n{\r\n    if (mp_model_component->GetModel()->IsScalingEnabled())\r\n\t{\r\n\t\treturn (1.0f - mp_model_component->GetModel()->GetScale()[Y]) * s_get_param(CRCD(0xa8c13e74, \"hang_vert_origin_offset\"));\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 0.0f;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CWalkComponent::get_hang_critical_point_vert_offset (   )\r\n{\r\n\treturn s_get_param(CRCD(0xde86132e, \"hang_critical_point_vert_offset\"))\r\n\t\t- s_get_param(CRCD(0x7201ad48, \"max_cas_scaling\")) * s_get_param(CRCD(0xa8c13e74, \"hang_vert_origin_offset\"));\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/WalkLadderUtil.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       WalkLadderUtil.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  4/29/3\r\n//****************************************************************************\r\n\r\n#include <gel/components/walkcomponent.h>\r\n#include <gel/components/triggercomponent.h>\r\n#include <gel/components/movablecontactcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <sk/objects/rail.h>\r\n#include <sk/engine/feeler.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n\r\n// NOTE: The ladder walking code currently ignores movable rail managers!\r\n                 \r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::maybe_climb_up_ladder ( bool user_requested )\r\n{\r\n\t// check to see if we're in a bail\r\n\tif (mp_core_physics_component->GetFlag(IS_BAILING)) return false;\r\n\t\r\n\tSLadderRailData rail_data;\r\n\r\n\t// Check for appropriate rails.\r\n    if (!Mdl::Skate::Instance()->GetRailManager()->CheckForLadderRail(\r\n        m_pos,\r\n        user_requested ? s_get_param(CRCD(0xeecd255, \"button_horiz_snap_distance\")) : s_get_param(CRCD(0xa2735dd9, \"max_horiz_snap_distance\")),\r\n        s_get_param(CRCD(0xc4c164e8, \"max_vert_snap_distance\")),\r\n\t\ttrue,\r\n        this,\r\n        rail_data,\r\n        &mp_rail_start\r\n    )) return false;\r\n\t\r\n\t// store the relevant rail manager\r\n\tmp_rail_manager = Mdl::Skate::Instance()->GetRailManager();\r\n\tmp_movable_contact_component->LoseAnyContact();\r\n\t\r\n\t// zero velocities\t\r\n\tm_vertical_vel = 0.0f;\r\n\tm_horizontal_vel.Set();\r\n    \r\n    // setup an anim wait state\r\n\t\r\n\tm_anim_wait_initial_pos = m_pos;\r\n\tm_anim_wait_goal_pos = rail_data.climb_point;\r\n\t\r\n    mp_anim_wait_complete_callback = &Obj::CWalkComponent::move_to_ladder_bottom_complete;\r\n\t\r\n\tm_drift_initial_display_offset = m_display_offset;\r\n\tm_drift_goal_display_offset = 0.0f;\r\n\t\r\n\tcalculate_anim_wait_facing_drift_parameters(rail_data.climb_facing);\r\n\t\r\n\tm_anim_wait_camera_mode = AWC_GOAL;\r\n\t\t  \t\r\n\t// setup the false wall incase the player jumps out of the animation wait\r\n\tm_false_wall.normal = rail_data.climb_facing;\r\n\tm_false_wall.cancel_height = rail_data.climb_point[Y];\r\n\r\n\tset_state(WALKING_ANIMWAIT);\r\n\r\n\tm_frame_event = CRCD(0xe2524194, \"LadderOntoBottom\");\r\n    \r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::maybe_climb_down_ladder (   )\r\n{\r\n   \t// check to see if we're in a bail\r\n\tif (mp_core_physics_component->GetFlag(IS_BAILING)) return false;\r\n\t\r\n    SLadderRailData rail_data;\r\n    \r\n\t// Check for appropriate rails.\r\n    if (!Mdl::Skate::Instance()->GetRailManager()->CheckForLadderRail(\r\n        m_pos,\r\n        s_get_param(CRCD(0xa2735dd9, \"max_horiz_snap_distance\")),\r\n        s_get_param(CRCD(0xc4c164e8, \"max_vert_snap_distance\")),\r\n\t\tfalse,\r\n        this,\r\n        rail_data,\r\n        &mp_rail_start\r\n    )) return false;\r\n\t\r\n\t// store the relevant rail manager\r\n\tmp_rail_manager = Mdl::Skate::Instance()->GetRailManager();\r\n\tmp_movable_contact_component->LoseAnyContact();\r\n\t\r\n\t// zero velocities\t\r\n\tm_vertical_vel = 0.0f;\r\n\tm_horizontal_vel.Set();\r\n\t\r\n    // setup an anim wait state\r\n\t\r\n\tm_anim_wait_initial_pos = m_pos;\r\n\tm_anim_wait_goal_pos = rail_data.climb_point;\r\n\t\r\n    mp_anim_wait_complete_callback = &Obj::CWalkComponent::move_to_ladder_top_complete;\r\n\t\r\n\tm_drift_initial_display_offset = m_display_offset;\r\n\tm_drift_goal_display_offset = 0.0f;\r\n\t\r\n\tcalculate_anim_wait_facing_drift_parameters(rail_data.climb_facing);\r\n\t\r\n\t// if (Mth::DotProduct(mp_camera->GetMatrix()[Z], m_facing) > 0.0f)\r\n\t// {\r\n\t\tm_anim_wait_camera_mode = AWC_GOAL;\r\n\t// }\r\n\t// else\r\n\t// {\r\n\t\t// m_anim_wait_camera_mode = AWC_CURRENT;\r\n\t// }\r\n\t   \t\t  \t\r\n\t// setup the false wall incase the player jumps out of the animation wait\r\n\tm_false_wall.normal = rail_data.climb_facing;\r\n\tm_false_wall.cancel_height = m_pos[Y];\r\n\r\n\tset_state(WALKING_ANIMWAIT);\r\n\r\n\tm_frame_event = CRCD(0xd63adcad, \"LadderOntoTop\");\r\n    \r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::maybe_grab_to_ladder ( const Mth::Vector& start_pos, const Mth::Vector& end_pos )\r\n{\r\n    SLadderRailData rail_data;\r\n\t\r\n\t// Check for appropriate rails.\r\n    if (!Mdl::Skate::Instance()->GetRailManager()->CheckForAirGrabLadderRail(\r\n\t\tstart_pos,\r\n\t\tend_pos,\r\n\t\tthis,\r\n\t\trail_data,\r\n\t\t&mp_rail_start\r\n    )) return false;\r\n\t\r\n\t// store the relevant rail manager\r\n\tmp_rail_manager = Mdl::Skate::Instance()->GetRailManager();\r\n\tmp_movable_contact_component->LoseAnyContact();\r\n\t\r\n\t// we've found a rail to climb\r\n\tm_pos = rail_data.climb_point;\r\n\tDUMP_WPOSITION\r\n\tm_facing = rail_data.climb_facing;\r\n\tm_along_rail_factor = rail_data.along_rail_factor;\r\n\t\r\n\t// zero velocities\t\r\n\tm_vertical_vel = 0.0f;\r\n\tm_horizontal_vel.Set();\r\n\t\r\n\tset_state(WALKING_LADDER);\r\n\r\n\tm_frame_event = CRCD(0xc84243da, \"Ladder\");\r\n    \r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::move_to_ladder_bottom_complete (   )\r\n{\r\n\t// getting on at the bottom of the ladder\r\n\t\r\n\t// determine top node\r\n\tconst CRailNode* p_top_rail_node = mp_rail_start->GetNextLink() ? mp_rail_start->GetNextLink() : mp_rail_start->GetPrevLink();\r\n\tDbg_Assert(p_top_rail_node);\r\n\t\t\r\n\t// the offset from the ladder bottom to rail top\r\n\tMth::Vector rail = mp_rail_manager->GetPos(p_top_rail_node) - mp_rail_manager->GetPos(mp_rail_start);\r\n\tfloat rail_length = rail.Length();\r\n\t\r\n\t// calculate initial positoin along rail\r\n\tm_along_rail_factor = s_get_param(CRCD(0x5296e3fd, \"ladder_bottom_offset_up\")) / rail_length;\r\n\t\r\n    set_state(WALKING_LADDER);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::move_to_ladder_top_complete (   )\r\n{\r\n\t// getting on at the top of the ladder\r\n\t\r\n\t// determine top node\r\n\tconst CRailNode* p_top_rail_node = mp_rail_start->GetNextLink() ? mp_rail_start->GetNextLink() : mp_rail_start->GetPrevLink();\r\n\tDbg_Assert(p_top_rail_node);\r\n\t\t\r\n\t// the offset from the ladder bottom to rail top\r\n\tMth::Vector rail = mp_rail_manager->GetPos(p_top_rail_node) - mp_rail_manager->GetPos(mp_rail_start);\r\n\tfloat rail_length = rail.Length();\r\n\t\r\n\t// calculate initial positoin along rail\r\n\tm_along_rail_factor = (rail_length - s_get_param(CRCD(0x76bf49e0, \"ladder_top_offset_up\"))) / rail_length;\r\n\t\r\n    set_state(WALKING_LADDER);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::FilterLadderUpRail ( const Mth::Vector& bottom_pos, const Mth::Vector& top_pos, const Mth::Matrix& orientation, SLadderRailData& rail_data )\r\n{\r\n    // check that we're at the bottom of the ladder\r\n    if (bottom_pos[Y] > top_pos[Y]) return false;\r\n    \r\n    // check that the proposed ladder rail is vertical\r\n    Mth::Vector ladder_direction = top_pos - bottom_pos;\r\n    ladder_direction.Normalize();\r\n    if (ladder_direction[Y] < 0.995f) return false;\r\n\t\r\n\t// check that we're facing the ladder\r\n\tif (Mth::DotProduct(m_facing, orientation[Z]) < cosf(Mth::DegToRad(s_get_param(CRCD(0x456f216d, \"max_onto_ladder_angle\"))))) return false;\r\n    \r\n    // calculate the climb position\r\n    rail_data.climb_point = bottom_pos + ladder_direction * s_get_param(CRCD(0x5296e3fd, \"ladder_bottom_offset_up\"));\r\n\trail_data.climb_point -= s_get_param(CRCD(0x35b3bbda, \"ladder_climb_offset\")) * orientation[Z];\r\n    \r\n    // send feeler to climb position\r\n    CFeeler feeler;\r\n    feeler.m_start = m_pos;\r\n    feeler.m_end = rail_data.climb_point - 6.0f * orientation[Z];\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(0, 0, 255, 0);\r\n\t}\r\n\t#endif\r\n    if (feeler.GetCollision()) return false;\r\n    \r\n    // store the climb facing\r\n    rail_data.climb_facing = orientation[Z];\r\n    \r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::FilterLadderDownRail ( const Mth::Vector& bottom_pos, const Mth::Vector& top_pos, const Mth::Matrix& orientation, SLadderRailData& rail_data )\r\n{\r\n    // check that we're at the top of the ladder\r\n    if (bottom_pos[Y] > top_pos[Y]) return false;\r\n    \r\n    // check that the proposed ladder rail is vertical\r\n    Mth::Vector ladder_direction = top_pos - bottom_pos;\r\n    ladder_direction.Normalize();\r\n    if (ladder_direction[Y] < 0.995f) return false;\r\n    \r\n    // calculate the climb position\r\n    rail_data.climb_point = top_pos - ladder_direction * s_get_param(CRCD(0x76bf49e0, \"ladder_top_offset_up\"));\r\n\trail_data.climb_point -= s_get_param(CRCD(0x35b3bbda, \"ladder_climb_offset\")) * orientation[Z];\r\n    \r\n\t/*\r\n    // send feeler to climb position\r\n    CFeeler feeler;\r\n    feeler.m_start = m_pos;\r\n    feeler.m_end = rail_data.climb_point - 6.0f * orientation[Z];\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(0, 0, 255, 0);\r\n\t}\r\n\t#endif\r\n    if (feeler.GetCollision()) return false;\r\n\t*/\r\n    \r\n    // store the climb facing\r\n    rail_data.climb_facing = orientation[Z];\r\n    \r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWalkComponent::FilterLadderAirGrabRail ( const Mth::Vector& bottom_pos, const Mth::Vector& top_pos, const Mth::Matrix& orientation, const Mth::Vector& preliminary_climb_point, float along_rail_factor, SLadderRailData& rail_data )\r\n{\r\n    // check that the proposed ladder rail is vertical\r\n    Mth::Vector ladder_direction = top_pos - bottom_pos;\r\n    ladder_direction.Normalize();\r\n    if (ladder_direction[Y] < 0.995f) return false;\r\n\t\r\n\t// insure that the target point on the ladder is above the climb off bottom point\r\n    float off_bottom_height = bottom_pos[Y] + ladder_direction[Y] * s_get_param(CRCD(0x5296e3fd, \"ladder_bottom_offset_up\"));\r\n\tif (preliminary_climb_point[Y] < off_bottom_height) return false;\r\n\t\r\n\t// insure that the target point on the ladder is below the climb off top point\r\n    float off_top_height = top_pos[Y] - ladder_direction[Y] * s_get_param(CRCD(0x76bf49e0, \"ladder_top_offset_up\"));\r\n\tif (preliminary_climb_point[Y] > off_top_height) return false;\r\n\t\r\n\t// move the climb point a touch back off the rail\r\n\trail_data.climb_point = preliminary_climb_point - s_get_param(CRCD(0x35b3bbda, \"ladder_climb_offset\")) * orientation[Z];\r\n\t\r\n\t// send a feeler to the climb position\r\n\tCFeeler feeler;\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_end = rail_data.climb_point;\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0xaf90c5fd, \"walking_debug_lines\")))\r\n\t{\r\n\t\tfeeler.DebugLine(0, 0, 255, 0);\r\n\t}\r\n\t#endif\r\n    if (feeler.GetCollision()) return false;\r\n\t\r\n\t// store the climb facing\r\n\trail_data.climb_facing = orientation[Z];\r\n\t\r\n\trail_data.along_rail_factor = along_rail_factor;\r\n\t\r\n\tmp_core_physics_component->SetFlagTrue(SNAPPED);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::go_ladder_state (   )\r\n{\r\n\tif (Mth::Abs((Mth::PI / 2.0f) - Mth::Abs(mp_input_component->GetControlPad().m_leftAngle)) > cosf(Mth::DegToRad(s_get_param(CRCD(0x7ee1b95b, \"ladder_control_tolerance\")))))\r\n\t{\r\n\t\tladder_movement();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tm_frame_event = CRCD(0xc84243da, \"Ladder\");\r\n\tm_anim_effective_speed = 0.0f;\r\n\treturn;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::ladder_movement (   )\r\n{\r\n\t// movement up and down the ladder\r\n\t\r\n\t// the desired speed; this will be used to scale the animation speed\r\n\tm_anim_effective_speed = s_get_param(CRCD(0xab2db54, \"ladder_move_speed\")) * m_control_magnitude * cosf(mp_input_component->GetControlPad().m_leftAngle);\r\n\t\r\n\t// the movement this frame\r\n\tfloat movement = m_anim_effective_speed * m_frame_length;\r\n\t\r\n\t// get the top rail node; mp_rail_start is always the bottom node\r\n\tconst CRailNode* p_top_rail_node = mp_rail_start->GetNextLink() ? mp_rail_start->GetNextLink() : mp_rail_start->GetPrevLink();\r\n\tDbg_Assert(p_top_rail_node);\r\n\t\t\r\n\t// the offset from the ladder bottom to rail top\r\n\tMth::Vector rail = mp_rail_manager->GetPos(p_top_rail_node) - mp_rail_manager->GetPos(mp_rail_start);\r\n\tDbg_MsgAssert(rail.Length() > s_get_param(CRCD(0x76bf49e0, \"ladder_top_offset_up\")), (\"Ladder too short for ladder animations\"));\r\n\t\r\n\t// the movement in terms of the fraction of the rail\r\n\tfloat delta_factor = movement / rail.Length();\r\n\t\r\n\t// movement is up or down\r\n\tbool up = delta_factor > 0.0f;\r\n\t\r\n\t// move along the rail\r\n\tm_along_rail_factor += delta_factor;\r\n\t\r\n\tfloat rail_length = rail.Length();\r\n\t\r\n\t// see if we've hit the bottom\r\n\tfloat bottom_along_rail_factor = s_get_param(CRCD(0x5296e3fd, \"ladder_bottom_offset_up\")) / rail_length;\r\n\tif (m_along_rail_factor < bottom_along_rail_factor)\r\n\t{\r\n\t\toff_ladder_bottom();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// see if we've hit the top\r\n\tfloat top_along_rail_factor = (rail_length - s_get_param(CRCD(0x76bf49e0, \"ladder_top_offset_up\"))) / rail_length;\r\n\tif (m_along_rail_factor > top_along_rail_factor)\r\n\t{\r\n\t\t// we've hit the top\r\n\t\toff_ladder_top();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// still clamp for now\r\n\tm_along_rail_factor = Mth::Clamp(m_along_rail_factor, 0.0f, 1.0f);\r\n\t\r\n\tif (m_along_rail_factor == 0.0f || m_along_rail_factor == 1.0f)\r\n\t{\r\n\t\tm_frame_event = CRCD(0xc84243da, \"Ladder\");\r\n\t\tm_anim_effective_speed = 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_frame_event = up ? CRCD(0xaf5abc82, \"LadderMoveUp\") : CRCD(0xfec9dded, \"LadderMoveDown\");\r\n\t}\r\n\t\r\n\t// calculate our new position\r\n\tm_pos = mp_rail_manager->GetPos(mp_rail_start) + m_along_rail_factor * rail - s_get_param(CRCD(0x35b3bbda, \"ladder_climb_offset\")) * m_facing;\r\n\tDUMP_WPOSITION\r\n\t\r\n\t// positive animation speed\r\n\tm_anim_effective_speed = Mth::Abs(m_anim_effective_speed);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::off_ladder_bottom (   )\r\n{\r\n\tMth::Vector stand_pos = m_pos - s_get_param(CRCD(0xcaf2831b, \"ladder_bottom_offset_forward\")) * m_facing;\r\n\tstand_pos[Y] -= s_get_param(CRCD(0x5296e3fd, \"ladder_bottom_offset_up\"));\r\n\tm_last_ground_feeler_valid = determine_stand_pos(stand_pos, stand_pos, m_last_ground_feeler);\r\n\t\r\n\tif (m_last_ground_feeler_valid)\r\n\t{\r\n\t\tm_ground_normal = m_last_ground_feeler.GetNormal();\r\n\t}\r\n\t\r\n    // setup an anim wait state\r\n\t\r\n\tm_anim_wait_initial_pos = m_pos;\r\n\tm_anim_wait_goal_pos = stand_pos;\r\n\t\r\n    mp_anim_wait_complete_callback = &Obj::CWalkComponent::off_ladder_bottom_complete;\r\n\t\r\n\tm_drift_initial_display_offset = m_display_offset;\r\n\tm_drift_goal_display_offset = 0.0f;\r\n\t\r\n\tcalculate_anim_wait_facing_drift_parameters(m_facing);\r\n\t\r\n\tm_anim_wait_camera_mode = AWC_GOAL;\r\n\t   \t\t  \t\r\n\t// setup the false wall incase the player jumps out of the animation wait\r\n\tm_false_wall.normal = m_facing;\r\n\tm_false_wall.cancel_height = m_pos[Y];\r\n\r\n\tset_state(WALKING_ANIMWAIT);\r\n\r\n\tm_frame_event = CRCD(0x4db1bbb1, \"LadderOffBottom\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::off_ladder_bottom_complete (   )\r\n{\r\n    set_state(WALKING_GROUND);\r\n\t\r\n\tif (m_last_ground_feeler_valid)\r\n\t{\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_ONTO, m_last_ground_feeler);\r\n\r\n\t\t// check for a moving contact\r\n\t\tmp_movable_contact_component->CheckForMovableContact(m_last_ground_feeler);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::off_ladder_top (   )\r\n{\r\n\t// determine goal position\r\n\t\r\n\tMth::Vector stand_pos = m_pos + s_get_param(CRCD(0xb620b580, \"ladder_top_offset_forward\")) * m_facing; \r\n\tstand_pos[Y] += s_get_param(CRCD(0x76bf49e0, \"ladder_top_offset_up\"));\r\n\t\r\n\tCFeeler potential_ground_feeler;\r\n\tbool ground = determine_stand_pos(stand_pos, stand_pos, potential_ground_feeler);\r\n\r\n\t// setup an anim wait state\r\n\t\r\n\tm_anim_wait_initial_pos = m_pos;\r\n\tm_anim_wait_goal_pos = stand_pos;\r\n\t\r\n\tif (ground)\r\n\t{\r\n        mp_anim_wait_complete_callback = &Obj::CWalkComponent::off_ladder_top_to_ground_complete;\r\n\t\t\r\n\t\tm_last_ground_feeler = potential_ground_feeler;\r\n\t\tm_last_ground_feeler_valid = true;\r\n\t\tm_ground_normal = m_last_ground_feeler.GetNormal();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_anim_wait_complete_callback = &Obj::CWalkComponent::off_ladder_top_to_air_complete;\r\n\t}\r\n\t\r\n\tm_drift_initial_display_offset = m_display_offset;\r\n\tm_drift_goal_display_offset = 0.0f;\r\n\t\r\n\tcalculate_anim_wait_facing_drift_parameters(m_facing);\r\n\t\r\n\tm_anim_wait_camera_mode = AWC_GOAL;\r\n\t   \t\t  \t\r\n\t// setup the false wall incase the player jumps out of the animation wait\r\n\tm_false_wall.normal = m_facing;\r\n\tm_false_wall.cancel_height = stand_pos[Y];\r\n\t\r\n\tset_state(WALKING_ANIMWAIT);\r\n\t\r\n\tm_frame_event = CRCD(0x12521bfb, \"LadderOffTop\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::off_ladder_top_to_ground_complete (   )\r\n{\r\n    set_state(WALKING_GROUND);\r\n\t\r\n\tif (m_last_ground_feeler_valid)\r\n\t{\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_ONTO, m_last_ground_feeler);\r\n\r\n\t\t// check for a moving contact\r\n\t\tmp_movable_contact_component->CheckForMovableContact(m_last_ground_feeler);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWalkComponent::off_ladder_top_to_air_complete (   )\r\n{\r\n    set_state(WALKING_AIR);\r\n\t\r\n\tm_primary_air_direction = m_facing;\r\n\tleave_movable_contact_for_air(m_horizontal_vel, m_vertical_vel);\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/animationcomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       AnimationComponent.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/24/2002\r\n//****************************************************************************\r\n\r\n#include <gel/components/animationcomponent.h>\r\n\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n#include <gel/components/suspendcomponent.h>\r\n\r\n// TODO:  All the network code should\r\n// be at the skater- or the player- level\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/component.h>\r\n\r\n#include <gfx/baseanimcontroller.h>\r\n#include <gfx/bonedanim.h>\r\n#include <gfx/gfxutils.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxanimcache.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/pose.h>\r\n#include <gfx/skeleton.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n\t\t  \r\nnamespace Obj\r\n{\r\n\textern bool DebugSkaterScripts;\r\n\t\r\n\t// if the animation time increment is too small,\r\n\t// then ignore it...\r\n\tconst float vMIN_SPEED_THRESHOLD = 0.05f;\r\n\r\n\t#define nxANIMCOMPONENTFLAGS_FLIPPED\t\t\t\t(1<<29)\r\n\t\r\n\t// maximum number of degenerate animations\r\n\tconst int vNUM_DEGENERATE_ANIMS = 3;\r\n\r\n\t// maximum number of procedural bones\r\n\tconst int vMAXPROCEDURALBONES = 12;\r\n\t\r\n\tstatic bool s_updating_channels = false;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// This static function is what is registered with the component\r\n// factory object, (currently the CCompositeObjectManager) \r\nCBaseComponent* CAnimationComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CAnimationComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCAnimationComponent::CAnimationComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_ANIMATION );\r\n\r\n\tm_animScriptName = 0;\r\n\tm_animEventTableName = 0;\r\n\r\n\tm_shouldBlend = false;\r\n\r\n\tReset();\r\n\r\n\tm_numProceduralBones = 0;\r\n\r\n\tmp_proceduralBones = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCAnimationComponent::~CAnimationComponent()\r\n{\r\n\tdestroy_blend_channels();\r\n\t\r\n\tif ( mp_proceduralBones )\r\n\t{\r\n\t\tdelete[] mp_proceduralBones;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::Reset()\r\n{\r\n\t// stops all the animations...\r\n\tdestroy_blend_channels();\r\n\r\n\t// resets \"global\" blend parameters\r\n\tmGotBlendPeriodOut = false;\r\n\tmBlendPeriodOut = 0.0f;\r\n\t\r\n\t// reset script animation waits\r\n\tif (m_animation_script_block_active)\r\n\t{\r\n\t\tm_animation_script_block_active = false;\r\n\t\tif (GetObject()->GetScript())\r\n\t\t{\r\n\t\t\tGetObject()->GetScript()->UnBlock();\r\n\t\t}\r\n\t}\r\n\tm_animation_script_unblock_point = 0;\r\n\t\r\n\t// reset animation frame count\r\n\tm_last_animation_time = 0.0f;\r\n\t\r\n\tm_dont_interrupt=false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::SetAnims( uint32 anim_checksum )\r\n{\r\n    m_animScriptName = anim_checksum;\r\n\r\n\tPlayPrimarySequence( 0, false, 0.0f, 1000.0f, Gfx::LOOPING_HOLD, 0.3f, 1.0f );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CAnimationComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tDbg_Assert( pParams );\r\n\r\n\tpParams->GetChecksum( CRCD(0x5b8c6dc2,\"animEventTableName\"), &m_animEventTableName, false );\r\n\r\n\tuint32 animScriptName;\r\n\r\n\tif ( pParams->GetChecksum( CRCD(0x6c2bfb7f,\"animName\"), &animScriptName, false ) )\r\n\t{\r\n\t\tSetAnims( animScriptName );\r\n\t\tReset();\r\n\r\n\t\t// safety-check to make sure he doesn't start out in the blair witch position\r\n\t\t// (because of our animation LOD-ing system)\r\n\t\t// this must be done before the models get initialized?\r\n\t\tuint32 defaultAnimName;\r\n\t\tif ( pParams->GetChecksum( CRCD(0xeae64b47,\"defaultAnimName\"), &defaultAnimName, false ) )\r\n\t\t{\r\n\t\t\tPlaySequence(defaultAnimName);\r\n\t\t\tSetLoopingType( Gfx::LOOPING_CYCLE, true );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// generally, the blair witch position\r\n\t\t\tPlaySequence( CRCD(0x1ca1ff20,\"default\") );\r\n\t\t}\r\n\t}\r\n\r\n\t// if it's the local skater, then give it some procedural animation as well\r\n\t// (the decision to do this should really be coming from a higher-level...)\r\n \tif ( GetObject()->GetID() == 0 )\r\n\t{\r\n\t\tDbg_MsgAssert( mp_proceduralBones == NULL, ( \"Already has procedural bones!\" ) );\r\n\t\tmp_proceduralBones = new Gfx::CProceduralBone[vMAXPROCEDURALBONES];\r\n\r\n\t\tScript::CStruct* pTempParams = new Script::CStruct;\r\n\t\tpTempParams->AppendStructure( pParams );\r\n\r\n\t\tpTempParams->AddChecksum( CRCD(0x7321a8d6,\"type\"), CRCD(0xfdf0436c,\"ProceduralAnim\") );\r\n\t\tpTempParams->AddChecksum( CRCD(0x3ed7262b,\"bone_list\"), CRCD(0x5d5c0e72,\"procedural_skater_bones\") );\r\n\t\t\r\n\t\tinitialize_procedural_bones( pTempParams );\r\n\r\n\t\tdelete pTempParams;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::ToggleFlipState( void )\t\t\t\t\t\t\t\t   \r\n{\r\n\t// Flip the animation to the correct orientation\r\n\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\tNet::Client* client = gamenet_man->GetClient( 0 );\r\n\tthis->FlipAnimation( GetObject()->GetID(), !IsFlipped(), client->m_Timestamp, true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CAnimationComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n    switch ( Checksum )\r\n    {        \r\n        // @script | Obj_EnableAnimBlending | \r\n        // @parm name | enabled | whether the anim blending should be enabled\r\n\t\t// peds should disable blending, as a speed optimization\r\n\t\tcase 0x98a32669:\t// Obj_EnableAnimBlending\r\n\t\t{\r\n\t\t\tint shouldBlend;\r\n\t\t\tpParams->GetInteger( CRCD(0xaf06447b,\"enabled\"), &shouldBlend, Script::ASSERT );\r\n\t\t\tEnableBlending( shouldBlend );\r\n\t\t}\r\n\t\tbreak;\r\n        \r\n\t\t// @script | Obj_SetAnimCycleMode | \r\n        // @flag off | turn cycle off (otherwise it will turn it on)\r\n\t\tcase 0x58c52f64:\t// Obj_SetAnimCycleMode\r\n        {\r\n           if ( pParams->ContainsFlag( CRCD(0xd443a2bc,\"off\") ) )\r\n           {\r\n               SetLoopingType( Gfx::LOOPING_HOLD, true );\r\n           }\r\n           else\r\n           {\r\n               // maybe we should clear the cycle time or num loops?\r\n               // or should we leave it at whatever was set before?  hmmm...\r\n               SetLoopingType( Gfx::LOOPING_CYCLE, true );\r\n           }\r\n        }\r\n        break;\r\n\r\n        // @script | Obj_PlayAnim | \r\n        // @parm name | Anim | animation to play\r\n        // @flag wobble | enable wobble\r\n        // @parmopt float | BlendPeriod | 0.3f | blend period (default may change)\r\n        // @parmopt int | BlendPeriodPercent | | blend period as a percentage of the anim length (20 means \"20 percent\")\r\n        // @parmopt float | speed | 1.0 | \r\n        // @flag NoRestart | \r\n        // @flag Cycle | \r\n        // @flag PingPong | \r\n        // @flag Wobble | \r\n        // @flag DontInterrupt | Makes further PlayAnims have no effect until the current\r\n\t\t// animation has finished.\r\n        // @parmopt name | From | | start, end, or current\r\n        // @parmopt int | From | | from can be specified as an int (60ths)\r\n        // @parmopt name | To | | start, end, or current\r\n        // @parmopt int | To | | to can be specified as an int (60ths)\r\n        // @flag Backwards | play animation backwards\r\n\t\tcase 0x2cb9ad09:\t// Obj_PlayAnim\r\n\t\tcase 0x0b1e7291:\t// PlayAnim\r\n        {\r\n\t\t\tPlayAnim( pParams, pScript );\r\n        \r\n\t\t\tGfx::CBlendChannel* pPrimaryChannel = get_primary_channel();\r\n\t\t\tif ( pPrimaryChannel && pPrimaryChannel->GetLoopingType() == Gfx::LOOPING_WOBBLE )\r\n\t\t\t{\r\n\t\t\t\t// the skater balance trick needs to do some extra stuff to\r\n\t\t\t\t// handle wobbles, but needs to do it after the anim has been\r\n\t\t\t\t// launched.  the following gives any component a chance to\r\n\t\t\t\t// handle the wobble first...  if it is not handled by the\r\n\t\t\t\t// time it gets to the animation component, then it's ignored\r\n\t\t\t\t// (this works for the case of the skater balance trick, because\r\n\t\t\t\t// it comes early in the component list)\r\n\t\t\t\tGetObject()->CallMemberFunction( CRCD(0xea6d0efd,\"SetWobbleDetails\"), pParams, pScript );\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0xea6d0efd:\t// SetWobbleDetails\r\n\t\t\t// this is a special case to make sure that the skater balance\r\n\t\t\t// trick component gets a chance to handle wobbles, if such\r\n\t\t\t// a component exists.\r\n\t\t\treturn MF_TRUE;\r\n        \r\n        // @script | Obj_AnimComplete | returns true when the object\r\n        // is done playing an anim.  This is only valid with \"hold on\r\n\t\t// last frame\" animations.\t\r\n\t\tcase 0x2889c6c9:\t// Obj_AnimComplete\r\n\t\tcase 0x76cc99d5: \t// AnimFinished\t\r\n\t\t\treturn ( IsAnimComplete() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_AnimEquals | True if specified animation is\r\n        // the one currently playing on the object, False otherwise\r\n        // @uparmopt name | single animation name to check\r\n        // @uparmopt [] | array of animation names to check\r\n\t\tcase 0xb5fb7eb6:  \t// Obj_AnimEquals\r\n\t\tcase 0x1a0f9646:\t// AnimEquals\r\n\t\t\treturn ( AnimEquals( pParams, pScript ) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_GetAnimSpeed | \r\n        // the one currently playing on the object\r\n        case 0x5195bcbb: // Obj_GetAnimSpeed\r\n        {\r\n            pScript->GetParams()->AddFloat(CRCD(0xf0d90109,\"speed\"), GetAnimSpeed( pParams, pScript ));\r\n        }\r\n        break;\r\n            \r\n        // @script | BlendPeriodOut | next call to playanim will use this blend period\r\n        // no matter what is specified in the actual call to playanim\r\n        // @uparm 1.0 | blend period out value\r\n\t\tcase 0x68c86aec:\t// BlendPeriodOut\t\r\n\t\t{\r\n\t\t\tif (!pParams->GetFloat(NONAME,&mBlendPeriodOut))\r\n            {\r\n\t\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nBlendPeriodOut requires a floating point value\",pScript->GetScriptInfo()));\r\n\t\t\t}\r\n\t\t\t// Set the flag so that PlayAnim will use mBlendPeriodOut instead next time.\r\n\t\t\tmGotBlendPeriodOut=true;\t\r\n\t\t}\r\n\t\tbreak;\r\n        \r\n        // @script | LoopingAnim | true if the current animation will loop forever\r\n\t\tcase 0x80fdbdf2:\t// LoopingAnim\t\r\n\t\t\t{\r\n\t\t\t\treturn IsLoopingAnim() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase 0x42ffc3ce: // GetAnimLength\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tprintf(\"GetAnimLength\\n\");\r\n\t\t\tScript::PrintContents(pParams);\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tuint32 anim_checksum=0;\r\n\t\t\tpParams->GetChecksum(CRCD(0x98549ba4, \"anim\"), &anim_checksum);\r\n\t\t\t\r\n\t\t\tif (AnimExists(anim_checksum))\r\n\t\t\t{\r\n\t\t\t\tpScript->GetParams()->AddFloat(CRCD(0xfe82614d, \"Length\"), fabs(AnimDuration(anim_checksum)));\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        // @script | FrameIs | checks if the current frame is equal\r\n        // to the specified frame\r\n        // @uparmopt 1 | frame number\r\n\t\tcase 0x922e7d14: // FrameIs\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tprintf(\"FrameIs\\n\");\r\n\t\t\tScript::PrintContents(pParams);\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tfloat Start,Current,End;\r\n\t\t\tGetPrimaryAnimTimes(&Start,&Current,&End);\r\n\t\t\t\r\n\t\t\tfloat t=0;\r\n\t\t\tpParams->GetFloat(NO_NAME,&t);\r\n\r\n\t\t\tt/=60.0f;\r\n\t\t\t\r\n\t\t\tfloat new_frame=Current-Start;\r\n\t\t\tfloat old_frame=m_last_animation_time-Start;\r\n\r\n\t\t\tif (t==new_frame)\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (old_frame<t && t<new_frame)\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (new_frame<old_frame && old_frame<t)\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t}\r\n\r\n\t\t\tif (t<new_frame && new_frame<old_frame)\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\treturn CBaseComponent::MF_FALSE;\t\r\n\t\t}\r\n\t\t\t\r\n        // @script | WaitAnim | \r\n        // @uparm 0.0 | wait time (default is milliseconds)\r\n        // @flag frame | time in frames\r\n        // @flag percent | time in percent\r\n        // @flag second | time in seconds\r\n        // @flag relative | \r\n        // @flag fromend | \r\n\t\tcase 0x74cf5c94: // WaitAnim\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\t// printf(\"WaitAnim\\n\");\r\n\t\t\t// Script::PrintContents(pParams);\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tfloat Start,Current,End;\r\n\t\t\tGetPrimaryAnimTimes(&Start,&Current,&End);\r\n\t\t\tfloat t=0;\r\n\t\t\tpParams->GetFloat(NO_NAME,&t);\r\n\r\n\t\t\tif (pParams->ContainsFlag(0x4a07c332/*\"frame\"*/) || pParams->ContainsFlag(0x19176c5/*\"frames\"*/))\r\n\t\t\t{\r\n\t\t\t\tt/=60.0f;\r\n\t\t\t}\r\n\t\t\telse if (pParams->ContainsFlag(0x9e497fc6/*\"percent\"*/))\r\n\t\t\t{\r\n\t\t\t\tt=Start+(End-Start)*t/100.0f; // Dodgy?\r\n\t\t\t}\t\r\n\t\t\telse if (pParams->ContainsFlag(0x49e0ee96/*\"second\"*/) || pParams->ContainsFlag(0xd029f619/*\"seconds\"*/))\r\n\t\t\t{\r\n\t\t\t\t// t is in seconds, so nothing to do.\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// If they did not specify any of the above, then t is in milliseconds, so convert to seconds.\r\n\t\t\t\tt/=1000.0f;\r\n\t\t\t}\r\n\t\t\t\r\n\r\n\t\t\tif (pParams->ContainsFlag(0x91a4c826/*\"relative\"*/))\t\r\n\t\t\t{\r\n\t\t\t\tif (Start<=End)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_animation_script_unblock_point=Current+t;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_animation_script_unblock_point=Current-t;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\telse if (pParams->ContainsFlag(0xe18cd075/*\"fromend\"*/))\t\r\n\t\t\t{\r\n\t\t\t\tif (Start<=End)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_animation_script_unblock_point=End-t;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_animation_script_unblock_point=Start+t;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_animation_script_unblock_point=t;\r\n\t\t\t}\r\n\t\t\t\r\n//\t\t\tDbg_MsgAssert( m_animation_script_unblock_point>=Start && m_animation_script_unblock_point<=End, ( \"WaitAnim time %f out of range of anim (%f %f) in %s\", m_animation_script_unblock_point, Start, End, pScript->GetScriptInfo() ) );\r\n\r\n\t\t\tif ( !GetObject()->GetScript() )\r\n\t\t\t{\r\n\t\t\t\tGetObject()->SetScript(new Script::CScript);\r\n\t\t\t}\r\n\r\n\t\t\tif ((Start<=End && Current>=m_animation_script_unblock_point) || (Start>=End && Current<=m_animation_script_unblock_point))\r\n\t\t\t{\r\n\t\t\t\tGetObject()->GetScript()->UnBlock();\r\n\t\t\t\tm_animation_script_block_active=false;\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tGetObject()->GetScript()->Block();\r\n\t\t\t\tm_animation_script_block_active=true;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t}\t\r\n\r\n\t\tcase 0x5f495ae0:\t// InvalidateCache\r\n\t\t{\r\n\t\t\tint num_channels = m_blendChannelList.CountItems();\r\n\t\t\tGfx::CBlendChannel* pChannel = (Gfx::CBlendChannel*)m_blendChannelList.GetNext();\r\n\t\t\tfor ( int i = 0; i < num_channels; i++ )\r\n\t\t\t{\r\n\t\t\t\tpChannel->InvalidateCache();\r\n\t\t\t\tpChannel = (Gfx::CBlendChannel*)pChannel->GetNext();\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n        // @script | Obj_WaitAnimFinished | wait for animation to complete\r\n\t\tcase 0xb628a959:  // Obj_WaitAnimFinished\r\n\t\t\tpScript->SetWait(Script::WAIT_TYPE_OBJECT_ANIM_FINISHED,this);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\r\n\t\t// @script | AnimExists | returns true if the given anim exists\r\n\t\t// @param name | animation to look for\r\n\t\tcase CRCC(0x9069f357, \"AnimExists\"):\r\n\t\t{\r\n\t\t\tuint32 anim_name;\r\n\t\t\tpParams->GetChecksum(NO_NAME, &anim_name);\r\n\t\t\treturn AnimExists(anim_name) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE; \r\n\t\t}\r\n\r\n\t\tcase 0x83654874: // AddAnimController\r\n\t\tcase 0x02565bd1: //\tSetBoneTransMin\r\n\t\tcase 0x3e5b6488: //\tSetBoneTransMax\r\n\t\tcase 0xc85b9ac0: //\tSetBoneTransSpeed\r\n\t\tcase 0x5ee9d5bd: //\tSetBoneTransCurrent\r\n\t\tcase 0x5661fb72: //\tSetBoneTransActive\r\n\t\tcase 0xa47767f2: //\tSetBoneRotMin\r\n\t\tcase 0x987a58ab: //\tSetBoneRotMax\r\n\t\tcase 0x599d3707: //\tSetBoneRotSpeed\r\n\t\tcase 0x7235daa7: //\tSetBoneRotCurrent\r\n\t\tcase 0x53f06acc: //\tSetBoneRotActive\r\n\t\tcase 0xc6889e91: //\tSetBoneScaleMin\r\n\t\tcase 0xfa85a1c8: //\tSetBoneScaleMax\r\n\t\tcase 0xd32c2724: //\tSetBoneScaleSpeed\r\n\t\tcase 0xd12b3713: //\tSetBoneScaleCurrent\r\n\t\tcase 0xf11daaae: //\tSetBoneScaleActive\r\n\t\tcase 0xd63a1b81: // GetPartialAnimParams\r\n\t\tcase 0xbd4edd44: // SetPartialAnimSpeed\r\n\t\tcase 0x6aaeb76f: // IncrementPartialAnimTime\r\n\t\tcase 0xf5e2b871: // ReversePartialAnimDirection\r\n\t\t\t{\r\n\t\t\t\tGfx::CBlendChannel* pPrimaryChannel = get_primary_channel();\r\n\t\t\t\tif ( pPrimaryChannel )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn pPrimaryChannel->CallMemberFunction( Checksum, pParams, pScript ) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase 0x986d274e: // RemoveAnimController\r\n\t\t\t{\r\n\t\t\t\tGfx::CBlendChannel* pChannel = (Gfx::CBlendChannel*)m_blendChannelList.GetNext();\r\n\t\t\t\twhile ( pChannel )\r\n\t\t\t\t{\r\n\t\t\t\t\tpChannel->CallMemberFunction( Checksum, pParams, pScript );\r\n\t\t\t\t\tpChannel = (Gfx::CBlendChannel*)pChannel->GetNext();\r\n\t\t\t\t}\r\n\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | Obj_Flip | \r\n\t\tcase 0x27a98022:  // Obj_Flip\r\n\t\t\tToggleFlipState( );\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | Obj_AnimationFlipped | \r\n\t\tcase 0x6eceb234:  // Obj_AnimationFlipped\r\n\t\t\treturn ( m_flags & nxANIMCOMPONENTFLAGS_FLIPPED ) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tdefault:\r\n            return CBaseComponent::MF_NOT_EXECUTED;\r\n\r\n    }\r\n    \r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::AddAnimController( Script::CStruct* pParams )\r\n{\r\n\tGfx::CBlendChannel* pPrimaryChannel = get_primary_channel();\r\n\tif ( pPrimaryChannel )\r\n\t{\r\n\t\tpPrimaryChannel->AddController( pParams );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::ProcessWait( Script::CScript * pScript )\r\n{\r\n\tswitch (pScript->GetWaitType())\r\n\t{\r\n\t\tcase Script::WAIT_TYPE_OBJECT_ANIM_FINISHED:\r\n\t\t\tif (IsAnimComplete())\r\n\t\t\t{\r\n\t\t\t\tpScript->ClearWait();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nWait type of %d not supported by CAnimationComponent\",pScript->GetScriptInfo(),pScript->GetWaitType()));\r\n\t\t\tbreak;\r\n\t}\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::GetDebugInfo( Script::CStruct* p_info )\r\n{\r\n\r\n#ifdef\t__DEBUG_CODE__\r\n\r\n\tDbg_MsgAssert( p_info, ( \"NULL p_info sent to CAnimationComponent::GetDebugInfo\" ) );\r\n\r\n\t// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\r\n\t\r\n\tp_info->AddInteger( CRCD(0x87ed8a3f,\"m_shouldblend\"), m_shouldBlend );\r\n\tp_info->AddInteger( CRCD(0xa2f4a5ea,\"mGotBlendPeriodOut\"), mGotBlendPeriodOut );\r\n\tp_info->AddFloat( CRCD(0xd0902723,\"mBlendPeriodOut\"), mBlendPeriodOut );\r\n\tp_info->AddChecksum( CRCD(0xc2fe9f39,\"m_animScriptName\"), m_animScriptName );\r\n\tp_info->AddInteger(CRCD(0x9fdd4257,\"m_dont_interrupt\"),m_dont_interrupt);\r\n\t\r\n\tScript::CStruct* p_tempParams = new Script::CStruct;\r\n\tp_tempParams->Clear();\r\n\tGfx::CBlendChannel* pPrimaryChannel = get_primary_channel();\r\n\tif ( pPrimaryChannel )\r\n\t{\r\n\t\tpPrimaryChannel->GetDebugInfo( p_tempParams );\r\n\t\tp_info->AddStructure( CRCD(0x969f358c,\"primary_channel\"), p_tempParams );\r\n\t}\r\n\r\n\tdelete p_tempParams;\r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGfx::CBlendChannel* CAnimationComponent::get_primary_channel()\r\n{\r\n\t// just grab the first item from the list...\r\n\tGfx::CBlendChannel* pBlendChannel = NULL;\r\n\tpBlendChannel = (Gfx::CBlendChannel*)m_blendChannelList.GetNext();\r\n\treturn pBlendChannel;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::pack_degenerate_channels()\r\n{\r\n\t// this removes all the channels that have expired...\r\n\r\n\tGfx::CBlendChannel* pChannel = (Gfx::CBlendChannel*)m_blendChannelList.GetNext();\r\n\twhile ( pChannel )\r\n\t{\r\n\t\tGfx::CBlendChannel* pNext = (Gfx::CBlendChannel*)pChannel->GetNext();\r\n\t\t\r\n\t\tif ( !pChannel->IsActive() )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(pChannel != get_primary_channel(), (\"Removing primary channel\"));\r\n\t\t\tDbg_MsgAssert( !s_updating_channels, ( \"Someone is trying to remove an animation channel while in channel update loop\" ) );\r\n\t\t\tpChannel->Remove();\r\n\t\t\tdelete pChannel;\r\n\t\t}\r\n\t\t\r\n\t\tpChannel = pNext;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::create_new_blend_channel( float blend_period )\r\n{\r\n\t// If there\tare too many channels, get rid of the tail channels\r\n\tGfx::CBlendChannel* pChannel = (Gfx::CBlendChannel*)m_blendChannelList.GetNext();//Item( 0 );\r\n\tint channelCount = 0;\r\n\r\n\twhile ( pChannel )\r\n\t{\r\n\t\tchannelCount++;\r\n\r\n\t\tGfx::CBlendChannel* pNext = (Gfx::CBlendChannel*)pChannel->GetNext();\r\n\t\t\r\n\t\tif ( channelCount >= vNUM_DEGENERATE_ANIMS )\r\n\t\t{\r\n\t\t\t// remove the tail items\r\n\t\t\tpChannel->Remove();\r\n\t\t\tDbg_MsgAssert( !s_updating_channels, ( \"Someone is trying to remove an animation channel while in channel update loop\" ) );\r\n\t\t\tdelete pChannel;\r\n\t\t}\r\n\r\n\t\tpChannel = pNext;\r\n\t}\r\n\t\t\r\n\t// degenerate the existing blend channels\r\n\t// make the first channel degenerate\r\n\tGfx::CBlendChannel* pBlendChannel = m_blendChannelList.CountItems() ? get_primary_channel() : NULL;//\t(Gfx::CBlendChannel*)m_blendChannelList.GetItem( 0 );\r\n\tif ( pBlendChannel )\r\n\t{\r\n\t\tif ( pBlendChannel->Degenerate( blend_period ) )\r\n\t\t{\r\n\t\t\t// degeneration worked, so we want to do this cumulative\r\n\t\t\t// blend value thing (not really sure what it is though)\r\n\t\t\tfloat cumulative_blend_value = 0.0f;\r\n\t\t\tGfx::CBlendChannel* pOtherChannels = (Gfx::CBlendChannel*)pBlendChannel->GetNext();\r\n\t\t\twhile ( pOtherChannels )\r\n\t\t\t{\r\n\t\t\t\t// if( !pOtherChannels->IsActive() )\r\n\t\t\t\tif( pOtherChannels->IsDegenerating() )\r\n\t\t\t\t{\r\n\t\t\t\t\tcumulative_blend_value += \r\n\t\t\t\t\t\tpOtherChannels->GetDegenerationTime() \r\n\t\t\t\t\t\t* pOtherChannels->GetDegenerationTimeToBlendMultiplier();\r\n\t\t\t\t}\r\n\t\t\t\tpOtherChannels = (Gfx::CBlendChannel*)pOtherChannels->GetNext();\r\n\t\t\t}\r\n\t\t\r\n\t\t\tfloat blend_value1 = 1.0f - ( cumulative_blend_value );\r\n\t\t\tpBlendChannel->SetDegenerationTimeToBlendMultiplier( blend_value1 / pBlendChannel->GetDegenerationTime() );\r\n\t\t}\r\n\t}\r\n\t\r\n\t// now add a new channel to the front of the list\r\n\tGfx::CBlendChannel* pPrimaryChannel = new Gfx::CBlendChannel( GetObject() );\r\n\tm_blendChannelList.AddToHead( pPrimaryChannel );\r\n\tDbg_MsgAssert( !s_updating_channels, ( \"Someone is trying to add an animation channel while in channel update loop\" ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAnimationComponent::AnimEquals( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\t\r\n\tuint32 current_animation=GetCurrentSequence();\r\n\t\r\n\tScript::CComponent *p_comp=NULL;\r\n\twhile (true)\r\n\t{\r\n\t\tp_comp=pParams->GetNextComponent(p_comp);\r\n\t\tif (!p_comp)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tif (p_comp->mNameChecksum==0)\r\n\t\t{\r\n\t\t\t// It's an unnamed component\r\n\t\t\t\r\n\t\t\tScript::CArray *p_array=NULL;\r\n\t\t\tif (p_comp->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t{\r\n\t\t\t\t// It's an unnamed name. Maybe it's the name of a global array ...\r\n\t\t\t\tScript::CSymbolTableEntry *p_entry=Script::Resolve(p_comp->mChecksum);\r\n\t\t\t\tif (p_entry && p_entry->mType==ESYMBOLTYPE_ARRAY)\r\n\t\t\t\t{\r\n\t\t\t\t\t// It is a global array\r\n\t\t\t\t\tp_array=p_entry->mpArray;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Nope, it's just a name, so see if it is the name of the current animation.\r\n\t\t\t\t\tif (p_comp->mChecksum==current_animation)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (p_comp->mType==ESYMBOLTYPE_ARRAY)\r\n\t\t\t{\r\n\t\t\t\tp_array=p_comp->mpArray;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (p_array)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(p_array->GetType()==ESYMBOLTYPE_NAME,(\"\\n%s\\nAnimEquals: Array must be of names\",pScript->GetScriptInfo()));\r\n\t\t\t\tfor (uint32 i=0; i<p_array->GetSize(); ++i)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (p_array->GetChecksum(i)==current_animation)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\t\t\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CAnimationComponent::AnimDuration( uint32 checksum )\r\n{\r\n\tGfx::CBonedAnimFrameData *p_anim = find_actual_anim( checksum );\r\n\r\n    Dbg_MsgAssert( p_anim, ( \"Trying to get duration on an animation that doesn't exist %s %s %s\", \r\n\t\t\t\t\t\t\t Script::FindChecksumName(m_animScriptName), \r\n\t\t\t\t\t\t\t Script::FindChecksumName(checksum),\r\n\t\t\t\t\t\t\t Script::FindChecksumName(GetObject()->GetID()) ) );\r\n\r\n\treturn ( p_anim->GetDuration() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAnimationComponent::AnimExists( uint32 checksum )\r\n{\r\n\tGfx::CBonedAnimFrameData *p_anim = find_actual_anim( checksum );\r\n\r\n\treturn p_anim;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::AddTime( float incVal )\r\n{\r\n\tGfx::CBlendChannel* pPrimaryChannel = get_primary_channel();\r\n\tif ( pPrimaryChannel )\r\n\t{\r\n\t\tpPrimaryChannel->AddTime( incVal );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGfx::CBonedAnimFrameData* CAnimationComponent::find_actual_anim( uint32 checksum )\r\n{\r\n\t// need to combine the animation name (Idle) \r\n\t// with the owner animscript (animload_thps5_human)\r\n\t// to get the asset name\r\n\treturn Nx::GetCachedAnim( m_animScriptName + checksum, false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::PrintStatus()\r\n{\r\n\t// for debugging the viewer object\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::Update()\r\n{\r\n\tif ( Gfx::CBlendChannel* primary_channel = get_primary_channel() )\r\n\t{\r\n\t\tm_last_animation_time = primary_channel->GetCurrentAnimTime();\r\n\t\t\r\n\t\t/*\r\n\t\tfloat s, c, e;\r\n\t\tprimary_channel->GetAnimTimes(&s, &c, &e);\r\n\t\tprintf(\"Animation Factor Complete = %f\\n\", c / (e - s));\r\n\t\t*/\r\n\t}\r\n\t\r\n\tif (m_animation_script_block_active)\r\n\t{\r\n\t\tif ( !GetObject()->GetScript() )\r\n\t\t{\r\n\t\t\tGetObject()->SetScript( new Script::CScript );\r\n\t\t}\r\n\t\t\r\n\t\t// The script should be blocked at this point, if it isn't that must\r\n\t\t// be because the script just got reloaded. So clear the m_animation_script_block_active\r\n\t\t// flag so that it doesn't get stuck on forever.\r\n\t\tif ( !GetObject()->GetScript()->getBlocked() )\r\n\t\t{\r\n\t\t\tm_animation_script_block_active = false;\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tfloat start, current, end;\r\n\t\t\tGetPrimaryAnimTimes( &start, &current, &end);\r\n\t\t\t\r\n\t\t\tif ( ( start <= end && current >= m_animation_script_unblock_point ) || ( start >= end && current <= m_animation_script_unblock_point ) )\r\n\t\t\t{\r\n\t\t\t\tGetObject()->GetScript()->UnBlock();\r\n\t\t\t\tm_animation_script_block_active = false;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t}\r\n\r\n\t// Alwyas update the channels\r\n\r\n\ts_updating_channels = true;\r\n\r\n\tint num_channels = m_blendChannelList.CountItems();\r\n\tGfx::CBlendChannel* pChannel = (Gfx::CBlendChannel*)m_blendChannelList.GetNext();\r\n\tfor ( int i = 0; i < num_channels; i++ )\r\n\t{\r\n\t\tpChannel->Update();\r\n\t\tpChannel = (Gfx::CBlendChannel*)pChannel->GetNext();\r\n\t}\r\n\r\n\ts_updating_channels = false;\r\n\r\n\t// remove channels which have decided they are complete\r\n\tpack_degenerate_channels();\r\n\r\n\t// (Mick) If there is a suspend component\r\n\t// then ask it if we should animate\r\n\t\r\n\t// This call determines whether the object is sufficiently far away that no animation is disabled,\r\n\t// or possibly at an intermediate distance, interleaved. The distance from parent object to camera is cached\r\n\t// for subsequent animation LOD calculations.\r\n\tDbg_Assert(mp_suspend_component);\r\n\tbool animate = mp_suspend_component->should_animate( &m_parent_object_dist_to_camera );\r\n\tif ( animate )\r\n\t{\t\r\n\t\tupdate_procedural_bones();\r\n\t\t\r\n\t\t// This call determines whether the object is actually on screen; animation is not requried\r\n\t\t// for offscreen objects.\r\n\t\tif ( ShouldAnimate() )\r\n\t\t{\r\n\t\t\tupdate_skeleton();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::UpdateSkeleton()\r\n{\r\n\t// don't use the animation cache, because\r\n\t// the viewer object doesn't call Update(),\r\n\t// which normally is responsible for\r\n\t// invalidating the cache at the\r\n\t// appropriate times\r\n\tGfx::CBlendChannel* pPrimaryChannel = get_primary_channel();\r\n\tif ( pPrimaryChannel )\r\n\t{\r\n\t\tpPrimaryChannel->InvalidateCache();\r\n\t}\r\n\r\n\t// allows the viewer object to update the skeleton,\r\n\t// outside of the normal Update() function...\r\n\t// (the viewer object sometimes suspends the\r\n\t// component and updates the time manually,\r\n\t// in which case we'd still need to apply\r\n\t// the animation to the skeleton...)\r\n\tupdate_skeleton();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAnimationComponent::IsAnimComplete( void )\r\n{\r\n\tif ( !get_primary_channel() )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n    return get_primary_channel()->IsAnimComplete();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAnimationComponent::IsLoopingAnim( void )\r\n{\r\n\tif ( !get_primary_channel() )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n    return get_primary_channel()->IsLoopingAnim();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CAnimationComponent::GetCurrentSequence( void )\r\n{\r\n\tif ( !get_primary_channel() )\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\r\n    return get_primary_channel()->GetCurrentAnim();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t  \r\nvoid CAnimationComponent::GetPrimaryAnimTimes(float *pStart, float *pCurrent, float *pEnd)\r\n{\r\n\t*pStart = 0.0f;\r\n\t*pCurrent = 0.0f;\r\n\t*pEnd = 0.0f;\r\n\r\n\tif ( get_primary_channel() )\r\n\t{\r\n\t\tget_primary_channel()->GetAnimTimes( pStart, pCurrent, pEnd );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CAnimationComponent::GetCurrentAnimTime( void )\r\n{\r\n\tif ( !get_primary_channel() )\r\n\t{\r\n\t\treturn 0.0f;\r\n\t}\r\n\r\n    return get_primary_channel()->GetCurrentAnimTime();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::PlaySequence( uint32 checksum, float BlendPeriod )\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tif ( !AnimExists( checksum ) )\r\n\t{\r\n\t\tDbg_Message( \"Couldn't find anim %s\\n\", Script::FindChecksumName(checksum) );\r\n\t}\r\n#endif\r\n\r\n\tPlayPrimarySequence( checksum, false, 0.0f, AnimDuration(checksum), Gfx::LOOPING_HOLD, BlendPeriod, 1.0f );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::PlayPrimarySequence( uint32 animName, bool propagate, float start_time, float end_time, Gfx::EAnimLoopingType loop_type, float blend_period, float speed )\r\n{\r\n\tif ( animName == 0 )\r\n\t{\r\n\t\tanimName = CRCD(0x1ca1ff20,\"default\");\r\n\t}\r\n\r\n\tif ( propagate )   \r\n\t{\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tGameNet::PlayerInfo* player;\r\n\t\t\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( GetObject()->GetID() );\r\n\t\tif ( player && player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tGameNet::MsgPlayPrimaryAnim\tanim_msg;\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\tchar msg[ Net::Manager::vMAX_PACKET_SIZE ];\r\n\t\t\tchar* stream;\r\n\t\t\tint size;\r\n\t\t\tNet::Client* client;\r\n                    \r\n\t\t\tclient = gamenet_man->GetClient( player->GetSkaterNumber());\r\n\t\t\tDbg_Assert( client );\r\n\r\n\t\t\t//anim_msg.m_Time = client->m_Timestamp;\r\n            anim_msg.m_Index = animName;\r\n\t\t\tanim_msg.m_ObjId = GetObject()->GetID();\r\n\t\t\tanim_msg.m_LoopingType = loop_type;\r\n\t\t\tanim_msg.m_StartTime = (unsigned short )( start_time * 4096.0f );\r\n\t\t\tanim_msg.m_EndTime = ((unsigned short )( end_time * 4096.0f ));\r\n\t\t\tanim_msg.m_BlendPeriod = (unsigned short )( blend_period * 4096.0f );\r\n\t\t\tanim_msg.m_Speed = (unsigned short )( speed * 4096.0f );\r\n\r\n\t\t\tstream = msg;\r\n\t\t\t//memcpy( stream, &anim_msg.m_Time, sizeof( unsigned int ));\r\n\t\t\t//stream += sizeof( int );\r\n\t\t\t*stream++ = anim_msg.m_LoopingType;\r\n\t\t\t*stream++ = anim_msg.m_ObjId;\r\n\t\t\tmemcpy( stream, &anim_msg.m_Index, sizeof( uint32 ));\r\n\t\t\tstream += sizeof( uint32 );\r\n\t\t\tmemcpy( stream, &anim_msg.m_StartTime, sizeof( unsigned short ));\r\n\t\t\tstream += sizeof( unsigned short );\r\n\t\t\tmemcpy( stream, &anim_msg.m_EndTime, sizeof( unsigned short ));\r\n\t\t\tstream += sizeof( unsigned short );\r\n\t\t\tmemcpy( stream, &anim_msg.m_BlendPeriod, sizeof( unsigned short ));\r\n\t\t\tstream += sizeof( unsigned short );\r\n\t\t\tmemcpy( stream, &anim_msg.m_Speed, sizeof( unsigned short ));\r\n\t\t\tstream += sizeof( unsigned short );\r\n\r\n\t\t\tsize = (unsigned int) stream - (unsigned int) msg;\r\n            \r\n\t\t\tmsg_desc.m_Data = msg;\r\n\t\t\tmsg_desc.m_Length = size;\r\n\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_PRIM_ANIM_START;\r\n\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t}\r\n\t}\r\n    \r\n\t// GJ:  Should this be broken up into two commands/\r\n\t// to degenerate the old, and start playing the new?\r\n\r\n//\tprintf( \"Playing anim %s\\n\", Script::FindChecksumName( animName ), blend_period );\r\n    \r\n#ifdef __NOPT_ASSERT__\r\n\t// Define this to disable blending\r\n\tif ( Script::GetInteger( CRCD(0xf098f123,\"disable_blending\"), Script::NO_ASSERT ) )\r\n\t{\r\n\t\tblend_period = 0.0f;\r\n\t}\r\n#endif\r\n\r\n\tif ( blend_period == 0.0f || !ShouldBlend() )\r\n\t{\r\n\t\tdestroy_blend_channels();\r\n\t}\r\n\r\n\tcreate_new_blend_channel( blend_period );\r\n\r\n\tGfx::CBlendChannel* pPrimaryChannel = get_primary_channel();\r\n\tDbg_Assert( pPrimaryChannel );\r\n    pPrimaryChannel->PlaySequence( animName, start_time, end_time, loop_type, blend_period, speed, IsFlipped() );\r\n\r\n\tdelete_anim_tags();\r\n\tadd_anim_tags( animName );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::delete_anim_tags()\r\n{\r\n\tScript::CStruct* pTags = GetObject()->GetTags();\r\n\tif ( pTags )\r\n\t{\r\n\t\tpTags->RemoveComponent( CRCD(0x5db4115f,\"AnimTags\") );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::add_anim_tags( uint32 animName )\r\n{\r\n\tScript::CStruct* pAnimTagTable = Script::GetStructure(CRCD(0x95807202,\"AnimTagTable\"), Script::ASSERT);\r\n\tif ( pAnimTagTable )\r\n\t{\r\n\t\tScript::CStruct* pSubStruct;\r\n\t\tif ( pAnimTagTable->GetStructure( animName, &pSubStruct, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tScript::CStruct* pTempStruct = new Script::CStruct;\r\n\r\n\t\t\t// add a new anim tags structure to the tags\r\n\t\t\tScript::CStruct* pTags = new Script::CStruct;\r\n\t\t\tpTags->AppendStructure( pSubStruct );\r\n\t\t\tpTempStruct->AddStructurePointer(CRCD(0x5db4115f,\"AnimTags\"), pTags);\r\n\r\n\t\t\tGetObject()->SetTagsFromScript( pTempStruct );\r\n\r\n\t\t\tdelete pTempStruct;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::SetWobbleTarget( float alpha, bool propagate )\r\n{\r\n\tif ( propagate )\r\n\t{\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tGameNet::PlayerInfo* player;\r\n\t\tstatic unsigned char s_last_alpha = 255;\r\n\t\t\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( GetObject()->GetID() );\r\n\t\tif ( player && player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tNet::Client* client;\r\n\t\t\tGameNet::MsgSetWobbleTarget msg;\r\n\r\n\t\t\tclient = gamenet_man->GetClient( player->GetSkaterNumber() );\r\n\t\t\tDbg_Assert( client );\r\n\r\n\t\t\tif( alpha < 0 )\r\n\t\t\t{ \r\n\t\t\t\talpha = 0;\r\n\t\t\t}\r\n\t\t\telse if( alpha > 1 )\r\n\t\t\t{\r\n\t\t\t\talpha = 1;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t//msg.m_Time = client->m_Timestamp;\r\n\t\t\tmsg.m_Alpha = (unsigned char ) ( alpha * 255.0f );\r\n\t\t\tmsg.m_ObjId = GetObject()->GetID();\r\n\t\t\t\r\n\t\t\tif( s_last_alpha != msg.m_Alpha )\r\n\t\t\t{\r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgSetWobbleTarget );\r\n\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_SET_WOBBLE_TARGET;\r\n\t\t\t\tmsg_desc.m_Singular = true;\r\n\t\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t\t\ts_last_alpha = msg.m_Alpha;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( get_primary_channel() )\r\n\t{\r\n\t\tScript::CStruct* pTempParams = new Script::CStruct;\r\n\r\n\t\tpTempParams->AddFloat( CRCD(0x4d747fa0,\"wobbletargetalpha\"), alpha );\r\n\r\n\t\tget_primary_channel()->CallMemberFunction( CRCD(0xd0209498,\"setwobbletarget\"), pTempParams, NULL );\r\n\r\n\t\tdelete pTempParams;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic int s_get_wobble_mask( int variable, float value )\r\n{   \r\n\tint mask;\r\n\r\n\tmask = 0;\r\n\tswitch( variable )\r\n\t{\r\n\t\tcase GameNet::MsgSetWobbleDetails::vWOBBLE_AMP_A:\r\n\t\t\tif( value == 0.05f )\r\n\t\t\t{\r\n\t\t\t\tmask = 0;\r\n\t\t\t}\r\n\t\t\telse if( value == 0.1f )\r\n\t\t\t{\r\n\t\t\t\tmask = 1;\r\n\t\t\t}\r\n\t\t\telse if( value == 10.1f )\r\n\t\t\t{\r\n\t\t\t\tmask = 2;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"value is %f\\n\", value );\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase GameNet::MsgSetWobbleDetails::vWOBBLE_AMP_B:\r\n\t\t\tif( value == 0.04f )\r\n\t\t\t{\r\n\t\t\t\tmask = 0;\r\n\t\t\t}\r\n\t\t\telse if( value == 10.1f )\r\n\t\t\t{\r\n\t\t\t\tmask = 1;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"VARIABLE: %d Value %f\\n\", variable, value );\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase GameNet::MsgSetWobbleDetails::vWOBBLE_K1:\r\n\t\t\tif( value == 0.0022f )\r\n\t\t\t{\r\n\t\t\t\tmask = 0;\r\n\t\t\t}\r\n\t\t\telse if( value == 20.0f )\r\n\t\t\t{\r\n\t\t\t\tmask = 1;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"value is %f\\n\", value );\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase GameNet::MsgSetWobbleDetails::vWOBBLE_K2:\r\n\t\t\tif( value == 0.0017f )\r\n\t\t\t{\r\n\t\t\t\tmask = 0;\r\n\t\t\t}\r\n\t\t\telse if( value == 10.0f )\r\n\t\t\t{\r\n\t\t\t\tmask = 1;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase GameNet::MsgSetWobbleDetails::vSPAZFACTOR:\r\n\t\t\tif( value == 1.5f )\r\n\t\t\t{\r\n\t\t\t\tmask = 0;\r\n\t\t\t}\r\n\t\t\telse if( value == 1.0f )\r\n\t\t\t{\r\n\t\t\t\tmask = 1;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"value is %f\\n\", value );\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\treturn mask;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::SetWobbleDetails( const Gfx::SWobbleDetails& wobble_details, bool propagate )\r\n{\r\n\tif ( propagate )\r\n\t{\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tGameNet::PlayerInfo* player;\r\n\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( GetObject()->GetID() );\r\n\t\tif ( player && player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tNet::Client* client;\r\n\t\t\tGameNet::MsgSetWobbleDetails msg;\r\n\t\t\tint mask;\r\n\t\t\tstatic char s_last_mask = -1;\r\n\t\t\t\r\n\t\t\tclient = gamenet_man->GetClient( player->GetSkaterNumber() );\r\n\t\t\tDbg_Assert( client );\r\n\r\n\t\t\t//msg.m_Time = client->m_Timestamp;\r\n\t\t\t\r\n\t\t\tmsg.m_WobbleDetails = 0;\r\n\t\t\tmask = s_get_wobble_mask( GameNet::MsgSetWobbleDetails::vWOBBLE_AMP_A, wobble_details.wobbleAmpA );\r\n\t\t\tmsg.m_WobbleDetails |= mask;\r\n\t\t\tmask = s_get_wobble_mask( GameNet::MsgSetWobbleDetails::vWOBBLE_AMP_B, wobble_details.wobbleAmpB );\r\n\t\t\tmsg.m_WobbleDetails |= ( mask << 2 );\r\n\t\t\tmask = s_get_wobble_mask( GameNet::MsgSetWobbleDetails::vWOBBLE_K1, wobble_details.wobbleK1 );\r\n\t\t\tmsg.m_WobbleDetails |= ( mask << 3 );\r\n\t\t\tmask = s_get_wobble_mask( GameNet::MsgSetWobbleDetails::vWOBBLE_K2, wobble_details.wobbleK2 );\r\n\t\t\tmsg.m_WobbleDetails |= ( mask << 4 );\r\n\t\t\tmask = s_get_wobble_mask( GameNet::MsgSetWobbleDetails::vSPAZFACTOR, wobble_details.spazFactor );\r\n\t\t\tmsg.m_WobbleDetails |= ( mask << 5 );\r\n\t\t\tmsg.m_ObjId = GetObject()->GetID();\r\n\r\n\t\t\t// Only propagate if it's actually different from our last wobble details message\r\n\t\t\tif( s_last_mask != msg.m_WobbleDetails )\r\n\t\t\t{\r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgSetWobbleDetails );\r\n\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_SET_WOBBLE_DETAILS;\r\n\t\t\t\tmsg_desc.m_Singular = true;\r\n\r\n\t\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\r\n\t\t\t\ts_last_mask = msg.m_WobbleDetails;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( get_primary_channel() )\r\n\t{\r\n\t\tScript::CStruct* pTempParams = new Script::CStruct;\r\n\r\n\t\tpTempParams->AddFloat( CRCD(0xfd266a26,\"wobbleAmpA\"), wobble_details.wobbleAmpA );\r\n\t\tpTempParams->AddFloat( CRCD(0x642f3b9c,\"wobbleAmpB\"), wobble_details.wobbleAmpB );\r\n\t\tpTempParams->AddFloat( CRCD(0x0f43fd49,\"wobbleK1\"), wobble_details.wobbleK1 );\r\n\t\tpTempParams->AddFloat( CRCD(0x964aacf3,\"wobbleK2\"), wobble_details.wobbleK2 );\r\n\t\tpTempParams->AddFloat( CRCD(0xf90b0824,\"spazFactor\"), wobble_details.spazFactor );\r\n\r\n \t\tget_primary_channel()->CallMemberFunction( CRCD(0xea6d0efd,\"setwobbledetails\"), pTempParams, NULL );\r\n\r\n\t\tdelete pTempParams;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::SetLoopingType( Gfx::EAnimLoopingType looping_type, bool propagate )\r\n{\r\n\tif ( propagate )\r\n\t{\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tGameNet::PlayerInfo* player;\r\n\t\tstatic char s_last_type = -1;\r\n\t\t\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( GetObject()->GetID() );\r\n\t\tif ( player && player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tNet::Client* client;\r\n\t\t\tGameNet::MsgSetLoopingType msg;\r\n\r\n\t\t\tclient = gamenet_man->GetClient( player->GetSkaterNumber() );\r\n\t\t\tDbg_Assert( client );\r\n\r\n\t\t\t//msg.m_Time = client->m_Timestamp;\r\n\t\t\tmsg.m_LoopingType = looping_type;\r\n\t\t\tmsg.m_ObjId = GetObject()->GetID();\r\n\t\t\tif( s_last_type != looping_type )\r\n\t\t\t{\r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgSetLoopingType );\r\n\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_SET_LOOPING_TYPE;\r\n\t\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t\t\ts_last_type = looping_type;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif ( get_primary_channel() )\r\n\t{\r\n\t\tget_primary_channel()->SetLoopingType( looping_type );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::ReverseDirection( bool propagate )\r\n{\r\n    Dbg_Assert( !propagate );\r\n\r\n\tif ( get_primary_channel() )\r\n\t{\r\n\t\tget_primary_channel()->ReverseDirection();\r\n\t}\r\n\r\n\t// TODO:  eventually turn this into a net message.\r\n\t// For now, only the viewer objects should be reversing the direction\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::SetAnimSpeed( float speed, bool propagate, bool all_channels )\r\n{\t\r\n\tif ( !get_primary_channel() )\r\n\t{\r\n\t\t// no primary channel, so do nothing\r\n\t\treturn;\r\n\t}\r\n\r\n\tfloat cur_speed = get_primary_channel()->GetAnimSpeed();\r\n\r\n\tif( !all_channels && Mth::Abs( cur_speed - speed ) < vMIN_SPEED_THRESHOLD )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( propagate )\r\n\t{\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tNet::Client* client;\r\n\t\tGameNet::MsgSetAnimSpeed msg;\r\n\t\tGameNet::PlayerInfo* player;\r\n\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( GetObject()->GetID() );\r\n\t\tif ( player && player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tclient = gamenet_man->GetClient( player->GetSkaterNumber() );\r\n\t\t\tif( client )\r\n\t\t\t{\r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t\t//msg.m_Time = client->m_Timestamp;\r\n\t\t\t\tmsg.m_AnimSpeed = speed;\r\n\t\t\t\tmsg.m_ObjId = GetObject()->GetID();\r\n\r\n\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgSetAnimSpeed );\r\n\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_SET_ANIM_SPEED;\r\n\t\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (all_channels)\r\n\t{\r\n\t\tGfx::CBlendChannel* pChannel = (Gfx::CBlendChannel*)m_blendChannelList.GetNext();\r\n\t\twhile ( pChannel )\r\n\t\t{\r\n\t\t\tpChannel->SetAnimSpeed( speed );\r\n\t\t\tpChannel = (Gfx::CBlendChannel*)pChannel->GetNext();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tget_primary_channel()->SetAnimSpeed( speed );\r\n\t}\r\n\t\r\n\tif (DebugSkaterScripts && GetObject()->GetID() == 0)\r\n\t{\r\n\t\tprintf(\"%d: Setting Anim Speed: %f\\n\",(int)Tmr::GetRenderFrame(),speed);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CAnimationComponent::GetAnimSpeed( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\t\r\n\tif ( !get_primary_channel() )\r\n\t{\r\n\t\t// no primary channel, so do nothing\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tfloat cur_speed = get_primary_channel()->GetAnimSpeed();\r\n\r\n    return cur_speed;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::EnableBlending( bool enabled )\r\n{\r\n\tm_shouldBlend = enabled;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAnimationComponent::ShouldBlend()\r\n{\r\n\treturn m_shouldBlend;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Plays an animation given a set of parameters contained in pParams.\r\n// This allows both the skater and other moving objects such as pedestrians to share a common-ish interface.\r\n\r\n// Returns the checksum of the animation if it did get successfully played, 0 otherwise.\r\n// (This feature is used by some debug code in the CSkater's PlayAnim script command)\r\nuint32 CAnimationComponent::PlayAnim(Script::CStruct *pParams, Script::CScript *pScript, float defaultBlendPeriod )\r\n{\r\n\tif (Gfx::CBlendChannel* primary_channel = get_primary_channel())\r\n\t{\r\n\t\tm_last_animation_time = primary_channel->GetCurrentAnimTime();\r\n\t}\r\n\r\n\tif (m_dont_interrupt && !IsAnimComplete())\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\t\t\r\n    if ( !has_anims() )\r\n    {\r\n        // some items don't have animation data associated with it yet...\r\n        return 0;\r\n    }\r\n\r\n\tuint32 AnimChecksum=0;\r\n\tpParams->GetChecksum( CRCD(0x98549ba4,\"Anim\"), &AnimChecksum );\r\n\tif ( !AnimChecksum )\r\n\t{\r\n\t\tScript::PrintContents(pParams);\r\n\t\tDbg_MsgAssert(0,(\"\\n%s\\nobj: %s\\nPlayAnim requires an anim name\",Script::FindChecksumName(GetObject()->GetID()),pScript->GetScriptInfo()));\r\n\t}\r\n\t\r\n\tfloat Speed=1.0f;\r\n\tpParams->GetFloat( CRCD(0xf0d90109,\"Speed\"), &Speed );   \r\n\t\r\n\tuint32 CurrentAnimChecksum = GetCurrentSequence();\r\n\tif ( AnimChecksum == CRCD(0x230ccbf4,\"Current\") )\r\n\t{\r\n\t\tAnimChecksum = CurrentAnimChecksum;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (CurrentAnimChecksum==AnimChecksum)\r\n\t\t{\r\n\t\t\tif ( pParams->ContainsFlag( CRCD(0xfe09fe09,\"NoRestart\") ) )\r\n\t\t\t{\r\n\t\t\t\t// Return without doing anything, since the user specified NoRestart, and the\r\n\t\t\t\t// current anim is the same as the requested one.\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t}\t\r\n\t}\r\n\r\n\tif ( !AnimExists( AnimChecksum ) )\r\n\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\tif ( Script::GetInt( CRCD(0x56d4128e,\"AssertOnMissingAnims\"), Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"*** Anim %s (%s) was not defined for object %s!\",\r\n\t\t\t\t\t\t\tScript::FindChecksumName(AnimChecksum),\r\n\t\t\t\t\t\t\tScript::FindChecksumName(m_animScriptName),\r\n\t\t\t\t\t\t\tScript::FindChecksumName(GetObject()->GetID() ) ) );\r\n\t\t}\r\n\t\telse if ( Script::GetInt( CRCD(0xf42cb81a,\"WarnOnMissingAnims\"), Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tDbg_Message( \"*** Anim %s (%s) was not defined for object %s!\",\r\n\t\t\t\t\t\t Script::FindChecksumName(AnimChecksum),\r\n\t\t\t\t\t\t Script::FindChecksumName(m_animScriptName),\r\n\t\t\t\t\t\t Script::FindChecksumName(GetObject()->GetID() ) );\r\n\t\t}\r\n#endif\r\n\r\n\t\t// by default, a missing anim will play the christ-pose anim\r\n\t\tAnimChecksum = CRCD(0x1ca1ff20,\"default\");\r\n\t}\r\n\t\r\n\tfloat BlendPeriod=defaultBlendPeriod;\r\n\tfloat BlendPeriodPercent=0.0f;\r\n\tif (mGotBlendPeriodOut)\r\n\t{\r\n\t\t// If a BlendPeriodOut command was issued, use that value to override any\r\n\t\t// value specified by PlayAnim.\r\n\t\tBlendPeriod=mBlendPeriodOut;\r\n\t\t// but clear the flag for next time.\r\n\t\tmGotBlendPeriodOut=false;\r\n\t}\r\n\telse if (pParams->GetFloat(CRCD( 0x4f3abd6c,\"BlendPeriodPercent\"), &BlendPeriodPercent) )\r\n\t{\r\n\t\tBlendPeriod = AnimDuration(AnimChecksum) * (BlendPeriodPercent/100.0f);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpParams->GetFloat( CRCD(0x8f0d24ed,\"BlendPeriod\"), &BlendPeriod );\r\n\t}\t\r\n\t\r\n\tfloat Duration=AnimDuration(AnimChecksum);\r\n\tfloat From=0;\r\n\tfloat Current=0;\r\n\tfloat To=Duration;\r\n\t\r\n\tif ( pParams->ContainsFlag( CRCD(0x099371ae,\"SyncToPreviousAnim\") ) )\r\n\t{\r\n\t\tfloat Dummy, PreviousAnimCurrent, PreviousAnimDuration;\r\n\t\t\r\n\t\tGetPrimaryAnimTimes(&Dummy, &PreviousAnimCurrent, &Dummy);\r\n\t\tPreviousAnimDuration = AnimDuration(CurrentAnimChecksum);\r\n\t\tpParams->GetFloat(CRCD(0x4b4a153a, \"EffectivePreviousAnimDuration\"), &PreviousAnimDuration);\r\n\t\t\r\n\t\tCurrent = Mth::Clamp(PreviousAnimCurrent / AnimDuration(CurrentAnimChecksum), 0.0f, 1.0f) * Duration;\r\n\t\tif ( pParams->ContainsFlag( CRCD(0xf8cfd515,\"Backwards\") ) )\r\n\t\t{\r\n\t\t\tCurrent = -(Duration - Current);\r\n\t\t}\r\n\t}\r\n\telse if ( pParams->ContainsFlag( CRCD(0xff5ac79e, \"SyncToReversePreviousAnim\") ) )\r\n\t{\r\n\t\tfloat Dummy, PreviousAnimCurrent, PreviousAnimDuration;\r\n\t\t\r\n\t\tGetPrimaryAnimTimes(&Dummy, &PreviousAnimCurrent, &Dummy);\r\n\t\tPreviousAnimDuration = AnimDuration(CurrentAnimChecksum);\r\n\t\tpParams->GetFloat(CRCD(0x4b4a153a, \"EffectivePreviousAnimDuration\"), &PreviousAnimDuration);\r\n\t\t\r\n\t\tCurrent = Mth::Clamp((PreviousAnimDuration - PreviousAnimCurrent) / PreviousAnimDuration, 0.0f, 1.0f) * Duration;\r\n\t\tif ( pParams->ContainsFlag( CRCD(0xf8cfd515,\"Backwards\") ) )\r\n\t\t{\r\n\t\t\tCurrent = -(Duration - Current);\r\n\t\t}\r\n\t}\r\n\r\n\t// Need TempCurrent, so that it doesn't conflict with regular Current\r\n\t// which is possibly modified in the above \"SyncToPreviousAnim\" code block\r\n\tfloat TempCurrent;\r\n\tfloat Dummy;\r\n\tGetPrimaryAnimTimes(&Dummy,&TempCurrent,&Dummy);\r\n\tGfx::GetTimeFromParams( &From, &To, TempCurrent, Duration, pParams, pScript );\r\n\r\n\tGfx::EAnimLoopingType LoopingType;\r\n\tGfx::GetLoopingTypeFromParams( &LoopingType, pParams );\r\n\r\n\tm_dont_interrupt=pParams->ContainsFlag( CRCD(0x84f13067,\"DontInterrupt\") );\r\n\t\r\n#ifdef __NOPT_ASSERT__\r\n\tif ( Script::GetInt( CRCD(0xca108bce,\"DebugAnims\"), false ) )\r\n\t{\r\n\t\tif ( GetObject()->GetID() == 0 )\r\n\t\t{\r\n\t\t\tprintf( \"DebugAnims:  Playing skater anim %s\\n\", Script::FindChecksumName(AnimChecksum) );\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (DebugSkaterScripts && AnimChecksum && GetObject()->GetID() == 0)\r\n\t{\r\n\t\tprintf(\"%d: Playing anim '%s'\\n\",(int)Tmr::GetRenderFrame(),Script::FindChecksumName(AnimChecksum));\r\n\t}\r\n#endif\r\n\r\n\tPlayPrimarySequence( AnimChecksum, true, From, To, LoopingType, BlendPeriod, Speed );\r\n\t\r\n\tif (Current != 0.0f)\r\n\t{\r\n\t\tget_primary_channel()->AddTime(Current);\r\n\t}\r\n\t\r\n\t/*\r\n\tif ( GetObject()->GetID() == 0 )\r\n\t{\r\n\t\tprintf(\"-standard-anim-\\n\");\r\n\t\tprintf(\"Anim = %s\\n\", Script::FindChecksumName(AnimChecksum));\r\n\t\tprintf(\"From = %f\\n\", From);\r\n\t\tprintf(\"To = %f\\n\", To);\r\n\t\tprintf(\"Duration = %f\\n\", Duration);\r\n\t\tprintf(\"Current = %f\\n\", Current);\r\n\t\tprintf(\"Speed = %f\\n\", Speed);\r\n\t\tprintf(\"BlendPeriod = %f\\n\", BlendPeriod);\r\n\t}\r\n\t*/\r\n\t\r\n\tuint32 PartialAnim;\r\n\tif (pParams->GetChecksum(CRCD(0x6c565f57, \"PartialAnimOverlay\"), &PartialAnim))\r\n\t{\r\n\t\tScript::CStruct* pPartialAnimParams = new Script::CStruct;\r\n\t\t\r\n\t\tuint32 partial_anim_id;\r\n\t\tif (pParams->GetChecksum(CRCD(0xf0ce9e0f, \"PartialAnimOverlayId\"), &partial_anim_id))\r\n\t\t{\r\n\t\t\tpPartialAnimParams->AddChecksum(CRCD(0x40c698af, \"Id\"), partial_anim_id);\r\n\t\t}\r\n\t\tpPartialAnimParams->AddChecksum(CRCD(0x7321a8d6, \"Type\"), CRCD(0x659bf355, \"PartialAnim\"));\r\n\t\tpPartialAnimParams->AddChecksum(CRCD(0x6c2bfb7f, \"AnimName\"), PartialAnim);\r\n\t\tpPartialAnimParams->AddFloat(CRCD(0x46e55e8f, \"From\"), From);\r\n\t\tpPartialAnimParams->AddFloat(CRCD(0x28782d3b, \"To\"), To);\r\n\t\tpPartialAnimParams->AddChecksum(NO_NAME, CRCD(0xd029f619, \"Seconds\"));\r\n\t\tpPartialAnimParams->AddFloat(CRCD(0x230ccbf4, \"Current\"), Current);\r\n\t\tpPartialAnimParams->AddFloat(CRCD(0xf0d90109, \"Speed\"), Speed);\r\n\t\tswitch (LoopingType)\r\n\t\t{\r\n\t\t\tcase Gfx::LOOPING_HOLD:\r\n\t\t\t\tbreak;\r\n\t\t\tcase Gfx::LOOPING_CYCLE:\r\n\t\t\t\tpPartialAnimParams->AddChecksum(NO_NAME, CRCD(0x4f792e6c, \"Cycle\"));\r\n\t\t\t\tbreak;\r\n\t\t\tcase Gfx::LOOPING_PINGPONG:\r\n\t\t\t\tpPartialAnimParams->AddChecksum(NO_NAME, CRCD(0x3153e314, \"PingPong\"));\r\n\t\t\t\tbreak;\r\n\t\t\tcase Gfx::LOOPING_WOBBLE:\r\n\t\t\t\tpPartialAnimParams->AddChecksum(NO_NAME, CRCD(0x6d941203, \"Wobble\"));\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tget_primary_channel()->AddController(pPartialAnimParams);\r\n\t\t\r\n\t\tdelete pPartialAnimParams;\r\n\t\t\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tif ( GetObject()->GetID() == 0 && Script::GetInt( CRCD(0xca108bce,\"DebugAnims\"), false ) )\r\n\t\t{\r\n\t\t\tprintf( \"DebugAnims:  Playing skater partial anim overlay %s\\n\", Script::FindChecksumName(PartialAnim) );\r\n\t\t}\r\n\t\t\r\n\t\tif (DebugSkaterScripts && PartialAnim && GetObject()->GetID() == 0)\r\n\t\t{\r\n\t\t\tprintf(\"%d: Playing partial anim overlay '%s'\\n\",(int)Tmr::GetRenderFrame(),Script::FindChecksumName(PartialAnim));\r\n\t\t}\r\n\t\t#endif\r\n\t}\r\n\r\n\treturn AnimChecksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// static workspace data\r\nstatic Gfx::CPose\tsBlendPoses[vNUM_DEGENERATE_ANIMS];\r\nstatic float\t\tsBlendValues[vNUM_DEGENERATE_ANIMS];\r\nstatic Gfx::CPose\tsResultPose;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid blend( Gfx::CPose* pPoseList, float* blendVal, int numBones, Gfx::CPose* pResultPose, int numBlendChannels )\r\n{\r\n\t// the blend value of the primary animation \r\n\t// should be 1.0, since it's active.\r\n\tDbg_Assert( blendVal[0] == 1.0f );\r\n\r\n\tfloat totalBlendVal = 0.0f;\r\n\tfor ( int i = 1; i < numBlendChannels; i++ )\r\n\t{\r\n\t\tif ( blendVal[i] )\r\n\t\t{\r\n\t\t\ttotalBlendVal += 1.0f;\r\n\t\t}\r\n\t}\r\n\r\n\tfloat degenerateBlendTotal = 0.0f;\r\n\tfor ( int i = 1; i < numBlendChannels; i++ )\r\n\t{\r\n\t\tdegenerateBlendTotal += blendVal[i];\r\n\t}\r\n\t\r\n\t// normalize them so that they all add up to total blend value\r\n\tblendVal[0] = totalBlendVal - degenerateBlendTotal;\r\n\r\n\t// Scan through the sets of frames, interpolating between the 2 based on the blend values.\r\n\tfloat sum = 0.0f;\r\n\r\n\tint i0, i1;\r\n\tfor ( i1 = (numBlendChannels - 1); i1 > 0; --i1 )\r\n\t{\r\n\t\tfloat blend1 = blendVal[i1];\r\n\t\tif ( blend1 )\r\n\t\t{\r\n\t\t\tblend1 += sum;\r\n\r\n\t\t\ti0 = i1 - 1;\r\n\t\t\twhile(( blendVal[i0] <= 0.0f ) && ( i0 > 0 ))\r\n\t\t\t{\r\n\t\t\t\t--i0;\r\n\t\t\t}\r\n\r\n\t\t\tfloat blend0 = blendVal[i0];\r\n\r\n\t\t\tsum += blendVal[i1];\r\n\r\n\t\t\t// Need to normalise blend0 and blend1 so they sum to 1.0.\r\n\t\t\tblend0 /= ( blend0 + blend1 );\r\n\t\t\tblend1 = 1.0f - blend0;\r\n\r\n\t\t\tMth::Quat* pRotations0 = pPoseList[i0].m_rotations;\r\n\t\t\tMth::Quat* pRotations1 = pPoseList[i1].m_rotations;\r\n\t\t\tMth::Vector* pTranslations0 = pPoseList[i0].m_translations;\r\n\t\t\tMth::Vector* pTranslations1 = pPoseList[i1].m_translations;\r\n\r\n\t\t\tfor( int b = 0; b < numBones; b++ )\r\n\t\t\t{\r\n\t\t\t\t*pRotations0 = Mth::FastSlerp( *pRotations0, *pRotations1, 1.0f - blend0 );\r\n\t\t\t\t\r\n\t\t\t\t*pTranslations0 = Mth::Lerp( *pTranslations0, *pTranslations1, 1.0f - blend0 );\r\n\r\n\t\t\t\tpRotations0++;\r\n\t\t\t\tpRotations1++;\r\n\t\t\t\tpTranslations0++;\r\n\t\t\t\tpTranslations1++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// copy the values into the result pose:\r\n\r\n\tMth::Quat* pSrcQuat = &pPoseList[0].m_rotations[0];\r\n\tMth::Vector* pSrcVector = &pPoseList[0].m_translations[0];\r\n\t\r\n\tMth::Quat* pDstQuat = &pResultPose->m_rotations[0];\r\n\tMth::Vector* pDstVector = &pResultPose->m_translations[0];\r\n\r\n\tmemcpy( pDstQuat, pSrcQuat, numBones * sizeof(Mth::Quat) );\r\n\tmemcpy( pDstVector, pSrcVector, numBones * sizeof(Mth::Vector) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CAnimationComponent::get_blend_channel( int blendChannel, Gfx::CPose* pResultPose, float* pBlendVal )\r\n{\r\n\tfloat blendVal = 0.0f;\r\n\tGfx::CBlendChannel* pBlendChannel = NULL;\r\n\tif ( 1 || ShouldBlend() )\r\n\t{\r\n\t\tDbg_MsgAssert( blendChannel >= 0 && blendChannel < (int)m_blendChannelList.CountItems(), ( \"out of range blend channel %d (0-%d)\", blendChannel, m_blendChannelList.CountItems() ) ); \r\n\t\tpBlendChannel = (Gfx::CBlendChannel*)m_blendChannelList.GetItem(blendChannel);\r\n\t\tblendVal = pBlendChannel->GetBlendValue();\r\n\t\tDbg_MsgAssert( blendChannel != 0 || blendVal == 1.0f, ( \"Expected primary channel to have a blend value of 1.0f\" ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tswitch ( blendChannel )\r\n\t\t{\r\n\t\t\tcase 0:\r\n\t\t\t\tpBlendChannel = get_primary_channel();\r\n\t\t\t\tblendVal = 1.0f;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"Invalid blend channel %d\", blendChannel ) );\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( blendVal <= 0.0f )\r\n\t{\r\n\t\t// GJ TODO:  I'm not sure why this case happens,\r\n\t\t// but it happened on THPS4 as well...  i should\r\n\t\t// look into this at some point...\r\n\t\t*pBlendVal = 0.0f;\r\n\t\treturn;\r\n\t}\r\n\r\n\tGfx::CSkeleton* pSkeleton = NULL;\r\n\r\n\tDbg_Assert(mp_skeleton_component);\r\n\tpSkeleton = mp_skeleton_component->GetSkeleton();\r\n\r\n\tif ( !pBlendChannel->GetPose( pResultPose ) )//, \r\n\t\t\t\t\t\t\t\t  // m_flags & nxANIMCOMPONENTFLAGS_FLIPPED,\r\n\t\t\t\t\t\t\t\t  // m_flags & nxANIMCOMPONENTFLAGS_ROTATESKATEBOARD,\r\n\t\t\t\t\t\t\t\t  // pSkeleton ) )\r\n\t{\r\n\t\t// couldn't find pose...\r\n\t\t// if it's the primary animation, assert\r\n\t\tif ( blendChannel == 0 )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"No primary animation found!  Is %08x/%s playing a default animation?\", GetObject()->GetID(), Script::FindChecksumName(m_animScriptName) ) );\r\n\t\t}\r\n\t}\r\n\t\r\n\t*pBlendVal = blendVal;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAnimationComponent::ShouldAnimate()\r\n{\r\n#if 1\r\n\r\n// The model will be inactive if off the screen\r\n\tNx::CModel* p_model = mp_model_component->GetModel();\r\n\treturn ( p_model && p_model->GetActive() );\r\n\r\n#else\r\n\r\n// Old version, kind of mixed up\t\r\n\t\r\n\t\r\n\t// this function will eventually be used to LOD\r\n\t// our animations (i.e. updating every Nth frame\r\n\t// based on distance)\r\n\t\r\n\t// if we did this, we would want to make sure that\r\n\t// the model's update function to be called at least\r\n\t// once to sync up the skeleton initially (we don't \r\n\t// want to do it in the constructor, because then\r\n\t// there's an order dependency on the components)\r\n\t\r\n\t// GJ:  Checking whether the model is visible\r\n\t// is a speed optimization, but it's ugly \r\n\t// because it makes this component dependent on the \r\n\t// model component...  Eventually, I'd like to \r\n\t// find a more elegant solution\r\n\t\t\r\n\t// update the skeleton, if it exists\r\n\tDbg_Assert(mp_model_component);\r\n\tNx::CModel* p_model = mp_model_component->GetModel();\r\n\tif ( p_model && p_model->GetActive() )\r\n\t{\r\n\t\tMth::Vector sphere = p_model->GetBoundingSphere();\r\n\t\t\r\n\t\tprintf (\"sphere = (%.2f,%.2f,%.2f,%.2f)\\n\",sphere[X],sphere[Y],sphere[Z],sphere[W]);\r\n\r\n\t\t// GJ:  The bounding sphere may have a position\r\n\t\t// offset built into it, so need to factor that in\r\n\t\tMth::Vector pos = GetObject()->GetPos() + sphere;\r\n\t\tpos[W] = 1.0f;\r\n\t\t\r\n\t\t// Mick:  This visibility test always returns true\r\n\t\t// when in split screen mode \t\r\n\t\tif ( !Nx::CEngine::sIsVisible( pos,sphere[3] ) )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t// for now, just always animate, even if no model, or the model is inactive !?\r\n\treturn true;\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::update_skeleton()\r\n{\r\n\tif ( has_anims() )\r\n\t{\r\n\t\tGfx::CSkeleton* pSkeleton = NULL;\r\n\t\t\r\n\t\tDbg_Assert(mp_skeleton_component);\r\n\t\tpSkeleton = mp_skeleton_component->GetSkeleton();\r\n\r\n\t\tif ( !pSkeleton )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Set the current view distance for the skeleton so that it may decide on an appropriate set of\r\n\t\t// bones to use in the animation.\r\n\t\tpSkeleton->SetBoneSkipDistance( m_parent_object_dist_to_camera );\r\n\r\n\t\tint numBlendChannels = m_blendChannelList.CountItems();\r\n\r\n\t\tfor ( int blendChannel = 0; blendChannel < numBlendChannels; blendChannel++ )\r\n\t\t{\r\n\t\t\t// this wil loop through each blend channel's animation channels\r\n\t\t\tget_blend_channel( blendChannel, &sBlendPoses[blendChannel], &sBlendValues[blendChannel] );\r\n\t\t}\r\n\r\n\t\t// TODO: Here, we could run any controllers that need to act on the final, post-blend pose...\r\n\t\tif( numBlendChannels > 1 )\r\n\t\t{\r\n\t\t\tblend( &sBlendPoses[0], &sBlendValues[0], pSkeleton->GetNumBones(), &sResultPose, numBlendChannels );\r\n\t\t\tpSkeleton->Update( &sResultPose );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// In the case that there is just one blend channel, there is no requirement to call the blend\r\n\t\t\t// function, which will needlessly copy the quaternion and translation values for each bone from\r\n\t\t\t// the sBlendPoses buffer to the sResultPose buffer. Just use the sBlendPoses buffer directly. \r\n\t\t\tpSkeleton->Update( &sBlendPoses[0] );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAnimationComponent::FlipAnimation( uint32 objId, bool flip, uint32 time, bool propagate )\r\n{\r\n\tif( propagate )\r\n\t{\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tGameNet::PlayerInfo* player;\r\n        \t\t\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( objId );\r\n\t\tif( player && player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tNet::Client* client;\r\n\t\t\tGameNet::MsgFlipAnim msg;\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\t\r\n\t\t\tclient = gamenet_man->GetClient( player->GetSkaterNumber());\r\n\t\t\tDbg_Assert( client );\r\n\r\n\t\t\tmsg.m_ObjId = objId;\r\n\t\t\tmsg.m_Flipped = flip;\r\n\t\t\t//msg.m_Time = time;\r\n\r\n\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgFlipAnim );\r\n\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_FLIP_ANIM;\r\n\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t}\r\n\t}\r\n\r\n\tbool oldFlipped = m_flags & nxANIMCOMPONENTFLAGS_FLIPPED;\r\n\r\n\tSetFlipState( flip );\r\n\r\n    return oldFlipped;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CAnimationComponent::SetFlipState( bool shouldFlip )\r\n{\r\n\t// TODO:  should actually be in blend channel code\r\n\t// since we want certain blend channels to be flipped\r\n\t// (the animation component will still need to know\r\n\t// which flip state to make new channels)\r\n\r\n\tm_flags &= ~nxANIMCOMPONENTFLAGS_FLIPPED;\r\n\tm_flags |= ( shouldFlip ? nxANIMCOMPONENTFLAGS_FLIPPED : 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CAnimationComponent::destroy_blend_channels()\r\n{\r\n\tm_blendChannelList.DestroyAllNodes();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\r\nvoid CAnimationComponent::initialize_procedural_bones( Script::CStruct* pParams )\r\n{\r\n\tScript::CArray* pArray;\r\n\r\n\tpParams->GetArray( CRCD(0x3ed7262b,\"bone_list\"), &pArray, Script::ASSERT );\r\n\t\r\n\tfor ( uint32 i = 0; i < pArray->GetSize(); i++ )\r\n\t{\r\n\t\tthis->InitializeProceduralBone( pArray->GetChecksum(i) );\r\n\t}\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\r\nvoid CAnimationComponent::update_procedural_bones()\r\n{\r\n\tint numProceduralBones = this->GetNumProceduralBones(); \r\n\tGfx::CProceduralBone* p_current_procedural_bone = this->GetProceduralBones();\r\n\r\n\tfor ( int i = 0; i < numProceduralBones; i++ )\r\n\t{\r\n\t\t// TODO:  Factor in the frame rate...\r\n\t\t\r\n\t\tif ( p_current_procedural_bone->transEnabled )\r\n\t\t{\r\n\t\t\tp_current_procedural_bone->currentTrans += p_current_procedural_bone->deltaTrans;\r\n\t\t\tp_current_procedural_bone->currentTrans[X] = (int)p_current_procedural_bone->currentTrans[X] & 0xfff;\r\n\t\t\tp_current_procedural_bone->currentTrans[Y] = (int)p_current_procedural_bone->currentTrans[Y] & 0xfff;\r\n\t\t\tp_current_procedural_bone->currentTrans[Z] = (int)p_current_procedural_bone->currentTrans[Z] & 0xfff;\r\n\t\t}\r\n\r\n\t\tif ( p_current_procedural_bone->rotEnabled )\r\n\t\t{\r\n\t\t\tp_current_procedural_bone->currentRot += p_current_procedural_bone->deltaRot;\r\n\t\t\tp_current_procedural_bone->currentRot[X] = (int)p_current_procedural_bone->currentRot[X] & 0xfff;\r\n\t\t\tp_current_procedural_bone->currentRot[Y] = (int)p_current_procedural_bone->currentRot[Y] & 0xfff;\r\n\t\t\tp_current_procedural_bone->currentRot[Z] = (int)p_current_procedural_bone->currentRot[Z] & 0xfff;\r\n\t\t}\r\n\r\n\t\tif ( p_current_procedural_bone->scaleEnabled )\r\n\t\t{\r\n\t\t\tp_current_procedural_bone->currentScale += p_current_procedural_bone->deltaScale;\r\n\t\t\tp_current_procedural_bone->currentScale[X] = (int)p_current_procedural_bone->currentScale[X] & 0xfff;\r\n\t\t\tp_current_procedural_bone->currentScale[Y] = (int)p_current_procedural_bone->currentScale[Y] & 0xfff;\r\n\t\t\tp_current_procedural_bone->currentScale[Z] = (int)p_current_procedural_bone->currentScale[Z] & 0xfff;\r\n\t\t}\r\n\r\n\t\tp_current_procedural_bone++;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CAnimationComponent::InitializeProceduralBone( uint32 boneName )\r\n{\r\n\tif ( m_numProceduralBones >= vMAXPROCEDURALBONES )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Too many procedural bones\" ) );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tGfx::CProceduralBone* pBone = &mp_proceduralBones[m_numProceduralBones];\r\n\r\n\tpBone->m_name = boneName;\r\n\r\n\tpBone->transEnabled = false;\r\n\tpBone->rotEnabled = true;\r\n\r\n\tpBone->trans0[X] = Script::GetFloat( CRCD(0x802638f7,\"trans_min_x\"), Script::NO_ASSERT );\r\n\tpBone->trans0[Y] = Script::GetFloat( CRCD(0xf7210861,\"trans_min_y\"), Script::NO_ASSERT );\r\n\tpBone->trans0[Z] = Script::GetFloat( CRCD(0x6e2859db,\"trans_min_z\"), Script::NO_ASSERT);\r\n\tpBone->trans0[W] = 1.0f;\r\n\r\n\tpBone->trans1[X] = Script::GetFloat( CRCD(0x5d39cfda,\"trans_max_x\"), Script::NO_ASSERT );\r\n\tpBone->trans1[Y] = Script::GetFloat( CRCD(0x2a3eff4c,\"trans_max_y\"), Script::NO_ASSERT );\r\n\tpBone->trans1[Z] = Script::GetFloat( CRCD(0xb337aef6,\"trans_max_z\"), Script::NO_ASSERT );\r\n\tpBone->trans1[W] = 1.0f;\r\n\r\n\tpBone->currentTrans = Mth::Vector(0.0f,0.0f,0.0f,0.0f);\r\n\tpBone->deltaTrans = Mth::Vector(32.0f,32.0f,32.0f,0.0f);\r\n\r\n\tpBone->rot0[X] = Script::GetFloat( CRCD(0x2dafa9c5,\"rot_min_x\"), Script::NO_ASSERT ) * 2.0f * Mth::PI / 4096.0f;\r\n\tpBone->rot0[Y] = Script::GetFloat( CRCD(0x5aa89953,\"rot_min_y\"), Script::NO_ASSERT ) * 2.0f * Mth::PI / 4096.0f;\r\n\tpBone->rot0[Z] = Script::GetFloat( CRCD(0xc3a1c8e9,\"rot_min_z\"), Script::NO_ASSERT ) * 2.0f * Mth::PI / 4096.0f;\r\n\tpBone->rot0[W] = 1.0f;\r\n\r\n\tpBone->rot1[X] = Script::GetFloat( CRCD(0xf0b05ee8,\"rot_max_x\"), Script::NO_ASSERT ) * 2.0f * Mth::PI / 4096.0f;\r\n\tpBone->rot1[Y] = Script::GetFloat( CRCD(0x87b76e7e,\"rot_max_y\"), Script::NO_ASSERT ) * 2.0f * Mth::PI / 4096.0f;\r\n\tpBone->rot1[Z] = Script::GetFloat( CRCD(0x1ebe3fc4,\"rot_max_z\"), Script::NO_ASSERT ) * 2.0f * Mth::PI / 4096.0f;\r\n\tpBone->rot1[W] = 1.0f;\r\n\r\n\tpBone->currentRot = Mth::Vector(0.0f,0.0f,0.0f,0.0f);\r\n\tpBone->deltaRot = Mth::Vector(32.0f,32.0f,32.0f,0.0f);\r\n\r\n\tpBone->scale0[X] = 1.0f; //Script::GetFloat(\"scale_min_x\",Script::NO_ASSERT) * 2.0f * Mth::PI / 4096.0f;\r\n\tpBone->scale0[Y] = 1.0f; //Script::GetFloat(\"scale_min_y\",Script::NO_ASSERT) * 2.0f * Mth::PI / 4096.0f;\r\n\tpBone->scale0[Z] = 1.0f; //Script::GetFloat(\"scale_min_z\",Script::NO_ASSERT) * 2.0f * Mth::PI / 4096.0f;\r\n\tpBone->scale0[W] = 1.0f;\r\n\r\n\tpBone->scale1[X] = 1.0f; //Script::GetFloat(\"scale_max_x\",Script::NO_ASSERT) * 2.0f * Mth::PI / 4096.0f;\r\n\tpBone->scale1[Y] = 1.0f; //Script::GetFloat(\"scale_max_y\",Script::NO_ASSERT) * 2.0f * Mth::PI / 4096.0f;\r\n\tpBone->scale1[Z] = 1.0f; //Script::GetFloat(\"scale_max_z\",Script::NO_ASSERT) * 2.0f * Mth::PI / 4096.0f;\r\n\tpBone->scale1[W] = 1.0f;\r\n\r\n\tpBone->currentScale = Mth::Vector(0.0f,0.0f,0.0f,0.0f);\r\n\tpBone->deltaScale = Mth::Vector(32.0f,32.0f,32.0f,0.0f);\r\n\r\n\tm_numProceduralBones++;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nGfx::CProceduralBone* CAnimationComponent::GetProceduralBoneByName( uint32 boneName )\r\n{\r\n\tfor ( int i = 0; i < m_numProceduralBones; i++ )\r\n\t{\r\n\t\tif ( boneName == mp_proceduralBones[i].m_name )\r\n\t\t{\r\n\t\t\treturn &mp_proceduralBones[i];\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CAnimationComponent::GetNumProceduralBones()\r\n{\r\n\treturn m_numProceduralBones;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGfx::CProceduralBone* CAnimationComponent::GetProceduralBones()\r\n{\r\n\treturn mp_proceduralBones;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CAnimationComponent::IsFlipped()\r\n{\r\n\treturn m_flags & nxANIMCOMPONENTFLAGS_FLIPPED;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimationComponent::Finalize()\r\n{\r\n\tmp_skeleton_component = GetSkeletonComponentFromObject( GetObject() );\r\n\tmp_suspend_component = GetSuspendComponentFromObject( GetObject() );\r\n\tmp_model_component = GetModelComponentFromObject( GetObject() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/animationcomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       AnimationComponent.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/24/2002\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_ANIMATIONCOMPONENT_H__\r\n#define __COMPONENTS_ANIMATIONCOMPONENT_H__\r\n\t\t\t\t\t\t\t\t   \r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <core/list.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <gfx/blendchannel.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_ANIMATION CRCD(0x72ad7b23,\"Animation\")\r\n#define\t\tGetAnimationComponent() ((Obj::CAnimationComponent*)GetComponent(CRC_ANIMATION))\r\n#define\t\tGetAnimationComponentFromObject(pObj) ((Obj::CAnimationComponent*)(pObj)->GetComponent(CRC_ANIMATION))\r\n\r\nnamespace Gfx\r\n{\r\n\tclass CBonedAnimFrameData;\r\n\tclass CPose;\r\n\tclass CProceduralBone;\r\n}\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CSuspendComponent;\r\n\tclass CSkeletonComponent;\r\n\tclass CModelComponent;\r\n\r\nclass CAnimationComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CAnimationComponent();\r\n    virtual ~CAnimationComponent();\r\n\r\npublic:\r\n\t// Basic component functions\r\n    virtual void            \t\tUpdate();\r\n    virtual void\t\t\t\t\tFinalize( );\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams ); \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void\t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\tvirtual void\t\t\t\t\tProcessWait( Script::CScript * pScript );\r\n\t\r\n    static CBaseComponent*\t\t\ts_create();\r\n\r\npublic:\r\n\t// Viewer functions\r\n    void       \t\t            \tPrintStatus();\r\n\tvoid\t\t\t\t\t\t\tAddTime( float incVal );\r\n\tfloat                       \tGetCurrentAnimTime( void );\r\n\r\npublic:\r\n    void\t\t\t\t\t\t\tSetAnims( uint32 anim_checksum );\r\n\tvoid                        \tReset();\r\n\tvoid\t\t\t\t        \tPlaySequence(uint32 checksum, float BlendPeriod=0.3f );    \r\n    bool\t\t\t\t        \tAnimEquals(Script::CStruct *pParams, Script::CScript *pScript );\r\n    uint32                      \tPlayAnim(Script::CStruct *pParams, Script::CScript *pScript, float defaultBlendPeriod = 0.3f );\r\n\tuint32\t\t\t\t\t\t\tGetAnimScriptName() const { return m_animScriptName; }\r\n\tuint32\t\t\t\t\t\t\tGetAnimEventTableName() const { return m_animEventTableName; }\r\n\r\npublic:\r\n    // TODO:  Eventually, make this class completely independent of Gfx...\r\n    // (You shouldn't need to reference CBonedAnimFrameData from this class...)\r\n    float                       \tAnimDuration( uint32 checksum );\r\n    bool                       \t\tAnimExists( uint32 checksum );\r\n    \t\t\r\nprotected:\r\n\tbool\t\t\t\t\t\t\tShouldBlend();\r\n\r\npublic:\r\n\tvoid\t\t\t\t\t\t\tEnableBlending( bool enabled );\r\n\tvoid \t\t\t\t\t\t\tToggleFlipState();\r\n\tvoid\t\t\t\t\t\t\tUpdateSkeleton();\r\n\r\npublic:\r\n\t// CLIENT FUNCTIONS\r\n\tvoid\t\t\t\t        \tPlayPrimarySequence( uint32 index, bool propagate, float start_time = 0.0f, float end_time = 1000.0f, Gfx::EAnimLoopingType loop_type = Gfx::LOOPING_CYCLE, float blend_period = 0.3f, float speed = 1.0f );\r\n\r\n\tvoid\t\t\t\t        \tSetLoopingType( Gfx::EAnimLoopingType loopingType, bool propagate );\r\n\tvoid\t\t\t\t        \tSetAnimSpeed( float speed, bool propagate, bool all_channels = false );\r\n    float\t\t\t\t        \tGetAnimSpeed( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvoid\t\t\t\t\t\t\tReverseDirection( bool propagate );\t\r\n\r\n\t// called once per frame, during manuals!\r\n\tvoid\t\t\t\t        \tSetWobbleTarget(float alpha, bool propagate);\r\n\r\n\t// should not be called once per frame...  only when the trick changes\r\n\tvoid\t\t\t\t        \tSetWobbleDetails( const Gfx::SWobbleDetails& wobble_details, bool propagate );\r\n\t\r\n\tbool\t\t\t\t    \t\tFlipAnimation( uint32 objId, bool flip, uint32 time, bool propagate );\r\n\tvoid\t\t\t\t\t\t\tSetFlipState( bool shouldFlip );\r\n\tvoid\t\t\t\t\t\t\tSetBoneRotation( uint32 boneId, bool shouldRotate );\r\n\tbool\t\t\t\t\t\t\tIsFlipped();\r\n\tvoid\t\t\t\t\t\t\tAddAnimController( Script::CStruct* pParams );\r\n\tbool\t\t\t\t\t\t\tShouldAnimate();\r\n\t\r\npublic:\r\n\t// SERVER-ONLY FUNCTIONS\r\n\tbool\t\t\t\t        \tIsAnimComplete( void );\r\n\tbool\t\t\t\t        \tIsLoopingAnim( void );\r\n\tuint32\t\t\t\t        \tGetCurrentSequence( void );\r\n\tvoid\t\t\t\t        \tGetPrimaryAnimTimes(float *pStart, float *pCurrent, float *pEnd);\r\n\r\nprotected:\r\n\tGfx::CBlendChannel*\t\t\t\tget_primary_channel();\r\n\tvoid\t\t\t\t\t\t\tpack_degenerate_channels();\r\n    Gfx::CBonedAnimFrameData*\t\tfind_actual_anim( uint32 checksum );\r\n\tint\t\t\t\t\t\t\t\tget_num_degenerate_anims();\r\n\r\nprotected:\r\n\tbool\t\t\t\t\t\t\thas_anims() { return m_animScriptName != 0; }\r\n\tvoid\t\t\t\t\t\t\tupdate_skeleton();\r\n\r\n\tvoid\t\t\t\t\t\t\tget_blend_channel( int blendChannel, Gfx::CPose* pResultPose, float* pBlendVal );\r\n\tvoid\t\t\t\t\t\t\tdestroy_blend_channels();\r\n\tvoid\t\t\t\t\t\t\tcreate_new_blend_channel( float blend_period );\r\n\tvoid\t\t\t\t\t\t\tadd_anim_tags( uint32 animName );\r\n\tvoid\t\t\t\t\t\t\tdelete_anim_tags();\r\n\r\nprotected:\r\n\tLst::Head<Gfx::CAnimChannel>\tm_blendChannelList;\r\n\r\n    // Get set by the BlendPeriodOut command.\r\n\tbool                        \tmGotBlendPeriodOut;\r\n\tfloat                       \tmBlendPeriodOut;\r\n\r\n\tbool\t\t\t\t\t\t\tm_shouldBlend;\r\n\t\r\n\t// If set, then PlayAnim will do nothing until the current anim has finished.\r\n\tbool\t\t\t\t\t\t\tm_dont_interrupt;\r\n\t\r\n    uint32                      \tm_animScriptName;\r\n\tuint32\t\t\t\t\t\t\tm_flags;\r\n\t\r\n\t// GJ:  This might get split into its own component later on\r\n\t// (among other things, it can then have its own suspend logic)\r\n\tuint32\t\t\t\t\t\t\tm_animEventTableName;\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_last_animation_time;\r\n\tbool\t\t\t\t\t\t\tm_animation_script_block_active;\r\n\tfloat\t\t\t\t\t\t\tm_animation_script_unblock_point;\r\n\r\n\tfloat\t\t\t\t\t\t\tm_parent_object_dist_to_camera;\r\n\r\n\t// GJ:  The following used to be in the CProceduralAnimController;\r\n\t// however, this data needs to be shared among different blend\r\n\t// channels so I had to move it here.  Maybe there should be a \r\n\t// way to copy a controller from one blend channel to another?  \r\n\t// For now, I'm just going to go with the easy implementation\r\n\t// until there's a pressing need for it.  Maybe this should be\r\n\t// separated off into a separate CProceduralAnimComponent that \r\n\t// the CProceduralAnimController acts upon?)\r\nprotected:\r\n\tint\t\t\t\t\t\t\t\tm_numProceduralBones;\r\n\tGfx::CProceduralBone*\t\t\tmp_proceduralBones;\r\n\tbool\t\t\t\t\t\t\tInitializeProceduralBone( uint32 boneName );\r\n\tvoid\t\t\t\t\t\t\tinitialize_procedural_bones( Script::CStruct* pParams );\r\n\tvoid\t\t\t\t\t\t\tupdate_procedural_bones();\r\n\t\r\nprotected:\r\n\tCSuspendComponent*\t\t\t\tmp_suspend_component;\r\n\tCSkeletonComponent*\t\t\t\tmp_skeleton_component;\r\n\tCModelComponent*\t\t\t\tmp_model_component;\r\n\r\npublic:\r\n\tGfx::CProceduralBone*\t\t\tGetProceduralBoneByName( uint32 id );\r\n\tint\t\t\t\t\t\t\t\tGetNumProceduralBones();\r\n\tGfx::CProceduralBone*\t\t\tGetProceduralBones();\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/avoidcomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       AvoidComponent.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/02/02\r\n//****************************************************************************\r\n\r\n#include <gel/components/avoidcomponent.h>\r\n\r\n#include <core/math.h>\r\n\t\t\t\t\t\t\t\t\t\r\n#include <gel/object/compositeobject.h>\r\n\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/motioncomponent.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/skeleton.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/pathob.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/engine/feeler.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool ped_debug_on()\r\n{\r\n\treturn ( Script::GetInt( CRCD(0x59f8e435,\"ped_debug\"), false ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic int get_jump_direction( float rotAng )\r\n{\r\n\t// split into forward/left/back/right quadrants \r\n\t// by shifting the angle by 45 degrees\r\n\r\n\trotAng += Mth::PI / 4.0f;\r\n\tif ( rotAng < 0 )\r\n\t{\r\n\t\trotAng += Mth::PI * 2.0f;\r\n\t}\r\n\r\n\tint direction = (int)( rotAng / ( Mth::PI / 2.0f ) );\r\n\r\n\treturn direction;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic float get_jump_distance( Script::CStruct* pParams, float rotAng )\r\n{\r\n\tDbg_Assert( pParams );\r\n\r\n\tint direction = get_jump_direction( rotAng );\r\n\r\n\tfloat distance = 0.0f;\r\n\r\n\tswitch ( direction )\r\n\t{\r\n\t\tcase 1:\t// left\r\n\t\t\tpParams->GetFloat( \"distLeft\", &distance, Script::ASSERT );\r\n\t\t\tbreak;\r\n\r\n\t\tcase 2:\t// backward\r\n\t\t\tpParams->GetFloat( \"distBack\", &distance, Script::ASSERT );\r\n\t\t\tbreak;\r\n\r\n\t\tcase 3:\t// right\r\n\t\t\tpParams->GetFloat( \"distRight\", &distance, Script::ASSERT );\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase 0: // forward\r\n\t\tcase 4:\r\n\t\tdefault:\r\n\t\t\tpParams->GetFloat( \"distForward\", &distance, Script::ASSERT );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\treturn distance;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic bool collides_with( Mth::Vector& vec0, Mth::Vector& vec1 )\r\n{\r\n\tCFeeler\tfeeler;\r\n\t\r\n\tfeeler.m_start = vec0;\r\n\tfeeler.m_end = vec1;\r\n\r\n\treturn feeler.GetCollision();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\nvoid CAvoidComponent::draw_collision_circle( int numPoints, float radius, uint32 rgb0 )\r\n{\r\n\tMth::Vector v1, v2;\r\n\r\n\tMth::Vector fwd( 0.0f, 0.0f, radius );\r\n\r\n\tv1 = m_pos + fwd;\r\n\r\n\tfor ( int i = 0; i < numPoints; i++ )\r\n\t{\r\n\t\tfwd.RotateY( 2.0f * Mth::PI / (float)numPoints );\r\n\t\tv2 = GetObject()->m_pos + fwd;\r\n\r\n\t\tif ( !collides_with( GetObject()->m_pos, v2 ) )\r\n\t\t{\r\n\t\t\tGfx::AddDebugLine(v1,v2,rgb0,rgb0,1);\r\n\t\t}\r\n\r\n\t\tv1 = v2;\r\n\t}\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAvoidComponent::play_appropriate_jump_anim( float rotAng, Script::CStruct* pParams )\r\n{\r\n\t// split into forward/left/back/right quadrants \r\n\t// by shifting the angle by 45 degrees\r\n\r\n\trotAng += Mth::PI / 4.0f;\r\n\tif ( rotAng < 0 )\r\n\t{\r\n\t\trotAng += Mth::PI * 2.0f;\r\n\t}\r\n\r\n\tint direction = (int)( rotAng / ( Mth::PI / 2.0f ) );\r\n\t// 0 = forward\r\n\t// 1 = left\r\n\t// 2 = back\r\n\t// 3 = right\r\n\r\n\tDbg_Assert( pParams );\r\n\r\n\tuint32 animChecksum;\r\n\tbool flipped;\r\n\r\n\tswitch ( direction )\r\n\t{\r\n\t\tcase ( 0 ):\t// JUMP FORWARD\r\n\t\tcase ( 4 ):\r\n//\t\t\tDbg_Message( \"Ped jumps forward to avoid skater\" );\r\n\t\t\tpParams->GetChecksum( CRCD(0x4de2c9e8,\"JumpForward\"), &animChecksum, true );\r\n\t\t\tbreak;\r\n\r\n\t\tcase ( 1 ):\t// JUMP LEFT\r\n\t\t\t{\r\n//\t\t\t\tDbg_Message( \"Ped jumps left to avoid skater\" );\r\n\t\t\t\tif ( pParams->GetChecksum( CRCD(0x733da756,\"JumpLeft\"), &animChecksum, false ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tflipped = 0;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpParams->GetChecksum( CRCD(0xa7a0dd72,\"JumpRight\"), &animChecksum, true );\r\n\t\t\t\t\tflipped = 1;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\t\t\t\tif ( pAnimationComponent )\r\n\t\t\t\t{\r\n\t\t\t\t\tpAnimationComponent->FlipAnimation( GetObject()->GetID(), flipped, 0, true );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase ( 2 ):\t// JUMP BACK\r\n//\t\t\tDbg_Message( \"Ped jumps back to avoid skater\" );\r\n\t\t\tpParams->GetChecksum( CRCD(0x64948109,\"JumpBack\"), &animChecksum, true );\r\n\t\t\tbreak;\r\n\r\n\t\tcase ( 3 ):\t// JUMP RIGHT\r\n\t\t\t{\r\n//\t\t\t\tDbg_Message( \"Ped jumps right to avoid skater\" );\r\n\t\t\t\tif ( pParams->GetChecksum( CRCD(0xa7a0dd72,\"JumpRight\"), &animChecksum, false ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tflipped = 0;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpParams->GetChecksum( CRCD(0x733da756,\"JumpLeft\"), &animChecksum, true );\r\n\t\t\t\t\tflipped = 1;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\t\t\t\tif ( pAnimationComponent )\r\n\t\t\t\t{\r\n\t\t\t\t\tpAnimationComponent->FlipAnimation( GetObject()->GetID(), flipped, 0, true );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Ped jumped in unrecognized direction: %d\", direction ) );\r\n\t\t\treturn;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t}\r\n\t\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\r\n    if ( pAnimationComponent )\r\n    {\r\n        pAnimationComponent->PlaySequence( animChecksum, 0 );\r\n        m_jumpTime = pAnimationComponent->AnimDuration( animChecksum );\r\n    }\r\n    else\r\n    {\r\n        Dbg_MsgAssert( 0, ( \"No animation component\" ) );\r\n    }\r\n}\r\n                                                                 \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CAvoidComponent::get_ideal_heading()\r\n{\r\n\tMdl::Skate* skate = Mdl::Skate::Instance();\r\n\t\t\t\t\r\n\t// assume pedestrians only appear in \"1 player\" game for now...\r\n\t// If this assumption becomes incorrect, cycle through skate->GetNumSkaters( )\r\n\t// and find the closest.\r\n\tCSkater *pSkater = skate->GetLocalSkater();\r\n\tDbg_MsgAssert( pSkater, ( \"Ped avoidance only works in 1-player games.\" ) );\r\n\t\r\n\tMth::Vector jumpDir;\r\n\r\n\t// find the 2 directions perpendicular to the skater's line of motion...\r\n\t// and select the direction that will take us further away from the\r\n\t// skater\r\n\t\r\n\tjumpDir = (pSkater->GetDisplayMatrix())[Mth::AT];\t\r\n\tjumpDir[Y] = 0.0f;\r\n\tjumpDir.Normalize( );\r\n\t\r\n\tMth::Vector upVect( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\tjumpDir = Mth::CrossProduct( jumpDir, upVect );\r\n\r\n\t// chose the direction that's farther...\r\n\tMth::Vector posPlus;\r\n\tMth::Vector posMinus;\r\n\tposPlus = GetObject()->m_pos + jumpDir;\r\n\tposMinus = GetObject()->m_pos - jumpDir;\r\n\t\t\t\r\n\tif ( Mth::DistanceSqr( pSkater->m_pos, posPlus ) < Mth::DistanceSqr( pSkater->m_pos, posMinus ) )\r\n\t{\r\n\t\tjumpDir[X] = -jumpDir[X];\r\n\t\tjumpDir[Z] = -jumpDir[Z];\r\n\t}\r\n\t\r\n\treturn Mth::RadToDeg( Mth::GetAngle( GetObject()->m_matrix, jumpDir ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// This static function is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\nCBaseComponent* CAvoidComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CAvoidComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCAvoidComponent::CAvoidComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_AVOID );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCAvoidComponent::~CAvoidComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CAvoidComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CAvoidComponent::Update()\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n//\tif ( ped_debug_on() )\r\n\t{\r\n\t\t//Gfx::AddDebugCircle( m_pos, 20, 15.0f, 0x0000ffff, 1 );\r\n\t\t//Gfx::AddDebugCircle( m_stored_pos, 20, 15.0f, 0x00ff00ff, 1 );\r\n\t\t//draw_collision_circle( 100, 50.0f, 0xff0000ff );\t\r\n\t}\r\n#else\r\n\t// Doing nothing, so tell code to do nothing next time around\r\n\tSuspend(true);\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAvoidComponent::jump( Mth::Matrix& mat0, Mth::Matrix& mat1, float rotAng, float jumpDist, float maxHerdDistance )\r\n{\r\n\tmat1 = mat0;\r\n\t\r\n\tmat1.RotateYLocal( Mth::DegToRad(rotAng) );\r\n\r\n\t// test for an extra 15 units (1.25 feet) radius of clearance \r\n\t// around the player to account for his actual body\r\n\t// (need to rotate it slightly up, to account for peds\r\n\t// that are below ground level...  not sure why this\r\n\t// happens, but will check it out in THPS5...)\r\n\tconst float clearanceDist = 15.0f;\r\n\tMth::Vector collisionTestPos = mat1.Transform( Mth::Vector( 0.0f, 10.0f, jumpDist + clearanceDist ) );\r\n\t\r\n#ifdef __NOPT_ASSERT__\r\n/*\r\n\tif ( ped_debug_on() )\r\n\t{\r\n\t\tGfx::AddDebugCircle( collisionTestPos, 20, 15.0f, 0x00ff00ff, 10 );\r\n\t}\r\n*/\r\n#endif\r\n\r\n\tif ( collides_with( mat0.GetPos(), collisionTestPos ) )\r\n\t{\r\n\t\tDbg_Message( \"Collides with something!\" );\r\n\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// build target matrix\r\n\t\tMth::Vector targetPos = mat1.Transform( Mth::Vector( 0.0f, 0.0f, jumpDist ) );\r\n\t\tmat1[Mth::POS] = targetPos;\r\n\r\n\t\tMdl::Skate* skate = Mdl::Skate::Instance();\r\n\t\tCSkater *pSkater = skate->GetLocalSkater();\r\n\t\tDbg_MsgAssert( pSkater, ( \"Ped avoidance only works in 1-player games.\" ) );\r\n\t\t\r\n\t\tMth::Vector toSkater = targetPos - pSkater->m_pos;\r\n\t\tif ( toSkater.Length() < 30.0f )\r\n\t\t{\r\n\t\t\tprintf( \"Too close to skater %f!\\n\", toSkater.Length() );\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// check if we're going too far from the original point\r\n\t\t// TODO:  check for distance from the path, not the point\r\n\t\t// don't allow going too far from the original path,\r\n\t\t// or else you'll be able to herd them into weird\r\n\t\t// positions...\r\n\t\tMth::Vector totalAvoidVec = targetPos - m_avoidOriginalPos;\r\n\t\ttotalAvoidVec[Y] = 0.0f;\r\n\r\n\t\tif ( totalAvoidVec.Length() >= maxHerdDistance )\r\n\t\t{\r\n\t\t\tDbg_Message( \"Too far from the original avoid point %f\", totalAvoidVec.Length() );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent::EMemberFunctionResult CAvoidComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch (Checksum)\r\n\t{\r\n\t\t// @script | Ped_SelectAvoidPoint | Will cause the pedestrian to jump out of\r\n\t\t// the way of the player.  He will land on a circle, JumpDist away from\r\n\t\t// the last postition stored in Obj_StorePos.  Once he lands the jump,\r\n\t\t// the LandedEscapeJump exception is triggered. \r\n\t\t// @parmopt name | JumpLeft | jumpLeft | name of anim to play when jumping left\r\n\t\t// @parmopt name | JumpRight | jumpRight | name of anim to play when jumping right\r\n\t\t// @parmopt name | JumpForward | jumpForward | name of anim to play when jumping forward\r\n\t\t// @parmopt name | JumpBack | jumpBack | name of anum to play when jumping back\r\n\t\t// position where the ped jumps to \r\n\t\tcase 0x6157cbc0:\t// Ped_SelectAvoidPoint\r\n\t\t{\r\n\t\t\t// this is the starting point...\r\n\t\t\tMth::Matrix mat0;\r\n\t\t\tmat0 = GetObject()->GetDisplayMatrix();\r\n\t\t\tmat0[Mth::POS] = GetObject()->m_pos;\r\n\r\n\t\t\t// this is where we will eventually end up\r\n\t\t\tMth::Matrix mat1;\r\n\r\n\t\t\tfloat maxHerdDistance = 100.0f;\r\n\t\t\tpParams->GetFloat( \"maxHerdDistance\", &maxHerdDistance, Script::NO_ASSERT );\r\n\r\n\t\t\tfloat idealHeading = get_ideal_heading();\r\n\r\n\t\t\tif ( jump(mat0, mat1, idealHeading, get_jump_distance( pParams, idealHeading ), maxHerdDistance ) )\r\n\t\t\t{\r\n\t\t\t   Dbg_Message( \"Selecting ideal jump (ang=%f newpos=(%f, %f, %f)\",\r\n\t\t\t\t\t\t\tidealHeading,\r\n\t\t\t\t\t\t\tmat1[Mth::POS][X],\r\n\t\t\t\t\t\t\tmat1[Mth::POS][Y],\r\n\t\t\t\t\t\t\tmat1[Mth::POS][Z] );   \t\t\t\r\n\t\t\t}\r\n\r\n\t\t\t// GJ:  Try a few more directions before trying \r\n\t\t\t// to jump back to the original point...\r\n\t\t\telse if ( jump(mat0, mat1, idealHeading + 180.0f, get_jump_distance( pParams, idealHeading + 180.0f ), maxHerdDistance) )\r\n\t\t\t{\r\n\t\t\t\t// jump to the other side was successful!\r\n\t\t\t\tprintf( \"Jumping to the other side...\\n\" );\r\n\t\t\t}\r\n\t\t\telse if ( jump(mat0, mat1, idealHeading - 90.0f, get_jump_distance( pParams, idealHeading - 90.0f ), maxHerdDistance) )\r\n\t\t\t{\r\n\t\t\t\t// jump away was successful!\r\n\t\t\t\tprintf( \"Jumping away...\\n\" );\r\n\t\t\t}\r\n\t\t\telse \r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"Jumping back towards original point %f %f %f\",\r\n\t\t\t\t\t\t\t m_avoidOriginalPos[X],\r\n\t\t\t\t\t\t\t m_avoidOriginalPos[Y],\r\n\t\t\t\t\t\t\t m_avoidOriginalPos[Z] );\r\n\r\n\t\t\t\t// otherwise, jump back towards original point\r\n\t\t\t\tMth::Vector jumpDir;\r\n\t\t\t\tjumpDir = m_avoidOriginalPos - mat0[Mth::POS];\r\n\r\n\t\t\t\tfloat rotAng;\r\n\t\t\t\trotAng = Mth::GetAngle( GetObject()->m_matrix, jumpDir );\r\n\r\n\t\t\t\tbool success = jump( mat0, mat1, rotAng, get_jump_distance(pParams, rotAng), maxHerdDistance );\r\n\r\n\t\t\t\tif ( !success )\r\n\t\t\t\t{\r\n\t\t\t\t\t// jump in place\r\n\t\t\t\t\tmat1 = mat0;\r\n\r\n\t\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\r\n\t\t\t}  \t\t\t\r\n\r\n\t\t\t// don't actually want to rotate the ped\r\n\t\t\t// (just translate it)\r\n\t\t\tmat1[Mth::RIGHT] = mat0[Mth::RIGHT];\r\n\t\t\tmat1[Mth::UP] = mat0[Mth::UP];\r\n\t\t\tmat1[Mth::AT] = mat0[Mth::AT];\r\n\r\n\t\t\tm_avoidInterpolator.setMatrices( &mat0, &mat1 );\r\n\t\t\tm_avoidAlpha = 0.0f;\r\n\r\n#ifdef __NOPT_ASSERT__\r\n/*\r\n\t\t\tif ( ped_debug_on() )\r\n\t\t\t{\r\n\t\t\t\tGfx::AddDebugCircle( mat0[Mth::POS], 20, 15.0f, 0x00ff00ff, 100 );\r\n\t\t\t\tGfx::AddDebugCircle( mat1[Mth::POS], 20, 15.0f, 0x00ff00ff, 100 );\r\n\t\t\t}\r\n*/\r\n#endif\r\n\r\n\t\t\tMth::Vector jumpDir;\r\n\t\t\tjumpDir = mat1[Mth::POS] - mat0[Mth::POS];\r\n\r\n\t\t\tfloat rotAng;\r\n\t\t\trotAng = Mth::GetAngle( GetObject()->m_matrix, jumpDir );\r\n\r\n\t\t\t// rotAng of zero means jump forward, so:\r\n\t\t\tplay_appropriate_jump_anim( rotAng, pParams );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\t// @script | Ped_BackOnOriginalPath |\r\n\t\tcase 0xd2aa4d2d:\t// Ped_BackOnOriginalPath\r\n\t\t{\r\n\t\t\tfloat safeDist;\r\n\t\t\tsafeDist = pParams->GetFloat( \"dist\", &safeDist, Script::ASSERT );\r\n\r\n\t\t\tMth::CBBox theBox;\r\n\t\t\ttheBox.SetMin( m_avoidOriginalPos - Mth::Vector( safeDist, safeDist, safeDist ) );\r\n\t\t\ttheBox.SetMax( m_avoidOriginalTargetPos + Mth::Vector( safeDist, safeDist, safeDist ) );\r\n\r\n\t\t\tif ( theBox.Within( GetObject()->m_pos ) )\r\n\t\t\t{\r\n\t\t\t\tprintf( \"Intersects!\\n\" ); \r\n\t\t\t//\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tprintf( \"Doesn't intersect!\\n\" ); \r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\r\n#if 0\r\n\t\t\tMth::Vector originalPath;\r\n\t\t\toriginalPath = m_avoidOriginalTargetPos - m_avoidOriginalPos;\r\n\r\n\t\t\tMth::Vector upVect( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t\t\tMth::Vector normalToOriginalPath;\r\n\t\t\tnormalToOriginalPath = Mth::CrossProduct( originalPath, upVect );\r\n\r\n\t\t\t// is the distance to the original path\r\n\t\t\t// choose the direction that's closer...\r\n\t\t\tMth::Vector posPlus;\r\n\t\t\tMth::Vector posMinus;\r\n\t\t\tposPlus = GetObject()->m_pos + normalToOriginalPath * safeDist;\r\n\t\t\tposMinus = GetObject()->m_pos - normalToOriginalPath * safeDist;\r\n\r\n\t\t\tMth::Line originalLine( m_avoidOriginalTargetPos, m_avoidOriginalPos );\r\n\t\t\tMth::Line currentLine1( m_avoidOriginalTargetPos, posPlus ); \r\n\t\t\tMth::Line currentLine2( m_avoidOriginalTargetPos, posMinus ); \r\n\r\n\t\t\tMth::Vector my_pt;\r\n\t\t\tMth::Vector other_pt;\r\n\t\t\tfloat dummyFloat;\r\n\r\n\t\t\tif ( Mth::LineLineIntersect( originalLine, currentLine1, &my_pt, &other_pt, &dummyFloat, &dummyFloat, false ))\r\n\t\t\t{\r\n\t\t\t\tMth::Vector difference = my_pt - other_pt;\r\n\t\t\t\tprintf( \"intersects with current line 1: %f\\n\", difference.Length() );\r\n\t\t\t//\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t\telse if ( Mth::LineLineIntersect( originalLine, currentLine2, &my_pt, &other_pt, &dummyFloat, &dummyFloat, false ))\r\n\t\t\t{\r\n\t\t\t\tMth::Vector difference = my_pt - other_pt;\r\n\t\t\t\tprintf( \"intersects with current line 2: %f\\n\", difference.Length() );\r\n\t\t\t//\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tprintf( \"does not intersect\\n\" );\r\n\t\t//\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n#endif\r\n\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\t// @script | Ped_MoveTowardsAvoidPoint |\r\n\t\tcase 0x41226942:\t// Ped_MoveTowardsAvoidPoint\r\n\t\t{\r\n\t\t\tMth::Matrix mat0;\r\n\t\t\tm_avoidAlpha += ( m_jumpTime * ( 1.0f / 60.0f ) * Tmr::FrameRatio() );\r\n\t\t\tm_avoidInterpolator.getMatrix( &mat0, m_avoidAlpha );\r\n\t\t\tGetObject()->m_pos = mat0[Mth::POS];\r\n\t\t\tGetObject()->m_matrix = mat0;\r\n\t\t\tGetObject()->m_matrix[Mth::POS] = Mth::Vector(0.0f, 0.0f, 0.0f, 1.0f);\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\t// @script | Ped_AvoidPointReached |\r\n\t\tcase 0x3c7f8f3e:\t// Ped_AvoidPointReached\r\n\t\t{\r\n\t\t\tDbg_Assert( GetAnimationComponentFromObject( GetObject() ) );\r\n\t\t\treturn ( m_avoidAlpha >= 1.0f && GetAnimationComponentFromObject( GetObject() )->IsAnimComplete() ) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0x6a4bca91:\t// Ped_RememberCurrentPosition\r\n\t\t\tm_avoidOriginalPos = GetObject()->m_pos;\r\n\t\tbreak;\r\n\r\n\t\tcase 0x3fb422e8:\t// Ped_RememberNextWaypoint\r\n\t\t{\r\n\t\t\tObj::CMotionComponent* pMotionComponent = GetMotionComponentFromObject( GetObject() );\r\n\t\t\tif ( pMotionComponent && pMotionComponent->GetPathOb() )\r\n\t\t\t{\r\n\t\t\t\tm_avoidOriginalTargetPos = pMotionComponent->GetPathOb()->m_wp_pos_to;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_avoidOriginalTargetPos = GetObject()->m_pos;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0x539a32dc:\t// Ped_RememberStickToGround\r\n\t\t{\r\n\t\t\tObj::CMotionComponent* pMotionComponent = GetMotionComponentFromObject( GetObject() );\r\n\t\t\tDbg_Assert( pMotionComponent );\r\n\t\t\tm_avoidOriginalStickToGround = ( pMotionComponent->m_movingobj_flags |= MOVINGOBJ_FLAG_STICK_TO_GROUND );\r\n\t\t}\t\r\n\t\tbreak;\r\n\r\n\t\tcase 0x53bc3b4e:\t// Ped_RestoreStickToGround\r\n\t\t{\r\n\t\t\tObj::CMotionComponent* pMotionComponent = GetMotionComponentFromObject( GetObject() );\r\n\t\t\tif ( pMotionComponent )\r\n\t\t\t{\r\n\t\t\t\tif ( m_avoidOriginalStickToGround )\r\n\t\t\t\t{\r\n\t\t\t\t\tpMotionComponent->m_movingobj_flags |= MOVINGOBJ_FLAG_STICK_TO_GROUND;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpMotionComponent->m_movingobj_flags &= ~MOVINGOBJ_FLAG_STICK_TO_GROUND;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAvoidComponent::GetDebugInfo( Script::CStruct* p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to C......Component::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\t/*\r\n\tp_info->AddInteger(\"m_never_suspend\",m_never_suspend);\r\n\tp_info->AddFloat(\"m_suspend_distance\",m_suspend_distance);\r\n\t*/\r\n\t\r\n\t// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo( p_info );\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/avoidcomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       AvoidComponent.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/02/02\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_AVOIDCOMPONENT_H__\r\n#define __COMPONENTS_AVOIDCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <core/math/slerp.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/components/pedlogiccomponent.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_AVOID CRCD(0x6eb050ed,\"Avoid\")\r\n#define\t\tGetAvoidComponent() ((CAvoidComponent*)GetComponent(CRC_AVOID))\r\n#define\t\tGetAvoidComponentFromObject(pObj) ((CAvoidComponent*)(pObj)->GetComponent(CRC_AVOID))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CAvoidComponent : public CBaseComponent\r\n{\r\n// share, dammit.\r\nfriend class CPedLogicComponent;\r\n\r\npublic:\r\n    CAvoidComponent();\r\n    virtual ~CAvoidComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\nprotected:\r\n\tvoid\t\t\t\t\t\t\tplay_appropriate_jump_anim( float rotAngle, Script::CStruct* pParams );\r\n\tbool\t\t\t\t\t\t\tjump( Mth::Matrix& mat0, Mth::Matrix& mat1, float rotAng, float jumpDist, float maxHerdDistance );\r\n\tfloat\t\t\t\t\t\t\tget_ideal_heading();\r\n\r\nprotected:\r\n\t// Functions/member variables used for getting out of the skater's way:\r\n\tfloat\t\t\t\t\t\t\tm_jumpTime;\r\n\r\n\tMth::SlerpInterpolator\t\t\tm_avoidInterpolator;\r\n\tfloat\t\t\t\t\t\t\tm_avoidAlpha;\r\n\tMth::Vector\t\t\t\t\t\tm_avoidOriginalPos;\r\n\tMth::Vector\t\t\t\t\t\tm_avoidOriginalTargetPos;\r\n\tbool\t\t\t\t\t\t\tm_avoidOriginalStickToGround;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/bouncycomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       BouncyComponent.cpp\r\n//* OWNER:          Mick West\r\n//* CREATION DATE:  10/17/2002\r\n//****************************************************************************\r\n\r\n//#define\t__DEBUG_BOUNCY__\r\n\r\n#include <gel/components/Bouncycomponent.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/objsearch.h>\r\n#include <gel/objman.h>\r\n\r\n#include <core/math/slerp.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n\r\n#include <gel/collision/collision.h>\r\n\r\n//#include <sk/objects/movingobject.h>\t\t// TODO:  remove - only used for getting the bouncing box via collision\r\n#include <sk/modules/skate/skate.h>\t\t\t\t// and this\r\n#include <sk/objects/skater.h>\t\t\t\t// and this\r\n\r\nnamespace Obj\r\n{\r\n\r\n#define SWITCH_STATE( x )\t\t\t\t\tm_state = x\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent *\tCBouncyComponent::s_create()\r\n{\r\n\treturn static_cast<CBaseComponent*>(new CBouncyComponent);\t\r\n}\r\n    \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBouncyComponent::CBouncyComponent() : CBaseComponent()\r\n{\r\n\tSetType(CRC_BOUNCY);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBouncyComponent::~CBouncyComponent()\r\n{\r\n\r\n\tif ( mp_bounce_slerp )\r\n\t\tdelete mp_bounce_slerp;\r\n\tif (mp_collide_script_params)\r\n\t\tdelete mp_collide_script_params;\r\n\tif (mp_bounce_script_params)\r\n\t\tdelete mp_bounce_script_params;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Returns \r\n//\t0 (MF_FALSE) if executed and returned false\r\n//  1 (MF_TRUE)  if executed and returned true\r\n//  2 (MF_NOT_EXECUTRED)    if not executed\r\n\r\nCBaseComponent::EMemberFunctionResult CBouncyComponent::CallMemberFunction( uint32 Checksum, Script::CScriptStructure *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tswitch ( Checksum )\r\n\t{\r\n\r\n        // @script | BouncyObj_PlayerCollisionOn | turn player collision on\r\n\t\tcase ( 0xf9055d81 ): // \"BouncyObj_PlayerCollisionOn\"\r\n\t\t\tm_bouncyobj_flags &= ~BOUNCYOBJ_FLAG_PLAYER_COLLISION_OFF;\r\n\t\t\treturn MF_TRUE;\r\n\r\n        \r\n        // @script | BouncyObj_PlayerCollisionOff | turn player collision off\r\n\t\tcase ( 0xf64ef88e ): // \"BouncyObj_PlayerCollisionOff\"\r\n\t\t\tm_bouncyobj_flags |= BOUNCYOBJ_FLAG_PLAYER_COLLISION_OFF;\r\n\t\t\treturn MF_TRUE;\r\n\r\n        // @script | BouncyObj_Go | The vector can be anything you want...\r\n        // the initial velocity.  It's optional, without it the object will\r\n        // fall from it's current location.  If it's already on the ground\r\n        // probably nothing will happen\r\n        // @uparmopt (0, 0, 0) | vector\r\n\t\tcase ( 0xfea0e952 ): // \"BouncyObj_Go\"\r\n\t\t{\r\n\t\t\tMth::Vector vel;\r\n\t\t\tvel.Set( );\r\n\t\t\tpParams->GetVector( NONAME, &vel );\r\n\t\t\tif ( m_state == BOUNCYOBJ_STATE_BOUNCING )\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"\\n%s\\nWarning:  Calling BouncyObj_Go when object is already bouncing.\", pScript->GetScriptInfo( ) );\r\n\t\t\t}\r\n\t\t\tif ( pParams->ContainsFlag( 0x26af9dc9 ) ) // \"FLAG_MAX_COORDS\"\r\n\t\t\t{\r\n\t\t\t\tvel.ConvertToMaxCoords( );\r\n\t\t\t}\r\n\t\t\tbounce( vel );\r\n\t\t\treturn MF_TRUE;\r\n\t\t}\r\n\t}\r\n\treturn MF_NOT_EXECUTED;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CBouncyComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\r\n\tm_time = 0.01666666f;\t\t\t// Patch!!!!\r\n\r\n\tm_state = BOUNCYOBJ_STATE_INIT;\r\n\r\n\tm_bounce_mult = 0.9f;\r\n\tm_bouncyobj_flags = 0;\r\n\r\n\t// Bouncy object properties:\r\n\tm_random_dir = 10;\r\n\tpParams->GetInteger( 0x767f323f, &m_random_dir ); // RandomDirectionOnBounce\r\n\t\r\n\tm_bounce_mult = 0.6f;\r\n\tpParams->GetFloat( 0xaf6034df, &m_bounce_mult ); // BounceMult\r\n\t\r\n\tm_min_bounce_vel = 3;\r\n\tpParams->GetFloat( 0xff08ee44, &m_min_bounce_vel );  // MinBounceVel\r\n\tm_min_bounce_vel = FEET_TO_INCHES( m_min_bounce_vel );\r\n\t\r\n\tm_rot_per_axis = 360;\r\n\tpParams->GetInteger( 0x33ee064f, &m_rot_per_axis ); // ConstRot\r\n\t\r\n\tm_bounce_rot = 45;\r\n\tpParams->GetInteger( 0xde14151d, &m_bounce_rot ); // BounceRot\r\n\t\r\n\tm_rest_orientation_type=0;\r\n\tpParams->GetInteger( 0xc0f30f40, &m_rest_orientation_type ); // RestOrientationType\r\n\r\n\tm_gravity = 32;\r\n\tpParams->GetFloat( 0xa5e2da58, &m_gravity ); // Gravity\r\n\tm_gravity = FEET_TO_INCHES( m_gravity );\r\n\t\r\n\tm_bounciness = 1.0f;\r\n\tpParams->GetFloat( 0x373d4e7d, &m_bounciness ); // Bounciness\r\n\t\r\n\tm_bounce_sound=0;\r\n\tpParams->GetChecksum( 0x1fb2f60c, &m_bounce_sound ); // BounceSound\r\n\t\r\n\tm_hit_sound=0;\r\n\tpParams->GetChecksum( 0x29e2e9e0, &m_hit_sound ); // HitSound\r\n\t\r\n\tm_up_mag = 32.0f;\r\n\tpParams->GetFloat( 0x3eca5c95, &m_up_mag ); // UpMagnitude\r\n\tm_up_mag = FEET_TO_INCHES( m_up_mag );\r\n\t\r\n\tm_destroy_when_done = !pParams->ContainsFlag( 0x65ba5a75 ); // NoDestroy\r\n\t\r\n\tm_min_initial_vel = 15; // feet per second...\r\n\tpParams->GetFloat( 0x96763c79, &m_min_initial_vel ); // MinInitialVel\r\n\tm_min_initial_vel = FEET_TO_INCHES( m_min_initial_vel );\r\n\t\r\n\t// Set up collision\r\n\r\n\tuint32\tcol_type_checksum = Nx::vCOLL_TYPE_NONE;\r\n\tpParams->GetChecksum(\"CollisionMode\", &col_type_checksum);\r\n\t#if 0\r\n\r\n\t\r\n\t// TODO - handle getting bouncing box from a collision component\r\n\tNx::CollType col_type = Nx::CCollObj::sConvertTypeChecksum(col_type_checksum);\r\n\t\r\n\tif (col_type != Nx::vCOLL_TYPE_NONE)\r\n\t{\r\n\t\tm_bounce_collision_radius=0.0f;\r\n\t\tm_skater_collision_radius_squared=0.0f;\r\n//\t\tInitCollision(col_type, p_coll_tri_data);\r\n\t\t// Calc radius from bounding box.\r\n\t\tif (((CMovingObject*)(GetObject()))->GetCollisionObject())\r\n\t\t{\r\n\t\t\tNx::CCollObjTriData *p_tri_data=((CMovingObject*)(GetObject()))->GetCollisionObject()->GetGeometry();\r\n\t\t\tDbg_MsgAssert(p_tri_data,(\"NULL p_tri_data\"));\r\n\t\t\tMth::CBBox bbox=p_tri_data->GetBBox();\r\n\t\t\tm_bounce_collision_radius=Mth::Distance(bbox.GetMax(),bbox.GetMin())/2.0f;\r\n\t\t\tm_skater_collision_radius_squared=m_bounce_collision_radius*m_bounce_collision_radius;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t#endif\r\n\t\r\n\t{\r\n\t\tm_bounce_collision_radius=0.0f;\r\n\t\tm_skater_collision_radius_squared=50.0f;\r\n\t\tpParams->GetFloat(\"CollisionRadius\",&m_skater_collision_radius_squared);\r\n\t\tm_skater_collision_radius_squared*=m_skater_collision_radius_squared;\r\n\t}\r\n\t\r\n\r\n\t// We need to copy in any script struct parameters, as they might have generated temporarily\r\n\tpParams->GetChecksum(CRCD(0x58cdc0f0,\"CollideScript\"),&m_collide_script);\r\n\tScript::CStruct * p_collide_script_params = NULL;\r\n\tpParams->GetStructure(CRCD(0x24031741,\"CollideScriptParams\"),&p_collide_script_params);\t\t\r\n\tif (p_collide_script_params)\r\n\t{\r\n\t\tmp_collide_script_params = new Script::CStruct;\r\n\t\t*mp_collide_script_params += *p_collide_script_params;\r\n\t}\r\n\t\r\n\tpParams->GetChecksum(CRCD(0x2d075f90,\"BounceScript\"),&m_bounce_script);\r\n\tScript::CStruct * p_bounce_script_params = NULL;\r\n\tpParams->GetStructure(CRCD(0x346b0c03,\"BounceScriptParams\"),&p_bounce_script_params);\t\t\r\n\tif (p_bounce_script_params)\r\n\t{\r\n\t\tmp_bounce_script_params = new Script::CStruct;\r\n\t\t*mp_bounce_script_params += *p_bounce_script_params;\r\n\t}\r\n\t\r\n\t\r\n//\t((CMovingObject*)(GetObject()))->RunNodeScript(0x2d075f90/*BounceScript*/,0x346b0c03/*BounceScriptParams*/);\r\n\t\r\n\r\n\r\n\tm_pos = GetObject()->m_pos;\r\n\tm_matrix = GetObject()->m_matrix;\r\n\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CBouncyComponent::Update()\r\n{\r\n\r\n\tMdl::Skate *\tskate_mod =  Mdl::Skate::Instance();\r\n\tuint32 numSkaters = skate_mod->GetNumSkaters( );\r\n\r\n\tm_time = Tmr::FrameLength();\r\n\r\n\tif ( !( m_bouncyobj_flags & BOUNCYOBJ_FLAG_PLAYER_COLLISION_OFF ) )\r\n\t{\r\n\t\tif ( m_state != BOUNCYOBJ_STATE_BOUNCING || ( ( !m_destroy_when_done ) && m_bounce_count ) )\r\n\t\t{\r\n\t\t\tuint32 i;\r\n\t\t\tfor ( i = 0; i < numSkaters; i++ )\r\n\t\t\t{\r\n\t\t\t\tCSkater *pSkater = skate_mod->GetSkater( i );\r\n\t\t\t\t\r\n\t\t\t\t// Very simple collision check ...\r\n\t\t\t\t// Seems to work fine.\r\n\t\t\t\tif ( Mth::DistanceSqr( m_pos, pSkater->m_pos ) < m_skater_collision_radius_squared )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Trigger any collide-script specified in the object's node.\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\t   \r\n\t\t\t\t\t#if 0\r\n\t\t\t\t\t// TODO - handle this RunNodeScript - IF IT IS ACTUALLY EVER USED!!!!!\r\n\t\t\t\t\t((CMovingObject*)GetObject())->RunNodeScript(0x58cdc0f0/*CollideScript*/,0x24031741/*CollideScriptParams*/);\r\n\t\t\t\t\t#else\r\n\t\t\t\t\t// This is also rather messy.  Seems like it would be better\r\n\t\t\t\t\t// to have this handled by an exception\r\n\t\t\t\t\tif (m_collide_script)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tScript::CScript *p_script=Script::SpawnScript(m_collide_script,mp_collide_script_params);\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\tp_script->SetCommentString(\"CBouncyComponent collide script\");\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\tDbg_MsgAssert(p_script,(\"NULL p_script\"));\r\n\t\t\t\t\t\tp_script->mpObject=GetObject();;\r\n\t\t\t\t\t\tp_script->Update();\r\n\t\t\t\t\t}\r\n\t\t\t\t\t#endif\t\t\t   \r\n\r\n\t\t\t\t\t// Trigger the bounce.\r\n\t\t\t\t\tMth::Vector vel;\r\n\t\t\t\t\tvel = pSkater->GetVel( );\r\n\t\t\t\t\tbounce_from_object_vel( vel, pSkater->m_pos );\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n    switch ( m_state )\r\n\t{\r\n\t\tcase ( BOUNCYOBJ_STATE_INIT ):\r\n\t\t\tm_state = BOUNCYOBJ_STATE_IDLE;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ( BOUNCYOBJ_STATE_IDLE ):\r\n\t\t\tbreak;\r\n\r\n\t\tcase ( BOUNCYOBJ_STATE_BOUNCING ):\r\n\t\t\t\r\n\t\t\t// TODO:  The following is needed only to update the position of the object\r\n\t\t\t// This should be done by updating the postion of the model component\r\n\t\t\t#if 0\r\n\t\t\t// TODO - delete this code if it is not used\r\n\t\t\t((CMovingObject*)GetObject())->MovingObj_Update( );    \r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tdo_bounce( );\r\n\t\t\tbreak;\r\n\t\t\t\t\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0,( \"Unknown substate.\" ));\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n#define DTR DEGREES_TO_RADIANS\r\n\r\nfloat get_closest_allowable_angle( float current, float allowableAngle )\r\n{\r\n\t\r\n\tfloat ang;\r\n\tfloat halfAllowable = allowableAngle / 2.0f;\r\n\tang = DTR( -180.0f );\r\n\tang += halfAllowable;\r\n\twhile ( ang < DTR( 180.0f ) )\r\n\t{\r\n\t\tif ( current < ang )\r\n\t\t{\r\n\t\t\treturn ( ang - ( halfAllowable ) );\r\n\t\t}\r\n\t\tang += allowableAngle;\r\n\t}\r\n\treturn ( ang - halfAllowable );\r\n}\r\n\r\nvoid CBouncyComponent::land_on_top_or_bottom( Mth::Vector &rot )\r\n{\r\n\t\r\n\t// x to nearest acceptable:\r\n\tif ( ( rot[ X ] > DTR( 90.0f ) ) || ( rot[ X ] < DTR( -90.0f ) ) )\r\n\t\trot[ X ] = DTR( 180.0f );\r\n\telse\r\n\t\trot[ X ] = 0.0f;\r\n\t// z to nearest acceptable:\r\n\tif ( ( rot[ Z ] > DTR( 90.0f ) ) || ( rot[ Z ] < DTR( -90.0f ) ) )\r\n\t\trot[ Z ] = DTR( 180.0f );\r\n\telse\r\n\t\trot[ Z ] = 0.0f;\r\n}\r\n\r\nvoid CBouncyComponent::land_on_any_face( Mth::Vector &rot )\r\n{\r\n\t\r\n\trot[ X ] = get_closest_allowable_angle( rot[ X ], DTR( 90.0f ) );\r\n\trot[ Y ] = get_closest_allowable_angle( rot[ Y ], DTR( 90.0f ) );\r\n\trot[ Z ] = get_closest_allowable_angle( rot[ Z ], DTR( 90.0f ) );\r\n}\r\n\r\n#define CONE_ANGLE\t110.0f\r\n\r\nvoid CBouncyComponent::land_traffic_cone( Mth::Vector &rot )\r\n{\r\n\t\r\n/*\tif ( rot[ X ] < -DTR( CONE_ANGLE / 2.0f ) )\r\n\t\trot[ X ] = -DTR( CONE_ANGLE );\r\n\telse if ( rot[ X ] > DTR( CONE_ANGLE / 2.0f ) )\r\n\t\trot[ X ] = DTR( CONE_ANGLE );\r\n\telse*/\r\n\t\trot[ X ] = 0;\r\n\r\n\tif ( rot[ Z ] < -DTR( CONE_ANGLE / 2.0f ) )\r\n\t\trot[ Z ] = -DTR( CONE_ANGLE );\r\n\telse if ( rot[ Z ] > DTR( CONE_ANGLE / 2.0f ) )\r\n\t\trot[ Z ] = DTR( CONE_ANGLE );\r\n\telse\r\n\t\trot[ Z ] = 0;\r\n\r\n//\trot[ Y ] = 0;\r\n}\r\n\r\nvoid CBouncyComponent::set_up_quats( void )\r\n{\r\n\t\r\n\tMth::Vector rot;// = currentRot;\r\n\tm_matrix.GetEulers( rot );\r\n\tDbg_MsgAssert( rot[ X ] <= DTR( 180.0f ),( \"Trig functions range from 0 to 360, not -180 to 180.\" ));\r\n\tDbg_MsgAssert( rot[ Y ] <= DTR( 180.0f ),( \"Trig functions range from 0 to 360, not -180 to 180.\" ));\r\n\tDbg_MsgAssert( rot[ Z ] <= DTR( 180.0f ),( \"Trig functions range from 0 to 360, not -180 to 180.\" ));\r\n\t\r\n\tm_quatrot_time_elapsed = 0.0f;\r\n\r\n\t// find out the amount we have to rotate:\r\n\tswitch ( m_rest_orientation_type )\r\n\t{\r\n\t\tcase ( 1 ):  // Upside down, or rightside up:\r\n\t\t\tland_on_top_or_bottom( rot );\r\n\t\t\tbreak;\r\n\r\n\t\tcase ( 2 ):\r\n\t\t\tland_on_any_face( rot );\r\n\t\t\tbreak;\r\n\r\n\t\tcase ( 3 ):\r\n\t\t\tland_traffic_cone( rot );\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ( 0 ):\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0,( \"Unknown rest orientation type: %d\", m_rest_orientation_type ));\r\n\t\t\treturn;\r\n\t\t\tbreak;\r\n\t}\r\n\tif ( !mp_bounce_slerp )\r\n\t{\r\n\t\tmp_bounce_slerp = new Mth::SlerpInterpolator;\r\n\t}\r\n\t\r\n\tMth::Matrix temp( rot[ X ], rot[ Y ], rot[ Z ] );\r\n\tmp_bounce_slerp->setMatrices( &m_matrix, &temp );\r\n\tm_quat_initialized = true;\r\n}\r\n\r\n#define QUAT_ROT_TIME 0.5f\r\n\r\nbool CBouncyComponent::rotate_to_quat( void )\r\n{\r\n\t\r\n\tfloat percent;\r\n\tm_quatrot_time_elapsed += m_time;\r\n\tif ( m_quatrot_time_elapsed >= QUAT_ROT_TIME )\r\n\t{\r\n\t\tpercent = 1.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpercent = m_quatrot_time_elapsed / QUAT_ROT_TIME;\r\n\t}\r\n\r\n\tmp_bounce_slerp->getMatrix( &m_matrix, percent );\r\n\treturn ( percent == 1.0f );\r\n}\r\n\r\n#define MAX_SKATER_VEL 1000.0f  // not exact... just about what the max would be.\r\n\r\nvoid CBouncyComponent::do_bounce( void )\r\n{\r\n\tm_old_pos = m_pos;\r\n\t\r\n\tint temp;\r\n\tswitch ( m_substate )\r\n\t{\r\n\t\tcase ( 0 ):\r\n\t\t\r\n\t\t\t// generate a new constant rotation:\r\n\t\t\ttemp = Mth::Rnd( 8 );\r\n\t\t\tm_rotation[ X ] = DEGREES_TO_RADIANS( ( float ) ( ( m_rot_per_axis >> 2 ) + ( Mth::Rnd( ( m_rot_per_axis >> 2 ) * 3 ) ) ) );\r\n\t\t\tif ( temp & 1 )\r\n\t\t\t{\r\n\t\t\t\tm_rotation[ X ] *= -1.0f;\r\n\t\t\t}\r\n\t\t\tm_rotation[ Y ] = DEGREES_TO_RADIANS( ( float ) ( ( m_rot_per_axis >> 2 ) + ( Mth::Rnd( ( m_rot_per_axis >> 2 ) * 3 ) ) ) );\r\n\t\t\tif ( temp & 2 )\r\n\t\t\t{\r\n\t\t\t\tm_rotation[ Y ] *= -1.0f;\r\n\t\t\t}\r\n\t\t\tm_rotation[ Z ] = DEGREES_TO_RADIANS( ( float ) ( ( m_rot_per_axis >> 2 ) + ( Mth::Rnd( ( m_rot_per_axis >> 2 ) * 3 ) ) ) );\r\n\t\t\tif ( temp & 4 )\r\n\t\t\t{\r\n\t\t\t\tm_rotation[ Z ] *= -1.0f;\r\n\t\t\t}\r\n\t\t\tm_rotation[ W ] = 1.0f;\r\n\t\t\tm_quat_initialized = false;\r\n\t\t\tm_substate++;\r\n\t\t// intentional fall through:\r\n\t\tcase ( 1 ):\r\n\t\t{\r\n\t\t\tMth::Vector rot;\r\n\t\t\tm_pos += m_vel * m_time;\r\n\t\t\tif ( m_quat_initialized )\r\n\t\t\t{\r\n\t\t\t\trotate_to_quat( );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\trot = m_rotation;\r\n\t\t\t\trot *= m_time;\r\n\t\t\t\tm_matrix.RotateLocal( rot );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t// add the radius of the object so we don't stick through the ground:\r\n\t\t\tMth::Vector velNormalized = m_vel;\r\n\t\t\tvelNormalized.Normalize( );\r\n\t\t\tMth::Vector colPoint = m_pos + ( velNormalized * m_bounce_collision_radius );\r\n\t\t\tm_vel[ Y ] -= m_gravity * m_time;\r\n\t\t\tCFeeler feeler;\r\n\t\t\tfeeler.SetLine(m_old_pos, colPoint);\r\n\t\t\tif ( feeler.GetCollision())\r\n\t\t\t{\r\n\t\t\t\t#if 0\r\n\t\t\t\t// TODO - make it work, or remove if not used\r\n\t\t\t\t((CMovingObject*)(GetObject()))->RunNodeScript(0x2d075f90/*BounceScript*/,0x346b0c03/*BounceScriptParams*/);\r\n\t\t\t\t#else\r\n\t\t\t\t// This is also rather messy.  Seems like it would be better\r\n\t\t\t\t// to have this handled by an exception\r\n\t\t\t\tif (m_bounce_script)\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CScript *p_script=Script::SpawnScript(m_bounce_script,mp_bounce_script_params);\r\n\t\t\t\t\tDbg_MsgAssert(p_script,(\"NULL p_script\"));\r\n\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\tp_script->SetCommentString(\"CBouncyComponent bounce script\");\r\n\t\t\t\t\t#endif\r\n\t\t\t\t\tp_script->mpObject=GetObject();;\r\n\t\t\t\t\tp_script->Update();\r\n\t\t\t\t}\r\n\t\t\t\t#endif\r\n\r\n\t\t\t\tm_bounce_count++;\r\n\t\t\t\tMth::Vector v;\r\n\t\t\t\tMth::Vector r;\r\n\t\t\t\tfloat dP;\r\n\t\t\t\tv = m_pos - m_old_pos;\r\n\t\t\t\tMth::Vector n;\r\n\t\t\t\tn = feeler.GetNormal();\r\n\t\t\t\tdP = Mth::DotProduct( v, n );\r\n\t\t\t\tr = ( dP * 2.0f ) * n;\r\n\t\t\t\tr -= v;\r\n\t\t\t\tfloat origVel = m_vel.Length( );\r\n\t\t\t\tm_vel = -r;\r\n\t\t\t\tm_vel.Normalize( origVel * m_bounce_mult );\r\n\t\t\t\tm_vel.RotateY( DTR( ( float ) ( Mth::Rnd( 2 * m_random_dir ) - m_random_dir ) ) );\r\n\t\t\t\tm_pos = feeler.GetPoint() - ( velNormalized * m_bounce_collision_radius );\r\n\t\t\t\tif ( fabsf( m_vel[ Y ] ) < ( m_min_bounce_vel + ( 2.0f *( m_gravity * m_time ) ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( m_rest_orientation_type )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( !m_quat_initialized )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tset_up_quats( );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tm_substate++;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t#if 0\r\n\t\t\t\t\t// TODO - make it work, or remove if not used\r\n\t\t\t\t\t// This \"HigerLevel\" is probably redundant for bouncy obs\r\n\t\t\t\t\t((CMovingObject*)(GetObject()))->HigherLevel( false );\r\n\t\t\t\t\t#endif\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\tSWITCH_STATE( BOUNCYOBJ_STATE_IDLE );\r\n\t\t\t\t\tif ( m_destroy_when_done )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tGetObject()->MarkAsDead( );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t#if 0\r\n\t\t\t\t\t\t// TODO - get exceptions working\r\n\t\t\t\t\t\tGetExceptionComponentFromObject( GetObject() )->FlagException( 0x61682835 ); // DoneBouncing\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif ( origVel > m_min_bounce_vel * 2.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( m_bounce_sound )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// adjust volume depending on magnitude of current velocity:\r\n\t\t\t\t\t\t#if 0\r\n\t\t\t\t\t\t// TODO - Get Bouncy object sounds working with components\r\n\t\t\t\t\t\tfloat vol;\r\n\t\t\t\t\t\tvol = 100.0f * ( origVel / ( MAX_SKATER_VEL * m_bounciness ) );\r\n\t\t\t\t\t\tfloat pitch = 80.0f + ( float ) Mth::Rnd( 40 );\r\n\t\t\t\t\t\t((CMovingObject*)(GetObject()))->PlaySound_VolumeAndPan( m_bounce_sound, vol, pitch );\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// bounce rot:\r\n\t\t\t\t\tif ( m_bounce_rot )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\trot[ X ] = DEGREES_TO_RADIANS( ( float )( Mth::Rnd( m_bounce_rot * 2 ) - m_bounce_rot ) );\r\n\t\t\t\t\t\trot[ Y ] = DEGREES_TO_RADIANS( ( float )( Mth::Rnd( m_bounce_rot * 2 ) - m_bounce_rot ) );\r\n\t\t\t\t\t\trot[ Z ] = DEGREES_TO_RADIANS( ( float )( Mth::Rnd( m_bounce_rot * 2 ) - m_bounce_rot ) );\r\n\t\t\t\t\t\tm_matrix.RotateLocal( rot );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tm_substate = 0;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( m_rest_orientation_type )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !m_quat_initialized )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// rotate to the resting orientation:\r\n\t\t\t\t\t\tset_up_quats( );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase ( 2 ):\r\n\t\t\tif ( rotate_to_quat( ) )\r\n\t\t\t{\r\n\t\t\t\t#if 0\r\n\t\t\t\t((CMovingObject*)(GetObject()))->HigherLevel( false );\r\n\t\t\t\t#endif\r\n\t\t\t\t\r\n\t\t\t\tSWITCH_STATE( BOUNCYOBJ_STATE_IDLE );\r\n\t\t\t\tif ( m_destroy_when_done )\r\n\t\t\t\t{\r\n\t\t\t\t\tGetObject()->MarkAsDead( );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_Message( 0, \"Woah!  Fire matt immediately.\" );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\t#ifdef\t__DEBUG_BOUNCY__\t\r\n//\tprintf (\"%d: %s: (%.2f,%.2f,%.2f)\\n\",__LINE__,__PRETTY_FUNCTION__,m_pos[X],m_pos[Y],m_pos[Z]); \r\n\t#endif\r\n\t\r\n\tGetObject()->m_pos = m_pos;\r\n\tGetObject()->m_matrix = m_matrix;\r\n\tGetObject()->SetDisplayMatrix(m_matrix);\r\n\t\r\n\t\r\n}\r\n\r\nvoid CBouncyComponent::bounce( const Mth::Vector &vel )\r\n{\r\n\r\n\t#ifdef\t__DEBUG_BOUNCY__\t\r\n//\tprintf (\"%d: %s: (%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f)\\n\",__LINE__,__PRETTY_FUNCTION__,vel[X],vel[Y],vel[Z]); \r\n\t#endif\r\n\t\r\n\tm_vel = vel;\r\n\tif ( m_hit_sound )\r\n\t{\r\n\t\t// adjust volume depending on magnitude of current velocity:\r\n\t\t#if 0\r\n\t\t// TODO - sound components for bouncy object\r\n\t\tfloat vol;\r\n\t\tvol = 100.0f * ( m_vel.Length( ) / MAX_SKATER_VEL );\r\n\t\tfloat pitch = 80.0f + ( float ) Mth::Rnd( 40 );\r\n\t\t((CMovingObject*)(GetObject()))->PlaySound_VolumeAndPan( m_hit_sound, vol, pitch );\r\n\t\t#endif\r\n\t}\r\n\tif ( m_bounciness != 1.0f )\r\n\t{\r\n\t\tm_vel *= m_bounciness;\r\n\t}\r\n\tm_bounce_count = 0;\r\n\t#if 0\r\n\t// TODO - is HigherLevel even needed here?  or just cut and paste from some other object?\r\n\t((CMovingObject*)(GetObject()))->HigherLevel( true );\r\n\t#endif\r\n\tSWITCH_STATE( BOUNCYOBJ_STATE_BOUNCING );\r\n\t#if 0\r\n\t// TODO - exceptions working as a component\r\n\tGetExceptionComponentFromObject( GetObject() )->FlagException( 0x7dc30ba6 ); // Bounce\r\n\t#endif\r\n}\r\n\r\n\r\n// Given an object velocity, then calculate the velocity to bounce by\r\nvoid CBouncyComponent::bounce_from_object_vel( const Mth::Vector &vel, const Mth::Vector &pos )\r\n{\r\n\r\n\t#ifdef\t__DEBUG_BOUNCY__\t\r\n//\tprintf (\"%d: %s: (%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f)\\n\",__LINE__,__PRETTY_FUNCTION__,vel[X],vel[Y],vel[Z],pos[X],pos[Y],pos[Z]); \r\n\t#endif\r\n\t\r\n\tMth::Vector vel2 = vel;\r\n\t\r\n\tfloat mag;\r\n\tmag = vel2.Length( );\r\n\tif ( mag < m_min_initial_vel )\r\n\t{\r\n\t\tmag = m_min_initial_vel;\r\n\t\tvel2.Normalize( mag );\r\n\t}\r\n\tMth::Vector dir = m_pos - pos;\r\n\tdir.Normalize( mag );\r\n\tvel2 += dir * ( ( ( float ) ( 50 + Mth::Rnd( 100 ) ) ) / 100.0f );\r\n\tvel2.Normalize( mag );\r\n\tvel2[ Y ] = ( m_up_mag * ( mag + MAX_SKATER_VEL ) ) / ( MAX_SKATER_VEL * 2.0f );\r\n\tbounce(vel2);\r\n}\r\n\r\nvoid CBouncyComponent::GetDebugInfo( Script::CStruct* p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CBouncyComponent::GetDebugInfo\"));\r\n\t// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n\r\n\tp_info->AddChecksum(\"m_collide_script\",m_collide_script);\r\n\tp_info->AddStructure(\"mp_collide_script_params\",mp_collide_script_params);\r\n\r\n\tp_info->AddChecksum(\"m_bounce_script\",m_bounce_script);\r\n\tp_info->AddStructure(\"mp_bounce_script_params\",mp_bounce_script_params);\r\n#endif\t\t\t\t \r\n}\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/carphysicscomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       CarPhysicsComponent.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  11/4/2002\r\n//****************************************************************************\r\n\r\n#include <gel/components/carphysicscomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n\r\n#include <gel/components/skeletoncomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\t \r\n#include <gfx/nxhierarchy.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/skeleton.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n//\t#define vMAX_WHEEL_Y_ROT ( 70.0f )\r\n//\t#define vMAX_CAR_X_ROT ( 5.0f )\r\n//\t#define vMIN_CAR_X_ROT ( -5.0f )\r\n//\t#define vSTEP_CAR_X_ROT ( 0.125f )\r\n//\t#define vACCEL_TO_CAR_ROT_FACTOR ( 3.0f )\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// This static function is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\nCBaseComponent* CCarPhysicsComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CCarPhysicsComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCarPhysicsComponent::CCarPhysicsComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_CARPHYSICS );\r\n\t\r\n\tm_wheelRotationX = 0.0f;\r\n\tm_wheelRotationY = 0.0f;\r\n\tm_targetWheelRotationY = 0.0f;\r\n\r\n\tm_shadowEnabled = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCarPhysicsComponent::~CCarPhysicsComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCarPhysicsComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// set up some car physics parameters\r\n\tm_minCarRot = Script::GetFloat( CRCD(0x877db8da,\"accelCarRot\"), Script::ASSERT );\r\n\tpParams->GetFloat( CRCD(0x877db8da,\"accelCarRot\"), &m_minCarRot );\r\n\t\r\n\tm_maxCarRot = Script::GetFloat( CRCD(0xfb3464df,\"decelCarRot\"), Script::ASSERT );\r\n\tpParams->GetFloat( CRCD(0xfb3464df,\"decelCarRot\"), &m_maxCarRot );\r\n\t\r\n\tm_stepCarRot = Script::GetFloat( CRCD(0xfd8bc8d6,\"speedCarRot\"), Script::ASSERT );\r\n\tpParams->GetFloat( CRCD(0xfd8bc8d6,\"speedCarRot\"), &m_stepCarRot );\r\n\t\r\n\tm_accelToCarRotFactor = Script::GetFloat( CRCD(0xb2c7447b,\"accelCarRotFactor\"), Script::ASSERT );\r\n\tpParams->GetFloat( CRCD(0xb2c7447b,\"accelCarRotFactor\"), &m_accelToCarRotFactor );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCarPhysicsComponent::Update()\r\n{\r\n\t// Doing nothing, so tell code to do nothing next time around\r\n\tSuspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent::EMemberFunctionResult CCarPhysicsComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tcase CRCC(0xa2331896,\"EnableCarShadow\"):\r\n\t\t\t{\r\n\t\t\t\tint enabled = 0;\r\n\t\t\t\tpParams->GetInteger( NONAME, &enabled, Script::NO_ASSERT );\r\n\t\t\t\tm_shadowEnabled = enabled;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t\t\tbreak;\r\n\r\n\t}\r\n\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCarPhysicsComponent::init_car_skeleton()\r\n{\t\r\n\t// Does some sanity checks\r\n\tObj::CSkeletonComponent* pSkeletonComponent = (Obj::CSkeletonComponent*)(GetObject()->GetComponent( CRC_SKELETON ));\r\n\tGfx::CSkeleton* pSkeleton = NULL;\r\n\tif ( pSkeletonComponent )\r\n\t{\r\n\t\tpSkeleton = pSkeletonComponent->GetSkeleton();\r\n\t}\r\n\t\r\n\tObj::CModelComponent* pModelComponent = (Obj::CModelComponent*)(GetObject()->GetComponent( CRC_MODEL ));\r\n\tNx::CModel* pModel = NULL;\r\n\tif ( pModelComponent )\r\n\t{\r\n\t\tpModel = pModelComponent->GetModel();\r\n\t}\r\n\t\r\n\tDbg_MsgAssert( pSkeleton, (\"Car has no skeleton\") );\r\n\tDbg_MsgAssert( pModel, ( \"Model hasn't been set up yet\" ) );\r\n\t\r\n\tDbg_MsgAssert( pModel->GetHierarchy(), (\"veh flagged as car has no hierarchy from node %s\", Script::FindChecksumName(GetObject()->GetID())));\r\n\tNx::CHierarchyObject* pHierarchyObjects = pModel->GetHierarchy();\r\n\tDbg_MsgAssert(( pHierarchyObjects + 0 ),(\"Missing matrix in car\"));\r\n\tDbg_MsgAssert(( pHierarchyObjects + 2 ),(\"Missing matrix in car\"));\r\n\tDbg_MsgAssert(( pHierarchyObjects + 4 ),(\"Missing matrix in car\"));\r\n\r\n\t// TODO:  This 5-bone hierarchy shouldn't be so hardcoded...\r\n\t// We should somehow make this generic so that we \r\n\t// can use different skeletons with the car physics.\r\n\r\n\tMth::Matrix frontTire = ( pHierarchyObjects + 2 )->GetSetupMatrix();\r\n\tfrontTire *= ( pHierarchyObjects + 0 )->GetSetupMatrix();\r\n\tMth::Matrix backTire = ( pHierarchyObjects + 4 )->GetSetupMatrix();\r\n\tbackTire *= ( pHierarchyObjects + 0 )->GetSetupMatrix();\r\n\r\n\tMth::Vector dist = frontTire[Mth::POS] - backTire[Mth::POS];\r\n\tm_distanceBetweenTires = fabs( dist.Length() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/carphysicscomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       CarPhysicsComponent.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  11/4/2002\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_CARPHYSICSCOMPONENT_H__\r\n#define __COMPONENTS_CARPHYSICSCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_CARPHYSICS CRCD(0xc695136d,\"CarPhysics\")\r\n#define\t\tGetCarPhysicsComponent() ((Obj::CCarPhysicsComponent*)GetComponent(CRC_CARPHYSICS))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CCarPhysicsComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CCarPhysicsComponent();\r\n    virtual ~CCarPhysicsComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\t\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\npublic:\r\n\tvoid\t\t\t\t\t\t\tinit_car_skeleton();\r\n\t\r\npublic:\r\n\t// public only during the transition\r\n\t\r\n\t// for wheel rotation\r\n\tfloat\t\t\t\t\t\t\tm_wheelRotationX;\r\n\tfloat\t\t\t\t\t\t\tm_wheelRotationY;\r\n\tfloat\t\t\t\t\t\t\tm_targetWheelRotationY;\r\n\tfloat\t\t\t\t\t\t\tm_carRotationX;\r\n\tfloat\t\t\t\t\t\t\tm_targetCarRotationX;\r\n\tfloat\t\t\t\t\t\t\tm_distanceBetweenTires;\r\n\tfloat\t\t\t\t\t\t\tm_old_vel_z;\r\n\r\n\t// for car rocking back and forth\r\n\tfloat\t\t\t\t\t\t\tm_minCarRot;\r\n\tfloat\t\t\t\t\t\t\tm_maxCarRot;\r\n\tfloat\t\t\t\t\t\t\tm_stepCarRot;\r\n\tfloat\t\t\t\t\t\t\tm_accelToCarRotFactor;\r\n\r\n\tbool\t\t\t\t\t\t\tm_shadowEnabled;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/collisioncomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       CollisionComponent.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/31/2002\r\n//****************************************************************************\r\n\r\n#include <gel/components/Collisioncomponent.h>\r\n\r\n#include <gel/assman/assman.h>\r\n#include <gel/collision/collision.h>\r\n#include <gel/collision/movcollman.h>\r\n\r\n#include <gel/components/modelcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/checksum.h>\r\n\t\t\t\t\t\t\t\r\n#include <gfx/nx.h>\r\n#include <gfx/nxhierarchy.h>\r\n#include <gfx/nxmesh.h>\r\n#include <gfx/nxmodel.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// This static function is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\nCBaseComponent* CCollisionComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CCollisionComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCollisionComponent::CCollisionComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_COLLISION );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCollisionComponent::~CCollisionComponent()\r\n{\r\n\tif ( mp_collision )\r\n\t{\r\n\t\tNx::CMovableCollMan::sRemoveCollision( mp_collision );\r\n\t\t// We don't want to do this after we start the PIP loading\r\n\t\tdelete mp_collision;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCollisionComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\t\r\n\tDbg_MsgAssert( pParams, ( \"No node data?\" ) );\r\n\tDbg_MsgAssert( !mp_collision, ( \"Set up collision twice?\" ) );\r\n\r\n\tuint32 col_type_checksum = Nx::vCOLL_TYPE_NONE;\r\n\tpParams->GetChecksum( CRCD(0x2d7e583b,\"CollisionMode\"), &col_type_checksum );\r\n\t\r\n\tNx::CollType col_type = Nx::CCollObj::sConvertTypeChecksum( col_type_checksum );\r\n\tif ( col_type != Nx::vCOLL_TYPE_NONE )\r\n\t{\r\n\t\tuint32 class_checksum = 0;\r\n\t\tpParams->GetChecksum(\"class\", &class_checksum);\r\n\t\tif ( class_checksum == CRCD(0xb7b3bd86,\"LevelObject\") )\r\n\t\t{\r\n\t\t\tuint32 name;\r\n\t\t\tpParams->GetChecksum(CRCD(0xa1dc81f9,\"name\"), &name, Script::ASSERT);\r\n\t\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(name);\r\n\t\t\tDbg_MsgAssert( p_sector, ( \"WARNING: sGetSector(0x%x) returned NULL (%s)\\n\", name, Script::FindChecksumName(name) ) );\r\n\t\t\tNx::CCollObjTriData *p_coll_tri_data = p_sector->GetCollSector()->GetGeometry();\r\n\t\t\tInitCollision(col_type, p_coll_tri_data);   \r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tInitCollision(col_type);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCollisionComponent::InitCollision( Nx::CollType type, Nx::CCollObjTriData *p_coll_tri_data )\r\n{\t\t\r\n\tDbg_Assert( !mp_collision );\r\n\r\n\tif ( p_coll_tri_data )\r\n\t{\r\n\t\tmp_collision = Nx::CCollObj::sCreateMovableCollision(type, p_coll_tri_data, 1, GetObject());\r\n\t} \r\n\telse\r\n\t{\r\n\t\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( GetObject() );\r\n\t\tDbg_MsgAssert( pModelComponent, ( \"Initing collision on something with no model component\" ) );\r\n\r\n\t\tNx::CModel* pModel = pModelComponent->GetModel();\r\n\t\tDbg_MsgAssert( pModel, ( \"Initing collision on something with no model\" ) );\r\n\r\n\t\tAss::CAssMan * ass_man = Ass::CAssMan::Instance();\r\n\t\tNx::CMesh* pMesh = (Nx::CMesh*)ass_man->GetAsset(pModel->GetFileName(), false);\r\n\t\tif (pMesh)\r\n\t\t{\r\n\t\t\tmp_collision = Nx::CCollObj::sCreateMovableCollision(type, pMesh->GetCollisionTriDataArray(), pMesh->GetCollisionTriDataArraySize(), GetObject());\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_collision = Nx::CCollObj::sCreateMovableCollision(type, NULL, 0, GetObject());\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nNx::CCollObj* CCollisionComponent::GetCollision() const\r\n{\r\n\treturn mp_collision;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCollisionComponent::Teleport()\r\n{\r\n\t// GJ:  the collision component's Update()\r\n\t// function doesn't really require finalization\r\n\t// right now, but having this assert in here\r\n\t// might help catch future errors\r\n\tDbg_MsgAssert( GetObject()->IsFinalized(), ( \"Has not been finalized!  Tell Gary!\" ) );\r\n\r\n\tUpdate();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCollisionComponent::Update()\r\n{\r\n//\tGJ:  On THPS4, we did the following test first before\r\n//\tupdating the collision;  I think this will be handled\r\n//\tby the suspend component, so we shouldn't have to do\r\n//  this here...\r\n//\tif ( (m_object_flags & vINVISIBLE) && !initialize )\r\n//\t{\r\n//\t\treturn;\r\n//\t}\r\n\r\n\t// get the collision object\r\n\tNx::CCollObj* p_coll = GetCollision();\r\n\t\r\n\t// Update collision\r\n\t// Might be problem with things being LODed off, but still needing collision?\r\n\tif ( p_coll )\r\n\t{\r\n\t\t// GJ TODO:  Somehow remove the collision object's dependency on the model!\r\n\r\n\t\tNx::CModel*\tp_model = NULL;\r\n\t\tNx::CHierarchyObject* p_hierarchy = NULL;\r\n\t\tObj::CModelComponent* p_model_component = GetModelComponentFromObject( GetObject() );\r\n\t\tif ( p_model_component )\r\n\t\t{\r\n\t\t\tp_model = p_model_component->GetModel();\r\n\t\t\tDbg_MsgAssert( p_model, ( \"No model?!?\" ) );\r\n\t\t\tp_hierarchy = p_model->GetHierarchy();\r\n\t\t}\r\n\r\n\t\tif (p_hierarchy)\r\n\t\t{\r\n\t\t\tMth::Vector translation(p_hierarchy->GetSetupMatrix()[W]);\r\n\t\t\ttranslation[W] = 0.0f;\t\t// turn into vector\r\n\t\t\tp_hierarchy->GetSetupMatrix().Transform(translation);\t\t// Re-orients the translation\r\n\r\n\t\t\tp_coll->SetWorldPosition( GetObject()->GetPos() + translation );\r\n\t\t\tp_coll->SetOrientation( p_hierarchy->GetSetupMatrix() * GetObject()->GetDisplayMatrix() );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_coll->SetWorldPosition( GetObject()->GetPos() );\r\n\t\t\tp_coll->SetOrientation( GetObject()->GetDisplayMatrix() );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent::EMemberFunctionResult CCollisionComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n//    Dbg_Assert( 0 );\r\n\r\n    return CBaseComponent::MF_NOT_EXECUTED;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/collisioncomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       CollisionComponent.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/24/2002\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_COLLISIONCOMPONENT_H__\r\n#define __COMPONENTS_COLLISIONCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <gel/collision/collenums.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_COLLISION CRCD(0xa432dc41,\"Collision\")\r\n#define\t\tGetCollisionComponent() ((Obj::CCollisionComponent*)GetComponent(CRC_COLLISION))\r\n#define\t\tGetCollisionComponentFromObject(pObj) ((Obj::CCollisionComponent*)(pObj)->GetComponent(CRC_COLLISION))\r\n\r\nnamespace Nx\r\n{\r\n\tclass CCollObj;\r\n\tclass CCollObjTriData;\r\n}\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CCollisionComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CCollisionComponent();\r\n    virtual ~CCollisionComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n\tvirtual void            \t\tTeleport();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\t\r\n    static CBaseComponent*\t\t\ts_create();\r\n\t\r\npublic:\r\n\tNx::CCollObj*\t\t\t\t\tGetCollision() const;\r\n\r\nprotected:\r\n\tvirtual void\t\t\t\t\tInitCollision( Nx::CollType type, Nx::CCollObjTriData *p_coll_tri_data = NULL );\r\n\tNx::CCollObj*\t\t\t\t\tmp_collision;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/emptycomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       EmptyComponent.cpp\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ???\r\n//****************************************************************************\r\n\r\n// The CEmptyComponent class is an skeletal version of a component\r\n// It is intended that you use this as the basis for creating new\r\n// components.  \r\n// To create a new component called \"Watch\", (CWatchComponent):\r\n//  - copy emptycomponent.cpp/.h to watchcomponent.cpp/.h\r\n//  - in both files, search and replace \"Empty\" with \"Watch\", preserving the case\r\n//  - in WatchComponent.h, update the CRCD value of CRC_WATCH\r\n//  - in CompositeObjectManager.cpp, in the CCompositeObjectManager constructor, add:\r\n//\t\t  \tRegisterComponent(CRC_WATCH,\t\t\tCWatchComponent::s_create); \r\n//  - and add the include of the header\r\n//\t\t\t#include <gel/components/watchcomponent.h> \r\n//  - Add it to build\\gel.mkf, like:\r\n//          $(NGEL)/components/WatchComponent.cpp\\\r\n//  - Fill in the OWNER (yourself) and the CREATION DATE (today's date) in the .cpp and the .h files\r\n//\t- Insert code as needed and remove generic comments\r\n//  - remove these comments\r\n//  - add comments specfic to the component, explaining its usage\r\n\r\n#include <gel/components/emptycomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\n\r\nCBaseComponent* CEmptyComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CEmptyComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCEmptyComponent::CEmptyComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_EMPTY );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCEmptyComponent::~CEmptyComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CEmptyComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// ** Add code to parse the structure, and initialize the component\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\n\tIt's commented out here.  You will also need to comment in the \r\n\tdefinition in emptycomponent.h\r\nvoid CEmptyComponent::Finalize()\r\n{\r\n\t// Virtual function, can be overridden to provided finialization to \r\n\t// a component after all components have been added to an object\r\n\t// Usually this consists of getting pointers to other components\r\n\t// Note:  It is GUARENTEED (at time of writing) that\r\n\t// Finalize() will be called AFTER all components are added\r\n\t// and BEFORE the CCompositeObject::Update function is called\r\n\t\r\n\t// Example:\r\n\t// mp_suspend_component =  GetSuspendComponentFromObject( GetObject() );\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CEmptyComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calline InitFromStructure()\r\n\t// but if that does not handle it, then will need to write a specific \r\n\t// function here. \r\n\t// The user might only want to update a single field in the structure\r\n\t// and we don't want to be asserting becasue everything is missing \r\n\t\r\n\tInitFromStructure(pParams);\r\n\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CEmptyComponent::Update()\r\n{\r\n\t// **  You would put in here the stuff that you would want to get run every frame\r\n\t// **  for example, a physics type component might update the position and orientation\r\n\t// **  and update the internal physics state \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CEmptyComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n/*\r\n        // @script | DoSomething | does some functionality\r\n\t\tcase 0xbb4ad101:\t\t// DoSomething\r\n\t\t\tDoSomething();\r\n\t\t\tbreak;\r\n\r\n        // @script | ValueIsTrue | returns a boolean value\r\n\t\tcase 0x769260f7:\t\t// ValueIsTrue\r\n\t\t{\r\n\t\t\treturn ValueIsTrue() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\tbreak;\r\n*/\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CEmptyComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CEmptyComponent::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\t/*\tExample:\r\n\tp_info->AddInteger(CRCD(0x7cf2a233,\"m_never_suspend\"),m_never_suspend);\r\n\tp_info->AddFloat(CRCD(0x519ab8e0,\"m_suspend_distance\"),m_suspend_distance);\r\n\t*/\r\n\t\r\n// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/emptycomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       EmptyComponent.h\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ??/??/??\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_EMPTYCOMPONENT_H__\r\n#define __COMPONENTS_EMPTYCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n// Replace this with the CRCD of the component you are adding\r\n#define\t\tCRC_EMPTY CRCD(0x9738c23b,\"Empty\")\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or \r\n//  given an object\t\t\t\t \r\n#define\t\tGetEmptyComponent() ((Obj::CEmptyComponent*)GetComponent(CRC_EMPTY))\r\n#define\t\tGetEmptyComponentFromObject(pObj) ((Obj::CEmptyComponent*)(pObj)->GetComponent(CRC_EMPTY))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CEmptyComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CEmptyComponent();\r\n    virtual ~CEmptyComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n//\tvirtual\tvoid \t\t\t\t\tFinalize();\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/lockobjcomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       LockObjComponent.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/31/2002\r\n//****************************************************************************\r\n\r\n#include <gel/components/lockobjcomponent.h>\r\n\r\n#include <core/singleton.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/objman.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/script.h>\r\n\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/skeleton.h>\r\n\t\t\t\t\t\t\t\t\t\t\t\t   \r\n// for kludgy skater stuff\r\n#include <sk/modules/skate/skate.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n\r\n\r\n// For the manager ... messy\r\n#include <gel/mainloop.h>\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// This static function is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\nCBaseComponent* CLockObjComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CLockObjComponent );\t\r\n}\r\n\r\n\r\n// And this one is the optional \"register\" function that provides on-time initilization\r\n// usually of a component manager\r\nvoid\tCLockObjComponent::s_register()\r\n{\r\n\t// Create and initilize the manager\r\n\tLockOb::Manager::Create();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCLockObjComponent::CLockObjComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_LOCKOBJ );\r\n\r\n\tm_lock_enabled = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCLockObjComponent::~CLockObjComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CLockObjComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\r\n\tm_locked_to_object_name=0;\r\n\tm_locked_to_object_id=Obj::CBaseManager::vNO_OBJECT_ID;\r\n\tm_locked_to_object_bone_name=0;\r\n\tm_lock_offset.Set();\r\n\t\r\n\tif (pParams->ContainsFlag(\"Off\"))\r\n\t{\r\n\t\tEnableLock( false );\r\n\t\treturn;\r\n\t}\r\n\r\n\tEnableLock( true );\r\n\r\n\t#if 0\r\n\t// SHOULD ALSO CLEAR OUT SOME OF THE OTHER\r\n\t// FLAGS THAT CANNOT CO-EXIST!\r\n\tGetObject()->m_movingobj_status &= ~MOVINGOBJ_STATUS_FOLLOWING_LEADER;\r\n\tGetObject()->m_movingobj_status &= ~MOVINGOBJ_STATUS_MOVETO;\r\n\t#endif\r\n\r\n\tpParams->GetChecksum(\"ObjectName\",&m_locked_to_object_name);\r\n\tpParams->GetVector(NONAME,&m_lock_offset);\r\n\tpParams->GetChecksum(\"id\",&m_locked_to_object_id);\r\n\tpParams->GetChecksum(\"bone\",&m_locked_to_object_bone_name);\r\n\r\n\tprintf( \"locking to object %s\\n\", Script::FindChecksumName(m_locked_to_object_id) );\r\n\r\n\tm_no_rotation=pParams->ContainsFlag(\"NoRotation\");\r\n\t\r\n\tm_lag=false;\r\n\t\r\n\tm_lag_factor_range_a=1.0f;\r\n\tm_lag_factor_range_b=1.0f;\r\n\tif (pParams->GetPair(\"LagRange\",&m_lag_factor_range_a,&m_lag_factor_range_b))\r\n\t{\r\n\t\tm_lag=true;\r\n\t}\t\r\n\t\r\n\tm_lag_freq_a=0.0f;\r\n\tm_lag_freq_b=0.0f;\r\n\tif (pParams->GetPair(\"LagWobble\",&m_lag_freq_a,&m_lag_freq_b))\r\n\t{\r\n\t\tm_lag=true;\r\n\t}\t\r\n\r\n\t// The random lag phase is to ensure that two objects using the same script won't\r\n\t// wobble in phase.\r\n\tm_lag_phase=Mth::Rnd(1024);\t\r\n\tuint32 t=Tmr::ElapsedTime(0)+m_lag_phase;\r\n\tt&=1023;\r\n\tfloat x=sinf(m_lag_freq_a*t*2.0f*3.1415926f/1024.0f) *\r\n\t\t\tsinf(m_lag_freq_b*t*2.0f*3.1415926f/1024.0f);\r\n\t\r\n\tm_lag_factor=m_lag_factor_range_a+(x+1)*(m_lag_factor_range_b-m_lag_factor_range_a)/2.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CLockObjComponent::Update()\r\n{\r\n\t// Doing nothing, so tell code to do nothing next time around\r\n\tSuspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent::EMemberFunctionResult CLockObjComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\r\n\t\t\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | Obj_LockToObject | Makes the object be locked a fixed offset from some other\r\n\t\t// object, and use the same orientation.\r\n        // @uparmopt tev_TramA01 | Name of the object to be locked to\r\n        // @uparmopt (0,0,0) | Offset from the host object.\r\n\t\t// @flag Off | Switch off lock so that object can be moved independently again.\r\n\t\t// @flag NoRotation | Makes the objects rotation be left unaffected.\r\n\t\t// @parmopt pair | LagRange | (1,1) | The range of the lag value, which determines how quickly\r\n\t\t// the object will catch up to the object being followed. The lower the value the further\r\n\t\t// the object will lag behind. 1 means no lag at all.\r\n\t\t// Example which works quite well: (0.05,0.07)\r\n\t\t// @parmopt pair | LagWobble | (0,0) | The frequencies used to wobble the lag value between\r\n\t\t// the two ranges. Two frequencies are specified so that the lag will wobble in an\r\n\t\t// irregular manner. Example which works quite well: (0.779,0.65)\r\n\t\tcase 0x785e57c7: // Obj_LockToObject\r\n\t\t{\r\n\t\t\t#if 0\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tuint32 foo=0;\r\n\t\t\tif (!pParams->GetChecksum(\"ObjectName\",&foo))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nMissing ObjectName parameter in Obj_LockToObject\",pScript->GetScriptInfo()));\r\n\t\t\t}\r\n\t\t\t#endif\t\t\t\t\r\n\t\t\t#endif\t\t\t\t\r\n\t\t\tInitFromStructure( pParams );\t\t\t\t\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\nvoid CLockObjComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CLockObjComponent::GetDebugInfo\"));\r\n\t// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n\t\r\n\tp_info->AddChecksum(\"m_locked_to_object_name\",m_locked_to_object_name);\r\n\tp_info->AddChecksum(\"m_locked_to_object_id\",m_locked_to_object_id);\r\n\tp_info->AddChecksum(\"m_locked_to_object_bone_name\",m_locked_to_object_bone_name);\r\n\tp_info->AddVector(\"m_lock_offset\",m_lock_offset.GetX(),m_lock_offset.GetY(),m_lock_offset.GetZ());\r\n\tp_info->AddFloat(\"m_lag_factor\",m_lag_factor);\r\n\tp_info->AddFloat(\"m_lag_factor_range_a\",m_lag_factor_range_a);\r\n\tp_info->AddFloat(\"m_lag_factor_range_b\",m_lag_factor_range_b);\r\n\tp_info->AddFloat(\"m_lag_freq_a\",m_lag_freq_a);\r\n\tp_info->AddFloat(\"m_lag_freq_b\",m_lag_freq_b);\r\n\tp_info->AddFloat(\"m_lag_phase\",m_lag_phase);\r\n\tp_info->AddChecksum(\"m_lag\",m_lag ? 0x203b372/*True*/:0xd43297cf/*False*/);\r\n\tp_info->AddChecksum(\"m_no_rotation\",m_no_rotation ? 0x203b372/*True*/:0xd43297cf/*False*/);\r\n\tp_info->AddChecksum(\"m_lock_enabled\",m_lock_enabled ? 0x203b372/*True*/:0xd43297cf/*False*/);\r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCompositeObject* CLockObjComponent::get_locked_to_object()\r\n{\r\n\tCCompositeObject* p_obj=NULL;\r\n\tif (m_locked_to_object_id!=CBaseManager::vNO_OBJECT_ID)\r\n\t{\r\n\t\tp_obj=(CCompositeObject*)Obj::ResolveToObject(m_locked_to_object_id);\r\n\t}\r\n\telse if (m_locked_to_object_name==0x5b8ab877) // Skater\r\n\t{\r\n\t\t// GJ:  phase this usage out...  we shouldn't have anything\r\n\t\t// skater-specific in here!\r\n\t\tDbg_MsgAssert(Mdl::Skate::Instance()->GetNumSkaters()==1,(\"Called get_locked_to_object with skater as parent when there is more than one skater\"));\r\n\t\tp_obj=(CCompositeObject*)Mdl::Skate::Instance()->GetLocalSkater();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//p_obj=CMovingObject::m_hash_table.GetItem(m_locked_to_object_name);\r\n\t\tp_obj = (Obj::CCompositeObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID( m_locked_to_object_name );\r\n\t\r\n\t}\r\n\t\r\n\treturn p_obj;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLockObjComponent::LockToObject( void )\r\n{\r\n\tMth::Matrix old_matrix=GetObject()->m_matrix;\r\n\t\r\n\tCCompositeObject* p_obj=get_locked_to_object();\r\n\tif (!p_obj)\r\n\t{\r\n\t\t// Can't find the object, oh well.\r\n\t\treturn;\r\n\t}\t\r\n\r\n\tMth::Vector target_pos = GetObject()->m_pos;\r\n\t\r\n\tif ( m_locked_to_object_bone_name )\r\n\t{\r\n\t\tGfx::CSkeleton* pSkeleton = NULL;\r\n\t\tif ( p_obj->GetComponent(CRC_SKELETON) )\r\n\t\t{\r\n\t\t\tpSkeleton = GetSkeletonComponentFromObject(p_obj)->GetSkeleton();\r\n\t\t}\r\n\t\tDbg_MsgAssert( pSkeleton, ( \"Locking object to bone on non-skeletal object\" ) );\r\n\t\tif ( pSkeleton && pSkeleton->GetBoneMatrix( m_locked_to_object_bone_name, &GetObject()->m_matrix ) )\r\n\t\t{\r\n\t\t\tMth::Vector boneOffset = GetObject()->m_matrix[Mth::POS];\r\n\t\t\tGetObject()->m_matrix[Mth::POS] = Mth::Vector( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\r\n\t\t    GetObject()->m_matrix = GetObject()->GetMatrix() * p_obj->GetMatrix();\r\n\r\n\t\t\ttarget_pos = p_obj->GetDisplayMatrix().Transform( boneOffset );\r\n\t\t\ttarget_pos += p_obj->m_pos+m_lock_offset*GetObject()->GetMatrix();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Using the display matrix otherwise the object will jitter if following the skater\r\n\t\t// up a half pipe.\r\n\t\t\r\n\t\t// K: If the parent object is doing some extra rotations (by using the RotateDisplay command),\r\n\t\t// the calculation of target pos is slightly different. \r\n\t\t// However, as a speed optimization only do this for the skater because currently that \r\n\t\t// is the only object that does extra rotations.\r\n\t\t// Fixes bug where the pizza box special item was not being displayed correctly when used in\r\n\t\t// a create-a-trick with rotations.\r\n\t\t\r\n\t\tbool calculate_extra_rotation = false;\r\n\r\n\t\tCCompositeObject* p_composite_object = (CCompositeObject*)p_obj;\r\n\t\tObj::CModelComponent* p_model_component = (Obj::CModelComponent*)p_composite_object->GetComponent( CRC_MODEL );\r\n\t\tDbg_Assert( p_model_component );\r\n\t\tif ( p_model_component->HasRefObject() )\r\n\t\t{\r\n\t\t\t// GJ THPS5:  We're now starting to have non-skater objects needing the extra rotate \r\n\t\t\t// display (i.e. the CAT preview skater)...  in theory, we could still do an optimization\r\n\t\t\t// where each lockobjcomponent is flagged to support the rotatedisplay, but i decided\r\n\t\t\t// to just kludge it for now by checking for a refObject.\r\n\t\t\tcalculate_extra_rotation = true;\r\n\t\t}\r\n\t\telse if ( p_obj->GetID() < Mdl::Skate::vMAX_SKATERS )\r\n\t\t{\r\n\t\t\t// If it's the skater ...\r\n\t\t\tcalculate_extra_rotation = true;\r\n\t\t}\r\n\r\n\t\tif ( calculate_extra_rotation )\r\n\t\t{\r\n\t\t\tMth::Matrix display_matrix;\r\n\t\t\tp_model_component->GetDisplayMatrixWithExtraRotation( display_matrix );\r\n\t\t\t\r\n\t\t\t// Note that p_obj->GetPos() is not added because the offset is contained in the matrix.\r\n\t\t\ttarget_pos=m_lock_offset*display_matrix;\r\n\t\t\t\r\n\t\t\t// but now zero out the translation part of the matrix otherwise the object will be rendered wrong.\r\n\t\t\tMth::Vector zero(0.0f,0.0f,0.0f,1.0f);\r\n\t\t\tdisplay_matrix.SetPos(zero);\r\n\t\t\tGetObject()->m_matrix=display_matrix;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tGetObject()->m_matrix=((CCompositeObject*)p_obj)->GetDisplayMatrix();\r\n\t\t\ttarget_pos=p_obj->GetPos()+m_lock_offset*GetObject()->m_matrix;\r\n\t\t}\r\n\t}\r\n\r\n\tif (m_lag)\r\n\t{\r\n\t\tGetObject()->m_pos=GetObject()->GetPos()+(target_pos-GetObject()->GetPos())*m_lag_factor;\r\n\t\t\r\n\t\tuint32 t=Tmr::ElapsedTime(0)+m_lag_phase;\r\n\t\tt&=1023;\r\n\t\tfloat x=sinf(m_lag_freq_a*t*2.0f*Mth::PI/1024.0f) *\r\n\t\t\t\tsinf(m_lag_freq_b*t*2.0f*Mth::PI/1024.0f);\r\n\t\t\r\n\t\tm_lag_factor=m_lag_factor_range_a+(x+1)*(m_lag_factor_range_b-m_lag_factor_range_a)/2.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGetObject()->m_pos=target_pos;\r\n\t}\r\n\t\r\n\t// take the object's velocity as well\r\n\tGetObject()->SetVel(p_obj->GetVel());\r\n\t\r\n\t// If the objects rotation is required to be preserved, recover the old value.\r\n\t// Alan's ferris wheel cars use this.\r\n\tif (m_no_rotation)\r\n\t{\r\n\t\tGetObject()->m_matrix[Mth::UP]=old_matrix[Mth::UP];\r\n\t\tGetObject()->m_matrix[Mth::AT]=old_matrix[Mth::AT];\r\n\t\tGetObject()->m_matrix[Mth::RIGHT]=old_matrix[Mth::RIGHT];\r\n\t\t//printf(\"m_pos=(%f,%f,%f)\\n\",m_pos[X],m_pos[Y],m_pos[Z]);\r\n\t}\t\r\n\t\r\n\t// GJ:  This function is called from a task that\r\n\t// happens after all the matrices have already\r\n\t// been sent to the rendering code for this frame...\r\n\t// so we'll need to re-apply any new m_pos/m_matrix\r\n\t// changes to the rendered model\r\n\t// (suggestion for THPS5...  have a render task\r\n\t// that sends all the matrices to the model after\r\n\t// the object update task has finished...)\r\n\tNx::CModel* pModel = NULL;\r\n\tif ( GetObject()->GetComponent( CRC_MODEL ) )\r\n\t{\r\n\t\tpModel = ((Obj::CModelComponent*)GetObject()->GetComponent(CRC_MODEL))->GetModel();\r\n\t}\r\n\t\r\n\tif ( pModel )\r\n\t{\r\n\t\tGfx::CSkeleton* pSkeleton = NULL;\r\n\t\tif ( GetObject()->GetComponent( CRC_SKELETON ) )\r\n\t\t{\r\n\t\t\tpSkeleton = ((Obj::CSkeletonComponent*)GetObject()->GetComponent(CRC_SKELETON))->GetSkeleton();\r\n\t\t}\r\n\r\n\t\tMth::Matrix rootMatrix;\r\n\t\trootMatrix = GetObject()->GetDisplayMatrix();\r\n\t\trootMatrix[Mth::POS] = GetObject()->GetPos();\r\n\t\trootMatrix[Mth::POS][W] = 1.0f;\r\n\t\tbool should_animate = false;\r\n\t\tpModel->Render( &rootMatrix, !should_animate, pSkeleton );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n\r\n\r\n\t\r\n}\r\n\r\n\r\n\r\n// The following is the LockOb manager, which iterates over the lockob components \r\n// to lock them to whatever they are locked to\r\n\r\nnamespace LockOb\r\n{\r\n// The purpose of this manager is just to update all the locked objects, by calling\r\n// CMovingObject::LockToObject on all objects that have had Obj_LockToObject run on them.\r\n// It is a manager so that it can be given a task with a priority such that it is called\r\n// after all the objects are updated.\r\n// The reason the lock logic cannot be done in the object update is because sometimes the parent's \r\n// update might happen after the child's, causing a frame lag. This was making the gorilla appear\r\n// behind the tram seat in the zoo when the tram was being skitched. (TT2324)\r\n\r\nDefineSingletonClass( Manager, \"Locked object Manager\" )\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::Manager()\r\n{\r\n\tmp_task = new Tsk::Task< Manager > ( s_code, *this,\r\n\t\t\t\t\t\t\t\t\t\tTsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_LOCKED_OBJECT_MANAGER_LOGIC );\r\n\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\tmlp_manager->AddLogicTask( *mp_task );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager()\r\n{\r\n\tdelete mp_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::s_code( const Tsk::Task< Manager >& task )\r\n{\r\n\t\r\n//\tif (Mdl::FrontEnd::Instance()->GamePaused())\r\n//\t{\r\n//\t\t// Must not update if game paused, because the game could be running a replay,\r\n//\t\t// which would mean the objects' models will have been deleted, causing the \r\n//\t\t// LockToObject function to assert.\r\n//\t\treturn;\r\n//\t}\r\n\r\n\t// new fast way, just go directly to the components, if any\r\n\tObj::CLockObjComponent *p_lock_obj_component = static_cast<Obj::CLockObjComponent*>( Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType( CRC_LOCKOBJ ));\r\n\twhile( p_lock_obj_component )\r\n\t{\r\n\t\tif ( p_lock_obj_component->IsLockEnabled() )\r\n\t\t{\r\n\t\t\tp_lock_obj_component->LockToObject();\r\n\t\t}\t\r\n\t\tp_lock_obj_component = static_cast<Obj::CLockObjComponent*>( p_lock_obj_component->GetNextSameType());\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gel/Components/lockobjcomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       LockObjComponent.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  11/4/2002\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_LOCKOBJCOMPONENT_H__\r\n#define __COMPONENTS_LOCKOBJCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/singleton.h>\r\n#include <core/task.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_LOCKOBJ CRCD(0x5cb5cb7e,\"LockObj\")\r\n#define\t\tGetLockObjComponent() ((Obj::CLockObjComponent*)GetComponent(CRC_LOCKOBJ))\r\n#define\t\tGetLockObjComponentFromObject(pObj) ((Obj::CLockObjComponent*)(pObj)->GetComponent(CRC_LOCKOBJ))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CLockObjComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CLockObjComponent();\r\n    virtual ~CLockObjComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\n\tvirtual void\t\t\t\t\tGetDebugInfo(Script::CStruct *p_info);\r\n\t\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\tstatic void\t\t\t\t\t\ts_register();\r\n\r\nprotected:\r\n\tCCompositeObject*\t\t\t\tget_locked_to_object();\r\n\r\npublic:\r\n\tvoid\t\t\t\t\t\t\tLockToObject();\r\n\tbool\t\t\t\t\t\t\tIsLockEnabled() const {return m_lock_enabled;}\r\n\tvoid\t\t\t\t\t\t\tEnableLock( bool enabled ) {m_lock_enabled = enabled;}\r\n\t\r\nprotected:\r\n\tuint32\t\t\t\t\t\t\tm_locked_to_object_name;\r\n\tuint32\t\t\t\t\t\t\tm_locked_to_object_id;\r\n\tuint32\t\t\t\t\t\t\tm_locked_to_object_bone_name;\r\n\tMth::Vector\t\t\t\t\t\tm_lock_offset;\r\n\tfloat\t\t\t\t\t\t\tm_lag_factor;\r\n\tfloat\t\t\t\t\t\t\tm_lag_factor_range_a;\r\n\tfloat\t\t\t\t\t\t\tm_lag_factor_range_b;\r\n\tfloat \t\t\t\t\t\t\tm_lag_freq_a;\r\n\tfloat \t\t\t\t\t\t\tm_lag_freq_b;\r\n\tuint32\t\t\t\t\t\t\tm_lag_phase;\r\n\tbool\t\t\t\t\t\t\tm_lag;\r\n\tbool\t\t\t\t\t\t\tm_no_rotation;\r\n\r\nprotected:\r\n\tbool\t\t\t\t\t\t\tm_lock_enabled;\r\n};\r\n\r\n}\r\n\r\nnamespace LockOb\r\n{\r\n// The purpose of this manager is just to update all the locked objects, by calling\r\n// CMovingObject::LockToObject on all objects that have had Obj_LockToObject run on them.\r\n// It is a manager so that it can be given a task with a priority such that it is called\r\n// after all the objects are updated.\r\n// The reason the lock logic cannot be done in the object update is because sometimes the parent's \r\n// update might happen after the child's, causing a frame lag. This was making the gorilla appear\r\n// behind the tram seat in the zoo when the tram was being skitched. (TT2324)\r\n\r\nclass Manager  : public Spt::Class\r\n{\r\n\tTsk::Task< Manager > *mp_task;\r\n\tstatic\tTsk::Task< Manager >::Code \ts_code;\r\n\r\npublic:\r\n\tManager();\r\n\t~Manager();\r\n\t\r\nprivate:\t\r\n\tDeclareSingletonClass( Manager );\r\n};\r\n};\r\n\r\n\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/modelcomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       ModelComponent.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/17/2002\r\n//****************************************************************************\r\n\r\n#include <gel/components/modelcomponent.h>\r\n\r\n#include <core/string/stringutils.h>\r\n\t\t\t\t\t\t\t\t\t\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n#include <gel/components/suspendcomponent.h>\r\n\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\t\t\t\t\t\t\t\t\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/utils.h>\r\n\r\n#include <gfx/gfxutils.h>\r\n#include <gfx/modelappearance.h>\r\n#include <gfx/modelbuilder.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxgeom.h>\r\n#include <gfx/nxlight.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/skeleton.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/engine/feeler.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/moviecam.h>\r\n\t\t\t\t\t \r\nnamespace Obj\r\n{\r\n\r\n#define vMAX_PATH (512)\r\n    \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelComponent::init_model_from_level_object( uint32 checksumName )\r\n{\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(checksumName);\r\n\tDbg_MsgAssert( p_sector, ( \"WARNING: sGetSector(0x%x) returned NULL (%s)\\n\", checksumName, Script::FindChecksumName(checksumName) ) );\r\n\tif ( p_sector )\r\n\t{\r\n\t\t// need to clone the source, not the instance?\r\n\t\tNx::CGeom* pGeom = p_sector->GetGeom();\r\n\t\tif( pGeom )\r\n\t\t{\r\n\t\t\tNx::CGeom* pClonedGeom = pGeom->Clone( true );\r\n\t\t\tpClonedGeom->SetActive(true);\r\n\t\t\tmp_model->AddGeom( pClonedGeom, 0 );\r\n\t\t\tm_isLevelObject = true;\r\n\t\t}\r\n\t\t// Also get the collision data pointer\r\n//\t\t\t\tDbg_Assert(p_sector->GetCollSector());\r\n//\t\t\t\tNx::CCollObjTriData* p_coll_tri_data = p_sector->GetCollSector()->GetGeometry();\r\n//\t\t\t\tDbg_Assert(p_coll_tri_data);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// This static function is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\nCBaseComponent *\tCModelComponent::s_create()\r\n{\r\n\treturn static_cast<CBaseComponent*>(new CModelComponent);\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCModelComponent::CModelComponent() : CBaseComponent()\r\n{\r\n\tSetType(CRCD(0x286a8d26,\"Model\"));\r\n    mp_model = Nx::CEngine::sInitModel();\r\n\t\r\n\t// since it's uninitialized\r\n\tm_display_rotation_offset.Set( 0.0f, 0.0f, 0.0f );\t\t\r\n\t\r\n\tmpDisplayRotationInfo[0].Clear();\r\n\tmpDisplayRotationInfo[1].Clear();\r\n\tmpDisplayRotationInfo[2].Clear();\r\n\r\n\tm_numLODs = 0;\r\n\tm_isLevelObject = false;\r\n\t\r\n\tmDisplayOffset.Set();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCModelComponent::~CModelComponent()\r\n{\r\n    Dbg_MsgAssert( mp_model, ( \"No model\" ) );\r\n    Nx::CEngine::sUninitModel( mp_model );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CModelComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// needs to come before the geoms get added,\r\n\t// because otherwise we've cause some fragmentaton\r\n\t// when we switch models...\r\n\tif ( pParams->ContainsFlag( CRCD(0x10079f2d,\"UseModelLights\") ) )\r\n\t{\r\n\t\tif ( !mp_model->GetModelLights() )\r\n\t\t{\r\n\t\t\tmp_model->CreateModelLights();\r\n\t\t\tNx::CModelLights *p_lights = mp_model->GetModelLights();\r\n\t\t\tp_lights->SetPositionPointer(&GetObject()->m_pos);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( mp_model->GetModelLights() )\r\n\t\t{\r\n\t\t\tmp_model->DestroyModelLights();\r\n\t\t}\r\n\t}\r\n\r\n\t// this function assumes that the skeletoncomponent\r\n\t// will be correctly added BEFORE the modelcomponent\r\n\t\r\n\t// not all models are initialized using InitFromStructure,\r\n\t// so we should find someplace better to put the following \r\n\t// call to SetSkeleton()\r\n\tCSkeletonComponent *p_skeleton_component = GetSkeletonComponentFromObject(GetObject());\r\n\tif (p_skeleton_component)\r\n\t{\r\n\t\tGetModel()->SetSkeleton( p_skeleton_component->GetSkeleton() );\r\n\t}\r\n\r\n\tint doShadowVolume = 0;\r\n\tpParams->GetInteger( CRCD(0x2a1f92c0,\"shadowVolume\"), &doShadowVolume, Script::NO_ASSERT );\r\n\tmp_model->EnableShadowVolume( doShadowVolume );\r\n\t\r\n\tInitModel( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CModelComponent::InitModel( Script::CStruct* pParams )\r\n{\r\n\t// should destroy the existing model\r\n\tmp_model->ClearGeoms();\r\n\r\n\t// update its scale, if any\r\n\t// (need to do this before init_model(), \r\n\t// which can potentially override the scale)\r\n\tMth::Vector theScale(1.0f,1.0f,1.0f);\r\n\tif ( Gfx::GetScaleFromParams( &theScale, pParams ) )\r\n\t{\r\n\t\tmp_model->SetScale( theScale );\r\n\t}\r\n\t\r\n\tconst char* pModelName;\r\n\tuint32 model_name_checksum=0;\r\n\tuint32 assetName;\r\n\tuint32 refObjectName;\r\n\tuint32 cloneID;\r\n\r\n\t// check first if it is a LevelObject\r\n\t// in which case it will have a \"name\" which is the name of the sector\r\n\tuint32 ClassChecksum = 0;\r\n\tpParams->GetChecksum( CRCD(0x12b4e660,\"Class\"), &ClassChecksum );\r\n\tif ( ClassChecksum == CRCD(0xb7b3bd86,\"LevelObject\") )\r\n\t{\r\n\t\tuint32\tchecksumName;\t\r\n\t\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"Name\"), &checksumName, Script::ASSERT );\r\n\t\tinit_model_from_level_object(checksumName);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// by default, use the asset manager\r\n\t\tint useAssetManager = 1;\r\n\t\tpParams->GetInteger( CRCD(0xc63c8d38,\"use_asset_manager\"), &useAssetManager, Script::NO_ASSERT );\r\n\r\n\t\tint texDictOffset = 0;\r\n\t\tpParams->GetInteger( CRCD(0xf891ac27,\"texDictOffset\"), &texDictOffset, Script::NO_ASSERT );\r\n\r\n\t\tif ( pParams->GetChecksum( CRCD(0x153a84de,\"refObjectName\"), &refObjectName, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tm_refObjectName = refObjectName;\r\n\t\t\tm_hasRefObject = true;\r\n\t\t\tmp_model->SetRenderMode( Nx::vNONE );\r\n\t\t}\r\n\t\telse if ( pParams->GetChecksum( CRCD(0x86bd5b8f,\"assetName\"), &assetName, Script::NO_ASSERT ) )\r\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\t\t// this means that the asset name was faked somehow\r\n\t\t\t// (for example, if we've loaded it up from a data stream\r\n\t\t\t// instead of a filename)\r\n\t\t\tDbg_MsgAssert( mp_model, ( \"No model\" ) );\r\n\r\n\t\t\tint supportMultipleMaterialColors = 0;\r\n\t\t\tpParams->GetInteger( CRCD(0x92b43e79,\"multicolor\"), &supportMultipleMaterialColors, Script::NO_ASSERT );\r\n\t\t\t\r\n\t\t\t// component name doesn't matter...  give it a dummy\r\n\t\t\tuint32 componentName = 0;\r\n\t\t\tmp_model->AddGeom( assetName, componentName, supportMultipleMaterialColors );\r\n\t\t}\r\n\t\telse if ( pParams->GetChecksum( CRCD(0x7dd037b3,\"cloneFrom\"), &cloneID, Script::NO_ASSERT ) )\r\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\t\t// Clone the geometry off of an existing model\r\n\t\t\tCCompositeObject* pObject = static_cast<CCompositeObject *>(CCompositeObjectManager::Instance()->GetObjectByID(cloneID));\r\n\t\t\tDbg_MsgAssert( pObject, ( \"Couldn't find object id %d to clone\", cloneID ) );\r\n\r\n\t\t\tCModelComponent *p_src_model_comp = GetModelComponentFromObject(pObject);\r\n\t\t\tDbg_MsgAssert( p_src_model_comp, ( \"Couldn't find model component in object id %d\", cloneID ) );\r\n\t\t\tDbg_MsgAssert( p_src_model_comp->mp_model, ( \"Couldn't find CModel in model component of object id %d\", cloneID ) );\r\n\r\n\t\t\tuint32 geomName;\r\n\t\t\tScript::CArray *p_geom_array=NULL;\r\n\t\t\tif ( pParams->GetChecksum( CRCD(0xe7308c1f,\"geom\"), &geomName, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tNx::CGeom *p_orig_geom = p_src_model_comp->mp_model->GetGeom(geomName);\r\n\t\t\t\tDbg_MsgAssert(p_orig_geom, (\"Couldn't find CGeom %s\", Script::FindChecksumName(geomName)));\r\n\r\n\t\t\t\tNx::CGeom *p_new_geom = p_orig_geom->Clone(true, mp_model);\r\n\t\t\t\tDbg_MsgAssert(p_new_geom, (\"Couldn't clone CGeom %s\", Script::FindChecksumName(geomName)));\r\n\r\n\t\t\t\tp_new_geom->SetActive(true);\r\n\t\t\t\tmp_model->AddGeom(p_new_geom, geomName);\r\n\t\t\t}\r\n\t\t\telse if (pParams->GetArray(CRCD(0x44e31dff,\"geoms\"), &p_geom_array))\r\n\t\t\t{\r\n\t\t\t\tuint32 geomName;\r\n\t\t\t\tfor (uint i = 0; i < p_geom_array->GetSize(); i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tgeomName = p_geom_array->GetChecksum(i);\r\n\t\t\t\t\tif (geomName)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tNx::CGeom *p_orig_geom = p_src_model_comp->GetModel()->GetGeom(geomName);\r\n\t\t\t\t\t\tDbg_MsgAssert(p_orig_geom, (\"Couldn't find CGeom %s\", Script::FindChecksumName(geomName)));\r\n\r\n\t\t\t\t\t\tNx::CGeom *p_new_geom = p_orig_geom->Clone(true, mp_model);\r\n\t\t\t\t\t\tDbg_MsgAssert(p_new_geom, (\"Couldn't clone CGeom %s\", Script::FindChecksumName(geomName)));\r\n\r\n\t\t\t\t\t\tp_new_geom->SetActive(true);\r\n\t\t\t\t\t\tmp_model->AddGeom(p_new_geom, geomName);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( pParams->GetText( CRCD(0x286a8d26,\"model\"), &pModelName, Script::NO_ASSERT )\r\n\t\t\t|| pParams->GetText( CRCD(0xb974f2fc,\"modelName\"), &pModelName, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\t// TODO:  If the model name is \"none\", then we shouldn't\r\n\t\t\t// have added the modelcomponent in the first place...\r\n\t\t\t// we should have some kind of higher-level logic decide\r\n\t\t\t// whether or not to create the modelcomponent, based on\r\n\t\t\t// whether the node specifies:  model=\"none\".\r\n\t\t\tif ( Script::GenerateCRC(pModelName) == CRCD(0x806fff30,\"none\") )\r\n\t\t\t{\r\n\t\t\t\t;\t// do nothing\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tchar fullModelName[vMAX_PATH];\r\n\r\n\t\t\t\tuint32 skeletonName;\r\n\t\t\t\tif ( pParams->GetChecksum( CRCD(0x9794932,\"skeletonName\"), &skeletonName, Script::NO_ASSERT ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t// if it's a skinned model\r\n\t\t\t\t\tGfx::GetModelFileName(pModelName, \".skin\", fullModelName);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// if it's a nonskinned model\r\n\t\t\t\t\tGfx::GetModelFileName(pModelName, \".mdl\", fullModelName);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tStr::LowerCase( fullModelName );\r\n\r\n\t\t\t\tbool forceTexDictLookup = pParams->ContainsFlag( CRCD(0x6c37fdc7,\"AllowReplaceTex\") );\r\n\r\n\t\t\t\t// TODO: remove this for thps5 (it's only used for the boards\r\n\t\t\t\t// in the skateshop, which need to do texture replacement, and \r\n\t\t\t\t// thus cannot use the asset manager...)\r\n\t\t\t\tif ( strstr( fullModelName, \"thps4board_\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tuseAssetManager = false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Model file name should look like this:  \"models/testcar/testcar.mdl\"\r\n\t\t\t\tDbg_MsgAssert( strlen(fullModelName) < vMAX_PATH, ( \"String too long\" ) );\r\n\t\t\t\tmp_model->AddGeom( fullModelName, 0, useAssetManager, texDictOffset, forceTexDictLookup );\r\n\t\t\t\t\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t\tint lodIndex = 0;\r\n\t\t\t\t// now load up the other LODs, if they exist\r\n\t\t\t\tfor ( int i = 0; i < vNUM_LODS; i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tchar paramName[256];\r\n\t\t\t\t\tsprintf( paramName, \"modelLOD%d\", lodIndex + 1 ); \r\n\t\t\t\t\tif ( pParams->GetText( paramName, &pModelName, Script::NO_ASSERT ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfloat modelDist;\r\n\t\t\t\t\t\tsprintf( paramName, \"modelLODdist%d\", lodIndex + 1 );\r\n\t\t\t\t\t\tif ( pParams->GetFloat( paramName, &modelDist, Script::NO_ASSERT ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tuint32 skeletonName;\r\n\t\t\t\t\t\t\tif ( pParams->GetChecksum( CRCD(0x9794932,\"skeletonName\"), &skeletonName, Script::NO_ASSERT ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// if it's a skinned model\r\n\t\t\t\t\t\t\t\tGfx::GetModelFileName(pModelName, \".skin\", fullModelName);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// if it's a nonskinned model\r\n\t\t\t\t\t\t\t\tGfx::GetModelFileName(pModelName, \".mdl\", fullModelName);\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tStr::LowerCase( fullModelName );\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tmp_model->AddGeom( fullModelName, lodIndex + 1, useAssetManager, texDictOffset );\r\n\t\t\t\t\t\t\tenable_lod( lodIndex + 1, modelDist );\r\n\t\t\t\t\t\t\tlodIndex++;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tDbg_MsgAssert( 0, ( \"Expected to find parameter for LOD model dist: %s\", paramName ) );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n#endif\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( pParams->GetChecksum( CRCD(0x286a8d26,\"model\"), &model_name_checksum, Script::NO_ASSERT ))\r\n\t\t{\r\n\t\t\tNx::CSector *p_source_sector = Nx::CEngine::sGetSector(model_name_checksum);\r\n\t\t\tDbg_MsgAssert(p_source_sector,(\"Could not find sector %s\\n\",Script::FindChecksumName(model_name_checksum)));\r\n\t\t\t\r\n\t\t\tNx::CGeom *p_orig_geom = p_source_sector->GetGeom();\r\n\t\t\tDbg_MsgAssert(p_orig_geom, (\"Couldn't find CGeom for %s\",Script::FindChecksumName(model_name_checksum)));\r\n\r\n\t\t\tNx::CGeom *p_new_geom = p_orig_geom->Clone(true, (Nx::CScene*)NULL);\r\n\t\t\tDbg_MsgAssert(p_new_geom, (\"Couldn't clone CGeom %s\", Script::FindChecksumName(model_name_checksum)));\r\n\t\t\tp_new_geom->SetActive(true);\r\n\t\t\t\r\n\t\t\tmp_model->AddGeom(p_new_geom, 0);\r\n\t\t}\r\n\t}\r\n\r\n\t// update its position\r\n\tif ( GetObject()->IsFinalized() )\r\n\t{\r\n\t\tFinalizeModelInitialization();\r\n\t}\r\n\r\n\t// now that the model has been created,\r\n\t// remember the bounding sphere\r\n\tm_original_bounding_sphere = mp_model->GetBoundingSphere();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// create-a-ped, create-a-skater\r\nvoid CModelComponent::InitModelFromProfile( Gfx::CModelAppearance* pAppearance, bool useAssetManager, uint32 texDictOffset, uint32 buildScript  )\r\n{\r\n\tDbg_MsgAssert( mp_model, ( \"No model?\" ) );\r\n\tNx::CModel* pModel = mp_model;\r\n\r\n\t// GJ:  shouldn't destroy the existing model\r\n\t// it's up to each build script to do this...\r\n\t// (in case we just want to re-apply a few\r\n\t// operations)\r\n\t//\tpModel->ClearGeoms();\r\n\r\n    Gfx::CSkeleton* pSkeleton = NULL;\r\n\tObj::CSkeletonComponent* pSkeletonComponent = GetSkeletonComponentFromObject( GetObject() );\r\n\tif ( pSkeletonComponent )\r\n\t{\r\n\t\tpSkeleton = pSkeletonComponent->GetSkeleton();\r\n\t}\r\n\r\n\tGfx::CModelBuilder theBuilder( useAssetManager, texDictOffset );\r\n\tif ( buildScript )\r\n\t{\r\n\t\ttheBuilder.BuildModel( pAppearance, pModel, pSkeleton, buildScript );\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttheBuilder.BuildModel( pAppearance, pModel, pSkeleton );\r\n\t}\r\n\r\n\t// update its position\r\n\tif ( GetObject()->IsFinalized() )\r\n\t{\r\n\t\tFinalizeModelInitialization();\r\n\t}\r\n\r\n\t// now that the model has been created,\r\n\t// remember the bounding sphere\r\n\tm_original_bounding_sphere = pModel->GetBoundingSphere();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelComponent::enable_lod(uint32 componentName, float distance)\r\n{\r\n\tif ( m_numLODs >= vNUM_LODS )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Too many LODs!\" ) );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tNx::CGeom* pGeom = mp_model->GetGeom( componentName );\r\n\tif ( !pGeom )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Couldn't find geom named %s\", Script::FindChecksumName(componentName) ) );\r\n\t\treturn false;\r\n\t}\r\n\r\n//\tprintf( \"Enabled lod %08x\\n\", componentName );\r\n\r\n\t// GJ TODO:  should sort the lods by distance, \r\n\t// and check for duplicates!\r\n\r\n\tm_LODdist[m_numLODs] = distance;\r\n\r\n\tm_numLODs++;\r\n\r\n\t// GJ TODO:  each client needs to do this\r\n\t// on a case-by-case basis...\r\n\r\n\treturn true;\r\n}\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelComponent::HideGeom( uint32 geomName, bool hidden, bool propagate )\r\n{\r\n    if( propagate )\r\n\t{\r\n\t\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\t\tGameNet::PlayerInfo* player;\r\n\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( GetObject()->GetID() );\r\n\t\tif( player && player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tNet::Client* client;\r\n\t\t\tGameNet::MsgHideAtomic msg;\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\tclient = gamenet_man->GetClient( player->GetSkaterNumber() );\r\n\t\t\tDbg_Assert( client );\r\n\r\n\t\t\t//msg.m_Time = client->m_Timestamp;\r\n\t\t\tmsg.m_Hide = hidden;\r\n\t\t\tmsg.m_AtomicName = geomName;\r\n\t\t\tmsg.m_ObjId = GetObject()->GetID();\r\n\r\n\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgHideAtomic );\r\n\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_SET_HIDE_ATOMIC;\r\n\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( mp_model )\r\n\t{\r\n\t\tmp_model->HideGeom( geomName, hidden );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelComponent::GeomHidden( uint32 geomName )\r\n{\r\n    return (mp_model->GeomHidden( geomName ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CModelComponent::GetDisplayMatrixWithExtraRotation( Mth::Matrix& displayMatrix )\r\n{\r\n    CCompositeObject* pObject = GetObject();\r\n    Dbg_MsgAssert( pObject, ( \"Couldn't find parent object\" ) );\r\n\t\r\n\tdisplayMatrix = pObject->GetDisplayMatrix();\r\n\tdisplayMatrix[Mth::POS] = Mth::Vector( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\t\r\n\tif (mFlipDisplayMatrix)\r\n\t{\r\n\t\tdisplayMatrix[Z] = -displayMatrix[Z];\r\n\t\tdisplayMatrix[X] = -displayMatrix[X];\r\n\t}\r\n\r\n\t// Record the display matrix for use by the camera before applying any extra rotation.\r\n//\tm_camera_display_matrix=m_display_matrix;\r\n\r\n\tMth::Matrix extra_display_rotation;\r\n\t\r\n\t// only do the math if we're not dealing w/ the identity...\r\n\tbool is_identity = true;\r\n\r\n\tfloat new_angle;\r\n\tif (mpDisplayRotationInfo[0].m_active)\r\n\t{\r\n\t\tnew_angle=mpDisplayRotationInfo[0].CalculateNewAngle();\t\r\n\t\tif ( new_angle )\r\n\t\t{\r\n\t\t\tif (is_identity)\r\n\t\t\t{\r\n\t\t\t\textra_display_rotation.Ident();\r\n\t\t\t}\r\n\t\t\tis_identity = false;\r\n\t\t\textra_display_rotation.RotateX(Mth::DegToRad(new_angle));\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (mpDisplayRotationInfo[1].m_active)\r\n\t{\r\n\t\tnew_angle=mpDisplayRotationInfo[1].CalculateNewAngle();\t\r\n\t\tif ( new_angle )\r\n\t\t{\r\n\t\t\tif (is_identity)\r\n\t\t\t{\r\n\t\t\t\textra_display_rotation.Ident();\r\n\t\t\t}\r\n\t\t\tis_identity = false;\r\n\t\t\textra_display_rotation.RotateY(Mth::DegToRad(new_angle));\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (mpDisplayRotationInfo[2].m_active)\r\n\t{\r\n\t\tnew_angle=mpDisplayRotationInfo[2].CalculateNewAngle();\t\r\n\t\tif ( new_angle )\r\n\t\t{\r\n\t\t\tif (is_identity)\r\n\t\t\t{\r\n\t\t\t\textra_display_rotation.Ident();\r\n\t\t\t}\r\n\t\t\tis_identity = false;\r\n\t\t\textra_display_rotation.RotateZ(Mth::DegToRad(new_angle));\r\n\t\t}\r\n\t}\r\n\r\n\tMth::Vector off(0.0f, 0.0f, 0.0f, 0.0f);\t\r\n\tif ( !is_identity )\r\n\t{\r\n\t\toff=m_display_rotation_offset;\t\r\n\t\tif ( !( off[X] == 0.0f && off[Y] == 0.0f && off[Z] == 0.0f ) )\r\n\t\t{\r\n\t//\t\tis_identity = false;\r\n\t\t\toff=off-off*extra_display_rotation;\t\t  // Would zero it if it's the identity\r\n\t\t\toff=off*displayMatrix;\t\t\r\n\t\t}\r\n\t\r\n\t//\tif ( !is_identity )\r\n\t\t{\r\n\t\t\tdisplayMatrix=extra_display_rotation*displayMatrix;\r\n\t\t}\r\n\t}\r\n\r\n//#ifdef\t\tDEBUG_DISPLAY_MATRIX\r\n//\tdodgy_test(); printf(\"%d: Setting display_matrix[Y][Y] to %f, [X][X] to %f\\n\",__LINE__,m_display_matrix[Y][Y],m_display_matrix[X][X]);\r\n//#endif\r\n\r\n\tdisplayMatrix[Mth::POS] = GetObject()->GetPos();\r\n\tdisplayMatrix[Mth::POS] += off;\r\n\tdisplayMatrix[Mth::POS] += mDisplayOffset;\r\n\tdisplayMatrix[Mth::POS][W] = 1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelComponent::Hide( bool shouldHide )\r\n{\r\n\tif ( mp_model )\r\n\t{\r\n\t\tmp_model->Hide( shouldHide );\r\n\t}\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelComponent::Teleport()\r\n{\r\n\tDbg_MsgAssert( GetObject()->IsFinalized(), ( \"Teleporting unfinalized component!\" ) );\r\n\r\n\tFinalizeModelInitialization();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CModelComponent::Update()\r\n{\r\n\tif ( m_hasRefObject )\r\n\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\tObj::CMovieManager* pMovieManager = Mdl::Skate::Instance()->GetMovieManager();\r\n\t\tDbg_MsgAssert( !pMovieManager->IsRolling(), ( \"Wasn't expecting cutscene to be rolling\" ) );\r\n#endif\r\n\r\n\t\t// this code was lifted from cutscenedetails.cpp,\r\n\t\t// which is why it has all these weird temp\r\n\t\t// variables referencing its own member vars.\r\n\t\t// it's used for doing the create-a-trick skater\r\n\t\tObj::CModelComponent* pModelComponent = this;\r\n\t\tObj::CCompositeObject* pCompositeObject = GetObject();\r\n\r\n\t\tuint32 refObjectName = pModelComponent->GetRefObjectName();\r\n\t\tObj::CCompositeObject* pRefObject = (Obj::CCompositeObject*)Obj::ResolveToObject( refObjectName );\r\n\t\tDbg_Assert( pRefObject );\r\n\t\tObj::CModelComponent* pRefModelComponent = GetModelComponentFromObject( pRefObject );\r\n\t\tDbg_Assert( pRefModelComponent );\r\n\t\tNx::CModel* pRefModel = pRefModelComponent->GetModel();\r\n\t\tbool should_animate = true;\r\n\t\tObj::CSkeletonComponent* pSkeletonComponent = GetSkeletonComponentFromObject( pCompositeObject );\r\n\t\tDbg_MsgAssert( pSkeletonComponent, ( \"Was expecting a skeleton component\" ) );\r\n\t\tDbg_Assert( pSkeletonComponent == mp_skeleton_component );\r\n\r\n\t\tMth::Matrix theDisplayMatrix;\r\n\t\tthis->GetDisplayMatrixWithExtraRotation( theDisplayMatrix );\r\n\t\t\r\n\t\t// the return matrix already takes the position (plus an additional offset)\r\n\t\t// into account, so we don't have to do the following:\r\n\t\t// theDisplayMatrix[Mth::POS] = GetObject()->GetPos();\r\n\t\t\r\n\t\tpRefModel->Render( &theDisplayMatrix, !should_animate, pSkeletonComponent->GetSkeleton() );\r\n\t\tpRefModel->SetBoneMatrixData( pSkeletonComponent->GetSkeleton() );\r\n\t}\r\n\t// Mick: Don't need to update it if not active, just leave it where it is\r\n\telse if (mp_model && mp_model->GetActive())\r\n\t{\r\n\t\t\r\n\t\tDbg_MsgAssert(GetObject()->IsFinalized(),(\"Update() to UnFinalized Composite object %s\",Script::FindChecksumName(GetObject()->GetID())));\r\n\t\r\n\t\tMth::Matrix theDisplayMatrix;\r\n\r\n\t\tGetDisplayMatrixWithExtraRotation( theDisplayMatrix );\r\n\t\t\t\r\n//\t\t\ttheDisplayMatrix = GetObject()->GetDisplayMatrix();\r\n//\t\t\ttheDisplayMatrix[Mth::POS] = GetObject()->GetPos();\r\n//\t\t\ttheDisplayMatrix[Mth::POS][W] = 1.0f;\r\n\t\t\r\n\t\t// TODO:  The interface between different components\r\n\t\t// should be more generic, maybe...\r\n\t\tGfx::CSkeleton* pSkeleton = NULL;\r\n\t\tif ( mp_skeleton_component )\r\n\t\t{\r\n\t\t\tpSkeleton = mp_skeleton_component->GetSkeleton();\r\n\t\t}\r\n\t\t\r\n\t\t// default to true, for skeletal cars...\r\n\t\tbool should_animate = true;\r\n\t\r\n\t\tif ( mp_animation_component )\r\n\t\t{\r\n\t\t\t// either the animation component should cache this\r\n\t\t\t// data rather than doing the visibility test twice,\r\n\t\t\t// or it should be able to set some member inside\r\n\t\t\t// the model component (CModelComponent::MarkAnimationAsDirty?)\r\n\t\t\tshould_animate = mp_animation_component->ShouldAnimate();\r\n\t\t}\r\n\t\r\n\t#ifdef __PLAT_NGPS__\r\n\t\t// if it has LODs, then hide all the unnecessary ones\r\n\t\tif ( m_numLODs > 0 )\r\n\t\t{\r\n\t\t\t// first hide all the models, including the base one (0)\r\n\t\t\tfor ( int i = 0; i < m_numLODs + 1; i++ )\r\n\t\t\t{\r\n\t\t\t\tmp_model->HideGeom( i, true );\r\n\t\t\t}\r\n\t\r\n\t\t\t// now go through and unhide the correct one\r\n\t\t\tfloat distanceSqrToCamera = mp_suspend_component->GetDistanceSquaredToCamera();\r\n\t\t\t\r\n\t//\t\tprintf( \"distance to camera: %f feet\\n\", sqrtf(distanceSqrToCamera)/12.0f );\r\n\t\r\n\t\t\tbool found = false;\r\n\t\t\tfor ( int i = 0; i < m_numLODs; i++ )\r\n\t\t\t{\r\n\t\t\t\tif ( distanceSqrToCamera < ( m_LODdist[i] * m_LODdist[i] ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_model->HideGeom( i, false );\r\n\t\t\t\t\tfound = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif ( !found )\r\n\t\t\t{\r\n\t\t\t\t// then the last lod is active\r\n\t\t\t\tmp_model->HideGeom( m_numLODs, false );\r\n\t\t\t}\r\n\t\t}\r\n\t#endif\r\n\t\r\n\t\t// TODO:  if it's offscreen, the data shouldn't be copied over either...\r\n\t\r\n\t\tmp_model->Render( &theDisplayMatrix, !should_animate, pSkeleton );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelComponent::Finalize()\r\n{\r\n\tmp_skeleton_component =  GetSkeletonComponentFromObject( GetObject() );\r\n\tmp_animation_component =  GetAnimationComponentFromObject( GetObject() );\r\n\tmp_suspend_component =  GetSuspendComponentFromObject( GetObject() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelComponent::SetModelLODDistance( int lodIndex, float distance )\r\n{\r\n\tif ( !mp_model )\r\n\t{\r\n\t\tDbg_Message( \"No model!\" );\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( m_numLODs == 0 )\r\n\t{\r\n\t\tDbg_Message( \"Model %s has no lods\", Script::FindChecksumName(GetObject()->GetID()) );\r\n\t}\r\n\r\n\tif ( lodIndex < 1 || lodIndex > m_numLODs )\r\n\t{\r\n\t\tDbg_Message( \"Was expecting an lod index between 1 and %d\", m_numLODs);\r\n\t\treturn;\r\n\t}\r\n\r\n\tm_LODdist[lodIndex-1] = distance;\r\n\tDbg_Message( \"ModelLODDist%d is now %f\", lodIndex, distance );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelComponent::SetBoundingSphere( const Mth::Vector& newSphere )\r\n{\r\n\tif ( mp_model )\r\n\t{\r\n\t\tmp_model->SetBoundingSphere( newSphere );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelComponent::UpdateBrightness()\r\n{\r\n\tDbg_MsgAssert(mp_model, (\"UpdateBrightness: CModel is NULL\"));\r\n\tDbg_MsgAssert(mp_model->GetModelLights(), (\"UpdateBrightness: MovingObject has no model lights\"));\r\n\tmp_model->GetModelLights()->UpdateBrightness();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CModelComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tbool success = true;\r\n    Script::CStruct *p_script_params;\r\n\t \r\n\tp_script_params = NULL;\r\n\tif( pScript )\r\n\t{\r\n\t\tp_script_params = pScript->GetParams();\r\n\t}\r\n\r\n\tswitch (Checksum)\r\n\t{\r\n\t\t// @script | Obj_EnableScaling | in case you want to dynamically\r\n        // turn on scaling\r\n\t\tcase ( 0x347ff11b ):\t// Obj_EnableScaling\r\n\t\t\tif ( mp_model )\r\n\t\t\t{\r\n\t\t\t\tmp_model->EnableScaling( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_DisableScaling | in case you want to dynamically\r\n        // turn off scaling\r\n\t\tcase ( 0xf951aa64 ):\t// Obj_DisableScaling\r\n\t\t\tif ( mp_model )\r\n\t\t\t{\r\n\t\t\t\tmp_model->EnableScaling( false );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_ApplyScaling | scale on x,y,z \r\n        // @parm float | x | \r\n        // @parm float | y | \r\n        // @parm float | z | \r\n\t\tcase ( 0x657ff1ed ):\t// Obj_ApplyScaling\r\n\t\t{\r\n\t\t\t// GJ:  Scaling only refers to the renderable\r\n\t\t\t// model, not the collision volume...\r\n\t\t\tif ( mp_model )\r\n\t\t\t{\r\n\t\t\t\tMth::Vector theScale(1.0f,1.0f,1.0f);\r\n\t\t\t\tif ( Gfx::GetScaleFromParams( &theScale, pParams ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_model->SetScale( theScale );\r\n\t\t\t\t\tmp_model->EnableScaling( true );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n        \r\n\t\t// @script | Obj_ClearColor | turns off color modulation on this resetting it to the default color\r\n\t\tcase ( 0x6052480a ):\t// Obj_ClearColor\r\n\t\t{\r\n\t\t\tif ( mp_model )\r\n\t\t\t{\r\n\t\t\t\tmp_model->ClearColor( CRCD(0xc4e78e22,\"all\") );\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n        // @script | Obj_SetColor | \r\n        // @parm int | h | hue - between 0 and 360\r\n        // @parm int | s | saturation - between 0 and 100\r\n        // @parm int | v | value - between 0 and 100\r\n        case ( 0x76ecfa1c ):\t// Obj_SetColor\r\n\t\t{\r\n            if ( mp_model )\r\n\t\t\t{\r\n\t\t\t\tint h, s, v;\r\n\t\t\t\tif ( pParams->GetInteger( CRCD(0x6e94f918,\"h\"), &h, false )\r\n\t\t\t\t\t&& pParams->GetInteger( CRCD(0xe4f130f4,\"s\"), &s, false )\r\n\t\t\t\t\t&& pParams->GetInteger( CRCD(0x949bc47b,\"v\"), &v, false ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_model->ModulateColor( CRCD(0xc4e78e22,\"all\"), (float)h, (float)s / 100.0f, (float)v / 100.0f );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n        // @script | Obj_ReplaceTexture | Replaces a texture in the model's dictionary\r\n        // @parm text | src | filename of the source texture\r\n        // @parm text | dest | filename of the destination texture\r\n        // @parmopt name | in | all | name of geom in which to look for texture (defaults to global replacement)\r\n\t\t// Ex:  Obj_ReplaceTexture src=\"knee_l.png\" dest=\"textures/skater_m/knee_scuff\"\tin=skater_m_legs\r\n\t\tcase 0x83f9be15: // Obj_ReplaceTexture\r\n\t\t{\r\n\t\t\tconst char* pSrcTexture;\r\n\t\t\tconst char* pDstTexture;\r\n\t\t\t\r\n\t\t\tsuccess = false;\r\n\t\t\t\r\n\t\t\tScript::CArray* pArray;\r\n\t\t\tif ( pParams->GetArray( CRCD(0x5ef31148,\"array\"), &pArray, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tfor ( uint32 i = 0; i < pArray->GetSize(); i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct* pSubParams = pArray->GetStructure( i );\r\n\t\t\t\t\r\n\t\t\t\t\tpSubParams->GetText( CRCD(0x9fbbdb72,\"src\"), &pSrcTexture, Script::ASSERT );\r\n\t\t\t\t\tpSubParams->GetText( CRCD(0x7799d66c,\"dest\"), &pDstTexture, Script::ASSERT );\r\n\r\n\t\t\t\t\t// by default, it searches globally in the model for the correct texture\r\n\t\t\t\t\tuint32 partChecksumToReplace = Nx::CModel::vREPLACE_GLOBALLY;\r\n\t\t\t\t\tpSubParams->GetChecksum( CRCD(0xa01371b1,\"in\"), &partChecksumToReplace, Script::NO_ASSERT );\r\n\t\t\t\t\tif ( mp_model )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( mp_model->ReplaceTexture( partChecksumToReplace, pSrcTexture, pDstTexture ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tsuccess = true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpParams->GetText( CRCD(0x9fbbdb72,\"src\"), &pSrcTexture, Script::ASSERT );\r\n\t\t\t\tpParams->GetText( CRCD(0x7799d66c,\"dest\"), &pDstTexture, Script::ASSERT );\r\n\r\n\t\t\t\t// by default, it searches globally in the model for the correct texture\r\n\t\t\t\tuint32 partChecksumToReplace = Nx::CModel::vREPLACE_GLOBALLY;\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xa01371b1,\"in\"), &partChecksumToReplace, Script::NO_ASSERT );\r\n\t\t\t\tif ( mp_model )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( mp_model->ReplaceTexture( partChecksumToReplace, pSrcTexture, pDstTexture ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsuccess = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n        \t\t\r\n\t\t// @script | Obj_ReplaceSpriteTexture | Replaces a texture in the model's dictionary\r\n\t\t// @parm text | src | filename of the source texture\r\n\t\t// @parm name | dest | name of the destination texture\r\n\t\t// @parmopt name | in | all | name of geom in which to look for texture (defaults to global replacement)\r\n\t\t// Ex:  Obj_ReplaceSpriteTexture src=\"knee_l.png\" dest=knee_scuff\tin=skater_m_legs\r\n\t\tcase 0x9a478afe: // Obj_ReplaceSpriteTexture\r\n\t\t{\r\n\t\t\tconst char* pSrcTexture;\r\n\t\t\tuint32 dest_checksum = 0;\r\n\r\n\t\t\tpParams->GetText( CRCD(0x9fbbdb72,\"src\"), &pSrcTexture, Script::ASSERT );\r\n\t\t\tpParams->GetChecksum( CRCD(0x7799d66c,\"dest\"), &dest_checksum, Script::ASSERT );\r\n\r\n\t\t\t// by default, it searches globally in the model for the correct texture\r\n\t\t\tuint32 partChecksumToReplace = Nx::CModel::vREPLACE_GLOBALLY;\r\n\t\t\tpParams->GetChecksum( CRCD(0xa01371b1,\"in\"), &partChecksumToReplace, Script::NO_ASSERT );\r\n\t\t\tif ( mp_model )\r\n\t\t\t{\r\n\t\t\t\tsuccess = mp_model->ReplaceTexture( partChecksumToReplace, pSrcTexture, dest_checksum );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsuccess = false;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\t// @script | Obj_ClearGeoms | removes the model's geoms\r\n\t\tcase 0xbd18e2e3: // Obj_ClearGeoms\r\n\t\t\tif ( mp_model )\r\n\t\t\t{\r\n\t\t\t\tmp_model->ClearGeoms();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n        \r\n\t\t// @script | Obj_HasModelLights | tests existence of model lights\r\n\t\tcase 0xe11f85e8: // Obj_HasModelLights\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(mp_model, (\"Obj_HasModelLights: CModel is NULL\"));\r\n\t\t\t\t\r\n\t\t\t\treturn mp_model->GetModelLights() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | Obj_UpdateBrightness | the normal lighting code assumes\r\n\t\t// that the collision code will be run once a frame to copy over\r\n\t\t// the m_ambient_base_color into the m_ambient_mod_color.  unfortunately,\r\n\t\t// the cutscene objects' ref objects don't go through this code, so I had to\r\n\t\t// add this function to explicitly copy over the data...  there's probably\r\n\t\t// a cleaner way to do it, but I didn't want to break the existing code.\r\n\t\tcase 0x1c16332e: // Obj_UpdateBrightness\r\n\t\t\tDbg_MsgAssert(mp_model, (\"Obj_UpdateBrightness: CModel is NULL\"));\r\n\t\t\tDbg_MsgAssert(mp_model->GetModelLights(), (\"Obj_UpdateBrightness: MovingObject has no model lights\"));\r\n\t\t\tmp_model->GetModelLights()->UpdateBrightness();\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | Obj_EnableAmbientLight | enables the ambient model light\r\n\t\tcase 0xa14d6372: // Obj_EnableAmbientLight\r\n\t\t\tDbg_MsgAssert(mp_model, (\"Obj_EnableAmbientLight: CModel is NULL\"));\r\n\t\t\tDbg_MsgAssert(mp_model->GetModelLights(), (\"Obj_EnableAmbientLight: MovingObject has no model lights\"));\r\n\t\t\tmp_model->GetModelLights()->EnableAmbientLight(true);\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | Obj_DisableAmbientLight | disables the ambient model light\r\n\t\tcase 0x8a445e26: // Obj_DisableAmbientLight\r\n\t\t\tDbg_MsgAssert(mp_model, (\"Obj_DisableAmbientLight: CModel is NULL\"));\r\n\t\t\tDbg_MsgAssert(mp_model->GetModelLights(), (\"Obj_DisableAmbientLight: MovingObject has no model lights\"));\r\n\t\t\tmp_model->GetModelLights()->EnableAmbientLight(false);\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | Obj_EnableDiffuseLight | enables a diffuse model light\r\n\t\t// @parm int | index | Light number\r\n\t\tcase 0xed5d1550: // Obj_EnableDiffuseLight\r\n\t\t{\r\n\t\t\tint index;\r\n\r\n\t\t\tif (!pParams->GetInteger(CRCD(0x7f8c98fe,\"index\"), &index))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Obj_EnableDiffuseLight: Can't find 'index' of light\"));\r\n\t\t\t}\r\n\r\n\t\t\tDbg_MsgAssert(mp_model, (\"Obj_EnableDiffuseLight: CModel is NULL\"));\r\n\t\t\tDbg_MsgAssert(mp_model->GetModelLights(), (\"Obj_EnableDiffuseLight: MovingObject has no model lights\"));\r\n\t\t\tmp_model->GetModelLights()->EnableDiffuseLight(index, true);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | Obj_DisableDiffuseLight | disables a diffuse model light\r\n\t\t// @parm int | index | Light number\r\n\t\tcase 0xc6542804: // Obj_DisableDiffuseLight\r\n\t\t{\r\n\t\t\tint index;\r\n\r\n\t\t\tif (!pParams->GetInteger(CRCD(0x7f8c98fe,\"index\"), &index))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Obj_DisableDiffuseLight: Can't find 'index' of light\"));\r\n\t\t\t}\r\n\r\n\t\t\tDbg_MsgAssert(mp_model, (\"Obj_DisableDiffuseLight: CModel is NULL\"));\r\n\t\t\tDbg_MsgAssert(mp_model->GetModelLights(), (\"Obj_DisableDiffuseLight: MovingObject has no model lights\"));\r\n\t\t\tmp_model->GetModelLights()->EnableDiffuseLight(index, false);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | Obj_SetLightAmbientColor | Sets the model light ambient color\r\n\t\t// @parm int | r | Red\r\n\t\t// @parm int | g | Green\r\n\t\t// @parm int | b | Blue\r\n\t\tcase 0x3cf63049: // Obj_SetLightAmbientColor\r\n\t\t{\r\n\t\t\tint r, g, b;\r\n\t\t\tif (!pParams->GetInteger(CRCD(0x93f60062,\"r\"), &r))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Obj_SetLightAmbientColor: Can't find 'r' color\"));\r\n\t\t\t}\r\n\t\t\tif (!pParams->GetInteger(CRCD(0xfe2be489,\"g\"), &g))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Obj_SetLightAmbientColor: Can't find 'g' color\"));\r\n\t\t\t}\r\n\t\t\tif (!pParams->GetInteger(CRCD(0x8e411006,\"b\"), &b))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Obj_SetLightAmbientColor: Can't find 'b' color\"));\r\n\t\t\t}\r\n\r\n\t\t\tImage::RGBA rgb(r, g, b, 0x80);\r\n\r\n\t\t\tDbg_MsgAssert(mp_model, (\"Obj_SetLightAmbientColor: CModel is NULL\"));\r\n\t\t\tDbg_MsgAssert(mp_model->GetModelLights(), (\"Obj_SetLightAmbientColor: MovingObject has no model lights\"));\r\n\t\t\tmp_model->GetModelLights()->SetLightAmbientColor(rgb);\r\n\t\t\tmp_model->GetModelLights()->EnableAmbientLight(true);\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | Obj_SetLightDirection | Sets the unit direction vector of a model light\r\n\t\t// @parm int | index | Light number\r\n\t\t// @parm vector | direction | Unit direction vector (overrides heading and pitch)\r\n\t\t// @parm float | heading | Heading angle (in degrees)\r\n\t\t// @parm float | pitch | Pitch angle (in degrees)\r\n\t\tcase 0x46a1f4a4: // Obj_SetLightDirection\r\n\t\t{\r\n\t\t\tint index;\r\n\r\n\t\t\tif (!pParams->GetInteger(CRCD(0x7f8c98fe,\"index\"), &index))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Obj_SetLightDirection: Can't find 'index' of light\"));\r\n\t\t\t}\r\n\r\n\t\t\tfloat heading, pitch;\r\n\t\t\tMth::Vector direction(0, 0, 1, 0);\r\n\t\t\tif (pParams->GetVector(CRCD(0xc1b52e4c,\"direction\"), &direction))\r\n\t\t\t{\r\n\t\t\t\tdirection[W] = 0.0f;\t\t// This is the only way to force this to be a vector (as opposed to a point)\r\n\t\t\t\t//Dbg_Message(\"************ direction (%f, %f, %f)\", direction[X], direction[Y], direction[Z]);\r\n\t\t\t}\r\n\t\t\telse if (pParams->GetFloat(CRCD(0xfd4bc03e,\"heading\"), &heading) && pParams->GetFloat(CRCD(0xd8604126,\"pitch\"), &pitch)) \r\n\t\t\t{\r\n\t\t\t\tdirection.RotateX(Mth::DegToRad(pitch));\r\n\t\t\t\tdirection.RotateY(Mth::DegToRad(heading));\r\n\t\t\t\t//Dbg_Message(\"************ heading and pitch direction (%f, %f, %f)\", direction[X], direction[Y], direction[Z]);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Obj_SetLightDirection: Can't find 'direction' or 'heading' and 'pitch' of light\"));\r\n\t\t\t}\r\n\r\n\t\t\tDbg_MsgAssert(mp_model, (\"Obj_SetLightDirection: CModel is NULL\"));\r\n\t\t\tDbg_MsgAssert(mp_model->GetModelLights(), (\"Obj_SetLightDirection: MovingObject has no model lights\"));\r\n\t\t\tmp_model->GetModelLights()->SetLightDirection(index, direction);\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | Obj_SetLightDiffuseColor | Sets a model light diffuse color\r\n\t\t// @parm int | index | Light number\r\n\t\t// @parm int | r | Red\r\n\t\t// @parm int | g | Green\r\n\t\t// @parm int | b | Blue\r\n\t\tcase 0x70e6466b: // Obj_SetLightDiffuseColor\r\n\t\t{\r\n\t\t\tint index;\r\n\r\n\t\t\tif (!pParams->GetInteger(CRCD(0x7f8c98fe,\"index\"), &index))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Obj_SetLightDiffuseLight: Can't find 'index' of light\"));\r\n\t\t\t}\r\n\r\n\t\t\tint r, g, b;\r\n\t\t\tif (!pParams->GetInteger(CRCD(0x93f60062,\"r\"), &r))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Obj_SetLightDiffuseColor: Can't find 'r' color\"));\r\n\t\t\t}\r\n\t\t\tif (!pParams->GetInteger(CRCD(0xfe2be489,\"g\"), &g))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Obj_SetLightDiffuseColor: Can't find 'g' color\"));\r\n\t\t\t}\r\n\t\t\tif (!pParams->GetInteger(CRCD(0x8e411006,\"b\"), &b))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Obj_SetLightDiffuseColor: Can't find 'b' color\"));\r\n\t\t\t}\r\n\r\n\t\t\tImage::RGBA rgb(r, g, b, 0x80);\r\n\r\n\t\t\tDbg_MsgAssert(mp_model, (\"Obj_SetLightDiffuseColor: CModel is NULL\"));\r\n\t\t\tDbg_MsgAssert(mp_model->GetModelLights(), (\"Obj_SetLightDiffuseColor: MovingObject has no model lights\"));\r\n\t\t\tmp_model->GetModelLights()->SetLightDiffuseColor(index, rgb);\r\n\t\t\tmp_model->GetModelLights()->EnableDiffuseLight(index, true);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | Obj_SetUVOffset | Sets the UV offset of a material pass\r\n\t\t// @parm name | material | material name\r\n\t\t// @parm int | pass | material pass\r\n\t\t// @parm float | u | u offset\r\n\t\t// @parm float | v | v offset\r\n\t\tcase 0x57eb306e: // Obj_SetUVOffset\r\n\t\t{\r\n\t\t\tuint32 mat_checksum;\r\n\t\t\tif (!pParams->GetChecksum(CRCD(0x83418a6a,\"material\"), &mat_checksum))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Can't find parameter material\"));\r\n\t\t\t}\r\n\r\n\t\t\t// Extract all the parameters\r\n\t\t\tint pass = 0;\r\n\t\t\tfloat u_offset;\r\n\t\t\tfloat v_offset;\r\n\t\t\tbool found_all;\r\n\r\n\t\t\tfound_all  = pParams->GetFloat(CRCD(0xd9295c1,\"u\"), &u_offset);\r\n\t\t\tfound_all &= pParams->GetFloat(CRCD(0x949bc47b,\"v\"), &v_offset);\r\n\t\t\tfound_all &= pParams->GetInteger(CRCD(0x318f2bdb,\"pass\"), &pass);\r\n\r\n\t\t\tDbg_MsgAssert(found_all, (\"Missing one or more of the wibble offset parameters.  Must fill them all out.\"));\r\n\r\n\t\t\tDbg_MsgAssert(mp_model, (\"Obj_SetUVOffset: CModel is NULL\"));\r\n\t\t\tmp_model->SetUVOffset(mat_checksum, pass, u_offset, v_offset);\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | Obj_SetUVParams | Sets the UV parameters of a material pass\r\n\t\t// @parm name | material | material name\r\n\t\t// @parm int | pass | material pass\r\n\t\t// @parmopt float | uoff | 0.0 | u offset\r\n\t\t// @parmopt float | voff | 0.0 | v offset\r\n\t\t// @parmopt float | uscale | 1.0 | u scale\r\n\t\t// @parmopt float | vscale | 1.0 | v scale\r\n\t\t// @parmopt float | rot | 0.0 | rotation in degrees\r\n\t\tcase 0x812ff44d: // Obj_SetUVParams\r\n\t\t{\r\n\t\t\tuint32 mat_checksum;\r\n\t\t\tint pass;\r\n\t\t\tif (!pParams->GetChecksum(CRCD(0x83418a6a,\"material\"), &mat_checksum))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Can't find parameter material\"));\r\n\t\t\t}\r\n\t\t\tif (!pParams->GetInteger(CRCD(0x318f2bdb,\"pass\"), &pass))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Can't find parameter pass\"));\r\n\t\t\t}\r\n\r\n\t\t\t// Clear matrix\r\n\t\t\tMth::Matrix mat;\r\n\t\t\tmat.Ident();\r\n\r\n\t\t\t// Scaling\r\n\t\t\tfloat uscale = 1.0f;\r\n\t\t\tfloat vscale = 1.0f;\r\n\t\t\tbool scale = pParams->GetFloat(CRCD(0x3fb610b7,\"uscale\"), &uscale);\r\n\t\t\tscale = pParams->GetFloat(CRCD(0xb9226219,\"vscale\"), &vscale) || scale;\r\n\t\t\tif (scale)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert((uscale >= 0.0f) && (vscale >= 0.0f), (\"Obj_SetUVParams: Don't use negative scales.\"));\r\n\r\n\t\t\t\tmat[0][0] *= uscale;\r\n\t\t\t\tmat[1][1] *= vscale;\r\n\t\t\t}\r\n\r\n\t\t\t// Rotation\r\n\t\t\tfloat rot_deg;\r\n\t\t\tif (pParams->GetFloat(CRCD(0xe2c6589e,\"rot\"), &rot_deg))\r\n\t\t\t{\r\n\t\t\t\tmat.RotateZ(Mth::DegToRad(rot_deg));\r\n\t\t\t}\r\n\r\n\t\t\t// Offset\r\n\t\t\tfloat uoffset = 0.0f;\r\n\t\t\tfloat voffset = 0.0f;\r\n\t\t\tbool translate = pParams->GetFloat(CRCD(0x56a7f41c,\"uoff\"), &uoffset);\r\n\t\t\ttranslate = pParams->GetFloat(CRCD(0x44125bf2,\"voff\"), &voffset) || translate;\r\n\t\t\tif (translate)\r\n\t\t\t{\r\n\t\t\t\tmat[3][0] = uoffset;\r\n\t\t\t\tmat[3][1] = voffset;\r\n\t\t\t}\r\n\r\n\t\t\tDbg_MsgAssert(mp_model, (\"Obj_SetUVParams: CModel is NULL\"));\r\n\t\t\tmp_model->SetUVMatrix(mat_checksum, pass, mat);\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n        // @script | EnableDisplayFlip | \r\n\t\tcase 0x721184c7: // EnableDisplayFlip\r\n\t\t\tmFlipDisplayMatrix=true;\r\n\t\t\tbreak;\r\n\r\n        // @script | DisableDisplayFlip | \r\n\t\tcase 0x4af3b1f7: // DisableDisplayFlip\r\n\t\t\tmFlipDisplayMatrix=false;\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_InitModel | \r\n\t\tcase 0x4d8e11ab: // Obj_InitModel\r\n\t\t\tInitModel( pParams );\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | SwitchOffAtomic | \r\n        // @uparm name | geom name\r\n\t\tcase 0xe48fd084: // SwitchOffAtomic\r\n\t\t{\r\n\t\t\tuint32 atomicName;\r\n\t\t\tpParams->GetChecksum( NONAME, &atomicName, Script::ASSERT );\r\n\t\t\tHideGeom(atomicName, true, true);\r\n\t\t}\r\n\t\tbreak;\r\n\r\n        // @script | SwitchOnAtomic | \r\n        // @uparm name | geom name\r\n\t\tcase 0x07d0c128: // SwitchOnAtomic\r\n\t\t{\r\n\t\t\tuint32 atomicName;\r\n\t\t\tpParams->GetChecksum( NONAME, &atomicName, Script::ASSERT );\r\n\t\t\tHideGeom(atomicName, false, true);\r\n\t\t}\r\n\t\tbreak;\r\n\r\n        // @script | AtomicIsHidden | \r\n        // @uparm name | geom name\r\n        case 0xe7fa7dd0: // AtomicIsHidden\r\n\t\t{\r\n\t\t\tuint32 atomicName;\r\n\t\t\tpParams->GetChecksum( NONAME, &atomicName, Script::ASSERT );\r\n            if (GeomHidden( atomicName ))\r\n                pScript->GetParams()->AddInteger(CRCD(0x77a21642,\"hidden\"), 1);\r\n            else\r\n                pScript->GetParams()->AddInteger(CRCD(0x77a21642,\"hidden\"), 0);\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n\t\t// @script | Obj_InitModelFromProfile | used for loading up peds and re-initializing the preview model\r\n\t\tcase 0x98ed5c8b: // Obj_InitModelFromProfile\r\n\t\t{\r\n\t\t\tif ( mp_model )\r\n\t\t\t{\r\n\t\t\t\tint texDictOffset = 0;\r\n\t\t\t\tpParams->GetInteger( CRCD(0xf891ac27,\"texDictOffset\"), &texDictOffset, Script::NO_ASSERT );\r\n\r\n\t\t\t\tint useAssetManager = 0;\r\n\t\t\t\tpParams->GetInteger( CRCD(0xc63c8d38,\"use_asset_manager\"), &useAssetManager, Script::NO_ASSERT );\r\n\r\n\t\t\t\tScript::CStruct* pAppearanceParams;\r\n\t\t\t\tpParams->GetStructure( CRCD(0x456d28d1,\"struct\"), &pAppearanceParams, Script::ASSERT );\r\n\r\n\t\t\t\tuint32 buildScript = 0;\r\n\t\t\t\tpParams->GetChecksum( CRCD(0x299ee352,\"buildscript\"), &buildScript, Script::NO_ASSERT );\r\n\t\t\t\t\r\n\t\t\t\t// load the skeleton (do i really need to do a sanity check here?)\r\n//              Dbg_MsgAssert( GetSkeleton(), ( \"Object has no skeleton\" ) )\r\n\r\n\t\t\t\tGfx::CModelAppearance theAppearance;\r\n\t\t\t\ttheAppearance.Load( pAppearanceParams, true );\r\n\t\t\t\tInitModelFromProfile( &theAppearance, useAssetManager, texDictOffset, buildScript );\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n\t\t// @script | Obj_SetBoundingSphere | sets a sphere with the specified radius (assumes position is 0,0,0)\r\n\t\t// @uparm float | radius of bounding sphere\r\n\t\tcase 0x452fb315:  // Obj_SetBoundingSphere\r\n\t\t{\t\r\n\t\t\tfloat radius;\r\n\t\t\tpParams->GetFloat( NONAME, &radius, Script::ASSERT );\r\n\t\t\t\r\n\t\t\t// take the existing position, and change the radius on it\r\n\t\t\tMth::Vector newSphere( 0.0f, 0.0f, 0.0f, radius );\r\n\t\t\t\r\n\t\t\tSetBoundingSphere( newSphere );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\t// @script | Obj_RestoreBoundingSphere | resets the sphere to whatever it was after the model was initialized\r\n\t\tcase 0x5b41da8f:  // Obj_RestoreBoundingSphere\r\n\t\t{\r\n\t\t\tSetBoundingSphere( m_original_bounding_sphere );\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n        // @script | RotateDisplay | \r\n        // @parmopt float | Duration | 0.0 | Duration time (default is ms) The rotation will take this much time to complete.\r\n        // @flag seconds | Units of seconds\r\n        // @flag frames | Units of frames\r\n        // @flag x | Rotate about the x-axis\r\n        // @flag y | Rotate about the y-axis\r\n        // @flag z | Rotate about the z-axis\r\n        // @parmopt float | StartAngle | 0.0 | Start angle, in degrees. The skater will instantly pop to this angle\r\n\t\t// when the RotateDisplay command is issued.\r\n        // @parmopt float | EndAngle | 360.0 | End angle, in degrees. The skater will rotate from\r\n\t\t// the start angle to the end angle over the time period specified by Duration.\r\n        // @parmopt int | SinePower | 0 | If set to zero (the default) the angle will change at a constant speed over\r\n\t\t// the specified duration.\r\n\t\t// A SinePower of 1 makes the speed start instantly but slow down smoothly at the end.\r\n\t\t// A SinePower of greater than one will make the speed smoothly accelerate from zero to a maximum, then\r\n\t\t// smoothly decelerate to zero. Values of 2,3 or 4 seem to work best.\r\n\t\t// A SinePower of -1 will make the speed smoothly accelerate from zero to a constant value. It will not\r\n\t\t// decelerate at the end.\r\n\t\t// Note that the final constant speed will be 1.5707 times the constant speed that would be have been used\r\n\t\t// if the SinePower was 0. The speed has to be a bit higher to make up for the smooth acceleration at the start\r\n\t\t// whilst keeping within the same Duration value.\r\n\t\t// So, if you want to follow with another RotateDisplay that maintains that constant speed, you will need to\r\n\t\t// divide it's duration by 1.5707, for example:\r\n\t\t// RotateDisplay y Duration=3 seconds EndAngle=(360*4) SinePower=-1\r\n\t\t// Wait 3 seconds\r\n\t\t// RotateDisplay y Duration=(3/1.5707) seconds EndAngle=(360*4) SinePower=0\r\n\t\t// @parmopt vector | RotationOffset | (0,30,0) | The offset of the point about which to rotate the skater.\r\n\t\t// @flag HoldOnLastAngle | If specified then the rotation will not pop back to what it was at\r\n\t\t// the end of the duration, but will stick until a CancelRotateDisplay command is issued.\r\n\t\tcase 0xa4c25c2f: // RotateDisplay\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tprintf(\"RotateDisplay\\n\");\r\n\t\t\tScript::PrintContents(pParams);\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tfloat duration = 0.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0x79a07f3f, \"Duration\"), &duration);\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0xd029f619, \"Seconds\")) || pParams->ContainsFlag(CRCD(0x49e0ee96, \"Second\")))\r\n\t\t\t{\r\n\t\t\t\t// Convert from seconds to milliseconds\r\n\t\t\t\tduration *= 1000.0f;\r\n\t\t\t}\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0x19176c5, \"Frames\")) || pParams->ContainsFlag(CRCD(0x4a07c332, \"Frame\")))\r\n\t\t\t{\r\n\t\t\t\t// Convert from frames to milliseconds\r\n\t\t\t\tduration = duration * 1000.0f / 60.0f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Milliseconds is what we want, so nothing to do.\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tfloat start_angle = 0.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0x9de2a72f, \"StartAngle\"), &start_angle);\r\n\t\t\t\r\n\t\t\tfloat end_angle = 0.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0x8c9946a9, \"EndAngle\"), &end_angle);\r\n\r\n\t\t\tint sine_power = 0;\r\n\t\t\tpParams->GetInteger(CRCD(0xf164f03d, \"SinePower\"), &sine_power);\r\n\t\t\t\r\n\t\t\tm_display_rotation_offset.Set(0.0f, 30.0f, 0.0f);\r\n\t\t\tpParams->GetVector(CRCD(0x8f38f109, \"RotationOffset\"), &m_display_rotation_offset);\r\n\r\n\t\t\tbool hold_on_last_angle = pParams->ContainsFlag(CRCD(0xe14bc9ac, \"HoldOnLastAngle\"));\r\n\t\t\t\r\n\t\t\tTmr::Time start_time = Tmr::ElapsedTime(0);\r\n\t\t\t\r\n\t\t\tchar flags = 0;\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0x7323e97c, \"X\")))\r\n\t\t\t{\r\n\t\t\t\tflags |= 1;\r\n\t\t\t\tmpDisplayRotationInfo[0].SetUp(duration,\r\n\t\t\t\t\t\t\t\t\t\t\t   start_time,\r\n\t\t\t\t\t\t\t\t\t\t\t   start_angle,\r\n\t\t\t\t\t\t\t\t\t\t\t   end_angle - start_angle,\r\n\t\t\t\t\t\t\t\t\t\t\t   sine_power,\r\n\t\t\t\t\t\t\t\t\t\t\t   hold_on_last_angle);\r\n\t\t\t}\t\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0x424d9ea, \"Y\")))\r\n\t\t\t{\r\n\t\t\t\tflags |= 2;\r\n\t\t\t\tmpDisplayRotationInfo[1].SetUp(duration,\r\n\t\t\t\t\t\t\t\t\t\t\t   start_time,\r\n\t\t\t\t\t\t\t\t\t\t\t   start_angle,\r\n\t\t\t\t\t\t\t\t\t\t\t   end_angle - start_angle,\r\n\t\t\t\t\t\t\t\t\t\t\t   sine_power,\r\n\t\t\t\t\t\t\t\t\t\t\t   hold_on_last_angle);\r\n\t\t\t}\t\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0x9d2d8850, \"Z\")))\r\n\t\t\t{\r\n\t\t\t\tflags |= 4;\r\n\t\t\t\tmpDisplayRotationInfo[2].SetUp(duration,\r\n\t\t\t\t\t\t\t\t\t\t\t   start_time,\r\n\t\t\t\t\t\t\t\t\t\t\t   start_angle,\r\n\t\t\t\t\t\t\t\t\t\t\t   end_angle - start_angle,\r\n\t\t\t\t\t\t\t\t\t\t\t   sine_power,\r\n\t\t\t\t\t\t\t\t\t\t\t   hold_on_last_angle);\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\t// if our object is associated with a local player, send a MsgRotateDisplay message\r\n\t\t\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\t\t\tGameNet::PlayerInfo* player = gamenet_man->GetPlayerByObjectID(GetObject()->GetID());\r\n\t\t\tif (player && player->IsLocalPlayer())\r\n\t\t\t{\r\n\t\t\t\tNet::Client* client;\r\n\t\t\t\tGameNet::MsgRotateDisplay msg;\r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\t\t\r\n\t\t\t\tclient = gamenet_man->GetClient( player->GetSkaterNumber() );\r\n\t\t\t\tDbg_Assert( client );\r\n\t\r\n\t\t\t\t//msg.m_Time = client->m_Timestamp;\r\n\t\t\t\tmsg.m_Duration = static_cast< int >( duration );\r\n\t\t\t\tmsg.m_StartAngle = static_cast< short >( start_angle );\r\n\t\t\t\tmsg.m_DeltaAngle = static_cast< short >( end_angle - start_angle );\r\n\t\t\t\tmsg.m_SinePower = static_cast< int >( sine_power );\r\n\t\t\t\tmsg.m_ObjId = GetObject()->GetID();\r\n\t\t\t\tmsg.m_HoldOnLastAngle = hold_on_last_angle;\r\n\t\t\t\tmsg.m_Flags = flags;\r\n\t\r\n\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgRotateDisplay );\r\n\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_ROTATE_DISPLAY;\r\n\t\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n        // @script | CancelRotateDisplay | Instantly cancels any rotation due to a RotateDisplay\r\n\t\t// command.\r\n\t\tcase 0x4424c267: // CancelRotateDisplay\r\n\t\t{\r\n\t\t\tmpDisplayRotationInfo[0].Clear();\r\n\t\t\tmpDisplayRotationInfo[1].Clear();\r\n\t\t\tmpDisplayRotationInfo[2].Clear();\r\n\t\t\t\t\r\n\t\t\t// if our object is associated with a local player, send a MsgRotateDisplay message\r\n\t\t\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\t\t\tGameNet::PlayerInfo* player = gamenet_man->GetPlayerByObjectID(GetObject()->GetID());\r\n\t\t\tif (player && player->IsLocalPlayer())\r\n\t\t\t{\r\n\t\t\t\tNet::Client* client;\r\n\t\t\t\tGameNet::MsgObjMessage msg;\r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\t\t\r\n\t\t\t\tclient = gamenet_man->GetClient( player->GetSkaterNumber() );\r\n\t\t\t\tDbg_Assert( client );\r\n\t\r\n\t\t\t\t//msg.m_Time = client->m_Timestamp;\r\n\t\t\t\tmsg.m_ObjId = GetObject()->GetID();\r\n\t\r\n\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgObjMessage );\r\n\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_CLEAR_ROTATE_DISPLAY;\r\n\t\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tdefault:\r\n            return CBaseComponent::MF_NOT_EXECUTED;\r\n    }\r\n\r\n    return success ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CModelComponent::GetDebugInfo\"));\r\n\t// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n\t\r\n\tp_info->AddChecksum(CRCD(0xc3f4169a,\"filename\"),mp_model->GetFileName());\r\n\t\r\n\tMth::Vector scale=mp_model->GetScale();\r\n\tp_info->AddVector(CRCD(0x13b9da7b,\"scale\"),scale.GetX(),scale.GetY(),scale.GetZ());\r\n\t\r\n\tuint32 mode=CRCD(0x52d95838,\"Unknown\");\r\n\tswitch (mp_model->GetRenderMode())\r\n\t{\r\n\t\tcase Nx::vTEXTURED:\t \tmode=CRCD(0xd939b2b6,\"vTEXTURED\"); break;\r\n\t\tcase Nx::vSKELETON:\t\tmode=CRCD(0x22b5274d,\"vSKELETON\"); break;\r\n\t\tcase Nx::vGOURAUD:\t\tmode=CRCD(0xe6d7f928,\"vGOURAUD\"); break;\r\n\t\tcase Nx::vFLAT:\t\t\tmode=CRCD(0x3b4168d5,\"vFLAT\"); break;\r\n\t\tcase Nx::vWIREFRAME:\tmode=CRCD(0xec50e3e1,\"vWIREFRAME\"); break;\r\n\t\tcase Nx::vBBOX:\t\t\tmode=CRCD(0x2988b32d,\"vBBOX\"); break;\r\n\t\tcase Nx::vNONE:\t\t\tmode=CRCD(0x119bc25e,\"vNONE\"); break;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\r\n\tp_info->AddChecksum(CRCD(0x2f006949,\"RenderMode\"),mode);\t\t\r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Mick:  This function actually gets called TWICE when a model is created\r\n// Once from the call to Teleport which is called from the CCOmpositeObject::Teleport functions\r\n// and then once from InitModelFromProfile(), whcih is called after the model is finalized.\r\n// Only on the second call will the model have its geometry set up correctly.\r\n// This does not seem to cause problems, but should probably be re-worked for future iterations of the\r\n// engine.\r\nvoid CModelComponent::FinalizeModelInitialization()\r\n{\r\n\t// need to synchronize rendered model's position to initial world position\r\n\tUpdate();\r\n\r\n\tif ( mp_model && mp_model->GetModelLights() )\r\n\t{\r\n\t\tUpdateBrightness();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelComponent::RefreshModel( Gfx::CModelAppearance* pAppearance, uint32 buildScript )\r\n{\r\n\tif ( mp_model )\r\n\t{\r\n\t\t// it doesn't matter whether we use the asset manager\r\n\t\t// or which texture dict offset we use, because\r\n\t\t// the build script will only affect colors...\r\n\t\tbool dummyUseAssetManager = true;\r\n\t\tint dummyTexDictOffset = 0;\r\n\r\n\t\tInitModelFromProfile( pAppearance, dummyUseAssetManager, dummyTexDictOffset, buildScript );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid SDisplayRotationInfo::Clear()\r\n{\r\n\tSDisplayRotation *p_rotation=mpRotations;\r\n\tfor (int i=0; i<MAX_ROTATIONS; ++i)\r\n\t{\r\n\t\tp_rotation->Clear();\r\n\t\t++p_rotation;\r\n\t}\t\r\n\tm_active = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid SDisplayRotationInfo::SetUp(float duration, Tmr::Time start_time, float start_angle, float change_in_angle, int sine_power, bool holdOnLastAngle)\r\n{\r\n\tSDisplayRotation *p_rotation=mpRotations;\r\n\tfor (int i=0; i<MAX_ROTATIONS; ++i)\r\n\t{\r\n\t\tif (!p_rotation->mDispRotating)\r\n\t\t{\r\n\t\t\tp_rotation->SetUp(duration, start_time, start_angle, change_in_angle, sine_power, holdOnLastAngle);\r\n\t\t\tm_active = true;\r\n\t\t\treturn;\r\n\t\t}\t\r\n\t\t++p_rotation;\r\n\t}\t\r\n\t\r\n\t//Dbg_MsgAssert(0,(\"Too many rotations overlaid at once, maximum is %d\",SDisplayRotationInfo::MAX_ROTATIONS));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat SDisplayRotationInfo::CalculateNewAngle()\r\n{\r\n\tfloat new_angle=0.0f;\r\n\tif (m_active)\r\n\t{\r\n\t\tm_active = false;\r\n\t\tSDisplayRotation *p_rotation=mpRotations;\r\n\t\tfor (int i=0; i<MAX_ROTATIONS; ++i)\r\n\t\t{\r\n\t\t\tif (p_rotation->mDispRotating)\r\n\t\t\t{\r\n\t\t\t\tm_active = true;\r\n\t\t\t\tnew_angle+=p_rotation->CalculateNewAngle();\r\n\t\t\t}\r\n\t\t\t++p_rotation;\r\n\t\t}\r\n\t}\t\r\n\treturn new_angle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid SDisplayRotation::Clear()\r\n{\r\n\tmDispRotating=false;\r\n\tmHoldOnLastAngle=false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid SDisplayRotation::SetUp(float duration, Tmr::Time start_time, float start_angle, float change_in_angle, int sine_power, bool holdOnLastAngle)\r\n{\r\n\tmDispRotating=true;\r\n\tmDispDuration=duration;\r\n\tmDispStartTime=start_time;\r\n\tmDispStartAngle=start_angle;\r\n\tmDispChangeInAngle=change_in_angle;\r\n\tmDispSinePower=sine_power;\r\n\tmHoldOnLastAngle=holdOnLastAngle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat SDisplayRotation::CalculateNewAngle()\r\n{\r\n\tfloat new_angle=0.0f;\r\n\t\r\n\tif (mDispRotating)\r\n\t{\r\n\t\tfloat t=Tmr::ElapsedTime(0)-mDispStartTime;\r\n\t\tif (t>mDispDuration)\r\n\t\t{\r\n\t\t\tif (mHoldOnLastAngle)\r\n\t\t\t{\r\n\t\t\t\t// Stick forever on the end angle, until the mHoldOnLastAngle gets reset\r\n\t\t\t\t// by a CancelRotateDisplay script command.\r\n\t\t\t\tnew_angle=mDispStartAngle+mDispChangeInAngle;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmDispRotating=false;\r\n\t\t\t}\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (mDispSinePower)\r\n\t\t\t{\r\n\t\t\t\tfloat s;\r\n\t\t\t\tif (mDispSinePower<0)\r\n\t\t\t\t{\r\n\t\t\t\t\t// If a negative sine power is specified, then use an upside-down and\r\n\t\t\t\t\t// back-to-front sine wave. This gives a rotation which smoothly accelerates\r\n\t\t\t\t\t// to a constant speed.\r\n\t\t\t\t\ts=1.0f-sinf(1.570796327f-t*1.570796327f/mDispDuration);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\ts=sinf(t*1.570796327f/mDispDuration);\r\n\t\t\t\t\tfor (int i=0; i<mDispSinePower-1; ++i)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ts=s*s;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\r\n\t\t\t\tnew_angle=mDispStartAngle+s*mDispChangeInAngle;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tnew_angle=mDispStartAngle+t*mDispChangeInAngle/mDispDuration;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t}\t\r\n\t\r\n\treturn new_angle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CModelComponent::GetRefObjectName()\r\n{\r\n\tDbg_MsgAssert( m_hasRefObject, ( \"Object %s doesn't have a ref object\", Script::FindChecksumName(GetObject()->GetID()) ) );\r\n\t\t\t\t  \r\n\treturn m_refObjectName;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelComponent::ApplyLightingFromCollision( CFeeler& feeler )\r\n{\r\n\tif (!feeler.IsBrightnessAvailable()) return;\r\n\t\r\n\tif (Nx::CModelLights* p_model_lights = GetModel()->GetModelLights())\r\n\t{\r\n\t\tp_model_lights->SetBrightness(feeler.GetBrightness());\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNx::CLightManager::sSetBrightness(feeler.GetBrightness());\r\n\t}\r\n}\r\n\t\t\t\t\t\t\t\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelComponent::ApplySceneLighting( Image::RGBA color )\r\n{\r\n\t// Mick: if the model is a level object, then apply the scene lighthing to it\r\n\tif (m_isLevelObject)\r\n\t{\r\n\t\tmp_model->GetGeomByIndex(0)->SetColor(color);\r\n\t}\r\n}\r\n\t\t\t\t\t\t\t\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t\t\t\t\t \r\n}\r\n\r\n#if 0\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// GJ TODO:  these cheat codes are kind of kludgy \r\n// and should be re-implemented later in a more \r\n// component-friendly format.\r\n\r\nbool apply_cheat_scale( Gfx::CSkeleton* pSkeleton, Nx::CModel* pModel, uint32 cheatName, uint32 bodyShapeName, uint32 animScriptName )\r\n{\r\n\tint flag = Script::GetInteger( cheatName, Script::ASSERT );\r\n\t\r\n\tif ( Mdl::Skate::Instance()->GetCareer()->GetGlobalFlag(flag) )\r\n\t{\r\n\t\tDbg_Assert( pModel );\r\n\r\n\t\tif ( animScriptName == CRCD(0x501949bd,\"animload_human\") \r\n\t\t\t || animScriptName == CRCD(0x105f6aa1,\"animload_ped_f\") )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( pSkeleton, ( \"Skeleton has not been assigned to this model yet\" ) );\r\n\t\t\tScript::CStruct* pBodyShapeStructure = Script::GetStructure( bodyShapeName, Script::ASSERT );\r\n\t\t\t\r\n\t\t\tMth::Vector theScale( 1.0f, 1.0f, 1.0f );\r\n\t\t\tif ( Gfx::GetScaleFromParams( &theScale, pBodyShapeStructure ) )\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec = pModel->GetScale();\r\n\t\t\t\t\r\n\t\t\t\tvec[X] *= theScale[X];\r\n\t\t\t\tvec[Y] *= theScale[Y];\r\n\t\t\t\tvec[Z] *= theScale[Z];\r\n\r\n\t\t\t\t// if the body shape has a scale\r\n\t\t\t\tpModel->SetScale( vec );\r\n\t\t\t}\r\n\r\n\t\t\tpSkeleton->ApplyBoneScale( pBodyShapeStructure );\r\n\t\t}\r\n\t\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/modelcomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       ModelComponent.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/17/2002\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_MODELCOMPONENT_H__\r\n#define __COMPONENTS_MODELCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <core/math.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gfx/image/imagebasic.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_MODEL CRCD(0x286a8d26,\"Model\")\r\n#define\t\tGetModelComponent() ((Obj::CModelComponent*)GetComponent(CRC_MODEL))\r\n#define\t\tGetModelComponentFromObject(pObj) ((Obj::CModelComponent*)(pObj)->GetComponent(CRC_MODEL))\r\n\r\nclass CFeeler;\r\n\t\t\r\nnamespace Gfx\r\n{\r\n\tclass CModelAppearance;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n    class CModel;\r\n}\r\n\r\nnamespace Script\r\n{\r\n\tclass CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\n\tclass CSkeletonComponent;\r\n\tclass CAnimationComponent;\r\n\tclass CSuspendComponent;\r\n\r\n\r\nstruct SDisplayRotation\r\n{\r\n\tbool mDispRotating;\r\n\tbool mHoldOnLastAngle;\r\n\tfloat mDispDuration;\r\n\tTmr::Time mDispStartTime;\r\n\tfloat mDispStartAngle;\r\n\tfloat mDispChangeInAngle;\r\n\tint\tmDispSinePower;\r\n\t\r\n\tvoid SetUp(float duration, Tmr::Time start_time, float start_angle, float change_in_angle, int sine_power, bool holdOnLastAngle);\r\n\tfloat CalculateNewAngle();\r\n\tvoid Clear();\r\n};\r\n\r\nstruct SDisplayRotationInfo\r\n{\r\n\t// Factored out the data members into the SDisplayRotation structure so that\r\n\t// there can be 6 operating at once. Needed by Zac for create-a-trick.\r\n\tenum\r\n\t{\r\n\t\tMAX_ROTATIONS=6\r\n\t};\r\n\tSDisplayRotation mpRotations[MAX_ROTATIONS];\r\n\tbool\tm_active;\r\n\t\r\n\tvoid SetUp(float duration, Tmr::Time start_time, float start_angle, float change_in_angle, int sine_power, bool holdOnLastAngle);\r\n\tfloat CalculateNewAngle();\r\n\tvoid Clear();\r\n};\r\n\r\nclass CModelComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CModelComponent();\r\n    virtual\t~CModelComponent();\r\n\r\npublic:\r\n    virtual void    \t\tUpdate();\r\n    virtual void    \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void\t\t\tHide( bool should_hide );\r\n    virtual void\t\t\tFinalize();\r\n\tvirtual void\t\t\tTeleport();\r\n\r\n    EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\t\r\n\t// Used by the script debugger code to fill in a structure\r\n\t// for transmitting to the monitor.exe utility running on the PC.\r\n\tvirtual void\t\t\tGetDebugInfo(Script::CStruct *p_info);\r\n\t\r\n\tstatic CBaseComponent*\ts_create();\r\n\r\npublic:\r\n\tvoid\t\t\t\t\tInitModel( Script::CStruct* pParams );\r\n\tvirtual void\t\t\tInitModelFromProfile( Gfx::CModelAppearance* pAppearance, bool useAssetManager, uint32 texDictOffset, uint32 buildScript = 0 );\r\n\tvoid \t\t\t\t\tFinalizeModelInitialization();\r\n\tvoid\t\t\t\t\tRefreshModel( Gfx::CModelAppearance* pAppearance, uint32 buildScript );\r\n    Nx::CModel*     \t\tGetModel();\r\n\tbool\t\t\t\t\tHideGeom( uint32 geomName, bool hidden, bool propagate );\r\n    bool\t\t\t\t\tGeomHidden( uint32 geomName );\r\n\tvoid\t\t\t\t\tSetModelLODDistance( int lodIndex, float distance );\r\n\tvoid\t\t\t\t\tSetBoundingSphere( const Mth::Vector& newSphere );\r\n\tvoid\t\t\t\t\tApplyLightingFromCollision ( CFeeler& feeler );\r\n\tvoid\t\t\t\t\tApplySceneLighting(Image::RGBA color);\r\n\tvoid\t\t\t\t\tUpdateBrightness();\r\n\t// K: This used to be protected, but I made it public for use by CLockObjComponent::LockToObject\r\n\tvoid\t\t\t\t\tGetDisplayMatrixWithExtraRotation( Mth::Matrix& displayMatrix );\r\n\t\r\n\tvoid\t\t\t\t\tSetDisplayOffset ( const Mth::Vector& display_offset ) { mDisplayOffset = display_offset; }\r\n\t\r\nprotected:\r\n\tvoid \t\t\t\t\tinit_model_from_level_object( uint32 checksumName );\r\n\tbool\t\t\t\t\tenable_lod(uint32 componentName, float distance);\r\n\r\n\r\nprotected:\r\n\t// Sometimes we need to temporarily change the bounding sphere\r\n\t// of an object (like when an animation takes a model far\r\n\t// from its original bouding sphere)...  the following\r\n\t// is used to correctly restore the original bounding sphere\r\n\tMth::Vector\t\t\t\tm_original_bounding_sphere;\r\n\r\n\r\n// the following are used for tweaking the display matrix\r\n// right before the rendered model actually uses it\r\n// public during transition\r\npublic:\r\n\t\r\n\t// The offset relative to the skater's origin about which the display rotation rotates.\r\n\tMth::Vector \t\t\tm_display_rotation_offset;\r\n\t\r\n\t\r\n\t// Stuff for rotating just the display matrix, so that\r\n\t// the physics and camera don't notice it.\r\n\tSDisplayRotationInfo \tmpDisplayRotationInfo[3];\r\n\r\n\t// Controlled by the script commands EnableDisplayFlip and DisableDisplayFlip.\r\n\t// Added to allow the lip script to finish its out-anim whilst on the ground without a glitch.\r\n\t// When set, this will cause the display matrix to be the regular matrix flipped, each frame.\r\n\tbool\t\t\t\t\tmFlipDisplayMatrix;\r\n\t\r\n\t// Offset from object's position at which the model is drawn.  Defaults to zero.\r\n\tMth::Vector\t\t\t\tmDisplayOffset;\r\n\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvNUM_LODS = 4\r\n\t};\r\n\r\nprotected:\r\n    Nx::CModel*    \t\t \tmp_model;\r\n\tCSkeletonComponent*\t\tmp_skeleton_component;\r\n\tCAnimationComponent*\tmp_animation_component;\r\n\tCSuspendComponent*\t\tmp_suspend_component;\r\n\r\nprotected:\r\n\tfloat\t\t\t\tm_LODdist[vNUM_LODS];\r\n\tint\t\t\t\t\tm_numLODs;\r\n\r\n\t// GJ:  ref objects are used by the cutscene code\r\n\t// for stealing another object's model\r\n\t// (maybe cutscene objects should just have\r\n\t// CRefModelComponent?)\r\npublic:\r\n\tuint32\t\t\t\tGetRefObjectName();\r\n\tbool\t\t\t\tHasRefObject()\r\n\t{\r\n\t\treturn m_hasRefObject;\r\n\t}\r\n\r\nprotected:\r\n\tuint32\t\t\t\tm_refObjectName;\r\n\tbool\t\t\t\tm_hasRefObject;\r\n\t\r\nprivate:\r\n\tbool\t\t\t\tm_isLevelObject;\t// True if it's a level object\t\r\n\t\r\n};\r\n\r\ninline Nx::CModel* CModelComponent::GetModel()\r\n{\r\n    return mp_model;\r\n}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/motioncomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       MotionComponent.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  11/5/2002\r\n//****************************************************************************\r\n\r\n// start autoduck documentation\r\n// @DOC motioncomponent\r\n// @module motioncomponent | None\r\n// @subindex Scripting Database\r\n// @index script | motioncomponent\r\n\r\n#include <gel/components/motioncomponent.h>\r\n#include <gel/components/pedlogiccomponent.h>\r\n#include <gel/components/lockobjcomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n\r\n#include <core/math/slerp.h>\r\n\t\t\t\t\t\t\t\t\t\r\n#include <gel/collision/collision.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <sk/objects/pathob.h>\r\n#include <sk/objects/pathman.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <sk/objects/followob.h>\r\n\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nenum\r\n{\r\n\tUNITS_IPS,\r\n\tUNITS_FPS,\r\n\tUNITS_MPH,\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// This static function is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\nCBaseComponent* CMotionComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CMotionComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCMotionComponent::CMotionComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_MOTION );\r\n\r\n\tmp_pathOb = NULL;\r\n\t\r\n\tmp_path_object_tracker = NULL;\r\n\r\n\tm_point_stick_to_ground = true;\r\n\r\n\tReset();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCMotionComponent::~CMotionComponent()\r\n{\r\n\tif ( mp_pathOb )\r\n\t{\r\n\t\tdelete mp_pathOb;\r\n\t\tmp_pathOb = NULL;\r\n\t}\r\n\r\n\t// Note: No need to unregister from mp_path_object_tracker, because the path tracker\r\n\t// uses smart pointers.\r\n\t\r\n\tif ( mp_slerp )\r\n\t{\r\n\t\tdelete mp_slerp;\r\n\t\tmp_slerp = NULL;\r\n\t}\r\n\t\r\n\tif (mp_follow_ob)\r\n\t{\r\n\t\tdelete mp_follow_ob;\r\n\t\tmp_follow_ob=NULL;\r\n\t}\t\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CMotionComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tint nodeNum = -1;\r\n\tpParams->GetInteger( CRCD(0xe50d6573,\"nodeIndex\"), &nodeNum, Script::NO_ASSERT );\r\n\tm_start_node = m_current_node = nodeNum;\r\n\tOrientToNode(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CMotionComponent::ProcessWait( Script::CScript * pScript )\r\n{\r\n\tswitch (pScript->GetWaitType())\r\n\t{\r\n\t\tcase Script::WAIT_TYPE_OBJECT_MOVE:\r\n\t\t\tif ( !IsMoving() )\r\n\t\t\t{\r\n\t\t\t\tpScript->ClearWait();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase Script::WAIT_TYPE_OBJECT_JUMP_FINISHED:\r\n\t\t\tif ( !(m_movingobj_status & MOVINGOBJ_STATUS_JUMPING) )\r\n\t\t\t{\r\n\t\t\t\tpScript->ClearWait();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase Script::WAIT_TYPE_OBJECT_ROTATE:\r\n\t\t\tif ( !IsRotating() )\r\n\t\t\t{\r\n\t\t\t\tpScript->ClearWait();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase Script::WAIT_TYPE_OBJECT_STOP_FINISHED:\r\n\t\t\tif ( !( m_vel_z > 0.0f ) )\r\n\t\t\t{\r\n\t\t\t\tpScript->ClearWait();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nWait type of %d not supported by CMotionComponent\",pScript->GetScriptInfo(),pScript->GetWaitType()));\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CMotionComponent::Update()\r\n{\r\n\r\n\tm_time = Tmr::FrameLength();\t\r\n\t\r\n\tif ( m_movingobj_status & MOVINGOBJ_STATUS_HOVERING )\r\n\t{\r\n\t\t// Having these functions next to each other here does mean that objects cannot be\r\n\t\t// moving and hovering at the same time, but currently nothing requires that.\r\n\t\tUndoHover();\r\n\t\tApplyHover();\r\n\t}\r\n\r\n\tif ( m_movingobj_status & MOVINGOBJ_STATUS_ROTXYZ )\r\n\t{\r\n\t\tRotUpdate( );\r\n\t}\r\n\t\r\n\tif ( m_movingobj_status & MOVINGOBJ_STATUS_QUAT_ROT )\r\n\t{\r\n\t\tQuatRot( );\r\n\t}\r\n\r\n\tif ( m_movingobj_status & MOVINGOBJ_STATUS_MOVETO )\r\n\t{\r\n\t\tif ( Move( ) )\r\n\t\t{\r\n\t\t\tm_movingobj_status &= ~MOVINGOBJ_STATUS_MOVETO;\r\n\t\t}\r\n\t}\r\n\telse if ( m_movingobj_status & MOVINGOBJ_STATUS_ON_PATH )\r\n\t{\r\n\t\tFollowPath( );\r\n\t}\r\n\telse if ( m_movingobj_status & MOVINGOBJ_STATUS_FOLLOWING_LEADER )\r\n\t{\r\n\t\tDbg_MsgAssert( !(m_movingobj_status & MOVINGOBJ_STATUS_QUAT_ROT), (\"Cannot have object rotating when it is following a leader\"));\r\n\t\tDbg_MsgAssert( !(m_movingobj_status & MOVINGOBJ_STATUS_ROTXYZ), (\"Cannot have object rotating when it is following a leader\"));\r\n\t\tFollowLeader( );\r\n\t}\r\n\r\n\tif ( m_movingobj_status & MOVINGOBJ_STATUS_JUMPING )\r\n\t{\r\n\t\tDoJump();\r\n\t\tGetObject()->m_pos = m_jump_pos;\r\n\t\t// m_pos[Y]=m_jump_y;\r\n\t}\r\n\r\n\r\n\t// TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO\r\n\t// BIT OF A PATCH, as the skater has a motion component\r\n\t// but we don't want to set his display matrix directly here.\r\n\tif (GetObject()->GetID() > 15)\r\n\t{\r\n\t\tGetObject()->SetDisplayMatrix(GetObject()->GetMatrix());\r\n\t}\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMotionComponent::IsMoving()\r\n{   \r\n\treturn ( m_movingobj_status & ( MOVINGOBJ_STATUS_ON_PATH | MOVINGOBJ_STATUS_MOVETO ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMotionComponent::IsRotating()\r\n{\t\r\n\treturn ( m_movingobj_status &  ( MOVINGOBJ_STATUS_ROTXYZ | MOVINGOBJ_STATUS_QUAT_ROT ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void s_get_velocity( Script::CStruct* pParams, float* pVel )\r\n{\r\n\tif ( pParams->GetFloat( NONAME, pVel ) )\r\n\t{\r\n\t\t// default is mph:\r\n\t\tif ( pParams->ContainsFlag( 0xaad7c80f ) ) // 'fps'\r\n\t\t{\r\n\t\t\t*pVel = FEET_TO_INCHES( *pVel );\r\n\t\t}\r\n\t\telse if ( !( pParams->ContainsFlag( 0xa18b8f32 ) ) ) // 'ips'\r\n\t\t{\r\n\t\t\t// miles per hour then...\r\n\t\t\t*pVel = MPH_TO_IPS( *pVel );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void s_get_acceleration( Script::CStruct* pParams, float* pAccel )\r\n{\r\n\tif ( pParams->GetFloat( NONAME, pAccel ) )\r\n\t{\r\n\t\t// default is mphps:\r\n\t\tif ( pParams->ContainsFlag( 0xf414a5ea ) ) // 'fpsps'\r\n\t\t{\r\n\t\t\t*pAccel = FEET_TO_INCHES( *pAccel );\r\n\t\t}\r\n\t\telse if ( !( pParams->ContainsFlag( 0x7644323b ) ) ) // 'ipsps'\r\n\t\t{\r\n\t\t\t// miles per hour per second then...\r\n\t\t\t*pAccel = MPH_TO_IPS( *pAccel );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::UndoHover( void )\r\n{   \r\n\tMth::Vector pos=GetObject()->GetPos();\r\n\tpos[Y]=m_y_before_applying_hover;\r\n\tGetObject()->SetPos(pos);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::ApplyHover( void )\r\n{   \r\n\tuint32 t=Tmr::ElapsedTime(0)%m_hover_period;\r\n\tm_hover_offset=m_hover_amp*sinf(t*2*3.141592653f/m_hover_period);\r\n\tMth::Vector pos=GetObject()->GetPos();\r\n\tm_y_before_applying_hover=pos[Y];\r\n\tpos[Y]+=m_hover_offset;\r\n\tGetObject()->SetPos(pos);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMotionComponent::IsHovering( void )\r\n{\r\n\treturn (m_movingobj_status & MOVINGOBJ_STATUS_HOVERING) && \r\n\t\t\t// If it is doing a Quat rot, then pretend it is not hovering.\r\n\t\t\t// This is so that the rocking buoy in the shipyard is not indicated as\r\n\t\t\t// being hovering, otherwise the replay code will show it as just hovering\r\n\t\t\t// up and down. The replay code optimizes hovering objects by not recording their\r\n\t\t\t// precise positions and orientations every frame. We need that for the buoy though.\r\n\t\t   !(m_movingobj_status &  (MOVINGOBJ_STATUS_QUAT_ROT));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::GetHoverOrgPos( Mth::Vector* p_orgPos )\r\n{\r\n\tDbg_MsgAssert(p_orgPos,(\"NULL p_orgPos\"));\r\n\tMth::Vector pos=GetObject()->GetPos();\r\n\tp_orgPos->Set(pos[X],m_y_before_applying_hover,pos[Z]);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent::EMemberFunctionResult CMotionComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | Obj_IsMoving | true if moving\r\n\t\tcase 0x21accf0d: \t\t// Obj_IsMoving\r\n\t\t\treturn ( IsMoving() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE );\r\n\t\t\tbreak;\r\n\t\r\n        // @script | Obj_IsRotating | true if rotating\r\n\t\tcase 0x7bc461ae: \t\t// Obj_IsRotating\r\n\t\t\treturn ( IsRotating() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_StorePos | stores the current position\r\n\t\tcase 0x8e52abea: \t\t// Obj_StorePos\r\n\t\t\tm_stored_pos = GetObject()->GetPos();\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_StoreNode | stores the next waypoint in the path\r\n\t\tcase 0xc8cc6820: \t\t// Obj_StoreNode\r\n\t\t\tDbg_MsgAssert( GetPathOb(),( \"\\n%s\\nObject trying to store waypoint when not on a path.\", pScript->GetScriptInfo( ) ));\r\n\t\t\tm_stored_node = GetPathOb()->m_node_to;\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_StopMoving |\r\n\t\tcase 0x68e1f022: \t\t// Obj_StopMoving\r\n\t\t\tm_movingobj_status &= ~( MOVINGOBJ_STATUS_MOVETO | MOVINGOBJ_STATUS_ON_PATH );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_StopRotating |\r\n\t\tcase 0xdfbe3db3: \t\t// Obj_StopRotating\r\n\t\t\tm_movingobj_status &= ~( MOVINGOBJ_STATUS_ROTX | MOVINGOBJ_STATUS_ROTY |\r\n\t\t\t\tMOVINGOBJ_STATUS_ROTZ | MOVINGOBJ_STATUS_QUAT_ROT | MOVINGOBJ_STATUS_LOOKAT );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_SetPathVelocity | \r\n        // @uparm 1.0 | velocity\r\n        // @flag mph | default units\r\n        // @flag ips |\r\n        // @flag fps | \r\n\t\tcase 0xfb603ea9:\t\t// Obj_SetPathVelocity\r\n\t\t\ts_get_velocity( pParams, &m_max_vel );\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | Obj_SetPathMinStopVel | Speed at which friction\r\n        // overcomes momentum and the object stops. If left at zero,\r\n        // the object will take forever to stop... A good value for\r\n        // a car is 1 or 2 mph. Pedestrians are more 'sticky': make\r\n        // it 3 or 4 mph for them. Only used if you call Obj_StopAlongPath\r\n        // @uparm 1.0 | velocity\r\n        // @flag mph | default units\r\n        // @flag ips |\r\n        // @flag fps | \r\n\t\tcase 0x2ca63cdf:\t\t// Obj_SetPathMinStopVel\r\n\t\t\ts_get_velocity( pParams, &m_min_stop_vel );\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | Obj_SetPathAcceleration | used for when the object\r\n        // is stopped, and needs to get up to speed (set by Obj_SetVelocity).\r\n        // @uparm 1.0 | acceleration\r\n        // @flag mphps | default units\r\n        // @flag ipsps |\r\n        // @flag fpsps | \r\n\t\tcase 0xd6697ad0:\t\t// Obj_SetPathAcceleration\r\n\t\t\ts_get_acceleration( pParams, &m_acceleration );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_SetPathDeceleration | used if the velocity is\r\n        // decreased while the object is traveling, to slow down to the new speed\r\n        // @uparm 1.0 | acceleration\r\n        // @flag mphps | default units\r\n        // @flag ipsps |\r\n        // @flag fpsps | \t\t\r\n\t\tcase 0xa67fc783:\t\t// Obj_SetPathDeceleration\r\n\t\t\ts_get_acceleration( pParams, &m_deceleration );\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | Obj_Rotate | rotate object\r\n        // @parmopt float | time | 0.0 | in seconds - if not included, instant rotation\r\n        // @parmopt vector | relative | (0, 0, 0) | rotate relative to the object\r\n        // @parmopt vector | absolute | (0, 0, 0) | rotate oriented along world axes\r\n        // @flag FLAG_MAX_COORDS | with this flag, coordinates will be converted to \r\n        // correspond to the axes in Max ( Z up, -Y forward, and X right. )\r\n\t\tcase 0x5cf1b7d4:  // \"Obj_Rotate\"\r\n\t\t\tQuatRot_Init( pParams );\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | Obj_RotX | rotate about x axis\r\n        // @parmopt float | angle | | If not specified, object will rotate forever\r\n        // @parmopt float | speed | | Speed of rotation in degrees per second. <nl>\r\n        // Required unless deltaROT is ZERO\r\n        // @parmopt float | acceleration | | Acceleration in degrees per\r\n        // second per second.  If not set, velocity is set instantly\r\n        // @parmopt float | deceleration | | If specified, velocity is set instantly.\r\n        // Deceleration in degrees per\r\n        // second per second.  Target stops rotating when it reaches the target\r\n        // angle specified, or when speed reaches ZERO\r\n        // @flag FLAG_MAX_COORDS | With this flag, coordinates will be converted to \r\n        // correspond to the axes in Max ( Z up, -Y forward, and X right. )\r\n\t\tcase 0x0b231a9d:  // \"Obj_RotX\"\r\n\t\t\tRotAxis_Init( pParams, pScript, X );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_RotY | rotate about Y axis\r\n        // @parmopt float | angle | | If not specified, object will rotate forever\r\n        // @parmopt float | speed | | Speed of rotation in degrees per second. <nl>\r\n        // Required unless deltaROT is ZERO\r\n        // @parmopt float | acceleration | | Acceleration in degrees per\r\n        // second per second.  If not set, velocity is set instantly\r\n        // @parmopt float | deceleration | | If specified, velocity is set instantly.\r\n        // Deceleration in degrees per\r\n        // second per second.  Target stops rotating when it reaches the target\r\n        // angle specified, or when speed reaches ZERO\r\n        // @flag FLAG_MAX_COORDS | With this flag, coordinates will be converted to \r\n        // correspond to the axes in Max ( Z up, -Y forward, and X right. )\r\n\t\tcase 0x7c242a0b:  // \"Obj_RotY\"\r\n\t\t\tRotAxis_Init( pParams, pScript, Y );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_RotZ | rotate about z axis\r\n        // @parmopt float | angle | | If not specified, object will rotate forever\r\n        // @parmopt float | speed | | Speed of rotation in degrees per second. <nl>\r\n        // Required unless deltaROT is ZERO\r\n        // @parmopt float | acceleration | | Acceleration in degrees per\r\n        // second per second.  If not set, velocity is set instantly\r\n        // @parmopt float | deceleration | | If specified, velocity is set instantly.\r\n        // Deceleration in degrees per\r\n        // second per second.  Target stops rotating when it reaches the target\r\n        // angle specified, or when speed reaches ZERO\r\n        // @flag FLAG_MAX_COORDS | With this flag, coordinates will be converted to \r\n        // correspond to the axes in Max ( Z up, -Y forward, and X right. )\r\n\t\tcase 0xe52d7bb1:  // \"Obj_RotZ\"\r\n\t\t\tRotAxis_Init( pParams, pScript, Z );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_PathHeading | Defaults to on. Sets the\r\n        // heading of the object in the direction of the path\r\n        // @flag off | use to set off\r\n\t\tcase 0xd8f4bc32:  // \"Obj_PathHeading\"\r\n\t\t\tif ( pParams->ContainsFlag( 0xd443a2bc ) ) // \"off\"\r\n\t\t\t{\r\n\t\t\t\tm_movingobj_flags |= MOVINGOBJ_FLAG_INDEPENDENT_HEADING;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_movingobj_flags &= ~MOVINGOBJ_FLAG_INDEPENDENT_HEADING;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n        // @Script | Obj_SetConstantHeight | sets object height to whatever\r\n        // height the object is currently at\r\n        // @flag off | turn it off (default is on)\r\n\t\tcase 0xaa3cb476:  // \"Obj_SetConstantHeight\"\r\n\t\t\tif ( pParams->ContainsFlag( 0xd443a2bc ) ) // \"off\"\r\n\t\t\t{\r\n\t\t\t\tm_movingobj_flags &= ~MOVINGOBJ_FLAG_CONSTANT_HEIGHT;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_movingobj_flags |= MOVINGOBJ_FLAG_CONSTANT_HEIGHT;\r\n\t\t\t\tpParams->GetFloat( NONAME, &GetObject()->m_pos[ Y ] );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_GetNextObjOnPath | Searches forward along the path the object is on for a max\r\n\t\t// of Range feet, and if another object on the path is encountered, its name is put into a parameter\r\n\t\t// called Ob. If no object is found, no Ob parameter will be created, and if it existed before, it\r\n\t\t// will be removed.\r\n        // @parmopt float | Range | 0.0 | Distance to search, in feet\r\n\t\tcase 0xb75589ce: // Obj_GetNextObjOnPath\t\r\n\t\t{\t\r\n\t\t\tfloat range=100.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0x6c78a5b6,\"Range\"),&range);\r\n\t\t\trange*=12.0f;\r\n\t\t\t\r\n\t\t\tpScript->GetParams()->RemoveComponent( CRCD(0xffff9a1c,\"Ob\") );\r\n\t\t\t\r\n\t\t\tCCompositeObject* p_closest_ob = GetNextObjectOnPath( range );\r\n\r\n\t\t\tif ( p_closest_ob )\r\n\t\t\t\tpScript->GetParams()->AddChecksum( CRCD(0xffff9a1c,\"Ob\"), p_closest_ob->GetID() );\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | Obj_GetRandomLink | Chooses a random node that the object's current node is \r\n\t\t// linked to, and puts its link number into a parameter called Link.\r\n\t\t// If the object's current node is not linked to anything, no Link parameter will be created.\r\n\t\tcase 0x6866312f: // Obj_GetRandomLink\r\n\t\t{\r\n\t\t\tuint32 num_links = SkateScript::GetNumLinks( m_current_node );\r\n\t\t\tif (num_links)\r\n\t\t\t{\r\n\t\t\t\t// Note: The +1 is because we're using the convention of numbering the\r\n\t\t\t\t// links from 1 to n rather than 0 to n-1\r\n\t\t\t\tpScript->GetParams()->AddInteger(CRCD(0xc953660e,\"Link\"),Mth::Rnd(num_links)+1);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        // @script | Obj_RandomPathMode | Causes Obj_FollowPath commands to\r\n        // pick random links as moving objects traverse paths\r\n        // @flag off | use to turn off - default is on\r\n\t\tcase 0x434ea1fb:\t// Obj_RandomPathMode\r\n\t\t\tif ( pParams->ContainsFlag( 0xd443a2bc ) ) // \"off\"\r\n\t\t\t{\r\n\t\t\t\tm_movingobj_flags &= ~MOVINGOBJ_FLAG_RANDOM_PATH_MODE;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_movingobj_flags |= MOVINGOBJ_FLAG_RANDOM_PATH_MODE;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_SetPathTurnDist | The distance from a waypoint \r\n        // at which the object starts turning\r\n        // @uparm 1.0 | distance in feet\r\n        // @flag inches | use units of inches for distance\r\n\t\tcase 0x76003d82: // \"Obj_SetPathTurnDist\"\r\n\t\t{\r\n\t\t\tfloat enterTurnDist;\r\n\t\t\tif ( pParams->GetFloat( NONAME, &enterTurnDist ) )\r\n\t\t\t{\r\n\t\t\t\tif ( !pParams->ContainsFlag( 0xf915b4f3 ) ) // \"inches\"\r\n\t\t\t\t{\r\n\t\t\t\t\tenterTurnDist = FEET_TO_INCHES( enterTurnDist );\r\n\t\t\t\t}\r\n\t\t\t\tEnsurePathobExists( GetObject() );\r\n\t\t\t\tGetPathOb()->m_enter_turn_dist = enterTurnDist;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\r\n        // @script | Obj_FollowPath | Must also have Obj_SetVelocity set.\r\n        // If the node has no links, the object will move to the node and\r\n        // stop. Linked in a circle: object follows loop until stopped.\r\n        // Linked to a finite path: walks to the end of the path. Returns\r\n        // true for Obj_IsMoving until path complete. If used in conjunction\r\n        // with Obj_MoveTo functions, will turn moveto function off, and\r\n        // vice versa\r\n        // @parm name | Name | name of node at beginning of path\r\n\t\tcase 0xbfb0031d:  // \"Obj_FollowPath\"\r\n\t\t\tm_movingobj_flags &= ~MOVINGOBJ_FLAG_STOP_ALONG_PATH;\r\n\t\t\tFollowPath_Init( pParams );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_LookAtNode | \r\n        // @parm name | Name | the name of the node you want to look at\r\n        // @parmopt name | lockAxis | | can lock any two axes (LOCK_X, LOCK_Y, LOCK_Z)\r\n        // @parmopt float | time | vel/acceleration | in seconds\r\n        // @parmopt float | speed | 360  | angular velocity in degrees per second\r\n        // @parmopt float | acceleration | 0 | angular acceleration in degrees per second\r\n        // per second \r\n        // @flag FLAG_MAX_COORDS | With this flag, coordinates will be converted to \r\n        // correspond to the axes in Max ( Z up, -Y forward, and X right. )\r\n\t\tcase 0x103bd253:  // \"Obj_LookAtNode\"\r\n\t\t\tLookAtNode_Init( pParams, pScript );\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | Obj_LookAtNodeLinked | looks at the next node\r\n        // @parmopt int | linkNum | 1 | The link to look at.\r\n\t\tcase 0x6419ceff: // \"Obj_LookAtNodeLinked\"\r\n\t\t\tLookAtNodeLinked_Init( pParams, pScript );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_LookAtNodeStored | looks at stored node\r\n        // @parmopt name | lockAxis | | can lock any two axes (LOCK_X, LOCK_Y, LOCK_Z)\r\n        // @parmopt float | time | vel/acceleration | in seconds\r\n        // @parmopt float | speed | 360  | angular velocity in degrees per second\r\n        // @parmopt float | acceleration | 0 | angular acceleration in degrees per second\r\n        // per second \r\n\t\t// @parmopt float | AngleThreshold | 0 | If the object is already looking within this\r\n\t\t// many degrees of the correct direction, it will not bother turning.\r\n        // @flag FLAG_MAX_COORDS | With this flag, coordinates will be converted to \r\n        // correspond to the axes in Max ( Z up, -Y forward, and X right. )\r\n\t\tcase 0xa5a2d218: // \"Obj_LookAtNodeStored\"\r\n\t\t{\r\n\t\t\tMth::Vector lookAtPos;\r\n\t\t\tSkateScript::GetPosition( m_stored_node, &lookAtPos );\r\n\t\t\tLookAt_Init( pParams, lookAtPos );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | Obj_LookAtPos |\r\n        // @uparm (0, 0, 0) | position vector\r\n        // @parmopt name | lockAxis | | can lock any two axes (LOCK_X, LOCK_Y, LOCK_Z)\r\n        // @parmopt float | time | vel/acceleration | in seconds\r\n        // @parmopt float | speed | 360  | angular velocity in degrees per second\r\n        // @parmopt float | acceleration | 0 | angular acceleration in degrees per second\r\n        // per second\r\n\t\tcase 0x74c30242:  // \"Obj_LookAtPos\"\r\n\t\t\tLookAtPos_Init( pParams, true );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_LookAtPosStored | look at stored pos\r\n        // @parmopt name | lockAxis | | can lock any two axes (LOCK_X, LOCK_Y, LOCK_Z)\r\n        // @parmopt float | time | vel/acceleration | in seconds\r\n        // @parmopt float | speed | 360  | angular velocity in degrees per second\r\n        // @parmopt float | acceleration | 0 | angular acceleration in degrees per second\r\n        // per second\r\n\t\t// @parmopt float | AngleThreshold | 0 | If the object is already looking within this\r\n\t\t// many degrees of the correct direction, it will not bother turning.\r\n\t\tcase 0xe8d121cb: // \"Obj_LookAtPosStored\"\r\n\t\t\tLookAt_Init( pParams, m_stored_pos );\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | Obj_LookAtRelPos | look at position relative to object position\r\n        // @uparm (0, 0, 0) | relative position vector\r\n        // @parmopt name | lockAxis | | can lock any two axes (LOCK_X, LOCK_Y, LOCK_Z)\r\n        // @parmopt float | time | vel/acceleration | in seconds\r\n        // @parmopt float | speed | 360  | angular velocity in degrees per second\r\n        // @parmopt float | acceleration | 0 | angular acceleration in degrees per second\r\n        // per second\r\n        case 0x33df698f:  // \"Obj_LookAtRelPos\"\r\n\t\t\tLookAtPos_Init( pParams, false );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_StopAlongPath | accurately stop and object\r\n        // @uparm 1.0 | distance in feet.  Note: doesn't use deceleration\r\n        // set in Obj_SetDeceleration\r\n\t\tcase 0xfe71453f:  // \"Obj_StopAlongPath\"\r\n\t\t\tm_stop_dist = 0;\r\n\t\t\tm_stop_dist_traveled = 0;\r\n\t\t\tif ( !m_min_stop_vel )\r\n\t\t\t{\r\n\t\t\t\tm_min_stop_vel = 15;\r\n\t\t\t}\r\n\t\t\tpParams->GetFloat( NONAME, &m_stop_dist );\r\n\t\t\tif ( !pParams->ContainsFlag( 0xf915b4f3 ) ) // inches\r\n\t\t\t{\r\n\t\t\t\tm_stop_dist = FEET_TO_INCHES( m_stop_dist );\r\n\t\t\t\tm_vel_z_start = m_vel_z;\r\n\t\t\t}\r\n\t\t\tif ( !m_stop_dist )\r\n\t\t\t{\r\n\t\t\t\tm_vel_z = 0;\r\n\t\t\t}\r\n\t\t\tm_movingobj_flags |= MOVINGOBJ_FLAG_STOP_ALONG_PATH;\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | Obj_StartAlongPath | Only needs to be used if you've\r\n        // stopped an object along a path, to restart the object moving. \r\n\t\tcase 0xbd6c6807:  // \"Obj_StartAlongPath\"\r\n\t\t\tm_movingobj_flags &= ~MOVINGOBJ_FLAG_STOP_ALONG_PATH;\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | Obj_FollowPathLinked | Will cause the object to\r\n        // follow the path that it is linked to.\r\n        // When calling Obj_FollowPathLinked, you can add an\r\n        // optional parameter: <nl>\r\n        // originalNode \r\n        // to follow a linked path to the node that created the object. <nl>\r\n        // If random mode is on, a random link from the original\r\n        // node will be used\r\n        // @flag originalNode | follow a linked path to the node that \r\n        // created the object\r\n\t\tcase 0x0da2d86d:  // \"Obj_FollowPathLinked\"\r\n\t\t\tm_movingobj_flags &= ~MOVINGOBJ_FLAG_STOP_ALONG_PATH;\r\n\t\t\tFollowPathLinked_Init( pParams, pScript );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_FollowPathStored | Follow the path from current\r\n        // position to the position of the waypoint last stored\r\n        // in the script call to Obj_StoreNode (when a pedestrian, for example, has to jump\r\n        // out of the way of the player, he stores his current position and the current node\r\n        // that he's heading for... then he walks back to his position, and finally ends up\r\n        // heading to the waypoint he was heading for before he left the path to jump out of the way).\r\n\t\tcase 0xcc19c48a: // \"Obj_FollowPathStored\"\r\n\t\t\tFollowStoredPath_Init( pParams );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_SetGroundOffset | \r\n\t\tcase 0xbf9fffe5: // \"Obj_SetGroundOffset\"\r\n\t\t\tDbg_Message( \"Obj_SetGroundOffset is obsolete!\" );\r\n            break;\r\n\t\t\r\n        // @script | Obj_MoveToPosStored | move to world position stored\r\n        // using Obj_StorePos\r\n        // @parmopt float | time | | default unit is milliseconds\r\n        // @parmopt float | speed | | used instead of time and acceleration\r\n        // @parmopt float | acceleration | | change in speed per second\r\n\t\tcase 0x8b669799: // \"Obj_MoveToPosStored\"\r\n\t\t\tMove_Init( pParams, pScript, m_stored_pos );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_MoveForward | Moves a distance in the direction the object is facing.\r\n        // @parmopt float | dist | | Distance to move, in inches.\r\n        // @parmopt float | time | | default unit is milliseconds\r\n        // @parmopt float | speed | | used instead of time and acceleration\r\n        // @parmopt float | acceleration | | change in speed per second\r\n\t\tcase 0xf389285d: // Obj_MoveForward\r\n\t\t{\r\n\t\t\tfloat dist=0.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0x7e832f08,\"Dist\"),&dist);\r\n\t\t\tMove_Init( pParams, pScript, GetObject()->GetPos() + GetObject()->m_matrix[Z] * dist );\t \r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | Obj_MoveLeft | Moves a distance at 90 degrees to the direction the object is facing.\r\n        // @parmopt float | dist | | Distance to move, in inches.\r\n        // @parmopt float | time | | default unit is milliseconds\r\n        // @parmopt float | speed | | used instead of time and acceleration\r\n        // @parmopt float | acceleration | | change in speed per second\r\n\t\tcase 0x5ce058fd: // Obj_MoveLeft\r\n\t\t{\r\n\t\t\tfloat dist=0.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0x7e832f08,\"Dist\"),&dist);\r\n\t\t\tMove_Init( pParams, pScript, GetObject()->GetPos() + GetObject()->m_matrix[X] * dist );\t \r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        // @script | Obj_MoveToNode | move to any node by node name\r\n        // @parm name | name | node name\r\n        // @parmopt float | time | | default unit is milliseconds\r\n        // @parmopt float | speed | | used instead of time and acceleration\r\n        // @flag mph | time in mph\r\n        // @flag IPS | time in IPS\r\n        // @flag fps | time in fps\r\n        // @parmopt float | acceleration | | change in speed per second\r\n\t\tcase 0x8819dd8b:  // \"Obj_MoveToNode\"\r\n\t\t\tMoveToNode_Init( pParams, pScript );\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | Obj_MoveToPos | moves to the world position specified\r\n        // by the vector\r\n        // @uparm (0, 0, 0) | position vector \r\n        // @parmopt float | time | | default unit is milliseconds\r\n        // @parmopt float | speed | | used instead of time and acceleration\r\n        // @parmopt float | acceleration | | change in speed per second\r\n\t\tcase 0x84ec6600:  // \"Obj_MoveToPos\"\r\n\t\t\tMoveToPos_Init( pParams, pScript, true );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_MoveToRelPos | moves to a position relative to the object\r\n        // @uparm (0, 0, 0) | position vector \r\n        // @parmopt float | time | | default unit is milliseconds\r\n        // @parmopt float | speed | | used instead of time and acceleration\r\n        // @parmopt float | acceleration | | change in speed per second\r\n\t\tcase 0xea81a32b:  // \"Obj_MoveToRelPos\"\r\n\t\t\tMoveToPos_Init( pParams, pScript, false );\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | Obj_MoveToLink | Moves to the 1st node that this object is linked to \r\n        // @parmopt float | time | | default unit is milliseconds\r\n        // @parmopt float | speed | | used instead of time and acceleration\r\n        // @parmopt float | acceleration | | change in speed per second\r\n\t\t// @parm int | LinkNum | link number\r\n        case 0x3bcaac3f:  // \"Obj_MoveToLink\"\r\n\t\t\tMoveToLink_Init( pParams, pScript );\r\n\t\t\tbreak;\r\n\t\r\n        // @script | Obj_StickToGround | \r\n        // @flag on | turn on (optional - default value is on)\r\n        // @flag off | turn off (default is on)\r\n        // @parm float | distAbove | distance above the object to check\r\n        // for collision\r\n        // @parm float | distBelow | distance below the object to check\r\n        // for collision\r\n\t\tcase 0xc5eca638:  // \"Obj_StickToGround\"\r\n\t\t\tpParams->GetFloat( 0xa8a5a3c7, &m_col_dist_above ); // \"distAbove\"\r\n\t\t\tpParams->GetFloat( 0x182d87a7, &m_col_dist_below ); // \"distBelow\"\r\n\t\t\tif ( pParams->ContainsFlag( 0xd443a2bc ) ) // \"off\"\r\n\t\t\t{\r\n\t\t\t\tm_movingobj_flags &= ~MOVINGOBJ_FLAG_STICK_TO_GROUND;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_movingobj_flags |= MOVINGOBJ_FLAG_STICK_TO_GROUND;\r\n\t\t\t\tif ( ( m_col_dist_above == 0 ) && ( m_col_dist_below == 0 ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Message( \"\\n%s\\nTrying to stick to the ground, distAbove and distBelow are zero!!!\", pScript->GetScriptInfo() );\r\n\t\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\r\n\t\t\t\tStickToGround();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_WaitJumpFinished | Waits for jump to finish, which is when the object \r\n\t\t// has fallen to the same height it was at when the Obj_Jump command was issued.\r\n\t\tcase 0x1e094b84:  // Obj_WaitJumpFinished\r\n\t\t{\r\n\t\t\tpScript->SetWait(Script::WAIT_TYPE_OBJECT_JUMP_FINISHED,this);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | Obj_WaitRotate | wait for rotation to complete\r\n\t\tcase 0xbdc4c878:  // Obj_WaitRotate\r\n\t\t\tpScript->SetWait(Script::WAIT_TYPE_OBJECT_ROTATE,this);\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_WaitMove | use to wait for move to complete\r\n\t\tcase 0xdbfdd02f:  // Obj_WaitMove\r\n\t\t\tpScript->SetWait(Script::WAIT_TYPE_OBJECT_MOVE,this);\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | Obj_WaitStop | use to wait for the object to come to a complete stop\r\n\t\tcase CRCC( 0x8d95f1e1, \"Obj_WaitStop\" ):\r\n\t\t\tpScript->SetWait(Script::WAIT_TYPE_OBJECT_STOP_FINISHED,this);\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | Obj_SkipToRestart | skips the object to a restart point\r\n\t\tcase 0x3407ad3d: // Obj_SkipToRestart\r\n\t\t{\r\n\t\t\tuint32 node_name=0;\r\n\t\t\tMth::Vector node_pos;\r\n\t\t\t\r\n\t\t\tpParams->GetChecksum(NONAME,&node_name);\r\n\t\t\tint node_index = SkateScript::FindNamedNode(node_name);\r\n\t\t\tScript::CStruct* p_node_data = SkateScript::GetNode(node_index);\r\n\t\t\t\r\n\t\t\tSkateScript::GetPosition(p_node_data, &node_pos);\r\n\t\t\tGetObject()->SetPos( node_pos );\r\n\t\t\tthis->OrientToNode(p_node_data);\r\n\t\t\r\n\t\t\t// refresh the model with the new pos/orientation\r\n\t\t\tObj::CModelComponent* pModelComponent = (Obj::CModelComponent*)GetModelComponentFromObject( GetObject() );\r\n\t\t\tpModelComponent->Update();\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0xe606eba2: // Obj_Hover\r\n\t\t{\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0xd443a2bc,\"Off\")))\r\n\t\t\t{\r\n\t\t\t\tUndoHover();\r\n\t\t\t\tm_movingobj_status &= ~MOVINGOBJ_STATUS_HOVERING;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_hover_offset=0;\r\n\t\t\t\t\r\n\t\t\t\tpParams->GetFloat(CRCD(0xc9fde32c,\"Amp\"),&m_hover_amp);\r\n\t\t\t\tfloat f=1.0f;\r\n\t\t\t\tpParams->GetFloat(CRCD(0xa80bea4a,\"Freq\"),&f);\r\n\t\t\t\tm_hover_period=(int)(1000.0f/f);\r\n\t\t\t\t// Add 10% of randomness so that groups of hovering things slowly\r\n\t\t\t\t// go out of phase with each other rather than hovering in unison.\r\n\t\t\t\tint random_number = Mth::Rnd(m_hover_period*20/10);\r\n\t\t\t\tm_hover_period += random_number-m_hover_period/10;\r\n\r\n//\t\t\t\tprintf( \"hover period = %d random number = %d\\n\", m_hover_period, random_number );\r\n\r\n\t\t\t\tif ( m_hover_period <= 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// GJ:  make sure that hover period is a valid value\r\n\t\t\t\t\tDbg_MsgAssert( false, ( \"Potential divide-by-zero m_hover_period=%d at %s...  tell Mick!\", m_hover_period, pScript->GetScriptInfo() ) );\r\n\t\t\t\t\tm_hover_period = 1;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tm_y_before_applying_hover=GetObject()->GetPos()[Y];\r\n\t\t\t\tm_movingobj_status |= MOVINGOBJ_STATUS_HOVERING;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        // @script | Obj_GetSpeed | Gets the object's current speed and puts it into a parameter called speed.\r\n\t\t// By default the units will be miles per hour.\r\n\t\t// @flag ips | Make the speed value be in inches per second\r\n\t\t// @flag fps | Make the speed value be in feet per second\r\n\t\tcase 0xe76d73d2: // Obj_GetSpeed \r\n\t\t{\r\n\t\t\tfloat speed=0.0f;\r\n\t\t\tif (m_movingobj_status & MOVINGOBJ_STATUS_MOVETO)\r\n\t\t\t{\r\n\t\t\t\tspeed=m_moveto_speed;\r\n\t\t\t}\r\n\t\t\telse if ( GetLockObjComponentFromObject(GetObject()) && GetLockObjComponentFromObject(GetObject())->IsLockEnabled() )\r\n\t\t\t{\r\n\t\t\t\tMth::Vector d=GetObject()->m_pos - GetObject()->m_old_pos;\r\n\t\t\t\tfloat m_time = Tmr::FrameLength();\t \t// dodgy\r\n\t\t\t\tif (m_time)\r\n\t\t\t\t{\r\n\t\t\t\t\tspeed=d.Length()/m_time;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tspeed=GetObject()->m_vel.Length();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// speed is now in inches per sec.\r\n\t\t\t\r\n\t\t\tif ( pParams->ContainsFlag( 0xa18b8f32 ) ) // \"ips\"\r\n\t\t\t{\r\n\t\t\t\t// Nothing to do.\r\n\t\t\t}\r\n\t\t\telse if ( pParams->ContainsFlag( 0xaad7c80f ) ) // \"fps\"\r\n\t\t\t{\r\n\t\t\t\t// Convert to feet per second\r\n\t\t\t\tspeed/=FEET_TO_INCHES(1.0f);\r\n\t\t\t} \r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Convert to miles per hour\r\n\t\t\t\tspeed/=MPH_TO_INCHES_PER_SECOND(1.0f);\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tpScript->GetParams()->AddFloat(\"Speed\",speed);\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\r\n\r\n        // @script | Obj_Jump | Makes the object jump.\r\n\t\t// @parmopt float | Speed | 150.0 | The upwards speed of the jump\r\n\t\t// @parmopt float | Gravity | -360.0 | The gravity applied to the jump\r\n\t\t// @parmopt vector | heading | | use this heading as jump direction rather than\r\n\t\t// jumping straight up\r\n\t\t// @parmopt float | col_dist_above | 6 | distance used for collision checks above the object\r\n\t\t// @parmopt float | col_dist_below | 6 | distance used for collision checks below the object\r\n\t\t// @flag use_current_heading | use the object's current Z vector as jump direction\r\n\t\tcase 0x1ae46261:  // Obj_Jump\r\n\t\t{\r\n\t\t\tm_jump_speed = 150.0f;\r\n\t\t\tpParams->GetFloat( CRCD(0xf0d90109,\"Speed\"), &m_jump_speed );\r\n\t\t\tm_jump_original_speed = m_jump_speed;\r\n\r\n\t\t\tm_jump_gravity = -360.0f;\r\n\t\t\tpParams->GetFloat( CRCD(0xa5e2da58,\"Gravity\"), &m_jump_gravity );\r\n\r\n\t\t\tm_jump_start_pos = GetObject()->m_pos;\r\n\r\n\t\t\tm_jump_col_dist_above = 6.0f;\r\n\t\t\tpParams->GetFloat( CRCD( 0xecc2c699, \"col_dist_above\" ), &m_jump_col_dist_above, Script::NO_ASSERT );\r\n\t\t\tm_jump_col_dist_below = 6.0f;\r\n\t\t\tpParams->GetFloat( CRCD( 0x5c4ae2f9, \"col_dist_below\" ), &m_jump_col_dist_below, Script::NO_ASSERT );\r\n\t\t\t\r\n\t\t\tif ( pParams->GetVector( CRCD( 0xfd4bc03e, \"heading\" ), &m_jump_heading, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tm_jump_use_heading = true;\r\n\t\t\t\tm_jump_speed *= m_jump_heading[Y];\r\n\t\t\t\tm_jump_heading[Y] = 0.0f;\r\n\t\t\t}\r\n\t\t\telse if ( pParams->ContainsFlag( CRCD( 0xfecffe49, \"use_current_heading\" ) ) )\r\n\t\t\t{\r\n\t\t\t\t// m_jump_heading = Mth::Vector(0, 0, 1);\r\n\t\t\t\tm_jump_heading = GetObject()->GetDisplayMatrix()[Z];\r\n\t\t\t\tm_jump_use_heading = true;\r\n\t\t\t\tm_jump_speed *= m_jump_heading[Y];\r\n\t\t\t\tm_jump_heading[Y] = 0.0f;\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\t\t\t\t\r\n\t\t\t\tm_jump_use_heading = false;\r\n\t\t\t}\r\n\r\n\t\t\tm_jump_use_land_height = false;\r\n\t\t\tif ( pParams->GetFloat( CRCD( 0xa1810c27, \"land_height\" ), &m_jump_land_height, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tm_jump_use_land_height = true;\r\n\t\t\t}\r\n\r\n\t\t\tm_movingobj_status |= MOVINGOBJ_STATUS_JUMPING;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        // @script | Obj_FollowLeader | Makes the object follow a fixed distance behind another object.\r\n        // @parm name | Name | Name of the object to follow\r\n        // @parmopt float | Distance | 100 | Distance behind the leader in inches\r\n\t\t// @flag OrientY | Tilt the object to be at right angles to the path direction\r\n\t\t// @flag Off | Switch off following\r\n\t\t// @flag LeaveYUnaffected | The y coordinate of the object will be left unaffected, so\r\n\t\t// that the object can be clamped to the ground and not follow the skater into the air\r\n\t\t// for example.\r\n\t\tcase 0x2fad370d: // Obj_FollowLeader\r\n\t\t\tFollowLeader_Init( pParams );\r\n\t\t\tbreak;\r\n\r\n\r\n\t\t\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\treturn CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::EnsurePathobExists( CCompositeObject* pCompositeObject )\r\n{\r\n\tif ( !mp_pathOb )\r\n\t{\r\n\t\tmp_pathOb = new CPathOb( pCompositeObject );\r\n\t\tDbg_MsgAssert( mp_pathOb,( \"Couldn't allocate pathob.\" ));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPathOb* CMotionComponent::GetPathOb()\r\n{\r\n\treturn mp_pathOb;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Added by Ken. If the object is following a path, this will return the node\r\n// index of the node it is heading towards. Returns -1 otherwise.\r\nint CMotionComponent::GetDestinationPathNode()\r\n{\t\r\n\tif ( !(m_movingobj_status & MOVINGOBJ_STATUS_ON_PATH) )\r\n\t{\r\n\t\treturn -1;\r\n\t}\t\r\n\r\n\tif ( !mp_pathOb )\r\n\t{\r\n\t\treturn -1;\r\n\t}\t\r\n\t//Dbg_MsgAssert(mp_pathOb,(\"NULL GetPathOb() ?\"));\r\n\treturn mp_pathOb->m_node_to;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CMotionComponent::GetPreviousPathNode()\r\n{\t\r\n\tif ( !(m_movingobj_status & MOVINGOBJ_STATUS_ON_PATH) )\r\n\t{\r\n\t\treturn -1;\r\n\t}\t\r\n\r\n\tif ( !mp_pathOb )\r\n\t{\r\n\t\treturn -1;\r\n\t}\t\r\n\t//Dbg_MsgAssert(mp_pathOb,(\"NULL GetPathOb() ?\"));\r\n\treturn mp_pathOb->m_node_from;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CMotionComponent::Reset()\r\n{\r\n\tm_turn_ang_target.Set( );\r\n\tm_cur_turn_ang.Set( );\r\n\tm_turn_speed_target.Set( );\r\n\tm_turn_speed.Set( );\r\n\tm_delta_turn_speed.Set( );\r\n\tm_angular_friction.Set( );\r\n\tm_orig_pos.Set( );\r\n\t\r\n\tm_moveto_pos.Set( );\r\n\tm_moveto_dist = 0.0f;\r\n\tm_moveto_dist_traveled = 0.0f;\r\n\tm_moveto_speed = 0.0f;\r\n\tm_moveto_speed_target = 0.0f;\r\n\tm_moveto_acceleration = 0.0f;\r\n\t\r\n\tm_acceleration = 0.0f;\r\n\tm_deceleration = 0.0f;\r\n\tm_max_vel = 0.0f;\r\n\tm_vel_z = 0.0f;\r\n\tm_stop_dist = 0.0f;\r\n\tm_stop_dist_traveled = 0.0f;\r\n\tm_vel_z_start = 0.0f;\r\n\tm_min_stop_vel = 0.0f;\r\n\t\r\n\tm_rot_time_target = 0.0f;\r\n\tm_rot_time = 0.0f;\r\n\t\r\n\t// don't think this is dangerous...\r\n\tm_movingobj_status = 0;\r\n\tm_movingobj_flags = 0;\r\n\t\r\n\t// Reset the Triangle collision caches\r\n\t\r\n\tm_last_triangle.Init();\r\n\tm_car_left_rear_last_triangle.Init();\r\n\tm_car_right_rear_last_triangle.Init();\r\n\tm_car_mid_front_last_triangle.Init();\r\n\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::SetCorrectRotationDirection( int rotAxis )\r\n{\r\n\t\r\n\tm_turn_speed[ rotAxis ] = Mth::Abs( m_turn_speed[ rotAxis ] );\r\n\tm_turn_speed_target[ rotAxis ] = Mth::Abs( m_turn_speed_target[ rotAxis ] );\r\n\tm_delta_turn_speed[ rotAxis ] = Mth::Abs( m_delta_turn_speed[ rotAxis ] );\r\n\tm_angular_friction[ rotAxis ] = Mth::Abs( m_angular_friction[ rotAxis ] );\r\n\tif ( m_turn_ang_target[ rotAxis ] < 0 )\r\n\t{\r\n\t\tm_turn_speed[ rotAxis ] *= -1.0f;\r\n\t\tm_turn_speed_target[ rotAxis ] *= -1.0f;\r\n\t\tm_delta_turn_speed[ rotAxis ] *= -1.0f;\r\n\t\tm_angular_friction[ rotAxis ] *= -1.0f;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::InitPath( int nodeNumber )\r\n{\r\n\tif (mp_path_object_tracker)\r\n\t{\r\n\t\tmp_path_object_tracker->StopTrackingObject( GetObject() );\r\n\t}\t\r\n\r\n\tmp_path_object_tracker=Obj::CPathMan::Instance()->TrackObject( GetObject(), nodeNumber );\t\r\n\t// Note: mp_path_object_tracker could be NULL\r\n\t\r\n\tEnsurePathobExists( GetObject() );\r\n\tGetPathOb()->NewPath( nodeNumber, GetObject()->GetPos() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::FollowPath_Init( Script::CStruct* pParams )\r\n{   \r\n\tuint32 nodeChecksum;\r\n\tif ( pParams->GetChecksum( 0xa1dc81f9, &nodeChecksum ) ) // \"name\"\r\n\t{\r\n\t\tint nodeNum = SkateScript::FindNamedNode( nodeChecksum );\r\n\t\tInitPath( nodeNum );\r\n\t\tm_movingobj_status |= MOVINGOBJ_STATUS_ON_PATH;\r\n\t\t// these can't coexist:\r\n\t\tm_movingobj_status &= ~MOVINGOBJ_STATUS_MOVETO;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Must specify name of node in Obj_FollowPath, using name = nodeName.\" ));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMotionComponent::PickRandomWaypoint()\r\n{\r\n\treturn ( m_movingobj_flags & MOVINGOBJ_FLAG_RANDOM_PATH_MODE );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::HitWaypoint( int nodeIndex )\r\n{\t\r\n\tuint32 scriptChecksum;\r\n\tScript::CStruct* pNodeData;\r\n\tpNodeData = SkateScript::GetNode( nodeIndex );\r\n\tDbg_MsgAssert( pNodeData,( \"Waypoint gave us a bad node index.\" ));\r\n\tm_current_node = nodeIndex;\r\n\t\r\n\tif ( pNodeData->GetChecksum( 0x3aefe377, &scriptChecksum ) ) \t// \"SpawnObjScript\"\r\n\t{\r\n\t\tScript::CStruct* pScriptParams = NULL;\r\n\t\tpNodeData->GetStructure( CRCD(0x7031f10c,\"Params\"), &pScriptParams );\r\n#ifdef __NOPT_ASSERT__\r\n\t\tScript::CScript* p_script=GetObject()->SpawnScriptPlease( scriptChecksum, pScriptParams );\r\n\t\tp_script->SetCommentString(\"Created by CMotionComponent::HitWaypoint\");\r\n#else\r\n\t\tGetObject()->SpawnScriptPlease( scriptChecksum, pScriptParams );\r\n#endif\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif ( pNodeData->GetChecksum( 0x86125749, &scriptChecksum ) ) \t// \"SwitchObjScript\"\r\n\t{\r\n\t\tScript::CStruct* pScriptParams = NULL;\r\n\t\tpNodeData->GetStructure( CRCD(0x7031f10c,\"Params\"), &pScriptParams );\r\n\t\tGetObject()->SwitchScript( scriptChecksum, pScriptParams );\r\n\t\treturn;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMotionComponent::LookAt_Init( Script::CStruct* pParams, const Mth::Vector& lookAtPos )\r\n{\t\r\n\tint deltaDegreesPerSecond = 360;\r\n\tint deltaDeltaDegreesPerSecond = 0;\r\n\tint lockAxis = ( 1 << Y );\r\n\tfloat time = 0.0f;\r\n\t\r\n\tif ( !( m_movingobj_status & MOVINGOBJ_STATUS_LOOKAT ) )\r\n\t{\r\n\t\tm_movingobj_status |= MOVINGOBJ_STATUS_LOOKAT;\r\n\t\tm_movingobj_status &= ~MOVINGOBJ_STATUS_ROTXYZ;\r\n\t\tm_movingobj_flags &= ~( MOVINGOBJ_FLAG_CONST_ROTX | MOVINGOBJ_FLAG_CONST_ROTY | MOVINGOBJ_FLAG_CONST_ROTZ );\r\n\t}\r\n\r\n\tpParams->GetFloat( 0x906b67ba, &time ); // \"time\"\r\n\tif ( !time )\r\n\t{\r\n\t\tpParams->GetInteger( 0xf0d90109, &deltaDegreesPerSecond );\t\t// 'speed'\r\n\t\tpParams->GetInteger( 0x85894a84, &deltaDeltaDegreesPerSecond );\t// 'acceleration'\r\n\t\tpParams->GetInteger( 0xa4aecb20, &lockAxis );  // \"lockAxis\"\r\n\t}\r\n\t\r\n\tfloat threshold=0.0f;\r\n\tpParams->GetFloat(0xf73a4efd,&threshold); // AngleThreshold\r\n\tthreshold=DEGREES_TO_RADIANS(threshold);\r\n\t\r\n\tbool rotation_required=false;\r\n\tint i;\r\n\tfor ( i = 0; i < 3; i++ )\r\n\t{\r\n\t\tif ( lockAxis & ( 1 << i ) )\r\n\t\t{\r\n\t\t\tif ( SetUpLookAtPos( lookAtPos, GetObject()->GetPos(), i == Z ? Y : Z, i, threshold ) )\r\n\t\t\t{\r\n\t\t\t\tif ( time )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_delta_turn_speed[ i ] = 0.0f;\r\n\t\t\t\t\tm_turn_speed[ i ] = m_turn_ang_target[ i ] / time;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_delta_turn_speed[ i ] = DEGREES_TO_RADIANS( deltaDeltaDegreesPerSecond );\r\n\t\t\t\t\tif ( !m_delta_turn_speed[ i ] )\r\n\t\t\t\t\t\tm_turn_speed[ i ] = DEGREES_TO_RADIANS( deltaDegreesPerSecond );\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_turn_speed[ i ] = 0.0f;\r\n\t\t\t\t\t\tm_turn_speed_target[ i ] = 0.0f;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tSetCorrectRotationDirection( i );\r\n\t\t\t\t}\r\n\t\t\t\trotation_required=true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn rotation_required;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::QuatRot_Setup( Script::CStruct* pParams, const Mth::Matrix& rot )\r\n{\r\n\tif ( !mp_slerp )\r\n\t{\r\n\t\tmp_slerp = new Mth::SlerpInterpolator;\r\n\t}\r\n\r\n    Mth::Matrix tempMatrix = rot;\r\n\tmp_slerp->setMatrices( &GetObject()->GetMatrix(), &tempMatrix );\r\n\t\r\n\tm_rot_time = 0.0f;\r\n\tm_rot_time_target = 0.0f;\r\n\tpParams->GetFloat( 0x906b67ba, &m_rot_time_target ); // \"time\" ( in seconds )\r\n\tm_movingobj_status |= MOVINGOBJ_STATUS_QUAT_ROT;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::QuatRot_Init( Script::CStruct* pParams )\r\n{\r\n\tMth::Vector rot( 0.0f, 0.0f, 0.0f );\r\n\tif ( pParams->GetVector( 0x91a4c826, &rot ) )  // relative\r\n\t{\r\n\t\tif ( pParams->ContainsFlag( 0x26af9dc9 ) ) // \"FLAG_MAX_COORDS\"\r\n\t\t{\r\n\t\t\trot[ Z ] = -rot[ Z ];\r\n\t\t\trot.ConvertToMaxCoords( );\r\n\t\t}\r\n\t\trot.DegreesToRadians( );\r\n\t\tMth::Matrix temp = GetObject()->GetMatrix();\r\n\t\ttemp.RotateLocal( rot );\r\n\t\tQuatRot_Setup( pParams, temp );\r\n\t}\r\n\telse if ( pParams->GetVector( 0x592089a9, &rot ) ) //absolute\r\n\t{\r\n\t\tif ( pParams->ContainsFlag( 0x26af9dc9 ) ) // \"FLAG_MAX_COORDS\"\r\n\t\t{\r\n\t\t\trot[ Z ] = -rot[ Z ];\r\n\t\t\trot.ConvertToMaxCoords( );\r\n\t\t}\r\n\t\trot.DegreesToRadians( );\r\n\t\tMth::Matrix temp( rot[ X ], rot[ Y ], rot[ Z ] );\r\n\t\tQuatRot_Setup( pParams, temp );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMotionComponent::SetUpLookAtPos( const Mth::Vector& lookToPos, const Mth::Vector& currentPos, int headingAxis, int rotAxis, float threshold )\r\n{\r\n\tMth::Vector pathHeading = lookToPos - currentPos;\r\n\t\r\n\tm_cur_turn_ang[ rotAxis ] = 0.0f;\r\n\tm_turn_ang_target[ rotAxis ] = Mth::GetAngle( GetObject()->GetMatrix(), pathHeading, headingAxis, rotAxis );\r\n\tif ( fabs(m_turn_ang_target[ rotAxis ]) > threshold )\r\n\t{\r\n\t\tm_movingobj_status |= ( MOVINGOBJ_STATUS_ROTX << rotAxis );\r\n/*\t\tDbg_MsgAssert( ( ( !( m_movingobj_status & MOVINGOBJ_STATUS_ON_PATH ) ) ||\r\n\t\t\t\t\t\t( m_movingobj_flags & MOVINGOBJ_FLAG_INDEPENDENT_HEADING ) ) ||\r\n\t\t\t\t\t\trotAxis == Z,( \"Can't rotate on X or Y axis while using auto-heading on path.\" ));*/\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::RotAxis_Init( Script::CStruct* pParams, Script::CScript* pScript, int rotAxis )\r\n{\r\n\t\r\n\tfloat mult = 1.0f;\r\n\r\n\t// Mick - Just being safe here.  \t\r\n\tDbg_MsgAssert( rotAxis == X || rotAxis == Y || rotAxis== Z,( \"Illegal rotAxis %d\", rotAxis ));\r\n\t\r\n\t\r\n\t// get out of lookat mode... and shit.\r\n\tif ( m_movingobj_status & MOVINGOBJ_STATUS_LOOKAT )\r\n\t{\r\n\t\tm_movingobj_status &= ~MOVINGOBJ_STATUS_LOOKAT;\r\n\t\tm_movingobj_status &= ~MOVINGOBJ_STATUS_ROTXYZ;\r\n\t}\r\n\tif ( pParams->ContainsFlag( 0x26af9dc9 ) ) // \"FLAG_MAX_COORDS\"\r\n\t{\r\n\t\tswitch ( rotAxis )\r\n\t\t{\r\n\t\t\tcase ( X ):\r\n\t\t\t\tmult = -1.0f;\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase ( Y ):\r\n\t\t\t\trotAxis = Z;\r\n//\t\t\t\tmult = -1.0f;\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase ( Z ):\r\n\t\t\t\trotAxis = Y;\r\n\t\t\t\tbreak;\r\n\t\t\t\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert( 0,( \"Illegal rotAxis\" ));\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// clear this in case it isn't set...\r\n\tm_angular_friction[ rotAxis ] = 0.0f;\r\n\tm_delta_turn_speed[ rotAxis ] = 0.0f;\r\n\tm_turn_ang_target[ rotAxis ] = 0.0f;\r\n\r\n\tif ( pParams->GetFloat( 0xff7ebaf6, &m_turn_ang_target[ rotAxis ] ) ) // \"angle\"\r\n\t{\r\n\t\tm_turn_ang_target[ rotAxis ] = mult * DEGREES_TO_RADIANS( m_turn_ang_target[ rotAxis ] );\r\n\t\tm_movingobj_flags &= ~( MOVINGOBJ_FLAG_CONST_ROTX << rotAxis );\r\n\t\tm_cur_turn_ang[ rotAxis ] = 0.0f;\r\n\t\tm_turn_speed[ rotAxis ] = 0.0f;\r\n\t\tif ( !m_turn_ang_target[ rotAxis ] )\r\n\t\t{\r\n\t\t\t// stop the rotation!\r\n\t\t\tm_movingobj_status &= ~( MOVINGOBJ_STATUS_ROTX << rotAxis );\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( pParams->GetFloat( 0xf59ff7d7, &m_angular_friction[ rotAxis ] ) ) // \"deceleration\"\r\n\t{\r\n\t\t// K: If a deceleration is specified, the 'speed' value specified is the target speed.\r\n\t\t// The current m_turn_speed remains unchanged so that it slows down to the target speed.\r\n\t\t// (TT427)\r\n\t\tm_angular_friction[ rotAxis ] = DEGREES_TO_RADIANS( m_angular_friction[ rotAxis ] );\r\n\t\tif ( pParams->GetFloat( 0xf0d90109, &m_turn_speed_target[ rotAxis ] ) ) // \"speed\"\r\n\t\t{\r\n\t\t\tm_turn_speed_target[ rotAxis ] = DEGREES_TO_RADIANS( m_turn_speed_target[ rotAxis ] );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"\\n%s\\nMust specify speed for Obj_Rot functions (degrees per second).\", pScript->GetScriptInfo( ) ));\r\n\t\t}\r\n\t}\r\n\telse if ( pParams->GetFloat( 0x85894a84, &m_delta_turn_speed[ rotAxis ] ) ) // acceleration\r\n\t{\r\n\t\tm_delta_turn_speed[ rotAxis ] = DEGREES_TO_RADIANS( m_delta_turn_speed[ rotAxis ] );\r\n\t\tif ( pParams->GetFloat( 0xf0d90109, &m_turn_speed_target[ rotAxis ] ) ) // \"speed\"\r\n\t\t{\r\n\t\t\tm_turn_speed_target[ rotAxis ] = DEGREES_TO_RADIANS( m_turn_speed_target[ rotAxis ] );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"\\n%s\\nMust specify speed for Obj_Rot functions (degrees per second).\", pScript->GetScriptInfo( ) ));\r\n\t\t}\r\n\t\tif ( !( m_movingobj_status & ( MOVINGOBJ_STATUS_ROTX << rotAxis ) ) )\r\n\t\t{\r\n\t\t\tm_turn_speed[ rotAxis ] = 0.0f;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( pParams->GetFloat( 0xf0d90109, &m_turn_speed[ rotAxis ] ) ) // \"speed\"\r\n\t\t{\r\n\t\t\tm_turn_speed[ rotAxis ] = DEGREES_TO_RADIANS( m_turn_speed[ rotAxis ] );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"\\n%s\\nMust specify speed for Obj_Rot functions (degrees per second).\", pScript->GetScriptInfo( ) ));\r\n\t\t}\r\n\t}\r\n\tif ( !( m_turn_ang_target[ rotAxis ] || m_angular_friction[ rotAxis ] ) )\r\n\t{\r\n\t\tm_movingobj_flags |= ( MOVINGOBJ_FLAG_CONST_ROTX << rotAxis );\r\n\t}\r\n\tif ( !( m_movingobj_flags & ( MOVINGOBJ_FLAG_CONST_ROTX << rotAxis ) ) )\r\n\t{\r\n\t\tSetCorrectRotationDirection( rotAxis );\r\n\t}\r\n\tm_movingobj_status |= ( MOVINGOBJ_STATUS_ROTX << rotAxis );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::LookAtNodeLinked_Init( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\t\r\n\tint numLinks;\r\n\tnumLinks = SkateScript::GetNumLinks( m_current_node );\r\n\tif ( !numLinks )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"\\n%s\\nNo node linked to object calling Obj_LookAtNodeLinked\", pScript->GetScriptInfo( ) ));\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tint link_num=1;\r\n\tpParams->GetInteger( 0xe85997d0, &link_num ); // \"linkNum\"\r\n\t// Designers number the links from 1 to n, so convert to programmer form\r\n\tlink_num -= 1;\r\n\t\r\n\t// Print a warning message instead of asserting, to save having to reboot.\r\n\tif (link_num<0 || link_num>=numLinks)\r\n\t{\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tprintf(\"!!!!!!!!!! Bad LinkNum of %d sent to Obj_LookAtNodeLinked, range is 1 to %d\\n\",link_num+1,numLinks);\r\n\t\t#endif\r\n\t\tlink_num=0;\r\n\t}\t\r\n\t\r\n\tMth::Vector lookAtPos;\r\n\tSkateScript::GetPosition( SkateScript::GetLink( m_current_node, link_num ), &lookAtPos );\r\n\tLookAt_Init( pParams, lookAtPos );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::LookAtNode_Init( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 checksum = 0;\r\n\t\r\n\tpParams->GetChecksum( 0xa1dc81f9, &checksum ); // \"name\"\r\n\tif ( !checksum )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"\\n%s\\nNeed node name in Obj_LookAtNode\", pScript->GetScriptInfo( ) ));\r\n\t\treturn;\r\n\t}\r\n\tMth::Vector lookAtPos;\r\n\tSkateScript::GetPosition( SkateScript::FindNamedNode( checksum ), &lookAtPos );\r\n\tLookAt_Init( pParams, lookAtPos );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::LookAtPos_Init( Script::CStruct* pParams, bool absolute )\r\n{\r\n\t\r\n\tMth::Vector vec( 0, 0, 0 );\r\n\tpParams->GetVector( NONAME, &vec );\r\n\tif ( pParams->ContainsFlag( 0x26af9dc9 ) ) // \"FLAG_MAX_COORDS\"\r\n\t{\r\n\t\tvec.ConvertToMaxCoords( );\r\n\t}\r\n\tif ( !absolute )\r\n\t{\r\n\t\tvec += GetObject()->GetPos();\r\n\t}\r\n\tLookAt_Init( pParams, vec );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::Rot( int rotAxis, float deltaRot )\r\n{\r\n\tswitch ( rotAxis )\r\n\t{\r\n\t\tcase ( X ):\r\n\t\t\tGetObject()->m_matrix.RotateXLocal( deltaRot );\r\n\t\t\tGetObject()->m_matrix.OrthoNormalizeAbout( X );\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase ( Y ):\r\n\t\t\tGetObject()->m_matrix.RotateYLocal( deltaRot );\r\n\t\t\tGetObject()->m_matrix.OrthoNormalizeAbout( Y );\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase ( Z  ):\r\n\t\t\tGetObject()->m_matrix.RotateZLocal( deltaRot );\r\n\t\t\tGetObject()->m_matrix.OrthoNormalizeAbout( Z );\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0,( \"illegal rot axis.\" ));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::RotateToFacePos( const Mth::Vector pos )\r\n{   \r\n\tMth::Vector desiredHeading;\r\n\tdesiredHeading = pos - GetObject()->GetPos();\r\n\tfloat deltaY = Mth::GetAngle( GetObject()->GetMatrix(), desiredHeading );\r\n\tGetObject()->m_matrix.RotateYLocal( deltaY );\r\n\tGetObject()->m_matrix.OrthoNormalizeAbout( Y );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Follow the path that's linked to the current waypoint (node) that the object is sitting at.\r\nvoid CMotionComponent::FollowPathLinked_Init( Script::CStruct* pParams, Script::CScript* pScript )\r\n{   \r\n\tint numLinks;\r\n\tint nodeNum;\r\n\r\n\tif ( pParams->ContainsFlag( 0x422e1fce ) ) // originalNode\r\n\t{\r\n\t\tnodeNum = m_start_node;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tnodeNum = m_current_node;\r\n\t}\r\n\t\r\n\tnumLinks = SkateScript::GetNumLinks( nodeNum );\r\n\tif ( !numLinks )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"\\n%s\\nNo node linked to object (from node %d) calling Obj_FollowPathLinked\", pScript->GetScriptInfo( ), nodeNum ));\r\n\t\treturn;\r\n\t}\r\n\tif ( ( numLinks > 1 ) && PickRandomWaypoint( ) )\r\n\t{\r\n\t\tInitPath( SkateScript::GetLink( nodeNum, Mth::Rnd( numLinks ) ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tInitPath( SkateScript::GetLink( nodeNum, 0 ) );\r\n\t}\r\n\tm_movingobj_status |= MOVINGOBJ_STATUS_ON_PATH;\r\n\t// these can't coexist:\r\n\tm_movingobj_status &= ~MOVINGOBJ_STATUS_MOVETO;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Follow the path from current position to the position of the waypoint last stored\r\n// in the script call to Obj_StoreNode (when a pedestrian, for example, has to jump\r\n// out of the way of the player, he stores his current position and the current node\r\n// that he's heading for... then he walks back to his position, and finally ends up\r\n// heading to the waypoint he was heading for before he left the path to jump out of the way).\r\nvoid CMotionComponent::FollowStoredPath_Init( Script::CStruct* pParams )\r\n{   \r\n\tInitPath( m_stored_node );\r\n\tm_movingobj_status |= MOVINGOBJ_STATUS_ON_PATH;\r\n\t// these can't coexist:\r\n\tm_movingobj_status &= ~MOVINGOBJ_STATUS_MOVETO;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Physics for when the moving object is following a path.\r\nvoid CMotionComponent::DoPathPhysics( void )\r\n{\t\r\n\tif ( m_movingobj_status & MOVINGOBJ_STATUS_ON_PATH )\r\n\t{\r\n\t\t// if we're stopping:\r\n\t\tif ( m_movingobj_flags & MOVINGOBJ_FLAG_STOP_ALONG_PATH )\r\n\t\t{\r\n\t\t\tif ( m_stop_dist_traveled >= m_stop_dist )\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\t// keep slowing down...\r\n\t\t\tm_stop_dist_traveled += m_vel_z * m_time;\r\n\t\t\tif ( ( !m_stop_dist ) || ( m_stop_dist_traveled >= m_stop_dist ) )\r\n\t\t\t{\r\n\t\t\t\tm_vel_z = 0;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfloat percent = m_stop_dist_traveled / m_stop_dist;\r\n\t\t\t\tm_vel_z = ( m_vel_z_start * ( 1.0f - percent ) ) + ( m_min_stop_vel * ( percent ) );\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\t// Adjust velocity...\r\n\t\tif ( m_vel_z < m_max_vel )\r\n\t\t{\r\n\t\t\tif ( m_acceleration )\r\n\t\t\t{\r\n\t\t\t\tm_vel_z += ( m_acceleration * m_time );\r\n\t\t\t\tif ( m_vel_z > m_max_vel )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_vel_z = m_max_vel;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_vel_z = m_max_vel;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( m_vel_z > m_max_vel )\r\n\t\t{\r\n\t\t\tif ( m_deceleration )\r\n\t\t\t{\r\n\t\t\t\tm_vel_z -= ( m_deceleration * m_time );\r\n\t\t\t\tif ( m_vel_z < m_max_vel )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_vel_z = m_max_vel;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_vel_z = m_max_vel;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#if 0\r\n\r\n// UNUSED...\r\n\r\n// BB: I have added a new version of this function below.  I moved the code\r\n// from the CallMemberFunction func because I needed to do the same thing from c.\r\n// I have left this here for reference, just in case.\r\nCCompositeObject* CMotionComponent::GetNextObjectOnPath( float range )\r\n{\r\n\tif (!(m_movingobj_status & MOVINGOBJ_STATUS_ON_PATH) || !GetPathOb() || !mp_path_object_tracker)\r\n\t{\r\n\t\treturn NULL;\r\n\t}\t\r\n\t\r\n\tfloat distance_covered=0.0f;\r\n\tMth::Vector path_pos=m_pos;\r\n\tint next_node=GetPathOb()->m_node_to;\r\n\t\r\n\t// Copy the non-NULL object pointers from the tracker to a small local array for speed,\r\n\t// since they may need to be stepped through several times and the tracker's array\r\n\t// contains lots of NULL's\r\n\t#define MAX_OBS 20\r\n\tCCompositeObject* pp_objects[MAX_OBS];\r\n\tint num_objects=0;\r\n\t\r\n\tconst CSmtPtr<CCompositeObject>* pp_object_list=mp_path_object_tracker->GetObjectList();\r\n\tfor (int i=0; i<CPathObjectTracker::MAX_OBJECTS_PER_PATH; ++i)\r\n\t{\r\n\t\tif (pp_object_list[i])\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(num_objects<MAX_OBS,(\"Too many objects on path, need to increase MAX_OBS in CMovingObject::GetNextObjectOnPath\"));\r\n\t\t\tpp_objects[num_objects++]=pp_object_list[i].Convert();\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\tCCompositeObject* p_nearest=NULL;\r\n\twhile (true)\r\n\t{\r\n\t\tfloat min_dist=0.0f;\r\n\t\t\r\n\t\tfor (int i=0; i<num_objects; ++i)\r\n\t\t{\r\n\t\t\tif (GetMotionComponentFromObject(pp_objects[i])->GetDestinationPathNode()==next_node)\r\n\t\t\t{\r\n\t\t\t\tfloat d=Mth::Distance(pp_objects[i]->m_pos,path_pos);\r\n\t\t\t\tif (distance_covered+d < range)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!p_nearest || d<min_dist)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmin_dist=d;\r\n\t\t\t\t\t\tp_nearest=pp_objects[i];\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\t\r\n\t\t\t\t\r\n\t\tif (p_nearest)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\tScript::CStruct* p_node=SkateScript::GetNode(next_node);\r\n\t\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\t\tMth::Vector node_pos;\r\n\t\tSkateScript::GetPosition(p_node,&node_pos);\r\n\t\t\r\n\t\tdistance_covered+=Mth::Distance(path_pos,node_pos);\r\n\t\tpath_pos=node_pos;\r\n\r\n\t\t// Get the next linked node\r\n\t\tScript::CArray* p_links=NULL;\r\n\t\tp_node->GetArray(0x2e7d5ee7/*Links*/,&p_links);\r\n\t\t\r\n\t\tif (!p_links)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tnext_node=p_links->GetInteger(0);\t\r\n\t}\r\n\t\r\n\treturn p_nearest;\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// returns TRUE if instant move, FALSE otherwise.\r\nbool CMotionComponent::Move_Init( Script::CStruct* pParams, Script::CScript* pScript, Mth::Vector pos, int nodeNum )\r\n{   \r\n\tint units = UNITS_MPH;\r\n\tfloat time;\r\n\tfloat speed;\r\n\r\n\tm_moveto_pos = pos;\r\n\tm_moveto_dist = Mth::Distance( m_moveto_pos, GetObject()->GetPos() );\r\n\tm_moveto_acceleration = 0.0f;\r\n\t\r\n\t// initialize everything:\r\n\tm_orig_pos = GetObject()->GetPos();\r\n\tm_moveto_dist_traveled = 0.0f;\r\n\tm_movingobj_status |= MOVINGOBJ_STATUS_MOVETO;\r\n\t// can't follow path and moveto at the same time:\r\n\tm_movingobj_status &= ~MOVINGOBJ_STATUS_ON_PATH;\r\n\tm_moveto_node_num = -1;\r\n\tif ( pParams->GetFloat( 0x906b67ba, &time ) ) // \"time\"\r\n\t{\r\n\t\t// time is in seconds:\r\n\t\tDbg_MsgAssert( time,( \"\\n%s\\nCan't have zero for time...\", pScript->GetScriptInfo( ) ));\r\n\t\tm_moveto_speed = m_moveto_dist / time;\r\n\t}\r\n\telse if ( pParams->GetFloat( 0xf0d90109, &speed ) ) // \"speed\"\r\n\t{\t// use speed and acceleration:\r\n\t\tif ( pParams->ContainsFlag( 0x2ce7ee02 ) ) // \"mph\"\r\n\t\t{\r\n\t\t\tunits = UNITS_MPH;\r\n\t\t}\r\n\t\telse if ( pParams->ContainsFlag( 0xaad7c80f ) ) // \"fps\"\r\n\t\t{\r\n\t\t\tunits = UNITS_FPS;\r\n\t\t} \r\n\t\telse if ( pParams->ContainsFlag( 0xa18b8f32 ) ) //IPS\r\n\t\t{\r\n\t\t\tunits = UNITS_IPS;\r\n\t\t}\r\n\r\n\t\tpParams->GetFloat( 0x85894a84, &m_moveto_acceleration ); // \"acceleration\"\r\n\r\n\t\tif ( units == UNITS_MPH )\r\n\t\t{\r\n\t\t\tspeed = MPH_TO_IPS( speed );\r\n\t\t\tm_moveto_acceleration = MPH_TO_IPS( m_moveto_acceleration );\r\n\t\t}\r\n\t\telse if ( units == UNITS_FPS )\r\n\t\t{\r\n\t\t\tspeed *= 12.0f;\r\n\t\t\tm_moveto_acceleration *= 12.0f;\r\n\t\t}\r\n\t\t\r\n\t\tif ( !m_moveto_acceleration )\r\n\t\t{\r\n\t\t\tm_moveto_speed = speed;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_moveto_speed = 0.0f;\r\n\t\t\tm_moveto_speed_target = speed;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// instantaneous move:\r\n\t\tGetObject()->SetPos(m_moveto_pos);\r\n\t\tm_movingobj_status &= ~MOVINGOBJ_STATUS_MOVETO;\r\n\t\t\r\n\t\tif ( nodeNum != -1 )\r\n\t\t{\r\n\t\t\tif ( pParams->ContainsFlag( 0x90a91232 ) ) // \"orient\"\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pNodeData = SkateScript::GetNode( nodeNum );\r\n\t\t\t\tOrientToNode( pNodeData );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// GJ:  Need to re-implement this on THPS5...\r\n\t\t// (used to fix quick-jump bug on Xbox/NGC,\r\n\t\t// where LODing code wasn't refreshing the model's\r\n\t\t// position)\r\n\r\n#if 0\r\n#ifndef __PLAT_NGPS__\r\n\t\t// Rebuild display matrix. Gary - you should look at this post THPS4 and generalize.\r\n\t\tMth::Matrix rootMatrix;\r\n\t\trootMatrix = m_display_matrix;\r\n\t\trootMatrix[Mth::POS] = m_pos;\r\n\t\trootMatrix[Mth::POS][W] = 1.0f;\r\n\t\tif( GetModel() )\r\n\t\t{\r\n\t\t\tGetModel()->Render( &rootMatrix, true, GetSkeleton() );\r\n\r\n\t\t\t// Also update the shadow if relevant.\r\n\t\t\tif( mp_shadow && mp_shadow->GetShadowType() != Gfx::vDETAILED_SHADOW )\r\n\t\t\t{\r\n\t\t\t\tupdate_shadow();\r\n\t\t\t}\r\n\t\t}\r\n#endif\r\n#endif\r\n\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::MoveToNode_Init( Script::CStruct* pParams, Script::CScript* pScript )\r\n{   \r\n\tMth::Vector pos;\r\n\t\r\n\t// if we're moving to a named node:\r\n\tuint32 checksum = 0;\r\n\tpParams->GetChecksum( 0xa1dc81f9, &checksum ); // \"name\"\r\n\tif ( checksum )\r\n\t{\r\n\t\tint nodeNum = SkateScript::FindNamedNode( checksum );\r\n\t\tSkateScript::GetPosition( nodeNum, &pos );\r\n\t\tif ( Move_Init( pParams, pScript, pos, nodeNum ) )\r\n\t\t{\r\n\t\t\tHitWaypoint( nodeNum );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_moveto_node_num = nodeNum;\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\tDbg_MsgAssert( 0,( \"\\n%s\\nObj_MoveToNode requires node name specification (name = *)\", pScript->GetScriptInfo( ) ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::MoveToPos_Init( Script::CStruct* pParams, Script::CScript* pScript, bool absolute )\r\n{   \r\n\tMth::Vector vec( 0, 0, 0 );\r\n\tpParams->GetVector( NONAME, &vec );\r\n\tif ( pParams->ContainsFlag( 0x26af9dc9 ) ) // \"FLAG_MAX_COORDS\"\r\n\t{\r\n\t\tvec.ConvertToMaxCoords( );\r\n\t}\r\n\tif ( !absolute )\r\n\t{\r\n\t\tvec += GetObject()->GetPos();\r\n\t}\r\n\tMove_Init( pParams, pScript, vec );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::MoveToLink_Init( Script::CStruct* pParams, Script::CScript* pScript )\r\n{   \r\n\tint linkNum = 0;\r\n\tint numLinks;\r\n\tnumLinks = SkateScript::GetNumLinks( m_current_node );\r\n\tif ( !numLinks )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Obj_MoveToLink requires a link to the object's current node (last node hit in path).\" ));\r\n\t\treturn;\r\n\t}\r\n\tif ( pParams->GetInteger( 0xe85997d0, &linkNum ) ) // \"linkNum\"\r\n\t{\r\n\t\tlinkNum -= 1;\r\n\t}\r\n\telse if ( ( numLinks > 1 ) && ( pParams->ContainsFlag( 0x90a1c52a ) ) ) // \"randomLink\"\r\n\t{\r\n\t\tlinkNum = Mth::Rnd( numLinks );\r\n\t}\r\n\tMth::Vector pos;\r\n\tDbg_MsgAssert( linkNum < numLinks,( \"\\n%s\\nLink num is greater than the number of links.\", pScript->GetScriptInfo( ) ));\r\n\tint nodeNum;\r\n\tnodeNum = SkateScript::GetLink( m_current_node, linkNum );\r\n\tSkateScript::GetPosition( nodeNum, &pos );\r\n\tif ( Move_Init( pParams, pScript, pos ) )\r\n\t{\r\n\t\tHitWaypoint( nodeNum );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_moveto_node_num = nodeNum;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMotionComponent::Move( void )\r\n{\t\r\n\tif ( m_moveto_acceleration )\r\n\t{\r\n\t\tm_moveto_speed += m_moveto_acceleration * Tmr::FrameRatio( );\r\n\t\tif ( m_moveto_speed >= m_moveto_speed_target )\r\n\t\t{\r\n\t\t\tm_moveto_speed = m_moveto_speed_target;\r\n\t\t\tm_moveto_acceleration = 0.0f;\r\n\t\t}\r\n\t}\r\n\tm_moveto_dist_traveled += m_time * m_moveto_speed;\r\n\tif ( m_moveto_dist_traveled >= m_moveto_dist )\r\n\t{\r\n\t\tGetObject()->m_pos = m_moveto_pos;\r\n\t\tif ( m_moveto_node_num != -1 )\r\n\t\t{\r\n\t\t\tHitWaypoint( m_moveto_node_num );\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\tMth::Vector newPos = m_moveto_pos - m_orig_pos;\r\n\tnewPos *= ( m_moveto_dist_traveled / m_moveto_dist );\r\n\tGetObject()->m_pos = m_orig_pos + newPos;\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::OrientToNode(Script::CStruct* pNodeData)\r\n{\r\n\tMth::Vector rot;\r\n\tGetObject()->m_matrix.Ident( );\t   \t\t// Set identity before we decided if we need to rotate or not, in case we don't.\r\n\tSkateScript::GetAngles( pNodeData, &rot );\r\n\tif ( rot[ X ] || rot[ Y ] || rot[ Z ] )\r\n\t{\r\n\t\t// AML: This was rotating Z, then X, then Y\r\n\t\t//\t\tSee me if there are problems, and I'll change\r\n\t\t//\t\tthe exporter to do Z,X,Y\r\n\r\n\t\t//m_matrix.RotateZ( rot[ Z ] );\r\n\t\tGetObject()->GetMatrix().RotateX( rot[ X ] );\r\n\t\tGetObject()->GetMatrix().RotateY( rot[ Y ] );\r\n\t\tGetObject()->GetMatrix().RotateZ( rot[ Z ] );\r\n\t}\t\r\n\t//printf (\"OrientToNode %d, (%f,%f,%f)\\n\",nodeNum,rot[X],rot[Y],rot[Z]);\r\n\t\r\n\t// sync up the display matrix to the physics matrix\r\n\tGetObject()->GetDisplayMatrix() = GetObject()->m_matrix;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::QuatRot( void )\r\n{\t\r\n\tfloat percent;\r\n\tm_rot_time += m_time;\r\n\tif ( ( !m_rot_time_target ) || ( m_rot_time >= m_rot_time_target ) )\r\n\t{\r\n\t\tpercent = 1.0f;\r\n\t\tm_movingobj_status &= ~MOVINGOBJ_STATUS_QUAT_ROT;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpercent = m_rot_time / m_rot_time_target;\r\n\t}\r\n\t\r\n\tDbg_MsgAssert( mp_slerp,( \"Missing mp_slerp...\" ));\r\n    mp_slerp->getMatrix( &GetObject()->m_matrix, percent );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::FollowPath( void )\r\n{   \r\n\t// temp hack to separate new peds from old path ob stuff\r\n\tObj::CPedLogicComponent* pPedLogicComp = GetPedLogicComponentFromObject( GetObject() );\r\n\tif ( pPedLogicComp )\r\n\t\treturn;\r\n\r\n\tDbg_MsgAssert( GetPathOb(),( \"Shouldn't be in FOLLOW_WAYPOINTS state without pathob.\" ));\r\n\r\n    Mth::Vector movement = -GetObject()->GetPos();\t\t\t\t\r\n\t\t\t\t\r\n\t// change velocity:\r\n\tDoPathPhysics();\r\n\r\n\t// do path traversal:\r\n\tif ( m_vel_z )\r\n\t{\r\n\t\t/*\r\n\t\tMth::Vector d=GetPathOb()->m_wp_pos_to-GetPathOb()->m_wp_pos_from;\r\n\t\tm_shadow_normal.Set(0.0f,1.0f,0.0f);\r\n\t\tm_shadow_normal=Mth::CrossProduct(m_shadow_normal,d);\r\n\t\tm_shadow_normal=Mth::CrossProduct(m_shadow_normal,d);\r\n\t\tm_shadow_normal.Normalize();\r\n\t\t*/\r\n\t\t\r\n\t\t// send in our forward direction, distance traveled...\r\n\t\t//if ( GetPathOb()->TraversePath( is_being_skitched, m_vel_z * m_time, \r\n\t\t//\t( m_movingobj_flags & MOVINGOBJ_FLAG_INDEPENDENT_HEADING ) ? NULL : &m_matrix[ Z ] ) )\r\n\t\tif ( GetPathOb()->TraversePath( m_vel_z * m_time, \r\n\t\t\t( m_movingobj_flags & MOVINGOBJ_FLAG_INDEPENDENT_HEADING ) ? NULL : &GetObject()->m_matrix[ Z ] ) )\r\n\t\t{\r\n\t\t\t// path is done... turn off flag:\r\n\t\t\tm_movingobj_status &= ~MOVINGOBJ_STATUS_ON_PATH;\r\n\t\t\tm_vel_z = 0.0f;\r\n\t\t}\r\n\r\n\t\tif ( !( m_movingobj_flags & MOVINGOBJ_FLAG_INDEPENDENT_HEADING ) )\r\n\t\t{\r\n\t\t\t// set up the matrix according to the nav point heading...\r\n\t\t\tGetPathOb()->SetHeading( &GetObject()->m_matrix[ Z ] );\r\n\t\t\tif ( m_movingobj_flags & MOVINGOBJ_FLAG_NO_PITCH_PLEASE )\r\n\t\t\t{\r\n\t\t\t\tif ( ( GetObject()->m_matrix[ Z ] )[ Y ] )\r\n\t\t\t\t{\r\n\t\t\t\t\t( GetObject()->m_matrix[ Z ] )[ Y ] = 0.0f;\r\n\t\t\t\t\tGetObject()->m_matrix[ Z ].Normalize( );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// this heading may be changed in a moment, when we stick\r\n\t\t\t// the object to the ground... if it isn't stuck, we should\r\n\t\t\t// normalize the matrix around that heading...\r\n\t\t\tif ( !( m_movingobj_flags & MOVINGOBJ_FLAG_STICK_TO_GROUND ) )\r\n\t\t\t{\r\n\t\t\t\t// make sure our matrix is orthagonal:\r\n\t\t\t\tGetObject()->m_matrix[ X ] = Mth::CrossProduct( GetObject()->m_matrix[ Y ], GetObject()->m_matrix[ Z ]);\r\n\t\t\t\tGetObject()->m_matrix[ X ].Normalize();\r\n\t\t\t\t// This will work for things whose Y axis is always up...\r\n\t\t\t\t// May have to add flags for things that rotate along Z axis or\r\n\t\t\t\t// far along X axis:\r\n\t\t\t\tGetObject()->m_matrix[ Z ] = Mth::CrossProduct( GetObject()->m_matrix[ X ], GetObject()->m_matrix[ Y ] );\r\n\t\t\t\tGetObject()->m_matrix[ Z ].Normalize( );\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( m_movingobj_flags & MOVINGOBJ_FLAG_STICK_TO_GROUND )\r\n\t\t{\r\n\t\t\t// Just move it to the nav pos ( except for y axis ) then stick it to the ground...\r\n\t\t\tfloat origY = GetObject()->m_pos[ Y ];\r\n\t\t\tGetObject()->m_pos = GetPathOb()->m_nav_pos;\r\n\t\t\tGetObject()->m_pos[ Y ] = origY;\r\n\r\n\t\t\tStickToGround();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfloat origY = GetObject()->m_pos[ Y ];\r\n\t\t\tGetObject()->m_pos = GetPathOb()->m_nav_pos;\r\n\t\t\tif ( m_movingobj_flags & MOVINGOBJ_FLAG_CONSTANT_HEIGHT )\r\n\t\t\t{\r\n\t\t\t\tGetObject()->m_pos[ Y ] = origY;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tmovement += GetObject()->m_pos;\t\t\t\t// actually calculate movement\t\r\n\tGetObject()->m_vel = movement / m_time; \t\t// calculate the velocity, so we can impart velocity in things we hit, etc\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// call SetUpLookAtPos first, or one of the other rotate\r\n// setup functions, then call this until it returns true:\r\nbool CMotionComponent::Rotate( int rotAxis )\r\n{\t\r\n\r\n\tbool done = false;\r\n\r\n\t// update angular acceleration/angular velocity:\r\n\tif ( m_delta_turn_speed[ rotAxis ] )\r\n\t{\r\n\t\tm_turn_speed[ rotAxis ] += m_delta_turn_speed[ rotAxis ] * m_time;\r\n\t\tif ( ( Mth::Abs( m_turn_speed[ rotAxis ] ) > Mth::Abs( m_turn_speed_target[ rotAxis ] ) )\r\n\t\t\t&& ( ( m_turn_speed[ rotAxis ] > 0.0f ) == ( m_turn_speed_target[ rotAxis ] > 0.0f ) ) )\r\n\t\t{\r\n\t\t\t// stop angular acceleration...settle on the target:\r\n\t\t\tm_turn_speed[ rotAxis ] = m_turn_speed_target[ rotAxis ];\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( m_angular_friction[ rotAxis ] )\r\n\t{\r\n\t\tfloat friction = m_angular_friction[ rotAxis ] * m_time;\r\n\t\t// Ken: Changed this so that it decelerates down to the m_turn_speed_target rather than 0\r\n\t\tif ( Mth::Abs( friction ) > Mth::Abs( m_turn_speed[ rotAxis ] - m_turn_speed_target[ rotAxis ] ) )\r\n\t\t{\r\n\t\t\t// Settle on the target speed\r\n\t\t\tm_turn_speed[ rotAxis ] = m_turn_speed_target[ rotAxis ];\r\n\t\t\t// Switch off the friction so that it deos not slow down any more\r\n\t\t\tm_angular_friction[ rotAxis ] = 0.0f;\r\n\t\t\t\r\n\t\t\tDbg_Message( \"done rotating due to deceleration... %s angle traversed = %f\", \r\n\t\t\t\trotAxis == X ? \"X\" : ( rotAxis == Y ? \"Y\" : \"Z\" ), RADIANS_TO_DEGREES( m_cur_turn_ang[ rotAxis ] ) );\r\n\t\t\tif (m_turn_speed_target[ rotAxis ]==0.0f)\r\n\t\t\t{\r\n\t\t\t\treturn true; // done rotating...\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn false;  \r\n\t\t\t}\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_turn_speed[ rotAxis ] -= friction;\r\n\t\t}\r\n\t}\r\n\tfloat cur_turn_dist = m_turn_speed[ rotAxis ] * m_time;\r\n\t\r\n\tif ( !( m_movingobj_flags & ( MOVINGOBJ_FLAG_CONST_ROTX << rotAxis ) ) )\r\n\t{\r\n\t\tbool positive = m_turn_ang_target[ rotAxis ] > m_cur_turn_ang[ rotAxis ];\r\n\t\tm_cur_turn_ang[ rotAxis ] += cur_turn_dist;\r\n\t\tif ( positive != ( m_turn_ang_target[ rotAxis ] > m_cur_turn_ang[ rotAxis ] ) )\r\n\t\t{\r\n\t\t\t//done rotating!\r\n\t\t\tdone = true;\r\n\t\t\t// and deltaYRot should be altered so as to hit 0 exactly:\r\n\t\t\tcur_turn_dist += m_turn_ang_target[ rotAxis ] - m_cur_turn_ang[ rotAxis ];\r\n\t//\t\tm_cur_turn_ang[ rotAxis ] = m_turn_ang_target[ rotAxis ];\r\n\t\t}\r\n\t}\r\n\r\n\tRot( rotAxis, cur_turn_dist );\r\n\t\r\n\treturn ( done );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::RotUpdate( void )\r\n{   \r\n\t// rotate states:\r\n\tfor ( int i = 0; i < 3; i++ )\r\n\t{\r\n\t\tif ( m_movingobj_status & ( MOVINGOBJ_STATUS_ROTX << i ) )\r\n\t\t{\r\n\t\t\tif ( Rotate( i ) )\r\n\t\t\t{\r\n\t\t\t\tm_movingobj_status &= ~( MOVINGOBJ_STATUS_ROTX << i );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nstatic bool s_do_collision_check(const Mth::Vector *p_v0, const Mth::Vector *p_v1, Mth::Vector *p_collisionPoint, \r\n\t\t\t\t\t\t\t\t STriangle *p_lastTriangle)\r\n{\r\n\t// First, see if there is a collision with the last triangle, and if there is, use that.\r\n\tMth::Vector d=*p_v1-*p_v0;\r\n\tfloat alpha=0.0f;\r\n\tif (Nx::CCollObj::sRayTriangleCollision(p_v0, &d,\r\n\t\t\t\t\t\t\t\t\t\t\t&p_lastTriangle->mpVertices[0],\r\n\t\t\t\t\t\t\t\t\t\t\t&p_lastTriangle->mpVertices[1],\r\n\t\t\t\t\t\t\t\t\t\t\t&p_lastTriangle->mpVertices[2], &alpha))\r\n\t{\r\n\t\t*p_collisionPoint = *p_v0+d*alpha;\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCFeeler feeler;\r\n\t\tif (feeler.GetCollision(*p_v0,*p_v1, false))\r\n\t\t{\r\n\t\t\tNx::CCollObj* p_col_obj=feeler.GetSector();\r\n\t\t\tDbg_MsgAssert(p_col_obj->IsTriangleCollision(),(\"Not triangle collision !!!\"));\r\n\t\r\n\t\t\tNx::CCollObjTriData* p_tri_data=p_col_obj->GetGeometry();\r\n\t\t\tDbg_MsgAssert(p_tri_data,(\"NULL p_tri_data\"));\r\n\t\r\n\t\t\tint face_index=feeler.GetFaceIndex();\r\n\t\t\tp_lastTriangle->mpVertices[0]=p_col_obj->GetVertexPos(p_tri_data->GetFaceVertIndex(face_index, 0));\r\n\t\t\tp_lastTriangle->mpVertices[1]=p_col_obj->GetVertexPos(p_tri_data->GetFaceVertIndex(face_index, 1));\r\n\t\t\tp_lastTriangle->mpVertices[2]=p_col_obj->GetVertexPos(p_tri_data->GetFaceVertIndex(face_index, 2));\r\n\t\r\n\t\t\t// if there is a collision, then snap to it\r\n\t\t\t*p_collisionPoint = feeler.GetPoint();\r\n\t\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\t\r\n}\r\n\r\n\r\nbool CMotionComponent::StickToGround()\r\n{\r\n\tif ( ( !m_col_dist_above ) && ( !m_col_dist_below ) )\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\tif ( m_point_stick_to_ground )\r\n\t{\r\n\t\t// standard stick to ground\r\n\t\t// (also need a car version,\r\n\t\t// which will be a separate component)\r\n\r\n\t\tMth::Vector v0, v1;\r\n\r\n\t\t// make sure our X vector is correct (got Z from the nav matrix...)\r\n\t\tGetObject()->m_matrix[ X ] = Mth::CrossProduct( GetObject()->m_matrix[ Y ], GetObject()->m_matrix[ Z ]);\r\n\t\tGetObject()->m_matrix[ X ].Normalize();\r\n\r\n\t\tv0.Set( 0.0f, FEET_TO_INCHES( fabs( m_col_dist_above ) ), 0.0f );\r\n\t\tv1.Set( 0.0f, -FEET_TO_INCHES( fabs( m_col_dist_below ) ), 0.0f );\r\n\r\n\t\tv0 += GetObject()->m_pos;\r\n\t\tv1 += GetObject()->m_pos;\r\n\r\n\t\t// get disatnce to ground\r\n\t\t// and snap the skater to it\r\n\r\n\t\tMth::Vector collision_point;\r\n\t\tif (s_do_collision_check(&v0, &v1, &collision_point, &m_last_triangle))\r\n\t\t{\r\n\t\t\tGetObject()->m_pos=collision_point;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// if it's a car, then it's big\r\n\t\tMth::Vector v0, v1, vectForward, vectLeft, leftCollidePoint, rightCollidePoint;\r\n\t\tbool leftCollision = false;\r\n\t\tbool rightCollision = false;\r\n\t\tCFeeler\t\tfeeler;\r\n\r\n\t\tGetObject()->m_matrix[ Y ].Set( 0.0f, 1.0f, 0.0f );\r\n\t\t// make sure our X vector is correct (got Y and Z from the nav matrix...)\r\n\t\tGetObject()->m_matrix[ X ] = Mth::CrossProduct( GetObject()->m_matrix[ Y ], GetObject()->m_matrix[ Z ]);\r\n\t\tGetObject()->m_matrix[ X ].Normalize();\r\n\r\n\t\tvectForward = GetObject()->m_matrix[ Z ] * FEET_TO_INCHES( 6.0f );\r\n\t\tvectLeft = GetObject()->m_matrix[ X ] * FEET_TO_INCHES( 2.5f );\r\n\r\n\t\tGetObject()->m_pos -= vectForward;\r\n\t\tGetObject()->m_pos += vectLeft;\r\n\r\n\t\tv0 = v1 = GetObject()->m_pos;\r\n\t\tv0[ Y ] += FEET_TO_INCHES( m_col_dist_above );\r\n\t\tv1[ Y ] -= FEET_TO_INCHES( m_col_dist_below );\r\n\r\n\t\t// find a collision point under the left rear:\r\n\t\tif (s_do_collision_check(&v0, &v1, &leftCollidePoint, &m_car_left_rear_last_triangle))\r\n\t\t{\r\n\t\t\tleftCollision = true;\r\n\t\t}\r\n\t\t\r\n\t\tGetObject()->m_pos -= vectLeft * 2;\r\n\r\n\t\tv0 = v1 = GetObject()->m_pos;\r\n\t\tv0[ Y ] += FEET_TO_INCHES( m_col_dist_above );\r\n\t\tv1[ Y ] -= FEET_TO_INCHES( m_col_dist_below );\r\n\r\n\t\t// find a collision point under the right rear:\r\n\t\tif (s_do_collision_check(&v0, &v1, &rightCollidePoint, &m_car_right_rear_last_triangle))\r\n\t\t{\r\n\t\t\trightCollision = true;\r\n\t\t\tif ( leftCollision )\r\n\t\t\t{\r\n\t\t\t\tGetObject()->m_matrix[ X ] = leftCollidePoint - rightCollidePoint;\r\n\t\t\t\tGetObject()->m_matrix[ X ].Normalize( );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tGetObject()->m_pos += vectForward * 2;\r\n\t\tGetObject()->m_pos += vectLeft;\r\n\r\n\t\tv0 = v1 = GetObject()->m_pos;\r\n\t\tv0[ Y ] += FEET_TO_INCHES( m_col_dist_above );\r\n\t\tv1[ Y ] -= FEET_TO_INCHES( m_col_dist_below );\r\n\r\n\t\tGetObject()->m_pos -= vectForward;\r\n\r\n\t\tMth::Vector mid_front_collide_point;\r\n\t\tif (s_do_collision_check(&v0, &v1, &mid_front_collide_point, &m_car_mid_front_last_triangle))\r\n\t\t{\r\n\t\t\tif ( rightCollision && leftCollision )\r\n\t\t\t{\r\n\t\t\t\tGetObject()->m_pos[ Y ] = leftCollidePoint[ Y ] + rightCollidePoint[ Y ];\r\n\t\t\t\tGetObject()->m_pos[ Y ] /= 2;\r\n\t\t\t\tGetObject()->m_pos[ Y ] += mid_front_collide_point.GetY();\r\n\t\t\t\tGetObject()->m_pos[ Y ] /= 2;\r\n\r\n\t\t\t\tMth::Vector heading;\r\n\r\n\t\t\t\theading = leftCollidePoint + rightCollidePoint;\r\n\t\t\t\theading /= 2;\r\n\t\t\t\theading -= mid_front_collide_point;\r\n\t\t\t\theading *= -1;\r\n\t\t\t\theading.Normalize( );\r\n\r\n\t\t\t\tGetObject()->m_matrix[ Z ] += heading;\r\n\t\t\t\tGetObject()->m_matrix[ Z ] /= 2;\r\n\r\n\t\t\t\tGetObject()->m_matrix[ Y ] = Mth::CrossProduct( GetObject()->m_matrix[ Z ], GetObject()->m_matrix[ X ] );\r\n\t\t\t\tGetObject()->m_matrix[ Y ].Normalize( );\r\n\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// (Mick) This assertion has been removed, as cars sometimes drive where the skater cannot go, and hence into no collision\t\t\r\n\t\t//\tDbg_MsgAssert( 0, ( \"StickToGround car %s was driving on an area with no collision\", Script::FindChecksumName(GetID()) ) );\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::GetDebugInfo( Script::CStruct* p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert( p_info, ( \"NULL p_info sent to CMotionComponent::GetDebugInfo\" ) );\r\n\tCBaseComponent::GetDebugInfo(p_info);\r\n\t\r\n\tp_info->AddChecksum( CRCD(0x9e6b250,\"m_movingobj_status\"), m_movingobj_status );\r\n\tp_info->AddChecksum( CRCD(0xe5dff85a,\"m_movingobj_flags\"), m_movingobj_flags );\r\n\tp_info->AddFloat( CRCD(0xc2d3b58d,\"m_moveto_speed\"), m_moveto_speed );\r\n\tp_info->AddFloat( CRCD(0x3a3ae81a,\"m_acceleration\"), m_acceleration );\r\n\tp_info->AddFloat( CRCD(0x4a2c5549,\"m_deceleration\"), m_deceleration );\r\n\tp_info->AddFloat( CRCD(0x472b8f9b,\"m_max_vel\"), m_max_vel );\r\n\tp_info->AddFloat( CRCD(0xc37e4e25,\"m_vel_z\"), m_vel_z );\r\n\tp_info->AddFloat( CRCD(0xcab44eaf,\"m_stop_dist\"), m_stop_dist );\r\n\r\n\t// p_info->AddFloat( \"m_col_dist_above\", m_col_dist_above );\r\n\t// p_info->AddFloat( \"m_col_dist_below\", m_col_dist_below );\r\n\t// p_info->AddVector( \"m_last_triangle_v0\", m_last_triangle_v0 );\r\n\t// p_info->AddVector( \"m_last_triangle_v1\", m_last_triangle_v1 );\r\n\t// p_info->AddVector( \"m_last_triangle_v2\", m_last_triangle_v2 );\r\n\t// p_info->AddVector( \"m_last_normal\", m_last_normal );\r\n\tp_info->AddInteger( CRCD(0xa13363b0,\"m_point_stick_to_ground\"), m_point_stick_to_ground );\r\n\t\r\n\tp_info->AddFloat( CRCD(0xac5b4824,\"m_moveto_dist\"), m_moveto_dist );\r\n\tp_info->AddFloat( CRCD(0x3e3570a6,\"m_moveto_dist_traveled\"), m_moveto_dist_traveled );\r\n\tp_info->AddFloat( CRCD(0x93e73df1,\"m_moveto_speed_target\"), m_moveto_speed_target );\r\n\tp_info->AddFloat( CRCD(0x6819fd8d,\"m_moveto_acceleration\"), m_moveto_acceleration );\t\r\n\t\r\n\tp_info->AddInteger( CRCD(0xd6d94326,\"m_moveto_node_num\"), m_moveto_node_num );\r\n\t\r\n\t// p_info->AddVector( \"m_turn_ang_target\", m_turn_ang_target );\r\n\t// p_info->AddVector( \"m_cur_turn_ang\", m_cur_turn_ang );\r\n\t// p_info->AddVector( \"m_turn_speed_target\", m_turn_speed_target );\r\n\tp_info->AddVector( CRCD(0x9d27cc70,\"m_turn_speed\"), m_turn_speed );\r\n\t// p_info->AddVector( \"m_delta_turn_speed\", m_delta_turn_speed );\r\n\t// p_info->AddVector( \"m_angular_friction\", m_angular_friction );\r\n\tp_info->AddVector( CRCD(0xfa4307e,\"m_orig_pos\"), m_orig_pos );\r\n\t\r\n\t// p_info->AddFloat( \"m_stop_dist_traveled\", m_stop_dist_traveled );\r\n\t// p_info->AddFloat( \"m_vel_z_start\", m_vel_z_start );\r\n\t// p_info->AddFloat( \"m_min_stop_vel\", m_min_stop_vel );\r\n\t\r\n\tp_info->AddVector( CRCD(0xc3e1cded,\"m_stored_pos\"), m_stored_pos );\r\n\tp_info->AddInteger( CRCD(0x56e54ee5,\"m_stored_node\"), m_stored_node );\r\n\t\r\n\t// CPathObjectTracker*\t\tmp_path_object_tracker;\r\n\t\r\n\t// Mth::SlerpInterpolator*\tmp_slerp;\r\n\t// p_info->AddFloat( \"m_rot_time_target\", m_rot_time_target );\r\n\tp_info->AddFloat( CRCD(0x622c6c9b,\"m_rot_time\"), m_rot_time );\r\n\t\r\n\tp_info->AddInteger( CRCD(0x80dd9065,\"m_start_node\"), m_start_node );\r\n\tp_info->AddInteger( CRCD(0xa80dc42,\"m_current_node\"), m_current_node );\r\n\t\r\n\tif (mp_pathOb)\r\n\t{\r\n\t\tScript::CStruct* p_pathOb_params = new Script::CStruct();\r\n\t\tmp_pathOb->GetDebugInfo( p_pathOb_params\t);\r\n\t\tp_info->AddStructure( CRCD(0x81270c1f,\"mp_pathOb\"), p_pathOb_params );\r\n\t\tdelete p_pathOb_params;\r\n\t}\t\r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCompositeObject* CMotionComponent::GetNextObjectOnPath( float range )\r\n{\r\n\tCCompositeObject* p_closest_ob=NULL;\r\n\r\n\tif ( mp_path_object_tracker )\r\n\t{\t\t\r\n\t\tconst CSmtPtr<CCompositeObject>* pp_object_list = mp_path_object_tracker->GetObjectList();\r\n\r\n\t\tfloat min_dist = 0.0f;\r\n\t\tfor (int i=0; i<CPathObjectTracker::MAX_OBJECTS_PER_PATH; ++i)\r\n\t\t{\r\n\t\t\tif (pp_object_list[i])\r\n\t\t\t{\r\n\t\t\t\tCCompositeObject* p_ob=pp_object_list[i].Convert();\r\n\t\r\n\t\t\t\tif (p_ob!=GetObject() && \r\n\t\t\t\t\tMth::DotProduct(GetObject()->m_matrix[Z],p_ob->GetMatrix()[Z]) >= 0.0f &&\r\n\t\t\t\t\tMth::DotProduct(GetObject()->m_matrix[Z],p_ob->GetPos()-GetObject()->GetPos()) >= 0.0f\r\n\t\t\t\t\t)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (GetMotionComponentFromObject(p_ob)->GetDestinationPathNode()==GetDestinationPathNode() &&\r\n\t\t\t\t\t\tGetMotionComponentFromObject(p_ob)->GetPreviousPathNode()!=GetPreviousPathNode())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Make vehicles on converging paths not collide, otherwise\r\n\t\t\t\t\t\t// a pile up happens at the start of the car paths in the school\r\n\t\t\t\t\t\t// Note: Actually, this didn't fix it ... might be a script bug?\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfloat d=Mth::Distance( GetObject()->GetPos(), p_ob->GetPos());\r\n\t\t\t\t\t\tif( d <= range )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif( !p_closest_ob || d < min_dist )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tmin_dist = d;\r\n\t\t\t\t\t\t\t\tp_closest_ob = p_ob;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn p_closest_ob;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nvoid CMotionComponent::FollowLeader( void )\r\n{   \r\n\tDbg_MsgAssert( mp_follow_ob,( \"Shouldn't be in follow-leader state without mp_follow_ob.\" ));\r\n\t\r\n\tmp_follow_ob->GetNewPathPointFromObjectBeingFollowed();\r\n\t\r\n\tfloat old_y = GetObject()->m_pos[Y];\r\n\tmp_follow_ob->CalculatePositionAndOrientation(&GetObject()->m_pos,&GetObject()->m_matrix);\r\n\tif (m_leave_y_unaffected_when_following_leader)\r\n\t{\r\n\t\tGetObject()->m_pos[Y]=old_y;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::FollowLeader_Init( Script::CStruct* pParams )\r\n{\r\n\tif (pParams->ContainsFlag(CRCD(0xd443a2bc,\"Off\")))\r\n\t{\r\n\t\tm_movingobj_status &= ~MOVINGOBJ_STATUS_FOLLOWING_LEADER;\r\n\t\tif (mp_follow_ob)\r\n\t\t{\r\n\t\t\tdelete mp_follow_ob;\r\n\t\t\tmp_follow_ob=NULL;\r\n\t\t}\r\n\t\treturn;\r\n\t}\t\t\r\n\t\t\r\n\tm_leave_y_unaffected_when_following_leader=pParams->ContainsFlag(\"LeaveYUnaffected\");\r\n\t\r\n\tm_movingobj_status |= MOVINGOBJ_STATUS_FOLLOWING_LEADER;\r\n\t\r\n\t// these can't coexist:\r\n\tm_movingobj_status &= ~MOVINGOBJ_STATUS_MOVETO;\r\n\r\n\t//\tGetMotionComponent()->m_movingobj_status &= ~MOVINGOBJ_STATUS_LOCKED_TO_OBJECT;\r\n\tObj::CLockObjComponent* pLockObjComponent = GetLockObjComponentFromObject(GetObject());\r\n\tpLockObjComponent->EnableLock( false );\r\n\r\n\tif ( !mp_follow_ob )\r\n\t{\r\n\t\tmp_follow_ob = new CFollowOb;\r\n\t}\t\r\n\tmp_follow_ob->Reset();\r\n\t\r\n\tfloat distance=0.0f;\r\n\tpParams->GetFloat(CRCD(0xe36d657e,\"Distance\"),&distance);\r\n\tmp_follow_ob->SetDistance(distance);\r\n\t\r\n\tuint32 name=0;\r\n\tpParams->GetChecksum(CRCD(0xa1dc81f9,\"Name\"),&name);\r\n\tmp_follow_ob->SetLeaderName(name);\r\n\t\r\n\tif (pParams->ContainsFlag(CRCD(0xe19e310a,\"OrientY\")))\r\n\t{\r\n\t\tmp_follow_ob->OrientY();\r\n\t}\t\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMotionComponent::DoJump( void )\r\n{\r\n\tMth::Vector new_pos;\r\n\r\n\t// Gfx::AddDebugLine( m_jump_start_pos, m_pos, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 1 );\r\n\tfloat distance = m_jump_speed * m_time + ( m_jump_gravity * 0.5f * m_time * m_time );\r\n\t// printf(\"m_jump_speed = %f, m_jump_gravity = %f\\n, m_jump_original_speed = %f, m_jump_heading = (%f, %f, %f)\\n\", m_jump_speed, m_jump_gravity, m_jump_original_speed, m_jump_heading[X], m_jump_heading[Y], m_jump_heading[Z]);\r\n\tnew_pos = GetObject()->m_pos;\r\n\tif ( m_jump_use_heading )\r\n\t{\t\t\r\n\t\t// first figure the pos if we stayed on our original heading\r\n\t\tnew_pos += ( m_jump_heading * m_jump_original_speed * m_time );\r\n\t\tnew_pos[Y] = GetObject()->m_pos[Y];\r\n\t}\r\n\tnew_pos[Y] += distance;\r\n\r\n\tm_jump_speed += m_jump_gravity * m_time;\r\n\r\n\t// do land checks if we're on our way down\r\n\tif ( distance < 0.0f )\r\n\t{\r\n\t\tif ( m_jump_use_land_height )\r\n\t\t{\r\n\t\t\tif ( new_pos[Y] < m_jump_land_height )\r\n\t\t\t{\r\n\t\t\t\tm_movingobj_status &= ~MOVINGOBJ_STATUS_JUMPING;\r\n\t\t\t\tnew_pos[Y] = m_jump_land_height;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// use collision checks\r\n\t\t\tCFeeler feeler;\r\n\t\t\tfeeler.m_start = new_pos + Mth::Vector( 0, m_jump_col_dist_above, 0 );\r\n\t\t\tfeeler.m_end = new_pos + Mth::Vector( 0, -m_jump_col_dist_below, 0 );\r\n\t\t\tif ( feeler.GetCollision() )\r\n\t\t\t{\r\n\t\t\t\tm_movingobj_status &= ~MOVINGOBJ_STATUS_JUMPING;\r\n\t\t\t\tif ( m_jump_start_pos[X] != GetObject()->m_pos[X] || m_jump_start_pos[Z] != GetObject()->m_pos[Z] )\r\n\t\t\t\t{\r\n\t\t\t\t\t// printf(\"StickToGround %s\\n\",Script::FindChecksumName(GetID()));\r\n\t\t\t\t\t// GetMotionComponent()->StickToGround();\r\n\t\t\t\t\t// m_jump_start_pos = m_pos;\r\n\t\t\t\t\r\n\t\t\t\t\t/*if ( new_pos[Y] < m_jump_start_pos[Y])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnew_pos[Y] = m_jump_start_pos[Y];\r\n\t\t\t\t\t\tGetMotionComponent()->m_movingobj_status &= ~MOVINGOBJ_STATUS_JUMPING;\r\n\t\t\t\t\t}*/\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// new_pos[Y] = m_jump_start_pos[Y];\r\n\t\t\t\t\t// GetMotionComponent()->m_movingobj_status &= ~MOVINGOBJ_STATUS_JUMPING;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tm_jump_pos = new_pos;\r\n}\r\n\r\n\r\n\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/motioncomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       MotionComponent.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  11/5/2002\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_MOTIONCOMPONENT_H__\r\n#define __COMPONENTS_MOTIONCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/math.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_MOTION CRCD(0xa015e17,\"Motion\")\r\n#define\t\tGetMotionComponent() ((Obj::CMotionComponent*)GetComponent(CRC_MOTION))\r\n#define\t\tGetMotionComponentFromObject(pObj) ((Obj::CMotionComponent*)(pObj)->GetComponent(CRC_MOTION))\r\n\r\nnamespace Mth\r\n{\r\n\tclass SlerpInterpolator;\r\n}\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CPathOb;\r\n\tclass CPathObjectTracker;\r\n    class CFollowOb;\r\n\r\n\r\n\tenum\r\n\t{\r\n\t\t// not used\r\n\t\t// MOVINGOBJ_STATUS_IDLE \t\t\t\t= 0,\r\n\r\n\t\tMOVINGOBJ_STATUS_ROTX \t\t\t\t= ( 1 << 0  ),\r\n\t\tMOVINGOBJ_STATUS_ROTY \t\t\t\t= ( 1 << 1  ),\r\n\t\tMOVINGOBJ_STATUS_ROTZ \t\t\t\t= ( 1 << 2  ),\r\n\t\tMOVINGOBJ_STATUS_MOVETO \t\t\t= ( 1 << 3  ),\r\n\t\tMOVINGOBJ_STATUS_ON_PATH \t\t\t= ( 1 << 4  ),\r\n\t\tMOVINGOBJ_STATUS_QUAT_ROT \t\t\t= ( 1 << 5  ),\r\n\t\tMOVINGOBJ_STATUS_LOOKAT \t\t\t= ( 1 << 6  ), // will be on in addition to rotx, y or z flags.\r\n\t\tMOVINGOBJ_STATUS_HOVERING \t\t\t= ( 1 << 7  ),\r\n\t\tMOVINGOBJ_STATUS_JUMPING  \t\t\t= ( 1 << 8  ),\r\n\t\tMOVINGOBJ_STATUS_FOLLOWING_LEADER\t= ( 1 << 9  ),\r\n\r\n\t\t// moved into lock obj component\r\n\t\t// MOVINGOBJ_STATUS_LOCKED_TO_OBJECT\t= ( 1 << 10 ),\r\n\r\n\t\t// don't do any other processing, until this flag is off:\r\n\t\t// wasn't being used...\r\n\t\t// MOVINGOBJ_STATUS_HIGH_LEVEL \t\t= ( 1 << 31 ), // running C-code on a high level.\r\n\t};\r\n\r\n\t#define MOVINGOBJ_STATUS_ROTXYZ ( MOVINGOBJ_STATUS_ROTX | MOVINGOBJ_STATUS_ROTY | MOVINGOBJ_STATUS_ROTZ )\r\n\t\r\n\t// movement flags (to be used with m_movingobj_flags)\r\n\t#define MOVINGOBJ_FLAG_STICK_TO_GROUND\t\t( 1 << 2 )\r\n\t#define MOVINGOBJ_FLAG_STOP_ALONG_PATH\t\t( 1 << 3 )\r\n\t#define MOVINGOBJ_FLAG_INDEPENDENT_HEADING\t( 1 << 4 )\r\n\t#define MOVINGOBJ_FLAG_CONST_ROTX\t\t\t( 1 << 5 )\r\n\t#define MOVINGOBJ_FLAG_CONST_ROTY\t\t\t( 1 << 6 )\r\n\t#define MOVINGOBJ_FLAG_CONST_ROTZ\t\t\t( 1 << 7 )\r\n\t#define MOVINGOBJ_FLAG_CONSTANT_HEIGHT\t\t( 1 << 8 )\r\n\t#define MOVINGOBJ_FLAG_RANDOM_PATH_MODE\t\t( 1 << 9 )\r\n\t#define MOVINGOBJ_FLAG_NO_PITCH_PLEASE\t\t( 1 << 10 )\r\n\r\n// Used to store the coords of the last triangle collided with,\r\n// so that it can be checked first next time as a collision speed optimization.\r\nstruct STriangle\r\n{\r\n\tMth::Vector mpVertices[3];\r\n\tvoid\tInit() {mpVertices[0].Set();mpVertices[1].Set();mpVertices[2].Set();}\r\n};\r\n\r\nclass CMotionComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CMotionComponent();\r\n    virtual ~CMotionComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tProcessWait( Script::CScript * pScript );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\t\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\n\tvirtual void\t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\t\r\npublic:\r\n\tCPathOb*\t\t\t\tGetPathOb();\r\n\tvoid\t\t\t\t\tReset();\r\n\tbool\t\t\t\t\tIsMoving( void );\r\n\tbool \t\t\t\t\tIsRotating( void );\r\n\r\n\tbool\t\t\t\t\tIsHovering();\r\n\tvoid\t\t\t\t\tGetHoverOrgPos( Mth::Vector *p_orgPos );\r\n\r\n\t// Added by Ken. If the object is following a path, this will return the node\r\n\t// index of the node it is heading towards. Returns -1 otherwise.\r\npublic:\r\n\tvoid\t\t\t\t\tDoPathPhysics();\r\n\tint\t\t\t\t\t\tGetDestinationPathNode();\r\n\tint\t\t\t\t\t\tGetPreviousPathNode();\r\n\tvoid\t\t\t\t\tEnsurePathobExists( CCompositeObject* pCompositeObj );\r\n\tCCompositeObject*   \tGetNextObjectOnPath(float range);\r\n\tvoid \t\t\t\t\tOrientToNode( Script::CStruct* pNodeData );\r\n\t\r\n\tvoid\t\t\t\t\tInitPath( int nodeNumber );\r\n\tvoid\t\t\t\t\tHitWaypoint( int nodeIndex );\r\n\tbool\t\t\t\t\tPickRandomWaypoint();\r\n\r\n\tbool\t\t\t\t\tLookAt_Init( Script::CStruct* pParams, const Mth::Vector& lookAtPos );\r\n\tvoid\t\t\t\t\tLookAtNodeLinked_Init( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvoid\t\t\t\t\tLookAtNode_Init( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvoid\t\t\t\t\tLookAtPos_Init( Script::CStruct* pParams, bool absolute );\r\n//\tbool\t\t\t\t\tLookAtObject_Init( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tMove_Init( Script::CStruct* pParams, Script::CScript* pScript, Mth::Vector pos, int nodeNum = -1 );\r\n\tvoid\t\t\t\t\tMoveToPos_Init( Script::CStruct* pParams, Script::CScript* pScript, bool absolute );\r\n\tvoid\t\t\t\t\tMoveToNode_Init( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvoid\t\t\t\t\tMoveToLink_Init( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvoid\t\t\t\t\tFollowPath_Init( Script::CStruct* pParams );\r\n\tvoid\t\t\t\t\tFollowPathLinked_Init( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvoid\t\t\t\t\tFollowStoredPath_Init( Script::CStruct* pParams );\r\n\tvoid\t\t\t\t\tFollowLeader_Init( Script::CStruct* pParams );\r\n\tvoid\t\t\t\t\tQuatRot_Init( Script::CStruct* pParams );\r\n\tvoid\t\t\t\t\tRotAxis_Init( Script::CStruct* pParams, Script::CScript* pScript, int whichAxis );\r\n\r\n\t// used for looking at a node or position...\r\n\tbool\t\t\t\t\tSetUpLookAtPos( const Mth::Vector& lookToPos, const Mth::Vector& currentPos, int headingAxis, int rotAxis, float threshold=0.0f );\r\n\tvoid\t\t\t\t\tQuatRot_Setup( Script::CStruct* pParams, const Mth::Matrix& rot );\r\n\tvoid\t\t\t\t\tSetCorrectRotationDirection( int rotAxis );\r\n\tvoid\t\t\t\t\tRotateToFacePos( const Mth::Vector pos );\r\n\t\r\n\tvoid\t\t\t\t\tRot( int rotAxis, float deltaRot );\r\n\tbool\t\t\t\t\tRotate( int rotAxis );\r\n\tvoid\t\t\t\t\tRotUpdate( void );\r\n\tbool\t\t\t\t\tMove( void );\r\n\tvoid\t\t\t\t\tFollowPath( void );\r\n\tvoid\t\t\t\t\tQuatRot( void );\r\n\tbool\t\t\t\t\tStickToGround();\r\n\tvoid\t\t\t\t\tUndoHover( void );\r\n\tvoid\t\t\t\t\tApplyHover( void );\r\npublic:\r\n\t// GJ:  Had to make this public during the transition,\r\n\t// because the moving objects need to access it\r\n\t// eventually, everything will be manipulated through\r\n\t// accessor functions\t\t\t\t\r\n    int\t\t\t\t\t\tm_movingobj_status;\r\n\tint\t\t\t\t\t\tm_movingobj_flags;\r\n\t\r\n\tfloat\t\t\t\t\tm_moveto_speed;\r\n\tfloat\t\t\t\t\tm_acceleration;\r\n\tfloat\t\t\t\t\tm_deceleration;\r\n\tfloat\t\t\t\t\tm_max_vel;\r\n\tfloat\t\t\t\t\tm_vel_z;\r\n\tfloat\t\t\t\t\tm_stop_dist;\r\n\r\n\t// when sticking to the ground, collision line length:\r\n\tfloat\t\t\t\t\tm_col_dist_above;\r\n\tfloat\t\t\t\t\tm_col_dist_below;\r\n\tSTriangle\t\t\t\tm_last_triangle;\r\n\tbool\t\t\t\t\tm_point_stick_to_ground;\r\n\t\r\n\tSTriangle\t\t\t\tm_car_left_rear_last_triangle;\r\n\tSTriangle\t\t\t\tm_car_right_rear_last_triangle;\r\n\tSTriangle\t\t\t\tm_car_mid_front_last_triangle;\r\n\r\n\t// A CPathObjectTracker keeps track of all the objects that are following a\r\n\t// particular path. Stored so that the object can un-register with the tracker\r\n\t// when it starts following a new path.\r\n\tCPathObjectTracker*\t\tmp_path_object_tracker;\r\nprotected:\r\n\tMth::Vector\t\t\t\tm_moveto_pos;\r\n\tfloat\t\t\t\t\tm_moveto_dist;\r\n\tfloat\t\t\t\t\tm_moveto_dist_traveled;\r\n//\tfloat\t\t\t\t\tm_moveto_speed;\t\t\t// TEMPORARILY PUBLIC\r\n\tfloat\t\t\t\t\tm_moveto_speed_target;\r\n\tfloat\t\t\t\t\tm_moveto_acceleration;\r\n\t\r\n\t// so that we can call SpawnObjScript or SwitchObjScript when we arrive...\r\n\tint\t\t\t\t\t\tm_moveto_node_num;\r\n\r\n\tMth::Vector\t\t\t\tm_turn_ang_target;\r\n\tMth::Vector\t\t\t\tm_cur_turn_ang;\r\n\tMth::Vector\t\t\t\tm_turn_speed_target;\r\n\tMth::Vector\t\t\t\tm_turn_speed;\r\n\tMth::Vector\t\t\t\tm_delta_turn_speed;\r\n\tMth::Vector\t\t\t\tm_angular_friction;\r\n\tMth::Vector\t\t\t\tm_orig_pos;\r\n\r\n\t// path traversal:\r\n//\tfloat\t\t\t\t\tm_acceleration;\t\t\t// TEMPORARILY PUBLIC\r\n//\tfloat\t\t\t\t\tm_deceleration;\t\t\t// TEMPORARILY PUBLIC\r\n//\tfloat\t\t\t\t\tm_max_vel;\t\t\t\t// TEMPORARILY PUBLIC\r\n//\tfloat\t\t\t\t\tm_vel_z;\t\t\t\t// TEMPORARILY PUBLIC\r\n//\tfloat\t\t\t\t\tm_stop_dist;        \t// TEMPORARILY PUBLIC\r\n\tfloat\t\t\t\t\tm_stop_dist_traveled;\r\n\tfloat\t\t\t\t\tm_vel_z_start;\r\n\tfloat\t\t\t\t\tm_min_stop_vel;\r\n\t\r\n\t// gotta remember where to return to when going to a higher level:\r\n\tMth::Vector\t\t\t\tm_stored_pos;\r\n\tint\t\t\t\t\t\tm_stored_node;\r\n\r\n\tfloat\t\t\t\t\tm_rot_time_target;\r\n\tfloat\t\t\t\t\tm_rot_time;\r\n\tMth::SlerpInterpolator*\tmp_slerp;\r\n\r\n\tfloat\t\t\t\t\tm_y_before_applying_hover;\r\n\tfloat\t\t\t\t\tm_hover_offset;\r\n\tfloat\t\t\t\t\tm_hover_amp;\r\n\tint\t\t\t\t\t\tm_hover_period;\r\n\r\n\tfloat\t\t\t\t\tm_time;\r\n\r\nprotected:\r\n\t// moved this down from CMovingObject\r\n\t// (information about the node that created this object)\r\n\tint\t\t\t\t\t\tm_start_node; \t// renamed, as we want to use it for path objs, but not for node identification\r\n\tint\t\t\t\t\t\tm_current_node;  // this may change if the object is moving... (needs to be at CMovingObject level for querying)\r\n\r\nprotected:\r\n\tCPathOb*\t\t\t\tmp_pathOb;\r\n\t\r\n// Mo stuff from MovingObject.h\t\t\r\n\t\t\r\n\t\tvoid\t\t\t\t\tFollowLeader( void );\r\n\t\t\r\n\t\t// Pointer to the follow ob, which contains all the info required to follow\r\n\t\t// an object on a path. Done this way so as to not use up memory for every instance\r\n\t\t// of a CMovingObject. (similar to CPathOb)\r\n\t\tCFollowOb*\t\t\t\tmp_follow_ob;\r\n\r\n\t\t// K: I think I should have put this in CFollowOb too?\r\n\t\tbool\t\t\t\t\tm_leave_y_unaffected_when_following_leader;\r\n\r\nprivate:\t\t\r\n\t\t\r\n\t\tvoid\t\t\t\t\tDoJump( void );\r\n\t\tfloat\t\t\t\t\tm_jump_speed;\r\n\t\tfloat\t\t\t\t\tm_jump_gravity;\r\n\t\tMth::Vector\t\t\t\tm_jump_heading;\r\n\t\tbool\t\t\t\t\tm_jump_use_heading;\r\n\t\tMth::Vector\t\t\t\tm_jump_pos;\r\n\t\tfloat\t\t\t\t\tm_jump_original_speed;\r\n\t\tfloat\t\t\t\t\tm_jump_col_dist_above;\r\n\t\tfloat\t\t\t\t\tm_jump_col_dist_below;\r\n\t\tfloat\t\t\t\t\tm_jump_y;\r\n\t\tbool\t\t\t\t\tm_jump_use_land_height;\r\n\t\tfloat\t\t\t\t\tm_jump_land_height;\r\n\t\t// The whole start pos is stored rather than just the y so that it knows whether \r\n\t\t// it needs to do another collision check once the jump has got back to the start y.\r\n\t\t// If the x or z has changed then it needs to do another collision check.\r\n\t\tMth::Vector\t \t\t  \tm_jump_start_pos;\r\n\r\n\t\r\n\t\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/rigidbodycomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       RigidBodyComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  1/22/3\r\n//****************************************************************************\r\n\r\n// An object component which dictates the motion of an object using an approximation of rigidbody physics.\r\n\r\n#include <gel/components/rigidbodycomponent.h>\r\n#include <gel/components/soundcomponent.h>\r\n\r\n#include <core/math/matrix.h>\r\n\r\n#include <gfx/nx.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/collision/collcache.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\nNx::CCollCache CRigidBodyComponent::s_collision_cache;\r\nbool CRigidBodyComponent::s_debug_lines_on = false;\r\nbool CRigidBodyComponent::s_draw_skater_collision_circles = false;\r\nfloat CRigidBodyComponent::s_skater_head_height;\r\nTmr::Time CRigidBodyComponent::s_collide_sound_allowed_time = 0;\r\nCRigidBodyComponent::SContactState CRigidBodyComponent::sp_contact_states [ CRigidBodyComponent::vRP_MAX_NUM_CONTACTS ];\r\n\r\n#ifdef __NOPT_DEBUG__\r\nbool CRigidBodyComponent::s_contact_states_in_use = false;\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CRigidBodyComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CRigidBodyComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCRigidBodyComponent::CRigidBodyComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_RIGIDBODY );\r\n\r\n\tmp_sound_component = NULL;\r\n\t\r\n\t// setup defaults\r\n\t\r\n\tm_const_acc = vRP_GRAVITATIONAL_ACCELERATION;\r\n\tm_mass_over_moment = vRP_DEFAULT_MASS_OVER_MOMENT;\r\n\tm_coeff_restitution = vRP_DEFAULT_COEFF_RESTITUTION;\r\n\tm_coeff_friction = vRP_DEFAULT_COEFF_FRICTION;\r\n\tm_spring_const = vRP_DEFAULT_SPRING_CONST;\r\n\tm_linear_velocity_sleep_point_sqr = vRP_DEFAULT_LINEAR_VELOCITY_SLEEP_POINT * vRP_DEFAULT_LINEAR_VELOCITY_SLEEP_POINT;\r\n\tm_angular_velocity_sleep_point_sqr = vRP_DEFAULT_ANGULAR_VELOCITY_SLEEP_POINT * vRP_DEFAULT_ANGULAR_VELOCITY_SLEEP_POINT;\r\n\tm_skater_collision_impulse_factor = vRP_DEFAULT_SKATER_COLLISION_IMPULSE_FACTOR;\r\n\tm_skater_collision_rotation_factor = vRP_DEFAULT_SKATER_COLLISION_ROTATION_FACTOR;\r\n\tm_skater_collision_radius = vRP_DEFAULT_SKATER_COLLISION_RADIUS;\r\n\tm_skater_collision_application_radius = vRP_DEFAULT_SKATER_COLLISION_APPLICATION_RADIUS;\r\n\tm_cos_skater_collision_assent = cosf(DEGREES_TO_RADIANS(vRP_DEFAULT_SKATER_COLLISION_ASSENT));\r\n\tm_sin_skater_collision_assent = sinf(DEGREES_TO_RADIANS(vRP_DEFAULT_SKATER_COLLISION_ASSENT));\r\n\tm_ignore_skater_duration = vRP_DEFAULT_IGNORE_SKATER_DURATION;\r\n\tm_model_offset.Set(0.0f, 0.0f, 0.0f);\r\n\t\r\n\tm_num_contacts = 0;\r\n\t\r\n\tm_script_names.collide = m_script_names.bounce = m_script_names.settle = m_script_names.stuck = 0;\r\n\tmp_script_params = NULL;\r\n\t\r\n\tm_sound_setup.collide_sound = m_sound_setup.bounce_sound = NULL;\r\n\tm_sound_setup.collide_mute_delay = vRP_DEFAULT_COLLIDE_MUTE_DELAY;\r\n\tm_sound_setup.global_collide_mute_delay = vRP_DEFAULT_GLOBAL_COLLIDE_MUTE_DELAY;\r\n\tm_sound_setup.bounce_velocity_callback_threshold = vRP_DEFAULT_BOUNCE_VELOCITY_CALLBACK_THRESHOLD;\r\n\tm_sound_setup.bounce_velocity_full_speed = vRP_DEFAULT_BOUNCE_VELOCITY_FULL_SPEED;\r\n\t\r\n\tm_collide_sound_allowed_time = 0;\r\n\t\r\n\tm_die_countdown = -1.0f;\r\n\t\r\n\tmp_contacts = NULL;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tm_sound_type_id = 0;\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCRigidBodyComponent::~CRigidBodyComponent()\r\n{\r\n\tdelete [] mp_contacts;\r\n\tdelete mp_script_params;\r\n\tdelete m_sound_setup.bounce_sound;\r\n\tdelete m_sound_setup.collide_sound;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// NOTE: right now rigidbodies ignore moving collidables; if we want to change this, we should account for the moving collidables' velocity\r\n\t// in the collision resolution code\r\n\t// NOTE: probably want to add some small random rotation when the skater hits the object; two reasons; one, when you hit a line of cones, right\r\n\t// now it seems too orderly; two, when you push a cone ahead of you, the cone's dynamics should be more jerky and less smooth\r\n\t\r\n\t// NOTE: don't make any contacts within a foot of the center of mass or the object is in danger of falling through the ground\r\n\r\n\t// IDEA: for a skateboard rigidbody, have four of the contacts only feel friction parallel to the wheel's axis\r\n\r\n\t// potential optimization; collision detect only every other frame, unless the last-ditch feeler says to do it this frame\r\n\r\n\tm_state = ASLEEP;\r\n\r\n\tm_vel.Set(0.0f, 0.0f, 0.0f);\r\n\tm_rotvel.Set(0.0f, 0.0f, 0.0f);\r\n\t\r\n\tm_matrix.Ident();\r\n\t\r\n\tm_pos = GetObject()->GetPos();\r\n\t\r\n\tm_orientation = GetObject()->GetMatrix();\r\n\tm_orientation.Normalize();\r\n\tm_orientation.GetMatrix(m_matrix);\r\n\t\r\n\tpParams->GetVector(CRCD(0xc4c809e, \"vel\"), &m_vel);\r\n\t\r\n\tpParams->GetVector(CRCD(0xfb1a83b2, \"rotvel\"), &m_rotvel);\r\n\r\n\tpParams->GetVector(CRCD(0x737612c6, \"center_of_mass\"), &m_center_of_mass);\r\n\r\n\tpParams->GetFloat(CRCD(0x6fae5c9a, \"const_acc\"), &m_const_acc);\r\n\r\n\tpParams->GetFloat(CRCD(0x60b4860d, \"coeff_restitution\"), &m_coeff_restitution);\r\n\r\n\tpParams->GetFloat(CRCD(0xf9d75930, \"coeff_friction\"), &m_coeff_friction);\r\n\t\r\n\tpParams->GetFloat(CRCD(0xf1ecb30f, \"spring_const\"), &m_spring_const);\r\n\r\n\tif (pParams->ContainsComponentNamed(CRCD(0xc11e4dd8, \"linear_velocity_sleep_point\")))\r\n\t{\r\n\t\tpParams->GetFloat(CRCD(0xc11e4dd8, \"linear_velocity_sleep_point\"), &m_linear_velocity_sleep_point_sqr);\r\n\t\tm_linear_velocity_sleep_point_sqr *= m_linear_velocity_sleep_point_sqr;\r\n\t}\r\n\r\n\tif (pParams->ContainsComponentNamed(CRCD(0xa457ece3, \"angular_velocity_sleep_point\")))\r\n\t{\r\n\t\tpParams->GetFloat(CRCD(0xa457ece3, \"angular_velocity_sleep_point\"), &m_angular_velocity_sleep_point_sqr);\r\n\t\tm_angular_velocity_sleep_point_sqr *= m_angular_velocity_sleep_point_sqr;\r\n\t}\r\n\r\n\tpParams->GetFloat(CRCD(0x3390d1e5, \"skater_collision_impulse_factor\"), &m_skater_collision_impulse_factor);\r\n\t\r\n\tpParams->GetFloat(CRCD(0x5a18f61f, \"skater_collision_rotation_factor\"), &m_skater_collision_rotation_factor);\r\n\r\n\tpParams->GetFloat(CRCD(0x85f112c1, \"skater_collision_radius\"), &m_skater_collision_radius);\r\n\r\n\tpParams->GetFloat(CRCD(0x8ab2db68, \"skater_collision_application_radius\"), &m_skater_collision_application_radius);\r\n\r\n\tif (pParams->ContainsComponentNamed(CRCD(0xe9156e6d, \"skater_collision_assent\")))\r\n\t{\r\n\t\tfloat skater_collision_assent;\r\n\t\tpParams->GetFloat(CRCD(0xe9156e6d, \"skater_collision_assent\"), &skater_collision_assent);\r\n\t\tm_cos_skater_collision_assent = cosf(DEGREES_TO_RADIANS(skater_collision_assent));\r\n\t\tm_sin_skater_collision_assent = sinf(DEGREES_TO_RADIANS(skater_collision_assent));\r\n\t}\r\n\r\n\tpParams->GetFloat(CRCD(0x1f4d0ca5, \"ignore_skater_duration\"), &m_ignore_skater_duration);\r\n\t\r\n\tpParams->GetChecksum(CRCD(0x58cdc0f0, \"CollideScript\"), &m_script_names.collide);\r\n\tpParams->GetChecksum(CRCD(0x2d075f90, \"BounceScript\"), &m_script_names.bounce);\r\n\tpParams->GetChecksum(CRCD(0x571917fa, \"SettleScript\"), &m_script_names.settle);\r\n\tpParams->GetChecksum(CRCD(0xccb84047, \"StuckScript\"), &m_script_names.stuck);\r\n\t\r\n\tif (pParams->ContainsComponentNamed(CRCD(0xdd85bda, \"CallbackParams\")))\r\n\t{\r\n\t\tScript::CStruct* p_struct;\r\n\t\tpParams->GetStructure(CRCD(0xdd85bda, \"CallbackParams\"), &p_struct, Script::ASSERT);\r\n\t\t\r\n\t\tmp_script_params = new Script::CStruct;\r\n\t\t*mp_script_params += *p_struct;\r\n\t}\r\n\t\r\n\t// get sound setup\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x94956e48, \"SoundType\")))\r\n\t{\r\n\t\tuint32 sound_type_id;\r\n\t\tpParams->GetChecksum(CRCD(0x94956e48, \"SoundType\"), &sound_type_id, Script::ASSERT);\r\n\t\t\r\n\t\tget_sound_setup(sound_type_id);\r\n\t\t\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tm_sound_type_id = sound_type_id;\r\n\t\t#endif\r\n\t}\r\n\t\r\n\tm_flags.Set(DIE_UPON_SLEEP, pParams->ContainsFlag(CRCD(0x5e51924f, \"DieUponSettling\")));\r\n\r\n\t// there are currently two ways to setup the contact points; either you pass them in as an array of offsets from the center of mass\r\n\t// or you specify a generic geometry and pass parameters to that geometry\r\n\t\r\n\tEObjectGeometryType object_geometry = NO_GEOMETRY;\r\n\tif (m_num_contacts == 0)\r\n\t{\r\n\t\tobject_geometry = BOX;\r\n\t}\r\n\t\r\n\tif (pParams->ContainsFlag(CRCD(0xf756b7c5, \"box\")))\r\n\t{\r\n\t\tobject_geometry = BOX;\r\n\t}\r\n\telse if (pParams->ContainsFlag(CRCD(0x1cb1a2b6, \"pyramid\")))\r\n\t{\r\n\t\tobject_geometry\t= PYRAMID;\r\n\t}\r\n\telse if (pParams->ContainsFlag(CRCD(0x64fba415, \"cylinder\")))\r\n\t{\r\n\t\tobject_geometry\t= CYLINDER;\r\n\t}\r\n\telse if (pParams->ContainsFlag(CRCD(0x20689278, \"triangle\")))\r\n\t{\r\n\t\tobject_geometry\t= TRIANGLE;\r\n\t}\r\n\r\n\t// setup contacts using an array\r\n\tif (pParams->ContainsComponentNamed(CRCD(0xccbfea8c, \"contacts\")))\r\n\t{\r\n\t\tScript::CArray* p_array;\r\n\t\tpParams->GetArray(CRCD(0xccbfea8c, \"contacts\"), &p_array);\r\n\t\tsetup_contacts_from_array(p_array);\r\n\t\tobject_geometry = NO_GEOMETRY;\r\n\t}\r\n\t\r\n\t// setup contacts using a generic geometry\r\n\tswitch (object_geometry)\r\n\t{\r\n\t\t// a rectangular prism with contacts at each corner\r\n\t\tcase BOX:\r\n\t\t{\r\n\t\t\tMth::Vector top_half_dimensions(32.0f, 32.0f, 16.0f);\r\n\t\t\tMth::Vector bottom_half_dimensions;\r\n\r\n\t\t\tpParams->GetVector(\"dimensions\", &top_half_dimensions);\r\n\t\t\tbottom_half_dimensions = top_half_dimensions;\r\n\t\t\tpParams->GetVector(\"top_dimensions\", &top_half_dimensions);\r\n\t\t\tpParams->GetVector(\"bottom_dimensions\", &bottom_half_dimensions);\r\n\t\t\ttop_half_dimensions /= 2.0f;\r\n\t\t\tbottom_half_dimensions /= 2.0f;\r\n\r\n\t\t\tsetup_contacts_as_box(top_half_dimensions, bottom_half_dimensions);\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// a pyramid with contacts at each corner along the bottom and one on the top\r\n\t\tcase PYRAMID:\r\n\t\t{\r\n\t\t\tfloat half_height = 42.0f;\r\n\t\t\tfloat half_depth = 32.0f;\r\n\t\t\t\r\n\t\t\tpParams->GetFloat(CRCD(0xab21af0,\"height\"), &half_height);\r\n\t\t\tpParams->GetFloat(CRCD(0x55ce396,\"depth\"), &half_depth);\r\n\t\t\thalf_height /= 2.0f;\r\n\t\t\thalf_depth /= 2.0f;\r\n\t\t\t\r\n\t\t\tsetup_contacts_as_pyramid(half_height, half_depth);\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// a cylinder with six contacts around the top and bottom\r\n\t\tcase CYLINDER:\r\n\t\t{\r\n\t\t\tfloat top_radius = 12.0f;\r\n\t\t\tfloat bottom_radius;\r\n\t\t\tfloat half_height = 60.0f;\r\n\t\t\tint edges = 6;\r\n\t\t\t\r\n\t\t\tpParams->GetFloat(CRCD(0xc48391a5,\"radius\"), &top_radius);\r\n\t\t\tbottom_radius = top_radius;\r\n\t\t\t\r\n\t\t\tpParams->GetFloat(CRCD(0x937e3b29,\"top_radius\"), &top_radius);\r\n\t\t\tpParams->GetFloat(CRCD(0xe2ac8c3a,\"bottom_radius\"), &bottom_radius);\r\n\t\t\tpParams->GetFloat(CRCD(0xab21af0,\"height\"), &half_height);\r\n\t\t\tpParams->GetInteger(CRCD(0x4055f24a,\"edges\"), &edges);\r\n\t\t\thalf_height /= 2.0f;\r\n\t\t\t\r\n\t\t\tsetup_contacts_as_cylinder(top_radius, bottom_radius, half_height, edges);\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// a triangle with three contacts on the left and right\r\n\t\tcase TRIANGLE:\r\n\t\t{\r\n\t\t\tMth::Vector half_dimensions(32.0f, 32.0f, 16.0f);\r\n\t\t\t\r\n\t\t\tpParams->GetVector(CRCD(0x1d82745a, \"dimensions\"), &half_dimensions);\r\n\t\t\thalf_dimensions /= 2.0f;\r\n\t\t\t\r\n\t\t\tsetup_contacts_as_triangle(half_dimensions);\r\n\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// don't use a generic geometry\r\n\t\tcase NO_GEOMETRY:\r\n\t\t\tDbg_MsgAssert(m_num_contacts, (\"Contact geometry not setup for rigidbody\"));\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\t// setup directional friction\r\n\tif (pParams->ContainsComponentNamed(CRCD(0xc35cac0d, \"directed_friction\")))\r\n\t{\r\n\t\tScript::CArray* p_array;\r\n\t\tpParams->GetArray(CRCD(0xc35cac0d, \"directed_friction\"), &p_array);\r\n\t\t\r\n\t\tDbg_MsgAssert(p_array->GetSize() == m_num_contacts, (\"Array of directed friction specifications must equal the number of contacts\"));\r\n\t\t\r\n\t\tfor (int n = p_array->GetSize(); n--; )\r\n\t\t{\r\n\t\t\tScript::CStruct* m_struct = p_array->GetStructure(n);\r\n\t\t\tif (m_struct->ContainsComponentNamed(CRCD(0x806fff30, \"none\")))\r\n\t\t\t{\r\n\t\t\t\tmp_contacts[n].directed_friction = false;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmp_contacts[n].directed_friction = true;\r\n\t\t\t\tm_struct->GetVector(NO_NAME, &mp_contacts[n].friction_direction, Script::ASSERT);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\t\t \t\r\n\t// adjust contacts based on extra angles\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x17b93077, \"rotate_contacts\")))\r\n\t{\r\n\t\tMth::Vector angles;\r\n\t\tpParams->GetVector(CRCD(0x17b93077, \"rotate_contacts\"), &angles, Script::ASSERT);\r\n\t\tMth::Matrix matrix;\r\n\t\tmatrix.SetFromAngles(angles);\r\n\t\t\r\n\t\tfor (int n = m_num_contacts; n--; )\r\n\t\t{\r\n\t\t\tmp_contacts[n].p = matrix.Rotate(mp_contacts[n].p);\r\n\t\t}\r\n\t\t\t\t }\r\n\r\n\t// adjust contacts based on node array angles\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x9d2d0915, \"Angles\")))\r\n\t{\r\n\t\tMth::Vector angles;\r\n\t\tSkateScript::GetAngles(pParams, &angles);\r\n\t\tMth::Matrix matrix;\r\n\t\tmatrix.SetFromAngles(angles);\r\n\t\t\r\n\t\tfor (int n = m_num_contacts; n--; )\r\n\t\t{\r\n\t\t\tmp_contacts[n].p = matrix.Rotate(mp_contacts[n].p);\r\n\t\t}\r\n\t}\r\n\t\r\n\t// setup model offset\r\n\tMth::Vector center_of_mass(0.0f, 0.0f, 0.0f);\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x737612c6, \"center_of_mass\")))\r\n\t{\r\n\t\tif (pParams->ContainsComponentNamed(CRCD(0x737612c6, \"center_of_mass\")))\r\n\t\t{\r\n\t\t\tpParams->GetVector(CRCD(0x737612c6, \"center_of_mass\"), &center_of_mass);\r\n\t\t}\r\n\t}\r\n\t\t\r\n\t// if not set (or set to default), calculate the center of mass\r\n\tif (center_of_mass[X] == 0.0f && center_of_mass[Y] == 0.0f && center_of_mass[Z] == 0.0f);\r\n\t{\r\n\t\tfor (int n = m_num_contacts; n--; )\r\n\t\t{\r\n\t\t\tcenter_of_mass += mp_contacts[n].p;\r\n\t\t}\r\n\t\tcenter_of_mass *= (1.0f / m_num_contacts);\r\n\t}\r\n\t\r\n\tm_model_offset = -center_of_mass;\r\n\tfor (int n = m_num_contacts; n--; )\r\n\t{\r\n\t\tmp_contacts[n].p -= center_of_mass;\r\n\t}\r\n\t\r\n\t\r\n\tif (!pParams->GetFloat(CRCD(0x967cd3ae, \"mass_over_moment\"), &m_mass_over_moment))\r\n\t{\r\n\t\t// calculate an appropriate mass over moment adjustment; otherwise, you can get some really weird behavior\r\n\t\tfloat max_dist = 0.0f;\r\n\t\tfor (int n = m_num_contacts; n--; )\r\n\t\t{\r\n\t\t\tmax_dist = Mth::Max(max_dist, mp_contacts[n].p.Length());\r\n\t\t}\r\n\t\tif (max_dist > 30.0f)\r\n\t\t{\r\n\t\t\tm_mass_over_moment /= Mth::Sqr((max_dist / 30.0f));\r\n\t\t}\r\n\t}\r\n\t\r\n\t// setup static variables\r\n\ts_skater_head_height = GetPhysicsFloat(CRCD(0x542cf0c7, \"Skater_default_head_height\"));\r\n\r\n\t// determine the largest feeler extent; used with the collision cache system\r\n\tm_largest_contact_extent = 0.0f;\r\n\tfor (int n = m_num_contacts; n--; )\r\n\t{\r\n\t\tSContact& contact = mp_contacts[n];\r\n\r\n\t\tfloat contact_extent_sqr = contact.p.LengthSqr();\r\n\t\tif (contact_extent_sqr > m_largest_contact_extent)\r\n\t\t{\r\n\t\t\tm_largest_contact_extent = contact_extent_sqr;\r\n\t\t}\r\n\t}\r\n\tm_largest_contact_extent = sqrtf(m_largest_contact_extent) + 1.0f;\r\n\r\n\tm_ignore_skater_countdown = 0.0f;\r\n\t\r\n\tm_pos -= m_matrix.Rotate(m_model_offset);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::Finalize()\r\n{\r\n\tmp_sound_component = GetSoundComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_sound_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::Update()\r\n{\r\n\t#ifdef __NOPT_DEBUG__\r\n\tDbg_MsgAssert(!s_contact_states_in_use, (\"Two CRigidBodyComponents updating simultaneously\"));\r\n\ts_contact_states_in_use = true;\r\n\t#endif\r\n\t\r\n\tfloat full_time_step = Tmr::FrameLength();\r\n\t\r\n\tsetup_contact_states();\r\n\t\r\n\t// only check for skater collisions if we haven't collided with the skater recently; this insures that the stupid skater doesn't cram us\r\n\t// into corners and the like\r\n\tif (m_ignore_skater_countdown > 0.0f)\r\n\t{\r\n\t\tm_ignore_skater_countdown -= full_time_step;\r\n\t}\r\n\telse if (!m_flags.Test(PLAYER_COLLISION_DISABLED))\r\n\t{\r\n\t\thandle_skater_collisions();\r\n\t}\r\n\t\r\n\tif (m_die_countdown >= 0.0f)\r\n\t{\r\n\t\tif (m_die_countdown <= full_time_step)\r\n\t\t{\r\n\t\t\tGetObject()->MarkAsDead();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_die_countdown -= full_time_step;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// if we are asleep\r\n\tif (m_state == ASLEEP)\r\n\t{\r\n\t\tGetObject()->SetDisplayMatrix(m_matrix);\r\n\r\n\t\tif (s_debug_lines_on)\r\n\t\t{\r\n\t\t\tdraw_debug_lines();\r\n\t\t}\r\n\r\n\t\t// do just about nothing\r\n\t\t\t\r\n\t\t#ifdef __NOPT_DEBUG__\r\n\t\ts_contact_states_in_use = false;\r\n\t\t#endif\r\n\r\n\t\treturn;\r\n\t}\r\n\r\n\tint main_update_loop_count = 0;\r\n\tbool last_ditch_collision = false;\r\n\tfloat remaining_time_step = full_time_step;\r\n\tdo {\r\n\t\tfloat time_step = remaining_time_step;\r\n\r\n\t\t// send a feeler from object's center of mass to our new center of mass; most collisions will not be caught in this manner;\r\n\t\t// this is a last-ditch feeler to insure that we don't fly through objects at high speeds\r\n\t\tCFeeler feeler;\r\n\t\tfeeler.m_start = m_pos;\r\n\t\tfeeler.m_end = m_pos + time_step * m_vel;\r\n\t\tfeeler.m_end[Y] += 0.5f * time_step * time_step * m_const_acc;\r\n\r\n\t\tlast_ditch_collision = feeler.GetCollision(false);\r\n\t\r\n\t\t// if we have such a collision, move only to it\r\n\t\tif (last_ditch_collision)\r\n\t\t{\r\n\t\t\ttime_step = (feeler.GetDist() * feeler.Length() - 6.0f) / m_vel.Length();\r\n\t\t\tif (time_step < 0.0f)\r\n\t\t\t{\r\n\t\t\t\ttime_step = 0.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t\tupdate_dynamic_state(time_step);\r\n\r\n\t\t// we do a very simple collision\r\n\t\tif (last_ditch_collision)\r\n\t\t{\r\n\t\t\tm_vel -= (1.0f + m_coeff_restitution) * Mth::DotProduct(m_vel, feeler.GetNormal()) * feeler.GetNormal();\r\n\t\t}\r\n\r\n\t\tremaining_time_step -= time_step;\r\n\r\n\t\t// make sure we're not in an infinite loop; a weirdly hanging box is better than a frozen game\r\n\t\tif (++main_update_loop_count == 5)\r\n\t\t{\r\n\t\t\tMESSAGE(\"too many last-ditch contacts in a single frame; going to sleep\");\r\n\t\t\tsleep();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t} while (last_ditch_collision);\r\n\t\r\n\tif (detect_collisions())\r\n\t{\r\n\t\tresolve_collisions();\r\n\t}\r\n\r\n\tconsider_sleeping();\r\n\r\n\t// if we've gotten here, we need to update the object\r\n\t\r\n\tGetObject()->SetPos(m_pos + m_matrix.Rotate(m_model_offset));\r\n\t\r\n\tGetObject()->SetMatrix(m_matrix);\r\n\tGetObject()->SetDisplayMatrix(m_matrix);\r\n\t\r\n\tGetObject()->SetVel(m_vel);\r\n\r\n\tif (s_debug_lines_on)\r\n\t{\r\n\t\tdraw_debug_lines();\r\n\t}\r\n\t\r\n\t#ifdef __NOPT_DEBUG__\r\n\ts_contact_states_in_use = false;\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CRigidBodyComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | RigidBody_IgnoreSkater | rigidbody ignores the skater for a given duration\r\n        // @uparm 0.0 | duration (defaults to seconds)\r\n        // @flag frames | time is given in frames\r\n\t\tcase CRCC(0xcc12cf87, \"RigidBody_IgnoreSkater\"):\r\n\t\t{\r\n\t\t\tpParams->GetFloat(NO_NAME, &m_ignore_skater_countdown, Script::ASSERT);\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0x19176c5, \"frames\")) || pParams->ContainsFlag(CRCD(0x4a07c332, \"frame\")))\r\n\t\t\t{\r\n\t\t\t\tm_ignore_skater_countdown *= (1.0f / 60.0f);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | RigidBody_Wake | wakes up the rigidbody\r\n\t\tcase CRCC(0x9599c10f, \"RigidBody_Wake\"):\r\n\t\t\twake();\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | RigidBody_Sleep | puts the rigidbody to sleep\r\n\t\tcase CRCC(0xcd5ba67b, \"RigidBody_Sleep\"):\r\n\t\t\tsleep();\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | RigidBody_Kick | wakes the rigidbody with a kick\r\n\t\tcase CRCC(0xae24df9f, \"RigidBody_Kick\"):\r\n\t\t{\r\n\t\t\tMth::Vector v;\r\n\t\t\tif (pParams->GetVector(CRCD(0xc4c809e, \"vel\"), &v))\r\n\t\t\t{\r\n\t\t\t\tGetObject()->SetVel(m_vel += v);\r\n\t\t\t}\r\n\t\t\tif (pParams->GetVector(CRCD(0xfb1a83b2, \"rotvel\"), &v))\r\n\t\t\t{\r\n\t\t\t\tm_rotvel += v;\r\n\t\t\t}\r\n\t\t\tif (pParams->GetVector(CRCD(0x7f261953, \"pos\"), &v))\r\n\t\t\t{\r\n\t\t\t\tGetObject()->SetPos(m_pos += v);\r\n\t\t\t}\r\n\t\t\twake();\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script : RigidBody_Reset | reset any parameters of the rigidbody\r\n\t\tcase CRCC(0x92f5db9a, \"RigidBody_Reset\"):\r\n\t\t\tInitFromStructure(pParams);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script : RigidBody_DisablePlayerCollision\r\n\t\tcase CRCC(0xa2bbb3a, \"RigidBody_DisablePlayerCollision\"):\r\n\t\t\tm_flags.Set(PLAYER_COLLISION_DISABLED);\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script : RigidBody_EnablePlayerCollision\r\n\t\tcase CRCC(0x49f44585, \"RigidBody_EnablePlayerCollision\"):\r\n\t\t\tm_flags.Clear(PLAYER_COLLISION_DISABLED);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script : RigidBody_EnablePlayerCollision\r\n\t\tcase CRCC(0x949be8a9, \"RigidBody_MatchVelocityTo\"):\r\n\t\t{\r\n\t\t\tScript::CComponent* p_component = pParams->GetNextComponent(NULL);\r\n\t\t\tDbg_MsgAssert(p_component->mType == ESYMBOLTYPE_NAME, (\"RigidBody_MatchVelocityTo requires an object name as its first parameter\"));\r\n\t\t\tCCompositeObject* p_composite_object = static_cast< CCompositeObject* >(CCompositeObjectManager::Instance()->GetObjectByID(p_component->mChecksum));\r\n\t\t\tDbg_MsgAssert(p_composite_object, (\"RigidBody_MatchVelocityTo requires a composite object name as its first parameter\"));\r\n\t\t\t\r\n\t\t\tbool apply_random_adjustment = pParams->ContainsFlag(CRCD(0x8ace8a0f, \"ApplyRandomAdjustment\"));\r\n\t\t\t\r\n\t\t\tm_vel = p_composite_object->m_vel;\r\n\t\t\tif (apply_random_adjustment)\r\n\t\t\t{\r\n\t\t\t\tm_vel *= 1.0f + Mth::PlusOrMinus(0.4f);\r\n\t\t\t}\r\n\t\t\tGetObject()->SetVel(m_vel);\r\n\t\t\t\r\n\t\t\tif (m_state == ASLEEP && Mth::Abs(m_vel[Y]) < 1.0f)\r\n\t\t\t{\r\n\t\t\t\tm_vel[Y] = 1.0f;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// use the rotational velocity also, if it's a rigidbody\r\n\t\t\tCRigidBodyComponent* p_rigid_body_component = GetRigidBodyComponentFromObject(p_composite_object);\r\n\t\t\tif (p_rigid_body_component)\r\n\t\t\t{\r\n\t\t\t\tm_rotvel = p_rigid_body_component->m_rotvel;\r\n\t\t\t\tif (apply_random_adjustment)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_rotvel *= 1.0f * Mth::PlusOrMinus(0.4f);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\twake();\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info, (\"NULL p_info sent to CRigidBodyComponent::GetDebugInfo\"));\r\n\r\n\tuint32 state_checksums[] =\r\n\t{\r\n\t\tCRCD(0x4484b712, \"ASLEEP\"), CRCD(0x99a34896, \"AWAKE\")\r\n\t};\r\n\tp_info->AddChecksum(\"m_state\", state_checksums[m_state]);\r\n\r\n\tp_info->AddFloat(\"m_orientation\", m_orientation.GetScalar());\r\n\tp_info->AddVector(\"m_orientation\", m_orientation.GetVector());\r\n\r\n\tp_info->AddVector(\"m_vel\", m_vel);\r\n\r\n\tp_info->AddVector(\"m_rotvel\", m_rotvel);\r\n\r\n\tp_info->AddFloat(\"m_const_acc\", m_const_acc);\r\n\r\n\tp_info->AddFloat(\"m_mass_over_moment\", m_mass_over_moment);\r\n\r\n\tp_info->AddFloat(\"m_coeff_restitution\", m_coeff_restitution);\r\n\r\n\tp_info->AddFloat(\"m_coeff_friction\", m_coeff_friction);\r\n\t\r\n\tp_info->AddFloat(\"m_spring_const\", m_spring_const);\r\n\r\n\tp_info->AddFloat(\"m_skater_collision_impulse_factor\", m_skater_collision_impulse_factor);\r\n\t\r\n\tp_info->AddFloat(\"m_skater_collision_rotation_factor\", m_skater_collision_rotation_factor);\r\n\t\r\n\tp_info->AddFloat(\"m_skater_collision_radius\", m_skater_collision_radius);\r\n\r\n    p_info->AddFloat(\"m_num_collisions\", m_num_collisions);\r\n\t\r\n\tp_info->AddVector(\"m_model_offset\", m_model_offset);\r\n\t\r\n\tp_info->AddFloat(\"CollideMuteDelay\", m_sound_setup.collide_mute_delay);\r\n\t\r\n\tp_info->AddFloat(\"GlobalCollideMuteDelay\", m_sound_setup.global_collide_mute_delay);\r\n\t\r\n\tp_info->AddFloat(\"BounceVelocityCallbackThreshold\", m_sound_setup.bounce_velocity_callback_threshold);\r\n\t\r\n\tp_info->AddFloat(\"BounceVelocityFullSpeed\", m_sound_setup.bounce_velocity_full_speed);\r\n\t\r\n\tScript::CArray* p_array = new Script::CArray;\r\n\tp_array->SetSizeAndType(m_num_contacts, ESYMBOLTYPE_VECTOR);\r\n\tfor (int n = m_num_contacts; n--; )\r\n\t{\r\n\t\tScript::CVector* p_vector = new Script::CVector;\r\n\t\tp_vector->mX = mp_contacts[n].p[X];\r\n\t\tp_vector->mY = mp_contacts[n].p[Y];\r\n\t\tp_vector->mZ = mp_contacts[n].p[Z];\r\n\t\tp_array->SetVector(n, p_vector);\r\n\t}\r\n\tp_info->AddArrayPointer(\"m_contacts\", p_array);\r\n\t\r\n\tp_info->AddChecksum(\"CollideScript\", m_script_names.collide);\r\n\tp_info->AddChecksum(\"BounceScript\", m_script_names.bounce);\r\n\tp_info->AddChecksum(\"SettleScript\", m_script_names.settle);\r\n\tp_info->AddChecksum(\"StuckScript\", m_script_names.stuck);\r\n\t\r\n\tif (mp_script_params)\r\n\t{\r\n\t\tp_info->AddStructure(\"CallbackParams\", mp_script_params);\r\n\t}\r\n\r\n\tp_info->AddChecksum(\"DieUponSettling\", m_flags.Test(DIE_UPON_SLEEP) ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\tp_info->AddChecksum(\"PlayerCollisionDisabled\", m_flags.Test(PLAYER_COLLISION_DISABLED) ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\t\r\n\tif (m_sound_setup.bounce_sound)\r\n\t{\r\n\t\tScript::CStruct* p_struct = new Script::CStruct;\r\n\t\t*p_struct += *m_sound_setup.bounce_sound;\r\n\t\tp_info->AddStructurePointer(CRCD(0x1fb2f60c, \"BounceSound\"), p_struct);\r\n\t}\r\n\tif (m_sound_setup.collide_sound)\r\n\t{\r\n\t\tScript::CStruct* p_struct = new Script::CStruct;\r\n\t\t*p_struct += *m_sound_setup.collide_sound;\r\n\t\tp_info->AddStructurePointer(CRCD(0xbf8e0ace, \"CollideSound\"), p_struct);\r\n\t}\r\n\t\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::sToggleDrawRigidBodyDebugLines (   )\r\n{\r\n\tif (s_debug_lines_on)\r\n\t{\r\n\t\t/*\r\n\t\tif (s_draw_skater_collision_circles)\r\n\t\t{\r\n\t\t\ts_debug_lines_on = s_draw_skater_collision_circles = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ts_draw_skater_collision_circles = true;\r\n\t\t}\r\n\t\t*/\r\n\t\ts_debug_lines_on = false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\ts_debug_lines_on = true;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::setup_contact_states (   )\r\n{\r\n\tfor (int n = m_num_contacts; n--; )\r\n\t{\r\n\t\tsp_contact_states[n].p_world = m_matrix.Rotate(mp_contacts[n].p);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::handle_skater_collisions (   )\r\n{\r\n\tfor (int n = Mdl::Skate::Instance()->GetNumSkaters(); n--; )\r\n\t{\r\n\t\tCSkater& skater = *Mdl::Skate::Instance()->GetSkater(n);\r\n\r\n\t\tfloat radius_boost = skater.GetRigidBodyCollisionRadiusBoost();\r\n\t\t\r\n\t\t// detect collisions within a cylinder of the skater; if objects end up having significant extent in some directions and not others,\r\n\t\t// this detection code may have to become more sophisticated\r\n\r\n\t\t// check distance to the skater in the X-Z plane\r\n\t\tfloat distance_sqr = (m_pos[X] - skater.GetPos()[X]) * (m_pos[X] - skater.GetPos()[X])\r\n\t\t\t+ (m_pos[Z] - skater.GetPos()[Z]) * (m_pos[Z] - skater.GetPos()[Z]);\r\n\t\tif (distance_sqr > Mth::Sqr(m_skater_collision_radius + radius_boost)) continue;\r\n\r\n\t\t// check Y-offset to the skater\r\n\t\tfloat y_offset = skater.GetPos()[Y] - m_pos[Y];\r\n\t\tif (y_offset > m_skater_collision_application_radius + radius_boost\r\n\t\t\t|| y_offset < -(m_skater_collision_application_radius + radius_boost + s_skater_head_height)) continue;\r\n\r\n\t\t// apply the skater collision impulse; the impulse occurs at a slight assent and in a direction halfway between of the skater's\r\n\t\t// velocity and the line to the object; the magnitude is roughly proportional to the component of the skater's velocity along the\r\n\t\t// line to the object; the impulse will be applied a few inches above the skater's lowest point, along the line between the object\r\n\t\t// and the skater at distance equal to the collision radius of the object\r\n\r\n\t\t// unit vector pointing from the skater to the object in the X-Z plane\r\n\t\tMth::Vector r = m_pos;\r\n\t\tr -= skater.GetPos();\r\n\t\t// r[Y] = 0.0f; // optimized out as r[Y] never used\r\n\t\tfloat eff_length = sqrtf(r[X] * r[X] + r[Z] * r[Z]);\r\n\t\tr[X] /= eff_length;\r\n\t\tr[Z] /= eff_length;\r\n\t\t\r\n\t\t// skater's relative velocity in the X-Z plane\r\n\t\tMth::Vector skater_vel = skater.GetVel();\r\n\t\tskater_vel -= m_vel;\r\n\t\tskater_vel[Y] = 0.0f;\r\n\r\n\t\tif(( fabsf( skater_vel[X] ) < 0.01f ) && ( fabsf( skater_vel[Z] ) < 0.01f ))\r\n\t\t{\r\n\t\t\t// Small enough not to worry about - smaller can cause NaN decomposition.\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\t// unadjusted impulse magnitude\r\n\t\tfloat magnitude = skater_vel[X] * r[X] + skater_vel[Z] * r[Z];\r\n\t\tif (magnitude <= 0.0f) continue;\r\n\r\n\t\t// we adjust the impulse magnitude so the object will be vaulted in front of the skater so as to give the player a nice view of the object's\r\n\t\t// dynamics; also, at low skater velocities, we want only a very small impulse\r\n\r\n\t\t// fast collisions\r\n\t\tif (magnitude > (2.0f * vRP_SKATER_COLLISION_VELOCITY_THRESHOLD_INCREMENT))\r\n\t\t{\r\n\t\t\t// increase the impulse by a constant\r\n\t\t\tmagnitude += ((1.0f + vRP_SKATER_COLLISION_VELOCITY_THRESHOLD_INCREMENT) * vRP_SKATER_COLLISION_VELOCITY_FACTOR);\r\n\t\t}\r\n\t\t// medium collisions\r\n\t\telse if (magnitude > vRP_SKATER_COLLISION_VELOCITY_THRESHOLD_INCREMENT) {\r\n\t\t\t// connect the functions continuously\r\n\t\t\tmagnitude += (vRP_SKATER_COLLISION_VELOCITY_FACTOR * vRP_SKATER_COLLISION_VELOCITY_THRESHOLD_INCREMENT)\r\n\t\t\t\t+ (magnitude - vRP_SKATER_COLLISION_VELOCITY_THRESHOLD_INCREMENT);\r\n\t\t}\r\n\t\telse\r\n\t\t// slow collisions\r\n\t\t{\r\n\t\t\t// increase the impulse by a factor\r\n\t\t\tmagnitude *= (1.0f + vRP_SKATER_COLLISION_VELOCITY_FACTOR);\r\n\t\t}\r\n\r\n\t\t// impulse direction in the X-Z plane is the average of the skater velocity and r directions\r\n\t\t// we know the Y component for both is zero\r\n\t\tMth::Vector impulse = skater_vel;\r\n\t\teff_length = sqrtf(impulse[X] * impulse[X] + impulse[Z] * impulse[Z]);\r\n\t\timpulse[X] = impulse[X] / eff_length + r[X];\r\n\t\timpulse[Z] = impulse[Z] / eff_length + r[Z];\r\n\t\teff_length = sqrtf(impulse[X] * impulse[X] + impulse[Z] * impulse[Z]);\r\n\t\timpulse[X] = impulse[X] / eff_length;\r\n\t\timpulse[Z] = impulse[Z] / eff_length;\r\n\r\n\t\t// adjust the impulse direction upwards\r\n\t\timpulse[X] *= m_cos_skater_collision_assent;\r\n\t\timpulse[Y] = m_sin_skater_collision_assent;\r\n\t\timpulse[Z] *= m_cos_skater_collision_assent;\r\n\r\n\t\t// factor in the magnitude\r\n\t\timpulse *= m_skater_collision_impulse_factor * magnitude;\r\n\r\n\t\t// the impulse's point of application in the XZ-plane is along the line between the skater and the object at the object's impulse application\r\n\t\t// radius\r\n\r\n\t\t// we calculate the point of application with respect to the center of mass\r\n        Mth::Vector application_point = skater.GetPos();\r\n\t\tapplication_point[X] -= m_pos[X];\r\n\t\tapplication_point[Y] = 0.0f;\r\n\t\tapplication_point[Z] -= m_pos[Z];\r\n\t\tapplication_point.Normalize(m_skater_collision_application_radius);\r\n\r\n\t\t// calculate the Y-component of the point of application\r\n\t\tif (y_offset > 0.0f)\r\n\t\t{\r\n\t\t\t// collide with the skater's feet\r\n\t\t\tapplication_point[Y] = skater.GetPos()[Y] - m_pos[Y];\r\n\t\t}\r\n\t\telse if (y_offset < -s_skater_head_height)\r\n\t\t{\r\n\t\t\t// collide with the skater's head\r\n\t\t\tapplication_point[Y] = skater.GetPos()[Y] + s_skater_head_height - m_pos[Y];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// collide with the skater's body; use an offset from the center of mass to cause rotation\r\n\t\t\tapplication_point[Y] = -12.0f;\r\n\t\t}\r\n\r\n\t\t// apply the impulse; artifically reduce the initial rotation; it looks nice when the objects tumbles more after their first bounce\r\n\t\tm_vel += impulse;\r\n\t\tm_rotvel += m_skater_collision_rotation_factor * 0.6f * m_mass_over_moment * Mth::CrossProduct(application_point, impulse);\r\n\r\n\t\twake();\r\n\r\n\t\t// start a countdown; while this countdown is complete, we will ignore the skater\r\n\t\tm_ignore_skater_countdown = m_ignore_skater_duration;\r\n\t\t\r\n\t\t// call the bounce script callback\r\n\t\tif (m_script_names.collide)\r\n\t\t{\r\n\t\t\tGetObject()->SpawnScriptPlease(m_script_names.collide, mp_script_params)->Update();\r\n\t\t}\r\n\t\t\r\n\t\t// kill the object's shadow\r\n\t\tif (Nx::CSector *p_shadow_sector = Nx::CEngine::sGetMainScene()->GetSector(Crc::ExtendCRCWithString(GetObject()->GetID(), \"_Shadow\")))\r\n\t\t{\r\n\t\t\tp_shadow_sector->SetActive(false);\r\n\t\t}\r\n\t\t\r\n\t\tTmr::Time time = Tmr::GetTime();\r\n\t\tif ((int) (time - m_collide_sound_allowed_time) > 0 && (int) (time - s_collide_sound_allowed_time) > 0)\r\n\t\t{\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tif (m_sound_type_id && Script::GetInteger(CRCD(0xd634a297, \"DynamicRigidbodySounds\")))\r\n\t\t\t{\r\n\t\t\t\tget_sound_setup(m_sound_type_id);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tif (m_sound_setup.collide_sound)\r\n\t\t\t{\r\n\t\t\t\tfloat percent = (100.0f / 1000.0f) * impulse.Length();\r\n\t\t\t\tm_sound_setup.collide_sound->AddFloat(CRCD(0x9e497fc6, \"Percent\"), percent);\r\n\t\t\t\tmp_sound_component->PlayScriptedSound(m_sound_setup.collide_sound);\r\n\t\t\t\t\r\n\t\t\t\t// delay the next collision sound\r\n\t\t\t\tm_collide_sound_allowed_time = Tmr::GetTime() + (50 + Mth::Rnd(100)) * m_sound_setup.collide_mute_delay / 100;\r\n\t\t\t\ts_collide_sound_allowed_time = Tmr::GetTime() + (50 + Mth::Rnd(100)) * m_sound_setup.global_collide_mute_delay / 100;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// collide with only a single skater\r\n\t\tbreak;\r\n\t} // END loop over skaters\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::update_dynamic_state ( float time_step )\r\n{\r\n\t// a massively shoe-string handling of contact forces\r\n\tif (m_num_collisions < 3)\r\n\t{\r\n\t\tMth::Vector delta_pos = m_vel;\r\n\t\tdelta_pos[Y] += 0.5f * time_step * m_const_acc;\r\n\t\tdelta_pos *= time_step;\r\n\t\tm_pos += delta_pos;\r\n\r\n\t\tm_vel[Y] += time_step * m_const_acc;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_pos += time_step * m_vel;\r\n\t}\r\n\r\n\tMth::Quat delta_orientation = m_orientation;\r\n\tdelta_orientation *= Mth::Quat(-0.5f * m_rotvel[X], -0.5f * m_rotvel[Y], -0.5f * m_rotvel[Z], 0.0f);\r\n\tdelta_orientation *= time_step;\r\n\tm_orientation += delta_orientation;\r\n\r\n\tm_orientation.Normalize();\r\n\r\n\tm_orientation.GetMatrix(m_matrix);\r\n\r\n\tfor (int n = m_num_contacts; n--; )\r\n\t{\r\n\t\tsp_contact_states[n].p_world = m_matrix.Rotate(mp_contacts[n].p);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::consider_sleeping (   )\r\n{\r\n\t// it is possible that we may want to check these conditions over a period of several frames to insure that sleeping is warranted\r\n\r\n\t// only sleep if we're experiencing three or more collisions; hopefully, a surface-to-surface contact\r\n\tif (m_num_collisions < 3) return;\r\n\r\n\t// only sleep if we're moving slow\r\n\tif (m_vel.LengthSqr() > m_linear_velocity_sleep_point_sqr) return;\r\n\r\n\t// only sleep if we're moving slow\r\n\tif (m_rotvel.LengthSqr() > m_angular_velocity_sleep_point_sqr) return;\r\n\r\n\tsleep();\r\n\t\r\n\t// if we're not suppose to when going to sleep\r\n\tif (!m_flags.Test(DIE_UPON_SLEEP)) return;\r\n\t\r\n\t// only die if we've moved substantially from our starting point\r\n\tif ((m_pos - m_wake_pos).LengthSqr() < 48.0f * 48.0f) return;\r\n\t\r\n\tm_die_countdown = 1.5f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::wake (   )\r\n{\r\n\tif (m_state != AWAKE)\r\n\t{\r\n\t\tm_wake_pos = GetObject()->GetPos();\r\n\t\tm_state = AWAKE;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::sleep (   )\r\n{\r\n\tif (m_script_names.settle)\r\n\t{\r\n\t\tGetObject()->SpawnScriptPlease(m_script_names.settle, mp_script_params)->Update();\r\n\t}\r\n\t\r\n\tm_vel.Set(0.0f, 0.0f, 0.0f);\r\n\tm_rotvel.Set(0.0f, 0.0f, 0.0f);\r\n\tm_state = ASLEEP;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CRigidBodyComponent::detect_collisions (   )\r\n{\r\n\tCFeeler feeler;\r\n\r\n\t// set up a bounding box around the space within which all collision detection will occur\r\n\tMth::CBBox bounding_box(m_pos - Mth::Vector(m_largest_contact_extent, m_largest_contact_extent, m_largest_contact_extent),\r\n\t\tm_pos + Mth::Vector(m_largest_contact_extent, m_largest_contact_extent, m_largest_contact_extent));\r\n\ts_collision_cache.Update(bounding_box);\r\n\tfeeler.SetCache(&s_collision_cache);\r\n\r\n\t// loop over the contact points\r\n\tm_num_collisions = 0;\r\n\tfor (int n = m_num_contacts; n--; )\r\n\t{\r\n\t\tSContactState& contact_state = sp_contact_states[n];\r\n\r\n\t\t// run a feeler from the object's center to the contact point\r\n\t\tfeeler.m_start = m_pos;\r\n\t\tfeeler.m_end = m_pos;\r\n\t\tfeeler.m_end += contact_state.p_world;\r\n\r\n\t\tcontact_state.collision = feeler.GetCollision(false);\r\n\r\n\t\tif (!contact_state.collision) continue;\r\n\r\n\t\tcontact_state.normal = feeler.GetNormal();\r\n\t\tcontact_state.normal_eff_mass_set = false;\r\n\t\tcontact_state.normal_impulse_magnitude = 0.0f;\r\n\t\t\r\n\t\tcontact_state.depth = Mth::DotProduct(contact_state.normal, (1.0f - feeler.GetDist()) * (feeler.m_end - feeler.m_start));\r\n\t\tcontact_state.collision = contact_state.depth <= 0.0f;\r\n\t\t\r\n\t\tif (contact_state.collision)\r\n\t\t{\r\n\t\t\tm_num_collisions++;\r\n\t\t}\r\n\t}\r\n\r\n\treturn m_num_collisions != 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CRigidBodyComponent::calculate_effective_mass ( const Mth::Vector& direction, const SContactState& contact_state ) const\r\n{\r\n\t// calculated the effective mass of the object at a contact for forces in a given direction\r\n\r\n\tMth::Vector delta_rotvel = Mth::CrossProduct(contact_state.p_world, direction);\r\n\tdelta_rotvel *= m_mass_over_moment;\r\n\treturn 1.0f / Mth::DotProduct(direction, direction + Mth::CrossProduct(delta_rotvel, contact_state.p_world));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::resolve_collisions (   )\r\n{\r\n\t// collision resolution code of my own devise; simplified and not wholly accurate, it is good enough because we only have a single object\r\n\t// colliding with a (mostly) static background; multiple collisions are not resolved simultaneously; instead, an iterative procedure is used to\r\n\t// resolve the normal forces; this can cause objects which are colliding face-to-face with a surface to bounce off with odd rotation,\r\n\t// as the required collision impulse will not be spread evenly across the contacts (as would be correct); also, friction is not handled in closed\r\n\t// form; instead, after the collision is resolved and the normal forces are determined, we go back in and apply frictional forces (using the\r\n\t// velocity of the object before the normal forces are applied; this generates friction which is incorrect, but visually reasonable; the friction\r\n\t// forces could ruin the resolution of the collision, but we just ignore that possibility, and leave the problem to be fixed on the next frame\r\n\r\n\t// cache the velocity and use it when determining the frictional forces\r\n\tMth::Vector cache_vel = m_vel;\r\n\tMth::Vector cache_rotvel = m_rotvel;\r\n\t\r\n\t// maximum collision velocity; used to determine if a bounce callback is warranted\r\n\tfloat max_collision_velocity = 0.0f;\r\n\r\n\t// loop until the collisions are fully resolved\r\n\tint collision_resolution_pass_count = 0;\r\n\tbool clean_pass;\r\n\tdo {\r\n\t\tclean_pass = true;\r\n\r\n\t\t// loop over the collision points\r\n\t\tfor (int n = m_num_contacts; n--; )\r\n\t\t{\r\n\t\t\tSContactState& contact_state = sp_contact_states[n];\r\n\t\t\tif (!contact_state.collision) continue;\r\n\t\r\n\t\t\t// calculate the normal velocity at the collision point\r\n\t\t\tMth::Vector vel = m_vel;\r\n\t\t\tvel += Mth::CrossProduct(m_rotvel, contact_state.p_world);\r\n\t\t\tfloat normal_vel = Mth::DotProduct(contact_state.normal, vel);\r\n\t\r\n\t\t\t// skip if we're not colliding\r\n\t\t\tif (normal_vel > 0.0f) continue;\r\n\t\t\tclean_pass = false;\r\n\t\t\t\r\n\t\t\tif (-normal_vel > max_collision_velocity)\r\n\t\t\t{\r\n\t\t\t\tmax_collision_velocity = -normal_vel;\r\n\t\t\t}\r\n\t\r\n\t\t\t// calculate the goal velocity\r\n\t\t\tfloat goal_normal_vel = -m_coeff_restitution * normal_vel;\r\n\r\n\t\t\t// calculate normal effective mass\r\n\t\t\tif (!contact_state.normal_eff_mass_set)\r\n\t\t\t{\r\n\t\t\t\tcontact_state.normal_eff_mass = calculate_effective_mass(contact_state.normal, contact_state);\r\n\t\t\t\tcontact_state.normal_eff_mass_set = true;\r\n\t\t\t}\r\n\t\r\n\t\t\t// calculate the normal impulse required to reach the goal velocity\r\n\t\t\tfloat normal_impulse = (goal_normal_vel - normal_vel) * contact_state.normal_eff_mass;\r\n\r\n\t\t\t// calculate normal impulse\r\n\t\t\tMth::Vector impulse = contact_state.normal;\r\n\t\t\timpulse *= normal_impulse;\r\n\r\n\t\t\t// accumulate the total normal impulse applied at his contact\r\n\t\t\tcontact_state.normal_impulse_magnitude += normal_impulse;\r\n\r\n\t\t\t// apply the normal impulse\r\n\t\t\tm_vel += impulse;\r\n\t\t\tm_rotvel += m_mass_over_moment * Mth::CrossProduct(contact_state.p_world, impulse);\r\n\t\t} // END loop over collision points\r\n\r\n\t\tif (++collision_resolution_pass_count == 20)\r\n\t\t{\r\n\t\t\tDbg_Message(\"CRigidBodyComponent::resolve_collisions: unresolveable collision; zeroing velocity\");\r\n\t\t\t// call the sleep script callback\r\n\t\t\tif (m_script_names.stuck)\r\n\t\t\t{\r\n\t\t\t\tGetObject()->SpawnScriptPlease(m_script_names.stuck, mp_script_params)->Update();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_vel.Set(0.0f, 0.0f, 0.0f);\r\n\t\t\t\tm_rotvel.Set(0.0f, 0.0f, 0.0f);\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\t// if there's only one collision point, we need to make only a single pass\r\n\t\tif (m_num_contacts == 1) break;\r\n\t} while (!clean_pass);\r\n\t// END loop until collision is resolved\r\n\r\n\t// we've resolved the collision; now calculate and apply the friction using the cached velocities\r\n\r\n\t// loop over the collision points\r\n\tfor (int n = m_num_contacts; n--; )\r\n\t{\r\n\t\tSContact& contact = mp_contacts[n];\r\n\t\tSContactState& contact_state = sp_contact_states[n];\r\n\t\tif (!contact_state.collision) continue;\r\n\r\n\t\t// calculate the tangent direction and velocity\r\n\t\tMth::Vector vel = cache_vel;\r\n\t\tvel += Mth::CrossProduct(cache_rotvel, contact_state.p_world);\r\n\t\tfloat normal_vel = Mth::DotProduct(contact_state.normal, vel);\r\n\t\tMth::Vector tangent = vel + -normal_vel * contact_state.normal;\r\n\t\t\r\n\t\tif (contact.directed_friction)\r\n\t\t{\r\n\t\t\tMth::Vector friction_direction_world = m_matrix.Rotate(contact.friction_direction);\r\n\t\t\tfriction_direction_world -= Mth::DotProduct(contact_state.normal, friction_direction_world) * contact_state.normal;\r\n\t\t\t\r\n\t\t\tfloat length = friction_direction_world.Length();\r\n\t\t\tif (length > 0.001f)\r\n\t\t\t{\r\n\t\t\t\tfriction_direction_world *= (1.0f / length);\r\n\t\t\t\ttangent.ProjectToNormal(friction_direction_world);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tfloat tangent_vel = tangent.Length();\r\n\r\n\t\t// if the tangential velocity is too small, it's direction will be meaningless anyway\r\n\t\tif (tangent_vel < 0.001f) continue;\r\n\r\n\t\t// normalize by hand\r\n\t\ttangent /= tangent_vel;\r\n\r\n\t\tfloat tangent_eff_mass = calculate_effective_mass(tangent, contact_state);\r\n\r\n\t\t// calculate the tangential impulse required to stop the tangential\tvelocity\r\n\t\tfloat tangent_impulse = tangent_vel * tangent_eff_mass;\r\n\r\n\t\t// the frictional impulse is only allowed to be so big\r\n\t\tfloat max_tangent_impulse = m_coeff_friction * contact_state.normal_impulse_magnitude;\r\n\t\tif (tangent_impulse > max_tangent_impulse)\r\n\t\t{\r\n\t\t\ttangent_impulse = max_tangent_impulse;\r\n\t\t}\r\n\t\t\r\n\t\t// calculate the tangent impulse\r\n\t\tMth::Vector impulse = tangent;\r\n\t\timpulse *= -tangent_impulse;\r\n\t\t\r\n\t\tif (s_draw_skater_collision_circles)\r\n\t\t{\r\n\t\t\tif (contact.directed_friction)\r\n\t\t\t{\r\n\t\t\t\tGfx::AddDebugLine(contact_state.p_world + m_pos + Mth::Vector(0.0f, 1.0f, 0.0f), contact_state.p_world + m_pos + 6.0f * impulse + Mth::Vector(0.0f, 1.0f, 0.0f), MAKE_RGB(255, 255, 0), MAKE_RGB(255, 255, 0), 1);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tGfx::AddDebugLine(contact_state.p_world + m_pos + Mth::Vector(0.0f, 1.0f, 0.0f), contact_state.p_world + m_pos + 6.0f * impulse + Mth::Vector(0.0f, 1.0f, 0.0f), MAKE_RGB(255, 0, 255), MAKE_RGB(255, 0, 255), 1);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// apply the tangent impulse to both the true velocity and the velocity we are using to determine the frictional forces\r\n\r\n\t\tMth::Vector delta_rotvel = m_mass_over_moment * Mth::CrossProduct(contact_state.p_world, impulse);\r\n\r\n\t\tm_vel += impulse;\r\n\t\tm_rotvel += delta_rotvel;\r\n\r\n\t\tcache_vel += impulse;\r\n\t\tcache_rotvel += delta_rotvel;\r\n\t} // END loop over collision points\r\n\t\r\n\t// apply penalty forces to prevent interpenetration\r\n\t\r\n\tfloat time_step = Tmr::FrameLength();\r\n\t\r\n\tfor (int n = m_num_contacts; n--; )\r\n\t{\r\n\t\tSContactState& contact_state = sp_contact_states[n];\r\n\t\tif (!contact_state.collision) continue;\r\n\t\t\r\n\t\tMth::Vector impulse = -m_spring_const * contact_state.depth * time_step * contact_state.normal;\r\n\t\t\r\n\t\tMth::Vector delta_rotvel = m_mass_over_moment * Mth::CrossProduct(contact_state.p_world, impulse);\r\n\t\t\r\n\t\tm_vel += impulse;\r\n\t\tm_rotvel += delta_rotvel;\r\n\t\t\r\n\t\tif (s_draw_skater_collision_circles)\r\n\t\t{\r\n\t\t\tGfx::AddDebugLine(contact_state.p_world + m_pos, contact_state.p_world + m_pos + 60.0f * impulse, MAKE_RGB(255, 255, 0), MAKE_RGB(255, 255, 255), 1);\r\n\t\t}\r\n\t}\r\n\t\r\n\t// script callback\r\n\tif (max_collision_velocity > m_sound_setup.bounce_velocity_callback_threshold)\r\n\t{\r\n\t\tif (m_script_names.bounce)\r\n\t\t{\r\n\t\t\tGetObject()->SpawnScriptPlease(m_script_names.bounce, mp_script_params)->Update();\r\n\t\t}\r\n\t\t\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tif (m_sound_type_id && Script::GetInteger(CRCD(0xd634a297, \"DynamicRigidbodySounds\")))\r\n\t\t{\r\n\t\t\tget_sound_setup(m_sound_type_id);\r\n\t\t}\r\n\t\t#endif\r\n\t\t\r\n\t\t// don't use up the last vRP_NUM_UNTOUCHABLE_VOICES voices\r\n\t\tif (m_sound_setup.bounce_sound && NUM_VOICES - Sfx::CSfxManager::Instance()->GetNumSoundsPlaying() > vRP_NUM_UNTOUCHABLE_VOICES)\r\n\t\t{\r\n\t\t\tfloat percent = Mth::Clamp(100.0f * max_collision_velocity / m_sound_setup.bounce_velocity_full_speed, 0.0f, 100.0f);\r\n\t\t\tm_sound_setup.bounce_sound->AddFloat(CRCD(0x9e497fc6, \"Percent\"), percent);\r\n\t\t\tmp_sound_component->PlayScriptedSound(m_sound_setup.bounce_sound);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::get_sound_setup ( uint32 sound_type_id )\r\n{\r\n\r\n\tScript::CStruct* p_base_struct;\r\n\tp_base_struct = Script::GetStructure(CRCD(0xb9738eba, \"RigidBodySounds\"), Script::ASSERT);\r\n\r\n\tScript::CStruct* p_sound_struct = NULL;\r\n\tp_base_struct->GetStructure(sound_type_id, &p_sound_struct);\r\n\tDbg_MsgAssert(p_sound_struct, (\"Sound type '%s' not found in RigidBodySounds\", Script::FindChecksumName(sound_type_id)));\r\n\r\n\tScript::CStruct* p_struct;\r\n\r\n\tif (p_sound_struct->ContainsComponentNamed(CRCD(0xbf8e0ace, \"CollideSound\")))\r\n\t{\r\n\t\tp_sound_struct->GetStructure(CRCD(0xbf8e0ace, \"CollideSound\"), &p_struct, Script::ASSERT);\r\n\t\tif (m_sound_setup.collide_sound)\r\n\t\t{\r\n\t\t\tdelete m_sound_setup.collide_sound;\r\n\t\t}\r\n\t\tm_sound_setup.collide_sound = new Script::CStruct;\r\n\t\t*m_sound_setup.collide_sound += *p_struct;\r\n\t}\r\n\r\n\tif (p_sound_struct->ContainsComponentNamed(CRCD(0x1fb2f60c, \"BounceSound\")))\r\n\t{\r\n\t\tp_sound_struct->GetStructure(CRCD(0x1fb2f60c, \"BounceSound\"), &p_struct, Script::ASSERT);\r\n\t\tif (m_sound_setup.bounce_sound)\r\n\t\t{\r\n\t\t\tdelete m_sound_setup.bounce_sound;\r\n\t\t}\r\n\t\tm_sound_setup.bounce_sound = new Script::CStruct;\r\n\t\t*m_sound_setup.bounce_sound += *p_struct;\r\n\r\n\t\tif (p_sound_struct->ContainsComponentNamed(CRCD(0x3818ee47, \"CollideMuteDelay\")))\r\n\t\t{\r\n\t\t\tint time;\r\n\t\t\tp_sound_struct->GetInteger(CRCD(0x3818ee47, \"CollideMuteDelay\"), &time);\r\n\t\t\tm_sound_setup.collide_mute_delay = static_cast< Tmr::Time >(time);\r\n\t\t}\r\n\t\tif (p_sound_struct->ContainsComponentNamed(CRCD(0xad67a34d, \"GlobalCollideMuteDelay\")))\r\n\t\t{\r\n\t\t\tint time;\r\n\t\t\tp_sound_struct->GetInteger(CRCD(0xad67a34d, \"GlobalCollideMuteDelay\"), &time);\r\n\t\t\tm_sound_setup.global_collide_mute_delay = static_cast< Tmr::Time >(time);\r\n\t\t}\r\n\t\tp_sound_struct->GetFloat(CRCD(0x4511ca8d, \"BounceVelocityCallbackThreshold\"), &m_sound_setup.bounce_velocity_callback_threshold);\r\n\t\tp_sound_struct->GetFloat(CRCD(0x8fc6519f, \"BounceVelocityFullSpeed\"), &m_sound_setup.bounce_velocity_full_speed);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::setup_contacts_from_array ( Script::CArray* pArray )\r\n{\r\n\tm_num_contacts = pArray->GetSize();\r\n\tDbg_MsgAssert(m_num_contacts <= vRP_MAX_NUM_CONTACTS, (\"Number of contacts in rigidbody exceeds limit of %i contacts\", vRP_MAX_NUM_CONTACTS));\r\n\t\r\n\tif (mp_contacts)\r\n\t{\r\n\t\tdelete [] mp_contacts;\r\n\t}\r\n\tmp_contacts = new SContact[m_num_contacts];\r\n\t\r\n\tfor (unsigned int n = 0; n < m_num_contacts; n++)\r\n\t{\r\n\t\tScript::CVector* p_v = pArray->GetVector(n);\r\n        mp_contacts[n].p[X] = p_v->mX;\r\n        mp_contacts[n].p[Y] = p_v->mY;\r\n        mp_contacts[n].p[Z] = p_v->mZ;\r\n\t\tmp_contacts[n].p[W] = 0.0f;\r\n\t\tmp_contacts[n].directed_friction = false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\r\nvoid CRigidBodyComponent::setup_contacts_as_box ( const Mth::Vector& top_half_dimensions, const Mth::Vector& bottom_half_dimensions )\r\n{\r\n\tm_num_contacts = 8;\r\n\r\n\tif (mp_contacts)\r\n\t{\r\n\t\tdelete [] mp_contacts;\r\n\t}\r\n\tmp_contacts = new SContact[m_num_contacts];\r\n\t\r\n\tint n = 0;\r\n\tbool x = false;\r\n\tdo {\r\n\t\tbool y = false;\r\n\t\tdo {\r\n\t\t\tbool z = false;\r\n\t\t\tdo {\r\n\t\t\t\tmp_contacts[n].p[X] = (x ? 1.0f : -1.0f) * (y ? top_half_dimensions[X] : bottom_half_dimensions[X]);\r\n\t\t\t\tmp_contacts[n].p[Y] = (y ? top_half_dimensions[Y] : -bottom_half_dimensions[Y]);\r\n\t\t\t\tmp_contacts[n].p[Z] = (z ? 1.0f : -1.0f) * (y ? top_half_dimensions[Z] : bottom_half_dimensions[Z]);\r\n\t\t\t\tmp_contacts[n].p[W] = 1.0f;\r\n\t\t\t\tmp_contacts[n].directed_friction = false;\r\n\t\t\t\tn++;\r\n\t\t\t\tz = !z;\r\n\t\t\t} while (z);\r\n\t\t\ty = !y;\r\n\t\t} while (y);\r\n\t\tx = !x;\r\n\t} while (x);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::setup_contacts_as_pyramid ( float half_height, float half_depth )\r\n{\r\n\tm_num_contacts = 5;\r\n\r\n\tif (mp_contacts)\r\n\t{\r\n\t\tdelete [] mp_contacts;\r\n\t}\r\n\tmp_contacts = new SContact[m_num_contacts];\r\n\t\r\n\tmp_contacts[0].p[X] = half_depth;\r\n\tmp_contacts[0].p[Y] = -0.6f * half_height;\r\n\tmp_contacts[0].p[Z] = half_depth;\r\n\tmp_contacts[0].p[W] = 1.0f;\r\n\tmp_contacts[0].directed_friction = false;\r\n\r\n\tmp_contacts[1].p[X] = -half_depth;\r\n\tmp_contacts[1].p[Y] = -0.6f * half_height;\r\n\tmp_contacts[1].p[Z] = half_depth;\r\n\tmp_contacts[1].p[W] = 1.0f;\r\n\tmp_contacts[0].directed_friction = false;\r\n\r\n\tmp_contacts[2].p[X] = -half_depth;\r\n\tmp_contacts[2].p[Y] = -0.6f * half_height;\r\n\tmp_contacts[2].p[Z] = -half_depth;\r\n\tmp_contacts[2].p[W] = 1.0f;\r\n\tmp_contacts[0].directed_friction = false;\r\n\r\n\tmp_contacts[3].p[X] = half_depth;\r\n\tmp_contacts[3].p[Y] = -0.6f * half_height;\r\n\tmp_contacts[3].p[Z] = -half_depth;\r\n\tmp_contacts[3].p[W] = 1.0f;\r\n\tmp_contacts[0].directed_friction = false;\r\n\r\n\tmp_contacts[4].p[X] = 0.0f;\r\n\tmp_contacts[4].p[Y] = 1.6f * half_height;\r\n\tmp_contacts[4].p[Z] = 0.0f;\r\n\tmp_contacts[4].p[W] = 1.0f;\r\n\tmp_contacts[0].directed_friction = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::setup_contacts_as_cylinder ( float top_radius, float bottom_radius, float half_height, int edges )\r\n{\r\n\tm_num_contacts = 2 * edges;\r\n\r\n\tif (mp_contacts)\r\n\t{\r\n\t\tdelete [] mp_contacts;\r\n\t}\r\n\tmp_contacts = new SContact[m_num_contacts];\r\n\t\r\n\tint i = 0;\r\n\tbool top = false;\r\n\tdo {\r\n\t\tfor (int n = edges; n--; )\r\n\t\t{\r\n\t\t\tmp_contacts[i].p[X] = (top ? top_radius : bottom_radius) * cosf(n * 2.0f * 3.1415f / edges);\r\n\t\t\tmp_contacts[i].p[Y] = (top ? half_height : -half_height);\r\n\t\t\tmp_contacts[i].p[Z] = (top ? top_radius : bottom_radius) * sinf(n * 2.0f * 3.1415f / edges);\r\n\t\t\tmp_contacts[i].p[W] = 1.0f;\r\n\t\t\tmp_contacts[i].directed_friction = false;\r\n\t\t\ti++;\r\n\t\t}\r\n\t\ttop = !top;\r\n\t} while (top);\r\n}\r\n\t\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::setup_contacts_as_triangle ( const Mth::Vector& half_dimensions )\r\n{\r\n\tm_num_contacts = 6;\r\n\r\n\tif (mp_contacts)\r\n\t{\r\n\t\tdelete [] mp_contacts;\r\n\t}\r\n\tmp_contacts = new SContact[m_num_contacts];\r\n\t\r\n\tint i = 0;\r\n\tbool left = false;\r\n\tdo {\r\n\t\tmp_contacts[i].p[X] = half_dimensions[X];\r\n\t\tmp_contacts[i].p[Y] = -half_dimensions[Y];\r\n\t\tmp_contacts[i].p[Z] = (left ? -1.0f : 1.0f) * half_dimensions[Z];\r\n\t\tmp_contacts[i].p[W] = 1.0f;\r\n\t\tmp_contacts[i].directed_friction = false;\r\n\t\ti++;\r\n\t\t\r\n\t\tmp_contacts[i].p[X] = -half_dimensions[X];\r\n\t\tmp_contacts[i].p[Y] = -half_dimensions[Y];\r\n\t\tmp_contacts[i].p[Z] = (left ? -1.0f : 1.0f) * half_dimensions[Z];\r\n\t\tmp_contacts[i].p[W] = 1.0f;\r\n\t\tmp_contacts[i].directed_friction = false;\r\n\t\ti++;\r\n\t\t\r\n\t\tmp_contacts[i].p[X] = 0.0f;\r\n\t\tmp_contacts[i].p[Y] = half_dimensions[Y];\r\n\t\tmp_contacts[i].p[Z] = (left ? -1.0f : 1.0f) * half_dimensions[Z];\r\n\t\tmp_contacts[i].p[W] = 1.0f;\r\n\t\tmp_contacts[i].directed_friction = false;\r\n\t\ti++;\r\n\t\t\r\n\t\tleft = !left;\r\n\t} while (left);\r\n}\t\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRigidBodyComponent::draw_debug_lines (   ) const\r\n{\r\n\tint color = 0;\r\n\tbool collidable = false;\r\n\tswitch (m_state)\r\n\t{\r\n\t\tcase ASLEEP:\r\n\t\t\tcolor = MAKE_RGB(0, 0, 200);\r\n\t\t\tcollidable = true;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase AWAKE:\r\n\t\t\tif (m_ignore_skater_countdown > 0.0f)\r\n\t\t\t{\r\n\t\t\t\tcolor = MAKE_RGB(0, 200, 0);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tcolor = MAKE_RGB(200, 0, 0);\r\n\t\t\t\tcollidable = true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\tif (collidable && s_draw_skater_collision_circles)\r\n\t{\r\n\t\tGfx::AddDebugCircle(m_pos + Mth::Vector(0.0f, m_skater_collision_application_radius, 0.0f), 8, m_skater_collision_radius, MAKE_RGB(200, 200, 0), 1);\r\n\t\tGfx::AddDebugCircle(m_pos + Mth::Vector(0.0f, -m_skater_collision_application_radius, 0.0f), 8, m_skater_collision_radius, MAKE_RGB(200, 200, 0), 1);\r\n\t}\r\n\t\r\n\tif (s_draw_skater_collision_circles)\r\n\t{\r\n\t\tGfx::AddDebugStar(m_pos, 36.0f, MAKE_RGB(200, 0, 200), 1);\r\n\t}\r\n\t\r\n\t// draw debug lines in less pretty yet general manner\r\n\tfor (int n = m_num_contacts; n--; )\r\n\t{\r\n\t\tfor (int m = 0; m < n; m++)\r\n\t\t{\r\n\t\t\tGfx::AddDebugLine(sp_contact_states[n].p_world + m_pos, sp_contact_states[m].p_world + m_pos, color, color, 1);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/rigidbodycomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       RigidBodyComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  1/22/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_RIGIDBODYCOMPONENT_H__\r\n#define __COMPONENTS_RIGIDBODYCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/collision/collcache.h>\r\n\r\n#define\t\tCRC_RIGIDBODY CRCD(0xffb39248, \"RigidBody\")\r\n#define\t\tGetRigidBodyComponent() ((Obj::CRigidBodyComponent*)GetComponent(CRC_RIGIDBODY))\r\n#define\t\tGetRigidBodyComponentFromObject(pObj) ((Obj::CRigidBodyComponent*)(pObj)->GetComponent(CRC_RIGIDBODY))\r\n\r\n#define vRP_GRAVITATIONAL_ACCELERATION\t \t\t\t\t\t(-386.4f)\r\n#define vRP_DEFAULT_MASS_OVER_MOMENT\t\t\t\t\t\t(0.003f)\r\n#define vRP_DEFAULT_COEFF_RESTITUTION\t  \t\t\t\t\t(0.4f)\r\n#define vRP_DEFAULT_COEFF_FRICTION\t    \t\t\t\t\t(0.5f)\r\n#define vRP_DEFAULT_SPRING_CONST    \t\t\t\t\t\t(10.0f)\r\n#define vRP_DEFAULT_SKATER_COLLISION_RADIUS\t  \t\t\t\t(12.0f + 36.0f)\r\n#define vRP_DEFAULT_SKATER_COLLISION_APPLICATION_RADIUS\t\t(12.0f)\r\n#define vRP_DEFAULT_SKATER_COLLISION_ASSENT\t\t\t\t\t(25.0f)\r\n#define vRP_DEFAULT_SKATER_COLLISION_IMPULSE_FACTOR\t\t\t(1.0f)\r\n#define vRP_DEFAULT_SKATER_COLLISION_ROTATION_FACTOR\t\t(1.0f)\r\n#define vRP_SKATER_COLLISION_VELOCITY_FACTOR \t\t   \t\t(1.0f)\r\n#define vRP_SKATER_COLLISION_VELOCITY_THRESHOLD_INCREMENT\t(50.0f)\r\n#define vRP_DEFAULT_LINEAR_VELOCITY_SLEEP_POINT\t   \t\t\t(10.0f)\r\n#define vRP_DEFAULT_ANGULAR_VELOCITY_SLEEP_POINT   \t\t\t(0.4f)\r\n#define vRP_DEFAULT_IGNORE_SKATER_DURATION\t\t\t\t\t(5.0f / 60.0f)\r\n#define vRP_DEFAULT_COLLIDE_MUTE_DELAY\t\t\t\t\t\t(1000)\r\n#define vRP_DEFAULT_GLOBAL_COLLIDE_MUTE_DELAY\t\t\t\t(100)\r\n#define vRP_DEFAULT_BOUNCE_VELOCITY_CALLBACK_THRESHOLD\t\t(20.0f)\r\n#define vRP_DEFAULT_BOUNCE_VELOCITY_FULL_SPEED\t\t\t\t(300.0f)\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CSoundComponent;\r\n\r\nclass CRigidBodyComponent : public CBaseComponent\r\n{\r\n\tenum ERigidBodyStateType\r\n\t{\r\n\t\tASLEEP, AWAKE\r\n\t};\r\n\r\n\tenum EObjectGeometryType\r\n\t{\r\n\t\tBOX, PYRAMID, CYLINDER, TRIANGLE, NO_GEOMETRY\r\n\t};\r\n\t\r\n\tenum EFlagType\r\n\t{\r\n\t\tDIE_UPON_SLEEP,\r\n\t\tPLAYER_COLLISION_DISABLED\r\n\t};\r\n\r\n\tstruct SContact\r\n\t{\r\n\t\t// defining element of a rigidbody contact point; position\r\n\t\tMth::Vector p;\r\n\t\t\r\n\t\t// the axis of friction\r\n\t\tMth::Vector friction_direction;\r\n\t\t\r\n\t\t// if friction at this contact occurs only along a single axis\r\n\t\tchar directed_friction;\r\n\t};\r\n\t\r\n\tstruct SContactState\r\n\t{\r\n\t\t// offset to the contact point in world space\r\n\t\tMth::Vector p_world;\r\n\r\n\t\t// normal of the surface is it colliding with\r\n\t\tMth::Vector normal;\r\n\r\n\t\t// the effective mass of this contact for impulses applied along the normal\r\n\t\tfloat normal_eff_mass;\r\n\r\n\t\t// keeps track of the total impulse magnitude of the normal force in a frame; used to limit the frictional impulse\r\n\t\tfloat normal_impulse_magnitude;\r\n\t\t\r\n\t\t// depth of the contact; negative corresponds to interpenetration\r\n\t\tfloat depth;\r\n\r\n\t\t// is this contact in collision\r\n\t\tchar collision;\r\n\r\n\t\t// false before the normal_inv_mass has been set\r\n\t\tchar normal_eff_mass_set;\r\n\t};\r\n\t\r\n\t// if the number of free voices is this number or less, don't play bounce sounds\r\n\tstatic const int vRP_NUM_UNTOUCHABLE_VOICES = 12;\r\n\t\r\n\t// maximum number of contacts allowed on a single rigidbody\r\n\tstatic const unsigned int vRP_MAX_NUM_CONTACTS = 24;\r\n\r\npublic:\r\n    CRigidBodyComponent();\r\n    virtual ~CRigidBodyComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tstatic void \t\t\t\t\tsToggleDrawRigidBodyDebugLines (   );\r\n\r\nprivate:\r\n\r\n\tvoid\t\t\t\t\t\t\tsetup_contact_states (   );\r\n\tvoid\t\t\t\t\t\t\thandle_skater_collisions (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_dynamic_state ( float time_step );\r\n\tvoid\t\t\t\t\t\t\tconsider_sleeping (   );\r\n\tvoid\t\t\t\t\t\t\twake (   );\r\n\tvoid\t\t\t\t\t\t\tsleep (   );\r\n\tbool\t\t\t\t\t\t\tdetect_collisions (   );\r\n\tfloat\t\t\t\t\t\t\tcalculate_effective_mass ( const Mth::Vector& direction, const SContactState& contact_state ) const;\r\n\tvoid\t\t\t\t\t\t\tresolve_collisions (   );\r\n\tvoid\t\t\t\t\t\t\tdraw_debug_lines (   ) const;\r\n\tvoid\t\t\t\t\t\t\tget_sound_setup ( uint32 sound_type_id );\r\n\tvoid\t\t\t\t\t\t\tsetup_contacts_as_box ( const Mth::Vector& top_half_dimensions, const Mth::Vector& bottom_half_dimensions );\r\n\tvoid\t\t\t\t\t\t\tsetup_contacts_as_pyramid ( float radius, float half_depth );\r\n\tvoid\t\t\t\t\t\t\tsetup_contacts_as_cylinder ( float top_radius, float bottom_radius, float half_depth, int edges = 6 );\r\n\tvoid\t\t\t\t\t\t\tsetup_contacts_as_triangle ( const Mth::Vector& half_dimensions );\r\n\tvoid\t\t\t\t\t\t\tsetup_contacts_from_array ( Script::CArray *pArray );\r\n\r\nprivate:\r\n\r\n\t// properties:\r\n\r\n\t// object's don't have masses or moments of inertia;\r\n\t// instead, a single scalar is used for the moment of inertia and only the ratio of mass over moment is used;\r\n\t// this ratio controls the object's relative tendency to move linearly or rotationally;\r\n\t// if proper external forces are ever applied to rigidbodies, they will need a mass;\r\n\t// units are inverse inches squared; should be on the order of the inverse of the square of the characteristic\r\n\t// distance between the contact points and the center of mass\r\n\tfloat m_mass_over_moment;\r\n\r\n\t// object's acceleration due to constant force on its center of mass (gravity)\r\n\tfloat m_const_acc;\r\n\r\n\t// coefficient of restitution; bounce factor\r\n\tfloat m_coeff_restitution;\r\n\r\n\t// coefficient of friction\r\n\tfloat m_coeff_friction;\r\n\t\r\n\t// spring constant used to prevent interpenetration\r\n\tfloat m_spring_const;\r\n\r\n\t// effectively the sum of the object radius and the skater radius; when the center-to-center distance is below this, there is a collision\r\n\tfloat m_skater_collision_radius;\r\n\r\n\t// effectively the radius of the object; the impulse is applied at this distance from the object; to have reasonable rotations, m_mass_over_moment\r\n\t// should on the order of the inverse of this radius squared; also used in skater collisions to check their Y-interception\r\n\tfloat m_skater_collision_application_radius;\r\n\r\n\t// sine and cosine of the angle of assent of the skater collision impulse\r\n\tfloat m_cos_skater_collision_assent;\r\n\tfloat m_sin_skater_collision_assent;\r\n\r\n\t// factor which adjusts the magnitude of skater collision impulses; sort of like an inverse mass\r\n\tfloat m_skater_collision_impulse_factor;\r\n\t\r\n\t// scales the rotation the object gains from a collision with the skater\r\n\tfloat m_skater_collision_rotation_factor;\r\n\r\n\t// if the velocities are below these points, the object may go to sleep\r\n\tfloat m_linear_velocity_sleep_point_sqr;\r\n\tfloat m_angular_velocity_sleep_point_sqr;\r\n\r\n\t// currently, we assume a box; the algorithm is general enough to do anything\r\n\tSContact* mp_contacts;\r\n\tunsigned short m_num_contacts;\r\n\t\r\n\t// center of mass of the object\r\n\tMth::Vector m_center_of_mass;\r\n\t\r\n\t// offset from the center of mass to the origin of the model\r\n\tMth::Vector m_model_offset;\r\n\r\n\t// number of frames after a skater collision before we begin checking for skater collisions again\r\n\tfloat m_ignore_skater_duration;\r\n\t\r\n\t// callback script names\r\n\tstruct SScriptCallbackNames\r\n\t{\r\n\t\tuint32 collide;\r\n\t\tuint32 bounce;\r\n\t\tuint32 settle;\r\n\t\tuint32 stuck;\r\n\t} m_script_names;\r\n\t\r\n\t// parameter structure passed to callback scripts\r\n\tScript::CStruct* mp_script_params;\r\n\t\r\n\t// sound setup\r\n\tstruct SSoundSetup\r\n\t{\r\n\t\tScript::CStruct* collide_sound;\r\n\t\tScript::CStruct* bounce_sound;\r\n\t\tTmr::Time collide_mute_delay;\r\n\t\tTmr::Time global_collide_mute_delay;\r\n\t\tfloat bounce_velocity_callback_threshold;\r\n\t\tfloat bounce_velocity_full_speed;\r\n\t} m_sound_setup;\r\n\t\r\n\t// time when the next collide sound is allowed\r\n\tTmr::Time m_collide_sound_allowed_time;\r\n\t\r\n\t// time when the any next collide sound is allowed\r\n\tstatic Tmr::Time s_collide_sound_allowed_time;\r\n\t\r\n\t// used to allow dynamic updating of sounds\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint32 m_sound_type_id;\r\n\t#endif\r\n\t\r\n\t// property flags\r\n\tFlags<EFlagType> m_flags;\r\n\t\r\n\t// position at which we were last woke\r\n\tMth::Vector m_wake_pos;\r\n\t\r\n\t// countdown to dying; not active if set to -1.0f\r\n\tfloat m_die_countdown;\r\n\t\r\n\t// primary state variables:\r\n\r\n\t// object's state; objects sleep when they are not active\r\n\tERigidBodyStateType m_state;\r\n\r\n\t// object's center of mass position\r\n\tMth::Vector m_pos;\r\n\r\n\t// object's velocity\r\n\tMth::Vector m_vel;\r\n\r\n\t// object's orientation around center of mass\r\n\tMth::Quat m_orientation;\r\n\r\n\t// object's angular velocity\r\n\tMth::Vector m_rotvel;\r\n\r\n\t// dependent state variables:\r\n\r\n\t// rotation matrix based on our orientation\r\n\tMth::Matrix m_matrix;\r\n\r\n\t// number of contacts in current collision\r\n\tchar m_num_collisions;\r\n\r\n\t// count down used to time the interval between a skater collision and the point when we begin looking for skater collisions again\r\n\tfloat m_ignore_skater_countdown;\r\n\r\n\t// work variables:\r\n\r\n\t// collision cache; used to improve collision detection turn-around time; shared by all rigidbodies\r\n\tstatic Nx::CCollCache s_collision_cache;\r\n\r\n\t// longest distance between a contact point and the center of mass; used to generate the collision cache's bounding box\r\n\tfloat m_largest_contact_extent;\r\n\r\n\t// debug variables\r\n\tstatic bool s_debug_lines_on;\r\n\tstatic bool s_draw_skater_collision_circles;\r\n\r\n\t// height of the skater; used when determining skater collisions and resulting impulse point of application\r\n\tstatic float s_skater_head_height;\r\n\t\r\n\t// to save memory, the rigidbodies share an array of structures which hold the state of their contacts during collision resolution\r\n\tstatic SContactState sp_contact_states [ vRP_MAX_NUM_CONTACTS ];\r\n\t\r\n\t#ifdef __NOPT_DEBUG__\r\n\t// insures that only a single rigidbody is using sp_contact_states at a time\r\n\tstatic bool s_contact_states_in_use;\r\n\t#endif\r\n\t\r\n\t// peer components\r\n\tCSoundComponent* mp_sound_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/shadowcomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       ShadowComponent.cpp\r\n//* OWNER:          gj\r\n//* CREATION DATE:  2/06/03\r\n//****************************************************************************\r\n\r\n#include <gel/components/shadowcomponent.h>\r\n\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/motioncomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/scripting/cfuncs.h>\r\n\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/nxlight.h>\r\n#include <gfx/shadow.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// This static function is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\nCBaseComponent* CShadowComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CShadowComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCShadowComponent::CShadowComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SHADOW );\r\n\r\n\t// no shadow object\r\n\tmp_shadow = NULL;\t\t\t\t\t\r\n\tm_shadowNormal.Set(0.0f,1.0f,0.0f);\r\n\tm_shadowType = CRCD(0x806fff30,\"none\");\r\n\tm_shadowPos.Set(0,0,0);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCShadowComponent::~CShadowComponent()\r\n{\r\n\tif ( mp_shadow )\r\n\t{\r\n\t\tdelete mp_shadow;\r\n\t\tmp_shadow = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CShadowComponent::Finalize()\r\n{\r\n\tmp_model_component = GetModelComponentFromObject( GetObject() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CShadowComponent::Teleport()\r\n{\t\t\t\t\t\t\t\t\t \r\n\t// GJ:  the shadow component's Update()\r\n\t// function doesn't really require finalization\r\n\t// right now, but having this assert in here\r\n\t// might help catch future errors\r\n\tDbg_MsgAssert( GetObject()->IsFinalized(), ( \"Has not been finalized!  Tell Gary!\" ) );\r\n\r\n\tUpdate();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CShadowComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tm_shadowType = CRCD(0x3e84c2fd,\"simple\");\r\n\tpParams->GetChecksum( CRCD(0x9ac24b18,\"ShadowType\"), &m_shadowType, Script::NO_ASSERT );\r\n\r\n\tif ( mp_shadow )\r\n\t{\r\n\t\t// get rid of existing shadow, in case it was the wrong type...\r\n\t\tSwitchOffShadow();\r\n\t}\r\n\r\n\tswitch ( m_shadowType )\r\n\t{\r\n\t\tcase 0x3e84c2fd:\t// simple\r\n\t\t\t{\r\n\t\t\t\tif ( !mp_shadow )\r\n\t\t\t\t{\r\n\t\t\t\t\tSwitchOnShadow( Gfx::vSIMPLE_SHADOW );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tfloat scale = 1.0f;\r\n\t\t\t\tpParams->GetFloat( CRCD(0x6f8cd62f,\"ShadowScale\"), &scale, Script::NO_ASSERT );\r\n\t\t\t\t\r\n\t\t\t\tconst char *p_shadow_model_name = \"Ped_Shadow\";\r\n\t\t\t\tpParams->GetString( CRCD(0x545f8172,\"ShadowModel\"), &p_shadow_model_name, Script::NO_ASSERT );\r\n\t\t\t\t\t\t\r\n\t\t\t\tDbg_MsgAssert( mp_shadow, (\"NULL mp_shadow\") );\r\n\t\t\t\tGfx::CSimpleShadow* pSimpleShadow = (Gfx::CSimpleShadow*)mp_shadow;\r\n\t\t\t\tpSimpleShadow->SetScale( scale );\r\n\t\t\t\tpSimpleShadow->SetModel( p_shadow_model_name );\r\n\r\n\t\t\t\t// GJ:  need to immediately change the shadow's position if Obj_ShadowOn gets called\r\n\t\t\t\t// this is because sometimes the shadow component will be suspended, and so\r\n\t\t\t\t// update_shadow() won't get called (fixes shadow appearing at the origin in SC2)\r\n\t\t\t\tpSimpleShadow->UpdatePosition( m_shadowPos, GetObject()->m_matrix, m_shadowNormal );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0x76a54cd1:\t// detailed\r\n\t\t\t{\r\n\t\t\t\tif ( !mp_shadow )\r\n\t\t\t\t{\r\n\t\t\t\t\tSwitchOnShadow( Gfx::vDETAILED_SHADOW );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0x806fff30:\t// none\r\n\t\t\t{\r\n\t\t\t\tif ( mp_shadow )\r\n\t\t\t\t{\r\n\t\t\t\t\tSwitchOffShadow();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Unrecognized shadow type %s\", Script::FindChecksumName(m_shadowType) ) );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CShadowComponent::update_shadow()\r\n{\r\n\tif ( mp_shadow )\r\n\t{\r\n//\t\tDbg_MsgAssert(mp_shadow->GetShadowType()!=Gfx::vDETAILED_SHADOW,(\"Tried to update a detailed shadow in MovingObj_Update, will need to change code to send a higher-up position\"));\r\n\r\n\t\t\r\n\t\tNx::CModel* pModel = NULL;\r\n\t\tif ( mp_model_component )\r\n\t\t{\r\n\t\t\tpModel = mp_model_component->GetModel();\r\n\t\t}\r\n\t\t\r\n\t\t// if we have a model and the model is not active,then don't need to update the shadwo\r\n\t\tif (pModel)\r\n\t\t{\r\n\t\t\tif (pModel->GetActive())\r\n\t\t\t{\r\n\t\t\t\tswitch( mp_shadow->GetShadowType() )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase Gfx::vDETAILED_SHADOW:\r\n\t\t\t\t\t{\r\n\t\t//\t\t\t\tMth::Vector shadow_target_pos = pos + ( matrix.GetUp() * 36.0f );\r\n\t\t\t\t\t\tMth::Vector shadow_target_pos = GetObject()->m_pos + ( GetObject()->m_matrix.GetUp() * 36.0f );\r\n\r\n\t\t#ifdef __PLAT_XBOX__\r\n\t\t\t\t\t\t// K: Moved this in here cos it was giving an unused-variable compile error on PS2\r\n\t\t\t\t\t\tMth::Vector ground_dir( 0.2f, -0.8f, 0.3f );\r\n\r\n\t\t\t\t\t\t// If lights are active, set the ground direction to be that of the primary light.\r\n\t\t\t\t\t\tif( pModel )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tNx::CModelLights* p_lights = pModel->GetModelLights();\r\n\t\t\t\t\t\t\tif( p_lights )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tground_dir = p_lights->GetLightDirection( 0 ) * -1.0f;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t//\t\t\t\tmp_shadow->UpdateDirection( ground_dir );\r\n\t\t#endif\t\r\n\t\t\t\t\t\tmp_shadow->UpdatePosition( shadow_target_pos );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase Gfx::vSIMPLE_SHADOW:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( pModel )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t((Gfx::CSimpleShadow*)mp_shadow)->SetScale( pModel->GetScale().GetX() );\r\n\t\t\t\t\t\t}\t\r\n\r\n\t\t\t\t\t\t/*\r\n\t\t\t\t\t\tTODO:  Commented this section out, because it \r\n\t\t\t\t\t\treferences m_jump_start_pos, which isn't accessible\r\n\t\t\t\t\t\tfrom the shadow code yet...\r\n\r\n\t\t\t\t\t\tif ( GetMotionComponentFromObject( GetObject() )->m_movingobj_status & MOVINGOBJ_STATUS_JUMPING )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// If jumping, use the jump's start-y so that the shadow stays on the ground.\t\r\n\t\t\t\t\t\t\tMth::Vector p=GetObject()->m_pos;\r\n\t\t\t\t\t\t\tp[Y]=m_jump_start_pos[Y];\r\n\t\t\t\t\t\t\tmp_shadow->UpdatePosition(p,GetObject()->m_matrix,m_shadowNormal);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t*/\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmp_shadow->UpdatePosition( m_shadowPos, GetObject()->m_matrix, m_shadowNormal );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"Bad shadow type: %d\",mp_shadow->GetShadowType()));\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmp_shadow->UnHide();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// model is not active, so we probably don't want the shadow's model to be active either\r\n\t\t\t\tmp_shadow->Hide();\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CShadowComponent::Hide( bool shouldHide )\r\n{\r\n\tHideShadow( shouldHide );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CShadowComponent::Update()\r\n{\r\n//\tm_shadowNormal.Set( 0.0f, 1.0f, 0.0f );\r\n\r\n\t/*\r\n\tif ( mp_shadow )\r\n\t{\r\n\t\tif (mp_shadow->GetShadowType()==Gfx::vSIMPLE_SHADOW)\r\n\t\t{\r\n\t\t\tmp_shadow->UpdatePosition(m_shadow_pos,m_matrix,pShadowComponent->m_shadownormal);\r\n\t\t}\t\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_shadow->UpdatePosition(shadow_target_pos); // at this point m_pos is the same as mp_physics->m_pos\r\n\t\t}\r\n\t}\r\n\t*/\r\n\r\n\tif ( GetObject()->GetID() >= 0 && GetObject()->GetID() < Mdl::Skate::vMAX_SKATERS )\r\n\t{\r\n\t\t// the skater shadows are handled elsewhere by other components\r\n\t\t// (CSkaterAdjustPhysicsComponent or CWalkComponent)\r\n//\t\tSetShadowPos( GetObject()->GetPos() );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// the ped shadow is handled here...\r\n\t\tSetShadowPos( GetObject()->GetPos() );\r\n\t}\r\n\r\n\tupdate_shadow();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent::EMemberFunctionResult CShadowComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | Obj_ShadowOff | turn off shadow\r\n\t\tcase ( 0xaaf6e513 ): // Obj_ShadowOff\r\n\t\t\tSwitchOffShadow();\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_ShadowOn | turn shadow on\r\n\t\t// @parmopt float | Offset | 0.2 | The y offset of the shadow, > 0 = up\r\n\t\t// @parmopt float | ShadowScale | 1.0 | The scale of the shadow.\r\n\t\t// @parmopt string | ShadowModel | \"Ped_Shadow\" | The mdl file to use\r\n\t\t// @parmopt name | shadow_type | Either \"detailed\" or \"simple\"\r\n\t\tcase ( 0xf272c43a ): // Obj_ShadowOn\r\n\t\t{\r\n\t\t\t// add a default shadow_type\r\n\t\t\tuint32 shadowType;\r\n\t\t\tif ( !pParams->GetChecksum( \"shadowType\", &shadowType, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tpParams->AddChecksum( \"shadowType\", CRCD(0x3e84c2fd,\"simple\") );\r\n\t\t\t}\r\n\r\n\t\t\tthis->InitFromStructure( pParams );\r\n\r\n\t\t\tif ( mp_shadow )\r\n\t\t\t{\r\n\t\t\t\tif( mp_shadow->GetShadowType() == Gfx::vSIMPLE_SHADOW )\r\n\t\t\t\t{\r\n\t\t\t\t\tfloat offset=0.2f;\r\n\t\t\t\t\tpParams->GetFloat(CRCD(0xa6f5352f,\"Offset\"),&offset);\r\n\t\t\t\t\t((Gfx::CSimpleShadow*)mp_shadow)->SetOffset(offset);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CShadowComponent::SwitchOnShadow( Gfx::EShadowType mode )\r\n{\r\n\t\r\n\t\r\n\tif ( mp_shadow )\r\n\t{\r\n\t\t// it's already got a shadow\r\n\t\treturn;\r\n\t}\r\n\r\n// Note we can't use mp_model_component here, as SwitchOnShaodow is called\r\n// from InitFromStructure, which is obviously called before Finalize(); \r\n\tCModelComponent* pModelComponent = GetModelComponentFromObject( GetObject() );\r\n\tNx::CModel* pModel = NULL;\r\n\tif ( pModelComponent )\r\n\t{\r\n\t\tpModel = pModelComponent->GetModel();\r\n\t}\r\n\r\n\r\n\tswitch (mode)\r\n\t{\r\n\t\tcase Gfx::vDETAILED_SHADOW:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( mp_shadow == NULL, (\"mp_shadow not NULL?\") );\r\n\t\t\tDbg_MsgAssert( pModel, (\"adding detailed shadow to something with no model?\") );\r\n\t\t\tmp_shadow = new Gfx::CDetailedShadow( pModel );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase Gfx::vSIMPLE_SHADOW:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( mp_shadow == NULL, (\"mp_shadow not NULL?\") );\r\n\t\t\tDbg_MsgAssert( pModel, (\"adding simple shadow to something with no model?\") );\r\n\t\t\t\r\n\t\t\tGfx::CSimpleShadow* pSimpleShadow = new Gfx::CSimpleShadow;\r\n\t\t\tpSimpleShadow->SetScale( pModel->GetScale().GetX() );\r\n\t\t\tpSimpleShadow->SetModel( \"Ped_Shadow\" );\r\n\t\t\t\r\n\t\t\tmp_shadow = pSimpleShadow;\r\n\t\t\tmp_shadow->UpdatePosition( m_shadowPos, GetObject()->m_matrix, m_shadowNormal );\r\n\t\t}\t\r\n\t\tbreak;\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_Message( \"Unrecognized shadow mode %d\", mode );\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CShadowComponent::SwitchOffShadow()\r\n{\r\n\tif ( mp_shadow )\r\n\t{\r\n\t\tif ( mp_model_component )\r\n\t\t{\r\n\t\t\tNx::CModel* pModel = mp_model_component->GetModel();\r\n\t\t\tDbg_Assert( pModel );\r\n\t\t\tpModel->EnableShadow( false );\r\n\t\t}\r\n\r\n\t\tdelete mp_shadow;\r\n\t\tmp_shadow = NULL;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CShadowComponent::HideShadow( bool should_hide )\r\n{\r\n\tif ( mp_shadow )\r\n\t{\r\n\t\tif ( should_hide )\r\n\t\t{\r\n\t\t\tmp_shadow->Hide();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_shadow->UnHide();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CShadowComponent::SetShadowPos( const Mth::Vector& pos )\r\n{\r\n\tm_shadowPos = pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CShadowComponent::SetShadowNormal( const Mth::Vector& normal )\r\n{\r\n\tm_shadowNormal = normal;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CShadowComponent::SetShadowScale( float scale )\r\n{\r\n\tif ( m_shadowType == CRCD(0x3e84c2fd,\"simple\") )\r\n\t{\r\n\t\t((Gfx::CSimpleShadow*)mp_shadow)->SetScale( scale );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CShadowComponent::SetShadowDirection( const Mth::Vector& vector )\r\n{\r\n\tif( mp_shadow )\r\n\t{\r\n\t\tmp_shadow->UpdateDirection( vector );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CShadowComponent::SwitchOnSkaterShadow()\r\n{\r\n\t// NOTE: skater specific and should not be here; migrate to somewhere like Mdl::Skate\r\n\t\r\n\t// only call on shadows attached to skaters\r\n\tDbg_MsgAssert(GetObject()->GetType() == SKATE_TYPE_SKATER, (\"CShadowComponent::SwitchOnSkaterShadow called on shadow not attached to skater object\"));\r\n\t\r\n\tCSkater* pSkater = static_cast< CSkater* >(GetObject());\r\n\t\r\n\tGfx::EShadowType mode = Gfx::vDETAILED_SHADOW;\r\n\t\r\n\t// put it on the bottom up heap, because we don't want to fragment the skater geom heap...\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterHeap(pSkater->GetHeapIndex()));\r\n\r\n\t// In Splitscreen games, shadow type for local player is optional\r\n\tif (CFuncs::ScriptInSplitScreenGame(NULL, NULL))\r\n\t{\r\n\t\tmode = Mdl::Skate::Instance()->GetShadowMode();\r\n\t}\r\n\r\n\tif (!pSkater->IsLocalClient())\r\n\t{\r\n\t\tDbg_Printf( \"************************ SWITCHING ON SKATER SHADOW FOR CLIENT\\n\" );\r\n\t\tmode = Gfx::vSIMPLE_SHADOW;\r\n\t}\r\n\t\r\n\tScript::CStruct* pTempParams = new Script::CStruct;\r\n\tpTempParams->AddFloat(CRCD(0x6f8cd62f, \"ShadowScale\"), 1.0f);\r\n\tpTempParams->AddString(CRCD(0x545f8172, \"ShadowModel\"), \"Ped_Shadow\");\r\n\tInitFromStructure(pTempParams);\r\n\tdelete pTempParams;\r\n\r\n\tSwitchOffShadow();\r\n\tSwitchOnShadow(mode);\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/shadowcomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       ShadowComponent.h\r\n//* OWNER:\t\t\tGary\r\n//* CREATION DATE:  2/06/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SHADOWCOMPONENT_H__\r\n#define __COMPONENTS_SHADOWCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n// For EShadowType\r\n#include <gfx/shadow.h>\r\n\r\n#include <core/math.h>\r\n\t\t\t\r\n#include <gel/object/basecomponent.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_SHADOW CRCD(0x8a897dd2,\"shadow\")\r\n#define\t\tGetShadowComponent() ((CShadowComponent*)GetComponent(CRC_SHADOW))\r\n#define\t\tGetShadowComponentFromObject(pObj) ((Obj::CShadowComponent*)(pObj)->GetComponent(CRC_SHADOW))\r\n\r\nnamespace Gfx\r\n{\r\n\tclass CShadow;\r\n}\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass\tCModelComponent;\r\n\r\nclass CShadowComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CShadowComponent();\r\n    virtual ~CShadowComponent();\r\n\r\npublic:\r\n    virtual void\t\t\t\t\tFinalize( );\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void\t\t\t\t\tHide( bool should_hide );\r\n\tvirtual void\t\t\t\t\tTeleport();\r\n\r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\t\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\nprotected: \r\n\tvoid\t\t\t\t\t\t\tupdate_shadow();\r\n\t\t\r\n\t\t\r\npublic:\t\t\r\n\tvoid\t\t\t\t\t\t\tSwitchOnShadow(Gfx::EShadowType mode);\r\n\tvoid \t\t\t\t\t\t\tSwitchOffShadow();\r\n\tvoid \t\t\t\t\t\t\tHideShadow( bool should_hide );\r\n\tvoid\t\t\t\t\t\t\tSetShadowPos( const Mth::Vector& vector );\r\n\tvoid\t\t\t\t\t\t\tSetShadowNormal( const Mth::Vector& vector );\r\n\tvoid\t\t\t\t\t\t\tSetShadowScale( float scale );\r\n\tvoid\t\t\t\t\t\t\tSetShadowDirection( const Mth::Vector& vector );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSwitchOnSkaterShadow();\r\n\r\nprotected:\r\n\tGfx::CShadow *\t\t\t\t\tmp_shadow;\r\n\tMth::Vector\t\t\t\t\t\tm_shadowPos;\r\n\tMth::Vector\t\t\t\t\t\tm_shadowNormal;\r\n\tuint32\t\t\t\t\t\t\tm_shadowType;\r\n\tCModelComponent * \t\t\t\tmp_model_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/skeletoncomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SkeletonComponent.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/22/2002\r\n//****************************************************************************\r\n\r\n#include <gel/components/skeletoncomponent.h>\r\n\r\n#include <gel/assman/assman.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/skeleton.h>\r\n\r\n// TODO:  These won't be needed after the initial\r\n// matrix data gets moved to the SKE file\r\n#include <core/crc.h>\r\n#include <core/math.h>\r\n#include <gfx/nxanimcache.h>\r\n#include <gfx/bonedanim.h>\r\n#include <gfx/nxmiscfx.h>\r\n\r\n// GJ:  CSkeletonComponent is supposed to be a wrapper\r\n// around the Gfx::CSkeleton, which contains a skeletal\r\n// object's final, post-blend matrix buffer.  It should\r\n// be pretty dumb;  neither the CSkeletonComponent nor\r\n// the Gfx::CSkeleton should contain any blending or \r\n// procedural anim data or functionality.  Furthermore, \r\n// it shouldn't know anything about animation flipping\r\n// or skateboard rotation.   \t    \r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// This static function is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\nCBaseComponent* CSkeletonComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkeletonComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkeletonComponent::init_skeleton( uint32 skeleton_name )\r\n{\r\n\tDbg_MsgAssert( mp_skeleton == NULL, ( \"Component already has skeleton.\" ) );\r\n    \r\n\tGfx::CSkeletonData* pSkeletonData = (Gfx::CSkeletonData*)Ass::CAssMan::Instance()->GetAsset( skeleton_name, false );\r\n\r\n\tif ( !pSkeletonData )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, (\"Unrecognized skeleton %s. (Is skeleton.q up to date?)\", Script::FindChecksumName(skeleton_name)) );\r\n\t}\r\n    \r\n\tmp_skeleton = new Gfx::CSkeleton( pSkeletonData );   \r\n    Dbg_MsgAssert( mp_skeleton, ( \"Couldn't create skeleton\" ) );\r\n\r\n    Dbg_MsgAssert( mp_skeleton->GetNumBones() > 0, ( \"Skeleton needs at least one bone\" ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkeletonComponent::CSkeletonComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKELETON );\r\n\r\n    mp_skeleton = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkeletonComponent::~CSkeletonComponent()\r\n{\r\n    Dbg_MsgAssert( mp_skeleton, ( \"No skeleton had been initialized\" ) );\r\n    \r\n    if ( mp_skeleton )\r\n    {\r\n        delete mp_skeleton;\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSkeletonComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n    uint32 skeletonName;\r\n\r\n    if ( !pParams->GetChecksum( CRCD(0x222756d5,\"skeleton\"), &skeletonName, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tpParams->GetChecksum( CRCD(0x9794932,\"skeletonName\"), &skeletonName, Script::ASSERT );\r\n\t}\r\n\r\n    init_skeleton( skeletonName );\r\n\r\n\tint maxBoneSkipLOD;\r\n\tif(( pParams->GetInteger( CRCD(0xd3982061,\"max_bone_skip_lod\"), &maxBoneSkipLOD )) && mp_skeleton )\r\n\t{\r\n\t\tmp_skeleton->SetMaxBoneSkipLOD( maxBoneSkipLOD );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSkeletonComponent::Update()\r\n{\r\n\t// Doing nothing, so tell code to do nothing next time around\r\n\tSuspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nGfx::CSkeleton* CSkeletonComponent::GetSkeleton()\r\n{\r\n    return mp_skeleton;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkeletonComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch (Checksum)\r\n    {\r\n\t\t// @script | Obj_SetBoneActive | changes whether the bone should be updated once per frame\r\n\t\tcase 0x20f7b992: // Obj_SetBoneActive\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( mp_skeleton, ( \"Obj_SetBoneActive on object without a skeleton\" ) );\r\n\t\t\t\r\n\t\t\tuint32 boneName;\r\n\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, Script::ASSERT );\r\n\t\t\t\r\n\t\t\tint enabled;\r\n\t\t\tpParams->GetInteger( CRCD(0xb4e103fd,\"active\"), &enabled, Script::ASSERT );\r\n\r\n\t\t\tDbg_Assert( mp_skeleton );\r\n            mp_skeleton->SetBoneActive( boneName, enabled );\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0xbe1c58ca:\t// Obj_GetBonePosition\r\n\t\t{\r\n\t\t\tMth::Vector bonePos(0.0f,0.0f,0.0f,1.0f);\r\n\r\n\t\t\tuint32 boneName;\r\n\t\t\tpParams->GetChecksum( CRCD(0xcab94088, \"bone\"), &boneName, Script::ASSERT );\r\n\t\t\tbool success = GetBoneWorldPosition( boneName, &bonePos );\r\n\t\t\t\r\n\t\t\t// make sure we have somewhere to return the data\r\n\t\t\tDbg_Assert( pScript && pScript->GetParams() );\r\n\t\t\tpScript->GetParams()->AddFloat( CRCD(0x7323e97c,\"x\"), bonePos[X] );\r\n\t\t\tpScript->GetParams()->AddFloat( CRCD(0x424d9ea,\"y\"), bonePos[Y] );\r\n\t\t\tpScript->GetParams()->AddFloat( CRCD(0x9d2d8850,\"z\"), bonePos[Z] );\r\n\t\t\r\n\t\t\treturn success ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | TextureSplat | create a texture splat\r\n        // @parm float | size | \r\n        // @parmopt float | lifetime | 5.0 | lifetime in seconds\r\n        // @parmopt float | radius | 0.0 | radius\r\n        // @parmopt float | dropdown_length | 3.0 | dropdown length in feet\r\n        // @parmopt float | forward | | distance forward of the origin that this spat goes, assuming no bone specififed\t\t\r\n        // @parmopt string | bone || bone name\r\n        // @parmopt string | name || texture name\r\n        // @parmopt string | trail || indicates that this splat should start or join a trail\r\n\t\tcase CRCC(0xb244c9cf,\"TextureSplat\"):\r\n\t\t\t\r\n\t\t// @script | Skeleton_SpawnTextureSplat | create a texture splat\r\n\t\t// @parm float | size | \r\n\t\t// @parmopt float | lifetime | 5.0 | lifetime in seconds\r\n\t\t// @parmopt float | radius | 0.0 | radius\r\n\t\t// @parmopt float | dropdown_length | 3.0 | dropdown length in feet\r\n\t\t// @parmopt float | forward | | distance forward of the origin that this spat goes, assuming no bone specififed\t\t\r\n\t\t// @parmopt string | bone || bone name\r\n\t\t// @parmopt string | name || texture name\r\n\t\t// @parmopt string | trail || indicates that this splat should start or join a trail\r\n\t\tcase CRCC(0xc51ce359, \"Skeleton_SpawnTextureSplat\"):\r\n\t\t{\t\r\n\t\t\tfloat\t\tsize;\r\n\t\t\tfloat\t\tradius\t\t\t\t= 0.0f;\r\n\t\t\tfloat\t\tlifetime\t\t\t= 5.0f;\r\n\t\t\tfloat\t\tdropdown_length\t\t= 3.0f;\r\n\t\t\tfloat \t\tforward \t\t\t= 0.0f;\r\n\t\t\tbool\t\ttrail\t\t\t\t= pParams->ContainsFlag( 0x4d977a70 /*\"trail\"*/ );\r\n\t\t\tbool\t\tdropdown_vertical\t= pParams->ContainsFlag( 0x7ee6c892 /*\"dropdown_vertical\"*/ );\r\n\t\t\tuint32\t\tbone_name_checksum  = 0;\r\n\t\t\tconst char*\tp_texture_name;\r\n\t\t\tMth::Vector\tpos;\r\n\r\n\t\t\tpParams->GetFloat( CRCD(0x83fdb95,\"size\"), &size );\r\n\t\t\tpParams->GetFloat( CRCD(0xc48391a5,\"radius\"), &radius );\r\n\t\t\tpParams->GetFloat( CRCD(0xc218cf77,\"lifetime\"), &lifetime );\r\n\t\t\tpParams->GetFloat( CRCD(0x12c62572,\"dropdown_length\"), &dropdown_length );\r\n\t\t\t\r\n\t\t\tif( !( pParams->GetText( \"name\", &p_texture_name )))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0, (\"%s\\nTextureSplat requires a texture name\"));\r\n\t\t\t}\r\n\r\n\t\t\tif( !(pParams->GetChecksumOrStringChecksum( \"bone\", &bone_name_checksum )))\r\n\t\t\t{\r\n\t\t\t\tif (!pParams->GetFloat( CRCD(0x186ed079,\"forward\"), &forward ))\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( 0, (\"%s\\nTextureSplat requires a bone name\"));\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpos = GetObject()->GetPos();\r\n\t\t\t\t\tpos += forward * GetObject()->GetMatrix()[Z];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tSpawnTextureSplat( pos, bone_name_checksum, size, radius, lifetime, dropdown_length, p_texture_name, trail, dropdown_vertical );\r\n            break;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | Skeleton_SpawnCompositeObject | creates a rigidbody at the specified bone's position and orientation\r\n\t\t// finish autoducking\r\n\t\tcase CRCC(0xf99f9faf, \"Skeleton_SpawnCompositeObject\"):\r\n\t\t{\r\n\t\t\tuint32 bone_name;\r\n\t\t\tpParams->GetChecksum(CRCD(0xcab94088, \"bone\"), &bone_name, Script::ASSERT);\r\n\t\t\t\r\n\t\t\tMth::Vector offset;\r\n\t\t\toffset.Set();\r\n\t\t\tpParams->GetVector(CRCD(0xa6f5352f, \"offset\"), &offset);\r\n\t\t\t\r\n\t\t\tScript::CArray* p_component_array;\r\n\t\t\tpParams->GetArray(CRCD(0x11b70a02, \"components\"), &p_component_array, Script::ASSERT);\r\n\t\t\t\r\n\t\t\tScript::CStruct* p_params;\r\n\t\t\tpParams->GetStructure(CRCD(0x7031f10c, \"params\"), &p_params, Script::ASSERT);\r\n\t\t\t\r\n\t\t\tMth::Vector relative_vel;\r\n\t\t\tpParams->GetVector(CRCD(0xc4c809e, \"vel\"), &relative_vel, Script::ASSERT);\r\n\t\t\t\r\n\t\t\tMth::Vector relative_rotvel;\r\n\t\t\tpParams->GetVector(CRCD(0xfb1a83b2, \"rotvel\"), &relative_rotvel, Script::ASSERT);\r\n\t\t\t\r\n\t\t\tfloat object_vel_factor = 1.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0x8c6a6e08, \"object_vel_factor\"), &object_vel_factor);\r\n\t\t\t\r\n\t\t\tSpawnCompositeObject(bone_name, p_component_array, p_params, object_vel_factor, relative_vel, relative_rotvel, offset);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        default:\r\n            return CBaseComponent::MF_NOT_EXECUTED;\r\n    }\r\n\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkeletonComponent::GetBonePosition( uint32 boneName, Mth::Vector* pBonePos )\r\n{\r\n\tDbg_Assert(mp_skeleton);\r\n\treturn mp_skeleton->GetBonePosition(boneName, pBonePos);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkeletonComponent::GetBoneWorldPosition( uint32 boneName, Mth::Vector* pBonePos )\r\n{\r\n\tDbg_Assert(mp_skeleton);\r\n\t\r\n\tif ( !mp_skeleton->GetBonePosition( boneName, pBonePos ) )\r\n\t{\r\n\t\tpBonePos->Set( 0.0f, 0.0f, 0.0f );\r\n\t}\r\n\r\n\t// now tranform it by the position of the object\r\n    Mth::Matrix rootMatrix;\r\n    rootMatrix = GetObject()->GetMatrix();\r\n    rootMatrix[Mth::POS] = GetObject()->GetPos();\r\n\trootMatrix[Mth::POS][W] = 1.0f;\r\n\tMth::Vector vec = rootMatrix.Transform(* pBonePos );\r\n\t(*pBonePos) = vec;\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkeletonComponent::SpawnTextureSplat( Mth::Vector& pos, uint32 bone_name_checksum, float size, float radius, float lifetime, float dropdown_length, const char *p_texture_name, bool trail, bool dropdown_vertical )\r\n{\r\n\tMth::Vector bone_pos;\r\n\tif (!bone_name_checksum)\r\n\t{\r\n\t\tbone_pos = pos;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGetBoneWorldPosition( bone_name_checksum, &bone_pos );\r\n\t}\r\n\r\n\t// Convert dropdown_length from feet to inches.\r\n\tdropdown_length *= 12.0f;\r\n\t\r\n\t// Calculate the end position by dropping down 3 feet along the skater's up vector, or 'world up',\r\n\t// depending on the dropdown_vertical flag.\r\n\tMth::Vector end;\r\n\tif( dropdown_vertical )\r\n\t{\r\n\t\tend = bone_pos - ( Mth::Vector( 0.0f, 1.0f, 0.0f ) * dropdown_length );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tend = bone_pos - ( GetObject()->GetMatrix().GetUp() * dropdown_length );\r\n\t}\r\n\t\r\n\t// In some cases, the bone can be beneath geometry (trucks during a revert), so move the start position up slightly.\r\n\tbone_pos += ( GetObject()->GetMatrix().GetUp() * 12.0f );\r\n\t\r\n\t// Calculate radial offset for end position.\r\n\tif( radius > 0.0f )\r\n\t{\r\n\t\tfloat x_offset = -radius + (( radius * 2.0f ) * (float)rand() / RAND_MAX );\r\n\t\tfloat z_offset = -radius + (( radius * 2.0f ) * (float)rand() / RAND_MAX );\r\n\r\n\t\tend += ( GetObject()->GetMatrix().GetRight() * x_offset );\r\n\t\tend += ( GetObject()->GetMatrix().GetAt() * z_offset );\r\n\t}\r\n\t\r\n\tNx::TextureSplat( bone_pos, end, size, lifetime, p_texture_name, trail ? bone_name_checksum : 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkeletonComponent::SpawnCompositeObject ( uint32 bone_name, Script::CArray* pArray, Script::CStruct* pParams,\r\n\tfloat object_vel_factor, Mth::Vector& relative_vel, Mth::Vector& relative_rotvel, Mth::Vector& offset )\r\n{\r\n\tDbg_Assert(pArray);\r\n\tDbg_Assert(pParams);\r\n\t\r\n\tCSkeletonComponent* p_skeleton_component = GetSkeletonComponentFromObject(GetObject());\r\n\tDbg_Assert(p_skeleton_component);\r\n\r\n\t// get the bone's matrix\r\n\tMth::Matrix bone_matrix;\r\n\tp_skeleton_component->GetSkeleton()->GetBoneMatrix(bone_name, &bone_matrix);\r\n\t\r\n\t// build the object's matrix\r\n\tMth::Matrix object_matrix = GetObject()->GetMatrix();\r\n\tobject_matrix[W] = GetObject()->GetPos();\r\n\tobject_matrix[X][W] = 0.0f;\r\n\tobject_matrix[Y][W] = 0.0f;\r\n\tobject_matrix[Z][W] = 0.0f;\r\n\t\r\n\t// NOTE: gludge to fix skater board model's coordinate system to match board bone's system\r\n\tMth::Vector temp;\r\n\ttemp = bone_matrix[Y];\r\n\tbone_matrix[Y] = bone_matrix[Z];\r\n\tbone_matrix[Z] = -temp;\r\n\toffset[W] = 0.0f;\r\n\tbone_matrix[W] += offset;\r\n\t\r\n\t// map the bone to world space\r\n\tbone_matrix *= object_matrix;\r\n\t\r\n\t// write the bone state into the composite object parameters\r\n\t\r\n\tpParams->AddVector(CRCD(0x7f261953, \"pos\"), bone_matrix[W]);\r\n\t\r\n\tMth::Quat orientation(bone_matrix);\r\n\tif (orientation.GetScalar() > 0.0f)\r\n\t{\r\n\t\tpParams->AddVector(CRCD(0xc97f3aa9, \"orientation\"), orientation.GetVector());\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpParams->AddVector(CRCD(0xc97f3aa9, \"orientation\"), -orientation.GetVector());\r\n\t}\r\n\t\r\n\t// setup rigidbody's initial velocity\r\n\tMth::Vector vel = object_vel_factor * GetObject()->GetVel() + GetObject()->GetMatrix().Rotate(relative_vel);\r\n\tpParams->AddVector(CRCD(0xc4c809e, \"vel\"), vel);\r\n\t\r\n\t// setup rigidbody's initial rotational velocity\r\n\tMth::Vector rotvel = GetObject()->GetMatrix().Rotate(relative_rotvel);\r\n\tpParams->AddVector(CRCD(0xfb1a83b2, \"rotvel\"), rotvel);\r\n\t\r\n\tCCompositeObjectManager::Instance()->CreateCompositeObjectFromNode(pArray, pParams);\r\n}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gel/Components/skeletoncomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SkeletonComponent.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/17/2002\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKELETONCOMPONENT_H__\r\n#define __COMPONENTS_SKELETONCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_SKELETON CRCD(0x222756d5,\"Skeleton\")\r\n#define\t\tGetSkeletonComponent() ((Obj::CSkeletonComponent*)GetComponent(CRC_SKELETON))\r\n#define\t\tGetSkeletonComponentFromObject(pObj) ((Obj::CSkeletonComponent*)(pObj)->GetComponent(CRC_SKELETON))\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nnamespace Gfx\r\n{\r\n    class CSkeleton;\r\n}\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nclass CSkeletonComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkeletonComponent();\r\n    virtual ~CSkeletonComponent();\r\n\r\npublic:\r\n    virtual void            Update();\r\n    virtual void            InitFromStructure( Script::CStruct* pParams );\r\n    \r\n    EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\t\r\n    static CBaseComponent*\ts_create();\r\n    Gfx::CSkeleton*         GetSkeleton();\r\n\r\n    bool\t\t\t\t\tGetBonePosition( uint32 boneName, Mth::Vector* pBonePos );\r\n\tbool\t\t\t\t\tGetBoneWorldPosition( uint32 boneName, Mth::Vector* pBonePos );\r\n\t\r\n\tvoid\t\t\t\t\tSpawnTextureSplat( Mth::Vector& pos, uint32 bone_name_checksum, float size, float radius, float lifetime, float dropdown_length, const char *p_texture_name, bool trail, bool dropdown_vertical );\r\n\tvoid\t\t\t\t\tSpawnCompositeObject ( uint32 bone_name, Script::CArray* pArray, Script::CStruct* pParams, float object_vel_factor, Mth::Vector& relative_vel, Mth::Vector& relative_rotvel, Mth::Vector& offset );\r\n\r\nprotected:\r\n    void                    init_skeleton( uint32 skeleton_name );\r\n\t\r\nprotected:\r\n    Gfx::CSkeleton*         mp_skeleton;\r\n};\r\n\t\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/soundcomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SoundComponent.cpp\r\n//* OWNER:          Mick West\r\n//* CREATION DATE:  10/17/2002\r\n//****************************************************************************\r\n\r\n// start autoduck documentation\r\n// @DOC soundcomponent.cpp\r\n// @module soundcomponent | None\r\n// @subindex Scripting Database\r\n// @index script | soundcomponent\r\n\r\n#include <gel/components/soundcomponent.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/objsearch.h>\r\n#include <gel/objman.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gfx/nxviewman.h>\r\n\r\n// TODO:  Refactor this - \r\n#include <sk/modules/frontend/frontend.h>\r\n#include <sk/objects/emitter.h>\r\n#include <sk/objects/proxim.h>\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent *\tCSoundComponent::s_create()\r\n{\r\n\treturn static_cast<CBaseComponent*>(new CSoundComponent);\t\r\n}\r\n    \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSoundComponent::CSoundComponent() : CBaseComponent()\r\n{\r\n\tSetType(CRC_SOUND);\r\n\tmp_emitter = NULL;\r\n\tmp_proxim_node = NULL;\r\n\tm_pos.Set();\r\n\tm_old_pos.Set();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSoundComponent::~CSoundComponent()\r\n{\r\n\t// Tell the sound manager that the sond component is being removed to clean up\r\n\t// any sound effects that are attached to this\r\n\tSfx::CSfxManager::Instance()->ObjectBeingRemoved( this );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSoundComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tuint32 proxim_node_checksum;\r\n\r\n\tif (pParams->GetChecksum(\"ProximNode\", &proxim_node_checksum))\r\n\t{\r\n\t\t//Dbg_Message(\"SoundComponent: Looking for ProximNode %s\", Script::FindChecksumName(proxim_node_checksum));\r\n\t\tmp_proxim_node = CProximManager::sGetNode(proxim_node_checksum);\r\n\t\t//if (mp_proxim_node)\r\n\t\t//{\r\n\t\t//\tDbg_Message(\"Found ProximNode %s\", Script::FindChecksumName(mp_proxim_node->m_name));\r\n\t\t//}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSoundComponent::Update()\r\n{\r\n\t\r\n\t// For tracking the position of the sound, then \r\n\t// we need to update the old position and the current position\r\n\tm_old_pos = m_pos;\r\n\tm_pos = GetObject()->m_pos;\r\n\t\r\n\t\r\n\tUpdateMutedSounds();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSoundComponent::Teleport()\r\n{\r\n\t// Garrett: Note that this doesn't update currently playing sounds.  That won't happen\r\n\t// until the next sound update iteration.\r\n\tUpdate();\r\n\r\n\t//Dbg_Message(\"SoundComponent: Teleporting to (%f, %f, %f)\", m_pos[X], m_pos[Y], m_pos[Z]);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nCBaseComponent::EMemberFunctionResult CSoundComponent::CallMemberFunction( uint32 Checksum, Script::CScriptStructure *pParams, Script::CScript *pScript )\r\n{\r\n\r\n\tswitch (Checksum)\r\n\t{\r\n\t\t// @script | Obj_PlaySound | Add your own enums to sfx_*.q.  Up to 8 allowed (0 - 7), \r\n\t\t// @flag Filename | name of the sound (filename without the quotes) or \r\n\t\t// Type = [as defined in Obj_SetSound] \r\n\t\t// @parm name | Type | the type (if this is being called from a car script, for example, \r\n\t\t// use CARSFX_HONK, or another enum from sfx_car.q (similarly for ped: sfx_ped.q)\r\n\t\t// @parmopt float | vol | 100 | This is the volume of the wav AFTER being modified \r\n\t\t// by the volume (if specified) in LoadSound \r\n\t\t// @parmopt float | pitch | 100 | range: 1 to 300 (assuming normal pitch in LoadSound) \r\n\t\tcase 0xafa20e18:  // \"Obj_PlaySound\"\r\n\t\t\tPlayScriptedSound( pParams );\r\n\t\t\treturn MF_TRUE;\r\n\t\r\n\t\t// @script | Obj_AdjustSound | This function adjusts a looping sound \r\n\t\t// associated with an object. If no volumeStep is specified, volume is \r\n\t\t// adjusted immediately, same with pitchStep and pitch.  If volumeStep \r\n\t\t// or pitchStep are specified, the current volume/pitch is adjusted towards \r\n\t\t// the target by the step, each frame (or 60 times a second, rather). So \r\n\t\t// if the current pitch is 100, and you call: Obj_AdjustSound pitch = 40 \r\n\t\t// pitchStep = 1 It will take one second for the pitch to go from 100 to 40. \r\n\t\t// The percent values (pitchPercent and volumePercent) modify the overall \r\n\t\t// pitch or volume after taking into consideration the pitch specified globally \r\n\t\t// during the LoadSound call, then specified per this object on the Obj_\r\n\t\t// PlaySound call (see example).\r\n\t\t// @flag Filename | name of the sound you want to adjust (no quotes)\r\n\t\t// @parm float | VolumePercent | Percentage to adjust the volume\r\n\t\t// @parm float | PitchPercent | Percentage to adjust the pitch\r\n\t\t// @parmopt float | VolumeStep | 0 |  Amount of time in seconds it takes to go from the current volume to new volume.\r\n\t\t// @parmopt float | PitchStep | 0 | Amount of time in seconds it takes to go from the current pith to new pitch.\r\n\t\tcase 0x3e5e8023: // \"Obj_AdjustSound\"\r\n\t\t\tAdjustObjectSound( pParams, pScript );\r\n\t\t\treturn MF_TRUE;\r\n\t\t\r\n\t\t// @script | Obj_StopSound | Obj_StopSound doesn't take a type = parameter... \r\n\t\t// it is used only for stopping a looping sound by checksum. If you don't \r\n\t\t// specify the name of the sound, all sounds that were loaded with PosUpdate \r\n\t\t// or PosUpdateWithDoppler parameters and are associated with the object \r\n\t\t// calling this will be stopped.\r\n\t\t// @flag Filename | name of the sound you want to stop (no quotes)\r\n\t\tcase 0x4e4132d6: // \"Obj_StopSound\"\r\n\t\t{\r\n\t\t\tuint32 soundChecksum = 0;\r\n\t\t\tpParams->GetChecksum( NONAME, &soundChecksum );\r\n\t\t\tSfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();\r\n\t\t\tsfx_manager->StopObjectSound( this, soundChecksum );\r\n\t\t\t// if it's temporarily out of range, we gotta stop it too!\r\n\t\t\tint i;\r\n\t\t\tfor ( i = 0; i < MAX_NUM_LOOPING_SOUNDS_PER_OBJECT; i++ )\r\n\t\t\t{\r\n\t\t\t\tif ( mSoundInfo[ i ].checksum == soundChecksum )\r\n\t\t\t\t{\r\n\t\t\t\t\t// since a sound checksum of 0 is invalid, this turns off the update:\r\n\t\t\t\t\tmSoundInfo[ i ].checksum = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn MF_TRUE;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | Obj_SetSound | Add your own enums to sfx_*.q.  Up to 8 allowed (0 - 7), \r\n\t\t// can be increased easily.  Use Obj_PlaySound (with the optional Type = * parameter \r\n\t\t// instead of the filename) to trigger one of these sounds to be played.  Don't \r\n\t\t// trigger a looping sound!  The engine loop on the car needs to be set up per car \r\n\t\t// using this function, but the update happens in the game engine (pun regretted because \r\n\t\t// it's confusing).  Don't forget to load the sounds specified by 'filename'.\r\n\t\t// @flag Filename | Name of the sound, no quotes\r\n\t\t// @parm name | Type | the type (if this is being called from a car script, for example, \r\n\t\t// use CARSFX_HONK, or another enum from sfx_car.q (similarly for ped: sfx_ped.q)\r\n\t\tcase 0xe8347171:  // \"Obj_SetSound\"\r\n\t\t\tSetSound( pParams );\r\n\t\t\treturn MF_TRUE;\r\n\t}\r\n\treturn MF_NOT_EXECUTED;\r\n}\r\n\r\nvoid CSoundComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSoundComponent::GetDebugInfo\"));\r\n\t// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n\t\r\n\tScript::CArray *p_array=new Script::CArray;\r\n\tp_array->SetSizeAndType(MAX_NUM_SOUNDFX_CHECKSUMS,ESYMBOLTYPE_NAME);\r\n\tfor (int i=0; i<MAX_NUM_SOUNDFX_CHECKSUMS; ++i)\r\n\t{\r\n\t\tp_array->SetChecksum(i,mSoundFXChecksums[i]);\r\n\t}\r\n\tp_info->AddArrayPointer(\"mSoundFXChecksums\",p_array);\r\n\r\n\tp_array=new Script::CArray;\r\n\tp_array->SetSizeAndType(MAX_NUM_LOOPING_SOUNDS_PER_OBJECT,ESYMBOLTYPE_STRUCTURE);\r\n\tfor (int i=0; i<MAX_NUM_LOOPING_SOUNDS_PER_OBJECT; ++i)\r\n\t{\r\n\t\tScript::CStruct *p_struct=new Script::CStruct;\r\n\t\tmSoundInfo[i].GetDebugInfo(p_struct);\r\n\t\tp_array->SetStructure(i,p_struct);\r\n\t}\t\r\n\tp_info->AddArrayPointer(\"mSoundInfo\",p_array);\r\n#endif\t\t\t\t \r\n}\r\n\r\n#define CHECKSUM_TYPE\t0x7321a8d6  // 'type'\r\n\r\n// Set individual soundfx for objects...\r\n// Designers can also trigger these sounds to be played by using the Obj_PlaySound\r\n// script command, using type =  (instead of using the checksum) to define the sound.\r\nvoid CSoundComponent::SetSound( Script::CScriptStructure *pParams )\r\n{\r\n\t\r\n\tint type = -1;\r\n\tuint32 soundChecksum = 0;\r\n\tpParams->GetInteger( CHECKSUM_TYPE, &type );\r\n\tpParams->GetChecksum( NONAME, &soundChecksum );\r\n\tif ( type == -1 )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Script command Obj_SetSound used without specifying sound type.\" ));\r\n\t\treturn;\r\n\t}\r\n\tif ( !soundChecksum )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Script command Obj_SetSound used without specifying name of sound.\" ));\r\n\t\treturn;\r\n\t}\r\n\tif ( ( type > MAX_NUM_SOUNDFX_CHECKSUMS ) || ( type == -1 ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Matt needs to increase MAX_NUM_SOUND_CHECKSUMS (or bad type %d sent in...)\", type ));\r\n\t\treturn;\r\n\t}\r\n\tmSoundFXChecksums[ type ] = soundChecksum;\r\n} // end of SetSound( )\r\n\r\n\r\nvoid CSoundComponent::PlayScriptedSound( Script::CScriptStructure *pParams )\r\n{\r\n\tuint32 soundChecksum = 0;\r\n\tuint32 emitterChecksum = 0;\r\n\tuint32 dropoffFuncChecksum;\r\n\tfloat volume = 100.0f;\r\n\tfloat pitch = 100.0f;\r\n\tfloat dropoffDist = 0.0f;\r\n\tEDropoffFunc dropoffFunction = DROPOFF_FUNC_STANDARD;\r\n\tbool noPosUpdate = false;\r\n    \r\n\tpParams->GetChecksum( NONAME, &soundChecksum );\r\n\tpParams->GetFloat( 0xf6a36814, &volume ); // \"vol\"\r\n\tpParams->GetFloat( 0xd8604126, &pitch ); // \"pitch\"\r\n\t\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x9e497fc6, \"Percent\")))\r\n\t{\r\n\t\tfloat minVol = 0.0f;\r\n\t\tfloat maxVol = 100.0f;\r\n\t\tfloat minPitch = 100.0f;\r\n\t\tfloat maxPitch = 100.0f;\r\n\t\t\r\n\t\tpParams->GetFloat(CRCD(0x0693daaf, \"MaxVol\"), &maxVol);\r\n\t\tpParams->GetFloat(CRCD(0x4391992d, \"MinVol\"), &minVol);\r\n\t\tpParams->GetFloat(CRCD(0xfa3e14c5, \"MaxPitch\"), &maxPitch);\r\n\t\tpParams->GetFloat(CRCD(0x1c5ebb24, \"MinPitch\"), &minPitch);\r\n\t\t\r\n\t\tfloat percent;\r\n\t\tpParams->GetFloat(CRCD(0x9e497fc6, \"Percent\"), &percent, Script::ASSERT);\r\n\t\tpercent *= (1.0f / 100.0f);\r\n\t\t\r\n\t\tvolume = Mth::Lerp(minVol, maxVol, percent);\r\n\t\tpitch = Mth::Lerp(minPitch, maxPitch, percent);\r\n\t}\r\n\t\r\n\tif ( pParams->GetFloat( 0xff2020ec, &dropoffDist ) ) // \"dropoff\"\r\n\t{\r\n\t\tdropoffDist = FEET_TO_INCHES( dropoffDist );\r\n\t}\r\n\tif ( pParams->GetChecksum( 0xc6ac50a, &dropoffFuncChecksum ) ) // \"dropoff_function\"\r\n\t{\r\n\t\tdropoffFunction = Sfx::GetDropoffFunctionFromChecksum( dropoffFuncChecksum );\r\n\t}\r\n\tif ( pParams->ContainsFlag( 0xbb39837f ) ) // \"NoPosUpdate\"\r\n\t{\r\n\t\tnoPosUpdate = true;\r\n\t}\r\n\tif (pParams->GetChecksum( 0x8a7132ce, &emitterChecksum ) ) // \"emitter\"\r\n\t{\r\n\t\tmp_emitter = CEmitterManager::sGetEmitter(emitterChecksum);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_emitter = NULL;\r\n\t}\r\n\r\n\tif ( !soundChecksum )\r\n\t{\r\n\t\t// If the checksum isn't specified, the designer may be requesting\r\n\t\t// to trigger a sound that can be individually specified per object\r\n\t\t// using the script command Obj_SetSound...\r\n\t\t// If that is the case, there will be a 'type = X' included, where\r\n\t\t// X is an enum such as CARSFX_HONK.\r\n\t\tint type = -1;\r\n\t\tpParams->GetInteger( \"Type\", &type );\r\n\t\tif ( type == -1 )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"Obj_PlaySound requires the name of the sound or a type specified (as in type = CARSFX_HONK)\" ));\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif ( type > MAX_NUM_SOUNDFX_CHECKSUMS )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"Bad type (%d) sent to Obj_PlaySound\", type ));\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tsoundChecksum = mSoundFXChecksums[ type ];\r\n\t\tif ( !soundChecksum )\r\n\t\t{\r\n\t\t\tDbg_Message( \"Object trying to play sound type %d, which hasn't been defined.\", type );\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// network stuff for higher level objects (need to add the update flag to this...)\r\n\tBroadcastScriptedSound( soundChecksum, volume, pitch );\r\n\t\r\n\tPlaySound_VolumeAndPan( soundChecksum, volume, pitch, dropoffDist, dropoffFunction, noPosUpdate );\r\n}// end of PlayScriptedSound( )\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector\t\tCSoundComponent::GetClosestEmitterPos( Gfx::Camera *pCamera )\r\n{\r\n\tif (mp_emitter && pCamera)\r\n\t{\r\n\t\treturn mp_emitter->GetClosestPoint(pCamera->GetPos());\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn m_pos;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector\t\tCSoundComponent::GetClosestOldEmitterPos( Gfx::Camera *pCamera )\r\n{\r\n\tif (mp_emitter && pCamera)\r\n\t{\r\n\t\t// This doesn't take into consideration the old position\r\n\t\treturn mp_emitter->GetClosestPoint(pCamera->GetPos());\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn m_old_pos;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCSoundComponent::GetClosestDropoffPos( Gfx::Camera *pCamera, Mth::Vector & dropoff_pos )\r\n{\r\n\tif (pCamera && mp_proxim_node)\r\n\t{\r\n\t\tdropoff_pos = mp_proxim_node->GetClosestIntersectionPoint(pCamera->GetPos());\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObjectSoundInfo *CSoundComponent::GetLoopingSoundInfo( uint32 soundChecksum )\r\n{\r\n\t\r\n\tint i;\r\n\tfor ( i = 0; i < MAX_NUM_LOOPING_SOUNDS_PER_OBJECT; i++ )\r\n\t{\r\n\t\tif ( mSoundInfo[ i ].checksum == soundChecksum )\r\n\t\t\treturn &mSoundInfo[ i ];\r\n\t}\r\n\treturn ( NULL );\r\n}\r\n\r\nvoid CSoundComponent::UpdateMutedSounds( void )\r\n{\r\n\t\r\n\tint i;\r\n\tTmr::Time gameTime;\r\n\tgameTime = Tmr::GetTime();\r\n\r\n\tfor ( i = 0; i < MAX_NUM_LOOPING_SOUNDS_PER_OBJECT; i++ )\r\n\t{\r\n\t\tif ( mSoundInfo[ i ].checksum )\r\n\t\t{\r\n\t\t\tObjectSoundInfo *pInfo = &mSoundInfo[ i ];\r\n\t\t\tUpdateObjectSound( pInfo );\r\n\t\t\tif ( pInfo->timeForNextDistCheck <= gameTime )\r\n\t\t\t{\r\n//\t\t\t\tDbg_Message( \"checking if we need to turn %s on\", Script::FindChecksumName( mSoundInfo[ i ].checksum ) );\r\n\t\t\t\t// see if we're dropoffDist*1.33 from the nearest camera...\r\n\t\t\t\t// if so, start the sound up again!\r\n\t\t\t\tfloat dist;\r\n\t\t\t\tGfx::Camera *p_camera = Nx::CViewportManager::sGetClosestCamera( m_pos, &dist );\r\n\t\t\t\tif ( p_camera && ( dist < ( pInfo->dropoffDist + DIST_FROM_DROPOFF_AT_WHICH_TO_START_SOUND ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t// start the sound playing again on this object:\r\n\t\t\t\t\tif ( PlaySound_VolumeAndPan( pInfo->checksum, pInfo->origVolume, pInfo->origPitch, pInfo->dropoffDist, pInfo->dropoffFunction ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//Dbg_Message( \"sound %s auto on object %x time %d\", Script::FindChecksumName( pInfo->checksum ), ( int ) this, gameTime );\r\n\t\t\t\t\t\tObjectSoundInfo *tempInfo;\r\n\t\t\t\t\t\tSfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();\r\n\t\t\t\t\t\ttempInfo = sfx_manager->GetObjectSoundProperties( this, pInfo->checksum );\r\n\t\t\t\t\t\t// and set up the targets to match the adjustments the scripts made\r\n\t\t\t\t\t\t// while the sound was turned off:\r\n\t\t\t\t\t\ttempInfo->targetVolume = pInfo->targetVolume;\r\n\t\t\t\t\t\ttempInfo->targetPitch = pInfo->targetPitch;\r\n\t\t\t\t\t\ttempInfo->deltaPitch = pInfo->deltaPitch;\r\n                        // give it a ramp up in volume, so it doesn't frickin'jump in our faces:\r\n\t\t\t\t\t\ttempInfo->currentVolume = 0.0f;\r\n\t\t\t\t\t\ttempInfo->deltaVolume = tempInfo->targetVolume / 100.0f;\r\n\t\t\t\t\t\t// don't forget to clear the slot to avoid updating it:\r\n\t\t\t\t\t\tpInfo->checksum = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// vary the time between distance checks, depending on how far\r\n\t\t\t\t\t// away the object is right now...\r\n\t\t\t\t\tpInfo->timeForNextDistCheck = gameTime;\r\n\t\t\t\t\tpInfo->timeForNextDistCheck += ( int )( ( 1000.0f * ( dist - pInfo->dropoffDist ) ) / 600.0f );\r\n\t\t\t\t\tpInfo->timeForNextDistCheck += 333;  // plus a third of a second...\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CSoundComponent::UpdateObjectSound( ObjectSoundInfo *pInfo )\r\n{\r\n\t\r\n\t// adjust pitch and volume, if necessary:\r\n\tif ( pInfo->targetPitch != pInfo->currentPitch )\r\n\t{\r\n\t\tpInfo->currentPitch = Mth::FRunFilter( pInfo->targetPitch, pInfo->currentPitch, pInfo->deltaPitch * Tmr::FrameRatio( ) );\r\n\t}\r\n\tif ( pInfo->targetVolume != pInfo->currentVolume )\r\n\t{\r\n\t\tpInfo->currentVolume = Mth::FRunFilter( pInfo->targetVolume, pInfo->currentVolume, pInfo->deltaVolume * Tmr::FrameRatio( )  );\r\n\t}\r\n}\r\n\r\nvoid CSoundComponent::AdjustObjectSound( Script::CScriptStructure *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n#ifndef __PLAT_NGC__\r\n\tObjectSoundInfo *pInfo;\r\n\tfloat volumePercent = 100.0f;\r\n\tfloat pitchPercent = 100.0f;\r\n\tuint32 soundChecksum;\r\n\r\n\tif ( !pParams->GetChecksum( NONAME, &soundChecksum ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"\\n%s\\nSound checksum required on Obj_AdjustSound\", pScript->GetScriptInfo( ) ));\r\n\t}\r\n\tSfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();\r\n\tpInfo = sfx_manager->GetObjectSoundProperties( this, soundChecksum );\r\n\tif ( !pInfo )\r\n\t{\r\n\t\t//Dbg_MsgAssert( 0,( \"\\n%s\\nAttempting to adjust object sound that isn't playing.\", pScript->GetScriptInfo( ) ));\r\n\t\t\r\n\t\t// Object went out of range, and the sound was stopped.\r\n\t\t// Store the current properties, so that when the sound\r\n\t\t// is started again the pitch/volume are correct!\r\n\t\t\r\n\t\t// NOTE:  If keeping the pitch/volume updated accurately by\r\n\t\t// adjusting by deltaPitch and deltaVolume causes noticable\r\n\t\t// slowdown, just set the pitch and vol immediately in this\r\n\t\t// function if the pInfo comes from the next line:\r\n\t\tpInfo = GetLoopingSoundInfo( soundChecksum );\r\n\r\n#\t\tifdef __PLAT_XBOX__\r\n\t\tif( !pInfo )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n#\t\tendif\r\n\r\n\t\tif (!pInfo)\r\n\t\t{\r\n\t\t\t//Dbg_MsgAssert( 0,( \"\\n%s\\nCan't adjust a sound (%s) that was never played on an object.\",  pScript->GetScriptInfo( ), Script::FindChecksumName(soundChecksum)  ));\r\n\t\t\tDbg_Message(\"\\n%s\\nCan't adjust a sound (%s) that was never played on an object.\",  pScript->GetScriptInfo( ), Script::FindChecksumName(soundChecksum));\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( pParams->GetFloat( 0x330f3415, &volumePercent ) ) // volumePercent\r\n\t{\r\n\t\tpInfo->targetVolume = PERCENT( pInfo->origVolume, volumePercent );\r\n\t\tif ( !pParams->GetFloat( 0xdaa9a3c2, &pInfo->deltaVolume ) )// volumeStep\r\n\t\t{\r\n\t\t\t// adjust immediately:\r\n\t\t\tpInfo->currentVolume = pInfo->targetVolume;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( pInfo->deltaVolume,( \"\\n%s\\nCan't have zero delta volume.\", pScript->GetScriptInfo( ) ));\r\n\t\t}\r\n\t}\r\n\tif ( pParams->GetFloat( 0xee616c13, &pitchPercent ) )\t// pitchPercent\r\n\t{\r\n\t\tpInfo->targetPitch = PERCENT( pInfo->origPitch, pitchPercent );\r\n\t\tif ( !pParams->GetFloat( 0x7b090774, &pInfo->deltaPitch ) ) // pitchStep\r\n\t\t{\r\n\t\t\t// adjust immediately:\r\n\t\t\tpInfo->currentPitch = pInfo->targetPitch;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( pInfo->deltaPitch,( \"\\n%s\\nCan't have zero delta pitch.\", pScript->GetScriptInfo( ) ));\r\n\t\t}\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n}\r\n\r\nvoid CSoundComponent::SoundOutOfRange( ObjectSoundInfo *pInfo, Tmr::Time gameTime )\r\n{\r\n\t\r\n\tint i;\r\n\tfor ( i = 0; i < MAX_NUM_LOOPING_SOUNDS_PER_OBJECT; i++ )\r\n\t{\r\n\t\tif ( !mSoundInfo[ i ].checksum  )\r\n\t\t{\r\n\t\t\tmSoundInfo[ i ] = *pInfo;\r\n\t\t\tmSoundInfo[ i ].timeForNextDistCheck = gameTime + 2000;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tDbg_MsgAssert( 0,( \"No empty looping sound slots for (%s) on object... (Limit %d)\",\r\n\t\t\t\t\tScript::FindChecksumName( pInfo->checksum ) ,MAX_NUM_LOOPING_SOUNDS_PER_OBJECT ));\r\n}\r\n\r\n\r\n// Will play a sound, setting the volume and pan according to world position\r\n// from the closest camera(s).\r\nint CSoundComponent::PlaySound_VolumeAndPan( uint32 soundChecksum, float volume, float pitch, float dropoffDist,\r\n\t\t\t\t\t\t\t\t\t\t\t EDropoffFunc dropoffFunction, bool noPosUpdate )\r\n{\r\n\t\r\n\t\r\n\tSfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();\r\n\tSfx::SoundUpdateInfo soundUpdateInfo;\r\n\tsoundUpdateInfo.volume = volume;\r\n\tsoundUpdateInfo.pitch = pitch;\r\n\tsoundUpdateInfo.dropoffDist = dropoffDist;\r\n\tsoundUpdateInfo.dropoffFunction = dropoffFunction;\r\n\t#if 0\r\n\t// TODO:  Replay code handling sound components\r\n\tReplay::WritePositionalSoundEffect(m_id,soundChecksum,volume,pitch,dropoffDist);\r\n\t#endif\r\n\treturn ( sfx_manager->PlaySoundWithPos( soundChecksum, &soundUpdateInfo, this, noPosUpdate ) );\r\n} // end of PlaySound_VolumeAndPan( )\r\n\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/soundcomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SoundComponent.h\r\n//* OWNER:          Mick West\r\n//* CREATION DATE:  10/17/2002\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SOUNDCOMPONENT_H__\r\n#define __COMPONENTS_SOUNDCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/math.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_SOUND CRCD(0x7713c7b,\"Sound\")\r\n#define\t\tGetSoundComponent() ((Obj::CSoundComponent*)GetComponent(CRC_SOUND))\r\n#define\t\tGetSoundComponentFromObject(pObj) ((Obj::CSoundComponent*)(pObj)->GetComponent(CRC_SOUND))\r\n\r\n//#define\t\tGetSounds() ((CSoundComponent*)GetComponent(CRC_SOUND))\r\n\r\n#define NUM_GENERAL_SOUNDS_PER_OBJECT\t( 10 )\r\n\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\t// Forward declarations\r\n\tclass CEmitterObject;\r\n\tclass CProximNode;\r\n\r\n\r\nclass CSoundComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSoundComponent();\r\n    virtual         ~CSoundComponent();\r\n    virtual void    Update();\r\n\tvirtual void    Teleport();\r\n    virtual void    InitFromStructure( Script::CStruct* pParams );\r\n\tstatic CBaseComponent *\ts_create();\r\n\r\n\r\n\tCBaseComponent::EMemberFunctionResult CallMemberFunction( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\n\tvirtual void GetDebugInfo(Script::CStruct *p_info);\r\n\t\t\t\t\t\t\t\r\n// Big old pile of crap....\r\n\r\npublic:\t\r\n\tvoid \t\t\tSetSound( Script::CStruct *pParams );\r\n\tvoid\t\t\tSoundOutOfRange( ObjectSoundInfo *pInfo, Tmr::Time gameTime );\r\n\tvoid\t\t\tUpdateObjectSound( ObjectSoundInfo *pInfo );\r\n\tint \t\t\tPlaySound_VolumeAndPan( uint32 soundChecksum, float volume = 100.0f, float pitch = 100.0,\r\n\t\t\t\t\t\t\t\t\t\t\tfloat dropoffDist = 0.0f, EDropoffFunc dropoffFunction = DROPOFF_FUNC_STANDARD,\r\n\t\t\t\t\t\t\t\t\t\t\tbool noPosUpdate = false );\r\n\tvirtual void \tBroadcastScriptedSound( uint32 soundChecksum, float volume, float pitch ) { };\r\n\tvoid\t\t\tPlayScriptedSound( Script::CStruct *pParams );\r\n\r\n\tMth::Vector\t\tGetPosition() const { return m_pos; }\r\n\tMth::Vector\t\tGetClosestEmitterPos( Gfx::Camera *pCamera );\r\n\tMth::Vector\t\tGetClosestOldEmitterPos( Gfx::Camera *pCamera );\r\n\r\n\tbool\t\t\tHasProximNode() const { return mp_proxim_node != NULL; }\r\n\tvoid\t\t\tClearProximNode() { mp_proxim_node = NULL; }\t\t\t\t\t\t\t\t// Needed for early proxim node cleanup\r\n\tbool\t\t\tGetClosestDropoffPos( Gfx::Camera *pCamera, Mth::Vector & dropoff_pos );\t// returns true if position defined\r\n\r\n\t// If the sound is muted due to the object being far from the nearest camera,\r\n\t// update the pitch and volume so that when it comes back onto the screen it\r\n\t// is how the designer would expect it ( called from GameObj_Update )\r\n\tvoid\t\t\tUpdateMutedSounds( void );\r\n\r\n\t#define\t\tMAX_NUM_SOUNDFX_CHECKSUMS\t8\r\n\tuint32\t\tmSoundFXChecksums[ MAX_NUM_SOUNDFX_CHECKSUMS ];\r\n\r\n\tvoid AdjustObjectSound( Script::CStruct *pParams, Script::CScript *pScript );\r\n\tObjectSoundInfo *GetLoopingSoundInfo( uint32 soundChecksum );\r\n\t\r\n\t#define\t\tMAX_NUM_LOOPING_SOUNDS_PER_OBJECT\t2\r\n\tObjectSoundInfo\tmSoundInfo[ MAX_NUM_LOOPING_SOUNDS_PER_OBJECT ];\r\n\t\t\t\t\t\t\t\r\nprotected:\r\n\t\t\t\t\t\t\t   \r\n\tMth::Vector\tm_pos,m_old_pos;\r\n\tCEmitterObject *mp_emitter;\r\n\tCProximNode *\tmp_proxim_node;\r\n\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/specialitemcomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SpecialItemComponent.cpp\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ???\r\n//****************************************************************************\r\n\r\n#include <gel/components/specialitemcomponent.h>\r\n\r\n#include <gel/objman.h>\r\n#include <gel/components/lockobjcomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/object/compositeobject.h>\r\n\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/nxmodel.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/objects/gameobj.h>\r\n#include <sk/modules/skate/skate.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\n\r\nCBaseComponent* CSpecialItemComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSpecialItemComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCSpecialItemComponent::CSpecialItemComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SPECIALITEM );\r\n\t\r\n\tfor ( int i = 0; i < vMAX_SPECIAL_ITEMS; i++ )\r\n\t{\r\n\t\tmp_special_items[i] = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSpecialItemComponent::~CSpecialItemComponent()\r\n{\t\r\n\t// Cleanup the special items\r\n\tDestroyAllSpecialItems();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CSpecialItemComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// ** Add code to parse the structure, and initialize the component\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CSpecialItemComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calline InitFromStructure()\r\n\t// but if that does not handle it, then will need to write a specific \r\n\t// function here. \r\n\t// The user might only want to update a single field in the structure\r\n\t// and we don't want to be asserting becasue everything is missing \r\n\t\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CSpecialItemComponent::Update()\r\n{\r\n\t// Doing nothing, so tell code to do nothing next time around\r\n\tSuspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CSpecialItemComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | CreateSpecialItem | attaches a new special item to the skater in the specified slot\r\n\t\t// @parm int | index | Index of special item to create\r\n\t\t// @parm structure | params | Special item creation data (should look like an entry in the node array)\r\n\t\t// @parmopt name | bone | | The bone to which the special item is attached; otherwise, it will be attached to the root\r\n\t\t// @parmopt vector | offset | (0, 0, 0) | An additional offset to the specified bone (or root) applied to the special item's position\r\n\t\tcase 0x827c6bd1:  // CreateSpecialItem\r\n\t\t\t{\r\n\t\t\t\tint index;\r\n\t\t\t\tuint32 bone = 0;\r\n\t\t\t\tpParams->GetInteger( CRCD(0x7f8c98fe,\"index\"), &index, true );\r\n\t\t\t\tpParams->GetChecksum( \"bone\", &bone );\r\n\r\n\t\t\t\tuint32 checksum;\r\n\t\t\t\tpParams->GetChecksum( \"params\", &checksum, Script::ASSERT );\r\n\t\t\t\tScript::CStruct* pSpecialItemParams;\r\n\t\t\t\tpSpecialItemParams = Script::GetStructure( checksum, Script::ASSERT );\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\tCCompositeObject* pMovingObject = CreateSpecialItem( index, pSpecialItemParams );\r\n\t\t\t\t\r\n\t\t\t\t// special items need a lock object to work...\r\n\t\t\t\tScript::CStruct* pLockParams = new Script::CStruct;\r\n\t\t\t\tpLockParams->AppendStructure( pParams ); \t\t\t// pass along any bone or offset parameters...\r\n\t\t\t\tpLockParams->AddChecksum( \"id\", GetObject()->GetID() );\t\t\t\t  \t\r\n\t\t\t\tObj::CLockObjComponent* pLockObjComponent = GetLockObjComponentFromObject( pMovingObject );\r\n\t\t\t\tDbg_MsgAssert( pLockObjComponent, ( \"No lock obj component\" ) );\r\n\t\t\t\tpLockObjComponent->InitFromStructure( pLockParams );\t\t\t\t \t\t\r\n\t\t\t\tdelete pLockParams;\r\n\r\n\t\t\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\t\t\tif( gamenet_man->InNetGame())\r\n\t\t\t\t{\r\n\t\t\t\t\tNet::Client* client;\r\n\t\t\t\t\tGameNet::MsgSpecialItem msg;\r\n\t\t\t\t\tNet::MsgDesc msg_desc;\r\n\t\r\n                    client = gamenet_man->GetClient( 0 );\r\n\t\t\t\t\tDbg_Assert( client );\r\n\t\r\n\t\t\t\t\tmsg.m_ObjId = GetObject()->GetID();\r\n\t\t\t\t\tmsg.m_Params = checksum;\r\n\t\t\t\t\tmsg.m_Index = index;\r\n\t\t\t\t\tmsg.m_Bone = bone;\r\n\t\t\t\t\t\r\n\t\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgSpecialItem );\r\n\t\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_CREATE_SPECIAL_ITEM;\r\n\t\t\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | DestroySpecialItem | Destroys a special item attached to the skater, if it exists\r\n\t\t// @parm int | index | Index of special item to destroy\r\n\t\tcase 0x742188fa:  // DestroySpecialItem\r\n\t\t\t{\r\n\t\t\t\tint index;\r\n\t\t\t\tpParams->GetInteger( CRCD(0x7f8c98fe,\"index\"), &index, true );\r\n\r\n\t\t\t\tthis->DestroySpecialItem( index );\r\n\t\t\t\t\r\n\t\t\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\t\t\tif( gamenet_man->InNetGame())\r\n\t\t\t\t{\r\n\t\t\t\t\tNet::Client* client;\r\n\t\t\t\t\tGameNet::MsgSpecialItem msg;\r\n\t\t\t\t\tNet::MsgDesc msg_desc;\r\n\t\r\n                    client = gamenet_man->GetClient( 0 );\r\n\t\t\t\t\tDbg_Assert( client );\r\n\t\r\n\t\t\t\t\tmsg.m_ObjId = GetObject()->GetID();\r\n\t\t\t\t\tmsg.m_Index = index;\r\n\t\t\t\t\t\r\n\t\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgSpecialItem );\r\n\t\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_DESTROY_SPECIAL_ITEM;\r\n\t\t\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | DestroyAllSpecialItems | Destroys all special items currently attached to the skater \r\n\t\tcase 0xa1baa25e:  // DestroyAllSpecialItems\r\n\t\t\t{\r\n\t\t\t\tthis->DestroyAllSpecialItems();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | SpecialItemExists | Returns whether a special item exists\r\n\t\t// @parm int | index | Index of special item to check\r\n\t\tcase 0xce887492:  // SpecialItemExists\r\n\t\t\t{\r\n\t\t\t\tint index;\r\n\t\t\t\tif ( pParams->GetInteger( CRCD(0x7f8c98fe,\"index\"), &index, false ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( index >= 0 && index < vMAX_SPECIAL_ITEMS, ( \"Special item index %d must be between 0 and %d\", index, vMAX_SPECIAL_ITEMS ) );\r\n\t\t\t\t\treturn ( mp_special_items[index] ) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int i = 0; i < vMAX_SPECIAL_ITEMS; i++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( mp_special_items[i] )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSpecialItemComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSpecialItemComponent::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\t/*\tExample:\r\n\tp_info->AddInteger(\"m_never_suspend\",m_never_suspend);\r\n\tp_info->AddFloat(\"m_suspend_distance\",m_suspend_distance);\r\n\t*/\r\n\t\r\n// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CCompositeObject* CSpecialItemComponent::CreateSpecialItem( int index, Script::CStruct* pNodeData )\r\n{\r\n\tDbg_MsgAssert( index >= 0 && index < vMAX_SPECIAL_ITEMS, ( \"Special item index %d must be between 0 and %d\", index, vMAX_SPECIAL_ITEMS ) );\r\n\tDbg_MsgAssert( pNodeData, ( \"Missing parameter\" ) );\r\n\r\n\tif ( mp_special_items[index] )\r\n\t{\r\n\t\t// TODO:  Maybe this should just be a warning?\r\n//\t\tDbg_MsgAssert( 0, ( \"Special item index %d not empty\", index ) );\r\n\t\tDestroySpecialItem( index );\r\n\t}\r\n\r\n//\tDbg_Message( \"Adding special item to index %d\", index );\r\n\t\r\n\t// eventually, we'll want to create a generic composite object\r\n\t// (maybe by running a script)\r\n\tMem::PushMemProfile(\"Game Objects\");\r\n\tObj::CCompositeObject* pGameObj = Obj::CreateGameObj( Mdl::Skate::Instance()->GetObjectManager(), pNodeData );\r\n\tDbg_Assert( pGameObj );\r\n\tMem::PopMemProfile();\r\n\r\n\t// GJ:  This is a special-case function that's used for\r\n\t// replays...  I'm not bothering to move it over to the\r\n\t// CCompositeObject stuff, because we've already made the\r\n\t// decision not to make the replay backwards-compatible.\r\n//\tpGameObj->FlagAsSpecialItem();\r\n\t\r\n\tmp_special_items[index] = pGameObj;\r\n\r\n\t// add the skater's id to the object's tags\r\n\t// so that the object knows which skater it's tied to\r\n\tScript::CStruct* pTempStructure;\r\n\tpTempStructure = new Script::CStruct;\r\n\tpTempStructure->AddChecksum( \"parentId\", GetObject()->GetID() );\r\n\tuint32 cleanupScript;\r\n\tif ( pNodeData->GetChecksum( CRCD(0x40764820,\"CleanupScript\"), &cleanupScript ) )\r\n\t{\r\n\t\tpTempStructure->AddChecksum( CRCD(0x40764820,\"CleanupScript\"), cleanupScript );\r\n\t}\r\n\tmp_special_items[index]->SetTagsFromScript( pTempStructure );\r\n\tdelete pTempStructure;\r\n\r\n\t// in case there's any scaling applied to the model,\r\n\t// apply that to the special item's model as well...\r\n\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( GetObject() );\r\n\tNx::CModel* pModel = NULL;\r\n\tif ( pModelComponent )\r\n\t{\r\n\t\tpModel = pModelComponent->GetModel();\r\n\t}\r\n\t\r\n\tObj::CModelComponent* pGameObjModelComponent = GetModelComponentFromObject( pGameObj );\r\n\tNx::CModel* pGameObjModel = NULL;\r\n\tif ( pGameObjModelComponent )\r\n\t{\r\n\t\tpGameObjModel = pGameObjModelComponent->GetModel();\r\n\t}\r\n\r\n\t// (Mick) ... but only if it has a model (might be just collision)\r\n\tif ( pModel && pGameObjModel )\t\t\r\n\t{\r\n\t\tMth::Vector scaleVec = pModel->GetScale();\r\n\t\tpGameObjModel->SetScale( scaleVec );\t\t// (Mick) - see check above\r\n\t}\r\n\t\r\n\treturn pGameObj;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSpecialItemComponent::DestroySpecialItem( int index )\r\n{\r\n\tDbg_MsgAssert( index >= 0 && index < vMAX_SPECIAL_ITEMS, ( \"Special item index %d must be between 0 and %d\", index, vMAX_SPECIAL_ITEMS ) );\r\n\t\r\n\tif ( mp_special_items[index] )\r\n\t{\r\n\t\t// run the cleanup script if it exists...\r\n\t\tScript::CStruct* pStruct = new Script::CStruct;\r\n\t\tmp_special_items[index]->CopyTagsToScriptStruct(pStruct);\r\n\t\tuint32 cleanupScript;\r\n\t\tif ( pStruct->GetChecksum( CRCD(0x40764820,\"CleanupScript\"), &cleanupScript, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\t// run a cleanup script if it exists\r\n\t\t\tScript::RunScript( cleanupScript, NULL, mp_special_items[index] );\r\n\t\t}\r\n\t\tdelete pStruct;\r\n\r\n\t\t// don't actually delete it yet...\r\n\t\t// instead, just mark it as dead, so \r\n\t\t// that if any objects still refer to\r\n\t\t// it on this frame, it won't crash...\r\n\t\tmp_special_items[index]->MarkAsDead();\r\n\t\tmp_special_items[index] = NULL;\r\n\t\t\r\n\t\t// THPS4:  flushes dead objects so that we can\r\n\t\t// recreate it on the same frame\r\n\t\t// (theoretically, we should have been\r\n\t\t// able to call \"wait 1 gameframe\",\r\n\t\t// but it turns out that CScript::Update()\r\n\t\t// can be called more than once per frame,\r\n\t\t// if someone uses the MakeSkaterGoto\r\n\t\t// command)\r\n\t\t// THPS5:  doesn't seem to be a problem any\r\n\t\t// more, perhaps due to the subtle changes in\r\n\t\t// order which object/component logic gets\r\n\t\t// run.  having this line in here does cause\r\n\t\t// some issues now, in that it's possible\r\n\t\t// for an object to indirectly delete itself from\r\n\t\t// its update() function, which is bad.  i've\r\n\t\t// taken this line out and will fix any\r\n\t\t// related bugs as they arise.\r\n//\t\tMdl::Skate::Instance()->GetObjectManager()->FlushDeadObjects();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSpecialItemComponent::DestroyAllSpecialItems()\r\n{\r\n\t// This also gets called when we switch levels...\r\n\t// (from DeleteResources)\r\n\t\t\r\n\tfor ( int index = 0; index < vMAX_SPECIAL_ITEMS; index++ )\r\n\t{\r\n\t\tDestroySpecialItem( index );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/specialitemcomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SpecialItemComponent.h\r\n//* OWNER:          gj\r\n//* CREATION DATE:  02/13/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SPECIALITEMCOMPONENT_H__\r\n#define __COMPONENTS_SPECIALITEMCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_SPECIALITEM CRCD(0xf27a294d,\"SpecialItem\")\r\n#define\t\tGetSpecialItemComponent() ((Obj::CSpecialItemComponent*)GetComponent(CRC_SPECIALITEM))\r\n#define\t\tGetSpecialItemComponentFromObject(pObj) ((Obj::CSpecialItemComponent*)(pObj)->GetComponent(CRC_SPECIALITEM))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CSpecialItemComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSpecialItemComponent();\r\n    virtual ~CSpecialItemComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\npublic:\r\n\tCCompositeObject*\t\t\t\tCreateSpecialItem( int index, Script::CStruct* pNodeData );\r\n\tvoid \t\t\t\t\t\t\tDestroySpecialItem( int index );\r\n\tvoid \t\t\t\t\t\t\tDestroyAllSpecialItems();\r\n\r\nprotected:\r\n\tenum\r\n\t{\r\n\t\tvMAX_SPECIAL_ITEMS = 2\r\n\t};\r\n\tCCompositeObject*\t\t\t\tmp_special_items[vMAX_SPECIAL_ITEMS];\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/trickcomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       TrickComponent.cpp\r\n//* OWNER:          Mr Kendall Stuart Harrison Esq.\r\n//* CREATION DATE:  3 Jan 2003\r\n//****************************************************************************\r\n\r\n#include <sys/config/config.h>\r\n\r\n#include <gel/components/trickcomponent.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/statsmanagercomponent.h>\r\n\r\n#include <gel/objtrack.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/component.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/score.h>\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/objects/skater.h> // Needed for GetPhysicsInt(...)\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/components/skaterbalancetrickcomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skatergapcomponent.h>\r\n#include <sk/components/skaterflipandrotatecomponent.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n#include <sk/components/skaterruntimercomponent.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\nstatic bool s_is_direction_button(uint32 buttonName);\r\n#ifdef\t__DEBUG_CODE__\r\nstatic void s_add_array_of_names(Script::CStruct *p_info, int size, uint32 *p_source_array, const char *p_name);\r\n#endif\t\t\t\t \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Used by ExtraGapTrickLogic\r\nstatic bool s_is_direction_button(uint32 buttonName)\r\n{\r\n\tswitch (buttonName)\r\n\t{\r\n\t\tcase 0xbc6b118f: // Up\r\n\t\tcase 0xe3006fc4: // Down\r\n\t\tcase 0x85981897: // Left\r\n\t\tcase 0x4b358aeb: // Right\r\n\t\tcase 0xb7231a95: // UpLeft\r\n\t\tcase 0xa50950c5: // UpRight\r\n\t\tcase 0xd8847efa: // DownLeft\r\n\t\tcase 0x786b8b68: // DownRight\r\n\t\t\treturn true;\r\n\t\t\tbreak;\r\n\t\t\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\treturn false;\t\r\n}\r\n\r\n#ifdef\t__DEBUG_CODE__\r\n// Converts an array of uint32's to a script array and inserts it into the passed structure, naming it p_name\r\nstatic void s_add_array_of_names(Script::CStruct *p_info, int size, uint32 *p_source_array, const char *p_name)\r\n{\r\n\tScript::CArray *p_array=new Script::CArray;\r\n\tif (size)\r\n\t{\r\n\t\tp_array->SetSizeAndType(size,ESYMBOLTYPE_NAME);\r\n\t\t\r\n\t\tfor (int i=0; i<size; ++i)\r\n\t\t{\r\n\t\t\tp_array->SetChecksum(i,p_source_array[i]);\r\n\t\t}\r\n\t}\r\n\tp_info->AddArrayPointer(p_name,p_array);\r\n}\r\n#endif\t\t\t\t \r\n\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\n\r\nCBaseComponent* CTrickComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CTrickComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCTrickComponent::CTrickComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_TRICK );\r\n\t\r\n\tmpTrickMappings=NULL;\r\n\tmp_score=NULL;\r\n\tmp_input_component=NULL;\r\n\tmp_skater_balance_trick_component=NULL;\r\n\tmp_skater_core_physics_component=NULL;\r\n\tmp_skater_flip_and_rotate_component=NULL;\r\n\tmp_skater_state_component=NULL;\r\n    mp_stats_manager_component=NULL;\r\n\t\t\t\t \r\n\tClear();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCTrickComponent::~CTrickComponent()\r\n{\r\n\tif (mpTrickMappings)\r\n\t{\r\n\t\tdelete mpTrickMappings;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTrickComponent::Finalize()\r\n{\r\n\tmp_input_component = GetInputComponentFromObject(GetObject());\r\n\tmp_skater_balance_trick_component = GetSkaterBalanceTrickComponentFromObject(GetObject());\r\n\tmp_skater_core_physics_component = GetSkaterCorePhysicsComponentFromObject(GetObject());\r\n\tmp_skater_flip_and_rotate_component = GetSkaterFlipAndRotateComponentFromObject(GetObject());\r\n\tmp_skater_state_component = GetSkaterStateComponentFromObject(GetObject());\r\n    mp_stats_manager_component = GetStatsManagerComponentFromObject(GetObject());\r\n            \r\n\tDbg_Assert(mp_input_component);\r\n\tDbg_Assert(mp_skater_balance_trick_component);\r\n\tDbg_Assert(mp_skater_core_physics_component);\r\n\tDbg_Assert(mp_skater_flip_and_rotate_component);\r\n\tDbg_Assert(mp_skater_state_component);\r\n    Dbg_Assert(mp_stats_manager_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Gets called from the CTrickComponent constructor, and also from CSkater::ResetEverything()\r\nvoid CTrickComponent::Clear()\r\n{\r\n\tm_num_runtrick_recursions=0;\r\n\tmNumButtonsToIgnore=0;\r\n\r\n\tmUseSpecialTrickText=false;\r\n\t\r\n\tmFrontTrick = -1;\r\n\tmBackTrick = -1;\r\n\t\r\n\tClearQueueTricksArrays();\r\n\t\r\n\tmSpecialTricksArrayChecksum = 0;\r\n\tmDoNotIgnoreMask=0;\r\n\r\n\tClearManualTrick();\r\n\tmSpecialManualTricksArrayChecksum=0;\r\n\t\r\n\tClearExtraGrindTrick();\r\n\tmSpecialExtraGrindTrickArrayChecksum=0;\r\n\t\r\n\tmGotExtraTricks = false;\r\n\tmExtraTricksInfiniteDuration = false;\r\n\tmExtraTricksDuration = 0;\r\n\tmExtraTricksStartTime = 0;\r\n\t\r\n\tmNumExtraTrickArrays = 0;\r\n\tmSpecialExtraTricksArrayChecksum = 0;\r\n\tmExcludedSpecialExtraTricks = 0;\r\n\t\r\n\tClearEventBuffer();\r\n\tfor (int i=0; i<MAX_TRICK_BUTTONS; ++i)\r\n\t{\r\n\t\tmp_trick_button[i]=0;\r\n\t}\t\r\n\t\r\n\tfor (int i=0; i<PAD_NUMBUTTONS; ++i)\r\n\t{\r\n\t\tmButtonState[i]=false;\r\n\t\tmButtonDebounceTime[i]=0;\r\n\t}\r\n\t\t\r\n\tmBashingEnabled = true;\r\n}\r\n\r\nScript::CStruct *CTrickComponent::get_trigger_structure(Script::CStruct *p_struct)\r\n{\r\n\tScript::CStruct *p_trigger=NULL;\r\n\tif (Config::GetHardware()==Config::HARDWARE_XBOX)\r\n\t{\r\n\t\tif (!p_struct->GetStructure(CRCD(0xce42ee1a,\"XBox_Trigger\"),&p_trigger))\r\n\t\t{\r\n\t\t\tp_struct->GetStructure(CRCD(0xe594f0a2,\"Trigger\"),&p_trigger,Script::ASSERT);\r\n\t\t}\r\n\t}\r\n\telse if (Config::GetHardware()==Config::HARDWARE_NGC)\r\n\t{\r\n\t\tif (!p_struct->GetStructure(CRCD(0xcb0e600c,\"NGC_Trigger\"),&p_trigger))\r\n\t\t{\r\n\t\t\tp_struct->GetStructure(CRCD(0xe594f0a2,\"Trigger\"),&p_trigger,Script::ASSERT);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_struct->GetStructure(CRCD(0xe594f0a2,\"Trigger\"),&p_trigger,Script::ASSERT);\r\n\t}\r\n\t\r\n\treturn p_trigger;\r\n}\r\n\r\n// K: 6/16/03 This is to implement a new feature, where as well as a Trigger structure, an Alt_Trigger\r\n// structure can be specified. If either of Trigger or Alt_Trigger is satisfied, the trick triggers.\r\n// The Alt_Trigger is the same for all three platforms.\r\nScript::CStruct *CTrickComponent::get_alternate_trigger_structure(Script::CStruct *p_struct)\r\n{\r\n\tScript::CStruct *p_trigger=NULL;\r\n\t// Note: Not passing Script::ASSERT as in get_trigger_structure above, because the Alt_Trigger is optional.\r\n\tp_struct->GetStructure(CRCD(0x68b74085,\"Alt_Trigger\"),&p_trigger);\r\n\t\r\n\treturn p_trigger;\r\n}\r\n\t\r\nvoid CTrickComponent::ClearQueueTricksArrays()\r\n{\r\n\tmNumQueueTricksArrays=0;\r\n\tfor (int i=0; i<MAX_QUEUE_TRICK_ARRAYS; ++i)\r\n\t{\r\n\t\tmpQueueTricksArrays[i]=0;\r\n\t}\t\r\n}\r\n\r\nvoid CTrickComponent::ClearEventBuffer()\r\n{\r\n\tfor (int i=0; i<MAX_EVENTS; ++i)\r\n\t{\r\n\t\tmpButtonEvents[i].EventType=EVENT_NONE;\r\n\t\tmpButtonEvents[i].MaybeUsed=false;\r\n\t\tmpButtonEvents[i].Used=false;\r\n\t}\r\n\tmNumEvents = 0;\r\n\tmLastEvent = 0;\r\n}\r\n\r\n// Called by the ClearManualTrick script command.\r\nvoid CTrickComponent::ClearManualTrick()\r\n{\r\n\tmGotManualTrick=false;\r\n\tmNumManualTrickArrays=0;\r\n\t\r\n\t// Just to be sure, zero the lot of 'em.\r\n\tfor (int i=0; i<MAX_MANUAL_TRICK_ARRAYS; ++i)\r\n\t{\r\n\t\tmpManualTrickArrays[i]=0;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTrickComponent::UpdateTrickMappings( Obj::CSkaterProfile* pSkaterProfile )\r\n{\r\n\tDbg_Assert( pSkaterProfile );\r\n\t\r\n\tif (!mpTrickMappings )\r\n\t{\r\n\t\tmpTrickMappings = new Script::CStruct;\r\n\t}\r\n\t\r\n\tmpTrickMappings->Clear();\r\n\r\n\t// \"max_specials\" is not stored in the skater profile by\r\n\t// the time the skater gets here...  so just loop through\r\n\t// all 10 slots\r\n\t\r\n\t// get the special tricks from the skater profile\r\n\t// they're stored in a different format than the\r\n\t// regular tricks, so we can't just append the structure\r\n\tfor ( int i = 0; i < Obj::CSkaterProfile::vMAXSPECIALTRICKSLOTS; i++ )\r\n\t{\r\n\t\tSSpecialTrickInfo theInfo = pSkaterProfile->GetSpecialTrickInfo( i );\r\n\t\tif ( !theInfo.IsUnassigned() )\r\n\t\t{\r\n\t\t\tif ( theInfo.m_isCat )\r\n\t\t\t{\r\n\t\t\t\tmpTrickMappings->AddComponent( theInfo.m_TrickSlot, ESYMBOLTYPE_INTEGER, (int)theInfo.m_TrickName );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t\tmpTrickMappings->AddComponent( theInfo.m_TrickSlot, ESYMBOLTYPE_NAME, (int)theInfo.m_TrickName );\r\n\t\t}\r\n\t}\r\n\r\n\t// get the regular tricks from the skater profile\r\n\tmpTrickMappings->AppendStructure( pSkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*  Adds a single new event and returns a pointer to it.\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSButtonEvent *CTrickComponent::AddEvent(EEventType EventType)\r\n{\r\n\tDbg_MsgAssert(mNumEvents<=MAX_EVENTS,(\"mNumEvents too big, = %d\",mNumEvents));\r\n\tDbg_MsgAssert(mLastEvent<MAX_EVENTS,(\"mLastEvent too big, = %d\",mLastEvent));\r\n\t\r\n\t++mLastEvent;\r\n\tif (mLastEvent>=MAX_EVENTS)\r\n\t{\r\n\t\tmLastEvent=0;\r\n\t}\r\n\tif (mNumEvents<MAX_EVENTS)\r\n\t{\r\n\t\t++mNumEvents;\r\n\t}\t\r\n\tmpButtonEvents[mLastEvent].EventType=EventType;\r\n\tmpButtonEvents[mLastEvent].Time=Tmr::ElapsedTime(0);\r\n\tmpButtonEvents[mLastEvent].MaybeUsed=false;\r\n\tmpButtonEvents[mLastEvent].Used=0;\r\n\t\r\n\treturn &mpButtonEvents[mLastEvent];\r\n}\r\n\r\nvoid CTrickComponent::ResetMaybeUsedFlags()\r\n{\r\n\tint Index=mLastEvent;\r\n\tfor (int i=0; i<mNumEvents; ++i)\r\n\t{\r\n\t\tmpButtonEvents[Index].MaybeUsed=false;\r\n\t\t--Index;\r\n\t\tif (Index<0)\r\n\t\t{\r\n\t\t\tIndex+=MAX_EVENTS;\r\n\t\t}\r\n\t}\t\t\r\n}\r\n\r\nvoid CTrickComponent::ConvertMaybeUsedToUsed(uint32 UsedMask)\r\n{\r\n\tint Index=mLastEvent;\r\n\tfor (int i=0; i<mNumEvents; ++i)\r\n\t{\r\n\t\tif (mpButtonEvents[Index].MaybeUsed)\r\n\t\t{\r\n\t\t\tmpButtonEvents[Index].MaybeUsed=false;\r\n\t\t\tmpButtonEvents[Index].Used|=UsedMask;\r\n\t\t}\r\n\t\t\t\r\n\t\t--Index;\r\n\t\tif (Index<0)\r\n\t\t{\r\n\t\t\tIndex+=MAX_EVENTS;\r\n\t\t}\r\n\t}\t\t\r\n}\r\n\r\n// Flags as used all button events for the given button that are older than the passed time.\r\nvoid CTrickComponent::RemoveOldButtonEvents(uint32 Button, uint32 OlderThan)\r\n{\r\n\tint Index=mLastEvent;\r\n\tfor (int i=0; i<mNumEvents; ++i)\r\n\t{\r\n\t\tif (mpButtonEvents[Index].ButtonNameChecksum==Button)\r\n\t\t{\r\n\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time) >= OlderThan)\r\n\t\t\t{\r\n\t\t\t\tmpButtonEvents[Index].Used=0xffffffff;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\t--Index;\r\n\t\tif (Index<0)\r\n\t\t{\r\n\t\t\tIndex+=MAX_EVENTS;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool CTrickComponent::TriggeredInLastNMilliseconds(uint32 ButtonNameChecksum, uint32 Duration, uint32 IgnoreMask)\r\n{\r\n\t\r\n\t\r\n\tint Index=mLastEvent;\r\n\tfor (int i=0; i<mNumEvents; ++i)\r\n\t{\r\n\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\tmpButtonEvents[Index].ButtonNameChecksum==ButtonNameChecksum)\r\n\t\t{\r\n\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t\t\r\n\t\t--Index;\r\n\t\tif (Index<0)\r\n\t\t{\r\n\t\t\tIndex+=MAX_EVENTS;\r\n\t\t}\t\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool CTrickComponent::BothTriggeredNothingInBetween(uint32 Button1, uint32 Button2, uint32 Duration, uint32 IgnoreMask)\r\n{\r\n\tbool GotButton1=false;\t\r\n\tbool GotButton2=false;\t\r\n\tbool AnyOtherCancel=false;\r\n\t\r\n\tint Index=mLastEvent;\r\n\tfor (int i=0; i<mNumEvents; ++i)\r\n\t{\r\n\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED)\r\n\t\t{\r\n\t\t\tif (mpButtonEvents[Index].ButtonNameChecksum==Button1)\r\n\t\t\t{\r\n\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\tif (GotButton2)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t\tGotButton1=true;\r\n\t\t\t\tAnyOtherCancel=true;\r\n\t\t\t}\t\r\n\t\t\telse if (mpButtonEvents[Index].ButtonNameChecksum==Button2)\r\n\t\t\t{\r\n\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\tif (GotButton1)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t\tGotButton2=true;\r\n\t\t\t\tAnyOtherCancel=true;\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (AnyOtherCancel)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\t\t\r\n\t\t}\t\r\n\t\t\r\n\t\t--Index;\r\n\t\tif (Index<0)\r\n\t\t{\r\n\t\t\tIndex+=MAX_EVENTS;\r\n\t\t}\t\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n// Reads the button names and time duration out of a 'Trigger' structure.\r\nuint32 CTrickComponent::get_buttons_and_duration(Script::CComponent *p_comp, int num_buttons, uint32 *p_button_names)\r\n{\r\n\tDbg_MsgAssert(p_comp,(\"NULL p_comp\"));\r\n\tDbg_MsgAssert(p_button_names,(\"NULL p_button_names\"));\r\n\tDbg_MsgAssert(num_buttons<=MAX_TRICK_BUTTONS,(\"Bad num_buttons\"));\r\n\t\r\n\tfor (int i=0; i<num_buttons; ++i)\r\n\t{\r\n\t\tDbg_MsgAssert(p_comp,(\"Missing button name\"));\r\n\t\tDbg_MsgAssert(p_comp->mType==ESYMBOLTYPE_NAME,(\"Bad component type, expected name\"));\r\n\t\t\r\n\t\tswitch (p_comp->mChecksum)\r\n\t\t{\r\n\t\t\tcase 0x9a7dc229: // Parent1\r\n\t\t\t\tp_button_names[i]=mp_trick_button[0];\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x03749393: // Parent2\r\n\t\t\t\tp_button_names[i]=mp_trick_button[1];\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x7473a305: // Parent3\r\n\t\t\t\tp_button_names[i]=mp_trick_button[2];\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tp_button_names[i]=p_comp->mChecksum;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\r\n\t\tp_comp=p_comp->mpNext;\r\n\t}\t\r\n\t\r\n\tDbg_MsgAssert(p_comp,(\"Missing duration\"));\r\n\tif (p_comp->mType==ESYMBOLTYPE_INTEGER)\r\n\t{\r\n\t\treturn p_comp->mIntegerValue;\r\n\t}\t\r\n\tDbg_MsgAssert(p_comp->mType==ESYMBOLTYPE_NAME,(\"Bad duration value in trick, must be either an integer or a named integer\"));\r\n\treturn GetPhysicsInt(p_comp->mChecksum);\r\n}\r\n\r\nvoid CTrickComponent::record_last_tricks_buttons(uint32 *p_button_names)\t\r\n{\r\n\tDbg_MsgAssert(p_button_names,(\"NULL p_button_names\"));\r\n\t\r\n\t// Remember what buttons were used by the last trick that got triggered.\r\n\t// They are stored so that the extra-trick trigger can use one of the parent trick's buttons,\r\n\t// rather than being hard wired. This is needed in case the player re-maps the parent trick to\r\n\t// a different button combination.\r\n\tuint32 *p_dest=mp_trick_button;\r\n\tfor (int i=0; i<MAX_TRICK_BUTTONS; ++i)\r\n\t{\r\n\t\t*p_dest++=*p_button_names++;\r\n\t}\t\t\t\r\n}\r\n\r\nvoid CTrickComponent::ButtonRecord(uint Button, bool Pressed)\r\n{\r\n\tDbg_MsgAssert(Button<PAD_NUMBUTTONS,(\"Bad Button\"));\r\n\t\r\n\tif (mButtonDebounceTime[Button])\r\n\t{\r\n\t\tif ((!Pressed) || (Tmr::GetTime() > mButtonDebounceTime[Button]))\r\n\t\t{\r\n\t\t\tmButtonDebounceTime[Button] = 0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\t \r\n\tif (mButtonState[Button]==Pressed)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tmButtonState[Button]=Pressed;\r\n\r\n\r\n\tuint32 ButtonChecksum=Inp::GetButtonChecksum( Button );\r\n\t\r\n\t// Perhaps ignore the button.\r\n\t// This feature is used by the skater to ignore the button events used to control the balance\r\n\t// when doing a manual, otherwise ChrisR can't do kickflips by very quickly jumping out of a \r\n\t// grind & kickflipping by rolling from X to Square.\r\n\tfor (int i=0; i<mNumButtonsToIgnore; ++i)\r\n\t{\r\n\t\tif (ButtonChecksum==mpButtonsToIgnore[i])\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\t\t\r\n\t// Generate an event.\r\n\tif (Pressed)\r\n\t{\r\n\t\tSButtonEvent *pEvent=AddEvent(EVENT_BUTTON_PRESSED);\r\n\t\tDbg_MsgAssert(pEvent,(\"NULL pEvent ?\"));\r\n\t\tpEvent->ButtonNameChecksum=ButtonChecksum;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSButtonEvent *pEvent=AddEvent(EVENT_BUTTON_RELEASED);\r\n\t\tDbg_MsgAssert(pEvent,(\"NULL pEvent ?\"));\r\n\t\tpEvent->ButtonNameChecksum=ButtonChecksum;\r\n\t}\r\n}\r\n\r\nbool CTrickComponent::GetButtonState(uint32 Checksum)\r\n{\r\n\treturn mButtonState[Inp::GetButtonIndex(Checksum)];\r\n}\r\n\r\n// Note: This probably needs a lot of optimization, hmmm.\r\nbool CTrickComponent::QueryEvents(Script::CStruct *pQuery, uint32 UsedMask, uint32 IgnoreMask)\r\n{\r\n\tif (!pQuery)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\tif (mp_input_component->IsInputDisabled())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\t//Script::PrintContents(pQuery);\t\r\n    Script::CComponent *pComp=pQuery->GetNextComponent(NULL);\r\n\tif (!pComp)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\tDbg_MsgAssert(pComp->mType==ESYMBOLTYPE_NAME,(\"Bad component type, expected name\"));\r\n\tuint32 NameChecksum=pComp->mChecksum;\r\n\tpComp=pComp->mpNext;\r\n\t\r\n\tuint32 p_button_names[MAX_TRICK_BUTTONS];\r\n\tfor (int b=0; b<MAX_TRICK_BUTTONS; ++b)\r\n\t{\r\n\t\tp_button_names[b]=0;\r\n\t}\t\r\n\t\r\n\tswitch (NameChecksum)\r\n\t{\r\n\t\tcase 0x14fe9b7d: //\tAirTrickLogic\r\n\t\t{\r\n\t\t\t// Get two button names followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,2,p_button_names);\r\n\t\t\t\r\n\t\t\tif (GetButtonState(p_button_names[1]))\r\n\t\t\t{\r\n\t\t\t\t// Search for the event saying that button 2 got pressed, and flag it as used.\r\n\t\t\t\t// If this was not done, we'd be able to get two kickflips by doing left-square,\r\n\t\t\t\t// then letting go of left and pressing square again.\r\n\t\t\t\tint Index=mLastEvent;\r\n\t\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (mpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\t\r\n\t\t\t\r\n\t\t\t\t\t--Index;\r\n\t\t\t\t\tif (Index<0)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tif (TriggeredInLastNMilliseconds(p_button_names[0],Duration,IgnoreMask))\r\n\t\t\t\t{\r\n\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (BothTriggeredNothingInBetween(p_button_names[0],p_button_names[1],Duration,IgnoreMask))\r\n\t\t\t\t{\r\n\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\tcase 0xffb718bd: // PressAndRelease\r\n\t\t{\r\n\t\t\t// Get two button names followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,2,p_button_names);\r\n\r\n\t\t\tint Index=mLastEvent;\r\n\t\t\tint Count=0;\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tswitch (Count)\r\n\t\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=1;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase 0x2c434c90: // TapTwiceRelease\r\n\t\t{\r\n\t\t\t// Get two button names followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,2,p_button_names);\r\n\r\n\t\t\tint Index=mLastEvent;\r\n\t\t\tint Count=0;\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tswitch (Count)\r\n\t\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\t(mpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED && \r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1]))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=1;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=2;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase 0x696e5e66: // ReleaseAndTap\r\n\t\t{\r\n\t\t\t// Get two button names followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,2,p_button_names);\r\n\r\n\t\t\tint e[3]={-1,-1,-1};\r\n\t\t\t\t\r\n\t\t\tint index=mLastEvent;\r\n\t\t\tint count=0;\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (!(mpButtonEvents[index].Used & IgnoreMask))\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 button=mpButtonEvents[index].ButtonNameChecksum;\r\n\t\t\t\t\tif (button != CRCD(0xbc6b118f,\"up\") &&\r\n\t\t\t\t\t\tbutton != CRCD(0xe3006fc4,\"down\") &&\r\n\t\t\t\t\t\tbutton != CRCD(0x85981897,\"left\") &&\r\n\t\t\t\t\t\tbutton != CRCD(0x4b358aeb,\"right\"))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\te[count++]=index;\r\n\t\t\t\t\t\tif (count==3)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t--index;\r\n\t\t\t\tif (index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tindex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (e[0]==-1 || e[1]==-1 || e[2]==-1)\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[e[0]].Time)>=Duration ||\r\n\t\t\t\tTmr::ElapsedTime(mpButtonEvents[e[1]].Time)>=Duration ||\r\n\t\t\t\tTmr::ElapsedTime(mpButtonEvents[e[2]].Time)>=Duration)\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\t\r\n\r\n\t\t\tif (mpButtonEvents[e[0]].EventType==EVENT_BUTTON_RELEASED && \r\n\t\t\t\tmpButtonEvents[e[0]].ButtonNameChecksum==p_button_names[1] &&\r\n                mpButtonEvents[e[1]].EventType==EVENT_BUTTON_PRESSED && \r\n\t\t\t\tmpButtonEvents[e[1]].ButtonNameChecksum==p_button_names[1] &&\r\n                mpButtonEvents[e[2]].EventType==EVENT_BUTTON_RELEASED && \r\n\t\t\t\tmpButtonEvents[e[2]].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t{\r\n\t\t\t\tmpButtonEvents[e[0]].MaybeUsed=true;\r\n\t\t\t\tmpButtonEvents[e[1]].MaybeUsed=true;\r\n\t\t\t\tmpButtonEvents[e[2]].MaybeUsed=true;\r\n\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase 0x3c3028f4: // PressTwo\r\n\t\t{\r\n\t\t\t// Get two button names followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,2,p_button_names);\r\n\t\t\t\r\n\t\t\tif (GetButtonState(p_button_names[0]) && GetButtonState(p_button_names[1]))\r\n\t\t\t{\r\n\t\t\t\tif (BothTriggeredNothingInBetween(p_button_names[0],p_button_names[1],Duration,IgnoreMask))\r\n\t\t\t\t{\r\n\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\t\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\tcase 0x7d482318: // InOrder\r\n\t\t{\r\n\t\t\t// Get two button names followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,2,p_button_names);\r\n\t\t\t\r\n\t\t\tint Index=mLastEvent;\r\n\t\t\tint Count=0;\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tswitch (Count)\r\n\t\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=1;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\r\n\t\tcase 0x3f369070: // PressTwoAnyOrder\r\n\t\t{\r\n\t\t\tint i;\r\n\t\t\tint Index;\r\n\t\t\t\r\n\t\t\t// Get two button names followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,2,p_button_names);\r\n\t\t\t\r\n\t\t\tbool Found = false;\r\n\t\t\t\r\n\t\t\tbool FirstPressed = false;\r\n\t\t\tbool SecondPressed = false;\r\n\t\t\tIndex=mLastEvent;\r\n\t\t\tfor (i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t{\r\n\t\t\t\t\tif (mpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tFirstPressed=false;\r\n\t\t\t\t\t\tSecondPressed=false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if (mpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tif (SecondPressed)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tFound=true;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tFirstPressed=true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\r\n\t\t\t\r\n\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t{\r\n\t\t\t\t\tif (mpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tFirstPressed=false;\r\n\t\t\t\t\t\tSecondPressed=false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if (mpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tif (FirstPressed)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tFound=true;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tSecondPressed=true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (Found)\r\n\t\t\t{\r\n\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\t\r\n\t\t\r\n\t\t// Various different TripleInOrder's, which became necessary when using it for different types of\r\n\t\t// tricks such as the boneless, and the special grinds.\r\n\t\t// It was found that the logic needs to be quite sloppy for the boneless so that they can get triggered\r\n\t\t// easily otherwise it feels wrong, whereas it needs to be stricter for special grinds otherwise \r\n\t\t// they go off all the time.\r\n\t\t\r\n\t\t// Requires that Button1 be pressed, followed by Button2 pressed, followed by Button3 pressed.\r\n\t\t// Doesn't care when they get released.\r\n\t\tcase 0xc1ad35c0: // TripleInOrderSloppy\r\n\t\t{\r\n\t\t\t// Get three button names followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,3,p_button_names);\r\n\t\t\t\r\n\t\t\tint Index=mLastEvent;\r\n\t\t\tint Count=0;\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tswitch (Count)\r\n\t\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[2])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=1;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=2;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t// Button1 must be pressed then released, then Button2 must be pressed then released,\r\n\t\t// then Button3 must be pressed. Doesn't require that Button3 be released, because it\r\n\t\t// feels better if the logic takes effect exactly on the 3rd press.\r\n\t\tcase 0x3fe7c311: // TripleInOrderStrict\r\n\t\t{\r\n\t\t\t// Get three button names followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,3,p_button_names);\r\n\t\t\t\r\n\t\t\tint Index=mLastEvent;\r\n\t\t\tint Count=0;\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tswitch (Count)\r\n\t\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[2])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=1;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=2;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=3;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=4;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 4:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t// Button1 must be pressed then released, followed by either button2 pressed then button3 pressed,\r\n\t\t// or button3 pressed then button2 pressed.\r\n\t\t// Sort of strict & sloppy at the same time.\r\n\t\tcase 0xa2e042d7: // TripleInOrder\r\n\t\t{\r\n\t\t\t// Get three button names followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,3,p_button_names);\r\n\t\t\t\r\n\t\t\tint Index=mLastEvent;\r\n\t\t\tint Count=0;\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tswitch (Count)\r\n\t\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\t// Even though it's called TripleInOrder, buttons 2 and 3\r\n\t\t\t\t\t// can be pressed in either order, so we do a bit of convoluted\r\n\t\t\t\t\t// branching here to check for both cases.\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (mpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[2])\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\t\tCount=1;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\tif (mpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\t\tCount=2;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=3;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[2])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=3;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t// Button 1 has to be pressed and released before the other 2.\t\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=4;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 4:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0x823b8342: // Press\r\n\t\t{\r\n\t\t\t// Get one button name followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,1,p_button_names);\r\n\t\t\t\r\n\t\t\tint Index=mLastEvent;\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t{\r\n\t\t\t\t\tmpButtonEvents[Index].Used|=UsedMask;\r\n\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase 0x61b8fce2: // Release\r\n\t\t{\r\n\t\t\t// Get one button name followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,1,p_button_names);\r\n\t\t\t\r\n\t\t\tint Index=mLastEvent;\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED &&\r\n\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t{\r\n\t\t\t\t\tmpButtonEvents[Index].Used|=UsedMask;\r\n\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase 0x7fa5cdbb: // Tap\r\n\t\t{\r\n\t\t\t// Get one button name followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,1,p_button_names);\r\n\t\t\t\r\n\t\t\tint Count=0;\r\n\t\t\tint Index=mLastEvent;\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (Count == 0)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase 0xf630dae5: // HoldTwoAndPress\r\n\t\t{\r\n\t\t\t// Get three button names followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,3,p_button_names);\r\n\t\t\t\r\n\t\t\tint Index=mLastEvent;\r\n\t\t\tint Count=0;\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tswitch (Count)\r\n\t\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[2])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tCount=1;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (mpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif (mpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\t\t\tCount=2;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse if (mpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse if (mpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif (mpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\t\t\tCount=3;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse if (mpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\t\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (mpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif (mpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse if (mpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\t\t\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (mpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif (mpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse if (mpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\t\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\r\n\t\tcase 0xac2b1445: // ReleaseTwoAndPress\r\n\t\t{\r\n\t\t\t// Get three button names followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,3,p_button_names);\r\n\t\t\t\r\n\t\t\tint Index=mLastEvent;\r\n\t\t\tbool got_a_released=false;\r\n\t\t\tbool got_b_released=false;\r\n\t\t\tbool got_c_pressed=false;\r\n\t\t\t\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (!got_a_released)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tgot_a_released=true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\t\t\t\t\r\n\t\t\t\tif (!got_b_released)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tgot_b_released=true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\t\t\t\t\r\n\t\t\t\tif (!got_c_pressed)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[2])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tgot_c_pressed=true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\t\t\t\t\r\n\r\n\r\n\t\t\t\tif (got_a_released && !got_b_released)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\t\t\t\t\r\n\t\t\t\tif (got_b_released && !got_a_released)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\tif (got_a_released && got_b_released && got_c_pressed)\r\n\t\t\t\t{\r\n\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\r\n\t\tcase 0x395ec2d4: // ReleaseTwo\r\n\t\t{\r\n\t\t\t// Get two button names followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,2,p_button_names);\r\n\t\t\t\r\n\t\t\tint Index=mLastEvent;\r\n\t\t\tbool got_a_released=false;\r\n\t\t\tbool got_b_released=false;\r\n\t\t\t\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (!got_a_released)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tgot_a_released=true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\t\t\t\t\r\n\t\t\t\tif (!got_b_released)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\tgot_b_released=true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\t\t\t\t\r\n\r\n\t\t\t\tif (got_a_released && !got_b_released)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\t\t\t\t\r\n\t\t\t\tif (got_b_released && !got_a_released)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED &&\r\n\t\t\t\t\t\tmpButtonEvents[Index].ButtonNameChecksum==p_button_names[1])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\tif (got_a_released && got_b_released)\r\n\t\t\t\t{\r\n\t\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\r\n\t\tcase 0xb6258557: // ExtraGrabTrickLogic\r\n\t\t{\r\n\t\t\tuint32 last_direction_button=0;\r\n\t\t\tfor (int b=0; b<MAX_TRICK_BUTTONS; ++b)\r\n\t\t\t{\r\n\t\t\t\tif (s_is_direction_button(mp_trick_button[b]))\r\n\t\t\t\t{\r\n\t\t\t\t\tlast_direction_button=mp_trick_button[b];\r\n\t\t\t\t}\r\n\t\t\t}\t\t\r\n\t\t\t\r\n\t\t\t// Get one button name followed by a duration value.\r\n\t\t\tuint32 Duration=get_buttons_and_duration(pComp,1,p_button_names);\r\n\t\t\t\r\n\t\t\tbool do_trigger=false;\r\n\t\t\tint pressed_index=0;\r\n\t\t\t\r\n\t\t\tint Index=mLastEvent;\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tif (!(mpButtonEvents[Index].Used & IgnoreMask) &&\r\n\t\t\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (mpButtonEvents[Index].ButtonNameChecksum==p_button_names[0])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// OK, so the button has been pressed, but don't return true\r\n\t\t\t\t\t\t// just yet cos we want to keep looking back in time & kill any\r\n\t\t\t\t\t\t// direction button events that are the same direction button as\r\n\t\t\t\t\t\t// used by last trick.\r\n\t\t\t\t\t\tdo_trigger=true;\r\n\t\t\t\t\t\tpressed_index=Index;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\telse if (s_is_direction_button(mpButtonEvents[Index].ButtonNameChecksum))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// A direction button has gotten pushed during the same time interval ...\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif (mpButtonEvents[Index].ButtonNameChecksum != last_direction_button)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// It is not the same as the previous trick's direction button,\r\n\t\t\t\t\t\t\t// so do not trigger at all. Run away without killing any events.\r\n\t\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// It is the same as the previous trick's direction button,\r\n\t\t\t\t\t\t\t// so flag it as maybe used.\r\n\t\t\t\t\t\t\t// If we survive the rest of this loop without the above 'return true'\r\n\t\t\t\t\t\t\t// firing then the MaybeUsed flags will get converted to used after\r\n\t\t\t\t\t\t\t// the loop has finished.\r\n\t\t\t\t\t\t\tmpButtonEvents[Index].MaybeUsed=true;\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t--Index;\r\n\t\t\t\tif (Index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tIndex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\r\n\t\t\tif (do_trigger)\r\n\t\t\t{\r\n\t\t\t\t// Kill the events for sure.\r\n\t\t\t\tmpButtonEvents[pressed_index].Used|=UsedMask;\r\n\t\t\t\tConvertMaybeUsedToUsed(UsedMask);\r\n\t\t\t\trecord_last_tricks_buttons(p_button_names);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0xa8123ecf: // HoldThree\t\t\t\r\n\t\t{\r\n\t\t\tScript::CComponent *p_comp=pComp;\r\n\t\t\t\r\n\t\t\tDbg_MsgAssert(p_comp && p_comp->mType==ESYMBOLTYPE_NAME,(\"HoldThree logic requires 3 button names\"));\r\n\t\t\tuint32 button1=p_comp->mChecksum;\r\n\t\t\tp_comp=p_comp->mpNext;\r\n\t\t\tDbg_MsgAssert(p_comp && p_comp->mType==ESYMBOLTYPE_NAME,(\"HoldThree logic requires 3 button names\"));\r\n\t\t\tuint32 button2=p_comp->mChecksum;\r\n\t\t\tp_comp=p_comp->mpNext;\r\n\t\t\tDbg_MsgAssert(p_comp && p_comp->mType==ESYMBOLTYPE_NAME,(\"HoldThree logic requires 3 button names\"));\r\n\t\t\tuint32 button3=p_comp->mChecksum;\r\n\t\t\t\r\n\t\t\treturn GetButtonState(button1) && GetButtonState(button2) && GetButtonState(button3);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Unexpected name '%s'\",Script::FindChecksumName(NameChecksum)));\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\r\n\tResetMaybeUsedFlags();\r\n\treturn false;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\tTrick queue stuff\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid CTrickComponent::ClearTrickQueue()\r\n{\r\n\t\r\n\tmFrontTrick=mBackTrick=-1;\r\n}\r\n\r\nvoid CTrickComponent::AddTrick(uint32 ArrayChecksum, uint Index, bool UseSpecialTrickText)\r\n{\r\n\tint i=0;\r\n\tif (mFrontTrick==-1 && mBackTrick==-1)\r\n\t{\r\n\t\t// The queue is empty, so initialise the front and back.\r\n\t\tmFrontTrick=i;\r\n\t\tmBackTrick=i;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mFrontTrick!=-1,(\"mFrontTrick = -1 ??\"));\r\n\t\tDbg_MsgAssert(mBackTrick!=-1,(\"mBackTrick = -1 ??\"));\r\n\t\t\r\n\t\t// Go to the current back of the queue\r\n\t\ti=mBackTrick;\r\n\t\t// Advance to the next entry\r\n\t\t++i;\r\n\t\tif (i>=TRICK_QUEUE_SIZE)\r\n\t\t{\r\n\t\t\ti=0;\r\n\t\t}\r\n\t\t// If reached the front again then there is no room left,\r\n\t\t// so don't do anything.\r\n\t\tif (i==mFrontTrick)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t// Got a new back of the queue.\r\n\t\tmBackTrick=i;\t\t\t\r\n\t}\t\r\n\t\r\n\t// Write in the info.\r\n\tmpTricks[i].ArrayChecksum=ArrayChecksum;\r\n\tmpTricks[i].Index=Index;\r\n\tmpTricks[i].UseSpecialTrickText=UseSpecialTrickText;\r\n}\r\n\r\nvoid CTrickComponent::RemoveFrontTrick()\r\n{\r\n\t\r\n\t// If the queue is empty then there is nothing to do.\r\n\tif (mFrontTrick==-1)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tDbg_MsgAssert(mBackTrick!=-1,(\"mBackTrick = -1 ??\"));\r\n\t\r\n\t// If only one element in the queue, then clear the queue.\r\n\tif (mFrontTrick==mBackTrick)\r\n\t{\r\n\t\tClearTrickQueue();\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\t// Advance the front trick to the next entry.\r\n\t++mFrontTrick;\r\n\tif (mFrontTrick>=TRICK_QUEUE_SIZE)\r\n\t{\r\n\t\tmFrontTrick=0;\r\n\t}\t\r\n}\r\n\r\n// This will remove all tricks that came from a certain trick array.\r\n// This is used by the ClearTricksFrom command, which is used by air-trick\r\n// scripts to remove any boneless's as soon as the air trick is triggered, so that \r\n// the boneless does not trigger afterwards. It is possible to trigger a boneless for\r\n// a short time after becoming airborne due to the ground-gone exception, this is\r\n// the 'late-jump'.\r\nvoid CTrickComponent::ClearTricksFrom(uint32 ArrayChecksum)\r\n{\r\n\t\r\n\t\r\n\tint i;\r\n\t\r\n\t// Remove the array from the list of arrays being checked.\r\n\tfor (i=0; i<mNumQueueTricksArrays; ++i)\r\n\t{\r\n\t\tif (mpQueueTricksArrays[i]==ArrayChecksum)\r\n\t\t{\r\n\t\t\t// Shift everything down\r\n\t\t\tfor (int j=i; j<mNumQueueTricksArrays-1; ++j)\r\n\t\t\t{\r\n\t\t\t\tmpQueueTricksArrays[j]=mpQueueTricksArrays[j+1];\r\n\t\t\t}\t\r\n\t\t\t// Oooh, changing the for-loop limit inside the for-loop!\r\n\t\t\t--mNumQueueTricksArrays;\r\n\t\t}\r\n\t}\t\r\n\t\r\n\t// Remove any tricks already in the trick queue that came from the specified array.\r\n\tfor (i=0; i<TRICK_QUEUE_SIZE; ++i)\r\n\t{\r\n\t\tif (mpTricks[i].ArrayChecksum==ArrayChecksum)\r\n\t\t{\r\n\t\t\t// Cancel the trick by zeroing its checksum.\r\n\t\t\tmpTricks[i].ArrayChecksum=0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool CTrickComponent::TrickIsDefined(Script::CStruct *pTrick)\r\n{\r\n\t\r\n\tDbg_MsgAssert(pTrick,(\"NULL pTrick\"));\r\n\t\r\n\tuint32 ScriptChecksum=0;\r\n\tif (pTrick->GetChecksum(0xa6d2d890/* Scr */,&ScriptChecksum))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\tif (pTrick->GetChecksum(0x22e168c1/* Scripts */,&ScriptChecksum))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\tScript::CArray *p_template_array=NULL;\r\n\tif (pTrick->GetArray(0x689fe07c/* Template */,&p_template_array))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\r\n\t// Get the checksum of the slot ...\r\n\tuint32 TrickSlotChecksum=0;\r\n\tif (pTrick->GetChecksum(0xa92a2280/* TrickSlot */,&TrickSlotChecksum))\r\n\t{\r\n\t\t// Look up this slot in the trick mappings ...\r\n\t\tDbg_MsgAssert(mpTrickMappings,(\"NULL mpTrickMappings ?\"));\r\n\t\tuint32 TrickChecksum=0;\r\n\t\tmpTrickMappings->GetChecksum(TrickSlotChecksum,&TrickChecksum);\r\n\t\r\n\t\tif (TrickChecksum)\r\n\t\t{\r\n\t\t\t// Now, look up the global structure with this name.\r\n\t\t\tif (Script::GetStructure(TrickChecksum))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// If the trick slot is defined to be an integer, then it is referring\r\n\t\t\t// to a create-a-trick.\r\n\t\t\tint create_a_trick=0;\r\n\t\t\tif (mpTrickMappings->GetInteger(TrickSlotChecksum,&create_a_trick))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\t\t\t\r\n\treturn false;\r\n}\r\n\r\nbool CTrickComponent::RunTrick(Script::CStruct *pTrick, uint32 optionalFlag, Script::CStruct* pExtraParams)\r\n{\r\n\tDbg_MsgAssert(pTrick,(\"NULL pTrick\"));\r\n\t\r\n    uint32 ScriptChecksum=0;\r\n    pTrick->GetChecksum(CRCD(0xa6d2d890,\"Scr\"),&ScriptChecksum);\r\n\t\r\n\t// Dan: HACK\r\n\t// final check to insure that we don't do a grind extra trick when we're not on a rail; if the scripts were perfect, this would never occur; however,\r\n\t// this should prevent an obscure net crash\r\n\tif (ScriptChecksum == CRCD(0x255ed86f, \"Grind\") && mp_skater_core_physics_component->GetRailNode() == -1)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n    \r\n    // counting fliptricks and grabtricks for stats goals\r\n    Script::CStruct* pParams;\r\n    if(pTrick->GetStructure(CRCD(0x7031f10c,\"Params\"),&pParams))\r\n    {\r\n        if (!pParams->ContainsComponentNamed(CRCD(0x7a16aca0,\"IsExtra\")) )\r\n        {\r\n            mp_stats_manager_component->SetTrickType( ScriptChecksum );\r\n        }\r\n    }\r\n\t\r\n#ifdef __NOPT_ASSERT__\r\n\tif (m_num_runtrick_recursions>5)\r\n\t{\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tprintf(\"WARNING! More than 5 RunTrick recursions\\nScriptChecksum='%s'\",Script::FindChecksumName(ScriptChecksum));\r\n\t\t#endif\r\n\t\treturn false;\r\n\t}\t\r\n#endif\t\t// __NOPT_ASSERT__\r\n\t\r\n\tif (ScriptChecksum)\r\n\t{\r\n\t\t// Increment this so that too many recursions can be detected.\r\n\t\t++m_num_runtrick_recursions;\r\n\t\t\r\n\t\t// A trick is triggered, so clear any manual or special grind trick that might have got triggered before.\r\n\t\tmGotManualTrick=false;\r\n\t\tmGotExtraGrindTrick=false;\r\n\t\r\n\t\t// Also clear the do-not-ignore mask, which may have got set by the last SetQueueTricks command.\r\n\t\tmDoNotIgnoreMask=0;\r\n\t\t\r\n\t\t// Change the skater script to be the trick script.\r\n\t\tScript::CStruct *pScriptParams=NULL;\r\n\t\tpTrick->GetStructure(CRCD(0x7031f10c,\"Params\"),&pScriptParams);\r\n\t\r\n\t\t// Run the script.\r\n\t\tmp_skater_flip_and_rotate_component->DoAnyFlipRotateOrBoardRotateAfters(); // <- See huge comment above definition of this function.\r\n\t\t\r\n\t\tCCompositeObject *p_object=GetObject();\r\n\t\tDbg_MsgAssert(p_object,(\"Trick component has NULL object ?\"));\r\n\t\tp_object->SwitchScript(ScriptChecksum,pScriptParams);\r\n\r\n\t\t// If a flag value was passed in, insert it into the script's parameters.\r\n\t\tif (optionalFlag)\r\n\t\t{\r\n\t\t\t// Note that the flag is being inserted into the script's params after calling\r\n\t\t\t// SetScript rather than putting it into pScriptParams.\r\n\t\t\t// This is because pScriptParams could be pointing into some global structure, and\r\n\t\t\t// that should be kept read-only.\r\n\t\t\tScript::CStruct *p_script_params=p_object->GetScript()->GetParams();\r\n\t\t\tDbg_MsgAssert(p_script_params,(\"NULL p_script_params\"));\r\n\t\t\tp_script_params->AddChecksum(NONAME,optionalFlag);\r\n\t\t}\r\n\t\t\r\n\t\tp_object->GetScript()->GetParams()->AppendStructure(pExtraParams);\r\n\t\t\t\r\n\t\tp_object->GetScript()->Update();\r\n\t\r\n\t\t// Set the mDoingTrick flag so that the camera can detect that a trick is being done.\r\n\t\tmp_skater_state_component->SetDoingTrick( true );\r\n\t\r\n\t\t// Increment the trick count, which may set pedestrian exceptions to\r\n\t\t// make them go \"oooOOOOOooooh\"\r\n\t\tIncrementNumTricksInCombo();\r\n\t\t\r\n\t\t// Decrement the recursion counter now that this chunk of code has completed.\r\n\t\t--m_num_runtrick_recursions;\r\n\t\treturn true;\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tuint32 trickslot=0;\r\n\t\tif (!pTrick->GetChecksum(CRCD(0xa92a2280,\"TrickSlot\"),&trickslot))\r\n\t\t{\r\n\t\t\tprintf(\"WARNING! Scr not defined in trick structure!\\n\");\r\n\t\t\tScript::PrintContents(pTrick);\r\n\t\t}\t\r\n\t\t#endif\r\n\t}\t\t\t\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/* Runs the next trick in the queue.\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nvoid CTrickComponent::TriggerNextQueuedTrick(uint32 scriptToRunFirst, Script::CStruct *p_scriptToRunFirstParams, Script::CStruct* pExtraParams)\r\n{\r\n\tmp_skater_state_component->SetDoingTrick( false );\r\n\tmUseSpecialTrickText=false;\r\n\r\n\twhile (true)\r\n\t{\r\n\t\tif (mFrontTrick==-1)\r\n\t\t{\r\n\t\t\t// No tricks left in the queue, so break.\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// Grab the array checksum & index of the trick within the array,\r\n\t\t// then remove the trick from the queue.\r\n\t\t// Removing the trick straight away in case the new script also does\r\n\t\t// a DoNextTrick, which would cause infinite recursion if this trick\r\n\t\t// was still in the queue.\r\n\t\tuint32 ArrayChecksum=mpTricks[mFrontTrick].ArrayChecksum;\r\n\t\tuint Index=mpTricks[mFrontTrick].Index;\r\n\t\t// Set this flag so that any special trick scripts that do get executed during the RunTrick\r\n\t\t// will use the yellow text if they execute a Display command. \r\n\t\tmUseSpecialTrickText=mpTricks[mFrontTrick].UseSpecialTrickText;\r\n\t\t\r\n\t\tRemoveFrontTrick();\r\n\r\n\t\t// The ArrayChecksum might be zero, this would indicate that \r\n\t\t// the trick got cancelled by a call to ClearTricksFrom().\r\n\t\tif (ArrayChecksum)\r\n\t\t{\r\n\t\t\t// The DoNextTrick command can specify a script that must be run before the trick script.\r\n\t\t\t// So if one was specified, run it.\r\n\t\t\tif (scriptToRunFirst)\r\n\t\t\t{\r\n\t\t\t\tGetObject()->AllocateScriptIfNeeded();\r\n\t\t\t\tGetObject()->GetScript()->Interrupt(scriptToRunFirst, p_scriptToRunFirstParams);\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\t// Get the trick array that the trick belongs to.\r\n\t\t\tScript::CArray *pArray=Script::GetArray(ArrayChecksum);\r\n\t\t\tDbg_MsgAssert(pArray,(\"NULL pArray ?\"));\r\n\t\t\t\r\n\t\t\t// Get the structure defining the trick.\r\n\t\t\tScript::CStruct *pTrickStruct=pArray->GetStructure(Index);\r\n\t\t\tDbg_MsgAssert(pTrickStruct,(\"NULL pTrickStruct ???\"));\r\n\t\t\t\r\n\t\t\t// Try running the trick the old way, which is where the trick script is\r\n\t\t\t// specified directly in the structure. \r\n\t\t\tif (!RunTrick(pTrickStruct, 0, pExtraParams))\r\n\t\t\t{\r\n\t\t\t\t// That didn't work, so they must be wanting to specify a trick slot\r\n\t\t\t\t// instead, so get the trickslot ...\r\n\t\t\t\t\r\n\t\t\t\t// Get the checksum of the slot ...\r\n\t\t\t\tuint32 TrickSlotChecksum=0;\r\n\t\t\t\tpTrickStruct->GetChecksum(CRCD(0xa92a2280,\"TrickSlot\"),&TrickSlotChecksum);\r\n\t\t\t\r\n\t\t\t\tif (TrickSlotChecksum)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Look up this slot in the trick mappings ...\r\n\t\t\t\t\tDbg_MsgAssert(mpTrickMappings,(\"NULL mpTrickMappings ?\"));\r\n\t\t\t\t\r\n\t\t\t\t\t// Maybe it is a create-a-trick, in which case it is referred to by an\r\n\t\t\t\t\t// integer index value.\r\n\t\t\t\t\tint create_a_trick=0;\r\n\t\t\t\t\tif (mpTrickMappings->GetInteger(TrickSlotChecksum,&create_a_trick))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// There is a create-a-trick defined!\r\n\t\t\t\t\t\t// Run the special CreateATrick script passing the index as a parameter.\r\n\t\t\t\t\t\tScript::CStruct *p_params=new Script::CStruct;\r\n\t\t\t\t\t\tp_params->AddInteger(CRCD(0xb4a39841,\"trick_index\"),create_a_trick);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tp_params->AppendStructure(pExtraParams);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tCCompositeObject *p_object=GetObject();\r\n\t\t\t\t\t\tDbg_MsgAssert(p_object,(\"Trick component has NULL object ?\"));\r\n\t\t\t\t\t\tp_object->SwitchScript(CRCD(0x2d90485d,\"CreateATrick\"),p_params);\r\n\t\t\t\t\t\tdelete p_params;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\tp_object->GetScript()->Update();\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// Set the mDoingTrick flag so that the camera can detect that a trick is being done.\r\n\t\t\t\t\t\tmp_skater_state_component->SetDoingTrick( true );\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t// Increment the trick count, which may set pedestrian exceptions to\r\n\t\t\t\t\t\t// make them go \"oooOOOOOooooh\"\r\n\t\t\t\t\t\tIncrementNumTricksInCombo();\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tuint32 TrickChecksum=0;\r\n\t\t\t\t\t\tmpTrickMappings->GetChecksum(TrickSlotChecksum,&TrickChecksum);\r\n\t\t\t\t\t\r\n\t\t\t\t\t\tif (TrickChecksum)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Now, look up the global structure with this name.\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tScript::CStruct *pTrick=Script::GetStructure(TrickChecksum);\r\n\t\t\t\t\t\t\tif (pTrick)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tRunTrick(pTrick, 0, pExtraParams);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\t\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// The ArrayChecksum was not zero, so break.\r\n\t\t\t// We only keep looping if the ArrayChecksum is zero, so that all the zeros get skipped over.\r\n\t\t\t// If the ArrayChecksum is zero this indicates that the trick got cancelled by a call to\r\n\t\t\t// ClearTricksFrom().\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Scans through a trick array, and adds any tricks that got   \t  */\r\n/* triggered to the trick queue.                                  */\r\n/******************************************************************/\r\nvoid CTrickComponent::MaybeAddTrick(uint32 ArrayChecksum, bool UseSpecialTrickText, uint32 DoNotIgnoreMask)\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert(ArrayChecksum,(\"Zero ArrayChecksum sent to MaybeAddTrick\"));\r\n\t\t\r\n\t// Resolve the checksum into a CArray pointer.\r\n\t// The array is stored by checksum in case it gets reloaded.\r\n\tScript::CArray *pArray=Script::GetArray(ArrayChecksum);\r\n\t\t\r\n\t// The above would have asserted if the array wasn't found, but check pArray isn't NULL anyway.\r\n\tif (pArray)\r\n\t{\r\n\t\t// Scan through the array checking each trick's trigger condition.\r\n\t\tint Size=pArray->GetSize();\r\n\t\tfor (int i=0; i<Size; ++i)\r\n\t\t{\r\n\t\t\tScript::CStruct *pStruct=pArray->GetStructure(i);\r\n\t\t\tDbg_MsgAssert(pStruct,(\"NULL pStruct ???\"));\r\n\t\t\t// pStruct is the structure defining the trick.\r\n\t\t\t\r\n\t\t\tif (TrickIsDefined(pStruct))\r\n\t\t\t{\r\n\t\t\t\t// Get the trigger, which is a structure defining the button combination that triggers the trick.\r\n\t\t\t\tScript::CStruct *p_trigger=get_trigger_structure(pStruct);\r\n\t\t\t\t// An alternate trigger may also be specified. This will also trigger the trick.\r\n\t\t\t\tScript::CStruct *p_alternate_trigger=get_alternate_trigger_structure(pStruct);\r\n\t\t\t\r\n\t\t\t\t// p_trigger could be NULL, but OK cos QueryEvents will return false in that case.\r\n\t\t\t\t// The DoNotIgnoreMask specifies additional used-events that should not be ignored.\r\n\t\t\t\tuint32 ignore_mask=(~USED_BY_MANUAL_TRICK) & (~DoNotIgnoreMask);\r\n\t\t\t\t\r\n\t\t\t\tif (QueryEvents(p_trigger,USED_BY_REGULAR_TRICK,ignore_mask) ||\r\n\t\t\t\t\tQueryEvents(p_alternate_trigger,USED_BY_REGULAR_TRICK,ignore_mask))\r\n\t\t\t\t{\r\n\t\t\t\t\t// The conditions are met, so add the trick to the trick queue.\r\n\t\t\t\t\t// The trick is specified by the name of the array it is in, and its index within that array.\r\n\t\t\t\t\tAddTrick(ArrayChecksum,i,UseSpecialTrickText);\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n}\r\n\t\r\nvoid CTrickComponent::AddTricksToQueue()\r\n{\r\n\t\r\n\r\n\t// If a special tricks array is specified, and we're in the special state, check them.\r\n\tif (mSpecialTricksArrayChecksum)\r\n\t{\r\n\t\tMdl::Score *pScore=GetScoreObject();\r\n\t\tif (pScore->GetSpecialState())\r\n\t\t{\r\n\t\t\tMaybeAddTrick(mSpecialTricksArrayChecksum,USE_SPECIAL_TRICK_TEXT,mDoNotIgnoreMask);\r\n\t\t}\r\n\t}\t\r\n\r\n\t// Check the usual arrays.\r\n\tfor (int TrickArrayIndex=0; TrickArrayIndex<mNumQueueTricksArrays; ++TrickArrayIndex)\r\n\t{\r\n\t\t// Wouldn't expect any of the checksums to be zero.\r\n\t\tDbg_MsgAssert(mpQueueTricksArrays[TrickArrayIndex],(\"Zero mpQueueTricksArrays[%d]\",TrickArrayIndex));\r\n\t\tMaybeAddTrick(mpQueueTricksArrays[TrickArrayIndex],0,mDoNotIgnoreMask);\r\n\t}\r\n}\r\n\r\nvoid CTrickComponent::TriggerAnyManualTrick(Script::CStruct *pExtraParams)\r\n{\r\n\tuint32 scriptToRunFirst=0;\r\n\tScript::CStruct *pScriptToRunFirstParams=NULL;\r\n\tpExtraParams->GetChecksum(CRCD(0x148fee96,\"ScriptToRunFirst\"),&scriptToRunFirst);\r\n\tpExtraParams->GetStructure(CRCD(0x7031f10c,\"Params\"),&pScriptToRunFirstParams);\r\n\r\n\tmUseSpecialTrickText=false;\r\n\t\r\n\tif (mGotManualTrick)\r\n\t{\r\n\t\t// Now that the trick is being done, remove it.\r\n\t\t// Removing it before changing the script rather than after to\r\n\t\t// prevent any possibility of infinite recursion.\r\n\t\tmGotManualTrick=false;\r\n\t\t\r\n\t\t\r\n\t\t// The DoNextManualTrick command can specify a script that must be run before the trick script.\r\n\t\t// So if one was specified, run it.\r\n\t\tif (scriptToRunFirst)\r\n\t\t{\r\n\t\t\t// we need to copy and restore the script parameters as they will be corrupted by the interrupt\r\n\t\t\tScript::CStruct extraParamsCopy(*pExtraParams);\r\n\t\t\tGetObject()->AllocateScriptIfNeeded();\r\n\t\t\tGetObject()->GetScript()->Interrupt(scriptToRunFirst, pScriptToRunFirstParams);\r\n\t\t\t*pExtraParams = extraParamsCopy;\r\n\t\t}\r\n\t\t\r\n\t\t// Get the trick array that the trick belongs to.\r\n\t\tScript::CArray *pArray=Script::GetArray(mManualTrick.ArrayChecksum);\r\n\t\tif (pArray)\r\n\t\t{\r\n\t\t\t// Get the structure defining the trick.\r\n\t\t\tScript::CStruct *pStruct=pArray->GetStructure(mManualTrick.Index);\r\n\t\t\tDbg_MsgAssert(pStruct,(\"NULL pStruct ???\"));\r\n\t\t\t\r\n\r\n\t\t\t// Get the checksum of the slot if there is one ...\r\n\t\t\tuint32 TrickSlotChecksum=0;\r\n\t\t\tpStruct->GetChecksum(CRCD(0xa92a2280,\"TrickSlot\"),&TrickSlotChecksum);\r\n\t\t\t\r\n\t\t\tif (TrickSlotChecksum)\r\n\t\t\t{\r\n\t\t\t\t// Look up this slot in the trick mappings ...\r\n\t\t\t\tDbg_MsgAssert(mpTrickMappings,(\"NULL mpTrickMappings ?\"));\r\n\t\t\t\tuint32 TrickChecksum=0;\r\n\t\t\t\tmpTrickMappings->GetChecksum(TrickSlotChecksum,&TrickChecksum);\r\n\t\t\t\t\r\n\t\t\t\tif (TrickChecksum)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Now, look up the global structure with this name.\r\n\t\t\t\t\t\r\n\t\t\t\t\tScript::CStruct *pTrick=Script::GetStructure(TrickChecksum);\r\n\t\t\t\t\tif (pTrick)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Now change pStruct to be pTrick, so that Scr and Params get read out of it instead.\r\n\t\t\t\t\t\tpStruct=pTrick;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// If there is no TrickSlot specified, then use pStruct as is, to maintain backwards compatibility.\t\t\t\r\n\r\n\t\t\t\r\n\t\t\t// Read the script checksum of the trick.\r\n\t\t\tuint32 ScriptChecksum=0;\r\n\t\t\tpStruct->GetChecksum(CRCD(0xa6d2d890,\"Scr\"),&ScriptChecksum);\r\n\t\t\tif (ScriptChecksum)\r\n\t\t\t{\r\n\t\t\t\tmp_skater_flip_and_rotate_component->DoAnyFlipRotateOrBoardRotateAfters(); // <- See huge comment above definition of this function.\r\n\t\t\t\tmUseSpecialTrickText=mManualTrick.UseSpecialTrickText;\r\n\t\t\t\r\n\t\t\t\t// Change the skater script to be the trick script.\r\n\t\t\t\tScript::CStruct *pScriptParams=NULL;\r\n\t\t\t\tpStruct->GetStructure(CRCD(0x7031f10c,\"Params\"),&pScriptParams);\r\n\t\t\t\t\r\n\t\t\t\tCCompositeObject *p_object=GetObject();\r\n\t\t\t\tDbg_MsgAssert(p_object,(\"Trick component has NULL object ?\"));\r\n\r\n\t\t\t\tif (pExtraParams)\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(pExtraParams!=pScriptParams,(\"Eh ??\"));\r\n\t\t\t\t\t\r\n\t\t\t\t\t// If extra params (params following the DoNextTrick command) were\r\n\t\t\t\t\t// specified, then merge the pScriptParams onto them and use them.\r\n\t\t\t\t\tpExtraParams->AppendStructure(pScriptParams);\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_object->SwitchScript(ScriptChecksum,pExtraParams);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_object->SwitchScript(ScriptChecksum,pScriptParams);\r\n\t\t\t\t}\r\n\t\t\t\tp_object->GetScript()->Update();\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t// Set the mDoingTrick flag so that the camera can detect that a trick is being done.\r\n\t\t\t\tmp_skater_state_component->SetDoingTrick( true );\r\n\t\t\t\t\r\n\t\t\t\t// Increment the trick count, which may set pedestrian exceptions to\r\n\t\t\t\t// make them go \"oooOOOOOooooh\"\r\n\t\t\t\tIncrementNumTricksInCombo();\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n}\r\n\t\r\nvoid CTrickComponent::CheckManualTrickArray(uint32 ArrayChecksum, uint32 IgnoreMask, bool UseSpecialTrickText)\r\n{\r\n\t\r\n\tDbg_MsgAssert(ArrayChecksum,(\"Zero ArrayChecksum sent to CheckManualTrickArray\"));\r\n\t\r\n\t// Resolve the checksum into a CArray pointer.\r\n\t// The array is stored by checksum in case it gets reloaded.\r\n\tScript::CArray *pArray=Script::GetArray(ArrayChecksum);\r\n\t\t\r\n\t// The above would have asserted if the array wasn't found, but check pArray isn't NULL anyway.\r\n\tif (pArray)\r\n\t{\r\n\t\t// Scan through the array checking each trick.\r\n\t\tint Size=pArray->GetSize();\r\n\t\tfor (int t=0; t<Size; ++t)\r\n\t\t{\r\n\t\t\tScript::CStruct *pStruct=pArray->GetStructure(t);\r\n\t\t\tDbg_MsgAssert(pStruct,(\"NULL pStruct ???\"));\r\n\t\t\t// pStruct is the structure defining the trick.\r\n\t\t\t\r\n\t\t\tif (TrickIsDefined(pStruct))\r\n\t\t\t{\r\n\t\t\t\t// Get the trigger, which is a structure defining the button combination that triggers the trick.\r\n\t\t\t\tScript::CStruct *p_trigger=get_trigger_structure(pStruct);\r\n\t\t\t\t// An alternate trigger may also be specified. This will also trigger the trick.\r\n\t\t\t\tScript::CStruct *p_alternate_trigger=get_alternate_trigger_structure(pStruct);\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t// p_trigger could be NULL, but OK cos QueryEvents will return false in that case.\r\n\t\t\t\tif (QueryEvents(p_trigger,USED_BY_MANUAL_TRICK,IgnoreMask) ||\r\n\t\t\t\t\tQueryEvents(p_alternate_trigger,USED_BY_MANUAL_TRICK,IgnoreMask))\r\n\t\t\t\t{\r\n\t\t\t\t\t// The conditions are met, so add the manual trick.\r\n\t\t\t\t\tmManualTrick.ArrayChecksum=ArrayChecksum;\r\n\t\t\t\t\tmManualTrick.Index=t;\r\n\t\t\t\t\tmManualTrick.Time=Tmr::GetTime();\r\n\t\t\t\t\tmManualTrick.Duration=0xffffffff;\r\n\t\t\t\t\tmManualTrick.UseSpecialTrickText=UseSpecialTrickText;\r\n\t\t\t\t\tpStruct->GetInteger(0x79a07f3f/*Duration*/,(int*)&mManualTrick.Duration);\r\n\t\t\t\t\tmGotManualTrick=true;\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n}\r\n\t\r\n// Always called every frame.\r\nvoid CTrickComponent::MaybeQueueManualTrick()\r\n{\r\n\t\r\n\r\n\t// Check any special manual tricks.\r\n\tif (mSpecialManualTricksArrayChecksum)\r\n\t{\r\n\t\t// Got extra manual tricks ...\r\n\t\tMdl::Score *pScore=GetScoreObject();\r\n\t\tif (pScore->GetSpecialState())\r\n\t\t{\r\n\t\t\t// And we're special, so check the tricks.\r\n\t\t\t// The ~USED_BY_MANUAL_TRICK means don't ignore button events that have already been\r\n\t\t\t// used by manuals. This is so that any normal manual that has just got queued won't\r\n\t\t\t// steal the events needed by a up-down-triangle special manual for example.\r\n\t\t\tCheckManualTrickArray(mSpecialManualTricksArrayChecksum,~USED_BY_MANUAL_TRICK,USE_SPECIAL_TRICK_TEXT);\r\n\t\t\tif (mGotManualTrick)\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n\t\r\n\t// For each of the trick arrays, check whether any of the tricks listed within are triggered.\r\n\tfor (int i=0; i<mNumManualTrickArrays; ++i)\r\n\t{\r\n\t\tDbg_MsgAssert(mpManualTrickArrays[i],(\"Zero mpManualTrickArrays[i]\"));\r\n\t\tCheckManualTrickArray(mpManualTrickArrays[i]);\r\n\t}\r\n}\r\n\r\nvoid CTrickComponent::MaybeExpireManualTrick()\r\n{\r\n\t\r\n\tif (mGotManualTrick && mManualTrick.Duration!=0xffffffff)\r\n\t{\r\n\t\tif (Tmr::ElapsedTime(mManualTrick.Time)>mManualTrick.Duration)\r\n\t\t{\r\n\t\t\tmGotManualTrick=false;\r\n\t\t}\t\r\n\t}\t\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\tExtra trick stuff\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool CTrickComponent::TriggerAnyExtraTrick(uint32 ArrayChecksum, uint32 ExcludedTricks)\r\n{\r\n\t\r\n\r\n\tbool TriggeredATrick=false;\r\n\t\r\n\tDbg_MsgAssert(ArrayChecksum,(\"Zero ArrayChecksum sent to TriggerAnyExtraTrick\"));\r\n\tScript::CArray *pArray=Script::GetArray(ArrayChecksum);\r\n\t\r\n\t// The above would have asserted if the array wasn't found, but check pArray isn't NULL anyway.\r\n\tif (pArray)\r\n\t{\r\n\t\t// Scan through the array checking each trick.\r\n\t\tint Size=pArray->GetSize();\r\n\t\t// Only 32 bits available in the mpExcludedExtraTricks entries.\r\n\t\tDbg_MsgAssert(Size<=32,(\"Extra trick array '%s' has more than 32 entries\",Script::FindChecksumName(ArrayChecksum)));\r\n\t\t\r\n\t\tfor (int i=0; i<Size; ++i)\r\n\t\t{\r\n\t\t\tif (!(ExcludedTricks & (1<<i)))\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct *pTrickStruct=pArray->GetStructure(i);\r\n\t\t\t\tDbg_MsgAssert(pTrickStruct,(\"NULL pTrickStruct ???\"));\r\n\t\t\t\t// pTrickStruct is the structure defining the trick.\r\n\t\t\t\t\r\n\t\t\t\tif (TrickIsDefined(pTrickStruct))\r\n\t\t\t\t{\r\n\t\t\t\t\t// Get the trigger, which is a structure defining the button combination that triggers the trick.\r\n\t\t\t\t\tScript::CStruct *p_trigger=get_trigger_structure(pTrickStruct);\r\n\t\t\t\t\t// An alternate trigger may also be specified. This will also trigger the trick.\r\n\t\t\t\t\tScript::CStruct *p_alternate_trigger=get_alternate_trigger_structure(pTrickStruct);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// p_trigger could be NULL, but OK cos QueryEvents will return false in that case.\r\n\t\t\t\t\t\r\n\t\t\t\t\t// The USED_BY_EXTRA_TRICK flags value means flag any button events used as being\r\n\t\t\t\t\t// used by the extra tricks.\r\n\t\t\t\t\tif (QueryEvents(p_trigger,USED_BY_EXTRA_TRICK,~USED_BY_MANUAL_TRICK) ||\r\n\t\t\t\t\t\tQueryEvents(p_alternate_trigger,USED_BY_EXTRA_TRICK,~USED_BY_MANUAL_TRICK))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Run the trick ...\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t// Try running the trick the old way, which is where the trick script is\r\n\t\t\t\t\t\t// specified directly in the structure. \r\n\t\t\t\t\t\t// Passing the flag IsExtra to the script, so that the script can tell\r\n\t\t\t\t\t\t// whether it was run as an extra trick or a regular trick.\r\n\t\t\t\t\t\tif (!RunTrick(pTrickStruct,0x7a16aca0/*IsExtra*/))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// That didn't work, so they must be wanting to specify a trick slot\r\n\t\t\t\t\t\t\t// instead, so get the trickslot ...\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\t// Get the checksum of the slot ...\r\n\t\t\t\t\t\t\tuint32 TrickSlotChecksum=0;\r\n\t\t\t\t\t\t\tpTrickStruct->GetChecksum(0xa92a2280/*TrickSlot*/,&TrickSlotChecksum);\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\tif (TrickSlotChecksum)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// Look up this slot in the trick mappings ...\r\n\t\t\t\t\t\t\t\tDbg_MsgAssert(mpTrickMappings,(\"NULL mpTrickMappings ?\"));\r\n\t\t\t\t\t\t\t\tuint32 TrickChecksum=0;\r\n\t\t\t\t\t\t\t\tmpTrickMappings->GetChecksum(TrickSlotChecksum,&TrickChecksum);\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tif (TrickChecksum)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Now, look up the global structure with this name.\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\tScript::CStruct *pTrick=Script::GetStructure(TrickChecksum);\r\n\t\t\t\t\t\t\t\t\tif (pTrick)\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t// Passing the flag IsExtra to the script, so that the script can tell\r\n\t\t\t\t\t\t\t\t\t\t// whether it was run as an extra trick or a regular trick.\r\n\t\t\t\t\t\t\t\t\t\tif (RunTrick(pTrick,0x7a16aca0/*IsExtra*/))\r\n\t\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t\tTriggeredATrick=true;\r\n\t\t\t\t\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tTriggeredATrick=true;\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t// Check the status of mGotExtraTricks again, because it might have got\r\n\t\t\t\t\t// reset by a call to KillExtraTricks in any script run above.\t\t\r\n\t\t\t\t\tif (!mGotExtraTricks)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn TriggeredATrick;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n\t\r\n\treturn TriggeredATrick;\r\n}\r\n\r\n// Called every frame.\r\nvoid CTrickComponent::TriggerAnyExtraTricks()\r\n{\r\n\t\r\n\r\n\t// Check whether any special extra tricks need to get triggered.\r\n\tif (mGotExtraTricks)\r\n\t{\r\n\t\tif (!mExtraTricksInfiniteDuration && Tmr::ElapsedTime(mExtraTricksStartTime)>mExtraTricksDuration)\r\n\t\t{\r\n\t\t\t// If not infinite duration, and the time is up, then stop checking for extra tricks.\r\n\t\t\tmGotExtraTricks=false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Check any special extra tricks if there are some & we're special.\r\n\t\t\tif (mSpecialExtraTricksArrayChecksum)\r\n\t\t\t{\r\n\t\t\t\tMdl::Score *pScore=GetScoreObject();\r\n\t\t\t\tif (pScore->GetSpecialState())\r\n\t\t\t\t{\r\n\t\t\t\t\t// Set this flag so that any trick scripts that do get executed during the TriggerAnyExtraTrick\r\n\t\t\t\t\t// will use the yellow text if they execute a Display command. \r\n\t\t\t\t\tmUseSpecialTrickText=true;\r\n\t\t\t\t\tif (!TriggerAnyExtraTrick(mSpecialExtraTricksArrayChecksum,mExcludedSpecialExtraTricks))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// No trick was run, so reset this flag just to be sure that it doesn't cause a non-special\r\n\t\t\t\t\t\t// trick triggered later to get displayed in yellow.\r\n\t\t\t\t\t\tmUseSpecialTrickText=false;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Check the status of mGotExtraTricks again, because it might have got\r\n\t\t\t\t\t// reset by a call to KillExtraTricks in any script run above.\t\t\r\n\t\t\t\t\tif (!mGotExtraTricks)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tmUseSpecialTrickText=false;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Check all the extra-trick arrays\r\n\t\t\tfor (int i=0; i<mNumExtraTrickArrays; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (TriggerAnyExtraTrick(mpExtraTrickArrays[i],mpExcludedExtraTricks[i]))\r\n\t\t\t\t{\r\n\t\t\t\t\tmUseSpecialTrickText=false;\r\n\t\t\t\t}\t\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t// Check the status of mGotExtraTricks again, because it might have got\r\n\t\t\t\t// reset by a call to KillExtraTricks in any script run above.\t\t\r\n\t\t\t\tif (!mGotExtraTricks)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\t\r\nvoid CTrickComponent::SetExtraTricks(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tDbg_MsgAssert(pParams,(\"NULL pParams\"));\r\n\tDbg_MsgAssert(pScript,(\"NULL pScript\"));\r\n\t\r\n\tmGotExtraTricks=true;\r\n\t\r\n\tmExtraTricksInfiniteDuration=true;\r\n\tfloat Duration=0.0f;\r\n\tif (pParams->GetFloat(CRCD(0x79a07f3f,\"Duration\"),&Duration))\r\n\t{\r\n\t\tmExtraTricksInfiniteDuration=false;\r\n\t\tmExtraTricksStartTime=Tmr::ElapsedTime(0);\r\n\t\t// Convert Duration, which is assumed to be a number of 60ths, to milliseconds.\r\n\t\tmExtraTricksDuration=(uint32)(Duration*100/6.0f);\r\n\t}\t\r\n\r\n\tmNumExtraTrickArrays=0;\r\n\r\n\t// If a single Tricks parameter is specified, then use that. \r\n\tuint32 ExtraTrickArrayChecksum=0;\r\n\tif (pParams->GetChecksum(CRCD(0x1e26fd3e,\"Tricks\"),&ExtraTrickArrayChecksum))\r\n\t{\r\n\t\tmNumExtraTrickArrays=1;\r\n\t\tmpExtraTrickArrays[0]=ExtraTrickArrayChecksum;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Otherwise, assume all the un-named names in the parameter list are the trick arrays required.\r\n\t\tScript::CComponent *pComp=NULL;\r\n\t\twhile (true)\r\n\t\t{\r\n\t\t\tpComp=pParams->GetNextComponent(pComp);\r\n\t\t\tif (!pComp)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\r\n\t\t\tif (pComp->mNameChecksum==0 && pComp->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t{\r\n\t\t\t\t// Found a name, so add it to the array.\r\n\t\t\t\tDbg_MsgAssert(mNumExtraTrickArrays<MAX_EXTRA_TRICK_ARRAYS,(\"\\n%s\\nToo many extra trick arrays, ask Ken to increase MAX_EXTRA_TRICK_ARRAYS\",pScript->GetScriptInfo()));\r\n\t\t\t\tDbg_MsgAssert(pComp->mChecksum,(\"Zero checksum ???\"));\r\n\t\t\t\tmpExtraTrickArrays[mNumExtraTrickArrays++]=pComp->mChecksum;\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n\r\n\t// Set any special extra tricks required.\r\n\tmSpecialExtraTricksArrayChecksum=0;\r\n\tpParams->GetChecksum(CRCD(0xb394c01c,\"Special\"),&mSpecialExtraTricksArrayChecksum);\r\n\t\r\n\t// Make sure no tricks are going to be excluded first of all ...\r\n\tfor (int i=0; i<MAX_EXTRA_TRICK_ARRAYS; ++i)\r\n\t{\r\n\t\tmpExcludedExtraTricks[i]=0;\r\n\t}\t\r\n\tmExcludedSpecialExtraTricks=0;\r\n\t\r\n\t// Exclude any 'Ignore' tricks specified. May be just one, may be an array of them.\r\n\tconst char *pExtraTrickToIgnore=\"\";\r\n\tScript::CArray *pArrayOfTricksToIgnore=NULL;\r\n\tif (pParams->GetLocalText(CRCD(0xf277291d,\"Ignore\"),&pExtraTrickToIgnore))\r\n\t{\r\n\t\tExcludeExtraTricks(pExtraTrickToIgnore);\r\n\t}\t\r\n\telse if (pParams->GetArray(CRCD(0xf277291d,\"Ignore\"),&pArrayOfTricksToIgnore))\r\n\t{\r\n\t\tDbg_MsgAssert(pArrayOfTricksToIgnore,(\"Eh ? NULL pArrayOfTricksToIgnore ??\"));\r\n\t\tint Size=pArrayOfTricksToIgnore->GetSize();\r\n\t\tfor (int i=0; i<Size; ++i)\r\n\t\t{\r\n\t\t\tExcludeExtraTricks(pArrayOfTricksToIgnore->GetLocalString(i));\r\n\t\t}\r\n\t}\t\t\r\n}\r\n\t\r\nvoid CTrickComponent::KillExtraTricks()\r\n{\r\n\t\r\n\tmGotExtraTricks=false;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// \t\t\t\t\t\t\t\t\tExtra grind trick stuff\r\n//\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n// Called by the ClearExtraGrindTrick script command.\r\nvoid CTrickComponent::ClearExtraGrindTrick()\r\n{\r\n\tmGotExtraGrindTrick=false;\r\n\tmNumExtraGrindTrickArrays=0;\r\n\t\r\n\t// Just to be sure, zero the lot of 'em.\r\n\tfor (int i=0; i<MAX_EXTRA_GRIND_TRICK_ARRAYS; ++i)\r\n\t{\r\n\t\tmpExtraGrindTrickArrays[i]=0;\r\n\t}\t\r\n}\r\n\r\n// Called from CSkater::MaybeStickToRail()\r\n// Returns true if it did trigger a trick, false otherwise.\r\nbool CTrickComponent::TriggerAnyExtraGrindTrick(bool Right, bool Parallel, bool Backwards, bool Regular)\r\n{\r\n\tif (mGotExtraGrindTrick)\r\n\t{\r\n\t\t// Now that the trick is being done, remove it.\r\n\t\t// Removing it before changing the script rather than after to\r\n\t\t// prevent any possibility of infinite recursion.\r\n\t\tmGotExtraGrindTrick=false;\r\n\t\t\r\n\t\t// Get the trick array that the trick belongs to.\r\n\t\tScript::CArray *pArray=Script::GetArray(mExtraGrindTrick.ArrayChecksum);\r\n\t\tif (pArray)\r\n\t\t{\r\n\t\t\t// Get the structure defining the trick.\r\n\t\t\tScript::CStruct *pStruct=pArray->GetStructure(mExtraGrindTrick.Index);\r\n\t\t\tDbg_MsgAssert(pStruct,(\"NULL pStruct ???\"));\r\n\t\t\t\r\n\t\t\tScript::CArray *pScriptArray=NULL;\r\n\t\t\tpStruct->GetArray(CRCD(0x22e168c1,\"Scripts\"),&pScriptArray);\r\n\t\t\t\r\n\t\t\t// The scripts array can alternatively be specified using a template array and a prefix.\r\n\t\t\tScript::CArray *p_template_array=NULL;\r\n\t\t\tpStruct->GetArray(CRCD(0x689fe07c,\"Template\"),&p_template_array);\r\n\t\t\tconst char *p_prefix=NULL;\r\n\t\t\tpStruct->GetString(CRCD(0x6c4e7971,\"Prefix\"),&p_prefix);\r\n\t\t\t\r\n\t\t\tif (!(pScriptArray || p_template_array))\r\n\t\t\t{\r\n\t\t\t\t// No array parameters found, so look for a TrickSlot\r\n\t\t\t\tuint32 TrickSlotChecksum=0;\r\n\t\t\t\tpStruct->GetChecksum(CRCD(0xa92a2280,\"TrickSlot\"),&TrickSlotChecksum);\r\n\t\t\t\tif (TrickSlotChecksum)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Look up this slot in the trick mappings ...\r\n\t\t\t\t\tDbg_MsgAssert(mpTrickMappings,(\"NULL mpTrickMappings ?\"));\r\n\t\t\t\t\tuint32 TrickChecksum=0;\r\n\t\t\t\t\tmpTrickMappings->GetChecksum(TrickSlotChecksum,&TrickChecksum);\r\n\t\t\t\t\r\n\t\t\t\t\tif (TrickChecksum)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Now, look up the global structure with this name.\r\n\t\t\t\t\t\tScript::CStruct *pFoo=Script::GetStructure(TrickChecksum);\r\n\t\t\t\t\t\tif (pFoo)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tpFoo->GetArray(CRCD(0x22e168c1,\"Scripts\"),&pScriptArray);\r\n\t\t\t\t\t\t\tpFoo->GetArray(CRCD(0x689fe07c,\"Template\"),&p_template_array);\r\n\t\t\t\t\t\t\tpFoo->GetString(CRCD(0x6c4e7971,\"Prefix\"),&p_prefix);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\t\t\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\r\n\t\t\t// Calculate the index into the scripts array, which ahs size 16\r\n\t\t\tuint Index=0;\r\n\t\t\tif (Right) Index|=1;\r\n\t\t\tif (Parallel) Index|=2;\r\n\t\t\tif (Backwards) Index|=4;\r\n\t\t\tif (Regular) Index|=8;\r\n\r\n\t\t\t\t\r\n\t\t\tuint32 script_checksum=0;\r\n\t\t\tif (pScriptArray)\r\n\t\t\t{\r\n\t\t\t\tscript_checksum=pScriptArray->GetNameChecksum(Index);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// The grind script arrays all tend to follow the same pattern, with all the\r\n\t\t\t\t// script names having a common prefix, with the suffix following a fixed pattern.\r\n\t\t\t\t// So to save Scott having to add a whole new array for each new grind trick, a\r\n\t\t\t\t// template array can be specified instead.\r\n\t\t\t\t// This template array is an array of 16 suffix strings. The full script name can \r\n\t\t\t\t// then be calculated given the prefix.\r\n\t\t\t\tDbg_MsgAssert(p_template_array,(\"No template array found for entry %d of array '%s'\",mExtraGrindTrick.Index,Script::FindChecksumName(mExtraGrindTrick.ArrayChecksum)));\r\n\t\t\t\tDbg_MsgAssert(p_prefix,(\"No script prefix specified for entry %d of array '%s'\",mExtraGrindTrick.Index,Script::FindChecksumName(mExtraGrindTrick.ArrayChecksum)));\r\n\t\t\t\t\r\n\t\t\t\t// Look up the suffix to use.\r\n\t\t\t\tconst char *p_suffix=p_template_array->GetString(Index);\r\n\t\t\t\tchar p_temp[100];\r\n\t\t\t\tDbg_MsgAssert(strlen(p_prefix)+strlen(p_suffix)<100,(\"Oops, grind script name '%s%s' too long\",p_prefix,p_suffix));\r\n\t\t\t\t// Generate the full script name\r\n\t\t\t\tsprintf(p_temp,\"%s%s\",p_prefix,p_suffix);\r\n\t\t\t\t// and hence calculate the script name checksum.\r\n\t\t\t\tscript_checksum=Script::GenerateCRC(p_temp);\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tScript::CStruct *pParams=NULL;\r\n\t\t\tpStruct->GetStructure(CRCD(0x7031f10c,\"Params\"),&pParams);\r\n\t\t\t\r\n\r\n\t\t\t// Initialise mGrindTweak, which should get set by a SetGrindTweak command\r\n\t\t\t// in the script that is about to be run.\r\n\t\t\t// TODO: Is there a neater way of doing this?\r\n\t\t\tCCompositeObject *p_object=GetObject();\r\n\t\t\tif (p_object->GetType()==SKATE_TYPE_SKATER)\r\n\t\t\t{\r\n\t\t\t\tmp_skater_core_physics_component->ResetGrindTweak();\r\n\t\t\t}\r\n\r\n\t\t\t// Set this flag so that any special trick scripts that do get executed during the mp_script->Update()\r\n\t\t\t// will use the yellow text if they execute a Display command. \r\n\t\t\tmUseSpecialTrickText=mExtraGrindTrick.UseSpecialTrickText;\r\n\t\t\r\n\t\t\tmp_skater_flip_and_rotate_component->DoAnyFlipRotateOrBoardRotateAfters(); // <- See huge comment above definition of this function.\r\n\t\t\t\r\n\t\t\tp_object->SwitchScript(script_checksum,pParams);\r\n\t\t\tp_object->GetScript()->Update();\r\n\t\t\t\r\n\t\t\t// Set the mDoingTrick flag so that the camera can detect that a trick is being done.\r\n\t\t\tmp_skater_state_component->SetDoingTrick( true );\r\n\r\n\t\t\t// Increment the trick count, which may set pedestrian exceptions to\r\n\t\t\t// make them go \"oooOOOOOooooh\"\r\n\t\t\tIncrementNumTricksInCombo();\r\n\t\t\t\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n// Checks a single array of grind tricks.\r\nvoid CTrickComponent::MaybeQueueExtraGrindTrick(uint32 ArrayChecksum, bool UseSpecialTrickText)\r\n{\r\n\t\r\n\tDbg_MsgAssert(ArrayChecksum,(\"Zero ArrayChecksum sent to MaybeQueueExtraGrindTrick\"));\r\n\r\n\t// Resolve the checksum into a CArray pointer.\r\n\t// The array is stored by checksum in case it gets reloaded.\r\n\tScript::CArray *pArray=Script::GetArray(ArrayChecksum);\r\n\t\t\r\n\t// The above would have asserted if the array wasn't found, but check pArray isn't NULL anyway.\r\n\tif (pArray)\r\n\t{\r\n\t\t// Scan through the array checking each trick.\r\n\t\tint Size=pArray->GetSize();\r\n\t\tfor (int t=0; t<Size; ++t)\r\n\t\t{\r\n\t\t\tScript::CStruct *pStruct=pArray->GetStructure(t);\r\n\t\t\tDbg_MsgAssert(pStruct,(\"NULL pStruct ???\"));\r\n\t\t\t// pStruct is the structure defining the trick.\r\n\t\t\t\r\n\t\t\tif (TrickIsDefined(pStruct))\r\n\t\t\t{\r\n\t\t\t\t// Get the trigger, which is a structure defining the button combination that triggers the trick.\r\n\t\t\t\tScript::CStruct *p_trigger=get_trigger_structure(pStruct);\r\n\t\t\t\t// An alternate trigger may also be specified. This will also trigger the trick.\r\n\t\t\t\tScript::CStruct *p_alternate_trigger=get_alternate_trigger_structure(pStruct);\r\n\t\t\t\t\r\n\t\t\t\t// p_trigger could be NULL, but OK cos QueryEvents will return false in that case.\r\n\t\t\t\tif (QueryEvents(p_trigger,USED_BY_EXTRA_GRIND_TRICK,~USED_BY_MANUAL_TRICK) ||\r\n\t\t\t\t\tQueryEvents(p_alternate_trigger,USED_BY_EXTRA_GRIND_TRICK,~USED_BY_MANUAL_TRICK))\r\n\t\t\t\t{\r\n\t\t\t\t\t// The conditions are met, so add the special grind trick.\r\n\t\t\t\t\tmExtraGrindTrick.ArrayChecksum=ArrayChecksum;\r\n\t\t\t\t\tmExtraGrindTrick.Index=t;\r\n\t\t\t\t\tmExtraGrindTrick.Time=Tmr::GetTime();\r\n\t\t\t\t\tmExtraGrindTrick.Duration=0xffffffff;\r\n\t\t\t\t\tmExtraGrindTrick.UseSpecialTrickText=UseSpecialTrickText;\r\n\t\t\t\t\tpStruct->GetInteger(0x79a07f3f/*Duration*/,(int*)&mExtraGrindTrick.Duration);\r\n\t\t\t\t\tmGotExtraGrindTrick=true;\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n}\r\n\t\r\n// Always called every frame.\r\nvoid CTrickComponent::MaybeQueueExtraGrindTrick()\r\n{\r\n\t\r\n\t\r\n\t// If got a special special grind trick array, and we're special, check it.\r\n\tif (mSpecialExtraGrindTrickArrayChecksum)\r\n\t{\r\n\t\tMdl::Score *pScore=GetScoreObject();\r\n\t\tif (pScore->GetSpecialState())\r\n\t\t{\r\n\t\t\tMaybeQueueExtraGrindTrick(mSpecialExtraGrindTrickArrayChecksum,USE_SPECIAL_TRICK_TEXT);\r\n\t\t}\t\r\n\t}\r\n\t\r\n\t// Note: Should this function carry on checking once mGotExtraGrindTrick becomes true?\r\n\t// Currently it does, so the first trick triggered will be overridden by any further special\r\n\t// grind. Check with Scott.\r\n\t\r\n\t// For each of the trick arrays, check whether any of the tricks listed within are triggered.\r\n\tfor (int i=0; i<mNumExtraGrindTrickArrays; ++i)\r\n\t{\r\n\t\tDbg_MsgAssert(mpExtraGrindTrickArrays[i],(\"Zero mpExtraGrindTrickArrays[%d]\",i));\r\n\t\tMaybeQueueExtraGrindTrick(mpExtraGrindTrickArrays[i]);\r\n\t}\r\n}\r\n\r\n// Also always called every frame.\r\nvoid CTrickComponent::MaybeExpireExtraGrindTrick()\r\n{\r\n\t\r\n\tif (mGotExtraGrindTrick && mExtraGrindTrick.Duration!=0xffffffff)\r\n\t{\r\n\t\tif (Tmr::ElapsedTime(mExtraGrindTrick.Time)>mExtraGrindTrick.Duration)\r\n\t\t{\r\n\t\t\t// It's past its sell by date, so kill it.\r\n\t\t\tmGotExtraGrindTrick=false;\r\n\t\t}\t\r\n\t}\t\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n// Returns true if the passed trick has the name pIgnoreName.\r\nbool CTrickComponent::IsExcluded(Script::CStruct *pTrick, const char *pIgnoreName)\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert(pTrick,(\"NULL pTrick\"));\r\n\t\r\n\t// See if it has a trick slot.\r\n\tuint32 TrickSlotChecksum=0;\r\n\tif (pTrick->GetChecksum(0xa92a2280/*TrickSlot*/,&TrickSlotChecksum))\r\n\t{\r\n\t\t// Look up this slot in the trick mappings ...\r\n\t\tDbg_MsgAssert(mpTrickMappings,(\"NULL mpTrickMappings ?\"));\r\n\t\tuint32 TrickChecksum=0;\r\n\t\tmpTrickMappings->GetChecksum(TrickSlotChecksum,&TrickChecksum);\r\n\t\t\t\t\t\t\t\r\n\t\tif (TrickChecksum)\r\n\t\t{\r\n\t\t\t// Now, look up the global structure with this name.\r\n\t\t\tpTrick=Script::GetStructure(TrickChecksum);\r\n\t\t\tif (!pTrick)\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tScript::CStruct *pParams=NULL;\r\n\tDbg_MsgAssert(pTrick,(\"Eh ?  NULL pTrick\"));\r\n\tpTrick->GetStructure(CRCD(0x7031f10c,\"Params\"),&pParams);\r\n\tif (pParams)\r\n\t{\r\n\t\tconst char *pName=NULL;\r\n\t\tpParams->GetLocalText(CRCD(0xa1dc81f9,\"Name\"),&pName);\r\n\t\tif (pName)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(pIgnoreName,(\"NULL pIgnoreName\"));\r\n\t\t\t// Compare pName and pIgnoreName.\r\n\t\t\t// If they match, return true so that the trick gets excluded.\r\n\t\t\tif (stricmp(pName,pIgnoreName)==0)\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\t\t\r\n\t\t\r\n\treturn false;\r\n}\t\t\t\t\r\n\r\n// Returns a bitfield indicating which of the entries in the passed array are excluded because they have the passed Id.\r\nuint32 CTrickComponent::CalculateIgnoreMask(uint32 ArrayChecksum, const char *pIgnoreName)\r\n{\r\n\t\r\n\tDbg_MsgAssert(ArrayChecksum,(\"Zero ArrayChecksum sent to CalculateIgnoreMask\"));\r\n\tScript::CArray *pArray=Script::GetArray(ArrayChecksum);\r\n\t\r\n\tint Size=pArray->GetSize();\r\n\t// Only 32 bits available ...\r\n\tDbg_MsgAssert(Size<=32,(\"Extra-trick array '%s' has more than 32 entries\",Script::FindChecksumName(ArrayChecksum)));\r\n\t\t\t\r\n\tuint32 Mask=0;\t\r\n\tfor (int i=0; i<Size; ++i)\r\n\t{\r\n\t\tScript::CStruct *pTrick=pArray->GetStructure(i);\r\n\t\tif (IsExcluded(pTrick,pIgnoreName))\r\n\t\t{\r\n\t\t\tMask |= (1<<i);\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn Mask;\t\t\t\r\n}\r\n\r\n// Runs through all the extra-tricks arrays flagging as excluded all those with the name pIgnoreName\r\nvoid CTrickComponent::ExcludeExtraTricks(const char *pIgnoreName)\r\n{\r\n\t\r\n\tfor (int i=0; i<mNumExtraTrickArrays; ++i)\r\n\t{\r\n\t\t// Note: Or-ing on top of what is already there rather than setting equal to the\r\n\t\t// passed mask, because ExcludeExtraTricks may be called on a set of IgnoreId's.\r\n\t\tmpExcludedExtraTricks[i] |= CalculateIgnoreMask(mpExtraTrickArrays[i],pIgnoreName);\r\n\t}\r\n\t\r\n\t// Also do the special extra tricks.\r\n\tif (mSpecialExtraTricksArrayChecksum)\r\n\t{\r\n\t\tmExcludedSpecialExtraTricks |= CalculateIgnoreMask(mSpecialExtraTricksArrayChecksum,pIgnoreName);\r\n\t}\t\r\n}\r\n\r\nvoid CTrickComponent::RecordButtons()\r\n{\r\n\tuint32 input_mask = mp_input_component->GetInputMask();\r\n\t\r\n\tuint32 Direction = CSkaterPad::sGetDirection(\r\n\t\tinput_mask & Inp::Data::mA_UP,\r\n\t\tinput_mask & Inp::Data::mA_DOWN,\r\n\t\tinput_mask & Inp::Data::mA_LEFT,\r\n\t\tinput_mask & Inp::Data::mA_RIGHT\r\n\t);\r\n\t\r\n\tButtonRecord(PAD_U, Direction == PAD_U);\r\n\tButtonRecord(PAD_D, Direction == PAD_D);\r\n\tButtonRecord(PAD_L, Direction== PAD_L);\r\n\tButtonRecord(PAD_R, Direction == PAD_R);\r\n\tButtonRecord(PAD_UL, Direction == PAD_UL);\r\n\tButtonRecord(PAD_UR, Direction == PAD_UR);\r\n\tButtonRecord(PAD_DL, Direction == PAD_DL);\r\n\tButtonRecord(PAD_DR, Direction == PAD_DR);\r\n\t\r\n\tButtonRecord(PAD_CIRCLE, input_mask & Inp::Data::mA_CIRCLE);\r\n\tButtonRecord(PAD_SQUARE, input_mask & Inp::Data::mA_SQUARE);\r\n\tButtonRecord(PAD_TRIANGLE, input_mask & Inp::Data::mA_TRIANGLE);\r\n\tButtonRecord(PAD_X, input_mask & Inp::Data::mA_X);\r\n\tButtonRecord(PAD_L1, input_mask & Inp::Data::mA_L1);\r\n\tButtonRecord(PAD_L2, input_mask & Inp::Data::mA_L2);\r\n\tButtonRecord(PAD_L3, input_mask & Inp::Data::mA_L3);\r\n\tButtonRecord(PAD_R1, input_mask & Inp::Data::mA_R1);\r\n\tButtonRecord(PAD_R2, input_mask & Inp::Data::mA_R2);\r\n\tButtonRecord(PAD_R3, input_mask & Inp::Data::mA_R3);\r\n\tButtonRecord(PAD_BLACK, input_mask & Inp::Data::mA_BLACK);\r\n\tButtonRecord(PAD_WHITE, input_mask & Inp::Data::mA_WHITE);\r\n\tButtonRecord(PAD_Z, input_mask & Inp::Data::mA_Z);\r\n}\r\n\r\nvoid CTrickComponent::DumpEventBuffer()\r\n{\r\n\tprintf(\"Event buffer:\\n\");\r\n\tint Index=mLastEvent;\r\n\tint n=mNumEvents;\r\n\tif (n>10) n=10;\r\n\tfor (int i=0; i<n; ++i)\r\n\t{\r\n\t\tprintf(\"T=%d Used=0x%08x Button=\",mpButtonEvents[Index].Time,mpButtonEvents[Index].Used);\r\n\t\t\r\n\t\tswitch (mpButtonEvents[Index].ButtonNameChecksum)\r\n\t\t{\r\n\t\tcase 0x0:  printf(\"Nothing\"); break;\r\n\t\tcase 0xbc6b118f:  printf(\"Up\"); break;\r\n\t\tcase 0xe3006fc4:  printf(\"Down\"); break;\r\n\t\tcase 0x85981897:  printf(\"Left\"); break;\r\n\t\tcase 0x4b358aeb:  printf(\"Right\"); break;\r\n\t\tcase 0xb7231a95:  printf(\"UpLeft\"); break;\r\n\t\tcase 0xa50950c5:  printf(\"UpRight\"); break;\r\n\t\tcase 0xd8847efa:  printf(\"DownLeft\"); break;\r\n\t\tcase 0x786b8b68:  printf(\"DownRight\"); break;\r\n\t\tcase 0x2b489a86:  printf(\"Circle\"); break;\r\n\t\tcase 0x321c9756:  printf(\"Square\"); break;\r\n\t\tcase 0x7323e97c:  printf(\"X\"); break;\r\n\t\tcase 0x20689278:  printf(\"Triangle\"); break;\r\n\t\tcase 0x26b0c991:  printf(\"L1\"); break;\r\n\t\tcase 0xbfb9982b:  printf(\"L2\"); break;\r\n\t\tcase 0xf2f1f64e:  printf(\"R1\"); break;\r\n\t\tcase 0x6bf8a7f4:  printf(\"R2\"); break;\r\n\t\tcase 0x767a45d7:  printf(\"Black\"); break;\r\n\t\tcase 0xbd30325b:  printf(\"White\"); break;\r\n\t\tdefault: break;\r\n\t\t}\r\n\t\tprintf(\" Event=\");\r\n\t\t\r\n\t\tswitch (mpButtonEvents[Index].EventType)\r\n\t\t{\r\n\t\t\tcase EVENT_NONE:  printf(\"None\"); break;\r\n\t\t\tcase EVENT_BUTTON_PRESSED:  printf(\"Pressed\"); break;\r\n\t\t\tcase EVENT_BUTTON_RELEASED:  printf(\"Released\"); break;\r\n\t\t\tdefault: break;\r\n\t\t}\r\n\t\tprintf(\"\\n\");\r\n\t\t\t\r\n\t\t--Index;\r\n\t\tif (Index<0)\r\n\t\t{\r\n\t\t\tIndex+=MAX_EVENTS;\r\n\t\t}\r\n\t}\t\t\r\n}\r\n\t\r\nvoid CTrickComponent::HandleBashing()\r\n{\r\n\tif (!mBashingEnabled) return;\r\n\t\r\n\tCAnimationComponent* p_animation_component = GetAnimationComponentFromObject(GetObject());\r\n\tDbg_Assert(p_animation_component);\r\n\tp_animation_component->SetAnimSpeed(GetBashFactor(), true);\r\n}\r\n\r\n// Calculates the amount by which the skater's animation needs to be sped up\r\n// due to the player bashing buttons.\r\n// The animation speed needs to be multiplied by the value that this returns.\r\nfloat CTrickComponent::GetBashFactor()\r\n{\r\n\tuint32 Duration=GetPhysicsInt(CRCD(0x6c83fdbf,\"BashPeriod\"));\r\n\t\r\n\t// Scan through all the events in the last BashPeriod milliseconds,\r\n\t// counting all the button press and release events.\r\n\tint Bashes=0;\r\n\tint Index=mLastEvent;\r\n\tfor (int i=0; i<mNumEvents; ++i)\r\n\t{\r\n\t\tif (Tmr::ElapsedTime(mpButtonEvents[Index].Time)>=Duration)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\r\n\t\tif (mpButtonEvents[Index].EventType==EVENT_BUTTON_PRESSED ||\r\n\t\t\tmpButtonEvents[Index].EventType==EVENT_BUTTON_RELEASED)\r\n\t\t{\r\n\t\t\t// Flag the event as used, so that it won't register once the bail has finished.\r\n\t\t\tmpButtonEvents[Index].Used=0xffffffff;\r\n\t\t\t++Bashes;\r\n\t\t}\t\r\n\t\t\r\n\t\t--Index;\r\n\t\tif (Index<0)\r\n\t\t{\r\n\t\t\tIndex+=MAX_EVENTS;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\t// Increase the anim speed based on the number of bashes.\r\n\t\r\n\tfloat bash_factor=Bashes*GetPhysicsFloat(CRCD(0xced14273, \"BashSpeedupFactor\"));\r\n\tfloat max=GetPhysicsFloat(CRCD(0xd24abfa3, \"BashMaxPercentSpeedup\"))/100.0f;\r\n\tif (bash_factor > max)\r\n\t{\r\n\t\tbash_factor=max;\r\n\t}\t\r\n\t\r\n\treturn 1.0f+bash_factor;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently isfrequently the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CTrickComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tDbg_MsgAssert(GetObject()->GetType() == SKATE_TYPE_SKATER, (\"CTrickComponent added to non-skater composite object\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTrickComponent::Update()\r\n{\r\n\t\r\n\t// nonlocal clients have a SkaterCorePhysicsComponent only to provide uber_frig functionality\r\n\tif (!GetSkater()->IsLocalClient())\r\n\t{\r\n\t\tSuspend(true);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tRecordButtons();\r\n\t\r\n\tmp_skater_balance_trick_component->ExcludeBalanceButtons(mNumButtonsToIgnore, mpButtonsToIgnore);\r\n\t\r\n\tTriggerAnyExtraTricks();\r\n\tAddTricksToQueue();\r\n\tMaybeQueueManualTrick();\r\n\tMaybeExpireManualTrick();\r\n\tMaybeQueueExtraGrindTrick();\r\n\tMaybeExpireExtraGrindTrick();\r\n\tHandleBashing();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CTrickComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | DumpEventBuffer | dumps the last ten button events\r\n\t\tcase 0x72c926ca: // DumpEventBuffer\r\n\t\t\tDumpEventBuffer();\r\n\t\t\tbreak;\r\n\r\n        // @script | Held | true if the specified button is being held\r\n        // @uparmopt name | Single button name\r\n\t\t// @parmopt array | Buttons | | Optional array of button names. If specified, then if\r\n\t\t// any of those buttons are held it will return true.\r\n\t\tcase 0xeda2772e: // Held\r\n\t\t{\r\n\t\t\tScript::CArray *p_array=NULL;\r\n\t\t\tif (pParams->GetArray(CRCD(0xbca37a49,\"Buttons\"),&p_array))\r\n\t\t\t{\r\n\t\t\t\t// If an array of buttons is specified, check each of them.\r\n\t\t\t\tint n=p_array->GetSize();\r\n\t\t\t\tfor (int i=0; i<n; ++i)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (GetButtonState(p_array->GetChecksum(i)))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\tuint32 ButtonChecksum=0;\r\n\t\t\tpParams->GetChecksum(NONAME,&ButtonChecksum);\r\n\t\t\tif (!ButtonChecksum)\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\t\r\n\t\t\treturn GetButtonState(ButtonChecksum) ? CBaseComponent::MF_TRUE:CBaseComponent::MF_FALSE;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        // @script | Released | true if the specified button is released\r\n        // @uparm X | button name\r\n\t\tcase 0x4ba9ee9: // Released\t\r\n\t\t{\r\n\t\t\tuint32 ButtonChecksum=0;\r\n\t\t\tpParams->GetChecksum(NONAME,&ButtonChecksum);\r\n\t\t\tif (!ButtonChecksum)\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\t\r\n\t\t\treturn GetButtonState(ButtonChecksum) ? CBaseComponent::MF_FALSE:CBaseComponent::MF_TRUE;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n/*\r\n        // @script | DoNextTrick | runs the next trick in the queue\r\n\t\t// @parmopt name | ScriptToRunFirst | | Script that will be run first before any trick script.\r\n\t\t// @parmopt structure | Params | | Parameters to pass to ScriptToRunFirst\r\n\t\t\r\n\t\tcase 0x09d58f25: // DoNextTrick\r\n\t\t{\r\n\t\t\tuint32 scriptToRunFirst=0;\r\n\t\t\tScript::CStruct *pScriptToRunFirstParams=NULL;\r\n\t\t\tpParams->GetChecksum(CRCD(0x148fee96,\"ScriptToRunFirst\"),&scriptToRunFirst);\r\n\t\t\tpParams->GetStructure(CRCD(0x7031f10c,\"Params\"),&pScriptToRunFirstParams);\r\n\t\t\tTriggerNextQueuedTrick(scriptToRunFirst, pScriptToRunFirstParams);\r\n\t\t\tbreak;\r\n\t\t}\r\n*/\r\n\t\t\r\n         // @script | ClearTricksFrom | \r\n\t\tcase 0xcb30572d: // ClearTricksFrom\r\n\t\t{\r\n\t\t\t// Run through all the parameters.\r\n\t\t\tScript::CComponent *pComp=NULL;\r\n\t\t\twhile (true)\r\n\t\t\t{\r\n\t\t\t\tpComp=pParams->GetNextComponent(pComp);\r\n\t\t\t\tif (!pComp)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tif (pComp->mNameChecksum==0 && pComp->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t\t{\r\n\t\t\t\t\t// It's an unnamed name, so remove the tricks that came from the array with that name.\r\n\t\t\t\t\tClearTricksFrom(pComp->mChecksum);\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | SetQueueTricks | sets the tricks queue\r\n        // @uparmopt name | trick array.  if no array specified\r\n        // a default air tricks array will be used\r\n        // @parmopt name | Special | | special tricks array\r\n\t\tcase 0xd8c79bb0: // SetQueueTricks\r\n\t\t{\r\n\t\t\tmNumQueueTricksArrays=0;\r\n\r\n\t\t\tScript::CComponent *pComp=NULL;\r\n\t\t\twhile (true)\r\n\t\t\t{\r\n\t\t\t\tpComp=pParams->GetNextComponent(pComp);\r\n\t\t\t\tif (!pComp)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tif (pComp->mNameChecksum==0 && pComp->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Found a name, so add it to the array.\r\n\t\t\t\t\tDbg_MsgAssert(mNumQueueTricksArrays<MAX_QUEUE_TRICK_ARRAYS,(\"\\n%s\\nToo many trick arrays\",pScript->GetScriptInfo()));\r\n\t\t\t\t\tDbg_MsgAssert(pComp->mChecksum,(\"Zero checksum ???\"));\r\n\t\t\t\t\tmpQueueTricksArrays[mNumQueueTricksArrays++]=pComp->mChecksum;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (mNumQueueTricksArrays==1)\r\n\t\t\t{\r\n\t\t\t\t// Check if the first array exists. If not, use DefaultAirTricks instead. This array is required to exist, otherwise\r\n\t\t\t\t// AddTricksToQueue will assert.\r\n\t\t\t\t\r\n\t\t\t\tScript::CArray *pArray=Script::GetArray(mpQueueTricksArrays[0]);\r\n\t\t\t\tif (!pArray)\r\n\t\t\t\t{\r\n\t\t\t\t\tmpQueueTricksArrays[0]=CRCD(0x9e22d268,\"DefaultAirTricks\");\r\n\t\t\t\t}\t\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\t// Set any special tricks array required.\r\n\t\t\tmSpecialTricksArrayChecksum=0;\r\n\t\t\tpParams->GetChecksum(CRCD(0xb394c01c,\"Special\"),&mSpecialTricksArrayChecksum);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | UseGrindEvents | \r\n\t\tcase 0xd4099d35: // UseGrindEvents\r\n\t\t\tmDoNotIgnoreMask=USED_BY_EXTRA_GRIND_TRICK;\t\t\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | AddTricksToQueue | This will check the button events and add any triggered tricks \r\n\t\t// to the trick queue. The c-code actually does this every frame anyway, but this function\r\n\t\t// allows it to be done immediately when necessary.\r\n\t\tcase 0xde98de7a: // AddTricksToQueue\r\n\t\t\tAddTricksToQueue();\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | ClearTrickQueue | clears the trick queue\r\n\t\tcase 0x54c33b20: // ClearTrickQueue\r\n\t\t\tClearTrickQueue();\t\t\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | DoNextManualTrick | does next trick while in a manual\r\n\t\tcase 0x788f9a4e: //\tDoNextManualTrick\r\n\t\t\tTriggerAnyManualTrick(pParams);\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | SetManualTricks | \r\n        // @uparm name | trick array\r\n\t\tcase 0x1fcf080a: // SetManualTricks\r\n\t\t{\r\n\t\t\tmNumManualTrickArrays=0;\r\n\r\n\t\t\tScript::CComponent *pComp=NULL;\r\n\t\t\twhile (true)\r\n\t\t\t{\r\n\t\t\t\tpComp=pParams->GetNextComponent(pComp);\r\n\t\t\t\tif (!pComp)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tif (pComp->mNameChecksum==0 && pComp->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Found a name, so add it to the array.\r\n\t\t\t\t\tDbg_MsgAssert(mNumManualTrickArrays<MAX_MANUAL_TRICK_ARRAYS,(\"\\n%s\\nToo many manual trick arrays\",pScript->GetScriptInfo()));\r\n\t\t\t\t\tDbg_MsgAssert(pComp->mChecksum,(\"Zero checksum ???\"));\r\n\t\t\t\t\tmpManualTrickArrays[mNumManualTrickArrays++]=pComp->mChecksum;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Set any special manual tricks array required.\r\n\t\t\tmSpecialManualTricksArrayChecksum=0;\r\n\t\t\tpParams->GetChecksum(CRCD(0xb394c01c,\"Special\"),&mSpecialManualTricksArrayChecksum);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\r\n        // @script | ClearManualTrick | \r\n\t\tcase 0x8e3d3bec: // ClearManualTrick\r\n\t\t\tClearManualTrick();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t/////////////////////////////////////////////////////////////////////////////////////////////\r\n\t\t//\r\n\t\t// Extra-Grind trick stuff, which has a very similar interface to the manual stuff above,\r\n\t\t// except that there is no script command corresponding to DoNextManualTrick because the\r\n\t\t// C-code will automatically run any queued extra grind trick when it snaps the player\r\n\t\t// to a rail in CSkater::MaybeStickToRail\r\n\t\t//\r\n\t\t/////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n        // @script | SetExtraGrindTricks | \r\n        // @uparm name | trick array\r\n\t\tcase 0x6ba35ab4: // SetExtraGrindTricks\r\n\t\t{\r\n\t\t\tmNumExtraGrindTrickArrays=0;\r\n\r\n\t\t\tScript::CComponent *pComp=NULL;\r\n\t\t\twhile (true)\r\n\t\t\t{\r\n\t\t\t\tpComp=pParams->GetNextComponent(pComp);\r\n\t\t\t\tif (!pComp)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tif (pComp->mNameChecksum==0 && pComp->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Found a name, so add it to the array.\r\n\t\t\t\t\tDbg_MsgAssert(mNumExtraGrindTrickArrays<MAX_EXTRA_GRIND_TRICK_ARRAYS,(\"\\n%s\\nToo many special grind trick arrays\",pScript->GetScriptInfo()));\r\n\t\t\t\t\tDbg_MsgAssert(pComp->mChecksum,(\"Zero checksum ???\"));\r\n\t\t\t\t\tmpExtraGrindTrickArrays[mNumExtraGrindTrickArrays++]=pComp->mChecksum;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tmSpecialExtraGrindTrickArrayChecksum=0;\r\n\t\t\tpParams->GetChecksum(CRCD(0xb394c01c,\"Special\"),&mSpecialExtraGrindTrickArrayChecksum);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\r\n        // @script | ClearExtraGrindTrick | \r\n\t\tcase 0xab6b8dd9: // ClearExtraGrindTrick\r\n\t\t\tClearExtraGrindTrick();\r\n\t\t\tbreak;\r\n\r\n        // @script | ClearEventBuffer |\r\n        // @parmopt array | Buttons | | buttons array\r\n        // @parmopt int | OlderThan | 0 | used in conjuction with optional buttons array\r\n\t\tcase 0x86928082: // ClearEventBuffer\t\r\n\t\t{\r\n\t\t\tScript::CArray *pButtonArray=NULL;\r\n\t\t\tif (pParams->GetArray(CRCD(0xbca37a49,\"Buttons\"),&pButtonArray))\r\n\t\t\t{\r\n\t\t\t\tint OlderThan=0;\r\n\t\t\t\tpParams->GetInteger(CRCD(0xcdcfee8a,\"OlderThan\"),&OlderThan);\r\n\t\t\t\tint Size=pButtonArray->GetSize();\r\n\t\t\t\tfor (int i=0; i<Size; ++i)\r\n\t\t\t\t{\r\n\t\t\t\t\tRemoveOldButtonEvents(pButtonArray->GetNameChecksum(i),OlderThan);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tClearEventBuffer();\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | RemoveXEvents | Run through all the recorded button\r\n        // events, and remove any involving button X.\r\n\t\t// This is used as an easy way of fixing the boneless bug.\r\n\t    // This function is called at the start of the land script, \r\n        // which prevents any previously\r\n\t\t// queued bonelesses from being detected.\r\n\t\tcase 0x70e934d: // RemoveXEvents\r\n\t\t{\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (mpButtonEvents[i].ButtonNameChecksum==0x7323e97c/* X */)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Flag the event as having been used, so that it won't be used again.\r\n\t\t\t\t\tmpButtonEvents[i].Used=true;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | RestoreEvents | Restores the events used by a particular trick type.\r\n        // @parmopt name | UsedBy | | The trick type, one of Regular, Extra, Manual or ExtraGrind\r\n\t\t// @parmopt int | Duration | 200 | How far back in time to restore events, in milliseconds\r\n\t\tcase 0x54d43789: // RestoreEvents\r\n\t\t{\r\n\t\t\tint duration=200;\r\n\t\t\tpParams->GetInteger(CRCD(0x79a07f3f,\"Duration\"),&duration);\r\n\t\t\t\r\n\t\t\tuint32 used_by=0;\r\n\t\t\tpParams->GetChecksum(CRCD(0x9694fc41,\"UsedBy\"),&used_by);\r\n\t\t\t\r\n\t\t\tuint32 mask=0;\r\n\t\t\tswitch (used_by)\r\n\t\t\t{\r\n\t\t\t\tcase 0xb58efc2b: // Regular\r\n\t\t\t\t\tmask=USED_BY_REGULAR_TRICK;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 0xb2c0f29a: // Extra\r\n\t\t\t\t\tmask=USED_BY_EXTRA_TRICK;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 0xef24413b: // Manual\r\n\t\t\t\t\tmask=USED_BY_MANUAL_TRICK;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 0xec066b6a: // ExtraGrind\r\n\t\t\t\t\tmask=USED_BY_EXTRA_GRIND_TRICK;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tint index=mLastEvent;\r\n\t\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::ElapsedTime(mpButtonEvents[index].Time) >= (uint32)duration)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\r\n\t\t\t\tif (mpButtonEvents[index].Used & mask)\r\n\t\t\t\t{\r\n\t\t\t\t\tmpButtonEvents[index].Used&=~mask;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t--index;\r\n\t\t\t\tif (index<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tindex+=MAX_EVENTS;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | SetExtraTricks | \r\n        // @parmopt float | Duration | | \r\n        // @parmopt name | Tricks | | trick array\r\n        // @parmopt name | Special | | special tricks array\r\n        // @parmopt local string | Ignore | | trick to ignore\r\n        // @parmopt array | Ignore | | array of tricks to ignore\r\n\t\tcase 0x7627dc71: // SetExtraTricks\r\n\t\t\tSetExtraTricks(pParams,pScript);\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | KillExtraTricks | \r\n\t\tcase 0xd5813251: // KillExtraTricks\r\n\t\t\tKillExtraTricks();\r\n\t\t\tbreak;\r\n\r\n        // @script | SetSlotTrick | \r\n        // @parm name | Slot | slot name\r\n        // @parm name | Trick | \r\n\t\tcase 0xb42a1230: // SetSlotTrick\r\n\t\t{\r\n\t\t\tuint32 Slot=0;\r\n\t\t\tpParams->GetChecksum(CRCD(0x53f1df98,\"Slot\"),&Slot);\r\n\t\t\tDbg_MsgAssert(Slot,(\"\\n%s\\nSetSlotTrick requires a slot name\",pScript->GetScriptInfo()));\r\n\t\t\tuint32 Trick=0;\r\n\t\t\tpParams->GetChecksum(CRCD(0x270f56e1,\"Trick\"),&Trick);\r\n\t\t\t\r\n\t\t\tDbg_MsgAssert(mpTrickMappings,(\"NULL mpTrickMappings\"));\r\n\t\t\t// This will just replace the slot if it exists already.\r\n\t\t\tmpTrickMappings->AddComponent(Slot,(uint8)ESYMBOLTYPE_NAME,Trick);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | ChangeProTricks | \r\n\t\tcase 0xabff7889: // ChangeProTricks \r\n\t\t{\r\n\t\t\t// Have to use GetNextComponent rather than GetChecksum, because GetChecksum won't work if\r\n\t\t\t// the checksum is unnamed, because by convention an unnamed checksum that resolves to a structure\r\n\t\t\t// effectively makes that structure part of the params, & the name of the structure is just considered\r\n\t\t\t// an intermediate thing which is not part of the params.\r\n\t\t\tScript::CComponent *pComp=pParams->GetNextComponent(NULL);\r\n\t\t\tif (pComp && pComp->mNameChecksum==0 && pComp->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct *pNewTrickMappings=Script::GetStructure(pComp->mChecksum);\r\n\t\t\t\tif (pNewTrickMappings)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Found the new structure, so load it in to mpTrickMappings.\r\n\t\t\t\t\tDbg_MsgAssert(mpTrickMappings,(\"NULL mpTrickMappings\"));\r\n\t\t\t\t\tmpTrickMappings->Clear();\r\n\t\t\t\t\tmpTrickMappings->AppendStructure(pNewTrickMappings);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\tprintf(\"\\n%s\\nWarning: Protrick mapping '%s' not found\\n\",pScript->GetScriptInfo(),Script::FindChecksumName(pComp->mChecksum));\r\n\t\t\t\t\t#endif\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\tprintf(\"\\n%s\\nWarning: ChangeProTricks command requires a name.\\n\",pScript->GetScriptInfo());\r\n\t\t\t\t#endif\r\n\t\t\t}\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\t\r\n        // @script | BashOn | turns bash on (for speeding up bails?)\r\n\t\tcase 0xd872002d: // BashOn\r\n\t\t\tmBashingEnabled=true;\r\n\t\t\t// Clear the event buffer so that button presses done before the bail will not\r\n\t\t\t// speed it up.\r\n\t\t\tClearEventBuffer();\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | BashOff | turns bash off\r\n\t\tcase 0x290f6010: // BashOff\r\n\t\t\tmBashingEnabled=false;\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | SetTrickName | \r\n        // @uparmopt 'local string' | trick name\r\n        // @uparmopt \"string\" | trick name\r\n\t\tcase 0x4b2ee2bc: // SetTrickName\r\n\t\t{\r\n\t\t\tconst char *pName=NULL;\r\n\t\t\tpParams->GetString(NO_NAME,&pName);\r\n\t\t\t// Make it accept regular strings too, because trick names probably won't get translated.\r\n\t\t\tif (pName)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(strlen(pName)<MAX_TRICK_NAME_CHARS,(\"\\n%s\\nToo many chars in trick name, max=%d\",pScript->GetScriptInfo(),MAX_TRICK_NAME_CHARS));\r\n\t\t\t\tstrcpy(mpTrickName, pName);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmpTrickName[0]=0;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | SetTrickScore | sets trick score flag\r\n        // @uparm 1 | trick score\r\n\t\tcase 0xcb3a8fd2: // SetTrickScore\r\n\t\t\tpParams->GetInteger(NO_NAME,&mTrickScore);\t  \r\n\t\t\tbreak;\r\n                          \r\n        // @script | GetSpin | Gets the current spin value, and adds it as an integer parameter\r\n\t\t// called Spin. It will always be positive and a multiple of 180. It takes into account\r\n\t\t// the spin slop.\r\n\t\tcase 0x4ba7719f: // GetSpin\r\n\t\t{\r\n\t\t\tint spin = static_cast< int >(Mth::Abs(mTallyAngles) + GetPhysicsFloat(CRCD(0x50c5cc2f, \"spin_count_slop\")));\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0xedf5db70, \"Spin\"), (spin / 180) * 180.0f);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        // @script | ResetSpin | \r\n\t\tcase 0xe50d471e: // ResetSpin\r\n\t\t\tmTallyAngles = 0.0f;\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | Display | display trick\r\n        // @flag Deferred | If deferred (currently only used for the ollie)\r\n        // then store it away, because we may not want to add it to the\r\n        // combo after all. Eg, a 180 ollie on its own is counted,\r\n\t\t// but if you do a 180 kickflip, you'll get the kickflip but not \r\n        // the ollie as well. \r\n        // @flag BlockSpin |\r\n\t\t// @parmopt int | AddSpin | 0 | If this is specified and the current trick is the\r\n\t\t// same as the last trick, then the spin will be added to the last trick rather than\r\n\t\t// adding it as a new trick.\r\n\t\tcase 0xf32e8d5c: // Display\t\t\t\t  \r\n\t\t{\r\n\t\t\tif (mpTrickName)\r\n\t\t\t{\r\n\t\t\t\tMdl::Score *pScore=GetScoreObject();\r\n\t\t\t\tint spin=0;\r\n\t\t\t\t\r\n\t\t\t\tif (pParams->ContainsFlag(CRCD(0x5c9b1765,\"Deferred\")))\r\n\t\t\t\t{\r\n\t\t\t\t\tstrcpy(mpDeferredTrickName,mpTrickName);\r\n\t\t\t\t\tmDeferredTrickScore=mTrickScore;\r\n\t\t\t\t\tif (mp_skater_core_physics_component->IsSwitched())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmDeferredTrickFlags|=Mdl::Score::vSWITCH;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t// If an AddSpin value is specified and the current trick is the same as\r\n\t\t\t\t// the last one in the score, then instead of adding the trick again just\r\n\t\t\t\t// give the last one some more spin. Used by the truckstand2 spin.\r\n\t\t\t\t// (See the ManualLink script in groundtricks.q)\r\n\t\t\t\telse if (pParams->GetInteger(CRCD(0x83cb0082,\"AddSpin\"),&spin) && \r\n\t\t\t\t\t\t pScore->GetLastTrickId()==Script::GenerateCRC(mpTrickName))\r\n\t\t\t\t{\r\n\t\t\t\t\tmTallyAngles+=spin;\r\n\t\t\t\t\tif (GetSkater()->IsLocalClient())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpScore->UpdateSpin(mTallyAngles);\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tMdl::Score::Flags Flags=0;\r\n\t\t\t\t\tif (pParams->ContainsFlag(CRCD(0xc2150bb0,\"BlockSpin\")))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tFlags|=Mdl::Score::vBLOCKING;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (pParams->ContainsFlag(CRCD(0x3c24ac46,\"NoDegrade\")))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tFlags|=Mdl::Score::vNODEGRADE;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tif (mp_skater_core_physics_component->IsSwitched())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tFlags|=Mdl::Score::vSWITCH;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (mUseSpecialTrickText)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tFlags|=Mdl::Score::vSPECIAL;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( pParams->ContainsFlag( CRCD(0x61a1bc57,\"cat\") ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tFlags |= Mdl::Score::vCAT;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Need to also include nollie check later.\r\n\t\t\t\t\t\t\r\n\t\t\t\t\tif( GetSkater()->IsLocalClient())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// if on a rail, then might need to degrade the rail score\r\n\t\t\t\t\t\tif (mp_skater_core_physics_component->GetState()==RAIL && mTrickScore)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tprintf (\"RAIL score %d * %2.3f = %d\\n\", mTrickScore,pScore->GetRobotRailMult(),(int) (pScore->GetRobotRailMult()*mTrickScore));\r\n\t\t\t\t\t\t\tmTrickScore = (int) (mTrickScore * pScore->GetRobotRailMult());\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t// add a trick to the series\r\n\t\t\t\t\t\tpScore->Trigger(mpTrickName, mTrickScore, Flags);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif (mpTrickName[0])\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// tell any observers to do the chicken dance:\r\n\t\t\t\t\t\t\tGetObject()->BroadcastEvent(CRCD(0x11d8bc9e, \"SkaterTrickDisplayed\"));\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tif (mp_skater_core_physics_component->GetFlag(VERT_AIR) || mp_skater_core_physics_component->GetTrueLandedFromVert())\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// If vert, only count it if the spin is at least 360\r\n\t\t\t\t\t\t\t\tif (Mth::Abs(mTallyAngles)>=360.0f-GetPhysicsFloat(CRCD(0x50c5cc2f,\"spin_count_slop\")) + 0.1f)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tpScore->SetSpin(mTallyAngles);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tpScore->SetSpin(mTallyAngles);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// K: If the trick was a 'Null' trick, then do not add the spin.\r\n\t\t\t\t\t\t\t// This is to fix TT6057\r\n\t\t\t\t\t\t\t// A null trick is a trick whose name is set using SetTrickName \"\"\r\n\t\t\t\t\t\t\t// and is often used to do a BlockSpin without displaying a trick name.\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (pParams->ContainsFlag(CRCD(0xc2150bb0,\"BlockSpin\")))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmTallyAngles=0.0f;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t// Clear the deferred trick, so that you won't get a 180 kickflip and a 180 ollie.\r\n\t\t\t\t\t//dodgy_test(); printf(\"Clearing deferred trick\\n\");\r\n\t\t\t\t\tmpDeferredTrickName[0]=0;\r\n\t\t\t\t}\t\r\n            }\r\n\t\t\t\r\n\t\t\t// Only clear the mUseSpecialTrickText flag if it is not a 'null' trick, which is\r\n\t\t\t// a trick whose name is just '' used to insert spin blocks.\r\n\t\t\t// Want to preserve the mUseSpecialTrickText for the next proper trick.\r\n\t\t\tif (mpTrickName[0])\r\n\t\t\t{\r\n\t\t\t\tmUseSpecialTrickText=false;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n        // @script | ClearPanel_Landed | end of trick combo...scoring and such\r\n\t\tcase 0x11ca5c42: // ClearPanel_Landed\r\n\t\t{\r\n\t\t\tMdl::Score *pScore=GetScoreObject();\r\n\r\n\t\t\tif(GetSkater()->IsLocalClient())\r\n\t\t\t{\r\n\t\t\t\t// If there is a deferred trick stored up, then decide whether to add it\r\n\t\t\t\t// to the combo depending on how much spin there is.\r\n\t\t\t\tif (mpDeferredTrickName[0])\r\n\t\t\t\t{\r\n\t\t\t\t\t//dodgy_test(); printf(\"Got a deferred trick, mTallyAngles=%f\\n\",mTallyAngles);\r\n\t\t\t\t\t// Note: Using the new 'mp_skater_core_physics_component->m_true_landed_from_vert' rather than 'mp_skater_core_physics_component->mLandedFromVert', because\r\n\t\t\t\t\t// mp_skater_core_physics_component->mLandedFromVert can be cleared by a script command, and if landing from vert it\r\n\t\t\t\t\t// will be cleared at this point, due to some script logic for detecting reverts.\r\n\t\t\t\t\tif (mp_skater_core_physics_component->GetTrueLandedFromVert())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// If vert, only count it if the spin is at least 360\r\n\t\t\t\t\t\tif (Mth::Abs(mTallyAngles)>= 360.0f - GetPhysicsFloat(CRCD(0x50c5cc2f,\"spin_count_slop\")) + 0.1f)\t// (Mick) adkisted for slop\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// add the deferred trick to the series\r\n\t\t\t\t\t\t\tpScore->Trigger(mpDeferredTrickName, mDeferredTrickScore, mDeferredTrickFlags);\r\n\t\t\t\t\t\t\tpScore->SetSpin(mTallyAngles);\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Only count it if the spin is at least 180, cos just ollieing is easy.\r\n\t\t\t\t\t\tif (Mth::Abs(mTallyAngles)>=180.0f - GetPhysicsFloat(CRCD(0x50c5cc2f,\"spin_count_slop\")) + 0.1f)  // (Mick) adkisted for slop\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// add the deferred trick to the series\r\n\t\t\t\t\t\t\tpScore->Trigger(mpDeferredTrickName, mDeferredTrickScore, mDeferredTrickFlags);\r\n\t\t\t\t\t\t\tpScore->SetSpin(mTallyAngles);\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t// Clear the deferred trick.\r\n\t\t\t\t\tmpDeferredTrickName[0]=0;\r\n\t\t\t\t}\r\n\t\t\t\r\n                // check for special trick if we're in a special trick goal\r\n                Game::CGoalManager* pGoalManager = Game::GetGoalManager();\r\n                Dbg_MsgAssert( pGoalManager, ( \"Unable to get goal manager\\n\" ) );\r\n                pGoalManager->CheckTrickText();\r\n\t\t\t\t\r\n\t\t\t\tif (pScore->GetScorePotValue() != 0)\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct* p_params = new Script::CStruct;\r\n\t\t\t\t\tp_params->AddChecksum(CRCD(0x5b24faaa, \"SkaterId\"), GetObject()->GetID());\r\n\t\t\t\t\tGetObject()->BroadcastEvent(CRCD(0x4b3ce1fe, \"SkaterExitCombo\"), p_params);\r\n\t\t\t\t\tdelete p_params;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t///////////////////////////////////////////////////////////////////////\r\n\t\t\t\t// K: Warning! I moved AwardPendingGaps() to before Land(), so that AwardPendingGaps()\r\n\t\t\t\t// can query the score to see if the required trick was got in the case of the\r\n\t\t\t\t// gap being part of a created goal.\r\n\t\t\t\t// Possible alternative solution in case this causes problems: Modify the c-code of\r\n\t\t\t\t// StartGap so that it detects if the gap is part of a created goal, and if so sets the\r\n\t\t\t\t// tricktext according to the trick required by the goal. \r\n\t\t\t\tGetSkaterGapComponentFromObject(GetObject())->AwardPendingGaps();\r\n                \r\n\t\t\t\tpScore->Land();\r\n\t\t\t\tmTallyAngles=0.0f;\t\t// Mick: Cleared, so a manual will not get it\r\n\t\t\t\t///////////////////////////////////////////////////////////////////////\r\n\t\t\t\t\r\n\t\t\t\t\r\n                mp_stats_manager_component->Land();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// tell any observers to cheer if they want:\r\n\t\t\tGetObject()->BroadcastEvent( CRCD(0xc98ba111,\"skaterLanded\"));\r\n\r\n\t\t\t// allows us to end the run if we're in horse mode\r\n\t\t\tif ( m_first_trick_started )\r\n\t\t\t\tm_first_trick_completed = true;\r\n\r\n\t\t\tmNumTricksInCombo=0;\r\n\t\t\t\r\n\t\t\tmp_skater_balance_trick_component->UpdateRecord();\r\n\t\t\tmp_skater_balance_trick_component->Reset();\r\n\t\t\t\r\n\t\t\t// Clear the special friction index (used by Reverts)\r\n\t\t\tmp_skater_core_physics_component->ResetSpecialFrictionIndex();\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t  \t\t\r\n        // @script | ClearPanel_Bailed | trick combo ended in bail...\r\n\t\tcase 0xb8045433: // ClearPanel_Bailed\r\n\t\t{\r\n\t\t\tif( GetSkater()->IsLocalClient())\r\n\t\t\t{\r\n\t\t\t\tif (GetScoreObject()->GetScorePotValue() != 0)\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct* p_params = new Script::CStruct;\r\n\t\t\t\t\tp_params->AddChecksum(CRCD(0x5b24faaa, \"SkaterId\"), GetObject()->GetID());\r\n\t\t\t\t\tGetObject()->BroadcastEvent(CRCD(0x4b3ce1fe, \"SkaterExitCombo\"), p_params);\r\n\t\t\t\t\tdelete p_params;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tGetScoreObject()->Bail();\r\n\t\t\t}\r\n\r\n\t\t\t// tell any observers to balk if they want:\r\n\t\t\tGetObject()->BroadcastEvent( CRCD(0x6045a960,\"skaterBailed\"));\r\n\t\t   \r\n \r\n\t\t\tm_first_trick_started = true;\r\n\t\t\tm_first_trick_completed = true;\r\n\r\n\t\t\t// clear out the graffiti tricks\r\n\t\t\tSetGraffitiTrickStarted( false );\r\n\t\t\t\r\n\t\t\tmNumTricksInCombo=0;\r\n\t\t\t\r\n\t\t\tmp_skater_balance_trick_component->Reset();\r\n\t\t\t\r\n            mp_skater_core_physics_component->StopSkitch();\r\n\t\t\t\r\n\t\t\t// Mick: Cleared, so a manual will not get it\r\n\t\t\tmTallyAngles=0.0f;\r\n\t\t\t\r\n\t\t\t// Clear the special friction index (used by Reverts)\r\n\t\t\tmp_skater_core_physics_component->ResetSpecialFrictionIndex();\r\n\t\t\tm_pending_tricks.FlushTricks();\r\n\t\t\t\r\n\t\t\tGetSkaterGapComponentFromObject(GetObject())->ClearPendingGaps();\r\n\r\n            mp_stats_manager_component->Bail();\r\n\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\r\n        // @script | TrickOffObject | \r\n        // @uparm name | object name\r\n\t\tcase 0x36b2be57: // TrickOffObject\r\n\t\t{\r\n\t\t\tuint32 clusterName;\r\n\t\t\tpParams->GetChecksum( NO_NAME, &clusterName, Script::ASSERT );\r\n\t\t\tTrickOffObject( clusterName );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTrickComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CTrickComponent::GetDebugInfo\"));\r\n\t// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\tp_info->AddStructure(\"mpTrickMappings\",mpTrickMappings);\r\n \r\n\tScript::CArray *p_events_array=new Script::CArray;\r\n\tif (mNumEvents)\r\n\t{\r\n\t\tp_events_array->SetSizeAndType(mNumEvents,ESYMBOLTYPE_STRUCTURE);\r\n\t\t\r\n\t\tint index=mLastEvent;\r\n\t\tfor (int i=0; i<mNumEvents; ++i)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_event=new Script::CStruct;\r\n\t\t\t\r\n\t\t\tp_event->AddChecksum(CRCD(0xc5f953c2,\"Button\"),mpButtonEvents[index].ButtonNameChecksum);\r\n\t\t\t\r\n\t\t\tuint32 event_type=0;\r\n\t\t\tswitch (mpButtonEvents[index].EventType)\r\n\t\t\t{\r\n\t\t\t\tcase EVENT_NONE:  event_type=CRCD(0x806fff30,\"None\"); break;\r\n\t\t\t\tcase EVENT_BUTTON_PRESSED:  event_type=CRCD(0xe4ab4785,\"Pressed\"); break;\r\n\t\t\t\tcase EVENT_BUTTON_RELEASED:  event_type=CRCD(0x4ba9ee9,\"Released\"); break;\r\n\t\t\t\tdefault: break;\r\n\t\t\t}\r\n\t\t\tp_event->AddChecksum(NONAME,event_type);\r\n\r\n\t\t\tp_event->AddInteger(CRCD(0x906b67ba,\"Time\"),mpButtonEvents[index].Time);\r\n\t\t\tp_event->AddInteger(CRCD(0x86b89ce7,\"Used\"),mpButtonEvents[index].Used);\r\n\t\t\t\t\r\n\t\t\tp_events_array->SetStructure(i,p_event);\r\n\t\t\t\t\r\n\t\t\t--index;\r\n\t\t\tif (index<0)\r\n\t\t\t{\r\n\t\t\t\tindex+=MAX_EVENTS;\r\n\t\t\t}\r\n\t\t}\t\t\r\n\t}\r\n    p_info->AddArrayPointer(CRCD(0xac78a8b5,\"Events\"),p_events_array);\r\n\r\n\ts_add_array_of_names(p_info,mNumQueueTricksArrays,mpQueueTricksArrays,\"QueueTrickArrays\");\r\n\t\r\n\tp_info->AddInteger(CRCD(0x50cab1f1,\"GotManualTrick\"),mGotManualTrick);\r\n\ts_add_array_of_names(p_info,mNumManualTrickArrays,mpManualTrickArrays,\"ManualTrickArrays\");\r\n\tp_info->AddChecksum(CRCD(0x9c93be77,\"SpecialManualTricksArray\"),mSpecialManualTricksArrayChecksum);\r\n\t\r\n\tp_info->AddInteger(CRCD(0xdf2c1464,\"GotExtraGrindTrick\"),mGotExtraGrindTrick);\r\n\ts_add_array_of_names(p_info,mNumExtraGrindTrickArrays,mpExtraGrindTrickArrays,\"ExtraGrindTrickArrays\");\r\n\tp_info->AddChecksum(CRCD(0x4cb1bfe,\"SpecialExtraGrindTrickArray\"),mSpecialExtraGrindTrickArrayChecksum);\r\n\r\n\tp_info->AddInteger(CRCD(0x33660920,\"GotExtraTricks\"),mGotExtraTricks);\r\n\tp_info->AddInteger(CRCD(0x15d82e35,\"ExtraTricksInfiniteDuration\"),mExtraTricksInfiniteDuration);\r\n\tp_info->AddInteger(CRCD(0x4c85f690,\"ExtraTricksDuration\"),mExtraTricksDuration);\r\n\tp_info->AddInteger(CRCD(0x9737fa16,\"ExtraTricksStartTime\"),mExtraTricksStartTime);\r\n\ts_add_array_of_names(p_info,mNumExtraTrickArrays,mpExtraTrickArrays,\"ExtraTrickArrays\");\r\n\tp_info->AddChecksum(CRCD(0x42569716,\"SpecialExtraTricksArray\"),mSpecialExtraTricksArrayChecksum);\r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTrickComponent::Debounce ( int button, float time )\r\n{\r\n\tmButtonState[button] = false;\r\n\tmButtonDebounceTime[button] = time;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Increment the trick count, which may set pedestrian exceptions to\r\n// make them go \"oooOOOOOooooh\"\r\n\r\n// Note: This count won't be totally accurate, because if an 'extra' trick is triggered it\r\n// will increment the count too, making the count get incremented more times than it should.\r\n// But this shouldn't be a big problem, cos it'll just mean the croud will more likely to cheer if\r\n// you do lots of extra tricks.\r\n// NOTE: move to trick component\r\nvoid CTrickComponent::IncrementNumTricksInCombo()\r\n{\r\n\t++mNumTricksInCombo;\r\n\tif ( mNumTricksInCombo > 3 )\r\n\t{\r\n\t\t// tell any observers to start taking notice:\r\n\t\tGetObject()->BroadcastEvent(CRCD(0x94182a08,\"skaterStartingRun\"));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTrickComponent::SetGraffitiTrickStarted( bool started )\r\n{\r\n\tm_graffiti_trick_started = started;\r\n\tif ( !started )\r\n\t{\r\n\t\tm_pending_tricks.FlushTricks();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tTrickOffObject( mp_skater_core_physics_component->GetLastNodeChecksum() );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTrickComponent::TrickOffObject( uint32 node_name )\r\n{\r\n\tif ( GraffitiTrickStarted() )\r\n\t{\r\n\t\tm_pending_tricks.TrickOffObject( node_name );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTrickComponent::ClearMiscellaneous()\r\n{\r\n\tmNumTricksInCombo = 0;\r\n\tm_first_trick_completed = false;\r\n\tm_first_trick_started = false;\r\n\tSetGraffitiTrickStarted( false );\r\n\tm_pending_tricks.FlushTricks();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CTrickComponent::WritePendingTricks( uint32* p_buffer, uint32 max_size )\r\n{\r\n\tuint32 size = m_pending_tricks.WriteToBuffer( p_buffer, max_size );\r\n\r\n\t// resets the graffiti trick list\r\n\tSetGraffitiTrickStarted( false );\r\n\t\r\n\treturn size;\r\n}\r\n\r\n\r\n// Experimenting with a new way of binding script commands\r\n// Doing it like this is twice as fast (11us vs 22 us) which can add up for\r\n// things that are called every frame (like the skater physics scripts) \r\n// It's a bit cumbersome to do it like this though\r\n// Perhaps there could be a more general database of script commands\r\n// with registration info about which component it goes to.\r\n// and a pointer to the memeber function\r\n \r\n// @script | DoNextTrick | runs the next trick in the queue\r\n// @parmopt name | ScriptToRunFirst | | Script that will be run first before any trick script.\r\n// @parmopt structure | Params | | Parameters to pass to ScriptToRunFirst\r\nbool ScriptDoNextTrick( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tCCompositeObject *p_object = (CCompositeObject *) (pScript->mpObject.Convert());\r\n\tDbg_MsgAssert(p_object, (\"Can't run DoNextTrick with no object\"));\r\n\tCTrickComponent* p_trick = GetTrickComponentFromObject(p_object);\r\n\tDbg_MsgAssert(p_trick, (\"Can't run DoNextTrick with no object\"));\r\n\t\t\r\n\tuint32 scriptToRunFirst=0;\r\n\tScript::CStruct *pScriptToRunFirstParams=NULL;\r\n\tpParams->GetChecksum(CRCD(0x148fee96,\"ScriptToRunFirst\"),&scriptToRunFirst);\r\n\tpParams->GetStructure(CRCD(0x7031f10c,\"Params\"),&pScriptToRunFirstParams);\r\n\t\r\n\tScript::CStruct *pExtraTrickParams=NULL;\r\n\tpParams->GetStructure(CRCD(0x31261d2f, \"TrickParams\"),&pExtraTrickParams);\r\n\tif (pExtraTrickParams)\r\n\t{\r\n\t\tScript::CStruct *pCopyOfExtraTrickParams=pCopyOfExtraTrickParams = new Script::CStruct(*pExtraTrickParams);\r\n\t\tp_trick->TriggerNextQueuedTrick(scriptToRunFirst, pScriptToRunFirstParams, pCopyOfExtraTrickParams);\r\n\t\tdelete pCopyOfExtraTrickParams;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_trick->TriggerNextQueuedTrick(scriptToRunFirst, pScriptToRunFirstParams);\r\n\t}\r\n\treturn true;\r\n} \r\n \r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/trickcomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       TrickComponent.h\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ??/??/??\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_TRICKCOMPONENT_H__\r\n#define __COMPONENTS_TRICKCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/trickobject.h>\r\n\r\n#ifndef __OBJECT_BASECOMPONENT_H__\r\n#include <gel/object/basecomponent.h>\r\n#endif\r\n\r\n#ifndef __GEL_INPMAN_H\r\n#include <gel/inpman.h>\r\n#endif\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_TRICK CRCD(0x270f56e1,\"Trick\")\r\n#define\t\tGetTrickComponent() ((Obj::CTrickComponent*)GetComponent(CRC_TRICK))\r\n#define\t\tGetTrickComponentFromObject(pObj) ((Obj::CTrickComponent*)(pObj)->GetComponent(CRC_TRICK))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n    class CComponent;\r\n}\r\n              \r\nnamespace Mdl\r\n{\r\n\tclass Score;\r\n};\r\n\t\r\nnamespace Obj\r\n{\r\n\r\nclass CSkaterProfile;\r\nclass CSkaterBalanceTrickComponent;\r\nclass CSkaterFlipAndRotateComponent;\r\nclass CSkaterStateComponent;\r\nclass CSkaterRunTimerComponent;\r\n\r\n// An element of the trick queue.\r\nstruct STrick\r\n{\r\n\tuint32 ArrayChecksum;\t// Checksum of the script array, eg AirTricks\r\n\tuint Index;\t\t\t\t// Index within the array of the trick.\r\n\t\r\n\t// These next two are only used by manual tricks and special grind tricks.\r\n\t// These have a finite duration. For example, if a manual is queued up early on\r\n\t// in a jump, it may expire before the player lands.\r\n\tuint32 Time;\t\t\t// The time when the trick was triggered.\r\n\tuint32 Duration;\t\t// How long after Time that the trick will last for.\r\n\tbool UseSpecialTrickText; // Whether to use the yellow text when displaying the trick.\r\n};\r\n\r\nenum EEventType\r\n{\r\n\t// All the events in the buffer have this type initially.\r\n\tEVENT_NONE,\r\n\t\r\n\tEVENT_BUTTON_PRESSED,\r\n\tEVENT_BUTTON_RELEASED,\r\n\t\r\n\tEVENT_BUTTON_PRESSURE_CHANGE,\r\n\t\r\n\tEVENT_ON_RAIL,\r\n\tEVENT_OFF_RAIL,\r\n};\r\n\r\n#define MAX_EVENTS 100\r\nstruct SButtonEvent\r\n{\r\n\tuint32 Time;\r\n\tEEventType EventType;\r\n\tuint32 ButtonNameChecksum;\r\n\tint ButtonPressure;\r\n\tbool MaybeUsed;\r\n\tuint32 Used;\r\n};\r\n\r\n#define USED_BY_REGULAR_TRICK (1<<0)\r\n#define USED_BY_EXTRA_TRICK (1<<1)\r\n#define USED_BY_MANUAL_TRICK (1<<2)\r\n#define USED_BY_EXTRA_GRIND_TRICK (1<<3)\r\n\r\n#define USE_SPECIAL_TRICK_TEXT true\r\n\r\nclass CTrickComponent : public CBaseComponent\r\n{\r\n\t// Used to detect infinite recursion of RunTrick\r\n\tuint32 m_num_runtrick_recursions;\r\n\t\r\n\tMdl::Score *mp_score;\r\n\t\r\n\tCInputComponent* \t\t\t\tmp_input_component;\r\n\tCSkaterBalanceTrickComponent*\tmp_skater_balance_trick_component;\r\n\tCSkaterCorePhysicsComponent*\tmp_skater_core_physics_component;\r\n\tCSkaterFlipAndRotateComponent*\tmp_skater_flip_and_rotate_component;\r\n\tCSkaterStateComponent*\t\t\tmp_skater_state_component;\r\n    CStatsManagerComponent*\t\t\tmp_stats_manager_component;\r\n\t\r\n\tScript::CStruct*\t\t\t\tget_trigger_structure(Script::CStruct *p_struct);\r\n\tScript::CStruct*\t\t\t\tget_alternate_trigger_structure(Script::CStruct *p_struct);\r\n\t\r\npublic:\r\n\tCSkater*\t\t\t\t\t\tGetSkater (   ) { return static_cast< CSkater* >(GetObject()); }\r\n\t\r\n\tvoid UpdateTrickMappings( Obj::CSkaterProfile* pSkaterProfile );\r\n\r\n\tMdl::Score *GetScoreObject();\r\n\tvoid SetAssociatedScore(Mdl::Score *p_score) {mp_score=p_score;}\r\n\r\n\t// Gets called from the CTrickComponent constructor, and also from CSkater::ResetEverything()\r\n\tvoid Clear();\r\n\r\n\tvoid RecordButtons();\r\n\tvoid Debounce ( int button, float time );\r\n\r\n\t// The Button Event buffer.\r\n\tSButtonEvent mpButtonEvents[MAX_EVENTS];\r\n\t// How many events are in the buffer. When the skater is first created this will be zero,\r\n\t// but will increase until it equals MAX_EVENTS then will stay equal to MAX_EVENTS from then on.\r\n\tuint16 mNumEvents;\r\n\t// Index of the last event in the buffer.\r\n\tuint16 mLastEvent;\r\n\r\n\t// If a trick gets triggered, the buttons which triggered it will be stored here.\r\n\t// Eg, for a kickflip, button 0 will be Square (checksum of), and button 1 will be Left.\r\n\t// They are stored so that the extra-trick trigger can use one of the parent trick's buttons,\r\n\t// rather than being hard wired. This is needed in case the player re-maps the parent trick to\r\n\t// a different button combination.\r\n\t#define MAX_TRICK_BUTTONS 3\r\n\tuint32 mp_trick_button[MAX_TRICK_BUTTONS];\r\n\t// Reads the button names and time duration out of a 'Trigger' structure.\r\n\tuint32 get_buttons_and_duration(Script::CComponent *p_comp, int num_buttons, uint32 *p_button_names);\r\n\tvoid record_last_tricks_buttons(uint32 *p_button_names);\r\n\r\n\tfloat mButtonDebounceTime[PAD_NUMBUTTONS];\r\n\tbool mButtonState[PAD_NUMBUTTONS];\r\n\t\r\n\tbool GetButtonState(uint32 Checksum);\r\n\r\n\tint mNumButtonsToIgnore;\r\n\t#define MAX_BUTTONS_TO_IGNORE 2\r\n\tuint32 mpButtonsToIgnore[MAX_BUTTONS_TO_IGNORE];\r\n\tvoid ButtonRecord(uint Button, bool Pressed);\r\n\t\r\n\tbool TriggeredInLastNMilliseconds(uint32 ButtonNameChecksum, uint32 Duration, uint32 IgnoreMask=0xffffffff);\r\n\tbool BothTriggeredNothingInBetween(uint32 Button1, uint32 Button2, uint32 Duration, uint32 IgnoreMask);\r\n\tbool QueryEvents(Script::CStruct *pQuery, uint32 UsedMask=USED_BY_REGULAR_TRICK, uint32 IgnoreMask=0xffffffff);\r\n\tvoid ResetMaybeUsedFlags();\r\n\tvoid ConvertMaybeUsedToUsed(uint32 UsedMask);\r\n\tvoid RemoveOldButtonEvents(uint32 Button, uint32 OlderThan);\r\n\tSButtonEvent *AddEvent(EEventType EventType);\r\n\tvoid ClearEventBuffer();\r\n\tvoid DumpEventBuffer();\r\n\t\r\n\t// If set, then the next call to Display will use the yellow text.\r\n\tbool mUseSpecialTrickText;\r\n\r\n\t// This maps trick slots to trick names. Each pro has their own set of default\r\n\t// mappings, stored in the profile.\r\n\t// The default mappings are defined in script, eg the structure HawkTricks.\r\n\tScript::CStruct *mpTrickMappings;\r\n\r\n\t//////////////////////////////////////////////////////////\r\n\t// \t\t\t\t\tTrick queue stuff\r\n\t//////////////////////////////////////////////////////////\r\n\t\r\n\tint mFrontTrick;\t// The trick that is at the front of the queue, ie, next to be executed.\r\n\tint mBackTrick;\t\t// The trick at the back of the queue, ie the last to be added.\r\n\t// mFrontTrick and mBackTrick are both -1 to indicate no tricks in queue.\r\n\t#define TRICK_QUEUE_SIZE 100\r\n\tSTrick mpTricks[TRICK_QUEUE_SIZE];\r\n\t// Called by the ClearTrickQueue script command.\r\n\tvoid ClearTrickQueue();\r\n\t\r\n\tvoid AddTrick(uint32 ArrayChecksum, uint Index, bool UseSpecialTrickText=false);\r\n\tvoid RemoveFrontTrick();\r\n\tvoid ClearTricksFrom(uint32 ArrayChecksum);\r\n\r\n\tbool TrickIsDefined(Script::CStruct *pTrick);\r\n\tbool RunTrick(Script::CStruct *pTrick, uint32 optionalFlag=0, Script::CStruct *pExtraParams=NULL);\r\n\r\n\t// Called by the DoNextTrick script command.\r\n\tvoid TriggerNextQueuedTrick(uint32 scriptToRunFirst=0, Script::CStruct *p_scriptToRunFirstParams=NULL, Script::CStruct* pExtraParams=NULL);\r\n\t\r\n\tint mNumQueueTricksArrays;\r\n\t// Storing array checksums rather than pointers to the arrays, in case they get reloaded.\r\n\t#define MAX_QUEUE_TRICK_ARRAYS 10\r\n\tuint32 mpQueueTricksArrays[MAX_QUEUE_TRICK_ARRAYS];\r\n\tvoid ClearQueueTricksArrays();\r\n\t\r\n\t// Checksum of any special tricks array specified by the last SetQueueTricks script command.\r\n\tuint32 mSpecialTricksArrayChecksum;\r\n\t\r\n\t// This can be set by the SetQueueTricks command, and allows events that have already been\r\n\t// used by certain tricks, eg extra grinds, to be not ignored.\r\n\tuint32 mDoNotIgnoreMask;\r\n\t\r\n\tvoid MaybeAddTrick(uint32 ArrayChecksum, bool UseSpecialTrickText=false, uint32 DoNotIgnoreMask=0);\r\n\t\r\n\t// Always called every frame.\r\n\tvoid AddTricksToQueue();\r\n\r\n\t//////////////////////////////////////////////////////////\r\n\t// \t\t\t\t\tManual stuff\r\n\t//////////////////////////////////////////////////////////\r\n\t\r\n\tint mNumManualTrickArrays;\r\n\t// Storing array checksums rather than pointers to the arrays, in case they get reloaded.\r\n\t#define MAX_MANUAL_TRICK_ARRAYS 10\r\n\tuint32 mpManualTrickArrays[MAX_MANUAL_TRICK_ARRAYS];\r\n\t\r\n\t// Checksum of any special manual tricks specified by the SetManualTricks script command.\r\n\tuint32 mSpecialManualTricksArrayChecksum;\r\n\t\r\n\tbool mGotManualTrick;\r\n\t// A special one entry 'queue' for manual tricks.\r\n\tSTrick mManualTrick;\r\n\t// Called by the DoNextManualTrick script command.\r\n\tvoid TriggerAnyManualTrick(Script::CStruct *pExtraParams=NULL);\r\n\t\r\n\t// Checks a single array to see if any trick needs to be put in the manual queue.\r\n\t// Called from MaybeQueueManualTrick()\r\n\tvoid CheckManualTrickArray(uint32 ArrayChecksum, uint32 IgnoreMask=0xffffffff, bool UseSpecialTrickText=false);\r\n\t\r\n\t// These two functions are always called every frame.\r\n\tvoid MaybeQueueManualTrick();\r\n\tvoid MaybeExpireManualTrick();\r\n\t// Called by the ClearManualTrick script command.\r\n\tvoid ClearManualTrick();\r\n\r\n\t//////////////////////////////////////////////////////////\r\n\t// \t\t\t\t\tExtra-grind stuff\r\n\t//////////////////////////////////////////////////////////\r\n\t\r\n\tint mNumExtraGrindTrickArrays;\r\n\t// Storing array checksums rather than pointers to the arrays, in case they get reloaded.\r\n\t#define MAX_EXTRA_GRIND_TRICK_ARRAYS 10\r\n\tuint32 mpExtraGrindTrickArrays[MAX_EXTRA_GRIND_TRICK_ARRAYS];\r\n\t\r\n\tuint32 mSpecialExtraGrindTrickArrayChecksum;\r\n\t\r\n\tbool mGotExtraGrindTrick;\r\n\t// A special one entry 'queue' for extra grind tricks.\r\n\tSTrick mExtraGrindTrick;\r\n\t\r\n\t// Called from CSkater::MaybeStickToRail()\r\n\tbool TriggerAnyExtraGrindTrick(bool Right, bool Parallel, bool Backwards, bool Regular);\r\n\t\r\n\t// For checking an single array. Called from MaybeQueueExtraGrindTrick()\r\n\tvoid MaybeQueueExtraGrindTrick(uint32 ArrayChecksum, bool UseSpecialTrickText=false);\r\n\t\r\n\t// These two functions are always called every frame.\r\n\tvoid MaybeQueueExtraGrindTrick();\r\n\tvoid MaybeExpireExtraGrindTrick();\r\n\t// Called by the ClearExtraGrindTrick script command.\r\n\tvoid ClearExtraGrindTrick();\r\n\t\r\n\t////////////////////////////////////////////////////////////////\r\n\t//\r\n\t// 'Extra' trick stuff.\r\n\t//\r\n\t////////////////////////////////////////////////////////////////\r\n\t\r\n\t// Whether we've got extra tricks to check for.\r\n\tbool mGotExtraTricks;\r\n\t// Whether to check for extra tricks forever.\r\n\tbool mExtraTricksInfiniteDuration;\r\n\t// If not infinite duration, this is how long after the start time to check for extra tricks for.\r\n\tuint32 mExtraTricksDuration;\r\n\t// The start time.\r\n\tuint32 mExtraTricksStartTime;\r\n\t\r\n\t// How many array checksums are in the array.\r\n\tint mNumExtraTrickArrays;\r\n\t#define MAX_EXTRA_TRICK_ARRAYS 10\r\n\tuint32 mpExtraTrickArrays[MAX_EXTRA_TRICK_ARRAYS];\r\n\t// Bitfields indicating which tricks in each array are excluded. (Hence each array can't have more than 32 tricks in it)\r\n\t// Used when an extra trick can branch to another trick in the same array, but we\r\n\t// don't want the same trick again, eg rail balance to another rail balance.\r\n\tuint32 mpExcludedExtraTricks[MAX_EXTRA_TRICK_ARRAYS];\r\n\r\n\t// Array checksum & exclusion bitfield for the special extra tricks, which are only checked for when special.\r\n\tuint32 mSpecialExtraTricksArrayChecksum;\r\n\tuint32 mExcludedSpecialExtraTricks;\r\n\t\r\n\tbool TriggerAnyExtraTrick(uint32 ArrayChecksum, uint32 ExcludedTricks);\r\n\tvoid TriggerAnyExtraTricks();\r\n\tvoid SetExtraTricks(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tvoid KillExtraTricks();\r\n\tuint32 CalculateIgnoreMask(uint32 ArrayChecksum, const char *pIgnoreName);\r\n\tvoid ExcludeExtraTricks(const char *pIgnoreName);\r\n\tbool IsExcluded(Script::CStruct *pTrick, const char *pIgnoreName);\r\n\r\n\tbool mBashingEnabled;\r\n\t\r\n\tvoid HandleBashing();\r\n\tfloat GetBashFactor();\r\n\r\n\t// Name of the current trick, which gets displayed when the trick is triggered.\r\n\tchar mpTrickName[MAX_TRICK_NAME_CHARS+1];\r\n\tint mTrickScore;\r\n\r\n\t// Name of the deferred trick, which gets displayed only if a 'display blockspin' or ClearPanel_Landed is done.\r\n\tchar mpDeferredTrickName[MAX_TRICK_NAME_CHARS+1];\r\n\tint mDeferredTrickScore;\r\n\tMdl::Score::Flags mDeferredTrickFlags;\r\n\r\n\tfloat mTallyAngles;\r\n\t\r\n\t// for knowing when to stop horse mode\r\n\tbool m_first_trick_started;\r\n\tbool m_first_trick_completed;\r\n\t\r\n\tint mNumTricksInCombo;\r\n\tvoid IncrementNumTricksInCombo();\r\n    void ClearMiscellaneous();\r\n\t\r\n\tvoid SetGraffitiTrickStarted( bool started );\r\n\tbool GraffitiTrickStarted() { return m_graffiti_trick_started; }\r\n\t\r\n\t// for knowing when to accumulate graffiti objects\r\n\tbool m_graffiti_trick_started;\r\n\t\r\n\tvoid TrickOffObject( uint32 node_name );\r\n\t\t\r\n\tvoid SetFirstTrickStarted( bool started ) { m_first_trick_started = started; }\r\n\tbool FirstTrickStarted() { return m_first_trick_started; }\r\n\tbool FirstTrickCompleted() { return m_first_trick_completed; }\r\n\t\r\n\tuint32 WritePendingTricks( uint32* p_buffer, uint32 max_size );\r\n\t\r\n\tObj::CPendingTricks m_pending_tricks;\r\n\r\n    CTrickComponent();\r\n    virtual ~CTrickComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tFinalize();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n};\r\n\r\ninline Mdl::Score* CTrickComponent::GetScoreObject()\r\n{\r\n\tDbg_MsgAssert(mp_score,(\"NULL pScore\"));\r\n\treturn mp_score;\r\n}\t\r\n\r\nbool ScriptDoNextTrick( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/vehiclecameracomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       VehicleCameraComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  2/10/3\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n\t\t\t\t\t\t\t\t\t \r\n#include <gel/components/vehiclecameracomponent.h>\r\n#include <gel/components/vehiclecomponent.h>\r\n#include <gel/components/cameracomponent.h>\r\n#include <gel/components/cameralookaroundcomponent.h>\r\n#include <gel/components/camerautil.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#define MESSAGE(a) { printf(\"M:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPI(a) { printf(\"D:%s:%i: \" #a \" = %i\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPB(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, a ? \"true\" : \"false\"); }\r\n#define DUMPF(a) { printf(\"D:%s:%i: \" #a \" = %g\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPE(a) { printf(\"D:%s:%i: \" #a \" = %e\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPS(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPP(a) { printf(\"D:%s:%i: \" #a \" = %p\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPV(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z]); }\r\n#define DUMP4(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z], (a)[W]); }\r\n#define DUMPM(a) { DUMP4(a[X]); DUMP4(a[Y]); DUMP4(a[Z]); DUMP4(a[W]); }\r\n#define MARK { printf(\"K:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, __PRETTY_FUNCTION__); }\r\n#define PERIODIC(n) for (static int p__ = 0; (p__ = ++p__ % (n)) == 0; )\r\n\r\n#define vVELOCITY_WEIGHT_DROP_THRESHOLD\t\t\t\tMPH_TO_IPS(15.0f)\r\n#define vLOCK_ATTRACTOR_VELOCITY_THRESHOLD\t\t\tMPH_TO_IPS(5000000.0f)\r\n#define vSTATE_CHANGE_DELAY (1.0f)\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CVehicleCameraComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CVehicleCameraComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCVehicleCameraComponent::CVehicleCameraComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_VEHICLECAMERA );\r\n\t\r\n\tm_offset_height = FEET(5.0f);\r\n\tm_offset_distance = FEET(12.0f);\r\n\t\r\n\tm_alignment_rate = 3.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCVehicleCameraComponent::~CVehicleCameraComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleCameraComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tuint32 subject_id;\r\n\t\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x431c185, \"subject\")))\r\n\t{\r\n\t\tpParams->GetChecksum(CRCD(0x431c185, \"subject\"), &subject_id, Script::ASSERT);\r\n\t\tmp_subject = static_cast< CCompositeObject* >(CCompositeObjectManager::Instance()->GetObjectByID(subject_id));\r\n\t\tDbg_MsgAssert(mp_subject, (\"Vehicle camera given subject which is not a composite object\"));\r\n\t\tmp_subject_vehicle_component = static_cast< CVehicleComponent* >(mp_subject->GetComponent(CRC_VEHICLE));\r\n\t\tDbg_MsgAssert(mp_subject_vehicle_component, (\"Vehicle camera given subject which contains no vehicle component\"));\r\n\t}\r\n\t\t\r\n\tpParams->GetFloat(CRCD(0x9213625f, \"alignment_rate\"), &m_alignment_rate);\r\n\t\r\n\tpParams->GetFloat(CRCD(0x14849b6d, \"offset_height\"), &m_offset_height);\r\n\t\r\n\tpParams->GetFloat(CRCD(0xbd3d3ca9, \"offset_distance\"), &m_offset_distance);\r\n\t\r\n\tpParams->GetFloat(CRCD(0xff7ebaf6, \"angle\"), &m_angle);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleCameraComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleCameraComponent::Finalize (   )\r\n{\r\n\tmp_camera_lookaround_component = GetCameraLookAroundComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_camera_lookaround_component);\r\n\t\r\n\treset_camera();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleCameraComponent::Update()\r\n{\r\n\t// NOTE: plenty of room for optimiziation\r\n\t\r\n\tGetCameraComponentFromObject(GetObject())->StoreOldPosition();\r\n\t\r\n\tcalculate_attractor_direction();\r\n\t\r\n\t// Due to rounding errors this can sometimes be > |1|, which hoses acosf(), so limit here.\r\n\tfloat angular_distance = acosf(Mth::Clamp(Mth::DotProduct(m_direction, m_attractor_direction), -1.0f, 1.0f));\r\n\tif (angular_distance > Mth::PI / 2.0f)\r\n\t{\r\n\t\tangular_distance = Mth::PI - angular_distance;\r\n\t}\r\n\t\r\n\tbool sign = Mth::CrossProduct(m_direction, m_attractor_direction)[Y] > 0.0f;\r\n\t\r\n\tfloat step = m_alignment_rate * angular_distance * Tmr::FrameLength();\r\n\t\r\n\tif (step > angular_distance)\r\n\t{\r\n\t\tstep = angular_distance;\r\n\t}\r\n\t\r\n\tm_direction.RotateY((sign ? 1.0f : -1.0f) * step);\r\n\tm_direction.Normalize();\r\n\t\r\n\tcalculate_dependent_variables();\r\n\t\r\n\tApplyCameraCollisionDetection(\r\n\t\tm_pos, \r\n\t\tm_orientation_matrix, \r\n\t\tm_pos - m_offset_distance * m_orientation_matrix[Z], \r\n\t\tm_pos - m_offset_distance * m_orientation_matrix[Z], \r\n\t\tfalse, \r\n\t\tfalse\r\n\t);\r\n\t\r\n\tapply_state();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CVehicleCameraComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tcase CRCC(0x469fd, \"VehicleCamera_Reset\"):\r\n\t\t\tRefreshFromStructure(pParams);\r\n\t\t\tFinalize();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleCameraComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to C......Component::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddChecksum(\"mp_subject\", mp_subject->GetID());\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleCameraComponent::reset_camera (   )\r\n{\r\n\tmp_camera_lookaround_component->mLookaroundHeading = 0.0f;\r\n\tmp_camera_lookaround_component->mLookaroundTilt = 0.0f;\r\n\tmp_camera_lookaround_component->mLookaroundLock = false;\r\n\t\r\n\tm_attractor_direction = -mp_subject->GetMatrix()[Z];\r\n\tm_attractor_direction[Y] = 0.0f;\r\n\tm_attractor_direction.Normalize();\r\n\t\r\n\tcalculate_attractor_direction();\r\n\t\r\n\tm_direction = m_attractor_direction;\r\n\t\r\n\tcalculate_dependent_variables();\r\n\t\r\n\tapply_state();\r\n\t\r\n\tGetCameraComponentFromObject(GetObject())->Update();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleCameraComponent::calculate_attractor_direction (   )\r\n{\r\n\tMth::Vector vel_direction = -mp_subject_vehicle_component->GetVel();\r\n\tvel_direction[Y] = 0.0f;\r\n\tfloat vel = vel_direction.Length();\r\n\tvel_direction.Normalize();\r\n\t\r\n\tif (mp_subject_vehicle_component->GetNumWheelsInContact() < 2)\r\n\t{\r\n\t\t// if vel under certain threshold, we lock the attractor\r\n\t\tif (vel < vLOCK_ATTRACTOR_VELOCITY_THRESHOLD)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\tm_attractor_direction = vel_direction;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfloat vel_weight = Mth::ClampMax(vel / vVELOCITY_WEIGHT_DROP_THRESHOLD, 1.0f) * Mth::DotProduct(vel_direction, -mp_subject->GetMatrix()[Z]);\r\n\t\t\r\n\t\tm_attractor_direction = -mp_subject->GetMatrix()[Z];\r\n\t\tm_attractor_direction[Y] = 0.0f;\r\n\t\tm_attractor_direction.Normalize();\r\n\t\t\r\n\t\tif (vel_weight > 0.0f)\r\n\t\t{\r\n\t\t\tm_attractor_direction += vel_weight * vel_direction;\r\n\t\t\tm_attractor_direction.Normalize();\r\n\t\t}\r\n\t\t\r\n\t\t// NOTE: potential bug if car is pointing straight down\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleCameraComponent::calculate_dependent_variables (   )\r\n{\r\n\tMth::Vector frame_direction = m_direction;\r\n\tframe_direction.RotateY(mp_camera_lookaround_component->mLookaroundHeading);\r\n\t\r\n\tm_orientation_matrix[X].Set(frame_direction[Z], 0.0f, -frame_direction[X]);\r\n\tm_orientation_matrix[Y].Set(0.0f, 1.0f, 0.0f);\r\n\tm_orientation_matrix[Z] = frame_direction;\r\n\tm_orientation_matrix[W].Set();\r\n\t\r\n\tm_pos = mp_subject->GetPos() + Mth::Vector(m_offset_distance * frame_direction[X], m_offset_height, m_offset_distance * frame_direction[Z]);\r\n\t\r\n\tm_orientation_matrix.RotateZLocal(DEGREES_TO_RADIANS(m_angle));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleCameraComponent::apply_state (   )\r\n{\r\n\tm_pos[W] = 1.0f;\r\n\tm_orientation_matrix[X][W] = 0.0f;\r\n\tm_orientation_matrix[Y][W] = 0.0f;\r\n\tm_orientation_matrix[Z][W] = 0.0f;\r\n\t\r\n\tGetObject()->SetPos(m_pos);\r\n\tGetObject()->SetMatrix(m_orientation_matrix);\r\n\tGetObject()->SetDisplayMatrix(m_orientation_matrix);\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/vehiclecameracomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       VehicleCameraComponent.h\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ??/??/??\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_VEHICLECAMERACOMPONENT_H__\r\n#define __COMPONENTS_VEHICLECAMERACOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/components/vehiclecomponent.h>\r\n\r\n// Just thinking about it - a generic way of accessing the component\t\t\t\t \r\n#define\t\tCRC_VEHICLECAMERA CRCD(0x2c747d8a, \"VehicleCamera\")\r\n#define\t\tGetVehicleCameraComponent() ((Obj::CVehicleCameraComponent*)GetComponent(CRC_VEHICLECAMERA))\r\n#define\t\tGetVehicleCameraComponentFromObject(pObj) ((Obj::CVehicleCameraComponent*)(pObj)->GetComponent(CRC_VEHICLECAMERA))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CCameraLookAroundComponent;\r\n\r\nclass CVehicleCameraComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CVehicleCameraComponent();\r\n    virtual ~CVehicleCameraComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tFinalize (   );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\treset_camera (   );\r\n\tvoid\t\t\t\t\t\t\tcalculate_attractor_direction (   );\r\n\tvoid\t\t\t\t\t\t\tcalculate_dependent_variables (   );\r\n\tvoid\t\t\t\t\t\t\tapply_state (   );\r\n\r\nprivate:\r\n\tCCompositeObject*\t\t\t\tmp_subject;\r\n\tCVehicleComponent*\t\t\t\tmp_subject_vehicle_component;\r\n\t\r\n\tMth::Vector\t\t   \t\t\t\tm_direction;\r\n\tMth::Vector\t\t   \t\t\t\tm_attractor_direction;\r\n\t\r\n\tMth::Vector\t\t\t\t\t\tm_pos;\r\n\tMth::Matrix\t\t\t\t\t\tm_orientation_matrix;\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_offset_height;\r\n\tfloat\t\t\t\t\t\t\tm_offset_distance;\r\n\tfloat\t\t\t\t\t\t\tm_angle;\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_alignment_rate;\r\n\t\r\n\tCCameraLookAroundComponent*\t\tmp_camera_lookaround_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/vehiclecomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       VehicleComponent.cpp\r\n//* OWNER:          Dan Nelson\r\n//* CREATION DATE:  1/31/3\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n\r\n#include <sys/config/config.h>\r\n\r\n#include <gel/components/vehiclecomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/soundcomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/collision/collcache.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/nxhierarchy.h>\r\n#include <gfx/skeleton.h>\r\n#include <gfx/nxviewman.h>\r\n#include <gfx/nxmiscfx.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/objects/restart.h>\r\n#include <sk/parkeditor2/parked.h>\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#include <core/math/slerp.h>\r\n\r\n#define MESSAGE(a) { printf(\"M:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPI(a) { printf(\"D:%s:%i: \" #a \" = %i\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPF(a) { printf(\"D:%s:%i: \" #a \" = %g\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPE(a) { printf(\"D:%s:%i: \" #a \" = %e\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPS(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPP(a) { printf(\"D:%s:%i: \" #a \" = %p\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPV(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z]); }\r\n#define DUMP4(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z], (a)[W]); }\r\n#define DUMPM(a) { DUMP4(a[X]); DUMP4(a[Y]); DUMP4(a[Z]); DUMP4(a[W]); }\r\n#define MARK { printf(\"K:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, __PRETTY_FUNCTION__); }\r\n#define PERIODIC(n) for (static int p__ = 0; (p__ = ++p__ % (n)) == 0; )\r\n\r\n// THOUGHTS:\r\n//\r\n// - BUG: solve negative collision depth issue for rect collisions; must project collision normal into rect plane before calculating depth (i think)\r\n// - BUG: bad wipeout behavior; IDEAS:\r\n//   - use only line feelers\r\n//   - turn off graivty with > 2 contacts\r\n//   - sleep like a rigidbody\r\n//   - compare algorithm with rigidbody\r\n// - Triggers.\r\n// - Lock motion if very slow and there's no input.\r\n// - Vehicle camera needs to reports its old position to get sounds' pitch correctly.\r\n//\r\n// - two center of masses (collision at zero and suspension) is an issue; actual rotation is done around zero; what sort of poor behavior does this cause\r\n//   when the car is on two wheels? what way is there to retain stable suspension behavior but use a common center of mass?\tperhaps simply damp rotational\r\n//   impulses due to the suspension; this may help with the \"vert, linear-to-angular energy\" freak-out issue as well\r\n// - body-body collisions; treat as boxes\r\n// - prehaps reduce wheel friction when very near vertical to prevent wall riding\r\n// - states: ASLEEP, AWAKE (full brake; rigidbody), DRIVEN, DRONE (?)\r\n// - vertical side rectangle feelers\r\n// - wheel camber <sp> extracted from model\r\n// - side slippage when stopped on hills\r\n\r\nnamespace Obj\r\n{\r\n\t\r\nCVehicleComponent::SCollisionPoint CVehicleComponent::sp_collision_points[4 * (Nx::MAX_NUM_2D_COLLISIONS_REPORTED + 1)];\r\n\t\t\t\t\t\t\t\t   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CVehicleComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CVehicleComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCVehicleComponent::CVehicleComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_VEHICLE );\r\n\t\r\n\tmp_input_component = NULL;\r\n\t\r\n\tm_draw_debug_lines = 0;\r\n\t\r\n\tm_update_suspension_only = false;\r\n\t\r\n\tm_steering_display = 0.0f;\r\n\t\r\n\tm_skater_pos.Set();\r\n\t\r\n\tmp_wheels = NULL;\r\n\t\r\n\tm_sound_setup_checksum = CRCD(0x1ca1ff20, \"Default\");\r\n\t\r\n\tm_num_collision_points = 0;\r\n\t\r\n\tm_artificial_collision_timer = 0.0f;\r\n\t\r\n\tm_state = AWAKE;\r\n\t\r\n\tm_consider_sleeping_count = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCVehicleComponent::~CVehicleComponent()\r\n{\r\n\tdelete [] mp_wheels;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// extract constant parameters from struct; parameters not included in the script are left unchanged\r\n\t\r\n\t// toggles through the debug line drawing states\r\n\tif (pParams->ContainsFlag(CRCD(0x935ab858, \"debug\")))\r\n\t{\r\n\t\tm_draw_debug_lines = ++m_draw_debug_lines % 3;\r\n\t}\r\n\telse if (pParams->ContainsFlag(CRCD(0xe6b5fcd9, \"full_debug\")))\r\n\t{\r\n\t\tm_draw_debug_lines = (m_draw_debug_lines + 2) % 3;\r\n\t}\r\n\telse if (pParams->ContainsFlag(CRCD(0x751da48b, \"no_debug\")))\r\n\t{\r\n\t\tm_draw_debug_lines = 0;\r\n\t}\r\n\t\r\n\t// center of mass location (in)\r\n\t// the point around which the car rotates; a lower center of mass reduces roll tendency; the XZ location affects the\r\n\t// vehicle's behavior during jumps\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x93346b8c, \"suspension_center_of_mass\")))\r\n\t{\r\n\t\tfloat suspension_center_of_mass_offset;\r\n\t\tpParams->GetFloat(CRCD(0x93346b8c, \"suspension_center_of_mass\"), &suspension_center_of_mass_offset);\r\n\t\tm_suspension_center_of_mass.Set(0.0f, suspension_center_of_mass_offset, 0.0f);\r\n\t}\r\n\t\r\n\t// mass (lbs)\r\n\t// affects acceleration, suspension behavior, and resistance to drag\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x93fca499, \"mass\")))\r\n\t{\r\n\t\tpParams->GetFloat(CRCD(0x93fca499, \"mass\"), &m_inv_mass);\r\n\t\tm_inv_mass = vVP_GRAVITATIONAL_ACCELERATION / m_inv_mass;\r\n\t}\r\n\r\n\t// moment of inertia (in^2 lbs)\r\n\t// resistance to changes in rotation along the three axes; natural value is about the weight of the car times the\r\n\t// square of the average radius of the car along the axes in question\r\n\t// X: resistance to rolling\r\n\t// Y: resistance to turning\r\n\t// Z: resistance to pitcing during acceleration, braking, and jumps\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x8c6473ec, \"moment_of_inertia\")))\r\n\t{\r\n\t\tpParams->GetVector(CRCD(0x8c6473ec, \"moment_of_inertia\"), &m_inv_moment_body);\r\n\t\tm_inv_moment_body[X] = vVP_GRAVITATIONAL_ACCELERATION / m_inv_moment_body[X];\r\n\t\tm_inv_moment_body[Y] = vVP_GRAVITATIONAL_ACCELERATION / m_inv_moment_body[Y];\r\n\t\tm_inv_moment_body[Z] = vVP_GRAVITATIONAL_ACCELERATION / m_inv_moment_body[Z];\r\n\t}\r\n\t\r\n\t// vehicle body's coefficient of restitution\r\n\tpParams->GetFloat(CRCD(0x79c3b862, \"body_restitution\"), &m_body_restitution);\r\n\t\r\n\t// vehicle body's coefficient of friction\r\n\tpParams->GetFloat(CRCD(0xf476273c, \"body_friction\"), &m_body_friction);\r\n\t\r\n\t// vehicle body's coefficient of friction\r\n\tpParams->GetFloat(CRCD(0x4a23a53c, \"body_wipeout_friction\"), &m_body_wipeout_friction);\r\n\t\r\n\t// vehicle body's penalty-method interpenetration-prevention spring constant\r\n\tpParams->GetFloat(CRCD(0x1dd4890, \"body_spring\"), &m_body_spring);\r\n\t\r\n\t// factor of normal impulse over which you can control via steering\r\n\tpParams->GetFloat(CRCD(0xb9f026ed, \"collision_control\"), &m_collision_control);\r\n\t\r\n\t// horizontal velocity cutoff below which no in-air slerping to face velocity occurs\r\n\tpParams->GetFloat(CRCD(0x8c14709e, \"in_air_slerp_velocity_cutoff\"), &m_in_air_slerp_vel_cutoff);\r\n\t\r\n\t// time over which in-air slerping lerps to full strength after takeoff\r\n\tpParams->GetFloat(CRCD(0x2c91e49b, \"in_air_slerp_time_delay\"), &m_in_air_slerp_time_delay);\r\n\t\r\n\t// in-air slerping strength\r\n\tpParams->GetFloat(CRCD(0x280f0e0b, \"in_air_slerp_strength\"), &m_in_air_slerp_strength);\r\n\t\r\n\t// special slerping below standard velocity threshold\r\n\tm_vert_correction = pParams->ContainsFlag(CRCD(0x5341806a, \"vert_correction\"));\r\n\t\r\n\t// maximum steering angle (degrees)\r\n\tif (pParams->ContainsComponentNamed(CRCD(0xc1e5abdd, \"max_steering_angle\")))\r\n\t{\r\n        pParams->GetFloat(CRCD(0xc1e5abdd, \"max_steering_angle\"), &m_max_steering_angle);\r\n\t\tm_max_steering_angle = DEGREES_TO_RADIANS(m_max_steering_angle);\r\n\t}\r\n\t\r\n\t// rotational damping parameters which prevent fishtailing and drift\r\n\tpParams->GetFloat(CRCD(0x386837db, \"constant_rotational_damping\"), &m_const_rotvel_damping);\r\n\tpParams->GetFloat(CRCD(0x469cf79a, \"quadratic_rotational_damping\"), &m_quad_rotvel_damping);\r\n\t\r\n\t// if the car can be exited via triangle\r\n\tm_exitable = pParams->ContainsFlag(CRCD(0xc2a136cc, \"exitable\"));\r\n\t\r\n\t// if the car has a handbrke\r\n\tm_no_handbrake = pParams->ContainsFlag(CRCD(0xad6c0a46, \"no_handbrake\"));\r\n\t\r\n\t// the vehicle's body's interaction with the environment is expressed as an array of rectangular colliders\r\n\tif (pParams->ContainsComponentNamed(CRCD(0xfc8c4ac6, \"colliders\")))\r\n\t{\r\n\t\tScript::CArray* p_colliders_array;\r\n\t\tpParams->GetArray(CRCD(0xfc8c4ac6, \"colliders\"), &p_colliders_array, Script::ASSERT);\r\n\t\t\r\n\t\tfloat average_distance = 0.0f;\r\n\t\t\r\n\t\tint num_colliders = p_colliders_array->GetSize();\r\n\t\t// Dbg_MsgAssert(num_colliders == vVP_NUM_COLLIDERS, (\"Number of colliders for CVehicleComponent is incorrect\"));\r\n\t\t\r\n\t\tfor (int collider_idx = num_colliders; collider_idx--; )\r\n\t\t{\r\n            SCollider& collider = mp_colliders[collider_idx];\r\n\t\t\t\r\n\t\t\tScript::CArray* p_corner_array = p_colliders_array->GetArray(collider_idx);\r\n\t\t\tDbg_MsgAssert(p_corner_array->GetSize() == 3, (\"Incorrect number of corner vectors in collider array\"));\r\n\t\t\t\r\n\t\t\tScript::CVector* p_corner_vector;\r\n            p_corner_vector = p_corner_array->GetVector(0);\r\n            collider.body.m_corner[X] = p_corner_vector->mX;\r\n            collider.body.m_corner[Y] = p_corner_vector->mY;\r\n            collider.body.m_corner[Z] = p_corner_vector->mZ;\r\n\t\t\tp_corner_vector = p_corner_array->GetVector(1);\r\n\t\t\tcollider.body.m_first_edge[X] = p_corner_vector->mX;\r\n\t\t\tcollider.body.m_first_edge[Y] = p_corner_vector->mY;\r\n\t\t\tcollider.body.m_first_edge[Z] = p_corner_vector->mZ;\r\n\t\t\tcollider.body.m_first_edge -= collider.body.m_corner;\r\n\t\t\tp_corner_vector = p_corner_array->GetVector(2);\r\n\t\t\tcollider.body.m_second_edge[X] = p_corner_vector->mX;\r\n\t\t\tcollider.body.m_second_edge[Y] = p_corner_vector->mY;\r\n\t\t\tcollider.body.m_second_edge[Z] = p_corner_vector->mZ;\r\n\t\t\tcollider.body.m_second_edge -= collider.body.m_corner;\r\n\t\t\t\r\n\t\t\t// update maximum_distance\r\n\t\t\taverage_distance += collider.body.m_corner.Length();\r\n\t\t\taverage_distance += (collider.body.m_corner + collider.body.m_first_edge).Length();\r\n\t\t\taverage_distance += (collider.body.m_corner + collider.body.m_second_edge).Length();\r\n\t\t\t\r\n\t\t\t// calculate the precomputable values\r\n\t\t\tcollider.first_edge_length = collider.body.m_first_edge.Length();\r\n\t\t\tcollider.second_edge_length = collider.body.m_second_edge.Length();\r\n\t\t\t\r\n\t\t\tDbg_MsgAssert(collider.first_edge_length > 0.0f, (\"Collider of zero area\"));\r\n\t\t\tDbg_MsgAssert(collider.second_edge_length > 0.0f, (\"Collider of zero area\"));\r\n\t\t}\r\n\t\t\r\n\t\t// set the skater's rigid body collision radius while in the car\r\n\t\tMdl::Skate::Instance()->GetLocalSkater()->SetRigidBodyCollisionRadiusBoost(average_distance / 3.0f / num_colliders - 48.0f);\r\n\t}\r\n\t\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x1757e572, \"engine\")))\r\n\t{\r\n\t\tScript::CStruct* p_engine_struct;\r\n\t\tpParams->GetStructure(CRCD(0x1757e572, \"engine\"), &p_engine_struct, Script::ASSERT);\r\n\t\t\r\n\t\t// base drive torque of the engine; multiplied by the gear and differential ratio (ft-lbs)\r\n\t\tif (p_engine_struct->ContainsComponentNamed(CRCD(0x9aa9faee, \"drive_torque\")))\r\n\t\t{\r\n\t\t\tp_engine_struct->GetFloat(CRCD(0x9aa9faee, \"drive_torque\"), &m_engine.drive_torque);\r\n\t\t\tm_engine.drive_torque *= 12.0f;\r\n\t\t}\r\n\t\t\r\n\t\t// base drag torque of the engine; multiplied by the square of the gear ratio (ft-lbs)\r\n\t\tif (p_engine_struct->ContainsComponentNamed(CRCD(0xb2268648, \"drag_torque\")))\r\n\t\t{\r\n\t\t\tp_engine_struct->GetFloat(CRCD(0xb2268648, \"drag_torque\"), &m_engine.drag_torque);\r\n\t\t\tm_engine.drag_torque *= 12.0f;\r\n\t\t}\r\n\t\t\r\n\t\t// when rpm reaches this speed, the transmition upshifts (rpm)\r\n\t\tif (p_engine_struct->ContainsComponentNamed(CRCD(0x33921583, \"upshift_rpm\")))\r\n\t\t{\r\n\t\t\tp_engine_struct->GetFloat(CRCD(0x33921583, \"upshift_rpm\"), &m_engine.upshift_rotvel);\r\n\t\t\tm_engine.upshift_rotvel = RPM_TO_RADIANS_PER_SECOND(m_engine.upshift_rotvel);\r\n\t\t}\r\n\t\t\r\n\t\t// base gear ratio; torque and rpm are multiplied by this when translated up and down the drive train\r\n\t\tp_engine_struct->GetFloat(CRCD(0x94ea6601, \"differential_ratio\"), &m_engine.differential_ratio);\r\n\t\t\r\n\t\t// instead of having a true reverse gear, all gears are scaled down by this ratio when in reverse\r\n\t\tp_engine_struct->GetFloat(CRCD(0x82bcbb10, \"reverse_torque_ratio\"), &m_engine.reverse_torque_ratio);\r\n\t\t\r\n\t\t// gear ratios; torque and rpm are multiplied by these when translated up and down the drive train\r\n\t\tif (p_engine_struct->ContainsComponentNamed(CRCD(0xc023fa75, \"gear_ratios\")))\r\n\t\t{\r\n\t\t\tScript::CArray* p_engine_gear_ratios_array;\r\n\t\t\tp_engine_struct->GetArray(CRCD(0xc023fa75, \"gear_ratios\"), &p_engine_gear_ratios_array, Script::ASSERT);\r\n\t\t\t\r\n\t\t\tm_engine.num_gears = p_engine_gear_ratios_array->GetSize();\r\n\t\t\tDbg_MsgAssert(m_engine.num_gears <= vVP_MAX_NUM_GEARS, (\"Number of gears exceeds the maximum allowed number\"));\r\n\t\t\t\r\n\t\t\tfor (int n = 0; n < m_engine.num_gears; n++)\r\n\t\t\t{\r\n\t\t\t\tm_engine.p_gear_ratios[n] = p_engine_gear_ratios_array->GetFloat(n);\r\n\t\t\t\t\r\n\t\t\t\tif (n == 0) continue;\r\n\t\t\t\t\r\n\t\t\t\tDbg_MsgAssert(n == 0 || m_engine.p_gear_ratios[n - 1] > m_engine.p_gear_ratios[n],\r\n\t\t\t\t\t(\"Low gear has lower gear ratio than high gear\"));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// you can setup all wheels at once or each individually\r\n\t\r\n\t// an array of wheel structures\r\n\tif (pParams->ContainsComponentNamed(CRCD(0xb3f8557e, \"wheels\")))\r\n\t{\r\n\t\tScript::CArray* p_wheels_array = NULL;\r\n\t\tpParams->GetArray(CRCD(0xb3f8557e, \"wheels\"), &p_wheels_array, Script::ASSERT);\r\n\t\t\r\n\t\tDbg_MsgAssert(!mp_wheels || m_num_wheels == p_wheels_array->GetSize(), (\"Changed number of wheels\"));\r\n\t\t\r\n\t\tm_num_wheels = p_wheels_array->GetSize();\r\n\t\t\t\r\n\t\tif (!mp_wheels)\r\n\t\t{\r\n\t\t\tmp_wheels = new SWheel[m_num_wheels];\r\n\t\t}\r\n\t\t\t\r\n\t\tfor (int n = m_num_wheels; n--; )\r\n\t\t{\r\n\t\t\tScript::CStruct* p_wheel_struct = NULL;\r\n\t\t\tp_wheel_struct = p_wheels_array->GetStructure(n);\r\n\t\t\t\r\n\t\t\t// see update_wheel_from_structure() for documentation on wheel parameters\r\n\t\t\tupdate_wheel_from_structure(mp_wheels[n], p_wheel_struct);\r\n\t\t} // END loop over wheels\r\n\t} // END if wheel array specified\r\n\r\n\tDbg_MsgAssert(mp_wheels, (\"Wheels not created\"));\r\n\t\r\n\t// a structure of wheel parameters which acts on all wheels\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x371badff, \"all_wheels\")))\r\n\t{\r\n\t\tScript::CStruct* p_wheel_struct;\r\n\t\tpParams->GetStructure(CRCD(0x371badff, \"all_wheels\"), &p_wheel_struct, Script::ASSERT);\r\n\t\t\r\n\t\tfor (int n = m_num_wheels; n--; )\r\n\t\t{\r\n\t\t\t// see update_wheel_from_structure() for documentation on wheel parameters\r\n\t\t\tupdate_wheel_from_structure(mp_wheels[n], p_wheel_struct);\r\n\t\t} // END loop over wheels\r\n\t} // END if all_wheel structure specified\r\n\t\r\n\t// calculate dependent constant characteristics\r\n\t\r\n\t// count the number of drive wheels\r\n\tm_num_drive_wheels = 0;\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tif (mp_wheels[n].drive)\r\n\t\t{\r\n\t\t\tm_num_drive_wheels++;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// setup position and orientation based on the object's state\r\n\tm_orientation = GetObject()->GetMatrix();\r\n\tm_orientation.Normalize();\r\n\tif (pParams->ContainsComponentNamed(CRCD(0xaa99c521, \"save\")))\r\n\t{\r\n\t\tMth::Vector orientation_vector;\r\n\t\torientation_vector.Set();\r\n\t\tpParams->GetVector(CRCD(0xc97f3aa9, \"orientation\"), &orientation_vector);\r\n\t\tm_orientation.SetVector(orientation_vector);\r\n\t\tm_orientation.Normalize();\r\n\t\tm_orientation.GetMatrix(m_orientation_matrix);\r\n\t\tm_orientation_matrix[W].Set();\r\n\t\tGetObject()->SetMatrix(m_orientation_matrix);\r\n\t\tGetObject()->SetDisplayMatrix(m_orientation_matrix);\r\n\t}\r\n\t\r\n\tm_pos = GetObject()->GetPos();\r\n\tif (pParams->ContainsComponentNamed(CRCD(0x7f261953, \"pos\")))\r\n\t{\r\n\t\tpParams->GetVector(CRCD(0x7f261953, \"pos\"), &m_pos);\r\n\t\tGetObject()->SetPos(m_pos);\r\n\t}\r\n\t\r\n\tm_skater_visible = m_skater_visible || pParams->ContainsFlag(CRCD(0x2ed67657, \"make_skater_visible\"));\r\n\tif (pParams->ContainsFlag(CRCD(0x2ed67657, \"make_skater_visible\")))\r\n\t{\r\n\t\tpParams->GetVector(CRCD(0xec86ef7a, \"skater_pos\"), &m_skater_pos, Script::ASSERT);\r\n\t\tpParams->GetChecksum(CRCD(0xda75a33e, \"skater_anim\"), &m_skater_anim, Script::ASSERT);\r\n\t}\r\n\t\r\n\tpParams->GetChecksum(CRCD(0xedcf90e, \"Sounds\"), &m_sound_setup_checksum);\r\n\t\r\n\t// zero velocities and accumulators\r\n\t\r\n\tm_mom.Set(0.0f, 0.0f, 0.0f);\r\n\tm_rotmom.Set(0.0f, 0.0f, 0.0f);\r\n\t\r\n\tm_force.Set(0.0f, 0.0f, 0.0f);\r\n\tm_torque.Set(0.0f, 0.0f, 0.0f);\r\n\t\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\twheel.state = SWheel::OUT_OF_CONTACT;\r\n \t\twheel.orientation = 0.0f;\r\n\t\twheel.rotvel = 0.0f;\r\n\t\twheel.y_offset = wheel.y_offset_hang;\r\n\t\twheel.steering_angle = 0.0f;\r\n\t\twheel.steering_angle_display = 0.0f;\r\n\t\t\r\n\t\twheel.rotacc = 0.0f;\r\n\r\n\t\t// set normal force history to their default values\r\n\t\tfor (int i = vVP_NORMAL_FORCE_HISTORY_LENGTH; i--; )\r\n\t\t{\r\n\t\t\twheel.normal_force_history[i] = vVP_GRAVITATIONAL_ACCELERATION / m_inv_mass / m_num_wheels;\r\n\t\t}\r\n\t}\r\n\tm_next_normal_force_history_idx = 0;\r\n\t\r\n\tm_gravity_override_timer = 0.0f;\r\n\tm_gravity_override_fraction = 1.0f;\r\n\t\r\n\tm_in_flip = false;\r\n\t\r\n\t// grab a pointer to the vehicle's skeleton\r\n\tmp_skeleton_component = static_cast< CSkeletonComponent* >(GetObject()->GetComponent(CRC_SKELETON));\r\n\tDbg_MsgAssert(mp_skeleton_component, (\"Vehicle component has no peer skeleton component.\"));\r\n\tDbg_MsgAssert(mp_skeleton_component->GetSkeleton()->GetNumBones() == static_cast< int >(2 + m_num_wheels), (\"Vehicle component's peer skeleton component has an unexpected number of bones\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tDbg_Assert(false);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::Finalize (   )\r\n{\r\n\tmp_input_component = GetInputComponentFromObject(GetObject());\r\n\tmp_model_component = GetModelComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_input_component);\r\n\tDbg_Assert(mp_model_component);\r\n\t\r\n\t// extract information about the car from the model\r\n\t\r\n\tDbg_MsgAssert(m_num_wheels == vVP_NUM_WHEELS, (\"Number of wheels must equal CVehicleComponent::vVP_NUM_WHEELS\"));\r\n\t\r\n\tCModelComponent* p_model_component = static_cast< CModelComponent* >(GetModelComponentFromObject(GetObject()));\r\n\tDbg_Assert(p_model_component);\r\n\tNx::CModel* p_model = p_model_component->GetModel();\r\n\tDbg_Assert(p_model);\r\n\tNx::CHierarchyObject* p_hierarchy_objects = p_model->GetHierarchy();\r\n\tDbg_Assert(p_hierarchy_objects);\r\n\t\r\n\tfor (int n = vVP_NUM_WHEELS; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\tMth::Matrix wheel_matrix = (p_hierarchy_objects + 2 + n)->GetSetupMatrix();\r\n\t\t\r\n\t\t// rotate out of max coordinate system\r\n\t\twheel.pos[X] = -wheel_matrix[W][X];\r\n\t\twheel.pos[Y] = wheel_matrix[W][Z];\r\n\t\twheel.pos[Z] = -wheel_matrix[W][Y];\r\n\t\twheel.pos[W] = 1.0f;\r\n\t}\r\n\t\r\n\tMth::Matrix body_matrix = (p_hierarchy_objects + 1)->GetSetupMatrix();\r\n\tm_body_pos[X] = -body_matrix[W][X];\r\n\tm_body_pos[Y] = body_matrix[W][Z];\r\n\tm_body_pos[Z] = -body_matrix[W][Y];\r\n\tm_body_pos[W] = 1.0f;\r\n\t\r\n\t// extract axle and wheelbase information\r\n\tint left_steering_tire = -1;\r\n\tint right_steering_tire = -1;\r\n\tint rear_tire = -1;\r\n\tfor (int n = vVP_NUM_WHEELS; n--; )\r\n\t{\r\n\t\tswitch (mp_wheels[n].steering)\r\n\t\t{\r\n\t\t\tcase SWheel::LEFT:\r\n\t\t\t\tleft_steering_tire = n;\r\n\t\t\t\tbreak;\r\n\t\t\tcase SWheel::RIGHT:\r\n\t\t\t\tright_steering_tire = n;\r\n\t\t\t\tbreak;\r\n\t\t\tcase SWheel::FIXED:\r\n\t\t\t\trear_tire = n;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tDbg_Assert(left_steering_tire != -1);\r\n\tDbg_Assert(right_steering_tire != -1);\r\n\tDbg_Assert(rear_tire != -1);\r\n\tm_cornering_wheelbase = Mth::Abs(\r\n\t\t(p_hierarchy_objects + 2 + left_steering_tire)->GetSetupMatrix()[W][Y] - (p_hierarchy_objects + 2 + rear_tire)->GetSetupMatrix()[W][Y]\r\n\t);\r\n\tm_cornering_axle_length = Mth::Abs(\r\n\t\t(p_hierarchy_objects + 2 + left_steering_tire)->GetSetupMatrix()[W][X] - (p_hierarchy_objects + 2 + right_steering_tire)->GetSetupMatrix()[W][X]\r\n\t);\r\n\t\r\n\t// calculate the true wheel positions based on the desired wheel positions with vehicle weight applied\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\r\n\t\t// place the wheel in the desired location based on the vehicle mass and the suspension spring rate; the suspension feeler starts at two\r\n\t\t// radii above the desired position\r\n\t\tfloat desired_y_pos = wheel.pos[Y];\r\n\t\twheel.pos[Y] = desired_y_pos + 2.0f * wheel.radius;\r\n\t\twheel.y_offset_hang = -wheel.pos[Y] + desired_y_pos - vVP_GRAVITATIONAL_ACCELERATION / (m_inv_mass * m_num_wheels * wheel.spring);\r\n\t}\r\n\t\r\n\t// determine the lowest collider point\r\n\tfloat lowest_collider_height = mp_colliders[0].body.m_corner[Y];\r\n\tfor (int n = vVP_NUM_COLLIDERS; n--; )\r\n\t{\r\n\t\tlowest_collider_height = Mth::Min(mp_colliders[n].body.m_corner[Y], lowest_collider_height);\r\n\t\tlowest_collider_height = Mth::Min(mp_colliders[n].body.m_corner[Y] + mp_colliders[n].body.m_first_edge[Y], lowest_collider_height);\r\n\t\tlowest_collider_height = Mth::Min(mp_colliders[n].body.m_corner[Y] + mp_colliders[n].body.m_second_edge[Y], lowest_collider_height);\r\n\t}\r\n\t\r\n\t// ready the skater for control\r\n\tmp_skater = Mdl::Skate::Instance()->GetLocalSkater();\r\n\tmp_skater_core_physics_component = GetSkaterCorePhysicsComponentFromObject(mp_skater);\r\n\tmp_skater_trigger_component = GetTriggerComponentFromObject(mp_skater);\r\n\tDbg_Assert(mp_skater_core_physics_component);\r\n\tDbg_Assert(mp_skater_trigger_component);\r\n\t\r\n\tif (!m_skater_visible)\r\n\t{\r\n\t\tmp_skater->Hide(true);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_skater_animation_component = GetAnimationComponentFromObject(mp_skater);\r\n\t\tDbg_Assert(mp_skater_animation_component);\r\n\t}\r\n\t\r\n\t// calculate the center of mass we will use based on the wheel locations\r\n\tMth::Vector center_of_mass(0.0f, 0.0f, 0.0f, 0.0f);\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tcenter_of_mass += mp_wheels[n].pos;\r\n\t}\r\n\tcenter_of_mass /= m_num_wheels;\r\n\tcenter_of_mass[Y] = lowest_collider_height;\r\n\tcenter_of_mass[W] = 0.0f;\r\n\t\r\n\t// move wheels and colliders so that they are relative to the correct center of mass\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tmp_wheels[n].pos -= center_of_mass;\r\n\t}\r\n\tfor (int n = vVP_NUM_COLLIDERS; n--; )\r\n\t{\r\n\t\tmp_colliders[n].body.m_corner -= center_of_mass;\r\n\t}\r\n\tm_body_pos -= center_of_mass;\r\n\tm_skater_pos -= center_of_mass;\r\n\t\r\n\tupdate_dependent_variables();\r\n\t\r\n\tGetObject()->SetPos(m_pos);\r\n\tGetObject()->SetVel(m_vel);\r\n\tGetObject()->SetMatrix(m_orientation_matrix);\r\n\tGetObject()->SetDisplayMatrix(GetObject()->GetMatrix());\r\n\t\r\n\tupdate_skeleton();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::Update()\r\n{\r\n\tm_reset_this_frame = false;\r\n\t\r\n\tif (!m_update_suspension_only)\r\n\t{\r\n\t\tget_input();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tzero_input();\r\n\t}\r\n\t\r\n\tif (m_state == ASLEEP)\r\n\t{\r\n\t\t// reduced work set if we're asleep\r\n\t\tGetObject()->SetDisplayMatrix(GetObject()->GetMatrix());\r\n\t\tupdate_steering_angles();\r\n\t\tif (m_controls.brake)\r\n\t\t{\r\n\t\t\tfor (int n = m_num_wheels; n--; )\r\n\t\t\t{\r\n\t\t\t\tmp_wheels[n].rotvel = 0.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t\tupdate_wheel_dynamic_state();\r\n\t\tupdate_skeleton();\r\n\t\tdraw_shadow();\r\n\t\tcontrol_skater();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tint num_time_steps;\r\n\tfloat frame_length = Tmr::FrameLength();\r\n\t\r\n\tif (in_artificial_collision())\r\n\t{\r\n\t\tm_artificial_collision_timer -= frame_length;\r\n\t}\r\n\t\r\n\t// count down timers\r\n\tif (m_gravity_override_timer != 0.0f)\r\n\t{\r\n\t\tm_gravity_override_timer -= frame_length;\r\n\t\tif (m_gravity_override_timer <= 0.0f || m_num_wheels_in_contact > 1)\r\n\t\t{\r\n\t\t\tMESSAGE(\"Ending vehicle gravity override\");\r\n\t\t\tm_gravity_override_timer = 0.0f;\r\n\t\t\tm_gravity_override_fraction = 1.0f;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// the physics is unstable at low frame rates, so we take multiple physics steps during long frame; if vehicle physics is a significant fraction\r\n\t// of CPU time, this could exacerbate whatever frame rate problems are occuring\r\n\tif (frame_length >= (1.0f / 30.0f))\r\n\t{\r\n\t\tnum_time_steps = static_cast< int >(ceilf(frame_length / (1.0f / 60.0f)));\r\n\t\tif (num_time_steps > 6)\r\n\t\t{\r\n\t\t\tnum_time_steps = 6;\r\n\t\t}\r\n\t\tm_time_step = frame_length / num_time_steps;\r\n\t\tDbg_Message(\"CVehicleComponent::Update: using %i steps this frame\", num_time_steps);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tnum_time_steps = 1;\r\n\t\tm_time_step = frame_length;\r\n\t}\r\n\t\r\n\tfor (int step = num_time_steps; step--; )\r\n\t{\r\n\t\tupdate_dynamic_state();\r\n\t\t\r\n\t\tm_force.Set(0.0f, 0.0f, 0.0f);\r\n\t\tm_torque.Set(0.0f, 0.0f, 0.0f);\r\n\t\tfor (int n = m_num_wheels; n--; )\r\n\t\t{\r\n\t\t\tmp_wheels[n].rotacc = 0.0f;\r\n\t\t}\r\n\t\t\r\n\t\tif (!m_update_suspension_only)\r\n\t\t{\r\n\t\t\tapply_environment_collisions();\r\n\t\t\tif (reset_this_frame()) return;\r\n\t\t}\r\n\t\t\r\n\t\t// teleport wheels to the ground, if within reach of the suspension\r\n\t\tupdate_wheel_heights();\r\n\t\tif (reset_this_frame()) return;\r\n\t\t\r\n\t\t// update the steering wheels' angles\r\n\t\tupdate_steering_angles();\r\n\t\t\r\n\t\t// damp out rotations to create a more drivable car\r\n\t\tdamp_rotation();\r\n\t\t\r\n\t\t// accumulate all forces and torques on the body and wheels\r\n\t\taccumulate_forces();\r\n\r\n\t\t/////////////\r\n\t\t// update state observers\r\n\r\n\t\tif (m_num_wheels_in_contact > 0)\r\n\t\t{\r\n\t\t\tm_air_time = 0.0f;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_air_time += m_time_step;\r\n\t\t}\r\n\t\t\r\n\t\tif (m_num_wheels_in_contact > 0 || m_max_normal_collision_impulse > 0.0f)\r\n\t\t{\r\n\t\t\tm_air_time_no_collision = 0.0f;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_air_time_no_collision += m_time_step;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (m_update_suspension_only) return;\r\n\t\r\n\t// draw debug lines\r\n\tdraw_debug_rendering();\r\n\t\r\n\t// update object's position and orientation\r\n\tGetObject()->SetPos(m_pos);\r\n\tGetObject()->SetVel(m_vel);\r\n\tGetObject()->SetMatrix(m_orientation_matrix);\r\n\tGetObject()->SetDisplayMatrix(GetObject()->GetMatrix());\r\n\t\r\n\tconsider_sleeping();\r\n\t\r\n\tupdate_skeleton();\r\n\r\n\t// Hack to draw shadow\r\n\tdraw_shadow();\r\n\t\r\n\t#if 0\r\n\tMth::Vector forward(0.0f, 0.0f, 1.0f);\r\n\tforward = m_orientation_matrix.Rotate(forward);\r\n\tfloat vel = IPS_TO_MPH(Mth::Abs(Mth::DotProduct(m_vel, forward)));\r\n\tPERIODIC(60) DUMPF(vel);\r\n\t#endif\r\n\t\r\n\t// HACK: get player proximity checks, triggers, driving animations, and the like working\r\n\tcontrol_skater();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CVehicleComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | Vehicle_Kick | kicks the vehicle with a force and torque\r\n\t\tcase CRCC(0x93b713a6, \"Vehicle_Kick\"):\r\n\t\t{\r\n\t\t\tMth::Vector linear;\r\n\t\t\tMth::Vector angular;\r\n\t\t\t\r\n\t\t\tm_state = AWAKE;\r\n\t\t\tm_consider_sleeping_count = 0;\r\n\t\t\t\r\n\t\t\tpParams->GetVector(\"linear\", &linear);\r\n\t\t\tpParams->GetVector(\"angular\", &angular);\r\n\t\t\t\r\n\t\t\tlinear = m_orientation_matrix.Rotate(linear);\r\n\t\t\tangular = m_orientation_matrix.Rotate(angular);\r\n\t\t\t\r\n\t\t\tm_mom += linear / m_inv_mass;\r\n\t\t\tm_rotmom += angular / m_inv_moment_body[X];\r\n\t\t\t\r\n\t\t\tupdate_velocities();\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | Vehicle_Wake | wakes the vehicle if asleep\r\n\t\tcase CRCC(0xa80a0d36, \"Vehicle_Wake\"):\r\n\t\t\tm_state = AWAKE;\r\n\t\t\tm_consider_sleeping_count = 0;\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | Vehicle_MoveToRestart | teleport the vehicle to the restart node\r\n\t\tcase CRCC(0x4b0b27dd, \"Vehicle_MoveToRestart\"):\r\n\t\t{\r\n\t\t\tuint32 node_name_checksum;\r\n\t\t\tif (pParams->GetChecksum(NO_NAME, &node_name_checksum))\r\n\t\t\t{\r\n\t\t\t\t// a node is specifically specified\r\n\t\t\t\tMoveToNode(SkateScript::GetNode(SkateScript::FindNamedNode(node_name_checksum, Script::ASSERT)));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// find a linked restart node\r\n\t\t\t\tint node = pScript->mNode;\r\n\t\t\t\tDbg_MsgAssert(node !=  -1,( \"Vehicle_MoveToRestart called from non-node script with no target node specified\"));\r\n\t\t\t\t{\r\n\t\t\t\t\tint num_links = SkateScript::GetNumLinks(node);\r\n\t\t\t\t\tfor (int n = 0; n < num_links; n++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint linked_node = SkateScript::GetLink(node, n);\r\n\t\t\t\t\t\tif (IsRestart(linked_node))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tMoveToNode(SkateScript::GetNode(linked_node));\r\n\t\t\t\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (Ed::CParkEditor::Instance()->UsingCustomPark())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMoveToNode(SkateScript::GetNode(Mdl::Skate::Instance()->find_restart_node(0)));\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_MsgAssert(0, (\"Vehicle_MoveToRestart called but node %d not linked to restart\", node));\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | Vehicle_PlaceBeforeCamera | moves the object before the active camera\r\n\t\tcase CRCC(0xc33608e4, \"Vehicle_PlaceBeforeCamera\"):\r\n\t\t{\r\n\t\t\tGfx::Camera* camera = Nx::CViewportManager::sGetActiveCamera(0);\r\n\t\t\tif (camera)\r\n\t\t\t{\r\n\t\t\t\tMth::Vector& cam_pos = camera->GetPos();\r\n\t\t\t\tMth::Matrix& cam_mat = camera->GetMatrix();\r\n\r\n\t\t\t\tm_pos = cam_pos;\r\n\t\t\t\tm_pos += cam_mat[Y] * 12.0f * 12.0f;\r\n\t\t\t\tm_pos -= cam_mat[Z] * 12.0f * 12.0f;\r\n\t\t\t\tGetObject()->SetPos(m_pos);\r\n\t\t\t\t\r\n\t\t\t\tm_orientation_matrix[X] = -cam_mat[X];\r\n\t\t\t\tm_orientation_matrix[Y] = cam_mat[Y];\r\n\t\t\t\tm_orientation_matrix[Z] = -cam_mat[Z];\r\n\t\t\t\tm_orientation = m_orientation_matrix;\r\n\t\t\t\tm_orientation.Normalize();\r\n\t\t\t\tm_orientation.GetMatrix(m_orientation_matrix);\r\n\t\t\t\tm_orientation_matrix[W].Set();\r\n\t\t\t\tGetObject()->SetMatrix(m_orientation_matrix);\r\n\t\t\t\t\r\n\t\t\t\tupdate_dependent_variables();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | Vehicle_AdjustGravity | adjusts effective gravity for a given duration or until the vehicle has two or more wheels on the ground,\r\n\t\t// whichever occurs first\r\n\t\t// @parm float | Percent | Percent of standard gravity.\r\n\t\t// @parm float | Duration | Duration in seconds over which to override gravity.\r\n\t\tcase CRCC(0xdb35aad8, \"Vehicle_AdjustGravity\"):\r\n\t\t\tpParams->GetFloat(CRCD(0x9e497fc6, \"Percent\"), &m_gravity_override_fraction, Script::ASSERT);\r\n\t\t\tm_gravity_override_fraction *= 1.0f / 100.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0x79a07f3f, \"Duration\"), &m_gravity_override_timer, Script::ASSERT);\r\n\t\t\tDbg_MsgAssert(m_gravity_override_timer > 0.0f, (\"Vehicle_AdjustGravity must have positive Duration\"));\r\n\t\t\tMESSAGE(\"Initiating vehicle gravity override\");\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | Vehicle_ForceBrake | forces on the brake\r\n\t\t// case CRCC(0x1ad6b6bc, \"Vehicle_ForceBrake\"):\r\n\t\t\t// m_force_brake = true;\r\n\t\t\t// break;\r\n\t\t\t\r\n\t\t// @script | Vehicle_HandbrakeActive | returns true if the car has a handbrake\r\n\t\tcase CRCC(0x5008b253, \"Vehicle_HandbrakeActive\"):\r\n\t\t\treturn m_force_brake ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\t// @script | Vehicle_AllWheelsAreInContact | returns true if all of the wheels are in contact with geo\r\n\t\tcase CRCC(0x279602ed, \"Vehicle_AllWheelsAreInContact\"):\r\n\t\t\treturn m_num_wheels_in_contact == m_num_wheels ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\r\n\t\t// @script | Vehicle_LostCollision | lost a net collision; respond appropriately\r\n\t\tcase CRCC(0x4c73526b, \"Vehicle_LostCollision\"):\r\n\t\t{\r\n\t\t\tMth::Vector offset;\r\n\t\t\tpParams->GetVector(CRCD(0xa6f5352f, \"Offset\"), &offset, Script::ASSERT);\r\n\t\t\tApplyArtificialCollision(offset);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | Vehicle_IsSkaterVisible | true if skater should be visible while driving\r\n\t\tcase CRCC(0x81faac21, \"Vehicle_IsSkaterVisible\"):\r\n\t\t\treturn m_skater_visible ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE; \r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::GetDebugInfo ( Script::CStruct *p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info, (\"NULL p_info sent to CVehicleComponent::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddVector(\"m_pos\", m_pos);\r\n\tp_info->AddVector(\"m_mom\", m_mom);\r\n\tp_info->AddVector(\"m_rotmom\", m_rotmom);\r\n\tp_info->AddFloat(\"m_orientation\", m_orientation.GetScalar());\r\n\tp_info->AddVector(\"m_orientation\", m_orientation.GetVector());\r\n\t\r\n\tp_info->AddVector(\"m_force\", m_force);\r\n\tp_info->AddVector(\"m_torque\", m_torque);\r\n\t\r\n\tp_info->AddVector(\"m_vel\", m_vel);\r\n\tp_info->AddVector(\"m_rotvel\", m_rotvel);\r\n\t\r\n\tp_info->AddVector(\"m_suspension_center_of_mass\", m_suspension_center_of_mass);\r\n\tp_info->AddFloat(\"mass\", vVP_GRAVITATIONAL_ACCELERATION / m_inv_mass);\r\n\tp_info->AddVector(\"moment_of_inertia\",\r\n\t\tvVP_GRAVITATIONAL_ACCELERATION / m_inv_moment_body[X],\r\n\t\tvVP_GRAVITATIONAL_ACCELERATION / m_inv_moment_body[Y],\r\n\t\tvVP_GRAVITATIONAL_ACCELERATION / m_inv_moment_body[Z]\r\n\t);\r\n\tp_info->AddFloat(\"body_restitution\", m_body_restitution);\r\n\tp_info->AddFloat(\"body_friction\", m_body_friction);\r\n\tp_info->AddFloat(\"body_spring\", m_body_spring);\r\n\tp_info->AddFloat(\"collision_control\", m_collision_control);\r\n\tp_info->AddFloat(\"in_air_slerp_velocity_cutoff\", m_in_air_slerp_vel_cutoff);\r\n\tp_info->AddFloat(\"in_air_slerp_time_delay\", m_in_air_slerp_time_delay);\r\n\tp_info->AddFloat(\"in_air_slerp_strength\", m_in_air_slerp_strength);\r\n\tp_info->AddChecksum(\"vert_correction\", m_vert_correction ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\t\r\n\tp_info->AddFloat(\"wipeout_body_friction\", m_body_wipeout_friction);\r\n\tp_info->AddFloat(\"max_steering_angle\", RADIANS_TO_DEGREES(m_max_steering_angle));\r\n\tp_info->AddFloat(\"cornering_wheelbase\", m_cornering_wheelbase);\r\n\tp_info->AddFloat(\"cornering_axle_length\", m_cornering_axle_length);\r\n\tp_info->AddFloat(\"constant_rotational_damping\", m_const_rotvel_damping);\r\n\tp_info->AddFloat(\"quadratic_rotational_damping\", m_quad_rotvel_damping);\r\n\t\r\n\tScript::CStruct* p_engine_info = new Script::CStruct;\r\n\tp_engine_info->AddFloat(\"drive_torque\", m_engine.drive_torque / 12.0f);\r\n\tp_engine_info->AddFloat(\"drag_torque\", m_engine.drag_torque / 12.0f);\r\n\tp_engine_info->AddFloat(\"upshift_rpm\", RADIANS_PER_SECOND_TO_RPM(m_engine.upshift_rotvel));\r\n\tp_engine_info->AddFloat(\"differential_ratio\", m_engine.differential_ratio);\r\n\tp_engine_info->AddFloat(\"reverse_torque_ratio\", m_engine.reverse_torque_ratio);\r\n\tScript::CArray* p_engine_gear_ratio_info = new Script::CArray;\r\n\tp_engine_gear_ratio_info->SetSizeAndType(m_engine.num_gears, ESYMBOLTYPE_FLOAT);\r\n\tfor (int n = m_engine.num_gears; n--; )\r\n\t{\r\n\t\tp_engine_gear_ratio_info->SetFloat(n, m_engine.p_gear_ratios[n]);\r\n\t}\r\n\tp_engine_info->AddArrayPointer(\"gear_ratios\", p_engine_gear_ratio_info);\r\n\tp_info->AddStructurePointer(\"m_engine\", p_engine_info);\r\n\t\r\n\tScript::CArray* p_wheels_info = new Script::CArray;\r\n\tp_wheels_info->SetSizeAndType(m_num_wheels, ESYMBOLTYPE_STRUCTURE);\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\tScript::CStruct* p_local_info = new Script::CStruct;\r\n\t\t\r\n\t\tuint32 state_checksums[] =\r\n\t\t{\r\n\t\t\tCRCC(0xba2b31d7, \"NO_STATE\"),\r\n\t\t\tCRCC(0xcd419ee6, \"OUT_OF_CONTACT\"),\r\n\t\t\tCRCC(0x927c0fed, \"UNDER_GRIPPING\"),\r\n\t\t\tCRCC(0xe9bc148a, \"GRIPPING\"),\r\n\t\t\tCRCC(0x26acccc8, \"SLIPPING\"),\r\n\t\t\tCRCC(0xa91003cc, \"SKIDDING\"),\r\n\t\t\tCRCC(0x2e7ef449, \"HANDBRAKE_THROTTLE\"),\r\n\t\t\tCRCC(0xbf6d6529, \"HANDBRAKE_LOCKED\"),\r\n\t\t};\r\n\t\tuint32 steering_checksums[] =\r\n\t\t{\r\n\t\t\tCRCC(0x613631cd, \"FIXED\"),\r\n\t\t\tCRCC(0x85981897, \"LEFT\"),\r\n\t\t\tCRCC(0x4b358aeb, \"RIGHT\")\r\n\t\t};\r\n\t\tp_local_info->AddChecksum(\"state\", state_checksums[wheel.state]);\r\n\t\tp_local_info->AddFloat(\"rotvel\", wheel.rotvel);\r\n        p_local_info->AddFloat(\"y_offset\", wheel.y_offset);\r\n        p_local_info->AddFloat(\"steering_angle\", RADIANS_TO_DEGREES(wheel.steering_angle));\r\n        p_local_info->AddFloat(\"steering_angle_display\", RADIANS_TO_DEGREES(wheel.steering_angle_display));\r\n        p_local_info->AddFloat(\"rotacc\", wheel.rotacc);\r\n\t\tp_local_info->AddFloat(\"orientation\", wheel.orientation);\r\n\t\tp_local_info->AddVector(\"pos\", wheel.pos);\r\n\t\tp_local_info->AddFloat(\"y_offset_hang\", wheel.y_offset_hang);\r\n\t\tp_local_info->AddFloat(\"max_draw_y_offset\", wheel.max_draw_y_offset);\r\n\t\tp_local_info->AddChecksum(\"steering\", steering_checksums[wheel.steering]);\r\n\t\tp_local_info->AddInteger(\"drive\", wheel.drive);\r\n\t\tp_local_info->AddFloat(\"radius\", wheel.radius);\r\n\t\tp_local_info->AddFloat(\"moment\", vVP_GRAVITATIONAL_ACCELERATION / wheel.inv_moment);\r\n\t\tp_local_info->AddFloat(\"spring_rate\", wheel.spring);\r\n\t\tp_local_info->AddFloat(\"damping_rate\", wheel.damping);\r\n\t\tp_local_info->AddFloat(\"static_friction\", wheel.static_friction);\r\n\t\tp_local_info->AddFloat(\"dynamic_friction\", wheel.dynamic_friction);\r\n\t\tp_local_info->AddFloat(\"handbrake_throttle_friction\", wheel.handbrake_throttle_friction);\r\n\t\tp_local_info->AddFloat(\"handbrake_locked_friction\", wheel.handbrake_locked_friction);\r\n\t\tp_local_info->AddFloat(\"min_static_grip_velocity\", IPS_TO_MPH(wheel.min_static_velocity));\r\n\t\tp_local_info->AddFloat(\"max_static_grip_velocity\", IPS_TO_MPH(wheel.max_static_velocity));\r\n\t\tp_local_info->AddFloat(\"min_dynamic_grip_velocity\", IPS_TO_MPH(wheel.min_dynamic_velocity));\r\n\t\tp_local_info->AddFloat(\"brake_torque\", wheel.brake.torque / 12.0f);\r\n\t\tp_local_info->AddFloat(\"handbrake_torque\", wheel.brake.handbrake_torque / 12.0f);\r\n\t\t\r\n\t\tp_wheels_info->SetStructure(n, p_local_info);\r\n\t}\r\n\tp_info->AddArrayPointer(\"mp_wheels\", p_wheels_info);\r\n\t\r\n\tScript::CStruct* p_controls_info = new Script::CStruct;\r\n\tp_controls_info->AddFloat(\"steering\", m_controls.steering);\r\n\tp_controls_info->AddInteger(\"throttle\", m_controls.throttle);\r\n\tp_controls_info->AddInteger(\"brake\", m_controls.brake);\r\n\tp_controls_info->AddInteger(\"handbrake\", m_controls.handbrake);\r\n\tp_controls_info->AddInteger(\"reverse\", m_controls.reverse);\r\n\tp_info->AddStructurePointer(\"m_controls\", p_controls_info);\r\n\t\r\n\tif (m_skater_visible)\r\n\t{\r\n\t\tp_info->AddVector(CRCD(0xec86ef7a, \"skater_pos\"), m_skater_pos);\r\n\t\tp_info->AddChecksum(CRCD(0xda75a33e, \"skater_anim\"), m_skater_anim);\r\n\t}\r\n\r\n\t// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::MoveToNode ( Script::CStruct* p_node )\r\n{\r\n\t// move to the position relative to the given node that a ped car would be at\r\n\t\r\n\tMth::Vector restart_pos;\r\n\tSkateScript::GetPosition(p_node, &restart_pos);\r\n\t\r\n\tMth::Vector restart_angles;\r\n\tSkateScript::GetAngles(p_node, &restart_angles);\r\n\tMth::Matrix restart_matrix;\r\n\trestart_matrix.SetFromAngles(restart_angles);\r\n\t\r\n\t// calculate appropriate offset from the ground based on estimated wheel offsets\r\n\tfloat avg_ground_offset = 0.0f;\r\n\tfor (int n = vVP_NUM_WHEELS; n--; )\r\n\t{\r\n\t\tavg_ground_offset += mp_wheels[n].y_offset_hang + mp_wheels[n].pos[Y] + vVP_GRAVITATIONAL_ACCELERATION / (m_inv_mass * m_num_wheels * mp_wheels[n].spring);\r\n\t\tavg_ground_offset -= mp_wheels[n].radius;\r\n\t}\r\n\tavg_ground_offset /= vVP_NUM_WHEELS;\r\n\t\r\n\t// find ground height\r\n\tCFeeler feeler(restart_pos + Mth::Vector(0.0f, 24.0f, 0.0f), restart_pos + Mth::Vector(0.0f, -240.0f, 0.0f));\r\n\tif (feeler.GetCollision(false))\r\n\t{\r\n\t\trestart_pos[Y] = feeler.GetPoint()[Y] - avg_ground_offset;\r\n\t}\r\n\t\r\n\t// ped cars have their origin between the rear wheels\r\n\tint rear_wheel_idx = -1;\r\n\tfor (int n = vVP_NUM_WHEELS; n--; )\r\n\t{\r\n\t\tif (mp_wheels[n].steering == SWheel::FIXED)\r\n\t\t{\r\n\t\t\trear_wheel_idx = n;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tDbg_Assert(rear_wheel_idx != -1);\r\n\trestart_pos -= restart_matrix[Z] * mp_wheels[rear_wheel_idx].pos[Z];\r\n\r\n\t// move the car to the restart position and allow it to settle on its suspension\r\n\t\r\n\tm_pos = restart_pos;\r\n\tm_orientation = restart_matrix;\r\n\t\r\n\tm_mom.Set(0.0f, 0.0f, 0.0f);\r\n\tm_rotmom.Set(0.0f, 0.0f, 0.0f);\r\n\t\r\n\t// zero wheels\r\n\t\r\n\tm_update_suspension_only = true;\r\n\tfor (int n = 60; n--; )\r\n\t{\r\n\t\t// lock wheels each frame\r\n\t\tfor (int n = m_num_wheels; n--; )\r\n\t\t{\r\n\t\t\tmp_wheels[n].rotvel = 0.0f;\r\n\t\t}\r\n\t\t\r\n\t\tUpdate();\r\n\t}\r\n\tm_update_suspension_only = false;\r\n\t\r\n\tm_mom.Set(0.0f, 0.0f, 0.0f);\r\n\tm_rotmom.Set(0.0f, 0.0f, 0.0f);\r\n\t\r\n\tm_reset_this_frame = true;\r\n\t\r\n\tm_state = ASLEEP;\r\n\t\r\n\t// update object's position and orientation\r\n\tGetObject()->SetPos(m_pos);\r\n\tGetObject()->SetVel(m_vel);\r\n\tGetObject()->SetMatrix(m_orientation_matrix);\r\n\tGetObject()->SetDisplayMatrix(GetObject()->GetMatrix());\r\n\t\r\n\tupdate_skeleton();\r\n\t\r\n\tcontrol_skater();\r\n\t\r\n\tGetObject()->SetTeleported();\r\n\tmp_skater->SetTeleported();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::ApplyArtificialCollision ( const Mth::Vector& offset )\r\n{\r\n\tMth::Vector impulse_direction = offset;\r\n\timpulse_direction[Y] = 0.0f;\r\n\timpulse_direction.Normalize();\r\n\t\r\n\tMth::Vector sideways(-impulse_direction[Z], 0.0f, impulse_direction[X]);\r\n\t\r\n\tfloat impulse_forward = (1.0f + Mth::PlusOrMinus(0.5f)) * Script::GetFloat(CRCD(0x3db3fa83, \"vehicle_physics_netcoll_forward_impulse\"));\r\n\tfloat impulse_sideways = Mth::PlusOrMinus(1.5f) * Script::GetFloat(CRCD(0x39e99fec, \"vehicle_physics_netcoll_sideways_impulse\"));\r\n\tfloat impulse_upwards = (1.0f + Mth::PlusOrMinus(0.2f)) * Script::GetFloat(CRCD(0x738500fd, \"vehicle_physics_netcoll_upwards_impulse\"));\r\n\t\r\n\tMth::Vector impulse = impulse_forward * impulse_direction + impulse_sideways * sideways;\r\n\timpulse[Y] += impulse_upwards;\r\n\t\r\n\tfloat rotate_spin = Mth::PlusOrMinus(1.5f) * Script::GetFloat(CRCD(0x14ddb3ef, \"vehicle_physics_netcoll_spin_impulse\"));\r\n\tfloat rotate_flip = (1.0f + Mth::PlusOrMinus(0.8f)) * Script::GetFloat(CRCD(0x4088e6ec, \"vehicle_physics_netcoll_flip_impulse\"));\r\n\t\r\n\tMth::Vector rotate = rotate_flip * sideways;\r\n\trotate[Y] += rotate_spin;\r\n\t\r\n\tm_mom += impulse / m_inv_mass;\r\n\tm_rotmom += rotate / m_inv_moment_body[X];\r\n\r\n\tupdate_velocities();\r\n\t\r\n\tm_artificial_collision_timer = Script::GetFloat(CRCD(0x771922a6, \"vehicle_physics_artificial_collision_duration\"));\r\n\t\r\n\tm_state = AWAKE;\r\n\tm_consider_sleeping_count = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::update_flip (   )\r\n{\r\n\tm_orientation.GetMatrix(m_orientation_matrix);\r\n\tm_orientation_matrix[W].Set();\r\n\t\r\n\tif (m_orientation_matrix[Y][Y] > 0.999f) // || !m_controls.throttle)\r\n\t{\r\n\t\tm_in_flip = false;\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tbool flipping_appropriate_this_frame = m_vel.LengthSqr() < Mth::Sqr(300.0f)\r\n\t\t&& m_rotvel.LengthSqr() < Mth::Sqr(Mth::PI / 4.0f)\r\n\t\t&& m_max_normal_collision_impulse > 0.0f\r\n\t\t&& m_orientation_matrix[Y][Y] < 0.25f\r\n\t\t&& (m_num_wheels_in_contact == 0 || m_orientation_matrix[Y][Y] < 0.0f)\r\n\t\t&& m_controls.throttle;\r\n\r\n\tif (!m_in_flip && !flipping_appropriate_this_frame) return;\r\n\t\r\n\t// starting a flip\r\n\tif (!m_in_flip)\r\n\t{\r\n\t\tm_mom.Set();\r\n\t\tm_rotmom.Set();\r\n\t\t\r\n\t\tm_in_flip = true;\r\n\t\tm_flip_start_time_stamp = Tmr::GetTime();\r\n\t}\r\n\t\r\n\t// check for maximum flip duration\r\n\tif (Tmr::ElapsedTime(m_flip_start_time_stamp) > vVP_FLIP_DURATION + vVP_FLIP_DELAY)\r\n\t{\r\n\t\tm_in_flip = false;\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// put a short delay before the flip actually has an effect\r\n\tif (Tmr::ElapsedTime(m_flip_start_time_stamp) < vVP_FLIP_DELAY)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// setup this frame's slerp\r\n\tMth::Matrix goal_orientation;\r\n\tgoal_orientation[Z] = m_orientation_matrix[Z];\r\n\tgoal_orientation[Z][Y] = 0.0f;\r\n\tgoal_orientation[Z].Normalize();\r\n\tgoal_orientation[Y].Set(0.0f, 1.0f, 0.0f);\r\n\tgoal_orientation[X].Set(goal_orientation[Z][Z], 0.0f, -goal_orientation[Z][X]);\r\n\tMth::SlerpInterpolator slerper;\r\n\tslerper.setMatrices(&m_orientation_matrix, &goal_orientation);\r\n\t\r\n\t// calculate the new orientation matrix\r\n\tslerper.getMatrix(\r\n\t\t&m_orientation_matrix,\r\n\t\tMth::ClampMax(vVP_FLIP_RATE * Tmr::FrameLength() / slerper.getRadians(), 1.0f)\r\n\t);\r\n\tm_orientation = m_orientation_matrix;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::update_wheel_from_structure ( SWheel& wheel, Script::CStruct* p_wheel_struct )\r\n{\r\n\tuint32 checksum;\r\n\t\r\n\t// wheel's steering type\r\n\tif (p_wheel_struct->ContainsComponentNamed(CRCD(0x7560e63, \"steering\")))\r\n\t{\r\n\t\tp_wheel_struct->GetChecksum(CRCD(0x7560e63, \"steering\"), &checksum);\r\n\t\tswitch (checksum)\r\n\t\t{\r\n\t\t\tcase CRCC(0x85981897, \"left\"):\r\n\t\t\t\twheel.steering = SWheel::LEFT;\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC(0x4b358aeb, \"right\"):\r\n\t\t\t\twheel.steering = SWheel::RIGHT;\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC(0x613631cd, \"fixed\"):\r\n\t\t\t\twheel.steering = SWheel::FIXED;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(false, (\"Bad wheel steering setting\"));\r\n\t\t}\r\n\t}\r\n\r\n\t// if the wheel is a drive wheel\r\n\tif (p_wheel_struct->ContainsComponentNamed(CRCD(0x97e20a70, \"drive\")))\r\n\t{\r\n\t\tp_wheel_struct->GetChecksum(CRCD(0x97e20a70, \"drive\"), &checksum);\r\n\t\tswitch (checksum)\r\n\t\t{\r\n\t\t\tcase CRCC(0x8a18ca56, \"yes\"):\r\n\t\t\t\twheel.drive = true;\r\n\t\t\t\tbreak;\r\n\t\t\tcase CRCC(0x9855d7e0, \"no\"):\r\n\t\t\t\twheel.drive = false;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(false, (\"Bad wheel drive setting\"));\r\n\t\t}\r\n\t}\r\n\r\n\t// suspension spring rate (lbs / in)\r\n\t// strength of the suspension spring; multiplied by the compresion to get the spring's force; must be scaled\r\n\t// with the vehicle weight; large spring rates give stiffer suspensions; large values may cause instability in\r\n\t// physics model\r\n\tp_wheel_struct->GetFloat(CRCD(0x9e931fdf, \"spring_rate\"), &wheel.spring);\r\n\r\n\t// suspension damping; bump rate (lbs s / in)\r\n\t// bounce damping strength of the suspension; smaller values cause bouncier suspensions; very large values may\r\n\t// cause instability in the physics model\r\n\tp_wheel_struct->GetFloat(CRCD(0xafa960ff, \"damping_rate\"), &wheel.damping);\r\n\r\n\t// wheel radius (in)\r\n\t// larger radius wheels are harder for the engine to rotate and the brake and rolling resistance to stop\r\n\tp_wheel_struct->GetFloat(CRCD(0xc48391a5, \"radius\"), &wheel.radius);\r\n\r\n\tif (p_wheel_struct->ContainsComponentNamed(CRCD(0xca73775d, \"moment\")))\r\n\t{\r\n\t\tp_wheel_struct->GetFloat(CRCD(0xca73775d, \"moment\"), &wheel.inv_moment);\r\n\t\twheel.inv_moment = vVP_GRAVITATIONAL_ACCELERATION / wheel.inv_moment;\r\n\t}\r\n\t\r\n\tp_wheel_struct->GetFloat(CRCD(0xd87d0183, \"max_draw_y_offset\"), &wheel.max_draw_y_offset);\r\n\r\n\t// the following parameters affect the shape of the tire's friction curve\r\n\t// the friction curve gives the strength of the frictional force as a function of the tire's slip velocity; our\r\n\t// simple curve rises linearly from zero at zero slip velocity, reaches static_friction at a slip velocity of\r\n\t// min_static_velocity, remains at static_friction up to a slip velocity of max_static_velocity, drops linearly\r\n\t// to dynamic_friction until a slip velocity of min_dynamic_velocity, and then remains constant at dynamic_friction\r\n\r\n\t// normalized friction strength when the wheel is not skidding\r\n\t// low values will cause the vehicle to be spin-out and skid easily; high values cause the tires to feel sticky;\r\n\t// real world values are on the order of 1.3; fun values are much higher\r\n\tp_wheel_struct->GetFloat(CRCD(0xf36b97c8, \"static_friction\"), &wheel.static_friction);\r\n\r\n\t// normalized friction strength when the wheel is skidding\r\n\t// should be lower than static_friction; values much lower than static_friction cause the vehicle to be unforgiving;\r\n\t// once you lose grip, it is harder to regain control of the vehicle; values near static_friction cause the vehicle\r\n\t// to be very forgiving, with skidding causing little loss of handling \r\n\tp_wheel_struct->GetFloat(CRCD(0x674852f6, \"dynamic_friction\"), &wheel.dynamic_friction);\r\n\t\r\n\t// normalized friction strength when the handbrake is applied\r\n\t// currently specially tuned in script to force a fishtail when the handbrake and throttle are both applied and spin-outs when only handbrake is applied\r\n\tp_wheel_struct->GetFloat(CRCD(0x52242919, \"handbrake_throttle_friction\"), &wheel.handbrake_throttle_friction);\r\n\tp_wheel_struct->GetFloat(CRCD(0x6d615f67, \"handbrake_locked_friction\"), &wheel.handbrake_locked_friction);\r\n\r\n\t// slip speed below which tires undergrip (mph)\r\n\t// should be around 1 to 2 mph\r\n\tif (p_wheel_struct->ContainsComponentNamed(CRCD(0x60b2c097, \"min_static_grip_velocity\")))\r\n\t{\r\n\t\tp_wheel_struct->GetFloat(CRCD(0x60b2c097, \"min_static_grip_velocity\"), &wheel.min_static_velocity);\r\n\t\twheel.min_static_velocity = MPH_TO_IPS(wheel.min_static_velocity);\r\n\t}\r\n\r\n\t// maximum slip speed before tires begin to lose their grip (mph)\r\n\t// should be larger than min_static_velocity; with a low value the vehicle will skid more readily; a high value\r\n\t// causes there to be a large range of slip velocties with maximum tire grip\r\n\tif (p_wheel_struct->ContainsComponentNamed(CRCD(0xbb0d9370, \"max_static_grip_velocity\")))\r\n\t{\r\n\t\tp_wheel_struct->GetFloat(CRCD(0xbb0d9370, \"max_static_grip_velocity\"), &wheel.max_static_velocity);\r\n\t\twheel.max_static_velocity = MPH_TO_IPS(wheel.max_static_velocity);\r\n\t}\r\n\r\n\t// minimum slip speed before tires begin skidding (imph)\r\n\t// should be larger than max_static_velocity; with a low values, tires are very unforgiving and begin to skid as soon\r\n\t// as they begin to slip; with a larger value, the loss of control and onset of skidding will be more gradual\r\n\tif (p_wheel_struct->ContainsComponentNamed(CRCD(0xb71803ad, \"min_dynamic_grip_velocity\")))\r\n\t{\r\n\t\tp_wheel_struct->GetFloat(CRCD(0xb71803ad, \"min_dynamic_grip_velocity\"), &wheel.min_dynamic_velocity);\r\n\t\twheel.min_dynamic_velocity = MPH_TO_IPS(wheel.min_dynamic_velocity);\r\n\t}\r\n\r\n\t// torque which the brake exerts on the wheel (ft-lbs)\r\n\tif (p_wheel_struct->ContainsComponentNamed(CRCD(0x3bccbadc, \"brake_torque\")))\r\n\t{\r\n\t\tp_wheel_struct->GetFloat(CRCD(0x3bccbadc, \"brake_torque\"), &wheel.brake.torque);\r\n\t\twheel.brake.torque *= 12.0f;\r\n\t}\r\n\r\n\t// torque which the handbrake exerts on the wheel when steering is straight and the throttle is down (ft-lbs)\r\n\tif (p_wheel_struct->ContainsComponentNamed(CRCD(0x9439d144, \"handbrake_torque\")))\r\n\t{\r\n\t\tp_wheel_struct->GetFloat(CRCD(0x9439d144, \"handbrake_torque\"), &wheel.brake.handbrake_torque);\r\n\t\twheel.brake.handbrake_torque *= 12.0f;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::update_dynamic_state (   )\r\n{\r\n\t// update body state\r\n\t\r\n\t// calculate accelerations\r\n\t\r\n\tMth::Vector acc = m_inv_mass * m_force;\r\n\tMth::Vector rotacc = m_inv_moment.Rotate(m_torque);\r\n\t\r\n\t// update state variables\r\n\t\r\n\tm_mom += m_time_step * m_force;\r\n\tupdate_pos_with_uber_frig(m_time_step * (m_vel + 0.5f * m_time_step * acc));\r\n\t\r\n\tMth::Vector delta_orientation_vector = -0.5f * m_time_step * (m_rotvel + 0.5f * m_time_step * rotacc);\r\n\tMth::Quat delta_orientation = m_orientation * Mth::Quat(delta_orientation_vector[X], delta_orientation_vector[Y], delta_orientation_vector[Z], 0.0f);\r\n\tm_orientation += delta_orientation;\r\n\tm_orientation.Normalize();\r\n\r\n    m_rotmom += m_time_step * m_torque;\r\n\t\r\n\tupdate_wheel_dynamic_state();\r\n\t\r\n    // if we're in the air and moving fast enough horizontally\r\n\tif (m_num_wheels_in_contact == 0 && m_max_normal_collision_impulse == 0.0f)\r\n\t{\r\n\t\tslerp_to_face_velocity();\r\n\t}\r\n\t\r\n\tupdate_flip();\r\n    \r\n\tupdate_dependent_variables();\r\n\t\r\n#if 0\r\n\tPERIODIC(60) {\r\n\t\tfloat K = 0.5f * Mth::DotProduct(m_vel, m_mom) + 0.5f * Mth::DotProduct(m_rotvel, m_rotmom);\r\n\t\tfloat U = vVP_GRAVITATIONAL_ACCELERATION * m_pos[Y] / m_inv_mass;\r\n\t\tDUMPF(K + U);\r\n\t\tMth::Vector a, b;\r\n\t\ta = m_rotmom;\r\n\t\tb = m_rotvel;\r\n\t\tDUMPF(Mth::DotProduct(a.Normalize(), b.Normalize()));\r\n\t\t// DUMPF(m_rotvel.Length());\r\n\t\t// DUMPV(m_rotvel);\r\n\t}\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::update_wheel_dynamic_state (   )\r\n{\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\t// wheel rotvel updates as torques are applied; thus, wheel rotvel is currently the frame's final rotvel \r\n\t\twheel.orientation += m_time_step * (wheel.rotvel - 0.5f * m_time_step * wheel.rotacc);\r\n\t\t\r\n\t\tif (wheel.orientation > (200.0f * Mth::PI))\r\n\t\t{\r\n\t\t\twheel.orientation -= (100.0f * Mth::PI);\r\n\t\t}\r\n\t\telse if (wheel.orientation < 0.0f)\r\n\t\t{\r\n\t\t\twheel.orientation += (100.0f * Mth::PI);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::update_dependent_variables (   )\r\n{\r\n\tm_orientation.GetMatrix(m_orientation_matrix);\r\n\tm_orientation_matrix[W].Set();\r\n\t\r\n\tm_suspension_center_of_mass_world = m_orientation_matrix.Rotate(m_suspension_center_of_mass);\r\n\t\r\n\tcalculate_inverse_moment();\r\n\t\r\n\tupdate_velocities();\r\n\t\r\n\t// update wheel feeler endpoint positions\r\n\tfor\t(int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\twheel.feeler_start_world = m_pos + m_orientation_matrix.Rotate(wheel.pos);\r\n\t\twheel.feeler_end_world = wheel.pos;\r\n\t\twheel.feeler_end_world[Y] += wheel.y_offset_hang - wheel.radius;\r\n\t\twheel.feeler_end_world = m_pos + m_orientation_matrix.Rotate(wheel.feeler_end_world);\r\n\t}\r\n\t\r\n\t// update collider world positions\r\n\tfor (int collider_idx = vVP_NUM_COLLIDERS; collider_idx--; )\r\n\t{\r\n\t\tSCollider& collider = mp_colliders[collider_idx];\r\n\t\t\r\n\t\tcollider.world.m_corner = m_pos + m_orientation_matrix.Rotate(collider.body.m_corner);\r\n\t\tcollider.world.m_first_edge = m_orientation_matrix.Rotate(collider.body.m_first_edge);\r\n        collider.world.m_second_edge = m_orientation_matrix.Rotate(collider.body.m_second_edge);\r\n\t\t\r\n\t\tcollider.first_edge_direction_world = collider.world.m_first_edge / collider.first_edge_length;\r\n\t\tcollider.second_edge_direction_world = collider.world.m_second_edge / collider.second_edge_length;\r\n\t}\r\n\t\r\n\tupdate_collision_cache();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CVehicleComponent::calculate_friction_coefficient ( SWheel& wheel, float velocity ) const\r\n{\r\n\t// friction based on section 2.4 and 2.7 of Race Car Vehicle Dynamics by Milliken\r\n\t\r\n\t// the tire friction coefficient curve is very simple; just four concatenated lines\r\n\t\r\n\tif (m_controls.handbrake)\r\n\t{\r\n\t\t// handbrake friction is a total scam\r\n\t\t\r\n\t\tfloat friction;\r\n\t\tif (m_controls.throttle)\r\n\t\t{\r\n\t\t\tfriction = wheel.handbrake_throttle_friction;\r\n\t\t\twheel.state = SWheel::HANDBRAKE_THROTTLE;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfriction = wheel.handbrake_locked_friction;\r\n\t\t\twheel.state = SWheel::HANDBRAKE_LOCKED;\r\n\t\t}\r\n\t\t\r\n\t\tif (velocity < wheel.min_static_velocity)\r\n\t\t{\r\n\t\t\t// under gripped handbrake \"skidding\"\r\n\t\t\twheel.state = SWheel::UNDER_GRIPPING;\r\n\t\t\treturn friction * velocity / wheel.min_static_velocity;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// handbrake \"skidding\"\r\n\t\t\treturn friction;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfloat multiplier = m_controls.brake ? 2.0f : 1.0f;\r\n\t\r\n\tif (velocity < wheel.min_static_velocity)\r\n\t{\r\n\t\t// under gripped\r\n\t\twheel.state = SWheel::UNDER_GRIPPING;\r\n\t\treturn wheel.static_friction * velocity / wheel.min_static_velocity;\r\n\t}\r\n\telse if (velocity < wheel.max_static_velocity)\r\n\t{\r\n\t\t// maximum grip\r\n\t\twheel.state = SWheel::GRIPPING;\r\n\t\treturn multiplier * wheel.static_friction;\r\n\t}\r\n\telse if (velocity < wheel.min_dynamic_velocity)\r\n\t{\r\n\t\t// on the verge of skidding\r\n\t\twheel.state = SWheel::SLIPPING;\r\n\t\treturn multiplier * wheel.dynamic_friction + (wheel.static_friction - wheel.dynamic_friction)\r\n\t\t\t* (velocity - wheel.max_static_velocity) / (wheel.min_dynamic_velocity - wheel.max_static_velocity);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// skidding\r\n\t\twheel.state = SWheel::SKIDDING;\r\n\t\treturn multiplier * wheel.dynamic_friction;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::calculate_friction_coefficients (   )\r\n{\r\n\t// calculate the wheels' friction coefficients this frame\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\tif (wheel.state == SWheel::OUT_OF_CONTACT) continue;\r\n\t\t\r\n\t\t// project the wheel's velocity due to the body's motion into the plane of the contact surface\r\n\t\tMth::Vector projected_vel = wheel.vel_world;\r\n\t\tprojected_vel.ProjectToPlane(wheel.contact_normal);\r\n\t\r\n\t\t// calculate the forward direction of the wheel\r\n\t\tMth::Vector wheel_direction(sinf(wheel.steering_angle), 0.0f, cosf(wheel.steering_angle));\r\n\t\twheel_direction = m_orientation_matrix.Rotate(wheel_direction);\r\n\t\t\r\n\t\t// project that forward direction onto the contact surface\r\n\t\twheel_direction.ProjectToPlane(wheel.contact_normal);\r\n\t\twheel_direction.Normalize();\r\n\t\t\r\n\t\t// NOTE: from this point and up, the calculation is repeated exactly in apply_friction_forces(); we cache the rotated and projected\r\n\t\t// wheel direction and the wheel velocity due to body velocity; because the wheel velocity will change before apply_friction_forces(),\r\n\t\t// the calculation below must be repeated\r\n\t\t\r\n\t\twheel.cache_projected_direction = wheel_direction;\r\n\t\twheel.cache_projected_vel = projected_vel;\r\n\t\r\n\t\t// subtract the contact patch velocity; positive wheel rotational velocity equals negative contact patch velocity\r\n\t\tprojected_vel -= wheel.rotvel * wheel.radius * wheel_direction;\r\n\t\r\n\t\t// calculate the friction coefficient\r\n\t\twheel.friction_coefficient = calculate_friction_coefficient(wheel, projected_vel.Length());\r\n\t}\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::calculate_inverse_moment (   )\r\n{\r\n\t// m_inv_moment = m_orientation_matrix * m_inv_moment_body_diag_matrix * m_orientation_matrix_transpose\r\n\t\r\n\tm_inv_moment[X][X] = m_inv_moment_body[X] * m_orientation_matrix[X][X];\r\n\tm_inv_moment[X][Y] = m_inv_moment_body[Y] * m_orientation_matrix[X][Y];\r\n\tm_inv_moment[X][Z] = m_inv_moment_body[Z] * m_orientation_matrix[X][Z];\r\n\tm_inv_moment[Y][X] = m_inv_moment_body[X] * m_orientation_matrix[Y][X];\r\n\tm_inv_moment[Y][Y] = m_inv_moment_body[Y] * m_orientation_matrix[Y][Y];\r\n\tm_inv_moment[Y][Z] = m_inv_moment_body[Z] * m_orientation_matrix[Y][Z];\r\n\tm_inv_moment[Z][X] = m_inv_moment_body[X] * m_orientation_matrix[Z][X];\r\n\tm_inv_moment[Z][Y] = m_inv_moment_body[Y] * m_orientation_matrix[Z][Y];\r\n\tm_inv_moment[Z][Z] = m_inv_moment_body[Z] * m_orientation_matrix[Z][Z];\r\n\t\r\n\tMth::Matrix orientation_matrix_transpose;\r\n\torientation_matrix_transpose.Transpose(m_orientation_matrix);\r\n\tm_inv_moment = m_inv_moment * orientation_matrix_transpose;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CVehicleComponent::determine_effective_gear ( float wheel_rotvel )\r\n{\r\n\tint gear = 0;\r\n\t\r\n\tdo\r\n\t{\r\n\t\tfloat engine_rotvel = wheel_rotvel * m_engine.differential_ratio * m_engine.p_gear_ratios[gear];\r\n\t\t\r\n\t\tif (engine_rotvel > m_engine.upshift_rotvel)\r\n\t\t{\r\n\t\t\tif (gear < m_engine.num_gears - 1)\r\n\t\t\t{\r\n\t\t\t\tgear++;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn gear;\r\n\t}\r\n\twhile (true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::update_collision_cache (   )\r\n{\r\n\tMth::CBBox collision_bbox;\r\n\t\r\n\t// add wheel location feelers\r\n\tfor\t(int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\tcollision_bbox.AddPoint(wheel.feeler_start_world);\r\n\t\tcollision_bbox.AddPoint(wheel.feeler_end_world);\r\n\t}\r\n\t\r\n\t// add body collision feelers\r\n\tfor (int collider_idx = vVP_NUM_COLLIDERS; collider_idx--; )\r\n\t{\r\n\t\tSCollider& collider = mp_colliders[collider_idx];\r\n\t\t\r\n        collision_bbox.AddPoint(collider.world.m_corner);\r\n\t\tcollision_bbox.AddPoint(collider.world.m_corner + collider.world.m_first_edge);\r\n\t\tcollision_bbox.AddPoint(collider.world.m_corner + collider.world.m_second_edge);\r\n\t\tcollision_bbox.AddPoint(collider.world.m_corner + collider.world.m_first_edge + collider.world.m_second_edge);\r\n\t}\r\n\t\r\n\tm_collision_cache.Update(collision_bbox);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::update_wheel_heights (   )\r\n{\r\n\t// We crap out and don't do real wheel dynamics.  Instead, if the ground is within a wheel's hang point, we teleport the wheel to the\r\n\t// ground.  If not, we teleport the wheel to its hang point.\r\n\t\r\n\tCFeeler feeler;\r\n\t\r\n\tfeeler.SetCache(&m_collision_cache);\r\n\t\r\n\tm_num_wheels_in_contact = 0;\r\n\tfor\t(int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\t// y_offset a feeler from the top of the wheel's y_offset to the wheel's hang point plus its radius\r\n\t\tfeeler.m_start = wheel.feeler_start_world;\r\n\t\tfeeler.m_end = wheel.feeler_end_world;\r\n\t\tfeeler.SetIgnore(mFD_NON_COLLIDABLE, 0);\r\n\t\t\r\n\t\tif (feeler.GetCollision(false))\r\n\t\t{\r\n\t\t\t// trip any triggers\r\n\t\t\tif (wheel.state != SWheel::OUT_OF_CONTACT)\r\n\t\t\t{\r\n\t\t\t\tif (feeler.GetSector() != wheel.last_ground_feeler.GetSector())\r\n\t\t\t\t{\r\n\t\t\t\t\ttrip_trigger(TRIGGER_SKATE_OFF, wheel.last_ground_feeler);\r\n\t\t\t\t\tif (reset_this_frame()) return;\r\n\t\t\t\t\ttrip_trigger(TRIGGER_SKATE_ONTO, feeler);\r\n\t\t\t\t\tif (reset_this_frame()) return;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ttrip_trigger(TRIGGER_SKATE_ONTO, feeler);\r\n\t\t\t\tif (reset_this_frame()) return;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\twheel.last_ground_feeler = feeler;\r\n\t\t\t\r\n\t\t\twheel.state = SWheel::NO_STATE;\r\n\t\t\twheel.contact_normal = feeler.GetNormal();\r\n\t\t\twheel.y_offset = feeler.GetDist() * (wheel.y_offset_hang - wheel.radius) + wheel.radius;\r\n\t\t\t\r\n\t\t\tm_num_wheels_in_contact++;\r\n\t\t\t\r\n\t\t\tfeeler.m_end = feeler.GetPoint();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// trip any triggers\r\n\t\t\tif (wheel.state != SWheel::OUT_OF_CONTACT)\r\n\t\t\t{\r\n\t\t\t\ttrip_trigger(TRIGGER_SKATE_OFF, wheel.last_ground_feeler);\r\n\t\t\t\tif (reset_this_frame()) return;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\twheel.state = SWheel::OUT_OF_CONTACT;\r\n\t\t\twheel.y_offset = wheel.y_offset_hang;\r\n\t\t}\r\n\t\t\r\n\t\t// Allows CAP kill planes to work on the car.\r\n\t\tif (Ed::CParkEditor::Instance()->UsingCustomPark())\r\n\t\t{\r\n\t\t\t// now check for non-collidable trigger polys\r\n\t\t\tfeeler.SetIgnore(0, mFD_NON_COLLIDABLE | mFD_TRIGGER);\r\n\t\t\tif (feeler.GetCollision(false))\r\n\t\t\t{\r\n\t\t\t\ttrip_trigger(TRIGGER_BONK, feeler);\r\n\t\t\t\tif (reset_this_frame()) return;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t} // END loop over wheels\r\n\t\r\n\t// update the wheels' dependent variables which depend of the wheel heights\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\twheel.pos_world = wheel.pos;\r\n\t\twheel.pos_world[Y] += wheel.y_offset - wheel.radius;\r\n\t\twheel.pos_world = m_orientation_matrix.Rotate(wheel.pos_world);\r\n\t\t\r\n\t\twheel.vel_world = calculate_body_point_velocity(wheel.pos_world);\r\n\t} // END loop over wheels\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::update_steering_angles (   )\r\n{\r\n\t// NOTE: could easily use a table here\r\n\t\r\n\tm_steering_display = Mth::Lerp(m_steering_display, m_controls.steering, 10.0f * m_time_step);\r\n\t\r\n\tfloat left_steering_angle;\r\n\tfloat right_steering_angle;\r\n\tfloat left_steering_angle_display;\r\n\tfloat right_steering_angle_display;\r\n\t\r\n\tif (Mth::Abs(m_controls.steering) > 0.001f)\r\n\t{\r\n\t\tfloat turning_radius = m_cornering_wheelbase / tanf(m_controls.steering * m_max_steering_angle);\r\n\t\t \r\n\t\tif (turning_radius > 0.0f)\r\n\t\t{\r\n\t\t\tleft_steering_angle = -atan2f(m_cornering_wheelbase, turning_radius - m_cornering_axle_length / 2.0f);\r\n\t\t\tright_steering_angle = -atan2f(m_cornering_wheelbase, turning_radius + m_cornering_axle_length / 2.0f);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tleft_steering_angle = atan2f(m_cornering_wheelbase, -turning_radius + m_cornering_axle_length / 2.0f);\r\n\t\t\tright_steering_angle = atan2f(m_cornering_wheelbase, -turning_radius - m_cornering_axle_length / 2.0f);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tleft_steering_angle = right_steering_angle = 0.0f;\r\n\t}\r\n\t\t\r\n\tif (Mth::Abs(m_steering_display) > 0.001f)\r\n\t{\r\n\t\tfloat turning_radius_display = m_cornering_wheelbase / tanf(m_steering_display * m_max_steering_angle);\r\n\t\t \r\n\t\tif (turning_radius_display > 0.0f)\r\n\t\t{\r\n\t\t\tleft_steering_angle_display = -atan2f(m_cornering_wheelbase, turning_radius_display - m_cornering_axle_length / 2.0f);\r\n\t\t\tright_steering_angle_display = -atan2f(m_cornering_wheelbase, turning_radius_display + m_cornering_axle_length / 2.0f);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tleft_steering_angle_display = atan2f(m_cornering_wheelbase, -turning_radius_display + m_cornering_axle_length / 2.0f);\r\n\t\t\tright_steering_angle_display = atan2f(m_cornering_wheelbase, -turning_radius_display - m_cornering_axle_length / 2.0f);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tleft_steering_angle_display = right_steering_angle_display = 0.0f;\r\n\t}\r\n\t\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\tif (wheel.steering == SWheel::FIXED) continue;\r\n\t\t\r\n        wheel.steering_angle = (wheel.steering == SWheel::LEFT ? left_steering_angle : right_steering_angle);\r\n        wheel.steering_angle_display = (wheel.steering == SWheel::LEFT ? left_steering_angle_display : right_steering_angle_display);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::damp_rotation (   )\r\n{\r\n\t// no damping when handbraking on the ground\r\n\tif (m_controls.handbrake && m_num_wheels_in_contact > 2) return;\r\n\t\r\n\tif (!m_controls.throttle && m_controls.steering != 0.0f && m_num_wheels_in_contact > 2) return;\r\n\t\r\n\tif (in_artificial_collision()) return;\r\n\t\r\n\t// apply quadtratic damping\r\n\t\r\n\t// quadratic damping in the air makes jump recovery much easier; the vehicle lands on its wheels much more often\r\n\tfloat quad_damping = m_time_step * m_quad_rotvel_damping * m_rotmom.LengthSqr();\r\n\t\r\n\t// prevent reversal\r\n\tif (quad_damping > m_rotmom.Length())\r\n\t{\r\n\t\tm_rotmom.Set(0.0f, 0.0f, 0.0f);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMth::Vector direction = m_rotmom;\r\n\t\tdirection.Normalize();\r\n\t\tm_rotmom -= quad_damping * direction;\r\n\t}\r\n\r\n\t// apply constant damping; only applied in the Y direction\r\n\t\r\n\t// apply only if we're not steering, we're on the ground, and we're relatively upright\r\n\tif (m_controls.steering == 0.0f && m_num_wheels_in_contact > 2 && m_orientation_matrix[Y][Y] > 0.5f)\r\n\t{\r\n\t\tfloat const_damping = m_time_step * m_const_rotvel_damping;;\r\n\t\t\r\n\t\t// prevent reversal\r\n\t\tif (Mth::Abs(const_damping) > Mth::Abs(m_rotmom[Y]))\r\n\t\t{\r\n\t\t\tm_rotmom[Y] = 0.0f;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_rotmom[Y] += (m_rotmom[Y] > 0.0f ? -const_damping : const_damping);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::accumulate_forces (   )\r\n{\r\n\t// forces and torques on the body accumulate and are applied at the end of the frame; torques on the wheels are too large to accumulate;\r\n\t// they are applied to wheel velocity as they occur; thus, the order of application of wheel torques is critical\r\n\t\r\n\tapply_gravitational_forces();\r\n\t\r\n\tapply_suspension_forces();\r\n\t\r\n    // we calculate the friction coefficients before applying engine torques so that friction will get the chance to counteract rotational\r\n\t// accelerations using static friction before the wheels spin out due to engine torque\r\n\tcalculate_friction_coefficients();\r\n\t\r\n\tif (!m_controls.handbrake)\r\n\t{\r\n\t\tapply_engine_forces();\r\n\t\t\r\n\t\tapply_drag_forces();\r\n\t\t\r\n\t\t// give the brakes a chance to cancel the rotation due to engine torque and to lock up the wheels before friction effects\r\n\t\tapply_brake_forces();\r\n\t\t\r\n\t\tapply_friction_forces();\r\n\t\t\r\n\t\t// after friction, the brakes are given the opportunity to apply additional torque and relock the wheels\r\n\t\tapply_spare_brake_forces();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (m_controls.throttle)\r\n\t\t{\r\n\t\t\tapply_engine_forces();\r\n\t\t\t\r\n            // scale the handbrake's braking effect with the steering factor; thus, you power through sharp handbrake turns; yet, the handbrake\r\n\t\t\t// still brakes on straight aways\r\n\t\t\tapply_handbrake_forces(1.0f - Mth::Abs(m_controls.steering));\r\n\r\n\t\t\tapply_friction_forces();\r\n\r\n\t\t\tapply_spare_brake_forces();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tapply_friction_forces();\r\n\t\t\t\r\n\t\t\t// lock wheels\r\n\t\t\tfor (int n = m_num_wheels; n--; )\r\n\t\t\t{\r\n\t\t\t\tmp_wheels[n].rotvel = 0.0f;\r\n\t\t\t\tmp_wheels[n].rotacc = 0.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::apply_gravitational_forces (   )\r\n{\r\n\t// use reduced gravity when flipping the car\r\n\tif (m_in_flip && Tmr::ElapsedTime(m_flip_start_time_stamp) > vVP_FLIP_DELAY)\r\n\t{\r\n\t\tm_force[Y] -= vVP_FLIP_GRAVITY_FACTOR * m_gravity_override_fraction * vVP_GRAVITATIONAL_ACCELERATION / m_inv_mass;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_force[Y] -= m_gravity_override_fraction * vVP_GRAVITATIONAL_ACCELERATION / m_inv_mass;\r\n\t}\r\n\t\r\n\t// we do our own force accumulation for this simple and constant force, having the same effect as the following code\r\n\t// Mth::Vector force(0.0f, -vVP_GRAVITATIONAL_ACCELERATION / m_inv_mass, 0.0f);\r\n\t// Mth::Vector location = m_suspension_center_of_mass;\r\n\t// accumulate_force(force, location, MAKE_RGB(50, 50, 0));\r\n\t\r\n\tif (m_draw_debug_lines)\r\n\t{\r\n\t\tGfx::AddDebugLine(m_pos, m_pos + 0.05f * Mth::Vector(0.0f, -vVP_GRAVITATIONAL_ACCELERATION / m_inv_mass, 0.0f), MAKE_RGB(50, 50, 0), MAKE_RGB(50, 50, 0), 1);\r\n\t}\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::apply_suspension_forces (   )\r\n{\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\t// if not in contact with the ground, y_offset == y_offset_hang\r\n\t\tif (wheel.state == SWheel::OUT_OF_CONTACT)\r\n\t\t{\r\n\t\t\t// set this frame's history to the default value to smooth out landings\r\n\t\t\twheel.normal_force_history[m_next_normal_force_history_idx] = vVP_GRAVITATIONAL_ACCELERATION / m_inv_mass / m_num_wheels;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\t// direction of the suspension line; commented version is slower but explicit\r\n\t\t// Mth::Vector direction = m_orientation_matrix.Rotate(Mth::Vector(0.0f, 1.0f, 0.0f));\r\n\t\tMth::Vector direction = m_orientation_matrix[Y];\r\n\t\t\r\n\t\t// magnitude of the spring force along the contact normal\r\n\t\tfloat magnitude = -wheel.spring * (wheel.y_offset_hang - wheel.y_offset) * Mth::DotProduct(wheel.contact_normal, direction);\r\n\t\t\r\n\t\t// velocity of the wheel projected into the contact normal direction\r\n\t\tfloat projected_vel = Mth::DotProduct(wheel.vel_world, wheel.contact_normal);\r\n\t\t\r\n\t\t// magnitude adjusted for damping\r\n\t\tmagnitude += -wheel.damping * projected_vel;\r\n\t\t\r\n\t\t// suspension force\r\n\t\tMth::Vector force = magnitude * wheel.contact_normal;\r\n\t\t\r\n\t\taccumulate_force(force, wheel.pos_world, MAKE_RGB(100, 100, 0));\r\n\t\t\r\n\t\t// set the normal force magnitude; used in the friction force code\r\n\t\t\r\n\t\twheel.normal_force_history[m_next_normal_force_history_idx] = magnitude;\r\n\t\t\r\n\t\twheel.normal_force = 0.0f;\r\n\t\tfor (int i = vVP_NORMAL_FORCE_HISTORY_LENGTH; i--; )\r\n\t\t{\r\n\t\t\twheel.normal_force += wheel.normal_force_history[i];\r\n\t\t}\r\n\t\twheel.normal_force /= vVP_NORMAL_FORCE_HISTORY_LENGTH;\r\n\t}\r\n\t\r\n\tm_next_normal_force_history_idx = ++m_next_normal_force_history_idx % vVP_NORMAL_FORCE_HISTORY_LENGTH;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::apply_friction_forces (   )\r\n{\r\n\t// NOTE: we've handled longitudinal friction reversal successfully; however, tangential friction reversal is still a significant issue for large\r\n\t// friction coefficients and high centers of mass\r\n\t\r\n\t// we use a simple tire model were the friction force is opposite the velocity of the tire contact and proportional to the normal force and a\r\n\t// friction coefficient; the friction coefficient is a function of the velocity of the contact with the following form:\r\n\t// 0 < v < min_static_velocity: rises linearly from zero to static_friction\r\n\t// min_static_velocity < v < max_static_velocity: constant at static_friction\r\n\t// max_static_velocity < v < min_dynamic_velocity: falls linearly from static_friction to dynamic_friction\r\n\t// min_dynamic_velocity < v: constant at dynamic_friction\r\n\t\r\n\t// NOTE: because friction is zero at zero slip velocity, hill slippage is an issue\r\n\t\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\tif (wheel.state == SWheel::OUT_OF_CONTACT) continue;\r\n\t\t\r\n\t\t// grab the cached wheel direction and velocity projected into the contact plane\r\n\t\tMth::Vector projected_wheel_direction = wheel.cache_projected_direction;\r\n\t\tMth::Vector projected_vel = wheel.cache_projected_vel;\r\n\t\t\r\n\t\t// subtract the contact patch velocity; positive wheel rotational velocity equals negative contact patch velocity\r\n\t\tprojected_vel -= wheel.rotvel * wheel.radius * projected_wheel_direction;\r\n\t\t\r\n\t\t// store the slip vel for later display\r\n\t\twheel.slip_vel = projected_vel.Length();\r\n\t\t\r\n\t\t// if the velocity is too small, its direction is meaningless\r\n\t\tif (wheel.slip_vel < 0.000001) continue;\r\n\t\t\r\n\t\t// propose a frictional force\r\n\t\tMth::Vector vel_direction = projected_vel;\r\n\t\tvel_direction.Normalize();\r\n\t\tMth::Vector proposed_force = -wheel.friction_coefficient * wheel.normal_force * vel_direction;\r\n\t\t\r\n\t\t// now we must check that this force is not more that the force which would stop the relative longitudinal velocity\r\n\t\t\r\n\t\t// calculate the torque required to stick the wheel contact patch to the ground\r\n\t\tfloat longitudinal_vel = Mth::DotProduct(projected_vel, projected_wheel_direction);\r\n\t\tfloat stopping_rotvel = longitudinal_vel / wheel.radius;\r\n\t\tfloat stopping_torque = -calculate_stopping_torque(wheel, stopping_rotvel);\r\n\t\t\r\n\t\t// calculate the proposed torque\r\n\t\tfloat proposed_torque = -wheel.radius * Mth::DotProduct(proposed_force, projected_wheel_direction);\r\n\t\t\r\n\t\tMth::Vector force;\r\n\t\tfloat torque;\r\n\t\t\r\n\t\t// if the proposed torque is less than what is required to stop the rotation\r\n\t\tif (Mth::Abs(proposed_torque) < Mth::Abs(stopping_torque))\r\n\t\t{\r\n\t\t\t// we're ok\r\n\t\t\tforce = proposed_force;\r\n\t\t\ttorque = proposed_torque;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// otherwise, reduce the proposed longitudinal force to only the stopping force\r\n\t\t\tfloat proposed_longitudinal_force = Mth::DotProduct(proposed_force, projected_wheel_direction);\r\n\t\t\tfloat stopping_longitudinal_force = -stopping_torque / wheel.radius;\r\n\t\t\tforce = proposed_force + (stopping_longitudinal_force - proposed_longitudinal_force) * projected_wheel_direction;\r\n\t\t\t\r\n\t\t\ttorque = stopping_torque;\r\n\t\t}\r\n\t\t\r\n\t\t// apply the force to the body\r\n\t\taccumulate_force(force, wheel.pos_world, MAKE_RGB(0, 0, 255));\r\n\t\t\r\n\t\t// apply the torque to the wheel\r\n\t\tapply_wheel_torque(wheel, torque);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::apply_drag_forces (   )\r\n{\r\n\tif (m_controls.throttle || m_controls.reverse || m_controls.brake) return;\r\n\t\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\tif (!wheel.drive || wheel.state == SWheel::OUT_OF_CONTACT) continue;\r\n\t\t\r\n\t\t// determine the effective engine gear\r\n\t\tint effective_gear = determine_effective_gear(Mth::Abs(wheel.rotvel));\r\n\t\t\r\n\t\t// drag torque scales like the square of the gear ratio\r\n\t\tfloat torque = m_engine.drag_torque * m_engine.p_gear_ratios[effective_gear] * m_engine.p_gear_ratios[effective_gear] / m_num_drive_wheels;\r\n\t\t\r\n\t\t// prevent reversal\r\n\t\tfloat maximum_torque = Mth::Abs(calculate_stopping_torque(wheel, wheel.rotvel));\r\n\t\tif (torque > maximum_torque)\r\n\t\t{\r\n\t\t\ttorque = maximum_torque;\r\n\t\t}\r\n\t\t\r\n\t\tapply_wheel_torque(wheel, wheel.rotvel < 0.0f ? torque : -torque);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::apply_engine_forces (   )\r\n{\r\n\t// NOTE: test\r\n\tfloat wall_climb_factor = Mth::ClampMax(m_orientation_matrix[Y][Y] * m_orientation_matrix[Y][Y] / 0.9f, 1.0f);\r\n\t\r\n\tif ((!m_controls.throttle && !m_controls.reverse) || m_controls.brake) return;\r\n\t\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\tif (!wheel.drive) continue;\r\n\t\t\r\n\t\t// turn off power to front wheels when power handbraking\r\n\t\tif (m_controls.handbrake && wheel.steering != SWheel::FIXED) continue;\r\n\t\t\r\n\t\t// determine effective engine gear\r\n\t\tint effective_gear;\r\n\t\tif (!m_controls.reverse)\r\n\t\t{\r\n\t\t\teffective_gear = determine_effective_gear(wheel.rotvel > 0.0f ? wheel.rotvel : 0.0f);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\teffective_gear = determine_effective_gear(wheel.rotvel < 0.0f ? -wheel.rotvel : 0.0f);\r\n\t\t}\r\n\t\t\r\n\t\tfloat torque = m_engine.drive_torque * m_engine.differential_ratio * m_engine.p_gear_ratios[effective_gear] / m_num_drive_wheels;\r\n\t\ttorque *= wall_climb_factor;\r\n\t\t\r\n\t\t// reverse gears are scaled down by a factor\r\n\t\tif (m_controls.reverse)\r\n\t\t{\r\n\t\t\ttorque *= -m_engine.reverse_torque_ratio;\r\n\t\t}\r\n\t\t\r\n\t\t// account for low of power in front wheels in four-wheel drive car when power handbraking\r\n\t\tif (m_controls.handbrake && m_num_drive_wheels == 4) torque *= 2.0f;\r\n\t\t\r\n\t\tapply_wheel_torque(wheel, torque);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::apply_brake_forces (   )\r\n{\r\n\tif (!m_controls.brake) return;\r\n\t\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\tfloat torque = wheel.brake.torque;\r\n\t\t\r\n\t\tfloat maximum_torque = Mth::Abs(calculate_stopping_torque(wheel, wheel.rotvel));\r\n\t\t\r\n\t\tif (torque > maximum_torque)\r\n\t\t{\r\n\t\t\twheel.brake.spare_torque = torque - maximum_torque;\r\n\t\t\ttorque = maximum_torque;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\twheel.brake.spare_torque = 0.0f;\r\n\t\t}\r\n\t\t\r\n\t\tapply_wheel_torque(wheel, wheel.rotvel < 0.0f ? torque : -torque);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::apply_handbrake_forces ( float application_factor )\r\n{\r\n\tDbg_Assert(m_controls.handbrake);\r\n\t\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\tfloat torque = application_factor * wheel.brake.handbrake_torque;\r\n\t\t\r\n\t\tfloat maximum_torque = Mth::Abs(calculate_stopping_torque(wheel, wheel.rotvel));\r\n\t\t\r\n\t\tif (torque > maximum_torque)\r\n\t\t{\r\n\t\t\twheel.brake.spare_torque = torque - maximum_torque;\r\n\t\t\ttorque = maximum_torque;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\twheel.brake.spare_torque = 0.0f;\r\n\t\t}\r\n\t\t\r\n\t\tapply_wheel_torque(wheel, wheel.rotvel < 0.0f ? torque : -torque);\r\n\t}\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::apply_spare_brake_forces (   )\r\n{\r\n\tif (!m_controls.brake) return;\r\n\t\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\r\n\t\tif (wheel.brake.spare_torque == 0.0f) continue;\r\n\t\t\r\n\t\tfloat torque = wheel.brake.spare_torque;\r\n\t\t\r\n\t\tfloat maximum_torque = Mth::Abs(calculate_stopping_torque(wheel, wheel.rotvel));\r\n\t\t\r\n\t\tif (torque > maximum_torque)\r\n\t\t{\r\n\t\t\ttorque = maximum_torque;\r\n\t\t}\r\n\t\t\r\n\t\tapply_wheel_torque(wheel, wheel.rotvel < 0.0f ? torque : -torque);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\r\nfloat CVehicleComponent::calculate_collision_depth ( const SCollisionPoint& collision_point, const SCollider& collider ) const\r\n{\r\n\tenum EDepthDirection\r\n\t{\r\n\t\tWITH_FIRST_EDGE, AGAINST_FIRST_EDGE, WITH_SECOND_EDGE, AGAINST_SECOND_EDGE\r\n\t};\r\n\t\r\n\t// calculate displacement from base corner\r\n\tMth::Vector displacement = collision_point.pos - collider.world.m_corner;\r\n\t\r\n\t// determine the minimum depth and correponding depth direction\r\n\t\r\n\tfloat min_depth = Mth::DotProduct(displacement, collider.first_edge_direction_world);\r\n\tEDepthDirection depth_direction = WITH_FIRST_EDGE;\r\n\t\r\n\tfloat depth = collider.first_edge_length - min_depth;\r\n\tif (depth < min_depth)\r\n\t{\r\n\t\tmin_depth = depth;\r\n\t\tdepth_direction = AGAINST_FIRST_EDGE;\r\n\t}\r\n\t\r\n\tdepth = Mth::DotProduct(displacement, collider.second_edge_direction_world);\r\n\tif (depth < min_depth)\r\n\t{\r\n\t\tmin_depth = depth;\r\n\t\tdepth_direction = WITH_SECOND_EDGE;\r\n\t}\r\n\t\r\n\tdepth = collider.second_edge_length - depth;\r\n\tif (depth < min_depth)\r\n\t{\r\n\t\tmin_depth = depth;\r\n\t\tdepth_direction = AGAINST_SECOND_EDGE;\r\n\t}\r\n\t\r\n\tif (min_depth < 0.01f)\r\n\t{\r\n\t\treturn 0.0f;\r\n\t}\r\n\t\r\n\tswitch (depth_direction)\r\n\t{\r\n\t\tcase WITH_FIRST_EDGE:\r\n\t\t\tdepth = min_depth / Mth::DotProduct(collider.first_edge_direction_world, collision_point.normal);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase AGAINST_FIRST_EDGE:\r\n\t\t\tdepth = -min_depth / Mth::DotProduct(collider.first_edge_direction_world, collision_point.normal);\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase WITH_SECOND_EDGE:\r\n\t\t\tdepth = min_depth / Mth::DotProduct(collider.second_edge_direction_world, collision_point.normal);\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase AGAINST_SECOND_EDGE:\r\n\t\t\tdepth = -min_depth / Mth::DotProduct(collider.second_edge_direction_world, collision_point.normal);\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\t#ifdef __USER_DAN__\r\n\tif (depth < 0.0f)\r\n\t{\r\n\t\tMESSAGE(\"negative depth bug\");\r\n\t}\r\n\t#endif\r\n\t\r\n\treturn depth;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\r\nbool CVehicleComponent::check_for_capping ( SCollisionPoint& collision_point, const CRectFeeler& rect_feeler, const SCollider& collider, int collision_line_idx, int collision_point_end_idx ) const\r\n{\r\n\t// check to see if this culled collision is the back of a cappable collision with a 2D object\r\n\tfor (int check_line_idx = rect_feeler.GetNumMergedCollisionSurfaces(); check_line_idx--; )\r\n\t{\r\n\t\tif (check_line_idx == collision_line_idx) continue;\r\n\t\t\r\n\t\tfor (int end = 2; end--; )\r\n\t\t{\r\n\t\t\tif (very_close(collision_point.pos, rect_feeler.GetMergedCollisionSurface(check_line_idx).ends[end].point)\r\n\t\t\t\t&& Mth::DotProduct(collision_point.normal, rect_feeler.GetMergedCollisionSurface(check_line_idx).normal) < -0.99)\r\n\t\t\t{\r\n\t\t\t\t// we'll use this point to cap the collision with the 2D object; the tangent cross the normal will point out of the triangle\r\n\t\t\t\tcollision_point.normal = Mth::CrossProduct(\r\n\t\t\t\t\trect_feeler.GetMergedCollisionSurface(collision_line_idx).ends[collision_point_end_idx].tangent,\r\n\t\t\t\t\tcollision_point.normal\r\n\t\t\t\t);\r\n\t\t\t\tcollision_point.depth = calculate_collision_depth(collision_point, collider);\r\n\t\t\t\t\r\n\t\t\t\tif (m_draw_debug_lines)\r\n\t\t\t\t{\r\n\t\t\t\t\tGfx::AddDebugLine(\r\n\t\t\t\t\t\tcollision_point.pos,\r\n\t\t\t\t\t\tcollision_point.pos + (72) * collision_point.normal,\r\n\t\t\t\t\t\tMAKE_RGB(255, 100, 255), MAKE_RGB(255, 100, 255), 1\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t} // END loop over checked collision line ends\r\n\t} // END loop over all other collision lines\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CVehicleComponent::consider_culling_point ( const SCollisionPoint& collision_point ) const\r\n{\r\n\t// cull collision points which have a normal direction along their body offset\r\n\t\r\n\tMth::Vector offset = collision_point.pos - m_pos;\r\n\tbool cull = Mth::DotProduct(offset, collision_point.normal) >= 0.0f;\r\n\tif (m_draw_debug_lines && cull)\r\n\t{\r\n\t\tuint32 c = MAKE_RGB(0, 0, 0);\r\n\t\tGfx::AddDebugLine(collision_point.pos, collision_point.pos + 48.0f * collision_point.normal, c, c, 1);\r\n\t}\r\n\treturn cull;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::apply_environment_collisions (   )\r\n{\r\n\tm_max_normal_collision_impulse = 0.0f;\r\n\t\r\n\tCRectFeeler rect_feeler;\r\n\tCLineFeeler line_feeler;\r\n\t\r\n\trect_feeler.SetCache(&m_collision_cache);\r\n\tline_feeler.SetCache(&m_collision_cache);\r\n\t\r\n\tm_num_collision_points = 0;\r\n\tfor (int collider_idx = vVP_NUM_COLLIDERS; collider_idx--; )\r\n\t{\r\n\t\tSCollider& collider = mp_colliders[collider_idx];\r\n\t\t\r\n\t\t// first we use a rectangular feeler\r\n\t\t\r\n\t\t// setup the feeler\r\n\t\trect_feeler.SetRectangle(collider.world);\r\n\t\t\r\n\t\t// detect collisions\r\n\t\tif (rect_feeler.GetCollision())\r\n\t\t{\r\n\t\t\ttrip_trigger(TRIGGER_BONK, rect_feeler);\r\n\t\t\tif (reset_this_frame()) return;\r\n\t\t\t\r\n\t\t\trect_feeler.MergeCollisionSurfaces();\r\n\t\t\t\r\n\t\t\t// copy out the collision points from the feeler output\r\n\t\t\tfor (int collision_line_idx = rect_feeler.GetNumMergedCollisionSurfaces(); collision_line_idx--; )\r\n\t\t\t{\r\n\t\t\t\tfor (int end = 2; end--; )\r\n\t\t\t\t{\r\n\t\t\t\t\t// add the collision line's start to the list of collision points\r\n\t\t\t\t\tSCollisionPoint& new_collision_point = sp_collision_points[m_num_collision_points];\r\n\t\t\t\t\t\r\n\t\t\t\t\tnew_collision_point.line = false;\r\n\t\t\t\t\t\r\n\t\t\t\t\tnew_collision_point.pos = rect_feeler.GetMergedCollisionSurface(collision_line_idx).ends[end].point;\r\n\t\t\t\t\tnew_collision_point.normal = rect_feeler.GetMergedCollisionSurface(collision_line_idx).normal;\r\n\t\t\t\t\tif (!consider_culling_point(new_collision_point))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// if this is a keeper, calculate the collision depth\r\n\t\t\t\t\t\tif (rect_feeler.GetMergedCollisionSurface(collision_line_idx).ends[end].tangent_exists)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnew_collision_point.depth = calculate_collision_depth(new_collision_point, collider);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnew_collision_point.depth = 0.0f;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tm_num_collision_points++;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if (rect_feeler.GetMergedCollisionSurface(collision_line_idx).ends[end].tangent_exists)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (check_for_capping(new_collision_point, rect_feeler, collider, collision_line_idx, end))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tm_num_collision_points++;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t} // END loop over collision line ends\r\n\t\t\t} // END loop over collision surfaces\r\n\t\t} // END if we had a collision this collider\r\n    \r\n\t\tif (m_draw_debug_lines)\r\n\t\t{\r\n\t\t\trect_feeler.DebugLines(255, 255, 255, 1);\r\n\t\t}\r\n\t\t\r\n\t\t// line feelers\r\n\r\n\t\tline_feeler.m_start = m_pos;\r\n\r\n\t\tline_feeler.m_end = rect_feeler.m_corner;\r\n\t\tif (line_feeler.GetCollision(false))\r\n\t\t{\r\n\t\t\ttrip_trigger(TRIGGER_BONK, line_feeler);\r\n\t\t\tif (reset_this_frame()) return;\r\n\t\t\t\r\n\t\t\tsp_collision_points[m_num_collision_points].pos = line_feeler.GetPoint();\r\n\t\t\tsp_collision_points[m_num_collision_points].normal = line_feeler.GetNormal();\r\n\t\t\tif (!consider_culling_point(sp_collision_points[m_num_collision_points]))\r\n\t\t\t{\r\n\t\t\t\tsp_collision_points[m_num_collision_points].depth = calculate_collision_depth(line_feeler);\r\n\t\t\t\tm_num_collision_points++;\r\n\t\t\t\tsp_collision_points[m_num_collision_points].line = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (m_draw_debug_lines)\r\n\t\t{\r\n\t\t\tline_feeler.DebugLine(255, 255, 255, 1);\r\n\t\t}\r\n\r\n\r\n\t\tline_feeler.m_end += rect_feeler.m_first_edge;\r\n\t\tif (line_feeler.GetCollision(false))\r\n\t\t{\r\n\t\t\ttrip_trigger(TRIGGER_BONK, line_feeler);\r\n\t\t\tif (reset_this_frame()) return;\r\n\t\t\t\r\n\t\t\tsp_collision_points[m_num_collision_points].pos = line_feeler.GetPoint();\r\n\t\t\tsp_collision_points[m_num_collision_points].normal = line_feeler.GetNormal();\r\n\t\t\tif (!consider_culling_point(sp_collision_points[m_num_collision_points]))\r\n\t\t\t{\r\n\t\t\t\tsp_collision_points[m_num_collision_points].depth = calculate_collision_depth(line_feeler);\r\n\t\t\t\tm_num_collision_points++;\r\n\t\t\t\tsp_collision_points[m_num_collision_points].line = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (m_draw_debug_lines)\r\n\t\t{\r\n\t\t\tline_feeler.DebugLine(255, 255, 255, 1);\r\n\t\t}\r\n\r\n\t\tline_feeler.m_end += rect_feeler.m_second_edge;\r\n\t\tif (line_feeler.GetCollision(false))\r\n\t\t{\r\n\t\t\ttrip_trigger(TRIGGER_BONK, line_feeler);\r\n\t\t\tif (reset_this_frame()) return;\r\n\t\t\t\r\n\t\t\tsp_collision_points[m_num_collision_points].pos = line_feeler.GetPoint();\r\n\t\t\tsp_collision_points[m_num_collision_points].normal = line_feeler.GetNormal();\r\n\t\t\tif (!consider_culling_point(sp_collision_points[m_num_collision_points]))\r\n\t\t\t{\r\n\t\t\t\tsp_collision_points[m_num_collision_points].depth = calculate_collision_depth(line_feeler);\r\n\t\t\t\tm_num_collision_points++;\r\n\t\t\t\tsp_collision_points[m_num_collision_points].line = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (m_draw_debug_lines)\r\n\t\t{\r\n\t\t\tline_feeler.DebugLine(255, 255, 255, 1);\r\n\t\t}\r\n\r\n\t\tline_feeler.m_end -= rect_feeler.m_first_edge;\r\n\t\tif (line_feeler.GetCollision(false))\r\n\t\t{\r\n\t\t\ttrip_trigger(TRIGGER_BONK, line_feeler);\r\n\t\t\tif (reset_this_frame()) return;\r\n\t\t\t\r\n\t\t\tsp_collision_points[m_num_collision_points].pos = line_feeler.GetPoint();\r\n\t\t\tsp_collision_points[m_num_collision_points].normal = line_feeler.GetNormal();\r\n\t\t\tif (!consider_culling_point(sp_collision_points[m_num_collision_points]))\r\n\t\t\t{\r\n\t\t\t\tsp_collision_points[m_num_collision_points].depth = calculate_collision_depth(line_feeler);\r\n\t\t\t\tm_num_collision_points++;\r\n\t\t\t\tsp_collision_points[m_num_collision_points].line = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (m_draw_debug_lines)\r\n\t\t{\r\n\t\t\tline_feeler.DebugLine(255, 255, 255, 1);\r\n\t\t}\r\n\t} // END loop over colliders\r\n\t\r\n\tif (m_num_collision_points == 0) return;\r\n\t\r\n\t// zero accumulators\r\n\tfor (int collision_idx = m_num_collision_points; collision_idx--; )\r\n\t{\r\n\t\tsp_collision_points[collision_idx].normal_impulse = 0.0f;\r\n\t}\r\n\t\r\n\t// cache the momentums and velocities before normal impulses are applied; they are used when determining the frictional forces\r\n\tMth::Vector cache_mom = m_mom;\r\n\tMth::Vector cache_rotmom = m_rotmom;\r\n\tMth::Vector cache_vel = m_vel;\r\n\tMth::Vector cache_rotvel = m_rotvel;\r\n\t\r\n\t// apply normal impulses\r\n\t\r\n\t// loop over normal impulse points until all collisions are fully resolved\r\n\tint pass_count = 0;\r\n\tbool clean_pass;\r\n\tdo\r\n\t{\r\n\t\tclean_pass = true;\r\n\t\t\r\n\t\tfor (int collision_idx = m_num_collision_points; collision_idx--; )\r\n\t\t{\r\n\t\t\tSCollisionPoint& collision = sp_collision_points[collision_idx];\r\n\t\t\t\r\n\t\t\t// calculate the collision position in body space\r\n\t\t\tMth::Vector pos_local = collision.pos - m_pos;\r\n\t\t\t\r\n\t\t\t// calculate the velocity and normal velocity of the collision point\r\n\t\t\tMth::Vector vel = calculate_body_point_velocity(pos_local);\r\n\t\t\tfloat normal_vel = Mth::DotProduct(vel, collision.normal);\r\n\t\t\t\r\n\t\t\t// ignore if we're not impacting\r\n\t\t\tif (normal_vel > 0.0f) continue;\r\n\t\t\tclean_pass = false;\r\n\t\t\t\r\n\t\t\t// calculate the goal velocity of the collision\r\n\t\t\tfloat goal_normal_velocity = -m_body_restitution * normal_vel;\r\n\t\t\t\r\n\t\t\t// calculate the effective mass of the collision point\r\n\t\t\tfloat effective_mass = calculate_body_point_effective_mass(pos_local, collision.normal);\r\n\t\t\t\r\n\t\t\t// calculate the normal impulse required to reach the body velocity\r\n\t\t\tfloat normal_impulse = (goal_normal_velocity - normal_vel) * effective_mass;\r\n\t\t\t\r\n\t\t\t// accumulate the total normal impulse applied to this collision point\r\n\t\t\tcollision.normal_impulse += normal_impulse;\r\n\t\t\t\r\n\t\t\t// setup the required impulse vector\r\n\t\t\tMth::Vector impulse = normal_impulse * collision.normal;\r\n\t\t\t\r\n\t\t\t// apply the normal impulse immediately\r\n\t\t\tapply_impulse(impulse, pos_local);\r\n\t\t}\r\n\r\n\t\tif (++pass_count > 5)\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tMESSAGE(\"environment collision resolution pass count limit exceeded\");\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t\t}\r\n\t} while (!clean_pass);\r\n\t\r\n    if (m_draw_debug_lines)\r\n\t{\r\n\t\tfor (int collision_idx = m_num_collision_points; collision_idx--; )\r\n\t\t{\r\n\t\t\t// SCollisionPoint& collision = sp_collision_points[collision_idx];\r\n\t\t\t// Gfx::AddDebugLine(\r\n\t\t\t\t// collision.pos + collision.normal,\r\n\t\t\t\t// collision.pos + collision.normal + collision.normal_impulse / 2.0f * collision.normal,\r\n\t\t\t\t// MAKE_RGB(0, 100, 100), MAKE_RGB(0, 100, 100), 1\r\n\t\t\t// );\r\n\t\t}\r\n\t} // END loop over collision points\r\n\r\n\t// apply penalty forces to prevent interpenetration\r\n\tfor (int collision_idx = m_num_collision_points; collision_idx--; )\r\n\t{\r\n\t\tSCollisionPoint& collision = sp_collision_points[collision_idx];\r\n\t\t\r\n\t\t// collision normal is facing opposite the depth\r\n\t\t// BUG: too many rect feeler collisions have negative depth!!!\r\n\t\tif (collision.depth <= 0.0f) continue;\r\n\t\t\r\n\t\t// extremely deep collisions are mostly collisions with the underbody which are actually shallow in the Y direction; for now we'll cap such\r\n\t\t// collisions and perhaps allow the car to sink down into geometry which comes from below but misses the wheels\r\n\t\tif (collision.depth > 2.0f)\r\n\t\t{\r\n\t\t\tcollision.depth = 2.0f;\r\n\t\t}\r\n\t\t\r\n\t\tMth::Vector force = m_body_spring * collision.depth * collision.normal;\r\n\t\t\r\n\t\taccumulate_collision_force(force, collision.pos - m_pos);\r\n\t\t\r\n\t\t// Gfx::AddDebugLine(\r\n\t\t\t// collision.pos,\r\n\t\t\t// collision.pos + (2 * collision.depth) * collision.normal,\r\n\t\t\t// MAKE_RGB(255, 255, 0), MAKE_RGB(255, 255, 0), 1\r\n\t\t// );\r\n\t}\r\n\t\r\n\tfloat body_friction = m_orientation_matrix[Y][Y] > 0.707f ? m_body_friction : m_body_wipeout_friction;\r\n\t\r\n\t// apply a friction impulse at each point\r\n\tfor (int collision_idx = m_num_collision_points; collision_idx--; )\r\n\t{\r\n\t\tSCollisionPoint& collision = sp_collision_points[collision_idx];\r\n\t\t\r\n\t\tif (collision.normal_impulse == 0.0f) continue;\r\n\t\t\r\n\t\t// calculate the local collision position\r\n\t\tMth::Vector pos_local = collision.pos - m_pos;\r\n\t\t\r\n\t\t// calculate the tangential velocity\r\n\t\tMth::Vector\tvel = cache_vel + Mth::CrossProduct(cache_rotvel, pos_local);\r\n\t\tMth::Vector tanjent = vel - Mth::DotProduct(vel, collision.normal) * collision.normal;\r\n\t\tfloat tanjent_vel = tanjent.Length();\r\n\t\tif (tanjent_vel < 0.001f) continue;\r\n\t\ttanjent /= tanjent_vel;\r\n\t\t\r\n\t\t// calculate the effective mass of the collision point\r\n\t\tfloat effective_mass = calculate_body_point_effective_mass(pos_local, tanjent);\r\n\t\t\r\n\t\t// calculate the tanjential impulse required to stop the tanjential velocity\r\n\t\tfloat tanjent_impulse = tanjent_vel * effective_mass;\r\n\t\t\r\n\t\t// cap the frictional force at the normal force times the coefficient of friction\r\n\t\tfloat max_tanjent_impulse = body_friction * collision.normal_impulse;\r\n\t\t\r\n\t\tif (tanjent_impulse > max_tanjent_impulse)\r\n\t\t{\r\n\t\t\ttanjent_impulse = max_tanjent_impulse;\r\n\t\t}\r\n\t\t\r\n\t\t// setup the tanjent impulse vector\r\n\t\tMth::Vector impulse = -tanjent_impulse * tanjent;\r\n\t\t\r\n\t\t// apply the friction impulse to the true state\r\n\t\tapply_impulse(impulse, pos_local);\r\n\t\t\r\n\t\tif (m_draw_debug_lines)\r\n\t\t{\r\n\t\t\t// Gfx::AddDebugLine(\r\n\t\t\t\t// collision.pos + collision.normal,\r\n\t\t\t\t// collision.pos + collision.normal + impulse / 2.0f,\r\n\t\t\t\t// MAKE_RGB(100, 0, 100), MAKE_RGB(100, 0, 100), 1\r\n\t\t\t// );\r\n\t\t}\r\n\t\t\r\n\t\t// apply the friction impulse to the state we are using for friction calculations\r\n\t\tcache_mom += impulse;\r\n\t\tcache_rotmom += Mth::CrossProduct(pos_local, impulse);\r\n\t\tcache_vel = m_inv_mass * cache_mom;\r\n\t\tcache_rotvel = m_inv_moment.Rotate(cache_rotmom);\r\n\t} // END loop over collision points\r\n\t\r\n\t// determine the maximum normal impulse this frame\r\n\tfor (int collision_idx = m_num_collision_points; collision_idx--; )\r\n\t{\r\n\t\tSCollisionPoint& collision = sp_collision_points[collision_idx];\r\n\t\t\r\n\t\tm_max_normal_collision_impulse = Mth::Max(collision.normal_impulse, m_max_normal_collision_impulse);\r\n\t}\r\n\t\r\n\t// no player controlled impulses in the air\tor with handbrake on\r\n\tif (m_controls.steering == 0.0f || m_num_wheels_in_contact < 3 || m_controls.handbrake) return;\r\n\t\r\n\t// extra player controled collision impulse; allows one slight control over the direction on collision impulses\r\n\tfor (int collision_idx = m_num_collision_points; collision_idx--; )\r\n\t{\r\n\t\tSCollisionPoint& collision = sp_collision_points[collision_idx];\r\n\t\t\t\t\r\n\t\tMth::Vector pos_local = collision.pos - m_pos;\r\n\t\t\r\n\t\tfloat strength = m_controls.steering * m_collision_control * Mth::DotProduct(m_orientation_matrix[Z], collision.normal) * collision.normal_impulse;\r\n\t\t\r\n\t\tMth::Vector direction(-collision.normal[Z], 0.0f, collision.normal[X]);\r\n\t\t\r\n\t\tapply_impulse(strength * direction, pos_local);\r\n\t\t\r\n\t\tif (m_draw_debug_lines)\t  \r\n\t\t{\r\n\t\t\tGfx::AddDebugLine(\r\n\t\t\t\tcollision.pos + collision.normal,\r\n\t\t\t\tcollision.pos + collision.normal + strength * direction / 5.0f,\r\n\t\t\t\tMAKE_RGB(255, 0, 100), MAKE_RGB(255, 0, 100), 1\r\n\t\t\t);\r\n\t\t}\r\n\t}\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::update_pos_with_uber_frig ( const Mth::Vector& movement )\r\n{\r\n\t// The vehicle has two uber frigs.  The first treats the c.o.m. as a point particle with respect to the geo.  The seconds is a traditional uber frig.\r\n\t\r\n\tMth::Vector frame_start_pos = m_pos;\r\n\t\r\n\t// look for collisions along the origin's movement; only do a single bounce, assuming the remaining movement is ok\r\n\tCFeeler feeler(m_pos, m_pos + movement);\r\n\tif (feeler.GetCollision(false))\r\n\t{\r\n\t\t// bounce off the surface\r\n\t\tMESSAGE(\"less than uber frig\");\r\n\t\t\r\n\t\tm_pos = feeler.GetPoint() + feeler.GetNormal();\r\n\t\t\r\n\t\tMth::Vector remaining_movement = feeler.GetDist() * movement;\r\n\t\tremaining_movement -= 2.0f * Mth::DotProduct(remaining_movement, feeler.GetNormal()) * feeler.GetNormal();\r\n\t\tm_pos += remaining_movement;\r\n\t\t\r\n\t\t// use coeff of restit of 0.5\r\n\t\tm_mom -= 1.5f * Mth::DotProduct(m_mom, feeler.GetNormal()) * feeler.GetNormal();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_pos += movement;\r\n\t}\r\n\t\r\n\t// now, a traditional uber frig\r\n\tfeeler.m_start = m_pos;\r\n\tfeeler.m_end = feeler.m_start;\r\n\tfeeler.m_end[Y] -= FEET(400.0f);\r\n\tif (!feeler.GetCollision(false))\r\n\t{\r\n\t\tMESSAGE(\"uber frig\");\r\n\t\tm_pos = frame_start_pos;\r\n\t\tm_mom *= 1.0f;\r\n\t\tm_rotmom *= 1.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_model_component->ApplyLightingFromCollision(feeler);\r\n\t}\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::slerp_to_face_velocity (  )\r\n{\r\n\t// slerp to face our velocity\r\n\t\r\n\tif (m_in_flip) return;\r\n\t\r\n\tif (in_artificial_collision()) return;\r\n\t\r\n\t// only slerp if horizontal velocity is below a given threshold\r\n\tbool vel_below_threshold = m_vel[X] * m_vel[X] + m_vel[Z] * m_vel[Z] < m_in_air_slerp_vel_cutoff * m_in_air_slerp_vel_cutoff;\r\n\tif (vel_below_threshold && !m_vert_correction) return;\r\n\r\n\t// extract the current orientation matrix\r\n\tm_orientation.GetMatrix(m_orientation_matrix);\r\n\tm_orientation_matrix[W].Set();\r\n\r\n\t// construct our target matrix\r\n\tMth::Matrix target;\r\n\tif (vel_below_threshold)\r\n\t{\r\n\t\ttarget[Z] = m_orientation_matrix[Z];\r\n\t\ttarget[Z][Y] = 0.0f;\r\n\t\ttarget[Z].Normalize();\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttarget[Z] = m_vel;\r\n\t\ttarget[Z].Normalize();\r\n\t}\r\n\tif (Mth::DotProduct(target[Z], m_orientation_matrix[Z]) < 0.0f)\r\n\t{\r\n\t\ttarget[Z] *= -1.0f;\r\n\t}\r\n\ttarget[Y].Set(0.0f, 1.0f, 0.0f);\r\n\ttarget[X] = Mth::CrossProduct(target[Y], target[Z]);\r\n\ttarget[Y] = Mth::CrossProduct(target[Z], target[X]);\r\n\ttarget[W].Set();\r\n\r\n\t// setup the slerp\r\n\tMth::SlerpInterpolator slerper;\r\n\tslerper.setMatrices(&m_orientation_matrix, &target);\r\n\r\n\t// lerp up to full strength over time\r\n\tif (m_vel[X] * m_vel[X] + m_vel[Z] * m_vel[Z] > 350.0f * 350.0f)\r\n\t{\r\n\t\tslerper.getMatrix(&m_orientation_matrix, Mth::LinearMap(\r\n\t\t\t0.0f,\r\n\t\t\tm_in_air_slerp_strength * m_time_step,\r\n\t\t\tMth::Min(m_air_time_no_collision, m_in_air_slerp_time_delay),\r\n\t\t\t0.0f,\r\n\t\t\tm_in_air_slerp_time_delay\r\n\t\t));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tslerper.getMatrix(&m_orientation_matrix, Mth::LinearMap(\r\n\t\t\t0.0f,\r\n\t\t\t0.3f * m_in_air_slerp_strength * m_time_step,\r\n\t\t\tMth::Min(m_air_time_no_collision, m_in_air_slerp_time_delay),\r\n\t\t\t0.0f,\r\n\t\t\tm_in_air_slerp_time_delay\r\n\t\t));\r\n\t}\r\n\tm_orientation = m_orientation_matrix;\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CVehicleComponent::calculate_body_point_effective_mass ( const Mth::Vector& pos, const Mth::Vector& direction ) const\r\n{\r\n\t// calculate the effect on momentums due to a unit impulse applied at pos towards direction\r\n\tMth::Vector delta_mom = direction;\r\n\tMth::Vector delta_rotmom = Mth::CrossProduct(pos, direction);\r\n\t\r\n\t// calculate the resulting change in velocities\r\n\tMth::Vector delta_vel = m_inv_mass * delta_mom;\r\n\tMth::Vector delta_rotvel = m_inv_moment.Rotate(delta_rotmom);\r\n\t\r\n\t// calculate the corresponding change in the body point's velocity\r\n\tMth::Vector delta_vel_body_point = delta_vel + Mth::CrossProduct(delta_rotvel, pos);\r\n\t\r\n\t// extract the change in velocity along the direction of interest\r\n\tfloat delta_vel_direction = Mth::DotProduct(direction, delta_vel_body_point);\r\n\t\r\n\t// return the effective mass of the body point in the direction of interest\r\n\tDbg_Assert(delta_vel_direction != 0.0f);\r\n\treturn 1.0f / delta_vel_direction;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::consider_sleeping (   )\r\n{\r\n\tint last_consider_sleeping_count = m_consider_sleeping_count;\r\n\tm_consider_sleeping_count = 0;\r\n\t\r\n\tif (m_controls.throttle) return;\r\n\t\r\n\tif (m_controls.reverse && m_num_wheels_in_contact != 0) return;\r\n\t\r\n\t// only sleep if we're experiencing three or more collisions; hopefully, a surface-to-surface contact\r\n\tif (m_num_wheels_in_contact + m_num_collision_points < 3) return;\r\n\t\r\n\t// only sleep if we've got four-on-the-floor or are completely flipped\r\n\tif (m_num_wheels_in_contact != 0 && m_num_wheels_in_contact != m_num_wheels) return;\r\n\r\n\t// only sleep if we're moving slow\r\n\tif (m_vel.LengthSqr() > Mth::Sqr(vVP_SLEEP_VEL)) return;\r\n\t#ifdef __USER_DAN__\r\n\tDUMPF(m_vel.Length());\r\n\t#endif\r\n\r\n\t// only sleep if we're moving slow\r\n\tif (m_rotvel.LengthSqr() > Mth::Sqr(vVP_SLEEP_ROTVEL)) return;\r\n\t#ifdef __USER_DAN__\r\n\tDUMPF(m_rotvel.Length());\r\n\t#endif\r\n\t\r\n\t// never sleep during an artificial collision period\r\n\tif (in_artificial_collision()) return;\r\n\t\r\n\tm_consider_sleeping_count = last_consider_sleeping_count + 1;\r\n\tif (m_consider_sleeping_count < 3)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// sleep\r\n\tm_mom.Set();\r\n\tm_rotmom.Set();\r\n\tm_force.Set(0.0f, 0.0f, 0.0f);\r\n\tm_torque.Set(0.0f, 0.0f, 0.0f);\r\n\tfor (int n = m_num_wheels; n--; )\r\n\t{\r\n\t\tmp_wheels[n].rotacc = 0.0f;\r\n\t}\r\n\tm_state = ASLEEP;\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::get_input (   )\r\n{\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\r\n\t// analog control\r\n\t// m_controls.steering = control_pad.m_scaled_leftX;\r\n\tm_controls.steering = control_pad.m_scaled_leftX * Mth::Abs(control_pad.m_scaled_leftX);\r\n\t\r\n\t// dpad control\r\n\tif (m_controls.steering == 0.0f)\r\n\t{\r\n\t\tif (control_pad.m_left.GetPressed() && !control_pad.m_right.GetPressed())\r\n\t\t{\r\n\t\t\tm_controls.steering = -1.0f;\r\n\t\t}\r\n\t\telse if (control_pad.m_right.GetPressed() && !control_pad.m_left.GetPressed())\r\n\t\t{\r\n\t\t\tm_controls.steering = 1.0f;\r\n\t\t}\r\n\t}\r\n\t\r\n\tm_controls.throttle = control_pad.m_x.GetPressed();\r\n\tm_controls.handbrake = control_pad.m_R1.GetPressed() && !m_no_handbrake;\r\n\t\r\n\tbool brake_pressed = control_pad.m_square.GetPressed() || (m_exitable && control_pad.m_triangle.GetPressed());\r\n\tbool exit_request = brake_pressed && !control_pad.m_square.GetPressed();\r\n\t\r\n\t// decide between brake and reverse\r\n\tif (brake_pressed)\r\n\t{\r\n\t\tif ((m_controls.reverse || (Mth::DotProduct(m_vel, m_orientation_matrix[Z]) < 300.0f && m_num_wheels_in_contact != 0))\r\n\t\t\t&& (m_state != ASLEEP || m_num_wheels_in_contact != 0))\r\n\t\t{\r\n\t\t\t// reverse\r\n\t\t\tm_controls.reverse = true;\r\n\t\t\tm_controls.brake = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// brake\r\n\t\t\tm_controls.brake = true;\r\n\t\t\tm_controls.reverse = false;\r\n\t\t}\r\n\t\t\r\n\t\tif (exit_request)\r\n\t\t{\r\n\t\t\tif (Mth::DotProduct(m_vel, m_orientation_matrix[Z]) < 0.0f)\r\n\t\t\t{\r\n\t\t\t\t// brake\r\n\t\t\t\tm_controls.brake = true;\r\n\t\t\t\tm_controls.reverse = false;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (Mth::Abs(Mth::DotProduct(m_vel, m_orientation_matrix[Z])) < 30.0f)\r\n\t\t\t{\r\n\t\t\t\t// signal an exit\r\n\t\t\t\tGetObject()->BroadcastEvent(CRCD(0xcbaa3476, \"ExitVehicleRequest\"));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_controls.reverse = false;\r\n\t\tm_controls.brake = false;\r\n\t}\r\n\t\r\n\tif (m_force_brake)\r\n\t{\r\n\t\tm_controls.brake = true;\r\n\t\tm_controls.reverse = false;\r\n\t}\r\n\t\r\n\tif (m_state == ASLEEP && (m_controls.throttle || m_controls.reverse))\r\n\t{\r\n\t\tm_state = AWAKE;\r\n\t\tm_consider_sleeping_count = 0;\r\n\t}\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::zero_input (   )\r\n{\r\n\tm_controls.brake = false;\r\n\tm_controls.handbrake = false;\r\n\tm_controls.throttle = false;\r\n\tm_controls.reverse = false;\r\n\tm_controls.steering = 0.0f;\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::update_skeleton (   )\r\n{\r\n\tMth::Matrix* p_matrices = mp_skeleton_component->GetSkeleton()->GetMatrices();\r\n\tfor (int i = mp_skeleton_component->GetSkeleton()->GetNumBones(); i--; )\r\n\t{\r\n\t\tMth::Matrix& matrix = p_matrices[i];\r\n\t\t\r\n\t\t// setup the matrix for each bone in the skeleton\r\n\t\t\r\n\t\tif (m_draw_debug_lines == 2)\r\n\t\t{\r\n\t\t\tmatrix.Zero();\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\t// shadow\r\n\t\tif (i == 0)\r\n\t\t{\r\n\t\t\tmatrix.Zero();\r\n\t\t}\r\n\t\t\r\n\t\t// body\r\n\t\telse if (i == 1)\r\n\t\t{\r\n\t\t\tmatrix.Zero();\r\n\t\t\tmatrix[X][X] = 1.0f;\r\n\t\t\tmatrix[Y][Z] = -1.0f;\r\n\t\t\tmatrix[Z][Y] = 1.0f;\r\n\t\t\tmatrix[W] = m_body_pos;\r\n\t\t}\r\n\t\t\r\n\t\t// wheel\r\n\t\telse\r\n\t\t{\r\n\t\t\tSWheel& wheel = mp_wheels[i - 2];\r\n\t\t\t\r\n\t\t\tmatrix.Zero();\r\n\t\t\tmatrix[X][X] = -1.0f;\r\n\t\t\tmatrix[Y][Z] = 1.0f;\r\n\t\t\tmatrix[Z][Y] = 1.0f;\r\n\t\t\t\r\n\t\t\tmatrix.RotateZLocal(wheel.steering_angle_display);\r\n\t\t\tmatrix.RotateXLocal(-wheel.orientation);\r\n\t\t\tmatrix[W] = wheel.pos;\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tif (Script::GetInteger(\"use_max_y_offset\"))\r\n\t\t\t{\r\n\t\t\t\tmatrix[W][Y] += wheel.max_draw_y_offset;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmatrix[W][Y] += Mth::ClampMax(wheel.y_offset, wheel.max_draw_y_offset);\r\n\t\t\t}\r\n\t\t\t#else\r\n\t\t\tmatrix[W][Y] += Mth::ClampMax(wheel.y_offset, wheel.max_draw_y_offset);\r\n\t\t\t#endif\r\n\t\t\tmatrix[W][W] = 1.0f;\r\n\t\t}\r\n\t}\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::draw_shadow (   )\r\n{\r\n\t//Dbg_Message(\"Drawing shadow for car\");\r\n\r\n#if 0\t// Experiment to draw a shadow using texture splats\r\n\tMth::Vector start_pos = GetObject()->GetPos();\r\n\tMth::Vector end_pos = start_pos;\r\n\tstart_pos[Y] += 12.0f;\r\n\tend_pos[Y] -= 120.0f;\r\n\r\n\tfloat y_rot = 360.0f - m_orientation.GetVector()[Y];\r\n\twhile (y_rot < 0.0f)\r\n\t\ty_rot += 360.0f;\r\n\r\n\tNx::TextureSplat( start_pos, end_pos, 120.0f, 100.0f, 2.0f / (float) Config::FPS(), \"blood_01\", y_rot);\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::control_skater (   )\r\n{\r\n    // HACKY; setup the skater's position, orientation, and animation each frame\r\n\t\r\n    mp_skater->SetPos(GetObject()->GetPos() + GetObject()->GetMatrix().Rotate(m_skater_pos));\r\n\tmp_skater->SetMatrix(GetObject()->GetMatrix());\r\n\tmp_skater_core_physics_component->ResetLerpingMatrix();\r\n\tmp_skater->SetVel(GetObject()->GetVel());\r\n\t\r\n\tif (!m_skater_visible) return;\r\n\t\r\n\tfloat target_time = Mth::LinearMap(\r\n\t\t0.0f,\r\n\t\tmp_skater_animation_component->AnimDuration(m_skater_anim),\r\n\t\tmp_skater_core_physics_component->GetFlag(FLIPPED) ? m_steering_display : -m_steering_display,\r\n\t\t-1.0f,\r\n\t\t1.0f\r\n\t);\r\n\t\r\n\tif (!GameNet::Manager::Instance()->InNetGame())\r\n\t{\r\n\t\tmp_skater_animation_component->PlayPrimarySequence(m_skater_anim, false, target_time, 1000.0f, Gfx::LOOPING_CYCLE, 0.0f, 0.0f);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// HACK to reduce number of animation events when driving cars\r\n\t\tstatic int anim_send_count = 0;\r\n\t\tif (++anim_send_count == 15)\r\n\t\t{\r\n\t\t\tanim_send_count = 0;\r\n\t\t\tmp_skater_animation_component->PlayPrimarySequence(m_skater_anim, true, target_time, 1000.0f, Gfx::LOOPING_CYCLE, 0.0f, 0.0f);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_skater_animation_component->PlayPrimarySequence(m_skater_anim, false, target_time, 1000.0f, Gfx::LOOPING_CYCLE, 0.0f, 0.0f);\r\n\t\t}\r\n\t}\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst int num_edges = 12;\r\n\r\nMth::Vector CVehicleComponent::wheel_point ( const SWheel& wheel, int i, bool side ) const\r\n{\r\n\tMth::Vector point(\r\n\t\t(side ? 1.0f : -1.0f) * 3.85f,\r\n\t\twheel.radius * cosf(2.0f * 3.141592f * i / num_edges + wheel.orientation),\r\n\t\twheel.radius * sinf(2.0f * 3.141592f * i / num_edges + wheel.orientation)\r\n\t);\r\n\tMth::Matrix steering_rotation(Mth::Vector(0.0f, 1.0f, 0.0f), wheel.steering_angle);\r\n\tpoint = steering_rotation.Rotate(point);\r\n\tpoint[Y] += wheel.y_offset;\r\n\tpoint += wheel.pos;\r\n\tpoint = m_pos + m_orientation_matrix.Rotate(point);\r\n\treturn point;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CVehicleComponent::draw_debug_rendering (   ) const\r\n{\r\n\tif (m_draw_debug_lines)\r\n\t{\r\n\t\tfor (int n = m_num_wheels; n--; )\r\n\t\t{\r\n\t\t\tSWheel& wheel = mp_wheels[n];\r\n\t\t\t\r\n\t\t\tint32 color = 0;\r\n\t\t\tswitch (wheel.state)\r\n\t\t\t{\r\n\t\t\t\tcase SWheel::UNDER_GRIPPING:\r\n\t\t\t\t\tcolor = MAKE_RGB(0, 255, 0);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SWheel::GRIPPING:\r\n\t\t\t\t\tcolor = MAKE_RGB(0, 0, 0);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SWheel::SLIPPING:\r\n\t\t\t\t\tcolor = MAKE_RGB(255, 200, 0);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SWheel::SKIDDING:\r\n\t\t\t\t\tcolor = MAKE_RGB(255, 0, 0);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SWheel::HANDBRAKE_THROTTLE:\r\n\t\t\t\t\tcolor = MAKE_RGB(150, 0, 150);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SWheel::HANDBRAKE_LOCKED:\r\n\t\t\t\t\tcolor = MAKE_RGB(0, 150, 150);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SWheel::NO_STATE:\r\n\t\t\t\tcase SWheel::OUT_OF_CONTACT:\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tcolor = MAKE_RGB(255, 255, 255);\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tfor (int i = num_edges; i--; )\r\n\t\t\t{\r\n\t\t\t\tMth::Vector start = wheel_point(wheel, i, true);\r\n\t\t\t\tMth::Vector end = wheel_point(wheel, i + 1, true);\r\n\t\t\t\tGfx::AddDebugLine(start, end, color, color, 1);\r\n\t\r\n\t\t\t\tstart = wheel_point(wheel, i, false);\r\n\t\t\t\tend = wheel_point(wheel, i + 1, false);\r\n\t\t\t\tGfx::AddDebugLine(start, end, color, color, 1);\r\n\t\t\t\t\r\n\t\t\t\tstart = wheel_point(wheel, i, true);\r\n\t\t\t\tend = wheel_point(wheel, i, false);\r\n\t\t\t\tGfx::AddDebugLine(start, end, color, color, 1);\r\n\t\t\t\t\r\n\t\t\t\t#if 1\r\n\t\t\t\t// draw axis of rotation lines\r\n\t\t\t\tMth::Matrix steering_rotation(Mth::Vector(0.0f, 1.0f, 0.0f), wheel.steering_angle);\r\n\t\t\t\tstart.Set(-240.0f, 0.0f, 0.0f);\r\n\t\t\t\tstart = steering_rotation.Rotate(start);\r\n\t\t\t\tstart += wheel.pos;\r\n\t\t\t\tstart[Y] += wheel.y_offset;\r\n\t\t\t\tstart = m_pos + m_orientation_matrix.Rotate(start);\r\n\t\t\t\tend.Set(240.0f, 0.0f, 0.0f);\r\n\t\t\t\tend = steering_rotation.Rotate(end);\r\n\t\t\t\tend += wheel.pos;\r\n\t\t\t\tend[Y] += wheel.y_offset;\r\n\t\t\t\tend = m_pos + m_orientation_matrix.Rotate(end);\r\n\t\t\t\tGfx::AddDebugLine(start, end, MAKE_RGB(0, 0, 0), MAKE_RGB(0, 0, 0), 1);\r\n\t\t\t\t#endif\r\n\t\t\t}\r\n\t\t} // END loop over wheels\r\n\t}\r\n\t\r\n\t#if 1\r\n\tif (m_draw_debug_lines)\r\n\t{\r\n\t\tGfx::AddDebugStar(m_pos + m_suspension_center_of_mass_world, 12.0f, MAKE_RGB(100, 0, 100), 1);\r\n\t\tGfx::AddDebugStar(m_pos, 12.0f, MAKE_RGB(0, 100, 100), 1);\r\n\t}\r\n\t#endif\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/vehiclecomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       VehicleComponent.h\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ??/??/??\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_VEHICLECOMPONENT_H__\r\n#define __COMPONENTS_VEHICLECOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/collision/collcache.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n#include <gel/components/triggercomponent.h>\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/engine/rectfeeler.h>\r\n#include <sk/engine/feeler.h>\r\n\r\n#define\t\tCRC_VEHICLE CRCD(0xe47f1b79, \"Vehicle\")\r\n#define\t\tGetVehicleComponent() ((Obj::CVehicleComponent*)GetComponent(CRC_VEHICLE))\r\n#define\t\tGetVehicleComponentFromObject(pObj) ((Obj::CVehicleComponent*)(pObj)->GetComponent(CRC_VEHICLE))\r\n\t\t \r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CInputComponent;\r\n\tclass CAnimationComponent;\r\n\tclass CSkaterCorePhysicsComponent;\r\n\tclass CModelComponent;\r\n\r\n#define vVP_GRAVITATIONAL_ACCELERATION\t\t\t\t\t\t\t\t(386.4f)\r\n#define vVP_MAX_NUM_GEARS\t\t\t\t\t\t\t\t\t\t\t(6)\r\n#define vVP_NUM_COLLIDERS\t\t\t\t\t\t\t\t\t\t\t(2)\r\n\r\n#define vVP_FLIP_DURATION\t\t\t\t\t\t\t\t\t\t\t(5000)\r\n#define vVP_FLIP_DELAY\t\t\t\t\t\t\t\t\t\t\t\t(300)\r\n#define vVP_FLIP_RATE\t\t\t\t\t\t\t\t\t\t\t\t(3.0f)\r\n#define vVP_FLIP_GRAVITY_FACTOR\t\t\t\t\t\t\t\t\t\t(0.3f)\r\n#define vVP_SLEEP_VEL\t\t\t\t\t\t\t\t\t\t\t\t(1.0f)\r\n#define vVP_SLEEP_ROTVEL\t\t\t\t\t\t\t\t\t\t\t(0.01f)\r\n\r\nclass CVehicleComponent : public CBaseComponent\r\n{\r\n\tfriend class CVehicleSoundComponent;\r\n\t\r\n\t// number of frames of normal force history to record for each tire\r\n\tenum { vVP_NORMAL_FORCE_HISTORY_LENGTH = 10 };\r\n\t\r\n\t// HACK for control\r\n\tstruct SControls {\r\n\t\t// steering; between -1.0 and 1.0\r\n\t\tfloat steering;\r\n\t\t\r\n\t\t// throttle\r\n\t\tbool throttle;\r\n\t\t\r\n\t\t// brake\r\n\t\tbool brake;\r\n\t\t\r\n\t\t// handbrake\r\n\t\tbool handbrake;\r\n\t\t\r\n\t\t// reverse\r\n\t\tbool reverse;\r\n\t};\r\n\t\r\n\tstruct SEngine\r\n\t{\r\n\t\t// state variables\r\n\t\t// int gear;\r\n\t\t\r\n\t\t// constant characteristics\r\n\t\t\r\n\t\t// engine's base torque output before applying gear ratios\r\n\t\tfloat drive_torque;\r\n\t\tfloat drag_torque;\r\n\t\t\r\n\t\tint num_gears;\r\n\t\t\r\n\t\tfloat p_gear_ratios[vVP_MAX_NUM_GEARS];\r\n\t\t\r\n\t\tfloat reverse_torque_ratio;\r\n\t\t\r\n\t\tfloat differential_ratio;\r\n\t\t\r\n\t\t// float differential_stiffness;\r\n\t\t\r\n\t\t// float downshift_rotvel;\r\n\t\t\r\n\t\tfloat upshift_rotvel;\r\n\t};\r\n\t\r\n\tstruct SBrake\r\n\t{\r\n\t\t// state variables\r\n\t\t\r\n\t\t// brake torque is applied both after engine torque and friction torque; here we track the unused torque between the applications\r\n\t\tfloat spare_torque;\r\n\t\t\r\n\t\t// constant characteristics\r\n\t\t\r\n\t\t// braking torque per wheel\r\n\t\tfloat torque;\r\n\t\t\r\n\t\t// strength of the handbrake torque when throttle is down and steering is forward\r\n\t\tfloat handbrake_torque;\r\n\t};\r\n\t\r\n\tstruct SWheel\r\n\t{\r\n\t\t\r\n\t\tenum EStateType {\r\n\t\t\tNO_STATE, OUT_OF_CONTACT, UNDER_GRIPPING, GRIPPING, SLIPPING, SKIDDING, HANDBRAKE_THROTTLE, HANDBRAKE_LOCKED\r\n\t\t};\r\n\t\t\r\n\t\tenum ESteeringType {\r\n\t\t\tFIXED, LEFT, RIGHT\r\n\t\t};\r\n\t\t\r\n\t\t// state variables\r\n\t\t\r\n\t\t// offset along Y-axis of wheel's position in vehicle's frame\r\n\t\tfloat y_offset;\r\n\t\t\r\n\t\t// is the wheel out of contact, gripped, skidding, etc\r\n\t\tEStateType state;\r\n\t\t\r\n\t\t// angular velocity about the axle\r\n\t\tfloat rotvel;\r\n\t\t\r\n\t\t// angular position about the axle\r\n\t\tfloat orientation;\r\n\t\t\r\n\t\t// angle of deflection from forward\r\n\t\tfloat steering_angle;\r\n\t\t\r\n\t\t// displayed angle of deflection from forward; lerps behind steering_angle\r\n\t\tfloat steering_angle_display;\r\n\t\t\r\n\t\t// dependent variables\r\n\t\t\r\n\t\t// world frame position of the bottom of the wheel\r\n\t\tMth::Vector pos_world;\r\n\t\t\r\n\t\t// world frame velocity of the bottom of the wheel, not counting rotation\r\n\t\tMth::Vector vel_world;\r\n\t\t\r\n\t\t// magnitude of the normal force applied by the suspension through the tire; set in apply_suspension_forces(); used in apply_friction_forces()\r\n\t\tfloat normal_force;\r\n\t\t\r\n\t\t// magnitude of the normal force for the last few frames; friction uses a smoothed normal force to even out control\r\n\t\tfloat normal_force_history [ vVP_NORMAL_FORCE_HISTORY_LENGTH ];\r\n\t\t\r\n\t\t// normal of the wheel's contact surface\r\n\t\tMth::Vector contact_normal;\r\n\t\t\r\n\t\t// friction coefficient this frame\r\n\t\tfloat friction_coefficient;\r\n\t\t\r\n\t\t// ground detector feeler start and end positions in world frame\r\n\t\tMth::Vector feeler_start_world;\r\n\t\tMth::Vector feeler_end_world;\r\n\t\t\r\n\t\t// NOTE: used only to draw skid indicators; remove if not used for anything else\r\n\t\tfloat slip_vel;\r\n\t\t\r\n\t\t// accumulators\r\n\t\t\r\n\t\t// total rotational acceleration applied so far this frame\r\n\t\tfloat rotacc;\r\n\t\t\r\n\t\t// constant characteristics\r\n\t\t\r\n\t\t// start of the wheel's downward pointing collision feeler; basically the top of the wheel's position in the vehicle's frame\r\n\t\tMth::Vector pos;\r\n\t\t\r\n\t\t// type of wheel with respect to steering\r\n\t\tESteeringType steering;\r\n\t\t\r\n\t\t// true if the wheel is a drive wheel\r\n\t\tbool drive;\r\n\t\t\r\n\t\t// hang point; wheel's y_offset will drop only to this point; the effective equilibrium point for the spring, if one accounts for the wheel's\r\n\t\t// weight ahead of time\r\n\t\tfloat y_offset_hang;\r\n\t\t\r\n\t\t// the wheels are never rendered above this y threshold; this has no affect on their location from the physics code's perspective\r\n\t\tfloat max_draw_y_offset;\r\n\t\t\r\n\t\t// radius of wheel and tire (in)\r\n\t\tfloat radius;\r\n\t\t\r\n\t\t// inverse moment of the wheel and tire around the axis (1 / lb / in^2)\r\n\t\tfloat inv_moment;\r\n\t\t\r\n\t\t// suspension's spring constant (lb / in); spring rate\r\n\t\tfloat spring;\r\n\t\t\r\n\t\t// suspension's damping constant (lb s / in); bump rate\r\n\t\tfloat damping;\r\n\t\t\r\n\t\t// the friction coefficient is a set of concatenated lines; the transitions are made as these velocities; a more sophisticated\r\n\t\tfloat min_static_velocity;\r\n\t\tfloat max_static_velocity;\r\n\t\tfloat min_dynamic_velocity;\r\n\t\t\r\n\t\t// static friction coefficient\r\n\t\tfloat static_friction;\r\n\t\t\r\n\t\t// dynamic friction coefficient\r\n\t\tfloat dynamic_friction;\r\n\t\t\r\n\t\t// friction coefficient during handbraking\r\n\t\tfloat handbrake_throttle_friction;\r\n\t\tfloat handbrake_locked_friction;\r\n\t\t\r\n\t\t// subelements\r\n\t\t\r\n\t\t// brake\r\n        SBrake brake;\r\n\t\t\r\n\t\t// caches to avoid repeating calculations between friction coefficient calculation and friction application\r\n\t\tMth::Vector cache_projected_direction;\r\n\t\tMth::Vector cache_projected_vel;\r\n\t\t\r\n\t\t// the last feeler for this wheel's height which touched the ground\r\n\t\tCFeeler last_ground_feeler;\r\n\t};\r\n\t\r\n\tstruct SCollisionPoint\r\n\t{\r\n\t\t// world position\r\n\t\tMth::Vector pos;\r\n\t\t\r\n\t\t// impact normal\r\n\t\tMth::Vector normal;\r\n\t\t\r\n\t\t// depth of collision as defined as the dot between the displacement from the nearest collider corner and the collision normal\r\n\t\tfloat depth;\r\n\t\t\r\n\t\t// normal impulse accumulator; used to set the maximum friction\r\n\t\tfloat normal_impulse;\r\n\t\t\r\n\t\tbool line;\r\n\t};\r\n\t\r\n\tstruct SCollider\r\n\t{\r\n\t\t// the rectangle defining the collider in body space\r\n\t\tMth::Rectangle body;\r\n\t\t\r\n\t\t// that rectangle transformed into world space\r\n\t\tMth::Rectangle world;\r\n\t\tMth::Vector first_edge_direction_world;\r\n\t\tMth::Vector second_edge_direction_world;\r\n\t\t\r\n\t\t// a few precomputable values\r\n\t\tfloat first_edge_length;\r\n\t\tfloat second_edge_length;\r\n\t};\r\n\t\r\npublic:\r\n\t// inorder to interface with models and skeletons, the number of wheels must be hardcoded to four\r\n\tenum { vVP_NUM_WHEELS = 4 };\r\n\t\r\npublic:\r\n    CVehicleComponent();\r\n    virtual ~CVehicleComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tFinalize (   );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tMoveToNode ( Script::CStruct* p_node );\r\n\tvoid\t\t\t\t\t\t\tApplyArtificialCollision ( const Mth::Vector& offset );\r\n\t\r\n\t\r\n\tconst Mth::Vector&\t\t\t\tGetVel (   ) const { return m_vel; }\r\n\tint\t\t\t\t\t\t\t\tGetNumWheelsInContact (   ) const { return m_num_wheels_in_contact; }\r\n\tbool\t\t\t\t\t\t\tIsOnGround (   ) const;\r\n\t\r\n\tuint32\t\t\t\t\t\t\tGetSoundSetupChecksum (   ) const;\r\n\t\r\nprivate:\r\n\t\r\n\tvoid\t\t\t\t\t\t\tget_input (   );\r\n\tvoid\t\t\t\t\t\t\tzero_input (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tupdate_wheel_from_structure ( SWheel& wheel, Script::CStruct* p_wheel_struct );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tupdate_dynamic_state (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_wheel_dynamic_state (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_dependent_variables (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_velocities (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_collision_cache (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tdamp_rotation (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tcalculate_inverse_moment (   );\r\n\tfloat\t\t\t\t\t\t\tcalculate_friction_coefficient ( SWheel& wheel, float velocity ) const;\r\n\tvoid\t\t\t\t\t\t\tcalculate_friction_coefficients (   );\r\n\tMth::Vector\t\t\t\t\t\tcalculate_body_point_velocity ( const Mth::Vector& pos ) const;\r\n\tfloat\t\t\t\t\t\t\tcalculate_body_point_effective_mass ( const Mth::Vector& pos, const Mth::Vector& direction ) const;\r\n\t\r\n\tint\t\t\t\t\t\t\t\tdetermine_effective_gear ( float wheel_rotvel );\r\n\tvoid\t\t\t\t\t\t\tupdate_wheel_heights (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_steering_angles (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\taccumulate_forces (   );\r\n\tvoid\t\t\t\t\t\t\tapply_gravitational_forces (   );\r\n\tvoid\t\t\t\t\t\t\tapply_suspension_forces (   );\r\n\tvoid\t\t\t\t\t\t\tapply_engine_forces (   );\r\n\tvoid\t\t\t\t\t\t\tapply_drag_forces (   );\r\n\tvoid\t\t\t\t\t\t\tapply_friction_forces (   );\r\n\tvoid\t\t\t\t\t\t\tapply_brake_forces (   );\r\n\tvoid\t\t\t\t\t\t\tapply_handbrake_forces ( float application_factor );\r\n\tvoid\t\t\t\t\t\t\tapply_spare_brake_forces (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\taccumulate_force ( const Mth::Vector& force, const Mth::Vector& location, uint32 color = MAKE_RGB(255, 255, 255) );\r\n\tvoid\t\t\t\t\t\t\taccumulate_collision_force ( const Mth::Vector& force, const Mth::Vector& location );\r\n\tvoid\t\t\t\t\t\t\tapply_wheel_torque ( SWheel& wheel, float torque );\r\n\tfloat\t\t\t\t\t\t\tcalculate_stopping_torque ( const SWheel& wheel, float rotvel ) const;\r\n\t\r\n\tvoid\t\t\t\t\t\t\tupdate_flip (   );\r\n\tvoid\t\t\t\t\t\t\tslerp_to_face_velocity (  );\r\n\tvoid\t\t\t\t\t\t\tconsider_sleeping (   );\r\n\tbool\t\t\t\t\t\t\tin_artificial_collision (    );\r\n\t\r\n\t\r\n\t\t\t\t\t\t\t\t\t// environment collision members\r\n\tfloat\t\t\t\t\t\t\tcalculate_collision_depth ( const SCollisionPoint& collision_point, const SCollider& collider ) const;\r\n\tfloat\t\t\t\t\t\t\tcalculate_collision_depth ( const CLineFeeler& line_feeler ) const;\r\n\tbool\t\t\t\t\t\t\tcheck_for_capping ( SCollisionPoint& collision_point, const CRectFeeler& rect_feeler, const SCollider& collider, int collision_line_idx, int collision_point_end_idx ) const;\r\n\tbool\t\t\t\t\t\t\tconsider_culling_point ( const SCollisionPoint& collision_point ) const;\r\n\tbool\t\t\t\t\t\t\tvery_close ( const Mth::Vector p, const Mth::Vector q ) const;\r\n\tbool\t\t\t\t\t\t\treset_this_frame (   ) const;\r\n\tvoid\t\t\t\t\t\t\tapply_environment_collisions (   );\r\n\tvoid\t\t\t\t\t\t\tupdate_pos_with_uber_frig ( const Mth::Vector& movement );\r\n\tvoid\t\t\t\t\t\t\tapply_impulse ( const Mth::Vector& impulse, const Mth::Vector& location);\r\n\t\r\n\tvoid\t\t\t\t\t\t\ttrip_trigger ( ESkaterTriggerType trigger_type, CLineFeeler &feeler );\r\n\tvoid\t\t\t\t\t\t\ttrip_trigger ( ESkaterTriggerType trigger_type, CRectFeeler &feeler );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tcontrol_skater (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tupdate_skeleton (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tdraw_shadow (   );\r\n\r\n\tMth::Vector\t\t\t\t\t\twheel_point ( const SWheel& wheel, int i, bool side ) const;\r\n    void\t\t\t\t\t\t\tdraw_debug_rendering (   ) const;\r\n\t\r\nprivate:\r\n\t\r\n\t// dynamic state variables\r\n\t\r\n\t// position\r\n\tMth::Vector m_pos;\r\n\t\r\n\t// linear momentum\r\n\tMth::Vector m_mom;\r\n\t\r\n\t// angular orientation\r\n\tMth::Quat m_orientation;\r\n\t\r\n\t// rotational momentum\r\n\tMth::Vector m_rotmom;\r\n\t\r\n\t// like a rigidbody, the vehicle can go to sleep\r\n\tenum EStateType\r\n\t{\r\n\t\tASLEEP, AWAKE\r\n\t}\r\n\tm_state;\r\n\t\r\n\t// counting the number of consecutive sleep-worthy frames; after a certain number, we will go to sleep\r\n\tint m_consider_sleeping_count;\r\n\t\r\n\t// number of collision contacts during latest collision test\r\n\tint m_num_collision_points;\r\n\t\r\n\t// dependent state variables\r\n\t\r\n\t// angular orientation in 3x3 matrix form\r\n\tMth::Matrix m_orientation_matrix;\r\n\t\r\n\t// linear velocity\r\n\tMth::Vector m_vel;\r\n\t\r\n\t// rotational velocity\r\n\tMth::Vector m_rotvel;\r\n\t\r\n\t// inverse moment of inertia in world frame\r\n\tMth::Matrix m_inv_moment;\r\n\t\r\n\t// offset of center of mass used for suspension and friction, but not collisions\r\n\tMth::Vector m_suspension_center_of_mass_world;\r\n\t\r\n\t// counts the number of wheels in contact with the ground\r\n\tunsigned int m_num_wheels_in_contact;\r\n\t\r\n\t// pointer to the next normal force history to use (the oldest one)\r\n\tchar m_next_normal_force_history_idx;\r\n\r\n\t// if true, we were reset from a trigger script and should bail from the frame's update logic\r\n\tbool m_reset_this_frame;\r\n\t\r\n\t// if true, we are currently in the midst of flipping the car over\r\n\tbool m_in_flip;\r\n\t\r\n\t// if we're flipping the car, this is a time stamp of when the flipping began\r\n\tTmr::Time m_flip_start_time_stamp;\r\n\t\r\n\t// during an artificial collision, this timer counts down to the end of the duration\r\n\tfloat m_artificial_collision_timer;\r\n\t\r\n\t// accumulators\r\n\t\r\n\t// accumulates the force on the body in a frame\r\n\tMth::Vector m_force;\r\n\t\r\n\t// accumulates the torque on the body in a frame\r\n\tMth::Vector m_torque;\r\n\t\r\n\t// length of current frame\r\n\tfloat m_time_step;\r\n\t\r\n\t// constant characteristics\r\n\t\r\n\t// vehicle's center of mass\r\n\tMth::Vector m_suspension_center_of_mass;\r\n\t\r\n\t// inverse mass (1 / lb)\r\n\tfloat m_inv_mass;\r\n\t\r\n\t// inverse moment of inertia in vehicle's frame (1 / lb / in^2)\r\n\tMth::Vector m_inv_moment_body;\r\n\t\r\n\t// coefficient of restitution of the body\r\n\tfloat m_body_restitution;\r\n\t\r\n\t// coefficient of friction of the body\r\n\tfloat m_body_friction;\r\n\t\r\n\t// spring constant of the collision penalty system\r\n\tfloat m_body_spring;\r\n\t\r\n\t// coefficient of friction of the body used when the vehicle is not upright\r\n\tfloat m_body_wipeout_friction;\r\n\t\r\n\t// factor of normal collision impulse which you can control via your steering\r\n\tfloat m_collision_control;\r\n\t\r\n\t// horizontal velocity cutoff below which no in-air slerping to face velocity occurs\r\n\tfloat m_in_air_slerp_vel_cutoff;\r\n\t\r\n\t// time over which in-air slerping lerps to full strength after takeoff\r\n\tfloat m_in_air_slerp_time_delay;\r\n\t\r\n\t// in-air slerping strength\r\n\tfloat m_in_air_slerp_strength;\r\n\t\r\n\t// special slerping at low speeds\r\n\tbool m_vert_correction;\r\n\r\n\t// number of wheels\r\n\tunsigned int m_num_wheels;\r\n\t\r\n\t// number of drive wheels; engine torque is divided between this number of wheels\r\n\tunsigned int m_num_drive_wheels;\r\n\t\r\n\t// maximum steering angle\r\n\tfloat m_max_steering_angle;\r\n\t\r\n\t// effective distance between fixed and steering axles (in); used when determining turning radius\r\n\tfloat m_cornering_wheelbase;\r\n\t\r\n\t// distance between center of steering wheels (in); used when determining steering angles\r\n\tfloat m_cornering_axle_length;\r\n\t\r\n\t// constant and quadratic rotational damp coefficients\r\n\tfloat m_const_rotvel_damping;\r\n\tfloat m_quad_rotvel_damping;\r\n\t\r\n\t// vehicles have rectangular feelers which they use to detect collisions with their environment\r\n\tSCollider mp_colliders[vVP_NUM_COLLIDERS];\r\n\t\r\n\t// offset from the vehicle's center of mass the model's origin\r\n\t// float m_body_model_offset;\r\n\t\r\n\t// body model's position\r\n\tMth::Vector m_body_pos;\r\n\t\r\n\t// if true, triangle acts as a brake and throws an ExitCar exception when the car stops\r\n\tbool m_exitable;\r\n\t\r\n\t// if true, the car has no handbrake\r\n\tbool m_no_handbrake;\r\n\t\r\n\t// subelements\r\n\t\r\n\t// wheels\r\n\tSWheel* mp_wheels;\r\n\t\r\n\t// engine\r\n\tSEngine m_engine;\r\n\t\r\n\t// input state\r\n\tSControls m_controls;\r\n\t\r\n\t// collision cache\r\n\tNx::CCollCache m_collision_cache;\r\n\t\r\n\t// parameters controlling skater while vehicle is active\r\n\t\r\n\t// true if the skater should be visible while in the vehicle\r\n\tbool m_skater_visible;\r\n\t\r\n\t// position offset of skater model\r\n\tMth::Vector m_skater_pos;\r\n\t\r\n\t// skater animation to use while in the vehicle\r\n\tuint32 m_skater_anim;\r\n\t\r\n\t// controls the steering used for the displayed wheels and driving animation; lerps to m_controls.steering\r\n\tfloat m_steering_display;\r\n\t\r\n\t// name of the sound setup structure from PlayerVehicleSounds that which vehicle uses\r\n\tuint32 m_sound_setup_checksum;\r\n\t\r\n\t// dynamic script-controllable parameters\r\n\t\r\n\t// the effective gravity can be modified via script; graviy is multiplied by m_gravity_fraction over a duration of m_gravity_override_timer\r\n\tfloat m_gravity_override_fraction;\r\n\tfloat m_gravity_override_timer;\r\n\t\r\n\t// if true, the brakes are forced to be on\r\n\tbool m_force_brake;\r\n\t\r\n\t// state observers\r\n\t\r\n\t// time since we last had a wheel on the ground (plus no body contact)\r\n\tfloat m_air_time;\r\n\tfloat m_air_time_no_collision;\r\n\t\r\n\t// latest updates maximum normal collision impulse\r\n\tfloat m_max_normal_collision_impulse;\r\n\t\r\n\t// peer components\r\n\t\r\n\tCSkeletonComponent* mp_skeleton_component;\r\n\tCInputComponent* mp_input_component;\r\n\tCModelComponent* mp_model_component;\r\n\t\r\n\t// shared objects\r\n\t\r\n\t// shared collision point array\r\n\tstatic SCollisionPoint sp_collision_points[4 * (Nx::MAX_NUM_2D_COLLISIONS_REPORTED + 1)];\r\n\t\r\n\t// debug\r\n\tint m_draw_debug_lines;\r\n\t\r\n\t// if true, no collision detection is done and the skeleton is not updated; this is used to allow a car to settle on its suspension \"off camera\"\r\n\tbool m_update_suspension_only;\r\n\t\r\n\t// the driver\r\n\tCCompositeObject* mp_skater;\r\n\tCAnimationComponent* mp_skater_animation_component;\r\n\tCSkaterCorePhysicsComponent* mp_skater_core_physics_component;\r\n\tCTriggerComponent* mp_skater_trigger_component;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CVehicleComponent::IsOnGround (   ) const\r\n{\r\n\treturn m_num_wheels_in_contact > 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint32 CVehicleComponent::GetSoundSetupChecksum (   ) const\r\n{\r\n\treturn m_sound_setup_checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CVehicleComponent::update_velocities (   )\r\n{\r\n\tm_vel = m_inv_mass * m_mom;\r\n\r\n\t// Zero the W component here to avoid possible NaN propogation issues.\r\n\tm_vel[W] = 0.0f;\r\n\tm_rotvel = m_inv_moment.Rotate(m_rotmom);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Mth::Vector CVehicleComponent::calculate_body_point_velocity ( const Mth::Vector& pos ) const\r\n{\r\n\treturn m_vel + Mth::CrossProduct(m_rotvel, pos);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CVehicleComponent::accumulate_force ( const Mth::Vector& force, const Mth::Vector& location, uint32 color )\r\n{\r\n\tm_force += force;\r\n\tm_torque += Mth::CrossProduct(location - m_suspension_center_of_mass_world, force);\r\n\t\r\n\t#if 0\r\n\tif (m_draw_debug_lines)\r\n\t{\r\n\t\tMth::Vector adjusted_location = location;\r\n\t\tadjusted_location[Y] += 1.0f; // pull out of the ground\r\n\t\tGfx::AddDebugLine(m_pos + adjusted_location, m_pos + adjusted_location + 0.05f * force, color, color, 1);\r\n\t}\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CVehicleComponent::accumulate_collision_force ( const Mth::Vector& force, const Mth::Vector& location )\r\n{\r\n\tm_force += force;\r\n\tm_torque += Mth::CrossProduct(location, force);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CVehicleComponent::apply_wheel_torque ( SWheel& wheel, float torque )\r\n{\r\n\tfloat rotacc = wheel.inv_moment * torque;\r\n\t\r\n\twheel.rotvel += rotacc * m_time_step;\r\n\t\r\n\twheel.rotacc += rotacc;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float CVehicleComponent::calculate_stopping_torque ( const SWheel& wheel, float rotvel ) const\r\n{\r\n\treturn -rotvel / (m_time_step * wheel.inv_moment);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\r\ninline float CVehicleComponent::calculate_collision_depth ( const CLineFeeler& line_feeler ) const\r\n{\r\n\treturn (1.0f - line_feeler.GetDist()) * Mth::DotProduct(line_feeler.GetNormal(), line_feeler.m_start - line_feeler.m_end);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CVehicleComponent::apply_impulse ( const Mth::Vector& impulse, const Mth::Vector& location )\r\n{\r\n\tm_mom += impulse;\r\n\tm_rotmom += Mth::CrossProduct(location, impulse);\r\n\t\r\n\tupdate_velocities();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CVehicleComponent::very_close ( const Mth::Vector p, const Mth::Vector q ) const\r\n{\r\n\treturn Mth::Abs(p[X] - q[X]) < 0.1f && Mth::Abs(p[Y] - q[Y]) < 0.1f && Mth::Abs(p[Z] - q[Z]) < 0.1f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CVehicleComponent::reset_this_frame (   ) const\r\n{\r\n\treturn m_reset_this_frame || GetObject()->IsDead();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CVehicleComponent::trip_trigger ( ESkaterTriggerType trigger_type, CLineFeeler &feeler )\r\n{                            \r\n\tmp_skater_trigger_component->CheckFeelerForTrigger(trigger_type, feeler);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CVehicleComponent::trip_trigger ( ESkaterTriggerType trigger_type, CRectFeeler &feeler )\r\n{                            \r\n\tmp_skater_trigger_component->CheckFeelerForTrigger(trigger_type, feeler);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CVehicleComponent::in_artificial_collision (    )\r\n{                            \r\n\treturn m_artificial_collision_timer > 0.0f;\r\n}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Components/weaponcomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       WeaponComponent.cpp\r\n//* OWNER:          Dave\r\n//* CREATION DATE:  06/10/03\r\n//****************************************************************************\r\n\r\n// The CWeaponComponent class is an skeletal version of a component\r\n// It is intended that you use this as the basis for creating new\r\n// components.  \r\n// To create a new component called \"Watch\", (CWatchComponent):\r\n//  - copy Weaponcomponent.cpp/.h to watchcomponent.cpp/.h\r\n//  - in both files, search and replace \"Weapon\" with \"Watch\", preserving the case\r\n//  - in WatchComponent.h, update the CRCD value of CRC_WATCH\r\n//  - in CompositeObjectManager.cpp, in the CCompositeObjectManager constructor, add:\r\n//\t\t  \tRegisterComponent(CRC_WATCH,\t\t\tCWatchComponent::s_create); \r\n//  - and add the include of the header\r\n//\t\t\t#include <gel/components/watchcomponent.h> \r\n//  - Add it to build\\gel.mkf, like:\r\n//          $(NGEL)/components/WatchComponent.cpp\\\r\n//  - Fill in the OWNER (yourself) and the CREATION DATE (today's date) in the .cpp and the .h files\r\n//\t- Insert code as needed and remove generic comments\r\n//  - remove these comments\r\n//  - add comments specfic to the component, explaining its usage\r\n\r\n#include <gel/components/weaponcomponent.h>\r\n#include <gel/components/pedlogiccomponent.h>\r\n\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/object/compositeobject.h>\r\n\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCBaseComponent* CWeaponComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CWeaponComponent );\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCWeaponComponent::CWeaponComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_WEAPON );\r\n\r\n\tm_sight_pos.Set( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\tm_sight_matrix.Identity();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCWeaponComponent::~CWeaponComponent()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CWeaponComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// ** Add code to parse the structure, and initialize the component\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\n\tIt's commented out here.  You will also need to comment in the \r\n\tdefinition in Weaponcomponent.h\r\nvoid CWeaponComponent::Finalize()\r\n{\r\n\t// Virtual function, can be overridden to provided finialization to \r\n\t// a component after all components have been added to an object\r\n\t// Usually this consists of getting pointers to other components\r\n\t// Note:  It is GUARENTEED (at time of writing) that\r\n\t// Finalize() will be called AFTER all components are added\r\n\t// and BEFORE the CCompositeObject::Update function is called\r\n\t\r\n\t// Example:\r\n\t// mp_suspend_component =  GetSuspendComponentFromObject( GetObject() );\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CWeaponComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calline InitFromStructure()\r\n\t// but if that does not handle it, then will need to write a specific \r\n\t// function here. \r\n\t// The user might only want to update a single field in the structure\r\n\t// and we don't want to be asserting becasue everything is missing \r\n\t\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CWeaponComponent::Update()\r\n{\r\n\t// **  You would put in here the stuff that you would want to get run every frame\r\n\t// **  for example, a physics type component might update the position and orientation\r\n\t// **  and update the internal physics state \r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCBaseComponent::EMemberFunctionResult CWeaponComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n/*\r\n        // @script | DoSomething | does some functionality\r\n\t\tcase 0xbb4ad101:\t\t// DoSomething\r\n\t\t\tDoSomething();\r\n\t\t\tbreak;\r\n\r\n        // @script | ValueIsTrue | returns a boolean value\r\n\t\tcase 0x769260f7:\t\t// ValueIsTrue\r\n\t\t{\r\n\t\t\treturn ValueIsTrue() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\tbreak;\r\n*/\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CWeaponComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CWeaponComponent::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\t/*\tExample:\r\n\tp_info->AddInteger(CRCD(0x7cf2a233,\"m_never_suspend\"),m_never_suspend);\r\n\tp_info->AddFloat(CRCD(0x519ab8e0,\"m_suspend_distance\"),m_suspend_distance);\r\n\t*/\r\n\t\r\n// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CWeaponComponent::ProcessStickyTarget( float heading_change, float tilt_change, float *p_extra_heading_change, float *p_extra_tilt_change )\r\n{\r\n\t// Zero the extra chnage values.\r\n\t*p_extra_heading_change = 0.0f;\r\n\t*p_extra_tilt_change\t= 0.0f;\r\n\r\n\t// If the player is trying to aim, this section of code tries to 'nudge' the aim in the right direction imperceptibly by\r\n\t// moving the cursor just a little more or less based on the requested movement of the cursor.\r\n\tif( mp_current_target )\r\n\t{\r\n\t\tif( heading_change != 0.0f )\r\n\t\t{\r\n\t\t\t// Figure default adjustment amount.\r\n\t\t\tfloat\t\theading_cursor_suck\t\t= Script::GetFloat( CRCD( 0xd90b2dfb, \"GunslingerLookaroundHeadingCursorSuck\" ), Script::ASSERT );\r\n\t\t\tfloat\t\tdefault_adjustment\t\t= heading_change * heading_cursor_suck;\r\n\r\n\t\t\tMth::Vector\timmediate_camera_pos\t= m_sight_pos;\r\n\t\t\tMth::Vector ped_pos\t\t\t\t\t= mp_current_target->GetPos() + Mth::Vector( 0.0f, 36.0f, 0.0f );\r\n\t\t\tMth::Vector\tped_to_cam\t\t\t\t= ped_pos - immediate_camera_pos;\r\n\t\t\tped_to_cam[Y] = 0.0f;\r\n\t\t\tped_to_cam.Normalize();\r\n\r\n\t\t\t// Figure exactly what the angular difference is.\r\n\t\t\tfloat\t\tdp\t\t\t\t\t\t= Mth::DotProduct( ped_to_cam, -m_sight_matrix[Z] );\r\n\t\t\tfloat\t\tangular_difference\t\t= acosf( dp );\r\n\r\n\t\t\t// If the angular difference is actually smaller than the default adjustment amount, make the default adjustment amount the angular difference.\r\n\t\t\tif( Mth::Abs( angular_difference ) < Mth::Abs( default_adjustment ))\r\n\t\t\t{\r\n\t\t\t\tdefault_adjustment = angular_difference;\r\n\t\t\t}\r\n\r\n\t\t\t// Now save off this matrix, and increase the rotation by some percentage of the rotation added to the lookaround heading.\r\n\t\t\tMth::Matrix\tsaved_mat\t\t\t\t= m_sight_matrix;\r\n\t\t\tm_sight_matrix.RotateYLocal( default_adjustment );\r\n\r\n\t\t\t// See if this brings us closer.\r\n\t\t\tfloat\t\tdp2\t\t\t\t\t\t= Mth::DotProduct( ped_to_cam, -m_sight_matrix[Z] );\r\n\t\t\tif( dp2 > dp )\r\n\t\t\t{\r\n\t\t\t\t// Yes it did, so store this change.\r\n\t\t\t\t*p_extra_heading_change\t\t\t= default_adjustment;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// No it didn't so revert to the old matrix.\r\n\t\t\t\tm_sight_matrix = saved_mat;\r\n\r\n\t\t\t\t// Maybe this change went too far? Try undoing 10% of the last change.\r\n\t\t\t\tm_sight_matrix.RotateYLocal( -default_adjustment );\r\n\r\n\t\t\t\t// See if this brings us closer.\r\n\t\t\t\tfloat\tdp3\t\t\t\t\t\t= Mth::DotProduct( ped_to_cam, -m_sight_matrix[Z] );\r\n\t\t\t\tif( dp3 > dp )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Yes it did, so store this change.\r\n\t\t\t\t\t*p_extra_heading_change\t\t= -default_adjustment;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No it didn't so revert to the old matrix.\r\n\t\t\t\t\tm_sight_matrix\t\t\t\t= saved_mat;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif( mp_current_target )\r\n\t{\r\n\t\tif( tilt_change != 0.0f )\r\n\t\t{\r\n\t\t\t// Figure default adjustment amount.\r\n\t\t\tfloat\t\ttilt_cursor_suck\t\t= Script::GetFloat( CRCD( 0x4ece2698, \"GunslingerLookaroundTiltCursorSuck\" ), Script::ASSERT );\r\n\t\t\tfloat\t\tdefault_adjustment\t\t= tilt_change * tilt_cursor_suck;\r\n\r\n\t\t\tMth::Vector\timmediate_camera_pos\t= m_sight_pos;\r\n\t\t\tMth::Vector ped_pos\t\t\t\t\t= mp_current_target->GetPos() + Mth::Vector( 0.0f, 36.0f, 0.0f );\r\n\t\t\tMth::Vector\tped_to_cam\t\t\t\t= ped_pos - immediate_camera_pos;\r\n\t\t\tped_to_cam.Normalize();\r\n\r\n\t\t\t// Figure exactly what the angular difference is.\r\n\t\t\tfloat\t\tdp\t\t\t\t\t\t= Mth::DotProduct( ped_to_cam, -m_sight_matrix[Z] );\r\n\t\t\tfloat\t\tangular_difference\t\t= acosf( dp );\r\n\r\n\t\t\t// If the angular difference is actually smaller than the default adjustment amount, make the default adjustment amount the angular difference.\r\n\t\t\tif( Mth::Abs( angular_difference ) < Mth::Abs( default_adjustment ))\r\n\t\t\t{\r\n\t\t\t\tdefault_adjustment = angular_difference;\r\n\t\t\t}\r\n\r\n\t\t\t// Now save off this matrix, and increase the rotation by some percentage of the rotation added to the lookaround heading.\r\n\t\t\tMth::Matrix\tsaved_mat\t\t\t\t= m_sight_matrix;\r\n\t\t\tm_sight_matrix.RotateXLocal( default_adjustment );\r\n\r\n\t\t\t// See if this brings us closer.\r\n\t\t\tfloat\t\tdp2\t\t\t\t\t\t= Mth::DotProduct( ped_to_cam, -m_sight_matrix[Z] );\r\n\t\t\tif( dp2 > dp )\r\n\t\t\t{\r\n\t\t\t\t// Yes it did, so store this change.\r\n\t\t\t\t*p_extra_tilt_change\t\t\t= default_adjustment;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// No it didn't so revert to the old matrix.\r\n\t\t\t\tm_sight_matrix = saved_mat;\r\n\r\n\t\t\t\t// Maybe this change went too far? Try undoing 10% of the last change.\r\n\t\t\t\tm_sight_matrix.RotateXLocal( -default_adjustment );\r\n\r\n\t\t\t\t// See if this brings us closer.\r\n\t\t\t\tfloat\tdp3\t\t\t\t\t\t= Mth::DotProduct( ped_to_cam, -m_sight_matrix[Z] );\r\n\r\n\t\t\t\tif( dp3 > dp )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Yes it did, so store this change.\r\n\t\t\t\t\t*p_extra_tilt_change\t\t= -default_adjustment;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No it didn't so revert to the old matrix.\r\n\t\t\t\t\tm_sight_matrix\t\t\t\t= saved_mat;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CWeaponComponent::DrawReticle( void )\r\n{\r\n\t// Draw the reticle, red if enemy is within sights, white otherwise.\r\n\tif( m_spin_modulator < 1.0f )\r\n\t{\r\n\t\tGfx::AddDebugStar( m_reticle_max, 24.0f, MAKE_RGB( 255, 0, 0 ), 1 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGfx::AddDebugStar( m_reticle_max, 24.0f, MAKE_RGB( 255, 255, 255 ), 1 );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CWeaponComponent::Fire( void )\r\n{\r\n\tif( mp_current_target )\r\n\t{\r\n\t\tmp_current_target->SelfEvent( CRCD( 0xfaeec40f, \"SkaterInAvoidRadius\" ));\r\n\t}\r\n\r\n\tScript::RunScript( CRCD( 0xe03997d0, \"PlayGunshot\" ));\r\n}\r\n\r\n\r\n\r\n// These values should really be specified per-weapon.\r\nconst float SPIN_MODULATION_ANGLE = 0.9848f;\t// Cosine of 10 degrees.\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCCompositeObject* CWeaponComponent::GetCurrentTarget( Mth::Vector& start_pos, Mth::Vector* p_reticle_max )\r\n{\r\n\t// This is the maximum distance that we will check for targets.\r\n\tfloat target_distance = Script::GetFloat( CRCD( 0x89495011,\"GunslingerTargetDistance\" ), Script::ASSERT );\r\n\r\n\tMth::Vector reticle_min\t\t= start_pos;\r\n\tm_reticle_max\t\t\t\t= reticle_min - ( m_sight_matrix[Z] * target_distance );\r\n\r\n\t// Ignore faces based on face flags.\r\n\tCFeeler feeler;\r\n\tfeeler.SetIgnore((uint16)( mFD_NON_COLLIDABLE | mFD_NON_CAMERA_COLLIDABLE ), 0 );\r\n\tfeeler.SetLine( reticle_min, m_reticle_max );\r\n\tbool collision = feeler.GetCollision( true );\r\n\tif( collision )\r\n\t{\r\n\t\tm_reticle_max = feeler.GetPoint();\r\n\t\t\r\n\t\t// Set the new target distance at the point of contact, to avoid considering targets beyond the collision point.\r\n\t\ttarget_distance\t= target_distance * feeler.GetDist();\r\n\t}\r\n\r\n\t// Only targets within the allowed angle will be considered.\r\n\t\t\t\t\t\t\tmp_current_target\t= NULL;\r\n\tfloat\t\t\t\t\tbest_dp\t\t\t\t= SPIN_MODULATION_ANGLE;\r\n\tMth::Vector\t\t\t\tbest_pos;\r\n\r\n\t// Rather than cycling through the ped logic components, eventually everything that is targettable should contain a targetting component.\r\n\tObj::CPedLogicComponent *p_ped_logic_component = static_cast<Obj::CPedLogicComponent*>( Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType( CRC_PEDLOGIC ));\r\n\twhile( p_ped_logic_component )\r\n\t{\r\n\t\tObj::CCompositeObject *p_ped = p_ped_logic_component->GetObject();\r\n\r\n\t\t// Have to hack in a height adjustment here - the default position appears to be at ground level.\r\n\t\tMth::Vector ped_pos\t\t= p_ped->GetPos() + Mth::Vector( 0.0f, 36.0f, 0.0f );\r\n\r\n\t\t// Want to get the position of this ped.\r\n\t\tMth::Vector\tped_to_cam\t= ped_pos - reticle_min;\r\n\r\n\t\t// Check not too far away.\r\n\t\tif( ped_to_cam.LengthSqr() < ( target_distance * target_distance ))\r\n\t\t{\r\n\t\t\tped_to_cam.Normalize();\r\n\r\n\t\t\t// Calculate angle this ped subtends at the camera position.\r\n\t\t\tfloat\t\tdp\t\t\t= Mth::DotProduct( ped_to_cam, -m_sight_matrix[Z] );\r\n\t\t\tif( dp > best_dp )\r\n\t\t\t{\r\n\t\t\t\tbest_dp\t\t\t\t= dp;\r\n\t\t\t\tbest_pos\t\t\t= ped_pos;\r\n\t\t\t\tmp_current_target\t= p_ped;\r\n\t\t\t}\r\n\t\t}\r\n\t\tp_ped_logic_component\t\t\t= static_cast<Obj::CPedLogicComponent*>( p_ped_logic_component->GetNextSameType());\r\n\t}\r\n\r\n\t// Reset spin and tilt modulators.\r\n\tm_spin_modulator\t= 1.0f;\r\n\tm_tilt_modulator\t= 1.0f;\r\n\r\n\tif( mp_current_target )\r\n\t{\r\n\t\t// We have a potential candidate for targetting.\r\n\t\t// However we still want to check that it is close enough to our line of sight.\r\n\t\tfloat dist_to_ped\t= Mth::Distance( best_pos, reticle_min );\r\n\t\tfloat dist_to_line\t= dist_to_ped * sqrtf( 1.0f - ( best_dp * best_dp ));\r\n\r\n\t\t// This value should really be per-weapon in some script array.\r\n\t\tif( dist_to_line < Script::GetFloat( CRCD( 0x755235db, \"GunslingerLookaroundModulationDistance\" ), Script::ASSERT ))\r\n\t\t{\r\n\t\t\t// Is this the same target as last time?\r\n//\t\t\tif( mp_best_target == p_selected_target )\r\n//\t\t\t{\r\n//\t\t\t\t// If so, increase the targetting timer.\r\n//\t\t\t\ttarget_selection_timer += frame_length;\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\t// Otherwise, reset the timer.\r\n//\t\t\t\tp_selected_target\t\t= mp_best_target;\r\n//\t\t\t\ttarget_selection_timer\t= frame_length;\r\n//\t\t\t}\r\n\r\n\t\t\t// Modulator gets smaller as result tends to 1.0.\r\n\t\t\tfloat max_damping = Script::GetFloat( CRCD( 0xef314a12, \"GunslingerLookaroundDamping\" ), Script::ASSERT );\r\n\t\t\tm_spin_modulator = 1.0f - ( max_damping * (( best_dp - SPIN_MODULATION_ANGLE ) / ( 1.0f - SPIN_MODULATION_ANGLE )));\r\n\r\n//\t\t\tif( gun_fired )\r\n//\t\t\t{\r\n//\t\t\t\t// Make this ped fall down.\r\n//\t\t\t\tmp_best_target->SelfEvent( CRCD( 0xfaeec40f, \"SkaterInAvoidRadius\" ));\r\n//\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_current_target = NULL;\r\n\t\t}\r\n\t}\r\n\r\n\t// Currently, set tilt modulator to be the same as spin modulator.\r\n\tm_tilt_modulator = m_spin_modulator;\r\n\r\n\tif( p_reticle_max )\r\n\t{\r\n\t\t*p_reticle_max = m_reticle_max;\r\n\t}\r\n\r\n\treturn mp_current_target;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Components/weaponcomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       WeaponComponent.h\r\n//* OWNER:          Dave\r\n//* CREATION DATE:  06/10/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_WEAPONCOMPONENT_H__\r\n#define __COMPONENTS_WEAPONCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_WEAPON CRCD( 0x96cc5819, \"Weapon\" )\r\n\r\n#define\t\tGetWeaponComponent()\t\t\t\t((Obj::CWeaponComponent*)GetComponent(CRC_WEAPON))\r\n#define\t\tGetWeaponComponentFromObject(pObj)\t((Obj::CWeaponComponent*)(pObj)->GetComponent(CRC_WEAPON))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CWeaponComponent : public CBaseComponent\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\t\tCWeaponComponent();\r\n\t\t\t\t\t\t\t\t\tvirtual ~CWeaponComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n//\tvirtual\tvoid \t\t\t\t\tFinalize();\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tCCompositeObject*\t\t\t\tGetCurrentTarget( Mth::Vector& start_pos, Mth::Vector* p_reticle_max );\r\n\tvoid\t\t\t\t\t\t\tSetCurrentTarget( CCompositeObject* p_obj )\t{ mp_current_target = p_obj; }\r\n\tvoid\t\t\t\t\t\t\tSetSightPos( Mth::Vector& p )\t\t\t\t{ m_sight_pos = p; }\r\n\tvoid\t\t\t\t\t\t\tSetSightMatrix( Mth::Matrix& s )\t\t\t{ m_sight_matrix = s; }\r\n\tvoid\t\t\t\t\t\t\tDrawReticle( void );\r\n\tvoid\t\t\t\t\t\t\tProcessStickyTarget( float heading_change, float tilt_change, float *p_extra_heading_change, float *p_extra_tilt_change );\r\n\tvoid\t\t\t\t\t\t\tFire( void );\r\n\r\n\tfloat\t\t\t\t\t\t\tGetSpinModulator( void )\t\t\t\t\t{ return m_spin_modulator; }\r\n\tfloat\t\t\t\t\t\t\tGetTiltModulator( void )\t\t\t\t\t{ return m_tilt_modulator; }\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\nprivate:\r\n\r\n\tMth::Matrix\t\t\t\t\t\tm_sight_matrix;\r\n\tMth::Vector\t\t\t\t\t\tm_sight_pos;\r\n\tMth::Vector\t\t\t\t\t\tm_reticle_max;\t\t\t// Position of reticle max point from last collision check.\r\n\tCCompositeObject*\t\t\t\tmp_current_target;\r\n\r\n\tfloat\t\t\t\t\t\t\tm_spin_modulator;\r\n\tfloat\t\t\t\t\t\t\tm_tilt_modulator;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Environment/terrain.cpp",
    "content": "/*\r\n\tThis is just a database for arrays of skater sounds on different terrains.\r\n\t\r\n\tFor each type of sound in sounds.h (like grind, land, slide, wheel roll, etc...)\r\n\tthere is an array of sounds to play, one for each possible terrain type.\r\n\t\r\n\tA terrain type of zero indicates that the sound is the default (for surfaces not\r\n\tdefined in the list).\r\n*/\r\n\r\n\r\n#include <string.h>\r\n#include <core/defines.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/environment/terrain.h>\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sys/config/config.h>\r\n#include <sys/replay/replay.h>\r\n\r\n\r\n\r\nnamespace Env\r\n{\r\n\r\n#ifdef __NOPT_ASSERT__\r\nbool\t\t\t\t\tCTerrainManager::s_terrain_loaded[ vNUM_TERRAIN_TYPES ];\r\n#endif __NOPT_ASSERT__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nETerrainType\t\t\tCTerrainManager::sGetTerrainFromChecksum(uint32 checksum)\r\n{\r\n\tswitch (checksum)\r\n\t{\r\n\tcase 0x64967688: // TERRAIN_DEFAULT\r\n\t\treturn vTERRAIN_DEFAULT;\r\n\r\n\tcase 0x9b37fa90: // TERRAIN_CONCSMOOTH\r\n\t\treturn vTERRAIN_CONCSMOOTH;   \r\n\r\n\tcase 0x9383172: // TERRAIN_CONCROUGH\r\n\t\treturn vTERRAIN_CONCROUGH;\r\n\r\n\tcase 0xa9ecf4e9: // TERRAIN_METALSMOOTH\r\n\t\treturn vTERRAIN_METALSMOOTH;\r\n\r\n\tcase 0xa5aab5e: // TERRAIN_METALROUGH\r\n\t\treturn vTERRAIN_METALROUGH;   \r\n\r\n\tcase 0x67af2cb5: // TERRAIN_METALCORRUGATED\r\n\t\treturn vTERRAIN_METALCORRUGATED;  \r\n\r\n\tcase 0x1134b31a: // TERRAIN_METALGRATING\r\n\t\treturn vTERRAIN_METALGRATING;\r\n\r\n\tcase 0xd814ef41: // TERRAIN_METALTIN\r\n\t\treturn vTERRAIN_METALTIN; \r\n\r\n\tcase 0x39075ea5: // TERRAIN_WOOD\r\n\t\treturn vTERRAIN_WOOD;   \r\n\r\n\tcase 0x3afca53f: // TERRAIN_WOODMASONITE\r\n\t\treturn vTERRAIN_WOODMASONITE;\r\n\r\n\tcase 0x6651a5d0: // TERRAIN_WOODPLYWOOD\r\n\t\treturn vTERRAIN_WOODPLYWOOD;\r\n\r\n\tcase 0xd11a620d: // TERRAIN_WOODFLIMSY\r\n\t\treturn vTERRAIN_WOODFLIMSY;   \r\n\r\n\tcase 0xd3e04021: // TERRAIN_WOODSHINGLE\r\n\t\treturn vTERRAIN_WOODSHINGLE;\r\n\r\n\tcase 0x866b2b83: // TERRAIN_WOODPIER\r\n\t\treturn vTERRAIN_WOODPIER; \r\n\r\n\tcase 0x3d5a952c: // TERRAIN_BRICK\r\n\t\treturn vTERRAIN_BRICK;\r\n\r\n\tcase 0x7315eeac: // TERRAIN_TILE\r\n\t\treturn vTERRAIN_TILE;   \r\n\r\n\tcase 0x6aa69ead: // TERRAIN_ASPHALT\r\n\t\treturn vTERRAIN_ASPHALT;  \r\n\r\n\tcase 0x32d3fc0a: // TERRAIN_ROCK\r\n\t\treturn vTERRAIN_ROCK;   \r\n\r\n\tcase 0x67f6ee4c: // TERRAIN_GRAVEL\r\n\t\treturn vTERRAIN_GRAVEL;   \r\n\r\n\tcase 0x103bb3b8: // TERRAIN_SIDEWALK\r\n\t\treturn vTERRAIN_SIDEWALK; \r\n\r\n\tcase 0xa207c1e3: // TERRAIN_GRASS\r\n\t\treturn vTERRAIN_GRASS;   \r\n\r\n\tcase 0x802c8f14: // TERRAIN_GRASSDRIED\r\n\t\treturn vTERRAIN_GRASSDRIED;   \r\n\r\n\tcase 0x9dfda61e: // TERRAIN_DIRT\r\n\t\treturn vTERRAIN_DIRT;   \r\n\r\n\tcase 0xd748f9b7: // TERRAIN_DIRTPACKED\r\n\t\treturn vTERRAIN_DIRTPACKED;   \r\n\r\n\tcase 0xf1394aca: // TERRAIN_WATER\r\n\t\treturn vTERRAIN_WATER;   \r\n\r\n\tcase 0x5e354fef: // TERRAIN_ICE\r\n\t\treturn vTERRAIN_ICE;   \r\n\r\n\tcase 0x3319e21b: // TERRAIN_SNOW\r\n\t\treturn vTERRAIN_SNOW;   \r\n\r\n\tcase 0xa5e0d5b9: // TERRAIN_SAND\r\n\t\treturn vTERRAIN_SAND;   \r\n\r\n\tcase 0x6362cc4f: // TERRAIN_PLEXIGLASS\r\n\t\treturn vTERRAIN_PLEXIGLASS;   \r\n\r\n\tcase 0x66987ee0: // TERRAIN_FIBERGLASS\r\n\t\treturn vTERRAIN_FIBERGLASS;   \r\n\r\n\tcase 0x8e6a5d9d: // TERRAIN_CARPET\r\n\t\treturn vTERRAIN_CARPET;   \r\n\r\n\tcase 0x2ee8ef42: // TERRAIN_CONVEYOR\r\n\t\treturn vTERRAIN_CONVEYOR; \r\n\r\n\tcase 0xbe7c0e6e: // TERRAIN_CHAINLINK\r\n\t\treturn vTERRAIN_CHAINLINK;\r\n\r\n\tcase 0x14259681: // TERRAIN_METALFUTURE\r\n\t\treturn vTERRAIN_METALFUTURE;\r\n\r\n\tcase 0xbb1ac0d4: // TERRAIN_GENERIC1\r\n\t\treturn vTERRAIN_GENERIC1; \r\n\r\n\tcase 0x2213916e: // TERRAIN_GENERIC2\r\n\t\treturn vTERRAIN_GENERIC2;\r\n\r\n\tcase 0x83b85f36: // TERRAIN_WHEELS\r\n\t\treturn vTERRAIN_WHEELS;   \r\n\r\n\tcase 0x22dd3d51: // TERRAIN_WETCONC\r\n\t\treturn vTERRAIN_WETCONC;\r\n\r\n\tcase 0xfa298f50: // TERRAIN_METALFENCE\r\n\t\treturn vTERRAIN_METALFENCE;\r\n\r\n\tcase 0x69803ba4: // TERRAIN_GRINDTRAIN\r\n\t\treturn vTERRAIN_GRINDTRAIN;\r\n\r\n\tcase 0xed035a39: // TERRAIN_GRINDROPE\r\n\t\treturn vTERRAIN_GRINDROPE;\r\n\r\n\tcase 0xec66b43b: // TERRAIN_GRINDWIRE\r\n\t\treturn vTERRAIN_GRINDWIRE;\r\n\r\n\tcase CRCC(0x3884f029,\"TERRAIN_GRINDCONC\"):\r\n\t\treturn vTERRAIN_GRINDCONC;\r\n\r\n\tcase CRCC(0x92a2112a,\"TERRAIN_GRINDROUNDMETALPOLE\"):\r\n\t\treturn vTERRAIN_GRINDROUNDMETALPOLE;\r\n\r\n\tcase CRCC(0xd7e88122,\"TERRAIN_GRINDCHAINLINK\"):\r\n\t\treturn vTERRAIN_GRINDCHAINLINK;\r\n\r\n\tcase CRCC(0xf5842bce,\"TERRAIN_GRINDMETAL\"):\r\n\t\treturn vTERRAIN_GRINDMETAL;\r\n\r\n\tcase CRCC(0xffc0b5e,\"TERRAIN_GRINDWOODRAILING\"):\r\n\t\treturn vTERRAIN_GRINDWOODRAILING;\r\n\r\n\tcase CRCC(0x8aadc3d0,\"TERRAIN_GRINDWOODLOG\"):\r\n\t\treturn vTERRAIN_GRINDWOODLOG;\r\n\r\n\tcase CRCC(0x60809403,\"TERRAIN_GRINDWOOD\"):\r\n\t\treturn vTERRAIN_GRINDWOOD;\r\n\r\n\tcase CRCC(0xf862cfe0,\"TERRAIN_GRINDPLASTIC\"):\r\n\t\treturn vTERRAIN_GRINDPLASTIC;\r\n\r\n\tcase CRCC(0x2bb33575,\"TERRAIN_GRINDELECTRICWIRE\"):\r\n\t\treturn vTERRAIN_GRINDELECTRICWIRE;\r\n\r\n\tcase CRCC(0x110f1bd3,\"TERRAIN_GRINDCABLE\"):\r\n\t\treturn vTERRAIN_GRINDCABLE;\r\n\r\n\tcase CRCC(0x84e4c7cd,\"TERRAIN_GRINDCHAIN\"):\r\n\t\treturn vTERRAIN_GRINDCHAIN;\r\n\r\n\tcase CRCC(0x3f1c35c5,\"TERRAIN_GRINDPLASTICBARRIER\"):\r\n\t\treturn vTERRAIN_GRINDPLASTICBARRIER;\r\n\r\n\tcase CRCC(0x6c4a1c6a,\"TERRAIN_GRINDNEONLIGHT\"):\r\n\t\treturn vTERRAIN_GRINDNEONLIGHT;\r\n\r\n\tcase CRCC(0xcaf52d56,\"TERRAIN_GRINDGLASSMONSTER\"):\r\n\t\treturn vTERRAIN_GRINDGLASSMONSTER;\r\n\r\n\tcase CRCC(0x8da017a8,\"TERRAIN_GRINDBANYONTREE\"):\r\n\t\treturn vTERRAIN_GRINDBANYONTREE;\r\n\r\n\tcase CRCC(0x7825b83c,\"TERRAIN_GRINDBRASSRAIL\"):\r\n\t\treturn vTERRAIN_GRINDBRASSRAIL;\r\n\r\n\tcase CRCC(0x5ce9c824,\"TERRAIN_GRINDCATWALK\"):\r\n\t\treturn vTERRAIN_GRINDCATWALK;\r\n\r\n\tcase CRCC(0x66ab4005,\"TERRAIN_GRINDTANKTURRET\"):\r\n\t\treturn vTERRAIN_GRINDTANKTURRET;\r\n\r\n\tcase 0x24dca61: // TERRAIN_MEATALSMOOTH\t\t// old typo that still exists\r\n\t\tDbg_Message(\"Metal is not spelled 'Meatal'\");\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0, (\"Unknown terrain checksum %x\\n\", checksum));\r\n\t\treturn vTERRAIN_DEFAULT;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nETerrainActionType\t\tCTerrainManager::sGetActionFromChecksum(uint32 checksum)\r\n{\r\n\tswitch (checksum)\r\n\t{\r\n\tcase 0xcaebd8e: // TA_ROLL\r\n\t\treturn vTABLE_WHEELROLL;\r\n\r\n\tcase 0x7e5d9202: // TA_GRIND\r\n\t\treturn vTABLE_GRIND;\r\n\r\n\tcase 0xc0669dd5: // TA_OLLIE\r\n\t\treturn vTABLE_JUMP;\r\n\r\n\tcase 0x8a1b5a98: // TA_LAND\r\n\t\treturn vTABLE_LAND;\r\n\r\n\tcase 0xf0e51d30: // TA_BONK\r\n\t\treturn vTABLE_BONK;\r\n\r\n\tcase 0x6ac1023d: // TA_GRINDJUMP\r\n\t\treturn vTABLE_GRINDJUMP;\r\n\r\n\tcase 0x6572d1f3: // TA_GRINDLAND\r\n\t\treturn vTABLE_GRINDLAND;\r\n\r\n\tcase 0xd6135bf0: // TA_SLIDE\r\n\t\treturn vTABLE_SLIDE;\r\n\r\n\tcase 0x6e27388f: // TA_SLIDEJUMP\r\n\t\treturn vTABLE_SLIDEJUMP;\r\n\r\n\tcase 0x6194eb41: // TA_SLIDELAND\r\n\t\treturn vTABLE_SLIDELAND;\r\n\r\n\tcase 0x20744cde: // TA_REVERT\r\n\t\treturn vTABLE_CESS;\r\n\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0, (\"Unknown terrain action checksum %x\\n\", checksum));\r\n\t\treturn vTABLE_WHEELROLL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\t\t\t\t\tCTerrainManager::s_get_action_checksum(ETerrainActionType action)\r\n{\r\n\tswitch (action)\r\n\t{\r\n\tcase vTABLE_WHEELROLL:\r\n\t\treturn 0xcaebd8e; // TA_ROLL\r\n\r\n\tcase vTABLE_GRIND:\r\n\t\treturn 0x7e5d9202; // TA_GRIND\r\n\r\n\tcase vTABLE_JUMP:\r\n\t\treturn 0xc0669dd5; // TA_OLLIE\r\n\r\n\tcase vTABLE_LAND:\r\n\t\treturn 0x8a1b5a98; // TA_LAND\r\n\r\n\tcase vTABLE_BONK:\r\n\t\treturn 0xf0e51d30; // TA_BONK\r\n\r\n\tcase vTABLE_GRINDJUMP:\r\n\t\treturn 0x6ac1023d; // TA_GRINDJUMP\r\n\r\n\tcase vTABLE_GRINDLAND:\r\n\t\treturn 0x6572d1f3; // TA_GRINDLAND\r\n\r\n\tcase vTABLE_SLIDE:\r\n\t\treturn 0xd6135bf0; // TA_SLIDE\r\n\r\n\tcase vTABLE_SLIDEJUMP:\r\n\t\treturn 0x6e27388f; // TA_SLIDEJUMP\r\n\r\n\tcase vTABLE_SLIDELAND:\r\n\t\treturn 0x6194eb41; // TA_SLIDELAND\r\n\r\n\tcase vTABLE_CESS:\r\n\t\treturn 0x20744cde; // TA_REVERT\r\n\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0, (\"Unknown terrain action %d\\n\", action));\r\n\t\treturn 0xcaebd8e; // TA_ROLL\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\t\tCTerrainManager::s_get_terrain_actions_struct(ETerrainType terrain, Script::CStruct *p_actions)\r\n{\r\n\tDbg_MsgAssert(p_actions, (\"s_get_terrain_actions_struct given NULL CStruct\"));\r\n\r\n\tScript::CStruct *p_default_actions = NULL;\r\n\tScript::CStruct *p_terrain_actions = NULL;\r\n\tScript::CStruct *p_level_default_actions = NULL;\r\n\tScript::CStruct *p_level_terrain_actions = NULL;\r\n\r\n\tuint32 terrain_checksum;\r\n\tETerrainType terrain_type;\r\n\r\n\t// Search Default Terrain array first\r\n\tScript::CArray *pDefaultTerrainArray = Script::GetArray(CRCD(0x1c2c4218,\"standard_terrain\"));\r\n\tDbg_MsgAssert(pDefaultTerrainArray, (\"standard_terrain not found\"));\r\n\r\n\tfor (uint i = 0; (!p_default_actions || !p_terrain_actions) && i < pDefaultTerrainArray->GetSize(); i++)\r\n\t{\r\n\t\t// Get next terrain struct\r\n\t\tScript::CStruct *pTerrainStruct = pDefaultTerrainArray->GetStructure(i);\r\n\t\tDbg_MsgAssert(pTerrainStruct, (\"terrain array not made of structures\"));\r\n\r\n\t\tpTerrainStruct->GetChecksum(CRCD(0x3789ac4e,\"Terrain\"), &terrain_checksum, Script::ASSERT);\r\n\t\tterrain_type = sGetTerrainFromChecksum(terrain_checksum);\r\n\r\n\t\tif (terrain_type == vTERRAIN_DEFAULT)\r\n\t\t{\r\n\t\t\tpTerrainStruct->GetStructure(CRCD(0x5c969c50,\"SoundActions\"), &p_default_actions);\r\n\t\t\t//Dbg_Message(\"Found default terrain:\");\r\n\t\t\t//Script::PrintContents(p_default_actions);\r\n\t\t}\r\n\t\telse if (terrain_type == terrain)\r\n\t\t{\r\n\t\t\tpTerrainStruct->GetStructure(CRCD(0x5c969c50,\"SoundActions\"), &p_terrain_actions);\r\n\t\t\t//Dbg_Message(\"Found terrain:\");\r\n\t\t\t//Script::PrintContents(p_terrain_actions);\r\n\t\t}\r\n\r\n\t\tif (p_default_actions && p_terrain_actions)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// Search Level Terrain array\r\n\tScript::CArray *pLevelTerrainArray = Script::GetArray(CRCD(0x96218951,\"level_terrain\"));\r\n\tif (pLevelTerrainArray)\r\n\t{\r\n\t\tfor (uint i = 0; i < pLevelTerrainArray->GetSize(); i++)\r\n\t\t{\r\n\t\t\t// Get next terrain struct\r\n\t\t\tScript::CStruct *pTerrainStruct = pLevelTerrainArray->GetStructure(i);\r\n\t\t\tDbg_MsgAssert(pTerrainStruct, (\"terrain array not made of structures\"));\r\n\r\n\t\t\tpTerrainStruct->GetChecksum(CRCD(0x3789ac4e,\"Terrain\"), &terrain_checksum, Script::ASSERT);\r\n\t\t\tterrain_type = sGetTerrainFromChecksum(terrain_checksum);\r\n\r\n\t\t\tif (terrain_type == vTERRAIN_DEFAULT)\r\n\t\t\t{\r\n\t\t\t\tpTerrainStruct->GetStructure(CRCD(0x5c969c50,\"SoundActions\"), &p_level_default_actions);\r\n\t\t\t} else if (terrain_type == terrain)\r\n\t\t\t{\r\n\t\t\t\tpTerrainStruct->GetStructure(CRCD(0x5c969c50,\"SoundActions\"), &p_level_terrain_actions);\r\n\t\t\t}\r\n\r\n\t\t\tif (p_level_default_actions && p_level_terrain_actions)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Combine them together\r\n\t*p_actions = *p_default_actions;\r\n\r\n\tif (p_level_default_actions)\r\n\t{\r\n\t\t*p_actions += *p_level_default_actions;\r\n\t}\r\n\r\n\tif (p_terrain_actions)\r\n\t{\r\n\t\t*p_actions += *p_terrain_actions;\r\n\t}\r\n\r\n\tif (p_level_terrain_actions)\r\n\t{\r\n\t\t*p_actions += *p_level_terrain_actions;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct *\t\tCTerrainManager::s_choose_sound_action(Script::CStruct *p_sound_action_struct)\r\n{\r\n\tScript::CStruct* p_sound;\r\n\t\r\n\t// soundAction is a single stucture, so just use it\r\n\tif (p_sound_action_struct->GetStructure(CRCD(0x25f654c8, \"soundAction\"), &p_sound))\r\n\t{\r\n\t\tDbg_MsgAssert(!p_sound->ContainsComponentNamed(CRCD(0xdbc4c4db, \"chance\")),\r\n\t\t\t(\"A sound may only include a chance parameter when it is an element of a random-choice list of sounds\"));\r\n\t\treturn p_sound;\r\n\t}\r\n\t\r\n\t// soundAction is an array of structures, so choose one randomly based on their given chances\r\n\tScript::CArray* p_random_indexed_sound_array;\r\n\tp_sound_action_struct->GetArray(CRCD(0x25f654c8, \"soundAction\"), &p_random_indexed_sound_array, Script::ASSERT);\r\n\t\r\n\tint total_chance = 0;\r\n\tfor (int sound_idx = p_random_indexed_sound_array->GetSize(); sound_idx--; )\r\n\t{\r\n\t\tp_sound = p_random_indexed_sound_array->GetStructure(sound_idx);\r\n\t\t\r\n\t\tint chance;\r\n\t\tp_sound->GetInteger(CRCD(0xdbc4c4db, \"chance\"), &chance, Script::ASSERT);\r\n\t\t\r\n\t\ttotal_chance += chance;\r\n\t}\r\n\t\r\n\tint choice = Mth::Rnd(total_chance);\r\n\t\r\n\tfor (int sound_idx = p_random_indexed_sound_array->GetSize(); sound_idx--; )\r\n\t{\r\n\t\tp_sound = p_random_indexed_sound_array->GetStructure(sound_idx);\r\n\t\t\r\n\t\tint chance;\r\n\t\tp_sound->GetInteger(CRCD(0xdbc4c4db, \"chance\"), &chance, Script::ASSERT);\r\n\t\t\r\n\t\tchoice -= chance;\r\n\t\tif (choice < 0)\r\n\t\t{\r\n\t\t\treturn p_sound;\r\n\t\t}\r\n\t}\r\n\t\r\n\tDbg_Assert(false);\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct *\t\tCTerrainManager::s_get_action_sound_struct(Script::CStruct *p_actions, ETerrainActionType action, float soundChoice)\r\n{\r\n\tDbg_MsgAssert(p_actions, (\"s_get_action_sound_struct given NULL action CStruct\"));\r\n\r\n\tScript::CStruct *p_sound;\r\n\t\r\n\tuint32 checksum = s_get_action_checksum(action);\r\n\r\n\t// sound is a single sound structure, so just use it\r\n\tif (p_actions->GetStructure(checksum, &p_sound))\r\n\t{\r\n\t\treturn p_sound;\r\n\t}\r\n\t\r\n\t// sound is an array of structures, one of which must be choosen depending upon speed\r\n\tScript::CArray* p_float_indexed_sound_array;\r\n\tp_actions->GetArray(checksum, &p_float_indexed_sound_array, Script::ASSERT);\r\n\t\r\n\t// check to insure that the final structure in the array has no useUpTo parameter and thus operates as a default choice\r\n\tDbg_MsgAssert(!p_float_indexed_sound_array->GetStructure(p_float_indexed_sound_array->GetSize() - 1)->ContainsComponentNamed(CRCD(0x9ee9a09a, \"useUpTo\")),\r\n\t\t(\"Final sound in a speed-indexed sound list must not include useUpTo\"));\r\n\t\r\n\tfor (uint32 sound_action_idx = 0; sound_action_idx < p_float_indexed_sound_array->GetSize(); sound_action_idx++)\r\n\t{\r\n\t\t// each structure contains a useUpTo parameter which is checked against speed in turn; if found to be larger\r\n\t\t// than speed, the sound is used; a structure lacking useUpTo is always used\r\n\t\tScript::CStruct* p_sound_action_struct = p_float_indexed_sound_array->GetStructure(sound_action_idx);\r\n\t\t\r\n\t\tfloat up_to_speed;\r\n\t\tif (!p_sound_action_struct->GetFloat(CRCD(0x9ee9a09a, \"useUpTo\"), &up_to_speed))\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(sound_action_idx == p_float_indexed_sound_array->GetSize() - 1,\r\n\t\t\t\t(\"Only the final sound in a float-indexed sound list may fail to include useUpTo\"));\r\n\t\t\treturn s_choose_sound_action(p_sound_action_struct);\r\n\t\t}\r\n\t\t\r\n\t\tif (soundChoice <= up_to_speed)\r\n\t\t{\r\n\t\t\treturn s_choose_sound_action(p_sound_action_struct);\r\n\t\t}\r\n\t}\r\n\t\r\n\tDbg_Assert(false);\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\t\tCTerrainManager::s_get_sound_info(Script::CStruct *p_sound, STerrainSoundInfo *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info, (\"s_get_sound_info given NULL STerrainSoundInfo\"));\r\n\r\n\t// Set defaults\r\n\tp_info->mp_soundName = NULL;\r\n\tp_info->m_soundChecksum = 0;\r\n\tp_info->m_maxPitch = 100.0f;\r\n\tp_info->m_minPitch = 100.0f;\r\n\tp_info->m_maxVol = 100.0f;\r\n\tp_info->m_minVol = 0.0f;\r\n\tp_info->m_loadPitch = 100.0f;\r\n\tp_info->m_loadVol = 100.0f;\r\n\r\n\tp_sound->GetString( CRCD(0x7713c7b,\"sound\"), &p_info->mp_soundName );\r\n\tif ( !p_info->mp_soundName )\r\n\t{\r\n\t\tDbg_MsgAssert(0, ( \"Need the name of a sound in s_get_sound_info\" ));\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Calculate checksum\r\n\tconst char\t*pNameMinusPath\t= p_info->mp_soundName;\r\n\tint\t\t\tstringLength\t= strlen( p_info->mp_soundName );\r\n\tfor( int i = 0; i < stringLength; i++ )\r\n\t{\r\n\t\tif(( p_info->mp_soundName[i] == '\\\\' ) || ( p_info->mp_soundName[i] == '/' ))\r\n\t\t\tpNameMinusPath = &p_info->mp_soundName[i + 1];\r\n\t}\r\n\t\r\n\tp_info->m_soundChecksum = Script::GenerateCRC( pNameMinusPath );\r\n\r\n\tp_sound->GetFloat( CRCD(0xfa3e14c5,\"maxPitch\"), &p_info->m_maxPitch );\r\n\tp_sound->GetFloat( CRCD(0x1c5ebb24,\"minPitch\"), &p_info->m_minPitch );\r\n\t\r\n\tp_sound->GetFloat( CRCD(0x693daaf,\"maxVol\"), &p_info->m_maxVol );\r\n\tp_sound->GetFloat( CRCD(0x4391992d,\"minVol\"), &p_info->m_minVol );\r\n\r\n\tp_sound->GetFloat( CRCD(0xf573682f,\"loadPitch\"), &p_info->m_loadPitch );\r\n\tp_sound->GetFloat( CRCD(0x312ccbcf,\"loadVol\"), &p_info->m_loadVol );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\t\tCTerrainManager::s_load_action_sound( Script::CStruct* p_sound )\r\n{\r\n\tDbg_MsgAssert(p_sound, (\"s_load_action_sound given NULL sound CStruct\"));\r\n\t\r\n\tSTerrainSoundInfo soundInfo;\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tbool result = \r\n\t#endif\r\n\ts_get_sound_info(p_sound, &soundInfo);\r\n\tDbg_Assert(result);\r\n\r\n\tSfx::CSfxManager::Instance()->LoadSound( soundInfo.mp_soundName, 0, 0.0f, soundInfo.m_loadPitch, soundInfo.m_loadVol );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\t\tCTerrainManager::s_load_action_sound_struct( Script::CStruct* p_actions, ETerrainActionType action )\r\n{\r\n\tDbg_MsgAssert(p_actions, (\"s_load_action_sound_struct given NULL action CStruct\"));\r\n\r\n\tScript::CStruct *p_sound;\r\n\r\n\tuint32 checksum = s_get_action_checksum(action);\r\n\r\n\t// sound is a single sound structure, so just load it\r\n\tif (p_actions->GetStructure(checksum, &p_sound))\r\n\t{\r\n\t\ts_load_action_sound(p_sound);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// sound is an array of sound structures, all of which must be loaded\r\n\tScript::CArray* p_float_indexed_sound_array;\r\n\tp_actions->GetArray(checksum, &p_float_indexed_sound_array, Script::ASSERT);\r\n\t\r\n\tfor (uint32 i = 0; i < p_float_indexed_sound_array->GetSize(); i++)\r\n\t{\r\n\t\tScript::CStruct* p_sound_action_struct = p_float_indexed_sound_array->GetStructure(i);\r\n\t\t\r\n\t\t// this entry is a single sound structure, so just load it\r\n\t\tif (p_sound_action_struct->GetStructure(CRCD(0x25f654c8, \"soundAction\"), &p_sound))\r\n\t\t{\r\n\t\t\ts_load_action_sound(p_sound);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\t// this entry is an array of sounds, all of which must be loaded\r\n\t\tScript::CArray* p_random_indexed_sound_array;\r\n\t\tp_sound_action_struct->GetArray(CRCD(0x25f654c8, \"soundAction\"), &p_random_indexed_sound_array, Script::ASSERT);\r\n\t\t\r\n\t\tfor (uint32 j = 0; j < p_random_indexed_sound_array->GetSize(); j++)\r\n\t\t{\r\n\t\t\tp_sound = p_random_indexed_sound_array->GetStructure(j);\r\n\t\t\ts_load_action_sound(p_sound);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef __NOPT_ASSERT__\r\nvoid\t\t\t\t\tCTerrainManager::s_check_terrain_loaded(ETerrainType terrain)\r\n{\r\n\t// Garrett: Comment the assert back in when the new plugin is released (on or after 2/20/03)\r\n\tif (!s_terrain_loaded[terrain])\r\n\t{\r\n//\t\tDbg_Message(\"****** ERROR: Trying to use terrain %d, which isn't loaded ******\", terrain);\r\n\t}\r\n//\tDbg_MsgAssert(s_terrain_loaded[terrain], (\"****** ERROR: Trying to use terrain %d, which isn't loaded ******\", terrain));\r\n}\r\n#endif __NOPT_ASSERT__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\t\tCTerrainManager::sReset()\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\t// Clear terrain loaded array\r\n\tfor (int i = 0; i < vNUM_TERRAIN_TYPES; i++)\r\n\t{\r\n\t\ts_terrain_loaded[i] = false;\r\n\t}\r\n#endif __NOPT_ASSERT__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\t\tCTerrainManager::sGetTerrainSoundInfo( STerrainSoundInfo *p_info, ETerrainType terrain,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   ETerrainActionType action, float soundChoice )\r\n{\r\n\tbool result = false;\r\n\r\n\tif (Sfx::NoSoundPlease()) return false;\r\n\r\n\tDbg_MsgAssert((terrain >= 0) && (terrain < vNUM_TERRAIN_TYPES), (\"Terrain type out of range\"));\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\t// Check that terrain is loaded\r\n\ts_check_terrain_loaded(terrain);\r\n#endif __NOPT_ASSERT__\r\n\r\n\tDbg_MsgAssert(p_info, (\"sGetTerrainSoundInfo given NULL STerrainSoundInfo\"));\r\n\r\n\t// Allocate new script structure for combining data\r\n\tScript::CStruct *p_actions = new Script::CStruct;\r\n\tScript::CStruct *p_sound;\r\n\r\n\tif (s_get_terrain_actions_struct(terrain, p_actions))\r\n\t{\r\n\t\tp_sound = s_get_action_sound_struct(p_actions, action, soundChoice);\r\n\t\tif (p_sound)\r\n\t\t{\r\n\t\t\t//Dbg_Message(\"Extracted sound:\");\r\n\t\t\t//Script::PrintContents(p_sound);\r\n\r\n\t\t\tresult = s_get_sound_info(p_sound, p_info);\r\n\t\t}\r\n\t}\r\n\r\n\t// Done with script data\r\n\tdelete p_actions;\r\n\r\n\treturn result;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\t\tCTerrainManager::sLoadTerrainSounds( ETerrainType terrain )\r\n{\r\n\tif (Sfx::NoSoundPlease()) return false;\r\n\r\n\tDbg_MsgAssert((terrain >= 0) && (terrain < vNUM_TERRAIN_TYPES), (\"Terrain type out of range\"));\r\n\r\n\tScript::CStruct *p_actions = new Script::CStruct;\r\n\r\n//\tSfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n//\tDbg_Assert(sfx_manager);\r\n\r\n\tif (s_get_terrain_actions_struct(terrain, p_actions))\r\n\t{\r\n\t\t// Go through each action\r\n\t\tfor (int action_idx = 0; action_idx < vNUM_ACTION_TYPES; action_idx++)\r\n\t\t{\r\n\t\t\ts_load_action_sound_struct(p_actions, (ETerrainActionType) action_idx);\r\n\t\t}\r\n\t}\r\n\r\n\t// Done with script data\r\n\tdelete p_actions;\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\t// Mark terrain loaded\r\n\ts_terrain_loaded[terrain] = true;\r\n#endif __NOPT_ASSERT__\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\t\tCTerrainManager::sPlaySound( ETerrainActionType action, ETerrainType terrain, const Mth::Vector &pos,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t float volPercent, float pitchPercent, float soundChoice, bool propogate )\r\n{\r\n\tif (Sfx::NoSoundPlease()) return;\r\n\t\r\n\tDbg_MsgAssert((terrain >= 0) && (terrain < vNUM_TERRAIN_TYPES), (\"Terrain type out of range\"));\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\t// Check that terrain is loaded\r\n\ts_check_terrain_loaded(terrain);\r\n#endif __NOPT_ASSERT__\r\n\r\n\t// need to write pitch as well\r\n\t// Replay::WriteSkaterSoundEffect(action,terrain,pos,volPercent);\r\n\t\r\n\tSfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();\r\n\tGameNet::Manager * gamenet_manager = GameNet::Manager::Instance();\r\n    \r\n\tSTerrainSoundInfo soundInfo;\r\n\tbool found = sGetTerrainSoundInfo( &soundInfo, terrain, action, soundChoice );\r\n\r\n\tif ( !found )\r\n\t{\r\n\t\t// no sounds are supposed to be played for this surface on this transition:\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif( propogate )\r\n\t{\r\n\t\tNet::Client* client;\r\n\t\tGameNet::MsgPlaySound msg;\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tclient = gamenet_manager->GetClient( 0 );\r\n\t\tDbg_Assert( client );\r\n\r\n\t\tmsg.m_WhichArray = (char) action;\r\n\t\tmsg.m_SurfaceFlag = (char) terrain;\r\n\t\tmsg.m_Pos[0] = (short) pos[X];\r\n\t\tmsg.m_Pos[1] = (short) pos[Y];\r\n\t\tmsg.m_Pos[2] = (short) pos[Z];\r\n\t\tmsg.m_VolPercent = (char) volPercent;\r\n\t\tmsg.m_PitchPercent = (char) pitchPercent;\r\n\t\tmsg.m_SoundChoice = (char) soundChoice;\r\n\r\n\t\tmsg_desc.m_Data = &msg;\r\n\t\tmsg_desc.m_Length = sizeof( GameNet::MsgPlaySound );\r\n\t\tmsg_desc.m_Id = GameNet::MSG_ID_PLAY_SOUND;\r\n\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t}\r\n\r\n\tSfx::sVolume vol;\r\n\tsfx_manager->SetVolumeFromPos( &vol, pos, sfx_manager->GetDropoffDist( soundInfo.m_soundChecksum ));\r\n\r\n\t// Adjust volume according to speed.\r\n\tvolPercent = sGetVolPercent( &soundInfo, volPercent );\r\n\tvol.PercentageAdjustment( volPercent );\r\n\t\r\n\tif (vol.IsSilent()) return;\r\n\t\r\n\tpitchPercent = sGetPitchPercent( &soundInfo, pitchPercent );\r\n\t\r\n\tsfx_manager->PlaySound( soundInfo.m_soundChecksum, &vol, pitchPercent, 0, NULL, soundInfo.mp_soundName );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// set the volume according to the range specified by the designers...\r\nfloat\t\t\t\t\tCTerrainManager::sGetVolPercent( STerrainSoundInfo *pInfo, float volPercent, bool clipToMaxVol )\r\n{\r\n\t\r\n\tDbg_MsgAssert(pInfo, (\"pInfo set to NULL.\"));\r\n\r\n\tif ( !( ( pInfo->m_minVol == 0.0f ) && ( pInfo->m_maxVol == 100.0f ) ) )\r\n\t{\r\n\t\tvolPercent = ( pInfo->m_minVol + PERCENT( ( pInfo->m_maxVol - pInfo->m_minVol ), volPercent ) );\r\n\t}\r\n\t\r\n\tif ( clipToMaxVol )\r\n\t{\r\n\t\tif ( volPercent > pInfo->m_maxVol )\r\n\t\t\tvolPercent = pInfo->m_maxVol;\r\n\t}\r\n\treturn ( volPercent );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\t\t\t\tCTerrainManager::sGetPitchPercent( STerrainSoundInfo *pInfo, float pitchPercent, bool clipToMaxPitch )\r\n{\r\n\t\r\n\tDbg_MsgAssert(pInfo, (\"pInfo set to NULL.\"));\r\n\r\n\tif ( !( ( pInfo->m_minPitch == 0.0f ) && ( pInfo->m_maxPitch == 100.0f ) ) )\r\n\t{\r\n\t\tpitchPercent = ( pInfo->m_minPitch + PERCENT( ( pInfo->m_maxPitch - pInfo->m_minPitch ), pitchPercent ) );\r\n\t}\r\n\t\r\n\tif ( clipToMaxPitch )\r\n\t{\r\n\t\tif ( pitchPercent > pInfo->m_maxPitch )\r\n\t\t\tpitchPercent = pInfo->m_maxPitch;\r\n\t}\r\n\treturn ( pitchPercent );\r\n}\r\n\r\n#if 0\r\n// Sound FX for the level...\r\n/*\tThe surface flag indicates which surface the skater is currently on (grass, cement, wood, metal)\r\n\twhichSound is the checksum from the name of the looping sound (should be loaded using LoadSound\r\n\t\tin the script file for each level)\r\n\twhichArray indicates whether this sound belongs in the list of wheels rolling sounds, or\r\n\t\tgrinding sounds, etc...\r\n*/\r\nvoid CSk3SfxManager::SetSkaterSoundInfo( int surfaceFlag, uint32 whichSound, int whichArray,\r\n\tfloat maxPitch, float minPitch, float maxVol, float minVol )\r\n{\r\n\t\r\n\tif (Sfx::NoSoundPlease()) return;\r\n\t\r\n\t// must initialize PInfo!\r\n\tint i;\r\n\tSfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();\r\n\r\n\tif ( NULL == sfx_manager->GetWaveTableIndex( whichSound ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Terrain sound not loaded! surface %d sound %s checksum %d soundType %d\",\r\n\t\t\tsurfaceFlag, Script::FindChecksumName( whichSound ), whichSound, whichArray ));\r\n\t\treturn;\r\n\t}\r\n\tint numEntries = mNumEntries[ whichArray ];\r\n\tSkaterSoundInfo\t*pArray = mSoundArray[ whichArray ];\r\n\tSkaterSoundInfo *pInfo = NULL;\r\n\t\r\n\tfor ( i = 0; i < numEntries; i++ )\r\n\t{\r\n\t\tif ( pArray[ i ].surfaceFlag == surfaceFlag )\r\n\t\t{\r\n\t\t\tDbg_Message( \"Re-defining soundtype %d for surfaceFlag %d\", whichArray, surfaceFlag );\r\n\t\t\tpInfo = &pArray[ i ];\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif ( !pInfo )\r\n\t{\r\n\t\tpInfo = &pArray[ mNumEntries[ whichArray ] ];\r\n\t\tmNumEntries[ whichArray ] += 1;\r\n\t\tDbg_MsgAssert( mNumEntries[ whichArray ] < vMAX_NUM_ENTRIES,( \"Array too small type %d.  Increase MAX_NUM_ENTRIES.\", whichArray ));\r\n\t}\r\n\t\r\n\tDbg_MsgAssert( pInfo,( \"Please fire Matt immediately after kicking him in the nuts.\" ));\r\n\t\r\n\t// surfaceFlag of zero will be used for the default\r\n\tpInfo->surfaceFlag = surfaceFlag;\r\n\t// if soundChecksum is zero, no sound will play on this surface.\r\n\tpInfo->soundChecksum = whichSound;\r\n\tpInfo->maxPitch = maxPitch;\r\n\tpInfo->minPitch = minPitch;\r\n\tpInfo->maxVol = maxVol;\r\n\tpInfo->minVol = minVol;\r\n\r\n} // end of SetSkaterSoundInfo( )\r\n\r\n#endif\r\n\r\n} // namespace Env\r\n"
  },
  {
    "path": "Code/Gel/Environment/terrain.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGel Module\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/environment/terrain.h\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\tGarrett Feb. 2003\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tTerrains and its properties (soundFX, etc.)\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_TERRAIN_H\r\n#define __GEL_TERRAIN_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/macros.h>\r\n#include <core/math.h>\r\n\r\n#include <gfx/nxflags.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CScriptStructure;\r\n\tclass CScript;\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Env\r\n{\r\n\r\n// these sound trigger values are also used to\r\n// communicate with the sounds.cpp module and scripted\r\n// soundfx for jumping/landing...\r\nenum ETerrainActionType\r\n{\r\n\tvTABLE_WHEELROLL = 0,\r\n\tvTABLE_GRIND, // on a rail...\r\n\tvTABLE_JUMP,\r\n\tvTABLE_LAND,\r\n\tvTABLE_BONK,\r\n\tvTABLE_GRINDJUMP,\r\n\tvTABLE_GRINDLAND,\r\n\tvTABLE_SLIDE, // on a rail\r\n\tvTABLE_SLIDEJUMP,\r\n\tvTABLE_SLIDELAND,\r\n\tvTABLE_CESS,\r\n\tvNUM_ACTION_TYPES,\r\n};\r\n\t\r\nstruct STerrainSoundInfo\r\n{\r\n\tconst char *mp_soundName;\r\n\tuint32\t\tm_soundChecksum;\t\t// Checksum of sound filename\r\n\tfloat\t\tm_maxPitch;\r\n\tfloat\t\tm_minPitch;\r\n\tfloat\t\tm_maxVol;\r\n\tfloat\t\tm_minVol;\r\n\tfloat\t\tm_loadPitch;\t\t\t// Values to use when the sound is loaded\r\n\tfloat\t\tm_loadVol;\r\n};\r\n\r\nstruct STerrainInfo\r\n{\r\n\tETerrainType\t\tm_type;\r\n\tbool\t\t\t\tm_loaded;\t\t// tells if being used by current level\r\n\tSTerrainSoundInfo\tm_sounds[vNUM_ACTION_TYPES];\r\n\r\n\tfloat\t\t\t\tm_friction;\r\n\t// etc, etc, etc\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  CTerrainManager\r\n{\r\n\t\r\npublic:\r\n\tstatic void\t\t\t\t\tsReset();\r\n\r\n\tstatic bool\t\t\t\t\tsGetTerrainSoundInfo( STerrainSoundInfo *p_info, ETerrainType terrain,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  ETerrainActionType action, float soundChoice = 0.0f );\r\n\r\n\tstatic bool\t\t\t\t\tsLoadTerrainSounds( ETerrainType terrain );\r\n\tstatic float\t\t\t\tsGetVolPercent( STerrainSoundInfo *pInfo, float volPercent, bool clipToMaxVol = false );\r\n\tstatic float\t\t\t\tsGetPitchPercent( STerrainSoundInfo *pInfo, float pitchPercent, bool clipToMaxVol = false );\r\n\r\n\tstatic void \t\t\t\tsPlaySound( ETerrainActionType action, ETerrainType terrain, const Mth::Vector &pos,\r\n\t\t\t\t\t\t\t\t\t\t\tfloat volPercent, float pitchPercent, float soundChoice, bool propogate = true );\r\n\r\n\tstatic ETerrainType\t\t\tsGetTerrainFromChecksum(uint32 checksum);\r\n\tstatic ETerrainActionType\tsGetActionFromChecksum(uint32 checksum);\r\n\r\n\r\nprivate:\r\n\r\n\tstatic uint32\t\t\t\ts_get_action_checksum(ETerrainActionType action);\r\n\r\n\tstatic bool\t\t\t\t\ts_get_terrain_actions_struct(ETerrainType terrain, Script::CStruct *p_actions);\r\n\tstatic Script::CStruct *\ts_get_action_sound_struct(Script::CStruct *p_actions, ETerrainActionType action, float soundChoice);\r\n\tstatic bool\t\t\t\t\ts_get_sound_info(Script::CStruct *p_sound, STerrainSoundInfo *p_info);\r\n\tstatic Script::CStruct *\ts_choose_sound_action(Script::CStruct *p_sound_action_struct);\r\n\t\r\n\tstatic void\t\t\t\t\ts_load_action_sound( Script::CStruct* p_sound );\r\n\tstatic void\t\t\t\t\ts_load_action_sound_struct( Script::CStruct* p_actions, ETerrainActionType action );\r\n\t\r\n\t\r\n\t//STerrainInfo \t\t\t\tsDefaultTerrainArray[ vNUM_TERRAIN_TYPES ];\t// This one is inited at the beginning and never changes\r\n\t//STerrainInfo \t\t\t\tsCurrentTerrainArray[ vNUM_TERRAIN_TYPES ];\t// This one is derived from the default and the level array\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\t\t\t// We check this array to make sure non-loaded terrains\r\n\tstatic void\t\t\t\t\ts_check_terrain_loaded(ETerrainType terrain);\r\n\r\n\tstatic bool\t\t\t\t\ts_terrain_loaded[ vNUM_TERRAIN_TYPES ];\r\n#endif __NOPT_ASSERT__\r\n};\r\n\r\n}  // namespace Env\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Event.h",
    "content": "#ifndef __GEL_EVENT_H\r\n#define __GEL_EVENT_H\r\n\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\tclass CScript;\r\n\tclass CStruct;\r\n\tclass CArray;\r\n}\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\nclass CObject;\r\nclass CTracker;\r\n\r\n\r\nclass CEvent\r\n{\r\n\tfriend class CTracker;\r\n\r\npublic:\r\n\r\n\tenum EEventLevel\r\n\t{\r\n\t\t// applies to target or source\r\n\t\tvSYSTEM_EVENT =\t0x36b2ee74\t\t// \"system\"\r\n\t};\r\n\r\n\t// should also add new event types to EventLog.q\r\n\tenum EEventType\r\n\t{\r\n\t\t// applies to type\r\n\t\tTYPE_FOCUS\t\t\t\t\t= 0x9d3fb516,\r\n\t\tTYPE_UNFOCUS\t\t\t\t= 0x4adf0cd3,\r\n\t\tTYPE_NOTIFY_CHILD_LOCK\t\t= 0x3056434f,\r\n\t\tTYPE_NOTIFY_CHILD_UNLOCK\t= 0x4a57316b,\r\n\t\tTYPE_PAD_UP\t\t\t\t\t= 0x30a4f836,\r\n\t\tTYPE_PAD_DOWN  \t\t\t\t= 0x0fd1ac26,\r\n\t\tTYPE_PAD_LEFT  \t\t\t\t= 0x6949db75,\r\n\t\tTYPE_PAD_RIGHT \t\t\t\t= 0x05ddd87c,\r\n\t\tTYPE_PAD_CHOOSE\t\t\t\t= 0x1e3e253b,\r\n\t\tTYPE_PAD_BACK\t\t\t\t= 0x7ee0fd2a,\r\n\t\tTYPE_PAD_SQUARE\t   \t\t\t= 0x5c3979e3,\r\n\t\tTYPE_PAD_CIRCLE\t   \t\t\t= 0x456d7433,\r\n\t\tTYPE_PAD_L1\t\t\t\t\t= 0xaa7f2028,\r\n\t\tTYPE_PAD_L2\t\t\t\t\t= 0x33767192,\r\n\t\tTYPE_PAD_L3\t\t\t\t\t= 0x44714104,\r\n\t\tTYPE_PAD_R1\t\t\t\t\t= 0x7e3e1ff7,\r\n\t\tTYPE_PAD_R2\t\t\t\t\t= 0xe7374e4d,\r\n\t\tTYPE_PAD_R3\t\t\t\t\t= 0x90307edb,\r\n\t\tTYPE_PAD_START \t\t\t\t= 0x2e6ef8e7,\r\n\t\tTYPE_PAD_SELECT\t\t\t\t= 0xda28fb8a,\r\n\t\t\r\n\t\t// these have been deprecated\r\n\t\t// Ryan: now they are reprecated again!\r\n\t\tTYPE_PAD_X\t\t\t\t\t= 0x6fb6a322,\r\n\t\tTYPE_PAD_TRIANGLE\t\t\t= 0xfe6869df,\r\n\t};\r\n\r\n\tenum EFlags\r\n\t{\r\n\t\tmREAD\t\t\t\t\t\t= (1<<0),\r\n\t\tmHANDLED\t\t\t\t\t= (1<<1),\r\n\t\tmCONTROLS_OWN_DATA\t\t\t= (1<<2),\r\n\t};\r\n\r\n\tuint32\t\t\t\t\t\tGetType() {return m_type;}\r\n\tuint32\t\t\t\t\t\tGetSource() {return m_source_id;}\r\n\tuint32\t\t\t\t\t\tGetTarget() {return m_target_id;}\r\n\tScript::CStruct *\t\t\tGetData() {return mp_data;}\r\n\r\n\tvoid\t\t\t\t\t\tMarkRead(uint32 receiverId = 0, uint32 script = 0);\r\n\tvoid\t\t\t\t\t\tMarkHandled(uint32 receiverId = 0, uint32 script = 0);\r\n\tbool\t\t\t\t\t\tWasHandled() {return (m_flags & mHANDLED);}\r\n\r\n\t/*\r\n\t\tHelper functions \r\n\t*/\r\n\r\n\t// for focus, pad events\r\n\tstatic int\t\t\t\t\tsExtractControllerIndex(CEvent *pEvent);\r\n\r\nprotected:\r\n\r\n\t\t\t\t\t\t\t\tCEvent();\r\n\t\t\t\t\t\t\t\t~CEvent();\r\n\t\r\n\tuint32\t\t\t\t\t\tm_type;\r\n\tuint32\t\t\t\t\t\tm_source_id;\r\n\tuint32\t\t\t\t\t\tm_target_id;\r\n\tuint32\t\t\t\t\t\tm_flags;\r\n\r\n\tScript::CStruct *\t\t\tmp_data;\r\n};\r\n\r\n\r\n\r\n\r\n/*\r\n\tNotes:\r\n\t-the event_filter() function automatically locks the associated CObject, so that no \r\n\tevent handling code or script will delete it during event_filter() or pass_event_to_listener(). \r\n\tThe danger is the CObject will delete the CEventListener.\r\n*/\r\nclass CEventListener\r\n{\r\n\tfriend class CTracker;\r\n\t\r\npublic:\r\n\r\n\t\t\t\t\t\t\t\tCEventListener();\r\n\tvirtual\t\t\t\t\t\t~CEventListener();\r\n\tvoid\t\t\t\t\t\tRegisterWithTracker(CObject *pObject);\r\n\r\nprotected:\r\n\r\n\tvoid\t\t\t\t\t\tevent_filter(CEvent *pEvent);\r\n\t\r\n\t// implement this function in subclasses for class-specific event handling\r\n\tvirtual void\t\t\t\tpass_event_to_listener(CEvent *pEvent) = 0;\r\n\r\n\t\r\n\tCObjectPtr\t\t\t\t\tmp_object;\r\n\tCEventListener *\t\t\tmp_next_listener;\r\n\tbool\t\t\t\t\t\tm_registered;\r\n\tint\t\t\t\t\t\t\tm_ref_count;\r\n};\r\n\r\n\r\n\r\n\r\nclass CEventHandlerTable\r\n{\r\n\tfriend class Script::CScript;\r\n\tfriend class CObject;\r\n\tfriend class CTracker;\r\n\r\npublic:\r\n\tenum \r\n\t{\r\n\t\t// when used, gets assigned to 'script' member of entry\r\n\t\tvDEAD_ENTRY\t\t\t\t= CRCC(0xc377c572, \"null_script\")\r\n\t};\r\n\t\r\n\tenum\r\n\t{\r\n\t\tvDEFAULT_GROUP\t\t\t= CRCC(0x1ca1ff20, \"Default\")\r\n\t};\r\n\t\r\n\t\r\n\tvoid\tGetDebugInfo(Script::CStruct *p_info);\r\n\r\npublic:  // temp public, for skater cleanup to prevent fragmentation\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\t\r\n\tvoid\t\t\t\t\t\tunregister_all(Script::CScript *p_script);\r\n#else\r\n\tvoid\t\t\t\t\t\tunregister_all(CObject *p_object);\r\n#endif\r\n\r\n\tvoid\t\t\t\t\t\tAddEvent(uint32 ex, uint32 scr, uint32 group, bool exception, Script::CStruct *p_params);\r\n\t\r\n\tstatic void\t\t\t\t\tsPrintTable ( CEventHandlerTable* table );\r\nprotected:\r\n\r\n\t\t\t\t\t\t\t\tCEventHandlerTable();\r\n\t\t\t\t\t\t\t\t~CEventHandlerTable();\r\n\r\n\r\n\tvoid\t\t\t\t\t\tadd_from_script(Script::CArray *pArray, bool replace = false);\r\n\tvoid\t\t\t\t\t\tremove_entry(uint32 type);\r\n\tvoid\t\t\t\t\t\tremove_group(uint32 group = vDEFAULT_GROUP);\r\n\tvoid\t\t\t\t\t\tcompress_table();\r\n\tvoid\t\t\t\t\t\tset_event_enable(uint32 type, bool state);\r\n\t\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tvoid\t\t\t\t\t\tpass_event(CEvent *pEvent, Script::CScript *pScript, bool broadcast = false);\r\n\tvoid\t\t\t\t\t\tregister_all(Script::CScript *p_script);\r\n#else\t\r\n\tvoid\t\t\t\t\t\tpass_event(CEvent *pEvent, CObject *pObject, bool broadcast = false);\r\n\tvoid\t\t\t\t\t\tregister_all(CObject *p_object);\r\n#endif\t\r\n\t\r\n\tstruct Entry\r\n\t{\r\n\t\tuint32\t\t\t\t\ttype;\r\n\t\tuint32\t\t\t\t\tscript;\r\n\t\tuint32\t\t\t\t\tgroup;\r\n\t\t\r\n\t\t// if false, script won't be run when event\r\n\t\t// of matching type received\r\n\t\tbool\t\t\t\t\tenabled;\r\n\t\t\r\n\t\t// if \"exception\" is true, then the script is jumped to, rather than called.\r\n\t\tbool\t\t\t\t\texception;\r\n\t\t\r\n\t\t// if \"broadcast\" is true, then this handler will also respont to broadcast events\r\n\t\tbool\t\t\t\t\tbroadcast;\r\n\t\t\t\r\n\t\tScript::CStruct\t\t*\tp_params;\r\n\t};\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\npublic:\r\n#endif\r\n\tEntry *\t\t\t\t\t\tmp_tab;\r\n\tint\t\t\t\t\t\t\tm_num_entries;\r\n\tbool\t\t\t\t\t\tm_valid;\r\n\tbool\t\t\t\t\t\tm_changed;\t\t// set if table changed while running an event\r\n\tint\t\t\t\t\t\t\tm_in_immediate_use_counter; // by pass_event()\r\n};\r\n\r\n\r\n\r\n}\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Input/InpMan.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tInput (INP) \t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tinpman.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/26/2000\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tInput manager code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n\r\n#ifdef __NOPT_DEBUG__\r\n#include <sys/timer.h>\r\n#endif\r\n\r\n#include <sys/sioman.h>\r\n#include <sys/siodev.h>\r\n \r\n#include <gel/inpman.h>\r\n\r\n#include <gel/scripting/script.h> \r\n#include <gel/scripting/checksum.h> \r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Inp\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefineSingletonClass( Manager, \"Input Manager\" );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nManager::Manager ( void )\r\n{\r\n\t\r\n\tint i;\r\n\t\r\n\tSIO::Manager * sio_manager = SIO::Manager::Instance();\r\n\r\n\tm_process_handlers_task = new Tsk::Task< Manager >( process_handlers, *this, Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_PROCESS_HANDLERS );\r\n\tfor( i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n\t\tm_server[i].m_device = sio_manager->GetDeviceByIndex( i );\r\n\t}\r\n\r\n\tm_override_pad_with_stick = true;\r\n\tDbg_AssertType( m_process_handlers_task, Tsk::Task< Manager > );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager( void )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( m_process_handlers_task, Tsk::Task< Manager > );\r\n\tdelete m_process_handlers_task;   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::process_handlers( const Tsk::Task< Manager >& task )\r\n{\r\n\t\r\n\r\n\tint i;\r\n\tManager&\tmanager = task.GetData();      \r\n\r\n\tfor( i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n\t\t// See if we hit the end of our record/playback buffers\r\n\t\tif( ( manager.m_server[i].m_data_in ) &&\r\n\t\t\t( manager.m_server[i].m_data_in >= manager.m_server[i].m_data_in_end ))\r\n\t\t{\r\n\t\t\tmanager.m_server[i].m_data_in = NULL;\r\n\t\t}\r\n\t\tif( ( manager.m_server[i].m_data_out ) &&\r\n\t\t\t( manager.m_server[i].m_data_out >= manager.m_server[i].m_data_out_end ))\r\n\t\t{\r\n\t\t\tmanager.m_server[i].m_data_out = NULL;\r\n\t\t}\r\n\t\t\r\n        manager.m_server[i].service_handlers();\r\n\t}   \r\n}\r\n\r\n// Note: The order of these checksums must match the corresponding order of the PAD_ defines\r\n// for the buttons in inpman.h\r\nstatic uint32 ButtonChecksums[PAD_NUMBUTTONS]=\r\n{\r\n\t0x0,\t\t// Nowt\r\n\t0xbc6b118f, // Up\r\n\t0xe3006fc4, // Down\r\n\t0x85981897, // Left\r\n\t0x4b358aeb, // Right\r\n\t0xb7231a95, // UpLeft\r\n\t0xa50950c5, // UpRight\r\n\t0xd8847efa, // DownLeft\r\n\t0x786b8b68, // DownRight\r\n\t0x2b489a86, // Circle\r\n\t0x321c9756, // Square\r\n\t0x7323e97c, // X\r\n\t0x20689278, // Triangle\r\n\t0x26b0c991, // L1\r\n\t0xbfb9982b, // L2\r\n\t0xc8bea8bd, // L3\r\n\t0xf2f1f64e, // R1\r\n\t0x6bf8a7f4, // R2\r\n\t0x1cff9762, // R3\r\n\t0x767a45d7, // Black\r\n\t0xbd30325b, // White\r\n\t0x9d2d8850, // Z\r\n};\t\r\n\r\nuint32 GetButtonChecksum( int whichButton )\r\n{\r\n\t\r\n\tDbg_MsgAssert( ( whichButton > 0 ) && ( whichButton < PAD_NUMBUTTONS ), ( \"button %d out of range\", whichButton ) );\r\n\treturn ( ButtonChecksums[ whichButton ] );\r\n}\r\n\r\nint GetButtonIndex(uint32 Checksum)\r\n{\r\n\t\r\n\tfor (int i=1; i<PAD_NUMBUTTONS; ++i)\r\n\t{\r\n\t\tif (ButtonChecksums[i]==Checksum)\r\n\t\t{\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\tDbg_MsgAssert(0,(\"Bad button name '%s' sent to GetButtonIndex\",Script::FindChecksumName(Checksum)));\r\n\treturn 0;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tManager::RecordInput( int index, RecordedData *data_buffer, int byte_length )\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert( index < SIO::vMAX_DEVICES,( \"Invalid controller index\" ));\r\n\tDbg_Assert( data_buffer );\r\n\t\r\n\tm_server[index].m_data_out = data_buffer;\r\n\tm_server[index].m_data_out_end = (sint8 *) data_buffer + byte_length;   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::PlaybackInput( int index, RecordedData *recorded_input, int byte_length )\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert( index < SIO::vMAX_DEVICES,( \"Invalid controller index\" ));\r\n\tDbg_Assert( recorded_input );   \r\n\t\r\n\tm_server[index].m_data_in = recorded_input;\r\n\tm_server[index].m_data_in_end = (sint8 *) recorded_input + byte_length;  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::PushInputLogicTasks( void )\r\n{\r\n\t\r\n\t\r\n\tint i;\r\n\r\n\tfor( i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n        m_server[i].m_handler_stack.Push();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::PopInputLogicTasks( void )\r\n{\r\n\t\r\n\r\n\tint i;\r\n\r\n\tfor( i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n        m_server[i].m_handler_stack.Pop();\r\n\t}\r\n}\r\n\r\nbool\tManager::ActuatorEnabled( int i )\r\n{\r\n\t\r\n\tDbg_MsgAssert(i>=0 && i<SIO::vMAX_DEVICES,(\"Bad actuator index sent to DisableActuator\"));\r\n\tif (m_server[i].m_device)\r\n\t{\r\n\t\treturn m_server[i].m_device->Enabled();\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* K: Disables the actuators on all devices.                      */\r\n/* Used by the VibrationOff script command.\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::DisableActuators( void )\r\n{\r\n\t\r\n\r\n\tint i;\r\n\r\n\tfor( i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n\t\tif (m_server[i].m_device)\r\n\t\t{\r\n\t\t\tm_server[i].m_device->DisableActuators();\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n// Disables just one actuator. Called by the VibrationOff script command.\r\nvoid\tManager::DisableActuator( int i )\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert(i>=0 && i<SIO::vMAX_DEVICES,(\"Bad actuator index sent to DisableActuator\"));\r\n\tif (m_server[i].m_device)\r\n\t{\r\n\t\tm_server[i].m_device->DisableActuators();\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* K: Enables the actuators on all devices.                       */\r\n/* Used by the VibrationOn script command.\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::EnableActuators( void )\r\n{\r\n\t\r\n\r\n\tint i;\r\n\r\n\tfor( i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n\t\tif (m_server[i].m_device)\r\n\t\t{\r\n\t\t\tm_server[i].m_device->EnableActuators();\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n// Enables just one actuator. Called by the VibrationOn script command.\r\nvoid\tManager::EnableActuator( int i )\r\n{\r\n\t\r\n\tDbg_MsgAssert(i>=0 && i<SIO::vMAX_DEVICES,(\"Bad actuator index %i sent to EnableActuator\", i));\r\n\tif (m_server[i].m_device)\r\n\t{\r\n\t\tm_server[i].m_device->EnableActuators();\r\n\t}\t\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Mick: stops the actuators on all devices.                      */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::ResetActuators( void )\r\n{\r\n\t\r\n\r\n\tint i;\r\n\r\n\tfor( i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n\t\tif (m_server[i].m_device)\r\n\t\t{\r\n\t\t\tm_server[i].m_device->ResetActuators();\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetAnalogStickOverride( bool should_override_pad )\r\n{\r\n\tm_override_pad_with_stick = should_override_pad;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ShouldAnalogStickOverride( void )\r\n{\r\n\treturn m_override_pad_with_stick;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Inp\r\n"
  },
  {
    "path": "Code/Gel/Input/inpserv.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tInput (INP) \t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tinpserv.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/31/2000\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tInput server code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n\r\n\r\n\r\n#ifdef __NOPT_DEBUG__\r\n#include <sys/timer.h>\r\n#endif\r\n\r\n#include <sys/demo.h>\r\n#include <sys/sioman.h>\r\n#include <sys/siodev.h>\r\n \r\n#include <gel/inpman.h>\r\n\r\n#include <string.h>\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#include <gfx/ngps/p_memview.h>\t  \t\t// Mick:  needed for low level input patch bypassing task system\r\n#include <libscedemo.h>\t\t\t\t\t// Mick: needed for low level inactivity timeout on PS2 demo disk\r\n#elif defined( __PLAT_NGC__ )\r\n#include <gfx/ngc/p_memview.h>\r\n#endif\r\n\r\n#include <sys/config/config.h>\r\n\r\n#ifdef\t__PLAT_NGPS__\r\nextern\tsceDemoEndReason demo_exit_reason;\r\nextern  int\t\tinactive_time;\r\nextern  int\t\tinactive_countdown;\r\nextern  int\t\tgameplay_time;\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Inp\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Used to map digital input to analog events in case of no analog button support\r\nstatic  int adc_table[][2] = \r\n{\r\n    { Data::mD_L3,        Data::vA_L3 },\r\n    { Data::mD_R3,        Data::vA_R3 },\r\n    { Data::mD_L2,        Data::vA_L2 },\r\n    { Data::mD_R2,        Data::vA_R2 },\r\n    { Data::mD_L1,        Data::vA_L1 },\r\n    { Data::mD_R1,        Data::vA_R1 },\r\n    { Data::mD_TRIANGLE,  Data::vA_TRIANGLE },\r\n    { Data::mD_CIRCLE,    Data::vA_CIRCLE },\r\n    { Data::mD_X,         Data::vA_X },\r\n    { Data::mD_SQUARE,    Data::vA_SQUARE },\r\n    { Data::mD_UP,        Data::vA_UP },\r\n    { Data::mD_RIGHT,     Data::vA_RIGHT },\r\n    { Data::mD_DOWN,      Data::vA_DOWN },\r\n    { Data::mD_LEFT,      Data::vA_LEFT },\r\n    { Data::mD_BLACK,     Data::vA_BLACK },\r\n    { Data::mD_WHITE,     Data::vA_WHITE },\r\n    { Data::mD_Z,         Data::vA_Z },\r\n//\t{ Data::mD_SELECT,\t  Data::vA_SELECT },\r\n    { 0,                  0 }\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Mick: Controller info is made public for quick and easy debug test\r\n// it sould not be used for any shippable code....\r\nuint32\tgDebugButtons[SIO::vMAX_DEVICES];\r\nuint32\tgDebugBreaks[SIO::vMAX_DEVICES];\r\nuint32\tgDebugMakes[SIO::vMAX_DEVICES];\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Server::service_handlers( void )\r\n{\r\n//    \r\n    \r\n    unsigned char *control_data;\r\n\tData *handler_data;\r\n    Flags<SIO::Capabilities> caps;\r\n\r\n\t// If we are getting our input from recorded data, set all depended controller data from recorded data   \r\n\tif( m_data_in && m_data_in->m_valid )\r\n\t{\r\n\t\tint i;\r\n\t\t\r\n\t\tm_data.m_prev = m_data.m_cur;\r\n\t\tm_data.m_cur = m_data_in->m_cur;\t\t// Get digital input from buffer\r\n\t\tm_data.m_new = m_data.m_prev ^ m_data.m_cur;\r\n\t\tm_data.m_Buttons = m_data.m_cur;\r\n\t\tm_data.m_Makes = m_data.m_new & m_data.m_cur;\r\n\t\tm_data.m_Breaks = m_data.m_new & ~m_data.m_cur;\r\n\t\t\r\n\t\tfor( i = 0; i < Data::vMAX_ANALOG_EVENTS; i++ )\t// Get analog input from buffer\r\n\t\t{      \r\n\t\t\tm_data.m_Event[i] = m_data_in->m_event[i];\r\n\t\t}\r\n\t\t\r\n\t\tm_handler_stack.Process();\r\n\t\t\r\n\t\tm_data_in++;\r\n\t\treturn;\r\n\t}\r\n\t\t\t\r\n\tif( ( m_device ) &&\r\n\t\t( m_device->HasValidControlData()))\r\n    {   \r\n\t\tInp::Manager * inp_manager = Inp::Manager::Instance();\r\n\r\n        control_data = m_device->GetControlData();\r\n        handler_data = &m_data;\r\n        caps = m_device->GetCapabilities();\r\n        Dbg_Assert( control_data );\r\n\t\t\r\n\t\tif( m_data_out )\r\n\t\t{\r\n\t\t\tm_data_out->m_valid = FALSE;\r\n\t\t}\r\n\r\n        if( control_data[0] == 0 )  // Valid controller communication\r\n        {\r\n            unsigned char controller_type;\r\n            \r\n            controller_type = control_data[1] >> 4;  // top 4 bits contain controller type\r\n            handler_data->m_prev = handler_data->m_cur;\r\n\t\t\t// Regular buttons\r\n            handler_data->m_cur = 0xFFFF ^ (( control_data[2] << 8 ) | control_data[3] );\r\n\t\t\t// The XBox black & white and NGC Z buttons.\r\n\t\t\thandler_data->m_cur |= (control_data[20]<<16);\r\n\t\t\t\r\n\t\t\t\r\n\t\t\thandler_data->m_new = handler_data->m_prev ^ handler_data->m_cur;\r\n\t\t\t\r\n\t\t\thandler_data->m_Buttons = handler_data->m_cur;         \r\n            handler_data->m_Makes = handler_data->m_new & handler_data->m_cur;\r\n            handler_data->m_Breaks = handler_data->m_new & ~handler_data->m_cur;\r\n            \r\n            switch( controller_type )\r\n            {\r\n            case SIO::Device::vNEGI_COM:\r\n                // TODO: Handle \r\n                Dbg_MsgAssert( 0,( \"Unsupported Device Type\\n\" ));\r\n                break;\r\n\r\n            case SIO::Device::vKONAMI_GUN:\r\n                // TODO: Handle \r\n                Dbg_MsgAssert( 0,( \"Unsupported Device Type\\n\" ));\r\n                break;\r\n\r\n            case SIO::Device::vDIGITAL_CTRL:\r\n                handler_data->ConvertDigitalToAnalog();\r\n                break;                                                   \r\n\r\n            case SIO::Device::vNAMCO_GUN:\r\n                // TODO: Handle \r\n                Dbg_MsgAssert( 0,( \"Unsupported Device Type\\n\" ));\r\n                break;\r\n\r\n            case SIO::Device::vJOYSTICK:\r\n                handler_data->m_Event[Data::vA_RIGHT_X] = control_data[4];\r\n                handler_data->m_Event[Data::vA_RIGHT_Y] = control_data[5];\r\n                handler_data->m_Event[Data::vA_LEFT_X] = control_data[6];\r\n                handler_data->m_Event[Data::vA_LEFT_Y] = control_data[7];\r\n                handler_data->ConvertDigitalToAnalog();\r\n\t\t\t\tif( inp_manager->ShouldAnalogStickOverride())\r\n\t\t\t\t{\r\n\t\t\t\t\thandler_data->OverrideAnalogPadWithStick();\r\n\t\t\t\t}\r\n                break;\r\n\r\n            case SIO::Device::vANALOG_CTRL:\r\n                //if( caps.TestMask( SIO::mANALOG_BUTTONS ))\r\n\t\t\t\tif( m_device->GetButtonMode() == SIO::vANALOG )\r\n                {\r\n                    memcpy( handler_data->m_Event, &control_data[4], Data::vMAX_ANALOG_EVENTS );\r\n                }\r\n                else\r\n                {\r\n                    handler_data->m_Event[Data::vA_RIGHT_X] = control_data[4];\r\n                    handler_data->m_Event[Data::vA_RIGHT_Y] = control_data[5];\r\n                    handler_data->m_Event[Data::vA_LEFT_X] = control_data[6];\r\n                    handler_data->m_Event[Data::vA_LEFT_Y] = control_data[7];\r\n                    handler_data->ConvertDigitalToAnalog();\r\n                    handler_data->handle_analog_tolerance();\r\n\t\t\t\t\tif( inp_manager->ShouldAnalogStickOverride())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\thandler_data->OverrideAnalogPadWithStick();\r\n\t\t\t\t\t}\r\n                }\r\n                break;\r\n\r\n            case SIO::Device::vFISHING_CTRL:\r\n                // TODO: Handle \r\n                Dbg_MsgAssert( 0,( \"Unsupported Device Type\\n\" ));\r\n                break;\r\n                \r\n            case SIO::Device::vJOG_CTRL:        \r\n                // TODO: Handle \r\n                Dbg_MsgAssert( 0,( \"Unsupported Device Type\\n\" ));\r\n                break;\r\n\r\n            }\r\n            \r\n\t\t\tif( m_data_out )\r\n\t\t\t{\r\n\t\t\t\tint i;\r\n\t\t\t\t\r\n\t\t\t\tm_data_out->m_cur = handler_data->m_cur;\r\n\t\t\t\tm_data_out->m_valid = TRUE;\r\n\t\t\t\tfor( i = 0; i < Data::vMAX_ANALOG_EVENTS; i++ )\t// Get analog input from buffer\r\n\t\t\t\t{      \r\n\t\t\t\t\tm_data_out->m_event[i] = handler_data->m_Event[i];\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tm_data_out++;\r\n\t\t\t}\r\n\r\n\t\t\t// Make simple controller buttons accessible at global level\r\n\t\t\t// for debugging tools\t\t\t\r\n\t\t\t\r\n\t\t\tif (m_device)\r\n\t\t\t{\r\n\t\t\t\tgDebugButtons[m_device->GetIndex()] = m_data.m_Buttons; \t\t\t\t\t\t\t\r\n\t\t\t\tgDebugMakes[m_device->GetIndex()] = m_data.m_Makes; \t\t\t\t\t\t\t\r\n\t\t\t\tgDebugBreaks[m_device->GetIndex()] = m_data.m_Breaks; \t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t#ifdef\t__PLAT_NGPS__\r\n\t\t\t\tMemView_Input(m_data.m_Buttons, m_data.m_Makes, m_data.m_Breaks );\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t// Mick: added test for \"Select\" which will now exit the game if in demo mode\r\n\t\t\t\t\r\n\t\t\t\tif (Config::Bootstrap())\r\n\t\t\t\t{\r\n\r\n\t\t\t\t\tbool exit = false;\r\n\t\t\r\n\t\t\t\t\tif (m_data.m_Buttons ||\t\t\t\r\n\t\t\t\t\t\t(handler_data->m_Event[Data::vA_RIGHT_X] !=128)||\r\n\t\t\t\t\t\t(handler_data->m_Event[Data::vA_RIGHT_Y] !=128)\t||\r\n\t\t\t\t\t\t(handler_data->m_Event[Data::vA_LEFT_X] !=128) \t||\r\n\t\t\t\t\t\t(handler_data->m_Event[Data::vA_LEFT_Y] !=128))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//printf (\"%d activity....\\n\", inactive_countdown);\r\n\t\t\t\t\t\tinactive_countdown = inactive_time;\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\r\n\t\t\t\t\tif (m_device->GetIndex() == 0)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif (inactive_countdown)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tinactive_countdown --;\r\n\t\t\t\t\t\t\tif (inactive_countdown == 0)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tprintf (\"Exiting due to inactivity\\n\");\r\n\t\t\t\t\t\t\t\texit = true;  \r\n\t\t\t\t\t\t\t\tdemo_exit_reason = SCE_DEMO_ENDREASON_PLAYABLE_INACTIVITY_TIMEOUT;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (gameplay_time)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tgameplay_time--;\r\n\t\t\t\t\t\t\tif (gameplay_time == 0)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tprintf (\"Exiting due to gameplay timer exiting\\n\");\r\n\t\t\t\t\t\t\t\texit = true;  \r\n\t\t\t\t\t\t\t\tdemo_exit_reason = SCE_DEMO_ENDREASON_PLAYABLE_GAMEPLAY_TIMEOUT;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tif ((m_data.m_Buttons & Inp::Data::mD_SELECT) && (m_data.m_Buttons & Inp::Data::mD_START))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\texit = true;  \r\n\t\t\t\t\t\tdemo_exit_reason = SCE_DEMO_ENDREASON_PLAYABLE_QUIT;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tif ( exit )\r\n\t\t\t\t\t{\r\n                        Sys::ExitDemo();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t#endif\t\t\t\t  \r\n\t\t\t}\r\n\t\t\t\r\n            // At this point, we have obtained and converted valid controller information\r\n            // Now propogate it to clients\r\n            m_handler_stack.Process();\r\n        }\r\n    }            \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Data::handle_analog_tolerance( void )\r\n{\r\n\r\n\t// copy unclamped values over before we clamp them\t\t\t\t\t\t\t\t\t\t  \r\n\tm_Event[Data::vA_RIGHT_X_UNCLAMPED] = m_Event[Data::vA_RIGHT_X];\t\r\n\tm_Event[Data::vA_RIGHT_Y_UNCLAMPED] = m_Event[Data::vA_RIGHT_Y];\t\r\n\tm_Event[Data::vA_LEFT_X_UNCLAMPED] = m_Event[Data::vA_LEFT_X];\t\r\n\tm_Event[Data::vA_LEFT_Y_UNCLAMPED] = m_Event[Data::vA_LEFT_Y];\t\r\n\t\t\t\t\t \r\n\t\t\t\t\t \r\n\tif( Mth::Abs( vANALOGUE_CENTER - m_Event[Data::vA_RIGHT_X] ) <= vANALOGUE_TOL )\r\n    {\r\n        m_Event[Data::vA_RIGHT_X] = vANALOGUE_CENTER;\r\n    }\r\n\r\n    if( Mth::Abs( vANALOGUE_CENTER - m_Event[Data::vA_RIGHT_Y] ) <= vANALOGUE_TOL )\r\n    {\r\n        m_Event[Data::vA_RIGHT_Y] = vANALOGUE_CENTER;\r\n    }\r\n\r\n    if( Mth::Abs( vANALOGUE_CENTER - m_Event[Data::vA_LEFT_X] ) <= vANALOGUE_TOL )\r\n    {\r\n        m_Event[Data::vA_LEFT_X] = vANALOGUE_CENTER;\r\n    }\r\n\r\n    if( Mth::Abs( vANALOGUE_CENTER - m_Event[Data::vA_LEFT_Y] ) <= vANALOGUE_TOL )\r\n    {\r\n        m_Event[Data::vA_LEFT_Y] = vANALOGUE_CENTER;\r\n    }\r\n\r\n// \"unclamped\", only zero the controllers if BOTH X and Y are in the dead zone\r\n// that way, we can smoothly go around the periphery, and get much better aiming ability\r\n// (improves the look-around camera, and the walking)\r\n\r\n\tif( Mth::Abs( vANALOGUE_CENTER - m_Event[Data::vA_RIGHT_X_UNCLAMPED] ) <= vANALOGUE_TOL \r\n\t&& Mth::Abs( vANALOGUE_CENTER - m_Event[Data::vA_RIGHT_Y_UNCLAMPED] ) <= vANALOGUE_TOL )\r\n    {\r\n        m_Event[Data::vA_RIGHT_X_UNCLAMPED] = vANALOGUE_CENTER;\r\n        m_Event[Data::vA_RIGHT_Y_UNCLAMPED] = vANALOGUE_CENTER;\r\n    }\r\n\r\n    if( Mth::Abs( vANALOGUE_CENTER - m_Event[Data::vA_LEFT_X_UNCLAMPED] ) <= vANALOGUE_TOL \r\n\t&& Mth::Abs( vANALOGUE_CENTER - m_Event[Data::vA_LEFT_Y_UNCLAMPED] ) <= vANALOGUE_TOL )\r\n    {\r\n        m_Event[Data::vA_LEFT_X_UNCLAMPED] = vANALOGUE_CENTER;\r\n        m_Event[Data::vA_LEFT_Y_UNCLAMPED] = vANALOGUE_CENTER;\r\n    }\r\n\t\r\n\t\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nServer::Server( void )\r\n{\r\n//    \r\n    \r\n\t\r\n\tm_data_in = NULL;\r\n\tm_data_out = NULL;\r\n\tm_data_in_end = NULL;\r\n\tm_data_out_end = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Server::RecordInput( RecordedData *data_buffer )\r\n{\r\n//    \r\n    \r\n\t\r\n\tDbg_Assert( data_buffer );\r\n\t\r\n\tm_data_out = data_buffer;   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Server::PlaybackInput( RecordedData *recorded_input )\r\n{\r\n//    \r\n    \r\n\t\r\n\tDbg_Assert( recorded_input );\r\n\t\r\n\tm_data_in = recorded_input;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n    \r\nvoid Data::MaskDigitalInput( int button_mask )\r\n{\r\n//    \r\n    \r\n\r\n\tm_Buttons &= ~button_mask;   \r\n\t\r\n#if 0 \t// old way of masking\r\n\tm_new = m_prev ^ m_Buttons;\r\n\tm_Makes = m_new & m_Buttons;\r\n\tm_Breaks = m_new & ~m_Buttons;\r\n#endif\r\n\t\r\n\tm_Makes &= ~button_mask;\r\n\tm_Breaks &= ~button_mask;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Data::MaskAnalogInput( int button_mask )\r\n{\r\n//    \r\n    \r\n\r\n\tint i, mask;   \r\n\t\t\r\n    mask = 1;\r\n\tfor( i = 0; i < vMAX_ANALOG_EVENTS; i++, mask <<= 1 )\r\n\t{\r\n\t\tif( button_mask & mask )\r\n\t\t{\r\n            // Analog stick is neutral at 128, all other buttons are neutral at 0\r\n            if( \r\n\t\t\t\t( i == vA_RIGHT_X ) ||\r\n                ( i == vA_RIGHT_Y ) ||\r\n                ( i == vA_LEFT_X  ) ||\r\n                ( i == vA_LEFT_Y  )\t||\r\n\t\t\t\t( i == vA_RIGHT_X_UNCLAMPED ) ||\r\n                ( i == vA_RIGHT_Y_UNCLAMPED ) ||\r\n                ( i == vA_LEFT_X_UNCLAMPED  ) ||\r\n                ( i == vA_LEFT_Y_UNCLAMPED  ))\r\n            {   \r\n                m_Event[i] = 128;\r\n            }\r\n            else\r\n            {\r\n                m_Event[i] = 0;\r\n            }\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Overrides Analog Pad with Analog Stick values if pad is not in */\r\n/* in use                                                         */\r\n/******************************************************************/\r\n\r\nvoid Data::OverrideAnalogPadWithStick( void )\r\n{\r\n\t\r\n\r\n\t// Only override analog pad if no analog input is present\r\n\tif( m_Buttons & ( mD_UP | mD_RIGHT | mD_DOWN | mD_LEFT ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif( m_Event[vA_LEFT_X] > vANALOGUE_CENTER )\r\n\t{\r\n\t\tm_Event[vA_RIGHT] = m_Event[vA_LEFT_X] - vANALOGUE_CENTER;\r\n\t\tm_Buttons |= mD_RIGHT;\r\n\t}\r\n\telse if( m_Event[vA_LEFT_X] < vANALOGUE_CENTER )\r\n\t{\r\n\t\tm_Event[vA_LEFT] = Mth::Abs( vANALOGUE_CENTER - m_Event[vA_LEFT_X] );\r\n\t\tm_Buttons |= mD_LEFT;\r\n\t}\r\n    \r\n\tif( m_Event[vA_LEFT_Y] < vANALOGUE_CENTER )\r\n\t{\r\n\t\tm_Event[vA_UP] = m_Event[Data::vA_LEFT_Y] - vANALOGUE_CENTER;\r\n\t\tm_Buttons |= mD_UP;\r\n\t}\r\n\telse if( m_Event[vA_LEFT_Y] > vANALOGUE_CENTER )\r\n\t{\r\n\t\tm_Event[vA_DOWN] = Mth::Abs( vANALOGUE_CENTER - m_Event[vA_LEFT_Y] );\r\n\t\tm_Buttons |= mD_DOWN;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Data::ConvertDigitalToAnalog( void )\r\n{\r\n\tint i;\r\n\r\n    for( i = 0; adc_table[i][0] > 0; i++ )\r\n\t{\r\n\t\tif( m_Buttons & adc_table[i][0] )  // If we have digital \"down\" convert to fully-pressed analog input\r\n\t\t{\r\n\t\t\tm_Event[adc_table[i][1]] = vMAX_ANALOG_VALUE;\r\n\t\t}\r\n        else\r\n        {\r\n            m_Event[adc_table[i][1]] = 0;\r\n        }\r\n\t}  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nData::Data( void )\r\n{\r\n    memset( m_Event, 0, vMAX_ANALOG_EVENTS );\r\n    m_Buttons = 0;\r\n\tm_cur = 0;\r\n    m_new = 0;\r\n    m_prev = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Inp\r\n"
  },
  {
    "path": "Code/Gel/MainLoop/Mainloop.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMain Loop (ML) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmainloop.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMain loop and support code\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gel/mainloop.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/task.h>\r\n\r\n#include <gfx/nx.h>\r\n\r\n#ifndef __PLAT_WN32__\r\n    #include <sys/profiler.h>\r\n#endif\r\n\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n    #include <gel/collision/batchtricoll.h>\r\n    #include <gel/soundfx/ngps/p_sfx.h>\r\n\r\n    namespace NxPs2\r\n    {\r\n        void\tWaitForRendering();\r\n\t\tvoid \tStuffAfterGSFinished();\r\n    }\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDbg_DefineProject( GEL, \"GEL Library\" )\r\n\r\nnamespace Mdl\r\n{\r\n\tvoid\tRail_DebugRender();\t\t\t// for debugging\r\n}\r\n\r\nnamespace Mlp\r\n{\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefineSingletonClass( Manager, \"Main Loop Manager\" );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nManager::Manager( void )\r\n{\r\n\t\r\n\t\r\n\tstart_render_hook = NULL;\r\n\tend_render_hook = NULL;\r\n\tdone = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager( void )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\tManager::service_system( void )\r\n{\r\n\t\r\n\r\n#ifndef __PLAT_WN32__\r\n#\tifdef __USE_PROFILER__\r\n\tSys::CPUProfiler->PushContext( 255, 0, 0 );\r\n#\tendif // __USE_PROFILER__\r\n#endif\r\n\r\n\tsystem_task_stack.Process (currently_profiling);\r\n\r\n#ifndef __PLAT_WN32__\r\n#\tifdef __USE_PROFILER__\r\n\tSys::CPUProfiler->PopContext();\r\n#\tendif // __USE_PROFILER__\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\tManager::game_logic( void )\r\n{\r\n\t\r\n\t\r\n#ifndef __PLAT_WN32__\r\n#\tifdef __USE_PROFILER__\r\n\tSys::CPUProfiler->PushContext( 0, 255, 0 );\r\n#\tendif // __USE_PROFILER__\r\n#endif\r\n\r\n//\tprintf (\"\\nTiming Logic\\n\"); \r\n\tlogic_task_stack.Process(currently_profiling);\r\n\r\n//\tprintf (\"\\nDumping Task List\\n\\n\");\t\r\n//\tlogic_task_stack.Dump();\r\n\r\n#ifndef __PLAT_WN32__\r\n#\tifdef __USE_PROFILER__\r\n\tSys::CPUProfiler->PopContext();\r\n#\tendif // __USE_PROFILER__\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::render_frame( void )\r\n{\r\n\t\r\n\t\r\n//\tprintf (\"############################## render_frame #############################\\n\");\t\r\n\t\r\n\r\n#ifndef __PLAT_WN32__\r\n#\tifdef __USE_PROFILER__\r\n\tSys::CPUProfiler->PushContext( 0, 0, 255 );\r\n#\tendif // __USE_PROFILER__\r\n#endif\r\n\r\n#\tifdef __PLAT_NGC__\r\n\tif( start_render_hook )\r\n\t{\r\n\t\tstart_render_hook->Call();\r\n\t}\r\n\tif( !display_tasks_paused )\r\n\t{\r\n\t\tdisplay_task_stack.Process( currently_profiling );\r\n\t}\r\n#\telse\r\n\tif (!display_tasks_paused)\r\n\t{\r\n\t\t// If paused don't call the start_render_hook\r\n\t\t// as this clears the none-visible frame buffer\r\n\t\t// which will result in a flash when display is unpaused\r\n\t\tif ( start_render_hook )\t\t\t// set up for rendering\r\n\t\t{\r\n\t\t\tstart_render_hook->Call();\r\n\t\t}\r\n\r\n//\t\tprintf (\"\\nTiming render\\n\"); \r\n\t\r\n\t\tdisplay_task_stack.Process(currently_profiling);\t\t// service rendering routines\r\n\t}\r\n#\tendif // __PLAT_NGC__\r\n\t\r\n#ifndef __PLAT_WN32__\r\n#\tifdef __USE_PROFILER__\r\n\tSys::CPUProfiler->PopContext();\r\n\tSys::CPUProfiler->PushContext( 255, 255, 0 );\r\n#\tendif // __USE_PROFILER__\r\n#endif\r\n\r\n\tif ( end_render_hook )\t\t\t\t// end rendering\r\n\t{\r\n\t\tend_render_hook->Call();\r\n\t}\r\n#ifndef __PLAT_WN32__\r\n#\tifdef __USE_PROFILER__\r\n\tSys::CPUProfiler->PopContext();\r\n#\tendif // __USE_PROFILER__\r\n#endif\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\t\tManager::MainLoop( void )\r\n{\r\n\t\r\n\r\n\tbool\t\t\t\t\t\t\t\told_flag = done;\t// push the current done flag\r\n\r\n\tdone = false;\r\n\r\n\twhile ( !done )\r\n\t{\r\n\t\r\n\t\tif (trigger_profiling)\r\n\t\t{\r\n\t\t\tprintf (\"\\nProfiling.....Start of main loop\\n\\n\");\r\n\t\t\ttrigger_profiling--;\r\n\t\t\tcurrently_profiling = 1;\r\n\t\t}\r\n\t\t\r\n\r\n#ifndef __PLAT_WN32__\r\n\r\n#ifdef\t__PLAT_NGPS__\t\t\r\n// for profiling on the PS2, we do a bit of the code from sPreRender here\r\n// so we can time the final waiting for GS\t\t\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::CPUProfiler->PushContext( 0,0,255 );\t\t// blue = wait for VU/DMA/GPU to finish\r\n#\tendif\t\t\r\n\t\tNxPs2::WaitForRendering();\t\t// PS2 Specific, wait for prior frame's DMA to finish\t\r\n\t\tNxPs2::StuffAfterGSFinished();\t\t// PS2 Specific, DMA altering stuff run after previous frame's DMA finished\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::CPUProfiler->PopContext(  );\r\n\t\tSys::CPUProfiler->PushContext( 128,0,0 );\t\t// red = wait for vblank\r\n#\tendif\t\t\r\n\t\tint framerate = Script::GetInteger(0x3214c818/*\"lock_framerate\"*/);\r\n\t\tif (framerate)\t// normal vsync\r\n\t\t{\r\n\t\t\tstatic uint64 next_vblanks= 0;\r\n\t\t\t// Still call VSync, as it updates some functions\r\n\t\t\tTmr::VSync();\r\n\t\t\twhile (Tmr::GetVblanks()<next_vblanks)\r\n\t\t\t{\r\n\t\t\t\t// just hanging until vblanks gets big enough\r\n\t\t\t}\r\n\t\t\tnext_vblanks = Tmr::GetVblanks() + framerate;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tTmr::VSync1();\r\n\t\t}\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::CPUProfiler->PopContext(  );\r\n#\tendif\t\t\r\n#endif\t\t\t\t\r\n#ifndef\t__PLAT_NGC__\t\t\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::Profiler::sStartFrame();\t\t  \t\t\r\n#\tendif\t\t\r\n#endif\t\t\r\n\t\t\r\n\t\tNx::CEngine::sPreRender();\t\t\t \t\t\t// start rendering previous frame's DMA list\r\n\r\n#ifdef\t__PLAT_NGPS__\t\t\r\n\t\tSfx::CSpuManager::sUpdateStatus();\t\t\t\t// Garrett: This should go into some system task, but I'll put it here for now\r\n#endif\r\n\r\n//\t\tSys::Profiler::sStartFrame();\t\t  \t\t\r\n#endif\r\n\r\n#ifdef\t__PLAT_NGC__\t\t\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::Profiler::sStartFrame();\t\t  \t\t\r\n#\tendif\t\t\r\n#\tendif\t\t\r\n\t\t\t\t\t \r\n\t\tservice_system();\r\n\r\n#if\tdefined(__PLAT_NGPS__) && defined(BATCH_TRI_COLLISION)\r\n\t\t// Enable VU0 collision\r\n\t\tbool got_vu0 = Nx::CBatchTriCollMan::sUseVU0Micro();\r\n\t\tDbg_Assert(got_vu0);\r\n#endif\r\n\r\n #ifdef\t__PLAT_NGPS__\t\t\r\n//\t\tsnProfSetRange( -1, (void*)0, (void*)-1);\r\n//\t\tsnProfSetFlagValue(0x01);\r\n #endif\r\n\r\n\t\tgame_logic();\t\t\r\n\r\n #ifdef\t__PLAT_NGPS__\t\t\r\n//\t\tsnProfSetRange( 4, (void*)NULL, (void*)-1);\r\n #endif\t\t\r\n\r\n\r\n#if\tdefined(__PLAT_NGPS__) && defined(BATCH_TRI_COLLISION)\r\n\t\t// Disable VU0 collision\r\n\t\tif (got_vu0)\r\n\t\t{\r\n\t\t\tNx::CBatchTriCollMan::sDisableVU0Micro();\r\n\t\t}\r\n#endif\r\n\r\n#ifndef __PLAT_WN32__\r\n\t\t// Display the memory contents, (if memview is active)\r\n\t\tMemView_Display();\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::CPUProfiler->PushContext( 255, 255, 0 );  // yellow = render world\r\n#\tendif\t\t\r\n\r\n #ifdef\t__PLAT_NGPS__\t\t\r\n//\t\tsnProfSetRange( -1, (void*)0, (void*)-1);\r\n//\t\tsnProfSetFlagValue(0x01);\r\n #endif\r\n\t\t\r\n\t\tNx::CEngine::sRenderWorld();\t\t\r\n#ifdef\t__PLAT_NGC__\t\t\r\n#ifdef\t\t__USE_PROFILER__\r\n\t\tSys::Render_Profiler();\t\t\r\n#endif\r\n#endif\r\n\t\t// Mick: bit of a patch here, we need some better debug hooks\r\n\t\tMdl::Rail_DebugRender();\r\n#\tifdef __USE_PROFILER__\r\n\t\t\tSys::CPUProfiler->PushContext( 0, 0, 0 );\t \t// Black (Under Yellow) = sPostRender\r\n#\tendif // __USE_PROFILER__\r\n\t\tNx::CEngine::sPostRender();\t\t  // Previous frames profiler is rendered here\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::CPUProfiler->PopContext(  );\r\n#\tendif\t\t\r\n\r\n\r\n\t\r\n\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::CPUProfiler->PopContext(  );\r\n#\tendif\t\t\r\n\t\tTmr::OncePerRender();\r\n #ifdef\t__PLAT_NGPS__\t\t\r\n//\t\tsnProfSetRange( 4, (void*)NULL, (void*)-1);\r\n #endif\t\t\r\n#endif\t\t\r\n\t\t\r\n\t\tcurrently_profiling = false;\r\n\r\n\t}\r\n\r\n\tdone = old_flag;\r\n}\r\n\r\nvoid Manager::ProfileTasks(int n)\r\n{\r\n\ttrigger_profiling = n;\r\n\tcurrently_profiling = 0;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::QuitLoop( void )\r\n{\r\n\t\r\n\r\n\tDbg_Notify( \"Exiting...\" );\r\n\r\n\tdone = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::DoGameLogic( void )\r\n{\r\n\tgame_logic();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mlp\r\n\r\n"
  },
  {
    "path": "Code/Gel/Module/modman.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tModule (MDL)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmodman.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tModule manager code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n\r\n#ifdef __NOPT_DEBUG__\r\n#include <sys/timer.h>\r\n#endif\r\n\r\n#include <gel/modman.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mdl\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefineSingletonClass( Manager, \"Module Manager\" );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nManager::Manager ( void )\r\n{\r\n\t\r\n\r\n\tprocess_modules_task = new Tsk::Task< Manager >( process_modules, *this, Tsk::BaseTask::Node::vSYSTEM_TASK_PRIORITY_PROCESS_MODULES );\r\n\tDbg_AssertType( process_modules_task, Tsk::Task< Manager > );\r\n\r\n\tcontrol_change = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager( void )\r\n{\r\n\t\r\n\t\r\n\tStopAllModules();\r\n\t\t\r\n\tDbg_AssertType( process_modules_task, Tsk::Task< Manager > );\r\n\tdelete process_modules_task;\r\n\t\r\n\tDbg_MsgAssert( module_list.IsEmpty(),( \r\n\t\t\"%d module%s still registered\\n\",\r\n\t\t\tmodule_list.CountItems(),\r\n\t\t\tmodule_list.CountItems() > 1 ? \"s\" : \"\" ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::process_modules( const Tsk::Task< Manager >& task )\r\n{\r\n\t\r\n\r\n\tModule*\t\t\t\t\tnext;\r\n\tModule*\t\t\t\t\tcurrent;\r\n\tLst::Search< Module >\tsh;\r\n\r\n\tManager&\tmanager = task.GetData();\r\n\r\n\tif ( !manager.control_change )\r\n\t{\r\n\t\treturn; // nothing to do\r\n\t}\r\n\r\n\tmanager.control_change = false;\r\n\t\r\n\tnext = sh.FirstItem( manager.module_list );\r\n\r\n\twhile ( next )\r\n\t{\r\n\t\tcurrent = next;\r\n\t\tnext = sh.NextItem();\t\t\t// get next item before excuting callback\r\n\r\n\t\tswitch ( current->state )\r\n\t\t{\r\n\t\t\tcase Module::vSTOPPED :\r\n\t\t\t{\r\n\t\t\t\tif (( current->command == Module::vSTART ) ||\r\n\t\t\t\t\t( current->command == Module::vRESTART ))\r\n\t\t\t\t{\r\n#ifndef __PLAT_XBOX__\r\n#ifndef __PLAT_NGC__\r\n#ifdef __NOPT_DEBUG__\r\n\t\t\t\tDbg_Notify ( \"Starting module %s @ %d\", current->GetName(), \r\n\t\t\t\t\tTmr::GetTime() ); // should use Game Clock not system clock\r\n#endif\r\n#endif\r\n#endif\r\n\t\t\t\t\tcurrent->v_start_cb();\r\n\t\t\t\t\tcurrent->state = Module::vRUNNING;\r\n\t\t\t\t\tcurrent->command = Module::vNONE;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase Module::vRUNNING :\r\n\t\t\t{\r\n\t\t\t\tif ( current->command == Module::vSTOP )\r\n\t\t\t\t{\r\n#ifndef __PLAT_XBOX__\r\n#ifndef __PLAT_NGC__\r\n#ifdef __NOPT_DEBUG__\r\n\t\t\t\t\tDbg_Notify ( \"Stopping module %s @ %d\", current->GetName(), \r\n\t\t\t\t\t\t Tmr::GetTime() ); // should use Game Clock not system clock\r\n#endif\r\n#endif\r\n#endif\r\n\t\t\t\t\tcurrent->v_stop_cb();\r\n\t\t\t\t\tcurrent->state = Module::vSTOPPED;\r\n\t\t\t\t\tcurrent->command = Module::vNONE;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( current->command == Module::vRESTART ) \r\n\t\t\t\t{\r\n#ifndef __PLAT_XBOX__\r\n#ifndef __PLAT_NGC__\r\n#ifdef __NOPT_DEBUG__\r\n\t\t\t\t\tDbg_Notify ( \"Restarting module %s @ %d\", current->GetName(), \r\n\t\t\t\t\t\tTmr::GetTime() ); // should use Game Clock not system clock\r\n#endif\r\n#endif\r\n#endif\r\n\t\t\t\t\tcurrent->v_stop_cb();\r\n\t\t\t\t\tcurrent->v_start_cb();               \r\n\t\t\t\t\tcurrent->command = Module::vNONE;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbreak;\r\n\t\t\t}        \r\n\r\n\t\t\tdefault:\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( false,( \"Invalid module control state\" ));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tManager::RegisterModule( Module &module )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType ( &module, Module );\r\n\r\n\tmodule_list.AddToTail ( module.node );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::UnregisterModule( Module &module )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( &module, Module );\r\n\r\n\tDbg_MsgAssert( module.node->InList(),( \"Module not Registered with Manager\" ));\r\n\r\n\tmodule.node->Remove();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::StartModule( Module &module )\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert( module.node->InList(),( \"Module not Registered with Manager\" ));\r\n\r\n\tif ( !module.Locked() )\r\n\t{\r\n\t\tmodule.command = Module::vSTART;\r\n\t\tcontrol_change = true;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::RestartModule( Module &module )\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert( module.node->InList(),( \"Module not Registered with Manager\" ));\r\n\r\n\tif ( !module.Locked() )\r\n\t{\r\n\t\tmodule.command = Module::vRESTART;\r\n\t\tcontrol_change = true;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::StopModule( Module &module )\r\n{\r\n\t\r\n\r\n\tif ( !module.Locked() )\r\n\t{\r\n\t\tmodule.command = Module::vSTOP;\r\n\t\tcontrol_change = true;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::StartAllModules( void )\r\n{\r\n\t\r\n\r\n\tModule*\t\t\t\t\tnext;\r\n\tModule*\t\t\t\t\tmdl;\r\n\tLst::Search< Module >\tsh;\r\n\r\n\tnext = sh.FirstItem( module_list );\r\n\r\n\twhile ( next )\r\n\t{\r\n\t\tmdl = next;\t\t\t\t\r\n\t\tnext = sh.NextItem();\t// get next item before excuting callback\r\n\r\n\t\tif ( !mdl->Locked() )\r\n\t\t{\r\n\t\t\tif ( mdl->state == Module::vSTOPPED )\r\n\t\t\t{\r\n\t\t\t\tmdl->v_start_cb();\r\n\t\t\t\tmdl->command = Module::vNONE;\r\n\t\t\t\tmdl->state = Module::vRUNNING;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::StopAllModules( void )\r\n{\r\n\t\r\n\r\n\tModule*\t\t\t\t\tnext;\r\n\tModule*\t\t\t\t\tmdl;\r\n\tLst::Search< Module >\tsh;\r\n\r\n\tnext = sh.FirstItem( module_list );\r\n\r\n\twhile ( next )\r\n\t{\r\n\t\tmdl = next;\t\t\t\t\r\n\t\tnext = sh.NextItem();\t// get next item before excuting callback\r\n\t\t\t\t\t\t\t\t\r\n\t\tif ( !mdl->Locked() )\r\n\t\t{\r\n\t\t\tif ( mdl->state == Module::vRUNNING )\r\n\t\t\t{\r\n\t\t\t\tmdl->v_stop_cb();\r\n\t\t\t\tmdl->command = Module::vNONE;\r\n\t\t\t\tmdl->state = Module::vSTOPPED;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::LockAllModules( void )\r\n{\r\n\t\r\n\r\n\tModule*\t\t\t\t\tmdl;\r\n\tLst::Search< Module >\tsh;\r\n\r\n\tmdl = sh.FirstItem( module_list );\r\n\r\n\twhile ( mdl )\r\n\t{\r\n\t\tmdl->Lock();\r\n\t\tmdl = sh.NextItem();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::UnlockAllModules ( void )\r\n{\r\n\t\r\n\r\n\tModule*\t\t\t\t\tmdl;\r\n\tLst::Search< Module >\tsh;\r\n\r\n\tmdl = sh.FirstItem ( module_list );\r\n\r\n\twhile ( mdl )\r\n\t{\r\n\t\tmdl->Unlock();\r\n\t\tmdl = sh.NextItem();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mdl\r\n"
  },
  {
    "path": "Code/Gel/Module/module.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tModule (MDL)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmodule.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tModule code\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gel/module.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Mdl\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nModule::Module ( void )\r\n{\r\n\t\r\n\r\n\tstate = vSTOPPED;\r\n\tlocked = false;\r\n\r\n\tnode = new Lst::Node< Module > ( this );\r\n\tDbg_AssertType( node, Lst::Node< Module > );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nModule::~Module ()\r\n{\r\n\t\r\n\r\n\tDbg_AssertType( node, Lst::Node< Module > );\r\n\tdelete node;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mdl\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Movies/Movies.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGEL\t\t\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmovies.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t5/14/1\t-\tmjd\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tstreaming movies\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/macros.h>\r\n#include <core/singleton.h>\r\n\r\n#ifdef __PLAT_NGPS__\r\n#include <gel/movies/ngps/p_movies.h>\r\n#elif defined( __PLAT_XBOX__ )\r\n#include <gel/movies/xbox/p_movies.h>\r\n#elif defined( __PLAT_NGC__ )\r\n#include <gel/movies/ngc/p_movies.h>\r\n#endif\r\n\r\n#include <sys/profiler.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\nvoid PlayMovie( const char *pMovieName )\r\n{\r\n\tPMovies_PlayMovie( pMovieName );\r\n}\r\n\r\n}  // namespace Flx\r\n"
  },
  {
    "path": "Code/Gel/Movies/Movies.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tmovies\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/movies/movies.h  \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t5/14/01\t-\tmjd\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_MOVIES_H\r\n#define __GEL_MOVIES_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/list.h>\r\n#include <core/macros.h>\r\n//#include <gel/scripting/script.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\nvoid PlayMovie( const char *pMovieName );\r\n\r\n} // namespace Flx\r\n\r\n#endif\t// __GEL_MOVIES_H\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/audiodec.cpp",
    "content": "#include <eekernel.h>\r\n#include <stdio.h>\r\n#include <string.h>\r\n#include <sif.h>\r\n#include <sifdev.h>\r\n#include <libsdr.h>\r\n#include <sdrcmd.h>\r\n#include \"sys/config/config.h\"\r\n#include \"gel/movies/ngps/defs.h\"\r\n#include \"gel/movies/ngps/audiodec.h\"\r\n#include \"gel/movies/ngps/p_movies.h\"\r\n#include \"gel/music/music.h\"\r\n#include \"gel/soundfx/soundfx.h\"\r\n\r\n#define AU_HEADER_SIZE 40\r\n#define UNIT_SIZE 1024\r\n#define PRESET_VALUE(count)\t(count)\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\n#define MAX_VOL\t\t\t\t ( ( float ) 0x3fff )\r\n\r\nstatic void iopGetArea(int *pd0, int *d0, int *pd1, int *d1,\r\n\tAudioDec *ad, int pos);\r\nstatic int sendToIOP2area(int pd0, int d0, int pd1, int d1,\r\n\tu_char *ps0, int s0, u_char *ps1, int s1);\r\nstatic int sendToIOP(int dst, u_char *src, int size);\r\n//static void changeMasterVolume(u_int val);\r\nstatic void changeInputVolume(u_int val);\r\n\r\nvoid SetMovieVolume( void )\r\n{\r\n    // ///////////////////////////////////////\r\n    //\r\n    // Change input volume\r\n    //\r\n\tSfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();\r\n\tfloat musicVol = Pcm::GetVolume( ) * Config::GetMasterVolume()/100.0f;\r\n\tfloat sfxVol = sfx_manager->GetMainVolume( )  * Config::GetMasterVolume()/100.0f;\r\n\tfloat vol = musicVol > sfxVol ? musicVol : sfxVol;\t\r\n\tint inputVol = ( int ) ( ( vol * MAX_VOL ) / 100.0f );\r\n    changeInputVolume( inputVol );\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Create audio decoder\r\n//\r\nint audioDecCreate(\r\n    AudioDec *ad,\r\n    u_char *buff,\r\n    int buffSize,\r\n    int iopBuffSize,\r\n\tint pIopBuff\r\n)\r\n{\r\n\tSetMovieVolume( );\r\n    ad->state = AU_STATE_INIT;\r\n    ad->hdrCount = 0;\r\n    ad->data = buff;\r\n    ad->put = 0;\r\n    ad->count = 0;\r\n    ad->size = buffSize;\r\n    ad->totalBytes = 0;\r\n    ad->totalBytesSent = 0;\r\n\r\n    ad->iopBuffSize = iopBuffSize;\r\n    ad->iopLastPos = 0;\r\n    ad->iopPausePos = 0;\r\n\r\n    // ///////////////////////////////////////\r\n    //\r\n    // Audio data buffer on IOP\r\n    //\r\n    ad->iopBuff = pIopBuff; //(int)sceSifAllocIopHeap(iopBuffSize);\r\n    if(ad->iopBuff < 0) {\r\n\tprintf( \"Cannot allocate IOP memory\\n\");\r\n\treturn 0;\r\n    }\r\n    printf(\"IOP memory 0x%08x(size:%d) is allocated\\n\",\r\n    \tad->iopBuff, iopBuffSize);\r\n\r\n    // ///////////////////////////////////////\r\n    //\r\n    // Zero data buffer on IOP\r\n    //\r\n    ad->iopZero = pIopBuff + iopBuffSize; //(int)sceSifAllocIopHeap(ZERO_BUFF_SIZE);\r\n    if(ad->iopZero < 0) {\r\n\tprintf( \"Cannot allocate IOP memory\\n\");\r\n\treturn 0;\r\n    }\r\n    printf(\"IOP memory 0x%08x(size:%d) is allocated\\n\",\r\n    \tad->iopZero, ZERO_BUFF_SIZE);\r\n\r\n    // send zero data to IOP\r\n    memset ( MOVIE_MEM_PTR _0_buf, 0, ZERO_BUFF_SIZE);\r\n    sendToIOP(ad->iopZero, ( u_char * ) MOVIE_MEM_PTR _0_buf, ZERO_BUFF_SIZE);\r\n\r\n    // ///////////////////////////////////////\r\n    //\r\n    // Change master volume\r\n    //\r\n//    changeMasterVolume(0x3fff);\r\n\r\n    return 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Delete audio decoder\r\n//\r\nint audioDecDelete(AudioDec *ad)\r\n{\r\n//    sceSifFreeIopHeap((void *)ad->iopBuff);\r\n//    sceSifFreeIopHeap((void *)ad->iopZero);\r\n\r\n    // ///////////////////////////////////////\r\n    //\r\n    // Change master volume\r\n    //\r\n//    changeMasterVolume(0x0000);\r\n    changeInputVolume(0x0000);\r\n\r\n    return 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Pause\r\n//\r\nvoid audioDecPause(AudioDec *ad)\r\n{\r\n    int ret;\r\n    ad->state = AU_STATE_PAUSE;\r\n\r\n    // ///////////////////////////////////////\r\n    //\r\n    // Change input volume\r\n    //\r\n    changeInputVolume(0x0000);\r\n\r\n    // ///////////////////////////////////////\r\n    //\r\n    // Stop DMA and save the position to be played\r\n    //\r\n    ret = sceSdRemote(1, rSdBlockTrans, AUTODMA_CH,\r\n\t\t\t   SD_TRANS_MODE_STOP, NULL, 0) & 0x00FFFFFF;\r\n    ad->iopPausePos = ret - ad->iopBuff;\r\n\r\n    // ///////////////////////////////////////\r\n    //\r\n    // Clear SPU2 buffer\r\n    //\r\n    sceSdRemote(1, rSdVoiceTrans, AUTODMA_CH,\r\n\t\t SD_TRANS_MODE_WRITE | SD_TRANS_BY_DMA,\r\n\t\t ad->iopZero, 0x4000, ZERO_BUFF_SIZE);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Resume\r\n//\r\nvoid audioDecResume(AudioDec *ad)\r\n{\r\n\tSetMovieVolume( );\r\n    sceSdRemote(1, rSdBlockTrans, AUTODMA_CH,\r\n    \t\t(SD_TRANS_MODE_WRITE_FROM | SD_BLOCK_LOOP),\r\n\t\t ad->iopBuff, (ad->iopBuffSize/UNIT_SIZE)*UNIT_SIZE,\r\n\t\t ad->iopBuff + ad->iopPausePos);\r\n\r\n    ad->state = AU_STATE_PLAY;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Start to play audio data\r\n//\r\nvoid audioDecStart(AudioDec *ad)\r\n{\r\n//    return audioDecResume(ad);\r\n    audioDecResume(ad);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Re-initialize audio decoder\r\n//\r\nvoid audioDecReset(AudioDec *ad)\r\n{\r\n    // ///////////////////////////////////////\r\n    //\r\n    // Stop audio\r\n    //\r\n    audioDecPause(ad);\r\n\r\n    ad->state = AU_STATE_INIT;\r\n    ad->hdrCount = 0;\r\n    ad->put = 0;\r\n    ad->count = 0;\r\n    ad->totalBytes = 0;\r\n    ad->totalBytesSent = 0;\r\n    ad->iopLastPos = 0;\r\n    ad->iopPausePos = 0;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Get empty areas\r\n//\r\nvoid audioDecBeginPut(AudioDec *ad,\r\n\tu_char **ptr0, int *len0, u_char **ptr1, int *len1)\r\n{\r\n    int len;\r\n\r\n    // ///////////////////////////////////////\r\n    //\r\n    // return ADS header area when (state == AU_STATE_INIT)\r\n    //\r\n    if (ad->state == AU_STATE_INIT) {\r\n    \t*ptr0 = (u_char*)&ad->sshd + ad->hdrCount;\r\n\t*len0 = AU_HDR_SIZE - ad->hdrCount;\r\n\t*ptr1 = (u_char*)ad->data;\r\n\t*len1 = ad->size;\r\n\r\n\treturn;\r\n    }\r\n\r\n    // ///////////////////////////////////////\r\n    //\r\n    // Return the empty areas\r\n    //\r\n    len = ad->size - ad->count;\r\n\r\n    if (ad->size -  ad->put >= len) { // area0\r\n    \t*ptr0 = ad->data + ad->put;\r\n\t*len0 = len;\r\n\t*ptr1 = NULL;\r\n\t*len1 = 0;\r\n    } else {\t\t\t    // area0 + area1\r\n    \t*ptr0 = ad->data + ad->put;\r\n\t*len0 = ad->size - ad->put;\r\n\t*ptr1 = ad->data;\r\n\t*len1 = len - (ad->size - ad->put);\r\n    }\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Update pointer\r\n//\r\nvoid audioDecEndPut(AudioDec *ad, int size)\r\n{\r\n    if (ad->state == AU_STATE_INIT) {\r\n    \tint hdr_add = min( size, AU_HDR_SIZE - ( int )ad->hdrCount);\r\n    \tad->hdrCount += hdr_add;\r\n\r\n\tif ( ( int ) ad->hdrCount >= AU_HDR_SIZE) {\r\n\t    ad->state = AU_STATE_PRESET;\r\n\r\n\t    printf(\"-------- audio information --------------------\\n\");\r\n\t    printf(\"[%c%c%c%c]\\n\"\r\n\t       \"header size:                            %d\\n\"\r\n\t       \"type(0:PCM big, 1:PCM little, 2:ADPCM): %d\\n\"\r\n\t       \"sampling rate:                          %dHz\\n\"\r\n\t       \"channels:                               %d\\n\"\r\n\t       \"interleave size:                        %d\\n\"\r\n\t       \"interleave start block address:         %d\\n\"\r\n\t       \"interleave end block address:           %d\\n\",\r\n\t\t    ad->sshd.id[0],\r\n\t\t    ad->sshd.id[1],\r\n\t\t    ad->sshd.id[2],\r\n\t\t    ad->sshd.id[3],\r\n\t\t    ad->sshd.size,\r\n\t\t    ad->sshd.type,\r\n\t\t    ad->sshd.rate,\r\n\t\t    ad->sshd.ch,\r\n\t\t    ad->sshd.interSize,\r\n\t\t    ad->sshd.loopStart,\r\n\t\t    ad->sshd.loopEnd\r\n\t    );\r\n\r\n\t    printf(\"[%c%c%c%c]\\n\"\r\n\t       \"data size:                              %d\\n\",\r\n\t\t    ad->ssbd.id[0],\r\n\t\t    ad->ssbd.id[1],\r\n\t\t    ad->ssbd.id[2],\r\n\t\t    ad->ssbd.id[3],\r\n\t\t    ad->ssbd.size\r\n\t    );\r\n\r\n\t}\r\n\tsize -= hdr_add;\r\n    }\r\n    ad->put = (ad->put + size) % ad->size;\r\n    ad->count += size;\r\n    ad->totalBytes += size;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Check to see if enough data is already sent to IOP or not\r\n//\r\nint audioDecIsPreset(AudioDec *ad)\r\n{\r\n    return ad->totalBytesSent >= PRESET_VALUE(ad->iopBuffSize);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Send data to IOP\r\n//\r\nint audioDecSendToIOP(AudioDec *ad)\r\n{\r\n    int pd0, pd1, d0, d1;\r\n    u_char *ps0, *ps1;\r\n    int s0, s1;\r\n    int count_sent = 0;\r\n    int countAdj;\r\n    int pos = 0;\r\n\r\n    switch (ad->state) {\r\n        case AU_STATE_INIT:\r\n\t    return 0;\r\n\t    break;\r\n\r\n        case AU_STATE_PRESET:\r\n\t    pd0 = ad->iopBuff + (ad->totalBytesSent) % ad->iopBuffSize;\r\n\t    d0 = ad->iopBuffSize - ad->totalBytesSent;\r\n\t    pd1 = 0;\r\n\t    d1 = 0;\r\n\t    break;\r\n\r\n        case AU_STATE_PLAY:\r\n\t    pos = ((sceSdRemote(1, rSdBlockTransStatus, AUTODMA_CH)\r\n\t    \t& 0x00FFFFFF) - ad->iopBuff);\r\n\t    iopGetArea(&pd0, &d0, &pd1, &d1, ad, pos);\r\n\t    break;\r\n\r\n        case AU_STATE_PAUSE:\r\n\t    return 0;\r\n\t    break;\r\n    }\r\n\r\n    ps0 = ad->data + (ad->put - ad->count + ad->size) % ad->size;\r\n    ps1 = ad->data;\r\n\r\n    // adjust to UNIT_SIZE boundary\r\n    countAdj = (ad->count / UNIT_SIZE) * UNIT_SIZE;\r\n\r\n    s0 = min(ad->data + ad->size - ps0, countAdj);\r\n    s1 = countAdj - s0;\r\n\r\n    if (d0 + d1 >= UNIT_SIZE && s0 + s1 >= UNIT_SIZE) {\r\n    \tcount_sent = sendToIOP2area(pd0, d0, pd1, d1, ps0, s0, ps1, s1);\r\n    }\r\n\r\n    ad->count -= count_sent;\r\n\r\n    ad->totalBytesSent += count_sent;\r\n    ad->iopLastPos = (ad->iopLastPos + count_sent) % ad->iopBuffSize;\r\n\r\n    return count_sent;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Get empty area of IOP audio buffer\r\n//\r\nstatic void iopGetArea(int *pd0, int *d0, int *pd1, int *d1,\r\n\t\t\t\t\tAudioDec *ad, int pos)\r\n{\r\n    int len = (pos + ad->iopBuffSize - ad->iopLastPos - UNIT_SIZE)\r\n    \t\t\t% ad->iopBuffSize;\r\n\r\n    // adjust to UNIT_SIZE boundary\r\n    len = (len / UNIT_SIZE) * UNIT_SIZE;\r\n\r\n    if (ad->iopBuffSize -  ad->iopLastPos >= len) { // area0\r\n    \t*pd0 = ad->iopBuff + ad->iopLastPos;\r\n\t*d0 = len;\r\n\t*pd1 = 0;\r\n\t*d1 = 0;\r\n    } else {\t\t\t    // area0 + area1\r\n    \t*pd0 = ad->iopBuff + ad->iopLastPos;\r\n\t*d0 = ad->iopBuffSize - ad->iopLastPos;\r\n\t*pd1 = ad->iopBuff;\r\n\t*d1 = len - (ad->iopBuffSize - ad->iopLastPos);\r\n    }\r\n}\r\n\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Send data to IOP\r\n//\r\nstatic int sendToIOP2area(int pd0, int d0, int pd1, int d1,\r\n\t\tu_char *ps0, int s0, u_char *ps1, int s1)\r\n{\r\n    if (d0 + d1 < s0 + s1) {\r\n    \tint diff = (s0 + s1) - (d0 + d1);\r\n\tif (diff >= s1) {\r\n\t    s0 -= (diff - s1);\r\n\t    s1 = 0;\r\n\t} else {\r\n\t    s1 -= diff;\r\n\t}\r\n    }\r\n\r\n    //\r\n    // (d0 + d1 >= s0 + s1)\r\n    //\r\n    if (s0 >= d0) {\r\n    \tsendToIOP(pd0,\t\t\tps0,\t\td0);\r\n    \tsendToIOP(pd1,\t\t\tps0 + d0,\ts0 - d0);\r\n    \tsendToIOP(pd1 + s0 - d0,\tps1,\t\ts1);\r\n    } else { // s0 < d0\r\n    \tif (s1 >= d0 - s0) {\r\n\t    sendToIOP(pd0,\t\tps0,\t\ts0);\r\n\t    sendToIOP(pd0 + s0,\t\tps1,\t\td0 - s0);\r\n\t    sendToIOP(pd1,\t\tps1 + d0 - s0,\ts1 - (d0 - s0));\r\n\t} else { // s1 < d0 - s0\r\n\t    sendToIOP(pd0,\t\tps0,\t\ts0);\r\n\t    sendToIOP(pd0 + s0,\t\tps1,\t\ts1);\r\n\t}\r\n    }\r\n    return s0 + s1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Send data to IOP\r\n//\r\nstatic int sendToIOP(int dst, u_char *src, int size)\r\n{\r\n    sceSifDmaData transData;\r\n    int did;\r\n\r\n    if (size <= 0) {\r\n        return 0;\r\n    }\r\n\r\n    transData.data = (u_int)src;\r\n    transData.addr = (u_int)dst;\r\n    transData.size = size;\r\n    transData.mode = 0; // caution\r\n    FlushCache(0);\r\n\r\n    did = sceSifSetDma( &transData, 1 );\r\n\r\n    while (sceSifDmaStat(did) >= 0)\r\n    \t;\r\n\r\n    return size;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Change master volume\r\n//\r\n/*\r\nstatic void changeMasterVolume(u_int val)\r\n{\r\n    int i;\r\n    for( i = 0; i < 2; i++ ) {\r\n\tsceSdRemote(1, rSdSetParam, i | SD_P_MVOLL, val);\r\n\tsceSdRemote(1, rSdSetParam, i | SD_P_MVOLR, val);\r\n    }\r\n} */\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Change input volume\r\n//\r\nstatic void changeInputVolume(u_int val)\r\n{\r\n    sceSdRemote(1, rSdSetParam, AUTODMA_CH | SD_P_BVOLL, val);\r\n    sceSdRemote(1, rSdSetParam, AUTODMA_CH | SD_P_BVOLR, val);\r\n}\r\n\r\n} // namespace Flx\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/audiodec.h",
    "content": "#ifndef _AUDIODEC_H_\r\n#define _AUDIODEC_H_\r\n\r\n#include <eetypes.h>\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/macros.h>\r\n#include <core/singleton.h>\r\n\r\n// ///////////////////////////////////////////////////////\r\n//\r\n// Audio decoder state\r\n//\r\n#define AU_STATE_INIT\t\t0\r\n#define AU_STATE_PRESET\t\t1\r\n#define AU_STATE_PLAY\t\t2\r\n#define AU_STATE_PAUSE\t\t3\r\n\r\n#define AU_HDR_SIZE\t\t( ( int )(sizeof(SpuStreamHeader) \t\t\t\t\t+ sizeof(SpuStreamBody)) )\r\n\r\n// ///////////////////////////////////////////////////////\r\n//\r\n// Spu stream header\r\n//\r\nstruct SpuStreamHeader{\r\n    char id[4];\t\t// 'S''S''h''d'\r\n    int size;\t\t// 24\r\n    int type;\t\t// 0: 16bit big endian\r\n    \t\t\t// 1: 16bit little endian\r\n\t\t\t// 2: SPU2-ADPCM (VAG) \r\n    int rate;\t\t// sampling rate\r\n    int ch;\t\t// number of channels\r\n    int interSize;\t// interleave size ... needs to be 512\r\n    int loopStart;\t// loop start block address\r\n    int loopEnd;\t// loop end block sddress\r\n};\r\n\r\n// ///////////////////////////////////////////////////////\r\n//\r\n// Spu stream body\r\n//\r\nstruct SpuStreamBody{\r\n    char id[4];\t\t// 'S''S''b''d'\r\n    int size;\t\t// size of audio data\r\n};\r\n\r\n// ///////////////////////////////////////////////////////\r\n//\r\n// Audio decoder\r\n//\r\nstruct AudioDec{\r\n\r\n    int state;\r\n\r\n    // header of ADS format\r\n\tstruct SpuStreamHeader sshd;\r\n\tstruct SpuStreamBody   ssbd;\r\n    int hdrCount;\r\n\r\n    // audio buffer\r\n    u_char *data;\r\n    int put;\r\n    int count;\r\n    int size;\r\n    int totalBytes;\r\n\r\n    // buffer on IOP\r\n    int iopBuff;\r\n    int iopBuffSize;\r\n    int iopLastPos;\r\n    int iopPausePos;\r\n    int totalBytesSent;\r\n    int iopZero;\r\n\r\n};\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\n// ///////////////////////////////////////////////////////\r\n//\r\n// Functions\r\n//\r\nint audioDecCreate(\r\n    struct AudioDec *ad,\r\n    u_char *buff,\r\n    int buffSize,\r\n    int iopBuffSize,\r\n\tint pIopBuf\r\n);\r\nint audioDecDelete( struct AudioDec *ad);\r\nvoid audioDecBeginPut( struct AudioDec *ad,\r\n\tu_char **ptr0, int *len0, u_char **ptr1, int *len1);\r\nvoid audioDecEndPut(struct AudioDec *ad, int size);\r\nint audioDecIsPreset(struct AudioDec *ad);\r\nvoid audioDecStart(struct AudioDec *ad);\r\nint audioDecSendToIOP(struct AudioDec *ad);\r\nvoid audioDecReset(struct AudioDec *ad);\r\nvoid audioDecPause(struct AudioDec *ad);\r\nvoid audioDecResume(struct AudioDec *ad);\r\n\r\n} // namespace Flx\r\n\r\n#endif _AUDIODEC_H_\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/defs.h",
    "content": "#ifndef _DEFS_H_\r\n#define _DEFS_H_\r\n\r\n#include <eeregs.h>\r\n#include <eetypes.h>\r\n#include <libmpeg.h>\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/macros.h>\r\n#include <core/singleton.h>\r\n\r\n#define STRFILE_NUM_STREAMING_SECTORS 80\r\n\r\n#define UNCMASK 0x0fffffff\r\n#define UNCBASE 0x20000000\r\n\r\n#define MAX_WIDTH 720\r\n#define MAX_HEIGHT 576\r\n\r\n#define MOVIE_THREAD_PRIORITY 1\r\n#define AUTODMA_CH 0\r\n\r\n#define N_LDTAGS (MAX_WIDTH/16 * MAX_HEIGHT/16 * 6 + 10)\r\n#define TS_NONE (-1)\r\n\r\n#define bound(val, x) ((((val) + (x) - 1) / (x))*(x))\r\n#define min(x, y) (((x) > (y))? (y): (x))\r\n#define max(x, y) (((x) < (y))? (y): (x))\r\n\r\nextern inline void *DmaAddr(void *val)\r\n{\r\n    return (void*)((u_int)val & UNCMASK);\r\n}\r\n\r\nextern inline void *UncAddr(void *val)\r\n{\r\n    return (void*)(((u_int)val & UNCMASK)|UNCBASE);\r\n}\r\n \r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\nvoid ErrMessage(char *message);\r\nvoid switchThread();\r\nvoid proceedAudio();\r\n\r\n}\r\n\r\n\r\n\r\n#endif // _DEFS_H_\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/disp.cpp",
    "content": "#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <malloc.h>\r\n#include <libgraph.h>\r\n#include <libdma.h>\r\n#include <libpkt.h>\r\n#include \"gel/movies/ngps/defs.h\"\r\n#include \"gel/movies/ngps/disp.h\"\r\n#include \"gel/movies/ngps/videodec.h\"\r\n#include \"gel/movies/ngps/vobuf.h\"\r\n#include \"gel/movies/ngps/p_movies.h\"\r\n#include <sys/config/config.h>\r\n\r\nextern sceGsDBuff gDB;\r\n\r\nvolatile int isCountVblank = 0;\r\nvolatile int vblankCount = 0;\r\nvolatile int isFrameEnd = 0;\r\nvolatile int oddeven = 0;\r\nvolatile int handler_error = 0;\r\n\r\nextern int frd;\r\n\r\ntypedef struct {\r\n  int x, y, w, h;\r\n} Rect;\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\n///////////////////////////////////////////////////////////////////\r\n//\r\n// Delete previous image of frame buffer and texture buffer\r\n//\r\nvoid clearGsMem(int r, int g, int b, int disp_width, int disp_height)\r\n{\r\n\tconst u_long giftag_clear[2] = { SCE_GIF_SET_TAG(0, 1, 0, 0, 0, 1), \r\n\t\t\t\t 0x000000000000000eL };\r\n\tsceGifPacket packet;\r\n\t\r\n\tu_long128 packetBase[ 6 ];\r\n\r\n\t// Abort if gDB hasn't been initialized\r\n\tif (*((uint64 *) &gDB.disp[0].display) == 0)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tsceDmaChan* dmaGif = sceDmaGetChan(SCE_DMA_GIF);\r\n\t\r\n\t// setting GIF tag for gDB.draw0 structure\r\n\tSCE_GIF_CLEAR_TAG(&gDB.giftag0);\r\n\tgDB.giftag0.NLOOP = 8;\r\n\tgDB.giftag0.EOP = 1;\r\n\tgDB.giftag0.NREG = 1;\r\n\tgDB.giftag0.REGS0 = 0xe; // A_D\r\n\t\r\n\t// define GS memory as a one big drawing area\r\n\t// \"bound(DISP_HEIGHT/2, 32)*2\" is for frame buffer * 2\r\n\t// \"bound(DISP_HEIGHT, 32)*2\" is for texture buffer\r\n\tsceGsSetDefDrawEnv(&gDB.draw0, SCE_GS_PSMCT32, disp_width,\r\n\t\t\t bound(disp_height/2, 32)*2 + bound(disp_height, 32)*2,\r\n\t\t\t 0, 0);\r\n\t*(u_long *)&gDB.draw0.xyoffset1 = SCE_GS_SET_XYOFFSET_1(0, 0);\r\n\t\r\n\tFlushCache(0);\r\n\tsceGsSyncPath(0, 0);\r\n\tsceGsPutDrawEnv(&gDB.giftag0);\r\n\t\r\n//\tsceGifPkInit(&packet, MOVIE_MEM_PTR packetBase);\r\n\tsceGifPkInit(&packet, packetBase);\t  \t\t// Mick: Use a local one, so I can use this function for laodng screen clearing\r\n\tsceGifPkReset(&packet);\r\n\t\r\n\tsceGifPkEnd(&packet, 0, 0, 0);\r\n\t\r\n\t// packet for a big sprite polygon\r\n\t{\r\n\tsceGifPkOpenGifTag(&packet, *(u_long128*)&giftag_clear);\r\n\tsceGifPkAddGsAD(&packet, SCE_GS_PRIM,\r\n\t\t\tSCE_GS_SET_PRIM(6, 0, 0, 0, 0, 0, 0, 0, 0));\r\n\tsceGifPkAddGsAD(&packet, SCE_GS_RGBAQ, SCE_GS_SET_RGBAQ(r, g, b, 0, 0));\r\n\tsceGifPkAddGsAD(&packet, SCE_GS_XYZ2,\r\n\t\t\tSCE_GS_SET_XYZ2(0 << 4,0 << 4, 0)); \r\n\tsceGifPkAddGsAD(&packet, SCE_GS_XYZ2,\r\n\t\t\tSCE_GS_SET_XYZ2( MAX_WIDTH << 4, MAX_HEIGHT*5 << 4, 0)); \r\n\tsceGifPkCloseGifTag(&packet);\r\n\t}\r\n\t\r\n\tsceGifPkTerminate(&packet);\r\n\t\r\n\tFlushCache(0);\r\n\tsceGsSyncPath(0, 0);\r\n\tsceDmaSend(dmaGif, (u_long128*)((u_int)packet.pBase));\r\n\tsceGsSyncPath(0, 0);\r\n//\tfree(packetBase);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Set tags for image transfer using path3\r\n//\r\nvoid setImageTag(u_int *tags, void *image, int index, int image_w, int image_h)\r\n{\r\n  u_int dbp, dbw, dpsm;\r\n  u_int dir, dsax, dsay;\r\n  u_int rrw, rrh;\r\n  u_int xdir;\r\n  int mbx = image_w >> 4;\r\n  int mby = image_h >> 4;\r\n  int i, j;\r\n  Rect tex;\r\n  Rect poly;\r\n\r\n  sceGifPacket packet;\t\r\n  const u_long giftag[2] = { SCE_GIF_SET_TAG(0, 0, 0, 0, 0, 1), \r\n\t\t\t     0x000000000000000eL };\r\n  const u_long giftag_eop[2] = { SCE_GIF_SET_TAG(0, 1, 0, 0, 0, 1), \r\n\t\t\t\t 0x000000000000000eL };\r\n  sceGifPkInit(&packet, (u_long128*)UncAddr(tags));\r\n  sceGifPkReset(&packet);\r\n  \r\n  if (index == 0) {  // set image data to packet\r\n\r\n    //  set params\r\n    dbp = (bound(MAX_WIDTH, 64) * bound((MAX_HEIGHT/2), 32) * 2)/64;\r\n    dbw = bound(MAX_WIDTH, 64)/64;\r\n    dpsm = SCE_GS_PSMCT32;\r\n\r\n    dir = 0;\r\n    dsax = 0;\r\n    dsay = 0;\r\n\r\n    rrw = 16;\r\n    rrh = 16;\r\n\r\n    xdir = 0;\r\n\r\n    sceGifPkCnt(&packet, 0, 0, 0);\r\n\r\n    // eop == 0\r\n    {    \r\n      sceGifPkOpenGifTag(&packet, *(u_long128*)&giftag);\r\n      sceGifPkAddGsAD(&packet, SCE_GS_BITBLTBUF,\r\n\t\t      SCE_GS_SET_BITBLTBUF(0, 0, 0, dbp, dbw, dpsm));\r\n      sceGifPkAddGsAD(&packet, SCE_GS_TRXREG, SCE_GS_SET_TRXREG(rrw, rrh));\r\n      sceGifPkCloseGifTag(&packet);\r\n    }\r\n\r\n    // //////////////////////////////////////\r\n    // \r\n    //  create packet for image data\r\n    // \r\n    for (i = 0; i < mbx; i++) {\r\n      for (j = 0; j < mby; j++) {\r\n\r\n\tsceGifPkCnt(&packet, 0, 0, 0);\r\n\r\n\t// eop == 0\r\n\t{\r\n\t  sceGifPkOpenGifTag(&packet, *(u_long128*)giftag);\r\n\t  sceGifPkAddGsAD(&packet, SCE_GS_TRXPOS,\r\n\t\t\t  SCE_GS_SET_TRXPOS(0, 0, 16*i+dsax, 16*j+dsay, 0));\r\n\t  sceGifPkAddGsAD(&packet, SCE_GS_TRXDIR, SCE_GS_SET_TRXDIR(xdir));\r\n\t  sceGifPkCloseGifTag(&packet);\r\n\t}\r\n\t\r\n\t{\r\n\t  u_long* const tag = (u_long*)sceGifPkReserve(&packet, 4);\r\n\t  tag[0] = SCE_GIF_SET_TAG(16*16*4/16, 0, 0, 0, 2, 0);\r\n\t\ttag[1] = 0;\r\n\t}\r\n\tsceGifPkRef(&packet, (u_long128 *) DmaAddr(image), 16*16*4/16, 0, 0, 0);\r\n\timage = (u_char*)image + 16*16*4;\r\n      }\r\n    }\r\n  }\r\n\r\n  tex.x = 8; // 0.5\r\n  tex.y = 8; // 0.5\r\n  tex.w = image_w << 4;\r\n  tex.h = image_h << 4;\r\n  \r\n\tif (Config::PAL())\r\n\t{\r\n\t\tpoly.x = (2048 - 320) << 4;\r\n\t\tpoly.y = (2048 - (512/2)/2) << 4;\r\n\t\tpoly.w = 640 << 4;\r\n\t\tpoly.h = (512/2) << 4;\r\n\t}  \r\n\telse\r\n\t{\r\n\t\tpoly.x = (2048 - 320) << 4;\r\n\t\tpoly.y = (2048 - (480/2)/2) << 4;\r\n\t\tpoly.w = 640 << 4;\r\n\t\tpoly.h = (480/2) << 4;\r\n\t}  \r\n  // --------------------------------\r\n  sceGifPkEnd(&packet, 0, 0, 0);\r\n\r\n  // eop == 1\r\n  {\r\n    sceGifPkOpenGifTag(&packet, *(u_long128*)giftag_eop);\r\n    sceGifPkAddGsAD(&packet, SCE_GS_TEXFLUSH, 0);\r\n    sceGifPkAddGsAD(&packet, SCE_GS_TEX1_1,\r\n\t\t    SCE_GS_SET_TEX1_1(0, 0, 1, 1, 0, 0, 0));\r\n    sceGifPkAddGsAD(&packet, SCE_GS_TEX0_1,\r\n\t\t    SCE_GS_SET_TEX0_1((bound(MAX_WIDTH, 64) \r\n\t\t\t\t       * bound((MAX_HEIGHT/2), 32) * 2)/64,\r\n\t\t\t\t      bound(MAX_WIDTH, 64)/64, SCE_GS_PSMCT32, \r\n\t\t\t\t      10, 10, 0, 1, 0, 0, 0, 0, 0));\r\n    sceGifPkAddGsAD(&packet, SCE_GS_PRIM,\r\n\t\t    SCE_GS_SET_PRIM(6, 0, 1, 0, 0, 0, 1, 0, 0));\r\n    sceGifPkAddGsAD(&packet, SCE_GS_UV, SCE_GS_SET_UV(tex.x, tex.y)); \r\n    sceGifPkAddGsAD(&packet, SCE_GS_XYZ2, SCE_GS_SET_XYZ2(poly.x, poly.y, 0)); \r\n    sceGifPkAddGsAD(&packet, SCE_GS_UV,\r\n\t\t    SCE_GS_SET_UV(tex.x + tex.w, tex.y + tex.h)); \r\n    sceGifPkAddGsAD(&packet, SCE_GS_XYZ2, \r\n\t\t    SCE_GS_SET_XYZ2(poly.x + poly.w, poly.y + poly.h, 0)); \r\n    sceGifPkCloseGifTag(&packet);\r\n  }\r\n\r\n  // finish making packet\r\n  sceGifPkTerminate(&packet);\r\n}\r\n\r\n// /////////////////////////////////////////////////////////////////////\r\n//\r\n// vblank handler\r\n//\r\nint vblankHandler(int val)\r\n{\r\n\t\r\n\t\r\n\tCHECK_MOVIE_MEM;\r\n\t\r\n\tsceDmaChan* dmaGif_loadimage = sceDmaGetChan(SCE_DMA_GIF);\r\n\toddeven = ((*GS_CSR) >> 13) & 1; // odd == 1, even == 0\r\n\r\n\tif (isCountVblank)\r\n\t{\r\n\r\n\t\tVoTag *tag;\r\n\t\tvblankCount++;\r\n\t\thandler_error = sceGsSyncPath(1, 0);\r\n\t\tif (!handler_error)\r\n\t\t{ // no error\r\n\t\t\ttag = voBufGetTag(& MOVIE_MEM_PTR voBuf);\r\n\t\t\tif (!tag)\r\n\t\t\t{\r\n\t\t\t\tfrd++;\r\n\t\t\t\tExitHandler();\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tsceGsSetHalfOffset((oddeven&1)?(sceGsDrawEnv1*)UncAddr(&gDB.draw1)\r\n\t\t\t\t:(sceGsDrawEnv1*)UncAddr(&gDB.draw0), 2048, 2048, oddeven^0x1);\r\n\t\t\t\r\n\t\t\tif ((oddeven == 0) && (tag->status == VOBUF_STATUS_FULL))\r\n\t\t\t{\r\n\t\t\t\tsceGsSwapDBuff(&gDB, 0);\r\n\t\t\t\t\r\n\t\t\t\t// Load image data to GS using path3\r\n\t\t\t\tsceGsSyncPath(0, 0);\r\n\t\t\t\tsceDmaSend(dmaGif_loadimage, (u_long128*)((u_int)tag->v[0]));\r\n\t\t\t\t\r\n\t\t\t\ttag->status = VOBUF_STATUS_TOPDONE;\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse if ((oddeven == 1) && tag->status == VOBUF_STATUS_TOPDONE)\r\n\t\t\t{\r\n\t\t\t\tsceGsSwapDBuff(&gDB, 1);\r\n\t\t\t\t\r\n\t\t\t\t// Load image data to GS using path3\r\n\t\t\t\tsceGsSyncPath(0, 0);\r\n\t\t\t\tsceDmaSend(dmaGif_loadimage, (u_long128*)((u_int)tag->v[1]));\r\n\t\t\t\ttag->status = VOBUF_STATUS_;\r\n\t\t\t\t\r\n\t\t\t\tisFrameEnd = 1;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tExitHandler();\r\n\treturn 0;\r\n}\r\n\r\n// ///////////////////////////////////////////////////////////////\r\n// \r\n//  Handler to check the end of image transfer\r\n// \r\nint handler_endimage(int val)\r\n{\r\n  if (isFrameEnd) {\r\n    voBufDecCount(& MOVIE_MEM_PTR voBuf);\r\n    isFrameEnd = 0;\r\n  }\r\n  ExitHandler();\r\n  return 0;\r\n}\r\n\r\n// ///////////////////////////////////////////////////////////////////\r\n// \r\n//  Wait until even/odd field\r\n//  Start to count vblank\r\n// \r\nvoid startDisplay(int waitEven)\r\n{\r\n  // wait untill even field\r\n  while (sceGsSyncV(0) == waitEven)\r\n    ;\r\n  \r\n  frd = 0;\r\n  isCountVblank = 1;\r\n  vblankCount = 0;\r\n}\r\n\r\n// ///////////////////////////////////////////////////////////////////\r\n// \r\n//  Stop to count vblank\r\n// \r\nvoid endDisplay()\r\n{\r\n  isCountVblank =  0;\r\n  frd = 0;\r\n}\r\n\r\n} // namespace Flx\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/disp.h",
    "content": "#ifndef _DISP_H_\r\n#define _DISP_H_\r\n\r\n#include <libgraph.h>\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/macros.h>\r\n#include <core/singleton.h>\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Functions\r\n//\r\nvoid clearGsMem(int r, int g, int b, int disp_width, int disp_height);\r\nvoid setImageTag(u_int *tags, void *image, int index,\r\n\t\t int image_w, int image_h);\r\nvoid startDisplay(int waitEven);\r\nvoid endDisplay();\r\n\r\n} // namespace Flx\r\n\r\n#endif _DISP_H_\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/p_movies.cpp",
    "content": "#include <eekernel.h>\r\n#include <stdio.h>\r\n#include <string.h>\r\n#include <libsdr.h>\r\n#include <sdrcmd.h>\r\n#include <libpkt.h>\r\n#include <libdma.h>\r\n#include <libmpeg.h>\r\n#include <libpad.h>\r\n#include <sifrpc.h>\r\n#include <sifdev.h>\r\n#include <libgraph.h>\r\n#include <libdev.h>\r\n#include <core/defines.h>\r\n#include <core/macros.h>\r\n#include <core/singleton.h>\r\n\r\n#include \"gfx/gfxman.h\"\r\n\r\n#include \"gfx/ngps/nx/nx_init.h\"\r\n#include \"gfx/ngps/nx/pcrtc.h\"\r\n#include \"gfx/ngps/nx/resource.h\"\r\n\r\n#include \"gel/music/ngps/p_music.h\"\r\n\r\n#include \"gel/movies/movies.h\"\r\n#include \"gel/movies/ngps/p_movies.h\"\r\n#include \"gel/movies/ngps/defs.h\"\r\n#include \"gel/movies/ngps/videodec.h\"\r\n#include \"gel/movies/ngps/disp.h\"\r\n#include \"gel/movies/ngps/readbuf.h\"\r\n#include \"gel/movies/ngps/vobuf.h\"\r\n#include \"gel/movies/ngps/audiodec.h\"\r\n#include \"gel/movies/ngps/strfile.h\"\r\n#include \"sys/timer.h\"\r\n\r\n#include <sys/file/filesys.h>\r\n#include <sys/timer.h>\r\n#include <sys/config/config.h>\r\n#include <gel/music/music.h>\r\n\r\n// K: To switch this off, make it 0 rather than undefining it, cos it won't compile otherwise\r\n#define FORCE_MOVIES_FROM_CD_PLEASE 0\r\n\r\nint videoDecTh;\r\nint defaultTh;\r\nint frd;\r\nu_int controller_val;\r\nint isWithAudio = 1;\r\n\r\nbool hitStart = false;\r\nuint64 hitStartFrame;\r\n\r\nsceGsDBuff gDB;\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\nstatic bool initAll( const char *bsfilename );\r\nstatic void termAll();\r\nstatic void defMain(void *dummy);\r\nstatic u_int movie( const char *name );\r\nstatic int readMpeg(VideoDec *vd, ReadBuf *rb, StrFile *file);\r\nstatic int isAudioOK();\r\n\r\nvoid dispMain(void);\r\nvoid videoDecMain( void *dummy);\r\nint videoCallback(sceMpeg *mp, sceMpegCbDataStr *str, void *data);\r\nint pcmCallback(sceMpeg *mp, sceMpegCbDataStr *str, void *data);\r\nint vblankHandler(int);\r\nint handler_endimage(int);\r\nvoid loadModule(char *moduleName);\r\n\r\n#define NUM_VIDEO_BUFFERS\t3\r\n#define VRAM_TOTAL_SIZE\t\t( 1024 * 4096 ) // 4 megs of video ram\r\n#define MAX_PIXEL_DATA_SIZE\t( 32767 * 16 )\r\n\r\n#define ZBUF_ADDR(w, h)\t\t( (((w) + 63) / 64) * (((h) + 31) / 32) * 2)\r\n\r\nSMovieMem *gpMovieMem = NULL;\r\n\r\nint GetThreadPriority( )\r\n{\r\n\tstruct ThreadParam info;\r\n\t// Fill info with zeros to be sure the following call is doing\r\n\t// something to info\r\n\tmemset(&info,0,sizeof(info));\r\n\t// return value not defined in 2.0 PDF EE lib ref\r\n\tReferThreadStatus( GetThreadId(), &info );\r\n\treturn ( info.currentPriority );\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Play Movie\r\n//\r\n\r\n#define RESTORE_VRAM 1\r\n#define PLAY_MOVIE_PLEASE 1\r\n#define SAVE_SCRATCHPAD 0\r\n#define SCRATCHPAD_SIZE\t8192\r\n\r\nvoid PMovies_PlayMovie( const char *pName )\r\n{\r\n\t// Re-enabled for CD even though we don't have a Sony fix.\r\n//\t// Garrett: Disabled CD movies until I know the sceCdSt() calls are working again in 2.7.2\r\n//\tif (Config::CD() || FORCE_MOVIES_FROM_CD_PLEASE)\r\n//\t{\r\n//\t\treturn;\r\n//\t}\r\n\t\r\n\tint origThreadPriority;\r\n//\tint origArenaSize;\r\n\tint width=0;\r\n\tint height=0;\r\n//\tint origDepth;\r\n//\tchar *pOrigVram;\r\n//\tchar *pNonAllignedOrigVram;\r\n\r\n\t//Dbg_Message(\"*************** Movie: In render frame %d\", Tmr::GetRenderFrame());\r\n\r\n\t// Check to see if we need to skip movies\r\n\tif (hitStart && (hitStartFrame == Tmr::GetRenderFrame()))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// stop music and streams (we're gonna be using the IOP memory)\r\n\tPcm::StopMusic( );\r\n\tPcm::StopStreams( );\r\n\r\n\t// Suspend Nx engine and its interrupts\r\n\tNxPs2::SuspendEngine();\r\n\t\t\r\n\r\n\tif (Config::PAL())\r\n\t{\r\n\t\twidth = 640;\r\n\t\theight = 512;\r\n\t} else {\r\n\t\twidth = 640;\r\n\t\theight = 480;\r\n\t}\r\n\r\n\t// clear vram onscreen:\r\n\tif (Config::PAL())\r\n\t{\r\n\t\tclearGsMem(0x00, 0x00, 0x00, 640, ( height * width * 2 ) / 640 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tclearGsMem(0x00, 0x00, 0x00, width, height * 2);\r\n\t}\r\n\r\n\t// get current thread priority:\r\n\torigThreadPriority = GetThreadPriority( );\r\n    ChangeThreadPriority(GetThreadId(), MOVIE_THREAD_PRIORITY );\r\n\t\r\n\r\n#if PLAY_MOVIE_PLEASE\r\n    isWithAudio = 1; // withAudio;\r\n    \r\n\tDbg_MsgAssert( pName, ( \"No movie name specified\" ) );\r\n\r\n\tDbg_MsgAssert( !gpMovieMem, ( \"Movie memory already allocated!\" ) );\r\n\t\t\t\t\t\t\t\t\t  \r\n\t// Allocate memory on high heap\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n\tvoid *pNonAllignedMovieMem = (void *) Mem::Malloc( sizeof( SMovieMem ) + 64 );\r\n\t\r\n\tif ( !pNonAllignedMovieMem )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Ran out of memory... can't play movie %s.\", pName ) );\r\n\t\treturn;\r\n\t}\r\n\tgpMovieMem = ( SMovieMem * )( ( ( int )pNonAllignedMovieMem ) + ( 64 - ( ( ( int ) pNonAllignedMovieMem ) & 63 ) ) );\r\n\r\n\tDbg_MsgAssert( !( ( ( int )& MOVIE_MEM_PTR voBufData & 63 ) ||\r\n\t\t( ( int )& MOVIE_MEM_PTR voBufTag & 63 ) ||\r\n        ( ( int )& MOVIE_MEM_PTR viBufTag & 63 ) ||\r\n\t\t( ( int )& MOVIE_MEM_PTR mpegWork & 63 ) ||\r\n\t\t( ( int )& MOVIE_MEM_PTR defStack & 63 ) ||\r\n\t\t( ( int )& MOVIE_MEM_PTR audioBuff & 63 ) ||\r\n\t\t( ( int )& MOVIE_MEM_PTR viBufData & 63 ) ||\r\n\t\t( ( int )& MOVIE_MEM_PTR videoDecStack & 63 ) ||\r\n\t\t( ( int )& MOVIE_MEM_PTR timeStamp & 63 ) ||\r\n//\t\t( ( int )& MOVIE_MEM_PTR controller_dma_buf & 63 ) ||\r\n\t\t( ( int )& MOVIE_MEM_PTR readBuf & 63 ) ||\r\n        ( ( int )& MOVIE_MEM_PTR infile & 63 ) ||\r\n\t\t( ( int )& MOVIE_MEM_PTR videoDec & 63 ) ||\r\n\t\t( ( int )& MOVIE_MEM_PTR audioDec & 63 ) ||\r\n\t\t( ( int )& MOVIE_MEM_PTR voBuf & 63 ) ), ( \"Bad allignment in SMovieMem structure.\" ) );\r\n/*\r\n\tDbg_Message( \"Allignment: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\", ( int )& MOVIE_MEM_PTR voBufData & 63, ( int )& MOVIE_MEM_PTR voBufTag & 63,\r\n\t ( int )& MOVIE_MEM_PTR viBufTag & 63, ( int )& MOVIE_MEM_PTR mpegWork & 63, ( int )& MOVIE_MEM_PTR defStack & 63, ( int )& MOVIE_MEM_PTR audioBuff & 63, ( int )& MOVIE_MEM_PTR viBufData & 63,\r\n\t ( int )& MOVIE_MEM_PTR videoDecStack & 63, ( int )& MOVIE_MEM_PTR timeStamp & 63, ( int )& MOVIE_MEM_PTR controller_dma_buf & 63, ( int )& MOVIE_MEM_PTR readBuf & 63,\r\n\t ( int )& MOVIE_MEM_PTR infile & 63, ( int )& MOVIE_MEM_PTR videoDec & 63, ( int )& MOVIE_MEM_PTR audioDec & 63, ( int )& MOVIE_MEM_PTR voBuf & 63 );\r\n*/\r\n\tDbg_Message( \"Size of SMovieMem struct: %d k\", sizeof( SMovieMem ) / 1024 );\r\n\r\n\r\n#if SAVE_SCRATCHPAD\r\n\t// remember scratchpad:\r\n\tunsigned char *pScratchpad = ( unsigned char * )Mem::Malloc( SCRATCHPAD_SIZE );\r\n\tDbg_MsgAssert( pScratchpad, ( \"Ran out of memory allocating scratchpad.\" ) );\r\n\tint i;\r\n\tfor ( i = 0; i < SCRATCHPAD_SIZE; i++ )\r\n\t{\r\n\t\tpScratchpad[ i ] = ( ( unsigned char * ) 0x70000000 )[ i ];\r\n\t}\r\n#else\r\n\t// Make sure scratchpad is available\r\n\tbool got_scratch = NxPs2::CSystemResources::sRequestResource(NxPs2::CSystemResources::vSCRATCHPAD_MEMORY);\r\n\tDbg_Assert(got_scratch);\r\n#endif // SAVE_SCRATCHPAD\r\n\r\n\t// Pop top-down context\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tsceGsResetPath();\r\n    sceDmaReset(1);\r\n\r\n\tNxPs2::SetupPCRTC(1, SCE_GS_FRAME);\r\n\r\n\t// Old way of initializing.  We can't use sceGsResetGraph() anymore.  It interferes with SetupPCRTC().\r\n\t// Also, clearGsMem() did nothing before because it used gDB, which you can see was not initialized until\r\n\t// after the calls.\r\n#if 0  \r\n\t\t//clearGsMem(0x00, 0x00, 0x00, 640, 480);\r\n\t\t//VSync( );\r\n\t\t\r\n\t\t//sceGsResetGraph(0, SCE_GS_INTERLACE, SCE_GS_NTSC, SCE_GS_FRAME);\r\n\r\n\t\t//  Initialize GS memory\r\n\t\t//clearGsMem(0x00, 0x00, 0x00, 640, 480);\r\n#endif\r\n\t\r\n\tsceGsSetDefDBuff(&gDB, SCE_GS_PSMCT32, width, (height/2),\r\n\t\t\t SCE_GS_ZNOUSE, 0, SCE_GS_CLEAR);\r\n\r\n\tint zbuf_addr = ZBUF_ADDR(width, (height/2));\r\n\r\n\t// Garrett: Since sceGsResetGraph() saves some register settings in internal library variables (including FRAME),\r\n\t// we have to update some settings in gDB with the correct values.\r\n\tgDB.disp[0].smode2.FFMD = SCE_GS_FRAME;\r\n\tgDB.disp[1].smode2.FFMD = SCE_GS_FRAME;\r\n\tgDB.disp[0].dispfb.FBP\t= 0x0;\r\n\tgDB.disp[1].dispfb.FBP\t= zbuf_addr >> 1;\r\n\tgDB.disp[0].display.DH\t= height-1;\r\n\tgDB.disp[1].display.DH\t= height-1;\r\n\tgDB.draw0.frame1.FBP\t= zbuf_addr >> 1;\r\n\tgDB.draw1.frame1.FBP\t= 0x0;\r\n\tgDB.draw0.zbuf1.ZBP\t\t= zbuf_addr;\r\n\tgDB.draw1.zbuf1.ZBP\t\t= zbuf_addr;\r\n\t\t\t\t \r\n    FlushCache(0);\r\n\r\n\t// Wait for all the music and streams to really stop, since we are stealing their IOP memory\r\n\tuint32 target_vblank = Tmr::GetVblanks() + (5 * Config::FPS());\t\t// 5 seconds\r\n\twhile (Tmr::GetVblanks() < target_vblank)\r\n\t{\r\n\t\tPcm::PCMAudio_Update();\r\n\r\n\t\tif (Pcm::PCMAudio_GetMusicStatus() != Pcm::PCM_STATUS_FREE)\r\n\t\t\tcontinue;\r\n\t\t\r\n\t\tbool done = true;\r\n\t\tfor (int streamNum = 0; streamNum < NUM_STREAMS; streamNum++)\r\n\t\t{\r\n\t\t\tif (Pcm::PCMAudio_GetStreamStatus( streamNum ) != Pcm::PCM_STATUS_FREE)\r\n\t\t\t\tdone = false;\r\n\t\t}\r\n\r\n\t\tif (done)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tmovie( pName );\r\n    //while ( ( movie( pName ) ) != MOVIE_ABORTED)\r\n    //\t;\r\n\r\n\t// Clear double buffers to black:\r\n\tclearGsMem(0x00, 0x00, 0x00, width, height);\r\n\t\r\n\t\r\n\t// wait for any sound transfer to complete and shit...\r\n\tif ( sceSdRemote( 1, rSdVoiceTransStatus, AUTODMA_CH, SD_TRANS_STATUS_WAIT ) == -1 )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Complete SPU2 Transfer Failed\\n\"));\r\n\t}\r\n\r\n\tMem::Free( pNonAllignedMovieMem );\r\n\tgpMovieMem = NULL;\r\n\t\r\n#if SAVE_SCRATCHPAD\r\n\t// restore scratchpad:\r\n\tfor ( i = 0; i < SCRATCHPAD_SIZE; i++ )\r\n\t{\r\n\t\t( ( unsigned char * ) 0x70000000 )[ i ] = pScratchpad[ i ];\r\n\t}\r\n\tMem::Free( pScratchpad );\r\n#else\r\n\tif (got_scratch)\r\n\t{\r\n\t\tNxPs2::CSystemResources::sFreeResource(NxPs2::CSystemResources::vSCRATCHPAD_MEMORY);\r\n\t}\r\n#endif // SAVE_SCRATCHPAD\r\n\r\n//\tVSync( );\r\n//\twhile ( Tmr::GetVblanks() & 1 );\r\n\r\n#endif // playmovieplease\r\n\r\n\r\n\tChangeThreadPriority(GetThreadId(), origThreadPriority );\r\n\r\n\tTmr::VSync( );\r\n\r\n\treturn;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Decode MPEG bitstream\r\n//\r\n// ret:\r\n//   1: ok\r\n//   0: error\r\n//  -1: abort\r\nstatic u_int movie( const char *name )\r\n{\r\n\tCHECK_MOVIE_MEM;\r\n\r\n    static int count = 0;\r\n\r\n    printf(\"========================== decode MPEG2 ============= %d ===========\\n\", count++);\r\n\t\r\n    if (initAll(name ))\r\n\t{\r\n\t\tprintf( \"done w/ initall\\n\" );\t\r\n\t\treadMpeg(& MOVIE_MEM_PTR videoDec, & MOVIE_MEM_PTR readBuf, & MOVIE_MEM_PTR infile);\r\n\t}\r\n\r\n\ttermAll();\r\n\r\n    return controller_val;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Read MPEG data\r\n//\r\n// return value\r\n//     1: normal end\r\n//     -1: aborted\r\nstatic int readMpeg(VideoDec *vd, ReadBuf *rb, StrFile *file)\r\n{\r\n\t\r\n    u_int ctrlmask =  SCE_PADRdown | SCE_PADstart;\r\n    u_char *put_ptr;\r\n    u_char *get_ptr;\r\n    int putsize;\r\n    int getsize;\r\n    int readrest = file->size;\r\n    int writerest = file->size;\r\n    int count;\r\n    int proceed;\r\n    int isStarted = 0;\r\n    u_int button_old = 0;\r\n    u_int pushed = 0;\r\n    u_char cdata[32];\r\n    int isPaused = 0;\r\n\r\n    // writerest > 4: to skip the last 4 bytes\r\n    while (isPaused\r\n    \t|| (writerest > 4 && videoDecGetState(vd) != VD_STATE_END)) {\r\n\r\n    \t// /////////////////////////////////////////////////\r\n\t//\r\n\t// Get controller information\r\n\t//\r\n   \tif (scePadRead(0, 0, cdata) > 0) {\r\n\t    controller_val = 0xffff ^ ((cdata[2] << 8) | cdata[3]);\r\n\t} else {\r\n\t    controller_val = 0;\r\n\t}\r\n\tpushed = (button_old ^ controller_val)\r\n\t\t\t& controller_val & ctrlmask;\r\n\tbutton_old = controller_val;\r\n\r\n\tCHECK_MOVIE_MEM;\r\n\r\n\tif (pushed && vd->mpeg.frameCount > 10)\r\n\t{\r\n\r\n/*\t    if (pushed & SCE_PADRleft) {\r\n\t    \tif (isPaused) {\r\n\t\t    startDisplay(1);\r\n\t\t    if (isWithAudio) {\r\n\t\t\taudioDecResume(& MOVIE_MEM_PTR audioDec);\r\n\t\t    }\r\n\t\t} else {\r\n\t\t    endDisplay();\r\n\t\t    if (isWithAudio) {\r\n\t\t\taudioDecPause(& MOVIE_MEM_PTR audioDec);\r\n\t\t    }\r\n\t\t}\r\n\t\tisPaused ^= 1;\r\n\t    } else if (!isPaused) {\r\n*/\r\n\t\t// /////////////////////////////////////////////////\r\n\t\t//\r\n\t\t// Abort decoding\r\n\t\t//\r\n\t\tvideoDecAbort(& MOVIE_MEM_PTR videoDec);\r\n\t//    }\r\n\r\n\t\t// Record frame number if we hit START so we skip all movies\r\n\t\tif (pushed & SCE_PADstart)\r\n\t\t{\r\n\t\t\thitStartFrame = Tmr::GetRenderFrame();\r\n\t\t\thitStart = true;\r\n\t\t} else {\r\n\t\t\thitStart = false;\r\n\t\t}\r\n\t}\r\n   \t\r\n\t// /////////////////////////////////////////////////\r\n\t//\r\n\t// Read data to the read buffer\r\n\t//\r\n        putsize = readBufBeginPut(rb, &put_ptr);\r\n\tif (readrest > 0 && putsize >= READ_UNIT_SIZE) {\r\n\t    count = strFileRead(file, put_ptr, READ_UNIT_SIZE);\r\n\t    readBufEndPut(rb, count);\r\n\t    readrest -= count;\r\n\t}\r\n\r\n\tswitchThread();\r\n\r\n    \t// /////////////////////////////////////////////////\r\n\t//\r\n\t// De-multiplex and put data on video/audio input buffer\r\n\t//\r\n\tgetsize = readBufBeginGet(rb, &get_ptr);\r\n\tif (getsize > 0) {\r\n\r\n\t    proceed = sceMpegDemuxPssRing(&vd->mpeg,\r\n\t    \t\tget_ptr, getsize, rb->data, rb->size);\r\n\r\n\t    readBufEndGet(rb, proceed);\r\n\t    writerest -= proceed;\r\n\r\n\t}\r\n\r\n    \t// /////////////////////////////////////////////////\r\n\t//\r\n\t// Send audio data to IOP\r\n\t//\r\n\tproceedAudio();\r\n\r\n    \t// /////////////////////////////////////////////////\r\n\t//\r\n\t// Wait until video and audio output buffer become full\r\n\t//\r\n\tCHECK_MOVIE_MEM;\r\n\t\r\n\tif (!isStarted && voBufIsFull(& MOVIE_MEM_PTR voBuf) && isAudioOK()) {\r\n\r\n\t    startDisplay(1);\t\t// start video\r\n\t    if (isWithAudio) {\r\n\t\taudioDecStart(& MOVIE_MEM_PTR audioDec);\t// start audio\r\n\t    }\r\n\t    isStarted = 1;\r\n\t}\r\n    }\r\n\r\n    // try to flush buffers inside decoder\r\n    while (!videoDecFlush(vd)) {\r\n\tswitchThread();\r\n    }\r\n\r\n    // wait till buffers are flushed\r\n    while (!videoDecIsFlushed(vd)\r\n    \t&& videoDecGetState(vd) != VD_STATE_END) {\r\n\r\n\tswitchThread();\r\n    }\r\n\r\n    endDisplay();\r\n    if (isWithAudio)\r\n\t{\r\n\t\taudioDecReset(& MOVIE_MEM_PTR audioDec);\r\n    }\r\n\r\n    return 1;\r\n}\r\n\r\n// /////////////////////////////////////////////////\r\n//\r\n// Switch to another thread\r\n//\r\nvoid switchThread()\r\n{\r\n    RotateThreadReadyQueue( MOVIE_THREAD_PRIORITY );\r\n}\r\n\r\n// /////////////////////////////////////////////////\r\n//\r\n// Check audio\r\n//\r\nstatic int isAudioOK()\r\n{\r\n\t\r\n    CHECK_MOVIE_MEM;\r\n\treturn (isWithAudio)? audioDecIsPreset(& MOVIE_MEM_PTR audioDec): 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Initialize all modules\r\n//\r\nstatic bool initAll( const char *bsfilename )\r\n{\r\n\t\r\n    struct ThreadParam th_param;\r\n\r\n    *D_CTRL = (*D_CTRL | 0x003);\r\n    *D_STAT = 0x4; // clear D_STAT.CIS2\r\n\r\n    // /////////////////////////////\r\n    // \r\n    //  Create read buffer\r\n    // \r\n    CHECK_MOVIE_MEM;\r\n\t\r\n\treadBufCreate(& MOVIE_MEM_PTR readBuf);\r\n\r\n    // /////////////////////////////\r\n    // \r\n    //  Initialize video decoder\r\n    // \r\n    sceMpegInit();\r\n    videoDecCreate(& MOVIE_MEM_PTR videoDec,\r\n    \t MOVIE_MEM_PTR mpegWork, MPEG_WORK_SIZE,\r\n    \t MOVIE_MEM_PTR viBufData,  MOVIE_MEM_PTR viBufTag, VIBUF_SIZE,  MOVIE_MEM_PTR timeStamp, VIBUF_TS_SIZE);\r\n\r\n    // /////////////////////////////\r\n    // \r\n    //  Initialize audio decoder\r\n    // \r\n#define NEED_TO_INIT_SD_AND_SHIT 0\r\n#if NEED_TO_INIT_SD_AND_SHIT    \r\n\tsceSdRemoteInit();\r\n    sceSdRemote(1, rSdInit, SD_INIT_COLD);  // i think having this in would fuck up soundfx module...\r\n#endif\r\n    audioDecCreate(& MOVIE_MEM_PTR audioDec,  MOVIE_MEM_PTR audioBuff, AUDIO_BUFF_SIZE,\r\n\t\t\tIOP_BUFF_SIZE, Pcm::PCMAudio_GetIopMemory( ) );\r\n\r\n    ///////////////////////////////\r\n    // \r\n    //  Choose stream to be played\r\n    // \r\n    videoDecSetStream(& MOVIE_MEM_PTR videoDec,\r\n\t    sceMpegStrM2V, 0, (sceMpegCallback)videoCallback, & MOVIE_MEM_PTR readBuf);\r\n    if (isWithAudio) {\r\n\tvideoDecSetStream(& MOVIE_MEM_PTR videoDec,\r\n\t    sceMpegStrPCM, 0, (sceMpegCallback)pcmCallback, & MOVIE_MEM_PTR readBuf);\r\n    }\r\n\r\n    // /////////////////////////////\r\n    // \r\n    //  Initialize video output buffer\r\n    // \r\n    voBufCreate(& MOVIE_MEM_PTR voBuf, ( VoData * )UncAddr( MOVIE_MEM_PTR voBufData),  MOVIE_MEM_PTR voBufTag, N_VOBUF);\r\n\r\n    // /////////////////////////////\r\n    // \r\n    //  Create 'default' thread\r\n    // \r\n\tDbg_Message( \"Starting default thread\" );\r\n    th_param.entry = defMain;\r\n    th_param.stack =  MOVIE_MEM_PTR defStack;\r\n    th_param.stackSize = MOVIE_DEF_STACK_SIZE;\r\n    th_param.initPriority = MOVIE_THREAD_PRIORITY;\r\n    th_param.gpReg = &_gp;\r\n    th_param.option = 0;\r\n    defaultTh = CreateThread(&th_param);\r\n    StartThread(defaultTh, NULL);\r\n    \r\n\t// /////////////////////////////\r\n    // \r\n    //  Create docode thread\r\n    // \r\n\tDbg_Message( \"Starting video decoder thread\" );\r\n    th_param.entry = videoDecMain;\r\n    th_param.stack =  MOVIE_MEM_PTR videoDecStack;\r\n    th_param.stackSize = MOVIE_STACK_SIZE;\r\n    th_param.initPriority = MOVIE_THREAD_PRIORITY;\r\n    th_param.gpReg = &_gp;\r\n    th_param.option = 0;\r\n    videoDecTh = CreateThread(&th_param);\r\n    StartThread(videoDecTh, NULL );\r\n\r\n    // /////////////////////////////\r\n    // \r\n    //  Initialize controller\r\n    // \r\n\r\n/*\tstatic int isFirst = 1;\r\n\tif (isFirst)\r\n\t{\r\n\t    scePadInit(0);\r\n\t    scePadPortOpen(0, 0,  MOVIE_MEM_PTR controller_dma_buf);\r\n\t    isFirst = 0;\r\n\t}*/\r\n\r\n\tchar filename[ 256 ];\r\n\tif (Config::CD() || FORCE_MOVIES_FROM_CD_PLEASE)\r\n\t{\r\n\t\tsprintf( filename, \"cdrom0:\\\\%s%s.PSS;1\",Config::GetDirectory(), bsfilename );\r\n\t\tunsigned int schraw;\r\n\t\tfor ( schraw = 7; schraw < strlen( filename ); schraw++ ) // start after \"cdrom0:\\\"\r\n\t\t{\r\n\t\t\tif ( filename[ schraw ] >= 'a' && filename[ schraw ] <= 'z' )\r\n\t\t\t{\r\n\t\t\t\tfilename[ schraw ] += 'A' - 'a';\r\n\t\t\t}\r\n\t\t\telse if ( filename[ schraw ] == '/' )\r\n\t\t\t{\r\n\t\t\t\tfilename[ schraw ] = '\\\\';\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tsprintf( filename, \"host0:\\\\%s.pss\", bsfilename );\r\n\t}\t\r\n\t\r\n    // /////////////////////////////\r\n    // \r\n    //  Open bitstream file\r\n    // \r\n\tFile::StopStreaming( );\r\n\tif ( Pcm::UsingCD( ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Can't load IRX modules when CD is busy.\" ));\r\n\t\treturn false;\r\n\t}\r\n    \r\n\tbool\tloaded = false;\r\n\tfor (int i = 0;i <10; i++)\r\n\t{\r\n\t\tprintf (\"Attempt %d\\n\",i);\r\n\t\tif (!strFileOpen(& MOVIE_MEM_PTR infile, filename,\r\n\t\t\tPcm::PCMAudio_GetIopMemory( ) + IOP_BUFF_SIZE + ( 2048 * STRFILE_NUM_STREAMING_SECTORS + 64 ) ))\t\t\t \r\n\t\t{\r\n\t\t\tprintf (\"Can't Open file %s\\n\", filename);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tloaded = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n    // /////////////////////////////\r\n    // \r\n    //  Set Interrupt handlers\r\n    // \r\n\tMOVIE_MEM_PTR videoDec.hid_vblank = AddIntcHandler(INTC_VBLANK_S, vblankHandler, 0);\r\n\tEnableIntc(INTC_VBLANK_S);\r\n\r\n\tMOVIE_MEM_PTR videoDec.hid_endimage = AddDmacHandler(DMAC_GIF, handler_endimage, 0);\r\n\tEnableDmac(DMAC_GIF);\r\n\t\r\n\treturn loaded;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Terminate all modules\r\n//\r\nstatic void termAll()\r\n{\r\n\t\r\n\t\r\n\tCHECK_MOVIE_MEM;\r\n\r\n    TerminateThread(videoDecTh);\r\n    DeleteThread(videoDecTh);\r\n\r\n    TerminateThread(defaultTh);\r\n    DeleteThread(defaultTh);\r\n\r\n    DisableDmac(DMAC_GIF);\r\n    RemoveDmacHandler(DMAC_GIF,  MOVIE_MEM_PTR videoDec.hid_endimage);\r\n\t//EnableDmac(DMAC_GIF);\r\n\r\n    DisableIntc(INTC_VBLANK_S);\r\n    RemoveIntcHandler(INTC_VBLANK_S,  MOVIE_MEM_PTR videoDec.hid_vblank);\r\n\tEnableIntc(INTC_VBLANK_S);\r\n    \r\n\treadBufDelete(& MOVIE_MEM_PTR readBuf);\r\n    voBufDelete(& MOVIE_MEM_PTR voBuf);\r\n\r\n    videoDecDelete(& MOVIE_MEM_PTR videoDec);\r\n    audioDecDelete(& MOVIE_MEM_PTR audioDec);\r\n\r\n    strFileClose(& MOVIE_MEM_PTR infile);\r\n\r\n\t// Re-init nx engine\r\n\tNxPs2::ResetEngine();\r\n\r\n\t// Re-init quick filesystem (since the CD stream buffer has changed)\r\n\tif (Config::CD())\r\n\t{\r\n\t\tFile::ResetQuickFileSystem();\r\n\t}\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Main function of default thread\r\n//\r\nstatic void defMain(void * dummy)\r\n{\r\n    while (1) {\r\n\tswitchThread();\r\n    }\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Print error message\r\n//\r\nvoid ErrMessage(char *message)\r\n{\r\n    printf(\"[ Error ] %s\\n\", message);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Send audio data to IOP\r\n//\r\nvoid proceedAudio()\r\n{\r\n\t\r\n    \r\n\tCHECK_MOVIE_MEM;\r\n\t\r\n\taudioDecSendToIOP(& MOVIE_MEM_PTR audioDec);\r\n}\r\n\r\n\r\n\r\n} // namespace Flx\r\n\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/p_movies.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tps2 movies\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/movies/ngps/p_movies.h \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t5/14/01\t-\tmjd\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __P_MOVIES_H\r\n#define __P_MOVIES_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/singleton.h>\r\n#include <core/list.h>\r\n#include <core/macros.h>\r\n#include <libmpeg.h>\r\n#include <libpad.h>\r\n\r\n#include \"gel/movies/ngps/defs.h\"\r\n#include \"gel/movies/ngps/vobuf.h\"\r\n#include \"gel/movies/ngps/vibuf.h\"\r\n#include \"gel/movies/ngps/strfile.h\"\r\n#include \"gel/movies/ngps/readbuf.h\"\r\n#include \"gel/movies/ngps/videodec.h\"\r\n#include \"gel/movies/ngps/audiodec.h\"\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\n#define MOVIE_STACK_SIZE    (16*1024)\r\n#define MOVIE_DEF_STACK_SIZE    2048\r\n#define MAX_MBX\t\t(MAX_WIDTH/16)\r\n#define MAX_MBY\t\t(MAX_HEIGHT/16)\r\n#define IOP_BUFF_SIZE (12288*2) // 512 * 48\r\n#define MOVIE_ABORTED SCE_PADRdown\r\n//#define DEF_PRIORITY       32\r\n#define ERR_STOP while(1)\r\n\r\n#define MPEG_WORK_SIZE ( SCE_MPEG_BUFFER_SIZE(MAX_WIDTH, MAX_HEIGHT) )\r\n#define AUDIO_BUFF_SIZE ( IOP_BUFF_SIZE * 2 )\r\n\r\n#define ZERO_BUFF_SIZE\t0x800\r\n\t  \r\n// send in size, returns the size needed to create a 64-byte boundary:\r\n#define PAD_FOR_64( x ) ( 64 - ( ( x ) & 63 ) )\r\n// send in size, returns the size to the next 64 byte boundary:\r\n#define PADDED_64( x ) ( ( x ) + PAD_FOR_64( x ) )\r\n\r\n// This structure contains everything that was previously just\r\n// global (and taking up loads of memory)...\r\nstruct SMovieMem{\r\n\r\n\tu_long128 packetBase[ 6 ];\r\n\tchar pad665[ PAD_FOR_64( sizeof( u_long128 ) * 6 ) ];\r\n\t\t \r\n\tchar _0_buf [ ZERO_BUFF_SIZE ];\r\n\tchar pad666[ PAD_FOR_64( ZERO_BUFF_SIZE ) ];\r\n\t\r\n\t// ******* NOTE ::: KEEP ALL THESE ON 64 - BYTE BOUNDARIES AND SHIT!! ********\r\n\r\n\t// These variables could be accessed from Uncached Area\r\n\tVoData voBufData[ N_VOBUF ];\r\n\tchar pad0[ PAD_FOR_64( ( sizeof( VoData ) * N_VOBUF ) ) ];\r\n\r\n\tVoTag voBufTag[ N_VOBUF ];\r\n\tchar pad1[ PAD_FOR_64( ( sizeof( VoTag ) * N_VOBUF ) ) ];\r\n\r\n\tu_long128 viBufTag[ VIBUF_SIZE + 1 ];\r\n\tchar pad2[ PAD_FOR_64( ( sizeof( u_long128 ) * ( VIBUF_SIZE + 1 ) ) ) ];\r\n\r\n\t// -------------- this needs to be 64 byte boudary -------------------\r\n\t\r\n\t// These variables are NOT accessed from Uncached Area\r\n\tu_char mpegWork[ PADDED_64( MPEG_WORK_SIZE ) ];\r\n\tchar defStack[ PADDED_64( MOVIE_DEF_STACK_SIZE )];\r\n\tu_char audioBuff[PADDED_64( IOP_BUFF_SIZE*2 )];\r\n\tu_long128 viBufData[ PADDED_64( VIBUF_SIZE * VIBUF_ELM_SIZE/16 ) ];\r\n\tchar videoDecStack[ PADDED_64 ( MOVIE_STACK_SIZE )];\r\n\tTimeStamp timeStamp[ VIBUF_TS_SIZE ];\r\n\tchar pad3[ PAD_FOR_64( sizeof( TimeStamp ) * VIBUF_TS_SIZE ) ];\r\n\r\n//\tu_long128 controller_dma_buf[ scePadDmaBufferMax ];\r\n//\tchar pad4[ PAD_FOR_64( ( sizeof( u_long128 ) * ( scePadDmaBufferMax ) ) ) ];\r\n\r\n\tstruct ReadBuf readBuf;\r\n\tchar pad5[ PAD_FOR_64( sizeof( ReadBuf ) ) ];\r\n\t\r\n\tstruct StrFile infile;\r\n\tchar pad6[ PAD_FOR_64( sizeof( StrFile ) ) ];\r\n\tstruct VideoDec videoDec;\r\n\tchar pad7[ PAD_FOR_64( sizeof( VideoDec ) ) ];\r\n\tstruct AudioDec audioDec;\r\n\tchar pad8[ PAD_FOR_64( sizeof( AudioDec ) ) ];\r\n\tstruct VoBuf voBuf;\r\n};\r\n\r\nextern SMovieMem *gpMovieMem;\r\n\r\n#define MOVIE_MEM_PTR\tgpMovieMem->\r\n#define CHECK_MOVIE_MEM\tDbg_MsgAssert( gpMovieMem, ( \"Movie Memory not initialized.\" ) )\r\n\r\nvoid PMovies_PlayMovie( const char *pName );\r\n\r\nvoid FuckUpVram( char color ); // testing what the fuck vram funcs are doing...\r\n\r\n} // namespace Flx\r\n\r\n#endif\t// __P_MOVIES_H\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/read.cpp",
    "content": "#include <libmpeg.h>\r\n#include <core/defines.h>\r\n#include <core/macros.h>\r\n#include <core/singleton.h>\r\n#include \"gel/movies/ngps/p_movies.h\"\r\n#include \"gel/movies/ngps/readbuf.h\"\r\n#include \"gel/movies/ngps/videodec.h\"\r\n#include \"gel/movies/ngps/defs.h\"\r\n#include \"gel/movies/ngps/audiodec.h\"\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\nstatic int copy2area(u_char *pd0, int d0, u_char *pd1, int d1,\r\n    u_char *ps0, int s0, u_char *ps1, int s1);\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Stream callback function for MPEG2 video stream\r\n//\r\nint videoCallback(sceMpeg *mp, sceMpegCbDataStr *str, void *data)\r\n{\r\n\t\r\n    \r\n\tCHECK_MOVIE_MEM;\r\n\t\r\n\tReadBuf *rb = (ReadBuf*)data;\r\n    u_char *ps0 = str->data;\r\n    u_char *ps1 = rb->data;\r\n    int s0 = min( ( int )rb->data + ( int )rb->size - ( int )str->data, ( int )str->len);\r\n    int s1 = str->len - s0;\r\n    u_char *pd0;\r\n    u_char *pd1;\r\n    u_char *pd0Unc;\r\n    u_char *pd1Unc;\r\n    int d0, d1;\r\n    int len;\r\n\r\n    videoDecBeginPut(& MOVIE_MEM_PTR videoDec, &pd0, &d0, &pd1, &d1);\r\n    pd0Unc = (u_char*)UncAddr(pd0);\r\n    pd1Unc = (u_char*)UncAddr(pd1);\r\n\r\n    len = copy2area(pd0Unc, d0, pd1Unc, d1, ps0, s0, ps1, s1);\r\n\r\n    // set PTS\r\n    if (len > 0) {\r\n\tif (!videoDecPutTs(& MOVIE_MEM_PTR videoDec, str->pts, str->dts, pd0, len)) {\r\n\t    ErrMessage(\"pts buffer overflow\\n\");\r\n\t}\r\n    }\r\n\r\n    videoDecEndPut(& MOVIE_MEM_PTR videoDec, len);\r\n\r\n    // ////////////////////////////////////////////\r\n    //\r\n    // Return 0 if no data is put\r\n    //\r\n    return (len > 0)? 1: 0;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Stream callback function for PS2 PCM stream\r\n//\r\nint pcmCallback(sceMpeg *mp, sceMpegCbDataStr *str, void *data)\r\n{\r\n    ReadBuf *rb = (ReadBuf*)data;\r\n    u_char *ps0 = str->data;\r\n    u_char *ps1 = rb->data;\r\n    int s0;\r\n    int s1;\r\n    u_char *pd0;\r\n    u_char *pd1;\r\n    int d0, d1;\r\n    int len;\r\n    int ret;\r\n\r\n    // skip\r\n    // sub_stream_id\r\n    ps0 = str->data + 4;\r\n    if (ps0 >= rb->data + rb->size) {\r\n    \tps0 -= rb->size;\r\n    }\r\n    len = str->len - 4;\r\n\r\n    ps1 = rb->data;\r\n    s0 = min(rb->data + rb->size - ps0, len);\r\n    s1 = len - s0;\r\n\r\n    audioDecBeginPut(& MOVIE_MEM_PTR audioDec, &pd0, &d0, &pd1, &d1);\r\n    ret = copy2area(pd0, d0, pd1, d1, ps0, s0, ps1, s1);\r\n\r\n    audioDecEndPut(& MOVIE_MEM_PTR audioDec, ret);\r\n\r\n    // ////////////////////////////////////////////\r\n    //\r\n    // Return 0 if no data is put\r\n    //\r\n    return (ret > 0)? 1: 0;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Copy two areas\r\n//\r\nstatic int copy2area(u_char *pd0, int d0, u_char *pd1, int d1,\r\n    u_char *ps0, int s0, u_char *ps1, int s1)\r\n{\r\n    if (d0 + d1 < s0 + s1) {\r\n        return 0;\r\n    }\r\n\r\n    if (s0 >= d0) {\r\n    \tmemcpy(pd0,\t\tps0,\t\td0);\r\n    \tmemcpy(pd1,\t\tps0 + d0,\ts0 - d0);\r\n    \tmemcpy(pd1 + s0 - d0,\tps1,\t\ts1);\r\n    } else { // s0 < d0\r\n    \tif (s1 >= d0 - s0) {\r\n\t    memcpy(pd0,\t\tps0,\t\ts0);\r\n\t    memcpy(pd0 + s0,\tps1,\t\td0 - s0);\r\n\t    memcpy(pd1,\t\tps1 + d0 - s0,\ts1 - (d0 - s0));\r\n\t} else { // s1 < d0 - s0\r\n\t    memcpy(pd0,\t\tps0,\t\ts0);\r\n\t    memcpy(pd0 + s0,\tps1,\t\ts1);\r\n\t}\r\n    }\r\n    return s0 + s1;\r\n}\r\n\r\n} // namespace Flx\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/readbuf.cpp",
    "content": "#include \"gel/movies/ngps/defs.h\"\r\n#include \"gel/movies/ngps/readbuf.h\"\r\n\r\n#define BUFF_SIZE (N_READ_UNIT * READ_UNIT_SIZE)\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Create read buffer\r\n//\r\nvoid readBufCreate(ReadBuf *b)\r\n{\r\n    b->put = b->count = 0;\r\n    b->size = BUFF_SIZE;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Delete read buffer\r\n//\r\nvoid readBufDelete(ReadBuf *b)\r\n{\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Get empty area\r\n//\r\nint readBufBeginPut(ReadBuf *b, u_char **ptr)\r\n{\r\n    int size = b->size - b->count;\r\n    if (size) {\r\n        *ptr = b->data + b->put;\r\n    }\r\n    return size;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Proceed 'write' pointer\r\n//\r\nint readBufEndPut(ReadBuf *b, int size)\r\n{\r\n    int size_ok = min(b->size - b->count, size);\r\n\r\n    b->put = (b->put + size_ok) % b->size;\r\n    b->count += size_ok;\r\n\r\n    return size_ok;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Get data area\r\n//\r\nint readBufBeginGet(ReadBuf *b, u_char **ptr)\r\n{\r\n    if (b->count) {\r\n        *ptr = b->data + (b->put - b->count + b->size) % b->size;\r\n    }\r\n    return b->count;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Proceed 'read' pointer\r\n//\r\nint readBufEndGet(ReadBuf *b, int size)\r\n{\r\n    int size_ok = min(b->count, size);\r\n\r\n    b->count -= size_ok;\r\n\r\n    return size_ok;\r\n}\r\n\r\n} // namespace Flx\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/readbuf.h",
    "content": "#ifndef _READBUF_H_\r\n#define _READBUF_H_\r\n\r\n#include <eetypes.h>\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/macros.h>\r\n#include <core/singleton.h>\r\n\r\n\r\n#define READ_UNIT_SIZE (64*1024)\r\n#define N_READ_UNIT     5\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Read buffer\r\n//\r\nstruct ReadBuf{\r\n    u_char data[N_READ_UNIT * READ_UNIT_SIZE];\r\n    int put;\r\n    int count;\r\n    int size;\r\n};\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Functions\r\n//\r\nvoid readBufCreate(ReadBuf *buff);\r\nvoid readBufDelete(ReadBuf *buff);\r\nint readBufBeginPut(ReadBuf *buff, u_char **ptr);\r\nint readBufEndPut(ReadBuf *buff, int size);\r\nint readBufBeginGet(ReadBuf *buff, u_char **ptr);\r\nint readBufEndGet(ReadBuf *buff, int size);\r\n\r\n} // namespace Flx\r\n\r\n#endif // _READBUF_H_\r\n\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/strfile.cpp",
    "content": "#include <stdio.h>\r\n#include <string.h>\r\n#include <ctype.h>\r\n#include <eekernel.h>\r\n#include <sifdev.h>\r\n#include \"gel/movies/ngps/defs.h\"\r\n#include \"gel/movies/ngps/strfile.h\"\r\n#include <sys/config/config.h>\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\nint isStrFileInit = 0;\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Open a file to read and check its size\r\n//\r\n//\t< file name conversion >\r\n//\t   = from HD =\r\n//\t    dir/file.pss           -> host0:dir/file.pss\r\n//\t    host0:dir/file.pss     -> host0:dir/file.pss\r\n//\r\n//\t   = from CD/DVD =\r\n//\t    cdrom0:\\dir\\file.pss;1 -> cdrom0:\\DIR\\FILE.PSS;1\r\n//\t    cdrom0:/dir/file.pss;1 -> cdrom0:\\DIR\\FILE.PSS;1\r\n//\t    cdrom0:/dir/file.pss   -> cdrom0:\\DIR\\FILE.PSS;1\r\n//\r\nint strFileOpen(StrFile *file, char *filename, int pIopBuff )\r\n{\r\n    int ret;\r\n    char *body = NULL;\r\n    char fn[256];\r\n    char devname[64];\r\n\r\n    body = index(filename, ':');\r\n\r\n\tif (body)\r\n\t{\r\n\t\tint dlen;\r\n\r\n\t\t// copy device name\r\n\t\tdlen = body - filename;\r\n\t\tstrncpy(devname, filename, dlen);\r\n\t\tdevname[dlen] = 0;\r\n\r\n\t\tbody += 1;\r\n\r\n\t\tif (!strcmp(devname, \"cdrom0\"))\r\n\t\t{ // CD/DVD\r\n\t\t\tint i;\r\n\t\t\tint len = strlen(body);\r\n\t\t\tconst char *tail;\r\n\r\n\t\t\tfile->isOnCD = 1;\r\n\r\n\t\t\tfor (i = 0; i < len; i++)\r\n\t\t\t{\r\n\t\t\t\tif (body[i] == '/')\r\n\t\t\t\t{\r\n\t\t\t\t\tbody[i] = '\\\\';\r\n\t\t\t\t}\r\n\t\t\t\tbody[i] = toupper(body[i]);\r\n\t\t\t}\r\n\r\n\t\t\ttail = (index(filename, ';'))? \"\": \";1\";\r\n\t\t\tsprintf(fn, \"%s%s\", body, tail);\r\n\r\n\t\t}\r\n\t\telse\r\n\t\t{\t\t\t // HD\r\n\t\t\tfile->isOnCD = 0;\r\n\t\t\tsprintf(fn, \"%s:%s\", devname, body+1);  // Mick:  The +1 is to skip the initial \\, so file names are the same off HD aas CD \r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\t\t\t\t // HD (default)\r\n\t\tbody = filename;            \r\n\t\tstrcpy(devname, \"host0\");\r\n\t\tfile->isOnCD = 0;\r\n\t\tsprintf(fn, \"%s:%s\", devname, body);\r\n\t}\r\n\r\n    printf(\"file: %s\\n\", fn);\r\n\r\n    if (file->isOnCD)\r\n\t{\r\n\t\tsceCdRMode mode;\r\n\t\tif (!Config::CD())\r\n\t\t{\r\n\t\t\tif (!isStrFileInit)\r\n\t\t\t{\r\n\t\t\t\tsceCdInit(SCECdINIT);\r\n\t\t\t\tsceCdMmode(SCECdDVD);\r\n\t\t\t\tsceCdDiskReady(0);\r\n\t\t\r\n\t\t\t\tisStrFileInit = 1;\r\n\t\t\t}\r\n\t\t}\t\r\n\t\tfile->iopBuf = ( u_char * )pIopBuff; //( u_char * )sceSifAllocIopHeap((2048 * 80) + 16);\r\n\t\tsceCdStInit(80, 5, bound((u_int)file->iopBuf, 16));\r\n\t\r\n\t\tif(!sceCdSearchFile(&file->fp, fn)){\r\n\t\r\n\t\t\tprintf(\"Cannot open '%s'(sceCdSearchFile)\\n\", fn);\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\r\n\t\tfile->size = file->fp.size;\r\n\t\tmode.trycount = 0;\r\n\t\tmode.spindlctrl = SCECdSpinStm;\r\n\t\tmode.datapattern = SCECdSecS2048;\r\n\t\tsceCdStStart(file->fp.lsn, &mode);\r\n    }\r\n\telse\r\n\t{\r\n\r\n\t\tfile->fd = sceOpen(fn, SCE_RDONLY);\r\n\t\tif (file->fd < 0)\r\n\t\t{\r\n\t\t\tprintf(\"Cannot open '%s'(sceOpen)\\n\", fn);\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\tfile->size = sceLseek(file->fd, 0, SCE_SEEK_END);\r\n\t\tif (file->size < 0)\r\n\t\t{\r\n\t\t\tprintf(\"sceLseek() fails (%s): %d\\n\", fn, file->size);\r\n\t\t\tsceClose(file->fd);\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\r\n\t\tret = sceLseek(file->fd, 0, SCE_SEEK_SET);\r\n\t\tif (ret < 0)\r\n\t\t{\r\n\t\t\tprintf(\"sceLseek() fails (%s)\\n\", fn);\r\n\t\t\tsceClose(file->fd);\r\n\t\t\treturn 0;\r\n\t\t}\r\n    }\r\n\r\n    return 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Close a file\r\n//\r\nint strFileClose(StrFile *file)\r\n{\r\n    if (file->isOnCD) {\r\n    \tsceCdStStop();\r\n//        sceSifFreeIopHeap((void *)file->iopBuf);\r\n    } else {\r\n\tsceClose(file->fd);\r\n    }\r\n    return 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Read data\r\n//\r\nint strFileRead(StrFile *file, void *buff, int size)\r\n{\r\n    int count;\r\n    if (file->isOnCD) {\r\n\tu_int err;\r\n\r\n        count= sceCdStRead(size >> 11, (u_int *)buff, STMBLK, &err);\r\n\tcount <<= 11;\r\n\r\n    } else {\r\n\tcount = sceRead(file->fd, buff, size);\r\n    }\r\n    return count;\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/strfile.h",
    "content": "#ifndef _STRFILE_H_\r\n#define _STRFILE_H_\r\n\r\n#include <eetypes.h>\r\n#include <libcdvd.h>\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/macros.h>\r\n#include <core/singleton.h>\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Structure to read data from CD/DVD or HD\r\n//\r\nstruct StrFile{\r\n    int isOnCD;\t\t// CD/DVD or HD\r\n    int size;\r\n\r\n    sceCdlFILE fp;\t// for CD/DVD stream\r\n    u_char *iopBuf;\r\n\r\n    int fd;\t\t// for HD stream\r\n};\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\nint strFileOpen(StrFile *file, char *filename, int pIopBuff);\r\nint strFileClose(StrFile *file);\r\nint strFileRead(StrFile *file, void *buff, int size);\r\n\r\n} // namespace Flx\r\n\r\n#endif // _STRFILE_H_\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/vibuf.cpp",
    "content": "#include <stdio.h>\r\n#include <sifdev.h>\r\n#include \"gel/movies/ngps/defs.h\"\r\n#include \"gel/movies/ngps/vibuf.h\"\r\n#include \"gel/movies/ngps/p_movies.h\"\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Definitions \r\n//\r\n#define DMA_ID_REFE\t0\r\n#define DMA_ID_NEXT\t2\r\n#define DMA_ID_REF\t3\r\n\r\n#define WAITSEMA(v) WaitSema(v)\r\n#define SIGNALSEMA(v) SignalSema(v)\r\n\r\n#define REST\t2\r\n\r\n#define TAG_ADDR(i)\t((u_int)DmaAddr(f->tag + i))\r\n#define DATA_ADDR(i)\t((u_int)f->data + VIBUF_ELM_SIZE * (i))\r\n#define WRAP_ADDR(addr) ((u_int)(f->data)     + (((u_int)(addr) - (u_int)(f->data)) % (VIBUF_ELM_SIZE * f->n)))\r\n\r\n#define IsInRegion(i,start,len,n)  (     (0 <= (((i) + (n) - (start)) % (n))) &&     ((((i) + (n) - (start)) % (n)) < (len)))\r\n\r\n#define FS(f)\t((f->dmaStart + f->dmaN) * VIBUF_ELM_SIZE)\r\n#define FN(f)\t((f->n - REST -  f->dmaN) * VIBUF_ELM_SIZE)\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// definition of QWORD\r\n//\r\ntypedef union {\r\n    u_long128\tq;\r\n    u_long \tl[2];\r\n    u_int  \ti[4];\r\n    u_short\ts[8];\r\n    u_char\tc[16];\r\n} QWORD;\r\n\r\nextern inline int IsPtsInRegion(int tgt, int pos, int len, int size)\r\n{\r\n    int tgt1 = (tgt + size - pos) % size;\r\n    return tgt1 < len;\r\n}\r\n\r\nint getFIFOindex(ViBuf *f, void *addr)\r\n{\r\n    if (addr == DmaAddr(f->tag + (f->n + 1))) {\r\n\treturn 0;\r\n    } else {\r\n\treturn ((u_int)addr - (u_int)f->data) / VIBUF_ELM_SIZE;\r\n    }\r\n}\r\n\r\nvoid setD3_CHCR(u_int val)\r\n{\r\n    DI();\r\n    *D_ENABLEW = ((*D_ENABLER)|0x00010000);\t// pause all channels\r\n    *D3_CHCR = val;\r\n    *D_ENABLEW = ((*D_ENABLER)&~0x00010000);\t// restart all channels\r\n    EI();\r\n}\r\n\r\nvoid setD4_CHCR(u_int val)\r\n{\r\n    DI();\r\n    *D_ENABLEW = ((*D_ENABLER)|0x00010000);\t// pause all channels\r\n    *D4_CHCR = val;\r\n    *D_ENABLEW = ((*D_ENABLER)&~0x00010000);\t// restart all channels\r\n    EI();\r\n}\r\n\r\nvoid scTag2(\r\n    QWORD *q,\r\n    void *addr,\r\n    u_int id,\r\n    u_int qwc\r\n)\r\n{\r\n    q->l[0] =\r\n    \t  (u_long)(u_int)addr << 32\r\n    \t| (u_long)id << 28\r\n    \t| (u_long)qwc << 0;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Create video input buffer\r\n//\r\nint viBufCreate(ViBuf *f,\r\n    u_long128 *data, u_long128 *tag, int size,\r\n    TimeStamp *ts, int n_ts)\r\n{\r\n    struct SemaParam param;\r\n\r\n    f->data = data;\r\n    f->tag = ( u_long128 * )UncAddr(tag);\r\n    f->n = size;\r\n    f->buffSize = size * VIBUF_ELM_SIZE;\r\n\r\n    f->ts = ts;\r\n    f->n_ts = n_ts;\r\n\r\n    // ////////////////////////////////\r\n    //\r\n    // Create Semaphore\r\n    //\r\n    param.initCount = 1;\r\n    param.maxCount = 1;\r\n    f->sema = CreateSema(&param);\r\n\r\n    // ////////////////////////////////\r\n    //\r\n    // Reset\r\n    //\r\n    viBufReset(f);\r\n\r\n    f->totalBytes = 0;\r\n\r\n    return TRUE;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Reset video input buffer\r\n//\r\nint viBufReset(ViBuf *f)\r\n{\r\n    int i;\r\n\r\n    f->dmaStart = 0;\r\n    f->dmaN = 0;\r\n    f->readBytes = 0;\r\n    f->isActive = TRUE;\r\n\r\n    f->count_ts = 0;\r\n    f->wt_ts = 0;\r\n    for (i = 0; i < f->n_ts; i++) {\r\n\tf->ts[i].pts = TS_NONE;\r\n\tf->ts[i].dts = TS_NONE;\r\n\tf->ts[i].pos = 0;\r\n\tf->ts[i].len = 0;\r\n    }\r\n\r\n    // ////////////////////////////////\r\n    //\r\n    // Init DMA tags\r\n    //\r\n    for (i = 0; i < f->n; i++) {\r\n    \tscTag2(\r\n\t    (QWORD*)(f->tag + i),\r\n\t    DmaAddr((char*)f->data + VIBUF_ELM_SIZE * i),\r\n\t    DMA_ID_REF,\r\n\t    VIBUF_ELM_SIZE/16\r\n\t);\r\n    }\r\n    scTag2(\r\n\t(QWORD*)(f->tag + i),\r\n\tDmaAddr(f->tag),\r\n\tDMA_ID_NEXT,\r\n\t0\r\n    );\r\n\r\n    *D4_QWC = 0;\r\n    *D4_MADR = (u_int)DmaAddr(f->data);\r\n    *D4_TADR = (u_int)DmaAddr(f->tag);\r\n    setD4_CHCR((0<<8) | (1<<2) | 1);\r\n\r\n    return TRUE;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Get areas to put data\r\n//\r\nvoid viBufBeginPut(ViBuf *f,\r\n\tu_char **ptr0, int *len0, u_char **ptr1, int *len1)\r\n{\r\n\t\r\n    int es;\r\n    int en;\r\n    int fs;\r\n    int fn;\r\n\r\n    WAITSEMA(f->sema);\r\n\r\n    fs = FS(f);\r\n    fn = FN(f);\r\n\r\n    es = (fs + f->readBytes) % f->buffSize;\r\n    en = fn - f->readBytes;\r\n\r\n    if (f->buffSize - es >= en) {\t// area0\r\n\t*ptr0 = (u_char*)f->data + es;\r\n    \t*len0 = en;\r\n\t*ptr1 = NULL;\r\n\t*len1 = 0;\r\n    } else {\t\t\t\t// area0 + area1\r\n\t*ptr0 = (u_char*)f->data + es;\r\n    \t*len0 = f->buffSize - es;\r\n\t*ptr1 = (u_char*)f->data;\r\n\t*len1 = en - (f->buffSize - es);\r\n    }\r\n\r\n    SIGNALSEMA(f->sema);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Proceed inner pointer\r\n//\r\nvoid viBufEndPut(ViBuf *f, int size)\r\n{\r\n    WAITSEMA(f->sema);\r\n\r\n    f->readBytes += size;\r\n    f->totalBytes += size;\r\n\r\n    SIGNALSEMA(f->sema);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Add bitstream data to DMA tag list\r\n//\r\nint viBufAddDMA(ViBuf *f)\r\n{\r\n    int i;\r\n    int index;\r\n    int id;\r\n    int last;\r\n    u_int d4chcr;\r\n    int isNewData = 0;\r\n    int consume;\r\n    int read_start, read_n;\r\n\r\n    WAITSEMA(f->sema);\r\n\r\n    if (!f->isActive) {\r\n\tErrMessage(\"DMA ADD not active\\n\");\r\n        return FALSE;\r\n    }\r\n\r\n    // ////////////////////////////////////////\r\n    //\r\n    // STOP DMA ch4\r\n    //\r\n    // d4chcr:\r\n    //\t(1) DMA was running\r\n    //\t    ORIGINAL DMA tag\r\n    //\t(2) DMA was not running\r\n    //\t    REFE tag\r\n    setD4_CHCR((DMA_ID_REFE<<28) | (0<<8) | (1<<2) | 1);\r\n    d4chcr = *D4_CHCR;\r\n\r\n    // ////////////////////////////////////////\r\n    //\r\n    // update dma pointer using D4_MADR\r\n    //\r\n    index = getFIFOindex(f, (void*)*D4_MADR);\r\n    consume = (index + f->n - f->dmaStart) % f->n;\r\n    f->dmaStart = (f->dmaStart + consume) % f->n;\r\n    f->dmaN -= consume;\r\n\r\n    // ////////////////////////////////////////\r\n    //\r\n    // update read pointer\r\n    //\r\n    read_start = (f->dmaStart + f->dmaN) % f->n;\r\n    read_n = f->readBytes/VIBUF_ELM_SIZE;\r\n    f->readBytes %= VIBUF_ELM_SIZE;\r\n\r\n    // ////////////////////////////////////////\r\n    //\r\n    // the last REFE -> REF\r\n    //\r\n    if (read_n > 0) {\r\n\tlast = (f->dmaStart + f->dmaN - 1 + f->n) % f->n;\r\n\tscTag2(\r\n\t    (QWORD*)(f->tag + last),\r\n\t    (char*)f->data + VIBUF_ELM_SIZE * last, \r\n\t    DMA_ID_REF,\r\n\t    VIBUF_ELM_SIZE/16\r\n\t);\r\n\tisNewData = 1;\r\n    }\r\n\r\n    index = read_start;\r\n    for (i = 0; i < read_n; i++) {\r\n    \tid = (i == read_n - 1)? DMA_ID_REFE: DMA_ID_REF;\r\n\tscTag2(\r\n\t    (QWORD*)(f->tag + index),\r\n\t    (char*)f->data + VIBUF_ELM_SIZE * index, \r\n\t    id,\r\n\t    VIBUF_ELM_SIZE/16\r\n\t);\r\n\tindex = (index + 1) % f->n;\r\n    }\r\n\r\n    f->dmaN += read_n;\r\n\r\n    // ////////////////////////////////////////\r\n    //\r\n    // RESTART DMA ch4\r\n    //\r\n    if (f->dmaN) {\r\n\tif (isNewData) {\r\n\t    // change ref/refe ----> ref\r\n\t    d4chcr = (d4chcr & 0x0fffffff) | (DMA_ID_REF << 28);\r\n\t}\r\n\tsetD4_CHCR(d4chcr | 0x100);\r\n    }\r\n\r\n    SIGNALSEMA(f->sema);\r\n\r\n    return TRUE;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Stop DMA and save DMA environment\r\n//\r\nint viBufStopDMA(ViBuf *f)\r\n{\r\n    WAITSEMA(f->sema);\r\n\r\n    f->isActive = FALSE;\r\n\r\n    setD4_CHCR((0<<8) | (1<<2) | 1);\t\t// STR: 0, DIR: 1\r\n\r\n    f->env.d4madr = *D4_MADR;\r\n    f->env.d4tadr = *D4_TADR;\r\n    f->env.d4qwc =  *D4_QWC;\r\n    f->env.d4chcr = *D4_CHCR;\r\n\r\n    // wait till ofc becomes 0\r\n    while (DGET_IPU_CTRL() & 0xf0)\r\n\t;\r\n\r\n    // DMA ch3\r\n    setD3_CHCR((0<<8) | 0);\t\t// STR: 0, DIR: 0\r\n    f->env.d3madr = *D3_MADR;\r\n    f->env.d3qwc =  *D3_QWC;\r\n    f->env.d3chcr = *D3_CHCR;\r\n\r\n    f->env.ipubp = DGET_IPU_BP();\r\n    f->env.ipuctrl = DGET_IPU_CTRL();\r\n\r\n    SIGNALSEMA(f->sema);\r\n\r\n    return TRUE;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Restore DMA environment and restart DMA\r\n//\r\nint viBufRestartDMA(ViBuf *f)\r\n{\r\n    int bp = f->env.ipubp & 0x7f;\r\n    int fp = (f->env.ipubp >> 16) & 0x3;\r\n    int ifc = (f->env.ipubp >> 8) & 0xf;\r\n    u_int d4madr_next = f->env.d4madr - ((fp + ifc) << 4);\r\n    u_int d4qwc_next = f->env.d4qwc + (fp + ifc);\r\n    u_int d4tadr_next = f->env.d4tadr;\r\n    u_int d4chcr_next = f->env.d4chcr | 0x100;\r\n    int index;\r\n    int index_next;\r\n    int id;\r\n\r\n    WAITSEMA(f->sema);\r\n\r\n    //\r\n    // check wrap around\r\n    //\r\n    if (d4madr_next < (u_int)f->data) {\r\n\td4qwc_next = (DATA_ADDR(0) - d4madr_next) >> 4;\r\n    \td4madr_next += (u_int)(f->n * VIBUF_ELM_SIZE);\r\n\td4tadr_next = TAG_ADDR(0);\r\n\tid = (f->env.d4madr == DATA_ADDR(0)\r\n\t\t|| f->env.d4madr == DATA_ADDR(f->n))?\r\n\t    DMA_ID_REFE:\r\n\t    DMA_ID_REF;\r\n\td4chcr_next = (f->env.d4chcr & 0x0fffffff)\r\n\t\t\t\t| (id << 28) | 0x100;\r\n\r\n\tif (!IsInRegion(0, f->dmaStart, f->dmaN, f->n)) {\r\n\t    f->dmaStart = f->n - 1;\r\n\t    f->dmaN++;\r\n\t}\r\n    } else if ((index = getFIFOindex(f, (void*)f->env.d4madr))\r\n    \t\t!= (index_next = getFIFOindex(f, (void*)d4madr_next))) {\r\n\td4tadr_next = TAG_ADDR(index);\r\n\td4qwc_next = (DATA_ADDR(index) - d4madr_next) >> 4;\r\n\tid = (WRAP_ADDR(f->env.d4madr)\r\n\t\t== DATA_ADDR((f->dmaStart + f->dmaN) % f->n))?\r\n\t    DMA_ID_REFE:\r\n\t    DMA_ID_REF;\r\n\td4chcr_next = (f->env.d4chcr & 0x0fffffff)\r\n\t\t\t\t| (id << 28) | 0x100;\r\n\r\n\tif (!IsInRegion(index_next, f->dmaStart, f->dmaN, f->n)) {\r\n\t    f->dmaStart = index_next;\r\n\t    f->dmaN++;\r\n\t}\r\n    }\r\n\r\n    // Restart DMA ch3\r\n    if (f->env.d3madr && f->env.d3qwc) {\r\n\t*D3_MADR = f->env.d3madr;\r\n\t*D3_QWC  = f->env.d3qwc;\r\n\tsetD3_CHCR(f->env.d3chcr | 0x100);\r\n    }\r\n\r\n    if (f->dmaN) {\r\n\twhile (sceIpuIsBusy())\r\n\t    ;\r\n\t// BCLR\r\n\tsceIpuBCLR(bp);\r\n\twhile (sceIpuIsBusy())\r\n\t    ;\r\n    }\r\n\r\n    // Restart DMA ch4\r\n    *D4_MADR = d4madr_next;\r\n    *D4_TADR = d4tadr_next;\r\n    *D4_QWC  = d4qwc_next;\r\n    if (f->dmaN) {\r\n\tsetD4_CHCR(d4chcr_next);\r\n    }\r\n\r\n    *IPU_CTRL = f->env.ipuctrl;\r\n\r\n    f->isActive = TRUE;\r\n\r\n    SIGNALSEMA(f->sema);\r\n\r\n    return TRUE;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Delete video input buffer\r\n//\r\nint viBufDelete(ViBuf *f)\r\n{\r\n    setD4_CHCR((0<<8) | (1<<2) | 1);\t// STR: 0, chain, DIR: 1\r\n    *D4_QWC = 0;\r\n    *D4_MADR = 0;\r\n    *D4_TADR = 0;\r\n\r\n    DeleteSema(f->sema);\r\n    return TRUE;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Check to see if decoder is in CSC period or not (0: CSC period)\r\n//\r\nint viBufIsActive(ViBuf *f)\r\n{\r\n    int ret;\r\n\r\n    WAITSEMA(f->sema);\r\n\r\n    ret = f->isActive;\r\n\r\n    SIGNALSEMA(f->sema);\r\n\r\n    return ret;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Data size in video input buffer\r\n//\r\nint viBufCount(ViBuf *f)\r\n{\r\n    int ret;\r\n\r\n    WAITSEMA(f->sema);\r\n\r\n    ret = f->dmaN * VIBUF_ELM_SIZE + f->readBytes;\r\n\r\n    SIGNALSEMA(f->sema);\r\n\r\n    return ret;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Flush video input buffer\r\n//\r\nvoid viBufFlush(ViBuf *f)\r\n{\r\n    WAITSEMA(f->sema);\r\n\r\n    f->readBytes = bound(f->readBytes, VIBUF_ELM_SIZE);\r\n\r\n    SIGNALSEMA(f->sema);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Add new time stamp and remove old one from the buffer\r\n//\r\nint viBufModifyPts(ViBuf *f, TimeStamp *new_ts)\r\n{\r\n    TimeStamp *ts;\r\n    int rd = (f->wt_ts - f->count_ts + f->n_ts) % f->n_ts;\r\n    int datasize =  VIBUF_ELM_SIZE * f->n;\r\n    int loop = 1;\r\n\r\n    if (f->count_ts > 0) {\r\n\twhile (loop) {\r\n\t    ts = f->ts + rd;\r\n\r\n\t    if (ts->len == 0 || new_ts->len == 0) {\r\n\t\tbreak;\r\n\t    }\r\n\r\n\t    if (IsPtsInRegion(ts->pos, new_ts->pos, new_ts->len, datasize)) {\r\n\t\tint len = min(new_ts->pos + new_ts->len - ts->pos, ts->len);\r\n\r\n\t\tts->pos = (ts->pos + len) % datasize;\r\n\t\tts->len -= len;\r\n\r\n\t\tif (ts->len == 0) {\r\n\t\t    if (ts->pts >= 0) {\r\n/*\t\t\tErrMessage(\"pts is not used\");*/\r\n\t\t\tts->pts = TS_NONE;\r\n\t\t\tts->dts = TS_NONE;\r\n\t\t\tts->pos = 0;\r\n\t\t\tts->len = 0;\r\n\t\t    }\r\n\t\t    f->count_ts = max(f->count_ts - 1, 0);\r\n\t\t}\r\n\t    } else {\r\n\t\tloop = 0;\r\n\t    }\r\n\r\n\t    rd = (rd + 1) % f->n_ts;\r\n\t}\r\n    }\r\n\r\n    return 0;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Add new time stamp\r\n//\r\nint viBufPutTs(ViBuf *f, TimeStamp *ts)\r\n{\r\n    int ret = 0;\r\n\r\n    WAITSEMA(f->sema);\r\n\r\n    if (f->count_ts < f->n_ts) {\r\n\r\n\tviBufModifyPts(f, ts);\r\n\r\n\tif (ts->pts >= 0 || ts->dts >= 0) {\r\n\r\n\t    f->ts[f->wt_ts].pts = ts->pts;\r\n\t    f->ts[f->wt_ts].dts = ts->dts;\r\n\t    f->ts[f->wt_ts].pos = ts->pos;\r\n\t    f->ts[f->wt_ts].len = ts->len;\r\n\r\n\t    f->count_ts++;\r\n\t    f->wt_ts = (f->wt_ts + 1) % f->n_ts;\r\n\t}\r\n\tret = 1;\r\n    } \r\n\r\n    SIGNALSEMA(f->sema);\r\n\r\n    return ret;\r\n}\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Get time stamp\r\n//\r\nint viBufGetTs(ViBuf *f, TimeStamp *ts)\r\n{\r\n    u_int d4madr = *D4_MADR;\r\n    u_int ipubp = DGET_IPU_BP();\r\n    int bp = f->env.ipubp & 0x7f;\r\n    int fp = (ipubp >> 16) & 0x3;\r\n    int ifc = (ipubp >> 8) & 0xf;\r\n    u_int d4madr_next = d4madr - ((fp + ifc) << 4);\r\n    u_int stop;\r\n    int datasize =  VIBUF_ELM_SIZE * f->n;\r\n    int isEnd = 0;\r\n    int tscount;\r\n    int wt;\r\n    int i;\r\n\r\n    WAITSEMA(f->sema);\r\n\r\n    ts->pts = TS_NONE;\r\n    ts->dts = TS_NONE;\r\n\r\n    stop = (d4madr_next + (bp >> 3) + datasize - (u_int)f->data)\r\n    \t\t\t\t\t\t\t% datasize;\r\n\r\n    tscount = f->count_ts;\r\n    wt = f->wt_ts;\r\n\r\n    for (i = 0; i < tscount && !isEnd; i++) {\r\n\r\n\tint rd = (wt - tscount + f->n_ts + i) % f->n_ts;\r\n\r\n\tif (IsPtsInRegion(stop,\r\n\t\tf->ts[rd].pos, f->ts[rd].len, datasize)) {\r\n\r\n\t    ts->pts = f->ts[rd].pts;\r\n\t    ts->dts = f->ts[rd].dts;\r\n\t    f->ts[rd].pts = TS_NONE;\r\n\t    f->ts[rd].dts = TS_NONE;\r\n\r\n\t    isEnd = 1;\r\n\t    f->count_ts -= min(1, f->count_ts);\r\n\t}\r\n    }\r\n\r\n    SIGNALSEMA(f->sema);\r\n\r\n    return 1;\r\n}\r\n\r\n} // namespace Flx\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/vibuf.h",
    "content": "#ifndef _VIBUF_H_\r\n#define _VIBUF_H_\r\n\r\n#include <eekernel.h>\r\n#include <libipu.h>\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/macros.h>\r\n#include <core/singleton.h>\r\n\r\n#define VIBUF_ELM_SIZE 2048\r\n#include \"gel/movies/ngps/vibuf.h\"\r\n#define VIBUF_SIZE 256\r\n#define VIBUF_TS_SIZE (VIBUF_SIZE*2)\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Time stamp\r\n//\r\nstruct TimeStamp{\r\n    long pts;\r\n    long dts;\r\n    int pos;\r\n    int len;\r\n};\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Video input buffer\r\n//\r\nstruct ViBuf{\r\n    u_long128 *data;\t// data array\r\n    u_long128 *tag;\t// tag array\r\n    int n;\t\t// the number of data/tag element in ViBuf\r\n    int dmaStart;\t// DMA area start position\r\n    int dmaN;\t\t// DMA area size\r\n    int readBytes;\t// read area size\r\n    int buffSize;\t// buffer size of ViBuf(bytes)\r\n    sceIpuDmaEnv env;\t// DMA environment\r\n    int sema;\t\t// semaphore\r\n    int isActive;\t// flag to check CSC period\r\n    long totalBytes;\t// total bytes of data which sent to ViBuf\r\n\r\n    // Time Stamp\r\n    TimeStamp *ts;\t// time stamp array\r\n    int n_ts;\t\t// time stamp array size\r\n    int count_ts;\t// the number of time stamps in the array\r\n    int wt_ts;\t\t// write position of time stamp array\r\n\r\n};\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Functions\r\n//\r\nint viBufCreate(ViBuf *f,\r\n    u_long128 *data, u_long128 *tag, int size,\r\n    TimeStamp *ts, int n_ts);\r\nint viBufReset(ViBuf *f);\r\nint viBufAddDMA(ViBuf *f);\r\nint viBufDelete(ViBuf *f);\r\nint viBufStopDMA(ViBuf *f);\r\nint viBufRestartDMA(ViBuf *f);\r\nvoid viBufPrint(ViBuf *f);\r\nint viBufIsActive(ViBuf *f);\r\nvoid viBufBeginPut(ViBuf *f,\r\n\tu_char **ptr0, int *len0, u_char **ptr1, int *len1);\r\nvoid viBufEndPut(ViBuf *f, int size);\r\nint viBufPutTs(ViBuf *f, TimeStamp *ts);\r\nint viBufGetTs(ViBuf *f, TimeStamp *ts);\r\nint viBufCount(ViBuf *f);\r\nvoid viBufFlush(ViBuf *f);\r\n\r\n} // namespace Flx\r\n\r\n#endif // _VIBUF_H_\r\n\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/videodec.cpp",
    "content": "#include <stdio.h>\r\n#include <eetypes.h>\r\n#include \"gel/movies/ngps/p_movies.h\"\r\n#include \"gel/movies/ngps/defs.h\"\r\n#include \"gel/movies/ngps/vobuf.h\"\r\n#include \"gel/movies/ngps/videodec.h\"\r\n#include \"gel/movies/ngps/disp.h\"\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\nvoid videoDecMain( void * dummy);\r\nint decBs0(VideoDec *vd);\r\nint mpegError(sceMpeg *mp, sceMpegCbDataError *cberror, void *anyData);\r\nint mpegNodata(sceMpeg *mp, sceMpegCbData *cbdata, void *anyData);\r\nint mpegStopDMA(sceMpeg *mp, sceMpegCbData *cbdata, void *anyData);\r\nint mpegRestartDMA(sceMpeg *mp, sceMpegCbData *cbdata, void *anyData);\r\nint mpegTS(sceMpeg *mp, sceMpegCbDataTimeStamp *cbts, void *anyData);\r\nstatic int cpy2area(u_char *pd0, int d0, u_char *pd1, int d1,\r\n    u_char *ps0, int s0, u_char *ps1, int s1);\r\n\r\nextern int vblankCount;\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Create video decoder\r\n//\r\nint videoDecCreate(VideoDec *vd,\r\n    u_char *mpegWork, int mpegWorkSize,\r\n    u_long128 *data, u_long128 *tag,\r\n    int tagSize, TimeStamp *pts, int n_pts)\r\n{\r\n    // Create sceMpeg\r\n    sceMpegCreate(&vd->mpeg, mpegWork, mpegWorkSize);\r\n\r\n    // Add Callbacks\r\n    sceMpegAddCallback(&vd->mpeg,\r\n    \tsceMpegCbError, (sceMpegCallback)mpegError, NULL);\r\n    sceMpegAddCallback(&vd->mpeg,\r\n    \tsceMpegCbNodata, mpegNodata, NULL);\r\n    sceMpegAddCallback(&vd->mpeg,\r\n    \tsceMpegCbStopDMA, mpegStopDMA, NULL);\r\n    sceMpegAddCallback(&vd->mpeg,\r\n    \tsceMpegCbRestartDMA, mpegRestartDMA, NULL);\r\n    sceMpegAddCallback(&vd->mpeg, sceMpegCbTimeStamp,\r\n    \t(sceMpegCallback)mpegTS, NULL);\r\n\r\n    videoDecReset(vd);\r\n\r\n    // Create input video buffer\r\n    viBufCreate(&vd->vibuf, data, tag, tagSize, pts, n_pts);\r\n\r\n    return 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Set decode mode\r\n//\r\nvoid videoDecSetDecodeMode(VideoDec *vd, int ni, int np, int nb)\r\n{\r\n    sceMpegSetDecodeMode(&vd->mpeg, ni, np, nb);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Choose stream to be decoded\r\n//\r\nint videoDecSetStream(VideoDec *vd, int strType, int ch,\r\n\tsceMpegCallback cb, void *data)\r\n{\r\n    sceMpegAddStrCallback(&vd->mpeg, ( sceMpegStrType )strType, ch, cb, data);\r\n    return 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Get areas to put data in video input buffer\r\n//\r\nvoid videoDecBeginPut(VideoDec *vd,\r\n\tu_char **ptr0, int *len0, u_char **ptr1, int *len1)\r\n{\r\n    viBufBeginPut(&vd->vibuf, ptr0, len0, ptr1, len1);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Proceed pointers of video input buffer\r\n//\r\nvoid videoDecEndPut(VideoDec *vd, int size)\r\n{\r\n    viBufEndPut(&vd->vibuf, size);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Reset video decoder\r\n//\r\nvoid videoDecReset(VideoDec *vd)\r\n{\r\n    vd->state = VD_STATE_NORMAL;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Delete video decoder\r\n//\r\nint videoDecDelete(VideoDec *vd)\r\n{\r\n    viBufDelete(&vd->vibuf);\r\n    sceMpegDelete(&vd->mpeg);\r\n\r\n    return 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Abort decoding\r\n//\r\nvoid videoDecAbort(VideoDec *vd)\r\n{\r\n    vd->state = VD_STATE_ABORT;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Get state of video decoder\r\n//\r\nu_int videoDecGetState(VideoDec *vd)\r\n{\r\n    return vd->state;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Set state of video decoder\r\n//\r\nu_int videoDecSetState(VideoDec *vd, u_int state)\r\n{\r\n    u_int old = vd->state;\r\n\r\n    vd->state = state;\r\n\r\n    return old;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Put time stamp to the video decoder\r\n//\r\nint videoDecPutTs(VideoDec *vd, long pts_val,\r\n    long dts_val, u_char *start, int len)\r\n{\r\n    TimeStamp ts;\r\n\r\n    // Set PTS\r\n    ts.pts = pts_val;\r\n    ts.dts = dts_val;\r\n    ts.pos = start - (u_char*)vd->vibuf.data;\r\n    ts.len = len;\r\n    return viBufPutTs(& MOVIE_MEM_PTR videoDec.vibuf, &ts);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Data size in video input buffer\r\n//\r\nint videoDecInputCount(VideoDec *vd)\r\n{\r\n    return viBufCount(&vd->vibuf);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Empty space size in video input buffer\r\n//\r\nint videoDecInputSpaceCount(VideoDec *vd)\r\n{\r\n    u_char *ptr0;\r\n    u_char *ptr1;\r\n    int len0, len1;\r\n\r\n    videoDecBeginPut(vd, &ptr0, &len0, &ptr1, &len1);\r\n\r\n    return len0 + len1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Flush video decoder\r\n//\r\nint videoDecFlush(VideoDec *vd)\r\n{\r\n    u_char *pd0;\r\n    u_char *pd1;\r\n    u_char *pd0Unc;\r\n    u_char *pd1Unc;\r\n    u_char seq_end_code[4] = {0x00, 0x00, 0x01, 0xb7};\r\n    int d0, d1;\r\n    int len;\r\n\r\n    videoDecBeginPut(vd, &pd0, &d0, &pd1, &d1);\r\n\r\n    if (d0 + d1 < 4) {\r\n    \treturn 0;\r\n    }\r\n\r\n    pd0Unc = (u_char*)UncAddr(pd0);\r\n    pd1Unc = (u_char*)UncAddr(pd1);\r\n\r\n    len = cpy2area(pd0Unc, d0, pd1Unc, d1, seq_end_code, 4, NULL, 0);\r\n\r\n    videoDecEndPut(& MOVIE_MEM_PTR videoDec, len);\r\n\r\n    viBufFlush(&vd->vibuf);\r\n\r\n    if (vd->state == VD_STATE_NORMAL) {\r\n\tvd->state = VD_STATE_FLUSH;\r\n    }\r\n\r\n    return 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Check to see if input buffer and reference image buffer are\r\n//  flushed\r\n//\r\nint videoDecIsFlushed(VideoDec *vd)\r\n{\r\n    return (videoDecInputCount(vd) == 0)\r\n    \t&& sceMpegIsRefBuffEmpty(&vd->mpeg);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Main function of decode thread\r\n//\r\nvoid videoDecMain( void * dummy)\r\n{\r\n\t\r\n\t\r\n\tCHECK_MOVIE_MEM;\r\n\t\r\n//\tDbg_MsgAssert( ( & MOVIE_MEM_PTR videoDec ) == vd, ( \"What the fuck assface?\" ) );\r\n    viBufReset(& MOVIE_MEM_PTR videoDec.vibuf);\r\n//    viBufReset(&vd->vibuf);\r\n\r\n    voBufReset(& MOVIE_MEM_PTR voBuf);\r\n\r\n    decBs0(& MOVIE_MEM_PTR videoDec);\r\n\r\n    while ( MOVIE_MEM_PTR voBuf.count)\r\n    \t;\r\n\r\n     videoDecSetState( & MOVIE_MEM_PTR videoDec, VD_STATE_END);\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Decode bitstream using MPEG decoder\r\n//\r\n// return value\r\n//     1: normal end\r\n//     -1: aborted\r\nint decBs0(VideoDec *vd)\r\n{\r\n\t\r\n    \r\n\tCHECK_MOVIE_MEM;\r\n\t\r\n\tVoData *voData;\r\n    sceIpuRGB32 *rgb32;\r\n    int ret;\r\n    int status = 1;\r\n    sceMpeg *mp = &vd->mpeg;\r\n\r\n    // ////////////////////////////\r\n    // \r\n    //  Main loop to decode MPEG bitstream\r\n    // \r\n    while (!sceMpegIsEnd(&vd->mpeg)) {\r\n\r\n\tif (videoDecGetState(vd) == VD_STATE_ABORT) {\r\n\t    status = -1;\r\n\t    printf(\"decode thread: aborted\\n\");\r\n\t    break;\r\n\t}\r\n\r\n\t// ////////////////////////////////////////////////\r\n\t// \r\n\t//  Get next available ouput buffer from voBuf\r\n\t//  switch to another thread if voBuf is full\r\n\t//\r\n\twhile (!(voData = voBufGetData(& MOVIE_MEM_PTR voBuf))) {\r\n\t    switchThread();\r\n\t}\r\n\trgb32 = (sceIpuRGB32*)voData->v;\r\n\r\n\t// ////////////////////////////////////////////////\r\n\t// \r\n\t//  Get decoded picture in sceIpuRGB32 format\r\n\t//\r\n        ret = sceMpegGetPicture(mp, rgb32, MAX_WIDTH/16 * MAX_HEIGHT/16);\r\n\r\n        if (ret < 0) {\r\n\t    ErrMessage(\"sceMpegGetPicture() decode error\");\r\n\t}\r\n\r\n\tif (mp->frameCount == 0) {\r\n\t    int i;\r\n\t    int image_w, image_h;\r\n\r\n\t    image_w = mp->width;\r\n\t    image_h = mp->height;\r\n\r\n\t    for (i = 0; i <  MOVIE_MEM_PTR voBuf.size; i++) {\r\n\r\n\t      // packet with texture data\r\n\t      setImageTag( MOVIE_MEM_PTR voBuf.tag[i].v[0],  MOVIE_MEM_PTR voBuf.data[i].v,\r\n\t\t\t  0, image_w, image_h);\r\n\t      \r\n\t      // packet without texture data\r\n\t      setImageTag( MOVIE_MEM_PTR voBuf.tag[i].v[1],  MOVIE_MEM_PTR voBuf.data[i].v,\r\n\t\t\t  1, image_w, image_h);\r\n\t    }\r\n\t}\r\n\r\n\t// ////////////////////////////\r\n\t// \r\n\t//  Increment video output buffer count\r\n\t// \r\n\tvoBufIncCount(& MOVIE_MEM_PTR voBuf);\r\n\r\n\tswitchThread();\r\n    }\r\n\r\n    sceMpegReset(mp);\r\n\r\n    return status;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Callback function for sceMpegCbError\r\n//\r\nint mpegError(sceMpeg *mp, sceMpegCbDataError *cberror, void *anyData)\r\n{\r\n    printf(\"%s\\n\", cberror->errMessage);\r\n    return 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Callback function for sceMpegCbNodata\r\n//\r\nint mpegNodata(sceMpeg *mp, sceMpegCbData *cbdata, void *anyData)\r\n{\r\n    switchThread();\r\n    viBufAddDMA(& MOVIE_MEM_PTR videoDec.vibuf);\r\n    return 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Callback function for sceMpegCbStopDMA\r\n//\r\nint mpegStopDMA(sceMpeg *mp, sceMpegCbData *cbdata, void *anyData)\r\n{\r\n    // Stop DMA\r\n    viBufStopDMA(& MOVIE_MEM_PTR videoDec.vibuf);\r\n    return 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Callback function for sceMpegCbRestartDMA\r\n//\r\nint mpegRestartDMA(sceMpeg *mp, sceMpegCbData *cbdata, void *anyData)\r\n{\r\n    // Restart DMA\r\n    viBufRestartDMA(& MOVIE_MEM_PTR videoDec.vibuf);\r\n    return 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Callback function for sceMpegCbTimeStamp\r\n//\tretruns PTS and DTS\r\n//\r\nint mpegTS(sceMpeg *mp, sceMpegCbDataTimeStamp *cbts, void *anyData)\r\n{\r\n    TimeStamp ts;\r\n\r\n    viBufGetTs(& MOVIE_MEM_PTR videoDec.vibuf, &ts);\r\n    cbts->pts = ts.pts;\r\n    cbts->dts = ts.dts;\r\n    return 1;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  copy 2 areas\r\n//\r\nstatic int cpy2area(u_char *pd0, int d0, u_char *pd1, int d1,\r\n    u_char *ps0, int s0, u_char *ps1, int s1)\r\n{\r\n    if (d0 + d1 < s0 + s1) {\r\n        return 0;\r\n    }\r\n\r\n    if (s0 >= d0) {\r\n    \tmemcpy(pd0,\t\tps0,\t\td0);\r\n    \tmemcpy(pd1,\t\tps0 + d0,\ts0 - d0);\r\n    \tmemcpy(pd1 + s0 - d0,\tps1,\t\ts1);\r\n    } else { // s0 < d0\r\n    \tif (s1 >= d0 - s0) {\r\n\t    memcpy(pd0,\t\tps0,\t\ts0);\r\n\t    memcpy(pd0 + s0,\tps1,\t\td0 - s0);\r\n\t    memcpy(pd1,\t\tps1 + d0 - s0,\ts1 - (d0 - s0));\r\n\t} else { // s1 < d0 - s0\r\n\t    memcpy(pd0,\t\tps0,\t\ts0);\r\n\t    memcpy(pd0 + s0,\tps1,\t\ts1);\r\n\t}\r\n    }\r\n    return s0 + s1;\r\n}\r\n\r\n\r\n} // namespace Flx\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/videodec.h",
    "content": "#ifndef _VIDEODEC_H_\r\n#define _VIDEODEC_H_\r\n\r\n#include <libmpeg.h>\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/macros.h>\r\n#include <core/singleton.h>\r\n\r\n#include \"gel/movies/ngps/vibuf.h\"\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Video decoder state\r\n//\r\n#define VD_STATE_NORMAL    0\r\n#define VD_STATE_ABORT     1\r\n#define VD_STATE_FLUSH     2\r\n#define VD_STATE_END       3\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Video Decoder\r\n//\r\nstruct VideoDec{\r\n    sceMpeg mpeg;\t// MPEG decoder\r\n    ViBuf vibuf;\t// video input buffer\r\n    u_int state;\t// video decoder state\r\n    int sema;\t\t// semaphore\r\n\r\n    int hid_endimage;\t// handler to check the end of image transfer\r\n    int hid_vblank;\t// vlbank handler\r\n\r\n};\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Functions\r\n//\r\nvoid videoDecReset(VideoDec *vd);\r\nint videoDecCreate(VideoDec *vd,\r\n    u_char *mpegWork, int mpegWorkSize,\r\n    u_long128 *data, u_long128 *tag,\r\n    int tagSize, TimeStamp *pts, int n_pts);\r\nint videoDecDelete(VideoDec *vd);\r\nvoid videoDecAbort(VideoDec *vd);\r\nu_int videoDecGetState(VideoDec *vd);\r\nu_int videoDecSetState(VideoDec *vd, u_int state);\r\nint videoDecInputCount(VideoDec *vd);\r\nint videoDecInputSpaceCount(VideoDec *vd);\r\nvoid videoDecSetDecodeMode(VideoDec *vd, int ni, int np, int nb);\r\nint videoDecFlush(VideoDec *vd);\r\nint videoDecIsFlushed(VideoDec *vd);\r\nint videoDecSetStream(VideoDec *vd, int strType, int ch,\r\n\tsceMpegCallback h, void *data);\r\nvoid videoDecBeginPut(VideoDec *vd,\r\n\tu_char **ptr0, int *len0, u_char **ptr1, int *len1);\r\nvoid videoDecEndPut(VideoDec *vd, int size);\r\nint videoDecPutTs(VideoDec *vd, long pts_val,\r\n    long dts_val, u_char *start, int len);\r\n\r\n} // namespace Flx\r\n\r\n#endif // _VIDEODEC_H_\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/vobuf.cpp",
    "content": "#include <eekernel.h>\r\n#include \"gel/movies/ngps/defs.h\"\r\n#include \"gel/movies/ngps/vobuf.h\"\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Functions called from decoding thread\r\n//\r\nvoid voBufCreate(\r\n    VoBuf *f,\r\n    VoData *data,\r\n    VoTag *tag,\r\n    int size\r\n)\r\n{\r\n    int i;\r\n\r\n    f->data = data;\r\n    f->tag = tag;\r\n    f->size = size;\r\n    f->count = 0;\r\n    f->write = 0;\r\n\r\n    for (i = 0; i < size; i++) {\r\n        f->tag[i].status = VOBUF_STATUS_;\r\n    }\r\n}\r\n\r\nvoid voBufDelete(VoBuf *f)\r\n{\r\n}\r\n\r\nvoid voBufReset(VoBuf *f)\r\n{\r\n    f->count = 0;\r\n    f->write = 0;\r\n}\r\n\r\nint voBufIsFull(VoBuf *f)\r\n{\r\n    return f->count == f->size;\r\n}\r\n\r\nvoid voBufIncCount(VoBuf *f)\r\n{\r\n    // disable interrupt\r\n    DI();\r\n\r\n    f->tag[f->write].status = VOBUF_STATUS_FULL;\r\n    f->count++;\r\n    f->write = (f->write + 1) % f->size;\r\n\r\n    // enable interrupt\r\n    EI();\r\n}\r\n\r\nVoData *voBufGetData(VoBuf *f)\r\n{\r\n    return voBufIsFull(f)? (VoData*)NULL: f->data + f->write;\r\n}\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Functions called from interrupt handler\r\n//\r\nint voBufIsEmpty(VoBuf *f)\r\n{\r\n    return f->count == 0;\r\n}\r\n\r\nVoTag *voBufGetTag(VoBuf *f)\r\n{\r\n    return voBufIsEmpty(f)? (VoTag*)NULL:\r\n    \tf->tag + ((f->write - f->count + f->size) % f->size);\r\n}\r\n\r\nvoid voBufDecCount(VoBuf *f)\r\n{\r\n    if (f->count > 0) {\r\n\tf->count--;\r\n    }\r\n}\r\n\r\n} // namespace Flx\r\n"
  },
  {
    "path": "Code/Gel/Movies/Ngps/vobuf.h",
    "content": "#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/macros.h>\r\n#include <core/singleton.h>\r\n\r\n#ifndef _VOBUF_H_\r\n#define _VOBUF_H_\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Definitions\r\n//\r\n#define N_VOBUF 2\r\n\r\n#define VOBUF_STATUS_    0\r\n#define VOBUF_STATUS_TOPDONE  1\r\n#define VOBUF_STATUS_FULL     2\r\n\r\n#define MAX_MBX\t\t(MAX_WIDTH/16)\r\n#define MAX_MBY\t\t(MAX_HEIGHT/16)\r\n\r\nnamespace Flx\r\n{\r\n\r\n\r\n\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Element data for video output buffer\r\n//\r\nstruct VoData{\r\n    u_char v[MAX_WIDTH * MAX_HEIGHT * 4];\r\n};\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Tag for video output buffer\r\n//\r\nstruct VoTag{\r\n    int status;\t\t// status\r\n    int dummy[15];\t// this is to adjust D$ line\r\n    u_int v[N_VOBUF][bound((N_LDTAGS+100)*4, 64)];\r\n};\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n//  Video output buffer\r\n//\r\nstruct VoBuf{\r\n    VoData *data;\t    // data array\r\n    VoTag *tag;\t\t    // tag array for path3 transfer\r\n    volatile int write;\t    // write position\r\n    volatile int count;\t    // the number of images in VoBuf\r\n    int size;\t\t    // total number of elements in VoBuf\r\n};\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Functions called from decoding thread\r\n//\r\nstruct _Display;\r\n\r\nvoid voBufCreate(\r\n    VoBuf *f,\r\n    VoData *data,\r\n    VoTag *tag,\r\n    int size\r\n);\r\nvoid voBufReset(VoBuf *f);\r\nint voBufSetTags(VoBuf *f, struct _Display *d);\r\nint voBufIsFull(VoBuf *f);\r\nvoid voBufIncCount(VoBuf *f);\r\nVoData *voBufGetData(VoBuf *f);\r\nvoid voBufDelete(VoBuf *f);\r\n\r\n// ////////////////////////////////////////////////////////////////\r\n//\r\n// Functions called from interrupt handler\r\n//\r\nint voBufIsEmpty(VoBuf *f);\r\nVoTag *voBufGetTag(VoBuf *f);\r\nvoid voBufDecCount(VoBuf *f);\r\n\r\nextern VoBuf voBuf;\r\n\r\n} // namespace Flx\r\n\r\n#endif // _VOBUF_H_\r\n"
  },
  {
    "path": "Code/Gel/Movies/Xbox/p_movies.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSK3\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGame Engine (GEL)\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_movies.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t07/24/01\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXbox specific .bik Bink movie streaming code\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n#include <core/defines.h>\r\n#include <core/macros.h>\r\n#include <core/singleton.h>\r\n#include <gfx/gfxman.h>\r\n#include <gfx/xbox/nx/render.h>\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/music/music.h>\r\n#include <gel/movies/movies.h>\r\n#include <gel/movies/xbox/p_movies.h>\r\n#include <sys/sioman.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\nextern DWORD PixelShader4;\r\n\r\nnamespace Flx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntypedef struct\r\n{\r\n\tfloat\tsx,sy,sz;\r\n\tfloat\trhw;\r\n\tuint32\tcolor;\r\n\tfloat\ttu,tv;\r\n}\r\nMOVIE_VERT;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool\talphaPixels\t\t\t\t\t= false;\r\nuint32\tcurrentPlaybackSurfaceType\t= BINKSURFACE32;\r\nfloat\tplaybackWidth\t\t\t\t= 640.0f;\r\nfloat\tplaybackHeight\t\t\t\t= 480.0f;\r\nfloat\ttextureWidth\t\t\t\t= 640.0f;\r\nfloat\ttextureHeight\t\t\t\t= 480.0f;\r\nfloat\tplaybackWidthScale\t\t\t= 1.0f;\r\nfloat\tplaybackHeightScale\t\t\t= 1.0f;\r\nHBINK\tplaybackBinkHandle\t\t\t= NULL;\r\n\r\nDWORD\tcullMode;\r\nDWORD\tmultisampleAntialias;\r\nDWORD\tminFilter;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nLPDIRECT3DTEXTURE8 openPlaybackImage( uint32 width, uint32 height )\r\n{\r\n\t// Need to this prevent the single poly being culled.\r\n\tD3DDevice_GetRenderState( D3DRS_CULLMODE,\t\t\t\t&cullMode );\r\n\tD3DDevice_SetRenderState( D3DRS_CULLMODE,\t\t\t\tD3DCULL_NONE );\r\n\r\n\tD3DDevice_GetRenderState( D3DRS_MULTISAMPLEANTIALIAS,\t&multisampleAntialias );\r\n\tD3DDevice_SetRenderState( D3DRS_MULTISAMPLEANTIALIAS,\tFALSE );\r\n\t\r\n\tD3DDevice_SetRenderState( D3DRS_LIGHTING,\t\t\t\tFALSE );\r\n\r\n\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t0 );\r\n\tNxXbox::set_render_state( RS_ZTESTENABLE,\t0 );\r\n\t\r\n\tD3DDevice_GetTextureStageState( 0, D3DTSS_MINFILTER,\t&minFilter );\r\n\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER,\tD3DTEXF_LINEAR );\r\n\r\n\ttextureWidth\t= (float)width;\r\n\ttextureHeight\t= (float)height;\r\n\t\r\n\t// Adjust for our current screen buffer.\r\n\tplaybackWidth\t= (float)NxXbox::EngineGlobals.backbuffer_width;\r\n\tplaybackHeight\t= (float)NxXbox::EngineGlobals.backbuffer_height;\r\n\t\r\n\t// Create a surface for our texture with the DirectDraw handle.\r\n\tLPDIRECT3DTEXTURE8 p_texture_surface;\r\n\tif( SUCCEEDED( D3DDevice_CreateTexture( width, height, 1, 0, D3DFMT_LIN_X8R8G8B8, 0, &p_texture_surface )))\r\n\t{\r\n\t\treturn p_texture_surface;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\nvoid closePlaybackImage( LPDIRECT3DTEXTURE8 p_image )\r\n{\r\n\t// Restore various states.\r\n\tD3DDevice_SetRenderState( D3DRS_CULLMODE,\t\t\t\tcullMode );\r\n\tD3DDevice_SetRenderState( D3DRS_MULTISAMPLEANTIALIAS,\tmultisampleAntialias );\r\n\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER,\tminFilter );\r\n\t\r\n\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t1 );\r\n\tNxXbox::set_render_state( RS_ZTESTENABLE,\t1 );\r\n\r\n\tif( p_image )\r\n\t{\r\n\t\tULONG refcount = p_image->Release();\r\n\t\tDbg_Assert( refcount == 0 );\r\n\t}\r\n\r\n\tNxXbox::set_texture( 0, NULL );\r\n}\r\n\r\n\r\n\r\n// Advance a Bink file by one frame into a 3D image buffer.\r\nstatic void decompressFrame( HBINK bink, LPDIRECT3DTEXTURE8 p_image, bool copy_all )\r\n{\r\n\t// Decompress the Bink frame.\r\n\tBinkDoFrame( bink );\r\n\r\n\t// Lock the 3D image so that we can copy the decompressed frame into it.\r\n\tD3DLOCKED_RECT lock_rect;\r\n\tif( SUCCEEDED( p_image->LockRect( 0, &lock_rect, 0, 0 )))\r\n\t{\r\n\t\tvoid*\tpixels\t\t= lock_rect.pBits;\r\n\t\tuint32\tpixel_pitch\t= lock_rect.Pitch;\r\n\r\n\t\t// Copy the decompressed frame into the 3D image.\r\n\t\tBinkCopyToBuffer(\tbink,\r\n\t\t\t\t\t\t\tpixels,\r\n\t\t\t\t\t\t\tpixel_pitch,\r\n\t\t\t\t\t\t\tbink->Height,\r\n\t\t\t\t\t\t\t0,\t\t\t\t\t// Left pixel offset.\r\n\t\t\t\t\t\t\t0,\t\t\t\t\t// Top pixel offset.\r\n\t\t\t\t\t\t\tcurrentPlaybackSurfaceType | (( copy_all ) ? BINKCOPYALL : 0 ));\r\n\r\n\t\t// Unlock the 3D image.\r\n\t\tp_image->UnlockRect( 0 );\r\n\t}\r\n}\r\n\r\n\r\n\r\n// Blit a 3D image onto the render target.\r\nvoid blitImage( LPDIRECT3DTEXTURE8 p_image, float x_offset, float y_offset, float x_scale, float y_scale, float alpha_level )\r\n{\r\n\tif( p_image == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tNxXbox::set_blend_mode( NxXbox::vBLEND_MODE_DIFFUSE );\r\n\t\r\n\t// Turn on clamping so that the linear textures work\r\n\tNxXbox::set_render_state( RS_UVADDRESSMODE0, 0x00010001UL );\r\n\t\r\n\t// Use a default vertex and pixel shader\r\n\tNxXbox::set_vertex_shader( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 );\r\n\tNxXbox::set_pixel_shader( PixelShader4 );\r\n\r\n\t// Select the texture.\r\n\tNxXbox::set_texture( 0, NULL );\r\n\tNxXbox::set_texture( 0, p_image );\r\n\r\n\t// Setup up the vertices.\r\n\tMOVIE_VERT vertices[4];\r\n\r\n\tvertices[0].sx\t\t= x_offset;\r\n\tvertices[0].sy\t\t= y_offset;\r\n\tvertices[0].sz\t\t= 0.0f;\r\n\tvertices[0].rhw\t\t= 0.0f;\r\n\tvertices[0].color\t= ((int)(( alpha_level * 255.0f )) << 24 ) | 0x808080;\r\n\tvertices[0].tu\t\t= -0.5f;\r\n\tvertices[0].tv\t\t= -0.5f;\r\n\r\n\tvertices[1]\t\t\t= vertices[ 0 ];\r\n\tvertices[1].sx\t\t= x_offset + (((float)playbackWidth ) * x_scale );\r\n\tvertices[1].tu\t\t= ((float)textureWidth ) - 0.5f;\r\n\r\n\tvertices[2]\t\t\t= vertices[0];\r\n\tvertices[2].sy\t\t= y_offset + (((float)playbackHeight ) * y_scale );\r\n\tvertices[2].tv\t\t= ((float)textureHeight ) - 0.5f;\r\n\r\n\tvertices[3]\t\t\t= vertices[1];\r\n\tvertices[3].sy\t\t= vertices[2].sy;\r\n\tvertices[3].tv\t\t= ((float)textureHeight ) - 0.5f;\r\n\r\n\t// Draw the vertices.\r\n\tD3DDevice_DrawVerticesUP( D3DPT_TRIANGLESTRIP, 4, vertices, sizeof( MOVIE_VERT ));\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\nstatic void showFrame( HBINK bink, LPDIRECT3DTEXTURE8 p_image )\r\n{\r\n\t// Begin a 3D frame.\r\n\tD3DDevice_Clear( 0, 0, D3DCLEAR_TARGET, 0, 1.0f, 0 );\r\n\r\n\t// Draw the image on the screen (centered)...\r\n\tfloat x = 0.0f;\r\n\tfloat y = 0.0f;\r\n\tblitImage( p_image, x, y, playbackWidthScale, playbackHeightScale, 1.0f );\r\n\r\n\t// End a 3D frame.\r\n\tD3DDevice_Swap( D3DSWAP_DEFAULT );\r\n\r\n\t// Keep playing the movie.\r\n\tBinkNextFrame( bink );\r\n}\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic bool sDebounceCheck(uint16 *p_debounceFlags, uint8 *p_data, uint16 mask)\r\n{\r\n\tif (p_data==NULL)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\tDbg_MsgAssert(p_debounceFlags,(\"NULL p_debounceFlags\"));\r\n\t\r\n\tuint16 data=(p_data[2]<<8)|p_data[3];\r\n\tif ((data & mask)==0)\r\n\t{\r\n\t\t// Button is pressed.\r\n\t\t\r\n\t\tif (*p_debounceFlags & mask)\r\n\t\t{\r\n\t\t\t// OK to return true, because the button got released at some point in the past.\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Button is not pressed, so set the appropriate debounce flag so that next time it is\r\n\t\t// pressed it will be detected.\r\n\t\t*p_debounceFlags |= mask;\r\n\t}\r\n\treturn false;\t\r\n}\r\n\r\nvoid PMovies_PlayMovie( const char* pName )\r\n{\r\n\t// Figure the volume we want to play at.\r\n\tSpt::SingletonPtr< Sfx::CSfxManager > sfx_manager;\r\n\tfloat music_vol\t= Pcm::GetVolume();\r\n\tfloat sfx_vol\t= sfx_manager->GetMainVolume( );\r\n\tfloat vol\t\t= music_vol > sfx_vol ? music_vol : sfx_vol;\r\n\r\n\t// Incoming movie name is in the form movies\\<name>, convert to d:\\data\\movies\\bik\\<name>.bik.\r\n\tchar name_conversion_buffer[256] = \"d:\\\\data\\\\movies\\\\bik\\\\\";\r\n\tint length\t\t= strlen( pName );\r\n\tint backwards\t= length;\r\n\twhile( backwards )\r\n\t{\r\n\t\tif( pName[backwards] == '\\\\' )\r\n\t\t{\r\n\t\t\t++backwards;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t--backwards;\r\n\t}\r\n\tstrncpy( name_conversion_buffer + 19, pName + backwards, length - backwards );\r\n\tlength = strlen( name_conversion_buffer );\r\n\tname_conversion_buffer[length] = '.';\r\n\tname_conversion_buffer[length + 1] = 'b';\r\n\tname_conversion_buffer[length + 2] = 'i';\r\n\tname_conversion_buffer[length + 3] = 'k';\r\n\tname_conversion_buffer[length + 4] = 0;\r\n\r\n\t// Stop music and streams.\r\n\tPcm::StopMusic();\r\n\tPcm::StopStreams();\r\n\t\r\n\tplaybackBinkHandle = BinkOpen( name_conversion_buffer, 0 );\r\n\tif( playbackBinkHandle == NULL )\r\n\t{\r\n\t\t// Movie not there, just quit.\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Switch the presentation interval to 30fps.\r\n\tDWORD presentation_interval;\r\n\tD3DDevice_GetRenderState( D3DRS_PRESENTATIONINTERVAL, &presentation_interval );\r\n\tD3DDevice_SetRenderState( D3DRS_PRESENTATIONINTERVAL, D3DPRESENT_INTERVAL_ONE );\r\n\t\r\n\t// Open a 3D image for the Bink.\r\n\tLPDIRECT3DTEXTURE8 p_image = openPlaybackImage( playbackBinkHandle->Width, playbackBinkHandle->Height );\r\n\tDbg_Assert( p_image );\r\n\r\n\t// K: Call XGetDeviceChanges once before going into the loop, otherwise the first time this function\r\n\t// is run it will think new cards and pads have been inserted.\r\n//\tbool running_demo_movie=Script::GetInt(\"RunningDemoMovie\");\r\n\tbool running_demo_movie=false;\r\n\tif (running_demo_movie)\r\n\t{\r\n\t\tDWORD insertions=0;\r\n\t\tDWORD removals=0;\r\n\t\tXGetDeviceChanges(XDEVICE_TYPE_MEMORY_UNIT, &insertions, &removals);\r\n\t\tXGetDeviceChanges(XDEVICE_TYPE_GAMEPAD, &insertions, &removals);\r\n\t}\t\t\t\t\r\n\t\r\n\tif( p_image )\r\n\t{\r\n\t\tBinkSetSoundOnOff( playbackBinkHandle, 1 );\r\n\r\n\t\t// For BinkSetVolume(), 32768 is the 'nornal volume', effectively full volume on systems that don't\r\n\t\t// do amplification, like Xbox.\r\n\t\tBinkSetVolume( playbackBinkHandle, 0, (int)( 16384 * ( vol * 0.01f )));\r\n\r\n\t\t// Will need this in the loop...\r\n\t\tSpt::SingletonPtr< SIO::Manager > sio_manager;\r\n\t\tuint16 debounce_flags[4] = { 0,0,0,0 };\r\n\r\n\t\t// Start the playback loop.\r\n\t\twhile( true )\r\n\t\t{\r\n\t\t\tif( !BinkWait( playbackBinkHandle ))\r\n\t\t\t{\r\n\t\t\t\tdecompressFrame( playbackBinkHandle, p_image, true );\r\n\t\t\t\tshowFrame( playbackBinkHandle, p_image );\r\n\r\n\t\t\t\tif( playbackBinkHandle->FrameNum >= ( playbackBinkHandle->Frames - 1 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Check for a button being pressed to skip out of movie playback.\r\n\t\t\t\tsio_manager->ProcessDevices();\r\n\r\n\t\t\t\t// If running a demo movie, then pad or mem card insertions must make it quit. (TRC requirement)\r\n\t\t\t\tif( running_demo_movie )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Use the XGetDeviceChanges function to determine if a card or pad has been inserted ...\r\n\t\t\t\t\tDWORD insertions=0;\r\n\t\t\t\t\tDWORD removals=0;\r\n\t\t\t\t\tif( XGetDeviceChanges( XDEVICE_TYPE_MEMORY_UNIT, &insertions, &removals ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( insertions )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tif( XGetDeviceChanges( XDEVICE_TYPE_GAMEPAD, &insertions, &removals ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( insertions )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\t\t\t\r\n\r\n\t\t\t\tbool quit = false;\r\n\t\t\t\tfor( int d = 0; d < 4; ++d )\r\n\t\t\t\t{\r\n\t\t\t\t\tSIO::Device* p_device = sio_manager->GetDeviceByIndex( d );\r\n\t\t\t\t\tif( p_device )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned char* p_data = p_device->GetControlData();\r\n\r\n\t\t\t\t\t\tif( sDebounceCheck( &debounce_flags[d], p_data, 0x0800 ) ||\t// Start\r\n\t\t\t\t\t\t\tsDebounceCheck( &debounce_flags[d], p_data, 0x0040 ))\t\t// A\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tquit = true;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// If running a demo movie, then these buttons must also make it quit. (TRC requirement)\r\n\t\t\t\t\t\tif( running_demo_movie )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif( sDebounceCheck(&debounce_flags[d], p_data, 0x0100) ||\t// Back\r\n\t\t\t\t\t\t\t\tsDebounceCheck(&debounce_flags[d], p_data, 0x0020) ||\t// B\r\n\t\t\t\t\t\t\t\tsDebounceCheck(&debounce_flags[d], p_data, 0x0080) ||\t// X\r\n\t\t\t\t\t\t\t\tsDebounceCheck(&debounce_flags[d], p_data, 0x0010) ||\t// Y\r\n\t\t\t\t\t\t\t\tsDebounceCheck(&debounce_flags[d], p_data, 0x0002) ||\t// Black\r\n\t\t\t\t\t\t\t\tsDebounceCheck(&debounce_flags[d], p_data, 0x0001) ||\t// White\r\n\t\t\t\t\t\t\t\tsDebounceCheck(&debounce_flags[d], p_data, 0x0200) ||\t// Thumbstick 1\r\n\t\t\t\t\t\t\t\tsDebounceCheck(&debounce_flags[d], p_data, 0x0400 ))\t// Thumbstick 2\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tquit = true;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t}\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif( quit )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tclosePlaybackImage( p_image );\r\n\tBinkClose( playbackBinkHandle );\r\n\tplaybackBinkHandle = NULL;\r\n\r\n\t// Switch the presentation interval bacl to what it was.\r\n\tD3DDevice_SetRenderState( D3DRS_PRESENTATIONINTERVAL, presentation_interval );\r\n}\r\n\r\n} // namespace Flx\r\n\r\n"
  },
  {
    "path": "Code/Gel/Movies/Xbox/p_movies.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tps2 movies\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/movies/ngps/p_movies.h \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t6/27/01\t-\tdc\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __P_MOVIES_H\r\n#define __P_MOVIES_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/list.h>\r\n#include <core/macros.h>\r\n\r\n#include <bink.h>\r\n\r\nnamespace Flx\r\n{\r\n\r\n\tvoid PMovies_PlayMovie( const char *pName );\r\n\r\n} // namespace Flx\r\n\r\n#endif\t// __P_MOVIES_H\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Movies/ngc/p_movies.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSK3\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGame Engine (GEL)\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_movies.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t08/27/01\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGamecube specific movie streaming code\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef DVDETH\r\n\r\n#undef __GX_H__\r\n#define _GX_H_\r\n\r\n#include <dolphin.h>\r\n#include <stdio.h>\r\n#include <string.h>\r\n#include <core/defines.h>\r\n#include <sys/ngc/p_display.h>\r\n#include <sys/ngc/p_prim.h>\r\n#include <dolphin\\dtk.h>\r\n#include <dolphin/mix.h>\r\n#include <dolphin.h>\r\n#include \"sys\\ngc\\p_aram.h\"\r\n#include <gel/mainloop.h>\r\n#include\t<sys/ngc\\p_dvd.h>\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/music/music.h>\r\n#include\t<sys/ngc\\p_render.h>\r\n#include\t<sys/ngc\\p_display.h>\r\n#include\t<sys/ngc\\p_hw.h>\r\n#include \"sys/ngc/p_prim.h\"\r\n#include \"gel\\music\\ngc\\p_music.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include <gfx\\ngc\\nx\\texture.h>\r\n#include <sys\\ngc\\p_gx.h>\r\n#include <gfx\\ngc\\nx\\render.h>\r\n#include <gel/Scripting/script.h>\r\n\r\n#include \"VIDSimpleDEMO.h\"\r\n#include \"VIDSimplePlayer.h\"\r\n#include \"VIDSimpleAudio.h\"\r\n#include \"VIDSimpleDraw.h\"\r\n\r\n#include <charpipeline/GQRSetup.h>\r\n#include <sys/sioman.h>\r\n\r\n#define MY_DEBUG\r\n\r\nextern PADStatus\t\tpadData[PAD_MAX_CONTROLLERS]; // game pad state\r\n\r\nextern GXColor messageColor;\r\n\r\n#undef ASSERT\r\n#define ASSERT(exp)                                             \\\r\n    (void) ((exp) ||                                            \\\r\n            (OSPanic(__FILE__, __LINE__, \"Failed assertion \" #exp), 0))\r\n\r\nextern GXRenderModeObj *rmode;\r\n\r\n//#define USE_DIRECT_XFB\r\n\r\n//! Base address for 'Locked Cache' simple memory manager\r\nstatic u8* \tlcMemBase = 0;\r\n\r\n//! Locked cache base address for XFB conversion stuff\r\n//! This is only required, if USE_DIRECT_XFB is set\r\nstatic void* xfbLCStart = 0;\t\t\r\n\r\n//#define\tVIDEO_FILENAME\t\t\"movies/peacemaker.vid\"\r\n//#define\tVIDEO_FILENAME\t\t\"movies/video3.vid\"\r\n//#define\tVIDEO_FILENAME\t\t\"movies/doomraiders.vid\"\r\n//#define\tVIDEO_FILENAME\t\t\"movies/pu.vid\"\r\n//#define\tVIDEO_FILENAME\t\t\"movies/nslogo.vid\"\r\n//#define\tVIDEO_FILENAME\t\t\"movies/out4.vid\"\r\n//#define\tVIDEO_FILENAME\t\t\"movies/hom.vid\"\r\n//#define\tVIDEO_FILENAME\t\t\"movies/out5.vid\"\r\n\r\nextern bool\tg_legal;\r\n\r\n/******************************************************************************\r\n *  GLOABL VARIABLES\r\n ******************************************************************************/\r\nextern void*   hwCurrentBuffer;         // current XFB frame buffer allocated in DEMO library \r\nVidSimplePlayer player;\r\n\r\n#ifndef MIN\r\n#define MIN(a,b) ((a) < (b) ? a : b)\r\n#endif\r\n\r\n/******************************************************************************\r\n *  LOCAL VARIABLES\r\n ******************************************************************************/\r\nstatic VidChunk workChunk ATTRIBUTE_ALIGN(32);\r\nstatic void dvdDoneCallback(s32 result, DVDFileInfo *videoInfo);\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tInitializes all player structures.\r\n *\r\n ******************************************************************************\r\n */\r\nvoid VIDSimpleInit(VIDAllocator _cbAlloc, VIDDeallocator _cbFree, VIDAllocator _cbLockedCache)\r\n\t{\r\n\tmemset(&player, 0, sizeof(player));\r\n\tplayer.cbAlloc = _cbAlloc;\r\n\tplayer.cbFree = _cbFree;\r\n\tplayer.cbLockedCache = _cbLockedCache;\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tRequest an async file transfer.\r\n *\r\n *\t\tThis function starts the transfer of the next frame into a free\r\n *\t\tbuffer.\r\n *\r\n ******************************************************************************\r\n */\r\nstatic void ReadFrameAsync(void)\r\n\t{\r\n\tif (!player.error && player.preFetchState == TRUE)\r\n\t\t{\r\n\t\tif (player.currentFrameCount >  player.videoInfo.maxFrameCount - 1)\r\n\t\t\t{\r\n\t\t\tif (player.loopMode)\r\n\t\t\t\t{\r\n\t\t\t\tplayer.currentFrameCount = 0;\r\n\t\t\t\tplayer.nextFrameOffset = player.firstFrameOffset;\r\n\t\t\t\tplayer.nextFrameSize  = player.firstFrameSize;\r\n\t\t\t\t}\r\n\t\t\telse\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\r\n\t\tplayer.asyncDvdRunning = TRUE;\r\n\r\n\t\tif (DVDReadAsync(&player.fileHandle,\r\n\t\t\t\t\t\t player.readBuffer[player.readIndex].ptr,\r\n\t\t\t\t\t\t (s32)player.nextFrameSize,\r\n\t\t\t\t\t\t (s32)player.nextFrameOffset, dvdDoneCallback) != TRUE )\r\n\t\t\t{\r\n\t\t\tplayer.asyncDvdRunning = FALSE;\r\n\t\t\tplayer.error = TRUE;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tDVD callback if async transfer is finished (or aborted)\r\n *\t\r\n *\t\tThe idea here is to transfer ONE frame and additional 32 bytes for the\r\n *\t\tHEADER of the NEXT frame in one transfer step. We store the size of\r\n *\t\tthe next frame, which is used in ReadFrameAsync().\r\n *\r\n *\t\t\r\n * \\note\r\n *\t\tThere a 32 padding bytes at the end of the .vid file. So, the reading\r\n *\t\tof 32 additional bytes is even possible for the LAST frame. (Otherwise,\r\n *\t\twe would 'point' out of the file)\r\n *\r\n *\t\tSee Dolphin documentation for information about parameters.\r\n *\r\n ******************************************************************************\r\n */\r\nstatic void dvdDoneCallback(s32 result, DVDFileInfo * _UNUSED(videoInfo))\r\n\t{\r\n\tif (result == DVD_RESULT_FATAL_ERROR)\r\n\t\t{\r\n\t\tplayer.error = TRUE;\r\n\t\treturn;\r\n\t\t}\r\n\telse if (result == DVD_RESULT_CANCELED)\r\n\t\t{\r\n\t\treturn;\r\n\t\t}\r\n\r\n\tplayer.asyncDvdRunning = FALSE;\r\n\r\n\tplayer.readBuffer[player.readIndex].frameNumber = player.currentFrameCount;\r\n\tplayer.readBuffer[player.readIndex].size = (u32)result;\t\r\n\tplayer.readBuffer[player.readIndex].valid = TRUE;\r\n\t\r\n\tplayer.currentFrameCount++;\r\n\r\n\t// move file pointer\r\n\tplayer.nextFrameOffset += player.nextFrameSize;\r\n\t\r\n\tif(player.currentFrameCount < player.videoInfo.maxFrameCount)\r\n\t\t{\r\n\t\t// set read size for next 'FRAM' chunk\r\n\t\tu32* nextFrameStart = (u32*)(player.readBuffer[player.readIndex].ptr + player.nextFrameSize - 32);\r\n\t\r\n\t\t// some check if file structure is okay\r\n\t\tASSERT(nextFrameStart[0] == VID_FCC('F','R','A','M'));\r\n\t\t\r\n\t\t// get the size of the next 'FRAM' chunk to read\r\n\t\tplayer.nextFrameSize = nextFrameStart[1];\r\n\t\tASSERT(player.nextFrameSize);\r\n\t\t}\r\n\telse\r\n\t\tplayer.nextFrameSize = 0;\t// at end of file we have a size of '0'. This should be reinitialized later\r\n\t\t\t\t\t\t\t\t\t// using the size of the first frame somwhere else! Otherwise, we get an assertion\r\n\r\n\t// use next buffer\r\n\tplayer.readIndex = (player.readIndex + 1) % VID_NUM_READ_BUFFERS;\r\n\r\n\t// continue loading if we have a free buffer\r\n\tif (!player.readBuffer[player.readIndex].valid)\r\n\t\tReadFrameAsync();\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tAllocate buffer memory for asynchronous dvd read\r\n *\r\n * \\param memAlloc\r\n *\t\tPointer to memory allocation function\r\n *\r\n * \\return\r\n *\t\tTRUE if DVD buffer setup was successful.\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL VIDSimpleAllocDVDBuffers(void)\r\n\t{\r\n\tu32 i;\r\n\tu32 bufferSize;\r\n\tu8* ptr;\r\n\r\n\tbufferSize = player.videoInfo.maxBufferSize;\r\n\tASSERT(bufferSize);\r\n\t\r\n\tbufferSize += VID_CHUNK_HEADER_SIZE;\t// 'fram' header\r\n\tbufferSize += VID_CHUNK_HEADER_SIZE;\t// 'vidd' header\r\n\tbufferSize = OSRoundUp32B(bufferSize);\r\n\t\r\n\tASSERT(player.cbAlloc);\r\n\tplayer.readBufferBaseMem = (u8*)((*player.cbAlloc)(bufferSize * VID_NUM_READ_BUFFERS));\r\n\t\r\n\tif(!player.readBufferBaseMem)\r\n\t\treturn FALSE;\t// out of mem\r\n\t\r\n\tptr = player.readBufferBaseMem;\r\n\tfor (i = 0; i < VID_NUM_READ_BUFFERS ; i++)\r\n\t\t{\r\n\t\tplayer.readBuffer[i].ptr = ptr;\r\n\t\tptr += bufferSize;\r\n\t\tplayer.readBuffer[i].valid = FALSE;\r\n\t\t}\r\n\t\r\n\treturn TRUE;\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tFree buffer memory used for dvd read\r\n *\r\n * \\param memFree\r\n *\t\tPointer to memory deallocation function\r\n *\r\n ******************************************************************************\r\n */\r\nvoid VIDSimpleFreeDVDBuffers(void)\r\n\t{\r\n\tASSERT(player.cbFree);\r\n\tASSERT(player.readBufferBaseMem);\r\n\t(*player.cbFree)(player.readBufferBaseMem);\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tCreate a new decoder instance.\r\n *\r\n *\t\tThe required parameters about the decoding process will be supplied\r\n *\t\tin the VIDDecoderSetup structure.\r\n *\r\n * \\param supportBFrames\r\n *\t\tSet to TRUE for enabling b-frame support.\r\n *\r\n * \\return\r\n *\t\tTRUE if decoder creation was successful\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL VIDSimpleCreateDecoder(BOOL supportBFrames)\r\n\t{\r\n\tVIDDecoderSetup\tsetup;\r\n\t\r\n\tsetup.size = sizeof(VIDDecoderSetup);\r\n\tsetup.width = player.videoInfo.width;\r\n\tsetup.height = player.videoInfo.height;\r\n\tsetup.flags = supportBFrames ? VID_DECODER_B_FRAMES : 0;\r\n\tsetup.cbMemAlloc = player.cbAlloc;\r\n\tsetup.cbMemFree = player.cbFree;\r\n\tsetup.cbMemAllocLockedCache = player.cbLockedCache;\r\n\r\n\t// Check if we want to setup audio decoding.\r\n\t// The audio header info must be already preset here!\r\n\tif(player.audioInfo.audioID == VID_FCC('V','A','U','D'))\r\n\t\t{\r\n\t\tu32 skip;\r\n\t\tASSERT(player.audioHeaderChunk);\r\n\t\tASSERT(player.audioInfo.vaud.maxHeap > 0);\r\n\t\tASSERT(player.audioInfo.vaud.preAlloc > 0);\r\n\t\t\r\n\t\tsetup.flags |= VID_DECODER_AUDIO;\r\n\r\n\t\tskip = VID_CHUNK_HEADER_SIZE + sizeof(u32) + (player.audioInfo.vaudex.version > 0 ? player.audioInfo.vaudex.size : sizeof(VidAUDHVAUD));\r\n\t\tsetup.audio.headerInfo = player.audioHeaderChunk + skip;\r\n        setup.audio.headerInfoBytes = ((VidChunk*)player.audioHeaderChunk)->len - skip;\r\n\t\tsetup.audio.maxHeap = player.audioInfo.vaud.maxHeap;\r\n\t\tsetup.audio.preAlloc = player.audioInfo.vaud.preAlloc;\r\n\t\t}\r\n\t\r\n\tplayer.decoder = VIDCreateDecoder(&setup);\r\n\r\n\t// check if decoder creation failed!\r\n\treturn player.decoder ? TRUE : FALSE;\r\n\t}/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tDestroy decoder instance.\r\n *\r\n *\t\tAt this point the decoder returns all allocated memory by using\r\n *\t\tthe cbFree callback.\r\n *\r\n ******************************************************************************\r\n */\r\nvoid VIDSimpleDestroyDecoder(void)\r\n\t{\r\n\tASSERT(player.decoder);\r\n\tVIDDestroyDecoder(player.decoder);\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tPreload the allocated buffers.\r\n *\r\n *\t\tThis functions fills all buffers with initial data\r\n *\r\n * \\param loopMode\r\n *\t\tTRUE if we want to operate in loop mode\r\n *\r\n * \\return\r\n *\t\tTRUE if preload was okay \t\t\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL VIDSimpleLoadStart(BOOL loopMode)\r\n\t{\r\n\tu8* ptr;\r\n\tu32\ti, readNum;\r\n\tu32* nextFrame;\r\n\r\n\tif (player.open && player.preFetchState == FALSE)\r\n\t\t{\r\n\t\t\r\n\t\treadNum = VID_NUM_READ_BUFFERS;\r\n\r\n\t\t// in 'non-loop' mode we must take care if we have LESS frames than preloading buffers\r\n        if (!loopMode && player.videoInfo.maxFrameCount < VID_NUM_READ_BUFFERS)\r\n                readNum = player.videoInfo.maxFrameCount;\r\n\t\t\t\t\r\n\t\tfor(i = 0; i < readNum; i++)\r\n\t\t\t{\r\n\t\t\t\r\n\t\t\tptr = player.readBuffer[player.readIndex].ptr;\r\n\t\t\t\r\n\t\t\t// read total 'FRAM' chunk and 32 bytes of NEXT chunk\r\n\t\t\tif (DVDRead(&player.fileHandle, ptr, (s32)player.nextFrameSize, (s32)player.nextFrameOffset) < 0 )\r\n\t\t\t\t{\r\n#ifdef MY_DEBUG\r\n\t\t\t\tOSReport(\"*** VIDSimpleLoadStart: Failed to read from file.\\n\");\r\n#endif\r\n\t\t\t\tplayer.error = TRUE;\r\n\t\t\t\treturn FALSE;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\tplayer.nextFrameOffset += player.nextFrameSize;\r\n\t\t\tplayer.readBuffer[player.readIndex].size = player.nextFrameSize;\r\n\r\n            // set read size for next 'FRAM' chunk\r\n\t\t\tnextFrame = (u32*)(ptr + player.nextFrameSize - 32);\r\n\t\t\t\r\n\t\t\t// some sanity check if file structure is valid!\r\n\t\t\tASSERT(nextFrame[0] == VID_FCC('F','R','A','M'));\r\n\t\t\t\r\n\t\t\tplayer.nextFrameSize = nextFrame[1];\r\n\t\t\tASSERT(player.nextFrameSize);\r\n\r\n\t\t\tplayer.readBuffer[player.readIndex].valid = TRUE;\r\n\t\t\tplayer.readBuffer[player.readIndex].frameNumber = player.currentFrameCount;\r\n\r\n\t\t\t// use next buffer\r\n\t\t\tplayer.readIndex = (player.readIndex + 1) % VID_NUM_READ_BUFFERS;\r\n\r\n\t\t\tplayer.currentFrameCount++;\r\n\r\n\t\t\tif (player.currentFrameCount >  player.videoInfo.maxFrameCount - 1)\r\n\t\t\t\t{\r\n\t\t\t\tif (loopMode)\r\n\t\t\t\t\t{\r\n\t\t\t\t\tplayer.currentFrameCount = 0;\r\n\t\t\t\t\tplayer.nextFrameOffset = player.firstFrameOffset;\r\n\t\t\t\t\tplayer.nextFrameSize  = player.firstFrameSize;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tplayer.loopMode = loopMode;\r\n\t\t\tplayer.preFetchState = TRUE;\r\n\r\n\t\t\treturn TRUE;\r\n\t\t}\r\n\treturn FALSE;\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tStops the asynchronous loading process.\r\n *\r\n * \\return\r\n *\t\tTRUE if player could be stopped!\t\t\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL VIDSimpleLoadStop(void)\r\n\t{\r\n\tu32 i;\r\n\r\n\tif (player.open)\r\n\t\t{\r\n\t\t// stop preloading process\r\n\t\tplayer.preFetchState = FALSE;\r\n\r\n\t\tif (player.asyncDvdRunning)\r\n\t\t\t{\r\n\t\t\tDVDCancel(&player.fileHandle.cb);\r\n\t\t\tplayer.asyncDvdRunning = FALSE;\r\n\t\t\t}\r\n\r\n\t\t// invalidate all buffers\r\n\t\tfor (i = 0 ; i < VID_NUM_READ_BUFFERS; i++)\r\n\t\t\tplayer.readBuffer[i].valid = FALSE;\r\n\r\n\t\tplayer.nextFrameOffset = player.firstFrameOffset;\r\n\t\tplayer.nextFrameSize = player.firstFrameSize;\r\n\t\tplayer.currentFrameCount = 0;\r\n\t\t\r\n\t\tplayer.error \t   \t\t= FALSE;\r\n\t\tplayer.readIndex   \t\t= 0;\r\n\t\tplayer.decodeIndex \t\t= 0;\r\n\r\n\t\treturn TRUE;\r\n\t\t}\r\n\treturn FALSE;\r\n    }\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tOpen video file.\r\n *\r\n *\t\tThis functions opens a video file and parses some basic file\r\n *\t\tinformation.\r\n *\r\n * \\param fileName\r\n *\t\tName of file to open\r\n *\r\n * \\return\r\n *\t\tTRUE if file could be opened and is in valid format!\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL VIDSimpleOpen(char* fileName, BOOL suppressAudio)\r\n\t{\r\n\tu32 fileOffset = 0;\r\n\tu32 headSize;\r\n\tu32 audioInfoSize;\r\n\t\r\n    if (player.open)\r\n\t\t{\r\n#ifdef _DEBUG\r\n\t\tOSReport(\"*** Cannot open '%s', because player already open.\\n\");\r\n#endif\r\n\t\treturn FALSE;\r\n\t\t}\r\n\r\n\tif (DVDOpen(fileName, &player.fileHandle) == FALSE)\r\n\t\t{\r\n#ifdef _DEBUG\r\n\t\tOSReport(\"*** Cannot open: '%s'\\n\", fileName);\r\n#endif\r\n\t\treturn FALSE;\r\n\t\t}\r\n\t\t\r\n\t// Read 'VID1' chunk from file and check for correct version\r\n    if (DVDRead(&player.fileHandle, &workChunk, 32, 0) < 0)\r\n\t\t{\r\n#ifdef _DEBUG\r\n\t\tOSReport(\"*** Failed to read the header.\\n\");\r\n#endif\r\n\t\tDVDClose(&player.fileHandle);\r\n\t\treturn FALSE;\r\n\t\t}\r\n\t\t\r\n\tfileOffset += 32;\r\n\t\r\n\t// Check file id\t\r\n\tif(workChunk.id != VID_FCC('V','I','D','1')  )\r\n\t\t{\r\n#ifdef _DEBUG\r\n\t\tOSReport(\"*** No VID1 file: '%s'\\n\", fileName);\r\n#endif\r\n\t\tDVDClose(&player.fileHandle);\r\n\t\treturn FALSE;\r\n\t\t}\r\n\t\r\n\t// Check for correct version of vid chunk.\r\n\t// If we find this version we assume a 'special' alignment and chunk ordering which may be invalid\r\n\t// in another version of the file format.\r\n\tif(workChunk.vid.versionMajor != 1 || workChunk.vid.versionMinor != 0)\r\n\t\t{\r\n#ifdef _DEBUG\r\n\t\tOSReport(\"*** Unsupported file version: major: %d, minor: %d\\n\",\r\n\t\t\t\t  workChunk.vid.versionMajor, workChunk.vid.versionMajor);\r\n#endif\r\n\t\tDVDClose(&player.fileHandle);\r\n\t\treturn FALSE;\r\n\t\t}\r\n\t\r\n#ifdef _DEBUG\r\n\t// Sometimes, it's required to check for a special build of the VidConv converter.\r\n\t{\r\n\tu32 version = VID_VERSION(workChunk.vid.vidConvMajor, workChunk.vid.vidConvMinor, workChunk.vid.vidConvBuild);\r\n\tif(version < VID_VERSION(1,6,4))\r\n\t\tOSReport(\"*** WARNING: Vid file created using an unsupported converter version: %d.%d.%d\\n\", (u32)workChunk.vid.vidConvMajor, (u32)workChunk.vid.vidConvMinor, (u32)workChunk.vid.vidConvBuild);\r\n\t}\r\n#endif\r\n\r\n\t// Check types of chunks we have in this file.\r\n\t// !!! Note that we assume start of 'HEAD' chunk at byte offset 32 from file start !!!\r\n\tif (DVDRead(&player.fileHandle, &workChunk, 32, (s32)fileOffset) < 0)\r\n\t\t{\r\n#ifdef _DEBUG\r\n\t\tOSReport(\"*** Failed to read 'HEAD' chunk.\\n\");\r\n#endif\r\n\t\tDVDClose(&player.fileHandle);\r\n\t\treturn FALSE;\r\n\t\t}\r\n\t\r\n\tif(workChunk.id != VID_FCC('H','E','A','D')  )\r\n\t\t{\r\n#ifdef _DEBUG\r\n\t\tOSReport(\"*** No HEAD chunk found at expected offset\\n\");\r\n#endif\r\n\t\tDVDClose(&player.fileHandle);\r\n\t\treturn FALSE;\r\n\t\t}\r\n\t\r\n\t// Calculate the start of the first frame chunk\r\n\t// (we know the header chunk starts at offset 32)\r\n\tplayer.nextFrameOffset = workChunk.len + 32;\r\n\r\n\t// Skip 'HEAD' chunk id, len and version fields\r\n\tfileOffset += VID_CHUNK_HEADER_SIZE;\r\n\t\r\n\t// We initialize audio codec info to a known value\r\n\t// (this way we can detect the absence of any audio data)\r\n\tplayer.audioInfo.audioID = VID_FCC('N','O','N','E');\r\n\t\r\n\t// The header chunk contains one or more header chunks for the different data types contained\r\n\t// in the stream. Parse them all...\r\n\r\n\theadSize = workChunk.len - VID_CHUNK_HEADER_SIZE;\r\n\twhile(headSize >= 32)\r\n\t\t{\r\n\t\tif (DVDRead(&player.fileHandle, &workChunk, 32, (s32)fileOffset) < 0)\r\n\t\t\t{\r\n#ifdef _DEBUG\r\n\t\t\tOSReport(\"*** Error reading file at offset %d\\n\", fileOffset);\r\n#endif\r\n\t\t\tDVDClose(&player.fileHandle);\r\n\t\t\treturn FALSE;\r\n\t\t\t}\r\n\t\t\r\n\t\tfileOffset += 32;\r\n\t\theadSize -= 32;\r\n\r\n\t\t// We analyze the 1st 32 bytes of the chunk for a known header format\r\n\t\t\r\n\t\t// Video header?\r\n\t\tif(workChunk.id == VID_FCC('V','I','D','H') )\r\n\t\t\t{\r\n\t\t\t// check if we have an old vid file.\r\n\t\t\tif(workChunk.version == 0)\r\n\t\t\t\t{\r\n\t\t\t\tworkChunk.vidh.frameRateScale = (u16)(*((u32*)&workChunk.vidh.frameRateScale));\r\n\t\t\t\tworkChunk.vidh.flags = 0;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t// Yes...\r\n\t\t\tASSERT(workChunk.len <= 32);\r\n\t\t\tASSERT(workChunk.len <= (sizeof(VidVIDH) + VID_CHUNK_HEADER_SIZE));\r\n\t\t\tmemcpy(&player.videoInfo, &workChunk.vidh, sizeof(VidVIDH));\r\n\t\t\t}\r\n\t\t// It's an audio header chunk! May we initialize it?\r\n\t\telse if(workChunk.id == VID_FCC('A','U','D','H') && !suppressAudio)\r\n\t\t\t{\r\n\t\t\t// Allocate memory for audio header chunk\r\n            player.audioHeaderChunk = (u8*)((*player.cbAlloc)(workChunk.len));\r\n\t\t\taudioInfoSize = workChunk.len - VID_CHUNK_HEADER_SIZE;\r\n\t\t\t\r\n\t\t\t// Copy the already loaded part\r\n\t\t\tmemcpy(player.audioHeaderChunk, &workChunk, 32);\r\n\t\t\tworkChunk.len -= 32;\r\n\t\t\t\r\n\t\t\t// Read additional audio header bytes if the audio header is greater that 32 bytes\r\n\t\t\tif(workChunk.len >= 32)\r\n\t\t\t\t{\r\n\t\t\t\tASSERT((workChunk.len&31)==0);\r\n\t\t\t\tif (DVDRead(&player.fileHandle, player.audioHeaderChunk+32, workChunk.len, (s32)fileOffset) < 0)\r\n\t\t\t\t\t{\r\n#ifdef _DEBUG\r\n\t\t\t\t\tOSReport(\"*** Error reading file at offset %d\\n\", fileOffset);\r\n#endif\r\n\t\t\t\t\tDVDClose(&player.fileHandle);\r\n\t\t\t\t\treturn FALSE;\r\n\t\t\t\t\t}\r\n\t\t\t\tfileOffset += workChunk.len;\r\n\t\t\t\theadSize -= workChunk.len;\r\n\t\t\t\t}\r\n\r\n\t\t\t// Setup and calc the number of bytes which we are allowed to copy into the audioInfo struct\r\n\t\t\tmemcpy(&player.audioInfo, player.audioHeaderChunk+VID_CHUNK_HEADER_SIZE, MIN(audioInfoSize, sizeof(player.audioInfo) + sizeof(player.adpcmInfo)));\r\n\t\t\t}\r\n\t\t// Skip unknown chunks. We already read 32 bytes for the header which we must subtract here.\r\n\t\telse\r\n\t\t\t{\r\n\t\t\tfileOffset += workChunk.len - 32;\r\n\t\t\theadSize -= workChunk.len - 32;\r\n\t\t\t}\r\n        }\r\n\t\r\n\tASSERT(player.videoInfo.width && player.videoInfo.height);\r\n\tASSERT(player.videoInfo.maxBufferSize);\r\n\t\r\n\tplayer.fps = (f32)player.videoInfo.frameRate / (f32)player.videoInfo.frameRateScale;\r\n\t\r\n\t// read beginning of 1st frame chunk to get required size information\r\n\tif (DVDRead(&player.fileHandle, &workChunk, 32 , (s32)player.nextFrameOffset) < 0 )\r\n\t\t{\r\n#ifdef _DEBUG\r\n\t\tOSReport(\"*** Failed to read 'FRAM' chunk.\\n\");\r\n#endif\r\n\t\tDVDClose(&player.fileHandle);\r\n\t\treturn FALSE;\r\n\t\t}\r\n\r\n\tif(workChunk.id != VID_FCC('F','R','A','M')  )\r\n\t\t{\r\n#ifdef _DEBUG\r\n\t\tOSReport(\"*** No FRAM chunk found.\");\r\n#endif\r\n\t\tDVDClose(&player.fileHandle);\r\n\t\treturn FALSE;\r\n\t\t}\r\n\r\n\tplayer.nextFrameSize = workChunk.len; \t\t// 32 bytes of this chunk are already consumed, but\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t// we want to 'preload' the NEXT chunk's FRAM header\r\n\tplayer.nextFrameOffset += 32;\r\n\t\r\n\tplayer.firstFrameOffset = player.nextFrameOffset;\r\n\tplayer.firstFrameSize   = player.nextFrameSize;\r\n\r\n\tstrncpy(player.fileName, fileName, 64);\r\n\tplayer.fileName[63] = 0;\r\n\t\r\n\tplayer.open \t\t\t \t= TRUE;\r\n\r\n\tplayer.readIndex \t\t\t= 0;\r\n\tplayer.decodeIndex \t\t\t= 0;\r\n\tplayer.lastDecodedFrame\t\t= 0;\r\n\tplayer.error \t\t\t \t= FALSE;\r\n\tplayer.preFetchState \t \t= FALSE;\r\n\tplayer.loopMode\t\t\t \t= FALSE;\r\n\tplayer.asyncDvdRunning\t\t= FALSE;\r\n\tplayer.currentFrameCount \t= 0;\r\n\tplayer.readBufferBaseMem\t= 0;\r\n\r\n\treturn TRUE;\r\n\t} \t\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tClose open video file\r\n *\r\n * \\return\r\n *\t\tTRUE if file is closed sucessfully.\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL VIDSimpleClose(void)\r\n\t{\r\n\tif (player.open)\r\n\t\t{\r\n\t\tif (player.preFetchState == FALSE)\r\n\t\t\t{\r\n\t\t\tif (!player.asyncDvdRunning)\r\n\t\t\t\t{\r\n\t\t\t\tplayer.open = FALSE;\r\n\t\t\t\tDVDClose(&player.fileHandle);\r\n\t\t\t\tif(player.audioHeaderChunk != NULL)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t(*player.cbFree)(player.audioHeaderChunk);\r\n\t\t\t\t\tplayer.audioHeaderChunk = NULL;\r\n\t\t\t\t\t}\r\n\t\t\t\treturn TRUE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\treturn FALSE;\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tDecode all frame data\r\n *\r\n *\t\tThis function operates on the full frame input data. It forwards this\r\n *\t\tdata to the required decoder.\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL VIDSimpleDecode(void)\r\n\t{\r\n\tBOOL enabled;\r\n\tu8* chunkStart;\r\n\tu32 chunkSize;\r\n\tu32 frameSize;\r\n\r\n\tif ( player.readBuffer[player.decodeIndex].valid )\r\n\t\t{\r\n\t\t\r\n\t\t// ptr to our (pre-) loaded data INSIDE (!) 'FRAM' chunk\r\n\t\t// (in other words, the 'FRAM' chunk itself is not visible here)\r\n\t\tchunkStart = player.readBuffer[player.decodeIndex].ptr;\r\n\r\n\t\t// usually, we read additional 32 bytes for getting info about the NEXT chunk.\r\n\t\t// We only deal with the actual 'FRAM' chunk data here and adjust the size by 32 bytes.\r\n        frameSize = player.readBuffer[player.decodeIndex].size - 32;\r\n\t\t\r\n\t\t// loop across ALL chunks inside 'FRAM'\r\n\t\twhile(frameSize >= 32)\r\n\t\t\t{\r\n\t\t\tchunkSize = VID_CHUNK_LEN(chunkStart);\r\n\t\t\t\r\n\t\t\tif( VID_CHUNK_ID(chunkStart) == VID_FCC('V','I','D','D') )\r\n\t\t\t\t{\r\n\t\t\t\tif(! VIDVideoDecode(player.decoder, chunkStart + VID_CHUNK_HEADER_SIZE, chunkSize - VID_CHUNK_HEADER_SIZE, &player.image))\r\n\t\t\t\t\t{\r\n#ifdef _DEBUG\r\n\t\t\t\t\tOSReport(\"*** VIDVideoDecode failed!\\n\");\r\n#endif\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\telse if( VID_CHUNK_ID(chunkStart) == VID_FCC('A','U','D','D') )\r\n\t\t\t\t{\r\n\t\t\t\t// This is audio data!\r\n\t\t\t\t\r\n\t\t\t\t// Get the data to the audio system...\r\n\t\t\t\tif(! VIDSimpleAudioDecode(chunkStart + VID_CHUNK_HEADER_SIZE, chunkSize - VID_CHUNK_HEADER_SIZE))\r\n\t\t\t\t\t{\r\n#ifdef _DEBUG\r\n\t\t\t\t\tOSReport(\"*** VIDAudioDecode failed!\\n\");\r\n#endif\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n#ifdef _DEBUG\r\n\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\tOSReport(\"*** VIDSimpleDecode: unknown chunk type!\\n\");\r\n\t\t\t\t}\r\n#endif\r\n\t\t\t\r\n\t\t\t// goto next chunk\r\n\t\t\tchunkStart += chunkSize;\r\n\t\t\tframeSize -= chunkSize;\r\n\t\t\t}\r\n\t\t\t\r\n\t\tplayer.lastDecodedFrame = player.readBuffer[player.decodeIndex].frameNumber;\r\n\t\tplayer.readBuffer[player.decodeIndex].valid = FALSE;\r\n\t\tplayer.decodeIndex = (player.decodeIndex + 1) % VID_NUM_READ_BUFFERS;\r\n\r\n\t\t// check if loading is still running\r\n\t\tenabled = OSDisableInterrupts();\r\n\t\tif (!player.readBuffer[player.readIndex].valid && !player.asyncDvdRunning)\r\n\t\t\tReadFrameAsync();\r\n\t\tOSRestoreInterrupts(enabled);\r\n\t\t\r\n        return TRUE;\r\n\t\t}\r\n\r\n#ifdef _DEBUG\r\n\tOSReport(\"*** VIDSimpleDecode: No valid decode buffer found (?).\\n\");\r\n#endif\r\n\treturn FALSE;\r\n\r\n\t}\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tDraw a decoded video frame.\r\n *\r\n * \\param rmode\r\n *\t\tRequired info about current rendering mode\r\n * \\param x\r\n *\t\tcurrent x pos of drawing surface\r\n * \\param y\r\n *\t\tcurrent y pos of drawing surface\r\n * \\param width\r\n *\t\tcurrent width of drawing surface\r\n * \\param height\r\n *\t\tcurrent height of drawing surface\r\n *\r\n ******************************************************************************\r\n */\r\nvoid VIDSimpleDraw(GXRenderModeObj *rmode, u32 x, u32 y, u32 width, u32 height)\r\n\t{\r\n\tVIDDrawGXYuv2RgbSetup(rmode);\r\n\tVIDDrawGXYuv2RgbDraw((s16)x, (s16)y, (s16)width, (s16)height, player.image);\r\n\tVIDDrawGXRestore();\r\n\t}\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tDraw decoded frame directely into the XFB\r\n *\r\n * \\param rmode\r\n *\t\tRequired info about current rendering mode\r\n * \\param lcMem\r\n *\t\tPointer to free locked cache mem used for conversion.\r\n *\r\n ******************************************************************************\r\n */\r\nvoid VIDSimpleDrawXFB(GXRenderModeObj *rmode, void* lcMem)\r\n\t{\r\n\tVIDXFBDraw(player.image, hwCurrentBuffer, rmode->fbWidth, rmode->xfbHeight, lcMem);\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tGet width and height of loaded video file.\r\n *\r\n ******************************************************************************\r\n */\r\nvoid VIDSimpleGetVideoSize(u32* width, u32* height)\r\n\t{\r\n\t// can only be returned if player has a loaded file\r\n\tASSERT(player.open);\r\n\t\r\n\t*width = player.videoInfo.width;\r\n\t*height = player.videoInfo.height;\r\n\t}\r\n\t\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tGet FPS rate of loaded video file.\r\n *\r\n ******************************************************************************\r\n */\r\nf32 VIDSimpleGetFPS(void)\r\n\t{\r\n\treturn(player.fps);\r\n\t}\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tCheck if the currently loaded video is in interlace mode or not\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL VIDSimpleIsInterlace(void)\r\n\t{\r\n\treturn(((player.videoInfo.flags & VID_VIDH_INTERLACED) != 0));\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tGet number of frames of loaded video file.\r\n *\r\n ******************************************************************************\r\n */\r\nu32 VIDSimpleGetFrameCount(void)\r\n\t{\r\n\treturn(player.videoInfo.maxFrameCount);\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tGet audio sample rate in Hz.\r\n *\r\n ******************************************************************************\r\n */\r\nu32 VIDSimpleGetAudioSampleRate(void)\r\n\t{\r\n\treturn(player.audioInfo.vaud.frq);\r\n\t}\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tCheck for drive status\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL VIDSimpleCheckDVDError(void)\r\n\t{\r\n\tswitch (DVDGetDriveStatus())\r\n\t\t{\r\n\t\tcase DVD_STATE_FATAL_ERROR:\r\n\t\t\t{\r\n\t\t\tOSReport(\"DVDGetDriveStatus()=DVD_STATE_FATAL_ERROR\\n\");\r\n\t\t\tbreak;\r\n\t\t\t}\r\n\t\tcase DVD_STATE_NO_DISK:\r\n\t\t\t{\r\n\t\t\tOSReport(\"DVDGetDriveStatus()=DVD_STATE_NO_DISK\\n\");\r\n\t\t\tbreak;\r\n\t\t\t}\r\n\t\tcase DVD_STATE_COVER_OPEN:\r\n\t\t\t{\r\n\t\t\tOSReport(\"DVDGetDriveStatus()=DVD_STATE_COVER_OPEN\\n\");\r\n\t\t\tbreak;\r\n\t\t\t}\r\n\t\tcase DVD_STATE_WRONG_DISK:\r\n\t\t\t{\r\n\t\t\tOSReport(\"DVDGetDriveStatus()=DVD_STATE_WRONG_DISK\\n\");\r\n\t\t\tbreak;\r\n\t\t\t}\r\n\t\tcase DVD_STATE_RETRY:\r\n\t\t\t{\r\n\t\t\tOSReport(\"DVDGetDriveStatus()=DVD_STATE_RETRY\\n\");\r\n\t\t\tbreak;\r\n\t\t\t}\r\n\t\tdefault:\r\n\t\t\treturn(TRUE);\r\n\t\t}\r\n\t\r\n\treturn(FALSE);\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tMemory allocation callback.\r\n *\r\n *\t\tThe player calls this function for all its memory needs. In this example\r\n *\t\tan OSAlloc() is all we need to do.\r\n *\r\n * \\note\r\n *\t\tThe returned memory address MUST be aligned on a 32 byte boundary.\r\n *\t\tOtherwise, the player will fail!\r\n *\r\n * \\param size\r\n *\t\tNumber of bytes to allocate\r\n *\r\n * \\return\r\n *\t\tPtr to allocated memory (aligned to 32 byte boundary)\r\n *\t\r\n ******************************************************************************\r\n */\r\nstatic void* myAlloc(u32 size)\r\n{\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().TopDownHeap());\r\n\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\tvoid * p = new u8[size]; \r\n\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn p;\r\n}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tMemory free callback.\r\n *\r\n * \\param ptr\r\n *\t\tMemory address to free\r\n *\t\r\n ******************************************************************************\r\n */\r\nstatic void myFree(void* ptr)\r\n\t{\r\n\tASSERT(ptr);\t// free on address 0 is only valid in C++ delete\r\n\tdelete ptr;\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tMemory allocation callback for 'Locked Cache' memory.\r\n *\r\n *\t\tIf the system should operate in 'Locked Cache' mode, you must\r\n *\t\tsupply a callback which is called for any 'locked cache'\r\n *\t\tmemory requirements.\r\n *\r\n *\t\tNote that there's no 'free' for the 'locked cache' memory,\r\n *\t\tbecause if the player is destroyed ANY 'locked cache' memory is\r\n *\t\tavaiable immediately.\r\n *\r\n * \\note\r\n *\t\tThe returned memory address MUST be aligned on a 32 byte boundary.\r\n *\t\tOtherwise, the player will fail!\r\n *\r\n * \\param size\r\n *\t\tNumber of bytes to allocate\r\n *\r\n * \\return\r\n *\t\tPtr to allocated memory (aligned to 32 byte boundary)\r\n *\t\r\n ******************************************************************************\r\n */\r\nstatic void* myAllocFromLC(u32 size)\r\n\t{\r\n#ifdef MY_DEBUG\r\n\tu32 lockCacheMem;\r\n#endif\r\n\tvoid* ret = lcMemBase;\r\n\tASSERT(ret);\r\n\t\r\n\tlcMemBase += size;\r\n\tlcMemBase = (u8*)OSRoundUp32B(lcMemBase);\r\n\r\n#ifdef MY_DEBUG\r\n\tlockCacheMem = (u32)(lcMemBase - ((u8*)LCGetBase()));\r\n\t//OSReport(\"myMallocFromLC: Used 'Locked Cache' Mem: %d kB.\\n\", lockCacheMem/1024);\r\n\tASSERTMSG(lockCacheMem < (15*1024), \"myMallocFromLC: Too much locked cache mem needed!\\n\");\r\n#endif\r\n\treturn ret;\r\n\t}\r\n\r\n/******************************************************************************\r\n *  DEFINES\r\n ******************************************************************************/\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tRestore GX graphics context to some 'defaults'\r\n *\r\n ******************************************************************************\r\n */\r\nvoid VIDDrawGXRestore(void)\r\n\t{\r\n    GXSetZMode(GX_ENABLE, GX_ALWAYS, GX_DISABLE);\r\n    GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_SET);\r\n\r\n    GXSetNumTexGens(1);\r\n    GXSetNumChans(0);\r\n    GXSetNumTevStages(1);\r\n    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);\r\n    GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);\r\n\r\n    // Swap mode settings\r\n    GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);\r\n    GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0);\r\n    GXSetTevSwapMode(GX_TEVSTAGE2, GX_TEV_SWAP0, GX_TEV_SWAP0);\r\n    GXSetTevSwapMode(GX_TEVSTAGE3, GX_TEV_SWAP0, GX_TEV_SWAP0);\r\n\r\n    GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED,   GX_CH_GREEN,\r\n                                        GX_CH_BLUE,  GX_CH_ALPHA); // RGBA\r\n    GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED,   GX_CH_RED,\r\n                                        GX_CH_RED,   GX_CH_ALPHA); // RRRA\r\n    GXSetTevSwapModeTable(GX_TEV_SWAP2, GX_CH_GREEN, GX_CH_GREEN,\r\n                                        GX_CH_GREEN, GX_CH_ALPHA); // GGGA\r\n    GXSetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE,  GX_CH_BLUE,\r\n                                        GX_CH_BLUE,  GX_CH_ALPHA); // BBBA\r\n\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tSetup GX for YUV conversion\r\n *\r\n ******************************************************************************\r\n */\r\nvoid VIDDrawGXYuv2RgbSetup(GXRenderModeObj *rmode)\r\n\t{\r\n    s32         scrWidth;\r\n    s32         scrHeight;\r\n    Mtx44       pMtx;\r\n\r\n    scrWidth  = rmode->fbWidth;\r\n    scrHeight = rmode->efbHeight;\r\n\r\n\tGXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);\r\n\r\n\tMTXOrtho(pMtx, 0.0f, (f32)scrHeight, 0.0f, (f32)scrWidth, 0.0f, -1.0F);\r\n\r\n\tGXSetProjection(pMtx, GX_ORTHOGRAPHIC);\r\n    GXSetViewport(0.0F, 0.0F, (f32)scrWidth, (f32)scrHeight, 0.0F, 1.0F);\r\n\tGXSetScissor(0, 0, (u32)scrWidth, (u32)scrHeight);\r\n\t\r\n    GXSetCurrentMtx(GX_IDENTITY);\r\n\r\n    // Framebuffer\r\n    GXSetZMode(GX_ENABLE, GX_ALWAYS, GX_DISABLE);\r\n    GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR);\r\n    GXSetColorUpdate(GX_TRUE);\r\n    GXSetAlphaUpdate(GX_FALSE);\r\n    GXSetDispCopyGamma(GX_GM_1_0);\r\n\t\r\n\t// Color channels\r\n    GXSetNumChans(0);\r\n\r\n    // Texture coord generation\r\n    GXSetNumTexGens(2);\r\n    GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY);\r\n\r\n    // Texture cache\r\n    GXInvalidateTexAll();\r\n\r\n    // Vertex formats\r\n    GXClearVtxDesc();\r\n    GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);\r\n    GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);\r\n    GXSetVtxDesc(GX_VA_TEX1, GX_DIRECT);\r\n\t\r\n    GXSetVtxAttrFmt(GX_VTXFMT7, GX_VA_POS,  GX_POS_XYZ, GX_S16, 0);\r\n    GXSetVtxAttrFmt(GX_VTXFMT7, GX_VA_TEX0, GX_TEX_ST,  GX_U16, 0);\r\n    GXSetVtxAttrFmt(GX_VTXFMT7, GX_VA_TEX1, GX_TEX_ST,  GX_U16, 0);\r\n\r\n\t// Setup TEV environment to perform color space conversion.\r\n\t// The function will return the number of TEV stages need and will\r\n\t// use the following HW resources:\r\n\t//\r\n\t//\tGX_TEVPREV\r\n\t//\tGX_TEVREG0\r\n\t//\tGX_TEVREG1\r\n\t//\tGX_TEVREG2\r\n\t//\r\n\t//\tGX_KCOLOR0\r\n\t//\tGX_KCOLOR1\r\n\t//\tGX_KCOLOR2\r\n\t//\tGX_KCOLOR3\r\n\t//\r\n\t// plus everything visible in this source\r\n\t//\r\n\tGXSetNumTevStages(VIDSetupTEV(VID_YUVCONV_HIGHPRECISION));\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tDraw a textured polygon using the decoded image a texture.\r\n *\r\n * \\param x\r\n *\t\txpos of polygon on screen\r\n * \\param y\r\n *\t\typos of polygon on screen\r\n * \\param polygonWidth\r\n *\t\twidth of polygon to draw\r\n * \\param polygonHeight\r\n *\t\theight of polygon to draw\r\n * \\param image\r\n *\t\tptr to VIDImage containing the required YUV pointers\r\n ******************************************************************************\r\n */\r\nvoid VIDDrawGXYuv2RgbDraw(s16 x, s16 y, s16 polygonWidth, s16 polygonHeight, const VIDImage* image)\r\n\t{\r\n\tu16 textureWidth2, textureHeight2;\r\n\tGXTexObj tobj0, tobj1, tobj2;\r\n\t\r\n\ttextureWidth2 = (u16)(image->texWidth >> 1);\r\n\ttextureHeight2 = (u16)(image->texHeight >> 1);\r\n\t\r\n\t// Y Texture\r\n\tGXInitTexObj(&tobj0, image->y, image->texWidth, image->texHeight,\r\n                 GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE);\r\n\tGXInitTexObjLOD(&tobj0, GX_LINEAR, GX_LINEAR, 0, 0, 0, 0, 0, GX_ANISO_1);\r\n\tGXLoadTexObj(&tobj0, GX_TEXMAP0);\r\n\r\n\t// Cb Texture\r\n\tGXInitTexObj(&tobj1, image->u, textureWidth2, textureHeight2,\r\n                 GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE);\r\n\tGXInitTexObjLOD(&tobj1, GX_LINEAR, GX_LINEAR, 0, 0, 0, 0, 0, GX_ANISO_1);\r\n\tGXLoadTexObj(&tobj1, GX_TEXMAP1);\r\n\r\n\t// Cr Texture\r\n\tGXInitTexObj(&tobj2, image->v, textureWidth2, textureHeight2,\r\n                 GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE);\r\n\tGXInitTexObjLOD(&tobj2, GX_LINEAR, GX_LINEAR, 0, 0, 0, 0, 0, GX_ANISO_1);\r\n\tGXLoadTexObj(&tobj2, GX_TEXMAP2);\r\n\r\n\tGXSetTexCoordScaleManually(GX_TEXCOORD0, GX_ENABLE, 1, 1);\r\n\tGXSetTexCoordScaleManually(GX_TEXCOORD1, GX_ENABLE, 1, 1);\r\n\r\n\t// Draw a textured quad\r\n\tGXBegin(GX_QUADS, GX_VTXFMT7, 4);\r\n\t\tGXPosition3s16(x, y, 0);\r\n\t\tGXTexCoord2u16(0, 0);\r\n\t\tGXTexCoord2u16(0, 0);\r\n\t\t\r\n\t\tGXPosition3s16((s16)(x+polygonWidth), y, 0);\r\n\t\tGXTexCoord2u16(image->width, 0);\r\n\t\tGXTexCoord2u16((u16)(image->width>>1), 0);\r\n\r\n\t\tGXPosition3s16((s16)(x+polygonWidth), (s16)(y+polygonHeight), 0);\r\n\t\tGXTexCoord2u16(image->width, image->height);\r\n\t\tGXTexCoord2u16((u16)(image->width>>1), (u16)(image->height>>1));\r\n\t\t\r\n\t\tGXPosition3s16(x, (s16)(y+polygonHeight), 0);\r\n\t\tGXTexCoord2u16(0, image->height);\r\n\t\tGXTexCoord2u16(0, (u16)(image->height>>1));\r\n\tGXEnd();\r\n\r\n\tGXSetTexCoordScaleManually(GX_TEXCOORD0, GX_DISABLE, 1, 1);\r\n\tGXSetTexCoordScaleManually(GX_TEXCOORD1, GX_DISABLE, 1, 1);\r\n\t\r\n\t}\r\n\r\n/******************************************************************************\r\n *  DEFINES\r\n ******************************************************************************/\r\n\r\n#define\tVID_AUDIO_READAHEADFRAMES\t8\t\t\t// Number of video frames worth of audio data that should be able to be stored prio to being routed into the AI buffer\r\n\t\t\t\t\t\t\t\t\t\t\t\t// (the data stream will contain MORE data than needed at times -- esspecially at the beginning of the stream.\r\n\t\t\t\t\t\t\t\t\t\t\t\t//  Hence an intermediate buffer is needed!)\r\n\r\n#define\tVID_AUDIO_NUMLEADFRAMES\t\t4\t\t\t// Number of lead in frames for audio in data file (VIDCONV default)\r\n#define\tVID_AUDIO_LEADFACTOR\t\t1.5f\t\t// Lead in data ratio factor in lead in frames (VIDCONV default)\r\n\r\n#define\tVID_AUDIO_AIBUFFERSAMPLES\t(2*256)\t\t// 10.6ms of 48KHz data per AI buffer (32 byte multiple), that'll be about 15.9ms at 32Khz\r\n#define\tVID_AUDIO_NUMAIBUFFERS\t\t2\t\t\t// Number of AI playback buffers (this has an impact on audio latency. 2 is the minimum needed)\r\n#define VID_AUDIO_NUMAIREQUESTS\t\t16\r\n\r\n#define\tAX_ARAM_BUFFER_SIZE\t\t\t(VID_AUDIO_AIBUFFERSAMPLES * VID_AUDIO_NUMAIBUFFERS)\r\n\r\n//#define\tAX_ARAM_LEFT_CHANNEL\t\t0x200000\t// @ 4MB (16-Bit addressing for DSP!)\r\n#define\tAX_ARAM_LEFT_CHANNEL\t\t( NxNgc::EngineGlobals.aram_stream0 >> 1 )\r\n#define\tAX_ARAM_RIGHT_CHANNEL\t\t(AX_ARAM_LEFT_CHANNEL + AX_ARAM_BUFFER_SIZE)\r\n\r\n/******************************************************************************\r\n *  LOCAL VARIABLES & LOCAL EXTERNAL REFERENCES\r\n ******************************************************************************/\r\n\r\nextern VidSimplePlayer\tplayer;\t\t\t\t\t\t\t\t\t\t// Player instance\r\n\r\nstatic void\t\t\t\t*audioReadBuffer;\t\t\t\t\t\t\t// Buffer to store audio data received from the data stream\r\nstatic u32\t\t\t\taudioReadBufferNumSamples;\t\t\t\t\t// Size of the above buffer in samples\r\nstatic u32\t\t\t\taudioReadBufferWritePos;\t\t\t\t\t// Write position in the above buffer in samples\r\nstatic u32\t\t\t\taudioReadBufferReadPos;\t\t\t\t\t\t// Read position in the above buffer in samples\r\nstatic u8\t\t\t\taudioReadBufferNumChannels;\t\t\t\t\t// Number of channels stored in the read buffer\r\n\r\nstatic void\t\t\t\t*audioPlayBuffer[VID_AUDIO_NUMAIBUFFERS];\t// AI playback buffers\r\nstatic u8\t\t\t\taudioPlayBufferWriteIndex;\t\t\t\t\t// Index to next AI buffer to be written to from the read buffer\r\nstatic u32\t\t\t\taudioPlayBufferFrq;\t\t\t\t\t\t\t// Playback frequency of AI in Hz\r\nstatic volatile BOOL\taudioPlayBufferEnabled;\t\t\t\t\t\t// TRUE if playback is enabled. AI will operate at all times, but zeros will be filled in instead of real data if this is FALSE.\r\nstatic volatile BOOL\taudioPlayBackPossible;\t\t\t\t\t\t// TRUE if read buffer is initialized and playback may start\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Normally this should be 1. It should never be greater or equal to the number of AI buffers.\r\n\r\nstatic void (*VIDSimpleDoAudioDecode)(s16* dest,u32 channels,const s16** samples,u32 sampleOffset,u32 sampleNum); // vector to the current decoder function\r\nstatic u32 (*VIDSimpleAudioBytesFromSamples)(u32 samples);\t\t\t\t\t// vector to the current bytes to samples conversion function\r\nstatic u32 (*VIDSimpleAudioSamplesFromBytes)(u32 bytes);\t\t\t\t\t// vector to the current samples to bytes conversion function\r\n\r\nstatic const u32\t\t*audioPlayMaskArray;\t\t\t\t\t\t// Pointer to an array of channel play masks (each set bit signals an active channel)\r\nstatic u32\t\t\t\taudioNumPlayMasks;\t\t\t\t\t\t\t// Number of play masks specified (0 indicates all channels should be active)\r\nstatic u32\t\t\t\taudioNumActiveVoices;\t\t\t\t\t\t// Number of active voices\r\n\r\nstatic AXVPB\t\t\t*axVoice[2];\t\t\t\t\t\t\t\t// AX voice structures\r\nstatic ARQRequest\t\tarqRequest[2][VID_AUDIO_NUMAIREQUESTS];\t\t// Enough ARQ request structures for worst case scenario\r\nstatic u32\t\t\t\taxLastAddr;\t\t\t\t\t\t\t\t\t// Last known address DSP read from for 1st voice\r\nstatic u32\t\t\t\taxPlayedSamples;\t\t\t\t\t\t\t// Number of samples played on first voice since last update\r\nstatic f32\t\t\t\taxCurrentFrq;\t\t\t\t\t\t\t\t// Current frequency used for playback\r\nstatic u32\t\t\t\taxMinAvailFrames;\t\t\t\t\t\t\t// Minimum number of frames available in the read buffer at which we are still \"happy\" and play at the specified frequency\t\t\t\r\n\r\ntypedef enum VID_AXPHASE {\r\n\t\tAX_PHASE_STARTUP = 0,\r\n\t\tAX_PHASE_START,\r\n\t\tAX_PHASE_PLAY\r\n} VID_AXPHASE;\r\n\r\nstatic VID_AXPHASE\t\taxPhase;\r\n\r\n/******************************************************************************\r\n *  LOCAL PROTOTYPES\r\n ******************************************************************************/\r\n\r\nstatic void AXCallback(void);\r\n\r\nstatic void VIDSimpleDoAudioDecodePCM16(s16* dest,u32 channels,const s16** samples,u32 sampleOffset,u32 sampleNum);\r\nstatic u32 VIDSimpleAudioBytesFromSamplesPCM16(u32 samples);\r\nstatic u32 VIDSimpleAudioSamplesFromBytesPCM16(u32 bytes);\r\n\r\nstatic void VIDSimpleDoAudioDecodeVAUD(s16* dest,u32 channels,const s16** samples,u32 sampleOffset,u32 sampleNum);\r\nstatic u32 VIDSimpleAudioBytesFromSamplesVAUD(u32 samples);\r\nstatic u32 VIDSimpleAudioSamplesFromBytesVAUD(u32 bytes);\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tInitialize audio decoder\r\n *\r\n *\t\tThis function allocates all neccessary memory for the audio processing\r\n *\t\tand sets the audio decoder into an idle state, waiting for first data.\r\n *\t\tA file must be opened with the VIDSimplePlayer before calling this\r\n *\t\tfunction.\r\n *\r\n * \\param cbAlloc\r\n *\t\tPointer to a memory allocation function to be used\r\n *\r\n * \\return\r\n *\t\tTRUE if any problem was detected\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL VIDSimpleInitAudioDecoder(void)\r\n\t{\r\n\tu32\ti;\r\n\tBOOL old;\r\n\r\n\tAXPBMIX\t  axMix[2];\r\n\tAXPBVE    axVE;\r\n\tAXPBSRC\t  axSRC;\r\n\tAXPBADDR  axAddr;\r\n\tAXPBADPCM axADPCM;\r\n\tu32\t\t  ratio;\r\n\r\n\t// Do we have any audio data?\r\n\tif (player.audioInfo.audioID != VID_FCC('N','O','N','E'))\r\n\t\t{\r\n\t\t// VAUD?\r\n\t\tif (player.audioInfo.audioID == VID_FCC('V','A','U','D'))\r\n\t\t\t{\r\n\t\t\t// Calculate buffer size to allocate proper memry to keep a bit of \"extra\" audio data around...\r\n\t\t\taudioReadBufferNumSamples = (u32)(((f32)VID_AUDIO_READAHEADFRAMES * player.audioInfo.vaud.frq) / player.fps);\r\n\t\t\taudioReadBufferNumChannels = player.audioInfo.vaud.numChannels <= 2 ? player.audioInfo.vaud.numChannels : 2;\r\n\r\n\t\t\t// Setup decoder & conversion functions to be used\r\n\t\t\tVIDSimpleDoAudioDecode = VIDSimpleDoAudioDecodeVAUD;\r\n\t\t\tVIDSimpleAudioBytesFromSamples = VIDSimpleAudioBytesFromSamplesVAUD;\r\n\t\t\tVIDSimpleAudioSamplesFromBytes = VIDSimpleAudioSamplesFromBytesVAUD;\r\n\t\t\t}\r\n\t\telse\r\n\t\t\t{\r\n\t\t\t// PCM16?\r\n\t        if (player.audioInfo.audioID == VID_FCC('P','C','1','6'))\r\n\t\t\t\t{\r\n\t\t        // Calculate buffer size to allocate proper memry to keep a bit of \"extra\" audio data around...\r\n\t\t        audioReadBufferNumSamples = (u32)(((f32)VID_AUDIO_READAHEADFRAMES * player.audioInfo.pcm16.frq) / player.fps);\r\n        \r\n\t\t        if (player.audioInfo.pcm16.numChannels <= 2)\r\n\t\t\t        audioReadBufferNumChannels = player.audioInfo.pcm16.numChannels;\r\n\t\t        else\r\n\t\t\t        audioReadBufferNumChannels = 2;\r\n\t\t        \r\n\t\t        // Setup decoder & conversion functions to be used\r\n\t\t        VIDSimpleDoAudioDecode = VIDSimpleDoAudioDecodePCM16;\r\n\t\t        VIDSimpleAudioBytesFromSamples = VIDSimpleAudioBytesFromSamplesPCM16;\r\n\t\t        VIDSimpleAudioSamplesFromBytes = VIDSimpleAudioSamplesFromBytesPCM16;\r\n\t\t        }\r\n\t        else\r\n\t\t        {\r\n\t\t        if (player.audioInfo.audioID == VID_FCC('A','P','C','M'))\r\n\t\t\t        {\r\n\t\t\t        // [...]\r\n\t\t\t        }\r\n\t\t        else\r\n\t\t\t        {\r\n\t\t\t        // Other audio codecs might be implemented here\r\n\t\t\t        // (the idea being to decode the data into the audioReadBuffer allocated below)\r\n\t\t\t        // [...]\r\n\t\t\t        ASSERT(FALSE);\r\n\t\t\t        }\r\n\t\t        }\r\n\t\t\t}\r\n\t\t\t\r\n\t\t// Allocate read buffer\r\n\t\taudioReadBuffer = player.cbAlloc(audioReadBufferNumSamples * sizeof(s16) * player.audioInfo.pcm16.numChannels);\r\n\t\tif (audioReadBuffer == NULL)\r\n\t\t\treturn TRUE;\t\t\t\t\t// error\r\n\t\t\r\n\t\t// Reset ring buffer\r\n\t\taudioReadBufferReadPos = audioReadBufferWritePos = 0;\r\n\t\t\r\n\t\t// What AI frquency is best?\r\n\t\taudioPlayBufferFrq = player.audioInfo.pcm16.frq;\r\n\t\t\r\n\t\t// Allocate AI playback buffer\r\n\t\taudioPlayBuffer[0] = player.cbAlloc(2 * sizeof(s16) * VID_AUDIO_AIBUFFERSAMPLES * VID_AUDIO_NUMAIBUFFERS);\r\n\t\tif (audioPlayBuffer[0] == NULL)\r\n\t\t\treturn TRUE;\t\t\t\t\t// error\r\n\t\t\r\n\t\tfor(i=1; i<VID_AUDIO_NUMAIBUFFERS; i++)\r\n\t\t\taudioPlayBuffer[i] = (void *)((u32)audioPlayBuffer[i - 1] + (2 * sizeof(s16) * VID_AUDIO_AIBUFFERSAMPLES));\r\n\t\t\r\n\t\t// Reset buffer index\r\n\t\taudioPlayBufferWriteIndex = 0;\r\n\t\t\r\n\t\t// We disable AI output for now (logically)\r\n\t\taudioPlayBufferEnabled = FALSE;\r\n\t\taudioPlayBackPossible = FALSE;\r\n\t\t\r\n\t\t// We assume to playback all we get by default\r\n\t\taudioPlayMaskArray = NULL;\r\n\t\taudioNumPlayMasks = 0;\r\n\t\taudioNumActiveVoices = 2;\r\n\t\t\r\n\t\t// Clear out AI buffers to avoid any noise what so ever\r\n\t\tmemset(audioPlayBuffer[0],0,2 * sizeof(s16) * VID_AUDIO_AIBUFFERSAMPLES * VID_AUDIO_NUMAIBUFFERS);\r\n\t\tDCFlushRange(audioPlayBuffer[0],2 * sizeof(s16) * VID_AUDIO_AIBUFFERSAMPLES * VID_AUDIO_NUMAIBUFFERS);\r\n\t\t\r\n\t\t// Init GCN audio system\r\n\t\told = OSDisableInterrupts();\r\n\r\n\t\taxVoice[0] = AXAcquireVoice(AX_PRIORITY_NODROP,NULL,0);\r\n\t\tASSERT(axVoice[0] != NULL);\r\n\t\taxVoice[1] = AXAcquireVoice(AX_PRIORITY_NODROP,NULL,0);\r\n\t\tASSERT(axVoice[1] != NULL);\r\n\r\n\t\tmemset(&axMix[0],0,sizeof(axMix[0]));\r\n\t\taxMix[0].vL = 0x7FFF;\r\n\t\tmemset(&axMix[1],0,sizeof(axMix[1]));\r\n\t\taxMix[1].vR = 0x7FFF;\r\n\t\t\r\n\t\tAXSetVoiceMix(axVoice[0],&axMix[0]);\r\n\t\tAXSetVoiceMix(axVoice[1],&axMix[1]);\r\n\t\t\r\n\t\taxVE.currentDelta = 0;\r\n\t\taxVE.currentVolume = 0x7FFF;\r\n\t\tAXSetVoiceVe(axVoice[0],&axVE);\r\n\t\tAXSetVoiceVe(axVoice[1],&axVE);\r\n\t\t\r\n\t\tmemset(&axSRC,0,sizeof(AXPBSRC));\r\n\t\t\r\n\t\tratio = (u32)(65536.0f * (f32)audioPlayBufferFrq / (f32)AX_IN_SAMPLES_PER_SEC);\r\n\t\taxSRC.ratioHi = (u16)(ratio >> 16);\r\n\t\taxSRC.ratioLo = (u16)ratio;\r\n\t\t\r\n\t\taxCurrentFrq = (f32)audioPlayBufferFrq;\r\n\r\n\t\t// Calculate what we deem is a save amount of extra data in our read buffers\r\n\t\taxMinAvailFrames = (u32)((audioPlayBufferFrq * (VID_AUDIO_LEADFACTOR - 1.0f) * ((f32)VID_AUDIO_NUMLEADFRAMES / player.fps)) / (f32)VID_AUDIO_AIBUFFERSAMPLES);\r\n\t\t\r\n\t\tAXSetVoiceSrcType(axVoice[0],AX_SRC_TYPE_4TAP_16K);\r\n\t\tAXSetVoiceSrc(axVoice[0],&axSRC);\r\n\t\tAXSetVoiceSrcType(axVoice[1],AX_SRC_TYPE_4TAP_16K);\r\n\t\tAXSetVoiceSrc(axVoice[1],&axSRC);\r\n\t\t\r\n        *(u32 *)&axAddr.currentAddressHi = AX_ARAM_LEFT_CHANNEL;\r\n\t\t*(u32 *)&axAddr.loopAddressHi = AX_ARAM_LEFT_CHANNEL;\r\n\t\t*(u32 *)&axAddr.endAddressHi = AX_ARAM_LEFT_CHANNEL + AX_ARAM_BUFFER_SIZE - 1;\r\n\t\taxAddr.format = AX_PB_FORMAT_PCM16;\r\n\t\taxAddr.loopFlag = AXPBADDR_LOOP_ON;\r\n\t\tAXSetVoiceAddr(axVoice[0],&axAddr);\r\n\t\t\r\n\t\t*(u32 *)&axAddr.currentAddressHi = AX_ARAM_RIGHT_CHANNEL;\r\n\t\t*(u32 *)&axAddr.loopAddressHi = AX_ARAM_RIGHT_CHANNEL;\r\n\t\t*(u32 *)&axAddr.endAddressHi = AX_ARAM_RIGHT_CHANNEL + AX_ARAM_BUFFER_SIZE - 1;\r\n\t\tAXSetVoiceAddr(axVoice[1],&axAddr);\r\n\r\n\t\tmemset(&axADPCM,0,sizeof(axADPCM));\r\n\t\taxADPCM.gain = 0x0800;\r\n\t\t\r\n\t\tAXSetVoiceAdpcm(axVoice[0],&axADPCM);\r\n\t\tAXSetVoiceAdpcm(axVoice[1],&axADPCM);\r\n\t\t\r\n\t\tAXSetVoiceType(axVoice[0],AX_PB_TYPE_STREAM);\r\n\t\tAXSetVoiceType(axVoice[1],AX_PB_TYPE_STREAM);\r\n\t\t\r\n\t\tAXRegisterCallback(AXCallback);\r\n\t\t\r\n\t\taxLastAddr = AX_ARAM_LEFT_CHANNEL;\r\n\t\taxPlayedSamples = VID_AUDIO_AIBUFFERSAMPLES * VID_AUDIO_NUMAIBUFFERS;\r\n\t\taxPhase = AX_PHASE_STARTUP;\r\n\t\t\r\n\t\t// All is setup for the voices. We'll start them inside the AX callback as soon as we got data in the ARAM buffers\r\n        OSRestoreInterrupts(old);\r\n\t\t}\r\n\t\t\r\n\treturn FALSE;\t\t\t// no error\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tShutdown audio decoder and free resources\r\n *\r\n * \\param cbFree\r\n *\t\tPointer to a fucntion to be used to free the allocated memory\r\n *\r\n ******************************************************************************\r\n */\r\nvoid VIDSimpleExitAudioDecoder(void)\r\n\t{\r\n\t// Any audio?\r\n\tif (player.audioInfo.audioID != VID_FCC('N','O','N','E'))\r\n\t\t{\r\n\t\t// Yes. Unregister callback & stop AI DMA\r\n\t\tBOOL old = OSDisableInterrupts();\r\n\t\t\r\n\t\tAXRegisterCallback(NULL);\r\n\t\tAXSetVoiceState(axVoice[0],AX_PB_STATE_STOP);\r\n\t\tAXSetVoiceState(axVoice[1],AX_PB_STATE_STOP);\r\n\t\tAXFreeVoice(axVoice[0]);\r\n\t\tAXFreeVoice(axVoice[1]);\r\n\t\t\r\n\t\taxVoice[0] = axVoice[1] = NULL;\r\n\t\t\r\n\t\tOSRestoreInterrupts(old);\r\n\t\t\r\n\t\t// Any codec related resources should be freed, too\r\n\t\t// [...]\r\n\t\t\r\n\t\t// Free allocated resources...\r\n\t\tplayer.cbFree(audioPlayBuffer[0]);\r\n\t\tplayer.cbFree(audioReadBuffer);\r\n\t\t}\r\n\t}\r\n\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tStop audio playback without shutting down AI etc.\r\n *\r\n ******************************************************************************\r\n */\r\nvoid VIDSimpleAudioReset(void)\r\n\t{\r\n\tBOOL\told;\r\n\t\r\n\tif (player.audioInfo.audioID != VID_FCC('N','O','N','E'))\r\n\t\t{\r\n\t\told = OSDisableInterrupts();\r\n\t\t\r\n\t\taudioReadBufferWritePos = 0;\r\n\t\taudioReadBufferReadPos = 0;\r\n\t\t\r\n\t\taudioPlayBufferEnabled = FALSE;\r\n\t\taudioPlayBackPossible = FALSE;\r\n\t\t\r\n\t\t// ADPCM?\r\n\t\tif (player.audioInfo.audioID != VID_FCC('A','P','C','M'))\r\n\t\t\t{\r\n\t\t\t// [...]\r\n\t\t\t}\r\n\t\telse\r\n\t\t\t{\r\n\t\t\t// Other codecs could reset their state right here...\r\n\t\t\t// [...]\r\n\t\t\t}\r\n\t\t\t\r\n\t\tOSRestoreInterrupts(old);\r\n\t\t}\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tReturn some information about current audio stream.\r\n *\r\n ******************************************************************************\r\n */\r\nvoid VIDSimpleAudioGetInfo(VidAUDH* audioHeader)\r\n\t{\r\n\tASSERT(audioHeader);\r\n\tmemcpy(audioHeader, &player.audioInfo, sizeof(*audioHeader));\r\n    }\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\t'Decode' PCM16 to PCM16\r\n *\r\n *\t\tThis function simply copies over new PCM16 samples into the read buffer.\r\n *\t\tOther codecs might use a more elaborate decoding of course ;-)\r\n *\r\n ******************************************************************************\r\n */\r\nstatic void VIDSimpleDoAudioDecodePCM16(s16* dest, u32 channels, const s16** samples, u32 sampleOffset, u32 sampleNum)\r\n\t{\r\n\tu32\t\ti,b,s;\r\n    u32 \t\tbytes  = VIDSimpleAudioBytesFromSamplesPCM16(sampleNum);\r\n\tconst void*\tsrc    = (const u8*)samples[0] + VIDSimpleAudioBytesFromSamplesPCM16(sampleOffset);\r\n\t\r\n\t// Do we have any playback masks?\r\n\tif (audioNumPlayMasks != 0)\r\n\t\t{\r\n\t\t// Yes! How many samples?\r\n\t\tu32 numSamples = bytes / (player.audioInfo.pcm16.numChannels * sizeof(s16));\r\n\t\t\r\n\t\t// Scan through all playback masks and update channels as they come\r\n\t\tu32 c = 0;\r\n\t\tu32 rc = 0;\r\n\t\tfor(i=0; i<audioNumPlayMasks; i++)\r\n\t\t\t{\r\n\t\t\tfor(b=0; b<32; b++)\r\n\t\t\t\t{\r\n\t\t\t\tif (audioPlayMaskArray[i] & (1<<b))\r\n\t\t\t\t\t{\r\n\t\t\t\t\tfor(s=0; s<numSamples; s++)\r\n\t\t\t\t\t\tdest[s * audioReadBufferNumChannels + c] = ((s16 *)src)[s * player.audioInfo.pcm16.numChannels + rc];\r\n\t\t\t\t\tc++;\r\n\t\t\t\t\t\r\n\t\t\t\t\t// If we already updated all read buffer channels we may exit. There's no more space anyways...\r\n\t\t\t\t\tif (c == audioReadBufferNumChannels)\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\trc++;\r\n\t\t\t\t\r\n\t\t\t\t// If we already read from all channels in the source, we can exit, too...\r\n\t\t\t\tif (rc == player.audioInfo.pcm16.numChannels)\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\telse\r\n\t\t{\r\n\t\t// We should use all channels we got. Okay, memcpy everything...\r\n\t\tmemcpy(dest,src,bytes);\r\n\t\t}\r\n\t}\r\n\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tMisc conversion fucntions for PCM16 stream data\r\n *\r\n ******************************************************************************\r\n */\r\nstatic u32 VIDSimpleAudioBytesFromSamplesPCM16(u32 samples)\r\n\t{\r\n\treturn(samples * sizeof(s16) * player.audioInfo.pcm16.numChannels);\r\n\t}\r\n\r\nstatic u32 VIDSimpleAudioSamplesFromBytesPCM16(u32 bytes)\r\n\t{\r\n\treturn(bytes / (sizeof(s16) * player.audioInfo.pcm16.numChannels));\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tDecode VAUD Data.\r\n *\r\n *\t\tThis function simply interleaves two channels from from the\r\n *\t\taudio decoder output into the required format.\r\n *\r\n ******************************************************************************\r\n */\r\nstatic void VIDSimpleDoAudioDecodeVAUD(s16* dest, u32 channels, const s16** samples, u32 sampleOffset, u32 sampleNum)\r\n\t{\r\n\tu32 j;\r\n\tif(channels == 1)\r\n\t\t{\r\n\t\tconst s16* in = samples[0] + sampleOffset;\r\n\t\tfor(j = 0; j < sampleNum; j++)\r\n\t\t\t{\r\n\t\t\t*dest++ = in[j];\r\n\t\t\t*dest++ = in[j];\r\n\t\t\t}\r\n\t\t}\r\n\telse\r\n\t\t{\r\n\t\tconst s16* inL = samples[0] + sampleOffset;\r\n\t\tconst s16* inR = samples[1] + sampleOffset;\r\n\t\tASSERT(channels == 2);\r\n\t\tfor(j = 0; j < sampleNum; j++)\r\n\t\t\t{\r\n\t\t\t*dest++ = *inL++;\r\n\t\t\t*dest++ = *inR++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tMisc conversion fucntions for VAUD stream data\r\n *\r\n ******************************************************************************\r\n */\r\nstatic u32 VIDSimpleAudioBytesFromSamplesVAUD(u32 samples)\r\n\t{\r\n\treturn(samples * sizeof(s16) * player.audioInfo.pcm16.numChannels);\r\n\t}\r\n\r\nstatic u32 VIDSimpleAudioSamplesFromBytesVAUD(u32 bytes)\r\n\t{\r\n\treturn(bytes / (sizeof(s16) * player.audioInfo.pcm16.numChannels));\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tMain audio data decode function.\r\n *\r\n *\t\tThis function will be used as a callback from the VIDAudioDecode\r\n *\t\tfunction or is called directely in case of PCM or ADPCM.\r\n *\r\n * \\param numChannels\r\n *\t\tNumber of channels present in the sample array\r\n *\r\n * \\param samples\r\n *\t\tArray of s16 pointers to the sample data \r\n *\r\n * \\param sampleNum\r\n *\t\tNumber of samples in the array. All arrays have the same amount\r\n *\t\tof sample data\r\n *\r\n * \\param userData\r\n *\t\tSome user data\r\n *\r\n * \\return\r\n *\t\tFALSE if data could not be interpreted properly\r\n *\r\n ******************************************************************************\r\n */\r\nstatic BOOL audioDecode(u32 numChannels, const s16 **samples, u32 sampleNum, void* userData)\r\n\t{\r\n\tu32\t\tfreeSamples;\r\n\tu32\t\tsampleSize;\r\n\tu32\t\tlen1;\r\n\tBOOL\told;\r\n\t\r\n\t// we can only play mono or stereo!\r\n\tASSERT(numChannels <= 2);\r\n\r\n\t// Disable IRQs. We must make sure we don't get interrupted by the AI callback.\r\n\told = OSDisableInterrupts();\r\n\r\n\t// Did the video decoder just jump back to the beginning of the stream?\r\n\tif (player.readBuffer[player.decodeIndex].frameNumber < player.lastDecodedFrame)\r\n\t\t{\r\n\t\t// Yes! We have to reset the internal read buffer and disable any audio output\r\n\t\t// until we got new video data to display...\r\n\t\t//\r\n\t\t// Note: we have to reset our buffers because the stream contains more audio data than\r\n\t\t// neccessary to cover a single video frame within the first few frames to accumulate\r\n\t\t// some safety buffer. If the stream would just be allowed to loop we would get an\r\n\t\t// overflow (unless we used up the extra buffer due to read / decode delays) after a few\r\n\t\t// loops...\r\n\t\t//\r\n\t\tVIDSimpleAudioReset();\r\n\t\t}\r\n\t\r\n\t// Calculate the read buffer's sample size\r\n\tsampleSize = sizeof(s16) * audioReadBufferNumChannels;\r\n\t\r\n\t// How many samples could we put into the buffer?\r\n\tif (audioReadBufferWritePos >= audioReadBufferReadPos)\r\n\t\t{\r\n\t\tfreeSamples = audioReadBufferNumSamples - (audioReadBufferWritePos - audioReadBufferReadPos);\r\n\t\t\r\n\t\tif (freeSamples < sampleNum)\r\n\t\t\t{\r\n\t\t\tOSRestoreInterrupts(old);\r\n\t\t\t#ifndef FINAL\r\n\t\t\tOSReport(\"*** audioDecode: overflow\\n\");\r\n\t\t\t#endif\r\n\t\t\treturn FALSE;\t\t\t\t// overflow!\r\n\t\t\t}\r\n\t\t\r\n\t\t// We might have a two buffer update to do. Check for it...\r\n\t\tif ((len1 = (audioReadBufferNumSamples - audioReadBufferWritePos)) >= sampleNum)\r\n\t\t\t{\r\n\t\t\t// No. We got ourselfs a nice, simple single buffer update.\r\n\t\t\tVIDSimpleDoAudioDecode((s16 *)((u32)audioReadBuffer + audioReadBufferWritePos * sampleSize),numChannels,samples,0,sampleNum);\r\n\t\t\t}\r\n\t\telse\r\n\t\t\t{\r\n\t\t\t// Dual buffer case\r\n\t\t\tVIDSimpleDoAudioDecode((s16 *)((u32)audioReadBuffer + audioReadBufferWritePos * sampleSize),numChannels,samples,0,len1);\r\n\t\t\tVIDSimpleDoAudioDecode((s16 *)audioReadBuffer,numChannels,samples,len1,sampleNum-len1);\r\n\t\t\t}\r\n\t\t}\r\n\telse\r\n\t\t{\r\n\t\tfreeSamples = audioReadBufferReadPos - audioReadBufferWritePos;\r\n\t\t\r\n\t\tif (freeSamples < sampleNum)\r\n\t\t\t{\r\n\t\t\tOSRestoreInterrupts(old);\r\n\t\t\t#ifndef FINAL\r\n\t\t\tOSReport(\"*** audioDecode: overflow\\n\");\r\n\t\t\t#endif\r\n\t\t\treturn FALSE;\t\t\t\t// overflow!\r\n\t\t\t}\r\n            // We're save to assume to have a single buffer update in any case...\r\n\t\t\tVIDSimpleDoAudioDecode((s16 *)((u32)audioReadBuffer + audioReadBufferWritePos * sampleSize),numChannels,samples,0,sampleNum);\r\n\t\t}\r\n\r\n\t// Advance write position...\r\n\taudioReadBufferWritePos += sampleNum;\r\n\t\t\r\n\tif (audioReadBufferWritePos >= audioReadBufferNumSamples)\r\n\t\taudioReadBufferWritePos -= audioReadBufferNumSamples;\r\n\t\t\r\n\t// We're done with all critical stuff. IRQs may be enabled again...\r\n\tOSRestoreInterrupts(old);\r\n\t\t\r\n\treturn TRUE;\r\n\t}\r\n\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tReceive data from bitstream and direct to required encoding facility\r\n *\r\n *\t\tThis function will receive the AUDD chunck from the VIDSimplePlayer's\r\n *\t\tdecode function. \r\n *\r\n * \\param bitstream\r\n *\t\tPointer to the data of a AUDD chunk\r\n *\r\n * \\param bitstreamLen\r\n *\t\tLength of the data in the AUDD chunk pointed to by above pointer\r\n *\r\n * \\return\r\n *\t\tFALSE if data could not be interpreted properly\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL VIDSimpleAudioDecode(const u8* bitstream, u32 bitstreamLen)\r\n\t{\r\n\t// Any audio data present?\r\n\tif (player.audioInfo.audioID != VID_FCC('N','O','N','E'))\r\n\t\t{\r\n        // Select requested audio decoding method\r\n        if(player.audioInfo.audioID == VID_FCC('V','A','U','D'))\r\n\t\t\t{\r\n\t\t\tu32 headerSize = ((VidAUDDVAUD*)bitstream)->size;\r\n\t\t\t// a channel mask if 0x3 selects the first two channels...\r\n\t\t\tif(!VIDAudioDecode(player.decoder, bitstream+headerSize, bitstreamLen-headerSize, 0x3, audioDecode, NULL))\r\n\t\t\t\treturn FALSE;\r\n\t\t\t\r\n\t\t\t}\r\n\t\telse\r\n\t\t\t{\r\n\t\t\t// Calc data and call audio decode callback by ourself\r\n\t\t\tconst u8* data = bitstream + sizeof(u32);\r\n\t\t\tu32 dataLength = *(const u32 *)bitstream;\r\n\t\t\t\r\n\t\t\t// We always assume 1 source data pointer\r\n\t\t\tif(!audioDecode(1, (const s16**)&data, VIDSimpleAudioSamplesFromBytes(dataLength), NULL))\r\n\t\t\t\treturn FALSE;\r\n\r\n\t\t\t}\r\n\t\taudioPlayBackPossible = TRUE;\r\n\t\t}\r\n\treturn TRUE;\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tEnable AI playback (within about 5ms)\r\n *\r\n ******************************************************************************\r\n */\r\n\t\t\t\t\r\nvoid VIDSimpleAudioStartPlayback(const u32 *playMaskArray,u32 numMasks)\r\n\t{\r\n\tBOOL old = OSDisableInterrupts();\r\n\t\r\n\tif (audioPlayBackPossible)\r\n\t\t{\r\n\t\taudioPlayBufferEnabled = TRUE;\r\n\t\t\r\n\t\tVIDSimpleAudioChangePlayback(playMaskArray,numMasks);\r\n\t\t}\r\n\t\r\n\tOSRestoreInterrupts(old);\r\n\t}\r\n\t\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tChange the active audio channels\r\n *\r\n ******************************************************************************\r\n */\r\n\t\t\t\t\r\nvoid VIDSimpleAudioChangePlayback(const u32 *playMaskArray,u32 numMasks)\r\n\t{\r\n\tu32\t\ti,b;\r\n\tBOOL\told = OSDisableInterrupts();\r\n\t\r\n\taudioPlayMaskArray = playMaskArray;\r\n\taudioNumPlayMasks = numMasks;\r\n\t\r\n\t// Any playback mask specified?\r\n\tif (audioNumPlayMasks != 0)\r\n\t\t{\r\n\t\t// Yes. Count the active voices...\r\n\t\taudioNumActiveVoices = 0;\r\n\t\t\r\n\t\tfor(i=0; i<numMasks; i++)\r\n\t\t\t{\r\n\t\t\tfor(b=0; b<32; b++)\r\n\t\t\t\t{\r\n\t\t\t\tif (audioPlayMaskArray[i] & (1<<b))\r\n\t\t\t\t\taudioNumActiveVoices++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\r\n\t\t// So, did we have too much?\r\n\t\tASSERT(audioNumActiveVoices <= 2);\r\n\t\t}\r\n\telse\r\n\t\taudioNumActiveVoices = audioReadBufferNumChannels;\t\t// Make all active...\r\n\t\r\n\tOSRestoreInterrupts(old);\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tCopy PCM16 data from the read buffer into the audio buffer\r\n *\r\n *\t\tThis function serves as an internal service function to make sure\r\n *\t\tmono and stereo audio data gets properly converted into audio buffer\r\n *\t\tformat.\r\n *\r\n * \\param smpOffset\r\n *\t\tOffset in samples into the current write buffer\r\n *\r\n * \\param numSamples\r\n *\t\tNumber of samples to be updated / copied\r\n *\r\n ******************************************************************************\r\n */\r\nstatic void audioCopy(u32 smpOffset,u32 numSamples)\r\n\t{\r\n\ts16\t\t*destAddrL,*destAddrR,*srcAddr,s;\r\n\tu32\t\tj;\r\n\t\r\n\t// Target address in audio buffer\r\n\tdestAddrL = (s16 *)((u32)audioPlayBuffer[audioPlayBufferWriteIndex] + smpOffset * sizeof(s16));\r\n\tdestAddrR = (s16 *)((u32)audioPlayBuffer[audioPlayBufferWriteIndex] + smpOffset * sizeof(s16) + (VID_AUDIO_AIBUFFERSAMPLES * sizeof(s16)));\r\n\r\n\t// Single or dual channel setup?\r\n    if (audioReadBufferNumChannels == 2)\r\n\t\t{\r\n\t\t// Stereo! Get source address of data...\r\n\t\tsrcAddr = (s16 *)((u32)audioReadBuffer + audioReadBufferReadPos * 2 * sizeof(s16));\r\n\t\t\r\n\t\t// Copy samples into AI buffer and swap channels\r\n\t\tfor(j=0; j<numSamples; j++)\r\n\t\t\t{\r\n\t\t\t*(destAddrL++) = *(srcAddr++);\r\n\t\t\t*(destAddrR++) = *(srcAddr++);\r\n\t\t\t}\r\n\t\t}\r\n\telse\r\n\t\t{\r\n\t\t// Mono case!\r\n\t\t\r\n\t\t// Make sure it's truely mono!\r\n\t\tASSERT(audioReadBufferNumChannels == 1);\r\n\t\t\r\n\t\t// Get source address...\r\n\t\tsrcAddr = (s16 *)((u32)audioReadBuffer + audioReadBufferReadPos * sizeof(s16));\r\n\t\t\r\n\t\t// Copy samples into AI buffer (AI is always stereo, so we have to dublicate data)\r\n\t\tfor(j=0; j<numSamples; j++)\r\n\t\t\t{\r\n\t\t\ts = (*srcAddr++);\r\n\t\t\t*(destAddrL++) = s;\r\n\t\t\t*(destAddrR++) = s;\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t// Advance read position as needed...\r\n\taudioReadBufferReadPos += numSamples;\r\n\tif (audioReadBufferReadPos >= audioReadBufferNumSamples)\r\n\t\taudioReadBufferReadPos -= audioReadBufferNumSamples;\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tAX callback\r\n *\r\n ******************************************************************************\r\n */\r\nstatic void AXCallback(void)\r\n\t{\r\n\tu32\t\tavailSamples,availFrames,numUpdate,i,n;\r\n\tu32\t\taudioPlayBufferNeededAudioFrames;\r\n\tu32\t\tcurrentAddr;\r\n\tu32\t\tleftSource, rightSource, leftTarget, rightTarget;\r\n\r\n\t// First thing to do here is call the regular soundfx callback.\r\n\tSfx::AXUserCBack();\r\n\t\r\n\t// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\r\n\t\r\n\tif (axPhase == AX_PHASE_START)\r\n\t{\r\n\t\tAXSetVoiceState(axVoice[0],AX_PB_STATE_RUN);\r\n\t\tAXSetVoiceState(axVoice[1],AX_PB_STATE_RUN);\r\n\t\taxPhase = AX_PHASE_PLAY;\r\n\t}\r\n\telse if( axPhase == AX_PHASE_PLAY )\r\n\t{\r\n\t\tif( axVoice[0]->pb.state == AX_PB_STATE_STOP )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\t\r\n\t// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\r\n\t\r\n\tcurrentAddr = *(u32 *)&axVoice[0]->pb.addr.currentAddressHi;\r\n\r\n\tif (currentAddr >= axLastAddr)\r\n\t\taxPlayedSamples += currentAddr - axLastAddr;\r\n\telse\r\n\t\taxPlayedSamples += ((AX_ARAM_LEFT_CHANNEL + AX_ARAM_BUFFER_SIZE) - axLastAddr) + (currentAddr - AX_ARAM_LEFT_CHANNEL);\r\n\t\t\r\n\taxLastAddr = currentAddr;\r\n\r\n\t//OSReport(\"%d\\n\",axPlayedSamples);\r\n\t\t\r\n\tif (axPlayedSamples >= VID_AUDIO_AIBUFFERSAMPLES)\r\n\t{\r\n\t\taudioPlayBufferNeededAudioFrames = axPlayedSamples / VID_AUDIO_AIBUFFERSAMPLES;\r\n\r\n\t\t// Make sure that we never get an underrun we don't notice...\r\n\t\tif(!(audioPlayBufferNeededAudioFrames <= VID_AUDIO_NUMAIBUFFERS))\r\n\t\t{\r\n//\t\t\tOSReport(\"AX audio buffer underrun!\\n\");\r\n\t\t\taudioPlayBufferEnabled = false;\r\n\t\t}\r\n\t\t\r\n\t\t//ASSERT(audioPlayBufferNeededAudioFrames <= VID_AUDIO_NUMAIBUFFERS);\r\n\r\n\t\t// Is actual audio playback enabled?\r\n\t\tif (audioPlayBufferEnabled)\r\n\t\t{\r\n\t\t\t// How many samples could we get from the read buffer?\r\n\t\t\tif (audioReadBufferWritePos >= audioReadBufferReadPos)\r\n\t\t\t\tavailSamples = audioReadBufferWritePos - audioReadBufferReadPos;\r\n\t\t\telse\r\n\t\t\t\tavailSamples = audioReadBufferNumSamples - (audioReadBufferReadPos - audioReadBufferWritePos);\r\n\t\t\t\r\n\t\t\t// That's how many audio frames?\r\n\t\t\tavailFrames = availSamples / VID_AUDIO_AIBUFFERSAMPLES;\r\n    \r\n\t\t\t// Are the voice already playing?\r\n\t\t\tif (axPhase == AX_PHASE_PLAY)\r\n\t\t\t{\r\n\t\t\t\tf32 targetFrq;\r\n\t\t\t\t\r\n\t\t\t\t// Yes. We better watch out for the buffer status, so we don't get under-runs...\r\n\t\t\t\tif (availFrames < axMinAvailFrames)\r\n\t\t\t\t\ttargetFrq = audioPlayBufferFrq * (1.0f - (1.0f/200.0f) * (axMinAvailFrames - availFrames));\r\n\t\t\t\telse\r\n\t\t\t\t\ttargetFrq = (f32)audioPlayBufferFrq;\r\n\t\t\t\t\r\n\t\t\t\t// Track the target frequency quite slowly to avoid audible artifacts\r\n                if (axCurrentFrq < targetFrq)\r\n\t\t\t\t{\r\n\t\t\t\t\taxCurrentFrq += audioPlayBufferFrq * 0.00125f;\r\n\t\t\t\t\tif (axCurrentFrq > targetFrq)\r\n\t\t\t\t\t\taxCurrentFrq = targetFrq;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\taxCurrentFrq -= audioPlayBufferFrq * 0.00125f;\r\n\t\t\t\t\tif (axCurrentFrq < targetFrq)\r\n\t\t\t\t\t\taxCurrentFrq = targetFrq;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t//OSReport(\"%d %f (%d)\\n\",availFrames,axCurrentFrq,axMinAvailFrames);\r\n\t\t\t\t\t\r\n\t\t\t\t// Set frequency\r\n\t\t\t\tAXSetVoiceSrcRatio(axVoice[0],axCurrentFrq / (f32)AX_IN_SAMPLES_PER_SEC);\r\n\t\t\t\tAXSetVoiceSrcRatio(axVoice[1],axCurrentFrq / (f32)AX_IN_SAMPLES_PER_SEC);\r\n\t\t\t}\r\n\r\n\t\t\t//OSReport(\"AX: %d %d (%d)\\n\",availSamples,audioPlayBufferNeededAudioFrames * VID_AUDIO_AIBUFFERSAMPLES,axPlayedSamples);\r\n\t\r\n\t\t\t// So, how many can we update?\r\n\t\t\tnumUpdate = (availFrames > audioPlayBufferNeededAudioFrames) ? audioPlayBufferNeededAudioFrames : availFrames;\r\n\t\r\n\t\t\t// If anything... go do it!\r\n\t\t\tif (numUpdate != 0)\r\n\t\t\t{\r\n\t\t\t\taxPlayedSamples -= numUpdate * VID_AUDIO_AIBUFFERSAMPLES;\r\n\t\t\t\t\r\n\t\t\t\t// Perform updates on each AI buffer in need of data...\r\n\t\t\t\tfor(i=0; i<numUpdate; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Can we copy everything from a single source or does the data wrap around?\r\n\t\t\t\t\tif ((n = audioReadBufferNumSamples - audioReadBufferReadPos) < VID_AUDIO_AIBUFFERSAMPLES)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// It wraps...\r\n\t\t\t\t\t\taudioCopy(0,n);\r\n\t\t\t\t\t\taudioCopy(n,VID_AUDIO_AIBUFFERSAMPLES - n);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// We got one continous source buffer\r\n\t\t\t\t\t\taudioCopy(0,VID_AUDIO_AIBUFFERSAMPLES);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t// Make sure the data ends up in real physical memory\r\n\t\t\t\t\tDCFlushRange(audioPlayBuffer[audioPlayBufferWriteIndex],VID_AUDIO_AIBUFFERSAMPLES * sizeof(s16) * 2);\r\n\t\t\t\t\t\r\n\t\t\t\t\tleftSource = (u32)audioPlayBuffer[audioPlayBufferWriteIndex];\r\n\t\t\t\t\trightSource = (u32)audioPlayBuffer[audioPlayBufferWriteIndex] + (VID_AUDIO_AIBUFFERSAMPLES * sizeof(s16));\r\n\t\t\t\t\tleftTarget = 2 * (AX_ARAM_LEFT_CHANNEL + audioPlayBufferWriteIndex * VID_AUDIO_AIBUFFERSAMPLES);\r\n\t\t\t\t\trightTarget = 2 * (AX_ARAM_RIGHT_CHANNEL + audioPlayBufferWriteIndex * VID_AUDIO_AIBUFFERSAMPLES);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Make sure we get this into ARAM ASAP...\r\n\t\t\t\t\tARQPostRequest(&arqRequest[0][i%VID_AUDIO_NUMAIREQUESTS],0,ARQ_TYPE_MRAM_TO_ARAM,ARQ_PRIORITY_HIGH,leftSource,leftTarget,VID_AUDIO_AIBUFFERSAMPLES * sizeof(s16),NULL);\r\n\t\t\t\t\tARQPostRequest(&arqRequest[1][i%VID_AUDIO_NUMAIREQUESTS],1,ARQ_TYPE_MRAM_TO_ARAM,ARQ_PRIORITY_HIGH,rightSource,rightTarget,VID_AUDIO_AIBUFFERSAMPLES * sizeof(s16),NULL);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Advance write index...\r\n\t\t\t\t\taudioPlayBufferWriteIndex = (u8)((audioPlayBufferWriteIndex + 1) % VID_AUDIO_NUMAIBUFFERS);\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (axPhase == AX_PHASE_STARTUP)\r\n\t\t\t\t\taxPhase = AX_PHASE_START;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Update buffer(s) with silence...\r\n\t\t\taxPlayedSamples -= audioPlayBufferNeededAudioFrames * VID_AUDIO_AIBUFFERSAMPLES;\r\n\t\t\t\r\n\t\t\tfor(i=0; i<audioPlayBufferNeededAudioFrames; i++)\r\n\t\t\t{\r\n\t\t\t\tmemset(audioPlayBuffer[audioPlayBufferWriteIndex],0,2 * sizeof(s16) * VID_AUDIO_AIBUFFERSAMPLES);\r\n\t\t\t\tDCFlushRange(audioPlayBuffer[audioPlayBufferWriteIndex],2 * sizeof(s16) * VID_AUDIO_AIBUFFERSAMPLES);\r\n\t\r\n\t\t\t\tleftSource = (u32)audioPlayBuffer[audioPlayBufferWriteIndex];\r\n\t\t\t\trightSource = (u32)audioPlayBuffer[audioPlayBufferWriteIndex] + (VID_AUDIO_AIBUFFERSAMPLES * sizeof(s16)) / 2;\r\n\t\t\t\tleftTarget = 2 * (AX_ARAM_LEFT_CHANNEL + audioPlayBufferWriteIndex * VID_AUDIO_AIBUFFERSAMPLES);\r\n\t\t\t\trightTarget = 2 * (AX_ARAM_RIGHT_CHANNEL + audioPlayBufferWriteIndex * VID_AUDIO_AIBUFFERSAMPLES);\r\n\t\t\t\t\r\n\t\t\t\t// Make sure we get this into ARAM ASAP...\r\n\t\t\t\tARQPostRequest(&arqRequest[0][i%VID_AUDIO_NUMAIREQUESTS],0,ARQ_TYPE_MRAM_TO_ARAM,ARQ_PRIORITY_HIGH,leftSource,leftTarget,VID_AUDIO_AIBUFFERSAMPLES * sizeof(s16),NULL);\r\n\t\t\t\tARQPostRequest(&arqRequest[1][i%VID_AUDIO_NUMAIREQUESTS],1,ARQ_TYPE_MRAM_TO_ARAM,ARQ_PRIORITY_HIGH,rightSource,rightTarget,VID_AUDIO_AIBUFFERSAMPLES * sizeof(s16),NULL);\r\n\t\t\t\t\r\n\t\t\t\taudioPlayBufferWriteIndex = (u8)((audioPlayBufferWriteIndex + 1) % VID_AUDIO_NUMAIBUFFERS);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (axPhase == AX_PHASE_STARTUP)\r\n\t\t\t\taxPhase = AX_PHASE_START;\r\n\t\t}\r\n\t}\r\n}\r\n\t\r\n//############################################################################\r\n//##                                                                        ##\r\n//## Main entry point to the this example application.                      ##\r\n//##                                                                        ##\r\n//############################################################################\r\n\r\n#endif\t\t// DVDETH\r\n\r\nnamespace Flx\r\n{\r\n\r\nvoid PMovies_PlayMovie( const char *pName )\r\n{\r\n\tNsDisplay::setBackgroundColor( (GXColor){0,0,0,0} );\r\n\tswitch (VIGetTvFormat())\r\n\t{\r\n\t\tcase VI_PAL:\r\n\t\tcase VI_DEBUG_PAL:\r\n\t\t\tif ( !NxNgc::EngineGlobals.use_60hz )\r\n\t\t\t{\r\n\t\t\t\trmode->viYOrigin = 0;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\tVISetBlack( TRUE );\r\n    VIConfigure(rmode);\r\n    VIFlush();\r\n    VIWaitForRetrace();\r\n\r\n\tg_legal = false;\r\n\r\n\tunsigned short last = ( padData[0].button | padData[1].button );\r\n\r\n\tPcm::StopMusic();\r\n\r\n#\tifndef DVDETH\r\n//\tGXRenderModeObj *rmode;\t//, demoMode;\r\n\tu32\t\tvideoWidth, videoHeight;\r\n\ts32\t\tsurfaceX, surfaceY;\r\n\ts32\t\tsurfaceWidth, surfaceHeight;\r\n//\tu16 \tbuttonsDown;\r\n\tf64\t\ttotalTime = 0.0;\r\n\tf64\t\tidealTime = 0.0;\r\n\tf32\t\tidealTimeInc;\r\n\tBOOL\tfirst = TRUE;\r\n\tBOOL \txfbMode = FALSE;\r\n\r\n#\tifdef USE_DIRECT_XFB\r\n\txfbMode = TRUE;\r\n#\tendif\r\n\r\n\tOSInitFastCast();\r\n\r\n\r\n\r\n\t// Reset a bunch of GX state.\r\n\r\n\t// Color definitions\r\n\t\r\n\t#define GX_DEFAULT_BG (GXColor){64, 64, 64, 255}\r\n\t#define BLACK (GXColor){0, 0, 0, 0}\r\n\t#define WHITE (GXColor){255, 255, 255, 255}\r\n\t\r\n\t//\r\n\t// Render Mode\r\n\t//\r\n\t// (set 'rmode' based upon VIGetTvFormat(); code not shown)\r\n\t\r\n\t//\r\n\t// Geometry and Vertex\r\n\t//\r\n\tGXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TEX2, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD3, GX_TG_MTX2x4, GX_TG_TEX3, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD4, GX_TG_MTX2x4, GX_TG_TEX4, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD5, GX_TG_MTX2x4, GX_TG_TEX5, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD6, GX_TG_MTX2x4, GX_TG_TEX6, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD7, GX_TG_MTX2x4, GX_TG_TEX7, GX_IDENTITY);\r\n\tGXSetNumTexGens(1);\r\n\tGXSetCurrentMtx(GX_PNMTX0);\r\n\tGXSetCullMode(GX_CULL_BACK);\r\n\tGXSetClipMode(GX_CLIP_ENABLE);\r\n\tGXSetNumChans(0); // no colors by default\r\n\t\r\n\tGXSetChanCtrl(\r\n\tGX_COLOR0A0,\r\n\tGX_DISABLE,\r\n\tGX_SRC_REG,\r\n\tGX_SRC_VTX,\r\n\tGX_LIGHT_NULL,\r\n\tGX_DF_NONE,\r\n\tGX_AF_NONE );\r\n\t\r\n\tGXSetChanAmbColor(GX_COLOR0A0, BLACK);\r\n\tGXSetChanMatColor(GX_COLOR0A0, WHITE);\r\n\t\r\n\tGXSetChanCtrl(\r\n\tGX_COLOR1A1,\r\n\tGX_DISABLE,\r\n\tGX_SRC_REG,\r\n\tGX_SRC_VTX,\r\n\tGX_LIGHT_NULL,\r\n\tGX_DF_NONE,\r\n\tGX_AF_NONE );\r\n\t\r\n\tGXSetChanAmbColor(GX_COLOR1A1, BLACK);\r\n\tGXSetChanMatColor(GX_COLOR1A1, WHITE);\r\n\t\r\n\tGXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD2, GX_TEXMAP2, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD3, GX_TEXMAP3, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE4, GX_TEXCOORD4, GX_TEXMAP4, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE5, GX_TEXCOORD5, GX_TEXMAP5, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE6, GX_TEXCOORD6, GX_TEXMAP6, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE7, GX_TEXCOORD7, GX_TEXMAP7, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE8, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE9, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE10,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE11,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE12,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE13,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE14,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE15,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetNumTevStages(1);\r\n\tGXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);\r\n\tGXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);\r\n\tfor ( int i = GX_TEVSTAGE0; i < GX_MAX_TEVSTAGE; i++) {\r\n\tGXSetTevKColorSel((GXTevStageID) i, GX_TEV_KCSEL_1_4 );\r\n\tGXSetTevKAlphaSel((GXTevStageID) i, GX_TEV_KASEL_1 );\r\n\tGXSetTevSwapMode ((GXTevStageID) i, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t}\r\n\r\n\r\n\r\n\r\n\r\n//\tdemoMode = GXNtsc480IntDf;\r\n//\tdemoMode.fbWidth   = 640; //512;\r\n//\t\r\n//\t_DEMOInit(&demoMode, xfbMode);\r\n//\t\r\n//\t// Init AI interface in case we got audio data\r\n//\tif ( !AICheckInit() ) AIInit(NULL);\r\n//\tif ( !ARCheckInit() ) ARInit(NULL,0);\r\n//\tif ( !ARQCheckInit() ) ARQInit();\r\n//\tAXInit();\r\n\r\n\t// If we want to use the 'Locked Cache', we need to enable it here!\r\n\t// The usage of 'Locked Cache' is optional, but speeds up decoding time a little bit\r\n\tLCEnable();\r\n\tlcMemBase = (u8*)LCGetBase();\r\n\t\r\n\t// In xfb mode, we need some memory for the conversion stuff.\r\n\t// We offset our locked cache 'base addr' by the required number of bytes!\r\n\t// NOTE: This mem is only used TEMPORARY during the VIDXFBDraw() function!\r\n\tif(xfbMode)\r\n\t\t{\r\n\t\txfbLCStart = lcMemBase;\r\n\t\tlcMemBase += VIDXFBGetLCSize();\r\n\t\t}\r\n\r\n//\trmode = DEMOGetRenderModeObj();\r\n\r\n\tVIDSimpleInit(myAlloc, myFree, myAllocFromLC);\r\n\r\n//\tif (VIDSimpleOpen(VIDEO_FILENAME, FALSE) == FALSE)\r\n\r\n\r\n\r\n\r\n\t// Incoming movie name is in the form movies\\<name>, convert to movies/vid\\<name>.vid.\r\n\tchar name_conversion_buffer[256] = \"movies/vid/\";\r\n\tint length\t\t= strlen( pName );\r\n\tint backwards\t= length;\r\n\twhile( backwards )\r\n\t{\r\n\t\tif( pName[backwards] == '\\\\' )\r\n\t\t{\r\n\t\t\t++backwards;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t--backwards;\r\n\t}\r\n\tstrncpy( name_conversion_buffer + 11, pName + backwards, length - backwards );\r\n\tlength = strlen( name_conversion_buffer );\r\n\tname_conversion_buffer[length] = '.';\r\n\tname_conversion_buffer[length + 1] = 'v';\r\n\tname_conversion_buffer[length + 2] = 'i';\r\n\tname_conversion_buffer[length + 3] = 'd';\r\n\tname_conversion_buffer[length + 4] = 0;\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\tif (VIDSimpleOpen(name_conversion_buffer, FALSE) == FALSE) goto quit;\r\n//\t\tOSHalt(\"*** VIDSimpleOpen failed!\\n\");\r\n\r\n\tif (VIDSimpleAllocDVDBuffers() == FALSE)\r\n\t{\r\n\t\tVIDSimpleLoadStop();\r\n\t\tVIDSimpleClose();\r\n\r\n        goto quit;\r\n\t}\r\n//\t\tOSHalt(\"*** VIDSimpleAllocDVDBuffers failed!\\n\");\r\n\t\r\n\tif (VIDSimpleCreateDecoder(TRUE) == FALSE)\r\n\t{\r\n\t\tVIDSimpleLoadStop();\r\n\t\tVIDSimpleClose();\r\n\t\tVIDSimpleFreeDVDBuffers();\r\n\r\n        goto quit;\r\n\t}\r\n//\t\tOSHalt(\"*** VIDSimpleCreateDecoder failed!\\n\");\r\n\t\t\r\n\tif (VIDSimpleInitAudioDecoder())\r\n\t{\r\n\t\tVIDSimpleLoadStop();\r\n\t\tVIDSimpleClose();\r\n\t\tVIDSimpleFreeDVDBuffers();\r\n\t\tVIDSimpleDestroyDecoder();\r\n\r\n        goto quit;\r\n\t}\r\n//\t\tOSHalt(\"*** VIDSimpleInitAudioDecoder failed!\\n\");\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t// Preload all DVD buffers and set 'loop' mode\r\n//\tVIDSimpleLoadStart(TRUE);\r\n\tVIDSimpleLoadStart(FALSE);\r\n\r\n\tVIDSimpleGetVideoSize(&videoWidth, &videoHeight);\r\n\t\r\n\t// Calculate width and height to be used to display movie\r\n\tsurfaceWidth = rmode->fbWidth;\r\n\tsurfaceHeight = (s32)(videoHeight * ((f32)rmode->fbWidth / (f32)videoWidth));\r\n\t\r\n\t// Get the pixels \"square\"\r\n\tsurfaceHeight = (s32)(surfaceHeight * (640.0f / (f32)rmode->fbWidth));\t// assuming 480 vertical at all times!\r\n\t\r\n\t// Calculate offset to put it into the center of the screen\r\n\tsurfaceX = 0;\r\n\tsurfaceY = ((s32)rmode->xfbHeight - (s32)surfaceHeight) / 2;\r\n\tif (surfaceY < 0)\r\n\t\tsurfaceY = 0;\r\n\t\r\n//#ifdef MY_DEBUG\r\n//\tOSReport(\"Resolution: %dx%d\\n\",videoWidth,videoHeight);\r\n//\tOSReport(\"Display resolution: %dx%d\\n\",surfaceWidth,surfaceHeight);\r\n//\tOSReport(\"Rate: %f fps\\n\",VIDSimpleGetFPS());\r\n//\tOSReport(\"Frames: %d\\n\",VIDSimpleGetFrameCount());\r\n//\tVIDSimpleAudioGetInfo(&header);\r\n//\tif(header.audioID != VID_FCC('N','O','N','E'))\r\n//\t\t{\r\n//\t\tOSReport(\"Audio codec: %4s\\n\", &header.audioID);\r\n//\t\tOSReport(\"Channels: %d\\n\", (u32)header.pcm16.numChannels);\r\n//\t\tOSReport(\"Sample rate: %d Hz\\n\", header.pcm16.frq);\r\n//\t\t}\r\n//#endif\r\n\r\n\tidealTimeInc = 1000.0f / VIDSimpleGetFPS();\r\n\r\n\t\twhile (1)\r\n\t\t{\r\n\t\tOSTick startTicks;\r\n\t\r\n\t\tstartTicks = OSGetTick();\r\n\r\n\t\tVISetBlack( FALSE );\r\n\t\tNsDisplay::begin();\r\n\t\tNsRender::begin();\r\n//\t\t_DEMOBeforeRender();\r\n\t\t\r\n\t\t// Decode one frame\r\n\t\tif (VIDSimpleDecode() == FALSE)\r\n\t\t{\r\n\t\t\t// Decode failed, usually just due to the end of the movie being reached.\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// We deomstrate two different drawing methods\r\n\t\tif(!xfbMode)\r\n\t\t{\r\n\t\t\t// Render decoded frame as texture. YUV conversion is handled by hardware.\r\n\t\t\tVIDSimpleDraw(rmode, (u32)surfaceX, (u32)surfaceY, (u32)surfaceWidth, (u32)surfaceHeight);\r\n\t\t}\r\n\t\t\r\n\t\t// Wait for frame buffer swap to be done (we might have triggered one in the last loop)\r\n//\t\t_DEMOWaitFrameBuffer();\r\n\t\t\r\n\t\tif (xfbMode)\r\n\t\t\t{\r\n\t\t\t// Render image into the XFB immediately\r\n\t\t\tVIDSimpleDrawXFB(rmode, xfbLCStart);\r\n\t\t\t}\r\n\t\t\t\r\n\t\ts32 error;\r\n\t\terror = DVDGetDriveStatus();\r\n\t\tif ( ( error != DVD_STATE_END ) &&\r\n\t\t\t ( error != DVD_STATE_BUSY ) &&\r\n\t\t\t ( error != DVD_STATE_CANCELED ) &&\r\n\t\t\t ( error != DVD_STATE_PAUSING ) &&\r\n\t\t\t ( error != DVD_STATE_WAITING ) )\r\n\r\n\r\n\t\t\t{\r\n\t\t\t\tswitch (VIGetTvFormat())\r\n\t\t\t\t{\r\n\t\t\t\t\tcase VI_PAL:\r\n\t\t\t\t\tcase VI_DEBUG_PAL:\r\n\t\t\t\t\t\tif ( !NxNgc::EngineGlobals.use_60hz )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\trmode->viYOrigin = 23;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tVIConfigure(rmode);\r\n\r\n\t\t\t\t// Stop audio, turn volume to 0.\r\n\t\t\t\tAXSetVoiceState(axVoice[0],AX_PB_STATE_STOP);\r\n\t\t\t\tAXSetVoiceState(axVoice[1],AX_PB_STATE_STOP);\r\n\r\n\t\t\t\thwGXInit();\r\n\t\r\n\t\t\t\tGXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);\r\n\t\t\t\tGXSetColorUpdate(GX_ENABLE);\r\n\t\t\t\tGXSetAlphaUpdate(GX_ENABLE);\r\n\r\n\t\t\t\tNxNgc::EngineGlobals.screen_brightness = 1.0f;\r\n\r\n\t\t\t\t// Display n\r\n\t\t\t\twhile ( 1 )\r\n\t\t\t\t{\r\n\t\t\t\t\terror = DVDGetDriveStatus();\r\n//\t\t\t\t\tprintf( \"Error code: %d\\n\", error );\r\n\r\n\t\t\t\t\tNsDisplay::doReset();\r\n\r\n\t\t\t\t\tif ( error == DVD_STATE_END ) break;\r\n\t\t\t\t\tif ( error == DVD_STATE_BUSY ) continue;\r\n\t\t\t\t\tif ( error == DVD_STATE_CANCELED ) break;\r\n\t\t\t\t\tif ( error == DVD_STATE_PAUSING ) continue;\r\n\t\t\t\t\tif ( error == DVD_STATE_WAITING ) continue;\r\n\r\n\t\t\t\t\t// Render the text.\r\n\t\t\t\t\tNsDisplay::begin();\r\n\t\t\t\t\tNsRender::begin();\r\n\t\r\n\t\t\t\t\tNsCamera cam;\r\n\t\t\t\t\tcam.orthographic( 0, 0, rmode->fbWidth, 448 );\r\n\t\r\n\t\t\t\t\t// Draw the screen.\r\n\t\t\t\t\tNsPrim::begin();\r\n\t\r\n\t\t\t\t\tcam.begin();\r\n\t\r\n\t\t\t\t\tGXSetZMode( GX_FALSE, GX_ALWAYS, GX_TRUE );\r\n\t\r\n\t\t\t\t\tNxNgc::set_blend_mode( NxNgc::vBLEND_MODE_BLEND );\r\n\t\r\n\t\t//\t\t\tif ( NsDisplay::shouldReset() )\r\n\t\t//\t\t\t{\r\n\t\t//\t\t\t\t// Reset message.\r\n\t\t//\t\t\t\tScript::RunScript( \"ngc_reset\" );\r\n\t\t//\t\t\t}\r\n\t\t//\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// DVD Error message.\r\n\t\t\t\t\t\tswitch ( error )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tcase DVD_STATE_FATAL_ERROR:\r\n\t\t\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_fatal\" );\r\n\t\t\t\t\t\t\t\tNxNgc::EngineGlobals.disableReset = true;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\tcase DVD_STATE_RETRY:\r\n\t\t\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_retry\" );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\tcase DVD_STATE_COVER_OPEN:\r\n\t\t\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_cover_open\" );\r\n\t\t\t\t\t\t\t\tNxNgc::EngineGlobals.disableReset = false;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\tcase DVD_STATE_NO_DISK:\r\n\t\t\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_no_disk\" );\r\n\t\t\t\t\t\t\t\tNxNgc::EngineGlobals.disableReset = false;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\tcase DVD_STATE_WRONG_DISK:\r\n\t\t\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_wrong_disk\" );\r\n\t\t\t\t\t\t\t\tNxNgc::EngineGlobals.disableReset = false;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\r\n\t\t\t\t\tNsDisplay::setBackgroundColor( messageColor );\r\n\t\r\n\t\t\t\t\tcam.end();\r\n\t\r\n\t\t\t\t\tNsPrim::end();\r\n\t\r\n\t\t\t\t\tNsRender::end();\r\n\t\t\t\t\tNsDisplay::end( true );\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Reset a bunch of GX state.\r\n\t\t\t\r\n\t\t\t\tNsDisplay::setBackgroundColor( (GXColor){0,0,0,0} );\r\n\r\n\t\t\t\t// Color definitions\r\n\t\t\t\t\r\n\t\t\t\t#define GX_DEFAULT_BG (GXColor){64, 64, 64, 255}\r\n\t\t\t\t#define BLACK (GXColor){0, 0, 0, 0}\r\n\t\t\t\t#define WHITE (GXColor){255, 255, 255, 255}\r\n\t\t\t\t\r\n\t\t\t\t//\r\n\t\t\t\t// Render Mode\r\n\t\t\t\t//\r\n\t\t\t\t// (set 'rmode' based upon VIGetTvFormat(); code not shown)\r\n\t\t\t\t\r\n\t\t\t\t//\r\n\t\t\t\t// Geometry and Vertex\r\n\t\t\t\t//\r\n\t\t\t\tGXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);\r\n\t\t\t\tGXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY);\r\n\t\t\t\tGXSetTexCoordGen(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TEX2, GX_IDENTITY);\r\n\t\t\t\tGXSetTexCoordGen(GX_TEXCOORD3, GX_TG_MTX2x4, GX_TG_TEX3, GX_IDENTITY);\r\n\t\t\t\tGXSetTexCoordGen(GX_TEXCOORD4, GX_TG_MTX2x4, GX_TG_TEX4, GX_IDENTITY);\r\n\t\t\t\tGXSetTexCoordGen(GX_TEXCOORD5, GX_TG_MTX2x4, GX_TG_TEX5, GX_IDENTITY);\r\n\t\t\t\tGXSetTexCoordGen(GX_TEXCOORD6, GX_TG_MTX2x4, GX_TG_TEX6, GX_IDENTITY);\r\n\t\t\t\tGXSetTexCoordGen(GX_TEXCOORD7, GX_TG_MTX2x4, GX_TG_TEX7, GX_IDENTITY);\r\n\t\t\t\tGXSetNumTexGens(1);\r\n\t\t\t\tGXSetCurrentMtx(GX_PNMTX0);\r\n\t\t\t\tGXSetCullMode(GX_CULL_BACK);\r\n\t\t\t\tGXSetClipMode(GX_CLIP_ENABLE);\r\n\t\t\t\tGXSetNumChans(0); // no colors by default\r\n\t\t\t\t\r\n\t\t\t\tGXSetChanCtrl(\r\n\t\t\t\tGX_COLOR0A0,\r\n\t\t\t\tGX_DISABLE,\r\n\t\t\t\tGX_SRC_REG,\r\n\t\t\t\tGX_SRC_VTX,\r\n\t\t\t\tGX_LIGHT_NULL,\r\n\t\t\t\tGX_DF_NONE,\r\n\t\t\t\tGX_AF_NONE );\r\n\t\t\t\t\r\n\t\t\t\tGXSetChanAmbColor(GX_COLOR0A0, BLACK);\r\n\t\t\t\tGXSetChanMatColor(GX_COLOR0A0, WHITE);\r\n\t\t\t\t\r\n\t\t\t\tGXSetChanCtrl(\r\n\t\t\t\tGX_COLOR1A1,\r\n\t\t\t\tGX_DISABLE,\r\n\t\t\t\tGX_SRC_REG,\r\n\t\t\t\tGX_SRC_VTX,\r\n\t\t\t\tGX_LIGHT_NULL,\r\n\t\t\t\tGX_DF_NONE,\r\n\t\t\t\tGX_AF_NONE );\r\n\t\t\t\t\r\n\t\t\t\tGXSetChanAmbColor(GX_COLOR1A1, BLACK);\r\n\t\t\t\tGXSetChanMatColor(GX_COLOR1A1, WHITE);\r\n\t\t\t\t\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD2, GX_TEXMAP2, GX_COLOR0A0);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD3, GX_TEXMAP3, GX_COLOR0A0);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE4, GX_TEXCOORD4, GX_TEXMAP4, GX_COLOR0A0);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE5, GX_TEXCOORD5, GX_TEXMAP5, GX_COLOR0A0);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE6, GX_TEXCOORD6, GX_TEXMAP6, GX_COLOR0A0);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE7, GX_TEXCOORD7, GX_TEXMAP7, GX_COLOR0A0);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE8, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE9, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE10,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE11,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE12,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE13,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE14,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\t\t\tGXSetTevOrder(GX_TEVSTAGE15,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\t\t\tGXSetNumTevStages(1);\r\n\t\t\t\tGXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);\r\n\t\t\t\tGXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);\r\n\t\t\t\tfor ( int i = GX_TEVSTAGE0; i < GX_MAX_TEVSTAGE; i++) {\r\n\t\t\t\tGXSetTevKColorSel((GXTevStageID) i, GX_TEV_KCSEL_1_4 );\r\n\t\t\t\tGXSetTevKAlphaSel((GXTevStageID) i, GX_TEV_KASEL_1 );\r\n\t\t\t\tGXSetTevSwapMode ((GXTevStageID) i, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\r\n\t\t\t\t// Restart audio, volume to full.\r\n\t\t\t\tAXSetVoiceState(axVoice[0],AX_PB_STATE_RUN);\r\n\t\t\t\tAXSetVoiceState(axVoice[1],AX_PB_STATE_RUN);\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tswitch (VIGetTvFormat())\r\n\t\t\t\t{\r\n\t\t\t\t\tcase VI_PAL:\r\n\t\t\t\t\tcase VI_DEBUG_PAL:\r\n\t\t\t\t\t\tif ( !NxNgc::EngineGlobals.use_60hz )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\trmode->viYOrigin = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tVIConfigure(rmode);\r\n\r\n//\t\t\tOSHalt(\"*** DVD error occured. A true DVD error handler is not part of this demo.\\n\");\r\n\t\t\t\tstartTicks = OSGetTick();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t// Final processing for this frame (copy out etc.)\r\n//\t\t_DEMODoneRender();\r\n\t\tNsRender::end();\r\n\t\tNsDisplay::end();\r\n\r\n//\t\t// handle GC controller\r\n//\t\tDEMOPadRead();\r\n//\t\tbuttonsDown = DEMOPadGetButtonDown(0);\r\n//\t\tif(buttonsDown & PAD_BUTTON_START)\r\n//\t\t\tbreak;\r\n\t\t\t\r\n\t\tunsigned short current = ( padData[0].button | padData[1].button );\r\n\t\tunsigned short press = ( current ^ last ) & current;\r\n\t\tlast = current;\r\n\r\n\t\tif ( press & ( PAD_BUTTON_START | PAD_BUTTON_A ) ) break;\r\n\r\n\t\t// Control timing\r\n\t\tif (!first)\r\n\t\t\t{\r\n\t\t\tf64\tdt;\r\n\t\t\tidealTime += 1000.0 / VIDSimpleGetFPS();\r\n\t\t\tdo\r\n\t\t\t\t{\r\n\t\t\t\tdt = OSTicksToMilliseconds((f64)(OSGetTick() - startTicks));\r\n\t\t\t\t}\r\n\t\t\twhile((totalTime + dt) < idealTime);\r\n\t\t\ttotalTime += dt;\r\n\t\t\t}\r\n\t\telse\r\n\t\t\tfirst = FALSE;\r\n\t\t\t\r\n\t\t} // while (1)\r\n\t\t\r\n\t// free our ressources. Just as demonstration what you need to do for a 'clean' exit\r\n\tVIDSimpleLoadStop();\r\n\tVIDSimpleClose();\r\n\r\n\tVIDSimpleFreeDVDBuffers();\r\n\tVIDSimpleDestroyDecoder();\r\n\tVIDSimpleExitAudioDecoder();\r\n\r\nquit:\r\n\tNsDisplay::setBackgroundColor( (GXColor){0,0,0,0} );\r\n\r\n//\tGXSetPixelFmt(/*GX_PF_RGB8_Z24*/GX_PF_RGBA6_Z24, GX_ZC_LINEAR);\r\n\r\n\tGQRSetup6( GQR_SCALE_64,\t\t// Pos\r\n\t\t\t   GQR_TYPE_S16,\r\n\t\t\t   GQR_SCALE_64,\r\n\t\t\t   GQR_TYPE_S16 );\r\n\tGQRSetup7( 14,\t\t// Normal\r\n\t\t\t   GQR_TYPE_S16,\r\n\t\t\t   14,\r\n\t\t\t   GQR_TYPE_S16 );\r\n\r\n\thwGXInit();\r\n\r\n\tGXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);\r\n\tGXSetColorUpdate(GX_ENABLE);\r\n\tGXSetAlphaUpdate(GX_ENABLE);\r\n\r\n\t// Register our default AX callback.\r\n\tAXRegisterCallback( Sfx::AXUserCBack );\r\n\r\n\tLCDisable();\r\n\r\n#\tifdef MY_DEBUG\r\n\tOSReport(\"VidPlayer done!\\n\");\t\r\n#\tendif\t\r\n\r\n#\tendif\t\t// DVDETH\r\n\r\n\tswitch (VIGetTvFormat())\r\n\t{\r\n\t\tcase VI_PAL:\r\n\t\tcase VI_DEBUG_PAL:\r\n\t\t\tif ( !NxNgc::EngineGlobals.use_60hz )\r\n\t\t\t{\r\n\t\t\t\trmode->viYOrigin = 23;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\tVISetBlack( TRUE );\r\n    VIConfigure(rmode);\r\n    VIFlush();\r\n    VIWaitForRetrace();\r\n\tVISetBlack( FALSE );\r\n}\r\n\t\r\n\r\nbool Movie_Render ( void )\r\n{\r\n//\tif ( !playing ) return false;\r\n//\r\n//\t//\r\n//\t// Decompress the Bink frame.\r\n//\t//\r\n//\t\r\n//\tBinkDoFrame( Bink );\r\n//\t\r\n//\t//\r\n//\t// Draw the next frame.\r\n//\t//\r\n//\t\r\n//\tShow_frame( Bink );\r\n//\t\r\n//\t//\r\n//\t// Keep playing the movie.\r\n//\t//\r\n//\t\r\n//\tBinkNextFrame( Bink );\r\n//\r\n//\treturn true;\r\n\r\n\treturn false;\r\n}\r\n\r\n} // namespace Flx\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Movies/ngc/p_movies.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMovies\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/movies/ngc/p_movies.h \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t8/27/01\t-\tdc\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __P_MOVIES_H\r\n#define __P_MOVIES_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/list.h>\r\n#include <core/macros.h>\r\n\r\nnamespace Flx\r\n{\r\n\r\nvoid PMovies_PlayMovie( const char *pName );\r\n\r\nbool Movie_Render( void );\r\n\r\n} // namespace Flx\r\n\r\n#endif\t// __P_MOVIES_H\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Bgm/PathDefs",
    "content": " AR      = C:/usr/local/sce/iop/gcc/bin/iop-elf-ar\r\n AS      = C:/usr/local/sce/iop/gcc/mipsel-scei-elfl/bin/as\r\n CC      = C:/usr/local/sce/iop/gcc/bin/iop-elf-gcc\r\n GCC     = C:/usr/local/sce/iop/gcc/bin/iop-elf-gcc\r\n LD      = C:/usr/local/sce/iop/gcc/mipsel-scei-elfl/bin/ld\r\n NM      = C:/usr/local/sce/iop/gcc/bin/iop-elf-nm\r\n SIZE    = C:/usr/local/sce/iop/gcc/bin/iop-elf-size\r\n STRIP   = C:/usr/local/sce/iop/gcc/bin/iop-elf-strip\r\n RANLIB  = C:/usr/local/sce/iop/gcc/bin/iop-elf-ranlib\r\n OBJCOPY = C:/usr/local/sce/iop/gcc/bin/iop-elf-objcopy\r\n OBJDUMP = C:/usr/local/sce/iop/gcc/bin/iop-elf-objdump\r\n IFIXUP  = iopfixup\r\n ILBGEN  = ioplibgen\r\n ILBLD   = ioplibld\r\n ILBDUMP = ioplibdump\r\n BIN2OBJ = bin2elf\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Bgm/bgm_com.c",
    "content": "// This code builds an IRX module that handles PCM streaming from\r\n// the CD to SPU2 Sound Data Input area...\r\n\r\n#include <kernel.h>\r\n#include <sys/types.h>\r\n#include <stdio.h>\r\n#include \"sif.h\"\r\n#include \"sifcmd.h\"\r\n#include \"sifrpc.h\"\r\n#include <libsd.h>\r\n#include \"bgm_i.h\"\r\n\r\nint gRpcArg[16];\t//--- Receiving channel for RPC arguments transferred from EE\r\n\r\n\r\nstatic void* bgmFunc(unsigned int fno, void *data, int size);\r\n\r\nextern int  BgmInit(int ch, int useCD);\r\nextern void BgmQuit(int channel, int status );\r\nextern int  BgmOpen( int ch, char* filename );\r\nextern void BgmClose(int ch, int status);\r\nextern void BgmCloseNoWait(int ch, int status);\r\nextern int  BgmPreLoad( int ch, int status );\r\nextern void BgmStart(int ch, int status);\r\nextern void BgmStop(int ch, int status);\r\nextern void BgmSeek( int ch, unsigned int vol );\r\nextern int BgmSetVolume( int ch, unsigned int vol );\r\nextern int BgmRaw2Spu( int ch, int which, int mode );\r\nextern int BgmSetVolumeDirect( int ch, unsigned int vol );\r\n// fuck this you big assbreath.\r\n//extern void BgmSetMasterVolume( int ch, unsigned int vol );\r\nextern unsigned int BgmGetMode( int ch, int status );\r\n//extern void BgmSetMode( int ch, u_int mode );\r\nextern void BgmSdInit(int ch, int status );\r\n\r\n\r\n/* ------------------------------------------------------------------------\r\n   Main thread for the ezbgm module.\r\n   After execution, initialize interrupt environment, register command, and\r\n   then wait until there is a request from the EE.\r\n   ------------------------------------------------------------------------ */\r\nint sce_bgm_loop()\r\n{\r\n\tsceSifQueueData qd;\r\n\tsceSifServeData sd;\r\n\r\n\t//-- Initialize interrupt environment in advance.\r\n\r\n\tCpuEnableIntr();\r\n\tEnableIntr( INUM_DMA_4 );\r\n\tEnableIntr( INUM_DMA_7 );\r\n\t\r\n\t//--- Register function that is called according to request\r\n\r\n\r\n\tsceSifInitRpc(0);\r\n\r\n\tsceSifSetRpcQueue( &qd, GetThreadId() );\r\n\tsceSifRegisterRpc( &sd, EZBGM_DEV, bgmFunc, (void*)gRpcArg, NULL, NULL, &qd );\r\n\tPRINTF((\"goto bgm cmd loop\\n\"));\r\n\r\n\t//--- Command-wait loop\r\n\r\n\tsceSifRpcLoop(&qd);\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n/* ------------------------------------------------------------------------\r\n   Function that is awakened by a request from the EE.\r\n   The argument is stored in *data.  The leading four bytes are reserved and are not used.\r\n   The return value of this function becomes the return value of the EE side's RPC.\r\n   When the argument is a structure, it is sent to gRpcData and used.\r\n   When a structure is returned to the EE, the value is sent to the address of the first argument (on the EE side).\r\n   ------------------------------------------------------------------------ */\r\nint ret = 0;\r\n\r\nstatic void* bgmFunc(unsigned int command, void *data, int size)\r\n{ \r\n\tint ch;\r\n\r\n//\tasm volatile( \"break 1\");\r\n\r\n//\tPRINTF(( \" bgmfunc %x, %x, %x, %x\\n\", *((int*)data + 0), \r\n//\t\t*((int*)data + 1), *((int*)data + 2),*((int*)data + 3) ));\r\n\r\n\tch = command&0x000F;\r\n\r\n\tswitch( command&0xFFF0 )\r\n\t{\r\n\tcase EzBGM_INIT:\r\n\t\tret = BgmInit( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_QUIT:\r\n\t\tBgmQuit ( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_OPEN:\r\n\t\tret = BgmOpen ( ch, (char*)((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_CLOSE:\r\n\t\tBgmClose( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_CLOSE_NO_WAIT:\r\n\t\tBgmCloseNoWait( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_PRELOAD:\r\n\t\tret = BgmPreLoad ( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_START:\r\n\t\tBgmStart( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_STOP:\r\n\t\tBgmStop( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_SEEK:\r\n\t\tBgmSeek( ch, (unsigned int)*((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_SETVOL:\r\n\t\tret = BgmSetVolume( ch, (unsigned int)*((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_SETVOLDIRECT:\r\n\t\tret = BgmSetVolumeDirect( ch, (unsigned int)*((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_GETMODE:\r\n\t\tret = BgmGetMode( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_SDINIT:\r\n\t\tBgmSdInit( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tERROR((\"EzBGM driver error: unknown command %d \\n\", *((int*)data) ));\r\n\t\tbreak;\r\n\t}\r\n//\tPRINTF(( \"return value = %x \\n\", ret )); \r\n\treturn (void*)(&ret);\r\n}\r\n\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n/* DON'T ADD STUFF AFTER THIS */\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Bgm/bgm_entr.c",
    "content": "#include <kernel.h>\r\n#include <sys/types.h>\r\n#include <stdio.h>\r\n#include <sif.h>\r\n#include <sifcmd.h>\r\n#include <sifrpc.h>\r\n#include \"bgm_i.h\"\r\n\r\nModuleInfo Module = {\"pcmaudio_driver\", 0x0102 };\r\n\r\nextern int sce_bgm_loop();\r\nextern volatile int gStThid;\r\n\r\nint create_th();\r\n\r\nint start ()\r\n{\r\n\tstruct ThreadParam param;\r\n\tint th;\r\n\r\n\tCpuEnableIntr();\r\n\r\n\tif( ! sceSifCheckInit() )\r\n\t\tsceSifInit();\r\n\tsceSifInitRpc(0);\r\n\r\n\tprintf(\"Entering PCM Audio Driver\\n\");\r\n\r\n\tparam.attr         = TH_C;\r\n\tparam.entry        = sce_bgm_loop;\r\n\tparam.initPriority = BASE_priority-2;\r\n\tparam.stackSize    = 0x800;\r\n\tparam.option       = 0;\r\n\tth = CreateThread(&param);\r\n\tif (th > 0) {\r\n\t\tStartThread(th,0);\r\n\t\tprintf(\"Exit PCM Audio Driver\\n\");\r\n\t\treturn 0;\r\n\t}else{\r\n\t\treturn 1;\r\n\t}\r\n}\r\n\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n/* DON'T ADD STUFF AFTER THIS */\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Bgm/bgm_i.h",
    "content": "//--- Highest bit indicates presence of return value\r\n#define EzBGM_INIT           0x8000\r\n#define EzBGM_QUIT           0x0010\r\n#define EzBGM_OPEN           0x8020\r\n#define EzBGM_CLOSE          0x0030\r\n#define EzBGM_PRELOAD        0x0040\r\n#define EzBGM_START          0x0050\r\n#define EzBGM_STOP           0x0060\r\n#define EzBGM_SEEK           0x0070\r\n#define EzBGM_SETVOL         0x8080\r\n#define EzBGM_SETVOLDIRECT   0x8090\r\n#define EzBGM_CLOSE_NO_WAIT  0x0100\r\n//#define EzBGM_SETMASTERVOL 0x00a0\r\n#define EzBGM_GETMODE        0x80b0\r\n#define EzBGM_SETMODE        0x80c0\r\n#define EzBGM_SDINIT         0x00d0\r\n\r\n\r\n//-- SET AVAILABLE\r\n#define BGM_MODE_REPEAT_OFF      0x0000\r\n#define BGM_MODE_REPEAT_DEFAULT  0x0001\r\n#define BGM_MODE_REPEAT_FORCED   0x0002\r\n\r\n#define BGM_MODE_STEREO          0x0000\r\n#define BGM_MODE_MONO            0x0010\r\n\r\n//-- GET ONLY\r\n#define BGM_MODE_IDLE            0x0000\r\n#define BGM_MODE_RUNNING         0x1000\r\n#define BGM_MODE_PAUSE           0x2000\r\n//#define BGM_MODE_KICKSTART       0x4000\r\n#define BGM_MODE_TERMINATE       0x8000\r\n\r\n\r\n#define BGM_MASK_STATUS          0x0FFF\r\n#define BGM_MASK_REPEAT          0xFFF0\r\n#define BGM_MASK_STEREO          0xFF0F\r\n\r\n#define WAV_STEREO_BIT           ( 1 << 1 )\r\n\r\n\r\n/* ----------------------------------------------\r\n   module ID number\r\n  ----------------------------------------------- */\r\n#define EZBGM_DEV   0x000666\r\n\r\n\r\n#define PRINTF(x) printf x\r\n//#define PRINTF(x) \r\n\r\n#define ERROR(x) printf x\r\n//#define ERROR(x) \r\n\r\n#define BASE_priority  42\r\n\r\n#define OLDLIB 0\r\n#define TRANS_CH  0\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Bgm/bgm_play.c",
    "content": "#include <stdio.h>\r\n#include <sys/file.h>\r\n#include <kernel.h>\r\n#include <string.h>\r\n#include <libsd.h>\r\n#include <libcdvd.h>\r\n#include \"bgm_i.h\"\r\n\r\n#define DEBUGGING_PLEASE 0\r\n#if DEBUGGING_PLEASE\r\n#define Dbg_Printf(A...)  printf(##A) \t\t\r\n#else\r\n#define Dbg_Printf(A...)\r\n#endif\r\n\r\n// wav format ------------------------\r\n#define RIFF_HEADER_SIZE 44\r\ntypedef struct {\r\n\tunsigned char     chunkID[4];\r\n\tunsigned int      chunkSize;\r\n\tunsigned short*   data;\r\n} DATAHeader;\r\n\r\ntypedef struct {\r\n\tunsigned char     chunkID[4];\r\n\tunsigned int      chunkSize;\r\n\tunsigned short    waveFmtType;\r\n\tunsigned short    channel;\r\n\tunsigned int      samplesPerSec;\r\n\tunsigned int      bytesPerSec;\r\n\tunsigned short    blockSize;\r\n\tunsigned short    bitsPerSample;\r\n} FMTHeader;\r\n\r\ntypedef struct {\r\n\tunsigned char     chunkID[4];\r\n\tunsigned int      chunkSize;\r\n\tunsigned char     formType[4];\r\n\tFMTHeader         fmtHdr;\r\n\tDATAHeader        dataHdr;\r\n} RIFFHeader;\r\n//------------------------------------\r\n\r\ntypedef struct {\r\n\tunsigned int     size;\r\n//\tunsigned int     offset;\r\n\tunsigned int     pos;\r\n} BGM_WAVE;\r\n\r\n\r\nBGM_WAVE gWave[2];\r\n\r\nint gMemInitializedForCD = 0;\r\nshort gBgmPause[2] = { 0, 0 };\r\nshort gBgmPreload[ 2 ] = { 0, 0 };\r\nchar gFileFromCD[ 2 ] = { 0, 0 };\r\nchar gBgmVolumeSet[2] = { 0, 0 };\r\nvolatile char gFileOpened[2] = { 0, 0 };\r\nvolatile char gBgmIntr[2] = { 0, 0 };\r\nint gThid = 0;\r\nint gSem = 0;\r\nint gFd[2];\r\nint gBuffRaw[2];\r\nint gBuffSpu[2] = {0, 0};\r\nint gRPacketSize[2];\r\nint gSPacketSize[2];\r\nint gAllockedSize[2];\r\nint gBgmVolume[2];\r\nint gBgmMode[2] = { BGM_MODE_REPEAT_OFF, BGM_MODE_REPEAT_OFF };\r\nint gBgmStereoMode[ 2 ] = { 0, 0 };\r\n\r\n#define MAX_FILENAME_LENGTH\t\t50\r\nchar gFilename[ 2 ][ MAX_FILENAME_LENGTH ];\r\n\r\n// Larger buffers will prevent skipping when loading in the background...\r\n// The more streams, the larger the buffers have to be.\r\n// Reading from the CDVD will be faster than debug stations from the host over the network,\r\n// so don't freak if you notice corruption on a dev system w/o CD.\r\n#define SECTOR_SIZE\t\t\t\t\t2048\r\n#define NUM_SECTORS_PER_READ\t\t2\r\n#define BUFFER_SIZE_FOR_HOST_FILE\t( 2048 * 132 ) // multiple of 6\r\n#define BUFFER_SIZE_FOR_CD_FILE\t\t( SECTOR_SIZE * NUM_SECTORS_PER_READ * 6 )\r\n\r\n#define RING_BUFFER_NUM_SECTORS\t\t48\r\n#define RING_BUFFER_ALLIGNMENT\t\t64\r\n#define RING_BUFFER_NUM_PARTITIONS\t3\r\nunsigned char gRingBuffer[ 2 ][ RING_BUFFER_NUM_SECTORS * 2048 ] __attribute__((aligned ( RING_BUFFER_ALLIGNMENT )));\r\nunsigned char gCDBuffSpu[ 2 ][ BUFFER_SIZE_FOR_CD_FILE ]__attribute__((aligned ( 64 )));\r\n\r\nint  _BgmPlay( int status );\r\nvoid _BgmRaw2Spu(u_long *src, u_long *dst,  u_long block_count );\r\nvoid _BgmRaw2SpuMono(u_long *src, u_long *dst,  u_long block_count );\r\nint\tBgmPreLoad( int ch, int status );\r\nvoid SetStereoOn( int ch, int stereo );\r\n\r\nstatic int IntFunc0( void* common )\r\n{\r\n\tgBgmIntr[0] = 1;\r\n\tiSignalSema( gSem );\r\n\treturn 1;  //-- Required for re-enabling interrupts\r\n}\r\n\r\nstatic int IntFunc1( void* common )\r\n{\r\n\tgBgmIntr[1] = 1;\r\n\tiSignalSema( gSem );\r\n\treturn 1;  //-- Required for re-enabling interrupts\r\n}\r\n\r\n\r\nstatic int makeMyThread( void )\r\n{\r\n    struct ThreadParam param;\r\n    int\tthid;\r\n\r\n    param.attr         = TH_C;\r\n    param.entry        = _BgmPlay;\r\n    param.initPriority = BASE_priority-3;\r\n    param.stackSize    = 0x800;\r\n    param.option = 0;\r\n\r\n    /* Create thread */\r\n\tthid = CreateThread(&param);\r\n\r\n\treturn thid;\r\n}\r\n\r\nstatic int makeMySem( void )\r\n{\r\n    struct SemaParam sem;\r\n\r\n    sem.initCount = 0;\r\n    sem.maxCount = 1;\r\n    sem.attr = AT_THFIFO;\r\n\r\n    /* Create semaphore.  */\r\n    return CreateSema(&sem);\r\n}\r\n\r\n\r\nint BgmRaw2Spu( int ch, int which )\r\n{\r\n    if ( gBgmStereoMode[ ch ] )\r\n\t{\r\n\t\t_BgmRaw2Spu( (u_long *)(gBuffRaw[ch]+ (gRPacketSize[ch])*which)\r\n\t\t\t, (u_long *)(gBuffSpu[ch] + (gSPacketSize[ch])*which)\r\n\t\t\t, gSPacketSize[ch]/1024 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t_BgmRaw2SpuMono ((u_long *)(gBuffRaw [ch] + (gRPacketSize [ch]) * which),\r\n\t\t\t\t (u_long *)(gBuffSpu [ch] + (gSPacketSize [ch]) * which),\r\n\t\t\t\t gSPacketSize [ch] / 1024);\r\n    }\r\n\treturn 0;\r\n}\r\n\r\n// returns zero if no longer playing...\r\nint BgmSetVolumeDirect( int ch, unsigned int vol )\r\n{\r\n\tsceSdSetParam( (ch)|SD_P_BVOLR, vol>>16 );\r\n\tsceSdSetParam( (ch)|SD_P_BVOLL, vol&0xFFFF);\r\n\treturn ( gBgmMode[ch] & ~BGM_MASK_STATUS );\r\n}\r\n\r\n\r\n\r\nvoid BgmSdInit(int ch, int status )\r\n{\r\n\t// This is already called from the soundFX module.\r\n\t//sceSdInit(0);\r\n\treturn;\r\n}\r\n\r\n\r\nint BgmInit( int ch, int useCD )\r\n{\r\n\r\n\tif( gSem == 0 ){\r\n\t\tgSem = makeMySem();\r\n\t}\r\n\tif( gThid == 0 ){\r\n\t\tgThid = makeMyThread();\r\n\t\tDbg_Printf(\"PCM Audio Streamer: create thread ID= %d, \", gThid );\r\n\t\t/* Activate thread  */\r\n\t\tStartThread( gThid, (u_long)NULL );\r\n\t}\r\n\r\n\tif ( !gBuffSpu[ ch ] )\r\n\t{\r\n\t\tgAllockedSize[ch] = useCD ? BUFFER_SIZE_FOR_CD_FILE : BUFFER_SIZE_FOR_HOST_FILE;\r\n\t\tif ( useCD )\r\n\t\t{\r\n\t\t\tgBuffSpu[ ch ] = ( int )gCDBuffSpu[ ch ]; //(int)AllocSysMemory( 0, gAllockedSize[ ch ], NULL );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tgBuffSpu[ ch ] = ( int )AllocSysMemory( 0, gAllockedSize[ ch ], NULL );\r\n\t\t}\r\n\t\tDbg_Printf(\" PCM spu buffer mem: 0x%x - 0x%x\\n\", gBuffSpu[ch], gBuffSpu[ch]+gAllockedSize[ ch ] );\r\n\t}\r\n\t// the memory should work for mono or stereo 44k files ( raw buffer always the same... )\r\n\tgRPacketSize[ ch ] = gAllockedSize[ ch ] / 6;\r\n\tgBuffRaw[ ch ] = ( int )( gBuffSpu[ ch ] + ( gRPacketSize[ ch ] * 4 ) );\r\n\tgMemInitializedForCD = useCD;\r\n\r\n\treturn  gThid;\r\n}\r\n\r\nvoid BgmQuit(int ch, int status )\r\n{\r\n\tif ( ( gBuffSpu[ ch ] ) && ( gBuffSpu[ ch ] != ( int ) gCDBuffSpu ) )\r\n\t\tFreeSysMemory( (void*)gBuffSpu[ch] );\r\n\tgBuffSpu[ch] = 0;\r\n\t//-- Frees resources unless another channel is used.\r\n\tif( gBuffSpu[1-ch] == 0 ){\r\n\t\tif (gThid != 0) TerminateThread( gThid );\r\n\t\tif (gSem != 0) DeleteSema( gSem );\r\n\t\tif (gThid != 0) DeleteThread( gThid );\r\n\t\tgThid = 0;\r\n\t\tgSem = 0;\r\n\t}\r\n\treturn;\r\n}\r\n\r\n/*\r\nvoid WaitForCDReady( char *description )\r\n{\r\n\tprintf( \"wait %s\", description );\r\n\twhile( SCECdComplete != sceCdDiskReady( 1 ) )\r\n\t{\r\n\t\tprintf( \".\" );\r\n\t}\r\n\tprintf( \"\\n\" );\r\n}*/\r\n\r\n#define NUM_BYTES_TO_CLEAR\t512 // must be divisible by 4!!!\r\n\r\nint BgmOpen( int data, char* filename )\r\n{\r\n//\tunsigned int channel;\r\n\tRIFFHeader wavHdr;\r\n\tint offset;\r\n\tint *addr;\r\n\tint i;\r\n\tint ch = data & 1;\r\n\tint stereo = data & WAV_STEREO_BIT;\r\n\t\r\n\tSetStereoOn( ch, stereo );\r\n\r\n\tfor ( i = 0; i < 2; i++ )\r\n\t{\r\n\t\tif ( gFileOpened[ i ] )\r\n\t\t{\r\n\t\t\tprintf( \"%s: Failed: Audio stream already running: %s\\n\", filename, gFilename[ i ] );\r\n//\t\t\tDbg_Printf( \"File already opened on that channel...\\n\" );\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t}\r\n\tprintf(\"pcm filename %s\\n\", filename );\r\n\t\r\n\tif ( !strncmp( filename, \"host\", 4 ) )\r\n\t{\r\n\t\tif ( gMemInitializedForCD )\r\n\t\t{\r\n\t\t\tprintf( \"Loading file from host when mem configured for CD... SOUND QUALITY WILL SUCK.\\n\" );\r\n\t\t\tprintf( \"If calling ezBGM_INIT with useCD (2nd param), send CDROM0 in filename...\\n\" );\r\n\t\t}\r\n\t\t\r\n\t\t// load the file from the dev system...\r\n\t\tif (( gFd[ch] = open ( filename, O_RDONLY)) < 0)\r\n\t\t{\r\n\t\t\tERROR((\"file open failed. %s \\n\", filename));\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t\t\r\n\t\tif ( read (gFd[ch], (unsigned char*)(&wavHdr)\r\n\t\t\t,RIFF_HEADER_SIZE ) != RIFF_HEADER_SIZE ) {\r\n\t\t\tERROR((\"file read failed. %s \\n\", filename));\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t\tif ( wavHdr.fmtHdr.channel == 2 )\r\n\t\t{\r\n\t\t\tif ( !stereo )\r\n\t\t\t\tprintf( \"WARNING: Playing stereo sound %s in mono mode.\\n\", filename );\r\n\t\t}\r\n\t\telse if ( stereo )\r\n\t\t{\r\n\t\t\tprintf( \"WARNING: Playing mono sound %s in stereo mode.\\n\", filename );\r\n\t\t}\r\n\t\t\r\n\t\tgWave[ch].size   = wavHdr.dataHdr.chunkSize;\r\n\t\tgWave[ch].pos    = 0;\r\n\t\r\n\t\t//--- Seek to start of data\r\n\t\toffset = (unsigned int)&(wavHdr.dataHdr.data) -(unsigned int)&wavHdr;\r\n\t\r\n\t\tlseek( gFd[ ch ], offset , SEEK_SET );\r\n\t\r\n\t\tgFileFromCD[ ch ] = 0;\r\n\t\tgFileOpened[ ch ] = 1;\r\n\t\tgBgmPreload[ ch ] = 3;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsceCdlFILE fp;\r\n\t\tsceCdRMode mode;\r\n\t\tint retVal;\r\n\t\tunsigned int stringLength;\r\n\t\tunsigned int lsn;\r\n\t\tint foundCDData = 0;\r\n\t\tint byteIndex;\r\n\t\t// open a stream and load from CD...\r\n\t\t// 1st arg: size in num sectors ( actual size / 2048 ).\r\n//\t\tWaitForCDReady( \"st init\" );\r\n//\t\tsceCdDiskReady( 0 );\r\n\t\tsceCdStInit( RING_BUFFER_NUM_SECTORS, RING_BUFFER_NUM_PARTITIONS, ( u_int )( gRingBuffer[ ch ] ) ); //+ ( RING_BUFFER_ALLIGNMENT - 1 ) )  );\r\n//\t\tprintf( \"wait for ready.\" );\r\n//\t\tsceCdDiskReady( 0 );\r\n//\t\tWaitForCDReady( \"init\" );\r\n//\t\tprintf( \"cdSearchFile\\n\" );\r\n\t\tstringLength = strlen( filename );\r\n\t\tif ( filename[ stringLength + 1 ] == '@' )\r\n\t\t{\r\n\t\t\tfoundCDData = 1;\r\n\t\t\tlsn = 0;\r\n\t\t\tfor ( byteIndex = 0; byteIndex < 4; byteIndex++ )\r\n\t\t\t{\r\n\t\t\t\tlsn |= ( ( ( unsigned int )( filename[ stringLength + 2 + byteIndex ] ) ) & 255 ) << ( 8 * byteIndex );\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( !foundCDData )\r\n\t\t{\r\n\t\t\tif ( !( retVal = sceCdSearchFile( &fp, filename ) ) )\r\n\t\t\t{\r\n\t\t\t\tERROR((\"cd filesearch failed %d. file %s \\n\", retVal, filename));\r\n\t\t\t\treturn -1;\r\n\t\t\t}\r\n\t\t\tlsn = fp.lsn;\r\n\t\t}\r\n\t\r\n//\t\tWaitForCDReady( \"find\" );\r\n//\t\tsceCdDiskReady( 0 );\r\n\t\tmode.trycount = 0;\r\n\t\tmode.spindlctrl = SCECdSpinNom;\r\n\t\tmode.datapattern = SCECdSecS2048;\r\n\t\tsceCdStStart( lsn, &mode );\r\n\t\tgFileFromCD[ ch ] = 1;\r\n\t\tgBgmPreload[ ch ] = 3;\r\n\t\tgFileOpened[ ch ] = 1;\r\n\t\tgWave[ ch ].pos = 0;\r\n\t\tgWave[ ch ].size = gRPacketSize[ ch ] * 4;\r\n\t}\r\n\t\r\n//\tprintf(\"wave size %d  offset %d\\n\", gWave[ch].size, gWave[ch].offset );\r\n\t\r\n\tBgmSetVolumeDirect( ch, 0 );\r\n\r\n\tstrncpy( gFilename[ ch ], filename, MAX_FILENAME_LENGTH  );\r\n\r\n\t// clear out the end of the second half of the last buffer...\r\n\taddr = ( int * )( gBuffRaw[ ch ] + ( gRPacketSize[ ch ] ) + ( gRPacketSize[ ch ] >> 1 ) );\r\n\tfor ( i = 0; i < ( ( gRPacketSize[ ch ] >> 1 ) >> 2 ); i++ )\r\n\t{\r\n\t\t*( addr++ ) = 0;\r\n\t}\r\n\t\r\n\tif( ch == 0 )\r\n\t{\r\n\t\tsceSdSetTransCallback( ch, IntFunc0 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsceSdSetTransCallback( ch, IntFunc1 );\r\n\t}\r\n\t\t\r\n\treturn ( gWave[ ch ].size );\r\n}\r\n\r\nvoid _BgmClose(int ch, int status)\r\n{\r\n\tif ( !gFileOpened[ ch ] )\r\n\t{\r\n\t\tPRINTF((\"Calling BgmClose when no file opened on that channel...\\n\"));\r\n\t\treturn;\r\n\t}\r\n\tDbg_Printf( \"_BgmClose\\n\" );\r\n\tif ( gFileFromCD[ ch ] )\r\n\t{\r\n\t\tsceCdStStop( );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tclose( gFd[ch] );\r\n\t\t//FreeSysMemory( ( void* )gBuffSpu[ ch ] );\r\n\t\t//gBuffSpu[ ch ] = 0;\r\n\t}\r\n\tgFileOpened[ ch ] = 0;\r\n\treturn;\r\n}\r\n\r\nvoid BgmStart(int ch, int status )\r\n{\r\n\tint retVal;\r\n\tif ( !gFileOpened[ ch ] )\r\n\t{\r\n\t\tprintf( \"trying to start track not loaded.\\n\" );\r\n\t\treturn;\r\n\t}\r\n\tDbg_Printf( \"starting block trans from bgm start/unpause\\n\" );\r\n\tif ( gBgmPause[ ch ] )\r\n\t{\r\n\t\tDbg_Printf( \"Starting music on channel where pause is requested...\\n\" );\r\n\t\tgBgmPause[ ch ] = 0;\r\n\t}\r\n\twhile( -1 == sceSdBlockTrans( ch, SD_TRANS_MODE_WRITE|SD_BLOCK_LOOP, (u_char*)gBuffSpu[ch], (gSPacketSize[ch]*2) ) )\r\n\t{\r\n\t\tfor ( retVal = 0; retVal < 10000; retVal++ )\r\n\t\t\t;\r\n\t\tDbg_Printf( \"failed to start loop.\\n\" );\r\n\t}\r\n\tif ( !( gBgmPreload[ ch ] ) )\r\n\t{\r\n\t\tBgmSetVolumeDirect(ch, gBgmVolume[ch]);\r\n\t}\r\n\tgBgmMode[ch] &= BGM_MASK_STATUS;\r\n\tgBgmMode[ch] |= BGM_MODE_RUNNING;\r\n\r\n\treturn;\r\n}\r\n\r\nvoid BgmCloseNoWait( int ch, int status )\r\n{\r\n\tif ( !gFileOpened[ ch ] )\r\n\t{\r\n\t\tPRINTF((\"Calling BgmClose when no file opened on that channel...\\n\"));\r\n\t\treturn;\r\n\t}\r\n\tif ( gBgmPause[ ch ] )\r\n\t{\r\n\t\tprintf( \"stopping music when pause is requested...\" );\r\n\t\treturn;\r\n\t}\r\n\t// if the pause has already stopped the callback, it's safe to unload now:\r\n\tif ( gBgmMode[ ch ] & BGM_MODE_PAUSE )\r\n\t{\r\n\t\t// callback isn't happening right now... can terminate with no worries here:\r\n\t\tDbg_Printf( \"unpausing from BgmClose\\n\" );\r\n\t\tgBgmMode[ch] &= BGM_MASK_STATUS; // Switch to IDLE mode\r\n\t\t_BgmClose( ch, status );\r\n\t\tDbg_Printf( \"calling _BgmClose from BgmClose\\n\" );\r\n\t\treturn;\r\n\t}\r\n\tgBgmMode[ch] &= BGM_MASK_STATUS;\r\n\tgBgmMode[ch] |= BGM_MODE_TERMINATE;\r\n}\r\n\r\nvoid BgmClose( int ch, int status )\r\n{\r\n\tint i;\r\n\tBgmCloseNoWait( ch, status );\r\n\tprintf( \"PCM close\" );\r\n\twhile ( ( gBgmMode[ ch ] & BGM_MODE_TERMINATE ) )\r\n\t{\r\n\t\tfor ( i = 0; i < 20000; i++ )\r\n\t\t\t;\r\n\t\tprintf( \".\" );\r\n\t}\r\n\tprintf( \"\\n\" );\r\n}\r\n\r\nint BgmPreLoad( int ch, int status )\r\n{\r\n\tif ( ( status == 666 ) || ( ( gWave[ ch ].size - gWave[ ch ].pos ) < gRPacketSize[ ch ] * 4 ) )\r\n\t{\r\n\t\tint i;\r\n\t\tint *addr;\r\n\t\tDbg_Printf( \"preloading at end of song. zero buffers.\\n\" );\r\n\t\t// we're at the end of the song... fill up read buffers with zero,\r\n\t\t// and convert...\r\n\t\taddr = ( int * )( gBuffRaw[ ch ] );\r\n\t\tfor ( i = 0; i < ( ( gRPacketSize[ ch ] * 2 ) >> 2 ); i++ )\r\n\t\t{\r\n\t\t\t*( addr++ ) = 0;\r\n\t\t}\r\n\t\t// fill up the spu with both buffers...\r\n\t\tBgmRaw2Spu( ch, 0 );\r\n\t\tBgmRaw2Spu( ch, 1 );\r\n\t\treturn ( 0 );\r\n\t}\r\n\t\r\n\t// it's still in preload mode... no need to preload ourselves...\r\n\tif ( gBgmPreload[ ch ] == 3 )\r\n\t\treturn ( 0 );\r\n\r\n\tif ( gFileFromCD[ ch ] )\r\n\t{\r\n\t\tunsigned int err;\r\n\t\tsceCdStRead( NUM_SECTORS_PER_READ * 2, ( u_int * )gBuffRaw[ ch ], STMBLK, &err );\r\n\t\tif ( err )\r\n\t\t{\r\n\t\t\tprintf( \"PCM A Disk error code 0x%08x\\n\", err );\r\n\t\t}\r\n\r\n\t\t// fill up the spu with both buffers...\r\n\t\tBgmRaw2Spu( ch, 0 );\r\n\t\tBgmRaw2Spu( ch, 1 );\r\n\t\t\r\n\t\t// fill up the buffers again...\r\n\t\tsceCdStRead( NUM_SECTORS_PER_READ * 2, ( u_int * )gBuffRaw[ ch ], STMBLK, &err );\r\n\t\tif ( err )\r\n\t\t{\r\n\t\t\tprintf( \"PCM B Disk error code 0x%08x\\n\", err );\r\n\t\t}\r\n\t\t\r\n\t\tgWave[ ch ].pos += gRPacketSize[ ch ] * 2;\r\n\t\treturn 0;\r\n\t}\r\n\t// reading from a file...\r\n\tif ( read (gFd[ch], (unsigned char*)(gBuffRaw[ch])\r\n\t, gRPacketSize[ch]*2 ) != gRPacketSize[ch]*2 ) {\r\n\t\tERROR ((\"BgmPreLoad: read failed \\n\")); return -1;\r\n\t}\r\n\r\n\tBgmRaw2Spu( ch, 0 );\r\n\tBgmRaw2Spu( ch, 1 );\r\n\r\n\tif ( read (gFd[ch], (unsigned char*)(gBuffRaw[ch])\r\n\t, (gRPacketSize[ch]*2) ) != gRPacketSize[ch]*2) {\r\n\t\tERROR ((\"BgmPreLoad: read failed \\n\")); return -1;\r\n\t}\r\n\r\n\tgWave[ch].pos += gRPacketSize[ch]*4;\r\n\r\n\treturn 0;\r\n}\r\n\r\nvoid _BgmPause(int ch, int status)\r\n{\r\n\tDbg_Printf( \"stopping spu block trans in _BgmPause\\n\" );\r\n\tsceSdBlockTrans( ch, SD_TRANS_MODE_STOP, NULL, 0 );\r\n\tgBgmMode[ch] &= BGM_MASK_STATUS; // Switch to PAUSE mode\r\n\tgBgmMode[ch] |= BGM_MODE_PAUSE;\r\n\treturn;\r\n}\r\n\r\nvoid _BgmStopAndUnload(int ch, int status)\r\n{\r\n\tDbg_Printf( \"stopping block trans from _BgmStopAndUnload\\n\" );\r\n\tsceSdBlockTrans( ch, SD_TRANS_MODE_STOP, NULL, 0 );\r\n\tgBgmMode[ch] &= BGM_MASK_STATUS; // Switch to IDLE mode\r\n\tDbg_Printf( \"bgm close from _BgmStopAndUnload\\n\" );\r\n\t_BgmClose( ch, status );\r\n\treturn;\r\n}\r\n\r\n// should be fucking called \"BgmPause\"\r\nvoid BgmStop( int ch, unsigned int vol )\r\n{\r\n\tint i;\r\n\r\n\tif ( gBgmMode[ ch ] & BGM_MODE_TERMINATE )\r\n\t{\r\n\t\tDbg_Printf( \"trying to pause PCM when stopped.\\n\" );\r\n\t\treturn;\r\n\t}\r\n\tif ( !gBgmMode[ ch ] & BGM_MODE_RUNNING )\r\n\t{\r\n\t\tDbg_Printf( \"trying to pause PCM when not running.\\n\" );\r\n\t\treturn;\r\n\t}\r\n\tgBgmPause[ch] = 1;\r\n\tprintf( \"waiting for pause\" );\r\n\twhile ( !( gBgmMode[ ch ] & BGM_MODE_PAUSE ) )\r\n\t{\r\n\t\tfor ( i = 0; i < 10000; i++ )\r\n\t\t\t;\r\n\t\tprintf( \".\" );\r\n\t}\r\n\tprintf( \"\\n\" );\r\n\t// don't set the flag until the callback has paused it:\r\n//\tgBgmMode[ch] &= BGM_MASK_STATUS;\r\n//\tgBgmMode[ch] |= BGM_MODE_PAUSE;\r\n\treturn;\r\n}\r\n\r\n\r\nint BgmSetVolume( int ch, unsigned int vol )\r\n{\r\n\tgBgmVolumeSet[ch] = 1;\r\n\tgBgmVolume[ch] = vol;\r\n\treturn ( gBgmMode[ch] & ~BGM_MASK_STATUS );\r\n}\r\n\r\n\r\nunsigned int BgmGetMode( int ch, int status )\r\n{\r\n\treturn gBgmMode[ch];\r\n}\r\n\r\nvoid BgmSeek( int ch, unsigned int value )\r\n{\r\n//\tlseek(gFd[ch], gWave[ch].offset+value, SEEK_SET );\r\n//\tgWave[ch].pos = value;\r\n\tprintf( \"seek not supported\\n\" );\r\n\treturn;\r\n}\r\n\r\nvoid SetStereoOn( int ch, int stereo )\r\n{\r\n    if ( stereo )\r\n\t{\r\n\t\tgSPacketSize[ ch ] = gAllockedSize[ ch ] / 6;\r\n\t\tgBgmStereoMode[ ch ] = 1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgSPacketSize[ ch ] = gAllockedSize [ ch ] / 3;\r\n\t\tgBgmStereoMode[ ch ] = 0;\r\n\t}\r\n}\r\n\r\nvoid PreloadFile( int which, int ch )\r\n{\r\n\tswitch ( gBgmPreload[ ch ] )\r\n\t{\r\n\t\tcase ( 3 ):\r\n\t\t\tif ( gFileFromCD[ ch ] )\r\n\t\t\t{\r\n\t\t\t\tRIFFHeader *pWavHdr;\r\n\t\t\t\tint i;\r\n\t\t\t\tint offset;\r\n\t\t\t\tunsigned char *pData;\r\n\t\t\t\tpWavHdr = ( RIFFHeader * )( gBuffRaw[ ch ]+gRPacketSize[ch]*which );\r\n\t\t\t\tif ( pWavHdr->dataHdr.chunkSize < gWave[ ch ].size )\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf( \"BIG WARNING:  Cd audio file currently playing is TOO SMALL!\\n\" );\r\n\t\t\t\t}\r\n\t\t\t\tif ( pWavHdr->fmtHdr.channel == 2 )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !gBgmStereoMode[ ch ] )\r\n\t\t\t\t\t\tprintf( \"WARNING: Playing stereo sound %s in mono mode.\\n\", gFilename[ ch ] );\r\n\t\t\t\t}\r\n\t\t\t\telse if ( gBgmStereoMode[ ch ] )\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf( \"WARNING: Playing mono sound %s in stereo mode.\\n\", gFilename[ ch ] );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tSetStereoOn( ch, pWavHdr->fmtHdr.channel == 2 );\r\n\t\t\t\tgWave[ch].size   = pWavHdr->dataHdr.chunkSize;\r\n\t\t\t\t//gWave[ch].offset = (unsigned int)&( pWavHdr->dataHdr.data ) - ( unsigned int )pWavHdr;\r\n\t\t\t\toffset = (unsigned int)&( pWavHdr->dataHdr.data ) - ( unsigned int )pWavHdr;\r\n\t\t\t\t// clear out the area where the header is... don't want some loud obnoxious sounds...\r\n\t\t\t\tpData = ( unsigned char * )( gBuffRaw[ ch ]+gRPacketSize[ch]*which );\r\n\t\t\t\tif ( offset > gRPacketSize[ ch ] )\r\n\t\t\t\t\toffset = gRPacketSize[ ch ]; // don't fuck up memory if some strange read happened...\r\n\t\t\t\tfor ( i = 0; i < offset; i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tpData[ i ] = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase ( 2 ):\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase ( 1 ):\r\n\t\t\t// turn the volume back up, the spooler is at the beginning of\r\n\t\t\t// the good SPU buffer...\r\n\t\t\tBgmSetVolume( ch, gBgmVolume[ch] );\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tprintf( \"unknown preload state... fire Matt.\\n\" );\r\n\t\t\tbreak;\r\n\t}\r\n\t--gBgmPreload[ ch ];\r\n}\r\n\r\nint _BgmPlay( int status )\r\n{\r\n\tint i, ch, read_size, which;\r\n\tint *addr, remain;\r\n\tDbg_Printf( \"entering _BgmPlay\\n\" );\r\n\twhile ( 1 )\r\n\t{\r\n\t\t//-- Wait for playing of buffer to finish\r\n\t\tWaitSema(gSem);\r\n\r\n\t\t//-- Which channel is the interrupt from?\r\n\t\tif( (gBgmIntr[0] == 1) && ( ch != 0 ) )  ch = 0;\r\n\t\telse if( (gBgmIntr[1] == 1) && ( ch != 1 ) )  ch = 1;\r\n\t\telse if( gBgmIntr[0] == 1 )  ch = 0;\r\n\t\telse if( gBgmIntr[1] == 1 )  ch = 1;\r\n\t\telse continue;\r\n\r\n\t\tgBgmIntr[ch] = 0;\r\n\r\n\t\twhich = 1 - (sceSdBlockTransStatus( ch, 0 )>>24);\r\n\r\n\t\t//--- Stopped due to end of data (no looping)\r\n\t\tif( ( gBgmMode[ ch ] & BGM_MODE_TERMINATE ) != 0 )\r\n\t\t{\r\n\t\t\tWaitSema( gSem ); // Wait until another interrupt is received\r\n\t\t\t_BgmStopAndUnload( ch, 0 );\r\n\t\t\tBgmSetVolumeDirect( ch, 0x0 );\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t//--- Volume change event\r\n\t\tif ( ( gBgmVolumeSet[ ch ] == 1 ) && ( !gBgmPreload[ ch ] ) )\r\n\t\t{\r\n\t\t\tBgmSetVolumeDirect( ch, gBgmVolume[ch] );\r\n\t\t\tgBgmVolumeSet[ch] = 0;\r\n\t\t}\r\n\r\n\t\t//--- Convert buffer\r\n\r\n\t\tBgmRaw2Spu( ch, which );\r\n\r\n\t\t//--- File READ for buffer\r\n\r\n\t\tremain = gWave[ ch ].size - gWave[ ch ].pos;\r\n\t\tif ( remain > gRPacketSize[ch] )\r\n\t\t{\r\n\t\t\tif ( gFileFromCD[ ch ] )\r\n\t\t\t{\r\n\t\t\t\t//--- Not end of data\r\n\t\t\t\tunsigned int err;\r\n\t\t\t\tsceCdStRead( NUM_SECTORS_PER_READ, ( u_int * )( gBuffRaw[ ch ]+gRPacketSize[ch]*which ), STMBLK, &err );\r\n\t\t\t\tif ( err )\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf( \"PCM C Disk error code 0x%08x\\n\", err );\r\n\t\t\t\t}\r\n\t\t\t\tread_size = gRPacketSize[ ch ];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tread_size = read (gFd[ch], (unsigned char*)(gBuffRaw[ch]+gRPacketSize[ch]*which), gRPacketSize[ch] );\r\n\t\t\t}\r\n\t\t\tif ( read_size < gRPacketSize[ch] )\r\n\t\t\t\tcontinue; //retry\r\n\t\t\tif ( gBgmPreload[ ch ] )\r\n\t\t\t{\r\n\t\t\t\tPreloadFile( which, ch );\r\n\t\t\t}\r\n\t\t\tgWave[ch].pos += read_size;\r\n\t\t}\r\n\t\telse  //--- End of data\r\n\t\t{\r\n\t\t\tif ( gFileFromCD[ ch ] )\r\n\t\t\t{\r\n\t\t\t\t//--- Not end of data\r\n\t\t\t\tunsigned int err;\r\n\t\t\t\tsceCdStRead( NUM_SECTORS_PER_READ, ( u_int * )( gBuffRaw[ ch ]+gRPacketSize[ch]*which ), STMBLK, &err );\r\n\t\t\t\tif ( err )\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf( \"PCM C Disk error code 0x%08x\\n\", err );\r\n\t\t\t\t}\r\n\t\t\t\tread_size = gRPacketSize[ ch ];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tread_size = read (gFd[ch], (unsigned char*)(gBuffRaw[ch]+gRPacketSize[ch]*which), remain );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif( read_size < remain ) continue; //retry\r\n\t    \t\r\n\t\t\tPRINTF((\"end of PCM track - ch %d\\n\", ch));\r\n\r\n\t\t\taddr = ( int * )( gBuffRaw[ ch ] + ( gRPacketSize[ ch ] * which ) + remain );\r\n\t\t\tfor( i = 0; i < ((gRPacketSize[ch]-remain)>>2); i++ )\r\n\t\t\t{\r\n\t\t\t\t*(addr++) = 0;\r\n\t\t\t}\r\n\t\t\tgBgmMode[ch] &= BGM_MASK_STATUS;\r\n\t\t\tgBgmMode[ch] |= BGM_MODE_TERMINATE;\r\n\t\t}\r\n\r\n\t\t//-- Stop event\r\n\t\tif( (gBgmPause[ch] == 1) )\r\n\t\t{\r\n\t\t\t//printf( \"_BgmPlay :: pause\\n\" );\r\n\t\t\t_BgmPause( ch, 0 );\r\n\t\t\tBgmSetVolumeDirect(ch, 0x0);\r\n\t\t\tgBgmPause[ch] = 0;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n/* This file ends here, DON'T ADD STUFF AFTER THIS */\r\n\r\n// Ha ha I added some stuff... FUCK YOU SONY!\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Bgm/bgm_r2s.s",
    "content": "/* SCEI CONFIDENTIAL\r\n \"PlayStation 2\" Programmer Tool Runtime Library  Release 2.0\r\n */\r\n/* \r\n *                  I/O Proseccor sample program\r\n *                          Version 1.20\r\n *                           Shift-JIS\r\n *\r\n *      Copyright (C) 1998-1999 Sony Computer Entertainment Inc.\r\n *                        All Rights Reserved.\r\n *\r\n *                       ezbgm.irx - bgm_r2s.c\r\n *                          raw to spu pcm\r\n *\r\n *   Version   Date            Design    Log\r\n *  --------------------------------------------------------------------\r\n *   1.20      Nov.23.1999     morita    modify for EzBGM\r\n *   0.01      Nov.18.1999     ishii     optimize for IOP\r\n */\r\n\r\n#include <cpureg.h>\r\n\r\n#define src  a0\r\n#define dst  a1\r\n#define blk  a2\r\n#define cnt  a3\r\n\r\n\t.globl\t_BgmRaw2Spu\r\n\t.ent\t_BgmRaw2Spu\r\n_BgmRaw2Spu:\r\n\tsubu\tsp, (8*4)\r\n\tsw\ts0, 0*4(sp)\t; \tsw\ts1, 1*4(sp)\r\n\tsw\ts2, 2*4(sp)\t; \tsw\ts3, 3*4(sp)\r\n\tsw\ts4, 4*4(sp)\t; \tsw\ts5, 5*4(sp)\r\n\tsw\ts6, 6*4(sp)\t; \tsw\ts7, 7*4(sp)\r\n\tmove\tv0, zero\r\n\tmove\tv1, zero\r\n\taddi\tcnt,zero, 256\r\n\r\n\t\t\t\t\t.set noreorder\r\n\t/* AŖ߂̂Ȃт𐧌B */\r\npcm_separate_loop:\r\n\tlw\tt0, 0*4(src)\t/* 1 + 4 clock */\r\n\tlw\tt1, 1*4(src)\t/* 1 + 2 clock */\r\n\r\n\t/* 7 clock */\r\n\tand\ts0, t0, 0xffff\t\t/* t0 ̉ʂ s0  */\r\n\tsrl\ts1, t0, 16\t\t/* t0 ̏ʂ s1  */\r\n\tsll\tt0, t1, 16\t\t/* t1 ̉ʂɃVtg s0  */\r\n\tor\ts0, t0\r\n\tsrl\tt1, t1, 16\t\t/* t1 ̏ʂ}XN s1  */\r\n\tsll\tt1, t1, 16\r\n\tor\ts1, t1\r\n\r\n\t/* ɃLbVɓǂݍ܂Ă͂ */\r\n\tlw\tt2, 2*4(src)\t/* 1 clock */\r\n\tlw\tt3, 3*4(src)\t/* 1 clock */\r\n\t/* ̃LbVCǂݍނ */\r\n\tlw\tt4, 4*4(src)\t/* 1 + 4 clock */\r\n\r\n\t/* 7 clock */\r\n\tand\ts2, t2, 0xffff\t\t/* t2 ̉ʂ s2  */\r\n\tsrl\ts3, t2, 16\t\t/* t2 ̏ʂ s3  */\r\n\tsll\tt2, t3, 16\t\t/* t3 ̉ʂɃVtg s2  */\r\n\tor\ts2, t2\r\n\tsrl\tt3, t3, 16\t\t/* t3 ̏ʂ}XN s3  */\r\n\tsll\tt3, t3, 16\r\n\tor\ts3, t3\r\n\r\n\t/* ɃLbVɓǂݍ܂Ă͂ */\r\n\tlw\tt5, 5*4(src)\t/* 1 clock */\r\n\tlw\tt6, 6*4(src)\t/* 1 clock */\r\n\tlw\tt7, 7*4(src)\t/* 1 clock */\r\n\tadd\tsrc, 8*4\t/* 1 clock */\r\n\r\n\t/* 7 clock */\r\n\tand\ts4, t4, 0xffff\t\t/* t4 ̉ʂ s4  */\r\n\tsrl\ts5, t4, 16\t\t/* t4 ̏ʂ s5  */\r\n\tsll\tt4, t5, 16\t\t/* t5 ̉ʂɃVtg s4  */\r\n\tor\ts4, t4\r\n\tsrl\tt5, t5, 16\t\t/* t5 ̏ʂ}XN s5  */\r\n\tsll\tt5, t5, 16\r\n\tor\ts5, t5\r\n\r\n\t/* store  dst1(s0, s2),  dst2(s1, s3) */\r\n\t/* 4 clock */\r\n\r\n\tsw\ts0, 0*4(dst)\t;\tsw\ts2, 1*4(dst)\r\n\tsw\ts1, (0*4+512)(dst); \tsw\ts3, (1*4+512)(dst)\r\n\t/* ȉƕs +2, 4+2 clock ŏ܂͂ */\r\n\r\n\t/* 7 clock */\r\n\tand\ts6, t6, 0xffff\t\t/* t6 ̉ʂ s6  */\r\n\tsrl\ts7, t6, 16\t\t/* t6 ̏ʂ s7  */\r\n\tsll\tt6, t7, 16\t\t/* t7 ̉ʂɃVtg s6  */\r\n\tor\ts6, t6\r\n\tsrl\tt7, t7, 16\t\t/* t7 ̏ʂ}XN s7  */\r\n\tsll\tt7, t7, 16\r\n\tor\ts7, t7\r\n\r\n\t/* store  dst1(s4, s6),  dst2(s5, s7) */\r\n\t/* 4 clock */\r\n\tsw\ts4, 2*4(dst)\t; \tsw\ts6, 3*4(dst)\r\n\tsw\ts5, (2*4+512)(dst)\t; \tsw\ts7, (3*4+512)(dst)\r\n\t/* ȉƕs +2, 4+2 clock ŏ܂͂ */\r\n\r\n\tadd\tdst, 4*4\t\t/* 1 clock */\r\n\r\n\r\n\t/* ܂ŁAŖ߂̂Ȃт𐧌B */\r\n\t\t\t\t\t.set reorder\r\n\r\n\tadd\tv0, 8\t\t\t/* 1 clock */\r\n\tblt\tv0, cnt, pcm_separate_loop\t/* 1 clock */\r\n\r\n\tadd\tdst, 512\r\n\tmove\tv0, zero\r\n\r\n\tadd\tv1, 1\r\n\tblt\tv1, blk, pcm_separate_loop\r\n\r\n\tlw\ts0, 0*4(sp)\t; \tlw\ts1, 1*4(sp)\r\n\tlw\ts2, 2*4(sp)\t; \tlw\ts3, 3*4(sp)\r\n\tlw\ts4, 4*4(sp)\t; \tlw\ts5, 5*4(sp)\r\n\tlw\ts6, 6*4(sp)\t; \tlw\ts7, 7*4(sp)\r\n\taddu\tsp, (8*4)\r\n\tj\tra\r\n\t.end\t_BgmRaw2Spu\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Bgm/bgm_r2sm.c",
    "content": "#include <kernel.h>\r\n\r\n#define SPU_BLOCK 512\r\n\r\n// Using SP will speed things up, but ...\r\n\r\nvoid _BgmRaw2SpuMono( unsigned int *src, unsigned int *dst, unsigned int block )\r\n{\r\n\tint i;\r\n\r\n\tfor ( i = 0; i < block; i++ )\r\n\t{\r\n\t\tmemcpy( (void*)((int)dst+i*SPU_BLOCK*2), (void*)((int)src+i*SPU_BLOCK), SPU_BLOCK );\r\n\t\tmemcpy( (void*)((int)dst+i*SPU_BLOCK*2+SPU_BLOCK), (void*)((int)src+i*SPU_BLOCK) , SPU_BLOCK );\r\n\t}\r\n\r\n\treturn;\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Bgm/makefile",
    "content": "ifeq ($(wildcard PathDefs),)\r\nPathDefs:\r\n\tiop-path-setup > PathDefs || (rm -f PathDefs ; exit 1)\r\n\tmake all\r\nelse\r\ninclude PathDefs\r\nendif\r\n\r\nINCDIR\t= -I/usr/local/sce/common/include -I/usr/local/sce/iop/install/include\r\n\r\nCFLAGS  = $(INCDIR) -I. -Wall -G0 -g\r\nASFLAGS  = $(INCDIR) -G0\r\n\r\nCOMPILE.s = $(CC) -xassembler-with-cpp $(ASFLAGS) $(CPPFLAGS) $(TARGET_MACH) -c\r\n\r\n#----------- customize section --------------\r\nPROGNAME = ezbgm\r\n\r\nOBJS     = bgm_entr.o bgm_com.o bgm_play.o bgm_r2s.o bgm_r2sm.o\r\n#ILIBS\t= -ilb=$(TOP)lib/iop.ilb \r\nILIBS\t= \r\nLIBI\t= /usr/local/sce/iop/install/lib\r\n\r\n#----------- rules --------------\r\nall:\t$(PROGNAME).irx\r\n\r\nclean:\r\n\trm -f *.o $(PROGNAME).irx *.obj *.map\r\n\r\n$(PROGNAME).irx: $(OBJS)\r\n\t$(LINK.o)  -o $@ \\\r\n\t\t$(OBJS) -L../../../lib -L./ -L$(LIBI) -ilb=libsd.ilb  -ilb=cdvdman.ilb\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Pcm/Makefile",
    "content": "ifeq ($(wildcard PathDefs),)\r\nPathDefs:\r\n\tiop-path-setup\r\n\tmake all\r\nelse\r\ninclude PathDefs\r\nendif\r\n\r\nTOPDIR = /usr/local/sce\r\nINCOPT = -I$(TOPDIR)/common/include -I$(TOPDIR)/iop/install/include\r\n\r\nCFLAGS  = $(INCOPT) -I. -Wall -G0 -g -D__PLAT_NGPS__\r\nASFLAGS = $(INCOPT) -G0\r\nRM          = /bin/rm -f\r\n\r\nCOMPILE.s = $(CC) -xassembler-with-cpp $(ASFLAGS) $(CPPFLAGS) $(TARGET_MACH) -c\r\n\r\n#----------- customize section --------------\r\nPROGNAME = ezpcm\r\n\r\nOBJS     = pcm_ent.o pcm_com.o pcm_sound.o \r\n#ILIBS\t= -ilb=$(TOP)lib/iop.ilb \r\nILIBS\t=\r\nLIBI\t= /usr/local/sce/iop/install/lib\r\n\r\n#----------- rules --------------\r\nall:\t$(PROGNAME).irx\r\n\r\nclean:\r\n\trm -f *.o $(PROGNAME).irx *.obj *.map\r\n\r\n$(PROGNAME).irx: $(OBJS)\r\n\t$(LINK.o)  -o $@ \\\r\n\t\t$(OBJS) -L../../../lib -L./ -L$(LIBI) -ilb=libsd.ilb\r\n\r\npcm_ent.o:\tpcm.h pcmiop.h\r\npcm_com.o:\tpcm.h pcmiop.h\r\npcm_sound.o:\tpcm.h pcmiop.h\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Pcm/PathDefs",
    "content": "AR\t = snarl.exe\r\nAS\t = ps2cc -iop\r\nCC\t = ps2cc -iop\r\nGCC\t = ps2cc -iop\r\nLD\t = ps2cc -iop\r\nNM\t = C:/usr/local/sce/iop/gcc/bin/iop-nm.exe\r\nSIZE\t = iop-size.exe\r\nSTRIP\t = C:/usr/local/sce/iop/gcc/bin/iop-strip.exe\r\nRANLIB\t = C:/usr/local/sce/iop/gcc/bin/iop-ranlib.exe\r\nOBJCOPY\t = C:/usr/local/sce/iop/gcc/bin/iop-objcopy.exe\r\nOBJDUMP\t = C:/usr/local/sce/iop/gcc/bin/iop-objdump.exe\r\nIFIXUP\t = iopfixup.exe\r\nILBGEN\t = C:/usr/local/sce/iop/gcc/bin/ioplibgen.exe\r\nILBLD\t = C:/usr/local/sce/iop/gcc/mipsel-scei-elfl/bin/ioplibld.exe\r\nILBDUMP\t = C:/usr/local/sce/iop/gcc/mipsel-scei-elfl/bin/ioplibdump.exe\r\nBIN2OBJ\t = bin2elf.exe\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Pcm/pcm.h",
    "content": "\r\n#ifndef\t__GEL_MUSIC_NGPS_PCM_PCM_H__\r\n#define\t__GEL_MUSIC_NGPS_PCM_PCM_H__\r\n\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#include <sifcmd.h>\r\n#endif\r\n\r\n#define NUM_STREAMS 3\r\n\r\n#define PCM_RPC_ARG_NUM_INTS 16\r\n\r\n#define DEFAULT_PITCH\t0x1000\r\n\r\n// VAG header structure\r\nstruct VagHeader\r\n{\r\n\tchar ID[4];\r\n\tint version;\r\n\tchar reserved1[4];\r\n\tint dataSize;\r\n\tint sampleFreq;\r\n\tchar reserved2[12];\r\n\tchar name[16];\r\n} ;\r\n\r\n#define SIZE_OF_VAGHEADER ( sizeof( VagHeader ) )\r\n\r\n// sound stuff:\r\n#define SB_BUF_SIZE ( 1024 * 32 )\t\t// hex 2000\r\n#define SB_BUF_HALF ( SB_BUF_SIZE / 2 )\t// hex 1000\r\n#define SB_BUF_SIZE_WITH_PADDING\t( SB_BUF_SIZE + 0x40 )\r\n\r\n// spu ram layout:\r\n// first valid address for use in SPU RAM\r\n#define SPU_RAM_SIZE\t\t\t\t\t0x1fffff\r\n#define SB_FIRST_USEABLE_ADDR\t\t\t0x5010\r\n\r\n//#define STRAY_VOICE_BLOCKER_SIZE\t\t128\r\n//#define STRAY_VOICE_BLOCKER_SPU_ADDR\tSB_TOP\r\n//#define STREAM_SPU_ADDR\t\t\t\t\t( STRAY_VOICE_BLOCKER_SPU_ADDR + STRAY_VOICE_BLOCKER_SIZE )\r\n#define STREAM_SPU_ADDR\t\t\t\t\tSB_FIRST_USEABLE_ADDR\r\n\r\n// slip in room for 3 streaming VAGS ( 2 for stereo music and one extra stream ):\r\n//#define SINGLE_STREAM_BUFFER_SIZE 2048\r\n//#define TOTAL_SPU_REQUIRED_FOR_STREAMS\t\t( SB_BUF_SIZE_WITH_PADDING * 4 )  // Assumes 2 streams\r\n#define TOTAL_SPU_REQUIRED_FOR_STREAMS\t\t( SB_BUF_SIZE_WITH_PADDING * ( 2 + NUM_STREAMS ) )\r\n#define MUSIC_L_SPU_BUF_LOC\t\t\t\t\t( STREAM_SPU_ADDR + 0x40 )\r\n#define MUSIC_R_SPU_BUF_LOC\t\t\t\t\t( MUSIC_L_SPU_BUF_LOC + SB_BUF_SIZE_WITH_PADDING )\r\n#define STREAM_SPU_BUF_LOC( i )\t\t\t\t( MUSIC_R_SPU_BUF_LOC + ( ( 1 + ( i ) ) * SB_BUF_SIZE_WITH_PADDING ) )\r\n\r\n#define END_OF_STREAMS\t\t\t\t\t\t( STREAM_SPU_ADDR + TOTAL_SPU_REQUIRED_FOR_STREAMS + 0x40 )\r\n\r\n//#define RAM_NEEDED_FOR_EFFECTS\t\t0\t// FUCK the effects...\r\n#define\tRAM_NEEDED_FOR_EFFECTS\t\t\t0xade0 // enough for HALL reverb\r\n//#define\tRAM_NEEDED_FOR_EFFECTS\t\t0xF6C0 // enough for space echo\r\n \r\n#define REVERB_ONLY_ON_CORE_0\t\t\t1\r\n\r\n#if !REVERB_ONLY_ON_CORE_0\r\n\r\n#define CORE_1_EFFECTS_START_ADDRESS\tEND_OF_STREAMS\r\n#define CORE_1_EFFECTS_END_ADDRESS\t\t0x02ffff // has to be on a 0xffff boundary!!\r\n#if ( ( CORE_1_EFFECTS_END_ADDRESS - CORE_1_EFFECTS_START_ADDRESS ) < RAM_NEEDED_FOR_EFFECTS )\r\n#error \"not enough space for core 0 effects!\"\r\n#endif\r\n\r\n#define BASE_WAVE_DATA_ADDR\t\t\t\tCORE_0_EFFECTS_END_ADDRESS\r\n\r\n#else\r\n#define BASE_WAVE_DATA_ADDR\t\t\t\tEND_OF_STREAMS\r\n#endif\r\n\r\n#define CORE_0_EFFECTS_START_ADDRESS\t( SPU_RAM_SIZE - RAM_NEEDED_FOR_EFFECTS )\r\n#define CORE_0_EFFECTS_END_ADDRESS\t\t( SPU_RAM_SIZE )\r\n#define END_WAVE_DATA_ADDR\t\t\t\t( CORE_0_EFFECTS_START_ADDRESS  - 0x40 )\r\n\r\n// used by temporary sounds and permanently loaded sounds...\r\n#define MAX_SPU_RAM_AVAILABLE\t\t\t( END_WAVE_DATA_ADDR - BASE_WAVE_DATA_ADDR )\r\n\r\n//#define MUSIC_R_SPU_BUF_LOC\t\tSB_TOP\r\n//#define MUSIC_L_SPU_BUF_LOC\t\t( MUSIC_R_SPU_BUF_LOC + SB_BUF_SIZE )\r\n//#define STREAM_SPU_BUF_LOC\t\t( MUSIC_L_SPU_BUF_LOC + SB_BUF_SIZE )\r\n\r\n// iop buffer taking streams off of the CD:\r\n#define MUSIC_IOP_BUFFER_SIZE\t\t\t\t( 1024 * (/*192*/192) )  // must be a multiple of 4k!\r\n#define MUSIC_HALF_IOP_BUFFER_SIZE\t\t\t( MUSIC_IOP_BUFFER_SIZE / 2 )  // must be a multiple of 2k!\r\n//#define STREAM_IOP_BUFFER_SIZE\t\t\t\t( 1024 * (/*128*/96) )  // must be a multiple of 4k!\r\n#define STREAM_IOP_BUFFER_SIZE\t\t\t\t( 1024 * (/*128*/64) )  // must be a multiple of 4k!\r\n#define STREAM_HALF_IOP_BUFFER_SIZE\t\t\t( STREAM_IOP_BUFFER_SIZE / 2 )  // must be a multiple of 2k!\r\n\r\n// must match values in pcm_com.c!!!\r\n#define TOTAL_IOP_BUFFER_SIZE_NEEDED\t\t( ( MUSIC_IOP_BUFFER_SIZE * 2 ) + ( STREAM_IOP_BUFFER_SIZE * NUM_STREAMS ) )\r\n#define ALLIGN_REQUIREMENT\t\t\t\t\t64\r\n#define SECTOR_SIZE\t\t\t\t\t\t\t( 2048 )\r\n#define NUM_SECTORS_PER_STREAM_BUFFER\t\t( STREAM_IOP_BUFFER_SIZE / SECTOR_SIZE )\r\n#define NUM_SECTORS_PER_STREAM_HALF_BUFFER\t( NUM_SECTORS_PER_STREAM_BUFFER / 2 )\r\n#define NUM_SECTORS_PER_MUSIC_BUFFER\t\t( MUSIC_IOP_BUFFER_SIZE / SECTOR_SIZE )\r\n#define NUM_SECTORS_PER_MUSIC_HALF_BUFFER\t( NUM_SECTORS_PER_MUSIC_BUFFER / 2 )\r\n\r\n#define MUSIC_L_IOP_OFFSET\t0\r\n#define MUSIC_R_IOP_OFFSET\t( MUSIC_HALF_IOP_BUFFER_SIZE )  // interwoven with the L IOP buffer... and shit\r\n#define STREAM_IOP_OFFSET( ch )\t\t\t\t( ( 2 * MUSIC_IOP_BUFFER_SIZE ) + ( STREAM_IOP_BUFFER_SIZE * ( ch ) ) )\r\n\r\n#define MUSIC_L_VOICE\t22\r\n#define MUSIC_R_VOICE\t23\r\n#define MUSIC_CORE\t\t1\r\n\r\n#define STREAM_VOICE( i ) ( 23 - ( i ) )\r\n#define STREAM_CORE\t\t0\r\n\r\n// RPC command:\r\n#define EzADPCM_COMMAND_MASK\t\t\t0xfff0\r\n#define EzADPCM_CH_MASK\t\t\t\t\t0x000f\r\n\t\r\n#define EzADPCM_INIT\t\t\t\t\t0x0000\r\n#define EzADPCM_QUIT\t\t\t\t\t0x0010\r\n#define EzADPCM_PLAYMUSIC\t\t\t\t0x0020\r\n#define EzADPCM_STOPMUSIC\t\t\t\t0x0030\r\n#define EzADPCM_PLAYSTREAM\t\t\t\t0x0040\r\n#define EzADPCM_STOPSTREAM\t\t\t\t0x0070\r\n#define EzADPCM_STOPSTREAMS\t\t\t\t0x00a0\r\n#define EzADPCM_SETMUSICVOL\t\t\t\t0x00b0\r\n#define EzADPCM_SETSTREAMVOL\t\t\t0x00c0\r\n#define EzADPCM_SETSTREAMVOLANDPITCH\t0x00d0\r\n#define EzADPCM_GETMUSICSTATUS\t\t\t0x00f0\r\n#define EzADPCM_PAUSEMUSIC\t\t\t\t0x0100\r\n#define EzADPCM_PAUSESTREAM\t\t\t\t0x0110\r\n#define EzADPCM_PAUSESTREAMS\t\t\t0x0120\r\n#define EzADPCM_SETSTREAMGLOBVOL\t\t0x0130\r\n#define EzADPCM_PRELOADMUSIC\t\t\t0x0140\r\n#define EzADPCM_PRELOADSTREAM\t\t\t0x0150\r\n#define EzADPCM_PLAYPRELOADEDMUSIC\t\t0x0160\r\n#define EzADPCM_PLAYPRELOADEDSTREAM\t\t0x0170\r\n#define EzADPCM_SDINIT\t\t\t\t\t0x7ff0\r\n\r\n// for GETSTREAMSTATUS or GETMUSICSTATUS:\r\n#define PCM_STATUS\t\t\t\t\t0x0001f000\r\n#define PCM_STATUS_IDLE\t\t   \t\t0x00000000\r\n#define PCM_STATUS_PRELOAD\t\t\t0x00001000\r\n#define PCM_STATUS_READY_TO_STOP\t0x00002000\r\n#define PCM_STATUS_NEED_UPDATE\t\t0x00003000\r\n#define PCM_STATUS_RUNNING\t\t\t0x00005000\r\n#define PCM_STATUS_TERMINATE\t\t0x00006000\r\n\r\n// flags for GETSTATUS\r\n#define PCMSTATUS_NEED_MUSIC_BUFFER_0\t( 1 << 0 ) // don't change the order of these!!! IMPORTANT!\r\n#define PCMSTATUS_NEED_STREAM0_BUFFER_0\t( 1 << 1 )\r\n#define PCMSTATUS_NEED_STREAM1_BUFFER_0\t( 1 << 2 )\r\n#define PCMSTATUS_NEED_STREAM2_BUFFER_0\t( 1 << 3 )\r\n#define PCMSTATUS_NEED_MUSIC_BUFFER_1\t( 1 << 4 )\r\n#define PCMSTATUS_NEED_STREAM0_BUFFER_1\t( 1 << 5 )\r\n#define PCMSTATUS_NEED_STREAM1_BUFFER_1\t( 1 << 6 )\r\n#define PCMSTATUS_NEED_STREAM2_BUFFER_1\t( 1 << 7 )\r\n#define PCMSTATUS_MUSIC_PLAYING\t\t\t( 1 << 8 )\r\n#define PCMSTATUS_STREAM0_PLAYING\t\t( 1 << 9 )\r\n#define PCMSTATUS_STREAM1_PLAYING\t\t( 1 << 10 )\r\n#define PCMSTATUS_STREAM2_PLAYING\t\t( 1 << 11 )\r\n#define PCMSTATUS_MUSIC_READY\t\t\t( 1 << 12 )\r\n#define PCMSTATUS_STREAM0_READY\t\t\t( 1 << 13 )\r\n#define PCMSTATUS_STREAM1_READY\t\t\t( 1 << 14 )\r\n#define PCMSTATUS_STREAM2_READY\t\t\t( 1 << 15 )\r\n#define PCMSTATUS_LOAD_MUSIC\t\t\t( 1 << 16 )\r\n#define PCMSTATUS_LOAD_STREAM0\t\t\t( 1 << 17 )\r\n#define PCMSTATUS_LOAD_STREAM1\t\t\t( 1 << 18 )\r\n#define PCMSTATUS_LOAD_STREAM2\t\t\t( 1 << 19 )\r\n#define PCMSTATUS_INITIALIZED\t\t\t( 1 << 20 )\r\n#define PCMSTATUS_PANIC\t\t\t\t\t( 1 << 30 )\t// Irrecoverable error occurred\r\n\r\n// flags for LOAD_STATUS\r\n#define LOAD_STATUS_DONE_MUSIC_BUFFER_0\t\t( 1 << 0 ) // don't change the order of these!!! IMPORTANT!\r\n#define LOAD_STATUS_DONE_MUSIC_BUFFER_1\t\t( 1 << 1 )\r\n#define LOAD_STATUS_DONE_STREAM0_BUFFER_0\t( 1 << 2 )\r\n#define LOAD_STATUS_DONE_STREAM0_BUFFER_1\t( 1 << 3 )\r\n#define LOAD_STATUS_DONE_STREAM1_BUFFER_0\t( 1 << 4 )\r\n#define LOAD_STATUS_DONE_STREAM1_BUFFER_1\t( 1 << 5 )\r\n#define LOAD_STATUS_DONE_STREAM2_BUFFER_0\t( 1 << 6 )\r\n#define LOAD_STATUS_DONE_STREAM2_BUFFER_1\t( 1 << 7 )\r\n\r\n// macros:\r\n#define PCMSTATUS_NEED_STREAM_BUFFER_0( xxx )\t( PCMSTATUS_NEED_STREAM0_BUFFER_0 << ( xxx ) )\r\n#define PCMSTATUS_NEED_STREAM_BUFFER_1( xxx )\t( PCMSTATUS_NEED_STREAM0_BUFFER_1 << ( xxx ) )\r\n#define PCMSTATUS_STREAM_PLAYING( xxx )\t\t\t( PCMSTATUS_STREAM0_PLAYING << ( xxx ) )\r\n#define PCMSTATUS_STREAM_READY( xxx )\t\t\t( PCMSTATUS_STREAM0_READY << ( xxx ) )\r\n#define PCMSTATUS_LOAD_STREAM( xxx )\t\t\t( PCMSTATUS_LOAD_STREAM0 << ( xxx ) )\r\n\r\n// These following macros work for both music and streams, where xxx is 0 for music and\r\n// starts at 1 for streams\r\n#define PCMSTATUS_NEED_AUDIO_BUFFER_0( xxx )\t( PCMSTATUS_NEED_MUSIC_BUFFER_0 << ( xxx ) )\r\n#define PCMSTATUS_NEED_AUDIO_BUFFER_1( xxx )\t( PCMSTATUS_NEED_MUSIC_BUFFER_1 << ( xxx ) )\r\n#define PCMSTATUS_AUDIO_PLAYING( xxx )\t\t\t( PCMSTATUS_MUSIC_PLAYING << ( xxx ) )\r\n#define PCMSTATUS_AUDIO_READY( xxx )\t\t\t( PCMSTATUS_MUSIC_READY << ( xxx ) )\r\n#define PCMSTATUS_LOAD_AUDIO( xxx )\t\t\t\t( PCMSTATUS_LOAD_MUSIC << ( xxx ) )\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n// Make sure this doesn't break the alignment of SSifCmdStreamReqPacket\r\ntypedef struct\r\n{\r\n\tint\t\t\t\tm_command;\r\n\tint\t\t\t\tm_param[3];\r\n} SStreamRequest;\r\n\r\n// Make sure this doesn't break the alignment of SSifCmdSoundReqPacket\r\ntypedef struct\r\n{\r\n\tunsigned short\tm_function;\r\n\tunsigned short\tm_entry;\r\n\tunsigned int\tm_value;\r\n\tunsigned int\tm_arg_0;\r\n\tunsigned int\tm_arg_1;\r\n\tunsigned int\tm_arg_2;\r\n\tunsigned int\tm_ee_dma_id;\t\t// Used on EE side; not sent to IOP side\r\n\tunsigned int\tm_pad[2];\r\n} SSoundRequest;\r\n\r\n// SifCmd structures ( keeping them 128-bit aligned )\r\n\r\n///////////////////////////////////\r\n// A stream request from the EE to the IOP\r\ntypedef struct\r\n{\r\n\tsceSifCmdHdr\tm_header;\r\n\tSStreamRequest\tm_request;\r\n} SSifCmdStreamRequestPacket;\r\n\r\n///////////////////////////////////\r\n// The result of a stream request\r\ntypedef struct\r\n{\r\n\tsceSifCmdHdr\tm_header;\r\n\tint\t\t\t\tm_return_value;\r\n\tint\t\t\t\tm_status_flags;\r\n\tint\t\t\t\tm_pad[2];\r\n} SSifCmdStreamResultPacket;\r\n\r\n///////////////////////////////////\r\n// This packet is sent from the IOP to the EE after the status flags are updated on the IOP\r\ntypedef struct\r\n{\r\n\tsceSifCmdHdr\tm_header;\r\n\tint\t\t\t\tm_status_flags;\r\n\tint\t\t\t\tm_pad[3];\r\n} SSifCmdStreamStatusPacket;\r\n\r\n///////////////////////////////////\r\n// This packet is sent from the EE to the IOP after a load finishes\r\ntypedef struct\r\n{\r\n\tsceSifCmdHdr\tm_header;\r\n\tint\t\t\t\tm_stream_num;\t\t// -1 for music\r\n\tint\t\t\t\tm_buffer_num;\r\n\tint\t\t\t\tm_bytes_loaded;\r\n\tint\t\t\t\tm_pad[1];\r\n} SSifCmdStreamLoadStatusPacket;\r\n\r\n///////////////////////////////////\r\n// This packet requests that a function is executed on the SPU2 chip\r\ntypedef struct\r\n{\r\n\tsceSifCmdHdr\tm_header;\r\n\tSSoundRequest\tm_request;\r\n} SSifCmdSoundRequestPacket;\r\n\r\n///////////////////////////////////\r\n// The result of any GET function (not all request packets get results)\r\ntypedef struct\r\n{\r\n\tsceSifCmdHdr\tm_header;\r\n\tunsigned short\tm_function;\r\n\tunsigned short\tm_entry;\r\n\tunsigned int\tm_result;\r\n\tunsigned int\tm_panic;\t\t\t// indicates that request caused a panic on the IOP side\r\n\tint\t\t\t\tm_pad;\r\n} SSifCmdSoundResultPacket;\r\n\r\n///////////////////////////////////\r\n// Stores the request\r\ntypedef struct\r\n{\r\n\tSStreamRequest\tm_request;\r\n\tint\t\t\t\tm_request_id;\r\n} SStreamRequestPacket;\r\n\r\n// EE to IOP commands\r\n#define STREAM_REQUEST_COMMAND\t\t(0)\r\n\t\t\t\t\t\t\t\t\t\t// command number 1 used by fileio.irx\r\n#define STREAM_LOAD_STATUS_COMMAND\t(2)\r\n#define SOUND_REQUEST_COMMAND\t\t(3)\r\n\r\n// IOP to EE commands\r\n#define STREAM_RESULT_COMMAND\t\t(0)\r\n\t\t\t\t\t\t\t\t\t\t// command number 1 used by fileio.irx\r\n#define STREAM_STATUS_COMMAND\t\t(2)\r\n#define SOUND_RESULT_COMMAND\t\t(3)\r\n\r\n//#define NUM_COMMAND_HANDLERS \t(0x10)\r\n\r\n#endif // __PLAT_NGPS__\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n/* DON'T ADD STUFF AFTER THIS */\r\n\r\n#endif\t//\t__GEL_MUSIC_NGPS_PCM_PCM_H__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Pcm/pcm_com.c",
    "content": "/* Vag streaming into SPU2 -- from sony sample -- matt may 2001 */\r\n\r\n#include <kernel.h>\r\n#include <sys/types.h>\r\n#include <sys/file.h>\r\n#include <stdio.h>\r\n#include <string.h>\r\n#include <sif.h>\r\n#include <sifcmd.h>\r\n#include <sifrpc.h>\r\n#include <libsd.h>\r\n#include <sdrcmd.h>\r\n#include <thread.h>\r\n#include \"pcm.h\"\r\n#include \"pcmiop.h\"\r\n\r\n// ================================================================\r\n\r\n#define STREAM_PITCH( x ) ( ( ( x ) * 22050 ) / 48000 )\r\n\r\n#define CHECK_TRANSFER_INTEGRITY\t0\r\n#define TEST_PLAY_TIMING\t\t\t0\r\n\r\n#define SHOW_STREAM_INFO\t0\r\n#define SHOW_STATE\t0\r\n#define SHOW_SMALL_STREAM_STATE\t0\r\n#define SHOW_SMALL_MUSIC_STATE\t0\r\n#define SHOW_ACTION 0\r\n#define SHOW_SMALL_ACTION 0\r\n#define DBUGPRINTF\t0\r\n#define SHOW_TIMING\t0\r\n#define SHOW_STOP\t0\r\n#define SHOW_SMALL_COMMANDS\t0\r\n#define PRINT_EXCESSIVE_WAIT 0\r\n\r\n#if SHOW_STREAM_INFO\r\n#define ShowStreamInfo( x ) _ShowStreamInfo( x )\r\n#else\r\n#define ShowStreamInfo( x ) \r\n#endif\r\n\r\n#if SHOW_SMALL_COMMANDS\r\n#define ShowSmallCommand printf\r\n#else\r\n#define ShowSmallCommand( x )\r\n#endif\r\n\r\n#if SHOW_STOP\r\n#define ShowStop printf\r\n#else\r\n#define ShowStop( x )\r\n#endif\r\n\r\n#if SHOW_TIMING\r\n#define ShowTime\tprintf\r\n#else\r\n#define ShowTime DoNothing\r\nvoid DoNothing( char* text, ... ) { }\r\n#endif\r\n\r\n#if SHOW_ACTION\r\n#define ShowAction printf\r\n#else\r\n#define ShowAction( x )\r\n#endif\r\n\r\n#if SHOW_SMALL_STREAM_STATE\r\n#define SmallShowStreamState printf( \"  %d\", whichStream ), printf\r\n#else\r\n#define SmallShowStreamState( x )\r\n#endif\r\n\r\n#if SHOW_SMALL_MUSIC_STATE\r\n#define SmallShowMusicState printf\r\n#else\r\n#define SmallShowMusicState( x )\r\n#endif\r\n\r\n#if SHOW_SMALL_ACTION\r\n#define SmallShowAction printf\r\n#else\r\n#define SmallShowAction( x )\r\n#endif\r\n\r\n#if SHOW_STATE\r\n#define ShowState printf\r\n#else\r\n#define ShowState( x )\r\n#endif\r\n\r\n#if DBUGPRINTF\r\n#define Dbug_Printf( x ) printf( x )\r\n#else\r\n#define Dbug_Printf( x )\r\n#endif\r\n\r\n// the program running on the EE side will check to see if any of the buffers need to be filled:\r\nvolatile unsigned int gEECommand = 0;\r\n\r\n#define TRANS_DMA_CH_MUSIC\t\t1\r\n#define TRANS_DMA_CH_STREAM\t\t0\r\n\r\n#define _1st 0\r\n#define _2nd 1\r\n\r\n#define TRUE  1\r\n#define FALSE 0\r\n\r\nunsigned int VCount=0;\r\nunsigned int gThid = 0;\r\nunsigned int gSem = 0;\r\nunsigned int gpIopBuf;\t\t// IOP SMEM\r\n\r\nstruct StreamInfo gStreamInfo[ NUM_STREAMS ];\r\nstruct StreamInfo gMusicInfo;\r\nvolatile int gUsingStreamDMA = 0;\r\nvolatile int gSPUUsingStreamDMA = 0;\r\n\r\n// Done on the EE now\r\n//volatile unsigned int gStreamVolPercent = 100;\r\n\r\n// Timing test code\r\n#if TEST_PLAY_TIMING\r\nstatic \t\t\tint\t\ttest_timing_request_id = 2;\r\nstatic\t\t\tint\t\ttest_timing_send_timing_result = FALSE;\r\nstatic\t\t\tint\t\ttest_timing_hit_point = FALSE;\r\n#endif // TEST_PLAY_TIMING\r\n\r\nu_int GetNAX(int core,int ch);\r\nint OutsideMusicSPULoadBuffer();\r\nint OutsideStreamSPULoadBuffer(int whichStream);\r\nint DownloadMusic(int whichChannel);\r\nint DownloadStream(int whichStream);\r\nvoid IncMusicBuffer();\r\nvoid IncStreamBuffer(int whichStream);\r\nvoid StartMusic();\r\nvoid StartStream(int whichStream);\r\nint RefreshStreams( int status );\r\nvoid SendStatus();\r\n\r\nstatic int _AdpcmDmaIntMusic( int, void* );\r\nstatic int _AdpcmDmaIntStream( int, void* );\r\n\r\n#define _L 0\r\n#define _R 1\r\n#define _Lch(x) ((x >> 16) & 0xffff)\r\n#define _Rch(x) (x & 0xffff)\r\n\r\n// Timer structure.\r\ntypedef struct TimerCtx {\r\n    int thread_id;\r\n    int timer_id;\r\n    int count;\r\n} TimerCtx;\r\n\r\nTimerCtx gTimer;\r\n\r\n#define ONE_HSCAN 1000*1000/60\t// Approx 60 frames per second\r\n\r\n/**********************************************************************************\r\nIRQ Interrupt - called, say, once per frame\r\n***********************************************************************************/\r\nint TimerFunc( void *common)\r\n{\r\n    TimerCtx *tc = (TimerCtx *) common;\r\n\t\tVCount++;\r\n\t\tiSignalSema(gSem);\t// Signal StreamADPCM to be called\r\n    return (tc->count);\r\n}\r\n\r\n/**********************************************************************************\r\nSetTimer - IRQ Interrupt\r\n***********************************************************************************/\r\nint SetTimer( TimerCtx* timer )\r\n{\r\n    struct SysClock clock;\r\n    int timer_id;\r\n\r\n    USec2SysClock (ONE_HSCAN, & clock);\r\n    timer->count = clock.low;\t/* within 32-bit */\r\n\r\n    // Use sysclock timer\r\n    if ((timer_id = AllocHardTimer (TC_SYSCLOCK, 32, 1)) <= 0) {\r\n\tprintf (\"Can NOT allocate hard timer ...\\n\");\r\n\treturn (-1);\r\n    }\r\n    timer->timer_id = timer_id;\r\n\r\n    if (SetTimerHandler (timer_id, timer->count,\r\n\t\t\t (void *)TimerFunc, (void *) timer) != KE_OK) {\r\n\tprintf (\"Can NOT set timeup timer handler ...\\n\");\r\n\treturn (-1);\r\n    }\r\n\r\n    if (SetupHardTimer (timer_id, TC_SYSCLOCK, TM_NO_GATE, 1) != KE_OK) {\r\n\tprintf (\"Can NOT setup hard timer ...\\n\");\r\n\treturn (-1);\r\n    }\r\n    return 0;\r\n\r\n}\r\n\r\n/**********************************************************************************\r\nstartTimer - IRQ Interrupt\r\n***********************************************************************************/\r\nint StartTimer( TimerCtx* timer )\r\n{\r\n    if (StartHardTimer (timer->timer_id) != KE_OK)\r\n    {\r\n\t\tprintf (\"Can NOT start hard timer ...\\n\");\r\n\t\treturn (-1);\r\n    }\r\n    return 0;\r\n}\r\n\r\n// EzADPCM_SDINIT\r\nvoid AdpcmSdInit( void )\r\n{\r\n    sceSdInit (0);\r\n\r\n    //\tDisk media: DVD\r\n    //\tOutput format: PCM\r\n    //\tCopy guard: normal (one generation recordable / default)\r\n    sceSdSetCoreAttr (SD_C_SPDIF_MODE, (SD_SPDIF_MEDIA_DVD |\r\n\t\t\t\t\tSD_SPDIF_OUT_PCM   |\r\n\t\t\t\t\tSD_SPDIF_COPY_NORMAL));\r\n    return;\r\n}\r\n\r\nvoid AdpcmSetUpVoice( int core, int vnum, int pSpuBuf )\r\n{\r\n    sceSdSetParam ( core | ( vnum << 1 ) | SD_VP_VOLL, 0 );\r\n    sceSdSetParam ( core | ( vnum << 1 ) | SD_VP_VOLR, 0 );\r\n    sceSdSetParam ( core | ( vnum << 1 ) | SD_VP_PITCH, core == MUSIC_CORE ? DEFAULT_PITCH : STREAM_PITCH( DEFAULT_PITCH ) );\r\n//    sceSdSetParam ( core | ( vnum << 1 ) | SD_VP_ADSR1, 0x000f );\r\n//    sceSdSetParam ( core | ( vnum << 1 ) | SD_VP_ADSR2, 0x1fc0 );\r\n    sceSdSetAddr  ( core | ( vnum << 1 ) | SD_VA_SSA,  pSpuBuf );\r\n    return;\r\n}\r\n\r\n// EzADPCM_INIT\r\nint AdpcmInit( int pIopBuf )\r\n{\r\n\tint i;\r\n\tif ( gEECommand & PCMSTATUS_INITIALIZED )\r\n\t{\r\n\t\treturn ( 0 );\r\n\t}\r\n\r\n    if ( gSem == 0 )\r\n\t{\r\n\t\tstruct SemaParam sem;\r\n\t\tsem.initCount = 0;\r\n\t\tsem.maxCount = 1;\r\n\t\tsem.attr = AT_THFIFO;\r\n\t\tgSem = CreateSema (&sem);\r\n    }\r\n    if (gThid == 0)\r\n\t{\r\n\t\tstruct ThreadParam param;\r\n\t\tparam.attr         = TH_C;\r\n\t\tparam.entry        = RefreshStreams;\r\n\t\tparam.initPriority = BASE_priority-3;\r\n\t\tparam.stackSize    = 0x800; // was 800\r\n\t\tparam.option = 0;\r\n\t\tgThid = CreateThread (&param);\r\n\t\tprintf( \"EzADPCM: create thread ID= %d\\n\", gThid );\r\n\t\tStartThread (gThid, (u_long) NULL);\r\n    }\r\n\r\n\tsceSdSetTransIntrHandler( TRANS_DMA_CH_MUSIC, ( sceSdTransIntrHandler ) _AdpcmDmaIntMusic, ( void * ) &gSem );\r\n    sceSdSetTransIntrHandler( TRANS_DMA_CH_STREAM, ( sceSdTransIntrHandler ) _AdpcmDmaIntStream, ( void * ) &gSem );\r\n\tSetTimer(&gTimer);\t\t// Setup IRQ interrupt\r\n\tStartTimer(&gTimer);\t\t// Start IRQ interrupt (calls TimerFunc)\r\n\t\r\n\tAdpcmSetUpVoice( MUSIC_CORE, MUSIC_L_VOICE, MUSIC_L_SPU_BUF_LOC );\r\n\tAdpcmSetUpVoice( MUSIC_CORE, MUSIC_R_VOICE, MUSIC_R_SPU_BUF_LOC );\r\n\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t{\r\n\t\tAdpcmSetUpVoice( STREAM_CORE, STREAM_VOICE( i ), STREAM_SPU_BUF_LOC( i ) );\r\n\t}\r\n\r\n\tmemset( gStreamInfo, 0, sizeof( struct StreamInfo ) * NUM_STREAMS );\r\n\tmemset( &gMusicInfo, 0, sizeof( struct StreamInfo ) );\r\n\t\r\n\tgpIopBuf = pIopBuf;\r\n\tgEECommand |= PCMSTATUS_INITIALIZED;\r\n\t//printf( \"PCM Irx iop buf %d\\n\", gpIopBuf );\r\n\t//Dbug_Printf( \"PCM irx is initialized\\n\" );\r\n    return gThid;\r\n}\r\n\r\n// EzADPCM_QUIT\r\nvoid AdpcmQuit( void )\r\n{\r\n    DeleteThread (gThid);\r\n    gThid = 0;\r\n#if 0\r\n    DeleteSema (gSem);\r\n    gSem = 0;\r\n#endif\r\n    return;\r\n}\r\n\r\n// EzADPCM_PRELOADMUSIC\r\n// EzADPCM_PLAYMUSIC\r\nint AdpcmPlayMusic( int size, int preload_only )\r\n{\r\n    extern void AdpcmSetMusicVolumeDirect( unsigned int );\r\n\r\n    if ( gMusicInfo.status != PCM_STATUS_IDLE )\r\n\t{\r\n\t\tShowAction( \"NOTE NOTE NOTE NOTE Can't play music -- music isn't in Idle state.\\n\" );\r\n\t\treturn -1;\r\n    }\r\n\r\n    AdpcmSetMusicVolumeDirect( gMusicInfo.volume );\r\n\r\n\tif (preload_only)\r\n\t{\r\n\t\tgMusicInfo.m_preloadMode = TRUE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgMusicInfo.m_preloadMode = FALSE;\r\n\t}\r\n\t\t\t\t\r\n\tgMusicInfo.status = PCM_STATUS_PRELOAD;\r\n\tgMusicInfo.loadState = MUSIC_LOAD_STATE_IDLE;\r\n\tgMusicInfo.size = size;\r\n\tgMusicInfo.m_iopBufLoaded[0] = TRUE;\r\n\tgMusicInfo.m_iopBufLoaded[1] = FALSE;\r\n\tgEECommand &= ~PCMSTATUS_NEED_MUSIC_BUFFER_0;\r\n\tif (size > MUSIC_HALF_IOP_BUFFER_SIZE)\r\n\t{\r\n\t\tgEECommand |= PCMSTATUS_NEED_MUSIC_BUFFER_1;\r\n\t}\r\n\tgEECommand |= PCMSTATUS_MUSIC_PLAYING;\r\n\tShowAction( \"Starting music\\n\" );\r\n\tSmallShowAction( \"-mb\" );\r\n    return 0;\r\n}\r\n\r\nvoid AdpcmSetStreamVolume( unsigned int vol, int whichStream );\r\n\r\n// EzADPCM_PRELOADMUSIC\r\n// EzADPCM_PLAYSTREAM\r\nint AdpcmPlayStream( int size, int whichStream, unsigned int vol, unsigned int pitch, int preload_only )\r\n{\r\n    if ( gStreamInfo[ whichStream ].status != PCM_STATUS_IDLE )\r\n\t{\r\n\t\tprintf( \"trying to play stream when stream already playing!\\n\" );\r\n\t\treturn -1;\r\n    }\r\n\r\n\tif (preload_only)\r\n\t{\r\n\t\tgStreamInfo[ whichStream ].m_preloadMode = TRUE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgStreamInfo[ whichStream ].m_preloadMode = FALSE;\r\n\t\tAdpcmSetStreamVolume( vol, whichStream );\r\n\t\tgStreamInfo[ whichStream ].pitch = STREAM_PITCH( pitch );\r\n\t}\r\n\r\n\t// have to make sure it's okay to use the stream DMA first...\r\n\tgStreamInfo[ whichStream ].status = PCM_STATUS_PRELOAD;\r\n\tgStreamInfo[ whichStream ].size = size;\r\n\tgStreamInfo[ whichStream ].m_iopBufLoaded[0] = TRUE;\r\n\tgStreamInfo[ whichStream ].m_iopBufLoaded[1] = FALSE;\r\n\tgEECommand &= ~( PCMSTATUS_NEED_STREAM0_BUFFER_0 << whichStream );\r\n\tif (size > STREAM_HALF_IOP_BUFFER_SIZE)\r\n\t{\r\n\t\tgEECommand |= PCMSTATUS_NEED_STREAM0_BUFFER_1 << whichStream;\r\n\t}\r\n\tgStreamInfo[ whichStream ].loadState = STREAM_LOAD_STATE_IDLE;\r\n\tgEECommand |= ( PCMSTATUS_STREAM_PLAYING( whichStream ) );\r\n\tShowAction( \"Starting stream\\n\" );\r\n\tSmallShowAction( \"-sb\" );\r\n\treturn 0;\r\n}\r\n\r\n// EzADPCM_PLAYPRELOADEDMUSIC\r\nint AdpcmPlayPreloadedMusic()\r\n{\r\n\t// Tell update loop it is OK to play\r\n\tgMusicInfo.m_preloadMode = FALSE;\r\n\tSignalSema(gSem);\t// Signal RefreshStreams() to be called\r\n\r\n\tShowAction( \"Playing preloaded music\\n\" );\r\n\tSmallShowAction( \"-ppm\" );\r\n\treturn 0;\r\n}\r\n\r\n// EzADPCM_PLAYPRELOADEDSTREAM\r\nint AdpcmPlayPreloadedStream(int whichStream, unsigned int vol, unsigned int pitch)\r\n{\r\n\tAdpcmSetStreamVolume( vol, whichStream );\r\n\tgStreamInfo[ whichStream ].pitch = STREAM_PITCH( pitch );\r\n\r\n\t// Tell update loop it is OK to play\r\n\tgStreamInfo[ whichStream ].m_preloadMode = FALSE;\r\n\tSignalSema(gSem);\t// Signal RefreshStreams() to be called\r\n\r\n\tShowAction( \"Playing preloaded stream\\n\" );\r\n\tSmallShowAction( \"-pps\" );\r\n\treturn 0;\r\n}\r\n\r\n/* internal */\r\nvoid _AdpcmSetMusicVoiceMute( void )\r\n{\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_L_VOICE << 1) | SD_VP_VOLL, 0);\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_L_VOICE << 1) | SD_VP_VOLR, 0);\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_R_VOICE << 1) | SD_VP_VOLL, 0);\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_R_VOICE << 1) | SD_VP_VOLR, 0);\r\n    return;\r\n}\r\n\r\n/* internal */\r\nvoid _AdpcmSetStreamVoiceMute( int whichVoice )\r\n{\r\n    sceSdSetParam( STREAM_CORE | ( STREAM_VOICE( whichVoice ) << 1) | SD_VP_VOLL, 0);\r\n    sceSdSetParam( STREAM_CORE | ( STREAM_VOICE( whichVoice ) << 1) | SD_VP_VOLR, 0);\r\n    return;\r\n}\r\n\r\nvoid StopMusic( void )\r\n{\r\n\tsceSdSetCoreAttr( MUSIC_CORE | SD_C_IRQ_ENABLE, 0 );\r\n\t_AdpcmSetMusicVoiceMute( );\r\n\tsceSdSetSwitch( MUSIC_CORE | SD_S_KOFF, ( 1 << MUSIC_R_VOICE ) | ( 1 << MUSIC_L_VOICE ) );\r\n\tShowAction( \"Stopping music\\n\" );\r\n    SmallShowAction( \"-!sm!\" );\r\n\tgMusicInfo.stop = 0;\r\n\tgMusicInfo.loadState = MUSIC_LOAD_STATE_IDLE;\r\n\t//gMusicInfo.m_iopBufLoaded[0] = FALSE;\t\t// This should not be necessary\r\n\t//gMusicInfo.m_iopBufLoaded[1] = FALSE;\r\n\tgEECommand &= ~( PCMSTATUS_MUSIC_PLAYING | PCMSTATUS_MUSIC_READY | PCMSTATUS_NEED_MUSIC_BUFFER_0 | PCMSTATUS_NEED_MUSIC_BUFFER_1 );\r\n\tgMusicInfo.status = PCM_STATUS_IDLE;\r\n}\r\n\r\nvoid StopStream( int whichStream )\r\n{\r\n\tsceSdSetCoreAttr( STREAM_CORE | SD_C_IRQ_ENABLE, 0 );\r\n\t_AdpcmSetStreamVoiceMute( whichStream );\r\n\tsceSdSetSwitch( STREAM_CORE | SD_S_KOFF, ( 1 << STREAM_VOICE( whichStream ) ) );\r\n\tShowAction( \"Stopping stream\\n\" );\r\n    SmallShowAction( \"-!ss!\" );\r\n\tgStreamInfo[ whichStream ].stop = 0;\r\n\tgStreamInfo[ whichStream ].loadState = STREAM_LOAD_STATE_IDLE;\r\n\t//gStreamInfo[ whichStream ].m_iopBufLoaded[0] = FALSE;\t\t// This should not be necessary\r\n\t//gStreamInfo[ whichStream ].m_iopBufLoaded[1] = FALSE;\r\n\tgEECommand &= ~( ( PCMSTATUS_STREAM0_PLAYING | PCMSTATUS_STREAM0_READY | PCMSTATUS_NEED_STREAM0_BUFFER_0 | PCMSTATUS_NEED_STREAM0_BUFFER_1 ) << whichStream );\r\n\tgStreamInfo[ whichStream ].status = PCM_STATUS_IDLE;\r\n}\r\n\r\n#define NUM_WAIT_CLICKS 10000\r\n\r\n// EzADPCM_STOPMUSIC\r\nint AdpcmStopMusic( void )\r\n{\r\n\tint i;\r\n\tint j = 0;\r\n\r\n\tif ( gMusicInfo.status != PCM_STATUS_IDLE )\r\n\t{\r\n\t\tShowStop( \"stopmusic\" );\r\n\t\tgMusicInfo.stop++;\r\n\t\tSignalSema(gSem);\t// Signal RefreshStreams() to be called\r\n\t\t// Why the hell are we waiting????  This is VERY lame!\r\n\t\twhile ( gMusicInfo.status != PCM_STATUS_IDLE )\r\n\t\t{\r\n\t\t\tfor ( i = 0; i < NUM_WAIT_CLICKS; i++ )\r\n\t\t\t\t;\r\n\t\t\tif ( j++ > NUM_WAIT_CLICKS )\r\n\t\t\t{\r\n\t\t\t\tj = 0;\r\n\t\t\t\tprintf( \"...Waiting for music stop...\\n\" );\r\n\t\t\t}\r\n\t\t}\r\n\t\tShowStop( \"\\n\" );\r\n\t\treturn ( 1 );\r\n    }\r\n\treturn ( 0 );\r\n}\r\n\r\n// EzADPCM_STOPSTREAM\r\nint AdpcmStopStream( int whichStream )\r\n{\r\n\tint i;\r\n\tint j = 0;\r\n\r\n\tif ( gStreamInfo[ whichStream ].status != PCM_STATUS_IDLE )\r\n\t{\r\n\t\tShowStop( \"Stop stream\" );\r\n\t\tgStreamInfo[ whichStream ].stop++;\r\n\t\tSignalSema(gSem);\t// Signal RefreshStreams() to be called\r\n\t\t// Why the hell are we waiting????  This is VERY lame!\r\n\t\twhile ( gStreamInfo[ whichStream ].status != PCM_STATUS_IDLE )\r\n\t\t{\r\n\t\t\tfor ( i = 0; i < NUM_WAIT_CLICKS; i++ )\r\n\t\t\t\t;\r\n\t\t\tif ( j++ > NUM_WAIT_CLICKS )\r\n\t\t\t{\r\n\t\t\t\tprintf( \"...Waiting for stream %d stop...\\n\", whichStream );\r\n\t\t\t\tj = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\tShowStop( \"\\n\" );\r\n\t\tSmallShowAction( \"-ss\" );\r\n\t\tShowAction( \"Stopped stream\\n\" );\r\n\t\treturn ( 1 );\r\n    }\r\n\treturn ( 0 );\r\n}\r\n\r\n// EzADPCM_SETMUSICVOL\r\nvoid AdpcmSetMusicVolume( unsigned int vol )\r\n{\r\n    gMusicInfo.volume = vol;\r\n    gMusicInfo.volumeSet = 1;\r\n    return;\r\n}\r\n\r\n// EzADPCM_SETMUSICVOLDIRECT\r\nvoid AdpcmSetMusicVolumeDirect( unsigned int vol )\r\n{\r\n    gMusicInfo.volume = vol;\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_L_VOICE << 1 ) | SD_VP_VOLL, vol );\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_L_VOICE << 1 ) | SD_VP_VOLR, 0 );\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_R_VOICE << 1 ) | SD_VP_VOLL, 0 );\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_R_VOICE << 1 ) | SD_VP_VOLR, vol );\r\n    return;\r\n}\r\n\r\n// Done on the EE now\r\n//void AdpcmSetStreamGlobVol( unsigned int volPercent )\r\n//{\r\n//\tgStreamVolPercent = volPercent;\r\n//}\r\n\r\n#define PERCENT_MULT ( ( 1 << 16 ) / 100 )\r\n#define PERCENT( x, y ) ( ( ( x ) * ( y ) * PERCENT_MULT ) >> 16 )\r\n\r\n// EzADPCM_SETSTREAMVOL\r\nvoid AdpcmSetStreamVolume( unsigned int vol, int whichStream )\r\n{\r\n    gStreamInfo[ whichStream ].volume = vol;\r\n    gStreamInfo[ whichStream ].volumeSet = 1;\r\n    return;\r\n}\r\n\r\n// EzADPCM_SETSTREAMVOLDIRECT\r\nvoid AdpcmSetStreamVolumeDirect( unsigned int vol, int whichStream )\r\n{\r\n    //sceSdSetParam ( STREAM_CORE | ( STREAM_VOICE( whichStream ) << 1 ) | SD_VP_VOLL, PERCENT( gStreamVolPercent, _Lch( vol ) ) );\r\n    //sceSdSetParam ( STREAM_CORE | ( STREAM_VOICE( whichStream ) << 1 ) | SD_VP_VOLR, PERCENT( gStreamVolPercent, _Rch( vol ) ) );\r\n    sceSdSetParam ( STREAM_CORE | ( STREAM_VOICE( whichStream ) << 1 ) | SD_VP_VOLL, _Lch( vol ) );\r\n    sceSdSetParam ( STREAM_CORE | ( STREAM_VOICE( whichStream ) << 1 ) | SD_VP_VOLR, _Rch( vol ) );\r\n    return;\r\n}\r\n\r\n// Shouldn't need these unless debugging or something --\r\n// Instead just get gEECommand each frame and act accordingly.\r\n\r\n// EzADPCM_GETMUSICSTATUS\r\nunsigned int AdpcmGetMusicStatus( void )\r\n{\r\n\treturn gMusicInfo.status;\r\n}\r\n\r\n// EzADPCM_GETSTREAMSTATUS\r\n/*unsigned int AdpcmGetStreamStatus( int whichStream )\r\n{\r\n    return gStreamInfo[ whichStream ].status;\r\n} */\r\n\r\nstatic volatile unsigned int sEELastCommand = 0xFFFFFFFF;\r\n\r\n// EzADPCM_GETSTATUS\r\nunsigned int AdpcmGetStatus( void )\r\n{\r\n\tunsigned int temp;\r\n\ttemp = gEECommand;\r\n\tgEECommand &= ~( PCMSTATUS_NEED_MUSIC_BUFFER_0 | PCMSTATUS_NEED_MUSIC_BUFFER_1 | \r\n\t\t\t\t\tPCMSTATUS_NEED_STREAM0_BUFFER_0 | PCMSTATUS_NEED_STREAM0_BUFFER_1 |\r\n\t\t\t\t\tPCMSTATUS_NEED_STREAM1_BUFFER_0 | PCMSTATUS_NEED_STREAM1_BUFFER_1 |\r\n\t\t\t\t\tPCMSTATUS_NEED_STREAM2_BUFFER_0 | PCMSTATUS_NEED_STREAM2_BUFFER_1 );\r\n\tsEELastCommand = gEECommand;\r\n#if SHOW_SMALL_COMMANDS\r\n\tif ( temp & ( PCMSTATUS_NEED_MUSIC_BUFFER_0 | PCMSTATUS_NEED_MUSIC_BUFFER_1 | \r\n\t\t\t\t\tPCMSTATUS_NEED_STREAM0_BUFFER_0 | PCMSTATUS_NEED_STREAM0_BUFFER_1 |\r\n\t\t\t\t\tPCMSTATUS_NEED_STREAM1_BUFFER_0 | PCMSTATUS_NEED_STREAM1_BUFFER_1 |\r\n\t\t\t\t\tPCMSTATUS_NEED_STREAM2_BUFFER_0 | PCMSTATUS_NEED_STREAM2_BUFFER_1 ) )\r\n\t{\r\n\t\tShowSmallCommand( \" <_L_>\" );\r\n\t}\r\n#endif\r\n\treturn temp;\r\n}\r\n\r\nint AdpcmHasStatusChanged( void )\r\n{\r\n\treturn sEELastCommand != gEECommand;\r\n}\r\n\r\n// ================================================================\r\n\r\n#define _ADPCM_MARK_START 0x04\r\n#define _ADPCM_MARK_LOOP  0x02\r\n#define _ADPCM_MARK_END   0x01\r\n\r\n#define _AdpcmSetMarkFINAL(a,s) { \\\r\n  *( ( unsigned int * ) ( ( a ) + ( s ) - 16 ) ) = 0; \\\r\n  *( ( unsigned int * ) ( ( a ) + ( s ) - 12 ) ) = 0; \\\r\n  *( ( unsigned int * ) ( ( a ) + ( s ) - 8 ) ) = 0; \\\r\n  *( ( unsigned int * ) ( ( a ) + ( s ) - 4 ) ) = 0; \\\r\n  *((unsigned char *)((a)+(s)-0x0f)) = (_ADPCM_MARK_LOOP | _ADPCM_MARK_START | _ADPCM_MARK_END); \\\r\n  FlushDcache (); }\r\n\r\n\r\n// Start of loop - note that a (address is either the start or mid address of the IOP buffer. s is half the buffer size)\r\n#define _AdpcmSetMarkSTART(a,s) { \\\r\n  *((unsigned char *)((a)+1)) = \\\r\n\t(_ADPCM_MARK_LOOP | _ADPCM_MARK_START); \\\r\n  *((unsigned char *)((a)+0x10+1)) = \\\r\n\t_ADPCM_MARK_LOOP; \\\r\n  *((unsigned char *)((a)+(s)-0x0f)) = \\\r\n\t_ADPCM_MARK_LOOP; \\\r\n\tFlushDcache (); }\r\n\r\n// End of loop - note that a (address is either the start or mid address of the IOP buffer. s is half the buffer size)\r\n#define _AdpcmSetMarkEND(a,s) { \\\r\n  *((unsigned char *)((a)+1)) = \\\r\n\t _ADPCM_MARK_LOOP; \\\r\n  *((unsigned char *)((a)+0x10+1)) = \\\r\n\t_ADPCM_MARK_LOOP; \\\r\n  *((unsigned char *)((a)+(s)-0x0f)) = \\\r\n\t(_ADPCM_MARK_LOOP | _ADPCM_MARK_END); \\\r\n\tFlushDcache (); }\r\n\r\n// Preload Start marker - note that a (address is the start address of the IOP buffer. s is buffer size)\r\n\r\n#define _AdpcmSetMarkSTARTpre(a,s) { \\\r\n  *((unsigned char *)((a)+1)) = \\\r\n\t(_ADPCM_MARK_LOOP | _ADPCM_MARK_START); \\\r\n  *((unsigned char *)((a)+0x10+1)) = \\\r\n\t_ADPCM_MARK_LOOP; \\\r\n\tFlushDcache (); }\r\n\r\n// Preload End marker - note that a (address is the start address of the IOP buffer. s is buffer size)\r\n#define _AdpcmSetMarkENDpre(a,s) { \\\r\n  *((unsigned char *)((a)+(s)-0xf)) = \\\r\n\t(_ADPCM_MARK_LOOP | _ADPCM_MARK_END); \\\r\n\tFlushDcache (); }\r\n\r\n/* internal */\r\nstatic int _AdpcmDmaIntMusic(int ch, void *common)\t// DMA Interrupt -- when transfering data to SPU2 from IOP\r\n{\r\n\t//Kprintf(\"Got music IRQ for channel %d\\n\", ch);\r\n\tif ( gMusicInfo.status != PCM_STATUS_IDLE )\r\n\t{\r\n\t\tgMusicInfo.m_spuTransDone = TRUE;\r\n\t\treturn 1;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n/* internal */\r\nstatic int _AdpcmDmaIntStream(int ch, void *common)\t// DMA Interrupt -- when transfering data to SPU2 from IOP\r\n{\r\n\tif ( gUsingStreamDMA )\r\n\t{\r\n\t\tint whichStream = gUsingStreamDMA - 1;\r\n\t\t//Kprintf(\"Received Stream DMA 0 callback\\n\");\r\n\t\tif ( gStreamInfo[ whichStream ].status != PCM_STATUS_IDLE )\r\n\t\t{\r\n\t\t\tgStreamInfo[ whichStream ].m_spuTransDone = TRUE;\r\n\t\t\tgUsingStreamDMA = 0;\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t}\r\n\telse if (gSPUUsingStreamDMA)\r\n\t{\r\n\t\tgSPUUsingStreamDMA = 0;\r\n\t\t//Kprintf(\"Received SPU DMA 0 callback\\n\");\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//Kprintf(\"Received outside DMA 0 callback\\n\");\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid UpdateMusic( void )\r\n{\r\n\tstruct StreamInfo *pInfo;\r\n\tpInfo = &gMusicInfo;\r\n\tswitch ( pInfo->status )\r\n\t{\r\n\t\tcase PCM_STATUS_IDLE:\r\n\t\t\tbreak;\r\n\r\n\t\tcase PCM_STATUS_PRELOAD:\r\n\t\t\tswitch ( pInfo->loadState )\r\n\t\t\t{\r\n\t\t\t\tcase ( MUSIC_LOAD_STATE_IDLE ):\r\n\t\t\t\t{\r\n\t\t\t\t\tShowState( \"music preload l\\n\" );\r\n\t\t\t\t\tSmallShowMusicState( \"-MPL\" );\r\n\t\t\t\t\tpInfo->m_spuBufSide = _1st;\r\n\t\t\t\t\tpInfo->m_iopBufIndex = _1st;\r\n\t\t\t\t\tpInfo->m_iopOffset = 0;\r\n\t\t\t\t\tpInfo->remaining = pInfo->size;\r\n\r\n\t\t\t\t\t// preload left:\r\n\t\t\t\t\tif (DownloadMusic(_L))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpInfo->loadState++;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase ( MUSIC_LOAD_STATE_PRELOADING_L ):\r\n\t\t\t\t{\r\n\t\t\t\t\t// Check that transfer is done\r\n\t\t\t\t\tif (!pInfo->m_spuTransDone)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( pInfo->stop )\t\t// Don't stop until we know the first CD stream and DMA to SPU have finished\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tStopMusic( );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tShowState( \"music preload r\\n\" );\r\n\t\t\t\t\tSmallShowMusicState( \"-MPR\" );\r\n\r\n\t\t\t\t\t// preload right:\r\n\t\t\t\t\tDownloadMusic(_R);\r\n\r\n\t\t\t\t\tpInfo->loadState++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\tcase ( MUSIC_LOAD_STATE_PRELOADING_R ):\r\n\t\t\t\t{\r\n\t\t\t\t\t// Check that transfer is done\r\n\t\t\t\t\tif (!pInfo->m_spuTransDone)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( pInfo->stop )\t\t// Don't stop until we the DMA to SPU has finished\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tStopMusic( );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// This will let the EE know that we are ready to play\r\n\t\t\t\t\tgEECommand |= PCMSTATUS_MUSIC_READY;\r\n\r\n\t\t\t\t\t// Now check if we are in a preload_only mode\r\n\t\t\t\t\tif (pInfo->m_preloadMode)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// We need to wait until we get a message from the EE to start\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tShowState( \"Music starting -- waiting for IRQ\\n\" );\r\n\t\t\t\t\tSmallShowMusicState( \" -MSIRQ\" );\r\n\r\n\t\t\t\t\tpInfo->status = PCM_STATUS_RUNNING;\r\n\t\t\t\t\tIncMusicBuffer();\r\n\r\n\t\t\t\t\t// Play music\r\n\t\t\t\t\tStartMusic();\r\n#if TEST_PLAY_TIMING\r\n\t\t\t\t\tif (test_timing_send_timing_result)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttest_timing_hit_point = TRUE;\r\n\t\t\t\t\t}\r\n#endif // TEST_PLAY_TIMING\r\n\r\n\t\t\t\t\tpInfo->loadState++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase PCM_STATUS_RUNNING:\r\n\t\t\tpInfo->m_spuCurAddr = GetNAX( MUSIC_CORE, MUSIC_L_VOICE );\r\n\r\n\t\t\tswitch ( pInfo->loadState )\r\n\t\t\t{\r\n\t\t\t\tcase ( MUSIC_LOAD_STATE_WAITING_FOR_REFRESH ):\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( pInfo->stop )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//pInfo->status = PCM_STATUS_READY_TO_STOP;\r\n\t\t\t\t\t\tStopMusic( );\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Wait for SPU buffer cross\r\n\t\t\t\t\tif (!OutsideMusicSPULoadBuffer())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tShowState( \"Music Running -- Wait For Last Load\\n\" );\r\n\t\t\t\t\tSmallShowStreamState( \"-MRWLL\" );\r\n\r\n\t\t\t\t\t// Change state and go immediately into it\r\n\t\t\t\t\tpInfo->loadState++;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcase ( MUSIC_LOAD_STATE_WAITING_FOR_LAST_LOAD ):\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( pInfo->stop )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tStopMusic( );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// After we got this far, we've crossed the SPU buffer and we\r\n\t\t\t\t\t// know we need to download.  But if the new IOP buffer isn't\r\n\t\t\t\t\t// loaded and download before we cross SPU buffers AGAIN, then \r\n\t\t\t\t\t// we know the stream has failed.  Time to panic!\r\n\t\t\t\t\tif (!OutsideMusicSPULoadBuffer())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (!(gEECommand & PCMSTATUS_PANIC))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Print only once\r\n\t\t\t\t\t\t\tKprintf(\"ERROR: Music did not load data in time.  In SPU buffer %d and pos %x\\n\", pInfo->m_spuBufSide, pInfo->m_spuCurAddr - MUSIC_L_SPU_BUF_LOC);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tgEECommand |= PCMSTATUS_PANIC;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tShowState( \"Music Running -- Loading L\\n\" );\r\n\t\t\t\t\tSmallShowMusicState( \"-MRLL\" );\r\n\r\n\t\t\t\t\t// load in left side:\r\n\t\t\t\t\tif (DownloadMusic(_L))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpInfo->loadState++;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcase ( MUSIC_LOAD_STATE_LOADING_L ):\r\n\t\t\t\t{\r\n\t\t\t\t\t// Check that transfer is done\r\n\t\t\t\t\tif (!pInfo->m_spuTransDone)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t//Kprintf( \"Music Running -- Loading R at offset %x and address %x\\n\", pInfo->m_iopOffset, gpIopBuf + MUSIC_R_IOP_OFFSET + pInfo->m_iopOffset );\r\n\t\t\t\t\tShowState( \"Music Running -- Loading R\\n\" );\r\n\t\t\t\t\tSmallShowMusicState( \"-MRLR\" );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// load in right side:\r\n\t\t\t\t\tDownloadMusic(_R);\r\n\r\n\t\t\t\t\tpInfo->loadState++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase ( MUSIC_LOAD_STATE_LOADING_R ):\r\n\t\t\t\t{\r\n\t\t\t\t\t// Check that transfer is done\r\n\t\t\t\t\tif (!pInfo->m_spuTransDone)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tShowState( \"Music Running -- Waiting for IRQ\\n\" );\r\n\t\t\t\t\tSmallShowMusicState( \"-MRIRQ\" );\r\n\r\n\t\t\t\t\tIncMusicBuffer();\r\n\r\n\t\t\t\t\tpInfo->loadState = MUSIC_LOAD_STATE_WAITING_FOR_REFRESH;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tprintf( \"Unknown music loading state %d\\n\", pInfo->loadState );\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase PCM_STATUS_TERMINATE: \r\n\t\t\tpInfo->m_spuCurAddr = GetNAX( MUSIC_CORE, MUSIC_L_VOICE );\r\n\r\n\t\t\tif ( !pInfo->stop && ( ( pInfo->m_spuCurAddr > pInfo->m_spuEndAddr ) || ( pInfo->m_spuCurAddr <= pInfo->m_spuEndAddr - 16 ) ) )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tShowState( \"Music at end\\n\" );\r\n\r\n\t\tcase PCM_STATUS_READY_TO_STOP:\r\n\t\t\tShowState( \"Music terminate\\n\" );\r\n\t\t\tSmallShowMusicState( \"-MT!!!\" );\r\n\t\t\tStopMusic( );\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\tprintf( \"unknown music status in pcm irx!!!\\n\" );\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid UpdateStream( int whichStream )\r\n{\r\n\tstruct StreamInfo *pInfo;\r\n\tpInfo = &gStreamInfo[ whichStream ];\r\n\r\n\tswitch ( pInfo->status )\r\n\t{\r\n\t\tcase PCM_STATUS_IDLE:\r\n\t\t\tbreak;\r\n\r\n\t\tcase PCM_STATUS_PRELOAD:\r\n\t\t\tswitch ( pInfo->loadState )\r\n\t\t\t{\r\n\t\t\t\tcase ( STREAM_LOAD_STATE_IDLE ):\r\n\t\t\t\t{\r\n\t\t\t\t\tShowState( \"stream preload l\\n\" );\r\n\t\t\t\t\tSmallShowStreamState( \"-SPL\" );\r\n\r\n\t\t\t\t\tpInfo->m_spuBufSide = _1st;\r\n\t\t\t\t\tpInfo->m_iopBufIndex = _1st;\r\n\t\t\t\t\tpInfo->m_iopOffset = 0;\r\n\t\t\t\t\tpInfo->remaining = pInfo->size;\r\n\r\n\t\t\t\t\tif (DownloadStream(whichStream))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpInfo->loadState++;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase ( STREAM_LOAD_STATE_PRELOADING ):\r\n\t\t\t\t{\r\n\t\t\t\t\tShowState( \"Stream starting -- waiting for IRQ\\n\" );\r\n\t\t\t\t\tSmallShowStreamState( \"-SSIRQ\" );\r\n\r\n\t\t\t\t\t// Check that transfer is done\r\n\t\t\t\t\tif (!pInfo->m_spuTransDone)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( pInfo->stop )\t\t// Don't stop until we know the first CD stream and DMA to SPU have finished\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tStopStream( whichStream );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// This will let the EE know that we are ready to play\r\n\t\t\t\t\tgEECommand |= PCMSTATUS_STREAM_READY(whichStream);\r\n\r\n\t\t\t\t\t// Now check if we are in a preload_only mode\r\n\t\t\t\t\tif (pInfo->m_preloadMode)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// We need to wait until we get a message from the EE to start\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tpInfo->status = PCM_STATUS_RUNNING;\r\n\t\t\t\t\tIncStreamBuffer(whichStream);\r\n\r\n\t\t\t\t\t// Play the stream\r\n\t\t\t\t\tStartStream(whichStream);\r\n\t\t\t\t\t//Kprintf(\"Started playing stream %d; paused = %d; volume = %x\\n\", whichStream, gStreamInfo[ whichStream ].paused, pInfo->volume);\r\n\r\n\t\t\t\t\tpInfo->loadState++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase PCM_STATUS_RUNNING:\r\n\t\t\tpInfo->m_spuCurAddr = GetNAX( STREAM_CORE, STREAM_VOICE( whichStream ) );\r\n\r\n\t\t\tswitch ( pInfo->loadState )\r\n\t\t\t{\r\n\t\t\t\tcase ( STREAM_LOAD_STATE_WAITING_FOR_REFRESH ):\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( pInfo->stop )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//pInfo->status = PCM_STATUS_READY_TO_STOP;\r\n\t\t\t\t\t\tStopStream( whichStream );\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Wait for SPU buffer cross\r\n\t\t\t\t\tif (!OutsideStreamSPULoadBuffer(whichStream))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tShowState( \"Stream Running -- Wait For Last Load\\n\" );\r\n\t\t\t\t\tSmallShowStreamState( \"-SRWLL\" );\r\n\r\n\t\t\t\t\t// Inc state and start it directly\r\n\t\t\t\t\tpInfo->loadState++;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcase ( STREAM_LOAD_STATE_WAITING_FOR_LAST_LOAD ):\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( pInfo->stop )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tStopStream( whichStream );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// After we got this far, we've crossed the SPU buffer and we\r\n\t\t\t\t\t// know we need to download.  But if the new IOP buffer isn't\r\n\t\t\t\t\t// loaded and download before we cross SPU buffers AGAIN, then \r\n\t\t\t\t\t// we know the stream has failed.  Time to panic!\r\n\t\t\t\t\tif (!OutsideStreamSPULoadBuffer(whichStream))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (!(gEECommand & PCMSTATUS_PANIC))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Print only once\r\n\t\t\t\t\t\t\tKprintf(\"ERROR: Stream %d did not load data in time.  In SPU buffer %d and pos %x\\n\", whichStream, pInfo->m_spuBufSide, pInfo->m_spuCurAddr - STREAM_SPU_BUF_LOC( whichStream ));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tgEECommand |= PCMSTATUS_PANIC;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tShowState( \"Stream Running -- Loading\\n\" );\r\n\t\t\t\t\tSmallShowStreamState( \"-SRL\" );\r\n\r\n\t\t\t\t\tif (DownloadStream(whichStream))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpInfo->loadState++;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase ( STREAM_LOAD_STATE_LOADING ):\r\n\t\t\t\t{\r\n\t\t\t\t\t// Check that transfer is done\r\n\t\t\t\t\tif (!pInfo->m_spuTransDone)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tShowState( \"Stream Running -- Waiting for IRQ\\n\" );\r\n\t\t\t\t\tSmallShowStreamState( \"-SRIRQ\" );\r\n\r\n\t\t\t\t\tIncStreamBuffer(whichStream);\r\n\r\n\t\t\t\t\tpInfo->loadState = STREAM_LOAD_STATE_WAITING_FOR_REFRESH;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tprintf( \"Unknown Stream loading state %d\\n\", pInfo->loadState );\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase PCM_STATUS_TERMINATE: \r\n\t\t\tpInfo->m_spuCurAddr = GetNAX( STREAM_CORE, STREAM_VOICE( whichStream ) );\r\n\r\n\t\t\tif ( !pInfo->stop && ( ( pInfo->m_spuCurAddr > pInfo->m_spuEndAddr ) || ( pInfo->m_spuCurAddr <= pInfo->m_spuEndAddr - 16 ) ) )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\tcase PCM_STATUS_READY_TO_STOP:\r\n\t\t\tif ( gUsingStreamDMA != (whichStream + 1) )\r\n\t\t\t{\r\n\t\t\t\tShowState( \"Stream terminate\\n\" );\r\n\t\t\t\tSmallShowStreamState( \"-ST!!!\" );\r\n\t\t\t\tStopStream( whichStream );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\tprintf( \"unknown stream status in pcm irx!!!\\n\" );\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n// Reserve Stream DMA channel\r\nint LockDMA( int whichStream )\r\n{\r\n\tif ( gSPUUsingStreamDMA )\r\n\t{\r\n\t\tSmallShowStreamState( \" -|spu_no\" );\t\t\r\n\t\t//Kprintf(\"******* Can't lock DMA for Stream %d because of SPU\\n\", whichStream);\r\n\t\treturn FALSE;\r\n\t}\r\n\tif ( gUsingStreamDMA )\r\n\t{\r\n\t\tSmallShowStreamState( \" -|no\" );\t\t\r\n\t\t//Kprintf(\"******* Can't lock DMA for Stream %d\\n\", whichStream);\r\n\t\treturn FALSE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSmallShowStreamState( \" -|ok\" );\t\t\r\n\t\tgUsingStreamDMA = 1 + whichStream;\r\n\t\t//Kprintf(\"Locked DMA for Stream %d\\n\", whichStream);\r\n\t\treturn TRUE;\r\n\t}\r\n}\r\n\r\n/**********************************************************************************\r\nGetNAX\r\n\tGet current NAX (Address where channel is playing in SPU RAM)\r\n\tCode must check the NAX 3 times to decide which result is correct.\r\n***********************************************************************************/\r\nu_int GetNAX(int core,int ch)\r\n{\r\n\tu_int pos,pos2,pos3;\r\n\tch <<= 1;\r\n\r\n\twhile(1)\r\n\t{\r\n\t\tpos=sceSdGetAddr(core|ch|SD_VA_NAX);\r\n\t\tpos2=sceSdGetAddr(core|ch|SD_VA_NAX);\r\n\t\tpos3=sceSdGetAddr(core|ch|SD_VA_NAX);\r\n\r\n\t\tif (pos == pos2)\r\n\t\t\treturn(pos);\r\n\t\telse if (pos2 == pos3)\r\n\t\t\treturn(pos2);\r\n\t}\r\n}\r\n\r\n#if CHECK_TRANSFER_INTEGRITY\r\nvoid CheckTransfer( int dmaCh )\r\n{\r\n\tif ( !sceSdVoiceTransStatus( dmaCh, SD_TRANS_STATUS_CHECK ) )\r\n\t{\r\n\t\tint i;\r\n\t\tprintf( \"waiting for voicetrans\" );\r\n\t\twhile ( !sceSdVoiceTransStatus( dmaCh, SD_TRANS_STATUS_CHECK ) )\r\n\t\t{\r\n\t\t\tprintf( \".\" );\r\n\t\t\tfor ( i = 0; i < NUM_WAIT_CLICKS; i++ )\r\n\t\t\t\t;\r\n\t\t}\r\n\t\tprintf( \"\\n\" );\r\n\t}\r\n}\r\n#endif\t\t\t\t\t\r\n\r\n// Checks to see if current SPU playing address is outside the loading buffer\r\nint OutsideMusicSPULoadBuffer()\r\n{\r\n\tstruct StreamInfo *pInfo;\r\n\tpInfo = &gMusicInfo;\r\n\r\n\tif ( pInfo->m_spuBufSide == _1st )\r\n\t{\r\n\t\tif ( pInfo->m_spuCurAddr > ( MUSIC_L_SPU_BUF_LOC + SB_BUF_HALF ) )\r\n\t\t{\r\n#if CHECK_TRANSFER_INTEGRITY\r\n\t\t\tCheckTransfer( TRANS_DMA_CH_MUSIC );\r\n#endif\t\t\t\t\t\r\n\t\t\treturn TRUE;\r\n\t\t\t//Kprintf(\"music position past end for SPU buffer %d\\n\", pInfo->bufSide);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( pInfo->m_spuCurAddr < ( MUSIC_L_SPU_BUF_LOC + SB_BUF_HALF ) )\r\n\t\t{\r\n#if CHECK_TRANSFER_INTEGRITY\r\n\t\t\tCheckTransfer( TRANS_DMA_CH_MUSIC );\r\n#endif\t\t\t\t\t\r\n\t\t\treturn TRUE;\r\n\t\t\t//Kprintf(\"music position past end for SPU buffer %d\\n\", pInfo->bufSide);\r\n\t\t}\r\n\t}\r\n\r\n\treturn FALSE;\r\n}\r\n\r\n// Checks to see if current SPU playing address is outside the loading buffer\r\nint OutsideStreamSPULoadBuffer(int whichStream)\r\n{\r\n\tstruct StreamInfo *pInfo;\r\n\tpInfo = &gStreamInfo[ whichStream ];\r\n\r\n\tif ( pInfo->m_spuBufSide == _1st )\r\n\t{\r\n\t\tif ( pInfo->m_spuCurAddr > ( STREAM_SPU_BUF_LOC( whichStream ) + SB_BUF_HALF ) )\r\n\t\t{\r\n#if CHECK_TRANSFER_INTEGRITY\r\n\t\t\tCheckTransfer( TRANS_DMA_CH_STREAM );\r\n#endif\r\n\t\t\treturn TRUE;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( pInfo->m_spuCurAddr < ( STREAM_SPU_BUF_LOC( whichStream ) + SB_BUF_HALF ) )\r\n\t\t{\r\n#if CHECK_TRANSFER_INTEGRITY\r\n\t\t\tCheckTransfer( TRANS_DMA_CH_STREAM );\r\n#endif\t\t\t\t\t\r\n\t\t\treturn TRUE;\r\n\t\t}\r\n\t}\r\n\r\n\treturn FALSE;\r\n}\r\n\r\n// Downloads music data from the IOP to a SPU buffer\r\nint DownloadMusic(int whichChannel)\r\n{\r\n\tint music_iop_offset;\r\n\tint music_spu_addr;\r\n\r\n\tstruct StreamInfo *pInfo;\r\n\tpInfo = &gMusicInfo;\r\n\r\n\tif (whichChannel == _L)\r\n\t{\r\n\t\t//int iopBufferIndex = (pInfo->m_iopOffset < MUSIC_HALF_IOP_BUFFER_SIZE) ? 0 : 1;\r\n\t\tif (!pInfo->m_iopBufLoaded[pInfo->m_iopBufIndex])\r\n\t\t{\r\n\t\t\t//Kprintf(\"****** ERROR: Music buffer #%d not loaded.\\n\", pInfo->m_iopBufIndex);\r\n\t\t\treturn FALSE;\r\n\t\t}\r\n\r\n\t\tpInfo->m_spuTransSize = SB_BUF_HALF;\r\n\t\tpInfo->remaining -= SB_BUF_HALF;\r\n\t\tif ( pInfo->remaining < 0 )\r\n\t\t{\r\n\t\t\tpInfo->m_spuTransSize += pInfo->remaining;\r\n\t\t}\r\n\r\n\t\tmusic_iop_offset = MUSIC_L_IOP_OFFSET;\r\n\t\tmusic_spu_addr = MUSIC_L_SPU_BUF_LOC;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmusic_iop_offset = MUSIC_R_IOP_OFFSET;\r\n\t\tmusic_spu_addr = MUSIC_R_SPU_BUF_LOC;\r\n\t}\r\n\r\n\t// load in a side:\r\n\tif ( pInfo->m_spuBufSide == _1st )\r\n\t{\r\n\t\t_AdpcmSetMarkSTART( gpIopBuf + music_iop_offset + pInfo->m_iopOffset, pInfo->m_spuTransSize );\r\n\t}\r\n\tif ( pInfo->remaining <= 0 )\r\n\t{\r\n\t\t_AdpcmSetMarkFINAL( gpIopBuf + music_iop_offset + pInfo->m_iopOffset, pInfo->m_spuTransSize );\r\n\t\tpInfo->m_spuEndAddr = MUSIC_L_SPU_BUF_LOC + pInfo->m_spuTransSize + SB_BUF_HALF * pInfo->m_spuBufSide;\r\n\t}\r\n\telse if ( pInfo->m_spuBufSide == _2nd )\r\n\t{\r\n\t\t_AdpcmSetMarkEND( gpIopBuf + music_iop_offset + pInfo->m_iopOffset, pInfo->m_spuTransSize );\r\n\t}\r\n\r\n\tpInfo->m_spuTransDone = FALSE;\r\n\tsceSdVoiceTrans( TRANS_DMA_CH_MUSIC, ( SD_TRANS_MODE_WRITE | SD_TRANS_BY_DMA ),\r\n\t\t(unsigned char *) gpIopBuf + music_iop_offset + pInfo->m_iopOffset,\r\n\t\t( music_spu_addr + SB_BUF_HALF * pInfo->m_spuBufSide ), pInfo->m_spuTransSize );\r\n\t//Kprintf(\"Downloading music channel %d from IOP %x to SPU %x of size %d\\n\", whichChannel, gpIopBuf + music_iop_offset + pInfo->m_iopOffset,\r\n\t//\t\t( music_spu_addr + SB_BUF_HALF * pInfo->m_spuBufSide ), pInfo->m_spuTransSize );\r\n\r\n\r\n\treturn TRUE;\r\n}\r\n\r\n// Downloads audio stream data from the IOP to a SPU buffer\r\nint DownloadStream(int whichStream)\r\n{\r\n\tstruct StreamInfo *pInfo;\r\n\tpInfo = &gStreamInfo[ whichStream ];\r\n\r\n\t//iopBufferIndex = (pInfo->m_iopOffset < STREAM_HALF_IOP_BUFFER_SIZE) ? 0 : 1;\r\n\tif (!pInfo->m_iopBufLoaded[pInfo->m_iopBufIndex])\r\n\t{\r\n\t\t//Kprintf(\"****** ERROR: Stream %d buffer #%d not loaded.\\n\", whichStream, pInfo->m_iopBufIndex);\r\n\t\treturn FALSE;\r\n\t}\r\n\r\n\tif (!LockDMA(whichStream))\r\n\t{\r\n\t\treturn FALSE;\r\n\t}\r\n\r\n\tpInfo->m_spuTransSize = SB_BUF_HALF;\r\n\tpInfo->remaining -= SB_BUF_HALF;\r\n\tif ( pInfo->remaining < 0 )\r\n\t{\r\n\t\tpInfo->m_spuTransSize += pInfo->remaining;\r\n\t}\r\n\t//Kprintf( \"Stream: IOP offset %d, transfer %d, remaining %d\\n\", pInfo->m_iopOffset, pInfo->m_spuTransSize, pInfo->remaining);\r\n\r\n\t// load in left side:\r\n\tif ( pInfo->m_spuBufSide == _1st )\r\n\t{\r\n\t\t_AdpcmSetMarkSTART( gpIopBuf + STREAM_IOP_OFFSET( whichStream ) + pInfo->m_iopOffset, pInfo->m_spuTransSize );\r\n\r\n\t}\r\n\tif ( pInfo->remaining <= 0 )\r\n\t{\r\n\t\t_AdpcmSetMarkFINAL( gpIopBuf + STREAM_IOP_OFFSET( whichStream ) + pInfo->m_iopOffset, pInfo->m_spuTransSize );\r\n\t\tpInfo->m_spuEndAddr = STREAM_SPU_BUF_LOC( whichStream ) + pInfo->m_spuTransSize + SB_BUF_HALF * pInfo->m_spuBufSide;\r\n\t}\r\n\telse if ( pInfo->m_spuBufSide == _2nd )\r\n\t{\r\n\t\t_AdpcmSetMarkEND( gpIopBuf + STREAM_IOP_OFFSET( whichStream ) + pInfo->m_iopOffset, pInfo->m_spuTransSize );\r\n\t}\r\n\r\n\tpInfo->m_spuTransDone = FALSE;\r\n\tsceSdVoiceTrans( TRANS_DMA_CH_STREAM, ( SD_TRANS_MODE_WRITE | SD_TRANS_BY_DMA ),\r\n\t\t(unsigned char *) gpIopBuf + STREAM_IOP_OFFSET( whichStream ) + pInfo->m_iopOffset,\r\n\t\t( STREAM_SPU_BUF_LOC( whichStream ) + SB_BUF_HALF * pInfo->m_spuBufSide ), pInfo->m_spuTransSize );\r\n\r\n\t//Kprintf(\"Downloaded Stream %d buffer #%d\\n\", whichStream, iopBufferIndex);\r\n\r\n\treturn TRUE;\r\n}\r\n\r\nvoid IncMusicBuffer()\r\n{\r\n\tstruct StreamInfo *pInfo;\r\n\tpInfo = &gMusicInfo;\r\n\r\n\tpInfo->m_iopOffset += SB_BUF_HALF;\r\n\tpInfo->m_spuBufSide = ( pInfo->m_spuBufSide == _1st ) ? _2nd : _1st;\r\n\r\n\tif ( pInfo->remaining <= 0 )\r\n\t{\r\n\t\t// the vag data up to the end should contain all zeros,\r\n\t\t// so it doesn't matter that the interrupt won't happen until the end.\r\n\t\t// stop the music when it gets to the end:\r\n\t\tpInfo->status = PCM_STATUS_TERMINATE;\r\n\t\tShowState( \"Music last buffer\\n\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( (pInfo->m_iopBufIndex == _1st) && (pInfo->m_iopOffset >= MUSIC_HALF_IOP_BUFFER_SIZE) )\r\n\t\t{\r\n\t\t\t//Dbug_Printf( \"music move over\\n\" );\r\n\t\t\tpInfo->m_iopOffset += MUSIC_HALF_IOP_BUFFER_SIZE; // move over by half the size since L/R load in together...\r\n\t\t\tpInfo->m_iopBufIndex = _2nd;\r\n\t\t\tif ( pInfo->remaining > MUSIC_HALF_IOP_BUFFER_SIZE )\r\n\t\t\t{\r\n\t\t\t\tgEECommand |= PCMSTATUS_NEED_MUSIC_BUFFER_0;\r\n\t\t\t\tpInfo->m_iopBufLoaded[0] = FALSE;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( (pInfo->m_iopBufIndex == _2nd) && ( pInfo->m_iopOffset >= ( MUSIC_IOP_BUFFER_SIZE + MUSIC_HALF_IOP_BUFFER_SIZE ) ) )\r\n\t\t{\r\n\t\t\t//Dbug_Printf( \"music move back\\n\" );\r\n\t\t\tpInfo->m_iopOffset = 0;\r\n\t\t\tpInfo->m_iopBufIndex = _1st;\r\n\t\t\tif ( pInfo->remaining > MUSIC_HALF_IOP_BUFFER_SIZE )\r\n\t\t\t{\r\n\t\t\t\tgEECommand |= PCMSTATUS_NEED_MUSIC_BUFFER_1;\r\n\t\t\t\tpInfo->m_iopBufLoaded[1] = FALSE;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid IncStreamBuffer(int whichStream)\r\n{\r\n\tstruct StreamInfo *pInfo;\r\n\tpInfo = &gStreamInfo[ whichStream ];\r\n\r\n\tpInfo->m_iopOffset += SB_BUF_HALF;\r\n\tpInfo->m_spuBufSide = ( pInfo->m_spuBufSide == _1st ) ? _2nd : _1st;\r\n\tif ( pInfo->remaining <= 0 )\r\n\t{\r\n\t\t// the vag data up to the end should contain all zeros,\r\n\t\t// so it doesn't matter that the interrupt won't happen until the end.\r\n\t\t// stop the stream when it gets to the end:\r\n\t\tpInfo->status = PCM_STATUS_TERMINATE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Must check if it has crossed from one IOP buffer to the other\r\n\t\tif ( (pInfo->m_iopBufIndex == _1st) && (pInfo->m_iopOffset >= STREAM_HALF_IOP_BUFFER_SIZE) )\r\n\t\t{\r\n\t\t\tSmallShowStreamState( \"-SMO\" );\r\n\t\t\tpInfo->m_iopBufIndex = _2nd;\r\n\t\t\tif ( pInfo->remaining > STREAM_HALF_IOP_BUFFER_SIZE )\r\n\t\t\t{\r\n\t\t\t\tgEECommand |= ( PCMSTATUS_NEED_STREAM0_BUFFER_0 << whichStream );\r\n\t\t\t\tpInfo->m_iopBufLoaded[0] = FALSE;\r\n\t\t\t\t//Kprintf(\"Asking for Stream %d buffer #%d\\n\", whichStream, 0);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( (pInfo->m_iopBufIndex == _2nd) && pInfo->m_iopOffset >= STREAM_IOP_BUFFER_SIZE )\r\n\t\t{\r\n\t\t\tSmallShowStreamState( \"-SMB\" );\r\n\t\t\tpInfo->m_iopOffset -= STREAM_IOP_BUFFER_SIZE;\r\n\t\t\tpInfo->m_iopBufIndex = _1st;\r\n\t\t\tif ( pInfo->remaining > STREAM_HALF_IOP_BUFFER_SIZE )\r\n\t\t\t{\r\n\t\t\t\tgEECommand |= ( PCMSTATUS_NEED_STREAM0_BUFFER_1 << whichStream );\r\n\t\t\t\tpInfo->m_iopBufLoaded[1] = FALSE;\r\n\t\t\t\t//Kprintf(\"Asking for Stream %d buffer #%d\\n\", whichStream, 1);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n// Start the music that is already preloaded\r\nvoid StartMusic()\r\n{\r\n\tAdpcmSetMusicVolumeDirect( gMusicInfo.volume );\r\n\tsceSdSetSwitch( MUSIC_CORE | SD_S_KON, ( ( 1 << MUSIC_R_VOICE ) | ( 1 << MUSIC_L_VOICE ) ) );\r\n}\r\n\r\n// Start the stream that is already preloaded\r\nvoid StartStream(int whichStream)\r\n{\r\n\tAdpcmSetStreamVolumeDirect( gStreamInfo[ whichStream ].volume, whichStream );\r\n\t// Here's the bug! This was causing a recently paused stream to un-pause...\r\n\tif ( !gStreamInfo[ whichStream ].paused )\r\n\t{\r\n\t\tsceSdSetParam( STREAM_CORE | ( STREAM_VOICE( whichStream ) << 1 ) | SD_VP_PITCH, gStreamInfo[ whichStream ].pitch );\r\n\t}\r\n\tsceSdSetSwitch( STREAM_CORE | SD_S_KON, 1 << STREAM_VOICE( whichStream ) );\r\n\r\n\t//Kprintf(\"Stream %d using SPU memory (%6x-%6x)\\n\", whichStream, STREAM_SPU_BUF_LOC( whichStream ), STREAM_SPU_BUF_LOC( whichStream ) + SB_BUF_SIZE - 1);\r\n}\r\n\r\n/* internal */\r\nint RefreshStreams( int status )\r\n{\r\n\tint i;\r\n\r\n    while ( 1 )\r\n\t{\r\n\t\tWaitSema(gSem);\r\n\r\n\t\t// Update everything\r\n\t\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t\t{\r\n\t\t\tUpdateStream( i );\r\n\t\t}\r\n\t\tUpdateMusic( );\r\n\r\n\t\tif ( gMusicInfo.volumeSet )\r\n\t\t{\r\n\t\t\tgMusicInfo.volumeSet = 0;\r\n\t\t\tAdpcmSetMusicVolumeDirect( gMusicInfo.volume );\r\n\t\t}\r\n\t\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t\t{\r\n\t\t\tif ( gStreamInfo[ i ].volumeSet )\r\n\t\t\t{\r\n\t\t\t\tgStreamInfo[ i ].volumeSet = 0;\r\n\t\t\t\tAdpcmSetStreamVolumeDirect( gStreamInfo[ i ].volume, i );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tSendStatus();\r\n    }\r\n    return 0;\r\n}\r\n\r\nvoid _ShowStreamInfo( struct StreamInfo *pInfo )\r\n{\r\n\tprintf( \"\\nStream Info:\\n\" );\r\n\tprintf( \"paused     %d\\n\", pInfo->paused );\r\n\tprintf( \"m_spuEndAddr %d\\n\", pInfo->m_spuEndAddr );\r\n\tprintf( \"m_spuBufSide %d\\n\", pInfo->m_spuBufSide );\r\n\tprintf( \"m_spuTransSize %d\\n\", pInfo->m_spuTransSize );\r\n\tprintf( \"loadState  %d\\n\", pInfo->loadState );\r\n\tprintf( \"volume     %d\\n\", pInfo->volume );\r\n\tprintf( \"volumeSet  %d\\n\", pInfo->volumeSet );\r\n\tprintf( \"stop       %d\\n\", pInfo->stop );\r\n\tprintf( \"status     %d\\n\", pInfo->status );\r\n\tprintf( \"size       %d\\n\", pInfo->size );\r\n\tprintf( \"remaining  %d\\n\", pInfo->remaining );\r\n\tprintf( \"m_iopOffset %d\\n\", pInfo->m_iopOffset );\r\n\tprintf( \"pitch      %d\\n\", pInfo->pitch );\r\n\tprintf( \"eecom      %d\\n\", gEECommand );\r\n}\r\n\r\nvoid PauseStream( int whichStream, int pause )\r\n{\r\n\tShowStreamInfo( &gStreamInfo[ whichStream ] );\r\n\tif ( pause )\r\n\t{\r\n\t\tif ( !gStreamInfo[ whichStream ].paused )\r\n\t\t{\r\n\t\t\tsceSdSetParam( STREAM_CORE | ( STREAM_VOICE( whichStream ) << 1 ) | SD_VP_PITCH, 0 );\r\n\t\t\tgStreamInfo[ whichStream ].paused = 1;\r\n\t\t\tShowAction( \"Pausing stream\\n\" );\r\n\t\t\tSmallShowAction( \"-ps\" );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( gStreamInfo[ whichStream ].paused )\r\n\t\t{\r\n\t\t\tsceSdSetParam( STREAM_CORE | ( STREAM_VOICE( whichStream ) << 1 ) | SD_VP_PITCH, gStreamInfo[ whichStream ].pitch );\r\n\t\t\tgStreamInfo[ whichStream ].paused = 0;\r\n\t\t\tShowAction( \"Unpausing stream\\n\" );\r\n\t\t\tSmallShowAction( \"-ups\" );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvolatile int ret = 0;\r\n\r\n#define U_DATA( x )\t( *( ( unsigned int * ) data_ + x ) ) \r\n#define DATA( x )\t( *( ( int * ) data_ + x ) )\r\n\r\nstatic void *dispatch( unsigned int command, void *data_, int size )\r\n{ \r\n    int ch;\r\n\r\n//    printf( \"size %d\", size );\r\n//\tprintf(\"# dispatch [%04x] %x, %x, %x, %x\\n\", command, *((int*) data_ + 0), *((int*) data_ + 1), *((int*) data_ + 2), *((int*) data_ + 3));\r\n\r\n    ch = command & EzADPCM_CH_MASK;\r\n    switch ( command & EzADPCM_COMMAND_MASK )\r\n\t{\r\n\t\tcase EzADPCM_INIT:\r\n\t\t\tret = AdpcmInit( DATA( 0 ) ); // iop buffer pointer\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_QUIT:\r\n\t\t\tAdpcmQuit( );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_PRELOADMUSIC:\r\n\t\t\tret = AdpcmPlayMusic( DATA( 0 ), TRUE );  // size of the entire PCM data in the file\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_PRELOADSTREAM:\r\n\t\t\tret = AdpcmPlayStream( DATA( 0 ), ch, 0, 0, TRUE); // size of the entire PCM data in the file\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_PLAYPRELOADEDMUSIC:\r\n\t\t\tret = AdpcmPlayPreloadedMusic();\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_PLAYPRELOADEDSTREAM:\r\n\t\t\tret = AdpcmPlayPreloadedStream(ch, DATA(0), DATA(1));\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_PLAYMUSIC:\r\n\t\t\tret = AdpcmPlayMusic( DATA( 0 ), FALSE );  // size of the entire PCM data in the file\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_PLAYSTREAM:\r\n\t\t\tret = AdpcmPlayStream( DATA( 0 ), ch, DATA( 1 ), DATA( 2 ), FALSE ); // size of the entire PCM data in the file\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase EzADPCM_PAUSEMUSIC:\r\n\t\t\tif ( DATA( 0 ) )\r\n\t\t\t{\r\n\t\t\t\tif ( !gMusicInfo.paused )\r\n\t\t\t\t{\r\n\t\t\t\t\tsceSdSetParam( MUSIC_CORE | ( MUSIC_L_VOICE << 1 ) | SD_VP_PITCH, 0 );\r\n\t\t\t\t\tsceSdSetParam( MUSIC_CORE | ( MUSIC_R_VOICE << 1 ) | SD_VP_PITCH, 0 );\r\n\t\t\t\t\tgMusicInfo.paused = 1;\r\n\t\t\t\t\tShowAction( \"Pausing music\\n\" );\r\n\t\t\t\t\tSmallShowAction( \"-pm\" );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( gMusicInfo.paused )\r\n\t\t\t\t{\r\n\t\t\t\t\tsceSdSetParam( MUSIC_CORE | ( MUSIC_L_VOICE << 1 ) | SD_VP_PITCH, DEFAULT_PITCH );\r\n\t\t\t\t\tsceSdSetParam( MUSIC_CORE | ( MUSIC_R_VOICE << 1 ) | SD_VP_PITCH, DEFAULT_PITCH );\r\n\t\t\t\t\tgMusicInfo.paused = 0;\r\n\t\t\t\t\tShowAction( \"Unpausing music\\n\" );\r\n\t\t\t\t\tSmallShowAction( \"-upm\" );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_PAUSESTREAMS:\r\n\t\t{\r\n\t\t\tint whichStream;\r\n\t\t\t\r\n\t\t\tfor ( whichStream = 0; whichStream < NUM_STREAMS; whichStream++ )\r\n\t\t\t{\r\n\t\t\t\tPauseStream( whichStream, DATA( 0 ) );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase EzADPCM_PAUSESTREAM:\r\n\t\t\tPauseStream( ch, DATA( 0 ) );\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase EzADPCM_STOPMUSIC:\r\n\t\t\tret = AdpcmStopMusic( );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_STOPSTREAMS:\r\n\t\t{\r\n\t\t\tint i;\r\n\t\t\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t\t\t{\r\n\t\t\t\tret = AdpcmStopStream( i );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase EzADPCM_STOPSTREAM:\r\n\t\t\tif ( NUM_STREAMS > DATA( 0 ) )\r\n\t\t\t\tret = AdpcmStopStream( DATA( 0 )  );\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase EzADPCM_SETMUSICVOL:\r\n\t\t\tAdpcmSetMusicVolume( U_DATA( 0 ) );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_SETSTREAMVOLANDPITCH:\r\n\t\t\tsceSdSetParam( STREAM_CORE | ( STREAM_VOICE( ch ) << 1 ) | SD_VP_PITCH, ( U_DATA( 1 ) / 2 ) );\r\n\t\t\t// Adjust for pitch --> 22,050 hz when standard is 48000\r\n\t\t\tgStreamInfo[ ch ].pitch = STREAM_PITCH( U_DATA( 1 ) );\r\n\t\t\t// intentional fall through:\r\n\t\tcase EzADPCM_SETSTREAMVOL:\r\n\t\t\tAdpcmSetStreamVolume( U_DATA( 0 ), ch );\r\n\t\t\tbreak;\r\n\r\n#if 0\r\n\t\tcase EzADPCM_SETSTREAMGLOBVOL:\r\n\t\t\tAdpcmSetStreamGlobVol( U_DATA( 0 ) );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_GETMUSICSTATUS:\r\n\t\t\tret = AdpcmGetMusicStatus( );\r\n\t\t\tbreak;\r\n#endif\r\n\r\n\t\tcase EzADPCM_SDINIT:\r\n\t\t\tAdpcmSdInit( );\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\tERROR ((\"EzADPCM driver error: unknown command %d \\n\", DATA( 0 ) ) );\r\n\t\t\tbreak;\r\n    }\r\n    //printf( \"! return value = %x \\n\", ret );\r\n    return (void*)(&ret);\r\n}\r\n\r\n// SifCmd variables\r\n\r\n//static sceSifCmdData cmdbuffer[NUM_COMMAND_HANDLERS];\r\nunsigned int gCmdSem;\r\n\r\n// Note these can be changed in an interrupt\r\n#define NUM_STREAM_REQUESTS\t(10)\r\n\r\nstatic volatile SStreamRequestPacket StreamRequestArray[NUM_STREAM_REQUESTS];\r\nstatic volatile int FirstStreamRequest;\t\t// Interrupt only reads this value.\r\nstatic volatile\tint FreeStreamRequest;\t\t// This is the main variable that changes in the interrupt\r\n\r\nstatic SSifCmdStreamResultPacket StreamResult;\r\n\r\nvoid request_callback(void *p, void *q);\r\nvoid load_status_callback(void *p, void *q);\r\n\r\nint sce_adpcm_loop( void )\r\n{\r\n\tint oldStat;\r\n\tint last_cmd_id = -1;\r\n\r\n\t// Create semaphore to signal command came in\r\n\tstruct SemaParam sem;\r\n\tsem.initCount = 0;\r\n\tsem.maxCount = 1;\r\n\tsem.attr = AT_THFIFO;\r\n\tgCmdSem = CreateSema (&sem);\r\n\r\n\t// Init the stream queue\r\n\tFirstStreamRequest = 0;\r\n\tFreeStreamRequest = 0;\r\n\r\n\tsceSifInitRpc(0);\r\n\r\n\t// set local buffer & functions\r\n\tCpuSuspendIntr(&oldStat);\r\n\r\n\t// SIFCMD\r\n\t// No longer need to call sceSifSetCmdBuffer() since we share it with fileio.irx\r\n\t//sceSifSetCmdBuffer( &cmdbuffer[0], NUM_COMMAND_HANDLERS);\r\n\r\n\tsceSifAddCmdHandler(STREAM_REQUEST_COMMAND, (void *) request_callback, NULL );\r\n\tsceSifAddCmdHandler(STREAM_LOAD_STATUS_COMMAND, (void *) load_status_callback, NULL );\r\n\r\n\tCpuResumeIntr(oldStat);\r\n\r\n\t// The loop\r\n\twhile (1) {\r\n\t\t//printf(\"waiting for pcm command semaphore\\n\");\r\n\t\tWaitSema(gCmdSem);\t\t// Get signal from callback\r\n\t\t//printf(\"got pcm command semaphore\\n\");\r\n\r\n\t\t// Note that FreeStreamRequest can change in the interrupt at any time\r\n\t\t// Also, FirstStreamRequest is examined in the interrupt, but just to make sure we don't overflow the buffer\r\n\t\t//Dbg_Assert(FreeStreamRequest != FirstStreamRequest);\r\n\t\twhile (FreeStreamRequest != FirstStreamRequest)\r\n\t\t{\r\n\t\t\tint *p_ret;\r\n\t\t\tvolatile SStreamRequestPacket *p_request = &(StreamRequestArray[FirstStreamRequest]);\r\n\r\n#if TEST_PLAY_TIMING\r\n\t\t\tif (p_request->m_request.m_command == EzADPCM_PLAYPRELOADEDMUSIC)\r\n\t\t\t{\r\n\t\t\t\ttest_timing_request_id = p_request->m_request_id;\r\n\t\t\t\ttest_timing_send_timing_result = TRUE;\r\n\t\t\t\ttest_timing_hit_point = FALSE;\r\n\t\t\t}\r\n#endif // TEST_PLAY_TIMING\r\n\r\n\t\t\t//printf(\"EzPcm: got request id %d with command %x\\n\", p_request->m_request_id, p_request->m_request.m_command);\r\n\t\t\tp_ret = dispatch(p_request->m_request.m_command, (void *) p_request->m_request.m_param, 0);\r\n\r\n\t\t\t// Send the result back\r\n\t\t\tif (last_cmd_id >= 0)\t// Wait for previous send to complete (it should already be done, though)\r\n\t\t\t{\r\n               while(sceSifDmaStat(last_cmd_id) >= 0)\r\n\t\t\t\t   printf(\"Waiting for PCM DMA\\n\");\r\n\t\t\t}\r\n\t\t\t// Gotta copy the id into SStreamRequest\r\n\t\t\tStreamResult.m_header.opt = p_request->m_request_id;\t// Copy id\r\n\t\t\tStreamResult.m_return_value = *p_ret;\r\n\t\t\tStreamResult.m_status_flags = AdpcmGetStatus();\r\n            last_cmd_id = sceSifSendCmd(STREAM_RESULT_COMMAND, &StreamResult, sizeof(StreamResult), 0, 0, 0);\r\n\r\n\t\t\t// Increment request index; Note that interrupt can look at this\r\n\t\t\tFirstStreamRequest = (FirstStreamRequest + 1) % NUM_STREAM_REQUESTS;\r\n\t\t}\r\n\t}\r\n\r\n    return 0;\r\n}\r\n\r\nvoid request_callback(void *p, void *q)\r\n{\r\n\tSSifCmdStreamRequestPacket *h = (SSifCmdStreamRequestPacket *) p;\r\n\r\n\t// Check to make sure we can add\r\n\tint nextFreeReq = (FreeStreamRequest + 1) % NUM_STREAM_REQUESTS;\r\n\tif (nextFreeReq == FirstStreamRequest)\r\n\t{\r\n\t\t// We can't allow a request to be ignored.  We must abort\r\n\t\t//Dbg_Assert(0);\r\n\t}\r\n\r\n\t// Copy the request into the reuest queue\r\n\tStreamRequestArray[FreeStreamRequest].m_request = h->m_request;\r\n\tStreamRequestArray[FreeStreamRequest].m_request_id = h->m_header.opt;\r\n\tFreeStreamRequest = nextFreeReq;\r\n\r\n\t// And wake up the dispatch thread\r\n\tiSignalSema(gCmdSem);\r\n\r\n\treturn;\r\n}\r\n\r\nvoid load_status_callback(void *p, void *q)\r\n{\r\n\tSSifCmdStreamLoadStatusPacket *h = (SSifCmdStreamLoadStatusPacket *) p;\r\n\r\n\t// Mark buffer as loaded\r\n\tif (h->m_stream_num == -1)\r\n\t{\r\n\t\t//Kprintf(\"Music buffer #%d finished loading.\\n\", h->m_buffer_num);\r\n\t\tgMusicInfo.m_iopBufLoaded[h->m_buffer_num] = TRUE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//Kprintf(\"Stream %d buffer #%d finished loading.\\n\", h->m_stream_num, h->m_buffer_num);\r\n\t\tgStreamInfo[h->m_stream_num].m_iopBufLoaded[h->m_buffer_num] = TRUE;\r\n\t}\r\n}\r\n\r\nvoid SendStatus()\r\n{\r\n\tstatic SSifCmdStreamStatusPacket StreamStatus;\r\n\r\n#if TEST_PLAY_TIMING\r\n\tif (test_timing_send_timing_result && test_timing_hit_point)\r\n\t{\r\n\t\tsEELastCommand = 0xFFFFFFFF;\r\n\t\tStreamStatus.m_header.opt = test_timing_request_id;\r\n\t\ttest_timing_send_timing_result = FALSE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tStreamStatus.m_header.opt = 0;\r\n\t}\r\n#endif // TEST_PLAY_TIMING\r\n\r\n\t// Only send updates when it has changed\r\n\tif (AdpcmHasStatusChanged())\r\n\t{\r\n\t\tStreamStatus.m_status_flags = AdpcmGetStatus();\r\n\t\tsceSifSendCmd(STREAM_STATUS_COMMAND, &StreamStatus, sizeof(StreamStatus), 0, 0, 0);\r\n\t}\r\n}\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n\r\n/* DON'T ADD STUFF AFTER THIS */\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Pcm/pcm_ent.c",
    "content": "/* Vag streaming into SPU2 -- Converted from Sony samples -- matt may 2001 */\r\n\r\n#include <kernel.h>\r\n#include <sys/types.h>\r\n#include <stdio.h>\r\n#include <sif.h>\r\n#include <sifcmd.h>\r\n#include <sifrpc.h>\r\n#include \"pcm.h\"\r\n#include \"pcmiop.h\"\r\n\r\nModuleInfo Module = {\"pcm_driver\", 0x0102};\r\n\r\n// in command.c\r\nextern int sce_adpcm_loop (void);\r\nextern int sce_sound_loop (void);\r\n\r\nint start ( void )\r\n{\r\n    struct ThreadParam param;\r\n    int th;\r\n\r\n    if (! sceSifCheckInit ())\r\n\tsceSifInit ();\r\n    sceSifInitRpc (0);\r\n\r\n    printf (\"PCM driver version 666\\n\");\r\n\r\n    param.attr         = TH_C;\r\n    param.entry        = sce_adpcm_loop;\r\n    param.initPriority = BASE_priority - 2;\r\n    param.stackSize    = 0x800;\r\n    param.option       = 0;\r\n    th = CreateThread (&param);\r\n    if (th > 0) {\r\n\t\tStartThread (th, 0);\r\n    } else {\r\n\t\treturn 1;\r\n    }\r\n\r\n    param.attr         = TH_C;\r\n    param.entry        = sce_sound_loop;\r\n    param.initPriority = BASE_priority - 2;\r\n    param.stackSize    = 0x800;\r\n    param.option       = 0;\r\n    th = CreateThread (&param);\r\n    if (th > 0) {\r\n\t\tStartThread (th, 0);\r\n        printf (\" Exit PCM loader thread \\n\");\r\n\t\treturn 0;\r\n\t} else {\r\n\t\treturn 1;\r\n\t}\r\n}\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n/* DON'T ADD STUFF AFTER THIS */\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Pcm/pcm_sound.c",
    "content": "/* Vag streaming into SPU2 -- from sony sample -- matt may 2001 */\r\n\r\n#include <kernel.h>\r\n#include <sys/types.h>\r\n#include <sys/file.h>\r\n#include <stdio.h>\r\n#include <string.h>\r\n#include <sif.h>\r\n#include <sifcmd.h>\r\n#include <libsd.h>\r\n#include <sdrcmd.h>\r\n#include <thread.h>\r\n#include \"pcm.h\"\r\n#include \"pcmiop.h\"\r\n\r\n#define PRINT_DROPPED_REQUESTS\t0\r\n\r\n// ================================================================\r\n\r\n#define _1st 0\r\n#define _2nd 1\r\n\r\n#define TRUE  1\r\n#define FALSE 0\r\n\r\n#define TRANS_DMA_CH_MUSIC\t\t1\r\n#define TRANS_DMA_CH_STREAM\t\t0\r\n\r\n#define NUM_CORES\t\t\t\t2\r\n\r\nunsigned int gSndSem;\r\n\r\nextern volatile int gUsingStreamDMA;\r\nextern volatile int gSPUUsingStreamDMA;\r\n\r\n#if PRINT_DROPPED_REQUESTS\r\nstatic int s_received_requests = 0;\r\n#endif\r\n\r\n//\tsceSdSetTransIntrHandler( TRANS_DMA_CH_MUSIC, ( sceSdTransIntrHandler ) _AdpcmDmaIntMusic, ( void * ) &gSem );\r\n//  sceSdSetTransIntrHandler( TRANS_DMA_CH_STREAM, ( sceSdTransIntrHandler ) _AdpcmDmaIntStream, ( void * ) &gSem );\r\n\r\n// Used to hold the queued up SPU switch registers\r\nvolatile static uint32\t\t\ts_spu_reg_kon[NUM_CORES];\r\nvolatile static uint32\t\t\ts_spu_reg_koff[NUM_CORES];\r\nvolatile static uint32\t\t\ts_spu_kon_changed[NUM_CORES];\r\nvolatile static uint32\t\t\ts_spu_koff_changed[NUM_CORES];\r\nvolatile static uint32\t\t\ts_spu_reg_endx[NUM_CORES];\r\nvolatile static uint32\t\t\ts_switch_alarm_set;\r\nvolatile static uint32\t\t\ts_send_spu_status;\r\n\r\n#define\tSET_PARAM_ALARM_TIME\t(100)\t\t\t// Number of microseconds to wait before setting SPU switches (must be greater\r\n\t\t\t\t\t\t\t\t\t\t\t\t// than 1/24000 seconds)\r\n\r\nuint32 switch_set_callback(void *p_nothing)\r\n{\r\n\tint core;\r\n\r\n\tfor (core = 0; core < NUM_CORES; core++)\r\n\t{\r\n\t\t// First, get the status\r\n\t\ts_spu_reg_endx[core] = sceSdGetSwitch( core | SD_S_ENDX );\r\n\r\n\t\tif (s_spu_kon_changed[core])\r\n\t\t{\r\n\t\t\tsceSdSetSwitch( core | SD_S_KON, s_spu_reg_kon[core] );\r\n\t\t\ts_spu_kon_changed[core] = FALSE;\r\n\t\t\ts_spu_reg_endx[core] &= ~s_spu_reg_kon[core];\t// Update the status since SPU won't do it for another tick\r\n\t\t\ts_spu_reg_kon[core] = 0;\r\n\t\t}\r\n\r\n\t\tif (s_spu_koff_changed[core])\r\n\t\t{\r\n\t\t\tsceSdSetSwitch( core | SD_S_KOFF, s_spu_reg_koff[core] );\r\n\t\t\ts_spu_koff_changed[core] = FALSE;\r\n\t\t\ts_spu_reg_endx[core] |= s_spu_reg_koff[core];\t// Update the status since SPU won't do it for another tick\r\n\t\t\ts_spu_reg_koff[core] = 0;\r\n\t\t}\r\n\t}\r\n\r\n\ts_switch_alarm_set = FALSE;\r\n\ts_send_spu_status = TRUE;\r\n\r\n\t// And wake up the dispatch thread\r\n\tiSignalSema(gSndSem);\r\n\r\n\treturn 0;\r\n}\r\n\r\n// This function will set an alarm so that multiple KON and KOFF settings are combined.  If it isn't these type\r\n// of switches, it will be passed through\r\nvoid queue_set_switch(unsigned short entry, unsigned int value)\r\n{\r\n\tint core = entry & 0x1;\r\n\tint switch_reg = entry & 0xFF00;\r\n\tint oldStat;\r\n\r\n\t// Make sure alarm callback doesn't run here\r\n\tCpuSuspendIntr(&oldStat);\r\n\r\n\tswitch (switch_reg)\r\n\t{\r\n\tcase SD_S_KON:\r\n\t\tif(s_spu_reg_koff[core] & value)\r\n\t\t{\r\n\t\t\t//Dbg_MsgAssert(0, (\"Turning on a voice that was turned off this frame.\"));\r\n\t\t\tKprintf(\"Turning on a voice that was turned off this SPU tick.\\n\");\r\n\t\t\ts_spu_reg_koff[core] &= ~(s_spu_reg_koff[core] & value);\t// turn off those bits\r\n\t\t}\r\n\r\n\t\ts_spu_reg_kon[core] |= value;\r\n\t\ts_spu_kon_changed[core] = TRUE;\r\n\r\n\t\tbreak;\r\n\r\n\tcase SD_S_KOFF:\r\n\t\tif(s_spu_reg_kon[core] & value)\r\n\t\t{\r\n\t\t\t//Dbg_MsgAssert(0, (\"Turning off a voice that was turned on this frame.\"));\r\n\t\t\tKprintf(\"Turning off a voice that was turned on this SPU tick.\\n\");\r\n\t\t\ts_spu_reg_kon[core] &= ~(s_spu_reg_kon[core] & value);\t\t// turn off those bits\r\n\t\t}\r\n\r\n\t\ts_spu_reg_koff[core] |= value;\r\n\t\ts_spu_koff_changed[core] = TRUE;\r\n\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\t// Just set SPU and exit (so we don't set alarm)\r\n\t\tsceSdSetSwitch( entry, value );\r\n\t\tCpuResumeIntr(oldStat);\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Turn on alarm if it isn't already on\r\n\tif (!s_switch_alarm_set)\r\n\t{\r\n\t\tstruct SysClock clock;\r\n\t\tUSec2SysClock(SET_PARAM_ALARM_TIME, &clock);\r\n\r\n\t\tSetAlarm(&clock, switch_set_callback, NULL);\r\n\r\n\t\ts_switch_alarm_set = TRUE;\r\n\t}\r\n\r\n\tCpuResumeIntr(oldStat);\r\n}\r\n\r\n// This function belongs in pcm_sound.c, but because of some SN Sys link error, it has to be in here for now.\r\nint execute_sound_request(unsigned short function, unsigned short entry, unsigned int value,\r\n\t\t\t\t\t\t  unsigned int arg0, unsigned int arg1, unsigned int arg2, ESendSoundResult *p_send_result)\r\n{ \r\n\tint ret = -1;\r\n\t*p_send_result = SEND_SOUND_RESULT_FALSE;\r\n\r\n\tswitch (function)\r\n\t{\r\n\tcase rSdInit:\r\n\t\tret = sceSdInit( entry );\r\n\t\t*p_send_result = SEND_SOUND_RESULT_TRUE;\r\n\t\tbreak;\r\n\r\n\tcase rSdSetParam:\r\n\t\tsceSdSetParam( entry, value );\r\n\t\tbreak;\r\n\r\n\tcase rSdGetParam:\r\n\t\tret = sceSdGetParam( entry );\r\n\t\t*p_send_result = SEND_SOUND_RESULT_TRUE;\r\n\t\tbreak;\r\n\r\n\tcase rSdSetSwitch:\r\n\t\tqueue_set_switch( entry, value );\r\n\t\tbreak;\r\n\r\n\tcase rSdGetSwitch:\r\n\t\tret = sceSdGetSwitch( entry );\r\n\t\t*p_send_result = SEND_SOUND_RESULT_TRUE;\r\n\t\tbreak;\r\n\r\n\tcase rSdSetAddr:\r\n\t\tsceSdSetAddr( entry, value );\r\n\t\t//Kprintf(\"Setting addr %x to %x\\n\", entry, value);\r\n\t\tbreak;\r\n\r\n\tcase rSdGetAddr:\r\n\t\tret = sceSdGetAddr( entry );\r\n\t\t*p_send_result = SEND_SOUND_RESULT_TRUE;\r\n\t\tbreak;\r\n\r\n\tcase rSdSetCoreAttr:\r\n\t\tsceSdSetCoreAttr( entry, value );\r\n\t\tbreak;\r\n\r\n\tcase rSdGetCoreAttr:\r\n\t\tret = sceSdGetCoreAttr( entry );\r\n\t\t*p_send_result = SEND_SOUND_RESULT_TRUE;\r\n\t\tbreak;\r\n\r\n\tcase rSdNote2Pitch:\r\n\t\tret = sceSdNote2Pitch ( entry /*center_note*/, value /*center_fine*/, arg0 /*note*/, arg1 /*fine*/);\r\n\t\t*p_send_result = SEND_SOUND_RESULT_TRUE;\r\n\t\tbreak;\r\n\r\n\tcase rSdPitch2Note:\r\n\t\tret = sceSdPitch2Note ( entry /*center_note*/, value /*center_fine*/, arg0 /*pitch*/);\r\n\t\t*p_send_result = SEND_SOUND_RESULT_TRUE;\r\n\t\tbreak;\r\n\r\n\tcase rSdVoiceTrans:\r\n\t\tsceSdVoiceTrans( entry /*channel*/, value /*mode*/, (u_char *) arg0 /*m_addr*/, arg1 /*s_addr*/, arg2 /*size*/ );\r\n\t\tbreak;\r\n\r\n\tcase rSdBlockTrans:\r\n\t\tsceSdBlockTrans( entry /*channel*/, value /*mode*/, (u_char *) arg0 /*m_addr*/, arg1 /*size*/, (u_char *) arg2 /*start_addr*/ );\r\n\t\tbreak;\r\n\r\n\tcase rSdVoiceTransStatus:\r\n\t\tret = sceSdVoiceTransStatus (entry /*channel*/, value /*flag*/);\r\n\t\t*p_send_result = SEND_SOUND_RESULT_TRUE;\r\n\t\tbreak;\r\n\r\n\tcase rSdBlockTransStatus:\r\n\t\tret = sceSdBlockTransStatus (entry /*channel*/, value /*flag*/);\r\n\t\t*p_send_result = SEND_SOUND_RESULT_TRUE;\r\n\t\tbreak;\r\n\r\n\tcase rSdSetEffectAttr:\r\n\t\t{\r\n\t\t\tsceSdEffectAttr attr;\r\n\r\n\t\t\tattr.core\t\t= entry;\r\n\t\t\tattr.mode\t\t= value;\r\n\t\t\tattr.depth_L\t= (short) (arg0 >> 16);\r\n\t\t\tattr.depth_R\t= (short) (arg0 & 0xFFFF);\r\n\t\t\tattr.delay\t\t= arg1;\r\n\t\t\tattr.feedback\t= arg2;\r\n\r\n\t\t\t//Kprintf(\"About to set core %d reverb mode to %d\\n\", entry, value);\r\n\t\t\tret = sceSdSetEffectAttr(entry /*core*/, &attr);\r\n\r\n\t\t\t// Wait for Stream DMA (0) to finish\r\n\t\t\twhile (gUsingStreamDMA)\r\n\t\t\t\t;\r\n\r\n\t\t\t// Clear out reverb memory (and make sure it doesn't interfere with streams)\r\n\t\t\tgSPUUsingStreamDMA = 1;\r\n            sceSdCleanEffectWorkArea(entry, 0, value);\r\n            sceSdVoiceTransStatus(0, SD_TRANS_STATUS_WAIT);\r\n\t\t\tif ((value == SD_REV_MODE_OFF) && gSPUUsingStreamDMA)\t\t// This mode doesn't seem to cause a DMA callback\r\n\t\t\t{\r\n\t\t\t\tgSPUUsingStreamDMA = 0;\r\n\t\t\t\t//Kprintf(\"Manually clearing DMA flag\\n\");\r\n\t\t\t}\r\n\t\t\t//Kprintf(\"Set core %d reverb mode to %d with return value of %d and %d\\n\", entry, value, ret);\r\n\t\t}\r\n\t\t*p_send_result = SEND_SOUND_RESULT_TRUE;\r\n\t\tbreak;\r\n\r\n\t\t// This is a meaningless call because we can't send the data back\r\n//\tcase rSdGetEffectAttr:\r\n//\t\tsceSdGetEffectAttr(entry /*core*/, (sceSdEffectAttr *) value /*attr*/);\r\n//\t\tbreak;\r\n\r\n//#define rSdClearEffectWorkArea   0x8150\r\n//#define rSdStopTrans             0x8180\r\n//#define rSdCleanEffectWorkArea   0x8190\r\n//#define rSdSetEffectMode         0x81a0\r\n//#define rSdSetEffectModeParams   0x81b0\r\n\r\n\tdefault:\r\n\t\tret = -1;\r\n\t\t*p_send_result = SEND_SOUND_RESULT_PANIC;\r\n\t\tKprintf(\"Unknown or unsupported SPU function %x\\n\", function);\r\n\t\tbreak;\r\n\t}\r\n\r\n    return ret;\r\n}\r\n\r\n// SifCmd variables\r\n\r\n// Note these can be changed in an interrupt\r\n#define NUM_SOUND_REQUESTS\t(128)\r\n\r\nstatic volatile SSoundRequest SoundRequestArray[NUM_SOUND_REQUESTS];\r\nstatic volatile int FirstSoundRequest;\t\t// Interrupt only reads this value.\r\nstatic volatile\tint FreeSoundRequest;\t\t// This is the main variable that changes in the interrupt\r\n\r\n// Set to TRUE if we hit a problem\r\nstatic volatile int global_sound_panic = FALSE;\r\n\r\nstatic SSifCmdSoundResultPacket SoundResult;\r\n\r\nvoid sound_request_callback(void *p, void *q);\r\n\r\nint sce_sound_loop( void )\r\n{\r\n\tint oldStat;\r\n\tint last_cmd_id = -1;\r\n\r\n\t// Create semaphore to signal command came in\r\n\tstruct SemaParam sem;\r\n\tsem.initCount = 0;\r\n\tsem.maxCount = 1;\r\n\tsem.attr = AT_THFIFO;\r\n\tgSndSem = CreateSema (&sem);\r\n\r\n\t// Init the stream queue\r\n\tFirstSoundRequest = 0;\r\n\tFreeSoundRequest = 0;\r\n\r\n\t// set local buffer & functions\r\n\tCpuSuspendIntr(&oldStat);\r\n\r\n\t// SIFCMD\r\n\t// No longer need to call sceSifSetCmdBuffer() since we share it with fileio.irx\r\n\tsceSifAddCmdHandler(SOUND_REQUEST_COMMAND, (void *) sound_request_callback, NULL );\r\n\r\n\tCpuResumeIntr(oldStat);\r\n\r\n\t// The loop\r\n\twhile (1) {\r\n\t\t//printf(\"waiting for sound command semaphore\\n\");\r\n\t\tWaitSema(gSndSem);\t\t// Get signal from callback\r\n\t\t//printf(\"got sound command semaphore\\n\");\r\n\r\n\t\t// Note that FreeSoundRequest can change in the interrupt at any time\r\n\t\t// Also, FirstSoundRequest is examined in the interrupt, but just to make sure we don't overflow the buffer\r\n\t\t//Dbg_Assert(FreeSoundRequest != FirstSoundRequest);\r\n\t\twhile (FreeSoundRequest != FirstSoundRequest)\r\n\t\t{\r\n\t\t\tint ret;\r\n\t\t\tESendSoundResult send_result;\r\n\r\n\t\t\tvolatile SSoundRequest *p_request = &(SoundRequestArray[FirstSoundRequest]);\r\n\t\t\t//Kprintf(\"Sound: %d executing command %x with entry %x and value %x\\n\", FirstSoundRequest, p_request->m_function, p_request->m_entry, p_request->m_value);\r\n\t\t\tret = execute_sound_request(p_request->m_function, p_request->m_entry, p_request->m_value,\r\n\t\t\t\t\t\t\t\t\t\tp_request->m_arg_0, p_request->m_arg_1, p_request->m_arg_2, &send_result);\r\n\r\n\t\t\tif ((send_result != SEND_SOUND_RESULT_FALSE) || global_sound_panic)\r\n\t\t\t{\r\n\t\t\t\t//Kprintf(\"Sending sound result from command %x with entry %x and result %x\\n\", p_request->m_function, p_request->m_entry, ret);\r\n\r\n\t\t\t\t// Send the result back\r\n\t\t\t\tif (last_cmd_id >= 0)\t// Wait for previous send to complete (it should already be done, though)\r\n\t\t\t\t{\r\n\t\t\t\t\twhile(sceSifDmaStat(last_cmd_id) >= 0)\r\n\t\t\t\t\t\t;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Gotta copy the function and entry\r\n\t\t\t\tSoundResult.m_function\t= p_request->m_function;\r\n\t\t\t\tSoundResult.m_entry \t= p_request->m_entry;\r\n\t\t\t\tSoundResult.m_result\t= ret;\r\n\t\t\t\tSoundResult.m_panic\t\t= (send_result == SEND_SOUND_RESULT_PANIC) || global_sound_panic;\r\n\t\t\t\tlast_cmd_id = sceSifSendCmd(SOUND_RESULT_COMMAND, &SoundResult, sizeof(SoundResult), 0, 0, 0);\r\n\t\t\t}\r\n\r\n\t\t\t// Increment request index; Note that interrupt can look at this\r\n\t\t\tFirstSoundRequest = (FirstSoundRequest + 1) % NUM_SOUND_REQUESTS;\r\n\t\t}\r\n\r\n\t\t// Send the status back, if it has been updated\r\n\t\tif (s_send_spu_status)\r\n\t\t{\r\n\t\t\tint core;\r\n\r\n\t\t\t//Kprintf(\"Sending sound status back\\n\");\r\n\r\n\t\t\tfor (core = 0; core < NUM_CORES; core ++)\r\n\t\t\t{\r\n\t\t\t\tif (last_cmd_id >= 0)\t// Wait for previous send to complete\r\n\t\t\t\t{\r\n\t\t\t\t\twhile(sceSifDmaStat(last_cmd_id) >= 0)\r\n\t\t\t\t\t\t;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Gotta copy the function and entry\r\n\t\t\t\tSoundResult.m_function\t= rSdGetSwitch;\r\n\t\t\t\tSoundResult.m_entry \t= SD_S_ENDX | core;\r\n\t\t\t\tSoundResult.m_result\t= s_spu_reg_endx[core];\r\n\t\t\t\tSoundResult.m_panic\t\t= FALSE;\r\n\t\t\t\tlast_cmd_id = sceSifSendCmd(SOUND_RESULT_COMMAND, &SoundResult, sizeof(SoundResult), 0, 0, 0);\r\n\t\t\t}\r\n\t\t\ts_send_spu_status = FALSE;\r\n\t\t}\r\n\t}\r\n\r\n    return 0;\r\n}\r\n\r\nvoid sound_request_callback(void *p, void *q)\r\n{\r\n\tSSifCmdSoundRequestPacket *h = (SSifCmdSoundRequestPacket *) p;\r\n\r\n\t// Check to make sure we can add\r\n\tint nextFreeReq = (FreeSoundRequest + 1) % NUM_SOUND_REQUESTS;\r\n\tif (nextFreeReq == FirstSoundRequest)\r\n\t{\r\n\t\t// We can't allow a request to be ignored.  We must abort\r\n\t\tKprintf(\"Fuck, we've overrun the sound request buffer\\n\");\r\n\t\tglobal_sound_panic = TRUE;\r\n\t}\r\n\r\n#if PRINT_DROPPED_REQUESTS\r\n\tif ((++s_received_requests) != h->m_request.m_pad[0])\r\n\t{\r\n\t\tKprintf(\"ERROR: Missed sound request.  Expected %d but only got up to %d\\n\", h->m_request.m_pad[0], s_received_requests);\r\n\t\ts_received_requests = h->m_request.m_pad[0];\r\n\t}\r\n#endif PRINT_DROPPED_REQUESTS\r\n\r\n\t// Copy the request into the reuest queue\r\n\tSoundRequestArray[FreeSoundRequest] = h->m_request;\r\n\tFreeSoundRequest = nextFreeReq;\r\n\r\n\t//Kprintf(\"Sound: %d got command %x with entry %x and value %x\\n\", FreeSoundRequest, h->m_request.m_function, h->m_request.m_entry, h->m_request.m_value);\r\n\r\n\t// And wake up the dispatch thread\r\n\tiSignalSema(gSndSem);\r\n\r\n\treturn;\r\n}\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n/* DON'T ADD STUFF AFTER THIS */\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/Pcm/pcmiop.h",
    "content": "#if 0\r\n#define PRINTF(x) printf x\r\n#else\r\n#define PRINTF(x) \r\n#endif\r\n#define ERROR(x) printf x\r\n#define xPRINTF(x) \r\n\r\n#define BASE_priority  32\r\n\r\n#define OLDLIB 0\r\n#define TRANS_CH  0\r\n\r\ntypedef char\t\t\t\tint8;\r\ntypedef short\t\t\t\tint16;\r\ntypedef int\t\t\t\t\tint32;\r\n\r\ntypedef unsigned char\t\tuint8;\r\ntypedef unsigned short\t\tuint16;\r\ntypedef unsigned int\t\tuint32;\r\n\r\n\r\ntypedef enum\r\n{\r\n\tSEND_SOUND_RESULT_FALSE = 0,\r\n\tSEND_SOUND_RESULT_TRUE,\r\n\tSEND_SOUND_RESULT_PANIC,\r\n} ESendSoundResult;\r\n\r\nenum{\r\n\tMUSIC_LOAD_STATE_IDLE = 0, // Idle state must be zero!\r\n\tMUSIC_LOAD_STATE_PRELOADING_L,\r\n\tMUSIC_LOAD_STATE_PRELOADING_R,\r\n\tMUSIC_LOAD_STATE_WAITING_FOR_REFRESH,\r\n\tMUSIC_LOAD_STATE_WAITING_FOR_LAST_LOAD,\r\n\tMUSIC_LOAD_STATE_LOADING_L,\r\n\tMUSIC_LOAD_STATE_LOADING_R,\r\n};\r\n\r\nenum{\r\n\tSTREAM_LOAD_STATE_IDLE = 0, // Idle state must be zero!\r\n\tSTREAM_LOAD_STATE_PRELOADING,\r\n\tSTREAM_LOAD_STATE_WAITING_FOR_REFRESH,\r\n\tSTREAM_LOAD_STATE_WAITING_FOR_LAST_LOAD,\r\n\tSTREAM_LOAD_STATE_LOADING,\r\n};\r\n\r\n// Holds all the data necessary for an audio or music stream\r\nstruct StreamInfo{\r\n\t// State variables\r\n\tvolatile uint32\tloadState;\r\n\tvolatile uint32\tstatus;\r\n\tvolatile uint16\tm_preloadMode;\r\n\r\n\tvolatile uint16\tm_iopBufLoaded[2];\r\n\r\n\t// Stream parameters\r\n\tvolatile uint16\tvolumeSet;\r\n\tvolatile uint32\tvolume;\r\n\tvolatile uint16\tpaused;\r\n\tvolatile uint16\tstop;\r\n\tint\t\t\t\tpitch;\r\n\r\n\t// Stream size info\r\n\tvolatile uint32\tsize;\r\n\tint \t\t\tremaining;\r\n\r\n\t// Current buffer and address info\r\n\tuint16\t\t\tm_iopBufIndex;\r\n\tuint32\t\t\tm_iopOffset;\r\n\tuint32\t\t\tm_spuBufSide;\t\t\t// buffer we are LOADING to\r\n\tuint32\t\t\tm_spuTransSize;\r\n\tvolatile uint16 m_spuTransDone;\r\n\tuint32\t\t\tm_spuCurAddr;\r\n\tuint32\t\t\tm_spuEndAddr;\r\n};\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/p_music.cpp",
    "content": "// Streaming music off the cd...\r\n\r\n\r\n\r\n#include <eetypes.h>\r\n#include <eekernel.h>\r\n#include <stdio.h>\r\n#include <sifdev.h>\r\n#include <libsdr.h>\r\n#include <sdrcmd.h>\r\n#include <sdmacro.h>\r\n#include <string.h>\r\n#include <sif.h>\r\n#include <sifrpc.h>\r\n\r\n#include <libcdvd.h>\r\n\r\n#include <core/macros.h>\r\n#include <core/defines.h>\r\n\r\n#include <sys/config/config.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/ngps/p_AsyncFilesys.h>\r\n#include <sys/file/ngps/hed.h>\r\n#include <gel/music/ngps/pcm/pcm.h>\r\n\r\n// temp for debugging ghost voice:\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\n// temp for stream sim Rnd( ) call:\r\n#include <core/math/math.h>\r\n\r\n#include \"p_music.h\"\r\n\r\n#define TEST_MOTHERFUCKING_CD 0\t\t\t// Doubt this even works now\r\n#define TEST_PLAY_TIMING\t  0\r\n\r\nnamespace Pcm\r\n{\r\n\t\r\n#define MAX_VOL\t\t\t\t\t( 0x3fff )\r\n#define NORMAL_VOL\t\t\t\t( 0x3fff >> 1 )\r\n\r\n#define MUSIC_PRIORITY\t\t\t( DEFAULT_ASYNC_PRIORITY - 20 )\r\n#define STREAM_PRIORITY\t\t\t( DEFAULT_ASYNC_PRIORITY - 10 )\t\t// The lower the number, the higher the priority\r\n\r\nint\tgIopBuffer = 0;\r\nint\tgNonAllignedIopBuffer = 0;\r\n\r\nint\tgPcmStatus = 0;\r\n\r\n// All the Wad file info for the music and audio streams\r\nSWadInfo gWadInfo[ 2 ];\r\n\r\nCFileStreamInfo gStreamList [ NUM_FILE_STREAMS ] = {\r\n\t\t{ FILE_STREAM_MUSIC, LOAD_STATE_DONE, PLAY_STATE_DONE, NULL, 0, 0, 0 },\t\t\t\t\t// Music stream\r\n\t\t{ FILE_STREAM_STREAM0, LOAD_STATE_DONE, PLAY_STATE_DONE, NULL, 0, 0, 0 },\t\t\t\t// Audio stream 0\r\n\t\t{ FILE_STREAM_STREAM1, LOAD_STATE_DONE, PLAY_STATE_DONE, NULL, 0, 0, 0 },   \t\t\t// Audio stream 1\r\n\t\t{ FILE_STREAM_STREAM2, LOAD_STATE_DONE, PLAY_STATE_DONE, NULL, 0, 0, 0 }\t\t\t\t// Audio stream 2\r\n};\r\n\r\nCFileStreamInfo * gpMusicInfo = &gStreamList[FILE_STREAM_MUSIC];\r\nCFileStreamInfo * gpStreamInfo[ NUM_STREAMS ] = { &gStreamList[FILE_STREAM_STREAM0], &gStreamList[FILE_STREAM_STREAM1],\r\n\t\t\t\t\t\t\t\t\t\t\t\t  &gStreamList[FILE_STREAM_STREAM2] };\r\n\r\nunsigned int gStreamVolume = 100;\r\n\r\n// Communication to RPC -- ezpcm.irx:\r\n// EzPcm is the function that the EE uses to call the IRX program EzPcm.irx.\r\n// EzPcm.irx is a separate code module that runs on the IOP chip (the playstation one chip).\r\n// The EzPcm module is build from the pcm* files in music\\ngps\\pcm.\r\n// The files in the music\\ngps\\bgm folder were used to build a different irx that is\r\n// no longer used for streaming music, so don't worry about the BGM files.\r\n\r\n#define MAX_QUEUED_REQUESTS\t(10)\r\n\r\n// SifCmd packets\r\nstatic SSifCmdStreamRequestPacket s_cmd_requests[MAX_QUEUED_REQUESTS] __attribute__ ((aligned(16)));\r\nstatic SSifCmdStreamLoadStatusPacket s_cmd_load_status __attribute__ ((aligned(16)));\r\n\r\nstatic uint32 s_cmd_request_dma_ids[MAX_QUEUED_REQUESTS] = { 0 };\r\nstatic uint32 s_cmd_load_status_last_id = 0;\r\nstatic int s_cmd_request_free_index = 0;\r\n\r\nstatic int s_request_id = 0;\r\nstatic volatile bool s_request_done;\r\nstatic volatile int s_request_result;\r\nstatic volatile int s_request_result_id;\r\n\r\n// These are set by sifcmds sent directly from the IOP\r\nvolatile int sSentStatus = 0;\r\nvolatile bool sNewStatus = false;\r\n\r\n// Timing test code\r\n#if TEST_PLAY_TIMING\r\nstatic volatile uint32 test_timing_start;\r\nstatic volatile uint32 test_timing_end;\r\nstatic \t\t\tint\t   test_timing_request_id = -1;\r\n#endif // TEST_PLAY_TIMING\r\n\r\nvoid result_callback(void *p, void *q)\r\n{\r\n\tSSifCmdStreamResultPacket *h = (SSifCmdStreamResultPacket *) p;\r\n\r\n\ts_request_result = h->m_return_value;\r\n\ts_request_result_id = h->m_header.opt;\r\n\tsSentStatus |= h->m_status_flags;\r\n\tsNewStatus = true;\r\n\ts_request_done = true;\r\n\r\n\t//scePrintf(\"*************** EzPcm() result ID %d result = %d\\n\", s_request_result_id, s_request_result);\r\n\r\n#if TEST_PLAY_TIMING\r\n\tif (s_request_result_id == test_timing_request_id)\r\n\t{\r\n\t\ttest_timing_end = Tmr::GetTimeInUSeconds();\r\n\t\tscePrintf(\"EzPcm() turnaround time Frame %d Time %d (%x - %x)\\n\", Tmr::GetVblanks(), (test_timing_end - test_timing_start), test_timing_end, test_timing_start);\r\n\t}\r\n#endif // TEST_PLAY_TIMING\r\n\r\n\tExitHandler();\r\n}\r\n\r\nvoid status_callback(void *p, void *q)\r\n{\r\n\tSSifCmdStreamStatusPacket *h = (SSifCmdStreamStatusPacket *) p;\r\n\r\n\tsSentStatus |= h->m_status_flags;\r\n\tsNewStatus = true;\r\n\r\n#if TEST_PLAY_TIMING\r\n\tif ((int) h->m_header.opt == test_timing_request_id)\r\n\t{\r\n\t\ttest_timing_end = Tmr::GetTimeInUSeconds();\r\n\t\tscePrintf(\"EzPcm() final turnaround time Frame %d Time %d (%x - %x)\\n\", Tmr::GetVblanks(), (test_timing_end - test_timing_start), test_timing_end, test_timing_start);\r\n\t}\r\n#endif // TEST_PLAY_TIMING\r\n\r\n\tExitHandler();\r\n}\r\n\r\nbool get_status(int & status)\r\n{\r\n\tbool new_stat;\r\n\r\n\t// Disable interrupts just in case we get a sifcmd callback\r\n\tDI();\r\n\tstatus = sSentStatus;\r\n\tnew_stat = sNewStatus;\r\n\tsSentStatus = 0;\r\n\tsNewStatus = false;\r\n\tEI();\r\n\r\n\treturn new_stat;\r\n}\r\n\r\n// prototype:\r\nvoid EzPcm( int command, int data, int data2 = 0, int data3 = 0 );\r\n\r\n// IOP\r\nvoid EzPcm( int command, int data, int data2, int data3 )\r\n{\r\n\t//scePrintf(\"Doing EzPcm request id %d with command %x\\n\", s_request_id, command);\r\n\r\n\t#if TEST_PLAY_TIMING\r\n\tif (command == EzADPCM_PLAYPRELOADEDMUSIC)\r\n\t{\r\n\t\ttest_timing_start = Tmr::GetTimeInUSeconds();\r\n\t\ttest_timing_request_id = s_request_id;\r\n\t\tDbg_Message(\"Doing EzPcm request id %d with command %x\", test_timing_request_id, command);\r\n\t}\r\n\t#endif // TEST_PLAY_TIMING\r\n\r\n\tint nextFreeIndex = (s_cmd_request_free_index + 1) % MAX_QUEUED_REQUESTS;\r\n\tSSifCmdStreamRequestPacket *p_packet = &s_cmd_requests[s_cmd_request_free_index];\r\n\r\n\t// Make sure this request packet is not still in the Sif DMA queue\r\n\tif (s_cmd_request_dma_ids[s_cmd_request_free_index])\r\n\t{\r\n\t\twhile(sceSifDmaStat(s_cmd_request_dma_ids[s_cmd_request_free_index]) >= 0)\r\n\t\t\t;\r\n\t}\r\n\r\n\tp_packet->m_header.opt = s_request_id++;\r\n\tp_packet->m_request.m_command = command;\r\n\tp_packet->m_request.m_param[0] = data;\r\n\tp_packet->m_request.m_param[1] = data2;\r\n\tp_packet->m_request.m_param[2] = data3;\r\n\r\n\ts_request_done = false;\t\t// Callback will change it to true\r\n\ts_cmd_request_dma_ids[s_cmd_request_free_index] = sceSifSendCmd(STREAM_REQUEST_COMMAND, p_packet, sizeof(*p_packet), 0, 0, 0);\r\n\r\n\ts_cmd_request_free_index = nextFreeIndex;\r\n\r\n\t//Dbg_MsgAssert(request_result_id == (request_id -1), (\"Result id (%d) differs from request id (%d)\", request_result_id, request_id - 1));\r\n}\r\n\r\n// Tell IOP that the buffer is done loading\r\nvoid send_load_done(EFileStreamType streamType, int buffer_num, int bytes_loaded)\r\n{\r\n\tDbg_Assert((buffer_num >= 0) && (buffer_num <= 1));\r\n\r\n\t// Wait for last send to complete\r\n\tif (s_cmd_load_status_last_id)\r\n\t{\r\n\t\twhile(sceSifDmaStat(s_cmd_load_status_last_id) >= 0)\r\n\t\t\t;\r\n\t}\r\n\r\n\ts_cmd_load_status.m_stream_num = streamType - 1;\r\n\ts_cmd_load_status.m_buffer_num = buffer_num;\r\n\ts_cmd_load_status.m_bytes_loaded = bytes_loaded;\r\n\r\n\t//FlushCache(0);\r\n\r\n\ts_cmd_load_status_last_id = sceSifSendCmd(STREAM_LOAD_STATUS_COMMAND, &s_cmd_load_status, sizeof(s_cmd_load_status), 0, 0, 0);\r\n\t//scePrintf(\"Audio stream %d buffer #%d finished loading\\n\", streamType, buffer_num);\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////////////////////////////\r\n#include <libcdvd.h>\r\n\r\nvoid InitCDPlease( void )\r\n{\r\n\tif (Config::CD())\r\n\t{\r\n\t\t// already done since we're building in CD mode...\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t#if TEST_MOTHERFUCKING_CD\r\n\tstatic bool initializedAndShit = false;\r\n\tif ( !initializedAndShit )\r\n\t{\r\n\t\tsceCdInit(SCECdINIT);\r\n\t\t// this may oughtta be changed to SCDCdDVD...\r\n\t\t// Actually, a smart thing to do would be to have this defined somewhere\r\n\t\t// and switched between SCECdCD or SCDCdDVD depending on the build?\r\n\t\t//sceCdMmode(SCECdCD);\r\n\t\tsceCdMmode(SCECdDVD);\r\n\t\tinitializedAndShit = true;\r\n\t}\r\n\t#endif\r\n}\t\r\n\r\nstatic bool CheckForCDErrors( void )\r\n{\r\n\tint cdErr;\r\n\tcdErr = sceCdGetError( );\r\n\tswitch ( cdErr )\r\n\t{\r\n\t\tcase ( SCECdErNO ): // no error\r\n\t\t\tbreak;\r\n\t\tcase ( SCECdErTRMOPN ):\t// cover opened during playback\r\n\t\tcase ( SCECdErREAD ):\t// read error\r\n\t\t\treturn ( true );\r\n\t\tdefault:\r\n\t\t\tprintf( \"cd err %d\\n\", cdErr );\r\n\t\t\tbreak;\r\n\t}\r\n\treturn ( false );\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n// CFileStreamInfo\r\n//\r\n\r\n// Preloads the SPU audio buffers (because this can take a few frames)\r\nvoid\t\t\tCFileStreamInfo::preload_spu_buffers()\r\n{\r\n\t// Check if it is music or normal audio\r\n\tif (IsMusicStream())\r\n\t{\r\n\t\t// got initial music buffers loaded - start preloading SPU buffers\r\n\t\tEzPcm( EzADPCM_PRELOADMUSIC, m_fileSize / 2 ); // because there are two channels L and R\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// got initial stream buffers loaded - start preloading SPU buffers\r\n\t\tEzPcm( EzADPCM_PRELOADSTREAM | GetAudioStreamIndex(), m_fileSize );\r\n\t}\r\n}\r\n\r\n// Starts playing a preloaded audio stream\r\nvoid\t\t\tCFileStreamInfo::start_preloaded_audio()\r\n{\r\n\tgPcmStatus &= ~PCMSTATUS_LOAD_AUDIO( m_streamType );\r\n\tgPcmStatus |= PCMSTATUS_AUDIO_PLAYING( m_streamType );\r\n\r\n\t// Check if it is music or normal audio\r\n\tif (IsMusicStream())\r\n\t{\r\n\t\t// got initial music buffers loaded on the SPU - start it playing:\r\n\t\tEzPcm( EzADPCM_PLAYPRELOADEDMUSIC, 0 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// got initial stream buffers loaded on the SPU - start it playing:\r\n\t\tEzPcm( EzADPCM_PLAYPRELOADEDSTREAM | GetAudioStreamIndex(), m_volume, m_pitch );\r\n\t}\r\n}\r\n\r\n// Starts playing the audio stream\r\nvoid\t\t\tCFileStreamInfo::start_audio()\r\n{\r\n\tgPcmStatus &= ~PCMSTATUS_LOAD_AUDIO( m_streamType );\r\n\tgPcmStatus |= PCMSTATUS_AUDIO_PLAYING( m_streamType );\r\n\r\n\t// Check if it is music or normal audio\r\n\tif (IsMusicStream())\r\n\t{\r\n\t\t// got initial music buffers loaded - start it playing:\r\n\t\tEzPcm( EzADPCM_PLAYMUSIC, m_fileSize / 2 ); // because there are two channels L and R\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// got initial stream buffers loaded - start it playing:\r\n\t\tEzPcm( EzADPCM_PLAYSTREAM | GetAudioStreamIndex(), m_fileSize, m_volume, m_pitch );\r\n\t}\r\n}\r\n\r\n// Starts the load of an audio stream chunk\r\nvoid\t\t\tCFileStreamInfo::load_chunk(int buffer)\r\n{\r\n\tif ( !mp_fileHandle )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"s'it, yo... no file opened for stream index %d\", GetAudioStreamIndex() ));\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Check if it is music or normal audio\r\n\tif (IsMusicStream())\r\n\t{\r\n\t\tvoid *p_iop_addr = (void *) (gIopBuffer + ( MUSIC_IOP_BUFFER_SIZE * buffer ));\r\n\t\tmp_fileHandle->Read( p_iop_addr, 1, MUSIC_IOP_BUFFER_SIZE );\r\n\t\t//scePrintf(\"Reading music buffer %d from disk to IOP buffer %x of size %d\\n\", buffer, p_iop_addr, MUSIC_IOP_BUFFER_SIZE);\r\n\r\n\t\tm_offset += MUSIC_IOP_BUFFER_SIZE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint whichStream =  GetAudioStreamIndex();\r\n\t\tvoid *p_iop_addr = (void *) (gIopBuffer + STREAM_IOP_OFFSET( whichStream ) + ( STREAM_HALF_IOP_BUFFER_SIZE * buffer ));\r\n\t\tmp_fileHandle->Read( p_iop_addr, 1, STREAM_HALF_IOP_BUFFER_SIZE );\r\n\r\n\t\tm_offset += STREAM_HALF_IOP_BUFFER_SIZE;\r\n\t}\r\n}\r\n\r\n// Checks to see if the IOP module is requesting another stream chunk\r\nELoadState\t\tCFileStreamInfo::check_for_load_requests()\r\n{\r\n\tELoadState state = LOAD_STATE_IDLE;\r\n\r\n\tif ( gPcmStatus & PCMSTATUS_NEED_AUDIO_BUFFER_0( m_streamType ) )\r\n\t{\r\n\t\tload_chunk( 0 );\r\n\t\tstate = LOAD_STATE_LOADING0;\r\n\t\tgPcmStatus &= ~PCMSTATUS_NEED_AUDIO_BUFFER_0( m_streamType );\r\n\t}\r\n\telse if ( gPcmStatus & PCMSTATUS_NEED_AUDIO_BUFFER_1( m_streamType ) )\r\n\t{\r\n\t\tload_chunk( 1 );\r\n\t\tstate = LOAD_STATE_LOADING1;\r\n\t\tgPcmStatus &= ~PCMSTATUS_NEED_AUDIO_BUFFER_1( m_streamType );\r\n\t}\r\n\r\n\treturn state;\r\n}\r\n\r\n// Checks to see if loading of stream chunk is done\r\n// errno will be non-zero if we were busy AND there was an error\r\nbool\t\t\tCFileStreamInfo::is_chunk_load_done(int & errno)\r\n{\r\n\tDbg_Assert(mp_fileHandle);\r\n\r\n\t// Clear error var\r\n\terrno = 0;\r\n\r\n\t// Check for delay errors\r\n\t// Garrett: We should only be concerned if we get a request for the buffer we are currently loading.  The\r\n\t// only problem to this is the fact that the IOP doesn't check to see if a buffer is loaded at all.  We\r\n\t// must add this so we can get rid of the conservative check of making sure we don't get ANY new load requests.\r\n//\tif ( gPcmStatus & ( PCMSTATUS_NEED_AUDIO_BUFFER_0( m_streamType ) | PCMSTATUS_NEED_AUDIO_BUFFER_1( m_streamType ) ) )\r\n\tint load_flag = (m_loadState == LOAD_STATE_LOADING0) ? PCMSTATUS_NEED_AUDIO_BUFFER_0( m_streamType ) : PCMSTATUS_NEED_AUDIO_BUFFER_1( m_streamType );\r\n\tif ( gPcmStatus & load_flag )\r\n\t{\r\n\t\tint cur_buffer_load = (int) (m_loadState - LOAD_STATE_LOADING0);\r\n\t\tDbg_Message(\"Load State: %d\", m_loadState);\r\n\t\tDbg_MsgAssert( 0, ( \"If repeatable, tell Garrett that audio #%d buffer #%d didn't load on time. Status: %x\", m_streamType, cur_buffer_load, gPcmStatus ));\r\n\t\tprintf( \"If repeatable, tell Garrett audio #%d buffer #%d didn't load on time -- must increase IOP streaming buf size. Status %x\", m_streamType, cur_buffer_load, gPcmStatus );\r\n\t\terrno = (IsMusicStream()) ? -1 : m_streamType;\r\n\t}\r\n\r\n\tif (!mp_fileHandle->IsBusy())\r\n\t{\r\n\t\tint cur_buffer_load = (int) (m_loadState - LOAD_STATE_LOADING0);\r\n\r\n\t\t// Tell IOP that we are done\r\n\t\tsend_load_done(m_streamType, cur_buffer_load, IsMusicStream() ? MUSIC_IOP_BUFFER_SIZE : STREAM_HALF_IOP_BUFFER_SIZE);\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Return that we aren't done\r\n\treturn false;\r\n}\r\n\r\n// returns true and closes fine if we read the whole file\r\nbool\t\t\tCFileStreamInfo::file_finished()\r\n{\r\n\tif ( m_offset < m_fileSize )\r\n\t{\r\n\t\treturn false;\r\n\t} else {\r\n\t\tDbg_Assert(mp_fileHandle);\t\t// It shouldn't be closed yet\r\n\r\n\t\tFile::CAsyncFileLoader::sClose( mp_fileHandle );\r\n\t\tmp_fileHandle = NULL;\r\n\r\n\t\treturn true;\r\n\t}\r\n}\r\n\r\n// Starts an audio stream\r\nbool\t\t\tCFileStreamInfo::StartStream(File::SHedFile *pHedFile, bool play)\r\n{\r\n\t// make sure CD isn't being used by another system:\r\n\t// Garrett: This should go away\r\n\tFile::StopStreaming( );\r\n\r\n\t// Make sure these load flags aren't set\r\n\tif ( gPcmStatus & ( PCMSTATUS_NEED_AUDIO_BUFFER_0( m_streamType ) | PCMSTATUS_NEED_AUDIO_BUFFER_1( m_streamType ) ) )\r\n\t{\r\n\t\tDbg_Message(\"Load State: %d\", m_loadState);\r\n\t\tDbg_MsgAssert( 0, ( \"Start Stream on audio #%d still has load buffer flag. Status: %x\", m_streamType, gPcmStatus ));\r\n\t\tprintf( \"Start Stream on audio #%d still has load buffer flag. Status %x\", m_streamType, gPcmStatus );\r\n\t}\r\n\r\n\t// Find correct wad filename\r\n\tchar *p_wadName;\r\n\tunsigned int wadLsn;\r\n\tint priority;\r\n\r\n\tif (IsMusicStream())\r\n\t{\r\n\t\twadLsn = gWadInfo[MUSIC_CHANNEL].m_lsn;\r\n\t\tp_wadName = gWadInfo[MUSIC_CHANNEL].m_fileName;\r\n\t\tpriority = MUSIC_PRIORITY;\r\n\t}\r\n\telse\r\n\t{\r\n\t\twadLsn = gWadInfo[EXTRA_CHANNEL].m_lsn;\r\n\t\tp_wadName = gWadInfo[EXTRA_CHANNEL].m_fileName;\r\n\t\tpriority = STREAM_PRIORITY;\r\n\t}\r\n\r\n\t// load Audio wad:\r\n\tif ( mp_fileHandle )\r\n\t{\r\n\t\tDbg_Message( \"What?  Audio file opened still: %d\", mp_fileHandle );\r\n\t\tDbg_MsgAssert( 0,( \"What?  Stream file still (or already) opened.\" ));\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (Config::CD() || TEST_MOTHERFUCKING_CD)\r\n\t{\r\n\t\tmp_fileHandle = File::CPs2AsyncFileLoader::sRawOpen(wadLsn, false, priority);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (pHedFile->HasNoWad())\r\n\t\t{\r\n\t\t\tchar local_file[256];\r\n\r\n\t\t\tstrcpy(local_file, pHedFile->p_filename);\r\n\t\t\tif (IsMusicStream())\r\n\t\t\t{\r\n\t\t\t\tstrcat(local_file, \".ivg\");\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tstrcat(local_file, \".vag\");\r\n\t\t\t}\r\n\t\t\tmp_fileHandle = File::CAsyncFileLoader::sOpen(&local_file[1], false, priority);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_fileHandle = File::CAsyncFileLoader::sOpen(p_wadName, false, priority);\r\n\t\t}\r\n\t}\r\n\r\n\tif ( !mp_fileHandle )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Play Audio: couldn't find audio wad file %s\", p_wadName ));\r\n\t\tprintf( \"play audio failed to find audio wad file %s\\n\", p_wadName );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tm_offset = 0;\r\n\tmp_fileHandle->SetDestination(File::MEM_IOP);\r\n\r\n\tif (pHedFile->HasNoWad())\r\n\t{\r\n\t\t// .ivg files don't have the VAG header\r\n\t\tif (!IsMusicStream()) mp_fileHandle->Seek( SIZE_OF_VAGHEADER, SEEK_SET );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_fileHandle->Seek( pHedFile->Offset, SEEK_SET );\r\n\t}\r\n\r\n\tm_fileSize = pHedFile->GetFileSize();\r\n\tm_loadState = LOAD_STATE_LOADING0;\r\n\tm_playState = (play) ? PLAY_STATE_START : PLAY_STATE_PRELOAD_EE;\r\n\r\n\t// Start loading the data, but don't play it yet\r\n\tload_chunk(0);\r\n\r\n\t// Change the state\r\n\tgPcmStatus |= PCMSTATUS_LOAD_AUDIO(m_streamType);\r\n\r\n\treturn true;\r\n}\r\n\r\n// Plays a preloaded audio stream\r\nbool\t\t\tCFileStreamInfo::PlayStream()\r\n{\r\n\tswitch (m_playState)\r\n\t{\r\n\tcase PLAY_STATE_DONE:\r\n\tcase PLAY_STATE_PLAYING:\r\n\t\treturn false;\r\n\r\n\tcase PLAY_STATE_PAUSED:\r\n\t\t// Not implemented yet\r\n\t\tDbg_MsgAssert(0, (\"Playing a paused stream not implemented yet\"));\r\n\t\treturn false;\r\n\r\n\tcase PLAY_STATE_PRELOAD_EE:\r\n\t\tDbg_MsgAssert(0, (\"Starting a preloaded stream that isn't finished preloading\"));\r\n\t\treturn false;\r\n\r\n\tcase PLAY_STATE_PRELOAD_IOP:\r\n\tcase PLAY_STATE_STOP:\r\n\tcase PLAY_STATE_START:\r\n\t\tswitch (m_loadState)\r\n\t\t{\r\n\t\tcase LOAD_STATE_DONE:\r\n\t\tcase LOAD_STATE_IDLE:\r\n\t\tcase LOAD_STATE_LOADING1:\t\t\t// Since it may already be loading the next section\r\n\t\t\tm_playState = PLAY_STATE_PLAYING;\r\n\r\n\t\t\t//start_audio();\r\n\t\t\tstart_preloaded_audio();\r\n\r\n\t\t\tbreak;\r\n\r\n\t\tcase LOAD_STATE_LOADING0:\r\n\t\t\tm_playState = PLAY_STATE_START;\r\n\t\t\tDbg_MsgAssert(0, (\"Starting a preloaded stream that isn't finished preloading. Load state: %d\", m_loadState));\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tbreak;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// Stops an audio stream\r\nbool\t\t\tCFileStreamInfo::StopStream()\r\n{\r\n\tint status = IsMusicStream() ? PCMAudio_GetMusicStatus( ) : PCMAudio_GetStreamStatus( GetAudioStreamIndex() );\r\n\r\n\t// Check states\r\n\tif ( status == PCM_STATUS_PLAYING )\r\n\t{\r\n\t\tif (IsMusicStream())\r\n\t\t{\r\n\t\t\tEzPcm( EzADPCM_STOPMUSIC, 0 );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tEzPcm( EzADPCM_STOPSTREAM, GetAudioStreamIndex() );\r\n\t\t}\r\n\t}\r\n\r\n\t// Close async file\r\n\tif ( mp_fileHandle )\r\n\t{\r\n\t\tm_loadState = LOAD_STATE_DONE;\r\n\t\tFile::CAsyncFileLoader::sClose( mp_fileHandle );\r\n\t\tmp_fileHandle = NULL;\r\n\t}\r\n\r\n\t// Clear flags\r\n\tPCMAudio_UpdateStatus();\r\n\tm_playState = PLAY_STATE_DONE;\r\n\tgPcmStatus &= ~( PCMSTATUS_NEED_AUDIO_BUFFER_0( m_streamType ) |\r\n\t\t\t\t\t PCMSTATUS_NEED_AUDIO_BUFFER_1( m_streamType ) |\r\n\t\t\t\t\t PCMSTATUS_LOAD_AUDIO( m_streamType ) |\r\n\t\t\t\t\t PCMSTATUS_AUDIO_PLAYING( m_streamType ) |\r\n\t\t\t\t\t PCMSTATUS_AUDIO_READY(m_streamType) );\r\n\r\n\treturn true;\r\n}\r\n\r\n// Update: executed on each stream every frame\r\n// returns error number on error, 0 otherwise...\r\nint\t\t\t\tCFileStreamInfo::Update()\r\n{\r\n\tint errno = 0;\r\n\r\n\tswitch (m_loadState)\r\n\t{\r\n\tcase LOAD_STATE_IDLE:\r\n\t\t// Make sure IOP didn't drop out (would probably be a state problem)\r\n\t\t//Dbg_MsgAssert(gPcmStatus & PCMSTATUS_AUDIO_PLAYING( m_streamType ), (\"Generic stream %d not playing while in LOAD_STATE_IDLE\", m_streamType));\r\n\r\n\t\tm_loadState = check_for_load_requests();\r\n\r\n\t\tbreak;\r\n\r\n\tcase LOAD_STATE_LOADING0:\r\n\tcase LOAD_STATE_LOADING1:\r\n\t\t// Make sure IOP didn't drop out (would probably be a state problem)\r\n\t\t//Dbg_MsgAssert(gPcmStatus & PCMSTATUS_AUDIO_PLAYING( m_streamType ), (\"Generic stream %d not playing while in LOAD_STATE_LOADING\", m_streamType));\r\n\r\n\t\tif (!is_chunk_load_done(errno))\r\n\t\t{\r\n\t\t\tif (errno != 0)\r\n\t\t\t{\r\n\t\t\t\treturn errno;\r\n\t\t\t}\r\n\r\n\t\t\tbreak; // still busy loading\r\n\t\t}\r\n\r\n\t\t// Check if it needs starting\r\n\t\tif (m_playState == PLAY_STATE_START)\r\n\t\t{\r\n\t\t\tm_playState = PLAY_STATE_PLAYING;\r\n\r\n\t\t\tstart_audio();\r\n\t\t}\r\n\t\telse if (m_playState == PLAY_STATE_PRELOAD_EE)\r\n\t\t{\r\n\t\t\tm_playState = PLAY_STATE_PRELOAD_IOP;\r\n\r\n\t\t\tpreload_spu_buffers();\r\n\t\t}\r\n\r\n\t\t// Change state and possibly close file\r\n\t\tif (file_finished())\r\n\t\t{\r\n\t\t\tm_loadState = LOAD_STATE_DONE;\r\n\t\t} else {\r\n\t\t\tm_loadState = LOAD_STATE_IDLE;\r\n\t\t}\r\n\r\n\t\tbreak;\r\n\r\n\tcase LOAD_STATE_DONE:\r\n\t\t// Just wait for the audio to finish playing\r\n\t\tif ( !(gPcmStatus & PCMSTATUS_AUDIO_PLAYING( m_streamType )) )\r\n\t\t{\r\n\t\t\tm_playState = PLAY_STATE_DONE;\r\n\t\t\t// Clear out any old sent load request flags\r\n\t\t\tgPcmStatus &= ~( PCMSTATUS_NEED_AUDIO_BUFFER_0( m_streamType ) | PCMSTATUS_NEED_AUDIO_BUFFER_1( m_streamType ) );\r\n\t\t}\r\n\r\n\t\tbreak;\r\n\t}\r\n\r\n\treturn errno;\r\n}\r\n\r\n#define DEBUG_LOAD_FLAGS 0\r\n\r\n#if DEBUG_LOAD_FLAGS\r\nint old_load_state[NUM_FILE_STREAMS];\r\nint old_play_state[NUM_FILE_STREAMS];\r\n#endif\r\n\r\n// Combine the IOP sent status into gPcmStatus\r\nvoid PCMAudio_UpdateStatus()\r\n{\r\n\tint new_status;\r\n\r\n\tif (get_status(new_status))\r\n\t{\r\n\t\tfor ( int i = 0; i < NUM_FILE_STREAMS; i++ )\r\n\t\t{\r\n\t\t\tgPcmStatus &= ~( PCMSTATUS_AUDIO_PLAYING( i ) | PCMSTATUS_AUDIO_READY( i ) );\r\n\t\t}\r\n\t\tgPcmStatus |= new_status;\r\n\t}\r\n}\r\n\r\n\r\n// returns error number on error, 0 otherwise...\r\nint PCMAudio_Update( void )\r\n{\r\n\tint i;\r\n\r\n#if DEBUG_LOAD_FLAGS\r\n\tfor (int i = 0; i < NUM_FILE_STREAMS; i++)\r\n\t{\r\n\t\told_load_state[i] = gStreamList[ i ].m_loadState;\r\n\t\told_play_state[i] = gStreamList[ i ].m_playState;\r\n\t}\r\n#endif\r\n\r\n\t// Clear the flags\r\n\tPCMAudio_UpdateStatus();\r\n\r\n\tstatic bool print_panic = true;\t\t// Using this now until we can clear the PANIC flag on the IOP\r\n\tif ((gPcmStatus & PCMSTATUS_PANIC) && print_panic)\r\n\t{\r\n\t\tprint_panic = false;\r\n\t\tscePrintf(\"ezpcm.irx module set PANIC flag: Look at its last error message.\\n\");\r\n\t\t//Dbg_MsgAssert(0, (\"ezpcm.irx module set PANIC flag: Look at its last error message.\"));\r\n\t}\r\n\r\n\t// Make sure there aren't any CD errors\r\n\tif (0 && (Config::CD() || TEST_MOTHERFUCKING_CD) && CheckForCDErrors( ))\r\n\t{\r\n\t\treturn ( -1 );\r\n\t}\r\n\r\n\t// Go through each stream and update\r\n\tfor (i = 0; i < NUM_FILE_STREAMS; i++)\r\n\t{\r\n\t\tCFileStreamInfo *pInfo = &gStreamList[ i ];\r\n\r\n\t\tint ret_val = pInfo->Update();\r\n\r\n\t\tif (ret_val != 0)\r\n\t\t{\r\n\t\t\treturn ret_val;\r\n\t\t}\r\n\t}\r\n\r\n#if 0\r\n\t\t// If file loads go out of sync over a busy network, keep it from crashing:\r\n\t\tif ( gMusicInfo.mp_fileHandle && !( gPcmStatus & PCMSTATUS_MUSIC_PLAYING ) )\r\n\t\t{\r\n\t\t\tFile::CAsyncFileLoader::sClose( gMusicInfo.mp_fileHandle );\r\n\t\t\tgMusicInfo.mp_fileHandle = NULL;\r\n\t\t\tDbg_Message( \"Symptom of a busy network: Closing music file.\" );\r\n\t\t}\r\n\t\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t\t{\r\n\t\t\tif ( gStreamInfo[ i ].mp_fileHandle && !( gPcmStatus & (PCMSTATUS_STREAM_PLAYING( i ) | PCMSTATUS_LOAD_STREAM( i ))) )\r\n\t\t\t{\r\n\t\t\t\tFile::CAsyncFileLoader::sClose( gStreamInfo[i].mp_fileHandle );\r\n\t\t\t\tgStreamInfo[ i ].mp_fileHandle = NULL;\r\n\t\t\t\tDbg_Message( \"Symptom of a busy network: Closing stream file.\" );\r\n\t\t\t}\r\n\t\t}\r\n#endif\r\n\r\n#if 0\r\n\tDbg_MsgAssert(!(gPcmStatus & ( PCMSTATUS_NEED_MUSIC_BUFFER_0 | PCMSTATUS_NEED_MUSIC_BUFFER_1 |\r\n\t\t\t\t\t\tPCMSTATUS_NEED_STREAM0_BUFFER_0 | PCMSTATUS_NEED_STREAM0_BUFFER_1 |\r\n\t\t\t\t\t\tPCMSTATUS_NEED_STREAM1_BUFFER_0 | PCMSTATUS_NEED_STREAM1_BUFFER_1 |\r\n\t\t\t\t\t\tPCMSTATUS_NEED_STREAM2_BUFFER_0 | PCMSTATUS_NEED_STREAM2_BUFFER_1 )), (\"Skipped a buffer load: status %x\", gPcmStatus));\r\n#else\r\n\tif (gPcmStatus & ( PCMSTATUS_NEED_MUSIC_BUFFER_0 | PCMSTATUS_NEED_MUSIC_BUFFER_1 |\r\n\t\t\t\t\t\tPCMSTATUS_NEED_STREAM0_BUFFER_0 | PCMSTATUS_NEED_STREAM0_BUFFER_1 |\r\n\t\t\t\t\t\tPCMSTATUS_NEED_STREAM1_BUFFER_0 | PCMSTATUS_NEED_STREAM1_BUFFER_1 |\r\n\t\t\t\t\t\tPCMSTATUS_NEED_STREAM2_BUFFER_0 | PCMSTATUS_NEED_STREAM2_BUFFER_1 ))\r\n\t{\r\n\t\tDbg_Message(\"************Skipped a buffer load: status %x\", gPcmStatus);\r\n#if DEBUG_LOAD_FLAGS\r\n\t\tfor (int i = 0; i < NUM_FILE_STREAMS; i++)\r\n\t\t{\r\n\t\t\tDbg_Message(\"Audio Stream %d: load state = %d\", i, gStreamList[ i ].m_loadState);\r\n\t\t\tDbg_Message(\"Audio Stream %d: play state = %d\", i, gStreamList[ i ].m_playState);\r\n\t\t\tDbg_Message(\"Audio Stream %d: old load state = %d\", i, old_load_state[i]);\r\n\t\t\tDbg_Message(\"Audio Stream %d: old play state = %d\", i, old_play_state[i]);\r\n\t\t}\r\n#endif\r\n\t}\r\n#endif\r\n\r\n\treturn ( 0 );\r\n}\r\n\r\n/* ------------\r\n   Initialize rpc  -- Just call once at the very beginning!\r\n   ------------ */\r\nvoid PCMAudio_Init( void )\r\n{\r\n\tDbg_MsgAssert(NUM_FILE_STREAMS == (NUM_STREAMS + 1),\r\n\t\t\t\t  (\"Number of file slots allocated for audio streams (%d) different than number of IOP audio streams (%d)\", NUM_FILE_STREAMS - 1, NUM_STREAMS));\r\n\r\n\t// Check to make sure stream array is filled\r\n\tfor (int i = 0; i < NUM_STREAMS; i++)\r\n\t{\r\n\t\tDbg_Assert(gpStreamInfo[i]);\r\n\t}\r\n\r\n\tDI();\r\n\r\n\tprintf( \"Setting up Sif Cmd with EzPCM Streaming IRX...\\n\" );\r\n\t// No longer need to call sceSifSetCmdBuffer() since we share it with async filesys\r\n//\tstatic sceSifCmdData cmdbuffer[NUM_COMMAND_HANDLERS];\r\n//\tsceSifSetCmdBuffer( &cmdbuffer[0], NUM_COMMAND_HANDLERS);\r\n\r\n\tsceSifAddCmdHandler(STREAM_RESULT_COMMAND, result_callback, NULL );\r\n\tsceSifAddCmdHandler(STREAM_STATUS_COMMAND, status_callback, NULL );\r\n\r\n\tEI();\r\n\r\n\t// if CD system hasn't been initialized,\r\n\t// but you want to test music from CD,\r\n\t// this will do it...\r\n\tInitCDPlease( );\r\n\r\n\r\n\tDbg_MsgAssert( !gIopBuffer,( \"What the fuck - buffer already exists?\" ));\r\n\r\n\tFlushCache( 0 );\r\n\t\r\n\tPCMAudio_GetIopMemory( );\r\n\t\r\n\tEzPcm( EzADPCM_INIT, gIopBuffer );\r\n\t//EzPcm( EzADPCM_SETSTREAMGLOBVOL, gStreamVolume );\r\n} // end of PCMAudio_Init( )\r\n\r\nint PCMAudio_GetIopMemory( void )\r\n{\r\n\t\r\n\t\r\n\tif ( !gNonAllignedIopBuffer )\r\n\t{\r\n\t\t// streaming buffers:\r\n\t\tgNonAllignedIopBuffer = ( int )sceSifAllocIopHeap( TOTAL_IOP_BUFFER_SIZE_NEEDED + ALLIGN_REQUIREMENT );\r\n\t\tgIopBuffer = gNonAllignedIopBuffer + ALLIGN_REQUIREMENT - ( gNonAllignedIopBuffer & ( ALLIGN_REQUIREMENT - 1 ) );\r\n\t\r\n\t\tif ( !gNonAllignedIopBuffer )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"Failed to allocate IOP memory - %d k\\n\", TOTAL_IOP_BUFFER_SIZE_NEEDED / 1024 ));\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t}\r\n\treturn ( gIopBuffer );\r\n}\r\nvoid PCMAudio_SetStreamGlobalVolume( unsigned int volume )\r\n{\r\n\tgStreamVolume = volume;\r\n\t//if ( gPcmStatus ) // make sure we've initialized PCM stuff:\r\n\t//{\r\n\t//\tEzPcm( EzADPCM_SETSTREAMGLOBVOL, gStreamVolume );\r\n\t//}\r\n}\r\n\r\nbool PCMAudio_SetMusicVolume( float volume )\r\n{\r\n\tint vol = ( int )PERCENT( volume, MAX_VOL );\r\n\tif ( vol > MAX_VOL )\r\n\t\tvol = MAX_VOL;\r\n\r\n\tEzPcm( EzADPCM_SETMUSICVOL, ( vol << 16 ) | vol );\r\n\treturn true;\r\n}// end of PCMAudio_SetMusicVolume( )\r\n\r\n\r\n/*int PCMAudio_SetStreamVolumeAndPitch( float volumeL, float volumeR, float fPitch, int whichStream )\r\n{\r\n\tDbg_Message( \"pitch %d\", pitch );\r\n   \treturn ( EzPcm( EzADPCM_SETSTREAMVOLANDPITCH | whichStream, ( ( volL << 16 ) | volR ), pitch ) );\r\n}// end of PCMAudio_SetVolumeAndPitch( )\r\n*/\r\n\r\n// Should check before calling this to make sure the sound is playing and has the uniqueID of the sound you are\r\n// trying to adjust:\r\nbool PCMAudio_SetStreamVolume( float volumeL, float volumeR, int whichStream )\r\n{\r\n\tint volL = ( int )PERCENT( volumeL, gStreamVolume );\r\n\tvolL = ( int )PERCENT( volL, NORMAL_VOL );\r\n\tif ( volL > MAX_VOL )\r\n\t\tvolL = MAX_VOL;\r\n\telse if ( volL < -MAX_VOL )\r\n\t\tvolL = -MAX_VOL;\r\n\tint volR;\r\n\tif ( volumeR == volumeL )\r\n\t{\r\n\t\tvolR = volL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tvolR = ( int )PERCENT( volumeR, gStreamVolume );\r\n\t\tvolR = ( int )PERCENT( volR, NORMAL_VOL );\r\n\t\tif ( volR > MAX_VOL )\r\n\t\t\tvolR = MAX_VOL;\r\n\t\telse if ( volR < -MAX_VOL )\r\n\t\t\tvolR = -MAX_VOL;\r\n\t}\r\n\r\n\t// for phasing effects (of sounds behind you), set the volume\r\n\t// to 0x7fff\r\n\tif ( volL < 0 )\r\n\t{\r\n\t\tvolL = 0x7fff + volL;\r\n\t}\r\n\tif ( volR < 0 )\t\t// Just in case we start phase shifting the right side instead\r\n\t{\r\n\t\tvolR = 0x7fff + volR;\r\n\t}\r\n\r\n\tgpStreamInfo[ whichStream ]->m_volume = ( ( (volL & 0x7FFF) << 16 ) | (volR & 0x7FFF) );\r\n\r\n\tif (gpStreamInfo[ whichStream ]->m_playState == PLAY_STATE_PLAYING)\r\n\t{\r\n\t\tEzPcm( EzADPCM_SETSTREAMVOL | whichStream, gpStreamInfo[ whichStream ]->m_volume);\r\n\t}\r\n\r\n\treturn true;\r\n}// end of PCMAudio_SetVolume( )\r\n\r\n// Currently, this only works when the stream isn't playing\r\nbool PCMAudio_SetStreamPitch( float fPitch, int whichStream )\r\n{\r\n\tif ( fPitch > 100.0f )\r\n\t{\r\n\t\tfPitch = 100.0f;\r\n\t}\r\n\tint pitch;\r\n\tpitch = ( int ) PERCENT( fPitch, ( float )DEFAULT_PITCH ); \r\n\tif ( pitch == 0 )\r\n\t{\r\n\t\tDbg_Message( \"Trying to set stream to zero pitch.\" );\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\tif (gpStreamInfo[ whichStream ]->m_playState == PLAY_STATE_PLAYING)\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't change pitch of stream %d while it is playing\", whichStream));\r\n\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgpStreamInfo[ whichStream ]->m_pitch = pitch;\r\n\t\treturn true;\r\n\t}\r\n}\r\n\r\nbool PCMAudio_PlayMusicTrack( const char *filename )\r\n{\r\n\tif ( PCMAudio_GetMusicStatus( ) != PCM_STATUS_FREE )\r\n\t{\r\n\t\tDbg_MsgAssert( 0 , ( \"Playing new track without stopping the first track.\" ) );\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\tif (!(Config::CD() || TEST_MOTHERFUCKING_CD))\r\n\t{\r\n\t\tint testMusic = 0;\r\n\t\ttestMusic = Script::GetInteger( 0x47ac7ba5 ); // checksum 'testMusicFromHost'\r\n\t\tif ( !testMusic )\r\n\t\t{\r\n\t\t\treturn ( false );\r\n\t\t}\r\n\t}\r\n\r\n\t// make sure CD is not in use by another system:\r\n\tFile::StopStreaming( );\r\n\r\n\tif ( !gWadInfo[MUSIC_CHANNEL].mp_hed )\r\n\t{\r\n\t\tDbg_Message( \"Music header not loaded, can't play track %s\", filename );\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\tFile::SHedFile *pHed = FindFileInHed( filename, gWadInfo[MUSIC_CHANNEL].mp_hed );\r\n\tif ( !pHed )\r\n\t{\r\n\t\tDbg_Message( \"Track %d not found in music header.\", filename );\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\t// Start the actual stream\r\n\treturn gpMusicInfo->StartStream(pHed, true);\r\n} // end of PCMAudio_PlayMusicTrack( )\r\n\r\n\r\nbool PCMAudio_PlayMusicStream( uint32 checksum )\r\n{\r\n\tif ( PCMAudio_GetMusicStatus( ) != PCM_STATUS_FREE )\r\n\t{\r\n\t\tDbg_MsgAssert( 0 , ( \"Playing music stream without stopping the last music track.\" ) );\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\tif (!(Config::CD() || TEST_MOTHERFUCKING_CD))\r\n\t{\r\n\t\tint testMusic = 0;\r\n\t\ttestMusic = Script::GetInteger( 0x47ac7ba5 ); // checksum 'testMusicFromHost'\r\n\t\tif ( !testMusic )\r\n\t\t{\r\n\t\t\treturn ( false );\r\n\t\t}\r\n\t}\r\n\r\n\t// make sure CD is not in use by another system:\r\n\tFile::StopStreaming( );\r\n\r\n\tif ( !gWadInfo[MUSIC_CHANNEL].mp_hed )\r\n\t{\r\n\t\tDbg_Message( \"Music header not loaded, can't play music stream %s\", Script::FindChecksumName(checksum) );\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\tFile::SHedFile *pHed = FindFileInHedUsingChecksum( checksum, gWadInfo[MUSIC_CHANNEL].mp_hed );\r\n\tif ( !pHed )\r\n\t{\r\n\t\tDbg_Message( \"Music Stream %s not found in music header.\", Script::FindChecksumName(checksum) );\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\t// Start the actual stream\r\n\treturn gpMusicInfo->StartStream(pHed, true);\r\n}\r\n\r\nbool PCMAudio_PlayStream( uint32 checksum, int whichStream, float volumeL, float volumeR, float fPitch )\r\n{\r\n\tDbg_MsgAssert( whichStream < NUM_STREAMS, ( \"Stream is out of range\" ) );\r\n\r\n\tif ( PCMAudio_GetStreamStatus( whichStream ) != PCM_STATUS_FREE )\r\n\t{\r\n\t\tDbg_Message(\"Stream %d not free: status is %x\", whichStream, PCMAudio_GetStreamStatus( whichStream ));\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\tif (!(Config::CD() || TEST_MOTHERFUCKING_CD))\r\n\t{\r\n\t\tint testStreams = 0;\r\n\t\ttestStreams = Script::GetInteger( 0x62df9442 ); // checksum 'testStreamsFromHost'\r\n\t\tif ( !testStreams )\r\n\t\t{\r\n\t\t\treturn ( false );\r\n\t\t}\r\n\t}\t\r\n\t\r\n\t//Dbg_Message(\"Playing stream %x on %d\", checksum, whichStream);\r\n\r\n\t// load from vag wad:\r\n\tif ( !gWadInfo[EXTRA_CHANNEL].mp_hed )\r\n\t{\r\n\t\t//Dbg_Message( \"Stream header not loaded, can't play track %s\", filename );\r\n\t\treturn ( false );\r\n\t}\r\n\tFile::SHedFile *pHed = FindFileInHedUsingChecksum( checksum, gWadInfo[EXTRA_CHANNEL].mp_hed );\r\n\tif ( !pHed )\r\n\t{\r\n\t\tDbg_Message( \"Stream %s not found in stream header.\", Script::FindChecksumName(checksum) );\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\t// Set pitch and volume\r\n\tPCMAudio_SetStreamPitch(fPitch, whichStream);\r\n\tPCMAudio_SetStreamVolume(volumeL, volumeR, whichStream);\r\n\r\n\t// Start the actual stream\r\n\treturn gpStreamInfo[ whichStream ]->StartStream(pHed, true);\r\n} // end of PCMAudio_PlayStream( )\r\n\r\nvoid PCMAudio_StopMusic( bool waitPlease )\r\n{\r\n\tgpMusicInfo->StopStream();\r\n}\r\n\r\nvoid PCMAudio_StopStream( int whichStream, bool waitPlease )\r\n{\r\n\tgpStreamInfo[ whichStream ]->StopStream();\r\n}\r\n\r\nvoid PCMAudio_StopStreams( void )\r\n{\r\n\tint i;\r\n\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t{\r\n\t\tPCMAudio_StopStream( i, true );\r\n\t}\r\n}\r\n\r\n// Get a stream loaded into a buffer, but don't play yet\r\nbool PCMAudio_PreLoadStream( uint32 checksum, int whichStream )\r\n{\r\n\tDbg_MsgAssert( whichStream < NUM_STREAMS, ( \"Stream is out of range\" ) );\r\n\r\n\tif ( PCMAudio_GetStreamStatus( whichStream ) != PCM_STATUS_FREE )\r\n\t{\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\tif (!(Config::CD() || TEST_MOTHERFUCKING_CD))\r\n\t{\r\n\t\tint testStreams = 0;\r\n\t\ttestStreams = Script::GetInteger( 0x62df9442 ); // checksum 'testStreamsFromHost'\r\n\t\tif ( !testStreams )\r\n\t\t{\r\n\t\t\treturn ( false );\r\n\t\t}\r\n\t}\r\n\r\n\t// load from vag wad:\r\n\tif ( !gWadInfo[EXTRA_CHANNEL].mp_hed )\r\n\t{\r\n\t\t//Dbg_Message( \"Stream header not loaded, can't play track %s\", filename );\r\n\t\treturn ( false );\r\n\t}\r\n\tFile::SHedFile *pHed = FindFileInHedUsingChecksum( checksum, gWadInfo[EXTRA_CHANNEL].mp_hed );\r\n\tif ( !pHed )\r\n\t{\r\n\t\t//Dbg_Message( \"Track %d not found in stream header.\", filename );\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\t// Start the actual stream\r\n\treturn gpStreamInfo[ whichStream ]->StartStream(pHed, false);\r\n}\r\n\r\n// Returns true if preload done.  Assumes that caller is calling this on a preloaded, but not yet played, stream.\r\n// The results are meaningless otherwise.\r\nbool PCMAudio_PreLoadStreamDone( int whichStream )\r\n{\r\n\tDbg_MsgAssert( whichStream < NUM_STREAMS, ( \"Stream is out of range\" ) );\r\n\tDbg_MsgAssert( (gpStreamInfo[whichStream]->m_playState == PLAY_STATE_PRELOAD_EE) ||\r\n\t\t\t\t   (gpStreamInfo[whichStream]->m_playState == PLAY_STATE_PRELOAD_IOP), ( \"PreLoadStreamDone(): This stream on channel %d is either playing or wasn't preloaded.  Load state %d.  Play State %d. IOP flags %x\",\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t whichStream, gpStreamInfo[whichStream]->m_loadState, gpStreamInfo[whichStream]->m_playState, gPcmStatus ) );\r\n\r\n\t//return gpStreamInfo[whichStream]->m_loadState != LOAD_STATE_LOADING0;\r\n\tif (gPcmStatus & PCMSTATUS_STREAM_READY(whichStream))\r\n\t{\r\n\t\tDbg_Message(\"PCMAudio_PreLoadStreamDone true for stream channel %d.  Load state %d.  Play State %d. IOP flags %x\", whichStream,\r\n\t\t\t\t\tgpStreamInfo[whichStream]->m_loadState, gpStreamInfo[whichStream]->m_playState, gPcmStatus);\r\n\t}\r\n\treturn (gPcmStatus & PCMSTATUS_STREAM_READY(whichStream)) && (gpStreamInfo[whichStream]->m_playState == PLAY_STATE_PRELOAD_IOP);\r\n}\r\n\r\n// Tells a preloaded stream to start playing.  Must call PCMAudio_PreLoadStreamDone() first to guarantee that\r\n// it starts immediately.\r\nbool PCMAudio_StartPreLoadedStream( int whichStream, float volumeL, float volumeR, float pitch )\r\n{\r\n\tDbg_MsgAssert( whichStream < NUM_STREAMS, ( \"Stream is out of range\" ) );\r\n\r\n\t// Set pitch and volume\r\n\tPCMAudio_SetStreamPitch(pitch, whichStream);\r\n\tPCMAudio_SetStreamVolume(volumeL, volumeR, whichStream);\r\n\r\n\t// Start playing the actual stream\r\n\treturn gpStreamInfo[ whichStream ]->PlayStream();\r\n}\r\n\r\nbool PCMAudio_PreLoadMusicStream( uint32 checksum )\r\n{\r\n\tif ( PCMAudio_GetMusicStatus( ) != PCM_STATUS_FREE )\r\n\t{\r\n\t\tDbg_MsgAssert( 0 , ( \"Preloading music stream without stopping the last music track.\" ) );\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\tif (!(Config::CD() || TEST_MOTHERFUCKING_CD))\r\n\t{\r\n\t\tint testMusic = 0;\r\n\t\ttestMusic = Script::GetInteger( 0x47ac7ba5 ); // checksum 'testMusicFromHost'\r\n\t\tif ( !testMusic )\r\n\t\t{\r\n\t\t\treturn ( false );\r\n\t\t}\r\n\t}\r\n\r\n\t// load from vag wad:\r\n\tif ( !gWadInfo[MUSIC_CHANNEL].mp_hed )\r\n\t{\r\n\t\t//Dbg_Message( \"Stream header not loaded, can't play track %s\", filename );\r\n\t\treturn ( false );\r\n\t}\r\n\tFile::SHedFile *pHed = FindFileInHedUsingChecksum( checksum, gWadInfo[MUSIC_CHANNEL].mp_hed );\r\n\tif ( !pHed )\r\n\t{\r\n\t\tDbg_Message( \"Music Stream %s not found in music header.\", Script::FindChecksumName(checksum) );\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\t// Start the actual stream\r\n\treturn gpMusicInfo->StartStream(pHed, false);\r\n}\r\n\r\nbool PCMAudio_PreLoadMusicStreamDone( void )\r\n{\r\n\tDbg_MsgAssert( (gpMusicInfo->m_playState == PLAY_STATE_PRELOAD_EE) ||\r\n\t\t\t\t   (gpMusicInfo->m_playState == PLAY_STATE_PRELOAD_IOP), ( \"PreLoadMusicStreamDone(): This stream is either playing or wasn't preloaded.\" ) );\r\n\r\n\t//return gpMusicInfo->m_loadState != LOAD_STATE_LOADING0;\r\n\treturn (gPcmStatus & PCMSTATUS_MUSIC_READY) && (gpMusicInfo->m_playState == PLAY_STATE_PRELOAD_IOP);\r\n}\r\n\r\nbool PCMAudio_StartPreLoadedMusicStream( void )\r\n{\r\n\t// Start playing the actual stream\r\n\treturn gpMusicInfo->PlayStream();\r\n}\r\n\r\nint PCMAudio_GetMusicStatus( void )\r\n{\r\n\t\r\n\r\n\tif ( gPcmStatus & PCMSTATUS_LOAD_MUSIC )\r\n\t{\r\n\t\treturn ( PCM_STATUS_LOADING );\r\n\t}\r\n\telse if ( gPcmStatus & PCMSTATUS_MUSIC_PLAYING )\r\n\t{\r\n\t\treturn ( PCM_STATUS_PLAYING );\r\n\t}\r\n\telse if ( gpMusicInfo->m_playState == PLAY_STATE_STOP)\r\n\t{\r\n\t\treturn ( PCM_STATUS_STOPPED );\r\n\t}\r\n\telse if ( gpMusicInfo->m_playState == PLAY_STATE_PLAYING)\t\t// EE thinks it is playing, but not IOP\r\n\t{\r\n\t\treturn ( PCM_STATUS_END );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//Dbg_Message(\"Music status is free %x\", gPcmStatus);\r\n\t\treturn ( PCM_STATUS_FREE );\r\n\t}\r\n\tDbg_MsgAssert( 0,( \"Sell your stock in GCC.\" ));\r\n\treturn ( 0 );\r\n}\r\n\r\nint PCMAudio_GetStreamStatus( int whichStream )\r\n{\r\n\t\r\n\tif ( (whichStream < 0) || (whichStream >= NUM_STREAMS) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Checking stream status on stream %d, past valid range ( 0 to %d ).\", whichStream, NUM_STREAMS - 1 ) );\r\n\t\treturn ( false );\r\n\t}\r\n\tif ( gPcmStatus & PCMSTATUS_LOAD_STREAM( whichStream ) )\r\n\t{\r\n\t\treturn ( PCM_STATUS_LOADING );\r\n\t}\r\n\telse if ( gPcmStatus & PCMSTATUS_STREAM_PLAYING( whichStream ) )\r\n\t{\r\n\t\treturn ( PCM_STATUS_PLAYING );\r\n\t}\r\n\telse if ( gpStreamInfo[whichStream]->m_playState == PLAY_STATE_STOP)\r\n\t{\r\n\t\treturn ( PCM_STATUS_STOPPED );\r\n\t}\r\n\telse if ( gpStreamInfo[whichStream]->m_playState == PLAY_STATE_PLAYING)\t\t// EE thinks it is playing, but not IOP\r\n\t{\r\n\t\treturn ( PCM_STATUS_END );\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn ( PCM_STATUS_FREE );\r\n\t}\r\n\tDbg_MsgAssert( 0,( \"Sell your stock in GCC.\" ));\r\n\treturn ( 0 );\r\n}\r\n\r\nvoid PCMAudio_Pause( bool pause, int ch )\r\n{\r\n\tif ( ch == MUSIC_CHANNEL )\r\n\t{\r\n\t\tEzPcm( EzADPCM_PAUSEMUSIC, pause );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tEzPcm( EzADPCM_PAUSESTREAMS, pause );\r\n\t}\r\n} // end of PCMAudio_Pause( )\r\n\r\nvoid PCMAudio_PauseStream( bool pause, int whichStream )\r\n{\r\n\tEzPcm( EzADPCM_PAUSESTREAM | whichStream, pause );\r\n}\r\n\r\nunsigned int GetCDLocation( const char *pWadName )\r\n{\r\n\t\r\n\r\n\tInitCDPlease( );\r\n\r\n\tFile::StopStreaming( );\r\n\tsceCdSync( 0 );\r\n\r\n\tchar tempFilename[ 255 ];\r\n\tsprintf( tempFilename, \"\\\\%s%s.WAD;1\", Config::GetDirectory(), pWadName );\r\n\tint i;\r\n\tfor ( i = strlen( tempFilename ) - 1; i > 0; i-- )\r\n\t{\r\n\t\tif ( tempFilename[ i ] >= 'a' && tempFilename[ i ] <= 'z' )\r\n\t\t{\r\n\t\t\ttempFilename[ i ] += 'A' - 'a';\r\n\t\t}\r\n\t}\r\n\tsceCdlFILE fileInfo;\r\n\tint retVal = 0;\r\n\tif ( !( retVal = sceCdSearchFile( &fileInfo, tempFilename ) ) )\r\n\t{\r\n\t\tprintf( \"Wad %s not found -- Err %d\\n\", tempFilename, retVal );\r\n\t\treturn ( 0 );\r\n\t}\r\n\treturn ( fileInfo.lsn );\r\n}\r\n\r\nbool PCMAudio_TrackExists( const char *pTrackName, int ch )\r\n{\r\n\tif ( !gWadInfo[ch].mp_hed )\r\n\t{\r\n\t\treturn ( false );\r\n\t}\r\n\tif ( !FindFileInHed( pTrackName, gWadInfo[ch].mp_hed ) )\r\n\t{\r\n\t\tDbg_Message( \"Audio file %s not found in header file.\", pTrackName );\r\n\t\treturn ( false );\r\n\t}\r\n\treturn ( true );\r\n\t\r\n}\r\n\r\nbool PCMAudio_LoadMusicHeader( const char *nameOfFile )\r\n{\r\n\tbool no_wad = false;\r\n\r\n\tif (!(Config::CD() || TEST_MOTHERFUCKING_CD))\r\n\t{\r\n\t\tno_wad = true;\r\n\t}\t\r\n\r\n\treturn gWadInfo[MUSIC_CHANNEL].LoadHeader(nameOfFile, no_wad);\r\n}\r\n\r\nbool PCMAudio_LoadStreamHeader( const char *nameOfFile )\r\n{\r\n\tbool no_wad = false;\r\n\r\n\tif (!(Config::CD() || TEST_MOTHERFUCKING_CD))\r\n\t{\r\n\t\tint testStreams = 0;\r\n\t\ttestStreams = Script::GetInteger( 0x62df9442 ); // checksum 'testStreamsFromHost'\r\n\t\tif ( !testStreams )\r\n\t\t{\r\n\t\t\treturn ( false );\r\n\t\t}\r\n\r\n\t\tno_wad = true;\r\n\t}\t\r\n\t\r\n\treturn gWadInfo[EXTRA_CHANNEL].LoadHeader(nameOfFile, no_wad);\r\n}\r\n\r\nuint32 PCMAudio_FindNameFromChecksum( uint32 checksum, int ch )\r\n{\r\n\t\r\n\tFile::SHed *pHed;\r\n\r\n\tpHed = gWadInfo[ch].mp_hed;\r\n\r\n\tif ( !pHed )\r\n\t{\r\n\t\treturn ( NULL );\r\n\t}\r\n\r\n\tFile::SHedFile* pHedFile = File::FindFileInHedUsingChecksum( checksum, pHed );\r\n\tif( pHedFile )\r\n\t{\r\n\t\treturn pHedFile->Checksum;\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n// SWadInfo\r\n//\r\nbool\t\t\tSWadInfo::LoadHeader(const char *nameOfFile, bool no_wad, bool assertOnError)\r\n{\r\n\tif ( mp_hed )\r\n\t{\r\n\t\tMem::Free( mp_hed );\r\n\t\tmp_hed = NULL;\r\n\t}\r\n\r\n\tmp_hed = File::LoadHed( nameOfFile, TEST_MOTHERFUCKING_CD, no_wad );\r\n\tif ( !mp_hed )\r\n\t{\r\n\t\tDbg_Message( \"Couldn't find audio header %s\", nameOfFile );\r\n\t\tDbg_MsgAssert( !assertOnError, ( \"Couldn't find audio header %s\", nameOfFile ));\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (Config::CD() || TEST_MOTHERFUCKING_CD)\r\n\t{\r\n\t\tDbg_MsgAssert(!no_wad, (\"Can't use a no-wad version of a hed file on the CD\"));\r\n\r\n\t\tm_lsn = GetCDLocation( nameOfFile );\r\n\t\tif ( !m_lsn )\r\n\t\t{\r\n\t\t\tMem::Free( mp_hed );\r\n\t\t\tmp_hed = NULL;\r\n\t\t\tDbg_Message( \"Couldn't find audio wad %s\", nameOfFile );\r\n\t\t\tDbg_MsgAssert( !assertOnError,( \"Couldn't find audio wad %s\", nameOfFile ));\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t sprintf( m_fileName, \"host:%s.WAD\", nameOfFile );\r\n\t}\t \r\n\r\n\treturn (bool) mp_hed;\r\n}\r\n\r\n} // namespace PCM\r\n"
  },
  {
    "path": "Code/Gel/Music/Ngps/p_music.h",
    "content": "// Audio streaming function prototypes:\r\n// mjd jan 2001\r\n\r\n#ifndef __P_MUSIC_H__\r\n#define __P_MUSIC_H__\r\n\r\n// Forward declarations\r\nnamespace File\r\n{\r\n\tclass CAsyncFileHandle;\r\n\tstruct SHed;\r\n\tstruct SHedFile;\r\n}\r\n\r\nnamespace Pcm\r\n{\r\n\r\n// Stream types\r\nenum EFileStreamType \r\n{\r\n\tFILE_STREAM_MUSIC = 0,\r\n\tFILE_STREAM_STREAM0,\r\n\tFILE_STREAM_STREAM1,\r\n\tFILE_STREAM_STREAM2,\r\n\tNUM_FILE_STREAMS\r\n};\r\n\r\n// The load state of a stream\r\nenum ELoadState\r\n{\r\n\tLOAD_STATE_IDLE = 0,\r\n\tLOAD_STATE_LOADING0,\r\n\tLOAD_STATE_LOADING1,\r\n\tLOAD_STATE_DONE,\r\n};\r\n\r\n// The play state of a stream\r\nenum EPlayState\r\n{\r\n\tPLAY_STATE_STOP = 0,\r\n\tPLAY_STATE_PRELOAD_EE,\r\n\tPLAY_STATE_PRELOAD_IOP,\r\n\tPLAY_STATE_START,\r\n\tPLAY_STATE_PLAYING,\r\n\tPLAY_STATE_PAUSED,\r\n\tPLAY_STATE_DONE,\r\n};\r\n\r\n// allows one channel for music, another for audio:\r\nenum{\r\n\tEXTRA_CHANNEL,\r\n\tMUSIC_CHANNEL,\r\n};\r\n\r\n\r\n// Holds the info for each stream\r\nclass CFileStreamInfo\r\n{\r\npublic:\r\n\r\n\tbool\t\t\t\t\tIsMusicStream() const;\r\n\tint\t\t\t\t\t\tGetAudioStreamIndex() const;\t\t// returns a negative number if it isn't a audio stream\r\n\r\n\tbool\t\t\t\t\tStartStream(File::SHedFile *pHedFile, bool play);\r\n\tbool\t\t\t\t\tPlayStream();\r\n\tbool\t\t\t\t\tStopStream();\r\n\tint\t\t\t\t\t\tUpdate();\r\n\r\nprotected:\r\n\tvoid\t\t\t\t\tstart_audio();\r\n\tvoid\t\t\t\t\tload_chunk(int buffer);\r\n\r\n\t// For preloading\r\n\tvoid\t\t\t\t\tpreload_spu_buffers();\r\n\tvoid\t\t\t\t\tstart_preloaded_audio();\r\n\r\n\tELoadState\t\t\t\tcheck_for_load_requests();\r\n\tbool\t\t\t\t\tis_chunk_load_done(int & errno);\t// errno will be non-zero if we were busy AND there was an error\r\n\tbool\t\t\t\t\tfile_finished();\t\t\t\t\t// returns true and closes fine if we read the whole file\r\n\r\n// This section should eventually become \"protected\"\r\npublic:\r\n\tEFileStreamType\t\t\tm_streamType;\t\t\t// Either music or audio stream\r\n\tELoadState\t\t\t\tm_loadState;\r\n\tEPlayState\t\t\t\tm_playState;\r\n\tFile::CAsyncFileHandle *mp_fileHandle;\r\n\tint\t\t\t\t\t\tm_fileSize;\r\n\tint\t\t\t\t\t\tm_offset;\r\n\tint\t\t\t\t\t\tm_offsetInWad;\r\n\tint\t\t\t\t\t\tm_pitch;\r\n\tuint32\t\t\t\t\tm_volume;\r\n};\r\n\r\n// All the Wad information for music and audio\r\nstruct SWadInfo\r\n{\r\n\tbool\t\t\t\t\tLoadHeader(const char *nameOfFile, bool no_wad = false, bool assertOnError = false);\r\n\r\n\tchar  \t\t\t\t\tm_fileName[ 256 ];\r\n\tint\t\t\t\t\t\tm_lsn;\r\n\tFile::SHed *\t\t\tmp_hed;\r\n};\r\n\r\n\r\n\r\n// Onetime call once upon loading the game...\r\nvoid PCMAudio_Init( void );\r\n\r\n// Combine the IOP sent status into gPcmStatus\r\nvoid PCMAudio_UpdateStatus();\r\n\r\n// Call every frame to make sure music and stream buffers are loaded and current status is checked each frame...\r\n// Returns true if there is a CD error, false otherwise...\r\nint PCMAudio_Update( void );\r\n\r\n// Load a track and start it playing...\r\n// You wanna loop a track?  Wait until this track is done, and PLAY IT AGAIN SAM!\r\nbool PCMAudio_PlayMusicTrack( const char *filename );\r\nbool PCMAudio_PlayMusicStream( uint32 checksum );\r\nbool PCMAudio_PlayStream( uint32 checksum, int whichStream, float volumeL, float volumeR, float pitch );\r\n\r\n// keep song loaded, stop playing it (or continue playing paused song)\r\nvoid PCMAudio_Pause( bool pause = true, int ch = MUSIC_CHANNEL );\r\n\r\nvoid PCMAudio_PauseStream( bool pause, int whichStream );\r\n\r\nvoid PCMAudio_StopMusic( bool waitPlease );\r\nvoid PCMAudio_StopStream( int whichStream, bool waitPlease = true );\r\nvoid PCMAudio_StopStreams( void );\r\n\r\n// Preload streams.  By preloading, you can guarantee they will start at a certain time.\r\nbool PCMAudio_PreLoadStream( uint32 checksum, int whichStream );\r\nbool PCMAudio_PreLoadStreamDone( int whichStream );\r\nbool PCMAudio_StartPreLoadedStream( int whichStream, float volumeL, float volumeR, float pitch );\r\n\r\n// Preload Music Streams.  By preloading, you can guarantee they will start at a certain time.\r\nbool PCMAudio_PreLoadMusicStream( uint32 checksum );\r\nbool PCMAudio_PreLoadMusicStreamDone( void );\r\nbool PCMAudio_StartPreLoadedMusicStream( void );\r\n\r\n// set the music volume ( 0 to 100 )\r\nbool\tPCMAudio_SetMusicVolume( float volume );\r\nbool\tPCMAudio_SetStreamVolume( float volumeL, float volumeR, int whichStream );\r\nbool\tPCMAudio_SetStreamPitch( float pitch, int whichStream );\r\n//int PCMAudio_SetStreamVolumeAndPitch( float volumeL, float volumeR, float pitch, int whichStream );\r\n\r\nvoid PCMAudio_SetStreamGlobalVolume( unsigned int volume );\r\n\r\nenum{\r\n\tPCM_STATUS_FREE \t\t\t= ( 1 << 0 ),\r\n\tPCM_STATUS_PLAYING\t\t\t= ( 1 << 1 ),\r\n\tPCM_STATUS_LOADING \t\t\t= ( 1 << 2 ),\r\n\tPCM_STATUS_END \t\t\t\t= ( 1 << 3 ),\t\t// Done playing on IOP, but not completely cleaned up on the IOP\r\n\tPCM_STATUS_STOPPED \t\t\t= ( 1 << 4 ),\r\n};\r\n\r\n// Return one of the PCM_STATUS values from above...\r\nint PCMAudio_GetMusicStatus( );\r\nint PCMAudio_GetStreamStatus( int whichStream );\r\n\r\n// preload any CD location info (to avoid a hitch in framerate on PS2):\r\nunsigned int PCMAudio_GetCDLocation( const char *pTrackName );\r\n\r\nbool PCMAudio_TrackExists( const char *pTrackName, int ch );\r\nbool PCMAudio_LoadMusicHeader( const char *nameOfFile );\r\nbool PCMAudio_LoadStreamHeader( const char *nameOfFile );\r\n\r\nuint32 PCMAudio_FindNameFromChecksum( uint32 checksum, int ch );\r\n\r\n// borrow this memory for the movies and shit...\r\nint PCMAudio_GetIopMemory( void );\r\n\t\t \r\n//////////////////////////////////////////////////////////////////////////////\r\n// Inlines\r\n//\r\n\r\ninline bool\t\tCFileStreamInfo::IsMusicStream() const\r\n{\r\n\treturn m_streamType == FILE_STREAM_MUSIC;\r\n}\r\n\r\ninline int\t\tCFileStreamInfo::GetAudioStreamIndex() const\r\n{\r\n\treturn (int) (m_streamType - FILE_STREAM_STREAM0);\r\n}\r\n\r\n} // namespace PCM\r\n\r\n#endif // __P_MUSIC_H__\r\n"
  },
  {
    "path": "Code/Gel/Music/Xbox/p_adpcmfilestream.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_adpcmfilestream.cpp\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/27/03\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXbox specific .pcm streaming code\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n#include <core/macros.h>\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <core/crc.h>\r\n\r\n#include <sys/config/config.h>\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n#include \"p_music.h\"\r\n#include \"p_adpcmfilestream.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Pcm\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Define the maximum amount of packets we will ever submit to the ADPCM renderer\r\n#define ADPCMSTRM_PACKET_COUNT\t\t\t\t\t8\r\n\r\n// Define the ADPCM renderer packet size. See the comment block above for an explanation.\r\n// This value is hard-coded assuming an ADPCM frame of 36 samples and 16 bit stereo (128 frames per packet)\r\n#define ADPCMSTRM_16BIT_MONO_PACKET_BYTES\t\t( 1 * 2 * 36 * 128 ) \r\n#define ADPCMSTRM_16BIT_STEREO_PACKET_BYTES\t\t( 2 * 2 * 36 * 128 ) \r\n\r\n// Read size is 16k (most efficient size for DVD reads).\r\n#define BYTES_PER_READ\t\t\t\t16384\r\n\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: CADPCMFileStream()\r\n// Desc: Object constructor.\r\n//-----------------------------------------------------------------------------\r\nCADPCMFileStream::CADPCMFileStream( bool use_3d )\r\n{\r\n    m_pSourceFilter\t\t= NULL;\r\n    m_pRenderFilter\t\t= NULL;\r\n    m_pvSourceBuffer\t= NULL;\r\n    m_pFileBuffer\t\t= NULL;\r\n\tm_hFile\t\t\t\t= INVALID_HANDLE_VALUE;\r\n\tm_hThread\t\t\t= NULL;\r\n\tm_bUse3D\t\t\t= use_3d;\r\n\tm_bOkayToPlay\t\t= true;\r\n\r\n    for( DWORD i = 0; i < ADPCMSTRM_PACKET_COUNT; i++ )\r\n\t{\r\n        m_adwPacketStatus[i] = XMEDIAPACKET_STATUS_SUCCESS;\r\n\t}\r\n\r\n    m_dwStartingDataOffset\t= 0;\r\n\tm_Completed\t\t\t\t= false;\r\n\tm_Paused\t\t\t\t= false;\r\n\r\n\t// Grab a pointer to the next overlapped structure.\r\n\tm_pOverlapped\t\t\t= PCMAudio_GetNextOverlapped();\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ~CADPCMFileStream()\r\n// Desc: Object destructor.\r\n//-----------------------------------------------------------------------------\r\nCADPCMFileStream::~CADPCMFileStream()\r\n{\r\n\tif( m_hThread )\r\n\t{\r\n\t\tCloseHandle( m_hThread );\r\n\t}\r\n\t\r\n\t// If the file i/o is still active, we need to remove the event and close the file.\r\n\tif(( m_hFile != INVALID_HANDLE_VALUE ) && !m_bUseWAD )\r\n\t{\r\n\t\tCloseHandle( m_hFile );\r\n\t}\r\n\r\n    if( m_pSourceFilter )\r\n\t{\r\n\t\tm_pSourceFilter->Release();\r\n\t}\r\n\r\n    if( m_pRenderFilter )\r\n\t{\r\n\t\tm_pRenderFilter->Release();\r\n\t}\r\n\r\n\tif( m_pvSourceBuffer )\r\n\t{\r\n\t\tdelete[] m_pvSourceBuffer;\r\n\t}\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: AsyncRead()\r\n// Desc: Called while the async read is in progress. If the read is still\r\n//       underway, simply returns. If the read has completed, sets up the\r\n//       next read. If the file has been completely read, closes the file.\r\n//-----------------------------------------------------------------------------\r\nvoid CADPCMFileStream::AsyncRead( void )\r\n{\r\n\tDbg_Assert( m_hFile != INVALID_HANDLE_VALUE );\r\n\r\n    // If paused, do nothing.\r\n\tif( m_Paused )\r\n\t{\r\n        return;\r\n    }\r\n\r\n    // See if the previous read is complete.\r\n\tDWORD\tdwBytesTransferred;\r\n\tBOOL\tbIsReadDone = GetOverlappedResult( m_hFile, m_pOverlapped, &dwBytesTransferred, FALSE );\r\n\tDWORD\tdwLastError = GetLastError();\r\n\r\n    // If the read isn't complete, keep going.\r\n\tif( !bIsReadDone )\r\n\t{\r\n\t\tDbg_Assert( dwLastError == ERROR_IO_INCOMPLETE );\r\n\t\tif( dwLastError != ERROR_IO_INCOMPLETE )\r\n\t\t{\r\n\t\t\tm_AwaitingDeletion = true;\r\n\t\t}\r\n\t\treturn;\r\n    }\r\n\r\n\t// If we get here, the read is complete.\r\n    m_pOverlapped->Offset\t+= dwBytesTransferred;\r\n\tm_FileBytesRead\t\t\t+= dwBytesTransferred;\r\n\r\n\t++m_SuccessiveReads;\r\n\r\n\tif( dwBytesTransferred < BYTES_PER_READ )\r\n\t{ \r\n\t\t// We've reached the end of the file during the call to ReadFile.\r\n\r\n        // Close the file (if not using the global WAD file).\r\n\t\tif( !m_bUseWAD )\r\n\t\t{\r\n\t\t\tBOOL bSuccess = CloseHandle( m_hFile );\r\n\t        Dbg_Assert( bSuccess );\r\n\t\t}\r\n\r\n        m_hFile = INVALID_HANDLE_VALUE;\r\n\r\n        // All done\r\n\t\tm_ReadComplete = true;\r\n    }\r\n    else\r\n    {\r\n\t\tif( m_bUseWAD && ( m_FileBytesRead >= (int)m_dwWADLength ))\r\n\t\t{\r\n\t\t\tm_hFile = INVALID_HANDLE_VALUE;\r\n\r\n\t\t\t// All done\r\n\t\t\tm_ReadComplete = true;\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\t// We still have more data to read. Start another asynchronous read from the file.\r\n\t\tBOOL bComplete\t= ReadFile( m_hFile, (BYTE*)m_pFileBuffer + ( m_FileBytesRead % PCMAudio_GetFilestreamBufferSize()), BYTES_PER_READ, NULL, m_pOverlapped );\r\n\t\tdwLastError\t\t= GetLastError();\r\n\r\n\t\t// Deal with hitting EOF (for files that are some exact multiple of BYTES_PER_READ bytes).\r\n\t\tif( bComplete || ( !bComplete && ( dwLastError == ERROR_HANDLE_EOF )))\r\n\t\t{\r\n\t\t\t// Close the file\r\n\t\t\tif( !m_bUseWAD )\r\n\t\t\t{\r\n\t\t\t\tBOOL bSuccess = CloseHandle( m_hFile );\r\n\t\t\t\tDbg_Assert( bSuccess );\r\n\t\t\t}\r\n\t\t\tm_hFile = INVALID_HANDLE_VALUE;\r\n\r\n\t\t\t// All done\r\n\t\t\tm_ReadComplete = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( bComplete || ( !bComplete && ( dwLastError == ERROR_IO_PENDING )), ( \"ReadFile error: %x\\n\", dwLastError ));\r\n\t\t\tif( !bComplete && ( dwLastError != ERROR_IO_PENDING ))\r\n\t\t\t{\r\n\t\t\t\t// There was a problem, so shut this stream down.\r\n\t\t\t\tm_AwaitingDeletion = true;\r\n\t\t\t}\r\n\t\t}\r\n    }\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Initialize()\r\n// Desc: Initializes the wave file streaming subsystem.\r\n//-----------------------------------------------------------------------------\r\nHRESULT CADPCMFileStream::Initialize( HANDLE h_file, unsigned int offset, unsigned int length, void* fileBuffer )\r\n{\r\n    m_dwPercentCompleted = 0;\r\n    \r\n\t// At this stage we don't want to create the decoder or the stream. We do want to just allocate the read\r\n\t// buffer, and start pulling in the data. Once sufficient data has been grabbed, we can analyze the header\r\n\t// and create the required objects for playback.\r\n\tm_hFile\t\t\t= h_file;\r\n\tm_bUseWAD\t\t= true;\r\n\tm_dwWADOffset\t= offset;\t\r\n\tm_dwWADLength\t= length;\r\n\tm_pFileBuffer = fileBuffer;\r\n\r\n\tDbg_Assert( DWORD( m_pFileBuffer ) % sizeof( DWORD ) == 0 );\r\n\r\n\treturn PostInitialize();\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: PostInitialize()\r\n// Desc: Initialisation stuff following the file creation\r\n//-----------------------------------------------------------------------------\r\nHRESULT CADPCMFileStream::PostInitialize( void )\r\n{\r\n\t// Start the asynchronous read from the start of the file.\r\n\tm_FirstRead\t\t\t\t= true;\r\n\tm_ReadComplete\t\t\t= false;\r\n\tm_FileBytesRead\t\t\t= 0;\r\n\tm_FileBytesProcessed\t= 0;\r\n\tm_SuccessiveReads\t\t= 0;\r\n\r\n\tif( m_bUseWAD )\r\n\t{\r\n\t\tm_pOverlapped->Offset\t= m_dwWADOffset;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_pOverlapped->Offset\t= 0;\r\n\t}\r\n\tm_pOverlapped->OffsetHigh\t= 0;\r\n\r\n\tBOOL bComplete = ReadFile( m_hFile, m_pFileBuffer, BYTES_PER_READ, NULL, m_pOverlapped );\r\n\tif( !bComplete )\r\n\t{\r\n\t\tDWORD dwLastError = GetLastError();\r\n\t\tDbg_Assert( dwLastError == ERROR_IO_PENDING );\r\n\t\tif( dwLastError != ERROR_IO_PENDING )\r\n\t\t{\r\n\t\t\treturn HRESULT_FROM_WIN32( dwLastError );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_ReadComplete = true;\r\n\t}\r\n\r\n\t// That's it for now.\r\n    return S_OK;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: InitializeFormatBlock()\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nHRESULT CADPCMFileStream::InitializeFormatBlock( uint32 *p_header_data )\r\n{\r\n\t// Ensure the format block is where we expect it to be.\r\n\tif( p_header_data[3] == 0x20746D66UL )\r\n\t{\r\n\t\t// Read format and number of channels.\r\n\t\tm_wfxExtendedSourceFormat.m_wfxSourceFormat.wFormatTag\t\t= (uint16)( p_header_data[5] & 0xFFFFUL );\r\n\t\tm_wfxExtendedSourceFormat.m_wfxSourceFormat.nChannels\t\t= (uint16)( p_header_data[5] >> 16 );\r\n\r\n\t\t// Make sure this is Xbox ADPCM.\r\n\t\tif( m_wfxExtendedSourceFormat.m_wfxSourceFormat.wFormatTag != WAVE_FORMAT_XBOX_ADPCM )\r\n\t\t{\r\n\t\t\treturn E_FAIL;\r\n\t\t}\r\n\r\n\t\t// Read samples per second.\r\n\t\tm_wfxExtendedSourceFormat.m_wfxSourceFormat.nSamplesPerSec\t= p_header_data[6];\r\n\r\n\t\t// Read average bytes per second.\r\n\t\tm_wfxExtendedSourceFormat.m_wfxSourceFormat.nAvgBytesPerSec\t= p_header_data[7];\r\n\r\n\t\t// Read block alignment and bits per sample.\r\n\t\tm_wfxExtendedSourceFormat.m_wfxSourceFormat.nBlockAlign\t\t= (uint16)( p_header_data[8] & 0xFFFFUL );\r\n\t\tm_wfxExtendedSourceFormat.m_wfxSourceFormat.wBitsPerSample\t= (uint16)( p_header_data[8] >> 16 );\r\n\r\n\t\t// Extra information.\r\n\t\tm_wfxExtendedSourceFormat.m_wfxSourceFormat.cbSize\t\t\t= (uint16)( p_header_data[9] & 0xFFFFUL );\r\n\t\tm_wfxExtendedSourceFormat.m_extendedInfo\t\t\t\t\t= (uint16)( p_header_data[9] >> 16 );\r\n\r\n\t\t// We have now processed the first 48 bytes of data.\r\n\t\tm_FileBytesProcessed = 48;\r\n\r\n\t\t// Now that we know the format, we can set the packet size.\r\n\t\tif( m_wfxExtendedSourceFormat.m_wfxSourceFormat.nChannels == 1 )\r\n\t\t\tm_PacketBytes = ADPCMSTRM_16BIT_MONO_PACKET_BYTES;\r\n\t\telse\r\n\t\t\tm_PacketBytes = ADPCMSTRM_16BIT_STEREO_PACKET_BYTES;\r\n\r\n\t\treturn S_OK;\r\n\t}\r\n\treturn E_FAIL;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: CreateSourceBuffer()\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nbool CADPCMFileStream::CreateSourceBuffer( void )\r\n{\r\n\t// Allocate data buffers. The source buffer holds the CPU decompressed packets ready to submit to the stream.\r\n\t// The size of the buffer will depend on the format of the stream - stereo requires double the packet size of mono.\r\n\t// Explicitly allocate from the bottom up heap.\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().BottomUpHeap());\r\n\tm_pvSourceBuffer = new BYTE[m_PacketBytes * ADPCMSTRM_PACKET_COUNT];\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn ( m_pvSourceBuffer != NULL );\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: PreLoadDone()\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nbool CADPCMFileStream::PreLoadDone( void )\r\n{\r\n\tif( m_DecoderCreation == 1 )\r\n\t{\r\n\t\tif( m_ReadComplete || ( m_FileBytesRead >= ( m_FileBytesProcessed + m_PacketBytes )))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Process()\r\n// Desc: Performs any work necessary to keep the stream playing.\r\n//-----------------------------------------------------------------------------\r\nHRESULT CADPCMFileStream::Process( void )\r\n{\r\n    HRESULT\t\t\thr;\r\n\tDSSTREAMDESC\tdssd;\r\n    DWORD\t\t\tdwPacketIndex;\r\n    \r\n\t// Do nothing if waiting to die.\r\n\tif( m_AwaitingDeletion )\r\n\t{\r\n\t\treturn S_OK;\r\n\t}\r\n\r\n\t// Do we need to kick off another read of data?\r\n\t// Don't read anymore if we have read ahead to the point where we are within 32k of free read buffer space.\r\n\tif( !m_ReadComplete )\r\n\t{\r\n\t\tif( m_FileBytesRead <= ( m_FileBytesProcessed + ((int)PCMAudio_GetFilestreamBufferSize() - 32768 )))\r\n\t\t{\r\n\t\t\tAsyncRead();\r\n\t\t}\r\n\t}\r\n\r\n\t// Has the first block of raw data been read? If so we need to instantiate the playback objects and data buffers.\r\n\tif( m_FirstRead && ( m_FileBytesRead > 1024 ))\r\n\t{\r\n\t\tif( m_pSourceFilter == NULL )\r\n\t\t{\r\n\t\t\t// Create the thread which will create the in-memory decoder. \r\n\t\t\tm_DecoderCreation = 0;\r\n\r\n\t\t\t// For WMA format, here is where we create the decoder. However, since there is no CPU-side decompression required\r\n\t\t\t// for ADPCM format, there is no requirement for a decoder.\r\n\t\t\tm_DecoderCreation\t= 1;\r\n\t\t}\r\n\r\n\t\tif( m_DecoderCreation == 0 )\r\n\t\t{\r\n\t\t\t// Still waiting to create decoder.\r\n\t\t\treturn S_OK;\r\n\t\t}\r\n\t\telse if( m_DecoderCreation == 2 )\r\n\t\t{\r\n\t\t\t// Failed to create decoder, just mark for deletion.\r\n\t\t\tm_AwaitingDeletion = true;\r\n\t\t\treturn S_OK;\r\n\t\t}\r\n\t\telse if( m_DecoderCreation == 1 )\r\n\t\t{\r\n\t\t\t// Managed to create decoder.\r\n\t\t\tm_FirstRead = false;\r\n\r\n\t\t\t// Set up the format information.\r\n\t\t\tif( InitializeFormatBlock((uint32*)m_pFileBuffer ) == E_FAIL )\r\n\t\t\t{\r\n\t\t\t\t// Failed to decode format information, just mark for deletion.\r\n\t\t\t\tm_AwaitingDeletion = true;\r\n\t\t\t\treturn S_OK;\r\n\t\t\t}\r\n\r\n\t\t\t// Create the render (DirectSoundStream) filter.\r\n\t\t\tDSMIXBINS\t\t\tdsmixbins;\r\n\t\t\tDSMIXBINVOLUMEPAIR\tdsmbvp[DSMIXBIN_ASSIGNMENT_MAX];\r\n\t\t\tZeroMemory( &dssd, sizeof( dssd ));\r\n\r\n\t\t\tdssd.dwFlags\t\t\t\t\t= 0;\r\n\t\t\tdssd.dwMaxAttachedPackets\t\t= ADPCMSTRM_PACKET_COUNT;\r\n\t\t\tdssd.lpwfxFormat\t\t\t\t= &m_wfxExtendedSourceFormat.m_wfxSourceFormat;\r\n\t\t\tdssd.lpMixBins\t\t\t\t\t= &dsmixbins;\r\n\r\n\t\t\tif( m_bUse3D )\r\n\t\t\t{\r\n\t\t\t\t// This is only designed to be fed a mono signal.\r\n\t\t\t\tDbg_Assert( m_wfxExtendedSourceFormat.m_wfxSourceFormat.nChannels == 1 );\r\n\r\n\t\t\t\tdsmixbins.dwMixBinCount\t\t\t= 6;\r\n\t\t\t\tdsmixbins.lpMixBinVolumePairs\t= dsmbvp;\r\n\t\t\t\tdsmbvp[0].dwMixBin\t\t\t\t= DSMIXBIN_3D_FRONT_LEFT;\r\n\t\t\t\tdsmbvp[0].lVolume\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\tdsmbvp[1].dwMixBin\t\t\t\t= DSMIXBIN_3D_FRONT_RIGHT;\r\n\t\t\t\tdsmbvp[1].lVolume\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\tdsmbvp[2].dwMixBin\t\t\t\t= DSMIXBIN_3D_BACK_LEFT;\r\n\t\t\t\tdsmbvp[2].lVolume\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\tdsmbvp[3].dwMixBin\t\t\t\t= DSMIXBIN_3D_BACK_RIGHT;\r\n\t\t\t\tdsmbvp[3].lVolume\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\tdsmbvp[4].dwMixBin\t\t\t\t= DSMIXBIN_FRONT_CENTER;\r\n\t\t\t\tdsmbvp[4].lVolume\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\tdsmbvp[5].dwMixBin\t\t\t\t= DSMIXBIN_I3DL2;\r\n\t\t\t\tdsmbvp[5].lVolume\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\r\n\t\t\t\tm_Mixbins\t\t\t\t\t\t= ( 1 << DSMIXBIN_3D_FRONT_LEFT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_3D_FRONT_RIGHT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_3D_BACK_LEFT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_3D_BACK_RIGHT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_FRONT_CENTER ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_I3DL2 );\r\n\t\t\t\tm_NumMixbins\t\t\t\t\t= dsmixbins.dwMixBinCount;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// If we are playing a music track, and if proper 5.1 output is selected, we want to feed the music to the left and\r\n\t\t\t\t// right back speakers with a slight echo via mixbins 5 and 6.\r\n\t\t\t\t// This is currently disabled.\r\n\t\t\t\tif( false && ( XGetAudioFlags() & XC_AUDIO_FLAGS_ENABLE_AC3 ))\r\n\t\t\t\t{\r\n\t\t\t\t\t// This is only designed to be fed a stereo signal.\r\n\t\t\t\t\tDbg_Assert( m_wfxExtendedSourceFormat.m_wfxSourceFormat.nChannels == 2 );\r\n\r\n\t\t\t\t\tdsmixbins.dwMixBinCount\t\t\t= 4;\r\n\t\t\t\t\tdsmixbins.lpMixBinVolumePairs\t= dsmbvp;\r\n\t\t\t\t\tdsmbvp[0].dwMixBin\t\t\t\t= DSMIXBIN_FRONT_LEFT;\r\n\t\t\t\t\tdsmbvp[0].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\t\t\t\t\tdsmbvp[1].dwMixBin\t\t\t\t= DSMIXBIN_FRONT_RIGHT;\r\n\t\t\t\t\tdsmbvp[1].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\t\t\t\t\tdsmbvp[2].dwMixBin\t\t\t\t= DSMIXBIN_FXSEND_5;\r\n\t\t\t\t\tdsmbvp[2].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\t\t\t\t\tdsmbvp[3].dwMixBin\t\t\t\t= DSMIXBIN_FXSEND_6;\r\n\t\t\t\t\tdsmbvp[3].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\r\n\t\t\t\t\tm_Mixbins\t\t\t\t\t\t= ( 1 << DSMIXBIN_FRONT_LEFT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_FRONT_RIGHT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_FXSEND_5 ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_FXSEND_6 );\r\n\t\t\t\t\tm_NumMixbins\t\t\t\t\t= dsmixbins.dwMixBinCount;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// This is only designed to be fed a stereo signal.\r\n\t\t\t\t\tDbg_Assert( m_wfxExtendedSourceFormat.m_wfxSourceFormat.nChannels == 2 );\r\n\r\n\t\t\t\t\tdsmixbins.dwMixBinCount\t\t\t= 4;\r\n\t\t\t\t\tdsmixbins.lpMixBinVolumePairs\t= dsmbvp;\r\n\t\t\t\t\tdsmbvp[0].dwMixBin\t\t\t\t= DSMIXBIN_FRONT_LEFT;\r\n\t\t\t\t\tdsmbvp[0].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\t\t\t\t\tdsmbvp[1].dwMixBin\t\t\t\t= DSMIXBIN_FRONT_RIGHT;\r\n\t\t\t\t\tdsmbvp[1].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\t\t\t\t\tdsmbvp[2].dwMixBin\t\t\t\t= DSMIXBIN_BACK_LEFT;\r\n\t\t\t\t\tdsmbvp[2].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\t\t\t\t\tdsmbvp[3].dwMixBin\t\t\t\t= DSMIXBIN_BACK_RIGHT;\r\n\t\t\t\t\tdsmbvp[3].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\r\n\t\t\t\t\tm_Mixbins\t\t\t\t\t\t= ( 1 << DSMIXBIN_FRONT_LEFT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_FRONT_RIGHT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_BACK_LEFT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_BACK_RIGHT );\r\n\t\t\t\t\tm_NumMixbins\t\t\t\t\t= dsmixbins.dwMixBinCount;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\thr = DirectSoundCreateStream( &dssd, &m_pRenderFilter );\r\n\t\t\tif( FAILED( hr ))\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\tm_pRenderFilter\t\t= NULL;\r\n\t\t\t\tm_AwaitingDeletion\t= true;\r\n\t\t\t\treturn S_OK;\r\n\t\t\t}\r\n\r\n\t\t\t// Set deferred volume if present.\r\n\t\t\tSetDeferredVolume();\r\n\r\n\t\t\t// Handle deferred pause.\r\n\t\t\tif( m_Paused )\r\n\t\t\t{\r\n\t\t\t\tm_pRenderFilter->Pause( 1 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// We only want to do processing when there is sufficient data available.\r\n\tif( m_ReadComplete || ( m_FileBytesRead >= ( m_FileBytesProcessed + m_PacketBytes )))\r\n\t{\r\n\t\tif( !m_Completed && m_pRenderFilter )\r\n\t\t{\r\n\t\t\t// Find a free packet. If there's none free, we don't have anything to do.\r\n\t\t\tif( FindFreePacket( &dwPacketIndex ))\r\n\t\t\t{\r\n\t\t\t\t// Read from the source filter.\r\n\t\t\t\tif( m_bOkayToPlay )\r\n\t\t\t\t{\r\n\t\t\t\t\thr = ProcessSource( dwPacketIndex );\r\n\t\t\t\t\tif( FAILED( hr ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn hr;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif( !m_Paused )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Send the data to the renderer\r\n\t\t\t\t\t\thr = ProcessRenderer( dwPacketIndex );\r\n\t\t\t\t\t\tif( FAILED( hr ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t return hr;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n    return S_OK;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: FindFreePacket()\r\n// Desc: Finds a render packet available for processing.\r\n//-----------------------------------------------------------------------------\r\nBOOL CADPCMFileStream::FindFreePacket( DWORD* pdwPacketIndex )\r\n{\r\n    for( DWORD dwPacketIndex = 0; dwPacketIndex < ADPCMSTRM_PACKET_COUNT; ++dwPacketIndex )\r\n    {\r\n        if( XMEDIAPACKET_STATUS_PENDING != m_adwPacketStatus[dwPacketIndex] )\r\n        {\r\n            if( pdwPacketIndex )\r\n\t\t\t{\r\n                (*pdwPacketIndex) = dwPacketIndex;\r\n\t\t\t}\r\n            return TRUE;\r\n        }\r\n    }\r\n    return FALSE;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ProcessSource()\r\n// Desc: Reads data from the source filter.\r\n//-----------------------------------------------------------------------------\r\nHRESULT CADPCMFileStream::ProcessSource( DWORD dwPacketIndex )\r\n{\r\n\tif( m_pvSourceBuffer == NULL )\r\n\t{\r\n\t\tif( CreateSourceBuffer() == false )\r\n\t\t{\r\n\t\t\t// Failed to create the source buffer, mark for deletion.\r\n\t\t\tm_AwaitingDeletion = true;\r\n\t\t\treturn E_FAIL;\r\n\t\t}\r\n\t}\r\n    \r\n\t// We just want to copy a full packet's worth of data from the file buffer directly into the source buffer...\r\n\tuint8*\tp_destination\t\t= (BYTE*)m_pvSourceBuffer + ( dwPacketIndex * m_PacketBytes );\r\n\r\n\t// However we don't want to overrun the file buffer when copying.\r\n\tuint32\tfile_buffer_offset\t= m_FileBytesProcessed % PCMAudio_GetFilestreamBufferSize();\r\n\tif(( PCMAudio_GetFilestreamBufferSize() - file_buffer_offset ) < (uint32)m_PacketBytes )\r\n\t{\r\n\t\t// Copying the data in one chunk will take us beyond the edge of the file buffer.\r\n\t\t// So we need to do the copy in two chunks.\r\n\t\tuint8*\tp_source\t\t\t= (BYTE*)m_pFileBuffer + file_buffer_offset;\r\n\t\tuint32\tfirst_chunk_bytes\t= PCMAudio_GetFilestreamBufferSize() - file_buffer_offset;\r\n\t\tCopyMemory( p_destination, p_source, first_chunk_bytes );\r\n\r\n\t\t// Wrap file buffer back round to start.\r\n\t\tp_source\t\t\t\t\t= (BYTE*)m_pFileBuffer + 0;\r\n\t\tp_destination\t\t\t\t= p_destination + first_chunk_bytes;\r\n\t\tCopyMemory( p_destination, p_source, m_PacketBytes - first_chunk_bytes );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Copying the data in one chunk is fine.\r\n\t\tuint8* p_source = (BYTE*)m_pFileBuffer + file_buffer_offset;\r\n\t\tCopyMemory( p_destination, p_source, m_PacketBytes );\r\n\t}\r\n\r\n\t// Now these bytes have been processed.\r\n\tm_FileBytesProcessed += m_PacketBytes;\r\n\r\n\t// If we've caught up with the number of bytes read, it's because we've finished processing.\r\n    if( m_FileBytesProcessed >= m_FileBytesRead )\r\n\t{\r\n\t\t// Set completion flag.\r\n\t\tm_Completed = true;\r\n\r\n\t\t// Zero remaining part of packet.\r\n\t\tuint32 bytes_to_zero = m_FileBytesProcessed - m_FileBytesRead;\r\n\t\tif( bytes_to_zero > 0 )\r\n\t\t{\r\n\t\t\tp_destination = (BYTE*)m_pvSourceBuffer + ( dwPacketIndex * m_PacketBytes ) + m_PacketBytes - bytes_to_zero;\r\n\t\t\tZeroMemory( p_destination, bytes_to_zero );\r\n\t\t}\r\n\t}\r\n    return S_OK;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ProcessRenderer()\r\n// Desc: Sends data to the renderer.\r\n//-----------------------------------------------------------------------------\r\nHRESULT CADPCMFileStream::ProcessRenderer( DWORD dwPacketIndex )\r\n{\r\n    XMEDIAPACKET xmp;\r\n    HRESULT      hr;\r\n\r\n\tDbg_Assert( m_pvSourceBuffer != NULL );\r\n\r\n\t// There's a full packet's worth of data ready for us to send to the renderer.  We want to track the status\r\n\t// of this packet since the render filter is asychronous and we need to know when the packet is completed.\r\n    ZeroMemory( &xmp, sizeof( xmp ));\r\n    xmp.pvBuffer  = (BYTE*)m_pvSourceBuffer + ( dwPacketIndex * m_PacketBytes );\r\n    xmp.dwMaxSize = m_PacketBytes;\r\n    xmp.pdwStatus = &m_adwPacketStatus[dwPacketIndex];\r\n\r\n\tif( m_Completed )\r\n\t{\r\n\t\t// Store index of last packet, since we will need to test the status of this for proper completion test.\r\n\t\tm_LastPacket = dwPacketIndex;\r\n\t}\r\n\r\n    hr = m_pRenderFilter->Process( &xmp, NULL );\r\n\r\n\tif( m_Completed )\r\n\t{\r\n\t\t// Tell the renderer not to expect any more data.\r\n\t\tm_pRenderFilter->Discontinuity();\r\n\t}\r\n\t\r\n\tif( FAILED( hr ))\r\n\t{\r\n\t\treturn hr;\r\n\t}\r\n\t\r\n\treturn S_OK;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Pause\r\n// Desc: Pauses and resumes stream playback\r\n//-----------------------------------------------------------------------------\r\nvoid CADPCMFileStream::Pause( DWORD dwPause )\r\n{\r\n\tm_Paused = ( dwPause > 0 );\r\n\r\n\t// Possible that the render filter hasn't been created yet.\r\n\tif( m_pRenderFilter )\r\n\t{\r\n\t\tm_pRenderFilter->Pause(( dwPause > 0 ) ? DSSTREAMPAUSE_PAUSE : DSSTREAMPAUSE_RESUME );\r\n\t}\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: SetVolume\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nvoid CADPCMFileStream::SetVolume( float volume )\r\n{\r\n\tif( m_pRenderFilter )\r\n\t{\r\n\t\tint i_volume\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\tint i_volume_rear\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\tif( volume > 0.0f )\r\n\t\t{\r\n\t\t\t// Figure base volume.\r\n\t\t\tfloat attenuation\t= 20.0f * log10f( volume * 0.01f );\r\n\t\t\ti_volume\t\t\t= DSBVOLUME_MAX + (int)( attenuation * 100.0f );\r\n\t\t\tif( i_volume < DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t\t\ti_volume = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\telse if( i_volume > DSBVOLUME_MAX )\r\n\t\t\t\ti_volume = DSBVOLUME_MAX;\r\n\r\n\t\t\t// Also figure half volume, in case we are routing to the back speakers.\r\n\t\t\tattenuation\t\t\t= 20.0f * log10f( volume * 0.5f * 0.01f );\r\n\t\t\ti_volume_rear\t\t= DSBVOLUME_MAX + (int)( attenuation * 100.0f );\r\n\t\t\tif( i_volume_rear < DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t\t\ti_volume_rear = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\telse if( i_volume_rear > DSBVOLUME_MAX )\r\n\t\t\t\ti_volume_rear = DSBVOLUME_MAX;\r\n\t\t}\r\n\t\t\r\n\t\t// Set individual mixbins for panning.\r\n\t\tDSMIXBINS\t\t\tdsmixbins;\r\n\t\tDSMIXBINVOLUMEPAIR\tdsmbvp[DSMIXBIN_ASSIGNMENT_MAX];\r\n\r\n\t\tdsmixbins.dwMixBinCount\t\t\t= 0;\r\n\t\tdsmixbins.lpMixBinVolumePairs\t= dsmbvp;\r\n\r\n\t\tif( i_volume > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n\t\t\t// Set the volume up depending on how the initial mixbins were set up.\r\n\t\t\tint mbbf = 0;\r\n\t\t\tfor( uint32 mb = 0; mb < m_NumMixbins; ++mb )\r\n\t\t\t{\r\n\t\t\t\twhile(( m_Mixbins & ( 1 << mbbf )) == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t++mbbf;\r\n\t\t\t\t\tDbg_Assert( mbbf < 32 );\r\n\t\t\t\t}\r\n\t\t\t\tdsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= mbbf;\r\n\r\n\t\t\t\t// For rear speakers (or mixbins that route to the rear), use half volume.\r\n\t\t\t\tif(( mbbf == DSMIXBIN_FXSEND_5 ) || ( mbbf == DSMIXBIN_FXSEND_6 ) || ( mbbf == DSMIXBIN_BACK_LEFT ) || ( mbbf == DSMIXBIN_BACK_RIGHT ))\r\n\t\t\t\t{\r\n\t\t\t\t\tdsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volume_rear;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tdsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volume;\r\n\t\t\t\t}\r\n\t\t\t\t++dsmixbins.dwMixBinCount;\r\n\t\t\t\t++mbbf;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Set all speaker volumes.\r\n\t\tm_pRenderFilter->SetMixBinVolumes( &dsmixbins );\r\n\r\n\t\t// Set overall buffer volume.\r\n\t\tif( dsmixbins.dwMixBinCount > 0 )\r\n\t\t{\r\n\t\t\tm_pRenderFilter->SetVolume( DSBVOLUME_MAX );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_pRenderFilter->SetVolume( DSBVOLUME_MIN );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_SetDeferredVolume = true;\r\n\t\tm_DeferredVolume[0]\t= volume;\r\n\t}\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: SetVolume\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nvoid CADPCMFileStream::SetVolume( float volL, float volR )\r\n{\r\n\tif( m_pRenderFilter )\r\n\t{\r\n\t\t// This array will hold individual volumes for the five speakers.\r\n\t\t// In order, they are: front left, center, front right, rear right, rear left.\r\n\t\tfloat\tvolumes[5];\r\n\t\tint\t\ti_volumes[5], max_i_volume;\r\n\t\tmemset( volumes, 0, sizeof( float ) * 5 );\r\n\t\t\r\n\t\tif(( volL == 0.0f ) && ( volR == 0.0f ))\r\n\t\t{\r\n\t\t\t// Pointless doing any more work.\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Get the length of the vector here which will be used to multiply out the normalised speaker volumes.\r\n\t\t\tMth::Vector test( fabsf( volL ), fabsf( volR ), 0.0f, 0.0f );\r\n\t\t\tfloat amplitude = test.Length();\r\n\r\n\t\t\t// Look just at the normalized right component to figure the sound angle from Matt's calculations.\r\n\t\t\ttest.Normalize();\r\n\r\n\t\t\tfloat angle;\r\n\t\t\tangle\t= asinf( test[Y] );\r\n\t\t\tangle\t= ( angle * 2.0f ) - ( Mth::PI * 0.5f );\r\n\t\t\tangle\t= ( volL < 0.0f ) ? ( Mth::PI - angle ) : angle;\r\n\t\t\r\n\t\t\t// Now figure volumes based on speaker coverage.\r\n\t\t\tangle\t= Mth::RadToDeg( angle );\r\n\t\t\r\n\t\t\tSpt::SingletonPtr< Sfx::CSfxManager > sfx_manager;\r\n\t\t\tsfx_manager->Get5ChannelMultipliers( angle, &volumes[0] );\r\n\r\n\t\t\t// Now readjust the relative values...\r\n\t\t\tfor( int v = 0; v < 5; ++v )\r\n\t\t\t{\r\n\t\t\t\t// Scale back up to original amplitude.\r\n\t\t\t\tvolumes[v] *= amplitude;\r\n\r\n\t\t\t\tif( volumes[v] > 100.0f )\r\n\t\t\t\t\tvolumes[v] = 100.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Now figure the attenuation of the sound. To convert to a decibel value, figure the ratio of requested\r\n\t\t// volume versus max volume, then calculate the log10 and multiply by (10 * 2). (The 2 is because sound\r\n\t\t// power varies as square of pressure, and squaring doubles the log value).\r\n\t\tmax_i_volume = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\tfor( int v = 0; v < 5; ++v )\r\n\t\t{\r\n\t\t\tif( volumes[v] > 0.0f )\r\n\t\t\t{\r\n\t\t\t\tfloat attenuation\t= 20.0f * log10f( volumes[v] * 0.01f );\r\n\t\t\t\ti_volumes[v]\t\t= DSBVOLUME_MAX + (int)( attenuation * 100.0f );\r\n\t\t\t\tif( i_volumes[v] < DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t\t\t\ti_volumes[v] = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\telse if( i_volumes[v] > DSBVOLUME_MAX )\r\n\t\t\t\t\ti_volumes[v] = DSBVOLUME_MAX;\r\n\r\n\t\t\t\tif( i_volumes[v] > max_i_volume )\r\n\t\t\t\t\tmax_i_volume = i_volumes[v];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ti_volumes[v] = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Set individual mixbins for panning.\r\n\t\tDSMIXBINS\t\t\tdsmixbins;\r\n\t\tDSMIXBINVOLUMEPAIR\tdsmbvp[DSMIXBIN_ASSIGNMENT_MAX];\r\n\r\n\t\tdsmixbins.dwMixBinCount\t\t\t= 0;\r\n\t\tdsmixbins.lpMixBinVolumePairs\t= dsmbvp;\r\n\r\n\t\tif( i_volumes[0] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_FRONT_LEFT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[0];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[1] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_FRONT_RIGHT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[1];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[2] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_BACK_LEFT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[2];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[3] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_BACK_RIGHT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[3];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[4] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_FRONT_CENTER;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[4];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( dsmixbins.dwMixBinCount > 0 )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_I3DL2;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= DSBVOLUME_MAX;\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\r\n\t\t// Set all speaker volumes.\r\n\t\tm_pRenderFilter->SetMixBinVolumes( &dsmixbins );\r\n\r\n\t\t// Set overall buffer volume.\r\n\t\tif( dsmixbins.dwMixBinCount > 0 )\r\n\t\t{\r\n\t\t\tm_pRenderFilter->SetVolume( DSBVOLUME_MAX );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_pRenderFilter->SetVolume( DSBVOLUME_MIN );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_SetDeferredVolumeLR\t= true;\r\n\t\tm_DeferredVolume[0]\t\t= volL;\r\n\t\tm_DeferredVolume[1]\t\t= volR;\r\n\t}\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: SetVolume\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nvoid CADPCMFileStream::SetVolume( float v0, float v1, float v2, float v3, float v4 )\r\n{\r\n\tif( m_pRenderFilter )\r\n\t{\r\n\t\tfloat volumes[5];\r\n\t\tvolumes[0] = ( v0 > 100.0f ) ? 100.0f : v0;\r\n\t\tvolumes[1] = ( v1 > 100.0f ) ? 100.0f : v1;\r\n\t\tvolumes[2] = ( v2 > 100.0f ) ? 100.0f : v2;\r\n\t\tvolumes[3] = ( v3 > 100.0f ) ? 100.0f : v3;\r\n\t\tvolumes[4] = ( v4 > 100.0f ) ? 100.0f : v4;\r\n\r\n\t\tint i_volumes[5], max_i_volume;\r\n\r\n\t\t// Now figure the attenuation of the sound. To convert to a decibel value, figure the ratio of requested\r\n\t\t// volume versus max volume, then calculate the log10 and multiply by (10 * 2). (The 2 is because sound\r\n\t\t// power varies as square of pressure, and squaring doubles the log value).\r\n\t\tmax_i_volume = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\tfor( int v = 0; v < 5; ++v )\r\n\t\t{\r\n\t\t\tif( volumes[v] > 0.0f )\r\n\t\t\t{\r\n\t\t\t\tfloat attenuation\t= 20.0f * log10f( volumes[v] * 0.01f );\r\n\t\t\t\ti_volumes[v]\t\t= DSBVOLUME_MAX + (int)( attenuation * 100.0f );\r\n\t\t\t\tif( i_volumes[v] < DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t\t\t\ti_volumes[v] = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\telse if( i_volumes[v] > DSBVOLUME_MAX )\r\n\t\t\t\t\ti_volumes[v] = DSBVOLUME_MAX;\r\n\r\n\t\t\t\tif( i_volumes[v] > max_i_volume )\r\n\t\t\t\t\tmax_i_volume = i_volumes[v];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ti_volumes[v] = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Set individual mixbins for panning.\r\n\t\tDSMIXBINS\t\t\tdsmixbins;\r\n\t\tDSMIXBINVOLUMEPAIR\tdsmbvp[DSMIXBIN_ASSIGNMENT_MAX];\r\n\r\n\t\tdsmixbins.dwMixBinCount\t\t\t= 0;\r\n\t\tdsmixbins.lpMixBinVolumePairs\t= dsmbvp;\r\n\r\n\t\tif( i_volumes[0] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_FRONT_LEFT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[0];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[1] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_FRONT_RIGHT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[1];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[2] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_BACK_LEFT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[2];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[3] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_BACK_RIGHT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[3];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[4] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_FRONT_CENTER;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[4];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( dsmixbins.dwMixBinCount > 0 )\r\n\t\t{\r\n\t\t\tdsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_I3DL2;\r\n\t\t\tdsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= DSBVOLUME_MAX;\r\n\t\t\tdsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\r\n\t\t// Set all speaker volumes.\r\n\t\tm_pRenderFilter->SetMixBinVolumes( &dsmixbins );\r\n\r\n\t\t// Set overall buffer volume.\r\n\t\tif( dsmixbins.dwMixBinCount > 0 )\r\n\t\t{\r\n\t\t\tm_pRenderFilter->SetVolume( DSBVOLUME_MAX );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_pRenderFilter->SetVolume( DSBVOLUME_MIN );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_SetDeferredVolume5Channel\t= true;\r\n\t\tm_DeferredVolume[0]\t\t\t= v0;\r\n\t\tm_DeferredVolume[1]\t\t\t= v1;\r\n\t\tm_DeferredVolume[2]\t\t\t= v2;\r\n\t\tm_DeferredVolume[3]\t\t\t= v3;\r\n\t\tm_DeferredVolume[4]\t\t\t= v4;\r\n\t}\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: SetDeferredVolume\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nvoid CADPCMFileStream::SetDeferredVolume( void )\r\n{\r\n\tif( m_SetDeferredVolume )\r\n\t{\r\n\t\tm_SetDeferredVolume = false;\r\n\t\tSetVolume( m_DeferredVolume[0] );\r\n\t}\r\n\r\n\tif( m_SetDeferredVolumeLR )\r\n\t{\r\n\t\tm_SetDeferredVolumeLR = false;\r\n\t\tSetVolume( m_DeferredVolume[0], m_DeferredVolume[1] );\r\n\t}\r\n\r\n\tif( m_SetDeferredVolume5Channel )\r\n\t{\r\n\t\tm_SetDeferredVolume5Channel = false;\r\n\t\tSetVolume( m_DeferredVolume[0], m_DeferredVolume[1], m_DeferredVolume[2], m_DeferredVolume[3], m_DeferredVolume[4] );\r\n\t}\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: IsSafeToDelete\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nbool CADPCMFileStream::IsSafeToDelete( void )\r\n{\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n} // namespace PCM\r\n"
  },
  {
    "path": "Code/Gel/Music/Xbox/p_adpcmfilestream.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGame Engine\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_adpcmfilesteam.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t01/27/2003\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __P_ADPCMFILESTREAM_H\r\n#define __P_ADPCMFILESTREAM_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Pcm\r\n{\r\n\r\n// Define the maximum amount of packets we will ever submit to the renderer.\r\n#define ADPCMSTRM_PACKET_COUNT\t\t8\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstruct sADPCMExtendedWaveFormatEx\r\n{\r\n\tWAVEFORMATEX\tm_wfxSourceFormat;\r\n\tuint16\t\t\tm_extendedInfo;\r\n};\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* ADPCM file streaming object, designed for fully asynchronous\t  */\r\n/* streaming from disc.\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nclass CADPCMFileStream : public Spt::Class\r\n{\r\n\tprivate:\r\n\r\n\tHANDLE\t\t\t\tm_hFile;\r\n\tHANDLE\t\t\t\tm_hThread;\r\n\tOVERLAPPED*\t\t\tm_pOverlapped;\t\t\t\t\t\t\t\t// OVERLAPPED structure for asynchronous file access.\r\n\tbool\t\t\t\tm_FirstRead;\t\t\t\t\t\t\t\t// Flag to indicate first request for more data to be streamed from disc.\r\n\tbool\t\t\t\tm_ReadComplete;\r\n\tint\t\t\t\t\tm_SuccessiveReads;\t\t\t\t\t\t\t// Counts how many read operations performed in total.\r\n\tbool\t\t\t\tm_bUseWAD;\r\n\tbool\t\t\t\tm_bUse3D;\t\t\t\t\t\t\t\t\t// Sets whether 2D or 3D mixbins are set up.\r\n\tDWORD\t\t\t\tm_dwWADOffset;\t\r\n\tDWORD\t\t\t\tm_dwWADLength;\r\n\r\n\tpublic:\r\n\r\n    IDirectSoundStream* m_pRenderFilter;\t\t\t\t\t\t\t// Render (DirectSoundStream) filter\r\n    LPVOID              m_pvSourceBuffer;\t\t\t\t\t\t\t// Source filter data buffer\r\n    LPVOID              m_pvRenderBuffer;\t\t\t\t\t\t\t// Render filter data buffer\r\n    DWORD               m_adwPacketStatus[ADPCMSTRM_PACKET_COUNT];\t// Packet status array\r\n\tint\t\t\t\t\tm_PacketBytes;\t\t\t\t\t\t\t\t// Size of each packet (will differ for mono and stereo).\r\n\tDWORD               m_dwStartingDataOffset;\t\t\t\t\t\t// Offset into wma file where data begins.\r\n    DWORD\t\t\t\tm_dwPercentCompleted;\t\t\t\t\t\t// Percent completed\r\n\tbool\t\t\t\tm_Paused;\r\n\tbool\t\t\t\tm_Completed;\t\t\t\t\t\t\t\t// For single-shot, indicates loading of final packet to renderer is completed\r\n    DWORD               m_LastPacket;\t\t\t\t\t\t\t\t// Last packet array index\r\n\tbool\t\t\t\tm_SetDeferredVolume;\r\n\tbool\t\t\t\tm_SetDeferredVolumeLR;\r\n\tbool\t\t\t\tm_SetDeferredVolume5Channel;\r\n\tbool\t\t\t\tm_bOkayToPlay;\t\t\t\t\t\t\t\t// Used when exact syncing is required - will load buffers but won't start decompression until this flag is true.\r\n\tfloat\t\t\t\tm_DeferredVolume[5];\r\n\tuint32\t\t\t\tm_Mixbins;\t\t\t\t\t\t\t\t\t// Bitfield indicating which mixbins are active for this buffer.\r\n\tuint32\t\t\t\tm_NumMixbins;\r\n\r\n    // Packet processing\r\n    BOOL\t\t\t\tFindFreePacket( DWORD* pdwPacketIndex );\r\n    HRESULT\t\t\t\tProcessSource( DWORD dwPacketIndex );\r\n    HRESULT\t\t\t\tProcessRenderer( DWORD dwPacketIndex );\r\n\r\n\tsADPCMExtendedWaveFormatEx\tm_wfxExtendedSourceFormat;\r\n    XFileMediaObject*   m_pSourceFilter;\t\t\t\t\t\t\t// Source (wave file) filter\r\n\tLPVOID\t\t\t\tm_pFileBuffer;\t\t\t\t\t\t\t\t// Buffer for async read of raw data.\r\n\tint\t\t\t\t\tm_FileBytesRead;\t\t\t\t\t\t\t// Total number of raw bytes read from disc.\r\n\tint\t\t\t\t\tm_FileBytesProcessed;\t\t\t\t\t\t// Total number of raw bytes processed by XMO.\r\n\tint\t\t\t\t\tm_DecoderCreation;\r\n\tbool\t\t\t\tm_AwaitingDeletion;\r\n\r\n    // Processing\r\n    HRESULT\t\t\t\tProcess();\r\n\r\n    // Initialization\r\n\tHRESULT\t\t\t\tInitializeFormatBlock( uint32 *p_header_data );\r\n\tHRESULT\t\t\t\tInitialize( HANDLE h_file, unsigned int offset, unsigned int length, void* fileBuffer );\r\n\tHRESULT\t\t\t\tPostInitialize( void );\r\n\tbool\t\t\t\tCreateSourceBuffer( void );\r\n    \r\n    // Play control\r\n    void\t\t\t\tPause( DWORD dwPause );\r\n\tvoid\t\t\t\tSetVolume( float volume );\r\n\tvoid\t\t\t\tSetVolume( float volumeL, float volumeR );\r\n\tvoid\t\t\t\tSetVolume( float v0, float v1, float v2, float v3, float v4 );\r\n\tvoid\t\t\t\tSetDeferredVolume( void );\r\n\r\n\t// Query\r\n\tIDirectSoundStream*\tGetSoundStream( void )\t\t\t\t\t{ return m_pRenderFilter; }\r\n\tbool\t\t\t\tIsCompleted( void )\t\t\t\t\t\t{ return ( m_Completed && ( XMEDIAPACKET_STATUS_PENDING != m_adwPacketStatus[m_LastPacket] )); }\r\n\tbool\t\t\t\tIsSafeToDelete( void );\r\n\tbool\t\t\t\tPreLoadDone( void );\r\n\r\n\t// Asynchronous stuff.\r\n\tvoid\t\t\t\tAsyncRead( void );\r\n\r\n\r\n    CADPCMFileStream( bool use_3d = false );\r\n    ~CADPCMFileStream();\r\n};\r\n\r\n\t\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Pcm\r\n\r\n#endif\t// __P_ADPCMFILESTREAM_H\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/Xbox/p_music.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGame Engine (GEL)\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_music.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t07/24/01\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXbox specific .wma streaming code\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n#include <core/macros.h>\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <core/crc.h>\r\n\r\n#include <sys/config/config.h>\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n#include \"p_music.h\"\r\n#include \"p_wmafilestream.h\"\r\n#include \"p_adpcmfilestream.h\"\r\n#include \"p_soundtrack.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Pcm\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define STREAMS_ARE_PCM\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sFileStreamInfo\r\n{\r\n\tenum FileStreamType\r\n\t{\r\n\t\tFILESTREAM_TYPE_WMA\t\t= 0,\r\n\t\tFILESTREAM_TYPE_ADPCM\t= 1\r\n\t};\r\n\r\n\t// These two could really be a union...\r\n\tCWMAFileStream*\t\tp_wma_filestream;\r\n\tCADPCMFileStream*\tp_adpcm_filestream;\r\n\r\n\tint\t\t\t\t\tpitch;\r\n\tfloat\t\t\t\tvolume;\r\n\tbool\t\t\t\tpaused;\r\n\r\n\tvoid\t\t\t\tCreateFileStream( FileStreamType type, bool use_3d = false );\r\n\tvoid\t\t\t\tDestroyFileStream( void );\r\n\t\r\n\tHRESULT\t\t\t\tInitialize( HANDLE h_file, void* fileBuffer );\r\n    HRESULT\t\t\t\tInitialize( HANDLE h_file, unsigned int offset, unsigned int length, void* fileBuffer );\r\n\tHRESULT\t\t\t\tProcess( void );\r\n\tvoid\t\t\t\tPause( uint32 pause );\r\n\tvoid\t\t\t\tSetOkayToPlay( bool okay_to_play );\r\n\tbool\t\t\t\tGetOkayToPlay( void );\r\n\tbool\t\t\t\tHasFileStream( void )\t{ return (( p_wma_filestream != NULL ) || ( p_adpcm_filestream != NULL )); }\r\n\tbool\t\t\t\tIsCompleted( void );\r\n\tbool\t\t\t\tIsAwaitingDeletion( void );\r\n\tvoid\t\t\t\tSetAwaitingDeletion( bool is_awaiting );\r\n\tbool\t\t\t\tIsSafeToDelete( void );\r\n\tvoid\t\t\t\tFlush( void );\r\n\tbool\t\t\t\tIsPreLoadDone( void );\r\n\tvoid\t\t\t\tSetVolume( float v0 );\r\n\tvoid\t\t\t\tSetVolume( float v0, float v1 );\r\n\tvoid\t\t\t\tSetVolume( float v0, float v1, float v2, float v3, float v4 );\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sFileStreamInfo::CreateFileStream( FileStreamType type, bool use_3d )\r\n{\r\n\tDbg_Assert(( p_wma_filestream == NULL ) && ( p_adpcm_filestream == NULL ));\r\n\tif( type == FILESTREAM_TYPE_WMA )\r\n\t{\r\n\t\tp_wma_filestream = new CWMAFileStream( use_3d );\r\n\t}\r\n\telse if( type == FILESTREAM_TYPE_ADPCM )\r\n\t{\r\n\t\tp_adpcm_filestream = new CADPCMFileStream( use_3d );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sFileStreamInfo::DestroyFileStream( void )\r\n{\r\n\tif( p_wma_filestream )\r\n\t{\r\n\t\tdelete p_wma_filestream;\r\n\t\tp_wma_filestream = NULL;\r\n\t}\r\n\r\n\tif( p_adpcm_filestream )\r\n\t{\r\n\t\tdelete p_adpcm_filestream;\r\n\t\tp_adpcm_filestream = NULL;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nHRESULT sFileStreamInfo::Initialize( HANDLE h_file, void* fileBuffer )\r\n{\r\n\tif( p_wma_filestream )\r\n\t{\r\n\t\treturn p_wma_filestream->Initialize( h_file, fileBuffer );\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nHRESULT sFileStreamInfo::Initialize( HANDLE h_file, unsigned int offset, unsigned int length, void* fileBuffer )\r\n{\r\n\tif( p_wma_filestream )\r\n\t{\r\n\t\treturn p_wma_filestream->Initialize( h_file, offset, length, fileBuffer );\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\treturn p_adpcm_filestream->Initialize( h_file, offset, length, fileBuffer );\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nHRESULT sFileStreamInfo::Process( void )\r\n{\r\n\tif( p_wma_filestream )\r\n\t{\r\n\t\treturn p_wma_filestream->Process();\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\treturn p_adpcm_filestream->Process();\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sFileStreamInfo::Pause( uint32 pause )\r\n{\r\n\tif( p_wma_filestream )\r\n\t{\r\n\t\tp_wma_filestream->Pause( pause );\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\tp_adpcm_filestream->Pause( pause );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sFileStreamInfo::SetOkayToPlay( bool okay_to_play )\r\n{\r\n\tif( p_wma_filestream )\r\n\t{\r\n\t\tp_wma_filestream->m_bOkayToPlay = okay_to_play;\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\tp_adpcm_filestream->m_bOkayToPlay = okay_to_play;\r\n\t}\r\n}\r\n\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool sFileStreamInfo::GetOkayToPlay( void )\r\n{\r\n\tif( p_wma_filestream )\r\n\t{\r\n\t\treturn p_wma_filestream->m_bOkayToPlay;\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\treturn p_adpcm_filestream->m_bOkayToPlay;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool sFileStreamInfo::IsCompleted( void )\r\n{\r\n\tif( p_wma_filestream )\r\n\t{\r\n\t\treturn p_wma_filestream->IsCompleted();\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\treturn p_adpcm_filestream->IsCompleted();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool sFileStreamInfo::IsAwaitingDeletion( void )\r\n{\r\n\tif( p_wma_filestream )\r\n\t{\r\n\t\treturn p_wma_filestream->m_AwaitingDeletion;\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\treturn p_adpcm_filestream->m_AwaitingDeletion;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sFileStreamInfo::SetAwaitingDeletion( bool is_awaiting )\r\n{\r\n\tif( p_wma_filestream )\r\n\t{\r\n\t\tp_wma_filestream->m_AwaitingDeletion = is_awaiting;\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\tp_adpcm_filestream->m_AwaitingDeletion = is_awaiting;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool sFileStreamInfo::IsSafeToDelete( void )\r\n{\r\n\tif( p_wma_filestream )\r\n\t{\r\n\t\treturn p_wma_filestream->IsSafeToDelete();\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\treturn p_adpcm_filestream->IsSafeToDelete();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool sFileStreamInfo::IsPreLoadDone( void )\r\n{\r\n\tif( p_wma_filestream )\r\n\t{\r\n\t\treturn p_wma_filestream->PreLoadDone();\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\treturn p_adpcm_filestream->PreLoadDone();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sFileStreamInfo::Flush( void )\r\n{\r\n\tif( p_wma_filestream ) \r\n\t{\r\n\t\tif( p_wma_filestream->m_pRenderFilter )\r\n\t\t{\r\n\t\t\tp_wma_filestream->m_pRenderFilter->FlushEx( 0, DSSTREAMFLUSHEX_ASYNC );\r\n\t\t}\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\tif( p_adpcm_filestream->m_pRenderFilter )\r\n\t\t{\r\n\t\t\tp_adpcm_filestream->m_pRenderFilter->FlushEx( 0, DSSTREAMFLUSHEX_ASYNC );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sFileStreamInfo::SetVolume( float v0 )\r\n{\r\n\tif( p_wma_filestream ) \r\n\t{\r\n\t\tp_wma_filestream->SetVolume( v0 );\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\tp_adpcm_filestream->SetVolume( v0 );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sFileStreamInfo::SetVolume( float v0, float v1 )\r\n{\r\n\tif( p_wma_filestream ) \r\n\t{\r\n\t\tp_wma_filestream->SetVolume( v0, v1 );\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\tp_adpcm_filestream->SetVolume( v0, v1 );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sFileStreamInfo::SetVolume( float v0, float v1, float v2, float v3, float v4 )\r\n{\r\n\tif( p_wma_filestream ) \r\n\t{\r\n\t\tp_wma_filestream->SetVolume( v0, v1, v2, v3, v4 );\r\n\t}\r\n\telse if( p_adpcm_filestream )\r\n\t{\r\n\t\tp_adpcm_filestream->SetVolume( v0, v1, v2, v3, v4 );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nsFileStreamInfo\tgMusicInfo;\r\nsFileStreamInfo\tgStreamInfo[NUM_STREAMS];\r\n\r\nconst uint32\tFILESTREAM_BUFFER_SIZE\t= 80 * 1024;\r\n\r\n#pragma pack( 16 )\r\n// Grab an 80k read buffer. Must be DWORD aligned.\r\n// This is big enough for (9 * 8k packets) for WMA, where last packet mirrors the first packet,\r\n// for cases when the decoder reads past the end of the ring buffer.\r\n// Also big enough for ( 5 * 16k packets) for ADPCM, where no wraparound is required.\r\nDWORD\t\t\tgMusicFileBuffer[FILESTREAM_BUFFER_SIZE / 4];\r\nDWORD\t\t\tgStreamFileBuffer[NUM_STREAMS][FILESTREAM_BUFFER_SIZE / 4];\r\n#pragma pack()\r\n\r\nconst int\t\tNUM_OVERLAPPED\t= 256;\r\nOVERLAPPED\t\tgOverlapped[NUM_OVERLAPPED];\r\nint\t\t\t\tgNextOverlap = 0;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nHANDLE\tghWADFile\t\t\t\t= INVALID_HANDLE_VALUE;\r\nuint32\t*pWADData\t\t\t\t= NULL;\r\nuint32\tnumWADFileEntries\t\t= 0;\r\n\r\nHANDLE\tghMusicWADFile\t\t\t= INVALID_HANDLE_VALUE;\r\nuint32\t*pMusicWADData\t\t\t= NULL;\r\nuint32\tnumMusicWADFileEntries\t= 0;\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nOVERLAPPED *PCMAudio_GetNextOverlapped( void )\r\n{\r\n\tOVERLAPPED *p_return = &( gOverlapped[gNextOverlap] );\r\n\tif( ++gNextOverlap >= NUM_OVERLAPPED )\r\n\t{\r\n\t\tgNextOverlap = 0;\r\n\t}\r\n\r\n\tZeroMemory( p_return, sizeof( OVERLAPPED ));\r\n\treturn p_return;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 PCMAudio_GetFilestreamBufferSize( void )\r\n{\r\n\treturn FILESTREAM_BUFFER_SIZE;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PCMAudio_Init( void )\r\n{\r\n\t// Zero the music and filestream info arrays.\r\n\tZeroMemory( &gMusicInfo, sizeof( sFileStreamInfo ));\r\n\tZeroMemory( &gStreamInfo[0], sizeof( sFileStreamInfo ) * NUM_STREAMS );\r\n\r\n\t// Enumerate user soundtracks.\r\n\tGetNumSoundtracks();\r\n\r\n\t// Figure out the language, and open appropriate file.\r\n\tConfig::ELanguage lang = Config::GetLanguage();\r\n\r\n\t// Assume English.\r\n#\tifdef STREAMS_ARE_PCM\r\n\tghWADFile\t\t= CreateFile( \"d:\\\\data\\\\streams\\\\pcm\\\\pcm.wad\",\r\n#\telse\r\n\tghWADFile\t\t= CreateFile( \"d:\\\\data\\\\streams\\\\wma\\\\wma.wad\",\r\n#\tendif\r\n\t\t\t\t\t\t\t\tGENERIC_READ,\r\n\t\t\t\t\t\t\t\tFILE_SHARE_READ,\t\t\t\t\t\t\t\t// Share mode.\r\n\t\t\t\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t\t\t\t// Ignored (security attributes).\r\n\t\t\t\t\t\t\t\tOPEN_EXISTING,\t\t\t\t\t\t\t\t\t// File has to exist already.\r\n\t\t\t\t\t\t\t\tFILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,\t// Xbox has no asynchronous i/o buffering.\r\n\t\t\t\t\t\t\t\tNULL );\t\t\t\t\t\t\t\t\t\t\t// Ignored (template file).\r\n#\tifdef STREAMS_ARE_PCM\r\n\tghMusicWADFile = CreateFile( \"d:\\\\data\\\\streams\\\\pcm\\\\music_pcm.wad\",\r\n#\telse\r\n\tghMusicWADFile = CreateFile( \"d:\\\\data\\\\streams\\\\wma\\\\music_wma.wad\",\r\n#\tendif\r\n\t\t\t\t\t\t\t\tGENERIC_READ,\r\n\t\t\t\t\t\t\t\tFILE_SHARE_READ,\t\t\t\t\t\t\t\t// Share mode.\r\n\t\t\t\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t\t\t\t// Ignored (security attributes).\r\n\t\t\t\t\t\t\t\tOPEN_EXISTING,\t\t\t\t\t\t\t\t\t// File has to exist already.\r\n\t\t\t\t\t\t\t\tFILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,\t// Xbox has no asynchronous i/o buffering.\r\n\t\t\t\t\t\t\t\tNULL );\t\t\t\t\t\t\t\t\t\t\t// Ignored (template file).\r\n\r\n\t// Now read in the data files used for indexing into the WAD files.\r\n#\tifdef STREAMS_ARE_PCM\r\n\tHANDLE wad_data = CreateFile( \"d:\\\\data\\\\streams\\\\pcm\\\\pcm.dat\",\r\n#\telse\r\n\tHANDLE wad_data = CreateFile( \"d:\\\\data\\\\streams\\\\wma\\\\wma.dat\",\r\n#\tendif\r\n\t\t\t\t\t\t\t\t\tGENERIC_READ,\r\n\t\t\t\t\t\t\t\t\tFILE_SHARE_READ,\t\t\t\t\t\t\t\t// Share mode.\r\n\t\t\t\t\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t\t\t\t// Ignored (security attributes).\r\n\t\t\t\t\t\t\t\t\tOPEN_EXISTING,\t\t\t\t\t\t\t\t\t// File has to exist already.\r\n\t\t\t\t\t\t\t\t\tFILE_FLAG_SEQUENTIAL_SCAN,\r\n\t\t\t\t\t\t\t\t\tNULL );\t\t\t\t\t\t\t\t\t\t\t// Ignored (template file).\r\n\r\n\tif( wad_data != INVALID_HANDLE_VALUE )\r\n\t{\r\n\t\tuint32 bytes_read;\r\n\t\tReadFile( wad_data, &numWADFileEntries, sizeof( uint32 ), &bytes_read, NULL );\r\n\t\tpWADData = new uint32[numWADFileEntries * 3];\r\n\t\tReadFile( wad_data, pWADData, sizeof( uint32 ) * numWADFileEntries * 3, &bytes_read, NULL );\r\n\t\tCloseHandle( wad_data );\r\n\t}\r\n\t\t\t\r\n\t// Sort the wad file entries into increasing checksum order, so that we can use a binary search algorithm to\r\n\t// find the checksum quickly.\r\n\tfor( uint32 i = 0; i < numWADFileEntries; ++i )\r\n\t{\r\n\t\tfor( uint32 j = i + 1; j < numWADFileEntries; ++j )\r\n\t\t{\r\n\t\t\tif( pWADData[i * 3] > pWADData[j * 3] )\r\n\t\t\t{\r\n\t\t\t\tuint32 temp[3];\r\n\t\t\t\ttemp[0]\t\t\t\t= pWADData[i * 3];\r\n\t\t\t\ttemp[1]\t\t\t\t= pWADData[i * 3 + 1];\r\n\t\t\t\ttemp[2]\t\t\t\t= pWADData[i * 3 + 2];\r\n\t\t\t\tpWADData[i * 3]\t\t= pWADData[j * 3];\r\n\t\t\t\tpWADData[i * 3 + 1]\t= pWADData[j * 3 + 1];\r\n\t\t\t\tpWADData[i * 3 + 2]\t= pWADData[j * 3 + 2];\r\n\t\t\t\tpWADData[j * 3]\t\t= temp[0];\r\n\t\t\t\tpWADData[j * 3 + 1]\t= temp[1];\r\n\t\t\t\tpWADData[j * 3 + 2]\t= temp[2];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\t\t\r\n#\tifdef STREAMS_ARE_PCM\r\n\twad_data = CreateFile( \"d:\\\\data\\\\streams\\\\pcm\\\\music_pcm.dat\",\r\n#\telse\r\n\twad_data = CreateFile( \"d:\\\\data\\\\streams\\\\wma\\\\music_wma.dat\",\r\n#\tendif\r\n\t\t\t\t\t\t\tGENERIC_READ,\r\n\t\t\t\t\t\t\tFILE_SHARE_READ,\t\t\t\t\t\t\t\t// Share mode.\r\n\t\t\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t\t\t\t// Ignored (security attributes).\r\n\t\t\t\t\t\t\tOPEN_EXISTING,\t\t\t\t\t\t\t\t\t// File has to exist already.\r\n\t\t\t\t\t\t\tFILE_FLAG_SEQUENTIAL_SCAN,\r\n\t\t\t\t\t\t\tNULL );\t\t\t\t\t\t\t\t\t\t\t// Ignored (template file).\r\n\r\n\tif( wad_data != INVALID_HANDLE_VALUE )\r\n\t{\r\n\t\tuint32 bytes_read;\r\n\t\tReadFile( wad_data, &numMusicWADFileEntries, sizeof( uint32 ), &bytes_read, NULL );\r\n\t\tpMusicWADData = new uint32[numMusicWADFileEntries * 3];\r\n\t\tReadFile( wad_data, pMusicWADData, sizeof( uint32 ) * numMusicWADFileEntries * 3, &bytes_read, NULL );\r\n\t\tCloseHandle( wad_data );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Call every frame to make sure music and stream buffers are\t  */\r\n/* loaded and current status is checked each frame...\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nint PCMAudio_Update( void )\r\n{\r\n\tif( gMusicInfo.HasFileStream())\r\n\t{\r\n\t\tHRESULT hr = gMusicInfo.Process();\r\n\r\n\t\tif( gMusicInfo.IsCompleted())\r\n\t\t{\r\n\t\t\tgMusicInfo.DestroyFileStream();\r\n\t\t}\r\n\t\telse if( gMusicInfo.IsAwaitingDeletion() && gMusicInfo.IsSafeToDelete())\r\n\t\t{\r\n\t\t\tgMusicInfo.DestroyFileStream();\r\n\t\t}\r\n\t}\r\n\r\n\tfor( int i = 0; i < NUM_STREAMS; ++i )\r\n\t{\r\n\t\tif( gStreamInfo[i].HasFileStream())\r\n\t\t{\r\n\t\t\tHRESULT hr = gStreamInfo[i].Process();\r\n\r\n\t\t\tif( gStreamInfo[i].IsCompleted())\r\n\t\t\t{\r\n\t\t\t\tgStreamInfo[i].DestroyFileStream();\r\n\t\t\t}\r\n\t\t\telse if( gStreamInfo[i].IsAwaitingDeletion() && gStreamInfo[i].IsSafeToDelete())\r\n\t\t\t{\r\n\t\t\t\tgStreamInfo[i].DestroyFileStream();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// A non-zero return value singnals an error condition.\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PCMAudio_StopMusic( bool waitPlease )\r\n{\r\n\tif( gMusicInfo.HasFileStream())\r\n\t{\r\n\t\tif( gMusicInfo.IsSafeToDelete())\r\n\t\t{\t\r\n\t\t\tgMusicInfo.Flush();\r\n\t\t\tgMusicInfo.DestroyFileStream();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tgMusicInfo.SetAwaitingDeletion( true );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PCMAudio_StopStream( int whichStream, bool waitPlease )\r\n{\r\n\tif( gStreamInfo[whichStream].HasFileStream())\r\n\t{\r\n\t\tif( gStreamInfo[whichStream].IsSafeToDelete())\r\n\t\t{\r\n\t\t\tgStreamInfo[whichStream].Flush();\r\n\t\t\tgStreamInfo[whichStream].DestroyFileStream();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tgStreamInfo[whichStream].SetAwaitingDeletion( true );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PCMAudio_StopStreams( void )\r\n{\r\n\tfor( int i = 0; i < NUM_STREAMS; ++i )\r\n\t{\r\n\t\tPCMAudio_StopStream( i, false );\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// This is temp code for the preload streams.  It just calls the normal one.\r\n\r\nstatic uint32 sPreLoadChecksum[NUM_STREAMS];\r\nstatic uint32 sPreLoadMusicChecksum;\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Get a stream loaded into a buffer, but don't play yet\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PreLoadStream( uint32 checksum, int whichStream )\r\n{\r\n\tDbg_Assert(( whichStream >= 0 ) && ( whichStream < NUM_STREAMS ));\r\n\tsPreLoadChecksum[whichStream] = checksum;\r\n\r\n\t// Start the track as normal...\r\n\tif( PCMAudio_PlayStream( checksum, whichStream, NULL, 0.0f, false ))\r\n\t{\r\n\t\t// ...but then flag it as not okay to play until we say so.\r\n\t\tif( gStreamInfo[whichStream].HasFileStream())\r\n\t\t{\r\n\t\t\tgStreamInfo[whichStream].SetOkayToPlay( false );\r\n\t\t}\r\n        return true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Returns true if preload done. Assumes that caller is calling\t  */\r\n/* this on a preloaded, but not yet played, stream. The results\t  */\r\n/* are meaningless otherwise.\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PreLoadStreamDone( int whichStream )\r\n{\r\n\tif( gStreamInfo[whichStream].HasFileStream())\r\n\t{\r\n\t\treturn gStreamInfo[whichStream].IsPreLoadDone();\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Tells a preloaded stream to start playing.\t\t\t\t\t  */\r\n/* Must call PCMAudio_PreLoadStreamDone() first to guarantee that */\r\n/* it starts immediately.\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_StartPreLoadedStream( int whichStream, Sfx::sVolume *p_volume, float pitch )\r\n{\r\n\t// Maybe we should check here to make sure the checksum of the music info filestream matches that\r\n\t// passed in when the music stream preload request came in.\r\n\tif( gStreamInfo[whichStream].HasFileStream())\r\n\t{\r\n\t\tgStreamInfo[whichStream].SetOkayToPlay( true );\r\n\t\tPCMAudio_SetStreamVolume( p_volume, whichStream );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PreLoadMusicStream( uint32 checksum )\r\n{\r\n\tsPreLoadMusicChecksum = checksum;\r\n\r\n\t// Start the track as normal...\r\n\tif( PCMAudio_PlayMusicTrack( sPreLoadMusicChecksum ))\r\n\t{\r\n\t\t// ...but then flag it as not okay to play until we say so.\r\n\t\tif( gMusicInfo.HasFileStream())\r\n\t\t{\r\n\t\t\tgMusicInfo.SetOkayToPlay( false );\r\n\t\t}\r\n        return true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PreLoadMusicStreamDone( void )\r\n{\r\n\tif( gMusicInfo.HasFileStream())\r\n\t{\r\n\t\treturn gMusicInfo.IsPreLoadDone();\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_StartPreLoadedMusicStream( void )\r\n{\r\n\t// Maybe we should check here to make sure the checksum of the music info filestream matches that\r\n\t// passed in when the music stream preload request came in.\r\n\tif( gMusicInfo.HasFileStream())\r\n\t{\r\n\t\t// Call update immediately to start playback ASAP.\r\n\t\tgMusicInfo.SetOkayToPlay( true );\r\n\t\tPCMAudio_Update();\r\n\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint PCMAudio_GetMusicStatus( void )\r\n{\r\n\tif( gMusicInfo.HasFileStream())\r\n\t{\r\n\t\treturn PCM_STATUS_PLAYING;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn PCM_STATUS_FREE;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint PCMAudio_GetStreamStatus( int whichStream )\r\n{\r\n\tint start, end;\r\n\r\n\t// Negative one is used to signal 'any stream'.\r\n\tif( whichStream == -1 )\r\n\t{\r\n\t\tstart\t= 0;\r\n\t\tend\t\t= NUM_STREAMS;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tstart\t= whichStream;\r\n\t\tend\t\t= start + 1;\r\n\t}\r\n\r\n\tfor( int s = start; s < end; ++s )\r\n\t{\r\n\t\tif( !gStreamInfo[s].HasFileStream())\r\n\t\t{\t\t\r\n\t\t\treturn PCM_STATUS_FREE;\r\n\t\t}\r\n\t}\r\n\r\n\treturn PCM_STATUS_PLAYING;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PCMAudio_Pause( bool pause, int ch )\r\n{\r\n\tif( ch == MUSIC_CHANNEL )\r\n\t{\r\n\t\tgMusicInfo.paused = pause;\r\n\t\tif( gMusicInfo.HasFileStream())\r\n\t\t{\r\n\t\t\tif( pause )\r\n\t\t\t{\r\n\t\t\t\tgMusicInfo.Pause( 1 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tgMusicInfo.Pause( 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor( int s = 0; s < NUM_STREAMS; ++s )\r\n\t\t{\r\n\t\t\tif( gStreamInfo[s].HasFileStream())\r\n\t\t\t{\r\n\t\t\t\tif( pause )\r\n\t\t\t\t{\r\n\t\t\t\t\tgStreamInfo[s].Pause( 1 );\r\n\t\t\t\t\tgStreamInfo[s].paused = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tgStreamInfo[s].Pause( 0 );\r\n\t\t\t\t\tgStreamInfo[s].paused = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_TrackExists( const char *pTrackName, int ch )\r\n{\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_LoadMusicHeader( const char *nameOfFile )\r\n{\r\n\t// Legacy call left over from PS2 code.\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_LoadStreamHeader( const char *nameOfFile )\r\n{\r\n\t// Legacy call left over from PS2 code.\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Return (any) position if t in sorted x[0..n-1] or -1 if t is\t  */\r\n/* not present.                                                    */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int binarySearch( uint32 checksum )\r\n{\r\n\tint l = 0;\r\n\tint u = numWADFileEntries - 1;\r\n\twhile( l <= u )\r\n\t{\r\n\t\tint m = ( l + u ) / 2;\r\n\t\tif( pWADData[m * 3] < checksum )\r\n\t\t\tl = m + 1;\r\n\t\telse if ( pWADData[m * 3] == checksum )\r\n\t\t\treturn m;\r\n\t\telse // x[m] > t\r\n\t\t\tu = m - 1;\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 PCMAudio_FindNameFromChecksum( uint32 checksum, int ch )\r\n{\r\n\tif( ch != EXTRA_CHANNEL )\r\n\t\treturn 0;\r\n\r\n\tint rv = binarySearch( checksum );\r\n\t\r\n\treturn ( rv == -1 ) ? 0 : checksum;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_SetStreamVolume( Sfx::sVolume *p_volume, int whichStream )\r\n{\r\n\tif( gStreamInfo[whichStream].HasFileStream())\r\n\t{\r\n\t\t// Adjust volumes for overall sound volume.\r\n\t\tSpt::SingletonPtr< Sfx::CSfxManager > sfx_manager;\r\n\r\n\t\tswitch( p_volume->GetVolumeType())\r\n\t\t{\r\n\t\t\tcase Sfx::VOLUME_TYPE_5_CHANNEL_DOLBY5_1:\r\n\t\t\t{\r\n\t\t\t\tfloat v0\t= PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 0 ));\r\n\t\t\t\tfloat v1\t= PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 1 ));\r\n\t\t\t\tfloat v2\t= PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 2 ));\r\n\t\t\t\tfloat v3\t= PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 3 ));\r\n\t\t\t\tfloat v4\t= PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 4 ));\r\n\r\n\t\t\t\tgStreamInfo[whichStream].volume = ( v0 + v1 + v2 + v3 + v4 ) * ( 1.0f / 5.0f );\r\n\t\t\t\tgStreamInfo[whichStream].SetVolume( v0, v1, v2, v3, v4 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase Sfx::VOLUME_TYPE_2_CHANNEL_DOLBYII:\r\n\t\t\t{\r\n\t\t\t\tfloat v0\t= PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 0 ));\r\n\t\t\t\tfloat v1\t= PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 1 ));\r\n\r\n\t\t\t\tgStreamInfo[whichStream].volume = v0;\r\n\t\t\t\tgStreamInfo[whichStream].SetVolume( v0, v1 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase Sfx::VOLUME_TYPE_BASIC_2_CHANNEL:\r\n\t\t\t{\r\n\t\t\t\tfloat v0\t= PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 0 ));\r\n\r\n\t\t\t\tgStreamInfo[whichStream].volume = v0;\r\n\t\t\t\tgStreamInfo[whichStream].SetVolume( v0 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint PCMAudio_SetMusicVolume( float volume )\r\n{\r\n\tif( gMusicInfo.HasFileStream())\r\n\t{\r\n\t\tgMusicInfo.volume = volume;\r\n\t\tgMusicInfo.SetVolume( volume );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_SetStreamPitch( float fPitch, int whichStream )\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PlayMusicTrack( uint32 checksum )\r\n{\r\n\t// Find the entry in the offset array.\r\n\tbool found = false;\r\n\t\r\n\tunsigned int samplelength, sampleoffset;\r\n\t\r\n\t// English.\r\n\tfor( unsigned int entry = 0; entry < numMusicWADFileEntries; ++entry )\r\n\t{\r\n\t\tif( pMusicWADData[entry * 3] == checksum )\r\n\t\t{\r\n\t\t\tsampleoffset\t= pMusicWADData[entry * 3 + 1];\r\n\t\t\tsamplelength\t= pMusicWADData[entry * 3 + 2];\r\n\t\t\tfound\t\t\t= true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif( !found )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Just a stream like everything else.\r\n\tif( PCMAudio_GetMusicStatus() != PCM_STATUS_FREE )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Don't want to use 3d processing for the music track.\r\n#\tifdef STREAMS_ARE_PCM\r\n\tgMusicInfo.CreateFileStream( sFileStreamInfo::FILESTREAM_TYPE_ADPCM, false );\r\n#\telse\r\n\tgMusicInfo.CreateFileStream( sFileStreamInfo::FILESTREAM_TYPE_WMA, false );\r\n#\tendif\r\n\r\n\tHRESULT hr = gMusicInfo.Initialize( ghMusicWADFile, sampleoffset, samplelength, gMusicFileBuffer );\r\n\tif( hr == S_OK )\r\n\t{\r\n\t\t// All started fine. Pause music if paused flag is set.\r\n\t\tif( gMusicInfo.paused )\r\n\t\t{\r\n\t\t\tPCMAudio_Pause( true, MUSIC_CHANNEL );\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Failed to initialize the stream.\r\n\t\tgMusicInfo.DestroyFileStream();\r\n\t\tDbg_MsgAssert( 0, ( \"Failed to initialize music stream: %x\", checksum ));\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PlayMusicTrack( const char *filename )\r\n{\r\n\tconst char\t*samplename = filename;\r\n\tchar\t\t*locate;\r\n\t\r\n\t// Search for the last directory seperator, and cut off all of the path prior to it.\r\n\tif( locate = strrchr( samplename, '\\\\' ))\r\n\t{\r\n\t\tsamplename = locate + 1;\r\n\t}\r\n\tif( locate = strrchr( samplename, '/' ))\r\n\t{\r\n\t\tsamplename = locate + 1;\r\n\t}\r\n\r\n\t// Now generate the checksum for this samplename.\r\n\tuint32 checksum = Crc::GenerateCRCFromString( samplename );\r\n\r\n\tbool rv = PCMAudio_PlayMusicTrack( checksum );\r\n\tif( rv == false )\r\n\t{\r\n\t\tDbg_Message( \"Failed to find stream: %s\", filename );\r\n\t}\r\n\treturn rv;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PlaySoundtrackMusicTrack( int soundtrack, int track )\r\n{\r\n\t// Just a stream like everything else.\r\n\tif( gMusicInfo.HasFileStream())\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Playing new track without stopping the first track.\" ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Don't want to use 3d processing for the music track.\r\n\t\tgMusicInfo.CreateFileStream( sFileStreamInfo::FILESTREAM_TYPE_WMA, false );\r\n\r\n\t\tHANDLE h_song = GetSoundtrackWMAHandle( soundtrack, track );\r\n\t\tif( h_song == INVALID_HANDLE_VALUE )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tHRESULT hr = gMusicInfo.Initialize( h_song, gMusicFileBuffer );\r\n\t\tif( hr == S_OK )\r\n\t\t{\r\n\t\t\t// All started fine. Pause music if paused flag is set.\r\n\t\t\tif( gMusicInfo.paused )\r\n\t\t\t{\r\n\t\t\t\tPCMAudio_Pause( true, MUSIC_CHANNEL );\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_StartStream( int whichStream )\r\n{\r\n\tif( gStreamInfo[whichStream].HasFileStream())\r\n\t{\r\n\t\tif( gStreamInfo[whichStream].GetOkayToPlay() == false )\r\n\t\t{\r\n\t\t\t// Now okay to start playing.\r\n\t\t\tgStreamInfo[whichStream].SetOkayToPlay( true );\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PlayStream( uint32 checksum, int whichStream, Sfx::sVolume *p_volume, float fPitch, bool preload )\r\n{\r\n\tunsigned int samplelength, sampleoffset;\r\n\r\n\t// Perform a binary search on the checksum table to find the correct entry.\t\r\n\tint entry = binarySearch( checksum );\r\n\tif( entry >= 0 )\r\n\t{\r\n\t\tsampleoffset\t= pWADData[entry * 3 + 1];\r\n\t\tsamplelength\t= pWADData[entry * 3 + 2];\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tDbg_Assert(( whichStream >= 0 ) && ( whichStream < NUM_STREAMS ));\r\n\r\n\t// Just a stream like everything else.\r\n\tif( PCMAudio_GetStreamStatus( whichStream ) != PCM_STATUS_FREE )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n#\tifdef STREAMS_ARE_PCM\r\n\tgStreamInfo[whichStream].CreateFileStream( sFileStreamInfo::FILESTREAM_TYPE_ADPCM, true );\r\n#\telse\r\n\tgStreamInfo[whichStream].CreateFileStream( sFileStreamInfo::FILESTREAM_TYPE_WMA, true );\r\n#\tendif\r\n\r\n\t// The preload parameter indicates that we want to get this stream in a position where it is ready to play\r\n\t// immediately at some later point in time. The m_bOkayToPlay member is used to signal this.\r\n\tif( preload )\r\n\t{\r\n\t\t// Not okay to start playing until told to do so.\r\n\t\tgStreamInfo[whichStream].SetOkayToPlay( false );\r\n\t}\r\n\r\n\tHRESULT hr = gStreamInfo[whichStream].Initialize( ghWADFile, sampleoffset, samplelength, &gStreamFileBuffer[whichStream][0] );\r\n\r\n\tif( hr == S_OK )\r\n\t{\r\n\t\t// All started fine.\r\n\t\tif( p_volume )\r\n\t\t{\r\n\t\t\tPCMAudio_SetStreamVolume( p_volume, whichStream );\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Failed to initialize the stream.\r\n\t\tgStreamInfo[whichStream].DestroyFileStream();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n} // namespace PCM\r\n"
  },
  {
    "path": "Code/Gel/Music/Xbox/p_music.h",
    "content": "// Audio streaming function prototypes:\r\n// mjd jan 2001\r\n\r\n#ifndef __P_MUSIC_H__\r\n#define __P_MUSIC_H__\r\n\r\n// Needed so music.cpp will build. Grrr.\r\n#define NUM_STREAMS 3\r\n\r\nnamespace Pcm\r\n{\r\n\r\n// allows one channel for music, another for audio:\r\nenum{\r\n\tEXTRA_CHANNEL,\r\n\tMUSIC_CHANNEL,\r\n};\r\n\r\n// Onetime call once upon loading the game...\r\nvoid PCMAudio_Init( void );\r\n\r\nOVERLAPPED *PCMAudio_GetNextOverlapped( void );\r\n\r\n// Call every frame to make sure music and stream buffers are loaded and current status is checked each frame...\r\nint PCMAudio_Update( void );\r\n\r\n// Load a track and start it playing...\r\n// You wanna loop a track?  Wait until this track is done, and PLAY IT AGAIN SAM!\r\nbool PCMAudio_PlayMusicTrack( const char *filename );\r\nbool PCMAudio_PlayMusicTrack( uint32 checksum );\r\nbool PCMAudio_PlaySoundtrackMusicTrack( int soundtrack, int track );\r\n//bool PCMAudio_PlayStream( uint32 checksum, int whichStream, float volumeL, float volumeR, float pitch, bool preload = false );\r\nbool PCMAudio_PlayStream( uint32 checksum, int whichStream, Sfx::sVolume *p_volume, float pitch, bool preload = false );\r\nbool PCMAudio_StartStream( int whichStream );\r\n\r\n// keep song loaded, stop playing it (or continue playing paused song)\r\nvoid PCMAudio_Pause( bool pause = true, int ch = MUSIC_CHANNEL );\r\n\r\nvoid PCMAudio_StopMusic( bool waitPlease );\r\nvoid PCMAudio_StopStream( int whichStream, bool waitPlease = true );\r\nvoid PCMAudio_StopStreams( void );\r\n\r\nuint32\tPCMAudio_GetFilestreamBufferSize( void );\r\n\r\n// Preload streams. By preloading, you can guarantee they will start at a certain time.\r\nbool PCMAudio_PreLoadStream( uint32 checksum, int whichStream );\r\nbool PCMAudio_PreLoadStreamDone( int whichStream );\r\n//bool PCMAudio_StartPreLoadedStream( int whichStream, float volumeL, float volumeR, float pitch );\r\nbool PCMAudio_StartPreLoadedStream( int whichStream, Sfx::sVolume *p_volume, float pitch );\r\n\r\n// Preload music streams. By preloading, you can guarantee they will start at a certain time.\r\nbool PCMAudio_PreLoadMusicStream( uint32 checksum );\r\nbool PCMAudio_PreLoadMusicStreamDone( void );\r\nbool PCMAudio_StartPreLoadedMusicStream( void );\r\n\r\n// set the music volume ( 0 to 100 )\r\nint PCMAudio_SetMusicVolume( float volume );\r\nbool\tPCMAudio_SetStreamPitch( float pitch, int whichStream );\r\n//int PCMAudio_SetStreamVolumeAndPitch( float volL, float volR, float pitch, int whichStream );\r\n\r\nenum{\r\n\tPCM_STATUS_FREE \t\t\t= ( 1 << 0 ),\r\n\tPCM_STATUS_PLAYING\t\t\t= ( 1 << 1 ),\r\n\tPCM_STATUS_LOADING \t\t\t= ( 1 << 2 ),\r\n};\r\n\r\nbool PCMAudio_SetStreamVolume( Sfx::sVolume *p_volume, int whichStream );\r\n\r\n// Return one of the PCM_STATUS values from above...\r\n// Return one of the PCM_STATUS values from above...\r\nint PCMAudio_GetMusicStatus( );\r\nint PCMAudio_GetStreamStatus( int whichStream );\r\n\r\nbool PCMAudio_TrackExists( const char *pTrackName, int ch );\r\nbool PCMAudio_LoadMusicHeader( const char *nameOfFile );\r\nbool PCMAudio_LoadStreamHeader( const char *nameOfFile );\r\n\r\nuint32 PCMAudio_FindNameFromChecksum( uint32 checksum, int ch );\r\n\t \r\n} // namespace PCM\r\n\r\n#endif // __P_MUSIC_H__\r\n"
  },
  {
    "path": "Code/Gel/Music/Xbox/p_soundtrack.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGame Engine (GEL)\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_soundtrack.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t11/29/01\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXbox specific user soundtrack code\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n#include <core/macros.h>\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <sys/file/xbox/hed.h>\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n#include \"p_music.h\"\r\n#include \"p_soundtrack.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Pcm\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define MAX_SOUNDTRACKS\t100\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nXSOUNDTRACK_DATA\tsoundtrackData[MAX_SOUNDTRACKS];\r\nbool\t\t\t\tinitialised = false;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint gNumSoundtracks = 0;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint GetNumSoundtracks( void )\r\n{\r\n\tBOOL\t\t\t\trv;\r\n\tHANDLE\t\t\t\th_strack;\r\n\r\n\tif( initialised )\r\n\t{\r\n\t\treturn gNumSoundtracks;\r\n\t}\r\n\r\n\tinitialised\t\t= true;\r\n\tgNumSoundtracks\t= 0;\r\n\r\n\th_strack = XFindFirstSoundtrack( &soundtrackData[gNumSoundtracks] );\r\n\tif( h_strack != INVALID_HANDLE_VALUE )\r\n\t{\r\n\t\tdo\r\n\t\t{\r\n\t\t\t++gNumSoundtracks;\r\n\r\n\t\t\t// Don't go over the maximum (should be a system-limit of 100 anyway).\r\n\t\t\tif( gNumSoundtracks >= MAX_SOUNDTRACKS )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\trv = XFindNextSoundtrack( h_strack, &soundtrackData[gNumSoundtracks] );\r\n\t\t}\t\r\n\t\twhile( rv );\r\n\t}\r\n\r\n\treturn gNumSoundtracks;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst WCHAR* GetSoundtrackName( int soundtrack )\r\n{\r\n\tif( soundtrack < gNumSoundtracks )\r\n\t{\r\n\t\treturn soundtrackData[soundtrack].szName;\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nunsigned int GetSoundtrackNumSongs( int soundtrack )\r\n{\r\n\tif( soundtrack < gNumSoundtracks )\r\n\t{\r\n\t\treturn soundtrackData[soundtrack].uSongCount;\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst WCHAR* GetSongName( int soundtrack, int track )\r\n{\r\n\tstatic WCHAR wcSongName[MAX_SONG_NAME];\r\n\r\n\tif( soundtrack < gNumSoundtracks )\r\n\t{\r\n\t\t// Check the track is within limits.\r\n\t\tif((UINT)track < soundtrackData[soundtrack].uSongCount )\r\n\t\t{\r\n\t\t\tDWORD dwSongID;\r\n\t\t\tDWORD dwSongLength;\r\n\r\n\t\t\tBOOL rv = XGetSoundtrackSongInfo(\tsoundtrackData[soundtrack].uSoundtrackId,\r\n\t\t\t\t\t\t\t\t\t\t\t\ttrack,\r\n\t\t\t\t\t\t\t\t\t\t\t\t&dwSongID,\r\n\t\t\t\t\t\t\t\t\t\t\t\t&dwSongLength,\r\n\t\t\t\t\t\t\t\t\t\t\t\twcSongName,\r\n\t\t\t\t\t\t\t\t\t\t\t\tMAX_SONG_NAME );\r\n\r\n\t\t\tif( rv )\r\n\t\t\t{\r\n\t\t\t\treturn wcSongName;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nHANDLE GetSoundtrackWMAHandle( int soundtrack, int track )\r\n{\r\n\tif( soundtrack < gNumSoundtracks )\r\n\t{\r\n\t\t// Check the track is within limits.\r\n\t\tif((UINT)track < soundtrackData[soundtrack].uSongCount )\r\n\t\t{\r\n\t\t\tDWORD dwSongID;\r\n\t\t\tDWORD dwSongLength;\r\n\r\n\t\t\tBOOL rv = XGetSoundtrackSongInfo(\tsoundtrackData[soundtrack].uSoundtrackId,\r\n\t\t\t\t\t\t\t\t\t\t\t\ttrack,\r\n\t\t\t\t\t\t\t\t\t\t\t\t&dwSongID,\r\n\t\t\t\t\t\t\t\t\t\t\t\t&dwSongLength,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNULL,\r\n\t\t\t\t\t\t\t\t\t\t\t\t0 );\r\n\r\n\t\t\tif( rv )\r\n\t\t\t{\r\n\t\t\t\t// Second parameter is true for asynchronous mode reads.\r\n\t\t\t\tHANDLE h_song = XOpenSoundtrackSong( dwSongID, TRUE );\r\n\t\t\t\treturn h_song;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn INVALID_HANDLE_VALUE;\r\n}\r\n\r\n\r\n\r\n\r\n} // namespace PCM\r\n"
  },
  {
    "path": "Code/Gel/Music/Xbox/p_soundtrack.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGame Engine\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_soundtrack.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t11/29/2001\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __MODULES_P_SOUNDTRACK_H\r\n#define __MODULES_P_SOUNDTRACK_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Pcm\r\n{\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint\t\t\t\tGetNumSoundtracks( void );\r\nconst WCHAR*\tGetSoundtrackName( int soundtrack );\r\nunsigned int\tGetSoundtrackNumSongs( int soundtrack );\r\nconst WCHAR*\tGetSongName( int soundtrack, int track );\r\nHANDLE\t\t\tGetSoundtrackWMAHandle( int soundtrack, int track );\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Pcm\r\n\r\n#endif\t// __MODULES_P_SOUNDTRACK_H\r\n"
  },
  {
    "path": "Code/Gel/Music/Xbox/p_wmafilestream.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_wmafilestream.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/27/03\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXbox specific .wma streaming code\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n\r\n#include <core/macros.h>\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <core/crc.h>\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n#include \"p_music.h\"\r\n#include \"p_wmafilestream.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Pcm\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Define the source packet size:\r\n// This value is hard-coded assuming a WMA file of stero, 16bit resolution.  If\r\n// this value can by dynamically set based on the wma format, keeping in mind\r\n// that wma needs enough buffer for a minimum of 2048 samples worth of PCM data\r\n#define WMASTRM_SOURCE_PACKET_BYTES\t( 2048 * 2 * 2 )\r\n\r\n\r\n\r\n// This is a homegrown value which is used in conjunction with the existing\r\n// DSound packet status values. This indicates a packet which has been written\r\n// to, but which has not yet been submitted to the renderer. The low-order 24\r\n// bits contain a timestamp. Packets should be submitted lowest-timestamp first.\r\n#define XMEDIAPACKET_STATUS_AWAITING_RENDER\t\t0x40000000UL\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nuint32 CALLBACK WMAXMediaObjectDataCallback( LPVOID pContext, uint32 offset, uint32 num_bytes, LPVOID *ppData )\r\n{\r\n\tDbg_Assert( pContext != NULL );\r\n\tDbg_Assert( ppData != NULL );\r\n\r\n\tCWMAFileStream *p_this = (CWMAFileStream*)pContext;\r\n\tDbg_Assert(( p_this->m_DecoderCreation == 0 ) || ( p_this->m_DecoderCreation == 1 ));\r\n\r\n\t*ppData = (BYTE*)( p_this->m_pFileBuffer ) + ( offset % ( 8 * 8192 ));\r\n\r\n    // Update current progress.\r\n    p_this->m_FileBytesProcessed\t= offset;\r\n\r\n    return num_bytes;\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: CWMAFileStream()\r\n// Desc: Object constructor.\r\n//-----------------------------------------------------------------------------\r\nCWMAFileStream::CWMAFileStream( bool use_3d )\r\n{\r\n    m_pSourceFilter\t\t= NULL;\r\n    m_pRenderFilter\t\t= NULL;\r\n    m_pvSourceBuffer\t= NULL;\r\n    m_pFileBuffer\t\t= NULL;\r\n\tm_hFile\t\t\t\t= INVALID_HANDLE_VALUE;\r\n\tm_hThread\t\t\t= NULL;\r\n\tm_bUse3D\t\t\t= use_3d;\r\n\tm_bOkayToPlay\t\t= true;\r\n\r\n    for( uint32 i = 0; i < WMASTRM_PACKET_COUNT; i++ )\r\n\t{\r\n        m_adwPacketStatus[i] = XMEDIAPACKET_STATUS_SUCCESS;\r\n\t}\r\n\r\n    m_dwStartingDataOffset\t= 0;\r\n\tm_Completed\t\t\t\t= false;\r\n\tm_Paused\t\t\t\t= false;\r\n\r\n\t// Grab a pointer to the next overlapped structure.\r\n\tm_pOverlapped\t\t\t= PCMAudio_GetNextOverlapped();\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ~CWMAFileStream()\r\n// Desc: Object destructor.\r\n//-----------------------------------------------------------------------------\r\nCWMAFileStream::~CWMAFileStream()\r\n{\r\n\tif( m_hThread )\r\n\t{\r\n\t\tCloseHandle( m_hThread );\r\n\t}\r\n\t\r\n\t// If the file i/o is still active, we need to remove the event and close the file.\r\n\tif(( m_hFile != INVALID_HANDLE_VALUE ) && !m_bUseWAD )\r\n\t{\r\n\t\tCloseHandle( m_hFile );\r\n\t}\r\n\r\n    if( m_pSourceFilter )\r\n\t{\r\n\t\tm_pSourceFilter->Release();\r\n\t}\r\n\r\n    if( m_pRenderFilter )\r\n\t{\r\n\t\tm_pRenderFilter->Release();\r\n\t}\r\n\r\n\tif( m_pvSourceBuffer )\r\n\t{\r\n\t\tdelete[] m_pvSourceBuffer;\r\n\t}\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: AsyncRead()\r\n// Desc: Called while the async read is in progress. If the read is still\r\n//       underway, simply returns. If the read has completed, sets up the\r\n//       next read. If the file has been completely read, closes the file.\r\n//-----------------------------------------------------------------------------\r\nvoid CWMAFileStream::AsyncRead( void )\r\n{\r\n\tDbg_Assert( m_hFile != INVALID_HANDLE_VALUE );\r\n\r\n    // If paused, do nothing.\r\n\tif( m_Paused )\r\n\t{\r\n        return;\r\n    }\r\n\r\n    // See if the previous read is complete.\r\n\tuint32\tdwBytesTransferred;\r\n\tbool\tbIsReadDone = GetOverlappedResult( m_hFile, m_pOverlapped, &dwBytesTransferred, false );\r\n\tuint32\tdwLastError = GetLastError();\r\n\r\n    // If the read isn't complete, keep going.\r\n\tif( !bIsReadDone )\r\n\t{\r\n\t\tDbg_Assert( dwLastError == ERROR_IO_INCOMPLETE );\r\n\t\tif( dwLastError != ERROR_IO_INCOMPLETE )\r\n\t\t{\r\n\t\t\tm_AwaitingDeletion = true;\r\n\t\t}\r\n\t\treturn;\r\n    }\r\n\r\n    // If we get here, the read is complete.\r\n    m_pOverlapped->Offset\t+= dwBytesTransferred;\r\n\tm_FileBytesRead\t\t\t+= dwBytesTransferred;\r\n\r\n\t// If we just read to the first block in the buffer, copy to the extra block at the end, to ensure jitter-free playback.\r\n\tif(( m_SuccessiveReads & 0x07 ) == 0 )\r\n\t{\r\n\t\tCopyMemory((BYTE*)m_pFileBuffer + ( 8 * 8192 ), (BYTE*)m_pFileBuffer, 8192 );\r\n\t}\r\n\r\n\t++m_SuccessiveReads;\r\n\r\n#\tdefine BYTES_PER_CALL\t8192\r\n\r\n\tif( dwBytesTransferred < 8192 )\r\n\t{ \r\n\t\t// We've reached the end of the file during the call to ReadFile.\r\n\r\n        // Close the file (if not using the global WAD file).\r\n\t\tif( !m_bUseWAD )\r\n\t\t{\r\n\t\t\tbool bSuccess = CloseHandle( m_hFile );\r\n\t        Dbg_Assert( bSuccess );\r\n\t\t}\r\n\r\n        m_hFile = INVALID_HANDLE_VALUE;\r\n\r\n        // All done\r\n\t\tm_ReadComplete = true;\r\n    }\r\n    else\r\n    {\r\n\t\tif( m_bUseWAD && ( m_FileBytesRead >= (int)m_dwWADLength ))\r\n\t\t{\r\n\t\t\tm_hFile = INVALID_HANDLE_VALUE;\r\n\r\n\t\t\t// All done\r\n\t\t\tm_ReadComplete = true;\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\t// We still have more data to read. Start another asynchronous read from the file.\r\n\t\tbool bComplete\t= ReadFile( m_hFile, (BYTE*)m_pFileBuffer + ( m_FileBytesRead % ( 8 * 8192 )), BYTES_PER_CALL, NULL, m_pOverlapped );\r\n\t\tdwLastError\t\t= GetLastError();\r\n\r\n\t\t// Deal with hitting EOF (for files that are some exact multiple of 8192 bytes).\r\n\t\tif( bComplete || ( !bComplete && ( dwLastError == ERROR_HANDLE_EOF )))\r\n\t\t{\r\n\t\t\t// Close the file\r\n\t\t\tif( !m_bUseWAD )\r\n\t\t\t{\r\n\t\t\t\tbool bSuccess = CloseHandle( m_hFile );\r\n\t\t\t\tDbg_Assert( bSuccess );\r\n\t\t\t}\r\n\t\t\tm_hFile = INVALID_HANDLE_VALUE;\r\n\r\n\t\t\t// All done\r\n\t\t\tm_ReadComplete = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( bComplete || ( !bComplete && ( dwLastError == ERROR_IO_PENDING )), ( \"ReadFile error: %x\\n\", dwLastError ));\r\n\t\t\tif( !bComplete && ( dwLastError != ERROR_IO_PENDING ))\r\n\t\t\t{\r\n\t\t\t\t// There was a problem, so shut this stream down.\r\n\t\t\t\tm_AwaitingDeletion = true;\r\n\t\t\t}\r\n\t\t}\r\n    }\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Initialize()\r\n// Desc: Initializes the wave file streaming subsystem.\r\n//-----------------------------------------------------------------------------\r\nHRESULT CWMAFileStream::Initialize( HANDLE h_file, unsigned int offset, unsigned int length, void* fileBuffer )\r\n{\r\n    m_dwPercentCompleted = 0;\r\n    \r\n\t// At this stage we don't want to create the decoder or the stream. We do want to just allocate the read\r\n\t// buffer, and start pulling in the data. Once sufficient data has been grabbed, we can analyze the header\r\n\t// and create the required objects for playback.\r\n\tm_hFile\t\t\t= h_file;\r\n\tm_bUseWAD\t\t= true;\r\n\tm_dwWADOffset\t= offset;\t\r\n\tm_dwWADLength\t= length;\r\n\t\r\n\t// Grab a 72k (9 * 8k packets) read buffer. Must be uint32 aligned.\r\n\t// The last packet mirrors the first packet, for cases when the decoder reads past the end of the ring buffer.\r\n\tm_pFileBuffer = fileBuffer;\r\n\tDbg_Assert( uint32( m_pFileBuffer ) % sizeof( uint32 ) == 0 );\r\n\r\n\treturn PostInitialize();\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Initialize()\r\n// Desc: Initializes the wave file streaming subsystem.\r\n//-----------------------------------------------------------------------------\r\nHRESULT CWMAFileStream::Initialize( HANDLE h_song, void* fileBuffer )\r\n{\r\n    HRESULT\t\t\thr;\r\n\r\n    m_dwPercentCompleted = 0;\r\n    \r\n\t// At this stage we don't want to create the decoder or the stream. We do want to just allocate the read\r\n\t// buffer, and start pulling in the data. Once sufficient data has been grabbed, we can analyze the header\r\n\t// and create the required objects for playback.\r\n\tm_hFile = h_song;\r\n\tif( m_hFile == INVALID_HANDLE_VALUE )\r\n\t{\r\n\t\thr = HRESULT_FROM_WIN32( GetLastError());\r\n        return hr;\r\n    }\r\n\r\n\t// Grab a 72k (9 * 8k packets) read buffer. Must be uint32 aligned.\r\n\t// The last packet mirrors the first packet, for cases when the decoder reads past the end of the ring buffer.\r\n\tm_pFileBuffer = fileBuffer;\r\n\tDbg_Assert( uint32( m_pFileBuffer ) % sizeof( uint32 ) == 0 );\r\n\r\n\treturn PostInitialize();\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: PostInitialize()\r\n// Desc: Initialisation stuff following the file creation\r\n//-----------------------------------------------------------------------------\r\nHRESULT CWMAFileStream::PostInitialize( void )\r\n{\r\n\t// Start the asynchronous read from the start of the file.\r\n\tm_FirstRead\t\t\t\t= true;\r\n\tm_ReadComplete\t\t\t= false;\r\n\tm_FileBytesRead\t\t\t= 0;\r\n\tm_FileBytesProcessed\t= 0;\r\n\tm_SuccessiveReads\t\t= 0;\r\n\r\n\tif( m_bUseWAD )\r\n\t{\r\n\t\tm_pOverlapped->Offset\t= m_dwWADOffset;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_pOverlapped->Offset\t= 0;\r\n\t}\r\n\tm_pOverlapped->OffsetHigh\t= 0;\r\n\r\n\tbool bComplete = ReadFile( m_hFile, m_pFileBuffer, BYTES_PER_CALL, NULL, m_pOverlapped );\r\n\tif( !bComplete )\r\n\t{\r\n\t\tuint32 dwLastError = GetLastError();\r\n\t\tDbg_Assert( dwLastError == ERROR_IO_PENDING );\r\n\t\tif( dwLastError != ERROR_IO_PENDING )\r\n\t\t{\r\n\t\t\treturn HRESULT_FROM_WIN32( dwLastError );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_ReadComplete = true;\r\n\t}\r\n\r\n\t// That's it for now.\r\n    return S_OK;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: CreateSourceBuffer()\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nvoid CWMAFileStream::CreateSourceBuffer( void )\r\n{\r\n\t// Allocate data buffers. The source buffer holds the CPU decompressed packets ready to submit to the stream.\r\n\t// Explicitly allocate from the bottom up heap.\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().BottomUpHeap());\r\n\tm_pvSourceBuffer = new BYTE[WMASTRM_SOURCE_PACKET_BYTES * WMASTRM_PACKET_COUNT];\r\n\tMem::Manager::sHandle().PopContext();\r\n\tDbg_Assert( m_pvSourceBuffer != NULL );\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: PreLoadDone()\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nbool CWMAFileStream::PreLoadDone( void )\r\n{\r\n\tif( m_DecoderCreation == 1 )\r\n\t{\r\n\t\tif( m_ReadComplete || ( m_FileBytesRead >= ( m_FileBytesProcessed + 8192 )))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Process()\r\n// Desc: Performs any work necessary to keep the stream playing.\r\n//-----------------------------------------------------------------------------\r\nHRESULT CWMAFileStream::Process( void )\r\n{\r\n    HRESULT\t\t\thr;\r\n\tDSSTREAMDESC\tdssd;\r\n    uint32\t\t\tdwPacketIndex;\r\n    \r\n\t// Do nothing if waiting to die.\r\n\tif( m_AwaitingDeletion )\r\n\t{\r\n\t\treturn S_OK;\r\n\t}\r\n\r\n\t// Do we need to kick off another read of data? Don't read anymore if we have read ahead more than 32k.\r\n\tif( !m_ReadComplete )\r\n\t{\r\n\t\tif( m_FileBytesRead > ( m_FileBytesProcessed + 32768 ))\r\n\t\t{\r\n//\t\t\tOutputDebugString( \"waiting...\\n\" );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tAsyncRead();\r\n//\t\t\tOutputDebugString( \"reading...\\n\" );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tOutputDebugString( \"complete...\\n\" );\r\n\t}\r\n\r\n\t// Has the first block of raw data been read? If so we need to instantiate the playback objects and data buffers.\r\n\tif( m_FirstRead && ( m_FileBytesRead > 1024 ))\r\n\t{\r\n\t\tif( m_pSourceFilter == NULL )\r\n\t\t{\r\n\t\t\t// Create the thread which will create the in-memory decoder. \r\n\t\t\tm_DecoderCreation = 0;\r\n\r\n\t\t\tHRESULT hr = WmaCreateInMemoryDecoder(\tWMAXMediaObjectDataCallback,\t\t\t// Callback pointer.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tthis,\t\t\t\t\t\t\t\t\t// Callback context pointer.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t3,\t\t\t\t\t\t\t\t\t\t// Yield rate during decoding.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&m_wfxSourceFormat,\t\t\t\t\t\t// Source format description.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t(LPXMEDIAOBJECT*)&m_pSourceFilter );\t// Pointer to media object.\r\n\t\t\tif( FAILED( hr ))\r\n\t\t\t{\r\n\t\t\t\t// Signal a failed creation.\r\n\t\t\t\tm_DecoderCreation\t= 2;\r\n\t\t\t\tm_pSourceFilter\t\t= NULL;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_DecoderCreation\t= 1;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// That's all we can do until the decoder has been instantiated.\r\n\t\t}\r\n\r\n\t\tif( m_DecoderCreation == 0 )\r\n\t\t{\r\n\t\t\t// Still waiting to create decoder.\r\n\t\t\treturn S_OK;\r\n\t\t}\r\n\t\telse if( m_DecoderCreation == 2 )\r\n\t\t{\r\n\t\t\t// Failed to create decoder, just mark for deletion.\r\n\t\t\tm_AwaitingDeletion = true;\r\n\t\t\treturn S_OK;\r\n\t\t}\r\n\t\telse if( m_DecoderCreation == 1 )\r\n\t\t{\r\n\t\t\t// Managed to create decoder.\r\n\t\t\tDbg_Assert( m_pSourceFilter != NULL );\r\n\r\n\t\t\tm_FirstRead = false;\r\n\r\n\t\t\t// Create the render (DirectSoundStream) filter.\r\n\t\t\tDSMIXBINS\t\t\tdsmixbins;\r\n\t\t\tDSMIXBINVOLUMEPAIR\tdsmbvp[7];\r\n\t\t\tZeroMemory( &dssd, sizeof( dssd ));\r\n\r\n\t\t\tdssd.dwFlags\t\t\t\t\t= 0;\r\n\t\t\tdssd.dwMaxAttachedPackets\t\t= WMASTRM_PACKET_COUNT;\r\n\t\t\tdssd.lpwfxFormat\t\t\t\t= &m_wfxSourceFormat;\r\n\t\t\tdssd.lpMixBins\t\t\t\t\t= &dsmixbins;\r\n\r\n\t\t\tif( m_bUse3D )\r\n\t\t\t{\r\n\t\t\t\t// This is only designed to be fed a mono signal.\r\n\t\t\t\tDbg_Assert( m_wfxSourceFormat.nChannels == 1 );\r\n\r\n\t\t\t\tdsmixbins.dwMixBinCount\t\t\t= 6;\r\n\t\t\t\tdsmixbins.lpMixBinVolumePairs\t= dsmbvp;\r\n\t\t\t\tdsmbvp[0].dwMixBin\t\t\t\t= DSMIXBIN_3D_FRONT_LEFT;\r\n\t\t\t\tdsmbvp[0].lVolume\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\tdsmbvp[1].dwMixBin\t\t\t\t= DSMIXBIN_3D_FRONT_RIGHT;\r\n\t\t\t\tdsmbvp[1].lVolume\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\tdsmbvp[2].dwMixBin\t\t\t\t= DSMIXBIN_3D_BACK_LEFT;\r\n\t\t\t\tdsmbvp[2].lVolume\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\tdsmbvp[3].dwMixBin\t\t\t\t= DSMIXBIN_3D_BACK_RIGHT;\r\n\t\t\t\tdsmbvp[3].lVolume\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\tdsmbvp[4].dwMixBin\t\t\t\t= DSMIXBIN_FRONT_CENTER;\r\n\t\t\t\tdsmbvp[4].lVolume\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\tdsmbvp[5].dwMixBin\t\t\t\t= DSMIXBIN_I3DL2;\r\n\t\t\t\tdsmbvp[5].lVolume\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\r\n\t\t\t\tm_Mixbins\t\t\t\t\t\t= ( 1 << DSMIXBIN_3D_FRONT_LEFT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_3D_FRONT_RIGHT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_3D_BACK_LEFT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_3D_BACK_RIGHT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_FRONT_CENTER ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_I3DL2 );\r\n\t\t\t\tm_NumMixbins\t\t\t\t\t= dsmixbins.dwMixBinCount;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// If we are playing a music track, and if proper 5.1 output is selected, we want to feed the music to the left and\r\n\t\t\t\t// right back speakers with a slight echo via mixbins 5 and 6.\r\n\t\t\t\tif( XGetAudioFlags() & XC_AUDIO_FLAGS_ENABLE_AC3 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// This is only designed to be fed a stereo signal.\r\n\t\t\t\t\tDbg_Assert( m_wfxSourceFormat.nChannels == 2 );\r\n\r\n\t\t\t\t\tdsmixbins.dwMixBinCount\t\t\t= 4;\r\n\t\t\t\t\tdsmixbins.lpMixBinVolumePairs\t= dsmbvp;\r\n\t\t\t\t\tdsmbvp[0].dwMixBin\t\t\t\t= DSMIXBIN_FRONT_LEFT;\r\n\t\t\t\t\tdsmbvp[0].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\t\t\t\t\tdsmbvp[1].dwMixBin\t\t\t\t= DSMIXBIN_FRONT_RIGHT;\r\n\t\t\t\t\tdsmbvp[1].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\t\t\t\t\tdsmbvp[2].dwMixBin\t\t\t\t= DSMIXBIN_FXSEND_5;\r\n\t\t\t\t\tdsmbvp[2].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\t\t\t\t\tdsmbvp[3].dwMixBin\t\t\t\t= DSMIXBIN_FXSEND_6;\r\n\t\t\t\t\tdsmbvp[3].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\r\n\t\t\t\t\tm_Mixbins\t\t\t\t\t\t= ( 1 << DSMIXBIN_FRONT_LEFT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_FRONT_RIGHT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_FXSEND_5 ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_FXSEND_6 );\r\n\t\t\t\t\tm_NumMixbins\t\t\t\t\t= dsmixbins.dwMixBinCount;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// This is only designed to be fed a stereo signal.\r\n\t\t\t\t\tDbg_Assert( m_wfxSourceFormat.nChannels == 2 );\r\n\r\n\t\t\t\t\tdsmixbins.dwMixBinCount\t\t\t= 4;\r\n\t\t\t\t\tdsmixbins.lpMixBinVolumePairs\t= dsmbvp;\r\n\t\t\t\t\tdsmbvp[0].dwMixBin\t\t\t\t= DSMIXBIN_FRONT_LEFT;\r\n\t\t\t\t\tdsmbvp[0].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\t\t\t\t\tdsmbvp[1].dwMixBin\t\t\t\t= DSMIXBIN_FRONT_RIGHT;\r\n\t\t\t\t\tdsmbvp[1].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\t\t\t\t\tdsmbvp[2].dwMixBin\t\t\t\t= DSMIXBIN_BACK_LEFT;\r\n\t\t\t\t\tdsmbvp[2].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\t\t\t\t\tdsmbvp[3].dwMixBin\t\t\t\t= DSMIXBIN_BACK_RIGHT;\r\n\t\t\t\t\tdsmbvp[3].lVolume\t\t\t\t= DSBVOLUME_MIN;\r\n\r\n\t\t\t\t\tm_Mixbins\t\t\t\t\t\t= ( 1 << DSMIXBIN_FRONT_LEFT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_FRONT_RIGHT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_BACK_LEFT ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  ( 1 << DSMIXBIN_BACK_RIGHT );\r\n\t\t\t\t\tm_NumMixbins\t\t\t\t\t= dsmixbins.dwMixBinCount;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\thr = DirectSoundCreateStream( &dssd, &m_pRenderFilter );\r\n\t\t\tif( FAILED( hr ))\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\tm_pRenderFilter\t\t= NULL;\r\n\t\t\t\tm_AwaitingDeletion\t= true;\r\n\t\t\t\treturn S_OK;\r\n\t\t\t}\r\n\r\n\t\t\t// Set deferred volume if present.\r\n\t\t\tSetDeferredVolume();\r\n\r\n\t\t\t// Handle deferred pause.\r\n\t\t\tif( m_Paused )\r\n\t\t\t{\r\n\t\t\t\tm_pRenderFilter->Pause( DSSTREAMPAUSE_PAUSE );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// We only want to do processing when there is sufficient data available.\r\n\tif( m_ReadComplete || ( m_FileBytesRead >= ( m_FileBytesProcessed + 8192 )))\r\n\t{\r\n\t\tif( !m_Completed && m_pSourceFilter && m_pRenderFilter )\r\n\t\t{\r\n\t\t\t// Find a free packet. If there's none free, we don't have anything to do.\r\n\t\t\tif( FindFreePacket( &dwPacketIndex ))\r\n\t\t\t{\r\n\t\t\t\t// Read from the source filter.\r\n\t\t\t\thr = ProcessSource( dwPacketIndex );\r\n\t\t\t\tif( FAILED( hr ) )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn hr;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Don't want to submit if we're paused, or we're flagged not to play. (Flagging is used to allow\r\n\t\t\t// the stream to be spooled up ready to play instantly when triggered).\r\n\t\t\tif(( !m_Paused ) && m_bOkayToPlay )\r\n\t\t\t{\r\n\t\t\t\tif( FindRenderablePacket( &dwPacketIndex ))\r\n\t\t\t\t{\r\n\t\t\t\t\t// Send the data to the renderer\r\n\t\t\t\t\thr = ProcessRenderer( dwPacketIndex );\r\n\t\t\t\t\tif( FAILED( hr ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t return hr;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n    return S_OK;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: FindFreePacket()\r\n// Desc: Finds a render packet available for processing.\r\n//-----------------------------------------------------------------------------\r\nbool CWMAFileStream::FindFreePacket( uint32* pdwPacketIndex )\r\n{\r\n    for( uint32 dwPacketIndex = 0; dwPacketIndex < WMASTRM_PACKET_COUNT; ++dwPacketIndex )\r\n    {\r\n\t\tif(( m_adwPacketStatus[dwPacketIndex] != XMEDIAPACKET_STATUS_PENDING ) &&\r\n\t\t   (( m_adwPacketStatus[dwPacketIndex] & XMEDIAPACKET_STATUS_AWAITING_RENDER ) != XMEDIAPACKET_STATUS_AWAITING_RENDER ))\r\n        {\r\n            if( pdwPacketIndex )\r\n\t\t\t{\r\n\t\t\t\t*pdwPacketIndex = dwPacketIndex;\r\n\r\n\t\t\t\t// Mark this packet as awaiting rendering.\r\n\t\t\t\tuint32 timestamp = (uint32)Tmr::GetVblanks();\r\n\t\t\t\tm_adwPacketStatus[dwPacketIndex] = XMEDIAPACKET_STATUS_AWAITING_RENDER | ( timestamp & 0xFFFFFFUL );\r\n\t\t\t}\r\n            return true;\r\n        }\r\n    }\r\n    return false;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: FindFreePacket()\r\n// Desc: Finds a render packet available for rendering.\r\n//-----------------------------------------------------------------------------\r\nbool CWMAFileStream::FindRenderablePacket( uint32* pdwPacketIndex )\r\n{\r\n\t// Found nothing yet.\r\n\tuint32 lowest_timestamp\t= 0xFFFFFFUL;\r\n\tuint32 lowest_index\t\t= WMASTRM_PACKET_COUNT;\r\n\r\n\tfor( uint32 dwPacketIndex = 0; dwPacketIndex < WMASTRM_PACKET_COUNT; ++dwPacketIndex )\r\n    {\r\n\t\tif(( m_adwPacketStatus[dwPacketIndex] & XMEDIAPACKET_STATUS_AWAITING_RENDER ) == XMEDIAPACKET_STATUS_AWAITING_RENDER )\r\n        {\r\n\t\t\tuint32 timestamp = m_adwPacketStatus[dwPacketIndex] & 0xFFFFFFUL;\r\n\t\t\tif( timestamp < lowest_timestamp )\r\n\t\t\t{\r\n\t\t\t\tlowest_timestamp\t= timestamp;\r\n\t\t\t\tlowest_index\t\t= dwPacketIndex;\r\n\t\t\t}\r\n\t\t}\r\n    }\r\n\r\n\t// If we found a packet, return its index.\r\n\tif( lowest_index < WMASTRM_PACKET_COUNT )\r\n\t{\r\n\t\tif( pdwPacketIndex )\r\n\t\t{\r\n\t\t\t*pdwPacketIndex = lowest_index;\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// No packets awaiting rendering.\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ProcessSource()\r\n// Desc: Reads data from the source filter.\r\n//-----------------------------------------------------------------------------\r\nHRESULT CWMAFileStream::ProcessSource( uint32 dwPacketIndex )\r\n{\r\n    uint32        dwTotalSourceUsed   = 0;\r\n    uint32        dwSourceUsed;\r\n    XMEDIAPACKET xmp;\r\n    HRESULT      hr;\r\n    \r\n\tif( m_pvSourceBuffer == NULL )\r\n\t{\r\n\t\tCreateSourceBuffer();\r\n\t}\r\n    \r\n\t// We're going to read a full packet's worth of data into the source buffer.\r\n    ZeroMemory( &xmp, sizeof( xmp ));\r\n    xmp.pvBuffer         = (BYTE*)m_pvSourceBuffer + (dwPacketIndex * WMASTRM_SOURCE_PACKET_BYTES);\r\n    xmp.dwMaxSize        = WMASTRM_SOURCE_PACKET_BYTES;\r\n    xmp.pdwCompletedSize = &dwSourceUsed;\r\n\r\n\t// Read from the source.\r\n\thr = m_pSourceFilter->Process( NULL, &xmp );\r\n\tif( FAILED( hr ))\r\n\t{\r\n\t\treturn hr;\r\n\t}\r\n\r\n\t// Add the amount read to the total\r\n\tdwTotalSourceUsed += dwSourceUsed;\r\n\r\n\t// If we read less than the amount requested, it's because we hit the end of the file.\r\n    if( dwSourceUsed < xmp.dwMaxSize )\r\n\t{\r\n\t\t// Set completion flag.\r\n\t\tm_Completed = true;\r\n\r\n\t\t// Zero remaining part of packet.\r\n\t\txmp.pvBuffer  = (BYTE*)xmp.pvBuffer + dwSourceUsed;\r\n\t\txmp.dwMaxSize = xmp.dwMaxSize - dwSourceUsed;\r\n\t\tZeroMemory( xmp.pvBuffer, xmp.dwMaxSize );\r\n\t}\r\n\r\n    return S_OK;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ProcessRenderer()\r\n// Desc: Sends data to the renderer.\r\n//-----------------------------------------------------------------------------\r\nHRESULT CWMAFileStream::ProcessRenderer( uint32 dwPacketIndex )\r\n{\r\n    XMEDIAPACKET xmp;\r\n    HRESULT      hr;\r\n\r\n\tDbg_Assert( m_pvSourceBuffer != NULL );\r\n\r\n\t// There's a full packet's worth of data ready for us to send to the renderer.  We want to track the status\r\n\t// of this packet since the render filter is asychronous and we need to know when the packet is completed.\r\n    ZeroMemory( &xmp, sizeof( xmp ));\r\n    xmp.pvBuffer  = (BYTE*)m_pvSourceBuffer + ( dwPacketIndex * WMASTRM_SOURCE_PACKET_BYTES );\r\n    xmp.dwMaxSize = WMASTRM_SOURCE_PACKET_BYTES;\r\n    xmp.pdwStatus = &m_adwPacketStatus[dwPacketIndex];\r\n\r\n\tif( m_Completed )\r\n\t{\r\n\t\t// Store index of last packet, since we will need to test the status of this for proper completion test.\r\n\t\tm_LastPacket = dwPacketIndex;\r\n\t}\r\n\r\n    hr = m_pRenderFilter->Process( &xmp, NULL );\r\n\r\n\tif( m_Completed )\r\n\t{\r\n\t\t// Tell the renderer not to expect any more data.\r\n\t\tm_pRenderFilter->Discontinuity();\r\n\t}\r\n\t\r\n\tif( FAILED( hr ))\r\n\t{\r\n\t\treturn hr;\r\n\t}\r\n\t\r\n\treturn S_OK;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Pause\r\n// Desc: Pauses and resumes stream playback\r\n//-----------------------------------------------------------------------------\r\nvoid CWMAFileStream::Pause( uint32 dwPause )\r\n{\r\n\tm_Paused = ( dwPause > 0 );\r\n\r\n\t// Possible that the render filter hasn't been created yet.\r\n\tif( m_pRenderFilter )\r\n\t{\r\n\t\tm_pRenderFilter->Pause(( dwPause > 0 ) ? DSSTREAMPAUSE_PAUSE : DSSTREAMPAUSE_RESUME );\r\n\t}\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: SetVolume\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nvoid CWMAFileStream::SetVolume( float volume )\r\n{\r\n\tif( m_pRenderFilter )\r\n\t{\r\n\t\tint i_volume\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\tint i_volume_rear\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\tif( volume > 0.0f )\r\n\t\t{\r\n\t\t\t// Figure base volume.\r\n\t\t\tfloat attenuation\t= 20.0f * log10f( volume * 0.01f );\r\n\t\t\ti_volume\t\t\t= DSBVOLUME_MAX + (int)( attenuation * 100.0f );\r\n\t\t\tif( i_volume < DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t\t\ti_volume = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\telse if( i_volume > DSBVOLUME_MAX )\r\n\t\t\t\ti_volume = DSBVOLUME_MAX;\r\n\r\n\t\t\t// Also figure half volume, in case we are routing to the back speakers.\r\n\t\t\tattenuation\t\t\t= 20.0f * log10f( volume * 0.5f * 0.01f );\r\n\t\t\ti_volume_rear\t\t= DSBVOLUME_MAX + (int)( attenuation * 100.0f );\r\n\t\t\tif( i_volume_rear < DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t\t\ti_volume_rear = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\telse if( i_volume_rear > DSBVOLUME_MAX )\r\n\t\t\t\ti_volume_rear = DSBVOLUME_MAX;\r\n\t\t}\r\n\t\t\r\n\t\t// Set individual mixbins for panning.\r\n\t\tDSMIXBINS\t\t\tdsmixbins;\r\n\t\tDSMIXBINVOLUMEPAIR\tdsmbvp[DSMIXBIN_ASSIGNMENT_MAX];\r\n\r\n\t\tdsmixbins.dwMixBinCount\t\t\t= 0;\r\n\t\tdsmixbins.lpMixBinVolumePairs\t= dsmbvp;\r\n\r\n\t\tif( i_volume > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n\t\t\t// Set the volume up depending on how the initial mixbins were set up.\r\n\t\t\tint mbbf = 0;\r\n\t\t\tfor( uint32 mb = 0; mb < m_NumMixbins; ++mb )\r\n\t\t\t{\r\n\t\t\t\twhile(( m_Mixbins & ( 1 << mbbf )) == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t++mbbf;\r\n\t\t\t\t\tDbg_Assert( mbbf < 32 );\r\n\t\t\t\t}\r\n\t\t\t\tdsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= mbbf;\r\n\r\n\t\t\t\t// For rear speakers (or mixbins that route to the rear), use half volume.\r\n\t\t\t\tif(( mbbf == DSMIXBIN_FXSEND_5 ) || ( mbbf == DSMIXBIN_FXSEND_6 ) || ( mbbf == DSMIXBIN_BACK_LEFT ) || ( mbbf == DSMIXBIN_BACK_RIGHT ))\r\n\t\t\t\t{\r\n\t\t\t\t\tdsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volume_rear;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tdsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volume;\r\n\t\t\t\t}\r\n\t\t\t\t++dsmixbins.dwMixBinCount;\r\n\t\t\t\t++mbbf;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Set all speaker volumes.\r\n\t\tm_pRenderFilter->SetMixBinVolumes( &dsmixbins );\r\n\r\n\t\t// Set overall buffer volume.\r\n\t\tif( dsmixbins.dwMixBinCount > 0 )\r\n\t\t{\r\n\t\t\tm_pRenderFilter->SetVolume( DSBVOLUME_MAX );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_pRenderFilter->SetVolume( DSBVOLUME_MIN );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_SetDeferredVolume = true;\r\n\t\tm_DeferredVolume[0]\t= volume;\r\n\t}\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: SetVolume\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nvoid CWMAFileStream::SetVolume( float volL, float volR )\r\n{\r\n\tif( m_pRenderFilter )\r\n\t{\r\n\t\t// This array will hold individual volumes for the five speakers.\r\n\t\t// In order, they are: front left, center, front right, rear right, rear left.\r\n\t\tfloat\tvolumes[5];\r\n\t\tint\t\ti_volumes[5], max_i_volume;\r\n\t\tmemset( volumes, 0, sizeof( float ) * 5 );\r\n\t\t\r\n\t\tif(( volL == 0.0f ) && ( volR == 0.0f ))\r\n\t\t{\r\n\t\t\t// Pointless doing any more work.\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Get the length of the vector here which will be used to multiply out the normalised speaker volumes.\r\n\t\t\tMth::Vector test( fabsf( volL ), fabsf( volR ), 0.0f, 0.0f );\r\n\t\t\tfloat amplitude = test.Length();\r\n\r\n\t\t\t// Look just at the normalized right component to figure the sound angle from Matt's calculations.\r\n\t\t\ttest.Normalize();\r\n\r\n\t\t\tfloat angle;\r\n\t\t\tangle\t= asinf( test[Y] );\r\n\t\t\tangle\t= ( angle * 2.0f ) - ( Mth::PI * 0.5f );\r\n\t\t\tangle\t= ( volL < 0.0f ) ? ( Mth::PI - angle ) : angle;\r\n\t\t\r\n\t\t\t// Now figure volumes based on speaker coverage.\r\n\t\t\tangle\t= Mth::RadToDeg( angle );\r\n\t\t\r\n\t\t\tSpt::SingletonPtr< Sfx::CSfxManager > sfx_manager;\r\n\t\t\tsfx_manager->Get5ChannelMultipliers( angle, &volumes[0] );\r\n\r\n\t\t\t// Now readjust the relative values...\r\n\t\t\tfor( int v = 0; v < 5; ++v )\r\n\t\t\t{\r\n\t\t\t\t// Scale back up to original amplitude.\r\n\t\t\t\tvolumes[v] *= amplitude;\r\n\r\n\t\t\t\tif( volumes[v] > 100.0f )\r\n\t\t\t\t\tvolumes[v] = 100.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Now figure the attenuation of the sound. To convert to a decibel value, figure the ratio of requested\r\n\t\t// volume versus max volume, then calculate the log10 and multiply by (10 * 2). (The 2 is because sound\r\n\t\t// power varies as square of pressure, and squaring doubles the log value).\r\n\t\tmax_i_volume = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\tfor( int v = 0; v < 5; ++v )\r\n\t\t{\r\n\t\t\tif( volumes[v] > 0.0f )\r\n\t\t\t{\r\n\t\t\t\tfloat attenuation\t= 20.0f * log10f( volumes[v] * 0.01f );\r\n\t\t\t\ti_volumes[v]\t\t= DSBVOLUME_MAX + (int)( attenuation * 100.0f );\r\n\t\t\t\tif( i_volumes[v] < DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t\t\t\ti_volumes[v] = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\telse if( i_volumes[v] > DSBVOLUME_MAX )\r\n\t\t\t\t\ti_volumes[v] = DSBVOLUME_MAX;\r\n\r\n\t\t\t\tif( i_volumes[v] > max_i_volume )\r\n\t\t\t\t\tmax_i_volume = i_volumes[v];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ti_volumes[v] = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Set individual mixbins for panning.\r\n\t\tDSMIXBINS\t\t\tdsmixbins;\r\n\t\tDSMIXBINVOLUMEPAIR\tdsmbvp[DSMIXBIN_ASSIGNMENT_MAX];\r\n\r\n\t\tdsmixbins.dwMixBinCount\t\t\t= 0;\r\n\t\tdsmixbins.lpMixBinVolumePairs\t= dsmbvp;\r\n\r\n\t\tif( i_volumes[0] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_FRONT_LEFT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[0];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[1] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_FRONT_RIGHT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[1];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[2] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_BACK_LEFT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[2];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[3] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_BACK_RIGHT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[3];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[4] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_FRONT_CENTER;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[4];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( dsmixbins.dwMixBinCount > 0 )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_I3DL2;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= DSBVOLUME_MAX;\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\r\n\t\t// Set all speaker volumes.\r\n\t\tm_pRenderFilter->SetMixBinVolumes( &dsmixbins );\r\n\r\n\t\t// Set overall buffer volume.\r\n\t\tif( dsmixbins.dwMixBinCount > 0 )\r\n\t\t{\r\n\t\t\tm_pRenderFilter->SetVolume( DSBVOLUME_MAX );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_pRenderFilter->SetVolume( DSBVOLUME_MIN );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_SetDeferredVolumeLR\t= true;\r\n\t\tm_DeferredVolume[0]\t\t= volL;\r\n\t\tm_DeferredVolume[1]\t\t= volR;\r\n\t}\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: SetVolume\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nvoid CWMAFileStream::SetVolume( float v0, float v1, float v2, float v3, float v4 )\r\n{\r\n\tif( m_pRenderFilter )\r\n\t{\r\n\t\tfloat volumes[5];\r\n\t\tvolumes[0] = ( v0 > 100.0f ) ? 100.0f : v0;\r\n\t\tvolumes[1] = ( v1 > 100.0f ) ? 100.0f : v1;\r\n\t\tvolumes[2] = ( v2 > 100.0f ) ? 100.0f : v2;\r\n\t\tvolumes[3] = ( v3 > 100.0f ) ? 100.0f : v3;\r\n\t\tvolumes[4] = ( v4 > 100.0f ) ? 100.0f : v4;\r\n\r\n\t\tint i_volumes[5], max_i_volume;\r\n\r\n\t\t// Now figure the attenuation of the sound. To convert to a decibel value, figure the ratio of requested\r\n\t\t// volume versus max volume, then calculate the log10 and multiply by (10 * 2). (The 2 is because sound\r\n\t\t// power varies as square of pressure, and squaring doubles the log value).\r\n\t\tmax_i_volume = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\tfor( int v = 0; v < 5; ++v )\r\n\t\t{\r\n\t\t\tif( volumes[v] > 0.0f )\r\n\t\t\t{\r\n\t\t\t\tfloat attenuation\t= 20.0f * log10f( volumes[v] * 0.01f );\r\n\t\t\t\ti_volumes[v]\t\t= DSBVOLUME_MAX + (int)( attenuation * 100.0f );\r\n\t\t\t\tif( i_volumes[v] < DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t\t\t\ti_volumes[v] = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t\telse if( i_volumes[v] > DSBVOLUME_MAX )\r\n\t\t\t\t\ti_volumes[v] = DSBVOLUME_MAX;\r\n\r\n\t\t\t\tif( i_volumes[v] > max_i_volume )\r\n\t\t\t\t\tmax_i_volume = i_volumes[v];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ti_volumes[v] = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Set individual mixbins for panning.\r\n\t\tDSMIXBINS\t\t\tdsmixbins;\r\n\t\tDSMIXBINVOLUMEPAIR\tdsmbvp[DSMIXBIN_ASSIGNMENT_MAX];\r\n\r\n\t\tdsmixbins.dwMixBinCount\t\t\t= 0;\r\n\t\tdsmixbins.lpMixBinVolumePairs\t= dsmbvp;\r\n\r\n\t\tif( i_volumes[0] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_FRONT_LEFT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[0];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[1] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_FRONT_RIGHT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[1];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[2] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_BACK_LEFT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[2];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[3] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_BACK_RIGHT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[3];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( i_volumes[4] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_FRONT_CENTER;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[4];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\t\tif( dsmixbins.dwMixBinCount > 0 )\r\n\t\t{\r\n\t\t\tdsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_I3DL2;\r\n\t\t\tdsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= DSBVOLUME_MAX;\r\n\t\t\tdsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\r\n\t\t// Set all speaker volumes.\r\n\t\tm_pRenderFilter->SetMixBinVolumes( &dsmixbins );\r\n\r\n\t\t// Set overall buffer volume.\r\n\t\tif( dsmixbins.dwMixBinCount > 0 )\r\n\t\t{\r\n\t\t\tm_pRenderFilter->SetVolume( DSBVOLUME_MAX );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_pRenderFilter->SetVolume( DSBVOLUME_MIN );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_SetDeferredVolume5Channel\t= true;\r\n\t\tm_DeferredVolume[0]\t\t\t= v0;\r\n\t\tm_DeferredVolume[1]\t\t\t= v1;\r\n\t\tm_DeferredVolume[2]\t\t\t= v2;\r\n\t\tm_DeferredVolume[3]\t\t\t= v3;\r\n\t\tm_DeferredVolume[4]\t\t\t= v4;\r\n\t}\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: SetDeferredVolume\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nvoid CWMAFileStream::SetDeferredVolume( void )\r\n{\r\n\tif( m_SetDeferredVolume )\r\n\t{\r\n\t\tm_SetDeferredVolume = false;\r\n\t\tSetVolume( m_DeferredVolume[0] );\r\n\t}\r\n\r\n\tif( m_SetDeferredVolumeLR )\r\n\t{\r\n\t\tm_SetDeferredVolumeLR = false;\r\n\t\tSetVolume( m_DeferredVolume[0], m_DeferredVolume[1] );\r\n\t}\r\n\r\n\tif( m_SetDeferredVolume5Channel )\r\n\t{\r\n\t\tm_SetDeferredVolume5Channel = false;\r\n\t\tSetVolume( m_DeferredVolume[0], m_DeferredVolume[1], m_DeferredVolume[2], m_DeferredVolume[3], m_DeferredVolume[4] );\r\n\t}\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: IsSafeToDelete\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nbool CWMAFileStream::IsSafeToDelete( void )\r\n{\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: WMAFileStreamThreadProc\r\n//-----------------------------------------------------------------------------\r\nuint32 WINAPI WMAFileStreamThreadProc( LPVOID lpParameter )\r\n{\r\n\tCWMAFileStream*\tp_filestream = (CWMAFileStream*)lpParameter;\r\n\r\n\tDbg_Assert( p_filestream->m_DecoderCreation == 0 );\r\n\r\n\t// Create the memory-based XMO.\r\n\tHRESULT hr = WmaCreateInMemoryDecoder(\tWMAXMediaObjectDataCallback,\t\t\t\t\t\t// Callback pointer.\r\n\t\t\t\t\t\t\t\t\t\t\tp_filestream,\t\t\t\t\t\t\t\t\t\t// Callback context pointer.\r\n\t\t\t\t\t\t\t\t\t\t\t3,\t\t\t\t\t\t\t\t\t\t\t\t\t// Yield rate during decoding.\r\n\t\t\t\t\t\t\t\t\t\t\t&p_filestream->m_wfxSourceFormat,\t\t\t\t\t// Source format description.\r\n\t\t\t\t\t\t\t\t\t\t\t(LPXMEDIAOBJECT*)&p_filestream->m_pSourceFilter );\t// Pointer to media object.\r\n\tif( FAILED( hr ))\r\n\t{\r\n\t\t// Signal a failed creation.\r\n\t\tp_filestream->m_DecoderCreation\t= 2;\r\n\t\tp_filestream->m_pSourceFilter\t= NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_filestream->m_DecoderCreation\t= 1;\r\n\t}\r\n\r\n\t// Terminate the thread.\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n\r\n} // namespace PCM\r\n"
  },
  {
    "path": "Code/Gel/Music/Xbox/p_wmafilestream.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGame Engine\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_wmafilesteam.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t01/27/2003\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __P_WMAFILESTREAM_H\r\n#define __P_WMAFILESTREAM_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Define the maximum amount of packets we will ever submit to the renderer.\r\n#define WMASTRM_PACKET_COUNT\t\t8\r\n\r\nnamespace Pcm\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* WMA file streaming object, designed for fully asynchronous\t  */\r\n/* streaming from disc.\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Note that WMA decompression does incur a CPU overhead.\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nclass CWMAFileStream : public Spt::Class\r\n{\r\n\tprivate:\r\n\r\n\tHANDLE\t\t\t\tm_hFile;\r\n\tHANDLE\t\t\t\tm_hThread;\r\n\tOVERLAPPED*\t\t\tm_pOverlapped;\t\t\t\t\t\t\t// OVERLAPPED structure for asynchronous file access.\r\n\tbool\t\t\t\tm_FirstRead;\t\t\t\t\t\t\t// Flag to indicate first request for more data to be streamed from disc.\r\n\tbool\t\t\t\tm_ReadComplete;\r\n\tint\t\t\t\t\tm_SuccessiveReads;\t\t\t\t\t\t// Counts how many read operations performed in total.\r\n\tbool\t\t\t\tm_bUseWAD;\r\n\tbool\t\t\t\tm_bUse3D;\t\t\t\t\t\t\t\t// Sets whether 2D or 3D mixbins are set up.\r\n\tuint32\t\t\t\tm_dwWADOffset;\t\r\n\tuint32\t\t\t\tm_dwWADLength;\r\n\r\n\tpublic:\r\n\r\n    IDirectSoundStream* m_pRenderFilter;                         // Render (DirectSoundStream) filter\r\n    LPVOID              m_pvSourceBuffer;                        // Source filter data buffer\r\n    LPVOID              m_pvRenderBuffer;                        // Render filter data buffer\r\n    uint32\t\t\t\tm_adwPacketStatus[WMASTRM_PACKET_COUNT]; // Packet status array\r\n    uint32\t\t\t\tm_dwStartingDataOffset;                  // Offset into wma file where data begins.\r\n    uint32\t\t\t\tm_dwPercentCompleted;\t\t\t\t\t // Percent completed\r\n\tbool\t\t\t\tm_Paused;\r\n\tbool\t\t\t\tm_Completed;\t\t\t\t\t\t\t// For single-shot, indicates loading of final packet to renderer is completed\r\n    uint32\t\t\t\tm_LastPacket;\t\t\t\t\t\t\t// Last packet array index\r\n\tbool\t\t\t\tm_SetDeferredVolume;\r\n\tbool\t\t\t\tm_SetDeferredVolumeLR;\r\n\tbool\t\t\t\tm_SetDeferredVolume5Channel;\r\n\tbool\t\t\t\tm_bOkayToPlay;\t\t\t\t\t\t\t// Used when exact syncing is required - will load buffers but won't start decompression until this flag is true.\r\n\tfloat\t\t\t\tm_DeferredVolume[5];\r\n\tuint32\t\t\t\tm_Mixbins;\t\t\t\t\t\t\t\t// Bitfield indicating which mixbins are active for this buffer.\r\n\tuint32\t\t\t\tm_NumMixbins;\r\n\r\n    // Packet processing\r\n    bool\t\t\t\tFindFreePacket( uint32* pdwPacketIndex );\r\n\tbool\t\t\t\tFindRenderablePacket( uint32* pdwPacketIndex );\r\n    HRESULT\t\t\t\tProcessSource( uint32 dwPacketIndex );\r\n    HRESULT\t\t\t\tProcessRenderer( uint32 dwPacketIndex );\r\n\r\n\tWAVEFORMATEX\t\tm_wfxSourceFormat;\r\n    XFileMediaObject*   m_pSourceFilter;\t\t\t\t\t\t\t// Source (wave file) filter\r\n\tLPVOID\t\t\t\tm_pFileBuffer;\t\t\t\t\t\t\t\t// Buffer for async read of raw data.\r\n\tint\t\t\t\t\tm_FileBytesRead;\t\t\t\t\t\t\t// Total number of raw bytes read from disc.\r\n\tint\t\t\t\t\tm_FileBytesProcessed;\t\t\t\t\t\t// Total number of raw bytes processed by XMO.\r\n\tint\t\t\t\t\tm_DecoderCreation;\r\n\tbool\t\t\t\tm_AwaitingDeletion;\r\n\r\n    // Processing\r\n    HRESULT\t\t\t\tProcess();\r\n\r\n    // Initialization\r\n    HRESULT\t\t\t\tInitialize( HANDLE h_file, unsigned int offset, unsigned int length, void* fileBuffer );\r\n    HRESULT\t\t\t\tInitialize( HANDLE h_file, void* fileBuffer );\r\n\tHRESULT\t\t\t\tPostInitialize( void );\r\n\tvoid\t\t\t\tCreateSourceBuffer( void );\r\n    \r\n    // Play control\r\n    void\t\t\t\tPause( uint32 dwPause );\r\n\tvoid\t\t\t\tSetVolume( float volume );\r\n\tvoid\t\t\t\tSetVolume( float volumeL, float volumeR );\r\n\tvoid\t\t\t\tSetVolume( float v0, float v1, float v2, float v3, float v4 );\r\n\tvoid\t\t\t\tSetDeferredVolume( void );\r\n\r\n\t// Query\r\n\tIDirectSoundStream*\tGetSoundStream( void )\t\t\t\t\t{ return m_pRenderFilter; }\r\n\tbool\t\t\t\tIsCompleted( void )\t\t\t\t\t\t{ return ( m_Completed && ( XMEDIAPACKET_STATUS_PENDING != m_adwPacketStatus[m_LastPacket] )); }\r\n\tbool\t\t\t\tIsSafeToDelete( void );\r\n\tbool\t\t\t\tPreLoadDone( void );\r\n\r\n\t// Asynchronous stuff.\r\n\tvoid\t\t\t\tAsyncRead( void );\r\n\r\n\r\n    CWMAFileStream( bool use_3d = false );\r\n    ~CWMAFileStream();\r\n};\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Pcm\r\n\r\n#endif\t// __P_WMAFILESTREAM_H\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/music.cpp",
    "content": "/*  \r\n\tMusic.cpp -- highest level\r\n\tp_music.cpp -- platform specific\r\n\tpcm*.c --  the code that runs on the IOP.\r\n\t\r\n\tThis module should actually be renamed now, as it isn't just for\r\n\tmusic any more!\r\n\r\n\tThis module should be called Streaming.cpp.\r\n\t\r\n\tThis module handles streaming music, and soundfx.\r\n\t\r\n\tThe stream data is read into IOP memory from the DVD, into a\r\n\tdouble buffer in IOP memory, about once every three seconds.\r\n\t\r\n\tThe IOP chip has a thread that is running on a timer interrupt (see the pcm\r\n\tcode, which compiles as an IOP module EzPcm.irx).  60 times per second,\r\n\tthis thread updates small areas of memory on the SPU2 chip -- double\r\n\tbuffers for each stream that need updating approximately every second\r\n\tand a half (or longer if the pitch has been turned down lower).\r\n\r\n\tThese voices work just like the other voices for soundfx, except that they\r\n\tloop over a small area that is updated with the sound data streaming off\r\n\tthe DVD.  You can change the pitch and volume of these voices on the fly\r\n\tjust like soundFX, so streaming sounds can be adjusted positionally over time.\r\n\r\n\tOh, yeah, just one more thing:  yo mamma, yo pappa, yo greasy bald gradma!\r\n*/\r\n\r\n#include <core/defines.h>\r\n#include <core/macros.h>\r\n#include <core/singleton.h>\r\n#include <core/math.h>\r\n\r\n#include <sys/timer.h>\r\n#include <sys/config/config.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/music/music.h>\r\n#include <gel/components/streamcomponent.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n\r\n#include <gfx/debuggfx.h>\r\n\r\n#ifdef __PLAT_NGPS__\r\n#include <gel/music/ngps/p_music.h>\r\n#include <gel/music/ngps/pcm/pcm.h>\r\n#elif defined( __PLAT_XBOX__ )\r\n#include <gel/music/xbox/p_music.h>\r\n#include <gel/music/xbox/p_soundtrack.h>\r\n#elif defined( __PLAT_NGC__ )\r\n#include <gel/music/ngc/p_music.h>\r\n#include <gel/music/ngc/pcm/pcm.h>\r\n#endif\r\n#include <sys/config/config.h>\r\n#include <sys/replay/replay.h>\r\n#include <sys/file/asyncfilesys.h>\r\n\r\n#define TEST_FROM_CD 0\r\n#define WAIT_AFTER_STOP_STREAM\t\t0\t\t// Set to 1 if we need to wait for stream to clear after stopping a stream\r\n\r\nnamespace Pcm\r\n{\r\n\r\nstatic bool music_hed_there = true;\t\t// assume music and streams are there to start with, so we can load the hed\r\nstatic bool streams_hed_there = true;\t// if hed is not there, then these get set to false\r\n\t\t\t\t\t\t\t\t\t\t// which will disable all music and/or streams.\r\n\r\nbool NoMusicPlease()\r\n{\r\n\t#if NO_MUSIC_PLEASE\r\n\treturn true;\r\n\t#else\r\n\t// Cannot have music if building for proview, because there is not enough IOP memory\r\n\t// (ProView uses up some IOP memory with it's monitor)\r\n\tif (Config::GetHardware()==Config::HARDWARE_PS2_PROVIEW)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn !music_hed_there;\t\r\n\t#endif\r\n}\r\n\r\nbool StreamsDisabled()\r\n{\r\n\t#if DISABLE_STREAMS\r\n\treturn true;\r\n\t#else\r\n\t// Cannot have music if building for proview, because there is not enough IOP memory\r\n\t// (ProView uses up some IOP memory with it's monitor)\r\n\tif (Config::GetHardware()==Config::HARDWARE_PS2_PROVIEW)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn !streams_hed_there;\t\r\n\t#endif\r\n}\r\n\r\n// prototypes...\r\nbool TrackIsPlaying( int whichList, int whichTrack );\r\n\r\nstatic int gLastStreamChannelPlayed = 0;\r\n\r\nCurrentStreamInfo gCurrentStreamInfo[ NUM_STREAMS ];\r\n\r\nTrackTitle PermTrackTitle[ MAX_NUM_TRACKS ];\r\n\r\n// Static globals\r\nstatic int          current_music_track = 0;\r\nstatic TrackList\tgTrackLists[ NUM_TRACKLISTS ];\r\nstatic int\t\t\tgCurrentTrackList = TRACKLIST_PERM;  // start out playing songs...\r\nstatic char\t\t\tgTrackName[ MAX_TRACKNAME_STRING_LENGTH ];\r\nstatic float\t\tgMusicVolume = DEFAULT_MUSIC_VOLUME;\r\nstatic float\t\tgMusicStreamVolume = DEFAULT_MUSIC_STREAM_VOLUME;\r\nstatic bool \t\tgMusicInRandomMode = true;\r\nstatic bool\t\t\tgMusicLooping = false;\r\nstatic int\t\t\tsCounter = 1;\r\nstatic bool\t\t\tgPcmInitialized = false;\r\nstatic int\t\t\tgNumStreams = 0;\r\nstatic Obj::CStreamComponent\t*gpStreamingObj[ NUM_STREAMS ]; // should have as many of these as streams...\r\n\r\n// Music stream data\r\n\r\nstatic EMusicStreamType\tgMusicStreamType = MUSIC_STREAM_TYPE_NONE;\r\n#if WAIT_AFTER_STOP_STREAM\r\nstatic uint32 \t\t\tgMusicStreamChecksum;\t// Checksum of music stream\r\nstatic float \t\t\tgMusicStreamVolume;\t\t// Volume of music stream\r\nstatic bool \t\t\tgMusicStreamWaitingToStart;\t// true if we are still waiting for the channel to become free\r\n#endif // WAIT_AFTER_STOP_STREAM\r\n\r\n// Limit is actually 500 ...\r\n#define\t\t\tMAX_USER_SONGS\t\t\t\t\t600\r\n\r\n#ifdef __PLAT_XBOX__\r\nstatic bool\t\ts_xbox_play_user_soundtracks\t= false;\r\nstatic int\t\ts_xbox_user_soundtrack\t\t\t= 0;\r\nstatic uint32\ts_xbox_user_soundtrack_song\t\t= 0;\r\nstatic bool\t\ts_xbox_user_soundtrack_random\t= false;\r\nstatic uint32\ts_xbox_random_index\t\t\t\t= 0;\r\n\r\nstatic int\t\tsp_xbox_randomized_songs[MAX_USER_SONGS];\r\n#endif\r\n\r\nstatic bool     shuffle_random_songs=true;\r\nstatic int      num_random_songs = 1;\r\nstatic int      random_song_index = 0;\r\nstatic int\t\tsp_random_song_order[MAX_USER_SONGS];\r\n\r\n\r\n// Stream ID functions\r\nbool IDAvailable(uint32 id)\r\n{\r\n\tfor ( int i = 0; i < NUM_STREAMS; i++ )\r\n\t{\r\n\t\tif ( (gCurrentStreamInfo[ i ].uniqueID == id) && (PCMAudio_GetStreamStatus(gCurrentStreamInfo[ i ].voice) != PCM_STATUS_FREE))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nint GetChannelFromID(uint32 id, bool assert_if_duplicate = true)\r\n{\r\n\tint i;\r\n\r\n\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t{\r\n\t\tif ( (gCurrentStreamInfo[ i ].uniqueID == id) && (PCMAudio_GetStreamStatus(gCurrentStreamInfo[ i ].voice) != PCM_STATUS_FREE))\r\n\t\t{\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t{\r\n\t\tif ( (gCurrentStreamInfo[ i ].controlID == id) && (PCMAudio_GetStreamStatus(gCurrentStreamInfo[ i ].voice) != PCM_STATUS_FREE))\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(!assert_if_duplicate, (\"Trying to control duplicate stream %s by checksum\", Script::FindChecksumName(id)));\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\r\n\treturn -1;\r\n}\r\n\r\nuint32 GenerateUniqueID(uint32 id)\r\n{\r\n\t// Keep incrementing ID until one works.\r\n\twhile (!IDAvailable(id))\r\n\t\tid++;\r\n\r\n\treturn id;\r\n}\r\n\r\nvoid StopMusic( void )\r\n{\r\n\tif (NoMusicPlease()) return;\r\n\t\r\n\t// the counter has to reach SONG_UPDATE_INTERVAL before a new song is played...\r\n\t// so resetting the counter keeps a new song from playing right away.\r\n\tsCounter = 1;\r\n\tgMusicStreamType = MUSIC_STREAM_TYPE_NONE;\t\t// In case we were in this mode\r\n\tPCMAudio_StopMusic( true );\r\n}\r\n\r\n// If a channel is specified, stop a specific stream (might be a streaming soundFX on an object that's getting\r\n// destroyed, for example).\r\n// If channel parameter is -1, stop all non-music streams!\r\nvoid StopStreams( int channel )\r\n{\r\n\tReplay::WriteStopStream(channel);\r\n\tif (StreamsDisabled()) return;\r\n\t\r\n\tDbg_MsgAssert( ( channel >= -1 ) && ( channel < NUM_STREAMS ), ( \"Invalid stream channel %d\", channel ) );\r\n\tif ( channel == -1 )\r\n\t{\r\n\t\tPCMAudio_StopStreams( );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tPCMAudio_StopStream( channel );\r\n\t}\r\n}\r\n\r\n// if uniqueID isn't specified, stop whatever stream is playing!\r\nvoid StopStreamFromID( uint32 streamID )\r\n{\r\n\tif (StreamsDisabled()) return;\r\n\t\r\n\tint channel = GetChannelFromID(streamID);\r\n\r\n\tif (channel >= 0)\r\n\t{\r\n\t\tPCMAudio_StopStream( channel, true );\r\n\t\tstreamID = gCurrentStreamInfo[ channel ].uniqueID;\t\t// change over to uniqueID\r\n\t}\r\n\r\n\tfor ( int i = 0; i < NUM_STREAMS; i++ )\r\n\t{\r\n\t\tif ( gpStreamingObj[ i ] )\r\n\t\t{\r\n\t\t\tfor ( int j = 0; j < MAX_STREAMS_PER_OBJECT; j++ )\r\n\t\t\t{\r\n\t\t\t\tif ( gpStreamingObj[ i ]->mStreamingID[ j ] == streamID )\r\n\t\t\t\t{\r\n\t\t\t\t\tgpStreamingObj[ i ]->mStreamingID[ j ] = 0;\r\n\t\t\t\t\tgpStreamingObj[ i ] = NULL;\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool SetStreamVolumeFromID( uint32 streamID, Sfx::sVolume *p_volume )\r\n{\r\n\tif (StreamsDisabled()) return true;\r\n\t\r\n\tint channel = GetChannelFromID(streamID);\r\n\r\n\tif (channel >= 0)\r\n\t{\r\n#\t\tifdef __PLAT_XBOX__\r\n\t\tPCMAudio_SetStreamVolume( p_volume, channel );\r\n#\t\telse\r\n\t\tPCMAudio_SetStreamVolume( p_volume->GetChannelVolume( 0 ), p_volume->GetChannelVolume( 1 ), channel );\r\n#\t\tendif\r\n\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool SetStreamPitchFromID( uint32 streamID, float pitch )\r\n{\r\n\tif (StreamsDisabled()) return true;\r\n\t\r\n\tint channel = GetChannelFromID(streamID);\r\n\r\n\tif (channel >= 0)\r\n\t{\r\n\t\tPCMAudio_SetStreamPitch( pitch, channel );\r\n\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#ifdef __PLAT_XBOX__\r\nstatic void sGenerateRandomSongOrder( void )\r\n{\r\n\tint num_songs=Pcm::GetSoundtrackNumSongs( s_xbox_user_soundtrack );\r\n\r\n\tif( num_songs == 0 )\r\n\t{\r\n\t\t// Nothing to do.\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\t// Limit to MAX_USER_SONGS to prevent any buffer overwriting.\r\n\tif (num_songs>MAX_USER_SONGS)\r\n\t{\r\n\t\tnum_songs=MAX_USER_SONGS;\r\n\t}\t\r\n\r\n\t// Remember the last song in the previous order, so we can make sure that\r\n\t// the first song in the new order is different from it.\r\n\t// Note: OK if the last song was just an uninitialised random value, won't cause any problems.\r\n\tint last_song=sp_xbox_randomized_songs[num_songs-1];\r\n\t\r\n\t// Initialise the order to be 0,1,2,3 ... etc\r\n\tfor (int i=0; i<num_songs; ++i)\r\n\t{\r\n\t\tsp_xbox_randomized_songs[i]=i;\r\n\t}\r\n\r\n\t// Jumble it up.\t\t\r\n\tfor (int n=0; n<2000; ++n)\r\n\t{\r\n\t\tint a=Mth::Rnd(num_songs);\r\n\t\tint b=Mth::Rnd(num_songs);\r\n\t\t\r\n\t\tint temp=sp_xbox_randomized_songs[a];\r\n\t\tsp_xbox_randomized_songs[a]=sp_xbox_randomized_songs[b];\r\n\t\tsp_xbox_randomized_songs[b]=temp;\r\n\t}\r\n\t\r\n\t// If the first song in the new order equals the last song of the last order,\r\n\t// do one further swap to make sure it is different.\r\n\tif (sp_xbox_randomized_songs[0]==last_song)\r\n\t{\r\n\t\t// a is the first song.\r\n\t\tint a=0;\r\n\t\t\r\n\t\t// Choose b to be a random one of the other songs.\r\n\t\tint b;\r\n\t\tif (num_songs>1)\r\n\t\t{\r\n\t\t\t// Make b not able to equal 0, so that we don't swap the first with itself.\r\n\t\t\tb=1+Mth::Rnd(num_songs-1);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Unless there is only one song, in which case just swap it with itself. No point but what the heck.\r\n\t\t\tb=0;\r\n\t\t}\r\n\t\t\r\n\t\t// Do the swap.\r\n\t\tint temp=sp_xbox_randomized_songs[a];\r\n\t\tsp_xbox_randomized_songs[a]=sp_xbox_randomized_songs[b];\r\n\t\tsp_xbox_randomized_songs[b]=temp;\r\n\t}\r\n}\r\n#endif // __PLAT_XBOX__\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid UseUserSoundtrack( int soundtrack )\r\n{\r\n#\tifdef __PLAT_XBOX__\r\n\r\n\tDbg_MsgAssert(soundtrack>=0 && soundtrack<Pcm::GetNumSoundtracks(),(\"Bad soundtrack\"));\r\n\r\n\ts_xbox_play_user_soundtracks=true;\r\n\ts_xbox_user_soundtrack=soundtrack;\r\n\tif (s_xbox_user_soundtrack_random)\r\n\t{\r\n\t\tsGenerateRandomSongOrder();\r\n\t\ts_xbox_random_index=0;\r\n\t\ts_xbox_user_soundtrack_song=sp_xbox_randomized_songs[0];\r\n\t}\r\n\telse\r\n\t{\r\n\t\ts_xbox_user_soundtrack_song=0;\r\n\t}\t\r\n#\tendif // __PLAT_XBOX__\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid UseStandardSoundtrack( void )\r\n{\r\n#\tifdef __PLAT_XBOX__\r\n\ts_xbox_play_user_soundtracks = false;\r\n#\tendif\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool UsingUserSoundtrack( void )\r\n{\r\n#\tifdef __PLAT_XBOX__\r\n\treturn s_xbox_play_user_soundtracks;\r\n#\telse\r\n\treturn false;\r\n#\tendif\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SaveSoundtrackToStructure( Script::CStruct *pStuff)\r\n{\r\n#\tifdef __PLAT_XBOX__\r\n\tDbg_MsgAssert( pStuff,(\"NULL pStuff\"));\r\n\t\t\r\n\tif (s_xbox_play_user_soundtracks)\r\n\t{\r\n\t\tpStuff->AddComponent(Script::GenerateCRC(\"UserSoundtrackIndex\"),ESYMBOLTYPE_INTEGER,s_xbox_user_soundtrack);\r\n\r\n\t\tchar p_buf[100];\r\n\t\tconst WCHAR* p_soundtrack_name_wide=Pcm::GetSoundtrackName(s_xbox_user_soundtrack);\r\n\t\tif (p_soundtrack_name_wide)\r\n\t\t{\r\n\t\t\twsprintfA( p_buf, \"%ls\", p_soundtrack_name_wide);\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_buf[0]=0;\r\n\t\t}\t\r\n\t\t\t\t\r\n\t\tpStuff->AddComponent(Script::GenerateCRC(\"UserSoundtrackName\"),ESYMBOLTYPE_STRING,p_buf);\r\n\t}\t\r\n#\tendif // __PLAT_XBOX__\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid GetSoundtrackFromStructure( Script::CStruct *pStuff)\r\n{\r\n#\tifdef __PLAT_XBOX__\r\n\tDbg_MsgAssert(pStuff,(\"NULL pStuff\"));\r\n\t\r\n\tint user_soundtrack_index=0;\r\n\tif (pStuff->GetInteger(\"UserSoundtrackIndex\",&user_soundtrack_index))\r\n\t{\r\n\t\t// A user soundtrack index is specified, but maybe the name does not match what is on this\r\n\t\t// machine, ie, they could have put the mem card into a different xbox ...\r\n\t\t\r\n\t\t// Get the name of this soundtrack on this machine\r\n\t\tchar p_buf[100];\r\n\t\tconst WCHAR* p_soundtrack_name_wide=Pcm::GetSoundtrackName(user_soundtrack_index);\r\n\t\tif (p_soundtrack_name_wide)\r\n\t\t{\r\n\t\t\twsprintfA( p_buf, \"%ls\", p_soundtrack_name_wide);\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_buf[0]=0;\r\n\t\t}\t\r\n\t\r\n\t\t// Get the name as stored on the mem card\r\n\t\tconst char *p_stored_name=\"\";\r\n\t\tpStuff->GetText(\"UserSoundtrackName\",&p_stored_name);\r\n\t\t\r\n\t\tif (strcmp(p_stored_name,p_buf)==0)\r\n\t\t{\r\n\t\t\t// They match! So use that soundtrack.\r\n\t\t\tUseUserSoundtrack(user_soundtrack_index);\r\n\t\t\treturn;\r\n\t\t}\t\r\n\t}\t\r\n\t\r\n\t// Oh well, use the standard soundtrack instead.\r\n\tUseStandardSoundtrack();\r\n#\tendif\t// __PLAT_XBOX__\r\n}\r\n\r\n\r\n\r\nbool _PlayMusicTrack( const char *filename, float volume )\r\n{\r\n\tif (NoMusicPlease()) return false;\r\n\t\r\n\tDbg_MsgAssert( gPcmInitialized,( \"Calling playtrack %s, when PCM Audio not initialized.\", filename ));\r\n\tDbg_MsgAssert( strlen( filename ) < 200,( \"Filename too long\" ));\r\n\r\n#\tifdef __PLAT_XBOX__\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tif( s_xbox_play_user_soundtracks && !skate_mod->GetGameMode()->IsFrontEnd())\r\n\t{\r\n\t\tif( Pcm::GetSoundtrackNumSongs( s_xbox_user_soundtrack ) == 0 )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\t\r\n\t\tif( !PCMAudio_PlaySoundtrackMusicTrack( s_xbox_user_soundtrack, s_xbox_user_soundtrack_song ))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif( s_xbox_user_soundtrack_random )\r\n\t\t\t{\r\n\t\t\t\t++s_xbox_random_index;\r\n\t\t\t\tif( s_xbox_random_index >= Pcm::GetSoundtrackNumSongs( s_xbox_user_soundtrack ))\r\n\t\t\t\t{\r\n\t\t\t\t\tsGenerateRandomSongOrder();\r\n\t\t\t\t\ts_xbox_random_index = 0;\r\n\t\t\t\t}\t\r\n\t\t\t\ts_xbox_user_soundtrack_song=sp_xbox_randomized_songs[s_xbox_random_index];\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t++s_xbox_user_soundtrack_song;\r\n\t\t\t\tif( s_xbox_user_soundtrack_song >= Pcm::GetSoundtrackNumSongs( s_xbox_user_soundtrack ))\r\n\t\t\t\t{\r\n\t\t\t\t\ts_xbox_user_soundtrack_song = 0;\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t}\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( !PCMAudio_PlayMusicTrack( filename ))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\t\t\r\n#\telse\r\n\tif( !PCMAudio_PlayMusicTrack( filename ))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n#\tendif // __PLAT_XBOX__\r\n\r\n//\tvolume = volume * Config::GetMasterVolume()/100.0f;\r\n//\tif (volume <0.1f)\r\n//\t{\r\n//\t\tvolume = 0.0f;\r\n//\t}\r\n\tPCMAudio_SetMusicVolume( volume );\r\n\treturn ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool _PlayMusicStream( uint32 checksum, float volume )\r\n{\r\n\tif (NoMusicPlease()) return false;\r\n\t\r\n\tDbg_MsgAssert( gPcmInitialized,( \"Calling playtrack %s, when PCM Audio not initialized.\", Script::FindChecksumName(checksum) ));\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tif( !PCMAudio_PlayMusicStream( checksum ))\r\n\t{\r\n\t\tDbg_MsgAssert(0, ( \"Failed playing track %s\", Script::FindChecksumName(checksum) ) );\r\n\t\tDbg_Message( \"Failed playing track %s\", Script::FindChecksumName(checksum) );\r\n\t\treturn false;\r\n\t}\r\n#else\r\n\tDbg_MsgAssert(0, (\"PCMAudio_PlayMusicStream() not implemented on this platform.\"));\r\n#endif // __PLAT_NGPS__\r\n\r\n\tPCMAudio_SetMusicVolume( volume );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// returns -1 on failure, otherwise the index into which voice played the sound.\r\nint _PlayStream( uint32 checksum, Sfx::sVolume *p_volume, float pitch, int priority, uint32 controlID, bool preload_only )\r\n{\r\n\tif (StreamsDisabled()) return -1;\r\n\t\r\n#\tifdef __PLAT_XBOX__\r\n\tDbg_MsgAssert( gPcmInitialized,( \"Calling _PlayStream(), when PCM Audio not initialized.\" ));\r\n#\tendif // __PLAT_XBOX__\r\n\r\n\t// Initialize lowest to a valid entry\r\n\tint lowest_priority = gCurrentStreamInfo[ 0 ].priority;\r\n\tint lowest_priority_channel = 0;\r\n\tuint32 lowest_priority_start_frame = gCurrentStreamInfo[ 0 ].start_frame;\r\n\r\n\tbool success;\r\n\r\n\tfor ( int i = 0; i < NUM_STREAMS; i++ )\r\n\t{\r\n\t\tif ( PCMAudio_GetStreamStatus( i ) == PCM_STATUS_FREE )\r\n\t\t{\r\n\t\t\tif (preload_only)\r\n\t\t\t{\r\n\t\t\t\tsuccess = PCMAudio_PreLoadStream( checksum, i );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n//\t\t\t\tsuccess = PCMAudio_PlayStream( checksum, i, volumeL, volumeR, pitch );\r\n#\t\t\t\tifdef __PLAT_XBOX__\r\n\t\t\t\tsuccess = PCMAudio_PlayStream( checksum, i, p_volume, pitch );\r\n#\t\t\t\telse\r\n\t\t\t\tsuccess = PCMAudio_PlayStream( checksum, i, p_volume->GetChannelVolume( 0 ), p_volume->GetChannelVolume( 1 ), pitch );\r\n#\t\t\t\tendif\r\n\t\t\t}\r\n\r\n\t\t\tif ( !success )\r\n\t\t\t{\r\n\t\t\t\treturn ( -1 );\r\n\t\t\t}\r\n\r\n\t   \t\tgCurrentStreamInfo[ i ].controlID = controlID;\r\n\t   \t\tgCurrentStreamInfo[ i ].uniqueID = GenerateUniqueID(controlID);\r\n\t   \t\tgCurrentStreamInfo[ i ].voice = i;\r\n\t   \t\tgCurrentStreamInfo[ i ].priority = priority;\r\n\t   \t\tgCurrentStreamInfo[ i ].start_frame = (uint32)Tmr::GetRenderFrame();\r\n\t\t\tgCurrentStreamInfo[ i ].p_frame_amp = CStreamFrameAmpManager::sGetFrameAmp(checksum);\r\n\t\t\treturn ( i );\r\n\t\t}\r\n\t\telse if ( gCurrentStreamInfo[ i ].priority <= lowest_priority )\r\n\t\t{\r\n\t\t\t// If it is equal priority, we want to find the oldest one\r\n\t\t\tif ((gCurrentStreamInfo[ i ].priority == lowest_priority) &&\r\n\t\t\t\t(gCurrentStreamInfo[ i ].start_frame >= lowest_priority_start_frame))\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tlowest_priority = gCurrentStreamInfo[ i ].priority;\r\n\t\t\tlowest_priority_channel = i;\r\n\t\t\tlowest_priority_start_frame = gCurrentStreamInfo[ i ].start_frame;\r\n\t\t}\r\n\t}\r\n\r\n\t// Couldn't find a free one, so lets see if we can knock one off\r\n\tif (priority >= lowest_priority)\r\n\t{\r\n\t\tPCMAudio_StopStream( lowest_priority_channel );\r\n\r\n\t#if WAIT_AFTER_STOP_STREAM\r\n\t\tDbg_MsgAssert(0, (\"Priority streams not implemented on this system\"));\t\t// Not implemented\r\n\t\treturn ( -1 );\r\n\t#else\r\n\t\tif (preload_only)\r\n\t\t{\r\n\t\t\tsuccess = PCMAudio_PreLoadStream( checksum, lowest_priority_channel );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n//\t\t\tsuccess = PCMAudio_PlayStream( checksum, lowest_priority_channel, volumeL, volumeR, pitch );\r\n#\t\t\tifdef __PLAT_XBOX__\r\n\t\t\tsuccess = PCMAudio_PlayStream( checksum, lowest_priority_channel, p_volume, pitch );\r\n#\t\t\telse\r\n\t\t\tsuccess = PCMAudio_PlayStream( checksum, lowest_priority_channel, p_volume->GetChannelVolume( 0 ), p_volume->GetChannelVolume( 1 ), pitch );\r\n#\t\t\tendif\r\n\t\t}\r\n\r\n\t\tif ( !success )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"Higher priority stream could not start.  Make sure there was another error (like file not found).\"));\r\n\t\t\treturn ( -1 );\r\n\t\t}\r\n\r\n\t\tgCurrentStreamInfo[ lowest_priority_channel ].controlID = controlID;\r\n\t\tgCurrentStreamInfo[ lowest_priority_channel ].uniqueID = GenerateUniqueID(controlID);\r\n\t\tgCurrentStreamInfo[ lowest_priority_channel ].voice = lowest_priority_channel;\r\n\t\tgCurrentStreamInfo[ lowest_priority_channel ].priority = priority;\r\n\t\tgCurrentStreamInfo[ lowest_priority_channel ].start_frame = (uint32)Tmr::GetRenderFrame();\r\n\t\tgCurrentStreamInfo[ lowest_priority_channel ].p_frame_amp = CStreamFrameAmpManager::sGetFrameAmp(checksum);\r\n\t#endif // WAIT_AFTER_STOP_STREAM\r\n\t\treturn ( lowest_priority_channel );\r\n\t}\r\n\r\n\treturn ( -1 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool _PreLoadMusicStream( uint32 checksum )\r\n{\r\n\tif (NoMusicPlease()) return false;\r\n\r\n\tDbg_MsgAssert( gPcmInitialized,( \"Calling _PreLoadMusicStream %s, when PCM Audio not initialized.\", Script::FindChecksumName(checksum) ));\r\n\r\n\treturn PCMAudio_PreLoadMusicStream( checksum );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool _StartPreLoadedMusicStream( float volume )\r\n{\r\n\tif( !PCMAudio_StartPreLoadedMusicStream( ))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tPCMAudio_SetMusicVolume( volume );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#define MIN_STREAM_VOL\t\t2.0f\r\n\r\n\r\n\r\nuint32 PlayStreamFromObject( Obj::CStreamComponent *pComponent, uint32 streamNameChecksum, float dropoff, float volume,\r\n\t\t\t\t\t\t\t float pitch, int priority, int use_pos_info, EDropoffFunc dropoffFunc, uint32 controlID )\r\n{\r\n\tSfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();\r\n\r\n\t// Don't start a stream if it won't be heard\r\n\tif( sfx_manager->PositionalSoundSilenceMode() )\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tReplay::WritePositionalStream(pComponent->GetObject()->GetID(),streamNameChecksum,dropoff,volume,pitch,priority,use_pos_info);\r\n\tif (StreamsDisabled()) return 0;\r\n\t\r\n\tSfx::sVolume vol;\r\n\tvol.SetSilent();\r\n\t\r\n\t// Let the priority system figure this out\r\n\t//if (!StreamAvailable())\r\n\t//\treturn 0;\r\n\t\r\n\t// Set up volume according to position of object to camera.\r\n\tif ( use_pos_info != 0 )\r\n\t{\r\n\t\tGfx::Camera *pCamera = Nx::CViewportManager::sGetClosestCamera( pComponent->GetObject()->m_pos );\r\n\r\n\t\tif (pCamera)\r\n\t\t{\r\n\t\t\tMth::Vector dropoff_pos;\r\n\t\t\tMth::Vector *p_dropoff_pos = NULL;\r\n\t\t\tif (pComponent->GetClosestDropoffPos(pCamera, dropoff_pos))\r\n\t\t\t{\r\n\t\t\t\tp_dropoff_pos = &dropoff_pos;\r\n\t\t\t}\r\n\r\n\t\t\tsfx_manager->SetVolumeFromPos( &vol, pComponent->GetClosestEmitterPos(pCamera), dropoff, dropoffFunc, pCamera, p_dropoff_pos );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tvol.SetSilent();\r\n\t\t}\r\n\r\n\t\t// Seems strange to cancel out a stream if it starting low\r\n\t\tif( fabsf( vol.GetLoudestChannel()) < MIN_STREAM_VOL )\r\n\t\t{\r\n\t\t\tif( Script::GetInteger( 0xd7bb618d /* DebugSoundFx */, Script::NO_ASSERT ))\r\n\t\t\t{\r\n\t\t\t\tDbg_Message(\"I wanted to cancel stream %s\", Script::FindChecksumName(streamNameChecksum));\r\n\t\t\t}\r\n//\t\t\treturn 0;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tvol.SetChannelVolume( 0, volume );\r\n\t\tvol.SetChannelVolume( 1, volume );\r\n\t}\r\n\t\r\n\t// K: The 'false' on the end means do not record the call in the replay, because this\r\n\t// call to PlayStreamFromObject has already been recorded.\r\n\tuint32 uniqueID = PlayStream( streamNameChecksum, &vol, pitch, priority, controlID, false );\r\n\tif ( uniqueID )\r\n\t{\r\n\t\tDbg_MsgAssert( ( ( gLastStreamChannelPlayed >= 0 ) && ( gLastStreamChannelPlayed < MAX_STREAMS_PER_OBJECT ) ), ( \"Tell Matt to fix object streams\" ) );\r\n\t\tif ( gpStreamingObj[ gLastStreamChannelPlayed ] )\r\n\t\t{\r\n\t\t\t// the object might not have called StreamUpdate yet, so the slot might\r\n\t\t\t// still think it's in use... clear the slot if that's the case:\r\n\t\t\tgpStreamingObj[ gLastStreamChannelPlayed ]->mStreamingID[ gLastStreamChannelPlayed ] = 0;\r\n\t\t\tgpStreamingObj[ gLastStreamChannelPlayed ] = NULL;\r\n\t\t}\r\n//\t\tDbg_MsgAssert( !gpStreamingObj[ gLastStreamChannelPlayed ], ( \"Have Matt fix object streams... Kick him in the nutsack while you're at it.\" ) );\r\n//\t\tDbg_MsgAssert( !pObject->mStreamingID[ gLastStreamChannelPlayed ], ( \"Have Matt fix object streams... Hell, fire matt!!!\" ) );\r\n\t\tgpStreamingObj[ gLastStreamChannelPlayed ] = pComponent;\r\n\t\tpComponent->mStreamingID[ gLastStreamChannelPlayed ] = uniqueID;\r\n\t\t// if volume modifier sent in, store that:\r\n\t\tif ( volume != 100.0f )\r\n\t\t{\r\n\t\t\tint i;\r\n\t\t\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t\t\t{\r\n\t\t\t\tif ( gCurrentStreamInfo[ i ].uniqueID == uniqueID )\r\n\t\t\t\t{\r\n\t\t\t\t\tgCurrentStreamInfo[ i ].volume = PERCENT( gCurrentStreamInfo[ i ].volume, volume );\r\n\t\t\t\t\tgCurrentStreamInfo[ i ].dropoff = dropoff;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// store state of use_pos_info\r\n\t\tif ( !use_pos_info )\r\n\t\t{\r\n\t\t\tfor ( int i = 0; i < NUM_STREAMS; i++ )\r\n\t\t\t{\r\n\t\t\t\tif ( gCurrentStreamInfo[i].uniqueID == uniqueID )\r\n\t\t\t\t{\r\n\t\t\t\t\tgCurrentStreamInfo[i].use_pos_info = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfor ( int i = 0; i < NUM_STREAMS; i++ )\r\n\t\t\t{\r\n\t\t\t\tif ( gCurrentStreamInfo[i].uniqueID == uniqueID )\r\n\t\t\t\t{\r\n\t\t\t\t\tgCurrentStreamInfo[i].use_pos_info = true;\r\n\t\t\t\t\tgCurrentStreamInfo[i].dropoffFunction = dropoffFunc;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn ( uniqueID );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 PlayStream( uint32 checksum, Sfx::sVolume *p_volume, float pitch, int priority, uint32 controlID, bool record_in_replay )\r\n{\r\n\tif (record_in_replay)\r\n\t{\r\n\t\tReplay::WritePlayStream( checksum, p_volume, pitch, priority );\r\n\t}\t\r\n\tif (StreamsDisabled()) return 0;\r\n\t\r\n\t// Just use checksum if no controlID is set\r\n\tif (controlID == 0)\r\n\t{\r\n\t\tcontrolID = checksum;\r\n\t}\r\n\r\n\tif (!IDAvailable(controlID))\r\n\t{\r\n\t\tDbg_Message(\"Playing stream %s with same checksum as one already being played, won't be able to control directly.\", Script::FindChecksumName(controlID));\r\n\t}\r\n\t\r\n\tint whichStream;\r\n\r\n\t// allow streams to play with default values, if not pre-loaded.\r\n\twhichStream = _PlayStream( checksum, p_volume, pitch, priority, controlID, false );\r\n\tif ( whichStream != -1 )\r\n\t{\r\n\t\tgCurrentStreamInfo[ whichStream ].dropoff = DEFAULT_STREAM_DROPOFF;\r\n\t\tgCurrentStreamInfo[ whichStream ].volume = 100.0f;\r\n\t\tgLastStreamChannelPlayed = whichStream;\r\n\t\treturn gCurrentStreamInfo[ whichStream ].uniqueID;\r\n\t}\r\n\r\n//\tDbg_MsgAssert( 0,( \"Tried to play track %s not in header.\", Script::FindChecksumName( checksum ) ));\r\n\treturn ( 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 PreLoadStream( uint32 checksum, int priority )\r\n{\r\n\tif (StreamsDisabled()) return 0;\r\n\t\r\n\t// Since this isn't hooked up to a script, we just supply the checksum\r\n\tuint32 controlID = checksum;\r\n\r\n\tint whichStream;\r\n\r\n\t// allow streams to play with default values, if not in list.\r\n\tSfx::sVolume vol;\r\n\tvol.SetSilent();\r\n\twhichStream = _PlayStream( checksum, &vol, 0.0, priority, controlID, true );\r\n\r\n\tif ( whichStream != -1 )\r\n\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\tDbg_Message(\"PreLoadStream for stream %s on channel %d\", Script::FindChecksumName( checksum ), whichStream);\r\n#endif \r\n\t\tgCurrentStreamInfo[ whichStream ].dropoff = DEFAULT_STREAM_DROPOFF;\r\n\t\tgCurrentStreamInfo[ whichStream ].volume = 100.0f;\r\n\t\treturn gCurrentStreamInfo[ whichStream ].uniqueID;\r\n\t}\r\n\r\n//\tDbg_MsgAssert( 0,( \"Tried to play track %s not in header.\", Script::FindChecksumName( checksum ) ));\r\n\treturn ( 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool PreLoadStreamDone( uint32 streamID )\r\n{\r\n\tif (StreamsDisabled()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tint channel = GetChannelFromID(streamID);\r\n\r\n\tif ( channel >= 0 )\r\n\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\tif (PCMAudio_PreLoadStreamDone( channel ))\r\n\t\t{\r\n\t\t\tDbg_Message(\"PreLoadStreamDone for stream %s on channel %d is true\", Script::FindChecksumName( streamID ), channel );\r\n\t\t}\r\n#endif \r\n\t\treturn PCMAudio_PreLoadStreamDone( channel );\r\n\t}\r\n\r\n\t// Couldn't find stream\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool StartPreLoadedStream( uint32 streamID, Sfx::sVolume *p_volume, float pitch )\r\n{\r\n\tif (StreamsDisabled()) return false;\r\n\t\r\n\tint channel = GetChannelFromID(streamID);\r\n\r\n\tif ( channel >= 0 )\r\n\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\tDbg_Message(\"StartPreLoadStream for stream %s on channel %d\", Script::FindChecksumName( streamID ), channel);\r\n#endif \r\n\r\n//\t\treturn PCMAudio_StartPreLoadedStream( channel, volumeL, volumeR, pitch );\r\n#\t\tifdef __PLAT_XBOX__\r\n\t\treturn PCMAudio_StartPreLoadedStream( channel, p_volume, pitch );\r\n#\t\telse\r\n\t\treturn PCMAudio_StartPreLoadedStream( channel, p_volume->GetChannelVolume( 0 ), p_volume->GetChannelVolume( 1 ), pitch );\r\n#\t\tendif\r\n\t}\r\n\r\n\t// Couldn't find stream\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool PreLoadMusicStream( uint32 checksum )\r\n{\r\n\tif (NoMusicPlease()) return false;\r\n\r\n\tDbg_MsgAssert( gPcmInitialized,( \"Calling Pcm::PlayMusicStream '%s', when PCM Audio not initialized.\", Script::FindChecksumName(checksum) ));\r\n\tDbg_MsgAssert( !gMusicStreamType,( \"Calling Pcm::PlayMusicStream '%s', when one is already playing.\", Script::FindChecksumName(checksum) ));\r\n\r\n\t// Stop any previous track\r\n\tPCMAudio_StopMusic(false);\r\n\t\r\n\tbool success = false;\r\n\r\n#if WAIT_AFTER_STOP_STREAM\r\n\tgMusicStreamChecksum = checksum;\r\n\tgMusicStreamWaitingToStart = true;\r\n#else\r\n\t// allow streams to play with default values, if not in list.\r\n\tsuccess = _PreLoadMusicStream( checksum );\r\n#endif // WAIT_AFTER_STOP_STREAM\r\n\r\n\tgMusicStreamType = MUSIC_STREAM_TYPE_PRELOAD;\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool PreLoadMusicStreamDone( void )\r\n{\r\n\tif (NoMusicPlease()) return false;\r\n\tDbg_MsgAssert( gMusicStreamType == MUSIC_STREAM_TYPE_PRELOAD,( \"Calling Pcm::PreLoadMusicStreamDone while in normal music mode.\" ));\r\n\r\n\treturn PCMAudio_PreLoadMusicStreamDone( );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool StartPreLoadedMusicStream( float volume )\r\n{\r\n\tif (NoMusicPlease()) return false;\r\n\r\n\tDbg_MsgAssert( gMusicStreamType == MUSIC_STREAM_TYPE_PRELOAD,( \"Calling Pcm::StartPreLoadedMusicStream while in normal music mode.\" ));\r\n\r\n\tif ( volume < 0.0f )\r\n\t{\r\n\t\tvolume = gMusicStreamVolume;\r\n\t}\r\n\t\r\n\treturn _StartPreLoadedMusicStream( volume );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool SetStreamVolume( int objStreamIndex )\r\n{\r\n\tif ( StreamsDisabled() ) return false;\r\n\t\r\n\tObj::CStreamComponent *pComp;\r\n\tpComp = gpStreamingObj[ objStreamIndex ];\r\n\r\n\tCurrentStreamInfo *pInfo = NULL;\r\n\r\n\tint i;\r\n\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t{\r\n\t\tif ( gCurrentStreamInfo[ i ].uniqueID == pComp->mStreamingID[ objStreamIndex ] )\r\n\t\t{\r\n\t\t\tif ( PCMAudio_GetStreamStatus( gCurrentStreamInfo[ objStreamIndex ].voice ) == PCM_STATUS_FREE )\r\n\t\t\t{\r\n\t\t\t\treturn ( false );\r\n\t\t\t}\t\r\n\t\t\tpInfo = &gCurrentStreamInfo[ i ];\r\n\r\n\t\t\t// Update volume from dropoff/pan for the object responsible for streaming.\r\n\t\t\tSfx::sVolume vol;\r\n\r\n\t\t\tSfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();\r\n\t\t\tif ( pInfo->use_pos_info )\r\n\t\t\t{\r\n\t\t\t\tGfx::Camera *pCamera = Nx::CViewportManager::sGetClosestCamera( pComp->GetObject()->m_pos );\r\n\r\n\t\t\t\tif (pCamera)\r\n\t\t\t\t{\r\n\t\t\t\t\tMth::Vector dropoff_pos;\r\n\t\t\t\t\tMth::Vector *p_dropoff_pos = NULL;\r\n\t\t\t\t\tif (pComp->GetClosestDropoffPos(pCamera, dropoff_pos))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_dropoff_pos = &dropoff_pos;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tsfx_manager->SetVolumeFromPos( &vol, pComp->GetClosestEmitterPos(pCamera), pInfo->dropoff, pInfo->dropoffFunction, pCamera, p_dropoff_pos );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tvol.SetSilent();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tvol.SetChannelVolume( 0, pInfo->volume );\r\n\t\t\t\tvol.SetChannelVolume( 1, pInfo->volume );\r\n\t\t\t}\r\n\r\n\t\t\tif( pInfo->volume != 100.0f )\r\n\t\t\t{\r\n\t\t\t\tvol.PercentageAdjustment( pInfo->volume );\r\n\t\t\t}\r\n\r\n#\t\t\tifdef __PLAT_XBOX__\r\n\t\t\t// We need the sign-correct version for Xbox to calculate proper 5.1 values.\r\n\t\t\tPCMAudio_SetStreamVolume( &vol, pInfo->voice );\r\n#\t\t\telse\r\n\t\t\tPCMAudio_SetStreamVolume( vol.GetChannelVolume( 0 ), vol.GetChannelVolume( 1 ), pInfo->voice );\r\n#\t\t\tendif\r\n\t\t\treturn ( true );\r\n\t\t}\r\n\t}\r\n\treturn ( false );\r\n}\r\n\r\nvoid Init( void )\r\n{\r\n\t// Zero these out at startup.\r\n\tfor( int s = 0; s < NUM_STREAMS; ++s )\r\n\t{\r\n\t\tgpStreamingObj[s] = NULL;\r\n\t}\r\n\r\n\tif (NoMusicPlease() && StreamsDisabled()) return;\r\n\t\r\n\tPCMAudio_Init( );\r\n\tgPcmInitialized = true;\r\n\tgMusicVolume = (float)Script::GetInteger( 0xabd4a575 ); // checksum 'MusicVolume'\r\n\tif ( !gMusicVolume )\r\n\t{\r\n\t\tgMusicVolume = DEFAULT_MUSIC_VOLUME;\r\n\t}\r\n//\tSetVolume( gMusicVolume );\r\n\tgMusicStreamVolume = (float)Script::GetInteger(CRCD(0x73f8e03b,\"MusicStreamVolume\"));\r\n\tif ( !gMusicStreamVolume )\r\n\t{\r\n\t\tgMusicStreamVolume = DEFAULT_MUSIC_STREAM_VOLUME;\r\n\t}\r\n\r\n\tint i;\r\n\tfor ( i = 0; i < NUM_TRACKLISTS; i++ )\r\n\t{\r\n\t\tgTrackLists[ i ].numTracks = 0;\r\n\t\tgTrackLists[ i ].trackForbidden0 = 0;\r\n        gTrackLists[ i ].trackForbidden1 = 0;\r\n\t\tgTrackLists[ i ].trackPlayed0 = 0;\r\n        gTrackLists[ i ].trackPlayed1 = 0;\r\n\t\t// no tracks, so all tracks forbidden, right?\r\n\t\tgTrackLists[ i ].allTracksForbidden = true;\r\n\t}\r\n\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t{\r\n\t\tgpStreamingObj[ i ] = NULL;\r\n\t\tgCurrentStreamInfo[ i ].controlID = 0;\r\n\t\tgCurrentStreamInfo[ i ].uniqueID = 0;\r\n\t}\r\n} // end of Init( )\r\n\r\n\r\n// Should be renamed to StopUsingCD( ) as if the cd is in use\r\n// by streams, this function stops the streams and frees up the\r\n// CD.\r\nbool UsingCD( void )\r\n{\r\n\t\r\n\t#if defined( __PLAT_NGC__ )\r\n\tif ( !( gPcmInitialized ) )\r\n\t{\r\n\t\treturn ( false );\r\n\t}\r\n\tStopMusic( );\r\n\tStopStreams( );\r\n\t\r\n\t#else\r\n\t\r\n\tif (Config::CD() || TEST_FROM_CD)\r\n\t{\r\n\t\tif ( !( gPcmInitialized ) )\r\n\t\t{\r\n\t//\t\tDbg_Message( \"uninitialized\" );\r\n\t\t\treturn ( false );\r\n\t\t}\r\n\t\tStopMusic( );\r\n\t\tStopStreams( );\r\n\t}\t\r\n\t#endif\r\n\t\t\r\n\treturn ( false );\r\n} // end of UsingCD( )\r\n\r\n// plays a music track.\r\nvoid PlayTrack( const char *filename, bool loop )\r\n{\r\n\tif (NoMusicPlease()) return;\r\n\r\n\tif (gMusicStreamType)\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Trying to play a music track in stereo stream mode.\"));\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tDbg_MsgAssert( gPcmInitialized,( \"Calling Pcm::PlayTrack '%s', when PCM Audio not initialized.\", filename ));\r\n\tDbg_MsgAssert( strlen( filename ) < MAX_TRACKNAME_STRING_LENGTH,( \"CD Audio Filename too long.\" ));\r\n\tstrcpy( gTrackName, filename );\r\n\t\r\n\tint trackList = gCurrentTrackList;\r\n\tfloat volume;\r\n\tif ( trackList == TRACKLIST_PERM )\r\n\t{\r\n\t\tvolume = gMusicVolume;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();\r\n\t\tvolume = sfx_manager->GetMainVolume( );\r\n\t}\r\n\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tif ( skate_mod->GetGameMode( )->IsFrontEnd( ) )\r\n\t{\r\n\t\ttrackList = TRACKLIST_LEVEL_SPECIFIC;\r\n\t\tvolume = gMusicVolume;\r\n\t}\r\n\r\n\tSetLoopingMode(loop);\r\n\t\r\n\tif ( !_PlayMusicTrack( gTrackName, volume ) )\r\n\t{\r\n\t\tif (Config::CD() || TEST_FROM_CD)\r\n\t\t{\r\n\t\t\tDbg_Message( \"Failed playing track %s\", filename );\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\t// see if this is a track in the current playlists...\r\n\t\t\t// if so, don't keep trying to play it...\r\n\t\t\tTrackList *pTrackList = &gTrackLists[ trackList ];\r\n\t\t\tint i;\r\n\t\t\tfor ( i = 0; i < pTrackList->numTracks; i++ )\r\n\t\t\t{\r\n\t\t\t\tif ( Script::GenerateCRC( filename ) == Script::GenerateCRC( pTrackList->trackInfo[ i ].trackName ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tSetTrackForbiddenStatus( i, true, trackList );\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n// Plays a stereo stream through the music channels\r\nvoid PlayMusicStream( uint32 checksum, float volume )\r\n{\r\n\tif (NoMusicPlease()) return;\r\n\r\n\tDbg_MsgAssert( gPcmInitialized,( \"Calling Pcm::PlayMusicStream '%s', when PCM Audio not initialized.\", Script::FindChecksumName(checksum) ));\r\n\tDbg_MsgAssert( !gMusicStreamType,( \"Calling Pcm::PlayMusicStream '%s', when one is already playing.\", Script::FindChecksumName(checksum) ));\r\n\r\n\t// Stop any previous track\r\n\tPCMAudio_StopMusic(false);\r\n\r\n\tif ( volume < 0.0f )\r\n\t{\r\n\t\tvolume = gMusicStreamVolume;\r\n\t}\r\n\r\n#if WAIT_AFTER_STOP_STREAM\r\n\tgMusicStreamChecksum = checksum;\r\n\tgMusicStreamVolume = volume;\r\n\tgMusicStreamWaitingToStart = true;\r\n#else\r\n\t_PlayMusicStream( checksum, volume );\r\n#endif\r\n\r\n\tgMusicStreamType = MUSIC_STREAM_TYPE_NORMAL;\r\n}\r\n\r\nstatic bool sMusicIsPaused=false;\r\nvoid PauseMusic( int pause )\r\n{\r\n\t\r\n\t\r\n\tstatic bool wasPaused = false;\r\n\r\n\tif (NoMusicPlease()) return;\r\n\t\r\n\tDbg_MsgAssert( gPcmInitialized,( \"Calling Pcm::Pause when PCM Audio not initialized.\" ));\r\n\tswitch ( pause )\r\n\t{\r\n\t\tcase ( -1 ):\r\n\t\t\t// special case... unpause only if it was unpaused last time pause was called...\r\n\t\t\tif ( !wasPaused )\r\n\t\t\t{\r\n\t\t\t\t// recursive... unpause this bitch...\r\n\t\t\t\tPauseMusic( 0 );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 1 ):\r\n\t\t\twasPaused = sMusicIsPaused;\r\n\t\t\tsMusicIsPaused = true;\r\n\t\t\tPCMAudio_Pause( true, MUSIC_CHANNEL );\r\n\t\t\tbreak;\r\n\t\tcase ( 0 ):\r\n\t\t\tsMusicIsPaused = false;\r\n\t\t\tPCMAudio_Pause( false, MUSIC_CHANNEL );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Unknown pause state %d\", pause ) );\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\nbool MusicIsPaused()\r\n{\r\n\treturn sMusicIsPaused;\r\n}\r\n\t\r\nvoid PauseStream( int pause )\r\n{\r\n\t\r\n\t\r\n\tstatic bool paused = false;\r\n\tstatic bool wasPaused = false;\r\n\r\n\tif (StreamsDisabled()) return;\r\n\t\r\n\tDbg_MsgAssert( gPcmInitialized,( \"Calling Pcm::Pause when PCM Audio not initialized.\" ));\r\n\tswitch ( pause )\r\n\t{\r\n\t\tcase ( -1 ):\r\n\t\t\t// special case... unpause only if it was unpaused last time pause was called...\r\n\t\t\tif ( !wasPaused )\r\n\t\t\t{\r\n\t\t\t\t// recursive... unpause this bitch...\r\n\t\t\t\tPauseStream( 0 );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 1 ):\r\n\t\t\twasPaused = paused;\r\n\t\t\tpaused = true;\r\n\t\t\tPCMAudio_Pause( true, EXTRA_CHANNEL );\r\n\t\t\tbreak;\r\n\t\tcase ( 0 ):\r\n\t\t\tpaused = false;\r\n\t\t\tPCMAudio_Pause( false, EXTRA_CHANNEL );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Unknown pause state %d\", pause ) );\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid SetVolume( float volume )\r\n{\r\n\t\r\n\tif (NoMusicPlease()) return;\r\n\t\r\n\tDbg_MsgAssert( gPcmInitialized,( \"Calling Pcm::SetVolume, when PCM Audio not initialized.\" ));\r\n\tif ( ( volume > 100.0f ) || ( volume < 0.0f ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Volume (%f) not between 0 and 100\", volume ));\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t\r\n\tgMusicVolume = volume;\r\n\tif ( gPcmInitialized )\r\n\t{\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tif ( ( gMusicStreamType == MUSIC_STREAM_TYPE_NONE) &&\r\n\t\t\t ( ( gCurrentTrackList == TRACKLIST_PERM ) ||\r\n\t\t\t ( skate_mod->GetGameMode( )->IsFrontEnd( ) ) ) )\r\n\t\t{\r\n//\t\t\tvolume = volume * Config::GetMasterVolume()/100.0f;\r\n//\t\t\tif (volume <0.1f)\r\n//\t\t\t{\r\n//\t\t\t\tvolume = 0.0f;\r\n//\t\t\t}\r\n\t\t\tPCMAudio_SetMusicVolume( volume );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfloat GetVolume( void )\r\n{\r\n\t\r\n\treturn ( gMusicVolume );\r\n}\r\n\r\nvoid SetMusicStreamVolume( float volume )\r\n{\r\n\tif (NoMusicPlease()) return;\r\n\t\r\n\tDbg_MsgAssert( gPcmInitialized,( \"Calling Pcm::SetVolume, when PCM Audio not initialized.\" ));\r\n\tif ( ( volume > 100.0f ) || ( volume < 0.0f ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Volume (%f) not between 0 and 100\", volume ));\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tgMusicStreamVolume = volume;\r\n\tif ( gPcmInitialized )\r\n\t{\r\n\t\tif (gMusicStreamType == MUSIC_STREAM_TYPE_NORMAL)\r\n\t\t{\r\n\t\t\tPCMAudio_SetMusicVolume( volume );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfloat GetMusicStreamVolume( void )\r\n{\r\n\treturn gMusicStreamVolume;\r\n}\r\n\r\nvoid AddTrackToPlaylist( const char *trackName, int whichList, const char *trackTitle )\r\n{\r\n\t\r\n\tif (NoMusicPlease()) return;\r\n\t\r\n\r\n\tDbg_MsgAssert( trackName,( \"What the fuck?\" ));\r\n\tDbg_MsgAssert( whichList < NUM_TRACKLISTS,( \"Dumbass.\" ));\r\n\tTrackList *pTrackList = &gTrackLists[ whichList ];\r\n\r\n\t// Ken: This is a fix to TT6484. When an ambient track finished, it was choosing\r\n\t// a new random ambient track, rather than playing the same one again.\r\n\t// So to fix, just force numTracks to zero if adding an ambient track, so that there\r\n\t// can be only one. That way, it will be forced to play the same one again. Nya ha!\r\n\tif (whichList==TRACKLIST_LEVEL_SPECIFIC)\r\n\t{\r\n\t\tpTrackList->numTracks=0;\r\n\t}\r\n\t\r\n\tif ( pTrackList->numTracks >= MAX_NUM_TRACKS )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Too many tracks in playlist (increase MAX_NUM_TRACKS or clear list).\" ));\r\n\t\treturn;\r\n\t}\r\n\tDbg_MsgAssert( strlen( trackName ) < MAX_TRACKNAME_STRING_LENGTH,( \"Track name too long.\" ));\r\n\tchar *pTrackName = pTrackList->trackInfo[ pTrackList->numTracks ].trackName;\r\n\tstrcpy( pTrackName, trackName );\r\n\t\r\n\tuint i;\r\n\tfor ( i = 0; i < strlen( pTrackName ); i++ )\r\n\t{\r\n\t\tif ( ( pTrackName[ i ] >= 'a' ) && ( pTrackName[ i ] <= 'z' ) )\r\n\t\t{\r\n\t\t\tpTrackName[ i ] = pTrackName[ i ] - 'a' + 'A';\r\n\t\t}\r\n\t}\r\n\t// Music tracks should have a title (for the user to be able to turn songs on/off):\r\n\tif ( whichList == TRACKLIST_PERM )\r\n\t{\r\n\t\tchar *pTrackTitle = PermTrackTitle[ pTrackList->numTracks ].trackTitle;\r\n\t\tif ( trackTitle )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( strlen( trackTitle ) < TRACK_TITLE_MAX_SIZE, ( \"Track title %s too long (max %d chars)\", trackTitle, TRACK_TITLE_MAX_SIZE ) );\r\n\t\t\tstrncpy( pTrackTitle, trackTitle, TRACK_TITLE_MAX_SIZE );\r\n\t\t\tpTrackTitle[ TRACK_TITLE_MAX_SIZE - 1 ] = '\\0';\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t   \t\tDbg_MsgAssert( 0, ( \"Track %s not given a title.\", trackName ) );\r\n\t\t\tstrcpy( pTrackTitle, \"No title provided\" );\r\n\t\t}\r\n\t}\r\n\tif ( !PCMAudio_TrackExists( pTrackName, MUSIC_CHANNEL ) )\r\n\t{\r\n\t\tDbg_MsgAssert(!Config::CD(),(\"Could not find music track '%s'\\n\",pTrackName));\r\n\t\tDbg_Message(\"Could not find music track '%s'\",pTrackName);\r\n\t\treturn;\r\n\t}\t\r\n\tpTrackList->allTracksForbidden = false;\r\n    pTrackList->numTracks++;\r\n}\r\n\r\nvoid ClearPlaylist( int whichList )\r\n{\r\n\t\r\n\tif (NoMusicPlease()) return;\r\n\t\r\n\tDbg_MsgAssert( whichList < NUM_TRACKLISTS,( \"Dumbshit.\" ));\r\n\tTrackList *pTrackList = &gTrackLists[ whichList ];\r\n\tpTrackList->numTracks = 0;\r\n\tpTrackList->allTracksForbidden = true; // if there are no tracks, all are forbidden, no?\r\n\tpTrackList->trackForbidden0 = 0;\r\n    pTrackList->trackForbidden1 = 0;\r\n\tpTrackList->trackPlayed0 = 0;\r\n    pTrackList->trackPlayed1 = 0;\r\n\t\r\n\tgNumStreams = 0;\r\n}\r\n\r\nvoid SkipMusicTrack( void )\r\n{\r\n\t\r\n\tif (NoMusicPlease()) return;\r\n\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tif ( skate_mod->GetGameMode( )->IsFrontEnd( ) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( gCurrentTrackList == TRACKLIST_PERM )\r\n\t{\r\n\t\t// will stop the current song, auto update will\r\n\t\t// cause music to continue with the next track...\r\n\t\tStopMusic( );\r\n\t}\r\n}\r\n\r\nvoid SetRandomMode( int randomModeOn )\r\n{\r\n\tif (NoMusicPlease()) return;\r\n\r\n\tgMusicInRandomMode = randomModeOn;\r\n\r\n#\tifdef __PLAT_XBOX__\r\n\ts_xbox_user_soundtrack_random = ( randomModeOn > 0 );\r\n\tif( randomModeOn )\r\n\t{\r\n\t\t// Generate a new random order now, since the current one may be invalid for this soundtrack.\r\n\t\tsGenerateRandomSongOrder();\r\n\t\ts_xbox_random_index = 0;\r\n\t\ts_xbox_user_soundtrack_song = sp_xbox_randomized_songs[0];\r\n\t}\r\n#\tendif // __PLAT_XBOX__\r\n\t\r\n\tDbg_MsgAssert(gCurrentTrackList>=0 && gCurrentTrackList<NUM_TRACKLISTS,(\"Bad gCurrentTrackList\"));\r\n\tTrackList *pTrackList = &gTrackLists[ gCurrentTrackList ];\r\n\tpTrackList->trackPlayed0=0;\r\n    pTrackList->trackPlayed1=0;\r\n}\r\n\r\nint GetRandomMode( void )\r\n{\r\n\treturn ( gMusicInRandomMode );\r\n}\r\n\r\nvoid SetLoopingMode( bool loop )\r\n{\r\n\tgMusicLooping = loop;\r\n}\r\n\r\n#if WAIT_AFTER_STOP_STREAM\r\nstatic void _StartMusicStream()\r\n{\r\n\tswitch (gMusicStreamType)\r\n\t{\r\n\tcase MUSIC_STREAM_TYPE_NORMAL:\r\n\t\t_PlayMusicStream( gMusicStreamChecksum, gMusicStreamVolume );\r\n\t\tbreak;\r\n\r\n\tcase MUSIC_STREAM_TYPE_PRELOAD:\r\n\t\t_PreLoadMusicStream( gMusicStreamChecksum );\r\n\t\tbreak;\r\n\r\n\tcase MUSIC_STREAM_TYPE_NONE:\r\n\t\tDbg_MsgAssert(0, (\"Bad start music stream state\"));\r\n\t\tbreak;\r\n\t}\r\n\r\n\t// No longer waiting\r\n\tgMusicStreamWaitingToStart = false;\r\n}\r\n#endif // WAIT_AFTER_STOP_STREAM\r\n\r\nstatic void sSetCorrectMusicVolume()\r\n{\r\n\t#ifdef __PLAT_XBOX__\r\n\tif (s_xbox_play_user_soundtracks)\r\n\t{\r\n\t\t// This 'if' is part of the fix to TT6957, where user soundtracks were getting sfx vol\r\n\t\t// when music vol turned down to zero.\r\n\t\tPCMAudio_SetMusicVolume( Pcm::GetVolume() );\r\n\t}\r\n\telse if (gCurrentTrackList == TRACKLIST_LEVEL_SPECIFIC)\r\n\t{\r\n\t\tSfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\t\tPCMAudio_SetMusicVolume( sfx_manager->GetMainVolume() );\r\n\t}\r\n\t#else\r\n\t// Ken: I added this as a fix to TT5588, 'ambient tracks don't play when music vol is set to zero'\r\n\t// This forces the ambient track to use the sfx volume rather than gMusicVolume.\r\n\t// Hopefully there is not too much of an overhead to calling PCMAudio_SetMusicVolume ...\r\n\t// This bit of code won't be executed every frame though, but every SONG_UPDATE_INTERVAL frames,\r\n\t// so I think it'll be OK ...\r\n\tif (gCurrentTrackList == TRACKLIST_LEVEL_SPECIFIC)\r\n\t{\r\n\t\tSfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\t\t//printf(\"Playing ambient track: Forcing volume to %f ...\\n\",sfx_manager->GetMainVolume());\r\n\t\tPCMAudio_SetMusicVolume( sfx_manager->GetMainVolume() );\r\n\t}\r\n\t#endif\r\n}\r\n\r\nvoid RandomTrackUpdate( void )\r\n{\r\n\t\r\n\tTrackList *pTrackList = &gTrackLists[ gCurrentTrackList ];\r\n\t\r\n\tif (NoMusicPlease()) return;\r\n\t\r\n\t\r\n\tif ( pTrackList->allTracksForbidden )\r\n\t{\r\n//\t\tDbg_Message( \"all tracks forbidden.. random mode\" );\r\n\t\treturn;\r\n\t}\r\n\tint pcmStatus = PCMAudio_GetMusicStatus( );\r\n\tif ( pcmStatus == PCM_STATUS_FREE )\r\n\t{\r\n\t#if WAIT_AFTER_STOP_STREAM\r\n\t\t// If we were waiting for StopMusic() to finish, we need to start the music stream\r\n\t\tif (gMusicStreamWaitingToStart)\r\n\t\t{\r\n\t\t\t_StartMusicStream();\r\n\t\t\treturn;\r\n\t\t}\r\n\t#endif // WAIT_AFTER_STOP_STREAM\r\n\r\n\t\tgMusicStreamType = MUSIC_STREAM_TYPE_NONE;\t\t// Just in case we were playing a music stream\r\n\t\tsSetCorrectMusicVolume();\r\n\r\n\t\t// Replay track if looping\r\n\t\tif (gMusicLooping)\r\n\t\t{\r\n\t\t\tPlayTrack( gTrackName, true );\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\tif ( !pTrackList->numTracks )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"AllTracksForbidden flag should be set if no tracks exist.\" ));\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n        if ( shuffle_random_songs )\r\n        {\r\n            // Remember the last song in the previous order, so we can make sure that\r\n        \t// the first song in the new order is different from it.\r\n        \t// Note: OK if the last song was just an uninitialised random value, won't cause any problems.\r\n        \tint last_song=sp_random_song_order[num_random_songs-1];\r\n            \r\n            // count active tracks\r\n            num_random_songs=0;\r\n            for (int i=0; i<pTrackList->numTracks; ++i)\r\n            {\r\n                if ( i < 64)\r\n                {\r\n                    if ( !( pTrackList->trackForbidden0 & ( ((uint64)1) << i ) ) )\r\n                    {\r\n                        // Intialize order\r\n                        sp_random_song_order[num_random_songs]=i;\r\n                        // add one\r\n                        num_random_songs++;\r\n                    }\r\n                }\r\n                else\r\n                {\r\n                    if ( !( pTrackList->trackForbidden1 & ( ((uint64)1) << (i-64) ) ) )\r\n                    {\r\n                        // Intialize order\r\n                        sp_random_song_order[num_random_songs]=i;\r\n                        // add one\r\n                        num_random_songs++;\r\n                    }\r\n                }\r\n            }\r\n\r\n            // need to shuffle order\r\n            printf(\"shuffling random song order num_songs=%i\\n\", num_random_songs );\r\n            \r\n            // Jumble it up.\t\t\r\n        \tfor (int n=0; n<2000; ++n)\r\n        \t{\r\n        \t\tint a=Mth::Rnd(num_random_songs);\r\n        \t\tint b=Mth::Rnd(num_random_songs);\r\n        \t\t\r\n                if ( a != b )\r\n                {\r\n                    int temp=sp_random_song_order[a];\r\n            \t\tsp_random_song_order[a]=sp_random_song_order[b];\r\n            \t\tsp_random_song_order[b]=temp;\r\n                }\r\n        \t}\r\n        \t\r\n            // If the first song in the new order equals the last song of the last order,\r\n        \t// do one further swap to make sure it is different.\r\n        \tif (sp_random_song_order[0]==last_song)\r\n        \t{\r\n        \t\t// a is the first song.\r\n        \t\tint a=0;\r\n        \t\t\r\n        \t\t// Choose b to be a random one of the other songs.\r\n        \t\tint b;\r\n        \t\tif (num_random_songs>1)\r\n        \t\t{\r\n        \t\t\t// Make b not able to equal 0, so that we don't swap the first with itself.\r\n        \t\t\tb=1+Mth::Rnd(num_random_songs-1);\r\n        \t\t}\r\n        \t\telse\r\n        \t\t{\r\n        \t\t\t// Unless there is only one song, in which case just swap it with itself. No point but what the heck.\r\n        \t\t\tb=0;\r\n        \t\t}\r\n        \t\t\r\n        \t\t// Do the swap.\r\n        \t\tint temp=sp_random_song_order[a];\r\n        \t\tsp_random_song_order[a]=sp_random_song_order[b];\r\n        \t\tsp_random_song_order[b]=temp;\r\n        \t}\r\n            \r\n            // reset index\r\n            random_song_index=0;\r\n            shuffle_random_songs=false;\r\n            pTrackList->trackPlayed0 = 0;\r\n            pTrackList->trackPlayed1 = 0;\r\n        }\r\n        else\r\n        {\r\n            random_song_index++;\r\n            if ( random_song_index >= (num_random_songs-1) )\r\n            {\r\n                shuffle_random_songs=true;\r\n            }\r\n        }\r\n        \r\n        for ( int i = 0; i < pTrackList->numTracks; i++ )\r\n\t\t{\r\n\t\t\tint t = ( sp_random_song_order[random_song_index] );\r\n            //printf(\"index = %i song = %i\\n\", random_song_index, sp_random_song_order[random_song_index] );\r\n\r\n            if ( ( !( pTrackList->trackForbidden0 & ( ((uint64)1) << t ) ) && ( t < 64 ) && \r\n                   !( pTrackList->trackPlayed0 & ( ((uint64)1) << t ) ) ) )\r\n\t\t\t{\r\n\t\t\t\tpTrackList->trackPlayed0 |= ( ((uint64)1) << t );\r\n\t\t\t\tPlayTrack( pTrackList->trackInfo[ t ].trackName );\r\n                current_music_track=t;\r\n\t\t\t\tDbg_Message( \"Playing track %s %i %i\", pTrackList->trackInfo[ t ].trackName, t, current_music_track );\r\n\r\n                // update track text on screen\r\n                Script::CStruct *pParams = new Script::CStruct;\r\n                pParams->AddInteger(CRCD(0x8d02705d,\"current_track\"),current_music_track);\r\n                Script::RunScript( \"spawn_update_music_track_text\", pParams );\r\n                delete pParams;\r\n\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n            if ( ( !( pTrackList->trackForbidden1 & ( ((uint64)1) << (t-64) ) ) && ( t >= 64 ) && \r\n                   !( pTrackList->trackPlayed1 & ( ((uint64)1) << (t-64) ) ) )\r\n               )\r\n\t\t\t{\r\n\t\t\t\tpTrackList->trackPlayed1 |= ( ((uint64)1) << (t-64) );\r\n\t\t\t\tPlayTrack( pTrackList->trackInfo[ t ].trackName );\r\n                current_music_track=t;\r\n\t\t\t\tDbg_Message( \"Playing track %s %i %i\", pTrackList->trackInfo[ t ].trackName, t, current_music_track );\r\n\r\n                // update track text on screen\r\n                Script::CStruct *pParams = new Script::CStruct;\r\n                pParams->AddInteger(CRCD(0x8d02705d,\"current_track\"),current_music_track);\r\n                Script::RunScript( \"spawn_update_music_track_text\", pParams );\r\n                delete pParams;\r\n\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid TrackUpdate( void )\r\n{\r\n\t\r\n\r\n\tif (NoMusicPlease()) return;\r\n\t\r\n\tint trackList = gCurrentTrackList;\r\n\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tif ( skate_mod->GetGameMode( )->IsFrontEnd( ) )\r\n\t{\r\n\t\ttrackList = TRACKLIST_LEVEL_SPECIFIC;\r\n\t}\r\n\r\n\tTrackList *pTrackList = &gTrackLists[ trackList ];\r\n\t\r\n\tif ( pTrackList->allTracksForbidden )\r\n\t{\r\n//\t\tDbg_Message( \"all tracks forbidden.. sequential mode\" );\r\n\t\treturn;\r\n\t}\r\n\tint pcmStatus = PCMAudio_GetMusicStatus( );\r\n\tif ( pcmStatus == PCM_STATUS_FREE )\r\n\t{\r\n\t#if WAIT_AFTER_STOP_STREAM\r\n\t\t// If we were waiting for StopMusic() to finish, we need to start the music stream\r\n\t\tif (gMusicStreamWaitingToStart)\r\n\t\t{\r\n\t\t\t_StartMusicStream();\r\n\t\t\treturn;\r\n\t\t}\r\n\t#endif // WAIT_AFTER_STOP_STREAM\r\n\r\n\t\tgMusicStreamType = MUSIC_STREAM_TYPE_NONE;\t\t// Just in case we were playing a music stream\r\n\t\tsSetCorrectMusicVolume();\r\n\t\t\r\n\t\t// Replay track if looping\r\n\t\tif (gMusicLooping)\r\n\t\t{\r\n\t\t\tPlayTrack( gTrackName, true );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// don't have a random function.  just play next track...\r\n\t\tint i;\r\n\t\tfor ( i = 0; i < pTrackList->numTracks; i++ )\r\n\t\t{\r\n            if ( ( !( pTrackList->trackForbidden0 & ( ((uint64)1) << i ) ) && ( i < 64 ) && \r\n                   !( pTrackList->trackPlayed0 & ( ((uint64)1) << i ) ) ) )\r\n\t\t\t{\r\n\t\t\t\tpTrackList->trackPlayed0 |= ( ((uint64)1) << i );\r\n\t\t\t\tPlayTrack( pTrackList->trackInfo[ i ].trackName );\r\n                current_music_track=i;\r\n\t\t\t\tDbg_Message( \"Playing track %s %i %i\", pTrackList->trackInfo[ i ].trackName, i, current_music_track );\r\n\r\n                // update track text on screen\r\n                Script::CStruct *pParams = new Script::CStruct;\r\n                pParams->AddInteger(CRCD(0x8d02705d,\"current_track\"),current_music_track);\r\n                Script::RunScript( \"spawn_update_music_track_text\", pParams );\r\n                delete pParams;\r\n\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n            if ( ( !( pTrackList->trackForbidden1 & ( ((uint64)1) << (i-64) ) ) && ( i >= 64 ) && \r\n                   !( pTrackList->trackPlayed1 & ( ((uint64)1) << (i-64) ) ) ) )\r\n\t\t\t{\r\n\t\t\t\tpTrackList->trackPlayed1 |= ( ((uint64)1) << (i-64) );\r\n\t\t\t\tPlayTrack( pTrackList->trackInfo[ i ].trackName );\r\n                current_music_track=i;\r\n\t\t\t\tDbg_Message( \"Playing track %s %i %i\", pTrackList->trackInfo[ i ].trackName, i, current_music_track );\r\n\r\n                // update track text on screen\r\n                Script::CStruct *pParams = new Script::CStruct;\r\n                pParams->AddInteger(CRCD(0x8d02705d,\"current_track\"),current_music_track);\r\n                Script::RunScript( \"spawn_update_music_track_text\", pParams );\r\n                delete pParams;\r\n\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\t// all the tracks have been played... reset:\r\n\t\tpTrackList->trackPlayed0 = 0;\r\n        pTrackList->trackPlayed1 = 0;\r\n\t}\r\n}\r\n\r\n//powers of 2 please...\r\n#define SONG_UPDATE_INTERVAL\t\t\t\t\t64\r\n#define STREAM_POSITIONAL_UPDATE_INTERVAL\t\t4\r\n\r\n// Call this function every frame...\r\n// keeps tracks playing during levels and shit like that...\r\nvoid Update( void )\r\n{\r\n\t\r\n\t//static int streamingObjToUpdate = 0;\r\n\r\n\tif (NoMusicPlease() && StreamsDisabled()) return;\r\n\t\r\n\tDbg_MsgAssert( gPcmInitialized,( \"Calling Pcm::Update when PCM Audio not initialized.\" ));\r\n\r\n\tint err_no = PCMAudio_Update( );\r\n\tif ( err_no != 0 )\r\n\t{\r\n\t\tif (err_no < 0)\r\n\t\t{\r\n\t\t\tStopStreams( );\r\n\t\t\tStopMusic( );\r\n\t\t} else {\r\n\t\t\t// Even though we are returning the stream number, lets just kill them all because we are at the end of the project\r\n\t\t\tStopStreams( );\r\n\t\t}\r\n\t}\r\n\r\n\t// Garrett: This should go away, since the IOP communication is async now.  But I left it in for\r\n\t// the music now since I don't know if there is a CPU hit there.\r\n\tsCounter++;\r\n\r\n\t//if ( !( sCounter & ( STREAM_POSITIONAL_UPDATE_INTERVAL - 1 ) ) )\r\n\tfor (int streamingObjToUpdate = 0; streamingObjToUpdate < NUM_STREAMS; streamingObjToUpdate++)\r\n\t{\r\n\t\tif ( gpStreamingObj[ streamingObjToUpdate ] )\r\n\t\t{\r\n\t\t\tif ( !SetStreamVolume( streamingObjToUpdate ) )\r\n\t\t\t{\r\n\t\t\t\tgpStreamingObj[ streamingObjToUpdate ]->mStreamingID[ streamingObjToUpdate ] = 0;\r\n\t\t\t\tgpStreamingObj[ streamingObjToUpdate ] = NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t\t//// update the other one next time...\r\n\t\t//streamingObjToUpdate++;\r\n\t\t//if ( streamingObjToUpdate >= NUM_STREAMS )\r\n\t\t//{\r\n\t\t//\tstreamingObjToUpdate = 0;\r\n\t\t//}\r\n\t}\r\n\r\n\t// Free any frame amp data that was used by a stream that already stopped\r\n\tfor (int i = 0; i < NUM_STREAMS; i++)\r\n\t{\r\n\t\tif (gCurrentStreamInfo[i].p_frame_amp && (PCMAudio_GetStreamStatus(gCurrentStreamInfo[i].voice) == PCM_STATUS_FREE))\r\n\t\t{\r\n\t\t\tDbg_Message(\"Clearing StreamFrameAmp %s\", Script::FindChecksumName(gCurrentStreamInfo[i].controlID));\r\n\t\t\tCStreamFrameAmpManager::sFreeFrameAmp(gCurrentStreamInfo[i].p_frame_amp);\r\n\t\t\tgCurrentStreamInfo[i].p_frame_amp = NULL;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( sCounter & ( SONG_UPDATE_INTERVAL - 1 ) )\r\n\t\treturn;\r\n\r\n\t// if volume is turned all the way down, the current song will finish\r\n\t// playing and then we'll keep returning here until volume isn't zero,\r\n\t// as soon as it is turned up a new song will begin playing.\r\n\tif ( gMusicVolume == 0.0f && gCurrentTrackList != TRACKLIST_LEVEL_SPECIFIC) \r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t#ifdef __PLAT_XBOX__\r\n\t// This is part of the fix to TT6957, \r\n\t// where user soundtracks were getting sfx vol when music vol turned down to zero.\r\n\t// (The other part of the fix is a bit further down, search for TT6957)\r\n\tif ( gMusicVolume == 0.0f && s_xbox_play_user_soundtracks) \r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t#endif\r\n\t\r\n\tif (sMusicIsPaused)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\r\n\t// K: Commented this out since it does not appear to be needed, and was stopping random\r\n\t// track mode from working on XBox & Gamecube, I think because is_frontend is defined to\r\n\t// be 1 in mode_skateshop in gamemode.q. I commented this out instead of changing\r\n\t// is_frontend to 0 in case that broke something else.\t\t\r\n\t\r\n\t// don't play music in the frontend: <- old comment\r\n\t/*\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tif ( skate_mod->GetGameMode( )->IsFrontEnd( ) )\r\n\t{\r\n\t\tTrackUpdate( );\r\n\t\treturn;\r\n\t}\r\n\t*/\r\n\r\n\t\t\r\n\t// if song is finished, start a new one playing...\r\n\tif ( gMusicInRandomMode || ( gCurrentTrackList == TRACKLIST_LEVEL_SPECIFIC ) )\r\n\t\tRandomTrackUpdate( );\r\n\telse\r\n\t\tTrackUpdate( );\r\n}\r\n\r\nvoid GetPlaylist( uint64* flags1, uint64* flags2 )\r\n{\r\n    *flags1 = gTrackLists[ TRACKLIST_PERM ].trackForbidden0;\r\n    *flags2 = gTrackLists[ TRACKLIST_PERM ].trackForbidden1;\r\n}\r\n\r\nvoid SetPlaylist( uint64 flags1, uint64 flags2 )\r\n{\r\n\tgTrackLists[ TRACKLIST_PERM ].trackForbidden0 = flags1;\r\n    gTrackLists[ TRACKLIST_PERM ].trackForbidden1 = flags2;\r\n}\r\n\r\n// Ambient volume is the same as SoundFX volume...\r\nvoid SetAmbientVolume( float volPercent )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tif ( skate_mod->GetGameMode( )->IsFrontEnd( ) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tif ( gCurrentTrackList == TRACKLIST_LEVEL_SPECIFIC )\r\n\t{\r\n\t\tPCMAudio_SetMusicVolume( volPercent );\r\n\t}\r\n}\r\n\r\n// set a particular song as 'forbidden' (don't play it, the player hates that song...)\r\nvoid SetTrackForbiddenStatus( int trackNum, bool forbidden, int whichList )\r\n{\r\n    if (NoMusicPlease()) return;\r\n\t\r\n    shuffle_random_songs=true;\r\n\r\n\tint i;\r\n\tDbg_MsgAssert( whichList < NUM_TRACKLISTS,( \"Dumbass.\" ));\r\n\tTrackList *pTrackList = &gTrackLists[ whichList ];\r\n\tDbg_MsgAssert( trackNum < pTrackList->numTracks,( \"Not that many tracks in list.\" ));\r\n\tif ( forbidden )\r\n\t{\r\n\t\tif ( trackNum < 64)\r\n        {\r\n            pTrackList->trackForbidden0 |= ( ((uint64)1) << trackNum );\r\n        }\r\n        else\r\n        {\r\n            pTrackList->trackForbidden1 |= ( ((uint64)1) << (trackNum-64) );\r\n        }\r\n        \r\n        if ( TrackIsPlaying( whichList, trackNum ) )\r\n\t\t{\r\n\t\t\tStopMusic( );\r\n\t\t}\r\n\t\tfor ( i = 0; i < pTrackList->numTracks; i++ )\r\n\t\t{\r\n\t\t\tif ( !( pTrackList->trackForbidden0 & ( ((uint64)1) << i ) ) || !( pTrackList->trackForbidden1 & ( ((uint64)1) << (i-64) ) ) )\r\n\t\t\t{\r\n\t\t\t\tpTrackList->allTracksForbidden = false;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\tpTrackList->allTracksForbidden = true;\r\n\t\treturn;\r\n\t}\r\n\t\r\n    if ( trackNum < 64)\r\n    {\r\n        pTrackList->trackForbidden0 &= ~( ((uint64)1) << trackNum );\r\n    }\r\n    else\r\n    {\r\n        pTrackList->trackForbidden1 &= ~( ((uint64)1) << (trackNum-64) );\r\n    }\r\n\tpTrackList->allTracksForbidden = false;\r\n}\r\n\r\n/*void CheckLockedTracks()\r\n{\r\n    if ( !Mdl::Skate::Instance()->GetCareer()->GetGlobalFlag(286) )\r\n    {\r\n        // if the kiss songs aren't unlocked make sure they stay forbidden\r\n        SetTrackForbiddenStatus( 32, true, Pcm::TRACKLIST_PERM );\r\n        SetTrackForbiddenStatus( 33, true, Pcm::TRACKLIST_PERM );\r\n    }\r\n}*/\r\n\r\nbool TrackIsPlaying( int whichList, int whichTrack )\r\n{\r\n\t\r\n\tif (NoMusicPlease()) return false;\r\n\t\r\n\tDbg_MsgAssert( gPcmInitialized,( \"Calling Pcm func when PCM Audio not initialized.\" ));\r\n\tint pcmStatus = PCMAudio_GetMusicStatus( );\r\n\tif ( pcmStatus == PCM_STATUS_FREE )\r\n\t\treturn ( false );\r\n\tif ( whichTrack >= gTrackLists[ whichList ].numTracks )\r\n\t\treturn ( false );\r\n\t// can't do a strcmp, because files in gTrackName have been converted to all uppercase...\r\n\tif ( Script::GenerateCRC( gTrackName ) == Script::GenerateCRC( gTrackLists[ whichList ].trackInfo[ whichTrack ].trackName ) )\r\n\t\treturn ( true );\r\n\treturn ( false );\r\n}\r\n\r\nint GetNumTracks( int whichList )\r\n{\r\n\t\r\n\r\n\tif (NoMusicPlease()) return 0;\r\n\t\r\n\r\n\tDbg_MsgAssert( whichList < NUM_TRACKLISTS,( \"Dumbass.\" ));\r\n\tTrackList *pTrackList = &gTrackLists[ whichList ];\r\n\treturn ( pTrackList->numTracks );\r\n}\r\n\r\nint GetTrackForbiddenStatus( int trackNum, int whichList )\r\n{\r\n\t\r\n\r\n\tif (NoMusicPlease()) return 1;\r\n\t\r\n\t\r\n\tDbg_MsgAssert( whichList < NUM_TRACKLISTS,( \"Dumbass.\" ));\r\n\tTrackList *pTrackList = &gTrackLists[ whichList ];\r\n\tDbg_MsgAssert( trackNum < pTrackList->numTracks,( \"Requesting forbidden status on invalid track.\" ));\r\n\t\r\n    if ( trackNum < 64 )\r\n    {\r\n        if (pTrackList->trackForbidden0 & ( ((uint64)1) << trackNum ))\r\n    \t{\r\n    \t\treturn true;\r\n    \t}\r\n    \telse\r\n    \t{\r\n    \t\treturn false;\r\n    \t}\r\n    }\r\n    else\r\n    {\r\n        if (pTrackList->trackForbidden1 & ( ((uint64)1) << (trackNum-64) ))\r\n    \t{\r\n    \t\treturn true;\r\n    \t}\r\n    \telse\r\n    \t{\r\n    \t\treturn false;\r\n    \t}\r\n    }\r\n}\r\n\r\nconst char *GetTrackName( int trackNum, int whichList )\r\n{\r\n\t\r\n\r\n\tif (NoMusicPlease())\r\n\t{\r\n\t\tstrcpy( gTrackLists[ 0 ].trackInfo[ 0 ].trackName, \"Empty.\" );\r\n\t\treturn ( gTrackLists[ 0 ].trackInfo[ 0 ].trackName );\r\n\t}\r\n\t\r\n\t//if ( whichList == TRACKLIST_PERM )\r\n\t//{\r\n\t//\tDbg_MsgAssert( trackNum < MAX_NUM_TRACKS, ( \"Invalid track num specified.\" ) );\r\n\t//\treturn ( PermTrackTitle[ trackNum ].trackTitle );\r\n\t//}\r\n\r\n\tDbg_MsgAssert( whichList < NUM_TRACKLISTS,( \"Dumbass.\" ));\r\n\tTrackList *pTrackList = &gTrackLists[ whichList ];\r\n\tDbg_MsgAssert( trackNum < pTrackList->numTracks,( \"Requesting invalid track name.\" ));\r\n\tint i;\r\n\tchar *pText = pTrackList->trackInfo[ trackNum ].trackName;\r\n\tchar *pRet = pText;\r\n\tint len = strlen( pText );\r\n\tfor ( i = 0; i < len; i++ )\r\n\tif ( ( pText[ i ] == '\\\\' ) || ( pText[ i ] == '/' ) )\r\n\t\tpRet = &pText[ i + 1 ];\r\n\treturn ( pRet );\r\n}\r\n\r\n// Ambient (TRACKLIST_LEVEL_SPECIFIC) or music (TRACKLIST_PERM)\r\nvoid SetActiveTrackList( int whichList )\r\n{\r\n\t\r\n\r\n\tif (NoMusicPlease()) return;\r\n\t\r\n\tDbg_MsgAssert( whichList < NUM_TRACKLISTS,( \"Dumbass.\" ));\r\n\tif ( gCurrentTrackList != whichList )\r\n\t{\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tif ( !skate_mod->GetGameMode( )->IsFrontEnd( ) )\r\n\t\t{\r\n\t\t\tStopMusic( );\r\n\t\t}\r\n\t}\r\n\tgCurrentTrackList = whichList;\r\n}\r\n\r\n// A user can choose to listen to music or ambience during gameplay.\r\nint GetActiveTrackList( void )\r\n{\r\n\t\r\n\treturn ( gCurrentTrackList );\r\n}\r\n\r\n// A music header contains the names and sizes of all the music files available:\r\nbool LoadMusicHeader( const char *nameOfFile )\r\n{\r\n\tif (NoMusicPlease()) return false;\r\n\t\r\n\tmusic_hed_there =( PCMAudio_LoadMusicHeader( nameOfFile ) );\r\n\t\r\n\treturn\tmusic_hed_there; \r\n}\r\n\r\n// Headers contain all available streams (probably will be one header per level).\r\nbool LoadStreamHeader( const char *nameOfFile )\r\n{\r\n\tif (StreamsDisabled()) return false;\r\n\t\r\n\tstreams_hed_there = PCMAudio_LoadStreamHeader( nameOfFile );\r\n\r\n\treturn streams_hed_there;\r\n}\r\n\r\nint GetNumStreamsAvailable( void )\r\n{\r\n\treturn ( NUM_STREAMS );\r\n}\r\n\r\nbool StreamAvailable( int whichStream )\r\n{\r\n\tif (StreamsDisabled()) return false;\r\n\t\r\n\tif ( PCMAudio_GetStreamStatus( whichStream ) == PCM_STATUS_FREE )\r\n\t{\r\n\t\treturn ( true );\r\n\t}\r\n\treturn ( false );\r\n}\r\n\r\nbool StreamAvailable( void )\r\n{\r\n\r\n\tif (StreamsDisabled()) return false;\r\n\t\r\n\tif (!(Config::CD() || TEST_FROM_CD))\r\n\t{\r\n\t\tint testStreams = 0;\r\n\t\ttestStreams = Script::GetInt( 0x62df9442, false ); // checksum 'testStreamsFromHost'\r\n\t\tif ( !testStreams )\r\n\t\t{\r\n\t\t\treturn ( true );\r\n\t\t}\r\n\t}\r\n\r\n//\treturn ( PCMAudio_GetStreamStatus( 0 ) == PCM_STATUS_FREE );\r\n\r\n\tint i;\r\n\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t{\r\n\t\tif ( PCMAudio_GetStreamStatus( i ) == PCM_STATUS_FREE )\r\n\t\t{\r\n\t\t\treturn ( true );\r\n\t\t}\r\n\t}\r\n\treturn ( false );\r\n}\r\n\r\nbool StreamExists( uint32 streamChecksum )\r\n{\r\n\t// try to find the name in the header file using the checksum:\r\n\tuint32 streamName = PCMAudio_FindNameFromChecksum( streamChecksum, EXTRA_CHANNEL );\r\n\treturn ( streamName != NULL );\r\n}\r\n\r\nbool StreamLoading( uint32 streamID )\r\n{\r\n\tif (StreamsDisabled()) return false;\r\n\t\r\n\tif (!(Config::CD() || TEST_FROM_CD))\r\n\t{\r\n\t\tint testStreams = 0;\r\n\t\ttestStreams = Script::GetInt( 0x62df9442, false ); // checksum 'testStreamsFromHost'\r\n\t\tif ( !testStreams )\r\n\t\t{\r\n\t\t\treturn ( false );\r\n\t\t}\r\n\t}\r\n\r\n\tint channel = GetChannelFromID(streamID);\r\n\r\n\tif ( channel >= 0 )\r\n\t{\r\n\t\treturn ( PCMAudio_GetStreamStatus( channel ) == PCM_STATUS_LOADING );\r\n\t}\r\n\r\n\treturn ( false );\r\n}\r\n\r\nbool StreamPlaying( uint32 streamID )\r\n{\r\n\tif (StreamsDisabled()) return false;\r\n\t\r\n\tint channel = GetChannelFromID(streamID, false);\r\n\r\n\tif ( channel >= 0 )\r\n\t{\r\n\t\treturn true;\t// Even if it is in loading state\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nint GetCurrentTrack()\r\n{\r\n    return ( current_music_track );\r\n}\r\n\r\nvoid SetCurrentTrack( int value )\r\n{\r\n    current_music_track=value;\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// Pcm::CStreamFrameAmp\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCStreamFrameAmp::CStreamFrameAmp()\r\n{\r\n\tInit();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCStreamFrameAmp::~CStreamFrameAmp()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCStreamFrameAmp::Init()\r\n{\r\n\tm_checksum = vNOT_ALLOCATED;\r\n\tm_num_samples = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\t\t\t\tCStreamFrameAmp::GetSample(int frame) const\r\n{\r\n\tDbg_Assert(is_allocated());\r\n\tDbg_Assert(frame < m_num_samples);\r\n\r\n\treturn m_frame_amp_samples[frame];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst uint8 *\t\tCStreamFrameAmp::GetSamples() const\r\n{\r\n\tDbg_Assert(is_allocated());\r\n\r\n\treturn m_frame_amp_samples;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst uint8 *\t\tCStreamFrameAmp::GetSamples(int frame) const\r\n{\r\n\tDbg_Assert(is_allocated());\r\n\tDbg_Assert(frame < m_num_samples);\r\n\r\n\treturn &m_frame_amp_samples[frame];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\t\tCStreamFrameAmp::GetNumSamples() const\r\n{\r\n\treturn m_num_samples;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCStreamFrameAmp::load(uint32 stream_checksum)\r\n{\r\n\tFile::CAsyncFileHandle *p_handle;\r\n\tchar filename[256];\r\n\r\n\t// Generate filename from checksum\r\n\tsprintf(filename,\"fam\\\\%x.fam\", stream_checksum);\r\n\r\n\t// Open with async blocking for now.  Look to make truly async later.\r\n\tp_handle = File::CAsyncFileLoader::sOpen(filename, true);\r\n\tif (p_handle)\r\n\t{\r\n\t\tm_num_samples = p_handle->GetFileSize();\r\n\t\tif (m_num_samples >= vMAX_SAMPLES)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\".fam file has too many samples: %d\", m_num_samples));\r\n\t\t\tFile::CAsyncFileLoader::sClose(p_handle);\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tp_handle->Read(m_frame_amp_samples, 1, m_num_samples);\r\n\t\tFile::CAsyncFileLoader::sClose(p_handle);\r\n\r\n\t\tm_checksum = stream_checksum;\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCStreamFrameAmp::free()\r\n{\r\n\tif (is_allocated())\r\n\t{\r\n\t\t// Easiest way to clear, since there is nothing to de-allocate.\r\n\t\tInit();\r\n\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// Pcm::CStreamFrameAmpManager\r\n\r\nCStreamFrameAmp\t\tCStreamFrameAmpManager::s_frame_amp_data[vMAX_BUFFERS];\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCStreamFrameAmp *\tCStreamFrameAmpManager::sLoadFrameAmp(uint32 stream_checksum)\r\n{\r\n\tfor (int i = 0; i < vMAX_BUFFERS; i++)\r\n\t{\r\n\t\tif (!s_frame_amp_data[i].is_allocated())\r\n\t\t{\r\n\t\t\tif (s_frame_amp_data[i].load(stream_checksum))\r\n\t\t\t{\r\n\t\t\t\treturn &s_frame_amp_data[i];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// If we got here, there weren't any free slots\r\n\t\t\t\tDbg_MsgAssert(0, (\"Couldn't load StreamFrameAmp %s\", Script::FindChecksumName(stream_checksum)));\r\n\t\t\t\treturn NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// If we got here, there weren't any free slots\r\n\tDbg_MsgAssert(0, (\"Can't load StreamFrameAmp %s: no free slots\", Script::FindChecksumName(stream_checksum)));\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCStreamFrameAmp *\tCStreamFrameAmpManager::sGetFrameAmp(uint32 stream_checksum)\r\n{\r\n\tfor (int i = 0; i < vMAX_BUFFERS; i++)\r\n\t{\r\n\t\tif (s_frame_amp_data[i].GetStreamNameCRC() == stream_checksum)\r\n\t\t{\r\n\t\t\treturn &s_frame_amp_data[i];\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCStreamFrameAmpManager::sFreeFrameAmp(uint32 stream_checksum)\r\n{\r\n\tfor (int i = 0; i < vMAX_BUFFERS; i++)\r\n\t{\r\n\t\tif (s_frame_amp_data[i].GetStreamNameCRC() == stream_checksum)\r\n\t\t{\r\n\t\t\treturn s_frame_amp_data[i].free();\r\n\t\t}\r\n\t}\r\n\r\n\t// If we got here, we didn't find it\r\n\tDbg_MsgAssert(0, (\"Can't find StreamFrameAmp %s data to free\", Script::FindChecksumName(stream_checksum)));\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCStreamFrameAmpManager::sFreeFrameAmp(CStreamFrameAmp *p_fam_data)\r\n{\r\n\treturn p_fam_data->free();\r\n}\r\n\r\n}  // namespace Pcm\r\n"
  },
  {
    "path": "Code/Gel/Music/music.h",
    "content": "/*\tStream audio off the disc...\r\n\tPlay music tracks or what not.\r\n\t\r\n\tmd Jan 2001\r\n*/\r\n\r\n#ifndef __MUSIC_H__\r\n#define __MUSIC_H__\r\n\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n// change the following line to compile out music or streams:\r\n#define NO_MUSIC_PLEASE\t0\r\n#define DISABLE_STREAMS\t0\r\n\r\nnamespace Obj\r\n{\r\n\tclass CStreamComponent;\r\n}\r\n\t\t\t\r\nnamespace Pcm\r\n{\r\n\r\n// Forward declarations\r\nclass CStreamFrameAmp;\r\nclass CStreamFrameAmpManager;\r\n\r\n\r\n#define NUM_CHANNELS\t\t\t\t2\r\n\r\n#define DEFAULT_MUSIC_VOLUME\t\t50.0f\r\n#define DEFAULT_MUSIC_STREAM_VOLUME\t100.0f\r\n\r\n#define MAX_NUM_TRACKS\t\t\t\t80\r\n#define MAX_TRACKNAME_STRING_LENGTH\t40\r\n#define TRACK_TITLE_MAX_SIZE\t\t100\r\n\r\n#define DEFAULT_STREAM_DROPOFF\t\tDEFAULT_DROPOFF_DIST\r\n\r\n#define STREAM_DEFAULT_PRIORITY\t\t(50)\t\t// Stream priority that is used when not set\r\n\r\nenum EMusicStreamType\r\n{\r\n\tMUSIC_STREAM_TYPE_NONE = 0,\r\n\tMUSIC_STREAM_TYPE_NORMAL,\r\n\tMUSIC_STREAM_TYPE_PRELOAD,\r\n};\r\n\r\n// Structures\r\nstruct CurrentStreamInfo\r\n{\r\n\tuint32\t\t\t\tcontrolID;\t\t// ID used from script to control stream (default value is checksum of stream)\r\n\tuint32\t\t\t\tuniqueID;\t\t// ID used within code (same as controlID unless this stream is playing on more than 1 channel)\r\n\tfloat\t\t\t\tvolume;\r\n\tfloat\t\t\t\tdropoff;\r\n\tint\t\t\t\t\tvoice;\r\n\tint\t\t\t\t\tpriority;\r\n\tuint32\t\t\t\tstart_frame;\r\n\tbool\t\t\t\tuse_pos_info;\r\n\tEDropoffFunc\t\tdropoffFunction;\r\n\tCStreamFrameAmp *\tp_frame_amp;\r\n};\r\n\r\nstruct TrackInfo\r\n{\r\n\tchar trackName[ MAX_TRACKNAME_STRING_LENGTH ];\r\n};\r\n\r\nstruct TrackTitle\r\n{\r\n\tchar trackTitle[ TRACK_TITLE_MAX_SIZE ];\r\n};\r\n\r\nstruct TrackList\r\n{\r\n\t// on PS2 version, the sceCdlFILE info is put into the end of this string:\r\n\tTrackInfo \t\ttrackInfo[ MAX_NUM_TRACKS ];\r\n\tint\t\t\t\tnumTracks;\r\n\t// the following are bitflags:\r\n\tuint64\t\t\ttrackForbidden0;\r\n    uint64\t\t\ttrackForbidden1;\r\n\tuint64\t\t\ttrackPlayed0;\r\n    uint64\t\t\ttrackPlayed1;\r\n\tbool\t\t\tallTracksForbidden;\r\n};\r\n\r\n\r\nvoid\tInit( void );\r\n\r\nbool NoMusicPlease();\r\nbool StreamsDisabled();\r\n\r\nint GetNumStreamsAvailable( void );\r\nint GetCurrentTrack( void );\r\nvoid SetCurrentTrack( int value );\r\n\r\n// Call update every frame...\r\n// this function checks once every second to see if the previous\r\n// song finished playing... if so it starts a new song.\r\n// Also handles Stop/Play commands.\r\nvoid\tUpdate( void );\r\n\r\nvoid\tPlayTrack( const char *filename, bool loop = false );\r\nvoid\tPlayMusicStream( uint32 checksum, float volume = -1 );\t\t// Plays a stereo stream through the music channels\r\n\r\n// These five only for XBox.\r\nvoid UseUserSoundtrack( int soundtrack );\r\nvoid UseStandardSoundtrack();\r\nbool UsingUserSoundtrack();\r\nvoid SaveSoundtrackToStructure( Script::CStruct *pStuff );\r\nvoid GetSoundtrackFromStructure( Script::CStruct *pStuff );\r\n\r\nuint32\tPlayStream( uint32 checksum, Sfx::sVolume *p_volume, float pitch = 100, int priority = STREAM_DEFAULT_PRIORITY,\r\n\t\t\t\t\tuint32 controlID = 0, bool record_in_replay=true );\r\nuint32\tPlayStreamFromObject( Obj::CStreamComponent *pObject, uint32 streamNameChecksum, float dropoff = 0, float volume = 0,\r\n\t\t\t\t\t\t\t  float pitch = 100, int priority = STREAM_DEFAULT_PRIORITY, int use_pos_info = 0,\r\n\t\t\t\t\t\t\t  EDropoffFunc dropoffFunc = DROPOFF_FUNC_STANDARD, uint32 controlID = 0 );\r\n\r\n// Control functions\r\nbool\tSetStreamVolumeFromID( uint32 streamID, Sfx::sVolume *p_volume );\t\t// For non-object streams\r\nbool\tSetStreamPitchFromID( uint32 streamID, float pitch );\t\t\t\t\t// For non-object streams\r\nvoid\tStopStreamFromID( uint32 streamID );\r\nvoid\tStopStreams( int channel = -1 );\r\nbool\tStreamAvailable( void );\r\nbool\tStreamAvailable( int whichStream );\r\n\r\nbool\tStreamExists( uint32 streamChecksum );\r\n\r\nbool\tStreamLoading( uint32 streamID );\r\nbool\tStreamPlaying( uint32 streamID );\r\n\r\n// Preload streams.  By preloading, you can guarantee they will start at a certain time.\r\nuint32\tPreLoadStream( uint32 checksum, int priority = STREAM_DEFAULT_PRIORITY );\r\nbool\tPreLoadStreamDone( uint32 streamID );\r\nbool\tStartPreLoadedStream( uint32 streamID, Sfx::sVolume* p_volume, float pitch = 100 );\r\n\r\n// Preload Music streams.  By preloading, you can guarantee they will start at a certain time.\r\nbool\tPreLoadMusicStream( uint32 checksum );\r\nbool\tPreLoadMusicStreamDone( void );\r\nbool\tStartPreLoadedMusicStream( float volume = -1 );\r\n\r\n/*\tArg:\t-1 to unpause only if it was unpaused last time pause was called\r\n\t\t\t1 to pause\r\n\t\t\t0 to unpause\r\n*/\r\nvoid\tPauseMusic( int pause );\r\nbool\tMusicIsPaused();\r\nvoid\tPauseStream( int pause );\r\n\r\nvoid\tStopMusic( void );\r\n\r\n// ambient tracks use the soundfx volume instead of music volume:\r\nvoid\tSetAmbientVolume( float volPercent );\r\n\r\nvoid\tSetVolume( float volume );\r\nfloat\tGetVolume( void );\r\nvoid\tSetMusicStreamVolume( float volume );\r\nfloat\tGetMusicStreamVolume( void );\r\nvoid\tGetPlaylist( uint64* flags1, uint64* flags2 );\r\nvoid\tSetPlaylist( uint64 flags1, uint64 flags2 );\r\n\r\nenum{\r\n\t\tTRACKLIST_PERM,\r\n\t\tTRACKLIST_LEVEL_SPECIFIC,\r\n\t\tNUM_TRACKLISTS,\r\n};\r\n\r\n// Music track management:\r\nvoid\tAddTrackToPlaylist( const char *trackName, int whichList, const char *trackTitle = NULL );\r\nvoid\tClearPlaylist( int whichList );\r\n\r\nconst char *GetTrackName( int trackNum, int whichList );\r\nint\t\tGetNumTracks( int whichList );\r\n\r\nbool UsingCD( void );\r\n\r\n// set a particular song as 'forbidden' (don't play it, the player hates that song...)\r\nvoid\tSetTrackForbiddenStatus( int trackNum, bool forbidden, int whichList );\r\n//void\tCheckLockedTracks( );\r\nint\t\tGetTrackForbiddenStatus( int trackNum, int whichList );\r\nvoid\tSkipMusicTrack( void );\r\nvoid\tSetRandomMode( int randomModeOn );\r\nint\t\tGetRandomMode( void );\r\nvoid\tSetLoopingMode( bool loop );\r\n\r\n// Perm list? Or ambient list?\r\nvoid\tSetActiveTrackList( int whichList );\r\nint\t\tGetActiveTrackList( void );\r\n\r\nbool LoadMusicHeader( const char *nameOfFile );\r\nbool LoadStreamHeader( const char *nameOfFile );\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// Pcm::CStreamFrameAmp\r\n\r\nclass CStreamFrameAmp\r\n{\r\npublic:\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tvNOT_ALLOCATED\t\t\t= 0,\t\t\t\t// 0 indicates not allocated\r\n\t\tvMAX_SAMPLES\t\t\t= 4096,\r\n\t};\r\n\r\n\t\t\t\t\t\t\t\tCStreamFrameAmp();\r\n\t\t\t\t\t\t\t\t~CStreamFrameAmp();\r\n\r\n\tvoid\t\t\t\t\t\tInit();\r\n\tuint32\t\t\t\t\t\tGetStreamNameCRC() const;\r\n\r\n\tuint8\t\t\t\t\t\tGetSample(int frame) const;\r\n\tconst uint8 *  \t\t\t\tGetSamples() const;\r\n\tconst uint8 *  \t\t\t\tGetSamples(int frame) const;\r\n\tint\t\t\t\t\t\t\tGetNumSamples() const;\r\n\r\nprotected:\r\n\r\n\tbool\t\t\t\t\t\tload(uint32 stream_checksum);\r\n\tbool\t\t\t\t\t\tfree();\r\n\tbool\t\t\t\t\t\tis_allocated() const;\r\n\r\n\tuint32\t\t\t\t\t\tm_checksum;\r\n\tint\t\t\t\t\t\t\tm_num_samples;\r\n\tuint8\t\t\t\t\t\tm_frame_amp_samples[vMAX_SAMPLES] nAlign(128);\t// Aligned data for the loading code\r\n\r\n\t// Friends\r\n\tfriend CStreamFrameAmpManager;\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// Pcm::CStreamFrameAmpManager\r\nclass CStreamFrameAmpManager\r\n{\r\npublic:\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tvMAX_BUFFERS\t\t\t= 1,\r\n\t};\r\n\r\n\tstatic CStreamFrameAmp *\tsLoadFrameAmp(uint32 stream_checksum);\r\n\tstatic CStreamFrameAmp *\tsGetFrameAmp(uint32 stream_checksum);\r\n\tstatic bool\t\t\t\t\tsFreeFrameAmp(uint32 stream_checksum);\r\n\tstatic bool\t\t\t\t\tsFreeFrameAmp(CStreamFrameAmp *p_fam_data);\r\n\r\nprotected:\r\n\r\n\tstatic CStreamFrameAmp\t\ts_frame_amp_data[vMAX_BUFFERS];\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n\r\ninline uint32\t\t\tCStreamFrameAmp::GetStreamNameCRC() const\r\n{\r\n\treturn m_checksum;\r\n}\r\n\r\ninline bool\t\t\t\tCStreamFrameAmp::is_allocated() const\r\n{\r\n\treturn m_checksum != vNOT_ALLOCATED;\r\n}\r\n\r\n\r\n}  // namespace Pcm\r\n\r\n#endif // __MUSIC_H__\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/bgm/bgm_com.c",
    "content": "// This code builds an IRX module that handles PCM streaming from\r\n// the CD to SPU2 Sound Data Input area...\r\n\r\n#include <kernel.h>\r\n#include <sys/types.h>\r\n#include <stdio.h>\r\n#include \"sif.h\"\r\n#include \"sifcmd.h\"\r\n#include \"sifrpc.h\"\r\n#include <libsd.h>\r\n#include \"bgm_i.h\"\r\n\r\nint gRpcArg[16];\t//--- Receiving channel for RPC arguments transferred from EE\r\n\r\n\r\nstatic void* bgmFunc(unsigned int fno, void *data, int size);\r\n\r\nextern int  BgmInit(int ch, int useCD);\r\nextern void BgmQuit(int channel, int status );\r\nextern int  BgmOpen( int ch, char* filename );\r\nextern void BgmClose(int ch, int status);\r\nextern void BgmCloseNoWait(int ch, int status);\r\nextern int  BgmPreLoad( int ch, int status );\r\nextern void BgmStart(int ch, int status);\r\nextern void BgmStop(int ch, int status);\r\nextern void BgmSeek( int ch, unsigned int vol );\r\nextern int BgmSetVolume( int ch, unsigned int vol );\r\nextern int BgmRaw2Spu( int ch, int which, int mode );\r\nextern int BgmSetVolumeDirect( int ch, unsigned int vol );\r\n// fuck this you big assbreath.\r\n//extern void BgmSetMasterVolume( int ch, unsigned int vol );\r\nextern unsigned int BgmGetMode( int ch, int status );\r\n//extern void BgmSetMode( int ch, u_int mode );\r\nextern void BgmSdInit(int ch, int status );\r\n\r\n\r\n/* ------------------------------------------------------------------------\r\n   Main thread for the ezbgm module.\r\n   After execution, initialize interrupt environment, register command, and\r\n   then wait until there is a request from the EE.\r\n   ------------------------------------------------------------------------ */\r\nint sce_bgm_loop()\r\n{\r\n\tsceSifQueueData qd;\r\n\tsceSifServeData sd;\r\n\r\n\t//-- Initialize interrupt environment in advance.\r\n\r\n\tCpuEnableIntr();\r\n\tEnableIntr( INUM_DMA_4 );\r\n\tEnableIntr( INUM_DMA_7 );\r\n\t\r\n\t//--- Register function that is called according to request\r\n\r\n\r\n\tsceSifInitRpc(0);\r\n\r\n\tsceSifSetRpcQueue( &qd, GetThreadId() );\r\n\tsceSifRegisterRpc( &sd, EZBGM_DEV, bgmFunc, (void*)gRpcArg, NULL, NULL, &qd );\r\n\tPRINTF((\"goto bgm cmd loop\\n\"));\r\n\r\n\t//--- Command-wait loop\r\n\r\n\tsceSifRpcLoop(&qd);\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n/* ------------------------------------------------------------------------\r\n   Function that is awakened by a request from the EE.\r\n   The argument is stored in *data.  The leading four bytes are reserved and are not used.\r\n   The return value of this function becomes the return value of the EE side's RPC.\r\n   When the argument is a structure, it is sent to gRpcData and used.\r\n   When a structure is returned to the EE, the value is sent to the address of the first argument (on the EE side).\r\n   ------------------------------------------------------------------------ */\r\nint ret = 0;\r\n\r\nstatic void* bgmFunc(unsigned int command, void *data, int size)\r\n{ \r\n\tint ch;\r\n\r\n//\tasm volatile( \"break 1\");\r\n\r\n//\tPRINTF(( \" bgmfunc %x, %x, %x, %x\\n\", *((int*)data + 0), \r\n//\t\t*((int*)data + 1), *((int*)data + 2),*((int*)data + 3) ));\r\n\r\n\tch = command&0x000F;\r\n\r\n\tswitch( command&0xFFF0 )\r\n\t{\r\n\tcase EzBGM_INIT:\r\n\t\tret = BgmInit( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_QUIT:\r\n\t\tBgmQuit ( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_OPEN:\r\n\t\tret = BgmOpen ( ch, (char*)((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_CLOSE:\r\n\t\tBgmClose( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_CLOSE_NO_WAIT:\r\n\t\tBgmCloseNoWait( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_PRELOAD:\r\n\t\tret = BgmPreLoad ( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_START:\r\n\t\tBgmStart( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_STOP:\r\n\t\tBgmStop( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_SEEK:\r\n\t\tBgmSeek( ch, (unsigned int)*((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_SETVOL:\r\n\t\tret = BgmSetVolume( ch, (unsigned int)*((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_SETVOLDIRECT:\r\n\t\tret = BgmSetVolumeDirect( ch, (unsigned int)*((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_GETMODE:\r\n\t\tret = BgmGetMode( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tcase EzBGM_SDINIT:\r\n\t\tBgmSdInit( ch, *((int*)data) );\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tERROR((\"EzBGM driver error: unknown command %d \\n\", *((int*)data) ));\r\n\t\tbreak;\r\n\t}\r\n//\tPRINTF(( \"return value = %x \\n\", ret )); \r\n\treturn (void*)(&ret);\r\n}\r\n\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n/* DON'T ADD STUFF AFTER THIS */\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/bgm/bgm_entr.c",
    "content": "#include <kernel.h>\r\n#include <sys/types.h>\r\n#include <stdio.h>\r\n#include <sif.h>\r\n#include <sifcmd.h>\r\n#include <sifrpc.h>\r\n#include \"bgm_i.h\"\r\n\r\nModuleInfo Module = {\"pcmaudio_driver\", 0x0102 };\r\n\r\nextern int sce_bgm_loop();\r\nextern volatile int gStThid;\r\n\r\nint create_th();\r\n\r\nint start ()\r\n{\r\n\tstruct ThreadParam param;\r\n\tint th;\r\n\r\n\tCpuEnableIntr();\r\n\r\n\tif( ! sceSifCheckInit() )\r\n\t\tsceSifInit();\r\n\tsceSifInitRpc(0);\r\n\r\n\tprintf(\"Entering PCM Audio Driver\\n\");\r\n\r\n\tparam.attr         = TH_C;\r\n\tparam.entry        = sce_bgm_loop;\r\n\tparam.initPriority = BASE_priority-2;\r\n\tparam.stackSize    = 0x800;\r\n\tparam.option       = 0;\r\n\tth = CreateThread(&param);\r\n\tif (th > 0) {\r\n\t\tStartThread(th,0);\r\n\t\tprintf(\"Exit PCM Audio Driver\\n\");\r\n\t\treturn 0;\r\n\t}else{\r\n\t\treturn 1;\r\n\t}\r\n}\r\n\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n/* DON'T ADD STUFF AFTER THIS */\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/bgm/bgm_i.h",
    "content": "//--- Highest bit indicates presence of return value\r\n#define EzBGM_INIT           0x8000\r\n#define EzBGM_QUIT           0x0010\r\n#define EzBGM_OPEN           0x8020\r\n#define EzBGM_CLOSE          0x0030\r\n#define EzBGM_PRELOAD        0x0040\r\n#define EzBGM_START          0x0050\r\n#define EzBGM_STOP           0x0060\r\n#define EzBGM_SEEK           0x0070\r\n#define EzBGM_SETVOL         0x8080\r\n#define EzBGM_SETVOLDIRECT   0x8090\r\n#define EzBGM_CLOSE_NO_WAIT  0x0100\r\n//#define EzBGM_SETMASTERVOL 0x00a0\r\n#define EzBGM_GETMODE        0x80b0\r\n#define EzBGM_SETMODE        0x80c0\r\n#define EzBGM_SDINIT         0x00d0\r\n\r\n\r\n//-- SET AVAILABLE\r\n#define BGM_MODE_REPEAT_OFF      0x0000\r\n#define BGM_MODE_REPEAT_DEFAULT  0x0001\r\n#define BGM_MODE_REPEAT_FORCED   0x0002\r\n\r\n#define BGM_MODE_STEREO          0x0000\r\n#define BGM_MODE_MONO            0x0010\r\n\r\n//-- GET ONLY\r\n#define BGM_MODE_IDLE            0x0000\r\n#define BGM_MODE_RUNNING         0x1000\r\n#define BGM_MODE_PAUSE           0x2000\r\n//#define BGM_MODE_KICKSTART       0x4000\r\n#define BGM_MODE_TERMINATE       0x8000\r\n\r\n\r\n#define BGM_MASK_STATUS          0x0FFF\r\n#define BGM_MASK_REPEAT          0xFFF0\r\n#define BGM_MASK_STEREO          0xFF0F\r\n\r\n#define WAV_STEREO_BIT           ( 1 << 1 )\r\n\r\n\r\n/* ----------------------------------------------\r\n   module ID number\r\n  ----------------------------------------------- */\r\n#define EZBGM_DEV   0x000666\r\n\r\n\r\n#define PRINTF(x) printf x\r\n//#define PRINTF(x) \r\n\r\n#define ERROR(x) printf x\r\n//#define ERROR(x) \r\n\r\n#define BASE_priority  42\r\n\r\n#define OLDLIB 0\r\n#define TRANS_CH  0\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/bgm/bgm_play.c",
    "content": "#include <stdio.h>\r\n#include <sys/file.h>\r\n#include <kernel.h>\r\n#include <string.h>\r\n#include <libsd.h>\r\n#include <libcdvd.h>\r\n#include \"bgm_i.h\"\r\n\r\n#define DEBUGGING_PLEASE 0\r\n#if DEBUGGING_PLEASE\r\n#define Dbg_Printf(A...)  printf(##A) \t\t\r\n#else\r\n#define Dbg_Printf(A...)\r\n#endif\r\n\r\n// wav format ------------------------\r\n#define RIFF_HEADER_SIZE 44\r\ntypedef struct {\r\n\tunsigned char     chunkID[4];\r\n\tunsigned int      chunkSize;\r\n\tunsigned short*   data;\r\n} DATAHeader;\r\n\r\ntypedef struct {\r\n\tunsigned char     chunkID[4];\r\n\tunsigned int      chunkSize;\r\n\tunsigned short    waveFmtType;\r\n\tunsigned short    channel;\r\n\tunsigned int      samplesPerSec;\r\n\tunsigned int      bytesPerSec;\r\n\tunsigned short    blockSize;\r\n\tunsigned short    bitsPerSample;\r\n} FMTHeader;\r\n\r\ntypedef struct {\r\n\tunsigned char     chunkID[4];\r\n\tunsigned int      chunkSize;\r\n\tunsigned char     formType[4];\r\n\tFMTHeader         fmtHdr;\r\n\tDATAHeader        dataHdr;\r\n} RIFFHeader;\r\n//------------------------------------\r\n\r\ntypedef struct {\r\n\tunsigned int     size;\r\n//\tunsigned int     offset;\r\n\tunsigned int     pos;\r\n} BGM_WAVE;\r\n\r\n\r\nBGM_WAVE gWave[2];\r\n\r\nint gMemInitializedForCD = 0;\r\nshort gBgmPause[2] = { 0, 0 };\r\nshort gBgmPreload[ 2 ] = { 0, 0 };\r\nchar gFileFromCD[ 2 ] = { 0, 0 };\r\nchar gBgmVolumeSet[2] = { 0, 0 };\r\nvolatile char gFileOpened[2] = { 0, 0 };\r\nvolatile char gBgmIntr[2] = { 0, 0 };\r\nint gThid = 0;\r\nint gSem = 0;\r\nint gFd[2];\r\nint gBuffRaw[2];\r\nint gBuffSpu[2] = {0, 0};\r\nint gRPacketSize[2];\r\nint gSPacketSize[2];\r\nint gAllockedSize[2];\r\nint gBgmVolume[2];\r\nint gBgmMode[2] = { BGM_MODE_REPEAT_OFF, BGM_MODE_REPEAT_OFF };\r\nint gBgmStereoMode[ 2 ] = { 0, 0 };\r\n\r\n#define MAX_FILENAME_LENGTH\t\t50\r\nchar gFilename[ 2 ][ MAX_FILENAME_LENGTH ];\r\n\r\n// Larger buffers will prevent skipping when loading in the background...\r\n// The more streams, the larger the buffers have to be.\r\n// Reading from the CDVD will be faster than debug stations from the host over the network,\r\n// so don't freak if you notice corruption on a dev system w/o CD.\r\n#define SECTOR_SIZE\t\t\t\t\t2048\r\n#define NUM_SECTORS_PER_READ\t\t2\r\n#define BUFFER_SIZE_FOR_HOST_FILE\t( 2048 * 132 ) // multiple of 6\r\n#define BUFFER_SIZE_FOR_CD_FILE\t\t( SECTOR_SIZE * NUM_SECTORS_PER_READ * 6 )\r\n\r\n#define RING_BUFFER_NUM_SECTORS\t\t48\r\n#define RING_BUFFER_ALLIGNMENT\t\t64\r\n#define RING_BUFFER_NUM_PARTITIONS\t3\r\nunsigned char gRingBuffer[ 2 ][ RING_BUFFER_NUM_SECTORS * 2048 ] __attribute__((aligned ( RING_BUFFER_ALLIGNMENT )));\r\nunsigned char gCDBuffSpu[ 2 ][ BUFFER_SIZE_FOR_CD_FILE ]__attribute__((aligned ( 64 )));\r\n\r\nint  _BgmPlay( int status );\r\nvoid _BgmRaw2Spu(u_long *src, u_long *dst,  u_long block_count );\r\nvoid _BgmRaw2SpuMono(u_long *src, u_long *dst,  u_long block_count );\r\nint\tBgmPreLoad( int ch, int status );\r\nvoid SetStereoOn( int ch, int stereo );\r\n\r\nstatic int IntFunc0( void* common )\r\n{\r\n\tgBgmIntr[0] = 1;\r\n\tiSignalSema( gSem );\r\n\treturn 1;  //-- Required for re-enabling interrupts\r\n}\r\n\r\nstatic int IntFunc1( void* common )\r\n{\r\n\tgBgmIntr[1] = 1;\r\n\tiSignalSema( gSem );\r\n\treturn 1;  //-- Required for re-enabling interrupts\r\n}\r\n\r\n\r\nstatic int makeMyThread( void )\r\n{\r\n    struct ThreadParam param;\r\n    int\tthid;\r\n\r\n    param.attr         = TH_C;\r\n    param.entry        = _BgmPlay;\r\n    param.initPriority = BASE_priority-3;\r\n    param.stackSize    = 0x800;\r\n    param.option = 0;\r\n\r\n    /* Create thread */\r\n\tthid = CreateThread(&param);\r\n\r\n\treturn thid;\r\n}\r\n\r\nstatic int makeMySem( void )\r\n{\r\n    struct SemaParam sem;\r\n\r\n    sem.initCount = 0;\r\n    sem.maxCount = 1;\r\n    sem.attr = AT_THFIFO;\r\n\r\n    /* Create semaphore.  */\r\n    return CreateSema(&sem);\r\n}\r\n\r\n\r\nint BgmRaw2Spu( int ch, int which )\r\n{\r\n    if ( gBgmStereoMode[ ch ] )\r\n\t{\r\n\t\t_BgmRaw2Spu( (u_long *)(gBuffRaw[ch]+ (gRPacketSize[ch])*which)\r\n\t\t\t, (u_long *)(gBuffSpu[ch] + (gSPacketSize[ch])*which)\r\n\t\t\t, gSPacketSize[ch]/1024 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t_BgmRaw2SpuMono ((u_long *)(gBuffRaw [ch] + (gRPacketSize [ch]) * which),\r\n\t\t\t\t (u_long *)(gBuffSpu [ch] + (gSPacketSize [ch]) * which),\r\n\t\t\t\t gSPacketSize [ch] / 1024);\r\n    }\r\n\treturn 0;\r\n}\r\n\r\n// returns zero if no longer playing...\r\nint BgmSetVolumeDirect( int ch, unsigned int vol )\r\n{\r\n\tsceSdSetParam( (ch)|SD_P_BVOLR, vol>>16 );\r\n\tsceSdSetParam( (ch)|SD_P_BVOLL, vol&0xFFFF);\r\n\treturn ( gBgmMode[ch] & ~BGM_MASK_STATUS );\r\n}\r\n\r\n\r\n\r\nvoid BgmSdInit(int ch, int status )\r\n{\r\n\t// This is already called from the soundFX module.\r\n\t//sceSdInit(0);\r\n\treturn;\r\n}\r\n\r\n\r\nint BgmInit( int ch, int useCD )\r\n{\r\n\r\n\tif( gSem == 0 ){\r\n\t\tgSem = makeMySem();\r\n\t}\r\n\tif( gThid == 0 ){\r\n\t\tgThid = makeMyThread();\r\n\t\tDbg_Printf(\"PCM Audio Streamer: create thread ID= %d, \", gThid );\r\n\t\t/* Activate thread  */\r\n\t\tStartThread( gThid, (u_long)NULL );\r\n\t}\r\n\r\n\tif ( !gBuffSpu[ ch ] )\r\n\t{\r\n\t\tgAllockedSize[ch] = useCD ? BUFFER_SIZE_FOR_CD_FILE : BUFFER_SIZE_FOR_HOST_FILE;\r\n\t\tif ( useCD )\r\n\t\t{\r\n\t\t\tgBuffSpu[ ch ] = ( int )gCDBuffSpu[ ch ]; //(int)AllocSysMemory( 0, gAllockedSize[ ch ], NULL );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tgBuffSpu[ ch ] = ( int )AllocSysMemory( 0, gAllockedSize[ ch ], NULL );\r\n\t\t}\r\n\t\tDbg_Printf(\" PCM spu buffer mem: 0x%x - 0x%x\\n\", gBuffSpu[ch], gBuffSpu[ch]+gAllockedSize[ ch ] );\r\n\t}\r\n\t// the memory should work for mono or stereo 44k files ( raw buffer always the same... )\r\n\tgRPacketSize[ ch ] = gAllockedSize[ ch ] / 6;\r\n\tgBuffRaw[ ch ] = ( int )( gBuffSpu[ ch ] + ( gRPacketSize[ ch ] * 4 ) );\r\n\tgMemInitializedForCD = useCD;\r\n\r\n\treturn  gThid;\r\n}\r\n\r\nvoid BgmQuit(int ch, int status )\r\n{\r\n\tif ( ( gBuffSpu[ ch ] ) && ( gBuffSpu[ ch ] != ( int ) gCDBuffSpu ) )\r\n\t\tFreeSysMemory( (void*)gBuffSpu[ch] );\r\n\tgBuffSpu[ch] = 0;\r\n\t//-- Frees resources unless another channel is used.\r\n\tif( gBuffSpu[1-ch] == 0 ){\r\n\t\tif (gThid != 0) TerminateThread( gThid );\r\n\t\tif (gSem != 0) DeleteSema( gSem );\r\n\t\tif (gThid != 0) DeleteThread( gThid );\r\n\t\tgThid = 0;\r\n\t\tgSem = 0;\r\n\t}\r\n\treturn;\r\n}\r\n\r\n/*\r\nvoid WaitForCDReady( char *description )\r\n{\r\n\tprintf( \"wait %s\", description );\r\n\twhile( SCECdComplete != sceCdDiskReady( 1 ) )\r\n\t{\r\n\t\tprintf( \".\" );\r\n\t}\r\n\tprintf( \"\\n\" );\r\n}*/\r\n\r\n#define NUM_BYTES_TO_CLEAR\t512 // must be divisible by 4!!!\r\n\r\nint BgmOpen( int data, char* filename )\r\n{\r\n//\tunsigned int channel;\r\n\tRIFFHeader wavHdr;\r\n\tint offset;\r\n\tint *addr;\r\n\tint i;\r\n\tint ch = data & 1;\r\n\tint stereo = data & WAV_STEREO_BIT;\r\n\t\r\n\tSetStereoOn( ch, stereo );\r\n\r\n\tfor ( i = 0; i < 2; i++ )\r\n\t{\r\n\t\tif ( gFileOpened[ i ] )\r\n\t\t{\r\n\t\t\tprintf( \"%s: Failed: Audio stream already running: %s\\n\", filename, gFilename[ i ] );\r\n//\t\t\tDbg_Printf( \"File already opened on that channel...\\n\" );\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t}\r\n\tprintf(\"pcm filename %s\\n\", filename );\r\n\t\r\n\tif ( !strncmp( filename, \"host\", 4 ) )\r\n\t{\r\n\t\tif ( gMemInitializedForCD )\r\n\t\t{\r\n\t\t\tprintf( \"Loading file from host when mem configured for CD... SOUND QUALITY WILL SUCK.\\n\" );\r\n\t\t\tprintf( \"If calling ezBGM_INIT with useCD (2nd param), send CDROM0 in filename...\\n\" );\r\n\t\t}\r\n\t\t\r\n\t\t// load the file from the dev system...\r\n\t\tif (( gFd[ch] = open ( filename, O_RDONLY)) < 0)\r\n\t\t{\r\n\t\t\tERROR((\"file open failed. %s \\n\", filename));\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t\t\r\n\t\tif ( read (gFd[ch], (unsigned char*)(&wavHdr)\r\n\t\t\t,RIFF_HEADER_SIZE ) != RIFF_HEADER_SIZE ) {\r\n\t\t\tERROR((\"file read failed. %s \\n\", filename));\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t\tif ( wavHdr.fmtHdr.channel == 2 )\r\n\t\t{\r\n\t\t\tif ( !stereo )\r\n\t\t\t\tprintf( \"WARNING: Playing stereo sound %s in mono mode.\\n\", filename );\r\n\t\t}\r\n\t\telse if ( stereo )\r\n\t\t{\r\n\t\t\tprintf( \"WARNING: Playing mono sound %s in stereo mode.\\n\", filename );\r\n\t\t}\r\n\t\t\r\n\t\tgWave[ch].size   = wavHdr.dataHdr.chunkSize;\r\n\t\tgWave[ch].pos    = 0;\r\n\t\r\n\t\t//--- Seek to start of data\r\n\t\toffset = (unsigned int)&(wavHdr.dataHdr.data) -(unsigned int)&wavHdr;\r\n\t\r\n\t\tlseek( gFd[ ch ], offset , SEEK_SET );\r\n\t\r\n\t\tgFileFromCD[ ch ] = 0;\r\n\t\tgFileOpened[ ch ] = 1;\r\n\t\tgBgmPreload[ ch ] = 3;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsceCdlFILE fp;\r\n\t\tsceCdRMode mode;\r\n\t\tint retVal;\r\n\t\tunsigned int stringLength;\r\n\t\tunsigned int lsn;\r\n\t\tint foundCDData = 0;\r\n\t\tint byteIndex;\r\n\t\t// open a stream and load from CD...\r\n\t\t// 1st arg: size in num sectors ( actual size / 2048 ).\r\n//\t\tWaitForCDReady( \"st init\" );\r\n//\t\tsceCdDiskReady( 0 );\r\n\t\tsceCdStInit( RING_BUFFER_NUM_SECTORS, RING_BUFFER_NUM_PARTITIONS, ( u_int )( gRingBuffer[ ch ] ) ); //+ ( RING_BUFFER_ALLIGNMENT - 1 ) )  );\r\n//\t\tprintf( \"wait for ready.\" );\r\n//\t\tsceCdDiskReady( 0 );\r\n//\t\tWaitForCDReady( \"init\" );\r\n//\t\tprintf( \"cdSearchFile\\n\" );\r\n\t\tstringLength = strlen( filename );\r\n\t\tif ( filename[ stringLength + 1 ] == '@' )\r\n\t\t{\r\n\t\t\tfoundCDData = 1;\r\n\t\t\tlsn = 0;\r\n\t\t\tfor ( byteIndex = 0; byteIndex < 4; byteIndex++ )\r\n\t\t\t{\r\n\t\t\t\tlsn |= ( ( ( unsigned int )( filename[ stringLength + 2 + byteIndex ] ) ) & 255 ) << ( 8 * byteIndex );\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( !foundCDData )\r\n\t\t{\r\n\t\t\tif ( !( retVal = sceCdSearchFile( &fp, filename ) ) )\r\n\t\t\t{\r\n\t\t\t\tERROR((\"cd filesearch failed %d. file %s \\n\", retVal, filename));\r\n\t\t\t\treturn -1;\r\n\t\t\t}\r\n\t\t\tlsn = fp.lsn;\r\n\t\t}\r\n\t\r\n//\t\tWaitForCDReady( \"find\" );\r\n//\t\tsceCdDiskReady( 0 );\r\n\t\tmode.trycount = 0;\r\n\t\tmode.spindlctrl = SCECdSpinNom;\r\n\t\tmode.datapattern = SCECdSecS2048;\r\n\t\tsceCdStStart( lsn, &mode );\r\n\t\tgFileFromCD[ ch ] = 1;\r\n\t\tgBgmPreload[ ch ] = 3;\r\n\t\tgFileOpened[ ch ] = 1;\r\n\t\tgWave[ ch ].pos = 0;\r\n\t\tgWave[ ch ].size = gRPacketSize[ ch ] * 4;\r\n\t}\r\n\t\r\n//\tprintf(\"wave size %d  offset %d\\n\", gWave[ch].size, gWave[ch].offset );\r\n\t\r\n\tBgmSetVolumeDirect( ch, 0 );\r\n\r\n\tstrncpy( gFilename[ ch ], filename, MAX_FILENAME_LENGTH  );\r\n\r\n\t// clear out the end of the second half of the last buffer...\r\n\taddr = ( int * )( gBuffRaw[ ch ] + ( gRPacketSize[ ch ] ) + ( gRPacketSize[ ch ] >> 1 ) );\r\n\tfor ( i = 0; i < ( ( gRPacketSize[ ch ] >> 1 ) >> 2 ); i++ )\r\n\t{\r\n\t\t*( addr++ ) = 0;\r\n\t}\r\n\t\r\n\tif( ch == 0 )\r\n\t{\r\n\t\tsceSdSetTransCallback( ch, IntFunc0 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsceSdSetTransCallback( ch, IntFunc1 );\r\n\t}\r\n\t\t\r\n\treturn ( gWave[ ch ].size );\r\n}\r\n\r\nvoid _BgmClose(int ch, int status)\r\n{\r\n\tif ( !gFileOpened[ ch ] )\r\n\t{\r\n\t\tPRINTF((\"Calling BgmClose when no file opened on that channel...\\n\"));\r\n\t\treturn;\r\n\t}\r\n\tDbg_Printf( \"_BgmClose\\n\" );\r\n\tif ( gFileFromCD[ ch ] )\r\n\t{\r\n\t\tsceCdStStop( );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tclose( gFd[ch] );\r\n\t\t//FreeSysMemory( ( void* )gBuffSpu[ ch ] );\r\n\t\t//gBuffSpu[ ch ] = 0;\r\n\t}\r\n\tgFileOpened[ ch ] = 0;\r\n\treturn;\r\n}\r\n\r\nvoid BgmStart(int ch, int status )\r\n{\r\n\tint retVal;\r\n\tif ( !gFileOpened[ ch ] )\r\n\t{\r\n\t\tprintf( \"trying to start track not loaded.\\n\" );\r\n\t\treturn;\r\n\t}\r\n\tDbg_Printf( \"starting block trans from bgm start/unpause\\n\" );\r\n\tif ( gBgmPause[ ch ] )\r\n\t{\r\n\t\tDbg_Printf( \"Starting music on channel where pause is requested...\\n\" );\r\n\t\tgBgmPause[ ch ] = 0;\r\n\t}\r\n\twhile( -1 == sceSdBlockTrans( ch, SD_TRANS_MODE_WRITE|SD_BLOCK_LOOP, (u_char*)gBuffSpu[ch], (gSPacketSize[ch]*2) ) )\r\n\t{\r\n\t\tfor ( retVal = 0; retVal < 10000; retVal++ )\r\n\t\t\t;\r\n\t\tDbg_Printf( \"failed to start loop.\\n\" );\r\n\t}\r\n\tif ( !( gBgmPreload[ ch ] ) )\r\n\t{\r\n\t\tBgmSetVolumeDirect(ch, gBgmVolume[ch]);\r\n\t}\r\n\tgBgmMode[ch] &= BGM_MASK_STATUS;\r\n\tgBgmMode[ch] |= BGM_MODE_RUNNING;\r\n\r\n\treturn;\r\n}\r\n\r\nvoid BgmCloseNoWait( int ch, int status )\r\n{\r\n\tif ( !gFileOpened[ ch ] )\r\n\t{\r\n\t\tPRINTF((\"Calling BgmClose when no file opened on that channel...\\n\"));\r\n\t\treturn;\r\n\t}\r\n\tif ( gBgmPause[ ch ] )\r\n\t{\r\n\t\tprintf( \"stopping music when pause is requested...\" );\r\n\t\treturn;\r\n\t}\r\n\t// if the pause has already stopped the callback, it's safe to unload now:\r\n\tif ( gBgmMode[ ch ] & BGM_MODE_PAUSE )\r\n\t{\r\n\t\t// callback isn't happening right now... can terminate with no worries here:\r\n\t\tDbg_Printf( \"unpausing from BgmClose\\n\" );\r\n\t\tgBgmMode[ch] &= BGM_MASK_STATUS; // Switch to IDLE mode\r\n\t\t_BgmClose( ch, status );\r\n\t\tDbg_Printf( \"calling _BgmClose from BgmClose\\n\" );\r\n\t\treturn;\r\n\t}\r\n\tgBgmMode[ch] &= BGM_MASK_STATUS;\r\n\tgBgmMode[ch] |= BGM_MODE_TERMINATE;\r\n}\r\n\r\nvoid BgmClose( int ch, int status )\r\n{\r\n\tint i;\r\n\tBgmCloseNoWait( ch, status );\r\n\tprintf( \"PCM close\" );\r\n\twhile ( ( gBgmMode[ ch ] & BGM_MODE_TERMINATE ) )\r\n\t{\r\n\t\tfor ( i = 0; i < 20000; i++ )\r\n\t\t\t;\r\n\t\tprintf( \".\" );\r\n\t}\r\n\tprintf( \"\\n\" );\r\n}\r\n\r\nint BgmPreLoad( int ch, int status )\r\n{\r\n\tif ( ( status == 666 ) || ( ( gWave[ ch ].size - gWave[ ch ].pos ) < gRPacketSize[ ch ] * 4 ) )\r\n\t{\r\n\t\tint i;\r\n\t\tint *addr;\r\n\t\tDbg_Printf( \"preloading at end of song. zero buffers.\\n\" );\r\n\t\t// we're at the end of the song... fill up read buffers with zero,\r\n\t\t// and convert...\r\n\t\taddr = ( int * )( gBuffRaw[ ch ] );\r\n\t\tfor ( i = 0; i < ( ( gRPacketSize[ ch ] * 2 ) >> 2 ); i++ )\r\n\t\t{\r\n\t\t\t*( addr++ ) = 0;\r\n\t\t}\r\n\t\t// fill up the spu with both buffers...\r\n\t\tBgmRaw2Spu( ch, 0 );\r\n\t\tBgmRaw2Spu( ch, 1 );\r\n\t\treturn ( 0 );\r\n\t}\r\n\t\r\n\t// it's still in preload mode... no need to preload ourselves...\r\n\tif ( gBgmPreload[ ch ] == 3 )\r\n\t\treturn ( 0 );\r\n\r\n\tif ( gFileFromCD[ ch ] )\r\n\t{\r\n\t\tunsigned int err;\r\n\t\tsceCdStRead( NUM_SECTORS_PER_READ * 2, ( u_int * )gBuffRaw[ ch ], STMBLK, &err );\r\n\t\tif ( err )\r\n\t\t{\r\n\t\t\tprintf( \"PCM A Disk error code 0x%08x\\n\", err );\r\n\t\t}\r\n\r\n\t\t// fill up the spu with both buffers...\r\n\t\tBgmRaw2Spu( ch, 0 );\r\n\t\tBgmRaw2Spu( ch, 1 );\r\n\t\t\r\n\t\t// fill up the buffers again...\r\n\t\tsceCdStRead( NUM_SECTORS_PER_READ * 2, ( u_int * )gBuffRaw[ ch ], STMBLK, &err );\r\n\t\tif ( err )\r\n\t\t{\r\n\t\t\tprintf( \"PCM B Disk error code 0x%08x\\n\", err );\r\n\t\t}\r\n\t\t\r\n\t\tgWave[ ch ].pos += gRPacketSize[ ch ] * 2;\r\n\t\treturn 0;\r\n\t}\r\n\t// reading from a file...\r\n\tif ( read (gFd[ch], (unsigned char*)(gBuffRaw[ch])\r\n\t, gRPacketSize[ch]*2 ) != gRPacketSize[ch]*2 ) {\r\n\t\tERROR ((\"BgmPreLoad: read failed \\n\")); return -1;\r\n\t}\r\n\r\n\tBgmRaw2Spu( ch, 0 );\r\n\tBgmRaw2Spu( ch, 1 );\r\n\r\n\tif ( read (gFd[ch], (unsigned char*)(gBuffRaw[ch])\r\n\t, (gRPacketSize[ch]*2) ) != gRPacketSize[ch]*2) {\r\n\t\tERROR ((\"BgmPreLoad: read failed \\n\")); return -1;\r\n\t}\r\n\r\n\tgWave[ch].pos += gRPacketSize[ch]*4;\r\n\r\n\treturn 0;\r\n}\r\n\r\nvoid _BgmPause(int ch, int status)\r\n{\r\n\tDbg_Printf( \"stopping spu block trans in _BgmPause\\n\" );\r\n\tsceSdBlockTrans( ch, SD_TRANS_MODE_STOP, NULL, 0 );\r\n\tgBgmMode[ch] &= BGM_MASK_STATUS; // Switch to PAUSE mode\r\n\tgBgmMode[ch] |= BGM_MODE_PAUSE;\r\n\treturn;\r\n}\r\n\r\nvoid _BgmStopAndUnload(int ch, int status)\r\n{\r\n\tDbg_Printf( \"stopping block trans from _BgmStopAndUnload\\n\" );\r\n\tsceSdBlockTrans( ch, SD_TRANS_MODE_STOP, NULL, 0 );\r\n\tgBgmMode[ch] &= BGM_MASK_STATUS; // Switch to IDLE mode\r\n\tDbg_Printf( \"bgm close from _BgmStopAndUnload\\n\" );\r\n\t_BgmClose( ch, status );\r\n\treturn;\r\n}\r\n\r\n// should be fucking called \"BgmPause\"\r\nvoid BgmStop( int ch, unsigned int vol )\r\n{\r\n\tint i;\r\n\r\n\tif ( gBgmMode[ ch ] & BGM_MODE_TERMINATE )\r\n\t{\r\n\t\tDbg_Printf( \"trying to pause PCM when stopped.\\n\" );\r\n\t\treturn;\r\n\t}\r\n\tif ( !gBgmMode[ ch ] & BGM_MODE_RUNNING )\r\n\t{\r\n\t\tDbg_Printf( \"trying to pause PCM when not running.\\n\" );\r\n\t\treturn;\r\n\t}\r\n\tgBgmPause[ch] = 1;\r\n\tprintf( \"waiting for pause\" );\r\n\twhile ( !( gBgmMode[ ch ] & BGM_MODE_PAUSE ) )\r\n\t{\r\n\t\tfor ( i = 0; i < 10000; i++ )\r\n\t\t\t;\r\n\t\tprintf( \".\" );\r\n\t}\r\n\tprintf( \"\\n\" );\r\n\t// don't set the flag until the callback has paused it:\r\n//\tgBgmMode[ch] &= BGM_MASK_STATUS;\r\n//\tgBgmMode[ch] |= BGM_MODE_PAUSE;\r\n\treturn;\r\n}\r\n\r\n\r\nint BgmSetVolume( int ch, unsigned int vol )\r\n{\r\n\tgBgmVolumeSet[ch] = 1;\r\n\tgBgmVolume[ch] = vol;\r\n\treturn ( gBgmMode[ch] & ~BGM_MASK_STATUS );\r\n}\r\n\r\n\r\nunsigned int BgmGetMode( int ch, int status )\r\n{\r\n\treturn gBgmMode[ch];\r\n}\r\n\r\nvoid BgmSeek( int ch, unsigned int value )\r\n{\r\n//\tlseek(gFd[ch], gWave[ch].offset+value, SEEK_SET );\r\n//\tgWave[ch].pos = value;\r\n\tprintf( \"seek not supported\\n\" );\r\n\treturn;\r\n}\r\n\r\nvoid SetStereoOn( int ch, int stereo )\r\n{\r\n    if ( stereo )\r\n\t{\r\n\t\tgSPacketSize[ ch ] = gAllockedSize[ ch ] / 6;\r\n\t\tgBgmStereoMode[ ch ] = 1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgSPacketSize[ ch ] = gAllockedSize [ ch ] / 3;\r\n\t\tgBgmStereoMode[ ch ] = 0;\r\n\t}\r\n}\r\n\r\nvoid PreloadFile( int which, int ch )\r\n{\r\n\tswitch ( gBgmPreload[ ch ] )\r\n\t{\r\n\t\tcase ( 3 ):\r\n\t\t\tif ( gFileFromCD[ ch ] )\r\n\t\t\t{\r\n\t\t\t\tRIFFHeader *pWavHdr;\r\n\t\t\t\tint i;\r\n\t\t\t\tint offset;\r\n\t\t\t\tunsigned char *pData;\r\n\t\t\t\tpWavHdr = ( RIFFHeader * )( gBuffRaw[ ch ]+gRPacketSize[ch]*which );\r\n\t\t\t\tif ( pWavHdr->dataHdr.chunkSize < gWave[ ch ].size )\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf( \"BIG WARNING:  Cd audio file currently playing is TOO SMALL!\\n\" );\r\n\t\t\t\t}\r\n\t\t\t\tif ( pWavHdr->fmtHdr.channel == 2 )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !gBgmStereoMode[ ch ] )\r\n\t\t\t\t\t\tprintf( \"WARNING: Playing stereo sound %s in mono mode.\\n\", gFilename[ ch ] );\r\n\t\t\t\t}\r\n\t\t\t\telse if ( gBgmStereoMode[ ch ] )\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf( \"WARNING: Playing mono sound %s in stereo mode.\\n\", gFilename[ ch ] );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tSetStereoOn( ch, pWavHdr->fmtHdr.channel == 2 );\r\n\t\t\t\tgWave[ch].size   = pWavHdr->dataHdr.chunkSize;\r\n\t\t\t\t//gWave[ch].offset = (unsigned int)&( pWavHdr->dataHdr.data ) - ( unsigned int )pWavHdr;\r\n\t\t\t\toffset = (unsigned int)&( pWavHdr->dataHdr.data ) - ( unsigned int )pWavHdr;\r\n\t\t\t\t// clear out the area where the header is... don't want some loud obnoxious sounds...\r\n\t\t\t\tpData = ( unsigned char * )( gBuffRaw[ ch ]+gRPacketSize[ch]*which );\r\n\t\t\t\tif ( offset > gRPacketSize[ ch ] )\r\n\t\t\t\t\toffset = gRPacketSize[ ch ]; // don't fuck up memory if some strange read happened...\r\n\t\t\t\tfor ( i = 0; i < offset; i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tpData[ i ] = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase ( 2 ):\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase ( 1 ):\r\n\t\t\t// turn the volume back up, the spooler is at the beginning of\r\n\t\t\t// the good SPU buffer...\r\n\t\t\tBgmSetVolume( ch, gBgmVolume[ch] );\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tprintf( \"unknown preload state... fire Matt.\\n\" );\r\n\t\t\tbreak;\r\n\t}\r\n\t--gBgmPreload[ ch ];\r\n}\r\n\r\nint _BgmPlay( int status )\r\n{\r\n\tint i, ch, read_size, which;\r\n\tint *addr, remain;\r\n\tDbg_Printf( \"entering _BgmPlay\\n\" );\r\n\twhile ( 1 )\r\n\t{\r\n\t\t//-- Wait for playing of buffer to finish\r\n\t\tWaitSema(gSem);\r\n\r\n\t\t//-- Which channel is the interrupt from?\r\n\t\tif( (gBgmIntr[0] == 1) && ( ch != 0 ) )  ch = 0;\r\n\t\telse if( (gBgmIntr[1] == 1) && ( ch != 1 ) )  ch = 1;\r\n\t\telse if( gBgmIntr[0] == 1 )  ch = 0;\r\n\t\telse if( gBgmIntr[1] == 1 )  ch = 1;\r\n\t\telse continue;\r\n\r\n\t\tgBgmIntr[ch] = 0;\r\n\r\n\t\twhich = 1 - (sceSdBlockTransStatus( ch, 0 )>>24);\r\n\r\n\t\t//--- Stopped due to end of data (no looping)\r\n\t\tif( ( gBgmMode[ ch ] & BGM_MODE_TERMINATE ) != 0 )\r\n\t\t{\r\n\t\t\tWaitSema( gSem ); // Wait until another interrupt is received\r\n\t\t\t_BgmStopAndUnload( ch, 0 );\r\n\t\t\tBgmSetVolumeDirect( ch, 0x0 );\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t//--- Volume change event\r\n\t\tif ( ( gBgmVolumeSet[ ch ] == 1 ) && ( !gBgmPreload[ ch ] ) )\r\n\t\t{\r\n\t\t\tBgmSetVolumeDirect( ch, gBgmVolume[ch] );\r\n\t\t\tgBgmVolumeSet[ch] = 0;\r\n\t\t}\r\n\r\n\t\t//--- Convert buffer\r\n\r\n\t\tBgmRaw2Spu( ch, which );\r\n\r\n\t\t//--- File READ for buffer\r\n\r\n\t\tremain = gWave[ ch ].size - gWave[ ch ].pos;\r\n\t\tif ( remain > gRPacketSize[ch] )\r\n\t\t{\r\n\t\t\tif ( gFileFromCD[ ch ] )\r\n\t\t\t{\r\n\t\t\t\t//--- Not end of data\r\n\t\t\t\tunsigned int err;\r\n\t\t\t\tsceCdStRead( NUM_SECTORS_PER_READ, ( u_int * )( gBuffRaw[ ch ]+gRPacketSize[ch]*which ), STMBLK, &err );\r\n\t\t\t\tif ( err )\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf( \"PCM C Disk error code 0x%08x\\n\", err );\r\n\t\t\t\t}\r\n\t\t\t\tread_size = gRPacketSize[ ch ];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tread_size = read (gFd[ch], (unsigned char*)(gBuffRaw[ch]+gRPacketSize[ch]*which), gRPacketSize[ch] );\r\n\t\t\t}\r\n\t\t\tif ( read_size < gRPacketSize[ch] )\r\n\t\t\t\tcontinue; //retry\r\n\t\t\tif ( gBgmPreload[ ch ] )\r\n\t\t\t{\r\n\t\t\t\tPreloadFile( which, ch );\r\n\t\t\t}\r\n\t\t\tgWave[ch].pos += read_size;\r\n\t\t}\r\n\t\telse  //--- End of data\r\n\t\t{\r\n\t\t\tif ( gFileFromCD[ ch ] )\r\n\t\t\t{\r\n\t\t\t\t//--- Not end of data\r\n\t\t\t\tunsigned int err;\r\n\t\t\t\tsceCdStRead( NUM_SECTORS_PER_READ, ( u_int * )( gBuffRaw[ ch ]+gRPacketSize[ch]*which ), STMBLK, &err );\r\n\t\t\t\tif ( err )\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf( \"PCM C Disk error code 0x%08x\\n\", err );\r\n\t\t\t\t}\r\n\t\t\t\tread_size = gRPacketSize[ ch ];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tread_size = read (gFd[ch], (unsigned char*)(gBuffRaw[ch]+gRPacketSize[ch]*which), remain );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif( read_size < remain ) continue; //retry\r\n\t    \t\r\n\t\t\tPRINTF((\"end of PCM track - ch %d\\n\", ch));\r\n\r\n\t\t\taddr = ( int * )( gBuffRaw[ ch ] + ( gRPacketSize[ ch ] * which ) + remain );\r\n\t\t\tfor( i = 0; i < ((gRPacketSize[ch]-remain)>>2); i++ )\r\n\t\t\t{\r\n\t\t\t\t*(addr++) = 0;\r\n\t\t\t}\r\n\t\t\tgBgmMode[ch] &= BGM_MASK_STATUS;\r\n\t\t\tgBgmMode[ch] |= BGM_MODE_TERMINATE;\r\n\t\t}\r\n\r\n\t\t//-- Stop event\r\n\t\tif( (gBgmPause[ch] == 1) )\r\n\t\t{\r\n\t\t\t//printf( \"_BgmPlay :: pause\\n\" );\r\n\t\t\t_BgmPause( ch, 0 );\r\n\t\t\tBgmSetVolumeDirect(ch, 0x0);\r\n\t\t\tgBgmPause[ch] = 0;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n/* This file ends here, DON'T ADD STUFF AFTER THIS */\r\n\r\n// Ha ha I added some stuff... FUCK YOU SONY!\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/bgm/bgm_r2s.s",
    "content": "/* SCEI CONFIDENTIAL\r\n \"PlayStation 2\" Programmer Tool Runtime Library  Release 2.0\r\n */\r\n/* \r\n *                  I/O Proseccor sample program\r\n *                          Version 1.20\r\n *                           Shift-JIS\r\n *\r\n *      Copyright (C) 1998-1999 Sony Computer Entertainment Inc.\r\n *                        All Rights Reserved.\r\n *\r\n *                       ezbgm.irx - bgm_r2s.c\r\n *                          raw to spu pcm\r\n *\r\n *   Version   Date            Design    Log\r\n *  --------------------------------------------------------------------\r\n *   1.20      Nov.23.1999     morita    modify for EzBGM\r\n *   0.01      Nov.18.1999     ishii     optimize for IOP\r\n */\r\n\r\n#include <cpureg.h>\r\n\r\n#define src  a0\r\n#define dst  a1\r\n#define blk  a2\r\n#define cnt  a3\r\n\r\n\t.globl\t_BgmRaw2Spu\r\n\t.ent\t_BgmRaw2Spu\r\n_BgmRaw2Spu:\r\n\tsubu\tsp, (8*4)\r\n\tsw\ts0, 0*4(sp)\t; \tsw\ts1, 1*4(sp)\r\n\tsw\ts2, 2*4(sp)\t; \tsw\ts3, 3*4(sp)\r\n\tsw\ts4, 4*4(sp)\t; \tsw\ts5, 5*4(sp)\r\n\tsw\ts6, 6*4(sp)\t; \tsw\ts7, 7*4(sp)\r\n\tmove\tv0, zero\r\n\tmove\tv1, zero\r\n\taddi\tcnt,zero, 256\r\n\r\n\t\t\t\t\t.set noreorder\r\n\t/* AŖ߂̂Ȃт𐧌B */\r\npcm_separate_loop:\r\n\tlw\tt0, 0*4(src)\t/* 1 + 4 clock */\r\n\tlw\tt1, 1*4(src)\t/* 1 + 2 clock */\r\n\r\n\t/* 7 clock */\r\n\tand\ts0, t0, 0xffff\t\t/* t0 ̉ʂ s0  */\r\n\tsrl\ts1, t0, 16\t\t/* t0 ̏ʂ s1  */\r\n\tsll\tt0, t1, 16\t\t/* t1 ̉ʂɃVtg s0  */\r\n\tor\ts0, t0\r\n\tsrl\tt1, t1, 16\t\t/* t1 ̏ʂ}XN s1  */\r\n\tsll\tt1, t1, 16\r\n\tor\ts1, t1\r\n\r\n\t/* ɃLbVɓǂݍ܂Ă͂ */\r\n\tlw\tt2, 2*4(src)\t/* 1 clock */\r\n\tlw\tt3, 3*4(src)\t/* 1 clock */\r\n\t/* ̃LbVCǂݍނ */\r\n\tlw\tt4, 4*4(src)\t/* 1 + 4 clock */\r\n\r\n\t/* 7 clock */\r\n\tand\ts2, t2, 0xffff\t\t/* t2 ̉ʂ s2  */\r\n\tsrl\ts3, t2, 16\t\t/* t2 ̏ʂ s3  */\r\n\tsll\tt2, t3, 16\t\t/* t3 ̉ʂɃVtg s2  */\r\n\tor\ts2, t2\r\n\tsrl\tt3, t3, 16\t\t/* t3 ̏ʂ}XN s3  */\r\n\tsll\tt3, t3, 16\r\n\tor\ts3, t3\r\n\r\n\t/* ɃLbVɓǂݍ܂Ă͂ */\r\n\tlw\tt5, 5*4(src)\t/* 1 clock */\r\n\tlw\tt6, 6*4(src)\t/* 1 clock */\r\n\tlw\tt7, 7*4(src)\t/* 1 clock */\r\n\tadd\tsrc, 8*4\t/* 1 clock */\r\n\r\n\t/* 7 clock */\r\n\tand\ts4, t4, 0xffff\t\t/* t4 ̉ʂ s4  */\r\n\tsrl\ts5, t4, 16\t\t/* t4 ̏ʂ s5  */\r\n\tsll\tt4, t5, 16\t\t/* t5 ̉ʂɃVtg s4  */\r\n\tor\ts4, t4\r\n\tsrl\tt5, t5, 16\t\t/* t5 ̏ʂ}XN s5  */\r\n\tsll\tt5, t5, 16\r\n\tor\ts5, t5\r\n\r\n\t/* store  dst1(s0, s2),  dst2(s1, s3) */\r\n\t/* 4 clock */\r\n\r\n\tsw\ts0, 0*4(dst)\t;\tsw\ts2, 1*4(dst)\r\n\tsw\ts1, (0*4+512)(dst); \tsw\ts3, (1*4+512)(dst)\r\n\t/* ȉƕs +2, 4+2 clock ŏ܂͂ */\r\n\r\n\t/* 7 clock */\r\n\tand\ts6, t6, 0xffff\t\t/* t6 ̉ʂ s6  */\r\n\tsrl\ts7, t6, 16\t\t/* t6 ̏ʂ s7  */\r\n\tsll\tt6, t7, 16\t\t/* t7 ̉ʂɃVtg s6  */\r\n\tor\ts6, t6\r\n\tsrl\tt7, t7, 16\t\t/* t7 ̏ʂ}XN s7  */\r\n\tsll\tt7, t7, 16\r\n\tor\ts7, t7\r\n\r\n\t/* store  dst1(s4, s6),  dst2(s5, s7) */\r\n\t/* 4 clock */\r\n\tsw\ts4, 2*4(dst)\t; \tsw\ts6, 3*4(dst)\r\n\tsw\ts5, (2*4+512)(dst)\t; \tsw\ts7, (3*4+512)(dst)\r\n\t/* ȉƕs +2, 4+2 clock ŏ܂͂ */\r\n\r\n\tadd\tdst, 4*4\t\t/* 1 clock */\r\n\r\n\r\n\t/* ܂ŁAŖ߂̂Ȃт𐧌B */\r\n\t\t\t\t\t.set reorder\r\n\r\n\tadd\tv0, 8\t\t\t/* 1 clock */\r\n\tblt\tv0, cnt, pcm_separate_loop\t/* 1 clock */\r\n\r\n\tadd\tdst, 512\r\n\tmove\tv0, zero\r\n\r\n\tadd\tv1, 1\r\n\tblt\tv1, blk, pcm_separate_loop\r\n\r\n\tlw\ts0, 0*4(sp)\t; \tlw\ts1, 1*4(sp)\r\n\tlw\ts2, 2*4(sp)\t; \tlw\ts3, 3*4(sp)\r\n\tlw\ts4, 4*4(sp)\t; \tlw\ts5, 5*4(sp)\r\n\tlw\ts6, 6*4(sp)\t; \tlw\ts7, 7*4(sp)\r\n\taddu\tsp, (8*4)\r\n\tj\tra\r\n\t.end\t_BgmRaw2Spu\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/bgm/bgm_r2sm.c",
    "content": "#include <kernel.h>\r\n\r\n#define SPU_BLOCK 512\r\n\r\n// Using SP will speed things up, but ...\r\n\r\nvoid _BgmRaw2SpuMono( unsigned int *src, unsigned int *dst, unsigned int block )\r\n{\r\n\tint i;\r\n\r\n\tfor ( i = 0; i < block; i++ )\r\n\t{\r\n\t\tmemcpy( (void*)((int)dst+i*SPU_BLOCK*2), (void*)((int)src+i*SPU_BLOCK), SPU_BLOCK );\r\n\t\tmemcpy( (void*)((int)dst+i*SPU_BLOCK*2+SPU_BLOCK), (void*)((int)src+i*SPU_BLOCK) , SPU_BLOCK );\r\n\t}\r\n\r\n\treturn;\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/divx/AUDSimpleAudio.cpp",
    "content": "#ifndef DVDETH\r\n/*!\r\n ******************************************************************************\r\n * \\file AUDSimpleAudio.cpp\r\n *\r\n * \\brief\r\n *\t\tThis file provides the required player audio functions.\r\n *\r\n * \\note\r\n *      This is a demonstration source only!\r\n *\r\n * \\date\r\n *\t\t08/19/02\r\n *\t\t04/28/03 - updated to AX audio playback\r\n *\r\n * \\version\r\n *\t\t1.0\r\n *\r\n * \\author\r\n *\t\tThomas Engel\r\n *\r\n ******************************************************************************\r\n */\r\n\r\n//\r\n// Note about sample frequencies on Nintendo GameCube:\r\n//\r\n// GameCube's AI knows two native sample frequencies. Generally these are\r\n// referenced as 48KHz and 32KHz. The DSP (no matter if driven by MusyX or AX)\r\n// is using 32KHz.\r\n//\r\n// The frequencies that are in fact used are not exactly these frequencies, though!\r\n//\r\n// While this is not important when handling sound effects or even streamed audio,\r\n// it is very important when interlaeving audio and video data since buffer under-runs\r\n// might be triggered if no care is taken.\r\n//\r\n// The actual AI output frequencies are 48043Hz and 32028.66Hz.\r\n//\r\n// Streamed audio data interleaved with video should match these frequencies as\r\n// closely as possible.\r\n//\r\n\r\n/******************************************************************************\r\n *  INCLUDES\r\n ******************************************************************************/\r\n#include <dolphin.h>\r\n#include <string.h>\r\n\r\n#include \"AUDSimplePlayer.h\"\r\n#include \"AUDSimpleAudio.h\"\r\n#include \"gel/soundfx/ngc/p_sfx.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n\r\n/******************************************************************************\r\n *  DEFINES\r\n ******************************************************************************/\r\n\r\n// Number of audio frames that should be able to be stored prio to being routed into the AX buffer\r\n#define\tAUD_AUDIO_READAHEADFRAMES\t0.5f\r\n\r\n#define\tAUD_AUDIO_AIBUFFERSAMPLES\t(2*256)\t\t// 10.6ms of 48KHz data per AI buffer (32 byte multiple), that'll be about 15.9ms at 32Khz\r\n#define\tAUD_AUDIO_NUMAIBUFFERS\t\t2\t\t\t// Number of AI playback buffers (this has an impact on audio latency. 2 is the minimum needed)\r\n\r\n#define\tAX_ARAM_BUFFER_SIZE\t\t\t(AUD_AUDIO_AIBUFFERSAMPLES * AUD_AUDIO_NUMAIBUFFERS)\r\n//#define\tAX_ARAM_LEFT_CHANNEL\t\t0x200000\t// @ 4MB (16-Bit addressing for DSP!)\r\n//#define\tAX_ARAM_RIGHT_CHANNEL\t\t(AX_ARAM_LEFT_CHANNEL + AX_ARAM_BUFFER_SIZE)\r\n#define\tAX_ARAM_LEFT_CHANNEL\t\t( NxNgc::EngineGlobals.aram_music >> 1 )\r\n#define\tAX_ARAM_RIGHT_CHANNEL\t\t(AX_ARAM_LEFT_CHANNEL + AX_ARAM_BUFFER_SIZE)\r\n\r\n#define\tAUD_NUM_ARQ_REQUESTS\t\t16\r\n\r\n/******************************************************************************\r\n *  LOCAL VARIABLES & LOCAL EXTERNAL REFERENCES\r\n ******************************************************************************/\r\n\r\nextern AudSimplePlayer\taudio_player;\t\t\t\t\t\t\t\t// Player instance\r\n\r\nstatic void\t\t\t\t*audioReadBuffer;\t\t\t\t\t\t\t// Buffer to store audio data received from the data stream\r\nstatic u32\t\t\t\taudioReadBufferNumSamples;\t\t\t\t\t// Size of the above buffer in samples\r\nstatic u32\t\t\t\taudioReadBufferWritePos;\t\t\t\t\t// Write position in the above buffer in samples\r\nstatic u32\t\t\t\taudioReadBufferReadPos;\t\t\t\t\t\t// Read position in the above buffer in samples\r\nstatic u8\t\t\t\taudioReadBufferNumChannels;\t\t\t\t\t// Number of channels stored in the read buffer\r\n\r\nstatic void\t\t\t\t*audioPlayBuffer[AUD_AUDIO_NUMAIBUFFERS];\t// AI playback buffers\r\nstatic u8\t\t\t\taudioPlayBufferWriteIndex;\t\t\t\t\t// Index to next AI buffer to be written to from the read buffer\r\nstatic u32\t\t\t\taudioPlayBufferFrq;\t\t\t\t\t\t\t// Playback frequency of AI in Hz\r\nstatic volatile BOOL\taudioPlayBufferEnabled;\t\t\t\t\t\t// TRUE if playback is enabled. AI will operate at all times, but zeros will be filled in instead of real data if this is FALSE.\r\n\r\nstatic const u32\t\t*audioPlayMaskArray;\t\t\t\t\t\t// Pointer to an array of channel play masks (each set bit signals an active channel)\r\nstatic u32\t\t\t\taudioNumPlayMasks;\t\t\t\t\t\t\t// Number of play masks specified (0 indicates all channels should be active)\r\nstatic u32\t\t\t\taudioNumActiveVoices;\t\t\t\t\t\t// Number of active voices\r\n\r\nstatic AXVPB\t\t\t*axVoice[2];\t\t\t\t\t\t\t\t// AX voice structures\r\nstatic ARQRequest\t\tarqRequest[2][AUD_NUM_ARQ_REQUESTS];\t\t// Enough ARQ request structures for worst case scenario\r\nstatic u32\t\t\t\taxLastAddr;\t\t\t\t\t\t\t\t\t// Last known address DSP read from for 1st voice\r\nstatic u32\t\t\t\taxPlayedSamples;\t\t\t\t\t\t\t// Number of samples played on first voice since last update\r\nstatic u32\t\t\t\taxPlayedSamplesTotal;\t\t\t\t\t\t// Number of samples played on first voice since playback began\r\n\r\ntypedef enum VID_AXPHASE {\r\n\t\tAX_PHASE_STARTUP = 0,\r\n\t\tAX_PHASE_START,\r\n\t\tAX_PHASE_PLAY\r\n\t\t} VID_AXPHASE;\r\n\r\nstatic VID_AXPHASE\t\taxPhase;\r\n\r\n\r\n/******************************************************************************\r\n *  LOCAL PROTOTYPES\r\n ******************************************************************************/\r\n\r\nstatic void AXCallback(void);\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tInitialize audio decoder\r\n *\r\n *\t\tThis function allocates all neccessary memory for the audio processing\r\n *\t\tand sets the audio decoder into an idle state, waiting for first data.\r\n *\t\tA file must be opened with the VIDSimplePlayer before calling this\r\n *\t\tfunction.\r\n *\r\n * \\return\r\n *\t\tFALSE if any problem was detected\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL AUDSimpleInitAudioDecoder(void)\r\n\t{\r\n\tu32\t \t\ti, ratio;\r\n\tBOOL \t\told;\r\n\tAXPBMIX\t\taxMix[2];\r\n\tAXPBVE \t\taxVE;\r\n\tAXPBSRC\t\taxSRC;\r\n\tAXPBADDR \taxAddr;\r\n\tAXPBADPCM \taxADPCM;\r\n\r\n\t// Calculate buffer size to allocate proper memry to keep a bit of \"extra\" audio data around...\r\n\taudioReadBufferNumSamples = (u32)((f32)AUD_AUDIO_READAHEADFRAMES * audio_player.audioInfo.vaud.frq);\r\n\taudioReadBufferNumChannels = audio_player.audioInfo.vaud.numChannels <= 2 ? audio_player.audioInfo.vaud.numChannels : 2;\r\n\r\n\t// Allocate read buffer\r\n\taudioReadBuffer = audio_player.cbAlloc(audioReadBufferNumSamples * sizeof(s16) * audio_player.audioInfo.vaud.numChannels);\r\n\tif (audioReadBuffer == NULL)\r\n\t\treturn FALSE;\t\t\t\t\t// error\r\n\t\r\n\t// Reset ring buffer\r\n\taudioReadBufferReadPos = audioReadBufferWritePos = 0;\r\n\r\n\t// What frquency is best?\r\n\taudioPlayBufferFrq = audio_player.audioInfo.vaud.frq;\r\n\t\r\n\t// Allocate AI playback buffer\r\n\taudioPlayBuffer[0] = audio_player.cbAlloc(2 * sizeof(s16) * AUD_AUDIO_AIBUFFERSAMPLES * AUD_AUDIO_NUMAIBUFFERS);\r\n\tif (audioPlayBuffer[0] == NULL)\r\n\t\treturn FALSE;\t\t\t\t\t// error\r\n\t\r\n\tfor(i=1; i<AUD_AUDIO_NUMAIBUFFERS; i++)\r\n\t\taudioPlayBuffer[i] = (void *)((u32)audioPlayBuffer[i - 1] + (2 * sizeof(s16) * AUD_AUDIO_AIBUFFERSAMPLES));\r\n\t\r\n\t// Reset buffer index\r\n\taudioPlayBufferWriteIndex = 0;\r\n\t\r\n\t// We disable AI output for now (logically)\r\n\taudioPlayBufferEnabled = FALSE;\r\n\t\r\n\t// We assume to playback all we get by default\r\n\taudioPlayMaskArray = NULL;\r\n\taudioNumPlayMasks = 0;\r\n\taudioNumActiveVoices = 2;\r\n\t\r\n\t// Clear out AI buffers to avoid any noise what so ever\r\n\tmemset(audioPlayBuffer[0],0,2 * sizeof(s16) * AUD_AUDIO_AIBUFFERSAMPLES * AUD_AUDIO_NUMAIBUFFERS);\r\n\tDCFlushRange(audioPlayBuffer[0],2 * sizeof(s16) * AUD_AUDIO_AIBUFFERSAMPLES * AUD_AUDIO_NUMAIBUFFERS);\r\n\t\r\n\t// Init GCN audio system\r\n\told = OSDisableInterrupts();\r\n\r\n\taxVoice[0] = AXAcquireVoice(AX_PRIORITY_NODROP,NULL,0);\r\n\tASSERT(axVoice[0] != NULL);\r\n\taxVoice[1] = AXAcquireVoice(AX_PRIORITY_NODROP,NULL,0);\r\n\tASSERT(axVoice[1] != NULL);\r\n\r\n\tmemset(&axMix[0],0,sizeof(axMix[0]));\r\n\taxMix[0].vL = 0x7FFF;\r\n\tmemset(&axMix[1],0,sizeof(axMix[1]));\r\n\taxMix[1].vR = 0x7FFF;\r\n\t\r\n\tAXSetVoiceMix(axVoice[0],&axMix[0]);\r\n\tAXSetVoiceMix(axVoice[1],&axMix[1]);\r\n\t\r\n\taxVE.currentDelta = 0;\r\n\taxVE.currentVolume = 0x7FFF;\r\n\tAXSetVoiceVe(axVoice[0],&axVE);\r\n\tAXSetVoiceVe(axVoice[1],&axVE);\r\n\t\r\n\tmemset(&axSRC,0,sizeof(AXPBSRC));\r\n\t\r\n\tratio = (u32)(65536.0f * (f32)audioPlayBufferFrq / (f32)AX_IN_SAMPLES_PER_SEC);\r\n\taxSRC.ratioHi = (u16)(ratio >> 16);\r\n\taxSRC.ratioLo = (u16)ratio;\r\n\t\r\n\tAXSetVoiceSrcType(axVoice[0],AX_SRC_TYPE_4TAP_16K);\r\n\tAXSetVoiceSrc(axVoice[0],&axSRC);\r\n\tAXSetVoiceSrcType(axVoice[1],AX_SRC_TYPE_4TAP_16K);\r\n\tAXSetVoiceSrc(axVoice[1],&axSRC);\r\n\t\r\n\t*(u32 *)&axAddr.currentAddressHi = AX_ARAM_LEFT_CHANNEL;\r\n\t*(u32 *)&axAddr.loopAddressHi = AX_ARAM_LEFT_CHANNEL;\r\n\t*(u32 *)&axAddr.endAddressHi = AX_ARAM_LEFT_CHANNEL + AX_ARAM_BUFFER_SIZE - 1;\r\n\taxAddr.format = AX_PB_FORMAT_PCM16;\r\n\taxAddr.loopFlag = AXPBADDR_LOOP_ON;\r\n\tAXSetVoiceAddr(axVoice[0],&axAddr);\r\n\t\r\n\t*(u32 *)&axAddr.currentAddressHi = AX_ARAM_RIGHT_CHANNEL;\r\n\t*(u32 *)&axAddr.loopAddressHi = AX_ARAM_RIGHT_CHANNEL;\r\n\t*(u32 *)&axAddr.endAddressHi = AX_ARAM_RIGHT_CHANNEL + AX_ARAM_BUFFER_SIZE - 1;\r\n\tAXSetVoiceAddr(axVoice[1],&axAddr);\r\n\r\n\tmemset(&axADPCM,0,sizeof(axADPCM));\r\n\taxADPCM.gain = 0x0800;\r\n\t\r\n\tAXSetVoiceAdpcm(axVoice[0],&axADPCM);\r\n\tAXSetVoiceAdpcm(axVoice[1],&axADPCM);\r\n\t\r\n\tAXSetVoiceType(axVoice[0],AX_PB_TYPE_STREAM);\r\n\tAXSetVoiceType(axVoice[1],AX_PB_TYPE_STREAM);\r\n\t\r\n\tAXRegisterCallback( AXCallback );\r\n\t\r\n\taxLastAddr\t\t\t\t= AX_ARAM_LEFT_CHANNEL;\r\n\taxPlayedSamples\t\t\t= AUD_AUDIO_AIBUFFERSAMPLES * AUD_AUDIO_NUMAIBUFFERS;\r\n\taxPlayedSamplesTotal\t= 0;\r\n\taxPhase\t\t\t\t\t= AX_PHASE_STARTUP;\r\n\t\r\n\t// All is setup for the voices. We'll start them inside the AX callback as soon as we got data in the ARAM buffers\r\n\tOSRestoreInterrupts(old);\r\n\r\n\treturn TRUE;\r\n    }\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tShutdown audio decoder and free resources\r\n *\r\n ******************************************************************************\r\n */\r\nvoid AUDSimpleExitAudioDecoder(void)\r\n\t{\r\n\t// Yes. Unregister callback & stop AI DMA\r\n\tBOOL old = OSDisableInterrupts();\r\n\t\r\n\t// Register our default AX callback.\r\n\tAXRegisterCallback( Sfx::AXUserCBack );\r\n\t\r\n\tAXSetVoiceState(axVoice[0],AX_PB_STATE_STOP);\r\n\tAXSetVoiceState(axVoice[1],AX_PB_STATE_STOP);\r\n\tAXFreeVoice(axVoice[0]);\r\n\tAXFreeVoice(axVoice[1]);\r\n\t\r\n\taxVoice[0] = axVoice[1] = NULL;\r\n\t\r\n\tOSRestoreInterrupts(old);\r\n\r\n\t// Free allocated resources...\r\n\taudio_player.cbFree(audioPlayBuffer[0]);\r\n\taudio_player.cbFree(audioReadBuffer);\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tStop audio playback without shutting down AI etc.\r\n *\r\n ******************************************************************************\r\n */\r\nvoid AUDSimpleAudioReset(void)\r\n\t{\r\n\tBOOL\told;\r\n\r\n\told = OSDisableInterrupts();\r\n\t\r\n\taudioReadBufferWritePos = 0;\r\n\taudioReadBufferReadPos = 0;\r\n\t\r\n\taudioPlayBufferEnabled = FALSE;\r\n\t\t\r\n\tOSRestoreInterrupts(old);\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tReturn some information about current audio stream.\r\n *\r\n ******************************************************************************\r\n */\r\nvoid AUDSimpleAudioGetInfo(VidAUDH* audioHeader)\r\n{\r\n\tASSERT(audioHeader);\r\n\tmemcpy(audioHeader, &audio_player.audioInfo, sizeof(*audioHeader));\r\n}\r\n\r\n\r\n\r\nvoid AUDSimpleAudioSetVolume( u16 vl, u16 vr )\r\n{\r\n\tAXPBVE axVE;\r\n\t\r\n\taxVE.currentDelta\t= 0;\r\n\taxVE.currentVolume\t= vl;\r\n\tAXSetVoiceVe( axVoice[0], &axVE );\r\n\t\r\n\taxVE.currentVolume\t= vr;\r\n\tAXSetVoiceVe( axVoice[1], &axVE );\r\n}\r\n\r\n\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\r\n ******************************************************************************\r\n */\r\nstatic void writeChannelData(s16* dest, u32 channels, const s16** samples, u32 sampleOffset, u32 sampleNum)\r\n\t{\r\n    u32 j;\r\n\tif(channels == 1)\r\n\t\t{\r\n\t\tconst s16* in = samples[0] + sampleOffset;\r\n\t\tfor(j = 0; j < sampleNum; j++)\r\n\t\t\t*dest++ = in[j];\r\n\t\t}\r\n\telse\r\n\t\t{\r\n\t\tconst s16* inL;\r\n\t\tconst s16* inR;\r\n\r\n\t\tASSERT(channels == 2);\r\n        inL = samples[0] + sampleOffset;\r\n\t\tinR = samples[1] + sampleOffset;\r\n        for(j = 0; j < sampleNum; j++)\r\n\t\t\t{\r\n\t\t\t*dest++ = *inL++;\r\n\t\t\t*dest++ = *inR++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\r\nu32 AUDSimpleAudioGetFreeReadBufferSamples( void )\r\n{\r\n\tu32 freeSamples;\r\n\t\r\n\tif( audioReadBufferWritePos >= audioReadBufferReadPos )\r\n\t{\r\n\t\tfreeSamples = audioReadBufferNumSamples - (audioReadBufferWritePos - audioReadBufferReadPos);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfreeSamples = audioReadBufferReadPos - audioReadBufferWritePos;\r\n\t}\r\n\treturn freeSamples;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tMain audio data decode function.\r\n *\r\n *\t\tThis function will be used as a callback from the VIDAudioDecode\r\n *\t\tfunction or is called directely in case of PCM or ADPCM.\r\n *\r\n * \\param numChannels\r\n *\t\tNumber of channels present in the sample array\r\n *\r\n * \\param samples\r\n *\t\tArray of s16 pointers to the sample data\r\n *\r\n * \\param sampleNum\r\n *\t\tNumber of samples in the array. All arrays have the same amount\r\n *\t\tof sample data\r\n *\r\n * \\param userData\r\n *\t\tSome user data\r\n *\r\n * \\return\r\n *\t\tFALSE if data could not be interpreted properly\r\n *\r\n ******************************************************************************\r\n */\r\nstatic BOOL audioDecode(u32 numChannels, const s16 **samples, u32 sampleNum, void* _UNUSED(userData))\r\n\t{\r\n\tu32\t freeSamples;\r\n\tu32\t sampleSize;\r\n\tu32\t len1;\r\n\tBOOL old;\r\n\t\r\n\t// we can only play mono or stereo!\r\n\tASSERT(numChannels <= 2);\r\n\r\n\t// Disable IRQs. We must make sure we don't get interrupted by the AI callback.\r\n\told = OSDisableInterrupts();\r\n\r\n\t// Did the video decoder just jump back to the beginning of the stream?\r\n\tif (audio_player.readBuffer[audio_player.decodeIndex].frameNumber < audio_player.lastDecodedFrame)\r\n\t\t{\r\n\t\t// Yes! We have to reset the internal read buffer and disable any audio output\r\n\t\t// until we got new video data to display...\r\n\t\t//\r\n\t\t// Note: we have to reset our buffers because the stream contains more audio data than\r\n\t\t// neccessary to cover a single video frame within the first few frames to accumulate\r\n\t\t// some safety buffer. If the stream would just be allowed to loop we would get an\r\n\t\t// overflow (unless we used up the extra buffer due to read / decode delays) after a few\r\n\t\t// loops...\r\n\t\t//\r\n\t\tAUDSimpleAudioReset();\r\n\t\t}\r\n\r\n\t// Calculate the read buffer's sample size\r\n\tsampleSize = sizeof(s16) * audioReadBufferNumChannels;\r\n\r\n\t// How many samples could we put into the buffer?\r\n\tif (audioReadBufferWritePos >= audioReadBufferReadPos)\r\n\t{\r\n\t\tfreeSamples = audioReadBufferNumSamples - (audioReadBufferWritePos - audioReadBufferReadPos);\r\n\r\n\t\tif( freeSamples < sampleNum )\r\n\t\t{\r\n\t\t\tOSRestoreInterrupts(old);\r\n\t\t\t#ifndef FINAL\r\n\t\t\tOSReport(\"*** audioDecode: overflow case 1\\n\");\r\n\t\t\t#endif\r\n\t\t\treturn FALSE;\t\t\t\t// overflow!\r\n\t\t}\r\n\r\n\t\t// We might have a two buffer update to do. Check for it...\r\n\t\tif ((len1 = (audioReadBufferNumSamples - audioReadBufferWritePos)) >= sampleNum)\r\n\t\t{\r\n\t\t\t// No. We got ourselfs a nice, simple single buffer update.\r\n\t\t\twriteChannelData((s16 *)((u32)audioReadBuffer + audioReadBufferWritePos * sampleSize),numChannels,samples,0,sampleNum);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Dual buffer case\r\n\t\t\twriteChannelData((s16 *)((u32)audioReadBuffer + audioReadBufferWritePos * sampleSize),numChannels,samples,0,len1);\r\n            writeChannelData((s16 *)audioReadBuffer,numChannels,samples,len1,sampleNum-len1);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfreeSamples = audioReadBufferReadPos - audioReadBufferWritePos;\r\n\r\n\t\tif (freeSamples < sampleNum)\r\n\t\t{\r\n\t\t\tOSRestoreInterrupts(old);\r\n\t\t\t#ifndef FINAL\r\n\t\t\tOSReport(\"*** audioDecode: overflow case 2\\n\");\r\n\t\t\t#endif\r\n\t\t\treturn FALSE;\t\t\t\t// overflow!\r\n\t\t}\r\n\r\n\t\t// We're save to assume to have a single buffer update in any case...\r\n\t\twriteChannelData((s16 *)((u32)audioReadBuffer + audioReadBufferWritePos * sampleSize),numChannels,samples,0,sampleNum);\r\n\t}\r\n\r\n\t// Advance write position...\r\n\taudioReadBufferWritePos += sampleNum;\r\n\r\n\tif (audioReadBufferWritePos >= audioReadBufferNumSamples)\r\n\t\taudioReadBufferWritePos -= audioReadBufferNumSamples;\r\n\r\n\t// We're done with all critical stuff. IRQs may be enabled again...\r\n\tOSRestoreInterrupts(old);\r\n\r\n\treturn TRUE;\r\n\t}\r\n\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tReceive data from bitstream and direct to required encoding facility\r\n *\r\n *\t\tThis function will receive the AUDD chunck from the VIDSimplePlayer's\r\n *\t\tdecode function.\r\n *\r\n * \\param bitstream\r\n *\t\tPointer to the data of a AUDD chunk\r\n *\r\n * \\param bitstreamLen\r\n *\t\tLength of the data in the AUDD chunk pointed to by above pointer\r\n *\r\n * \\return\r\n *\t\tFALSE if data could not be interpreted properly\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL AUDSimpleAudioDecode(const u8* bitstream, u32 bitstreamLen)\r\n\t{\r\n\r\n\t// select first two channels by default\r\n\tu32 channelSelectMask = audioPlayMaskArray ? audioPlayMaskArray[0] : 0x3;\t\t\r\n\t\r\n\tu32 headerSize = ((VidAUDDVAUD*)bitstream)->size;\r\n\tif(!VAUDDecode(audio_player.decoder, bitstream+headerSize, bitstreamLen-headerSize, channelSelectMask, audioDecode, NULL))\r\n\t\treturn FALSE;\r\n\t\r\n\taudioPlayBufferEnabled = TRUE;\r\n\t\r\n\treturn TRUE;\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tChange the active audio channels\r\n *\r\n ******************************************************************************\r\n */\r\n\t\t\t\t\r\nvoid AUDSimpleAudioChangePlayback(const u32 *playMaskArray,u32 numMasks)\r\n\t{\r\n\tu32\t\ti,b;\r\n\tBOOL\told = OSDisableInterrupts();\r\n\t\r\n\taudioPlayMaskArray = playMaskArray;\r\n\taudioNumPlayMasks = numMasks;\r\n\t\r\n\t// Any playback mask specified?\r\n\tif (audioNumPlayMasks != 0)\r\n\t\t{\r\n\t\t// Yes. Count the active voices...\r\n\t\taudioNumActiveVoices = 0;\r\n\t\t\r\n\t\tfor(i=0; i<numMasks; i++)\r\n\t\t\t{\r\n\t\t\tfor(b=0; b<32; b++)\r\n\t\t\t\t{\r\n\t\t\t\tif (audioPlayMaskArray[i] & (1<<b))\r\n\t\t\t\t\taudioNumActiveVoices++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\r\n        // So, did we have too much?\r\n\t\tASSERT(audioNumActiveVoices <= 2);\r\n\t\t}\r\n\telse\r\n\t\taudioNumActiveVoices = audioReadBufferNumChannels;\t\t// Make all active...\r\n\t\r\n\tOSRestoreInterrupts(old);\r\n\t}\r\n\r\nvoid AUDSimplePause( bool pause )\r\n{\r\n\tAXSetVoiceState(axVoice[0],pause ? AX_PB_STATE_STOP : AX_PB_STATE_RUN);\r\n\tAXSetVoiceState(axVoice[1],pause ? AX_PB_STATE_STOP : AX_PB_STATE_RUN);\r\n}\r\n\t\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tCopy PCM16 data from the read buffer into the audio buffer\r\n *\r\n *\t\tThis function serves as an internal service function to make sure\r\n *\t\tmono and stereo audio data gets properly converted into audio buffer\r\n *\t\tformat.\r\n *\r\n * \\param smpOffset\r\n *\t\tOffset in samples into the current write buffer\r\n *\r\n * \\param numSamples\r\n *\t\tNumber of samples to be updated / copied\r\n *\r\n ******************************************************************************\r\n */\r\nstatic void audioCopy(u32 smpOffset,u32 numSamples)\r\n\t{\r\n\ts16\t\t*destAddrL,*destAddrR,*srcAddr,s;\r\n\tu32\t\tj;\r\n\t\r\n\t// Target address in audio buffer\r\n\tdestAddrL = (s16 *)((u32)audioPlayBuffer[audioPlayBufferWriteIndex] + smpOffset * sizeof(s16));\r\n\tdestAddrR = (s16 *)((u32)audioPlayBuffer[audioPlayBufferWriteIndex] + smpOffset * sizeof(s16) + (AUD_AUDIO_AIBUFFERSAMPLES * sizeof(s16)));\r\n\r\n\t// Single or dual channel setup?\r\n    if (audioReadBufferNumChannels == 2)\r\n\t\t{\r\n\t\t// Stereo! Get source address of data...\r\n\t\tsrcAddr = (s16 *)((u32)audioReadBuffer + audioReadBufferReadPos * 2 * sizeof(s16));\r\n\t\t\r\n\t\t// Copy samples into AI buffer and swap channels\r\n\t\tfor(j=0; j<numSamples; j++)\r\n\t\t\t{\r\n\t\t\t*(destAddrL++) = *(srcAddr++);\r\n\t\t\t*(destAddrR++) = *(srcAddr++);\r\n\t\t\t}\r\n\t\t}\r\n\telse\r\n\t\t{\r\n\t\t// Mono case!\r\n\t\t\r\n\t\t// Make sure it's truely mono!\r\n\t\tASSERT(audioReadBufferNumChannels == 1);\r\n\t\t\r\n\t\t// Get source address...\r\n\t\tsrcAddr = (s16 *)((u32)audioReadBuffer + audioReadBufferReadPos * sizeof(s16));\r\n\t\t\r\n\t\t// Copy samples into AI buffer (AI is always stereo, so we have to dublicate data)\r\n\t\tfor(j=0; j<numSamples; j++)\r\n\t\t\t{\r\n\t\t\ts = (*srcAddr++);\r\n\t\t\t*(destAddrL++) = s;\r\n\t\t\t*(destAddrR++) = s;\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t// Advance read position as needed...\r\n\taudioReadBufferReadPos += numSamples;\r\n\tif (audioReadBufferReadPos >= audioReadBufferNumSamples)\r\n\t\taudioReadBufferReadPos -= audioReadBufferNumSamples;\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tAX callback\r\n *\r\n ******************************************************************************\r\n */\r\nstatic void AXCallback(void)\r\n{\r\n\t// First thing to do here is call the regular soundfx callback.\r\n\tSfx::AXUserCBack();\r\n\r\n\tu32\t\tavailSamples,availFrames,numUpdate,i,n;\r\n\tu32\t\taudioPlayBufferNeededAudioFrames;\r\n\tu32\t\tcurrentAddr;\r\n\r\n\t// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\r\n\t\r\n\tif (axPhase == AX_PHASE_START)\r\n\t{\r\n\t\tAXSetVoiceState(axVoice[0],AX_PB_STATE_RUN);\r\n\t\tAXSetVoiceState(axVoice[1],AX_PB_STATE_RUN);\r\n\t\taxPhase = AX_PHASE_PLAY;\r\n\t}\r\n\t\t\r\n\t// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\r\n\t\r\n\tcurrentAddr = *(u32 *)&axVoice[0]->pb.addr.currentAddressHi;\r\n\r\n\tif( currentAddr >= axLastAddr )\r\n\t{\r\n\t\taxPlayedSamples\t\t\t+= currentAddr - axLastAddr;\r\n\t\taxPlayedSamplesTotal\t+= currentAddr - axLastAddr;\r\n\t}\r\n\telse\r\n\t{\r\n\t\taxPlayedSamples\t\t\t+= (( AX_ARAM_LEFT_CHANNEL + AX_ARAM_BUFFER_SIZE ) - axLastAddr ) + ( currentAddr - AX_ARAM_LEFT_CHANNEL );\r\n\t\taxPlayedSamplesTotal\t+= (( AX_ARAM_LEFT_CHANNEL + AX_ARAM_BUFFER_SIZE ) - axLastAddr ) + ( currentAddr - AX_ARAM_LEFT_CHANNEL );\r\n\t}\r\n\t\r\n\taxLastAddr = currentAddr;\r\n\r\n\t// If we have played the required number of samples, stop the voice.\r\n\tif( axPlayedSamplesTotal >= audio_player.audioInfo.vaudex.totalSampleCount )\r\n\t{\r\n\t\tAXSetVoiceState( axVoice[0], AX_PB_STATE_STOP );\r\n\t\tAXSetVoiceState( axVoice[1], AX_PB_STATE_STOP );\r\n\t\taudio_player.playbackComplete = true;\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tif( axPlayedSamples >= AUD_AUDIO_AIBUFFERSAMPLES )\r\n\t{\r\n\t\taudioPlayBufferNeededAudioFrames = axPlayedSamples / AUD_AUDIO_AIBUFFERSAMPLES;\r\n\r\n\t\t// Make sure that we never get an underrun we don't notice...\r\n\t\tif( !( audioPlayBufferNeededAudioFrames <= AUD_AUDIO_NUMAIBUFFERS ))\r\n\t\t{\r\n//\t\t\tOSReport( \"AX audio buffer underrun!\\n\" );\r\n\r\n\t\t\t// Disable playback.\r\n\t\t\taudioPlayBufferEnabled = false;\r\n\t\t}\r\n\r\n\t\t// Is actual audio playback enabled?\r\n\t\tif( audioPlayBufferEnabled )\r\n\t\t{\r\n\t\t\t// How many samples could we get from the read buffer?\r\n\t\t\tif( audioReadBufferWritePos >= audioReadBufferReadPos )\r\n\t\t\t\tavailSamples = audioReadBufferWritePos - audioReadBufferReadPos;\r\n\t\t\telse\r\n\t\t\t\tavailSamples = audioReadBufferNumSamples - ( audioReadBufferReadPos - audioReadBufferWritePos );\r\n\t\t\t\r\n\t\t\t// That's how many audio frames?\r\n\t\t\tavailFrames = availSamples / AUD_AUDIO_AIBUFFERSAMPLES;\r\n\r\n\t\t\t//OSReport(\"AX: %d %d (%d)\\n\",availSamples,audioPlayBufferNeededAudioFrames * VID_AUDIO_AIBUFFERSAMPLES,axPlayedSamples);\r\n\t\r\n\t\t\t// So, how many can we update?\r\n\t\t\tnumUpdate = ( availFrames > audioPlayBufferNeededAudioFrames ) ? audioPlayBufferNeededAudioFrames : availFrames;\r\n\t\r\n\t\t\t// If anything... go do it!\r\n\t\t\tif( numUpdate != 0 )\r\n\t\t\t{\r\n\t\t\t\taxPlayedSamples -= numUpdate * AUD_AUDIO_AIBUFFERSAMPLES;\r\n\t\t\t\t\r\n\t\t\t\t// Perform updates on each AI buffer in need of data...\r\n\t\t\t\tfor( i = 0; i < numUpdate; i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tu32 leftSource, rightSource, leftTarget, rightTarget;\r\n\r\n\t\t\t\t\t// Can we copy everything from a single source or does the data wrap around?\r\n\t\t\t\t\tif(( n = audioReadBufferNumSamples - audioReadBufferReadPos) < AUD_AUDIO_AIBUFFERSAMPLES )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// It wraps...\r\n\t\t\t\t\t\taudioCopy( 0, n );\r\n\t\t\t\t\t\taudioCopy( n, AUD_AUDIO_AIBUFFERSAMPLES - n );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// We got one continous source buffer\r\n\t\t\t\t\t\taudioCopy( 0, AUD_AUDIO_AIBUFFERSAMPLES );\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t// Make sure the data ends up in real physical memory\r\n\t\t\t\t\tDCFlushRange( audioPlayBuffer[audioPlayBufferWriteIndex], AUD_AUDIO_AIBUFFERSAMPLES * sizeof( s16 ) * 2 );\r\n\t\t\t\t\t\r\n\t\t\t\t\tleftSource\t= (u32)audioPlayBuffer[audioPlayBufferWriteIndex];\r\n\t\t\t\t\trightSource\t= (u32)audioPlayBuffer[audioPlayBufferWriteIndex] + ( AUD_AUDIO_AIBUFFERSAMPLES * sizeof( s16 ));\r\n\t\t\t\t\tleftTarget\t= 2 * ( AX_ARAM_LEFT_CHANNEL + audioPlayBufferWriteIndex * AUD_AUDIO_AIBUFFERSAMPLES );\r\n\t\t\t\t\trightTarget\t= 2 * ( AX_ARAM_RIGHT_CHANNEL + audioPlayBufferWriteIndex * AUD_AUDIO_AIBUFFERSAMPLES );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Make sure we get this into ARAM ASAP...\r\n\t\t\t\t\tARQPostRequest( &arqRequest[0][i%AUD_NUM_ARQ_REQUESTS], 0, ARQ_TYPE_MRAM_TO_ARAM,ARQ_PRIORITY_HIGH, leftSource, leftTarget, AUD_AUDIO_AIBUFFERSAMPLES * sizeof( s16 ), NULL );\r\n\t\t\t\t\tARQPostRequest( &arqRequest[1][i%AUD_NUM_ARQ_REQUESTS], 1, ARQ_TYPE_MRAM_TO_ARAM,ARQ_PRIORITY_HIGH, rightSource, rightTarget, AUD_AUDIO_AIBUFFERSAMPLES * sizeof( s16 ), NULL );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Advance write index...\r\n\t\t\t\t\taudioPlayBufferWriteIndex = (u8)(( audioPlayBufferWriteIndex + 1 ) % AUD_AUDIO_NUMAIBUFFERS );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif( axPhase == AX_PHASE_STARTUP )\r\n\t\t\t\t{\r\n\t\t\t\t\taxPhase = AX_PHASE_START;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Update buffer(s) with silence...\r\n\t\t\taxPlayedSamples -= audioPlayBufferNeededAudioFrames * AUD_AUDIO_AIBUFFERSAMPLES;\r\n\t\t\t\r\n\t\t\tfor( i = 0; i < audioPlayBufferNeededAudioFrames; i++ )\r\n\t\t\t{\r\n\t\t\t\tu32 leftSource, rightSource, leftTarget, rightTarget;\r\n\r\n\t\t\t\tmemset(audioPlayBuffer[audioPlayBufferWriteIndex],0,2 * sizeof(s16) * AUD_AUDIO_AIBUFFERSAMPLES);\r\n\t\t\t\tDCFlushRange(audioPlayBuffer[audioPlayBufferWriteIndex],2 * sizeof(s16) * AUD_AUDIO_AIBUFFERSAMPLES);\r\n\t\r\n\t\t\t\tleftSource = (u32)audioPlayBuffer[audioPlayBufferWriteIndex];\r\n\t\t\t\trightSource = (u32)audioPlayBuffer[audioPlayBufferWriteIndex] + (AUD_AUDIO_AIBUFFERSAMPLES * sizeof(s16)) / 2;\r\n\t\t\t\tleftTarget = 2 * (AX_ARAM_LEFT_CHANNEL + audioPlayBufferWriteIndex * AUD_AUDIO_AIBUFFERSAMPLES);\r\n\t\t\t\trightTarget = 2 * (AX_ARAM_RIGHT_CHANNEL + audioPlayBufferWriteIndex * AUD_AUDIO_AIBUFFERSAMPLES);\r\n\t\t\t\t\r\n\t\t\t\t// Make sure we get this into ARAM ASAP...\r\n\t\t\t\tARQPostRequest(&arqRequest[0][i%AUD_NUM_ARQ_REQUESTS],0,ARQ_TYPE_MRAM_TO_ARAM,ARQ_PRIORITY_HIGH,leftSource,leftTarget,AUD_AUDIO_AIBUFFERSAMPLES * sizeof(s16),NULL);\r\n\t\t\t\tARQPostRequest(&arqRequest[1][i%AUD_NUM_ARQ_REQUESTS],1,ARQ_TYPE_MRAM_TO_ARAM,ARQ_PRIORITY_HIGH,rightSource,rightTarget,AUD_AUDIO_AIBUFFERSAMPLES * sizeof(s16),NULL);\r\n\t\t\t\t\r\n\t\t\t\taudioPlayBufferWriteIndex = (u8)((audioPlayBufferWriteIndex + 1) % AUD_AUDIO_NUMAIBUFFERS);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (axPhase == AX_PHASE_STARTUP)\r\n\t\t\t\taxPhase = AX_PHASE_START;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n#endif\t\t// DVDETH\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/divx/AUDSimpleAudio.h",
    "content": "/*!\r\n ******************************************************************************\r\n * \\file AUDSimpleAudio.h\r\n *\r\n * \\brief\r\n *\t\tHeader file for AUDSimpleAudio interface\r\n *\r\n * \\date\r\n *\t\t5/22/03\r\n *\r\n * \\version\r\n *\t\t1.0\r\n *\r\n * \\author\r\n *\t\tThomas Engel/Achim Moller\r\n *\r\n ******************************************************************************\r\n */\r\n#ifndef __AUDSIMPLE_AUDIO_H__\r\n#define __AUDSIMPLE_AUDIO_H__\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\n/******************************************************************************\r\n *  INCLUDES\r\n ******************************************************************************/\r\n#include <dolphin/types.h>\r\n#include <demo.h>\r\n#include \"vaud.h\"\r\n\r\n/******************************************************************************\r\n *  DEFINES\r\n ******************************************************************************/\r\n\r\n/******************************************************************************\r\n *  STRUCTS AND TYPES\r\n ******************************************************************************/\r\n\r\n/******************************************************************************\r\n *  PROTOTYPES\r\n ******************************************************************************/\r\n\r\n//! Initialize audio decoding / playback\r\nextern BOOL AUDSimpleInitAudioDecoder(void);\r\n\r\n//! Shutdown audio decoding / playback\r\nextern void AUDSimpleExitAudioDecoder(void);\r\n\r\n//! Decode audio data for one frame\r\nextern BOOL AUDSimpleAudioDecode(const u8* bitstream, u32 bitstreamLen);\r\n\r\n//! Change currently active audio channels\r\nextern void AUDSimpleAudioChangePlayback(const u32 *playMaskArray,u32 numMasks);\r\n\r\n//! Stop audio decode / output\r\nextern void AUDSimpleAudioReset(void);\r\n\r\n//! Return some information about running audio\r\nextern void AUDSimpleAudioGetInfo(VidAUDH* audioHeader);\r\n\r\nextern u32\tAUDSimpleAudioGetFreeReadBufferSamples( void );\r\nextern void\tAUDSimpleAudioSetVolume( u16 vl, u16 vr );\r\n\r\nextern void AUDSimplePause( bool pause );\r\n\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n#endif\t// __AUDSIMPLE_PLAYER_H__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/divx/AUDSimplePlayer.cpp",
    "content": "#ifndef DVDETH\r\n/*!\r\n ******************************************************************************\r\n * \\file AUDSimplePlayer.cpp\r\n *\r\n * \\brief\r\n *\t\tThis file provides the required player control functions.\r\n *\r\n * \\note\r\n *      This is a demonstration source only!\r\n *\r\n * \\date\r\n *\t\t05/21/03\r\n *\r\n * \\version\r\n *\t\t1.0\r\n *\r\n * \\author\r\n *\t\tAchim Moller\r\n *\r\n ******************************************************************************\r\n */\r\n\r\n/******************************************************************************\r\n *  INCLUDES\r\n ******************************************************************************/\r\n#include <dolphin.h>\r\n#include <string.h>\r\n\r\n#include \"AUDSimplePlayer.h\"\r\n#include \"AUDSimpleAudio.h\"\r\n\r\n/******************************************************************************\r\n *  GLOABL VARIABLES\r\n ******************************************************************************/\r\nAudSimplePlayer audio_player;\r\n\r\n#ifndef MIN\r\n#define MIN(a,b) ((a) < (b) ? a : b)\r\n#endif\r\n\r\n/******************************************************************************\r\n *  LOCAL VARIABLES\r\n ******************************************************************************/\r\nstatic VidChunk workChunk ATTRIBUTE_ALIGN(32);\r\nstatic void dvdDoneCallback(s32 result, DVDFileInfo *videoInfo);\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tInitializes all audio_player structures.\r\n *\r\n ******************************************************************************\r\n */\r\nvoid AUDSimpleInit(VAUDAllocator _cbAlloc, VAUDDeallocator _cbFree)\r\n\t{\r\n\tmemset(&audio_player, 0, sizeof(audio_player));\r\n\taudio_player.cbAlloc = _cbAlloc;\r\n\taudio_player.cbFree = _cbFree;\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tRequest an async file transfer.\r\n *\r\n *\t\tThis function starts the transfer of the next frame into a free\r\n *\t\tbuffer.\r\n *\r\n ******************************************************************************\r\n */\r\nstatic void ReadFrameAsync(void)\r\n\t{\r\n\tif (!audio_player.error && audio_player.preFetchState == TRUE)\r\n\t\t{\r\n\t\tif (audio_player.currentFrameCount >  audio_player.audioInfo.vaudex.frameCount - 1)\r\n\t\t\t{\r\n\t\t\tif (audio_player.loopMode)\r\n\t\t\t\t{\r\n\t\t\t\taudio_player.currentFrameCount = 0;\r\n\t\t\t\taudio_player.nextFrameOffset = audio_player.firstFrameOffset;\r\n\t\t\t\taudio_player.nextFrameSize  = audio_player.firstFrameSize;\r\n\t\t\t\t}\r\n\t\t\telse\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\r\n\t\taudio_player.asyncDvdRunning = TRUE;\r\n\r\n\t\tif (DVDReadAsync(&audio_player.fileHandle,\r\n\t\t\t\t\t\t audio_player.readBuffer[audio_player.readIndex].ptr,\r\n\t\t\t\t\t\t (s32)audio_player.nextFrameSize,\r\n\t\t\t\t\t\t (s32)audio_player.nextFrameOffset, dvdDoneCallback) != TRUE )\r\n\t\t\t{\r\n\t\t\taudio_player.asyncDvdRunning = FALSE;\r\n\t\t\taudio_player.error = TRUE;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tDVD callback if async transfer is finished (or aborted)\r\n *\t\r\n *\t\tThe idea here is to transfer ONE frame and additional 32 bytes for the\r\n *\t\tHEADER of the NEXT frame in one transfer step. We store the size of\r\n *\t\tthe next frame, which is used in ReadFrameAsync().\r\n *\r\n *\t\t\r\n * \\note\r\n *\t\tThere a 32 padding bytes at the end of the .vid file. So, the reading\r\n *\t\tof 32 additional bytes is even possible for the LAST frame. (Otherwise,\r\n *\t\twe would 'point' out of the file)\r\n *\r\n *\t\tSee Dolphin documentation for information about parameters.\r\n *\r\n ******************************************************************************\r\n */\r\nstatic void dvdDoneCallback(s32 result, DVDFileInfo * _UNUSED(videoInfo))\r\n\t{\r\n\tif (result == DVD_RESULT_FATAL_ERROR)\r\n\t\t{\r\n\t\taudio_player.error = TRUE;\r\n\t\treturn;\r\n\t\t}\r\n\telse if (result == DVD_RESULT_CANCELED)\r\n\t\t{\r\n\t\treturn;\r\n\t\t}\r\n\r\n\taudio_player.asyncDvdRunning = FALSE;\r\n\r\n\taudio_player.readBuffer[audio_player.readIndex].frameNumber = audio_player.currentFrameCount;\r\n\taudio_player.readBuffer[audio_player.readIndex].size = (u32)result;\t\r\n\taudio_player.readBuffer[audio_player.readIndex].valid = TRUE;\r\n\t\r\n\taudio_player.currentFrameCount++;\r\n\r\n\t// move file pointer\r\n\taudio_player.nextFrameOffset += audio_player.nextFrameSize;\r\n\t\r\n\tif(audio_player.currentFrameCount < audio_player.audioInfo.vaudex.frameCount)\r\n\t\t{\r\n\t\t// set read size for next 'FRAM' chunk\r\n\t\tu32* nextFrameStart = (u32*)(audio_player.readBuffer[audio_player.readIndex].ptr + audio_player.nextFrameSize - 32);\r\n\t\r\n\t\t// some check if file structure is okay\r\n\t\tASSERT(nextFrameStart[0] == VID_FCC('F','R','A','M'));\r\n\t\t\r\n\t\t// get the size of the next 'FRAM' chunk to read\r\n\t\taudio_player.nextFrameSize = nextFrameStart[1];\r\n\t\tASSERT(audio_player.nextFrameSize);\r\n\t\t}\r\n\telse\r\n\t\taudio_player.nextFrameSize = 0;\t// at end of file we have a size of '0'. This should be reinitialized later\r\n\t\t\t\t\t\t\t\t\t// using the size of the first frame somwhere else! Otherwise, we get an assertion\r\n\r\n\t// use next buffer\r\n\taudio_player.readIndex = (audio_player.readIndex + 1) % AUD_NUM_READ_BUFFERS;\r\n\r\n\t// continue loading if we have a free buffer\r\n\tif (!audio_player.readBuffer[audio_player.readIndex].valid)\r\n\t\tReadFrameAsync();\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tAllocate buffer memory for asynchronous dvd read\r\n *\r\n* \\return\r\n *\t\tTRUE if DVD buffer setup was successful.\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL AUDSimpleAllocDVDBuffers(void)\r\n\t{\r\n\tu32 i;\r\n\tu32 bufferSize;\r\n\tu8* ptr;\r\n\r\n\tbufferSize = audio_player.audioInfo.vaudex.maxBufferSize;\r\n\tASSERT(bufferSize);\r\n\t\r\n\tbufferSize += VID_CHUNK_HEADER_SIZE;\t// 'fram' header\r\n\tbufferSize += VID_CHUNK_HEADER_SIZE;\t// 'vidd' header\r\n\tbufferSize = OSRoundUp32B(bufferSize);\r\n\t\r\n\tASSERT(audio_player.cbAlloc);\r\n\taudio_player.readBufferBaseMem = (u8*)((*audio_player.cbAlloc)(bufferSize * AUD_NUM_READ_BUFFERS));\r\n\t\r\n\tif(!audio_player.readBufferBaseMem)\r\n\t\treturn FALSE;\t// out of mem\r\n\t\r\n\tptr = audio_player.readBufferBaseMem;\r\n\tfor (i = 0; i < AUD_NUM_READ_BUFFERS ; i++)\r\n\t\t{\r\n\t\taudio_player.readBuffer[i].ptr = ptr;\r\n\t\tptr += bufferSize;\r\n\t\taudio_player.readBuffer[i].valid = FALSE;\r\n\t\t}\r\n\t\r\n\treturn TRUE;\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tFree buffer memory used for dvd read\r\n *\r\n * \\param memFree\r\n *\t\tPointer to memory deallocation function\r\n *\r\n ******************************************************************************\r\n */\r\nvoid AUDSimpleFreeDVDBuffers(void)\r\n\t{\r\n\tASSERT(audio_player.cbFree);\r\n\tASSERT(audio_player.readBufferBaseMem);\r\n\t(*audio_player.cbFree)(audio_player.readBufferBaseMem);\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tCreate a new decoder instance.\r\n *\r\n * \\return\r\n *\t\tTRUE if decoder creation was successful\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL AUDSimpleCreateDecoder(void)\r\n\t{\r\n\tu32 skip;\r\n\t\r\n\taudio_player.decoder = VAUDCreateDecoder(audio_player.cbAlloc, audio_player.cbFree, audio_player.audioInfo.vaud.maxHeap);\r\n\t\r\n\tif(!audio_player.decoder)\r\n\t\treturn FALSE;\r\n\r\n\tASSERT(audio_player.audioHeaderChunk);\r\n\tASSERT(audio_player.audioInfo.vaud.maxHeap > 0);\r\n\tASSERT(audio_player.audioInfo.vaud.preAlloc > 0);\r\n\tskip = VID_CHUNK_HEADER_SIZE + sizeof(u32) + (audio_player.audioInfo.vaudex.version > 0 ? audio_player.audioInfo.vaudex.size : sizeof(VidAUDHVAUD));\r\n\r\n\tif(!VAUDInitDecoder(audio_player.decoder, audio_player.audioHeaderChunk + skip, ((VidChunk*)audio_player.audioHeaderChunk)->len - skip, audio_player.audioInfo.vaud.preAlloc))\r\n\t\t{\r\n\t\tVAUDDestroyDecoder(audio_player.decoder);\r\n\t\treturn FALSE;\r\n\t\t}\r\n\t\r\n\treturn TRUE;\r\n\t}\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tDestroy decoder instance.\r\n *\r\n *\t\tAt this point the decoder returns all allocated memory by using\r\n *\t\tthe cbFree callback.\r\n *\r\n ******************************************************************************\r\n */\r\nvoid AUDSimpleDestroyDecoder(void)\r\n{\r\n\tASSERT(audio_player.decoder);\r\n\tVAUDDestroyDecoder(audio_player.decoder);\r\n\t\r\n\t// Set the decoder to NULL.\r\n\taudio_player.decoder = NULL;\r\n}\r\n\r\n\r\n\r\nstatic u32 readNum = 0;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void AUDSimpleLoadStartDVDCallback( s32 result, DVDFileInfo* fileInfo )\r\n{\r\n\t// Deal with errors.\r\n\tif( audio_player.error )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\taudio_player.nextFrameOffset += audio_player.nextFrameSize;\r\n\taudio_player.readBuffer[audio_player.readIndex].size = audio_player.nextFrameSize;\r\n\r\n\t// Set read size for next 'FRAM' chunk.\r\n\tu32* nextFrame = (u32*)(audio_player.readBuffer[audio_player.readIndex].ptr + audio_player.nextFrameSize - 32);\r\n\r\n\t// Some sanity check if file structure is valid!\r\n\tASSERT( nextFrame[0] == VID_FCC( 'F','R','A','M' ));\r\n\r\n\taudio_player.nextFrameSize = nextFrame[1];\r\n\tASSERT( audio_player.nextFrameSize );\r\n\r\n\taudio_player.readBuffer[audio_player.readIndex].valid = TRUE;\r\n\taudio_player.readBuffer[audio_player.readIndex].frameNumber = audio_player.currentFrameCount;\r\n\r\n\t// Use next buffer.\r\n\taudio_player.readIndex = (audio_player.readIndex + 1) % AUD_NUM_READ_BUFFERS;\r\n\taudio_player.currentFrameCount++;\r\n\t\r\n\tif( --readNum > 0 )\r\n\t{\r\n\t\tif( DVDReadAsync( &audio_player.fileHandle, audio_player.readBuffer[audio_player.readIndex].ptr, (s32)audio_player.nextFrameSize, (s32)audio_player.nextFrameOffset, AUDSimpleLoadStartDVDCallback ) < 0 )\r\n\t\t{\r\n#\t\t\tifdef _DEBUG\r\n\t\t\tOSReport(\"*** AUDSimpleLoadStart: Failed to read from file.\\n\");\r\n#\t\t\tendif\r\n\t\t\taudio_player.error = TRUE;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// All done.\r\n\t\taudio_player.loopMode\t\t= FALSE;\r\n\t\taudio_player.preFetchState\t= TRUE;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tPreload the allocated buffers.\r\n *\r\n *\t\tThis functions fills all buffers with initial data\r\n *\r\n * \\param loopMode\r\n *\t\tTRUE if we want to operate in loop mode\r\n *\r\n * \\return\r\n *\t\tTRUE if preload was okay \t\t\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL AUDSimpleLoadStart(BOOL loopMode)\r\n{\r\n//\tu32\t\ti, readNum;\r\n//\tu32\t\ti;\r\n//\tu32*\tnextFrame;\r\n\r\n\tASSERT( loopMode == FALSE );\r\n\t\r\n\tif( audio_player.open && audio_player.preFetchState == FALSE )\r\n\t{\r\n\t\treadNum = AUD_NUM_READ_BUFFERS;\r\n\r\n\t\t// In 'non-loop' mode we must take care if we have LESS frames than preloading buffers\r\n        if( !loopMode && audio_player.audioInfo.vaudex.frameCount < AUD_NUM_READ_BUFFERS )\r\n\t\t\treadNum = audio_player.audioInfo.vaudex.frameCount;\r\n\t\t\t\t\r\n//\t\tfor( i = 0; i < readNum; i++ )\r\n\t\tif( readNum > 0 )\r\n\t\t{\r\n\t\t\t// Read total 'FRAM' chunk and 32 bytes of NEXT chunk.\r\n//\t\t\tif( DVDRead( &audio_player.fileHandle, ptr, (s32)audio_player.nextFrameSize, (s32)audio_player.nextFrameOffset ) < 0 )\r\n\t\t\tif( DVDReadAsync( &audio_player.fileHandle, audio_player.readBuffer[audio_player.readIndex].ptr, (s32)audio_player.nextFrameSize, (s32)audio_player.nextFrameOffset, AUDSimpleLoadStartDVDCallback ) < 0 )\r\n\t\t\t{\r\n#\t\t\t\tifdef _DEBUG\r\n\t\t\t\tOSReport(\"*** AUDSimpleLoadStart: Failed to read from file.\\n\");\r\n#\t\t\t\tendif\r\n\t\t\t\taudio_player.error = TRUE;\r\n\t\t\t\treturn FALSE;\r\n\t\t\t}\r\n\t\t\t\r\n//\t\t\taudio_player.nextFrameOffset += audio_player.nextFrameSize;\r\n//\t\t\taudio_player.readBuffer[audio_player.readIndex].size = audio_player.nextFrameSize;\r\n\r\n            // set read size for next 'FRAM' chunk\r\n//\t\t\tnextFrame = (u32*)(audio_player.readBuffer[audio_player.readIndex].ptr + audio_player.nextFrameSize - 32);\r\n\t\t\t\r\n\t\t\t// some sanity check if file structure is valid!\r\n//\t\t\tASSERT(nextFrame[0] == VID_FCC('F','R','A','M'));\r\n\t\t\t\r\n//\t\t\taudio_player.nextFrameSize = nextFrame[1];\r\n//\t\t\tASSERT( audio_player.nextFrameSize );\r\n\r\n//\t\t\taudio_player.readBuffer[audio_player.readIndex].valid = TRUE;\r\n//\t\t\taudio_player.readBuffer[audio_player.readIndex].frameNumber = audio_player.currentFrameCount;\r\n\r\n\t\t\t// Use next buffer\r\n//\t\t\taudio_player.readIndex = (audio_player.readIndex + 1) % AUD_NUM_READ_BUFFERS;\r\n\r\n//\t\t\taudio_player.currentFrameCount++;\r\n\r\n//\t\t\tif (audio_player.currentFrameCount >  audio_player.audioInfo.vaudex.frameCount - 1)\r\n//\t\t\t{\r\n//\t\t\t\tif (loopMode)\r\n//\t\t\t\t{\r\n//\t\t\t\t\taudio_player.currentFrameCount = 0;\r\n//\t\t\t\t\taudio_player.nextFrameOffset = audio_player.firstFrameOffset;\r\n//\t\t\t\t\taudio_player.nextFrameSize  = audio_player.firstFrameSize;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n\t\t}\r\n//\t\taudio_player.loopMode = loopMode;\r\n//\t\taudio_player.preFetchState = TRUE;\r\n\t\treturn TRUE;\r\n\t}\r\n\treturn FALSE;\r\n}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tStops the asynchronous loading process.\r\n *\r\n * \\return\r\n *\t\tTRUE if audio_player could be stopped!\t\t\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL AUDSimpleLoadStop(void)\r\n\t{\r\n\tu32 i;\r\n\r\n\tif (audio_player.open)\r\n\t\t{\r\n\t\t// stop preloading process\r\n\t\taudio_player.preFetchState = FALSE;\r\n\r\n\t\tif (audio_player.asyncDvdRunning)\r\n\t\t\t{\r\n\t\t\tDVDCancel(&audio_player.fileHandle.cb);\r\n\t\t\taudio_player.asyncDvdRunning = FALSE;\r\n\t\t\t}\r\n\r\n\t\t// invalidate all buffers\r\n\t\tfor (i = 0 ; i < AUD_NUM_READ_BUFFERS; i++)\r\n\t\t\taudio_player.readBuffer[i].valid = FALSE;\r\n\r\n\t\taudio_player.nextFrameOffset = audio_player.firstFrameOffset;\r\n\t\taudio_player.nextFrameSize = audio_player.firstFrameSize;\r\n\t\taudio_player.currentFrameCount = 0;\r\n\t\t\r\n\t\taudio_player.error \t   \t\t= FALSE;\r\n\t\taudio_player.readIndex   \t\t= 0;\r\n\t\taudio_player.decodeIndex \t\t= 0;\r\n\r\n\t\treturn TRUE;\r\n\t\t}\r\n\treturn FALSE;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void AUDSimpleOpenDVDCallback( s32 result, DVDFileInfo* fileInfo )\r\n{\r\n\tstatic u32\tfileOffset\t\t= 0;\r\n\tstatic u32\theadSize\t\t= 0;\r\n\tstatic u32\taudioInfoSize\t= 0;\r\n\t\r\n\t// Deal with errors, possibly flagged as an indication to shut down immediately.\r\n\tif( audio_player.error )\r\n\t{\r\n\t\t// Set this back to zero so the player will be regarded as 'free' again.\r\n\t\taudio_player.asyncOpenCallbackStatus = 0;\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tswitch( audio_player.asyncOpenCallbackStatus )\r\n\t{\r\n\t\tcase 1:\r\n\t\t{\r\n\t\t\t// The read of the 'VID1' chunk has completed.\r\n\t\t\tfileOffset = 32;\r\n\t\r\n\t\t\t// Check file id.\r\n\t\t\tif( workChunk.id != VID_FCC('V','I','D','1' ))\r\n\t\t\t{\r\n#\t\t\t\tifdef _DEBUG\r\n\t\t\t\tOSReport(\"*** No VID1 file: '%s'\\n\", fileName);\r\n#\t\t\t\tendif\r\n\t\t\t\tDVDClose( &audio_player.fileHandle );\r\n\t\t\t\taudio_player.asyncOpenCallbackStatus = ASYNC_OPEN_FAIL;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\r\n\t\t\t// Check for correct version of vid chunk.\r\n\t\t\t// If we find this version we assume a 'special' alignment and chunk ordering which may be invalid\r\n\t\t\t// in another version of the file format.\r\n\t\t\tif( workChunk.vid.versionMajor != 1 || workChunk.vid.versionMinor != 0 )\r\n\t\t\t{\r\n#\t\t\t\tifdef _DEBUG\r\n\t\t\t\tOSReport(\"*** Unsupported file version: major: %d, minor: %d\\n\", workChunk.vid.versionMajor, workChunk.vid.versionMajor);\r\n#\t\t\t\tendif\r\n\t\t\t\tDVDClose( &audio_player.fileHandle );\r\n\t\t\t\taudio_player.asyncOpenCallbackStatus = ASYNC_OPEN_FAIL;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\r\n#\t\t\tifdef _DEBUG\r\n\t\t\t// Sometimes, it's required to check for a special build of the VidConv converter.\r\n\t\t\t{\r\n\t\t\t\tu32 version = VID_VERSION(workChunk.vid.vidConvMajor, workChunk.vid.vidConvMinor, workChunk.vid.vidConvBuild);\r\n\t\t\t\tif( version < VID_VERSION( 1, 0, 1 ))\r\n\t\t\t\t\tOSReport(\"*** WARNING: Vid file created using an unsupported converter version: %d.%d.%d\\n\", (u32)workChunk.vid.vidConvMajor, (u32)workChunk.vid.vidConvMinor, (u32)workChunk.vid.vidConvBuild);\r\n\t\t\t}\r\n#\t\t\tendif\r\n\r\n\t\t\t// Set callback status to indicate 'VID1' chunk is read.\r\n\t\t\taudio_player.asyncOpenCallbackStatus = 2;\r\n\t\t\t\r\n\t\t\t// Check types of chunks we have in this file.\r\n\t\t\t// !!! Note that we assume start of 'HEAD' chunk at byte offset 32 from file start !!!\r\n\t\t\tif( DVDReadAsync( &audio_player.fileHandle, &workChunk, 32, (s32)fileOffset, AUDSimpleOpenDVDCallback ) < 0 )\r\n\t\t\t{\r\n#\t\t\t\tifdef _DEBUG\r\n\t\t\t\tOSReport(\"*** Failed to read 'HEAD' chunk.\\n\");\r\n#\t\t\t\tendif\r\n\t\t\t\tDVDClose( &audio_player.fileHandle );\r\n\t\t\t\taudio_player.asyncOpenCallbackStatus = ASYNC_OPEN_FAIL;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\r\n\t\tcase 2:\r\n\t\t{\r\n\t\t\t// The read of the chunk type info has completed.\r\n\t\t\tif( workChunk.id != VID_FCC('H','E','A','D' ))\r\n\t\t\t{\r\n#\t\t\t\tifdef _DEBUG\r\n\t\t\t\tOSReport(\"*** No HEAD chunk found at expected offset\\n\");\r\n#\t\t\t\tendif\r\n\t\t\t\tDVDClose( &audio_player.fileHandle );\r\n\t\t\t\taudio_player.asyncOpenCallbackStatus = ASYNC_OPEN_FAIL;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// Calculate the start of the first frame chunk (we know the header chunk starts at offset 32).\r\n\t\t\taudio_player.nextFrameOffset = workChunk.len + 32;\r\n\r\n\t\t\t// Skip 'HEAD' chunk id, len and version fields.\r\n\t\t\tfileOffset += VID_CHUNK_HEADER_SIZE;\r\n\r\n\t\t\t// The header chunk contains one or more header chunks for the different data types contained\r\n\t\t\t// in the stream. Parse them all...\r\n\r\n\t\t\theadSize = workChunk.len - VID_CHUNK_HEADER_SIZE;\r\n\t\t\t\r\n\t\t\taudio_player.asyncOpenCallbackStatus = 3;\r\n\t\t\tif( DVDReadAsync( &audio_player.fileHandle, &workChunk, 32, (s32)fileOffset, AUDSimpleOpenDVDCallback ) < 0 )\r\n\t\t\t{\r\n#\t\t\t\tifdef _DEBUG\r\n\t\t\t\tOSReport(\"*** Error reading file at offset %d\\n\", fileOffset);\r\n#\t\t\t\tendif\r\n\t\t\t\tDVDClose( &audio_player.fileHandle );\r\n\t\t\t\taudio_player.asyncOpenCallbackStatus = ASYNC_OPEN_FAIL;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\r\n\t\tcase 3:\r\n\t\t{\r\n\t\t\tfileOffset\t+= 32;\r\n\t\t\theadSize\t-= 32;\r\n\r\n\t\t\t// We analyze the 1st 32 bytes of the chunk for a known header format.\r\n\t\t\tif( workChunk.id == VID_FCC( 'A','U','D','H' ))\r\n\t\t\t{\r\n\t\t\t\t// Allocate memory for audio header chunk.\r\n\t\t\t\taudio_player.audioHeaderChunk\t= (u8*)((*audio_player.cbAlloc)(workChunk.len));\r\n\t\t\t\taudioInfoSize\t\t\t\t\t= workChunk.len - VID_CHUNK_HEADER_SIZE;\r\n\r\n\t\t\t\t// Copy the already loaded part.\r\n\t\t\t\tmemcpy( audio_player.audioHeaderChunk, &workChunk, 32 );\r\n\t\t\t\tworkChunk.len -= 32;\r\n\r\n\t\t\t\t// Read additional audio header bytes if the audio header is greater that 32 bytes\r\n\t\t\t\tif( workChunk.len >= 32 )\r\n\t\t\t\t{\r\n\t\t\t\t\tASSERT(( workChunk.len & 31 ) == 0 );\r\n\t\t\t\t\taudio_player.asyncOpenCallbackStatus = 4;\r\n\t\t\t\t\tif( DVDReadAsync( &audio_player.fileHandle, audio_player.audioHeaderChunk + 32, workChunk.len, (s32)fileOffset, AUDSimpleOpenDVDCallback ) < 0 )\r\n\t\t\t\t\t{\r\n#\t\t\t\t\t\tifdef _DEBUG\r\n\t\t\t\t\t\tOSReport(\"*** Error reading file at offset %d\\n\", fileOffset);\r\n#\t\t\t\t\t\tendif\r\n\t\t\t\t\t\tDVDClose( &audio_player.fileHandle );\r\n\t\t\t\t\t\taudio_player.asyncOpenCallbackStatus = ASYNC_OPEN_FAIL;\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tASSERT( 0 );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tASSERT( 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\t\r\n\t\tcase 4:\r\n\t\t{\r\n\t\t\tfileOffset\t+= workChunk.len;\r\n\t\t\theadSize\t-= workChunk.len;\r\n\r\n\t\t\t// Setup and calc the number of bytes which we are allowed to copy into the audioInfo struct\r\n\t\t\tmemcpy( &audio_player.audioInfo, audio_player.audioHeaderChunk + VID_CHUNK_HEADER_SIZE, MIN( audioInfoSize, sizeof( audio_player.audioInfo )));\r\n\t\t\t\r\n\t\t\t// Check if we have the correct vaud file version (>0).\r\n\t\t\tif( audio_player.audioInfo.vaudex.version == 0 )\r\n\t\t\t{\r\n#\t\t\t\tifdef _DEBUG\r\n\t\t\t\tOSReport(\"*** Invalid version in vaud file.\");\r\n#\t\t\t\tendif\r\n\t\t\t\tDVDClose( &audio_player.fileHandle );\r\n\t\t\t\taudio_player.asyncOpenCallbackStatus = ASYNC_OPEN_FAIL;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// We can only play audio files which have the following fields set.\r\n\t\t\t// Note that in case of VIDEO files this fields are allowed to be 0.\r\n\t\t\tASSERT( audio_player.audioInfo.vaudex.maxBufferSize > 0 );\r\n\t\t\tASSERT( audio_player.audioInfo.vaudex.frameCount > 0 );\r\n\t\t\tASSERT( audio_player.audioInfo.vaudex.frameTimeMs > 0 );\r\n\r\n\t\t\t// Read beginning of 1st frame chunk to get required size information.\r\n\t\t\taudio_player.asyncOpenCallbackStatus = 5;\r\n\t\t\tif( DVDReadAsync( &audio_player.fileHandle, &workChunk, 32 , (s32)audio_player.nextFrameOffset, AUDSimpleOpenDVDCallback ) < 0 )\r\n\t\t\t{\r\n#\t\t\t\tifdef _DEBUG\r\n\t\t\t\tOSReport(\"*** Failed to read 'FRAM' chunk.\\n\");\r\n#\t\t\t\tendif\r\n\t\t\t\tDVDClose( &audio_player.fileHandle );\r\n\t\t\t\taudio_player.asyncOpenCallbackStatus = ASYNC_OPEN_FAIL;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase 5:\r\n\t\t{\r\n\t\t\tif( workChunk.id != VID_FCC('F','R','A','M') )\r\n\t\t\t{\r\n#\t\t\t\tifdef _DEBUG\r\n\t\t\t\tOSReport(\"*** No FRAM chunk found.\");\r\n#\t\t\t\tendif\r\n\t\t\t\taudio_player.asyncOpenCallbackStatus = ASYNC_OPEN_FAIL;\r\n\t\t\t\tDVDClose( &audio_player.fileHandle );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// 32 bytes of this chunk are already consumed, but we want to 'preload' the NEXT chunk's FRAM header.\r\n\t\t\taudio_player.nextFrameSize\t\t\t\t= workChunk.len; \t\t\r\n\t\t\taudio_player.nextFrameOffset\t\t\t+= 32;\r\n\r\n\t\t\taudio_player.firstFrameOffset\t\t\t= audio_player.nextFrameOffset;\r\n\t\t\taudio_player.firstFrameSize\t\t\t\t= audio_player.nextFrameSize;\r\n\r\n//\t\t\tstrncpy( audio_player.fileName, fileName, 64 );\r\n//\t\t\taudio_player.fileName[63]\t\t\t\t= 0;\r\n\r\n\t\t\taudio_player.open \t\t\t \t\t\t= TRUE;\r\n\r\n\t\t\taudio_player.asyncOpenCallbackStatus\t= ASYNC_OPEN_SUCCESS;\r\n\t\t\taudio_player.readIndex \t\t\t\t\t= 0;\r\n\t\t\taudio_player.decodeIndex \t\t\t\t= 0;\r\n\t\t\taudio_player.lastDecodedFrame\t\t\t= 0;\r\n\t\t\taudio_player.error \t\t\t \t\t\t= FALSE;\r\n\t\t\taudio_player.preFetchState \t \t\t\t= FALSE;\r\n\t\t\taudio_player.loopMode\t\t \t\t\t= FALSE;\r\n\t\t\taudio_player.asyncDvdRunning\t\t\t= FALSE;\r\n\t\t\taudio_player.currentFrameCount \t\t\t= 0;\r\n\t\t\taudio_player.readBufferBaseMem\t\t\t= 0;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tASSERT( 0 );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tOpen video file.\r\n *\r\n *\t\tThis functions opens a video file and parses some basic file\r\n *\t\tinformation.\r\n *\r\n * \\param fileName\r\n *\t\tName of file to open\r\n *\r\n * \\return\r\n *\t\tTRUE if file could be opened and is in valid format!\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL AUDSimpleOpen( char* fileName )\r\n{\r\n//\tu32 fileOffset = 0;\r\n//\tu32 headSize;\r\n//\tu32 audioInfoSize;\r\n\t\r\n\tif( audio_player.open )\r\n\t{\r\n#\t\tifdef _DEBUG\r\n\t\tOSReport( \"*** Cannot open '%s' because audio_player already open.\\n\", fileName );\r\n#\t\tendif\r\n\t\treturn FALSE;\r\n\t}\r\n\r\n\t// Initialise the callback status.\r\n\taudio_player.asyncOpenCallbackStatus = 0;\r\n\t\r\n\ts32 entry_num = DVDConvertPathToEntrynum( fileName );\r\n\tif( entry_num == -1 )\r\n\t{\r\n#\t\tifdef _DEBUG\r\n\t\tOSReport( \"*** Cannot find '%s'\\n\", filename );\r\n#\t\tendif\r\n\t\treturn FALSE;\r\n\t}\r\n\tif( DVDFastOpen( entry_num, &audio_player.fileHandle ) == FALSE )\r\n\t{\r\n#\t\tifdef _DEBUG\r\n\t\tOSReport( \"*** Cannot open: '%s'\\n\", fileName );\r\n#\t\tendif\r\n\t\treturn FALSE;\r\n\t}\r\n\t\t\r\n\t// Set callback status to indicate file is now open.\r\n\taudio_player.asyncOpenCallbackStatus = 1;\r\n\t\r\n\t// Read 'VID1' chunk from file and check for correct version.\r\n//\tif( DVDRead( &audio_player.fileHandle, &workChunk, 32, 0 ) < 0 )\r\n\tif( DVDReadAsync( &audio_player.fileHandle, &workChunk, 32, 0, AUDSimpleOpenDVDCallback ) < 0 )\r\n\t{\r\n#\t\tifdef _DEBUG\r\n\t\tOSReport( \"*** Failed to read the header for %s.\\n\", fileName );\r\n#\t\tendif\r\n\t\tDVDClose( &audio_player.fileHandle );\r\n\t\treturn FALSE;\r\n\t}\r\n\r\n\tstrncpy( audio_player.fileName, fileName, 64 );\r\n\taudio_player.fileName[63]\t\t\t\t= 0;\r\n\r\n\t// Nothing more to do here.\r\n\treturn TRUE;\r\n\t\t\r\n//\tfileOffset += 32;\r\n\t\r\n\t// Check file id\t\r\n//\tif( workChunk.id != VID_FCC('V','I','D','1' ))\r\n//\t{\r\n//#\t\tifdef _DEBUG\r\n//\t\tOSReport(\"*** No VID1 file: '%s'\\n\", fileName);\r\n//#\t\tendif\r\n//\t\tDVDClose( &audio_player.fileHandle );\r\n//\t\treturn FALSE;\r\n//\t}\r\n\t\r\n\t// Check for correct version of vid chunk.\r\n\t// If we find this version we assume a 'special' alignment and chunk ordering which may be invalid\r\n\t// in another version of the file format.\r\n//\tif( workChunk.vid.versionMajor != 1 || workChunk.vid.versionMinor != 0 )\r\n//\t{\r\n//#\t\tifdef _DEBUG\r\n//\t\tOSReport(\"*** Unsupported file version: major: %d, minor: %d\\n\", workChunk.vid.versionMajor, workChunk.vid.versionMajor);\r\n//#\t\tendif\r\n//\t\tDVDClose(&audio_player.fileHandle);\r\n//\t\treturn FALSE;\r\n//\t}\r\n\t\r\n//#\tifdef _DEBUG\r\n\t// Sometimes, it's required to check for a special build of the VidConv converter.\r\n//\t{\r\n//\t\tu32 version = VID_VERSION(workChunk.vid.vidConvMajor, workChunk.vid.vidConvMinor, workChunk.vid.vidConvBuild);\r\n//\t\tif(version < VID_VERSION(1,0,1))\r\n//\t\tOSReport(\"*** WARNING: Vid file created using an unsupported converter version: %d.%d.%d\\n\", (u32)workChunk.vid.vidConvMajor, (u32)workChunk.vid.vidConvMinor, (u32)workChunk.vid.vidConvBuild);\r\n//\t}\r\n//#\tendif\r\n\r\n\t// Check types of chunks we have in this file.\r\n\t// !!! Note that we assume start of 'HEAD' chunk at byte offset 32 from file start !!!\r\n//\tif( DVDRead( &audio_player.fileHandle, &workChunk, 32, (s32)fileOffset ) < 0 )\r\n//\t{\r\n//#\t\tifdef _DEBUG\r\n//\t\tOSReport(\"*** Failed to read 'HEAD' chunk.\\n\");\r\n//#\t\tendif\r\n//\t\tDVDClose( &audio_player.fileHandle );\r\n//\t\treturn FALSE;\r\n//\t}\r\n\t\r\n//\tif( workChunk.id != VID_FCC('H','E','A','D' ))\r\n//\t{\r\n//#\t\tifdef _DEBUG\r\n//\t\tOSReport(\"*** No HEAD chunk found at expected offset\\n\");\r\n//#\t\tendif\r\n//\t\tDVDClose(&audio_player.fileHandle);\r\n//\t\treturn FALSE;\r\n//\t}\r\n\t\r\n\t// Calculate the start of the first frame chunk\r\n\t// (we know the header chunk starts at offset 32)\r\n//\taudio_player.nextFrameOffset = workChunk.len + 32;\r\n\r\n\t// Skip 'HEAD' chunk id, len and version fields\r\n//\tfileOffset += VID_CHUNK_HEADER_SIZE;\r\n\t\r\n\t// The header chunk contains one or more header chunks for the different data types contained\r\n\t// in the stream. Parse them all...\r\n//\theadSize = workChunk.len - VID_CHUNK_HEADER_SIZE;\r\n//\twhile( headSize >= 32 )\r\n//\t{\r\n//\t\tif( DVDRead( &audio_player.fileHandle, &workChunk, 32, (s32)fileOffset ) < 0 )\r\n//\t\t{\r\n//#\t\t\tifdef _DEBUG\r\n//\t\t\tOSReport(\"*** Error reading file at offset %d\\n\", fileOffset);\r\n//#\t\t\tendif\r\n//\t\t\tDVDClose(&audio_player.fileHandle);\r\n//\t\t\treturn FALSE;\r\n//\t\t}\r\n\t\t\r\n//\t\tfileOffset += 32;\r\n//\t\theadSize -= 32;\r\n\r\n\t\t// We analyze the 1st 32 bytes of the chunk for a known header format\r\n//\t\tif(workChunk.id == VID_FCC('A','U','D','H'))\r\n//\t\t{\r\n\t\t\t// Allocate memory for audio header chunk\r\n//\t\t\taudio_player.audioHeaderChunk = (u8*)((*audio_player.cbAlloc)(workChunk.len));\r\n//\t\t\taudioInfoSize = workChunk.len - VID_CHUNK_HEADER_SIZE;\r\n\t\t\t\r\n\t\t\t// Copy the already loaded part\r\n//\t\t\tmemcpy(audio_player.audioHeaderChunk, &workChunk, 32);\r\n//\t\t\tworkChunk.len -= 32;\r\n\t\t\t\r\n\t\t\t// Read additional audio header bytes if the audio header is greater that 32 bytes\r\n//\t\t\tif(workChunk.len >= 32)\r\n//\t\t\t{\r\n//\t\t\t\tASSERT((workChunk.len&31)==0);\r\n//\t\t\t\tif( DVDRead( &audio_player.fileHandle, audio_player.audioHeaderChunk + 32, workChunk.len, (s32)fileOffset ) < 0 )\r\n//\t\t\t\t{\r\n//#\t\t\t\t\tifdef _DEBUG\r\n//\t\t\t\t\tOSReport(\"*** Error reading file at offset %d\\n\", fileOffset);\r\n//#\t\t\t\t\tendif\r\n//\t\t\t\t\tDVDClose(&audio_player.fileHandle);\r\n//\t\t\t\t\treturn FALSE;\r\n//\t\t\t\t}\r\n//\t\t\t\tfileOffset += workChunk.len;\r\n//\t\t\t\theadSize -= workChunk.len;\r\n//\t\t\t}\r\n\r\n\t\t\t// Setup and calc the number of bytes which we are allowed to copy into the audioInfo struct\r\n//\t\t\tmemcpy(&audio_player.audioInfo, audio_player.audioHeaderChunk+VID_CHUNK_HEADER_SIZE, MIN(audioInfoSize, sizeof(audio_player.audioInfo)));\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\t// Skip unknown chunks. We already read 32 bytes for the header which we must subtract here.\r\n//\t\t\tfileOffset += workChunk.len - 32;\r\n///\t\t\theadSize -= workChunk.len - 32;\r\n//\t\t}\r\n//\t}\r\n\t\r\n\t// check if we have the correct vaud file version (>0)\r\n//\tif(audio_player.audioInfo.vaudex.version == 0)\r\n//\t{\r\n//#\t\tifdef _DEBUG\r\n//\t\tOSReport(\"*** Invalid version in vaud file.\");\r\n//#\t\tendif\r\n//\t\tDVDClose(&audio_player.fileHandle);\r\n//\t\treturn FALSE;\r\n//\t}\r\n\r\n\t// we can only play audio files which have the following fiels set.\r\n\t// Note that in case of VIDEO files this fields are allowed to be 0.\r\n//\tASSERT(audio_player.audioInfo.vaudex.maxBufferSize > 0);\r\n//\tASSERT(audio_player.audioInfo.vaudex.frameCount > 0);\r\n//\tASSERT(audio_player.audioInfo.vaudex.frameTimeMs > 0);\r\n\t\r\n\t// read beginning of 1st frame chunk to get required size information\r\n//\tif( DVDRead( &audio_player.fileHandle, &workChunk, 32 , (s32)audio_player.nextFrameOffset ) < 0 )\r\n//\t{\r\n//#\t\tifdef _DEBUG\r\n//\t\tOSReport(\"*** Failed to read 'FRAM' chunk.\\n\");\r\n//#\t\tendif\r\n//\t\tDVDClose(&audio_player.fileHandle);\r\n//\t\treturn FALSE;\r\n//\t}\r\n\r\n//\tif( workChunk.id != VID_FCC('F','R','A','M') )\r\n//\t{\r\n//#\t\tifdef _DEBUG\r\n//\t\tOSReport(\"*** No FRAM chunk found.\");\r\n//#\t\tendif\r\n//\t\tDVDClose(&audio_player.fileHandle);\r\n//\t\treturn FALSE;\r\n//\t}\r\n\r\n//\taudio_player.nextFrameSize = workChunk.len; \t\t// 32 bytes of this chunk are already consumed, but we want to 'preload' the NEXT chunk's FRAM header\r\n//\taudio_player.nextFrameOffset += 32;\r\n\t\r\n//\taudio_player.firstFrameOffset = audio_player.nextFrameOffset;\r\n//\taudio_player.firstFrameSize   = audio_player.nextFrameSize;\r\n\r\n//\tstrncpy(audio_player.fileName, fileName, 64);\r\n//\taudio_player.fileName[63] = 0;\r\n\t\r\n//\taudio_player.open \t\t\t \t= TRUE;\r\n\r\n//\taudio_player.readIndex \t\t\t= 0;\r\n//\taudio_player.decodeIndex \t\t\t= 0;\r\n//\taudio_player.lastDecodedFrame\t\t= 0;\r\n//\taudio_player.error \t\t\t \t= FALSE;\r\n//\taudio_player.preFetchState \t \t= FALSE;\r\n//\taudio_player.loopMode\t\t\t \t= FALSE;\r\n//\taudio_player.asyncDvdRunning\t\t= FALSE;\r\n//\taudio_player.currentFrameCount \t= 0;\r\n//\taudio_player.readBufferBaseMem\t= 0;\r\n\r\n//\treturn TRUE;\r\n} \t\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tClose open video file\r\n *\r\n * \\return\r\n *\t\tTRUE if file is closed sucessfully.\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL AUDSimpleClose(void)\r\n\t{\r\n\tif (audio_player.open)\r\n\t\t{\r\n\t\tif (audio_player.preFetchState == FALSE)\r\n\t\t\t{\r\n\t\t\tif (!audio_player.asyncDvdRunning)\r\n\t\t\t\t{\r\n\t\t\t\taudio_player.open = FALSE;\r\n\t\t\t\tDVDClose(&audio_player.fileHandle);\r\n\t\t\t\tif(audio_player.audioHeaderChunk != NULL)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t(*audio_player.cbFree)(audio_player.audioHeaderChunk);\r\n\t\t\t\t\taudio_player.audioHeaderChunk = NULL;\r\n\t\t\t\t\t}\r\n\t\t\t\treturn TRUE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\treturn FALSE;\r\n\t}\r\n\r\n\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tDecode all frame data\r\n *\r\n *\t\tThis function operates on the full frame input data. It forwards this\r\n *\t\tdata to the required decoder.\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL AUDSimpleDecode(void)\r\n{\r\n\tBOOL enabled;\r\n\tu8* chunkStart;\r\n\tu32 chunkSize;\r\n\tu32 frameSize;\r\n\r\n\tif( audio_player.readBuffer[audio_player.decodeIndex].valid )\r\n\t{\r\n\t\t\r\n\t\t// ptr to our (pre-) loaded data INSIDE (!) 'FRAM' chunk\r\n\t\t// (in other words, the 'FRAM' chunk itself is not visible here)\r\n\t\tchunkStart = audio_player.readBuffer[audio_player.decodeIndex].ptr;\r\n\r\n\t\t// usually, we read additional 32 bytes for getting info about the NEXT chunk.\r\n\t\t// We only deal with the actual 'FRAM' chunk data here and adjust the size by 32 bytes.\r\n        frameSize = audio_player.readBuffer[audio_player.decodeIndex].size - 32;\r\n\t\t\r\n\t\t// loop across ALL chunks inside 'FRAM'\r\n\t\twhile(frameSize >= 32)\r\n\t\t{\r\n\t\t\tchunkSize = VID_CHUNK_LEN(chunkStart);\r\n\t\t\t\r\n\t\t\tif( VID_CHUNK_ID(chunkStart) == VID_FCC('A','U','D','D') )\r\n\t\t\t{\r\n\t\t\t\t// Get the data to the audio system...\r\n\t\t\t\tif(! AUDSimpleAudioDecode(chunkStart + VID_CHUNK_HEADER_SIZE, chunkSize - VID_CHUNK_HEADER_SIZE))\r\n\t\t\t\t{\r\n#ifdef _DEBUG\r\n\t\t\t\t\tOSReport(\"*** AUDSimpleAudioDecode failed!\\n\");\r\n#endif\r\n\t\t\t\t}\r\n\t\t\t}\r\n#ifdef _DEBUG\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tOSReport(\"*** AUDSimpleDecode: unknown chunk type!\\n\");\r\n\t\t\t}\r\n#endif\r\n\t\t\t\r\n\t\t\t// goto next chunk\r\n\t\t\tchunkStart += chunkSize;\r\n\t\t\tframeSize -= chunkSize;\r\n\t\t}\r\n\t\t\t\r\n\t\taudio_player.lastDecodedFrame = audio_player.readBuffer[audio_player.decodeIndex].frameNumber;\r\n\t\taudio_player.readBuffer[audio_player.decodeIndex].valid = FALSE;\r\n\t\taudio_player.decodeIndex = (audio_player.decodeIndex + 1) % AUD_NUM_READ_BUFFERS;\r\n\r\n\t\t// check if loading is still running\r\n\t\tenabled = OSDisableInterrupts();\r\n\t\tif (!audio_player.readBuffer[audio_player.readIndex].valid && !audio_player.asyncDvdRunning)\r\n\t\t\tReadFrameAsync();\r\n\t\tOSRestoreInterrupts(enabled);\r\n\t\t\r\n        return TRUE;\r\n\t}\r\n\r\n#ifdef _DEBUG\r\n\tOSReport(\"*** AUDSimpleDecode: No valid decode buffer found (?).\\n\");\r\n#endif\r\n\treturn FALSE;\r\n\r\n}\r\n\r\n\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tChange active play mask\r\n *\r\n ******************************************************************************\r\n */\r\nvoid AUDSimplePlayMaskChange(void)\r\n\t{\r\n\tstatic u32 myPlayMask = 0x3;\r\n\tu32 maxChannels = audio_player.audioInfo.vaud.numChannels;\r\n\tASSERT(maxChannels > 0 && maxChannels <= 32);\r\n\r\n\tmyPlayMask <<= 1;\r\n\tif(myPlayMask >= ((u32)(1<<maxChannels)))\r\n\t   myPlayMask |= 1;\r\n\r\n\tmyPlayMask &= (1<<maxChannels)-1;\r\n\r\n\tAUDSimpleAudioChangePlayback(&myPlayMask, 1);\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tGet audio sample rate in Hz.\r\n *\r\n ******************************************************************************\r\n */\r\nu32 AUDSimpleGetAudioSampleRate(void)\r\n\t{\r\n\treturn(audio_player.audioInfo.vaud.frq);\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tReturn time in ms of one audio frame\r\n *\r\n ******************************************************************************\r\n */\r\nextern u32 AUDSimpleGetFrameTime(void)\r\n\t{\r\n\treturn(audio_player.audioInfo.vaudex.frameTimeMs);\r\n\t}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tCheck for drive status\r\n *\r\n ******************************************************************************\r\n */\r\nBOOL AUDSimpleCheckDVDError(void)\r\n\t{\r\n\tswitch (DVDGetDriveStatus())\r\n\t\t{\r\n\t\tcase DVD_STATE_FATAL_ERROR:\r\n\t\t\t{\r\n\t\t\tOSReport(\"DVDGetDriveStatus()=DVD_STATE_FATAL_ERROR\\n\");\r\n\t\t\tbreak;\r\n\t\t\t}\r\n\t\tcase DVD_STATE_NO_DISK:\r\n\t\t\t{\r\n\t\t\tOSReport(\"DVDGetDriveStatus()=DVD_STATE_NO_DISK\\n\");\r\n\t\t\tbreak;\r\n\t\t\t}\r\n\t\tcase DVD_STATE_COVER_OPEN:\r\n\t\t\t{\r\n\t\t\tOSReport(\"DVDGetDriveStatus()=DVD_STATE_COVER_OPEN\\n\");\r\n\t\t\tbreak;\r\n\t\t\t}\r\n\t\tcase DVD_STATE_WRONG_DISK:\r\n\t\t\t{\r\n\t\t\tOSReport(\"DVDGetDriveStatus()=DVD_STATE_WRONG_DISK\\n\");\r\n\t\t\tbreak;\r\n\t\t\t}\r\n\t\tcase DVD_STATE_RETRY:\r\n\t\t\t{\r\n\t\t\tOSReport(\"DVDGetDriveStatus()=DVD_STATE_RETRY\\n\");\r\n\t\t\tbreak;\r\n\t\t\t}\r\n\t\tdefault:\r\n\t\t\treturn(TRUE);\r\n\t\t}\r\n\t\r\n\treturn(FALSE);\r\n\t}\r\n#endif\t\t// DVDETH\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/divx/AUDSimplePlayer.h",
    "content": "/*!\r\n ******************************************************************************\r\n * \\file AUDSimplePlayer.h\r\n *\r\n * \\brief\r\n *\t\tHeader file for AUDSimplePlayer interface\r\n *\r\n * \\date\r\n *\t\t5/21/03\r\n *\r\n * \\version\r\n *\t\t1.0\r\n *\r\n * \\author\r\n *\t\tAchim Moller\r\n *\r\n ******************************************************************************\r\n */\r\n#ifndef __AUDSIMPLE_PLAYER_H__\r\n#define __AUDSIMPLE_PLAYER_H__\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\n/******************************************************************************\r\n *  INCLUDES\r\n ******************************************************************************/\r\n#include <dolphin/types.h>\r\n#include <demo.h>\r\n#include \"vaud.h\"\r\n\r\n/******************************************************************************\r\n *  DEFINES\r\n ******************************************************************************/\r\n\r\n//! Number of 'read-ahead' buffers\r\n#define AUD_NUM_READ_BUFFERS\t10\r\n#define\tASYNC_OPEN_FAIL\t\t\t666\r\n#define\tASYNC_OPEN_SUCCESS\t\t999\r\n\r\n/******************************************************************************\r\n *  STRUCTS AND TYPES\r\n ******************************************************************************/\r\n\r\ntypedef struct {\r\n\tu8*\t\t\t\tptr;\r\n\tu32\t\t\t\tsize;\r\n\tu32\t\t\t\tframeNumber;\r\n\tvolatile BOOL \tvalid;\r\n} AudReadBuffer;\r\n\r\n//! Required fields for simple demonstation player\r\ntypedef struct {\r\n\r\n\tVAUDAllocator \tcbAlloc;\t\t\t// memory allocator\r\n\tVAUDDeallocator cbFree;\t\t\t\t// memory deallocator\r\n\r\n    DVDFileInfo\t\tfileHandle;\r\n\tchar\t\t\tfileName[64];\r\n\r\n\tVidAUDH\t\t\taudioInfo;\t\t\t// common header and first 2 channels (or all channels if not ADPCM)\r\n    u8*\t\t\t\taudioHeaderChunk;\r\n\t\r\n\tBOOL            open;\r\n\tBOOL            error;\r\n\tBOOL\t\t\tpreFetchState;\r\n\tBOOL\t\t\tloopMode;\r\n\tBOOL\t\t\tasyncDvdRunning;\r\n\tu32\t\t\t\tasyncOpenCallbackStatus;\t// Value indicating status of callback position for async startup\r\n\r\n\tBOOL\t\t\tdecodeComplete;\r\n\tBOOL\t\t\tplaybackComplete;\r\n\t\r\n\tu32\t\t\t\tnextFrameOffset;\r\n\tu32\t\t\t\tnextFrameSize;\r\n\tu32\t\t\t\tcurrentFrameCount;\r\n\tu32 \t\t\tlastDecodedFrame;\r\n\t\r\n\tu32 \t\t\tfirstFrameOffset;\r\n\tu32\t\t\t\tfirstFrameSize;\r\n\t\r\n\tu32             readIndex;\r\n\tu32\t\t\t\tdecodeIndex;\r\n\t\r\n\tAudReadBuffer\treadBuffer[AUD_NUM_READ_BUFFERS];\r\n\tu8*\t\t\t\treadBufferBaseMem;\r\n\t\r\n\tVAUDDecoder\t\tdecoder;\r\n\r\n} AudSimplePlayer;\r\n\r\n/******************************************************************************\r\n *  PROTOTYPES\r\n ******************************************************************************/\r\nextern void AUDSimpleInit(VAUDAllocator cbAlloc, VAUDDeallocator cbFree);\r\n\r\nextern BOOL AUDSimpleAllocDVDBuffers(void);\r\nextern void AUDSimpleFreeDVDBuffers(void);\r\n\r\nextern BOOL AUDSimpleCreateDecoder(void);\r\nextern void AUDSimpleDestroyDecoder(void);\r\n\r\nextern BOOL AUDSimpleLoadStart(BOOL loop);\r\nextern BOOL AUDSimpleLoadStop(void);\r\n\r\nextern BOOL AUDSimpleOpen(char* fileName);\r\nextern BOOL AUDSimpleClose(void);\r\n\r\nextern BOOL AUDSimpleDecode(void);\r\nextern u32  AUDSimpleGetAudioSampleRate(void);\r\nextern u32  AUDSimpleGetFrameTime(void);\r\n\r\nextern void AUDSimplePlayMaskChange(void);\r\n\r\nextern BOOL AUDSimpleCheckDVDError(void);\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n#endif\t// __AUDSIMPLE_PLAYER_H__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/p_music.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2001 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMusic (Pcm)\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tngc/p_music.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t08/23/01\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNGC audio streaming\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef DVDETH\r\n#define USE_VORBIS\r\n#endif\t\t// DVDETH\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <dolphin.h>\r\n#include <core/macros.h>\r\n#include <core/defines.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/ngc/hed.h>\r\n#include <gel/music/ngc/pcm/pcm.h>\r\n#include <sys\\timer.h>\r\n\r\n#ifdef USE_VORBIS\r\n#include <gel/music/ngc/divx/AUDSimpleAudio.h>\r\n#include <gel/music/ngc/divx/AUDSimplePlayer.h>\r\n#endif\r\n\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/scripting/symboltype.h> \r\n//#include <dolphin\\dtk.h>\r\n#include \"p_music.h\"\r\n#include <sys/ngc/p_dvd.h>\r\n#include \"gfx\\ngc\\nx\\nx_init.h\"\r\n#include <charpipeline/GQRSetup.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef USE_VORBIS\r\n// Player instance\r\nextern AudSimplePlayer audio_player;\r\n#endif\r\n\r\n//bool g_using_dtk = false;\r\n//extern bool g_in_cutscene;\r\n\r\n// Info about last 8 reads.\r\nstatic DVDFileInfo* last_fileInfo[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };\r\nstatic void * last_addr[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; \r\nstatic s32 last_length[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };\r\nstatic s32 last_offset[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };\r\n\r\n// Callback will happen 8 frames later.\r\nDVDCallback last_callback[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };  \r\ns32 last_callback_length[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; \r\nDVDFileInfo* last_callback_fileInfo[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };\r\nint last_callback_counter[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; \r\n\r\nnamespace Pcm\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define MAX_DTK_VOL\t\t\t\t0xFF\t\t\t\t// Max volume for DTK hardware streamed audio tracks.\r\n#define MAX_VOL\t\t\t\t\t0x7FFF\r\n#define NORMAL_VOL\t\t\t\t( MAX_VOL >> 1 )\r\n#define UNALTERED_PITCH\t\t\t0x10000L\r\n\r\n#define\tQUIT_DMA_INACTIVE\t\t\t0\r\n#define\tQUIT_DMA_PENDING\t\t\t1\r\n#define\tQUIT_DMA_COMPLETE\t\t\t2\r\n\r\n#define STREAM_BUFFER_HEADER_SIZE\t96\t\t\t\t// Size of the header for each stream\r\n#define STREAM_BUFFER_SIZE\t\t\t16384\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstruct FileStreamInfo\r\n{\r\n\tint\t\t\t\tfileSize;\r\n\tint\t\t\t\toffset;\r\n\tint\t\t\t\thedOffset;\r\n\tint\t\t\t\toffsetInARAM;\r\n\tfloat\t\t\tpitch;\r\n\tfloat\t\t\tpitchAdjustmentForSamplingRate;\r\n\tfloat\t\t\tvolumeL;\r\n\tfloat\t\t\tvolumeR;\r\n\tbool\t\t\tpaused;\r\n\tbool\t\t\thasStartedPlaying;\r\n\tunsigned int\tcurrentFileInfo;\r\n\tDVDFileInfo\t\tfileInfo[8];\r\n\tAXVPB*\t\t\tp_voice;\r\n\tuint32\t\t\tnextWrite;\t\t// 0 for first half of ARAM buffer, 1 for second half of ARAM buffer.\r\n\tbool\t\t\thas_paused;\r\n\tbool\t\t\tpreloadActive;\r\n};\r\n\r\n// This is also defined in p_sfx.cpp - should probably share a common definition.\r\nstruct sDSPADPCM\r\n{\r\n\t// for WAV header generation during decode\r\n\tu32 num_samples;\t\t// total number of RAW samples\r\n\tu32 num_adpcm_nibbles;\t// number of ADPCM nibbles (including frame headers)\r\n\tu32 sample_rate;\t\t// Sample rate, in Hz\r\n\r\n\t// DSP addressing and decode context\r\n\tu16 loop_flag; // 1=LOOPED, 0=NOT LOOPED\r\n\tu16 format; // Always 0x0000, for ADPCM\r\n\tu32 sa; // Start offset address for looped samples (zero for non-looped)\r\n\tu32 ea; // End offset address for looped samples\r\n\tu32 ca; // always zero\r\n\tu16 coef[16]; // decode coefficients (eight pairs of 16-bit words)\r\n\r\n\t// DSP decoder initial state\r\n\tu16 gain; // always zero for ADPCM\r\n\tu16 ps; // predictor/scale\r\n\tu16 yn1; // sample history\r\n\tu16 yn2; // sample history\r\n\r\n\t// DSP decoder loop context\r\n\tu16 lps; // predictor/scale for loop context\r\n\tu16 lyn1; // sample history (n-1) for loop context\r\n\tu16 lyn2; // sample history (n-2) for loop context\r\n\tu16 pad[10]; // reserved\r\n};\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#ifndef USE_VORBIS\r\n//#ifndef DVDETH\r\n//static DTKTrack\ts_dtk_track;\r\n//#endif\t\t// DVDETH\r\n//#endif\t\t// USE_VORBIS\r\n\r\nFileStreamInfo\t\tgStreamInfo[NUM_STREAMS];\r\nint\t\t\t\t\tgPcmStatus\t\t\t\t\t= 0;\r\nunsigned int\t\tgStreamVolume\t\t\t\t= 100;\r\nFile::SHed*\t\t\tgpStreamHed\t\t\t\t\t= NULL;\r\nint\t\t\t\t\tstream_base[3];\r\nint\t\t\t\t\tstream_size[3];\r\nstatic char\t\t\tstream_0_mem[STREAM_BUFFER_SIZE + STREAM_BUFFER_HEADER_SIZE] __attribute__((aligned( 32 )));\t// Must be 32 for DVD.\r\nstatic char\t\t\tstream_1_mem[STREAM_BUFFER_SIZE + STREAM_BUFFER_HEADER_SIZE] __attribute__((aligned( 32 )));\t// Must be 32 for DVD.\r\nstatic char\t\t\tstream_2_mem[STREAM_BUFFER_SIZE + STREAM_BUFFER_HEADER_SIZE] __attribute__((aligned( 32 )));\t// Must be 32 for DVD.\r\nstatic char*\t\tstream_mem_buffer[3]\t\t= { stream_0_mem, stream_1_mem, stream_2_mem };\r\nstatic ARQRequest\tstream_arq_request[NUM_STREAMS];\r\nbool\t\t\t\tmusicPaused\t\t\t\t\t= false;\r\nfloat\t\t\t\tmusicVolume\t\t\t\t\t= 0.0f;\r\nbool\t\t\t\tmusicPreloadActive\t\t\t= false;\r\nbool\t\t\t\tstreamsPaused\t\t\t\t= false;\r\n\r\nstatic uint32\t\tsPreLoadChecksum[NUM_STREAMS];\r\nstatic uint32\t\tsPreLoadMusicChecksum;\r\nstatic char\t\t\tsPreLoadMusicFilename[256];\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nBOOL _DVDReadAsync( DVDFileInfo* fileInfo, void* addr, s32 length, s32 offset, DVDCallback callback )\r\n{\r\n\t// See if this is a repeat read.\r\n\tbool repeat_read = false;\r\n\tfor ( int lp = 0; lp < 8; lp++ )\r\n\t{\r\n\t\tif ( ( fileInfo == last_fileInfo[lp] ) &&\r\n\t\t\t ( addr == last_addr[lp] ) &&\r\n\t\t\t ( length == last_length[lp] ) &&\r\n\t\t\t ( offset == last_offset[lp] ) )\r\n\t\t{\r\n\t\t\trepeat_read = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( repeat_read )\r\n\t{\r\n\t\t// Find an empty slot for this callback.\r\n\t\tint cb = -1;\r\n\t\tfor ( int lp = 0; lp < 8; lp++ )\r\n\t\t{\r\n\t\t\tif ( last_callback_counter[lp] == -1 )\r\n\t\t\t{\r\n\t\t\t\tcb = lp;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( cb == -1 )\r\n\t\t{\r\n#\t\t\tifdef __NOPT_FINAL__\r\n\t\t\tOSReport( \"Warning: Overflowed DVD callback buffer\\n\" );\r\n#\t\t\telse\r\n\t\t\tDbg_MsgAssert( 0, ( \"Overflowed DVD callback buffer\" ));\r\n#\t\t\tendif\r\n\t\t\t// Issue read normally in this case.\r\n\t\t\tDVDReadAsync( fileInfo, addr, length, offset, callback ); \r\n\t\t}\r\n\t\tlast_callback[cb] = callback;\r\n\t\tlast_callback_length[cb] = length;\r\n\t\tlast_callback_fileInfo[cb] = fileInfo;\r\n\t\tlast_callback_counter[cb] = 8;\r\n\t\t\r\n\t\treturn TRUE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Shunt last reads down & fill in new one.\r\n\t\tfor ( int lp = 7; lp > 0; lp-- )\r\n\t\t{\r\n\t\t\tlast_fileInfo[lp] = last_fileInfo[lp-1];\r\n\t\t\tlast_addr[lp] = last_addr[lp-1];\r\n\t\t\tlast_length[lp] = last_length[lp-1];\r\n\t\t\tlast_offset[lp] = last_offset[lp-1];\r\n\t\t}\r\n\t\tlast_fileInfo[0] = fileInfo;\r\n\t\tlast_addr[0] = addr;\r\n\t\tlast_length[0] = length;\r\n\t\tlast_offset[0] = offset;\r\n\r\n\t\treturn DVDReadAsync( fileInfo, addr, length, offset, callback );\r\n\t}\r\n}\r\n\r\nvoid setDolby( AXPB * p_pb, AXVPB * p_vpb, float volL, float volR, unsigned int pitch, bool set_pitch, float volume_percent )\r\n{\r\n\tfloat\tvolumes[4];\r\n\tint\t\ti_volumes[4];\t//, max_i_volume;\r\n\tvolumes[0] = 0.0f;\r\n\tvolumes[1] = 0.0f;\r\n\tvolumes[2] = 0.0f;\r\n\tvolumes[3] = 0.0f;\r\n\t\r\n\tif( Sfx::isStereo )\r\n\t{\r\n\t\tif(( volL == 0.0f ) && ( volR == 0.0f ))\r\n\t\t{\r\n\t\t\t// Dave note - in theory setting the mixerCtrl to zero should cause the sound not to play.\r\n\t\t\t// In practice however it seems to lead to small audio 'pops'.\r\n//\t\t\tp_pb->mixerCtrl = 0;\r\n//\t\t\tp_vpb->sync |= AX_SYNC_USER_MIXCTRL;\r\n\t\t\t\r\n\t\t\t// Pointless doing any more work.\r\n\t\t\tp_pb->mix.vL\t= 0;\r\n\t\t\tp_pb->mix.vR\t= 0;\r\n\t\t\tp_pb->mixerCtrl = AX_PB_MIXCTRL_L | AX_PB_MIXCTRL_R;\r\n\t\t\tp_vpb->sync\t   |= AX_SYNC_USER_MIX | AX_SYNC_USER_MIXCTRL;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Get the length of the vector here which will be used to multiply out the normalised speaker volumes.\r\n\t\t\tMth::Vector test( fabsf( volL ), fabsf( volR ), 0.0f, 0.0f );\r\n\t\t\tfloat amplitude = test.Length();\r\n\r\n\t\t\t// Look just at the normalized right component to figure the sound angle from Matt's calculations.\r\n\t\t\ttest.Normalize();\r\n\r\n\t\t\tfloat angle;\r\n\t\t\tangle\t= asinf( test[Y] );\r\n\t\t\tangle\t= ( angle * 2.0f ) - ( Mth::PI * 0.5f );\r\n\t\t\tangle\t= ( volL < 0.0f ) ? ( Mth::PI - angle ) : angle;\r\n\r\n\t\t\t// Now figure volumes based on speaker coverage.\r\n\t\t\tangle\t= Mth::RadToDeg( angle );\r\n\r\n\t\t\t// Left front channel.\r\n\t\t\tif(( angle >= 225.0f ) || ( angle <= 45.0f ))\r\n\t\t\t{\r\n\t\t\t\t// Because of the discontinuity, shift this angle round to the [0,180] range.\r\n\t\t\t\tfloat shift_angle = angle + 135;\r\n\t\t\t\tshift_angle = ( shift_angle >= 360.0f ) ? ( shift_angle - 360.0f ) : shift_angle;\r\n\t\t\t\tvolumes[0]\t= ( shift_angle / 180.0f ) * Mth::PI;\r\n\t\t\t\tvolumes[0]\t= sqrtf( sinf( volumes[0] ));\r\n\t\t\t}\r\n\r\n//\t\t\t// Center channel.\r\n//\t\t\tif(( angle >= -60.0f ) && ( angle <= 60.0f ))\r\n//\t\t\t{\r\n//\t\t\t\t// Scale this into [0,PI] space so we can get smooth fadeout.\r\n//\t\t\t\tvolumes[1]\t= (( angle + 60.0f ) / 120.0f ) * Mth::PI;\r\n//\t\t\t\tvolumes[1]\t= sqrtf( sinf( volumes[1] ));\r\n//\t\t\t}\r\n\r\n\t\t\t// Right front channel.\r\n\t\t\tif(( angle >= -45.0f ) && ( angle <= 135.0f ))\r\n\t\t\t{\r\n\t\t\t\t// Scale this into [0,PI] space so we can get smooth fadeout.\r\n\t\t\t\tvolumes[1]\t= (( angle + 45.0f ) / 180.0f ) * Mth::PI;\r\n\t\t\t\tvolumes[1]\t= sqrtf( sinf( volumes[1] ));\r\n\t\t\t}\r\n\r\n\t\t\t// Right rear channel.\r\n\t\t\tif(( angle >= 45.0f ) && ( angle <= 225.0f ))\r\n\t\t\t{\r\n\t\t\t\t// Scale this into [0,PI] space so we can get smooth fadeout.\r\n\t\t\t\tvolumes[2]\t= (( angle - 45.0f ) / 180.0f ) * Mth::PI;\r\n\t\t\t\tvolumes[2]\t= sqrtf( sinf( volumes[2] ));\r\n\t\t\t}\r\n\r\n\t\t\t// Left rear channel.\r\n\t\t\tif(( angle >= 135.0f ) || ( angle <= -45.0f ))\r\n\t\t\t{\r\n\t\t\t\t// Because of the discontinuity, shift this angle round to the [0,180] range.\r\n\t\t\t\tfloat shift_angle = angle + 225;\r\n\t\t\t\tshift_angle = ( shift_angle >= 360.0f ) ? ( shift_angle - 360.0f ) : shift_angle;\r\n\t\t\t\tvolumes[3]\t= ( shift_angle / 180.0f ) * Mth::PI;\r\n\t\t\t\tvolumes[3]\t= sqrtf( sinf( volumes[3] ));\r\n\t\t\t}\r\n\r\n\t\t\t// Now readjust the relative values...\r\n\t\t\tfor( int v = 0; v < 4; ++v )\r\n\t\t\t{\r\n\t\t\t\t// Scale back up to original amplitude.\r\n\t\t\t\tvolumes[v] *= amplitude;\r\n\r\n\t\t\t\t// Then adjust for SFX volume level, and scale into limits.\r\n//\t\t\t\tvolumes[v] = PERCENT( volume_percent, volumes[v] );\r\n//\t\t\t\tvolumes[v] = fabsf( PERCENT( sfx_manager->GetMainVolume(), volumes[v] ));\r\n\r\n\t\t\t\tif( volumes[v] > 100.0f )\r\n\t\t\t\t\tvolumes[v] = 100.0f;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Now figure the attenuation of the sound. To convert to a decibel value, figure the ratio of requested\r\n\t\t\t// volume versus max volume, then calculate the log10 and multiply by (10 * 2). (The 2 is because sound\r\n\t\t\t// power varies as square of pressure, and squaring doubles the log value).\r\n//#define DSBVOLUME_EFFECTIVE_MIN -6400\r\n//#define DSBVOLUME_MAX 0\r\n//\t\t\tmax_i_volume = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\tfor( int v = 0; v < 4; ++v )\r\n\t\t\t{\r\n//\t\t\t\tif( volumes[v] > 0.0f )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tfloat attenuation\t= 20.0f * log10f( volumes[v] * 0.01f );\r\n//\t\t\t\t\ti_volumes[v]\t\t= DSBVOLUME_MAX + (int)( attenuation * 100.0f );\r\n//\t\t\t\t\tif( i_volumes[v] < DSBVOLUME_EFFECTIVE_MIN )\r\n//\t\t\t\t\t\ti_volumes[v] = DSBVOLUME_EFFECTIVE_MIN;\r\n//\r\n//\t\t\t\t\tif( i_volumes[v] > max_i_volume )\r\n//\t\t\t\t\t\tmax_i_volume = i_volumes[v];\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\ti_volumes[v] = DSBVOLUME_EFFECTIVE_MIN;\r\n//\t\t\t\t}\r\n\t\t\t\t// GameCube:: Change from -6400 -> 0 to 0 -> 0x1fff.\r\n//\t\t\t\ti_volumes[v] = ( ( i_volumes[v] + -DSBVOLUME_EFFECTIVE_MIN ) * 0x1fff ) / -DSBVOLUME_EFFECTIVE_MIN;\r\n//\t\t\t\ti_volumes[v] = (int)PERCENT( volume_percent, (float)i_volumes[v] );\r\n\t\t\t\ti_volumes[v] = (int)(( volumes[v] * (float)0x3fff ) / 100.0f);\r\n\t\t\t\ti_volumes[v] = (int)PERCENT( volume_percent, (float)i_volumes[v] );\r\n\t\t\t}\r\n\r\n\t\t\t// Set individual mixbins for panning. Clampo very low volumes to zero, and for zero volumes, early out\r\n\t\t\t// without setting the Dolby stuff up.\r\n\t\t\tif(( i_volumes[0] <= 32 ) && ( i_volumes[1] <= 32 ) && ( i_volumes[2] <= 32 ) && ( i_volumes[3] <= 32 ))\r\n\t\t\t{\r\n\t\t\t\t// Pointless doing any more work.\r\n\t\t\t\tp_pb->mix.vL\t= 0;\r\n\t\t\t\tp_pb->mix.vR\t= 0;\r\n\t\t\t\tp_pb->mixerCtrl = AX_PB_MIXCTRL_L | AX_PB_MIXCTRL_R;\r\n\t\t\t\tp_vpb->sync\t   |= AX_SYNC_USER_MIX | AX_SYNC_USER_MIXCTRL;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_pb->mixerCtrl = AX_PB_MIXCTRL_B_DPL2;\r\n\t\t\t\r\n\t\t\t\tif( i_volumes[0] > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_pb->mix.vL = i_volumes[0];\r\n\t\t\t\t\tp_pb->mixerCtrl |= AX_PB_MIXCTRL_L;\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tif( i_volumes[1] > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_pb->mix.vR = i_volumes[1];\r\n\t\t\t\t\tp_pb->mixerCtrl |= AX_PB_MIXCTRL_R;\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tif( i_volumes[2] > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_pb->mix.vAuxBL = i_volumes[2];\r\n\t\t\t\t\tp_pb->mixerCtrl |= AX_PB_MIXCTRL_B_L;\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tif( i_volumes[3] > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_pb->mix.vAuxBR = i_volumes[3];\r\n\t\t\t\t\tp_pb->mixerCtrl |= AX_PB_MIXCTRL_B_R;\r\n\t\t\t\t}\r\n\t\t\t\tp_vpb->sync |= AX_SYNC_USER_MIX | AX_SYNC_USER_MIXCTRL;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Adjust for SFX volume level.\r\n\t\tvolL = PERCENT( volume_percent, volL );\r\n\t\tvolR = PERCENT( volume_percent, volR );\r\n\r\n\t\t// Adjust for channel volume.\r\n\t\tint lVol = (int)PERCENT( 0x3fff, volL );\t\r\n\t\tint rVol = (int)PERCENT( 0x3fff, volR );\r\n\r\n\t\t// Clamp to maximum allowed volume.\r\n\t\tif ( lVol > 0x7fff )\r\n\t\t\tlVol = 0x7fff;\r\n\t\telse if ( lVol < 0 )\r\n\t\t\tlVol = 0;\r\n\r\n\t\tif ( rVol > 0x7fff )\r\n\t\t\trVol = 0x7fff;\r\n\t\telse if ( rVol < 0 )\r\n\t\t\trVol = 0;\r\n\r\n\t\tp_pb->mix.vL\t= ( lVol + rVol ) / 2;\r\n\t\tp_pb->mix.vR\t= ( lVol + rVol ) / 2;\r\n\t\tp_pb->mixerCtrl = AX_PB_MIXCTRL_L | AX_PB_MIXCTRL_R;\r\n\t\tp_vpb->sync\t   |= AX_SYNC_USER_MIX | AX_SYNC_USER_MIXCTRL;\r\n\t}\r\n\t\r\n\tif ( set_pitch )\r\n\t{\r\n\t\tp_pb->src.ratioHi\t\t= ( pitch >> 16 );\r\n\t\tp_pb->src.ratioLo\t\t= ( pitch & 0xFFFF );\r\n\t\tp_vpb->sync\t\t\t   |= AX_SYNC_USER_SRCRATIO;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void ax_voice_reacquisition_callback( void* p )\r\n{\r\n\t// Should never happen for stream voices.\r\n\tDbg_Assert( 0 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n////#ifndef USE_VORBIS\r\n//#ifndef DVDETH\r\n//static void s_dtk_callback( u32 event_mask )\r\n//{\r\n//\tif( event_mask & DTK_EVENT_TRACK_ENDED )\r\n//\t{\r\n//\t\t// Stop the music track.\r\n//\t\tDTKSetState( DTK_STATE_STOP );\r\n//\t\tgPcmStatus &= ~PCMSTATUS_MUSIC_PLAYING;\r\n//\t}\r\n//\r\n//\tif( event_mask & DTK_EVENT_PLAYBACK_STARTED )\r\n//\t{\r\n//\t\tif( musicPaused )\r\n//\t\t{\r\n//\t\t\t// Pause the music track.\r\n//\t\t\tDTKSetState( DTK_STATE_PAUSE );\r\n//\t\t}\r\n//\t}\r\n//}\r\n//#endif\t\t// DVDETH\r\n////#endif\t\t// USE_VORBIS\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void s_start_voice_callback( u32 pointerToARQRequest )\r\n{\r\n\t// Figure which stream this is for.\r\n\tint stream = -1;\r\n\t\r\n\tfor( int s = 0; s < NUM_STREAMS; ++s )\r\n\t{\r\n\t\tif( pointerToARQRequest == (u32)( &stream_arq_request[s] ))\r\n\t\t{\r\n\t\t\tstream = s;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif( stream == -1 )\r\n\t{\r\n\t\t// Something has gone very wrong.\r\n\t\tDbg_MsgAssert( 0, ( \"Unsynced dvd callback\" ));\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Deal with the voice already having been deleted.\r\n\tif( gStreamInfo[stream].p_voice == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Set the voice to run.\r\n\tgStreamInfo[stream].hasStartedPlaying\t= true;\r\n\tgStreamInfo[stream].paused\t\t\t\t= streamsPaused;\r\n\tif( !streamsPaused && !gStreamInfo[stream].preloadActive )\r\n\t{\r\n\t\tif( gStreamInfo[stream].p_voice == NULL )\r\n\t\t{\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t\treturn;\t\t\t\r\n\t\t}\r\n\t\tAXSetVoiceState( gStreamInfo[stream].p_voice, AX_PB_STATE_RUN );\r\n\t}\r\n\r\n\t// Adjust pitch to account for lower sampling rates:\r\n\tfloat\t\t\tpitch\t= PERCENT( gStreamInfo[stream].pitch, gStreamInfo[stream].pitchAdjustmentForSamplingRate );\r\n\tunsigned int\tu_pitch\t= (unsigned int)PERCENT( UNALTERED_PITCH, pitch );\r\n\r\n\tint old = OSDisableInterrupts();\r\n\tAXPB*\tp_pb\t\t\t\t\t\t= &( gStreamInfo[stream].p_voice->pb );\r\n\tSpt::SingletonPtr< Sfx::CSfxManager > sfx_manager;\r\n\tsetDolby( p_pb, gStreamInfo[stream].p_voice, gStreamInfo[stream].volumeL, gStreamInfo[stream].volumeR, u_pitch, true, sfx_manager->GetMainVolume() );\r\n\tOSRestoreInterrupts( old );\r\n\r\n\tgPcmStatus |= PCMSTATUS_STREAM_PLAYING( stream );\r\n\tgPcmStatus &= ~PCMSTATUS_LOAD_STREAM( stream );\r\n}\r\n\r\n\t\t\t\t\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void s_dvd_callback( s32 result, DVDFileInfo* fileInfo )\r\n{\r\n\t// Figure which stream this is for.\r\n\tint stream\t= -1;\r\n\r\n\tfor( unsigned int i = 0; i < 8; ++i )\r\n\t{\r\n\t\tfor( uint32 s = 0; s < NUM_STREAMS; ++s )\r\n\t\t{\r\n\t\t\tif( fileInfo == &( gStreamInfo[s].fileInfo[i] ))\r\n\t\t\t{\r\n\t\t\t\tif( i == gStreamInfo[s].currentFileInfo )\r\n\t\t\t\t{\r\n\t\t\t\t\tstream = s;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif( stream >= 0 )\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif( stream == -1 )\r\n\t{\r\n\t\t// Possibly the result of a read in which we are no longer interested.\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Handle read errors by just stopping the stream.\r\n\tif(( result < 0 ) || gStreamInfo[stream].has_paused )\r\n\t{\r\n\t\tint enabled = OSDisableInterrupts();\r\n\t\tif( gStreamInfo[stream].p_voice )\r\n\t\t{\r\n\t\t\t// This should be the case.\r\n\t\t\tAXFreeVoice( gStreamInfo[stream].p_voice );\r\n\t\t}\r\n\t\tgStreamInfo[stream].p_voice\t\t\t= NULL;\r\n\t\tgStreamInfo[stream].preloadActive\t= false;\r\n\t\tgStreamInfo[stream].currentFileInfo\t= ( gStreamInfo[stream].currentFileInfo + 1 ) & 0x07;\r\n\t\tOSRestoreInterrupts( enabled );\r\n\r\n\t\tgPcmStatus &= ~PCMSTATUS_LOAD_STREAM( stream );\r\n\t\tgPcmStatus &= ~PCMSTATUS_STREAM_PLAYING( stream );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Check if has already been stopped.\r\n\tAXVPB* p_axvpb = gStreamInfo[stream].p_voice;\r\n\tif( p_axvpb == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// If this is the first chunk read for this voice, need to grab the voice and look at the header information.\r\n\tif( gStreamInfo[stream].offset == 0 )\r\n\t{\r\n\t\tAXPBADDR        addr;\r\n\t\tAXPBADPCM       adpcm;\r\n\t\tAXPBVE\t\t\tve;\r\n\t\t\r\n\t\tint enabled = OSDisableInterrupts();\r\n\t\t// Grab pointer to header (first 96 byes of data).\r\n\t\tsDSPADPCM*\tp_header\t\t= (sDSPADPCM*)( stream_mem_buffer[stream] );\r\n\r\n\t\taddr.format\t\t\t\t\t= AX_PB_FORMAT_ADPCM;   \r\n\r\n\t\t// Depending on the number of bytes in the sound, we may not need to loop.\r\n\t\t// Also depending on how many times we will be uploading to ARAM, we may want to start the stream\r\n\t\t// halfway through the ARAM buffer, in order to ensure that we always write the last block to the upper half of ARAM\r\n\t\t// (in order that we can safely set the end position).\r\n\t\tint num_adpcm_bytes\t\t\t= p_header->num_adpcm_nibbles / 2;\r\n\r\n\t\t// Convert from byte to nibble address, and split into low and high words.\r\n\t\tu32 start_address\t\t\t= ( stream_base[stream] * 2 ) + 2;\r\n\t\taddr.currentAddressHi\t\t= (u16)( start_address >> 16 );\r\n\t\taddr.currentAddressLo\t\t= (u16)( start_address & 0xFFFFU );\r\n\r\n\t\tif( num_adpcm_bytes <= 32768 )\r\n\t\t{\r\n\t\t\t// Stream fits in to ARAM buffer completely. No need to loop.\r\n\t\t\tu32 end_address\t\t\t\t\t= ( stream_base[stream] * 2 ) + p_header->num_adpcm_nibbles - 1;\r\n\t\t\r\n\t\t\taddr.endAddressHi\t\t\t\t= (u16)( end_address >> 16 );\r\n\t\t\taddr.endAddressLo\t\t\t\t= (u16)( end_address & 0xFFFFU );\r\n\t\t\r\n\t\t\tu32 zero_buffer_address\t\t\t= NxNgc::EngineGlobals.aram_zero * 2;\r\n\t\t\taddr.loopAddressHi\t\t\t\t= (u16)( zero_buffer_address >> 16 );\r\n\t\t\taddr.loopAddressLo\t\t\t\t= (u16)( zero_buffer_address & 0xFFFFU );\r\n\t\t\r\n\t\t\taddr.loopFlag\t\t\t\t\t= AXPBADDR_LOOP_OFF;\r\n\t\t\r\n\t\t\tgStreamInfo[stream].nextWrite\t= 1;\r\n//\t\t\tOSReport( \"Stream: %d is simple <= 32768 bytes\\n\", stream );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Stream does not fit in to ARAM buffer completely. Needs to loop.\r\n\t\t\tuint32 num_uploads\t\t\t\t= num_adpcm_bytes / STREAM_BUFFER_SIZE;\r\n\t\t\tif(( num_adpcm_bytes % STREAM_BUFFER_SIZE ) > 0 )\r\n\t\t\t\t++num_uploads;\r\n\t\t\tDbg_Assert( num_uploads > 2 );\r\n\r\n\t\t\taddr.loopAddressHi\t\t= addr.currentAddressHi;\r\n\t\t\taddr.loopAddressLo\t\t= addr.currentAddressLo;\r\n\t\t\t\r\n\t\t\tif( num_uploads & 0x01 )\r\n\t\t\t{\r\n\t\t\t\t// This is the tricky situation, where we start halfway through the ARAM buffer.\r\n\t\t\t\tgStreamInfo[stream].offsetInARAM   += STREAM_BUFFER_SIZE;\r\n\t\t\t\tstart_address\t\t\t\t\t   += ( STREAM_BUFFER_SIZE * 2 );\r\n\t\t\t\taddr.currentAddressHi\t\t\t\t= (u16)( start_address >> 16 );\r\n\t\t\t\taddr.currentAddressLo\t\t\t\t= (u16)( start_address & 0xFFFFU );\r\n\t\t\t\tgStreamInfo[stream].nextWrite\t\t= 0;\r\n//\t\t\t\tOSReport( \"Stream: %d is complex tricky %d bytes\\n\", stream, num_adpcm_bytes );\r\n\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// This is the easy situation, where we start at the start of the ARAM buffer.\r\n\t\t\t\tgStreamInfo[stream].offsetInARAM\t= 0;\r\n\t\t\t\tgStreamInfo[stream].nextWrite\t\t= 1;\r\n//\t\t\t\tOSReport( \"Stream: %d is complex non-tricky %d bytes\\n\", stream, num_adpcm_bytes );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tu32 end_address\t\t\t= ( stream_base[stream] * 2 ) + ( 32768 * 2 ) - 1;\r\n\t\t\taddr.endAddressHi\t\t= (u16)( end_address >> 16 );\r\n\t\t\taddr.endAddressLo\t\t= (u16)( end_address & 0xFFFFU );\r\n\t\t\r\n\t\t\taddr.loopFlag\t\t\t= AXPBADDR_LOOP_ON;\r\n\t\t}\r\n\r\n\t\tmemcpy( &adpcm.a[0][0], p_header->coef, sizeof( u16 ) * 16 );\r\n\t\tadpcm.gain\t\t\t\t\t= p_header->gain;\r\n\t\tadpcm.pred_scale\t\t\t= p_header->ps;\r\n\t\tadpcm.yn1\t\t\t\t\t= p_header->yn1;\r\n\t\tadpcm.yn2\t\t\t\t\t= p_header->yn2;\r\n\r\n\t\tve.currentVolume\t\t\t= 0x7FFF;\r\n\t\tve.currentDelta\t\t\t\t= 0;\r\n\r\n\t\t// Set voice parameters.\r\n\t\tAXSetVoiceType( p_axvpb, AX_PB_TYPE_NORMAL );\t\t// No loop context.\r\n\t\tAXSetVoiceSrcType( p_axvpb, AX_PB_SRCSEL_LINEAR );\t// Use linear interpolation.\r\n\t\tAXSetVoiceVe( p_axvpb, &ve );\t\t\t\t\t\t// Set overall volume.\r\n\t\tAXSetVoiceAddr( p_axvpb, &addr );\t\t\t\t\t// Input addressing.\r\n\t\tAXSetVoiceAdpcm( p_axvpb, &adpcm );\t\t\t\t\t// ADPCM coefficients.\r\n\r\n//\t\tp_axvpb->sync |= AX_SYNC_USER_ALLPARAMS;\r\n//\t\tAXSetVoiceSrcRatio( p_axvpb, (48000.0f / ((float)AX_IN_SAMPLES_PER_SEC)) );\r\n\r\n\t\t// If this chunk is less than buffersize, zero out the excess bytes to prevent sound pop.\r\n\t\tif( result < ( STREAM_BUFFER_SIZE + STREAM_BUFFER_HEADER_SIZE ))\r\n\t\t{\r\n\t\t\tmemset( stream_mem_buffer[stream] + result, 0, ( STREAM_BUFFER_SIZE + STREAM_BUFFER_HEADER_SIZE ) - result );\r\n\t\t\tDCFlushRange( stream_mem_buffer[stream] + result, ( STREAM_BUFFER_SIZE + STREAM_BUFFER_HEADER_SIZE ) - result );\r\n\t\t}\r\n\t\tOSRestoreInterrupts( enabled );\r\n\r\n\t\t// DMA this chunk up to ARAM, then use the ARQ callback to start the voice.\r\n\t\tARQPostRequest(\t&stream_arq_request[stream],\t\t\t\t\t\t\t// Address to user-allocated storage for an ARQTask data structure.\r\n\t\t\t\t\t\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t// User-enumerated identifier for the owner of the ARAM transaction.\r\n\t\t\t\t\t\tARQ_TYPE_MRAM_TO_ARAM,\t\t\t\t\t\t\t\t\t// Direction.\r\n\t\t\t\t\t\tARQ_PRIORITY_HIGH,\t\t\t\t\t\t\t\t\t\t// Priority.\r\n\t\t\t\t\t\t(u32)( stream_mem_buffer[stream] + 96 ),\t\t\t\t// Source address.\r\n\t\t\t\t\t\tstream_base[stream] + gStreamInfo[stream].offsetInARAM,\t// Destination address.\r\n\t\t\t\t\t\tSTREAM_BUFFER_SIZE,\t\t\t\t\t\t\t\t\t\t// Transfer length (bytes). Must be multiple of 4.\r\n\t\t\t\t\t\t&s_start_voice_callback );\t\t\t\t\t\t\t\t// DMA complete callback function.\r\n\r\n\t\tgStreamInfo[stream].pitchAdjustmentForSamplingRate\t= ((float)p_header->sample_rate * 100.0f ) / 32000.0f;\r\n\t\t\r\n\t\t// Increment the ARAM offset and wrap when appropriate.\r\n\t\tgStreamInfo[stream].offsetInARAM += STREAM_BUFFER_SIZE;\r\n\t\tif( gStreamInfo[stream].offsetInARAM >= ( STREAM_BUFFER_SIZE * 2 ))\r\n\t\t{\r\n\t\t\tgStreamInfo[stream].offsetInARAM -= ( STREAM_BUFFER_SIZE * 2 );\r\n\t\t}\r\n\t\t\r\n\t\t// Increment the file pointer (remember we read the extra buffer bytes for the first read).\r\n\t\tgStreamInfo[stream].offset += STREAM_BUFFER_SIZE + STREAM_BUFFER_HEADER_SIZE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// If this chunk is less than buffersize, zero out the excess bytes to prevent sound pop.\r\n\t\tif( result < STREAM_BUFFER_SIZE )\r\n\t\t{\r\n\t\t\tmemset( stream_mem_buffer[stream] + result, 0, STREAM_BUFFER_SIZE - result );\r\n\t\t\tDCFlushRange( stream_mem_buffer[stream] + result, STREAM_BUFFER_SIZE - result );\r\n\t\t}\r\n\r\n\t\t// We want to DMA this chunk up to ARAM, but only if safe to do so, i.e. only when the playback position is in\r\n\t\t// the opposite half of the ARAM buffer.\r\n\t\tint\t\tcurrent_aram_pos\t= ((uint32)( p_axvpb->pb.addr.currentAddressHi ) << 16 ) | (uint32)( p_axvpb->pb.addr.currentAddressLo );\r\n\t\tbool\tsafe_to_dma\t\t\t= false;\r\n\r\n\t\t// Convert from current ARAM position (in nibbles) to current offset within buffer (in bytes).\r\n\t\tcurrent_aram_pos\t\t\t= ( current_aram_pos - ( stream_base[stream] * 2 )) / 2;\r\n\t\t\r\n\t\tif( current_aram_pos < STREAM_BUFFER_SIZE )\r\n\t\t{\r\n\t\t\t// Safe to write to the second half of the ARAM buffer, if that is what needs updating.\r\n\t\t\tif( gStreamInfo[stream].nextWrite == 1 )\r\n\t\t\t{\r\n\t\t\t\tsafe_to_dma = true;\r\n//\t\t\t\tOSReport( \"Stream: %d ARAM: %d writing to second half\\n\", stream, current_aram_pos );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Safe to write to the first half of the ARAM buffer, if that is what needs updating.\r\n\t\t\tif( gStreamInfo[stream].nextWrite == 0 )\r\n\t\t\t{\r\n\t\t\t\tsafe_to_dma = true;\r\n//\t\t\t\tOSReport( \"Stream: %d ARAM: %d writing to first half\\n\", stream, current_aram_pos );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif( safe_to_dma )\r\n\t\t{\r\n\t\t\t// DMA this chunk up to ARAM.\r\n\t\t\tARQPostRequest(\t&stream_arq_request[stream],\t\t\t\t\t\t\t// Address to user-allocated storage for an ARQTask data structure.\r\n\t\t\t\t\t\t\t0,\t\t\t\t\t\t\t\t\t\t\t\t\t\t// User-enumerated identifier for the owner of the ARAM transaction.\r\n\t\t\t\t\t\t\tARQ_TYPE_MRAM_TO_ARAM,\t\t\t\t\t\t\t\t\t// Direction.\r\n\t\t\t\t\t\t\tARQ_PRIORITY_HIGH,\t\t\t\t\t\t\t\t\t\t// Priority.\r\n\t\t\t\t\t\t\t(u32)( stream_mem_buffer[stream] ),\t\t\t\t\t\t// Source address.\r\n\t\t\t\t\t\t\tstream_base[stream] + gStreamInfo[stream].offsetInARAM,\t// Destination address.\r\n\t\t\t\t\t\t\tSTREAM_BUFFER_SIZE,\t\t\t\t\t\t\t\t\t\t// Transfer length (bytes). Must be multiple of 4.\r\n\t\t\t\t\t\t\tNULL );\t\t\t\t\t\t\t\t\t\t\t\t\t// DMA complete callback function.\r\n\r\n\t\t\t// Increment the ARAM offset and wrap when appropriate.\r\n\t\t\tgStreamInfo[stream].offsetInARAM += STREAM_BUFFER_SIZE;\r\n\t\t\tif( gStreamInfo[stream].offsetInARAM >= ( STREAM_BUFFER_SIZE * 2 ))\r\n\t\t\t{\r\n\t\t\t\tgStreamInfo[stream].offsetInARAM -= ( STREAM_BUFFER_SIZE * 2 );\r\n\t\t\t}\r\n\t\r\n\t\t\t// We have now processed another chunk.\r\n\t\t\tgStreamInfo[stream].nextWrite = ( gStreamInfo[stream].nextWrite == 0 ) ? 1 : 0;\r\n\t\t\r\n\t\t\t// Increment the file pointer.\r\n\t\t\tgStreamInfo[stream].offset += STREAM_BUFFER_SIZE;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n//\t\t\tOSReport( \"Stream: %d ARAM: %d discarding file buffer\\n\", stream, current_aram_pos );\r\n\t\t}\r\n\t}\r\n\r\n\t// If there is more data, kick off another read. NOTE this could potentially write over what we are about to DMA to ARAM.\r\n\tint total_bytes_after_next_read\t= gStreamInfo[stream].offset + STREAM_BUFFER_SIZE;\r\n\tint bytes_to_read;\r\n\tif( total_bytes_after_next_read <= gStreamInfo[stream].fileSize )\r\n\t{\r\n\t\tbytes_to_read = STREAM_BUFFER_SIZE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tbytes_to_read = STREAM_BUFFER_SIZE - ( total_bytes_after_next_read - gStreamInfo[stream].fileSize );\r\n\r\n\t\t// Reduce bytes_to_read down to the next lowest multiple of 32.\r\n\t\tbytes_to_read &= ~31;\r\n\t}\r\n\r\n\tif( bytes_to_read > 0 )\r\n\t{\r\n\t\t_DVDReadAsync(\t&( gStreamInfo[stream].fileInfo[gStreamInfo[stream].currentFileInfo] ),\r\n\t\t\t\t\t\tstream_mem_buffer[stream],\t\t\t\t\t\t\t\t\t\t\t\t// Base pointer of memory to read data into.\r\n\t\t\t\t\t\tbytes_to_read,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Bytes to read.\r\n\t\t\t\t\t\tgStreamInfo[stream].hedOffset + gStreamInfo[stream].offset,\t\t\t\t// Offset in file.\r\n\t\t\t\t\t\ts_dvd_callback );\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Read complete callback.\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Here we may need to set the stop point for the voice, and switch from looping to non-looping.\r\n\t\tif( p_axvpb->pb.addr.loopFlag == AXPBADDR_LOOP_ON )\r\n\t\t{\r\n//\t\t\tOSReport( \"Stream: %d switching to loop off\\n\", stream );\r\n\t\t\tp_axvpb->pb.addr.loopFlag\t\t= AXPBADDR_LOOP_OFF;\r\n\t\t\tu32 zero_buffer_address\t\t\t= NxNgc::EngineGlobals.aram_zero * 2;\r\n\t\t\tp_axvpb->pb.addr.loopAddressHi\t= (u16)( zero_buffer_address >> 16 );\r\n\t\t\tp_axvpb->pb.addr.loopAddressLo\t= (u16)( zero_buffer_address & 0xFFFFU );\r\n\t\t\tp_axvpb->sync |= ( AX_SYNC_USER_LOOP | AX_SYNC_USER_LOOPADDR );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t    Public Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PCMAudio_Init( void )\r\n{\r\n////#\tifdef USE_VORBIS\r\n////#\telse\r\n//#\tifndef DVDETH\r\n//\tDTKInit();\r\n//\tDTKSetVolume( 64, 64 );\t\t// Defaults to half volume.\r\n//\tDTKSetRepeatMode( DTK_MODE_NOREPEAT );\r\n//#\tendif\t\t// DVDETH\r\n////#\tendif\t\t// VORBIS\r\n\r\n\tmemset( gStreamInfo, 0, sizeof( FileStreamInfo ) * NUM_STREAMS );\r\n\r\n\t// Just zero out the audio_player structure.\r\n\tmemset( &audio_player, 0, sizeof( audio_player ));\r\n\t\r\n\tSfx::GetStreamBufferInfo( &stream_base[0], &stream_base[1], &stream_base[2],\r\n\t\t\t\t\t\t\t  &stream_size[0], &stream_size[1], &stream_size[2] );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint PCMAudio_SetMusicVolume( float volume )\r\n{\r\n\t// Save this value off so it can be used again for async startup.\r\n\tmusicVolume = volume;\r\n\t\r\n\t// Normalize down to match PS2.\r\n\tvolume *= 0.5f;\r\n\r\n//#\tifdef USE_VORBIS\r\n//\tif ( !g_using_dtk )\r\n\t{\r\n#\t\tifdef USE_VORBIS\r\n\t\tif( PCMAudio_GetMusicStatus() == PCM_STATUS_PLAYING )\r\n\t\t{\r\n\t\t\tuint32 vol = (uint32)PERCENT( volume, 0x7FFF );\r\n\t\t\tAUDSimpleAudioSetVolume( vol, vol );\r\n\t\t}\r\n#\t\tendif\t// VORBIS\r\n\t}\r\n//\telse\r\n//\t{\r\n//\t\tint vol = (int)PERCENT( volume, MAX_DTK_VOL );\r\n//\t\tif( vol > MAX_DTK_VOL )\r\n//\t\t{\r\n//\t\t\tvol = MAX_DTK_VOL;\r\n//\t\t}\r\n//\t#\tifndef DVDETH\r\n//\t\tDTKSetVolume( vol, vol );\r\n//\t#\tendif\t// DVDETH\r\n//\t}\r\n////#\telse\t\r\n////#\tendif\t// VORBIS\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_LoadMusicHeader( const char *nameOfFile )\r\n{\r\n\t// For now, just fix this as true.\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_TrackExists( const char *pTrackName, int ch )\r\n{\r\n\tif( ch == MUSIC_CHANNEL )\r\n\t{\r\n\t\t// For now, assume all music tracks exist.\r\n\t\treturn true;\r\n\r\n/*\r\n\t\tif( !gpMusicHed )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tif( !FindFileInHed( pTrackName, gpMusicHed ))\r\n\t\t{\r\n\t\t\tDbg_Message( \"Track %s not found in header file.\", pTrackName );\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\treturn true;\r\n*/\r\n\t}\r\n\r\n\tif( !gpStreamHed )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\tif( !FindFileInHed( pTrackName, gpStreamHed ))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n#ifdef USE_VORBIS\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tMemory allocation callback.\r\n *\r\n *\t\tThe player calls this function for all its memory needs. In this example\r\n *\t\tan OSAlloc() is all we need to do.\r\n *\r\n * \\note\r\n *\t\tThe returned memory address MUST be aligned on a 32 byte boundary.\r\n *\t\tOtherwise, the player will fail!\r\n *\r\n * \\param size\r\n *\t\tNumber of bytes to allocate\r\n *\r\n * \\return\r\n *\t\tPtr to allocated memory (aligned to 32 byte boundary)\r\n *\t\r\n ******************************************************************************\r\n */\r\n\r\nstatic void* myAlloc(u32 size)\r\n{\r\n//\tif ( g_in_cutscene )\r\n//\t{\r\n//\t\tint mem_available;\r\n//\r\n//\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().FrontEndHeap() );\r\n//\t\tmem_available = Mem::Manager::sHandle().Available();\r\n//\t\tif ( (int)size < ( mem_available - ( 30 * 1024 ) ) )\r\n//\t\t{\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tMem::Manager::sHandle().PopContext();\r\n//\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ThemeHeap() );\r\n//\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n//\t\t\tif ( (int)size < ( mem_available - ( 5 * 1024 ) ) )\r\n//\t\t\t{\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\tMem::Manager::sHandle().PopContext();\r\n//\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ScriptHeap() );\r\n//\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n//\t\t\t\tif ( (int)size < ( mem_available - ( 15 * 1024 ) ) )\r\n//\t\t\t\t{\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n//\t\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().CutsceneTopDownHeap());\t\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\telse\r\n//\t{\r\n\r\n//\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().TopDownHeap());\r\n//\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().BottomUpHeap());\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().AudioHeap());\r\n\r\n//\t}\r\n\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\tvoid * p = new u8[size]; \r\n\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn p;\r\n}\r\n\r\n/*!\r\n ******************************************************************************\r\n * \\brief\r\n *\t\tMemory free callback.\r\n *\r\n * \\param ptr\r\n *\t\tMemory address to free\r\n *\t\r\n ******************************************************************************\r\n */\r\nstatic void myFree(void* ptr)\r\n{\r\n\tASSERT(ptr);\t// free on address 0 is only valid in C++ delete\r\n\tdelete [] ptr;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PCMAudio_DecodeLoop( void )\r\n{\r\n\t// Deal with the asynchronous opening of music tracks.\r\n\tif( audio_player.asyncOpenCallbackStatus > 0 )\r\n\t{\r\n\t\tgPcmStatus |= PCMSTATUS_MUSIC_PLAYING;\r\n\t\r\n\t\tif( audio_player.asyncOpenCallbackStatus == ASYNC_OPEN_SUCCESS )\r\n\t\t{\r\n\t\t\t// Reset the callback status.\r\n\t\t\taudio_player.asyncOpenCallbackStatus = 0;\r\n\t\t\t\r\n\t\t\t// At this point we can complete the initialization process.\r\n\t\t\tif( AUDSimpleAllocDVDBuffers() == FALSE )\r\n\t\t\t\tOSHalt(\"*** AUDSimpleAllocDVDBuffers failed!\\n\");\r\n\t\t\tif( AUDSimpleCreateDecoder() == FALSE )\r\n\t\t\t\tOSHalt(\"*** AUDSimpleCreateDecoder failed!\\n\");\r\n\t\t\tif( AUDSimpleInitAudioDecoder() == FALSE )\r\n\t\t\t\tOSHalt(\"*** AUDSimpleInitAudioDecoder failed!\\n\");\r\n\t\t\t\r\n\t\t\t// Reset the music volume, now that we have voices allocated.\r\n\t\t\tPCMAudio_SetMusicVolume( musicVolume );\r\n\t\t\t\r\n\t\t\t// Preload all DVD buffers and set 'loop' mode to false.\r\n\t\t\tAUDSimpleLoadStart( FALSE );\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// Decode one frame.\r\n\tif( audio_player.decoder && !musicPaused )\r\n\t{\r\n\t\tgPcmStatus |= PCMSTATUS_MUSIC_PLAYING;\r\n\t\t\r\n\t\tif(\taudio_player.decodeComplete )\r\n\t\t{\r\n\t\t\tif(\taudio_player.playbackComplete )\r\n\t\t\t{\r\n//\t\t\t\tOSReport( \"Ending song\\n\" );\r\n\t\t\t\r\n\t\t\t\t// Come to the end of the music data. Free our resources.\r\n\t\t\t\tAUDSimpleLoadStop();\r\n\t\t\t\tAUDSimpleClose();\r\n\t\t\t\tAUDSimpleFreeDVDBuffers();\r\n\t\t\t\t\r\n\t\t\t\tAUDSimpleDestroyDecoder();\r\n\t\t\t\tAUDSimpleExitAudioDecoder();\r\n\t\t\t\r\n\t\t\t\tgPcmStatus &= ~PCMSTATUS_MUSIC_PLAYING;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( audio_player.preFetchState && !musicPreloadActive )\r\n\t\t{\r\n\t\t\t// See how many free samples in the read buffer (the big buffer into which the bitstream\r\n\t\t\t// is decoded). Overflowing this buffer causes DivX to behave very badly.\r\n\t\t\tu32\tfree_samples = AUDSimpleAudioGetFreeReadBufferSamples();\r\n//\t\t\tOSReport( \"Free samples is: %d\\n\", free_samples );\r\n\r\n\t\t\tif( free_samples > 20000 )\r\n\t\t\t{\r\n\t\t\t\t// 20000 samples was derived empirically.\r\n\t\t\t\tif( AUDSimpleDecode() == FALSE )\r\n\t\t\t\t{\r\n//\t\t\t\t\tOSReport( \"Decode complete\\n\" );\r\n\t\t\t\t\taudio_player.decodeComplete = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if( audio_player.playbackComplete )\r\n\t\t\t{\r\n\t\t\t\t// Seems like if the CPU is starved, the playbackComplete flag can be set despite the \r\n\t\t\t\t// decodeComplete flag not being set. Try to cater for this situation here.\r\n\t\t\t\tif( AUDSimpleDecode() == FALSE )\r\n\t\t\t\t{\r\n//\t\t\t\t\tOSReport( \"Decode complete\\n\" );\r\n\t\t\t\t\taudio_player.decodeComplete = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// The decoder changes these, so reset them, otherwise animations/particles are messed up.\r\n    GQRSetup6( GQR_SCALE_64,\t\t// Pos\r\n               GQR_TYPE_S16,\r\n\t\t\t   GQR_SCALE_64,\r\n               GQR_TYPE_S16 );\r\n    GQRSetup7( 14,\t\t// Normal\r\n               GQR_TYPE_S16,\r\n               14,\r\n               GQR_TYPE_S16 );\r\n//\tif( AUDSimpleCheckDVDError() == FALSE )\r\n//\t{\r\n//\t\tOSHalt( \"*** DVD error occured. A true DVD error handler is not part of this demo.\\n\" );\r\n//\t}\r\n\r\n\r\n}\r\n#endif\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PlayMusicTrack( const char *filename, bool preload )\r\n{\r\n\t// Set the preload flag.\r\n\tmusicPreloadActive = preload;\r\n\t\r\n\tif ( NxNgc::EngineGlobals.disableReset ) return false;\r\n\r\n\tif( PCMAudio_GetMusicStatus() != PCM_STATUS_FREE )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Playing new track without stopping the first track.\" ));\r\n\t\treturn false;\r\n\t}\r\n\r\n\tFile::StopStreaming();\r\n\r\n//#\tifdef USE_VORBIS\r\n#\tifdef USE_VORBIS\r\n\t{\r\n\t\t// Fix up the filename, which comes in the form music\\vag\\songs\\<foo>, and add the .ogg extension.\r\n\t\tstatic char\tname_buffer[256] = \"music/ogg/\";\r\n\t\tstrcpy( &name_buffer[10], &filename[10] );\r\n\t\tstrcpy( name_buffer + strlen( name_buffer ), \".ogg\" );\r\n\t\tchar* p = name_buffer;\r\n\t\twhile( *p != '\\0' )\r\n\t\t{\r\n\t\t\tif ( *p == '\\\\' ) *p = '/';\r\n\t\t\t++p;\r\n\t\t}\r\n\r\n\t\tAUDSimpleInit( myAlloc, myFree );\r\n\t\t\r\n\t\t// This will open the file asynchronously, so nothing after this point except wait.\r\n\t\tif( AUDSimpleOpen( name_buffer ) == FALSE )\r\n\t\t{\r\n\t\t\t// File not found.\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\taudio_player.decodeComplete\t\t= false;\r\n\t\taudio_player.playbackComplete\t= false;\r\n\t\t\r\n//\t\tif( AUDSimpleAllocDVDBuffers() == FALSE )\r\n//\t\t\tOSHalt(\"*** AUDSimpleAllocDVDBuffers failed!\\n\");\r\n//\t\tif( AUDSimpleCreateDecoder() == FALSE )\r\n//\t\t\tOSHalt(\"*** AUDSimpleCreateDecoder failed!\\n\");\r\n//\t\tif( AUDSimpleInitAudioDecoder() == FALSE )\r\n//\t\t\tOSHalt(\"*** AUDSimpleInitAudioDecoder failed!\\n\");\r\n\r\n\t\t// Preload all DVD buffers and set 'loop' mode\r\n//\t\tAUDSimpleLoadStart( FALSE );\r\n\t\t\r\n\t\treturn true;\r\n\t}\r\n#\tendif\t\t// USE_VORBIS\r\n////#\telse\r\n//\r\n//\t// Allow turning off of music from script global.\r\n////\tint testMusic = Script::GetInt( 0x47ac7ba5, false ); // checksum 'testMusicFromHost'\r\n////\tif( !testMusic )\r\n////\t{\r\n////\t\treturn false;\r\n////\t}\r\n//\r\n//\t{\r\n//\t\t// Fix up the filename, and add the .dtk extension.\r\n//\t\tstatic char\tname_buffer[256] = \"music/dtk/\";\r\n//\t\tstrcpy( &name_buffer[10], &filename[10] );\r\n//\t\tstrcpy( name_buffer + strlen( name_buffer ), \".dtk\" );\r\n//\t\tchar* p = name_buffer;\r\n//\t\twhile( *p != '\\0' )\r\n//\t\t{\r\n//\t\t\tif ( *p == '\\\\' ) *p = '/';\r\n//\t\t\t++p;\r\n//\t\t}\r\n//\r\n//\t#\tifndef DVDETH\r\n//\t\tu32 dtk_result = DTKQueueTrack( name_buffer, &s_dtk_track, 0xff, s_dtk_callback );\r\n//\t//\tDbg_MsgAssert( dtk_result == DTK_QUEUE_SUCCESS, ( \"Failed to play: %s\\n\", name_buffer ));\r\n//\r\n//\t\tif( dtk_result == DTK_QUEUE_SUCCESS )\r\n//\t\t{\r\n//\t\t\tif(\tmusicPaused )\r\n//\t\t\t{\r\n//\t\t\t\t// The callback will handle pausing the track.\r\n//\t\t\t\tDTKSetState( DTK_STATE_RUN );\r\n//\t//\t\t\tDTKSetState( DTK_STATE_PAUSE );\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\tDTKSetState( DTK_STATE_RUN );\r\n//\t\t\t}\r\n//\r\n//\t\t\tgPcmStatus |= PCMSTATUS_MUSIC_PLAYING;\r\n//\t\t\treturn true;\r\n//\t\t}\r\n//\t#\tendif\t\t// DVDETH\r\n//\t\t// If we get here then the track did not get queued.\r\n//\t}\r\n//\treturn false;\r\n////#\tendif // USE_VORBIS\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PCMAudio_StopMusic( bool waitPlease )\r\n{\r\n//\tint status = PCMAudio_GetMusicStatus();\r\n\r\n//\tif ( g_using_dtk )\r\n//\t{\r\n//\t\tif( status == PCM_STATUS_LOADING )\r\n//\t\t{\r\n//\t\t\tDbg_MsgAssert( 0, ( \"What, how can we be loading?\" ));\r\n//\t\t}\r\n//\t\telse if( status == PCM_STATUS_PLAYING )\r\n//\t\t{\r\n//\t\t\t// Stop the track playing.\r\n//#\t\t\tifndef DVDETH\r\n//\t\t\tDTKSetState( DTK_STATE_STOP );\r\n//#\t\t\tendif\t\t// DVDETH\r\n//\t\t}\r\n//\t\tgPcmStatus &= ~PCMSTATUS_MUSIC_PLAYING;\r\n//\t}\r\n//\telse\r\n\t{\r\n#\t\tifdef USE_VORBIS\r\n\t\tif( audio_player.asyncOpenCallbackStatus > 0 )\r\n\t\t{\r\n\t\t\t// Player is in async startup state, hasn't allocated buffers yet.\r\n\t\t\taudio_player.error = TRUE;\r\n\t\t}\r\n\t\telse if( audio_player.decoder )\r\n\t\t{\r\n\t\t\tif( !audio_player.preFetchState )\r\n\t\t\t{\r\n\t\t\t\t// Still seeding the DVD buffers, so dangerous to stop the music immediately.\r\n\t\t\t\ts32 tick = OSGetTick();\r\n\t\t\t\twhile( audio_player.preFetchState == false )\r\n\t\t\t\t{\r\n\t\t\t\t\ts32 diff = OSDiffTick( OSGetTick(), tick );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Wait no more than quarter of a second.\r\n\t\t\t\t\tif( diff > (s32)( OS_TIMER_CLOCK / 4 ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tAUDSimpleAudioReset();\r\n\t\t\tAUDSimpleLoadStop();\r\n\t\t\tAUDSimpleClose();\r\n\t\r\n\t\t\tAUDSimpleFreeDVDBuffers();\r\n\t\t\tAUDSimpleDestroyDecoder();\r\n\t\t\tAUDSimpleExitAudioDecoder();\r\n\t\t}\r\n#\tendif\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint PCMAudio_GetMusicStatus( void )\r\n{\r\n//\tif ( g_using_dtk )\r\n//\t{\r\n//\t\tif( gPcmStatus & PCMSTATUS_LOAD_MUSIC )\r\n//\t\t{\r\n//\t\t\treturn PCM_STATUS_LOADING;\r\n//\t\t}\r\n//\t\telse if( gPcmStatus & PCMSTATUS_MUSIC_PLAYING )\r\n//\t\t{\r\n//\t\t\treturn PCM_STATUS_PLAYING;\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\t// Sanity check.\r\n//\t#\t\tifndef DVDETH\r\n//\t\t\tu32 state = DTKGetState();\r\n//\t\t\tif( state == DTK_STATE_BUSY )\r\n//\t\t\t{\r\n//\t\t\t\treturn PCM_STATUS_PLAYING;\r\n//\t\t\t}\r\n//\t#\t\tendif\t\t// DVDETH\r\n//\t\t\treturn PCM_STATUS_FREE;\r\n//\t\t}\r\n//\t\treturn 0;\r\n//\t}\r\n//\telse\r\n\t{\r\n#\t\tifdef USE_VORBIS\r\n\t\tif( audio_player.asyncOpenCallbackStatus > 0 )\r\n\t\t{\r\n\t\t\treturn PCM_STATUS_LOADING;\r\n\t\t}\r\n\t\tif( audio_player.decoder )\r\n\t\t{\r\n\t\t\treturn PCM_STATUS_PLAYING;\r\n\t\t}\r\n#\t\tendif // USE_VORBIS\r\n\t\treturn PCM_STATUS_FREE;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PCMAudio_Pause( bool pause, int ch )\r\n{\r\n\tif( ch == MUSIC_CHANNEL )\r\n\t{\r\n\t\tmusicPaused = pause;\r\n\r\n//\t\tif ( g_using_dtk )\r\n//\t\t{\r\n//#\t\t\tifndef DVDETH\r\n//\t\t\tu32 state = DTKGetState();\r\n//\t\t\tif( pause && ( state == DTK_STATE_RUN ))\r\n//\t\t\t{\r\n//\t\t\t\tDTKSetState( DTK_STATE_PAUSE );\r\n//\t\t\t}\r\n//\t\t\telse if( !pause && ( state == DTK_STATE_PAUSE ))\r\n//\t\t\t{\r\n//\t\t\t\tDTKSetState( DTK_STATE_RUN );\r\n//\t\t\t}\r\n//#\t\t\tendif\t// DVDETH\r\n//\t\t}\r\n//\t\telse\r\n\t\t{\r\n#\t\t\tifdef USE_VORBIS\r\n\t\t\tif( audio_player.decoder )\r\n\t\t\t{\r\n\t\t\t\tAUDSimplePause( pause );\r\n\t\t\t}\r\n\r\n//\t\t\tPCMAudio_StopMusic( true );\r\n#\t\t\tendif // USE_VORBIS\r\n\t\t}\r\n//#\t\tifdef USE_VORBIS\r\n//#\t\telse\r\n//#\t\tendif\t// USE_VORBIS\r\n\t}\r\n\telse\r\n\t{\r\n\t\tstreamsPaused = pause;\r\n\r\n\t\tfor( int i = 0; i < NUM_STREAMS; ++i )\r\n\t\t{\r\n\t\t\tif( gStreamInfo[i].p_voice )\r\n\t\t\t{\r\n\t\t\t\tif( pause && !gStreamInfo[i].paused )\r\n\t\t\t\t{\r\n\t\t\t\t\tgStreamInfo[i].paused = true;\r\n\t\t\t\t\tAXSetVoiceState( gStreamInfo[i].p_voice, AX_PB_STATE_STOP );\r\n\t\t\t\t}\r\n\t\t\t\telse if( !pause && gStreamInfo[i].paused )\r\n\t\t\t\t{\r\n\t\t\t\t\tgStreamInfo[i].paused = false;\r\n\t\t\t\t\tAXSetVoiceState( gStreamInfo[i].p_voice, AX_PB_STATE_RUN );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( pause )\r\n\t\t{\r\n\t\t\tfor( int s = 0; s < NUM_STREAMS; ++s )\r\n\t\t\t{\r\n\t\t\t\tgStreamInfo[s].has_paused = true;\r\n\t\t\t\tif( gStreamInfo[s].p_voice )\r\n\t\t\t\t\tsetDolby( &gStreamInfo[s].p_voice->pb, gStreamInfo[s].p_voice, 0, 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Returns true if there is a pcm error.                          */\r\n/*                                                                */\r\n/******************************************************************/\r\n//static uint64 last_vb = 0;\r\nint PCMAudio_Update( void )\r\n{\r\n//\tuint64 vb = Tmr::GetVblanks();\r\n//\tif ( last_vb == vb ) return true;\r\n//\tlast_vb = vb;\r\n\r\n\tgPcmStatus &= ~PCMSTATUS_MUSIC_PLAYING;\r\n\r\n//\tif ( g_using_dtk )\r\n//\t{\r\n//#\t\tifndef DVDETH\r\n//\t\tu32 state = DTKGetState();\r\n//\t\r\n//\t\tif( state != DTK_STATE_STOP )\r\n//\t\t{\r\n//\t\t\tgPcmStatus |= PCMSTATUS_MUSIC_PLAYING;\r\n//\t\t}\r\n//#\t\tendif\t// DVDETH\r\n//\t}\r\n//\telse\r\n\t{\r\n#\t\tifdef USE_VORBIS\r\n\t\tPCMAudio_DecodeLoop();\r\n#\t\tendif\t\t// USE_VORBIS\r\n\t}\r\n#\tifdef USE_VORBIS\r\n#\telse\r\n#\tendif\t// USE_VORBIS\r\n\r\n\t// Check the stream voices to see if they are finished playing.\r\n\tbool check = false;\r\n\tfor( int i = 0; i < NUM_STREAMS; ++i )\r\n\t{\r\n\t\tif( gStreamInfo[i].p_voice )\r\n\t\t{\r\n\t\t\tif(( gStreamInfo[i].p_voice->pb.state == AX_PB_STATE_STOP ) && ( gStreamInfo[i].hasStartedPlaying ) && !gStreamInfo[i].paused && !gStreamInfo[i].preloadActive )\r\n\t\t\t{\r\n\t\t\t\t// Playback on this voice has ended, so free up the voice.\r\n\t\t\t\tint enabled = OSDisableInterrupts();\r\n\t\t\t\tAXFreeVoice( gStreamInfo[i].p_voice );\r\n\t\t\t\tgStreamInfo[i].p_voice = NULL;\r\n\t\t\t\tgStreamInfo[i].currentFileInfo = ( gStreamInfo[i].currentFileInfo + 1 ) & 0x07;\r\n\t\t\t\tOSRestoreInterrupts( enabled );\r\n\r\n\t\t\t\tgPcmStatus &= ~PCMSTATUS_LOAD_STREAM( i );\r\n\t\t\t\tgPcmStatus &= ~PCMSTATUS_STREAM_PLAYING( i );\r\n//\t\t\t\tOSReport( \"freed voice for stream: %d\\n\", i );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Check to see whether the sound has played beyond the amount of data already dma'ed.\r\n\t\t\t\tint offset = gStreamInfo[i].p_voice->pb.addr.currentAddressLo + ((int)gStreamInfo[i].p_voice->pb.addr.currentAddressHi * 65536 );\r\n\r\n\t\t\t\t// Convert offset from nibble to byte address, and make relative to stream base.\r\n\t\t\t\toffset = ( offset / 2 ) - stream_base[i];\r\n//\t\t\t\tOSReport( \"stream %d offset is at: %d\\n\", i, offset );\r\n\r\n\t\t\t\tif( offset > gStreamInfo[i].offsetInARAM )\r\n\t\t\t\t{\r\n//\t\t\t\t\tOSReport( \"play point beyond byuffer...\\n\" );\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Flag this stream as playing.\r\n\t\t\t\tgPcmStatus |= PCMSTATUS_STREAM_PLAYING( i );\r\n\t\t\t\tcheck = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t// Deal with disk errors.\r\n\tif ( gPcmStatus & PCMSTATUS_MUSIC_PLAYING ) check = true;\r\n\tif ( check ) DVDCheckAsync();\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 PCMAudio_FindNameFromChecksum( uint32 checksum, int ch )\r\n{\r\n\tFile::SHed*\tpHed;\r\n\r\n\tif( ch == EXTRA_CHANNEL )\r\n\t{\r\n\t\tpHed = gpStreamHed;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Don't use the music hed file.\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tif( !pHed )\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tFile::SHedFile* pHedFile = File::FindFileInHedUsingChecksum( checksum, pHed );\r\n\tif( pHedFile )\r\n\t{\r\n\t\treturn pHedFile->Checksum;\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PlayStream( uint32 checksum, int whichStream, float volumeL, float volumeR, float fPitch, bool preload )\r\n{\r\n//#ifdef \r\n\t\r\n\tif( PCMAudio_GetStreamStatus( whichStream ) != PCM_STATUS_FREE )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n//\tint testStreams = Script::GetInt( 0x62df9442, false ); // checksum 'testStreamsFromHost'\r\n//\tif( !testStreams )\r\n//\t{\r\n//\t\treturn false;\r\n//\t}\r\n\r\n\t// Incoming filenames are either of the form '\\skateshp\\menu', or '\\streams\\la\\la_argue51' etc.\r\n\t// Strip the preceeding '\\streams' if present.\r\n//\tif( strnicmp( filename, \"\\\\streams\", 8 ) == 0 )\r\n//\t{\r\n//\t\tfilename += 8;\r\n//\t}\r\n//\r\n//\tstatic char name_buffer[128] = \"streams/dsp\";\r\n//\tconst int MUSIC_PREPEND_START_POS = 11;\r\n//\r\n//\t// Need to append file type. Copy string into a buffer. Check there is room to add the extension.\r\n//\tint length = strlen( filename );\r\n//\tDbg_Assert( length <= ( 128 - ( MUSIC_PREPEND_START_POS + 4 )));\r\n//\tstrcpy( name_buffer + MUSIC_PREPEND_START_POS, filename );\r\n//\tstrcpy( name_buffer + MUSIC_PREPEND_START_POS + length, \".dsp\" );\r\n//\r\n//\t// Fix directory separators.\r\n//\tchar* p = name_buffer;\r\n//\twhile( *p != '\\0' )\r\n//\t{\r\n//\t\tif ( *p == '\\\\' ) *p = '/';\r\n//\t\t++p;\r\n//\t}\r\n\r\n\tFile::SHedFile *pHed = FindFileInHedUsingChecksum( checksum, gpStreamHed );\r\n\r\n#ifdef DVDETH\r\n\tBOOL result = false;\r\n#else\r\n\tBOOL result = DVDFastOpen( DVDConvertPathToEntrynum( \"streams/streamsngc.wad\" ), &( gStreamInfo[whichStream].fileInfo[gStreamInfo[whichStream].currentFileInfo] ) );\r\n#endif\r\n//\tDVDSeek( &( gStreamInfo[whichStream].fileInfo[gStreamInfo[whichStream].currentFileInfo] ), pHed->Offset );\r\n\tif( result )\r\n\t{\r\n\t\tif ( pHed && pHed->FileSize )\r\n\t\t{\r\n\t\t\t// Allocate a voice for use, and store it for later.\r\n\t\t\tAXVPB*\t\tp_axvpb\t\t\t\t\t\t\t= AXAcquireVoice( AX_PRIORITY_NODROP, ax_voice_reacquisition_callback, 0 );\r\n\t\t\tDbg_Assert( p_axvpb );\r\n\t\t\tgStreamInfo[whichStream].p_voice\t\t\t= p_axvpb;\r\n\t\t\tgStreamInfo[whichStream].paused\t\t\t\t= false;\r\n\t\t\tgStreamInfo[whichStream].hasStartedPlaying\t= false;\r\n\t\r\n\t\t\t// Flag that we are loading the stream up.\r\n\t\t\tgPcmStatus |= PCMSTATUS_LOAD_STREAM( whichStream );\r\n\t\r\n\t\t\t// Read in the first chunk.\r\n\t\t\tgStreamInfo[whichStream].offset\t\t\t\t= 0;\r\n\t\t\tgStreamInfo[whichStream].offsetInARAM\t\t= 0;\r\n\t\t\tgStreamInfo[whichStream].nextWrite\t\t\t= 0;\r\n\t\r\n\t\t\tgStreamInfo[whichStream].hedOffset\t\t\t= pHed->Offset;\r\n\t\t\t\r\n\t\t\t// Round filesize up to 32 byte alignment.\r\n\t\t\tgStreamInfo[whichStream].fileSize\t\t\t= pHed->FileSize;\r\n\t\t\tgStreamInfo[whichStream].pitch\t\t\t\t= fPitch;\r\n\t\t\tgStreamInfo[whichStream].volumeL\t\t\t= volumeL;\r\n\t\t\tgStreamInfo[whichStream].volumeR\t\t\t= volumeR;\r\n//\t\t\tOSReport( \"%s %d\\n\", name_buffer, gStreamInfo[whichStream].fileSize );\r\n\t\r\n\t\t\t// Shhhh.....\r\n\t\t\tsetDolby( &p_axvpb->pb, p_axvpb, 0, 0 );\r\n\r\n\t\t\t// Set the preload flag.\r\n\t\t\tgStreamInfo[whichStream].preloadActive = preload;\r\n\t\t\t\r\n\t\t\t// The first chunk we read is STREAM_BUFFER_HEADER_SIZE bigger than normal, so that even with the header in\r\n\t\t\t// the first read, we can still DMA the full amount up to ARAM.\r\n\t\t\tint bytes_to_read = ( pHed->FileSize >= ( STREAM_BUFFER_SIZE + STREAM_BUFFER_HEADER_SIZE )) ? ( STREAM_BUFFER_SIZE + STREAM_BUFFER_HEADER_SIZE ) : ( pHed->FileSize & ~31 );\r\n\t\t\tgStreamInfo[whichStream].has_paused = false;\r\n//\t\t\tOSReport( \"Starting stream %x on channel %d\\n\", checksum, whichStream );\r\n\t\t\tresult = DVDReadAsync(\t&( gStreamInfo[whichStream].fileInfo[gStreamInfo[whichStream].currentFileInfo] ),\r\n\t\t\t\t\t\t\t\t\tstream_mem_buffer[whichStream],\t\t// Base pointer of memory to read data into.\r\n\t\t\t\t\t\t\t\t\tbytes_to_read,\t\t\t\t\t\t// Bytes to read.\r\n\t\t\t\t\t\t\t\t\tpHed->Offset,\t\t\t\t\t\t// Offset in file.\r\n\t\t\t\t\t\t\t\t\ts_dvd_callback );\t\t\t\t\t// Read complete callback.\r\n\t\r\n\t\t\t// Nothing more required for now.\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDVDClose( &( gStreamInfo[whichStream].fileInfo[gStreamInfo[whichStream].currentFileInfo] ));\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PCMAudio_SetStreamGlobalVolume( unsigned int volume )\r\n{\r\n\tgStreamVolume = volume;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_SetStreamVolume( float volumeL, float volumeR, int whichStream )\r\n{\r\n\tif( gStreamInfo[whichStream].p_voice )\r\n\t{\r\n\t\tint old = OSDisableInterrupts();\r\n\r\n\t\tAXPB*\tp_pb\t= &( gStreamInfo[whichStream].p_voice->pb );\r\n\r\n\t\tSpt::SingletonPtr< Sfx::CSfxManager > sfx_manager;\r\n\t\tvolumeL = PERCENT( sfx_manager->GetMainVolume() / 2.0f, volumeL );\r\n\t\tvolumeR = PERCENT( sfx_manager->GetMainVolume() / 2.0f, volumeR );\r\n\t\tsetDolby( p_pb, gStreamInfo[whichStream].p_voice, volumeL, volumeR );\r\n\r\n\t\tOSRestoreInterrupts( old );\r\n\r\n//\t\t// Adjust stream volume based on global sound effect volume.\r\n//\t\tSpt::SingletonPtr< Sfx::CSfxManager > sfx_manager;\r\n//\t\tp_pb->mix.vL\t\t\t\t\t\t= (unsigned int)(( volL * sfx_manager->GetMainVolume()) * 0.01f );\r\n//\t\tp_pb->mix.vR\t\t\t\t\t\t= (unsigned int)(( volR * sfx_manager->GetMainVolume()) * 0.01f );\r\n//\r\n//\t\tif( !Sfx::isStereo )\r\n//\t\t{\r\n//\t\t\tunsigned int mix\t= ( p_pb->mix.vL + p_pb->mix.vR ) / 2;\r\n//\t\t\tp_pb->mix.vL\t\t= mix;\r\n//\t\t\tp_pb->mix.vR\t\t= mix;\r\n//\t\t}\r\n//\r\n//\t\tgStreamInfo[whichStream].p_voice->sync  |= ( AX_SYNC_USER_MIX );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_SetStreamPitch( float fPitch, int whichStream )\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PCMAudio_StopStream( int whichStream, bool waitPlease )\r\n{\r\n\t// Clear the preload flag to be safe.\r\n\tgStreamInfo[whichStream].preloadActive\t= false;\r\n\tsPreLoadChecksum[whichStream]\t\t\t= 0;\r\n\t\r\n\tif( gStreamInfo[whichStream].p_voice )\r\n\t{\r\n\t\tint enabled = OSDisableInterrupts();\r\n\t\tAXFreeVoice( gStreamInfo[whichStream].p_voice );\r\n\t\tgStreamInfo[whichStream].p_voice\t\t\t= NULL;\r\n\t\tgStreamInfo[whichStream].currentFileInfo\t= ( gStreamInfo[whichStream].currentFileInfo + 1 ) & 0x07;\r\n\t\tOSRestoreInterrupts( enabled );\r\n\r\n\t\tgPcmStatus &= ~PCMSTATUS_LOAD_STREAM( whichStream );\r\n\t\tgPcmStatus &= ~PCMSTATUS_STREAM_PLAYING( whichStream );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PCMAudio_StopStreams( void )\r\n{\r\n\tfor( int i = 0; i < NUM_STREAMS; i++ )\r\n\t{\r\n\t\tPCMAudio_StopStream( i, true );\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Get a stream loaded into a buffer, but don't play yet.\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PreLoadStream( uint32 checksum, int whichStream )\r\n{\r\n\tbool rv = PCMAudio_PlayStream( checksum, whichStream, 0.0f, 0.0f, 100.0f, true );\r\n\tif( rv )\r\n\t{\r\n\t\tsPreLoadChecksum[whichStream] = checksum;\r\n\t}\r\n\treturn rv;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Returns true if preload done. Assumes that caller is calling\t  */\r\n/* this on a preloaded, but not yet played, stream. The results\t  */\r\n/* are meaningless otherwise.\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PreLoadStreamDone( int whichStream )\r\n{\r\n\tif( gStreamInfo[whichStream].preloadActive )\r\n\t{\r\n\t\t// The hasStartedPlaying member will be set to true in the start voice callback, which is when\r\n\t\t// we are ready to allow playback.\r\n\t\tif( gStreamInfo[whichStream].hasStartedPlaying )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Tells a preloaded stream to start playing. Must call\t\t\t  */\r\n/* PCMAudio_PreLoadStreamDone() first to guarantee that it starts */\r\n/* immediately.\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_StartPreLoadedStream( int whichStream, float volumeL, float volumeR, float pitch )\r\n{\r\n\tDbg_Assert( gStreamInfo[whichStream].offset > 0 );\r\n\t\r\n\tsPreLoadChecksum[whichStream] = 0;\r\n\t\r\n\tif( gStreamInfo[whichStream].p_voice )\r\n\t{\r\n\t\tgStreamInfo[whichStream].preloadActive = false;\r\n\t\t\r\n\t\t// If we are not paused, set voice to RUN.\r\n\t\tif( !streamsPaused )\r\n\t\t{\r\n\t\t\tAXSetVoiceState( gStreamInfo[whichStream].p_voice, AX_PB_STATE_RUN );\r\n\t\t}\r\n\t\t\r\n\t\t// Set the correct volume.\r\n\t\tPCMAudio_SetStreamVolume( volumeL, volumeR, whichStream );\r\n\t\tPCMAudio_SetStreamPitch( pitch, whichStream );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PreLoadMusicStream( uint32 checksum )\r\n{\r\n\tsPreLoadMusicChecksum = checksum;\r\n\r\n\tstatic char* p_filename[] =\r\n\t{\r\n\t\t\"AU/AU_01V_Female\",\r\n\t\t\"AU/AU_01V_Male\",\r\n\t\t\"AU/AU_02_Female\",\r\n\t\t\"AU/AU_02_Male\",\r\n\t\t\"Final/Final_Female\",\r\n\t\t\"Final/Final_Male\",\r\n\t\t\"FL/FL_01_Female\",\r\n\t\t\"FL/FL_01_Male\",\r\n\t\t\"FL/FL_02_Female\",\r\n\t\t\"FL/FL_02_Male\",\r\n\t\t\"FL/FL_03_Female\",\r\n\t\t\"FL/FL_03_Male\",\r\n\t\t\"FL/FL_04_Female\",\r\n\t\t\"FL/FL_04_Male\",\r\n\t\t\"HI/HI_01_Female\",\r\n\t\t\"HI/HI_01_Male\",\r\n\t\t\"HI/HI_02V_Female\",\r\n\t\t\"HI/HI_02V_Male\",\r\n\t\t\"HI/HI_03_Female\",\r\n\t\t\"HI/HI_03_Male\",\r\n\t\t\"HI/HI_04_Female\",\r\n\t\t\"HI/HI_04_Male\",\r\n\t\t\"HI/HI_05_Female\",\r\n\t\t\"HI/HI_05_Male\",\r\n\t\t\"Intro/Intro_01_Female\",\r\n\t\t\"Intro/Intro_01_Male\",\r\n\t\t\"Intro/Intro_02_Female\",\r\n\t\t\"Intro/Intro_02_Male\",\r\n\t\t\"NJ/NJ_01V_Female\",\r\n\t\t\"NJ/NJ_01V_Male\",\r\n\t\t\"NJ/NJ_02A_Female\",\r\n\t\t\"NJ/NJ_02A_Male\",\r\n\t\t\"NJ/NJ_02B_Female\",\r\n\t\t\"NJ/NJ_02B_Male\",\r\n\t\t\"NJ/NJ_02_Female\",\r\n\t\t\"NJ/NJ_02_Male\",\r\n\t\t\"NJ/NJ_03_Female\",\r\n\t\t\"NJ/NJ_03_Male\",\r\n\t\t\"NJ/NJ_04_Female\",\r\n\t\t\"NJ/NJ_04_Male\",\r\n\t\t\"NJ/NJ_05B_Female\",\r\n\t\t\"NJ/NJ_05B_Male\",\r\n\t\t\"NJ/NJ_05_Female\",\r\n\t\t\"NJ/NJ_05_Male\",\r\n\t\t\"NJ/NJ_06_Female\",\r\n\t\t\"NJ/NJ_06_Male\",\r\n\t\t\"NJ/NJ_07_Female\",\r\n\t\t\"NJ/NJ_07_Male\",\r\n\t\t\"NJ/NJ_08_Female\",\r\n\t\t\"NJ/NJ_08_Male\",\r\n\t\t\"NJ/NJ_09_ALT_Female\",\r\n\t\t\"NJ/NJ_09_ALT_Male\",\r\n\t\t\"NJ/NJ_09_Female\",\r\n\t\t\"NJ/NJ_09_Male\",\r\n\t\t\"NJ/NJ_10_Female\",\r\n\t\t\"NJ/NJ_10_Male\",\r\n\t\t\"NJ/NJ_Pool_Female\",\r\n\t\t\"NJ/NJ_Pool_Male\",\r\n\t\t\"NY/NY_01V_Female\",\r\n\t\t\"NY/NY_01V_Male\",\r\n\t\t\"NY/NY_02_Female\",\r\n\t\t\"NY/NY_02_Male\",\r\n\t\t\"NY/NY_03_Female\",\r\n\t\t\"NY/NY_03_Male\",\r\n\t\t\"RU/RU_01V_Female\",\r\n\t\t\"RU/RU_01V_Male\",\r\n\t\t\"RU/RU_02_Female\",\r\n\t\t\"RU/RU_02_Male\",\r\n\t\t\"RU/RU_03B_Female\",\r\n\t\t\"RU/RU_03B_Male\",\r\n\t\t\"RU/RU_03_Female\",\r\n\t\t\"RU/RU_03_Male\",\r\n\t\t\"SD/SD_01_Female\",\r\n\t\t\"SD/SD_01_Male\",\r\n\t\t\"SD/SD_02_Female\",\r\n\t\t\"SD/SD_02_Male\",\r\n\t\t\"SD/SD_03_Female\",\r\n\t\t\"SD/SD_03_Male\",\r\n\t\t\"SJ/SJ_01A_Female\",\r\n\t\t\"SJ/SJ_01A_Male\",\r\n\t\t\"SJ/SJ_01B_Female\",\r\n\t\t\"SJ/SJ_01B_Male\",\r\n\t\t\"SJ/SJ_02_Female\",\r\n\t\t\"SJ/SJ_02_Male\",\r\n\t\t\"VC/VC_01V_Female\",\r\n\t\t\"VC/VC_01V_Male\",\r\n\t\t\"VC/VC_02_Female\",\r\n\t\t\"VC/VC_02_Male\"\r\n\t};\r\n\r\n\t// Clear the preload flag.\r\n\tmusicPreloadActive = false;\r\n\t\r\n\tfor ( uint lp = 0; lp < ( sizeof( p_filename ) / sizeof( char* )); lp++ )\r\n\t{\r\n\t\tchar *p_name = strchr( p_filename[lp], '/' );\r\n\t\tif( p_name )\r\n\t\t{\r\n\t\t\tuint32 name_checksum = Crc::GenerateCRCFromString( p_name + 1 );\r\n\t\t\tif( checksum == name_checksum )\r\n\t\t\t{\r\n\t\t\t\t// Got a match - hook up filename here....\r\n\t\t\t\tsprintf( sPreLoadMusicFilename, \"music/vag/cutscenes/%s\", p_filename[lp] );\r\n\t\t\t\treturn PCMAudio_PlayMusicTrack( sPreLoadMusicFilename, true );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tsPreLoadMusicFilename[0] = 0;\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_PreLoadMusicStreamDone( void )\r\n{\r\n\tif( musicPreloadActive )\r\n\t{\r\n\t\tif( audio_player.preFetchState )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_StartPreLoadedMusicStream( void )\r\n{\r\n\t// Maybe we should check here to make sure the checksum of the music info filestream matches that\r\n\t// passed in when the music stream preload request came in.\r\n\tif( sPreLoadMusicFilename[0] > 0 )\r\n\t{\r\n\t\t// Turn off the preload flag, which will allow decoding to start.\r\n\t\tmusicPreloadActive = false;\r\n\r\n\t\t// Call the update loop immediately.\r\n\t\tPCMAudio_DecodeLoop();\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint PCMAudio_GetStreamStatus( int whichStream )\r\n{\r\n\tif( whichStream >= NUM_STREAMS )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Checking stream status on stream %d, past valid range ( 0 to %d ).\", whichStream, NUM_STREAMS - 1 ) );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif( sPreLoadChecksum[whichStream] > 0 )\r\n\t{\r\n\t\treturn PCM_STATUS_LOADING;\r\n\t}\r\n\r\n\tif( gPcmStatus & PCMSTATUS_LOAD_STREAM( whichStream ))\r\n\t{\r\n\t\treturn PCM_STATUS_LOADING;\r\n\t}\r\n\telse if( gPcmStatus & PCMSTATUS_STREAM_PLAYING( whichStream ))\r\n\t{\r\n\t\treturn PCM_STATUS_PLAYING;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn PCM_STATUS_FREE;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PCMAudio_PauseStream( bool pause, int whichStream )\r\n{\r\n\t// Not sure how to do this yet...\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool PCMAudio_LoadStreamHeader( const char *nameOfFile )\r\n{\r\n\tif( gpStreamHed )\r\n\t{\r\n\t\tMem::Free( gpStreamHed );\r\n\t\tgpStreamHed = NULL;\r\n\t}\r\n\r\n\tgpStreamHed = File::LoadHed( nameOfFile );\r\n\r\n\tif( !gpStreamHed )\r\n\t{\r\n\t\tDbg_Message( \"Couldn't find stream header %s\\n\", nameOfFile );\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n} // namespace Pcm\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/p_music.h",
    "content": "// Audio streaming function prototypes:\r\n// mjd jan 2001\r\n\r\n#ifndef __P_MUSIC_H__\r\n#define __P_MUSIC_H__\r\n\r\n#include <dolphin.h>\r\n#include <gel/music/music.h>\r\n#include <dolphin/mix.h>\r\n\r\nnamespace Pcm\r\n{\r\n\r\n// allows one channel for music, another for audio:\r\nenum{\r\n\tEXTRA_CHANNEL,\r\n\tMUSIC_CHANNEL,\r\n};\r\n\r\n\r\n// Onetime call once upon loading the game...\r\nvoid PCMAudio_Init( void );\r\n\r\n// Call every frame to make sure music and stream buffers are loaded and current status is checked each frame...\r\nint PCMAudio_Update( void );\r\n\r\n// Load a track and start it playing...\r\n// You wanna loop a track?  Wait until this track is done, and PLAY IT AGAIN SAM!\r\nbool PCMAudio_PlayMusicTrack( const char *filename, bool preload = false );\r\nbool PCMAudio_PlayStream( uint32 checksum, int whichStream, float volumeL, float volumeR, float pitch, bool preload = false );\r\n\r\n// keep song loaded, stop playing it (or continue playing paused song)\r\nvoid PCMAudio_Pause( bool pause = true, int ch = MUSIC_CHANNEL );\r\n\r\nvoid PCMAudio_PauseStream( bool pause, int whichStream );\r\n\r\nvoid PCMAudio_StopMusic( bool waitPlease );\r\nvoid PCMAudio_StopStream( int whichStream, bool waitPlease = true );\r\nvoid PCMAudio_StopStreams( void );\r\n\r\n// Preload streams. By preloading, you can guarantee they will start at a certain time.\r\nbool PCMAudio_PreLoadStream( uint32 checksum, int whichStream );\r\nbool PCMAudio_PreLoadStreamDone( int whichStream );\r\nbool PCMAudio_StartPreLoadedStream( int whichStream, float volumeL, float volumeR, float pitch );\r\n\r\n// Preload music streams. By preloading, you can guarantee they will start at a certain time.\r\nbool PCMAudio_PreLoadMusicStream( uint32 checksum );\r\nbool PCMAudio_PreLoadMusicStreamDone( void );\r\nbool PCMAudio_StartPreLoadedMusicStream( void );\r\n\r\n// set the music volume ( 0 to 100 )\r\nint\t\tPCMAudio_SetMusicVolume( float volume );\r\nbool\tPCMAudio_SetStreamVolume( float volumeL, float volumeR, int whichStream );\r\nbool\tPCMAudio_SetStreamPitch( float pitch, int whichStream );\r\n//int PCMAudio_SetStreamVolumeAndPitch( float volumeL, float volumeR, float pitch, int whichStream );\r\n\r\nvoid PCMAudio_SetStreamGlobalVolume( unsigned int volume );\r\n\r\nenum{\r\n\tPCM_STATUS_FREE \t\t\t= ( 1 << 0 ),\r\n\tPCM_STATUS_PLAYING\t\t\t= ( 1 << 1 ),\r\n\tPCM_STATUS_LOADING \t\t\t= ( 1 << 2 ),\r\n};\r\n\r\n// Return one of the PCM_STATUS values from above...\r\nint PCMAudio_GetMusicStatus( );\r\nint PCMAudio_GetStreamStatus( int whichStream );\r\n\r\n// preload any CD location info (to avoid a hitch in framerate on PS2):\r\nunsigned int PCMAudio_GetCDLocation( const char *pTrackName );\r\n\r\nbool PCMAudio_TrackExists( const char *pTrackName, int ch );\r\nbool PCMAudio_LoadMusicHeader( const char *nameOfFile );\r\nbool PCMAudio_LoadStreamHeader( const char *nameOfFile );\r\n\r\nuint32 PCMAudio_FindNameFromChecksum( uint32 checksum, int ch );\r\n\r\n// borrow this memory for the movies and shit...\r\nint PCMAudio_GetIopMemory( void );\r\n\t\t \r\nvoid setDolby( AXPB * p_pb, AXVPB * p_vpb, float volL, float volR, unsigned int pitch = 0, bool set_pitch = false, float volume_percent = 100.0f );\r\n\r\n} // namespace PCM\r\n\r\n#endif // __P_MUSIC_H__\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/pcm/pcm.h",
    "content": "#ifndef __MODULES_PCM_PCM_H\r\n#define __MODULES_PCM_PCM_H\r\n\r\n#define NUM_STREAMS 3\r\n\r\n#define PCM_RPC_ARG_NUM_INTS 16\r\n\r\n#define DEFAULT_PITCH\t0x1000\r\n\r\n// VAG header structure\r\ntypedef struct\r\n{\r\n\tchar ID[4];\r\n\tint version;\r\n\tchar reserved1[4];\r\n\tint dataSize;\r\n\tint sampleFreq;\r\n\tchar reserved2[12];\r\n\tchar name[16];\r\n} VagHeader;\r\n\r\n#define SIZE_OF_VAGHEADER ( sizeof( VagHeader ) )\r\n\r\n// sound stuff:\r\n#define SB_BUF_SIZE ( 1024 * 32 )\t\t// hex 2000\r\n#define SB_BUF_HALF ( SB_BUF_SIZE / 2 )\t// hex 1000\r\n#define SB_BUF_SIZE_WITH_PADDING\t( SB_BUF_SIZE + 0x40 )\r\n\r\n// spu ram layout:\r\n// first valid address for use in SPU RAM\r\n#define SPU_RAM_SIZE\t\t\t\t\t0x1fffff\r\n#define SB_FIRST_USEABLE_ADDR\t\t\t0x5010\r\n\r\n//#define STRAY_VOICE_BLOCKER_SIZE\t\t128\r\n//#define STRAY_VOICE_BLOCKER_SPU_ADDR\tSB_TOP\r\n//#define STREAM_SPU_ADDR\t\t\t\t\t( STRAY_VOICE_BLOCKER_SPU_ADDR + STRAY_VOICE_BLOCKER_SIZE )\r\n#define STREAM_SPU_ADDR\t\t\t\t\tSB_FIRST_USEABLE_ADDR\r\n\r\n// slip in room for 3 streaming VAGS ( 2 for stereo music and one extra stream ):\r\n//#define SINGLE_STREAM_BUFFER_SIZE 2048\r\n#define TOTAL_SPU_REQUIRED_FOR_STREAMS\t\t( SB_BUF_SIZE_WITH_PADDING * 4 )\r\n#define MUSIC_L_SPU_BUF_LOC\t\t\t\t\t( STREAM_SPU_ADDR + 0x40 )\r\n#define MUSIC_R_SPU_BUF_LOC\t\t\t\t\t( MUSIC_L_SPU_BUF_LOC + SB_BUF_SIZE_WITH_PADDING )\r\n#define STREAM_SPU_BUF_LOC( i )\t\t\t\t( MUSIC_R_SPU_BUF_LOC + ( ( 1 + ( i ) ) * SB_BUF_SIZE_WITH_PADDING ) )\r\n\r\n#define END_OF_STREAMS\t\t\t\t\t\t( STREAM_SPU_ADDR + TOTAL_SPU_REQUIRED_FOR_STREAMS + 0x40 )\r\n\r\n//#define RAM_NEEDED_FOR_EFFECTS\t\t0\t// FUCK the effects...\r\n#define\tRAM_NEEDED_FOR_EFFECTS\t\t\t0xade0 // enough for HALL reverb\r\n//#define\tRAM_NEEDED_FOR_EFFECTS\t\t0xF6C0 // enough for space echo\r\n \r\n#define REVERB_ONLY_ON_CORE_0\t\t\t1\r\n\r\n#if !REVERB_ONLY_ON_CORE_0\r\n\r\n#define CORE_1_EFFECTS_START_ADDRESS\tEND_OF_STREAMS\r\n#define CORE_1_EFFECTS_END_ADDRESS\t\t0x02ffff // has to be on a 0xffff boundary!!\r\n#if ( ( CORE_1_EFFECTS_END_ADDRESS - CORE_1_EFFECTS_START_ADDRESS ) < RAM_NEEDED_FOR_EFFECTS )\r\n#error \"not enough space for core 0 effects!\"\r\n#endif\r\n\r\n#define BASE_WAVE_DATA_ADDR\t\t\t\tCORE_0_EFFECTS_END_ADDRESS\r\n\r\n#else\r\n#define BASE_WAVE_DATA_ADDR\t\t\t\tEND_OF_STREAMS\r\n#endif\r\n\r\n#define CORE_0_EFFECTS_START_ADDRESS\t( SPU_RAM_SIZE - RAM_NEEDED_FOR_EFFECTS )\r\n#define CORE_0_EFFECTS_END_ADDRESS\t\t( SPU_RAM_SIZE )\r\n#define END_WAVE_DATA_ADDR\t\t\t\t( CORE_0_EFFECTS_START_ADDRESS  - 0x40 )\r\n\r\n// used by temporary sounds and permanently loaded sounds...\r\n#define MAX_SPU_RAM_AVAILABLE\t\t\t( END_WAVE_DATA_ADDR - BASE_WAVE_DATA_ADDR )\r\n\r\n//#define MUSIC_R_SPU_BUF_LOC\t\tSB_TOP\r\n//#define MUSIC_L_SPU_BUF_LOC\t\t( MUSIC_R_SPU_BUF_LOC + SB_BUF_SIZE )\r\n//#define STREAM_SPU_BUF_LOC\t\t( MUSIC_L_SPU_BUF_LOC + SB_BUF_SIZE )\r\n\r\n// iop buffer taking streams off of the CD:\r\n#define MUSIC_IOP_BUFFER_SIZE\t\t\t\t( 1024 * 192 )  // must be a multiple of 4k!\r\n#define MUSIC_HALF_IOP_BUFFER_SIZE\t\t\t( MUSIC_IOP_BUFFER_SIZE / 2 )  // must be a multiple of 2k!\r\n#define STREAM_IOP_BUFFER_SIZE\t\t\t\t( 1024 * /*128*/64 )  // must be a multiple of 4k!\r\n#define STREAM_HALF_IOP_BUFFER_SIZE\t\t\t( STREAM_IOP_BUFFER_SIZE / 2 )  // must be a multiple of 2k!\r\n\r\n// must match values in pcm_com.c!!!\r\n#define TOTAL_IOP_BUFFER_SIZE_NEEDED\t\t( ( MUSIC_IOP_BUFFER_SIZE * 2 ) + ( STREAM_IOP_BUFFER_SIZE * NUM_STREAMS ) )\r\n#define ALLIGN_REQUIREMENT\t\t\t\t\t64\r\n#define SECTOR_SIZE\t\t\t\t\t\t\t( 2048 )\r\n#define NUM_SECTORS_PER_STREAM_BUFFER\t\t( STREAM_IOP_BUFFER_SIZE / SECTOR_SIZE )\r\n#define NUM_SECTORS_PER_STREAM_HALF_BUFFER\t( NUM_SECTORS_PER_STREAM_BUFFER / 2 )\r\n#define NUM_SECTORS_PER_MUSIC_BUFFER\t\t( MUSIC_IOP_BUFFER_SIZE / SECTOR_SIZE )\r\n#define NUM_SECTORS_PER_MUSIC_HALF_BUFFER\t( NUM_SECTORS_PER_MUSIC_BUFFER / 2 )\r\n\r\n#define MUSIC_L_IOP_OFFSET\t0\r\n#define MUSIC_R_IOP_OFFSET\t( MUSIC_HALF_IOP_BUFFER_SIZE )  // interwoven with the L IOP buffer... and shit\r\n#define STREAM_IOP_OFFSET( ch )\t\t\t\t( ( 2 * MUSIC_IOP_BUFFER_SIZE ) + ( STREAM_IOP_BUFFER_SIZE * ( ch ) ) )\r\n\r\n#define MUSIC_L_VOICE\t22\r\n#define MUSIC_R_VOICE\t23\r\n#define MUSIC_CORE\t\t1\r\n\r\n#define STREAM_VOICE( i ) ( 23 - ( i ) )\r\n#define STREAM_CORE\t\t0\r\n\r\n// RPC command:\r\n#define EzADPCM_COMMAND_MASK\t\t\t0xfff0\r\n#define EzADPCM_CH_MASK\t\t\t\t\t0x000f\r\n\t\r\n#define EzADPCM_INIT\t\t\t\t\t0x0000\r\n#define EzADPCM_QUIT\t\t\t\t\t0x0010\r\n#define EzADPCM_PLAYMUSIC\t\t\t\t0x0020\r\n#define EzADPCM_STOPMUSIC\t\t\t\t0x0030\r\n#define EzADPCM_PLAYSTREAM\t\t\t\t0x0040\r\n#define EzADPCM_STOPSTREAM\t\t\t\t0x0070\r\n#define EzADPCM_STOPSTREAMS\t\t\t\t0x00a0\r\n#define EzADPCM_SETMUSICVOL\t\t\t\t0x00b0\r\n#define EzADPCM_SETSTREAMVOL\t\t\t0x00c0\r\n#define EzADPCM_SETSTREAMVOLANDPITCH\t0x00d0\r\n#define EzADPCM_GETSTATUS\t\t\t\t0x00e0\r\n#define EzADPCM_GETMUSICSTATUS\t\t\t0x00f0\r\n#define EzADPCM_PAUSEMUSIC\t\t\t\t0x0100\r\n#define EzADPCM_PAUSESTREAM\t\t\t\t0x0110\r\n#define EzADPCM_PAUSESTREAMS\t\t\t0x0120\r\n#define EzADPCM_SETSTREAMGLOBVOL\t\t0x0130\r\n#define EzADPCM_SDINIT\t\t\t\t\t0x7ff0\r\n\r\n// for GETSTREAMSTATUS or GETMUSICSTATUS:\r\n#define PCM_STATUS\t\t\t\t\t0x0001f000\r\n#define PCM_STATUS_IDLE\t\t   \t\t0x00000000\r\n#define PCM_STATUS_PRELOAD\t\t\t0x00001000\r\n#define PCM_STATUS_READY_TO_STOP\t0x00002000\r\n#define PCM_STATUS_NEED_UPDATE\t\t0x00003000\r\n#define PCM_STATUS_RUNNING\t\t\t0x00005000\r\n#define PCM_STATUS_TERMINATE\t\t0x00006000\r\n\r\n// flags for GETSTATUS\r\n#define PCMSTATUS_NEED_MUSIC_BUFFER_0\t( 1 << 0 )\r\n#define PCMSTATUS_NEED_MUSIC_BUFFER_1\t( 1 << 1 )\r\n#define PCMSTATUS_NEED_STREAM0_BUFFER_0\t( 1 << 2 ) // don't change the order of these!!! IMPORTANT!\r\n#define PCMSTATUS_NEED_STREAM1_BUFFER_0\t( 1 << 3 )\r\n#define PCMSTATUS_NEED_STREAM2_BUFFER_0\t( 1 << 4 )\r\n#define PCMSTATUS_NEED_STREAM0_BUFFER_1\t( 1 << 5 )\r\n#define PCMSTATUS_NEED_STREAM1_BUFFER_1\t( 1 << 6 )\r\n#define PCMSTATUS_NEED_STREAM2_BUFFER_1\t( 1 << 7 )\r\n#define PCMSTATUS_MUSIC_PLAYING\t\t\t( 1 << 8 )\r\n#define PCMSTATUS_STREAM0_PLAYING\t\t( 1 << 9 )\r\n#define PCMSTATUS_STREAM1_PLAYING\t\t( 1 << 10 )\r\n#define PCMSTATUS_STREAM2_PLAYING\t\t( 1 << 11 )\r\n#define PCMSTATUS_LOAD_MUSIC\t\t\t( 1 << 12 )\r\n#define PCMSTATUS_LOAD_STREAM0\t\t\t( 1 << 13 )\r\n#define PCMSTATUS_LOAD_STREAM1\t\t\t( 1 << 14 )\r\n#define PCMSTATUS_LOAD_STREAM2\t\t\t( 1 << 15 )\r\n#define PCMSTATUS_INITIALIZED\t\t\t( 1 << 16 )\r\n\r\n// macros:\r\n#define PCMSTATUS_NEED_STREAM_BUFFER_0( xxx )\t( PCMSTATUS_NEED_STREAM0_BUFFER_0 << ( xxx ) )\r\n#define PCMSTATUS_NEED_STREAM_BUFFER_1( xxx )\t( PCMSTATUS_NEED_STREAM0_BUFFER_1 << ( xxx ) )\r\n#define PCMSTATUS_STREAM_PLAYING( xxx )\t\t\t( PCMSTATUS_STREAM0_PLAYING << ( xxx ) )\r\n#define PCMSTATUS_LOAD_STREAM( xxx )\t\t\t( PCMSTATUS_LOAD_STREAM0 << ( xxx ) )\r\n// Module ID number\r\n#define EzADPCM_DEV 0x00012345\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n#endif // __MODULES_PCM_PCM_H\r\n/* DON'T ADD STUFF AFTER THIS */\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/pcm/pcm_com.c",
    "content": "/* Vag streaming into SPU2 -- from sony sample -- matt may 2001 */\r\n\r\n#include <kernel.h>\r\n#include <sys/types.h>\r\n#include <sys/file.h>\r\n#include <stdio.h>\r\n#include <string.h>\r\n#include <sif.h>\r\n#include <sifcmd.h>\r\n#include <sifrpc.h>\r\n#include <libsd.h>\r\n#include <thread.h>\r\n#include \"pcm.h\"\r\n#include \"pcmiop.h\"\r\n\r\n// ================================================================\r\n#define DATA_INTEGRITY_CHECK 1\r\n\r\n#define SHOW_STATE\t0\r\n#define SHOW_SMALL_STATE 1\r\n#define SHOW_ACTION 0\r\n#define SHOW_SMALL_ACTION 1\r\n#define DBUGPRINTF\t0\r\n#define SHOW_TIMING\t1\r\n#define SHOW_STOP\t1\r\n#define SHOW_SMALL_COMMANDS\t1\r\n\r\n#if SHOW_SMALL_COMMANDS\r\n#define ShowSmallCommand printf\r\n#else\r\n#define ShowSmallCommand( x )\r\n#endif\r\n\r\n#if SHOW_STOP\r\n#define ShowStop printf   //printf( \" %d}{\", GetTime( ) ), printf\r\n#else\r\n#define ShowStop( x )\r\n#endif\r\n\r\n#if SHOW_TIMING\r\n#define ShowTime\tprintf\r\n#else\r\n#define ShowTime DoNothing\r\nvoid DoNothing( char* text, ... ) { }\r\n#endif\r\n\r\n#if SHOW_ACTION\r\n#define ShowAction printf( \"Time %d\", GetTime( ) ), printf\r\n#else\r\n#define ShowAction( x )\r\n#endif\r\n\r\n#if SHOW_SMALL_STATE\r\n#define SmallShowState printf\r\n#else\r\n#define SmallShowState( x )\r\n#endif\r\n\r\n#if SHOW_SMALL_ACTION\r\n#define SmallShowAction printf( \" %d*\", GetTime( ) ), printf\r\n#else\r\n#define SmallShowAction( x )\r\n#endif\r\n\r\n#if SHOW_STATE\r\n#define ShowState printf( \"Time %d                  \", GetTime( ) ), printf\r\n#else\r\n#define ShowState( x )\r\n#endif\r\n\r\n#if DBUGPRINTF\r\n#define Dbug_Printf( x ) printf( x )\r\n#else\r\n#define Dbug_Printf( x )\r\n#endif\r\n\r\n//volatile int gTestPause = 0;\r\n\r\n#define SHARE_DMA_CH\t0\r\n\r\n// the program running on the EE side will check to see if any of the buffers need to be filled:\r\nvolatile unsigned int gEECommand = 0;\r\n\r\n#if SHARE_DMA_CH\r\n#define TRANS_DMA_CH_COMMON\t\t0\r\n#define TRANS_DMA_CH_MUSIC\t\tTRANS_DMA_CH_COMMON\r\n#define TRANS_DMA_CH_STREAM\t\tTRANS_DMA_CH_COMMON\r\n\r\nenum{\r\n\tLOAD_STATUS_IDLE = \t\t\t\t0,\r\n\tLOAD_STATUS_LOADING_MUSIC =\t\t( 1 << 0 ),\r\n\tLOAD_STATUS_LOADING_STREAM = \t( 1 << 1 ),\r\n\tLOAD_STATUS_NEED_MUSIC =\t\t( 1 << 2 ),\r\n\tLOAD_STATUS_NEED_STREAM =\t\t( 1 << 3 ),\r\n};\r\n\r\nvolatile unsigned int gLoadStatus = LOAD_STATUS_IDLE;\r\n\r\n#else\r\n#define TRANS_DMA_CH_MUSIC\t\t1\r\n#define TRANS_DMA_CH_STREAM\t\t0\r\n#endif\r\n\r\n\r\n#define _1st 0\r\n#define _2nd 1\r\n\r\n#define DEFAULT_PITCH\t0x1000\r\n\r\nunsigned int gThid = 0;\r\nunsigned int gSem = 0;\r\nunsigned int gpIopBuf;\t\t// IOP SMEM\r\nunsigned int gMusicIopOffset;\r\nunsigned int gStreamIopOffset;\r\n\r\nenum{\r\n\tMUSIC_LOAD_STATE_IDLE,\r\n\tMUSIC_LOAD_STATE_PRELOADING_L,\r\n\tMUSIC_LOAD_STATE_PRELOADING_R,\r\n\tMUSIC_LOAD_STATE_WAITING_FOR_IRQ,\r\n\tMUSIC_LOAD_STATE_LOADING_L,\r\n\tMUSIC_LOAD_STATE_LOADING_R,\r\n};\r\n\r\nvolatile unsigned int gMusicPaused = 0;\r\nvolatile unsigned int gStreamPaused = 0;\r\nvolatile unsigned int gStreamTimeOffset = 0;  // when paused, keep track of time passed since last IRQ\r\nvolatile unsigned int gMusicTimeOffset = 0;   // when paused, keep track of time passed since last IRQ\r\n\r\n#define RF_START_MUSIC\t\t\t( 1 << 0 )\r\n#define RF_START_STREAM\t\t\t( 1 << 1 )\r\n#define RF_UNPAUSE_MUSIC\t\t( 1 << 2 )\r\n#define RF_UNPAUSE_STREAM\t\t( 1 << 3 )\r\n\r\nvolatile unsigned int gRequestFlags = 0;\r\n\r\nvolatile unsigned int gTimeOfLastMusicUpdate = 0;\r\nvolatile unsigned int gTimeOfLastStreamUpdate = 0;\r\n\r\nvolatile unsigned int gMusicBufSide = _1st;\r\nvolatile unsigned int gMusicTransSize = 0;\r\nvolatile unsigned int gMusicLoadState = MUSIC_LOAD_STATE_IDLE;\r\nvolatile unsigned int gMusicVolume;\r\nvolatile unsigned int gMusicVolumeSet = 0;\r\nvolatile unsigned int gMusicStop = 0;\r\nvolatile unsigned int gMusicStatus = EzADPCM_STATUS_IDLE;\r\nvolatile unsigned int gUpdateMusic = 0;\r\nvolatile unsigned int gMusicSize;\r\nvolatile unsigned int gMusicRemaining;\r\n\r\nenum{\r\n\tSTREAM_LOAD_STATE_IDLE,\r\n\tSTREAM_LOAD_STATE_PRELOADING,\r\n\tSTREAM_LOAD_STATE_WAITING_FOR_IRQ,\r\n\tSTREAM_LOAD_STATE_LOADING,\r\n};\r\n\r\n\r\nvolatile unsigned int gStreamBufSide = _1st;\r\nvolatile unsigned int gStreamTransSize = 0;\r\nvolatile unsigned int gStreamLoadState = STREAM_LOAD_STATE_IDLE;\r\nvolatile unsigned int gStreamVolume;\r\nvolatile unsigned int gStreamVolumeSet = 0;\r\nvolatile unsigned int gStreamStop = 0;\r\nvolatile unsigned int gStreamStatus = EzADPCM_STATUS_IDLE;\r\nvolatile unsigned int gUpdateStream = 0;\r\nvolatile unsigned int gStreamSize;\r\nvolatile unsigned int gStreamRemaining;\r\n\r\nint _AdpcmPlay( int status );\r\n\r\n#if SHARE_DMA_CH\r\nstatic int _AdpcmDmaIntCommon( int, void* );\r\n#else\r\nstatic int _AdpcmDmaIntMusic( int, void* );\r\nstatic int _AdpcmDmaIntStream( int, void* );\r\n#endif\r\nstatic int _AdpcmSpu2Int( int, void * );\r\n\r\n#define _L 0\r\n#define _R 1\r\n#define _Lch(x) ((x >> 16) & 0xffff)\r\n#define _Rch(x) (x & 0xffff)\r\n\r\nunsigned int GetTime( void )\r\n{\r\n\tunsigned int sex, usex, msex;\r\n\tstruct SysClock sysClock;\r\n\tGetSystemTime( &sysClock );\r\n\tSysClock2USec( &sysClock, &sex, &usex );\r\n\tmsex = ( sex * 1000 ) + ( usex / 1000 );\r\n\treturn ( msex );\r\n}\r\n\r\n// EzADPCM_SDINIT\r\nvoid AdpcmSdInit( void )\r\n{\r\n    sceSdInit (0);\r\n\r\n    //\tDisk media: DVD\r\n    //\tOutput format: PCM\r\n    //\tCopy guard: normal (one generation recordable / default)\r\n    sceSdSetCoreAttr (SD_C_SPDIF_MODE, (SD_SPDIF_MEDIA_DVD |\r\n\t\t\t\t\tSD_SPDIF_OUT_PCM   |\r\n\t\t\t\t\tSD_SPDIF_COPY_NORMAL));\r\n    return;\r\n}\r\n\r\nvoid AdpcmSetUpVoice( int core, int vnum, int pSpuBuf )\r\n{\r\n    sceSdSetParam ( core | ( vnum << 1 ) | SD_VP_VOLL, 0 );\r\n    sceSdSetParam ( core | ( vnum << 1 ) | SD_VP_VOLR, 0 );\r\n    sceSdSetParam ( core | ( vnum << 1 ) | SD_VP_PITCH, DEFAULT_PITCH );\r\n    sceSdSetParam ( core | ( vnum << 1 ) | SD_VP_ADSR1, 0x000f );\r\n    sceSdSetParam ( core | ( vnum << 1 ) | SD_VP_ADSR2, 0x1fc0 );\r\n    sceSdSetAddr  ( core | ( vnum << 1 ) | SD_VA_SSA,  pSpuBuf );\r\n    return;\r\n}\r\n\r\n/*const char StrayVoiceData[ STRAY_VOICE_BLOCKER_SIZE ] =\r\n{\r\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n\t0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n\t0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n\t0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n\t0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n\t0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n\t0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n\t0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n};*/\r\n\r\n// EzADPCM_INIT\r\nint AdpcmInit( int pIopBuf )\r\n{\r\n\tif ( gEECommand & PCMSTATUS_INITIALIZED )\r\n\t{\r\n\t\treturn ( 0 );\r\n\t}\r\n\r\n    if ( gSem == 0 )\r\n\t{\r\n\t\tstruct SemaParam sem;\r\n\t\tsem.initCount = 0;\r\n\t\tsem.maxCount = 1;\r\n\t\tsem.attr = AT_THFIFO;\r\n\t\tgSem = CreateSema (&sem);\r\n    }\r\n    if (gThid == 0)\r\n\t{\r\n\t\tstruct ThreadParam param;\r\n\t\tparam.attr         = TH_C;\r\n\t\tparam.entry        = _AdpcmPlay;\r\n\t\tparam.initPriority = 5;// BASE_priority-3;\r\n\t\tparam.stackSize    = 0x800; // was 800\r\n\t\tparam.option = 0;\r\n\t\tgThid = CreateThread (&param);\r\n\t\tprintf( \"EzADPCM: create thread ID= %d\\n\", gThid );\r\n\t\tStartThread (gThid, (u_long) NULL);\r\n    }\r\n\t\r\n/*\r\n\t// This data represents an empty looping sound...\r\n\t// The voices wandering across SPU ram will get\r\n\t// stuck here, so as not to trigger the interrupts\r\n\t// reserved for the stream and music voices and shit.\r\n\tstrcpy( ( char * )pIopBuf, StrayVoiceData );\r\n\t// send that to the SPU ram:\r\n\tsceSdVoiceTrans( 0, ( SD_TRANS_MODE_WRITE | SD_TRANS_BY_DMA ),\r\n\t\t(unsigned char *) pIopBuf, STRAY_VOICE_BLOCKER_SPU_ADDR, STRAY_VOICE_BLOCKER_SIZE );\r\n\tsceSdVoiceTransStatus( 0, SD_TRANS_STATUS_WAIT );*/\r\n\t\t\r\n#if SHARE_DMA_CH\r\n\tsceSdSetTransIntrHandler( TRANS_DMA_CH_COMMON, ( sceSdTransIntrHandler ) _AdpcmDmaIntCommon, ( void * ) &gSem );\r\n#else\r\n\tsceSdSetTransIntrHandler( TRANS_DMA_CH_MUSIC, ( sceSdTransIntrHandler ) _AdpcmDmaIntMusic, ( void * ) &gSem );\r\n    sceSdSetTransIntrHandler( TRANS_DMA_CH_STREAM, ( sceSdTransIntrHandler ) _AdpcmDmaIntStream, ( void * ) &gSem );\r\n#endif\r\n    sceSdSetSpu2IntrHandler( ( sceSdSpu2IntrHandler ) _AdpcmSpu2Int, ( void * ) &gSem );\r\n\r\n\tAdpcmSetUpVoice( MUSIC_CORE, MUSIC_L_VOICE, MUSIC_L_SPU_BUF_LOC );\r\n\tAdpcmSetUpVoice( MUSIC_CORE, MUSIC_R_VOICE, MUSIC_R_SPU_BUF_LOC );\r\n\tAdpcmSetUpVoice( STREAM_CORE, STREAM_VOICE, STREAM_SPU_BUF_LOC );\r\n\r\n\tgpIopBuf = pIopBuf;\r\n\tgEECommand |= PCMSTATUS_INITIALIZED;\r\n\t//printf( \"PCM Irx iop buf %d\\n\", gpIopBuf );\r\n\t//Dbug_Printf( \"PCM irx is initialized\\n\" );\r\n    return gThid;\r\n}\r\n\r\n// EzADPCM_QUIT\r\nvoid AdpcmQuit( void )\r\n{\r\n    DeleteThread (gThid);\r\n    gThid = 0;\r\n#if 0\r\n    DeleteSema (gSem);\r\n    gSem = 0;\r\n#endif\r\n    return;\r\n}\r\n\r\n// EzADPCM_PLAYMUSIC\r\nint AdpcmPlayMusic( int size )\r\n{\r\n    extern void AdpcmSetMusicVolumeDirect( unsigned int );\r\n\r\n    if ( gMusicStatus != EzADPCM_STATUS_IDLE )\r\n\t{\r\n\t\tShowAction( \"NOTE NOTE NOTE NOTE Can't play music -- music isn't in Idle state.\\n\" );\r\n\t\treturn -1;\r\n    }\r\n\r\n    AdpcmSetMusicVolumeDirect( gMusicVolume );\r\n\t\t\t\t\r\n\tgMusicStatus = EzADPCM_STATUS_PRELOAD;\r\n\tgMusicLoadState = MUSIC_LOAD_STATE_IDLE;\r\n\tgMusicSize = size;\r\n\tgMusicTimeOffset = 0;\r\n\tif ( gMusicSize < 64 )\r\n\t{\r\n\t\tgMusicSize = 64;\r\n\t}\r\n\tgEECommand &= ~( PCMSTATUS_NEED_MUSIC_BUFFER_0 | PCMSTATUS_NEED_MUSIC_BUFFER_1 );\r\n\tgEECommand |= PCMSTATUS_MUSIC_PLAYING;\r\n\r\n\t// stagger the two streams so there are no IRQ or DMA interrupt conflicts:\r\n\tgRequestFlags |= RF_START_MUSIC;\r\n    return 0;\r\n}\r\n\r\n// EzADPCM_PLAYSTREAM\r\nint AdpcmPlayStream( int size )\r\n{\r\n    extern void AdpcmSetStreamVolumeDirect( unsigned int );\r\n\r\n    if ( gStreamStatus != EzADPCM_STATUS_IDLE )\r\n\t{\r\n\t\tprintf( \"trying to play stream when stream already playing!\\n\" );\r\n\t\treturn -1;\r\n    }\r\n\r\n    AdpcmSetStreamVolumeDirect( gStreamVolume );\r\n\r\n\tgStreamStatus = EzADPCM_STATUS_PRELOAD;\r\n\tgStreamSize = size;\r\n\tif ( gStreamSize < 64 )\r\n\t{\r\n\t\tgStreamSize = 64;\r\n\t}\r\n\tgStreamLoadState = STREAM_LOAD_STATE_IDLE;\r\n\tgEECommand &= ~( PCMSTATUS_NEED_STREAM_BUFFER_0 | PCMSTATUS_NEED_STREAM_BUFFER_1 );\r\n\tgEECommand |= PCMSTATUS_STREAM_PLAYING;\r\n\tgStreamTimeOffset = 0;\r\n\tgRequestFlags = RF_START_STREAM;\r\n\tShowAction( \"Requesting stream start\\n\" );\r\n    SmallShowAction( \"-rsb\" );\r\n\treturn 0;\r\n}\r\n\r\n/* internal */\r\nvoid _AdpcmSetMusicVoiceMute( void )\r\n{\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_L_VOICE << 1) | SD_VP_VOLL, 0);\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_L_VOICE << 1) | SD_VP_VOLR, 0);\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_R_VOICE << 1) | SD_VP_VOLL, 0);\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_R_VOICE << 1) | SD_VP_VOLR, 0);\r\n    return;\r\n}\r\n\r\n/* internal */\r\nvoid _AdpcmSetStreamVoiceMute( void )\r\n{\r\n    sceSdSetParam( STREAM_CORE | ( STREAM_VOICE << 1) | SD_VP_VOLL, 0);\r\n    sceSdSetParam( STREAM_CORE | ( STREAM_VOICE << 1) | SD_VP_VOLR, 0);\r\n    return;\r\n}\r\n\r\nvoid StopMusic( void )\r\n{\r\n\tsceSdSetCoreAttr( MUSIC_CORE | SD_C_IRQ_ENABLE, 0 );\r\n\tgMusicStatus = EzADPCM_STATUS_IDLE;\r\n\tgEECommand &= ~( PCMSTATUS_MUSIC_PLAYING | PCMSTATUS_NEED_MUSIC_BUFFER_0 | PCMSTATUS_NEED_MUSIC_BUFFER_1 );\r\n\t_AdpcmSetMusicVoiceMute( );\r\n\tsceSdSetSwitch( MUSIC_CORE | SD_S_KOFF, ( 1 << MUSIC_L_VOICE ) );\r\n\tsceSdSetSwitch( MUSIC_CORE | SD_S_KOFF, ( 1 << MUSIC_R_VOICE ) );\r\n\tShowAction( \"Stopping music\\n\" );\r\n    SmallShowAction( \"-!sm!\" );\r\n}\r\n\r\nvoid StopStream( void )\r\n{\r\n\tsceSdSetCoreAttr( STREAM_CORE | SD_C_IRQ_ENABLE, 0 );\r\n\tgStreamStatus = EzADPCM_STATUS_IDLE;\r\n\tgEECommand &= ~( PCMSTATUS_STREAM_PLAYING | PCMSTATUS_NEED_STREAM_BUFFER_0 | PCMSTATUS_NEED_STREAM_BUFFER_1 );\r\n\t_AdpcmSetStreamVoiceMute( );\r\n\tsceSdSetSwitch( STREAM_CORE | SD_S_KOFF, ( 1 << STREAM_VOICE ) );\r\n\tShowAction( \"Stopping stream\\n\" );\r\n    SmallShowAction( \"-!ss!\" );\r\n}\r\n\r\n#define NUM_WAIT_CLICKS 25000\r\n\r\n// EzADPCM_STOPMUSIC\r\nint AdpcmStopMusic( void )\r\n{\r\n\tint i;\r\n\tint j = 0;\r\n\r\n\tif ( gMusicStatus != EzADPCM_STATUS_IDLE )\r\n\t{\r\n\t\tif ( gRequestFlags & RF_START_MUSIC )\r\n\t\t{\r\n\t\t\tgRequestFlags &= ~RF_START_MUSIC;\r\n\t\t\tgMusicStatus = EzADPCM_STATUS_IDLE;\r\n\t\t\tShowAction( \"Supressing music request\\n\" );\r\n\t\t\tSmallShowAction( \"-smr\" );\r\n\t\t}\r\n\t\telse if ( gMusicPaused )\r\n\t\t{\r\n\t\t\t// if loading is happening, wait then just stop:\r\n\t\t\tShowStop( \"stop music %d\", GetTime( ) );\r\n\t\t\twhile ( gMusicLoadState != MUSIC_LOAD_STATE_WAITING_FOR_IRQ )\r\n\t\t\t{\r\n\t\t\t\tfor ( i = 0; i < NUM_WAIT_CLICKS; i++ )\r\n\t\t\t\t\t;\r\n\t\t\t\tj++;\r\n\t\t\t\tif ( j > NUM_WAIT_CLICKS )\r\n\t\t\t\t{\r\n\t\t\t\t\tj = 0;\r\n\t\t\t\t\tShowStop( \".\" );\r\n\t\t\t\t}\r\n\t\t\t}\r\n//\t\t\tShowStop( \"\\n\" );\r\n\t\t\tShowAction( \"Stopped paused music\\n\" );\r\n\t\t\tSmallShowAction( \"-spm\" );\r\n\t\t\tStopMusic( );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tShowStop( \" %d-stopmusic\", GetTime( ) );\r\n\t\t\tgMusicStop++;\r\n\t\t\twhile ( gMusicStatus != EzADPCM_STATUS_IDLE )\r\n\t\t\t{\r\n\t\t\t\tfor ( i = 0; i < NUM_WAIT_CLICKS; i++ )\r\n\t\t\t\t\t;\r\n\t\t\t\tif ( j++ > NUM_WAIT_CLICKS )\r\n\t\t\t\t{\r\n\t\t\t\t\tj = 0;\r\n\t\t\t\t\tShowStop( \".\" );\r\n\t\t\t\t\t//printf( \" ms %d mls %d rf %d eecom %d\\n\", gMusicStatus, gMusicLoadState, gRequestFlags, gEECommand );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t//ShowStop( \"\\n\" );\r\n\t\t}\r\n\t\tgEECommand &= ~ ( PCMSTATUS_MUSIC_PLAYING | PCMSTATUS_NEED_MUSIC_BUFFER_0 | PCMSTATUS_NEED_MUSIC_BUFFER_1 );\r\n\t\treturn ( 1 );\r\n    }\r\n\treturn ( 0 );\r\n}\r\n\r\n// EzADPCM_STOPSTREAM\r\nint AdpcmStopStream( void )\r\n{\r\n\tint i;\r\n\tint j = 0;\r\n\r\n\tif ( gStreamStatus != EzADPCM_STATUS_IDLE )\r\n\t{\r\n\t\tif ( gRequestFlags & RF_START_STREAM )\r\n\t\t{\r\n\t\t\tgRequestFlags &= ~RF_START_STREAM;\r\n\t\t\tgStreamStatus = EzADPCM_STATUS_IDLE;\r\n\t\t\tShowAction( \"Supressing stream request\\n\" );\r\n\t\t\tSmallShowAction( \"-ssr\" );\r\n\t\t}\r\n\t\telse if ( gStreamPaused )\r\n\t\t{\r\n\t\t\t// if loading is happening, wait then just stop:\r\n\t\t\tShowStop( \" %d-Stop p stream\", GetTime( ) );\r\n\t\t\twhile ( gStreamLoadState != STREAM_LOAD_STATE_WAITING_FOR_IRQ )\r\n\t\t\t{\r\n\t\t\t\tfor ( i = 0; i < NUM_WAIT_CLICKS; i++ )\r\n\t\t\t\t\t;\r\n\t\t\t\tShowStop( \".\" );\r\n\t\t\t}\r\n\t\t\t//ShowStop( \"\\n\" );\r\n\t\t\tStopStream( );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tShowStop( \" %d-Stop stream\", GetTime( ) );\r\n\t\t\tgStreamStop++;\r\n\t\t\twhile ( gStreamStatus != EzADPCM_STATUS_IDLE )\r\n\t\t\t{\r\n\t\t\t\tfor ( i = 0; i < NUM_WAIT_CLICKS; i++ )\r\n\t\t\t\t\t;\r\n\t\t\t\tif ( j++ > NUM_WAIT_CLICKS )\r\n\t\t\t\t{\r\n\t\t\t\t\tShowStop( \".\" );\r\n//\t\t\t\t\tprintf( \" ss %x sls %d rf %d eecom %d\\n\", gStreamStatus, gStreamLoadState, gRequestFlags, gEECommand );\r\n\t\t\t\t\tj = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t//ShowStop( \"\\n\" );\r\n\t\t\tSmallShowAction( \"-ss\" );\r\n\t\t\tShowAction( \"Stopped stream\\n\" );\r\n\t\t}\r\n\t\tgEECommand &= ~ ( PCMSTATUS_STREAM_PLAYING | PCMSTATUS_NEED_STREAM_BUFFER_0 | PCMSTATUS_NEED_STREAM_BUFFER_1 );\r\n\t\treturn ( 1 );\r\n    }\r\n\treturn ( 0 );\r\n}\r\n\r\n// EzADPCM_SETMUSICVOL\r\nvoid AdpcmSetMusicVolume( unsigned int vol )\r\n{\r\n    gMusicVolumeSet = 1;\r\n    gMusicVolume = vol;\r\n    return;\r\n}\r\n\r\n// EzADPCM_SETMUSICVOLDIRECT\r\nvoid AdpcmSetMusicVolumeDirect( unsigned int vol )\r\n{\r\n    gMusicVolume = vol;\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_L_VOICE << 1 ) | SD_VP_VOLL, vol );\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_L_VOICE << 1 ) | SD_VP_VOLR, 0 );\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_R_VOICE << 1 ) | SD_VP_VOLL, 0 );\r\n    sceSdSetParam ( MUSIC_CORE | ( MUSIC_R_VOICE << 1 ) | SD_VP_VOLR, vol );\r\n    return;\r\n}\r\n\r\n// EzADPCM_SETSTREAMVOL\r\nvoid AdpcmSetStreamVolume( unsigned int vol )\r\n{\r\n    gStreamVolumeSet = 1;\r\n    gStreamVolume = vol;\r\n    return;\r\n}\r\n\r\n// EzADPCM_SETSTREAMVOLDIRECT\r\nvoid AdpcmSetStreamVolumeDirect( unsigned int vol )\r\n{\r\n    gStreamVolume = vol;\r\n    sceSdSetParam ( STREAM_CORE | ( STREAM_VOICE << 1 ) | SD_VP_VOLL, _Lch( vol ) );\r\n    sceSdSetParam ( STREAM_CORE | ( STREAM_VOICE << 1 ) | SD_VP_VOLR, _Rch( vol ) );\r\n    return;\r\n}\r\n\r\n// Shouldn't need these unless debugging or something --\r\n// Instead just get gEECommand each frame and act accordingly.\r\n\r\n// EzADPCM_GETMUSICSTATUS\r\nunsigned int AdpcmGetMusicStatus( void )\r\n{\r\n\treturn gMusicStatus;\r\n}\r\n\r\n// EzADPCM_GETSTREAMSTATUS\r\nunsigned int AdpcmGetStreamStatus( void )\r\n{\r\n    return gStreamStatus;\r\n}\r\n\r\n// actual time 300 ms across one buffer (600ms across double buffer)\r\n#define SINGLE_BUFFER_MS\t300\r\n#define MIN_INTERRUPT_SEPARATION_MS\t\t90\r\n#define MAX_MS_BETWEEN_STREAMS\t\t\t( SINGLE_BUFFER_MS - MIN_INTERRUPT_SEPARATION_MS )\r\n#define MIN_MS_BETWEEN_STREAMS\t\t\t( MIN_INTERRUPT_SEPARATION_MS )\r\n\r\nint SafeForStreamToGo( unsigned int time )\r\n{\r\n\tif ( gMusicStatus == EzADPCM_STATUS_IDLE )\r\n\t{\r\n\t\tSmallShowState( \"[ss]\" );\r\n\t\treturn ( 1 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttime -= gStreamTimeOffset;\r\n\t\tif ( gMusicPaused )\r\n\t\t{\r\n\t\t\tif ( time > gMusicPaused + MIN_MS_BETWEEN_STREAMS )\r\n\t\t\t{\r\n\t\t\t\tSmallShowState( \"[ss0]\" );\r\n\t\t\t\treturn ( 1 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tint musicMod;\r\n\t\t\tint streamMod;\r\n\t\t\tmusicMod = gTimeOfLastMusicUpdate % SINGLE_BUFFER_MS;\r\n\t\t\tstreamMod = time % SINGLE_BUFFER_MS;\r\n\t\t\tif ( musicMod > streamMod )\r\n\t\t\t{\r\n\t\t\t\tif ( ( musicMod - streamMod > MIN_MS_BETWEEN_STREAMS ) &&\r\n\t\t\t\t\t( ( ( streamMod + SINGLE_BUFFER_MS ) - musicMod ) > MIN_MS_BETWEEN_STREAMS ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tSmallShowState( \"[ss1]\" );\r\n\t\t\t\t\treturn ( 1 );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( ( streamMod - musicMod > MIN_MS_BETWEEN_STREAMS ) &&\r\n\t\t\t\t\t( ( ( musicMod + SINGLE_BUFFER_MS ) - streamMod ) > MIN_MS_BETWEEN_STREAMS ) )\r\n\t\t\t{\r\n\t\t\t\tSmallShowState( \"[ss2]\" );\r\n\t\t\t\treturn ( 1 );\r\n\t\t\t}\r\n\t\t}\r\n/*\t\t\r\n\t\telse if ( ( time > gTimeOfLastMusicUpdate + MIN_MS_BETWEEN_STREAMS ) &&\r\n\t\t\t ( time < gTimeOfLastMusicUpdate + MAX_MS_BETWEEN_STREAMS ) )\r\n\t\t{\r\n\t\t\tSmallShowState( \"[ss1]\" );\r\n\t\t\treturn ( 1 );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tunsigned int predictedTimeOfInterrupt;\r\n\t\t\tpredictedTimeOfInterrupt = ( time + SINGLE_BUFFER_MS );\r\n\t\t\tif ( ( predictedTimeOfInterrupt > ( gTimeOfLastMusicUpdate + MIN_MS_BETWEEN_STREAMS ) )\r\n\t\t\t\t&& ( predictedTimeOfInterrupt < ( gTimeOfLastMusicUpdate + MAX_MS_BETWEEN_STREAMS ) ) )\r\n\t\t\t{\r\n\t\t\t\tSmallShowState( \"[ss2]\" );\r\n\t\t\t\treturn ( 1 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//printf( \" <>gsto %d<>\", gStreamTimeOffset );\r\n\t\t\t\tSmallShowState( \"[nss]\" ); //fe ss %x sls %d eecom %d\\n\", gStreamStatus, gStreamLoadState, gEECommand );\r\n\t\t\t}\r\n\t\t}*/\r\n\t}\r\n\tSmallShowState( \"[nss]\" ); //fe ss %x sls %d eecom %d\\n\", gStreamStatus, gStreamLoadState, gEECommand );\r\n\treturn ( 0 );\r\n}\r\n\r\nint SafeForMusicToGo( unsigned int time )\r\n{\r\n\tif ( gStreamStatus == EzADPCM_STATUS_IDLE )\r\n\t{\r\n\t\tSmallShowState( \"[ms]\" ); //fe ss %x sls %d eecom %d\\n\", gStreamStatus, gStreamLoadState, gEECommand );\r\n\t\treturn ( 1 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttime -= gMusicTimeOffset;\r\n\t\tif ( gStreamPaused )\r\n\t\t{\r\n\t\t\tif ( time > gStreamPaused + MIN_MS_BETWEEN_STREAMS )\r\n\t\t\t{\r\n\t\t\t\tSmallShowState( \"[ms0]\" ); //fe ss %x sls %d eecom %d\\n\", gStreamStatus, gStreamLoadState, gEECommand );\r\n\t\t\t\treturn ( 1 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tint streamMod;\r\n\t\t\tint musicMod;\r\n\t\t\tstreamMod = gTimeOfLastStreamUpdate % SINGLE_BUFFER_MS;\r\n\t\t\tmusicMod = time % SINGLE_BUFFER_MS;\r\n\t\t\tif ( musicMod > streamMod )\r\n\t\t\t{\r\n\t\t\t\tif ( ( musicMod - streamMod > MIN_MS_BETWEEN_STREAMS ) &&\r\n\t\t\t\t\t( ( ( streamMod + SINGLE_BUFFER_MS ) - musicMod ) > MIN_MS_BETWEEN_STREAMS ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tSmallShowState( \"[ms1]\" );\r\n\t\t\t\t\treturn ( 1 );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( ( streamMod - musicMod > MIN_MS_BETWEEN_STREAMS ) &&\r\n\t\t\t\t\t( ( ( musicMod + SINGLE_BUFFER_MS ) - streamMod ) > MIN_MS_BETWEEN_STREAMS ) )\r\n\t\t\t{\r\n\t\t\t\tSmallShowState( \"[ms2]\" );\r\n\t\t\t\treturn ( 1 );\r\n\t\t\t}\r\n\t\t}\r\n/*\t\t\r\n        else if ( ( time > gTimeOfLastStreamUpdate + MIN_MS_BETWEEN_STREAMS ) &&\r\n\t\t\t ( time < gTimeOfLastStreamUpdate + MAX_MS_BETWEEN_STREAMS ) )\r\n\t\t{\r\n\t\t\tSmallShowState( \"[ms1]\" ); //fe ss %x sls %d eecom %d\\n\", gStreamStatus, gStreamLoadState, gEECommand );\r\n\t\t\treturn ( 1 );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tunsigned int predictedTimeOfInterrupt;\r\n\t\t\tpredictedTimeOfInterrupt = ( time + SINGLE_BUFFER_MS );\r\n\t\t\tif ( ( predictedTimeOfInterrupt > ( gTimeOfLastStreamUpdate + MIN_MS_BETWEEN_STREAMS ) )\r\n\t\t\t\t&& ( predictedTimeOfInterrupt < ( gTimeOfLastStreamUpdate + MAX_MS_BETWEEN_STREAMS ) ) )\r\n\t\t\t{\r\n\t\t\t\tSmallShowState( \"[ms2]\" ); //fe ss %x sls %d eecom %d\\n\", gStreamStatus, gStreamLoadState, gEECommand );\r\n\t\t\t\treturn ( 1 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tSmallShowState( \"[nsm]\" ); //fe ss %x sls %d eecom %d\\n\", gStreamStatus, gStreamLoadState, gEECommand );\r\n\t\t\t}\r\n\t\t}*/\r\n\t\t\r\n\t}\r\n\tSmallShowState( \"[nsm]\" ); //fe ss %x sls %d eecom %d\\n\", gStreamStatus, gStreamLoadState, gEECommand );\r\n\treturn ( 0 );\r\n}\r\n\r\n// EzADPCM_GETSTATUS\r\nunsigned int AdpcmGetStatus( void )\r\n{\r\n\tunsigned int temp;\r\n\tunsigned int time;\r\n\t\r\n\tif ( gRequestFlags & ( RF_START_MUSIC | RF_START_STREAM | RF_UNPAUSE_MUSIC | RF_UNPAUSE_STREAM ) )\r\n\t{\r\n\t\ttime = GetTime( );\r\n\t\tif ( ( gRequestFlags & RF_START_STREAM ) && ( SafeForStreamToGo( time ) ) )\r\n\t\t{\r\n\t\t\tgUpdateStream = 1;\r\n\t\t\tgTimeOfLastStreamUpdate = time;\r\n\t\t\tShowAction( \"Starting stream\\n\" );\r\n\t\t\tSmallShowAction( \"-sb\" );\r\n\t\t\tSignalSema( gSem );\r\n\t\t\tgRequestFlags &= ~RF_START_STREAM;\r\n\t\t}\r\n\t\telse if ( ( gRequestFlags & RF_START_MUSIC ) && ( SafeForMusicToGo( time ) ) )\r\n\t\t{\r\n\t\t\tgUpdateMusic = 1;\r\n\t\t\tgTimeOfLastStreamUpdate = time;\r\n\t\t\tShowAction( \"Starting music\\n\" );\r\n\t\t\tSmallShowAction( \"-mb\" );\r\n\t\t\tSignalSema( gSem );\r\n\t\t\tgRequestFlags &= ~RF_START_MUSIC;\r\n\t\t}\r\n\t\telse  // unpause one or both of these motherfuckers:\r\n\t\t{\r\n\t\t\tif ( ( gRequestFlags & RF_UNPAUSE_STREAM ) && ( SafeForStreamToGo( time ) )\t)\r\n\t\t\t{\r\n\t\t\t\tsceSdSetParam( STREAM_CORE | ( STREAM_VOICE << 1 ) | SD_VP_PITCH, DEFAULT_PITCH );\r\n\t\t\t\tgStreamPaused = 0;\r\n\t\t\t\tgTimeOfLastStreamUpdate = time - gStreamTimeOffset;\r\n\t\t\t\tgStreamTimeOffset = 0;\r\n\t\t\t\tgRequestFlags &= ~RF_UNPAUSE_STREAM;\r\n\t\t\t\tShowAction( \"Unpausing stream\\n\" );\r\n\t\t\t\tSmallShowAction( \"-ups\" );\r\n\t\t\t}\r\n\t\t\tif ( ( gRequestFlags & RF_UNPAUSE_MUSIC ) && ( SafeForMusicToGo( time ) ) )\r\n\t\t\t{\r\n\t\t\t\tsceSdSetParam( MUSIC_CORE | ( MUSIC_L_VOICE << 1 ) | SD_VP_PITCH, DEFAULT_PITCH );\r\n\t\t\t\tsceSdSetParam( MUSIC_CORE | ( MUSIC_R_VOICE << 1 ) | SD_VP_PITCH, DEFAULT_PITCH );\r\n\t\t\t\tgMusicPaused = 0;\r\n\t\t\t\tgTimeOfLastMusicUpdate = time - gMusicTimeOffset;\r\n\t\t\t\tgMusicTimeOffset = 0;\r\n\t\t\t\tgRequestFlags &= ~RF_UNPAUSE_MUSIC;\r\n\t\t\t\tShowAction( \"Unpausing music\\n\" );\r\n\t\t\t\tSmallShowAction( \"-upm\" );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\ttemp = gEECommand;\r\n\tgEECommand &= ~( PCMSTATUS_NEED_MUSIC_BUFFER_0 | PCMSTATUS_NEED_MUSIC_BUFFER_1 | \r\n\t\t\t\t\tPCMSTATUS_NEED_STREAM_BUFFER_0 | PCMSTATUS_NEED_STREAM_BUFFER_1 );\r\n#if SHOW_SMALL_COMMANDS\r\n\tif ( temp & ( PCMSTATUS_NEED_MUSIC_BUFFER_0 | PCMSTATUS_NEED_MUSIC_BUFFER_1 | \r\n\t\t\t\t\tPCMSTATUS_NEED_STREAM_BUFFER_0 | PCMSTATUS_NEED_STREAM_BUFFER_1 ) )\r\n\t{\r\n\t\tShowSmallCommand( \" <_L_>\" );\r\n\t}\r\n#endif\r\n\treturn temp;\r\n}\r\n\r\n// ================================================================\r\n\r\n#define _ADPCM_MARK_START 0x04\r\n#define _ADPCM_MARK_LOOP  0x02\r\n#define _ADPCM_MARK_END   0x01\r\n\r\n#define _AdpcmSetMarkSTART(a,s) { \\\r\n  *((unsigned char *)((a)+1)) = \\\r\n\t(_ADPCM_MARK_LOOP | _ADPCM_MARK_START); \\\r\n  *((unsigned char *)((a)+0x10+1)) = \\\r\n\t_ADPCM_MARK_LOOP; \\\r\n  *((unsigned char *)((a)+(s)-0x0f)) = \\\r\n\t_ADPCM_MARK_LOOP; \\\r\n\tFlushDcache (); }\r\n#define _AdpcmSetMarkEND(a,s) { \\\r\n  *((unsigned char *)((a)+1)) = \\\r\n\t _ADPCM_MARK_LOOP; \\\r\n  *((unsigned char *)((a)+0x10+1)) = \\\r\n\t_ADPCM_MARK_LOOP; \\\r\n  *((unsigned char *)((a)+(s)-0x0f)) = \\\r\n\t(_ADPCM_MARK_LOOP | _ADPCM_MARK_END); \\\r\n\tFlushDcache (); }\r\n\r\n#define _AdpcmSetMarkFINAL(a,s) { \\\r\n  *((unsigned char *)((a)+(s)-0x0f)) = \\\r\n\t(_ADPCM_MARK_LOOP | _ADPCM_MARK_START | _ADPCM_MARK_END); \\\r\n\tFlushDcache (); }\r\n\r\n#define _AdpcmSetMarkSTARTpre(a,s) { \\\r\n  *((unsigned char *)((a)+1)) = \\\r\n\t(_ADPCM_MARK_LOOP | _ADPCM_MARK_START); \\\r\n  *((unsigned char *)((a)+0x10+1)) = \\\r\n\t_ADPCM_MARK_LOOP; \\\r\n\tFlushDcache (); }\r\n#define _AdpcmSetMarkENDpre(a,s) { \\\r\n  *((unsigned char *)((a)+(s)-0x0f)) = \\\r\n\t(_ADPCM_MARK_LOOP | _ADPCM_MARK_END); \\\r\n\tFlushDcache (); }\r\n\r\n#if SHARE_DMA_CH\r\n\r\n/* internal */\r\nstatic int _AdpcmDmaIntCommon(int ch, void *common) // DMA Interrupt -- when transfering data to SPU2 from IOP\r\n{\r\n\tif ( gLoadStatus & LOAD_STATUS_LOADING_MUSIC )\r\n\t{\r\n\t\tif ( gMusicStatus != EzADPCM_STATUS_IDLE )\r\n\t\t{\r\n\t\t\tgUpdateMusic++;\r\n\t\t\tiSignalSema (* (int *) common);\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t}\r\n\telse if ( gLoadStatus & LOAD_STATUS_LOADING_STREAM )\r\n\t{\r\n\t\tif ( gStreamStatus != EzADPCM_STATUS_IDLE )\r\n\t\t{\r\n\t\t\tgUpdateStream++;\r\n\t\t\tiSignalSema (* (int *) common);\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n#else\r\n\r\n/* internal */\r\nstatic int _AdpcmDmaIntMusic(int ch, void *common)\t// DMA Interrupt -- when transfering data to SPU2 from IOP\r\n{\r\n\tif ( gMusicStatus != EzADPCM_STATUS_IDLE )\r\n\t{\r\n\t\tgUpdateMusic++;\r\n\t\tiSignalSema (* (int *) common);\r\n\t\treturn 1;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n/* internal */\r\nstatic int _AdpcmDmaIntStream(int ch, void *common)\t// DMA Interrupt -- when transfering data to SPU2 from IOP\r\n{\r\n\tif ( gStreamStatus != EzADPCM_STATUS_IDLE )\r\n\t{\r\n\t\tgUpdateStream++;\r\n\t\tiSignalSema (* (int *) common);\r\n\t\treturn 1;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n#endif\r\n\r\n/* internal */\r\nstatic int _AdpcmSpu2Int( int core, void *common ) // SPU2 Voice Interrupt\r\n{\r\n\tif ( core == ( 1 << MUSIC_CORE ) )\r\n\t{\r\n\t\tif ( gMusicLoadState != MUSIC_LOAD_STATE_WAITING_FOR_IRQ )\r\n\t\t{\r\n\t\t\tint shit;\r\n\t\t\tfor ( shit = 0; shit < 666; shit++ )\r\n\t\t\t{\r\n\t\t\t\tprintf( \"shit\\n\" );\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\tgUpdateMusic++;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( gStreamLoadState != STREAM_LOAD_STATE_WAITING_FOR_IRQ )\r\n\t\t{\r\n\t\t\tint shit;\r\n\t\t\tfor ( shit = 0; shit < 666; shit++ )\r\n\t\t\t{\r\n\t\t\t\tprintf( \"shit\\n\" );\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\tgUpdateStream++;\r\n\t}\r\n\tiSignalSema (* (int *) common);\r\n    return 1;\r\n}\r\n\r\n#define LAST_VAG_POS 15\r\n\r\n//prototype:\r\nvoid UpdateStream( void );\r\n\r\nvoid UpdateMusic( void )\r\n{\r\n\tswitch ( gMusicStatus )\r\n\t{\r\n\t\tcase EzADPCM_STATUS_IDLE:\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_STATUS_PRELOAD:\r\n\t\t\tswitch ( gMusicLoadState )\r\n\t\t\t{\r\n\t\t\t\tcase ( MUSIC_LOAD_STATE_IDLE ):\r\n\t\t\t\t{\r\n#if SHARE_DMA_CH\t\t\t\t\t\r\n\t\t\t\t\tif ( gLoadStatus & LOAD_STATUS_LOADING_STREAM )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgLoadStatus |= LOAD_STATUS_NEED_MUSIC;\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tgLoadStatus |= LOAD_STATUS_LOADING_MUSIC;\r\n#endif\r\n\t\t\t\t\tShowState( \"music preload l\\n\" );\r\n\t\t\t\t\tSmallShowState( \"-MPL\" );\r\n\t\t\t\t\tgMusicBufSide = _1st;\r\n\t\t\t\t\tgMusicIopOffset = 0;\r\n\t\t\t\t\tgMusicRemaining = gMusicSize;\r\n\t\t\t\t\tgMusicRemaining -= SB_BUF_SIZE;\r\n\t\t\t\t\tgMusicTransSize = SB_BUF_SIZE;\r\n\t\t\t\t\tif ( gMusicRemaining < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgMusicTransSize += gMusicRemaining;\r\n\t\t\t\t\t}\r\n\r\n#if DATA_INTEGRITY_CHECK\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint gronk;\r\n\t\t\t\t\t\tfor ( gronk = 0; gronk < gMusicTransSize >> 4; gronk++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( *( ( char * )( 1 + gpIopBuf + MUSIC_L_IOP_OFFSET + ( gronk * 16 ) ) ) != 0 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tprintf( \"Fucked up data!!!!\" );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\t\r\n\t\t\t\t\t// preload left:\r\n\t\t\t\t\t_AdpcmSetMarkSTARTpre( gpIopBuf + MUSIC_L_IOP_OFFSET, gMusicTransSize );\r\n\t\t\t\t\tif ( gMusicRemaining > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkENDpre( gpIopBuf + MUSIC_L_IOP_OFFSET, gMusicTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkFINAL( gpIopBuf + MUSIC_L_IOP_OFFSET, gMusicTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsceSdVoiceTrans( TRANS_DMA_CH_MUSIC, ( SD_TRANS_MODE_WRITE | SD_TRANS_BY_DMA ),\r\n\t\t\t\t\t\t(unsigned char *) ( gpIopBuf + MUSIC_L_IOP_OFFSET ),\r\n\t\t\t\t\t\tMUSIC_L_SPU_BUF_LOC, gMusicTransSize );\r\n\t\t\t\t\tgMusicLoadState++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase ( MUSIC_LOAD_STATE_PRELOADING_L ):\r\n\t\t\t\t{\r\n\t\t\t\t\tShowState( \"music preload r\\n\" );\r\n\t\t\t\t\tSmallShowState( \"-MPR\" );\r\n\t\t\t\t\t// preload right:\r\n#if DATA_INTEGRITY_CHECK\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint gronk;\r\n\t\t\t\t\t\tfor ( gronk = 0; gronk < gMusicTransSize >> 4; gronk++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( *( ( char * )( 1 + gpIopBuf + MUSIC_R_IOP_OFFSET + ( gronk * 16 ) ) ) != 0 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tprintf( \"Fucked up data!!!!\" );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\t_AdpcmSetMarkSTARTpre( gpIopBuf + MUSIC_R_IOP_OFFSET, gMusicTransSize );\r\n\t\t\t\t\tif ( gMusicRemaining > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkENDpre( gpIopBuf + MUSIC_R_IOP_OFFSET, gMusicTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkFINAL( gpIopBuf + MUSIC_R_IOP_OFFSET, gMusicTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsceSdVoiceTrans( TRANS_DMA_CH_MUSIC, ( SD_TRANS_MODE_WRITE | SD_TRANS_BY_DMA ),\r\n\t\t\t\t\t\t(unsigned char *) ( gpIopBuf + MUSIC_R_IOP_OFFSET ),\r\n\t\t\t\t\t\tMUSIC_R_SPU_BUF_LOC, gMusicTransSize );\r\n\t\t\t\t\tgMusicLoadState++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\tcase ( MUSIC_LOAD_STATE_PRELOADING_R ):\r\n\t\t\t\t{\r\n\t\t\t\t\tShowState( \"Music starting -- waiting for IRQ\\n\" );\r\n\t\t\t\t\tSmallShowState( \" %d-MSIRQ\", GetTime( ) );\r\n\t\t\t\t\tgMusicIopOffset = SB_BUF_SIZE;\r\n\t\t\t\t\tif ( gMusicRemaining <= 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsceSdSetAddr( MUSIC_CORE | SD_A_IRQA, MUSIC_L_SPU_BUF_LOC + gMusicTransSize - LAST_VAG_POS );\r\n\t\t\t\t\t\tgMusicStatus = EzADPCM_STATUS_TERMINATE;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsceSdSetAddr( MUSIC_CORE | SD_A_IRQA, MUSIC_L_SPU_BUF_LOC + SB_BUF_HALF );\r\n\t\t\t\t\t\tgMusicStatus = EzADPCM_STATUS_RUNNING;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tAdpcmSetMusicVolumeDirect( gMusicVolume );\r\n\t\t\t\t\tsceSdSetCoreAttr( MUSIC_CORE | SD_C_IRQ_ENABLE, 1 );\r\n\t\t\t\t\tsceSdSetSwitch( MUSIC_CORE | SD_S_KON, ( ( 1 << MUSIC_R_VOICE ) | ( 1 << MUSIC_L_VOICE ) ) );\r\n\t\t\t\t\tgMusicLoadState++;\r\n\t\t\t\t\tgTimeOfLastMusicUpdate = GetTime( );\r\n//\t\t\t\t\tprintf( \"music wait IRQ...\\n\" );\r\n#if SHARE_DMA_CH\t\t\t\t\t\r\n\t\t\t\t\tgLoadStatus &= ~LOAD_STATUS_LOADING_MUSIC;\r\n\t\t\t\t\tif ( gLoadStatus & LOAD_STATUS_NEED_STREAM )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgLoadStatus &= ~LOAD_STATUS_NEED_STREAM;\r\n\t\t\t\t\t\tUpdateStream( );\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_STATUS_RUNNING:\r\n\t\t\tswitch ( gMusicLoadState )\r\n\t\t\t{\r\n\t\t\t\tcase ( MUSIC_LOAD_STATE_WAITING_FOR_IRQ ):\r\n\t\t\t\t{\r\n#if SHARE_DMA_CH\t\t\t\t\t\r\n\t\t\t\t\tif ( gLoadStatus & LOAD_STATUS_LOADING_STREAM )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgLoadStatus |= LOAD_STATUS_NEED_MUSIC;\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tgLoadStatus |= LOAD_STATUS_LOADING_MUSIC;\r\n#endif\t\t\t\t\t\r\n\t\t\t\t\tShowState( \"Music Running -- Loading L\\n\" );\r\n\t\t\t\t\tSmallShowState( \"-MRLL\" );\r\n\t\t\t\t\tsceSdSetCoreAttr ( MUSIC_CORE | SD_C_IRQ_ENABLE, 0);\r\n\t\t\t\t\tgMusicTransSize = SB_BUF_HALF;\r\n\t\t\t\t\tgMusicRemaining -= SB_BUF_HALF;\r\n\t\t\t\t\tif ( gMusicRemaining < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgMusicTransSize += gMusicRemaining;\r\n\t\t\t\t\t}\r\n#if DATA_INTEGRITY_CHECK\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint gronk;\r\n\t\t\t\t\t\tfor ( gronk = 0; gronk < gMusicTransSize >> 4; gronk++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( *( ( char * )( 1 + gpIopBuf + MUSIC_L_IOP_OFFSET + gMusicIopOffset + ( gronk * 16 ) ) ) != 0 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tprintf( \"Fucked up data!!!!\" );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\t\r\n\t\t\t\t\t// load in left side:\r\n\t\t\t\t\tif ( gMusicBufSide == _1st )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkSTART( gpIopBuf + MUSIC_L_IOP_OFFSET + gMusicIopOffset, gMusicTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( gMusicRemaining <= 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkFINAL( gpIopBuf + MUSIC_L_IOP_OFFSET + gMusicIopOffset, gMusicTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if ( gMusicBufSide == _2nd )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkEND( gpIopBuf + MUSIC_L_IOP_OFFSET + gMusicIopOffset, gMusicTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tsceSdVoiceTrans( TRANS_DMA_CH_MUSIC, ( SD_TRANS_MODE_WRITE | SD_TRANS_BY_DMA ),\r\n\t\t\t\t\t\t(unsigned char *) gpIopBuf + MUSIC_L_IOP_OFFSET + gMusicIopOffset,\r\n\t\t\t\t\t\t( MUSIC_L_SPU_BUF_LOC + SB_BUF_HALF * gMusicBufSide ), gMusicTransSize );\r\n\t\t\t\t\tgMusicLoadState++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase ( MUSIC_LOAD_STATE_LOADING_L ):\r\n\t\t\t\t{\r\n\t\t\t\t\tShowState( \"Music Running -- Loading R\\n\" );\r\n\t\t\t\t\tSmallShowState( \"-MRLR\" );\r\n#if DATA_INTEGRITY_CHECK\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint gronk;\r\n\t\t\t\t\t\tfor ( gronk = 0; gronk < gMusicTransSize >> 4; gronk++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( *( ( char * )( 1 + gpIopBuf + MUSIC_R_IOP_OFFSET + gMusicIopOffset + ( gronk * 16 ) ) ) != 0 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tprintf( \"Fucked up data!!!!\" );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\t\r\n\t\t\t\t\t// load in right side:\r\n\t\t\t\t\tif ( gMusicBufSide == _1st )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkSTART( gpIopBuf + MUSIC_R_IOP_OFFSET + gMusicIopOffset, gMusicTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( gMusicRemaining <= 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkFINAL( gpIopBuf + MUSIC_R_IOP_OFFSET + gMusicIopOffset, gMusicTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if ( gMusicBufSide == _2nd )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkEND( gpIopBuf + MUSIC_R_IOP_OFFSET + gMusicIopOffset, gMusicTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsceSdVoiceTrans( TRANS_DMA_CH_MUSIC, ( SD_TRANS_MODE_WRITE | SD_TRANS_BY_DMA ),\r\n\t\t\t\t\t\t(unsigned char *) gpIopBuf + MUSIC_R_IOP_OFFSET + gMusicIopOffset,\r\n\t\t\t\t\t\t( MUSIC_R_SPU_BUF_LOC + SB_BUF_HALF * gMusicBufSide ), gMusicTransSize );\r\n\t\t\t\t\tgMusicLoadState++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase ( MUSIC_LOAD_STATE_LOADING_R ):\r\n\t\t\t\t{\r\n\t\t\t\t\tShowState( \"Music Running -- Waiting for IRQ\\n\" );\r\n\t\t\t\t\tSmallShowState( \" %d-MRIRQ\", GetTime( ) );\r\n\t\t\t\t\t// reset the interrupt:\r\n\t\t\t\t\tif ( gMusicRemaining <= 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsceSdSetAddr( MUSIC_CORE | SD_A_IRQA, gMusicTransSize - LAST_VAG_POS + MUSIC_L_SPU_BUF_LOC + SB_BUF_HALF * gMusicBufSide );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsceSdSetAddr( MUSIC_CORE | SD_A_IRQA, MUSIC_L_SPU_BUF_LOC + SB_BUF_HALF * gMusicBufSide );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tgTimeOfLastMusicUpdate = GetTime( );\r\n\t\t\t\t\tgMusicIopOffset += SB_BUF_HALF;\r\n\t\t\t\t\tgMusicBufSide = ( gMusicBufSide == _1st ) ? _2nd : _1st;\r\n\t\t\t\t\t\r\n\t\t\t\t\tif ( gMusicRemaining <= 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// the vag data up to the end should contain all zeros,\r\n\t\t\t\t\t\t// so it doesn't matter that the interrupt won't happen until the end.\r\n\t\t\t\t\t\t// stop the music when it gets to the end:\r\n\t\t\t\t\t\tgMusicStop++;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( gMusicIopOffset == HALF_BUFFER_SIZE )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t//Dbug_Printf( \"music move over\\n\" );\r\n\t\t\t\t\t\t\tgMusicIopOffset += HALF_BUFFER_SIZE; // move over by half the size since L/R load in together...\r\n\t\t\t\t\t\t\tif ( gMusicRemaining > HALF_BUFFER_SIZE )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tgEECommand |= PCMSTATUS_NEED_MUSIC_BUFFER_0;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse if ( gMusicIopOffset == ( SINGLE_STREAM_BUFFER_SIZE + HALF_BUFFER_SIZE ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t//Dbug_Printf( \"music move back\\n\" );\r\n\t\t\t\t\t\t\tgMusicIopOffset = 0;\r\n\t\t\t\t\t\t\tif ( gMusicRemaining > HALF_BUFFER_SIZE )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tgEECommand |= PCMSTATUS_NEED_MUSIC_BUFFER_1;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( gMusicStop )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgMusicStop = 0;\r\n\t\t\t\t\t\tgMusicStatus = EzADPCM_STATUS_TERMINATE;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsceSdSetCoreAttr( MUSIC_CORE | SD_C_IRQ_ENABLE, 1);\r\n\t\t\t\t\tgMusicLoadState = MUSIC_LOAD_STATE_WAITING_FOR_IRQ;\r\n//\t\t\t\t\tprintf( \"music wait IRQ\\n\" );\r\n#if SHARE_DMA_CH\r\n\t\t\t\t\tgLoadStatus &= ~LOAD_STATUS_LOADING_MUSIC;\r\n\t\t\t\t\tif ( gLoadStatus & LOAD_STATUS_NEED_STREAM )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgLoadStatus &= ~LOAD_STATUS_NEED_STREAM;\r\n\t\t\t\t\t\tUpdateStream( );\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tprintf( \"Unknown music loading state %d\\n\", gMusicLoadState );\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_STATUS_TERMINATE: \r\n\t\t\tShowState( \"Music terminate\\n\" );\r\n\t\t\tSmallShowState( \"-MT!!!\" );\r\n\t\t\tStopMusic( );\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\tprintf( \"unknown music status in pcm irx!!!\\n\" );\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid UpdateStream( void )\r\n{\r\n//\tprintf( \"hmmm %d %d bufside %d left %d\\n\", gStreamStatus, gStreamLoadState, gStreamBufSide, gStreamRemaining );\r\n\tswitch ( gStreamStatus )\r\n\t{\r\n\t\tcase EzADPCM_STATUS_IDLE:\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_STATUS_PRELOAD:\r\n\t\t\tswitch ( gStreamLoadState )\r\n\t\t\t{\r\n\t\t\t\tcase ( STREAM_LOAD_STATE_IDLE ):\r\n\t\t\t\t{\r\n#if SHARE_DMA_CH\t\t\t\t\t\r\n\t\t\t\t\tif ( gLoadStatus & LOAD_STATUS_LOADING_MUSIC )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgLoadStatus |= LOAD_STATUS_NEED_STREAM;\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tgLoadStatus |= LOAD_STATUS_LOADING_STREAM;\r\n#endif\t\t\t\t\t\r\n\t\t\t\t\tShowState( \"stream preload l\\n\" );\r\n\t\t\t\t\tSmallShowState( \"-SPL\" );\r\n\t\t\t\t\tgStreamBufSide = _1st;\r\n\t\t\t\t\tgStreamIopOffset = 0;\r\n\t\t\t\t\tgStreamRemaining = gStreamSize;\r\n\t\t\t\t\tgStreamRemaining -= SB_BUF_SIZE;\r\n\t\t\t\t\tgStreamTransSize = SB_BUF_SIZE;\r\n\t\t\t\t\tif ( gStreamRemaining < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgStreamTransSize += gStreamRemaining;\r\n\t\t\t\t\t}\r\n#if DATA_INTEGRITY_CHECK\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint gronk;\r\n\t\t\t\t\t\tfor ( gronk = 0; gronk < gStreamTransSize >> 4; gronk++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( *( ( char * )( 1 + gpIopBuf + STREAM_IOP_OFFSET + ( gronk * 16 ) ) ) != 0 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tprintf( \"Fucked up data!!!!\" );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\t// preload left:\r\n\t\t\t\t\t_AdpcmSetMarkSTARTpre( gpIopBuf + STREAM_IOP_OFFSET, gStreamTransSize );\r\n\t\t\t\t\tif ( gStreamRemaining > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkENDpre( gpIopBuf + STREAM_IOP_OFFSET, gStreamTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkFINAL( gpIopBuf + STREAM_IOP_OFFSET, gStreamTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsceSdVoiceTrans( TRANS_DMA_CH_STREAM, ( SD_TRANS_MODE_WRITE | SD_TRANS_BY_DMA ),\r\n\t\t\t\t\t\t(unsigned char *) ( gpIopBuf + STREAM_IOP_OFFSET ),\r\n\t\t\t\t\t\tSTREAM_SPU_BUF_LOC, gStreamTransSize );\r\n\t\t\t\t\tgStreamLoadState++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase ( STREAM_LOAD_STATE_PRELOADING ):\r\n\t\t\t\t{\r\n\t\t\t\t\tShowState( \"Stream starting -- waiting for IRQ\\n\" );\r\n\t\t\t\t\tSmallShowState( \" %d-SSIRQ\", GetTime( ) );\r\n\t\t\t\t\tgStreamIopOffset = SB_BUF_SIZE;\r\n\t\t\t\t\tif ( gStreamRemaining <= 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsceSdSetAddr( STREAM_CORE | SD_A_IRQA, STREAM_SPU_BUF_LOC + gStreamTransSize - LAST_VAG_POS );\r\n\t\t\t\t\t\t//printf( \"tiny stream!!! addr %x transsize %x remaining %x\", STREAM_SPU_BUF_LOC + gStreamTransSize - LAST_VAG_POS, gStreamTransSize, gStreamRemaining );\r\n\t\t\t\t\t\tgStreamStatus = EzADPCM_STATUS_TERMINATE;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsceSdSetAddr( STREAM_CORE | SD_A_IRQA, STREAM_SPU_BUF_LOC + SB_BUF_HALF );\r\n\t\t\t\t\t\tgStreamStatus = EzADPCM_STATUS_RUNNING;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tAdpcmSetStreamVolumeDirect( gStreamVolume );\r\n\t\t\t\t\tsceSdSetCoreAttr( STREAM_CORE | SD_C_IRQ_ENABLE, 1 );\r\n\t\t\t\t\tsceSdSetSwitch( STREAM_CORE | SD_S_KON, 1 << STREAM_VOICE );\r\n\t\t\t\t\tgStreamLoadState++;\r\n\t\t\t\t\tgTimeOfLastStreamUpdate = GetTime( );\r\n#if SHARE_DMA_CH\r\n\t\t\t\t\tgLoadStatus &= ~LOAD_STATUS_LOADING_STREAM;\r\n\t\t\t\t\tif ( gLoadStatus & LOAD_STATUS_NEED_MUSIC )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgLoadStatus &= ~LOAD_STATUS_NEED_MUSIC;\r\n\t\t\t\t\t\tUpdateMusic( );\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_STATUS_RUNNING:\r\n\t\t\tswitch ( gStreamLoadState )\r\n\t\t\t{\r\n\t\t\t\tcase ( STREAM_LOAD_STATE_WAITING_FOR_IRQ ):\r\n\t\t\t\t{\r\n\t\t\t\t\tShowState( \"Stream Running -- Loading\\n\" );\r\n\t\t\t\t\tSmallShowState( \"-SRL\" );\r\n#if SHARE_DMA_CH\t\t\t\t\t\r\n\t\t\t\t\tif ( gLoadStatus & LOAD_STATUS_LOADING_MUSIC )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgLoadStatus |= LOAD_STATUS_NEED_STREAM;\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tgLoadStatus |= LOAD_STATUS_LOADING_STREAM;\r\n#endif\t\t\t\t\t\r\n\t\t\t\t\tsceSdSetCoreAttr ( STREAM_CORE | SD_C_IRQ_ENABLE, 0);\r\n\t\t\t\t\tgStreamTransSize = SB_BUF_HALF;\r\n\t\t\t\t\tgStreamRemaining -= SB_BUF_HALF;\r\n\t\t\t\t\tif ( gStreamRemaining < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgStreamTransSize += gStreamRemaining;\r\n\t\t\t\t\t}\r\n\r\n#if DATA_INTEGRITY_CHECK\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint gronk;\r\n\t\t\t\t\t\tfor ( gronk = 0; gronk < gStreamTransSize >> 4; gronk++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( *( ( char * )( 1 + gpIopBuf + gStreamIopOffset + STREAM_IOP_OFFSET + ( gronk * 16 ) ) ) != 0 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tprintf( \"Fucked up data!!!!\" );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\t\r\n\t\t\t\t\t// load in left side:\r\n\t\t\t\t\tif ( gStreamBufSide == _1st )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkSTART( gpIopBuf + STREAM_IOP_OFFSET + gStreamIopOffset, gStreamTransSize );\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( gStreamRemaining <= 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkFINAL( gpIopBuf + STREAM_IOP_OFFSET + gStreamIopOffset, gStreamTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if ( gStreamBufSide == _2nd )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t_AdpcmSetMarkEND( gpIopBuf + STREAM_IOP_OFFSET + gStreamIopOffset, gStreamTransSize );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsceSdVoiceTrans( TRANS_DMA_CH_STREAM, ( SD_TRANS_MODE_WRITE | SD_TRANS_BY_DMA ),\r\n\t\t\t\t\t\t(unsigned char *) gpIopBuf + STREAM_IOP_OFFSET + gStreamIopOffset,\r\n\t\t\t\t\t\t( STREAM_SPU_BUF_LOC + SB_BUF_HALF * gStreamBufSide ), gStreamTransSize );\r\n\t\t\t\t\tgStreamLoadState++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase ( STREAM_LOAD_STATE_LOADING ):\r\n\t\t\t\t{\r\n\t\t\t\t\tShowState( \"Stream Running -- Waiting for IRQ\\n\" );\r\n\t\t\t\t\tSmallShowState( \" %d-SRIRQ\", GetTime( ) );\r\n\t\t\t\t\t// reset the interrupt:\r\n\t\t\t\t\tif ( gStreamRemaining <= 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsceSdSetAddr( STREAM_CORE | SD_A_IRQA, gStreamTransSize - LAST_VAG_POS + STREAM_SPU_BUF_LOC + SB_BUF_HALF * gStreamBufSide );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsceSdSetAddr( STREAM_CORE | SD_A_IRQA, STREAM_SPU_BUF_LOC + SB_BUF_HALF * gStreamBufSide );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tgTimeOfLastStreamUpdate = GetTime( );\r\n\t\t\r\n\t\t\t\t\tgStreamIopOffset += SB_BUF_HALF;\r\n\t\t\t\t\tgStreamBufSide = ( gStreamBufSide == _1st ) ? _2nd : _1st;\r\n\t\t\t\t\t\r\n\t\t\t\t\tif ( gStreamRemaining <= 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// the vag data up to the end should contain all zeros,\r\n\t\t\t\t\t\t// so it doesn't matter that the interrupt won't happen until the end.\r\n\t\t\t\t\t\t// stop the stream when it gets to the end:\r\n\t\t\t\t\t\tgStreamStop++;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( gStreamIopOffset == HALF_BUFFER_SIZE )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t//Dbug_Printf( \"Stream move over\\n\" );\r\n\t\t\t\t\t\t\tif ( gStreamRemaining > HALF_BUFFER_SIZE )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tgEECommand |= PCMSTATUS_NEED_STREAM_BUFFER_0;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse if ( gStreamIopOffset == SINGLE_STREAM_BUFFER_SIZE )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t//Dbug_Printf( \"Stream move back\\n\" );\r\n\t\t\t\t\t\t\tgStreamIopOffset = 0;\r\n\t\t\t\t\t\t\tif ( gStreamRemaining > HALF_BUFFER_SIZE )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tgEECommand |= PCMSTATUS_NEED_STREAM_BUFFER_1;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( gStreamStop )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgStreamStop = 0;\r\n\t\t\t\t\t\tgStreamStatus = EzADPCM_STATUS_TERMINATE;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsceSdSetCoreAttr( STREAM_CORE | SD_C_IRQ_ENABLE, 1);\r\n\t\t\t\t\tgStreamLoadState = STREAM_LOAD_STATE_WAITING_FOR_IRQ;\r\n//\t\t\t\t\tprintf( \"stream wait IRQ\\n\" );\r\n#if SHARE_DMA_CH\r\n\t\t\t\t\tgLoadStatus &= ~LOAD_STATUS_LOADING_STREAM;\r\n\t\t\t\t\tif ( gLoadStatus & LOAD_STATUS_NEED_MUSIC )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgLoadStatus &= ~LOAD_STATUS_NEED_MUSIC;\r\n\t\t\t\t\t\tUpdateMusic( );\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tprintf( \"Unknown Stream loading state %d\\n\", gStreamLoadState );\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_STATUS_TERMINATE: \r\n\t\t\tShowState( \"Stream terminate\\n\" );\r\n\t\t\tSmallShowState( \"-ST!!!\" );\r\n\t\t\tStopStream( );\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\tprintf( \"unknown stream status in pcm irx!!!\\n\" );\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/* internal */\r\nint _AdpcmPlay( int status )\r\n{\r\n    while ( 1 )\r\n\t{\r\n//        int st, mu;\r\n\t\tWaitSema(gSem);\r\n\t\t\r\n//\t\tShowTime( \"ssig us %d um %d ss %d ms %d ee %d time %d\\n\", gUpdateStream, gUpdateMusic, gStreamStatus, gMusicStatus, gEECommand, GetTime( ) );\r\n//\t\tSmallShowTime( \" <%d>\", GetTime( ) );\r\n//\t\tst = gUpdateStream;\r\n//\t\tmu = gUpdateMusic;\r\n\t\twhile ( gUpdateStream )\r\n\t\t{\r\n//printf( \"s u\\n\" );\t\t\r\n\t\t\tgUpdateStream--;\r\n\t\t\tUpdateStream( );\r\n\t\t}\r\n\t\twhile ( gUpdateMusic )\r\n\t\t{\r\n//printf( \"m u\\n\" );\t\t\r\n\t\t\tgUpdateMusic--;\r\n\t\t\tUpdateMusic( );\r\n\t\t}\r\n\t\t\r\n/*\t\t\r\n\t\tif ( gTestPause == 666 )\r\n\t\t{\r\n\t\t\tsceSdSetParam( MUSIC_CORE | ( MUSIC_L_VOICE << 1 ) | SD_VP_PITCH, 0 );\r\n\t\t\tsceSdSetParam( MUSIC_CORE | ( MUSIC_R_VOICE << 1 ) | SD_VP_PITCH, 0 );\r\n\t\t\tsceSdSetParam( STREAM_CORE | ( STREAM_VOICE << 1 ) | SD_VP_PITCH, 0 );\r\n\t\t\tgPaused = 1;\r\n\t\t}\r\n\t\tif ( ( !gTestPause ) && ( !st && !mu ) )\r\n\t\t{\r\n\t\t\tprintf( \"MOTHERFUCKER MOTHERFUCKER MOTHERFUCKER MOTHERFUCKER\\n\" );\r\n\t\t\tgTestPause = 30;\r\n\t\t}*/\r\n\r\n//printf( \"hmm NAX %x\\n\", sceSdGetAddr( MUSIC_CORE | ( MUSIC_R_VOICE << 1 ) | SD_VA_NAX ) );\r\n\t\tif ( gMusicVolumeSet )\r\n\t\t{\r\n\t\t\tgMusicVolumeSet = 0;\r\n\t\t\tAdpcmSetMusicVolumeDirect( gMusicVolume );\r\n\t\t}\r\n\t\tif ( gStreamVolumeSet )\r\n\t\t{\r\n\t\t\tgStreamVolumeSet = 0;\r\n\t\t\tAdpcmSetStreamVolumeDirect( gStreamVolume );\r\n\t\t}\r\n    }\r\n    return 0;\r\n}\r\n\r\nstatic int rpc_arg [16];\r\nvolatile int ret = 0;\r\n\r\nstatic void *dispatch( unsigned int command, void *data_, int size )\r\n{ \r\n    int ch;\r\n    int          data  = *((         int *) data_);\r\n    unsigned int dataU = *((unsigned int *) data_);\r\n\r\n/*    PRINTF ((\"# dispatch [%04x] %x, %x, %x, %x\\n\",\r\n\t      command,\r\n\t      *((int*) data_ + 0), \r\n\t      *((int*) data_ + 1),\r\n\t      *((int*) data_ + 2),\r\n          *((int*) data_ + 3)));*/\r\n\r\n    ch = command & EzADPCM_CH_MASK;\r\n    switch ( command & EzADPCM_COMMAND_MASK )\r\n\t{\r\n\t\tcase EzADPCM_INIT:\r\n\t\t\tret = AdpcmInit( data ); // iop buffer pointer\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_QUIT:\r\n\t\t\tAdpcmQuit( );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_PLAYMUSIC:\r\n\t\t\tret = AdpcmPlayMusic( data );  // size of the entire PCM data in the file\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_PLAYSTREAM:\r\n\t\t\tret = AdpcmPlayStream( data ); // size of the entire PCM data in the file\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_PAUSEMUSIC:\r\n\t\t\tif ( data )\r\n\t\t\t{\r\n\t\t\t\tif ( !gMusicPaused )\r\n\t\t\t\t{\r\n\t\t\t\t\tsceSdSetParam( MUSIC_CORE | ( MUSIC_L_VOICE << 1 ) | SD_VP_PITCH, 0 );\r\n\t\t\t\t\tsceSdSetParam( MUSIC_CORE | ( MUSIC_R_VOICE << 1 ) | SD_VP_PITCH, 0 );\r\n\t\t\t\t\tgMusicPaused = GetTime( );\r\n\t\t\t\t\tgMusicTimeOffset = gMusicPaused - gTimeOfLastMusicUpdate;\r\n\t\t\t\t\tif ( gMusicTimeOffset > SINGLE_BUFFER_MS )\r\n\t\t\t\t\t{\r\n/*\t\t\t\t\t\tif ( gMusicStatus != EzADPCM_STATUS_TERMINATE )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tprintf( \"\\n\\nfuck your mom %x \\n\\n\", gMusicStatus );\r\n\t\t\t\t\t\t}*/\r\n\t\t\t\t\t\tgMusicTimeOffset -= SINGLE_BUFFER_MS;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tShowAction( \"Pausing music\\n\" );\r\n\t\t\t\t\tSmallShowAction( \"-pm\" );\r\n\t\t\t\t}\r\n\t\t\t\tgRequestFlags &= ~RF_UNPAUSE_MUSIC;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( gMusicPaused )\r\n\t\t\t\t{\r\n\t\t\t\t\tgRequestFlags |= RF_UNPAUSE_MUSIC;\r\n\t\t\t\t\tShowAction( \"Requesting unpause music\\n\" );\r\n\t\t\t\t\tSmallShowAction( \"-rupm\" );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_PAUSESTREAM:\r\n\t\t\tif ( data )\r\n\t\t\t{\r\n\t\t\t\tif ( !gStreamPaused )\r\n\t\t\t\t{\r\n\t\t\t\t\tsceSdSetParam( STREAM_CORE | ( STREAM_VOICE << 1 ) | SD_VP_PITCH, 0 );\r\n\t\t\t\t\tgStreamPaused = GetTime( );\r\n\t\t\t\t\tgStreamTimeOffset = gStreamPaused - gTimeOfLastStreamUpdate;\r\n\t\t\t\t\tif ( gStreamTimeOffset > SINGLE_BUFFER_MS )\r\n\t\t\t\t\t{\r\n/*\t\t\t\t\t\tif ( gStreamStatus != EzADPCM_STATUS_TERMINATE )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tprintf( \"\\n\\nfuck your mom %x \\n\\n\", gStreamStatus );\r\n\t\t\t\t\t\t}*/\r\n\t\t\t\t\t\tgStreamTimeOffset -= SINGLE_BUFFER_MS;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tShowAction( \"Pausing stream\\n\" );\r\n\t\t\t\t\tSmallShowAction( \"-ps\" );\r\n\t\t\t\t}\r\n\t\t\t\tgRequestFlags &= ~( RF_UNPAUSE_STREAM );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( gStreamPaused )\r\n\t\t\t\t{\r\n\t\t\t\t\tgRequestFlags |= RF_UNPAUSE_STREAM;\r\n\t\t\t\t\tShowAction( \"Requesting unpause stream\\n\" );\r\n\t\t\t\t\tSmallShowAction( \"-rups\" );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase EzADPCM_STOPMUSIC:\r\n\t\t\tret = AdpcmStopMusic( );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_STOPSTREAM:\r\n\t\t\tret = AdpcmStopStream( );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_SETMUSICVOL:\r\n\t\t\tAdpcmSetMusicVolume( dataU );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_SETMUSICVOLDIRECT:\r\n\t\t\tAdpcmSetMusicVolumeDirect( dataU );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_SETSTREAMVOL:\r\n\t\t\tAdpcmSetStreamVolume( dataU );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_SETSTREAMVOLDIRECT:\r\n\t\t\tAdpcmSetStreamVolumeDirect( dataU );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_GETSTATUS:\r\n\t\t\tret = AdpcmGetStatus( );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_GETMUSICSTATUS:\r\n\t\t\tret = AdpcmGetMusicStatus( );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_GETSTREAMSTATUS:\r\n\t\t\tret = AdpcmGetStreamStatus( );\r\n\t\t\tbreak;\r\n\r\n\t\tcase EzADPCM_SDINIT:\r\n\t\t\tAdpcmSdInit( );\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\tERROR ((\"EzADPCM driver error: unknown command %d \\n\", data));\r\n\t\t\tbreak;\r\n    }\r\n    //printf( \"! return value = %x \\n\", ret );\r\n    return (void*)(&ret);\r\n}\r\n\r\nint sce_adpcm_loop( void )\r\n{\r\n    sceSifQueueData qd;\r\n    sceSifServeData sd;\r\n\r\n    sceSifInitRpc (0);\r\n    sceSifSetRpcQueue (&qd, GetThreadId ());\r\n    sceSifRegisterRpc (&sd, EzADPCM_DEV, dispatch, (void*)rpc_arg, NULL, NULL, &qd);\r\n    //Dbug_Printf((\"goto adpcm cmd loop\\n\"));\r\n    \r\n    sceSifRpcLoop (&qd);\r\n\r\n    return 0;\r\n}\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n/* DON'T ADD STUFF AFTER THIS */\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/pcm/pcm_ent.c",
    "content": "/* Vag streaming into SPU2 -- Converted from Sony samples -- matt may 2001 */\r\n\r\n#include <kernel.h>\r\n#include <sys/types.h>\r\n#include <stdio.h>\r\n#include <sif.h>\r\n#include <sifcmd.h>\r\n#include <sifrpc.h>\r\n#include \"pcm.h\"\r\n#include \"pcmiop.h\"\r\n\r\nModuleInfo Module = {\"pcm_driver\", 0x0102};\r\n\r\n// in command.c\r\nextern int sce_adpcm_loop (void);\r\n\r\nint start ( void )\r\n{\r\n    struct ThreadParam param;\r\n    int th;\r\n\r\n    if (! sceSifCheckInit ())\r\n\tsceSifInit ();\r\n    sceSifInitRpc (0);\r\n\r\n    printf (\"PCM driver version 666\\n\");\r\n\r\n    param.attr         = TH_C;\r\n    param.entry        = sce_adpcm_loop;\r\n    param.initPriority = BASE_priority - 2;\r\n    param.stackSize    = 0x800;\r\n    param.option       = 0;\r\n    th = CreateThread (&param);\r\n    if (th > 0) {\r\n\tStartThread (th, 0);\r\n\tprintf (\" Exit PCM loader thread \\n\");\r\n\treturn 0;\r\n    }else{\r\n\treturn 1;\r\n    }\r\n}\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n/* DON'T ADD STUFF AFTER THIS */\r\n"
  },
  {
    "path": "Code/Gel/Music/ngc/pcm/pcmiop.h",
    "content": "#if 0\r\n#define PRINTF(x) printf x\r\n#else\r\n#define PRINTF(x) \r\n#endif\r\n#define ERROR(x) printf x\r\n#define xPRINTF(x) \r\n\r\n#define BASE_priority  32\r\n\r\n#define OLDLIB 0\r\n#define TRANS_CH  0\r\n\r\n"
  },
  {
    "path": "Code/Gel/Net/App/netapp.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNet (OBJ) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tnetapp.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/29/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNetwork app code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <string.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/crc.h>\r\n#include <core/thread.h>\r\n\r\n#include <sys/timer.h>\r\n\r\n#ifndef __PLAT_WN32__\r\n#include <sys/profiler.h>\r\n#endif// __PLAT_WN32__\r\n\r\n#include <gel/net/net.h>\r\n\r\n#include <gel/mainloop.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//extern \"C\"\r\n//{\r\n\tvoid NS_SetSemaphores( int send_semaphore, int recv_semaphore );\r\n//}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#define DEBUG_MESSAGES\r\n \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Net\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nconst unsigned int App::MAX_LATENCY = 2000;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/* Initialize the socket and set socket options\t\t\t\t\t  */\r\n/* Also, add default message handlers                             */\r\n/******************************************************************/\r\n\r\nbool\tApp::init( void )\r\n{\t\r\n#ifndef __PLAT_NGPS__\r\n\tif( !IsLocal())\r\n\t{\r\n\t\t// create socket\r\n\t\tm_socket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );\r\n#ifdef __PLAT_NGC__\r\n\t\tif( m_socket < 0 )\r\n#else\r\n\t\tif( m_socket == INVALID_SOCKET )\r\n#endif\r\n\t\t{\r\n\t\t\tReportError();\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\r\n#ifdef __PLAT_NGC__\r\n\t\tint val;\r\n\t\t \r\n\t\tval = SOFcntl( m_socket, SO_F_GETFL, 0);\r\n\t\tif( val < 0 )\r\n\t\t{\r\n\t\t\tReportError();\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tval = SOFcntl( m_socket, SO_F_SETFL, val | SO_O_NONBLOCK);\r\n\t\tif( val < 0 )\r\n\t\t{\r\n\t\t\tReportError();\r\n\t\t\treturn false;\r\n\t\t}\r\n#else\r\n\t\tunsigned long argp = 1L;\t// non-zero enables non-blocking mode\r\n\r\n\t\tif( ioctlsocket( m_socket, FIONBIO, &argp ) == SOCKET_ERROR )\r\n\t\t{\r\n\t\t\tReportError();\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\r\n\t\tif( m_flags.TestMask( mBROADCAST ))\r\n\t\t{\r\n\t\t\tif(( setsockopt( m_socket, SOL_SOCKET, SO_BROADCAST, \r\n\t\t\t\t\t(char*) &argp, sizeof(argp))) == SOCKET_ERROR )\r\n\t\t\t{\r\n\t\t\t\tReportError();\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n#endif \t// __PLAT_NGC\r\n\t}\r\n#else // __PLAT_NGPS__\r\n\tif( !IsLocal())\r\n\t{\r\n\t\tsn_int32 true_val, false_val;\r\n\t\r\n\t\ttrue_val = 1;\r\n\t\tfalse_val = 0;\r\n\t\t\r\n\t\tif(( m_socket = socket( AF_INET, SOCK_DGRAM, PF_INET )) == INVALID_SOCKET )\r\n\t\t{\r\n\t\t\tReportError();\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\r\n\t\t// make socket non-blocking\r\n\t\tif( setsockopt( m_socket, SOL_SOCKET, SO_NBIO, &true_val, sizeof( sn_int32 )) == SOCKET_ERROR )\r\n\t\t{\r\n\t\t\tReportError();\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\r\n\t\tif( m_flags.TestMask( mBROADCAST ))\r\n\t\t{\r\n\t\t\tif(( setsockopt( m_socket, SOL_SOCKET, SO_BROADCAST, \r\n\t\t\t\t\t(char*) &true_val, sizeof( sn_int32 ))) == SOCKET_ERROR )\r\n\t\t\t{\r\n\t\t\t\tReportError();\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif(( setsockopt( m_socket, SOL_SOCKET, SO_BROADCAST, \r\n\t\t\t\t\t(char*) &false_val, sizeof( sn_int32 ))) == SOCKET_ERROR )\r\n\t\t\t{\r\n\t\t\t\tReportError();\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tm_shutting_down = false;\r\n\r\n\tm_socket_thread_data.m_pEntry = threaded_transfer_data;\r\n\tm_socket_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY;\r\n\tm_socket_thread_data.m_pStackBase = m_socket_thread_stack;\r\n\tm_socket_thread_data.m_iStackSize = vSOCKET_THREAD_STACK_SIZE;\r\n\tm_socket_thread_data.m_utid = vBASE_SOCKET_THREAD_ID + m_net_man->NumApps();\r\n\tThread::CreateThread( &m_socket_thread_data );\r\n\tm_socket_thread_id = m_socket_thread_data.m_osId;\r\n\t\r\n\tstruct SemaParam params;\r\n\r\n\tparams.initCount = 1;\r\n\tparams.maxCount = 10;\r\n\r\n\tm_send_semaphore_id = CreateSema( &params );\r\n\tm_receive_semaphore_id = CreateSema( &params );\r\n\tm_transfer_semaphore_id = CreateSema( &params );\r\n\tm_active_semaphore_id = CreateSema( &params );\r\n\r\n    if( !IsLocal())\r\n\t{\r\n        NS_SetSemaphores( m_send_semaphore_id, m_receive_semaphore_id );\r\n\t}\r\n\r\n\t#ifdef __USER_STEVE__\r\n\tDbg_Printf( \"Send Semaphore %d\\n\", m_send_semaphore_id );\r\n\tDbg_Printf( \"Receive Semaphore %d\\n\", m_receive_semaphore_id );\r\n\tDbg_Printf( \"Transfer Semaphore %d\\n\", m_transfer_semaphore_id );\r\n\t#endif\r\n\r\n\tStartThread( m_socket_thread_id, this );\r\n#endif\t// __PLAT_NGPS__\r\n\r\n\tm_num_connections = 0;\t\r\n\tm_TotalBytesIn = 0;\r\n\tm_TotalBytesOut = 0;\r\n\tm_LostPackets = 0;\r\n\tm_LatePackets = 0;\r\n\tm_DupePackets = 0;\r\n\tm_FrameCounter = 0;\r\n\r\n\tm_Dispatcher.Init();\r\n    \r\n\tm_Dispatcher.AddHandler( MSG_ID_ACK, handle_ack, mHANDLE_LATE | mHANDLE_FOREIGN );\r\n\tm_Dispatcher.AddHandler( MSG_ID_SEQUENCED, handle_sequenced_messages, mHANDLE_LATE );\r\n\tm_Dispatcher.AddHandler( MSG_ID_STREAM_START, handle_stream_messages, mHANDLE_LATE );\r\n\tm_Dispatcher.AddHandler( MSG_ID_STREAM_DATA, handle_stream_messages, mHANDLE_LATE );\r\n\tm_Dispatcher.AddHandler( MSG_ID_PING_TEST, handle_latency_test, mHANDLE_LATE );\r\n\tm_Dispatcher.AddHandler( MSG_ID_PING_RESPONSE, handle_latency_response, mHANDLE_LATE );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/* Bind a socket                                      \t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool App::bind_app_socket( int address, unsigned short port )\r\n{\r\n\tstruct sockaddr_in host_address;\r\n\tint address_len, result;\r\n\r\n\t// bind the socket to an address.\r\n\r\n\tmemset( &host_address, 0, sizeof(host_address));\r\n\thost_address.sin_family = AF_INET;\r\n\thost_address.sin_port = htons( port );\r\n\t// This should basically check if we're using DHCP, but right now modem is the only\r\n\t// device using it\r\n\tif( m_net_man->GetConnectionType() != vCONN_TYPE_MODEM )\r\n\t{\r\n#ifdef __PLAT_XBOX__\r\n\t\thost_address.sin_addr.s_addr = INADDR_ANY;\r\n#else\r\n#ifdef __PLAT_NGC__\r\n\t\thost_address.s_addr.s_addr = address;\r\n#else\r\n\t\thost_address.sin_addr.s_addr = address;\r\n#endif\r\n#endif\t\t\t\t\r\n\t}\r\n#ifdef __PLAT_NGC__\r\n\thost_address.len = sizeof( SOSockAddrIn );\r\n#else\r\n\tmemset ( &host_address.sin_zero, 0, 8 );  \r\n#endif\r\n\r\n\t// bind(name) socket\r\n\tresult = bind( m_socket, (struct sockaddr *)&host_address, sizeof(host_address));\r\n\tif( result < 0 )// == SOCKET_ERROR )\r\n\t{\r\n#ifdef WIN32\r\n\t\tint err = WSAGetLastError();\r\n\t\tif( err == WSAEADDRINUSE )  \r\n#else\r\n#ifdef __PLAT_NGPS__\r\n\t\tint err = sn_errno( m_socket );\r\n\t\tif( err == EADDRINUSE )\r\n#else\r\n#ifdef __PLAT_NGC__\r\n\t\tif( result == SO_EADDRINUSE )\r\n#endif\r\n#endif\r\n#endif\r\n\r\n\t\t{\r\n\t\t\tReportError();\r\n\t\t\thost_address.sin_port = htons( 0 );\r\n\t\t\tresult = bind( m_socket, (struct sockaddr *)&host_address, sizeof(host_address));\r\n\t\t\tif( result < 0 )// == SOCKET_ERROR )\r\n\t\t\t{\r\n\t\t\t\tReportError();\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tReportError();\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\t\t\r\n    \r\n#ifdef __PLAT_NGC__\r\n\tm_local_address.len = sizeof( SOSockAddrIn );\r\n#endif\r\n\taddress_len = sizeof( m_local_address );\r\n\tresult = getsockname( m_socket, (sockaddr*) &m_local_address, &address_len );\r\n\tif( result < 0 )// == SOCKET_ERROR )\r\n\t{\r\n\t\tReportError();\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/* Free up memory used by the network app. Remove msg handlers    */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::deinit( void )\r\n{\r\n\t\r\n\r\n\tLst::Search< Conn > sh;\r\n\tConn *conn, *next;\r\n\r\n\tif( !IsLocal())\r\n\t{\r\n\t\tclosesocket( m_socket );\r\n\t}\r\n\t\r\n\tm_Dispatcher.Deinit();\r\n\r\n\tfor( conn = sh.FirstItem( m_connections ); conn; conn = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tdelete conn;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Get the next free available handle                             */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tApp::get_free_handle( void )\r\n{\r\n\tint i;\r\n\r\n\t\r\n\r\n\tfor( i = Conn::vHANDLE_FIRST; i < 256; i++ )\r\n\t{\r\n\t\tif( !GetConnectionByHandle( i ))\r\n\t\t{\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert( 0,( \"No free handles\\n\" ));\r\n\treturn Conn::vHANDLE_INVALID;\r\n}\r\n\r\n/******************************************************************/\r\n/* Process the list of sequenced messages that we have queued up  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::process_sequenced_messages( Conn *conn )\r\n{\r\n\tint i;\r\n\tLst::Search< MsgSeqLink > sh;\r\n\tMsgSeqLink *msg_link, *next;\r\n\tMsgHandlerContext msg_context;\r\n\tint result;\r\n\r\n\t\r\n\r\n\tDbg_Assert( conn );\r\n\r\n\tresult = HANDLER_CONTINUE;\t\r\n\tfor( i = 0; i < MAX_SEQ_GROUPS; i++ )\r\n\t{\r\n\t\tfor( msg_link = sh.FirstItem( conn->m_SequencedBuffer[i] );\r\n\t\t\t\tmsg_link; msg_link = next )\r\n\t\t{\r\n\t\t\tnext = sh.NextItem();\r\n\t\t\t\r\n\t\t\tif( msg_link->m_SequenceId == conn->m_WaitingForSequenceId[msg_link->m_GroupId] )\r\n\t\t\t{\t\t\t\t\r\n\t\t\t\tmsg_context.m_Conn = conn;\r\n\t\t\t\tmsg_context.m_Msg = NULL;\r\n\t\t\t\t\r\n\t\t\t\tif( msg_link->m_QMsg->m_Data )\r\n\t\t\t\t{\r\n\t\t\t\t\tmsg_context.m_Msg = msg_link->m_QMsg->m_Data;\r\n\t\t\t\t}\r\n\t\t\t\tmsg_context.m_App = this;\r\n\t\t\t\tmsg_context.m_PacketFlags = 0;\r\n\t\t\t\tmsg_context.m_MsgId = msg_link->m_QMsg->m_MsgId;\r\n\t\t\t\tmsg_context.m_MsgLength = msg_link->m_QMsg->m_MsgLength;\r\n\r\n\t\t\t\tconn->m_WaitingForSequenceId[msg_link->m_GroupId]++;\r\n\r\n\t\t\t\tresult = m_Dispatcher.DispatchMessage( &msg_context );\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\tif( result != HANDLER_MSG_DESTROYED )\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete msg_link->m_QMsg;\r\n\t\t\t\t\tdelete msg_link;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// If we've gotten a false result, that means we should\r\n\t\t\t\t// stop processing this connection\r\n\t\t\t\tif( result != HANDLER_CONTINUE )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n#ifdef NET_DEBUG_MESSAGES\r\n\t\t\t\tstatic unsigned int stall = 0;\r\n\r\n\t\t\t\tif( stall != msg_link->m_SequenceId )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Printf( \"*** Stalling on seq: %d, waiting for %d : msg %d, group %d\\n\", \r\n\t\t\t\t\t\t\t\tmsg_link->m_SequenceId, conn->m_WaitingForSequenceId[msg_link->m_GroupId],\r\n\t\t\t\t\t\t\t\tmsg_link->m_QMsg->m_MsgId, msg_link->m_GroupId );\r\n\t\t\t\t\tstall = msg_link->m_SequenceId;\r\n\t\t\t\t}\r\n#endif\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Kill off invalid connections. Should be done at a safe time.   */\r\n/* i.e. when you're not processing connections anymore            */\r\n/******************************************************************/\r\n\r\nvoid\tApp::terminate_invalid_connections( void )\r\n{\r\n\tConn *conn, *next_conn;\r\n\tLst::Search< Conn > sh;\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tWaitSema( m_transfer_semaphore_id );\r\n#endif\t// __PLAT_NGPS__    \r\n\tfor( conn = FirstConnection( &sh ); conn;\r\n\t\t\tconn = next_conn )\r\n\t{\r\n\t\tnext_conn = NextConnection( &sh );\r\n\r\n\t\t// If we're in the process of disconnecting them and we have no more messages\r\n\t\t// to send them, go ahaed and disconnect them\r\n\t\tif( conn->TestStatus( Conn::mSTATUS_DISCONNECTING ))\r\n\t\t{\r\n\t\t\tif( MessagesToSend( conn ) == false )\r\n\t\t\t{\r\n\t\t\t\tconn->Invalidate();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Destroy invalid connections\r\n\t\tif( conn->IsValid() == false )\r\n\t\t{\r\n\t\t\tif( ( MessagesToProcess( conn ) == false ) && \r\n\t\t\t\t( MessagesToSend( conn ) == false ))\r\n\t\t\t{\r\n\t\t\t\tTerminateConnection( conn );\r\n\t\t\t}\r\n\t\t}\r\n\t}       \r\n#ifdef __PLAT_NGPS__\r\n\tSignalSema( m_transfer_semaphore_id );\r\n#endif\t// __PLAT_NGPS__    \r\n}\r\n\r\n/******************************************************************/\r\n/* Processes any pending stream messages. Enqueuing data if the\t  */\r\n/* sliding window permits it                                      */\r\n/******************************************************************/\r\n\r\nvoid    App::process_stream_messages( void )\r\n{\r\n\tint size, packet_len, msg_len;\r\n\tMsgStreamData data_msg;\r\n\tMsgDesc msg_desc;\r\n\tStreamDesc* stream_desc;\r\n\tStreamLink* stream_link, *next_link;\r\n\tConn *conn;\r\n\tLst::Search< Conn > sh;\r\n\tLst::Search< StreamLink > stream_sh;\r\n\tint num_pending, num_to_send;\r\n\tNet::Manager* net_man = Net::Manager::Instance();\r\n\r\n\tfor( conn = FirstConnection( &sh ); conn; conn = NextConnection( &sh ))\r\n\t{\r\n\t\tint pending_threshold, max_to_send;\r\n\r\n\t\tpending_threshold = 5;\r\n\t\tmax_to_send = 3;\r\n\t\tif(( net_man->GetConnectionType() == Net::vCONN_TYPE_MODEM ) ||\r\n\t\t   ( conn->GetBandwidthType() == Conn::vNARROWBAND ))\r\n\t\t{\r\n\t\t\tpending_threshold = 2;\r\n\t\t\tmax_to_send = 1;\r\n\t\t}\r\n\t\t// If we have any pending streams, see if there is any room to queue up chunks\r\n\t\tif( conn->m_StreamOutList.CountItems() > 0 )\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"******** %d items remain to stream\\n\", conn->m_StreamOutList.CountItems());\r\n\t\t\tnum_pending = conn->GetNumPendingStreamMessages();\r\n\t\t\tif( num_pending < pending_threshold ) // Should be configurable and dynamic\r\n\t\t\t{\r\n\t\t\t\tnum_to_send = pending_threshold - num_pending;\r\n\t\t\t\tif( num_to_send > max_to_send )\r\n\t\t\t\t{\r\n\t\t\t\t\tnum_to_send = max_to_send;\r\n\t\t\t\t}\r\n\t\t\t\tfor( stream_link = stream_sh.FirstItem( conn->m_StreamOutList ); stream_link; stream_link = next_link )\r\n\t\t\t\t{\r\n\t\t\t\t\tnext_link = stream_sh.NextItem();\r\n\r\n\t\t\t\t\tstream_desc = stream_link->m_Desc;\r\n\t\t\t\t\tsize = (unsigned int) stream_desc->m_DataPtr - (unsigned int) stream_desc->m_Data;\r\n\t\t\t\t\tmsg_len = stream_desc->m_Size;\r\n\t\t\t\t\twhile(( size < msg_len ) && ( num_to_send > 0 ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpacket_len = msg_len - size;\r\n\t\t\t\t\t\tif( packet_len > MAX_STREAM_CHUNK_LENGTH )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tpacket_len = MAX_STREAM_CHUNK_LENGTH;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t\t\tdata_msg.m_StreamId = stream_desc->m_StreamId;\r\n\t\t\t\t\t\tmemcpy( data_msg.m_Data, stream_desc->m_DataPtr, packet_len );\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tmsg_desc.m_Id = MSG_ID_STREAM_DATA;\r\n\t\t\t\t\t\tmsg_desc.m_Data = &data_msg;\r\n\t\t\t\t\t\tmsg_desc.m_Length = packet_len + sizeof( int );\r\n\t\t\t\t\t\tmsg_desc.m_Queue = QUEUE_SEQUENCED;\r\n\t\t\t\t\t\tmsg_desc.m_GroupId = stream_desc->m_GroupId;\r\n\t\t\t\t\t\tmsg_desc.m_StreamMessage = 1;\r\n\t\t\t\t\t\tmsg_desc.m_ForcedSequenceId = stream_desc->m_SequenceId++;\r\n\t\t\t\t\r\n\t\t\t\t\t\t//Dbg_Printf( \"%d ******** [%d] Streaming %d bytes. ForcedSequence: %d\\n\", m_FrameCounter, stream_desc->m_StreamId, packet_len, stream_desc->m_SequenceId );\r\n\t\t\t\t\t\tEnqueueMessage( conn->GetHandle(), &msg_desc );\r\n\t\t\t\t\r\n\t\t\t\t\t\tstream_desc->m_DataPtr += packet_len;\r\n\t\t\t\t\t\tsize += packet_len;\r\n\r\n\t\t\t\t\t\tnum_to_send--;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif( size >= msg_len )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//Dbg_Printf( \"******** [%d] Finished streaming. Destroying Stream Link\\n\", stream_desc->m_StreamId );\r\n\t\t\t\t\t\tdelete stream_desc;\r\n\t\t\t\t\t\tdelete stream_link;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Read the data from the stack and store in appropriate conn     */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::read_network_data( const Tsk::Task< App > &task )\r\n{\r\n\tApp *app;\r\n    \r\n    app = &task.GetData();\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tapp->m_double_timestamp += ( Tmr::UncappedFrameLength() * 60.0f ) * \r\n\t\t\t\t\t\t\t\t\t( Tmr::vRESOLUTION / 60.0f );\r\n\tapp->m_Timestamp = (unsigned int) app->m_double_timestamp;\r\n#else\r\n\tapp->m_Timestamp = Tmr::GetTime();\r\n#endif // _PLAT_NGPS__\r\n\r\n\tapp->terminate_invalid_connections();\r\n\t\r\n#ifdef __PLAT_NGPS__\r\n\tWaitSema( app->m_transfer_semaphore_id );\r\n\tSignalSema( app->m_transfer_semaphore_id );\r\n\tWakeupThread( app->m_socket_thread_id );\r\n#else\r\n\tapp->ReceiveData();\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/* Service metrics data                 \t\t\t\t\t  \t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::service_network_metrics( const Tsk::Task< App > &task )\r\n{\r\n\tApp *app;\r\n\tConn *conn;\r\n\tLst::Search< Conn > sh;\r\n    \r\n    app = &task.GetData();\r\n\tDbg_Assert( app );\r\n\r\n\tfor( conn = app->FirstConnection( &sh ); conn; conn = app->NextConnection( &sh ))\r\n\t{\r\n\t\tconn->GetInboundMetrics()->CalculateBytesPerSec( app->m_Timestamp );\r\n\t\tconn->GetOutboundMetrics()->CalculateBytesPerSec( app->m_Timestamp );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Process network data task                 \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::process_network_data( const Tsk::Task< App > &task )\r\n{\r\n\tApp *app;\r\n    \r\n    app = &task.GetData();\r\n\tDbg_Assert( app );\r\n\t\r\n\t\tapp->m_FrameCounter++;\r\n\r\n#\tifdef __USE_PROFILER__\r\n\tSys::CPUProfiler->PushContext( 255, 255, 255 );\r\n#\tendif // __USE_PROFILER__\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tWaitSema( app->m_receive_semaphore_id );\r\n#endif\t// __PLAT_NGPS__    \r\n\tapp->ProcessData(); \r\n#ifdef __PLAT_NGPS__\r\n\tSignalSema( app->m_receive_semaphore_id );\r\n#endif\t// __PLAT_NGPS__    \r\n\r\n#\tifdef __USE_PROFILER__\r\n\tSys::CPUProfiler->PopContext();\r\n#\tendif // __USE_PROFILER__\r\n}\r\n\r\n/******************************************************************/\r\n/* Threaded send/receive data for the PS2\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\nvoid\tApp::threaded_transfer_data( void *data )\r\n{\r\n\t\r\n    Net::App* app = (Net::App *) data;\r\n    \r\n\tWaitSema( app->m_active_semaphore_id );\r\n\r\n\tif( !app->IsLocal())\r\n\t{\r\n#ifdef DEBUG_MESSAGES\r\n\t\tDbg_Printf( \"Registering transfer thread %d with stack\\n\", GetThreadId());\r\n#endif\r\n\t\r\n#ifdef __NOPT_ASSERT__\r\n\t\tint result = \r\n#endif\t\t\r\n\t\tsockAPIregthr();\r\n\t\tDbg_Assert( result == 0 );\r\n\t}\r\n\r\n\tapp->m_socket_thread_active = true;\r\n\t\r\n\tapp->TransferData();\r\n\r\n\tif( !app->IsLocal())\r\n\t{   \r\n#ifdef DEBUG_MESSAGES\r\n\t\tDbg_Printf( \"DeRegistering transfer thread %d with stack\\n\", GetThreadId());\r\n#endif\r\n\t\tsockAPIderegthr();\r\n\t}\r\n\r\n\tapp->m_socket_thread_active = false;\r\n\t\r\n\tSignalSema( app->m_active_semaphore_id );\r\n}\r\n\r\n#endif\r\n\r\n/******************************************************************/\r\n/* Send queued messages across the wire                           */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::send_network_data( const Tsk::Task< App > &task )\r\n{\r\n\tApp *app;\r\n\r\n\tapp = &task.GetData();\r\n\tDbg_Assert( app );\r\n\r\n\tapp->process_stream_messages();\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tWaitSema( app->m_transfer_semaphore_id );\r\n\tSignalSema( app->m_transfer_semaphore_id );\r\n\tWakeupThread( app->m_socket_thread_id );\r\n#else\r\n\tapp->SendData( true );    \r\n#endif\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::crc_and_copy_stream( char* in_stream, char* out_stream, int in_len, int* out_len )\r\n{\r\n\tuint32 actual_crc;\t\r\n\tint i;\r\n\tunsigned char* in, *out;\r\n\tunsigned char key;\r\n\tunsigned short hi_word, lo_word, sum_crc;\r\n\r\n\t\r\n\t\r\n\tDbg_Assert( out_stream );\r\n\tDbg_Assert( in_stream );\r\n\tDbg_Assert( in_len > 0 );\r\n\t\r\n\tactual_crc = Crc::GenerateCRCCaseSensitive( in_stream, in_len );\r\n\thi_word = ( actual_crc & 0xFFFF0000 ) >> 16;\r\n\tlo_word = ( actual_crc & 0xFFFF );\r\n\tsum_crc = hi_word + lo_word;\r\n\r\n\tmemcpy( out_stream, &sum_crc, sizeof( unsigned short ));\r\n\r\n\t// Encrypt by XOring each byte with the lsB of the checksum\r\n\tout = (unsigned char*) ( out_stream + sizeof( unsigned short ));\r\n\tin = (unsigned char*) in_stream;\r\n\tkey = (unsigned char) sum_crc;\r\n\tfor( i = 0; i < in_len; i++ )\r\n\t{\r\n\t\t*out++ = ( *in++ ) ^ key;\r\n\t}\r\n\t\r\n\t*out_len = in_len + sizeof( unsigned short );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tApp::validate_and_copy_stream( char* in_stream, char* out_stream, int in_len )\r\n{\r\n    uint32 actual_crc;\r\n\tint out_len;\r\n\tunsigned char key;\r\n\tunsigned short hi_word, lo_word;\r\n\tunsigned short packet_crc, sum_crc;\r\n\tunsigned char* in;\r\n\tint i;\r\n\tchar packet_data[ Manager::vMAX_PACKET_SIZE ];\r\n\r\n\t\r\n\t\r\n\tDbg_Assert( out_stream );\r\n\tDbg_Assert( in_stream );\r\n\t\t\r\n\tif( in_len < Manager::vMIN_PACKET_SIZE )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// If this isn't a secure app, just process the data as unencrypted and un-checksumed\r\n\tif(( m_flags & mSECURE ) == 0 )\r\n\t{\r\n\t\tmemcpy( out_stream, in_stream, in_len );\r\n\t\treturn true;\r\n\t}\r\n\r\n\tout_len = in_len - sizeof( unsigned short );\r\n\tmemcpy( &packet_crc, in_stream, sizeof( unsigned short ));\r\n\tmemcpy( packet_data, in_stream + sizeof( unsigned short ), out_len );\t// skip CRC\r\n\r\n\tkey = (unsigned char) packet_crc;\t// use the lsB of the packet CRC to decrypt the packet\r\n\tin = (unsigned char*) packet_data;\r\n\tfor( i = 0; i < out_len; i++ )\r\n\t{\r\n\t\t*in = (*in) ^ key;\r\n\t\tin++;\r\n\t}\r\n\r\n\tactual_crc = Crc::GenerateCRCCaseSensitive( packet_data, out_len );\r\n\thi_word = ( actual_crc & 0xFFFF0000 ) >> 16;\r\n\tlo_word = ( actual_crc & 0xFFFF );\r\n\tsum_crc = hi_word + lo_word;\r\n\tif( sum_crc != packet_crc )\r\n\t{\r\n#ifdef DEBUG_MESSAGES\r\n\t\tDbg_Printf( \"CRC Check Failed!!! Got %d instead of %d\\n\", packet_crc, sum_crc );\r\n#endif\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tmemcpy( out_stream, packet_data, out_len );\r\n\r\n#ifdef WRITE_OUT_NET_PACKETS\r\n\tstatic int f = 0;\r\n\tchar path[32];\r\n\r\n\tsprintf( path, \"jpacket%d.net\", f );\r\n\tvoid* handle;\r\n\r\n\thandle = File::Open( path, \"wb\");\r\n\tif( handle )\r\n\t{\r\n\t\tFile::Write( out_stream, 1, out_len, handle );\r\n\t\tFile::Close( handle );\t\r\n\t\tf++;\r\n\t}\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nLatencyTest::LatencyTest( void )\r\n{\r\n\tmemset( m_TimeTests, 0, sizeof( int ) * NET_NUM_LATENCY_TESTS );\r\n\tm_AveLatency = Manager::vSTANDARD_RESEND_THRESHOLD / 2;\r\n\tm_CurrentTest = 0;\r\n\tm_SendTime = 0;\r\n\tm_ReceiveTime = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/* Add data to our latency calculator                             */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tLatencyTest::InputLatencyValue( int latency )\r\n{\r\n\tint i, num_tests, total;\r\n\r\n\tm_TimeTests[ m_CurrentTest ] = latency;\r\n\tm_CurrentTest = ( m_CurrentTest + 1 ) % NET_NUM_LATENCY_TESTS;\r\n\r\n\ttotal = 0;\r\n\tnum_tests = 0;\r\n\t// compute new average\r\n\tfor( i = 0; i < NET_NUM_LATENCY_TESTS; i++ )\r\n\t{\r\n\t\tif( m_TimeTests[i] != 0 )\r\n\t\t{\r\n\t\t\ttotal += m_TimeTests[i];\r\n\t\t\tnum_tests++;\r\n\t\t}\r\n\t}\r\n\r\n\tif( num_tests > 0 )\r\n\t{\r\n        m_AveLatency = total/num_tests;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nApp::App( int flags )\r\n: m_Dispatcher( this ), m_node( this )\r\n{\r\n\tm_network_metrics_task = new Tsk::Task< App > ( service_network_metrics, *this, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_PROCESS_NETWORK_METRICS );\r\n\tm_receive_network_data_task = new Tsk::Task< App > ( read_network_data, *this, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_RECEIVE_NETWORK_DATA );\r\n\tm_process_network_data_task = new Tsk::Task< App > ( process_network_data, *this,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_PROCESS_NETWORK_DATA );\r\n\tm_double_timestamp = 0;\r\n\tm_flags = flags;\r\n\tm_Timestamp = 0;\r\n\tm_foreign_handler = NULL;\r\n#ifdef\t__PLAT_NGPS__\t\t\t\t\t\t\t\t\t\t\t  \r\n\tDbg_MsgAssert(Mem::SameContext(this,Mem::Manager::sHandle().NetworkHeap()),(\"Net::App not on network heap\"));\t\r\n#endif\t\t//\t__PLAT_NGPS__\t\t\t\t\t\t\t\t\t\t\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nApp::~App( void )\r\n{\r\n\t\r\n\tBannedConn* banned_conn, *next;\r\n\tLst::Search< BannedConn > sh;\r\n\t\r\n\tfor( banned_conn = sh.FirstItem( m_banned_connections ); banned_conn;\r\n\t\t\tbanned_conn = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tdelete banned_conn;\r\n\t}\r\n\t\r\n    \r\n\tdelete m_send_network_data_task;\r\n\tdelete m_receive_network_data_task;\r\n    delete m_process_network_data_task;\r\n\tdelete m_network_metrics_task;\r\n}\r\n\r\n/******************************************************************/\r\n/* Processes the messages in the input queue and also sequenced   */\r\n/* messages. Sends them off to the dispatcher                     */\r\n/******************************************************************/\r\n\r\nvoid\tApp::ProcessData( void )\r\n{\r\n\tConn *conn, *next_conn;\r\n\tLst::Search< Conn > sh;\r\n\tint result;\r\n\r\n\tfor( conn = FirstConnection( &sh ); conn;\r\n\t\t\tconn = next_conn )\r\n\t{   \r\n\t\tnext_conn = NextConnection( &sh );\r\n\r\n\t\tif( conn->IsLocal() &&\r\n\t\t\tconn->m_alias_connection )\r\n\t\t{   \r\n\t\t\tint num_bytes;\r\n\t\t\t\r\n\t\t\tnum_bytes = (int) conn->m_alias_connection->m_write_ptr - \r\n\t\t\t\t\t\t\t(int) conn->m_alias_connection->m_write_buffer;\r\n\t\t\tmemcpy( conn->m_read_ptr, conn->m_alias_connection->m_write_buffer, num_bytes );\r\n\t\t\tconn->m_alias_connection->m_write_ptr = conn->m_alias_connection->m_write_buffer;\r\n\t\t\tconn->m_read_ptr += num_bytes;\r\n\t\t}\r\n\r\n\t\tresult = m_Dispatcher.DispatchMsgHandlers( conn, 0 );\r\n\t\tif( result == HANDLER_ERROR )\r\n\t\t{\r\n\t\t\t// output that we've received mal-formatted data\r\n\t\t}\r\n\t\telse if( result == HANDLER_HALT )\t// something terminable happened\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tprocess_sequenced_messages( conn );\r\n\t}\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/* Given an ip/port combo, return the corresponding connection    */\r\n/* if one exists                                                  */\r\n/******************************************************************/\r\n\r\nConn *App::GetConnectionByAddress( int ip, unsigned short port )\r\n{\r\n\tLst::Search< Conn > sh;\r\n\tConn *conn;\r\n\r\n\tfor( conn = sh.FirstItem( m_connections ); \r\n\t\t\tconn; conn = sh.NextItem())\r\n\t{\r\n\t\tif(( conn->GetIP() == ip ) && ( conn->GetPort() == port ))\r\n\t\t{\r\n\t\t\treturn conn;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/* Given a handle, return the connection if there is a match      */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nConn *App::GetConnectionByHandle( int handle )\r\n{\r\n\tLst::Search< Conn > sh;\r\n\tConn *conn;\r\n\r\n\tfor( conn = sh.FirstItem( m_connections ); \r\n\t\t\tconn; conn = sh.NextItem())\r\n\t{\r\n\t\tif( conn->GetHandle() == handle )\r\n\t\t{\r\n\t\t\treturn conn;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\tApp::GetID( void )\r\n{\r\n\treturn m_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar\t\t*App::GetName( void )\r\n{\r\n\treturn m_name;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nTsk::BaseTask&\tApp::GetSendDataTask( void )\r\n{\r\n\treturn *m_send_network_data_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nTsk::BaseTask&\tApp::GetReceiveDataTask( void )\r\n{\r\n\treturn *m_receive_network_data_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nTsk::BaseTask&\tApp::GetProcessDataTask( void )\r\n{\r\n\treturn *m_process_network_data_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nTsk::BaseTask&\tApp::GetNetworkMetricsTask( void )\r\n{\r\n\treturn *m_network_metrics_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*  Create a new connection for an ip/port combo                  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nConn *App::NewConnection( int ip, unsigned short port, int flags )\r\n{\r\n\tConn *conn;\r\n\t\r\n\t\r\n\r\n\tconn = NULL;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\tif( m_num_connections < m_max_connections )\r\n\t{\r\n\t\tconn = new Conn( flags );\r\n\t\tconn->SetIP( ip );\r\n\t\tconn->SetPort( port );\r\n\t\tconn->m_handle = get_free_handle();\r\n\t\tconn->m_app = this;\r\n\t\tconn->m_last_comm_time = Tmr::GetTime();\r\n\t\tm_connections.AddToTail( &conn->m_node );\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn conn;\r\n}\r\n\r\n/******************************************************************/\r\n/* Allocate a new sequenced message with a header                 */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nQueuedMsgSeq*\tApp::AllocateNewSeqMessage( unsigned char msg_id, unsigned short msg_len, char* data, unsigned char group_id )\r\n{\r\n\tQueuedMsgSeq* queued_msg;\r\n\r\n\tqueued_msg = new QueuedMsgSeq( msg_id, msg_len, data, group_id );\r\n\r\n\treturn queued_msg;\r\n}\r\n\r\n/******************************************************************/\r\n/* Build the outgoing stream to send to a connection.  This       */\r\n/* will also re-send important messages which haven't been acked  */\r\n/******************************************************************/\r\n\r\nbool App::BuildMsgStream( Conn *conn, QUEUE_TYPE queue, bool resends_only )\r\n{\r\n\tbool all_fit;\r\n\tunsigned short total_msg_len;\r\n\r\n\tall_fit = true;\r\n\r\n\tDbg_Assert( conn );\r\n\t// For each queue, copy all messages into what will be the final\r\n\t// buffer to send over the net\r\n\tswitch( queue )\r\n\t{\r\n\t\tcase QUEUE_DEFAULT:\r\n\t\t{\r\n\t\t\tLst::Search< MsgLink > sh;\r\n\t\t\tMsgLink *msg_link, *next_link;\r\n\t\t\tQueuedMsg* queued_msg;\r\n\t\t\t\t\t\t\r\n\t\t\tfor( msg_link = sh.FirstItem( conn->m_normal_msg_list ); msg_link; msg_link = next_link )\r\n\t\t\t{   \r\n\t\t\t\tint msg_header_size;\r\n\r\n\t\t\t\tnext_link = sh.NextItem();\r\n\t\t\t\tif( m_Timestamp < msg_link->m_SendTime )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( BandwidthExceeded( conn ))\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tqueued_msg = msg_link->m_QMsg;              \r\n\t\t\t\tif( m_net_man->GetMessageFlags( queued_msg->m_MsgId ) & mMSG_SIZE_UNKNOWN )\r\n\t\t\t\t{\r\n\t\t\t\t\tmsg_header_size = Manager::vMSG_HEADER_LENGTH;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tmsg_header_size = Manager::vMSG_HEADER_LENGTH_WITH_SIZE;\r\n\t\t\t\t}\r\n\t\t\t\ttotal_msg_len = msg_header_size + queued_msg->m_MsgLength;\r\n\t\t\t\tif((( conn->m_write_ptr - conn->m_write_buffer ) + total_msg_len ) < Manager::vMAX_PAYLOAD )\r\n\t\t\t\t{\r\n\t\t\t\t\tmemcpy( conn->m_write_ptr, &queued_msg->m_MsgId, sizeof( unsigned char ));\r\n\t\t\t\t\tconn->m_write_ptr += sizeof( unsigned char );\r\n\t\t\t\t\t// Optionally write out the message's size to the stream\r\n\t\t\t\t\tif(( m_net_man->GetMessageFlags( queued_msg->m_MsgId ) & mMSG_SIZE_UNKNOWN ) == 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmemcpy( conn->m_write_ptr, &queued_msg->m_MsgLength, sizeof( unsigned short ));\r\n\t\t\t\t\t\tconn->m_write_ptr += sizeof( unsigned short );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif( queued_msg->m_MsgLength > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmemcpy( conn->m_write_ptr, queued_msg->m_Data, queued_msg->m_MsgLength );\r\n\t\t\t\t\t\tconn->m_write_ptr += queued_msg->m_MsgLength;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconn->GetOutboundMetrics()->AddMessage( queued_msg->m_MsgId, queued_msg->m_MsgLength );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// K: Moved this here so that multiple EnqueueMessage's can be done in one frame\r\n\t\t\t\t\t// without earlier ones being dropped.\r\n\t\t\t\t\t// Otherwise CScriptDebugger::SplitAndEnqueueMessage will not work, because\r\n\t\t\t\t\t// only the last message enqueued will get through.\r\n\t\t\t\t\tqueued_msg->m_Ref.Release();\r\n\t\t\t\t\tif( queued_msg->m_Ref.InUse() == false )\r\n\t\t\t\t\t{   \r\n\t\t\t\t\t\tdelete queued_msg;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdelete msg_link;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tall_fit = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase QUEUE_IMPORTANT:\r\n\t\t{\r\n\t\t\tMsgImpLink *msg_link;\r\n\t\t\tLst::Search< MsgImpLink > sh;\r\n\t\t\tQueuedMsg* queued_msg;\r\n\t\t\t\t\t\t\r\n\t\t\tfor( msg_link = sh.FirstItem( conn->m_important_msg_list ); msg_link; \r\n\t\t\t\t\tmsg_link = sh.NextItem())\r\n\t\t\t{\r\n\t\t\t\tif( m_Timestamp < msg_link->m_SendTime )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( BandwidthExceeded( conn ))\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif(( msg_link->m_Timestamp == 0 ) && resends_only )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// resend if it takes longer than roughly twice the latency\r\n\t\t\t\tif( ( msg_link->m_Timestamp == 0 ) ||\t// i.e. hasn't been sent yet\r\n\t\t\t\t\t(( m_Timestamp - msg_link->m_Timestamp ) > (unsigned int) conn->GetResendThreshold()))\r\n\t\t\t\t{\r\n\t\t\t\t\tint msg_header_size;\r\n\r\n\t\t\t\t\tqueued_msg = msg_link->m_QMsg;\r\n#ifdef DEBUG_MESSAGES\r\n\t\t\t\t\tif( conn->IsRemote())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( msg_link->m_Timestamp != 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tDbg_Printf( \"** RESEND #%d (%d) Conn %d: (%d) %s T %d %d, P %d %d, L %d %d\\n\", \r\n\t\t\t\t\t\t\t\tmsg_link->m_NumResends + 1,\r\n\t\t\t\t\t\t\t\tm_FrameCounter,\r\n\t\t\t\t\t\t\t\tconn->GetHandle(),\r\n\t\r\n\t\t\t\t\t\t\t\tqueued_msg->m_MsgId,\r\n\t\t\t\t\t\t\t\tm_net_man->GetMessageName( queued_msg->m_MsgId ),\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tm_Timestamp,\r\n\t\t\t\t\t\t\t\tmsg_link->m_Timestamp,\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tconn->m_latest_sent_packet_stamp,\r\n\t\t\t\t\t\t\t\tmsg_link->m_Packetstamp,\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tconn->GetResendThreshold(),\r\n\t\t\t\t\t\t\t\tconn->GetAveLatency());\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\tif( m_net_man->GetMessageFlags( queued_msg->m_MsgId ) & mMSG_SIZE_UNKNOWN )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmsg_header_size = Manager::vMSG_HEADER_LENGTH;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmsg_header_size = Manager::vMSG_HEADER_LENGTH_WITH_SIZE;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttotal_msg_len = msg_header_size + queued_msg->m_MsgLength;\r\n\t\t\t\t\tif((( conn->m_write_ptr - conn->m_write_buffer ) + total_msg_len ) < Manager::vMAX_PAYLOAD )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmemcpy( conn->m_write_ptr, &queued_msg->m_MsgId, sizeof( unsigned char ));\r\n\t\t\t\t\t\tconn->m_write_ptr += sizeof( unsigned char );\r\n\t\t\t\t\t\t// Optionally write out the message's size to the stream\r\n\t\t\t\t\t\tif(( m_net_man->GetMessageFlags( queued_msg->m_MsgId ) & mMSG_SIZE_UNKNOWN ) == 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmemcpy( conn->m_write_ptr, &queued_msg->m_MsgLength, sizeof( unsigned short ));\r\n\t\t\t\t\t\t\tconn->m_write_ptr += sizeof( unsigned short );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif( queued_msg->m_MsgLength > 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmemcpy( conn->m_write_ptr, queued_msg->m_Data, queued_msg->m_MsgLength );\r\n\t\t\t\t\t\t\tconn->m_write_ptr += queued_msg->m_MsgLength;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tconn->GetOutboundMetrics()->AddMessage( queued_msg->m_MsgId, queued_msg->m_MsgLength );\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif( msg_link->m_Timestamp != 0 )\r\n\t\t\t\t\t\t{   \r\n\t\t\t\t\t\t\tmsg_link->m_NumResends++;\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tmsg_link->m_Timestamp = m_Timestamp;\r\n\t\t\t\t\t\tmsg_link->m_Packetstamp = conn->m_latest_sent_packet_stamp;\r\n\t\t\t\t\t}\t\t\t\t\t\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tall_fit = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase QUEUE_SEQUENCED:\r\n\t\t{\r\n\t\t\tMsgSeqLink *msg_link;\r\n\t\t\tLst::Search< MsgSeqLink > sh;\r\n\t\t\tQueuedMsgSeq* queued_msg;\r\n\t\t\tunsigned char seq_msg_id;\r\n\t\t\tunsigned short seq_msg_length;\r\n\t\t\t\t\t\t\r\n\t\t\tseq_msg_id = MSG_ID_SEQUENCED;\r\n\t\t\tfor( msg_link = sh.FirstItem( conn->m_sequenced_msg_list ); msg_link; \r\n\t\t\t\t\tmsg_link = sh.NextItem())\r\n\t\t\t{   \r\n\t\t\t\tif( m_Timestamp < msg_link->m_SendTime )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( BandwidthExceeded( conn ))\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif(( msg_link->m_Timestamp == 0 ) && resends_only )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// resend if it takes longer than roughly twice the latency\r\n\t\t\t\tif( ( msg_link->m_Timestamp == 0 ) ||\t// i.e. hasn't been sent yet\r\n\t\t\t\t\t(( m_Timestamp - msg_link->m_Timestamp ) > (unsigned int) conn->GetResendThreshold()))\r\n\t\t\t\t{\r\n\t\t\t\t\tqueued_msg = msg_link->m_QMsg;\r\n#ifdef DEBUG_MESSAGES\r\n\t\t\t\t\tif( conn->IsRemote())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( msg_link->m_Timestamp != 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tDbg_Printf( \"** RESEND #%d (%d) Conn %d: (%d) %s T %d %d, P %d %d, Seq: %d Group: %d\\n\", \r\n\t\t\t\t\t\t\t\tmsg_link->m_NumResends + 1,\r\n\t\t\t\t\t\t\t\tm_FrameCounter,\r\n\t\t\t\t\t\t\t\tconn->GetHandle(),\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tqueued_msg->m_MsgId,\r\n\t\t\t\t\t\t\t\tm_net_man->GetMessageName( queued_msg->m_MsgId ),\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tm_Timestamp,\r\n\t\t\t\t\t\t\t\tmsg_link->m_Timestamp,\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tconn->m_latest_sent_packet_stamp,\r\n\t\t\t\t\t\t\t\tmsg_link->m_Packetstamp,\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tmsg_link->m_SequenceId,\r\n\t\t\t\t\t\t\t\tmsg_link->m_GroupId );\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t}\t\t\t\t\t\t\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\ttotal_msg_len = Manager::vMSG_HEADER_LENGTH_WITH_SIZE + Manager::vMSG_SEQ_HEADER_LENGTH + queued_msg->m_MsgLength;\r\n\t\t\t\t\tseq_msg_length = Manager::vMSG_SEQ_HEADER_LENGTH + queued_msg->m_MsgLength;\r\n\t\t\t\t\tif((( conn->m_write_ptr - conn->m_write_buffer ) + total_msg_len ) < ( Manager::vMAX_PAYLOAD ))\r\n\t\t\t\t\t{\t\t\t\t\t\t\r\n\t\t\t\t\t\tmemcpy( conn->m_write_ptr, &seq_msg_id, sizeof( unsigned char ));\r\n\t\t\t\t\t\tconn->m_write_ptr += sizeof( unsigned char );\r\n                        memcpy( conn->m_write_ptr, &seq_msg_length, sizeof( unsigned short ));\r\n\t\t\t\t\t\tconn->m_write_ptr += sizeof( unsigned short );\r\n                        memcpy( conn->m_write_ptr, &msg_link->m_GroupId, sizeof( char ));\r\n\t\t\t\t\t\tconn->m_write_ptr += sizeof( char );\r\n\t\t\t\t\t\tmemcpy( conn->m_write_ptr, &msg_link->m_SequenceId, sizeof( unsigned int ));\r\n\t\t\t\t\t\tconn->m_write_ptr += sizeof( unsigned int );\r\n\t\t\t\t\t\tmemcpy( conn->m_write_ptr, &queued_msg->m_MsgId, sizeof( unsigned char ));\r\n\t\t\t\t\t\tconn->m_write_ptr += sizeof( unsigned char );\r\n\t\t\t\t\t\tif( queued_msg->m_MsgLength > 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmemcpy( conn->m_write_ptr, queued_msg->m_Data, queued_msg->m_MsgLength );\r\n\t\t\t\t\t\t\tconn->m_write_ptr += queued_msg->m_MsgLength;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tconn->GetOutboundMetrics()->AddMessage( queued_msg->m_MsgId, queued_msg->m_MsgLength );\r\n\t\t\t\t\t\tif( msg_link->m_Timestamp != 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmsg_link->m_NumResends++;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tmsg_link->m_Timestamp = m_Timestamp;\r\n\t\t\t\t\t\tmsg_link->m_Packetstamp = conn->m_latest_sent_packet_stamp;\r\n\t\t\t\t\t}                   \r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tall_fit = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\treturn all_fit;\r\n}\r\n\r\n/******************************************************************/\r\n/* Any pending messages to process from this client??     \t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tApp::MessagesToProcess( Conn* conn )\r\n{\r\n\tif( conn->m_read_ptr > conn->m_read_buffer )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/* Are there any important messages to send?\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tApp::ImportantMessagesToSend( Conn* conn )\r\n{\r\n\t{\r\n\t\tMsgImpLink *msg_link;\r\n\t\tLst::Search< MsgImpLink > imp_sh;\r\n\t\tfor( msg_link = imp_sh.FirstItem( conn->m_important_msg_list ); \r\n\t\t\t\tmsg_link; msg_link = imp_sh.NextItem())\r\n\t\t{\r\n\t\t\t// resend if it takes longer than roughly twice the latency\r\n\t\t\tif(\t( msg_link->m_Timestamp == 0 ) ||\r\n\t\t\t\t(( m_Timestamp - msg_link->m_Timestamp ) > (unsigned int) conn->GetResendThreshold()))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t{\r\n\t\tMsgSeqLink *msg_link;\r\n\t\tLst::Search< MsgSeqLink > seq_sh;\r\n\t\tfor( msg_link = seq_sh.FirstItem( conn->m_sequenced_msg_list ); \r\n\t\t\t\tmsg_link; msg_link = seq_sh.NextItem())\r\n\t\t{\r\n\t\t\t// resend if it takes longer than roughly twice the latency\r\n\t\t\tif( ( msg_link->m_Timestamp == 0 ) || \r\n\t\t\t\t(( m_Timestamp - msg_link->m_Timestamp ) > (unsigned int) conn->GetResendThreshold()))\r\n\t\t\t{\r\n\t\t\t\treturn true;\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/* Are there any messages to send to a particular connection?     */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tApp::MessagesToSend( Conn* conn )\r\n{   \r\n\t{\r\n\t\tLst::Search< MsgLink > sh;\r\n\t\tMsgLink* msg_link;\r\n\t\tfor( msg_link = sh.FirstItem( conn->m_normal_msg_list ); \r\n\t\t\t\tmsg_link; msg_link = sh.NextItem())\r\n\t\t{\r\n\t\t\tif( m_Timestamp < msg_link->m_SendTime )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t{\r\n\t\tMsgImpLink *msg_link;\r\n\t\tLst::Search< MsgImpLink > imp_sh;\r\n\t\tfor( msg_link = imp_sh.FirstItem( conn->m_important_msg_list ); \r\n\t\t\t\tmsg_link; msg_link = imp_sh.NextItem())\r\n\t\t{\r\n\t\t\t// resend if it takes longer than roughly twice the latency\r\n\t\t\tif( ( msg_link->m_Timestamp == 0 ) ||\r\n\t\t\t\t( m_Timestamp < msg_link->m_SendTime ) ||\r\n\t\t\t\t(( m_Timestamp - msg_link->m_Timestamp ) > (unsigned int) conn->GetResendThreshold()))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t{\r\n\t\tMsgSeqLink *msg_link;\r\n\t\tLst::Search< MsgSeqLink > seq_sh;\r\n\t\tfor( msg_link = seq_sh.FirstItem( conn->m_sequenced_msg_list ); \r\n\t\t\t\tmsg_link; msg_link = seq_sh.NextItem())\r\n\t\t{\r\n\t\t\t// resend if it takes longer than roughly twice the latency\r\n\t\t\tif(\t( msg_link->m_Timestamp == 0 ) || \r\n\t\t\t\t( m_Timestamp < msg_link->m_SendTime ) ||\r\n\t\t\t\t(( m_Timestamp - msg_link->m_Timestamp ) > (unsigned int) conn->GetResendThreshold()))\r\n\t\t\t{\r\n\t\t\t\treturn true;\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/* Dequeue Messages of type <msg_id>   \t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid App::DequeueMessagesByType( Net::Conn* conn, QUEUE_TYPE queue, unsigned char msg_id )\r\n{\r\n\t\r\n\r\n    switch( queue )\r\n\t{\r\n\t\tcase QUEUE_DEFAULT:\r\n\t\t{\r\n\t\t\tLst::Search< MsgLink > sh;\r\n\t\t\tMsgLink *msg_link, *next;\r\n\t\t\tQueuedMsg *msg;\r\n\r\n\t\t\tfor( msg_link = sh.FirstItem( conn->m_normal_msg_list ); msg_link;\r\n\t\t\t\t\tmsg_link = next )\r\n\t\t\t{\r\n\t\t\t\tnext = sh.NextItem();\r\n\t\t\t\tmsg = msg_link->m_QMsg;\r\n\t\t\t\tif( msg->m_MsgId == msg_id )\r\n\t\t\t\t{\r\n\t\t\t\t\tmsg->m_Ref.Release();\r\n\t\t\t\t\tif( msg->m_Ref.InUse() == false )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdelete msg;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdelete msg_link;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase QUEUE_IMPORTANT:\r\n\t\t{\r\n\t\t\tLst::Search< MsgImpLink > sh;\r\n\t\t\tMsgImpLink *msg_link, *next;\r\n\t\t\tQueuedMsg *msg;\r\n\r\n\t\t\tfor( msg_link = sh.FirstItem( conn->m_important_msg_list ); msg_link;\r\n\t\t\t\t\tmsg_link = next )\r\n\t\t\t{\r\n\t\t\t\tnext = sh.NextItem();\r\n\t\t\t\tmsg = msg_link->m_QMsg;\r\n\t\t\t\tif( msg->m_MsgId == msg_id )\r\n\t\t\t\t{\r\n\t\t\t\t\tmsg->m_Ref.Release();\r\n\t\t\t\t\tif( msg->m_Ref.InUse() == false )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdelete msg;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdelete msg_link;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase QUEUE_SEQUENCED:\r\n\t\t{\r\n\t\t\tLst::Search< MsgSeqLink > sh;\r\n\t\t\tMsgSeqLink *msg_link, *next;\r\n\t\t\tQueuedMsgSeq *msg;\r\n\r\n\t\t\tfor( msg_link = sh.FirstItem( conn->m_sequenced_msg_list ); msg_link;\r\n\t\t\t\t\tmsg_link = next )\r\n\t\t\t{\r\n\t\t\t\tnext = sh.NextItem();\r\n\t\t\t\tmsg = msg_link->m_QMsg;\r\n\t\t\t\tif( msg->m_MsgId == msg_id )\r\n\t\t\t\t{\r\n\t\t\t\t\tmsg->m_Ref.Release();\r\n\t\t\t\t\tif( msg->m_Ref.InUse() == false )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdelete msg;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdelete msg_link;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Enqueue a new message to be sent to a connection (by handle)   */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid App::EnqueueMessage( int handle, MsgDesc* desc )\r\n{\r\n\tConn *conn;\r\n\tLst::Search< Conn > sh;\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tWaitSema( m_send_semaphore_id );\r\n#endif\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\t// Make sure the message + headers isn't larger than a packet or else it will never be sent\r\n\tDbg_MsgAssert( desc->m_Length < ( Manager::vMAX_PAYLOAD - 64 ), (\"Network Message size (%d) is bigger than %d\",desc->m_Length, Manager::vMAX_PAYLOAD - 64) );\r\n\t\r\n\t// Add new message to the appropriate queue\t\r\n\tswitch( desc->m_Queue )\r\n\t{\r\n\t\tcase QUEUE_DEFAULT:\r\n\t\t{\r\n\t\t\tMsgLink *msg_link;\r\n\t\t\tQueuedMsg *queued_msg;\r\n\t\t\t\r\n\t\t\tqueued_msg = new QueuedMsg( desc->m_Id, desc->m_Length, desc->m_Data );\r\n\t\t\tif( handle == HANDLE_ID_BROADCAST )\r\n\t\t\t{\t\r\n\t\t\t\tfor( conn = sh.FirstItem( m_connections ); conn; conn = sh.NextItem())\r\n\t\t\t\t{   // Only enqueue the message if the connection is ready and valid\r\n\t\t\t\t\tif( conn->GetStatus() == Conn::mSTATUS_READY )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( desc->m_Singular )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tDequeueMessagesByType( conn, desc->m_Queue, desc->m_Id );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tqueued_msg->m_Ref.Acquire();\r\n\t\t\t\t\t\tmsg_link = new MsgLink( queued_msg );\r\n\t\t\t\t\t\tmsg_link->SetPri( desc->m_Priority );\r\n\t\t\t\t\t\tmsg_link->m_SendTime = m_Timestamp + desc->m_Delay;\r\n\t\t\t\t\t\tconn->m_normal_msg_list.AddNodeFromTail( msg_link );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if( handle & HANDLE_ID_EXCLUDE_BROADCAST )\r\n\t\t\t{\r\n\t\t\t\tint excluded_handle;\r\n\r\n\t\t\t\texcluded_handle = handle & ~HANDLE_ID_EXCLUDE_BROADCAST;\r\n\t\t\t\tfor( conn = sh.FirstItem( m_connections ); conn; conn = sh.NextItem())\r\n\t\t\t\t{\r\n\t\t\t\t\t// Broadcast to all but one handle\r\n\t\t\t\t\tif( conn->GetHandle() == excluded_handle )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// Only enqueue the message if the connection is ready and valid\r\n\t\t\t\t\tif( conn->GetStatus() == Conn::mSTATUS_READY )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( desc->m_Singular )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tDequeueMessagesByType( conn, desc->m_Queue, desc->m_Id );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tqueued_msg->m_Ref.Acquire();\r\n\t\t\t\t\t\tmsg_link = new MsgLink( queued_msg );\r\n\t\t\t\t\t\tmsg_link->SetPri( desc->m_Priority );\r\n\t\t\t\t\t\tmsg_link->m_SendTime = m_Timestamp + desc->m_Delay;\r\n\t\t\t\t\t\tconn->m_normal_msg_list.AddNodeFromTail( msg_link );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tconn = this->GetConnectionByHandle( handle );\r\n\t\t\t\tDbg_Assert( conn );\r\n\r\n\t\t\t\t// Only enqueue the message if the connection is ready and valid\r\n\t\t\t\tif(\t( conn->GetStatus() == Conn::mSTATUS_READY ) ||\r\n\t\t\t\t\t( desc->m_Id == MSG_ID_TIMESTAMP ))\r\n\t\t\t\t{\r\n\t\t\t\t\tif( desc->m_Singular )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDequeueMessagesByType( conn, desc->m_Queue, desc->m_Id );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tqueued_msg->m_Ref.Acquire();\r\n\t\t\t\t\tmsg_link = new MsgLink( queued_msg );\r\n\t\t\t\t\tmsg_link->SetPri( desc->m_Priority );\r\n\t\t\t\t\tmsg_link->m_SendTime = m_Timestamp + desc->m_Delay;\r\n\t\t\t\t\tconn->m_normal_msg_list.AddNodeFromTail( msg_link );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// If it didn't actually get enqueued, delete it\r\n\t\t\tif( queued_msg->m_Ref.InUse() == false )\r\n\t\t\t{\r\n\t\t\t\tdelete queued_msg;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase QUEUE_IMPORTANT:\r\n\t\t{\r\n\t\t\tMsgImpLink* msg_link;\r\n\t\t\tQueuedMsg* queued_msg;\r\n\t\t\t\r\n\t\t\tqueued_msg = new QueuedMsg( desc->m_Id, desc->m_Length, desc->m_Data );\r\n\t\t\tif( handle == HANDLE_ID_BROADCAST )\r\n\t\t\t{\t\r\n\t\t\t\tfor( conn = sh.FirstItem( m_connections ); conn; conn = sh.NextItem())\r\n\t\t\t\t{\r\n\t\t\t\t\tif( !( conn->TestStatus( Conn::mSTATUS_DISCONNECTING )))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( desc->m_Singular )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tDequeueMessagesByType( conn, desc->m_Queue, desc->m_Id );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tqueued_msg->m_Ref.Acquire();\r\n\t\t\t\t\t\tmsg_link = new MsgImpLink( queued_msg );\r\n\t\t\t\t\t\tmsg_link->SetPri( desc->m_Priority );\r\n\t\t\t\t\t\tmsg_link->m_SendTime = m_Timestamp + desc->m_Delay;\r\n\t\t\t\t\t\tmsg_link->m_Timestamp = 0;\r\n\t\t\t\t\t\tconn->m_important_msg_list.AddNodeFromTail( msg_link ); \r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if( handle & HANDLE_ID_EXCLUDE_BROADCAST )\r\n\t\t\t{\r\n\t\t\t\tint excluded_handle;\r\n\r\n\t\t\t\texcluded_handle = handle & ~HANDLE_ID_EXCLUDE_BROADCAST;\r\n\t\t\t\tfor( conn = sh.FirstItem( m_connections ); conn; conn = sh.NextItem())\r\n\t\t\t\t{\r\n\t\t\t\t\t// Broadcast to all but one handle\r\n\t\t\t\t\tif( conn->GetHandle() == excluded_handle )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif( !( conn->TestStatus( Conn::mSTATUS_DISCONNECTING )))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( desc->m_Singular )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tDequeueMessagesByType( conn, desc->m_Queue, desc->m_Id );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tqueued_msg->m_Ref.Acquire();\r\n\t\t\t\t\t\tmsg_link = new MsgImpLink( queued_msg );\r\n\t\t\t\t\t\tmsg_link->SetPri( desc->m_Priority );\r\n\t\t\t\t\t\tmsg_link->m_SendTime = m_Timestamp + desc->m_Delay;\r\n\t\t\t\t\t\tmsg_link->m_Timestamp = 0;\r\n\t\t\t\t\t\tconn->m_important_msg_list.AddNodeFromTail( msg_link ); \r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tconn = this->GetConnectionByHandle( handle );\r\n\t\t\t\tDbg_Assert( conn );\r\n\t\t\t\r\n\t\t\t\tif( !( conn->TestStatus( Conn::mSTATUS_DISCONNECTING )))\r\n\t\t\t\t{\r\n\t\t\t\t\tif( desc->m_Singular )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDequeueMessagesByType( conn, desc->m_Queue, desc->m_Id );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tqueued_msg->m_Ref.Acquire();\r\n\t\t\t\t\tmsg_link = new MsgImpLink( queued_msg );\r\n\t\t\t\t\tmsg_link->SetPri( desc->m_Priority );\r\n\t\t\t\t\tmsg_link->m_SendTime = m_Timestamp + desc->m_Delay;\r\n\t\t\t\t\tmsg_link->m_Timestamp = 0;\r\n\t\t\t\t\tconn->m_important_msg_list.AddNodeFromTail( msg_link ); \r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// If it didn't actually get enqueued, delete it\r\n\t\t\tif( queued_msg->m_Ref.InUse() == false )\r\n\t\t\t{\r\n\t\t\t\tdelete queued_msg;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase QUEUE_SEQUENCED:\r\n\t\t{\r\n\t\t\tMsgSeqLink *msg_link;\r\n\t\t\tQueuedMsgSeq* queued_msg;\r\n\t\t\t\r\n\t\t\tqueued_msg = AllocateNewSeqMessage( desc->m_Id, desc->m_Length, (char *) desc->m_Data, desc->m_GroupId );\r\n\t\t\t\t\t\t\r\n\t\t\tif( handle == HANDLE_ID_BROADCAST )\r\n\t\t\t{\t\r\n\t\t\t\tfor( conn = sh.FirstItem( m_connections ); conn; conn = sh.NextItem())\r\n\t\t\t\t{\r\n\t\t\t\t\tif( !( conn->TestStatus( Conn::mSTATUS_DISCONNECTING )))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_Assert( desc->m_Singular == false );\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tqueued_msg->m_Ref.Acquire();\r\n\t\t\t\t\t\tmsg_link = new MsgSeqLink( queued_msg );\r\n\t\t\t\t\t\tmsg_link->SetPri( desc->m_Queue );\r\n\t\t\t\t\t\tmsg_link->m_SendTime = m_Timestamp + desc->m_Delay;\r\n\t\t\t\t\t\tmsg_link->m_Timestamp = 0;\r\n\t\t\t\t\t\tmsg_link->m_GroupId = desc->m_GroupId;\r\n\t\t\t\t\t\tif( desc->m_ForcedSequenceId > 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmsg_link->m_SequenceId = desc->m_ForcedSequenceId;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmsg_link->m_SequenceId = conn->m_SequenceId[desc->m_GroupId]++;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tmsg_link->m_StreamMessage = desc->m_StreamMessage;\r\n\t\t\t\t\t\tconn->m_sequenced_msg_list.AddNodeFromTail( msg_link );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if( handle & HANDLE_ID_EXCLUDE_BROADCAST )\r\n\t\t\t{\r\n\t\t\t\tint excluded_handle;\r\n\r\n\t\t\t\texcluded_handle = handle & ~HANDLE_ID_EXCLUDE_BROADCAST;\r\n\t\t\t\tfor( conn = sh.FirstItem( m_connections ); conn; conn = sh.NextItem())\r\n\t\t\t\t{\r\n\t\t\t\t\t// Broadcast to all but one handle\r\n\t\t\t\t\tif( conn->GetHandle() == excluded_handle )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif( !( conn->TestStatus( Conn::mSTATUS_DISCONNECTING )))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_Assert( desc->m_Singular == false );\r\n\r\n\t\t\t\t\t\tqueued_msg->m_Ref.Acquire();\r\n\t\t\t\t\t\tmsg_link = new MsgSeqLink( queued_msg );\r\n\t\t\t\t\t\tmsg_link->SetPri( desc->m_Priority );\r\n\t\t\t\t\t\tmsg_link->m_SendTime = m_Timestamp + desc->m_Delay;\r\n\t\t\t\t\t\tmsg_link->m_Timestamp = 0;\r\n\t\t\t\t\t\tmsg_link->m_GroupId = desc->m_GroupId;\r\n\t\t\t\t\t\tif( desc->m_ForcedSequenceId > 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmsg_link->m_SequenceId = desc->m_ForcedSequenceId;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmsg_link->m_SequenceId = conn->m_SequenceId[desc->m_GroupId]++;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tmsg_link->m_StreamMessage = desc->m_StreamMessage;\r\n\t\t\t\t\t\tconn->m_sequenced_msg_list.AddNodeFromTail( msg_link );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tconn = GetConnectionByHandle( handle );\r\n\t\t\t\tDbg_Assert( conn );\r\n\r\n\t\t\t\tif( !( conn->TestStatus( Conn::mSTATUS_DISCONNECTING )))\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( desc->m_Singular == false );\r\n\r\n\t\t\t\t\tqueued_msg->m_Ref.Acquire();\r\n\t\t\t\t\tmsg_link = new MsgSeqLink( queued_msg );\r\n\t\t\t\t\tmsg_link->SetPri( desc->m_Priority );\r\n\t\t\t\t\tmsg_link->m_SendTime = m_Timestamp + desc->m_Delay;\r\n\t\t\t\t\tmsg_link->m_Timestamp = 0;\r\n\t\t\t\t\tmsg_link->m_GroupId = desc->m_GroupId;\r\n\t\t\t\t\tif( desc->m_ForcedSequenceId > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmsg_link->m_SequenceId = desc->m_ForcedSequenceId;\r\n\t\t\t\t\t\t//Dbg_Printf( \"Sending stream data sequence %d\\n\", msg_link->m_SequenceId );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmsg_link->m_SequenceId = conn->m_SequenceId[desc->m_GroupId]++;\r\n\t\t\t\t\t\t//Dbg_Printf( \"Sending stream start sequence %d\\n\", msg_link->m_SequenceId );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tmsg_link->m_StreamMessage = desc->m_StreamMessage;\r\n\t\t\t\t\tconn->m_sequenced_msg_list.AddNodeFromTail( msg_link );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// If it didn't actually get enqueued, delete it\r\n\t\t\tif( queued_msg->m_Ref.InUse() == false )\r\n\t\t\t{\r\n\t\t\t\tdelete queued_msg;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t\tDbg_Assert( 0 );\t\t// unsupported queue type\r\n\t\t\tbreak;\r\n\r\n\t}\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tSignalSema( m_send_semaphore_id );\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/* Stream a new message, given a connection instead of a handle\t  */\r\n/*                                              \t\t\t\t  */\r\n/******************************************************************/\r\n\r\nvoid\tApp::StreamMessageToConn( Net::Conn* conn, unsigned char msg_id, unsigned short msg_len, void* data, char* desc, unsigned char group_id,\r\n\t\t\t\t\t\t\t\t  bool all_at_once, bool send_in_place )\r\n{\r\n\tchar* data_ptr;\r\n\tint size, packet_len;\r\n\tMsgStreamStart start_msg;\r\n\tMsgStreamData data_msg;\r\n\tMsgDesc msg_desc;\r\n\tStreamDesc* stream_desc;\r\n\tStreamLink* stream_link;\r\n\r\n\tDbg_Assert( desc );\r\n\tDbg_Assert( conn );\r\n\r\n    // Also, for now, just split the data up into chunks no larger than MAX_STREAM_CHUNK_LENGTH\r\n\t// but eventually, maybe let the user decide what that chunk size should be.\r\n\r\n    start_msg.m_Size = msg_len;\r\n\tstart_msg.m_StreamId = conn->m_NextStreamId;\r\n\tstart_msg.m_MsgId = msg_id;\r\n\tstart_msg.m_Checksum = Crc::GenerateCRCCaseSensitive((char*) data, msg_len );\r\n\tstrcpy( start_msg.m_StreamDesc, desc );\r\n\tsize = 0;\r\n\r\n\tmemcpy( start_msg.m_Data, data, ( msg_len <= MAX_STREAM_CHUNK_LENGTH ) ? msg_len : MAX_STREAM_CHUNK_LENGTH );\r\n\tsize += ( msg_len <= MAX_STREAM_CHUNK_LENGTH ) ? msg_len : MAX_STREAM_CHUNK_LENGTH;\r\n\tpacket_len = ( sizeof( start_msg ) - MAX_STREAM_CHUNK_LENGTH ) + size;\r\n\r\n\tmsg_desc.m_Id = MSG_ID_STREAM_START;\r\n\tmsg_desc.m_Length = packet_len;\r\n\tmsg_desc.m_Data = &start_msg;\r\n\tmsg_desc.m_Queue = QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = group_id;\r\n\tmsg_desc.m_StreamMessage = 1;\r\n\r\n\t//Dbg_Printf( \"******** [%d] Streaming %d bytes\\n\", conn->m_NextStreamId, packet_len );\r\n    EnqueueMessage( conn->GetHandle(), &msg_desc );\r\n\r\n\tif( msg_len > MAX_STREAM_CHUNK_LENGTH )\r\n\t{\r\n\t\tif( all_at_once )\r\n\t\t{\r\n\t\t\tdata_ptr = (char*) data + size;\r\n\t\t\twhile( size < msg_len )\r\n\t\t\t{\r\n\t\t\t\tpacket_len = msg_len - size;\r\n\t\t\t\tif( packet_len > MAX_STREAM_CHUNK_LENGTH )\r\n\t\t\t\t{\r\n\t\t\t\t\tpacket_len = MAX_STREAM_CHUNK_LENGTH;\r\n\t\t\t\t}\r\n\t\t\r\n\t\t\t\tdata_msg.m_StreamId = conn->m_NextStreamId;\r\n\t\t\t\tmemcpy( data_msg.m_Data, data_ptr, packet_len );\r\n\t\t\t\t\r\n\t\t\t\tmsg_desc.m_Id = MSG_ID_STREAM_DATA;\r\n\t\t\t\tmsg_desc.m_Data = &data_msg;\r\n\t\t\t\tmsg_desc.m_Length = packet_len + sizeof( int );\r\n\t\t\t\tmsg_desc.m_Queue = QUEUE_SEQUENCED;\r\n\t\t\t\tmsg_desc.m_GroupId = group_id;\r\n\t\t\t\tmsg_desc.m_StreamMessage = 1;\r\n\t\t\r\n\t\t\t\t//Dbg_Printf( \"%d ******** [%d] Streaming %d bytes.\\n\", m_FrameCounter, conn->m_NextStreamId, packet_len );\r\n\t\t\t\tEnqueueMessage( conn->GetHandle(), &msg_desc );\r\n\t\t\r\n\t\t\t\tdata_ptr += packet_len;\r\n\t\t\t\tsize += packet_len;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// If this message is larger than one chunk, add it to our list of out-bound streams so that we can\r\n\t\t\t// send it to the connection with a sliding window\r\n\t\t\tint num_extra_msgs;\r\n\t\t\tchar* send_data;\r\n\t\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\t\r\n\t\t\tnum_extra_msgs = ( msg_len - 1 ) / MAX_STREAM_CHUNK_LENGTH;\r\n\t\t\t\r\n\t\t\tif( send_in_place )\r\n\t\t\t{\r\n\t\t\t\tsend_data = (char*) data;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsend_data = new char[msg_len];\r\n\t\t\t\tmemcpy( send_data, data, msg_len );\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tdata_ptr = (char*) send_data + size;\r\n\t\r\n\t\t\tstream_desc = new StreamDesc;\r\n\t\t\tstream_link = new StreamLink( stream_desc );\r\n\t\t\r\n\t\t\tstream_desc->m_StreamId = conn->m_NextStreamId;\r\n\t\t\tstream_desc->m_Size = msg_len;\r\n\t\t\tstream_desc->m_MsgId = msg_id;\r\n\t\t\tstrcpy( stream_desc->m_StreamDesc, desc );\r\n\t\t\tstream_desc->m_Data = (char*) send_data;\r\n\t\t\tstream_desc->m_DataPtr = data_ptr;\r\n\t\t\tstream_desc->m_GroupId = group_id;\r\n\t\t\tstream_desc->m_SequenceId = conn->m_SequenceId[group_id];\r\n\t\t\tstream_desc->m_SendInPlace = send_in_place;\r\n\t\r\n\t\t\tconn->m_StreamOutList.AddToTail( stream_link );\r\n\t\r\n\t\t\t//Dbg_Printf( \"******** [%d] Stream rest (%d bytes, %d chunks) later....\\n\", conn->m_NextStreamId, msg_len - size, num_extra_msgs );\r\n\t\r\n\t\t\tconn->m_SequenceId[group_id] += num_extra_msgs;\r\n\t\t\t\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t}\r\n\t}\r\n\r\n\tconn->m_NextStreamId++;\r\n}\r\n\r\n/******************************************************************/\r\n/* Stream a new message to send to the connection.\t\t\t\t  */\r\n/*                                              \t\t\t\t  */\r\n/******************************************************************/\r\n\r\nvoid\tApp::StreamMessage( int handle, unsigned char msg_id, unsigned short msg_len, void* data, char* desc, unsigned char group_id,\r\n\t\t\t\t\t\t\tbool all_at_once, bool send_in_place )\r\n{\r\n\tLst::Search< Conn > sh;\r\n\tConn* conn;\r\n\r\n\tDbg_Assert( desc );\r\n\t\r\n\tif( handle == HANDLE_ID_BROADCAST )\r\n\t{\t\r\n\t\tfor( conn = sh.FirstItem( m_connections ); conn; conn = sh.NextItem())\r\n\t\t{\r\n\t\t\tif( conn->IsValid())\r\n\t\t\t{\r\n\t\t\t\tStreamMessageToConn( conn, msg_id, msg_len, data, desc, group_id, all_at_once, send_in_place );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tconn = GetConnectionByHandle( handle );\r\n\t\tDbg_Assert( conn );\r\n\r\n\t\tif( conn->IsValid())\r\n\t\t{\r\n\t\t\tStreamMessageToConn( conn, msg_id, msg_len, data, desc, group_id, all_at_once, send_in_place );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Stream a new message to send to the server. Just a shortcut\t  */\r\n/* to EnqueueMessage                                              */\r\n/******************************************************************/\r\n\r\nvoid\tApp::StreamMessageToServer( unsigned char msg_id, unsigned short msg_len, void* data, char* desc, unsigned char group_id,\r\n\t\t\t\t\t\t\t\t\tbool all_at_once, bool send_in_place )\r\n{\r\n\tConn *conn;\r\n\tLst::Search< Conn > sh;\r\n\r\n\tif(( conn = FirstConnection( &sh )))\r\n\t{\r\n\t\tStreamMessageToConn( conn, msg_id, msg_len, data, desc, group_id, all_at_once, send_in_place );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Enqueue a new message to send to the server. Just a shortcut   */\r\n/* to EnqueueMessage                                              */\r\n/******************************************************************/\r\n\r\nvoid\tApp::EnqueueMessageToServer( MsgDesc* desc )\r\n{\r\n\tConn *conn;\r\n\tLst::Search< Conn > sh;\r\n\r\n\t\r\n\r\n\tif(( conn = FirstConnection( &sh )))\r\n\t{\r\n\t\tEnqueueMessage( conn->GetHandle(), desc );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Free the message queue for a given connection                  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::FreeConnMessageQueue( Conn *conn, QUEUE_TYPE queue )\r\n{\r\n\t\t\r\n\t\r\n\r\n\tDbg_Assert( conn );\r\n\r\n\tswitch( queue )\r\n\t{\r\n\t\tcase QUEUE_DEFAULT:\r\n\t\t{\r\n\t\t\tLst::Search< MsgLink > sh;\r\n\t\t\tMsgLink *msg_link, *next;\r\n\t\t\tQueuedMsg *msg;\r\n\r\n\t\t\tfor( msg_link = sh.FirstItem( conn->m_normal_msg_list ); msg_link;\r\n\t\t\t\t\tmsg_link = next )\r\n\t\t\t{\r\n\t\t\t\tnext = sh.NextItem();\r\n\t\t\t\tmsg = msg_link->m_QMsg;\r\n\t\t\t\tmsg->m_Ref.Release();\r\n\t\t\t\tif( msg->m_Ref.InUse() == false )\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete msg;\r\n\t\t\t\t}\r\n\t\t\t\tdelete msg_link;\r\n\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase QUEUE_IMPORTANT:\r\n\t\t{\r\n\t\t\tLst::Search< MsgImpLink > sh;\r\n\t\t\tMsgImpLink *msg_link, *next;\r\n\t\t\tQueuedMsg *msg;\r\n\r\n\t\t\tfor( msg_link = sh.FirstItem( conn->m_important_msg_list ); msg_link;\r\n\t\t\t\t\tmsg_link = next )\r\n\t\t\t{\r\n\t\t\t\tnext = sh.NextItem();\r\n\t\t\t\tmsg = msg_link->m_QMsg;\r\n\t\t\t\tmsg->m_Ref.Release();\r\n\t\t\t\tif( msg->m_Ref.InUse() == false )\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete msg;\r\n\t\t\t\t}\r\n\t\t\t\tdelete msg_link;\r\n\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase QUEUE_SEQUENCED:\r\n\t\t{\r\n\t\t\tLst::Search< MsgSeqLink > sh;\r\n\t\t\tMsgSeqLink *msg_link, *next;\r\n\t\t\tQueuedMsgSeq *msg;\r\n\r\n\t\t\tfor( msg_link = sh.FirstItem( conn->m_sequenced_msg_list ); msg_link;\r\n\t\t\t\t\tmsg_link = next )\r\n\t\t\t{\r\n\t\t\t\tnext = sh.NextItem();\r\n\t\t\t\tmsg = msg_link->m_QMsg;\r\n\t\t\t\tmsg->m_Ref.Release();\r\n\t\t\t\tif( msg->m_Ref.InUse() == false )\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete msg;\r\n\t\t\t\t}\r\n\t\t\t\tdelete msg_link;\r\n\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Free message queues of a certain type from all connections     */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::FreeMessageQueue( QUEUE_TYPE queue )\r\n{\r\n\tConn *conn;\r\n\tLst::Search< Conn > sh;\r\n\r\n\tfor( conn = FirstConnection( &sh ); conn; conn = NextConnection( &sh ))\r\n\t{\r\n\t\tFreeConnMessageQueue( conn, queue );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Medium-level send function.  Works as the message level\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tApp::SendMessageTo( unsigned char msg_id, unsigned short msg_len, void* data,\r\n\t\t\t\t\t\t\tint ip, unsigned short port, int flags )\r\n{\r\n\tchar\tmsg_data[Manager::vMAX_PACKET_SIZE];\r\n\tbool result;\r\n\r\n\tmsg_data[0] = msg_id;\r\n\tmemcpy( &msg_data[1], &msg_len, sizeof( unsigned short ));\r\n\tif( msg_len > 0 )\r\n\t{\r\n\t\tmemcpy( &msg_data[3], data, msg_len ); \r\n\t}\r\n    \r\n#ifdef __PLAT_NGPS__\t\r\n\tWaitSema( m_send_semaphore_id );\r\n#endif // __PLAT_NGPS__\r\n\t\r\n\tresult = SendTo( ip, port, msg_data, msg_len + Manager::vMSG_HEADER_LENGTH_WITH_SIZE, flags );\r\n\r\n#ifdef __PLAT_NGPS__    \r\n\tSignalSema( m_send_semaphore_id );\r\n#endif // __PLAT_NGPS__\r\n\t\r\n\treturn result;\r\n}\r\n\r\n/******************************************************************/\r\n/* Lower level, pre-connection network send function              */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tApp::SendTo( int ip, unsigned short port, char *data, int len, int flags )\r\n{\r\n\tstruct sockaddr_in\tto_address;\r\n#ifdef __PLAT_NGC__\r\n    to_address.len = sizeof( sockaddr );\r\n#else\r\n\tint addr_len = sizeof(to_address);\r\n#endif\r\n\tint\tresult = 0;\r\n\tint send_len;\r\n\t\r\n\t\r\n\r\n\tDbg_Assert( data );\r\n\tDbg_Assert( len <= Manager::vMAX_PAYLOAD );\r\n\r\n\t// Send data immediately to a destination socket\r\n\tmemset( &to_address, 0, sizeof(to_address));\r\n\tto_address.sin_family = AF_INET;\r\n\tto_address.sin_port = htons( port );\r\n\t\t\r\n\t// use ip = INADDR_BROADCAST to broadcast\r\n\tto_address.sin_addr.s_addr = ip;\r\n\tif( m_flags & mSECURE )\r\n\t{\r\n\t\tcrc_and_copy_stream( data, m_out_packet_buffer, len, &send_len );\r\n\t\tresult = sendto( m_socket, m_out_packet_buffer, send_len, flags, \r\n\t\t\t\t(struct sockaddr *) &(to_address), addr_len );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tresult = sendto( m_socket, data, len, flags, (struct sockaddr *) &(to_address), addr_len );\r\n\t}\r\n\t\r\n#ifndef __PLAT_NGC__\r\n\tif(\tresult == SOCKET_ERROR )\r\n\t{\r\n\t\tint err;\r\n#if defined( __PLAT_WN32__ ) || defined( __PLAT_XBOX__ )\r\n\t\terr = WSAGetLastError();\r\n\t\tif(\t( err != WSAEWOULDBLOCK ) &&\r\n\t\t\t( err != WSAEINPROGRESS ))\r\n#else\r\n#ifdef __PLAT_NGPS__\r\n\t\terr = sn_errno( m_socket );\r\n\t\tif( ( err != EWOULDBLOCK ) &&\r\n\t\t\t( err != EINPROGRESS ))\r\n#endif\r\n#endif\r\n\t\t{\r\n#ifdef DEBUG_MESSAGES\r\n\t\tDbg_Printf( \"Sendto Error: packet length %d\\n\", len );\r\n\t\t\tReportError();\r\n#endif\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/* Lower level, pre-(app-level) connection network send function  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tApp::Send( char *data, int len, int flags )\r\n{\r\n\tint\tresult = 0;\r\n\tint send_len;\r\n\t\t\r\n\t\r\n\r\n\tDbg_Assert( data );\r\n\t\r\n\tif( m_connected == false )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tDbg_Assert( len <= Manager::vMAX_PAYLOAD );\r\n\r\n\t// Send data immediately to a destination socket\r\n\tif( m_flags & mSECURE )\r\n\t{\r\n\t\tcrc_and_copy_stream( data, m_out_packet_buffer, len, &send_len );\r\n\t\tresult = send( m_socket, m_out_packet_buffer, send_len, flags );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tresult = send( m_socket, data, len, flags );\r\n\t}\r\n\r\n\tif( result == SOCKET_ERROR )\r\n\t{\r\n#ifdef DEBUG_MESSAGES\r\n\t\tDbg_Printf( \"Send Error: packet length %d\\n\", len );\r\n\t\tReportError();\r\n#endif\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nConn\t*App::FirstConnection( Lst::Search< Conn > *sh )\r\n{\r\n\t\r\n\r\n\tDbg_Assert( sh );\r\n\r\n\treturn( sh->FirstItem( m_connections ));\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nConn\t*App::NextConnection( Lst::Search< Conn > *sh )\r\n{\r\n\t\r\n\r\n\tDbg_Assert( sh );\r\n\r\n\treturn( sh->NextItem());\r\n}\r\n\r\n/******************************************************************/\r\n/* Immediately terminate connection.  Don't use this in msg\t\t  */\r\n/* handlers. Instead, invalidate the connection only              */\r\n/******************************************************************/\r\n\r\nvoid\tApp::TerminateConnection( Conn* conn )\r\n{\r\n\t\r\n\t\r\n\tDbg_Assert( conn );\r\n\r\n\tstruct in_addr address;\r\n\r\n\taddress.s_addr = conn->GetIP();\r\n\tconn->m_node.Remove();\r\n\tdelete conn;\r\n}\r\n\r\n/******************************************************************/\r\n/* Report the last error on the socket                            */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tApp::ReportError( void )\r\n{\r\n\t\r\n\r\n#ifdef WIN32\r\n\tchar msg[1024];\r\n\r\n\t//Dbg_Printf( \"%s: Error %d\\n\", m_name, WSAGetLastError());\r\n\tsprintf( msg, \"%s: Error %d\\n\", m_name, WSAGetLastError());\r\n\tOutputDebugString( msg );\r\n#else\r\n#ifdef __PLAT_NGPS__\r\n#ifdef DEBUG_MESSAGES\r\n\tDbg_Printf( \"(%d) %s: Error %d\\n\", m_FrameCounter, m_name, sn_errno( m_socket ));\r\n#endif\r\n#endif\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager*\tApp::GetManager( void )\r\n{\r\n\treturn m_net_man;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tApp::SendEnqueuedMessages( void )\r\n{\r\n\tConn *conn;\r\n\tLst::Search< Conn > sh;\r\n\t\t\r\n\t\r\n    \r\n#ifdef __PLAT_NGPS__\r\n    WaitSema( m_send_semaphore_id );\r\n#endif\t// __PLAT_NGPS__    \r\n\tfor( conn = FirstConnection( &sh );\r\n\t\t\tconn; conn = NextConnection( &sh ))\r\n\t{\r\n\t\tSendEnqueuedMessages( conn );\r\n\t}\r\n\t\r\n#ifdef __PLAT_NGPS__\r\n\tSignalSema( m_send_semaphore_id );\r\n#endif\t// __PLAT_NGPS__\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#ifdef __PLAT_NGPS__\r\n\r\nvoid\t\tApp::TransferData( void )\r\n{\r\n\twhile( 1 )\r\n\t{\r\n\t\t// Receive data\r\n\t\tSleepThread();\r\n\t\tif( m_shutting_down )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tWaitSema( m_transfer_semaphore_id );\r\n\t\tReceiveData();\r\n\t\tSignalSema( m_transfer_semaphore_id );\r\n\t\t\r\n\t\t// Now wait until that data has been processed and it is time to send new data\r\n\t\t// outbound\r\n\t\tSleepThread();\r\n\r\n\t\t// Send Data\r\n\t\tif( m_shutting_down )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tWaitSema( m_transfer_semaphore_id );\r\n\t\tSendEnqueuedMessages();\r\n\t\tSignalSema( m_transfer_semaphore_id );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tApp::WaitForAsyncCallsToFinish( void )\r\n{\r\n\t\r\n    \r\n\tWaitForTransferSemaphore();\r\n    SignalTransferSemaphore(); \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tApp::WaitForTransferSemaphore( void )\r\n{   \r\n\tWaitSema( m_transfer_semaphore_id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tApp::SignalTransferSemaphore( void )\r\n{   \r\n\tSignalSema( m_transfer_semaphore_id );\r\n}\r\n\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tApp::SendData( bool scheduled_send )\r\n{\r\n\t\r\n\tLst::Search< Conn > sh;\r\n\tConn* conn;\r\n\r\n\t// If someone is requesting a send of all curretly enqueued data before its time\r\n\t// we need to tell each connection to ignore the logic to send every N frames and rather\r\n\t// send immediately\r\n\tif( scheduled_send == false )\r\n\t{   \r\n\t\tm_Timestamp++;\t// This will ensure that the timestamp is unique. Otherwise\r\n\t\t\t\t\t\t// the recipient will think it's a dupe packet\r\n\t\tfor( conn = FirstConnection( &sh ); conn; conn = NextConnection( &sh ))\r\n\t\t{\r\n\t\t\tconn->SetForceSendThisFrame( true );\r\n\t\t}\r\n\t}\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tif( !IsLocal() && m_socket_thread_active )\r\n\t{   \r\n\t\tWaitSema( m_transfer_semaphore_id );\r\n\t}\r\n#endif\r\n\r\n\tSendEnqueuedMessages();\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tif( !IsLocal() && m_socket_thread_active )\r\n\t{   \r\n\t\tSignalSema( m_transfer_semaphore_id );\r\n\t}\r\n#endif\t// __PLAT_NGPS_\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tApp::ShouldSendThisFrame( Conn* conn )\r\n{\r\n\tif( (( m_Timestamp - conn->m_last_send_time ) >= (unsigned int) conn->GetSendInterval()) ||\r\n\t\t( conn->GetForceSendThisFrame() ))\r\n\t\t\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::ShutDown( void )\r\n{\r\n\t\r\n#ifdef DEBUG_MESSAGES\r\n\tDbg_Printf( \"Shutting NetApp %s Down\\n\", GetName());\r\n#endif\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tm_shutting_down = true;\r\n\r\n\t//if( m_socket_thread_active )\r\n\t{   \r\n\t\tWakeupThread( m_socket_thread_id );\r\n\t}\r\n#ifdef DEBUG_MESSAGES\t\r\n\tDbg_Printf( \"Waiting for active semaphore\\n\" );\r\n#endif\r\n\tWaitSema( m_active_semaphore_id );\r\n\r\n#ifdef DEBUG_MESSAGES\r\n    Dbg_Printf( \"Deleting semaphores\\n\" );\r\n#endif\r\n\tDeleteSema( m_send_semaphore_id );\r\n\tDeleteSema( m_receive_semaphore_id );\r\n\tDeleteSema( m_transfer_semaphore_id );\r\n\tDeleteSema( m_active_semaphore_id );\r\n\t\r\n#ifdef DEBUG_MESSAGES\r\n\tDbg_Printf( \"Deleting socket thread\\n\" );\r\n#endif\r\n\tDeleteThread( m_socket_thread_id );\r\n    \r\n#endif\r\n    \r\n    deinit();\r\n#ifdef DEBUG_MESSAGES\r\n\tDbg_Printf( \"NetApp %s successfully shut down\\n\", GetName());\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::AliasConnections( Conn* server_conn, Conn* client_conn )\r\n{\r\n\t\r\n\r\n\tDbg_Assert( server_conn->IsLocal() && client_conn->IsLocal());\r\n\tserver_conn->m_alias_connection = client_conn;\r\n\tclient_conn->m_alias_connection = server_conn;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tApp::IsLocal( void )\r\n{\r\n\treturn m_flags.TestMask( mLOCAL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::AcceptForeignConnections( bool accept )\r\n{\r\n\tif( accept )\r\n\t{\r\n\t\tm_flags.SetMask( mACCEPT_FOREIGN_CONN );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_flags.ClearMask( mACCEPT_FOREIGN_CONN );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tApp::AcceptsForeignConnections( void )\r\n{\r\n\treturn m_flags.TestMask( mACCEPT_FOREIGN_CONN );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSOCKET\tApp::GetSocket( void )\r\n{\r\n\treturn m_socket;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::SetForeignPacketHandler( ForeignPacketHandlerCode* code )\r\n{\r\n\tm_foreign_handler = code;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tApp::BanConnection( Conn* conn )\r\n{\r\n\tBannedConn* banned_conn;\r\n\r\n\tbanned_conn = new BannedConn;\r\n\r\n\tbanned_conn->m_Ip = conn->GetIP();\r\n\tm_banned_connections.AddToTail( banned_conn );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tApp::IsConnectionBanned( Conn* conn )\r\n{\r\n\tBannedConn* banned_conn;\r\n\tLst::Search< BannedConn > sh;\r\n\t\r\n\tfor( banned_conn = sh.FirstItem( m_banned_connections ); banned_conn;\r\n\t\t\tbanned_conn = sh.NextItem())\r\n\t{\r\n\t\tif( banned_conn->m_Ip == conn->GetIP())\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tApp::BandwidthUsed( void )\r\n{\r\n\tint total_bandwidth;\r\n\tConn* conn;\r\n\tLst::Search< Conn > sh;\r\n\r\n\ttotal_bandwidth = 0;\r\n\tfor( conn = FirstConnection( &sh ); conn; conn = NextConnection( &sh ))\r\n\t{\r\n\t\tif( conn->IsRemote())\r\n\t\t{\r\n\t\t\tMetrics* metrics;\r\n\t\r\n\t\t\tmetrics = conn->GetOutboundMetrics();\r\n\t\t\ttotal_bandwidth += metrics->GetBytesPerSec();\r\n\t\t}\r\n\t}\r\n\r\n\treturn total_bandwidth;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tApp::BandwidthExceeded( Conn* conn )\r\n{\r\n\tMetrics* metrics;\r\n\tint total_bandwidth, per_user_bandwidth, num_remote_connections;\r\n\tConn* tmp_conn;\r\n\tLst::Search< Conn > sh;\r\n\r\n    metrics = conn->GetOutboundMetrics();\r\n\ttotal_bandwidth = BandwidthUsed();\r\n\t// First, make sure we haven't exceeded the total bandwidth of our connection\r\n\tif( total_bandwidth >= m_net_man->GetBandwidth())\r\n\t{\r\n\t\tDbg_Printf( \"Total bandwidth exceeded : %d  %d\\n\", total_bandwidth, m_net_man->GetBandwidth() );\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Then, make sure we haven't flooded the client\r\n\tif( metrics->GetBytesPerSec() >= conn->GetBandwidth())\r\n\t{\r\n\t\tDbg_Printf( \"(%d) Client flooded: %d %d\\n\", m_FrameCounter, metrics->GetBytesPerSec(), conn->GetBandwidth() );\r\n\t\treturn true;\r\n\t}\r\n\r\n\tnum_remote_connections = 0;\r\n\tfor( tmp_conn = FirstConnection( &sh ); tmp_conn; tmp_conn = NextConnection( &sh ))\r\n\t{\r\n\t\tif( tmp_conn->IsRemote() && !tmp_conn->IsForeign())\r\n\t\t{\r\n\t\t\tnum_remote_connections++;\r\n\t\t}\r\n\t}\r\n\r\n\tif( num_remote_connections == 0 )\r\n\t{\r\n\t\tnum_remote_connections = 1;\t// Avoid DBZ\r\n\t}\r\n\t// Also, check if we've used up this client's share of our bandwidth\r\n\tper_user_bandwidth = ( m_net_man->GetBandwidth() / num_remote_connections );\r\n\tif( metrics->GetBytesPerSec() > per_user_bandwidth )\r\n\t{\r\n\t\tDbg_Printf( \"Share flooded: %d %d\\n\",  metrics->GetBytesPerSec(), per_user_bandwidth );\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\t// namespace Net\r\n"
  },
  {
    "path": "Code/Gel/Net/Client/netclnt.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNet (OBJ) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tnetclnt.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/29/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNetwork client code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdlib.h>\r\n#include <string.h>\r\n\r\n#include <core/defines.h>\r\n\r\n#include <sys/timer.h>\r\n\r\n#include <gel/net/net.h>\r\n#include <gel/net/client/netclnt.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Net\r\n{\r\n\t\t\t\t\t\t\t\t  \r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool\tClient::init( void )\r\n{\r\n\t\r\n\r\n#ifdef\t__PLAT_NGPS__\t\t\t\t\t\t\t\t\t\t\t  \r\n\tDbg_MsgAssert(Mem::SameContext(this,Mem::Manager::sHandle().NetworkHeap()),(\"Client not on network heap\"));\t\r\n#endif\t\t//\t__PLAT_NGPS__\t\t\t\t\t\t\t\t\t\t\t  \r\n\r\n\r\n\tm_connected = false;\r\n\tm_Timestamp = 0;\r\n\tif( App::init() == false )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tm_Dispatcher.AddHandler( MSG_ID_CONNECTION_ACCEPTED, handle_connection_accepted, \r\n\t\t\t\t\t\t\t mHANDLE_FOREIGN | mHANDLE_LATE );\r\n\tm_Dispatcher.AddHandler( MSG_ID_CONNECTION_REFUSED, handle_connection_refusal, mHANDLE_LATE );\r\n\tm_Dispatcher.AddHandler( MSG_ID_CONNECTION_TERMINATED, handle_connection_refusal, mHANDLE_LATE );\r\n\tm_Dispatcher.AddHandler( MSG_ID_TIMESTAMP, handle_timestamp, mHANDLE_LATE | mHANDLE_FOREIGN );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tClient::deinit( void )\r\n{\r\n\t\r\n\r\n\tApp::deinit();\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/* Connect (socket-level) to a server at a given IP/Port          */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Client::ConnectToServer( int ip, unsigned short port )\r\n{\r\n\tint result;\r\n\tbool connected;\r\n\t\r\n\tmemset( &m_server_address, 0, sizeof(m_server_address));\r\n\tm_server_address.sin_family = AF_INET;\r\n\tm_server_address.sin_port = htons( port );\t\r\n\tm_server_address.sin_addr.s_addr = ip;\r\n#ifdef __PLAT_NGC__\r\n\tm_server_address.len = sizeof( sockaddr_in );\r\n#else\r\n\tmemset ( &m_server_address.sin_zero, 0, 8 );  \r\n#endif\r\n\r\n\tDbg_Printf( \"%s Connecting to server\\n\", GetName());\r\n\tconnected = false;\r\n\tdo\r\n\t{\r\n\t\tif(( result = connect( m_socket, (struct sockaddr *)&m_server_address, \r\n\t\t\t\t\tsizeof( m_server_address ))) == SOCKET_ERROR )\r\n\t\t{\r\n#if defined( __PLAT_WN32__ ) || defined( __PLAT_XBOX__ )\r\n\t\t\tif( WSAGetLastError() != WSAEWOULDBLOCK )\r\n#else\r\n#ifdef __PLAT_NGPS__\r\n\t\t\tif( sn_errno( m_socket ) != EWOULDBLOCK )\r\n#endif\r\n#endif\r\n\t\t\t{\r\n\t\t\t\tReportError();\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tconnected = true;\r\n\t\t}\r\n\t} while( !connected );\r\n\r\n\t// \"Connecting\" to INADDR_ANY disassociates our socket from all addresses\r\n\tif( ip == INADDR_ANY )\r\n\t{   \r\n\t\tm_connected = false;\r\n\t}\r\n\telse\r\n\t{   \r\n\t\tm_connected = true;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/* Client's send function.                                        */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tClient::SendEnqueuedMessages( Conn* conn )\r\n{\r\n\tint buf_len;\r\n\tMsgPacketStamp msg;\r\n\tbool buffer_full;\r\n    \r\n\t// Should we send this frame?\r\n\tif( ShouldSendThisFrame( conn ) == false )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tbuffer_full = false;\r\n    while( !buffer_full && MessagesToSend( conn ) && !BandwidthExceeded( conn ))\r\n\t{\r\n\t\t// Tack on a timestamp (for acking) if we are sending important\r\n\t\t// messages in this packet\r\n\t\tif( ImportantMessagesToSend( conn ))\r\n\t\t{\r\n\t\t\tMsgDesc msg_desc;\r\n#ifdef __PLAT_NGPS__\r\n\t\t\tSignalSema( m_send_semaphore_id );\r\n#endif  \r\n\t\t\tmsg.m_Packetstamp = (unsigned short) conn->m_latest_sent_packet_stamp;\r\n            //msg.m_Handle = conn->GetHandle();\r\n\t\t\t\r\n\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\tmsg_desc.m_Length = sizeof( MsgPacketStamp );\r\n\t\t\tmsg_desc.m_Id = MSG_ID_TIMESTAMP;\r\n\t\t\tmsg_desc.m_Priority = HIGHEST_PRIORITY;\r\n\t\t\tEnqueueMessage( conn->GetHandle(), &msg_desc );\r\n#ifdef __PLAT_NGPS__\r\n\t\t\tWaitSema( m_send_semaphore_id );\r\n#endif\r\n\t\t}\r\n\t\r\n\t\t// Send Latency Tests/Responses if applicable\r\n\t\tif( ( conn->IsRemote()) &&\r\n\t\t\t( conn->IsForeign() == false ) &&\r\n\t\t\t( m_flags.TestMask( App::mDYNAMIC_RESEND )))\r\n\t\t{\r\n\t\t\tMsgDesc msg_desc;\r\n\t\t\tMsgTimestamp latency_msg;\r\n\t\t\tunsigned int cur_time;\r\n\t\r\n\t\t\tcur_time = m_Timestamp;\r\n\t\t\tlatency_msg.m_Timestamp = cur_time;\r\n\t\t\t// send out a new latency test, keeping track of the time at which\r\n\t\t\t// we sent it\r\n\t\t\tif(\t( conn->m_latency_test.m_SendTime == 0 ) ||\r\n\t\t\t\t( ( cur_time - conn->m_latency_test.m_SendTime ) > App::MAX_LATENCY ))\r\n\t\t\t{\r\n\t\t\t\t// If we never got a response, simulate an increased latency\r\n\t\t\t\tif( conn->m_latency_test.m_SendTime > conn->m_latency_test.m_ReceiveTime )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned int latency_value;\r\n\t\r\n\t\t\t\t\tlatency_value = conn->GetAveLatency();\r\n\t\t\t\t\tlatency_value += 100;\r\n\t\r\n\t\t\t\t\tif( latency_value > App::MAX_LATENCY )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tlatency_value = App::MAX_LATENCY;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconn->m_latency_test.InputLatencyValue( latency_value );\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tconn->m_latency_test.m_SendTime = cur_time;\r\n\t\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t\tSignalSema( m_send_semaphore_id );\r\n#endif  \r\n\t\t\t\tmsg_desc.m_Data = &latency_msg;\r\n\t\t\t\tmsg_desc.m_Id = MSG_ID_PING_TEST;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( MsgTimestamp );\r\n\t\t\t\tEnqueueMessage( conn->GetHandle(), &msg_desc ); \r\n\t\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t\tWaitSema( m_send_semaphore_id );\r\n#endif\r\n\t\t\t}\t\t\t\r\n\t\t}\r\n\t\t\r\n\t\tif( !BuildMsgStream( conn, QUEUE_DEFAULT ))\r\n\t\t{\r\n\t\t\tbuffer_full = true;\r\n\t\t}\r\n\t\t// First, use up our bandwidth with re-sends or else they might remain un-sent\r\n\t\t// indefinitely, causing a bad backup on the client if he's waiting on \r\n\t\t// one particular sequence\r\n\t\tif( !BuildMsgStream( conn, QUEUE_SEQUENCED, true ))\r\n\t\t{\r\n\t\t\tbuffer_full = true;\r\n\t\t}\r\n\t\tif( !BuildMsgStream( conn, QUEUE_IMPORTANT, true ))\r\n\t\t{\r\n\t\t\tbuffer_full = true;\r\n\t\t}\r\n\t\tif( !BuildMsgStream( conn, QUEUE_SEQUENCED ))\r\n\t\t{\r\n\t\t\tbuffer_full = true;\r\n\t\t}\r\n\t\tif( !BuildMsgStream( conn, QUEUE_IMPORTANT ))\r\n\t\t{\r\n\t\t\tbuffer_full = true;\r\n\t\t}\r\n\t\t\r\n\t\tbuf_len = conn->m_write_ptr - conn->m_write_buffer;\r\n\t\t// If there is data to send\r\n\t\tif(\t( buf_len > 0 ) &&\r\n\t\t\t( conn->IsRemote()))\r\n\t\t{\r\n\t\t\tif( m_connected )\r\n\t\t\t{           \r\n\t\t\t\tif( Send( conn->m_write_buffer, buf_len, 0 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tm_TotalBytesOut += buf_len;\r\n\t\t\t\t\tconn->GetOutboundMetrics()->AddPacket( buf_len + vUDP_PACKET_OVERHEAD, m_Timestamp );\r\n\t\t\t\t\tconn->m_last_send_time = m_Timestamp;\r\n\t\t\t\t\tconn->SetForceSendThisFrame( false );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// If it didn't send the messages properly, flag them for resend next frame\r\n\t\t\t\t\tconn->FlagMessagesForResending( conn->m_latest_sent_packet_stamp );\r\n\t\t\t\t\tconn->m_write_ptr = conn->m_write_buffer;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tconn->m_write_ptr = conn->m_write_buffer;\t\t\t\t\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( SendTo( conn->GetIP(), conn->GetPort(), conn->m_write_buffer, buf_len, 0 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tm_TotalBytesOut += buf_len;\r\n\t\t\t\t\tconn->GetOutboundMetrics()->AddPacket( buf_len + vUDP_PACKET_OVERHEAD, m_Timestamp );\r\n\t\t\t\t\tconn->m_last_send_time = m_Timestamp;\r\n\t\t\t\t\tconn->SetForceSendThisFrame( false );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Printf( \"*** SendTo Error: Flagging messages for resending\\n\" );\r\n\t\t\t\t\t// If it didn't send the messages properly, flag them for resend next frame\r\n\t\t\t\t\tconn->FlagMessagesForResending( conn->m_latest_sent_packet_stamp );\r\n\t\t\t\t\tconn->m_write_ptr = conn->m_write_buffer;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tconn->m_write_ptr = conn->m_write_buffer;\t\t\t\t\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tconn->m_latest_sent_packet_stamp++;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Client's receive function                                      */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tClient::ReceiveData( void )\r\n{\r\n\tConn *conn;\r\n\tint num_bytes, actual_data_len;\r\n\tstruct sockaddr from_address;\r\n#ifdef __PLAT_NGC__\r\n\tfrom_address.len = sizeof( sockaddr );\r\n#else\r\n\tint addr_len = sizeof( from_address );\r\n#endif\r\n\tstruct sockaddr_in *foreign_address;\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t// Local clients never really receive. Their data is automatically \"received\" when\r\n\t// the local server writes its data into the client's receive buffer automatically\r\n\tif( IsLocal())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t// read data into local buffers\r\n\tdo\r\n\t{   \r\n\t\tif( !m_connected )\r\n\t\t{   \r\n\t\t\tnum_bytes = recvfrom( m_socket, m_in_packet_buffer, \r\n\t\t\t\tManager::vMAX_PACKET_SIZE, 0, &from_address, &addr_len );\r\n\t\t}\r\n\t\telse\r\n\t\t{   \r\n\t\t\tnum_bytes = recv( m_socket, m_in_packet_buffer, Manager::vMAX_PACKET_SIZE, 0 );\r\n\t\t}\r\n\t\tif ( num_bytes < 0 )//== SOCKET_ERROR ) \r\n\t\t{\r\n#if defined( __PLAT_WN32__ ) || defined( __PLAT_XBOX__ )\r\n\t\t\tif( WSAGetLastError() != WSAEWOULDBLOCK )\r\n#else\r\n#ifdef __PLAT_NGPS__\r\n\t\t\tif( sn_errno( m_socket ) != EWOULDBLOCK )\r\n#else\r\n#ifdef __PLAT_NGC__\r\n\t\t\tif( num_bytes != SO_EWOULDBLOCK )\r\n#endif\r\n#endif\r\n#endif\r\n            {\r\n#ifdef NET_DEBUG_MESSAGES\r\n\t\t\t\tDbg_Printf( \"Client Receive Error :\" );\r\n#ifdef __PLAT_WN32__\r\n\t\t\t\tOutputDebugString( \"Client Receive Error!\\n\" );\r\n#endif\r\n\t\t\t\tReportError();\r\n#endif\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\telse\r\n\t\t{   \r\n#ifdef __PLAT_NGPS__\r\n\t\t\tWaitSema( m_receive_semaphore_id );\r\n#endif\t// __PLAT_NGPS__\r\n\t\t\tm_TotalBytesIn += num_bytes;\r\n\t\t\tif( m_flags & App::mSECURE )\r\n\t\t\t{\r\n\t\t\t\tactual_data_len = num_bytes - sizeof( unsigned short );\t// total size - CRC size\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tactual_data_len = num_bytes;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tconn = GetConnectionByAddress( m_server_address.sin_addr.s_addr, \r\n\t\t\t\t\t\t\t\t\t\t\tntohs( m_server_address.sin_port ));\r\n            if( conn )\r\n\t\t\t{\r\n\t\t\t\tif(( conn->m_read_ptr + actual_data_len ) < ( conn->m_read_buffer + Conn::vREAD_BUFFER_LENGTH ))\r\n\t\t\t\t{\r\n\t\t\t\t\tTmr::Time cur_time;\r\n\r\n\t\t\t\t\tcur_time = Tmr::GetTime();\r\n\t\t\t\t\tif( !validate_and_copy_stream( m_in_packet_buffer, conn->m_read_ptr, num_bytes ))\r\n\t\t\t\t\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t\t\t\tSignalSema( m_receive_semaphore_id );\r\n#endif\t// __PLAT_NGPS__\r\n\t\t\t\t\t\t// If the game would like to handle this foreign data, allow it to do so now\r\n\t\t\t\t\t\tif( m_foreign_handler )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tm_foreign_handler( m_in_packet_buffer, num_bytes, &from_address );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconn->m_read_ptr += actual_data_len;\r\n\t\t\t\t\tconn->GetInboundMetrics()->AddPacket( num_bytes + vUDP_PACKET_OVERHEAD, m_Timestamp );\r\n\t\t\t\t\tif( cur_time > conn->m_last_comm_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tconn->m_last_comm_time = cur_time;\r\n\t\t\t\t\t}\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n#ifdef __PLAT_WN32__\r\n\t\t\t\t\tchar message[1024];\r\n\t\t\t\t\tsprintf( message, \"****** %d: Dropped Packet\\n\", m_Timestamp );\r\n\t\t\t\t\tOutputDebugString( message ); \r\n#endif\t// __PLAT_WN32__\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if( !m_connected )\r\n\t\t\t{\r\n\t\t\t\tConn* foreign_conn;\r\n\r\n\t\t\t\tforeign_address = (struct sockaddr_in*) &from_address;\r\n\t\t\t\t// Foreign connection. Create temporary connection to process this foreign message\r\n\t\t\t\tforeign_conn = NewConnection( foreign_address->sin_addr.s_addr, \r\n\t\t\t\t\t\t\t\t\t\t\t\tntohs( foreign_address->sin_port ), \r\n\t\t\t\t\t\t\t\t\t\t\t  Conn::mREMOTE | \r\n\t\t\t\t\t\t\t\t\t\t\t  Conn::mFOREIGN );\r\n\t\t\t\tif( foreign_conn )\r\n\t\t\t\t{\r\n\t\t\t\t\tforeign_conn->m_app = this;\r\n\t\t\t\t\t//memcpy( foreign_conn->m_read_buffer, m_read_buffer, actual_data_len );\t\t\t\t\r\n\t\t\t\t\tif( !validate_and_copy_stream( m_in_packet_buffer, foreign_conn->m_read_ptr, num_bytes ))\r\n\t\t\t\t\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t\t\t\tSignalSema( m_receive_semaphore_id );\r\n#endif\t// __PLAT_NGPS__\r\n\t\t\t\t\t\t// If the game would like to handle this foreign data, allow it to do so now\r\n\t\t\t\t\t\tif( m_foreign_handler )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tm_foreign_handler( m_in_packet_buffer, num_bytes, &from_address );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tdelete foreign_conn;\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tforeign_conn->m_read_ptr = foreign_conn->m_read_buffer + actual_data_len;\t\t\t\t\r\n\t\t\t\t\tforeign_conn->Invalidate();\r\n\t\t\t\t}\r\n\t\t\t}\r\n#ifdef __PLAT_NGPS__\r\n\t\t\tSignalSema( m_receive_semaphore_id );\r\n#endif\t// __PLAT_NGPS__\r\n\t\t}\t\t\r\n\r\n\t} while( num_bytes > 0 );\r\n}\r\n\r\n#ifdef USE_ALIASES\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tClient::ClearAliasTable( void )\r\n{\r\n\tint i;\r\n\r\n\tfor( i = 0; i < vNUM_ALIASES; i++ )\r\n\t{\r\n\t\tm_alias_table[i].m_Id = 0;\r\n\t\tm_alias_table[i].m_Expiration = -1;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nunsigned char\tClient::GetObjectAlias( int obj_id, int cur_time )\r\n{\r\n\tint hash, i;\r\n\tbool quit;\r\n\r\n\thash = obj_id & 0xff;\t// mask off all but lowest byte and use as a hash into the table\r\n\thash %= vNUM_ALIASES;\r\n\tquit = false;\r\n\ti = hash;\r\n\tdo\r\n\t{   \r\n\t\tif( m_alias_table[i].m_Id == obj_id )\r\n\t\t{   \r\n\t\t\tif( cur_time > m_alias_table[i].m_Expiration )\r\n\t\t\t{\r\n\t\t\t\treturn (unsigned char) vNO_ALIAS;\r\n\t\t\t}\r\n\t\t\treturn i;\r\n\t\t}\r\n\t\t\r\n\t\ti = ( i + 1 ) % vNUM_ALIASES;\r\n\t\tif( i == hash )\t// complete revolution\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t} while( !quit );\r\n\r\n\treturn (unsigned char) vNO_ALIAS;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nunsigned char\tClient::NewObjectAlias( int obj_id, int cur_time, bool expires )\r\n{\r\n\tint hash, i;\r\n\tbool quit;\r\n\r\n\t\r\n\r\n\thash = obj_id & 0xff;\t// mask off all but lowest byte and use as a hash into the table\r\n\thash %= vNUM_ALIASES;\r\n\tquit = false;\r\n\ti = hash;\r\n\tdo\r\n\t{\r\n\t\tif( m_alias_table[i].m_Id == obj_id )\r\n\t\t{   \r\n\t\t\tm_alias_table[i].m_Expiration = cur_time + vALIAS_DURATION;\r\n\t\t\treturn (unsigned char) i;\r\n\t\t}\r\n\t\telse if(( cur_time - m_alias_table[i].m_Expiration ) > vALIAS_DURATION )\r\n\t\t{\r\n\t\t\tm_alias_table[i].m_Id = obj_id;\r\n\t\t\tm_alias_table[i].m_Expiration = cur_time + vALIAS_DURATION;\r\n\t\t\treturn (unsigned char) i;\r\n\t\t}\r\n\t\ti = ( i + 1 ) % vNUM_ALIASES;\r\n\t\tif( i == hash )\t// complete revolution\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t} while( !quit );\r\n\r\n\t// no free aliases\r\n\treturn (unsigned char) vNO_ALIAS;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tClient::GetObjectId( unsigned char alias )\r\n{\r\n\t\r\n    \r\n\t//Dbg_MsgAssert(( m_LatestPacketStamp <= m_alias_table[ alias ].m_Expiration ), \"Server using expired alias\\n\" );\r\n\treturn m_alias_table[ alias ].m_Id;\r\n}\r\n\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nClient::Client( int flags )\r\n: App( flags )\r\n{\r\n\tm_send_network_data_task = new Tsk::Task< App > ( send_network_data, *this, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_CLIENT_SEND_NETWORK_DATA );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\t// namespace Net\r\n"
  },
  {
    "path": "Code/Gel/Net/Client/netclnt.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNET  (Net)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/netclnt.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t01/29/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __NETCLNT_H__\r\n#define __NETCLNT_H__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gel/net/net.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Net\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Client : public App\r\n{\r\n\tfriend class Manager;\r\n\r\npublic:\r\n\t\t\tClient( int flags = 0 );\r\n\r\n\tbool\tConnectToServer( int ip, unsigned short port );\t\r\n\tvoid\tReceiveData( void );\t\r\n\tvoid\tSendEnqueuedMessages( Conn* conn );\r\n\t\r\n#ifdef USE_ALIASES\r\n\t// Alias functions\r\n\tvoid\tClearAliasTable( void );\r\n\tunsigned char\tGetObjectAlias( int obj_id, int cur_time );\r\n\tunsigned char\tNewObjectAlias( int obj_id, int cur_time, bool expires = true );\r\n\tint\t\tGetObjectId( unsigned char alias );\r\nprivate:\r\n\t\r\n\tAliasEntry\tm_alias_table[ vNUM_ALIASES ];\r\n#endif\r\n    \r\nprotected:\r\n\tbool\tinit( void );\r\n\tvoid\tdeinit( void );\r\n\r\n\tstatic\tMsgHandlerCode\thandle_timestamp;\r\n\tstatic\tMsgHandlerCode\thandle_connection_refusal;\r\n\r\n\tstruct\tsockaddr_in\tm_server_address;\r\n\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\t// namespace Net\r\n\r\n#endif // __NETCLNT_H__"
  },
  {
    "path": "Code/Gel/Net/Dispatch/netdsptch.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNet (OBJ) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tnetdsptch.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/29/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNetwork Dispatching code\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <string.h>\r\n#include <gel/net/net.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#define NET_PRINT_MESSAGES 1 \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Net\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMsgHandler::MsgHandler( MsgHandlerCode *code, int flags, void *data, int pri )\r\n: Lst::Node< MsgHandler >( this, pri ), m_code( code ), m_data( data ), m_flags( flags )\r\n{   \r\n}\r\n\r\n/******************************************************************/\r\n/* Register a handler for a net msg                               */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMsgHandler*\tDispatcher::AddHandler( unsigned char net_msg_id, MsgHandlerCode *code, int flags, \r\n\t\t\t\t\t\tvoid *data, int pri )\r\n{\t\r\n\tMsgHandler* handler;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\thandler = new MsgHandler( code, flags, data, pri );\r\n\r\n\tm_handler_list[net_msg_id].AddNode( handler );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn handler;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tDispatcher::Init( void )\r\n{\r\n\tint i;\r\n\r\n\tfor( i = 0; i < MAX_NET_MSG_ID; i++ )\r\n\t{\r\n\t\tm_handler_list[i].DestroyAllNodes();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tDispatcher::Deinit( void )\r\n{\r\n\tint i;\r\n\r\n\t\r\n\r\n\tfor( i = 0; i < MAX_NET_MSG_ID; i++ )\r\n\t{   \r\n\t\tLst::Search< MsgHandler > sh;\r\n\t\tMsgHandler* handler, *next;\r\n\t\t\r\n\t\tfor( handler = sh.FirstItem( m_handler_list[i] ); handler;\r\n\t\t\t\thandler = next )\r\n\t\t{\r\n\t\t\tnext = sh.NextItem();\r\n\r\n\t\t\tdelete handler;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Dispatch messages to their appropriate handlers                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tDispatcher::DispatchMsgHandlers( Conn *conn, int flags )\r\n{\r\n\tMsgHandlerContext msg_context;\r\n\tchar msg_data[MAX_STREAM_LENGTH];\r\n\tint result;\r\n\tchar *data;\r\n\r\n\tDbg_Assert( conn != NULL );\t\r\n\r\n\tmsg_context.m_Conn = conn;\r\n\tmsg_context.m_App = conn->m_app;\r\n\tmsg_context.m_PacketFlags = flags;\r\n\tmsg_context.m_Msg = msg_data;\r\n\tmsg_context.m_MsgLength = 0;\r\n\r\n\tdata = conn->m_read_buffer;\t\t\r\n\r\n\t// loop through received data and handle messages\r\n\twhile( data < conn->m_read_ptr )\r\n\t{\t\t\r\n\t\tbool size_known;\r\n\r\n        // *** IMPORTANT.  Because of alignment issues, I now copy the data from the byte stream\r\n\t\t// into an aligned message buffer.  Indexing into the buffer and casting to Msg's caused\r\n\t\t// load errors\r\n\t\tmemcpy( &msg_context.m_MsgId, data, sizeof( unsigned char ));\r\n\t\tdata += sizeof( unsigned char );\r\n\r\n\t\t// Check to see if the size of this message type is stored after the msg id\r\n\t\tsize_known = (( conn->m_app->GetManager()->GetMessageFlags( msg_context.m_MsgId ) & mMSG_SIZE_UNKNOWN ) == 0 );\r\n\t\t//if( conn->IsRemote())\r\n\t\t//{\r\n\t\t\t//Dbg_Printf( \"Got message %s with size_known of %d\\n\", conn->m_app->GetManager()->GetMessageName(msg_context.m_MsgId ), size_known);\r\n\t\t//}\r\n\t\t\r\n\t\tif( size_known )\r\n\t\t{\r\n\t\t\tunsigned short temp;\r\n\t\t\tmemcpy( &temp, data, sizeof( unsigned short ));\r\n\t\t\tmsg_context.m_MsgLength = (unsigned long)temp;\r\n\r\n\t\t\tdata += sizeof( unsigned short );\t\t\r\n\t\t}\r\n        \r\n\t\tif( msg_context.m_MsgId == MSG_ID_SEQUENCED )\r\n\t\t{\r\n\t\t\tunsigned char embedded_msg_id;\r\n\t\t\tunsigned short embedded_msg_length;\r\n            \r\n\t\t\tDbg_Assert( size_known );\r\n\r\n\t\t\tmemcpy( &embedded_msg_id, data + 5, sizeof( unsigned char ));\r\n\t\t\tembedded_msg_length = msg_context.m_MsgLength - Manager::vMSG_SEQ_HEADER_LENGTH;\r\n\t\t\t\t\t\t\r\n\t\t\tconn->GetInboundMetrics()->AddMessage( embedded_msg_id, msg_context.m_MsgLength );\r\n#ifdef NET_PRINT_MESSAGES\r\n\t\t\tif( conn->IsRemote())\r\n\t\t\t{\r\n\t\t\t\tunsigned char group_id;\r\n\t\t\t\tunsigned int seq_id;\r\n\r\n\t\t\t\tmemcpy( &group_id, data, sizeof( unsigned char ));\r\n\t\t\t\tmemcpy( &seq_id, data + 1, sizeof( unsigned int ));\r\n\t\t\t\tDbg_Printf( \"(%d) Dispatching Sequenced Message (%d) Length (%d) Emb. Length (%d) : %s. Seq: %d Group: %d\\n\", \r\n\t\t\t\t\t\t\tconn->m_app->m_FrameCounter,\r\n\t\t\t\t\t\t\tembedded_msg_id,\r\n\t\t\t\t\t\t\tmsg_context.m_MsgLength,\r\n\t\t\t\t\t\t\tembedded_msg_length,\r\n\t\t\t\t\t\t\tconn->m_app->GetManager()->GetMessageName( embedded_msg_id ),\r\n\t\t\t\t\t\t\tseq_id,\r\n\t\t\t\t\t\t\tgroup_id );\r\n\t\t\t}\r\n#endif NET_PRINT_MESSAGES\r\n\t\t}\r\n\t\t\r\n\t\t// If we know the size, just copy the message into the aligned buffer\r\n\t\t// otherwise, copy the maximum size of a message into the buffer and have the\r\n\t\t// handler tell us the size of the message by changint the context's m_MsgLength member\r\n\t\tif( size_known )\r\n\t\t{\r\n\t\t\tif( msg_context.m_MsgLength > 0 )\r\n\t\t\t{\r\n\t\t\t\tmemcpy( msg_context.m_Msg, data, msg_context.m_MsgLength );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmemcpy( msg_context.m_Msg, data, Manager::vMAX_PACKET_SIZE );\r\n\t\t}\r\n\r\n\t\tif( conn->IsForeign())\r\n\t\t{\r\n\t\t\tmsg_context.m_PacketFlags |= mHANDLE_FOREIGN;\r\n\t\t}\r\n\t\tresult = DispatchMessage( &msg_context );\r\n\t\tif(\t( result == HANDLER_ERROR ) ||\r\n\t\t\t( result == HANDLER_HALT ))\r\n\t\t{\r\n\t\t\t// output error indicating mal-formmated data\r\n\t\t\tDbg_Printf( \"Stream processing halted on message %d\\n\", msg_context.m_MsgId );\r\n\t\t\tconn->m_read_ptr = conn->m_read_buffer;\r\n\t\t\treturn HANDLER_HALT;\r\n\t\t}\r\n\r\n\t\t// By this time we know the message size, whether it was explicit or implicit\r\n\t\t// so we can do the metrics calculation and the debug printout\r\n\t\tif( msg_context.m_MsgId != MSG_ID_SEQUENCED )\r\n\t\t{\r\n\t\t\tconn->GetInboundMetrics()->AddMessage( msg_context.m_MsgId, msg_context.m_MsgLength );\r\n#ifdef NET_PRINT_MESSAGES\r\n\t\t\t/*if( conn->IsRemote())\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"(%d) Dispatching Message (%d) Length (%d) : %s\\n\", \r\n\t\t\t\t\t\t\tconn->m_app->m_FrameCounter,\r\n\t\t\t\t\t\t\tmsg_context.m_MsgId,\r\n\t\t\t\t\t\t\tmsg_context.m_MsgLength,\r\n\t\t\t\t\t\t\tconn->m_app->GetManager()->GetMessageName( msg_context.m_MsgId ));\r\n\t\t\t}*/\r\n#endif\r\n\t\t}\r\n\r\n\t\tdata += msg_context.m_MsgLength;\r\n\t}\r\n\r\n\tconn->m_read_ptr = conn->m_read_buffer;\r\n\treturn HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Dispatch a message to its appropriate handler. Stop if higher  */\r\n/* priority handlers say to                                       */\r\n/******************************************************************/\r\n\r\nint\tDispatcher::DispatchMessage( MsgHandlerContext *context )\r\n{\r\n\tLst::Search< MsgHandler > sh;\r\n\tMsgHandler *handler, *next;\r\n\tint result;\r\n\r\n\t\r\n\r\n\tDbg_Assert( context );\r\n\r\n    // If this is a message we want to handle, call the handler\r\n\tfor( handler = sh.FirstItem( m_handler_list[context->m_MsgId] );\r\n\t\t\thandler; handler = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\r\n\t\tif(( handler->m_flags & context->m_PacketFlags ) != context->m_PacketFlags )\r\n\t\t{\r\n\t\t\tDbg_Printf( \"*** Conn %d packetflag mismatch on id %d : 0x%x 0x%x\\n\", context->m_Conn->GetHandle(), context->m_MsgId, handler->m_flags, context->m_PacketFlags );\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tcontext->m_Data = handler->m_data;\r\n\t\tresult = handler->m_code( context );\r\n\t\t// Check the result from the handler\r\n\t\tif(\t( result == HANDLER_ERROR ) ||\r\n\t\t\t( result == HANDLER_HALT ) ||\r\n\t\t\t( result == HANDLER_MSG_DESTROYED ))\r\n\t\t{\r\n\t\t\t// Stop processing the buffer\r\n\t\t\treturn result;\r\n\t\t}\t\t\r\n\t\t// A higher int handler has chosen to mask this message from the rest\r\n\t\tif( ( result == HANDLER_MSG_DONE ))\r\n\t\t{\r\n\t\t\treturn HANDLER_CONTINUE;\r\n\t\t}\r\n\t}\r\n\r\n\treturn HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\t// namespace Net"
  },
  {
    "path": "Code/Gel/Net/Handler/nethndlr.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNet (OBJ) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tnet.cpp\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/29/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNetwork Manager code\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <sys/timer.h>\r\n\r\n#include <stdio.h>\r\n\r\n#include <gel/net/net.h>\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#define DEBUG_MESSAGES\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Net\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/* Ack important messages                               \t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\thandle_ack( MsgHandlerContext *context )\r\n{\r\n\tMsgImpLink *msg_imp_link, *next_imp;\r\n\tMsgSeqLink *msg_seq_link, *next_seq;\r\n\tLst::Search< MsgImpLink > imp_sh;\r\n\tLst::Search< MsgSeqLink > seq_sh;\r\n\tMsgAck *ack_msg;\r\n\tQueuedMsg* msg;\r\n\tQueuedMsgSeq* msg_seq;\r\n\tunsigned int send_time;\r\n\t\t\r\n\t\r\n\r\n\tDbg_Assert( context );\r\n\r\n\tack_msg = (MsgAck*) context->m_Msg;\r\n\tsend_time = 0;\r\n\r\n#ifdef DEBUG_MESSAGES\r\n\tif( context->m_Conn->IsRemote())\r\n\t{\r\n\t\tDbg_Printf( \"(%d) Conn %d: (%d) Got Ack for Packetstamp %d\\n\", \r\n\t\t\tcontext->m_App->m_FrameCounter, \r\n\t\t\tcontext->m_Conn->GetHandle(),\r\n\t\t\tcontext->m_App->m_Timestamp, \r\n\t\t\tack_msg->m_Packetstamp );\r\n\t}\r\n#endif\r\n\r\n#ifdef __PLAT_NGPS__\r\n\t/*if( context->m_Conn->GetHandle() != ack_msg->m_Handle )\r\n\t{\r\n\t\tLst::Search< Conn > sh;\r\n\t\tConn* conn;\r\n\r\n\t\tfor( conn = context->m_App->FirstConnection( &sh ); conn; conn = context->m_App->NextConnection( &sh ))\r\n\t\t{\r\n\t\t\tDbg_Printf( \"*** Conn %d : %p. Ip: 0x%x Port: %d\\n\", conn->GetHandle(), conn, conn->GetIP(), conn->GetPort());\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert( context->m_Conn->GetHandle() == ack_msg->m_Handle, (\"*** Different handles! %d %d\\n\", context->m_Conn->GetHandle(), ack_msg->m_Handle ));*/\r\n#endif\r\n\r\n\t// Tell the dispatcher the size of this message because it does not know (optimization)\r\n\tcontext->m_MsgLength = sizeof( MsgAck );\r\n\r\n\t// Don't ack foreign acks. We only even handle them because we need to tell the dispatcher\r\n\t// the length of the message\r\n\tif( context->m_PacketFlags & mHANDLE_FOREIGN )\r\n\t{\r\n\t    return HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\tfor( msg_imp_link = imp_sh.FirstItem( context->m_Conn->m_important_msg_list ); \r\n\t\t\tmsg_imp_link; msg_imp_link = next_imp )\r\n\t{\r\n\t\tnext_imp = imp_sh.NextItem();\r\n\t\tif(\t( ack_msg->m_Packetstamp == (unsigned short) msg_imp_link->m_Packetstamp ) &&\r\n\t\t\t( msg_imp_link->m_Timestamp != 0 ))\t// guard against acking packet stamp of zero where zero is the initialized value\r\n\t\t{\r\n\t\t\tmsg = msg_imp_link->m_QMsg;\r\n\t\t\tmsg->m_Ref.Release();\r\n\t\t\tif( msg->m_Ref.InUse() == false )\r\n\t\t\t{\r\n\t\t\t\tdelete msg;\r\n\t\t\t}\r\n\t\t\tsend_time = msg_imp_link->m_Timestamp;\r\n\t\t\tdelete msg_imp_link;\r\n\t\t}\r\n\t}\t\r\n\r\n\tfor( msg_seq_link = seq_sh.FirstItem( context->m_Conn->m_sequenced_msg_list ); \r\n\t\t\tmsg_seq_link; msg_seq_link = next_seq )\r\n\t{\r\n\t\tnext_seq = seq_sh.NextItem();\r\n\t\t// ACK the message\r\n\t\tif( ( ack_msg->m_Packetstamp == (unsigned short) msg_seq_link->m_Packetstamp ) &&\r\n\t\t\t( msg_seq_link->m_Timestamp != 0 ))\t// guard against acking packet stamp of zero where zero is the initialized value\r\n\t\t{\r\n\t\t\tmsg_seq = msg_seq_link->m_QMsg;\r\n\t\t\tmsg_seq->m_Ref.Release();\r\n\t\t\t// If this message is no longer being referenced, free it\r\n\t\t\tif( msg_seq->m_Ref.InUse() == false )\r\n\t\t\t{\r\n\t\t\t\tdelete msg_seq;\r\n\t\t\t}\r\n\t\t\tsend_time = msg_seq_link->m_Timestamp;\r\n\t\t\tdelete msg_seq_link;\r\n\t\t}\r\n\t}\r\n\r\n\t// If we can detect that the connection is starting to take longer to ack\r\n\t// our messages then affect his calculated latency so that we don't expect\r\n\t// acks back so quickly (which prompts resends )\r\n\tif(\t( context->m_Conn->IsRemote()) &&\r\n\t\t( context->m_Conn->TestStatus( Conn::mSTATUS_READY )) &&\r\n\t\t( send_time > 0 ))\r\n\t{\r\n\t\tunsigned int latency_value;\r\n\r\n\t\tlatency_value = context->m_App->m_Timestamp - send_time;\r\n\t\tif( latency_value > (unsigned int) context->m_Conn->GetAveLatency())\r\n\t\t{\r\n            if( latency_value > App::MAX_LATENCY )\r\n\t\t\t{\r\n\t\t\t\tlatency_value = App::MAX_LATENCY;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcontext->m_Conn->m_latency_test.InputLatencyValue( latency_value );\r\n\t\t}\r\n\t}\r\n\r\n\treturn HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Aggregate stream messages\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tApp::handle_stream_messages( MsgHandlerContext *context )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\t//Dbg_Printf( \"******** Got Stream Message\\n\" );\r\n\r\n\tswitch( context->m_MsgId )\r\n\t{\r\n\t\tcase MSG_ID_STREAM_START:\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"******** Got Stream Start\\n\" );\r\n\t\t\tMsgStreamStart* msg;\r\n\t\t\tStreamLink* str_link;\r\n\t\t\tStreamDesc* new_stream;\r\n\t\t\tLst::Search< StreamLink > str_sh;\r\n\t\t\tint packet_len;\r\n\r\n\t\t\tmsg = (MsgStreamStart*) context->m_Msg;\r\n\t\t\t\r\n\t\t\tfor( str_link = str_sh.FirstItem( context->m_Conn->m_StreamInList ); str_link; \r\n\t\t\t\t\tstr_link = str_sh.NextItem())\r\n\t\t\t{\r\n\t\t\t\tStreamDesc* desc;\r\n\r\n\t\t\t\tdesc = str_link->m_Desc;\r\n\t\t\t\tif( desc->m_StreamId == msg->m_StreamId )\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\treturn HANDLER_MSG_DONE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n            \r\n\t\t\tnew_stream = new StreamDesc;\r\n\t\t\tstrcpy( new_stream->m_StreamDesc, msg->m_StreamDesc );\r\n\t\t\tDbg_Printf( \"StreamDesc: %s\\n\", new_stream->m_StreamDesc );\r\n\t\t\tnew_stream->m_Size = msg->m_Size;\r\n\t\t\tnew_stream->m_StreamId = msg->m_StreamId;\r\n\t\t\tnew_stream->m_Checksum = msg->m_Checksum;\r\n\t\t\tnew_stream->m_MsgId = msg->m_MsgId;\r\n\t\t\tnew_stream->m_Data = new char[ msg->m_Size ];\r\n\t\t\tnew_stream->m_DataPtr = new_stream->m_Data;\r\n\t\t\tpacket_len = ( msg->m_Size < MAX_STREAM_CHUNK_LENGTH ) ? msg->m_Size : MAX_STREAM_CHUNK_LENGTH;\r\n\t\t\tmemcpy( new_stream->m_Data, msg->m_Data, packet_len );\r\n\t\t\tnew_stream->m_DataPtr += packet_len;\r\n\t\t\tstr_link = new StreamLink( new_stream );\r\n\t\t\tcontext->m_Conn->m_StreamInList.AddToTail( str_link );\r\n\r\n\t\t\tif(((unsigned int) new_stream->m_DataPtr - (unsigned int) new_stream->m_Data ) >= (unsigned int) new_stream->m_Size )\r\n\t\t\t{\r\n\t\t\t\tMsgHandlerContext msg_context;\r\n\t\t\t\tint result;\r\n\r\n\t\t\t\t// Shouldn't go over\r\n\t\t\t\tDbg_Assert( ((unsigned int) new_stream->m_DataPtr - (unsigned int) new_stream->m_Data ) == (unsigned int) new_stream->m_Size );\r\n\r\n\t\t\t\tmsg_context.m_Conn = context->m_Conn;\r\n\t\t\t\tmsg_context.m_App = context->m_App;\r\n\t\t\t\tmsg_context.m_PacketFlags = 0;\r\n\t\t\t\tmsg_context.m_MsgId = new_stream->m_MsgId;\r\n\t\t\t\tmsg_context.m_MsgLength = new_stream->m_Size;\r\n\t\t\t\tmsg_context.m_Msg = new char[new_stream->m_Size];\r\n\t\t\t\t\r\n                memcpy( msg_context.m_Msg, new_stream->m_Data, new_stream->m_Size );\r\n\r\n\t\t\t\tresult = context->m_App->m_Dispatcher.DispatchMessage( &msg_context );\r\n\t\t\t\tif( result != HANDLER_MSG_DESTROYED )\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete str_link->m_Desc;\r\n\t\t\t\t\tdelete str_link;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tdelete [] msg_context.m_Msg;\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\treturn result;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase MSG_ID_STREAM_DATA:\r\n\t\t{\r\n\t\t\tMsgStreamData* msg;\r\n\t\t\tStreamLink* str_link;\r\n\t\t\tLst::Search< StreamLink > str_sh;\r\n\r\n\t\t\tmsg = (MsgStreamData*) context->m_Msg;\r\n\r\n\t\t\t//Dbg_Printf( \"******** Got Stream Data\\n\" );\r\n\t\t\tfor( str_link = str_sh.FirstItem( context->m_Conn->m_StreamInList ); str_link; \r\n\t\t\t\t\tstr_link = str_sh.NextItem())\r\n\t\t\t{\r\n\t\t\t\tStreamDesc* desc;\r\n\t\t\t\tint packet_len;\r\n\r\n\t\t\t\tdesc = str_link->m_Desc;\r\n\t\t\t\tif( desc->m_StreamId == msg->m_StreamId )\r\n\t\t\t\t{   \r\n\t\t\t\t\tpacket_len = context->m_MsgLength - sizeof( int );\t// subtract the size of the stream id\r\n\t\t\t\t\tmemcpy( desc->m_DataPtr, msg->m_Data, packet_len );\r\n\t\t\t\t\tdesc->m_DataPtr += packet_len;\r\n\r\n\t\t\t\t\tif(((unsigned int) desc->m_DataPtr - (unsigned int) desc->m_Data ) >= (unsigned int) desc->m_Size )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMsgHandlerContext msg_context;\r\n\t\t\t\t\t\tint result;\r\n\t\t\t\t\t\tuint32 actual_crc;\r\n\r\n\t\t\t\t\t\t// Shouldn't go over\r\n\t\t\t\t\t\tDbg_Assert( ((unsigned int) desc->m_DataPtr - (unsigned int) desc->m_Data ) == (unsigned int) desc->m_Size );\r\n\r\n\t\t\t\t\t\tmsg_context.m_Conn = context->m_Conn;\r\n\t\t\t\t\t\tmsg_context.m_App = context->m_App;\r\n\t\t\t\t\t\tmsg_context.m_PacketFlags = 0;\r\n\t\t\t\t\t\tmsg_context.m_MsgId = desc->m_MsgId;\r\n\t\t\t\t\t\tmsg_context.m_MsgLength = desc->m_Size;\r\n\t\t\t\t\t\tmsg_context.m_Msg = new char[desc->m_Size];\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tmemcpy( msg_context.m_Msg, desc->m_Data, desc->m_Size );\r\n\t\t\t\t\t\tactual_crc = Crc::GenerateCRCCaseSensitive( msg_context.m_Msg, desc->m_Size );\r\n\t\t\t\t\t\tif( actual_crc != desc->m_Checksum )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmsg_context.m_PacketFlags |= mHANDLE_CRC_MISMATCH;\r\n\t\t\t\t\t\t\tDbg_Printf( \"CRC MISMATCH!!!\\n\" );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tDbg_Printf( \"handling stream: %s\\n\", desc->m_StreamDesc );\r\n\t\t\t\t\t\tresult = context->m_App->m_Dispatcher.DispatchMessage( &msg_context );\r\n\t\t\t\t\t\tif( result != HANDLER_MSG_DESTROYED )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tdelete str_link->m_Desc;\r\n\t\t\t\t\t\t\tdelete str_link;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tdelete [] msg_context.m_Msg;\r\n\r\n\t\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\t\treturn result;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Put sequenced messages in their queue in order in their group  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tApp::handle_sequenced_messages( MsgHandlerContext *context )\r\n{\r\n\tMsgSeqLink *msg_link;\t\r\n\tchar* data;\r\n\tunsigned short\tmsg_len;\r\n\tQueuedMsgSeq* queued_msg;\r\n\tunsigned char group_id, msg_id;\t\r\n\tunsigned int seq_id;\r\n\tLst::Search< MsgHandler > sh;\r\n\t\r\n\t\r\n\r\n\tDbg_Assert( context );\r\n\r\n\tdata = context->m_Msg;\r\n\tmemcpy( &group_id, data, sizeof( char ));\r\n\tdata += sizeof( char );\r\n\tmemcpy( &seq_id, data, sizeof( unsigned int ));\r\n\tdata += sizeof (unsigned int );\t\r\n\t\t\r\n\t// don't accept old sequenced messages\r\n\tif( seq_id < context->m_Conn->m_WaitingForSequenceId[ group_id ] )\r\n\t{\r\n\t\treturn HANDLER_CONTINUE;\r\n\t}\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\tmemcpy( &msg_id, data, sizeof( unsigned char ));\r\n\tdata += sizeof( unsigned char );\r\n\r\n\tmsg_len = context->m_MsgLength - Manager::vMSG_SEQ_HEADER_LENGTH;\r\n\t\r\n\tqueued_msg = new QueuedMsgSeq( msg_id, msg_len, data, group_id );\r\n\r\n\tmsg_link = new MsgSeqLink( queued_msg );\r\n\tmsg_link->SetPri( seq_id );\r\n\tmsg_link->m_Timestamp = 0;\r\n\tmsg_link->m_Packetstamp = 0;\r\n\tmsg_link->m_GroupId = group_id;\r\n\tmsg_link->m_SequenceId = seq_id;\r\n    \r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// This might be dangerous in some apps, but it makes sense right now.  Don't add\r\n\t// this message to the sequenced queue if we dont have a handler for it.\r\n\t/*if( sh.FirstItem( context->m_App->m_Dispatcher.m_handler_list[msg_id] ) == NULL )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"No handler for msg %d\\n\", msg_id ));\r\n\t\tdelete msg_link->m_QMsg;\r\n\t\tdelete msg_link;\t\r\n\t\treturn HANDLER_MSG_DONE;\r\n\t}*/\r\n\t\t// Don't re-add identical sequenced messages\r\n\tif( context->m_Conn->m_SequencedBuffer[group_id].AddUniqueSequence( msg_link ) == false )\r\n\t{\r\n\t    delete msg_link->m_QMsg;\r\n\t\tdelete msg_link;\r\n\t\treturn HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\treturn HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Ack the packet immediately when we get it                      */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tServer::handle_timestamp( MsgHandlerContext *context )\r\n{\r\n\tMsgDesc msg_desc;\r\n\tMsgPacketStamp *time_msg;\r\n\tMsgAck ack_msg;\r\n\t\r\n\tDbg_Assert( context );\r\n\r\n\t// Tell the dispatcher the size of this message because it does not know (optimization)\r\n\tcontext->m_MsgLength = sizeof( MsgPacketStamp );\r\n\r\n\t// Don't ack foreign timestamps. We only even handle them because we need to tell the dispatcher\r\n\t// the length of the message\r\n\tif( context->m_PacketFlags & mHANDLE_FOREIGN )\r\n\t{\r\n\t\treturn HANDLER_MSG_DONE;\r\n\t}\r\n\t\r\n\ttime_msg = (MsgPacketStamp *) context->m_Msg;\t\r\n\tack_msg.m_Packetstamp = time_msg->m_Packetstamp;\r\n\t//ack_msg.m_Handle = time_msg->m_Handle;\r\n\r\n#ifdef DEBUG_MESSAGES\r\n\tif( context->m_Conn->IsRemote())\r\n\t{\r\n\t\tDbg_Printf( \"(%d) Conn %d: (%d) Got Packetstamp %d\\n\", \r\n\t\t\tcontext->m_App->m_FrameCounter, \r\n\t\t\tcontext->m_Conn->GetHandle(),\r\n\t\t\tcontext->m_App->m_Timestamp, \r\n\t\t\ttime_msg->m_Packetstamp );\r\n\t}\r\n#endif\r\n\r\n\tmsg_desc.m_Data = &ack_msg;\r\n\tmsg_desc.m_Length = sizeof( MsgAck );\r\n\tmsg_desc.m_Id = MSG_ID_ACK;\r\n\tcontext->m_App->EnqueueMessage( context->m_Conn->GetHandle(), &msg_desc );\r\n\t\r\n\treturn HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*     \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                         \t\t  */\r\n/******************************************************************/\r\n\r\nint Server::handle_disconn_req( MsgHandlerContext* context )\r\n{\r\n\tMsgDesc msg_desc;\r\n\r\n#ifdef DEBUG_MESSAGES\r\n\tDbg_Message( \"Got disconnection request. Setting connection status to mSTATUS_DISCONNECTING\\n\" );\r\n#endif\r\n\t// Don't re-disconnect someone\r\n\tif( context->m_Conn->TestStatus( Conn::mSTATUS_DISCONNECTING ))\r\n\t{\r\n\t\treturn HANDLER_MSG_DONE;\r\n\t}\r\n\t// Enqueue a disconn acceptance message before the cutoff point \r\n\t// for enqueuing messages( Conn::mSTATUS_DISCONNECTING )\r\n    msg_desc.m_Id = MSG_ID_DISCONN_ACCEPTED;\r\n\tcontext->m_App->EnqueueMessage( context->m_Conn->GetHandle(), &msg_desc );\r\n\tcontext->m_Conn->SetStatus( Conn::mSTATUS_DISCONNECTING );\r\n\treturn HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Handle the timestamp from the server. Check for lost & late    */\r\n/* packets                                                        */\r\n/******************************************************************/\r\n\r\nint\tClient::handle_timestamp( MsgHandlerContext *context )\r\n{\r\n\tMsgPacketStamp *time_msg;\r\n\tMsgAck ack_msg;\r\n\tMsgDesc msg_desc;\r\n\r\n\tDbg_Assert( context );\r\n\r\n\t// Tell the dispatcher the size of this message because it does not know (optimization)\r\n\tcontext->m_MsgLength = sizeof( MsgPacketStamp );\r\n\r\n\t// Don't ack foreign timestamps. We only even handle them because we need to tell the dispatcher\r\n\t// the length of the message\r\n\tif( context->m_PacketFlags & mHANDLE_FOREIGN )\r\n\t{\r\n\t\treturn HANDLER_MSG_DONE;\r\n\t}\r\n    \r\n\ttime_msg = (MsgPacketStamp *) context->m_Msg;\r\n\tack_msg.m_Packetstamp = time_msg->m_Packetstamp;\r\n\t//ack_msg.m_Handle = time_msg->m_Handle;\r\n\r\n#ifdef DEBUG_MESSAGES\r\n\tif( context->m_Conn->IsRemote())\r\n\t{\r\n\t\tDbg_Printf( \"(%d) Conn %d: (%d) Got Packetstamp %d\\n\", \r\n\t\t\tcontext->m_App->m_FrameCounter, \r\n\t\t\tcontext->m_Conn->GetHandle(),\r\n\t\t\tcontext->m_App->m_Timestamp, \r\n\t\t\ttime_msg->m_Packetstamp );\r\n\t}\r\n#endif\r\n\t\r\n\tmsg_desc.m_Data = &ack_msg;\r\n\tmsg_desc.m_Length = sizeof( MsgAck );\r\n\tmsg_desc.m_Id = MSG_ID_ACK;\r\n\tcontext->m_App->EnqueueMessageToServer( &msg_desc );\r\n\r\n\t// Todo : Change this logic as packetstamps DO wraparound\r\n\t// if == 0, we just connected : accept first timestamp unconditionally\r\n\tif( context->m_Conn->m_latest_packet_stamp == 0 )\r\n\t{\r\n\t\tcontext->m_Conn->m_latest_packet_stamp = time_msg->m_Packetstamp;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Check for late packets, but also make sure it's actually late, and not just wraparound\r\n\t\tif( time_msg->m_Packetstamp < context->m_Conn->m_latest_packet_stamp )\r\n\t\t{\r\n\t\t\tif(( context->m_Conn->m_latest_packet_stamp - time_msg->m_Packetstamp ) > 5000 )\r\n\t\t\t{\r\n\t\t\t\tcontext->m_Conn->m_latest_packet_stamp = time_msg->m_Packetstamp;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tcontext->m_App->m_LatePackets++;\r\n\t\t\t\tcontext->m_App->m_LostPackets--;\r\n\t\t\t\tcontext->m_PacketFlags |= mHANDLE_LATE;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( time_msg->m_Packetstamp == context->m_Conn->m_latest_packet_stamp )\r\n\t\t{\r\n\t\t\tcontext->m_App->m_DupePackets++;\r\n\t\t\tDbg_Printf( \"**** Got Duplicate Packet: %d\\n\", context->m_App->m_DupePackets ); \r\n\t\t\treturn HANDLER_ERROR;\t// don't process dupes\r\n\t\t}\r\n\t\telse if(( time_msg->m_Packetstamp - context->m_Conn->m_latest_packet_stamp ) > 1 )\r\n\t\t{\r\n\t\t\t// Check for lost packets and make sure it's not just wraparound\r\n\t\t\tif(( time_msg->m_Packetstamp - context->m_Conn->m_latest_packet_stamp ) > 5000 )\r\n\t\t\t{\r\n\t\t\t\tcontext->m_App->m_LatePackets++;\r\n\t\t\t\tcontext->m_App->m_LostPackets--;\r\n\t\t\t\tcontext->m_PacketFlags |= mHANDLE_LATE;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tcontext->m_App->m_LostPackets += \r\n\t\t\t\t\t\t(( time_msg->m_Packetstamp - context->m_Conn->m_latest_packet_stamp ) - 1 );\r\n\t\t\t\tcontext->m_Conn->m_latest_packet_stamp = time_msg->m_Packetstamp;  \r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcontext->m_Conn->m_latest_packet_stamp = time_msg->m_Packetstamp;  \r\n\t\t}\r\n\t}\r\n\r\n\treturn HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Respond to ping test                                           */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\thandle_latency_test( MsgHandlerContext *context )\r\n{\r\n\tMsgDesc msg_desc;\r\n\tMsgTimestamp latency_response_msg;\r\n    MsgTimestamp *time_msg;\r\n\tConn *conn;\r\n\r\n\tDbg_Assert( context );\r\n    \r\n\ttime_msg = (MsgTimestamp *) context->m_Msg;\r\n\tconn = context->m_Conn;\r\n    \r\n\t// \"Pong\" back to the ping\r\n\tlatency_response_msg.m_Timestamp = time_msg->m_Timestamp;\r\n\r\n\tmsg_desc.m_Data = &latency_response_msg;\r\n\tmsg_desc.m_Length = sizeof( MsgTimestamp );\r\n\tmsg_desc.m_Id = MSG_ID_PING_RESPONSE;\r\n\tcontext->m_App->EnqueueMessage( conn->GetHandle(), &msg_desc );   \r\n    \r\n\treturn HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Take note of latency value                                     */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\thandle_latency_response( MsgHandlerContext *context )\r\n{\r\n\tMsgTimestamp *time_msg;\r\n\tConn *conn;\r\n\tint cur_time;\r\n\r\n\tDbg_Assert( context );\r\n\r\n\ttime_msg = (MsgTimestamp *) context->m_Msg;\r\n\tconn = context->m_Conn;\r\n\r\n\tif( conn->IsLocal())\r\n\t{\r\n\t\treturn HANDLER_CONTINUE;\r\n\t}\r\n\t\r\n\tcur_time = context->m_App->m_Timestamp;\r\n\r\n\t// if it's the one we're waiting for\r\n\tif( time_msg->m_Timestamp == conn->m_latency_test.m_SendTime )\r\n\t{   \r\n\t\tunsigned int latency_value;\r\n\r\n\t\tconn->m_latency_test.m_ReceiveTime = time_msg->m_Timestamp;\r\n\t\tlatency_value = ( cur_time - time_msg->m_Timestamp );\r\n\t\tif( latency_value > App::MAX_LATENCY )\r\n\t\t{\r\n\t\t\tlatency_value = App::MAX_LATENCY;\r\n\t\t}\r\n\t\tconn->m_latency_test.InputLatencyValue( latency_value );\t\t\r\n\t}\r\n\r\n\treturn HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* We've been accepted to the server                              */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tApp::handle_connection_accepted( MsgHandlerContext *context )\r\n{\r\n\t\r\n#ifdef DEBUG_MESSAGES\r\n\tDbg_Message( \"Connection was accepted!\\n\" );\r\n#endif\r\n\treturn HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* The server rejected our connection request (app_level)         */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tClient::handle_connection_refusal( MsgHandlerContext *context )\r\n{\r\n\tClient *client;\r\n\r\n\t\r\n\r\n\tDbg_Assert( context );\r\n\r\n\tclient = (Client *) context->m_App;\r\n\t// disconnect\r\n\t//client->ConnectToServer( INADDR_ANY, 0 );\r\n\tclient->TerminateConnection( context->m_Conn );\r\n\r\n\treturn HANDLER_HALT;\r\n}\r\n\r\n/******************************************************************/\r\n/* Someone is requesting connection (app-level)                   */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tApp::handle_connection_request( MsgHandlerContext *context )\r\n{\r\n\tMsgDesc msg_desc;\r\n\r\n\tDbg_Assert( context );\r\n\r\n#ifdef DEBUG_MESSAGES\r\n\tDbg_Message( \"Got Connection Request!\\n\" );\r\n#endif\r\n\r\n\t// Redundancy check\r\n    if( context->m_PacketFlags & mHANDLE_FOREIGN )\r\n\t{\r\n\t\tint ip;\r\n\r\n\t\tif( context->m_App->AcceptsForeignConnections() == false )\r\n\t\t{\r\n\t\t\treturn HANDLER_MSG_DONE;\r\n\t\t}\r\n\r\n\t\tip = context->m_Conn->GetIP();\r\n        \r\n#ifndef __PLAT_NGC__\r\n\t\t/*Dbg_Message( \"Accepting connection from IP:%s Port:%d\\n\", \r\n\t\t\t\t\t inet_ntoa( *(struct in_addr *) &ip), \r\n\t\t\t\t\t context->m_Conn->GetPort());*/\r\n#endif\t\t// __PLAT_NGC__\r\n\t\tcontext->m_App->SendMessageTo( MSG_ID_CONNECTION_ACCEPTED, 0, NULL,\r\n\t\t\t\t\t\t\t\t\t   context->m_Conn->GetIP(), context->m_Conn->GetPort(), 0 );\r\n\r\n\t\treturn HANDLER_CONTINUE;\r\n\t}\r\n\telse if( context->m_Conn->IsLocal())\r\n\t{\r\n\t\tmsg_desc.m_Id = MSG_ID_CONNECTION_ACCEPTED;\r\n\t\tmsg_desc.m_Priority = HIGHEST_PRIORITY;\r\n\t\tmsg_desc.m_Queue = QUEUE_IMPORTANT;\r\n\t\tcontext->m_App->EnqueueMessage( context->m_Conn->GetHandle(), &msg_desc );\r\n\r\n\t\treturn HANDLER_CONTINUE;\r\n\t}\r\n\t\r\n\treturn HANDLER_MSG_DONE;\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\t// namespace Net\r\n"
  },
  {
    "path": "Code/Gel/Net/Server/netserv.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNet (OBJ) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tnet.cpp\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/29/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNetwork Manager code\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdlib.h>\r\n#include <string.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/thread.h>\r\n\r\n#include <sys/timer.h>\r\n#include <gel/net/net.h>\r\n#include <gel/net/server/netserv.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Net\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool\tServer::init( void )\r\n{\r\n\tm_Timestamp = 0;\r\n\tm_connected = false;\r\n\tm_max_connections = 0;\r\n\r\n\tif( App::init() == false )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n    \r\n#ifdef __PLAT_XBOX__\r\n\t//DWORD dwStatus = XNetGetEthernetLinkStatus();\r\n\t//if( dwStatus == 0 )\r\n\t//{\r\n\t\t//return false;\r\n\t//}\r\n\r\n\t// Get host XNADDR (asynchronous).\r\n\twhile( XNetGetTitleXnAddr/*XNetGetDebugXnAddr*/( &m_XboxAddr ) == XNET_GET_XNADDR_PENDING )\r\n\t{\r\n\t\t// Can do other work/rendering here ...\r\n\t}\r\n\r\n\t// Create session key and register the session with the SNL.\r\n\tXNetCreateKey( &m_XboxKeyId, &m_XboxKey );\r\n\tXNetRegisterKey( &m_XboxKeyId, &m_XboxKey );\t// != NO_ERROR\t   \r\n#endif\r\n\r\n\tm_Dispatcher.AddHandler( MSG_ID_CONNECTION_REQ, handle_connection_request, \r\n\t\t\t\t\t\t\t mHANDLE_FOREIGN | mHANDLE_LATE, \r\n\t\t\t\t\t\t\t NULL, \r\n\t\t\t\t\t\t\t HIGHEST_PRIORITY );\r\n\tm_Dispatcher.AddHandler( MSG_ID_TIMESTAMP, handle_timestamp, mHANDLE_LATE | mHANDLE_FOREIGN );\r\n\tm_Dispatcher.AddHandler( MSG_ID_DISCONN_REQ, handle_disconn_req,mHANDLE_LATE,\r\n\t\t\t\t\t\t\t\tNULL, HIGHEST_PRIORITY );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tServer::deinit( void )\r\n{\r\n#ifdef USE_ALIASES\r\n\tint i;\r\n\r\n\tfor( i = 0; i < vNUM_ALIASES; i++ )\r\n\t{\r\n\t\tif( m_alias_table[i] )\r\n\t\t{\r\n\t\t\tdelete [] m_alias_table[i];\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tApp::deinit();\r\n\r\n#ifdef __PLAT_XBOX__\r\n\tXNetUnregisterKey( &m_XboxKeyId );\r\n#endif\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/* Server's send function                                         */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tServer::SendEnqueuedMessages( Conn* conn )\r\n{\r\n\tint buf_len;\r\n\tMsgPacketStamp msg;\r\n\tint num_resends;\r\n\tMsgDesc timestamp_msg_desc;\r\n\tbool buffer_full;\r\n\t\r\n\t// Should we send this frame?\r\n\tif(\tShouldSendThisFrame( conn ) == false )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tbuffer_full = false;\r\n\twhile( !buffer_full && MessagesToSend( conn ) && !BandwidthExceeded( conn ))\r\n\t{    \r\n\t\t// Send Latency Tests/Responses if applicable\r\n\t\tif( ( conn->IsRemote()) &&\r\n\t\t\t( conn->IsForeign() == false ) &&\r\n\t\t\t( m_flags.TestMask( App::mDYNAMIC_RESEND )))\r\n\t\t{\r\n\t\t\tMsgDesc msg_desc;\r\n\t\t\tMsgTimestamp latency_msg;\r\n\t\t\tunsigned int cur_time;\r\n\t\r\n\t\t\tcur_time = m_Timestamp;\r\n\t\t\tlatency_msg.m_Timestamp = cur_time;\r\n\t\t\t// send out a new latency test, keeping track of the time at which\r\n\t\t\t// we sent it\r\n\t\t\tif(\t( conn->m_latency_test.m_SendTime == 0 ) ||\r\n\t\t\t\t( ( cur_time - conn->m_latency_test.m_SendTime ) > App::MAX_LATENCY ))\r\n\t\t\t{   \r\n\t\t\t\t// If we never got a response, simulate an increased latency\r\n\t\t\t\tif( conn->m_latency_test.m_SendTime > conn->m_latency_test.m_ReceiveTime )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned int latency_value;\r\n\t\r\n\t\t\t\t\tlatency_value = conn->GetAveLatency();\r\n\t\t\t\t\tlatency_value += 100;\r\n\t\r\n\t\t\t\t\tif( latency_value > App::MAX_LATENCY )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tlatency_value = App::MAX_LATENCY;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconn->m_latency_test.InputLatencyValue( latency_value );\r\n\t\t\t\t}\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t\tSignalSema( m_send_semaphore_id );\r\n#endif\r\n\t\t\t\tconn->m_latency_test.m_SendTime = cur_time;\r\n\t\r\n\t\t\t\tmsg_desc.m_Data = &latency_msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( MsgTimestamp );\r\n\t\t\t\tmsg_desc.m_Id = MSG_ID_PING_TEST;\r\n\t\t\t\tEnqueueMessage( conn->GetHandle(), &msg_desc );\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t\tWaitSema( m_send_semaphore_id );\r\n#endif\r\n\t\t\t}\r\n\t\t}\t\r\n    \r\n#ifdef __PLAT_NGPS__\r\n\t\tSignalSema( m_send_semaphore_id );\r\n#endif\r\n\t\r\n\t\tmsg.m_Packetstamp = (unsigned short) conn->m_latest_sent_packet_stamp;\r\n\t\t//msg.m_Handle = conn->GetHandle();\r\n\t\r\n\t\ttimestamp_msg_desc.m_Data = &msg;\r\n\t\ttimestamp_msg_desc.m_Length = sizeof( MsgPacketStamp );\r\n\t\ttimestamp_msg_desc.m_Id = MSG_ID_TIMESTAMP;\r\n\t\ttimestamp_msg_desc.m_Priority = HIGHEST_PRIORITY;\r\n\t\tEnqueueMessage( conn->GetHandle(), &timestamp_msg_desc );\r\n\r\n#ifdef __PLAT_NGPS__\r\n\t\tWaitSema( m_send_semaphore_id );\r\n#endif\r\n\r\n\t\tnum_resends = conn->GetNumResends();\r\n\r\n\t\tif( !BuildMsgStream( conn, QUEUE_DEFAULT ))\r\n\t\t{\r\n\t\t\tbuffer_full = true;\r\n\t\t}\r\n\t\t// First, use up our bandwidth with re-sends or else they might remain un-sent\r\n\t\t// indefinitely, causing a bad backup on the client if he's waiting on \r\n\t\t// one particular sequence\r\n\t\tif( !BuildMsgStream( conn, QUEUE_SEQUENCED, true ))\r\n\t\t{\r\n\t\t\tbuffer_full = true;\r\n\t\t}\r\n\t\tif( !BuildMsgStream( conn, QUEUE_IMPORTANT, true ))\r\n\t\t{\r\n\t\t\tbuffer_full = true;\r\n\t\t}\r\n\t\tif( !BuildMsgStream( conn, QUEUE_SEQUENCED ))\r\n\t\t{\r\n\t\t\tbuffer_full = true;\r\n\t\t}\r\n\t\tif( !BuildMsgStream( conn, QUEUE_IMPORTANT ))\r\n\t\t{\r\n\t\t\tbuffer_full = true;\r\n\t\t}\r\n\r\n\t\t// If we had to resend some messages this frame, affect the latency for this client\r\n\t\t// so that we don't expect so much from their connection.\r\n\t\t// Also, reduce their estimated bandwidth\r\n\t\tif( conn->GetNumResends() > num_resends )\r\n\t\t{\r\n\t\t\tconn->m_latency_test.InputLatencyValue( App::MAX_LATENCY );\r\n\t\t\tconn->SetBandwidth( conn->GetBandwidth() - 500 );\r\n\t\t\t// Make sure that we'll still be able to send at least one large (max-size) packet.\r\n\t\t\t// Otherwise, we might get deadlocked.\r\n\t\t\tif( conn->GetBandwidth() < ( MAX_UDP_PACKET_SIZE + vUDP_PACKET_OVERHEAD ))\r\n\t\t\t{\r\n\t\t\t\tconn->SetBandwidth( MAX_UDP_PACKET_SIZE + vUDP_PACKET_OVERHEAD );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tbuf_len = conn->m_write_ptr - conn->m_write_buffer;\r\n\t\t// If there is data to send\r\n\t\tif( ( buf_len > 0 ) &&\r\n\t\t\t( conn->IsRemote()))\r\n\t\t{\r\n#ifdef NET_DEBUG_MESSAGES\r\n\t\t\t/*Dbg_Printf( \"(%d) Conn %d: Sending pstamp %d at time %d\\n\", \r\n\t\t\t\t\t\t\tm_FrameCounter, \r\n\t\t\t\t\t\t\tconn->GetHandle(),\r\n\t\t\t\t\t\t\tconn->m_latest_sent_packet_stamp,\r\n\t\t\t\t\t\t\tm_Timestamp );*/\r\n#endif\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\tif ( SendTo( conn->GetIP(), conn->GetPort(), conn->m_write_buffer, buf_len, 0 ))\r\n\t\t\t{\r\n\t\t\t\tm_TotalBytesOut += buf_len;\r\n\t\t\t\tconn->GetOutboundMetrics()->AddPacket( buf_len + vUDP_PACKET_OVERHEAD, m_Timestamp );\r\n\t\t\t\tconn->SetForceSendThisFrame( false );\r\n\t\t\t\tconn->m_last_send_time = m_Timestamp;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// If it didn't send the messages properly, flag them for resend next frame\r\n\t\t\t\tconn->FlagMessagesForResending( conn->m_latest_sent_packet_stamp );\r\n\t\t\t\tconn->m_write_ptr = conn->m_write_buffer;\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tconn->m_write_ptr = conn->m_write_buffer;\t\t\r\n\t\t}\r\n\r\n\t\tconn->m_latest_sent_packet_stamp++;\r\n\t}\r\n\r\n\t// If we're successfully sending data at/near the connection's estimated max bandwidth and there\r\n\t// are no problems, try ramping up the estimated bandwidth for this connection\r\n\tif( BandwidthExceeded( conn ) && ( conn->GetNumResends() == 0 ))\r\n\t{\r\n\t\tconn->SetBandwidth( conn->GetBandwidth() + 1000 );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Server's Receive function                                      */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tServer::ReceiveData( void )\r\n{\r\n\tConn *conn;\r\n\tstruct sockaddr from_address;\r\n\tstruct sockaddr_in *client_address;\r\n\tint num_bytes, actual_data_len;\r\n    \r\n#ifdef __PLAT_NGC__\r\n\tfrom_address.len = sizeof( sockaddr );\r\n#else\r\n\tint addr_len = sizeof( from_address );\r\n#endif\r\n\r\n\t// Local servers (i.e. non-network play) never really receive. Their data is automatically \r\n\t// \"received\" when the local client writes its data into the server's receive buffer transparently\r\n\tif( IsLocal())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tdo\r\n\t{\r\n\t\tnum_bytes = recvfrom( m_socket, m_in_packet_buffer, \r\n\t\t\tManager::vMAX_PACKET_SIZE, 0, &from_address, &addr_len );\r\n\t\tif ( num_bytes < 0 )// == SOCKET_ERROR ) \r\n\t\t{\r\n#if defined( __PLAT_WN32__ ) || defined( __PLAT_XBOX__ )\r\n\t\t\tif( WSAGetLastError() != WSAEWOULDBLOCK )\r\n#else\r\n#ifdef __PLAT_NGPS__\r\n\t\t\tif( sn_errno( m_socket ) != EWOULDBLOCK )\r\n#else\r\n#ifdef __PLAT_NGC__\r\n\t\t\tif( num_bytes != SO_EWOULDBLOCK )\r\n#endif\r\n#endif\r\n#endif\r\n\t\t\t{\r\n#ifdef NET_DEBUG_MESSAGES\r\n\t\t\t\tDbg_Printf( \"Server Receive Error: \" );\r\n\t\t\t\tReportError();\r\n#endif\r\n\t\t\t}\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\telse\r\n\t\t{   \r\n#ifdef __PLAT_NGPS__\r\n\t\t\tWaitSema( m_receive_semaphore_id );\r\n#endif\t// __PLAT_NGPS__\r\n\t\t\tm_TotalBytesIn += num_bytes;\r\n\t\t\tif( m_flags & App::mSECURE )\r\n\t\t\t{\r\n\t\t\t\tactual_data_len = num_bytes - sizeof( unsigned short );\t// subtract size of CRC\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tactual_data_len = num_bytes;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tclient_address = (struct sockaddr_in*) &from_address;\r\n\t\t\t//Dbg_Printf( \"**** Received data from client 0x%x : %d, addr_len : %d\\n\", client_address->sin_addr.s_addr,\r\n\t\t\t\t\t\t//client_address->sin_port, addr_len );\r\n\t\t\tconn = GetConnectionByAddress( client_address->sin_addr.s_addr, \r\n\t\t\t\t\t\t\t\t\t\t\tntohs( client_address->sin_port ));\r\n\t\t\tif( conn )\r\n\t\t\t{\r\n\t\t\t\tif( conn->IsValid() || (( m_flags & App::mSECURE ) == 0 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tif( ( conn->m_read_ptr + actual_data_len ) < ( conn->m_read_buffer + Conn::vREAD_BUFFER_LENGTH ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( !validate_and_copy_stream( m_in_packet_buffer, conn->m_read_ptr, num_bytes ))\r\n\t\t\t\t\t\t{\r\n\t#ifdef __PLAT_NGPS__\r\n\t\t\t\t\t\t\tSignalSema( m_receive_semaphore_id );\r\n\t#endif\t// __PLAT_NGPS__\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t// If the game would like to handle this foreign data, allow it to do so now\r\n\t\t\t\t\t\t\tif( m_foreign_handler )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tm_foreign_handler( conn->m_read_ptr, num_bytes, &from_address );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n                        \r\n\t\t\t\t\t\tconn->m_read_ptr += actual_data_len;\r\n\t\t\t\t\t\tconn->GetInboundMetrics()->AddPacket( num_bytes + vUDP_PACKET_OVERHEAD, m_Timestamp );\r\n\t\t\t\t\t\tconn->m_last_comm_time = Tmr::GetTime();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tConn* foreign_conn;\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t// Foreign connection. Create temporary connection to process this foreign message\r\n\t\t\t\tforeign_conn = NewConnection( client_address->sin_addr.s_addr, \r\n\t\t\t\t\t\t\t\t\t\t\t  ntohs( client_address->sin_port ), \r\n\t\t\t\t\t\t\t\t\t\t\t  Conn::mREMOTE |\r\n\t\t\t\t\t\t\t\t\t\t\t  Conn::mFOREIGN );\r\n\r\n\t\t\t\tif( foreign_conn )\r\n\t\t\t\t{\r\n\t\t\t\t\tforeign_conn->m_app = this;\r\n\t\t\t\t\tif( !validate_and_copy_stream( m_in_packet_buffer, foreign_conn->m_read_ptr, num_bytes ))\r\n\t\t\t\t\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t\t\t\tSignalSema( m_receive_semaphore_id );\r\n#endif\t// __PLAT_NGPS__\r\n\t\t\t\t\t\t// If the game would like to handle this foreign data, allow it to do so now\r\n\t\t\t\t\t\tif( m_foreign_handler )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tm_foreign_handler( m_in_packet_buffer, num_bytes, &from_address );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tdelete foreign_conn;\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tforeign_conn->m_read_ptr = foreign_conn->m_read_buffer + actual_data_len;\r\n\t\t\t\t\tforeign_conn->Invalidate();\r\n\t\t\t\t}\r\n\t\t\t}\r\n#ifdef __PLAT_NGPS__\r\n\t\t\tSignalSema( m_receive_semaphore_id );\r\n#endif\t// __PLAT_NGPS__\r\n\t\t}       \r\n\t} while( num_bytes > 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef USE_ALIASES\r\n\r\nvoid\tServer::AllocateAliasTables( void )\r\n{\r\n\tint i;\r\n\r\n\t\r\n    \r\n\tDbg_Assert( m_max_connections > 0 );\r\n\r\n\tfor( i = 0; i < vNUM_ALIASES; i++ )\r\n\t{\r\n\t\tm_alias_table[i] = new AliasEntry[ m_max_connections ];\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tServer::ClearAliasTables( void )\r\n{\r\n\t\r\n\r\n\tint i, j;\r\n\r\n\tfor( i = 0; i < m_max_connections; i++ )\r\n\t{\r\n\t\tfor( j = 0; j < vNUM_ALIASES; j++ )\r\n\t\t{\r\n\t\t\tm_alias_table[j][i].m_Id = ~0;\r\n\t\t\tm_alias_table[j][i].m_Expiration = -1;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tServer::ClearAliasTable( int handle )\r\n{\r\n\t\r\n\r\n\tint i;\r\n\r\n\tfor( i = 0; i < vNUM_ALIASES; i++ )\r\n\t{\r\n\t\tm_alias_table[i][handle].m_Id = 0;\r\n\t\tm_alias_table[i][handle].m_Expiration = -1;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nunsigned char\tServer::GetObjectAlias( int handle, int obj_id, int cur_time )\r\n{\r\n\tint hash, i;\r\n\tbool quit;\r\n\r\n\thash = obj_id & 0xff;\t// mask off all but lowest byte and use as a hash into the table\r\n\thash %= vNUM_ALIASES;\r\n\tquit = false;\r\n\ti = hash;\r\n\tdo\r\n\t{\r\n\t\tif( m_alias_table[i][handle].m_Id == obj_id )\r\n\t\t{\r\n\t\t\tif(\t( m_alias_table[i][handle].m_Expiration == -1 ) ||\r\n\t\t\t\t( cur_time > m_alias_table[i][handle].m_Expiration ))\r\n\t\t\t{   \r\n\t\t\t\treturn (unsigned char) vNO_ALIAS;\r\n\t\t\t}\r\n\t\t\treturn (unsigned char) i;\r\n\t\t}\r\n\t\t\r\n\t\ti = ( i + 1 ) % vNUM_ALIASES;\r\n\t\tif( i == hash )\t// complete revolution\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t} while( !quit );\r\n    \r\n\treturn (unsigned char) vNO_ALIAS;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tServer::SetObjectAlias( int handle, unsigned char alias, int obj_id, int expiration )\r\n{\r\n\tm_alias_table[alias][handle].m_Id = obj_id;\r\n\tm_alias_table[alias][handle].m_Expiration = expiration;\r\n}\r\n\r\n#endif // USE_ALIASES\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nServer::Server( int flags )\r\n: App( flags )\r\n{\r\n\tm_send_network_data_task = new Tsk::Task< App > ( send_network_data, *this, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_SERVER_SEND_NETWORK_DATA );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\t// namespace Net\r\n"
  },
  {
    "path": "Code/Gel/Net/Server/netserv.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNET  (Net)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/net.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t01/29/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __NETSERV_H__\r\n#define __NETSERV_H__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gel/net/net.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Net\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Server : public App\r\n{\r\n\tfriend class Manager;\t\r\npublic:\r\n\t\t\tServer( int flags = 0 );\r\n\r\n\tvoid\tReceiveData( void );\t\r\n\tvoid\tSendEnqueuedMessages( Conn* conn );\r\n\t\t\r\n#ifdef USE_ALIASES\r\n\t// Alias Functionality\r\n\tvoid\tAllocateAliasTables( void );\r\n\tvoid\tClearAliasTables( void );\r\n\tvoid\tClearAliasTable( int handle );\r\n\tunsigned char\tGetObjectAlias( int handle, int obj_id, int cur_time );\r\n\tvoid\tSetObjectAlias( int handle, unsigned char alias, int obj_id, int expiration );\r\n\r\nprivate:\r\n\tAliasEntry*\tm_alias_table[vNUM_ALIASES];\r\n#endif\r\n\r\nprivate:\r\n\tbool\tinit( void );\r\n\tvoid\tdeinit( void );\r\n    \r\n\tstatic\tMsgHandlerCode\thandle_timestamp;\t\t\r\n\tstatic\tMsgHandlerCode\thandle_disconn_req;\r\n\r\n\tAliasEntry*\tm_alias_table[vNUM_ALIASES];\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\t// namespace Net\r\n\r\n#endif // __NETSERV_H__"
  },
  {
    "path": "Code/Gel/Net/net.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNet (OBJ) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tnet.cpp\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/29/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNetwork Manager code\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gel/net/net.h>\r\n\r\n#include <core/defines.h>\r\n\r\n#include <sys/timer.h>\r\n#include <sys/config/config.h>\r\n#include <sys/sioman.h>\r\n#include <sys/file/filesys.h>\r\n\r\n#include <stdlib.h>\r\n#include <string.h>\r\n\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n\r\n#ifndef __PLAT_WN32__\r\n#include <gel/music/music.h>\r\n#endif\r\n\r\n#ifdef __PLAT_XBOX__\r\n//#include <xonline.h>\r\n#include <winsockx.h>\r\n#endif\r\n\r\n#include <gel/mainloop.h>\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\n#include <sifdev.h>\r\n#include <libcdvd.h>\r\n\r\n#endif\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#define USE_DECI2\r\n\r\n#define DEFAULT_SNPS2_SUB_MSK\t\"255.255.255.0\"\r\n#define DEFAULT_SNPS2_GATEWAY\t\"192.168.0.1\"\r\n\r\nconst char  spduartArgs[]   = \"-nogci\\0dial=cdrom0:\\\\IOP\\\\DIAL_SPD.CNF;1\";\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Net\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefineSingletonClass( Manager, \"Network Manager\" )\r\n\r\n#ifdef __PLAT_NGPS__\r\n/* Set up the following list with one or more suitable DNS servers   */\r\n\r\n/*static const sn_char* dns_servers[] =\r\n{   \r\n\t    \"205.147.0.100\",\r\n\t\t\"205.147.0.102\",\r\n\t\t\"\"                // List is terminated by null string\r\n};*/\r\nstatic sn_char custom_built_script[SN_MAX_SCRIPT_LINES][SN_MAX_SCRIPT_LEN+1];\r\nstatic const char *s_custom_isp_script[] =\r\n    {\r\n        \"input 30 ogin:\",      /* Line 0 */\r\n        \"output \",             /* Line 1 */\r\n        \"input 10 word:\",      /* Line 2 */\r\n        \"output \",             /* Line 3 */\r\n        \"input 10 ing PPP\",    /* Line 4 */\r\n        \"\"                     /* script is terminated with null string     */\r\n    };\r\n\r\n#define vCUSTOM_USERNAME_LINE  1\r\n#define vCUSTOM_PASSWORD_LINE  3\r\n\r\nstatic bool s_cancel_dialup_conn;\r\nstatic int  s_conn_semaphore;\r\n#endif // __PLAT_NGPS__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\n#define vPOWEROFF_STACK_SIZE\t\t(2 * 1024)\r\n\r\nstatic u_char s_poweroff_stack[vPOWEROFF_STACK_SIZE] __attribute__ ((aligned(16)));\r\n\r\n/******************************************************************/\r\n/* The thread which waits for\t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void s_power_off_thread(void *arg) \r\n{\r\n\tint sid = (int)arg;\r\n\tint stat;\r\n\twhile( 1 ) \r\n\t{\r\n\t\tWaitSema(sid);\r\n\t\t// dev9 power off, need to power off PS2\r\n\t\t//while( sceDevctl(\"dev9x:\", DDIOC_OFF, NULL, 0, NULL, 0 ) < 0 );\r\n\t\twhile( sceDevctl(\"dev9x:\", DDIOC_OFF, NULL, 0, NULL, 0 ) < 0 );\r\n\t\t// PS2 power off\r\n\t\twhile( !sceCdPowerOff( &stat ) || stat );\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void s_power_off_handler(void *arg) \r\n{\r\n\tint sid = (int)arg;\r\n    iSignalSema(sid);\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void s_prepare_power_off(void) \r\n{\r\n    struct ThreadParam tparam;\r\n    struct SemaParam   sparam;\r\n    int tid, sid;\r\n\r\n\tsparam.initCount = 0;\r\n    sparam.maxCount  = 1;\r\n    sparam.option    = 0;\r\n    sid = CreateSema(&sparam);\r\n\r\n    tparam.stackSize = vPOWEROFF_STACK_SIZE;\r\n    tparam.gpReg = &_gp;\r\n    tparam.entry = s_power_off_thread;\r\n    tparam.stack = (void *) s_poweroff_stack;\r\n    tparam.initPriority = 1;\r\n    tid = CreateThread( &tparam );\r\n    StartThread( tid, (void *) sid );\r\n\r\n    sceCdPOffCallback( s_power_off_handler, (void *) sid );\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic sn_int32 set_host_name( sn_char* host_name )\r\n{\r\n    sndev_set_dhost_type optval;\r\n    sn_int32 host_size, r;\r\n\r\n\t\r\n\r\n\tDbg_Assert( host_name );\r\n\r\n    host_size = strlen(host_name) + 1;\r\n\r\n    // Check host_name isn't too big\r\n    if (host_size > (sn_int32) sizeof(optval.host))\r\n    {\r\n        Dbg_Printf(\"EE:set_host_name():error host_name too big\\n\");\r\n        return -1;\r\n    }\r\n\r\n    // I'm going to fill optval with zeros to start with, not strictly\r\n    // necessary but this is only an example.\r\n    memset(&optval,0,sizeof(optval));\r\n\r\n    // Fill in the optval structure\r\n    optval.flags = 0;        // Steve, you could set one of these two\r\n                             // values SN_DFLAG_EXCL_DIS or\r\n                             // SN_DFLAG_EXCL_REQ in the flags to\r\n                             // *exclude* either the discovery or\r\n                             // request message from the operation with\r\n                             // flags set to zero the option will be\r\n                             // applied to both messages\r\n\r\n\tif( host_name[0] == '\\0' )\r\n\t{\r\n\t\tDbg_Printf( \"Clearing Host Name Option\\n\" );\r\n\t\toptval.clear_option = 1; // Steve, you would set this to 1 if you\r\n\t\t\t\t\t\t\t\t // wanted to remove the host name\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Printf( \"Setting Host Name Option to %s\\n\", host_name );\r\n\t\toptval.clear_option = 0;\r\n\t}\r\n    \r\n\r\n    optval.include_null = 0; // Steve, if you wanted the null terminator\r\n                             // included in the host name that's sent in\r\n                             // the DHCP msg you would set this to 1\r\n\r\n    optval.reserved = 0;    // Must be 0\r\n\r\n    memcpy(optval.host, host_name, host_size);\r\n\r\n    // Send the option to the IOP\r\n\r\n    r = sndev_set_options(0, SN_DEV_SET_DHOST, &optval, sizeof(optval));\r\n\r\n    if (r != 0)\r\n    {\r\n        Dbg_Printf(\"EE:sndev_set_options():error %d\\n\",r);\r\n        return -1;\r\n    }\r\n\r\n    return 0;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::stop_stack( void )\r\n{\r\n\t\r\n\r\n\tint result, stack_state;\r\n\r\n\tDbg_Printf( \"EE:Stopping the TCP/IP stack\\n\" );\r\n\t\r\n\tresult = sn_stack_state(SN_STACK_STATE_STOP, &stack_state);\r\n\r\n\tif( result != 0 )\r\n\t{\r\n\t\tDbg_Printf( \"EE:sn_stack_sate() failed %d\\n\", result );\r\n\t\tSetError( vRES_ERROR_GENERAL );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tDbg_Printf( \"EE:Stack Stopped\\n\" );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::start_stack( void )\r\n{\r\n\tsn_int32\tresult, stack_state;\r\n\tTmr::Time \tstart_time;\r\n\r\n\t\r\n\r\n\t// Start the stack\r\n    Dbg_Printf(\"EE:Starting the TCP/IP stack\\n\");\r\n\r\n    result = sn_stack_state( SN_STACK_STATE_START, &stack_state );\r\n    \r\n    if( result != 0 )\r\n    {\r\n        Dbg_Printf( \"EE:sn_stack_sate() failed %d\\n\", result );\r\n\t\tSetError( vRES_ERROR_GENERAL );\r\n        return false;\r\n    }\r\n\r\n\tDbg_Printf( \"EE:Stack Started\\n\" );\r\n\tif(( GetConnectionType() == vCONN_TYPE_MODEM ) ||\r\n\t   ( GetConnectionType() == vCONN_TYPE_PPPOE ))\r\n\t{\r\n\t\tint modem_state, prev_modem_state;\r\n\t\tTmr::Time start_time;\r\n\r\n        modem_state      = -1; // Invalid\r\n\t\tprev_modem_state = -2; // Ivalid and != modem_state\r\n\r\n\t\tstart_time = Tmr::GetTime();\r\n\t\tDbg_Printf( \"EE:Calling snmdm_get_state() - until modem ready\\n\" );\r\n\t\twhile( modem_state != SN_MODEM_READY )\r\n\t\t{\r\n\t\t\tresult = snmdm_get_state( &modem_state );\r\n\t\r\n\t\t\tif (result != 0)\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf(\"EE:snmdm_get_state() failed %d\\n\", result);\r\n\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\r\n\t\t\tif (modem_state == prev_modem_state)\r\n\t\t\t{\r\n\t\t\t\tsn_delay(10);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tprev_modem_state = modem_state;\r\n\t\t\t\tDbg_Printf(\"  Modem state = %d %s\\n\", modem_state, sntc_str_modem_state( modem_state ));\r\n\t\t\t}\r\n\r\n\t\t\t// After 5 seconds, time out and say there was no dialtone\r\n\t\t\tif(( Tmr::GetTime() - start_time ) > Tmr::Seconds( 10 ))\r\n\t\t\t{\r\n\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tDbg_Printf( \"EE:Ready\\n\" );\r\n\t}\r\n\r\n\r\n    // Wait for the stack to come up\r\n    Dbg_Printf( \"EE:Waiting for socket API to be ready\\n\" );\r\n\tstart_time = Tmr::GetTime();\r\n    while( sn_socket_api_ready() == SN_FALSE )\r\n\t{\r\n\t\t// Delay to avoid hogging the processor\r\n\t\tsn_delay( 500 );\r\n\t\tif(( Tmr::GetTime() - start_time ) > Tmr::Seconds( 10 ))\r\n\t\t{\r\n\t\t\tDbg_Printf( \"EE:Timed out waiting for socket API to be ready\\n\" );\r\n\t\t\treturn false;\r\n\t\t}\r\n    }\r\n\r\n\tif( ShouldUseDHCP())\r\n\t{\r\n\t\tstruct hostent* hentp       = NULL;\r\n\t\tsn_bool         got_ip_addr = SN_FALSE;\r\n\t\tstruct in_addr  ip_addr;\r\n\t\r\n\t\tDbg_Printf( \"EE:Waiting for DHCP server to supply IP addr etc\\n\" );\r\n\t\tstart_time = Tmr::GetTime();\r\n\t\tdo\r\n\t\t{\r\n\t\t\t// A way of getting the local IP address\r\n\t\t\thentp = gethostbyname(LOCAL_NAME);\r\n\t\r\n\t\t\tif(( hentp != NULL ) && ( hentp->h_addr_list[0] != NULL ))\r\n\t\t\t{\r\n\t\t\t\t// Read the IP address from the hostent struct\r\n\t\t\t\tmemcpy( &ip_addr,hentp->h_addr_list[0], sizeof( ip_addr ));\r\n\t\r\n\t\t\t\tif( ip_addr.s_addr != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tgot_ip_addr = SN_TRUE;\r\n\t\t\t\t\tDbg_Printf( \"DHCP allocated IP addr %s\\n\", inet_ntoa( ip_addr ));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\r\n\t\t\t// Delay to avoid hogging the processor\r\n\t\t\tif( got_ip_addr == SN_FALSE )\r\n\t\t\t{\r\n\t\t\t\tsn_delay(500);\r\n\t\t\t}\r\n\t\t\tif(( Tmr::GetTime() - start_time ) > Tmr::Seconds( 10 ))\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"EE:Timed out waiting for DHCP response\\n\" );\r\n\t\t\t\tSetError( vRES_ERROR_DHCP );\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t} while( got_ip_addr == SN_FALSE );\r\n\r\n\t\tstrcpy( m_local_ip, inet_ntoa( ip_addr ));\r\n    }\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::setup_ethernet_params( void )\r\n{\r\n\tsndev_set_ether_ip_type params;\r\n\tint result;\r\n\r\n    if( ShouldUseDHCP())\r\n    {\r\n\t\tDbg_Printf( \"\\n\\n\\n*********************** USING DHCP ******************* \\n\\n\\n\" );\r\n        memset( &params,0, sizeof( params ));\r\n    }\r\n    else\r\n    {   \r\n        inet_aton( GetLocalIP(), (struct in_addr*) &params.ip_addr );\r\n\t\tDbg_Printf( \"======================== Ip is %d : %d\\n\", params.ip_addr, htonl( params.ip_addr ));\r\n        inet_aton( GetSubnetMask(), (struct in_addr*) &params.sub_mask );\r\n        inet_aton( GetGateway(), (struct in_addr*) &params.gateway );\r\n\t}\r\n\r\n    result = sndev_set_options( 0, SN_DEV_SET_ETHER_IP, &params, sizeof(params));\r\n\r\n    if( result != 0 )\r\n    {\r\n        Dbg_Printf( \"EE:Error sndev_set_options() returned %d\\n\", result );\r\n\t\tSetError( vRES_ERROR_GENERAL );\r\n        return false;\r\n    }\r\n\r\n\tif( ShouldUseDHCP())\r\n\t{\r\n\t\tresult = set_host_name( m_host_name );\r\n\t\tif( result != 0 )\r\n\t\t{   \r\n\t\t\tSetError( vRES_ERROR_GENERAL );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::initialize_device( void )\r\n{\r\n\tsn_int32            result;\r\n    sn_int32            device_type;\r\n    sn_int16            idVendor;\r\n    sn_int16            idProduct;\r\n    sn_bool             first_time;\r\n\tTmr::Time \t\t\tstart_time;\r\n\tTmr::Time\t\t\ttimeout;\r\n\r\n    // Initialise the socket API, if fails print error and return\r\n    Dbg_Printf( \"EE:Initialising socket API\\n\" );\r\n\r\n    result = sockAPIinit( 6 );\r\n    if(\t( result != 0 ) &&\r\n\t\t( result != SN_EALRDYINIT ))\r\n    {\r\n        Dbg_Printf( \"EE:sockAPIinit() failed %d\\n\", result );\r\n\t\tSetError( vRES_ERROR_GENERAL );\r\n        return false;\r\n    }\r\n    \r\n    // If we've already init'd the sockets API, don't re-register this thread\r\n\t// just let it run through the rest of setup\r\n\tif( result != SN_EALRDYINIT )\r\n\t{\r\n\t\t// Register this thread with the socket API\r\n\t\tresult = sockAPIregthr();\r\n\t\r\n\t\tif (result != 0)\r\n\t\t{\r\n\t\t\tDbg_Printf( \"EE:sockAPIregthr() failed %d\\n\", result );\r\n\t\t\tSetError( vRES_ERROR_GENERAL );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n    // Now wait for DECI2 'device' to be 'attached'\r\n    device_type = SN_DEV_TYPE_NONE;\r\n    first_time  = SN_TRUE;\r\n\tstart_time = Tmr::GetTime();\r\n\t// It takes longer to init the sony modem\r\n\tif( GetDeviceType() == vDEV_TYPE_SONY_MODEM )\r\n\t{\r\n\t\ttimeout = Tmr::Seconds( 15 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttimeout = Tmr::Seconds( 10 );\r\n\t}\r\n\t\r\n    while( device_type == SN_DEV_TYPE_NONE )\r\n    {\r\n        result = sndev_get_attached( 0, &device_type, &idVendor, &idProduct );\r\n\r\n        if( result != 0 )\r\n        {\r\n            Dbg_Printf( \"EE:sndev_get_attached() failed %d\\n\", result );\r\n\t\t\tSetError( vRES_ERROR_GENERAL );\r\n            return false;\r\n        }\r\n\r\n        if( device_type == SN_DEV_TYPE_NONE )\r\n        {\r\n            if( first_time == SN_TRUE )\r\n            {\r\n                first_time = SN_FALSE;\r\n                Dbg_Printf( \"EE:Waiting for network device to be attached ...\\n\" );\r\n            }\r\n            sn_delay( 10 );\r\n        }\r\n\r\n\t\tif(( Tmr::GetTime() - start_time ) > timeout )\r\n\t\t{\r\n\t\t\tDbg_Printf( \"EE:Timed out waiting for network device to be attached\\n\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n    }\r\n\r\n\tswitch( device_type )\r\n\t{\r\n\t\tcase SN_DEV_TYPE_DECI2:\r\n\t\t\tDbg_Printf( \"Using DECI-2 ethernet emulation\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase SN_DEV_TYPE_USB_MODEM:\r\n\t\t\tDbg_Printf(\"EE:USB-Modem Attached (idVendor=0x%04X idProduct=0x%04X)\\n\",\r\n\t\t\t\t\t((int)idVendor)  & 0xFFFF,\r\n\t\t\t\t\t((int)idProduct) & 0xFFFF);\r\n\t\t\tbreak;\r\n\t\tcase SN_DEV_TYPE_USB_ETHER:\r\n\t\t\tDbg_Printf(\"EE:USB-Ethernet Attached (idVendor=0x%04X idProduct=0x%04X)\\n\",\r\n\t\t\t\t\t((int)idVendor)  & 0xFFFF,\r\n\t\t\t\t\t((int)idProduct) & 0xFFFF);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tif( idVendor == 0 )\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"Unknown Device %d\\n\", device_type );\r\n\t\t\t\tSetError( vRES_ERROR_UNKNOWN_DEVICE );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( idVendor == 1 );\r\n\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_HOT );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n    \r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::sn_stack_setup( void )\r\n{\r\n\t// Set up the list of DNS servers\r\n\tchar* dns_servers[3];\r\n\tint result, i;\r\n\tsn_int32\tstack_state;\r\n\t\t\r\n\t\r\n\r\n\tsn_stack_state( SN_STACK_STATE_READ, &stack_state );\r\n\tif( stack_state == SN_STACK_STATE_START )\r\n\t{\r\n\t\tif( stop_stack() == false )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tif( GetConnectionType() == vCONN_TYPE_ETHERNET ) \r\n\t{\r\n\t\tif(( setup_ethernet_params() == false ))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\tfor( i = 0; i < 3; i++ )\r\n\t{\r\n\t\tdns_servers[i] = m_dns_servers[i];\r\n\t\tDbg_Printf( \"DNS Server %d is %s\\n\", i, dns_servers[i] );\r\n\t}\r\n\tresult = sntc_set_dns_server_list((const sn_char**) dns_servers);\r\n\r\n\tif( result != 0 )\r\n\t{\r\n\t\tDbg_Printf( \"EE:sntc_set_dns_server_list() failed %d\\n\", result );\r\n\t\tSetError( vRES_ERROR_GENERAL );\r\n\t\t\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif( GetConnectionType() == vCONN_TYPE_PPPOE )\r\n\t{\r\n\t\tsndev_set_pppoe_opt_type pppoe;\r\n\r\n\t\t// Enable PPPoE\r\n\t\tpppoe.flags = 1;\r\n\r\n\t\tDbg_Printf( \"Enabling PPPoE\\n\" );\r\n\t\tresult = sndev_set_options( 0, SN_DEV_SET_PPPOE_OPT, &pppoe, sizeof(pppoe));\r\n\r\n\t\tDbg_Printf( \"EE:sndev_set_options(pppoe) returned %d\\n\", result );\r\n\t}\r\n\tif(( GetConnectionType() == vCONN_TYPE_MODEM ) ||\r\n\t   ( GetConnectionType() == vCONN_TYPE_PPPOE ))\r\n\t{\r\n\t\t// Now, we have a valid modem. Try to initialize\r\n\t\t//result = snmdm_set_mdm_init( \"AT&F S0=0\" );\r\n\t\tresult = snmdm_set_mdm_init( \"AT&F S0=0 W2\" );\r\n\t\r\n\t\tif( result != 0 )\r\n\t\t{\r\n\t\t\tDbg_Printf( \"EE:snmdm_set_mdm_init() failed %d\\n\", result );\r\n\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tDbg_Printf( \"EE:snmdm_set_mdm_init() worked ok\\n\" );\r\n\t}\r\n\r\n    if( start_stack() == false )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tm_options_changed = false;\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic sn_int32 custom_construct_script( sn_int32 isp_type, sn_char* user_name, \r\n\t\t\t\t\t\t\t\t\t\t sn_char* password)\r\n{\r\n    sn_int32  line_index;\r\n    sn_bool   copy_done;\r\n\r\n    copy_done  = SN_FALSE;\r\n    line_index = 0;\r\n\r\n    // Copy the preset script to custom_built_script\r\n    while( copy_done == SN_FALSE )\r\n    {\r\n        // Copy this line of the script\r\n        strcpy( custom_built_script[line_index], s_custom_isp_script[line_index] );\r\n\r\n        // If this line was a null string then finished copy\r\n        if( s_custom_isp_script[line_index][0] == 0 )\r\n\t\t{\r\n             copy_done = SN_TRUE;\r\n\t\t}\r\n        else\r\n\t\t{\r\n\t\t\tline_index++;\r\n\t\t}\r\n    }\r\n\r\n    sn_strcat( custom_built_script[vCUSTOM_USERNAME_LINE], user_name );\r\n    sn_strcat( custom_built_script[vCUSTOM_USERNAME_LINE], \"\\\\r\" );\r\n\r\n    // Concatenate password\\r on to line index CUSTOM_PASSWORD_LINE\r\n    sn_strcat( custom_built_script[vCUSTOM_PASSWORD_LINE], password );\r\n    sn_strcat( custom_built_script[vCUSTOM_PASSWORD_LINE], \"\\\\r\" );\r\n\r\n    return 0; // Success\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nsn_int32 custom_connect_modem(\tsn_char*               phone_no,\r\n\t\t\t\t\t\t\t\tsn_int32               isp_type,\r\n\t\t\t\t\t\t\t\tsn_char*               user_name,\r\n\t\t\t\t\t\t\t\tsn_char*               password,\r\n\t\t\t\t\t\t\t\tsn_int32               timeout_secs,\r\n\t\t\t\t\t\t\t\tsntc_mdmstate_callback callback )\r\n{\r\n    sn_int32           result;\r\n    sn_int32           modem_state;\r\n    sn_bool            done_script;\r\n    sn_int32           script_index;\r\n    sn_int32           prev_modem_state;\r\n    sn_bool            connect_started;\r\n    sn_int32           timeout_ms;\r\n    sn_int32           connect_err;\r\n    \r\n    result = snmdm_set_phone_no( phone_no );\r\n\r\n    // Check that the above function call worked ok\r\n    if( result != 0 )\r\n    {\r\n\t\tDbg_Printf( \"Failed to set phone number: %d\\n\", result );\r\n        return SNTC_ERR_MDMAPI;\r\n    }\r\n\r\n    // Construct the log in script file (in custom_built_script)\r\n    result = custom_construct_script( isp_type, user_name, password );\r\n    if( result != 0 )\r\n    {\r\n        Dbg_Printf( \"Failed to build login script: %d\\n\", result );\r\n        return SNTC_ERR_BSCRIPT;\r\n    }\r\n\r\n    // Store the log in script file via the modem API\r\n    // Send a null string first, this resets the script write ptr to 0,\r\n    // it should already be at 0, but just being defensive.\r\n    result = snmdm_set_script(\"\");\r\n    if( result != 0 )\r\n    {\r\n\t\tDbg_Printf( \"snmdm_set_script() failed: %d\\n\", result );\r\n        return SNTC_ERR_MDMAPI;\r\n    }\r\n\r\n    // Now send the script file to the modem API\r\n    script_index = 0;\r\n    done_script  = SN_FALSE;\r\n    while( done_script == SN_FALSE )\r\n    {\r\n        result = snmdm_set_script( custom_built_script[ script_index ] );\r\n        if( result != 0 )\r\n        {\r\n\t\t\tDbg_Printf( \"snmdm_set_script() failed: %d\\n\", result );\r\n            return SNTC_ERR_MDMAPI;\r\n        }\r\n\r\n        // Check for null line, which is last line\r\n        if( custom_built_script[script_index][0] == 0 )\r\n\t\t{\r\n\t\t\t done_script = SN_TRUE;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tscript_index++;\r\n\t\t}\r\n    }\r\n\r\n    // Everything is ready, so ask the modem to connect\r\n\tresult = snmdm_connect();\r\n    if( result != 0 )\r\n    {\r\n\t\tDbg_Printf( \"snmdm_connect() failed: %d\\n\", result );\r\n        return SNTC_ERR_MDMAPI;\r\n    }\r\n\r\n    // Now wait for the modem to become connected\r\n    modem_state      = -1; /* Invalid */\r\n    prev_modem_state = -2; /* Ivalid and != modem_state */\r\n    connect_started  = SN_FALSE;\r\n    timeout_ms       = timeout_secs * 1000;\r\n\r\n    while(( modem_state != SN_MODEM_PPP_UP ) &&\r\n\t\t  ( s_cancel_dialup_conn == false ))\r\n    {\r\n\r\n        // Get the current state of the modem link\r\n        result = snmdm_get_state(&modem_state);\r\n        if( result != 0 )\r\n        {\r\n\t\t\tDbg_Printf( \"snmdm_get_state() failed: %d\\n\", result );\r\n            return SNTC_ERR_MDMAPI;\r\n        }\r\n\r\n        // Monitor for modem connection process starting, then if it\r\n        // goes back to ready we know it's failed to connect.\r\n        if( connect_started == SN_FALSE )\r\n        {\r\n            // Any of the following means modem connection started\r\n            if(  (modem_state == SN_MODEM_DIALING)\r\n               ||(modem_state == SN_MODEM_LOGIN)\r\n               ||(modem_state == SN_MODEM_CONNECTED)\r\n               ||(modem_state == SN_MODEM_PPP_UP))\r\n            {\r\n                connect_started = SN_TRUE;\r\n            }\r\n        }\r\n        else\r\n        {\r\n            // Having started the connection, then unless it's in\r\n            // one of the following states it's failed to connect\r\n            if(  (modem_state != SN_MODEM_DIALING)\r\n               &&(modem_state != SN_MODEM_LOGIN)\r\n               &&(modem_state != SN_MODEM_CONNECTED)\r\n               &&(modem_state != SN_MODEM_PPP_UP))\r\n            {\r\n                // Read the reason why the connect failed.\r\n                result = snmdm_get_connect_err( &connect_err );\r\n                if( result != 0 )\r\n                {\r\n\t\t\t\t\tDbg_Printf( \"snmdm_get_connect_err() failed: %d\\n\", result );\r\n                    return SNTC_ERR_MDMAPI;\r\n                }\r\n\r\n                switch( connect_err )\r\n                {\r\n                    case SN_CONERR_BUSY:\r\n                       Dbg_Printf( \"Busy\\n\" );\r\n                       return SNTC_ERR_BUSY;\r\n                    break;\r\n\r\n                    case SN_CONERR_NOCARRIER:\r\n                       Dbg_Printf( \"No carrier\\n\" );\r\n                       return SNTC_ERR_NOCARRIER;\r\n                    break;\r\n\r\n\t\t\t\t\tcase SN_CONERR_NOANSWER:\r\n\t\t\t\t\t\tDbg_Printf( \"No answer\\n\" );\r\n\t\t\t\t\t\treturn SNTC_ERR_NOANSWER;\r\n                    break;\r\n\r\n\t\t\t\t\tcase SN_CONERR_NODIALTONE:\r\n\t\t\t\t\t\tDbg_Printf( \"No dialtone\\n\" );\r\n\t\t\t\t\t\treturn SNTC_ERR_NODIALTONE;\r\n                    break;\r\n\r\n                    default:\r\n                        Dbg_Printf( \"connect started then modem state=sntc_str_modem_state(modem_state)\\n\" );\r\n                        return SNTC_ERR_CONNECT;\r\n                }\r\n            }\r\n        }\r\n\r\n        // Now check whether the modem state has changed since the\r\n        // previous time round this loop, and if so call the user\r\n        // callback function (unless it's NULL), otherwise check\r\n        // for time-out / do a delay\r\n        if( modem_state != prev_modem_state )\r\n        {\r\n            prev_modem_state = modem_state;\r\n            if( callback != NULL )\r\n\t\t\t{\r\n\t\t\t\t(*callback)(modem_state);\r\n\t\t\t}\r\n        }\r\n        else\r\n        {\r\n            if( timeout_ms <= 0 )\r\n            {\r\n\t\t\t\tDbg_Printf( \"Connect timed out in modem state %s\\n\", sntc_str_modem_state(modem_state) );\r\n                return SNTC_ERR_TIMEOUT;\r\n            }\r\n\r\n            sn_delay( 10 );\r\n            timeout_ms -= 10;\r\n        }\r\n    }\r\n\r\n    // If we get to here, the modem has successfully connected\r\n    Dbg_Printf( \"Connected!\\n\" );\r\n    \r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::threaded_modem_conn( void *data )\r\n{\r\n\t\r\n\tManager* man = (Manager *) data;\r\n\tint result;\r\n    \r\n\tDbg_Printf( \"Registering modem thread %d with stack\\n\", GetThreadId());\r\n\t\r\n\tresult = sockAPIregthr();\r\n\tDbg_Assert( result == 0 );\r\n\r\n\tWaitSema( s_conn_semaphore );\r\n\r\n\tDbg_Printf(\"EE:Calling sntc_connect_modem()\\n\");\r\n\r\n\t// Set the script write pointer back to zero\r\n    result = snmdm_set_script(\"\");\r\n\r\n\t// Set up Authentication parameters.\r\n\tsndev_set_chap_type ChapOptions = {0};\r\n\t\r\n    ChapOptions.accept_chap = man->ShouldUseDialupAuthentication();\r\n\tDbg_Printf( \"Setting chap to %d\\n\", ChapOptions.accept_chap );\r\n\tChapOptions.require_chap = 0;\r\n\tstrcpy(ChapOptions.locl_name, man->m_isp_user_name );\r\n\tstrcpy(ChapOptions.locl_secr, man->m_isp_password );\r\n\tstrcpy(ChapOptions.chal_name,\"*\"); // Accept any challenge name\r\n\t\r\n\tDbg_Printf( \"Chap username: %s password: %s\\n\", man->m_isp_user_name, man->m_isp_password );\r\n\tresult = sndev_set_options( 0, SN_DEV_SET_CHAP, &ChapOptions, sizeof(ChapOptions));\r\n\tDbg_Printf( \"EE:sndev_set_options(SN_DEV_SET_CHAP) returned %d\\n\", result );\r\n\r\n\tsndev_set_pap_type PapOptions = {0};\r\n\r\n\tPapOptions.accept_pap = man->ShouldUseDialupAuthentication();\r\n\tDbg_Printf( \"Setting pap to %d\\n\", PapOptions.accept_pap );\r\n\tPapOptions.require_pap = 0;\r\n\tstrcpy(PapOptions.locl_name, man->m_isp_user_name );\r\n\tstrcpy(PapOptions.locl_pass, man->m_isp_password );\r\n\tDbg_Printf( \"Pap username: %s password: %s\\n\", man->m_isp_user_name, man->m_isp_password );\r\n\r\n\tresult = sndev_set_options( 0, SN_DEV_SET_PAP, &PapOptions, sizeof(PapOptions));\r\n\tDbg_Printf( \"EE:sndev_set_options(SN_DEV_SET_PAP) returned %d\\n\", result );\r\n\r\n\tman->m_modem_err = 0;\r\n\tif( man->GetConnectionType() == vCONN_TYPE_MODEM )\r\n\t{   \r\n\t\tDbg_Printf( \"Dialing %s user: %s pass: %s\\n\", man->m_isp_phone_no, man->m_isp_user_name, man->m_isp_password );\r\n\t\tresult = custom_connect_modem\r\n\t\t\t\t ( man->m_isp_phone_no,\t\t\t// phone_no\r\n\t\t\t\t   SNTC_ISP_GENERIC,\t\t// isp_type\r\n\t\t\t\t   man->m_isp_user_name,\t\t\t// user_name\r\n\t\t\t\t   man->m_isp_password,\t\t\t// password\r\n\t\t\t\t   vMODEM_CONNECT_TIMEOUT,\t// timeout_secs\r\n\t\t\t\t   man->conn_modem_state_callback );// callback\r\n\t}\r\n\telse if( man->GetConnectionType() == vCONN_TYPE_PPPOE )\r\n\t{\r\n\t\tresult = custom_connect_modem\r\n\t\t\t\t ( \"\",\t\t\t// phone_no\r\n\t\t\t\t   0,\t\t// isp_type\r\n\t\t\t\t   \"\",\t\t\t// user_name\r\n\t\t\t\t   \"\",\t\t\t// password\r\n\t\t\t\t   vMODEM_CONNECT_TIMEOUT,\t// timeout_secs\r\n\t\t\t\t   man->conn_modem_state_callback );// callback\r\n\t}\r\n\t// Check whether connection succeeded\r\n\tif( result == 0 )\r\n\t{\r\n        sn_int32 result, statval, statlen;\r\n\r\n\t\tstatval = 1234; // so can see it's modified\r\n\t\tstatlen = sizeof(statval);\r\n\r\n        result = sndev_get_status(0, SN_DEV_STAT_BAUD, &statval, &statlen);\r\n        man->m_modem_baud_rate = statval;\r\n\t\t\r\n\t\tman->m_online = true;\r\n\t}\r\n\telse\r\n\t{   \r\n\t\tsntc_disconnect_modem(\tvMODEM_DISCONNECT_TIMEOUT,\t// timeout_secs\r\n\t\t\t\t\t\t\t\tNULL,\t\t// callback\r\n\t\t\t\t\t\t\t\tNULL );\t\t\t\t// error_message\r\n\t\tman->SetModemState( vMODEM_STATE_ERROR );\r\n\t\tman->m_modem_err = result;\r\n\t\tDbg_Printf( \"EE:sntc_connect_modem() failed: %d\\n\", result );\r\n\t\tman->m_online = false;\r\n\t}   \r\n\r\n\tDbg_Printf( \"DeRegistering modem thread %d with stack\\n\", GetThreadId());\r\n\tsockAPIderegthr();\r\n\tSignalSema( s_conn_semaphore );\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::threaded_modem_disconn( void *data )\r\n{\r\n\t\r\n\tManager* man = (Manager *) data;\r\n\tsn_char* err_msg_ptr;\r\n\tbool modem_disconnected;\r\n\tint result;\r\n    \r\n\tDbg_Printf( \"Registering modem thread %d with stack\\n\", GetThreadId());\r\n\t\r\n\tresult = sockAPIregthr();\r\n\tDbg_Assert( result == 0 );\r\n\t\t\r\n\tmodem_disconnected = false;\r\n\tif( man->m_online )\r\n\t{\r\n\t\tDbg_Printf( \"EE:Calling sntc_disconnect_modem()\\n\" );\r\n\t\tresult = sntc_disconnect_modem(\tvMODEM_DISCONNECT_TIMEOUT,\t// timeout_secs\r\n\t\t\t\t\t\t\t\t\t\tdisconn_modem_state_callback,\t\t// callback\r\n\t\t\t\t\t\t\t\t\t\t&err_msg_ptr );\t\t\t\t// error_message\r\n\t\r\n\t\t// Check whether disconnection succeeded\r\n\t\tif (result == 0)\r\n\t\t{\r\n\t\t\tDbg_Printf(\"EE:sntc_disconnect_modem() worked:%s\\n\",err_msg_ptr);\r\n\t\t\tmodem_disconnected = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Printf(\"EE:sntc_disconnect_modem() failed:%s\\n\",err_msg_ptr);\r\n\t\t\tmodem_disconnected = false;\r\n\t\t}\r\n\t}\r\n\r\n\t// If the modem didn't connect and disconnect ok, then reset it\r\n\tif( !modem_disconnected )\r\n\t{\r\n\t\tbool modem_reset;\r\n\r\n\t\tdo\r\n\t\t{\r\n\t\t\tDbg_Printf( \"EE:Calling sntc_reset_modem()\\n\" );\r\n\r\n\t\t\tresult = sntc_reset_modem\r\n\t\t\t\t\t\t(\tvMODEM_RESET_TIMEOUT,\t// timeout_secs\r\n\t\t\t\t\t\t\tdisconn_modem_state_callback,\t// callback\r\n\t\t\t\t\t\t\t&err_msg_ptr );     \t// error_message\r\n\r\n\t\t\t// Check whether reset succeeded\r\n\t\t\tif( result == 0 )\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"EE:sntc_reset_modem() worked:%s\\n\", err_msg_ptr );\r\n\t\t\t\tmodem_reset = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"EE:sntc_reset_modem() failed:%s\\n\", err_msg_ptr );\r\n\t\t\t\tmodem_reset = false;\r\n\t\t\t\t// If their modem is no longer plugged in, just consider it \"hung up\"\r\n\t\t\t\tif( result == SNTC_ERR_NOMODEM )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tsn_delay( 1000 ); // avoid excessive printf if unplugged\r\n\t\t\t}\r\n\t\t} while( !modem_reset );\r\n\t}\r\n\t\r\n\tman->SetModemState( vMODEM_STATE_DISCONNECTED );\r\n\tman->m_online = false;\r\n\r\n\tDbg_Printf( \"DeRegistering modem thread %d with stack\\n\", GetThreadId());\r\n\tsockAPIderegthr();\r\n}\r\n\r\n#endif\t// __PLAT_NGPS__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/* Add logic tasks to the current task list                       */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::AddLogicTasks( App* app )\r\n{\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n    \r\n\tmlp_manager->AddLogicTask( app->GetReceiveDataTask());\r\n\tmlp_manager->AddLogicTask( app->GetSendDataTask());\r\n\tmlp_manager->AddLogicTask( app->GetProcessDataTask());\r\n\tmlp_manager->AddLogicTask( app->GetNetworkMetricsTask());\r\n}\r\n\r\n/******************************************************************/\r\n/* Add logic tasks to the push logic task list                    */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::AddLogicPushTasks( App* app )\r\n{\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\r\n\tapp->GetSendDataTask().Remove();\r\n\tapp->GetReceiveDataTask().Remove();\r\n\tapp->GetProcessDataTask().Remove();\r\n\tapp->GetNetworkMetricsTask().Remove();\r\n\r\n\tmlp_manager->AddLogicPushTask( app->GetReceiveDataTask());\r\n\tmlp_manager->AddLogicPushTask( app->GetSendDataTask());\r\n\tmlp_manager->AddLogicPushTask( app->GetProcessDataTask());\r\n\tmlp_manager->AddLogicPushTask( app->GetNetworkMetricsTask());\r\n}\r\n\r\n/******************************************************************/\r\n/* Removes network logic tasks                    \t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::RemoveNetworkTasks( App* app )\r\n{\r\n\tapp->GetSendDataTask().Remove();\r\n\tapp->GetReceiveDataTask().Remove();\r\n\tapp->GetProcessDataTask().Remove();\r\n\tapp->GetNetworkMetricsTask().Remove();\r\n}\r\n\r\n/******************************************************************/\r\n/* Creates a new Server at the given address and port\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nServer*\tManager::CreateNewAppServer( int id, char* appName, int max_clients, \r\n\t\t\t\t\t\t\t\t\t  unsigned short port, int address, int flags )\r\n{\r\n\tServer *new_app;\r\n\t\t\r\n\t\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\t// If we're using DHCP, we should have gotten our real IP address by now\r\n\t// from the DHCP server. Use that address from now on\r\n\tif( ShouldUseDHCP())\r\n\t{\r\n\t\taddress = inet_addr( m_local_ip );\t\t\r\n\t}\r\n\r\n\tnew_app = new Server( flags );\r\n\tnew_app->m_net_man = this;\r\n\tnew_app->init();\r\n    \r\n\tnew_app->m_id = id;\t\r\n\tstrncpy( new_app->m_name, appName, MAX_LEN_APP_NAME );\r\n\tnew_app->m_max_connections = max_clients;\r\n    \r\n\tm_net_servers.AddToTail( &new_app->m_node );\r\n\tif( new_app->IsLocal())\r\n\t{                  \r\n\t\tnew_app->m_connected = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tnew_app->bind_app_socket( address, port );\r\n\t\tif( flags & App::mBROADCAST )\r\n\t\t{\r\n\t\t\tnew_app->m_connected = true;\r\n\t\t}\r\n\t}\r\n\r\n#ifdef USE_ALIASES\r\n\tif( flags & App::mALIAS_SUPPORT )\r\n\t{\r\n\t\tnew_app->AllocateAliasTables();\r\n\t\tnew_app->ClearAliasTables();\r\n\t}\r\n#endif\r\n    \r\n\tAddLogicTasks( new_app );\r\n\r\n#ifndef __PLAT_NGC__\r\n    Dbg_Printf( \"Created new: %s server %p, Max Clients: %d, IP: %s, Port: %d\", appName, new_app, max_clients,\r\n\t\t   \t\t\t\t\tinet_ntoa( *(struct in_addr*) &address ), port );\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\tm_num_apps++;\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn new_app;\r\n}\r\n\r\n/******************************************************************/\r\n/* Creates a new client socket\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nClient\t*Manager::CreateNewAppClient( \tint id, char* appName, unsigned short port, int address,\r\n\t\t\t\t\t\t\t\t\t\tint flags )\r\n{\r\n\tClient *new_app;\r\n\r\n\t\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\t// If we're using DHCP, we should have gotten our real IP address by now\r\n\t// from the DHCP server. Use that address from now on\r\n\tif( ShouldUseDHCP())\r\n\t{\r\n\t\taddress = inet_addr( m_local_ip );\r\n\t}\r\n\r\n\tnew_app = new Client( flags );\r\n\tstrncpy( new_app->m_name, appName, MAX_LEN_APP_NAME );\r\n\tnew_app->m_net_man = this;\r\n    new_app->init();\r\n\r\n\tnew_app->m_id = id; \r\n\tnew_app->m_max_connections = 1;\r\n    \r\n\tm_net_clients.AddToTail( &new_app->m_node );\r\n\tif( !new_app->IsLocal())\r\n\t{\r\n#ifndef __PLAT_XBOX__\r\n\t\tnew_app->bind_app_socket( address, port );\r\n#endif\r\n\t}\r\n\t\r\n#ifdef USE_ALIASES\r\n\tnew_app->ClearAliasTable();\r\n#endif\r\n    \r\n\tAddLogicTasks( new_app );\r\n\r\n\tDbg_Printf( \"Created new: %s client %p on port %d\\n\", appName, new_app, port );\r\n\tm_num_apps++;\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn new_app;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::DestroyApp( App *app )\r\n{\r\n\tapp->m_node.Remove();\r\n\tapp->ShutDown();\r\n\tdelete app;\r\n\tm_num_apps--;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMetrics::Metrics( void )\r\n{\r\n\tm_num_packets = 0;\r\n\tm_total_bytes = 0;\r\n\tm_bytes_per_sec = 0;\r\n\tmemset( m_num_messages, 0, sizeof( int ) * MAX_MSG_IDS );\r\n\tmemset( m_size_messages, 0, sizeof( int ) * MAX_MSG_IDS );\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tMetrics::CalculateBytesPerSec( int cur_time )\r\n{\r\n\tint i, num_bytes;\r\n\t\t\r\n\tnum_bytes = 0; \r\n\t// Sum up number of bytes transferred over the last second\r\n\tfor( i = 0; i < vNUM_BUFFERED_PACKETS; i++ )\r\n\t{\r\n\t\tif( i >= m_num_packets )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tif(( cur_time - m_packets[i].GetTime()) < (int) Tmr::Seconds( 1 ))\r\n\t\t{\r\n\t\t\tnum_bytes += m_packets[i].GetNumBytes();\r\n\t\t}\r\n\t}\r\n\r\n\tm_bytes_per_sec = num_bytes;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tMetrics::GetBytesPerSec( void )\r\n{\r\n\treturn m_bytes_per_sec;\r\n}\r\n\t\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tMetrics::GetTotalBytes( void )\r\n{\r\n\treturn m_total_bytes;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tMetrics::GetTotalMessageData( int msg_id )\r\n{\r\n\treturn m_size_messages[ msg_id ];\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tMetrics::GetTotalNumMessagesOfId( int msg_id )\r\n{\r\n\treturn m_num_messages[ msg_id ];\r\n}\r\n\t\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tMetrics::AddPacket( int size, int time )\r\n{\r\n\tint index;\r\n\r\n\tindex = m_num_packets % vNUM_BUFFERED_PACKETS;\r\n\r\n\tm_packets[ index ].SetNumBytes( size );\r\n\tm_packets[ index ].SetTime( time );\r\n\tm_total_bytes += size;\r\n\tm_num_packets++;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tMetrics::AddMessage( int msg_id, int size )\r\n{\r\n\tm_num_messages[ msg_id ]++;\r\n\tm_size_messages[ msg_id ] += size;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tPacketInfo::GetNumBytes( void )\r\n{\r\n\treturn m_num_bytes;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tPacketInfo::GetTime( void )\r\n{\r\n\treturn m_time;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPacketInfo::SetNumBytes( int size )\r\n{\r\n\tm_num_bytes = size;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid\tPacketInfo::SetTime( int time )\r\n{\r\n\tm_time = time;\r\n}\r\n\r\n/******************************************************************/\r\n/* Iterator                                                       */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nServer *Manager::FirstServer( Lst::Search< App > *sh )\r\n{\r\n\t\r\n\r\n\tDbg_Assert( sh );\r\n\r\n\treturn((Server*) sh->FirstItem( m_net_servers ));\r\n}\r\n\r\n/******************************************************************/\r\n/* Iterator                                                       */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nClient *Manager::FirstClient( Lst::Search< App > *sh )\r\n{\r\n\t\r\n\r\n\tDbg_Assert( sh );\r\n\r\n\treturn((Client*) sh->FirstItem( m_net_clients ));\r\n}\r\n\r\n/******************************************************************/\r\n/* Iterator                                                       */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nApp *Manager::NextApp( Lst::Search< App > *sh )\r\n{\r\n\t\r\n\r\n\tDbg_Assert( sh );\r\n\r\n\treturn( sh->NextItem());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::NumApps( void )\r\n{\r\n\treturn m_num_apps;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef __PLAT_NGC__\r\nstatic\tvoid*    s_so_alloc( u32 name, s32 size )\r\n{\r\n\treturn Mem::Malloc( size );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic\tvoid     s_so_free( u32 name, void* ptr, s32 size )\r\n{\r\n\tMem::Free( ptr );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::initialize_ngc( void )\r\n{\r\n\tint result;\r\n    SOConfig config;\r\n\r\n\tmemset( &config, 0, sizeof( SOConfig ));\r\n\t\r\n\tconfig.vendor = SO_VENDOR_NINTENDO;\r\n\tconfig.version = SO_VERSION;\r\n\tconfig.alloc = s_so_alloc;\r\n\tconfig.free = s_so_free;\r\n\tif( ShouldUseDHCP())\r\n    {\r\n\t\tconfig.flag = SO_FLAG_DHCP;\r\n    }\r\n    else\r\n    {   \r\n\t\tconfig.flag = 0;\r\n\r\n        inet_aton( GetLocalIP(), (struct in_addr*) &config.addr );\r\n        inet_aton( GetSubnetMask(), (struct in_addr*) &config.netmask );\r\n        inet_aton( GetGateway(), (struct in_addr*) &config.router );\r\n\t\tinet_aton( GetDNSServer( 0 ), (struct in_addr*) &config.dns1 );\r\n\t\tinet_aton( GetDNSServer( 1 ), (struct in_addr*) &config.dns2 );\r\n\t}\r\n\r\n\tresult = SOStartup( &config );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tSOCleanup();\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#ifdef __PLAT_NGPS__\r\n\r\nbool\tManager::load_irx_files( void )\r\n{\r\n\r\n//////////////////////////////\r\n#if 0\t// MOVED TO SIOMAN.CPP\r\n\r\n\tint result;\r\n\r\n\t// Load the stack IRX file\r\n#ifdef __NOPT_DEBUG__\r\n\tresult = SIO::LoadIRX( \"SNSTKDBG\" );\r\n#else\r\n\tresult = SIO::LoadIRX( \"SNSTKREL\" );\r\n#endif\r\n\r\n    if( result < 0 )\r\n    {\r\n\t\tDbg_MsgAssert( 0,( \"EE:Can't load module snstkrel/dbg.irx. Error : %d\\n\", result ));\r\n\t\tSetError( vRES_ERROR_INVALID_IRX );\r\n\t\t\r\n\t\treturn false;\r\n\t}\r\n#endif\t\r\n//////////////////////////////\r\n\r\n\r\n\r\n#ifdef USE_DECI2\r\n    // Load the DECI2 driver IRX file\r\n    SIO::LoadIRX( \"sndrv000\" );\r\n#else\r\n\r\n\tswitch( GetConnectionType())\r\n\t{\r\n\t\tcase vCONN_TYPE_PPPOE:\r\n\t\t{\r\n\t\t\tswitch( GetDeviceType())\r\n\t\t\t{\r\n\t\t\t\tcase vDEV_TYPE_USB_ETHERNET:\r\n\t\t\t\t{\r\n\t\t\t\t\t// Load the PPPoE Driver IRX file\r\n\t\t\t\t\tif( SIO::LoadIRX( \"sndrv200\" ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// Load the USB-Ethernet Driver IRX file\r\n\t\t\t\t\tif( SIO::LoadIRX( \"sndrv201\" ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase vDEV_TYPE_PC_ETHERNET:\r\n\t\t\t\t{\r\n\t\t\t\t\t// Load the PPPoE Driver IRX file\r\n\t\t\t\t\tif( SIO::LoadIRX( \"sndrv200\" ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// Load the SN Wrapper (PPPoE variant) for Sony Ether\r\n\t\t\t\t\tif( SIO::LoadIRX( \"sndrv202\" ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t} \r\n\t\t\t\t\t// Load the Sony pcmcia irx\r\n\t\t\t\t\tif( SIO::LoadIRX( \"dev9\" ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ts_prepare_power_off();\r\n\t\t\t\t\t// Load the Sony Ethernet driver IRX file\r\n\t\t\t\t\tif( SIO::LoadIRX( \"smap\", 0, NULL, false ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tSetError( vRES_ERROR_GENERAL );\r\n\t\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vCONN_TYPE_ETHERNET:\r\n\t\t{\r\n\t\t\tswitch( GetDeviceType())\r\n\t\t\t{\r\n\t\t\t\tcase vDEV_TYPE_USB_ETHERNET:\r\n\t\t\t\t{\r\n\t\t\t\t\t// Load the USB-Ethernet Driver IRX file\r\n\t\t\t\t\tif( SIO::LoadIRX( \"sndrv001\" ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase vDEV_TYPE_PC_ETHERNET:\r\n\t\t\t\t{\r\n                    if( SIO::LoadIRX( \"sndrv100\" ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// Load the Sony pcmcia irx\r\n\t\t\t\t\tif( SIO::LoadIRX( \"dev9\" ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ts_prepare_power_off();\r\n\t\t\t\t\t// Load the Sony Ethernet driver IRX file\r\n\t\t\t\t\tif( SIO::LoadIRX( \"smap\", 0, NULL, false ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tSetError( vRES_ERROR_GENERAL );\r\n\t\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vCONN_TYPE_MODEM:\r\n\t\t{\r\n\t\t\tswitch( GetDeviceType())\r\n\t\t\t{\r\n\t\t\t\tcase vDEV_TYPE_USB_MODEM:\r\n\t\t\t\t{\r\n\t\t\t\t\t// Load the USB-Modem Driver IRX file\r\n\t\t\t\t\tif( SIO::LoadIRX( \"sndrv002\" ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcase vDEV_TYPE_SONY_MODEM:\r\n\t\t\t\t{\r\n\t\t\t\t\tif (Config::PAL())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Sony Modem Not Supported in PAL territories\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Load the SN modem wrapper irx\r\n\t\t\t\t\tif( SIO::LoadIRX( \"sndrv101\" ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// Load the Sony pcmcia irx\r\n\t\t\t\t\tif( SIO::LoadIRX( \"dev9\" ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ts_prepare_power_off();\r\n                    // Load the Sony modem driver irx\r\n\t\t\t\t\tif( SIO::LoadIRX( \"spduart\", sizeof(spduartArgs),  (char*) spduartArgs ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSetError( vRES_ERROR_DEVICE_NOT_CONNECTED );\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tSetError( vRES_ERROR_GENERAL );\r\n\t\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\t// No valid device specified\r\n\t\t\tSetError( vRES_ERROR_GENERAL );\r\n\t\t\treturn false;\r\n\t}\r\n\t\r\n#endif\t// USE_DECI2\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::initialize_ps2( void )\r\n{\r\n\t\r\n\t\r\n\tbool result;\r\n\r\n\tDbg_Printf( \"initializing PS2\\n\" );\r\n    \r\n    if( m_net_drivers_loaded == false )\r\n\t{   \r\n\t\tbool success;\r\n\r\n\t\tFile::StopStreaming( );\r\n\t\tif ( Pcm::UsingCD( ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"Can't load IRX modules when CD is busy.\" ));\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\r\n\t\tDbg_Printf( \"initializing PS2_2\\n\" );\r\n\t\tsuccess = load_irx_files();\r\n\t\tm_net_drivers_loaded = true;\r\n\t\tif( success == false )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( m_device_changed )\r\n\t\t{\r\n\t\t\tSetError( vRES_ERROR_DEVICE_CHANGED );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n    \r\n\tresult = initialize_device();\r\n\tif( result == false )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif( !m_stack_setup || m_options_changed )\r\n\t{\r\n\t\tm_stack_setup = sn_stack_setup();\r\n\t}\r\n\r\n\tm_device_changed = false;\r\n\treturn m_stack_setup;\r\n}\r\n\r\n#endif\t// __PLAT_NGPS__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::Manager( void )\r\n{\t\r\n\tint msg_id, i;\r\n\r\n#if( defined ( __PLAT_WN32__ ) || defined ( __PLAT_XBOX__ ))\r\n\tint err;\r\n\tWORD version_required;\r\n\tWSADATA wsa_data;\r\n\r\n#ifdef __PLAT_XBOX__\r\n\tXNetStartupParams xnsp;\r\n\tZeroMemory( &xnsp, sizeof(xnsp) );\r\n\txnsp.cfgSizeOfStruct = sizeof(xnsp);\r\n\r\n#ifdef __NOPT_NOASSERTIONS__\r\n\txnsp.cfgFlags = 0;\r\n#else\r\n\txnsp.cfgFlags = XNET_STARTUP_BYPASS_SECURITY;// | XNET_STARTUP_BYPASS_DHCP;\r\n#endif\r\n\r\n\terr = XNetStartup( &xnsp );\r\n\tif( err )\r\n\t{\r\n\t\tXNetCleanup();\r\n\t\treturn;\r\n\t}\t\r\n#endif\r\n\r\n\tversion_required = MAKEWORD( 2, 2 );\r\n\tif( err = WSAStartup ( version_required, &wsa_data ))\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Failed to start WinSock\\n\" ));\r\n\t\tWSACleanup();\t\r\n#ifdef __PLAT_XBOX__\r\n\t\tXNetCleanup();\r\n#endif\r\n\t\treturn;\r\n\t}\t\r\n\tif (\t( LOBYTE( wsa_data.wVersion ) != 2 ) ||\r\n\t\t\t( HIBYTE( wsa_data.wVersion ) != 2 ))\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Failed to start WinSock\\n\" ));\r\n\t\tWSACleanup();\t\r\n#ifdef __PLAT_XBOX__\r\n\t\tXNetCleanup();\r\n#endif\r\n\t\treturn;\r\n\t}\r\n\r\n#ifdef __PLAT_XBOX__\t\r\n#\tif 0\r\n\tHRESULT hr;\r\n\tXONLINE_STARTUP_PARAMS xosp = { 0 };\r\n\r\n\thr = XOnlineStartup( &xosp );\r\n\tif( FAILED( hr ))\r\n\t{\r\n\t\tXOnlineCleanup();\r\n\t\treturn;\r\n\t}\r\n#\tendif\r\n#endif\r\n\r\n#else    \r\n#ifdef __PLAT_NGPS__\r\n\tChangeThreadPriority( GetThreadId(), vMAIN_THREAD_PRIORITY );\r\n\tm_stack_setup = false;\r\n\tm_options_changed = false;\r\n\tm_device_changed = false;\r\n\tm_net_drivers_loaded = false;\r\n#endif\t// __PLAT_NGPS__\r\n#endif\t// __PLAT_WN32__\r\n\r\n\tfor( msg_id = 0; msg_id < 255; msg_id++ )\r\n\t{\r\n\t\tSetMessageName( msg_id, \"<No Text>\" );\r\n\t\tSetMessageFlags( msg_id, 0 );\r\n\t}\r\n\r\n\tSetMessageName( MSG_ID_PING_TEST, \"Ping Test\" );\r\n\tSetMessageName( MSG_ID_PING_RESPONSE, \"Ping Response\" );\r\n\tSetMessageName( MSG_ID_CONNECTION_REQ, \"Connection Request\" );\r\n\tSetMessageName( MSG_ID_CONNECTION_ACCEPTED, \"Connection Accepted\" );\r\n\tSetMessageName( MSG_ID_CONNECTION_REFUSED, \"Connection Refused\" );\r\n\tSetMessageName( MSG_ID_CONNECTION_TERMINATED, \"Connection Terminated\" );\r\n\tSetMessageName( MSG_ID_SEQUENCED, \"Sequenced Message\" );\r\n\tSetMessageName( MSG_ID_ACK, \"Ack\" );\r\n\tSetMessageName( MSG_ID_FIND_SERVER, \"Find Server\" );\r\n\tSetMessageName( MSG_ID_SERVER_RESPONSE, \"Server Find Response\" );\r\n\tSetMessageName( MSG_ID_TIMESTAMP, \"Timestamp\" );\r\n\tSetMessageName( MSG_ID_ALIAS, \"New Alias\" );\r\n\tSetMessageName( MSG_ID_DISCONN_REQ,\t\"Disconn Request\" );\r\n\tSetMessageName( MSG_ID_DISCONN_ACCEPTED, \"Disconn Accepted\" );\r\n\r\n\tSetMessageFlags( MSG_ID_TIMESTAMP, mMSG_SIZE_UNKNOWN );\r\n\tSetMessageFlags( MSG_ID_ACK, mMSG_SIZE_UNKNOWN );\r\n\r\n\tsprintf( m_local_ip, \"<Unknown>\" );\r\n\tsprintf( m_gateway, DEFAULT_SNPS2_GATEWAY );\r\n\tsprintf( m_subnet, DEFAULT_SNPS2_SUB_MSK );\r\n\t\t\t \r\n\tm_num_apps = 0;\r\n\tm_conn_type = vCONN_TYPE_NONE;\r\n\tm_use_dhcp = false;\r\n\tm_online = false;\r\n\tm_use_dialup_auth = false;\r\n\tm_last_error = vRES_SUCCESS;\r\n\tm_modem_state = vMODEM_STATE_DISCONNECTED;\r\n\tm_modem_err = 0;\r\n\r\n\tfor( i = 0; i < 3; i++ )\r\n\t{\r\n\t\tm_dns_servers[i][0] = '\\0';\r\n\t}\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tm_bandwidth = 4200;\t// Default to a 33.6kbps modem's approximate payload threshold (i.e. including packet overhead)\r\n#else\r\n\tm_bandwidth = 400000;\t// On Xbox, just assume broadband\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager( void )\r\n{\r\n\t\r\n#if( defined ( __PLAT_WN32__ ) || defined ( __PLAT_XBOX__ ))\r\n\tWSACleanup();\t\r\n#endif\r\n\r\n#ifdef __PLAT_XBOX__\r\n\tXNetCleanup();\r\n#\tif 0\r\n\tXOnlineCleanup();\r\n#\tendif\r\n#endif\r\n\r\n#ifdef __PLAT_NGC__\r\n\tSOCleanup();\r\n#endif\r\n\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tsn_int32\tstack_state, result;\r\n\t\r\n\tif( m_stack_setup )\r\n\t{\r\n\t\t// Stop the stack\r\n\t\tresult = sn_stack_state(SN_STACK_STATE_STOP, &stack_state );\r\n\t\tDbg_MsgAssert( result == 0,( \"EE:sn_stack_sate() failed %d\\n\", result ));\r\n\t\t\t\r\n\t\t// De-Register this thread with the socket API\r\n\t\tDbg_Printf( \"EE:Calling sockAPIderegthr()\\n\" );\r\n\t\tsockAPIderegthr();\r\n\t}\r\n#endif // __PLAY_NGPS__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#ifdef __PLAT_NGPS__\r\n\r\nvoid Manager::conn_modem_state_callback( sn_int32 modem_state )\r\n{\r\n\t\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\t\t\r\n\tDbg_Printf(\"  Modem state %d = %s\\n\", modem_state, sntc_str_modem_state( modem_state ));\r\n\tswitch( modem_state )\r\n\t{\r\n\t\tcase SN_MODEM_READY:\r\n\t\tcase SN_MODEM_DIALING:\r\n\t\t\tnet_man->SetModemState( vMODEM_STATE_DIALING );\r\n\t\t\t\r\n\t\t\t// If we're using PAP/CHAP, clear the login script. We do it here instead of before\r\n\t\t\t// sntc_connect_modem() because that call resets to the default login script.\r\n\t\t\tif( net_man->ShouldUseDialupAuthentication())\r\n\t\t\t{\r\n\t\t\t\tsndev_set_null_scrpt_type clr;\r\n\t\t\t\tint result;\r\n\r\n\t\t\t\tclr.reserved = 0;\r\n\r\n\t\t\t\tresult = sndev_set_options(0, SN_DEV_SET_NULL_SCRPT, &clr, sizeof(clr));\r\n                Dbg_Printf( \"EE:sndev_set_options(clr) returned %d\\n\", result );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tDbg_Printf( \"Setting modem state to modem state dialing\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase SN_MODEM_LOGIN:\r\n\t\t\tDbg_Printf( \"Setting modem state to modem state connected\\n\" );\r\n\t\t\tnet_man->SetModemState( vMODEM_STATE_CONNECTED );\r\n\t\t\tbreak;\r\n\t\tcase SN_MODEM_PPP_UP:\r\n\t\t\tDbg_Printf( \"Setting modem state to modem state logged in\\n\" );\r\n\t\t\tnet_man->SetModemState( vMODEM_STATE_LOGGED_IN );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\treturn;\r\n\t};\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::disconn_modem_state_callback( sn_int32 modem_state )\r\n{\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n    \r\n    Dbg_Printf(\"  Modem state = %s\\n\", sntc_str_modem_state( modem_state ));\r\n\tswitch( modem_state )\r\n\t{\r\n\t\tcase SN_MODEM_HANGINGUP:\r\n\t\t\tnet_man->SetModemState( vMODEM_STATE_HANGING_UP );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\treturn;\r\n\t};\r\n}\r\n\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nbool\tManager::NetworkEnvironmentSetup( void )\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\treturn initialize_ps2();\r\n#endif\r\n#ifdef __PLAT_NGC__\r\n\treturn initialize_ngc();\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::NeedToTestNetworkEnvironment( void )\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\tif( m_net_drivers_loaded && m_device_changed )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\tif( !m_stack_setup || m_options_changed )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n#endif\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ConnectToInternet( void )\r\n{\r\n\t\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\n\tif(( IsOnline() == false ) || m_options_changed )\r\n\t{\r\n        if( GetConnectionType() == vCONN_TYPE_ETHERNET )\r\n\t\t{\r\n\t\t\tm_online = true;\r\n\t\t}\r\n\t\telse if(( GetConnectionType() == vCONN_TYPE_MODEM ) ||\r\n\t\t\t\t( GetConnectionType() == vCONN_TYPE_PPPOE ))\r\n\t\t{\r\n\t\t\tint result, device_type;\r\n\t\t\tint modem_state;\r\n            \r\n\t\t\ts_cancel_dialup_conn = false;\r\n            result = sndev_get_attached(0, &device_type, NULL, NULL);\r\n\t\t\t// Check that the above function call worked ok\r\n\t\t\tif( result != 0 )\r\n\t\t\t{\r\n\t\t\t\tSetModemState( vMODEM_STATE_ERROR );\r\n\t\t\t\tm_modem_err = SNTC_ERR_NOMODEM;\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\r\n\t\t\t// Check that there is a compatible modem attached\r\n\t\t\tif( device_type != SN_DEV_TYPE_USB_MODEM )\r\n\t\t\t{\r\n\t\t\t\tSetModemState( vMODEM_STATE_ERROR );\r\n\t\t\t\tm_modem_err = SNTC_ERR_NOMODEM;\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\tresult = snmdm_get_state( &modem_state );\r\n\t\t\t// Check that the above function call worked ok\r\n\t\t\tif( result != 0 )\r\n\t\t\t{\r\n\t\t\t\tSetModemState( vMODEM_STATE_ERROR );\r\n\t\t\t\tm_modem_err = SNTC_ERR_NOMODEM;\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\r\n\t\t\t// Make sure that the modem is ready to dial, if not reset it\r\n\t\t\tif(\t( modem_state != SN_MODEM_READY ) && \r\n\t\t\t\t( modem_state != SN_MODEM_READY_AUTOANS ))\r\n\t\t\t{\r\n\t\t\t\tsn_char* err_msg_ptr;\r\n\r\n\t\t\t\tDbg_Printf( \"EE:Calling sntc_reset_modem()\\n\" );\r\n\t\t\t\t// Attempt to reset the modem\r\n\t\t\t\tresult = sntc_reset_modem(\tvMODEM_RESET_TIMEOUT,\t// timeout_secs\r\n\t\t\t\t\t\t\t\t\t\t\tdisconn_modem_state_callback,\t// callback\r\n\t\t\t\t\t\t\t\t\t\t\t&err_msg_ptr );     \t// error_message\r\n\t\t\t\t// If failed to reset the modem, then the result, and\r\n\t\t\t\t// error_message will have been set up by sntc_reset_modem.\r\n\t\t\t\tif( result != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tSetModemState( vMODEM_STATE_ERROR );\r\n\t\t\t\t\tm_modem_err = SNTC_ERR_NOMODEM;\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t{\r\n\t\t\t\tstruct SemaParam params;\r\n\r\n\t\t\t\tparams.initCount = 1;\r\n\t\t\t\tparams.maxCount = 10;\r\n\t\t\t\r\n\t\t\t\ts_conn_semaphore = CreateSema( &params );\r\n\r\n                // Clear the modem state before we start\r\n\t\t\t\tSetModemState( -1 );\r\n\r\n\t\t\t\tm_modem_thread_data.m_pEntry = threaded_modem_conn;\r\n\t\t\t\tm_modem_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY;\r\n\t\t\t\tm_modem_thread_data.m_pStackBase = m_modem_thread_stack;\r\n\t\t\t\tm_modem_thread_data.m_iStackSize = vMODEM_THREAD_STACK_SIZE;\r\n\t\t\t\tm_modem_thread_data.m_utid = 0x150;//vBASE_SOCKET_THREAD_ID + NumApps();\r\n\t\t\t\tThread::CreateThread( &m_modem_thread_data );\r\n\t\t\t\tm_modem_thread_id = m_modem_thread_data.m_osId;\r\n                \r\n\t\t\t\tStartThread( m_modem_thread_id, this );\r\n\t\t\t}\r\n\t\t}   \r\n\t}\r\n#else\r\n\tm_online = true;\r\n#endif\r\n\r\n\treturn m_online;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::DisconnectFromInternet( void )\r\n{\r\n\t\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tif(\tm_conn_type == vCONN_TYPE_ETHERNET )\r\n\t{\r\n\t\tm_online = false;\r\n\t}\r\n\telse if( ( m_conn_type == vCONN_TYPE_MODEM ) ||\r\n\t\t\t ( m_conn_type == vCONN_TYPE_PPPOE ))\r\n\t{\r\n        // Just in case the modem thread is running, stop it\r\n\t\ts_cancel_dialup_conn = true;\r\n\t\tWaitSema( s_conn_semaphore );\r\n\t\tDeleteSema( s_conn_semaphore );\r\n\t\tTerminateThread( m_modem_thread_id );\r\n\t\tDeleteThread( m_modem_thread_id );\r\n\r\n\t\tSetModemState( vMODEM_STATE_DISCONNECTING );\r\n\t\tm_modem_err = 0;\r\n\r\n\t\tm_modem_thread_data.m_pEntry = threaded_modem_disconn;\r\n\t\tm_modem_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY;\r\n\t\tm_modem_thread_data.m_pStackBase = m_modem_thread_stack;\r\n\t\tm_modem_thread_data.m_iStackSize = vMODEM_THREAD_STACK_SIZE;\r\n\t\tm_modem_thread_data.m_utid = 0x14F;//vBASE_SOCKET_THREAD_ID + NumApps();\r\n\t\tThread::CreateThread( &m_modem_thread_data );\r\n\t\tm_modem_thread_id = m_modem_thread_data.m_osId;\r\n\t\t\r\n\t\tStartThread( m_modem_thread_id, this );\r\n\t}\r\n#else\r\n\tm_online = false;\r\n#endif\r\n\r\n\treturn ( m_online == false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::GetModemBaudRate( void )\r\n{\r\n\treturn m_modem_baud_rate;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetBandwidth( int bytes_per_sec )\r\n{\r\n\tm_bandwidth = bytes_per_sec;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::GetBandwidth( void )\r\n{\r\n\treturn m_bandwidth;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::IsOnline( void )\r\n{   \r\n#ifdef __PLAT_NGPS__\r\n\tif(\t( GetConnectionType() == vCONN_TYPE_MODEM ) ||\r\n\t\t( GetConnectionType() == vCONN_TYPE_PPPOE ))\r\n\t{\r\n\t\tint modem_state;\r\n        \r\n\t\tm_online = false;\r\n\t\tif( snmdm_get_state( &modem_state ) == 0 )\r\n\t\t{\r\n\t\t\tif( modem_state == SN_MODEM_PPP_UP )\r\n\t\t\t{\r\n\t\t\t\tm_online = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif// __PLAT_NGPS__\r\n\r\n\treturn m_online;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetISPPhoneNumber( char* phone_no )\r\n{\r\n\t\r\n\r\n\tDbg_Assert( phone_no );\r\n\r\n\tstrcpy( m_isp_phone_no, phone_no );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetISPLogin( char* login )\r\n{\r\n\t\r\n\r\n\tDbg_Assert( login );\r\n\r\n\tstrcpy( m_isp_user_name, login );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetISPPassword( char* password )\r\n{\r\n\t\r\n\r\n\tDbg_Assert( password );\r\n\r\n\tstrcpy( m_isp_password, password );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetGateway( char* ip )\r\n{\r\n\t\r\n\r\n\tif( strcmp( ip, m_gateway ))\r\n\t{\r\n\t\tstrcpy( m_gateway, ip );\r\n#ifdef __PLAT_NGPS__\r\n\t\tm_options_changed = true;\r\n#endif\t\t// __PLAT_NGC__\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetSubnetMask( char* ip )\r\n{\r\n\t\r\n\r\n\tif( strcmp( ip, m_subnet ))\r\n\t{\r\n\t\tstrcpy( m_subnet, ip );\r\n#ifdef __PLAT_NGPS__\r\n\t\tm_options_changed = true;\r\n#endif\t\t// __PLAT_NGC__\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetPublicIP( unsigned int ip )\r\n{\r\n\tm_public_ip = ip;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetLocalIP( char* ip )\r\n{\r\n\t\r\n\r\n\tif( strcmp( ip, m_local_ip ))\r\n\t{\r\n\t\tstrcpy( m_local_ip, ip );\r\n#ifdef __PLAT_NGPS__\r\n\t\tm_options_changed = true;\r\n#endif\t\t// __PLAT_NGC__\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetConnectionType( ConnType conn_type )\r\n{\r\n\tif( m_conn_type != conn_type )\r\n\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\tif( m_conn_type != vCONN_TYPE_NONE )\r\n\t\t{\r\n\t\t\tm_device_changed = true;\r\n\t\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\t\tm_conn_type = conn_type;\r\n\r\n        // Some default values for bandwidth limiting\r\n\t\tswitch( m_conn_type )\r\n\t\t{\r\n\t\t\tcase vCONN_TYPE_MODEM:\r\n\t\t\t\tSetBandwidth( 4200 );\t\r\n\t\t\t\tbreak;\r\n\t\t\tcase vCONN_TYPE_ETHERNET:\r\n\t\t\t\tSetBandwidth( 400000 );\r\n\t\t\t\tbreak;\r\n\t\t\tcase vCONN_TYPE_PPPOE:\r\n\t\t\t\tSetBandwidth( 300000 );\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetDeviceType( DeviceType dev_type )\r\n{\r\n\tif( m_device_type != dev_type )\r\n\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\tif( m_device_type != vDEV_TYPE_NONE )\r\n\t\t{\r\n\t\t\tm_device_changed = true;\r\n\t\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\t\tm_device_type = dev_type;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetDHCP( bool use_dhcp )\r\n{    \r\n\tif( m_use_dhcp != use_dhcp )\r\n\t{\r\n\t\tm_use_dhcp = use_dhcp;\r\n#ifdef __PLAT_NGPS__\r\n\t\tm_options_changed = true;\r\n#endif\t\t// __PLAT_NGC__\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetDialupAuthentication( bool authenticate )\r\n{\r\n\tm_use_dialup_auth = authenticate;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetDNSServer( int index, char* ip )\r\n{\r\n\t\r\n\t\r\n\tDbg_Assert(( index >= 0 ) && ( index < 3 ));\r\n\tDbg_Assert( ip );\r\n\r\n\tif( strcmp( ip, m_dns_servers[index] ))\r\n\t{\r\n\t\tstrcpy( m_dns_servers[index], ip );\r\n#ifdef __PLAT_NGPS__\r\n\t\tm_options_changed = true;\r\n#endif\t\t// __PLAT_NGC__\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetHostName( char* host )\r\n{\r\n\t\r\n\r\n\t// Either they pass us NULL or they pass us a value less than 32 chars long\r\n\tDbg_Assert( !host || ( strlen( host ) < 32 ));\r\n\r\n    if( host == NULL )\r\n\t{\r\n\t\tm_host_name[0] = '\\0';\r\n\t}\r\n\r\n\tstrcpy( m_host_name, host );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetDomainName( char* domain )\r\n{\r\n\t\r\n\r\n\t// Either they pass us NULL or they pass us a value less than 32 chars long\r\n\tDbg_Assert( !domain || ( strlen( domain ) < 32 ));\r\n\r\n    if( domain == NULL )\r\n\t{\r\n\t\tm_domain_name[0] = '\\0';\r\n\t}\r\n\r\n\tstrcpy( m_domain_name, domain );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\tManager::GetDNSServer( int index )\r\n{\r\n\t\r\n\r\n\tDbg_Assert(( index >= 0 ) && ( index < 3 ));\r\n\r\n\treturn m_dns_servers[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\tManager::GetISPPhoneNumber( void )\r\n{\r\n\tif( GetConnectionType() == vCONN_TYPE_PPPOE )\r\n\t{\r\n\t\treturn \"\";\r\n\t}\r\n\treturn m_isp_phone_no;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ShouldUseDHCP( void )\r\n{\r\n\tif(( GetConnectionType() == vCONN_TYPE_PPPOE ) ||\r\n\t   ( GetConnectionType() == vCONN_TYPE_MODEM ))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn m_use_dhcp;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ShouldUseDialupAuthentication( void )\r\n{\r\n\tif( GetConnectionType() == vCONN_TYPE_PPPOE )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn m_use_dialup_auth;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\tManager::GetGateway( void )\r\n{\r\n\t\r\n\r\n\treturn m_gateway;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\tManager::GetSubnetMask( void )\r\n{\r\n\t\r\n\r\n\treturn m_subnet;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\tManager::GetHostName( void )\r\n{\r\n\t\r\n\r\n\treturn m_host_name;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\tManager::GetDomainName( void )\r\n{\r\n\t\r\n\r\n\treturn m_domain_name;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nunsigned int\tManager::GetPublicIP( void )\r\n{\r\n\tif( m_public_ip == 0 )\r\n\t{\r\n\t\treturn inet_addr( m_local_ip );\r\n\t}\r\n\t\r\n\treturn m_public_ip;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\tManager::GetLocalIP( void )\r\n{   \r\n\t\r\n\r\n#if defined( __PLAT_NGPS__ ) || defined( __PLAT_XBOX__ ) || defined( __PLAT_NGC__ )\r\n\treturn m_local_ip;\r\n#else\r\n\tstruct hostent *host, *local_host;\r\n\tstruct in_addr address;\r\n\tchar *ip_str;\r\n\tint ip;\r\n\r\n\tif(( local_host = gethostbyname( \"localhost\" )))\r\n\t{\t\r\n\t\tif(( host = gethostbyname( local_host->h_name )))\r\n\t\t{\r\n\t\t\tip = *(unsigned long *) host->h_addr_list[0];\t\t\t\r\n\t\t\taddress.s_addr = ip;\r\n\t\t\tip_str = inet_ntoa( address ); \r\n\t\t\treturn ip_str;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tip = *(unsigned long *) local_host->h_addr_list[0];\t\t\t\r\n\t\t\taddress.s_addr = ip;\r\n\t\t\tip_str = inet_ntoa( address ); \r\n\t\t\treturn ip_str;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn \"<Unknown>\";\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nConnType\tManager::GetConnectionType( void )\r\n{\r\n\treturn m_conn_type;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nDeviceType\tManager::GetDeviceType( void )\r\n{\r\n#ifdef __PLAT_XBOX__\r\n\treturn vDEV_TYPE_USB_ETHERNET;\r\n#else\r\n\treturn m_device_type;\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::SetError( int error )\r\n{\r\n\tm_last_error = error;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\tManager::GetLastError( void )\r\n{\r\n\treturn m_last_error;\r\n}\r\n\r\n/******************************************************************/\r\n/* Get the name associated with a message id \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\tManager::GetMessageName( unsigned char msg_id )\r\n{\r\n#ifdef\tNET_DEBUG_MESSAGES\r\n\treturn m_message_names[ msg_id ];\r\n#else\r\n\treturn \"<Disabled>\";\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/* Associate a text name with a message id for debugging purposes */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetMessageName( unsigned char msg_id, char* msg_name )\r\n{\r\n#ifdef NET_DEBUG_MESSAGES\r\n\tDbg_Assert( msg_name );\r\n\r\n\tstrncpy( m_message_names[ msg_id ], msg_name, vMAX_MSG_NAME_LEN - 1 );\r\n\tm_message_names[msg_id][vMAX_MSG_NAME_LEN - 1] = '\\0';\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar\tManager::GetMessageFlags( unsigned char msg_id )\r\n{\r\n\treturn m_message_flags[ msg_id ];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetMessageFlags( unsigned char msg_id, char flags )\r\n{\r\n\tm_message_flags[ msg_id ] = flags;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::GetModemState( void )\r\n{\r\n\treturn m_modem_state;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetModemState( int state )\r\n{\r\n\tm_modem_state = state;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::GetModemError( void )\r\n{\r\n\treturn m_modem_err;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::CanChangeDevices( void )\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\treturn !m_net_drivers_loaded;\r\n#else\r\n\treturn true;\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMsgLink::MsgLink( QueuedMsg *msg )\r\n: Lst::Node< MsgLink > ( this ), m_QMsg( msg ), m_SendTime( 0 )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMsgImpLink::MsgImpLink( QueuedMsg *msg )\r\n: Lst::Node< MsgImpLink > ( this ), m_QMsg( msg ), m_SendTime( 0 )\r\n{\r\n\tm_NumResends = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMsgSeqLink::MsgSeqLink( QueuedMsgSeq *msg )\r\n: Lst::Node< MsgSeqLink > ( this ), m_StreamMessage( 0 ), m_SendTime( 0 ), m_QMsg( msg )\r\n{\r\n\tm_NumResends = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStreamLink::StreamLink( StreamDesc* desc )\r\n: Lst::Node< StreamLink > ( this ), m_Desc ( desc )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStreamDesc::StreamDesc( void )\r\n: m_Size( 0 ), m_Data( NULL ), m_DataPtr( NULL ), m_GroupId( 0 ), m_SendInPlace( false )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStreamDesc::~StreamDesc( void )\r\n{\r\n\tif( m_Data && !m_SendInPlace )\r\n\t{\r\n\t\tdelete [] m_Data;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMsgDesc::MsgDesc( void )\r\n: m_Id( 0 ), m_StreamMessage( 0 ), m_Length( 0 ), m_Data( 0 ), m_Priority( NORMAL_PRIORITY ), m_Queue( QUEUE_DEFAULT ), m_GroupId( GROUP_ID_DEFAULT ),\r\n\tm_Singular( false ), m_Delay( 0 ), m_ForcedSequenceId( 0 )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nQueuedMsg::QueuedMsg( unsigned char msg_id, unsigned short msg_len, void* data )\r\n{\r\n\t\r\n\t\r\n\tm_Data = NULL;\r\n\tif( msg_len > 0 )\r\n\t{\r\n\t\tm_Data = new char[ msg_len ];\r\n\t\tmemcpy( m_Data, data, msg_len );\r\n\t}\r\n\t\r\n\tm_MsgId = msg_id;\r\n\tm_MsgLength = msg_len;\r\n#ifdef\t__PLAT_NGPS__\t\t\t\t\t\t\t\t\t\t\t  \r\n\tDbg_MsgAssert(Mem::SameContext(this,Mem::Manager::sHandle().NetworkHeap()),(\"QueuedMsg not on network heap\"));\t\r\n#endif\t\t//\t__PLAT_NGPS__\t\t\t\t\t\t\t\t\t\t\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nQueuedMsg::~QueuedMsg( void )\r\n{\r\n\t\r\n\tif( m_Data )\r\n\t{\r\n\t\tdelete [] m_Data;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nQueuedMsgSeq::QueuedMsgSeq( unsigned char msg_id, unsigned short msg_len, void* data, unsigned char group_id )\r\n{\r\n\t\r\n\t\r\n\tm_Data = NULL;\r\n\tif( msg_len > 0 )\r\n\t{\r\n\t\tm_Data = new char[ msg_len ];\r\n\t\tmemcpy( m_Data, data, msg_len );\r\n\t}\r\n\t\r\n\tm_MsgId = msg_id;\r\n\tm_MsgLength = msg_len;\r\n\tm_GroupId = group_id;\t\r\n#ifdef\t__PLAT_NGPS__\t\t\t\t\t\t\t\t\t\t\t  \r\n\tDbg_MsgAssert(Mem::SameContext(this,Mem::Manager::sHandle().NetworkHeap()),(\"QueuedMsgSeq not on network heap\"));\t\r\n#endif\t\t//\t__PLAT_NGPS__\t\t\t\t\t\t\t\t\t\t\t  \r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nQueuedMsgSeq::~QueuedMsgSeq( void )\r\n{\r\n\tif( m_Data )\r\n\t{\r\n\t\tdelete [] m_Data;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nBitStream::BitStream( void )\r\n{\r\n\tm_data = NULL;\r\n\tm_bits_left = 32;\r\n\tm_size = 0;\r\n\tm_cur_val = 0;\r\n\tm_bits_processed = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBitStream::SetInputData( char* data, int size )\r\n{\r\n\tm_data = (unsigned int*) data;\r\n\tm_start_data = m_data;\r\n\tm_size = size;\r\n\tm_bits_left = 0;\r\n\tm_bits_processed = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBitStream::SetOutputData( char* data, int size )\r\n{\r\n\tm_data = (unsigned int*) data;\r\n\tm_start_data = m_data;\r\n\tm_size = size;\r\n\tm_bits_left = 32;\r\n\tm_bits_processed = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tBitStream::GetByteLength( void )\r\n{\r\n\treturn (( m_bits_processed + 7 ) >> 3 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBitStream::WriteValue( int value, int num_bits )\r\n{\r\n\tm_bits_processed += num_bits;\r\n\t\r\n\t// If we cannot fit all bits into our current int, we'll have to span it over\r\n\t// two ints\r\n\tif( m_bits_left < num_bits )\r\n\t{\r\n\t\t// Write out the first portion, then advance to the next int\r\n\r\n        // First clear all top (unwritten) bits\r\n\t\tm_cur_val &= ( 1 << ( 32 - m_bits_left )) - 1;\r\n\t\t\r\n\t\t// Now write them (without having to mask low bits off)\r\n\t\tm_cur_val |= value << ( 32 - m_bits_left );\r\n\t\tnum_bits -= m_bits_left;\r\n\t\tvalue >>= m_bits_left;\r\n\t\tmemcpy( m_data, &m_cur_val, sizeof( unsigned int ));\r\n\t\tm_data++;\r\n\t\tm_cur_val = 0;\r\n\t\tm_bits_left = 32;\r\n\t}\r\n\r\n    // First clear all top (unwritten) bits\r\n\tm_cur_val &= ( 1 << ( 32 - m_bits_left )) - 1;\r\n\t// Now write them (without having to mask low bits off)\r\n\tm_cur_val |= value << ( 32 - m_bits_left );\r\n\tm_bits_left -= num_bits;\r\n\t\r\n\t// Flush bits if full\r\n\tif( m_bits_left == 0 )\r\n\t{\r\n\t\tmemcpy((char*) m_data, (char*) &m_cur_val, sizeof( unsigned int ));\r\n\t\tm_data++;\r\n\t\tm_cur_val = 0;\r\n\t\tm_bits_left = 32;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid BitStream::WriteFloatValue( float value )\r\n{\r\n\tWriteValue( *(int*) &value, sizeof( float ) * 8 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid BitStream::Flush( void )\r\n{\r\n\t// Only flush if we have bits to flush\r\n\tif( m_bits_left != 32)\r\n\t{\r\n\t\tmemcpy( m_data, &m_cur_val, sizeof( unsigned int ));\r\n\t\tm_data++;\r\n\t\tm_cur_val = 0;\r\n\t\tm_bits_left = 32;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\t\tBitStream::ReadFloatValue( void )\r\n{\r\n\tfloat res;\r\n\tint num_bits;\r\n\t\r\n\tnum_bits = 32;\r\n\tm_bits_processed += num_bits;\r\n\r\n\t// If we're all out of bits (like at start), read a full word\r\n\tif( m_bits_left == 0 )\r\n\t{\r\n\t\tmemcpy( &m_cur_val, m_data, sizeof( unsigned int ));\r\n\t\tm_data++;\r\n\t\tm_bits_left = 32;\r\n\t}\r\n\t\r\n\t// Do we hold all bits requested?\r\n\tif( m_bits_left >= num_bits )\r\n\t{\r\n\t\t// Yes, easy peasy case\r\n\t\tm_bits_left -= num_bits;\r\n\t\tif( num_bits == 32 )\r\n\t\t{\r\n\t\t\tmemcpy( &res, &m_cur_val, sizeof( float ));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tunsigned int int_val;\r\n\r\n\t\t\tint_val = m_cur_val & ((1 << num_bits) - 1);\r\n\t\t\tmemcpy( &res, &int_val, sizeof( float ));\r\n\t\t}\r\n\t\t\r\n\t\tm_cur_val >>= num_bits;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tunsigned int int_val;\r\n\t\t// Nope, grab those we have and fetch more from stream\r\n\r\n\t\tint_val = m_cur_val & (( 1 << m_bits_left ) - 1);\r\n\t\tnum_bits -= m_bits_left;\r\n\t\tmemcpy( &m_cur_val, m_data, sizeof( unsigned int ));\r\n\t\tm_data++;\r\n\t\tint_val |= ( m_cur_val & (( 1 << num_bits ) - 1)) << m_bits_left;\r\n\t\tm_cur_val >>= num_bits;\r\n\t\tm_bits_left = 32 - num_bits;\r\n\r\n\t\tmemcpy( &res, &int_val, sizeof( float ));\r\n\t}\r\n\t\r\n\treturn res;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nunsigned int\tBitStream::ReadUnsignedValue( int num_bits )\r\n{\r\n\tunsigned long res;\r\n\t\r\n\tDbg_Assert(( num_bits >= 0 ) && ( num_bits <= 32 ));\r\n   \r\n\tm_bits_processed += num_bits;\r\n\r\n\t// If we're all out of bits (like at start), read a full word\r\n\tif( m_bits_left == 0 )\r\n\t{\r\n\t\tmemcpy( &m_cur_val, m_data, sizeof( unsigned int ));\r\n\t\tm_data++;\r\n\t\tm_bits_left = 32;\r\n\t}\r\n\t\r\n\t// Do we hold all bits requested?\r\n\tif( m_bits_left >= num_bits )\r\n\t{\r\n\t\t\t\t// Yes, easy peasy case\r\n\t\tm_bits_left -= num_bits;\r\n\t\tif( num_bits == 32 )\r\n\t\t{\r\n\t\t\tres = m_cur_val;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tres = m_cur_val & ((1 << num_bits) - 1);\r\n\t\t}\r\n\t\t\r\n\t\tm_cur_val >>= num_bits;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Nope, grab those we have and fetch more from stream\r\n\t\tres = m_cur_val & (( 1 << m_bits_left ) - 1);\r\n\t\tnum_bits -= m_bits_left;\r\n\t\tmemcpy( &m_cur_val, m_data, sizeof( unsigned int ));\r\n\t\tm_data++;\r\n\t\tres |= ( m_cur_val & (( 1 << num_bits ) - 1)) << m_bits_left;\r\n\t\tm_cur_val >>= num_bits;\r\n\t\tm_bits_left = 32 - num_bits;\r\n\t}\r\n\t\r\n\treturn res;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tBitStream::ReadSignedValue( int num_bits )\r\n{\r\n\tlong res;\r\n\r\n\tDbg_Assert(( num_bits >= 0 ) && ( num_bits <= 32 ));\r\n\r\n\t// Cheasy call to that other function for simplicity\r\n\tres = ReadUnsignedValue( num_bits );\r\n\r\n\t// Sign extend result if sign bit set\r\n\tif( res & ( 1 << ( num_bits - 1 )))\r\n\t{\r\n\t\tres |= ~(( 1 << num_bits ) - 1 );\r\n\t}\r\n\r\n\treturn res;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\t// namespace Net"
  },
  {
    "path": "Code/Gel/Net/net.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNET  (Net)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/net.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t01/29/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __NET_H__\r\n#define __NET_H__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/list.h>\r\n#include <core/task.h>\r\n#include <core/singleton.h>\r\n#include <core/thread.h>\r\n#include <core/support/ref.h>\r\n\r\n#include <sys/timer.h>\r\n\r\n#if __PLAT_NGPS__\r\n#include <sifrpc.h>        /* For sceSifInitRpc()                    */\r\n#include <sifdev.h>        /* For sceSifLoadModule()                 */\r\n\r\n#include \"sntypes.h\"       /* SN Systems types                       */\r\n#include \"sneeutil.h\"      /* SN Systems PS2 EE Utilites (General)   */\r\n#include \"snsocket.h\"      /* SN Systems socket API header file      */\r\n#include \"sntcutil.h\"      /* SN Systems PS2 EE Utilites (TCP/IP)    */\r\n#endif\t// __PLAT_NGPS__\r\n\r\n#ifdef __PLAT_WN32__\r\n#include <winsock2.h>\r\n#endif // __PLAT_WN32__\r\n\r\n#ifdef __PLAT_XBOX__\r\n#include <xtl.h>\r\n#include <winsockx.h>\r\n#endif // __PLAT_XBOX__\r\n\r\n#ifdef __PLAT_NGC__\r\n//// GameCube only.\r\n//#include <sys/ngc/p_hw.h>\r\n//#include \"sys/ngc/p_dl.h\"\r\n//#include \"sys/ngc/p_scene.h\"\r\n//#include \"sys/ngc/p_slerp.h\"\r\n//#include \"sys/ngc/p_vector.h\"\r\n//#include \"sys/ngc/p_matrix.h\"\r\n//#include \"sys/ngc/p_texman.h\"\r\n#include <dolphin/socket.h>\r\n#define NsWorldSector\tNsDL\r\n#define gethostbyname(name) SOGetHostByName(name)\r\n#define gethostname(name,namelen) 0\r\n#define inet_addr(cp) 0\r\n#define inet_aton(cp,addr) SOInetAtoN(cp, addr)\r\n#define inet_ntoa(in) SOInetNtoA(in)\r\n#define in_addr SOInAddr\r\n#define sockaddr_in SOSockAddrIn\r\n#define sockaddr SOSockAddr\r\n#define AF_INET         SO_PF_INET              /* internetwork: UDP, TCP, etc. */\r\n#define PF_INET         AF_INET\r\n#define htonl(l)        SOHtoNl(l)\r\n#define ntohl(l)        SONtoHl(l)\r\n#define htons(s)        SOHtoNs(s)\r\n#define ntohs(s)        SONtoHs(s)\r\n#define sin_family family\r\n#define sin_port port\r\n#define sin_addr addr\r\n#define sin_zero zero\r\n#define s_addr addr\r\n#define INADDR_ANY\tSO_INADDR_ANY\r\n#define IPPROTO_UDP 0\r\n\r\n#define accept(s,addr,addrlen) SOAccept(s,addr)\r\n#define bind(s,addr,addrlen) SOBind(s,addr)\r\n#define closesocket(s) SOClose(s)\r\n#define connect(s,addr,addrlen) SOConnect(s,addr)\r\n#define getpeername(s,addr,addrlen) SOGetPeerName(s,addr)\r\n#define getsockname(s,addr,addrlen) SOGetSockName(s,addr)\r\n#define getsockopt(s,level,optname,optval,optlen) SOGetSockOpt(s,level,optname,optval)\r\n#define listen(s,backlog) SOListen(s,backlog)\r\n#define recv(s,buf,len,flags) SORecv(s,buf,len,flags)\r\n#define recvfrom(s,buf,len,flags,from,fromlen) SORecvFrom(s,buf,len,flags,from)\r\n#define recvmsg(s,msg,flags) 0\r\n#define select(nfds,readfs,writefs,exceptfs,timeout) 0\r\n#define send(s,buf,len,flags) SOSend(s,buf,len,flags)\r\n#define sendmsg(s,msg,flags) 0\r\n#define sendto(s,buf,len,flags,to,tolen) SOSendTo(s,buf,len,flags,to)\r\n#define setsockopt(s,level,optname,optval,optlen) SOSetSockOpt(s,level,optname,optval)\r\n#define shutdown(s,how) SOShutdown(s,how)\r\n#define sockAPIinit(maxthreads) 0\r\n#define sockAPIreinit() 0\r\n#define sockAPIregthr() 0\r\n#define sockAPIderegthr() 0\r\n#define socket(af,type,protocol) SOSocket(af,type,protocol)\r\n\r\n\r\n#define ENOBUFS         1\r\n#define ETIMEDOUT       2\r\n#define EISCONN         3\r\n#define EOPNOTSUPP      4\r\n#define ECONNABORTED    5\r\n#define EWOULDBLOCK     6\r\n#define ECONNREFUSED    7\r\n#define ECONNRESET      8\r\n#define ENOTCONN        9\r\n#define EALREADY        10\r\n#define EINVAL          11\r\n#define EMSGSIZE        12\r\n#define EPIPE           13\r\n#define EDESTADDRREQ    14\r\n#define ESHUTDOWN       15\r\n#define ENOPROTOOPT     16\r\n#define EHAVEOOB        17\r\n#define ENOMEM          18\r\n#define EADDRNOTAVAIL   19\r\n#define EADDRINUSE      20\r\n#define EAFNOSUPPORT    21\r\n#define EINPROGRESS     22\r\n#define ELOWER          23\r\n#define EBADF           24\r\n\r\n#define SOCK_STREAM     1               /* stream socket */\r\n#define SOCK_DGRAM      2               /* datagram socket */\r\n\r\n#define SO_DEBUG        0x0001          /* turn on debugging info recording */\r\n#define SO_ACCEPTCONN   0x0002          /* socket has had listen() */\r\n#define SO_REUSEADDR    0x0004          /* allow local address reuse */\r\n#define SO_KEEPALIVE    0x0008          /* keep connections alive */\r\n#define SO_DONTROUTE    0x0010          /* just use interface addresses */\r\n#define SO_BROADCAST    0x0020          /* permit sending of broadcast msgs */\r\n#define SO_USELOOPBACK  0x0040          /* bypass hardware when possible */\r\n#define SO_LINGER       0x0080          /* linger on close if data present */\r\n#define SO_OOBINLINE    0x0100          /* leave received OOB data in line */\r\n\r\n/* Additional options not kept in so_options */\r\n\r\n#define SO_SNDBUF       0x1001          /* send buffer size */\r\n#define SO_RCVBUF       0x1002          /* receive buffer size */\r\n#define SO_SNDLOWAT     0x1003          /* send low-water mark */\r\n#define SO_RCVLOWAT     0x1004          /* receive low-water mark */\r\n#define SO_SNDTIMEO     0x1005          /* send timeout */\r\n#define SO_RCVTIMEO     0x1006          /* receive timeout */\r\n#define SO_ERROR        0x1007          /* get error status and clear */\r\n#define SO_TYPE         0x1008          /* get socket type */\r\n\r\n#define SO_HOPCNT       0x1009          /* Get hop count to destination */\r\n#define SO_MAXMSG       0x1010          /* Get TCP_MSS (max segment size) */\r\n\r\n/* Option extensions */\r\n\r\n#define SO_RXDATA       0x1011          /* Get count of received bytes */\r\n#define SO_MYADDR       0x1012          /* Get local IP address */\r\n#define SO_NBIO         0x1013          /* Set socket non-blocking */\r\n#define SO_BIO          0x1014          /* Set socket blocking */\r\n#define SO_NONBLOCK     0x1015          /* Set/get blocking state */\r\n\r\n#define MSG_OOB         0x1             /* process out-of-band data */\r\n#define MSG_PEEK        0x2             /* peek at incoming message */\r\n#define MSG_DONTROUTE   0x4             /* send without using routing tables */\r\n#define MSG_DONTWAIT    0x20            /* this message should be nonblocking */\r\n\r\n#define SD_RECEIVE  0\r\n#define SD_SEND     1\r\n#define SD_BOTH     2\r\n#endif // __PLAT_NGC__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __PLAT_NGPS__\r\n#define vBASE_SOCKET_THREAD_ID\t0x110\r\n\r\n#define vSOCKET_THREAD_PRIORITY\t10\r\n#define vMAIN_THREAD_PRIORITY\t11\r\n\r\n#define vSOCKET_THREAD_STACK_SIZE\t( 8 * 1024 )\r\n#define vMODEM_THREAD_STACK_SIZE\t( 12 * 1024 )\r\n#endif\r\n\r\n#ifndef SOCKET_ERROR\r\n#\tdefine SOCKET_ERROR -1\r\n#endif\r\n\r\n#ifndef INVALID_SOCKET\r\n#\tdefine INVALID_SOCKET -1\r\n#endif\r\n\r\n#if( defined( __PLAT_NGPS__ ) || defined( __PLAT_NGC__ ))\r\ntypedef int\tSOCKET;\t// Xbox type SOCKET is defined in winsockx.h.\r\n#endif\r\n\r\n//#define NET_DEBUG_MESSAGES\r\n\r\nnamespace Net\r\n{\r\n\r\n\r\n\r\nenum\r\n{\r\n\tMSG_ID_PING_TEST\t\t\t= 1,\t\t// = 1 : Server->Client\r\n\tMSG_ID_PING_RESPONSE,\t\t\t\t\t// = 2 : Client->Server\r\n\tMSG_ID_CONNECTION_REQ,\t\t\t\t\t// = 3 : Client->Server\r\n\tMSG_ID_CONNECTION_ACCEPTED,\t\t\t\t// = 4 : Server->Client\r\n\tMSG_ID_CONNECTION_REFUSED,\t\t\t\t// = 5 : Server->Client\r\n\tMSG_ID_CONNECTION_TERMINATED,\t\t\t// = 6 : Server->Client\r\n\tMSG_ID_SEQUENCED,\t\t\t\t\t\t// = 7 : Bi-directional sequenced identifier\r\n\tMSG_ID_ACK,\t\t\t\t\t\t\t\t// = 8 : Bi-directional acknowledgement\r\n\tMSG_ID_TIMESTAMP,\t\t\t\t\t\t// = 9 : Server->Client\r\n\tMSG_ID_ALIAS,\t\t\t\t\t\t\t// = 10 : Client->Server New alias request\r\n\tMSG_ID_DISCONN_REQ,\t\t\t\t\t\t// = 11 : Client->Server Request to disconnect\r\n\tMSG_ID_DISCONN_ACCEPTED,\t\t\t\t// = 12 : Server->Client Go ahead and quit\r\n\tMSG_ID_KEEPALIVE,\t\t\t\t\t\t// = 13 : Bi-directional general keepalive message\t\t\r\n\tMSG_ID_STREAM_START,\t\t\t\t\t// = 14 : Bi-directional general stream start message\r\n\tMSG_ID_STREAM_DATA,\t\t\t\t\t\t// = 15 : Bi-directional general stream data message\r\n\tMSG_ID_SERVER_RESPONSE,\t\t\t\t\t// = 16 : Server->Client\r\n\tMSG_ID_FIND_SERVER,\t\t\t\t\t\t// = 17 : Client->Server Broadcast\r\n\r\n\tMSG_ID_USER\t\t\t\t\t= 32,\t\t// Game-Specific messages start here\r\n};\r\n\r\nenum\r\n{\r\n\tGROUP_ID_DEFAULT,\r\n\tGROUP_ID_LATENCY_TESTS,\r\n\tGROUP_ID_STREAMS,\r\n};\r\n\r\n#define MAX_NET_MSG_ID\t255\r\n#define MAX_MSG_IDS\t\t256\r\n#define MAX_SEQ_GROUPS\t256\r\n#define MAX_LEN_APP_NAME 64\r\n#define MAX_STREAM_CHUNK_LENGTH\t256\r\n#define MAX_STREAM_LENGTH (Net::Conn::vREAD_BUFFER_LENGTH)\r\n#define MAX_UDP_PACKET_SIZE 1300\r\n#define vUDP_PACKET_OVERHEAD 28 // 20 for IPv4 header, 8 for UDP Header\r\n\r\n#define NET_NUM_LATENCY_TESTS\t10\r\n\r\nenum\r\n{\r\n\tHANDLE_ID_EXCLUDE_BROADCAST\t= 0x80,\t// Or this with a handle ID and it will send to all\r\n\t\t\t\t\t\t\t\t\t\t// handles except that id\r\n\tHANDLE_ID_BROADCAST \t\t= 255,\r\n};\r\n\r\nenum\r\n{\r\n\tvNO_ALIAS  \t\t= 255,\r\n\tvNUM_ALIASES\t= 255,\r\n\tvALIAS_DURATION = 2000\t// number of ms before an alias expires (2 seconds)\r\n};\r\n\r\nenum\r\n{\r\n\tLOWEST_PRIORITY = 0,\r\n\tNORMAL_PRIORITY\t= 128,\r\n\tHIGHEST_PRIORITY = 255\r\n};\r\n\r\n// MSG_HANDLER_FLAGS\r\nenum\r\n{\r\n\tmHANDLE_FOREIGN \t\t= 0x0001,\r\n\tmHANDLE_LATE\t\t\t= 0x0002,\r\n\tmHANDLE_CRC_MISMATCH\t= 0x0004,\r\n};\r\n\r\nenum\r\n{\r\n\tHANDLER_ERROR,\r\n\tHANDLER_CONTINUE,\r\n\tHANDLER_HALT,\r\n\tHANDLER_MSG_DONE,\r\n\tHANDLER_MSG_DESTROYED,\r\n};\r\n\t\r\ntypedef enum\r\n{\r\n\tQUEUE_DEFAULT,\r\n\tQUEUE_IMPORTANT,\r\n\tQUEUE_SEQUENCED\r\n\r\n} QUEUE_TYPE;\r\n\r\nenum ConnType\r\n{\r\n\tvCONN_TYPE_NONE,\r\n\tvCONN_TYPE_MODEM,\r\n\tvCONN_TYPE_ETHERNET,\r\n\tvCONN_TYPE_PPPOE\r\n};\r\n\r\nenum DeviceType\r\n{\r\n\tvDEV_TYPE_NONE,\r\n\tvDEV_TYPE_USB_ETHERNET,\r\n\tvDEV_TYPE_USB_MODEM,\r\n\tvDEV_TYPE_PC_ETHERNET,\r\n\tvDEV_TYPE_SONY_MODEM,\r\n};\r\n\r\nenum\r\n{\r\n\tvMODEM_CONNECT_TIMEOUT\t\t= 60,\t// seconds\r\n\tvMODEM_DISCONNECT_TIMEOUT\t= 10,\t// seconds\r\n\tvMODEM_RESET_TIMEOUT\t\t= 10,\t// seconds\r\n};\r\n\r\nenum\r\n{\r\n\tvRES_SUCCESS,\r\n\tvRES_ERROR_GENERAL,\r\n\tvRES_ERROR_UNKNOWN_DEVICE,\r\n\tvRES_ERROR_INVALID_IRX,\r\n\tvRES_ERROR_DEVICE_NOT_CONNECTED,\r\n\tvRES_ERROR_DEVICE_NOT_HOT,\r\n\tvRES_ERROR_DHCP,\r\n\tvRES_ERROR_DEVICE_CHANGED,\r\n};\r\n\r\nenum\r\n{\r\n\tvMODEM_STATE_DIALING,\r\n\tvMODEM_STATE_CONNECTED,\r\n\tvMODEM_STATE_LOGGED_IN,\r\n\tvMODEM_STATE_DISCONNECTING,\r\n\tvMODEM_STATE_HANGING_UP,\r\n\tvMODEM_STATE_DISCONNECTED,\r\n\tvMODEM_STATE_READY_TO_TRANSMIT,\r\n\tvMODEM_STATE_ERROR,\r\n};\r\n\r\nenum\r\n{\r\n\tmMSG_SIZE_UNKNOWN = 0x01\r\n};\r\n\r\nclass App;\r\nclass Server;\r\nclass Client;\r\nclass Conn;\r\nclass Manager;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n// STANDARD NET MESSAGES\r\nclass MsgMax\r\n{\r\npublic:\r\n\tchar\tm_Data[4096];\r\n};\r\n\r\nclass MsgTimestamp\r\n{\r\npublic:\r\n\tunsigned int m_Timestamp;\r\n};\r\n\r\nclass MsgPacketStamp\r\n{\r\npublic:\r\n\t//unsigned char  m_Handle;\r\n\tunsigned short m_Packetstamp;\r\n};\r\n\r\ntypedef MsgPacketStamp\tMsgAck;\r\n\r\nclass MsgAlias\r\n{\r\npublic:\r\n\tunsigned char\tm_Alias;\r\n\tint\t\t\t\tm_ObjId;\r\n\tint\t\t\t\tm_Expiration;\t// Frame of expiration\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass MsgStreamStart\r\n{\r\npublic:\r\n\tchar\tm_StreamDesc[32];\r\n\tint\t\tm_Size;\r\n\tunsigned int\tm_StreamId;\r\n\tuint32\tm_Checksum;\r\n\tunsigned char\tm_MsgId;\r\n\tchar\tm_Data[ MAX_STREAM_CHUNK_LENGTH ];\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass MsgStreamData\r\n{\r\npublic:\r\n\tunsigned int\tm_StreamId;\r\n\tchar\t\t\tm_Data[ MAX_STREAM_CHUNK_LENGTH ];\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass StreamDesc\r\n{\r\npublic:\r\n\tStreamDesc( void );\r\n\t~StreamDesc( void );\r\n\tint\t\t\tm_Size;\r\n\tunsigned int\tm_StreamId;\r\n\tunsigned char\t\tm_MsgId;\r\n\tchar\t\tm_StreamDesc[32];\r\n\tchar*\t\tm_Data;\r\n\tchar* \t\tm_DataPtr;\r\n\tunsigned char\tm_GroupId;\r\n\tunsigned int\tm_SequenceId;\r\n\tuint32\t\tm_Checksum;\r\n\tbool\t\tm_SendInPlace;\r\n};\r\n\r\nclass StreamLink : public Lst::Node< StreamLink >\r\n{\r\npublic:\r\n\tStreamLink( StreamDesc* desc );\r\n\r\n\tStreamDesc*\tm_Desc;\r\n};\r\n\r\n// NET MESSAGE LINKS\r\nclass QueuedMsg\r\n{\r\npublic:\r\n\tQueuedMsg( unsigned char msg_id, unsigned short msg_len, void* data );\r\n\t~QueuedMsg( void );\r\n\r\n\tunsigned char\tm_MsgId;\r\n\tunsigned short\tm_MsgLength;\r\n\tchar*\t\t\tm_Data;\r\n\tSpt::Ref\t\tm_Ref;\r\n};\r\n\r\nclass QueuedMsgSeq\r\n{\r\npublic:\r\n\tQueuedMsgSeq( unsigned char msg_id, unsigned short msg_len, void* data, unsigned char group_id );\r\n\t~QueuedMsgSeq( void );\r\n\r\n\tunsigned char\tm_MsgId;\r\n\tunsigned short\tm_MsgLength;\r\n\tchar*\t\t\tm_Data;\r\n\tchar\t\t\tm_GroupId;\r\n\t\r\n\tSpt::Ref\tm_Ref;\r\n};\r\n\r\nclass MsgLink : public Lst::Node< MsgLink >\r\n{\r\npublic:\r\n\tMsgLink( QueuedMsg* msg );\r\n\r\n\tQueuedMsg*\t\tm_QMsg;\r\n\tunsigned int\tm_SendTime;\r\n};\r\n\r\nclass MsgImpLink : public Lst::Node< MsgImpLink >\r\n{\t\r\npublic:\r\n\tMsgImpLink( QueuedMsg* msg );\r\n\r\npublic:\r\n\tunsigned int \tm_Timestamp;\r\n\tQueuedMsg*\t\tm_QMsg;\r\n\tunsigned int\tm_Packetstamp;\r\n\tunsigned char\tm_NumResends;\r\n\tunsigned int\tm_SendTime;\r\n};\r\n\r\nclass MsgSeqLink : public Lst::Node< MsgSeqLink >\r\n{\r\npublic:\r\n\tMsgSeqLink( QueuedMsgSeq* msg );\r\n\r\n\tunsigned char\tm_NumResends;\r\n\tunsigned char\tm_GroupId;\r\n\tchar\t\t\tm_StreamMessage;\t// boolean\r\n\tunsigned int\tm_Packetstamp;\r\n\tunsigned int \tm_Timestamp;\r\n\tunsigned int\tm_SequenceId;   \r\n\tunsigned int\tm_SendTime;\r\n\r\n\tQueuedMsgSeq*\tm_QMsg;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass AliasEntry\r\n{\r\npublic:\r\n\tint\tm_Id;\t\t\t// full id of aliased object\r\n\tint m_Expiration;\t// frame of expiration\r\n};\r\n\r\nclass MsgHandlerContext\r\n{\r\npublic:\r\n\t\r\n\tchar*\t\t\tm_Msg;\r\n\tunsigned char\tm_MsgId;\r\n\tunsigned long   m_MsgLength;\r\n\tApp*\t\t\tm_App;\r\n\tConn*\t\t\tm_Conn;\r\n\tint\t\t\t\tm_PacketFlags;\r\n\tvoid*\t\t\tm_Data;\r\n};\r\n\r\ntypedef int\t(MsgHandlerCode)( MsgHandlerContext *context );\r\n\r\nclass MsgHandler : public Lst::Node< MsgHandler >\r\n{\r\n\tfriend class Dispatcher;\r\n\tfriend class Server;\r\n\tfriend class Client;\r\n\r\npublic:\r\n\tMsgHandler( MsgHandlerCode *code, int flags = 0, \r\n\t\t\t\t\t\tvoid *data = NULL, int pri = NORMAL_PRIORITY );\r\n\r\nprivate:\r\n\tMsgHandlerCode\t*m_code;\r\n\tvoid\t\t\t*m_data;\r\n\tint\t\t\t\tm_flags;\r\n\t\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass LatencyTest\r\n{\r\npublic:\r\n\r\n\tLatencyTest ();\r\n\r\n\tvoid\tInputLatencyValue( int latency );\r\n\r\n\tint\t\t\t\tm_AveLatency;\r\n\tunsigned int\tm_TimeTests[NET_NUM_LATENCY_TESTS];\r\n\tunsigned int\tm_CurrentTest;\r\n\tunsigned int\tm_SendTime;\r\n\tunsigned int\tm_ReceiveTime;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  PacketInfo  : public Spt::Class\r\n{\t\r\npublic:\r\n\tint\t\t\tGetNumBytes( void );\r\n\tint\t\t\tGetTime( void );\r\n\r\n\tvoid\t\tSetNumBytes( int size );\r\n\tvoid\t\tSetTime( int time );\r\n\r\nprivate:\r\n\tint\t\t\tm_num_bytes;\r\n\tint\t\t\tm_time;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  Metrics  : public Spt::Class\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvNUM_BUFFERED_PACKETS = 256\r\n\t};\r\n\r\n\t\t\t\tMetrics( void );\r\n\r\n\tvoid\t\tCalculateBytesPerSec( int cur_time );\r\n\tint\t\t\tGetBytesPerSec( void );\r\n\t\r\n\tint\t\t\tGetTotalBytes( void );\r\n\tint\t\t\tGetTotalMessageData( int msg_id );\r\n\tint\t\t\tGetTotalNumMessagesOfId( int msg_id );\r\n\t\t\r\n\tvoid\t\tAddPacket( int size, int time );\r\n\tvoid\t\tAddMessage( int msg_id, int size );\r\n    \r\nprivate:\r\n\r\n\tPacketInfo\tm_packets[ vNUM_BUFFERED_PACKETS ];\r\n\tint\t\t\tm_num_packets;\r\n\t\t\r\n\tint\t\t\tm_num_messages[ MAX_MSG_IDS ];\t\t// total # messages per msg id\r\n\tint\t\t\tm_size_messages[ MAX_MSG_IDS ];\t\t// total # bytes per msg id\r\n\r\n\tint\t\t\tm_total_bytes;\r\n\tint\t\t\tm_bytes_per_sec;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// NET CONNECTION\r\n\r\nclass Conn\r\n{\r\n\tfriend class Client;\r\n\tfriend class Server;\r\n\tfriend class App;\r\n\tfriend class Dispatcher;\r\n\r\nprivate:\r\n\t\r\n\tLst::Head< MsgLink >\tm_normal_msg_list;\r\n\tLst::Head< MsgImpLink >\tm_important_msg_list;\r\n\tLst::Head< MsgSeqLink >\tm_sequenced_msg_list;\r\n\r\n\tfriend\tMsgHandlerCode\thandle_ack;\t\r\n\tfriend\tMsgHandlerCode\thandle_latency_response;\r\n\tfriend\tMsgHandlerCode\thandle_latency_test;\r\n\r\n\tint\t\t\t\tm_handle;\r\n\tint\t\t\t\tm_ip;\r\n\tunsigned short\tm_port;\r\n\t\r\n\tchar*\t\t\tm_write_buffer;\r\n\tchar*\t\t\tm_write_ptr;\r\n\tchar*\t\t\tm_read_buffer;\r\n\tchar*\t\t\tm_read_ptr;\r\n\tint\t\t\t\tm_num_bytes_waiting;\r\n\r\n\t\r\n\tFlags< int >\tm_status;\r\n\tFlags< int >\tm_flags;\r\n    \r\n\tApp*\t\t\tm_app;\t\r\n\tTmr::Time\t\tm_last_comm_time;\t// The last time we've communicated with this connection\r\n    int\t\t\t\tm_last_send_time;\r\n\tint\t\t\t\tm_send_interval;\r\npublic:\r\n\tenum Status\r\n\t{\r\n\t\tmSTATUS_READY \t\t\t= 0x0001,\r\n\t\tmSTATUS_BUSY\t\t\t= 0x0002,\r\n\t\tmSTATUS_INVALID\t\t\t= 0x0004,\r\n\t\tmSTATUS_DISCONNECTING\t= 0x0008\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n\t\tmLOCAL\t\t= 0x01,\t// local connection: i.e. on this machine\r\n\t\tmREMOTE\t\t= 0x02,\t// remote connection: i.e. on another machine\r\n\t\tmFOREIGN\t= 0x04,\t// foreign connection: i.e. one we don't recognize\r\n\t};\r\n\r\n\tenum\r\n\t{   \r\n\t\tvHANDLE_INVALID\t= 0,\r\n\t\tvHANDLE_FIRST \t= 1,\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n#ifdef __PLAT_WN32__\r\n\t\tvREAD_BUFFER_LENGTH = 10*MAX_UDP_PACKET_SIZE // Used to be 2048\r\n#else\r\n\t\tvREAD_BUFFER_LENGTH = 2*MAX_UDP_PACKET_SIZE // Used to be 2048\r\n#endif\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n\t\tvBROADBAND,\r\n\t\tvNARROWBAND,\r\n\t\tvLAN,\r\n\t};\r\n\r\n\tConn( int flags );\r\n\t~Conn( void );\r\n\r\n\tvoid\t\t\tDestroyAllMessageData( void );\r\n    void\t\t\tAckAllMessages( void );\r\n\tvoid\t\t\tDestroyMessageQueues( void );\r\n\tvoid\t\t\tDestroyImportantMessageQueues( void );\r\n\r\n\tint\t\t\t\tGetHandle( void );\r\n\tunsigned short\tGetPort( void );\r\n\tint\t\t\t\tGetIP( void );\r\n\tint\t\t\t\tGetResendThreshold( void );\r\n\tTmr::Time\t\tGetLastCommTime( void );\r\n\tTmr::Time\t\tGetTimeElapsedSinceCommunication( void );\r\n\tvoid\t\t\tUpdateCommTime( Tmr::Time extra_time = 0 );\r\n\t\r\n\tvoid\t\t\tSetStatus( int status_mask );\r\n\tvoid\t\t\tClearStatus( int status_mask );\r\n\tbool\t\t\tTestStatus( int status_mask );\r\n\tint\t\t\t\tGetStatus( void );\r\n\r\n\tvoid\t\t\tSetIP( int ip );\r\n\tvoid\t\t\tSetPort( unsigned short port );\r\n\r\n\tvoid\t\t\tInvalidate( void );\r\n\tbool\t\t\tIsValid( void );\r\n\tbool\t\t\tIsForeign( void );\r\n\tbool\t\t\tIsLocal( void );\r\n\tbool\t\t\tIsRemote( void );\r\n    \r\n\tvoid\t\t\tSetSendInterval( int interval );\t\t// in milliseconds\r\n\tint\t\t\t\tGetSendInterval( void );\r\n\tvoid\t\t\tSetForceSendThisFrame( bool force_send );\r\n\tbool\t\t\tGetForceSendThisFrame( void );\r\n\tint\t\t\t\tGetBandwidthType( void );\r\n    void\t\t\tSetBandwidthType( int type );\r\n\r\n\tint\t\t\t\tGetAveLatency( void );\r\n\r\n\tMetrics*\t\tGetOutboundMetrics( void );\r\n\tMetrics*\t\tGetInboundMetrics( void );\r\n\r\n\tvoid\t\t\tSetBandwidth( int in_bytes_per_sec );\r\n\tint\t\t\t\tGetBandwidth( void );\r\n\r\n\tvoid\t\t\tClearNumResends( void );\r\n\tint\t\t\t\tGetNumResends( void );\r\n\tvoid\t\t\tFlagMessagesForResending( unsigned int packet_stamp );\r\n\r\n\tint\t\t\t\tGetNumPendingStreamMessages( void );\r\n\r\n\tunsigned int\tm_SequenceId[MAX_SEQ_GROUPS];\t\t\t// per-group, per-client array of 'next' sequence ids\t\t\r\n\tunsigned int\tm_WaitingForSequenceId[MAX_SEQ_GROUPS];\t// per-group, per-client array of 'waiting for' sequence ids\t\t\t\r\n\tunsigned int\tm_NextStreamId;\t\t\t// Next stream id\r\n\tLst::Head< MsgSeqLink >\tm_SequencedBuffer[MAX_SEQ_GROUPS];\t\r\n\tLst::Head< StreamLink > m_StreamInList;\r\n\tLst::Head< StreamLink > m_StreamOutList;\r\n    \r\nprivate:\r\n\tvoid\t\t\tdestroy_pending_sequenced_messages( void );\r\n\r\n\tLatencyTest \tm_latency_test;\r\n\tMetrics\t\t\tm_metrics_in;\r\n\tMetrics\t\t\tm_metrics_out;\r\n\tbool\t\t\tm_force_send_packet;\r\n\tLst::Node< Conn > m_node;\r\n\tConn*\t\t\tm_alias_connection;\r\n\tint\t\t\t\tm_bandwidth_type;\r\n\tunsigned int \tm_latest_packet_stamp;\r\n\tunsigned int \tm_latest_sent_packet_stamp;\r\n\tint\t\t\t\tm_bandwidth;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass Dispatcher\r\n{\t\r\n\tfriend class App;\r\n\r\npublic:\r\n\tDispatcher( App* app ) \r\n\t\t: m_app( app ) {}\r\n\tMsgHandler*\tAddHandler( unsigned char net_msg_id, MsgHandlerCode *code, int flags = 0, \r\n\t\t\t\t\t\tvoid *data = NULL, int pri = NORMAL_PRIORITY );\r\n\tvoid\t\tInit( void );\r\n\tvoid\t\tDeinit( void );\r\n\tint\t\t\tDispatchMsgHandlers( Conn *conn, int flags );\r\n\tint\t\t\tDispatchMessage( MsgHandlerContext *context );\r\n\r\nprivate:\r\n\tLst::Head< MsgHandler > m_handler_list[MAX_NET_MSG_ID];\r\n\tApp*\t\tm_app;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  Manager  : public Spt::Class\r\n{\r\n\t\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvMAX_MSG_NAME_LEN\t= 32,\r\n\t\tvMAX_PACKET_SIZE \t= MAX_UDP_PACKET_SIZE,\r\n\t\tvMIN_PACKET_SIZE\t= 3,\t\t// msg should be sizeof( crc) plus at least 1 byte of data\r\n\t\tvPORT_ANY \t\t\t= 0,\r\n\t\tvSTANDARD_RESEND_THRESHOLD \t= 2000,\t// ms\r\n\t\tvMINIMUM_RESEND_THRESHOLD \t= 500,\t\t// ms\r\n\t\tvMSG_HEADER_LENGTH \t\t\t= 1,\r\n\t\tvMSG_HEADER_LENGTH_WITH_SIZE= 3,\r\n\t\tvMSG_SEQ_HEADER_LENGTH\t= 6,\r\n\t\tvMSG_CRC_LEN = 2,\r\n\t\tvMAX_PAYLOAD = vMAX_PACKET_SIZE - vMSG_CRC_LEN,\r\n\t};\r\n\r\n\tvoid\t\tSetError( int error );\r\n\tint\t\t\tGetLastError( void );\r\n\r\n\tbool\t\tConnectToInternet( void );\r\n\tbool\t\tDisconnectFromInternet( void );\r\n\tbool\t\tIsOnline( void );\r\n\r\n\tServer*\t\tCreateNewAppServer( int id, char* appName, int max_clients, unsigned short port, \r\n\t\t\t\t\t\t\t\t\tint address, int flags = 0 );\r\n\tClient*\t\tCreateNewAppClient( int id, char* appName, unsigned short port, int address,\r\n\t\t\t\t\t\t\t\t\tint flags = 0 );\r\n\t\r\n\tvoid\t\tDestroyApp( App *app );\r\n\t\t\r\n\tvoid\t\tSetConnectionType( ConnType conn_type );\r\n\tvoid\t\tSetDeviceType( DeviceType dev_type );\r\n\tvoid\t\tSetPublicIP( unsigned int ip );\r\n\tvoid\t\tSetLocalIP( char* ip );\r\n\tvoid\t\tSetGateway( char* ip );\r\n\tvoid\t\tSetSubnetMask( char* ip );\r\n\tvoid\t\tSetISPPhoneNumber( char* phone_no );\r\n\tvoid\t\tSetISPLogin( char* login );\r\n\tvoid\t\tSetISPPassword( char* password );\r\n\tvoid\t\tSetDHCP( bool use_dhcp );\r\n\tvoid\t\tSetDialupAuthentication( bool authenticate );\r\n\tvoid\t\tSetDNSServer( int index, char* ip );\r\n\tvoid\t\tSetHostName( char* host );\r\n\tvoid\t\tSetDomainName( char* host );\r\n\tConnType\tGetConnectionType( void );\r\n\tDeviceType\tGetDeviceType( void );\r\n\tchar*\t\tGetLocalIP( void );\r\n\tunsigned int\tGetPublicIP( void );\r\n\tchar*\t\tGetGateway( void );\r\n\tchar*\t\tGetSubnetMask( void );\r\n\tchar*\t\tGetDNSServer( int index );\r\n\tchar*\t\tGetISPPhoneNumber( void );\r\n\tchar*\t\tGetHostName( void );\r\n\tchar*\t\tGetDomainName( void );\r\n\tbool\t\tShouldUseDialupAuthentication( void );\r\n\tbool\t\tShouldUseDHCP( void );\r\n\r\n\tServer*\t\tFirstServer( Lst::Search< App > *sh );\r\n\tClient*\t\tFirstClient( Lst::Search< App > *sh );\r\n\tApp*\t\tNextApp( Lst::Search< App > *sh );\r\n\tint\t\t\tNumApps( void );\r\n\r\n\tvoid\t\tSetMessageName( unsigned char msg_id, char* msg_name );\r\n\tchar*\t\tGetMessageName( unsigned char msg_id );\r\n\tvoid\t\tSetMessageFlags( unsigned char msg_id, char flags );\r\n\tchar\t\tGetMessageFlags( unsigned char msg_id );\r\n\r\n\tvoid\t\tAddLogicTasks( App* app );\r\n\tvoid\t\tAddLogicPushTasks( App* app );\r\n\tvoid\t\tRemoveNetworkTasks( App* app );\r\n\r\n\tbool\t\tNeedToTestNetworkEnvironment( void );\r\n\tbool\t\tNetworkEnvironmentSetup( void );\r\n\r\n\tint\t\t\tGetModemState( void );\r\n\tvoid\t\tSetModemState( int state );\r\n\tint\t\t\tGetModemError( void );\r\n\tint\t\t\tGetModemBaudRate( void );\r\n\r\n\tvoid\t\tSetBandwidth( int bytes_per_sec );\r\n\tint\t\t\tGetBandwidth( void );\r\n\r\n\tbool\t\tCanChangeDevices( void );\r\n\t\r\nprotected:\t\r\n\tLst::Head< App >\tm_net_servers;\r\n\tLst::Head< App >\tm_net_clients;\r\n\t\r\nprivate:\r\n\tManager();\r\n\t~Manager();\r\n\r\n#ifdef NET_DEBUG_MESSAGES\r\n\tchar\t\tm_message_names[ MAX_MSG_IDS ][ vMAX_MSG_NAME_LEN ];\t// Text names for each message\r\n#endif\r\n\tchar\t\tm_message_flags[ MAX_MSG_IDS ];\r\n\tConnType\tm_conn_type;\r\n\tDeviceType\tm_device_type;\r\n\tchar\t\tm_local_ip[16];\r\n\tunsigned int\tm_public_ip;\r\n\tchar\t\tm_dns_servers[3][16];\r\n\tchar\t\tm_gateway[16];\r\n\tchar\t\tm_subnet[16];\r\n\tchar\t\tm_isp_phone_no[32];\r\n\tchar\t\tm_isp_user_name[80];\r\n\tchar\t\tm_isp_password[80];\r\n\tchar\t\tm_host_name[32];\r\n\tchar\t\tm_domain_name[32];\r\n\tint\t\t\tm_num_apps;\r\n\tint\t\t\tm_last_error;\r\n\r\n\tbool\t\tm_online;\r\n\tbool\t\tm_use_dhcp;\r\n\tbool\t\tm_use_dialup_auth;\r\n\tint\t\t\tm_modem_state;\r\n\tint\t\t\tm_modem_err;\t\r\n\tint\t\t\tm_modem_baud_rate;\r\n\tint\t\t\tm_bandwidth;\r\n#ifdef __PLAT_NGC__\r\n\tbool\t\tinitialize_ngc( void );\r\n#endif\r\n#ifdef __PLAT_NGPS__\r\n\tbool\t\tinitialize_ps2( void );\r\n\tbool\t\tsn_stack_setup( void );\r\n\tbool\t\tsetup_ethernet_params( void );\r\n\tbool\t\tinitialize_device( void );\r\n\tbool\t\tload_irx_files( void );\r\n\tbool\t\tstart_stack( void );\r\n\tbool\t\tstop_stack( void );\r\n\tbool\t\tm_stack_setup;\r\n\tbool\t\tm_net_drivers_loaded;\r\n\tbool\t\tm_options_changed;\r\n\tbool\t\tm_device_changed;\r\n    \r\n\r\n\t// Sn Modem Setup\r\n\tstatic \tvoid \t\t\tconn_modem_state_callback( sn_int32 modem_state );\r\n\tstatic \tvoid \t\t\tdisconn_modem_state_callback( sn_int32 modem_state );\r\n\tchar\t\t\t\t\tm_modem_thread_stack[ vMODEM_THREAD_STACK_SIZE ]\t__attribute__ ((aligned(16)));\r\n\tstatic \tvoid\t\t\tthreaded_modem_conn( void *data );\r\n\tstatic \tvoid\t\t\tthreaded_modem_disconn( void *data );\r\n\tThread::PerThreadStruct\tm_modem_thread_data;\r\n\tThread::THREADID\t\tm_modem_thread_id;\r\n\r\n#endif // __PLAT_NGPS__\r\n    \r\n\tDeclareSingletonClass( Manager );\r\n};\r\n\r\nclass BitStream\r\n{\r\npublic:\r\n\tBitStream( void );\r\n\r\n\tvoid\t\t\tSetInputData( char* data, int size );\r\n\tvoid\t\t\tSetOutputData( char* data, int size );\r\n\r\n\tvoid\t\t\tWriteValue( int value, int num_bits );\r\n\tvoid\t\t\tWriteFloatValue( float value );\r\n\tvoid \t\t\tFlush( void );\r\n\tfloat\t\t\tReadFloatValue( void );\r\n\tunsigned int\tReadUnsignedValue( int num_bits );\r\n\tint\t\t\t\tReadSignedValue( int num_bits );\r\n\r\n\tint\t\t\t\tGetByteLength( void );\r\n\r\nprivate:\r\n\tunsigned int*\tm_data;\r\n\tunsigned int*\tm_start_data;\r\n\tunsigned int\tm_cur_val;\r\n\tint\t\t\t\tm_bits_left;\r\n\tint\t\t\t\tm_size;\r\n\tint\t\t\t\tm_bits_processed;\r\n};\r\n\r\nclass MsgDesc\r\n{\r\npublic:\r\n\tMsgDesc( void );\r\n\r\n\tunsigned char\tm_Id;\r\n\tchar\t\t\tm_StreamMessage;\t// bool\r\n\tunsigned short\tm_Length;\r\n\tvoid*\t\t\tm_Data;\r\n\tint\t\t\t\tm_Priority;\r\n\tQUEUE_TYPE\t\tm_Queue;\r\n\tunsigned char\tm_GroupId;\r\n    bool\t\t\tm_Singular;\r\n\tint\t\t\t\tm_Delay;\r\n\tunsigned int\tm_ForcedSequenceId;\r\n\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass BannedConn : public Lst::Node< BannedConn >\r\n{\r\npublic:\r\n\tBannedConn( void ) : Lst::Node< BannedConn > ( this ) {}\r\n\tint\tm_Ip;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass App\r\n{\r\nfriend class Manager;\r\n\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tmBROADCAST\t\t\t\t= 0x01,\r\n\t\tmALIAS_SUPPORT\t\t\t= 0x02,\r\n\t\tmDYNAMIC_RESEND\t\t\t= 0x04,\r\n\t\tmLOCAL\t\t\t\t\t= 0x08,\t// Local client (i.e. no real port/address info associated with it)\r\n\t\tmACCEPT_FOREIGN_CONN\t= 0x10,\r\n\t\tmSECURE\t\t\t\t\t= 0x20,\r\n\t};\r\n    \r\n\tApp( int flags = 0 );\r\n\tvirtual\t~App( void );\r\n\r\n\tstatic\tconst\tunsigned int\tMAX_LATENCY;\r\n\ttypedef void\t(ForeignPacketHandlerCode)( char* packet, int len, struct sockaddr* sender );\r\n    \r\n\tConn\t*GetConnectionByHandle( int handle );\r\n\tConn\t*GetConnectionByAddress( int ip, unsigned short port );\r\n\tConn\t*NewConnection( int ip, unsigned short port, int flags = Conn::mREMOTE );\r\n\tvoid\tBanConnection( Conn* conn );\r\n\tbool\tIsConnectionBanned( Conn* conn );\r\n\r\n\tvoid\tStreamMessageToConn( Net::Conn* conn, unsigned char msg_id, unsigned short msg_len, void* data, char* desc, unsigned char group_id = GROUP_ID_DEFAULT,\r\n\t\t\t\t\t\t\t\t bool all_at_once = true, bool send_in_place = false );\r\n\tvoid\tStreamMessage( int handle, unsigned char msg_id, unsigned short msg_len, void* data, char* desc, unsigned char group_id = GROUP_ID_DEFAULT,\r\n\t\t\t\t\t\t   bool all_at_once = true, bool send_in_place = false );\r\n\tvoid\tStreamMessageToServer( unsigned char msg_id, unsigned short msg_len, void* data, char* desc, unsigned char group_id = GROUP_ID_DEFAULT,\r\n\t\t\t\t\t\t\t\t   bool all_at_once = true, bool send_in_place = false );\r\n\tvoid\tEnqueueMessage( int handle, MsgDesc* desc );\r\n\tvoid\tEnqueueMessageToServer( MsgDesc* desc );\r\n\tvoid \tDequeueMessagesByType( Net::Conn* conn, QUEUE_TYPE queue, unsigned char msg_id );\r\n\tvoid\tFreeConnMessageQueue( Conn *conn, QUEUE_TYPE queue );\r\n\tvoid\tFreeMessageQueue( QUEUE_TYPE queue );\r\n\tbool\tBuildMsgStream( Conn *conn, QUEUE_TYPE queue, bool resends_only = false );\r\n\tQueuedMsgSeq*\tAllocateNewSeqMessage( unsigned char msg_id, unsigned short msg_len, char* data, unsigned char group_id );\r\n\tbool\tSendMessageTo( unsigned char msg_id, unsigned short msg_len, void* data,\r\n\t\t\t\t\t\t\tint ip, unsigned short port, int flags );\r\n\tbool\tSendTo( int ip, unsigned short port, char *data, int len, int flags );\r\n\tbool\tSend( char *data, int len, int flags );\r\n\t\r\n\tConn\t*FirstConnection( Lst::Search< Conn > *sh );\r\n\tConn\t*NextConnection( Lst::Search< Conn > *sh );\t\r\n\tvoid\tTerminateConnection( Conn* conn );\r\n\r\n\tManager*\tGetManager( void );\r\n\t\r\n\tint\t\tGetID( void );\r\n\tchar*\tGetName( void );\r\n\r\n\tbool\tIsLocal( void );\r\n\t\r\n\tvoid\tAcceptForeignConnections( bool accept );\r\n\tbool\tAcceptsForeignConnections( void );\r\n\r\n\tbool\tShouldSendThisFrame( Conn* conn );\r\n\tbool\tMessagesToProcess( Conn* conn );\t\r\n\tbool\tMessagesToSend( Conn *conn );\r\n\tbool\tImportantMessagesToSend( Conn* conn );\r\n\r\n\tint\t\tBandwidthUsed( void );\r\n\tbool\tBandwidthExceeded( Conn* conn );\r\n\r\n\tvoid\tReportError( void );\r\n\r\n\tvoid\tAliasConnections( Conn* server_conn, Conn* client_conn );\r\n\r\n\tTsk::BaseTask&\tGetSendDataTask( void );\r\n\tTsk::BaseTask&\tGetReceiveDataTask( void );\r\n\tTsk::BaseTask&\tGetProcessDataTask( void );\r\n\tTsk::BaseTask&\tGetNetworkMetricsTask( void );\r\n\t    \r\n\tvirtual\tvoid\tProcessData( void );\r\n    \r\n\tvoid\t\t\tSendData( bool scheduled_send = false );\r\n\tvirtual\tvoid\tReceiveData( void ) = 0;\t\r\n\r\n\tvoid\tSendEnqueuedMessages( void );\r\n\tvirtual void\tSendEnqueuedMessages( Conn* conn ) = 0;\r\n\t\r\n\tvoid\t\t\tShutDown( void );\r\n    \t\t\r\n\tSOCKET\t\t\tGetSocket( void );\r\n\tvoid\t\t\tSetForeignPacketHandler( ForeignPacketHandlerCode* code );\r\n\r\n\tunsigned int\tm_Timestamp;\r\n\tDispatcher\t\tm_Dispatcher;\r\n\r\n\tunsigned int m_TotalBytesOut;\r\n\tunsigned int m_TotalBytesIn;\r\n\tunsigned int m_LostPackets;\r\n\tunsigned int m_LatePackets;\r\n\tunsigned int m_DupePackets;\r\n\tunsigned int m_FrameCounter;\r\n\r\n#ifdef __PLAT_XBOX__\r\n\tXNADDR\t\tm_XboxAddr;\r\n\tXNKID\t\tm_XboxKeyId;\r\n\tXNKEY\t\tm_XboxKey;\r\n\tBYTE\t\tm_Nonce[8];\r\n#endif\r\n\r\nprotected:\r\n\r\n\tvirtual bool\tinit( void );\r\n\tvirtual\tvoid\tdeinit( void );\r\n\r\n\tbool\t\t\tbind_app_socket( int address, unsigned short port );\r\n\r\n\tLst::Node< App >\tm_node;\r\n\tSOCKET\t\tm_socket;\r\n\tstruct\tsockaddr_in\tm_local_address;\r\n\tbool\tm_connected;\r\n\t\r\n\tManager *m_net_man;\t\r\n\r\n\tTsk::Task< App >*\tm_process_network_data_task;\r\n\tTsk::Task< App >*\tm_send_network_data_task;\r\n\tTsk::Task< App >*\tm_receive_network_data_task;        \r\n\tTsk::Task< App >*\tm_network_metrics_task;\r\n\r\n    void    process_stream_messages( void );\r\n\tvoid\tterminate_invalid_connections( void );\r\n\tvoid\tcrc_and_copy_stream( char* in_stream, char* out_stream, int in_len, int* out_len );\r\n\tbool\tvalidate_and_copy_stream( char* in_stream, char* out_stream, int in_len );\r\n\r\n    int \tm_num_connections;\r\n\tint \tm_max_connections;\r\n\r\n\tstatic\tMsgHandlerCode\thandle_sequenced_messages; \t\r\n\tstatic\tMsgHandlerCode\thandle_connection_request;\r\n\tstatic\tMsgHandlerCode\thandle_connection_accepted;\r\n\tstatic\tMsgHandlerCode\thandle_stream_messages; \t\r\n\r\n\tchar\tm_out_packet_buffer[ Manager::vMAX_PACKET_SIZE ];\r\n\tchar\tm_in_packet_buffer[ Manager::vMAX_PACKET_SIZE ];\r\n\r\n\tFlags< int > m_flags;\r\n\r\n\tForeignPacketHandlerCode*\tm_foreign_handler;\r\n#ifdef __PLAT_NGPS__\r\n\r\npublic:\r\n\tvoid\t\t\tTransferData( void );\r\n\t\r\n\tvoid\t\t\tWaitForAsyncCallsToFinish( void );\r\n\tvoid\t\t\tWaitForTransferSemaphore( void );\r\n\tvoid\t\t\tSignalTransferSemaphore( void );\r\n\r\nprotected:\r\n\tchar\tm_socket_thread_stack[ vSOCKET_THREAD_STACK_SIZE ]\t__attribute__ ((aligned(16)));\r\n\r\n\tbool\tm_socket_thread_active;\r\n\r\n\tThread::THREADID\tm_socket_thread_id;\r\n    \r\n\tint\t\tm_transfer_semaphore_id;\r\n\tint\t\tm_send_semaphore_id;\r\n\tint\t\tm_receive_semaphore_id;\r\n\tint \tm_active_semaphore_id;\r\n\t\r\n\tThread::PerThreadStruct\tm_socket_thread_data;\r\n\t\t\r\n\tstatic \tvoid\tthreaded_transfer_data( void *data );\r\n\r\n\tbool\tm_shutting_down;\r\n#endif // __PLAT_NGPS__\r\n\r\n\tstatic\tTsk::Task< App >::Code\tprocess_network_data;\r\n\tstatic\tTsk::Task< App >::Code\tsend_network_data;\r\n\tstatic\tTsk::Task< App >::Code\tread_network_data;\r\n\tstatic\tTsk::Task< App >::Code\tservice_network_metrics;\r\n    \r\nprivate:\r\n\r\n\tvoid\tprocess_sequenced_messages( Conn *conn );   \r\n    \r\n\tint\tget_free_handle( void );\r\n\t\r\n    Lst::Head< Conn >\t\tm_connections;\r\n\tLst::Head< BannedConn >\tm_banned_connections;\r\n\t\r\n\tint\t\tm_id;\r\n\tchar\tm_name[MAX_LEN_APP_NAME];\r\n\tbool\tm_loop_read;\r\n\tdouble\tm_double_timestamp;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tunsigned short\tConn::GetPort( void )\r\n{\r\n\treturn m_port;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tint\t\tConn::GetIP( void )\r\n{\r\n\treturn m_ip;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tint Conn::GetHandle( void )\r\n{\r\n\treturn m_handle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tint Conn::GetAveLatency( void )\r\n{\r\n\tif( IsLocal())\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\treturn m_latency_test.m_AveLatency;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\tConn::SetIP( int ip )\r\n{\r\n\tm_ip = ip;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\tConn::SetPort( unsigned short port )\r\n{\r\n\tm_port = port;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\tConn::SetStatus( int status_mask )\r\n{\r\n\tm_status.SetMask( status_mask );\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\tConn::ClearStatus( int status_mask )\r\n{\r\n\tm_status.ClearMask( status_mask );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\tConn::TestStatus( int status_mask )\r\n{\r\n\treturn m_status.TestMask( status_mask );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline int\t\tConn::GetStatus( void )\r\n{\r\n\treturn m_status;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tMetrics*\tConn::GetInboundMetrics( void )\r\n{\r\n\treturn &m_metrics_in;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tMetrics*\tConn::GetOutboundMetrics( void )\r\n{\r\n\treturn &m_metrics_out;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n}\t// namespace Net\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __PLAT_XBOX__\r\n// Need this to be outside the Net:: namespace...\r\ninline char* inet_ntoa( struct in_addr addr )\r\n{\r\n\tIN_ADDR\t\tin_a;\r\n\tin_a.S_un\t= addr.S_un;\r\n\r\n\tconst int\tSTRING_BUFFER_SIZE = 100;\r\n//\tstatic char\tstring_buffer[STRING_BUFFER_SIZE];\r\n//\tint\t\t\trv = XNetInAddrToString( in_a, string_buffer, STRING_BUFFER_SIZE );\r\n\r\n\t// Cheesy hack for now.\r\n\tstatic char\tstring_buffer[STRING_BUFFER_SIZE] = \"0.0.0.0\";\r\n\r\n\treturn string_buffer;\r\n}\r\n#endif\r\n\r\n#endif // __NET_H__\r\n\r\n"
  },
  {
    "path": "Code/Gel/Net/netconn.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNet (OBJ) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tnetconn.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t08/09/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNetwork Connection code\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <stdlib.h>\r\n#include <string.h>\r\n\r\n#include <gel/net/net.h>\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Net\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nConn::Conn( int flags )\r\n: m_node( this )\r\n{\r\n\tm_flags = flags;\r\n\tm_status.ClearAll();\r\n\tm_status.SetMask( mSTATUS_READY );\r\n\tm_read_buffer = new char[ vREAD_BUFFER_LENGTH ];\t\r\n\tm_read_ptr = m_read_buffer;\r\n\tm_write_buffer = new char[ Manager::vMAX_PACKET_SIZE ];\r\n\tm_write_ptr = m_write_buffer;\r\n\tm_send_interval = 0;\r\n\tm_last_send_time = 0;\r\n\tm_force_send_packet = false;\r\n\tm_alias_connection = NULL;\r\n\tm_latest_packet_stamp = 0;\r\n\tm_latest_sent_packet_stamp = 0;\r\n#ifdef __PLAT_NGPS__\r\n\tm_bandwidth = 4200;\t// Start with a 33.6kbps modem's payload threshold (i.e. including packet overhead)\r\n#else\r\n\tm_bandwidth = 400000;\t// On xbox, just assume broadband\r\n#endif\r\n\t\r\n\tm_NextStreamId = 0;\r\n\tmemset( m_SequenceId, 0, MAX_SEQ_GROUPS );\t\r\n\tmemset( m_WaitingForSequenceId, 0, MAX_SEQ_GROUPS );\r\n#ifdef\t__PLAT_NGPS__\t\t\t\t\t\t\t\t\t\t\t  \r\n\tDbg_MsgAssert(Mem::SameContext(this,Mem::Manager::sHandle().NetworkHeap()),(\"Conn not on network heap\"));\t\r\n#endif\t\t//\t__PLAT_NGPS__\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nConn::~Conn( void )\r\n{\r\n\tDestroyAllMessageData();\r\n    \r\n\tdelete [] m_read_buffer;\r\n\tdelete [] m_write_buffer;\r\n}\r\n\r\n/******************************************************************/\r\n/*  Destroy pending sequenced messages\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \tConn::destroy_pending_sequenced_messages( void )\r\n{\r\n\tint i;\r\n\tLst::Search< MsgSeqLink > sh;\r\n    MsgSeqLink *msg_link, *next;\r\n    \r\n\t\r\n\r\n    for( i = 0; i < MAX_SEQ_GROUPS; i++ )\r\n\t{\r\n        for( msg_link = sh.FirstItem( m_SequencedBuffer[i] );\r\n\t\t\t\tmsg_link; msg_link = next )\r\n\t\t{\r\n\t\t\tnext = sh.NextItem();\r\n\t\t\t\r\n\t\t\tdelete msg_link->m_QMsg;\r\n\t\t\tdelete msg_link;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tConn::DestroyAllMessageData( void )\r\n{\r\n\tdestroy_pending_sequenced_messages();\r\n\r\n\tAckAllMessages();\r\n\tDestroyMessageQueues();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tConn::DestroyMessageQueues( void )\r\n{\r\n\tint i;\r\n\tLst::Search< MsgLink >\tmsg_sh;\r\n\tLst::Search< MsgImpLink >\timp_sh;\r\n\tLst::Search< MsgSeqLink >\tseq_sh;\r\n\tLst::Search< StreamLink > stream_sh;\r\n\r\n\tMsgLink *msg_link, *next_msg_link;\r\n\tMsgImpLink *imp_link, *next_imp_link;\r\n\tMsgSeqLink *seq_link, *next_seq_link;\r\n\tStreamLink* str_link, *next_str_link;\r\n\r\n\tfor( msg_link = msg_sh.FirstItem( m_normal_msg_list ); msg_link; msg_link = next_msg_link )\r\n\t{\r\n\t\tnext_msg_link = msg_sh.NextItem();\r\n        \r\n\t\tdelete msg_link;\r\n\t}\r\n\r\n\tfor( imp_link = imp_sh.FirstItem( m_important_msg_list ); imp_link; imp_link = next_imp_link )\r\n\t{\r\n\t\tnext_imp_link = imp_sh.NextItem();\r\n\t\t\r\n\t\tdelete imp_link;\r\n\t}\r\n\r\n\tfor( seq_link = seq_sh.FirstItem( m_sequenced_msg_list ); seq_link; seq_link = next_seq_link )\r\n\t{\r\n\t\tnext_seq_link = seq_sh.NextItem();\r\n\t\t\r\n\t\tdelete seq_link;\r\n\t}\r\n\r\n\tfor( i = 0; i < MAX_SEQ_GROUPS; i++ )\r\n\t{\r\n\t\tfor( seq_link = seq_sh.FirstItem( m_SequencedBuffer[i] ); seq_link; seq_link = next_seq_link )\r\n\t\t{\r\n\t\t\tnext_seq_link = seq_sh.NextItem();\r\n\t\t\t\r\n\t\t\tdelete seq_link;\r\n\t\t}\r\n\t}\r\n\r\n\t//Dbg_Printf( \"** Destroying StreamIn list\\n\" );\r\n\tfor( str_link = stream_sh.FirstItem( m_StreamInList ); str_link; str_link = next_str_link )\r\n\t{\r\n\t\tnext_str_link = stream_sh.NextItem();\r\n\r\n\t\tdelete str_link->m_Desc;\r\n\t\tdelete str_link;\r\n\t}\r\n\r\n\t//Dbg_Printf( \"** Destroying StreamOut list\\n\" );\r\n\tfor( str_link = stream_sh.FirstItem( m_StreamOutList ); str_link; str_link = next_str_link )\r\n\t{\r\n\t\tnext_str_link = stream_sh.NextItem();\r\n\r\n\t\tdelete str_link->m_Desc;\r\n\t\tdelete str_link;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tConn::DestroyImportantMessageQueues( void )\r\n{\r\n\tMsgImpLink *msg_imp_link, *next_imp;\r\n\tMsgSeqLink *msg_seq_link, *next_seq;\r\n\tLst::Search< MsgLink > msg_sh;\r\n\tLst::Search< MsgImpLink > imp_sh;\r\n\tLst::Search< MsgSeqLink > seq_sh;\r\n\tQueuedMsg* msg;\r\n\tQueuedMsgSeq* msg_seq;\r\n\t\t\r\n\tfor( msg_imp_link = imp_sh.FirstItem( m_important_msg_list ); \r\n\t\t\tmsg_imp_link; msg_imp_link = next_imp )\r\n\t{\r\n\t\tnext_imp = imp_sh.NextItem();\r\n\t\tmsg = msg_imp_link->m_QMsg;\r\n\t\tmsg->m_Ref.Release();\r\n\t\tif( msg->m_Ref.InUse() == false )\r\n\t\t{\r\n\t\t\tdelete msg;\r\n\t\t}\r\n\t\t\r\n\t\tdelete msg_imp_link;\r\n\t}\t\r\n\r\n\tfor( msg_seq_link = seq_sh.FirstItem( m_sequenced_msg_list ); \r\n\t\t\tmsg_seq_link; msg_seq_link = next_seq )\r\n\t{\r\n\t\tnext_seq = seq_sh.NextItem();\r\n\t\t// ACK the message\r\n\t\tmsg_seq = msg_seq_link->m_QMsg;\r\n\t\tmsg_seq->m_Ref.Release();\r\n\r\n\t\tDbg_Printf( \"*** Destroying seq message %d, still on queue\\n\", msg_seq->m_MsgId );\r\n\t\t// If this message is no longer being referenced, free it\r\n\t\tif( msg_seq->m_Ref.InUse() == false )\r\n\t\t{\r\n\t\t\tdelete msg_seq;\r\n\t\t}\r\n\r\n\t\tdelete msg_seq_link;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tConn::AckAllMessages( void )\r\n{\r\n\tMsgLink* msg_link, *next_msg_link;\r\n\tMsgImpLink *msg_imp_link, *next_imp;\r\n\tMsgSeqLink *msg_seq_link, *next_seq;\r\n\tLst::Search< MsgLink > msg_sh;\r\n\tLst::Search< MsgImpLink > imp_sh;\r\n\tLst::Search< MsgSeqLink > seq_sh;\r\n\tQueuedMsg* msg;\r\n\tQueuedMsgSeq* msg_seq;\r\n\t\t\r\n\tfor( msg_link = msg_sh.FirstItem( m_normal_msg_list ); msg_link; msg_link = next_msg_link )\r\n\t{\r\n\t\tnext_msg_link = msg_sh.NextItem();\r\n\t\tmsg = msg_link->m_QMsg;\r\n\t\tmsg->m_Ref.Release();\r\n\t\tif( msg->m_Ref.InUse() == false )\r\n\t\t{\r\n\t\t\tdelete msg;\r\n\t\t}\r\n\t}\r\n\r\n\tfor( msg_imp_link = imp_sh.FirstItem( m_important_msg_list ); \r\n\t\t\tmsg_imp_link; msg_imp_link = next_imp )\r\n\t{\r\n\t\tnext_imp = imp_sh.NextItem();\r\n\t\tmsg = msg_imp_link->m_QMsg;\r\n\t\tmsg->m_Ref.Release();\r\n\t\tif( msg->m_Ref.InUse() == false )\r\n\t\t{\r\n\t\t\tdelete msg;\r\n\t\t}\r\n\t}\t\r\n\r\n\tfor( msg_seq_link = seq_sh.FirstItem( m_sequenced_msg_list ); \r\n\t\t\tmsg_seq_link; msg_seq_link = next_seq )\r\n\t{\r\n\t\tnext_seq = seq_sh.NextItem();\r\n\t\t// ACK the message\r\n\t\tmsg_seq = msg_seq_link->m_QMsg;\r\n\t\tmsg_seq->m_Ref.Release();\r\n\t\t// If this message is no longer being referenced, free it\r\n\t\tif( msg_seq->m_Ref.InUse() == false )\r\n\t\t{\r\n\t\t\tdelete msg_seq;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nTmr::Time\tConn::GetLastCommTime( void )\r\n{\r\n\tif( IsLocal())\r\n\t{\r\n\t\treturn Tmr::GetTime();\r\n\t}\r\n\treturn m_last_comm_time;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tConn::UpdateCommTime( Tmr::Time extra_time )\r\n{\r\n\tTmr::Time cur_time;\r\n\r\n\tcur_time = Tmr::GetTime();\r\n\tif(( cur_time + extra_time ) > m_last_comm_time )\r\n\t{\r\n\t\tm_last_comm_time = cur_time + extra_time;\r\n\t}\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nTmr::Time\tConn::GetTimeElapsedSinceCommunication( void )\r\n{\r\n\tTmr::Time cur_time;\r\n\r\n\tcur_time = Tmr::GetTime();\r\n\r\n\tif( cur_time < m_last_comm_time )\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\r\n    return cur_time - m_last_comm_time;\r\n}\r\n\r\n/******************************************************************/\r\n/* Used to invalidate a connection. This way, you can defer the   */\r\n/* Destruction of the connection until later, but ignore it now   */\r\n/******************************************************************/\r\n\r\nvoid\tConn::Invalidate( void )\r\n{\r\n\t//Dbg_Message( \"Invalidating Connection\\n\" );\r\n\tClearStatus( mSTATUS_READY );\r\n\tSetStatus( mSTATUS_INVALID );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tConn::IsValid( void )\r\n{\r\n\t\r\n\r\n\treturn( TestStatus( mSTATUS_INVALID ) == false );\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tConn::IsForeign( void )\r\n{\r\n\treturn m_flags.TestMask( mFOREIGN );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tConn::IsLocal( void )\r\n{\r\n\treturn m_flags.TestMask( mLOCAL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tConn::IsRemote( void )\r\n{\r\n\treturn m_flags.TestMask( mREMOTE );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tConn::GetResendThreshold( void )\r\n{\r\n\tint threshold;\r\n\t \r\n\t// Don't resend as often if the client is busy\r\n\tif( TestStatus( mSTATUS_BUSY ))\r\n\t{\r\n\t\treturn Tmr::Seconds( 1 );\r\n\t}\r\n\r\n\t// by default, the resend threshold is two times your average latency\r\n\tthreshold = 2 * GetAveLatency();\r\n\r\n\t// We have a threshold for resending.  So that clients don't spam the server with resends\r\n\t// while he's busy\r\n\tif( threshold < Manager::vMINIMUM_RESEND_THRESHOLD )\r\n\t{\r\n\t\treturn Manager::vMINIMUM_RESEND_THRESHOLD;\r\n\t}\r\n\r\n\treturn threshold;\r\n}\r\n\r\n/******************************************************************/\r\n/* Send every N milliseconds                                  \t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tConn::SetSendInterval( int interval )\r\n{\r\n\tm_send_interval = interval;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tConn::GetSendInterval( void )\r\n{\r\n\treturn m_send_interval;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tConn::SetForceSendThisFrame( bool force_send )\r\n{\r\n\tm_force_send_packet = force_send;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tConn::GetForceSendThisFrame( void )\r\n{\r\n\treturn m_force_send_packet;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tConn::GetNumResends( void )\r\n{\r\n\tMsgImpLink *msg_imp_link;\r\n\tMsgSeqLink *msg_seq_link;\r\n\tLst::Search< MsgImpLink > imp_sh;\r\n\tLst::Search< MsgSeqLink > seq_sh;\r\n\tint highest_num_resends;\r\n    \r\n\t\r\n\r\n\thighest_num_resends = 0;\r\n\r\n\tfor( msg_imp_link = imp_sh.FirstItem( m_important_msg_list ); \r\n\t\t\tmsg_imp_link; msg_imp_link = imp_sh.NextItem())\r\n\t{\r\n\t\tif( msg_imp_link->m_NumResends > highest_num_resends )\r\n\t\t{\r\n\t\t\thighest_num_resends = msg_imp_link->m_NumResends;\r\n\t\t}\r\n\t}\t\r\n\r\n\tfor( msg_seq_link = seq_sh.FirstItem( m_sequenced_msg_list ); \r\n\t\t\tmsg_seq_link; msg_seq_link = seq_sh.NextItem())\r\n\t{\r\n\t\tif( msg_seq_link->m_NumResends > highest_num_resends )\r\n\t\t{\r\n\t\t\thighest_num_resends = msg_seq_link->m_NumResends;\r\n\t\t}\r\n\t}\r\n\r\n\treturn highest_num_resends;\r\n}\r\n\r\n/******************************************************************/\r\n/* Get the number of stream messages still pending for this conn. */\r\n/* If num_pending > our sliding window's size, don't send any more*/\r\n/******************************************************************/\r\n\r\nint\t\tConn::GetNumPendingStreamMessages( void )\r\n{\r\n\tMsgSeqLink *msg_seq_link;\r\n\tLst::Search< MsgSeqLink > seq_sh;\r\n\tint num_pending;\r\n\r\n\tnum_pending = 0;\r\n\tfor( msg_seq_link = seq_sh.FirstItem( m_sequenced_msg_list ); msg_seq_link; msg_seq_link = seq_sh.NextItem())\r\n\t{\r\n\t\tif( msg_seq_link->m_StreamMessage )\r\n\t\t{\r\n\t\t\tnum_pending++;\r\n\t\t}\r\n\t}\r\n\r\n\treturn num_pending;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tConn::ClearNumResends( void )\r\n{\r\n\tMsgImpLink *msg_imp_link;\r\n\tMsgSeqLink *msg_seq_link;\r\n\tLst::Search< MsgImpLink > imp_sh;\r\n\tLst::Search< MsgSeqLink > seq_sh;\r\n\t\r\n\t\r\n\r\n    for( msg_imp_link = imp_sh.FirstItem( m_important_msg_list ); \r\n\t\t\tmsg_imp_link; msg_imp_link = imp_sh.NextItem())\r\n\t{\r\n\t\tmsg_imp_link->m_NumResends = 0;\r\n\t}\t\r\n\r\n\tfor( msg_seq_link = seq_sh.FirstItem( m_sequenced_msg_list ); \r\n\t\t\tmsg_seq_link; msg_seq_link = seq_sh.NextItem())\r\n\t{\r\n\t\tmsg_seq_link->m_NumResends = 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tConn::GetBandwidthType( void )\r\n{\r\n\treturn m_bandwidth_type;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tConn::SetBandwidthType( int type )\r\n{\r\n\tm_bandwidth_type = type;\r\n\t\r\n\t// Some default values for bandwidth limiting\r\n\tswitch( m_bandwidth_type )\r\n\t{\r\n\t\tcase vNARROWBAND:\r\n\t\t\tSetBandwidth( 4200 );\t\r\n\t\t\tbreak;\r\n\t\tcase vBROADBAND:\r\n\t\t\tSetBandwidth( 400000 );\r\n\t\t\tbreak;\r\n\t\tcase vLAN:\r\n\t\t\tSetBandwidth( 800000 );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tConn::SetBandwidth( int bytes_per_sec )\r\n{\r\n\tm_bandwidth = bytes_per_sec;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tConn::GetBandwidth( void )\r\n{\r\n\treturn m_bandwidth;\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tConn::FlagMessagesForResending( unsigned int packet_stamp )\r\n{\r\n\tMsgImpLink *msg_imp_link;\r\n\tMsgSeqLink *msg_seq_link;\r\n\tLst::Search< MsgImpLink > imp_sh;\r\n\tLst::Search< MsgSeqLink > seq_sh;\r\n\r\n\t// Mark each message of a matching packet stamp with a timestamp of zero.\r\n\t// Doing so signifies that it should be sent next frame\r\n\tfor( msg_imp_link = imp_sh.FirstItem( m_important_msg_list ); \r\n\t\t\tmsg_imp_link; msg_imp_link = imp_sh.NextItem() )\r\n\t{\r\n\t\tif( msg_imp_link->m_Packetstamp == packet_stamp )\r\n\t\t{\r\n\t\t\tmsg_imp_link->m_Timestamp = 0;\r\n\t\t}\r\n\t}\t\r\n\r\n\tfor( msg_seq_link = seq_sh.FirstItem( m_sequenced_msg_list ); \r\n\t\t\tmsg_seq_link; msg_seq_link = seq_sh.NextItem() )\r\n\t{\r\n\t\tif( msg_seq_link->m_Packetstamp == packet_stamp )\r\n\t\t{\r\n\t\t\tmsg_seq_link->m_Timestamp = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* \t\t\t                                  \t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\t// namespace Net"
  },
  {
    "path": "Code/Gel/ObjPtr.h",
    "content": "#ifndef __GEL_OBJPTR_H\r\n#define __GEL_OBJPTR_H\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n\r\nclass CRefCounted;\r\n\r\n\r\n\r\n/*\r\n\t-Self assignment\r\n\t-http://web.ftech.net/~honeyg/articles/smartp.htm\r\n*/\r\n\r\ntemplate<class T>\r\nclass CSmtPtr\r\n{\r\n\tfriend class CRefCounted;\r\n\r\npublic:\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tCSmtPtr();\r\n\t\t\t\t\t\t\tCSmtPtr(T* pT);\r\n\t\t\t\t\t\t\tCSmtPtr(CSmtPtr<T> &ref);\r\n\t\t\t\t\t\t\t~CSmtPtr();\r\n\r\n\tCSmtPtr<T> &\t\t\toperator=(T* pT);\r\n\tCSmtPtr<T> &\t\t\toperator=(CSmtPtr<T> &ref);\r\n\tT *\t\t\t\t\t\toperator->() const;\r\n\tT &\t\t\t\t\t\toperator*() const;\r\n\tT **\t\t\t\t\toperator&() const;\r\n\r\n\tbool\t\t\t\t\toperator!() const {return (mp_object == NULL);}\r\n\t\r\n\t\t\t\t\t\t\toperator T*() const {return mp_object;}\r\n\r\n\tfriend bool \t\t\toperator==(const CSmtPtr<T>& lhs, T* pRhs) {return lhs.mp_object == pRhs;}\r\n\tfriend bool \t\t\toperator!=(const CSmtPtr<T>& lhs, T* pRhs) {return lhs.mp_object != pRhs;}\r\n\r\n\tT *\t\t\t\t\t\tConvert() const {return mp_object;}\r\n\tvoid\t\t\t\t\tKill() const;\r\n\r\nprivate:\r\n\r\n\tvoid\t\t\t\t\tadd_ref();\r\n\tvoid\t\t\t\t\tremove_ref();\r\n\t\r\n\tT *\t\t\t\t\t\tmp_object;\r\n\t\r\n\tCSmtPtr<CRefCounted> *\tmp_prev_ptr;\r\n\tCSmtPtr<CRefCounted> *\tmp_next_ptr;\r\n};\r\n\r\n\r\n\r\n\r\ntemplate<class T>\r\ninline CSmtPtr<T>::CSmtPtr()\r\n{\r\n\tmp_prev_ptr = NULL;\r\n\tmp_next_ptr = NULL;\r\n\t\r\n\tmp_object = NULL;\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class T>\r\ninline CSmtPtr<T>::CSmtPtr(T *pT)\r\n{\r\n\tmp_prev_ptr = NULL;\r\n\tmp_next_ptr = NULL;\r\n\t\r\n\tmp_object = pT;\r\n\tadd_ref();\r\n\t//printf(\"WWW in copy constructor for 0x%x\\n\", mp_object);\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class T>\r\ninline CSmtPtr<T>::CSmtPtr(CSmtPtr<T> &ref)\r\n{\r\n\tmp_prev_ptr = NULL;\r\n\tmp_next_ptr = NULL;\r\n\t\r\n\tmp_object = ref.mp_object;\r\n\tadd_ref();\r\n\t//printf(\"WWW in copy constructor 2 for pointer at 0x%x, object 0x%x\\n\", this, mp_object);\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class T>\r\ninline CSmtPtr<T>::~CSmtPtr()\r\n{\r\n\t//printf(\"WWW in destructor for 0x%x\\n\", mp_object);\r\n\tremove_ref();\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class T>\r\ninline CSmtPtr<T> & CSmtPtr<T>::operator=(T *pT)\r\n{\r\n\t//printf(\"WWW in CSmtPtr<T>::operator=(T *pT) for pointer at 0x%x, object 0x%x (old) and 0x%x (new)\\n\", this, mp_object, pT);\r\n\tremove_ref();\r\n\tmp_object = pT;\r\n\tadd_ref();\r\n\treturn *this;\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class T>\r\ninline CSmtPtr<T> & CSmtPtr<T>::operator=(CSmtPtr<T> &ref)\r\n{\r\n\t//printf(\"WWW in CSmtPtr<T>::operator=(const CSmtPtr<T> &ref) for pointer at 0x%x, object 0x%x (old) and 0x%x (new)\\n\", this, mp_object, ref.mp_object);\r\n\tremove_ref();\r\n\tmp_object = ref.mp_object;\r\n\tadd_ref();\r\n\treturn *this;\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class T>\r\ninline T * CSmtPtr<T>::operator->() const\r\n{\r\n\tDbg_MsgAssert(mp_object, (\"NULL smart pointer!\"));\r\n\treturn (T *) mp_object;\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class T>\r\ninline T & CSmtPtr<T>::operator*()\tconst\r\n{\r\n\tDbg_MsgAssert(mp_object, (\"NULL smart pointer!\"));\r\n\treturn *((T *) mp_object);\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class T>\r\ninline T ** CSmtPtr<T>::operator&()\tconst\r\n{\r\n\tDbg_MsgAssert(0, (\"operator& not supported, comrade!\"));\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class T>\r\ninline void CSmtPtr<T>::Kill() const \r\n{\r\n\tDbg_MsgAssert(mp_object, (\"attempting delete with NULL smart pointer!\"));\r\n\t// this will lead to remove_ref() being called on this\r\n\tdelete mp_object;\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class T>\r\ninline void CSmtPtr<T>::add_ref()\r\n{\r\n\tif (mp_object)\r\n\t{\r\n\t\t//printf(\"WWW adding ref to 0x%x\\n\", mp_object);\r\n\t\tmp_object->AddSmartPointer((CSmtPtr<CRefCounted> *) this);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class T>\r\ninline void CSmtPtr<T>::remove_ref()\r\n{\r\n\tif (mp_object)\r\n\t{\r\n\t\t//printf(\"WWW removing ref from 0x%x\\n\", mp_object);\r\n\t\tmp_object->RemoveSmartPointer((CSmtPtr<CRefCounted> *) this);\r\n\t\tmp_object = NULL;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Object/Event.cpp",
    "content": "#include <core/defines.h>\r\n#include <gel/object.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/event.h>\r\n\r\n\r\n#include <gfx/2D/ScreenElement2.h>\r\n#ifdef __NOPT_ASSERT__\r\n#include <gfx/debuggfx.h>\r\n#endif\r\n\r\nnamespace Obj\r\n{\r\n\t\r\n#ifdef __NOPT_ASSERT__\r\nextern bool DebugSkaterScripts;\r\n#endif\r\n\r\n\r\n\r\n\r\nCEvent::CEvent()\r\n{\r\n\tm_flags = 0;\r\n}\r\n\r\n\r\n\r\n\r\nCEvent::~CEvent()\r\n{\r\n\tif (m_flags & mCONTROLS_OWN_DATA && mp_data)\r\n\t\tdelete mp_data;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CEvent::MarkRead(uint32 receiverId, uint32 script)\r\n{\r\n\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\tp_tracker->LogEventRead(this, receiverId, script);\r\n\tm_flags |= mREAD;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CEvent::MarkHandled(uint32 receiverId, uint32 script)\r\n{\r\n\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\tp_tracker->LogEventHandled(this, receiverId, script);\r\n\tm_flags |= mHANDLED;\r\n}\r\n\r\n\r\n\r\n\r\nint\tCEvent::sExtractControllerIndex(CEvent *pEvent)\r\n{\r\n\tint controller = 0;\r\n\tScript::CStruct *pData = pEvent->GetData();\r\n\tif (pData)\r\n\t\tpData->GetInteger(\"controller\", &controller);\r\n\r\n\treturn controller;\r\n}\r\n\r\n\r\n\r\n\r\nCEventListener::CEventListener()\r\n{\r\n\tm_registered = false;\r\n\tm_ref_count = 0;\r\n}\r\n\r\n\r\n\r\n\r\nCEventListener::~CEventListener()\r\n{\r\n\tCTracker* p_tracker = CTracker::Instance();\r\n\tp_tracker->UnregisterEventListener(this);\r\n\tDbg_MsgAssert(m_ref_count == 0, (\"Event listener still being referenced\"));\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tThe flags are for optimization purposes. Don't allow events that aren't\r\n\ttargeted to the attached object if it isn't necessary -- this will \r\n\tspeed things up.\r\n\t\r\n\tpObject = NULL means no associated CObject, which is legal, but you must\r\n\tset mALL_ALL_EVENTS\r\n*/\r\nvoid CEventListener::RegisterWithTracker(CObject *pObject)\r\n{\r\n\tmp_object = pObject;\r\n\r\n\tCTracker* p_tracker = CTracker::Instance();\r\n\tp_tracker->RegisterEventListener(this);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCalled by CTracker singleton on every event listener that is registered,\r\n\twhenever CTracker receives an event.\r\n*/\r\nvoid CEventListener::event_filter(CEvent *pEvent)\r\n{\t\r\n\tif (mp_object)\r\n\t{\r\n\t\t#ifdef __NOPT_ASSERT__\r\n//\t\tif (mp_object->GetFlags() & Front::CScreenElement::vIS_SCREEN_ELEMENT)\r\n//\t\t\t((Front::CScreenElement *) mp_object.Convert())->debug_verify_integrity();\r\n\t\t#endif\r\n\t}\r\n\t\r\n\t// TRICKY DELETE\r\n\t// Can in theory lead to the destruction of any CObject or any listener.\r\n\t// Will assert if this listener gets destroyed\r\n\tpass_event_to_listener(pEvent);\r\n\t\r\n\tif (mp_object)\r\n\t{\r\n\t\t#ifdef __NOPT_ASSERT__\r\n//\t\tif (mp_object->GetFlags() & Front::CScreenElement::vIS_SCREEN_ELEMENT)\r\n//\t\t\t((Front::CScreenElement *) mp_object.Convert())->debug_verify_integrity();\r\n\t\t#endif\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nCEventHandlerTable::CEventHandlerTable()\r\n{\r\n\tm_num_entries = 0; \r\n\tmp_tab = NULL;\r\n\tm_valid = true;\r\n\tm_in_immediate_use_counter = 0;\r\n\tm_changed = false;\r\n}\r\n\r\n\r\n\r\n\r\nCEventHandlerTable::~CEventHandlerTable()\r\n{\r\n\tDbg_Assert(!m_in_immediate_use_counter);\r\n\r\n\t\r\n\tif (mp_tab)\r\n\t{\r\n\t\tfor (int i = 0; i < m_num_entries; i++)\r\n\t\t{\r\n\t\t\tif (mp_tab[i].p_params)\r\n\t\t\t{\r\n\t\t\t\tdelete mp_tab[i].p_params;\r\n\t\t\t}\r\n\t\t}\r\n\t\tdelete [] mp_tab;\r\n\t}\r\n}\r\n\r\n\r\nvoid CEventHandlerTable::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tif (mp_tab && m_num_entries)\r\n\t{\r\n\t\r\n\t\tScript::CArray *p_array=new Script::CArray;\r\n\t\tp_array->SetSizeAndType(m_num_entries,ESYMBOLTYPE_STRUCTURE);\r\n\t\tfor (int i=0; i<m_num_entries; ++i)\r\n\t\t{\r\n\t\t\tif (mp_tab[i].script != vDEAD_ENTRY)\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct *p_ex = new Script::CStruct;\r\n\t\t\t\tp_ex->AddChecksum(CRCD(0x7321a8d6,\"Type\"), mp_tab[i].type);\t\t\r\n\t\t\t\tp_ex->AddChecksum(CRCD(0xd1e70f97,\"Event_Script\"), mp_tab[i].script);\t\t\r\n\t\t\t\tp_ex->AddChecksum(CRCD(0x923fbb3a, \"Group\"), mp_tab[i].group);\r\n\t\t\t\tp_array->SetStructure(i,p_ex);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct *p_ex = new Script::CStruct;\r\n\t\t\t\tp_ex->AddChecksum(NO_NAME, CRCD(0xd3d5f556, \"DeadEntry\"));\r\n\t\t\t\tp_array->SetStructure(i,p_ex);\r\n\t\t\t}\r\n\t\t}\r\n\t\tp_info->AddArrayPointer(CRCD(0x3e55ff39,\"mp_event_handler_table\"),p_array);\r\n\r\n\t}\r\n#endif\t\t\t\t \r\n}\r\n\r\n\r\n\r\n// Add a single event to the table\r\n// replacing any existing event handler with the same ex type\r\nvoid\tCEventHandlerTable::AddEvent(uint32 ex, uint32 scr, uint32 group, bool exception, Script::CStruct *p_params)\r\n{\r\n\tEntry *p_entry = NULL;\t\r\n\r\n// if there is no mp_tab, then we'll need to create a single entry one \r\n\tif (!mp_tab)\r\n\t{\r\n\t\tm_num_entries = 1;\r\n\t\tmp_tab = new Entry[1];\r\n\t\tp_entry = mp_tab;\r\n\t}\r\n\telse\r\n\t{\r\n\t// otherwise see it it exists, and if so, then simply replace it\r\n\t\tint i;\r\n\r\n\t\tfor (i = 0; i<m_num_entries; i++)\r\n\t\t{\r\n\t\t\tif (mp_tab[i].type == ex)\r\n\t\t\t{\r\n\t\t\t\tp_entry = &mp_tab[i];\r\n\t\t\t\tif (p_entry->p_params)\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete p_entry->p_params;\r\n\t\t\t\t}\r\n\t\t\t\tgoto GOT_ENTRY;\t\t\t\t// goto useful\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// check for empty slots, and use them\t\r\n\r\n\t\tfor (i = 0; i<m_num_entries; i++)\r\n\t\t{\r\n\t\t\tif (mp_tab[i].script == vDEAD_ENTRY)\r\n\t\t\t{\r\n\t\t\t\tp_entry = &mp_tab[i];\r\n\t\t\t\tgoto GOT_ENTRY;\t\t\t\t// goto useful\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// otherwise, extend the table by one entry\r\n\t\r\n//\t\tprintf (\"Allocating new table to extend by one\\n\");\r\n\t\tEntry * p_old_tab = mp_tab;\r\n\t\tmp_tab = new Entry[m_num_entries + 1];\r\n\t\tfor (i=0; i<m_num_entries; i++)\r\n\t\t{\r\n\t\t\tmp_tab[i] = p_old_tab[i];\r\n\t\t}\r\n\t\tdelete [] p_old_tab;\r\n\t\tp_entry = &mp_tab[m_num_entries];\r\n\t\tm_num_entries++;\r\n\t\r\n\t}\r\n\r\nGOT_ENTRY:\r\n\r\n\tDbg_MsgAssert(p_entry, (\"NULL p_entry\"));\r\n\r\n\tp_entry->enabled = true;\r\n\tp_entry->exception = exception;\r\n\tp_entry->group = group;\r\n\tif (p_params)\r\n\t{\r\n//\t\tprintf (\"Allocating parameters\\n\");\r\n\t\t// if params are passed, then we need to make a copy of them\r\n\t\tp_entry->p_params = new Script::CStruct(*p_params);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_entry->p_params = NULL;  \r\n\t}\r\n\tp_entry->script = scr;\r\n\tp_entry->type = ex;\r\n\r\n\t// Need to flag it as changed, so we can break out of pass_event\r\n\t// if an event causes a change in the table (which we are iterating over)   \r\n\tm_changed = true;\r\n\r\n}\r\n\r\n\r\nvoid CEventHandlerTable::add_from_script(Script::CArray *pArray, bool replace)\r\n{\r\n\tDbg_Assert(pArray);\r\n\r\n\t\r\n\tint new_entries = pArray->GetSize();\r\n\tif (replace && !new_entries)\r\n\t{\r\n\t\t// if no new entries, and we are \"replacing\", then delete any existing table\r\n\t\t// and return \r\n\t\tif (mp_tab)\r\n\t\t{\r\n\t\t\tfor (int i = 0; i < m_num_entries; i++)\r\n\t\t\t{\r\n\t\t\t\tif (mp_tab[i].p_params)\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete mp_tab[i].p_params;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tdelete [] mp_tab;\r\n\t\t\tmp_tab = NULL;\r\n\t\t\tm_num_entries = 0;\r\n\t\t\tm_changed = true;\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n/*\r\n\t// Optimization for adding a single entry\r\n\tif (new_entries == 1)\r\n\t{\r\n\r\n\t\t// get the type, script pair, and any params and flags\r\n\t\tScript::CStruct *pEventStruct = pArray->GetStructure(0);\r\n\t\t\r\n\t\tScript::CComponent *p_left = pEventStruct->GetNextComponent(NULL);\r\n\t\tDbg_MsgAssert(p_left, (\"missing 'type' half of event handler pair\"));\r\n\t\tDbg_Assert(p_left->mType == ESYMBOLTYPE_NAME);\r\n\r\n\t\tScript::CComponent *p_right = pEventStruct->GetNextComponent(p_left);\r\n\t\tDbg_MsgAssert(p_right, (\"missing 'handler' half of event handler pair\"));\r\n\t\tDbg_Assert(p_right->mType == ESYMBOLTYPE_NAME);\r\n\r\n\t\tuint32\ttype = p_left->mChecksum;\r\n\r\n\t\tEntry *p_entry = NULL;\r\n\r\n\r\n\t\t// if it's a \"replace\" entry, then we scan through to see if we already have an entry\r\n\t\t// then we delete it, and can use that slot\r\n\t\tif (replace)\r\n\t\t{\r\n\t\t\tfor (int i = 0; i < m_num_entries; i++)\r\n\t\t\t{\r\n\t\t\t\tif (mp_tab[i].type == type)\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_tab[i].script = vDEAD_ENTRY;\r\n\t\t\t\t\t// delete the original parameters, whilst (while!) we are at it\r\n\t\t\t\t\tif (mp_tab[i].p_params)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdelete mp_tab[i].p_params;\r\n\t\t\t\t\t\tmp_tab[i].p_params = NULL;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tp_entry = &mp_tab[i];\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// if not got one via replace, we need to look for an empty slot\r\n\t\t// 95% of the time there should be one, as the table\r\n\t\t// will expand to the max size required, and will not shrink\r\n\t\t// so we only need to add slots during expansion.\r\n\r\n\t\tfor (int i = 0; i < m_num_entries; i++)\r\n\t\t{\r\n\t\t\tif (mp_tab[i].script == vDEAD_ENTRY)\r\n\t\t\t{\r\n\t\t\t\tp_entry = &mp_tab[i];\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (p_entry)\r\n\t\t{\r\n\r\n\t\t\t// DANG!  This is a chunk of cut and paste code from below\r\n\t\t\t// this event handler container is in serious need\r\n\t\t\t// of refactoring\r\n\t\t\t\r\n\t\t\t// Mick, if the event handler has a \"params\" structure\r\n\t\t\t// then add it to the entry.\r\n\t\t\t// (note, have to be careful in cleaning these up)\r\n\t\t\tScript::CStruct *p_params;\r\n\t\t\tif (pEventStruct->GetStructure(CRCD(0x7031f10c,\"params\"),&p_params))\r\n\t\t\t{\r\n\t\t\t\tprintf (\"Allocating Params\\n\");\r\n\t\t\t\tp_entry->p_params = new Script::CStruct(*p_params);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_entry->p_params = NULL;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (!pEventStruct->GetChecksum(CRCD(0x923fbb3a, \"Group\"), &p_entry->group))\r\n\t\t\t{\r\n\t\t\t\tp_entry->group = vDEFAULT_GROUP;\r\n\t\t\t}\r\n\t\r\n\t\t\tp_entry->exception = pEventStruct->ContainsFlag(CRCD(0x80367192,\"Exception\"));\r\n\t\t\t\r\n\t\t\tp_entry->type = p_left->mChecksum;\r\n\t\t\tp_entry->script = p_right->mChecksum;\r\n\t\t\tDbg_MsgAssert(p_entry->script,(\"Adding Null script in event handler\"));\r\n\t\t\tp_entry->enabled = true;\r\n\t\t\tm_changed = true;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n*/\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\r\n\t// create new table\t(this is the one with problems with p_params)\r\n\t// the values are not initialized\r\n\t// so if it's allocated over an old one, then\r\n\t// errors might occur\r\n\t\r\n//\tprintf(\"Allocating memory for %d new entries\\n\",new_entries);\r\n\t\r\n\tEntry *p_edit_tab = new Entry[m_num_entries + new_entries];\r\n\t#ifdef __NOPT_ASSERT__ \r\n\tint first_edit_entry = m_num_entries;\t\r\n\t#endif\r\n\r\n\r\n\tint\tnew_entry_index = 0;\r\n\r\n\t// transfer the new entries from script array into new table\r\n\tfor (int i = 0; i < new_entries; i++)\r\n\t{\r\n\t\t// get the type, script pair, and any params and flags\r\n\t\tScript::CStruct *pEventStruct = pArray->GetStructure(i);\r\n\t\t\r\n\t\tScript::CComponent *p_left = pEventStruct->GetNextComponent(NULL);\r\n\t\tDbg_MsgAssert(p_left, (\"missing 'type' half of event handler pair\"));\r\n\t\tDbg_Assert(p_left->mType == ESYMBOLTYPE_NAME);\r\n\r\n\t\tScript::CComponent *p_right = pEventStruct->GetNextComponent(p_left);\r\n\t\tDbg_MsgAssert(p_right, (\"missing 'handler' half of event handler pair\"));\r\n\t\tDbg_Assert(p_right->mType == ESYMBOLTYPE_NAME);\r\n\r\n\t\tif (replace)\r\n\t\t{\r\n\t\t\t// remove entry from old table, if it exists in there\r\n\t\t\tremove_entry(p_left->mChecksum);\r\n\t\t}\r\n\t\t\r\n\t\tEntry *p_entry = p_edit_tab + new_entry_index++;\r\n\r\n\t\t// Mick, if the event handler has a \"params\" structure\r\n\t\t// then add it to the entry.\r\n\t\t// (note, have to be careful in cleaning these up)\r\n\t\tScript::CStruct *p_params;\r\n\t\tif (pEventStruct->GetStructure(CRCD(0x7031f10c,\"params\"),&p_params))\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( (i + first_edit_entry) < (m_num_entries + new_entries),\r\n\t\t\t\t\t\t   ( \"Array overflow\" ) );\r\n\t\t\t\r\n\t\t\tp_entry->p_params = new Script::CStruct(*p_params);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_entry->p_params = NULL;\r\n\t\t}\r\n\t\t\r\n\t\tif (!pEventStruct->GetChecksum(CRCD(0x923fbb3a, \"Group\"), &p_entry->group))\r\n\t\t{\r\n\t\t\tp_entry->group = vDEFAULT_GROUP;\r\n\t\t}\r\n\r\n\t\tp_entry->exception = pEventStruct->ContainsFlag(CRCD(0x80367192,\"Exception\"));\r\n\t\t\r\n\t\tp_entry->type = p_left->mChecksum;\r\n\t\tp_entry->script = p_right->mChecksum;\r\n\t\tDbg_MsgAssert(p_entry->script,(\"Adding Null script in event handler\"));\r\n\t\tp_entry->enabled = true;\r\n\t\tm_changed = true;\r\n\t}\r\n\t\r\n\t// if member table already exists, copy it into new one, at the end\r\n\t// (append to items already added)\r\n\t// Note that some entries in the original table might have been deleted, so\r\n\t// the size of mp_tab might end up being bigger than that indicated by m_num_entries\r\n\t// but the extra at the end is just garbage.\r\n\t// This is most common when you Set individual events on\r\n\t// and already existing table that contains that event\r\n\t// (old code would have left an uninitialized gap, causing very obscure bugs)\r\n\r\n\tif (mp_tab)\r\n\t{\r\n\t\tfor (int i = 0; i < m_num_entries; i++)\r\n\t\t{\r\n\t\t\tp_edit_tab[new_entry_index++] = mp_tab[i];\r\n\t\t}\r\n\t}\r\n\tdelete [] mp_tab;  \t\t\t\t\t// old table has been coped over, so we can delete it\r\n\tmp_tab = p_edit_tab;\t\t\t\t// and make the newly constructed table the active table\r\n\tm_num_entries = new_entry_index;\t// set the number of entries to the actual counted entries (not the size of the array)\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n}\r\n\r\n\r\n\r\n\r\n// doesn't change the array size, just marks entry dead (and deletes p_params struct)\r\nvoid CEventHandlerTable::remove_entry(uint32 type)\r\n{\r\n\tfor (int i = 0; i < m_num_entries; i++)\r\n\t{\r\n\t\tif (mp_tab[i].type == type)\r\n\t\t{\r\n\t\t\tmp_tab[i].type = 0;\r\n\t\t\tmp_tab[i].script = vDEAD_ENTRY;\r\n\t\t\t// delete the original parameters, whilst (while!) we are at it\r\n\t\t\tif (mp_tab[i].p_params)\r\n\t\t\t{\r\n\t\t\t\tdelete mp_tab[i].p_params;\r\n\t\t\t\tmp_tab[i].p_params = NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Note, we don't set m_changed here, as the table has not really changed\r\n\t// just one entry has changed\r\n\t// we will set the m_changed flag if compress_table later removed this entry\r\n\t\r\n}\r\n\r\n\r\n// removes all entries with the given group id\r\n// or remove them all if \"all_groups\" is specifed\r\nvoid CEventHandlerTable::remove_group(uint32 group)\r\n{\r\n\tfor (int i = 0; i < m_num_entries; i++)\r\n\t{\r\n\t\tif (mp_tab[i].group == group || group == CRCD(0x8b713e0e,\"all_groups\"))\r\n\t\t{\r\n\t\t\tmp_tab[i].script = vDEAD_ENTRY;\r\n\t\t\tif (mp_tab[i].p_params)\r\n\t\t\t{\r\n\t\t\t\tdelete mp_tab[i].p_params;\r\n\t\t\t\tmp_tab[i].p_params = NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n// changes size of table, removing dead entries\r\nvoid CEventHandlerTable::compress_table()\r\n{\r\n\tif (!mp_tab) return;\r\n\r\n\t// count up dead entries\r\n\tint num_dead = 0;\r\n\tint in = 0;\r\n\tfor (; in < m_num_entries; in++)\r\n\t{\r\n\t\tif (mp_tab[in].script == vDEAD_ENTRY)\r\n\t\t\tnum_dead++;\r\n\t}\r\n\r\n\tif (num_dead == 0) return;\r\n\r\n\tint new_size = m_num_entries - num_dead;\r\n\r\n\tm_changed = true;\r\n\r\n\t// Mick - If new table has zero size, then don't allocate it\t\r\n\t// just delete the old table, and set it to NULL\r\n\tif ( 0 == new_size)\r\n\t{\r\n\t\tfor (int i = 0; i < m_num_entries; i++)\r\n\t\t{\r\n\t\t\t// we're about to remove an entry\r\n\t\t\t// so delete its params if necessary\r\n\t\t\tif ( mp_tab[i].p_params )\r\n\t\t\t{\r\n\t\t\t\tdelete mp_tab[i].p_params;\r\n\t\t\t\tmp_tab[i].p_params = NULL;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tdelete[]\tmp_tab;\r\n\t\tmp_tab = NULL;\r\n\t\tm_num_entries = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\tEntry *p_new_tab = new Entry[new_size];\t\t\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\tint out = 0;\r\n\t\tfor (in = 0; in < m_num_entries; in++)\r\n\t\t{\r\n\t\t\tif (mp_tab[in].script != vDEAD_ENTRY)\r\n\t\t\t{\r\n\t\t\t\tp_new_tab[out++] = mp_tab[in];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// we're about to remove an entry\r\n\t\t\t\t// so delete its params if necessary\r\n\t\t\t\tif ( mp_tab[in].p_params )\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete mp_tab[in].p_params;\r\n\t\t\t\t\tmp_tab[in].p_params = NULL;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tdelete[] mp_tab;\r\n\t\tmp_tab = p_new_tab;\r\n\t\tm_num_entries = new_size;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CEventHandlerTable::set_event_enable(uint32 type, bool state)\r\n{\r\n\tfor (int i = 0; i < m_num_entries; i++)\r\n\t{\r\n\t\tif (mp_tab[i].type == type)\r\n\t\t\tmp_tab[i].enabled = state;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\nvoid CEventHandlerTable::pass_event(CEvent *pEvent, Script::CScript *pScript, bool broadcast)\r\n{\r\n\t// if it's a screen element, check that events aren't blocked\r\n#ifdef __NOPT_ASSERT__\r\n//\tif ( ( pObject->GetFlags() & Front::CScreenElement::vIS_SCREEN_ELEMENT ) && \r\n//\t\t ( pObject->GetFlags() & Front::CScreenElement::vEVENTS_BLOCKED ) )\r\n//\t{\r\n//\t\treturn;\r\n//\t}\r\n#endif\t\t// __NOPT_ASSERT__\r\n\r\n\r\n\r\n\t#if 1\r\n\tbool\told_m_changed = m_changed;\r\n\tm_changed = false;\t\t\r\n\t#else\t \r\n\t// only clear the m_changed flag if we are not recursing into here\r\n\tif (!m_in_immediate_use_counter)\r\n\t{\t \t\r\n\t\t\tm_changed = false;\t\t\r\n\t}\r\n\t#endif\r\n\t\r\n\tm_in_immediate_use_counter++;\r\n\r\n#ifndef __PLAT_WN32__\r\n\t// Need to assert that mp_tab is valid (or we have no entries in it)\r\n\tDbg_MsgAssert(!m_num_entries || Mem::Valid(mp_tab),(\"Invalid event handler table for Event %s\", Script::FindChecksumName(pEvent->GetType())));\r\n#endif\r\n\r\n\t\r\n\tEntry *p_entry = mp_tab;\r\n\tfor (int i = 0; i < m_num_entries; i++)\r\n\t{  \r\n\t\tif (p_entry->type == pEvent->GetType() && p_entry->script != vDEAD_ENTRY && p_entry->enabled)\r\n\t\t{\r\n\t\t\t\r\n\t\t\tScript::CScript *p_new_script = NULL;\r\n\t\t\tScript::CStruct\t*p_params = NULL;\r\n\t\t\tScript::CStruct\t*p_passed_params = NULL;\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t//\t\tprintf (\"%s calls %s\\n\",Script::FindChecksumName(p_entry->type),Script::FindChecksumName(p_entry->script));\r\n\t\t\t\r\n\t\t\tif (pEvent->GetData())\r\n\t\t\t{\r\n\t\t\t\t// there is event data, so copy it into a new structure\r\n\t\t\t\tp_params = new Script::CStruct();\r\n\t\t\t\t// and then merge the parameters in with it\r\n\t\t\t\tif (p_entry->p_params)\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_params += *(p_entry->p_params);\r\n\t\t\t\t}\r\n\t\t\t\t*p_params += *(pEvent->GetData());\r\n\t\t\t\tp_passed_params = p_params;\r\n\t\t\t\t// using p_params like this is safe, since SpawnScript makes its own copy\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_passed_params = p_entry->p_params;\r\n\t\t\t}\t\t\t\r\n\r\n\t\t\tif (p_entry->exception)\r\n\t\t\t{\r\n\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\tif (DebugSkaterScripts && (pEvent->GetTarget() == 0 || pEvent->GetSource()))\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf(\"%d: Exception %s, Script %s, Target %s, Source %s\\n\",\r\n\t\t\t\t\t\t(int)Tmr::GetRenderFrame(),\r\n\t\t\t\t\t\tScript::FindChecksumName(pEvent->GetType()),\r\n\t\t\t\t\t\tScript::FindChecksumName(p_entry->script),\r\n\t\t\t\t\t\tpEvent->GetTarget() ? Script::FindChecksumName(pEvent->GetTarget()) : \"Skater\",\r\n\t\t\t\t\t\tpEvent->GetSource() ? Script::FindChecksumName(pEvent->GetSource()) : \"Skater\"\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t\t#endif\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t// If it's an exception, we check to see if the object\r\n\t\t\t\t// has flagged an \"OnExceptionRun\" \r\n\r\n\t\t\t\tif (pScript->GetOnExceptionScriptChecksum())\r\n\t\t\t\t{\r\n\t\t\t\t\t// Pass in the name of the exception so that certain exceptions can be ignored.\r\n\t\t\t\t\tScript::CStruct *pFoo=new Script::CStruct;\r\n\t\t\t\t\tpFoo->AddComponent(NONAME, ESYMBOLTYPE_NAME, (int)p_entry->exception);\r\n\t\t\t\t\t// Script::RunScript(pScript->GetOnExceptionScriptChecksum(), pFoo, pScript->mpObject );\r\n\t\t\t\t\t// Dan: interrupt instead of run\r\n\t\t\t\t\tuint32 checksum = pScript->GetOnExceptionScriptChecksum();\r\n\t\t\t\t\tpScript->SetOnExceptionScriptChecksum(0);\t// clear it once it has been run\r\n\t\t\t\t\tpScript->Interrupt(checksum, pFoo);\r\n\t\t\t\t\tdelete pFoo;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// the OnException script may alter the table\r\n\t\t\t\tif (p_entry->script != vDEAD_ENTRY)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Exceptions act like a GOTO, so we just set the script we are running on to this new script\r\n\t\t\t\t\t// the object reamins the same\r\n\t\t\t\t\tpScript->SetScript(p_entry->script,p_passed_params,pScript->mpObject);\r\n\t\t\t\t\tpScript->Update();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Current Screen element code relies on spawned scripts\r\n\t\t\t\t// as they don't update their own scripts\r\n\t\t\t\t// but we are moving to an \"Interrupt\" model, so we\r\n\t\t\t\t// only support this \"Spawned\" model for the screen elements\r\n\t\t\t\t\r\n\t\t\t\tif (pScript->mpObject &&  pScript->mpObject->GetFlags() & Front::CScreenElement::vIS_SCREEN_ELEMENT)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Normal events spawn a new script running on the same object as the current script (if any)\r\n\t\t\t\t\tp_new_script = Script::SpawnScript(p_entry->script, p_passed_params, 0, NULL);\r\n\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\tp_new_script->SetCommentString(\"Spawned by CEventHandlerTable::pass_event, 1\");\r\n\t\t\t\t\t#endif\r\n\t\t\t\t\tp_new_script->mpObject = pScript->mpObject;\t   \r\n\t\t\t\t\tp_new_script->Update(); \r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Instead of spawning, just interrupt the current script\r\n\t\t\t\t\tpScript->Interrupt(p_entry->script, p_passed_params);\t\t\t\t\t\r\n\t\t\t\t}\t\t\t\t\r\n\t\t\t}\r\n\r\n\t\t\tif (p_params)\r\n\t\t\t{\r\n\t\t\t\tdelete p_params;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tDbg_MsgAssert((*(uint32*)this) != 0x01010101,(\"%s\\nCEventHandlerTable deleted whilst being used\",p_new_script->GetScriptInfo()));\r\n\t\t\t//p_new_script->mpObject = NULL;\r\n\r\n\t\t\t// do logging\r\n\t\t\t//pEvent->MarkHandled(pObject->GetID(), p_entry->script);\r\n\t\t\tpEvent->MarkHandled(0, p_entry->script);\t// receiver id not important\r\n\t\t}\r\n\r\n\t\tp_entry++;\r\n\r\n\t\tif (!m_valid)\r\n\t\t{\r\n\t\t\t// Looks like the spawned script deleted the CObject, invalidating this event handler table.\r\n\t\t\t// Exit now. If the outermost pass_event() in a recursive chain, then kill self.\r\n\t\t\tm_in_immediate_use_counter--;\r\n\t\t\tif (!m_in_immediate_use_counter)\r\n\t\t\t\tdelete this;\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\tif (m_changed)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t}\r\n\r\n\t// if we were previously flagged as changed, or some other function flagged us as changed\r\n\t// then say we have changed\t\r\n\tm_changed = m_changed || old_m_changed;\r\n\r\n\tm_in_immediate_use_counter--;\r\n}\r\n\r\n#else\r\n\r\nvoid CEventHandlerTable::pass_event(CEvent *pEvent, CObject *pObject, bool broadcast)\r\n{\r\n\t// if it's a screen element, check that events aren't blocked\r\n#ifdef __NOPT_ASSERT__\r\n\tif ( ( pObject->GetFlags() & Front::CScreenElement::vIS_SCREEN_ELEMENT ) )\r\n\t{\r\n\t\tFront::CScreenElement* pScreenElement = (Front::CScreenElement*)pObject;\r\n\t\tif ( pScreenElement->EventsBlocked() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\t\t\r\n\t}\r\n#endif\t\t// __NOPT_ASSERT__\r\n\r\n\t// only clear the m_changed flag if we are not recursing into here\r\n\tif (!m_in_immediate_use_counter)\r\n\t{\t \t\r\n\t\t\tm_changed = false;\t\t\r\n\t}\r\n\t\r\n\tm_in_immediate_use_counter++;\r\n\t\r\n\tEntry *p_entry = mp_tab;\r\n\tfor (int i = 0; i < m_num_entries; i++)\r\n\t{  \r\n\t\t \r\n//\t\tif (broadcast && !p_entry->broadcast)\r\n//\t\t{\r\n//\t\t\tp_entry++;\r\n//\t\t\tcontinue;\r\n//\t\t}\t\t\r\n\t\r\n\t\tif (p_entry->type == pEvent->GetType() && p_entry->script != vDEAD_ENTRY && p_entry->enabled)\r\n\t\t{\r\n\t\t\t\r\n\t\t\tScript::CScript *p_new_script = NULL;\r\n\t\t\tScript::CStruct\t*p_params = NULL;\r\n\t\t\tScript::CStruct\t*p_passed_params = NULL;\r\n\t\t\t\r\n\t\t\t// visual debugging, if there is a source and target, and they are different\r\n\t\t\t// then draw a line between the two objects\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tif (Script::GetInteger(CRCD(0xffc8c5f8,\"Display_event_arrows\")))\r\n\t\t\t{\r\n\t\t\t\tif (pObject->GetFlags() & Obj::CObject::vCOMPOSITE)\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32\t\tsource_id = pEvent->GetSource();\r\n\t//\t\t\t\tprintf (\"Source = 0x%x  %s,  target = 0x%x, %s\\n\",source_id, Script::FindChecksumName(source_id),pObject->GetID(),Script::FindChecksumName(pObject->GetID()));\r\n\t\t\t\t\tif ( source_id != pObject->GetID() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tObj::CObject * p_source_object = Obj::CTracker::Instance()->GetObject(source_id);\r\n\t\t\t\t\t\tif (p_source_object)\r\n\t\t\t\t\t\t{\r\n\t//\t\t\t\t\t\tprintf (\"objects types %d, %d\\n\",pObject->GetType(), p_source_object->GetType());\r\n\t\t\t\t\t\t\t// and we only want to do it if they are composite object\r\n\t\t\t\t\t\t\tif (pObject->GetFlags() & Obj::CObject::vCOMPOSITE && p_source_object->GetFlags() & Obj::CObject::vCOMPOSITE)\t// eek!\r\n\t\t\t\t\t\t\t{\t\r\n\t\t\t\t\t\t\t\tGfx::AddDebugArrow(((CCompositeObject*)p_source_object)->GetPos(),((CCompositeObject*)pObject)->GetPos(),0xff00ff,0xff00ff,200);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tprintf (\"No Source object found\\n\");\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\t\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (DebugSkaterScripts && (pObject->GetID() == 0 || pEvent->GetSource() == 0))\r\n\t\t\t{\r\n\t\t\t\tprintf(\"%d: Exception %s, Script %s, Target %s, Source %s\\n\",\r\n\t\t\t\t\t(int)Tmr::GetRenderFrame(),\r\n\t\t\t\t\tScript::FindChecksumName(pEvent->GetType()),\r\n\t\t\t\t\tScript::FindChecksumName(p_entry->script),\r\n\t\t\t\t\tpEvent->GetTarget() ? Script::FindChecksumName(pEvent->GetTarget()) : \"Skater\",\r\n\t\t\t\t\tpEvent->GetSource() ? Script::FindChecksumName(pEvent->GetSource()) : \"Skater\"\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\t\r\n\t\t\tif (pEvent->GetData())\r\n\t\t\t{\r\n\t\t\t\t// there is event data, so copy it into a new structure\r\n\t\t\t\tp_params = new Script::CStruct();\r\n\t\t\t\t// and then merge the parameters in with it\r\n\t\t\t\tif (p_entry->p_params)\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_params += *(p_entry->p_params);\r\n\t\t\t\t}\r\n\t\t\t\t*p_params += *(pEvent->GetData());\r\n\t\t\t\tp_passed_params = p_params;\r\n\t\t\t\t// using p_params like this is safe, since SpawnScript makes its own copy\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_passed_params = p_entry->p_params;\r\n\t\t\t}\t\t\t\r\n\r\n\t\t\tif (p_entry->exception)\r\n\t\t\t{\r\n\t\t\t\t// If it's an exception, we check to see if the object\r\n\t\t\t\t// has flagged an \"OnExceptionRun\" \r\n\r\n\r\n\t\t\t\t// Ooh, we need to run a script, so better make sure mp_script points to something.\r\n\t\t\t\tif (pObject->GetScript()==NULL)\r\n\t\t\t\t{\r\n\t\t\t\t\tpObject->SetScript( new Script::CScript);\r\n\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\tpObject->GetScript()->SetCommentString(\"Created in CEventHandlerTable::pass_event(...) (exception)\");\r\n\t\t\t\t\t#endif\r\n\t\t\t\t}\t\r\n\t\t\t\t// Now we're safe. Note: mp_script will get cleaned up by the CObject destructor.\r\n\r\n\t\t\t\t\r\n\t\t\t\tif (pObject->GetOnExceptionScriptChecksum())\r\n\t\t\t\t{\r\n//\t\t\t\t\tprintf (\"Running onException script %s\\n\",Script::FindChecksumName(pObject->GetOnExceptionScriptChecksum()));\r\n\t\t\t\t\t// Pass in the name of the exception so that certain exceptions can be ignored.\r\n\t\t\t\t\tScript::CStruct *pFoo=new Script::CStruct;\r\n\t\t\t\t\tpFoo->AddComponent(NONAME, ESYMBOLTYPE_NAME, (int)p_entry->exception);\r\n\t\t\t\t\tScript::RunScript(pObject->GetOnExceptionScriptChecksum(), pFoo, pObject );\r\n\t\t\t\t\tdelete pFoo;\r\n\t\t\t\t\tpObject->SetOnExceptionScriptChecksum(0);\t// clear it once it has been run\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t// An exception will act like a \"goto\"\r\n\t\t\t\tScript::CScript *p_old_script = pObject->GetScript();\r\n//\t\t\t\tprintf(\"RUNNING exception %s script %s on object %s\\n\",Script::FindChecksumName(p_entry->type),Script::FindChecksumName(p_entry->script),Script::FindChecksumName(pObject->GetID()));\r\n\t\t\t\tp_old_script->SetScript(p_entry->script,p_passed_params,pObject);\r\n\t\t\t\tp_old_script->Update();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Normal events spawn a script running on an object\r\n//\t\t\t\tprintf(\"SPAWNING exception %s script %s on object %s\\n\",Script::FindChecksumName(p_entry->type),Script::FindChecksumName(p_entry->script),Script::FindChecksumName(pObject->GetID()));\r\n\t\t\t\tp_new_script = Script::SpawnScript(p_entry->script, p_passed_params, 0, NULL);\r\n\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\tp_new_script->SetCommentString(\"Spawned by CEventHandlerTable::pass_event, 1\");\r\n\t\t\t\t#endif\r\n\t\t\t\tp_new_script->mpObject = pObject;\t\t\t   \r\n\t\t\t\tp_new_script->Update();\r\n\t\t\t}\r\n\r\n\t\t\tif (p_params)\r\n\t\t\t{\r\n\t\t\t\tdelete p_params;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tDbg_MsgAssert((*(uint32*)this) != 0x01010101,(\"%s\\nCEventHandlerTable deleted whilst being used\",p_new_script->GetScriptInfo()));\r\n\t\t\t//p_new_script->mpObject = NULL;\r\n\r\n\t\t\t// do logging\r\n\t\t\tpEvent->MarkHandled(pObject->GetID(), p_entry->script);\r\n\t\t}\r\n\r\n\t\tp_entry++;\r\n\r\n\t\tif (!m_valid)\r\n\t\t{\r\n\t\t\t// Looks like the spawned script deleted the CObject, invalidating this event handler table.\r\n\t\t\t// Exit now. If the outermost pass_event() in a recursive chain, then kill self.\r\n\t\t\tm_in_immediate_use_counter--;\r\n\t\t\tif (!m_in_immediate_use_counter)\r\n\t\t\t\tdelete this;\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\tif (m_changed)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t}\r\n\r\n\tm_in_immediate_use_counter--;\r\n}\r\n#endif\r\n\r\n\r\n\r\n\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n// Register all the entries in this even table with the event receiver table in the tracker\r\n// (Hey, maybe store the script in here, allow multiple entries and do away with this table?)\r\nvoid\tCEventHandlerTable::register_all(Script::CScript *p_script)\r\n{\r\n\tEntry *p_entry = mp_tab;\r\n\tfor (int i = 0; i < m_num_entries; i++)\r\n\t{\r\n\t\t// if it's a live entry, then add it as a receiver\r\n\t\tif (p_entry->type && p_entry->script && p_entry->script != vDEAD_ENTRY)\r\n\t\t{\r\n\t\t\tObj::CTracker::Instance()->RegisterEventReceiver(p_entry->type, p_script);\r\n\t\t}\r\n\t\tp_entry++;\r\n\t}  \r\n}\r\n\r\n// Flush out all references from the Event Receiver table to this object, based on the event handler table\r\nvoid\tCEventHandlerTable::unregister_all(Script::CScript *p_script)\r\n{\r\n\tEntry *p_entry = mp_tab;\r\n\tfor (int i = 0; i < m_num_entries; i++)\r\n\t{\r\n\t\tif (p_entry->type)\r\n\t\t{\r\n\t\t\tObj::CTracker::Instance()->UnregisterEventReceiver(p_entry->type, p_script);\r\n\t\t}\r\n\t\tp_entry++;\r\n\t}  \r\n}\r\n\r\n#else\r\n\r\n// Register all the entries in this even table with the event receiver table in the tracker\r\n// (Hey, maybe store the script in here, allow multiple entries and do away with this table?)\r\nvoid\tCEventHandlerTable::register_all(CObject *p_object)\r\n{\r\n\tEntry *p_entry = mp_tab;\r\n\tfor (int i = 0; i < m_num_entries; i++)\r\n\t{\r\n\t\tif (p_entry->type && p_entry->script)\r\n\t\t{\r\n\t\t\tObj::CTracker::Instance()->RegisterEventReceiver(p_entry->type, p_object);\r\n\t\t}\r\n\t\tp_entry++;\r\n\t}  \r\n}\r\n\r\n// Flush out all references from the Event Receiver table to this object, based on the event handler table\r\nvoid\tCEventHandlerTable::unregister_all(CObject *p_object)\r\n{\r\n\tEntry *p_entry = mp_tab;\r\n\tfor (int i = 0; i < m_num_entries; i++)\r\n\t{\r\n\t\tif (p_entry->type)\r\n\t\t{\r\n\t\t\tObj::CTracker::Instance()->UnregisterEventReceiver(p_entry->type, p_object);\r\n\t\t}\r\n\t\tp_entry++;\r\n\t}  \r\n}\r\n\r\n#endif\r\n\r\n// Dump the given table\r\nvoid\tCEventHandlerTable::sPrintTable ( CEventHandlerTable* table )\r\n{\r\n#\tif !defined( __PLAT_NGC__ ) || ( defined( __PLAT_NGC__ ) && !defined( __NOPT_FINAL__ ) )\r\n\tprintf(\"====================================\\n\");\r\n\tprintf(\"Event Handler Table:\\n\");\r\n\tif (table)\r\n\t{\r\n\t\tfor (int i = 0; i < table->m_num_entries; i++)\r\n\t\t{\r\n\t\t\tEntry* p_entry = table->mp_tab + i;\r\n\t\t\t\r\n\t\t\tprintf(\"------------------------------------\\n\");\r\n\t\t\tprintf(\"  Type     : %s\\n\", Script::FindChecksumName(p_entry->type));\r\n\t\t\tprintf(\"  Script   : %s\\n\", Script::FindChecksumName(p_entry->script));\r\n\t\t\tprintf(\"  Group    : %s\\n\", Script::FindChecksumName(p_entry->group));\r\n\t\t\tprintf(\"  Exception: %s\\n\", p_entry->exception ? \"yes\" : \"no\");\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tprintf(\"  Emtpy\\n\");\r\n\t}\r\n\tprintf(\"====================================\\n\");\r\n#endif\t\t// __NOPT_FINAL__\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Object/ObjPtr.cpp",
    "content": "#include <core/defines.h>\r\n#include <gel/object.h>\r\n#include <gel/ObjPtr.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Object/RefCounted.cpp",
    "content": "#include <core/defines.h>\r\n#include <gel/RefCounted.h>\r\n#include <gel/ObjPtr.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n\r\n\r\nCRefCounted::CRefCounted()\r\n{\r\n\tmp_smart_ptr_list = NULL;\r\n}\r\n\r\n\r\n\r\n\r\nCRefCounted::~CRefCounted()\r\n{\r\n\tCSmtPtr<CRefCounted> *p_smt = mp_smart_ptr_list;\r\n\twhile(p_smt)\r\n\t{\r\n\t\tCSmtPtr<CRefCounted> *p_next = p_smt->mp_next_ptr;\r\n\t\tDbg_Assert(p_smt->mp_object);\r\n\t\tDbg_Assert(p_smt->mp_object == this);\r\n\t\t*p_smt = NULL;\r\n\t\tp_smt = p_next;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CRefCounted::AddSmartPointer(CSmtPtr<CRefCounted> *pSmtPtr)\r\n{\r\n\t//debug_validate_smart_pointers();\r\n\t\r\n\tDbg_Assert(!pSmtPtr->mp_prev_ptr);\r\n\tDbg_Assert(!pSmtPtr->mp_next_ptr);\r\n\tpSmtPtr->mp_next_ptr = mp_smart_ptr_list;\r\n\tif (mp_smart_ptr_list)\r\n\t\tmp_smart_ptr_list->mp_prev_ptr = pSmtPtr;\r\n\tmp_smart_ptr_list = pSmtPtr;\r\n\r\n\t//debug_validate_smart_pointers();\r\n}\r\n\r\n\r\n\r\n\r\nvoid CRefCounted::RemoveSmartPointer(CSmtPtr<CRefCounted> *pSmtPtr)\r\n{\r\n\tDbg_Assert(pSmtPtr->mp_object == this);\r\n\t//debug_validate_smart_pointers(pSmtPtr);\r\n\r\n\tif (pSmtPtr->mp_prev_ptr)\r\n\t{\r\n\t\tDbg_Assert(pSmtPtr->mp_prev_ptr->mp_next_ptr == pSmtPtr);\r\n\t\tpSmtPtr->mp_prev_ptr->mp_next_ptr = pSmtPtr->mp_next_ptr;\r\n\t}\r\n\telse\r\n\t\tmp_smart_ptr_list = pSmtPtr->mp_next_ptr;\r\n\r\n\tif (pSmtPtr->mp_next_ptr)\r\n\t{\r\n\t\tDbg_Assert(pSmtPtr->mp_next_ptr->mp_prev_ptr == pSmtPtr);\r\n\t\tpSmtPtr->mp_next_ptr->mp_prev_ptr = pSmtPtr->mp_prev_ptr;\r\n\t}\r\n\r\n\tpSmtPtr->mp_prev_ptr = NULL;\r\n\tpSmtPtr->mp_next_ptr = NULL;\r\n\t\r\n\t//debug_validate_smart_pointers();\r\n}\r\n\r\n\r\n\r\n\r\nvoid CRefCounted::debug_validate_smart_pointers(CSmtPtr<CRefCounted> *pPtrToCheckForInclusion)\r\n{\r\n\tbool included = false;\r\n\t\r\n\tCSmtPtr<CRefCounted> *p_entry = mp_smart_ptr_list;\r\n\twhile(p_entry)\r\n\t{\r\n\t\tDbg_Assert(p_entry->mp_object == this);\r\n\t\tif (p_entry->mp_prev_ptr)\r\n\t\t\tDbg_Assert(p_entry->mp_prev_ptr->mp_next_ptr == p_entry);\r\n\t\tif (p_entry->mp_next_ptr)\r\n\t\t\tDbg_Assert(p_entry->mp_next_ptr->mp_prev_ptr == p_entry);\r\n\r\n\t\tif (pPtrToCheckForInclusion == p_entry)\r\n\t\t\tincluded = true;\r\n\r\n\t\tp_entry = p_entry->mp_next_ptr;\r\n\t}\r\n\r\n\tDbg_MsgAssert(!pPtrToCheckForInclusion || included, (\"smart pointer not in list as expected\"));\r\n}\r\n\r\n\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Object/basecomponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Object\r\n//* FILENAME:       basecomponent.cpp\r\n//* OWNER:          Mick West\r\n//* CREATION DATE:  10/17/2002\r\n//****************************************************************************\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent::CBaseComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent::~CBaseComponent()\r\n{\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBaseComponent::Finalize()\r\n{\r\n\t// Virtual function, can be overridden to provided finialization to \r\n\t// a component after all components have been added to an object\r\n}\r\n\r\n\r\nvoid CBaseComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calline InitFromStructure()\r\n\t// This is primarily for pre-existing components that we \r\n\t// need to update\r\n\t//\r\n\t// Components that are created from EmptyComponent.cpp/h should\r\n\t// have the funtion automatically overridden\r\n\r\n\tprintf (\"WARNING:  Refreshing component %s using InitFromStructure\\n\");  \r\n\tInitFromStructure(pParams);\r\n}\r\n\r\nvoid CBaseComponent::ProcessWait( Script::CScript * pScript )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// By default, a component has no member functions\r\n// so attempting to call one will just return MF_NOT_EXECUTED\r\nCBaseComponent::EMemberFunctionResult CBaseComponent::CallMemberFunction( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\treturn MF_NOT_EXECUTED;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBaseComponent::Suspend(bool suspend)\r\n{\r\n\tm_flags.Set(BC_NO_UPDATE, suspend);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBaseComponent::Hide( bool shouldHide )\r\n{\r\n\t// the base component does nothing,\r\n\t// but some components need to do extra stuff\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBaseComponent::Teleport()\r\n{\r\n\t// the base component does nothing,\r\n\t// but some components need to do extra stuff\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Used by the script debugger code to fill in a structure\r\n// for transmitting to the monitor.exe utility running on the PC.\r\nvoid CBaseComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CBaseComponent::GetDebugInfo\"));\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tp_info->AddInteger(\"CPUTime\",m_update_time);\r\n\t#endif\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Object/basecomponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Object\r\n//* FILENAME:       BaseComponent.h\r\n//* OWNER:          Mick West\r\n//* CREATION DATE:  10/17/2002\r\n//****************************************************************************\r\n\r\n#ifndef __OBJECT_BASECOMPONENT_H__\r\n#define __OBJECT_BASECOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object.h>\r\n\r\nnamespace Script\r\n{\r\n    class CStruct;\r\n    class CScript;\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\r\n// CBaseComponent is a virtual base class for object components\r\nclass CBaseComponent : public Spt::Class\r\n{\r\n\tfriend\tclass\tCCompositeObject;\r\n\r\n\t\r\npublic:\r\n    CBaseComponent();\r\n    virtual ~CBaseComponent();\r\n\r\n\t// Possible results from calling CallMemberFunction\r\n\t// (If the order of these change, then please\r\n\t// also change Gfx::EAnimFunctionResult)\r\n\tenum EMemberFunctionResult\r\n\t{\r\n\t\tMF_FALSE \t\t= 0,\r\n\t\tMF_TRUE  \t\t= 1,\r\n\t\tMF_NOT_EXECUTED = 2\r\n\t};\r\n\t\r\n\tenum EBaseComponentFlags\r\n\t{\r\n\t\tBC_NO_UPDATE\r\n\t};\r\n\r\n\r\npublic:\r\n\tvirtual\tvoid \t\t\t\t\tUpdate() = 0;\r\n    virtual void \t\t\t\t\tInitFromStructure( Script::CStruct* pParams ) = 0;\r\n\tvirtual\tvoid \t\t\t\t\tFinalize();\r\n    virtual void \t\t\t\t\tRefreshFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tProcessWait( Script::CScript * pScript );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetObject(CCompositeObject* p_object) {mp_object = p_object;}\r\n\tCCompositeObject*\t\t\t\tGetObject() const {return mp_object;}\r\n\tCBaseComponent*\t\t\t\t\tGetNext() const {return mp_next;}\r\n\tCBaseComponent*\t\t\t\t\tGetNextSameType() const {return mp_next_same_type;}\r\n\tvoid\t\t\t\t\t\t\tSetNextSameType( CBaseComponent *p_component ){ mp_next_same_type = p_component; }\r\n\tuint32\t\t\t\t\t\t\tGetType() const {return m_type;}\r\n\tvirtual\tvoid\t\t\t\t\tSuspend(bool suspend);\r\n\tbool\t\t\t\t\t\t\tIsSuspended() const { return m_flags.Test(BC_NO_UPDATE); }\r\n\tvirtual void\t\t\t\t\tHide(bool shouldHide);\r\n\tvirtual void\t\t\t\t\tTeleport();\r\n\r\n\t// Used by the script debugger code to fill in a structure\r\n\t// for transmitting to the monitor.exe utility running on the PC.\r\n\tvirtual void\t\t\t\t\tGetDebugInfo(Script::CStruct *p_info);\r\n\r\npublic:\r\n\tvirtual EMemberFunctionResult \tCallMemberFunction( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript );\r\n\t\r\nprotected:\r\n\tvoid\t\t\t\t\t\t\tSetType(uint32 type) {m_type = type;}\r\n\r\nprivate:\r\n\tuint32\t\t\t\t\t\t\tm_type;\t   \t\t\t// Unique ID of the component, stuck here during constuction\r\n\tFlags<EBaseComponentFlags>\t\tm_flags;\r\n\tCCompositeObject\t* \t\t\tmp_object; \t\t\t// Parent object that contains this component\r\n\tCBaseComponent * \t\t\t\tmp_next;\t\t\t// next component in the list\r\n\tCBaseComponent * \t\t\t\tmp_next_same_type;\t// next component in the list that is of the same type\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\t// The time spent (in microseconds) executing ::Update(), for displaying in the script debugger.\r\n\tint\t\t\t\t\t\t\t\tm_update_time;\r\n\t#endif\t\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Object/compositeobject.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Object\r\n//* FILENAME:       compositeobject.cpp\r\n//* OWNER:          Mick West\r\n//* CREATION DATE:  10/17/2002\r\n//****************************************************************************\r\n\r\n/***************************************************************************\r\n A composite object is a generic object which basically consists of:\r\n - a position and orientation\r\n - some flags\r\n - a script\r\n - a list of components\r\n \r\n The purpose of the Composite Object is to represent a thing that exists \r\n in the game world.  For example:\r\n \r\n  - Cars and other vechicals\r\n  - Pedestrians, animals, etc\r\n  - Pickup Icons\r\n  - 3D sound emitters\r\n  - Particle systems\r\n  - Skaters or other player type objects\r\n  - Bouncy Objects like trash cans\r\n\r\n CCompositeObject is derived from CObject, so all CCompositeObjects have\r\n a mp_script (which might be NULL)\r\n \r\n A composite object is normally comprised of several components.  These are \r\n generally independent things such as:\r\n  - A Model\tcomponet\r\n  - A physics component (e.g., drive around, or skating)\r\n  - A suspend component\r\n  - and various other components as needed\r\n  \r\n There is one global list of all composite objects.  This is managed by the \r\n CCompositeObjectManager class, whcih is also responsible for creating\r\n the composite objects.\r\n \r\n A composite object is typically create from an array of structs\r\n and a structe that contains the initialization parameters.\r\n \r\n Here's an example of the array of structs.  Note that some components\r\n have default parameters.  These can be overridden by the struct of parameters\r\n \r\n gameobj_composite_structure = [\r\n    { component = suspend }\r\n    { component = model  }\r\n    { component = exception }\r\n    { component = collision }\r\n ]\r\n\r\n****************************************************************************/\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectManager.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <modules/skate/skate.h>\r\n#include <sk/scripting/nodearray.h> // Needed by GetDebugInfo\r\n#include <sk/engine/feeler.h>\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCompositeObject::CCompositeObject()\r\n{\r\n    // set position and orientation to a known state (at the origin, identity matrix)\t\r\n\tm_vel.Set( 0.0f, 0.0f, 0.0f );\r\n\tm_pos.Set( 0.0f, 0.0f, 0.0f );\r\n\tm_matrix.Ident();\r\n\tm_display_matrix.Ident();\r\n\r\n\tmp_component_list = NULL;\r\n\tm_composite_object_flags.ClearAll();\r\n\r\n\tSetFlags( GetFlags() | vCOMPOSITE);   // Kind of a temp solution for now\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCompositeObject::~CCompositeObject()\r\n{   \r\n\twhile ( mp_component_list )\r\n    {\r\n\t\t// Get the component at the head of the list\t\t\r\n\t\tCBaseComponent* pComponent = mp_component_list;\r\n\t\t\r\n\t\t// advance the list past this component, effectivly isolating it\r\n\t\t// (unless someone else is storing a pointer to it)\r\n\t\tmp_component_list =  pComponent->mp_next;\r\n\t\t\r\n\t\t// remove the component from the by-type list of components maintained by the CompositeObjectManager\r\n\t\tObj::CCompositeObjectManager::Instance()->RemoveComponentByType( pComponent );\r\n\r\n\t\t// delete the isolated component\r\n\t\tdelete pComponent;   \r\n\t\t     \r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n#ifdef __NOPT_ASSERT__\r\n// Runs through all the components and zeroes their update times.\r\nvoid CCompositeObject::zero_component_update_times()\r\n{\r\n\tCBaseComponent* pComponent = mp_component_list;\r\n    while ( pComponent )\r\n    {\r\n\t\tpComponent->m_update_time=0;\r\n        pComponent = pComponent->mp_next;\r\n    }\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompositeObject::Update()\r\n{\r\n#ifdef __USE_PROFILER__\r\n\tSys::CPUProfiler->PushContext( m_profile_color );\r\n#endif // __USE_PROFILER__\r\n\r\n\tDbg_MsgAssert(IsFinalized(),(\"Update called on UnFinalized Composite object %s\",Script::FindChecksumName(GetID())));\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\t// GJ:  don't do this if the composite object is paused,\r\n\t// because some lock obj component might be trying\r\n\t// to lock to this object while the game is paused\r\n\tif (!m_composite_object_flags.Test(CO_SUSPENDED)\r\n\t\t&& !m_composite_object_flags.Test(CO_PAUSED))\r\n\t{\r\n\t\t// clear out the display matrix, to make \r\n\t\t// sure that no one's relying on the\r\n\t\t// last frame's matrix                                                                                               \r\n\t\tm_display_matrix.Ident();\r\n\t}\r\n#endif\r\n\t\r\n#ifdef __NOPT_ASSERT__\r\n\t// Make sure the component update times are initialized to zero so that they do not\r\n\t// show incorrect old values in the debugger if this function returns before\r\n\t// getting to the component update loop.\r\n\tzero_component_update_times();\r\n\t\r\n\tm_total_script_update_time=0;\r\n\tm_do_game_logic_time=0;\r\n#endif\r\n\r\n\tif (m_composite_object_flags.Test(CO_PAUSED))\r\n\t{\r\n#ifdef __USE_PROFILER__\r\n\tSys::CPUProfiler->PopContext();\r\n#endif // __USE_PROFILER__\r\n\t\treturn;\r\n\t}\r\n\r\n\r\n\tif (!m_composite_object_flags.Test(CO_SUSPENDED))\r\n\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\tTmr::CPUCycles time_before=Tmr::GetTimeInCPUCycles();\r\n#endif\r\n\t\tif ( mp_script )\r\n\t\t{\r\n\t\t\tif ( mp_script->Update() == Script::ESCRIPTRETURNVAL_FINISHED )\r\n\t\t\t{\r\n\t\t\t\t// if we have script based events then we only want to kill the script if\r\n\t\t\t\t// it has an empty event handler table\r\n\t\t\t\t// as a script can finish, but still have event handlers\r\n\t\t\t\t// this kind of logic will be duplicated in various places in the code\r\n\t\t\t\t// so we could do with a bit of refactoring\r\n\t\t\t\t// like a mp_script->CanBeDeleted() function\r\n\t\t\t\t#ifdef\t__SCRIPT_EVENT_TABLE__\t \r\n\t\t\t\t\t// in practice it seems okay to just leave the script\r\n\t\t\t\t\t// probably not a big issue   \r\n\t\t\t\t#else\r\n\t\t\t\t\tdelete mp_script;\r\n\t\t\t\t\tmp_script = NULL;\r\n\t\t\t\t#endif\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// if a script has called \"Die\",\r\n\t\t// then don't update the components\r\n\t\tif ( IsDead() )\r\n\t\t{\r\n\t\t\t#\tifdef __USE_PROFILER__\r\n\t\t\t\tSys::CPUProfiler->PopContext();\r\n\t\t\t#\tendif // __USE_PROFILER__\r\n\t\t\treturn;\r\n\t\t}\r\n#ifdef __NOPT_ASSERT__\r\n\t\t// Convert to microseconds by dividing by 150\r\n\t\tm_total_script_update_time=(Tmr::GetTimeInCPUCycles()-time_before)/150;\r\n#endif\r\n\r\n\t\t// transition-only function call,\r\n\t\t// call each specific object's\r\n\t\t// DoGameLogic() function (previously,\r\n\t\t// this was called by each object's task)\r\n#ifdef __NOPT_ASSERT__\r\n\t\ttime_before=Tmr::GetTimeInCPUCycles();\r\n#endif\r\n\t\t// Mick:  DoGameLogic is Deprecated, and only exists for a few misc objects\r\n\t\t// it should eventually be removed\r\n\t\tDoGameLogic();\r\n#ifdef __NOPT_ASSERT__\r\n\t\t// Convert to microseconds by dividing by 150\r\n\t\tm_do_game_logic_time=(Tmr::GetTimeInCPUCycles()-time_before)/150;\r\n#endif\r\n\r\n\t}\r\n\r\n\tCBaseComponent* pComponent = mp_component_list;\r\n    while ( pComponent )\r\n    {\r\n\t\tif ( ! (pComponent->m_flags.Test(CBaseComponent::BC_NO_UPDATE)))\r\n\t\t{\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tTmr::CPUCycles time_before_components=Tmr::GetTimeInCPUCycles();\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tpComponent->Update();\r\n\t\t\t\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t// Convert to microseconds by dividing by 150\r\n\t\t\tpComponent->m_update_time=(Tmr::GetTimeInCPUCycles()-time_before_components)/150;\r\n\t\t\t#endif\r\n\r\n\t\t\t// If a component update has killed the object\r\n\t\t\t// then we don't process any more components\r\n\t\t\t// as they might attempt to fire an event, or reference this object in some way\r\n\t\t\t// and it won't be in the tracking system any more\r\n\t\t\tif (IsDead())\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\r\n\t\t}\r\n        pComponent = pComponent->mp_next;\r\n    }\r\n\t#\tifdef __USE_PROFILER__\r\n\t\tSys::CPUProfiler->PopContext();\r\n\t#\tendif // __USE_PROFILER__\r\n\t\r\n\tm_composite_object_flags.Clear(CO_TELEPORTED);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCompositeObject::Hide( bool should_hide )\r\n{\r\n\tif ( should_hide == m_composite_object_flags.Test(CO_HIDDEN) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tm_composite_object_flags.Set(CO_HIDDEN, should_hide);\r\n\t\t\r\n\t// loop through all the components\r\n\t// and call their individual Hide functions...\r\n\tCBaseComponent* pComponent = mp_component_list;\r\n\twhile ( pComponent )\r\n\t{\r\n\t\tpComponent->Hide( should_hide );\r\n\t\tpComponent = pComponent->mp_next;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Suspending a composite object tells it not to update the script\r\n// but the individual components take care of suspending themselves\r\n// (Generally handled by the BC_NO_UPDATE flag being set)\t\r\n// \"suspending\" is generally soemthing done when the object goes a\r\n// certain distance from the camera\r\nvoid CCompositeObject::Suspend(bool suspended)\r\n{\r\n    if (suspended == m_composite_object_flags.Test(CO_SUSPENDED)) return;\r\n\t\r\n\tm_composite_object_flags.Set(CO_SUSPENDED, suspended);\r\n\t\r\n\t// suspend the individual components\r\n\tCBaseComponent* pComponent = mp_component_list;\r\n\twhile ( pComponent )\r\n\t{\r\n\t\tpComponent->Suspend(suspended);\r\n\t\tpComponent = pComponent->mp_next;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompositeObject::Teleport()\r\n{\r\n\t// calls each component's Teleport() function so\r\n\t// that things like the model, the collision, and the\r\n\t// shadow can be updated immediately when the\r\n\t// object has radically changed position\r\n\tCBaseComponent* pComponent = mp_component_list;\r\n\twhile ( pComponent )\r\n\t{\r\n\t\tpComponent->Teleport();\r\n\t\tpComponent = pComponent->mp_next;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompositeObject::AddComponent( CBaseComponent* pComponent )\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tif ( GetComponent( pComponent->GetType() ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Object already has a component of type '%s'\", Script::FindChecksumName(pComponent->GetType()) ) );\r\n\t}\r\n#endif\r\n\r\n\tDbg_MsgAssert(!IsFinalized(),(\"Adding Component %s to Finalized Composite object %s\",Script::FindChecksumName(pComponent->GetType()),Script::FindChecksumName(GetID())));\r\n\r\n\tif (!mp_component_list)\r\n\t{\r\n\t\tmp_component_list = pComponent;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCBaseComponent* p_tail = mp_component_list;\r\n\t\twhile(p_tail->mp_next)\r\n\t\t{\r\n\t\t\tp_tail = p_tail->mp_next;\r\n\t\t}\r\n\t\tp_tail->mp_next = pComponent;\r\n\t}\r\n\r\n    // now that the component is \"officially\" associated with\r\n    // this object, we can set the component's object ptr\r\n    pComponent->SetObject( this );\r\n\r\n\t// add the component to the by-type list of components maintained by the CompositeObjectManager\r\n\tObj::CCompositeObjectManager::Instance()->AddComponentByType( pComponent );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given a single component definition in the form:\r\n// {\r\n// \t\tcomponent = ...\r\n//      .... other params\r\n// }\r\n//\r\n// Then create a component of the correct type\r\n// add it to this object\r\n// and initialize it with this structure\r\n//\r\n// Optionally supply a seperate additional p_params structure from which to initialize it\r\n\r\nvoid CCompositeObject::CreateComponentFromStructure(Script::CStruct *p_struct, Script::CStruct *p_params)\r\n{\r\n\tuint32\tcomponent_name;\r\n\tp_struct->GetChecksum(\"component\",&component_name,Script::ASSERT);\r\n\tObj::CBaseComponent* p_component = Obj::CCompositeObjectManager::Instance()->CreateComponent(component_name);\r\n\tAddComponent(p_component);\t // Add it first, as InitFromStructure might need to query the object\r\n\tif (p_params)\r\n\t{\r\n\t\t// If we have additional parameters, then add then in to the parameters in the array\r\n\t\t// this will override the array paramaeters, which are assumed to be defaults\r\n\t\tScript::CScriptStructure *p_combinedParams=new Script::CScriptStructure;\r\n\t\t*p_combinedParams += *p_struct;\r\n\t\t*p_combinedParams += *p_params;\r\n\t\tp_component->InitFromStructure(p_combinedParams);\r\n\t\tdelete p_combinedParams;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// No additional parameters, so just initialze from the params in the structure in the array\r\n\t\tp_component->InitFromStructure(p_struct);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given an array of component definitions in the form:\r\n// [\r\n//   { component = ......\r\n//     ... other params .....\r\n//   }\r\n//   {\r\n//    ... other components\r\n//   }\r\n// ]\r\n// then iterate over the array, and add the components to the composite object\r\n//\r\n// Optionally supply a \"p_params\" structure that contains all the initialization info\r\n// instead of interleaving it in the array \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\nvoid CCompositeObject::CreateComponentsFromArray(Script::CArray *p_array, Script::CStruct* p_params)\r\n{\r\n\tint num_components = p_array->GetSize();\r\n\tfor (int i=0;i<num_components;i++)\r\n\t{\r\n\t\tScript::CStruct* p_struct = p_array->GetStructure(i);\r\n        CreateComponentFromStructure(p_struct, p_params);\r\n\t}\r\n}\r\n\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently isfrequently the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CCompositeObject::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tuint32 NameChecksum;\r\n\tif ( pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &NameChecksum ))\r\n\t{\r\n\t\tSetID(NameChecksum);\r\n\t}\r\n\t\r\n\tSkateScript::GetPosition(pParams,&m_pos);\r\n\t\r\n\tSkateScript::GetOrientation(pParams,&m_matrix);\r\n\t\r\n#\tifdef __USE_PROFILER__\r\n\tint ProfileColor = 0x800000;\t\t\t// default to blue profile color\t\t\r\n\tpParams->GetInteger( CRCD(0x72444899,\"ProfileColor\"), &ProfileColor );\r\n\tSetProfileColor(ProfileColor);\r\n#\tendif // __USE_PROFILER__\r\n\r\n\tif (pParams->ContainsFlag(CRCD(0x23627fd7,\"permanent\")))\r\n\t{\r\n\t\tSetFlags( GetFlags() | vLOCKED);\r\n\t}\r\n}\r\n\r\n\r\n// Finalize is called after all components have been added\r\n// and will call the virtual Finalize() function on each component\r\n// This is intended for any components that are depended on other components\r\n// but where the initialization order can't be guaranteed\r\nvoid CCompositeObject::Finalize()\r\n{\r\n\tDbg_MsgAssert(!IsFinalized(),(\"Finalizing Composite object %s twice\",Script::FindChecksumName(GetID())));\r\n\tCBaseComponent *p_component = mp_component_list;\r\n\twhile (p_component)\r\n\t{\r\n\t\tp_component->Finalize();\r\n\t\tp_component = p_component->GetNext();\r\n\t}\r\n\tm_composite_object_flags.Set(CO_FINALIZED);\r\n\r\n\t// now that the component is finalized,\r\n\t// update the components that depend\r\n\t// on the position of the object\r\n\tTeleport();\r\n}\r\n\r\n\r\n// RefreshFromStructure is passed the same parameters as the above\r\n// but will use them to update \r\nvoid CCompositeObject::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Make sure they are not trying to change the id to something else\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tuint32 NameChecksum;\r\n\tif ( pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &NameChecksum ))\r\n\t{\r\n\t\tDbg_MsgAssert(GetID() == NameChecksum,(\"Attempting to refresh id from %s to %s\\n\", Script::FindChecksumName(GetID()),NameChecksum));\r\n\t}\r\n\t#endif\r\n\r\n\t// Update the position\t\r\n\t// Note this is just cut and paste from above\r\n\t// so if we're going to be doing more initting of the composite object\r\n\t// from a script struct, then we might want to factor it out\r\n\tSkateScript::GetPosition(pParams,&m_pos);\r\n\t\r\n\t// Now iterate over the components, and Refresh them\r\n\tCBaseComponent* pComponent = mp_component_list;\r\n    while ( pComponent )\r\n    {\r\n\t\tpComponent->RefreshFromStructure(pParams);\r\n        pComponent = pComponent->mp_next;\r\n    }\r\n\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CCompositeObject::GetComponent( uint32 id ) const\r\n{\r\n\tCBaseComponent *p_component = mp_component_list;\r\n\twhile (p_component)\r\n\t{\r\n\t\tif (p_component->GetType() == id)\r\n\t\t{\t\r\n\t\t\treturn p_component;\r\n\t\t}\r\n\t\tp_component = p_component->GetNext();\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool \tCCompositeObject::CallMemberFunction( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\r\n\r\n\t// This should probably go in some debug component?\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | Obj_PrintDetails | This is a debug function.  Add this\r\n        // command to an object's script\r\n\t\t// and it will print the details.  Add anything you want to the Dbg_Message( )\r\n\t\t// below.\r\n        // @uparmopt \"string\" | text to print\r\n\t\tcase 0xc2404947: // Obj_PrintDetails\r\n\t\t{\r\n\t\t\tconst char* pText;\r\n\t\t\tif ( pParams->GetText( NONAME, &pText ) )\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"%s\", pText );\r\n\t\t\t}\r\n\t\t\tDbg_Message( \"Obj details:\\n  pos %f %f %f\\n  time %d\\n  type %d\",\r\n\t\t\t\tm_pos[ X ], m_pos[ Y ], m_pos[ Z ], Tmr::GetTime(), m_type );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\t// @script | CreateComponentFromStructure |\r\n\t\tcase 0x406998a5: // CreateComponentFromStructure\r\n\t\t{\r\n\t\t\tCreateComponentFromStructure( pParams, NULL );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\t// @script | Obj_GetPosition |\r\n\t\tcase 0xe90aad2d: // Obj_GetPosition\r\n\t\t{\t\t\t\t\t\t\t\t\t \r\n\t\t\tpScript->GetParams()->AddVector( CRCD(0x7f261953,\"pos\"), m_pos[X], m_pos[Y], m_pos[Z] );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\t// @script | Obj_SetPosition | Sets the world position of the object.\r\n\t\t// @parmopt vector | Position | | Position to give to the object.\r\n\t\tcase 0xf7251a64: // Obj_SetPosition\r\n\t\t{\t\t\t\t\t\t\t\t\t \r\n\t\t\tpParams->GetVector(CRCD(0xb9d31b0a,\"Position\"),&m_pos);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n\t\t// @script | Obj_SetOrientation |\r\n\t\t// @parmopt float | x | 0.0 | The x angle, in degrees\r\n\t\t// @parmopt float | y | 0.0 | The y angle, in degrees\r\n\t\t// @parmopt float | z | 0.0 | The z angle, in degrees\r\n\t\t// @parmopt vector | dir | (0,0,1) | Direction vector (an alternative to specifying angles)\r\n\t\t// The direction vector does not need to be normalized.\r\n\t\tcase 0xc6f3baa5: // Obj_SetOrientation\r\n\t\t{\r\n\t\t\tMth::Vector dir(0.0f,0.0f,1.0f);\r\n\t\t\tif (pParams->GetVector(CRCD(0x455485ef,\"dir\"),&dir))\r\n\t\t\t{\r\n\t\t\t\tMth::Matrix mat;\r\n\t\t\t\tmat.Ident();\r\n\t\t\t\t\r\n\t\t\t\tmat[Z]=dir;\r\n\t\t\t\tmat[Z].Normalize();\r\n\t\t\t\tmat[X] = Mth::CrossProduct(mat[Y], mat[Z]);\r\n\t\t\t\tmat[X].Normalize();\r\n\t\t\t\tmat[Y] = Mth::CrossProduct(mat[Z], mat[X]);\r\n\t\t\t\tmat[Y].Normalize();\r\n\t\t\t\t\r\n\t\t\t\tSetMatrix(mat);\r\n\t\t\t\tSetDisplayMatrix(mat);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfloat p=0.0f;\r\n\t\t\t\tfloat h=0.0f;\r\n\t\t\t\tfloat r=0.0f;\r\n\t\t\t\tpParams->GetFloat(CRCD(0x7323e97c,\"x\"),&p);\r\n\t\t\t\tpParams->GetFloat(CRCD(0x424d9ea,\"y\"),&h);\r\n\t\t\t\tpParams->GetFloat(CRCD(0x9d2d8850,\"z\"),&r);\r\n\t\t\t\tp*=3.141592654f/180.0f;\r\n\t\t\t\th*=3.141592654f/180.0f;\r\n\t\t\t\tr*=3.141592654f/180.0f;\r\n\t\t\t\tMth::Matrix mat(p,h,r);\r\n\t\t\t\tSetMatrix(mat);\r\n\t\t\t\tSetDisplayMatrix(mat);\r\n\t\t\t}\t\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t\tbreak;\r\n\r\n        // @script | Obj_ForceUpdate | Does a single call to the object's Update function\r\n\t\tcase 0xc1bff0f3: // Obj_ForceUpdate\r\n\t\t{\r\n\t\t\tUpdate();\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t\tbreak;\r\n\t\t\r\n\t\t// @script | Obj_GetVelocity |\r\n\t\tcase 0x11fe9f71: // Obj_GetVelocity\r\n\t\t{\t\t\t\t\t\t\t\t   \r\n\t\t\tpScript->GetParams()->AddVector( CRCD(0x0c4c809e,\"vel\"), m_vel[X], m_vel[Y], m_vel[Z] );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n\t\t// @script | GetSpeed |\r\n\t\tcase 0xc0caac4a: // GetSpeed\r\n\t\t{\t\t\t\t\t\t\t\t   \r\n\t\t\tpScript->GetParams()->AddFloat( CRCD(0xf0d90109,\"speed\"), m_vel.Length() );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n\t\t// @script | Hide | hides object\r\n\t\tcase 0x5b6634d4: // Hide\r\n\t\t{\r\n\t\t\tHide( true );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\t// @script | Unhide | unhides object\r\n\t\tcase 0xb60d1f35: // Unhide\r\n\t\t{\r\n\t\t\tHide( false );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\t// @script | IsHidden | checks the hide flag of object\r\n\t\tcase 0xb16619ae: // IsHidden\r\n\t\t{\r\n\t\t\treturn m_composite_object_flags.Test(CO_HIDDEN);\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n        // @script | Move |\r\n        // @parmopt float | x | 0.0 | x component\r\n        // @parmopt float | y | 0.0 | y component\r\n        // @parmopt float | z | 0.0 | z component\r\n\t\tcase 0x10c1c887: // Move\t\r\n\t\t{\r\n\t\t\tfloat distance = 0.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0x7323e97c, \"x\"), &distance);\r\n\t\t\tm_pos += distance * m_matrix[X];\r\n\t\t\tdistance = 0.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0x424d9ea, \"y\"), &distance);\r\n\t\t\tm_pos += distance * m_matrix[Y];\r\n\t\t\tdistance = 0.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0x9d2d8850, \"z\"), &distance);\r\n\t\t\tm_pos += distance * m_matrix[Z];\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0xce0ca665: // Suspend\r\n\t\t\tSuspend(true);\r\n\t\t\treturn true;\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0xca3c59a6: // Unsuspend\r\n\t\t\tSuspend(false);\r\n\t\t\treturn true;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase 0x28656d12: // Pause\r\n\t\t\tPause(true);\r\n\t\t\treturn true;\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0xff85d4d7: // Unpause\r\n\t\t\tPause(false);\r\n\t\t\treturn true;\r\n\t\t\tbreak;\r\n\r\n// MOVED FROM CMOVINGOBJECT.CPP\t\t\r\n\t\t\r\n\t\t// @script | Obj_GetCollision | Checks to see if there is a collision along a line in front\r\n\t\t// of the object.\r\n        // @parmopt float | Height | 3.0 | Height above origin of start point in feet\r\n        // @parmopt float | Lnegth | 3.0 | length of ocllision line in feet\r\n        // @flag side | Check side collision instead of forward collision\r\n        // @flag debug | display green debug lines at each collision test, white if there is a collision\r\n\t\tcase 0x168b09c:\t// Obj_GetCollision\r\n\t\t\t{\r\n\t\t\t\tCFeeler\tfeeler;\r\n\t\t\t\t//if (pParams->ContainsFlag(0xc4e78e22/*All*/))\r\n\t\t\t\t\r\n\t\t\t\tfloat\tlength = 3.0f;\r\n\t\t\t\tpParams->GetFloat(0xfe82614d /*length*/,&length);\r\n\t\t\t\tlength *= 12.0f;\r\n\t\t\t\tfloat\theight = 3.0f;\r\n\t\t\t\tpParams->GetFloat(0xab21af0 /*height*/,&height);\r\n\t\t\t\theight *= 12.0f;\r\n\t\t\t\t\r\n\t\t\t\tfeeler.m_start = m_pos + m_matrix[Y] * height;;\r\n\t\t\t\tfeeler.m_end = feeler.m_start;\r\n\t\t\t\tif (pParams->ContainsFlag(0xdc7ee44a/*side*/))\r\n\t\t\t\t{\r\n\t\t\t\t\tfeeler.m_end += length * m_matrix[X];\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tfeeler.m_end += length * m_matrix[Z];\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (feeler.GetCollision())\r\n\t\t\t\t{\r\n\t\t\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\t\t\tif (pParams->ContainsFlag(0x935ab858/*debug*/))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfeeler.DebugLine(255,255,255);\t // White line = collision\r\n\t\t\t\t\t}\r\n\t\t\t\t\t#endif\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\t\t\tif (pParams->ContainsFlag(0x935ab858/*debug*/))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfeeler.DebugLine(0,255,0);\t // green line = no collision\r\n\t\t\t\t\t}\r\n\t\t\t\t\t#endif\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\r\n        // @script | Obj_GetOrientation | Gets the X,Y,Z vector representing orientation \r\n\t\tcase 0xb9ed09d2: // Obj_GetOrientation\r\n\t\t{\r\n\t\t\tMth::Vector atVector;\r\n\t\t\tatVector = m_display_matrix[Mth::AT];\r\n\t\t\tatVector.Normalize();\r\n\r\n\t\t\tpScript->GetParams()->AddFloat( \"x\", atVector[X] );\r\n\t\t\tpScript->GetParams()->AddFloat( \"y\", atVector[Y] );\r\n\t\t\tpScript->GetParams()->AddFloat( \"z\", atVector[Z] );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n\t\tcase 0xd96c0a20: // Obj_GetDistToNode\r\n\t\t{\r\n\t\t\tuint32 node_name=0;\r\n\t\t\tpParams->GetChecksum(NONAME,&node_name);\r\n\t\t\tint node = SkateScript::FindNamedNode(node_name);\r\n\t\t\tMth::Vector node_pos;\r\n\t\t\tSkateScript::GetPosition(node, &node_pos);\r\n\t\t\tpScript->GetParams()->AddFloat(\"Dist\",(m_pos-node_pos).Length());\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\t\r\n        // @script | Obj_GetDistanceToObject | Calculates the distance to the specified object,\r\n\t\t// and puts the result, in units of feet, into ObjectDistance\r\n        // @uparmopt name | Name of the object. May be Skater.\r\n\t\tcase 0x4af57bbb: // Obj_GetDistanceToObject\t\r\n\t\t{\r\n\t\t\tuint32 object_name=0;\r\n\t\t\tpParams->GetChecksum(NONAME,&object_name);\r\n\t\t\tCCompositeObject* p_obj=(CCompositeObject*)Obj::ResolveToObject(object_name);\r\n\t\t\t\r\n\t\t\tfloat dist=0.0f;\r\n\t\t\tif (p_obj)\r\n\t\t\t{\r\n\t\t\t\tMth::Vector d = m_pos - p_obj->GetPos();\r\n\t\t\t\tdist=d.Length()/12.0f;\r\n\t\t\t}\r\n\t\t\tpScript->GetParams()->AddFloat(\"ObjectDistance\",dist);\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// @script | Obj_GetOrientationToObject |\r\n        // @uparm name | Name of the object. May be Skater.\r\n\t\tcase 0x2a26ffa2: // Obj_GetOrientationToObject\t\r\n\t\t{\r\n\t\t\tuint32 object_name=0;\r\n\t\t\tpParams->GetChecksum(NONAME,&object_name,Script::ASSERT);\r\n\t\t\tCCompositeObject* p_obj=(CCompositeObject*)Obj::ResolveToObject(object_name);\r\n\t\t\tDbg_MsgAssert( p_obj, ( \"Couldn't find object %s to get orientation\", Script::FindChecksumName(object_name) ) );\r\n\t\t\t\r\n    \t\tfloat dotProd=0.0f;\r\n\t\t\tfloat orientation=0.0f;\r\n\r\n\t\t\tif ( p_obj )\r\n\t\t\t{\r\n\t\t\t\t// first get the object's current right vector\r\n\t\t\t\tMth::Vector atVector;\r\n\t\t\t\tatVector = m_matrix[Mth::RIGHT];\r\n\t\t\t\tatVector[W] = 0.0f;\r\n\t\t\t\tatVector.Normalize();\r\n\r\n\t\t\t\t// now take the vector to the object\r\n\t\t\t\tMth::Vector\ttoObjVector;\r\n\t\t\t\ttoObjVector = p_obj->m_pos - m_pos;\r\n\t\t\t\ttoObjVector[W] = 0.0f;\r\n\t\t\t\ttoObjVector.Normalize();\r\n                \r\n\t\t\t\t// dot product tells us whether the right\r\n\t\t\t\t// vector is on the left or the right hand\r\n\t\t\t\t// side of the toObject vector\r\n\t\t\t\tdotProd = Mth::DotProduct( atVector, toObjVector );\r\n\r\n\t\t\t\t// subtracting 90 gets us whether the at vector is on\r\n\t\t\t\t// the left or the right...\r\n\t\t\t\torientation = Mth::RadToDeg( Mth::Kenacosf( dotProd ) ) - 90.0f;\t// add 90 to get the at vector\r\n\t\t\t}\r\n\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x7c6a7d7c,\"DotProd\"),dotProd);\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0xc97f3aa9,\"Orientation\"),orientation);\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n        // @script | Backwards | Returns true if the skater is\r\n        // facing backwards from his direction of travel.\r\n\t\tcase CRCC(0xf8cfd515, \"Backwards\"):\r\n\t\t\treturn Mth::DotProduct(m_vel, m_matrix[Z]) < 0.0f ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | SpeedEquals | true if skater speed is within 0.1 \r\n        // of the specified speed\r\n        // @uparm 1.0 | speed\r\n\t\tcase CRCC(0x7dcc5fb9, \"SpeedEquals\"):\t \r\n\t\t{\r\n\t\t\tfloat TestSpeed = 0;\r\n\t\t\tpParams->GetFloat(NO_NAME, &TestSpeed);\r\n\t\t\treturn Mth::Abs(m_vel.Length() - TestSpeed) < 0.1f ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE; \r\n\t\t}\r\n\t\t\t\r\n        // @script | SpeedGreaterThan | true if the skater speed is \r\n        // greater than the specified speed\r\n        // @uparm 1.0 | speed\r\n\t\tcase CRCC(0xe5df66d7, \"SpeedGreaterThan\"):\r\n\t\t{\r\n\t\t\tfloat TestSpeed = 0;\r\n\t\t\tpParams->GetFloat(NO_NAME, &TestSpeed);\r\n\t\t\treturn m_vel.Length() > TestSpeed ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE; \r\n\t\t}\r\n\r\n        // @script | SpeedLessThan | true if the skater speed is\r\n        // less than the specified speed\r\n        // @uparm 1.0 | speed\r\n\t\tcase CRCC(0xdd468509, \"SpeedLessThan\"):\r\n\t\t{\r\n\t\t\tfloat TestSpeed = 0;\r\n\t\t\tpParams->GetFloat(NO_NAME, &TestSpeed);\r\n\t\t\treturn m_vel.Length() < TestSpeed ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE; \r\n\t\t}\r\n\t}\r\n\r\n\r\n\tDbg_MsgAssert(IsFinalized(),(\"CallMemberFunction %s to UnFinalized Composite object %s\",Script::FindChecksumName(Checksum),Script::FindChecksumName(GetID())));\r\n\tCBaseComponent *p_component = mp_component_list;\r\n\twhile (p_component)\r\n\t{\r\n\t\tswitch (p_component->CallMemberFunction(Checksum, pParams, pScript))\r\n\t\t{\r\n\t\t\tcase CBaseComponent::MF_TRUE:\r\n\t\t\t\treturn true;\r\n\t\t\tcase CBaseComponent::MF_FALSE:\r\n\t\t\t\treturn false;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tp_component = p_component->GetNext();\r\n\t}\r\n\t\r\n\treturn CObject::CallMemberFunction( Checksum, pParams, pScript );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Used by the script debugger code (gel\\scripting\\debugger.cpp) to fill in a structure\r\n// for transmitting to the monitor.exe utility running on the PC.\r\n\r\n// This adds basic info about the CCompositeObject such as the id, position etc.\r\n// It also adds the debug info for each of the components in the list.\r\n// If classes derived from CCompositeObject override this function, then they should call\r\n// CCompositeObject::GetDebugInfo at the end.\r\n// It would not matter too much if they called it at the start instead, that would just mean\r\n// that derived classes info would appear at the end of the structure (after the list of components)\r\n// rather than at the start.\r\nvoid CCompositeObject::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CCompositeObject::GetDebugInfo\"));\r\n\t\r\n\tint node_index=SkateScript::FindNamedNode(m_id,false); // false means don't assert if not found.\r\n\tif (node_index >= 0 && m_id) // The && m_id is cos FindNamedNode erroneously returns 0 in that case.\r\n\t{\r\n\t\tScript::CStruct *p_node=SkateScript::GetNode(node_index);\r\n\t\tp_info->AddInteger(\"NodeIndex\",node_index);\r\n\t\tp_info->AddStructure(\"NodeInfo\",p_node);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_info->AddChecksum(NONAME,CRCD(0xc39ae7b3,\"NoNode\"));\r\n\t}\t\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tp_info->AddInteger(\"CPUTime\",m_update_time);\r\n\tp_info->AddInteger(\"m_total_script_update_time\",m_total_script_update_time);\r\n\tp_info->AddInteger(\"m_do_game_logic_time\",m_do_game_logic_time);\r\n\t#endif\r\n\r\n\tCObject::GetDebugInfo(p_info);\r\n\t\r\n\tuint32 type_name=0;\r\n\r\n\tswitch (m_type)\r\n\t{\r\n\t\tcase SKATE_TYPE_UNDEFINED:\r\n\t\t\ttype_name=CRCD(0x4cb79b3b,\"SKATE_TYPE_UNDEFINED\");\r\n\t\t\tbreak;\r\n\t\tcase SKATE_TYPE_SKATER: \t\t\t\r\n\t\t\ttype_name=CRCD(0xdbb4aeb6,\"SKATE_TYPE_SKATER\");\r\n\t\t\tbreak;\r\n\t\tcase SKATE_TYPE_PED:\r\n\t\t\ttype_name=CRCD(0xa88987b7,\"SKATE_TYPE_PED\");\r\n\t\t\tbreak;\r\n\t\tcase SKATE_TYPE_CAR:\r\n\t\t\ttype_name=CRCD(0x2651eacb,\"SKATE_TYPE_CAR\");\r\n\t\t\tbreak;\r\n\t\tcase SKATE_TYPE_GAME_OBJ:\t\t\t\r\n\t\t\ttype_name=CRCD(0x84f6eb36,\"SKATE_TYPE_GAME_OBJ\");\r\n\t\t\tbreak;\r\n\t\tcase SKATE_TYPE_BOUNCY_OBJ:\t\t\r\n\t\t\ttype_name=CRCD(0x5f4886c1,\"SKATE_TYPE_BOUNCY_OBJ\");\r\n\t\t\tbreak;\r\n\t\tcase SKATE_TYPE_CASSETTE:\t\t\t\r\n\t\t\ttype_name=CRCD(0xd5021817,\"SKATE_TYPE_CASSETTE\");\r\n\t\t\tbreak;\r\n\t\tcase SKATE_TYPE_ANIMATING_OBJECT:\t\r\n\t\t\ttype_name=CRCD(0x42018493,\"SKATE_TYPE_ANIMATING_OBJECT\");\r\n\t\t\tbreak;\r\n\t\tcase SKATE_TYPE_CROWN:\t\r\n\t\t\ttype_name=CRCD(0xf4f7488e,\"SKATE_TYPE_CROWN\");\r\n\t\t\tbreak;\r\n\t\tcase SKATE_TYPE_PARTICLE:\t\t\t\r\n\t\t\ttype_name=CRCD(0x8feeb37e,\"SKATE_TYPE_PARTICLE\");\r\n\t\t\tbreak;\r\n\t\tcase SKATE_TYPE_REPLAY_DUMMY:\t\t\r\n\t\t\ttype_name=CRCD(0xf4ac5a55,\"SKATE_TYPE_REPLAY_DUMMY\");\r\n\t\t\tbreak;\r\n\t\tcase SKATE_TYPE_COMPOSITE:\t\r\n\t\t\ttype_name=CRCD(0x8a61a62c,\"SKATE_TYPE_COMPOSITE\");\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\ttype_name=0;\r\n\t\t\tbreak;\r\n\t\t\r\n\t}\r\n\tif (type_name)\r\n\t{\r\n\t\tp_info->AddChecksum(\"m_type\",type_name);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// If the value is missing from the above switch statement then just add it as an integer.\r\n\t\tp_info->AddInteger(\"m_type\",m_type);\r\n\t}\r\n\t\r\n\tp_info->AddChecksum(\"m_object_flags\",m_object_flags);\r\n\r\n\t// CCompositeObject stuff\r\n\tif (m_composite_object_flags.Test(CO_PAUSED))\r\n\t{\r\n\t\tp_info->AddChecksum(NONAME,Script::GenerateCRC(\"Paused\"));\r\n\t}\r\n\t\r\n\tp_info->AddVector(\"m_pos\",m_pos.GetX(),m_pos.GetY(),m_pos.GetZ());\r\n\tp_info->AddVector(\"m_vel\",m_vel.GetX(),m_vel.GetY(),m_vel.GetZ());\r\n\t\r\n\tScript::CArray *p_mat=new Script::CArray;\r\n\tp_mat->SetSizeAndType(3,ESYMBOLTYPE_VECTOR);\r\n\tScript::CVector *p_vec=new Script::CVector;\r\n\tp_vec->mX=m_matrix[X][X]; p_vec->mY=m_matrix[X][Y]; p_vec->mZ=m_matrix[X][Z];\r\n\tp_mat->SetVector(0,p_vec);\r\n\tp_vec=new Script::CVector;\r\n\tp_vec->mX=m_matrix[Y][X]; p_vec->mY=m_matrix[Y][Y]; p_vec->mZ=m_matrix[Y][Z];\r\n\tp_mat->SetVector(1,p_vec);\r\n\tp_vec=new Script::CVector;\r\n\tp_vec->mX=m_matrix[Z][X]; p_vec->mY=m_matrix[Z][Y]; p_vec->mZ=m_matrix[Z][Z];\r\n\tp_mat->SetVector(2,p_vec);\r\n\tp_info->AddArrayPointer(\"m_matrix\",p_mat);\r\n\r\n\tp_mat=new Script::CArray;\r\n\tp_mat->SetSizeAndType(3,ESYMBOLTYPE_VECTOR);\r\n\tp_vec=new Script::CVector;\r\n\tp_vec->mX=m_display_matrix[X][X]; p_vec->mY=m_display_matrix[X][Y]; p_vec->mZ=m_display_matrix[X][Z];\r\n\tp_mat->SetVector(0,p_vec);\r\n\tp_vec=new Script::CVector;\r\n\tp_vec->mX=m_display_matrix[Y][X]; p_vec->mY=m_display_matrix[Y][Y]; p_vec->mZ=m_display_matrix[Y][Z];\r\n\tp_mat->SetVector(1,p_vec);\r\n\tp_vec=new Script::CVector;\r\n\tp_vec->mX=m_display_matrix[Z][X]; p_vec->mY=m_display_matrix[Z][Y]; p_vec->mZ=m_display_matrix[Z][Z];\r\n\tp_mat->SetVector(2,p_vec);\r\n\tp_info->AddArrayPointer(\"m_display_matrix\",p_mat);\r\n\r\n\tScript::CStruct *p_components_structure=new Script::CStruct;\r\n\tCBaseComponent *p_comp=mp_component_list;\r\n\twhile (p_comp)\r\n\t{\r\n\t\tScript::CStruct *p_component_structure=new Script::CStruct;\r\n\t\tp_comp->GetDebugInfo(p_component_structure);\r\n\t\t\r\n\t\t// Using the component type as the name given to the structure, since the\r\n\t\t// type is the checksum of the type name.\r\n\t\tp_components_structure->AddStructurePointer(p_comp->GetType(),p_component_structure);\r\n\t\tp_comp=p_comp->GetNext();\r\n\t}\r\n\t\t\r\n\tp_info->AddStructurePointer(\"Components\",p_components_structure);\r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompositeObject::SetTeleported( bool update_components )\r\n{\r\n\tm_composite_object_flags.Set(CO_TELEPORTED);\r\n\r\n\tif ( update_components )\r\n\t{\r\n\t\tTeleport();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gel/Object/compositeobject.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Object\r\n//* FILENAME:       CompositeObject.h\r\n//* OWNER:          Mick West\r\n//* CREATION DATE:  10/17/2002\r\n//****************************************************************************\r\n\r\n#ifndef __OBJECT_COMPOSITEOBJECT_H__\r\n#define __OBJECT_COMPOSITEOBJECT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/list.h>\r\n#include <core/math.h>\r\n#include <sys/profiler.h>\r\n#include <gel/object.h>\r\n#include <gel/object/basecomponent.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n// CComposite object contains a list of simple object components\r\n// which can be combined to make up complex stuff like cars and stuff\r\n\r\nclass\tCCompositeObject : public CObject\r\n{\r\n\r\npublic:\r\n\t\t\t\t\t\t\t\t\tCCompositeObject();\r\n    virtual \t\t\t\t\t\t~CCompositeObject();\r\n\r\n\tenum ECompositeObjectFlags\r\n\t{\r\n\t\tCO_PAUSED,\r\n\t\tCO_SUSPENDED,\r\n\t\tCO_HIDDEN,\r\n\t\t\r\n\t\t// components should not consider the object's change in position since the beginning of this frame to have been smooth\r\n\t\tCO_TELEPORTED,\r\n\t\t\r\n\t\t// Used by the script debugger.\r\n\t\tCO_SENDING_DEBUG_INFO_EVERY_FRAME,\r\n\t\t\r\n\t\t// Used to indicate the object has been finalized\r\n\t\t// so we can't add any more components to it\r\n\t\tCO_FINALIZED,\r\n\t};\r\n\r\n    void \t\t\t\t\t\t\tUpdate();\r\n\tvoid \t\t\t\t\t\t\tPause( bool paused )\t\t\t\t{ m_composite_object_flags.Set(CO_PAUSED, paused); }\r\n\tbool \t\t\t\t\t\t\tIsPaused( void )  const  \t\t\t{ return m_composite_object_flags.Test(CO_PAUSED); }\r\n\tvoid \t\t\t\t\t\t\tSuspend( bool suspended );\r\n\tbool\t\t\t\t\t\t\tIsSuspended( void )\tconst\t\t\t{ return m_composite_object_flags.Test(CO_SUSPENDED); }\r\n\tvoid\t\t\t\t\t\t\tHide( bool should_hide );\r\n\tbool \t\t\t\t\t\t\tIsHidden( void ) const\t\t\t\t{ return m_composite_object_flags.Test(CO_HIDDEN); }\r\n\tbool \t\t\t\t\t\t\tIsFinalized( void )\tconst\t\t\t{ return m_composite_object_flags.Test(CO_FINALIZED); }\r\n\r\n\tvoid\t\t\t\t\t\t\tSetTeleported( bool update_components = true );\r\n\tvoid\t\t\t\t\t\t\tClearTeleported( void )\t\t\t\t{ m_composite_object_flags.Clear(CO_TELEPORTED); }\r\n\tbool\t\t\t\t\t\t\tHasTeleported( void )\tconst\t\t{ return m_composite_object_flags.Test(CO_TELEPORTED); }\r\n\r\n\t// called when a model has radically changed position\r\n\tvoid\t\t\t\t\t\t\tTeleport();\r\n\r\n    void \t\t\t\t\t\t\tAddComponent( CBaseComponent* pComponent );\r\n\t\r\n\tvoid            \t\t\t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvoid\t\t\t\t\t\t\tFinalize();\r\n\tvoid            \t\t\t\tRefreshFromStructure( Script::CStruct* pParams );\r\n\tvoid \t\t\t\t\t\t\tCreateComponentFromStructure(Script::CStruct *p_struct, Script::CStruct* p_params = NULL);\r\n\tvoid \t\t\t\t\t\t\tCreateComponentsFromArray(Script::CArray *p_array, Script::CStruct * p_params = NULL);\r\n\tCBaseComponent* \t\t\t\tGetComponent( uint32 id ) const;\r\n\tvirtual bool \t\t\t\t\tCallMemberFunction (uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\n\t\r\n\tvoid\t\t\t\t\t\t\tLoadComponent ( CBaseComponent** pComp, uint32 id );\r\n\t\r\n\t// Used by the script debugger code (gel\\scripting\\debugger.cpp) to fill in a structure\r\n\t// for transmitting to the monitor.exe utility running on the PC.\r\n\tvirtual void\t\t\t\t\tGetDebugInfo(Script::CStruct *p_info);\r\n\tvoid\t\t\t\t\t\t\tSetDebuggerEveryFrameFlag(bool state) { m_composite_object_flags.Set(CO_SENDING_DEBUG_INFO_EVERY_FRAME,state); }\r\n\tbool\t\t\t\t\t\t\tGetDebuggerEveryFrameFlag()\t\t\t{ return m_composite_object_flags.Test(CO_SENDING_DEBUG_INFO_EVERY_FRAME); }\r\n\t\r\n\t\t\r\n\t// when a composite object is paused, spawned (non-main) scripts running on it should be paused, if the script has its mPauseWithObject flag set\r\n\tvirtual bool\t\t\t\t\tShouldUpdatePauseWithObjectScripts (   ) { return !IsPaused(); }\r\n\r\n\t\r\npublic:\r\n\tconst Mth::Vector&\t\t\t\t\tGetPos( void )\t  const   { return m_pos; }\r\n\tvoid \t\t\t\t\t\t\tSetPos(const Mth::Vector& pos) \t\t{ m_pos = pos; }\r\n\tMth::Matrix&\t\t\t\t\tGetMatrix( void )\t\t\t{ return m_matrix; }\r\n\tvoid\t\t\t\t\t\t\tSetMatrix( const Mth::Matrix& matrix )\t{ m_matrix = matrix; }\r\n\tvoid\t\t\t\t\t\t\tSetDisplayMatrix( const Mth::Matrix& matrix )\t{ m_display_matrix = matrix; }\r\n\tMth::Matrix&\t\t\t\t\tGetDisplayMatrix( void )\t{ return m_display_matrix; }\r\n\r\n//////////////////////////////\r\n// These are public only while transitioning from CMovingObject to CComposititeobject\r\npublic:\r\n\tMth::Vector\t\t\t\t\t\tm_pos;\r\n\tMth::Vector\t\t\t\t\t\tm_old_pos;\r\n\tMth::Matrix\t\t\t\t\t\tm_matrix;\r\n///////////////////////////////\t\r\n\t\r\n\t// velocity data doesn't belong here,\r\n\t// but it's needed during the transition\r\n\t// so that it doesn't break the collision code\r\n\tMth::Vector&\t\t\t\t\tGetVel( void )  { return m_vel; }\r\n\tvoid\t\t\t\t\t\t\tSetVel( const Mth::Vector& vel )\t\t\t{ m_vel = vel; }\r\n\tMth::Vector\t\t\t\t\t\tm_vel;\r\n\r\nprotected:\r\n\tMth::Matrix\t\t\t\t\t\tm_display_matrix;\t\t// final matrix used for display.  You need to rebuild this every frame\r\n\t\r\n\t// this is needed during the transition, only\r\n\t// until we move all of the specific objects'\r\n\t// logic into components.  this allows us\r\n\t// to get rid of the tasks\r\n\tvirtual void\t\t\t\t\tDoGameLogic() {}\r\n\r\nprivate:\t\r\n\tCBaseComponent*\t\t\t\t\tmp_component_list;\r\n\t\r\n\tFlags<ECompositeObjectFlags>\tm_composite_object_flags;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\t// The time (in microseconds) spent executing ::Update(), for displaying in the script debugger.\r\n\tint\t\t\t\t\t\t\t\tm_update_time;\t\t\r\n\t\r\n\tint\t\t\t\t\t\t\t\tm_total_script_update_time;\r\n\tint\t\t\t\t\t\t\t\tm_do_game_logic_time;\r\n\t\r\n\t// Runs through all the components and zeroes their update times.\r\n\tvoid\t\t\t\t\t\t\tzero_component_update_times();\r\npublic:\r\n\tvoid\t\t\t\t\t\t\tSetUpdateTime(int t) {m_update_time=t;}\r\n\tint\t\t\t\t\t\t\t\tGetUpdateTime() const {return m_update_time;}\r\nprivate:\t\r\n\t#endif\t\r\n\r\n#ifdef __USE_PROFILER__\r\npublic:\t\r\n\tvoid \t\t\t\t\t\t\tSetProfileColor(uint32 ProfileColor) {m_profile_color = ProfileColor;} \r\n\tuint32 \t\t\t\t\t\t\tGetProfileColor() const {return m_profile_color;} \r\nprivate:\r\n\tuint32\t\t\t\t\t\t\tm_profile_color;\r\n#else\r\npublic:\t\r\n\tvoid \t\t\t\t\t\t\tSetProfileColor(uint32 ProfileColor) {;} \r\n#endif\t\r\n\t\r\n\t// Composite objects have some common components hard wired, as it\r\n\t// much simpler and more efficient to do it that way\t\r\n};\r\n\r\ninline void CCompositeObject::LoadComponent ( CBaseComponent** pComp, uint32 id )\r\n{\r\n\tif (!*pComp)\r\n\t{\r\n\t\t*pComp = GetComponent(id);\r\n\t}\r\n\tDbg_Assert(*pComp);\r\n}\r\n\r\n}\r\n\r\n#endif\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Object/compositeobjectmanager.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Object\r\n//* FILENAME:       CompositeObjectManager.cpp\r\n//* OWNER:          Mick West\r\n//* CREATION DATE:  10/17/2002\r\n//****************************************************************************\r\n\r\n#include <gel/object/compositeobjectmanager.h>\r\n\r\n#include <core/list/node.h>\r\n#include <core/list/search.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\n#include <sk/modules/frontend/frontend.h>\r\n\r\n// move these to the component factory\r\n#include <gel/components/skeletoncomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/modellightupdatecomponent.h>\r\n#include <gel/components/bouncycomponent.h>\r\n#include <gel/components/particlecomponent.h>\r\n#include <gel/components/soundcomponent.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/collisioncomponent.h>\r\n#include <gel/components/lockobjcomponent.h>\r\n#include <gel/components/carphysicscomponent.h>\r\n#include <gel/components/motioncomponent.h>\r\n#include <gel/components/suspendcomponent.h>\r\n#include <gel/components/trickcomponent.h>\r\n#include <gel/components/avoidcomponent.h>\r\n#include <gel/components/pedlogiccomponent.h>\r\n#include <gel/components/rigidbodycomponent.h>\r\n#include <gel/components/shadowcomponent.h>\r\n#include <gel/components/streamcomponent.h>\r\n#include <gel/components/specialitemcomponent.h>\r\n#include <gel/components/vehiclecomponent.h>\r\n#include <gel/components/vehiclecameracomponent.h>\r\n#include <gel/components/nodearraycomponent.h>\r\n#include <gel/components/railmanagercomponent.h>\r\n#include <gel/components/objecthookmanagercomponent.h>\r\n#include <gel/components/skitchcomponent.h>\r\n//#include <gel/components/nearcomponent.h>\r\n#include <gel/components/cameracomponent.h>\r\n#include <gel/components/skatercameracomponent.h>\r\n#include <gel/components/vibrationcomponent.h>\r\n#include <gel/components/proximtriggercomponent.h>\r\n#include <gel/components/triggercomponent.h>\r\n#include <gel/components/floatinglabelcomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/walkcomponent.h>\r\n#include <gel/components/walkcameracomponent.h>\r\n#include <gel/components/cameralookaroundcomponent.h>\r\n#include <gel/components/movablecontactcomponent.h>\r\n#include <gel/components/vehiclesoundcomponent.h>\r\n#include <gel/components/statsmanagercomponent.h>\r\n#include <gel/components/velocitycomponent.h>\r\n#include <gel/components/collideanddiecomponent.h>\r\n#include <gel/components/setdisplaymatrixcomponent.h>\r\n#include <gel/components/staticvehiclecomponent.h>\r\n#include <sk/components/skaterstancepanelcomponent.h>\r\n#include <sk/components/skaterloopingsoundcomponent.h>\r\n#include <sk/components/skatersoundcomponent.h>\r\n#include <sk/components/skatergapcomponent.h>\r\n#include <sk/components/skaterrotatecomponent.h>\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n#include <sk/components/skaternonlocalnetlogiccomponent.h>\r\n#include <sk/components/skaterlocalnetlogiccomponent.h>\r\n#include <sk/components/skaterscorecomponent.h>\r\n#include <sk/components/skatermatrixqueriescomponent.h>\r\n#include <sk/components/skaterfloatingnamecomponent.h>\r\n#include <sk/components/skaterstatehistorycomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skateradjustphysicscomponent.h>\r\n#include <sk/components/skaterfinalizephysicscomponent.h>\r\n#include <sk/components/skaterproximitycomponent.h>\r\n#include <sk/components/skatercleanupstatecomponent.h>\r\n#include <sk/components/skaterendruncomponent.h>\r\n#include <sk/components/skaterbalancetrickcomponent.h>\r\n#include <sk/components/skaterflipandrotatecomponent.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n#include <sk/components/goaleditorcomponent.h>\r\n#include <sk/components/raileditorcomponent.h>\r\n#include <sk/components/editorcameracomponent.h>\r\n#include <sk/components/projectilecollisioncomponent.h>\r\n#include <sk/components/skaterruntimercomponent.h>\r\n\r\n#ifdef TESTING_GUNSLINGER\r\n#include <gel/components/horsecomponent.h>\r\n#include <gel/components/horsecameracomponent.h>\r\n#include <gel/components/ridercomponent.h>\r\n#include <gel/components/weaponcomponent.h>\r\n#endif\r\n\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\nDefineSingletonClass( CCompositeObjectManager, \"Composite Manager\" );\r\n\r\nCBaseComponent*\tCCompositeObjectManager::mp_components_by_type[vMAX_COMPONENTS];\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCompositeObjectManager::CCompositeObjectManager()\r\n{\r\n    mp_logic_task = new Tsk::Task< CCompositeObjectManager > ( CCompositeObjectManager::s_logic_code, *this, Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_COMPOSITE_MANAGER );\r\n\t\r\n    Mlp::Manager* mlp_manager =  Mlp::Manager::Instance(); \r\n\tmlp_manager->AddLogicTask( *mp_logic_task );\r\n\r\n\t// Register the default component objects\r\n\t// This also might be better moved to a CComponentFactory class\r\n\t// but let's see how it works first.\r\n\t\r\n\tRegisterComponent(CRC_SKATERSTANCEPANEL,\tCSkaterStancePanelComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERLOOPINGSOUND,\tCSkaterLoopingSoundComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERSOUND,\t\t\tCSkaterSoundComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERGAP,\t\t\tCSkaterGapComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERROTATE,\t\t\tCSkaterRotateComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERPHYSICSCONTROL,\tCSkaterPhysicsControlComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERLOCALNETLOGIC,\tCSkaterLocalNetLogicComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERNONLOCALNETLOGIC,\tCSkaterNonLocalNetLogicComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERSCORE,\t\t\tCSkaterScoreComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERMATRIXQUERIES,\tCSkaterMatrixQueriesComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERFLOATINGNAME,\tCSkaterFloatingNameComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERSTATEHISTORY,\tCSkaterStateHistoryComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERCOREPHYSICS,\tCSkaterCorePhysicsComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERADJUSTPHYSICS,\tCSkaterAdjustPhysicsComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERFINALIZEPHYSICS,\tCSkaterFinalizePhysicsComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERCLEANUPSTATE,\tCSkaterCleanupStateComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERENDRUN,\t\t\tCSkaterEndRunComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERBALANCETRICK,\tCSkaterBalanceTrickComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERFLIPANDROTATE,\tCSkaterFlipAndRotateComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERSTATE,\t\t\tCSkaterStateComponent::s_create);\r\n\tRegisterComponent(CRC_GOALEDITOR,\t\t\tCGoalEditorComponent::s_create); \t\r\n\tRegisterComponent(CRC_RAILEDITOR,\t\t\tCRailEditorComponent::s_create); \t\r\n\tRegisterComponent(CRC_SKATERPROXIMITY,\t\tCSkaterProximityComponent::s_create);\r\n\tRegisterComponent(CRC_EDITORCAMERA,\t\t\tCEditorCameraComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERRUNTIMER,\t\tCSkaterRunTimerComponent::s_create);\r\n\t\r\n\tRegisterComponent(CRC_MODEL,\t\t\t\tCModelComponent::s_create); \r\n\tRegisterComponent(CRC_MODELLIGHTUPDATE,\t\tCModelLightUpdateComponent::s_create); \r\n\tRegisterComponent(CRC_BOUNCY,\t\t\t\tCBouncyComponent::s_create); \r\n\tRegisterComponent(CRC_SKELETON,\t\t    \tCSkeletonComponent::s_create); \r\n\tRegisterComponent(CRC_ANIMATION,\t\t\tCAnimationComponent::s_create); \r\n\tRegisterComponent(CRC_SOUND,\t\t    \tCSoundComponent::s_create); \r\n\tRegisterComponent(CRC_COLLISION,\t\t\tCCollisionComponent::s_create); \r\n\tRegisterComponent(CRC_LOCKOBJ,\t\t\t\tCLockObjComponent::s_create, CLockObjComponent::s_register); \r\n\tRegisterComponent(CRC_CARPHYSICS,\t\t\tCCarPhysicsComponent::s_create);\r\n\tRegisterComponent(CRC_MOTION,\t\t\t\tCMotionComponent::s_create); \r\n\tRegisterComponent(CRC_SUSPEND,\t\t\t\tCSuspendComponent::s_create, CSuspendComponent::s_register); \r\n\tRegisterComponent(CRC_TRICK,\t\t\t\tCTrickComponent::s_create);\r\n\tRegisterComponent(CRC_AVOID,\t\t\t\tCAvoidComponent::s_create);\r\n\tRegisterComponent(CRC_PEDLOGIC,\t\t\t\tCPedLogicComponent::s_create);\r\n\tRegisterComponent(CRC_RIGIDBODY,\t\t\tCRigidBodyComponent::s_create);\r\n\tRegisterComponent(CRC_SHADOW,\t\t\t\tCShadowComponent::s_create);\r\n\tRegisterComponent(CRC_STREAM,\t\t\t\tCStreamComponent::s_create);\r\n\tRegisterComponent(CRC_SPECIALITEM,\t\t\tCSpecialItemComponent::s_create);\r\n\tRegisterComponent(CRC_VEHICLE,\t\t\t\tCVehicleComponent::s_create); \r\n\tRegisterComponent(CRC_VEHICLECAMERA,\t\tCVehicleCameraComponent::s_create); \r\n\tRegisterComponent(CRC_NODEARRAY,\t\t\tCNodeArrayComponent::s_create); \r\n\tRegisterComponent(CRC_RAILMANAGER,\t\t\tCRailManagerComponent::s_create); \r\n\tRegisterComponent(CRC_OBJECTHOOKMANAGER,\tCObjectHookManagerComponent::s_create); \r\n\tRegisterComponent(CRC_SKITCH,\t\t\t\tCSkitchComponent::s_create);\r\n//\tRegisterComponent(CRC_NEAR,\t\t\t\t\tCNearComponent::s_create);\r\n\tRegisterComponent(CRC_CAMERA,\t\t\t\tCCameraComponent::s_create);\r\n\tRegisterComponent(CRC_SKATERCAMERA,\t\t\tCSkaterCameraComponent::s_create);\r\n\tRegisterComponent(CRC_VIBRATION,\t\t\tCVibrationComponent::s_create);\r\n//\tRegisterComponent(CRC_PROXIMTRIGGER,\t\tCProximTriggerComponent::s_create);\r\n\tRegisterComponent(CRC_TRIGGER,\t\t\t\tCTriggerComponent::s_create);\r\n\tRegisterComponent(CRC_FLOATINGLABEL,\t\tCFloatingLabelComponent::s_create);\r\n\tRegisterComponent(CRC_INPUT,\t\t\t\tCInputComponent::s_create);\r\n\tRegisterComponent(CRC_PARTICLE,\t\t\t\tCParticleComponent::s_create);\r\n\tRegisterComponent(CRC_WALK,\t\t\t\t\tCWalkComponent::s_create);\r\n\tRegisterComponent(CRC_WALKCAMERA,\t\t\tCWalkCameraComponent::s_create);\r\n\tRegisterComponent(CRC_CAMERALOOKAROUND,\t\tCCameraLookAroundComponent::s_create);\r\n\tRegisterComponent(CRC_MOVABLECONTACT,\t\tCMovableContactComponent::s_create);\r\n    RegisterComponent(CRC_STATSMANAGER,\t\t\tCStatsManagerComponent::s_create); \r\n    RegisterComponent(CRC_VEHICLESOUND,\t\t\tCVehicleSoundComponent::s_create); \r\n\tRegisterComponent(CRC_VELOCITY,\t\t\t\tCVelocityComponent::s_create);\r\n\tRegisterComponent(CRC_COLLIDEANDDIE,\t\tCCollideAndDieComponent::s_create);\r\n\tRegisterComponent(CRC_PROJECTILECOLLISION,\tCProjectileCollisionComponent::s_create);\r\n\tRegisterComponent(CRC_SETDISPLAYMATRIX,\t\tCSetDisplayMatrixComponent::s_create);\r\n\tRegisterComponent(CRC_STATICVEHICLE,\t\tCStaticVehicleComponent::s_create);\r\n\r\n\r\n#\tifdef TESTING_GUNSLINGER\r\n\tRegisterComponent(CRC_HORSE,\t\t\t\tCHorseComponent::s_create);\r\n\tRegisterComponent(CRC_HORSECAMERA,\t\t\tCHorseCameraComponent::s_create);\r\n\tRegisterComponent(CRC_RIDER,\t\t\t\tCRiderComponent::s_create);\r\n\tRegisterComponent(CRC_WEAPON,\t\t\t\tCWeaponComponent::s_create);\r\n#\tendif\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCompositeObjectManager::~CCompositeObjectManager()\r\n{\r\n    if ( mp_logic_task )\r\n    {\r\n        mp_logic_task->Remove();\r\n        delete mp_logic_task;\r\n    }\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCompositeObject*\tCCompositeObjectManager::CreateCompositeObject()\r\n{\r\n\tObj::CCompositeObject *p_composite = new Obj::CCompositeObject;\r\n\t\r\n\t// printf(\"+++> Frame: %i\\n\", Tmr::GetRenderFrame());\r\n\t\r\n\t// DODGY SETTING OF COMPOSITE TYPE\r\n\t// FOR TEMP PATCHING OF SYSTEMS THAT ASSUME EVERYTHING IS A CMovingObject\r\n\tp_composite->SetType(11);\t// SKATE_TYPE_COMPOSITE;\r\n\r\n    RegisterObject( *p_composite );\r\n\treturn p_composite;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given a composite object definition array, and a \"node\" style structure\r\n// with a \"name\" and \"position\"\r\n// then create the Composite object at that position, with the id or the name\r\n// and create the componets for it from the array\r\n// NOTE: this is kind of a specific utility function, added\r\n// to ease the transition from old nodearray style contruction of objects \r\n\r\nCCompositeObject* CCompositeObjectManager::CreateCompositeObjectFromNode(Script::CArray *pArray, Script::CStruct *pNodeData, bool finalize)\r\n{\r\n\tObj::CCompositeObject* pObj = CreateCompositeObject();\r\n\tpObj->InitFromStructure(pNodeData);\t\r\n\tpObj->CreateComponentsFromArray(pArray, pNodeData);\t\r\n\tif (finalize)\r\n\t{\r\n\t\tpObj->Finalize();\t\t// Finalize the interfaces between components\r\n\t}\r\n\t// printf(\"+++> Creating Composite Object:  %s\\n\", Script::FindChecksumName(pObj->GetID()));\r\n\treturn pObj;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Registering components simply adds them to the list of components that\r\n// the compositeobject manager can create\r\n// All that is passed in is a 32 bit id (of the component, e.g. CRC_MODEL)\r\n// and the callback function pointer to the s_create function\r\n\t\r\nvoid\tCCompositeObjectManager::RegisterComponent(uint32 id, CBaseComponent *(p_create_function)(), void(p_register_function)()) \r\n{\r\n\tDbg_MsgAssert(m_num_components < vMAX_COMPONENTS,(\"Too many components (%d)\",vMAX_COMPONENTS));\r\n\tm_registered_components[m_num_components].mComponentID = id;\r\n\tm_registered_components[m_num_components].mpCreateFunction = p_create_function;\r\n\tm_num_components++;\r\n\r\n\t// I'm letting the component manager control calling the \"register\" function\r\n\t// no good reason, just better encapsulation.  Prevents bugs.\r\n\tif (p_register_function)\r\n\t{\r\n\t\tp_register_function();\r\n\t}\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent*\t\tCCompositeObjectManager::CreateComponent(uint32 id)\r\n{\r\n\tfor (uint32 i=0;i<m_num_components;i++)\r\n\t{\r\n\t\tif (m_registered_components[i].mComponentID == id)\r\n\t\t{\r\n\t\t\treturn m_registered_components[i].mpCreateFunction();\t\r\n\t\t}\r\n\t}\r\n\tDbg_MsgAssert(0,(\"Component %s not registered\",Script::FindChecksumName(id)));\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompositeObjectManager::Update()\r\n{\r\n\tLst::Search< CObject > sh;\r\n\t\r\n\tuint32 stamp_mask = m_stamp_bit_manager.RequestBit();\r\n\t\r\n\t// clear the appropriate stamp bit\r\n\tfor (CObject* pObject = sh.FirstItem(m_object_list); pObject; pObject = sh.NextItem())\r\n\t{\r\n\t\tpObject->ClearStampBit(stamp_mask);\r\n\t}\r\n\t\r\n\t// traverse the object list\r\n\tdo\r\n\t{\r\n\t\t// clear the appropriate list changed bit\r\n\t\tm_list_changed &= ~stamp_mask;\r\n\t\t\r\n        CObject* pNextObject = sh.FirstItem(m_object_list);\r\n\t\t\r\n\t\twhile (pNextObject)\r\n\t\t{\r\n\t\t\tCObject* pObject = pNextObject;\r\n\t\t\tpNextObject = sh.NextItem();\r\n\t\t\t\r\n\t\t\tif (!pObject->CheckStampBit(stamp_mask))\r\n\t\t\t{\r\n\t\t\t\tpObject->SetStampBit(stamp_mask);\r\n\t\t\t\t\r\n\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\tTmr::CPUCycles time_before = Tmr::GetTimeInCPUCycles();\r\n\t\t\t\tCSmtPtr< CObject > p_smart_object = pObject;\r\n\t\t\t\tuint32 obj_id = pObject->GetID(); \r\n\t\t\t\t#endif\r\n\t\t\t\t\r\n\t\t\t\tstatic_cast< CCompositeObject* >(pObject)->Update();\r\n\t\t\t\t\r\n\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\tDbg_MsgAssert(p_smart_object, (\"Object %s has deleted itself in its Update() function\", Script::FindChecksumName(obj_id)));\r\n\t\t\t\t// Convert to microseconds by dividing by 150\r\n\t\t\t\tstatic_cast< CCompositeObject* >(pObject)->SetUpdateTime((Tmr::GetTimeInCPUCycles() - time_before) / 150);\r\n\t\t\t\t#endif\r\n\t\t\t\t\r\n\t\t\t\tif (m_list_changed & stamp_mask) break;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\twhile (m_list_changed & stamp_mask);\r\n\t\r\n\tm_stamp_bit_manager.ReturnBit(stamp_mask);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompositeObjectManager::Pause(bool paused)\r\n{\r\n\tLst::Search< CObject >\tsh;\r\n\t\r\n\tuint32 stamp_mask = m_stamp_bit_manager.RequestBit();\r\n\t\r\n\t// clear the appropriate stamp bit\r\n\tfor (CObject* pObject = sh.FirstItem(m_object_list); pObject; pObject = sh.NextItem())\r\n\t{\r\n\t\tpObject->ClearStampBit(stamp_mask);\r\n\t}\r\n\t\r\n\t// traverse the object list\r\n\tdo\r\n\t{\r\n\t\t// clear the appropriate list changed bit\r\n\t\tm_list_changed &= ~stamp_mask;\r\n\t\t\r\n        CObject* pNextObject = sh.FirstItem(m_object_list);\r\n\t\t\r\n\t\twhile (pNextObject)\r\n\t\t{\r\n\t\t\tCObject* pObject = pNextObject;\r\n\t\t\tpNextObject = sh.NextItem();\r\n\t\t\t\r\n\t\t\tif (!pObject->CheckStampBit(stamp_mask))\r\n\t\t\t{\r\n\t\t\t\tpObject->SetStampBit(stamp_mask);\r\n\t\t\t\t\r\n\t\t\t\tstatic_cast< CCompositeObject* >(pObject)->Pause(paused);\r\n\t\t\t\t\r\n\t\t\t\tif (m_list_changed & stamp_mask) break;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\twhile (m_list_changed & stamp_mask);\r\n\t\r\n\tm_stamp_bit_manager.ReturnBit(stamp_mask);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompositeObjectManager::s_logic_code ( const Tsk::Task< CCompositeObjectManager >& task )\r\n{\r\n    Dbg_AssertType ( &task, Tsk::Task< CCompositeObjectManager > );\r\n\r\n\tCCompositeObjectManager& obj_man = task.GetData();\r\n\r\n\tobj_man.Update();    \r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCBaseComponent* CCompositeObjectManager::GetFirstComponentByType( uint32 id )\r\n{\r\n\tfor( uint32 i = 0; i < m_num_components; ++i )\r\n\t{\r\n\t\tif( m_registered_components[i].mComponentID == id )\r\n\t\t{\r\n\t\t\treturn mp_components_by_type[i];\r\n\t\t}\r\n\t}\r\n\tDbg_MsgAssert( 0, ( \"Component %s not registered\", Script::FindChecksumName( id )));\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CCompositeObjectManager::AddComponentByType( CBaseComponent *p_component )\r\n{\r\n\tuint32 id = p_component->GetType();\r\n\r\n\tfor( uint32 i = 0; i < m_num_components; ++i )\r\n\t{\r\n\t\tif( m_registered_components[i].mComponentID == id )\r\n\t\t{\r\n\t\t\tp_component->SetNextSameType( mp_components_by_type[i] );\r\n\t\t\tmp_components_by_type[i] = p_component;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tDbg_MsgAssert( 0, ( \"Component %s not registered\", Script::FindChecksumName( id )));\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CCompositeObjectManager::RemoveComponentByType( CBaseComponent *p_component )\r\n{\r\n\tuint32 id = p_component->GetType();\r\n\r\n\tfor( uint32 i = 0; i < m_num_components; ++i )\r\n\t{\r\n\t\tif( m_registered_components[i].mComponentID == id )\r\n\t\t{\r\n\t\t\tif( mp_components_by_type[i] == p_component )\r\n\t\t\t{\r\n\t\t\t\tmp_components_by_type[i] = p_component->GetNextSameType();\r\n\t\t\t\tp_component->SetNextSameType( NULL );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tCBaseComponent *p_loop = mp_components_by_type[i];\r\n\t\t\t\twhile( p_loop )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( p_loop->GetNextSameType() == p_component )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_loop->SetNextSameType( p_component->GetNextSameType());\r\n\t\t\t\t\t\tp_component->SetNextSameType( NULL );\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tp_loop = p_loop->GetNextSameType();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tDbg_MsgAssert( 0, ( \"Component %s not registered\", Script::FindChecksumName( id )));\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Object/compositeobjectmanager.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Object\r\n//* FILENAME:       compositeobjectmanager.h\r\n//* OWNER:          Mick West\r\n//* CREATION DATE:  10/17/2002\r\n//****************************************************************************\r\n\r\n#ifndef __OBJECT_COMPOSITEMANAGER_H__\r\n#define __OBJECT_COMPOSITEMANAGER_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support/support.h>\r\n#include <core/task/task.h>\r\n#include <gel/object.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/objman.h>\r\n                          \r\nnamespace Obj\r\n{\r\n\r\n// Pointer to member.  See Bjarne, Page 418\r\n// not sure if we can use these instead of function pointers to static functions\r\n// (for now, use the old fasioned way)\r\n//typedef\tCBaseComponent * (Obj::CBaseComponent *PComponent)();\t// Pointer to member of CBaseComponent\r\n\r\nstruct\tSRegisteredComponent\r\n{\r\n\tuint32\t\t\t\tmComponentID;\t\t   \t\t\r\n\tCBaseComponent*\t\t(*mpCreateFunction)();\r\n};\r\n\r\n\r\nclass CCompositeObjectManager : public Obj::CGeneralManager\r\n{\r\n\r\n\tenum \r\n\t{\r\n\t\t\t\tvMAX_COMPONENTS=128\t\t\t\t\t\t\r\n\t};\r\n\r\npublic:\r\n\t\t\t\t\t\tCCompositeObjectManager();\r\n    virtual \t\t\t~CCompositeObjectManager();\r\n\r\n\tvoid \t\t\t\tUpdate();\r\n\tvoid \t\t\t\tPause( bool paused );\r\n\t\r\n\tCCompositeObject*\tCreateCompositeObject();\r\n\tCCompositeObject* \tCreateCompositeObjectFromNode(Script::CArray *pArray, Script::CStruct *pNodeData, bool finalize=true);\r\n\r\n\tvoid\t\t\t\tRegisterComponent(uint32 id, CBaseComponent *(p_create_function)(), void(p_register_function)() = NULL); \r\n\tCBaseComponent*\t\tCreateComponent(uint32 id);\r\n    \r\n\tCBaseComponent*\t\tGetFirstComponentByType( uint32 id );\r\n\tvoid\t\t\t\tAddComponentByType( CBaseComponent *p_component );\r\n\tvoid\t\t\t\tRemoveComponentByType( CBaseComponent *p_component );\r\n\r\nprotected:\r\n\tstatic Tsk::Task< CCompositeObjectManager >::Code   \ts_logic_code; \r\n\tTsk::Task< CCompositeObjectManager >*\t\t\t\t    mp_logic_task;\t\r\n\r\n\tuint32\t\t\t\t\t\t\t\t\t\t\t\t\tm_num_components;\r\n\tSRegisteredComponent\t\t\t\t\t\t\t\t\tm_registered_components[vMAX_COMPONENTS];\r\n\r\n\tstatic CBaseComponent\t\t\t\t\t\t\t\t\t*mp_components_by_type[vMAX_COMPONENTS];\r\n\t\r\n\tDeclareSingletonClass( CCompositeObjectManager );\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Object/object.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObjects (OBJ) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobject.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGame object code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// start autoduck documentation\r\n// @DOC object.cpp\r\n// @module object | None\r\n// @subindex Scripting Database\r\n// @index script | object\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/object.h>\r\n#include <gel/ObjPtr.h>\r\n#include <gel/objman.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/objsearch.h>\r\n#include <gel/Event.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Script\r\n{\r\n\textern void PrintContents(CStruct *p_structure, int indent);\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// temp\r\n// temp\t  REMOVE THIS WHEN script.h is implemented\r\n// temp\r\n//class\tCScript\r\n//{\r\n//};\r\n// temp\r\n// temp\r\n// temp\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*\r\n\tCreates CObject, does not give it an ID or register it.\r\n*/\r\nCObject::CObject() :\r\n\tm_node(this)\r\n{\r\n\tm_id = CBaseManager::vNO_OBJECT_ID;\t\r\n\tm_type = CBaseManager::vNO_OBJECT_TYPE;\t\r\n#ifndef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tmp_event_handler_table = NULL;\r\n#endif\t\r\n\tmp_tags = NULL;\r\n\tmp_script = NULL;\r\n\tmp_manager = NULL;\r\n\tm_object_flags = 0;\r\n\t\r\n\tm_ref_count = 0;\r\n\t\r\n\tm_stamp = 0;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCreates CObject, registers it with manager, giving it automatic ID.\r\n*/\r\nCObject::CObject( CBaseManager* p_obj_manager )\r\n\t: m_node(this)\r\n//: manager( obj_manager )\r\n\r\n{\r\n\tDbg_Assert(p_obj_manager);\t\r\n\r\n\tm_id = CBaseManager::vNO_OBJECT_ID;\t\r\n\tm_type = CBaseManager::vNO_OBJECT_TYPE;\t\r\n\tp_obj_manager->RegisterObject( *this );\t// add to manager's object list\r\n#ifndef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tmp_event_handler_table = NULL;\r\n#endif\t\r\n\tmp_tags = NULL;\r\n\tmp_script = NULL;\r\n\tmp_manager = NULL;\r\n\tm_object_flags = 0;\r\n\t\r\n\tm_ref_count = 0;\r\n\r\n\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tDestroying CObject disconnects it from manager, stops all scripts running on it.\r\n*/\r\nCObject::~CObject()\r\n{\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\t\r\n\tif (GetLockAssert())\r\n\t{\r\n\t\tif (mp_script)\r\n\t\t{\t\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\n Object %s at %p has been deleted while updating a script running on it, maybe goal manager callback? See Mick.\",mp_script->GetScriptInfo(),Script::FindChecksumName(GetID()),this));\r\n\t\t}\r\n\t\tDbg_MsgAssert(0,(\"Object %s at %p has been deleted while updating a script running on it, maybe goal manager callback? See Mick.\",Script::FindChecksumName(GetID()),this));\r\n\t}\r\n\t#endif\r\n\t\r\n\tDbg_MsgAssert(!IsLocked(), (\"can't destroy CObject, is locked\"));\r\n\t\r\n\tif (mp_tags)\r\n\t\tdelete mp_tags;\r\n\r\n#ifndef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tif (mp_event_handler_table)\r\n\t{\r\n\t\t// Remove the references to the event handler from the tracker\r\n\t\tmp_event_handler_table->unregister_all(this);\r\n\t\t\r\n\t\tif (mp_event_handler_table->m_in_immediate_use_counter)\r\n\t\t{\r\n\t\t\t// table still in use by its pass_event() function,\r\n\t\t\t// so leave it up to that function to destroy the table\r\n\t\t\tmp_event_handler_table->m_valid = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tdelete mp_event_handler_table;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tif (mp_manager)\r\n\t{\r\n\t\tmp_manager->UnregisterObject( *this );\r\n\t}\r\n\r\n\tif (mp_script)\r\n\t{\r\n\t\tdelete mp_script;\r\n\t\tmp_script = NULL;\r\n\t}\r\n\t\r\n\t// Stop any scripts that have this object as their parent.\r\n\t// Note: This won't actually delete the scripts, to prevent dangling pointers.\r\n\tScript::StopAllScriptsUsingThisObject(this);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tUsed by object managers when they delete all but a few objects (which have been locked).\r\n*/\r\nvoid CObject::DestroyIfUnlocked()\r\n{\t   \r\n\tif ( !IsLocked() )\r\n\t{\r\n\t\tdelete this;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tSets the global ID of this CObject. A CObject needs an ID in order to function\r\n\tin the system. If no ID is assigned, it will automatically be assigned one \r\n\twhen registered with a manager.\r\n\t\r\n\tCalling this function on a CObject that already has an ID will attempt to change\r\n\tits ID globally (whereever that ID is used).\r\n*/\r\nvoid CObject::SetID(uint32 id) \r\n{\t\r\n\tif (m_id != CBaseManager::vNO_OBJECT_ID && mp_manager)\r\n\t{\r\n\t\tmp_manager->ReregisterObject(*this, id);\r\n\t}\r\n\tm_id = id;\r\n\tSetChecksumTag(CRCD(0x40c698af, \"id\"), m_id);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tType is pretty much just the checksum of the class, minus the \"C\"\r\n*/\r\nvoid CObject::SetType(sint type) \r\n{\r\n\tDbg_MsgAssert(m_type == CBaseManager::vNO_OBJECT_TYPE, (\"CObject already assigned a type\"));\r\n\tm_type = type;\r\n\tSetChecksumTag(CRCD(0x7321a8d6, \"type\"), m_type);\r\n}\r\n\r\n\r\n#ifndef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\r\n/*\r\n\tSets up the table that specifies which scripts to run in response to which events.\r\n\t\r\n\tSee object scripting document.\r\n*/\r\nvoid CObject::SetEventHandlers(Script::CArray *pArray, EReplaceEventHandlers replace)\r\n{\r\n\t\r\n\tif (!mp_event_handler_table)\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\tmp_event_handler_table = new CEventHandlerTable();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_event_handler_table->unregister_all(this);\t\r\n\t}\r\n\tmp_event_handler_table->add_from_script(pArray, replace);\r\n//\tmp_event_handler_table->compress_table();\r\n\t\r\n\tmp_event_handler_table->register_all(this);\r\n\r\n}\r\n\r\n\r\n\r\n/*\r\n\tRemoves an entry in the event table with the given type id\r\n*/\r\nvoid CObject::RemoveEventHandler(uint32 type)\r\n{\r\n\tif (!mp_event_handler_table) return;\r\n\tmp_event_handler_table->remove_entry(type);\r\n\r\n// Mick:  by not compressing the event handler table after removing entries\r\n// we should minimize the amount of allocs needed\r\n// new event handlers can just re-use these \"removed\" sloes\r\n//\tmp_event_handler_table->compress_table();\r\n\r\n// Refresh the Obj::Tracker\r\n\r\n\tObj::CTracker::Instance()->UnregisterEventReceiver(type, this); \r\n\t\t\r\n}\r\n\r\n\r\n\r\n/*\r\n\tRemoves all entries in the event table with the given group id\r\n*/\r\nvoid CObject::RemoveEventHandlerGroup(uint32 group)\r\n{\r\n\tif (!mp_event_handler_table) return;\r\n\t\r\n\tmp_event_handler_table->unregister_all(this);\t\r\n\t\r\n\tmp_event_handler_table->remove_group(group);\r\n\r\n// Mick:  by not compressing the event handler table after removing entries\r\n// we should minimize the amount of allocs needed\r\n// new event handlers can just re-use these \"removed\" sloes\r\n//\tmp_event_handler_table->compress_table();\r\n\t\r\n\tmp_event_handler_table->register_all(this);\t\r\n\r\n}\r\n\r\n#else\r\n\r\n\r\n/*\r\n\tSets up the table that specifies which scripts to run in response to which events.\r\n\t\r\n\tSee object scripting document.\r\n*/\r\nvoid CObject::SetEventHandlers(Script::CArray *pArray, EReplaceEventHandlers replace)\r\n{\r\n\t// TEMP - Pass into script object.  Eventually handled soley by script with no need for object\r\n\tAllocateScriptIfNeeded();\r\n\tmp_script->SetEventHandlers(pArray, replace);\r\n}\r\n\r\n/*\r\n\tRemoves an entry in the event table with the given type id\r\n*/\r\nvoid CObject::RemoveEventHandler(uint32 type)\r\n{\r\n\tif (!mp_script)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tmp_script->RemoveEventHandler(type );\r\n}\r\n\r\n/*\r\n\tRemoves all entries in the event table with the given group id\r\n*/\r\nvoid CObject::RemoveEventHandlerGroup(uint32 group)\r\n{\r\n\tif (!mp_script)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tmp_script->RemoveEventHandlerGroup(group);\r\n}\r\n\r\n\r\n\r\n#endif\r\n\r\n\r\nvoid CObject::SetIntegerTag(uint32 name, int value)\r\n{\r\n\tallocate_tags_if_needed();\r\n\r\n\tmp_tags->AddInteger(name, value);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CObject::SetChecksumTag(uint32 name, uint32 value)\r\n{\r\n\tallocate_tags_if_needed();\r\n\r\n\tmp_tags->AddChecksum(name, value);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CObject::RemoveFlagTag(uint32 name)\r\n{\r\n\tif (mp_tags)\r\n\t\tmp_tags->RemoveFlag(name);\r\n}\r\n\r\n\r\n\r\n\r\nbool CObject::GetIntegerTag(uint32 name, int *pResult) const\r\n{\r\n\tif (mp_tags)\r\n\t\treturn mp_tags->GetInteger(name, pResult);\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\nbool CObject::GetChecksumTag(uint32 name, uint32 *pResult) const \r\n{\r\n\tif (mp_tags)\r\n\t\treturn mp_tags->GetChecksum(name, pResult);\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\nbool CObject::ContainsFlagTag(uint32 name) const\r\n{\r\n\tif (mp_tags)\r\n\t\treturn mp_tags->ContainsFlag(name);\r\n\treturn false;\r\n}\r\n\r\n\r\n// Add a vector to the tag structure with name \"name\", and copy in the vector \"v\"\r\nvoid CObject::SetVectorTag(uint32 name, Mth::Vector\tv)\r\n{\r\n\tallocate_tags_if_needed();\r\n\r\n\tmp_tags->AddVector(name, v[X], v[Y], v[Z]);\r\n}\r\n\r\n\r\n// get the value a vector tag.\r\n// returning false if not found\r\nbool CObject::GetVectorTag(uint32 name, Mth::Vector *pResult) const\r\n{\r\n\tif (mp_tags)\r\n\t\treturn mp_tags->GetVector(name, pResult);\r\n\treturn false;\r\n}\r\n\r\n#ifndef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\r\nvoid \tCObject::SetOnExceptionScriptChecksum(uint32 OnExceptionScriptChecksum) \r\n{\r\n\tmOnExceptionScriptChecksum = OnExceptionScriptChecksum;\r\n}\r\n\r\nuint32 \tCObject::GetOnExceptionScriptChecksum() const \r\n{\r\n\treturn mOnExceptionScriptChecksum;\r\n}\r\n#else\r\n// Todo - Pass these to the script\r\n\r\n#endif\r\n\r\n\r\nvoid CObject::SetTagsFromScript(Script::CStruct *pStruct)\r\n{\r\n\tallocate_tags_if_needed();\r\n\r\n\tmp_tags->AppendStructure(pStruct);\r\n\t//printf(\"Set tags of object %s to:\\n\", Script::FindChecksumName(m_id));\r\n\t//Script::PrintContents(mp_tags, 4);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CObject::RemoveTagsFromScript(Script::CArray *pNameArray)\r\n{\r\n\tif (!mp_tags) return;\r\n\r\n\tfor (uint i = 0; i < pNameArray->GetSize(); i++)\r\n\t{\r\n\t\tuint32 name_crc = pNameArray->GetChecksum(i);\r\n\t\tmp_tags->RemoveComponent(name_crc);\r\n\t\tmp_tags->RemoveFlag(name_crc);\r\n\t}\r\n\t\r\n\tif (mp_tags->IsEmpty())\r\n\t{\r\n\t\tdelete mp_tags;\r\n\t\tmp_tags = NULL;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CObject::CopyTagsToScriptStruct(Script::CStruct *pStruct)\r\n{\r\n\tDbg_Assert(pStruct);\r\n\t\r\n\tif (mp_tags)\t\r\n\t{\r\n\t\tpStruct->AppendStructure(mp_tags);\r\n\t\t//printf(\"Fetching tags of object %s:\\n\", Script::FindChecksumName(m_id));\r\n\t\t//Script::PrintContents(pStruct, 4);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tProperty setting script commands enter through this function.\r\n*/\r\nvoid CObject::SetProperties(Script::CStruct *pProps)\r\n{\r\n\tbool replace_handlers = pProps->ContainsFlag(\"replace_handlers\");\r\n\r\n\tScript::CArray *p_event_handler_table;\r\n\tif (pProps->GetArray(\"event_handlers\", &p_event_handler_table))\r\n\t{\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\t\tCObject::SetEventHandlers(p_event_handler_table, EReplaceEventHandlers(replace_handlers));\r\n#else\t\r\n\t\tCObject::SetEventHandlers(p_event_handler_table, EReplaceEventHandlers(replace_handlers));\r\n#endif\t\r\n\t}\r\n\t/*\r\n\telse if (pProps->GetArray(\"event_handler\", &p_event_handler_table))\r\n\t{\r\n\t\t// just a single entry (makes for easier-to-read script)\r\n\t\tCObject::SetEventHandlers(p_event_handler_table, replace_handlers, true);\r\n\t}\r\n\t*/\r\n\r\n\tScript::CStruct *p_tags;\r\n\tif (pProps->GetStructure(\"tags\", &p_tags)) \r\n\t\tSetTagsFromScript(p_tags);\r\n\r\n\tScript::CArray *p_remove_tags;\r\n\tif (pProps->GetArray(\"remove_tags\", &p_remove_tags))\r\n\t\tRemoveTagsFromScript(p_remove_tags);\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*   CObject::CallMemberFunction                                  */\r\n/*   Call a member function, based on a checksum                  */\r\n/*   This is usually the checksum of the name of the function     */\r\n/*   but can actually be any number, as it just uses a switch     */\r\n/*   note this is a virtual function, so the same checksum        */\r\n/*   can do differnet things for different objects                */\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CObject::CallMemberFunction( uint32 Checksum, Script::CScriptStructure *pParams, Script::CScript *pScript )\r\n{\r\n    \r\n\tDbg_MsgAssert(pScript,(\"NULL pScript\"));\r\n\r\n\tswitch(Checksum)\r\n\t{\r\n\t\tcase CRCC(0x3611c136, \"GetTags\"):\r\n\t\t\tCopyTagsToScriptStruct(pScript->GetParams());\r\n\t\t\tbreak;\r\n\r\n\t\tcase CRCC( 0xa58079eb, \"SetTags\" ):\r\n\t\t\tSetTagsFromScript( pParams );\r\n\t\t\tbreak;\r\n\t\t\t \r\n\t\tcase 0xc6870028:// \"Die\"\r\n\t\t\tMarkAsDead( );\r\n\t\t\tbreak;\t\r\n\t\t        \r\n\t\tcase 0xb3c262ec:// \"DisassociateFromObject\"\r\n\t\t\tpScript->DisassociateWithObject(this);\r\n\t\t\tbreak;\t\r\n\t\t        \r\n\t\t// @script | Obj_GetId | \r\n\t\tcase 0x500eb224: // Obj_GetId\r\n\t\t\tDbg_Assert( pScript && pScript->GetParams() );\r\n\t\t\tpScript->GetParams()->AddChecksum( \"objId\", m_id ); \r\n\t\tbreak;\r\n\t\t\r\n\t\t// @script | Obj_FlagSet | Check to see if a flag has been set.  Flags can \r\n\t\t// be defined anywhere, but you should keep them in your personal scripts file.  \r\n\t\t// It is important that you prefix all flags with your initials to ensure that \r\n\t\t// there are no conflicts with the other designers.\r\n\t\t// <nl>Example 1:\r\n\t\t// <nl>MJD_LAMP_GOT_BROKEN = 14\r\n\t\t// <nl>MJD_LAMP_GOT_HIT = 15\r\n\t\t// <nl>MJD_LAMP_GOT_DISABLED = 16\r\n\t\t// <nl>if Obj_FlagSet 15\r\n\t\t// <nl>    Obj_ClearFlag MJD_LAMP_GOT_HIT\r\n\t\t// <nl>    WiggleProfusely\r\n\t\t// <nl>endif\r\n\t\t// <nl>Example 2:\r\n\t\t// <nl>if Obj_FlagSet MJD_LAMP_GOT_HIT clear\r\n\t\t// <nl>    WiggleProfusely\r\n\t\t// <nl>endif\r\n\t\t// <nl>Example 3:\r\n\t\t// <nl>If Obj_FlagSet JKU_FLAG_PED_START  // JKU_FLAG_PED_START would be defined in JKU_Scripts.q\r\n\t\t// <nl>     Printf Yes\r\n\t\t// <nl>endif\r\n\t\t// @flag all | Clear all flags\r\n\t\t// @flag clear | Clear the flag\r\n\t\t// @flag reset | I just added a 'reset' flag you can send in to clear \r\n\t\t// the flag after checking it, if it's set\r\n\t\tcase 0x4babc987: // Obj_FlagSet\r\n\t\t{\r\n\t\t\tuint32 scriptFlags = mScriptFlags;\r\n\t\t\tuint32 Flags = 0;\r\n\t\t\tFlags = GetFlags( pParams, pScript );\r\n\t\t\tif ( !Flags )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0,( \"\\n%s\\nObj_FlagSet command requires a flag to be specified.\\n(Either an integer or a name defined to be an integer)\",pScript->GetScriptInfo()));\r\n\t\t\t\treturn ( false );\r\n\t\t\t}\r\n\t\t\tif ( pParams->ContainsFlag( 0x1a4e0ef9 ) ) // clear\r\n\t\t\t{\r\n\t\t\t\tmScriptFlags &= ~( Flags );\r\n\t\t\t}\r\n\t\t\tif ( scriptFlags & Flags )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t\t\r\n\t\t// @script | Obj_FlagNotSet | Check to see if a flag has not been set.\r\n\t\tcase 0x53ebee03: // Obj_FlagNotSet\r\n\t\t{\r\n\t\t\tuint32 Flags = 0;\r\n\t\t\tFlags = GetFlags( pParams, pScript );\r\n\t\t\tif ( !Flags )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0,( \"\\n%s\\nObj_FlagNotSet command requires a flag to be specified.\\n(Either an integer or a name defined to be an integer)\",pScript->GetScriptInfo()));\r\n\t\t\t\treturn ( false );\r\n\t\t\t}\r\n\t\t\tif ( mScriptFlags & ( Flags ) )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t\t\r\n\t\t// @script | Obj_ClearFlag | Object member function which clears the specified flag or flags.\r\n\t\t// <nl>There are 3 ways of using it, it can clear just one flag, or an array of flags, \r\n\t\t// or all the flags.\r\n\t\t// <nl>Example 1:\r\n\t\t// <nl>Obj_ClearFlag JKU_FLAG_PED_START  // Set the flag to 0\r\n\t\t// <nl>Example 2:\r\n\t\t// <nl>Obj_ClearFlag [ JKU_FLAG_PED_START JKU_FLAG_PED_STOP ]  // Clears an array of flags\r\n\t\t// <nl>Example 3:\r\n\t\t// <nl>Obj_ClearFlag All  // Clears all the flags.\r\n\t\t// @flag all | Clear all the flags\r\n\t\tcase 0x6c2b67f9: // Obj_ClearFlag\r\n\t\t{\r\n\t\t\tif (pParams->ContainsFlag(0xc4e78e22/*All*/))\r\n\t\t\t{\r\n\t\t\t\tmScriptFlags=0;\r\n\t\t\t\treturn true;\r\n\t\t\t}\t\r\n\t\t\tuint32 Flags = 0;\r\n\t\r\n\t\t\tFlags = GetFlags( pParams, pScript );\r\n\t\t\tif ( !Flags )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0,( \"\\n%s\\nObj_ClearFlag command requires a flag to be specified.\\n(Either an integer or a name defined to be an integer)\",pScript->GetScriptInfo()));\r\n\t\t\t\treturn ( false );\r\n\t\t\t}\r\n\t\t\tmScriptFlags &= ~Flags;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\r\n\t\t// @script | Obj_SetFlag | Sets the flag (or an array of flags) on an object.\r\n\t\t// <nl>Same parameters as Obj_ClearFlag (except doesn't recognize the \r\n\t\t// 'all' parameter).\r\n\t\tcase 0xbe563426: // Obj_SetFlag\r\n\t\t{\r\n\t\t\tuint32 Flags = 0;\r\n\t\t\tFlags = GetFlags( pParams, pScript );\r\n\t\t\tif ( !Flags )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0,( \"\\n%s\\nObj_SetFlag command requires a flag to be specified.\\n(Either an integer or a name defined to be an integer)\",pScript->GetScriptInfo()));\r\n\t\t\t\treturn ( false );\r\n\t\t\t}\r\n\t\t\tmScriptFlags |= Flags;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | Obj_KillSpawnedScript | Kills a spawned script.  Can be passeed a name or id.\r\n\t\t// @parm name | name | Name of the script you want to spawn (no quotes)\r\n\t\t// @parm name | id | id of the script you want to spawn (no quotes)\r\n\t\tcase 0xfbd89cd5: // Obj_KillSpawnedScript\r\n\t\t{\r\n\t\t\tuint32 ScriptChecksum=0;\r\n\t\t\tif (pParams->GetChecksum(CRCD(0xa1dc81f9,\"Name\"),&ScriptChecksum))\r\n\t\t\t{\r\n\t\t\t\t// Got a script name, so kill all spawned scripts that ran that script.\r\n\t\t\t\t// BUT NOT THE SCRIPT CALLING THIS!\r\n\t\t\t\tScript::KillSpawnedScriptsWithObjectAndName( this, ScriptChecksum, pScript );\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\r\n\t\t\tuint32 Id=0;\t\t\t\t\t\t\t\t\t\t   \r\n\t\t\tif (pParams->GetChecksum(CRCD(0x40c698af,\"Id\"),&Id))\r\n\t\t\t{\r\n\t\t\t\t// They specified an Id, so kill all spawned scripts with this Id,\r\n\t\t\t\t// BUT NOT THE SCRIPT CALLING THIS!\r\n\t\t\t\tScript::KillSpawnedScriptsWithObjectAndId( this, Id, pScript );\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tDbg_MsgAssert( 0,( \"\\n%s\\nMust specify Name or ID on Obj_KillSpawnedScript\", pScript->GetScriptInfo() ));\r\n\t\t\treturn true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\r\n\t\t// @script | Obj_SpawnScript | Causes the object to run a script, in parallel\r\n\t\t// to whatever script is running on the object.\r\n\t\t// @flag ScriptName | Name of the script you want to spawn (no quotes)\r\n\t\t// @parmopt name | Params | {} | Any parameters you want to pass to the script being\r\n\t\t// spawned.  Must surround params in { }\r\n\t\tcase 0x23a4e5c2: // Obj_SpawnScript\r\n\t\t{\r\n\t\t\tScript::CComponent* p_component = pParams->GetNextComponent();\r\n\t\t\tif ( p_component && p_component->mType == ESYMBOLTYPE_NAME )\r\n\t\t\t{\r\n\t\t\t\tuint32 scriptChecksum = p_component->mChecksum;\r\n\t\t\t\t\r\n\t\t\t\t// The spawned script can optionally be given an Id, so that it can be deleted\r\n\t\t\t\t// by KillSpawnedScript.\r\n\t\t\t\tuint32 Id=0;\r\n\t\t\t\t// keep the same ID as the parent if not specified...\r\n\t\t\t\tId = Script::FindSpawnedScriptID(pScript);\r\n\t\t\t\tpParams->GetChecksum(\"Id\",&Id);\r\n\t\t\t\tScript::CScriptStructure *pScriptParams = NULL;\r\n\t\t\t\tpParams->GetStructure( \"Params\", &pScriptParams );\r\n\t\t\t\t#ifdef __NOPT_ASSERT__\t\r\n\t\t\t\tScript::CScript *p_script=SpawnScriptPlease( scriptChecksum, pScriptParams, Id, pParams->ContainsFlag(CRCD(0x8757d0bb, \"PauseWithObject\")) );\r\n\t\t\t\tp_script->SetCommentString(\"Created by Obj_SpawnScript\");\r\n\t\t\t\tp_script->SetOriginatingScriptInfo(pScript->GetCurrentLineNumber(),pScript->mScriptChecksum);\r\n\t\t\t\t#else\r\n\t\t\t\tSpawnScriptPlease( scriptChecksum, pScriptParams, Id );\r\n\t\t\t\t#endif\r\n\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\r\n\t\t// @script | Obj_SwitchScript | Causes the object to replace the current script \r\n\t\t// attached to it with the script specified by ScriptName. <nl>\r\n\t\t// Can use the pass params just like Obj_SpawnScript.\r\n\t\t// @flag ScriptName | Name of the script you want to spawn (no quotes)\r\n\t\tcase 0x714937c7: // Obj_SwitchScript\r\n\t\t{\r\n\t\t\tuint32 scriptChecksum;\r\n\t\t\tif ( pParams->GetChecksum( NONAME, &scriptChecksum ) )\r\n\t\t\t{\r\n\t\t\t\tScript::CScriptStructure *pScriptParams = NULL;\r\n\t\t\t\tpParams->GetStructure( \"Params\", &pScriptParams );\r\n\t\t\t\tSwitchScript( scriptChecksum, pScriptParams );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t\r\n\t\t// case\tCRCC(0x6df6caef,\"SetProperties\"):\r\n\t\tcase\tCRCC(0x6c63c7c5,\"SetProps\"):\r\n\t\t{\r\n\t\t\t// Lowest level SetProperties, allowing ANY object to set event handlers\r\n\t\t\tSetProperties(pParams);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n/*\t\t\r\n\t\tcase\tCRCC(0x1127430c, \"ClearEventHandler\"):\r\n\t\t{\r\n\t\t\tuint32 type;\r\n\t\t\tpParams->GetChecksum(NO_NAME, &type, Script::ASSERT);\r\n\t\t\tRemoveEventHandler(type);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t\t\r\n\t\tcase\tCRCC(0x8968da7f, \"ClearEventHandlerGroup\"):\r\n\t\t{\r\n\t\t\tuint32 group = CEventHandlerTable::vDEFAULT_GROUP;\r\n\t\t\tpParams->GetChecksum(NO_NAME, &group);\r\n\t\t\tRemoveEventHandlerGroup(group);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n// @script | OnExceptionRun | run the specified script on exception\r\n// @uparm name | script name to run\r\n// can be called without a parameter to clear it\r\n//\t\tcase 0x2c0c9e7b: // OnExceptionRun\t\r\n\t\tcase CRCC(0x2c0c9e7b,\"OnExceptionRun\"):\r\n\t\t{\r\n\t\t\tuint32 OnExceptionScriptChecksum = 0;\r\n\t\t\tpParams->GetChecksum( NONAME, &OnExceptionScriptChecksum);\r\n\t\t\t#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\t\t\tif (mp_script)\r\n\t\t\t{\r\n\t\t\t\tmp_script->SetOnExceptionScriptChecksum(OnExceptionScriptChecksum);\r\n\t\t\t}\r\n\t\t\t#else\r\n\t\t\tSetOnExceptionScriptChecksum(OnExceptionScriptChecksum);\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase CRCC(0xbefaa466,\"OnExitRun\"):\r\n\t\t{\r\n\t\t\tuint32 OnExitScriptChecksum = 0;\r\n\t\t\tpParams->GetChecksum( NONAME, &OnExitScriptChecksum);\r\n\t\t\t#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\t\t\tif (mp_script)\r\n\t\t\t{\r\n\t\t\t\tmp_script->SetOnExitScriptChecksum(OnExitScriptChecksum);\r\n\t\t\t}\r\n\t\t\t#else\r\n\t\t\tSetOnExitScriptChecksum(OnExitScriptChecksum);\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n*/\r\n\r\n\t\tcase 0x20d125d7: // Obj_Visible\r\n\t\t\tm_object_flags &= ~vINVISIBLE;\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0x3578e5a9: // Obj_Invisible\r\n\t\t\tm_object_flags |= vINVISIBLE;\r\n\t\t\tbreak;\r\n\r\n\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nNo CObject member function found for '%s'\",pScript->GetScriptInfo(),Script::FindChecksumName(Checksum)));\r\n\r\n\t\t\t\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\nuint32 CObject::GetFlags( Script::CScriptStructure *pParams, Script::CScript *pScript ) const\r\n{\r\n\t\r\n\tuint32 Flags = 0;\r\n\tint Flag = 0;\r\n\r\n\t// Scan through any array of flags specified.\r\n\tScript::CArray *pArray=NULL;\r\n\tpParams->GetArray(NONAME,&pArray);\r\n\tif (pArray)\r\n\t{\r\n\t\tfor (uint32 i=0; i<pArray->GetSize(); ++i)\r\n\t\t{\r\n\t\t\tuint32 Checksum=pArray->GetNameChecksum(i);\r\n\t\t\tint Flag=Script::GetInteger(Checksum);\r\n\t\t\tDbg_MsgAssert(Flag>=0 && Flag<32,(\"\\n%s\\nBad flag value %s=%d, value must be between 0 and 31\",pScript->GetScriptInfo(),Script::FindChecksumName(Checksum),Flag));\r\n\t\t\tFlags |= ( 1 << Flag );\r\n\t\t}\t\r\n\t}\r\n\telse if ( pParams->GetInteger( NONAME, &Flag ) )\r\n\t{\r\n\t\tDbg_MsgAssert(Flag>=0 && Flag<32,(\"\\n%s\\nBad flag value of %d, value must be between 0 and 31\",pScript->GetScriptInfo(),Flag));\r\n\t\tFlags = ( 1 << Flag );\r\n\t}\r\n\treturn Flags;\r\n}\r\n\r\n/*\r\n\tIf an event is targeted specifically to this CObject (using the same ID), it will be\r\n\tpassed through this function.\r\n*/\r\nbool CObject::PassTargetedEvent(CEvent *pEvent, bool broadcast)\r\n{\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tif (!mp_script)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n#endif\r\n\t\r\n\tObj::CSmtPtr<CObject> p = this;\r\n\t\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tmp_script->PassTargetedEvent(pEvent, broadcast);\r\n#else\t\r\n\tif (mp_event_handler_table)\r\n\t\tmp_event_handler_table->pass_event(pEvent, this, broadcast);\r\n#endif\r\n\r\n\treturn (p != NULL);\r\n}\r\n\r\n\r\n// Send myself an event.  Just a useful shortcut for a commonly done thing\r\nvoid CObject::SelfEvent(uint32 event, Script::CStruct* pParams)\r\n{\r\n\tObj::CTracker::Instance()->LaunchEvent(event,GetID(),GetID(),pParams); \r\n}\r\n\r\n\r\nvoid CObject::BroadcastEvent(uint32 event, Script::CStruct *pData, float radius)\r\n{\r\n\t// no target\r\n\t// radius not implemented yet\r\n\tObj::CTracker::Instance()->LaunchEvent( event, 0xffffffff, GetID(), pData, true /*, radius */  );\r\n}\r\n\r\n\r\n\r\n/*\r\n\tHas the same effect as deleting the CObject, except the actual deletion is deferred until next frame.\r\n\tSo that objects can be killed and not mess up list traversal\r\n*/\r\nvoid CObject::MarkAsDead( void )\r\n{\r\n\t\r\n\t// make sure we don't continue running anything on this script!\r\n\tif ( mp_script )\r\n\t{\r\n\t\tmp_script->Block( );\r\n\t}\r\n\r\n\t// The following line will set the mp_object of any referring scripts to NULL\r\n\tScript::StopAllScriptsUsingThisObject(this);  // Mick: we don't want any other scripts to continue running on a dead object \t\r\n\t\r\n\tDbg_MsgAssert( mp_manager,( \"No object manager associated with this object...\" ));\r\n\t// who locks an object?\r\n\tSetLockOff();\r\n\r\n\t\r\n\t// mp_manager will be cleared by UnregisterObject()\r\n\tCBaseManager *p_manager = mp_manager;\r\n\tp_manager->UnregisterObject( *this );\r\n\tp_manager->KillObject( *this );  // add object to kill list, to be purged next frame...\t\r\n\tm_object_flags |= ( vDEAD );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CObject::allocate_tags_if_needed()\r\n{\r\n\tif (!mp_tags) \r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\tmp_tags = new Script::CStruct();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CObject::AllocateScriptIfNeeded()\r\n{\r\n\tif (!mp_script) \r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\tmp_script = new Script::CScript();\r\n\t\tmp_script->SetScript(CRCD(0x3f5cdb8a,\"empty_script\"),NULL,this);\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CObject::SwitchScript( uint32 scriptChecksum, Script::CScriptStructure *pParams )\r\n{\r\n\t\r\n\tif ( mp_script )\r\n\t{\r\n\t\tmp_script->SetScript( scriptChecksum, pParams, this );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_script = new Script::CScript;\r\n\t\tmp_script->SetScript( scriptChecksum, pParams, this );\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tmp_script->SetCommentString(\"Created in CObject::SwitchScript(...)\");\r\n\t\t#endif\r\n\t}\r\n\tif ( !mp_script->GotScript( ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Couldn't find script specified: %s\", Script::FindChecksumName( scriptChecksum ) ));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CScript *CObject::SpawnScriptPlease( uint32 scriptChecksum, Script::CScriptStructure *pParams, int Id, bool pause_with_object )\r\n{\r\n\t\r\n\tScript::CScript *pScript;\r\n\tpScript = Script::SpawnScript( scriptChecksum, pParams, 0, NULL, -1, Id, false, false, false, pause_with_object ); // K: The 0,NULL means no callback specified.\r\n\tpScript->mpObject = this;\r\n\treturn pScript;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// spawn and immediatly run a script\r\n// script will be deleted after it terminates\r\nvoid CObject::SpawnAndRunScript ( uint32 ScriptChecksum, int node, bool net_script, bool permanent, Script::CStruct *p_params )\r\n{\r\n    // Send this event to other clients if applicable\r\n\tif( net_script )\r\n\t{\r\n\t\t// Ken: TODO: Currently p_params are not being passed on in net games, fix if necessary ...\r\n\t\t// Currently p_params is only used to store the contents of any ModelTriggerScriptParams\r\n\t\t// that may be specified in an object's node and which are required to be passed on to\r\n\t\t// any TriggerScript in it's local node array. (Used by a goal in London)\r\n\t\t// (Note: The NULL below means a NULL p_object)\r\n\t\tScript::SendSpawnScript( ScriptChecksum, NULL, node, permanent );\r\n\t}\r\n\r\n\tScript::CScript* pScript = Script::SpawnScript( ScriptChecksum, p_params, 0, NULL, node );\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tpScript->SetCommentString( \"Spawned by CObject::SpawnAndRun(...)\" );\r\n\t#endif\r\n\t\r\n\tpScript->mpObject = this; \r\n\t\r\n\tpScript->Update(); \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CObject::SpawnAndRunScript( const char *pScriptName, int node, bool net_script, bool permanent, Script::CStruct *p_params )\r\n{\r\n\tSpawnAndRunScript(Script::GenerateCRC(pScriptName),node, net_script, permanent, p_params );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CObject::CallScript( uint32 ScriptChecksum, Script::CStruct *pParams )\r\n{\r\n\tif ( !mp_script )\r\n\t{\r\n\t\tmp_script = new Script::CScript;\r\n\t\t\r\n\t\t// K: Added this in case the script being called contains member functions, which\r\n\t\t// it does when a two player trick-attack game is started.\r\n\t\tmp_script->mpObject=this;\r\n\t}\r\n\r\n\tmp_script->Interrupt(ScriptChecksum, pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tDestroyIfUnlocked( Obj::CObject* obj, void* data )\r\n{\r\n\tobj->DestroyIfUnlocked();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tSetLockOff( CObject* obj, void* data )\r\n{\r\n\tobj->SetLockOff();\r\n}\r\n\r\nvoid\t\t\tCObject::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\t\t// CObject stuff\r\n\tScript::CStruct *p_scripts=new Script::CStruct;\r\n\tScript::CScript *p_script=Script::GetNextScript(NULL);\r\n\twhile (p_script)\r\n\t{\r\n\t\tif (p_script->mpObject==this)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_script_info=new Script::CStruct;\r\n\t\t\t\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t// Convert to microseconds by dividing by 150\r\n\t\t\tp_script_info->AddInteger(\"CPUTime\",p_script->m_last_time/150);\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tp_script_info->AddChecksum(\"m_unique_id\",p_script->GetUniqueId());\r\n\t\t\tif (p_script->mIsSpawned)\r\n\t\t\t{\r\n\t\t\t\tp_script_info->AddChecksum(NONAME,CRCD(0xf697fda7,\"Spawned\"));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\t\t\t\tif (p_script->GetEventHandlerTable())\r\n\t\t\t\t{\r\n\t\t\t\t\tp_script->GetEventHandlerTable()->GetDebugInfo(p_script_info);\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\t\r\n\t\t\tp_scripts->AddStructurePointer(p_script->GetBaseScript(),p_script_info);\r\n\t\t}\r\n\t\t\t\r\n\t\tp_script=Script::GetNextScript(p_script);\r\n\t}\t\r\n\tp_info->AddStructurePointer(\"Scripts\",p_scripts);\r\n\t\r\n\tp_info->AddChecksum(\"m_id\",m_id);\r\n\tif (mp_tags)\r\n\t{\r\n\t\tp_info->AddStructure(\"mp_tags\",mp_tags);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_info->AddChecksum(\"mp_tags\",CRCD(0xda3403b0,\"NULL\"));\r\n\t}\r\n\t\r\n#ifndef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tif (mp_event_handler_table)\r\n\t{\r\n\t\tmp_event_handler_table->GetDebugInfo(p_info);\r\n\t}\r\n#endif\r\n#endif\t\t\t\t \r\n\r\n}\r\n\r\n// Leftover from when this function was more complex\r\n// just retained for convenience\r\nCObject *ResolveToObject(uint32 id)\r\n{\r\n\treturn Obj::CTracker::Instance()->GetObject(id); \t\r\n}\r\n\r\n\r\n} // namespace Obj\r\n\r\n"
  },
  {
    "path": "Code/Gel/Object/objman.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObjects (OBJ) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobjman.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tObject Manager\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n\r\n#include <core/list.h>\r\n#include <core/task.h>\r\n\r\n#include <gel/objman.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/mainloop.h>\r\n\r\n#include <gel/scripting/script.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#define __DEBUG_OBJ_MAN__\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nconst uint32 CBaseManager::vNO_GROUP = 0;\r\nconst uint32 CBaseManager::vNO_OBJECT_ID\t\t=\tvUINT32_MAX;\r\n\r\nconst sint CBaseManager::vNO_OBJECT_TYPE\t=\t0;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tCGeneralManager::flush_dead_objects( const Tsk::Task< CGeneralManager >& task )\r\n{\r\n\t \r\n\r\n\tCGeneralManager&\t\tobj_manager = task.GetData();\r\n\t\r\n\tobj_manager.FlushDeadObjects();\r\n\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseManager::CBaseManager( void )\r\n: m_list_changed( 0x00000000 )\r\n{\r\n\tm_momentary_removal = false;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tAdds the specified CObject to the manager, registers it with the CTracker singleton.\r\n\t\r\n\tIf the CObject has no ID, it is automatically assigned one at this point.\r\n*/\r\nvoid CBaseManager::RegisterObject ( CObject& obj )\r\n{\r\n\tCTracker* p_tracker = CTracker::Instance();\r\n\tDbg_MsgAssert(!obj.mp_manager, (\"object already registered with manager\"));\r\n\r\n   \tobj.mp_manager = this;\r\n\tm_object_list.AddNode ( &obj.m_node );\r\n\t\r\n\t// set all list changed bits\r\n\tm_list_changed = 0xFFFFFFFF;\r\n\t\r\n\tif (obj.GetID() == vNO_OBJECT_ID)\r\n\t\tobj.SetID(p_tracker->GetFreshId());\r\n\r\n\tp_tracker->addObject(&obj);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tRemoves the specified CObject to the manager, unregisters it from the CTracker singleton.\r\n\t\r\n\tAfter this, the CObject is no longer \"in the system\", and probably should be deleted. Its\r\n\tID will be available for usage by other CObjects again.\r\n*/\r\nvoid CBaseManager::UnregisterObject( CObject& obj )\r\n{\r\n\tCTracker* p_tracker = CTracker::Instance();\r\n\tDbg_MsgAssert(obj.mp_manager == this, (\"object not registered with this manager\"));\r\n\tDbg_AssertType( &obj, CObject );\r\n\r\n\tp_tracker->removeObject(&obj, m_new_id_of_object_being_momentarily_removed, m_momentary_removal);\r\n\t\r\n\tif ( obj.m_node.InList() )\r\n\t{\r\n\t\tobj.m_node.Remove();\r\n\t\tobj.mp_manager = NULL;\r\n\r\n\t\t// set all list changed bits\r\n\t\tm_list_changed = 0xFFFFFFFF;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCalled by CObject::SetID() when a CObject's ID is changed. Shouldn't be called\r\n\tfrom any other place.\r\n*/\r\nvoid CBaseManager::ReregisterObject(CObject& obj, uint32 newId)\r\n{\r\n\t/* \r\n\t\tIn the CTracker singleton, we are concerned with keeping:\r\n\t\t-Aliases. They don't use object ID, just pointers\r\n\t\t-Event listeners: don't use ID, so no worries\r\n\t\t-Waiting script entries: scan through and change stored ID\r\n\t*/\r\n\t\r\n\tm_new_id_of_object_being_momentarily_removed = newId;\r\n\tm_momentary_removal = true;\r\n\tUnregisterObject(obj);\r\n\tobj.m_id = newId;\r\n\tRegisterObject(obj);\r\n\tm_momentary_removal = false;\r\n\t\r\n}\r\n\r\n/*\r\n\tChanges the priority of an object, then reregisters.\r\n*/\r\nvoid CBaseManager::SetObjectPriority ( CObject& obj, Lst::Node< CObject >::Priority priority )\r\n{\r\n\tobj.m_node.SetPri(priority);\r\n\tReregisterObject(obj, obj.GetID());\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n/*\r\n\tDeletes CObjects that have been killed by CObject::mark_as_dead() (which is called\r\n\tby the \"Die\" member command). These CObjects will be \"out of play\" by this point, and\r\n\tonly need be deleted.\r\n*/\r\nvoid CGeneralManager::FlushDeadObjects()\r\n{\r\n\tLst::Head< CObject >*\t\thead = &m_kill_list;\r\n\tLst::Node< CObject >*\t\tnext = head->GetNext();\r\n\r\n\twhile ( next )\r\n\t{\r\n\t\tLst::Node< CObject >*\tkill = next;\r\n\t\tnext = next->GetNext();\r\n\t\tkill->Remove();\r\n\t\tCObject *pObject = kill->GetData( );\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\t// Lock Assert is not needed for objects that have been flagged for deletion  \t\r\n\t\tpObject->SetLockAssertOff();\r\n\t\t#endif\r\n\t\tdelete pObject;\r\n\t}\t\r\n}\r\n\r\n\r\nCGeneralManager::CGeneralManager( void )\r\n{\t\r\n\t// add flush task\r\n\tmp_kill_task = new Tsk::Task< CGeneralManager > ( flush_dead_objects, *this, Tsk::BaseTask::Node::vSYSTEM_TASK_PRIORITY_FLUSH_DEAD_OBJECTS );\r\n\tDbg_AssertType ( mp_kill_task, Tsk::Task< CGeneralManager > );\r\n\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tmlp_man->AddSystemTask ( *mp_kill_task ); \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeneralManager::~CGeneralManager( void )\r\n{\r\n\tUnlockAllObjects();\r\n\tDestroyAllObjects();\r\n\t\t\r\n\tDbg_AssertType ( mp_kill_task, Tsk::Task< CGeneralManager > );\r\n\tdelete mp_kill_task;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tRuns the specified function on all CObjects of the given type. Deleting is allowed.\r\n*/\r\nvoid\t\t\tCGeneralManager::ProcessAllObjectsOfType( sint type, Callback* process, void* data )\r\n{\r\n\tLst::Search< CObject >\tsh;\r\n\t\r\n\tuint32 stamp_mask = m_stamp_bit_manager.RequestBit();\r\n\t\r\n\t// clear the appropriate stamp bit\r\n\tfor (CObject* pObject = sh.FirstItem(m_object_list); pObject; pObject = sh.NextItem())\r\n\t{\r\n\t\tpObject->ClearStampBit(stamp_mask);\r\n\t}\r\n\t\r\n\t// traverse the object list\r\n\tdo\r\n\t{\r\n\t\t// clear the appropriate list changed bit\r\n\t\tm_list_changed &= ~stamp_mask;\r\n\t\t\r\n        CObject* pNextObject = sh.FirstItem(m_object_list);\r\n\t\t\r\n\t\twhile (pNextObject)\r\n\t\t{\r\n\t\t\tCObject* pObject = pNextObject;\r\n\t\t\tpNextObject = sh.NextItem();\r\n\t\t\t\r\n\t\t\tif (pObject->GetType() == type && !pObject->CheckStampBit(stamp_mask))\r\n\t\t\t{\r\n\t\t\t\tpObject->SetStampBit(stamp_mask);\r\n\t\t\t\t\r\n\t\t\t\tprocess(pObject, data);\r\n\t\t\t\t\r\n\t\t\t\tif (m_list_changed & stamp_mask) break;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\twhile (m_list_changed & stamp_mask);\r\n\t\r\n\tm_stamp_bit_manager.ReturnBit(stamp_mask);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tRuns the specified function on all CObjects in manager. Deleting is allowed.\r\n*/\r\nvoid\t\t\tCGeneralManager::ProcessAllObjects( Callback* process, void *data )\r\n{\r\n\tLst::Search< CObject >\tsh;\r\n\t\r\n\tuint32 stamp_mask = m_stamp_bit_manager.RequestBit();\r\n\t\r\n\t// clear the appropriate stamp bit\r\n\tfor (CObject* pObject = sh.FirstItem(m_object_list); pObject; pObject = sh.NextItem())\r\n\t{\r\n\t\tpObject->ClearStampBit(stamp_mask);\r\n\t}\r\n\t\r\n\t// traverse the object list\r\n\tdo\r\n\t{\r\n\t\t// clear the appropriate list changed bit\r\n\t\tm_list_changed &= ~stamp_mask;\r\n\t\t\r\n        CObject* pNextObject = sh.FirstItem(m_object_list);\r\n\t\t\r\n\t\twhile (pNextObject)\r\n\t\t{\r\n\t\t\tCObject* pObject = pNextObject;\r\n\t\t\tpNextObject = sh.NextItem();\r\n\t\t\t\r\n\t\t\tif (!pObject->CheckStampBit(stamp_mask))\r\n\t\t\t{\r\n\t\t\t\tpObject->SetStampBit(stamp_mask);\r\n\t\t\t\t\r\n\t\t\t\tprocess(pObject, data);\r\n\t\t\t\t\r\n\t\t\t\tif (m_list_changed & stamp_mask) break;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\twhile (m_list_changed & stamp_mask);\r\n\t\r\n\tm_stamp_bit_manager.ReturnBit(stamp_mask);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nsint\t\t\tCGeneralManager::CountObjectsOfType( sint type )\r\n{\r\n\t\r\n\r\n\tsint\t\t\t\t\tcount = 0;\r\n\tCObject*\t\t\t\t\tobj;\r\n\tLst::Search< CObject >\tsh;\r\n\r\n\r\n\tobj = sh.FirstItem( m_object_list );\r\n\r\n\twhile ( obj )\r\n\t{\r\n\t\tDbg_AssertType( obj, CObject );\r\n\r\n\t\tif (obj->GetType() == type)\r\n\t\t{\r\n\t\t\tcount++;\r\n\t\t}\r\n\t\tobj = sh.NextItem();\r\n\t}\r\n\r\n\treturn count;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeneralManager::AssertIfObjectsRemainApartFrom( sint *pApartFromThisType )\r\n{\r\n\t\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\t\r\n\tCObject* pObj;\r\n\tLst::Search< CObject > sh;\r\n\r\n\tbool GotRemainingObjects=false;\r\n\t\r\n\tpObj = sh.FirstItem( m_object_list );\r\n\r\n\twhile ( pObj )\r\n\t{\r\n\t\tDbg_AssertType( pObj, CObject );\r\n\r\n\t\tbool Match=false;\r\n\t\tsint *pType=pApartFromThisType;\r\n\t\twhile (*pType!=-1)\r\n\t\t{\r\n\t\t\tif (pObj->GetType()==*pType)\r\n\t\t\t{\r\n\t\t\t\tMatch=true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t++pType;\r\n\t\t}\t\r\n\t\t\r\n\t\tif ( !Match )\r\n\t\t{\r\n\t\t\tprintf(\"Object type = %d\\n\",pObj->GetType());\r\n\t\t\tGotRemainingObjects=true;\r\n\t\t}\r\n\t\tpObj = sh.NextItem();\r\n\t}\r\n\r\n\tDbg_MsgAssert(!GotRemainingObjects,(\"Objects remain !!!\"));\r\n\t\r\n\t#endif\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCalled by CObject::mark_as_dead(). Shouldn't call from anywhere else.\r\n*/\r\nvoid\t\tCGeneralManager::KillObject( CObject& obj )\r\n{\t\r\n\tDbg_AssertType( &obj, CObject );\r\n\t//Dbg_MsgAssert( obj.mp_node, ( \"CObject does not have a node\" ));\r\n\tDbg_MsgAssert( !obj.m_node.InList(),( \"CObject has not been unregistered\" ));\r\n\t\r\n\tm_kill_list.AddToHead( &obj.m_node );\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tReturns a (currently) unused ID.\r\n*/\r\nuint32 CGeneralManager::NewObjectID( void )\r\n{\r\n\tCTracker* p_tracker = CTracker::Instance();\r\n\treturn p_tracker->GetFreshId();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCObject*\t\tCGeneralManager::GetObjectByID( uint32 id )\r\n{\r\n\tCTracker* p_tracker = CTracker::Instance();\r\n\treturn p_tracker->GetObject(id);\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n"
  },
  {
    "path": "Code/Gel/Object/objsearch.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObjects (OBJ) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobjsearch.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tObject search code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <core/list.h>\r\n#include <core/task.h>\r\n\r\n#include <gel/objsearch.h>\r\n#include <gel/mainloop.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCObject*\t\t\tSearch::FindFirstObjectOfType( Lst::Head< CObject >& head, sint type )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( &head, Lst::Head< CObject > );\r\n\r\n\tCObject*\tobj = FirstItem( head );\r\n\t\r\n\tobj_type = type;\r\n\r\n\twhile ( obj )\r\n\t{\r\n\t\tDbg_AssertType( obj, CObject );\r\n\r\n\t\tif ( obj->GetType() == obj_type )\r\n\t\t{\r\n\t\t\treturn obj;\r\n\t\t}\r\n\t\t\r\n\t\tobj = NextItem();\r\n\t}\r\n\t\r\n\treturn obj;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCObject*\t\t\tSearch::FindNextObjectOfType( void )\r\n{\r\n\t\r\n\r\n\tCObject*\tobj = NextItem();\r\n\r\n\twhile ( obj )\r\n\t{\r\n\t\tDbg_AssertType( obj, CObject );\r\n\t\r\n\t\tif ( obj->GetType() == obj_type )\r\n\t\t{\r\n\t\t\treturn obj;\r\n\t\t}\r\n\t\t\t\r\n\t\tobj = NextItem();\r\n\t}\r\n\t\r\n\treturn obj;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Object/objtrack.cpp",
    "content": "#include <core/defines.h>\r\n#include <core/singleton.h>\r\n\r\n#include <core/hashtable.h>\r\n\r\n#include <gel/objman.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/Event.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/component.h>\r\n\r\n#include <gfx/2D/ScreenElemMan.h>\r\n\r\n\r\n// start autoduck documentation\r\n// @DOC objtrack\r\n// @module objtrack | None\r\n// @subindex Scripting Database\r\n// @index script | bails\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n\r\nCEventLog::CEventLog()\r\n{\r\n\tm_next_entry = 0;\r\n\tm_wrapped = false;\r\n\t\r\n\tmp_event_type_hash_table = NULL;\r\n\tm_event_depth = 0;\r\n\tm_num_new_entries = 0;\r\n}\r\n\r\n\r\n\r\nCEventLog::~CEventLog()\r\n{\r\n\tDbg_Assert(mp_event_type_hash_table);\r\n\tdelete mp_event_type_hash_table;\r\n}\r\n\r\n\r\n\r\nvoid CEventLog::AddEntry(uint32 type, uint32 target, uint32 source, uint32 script, uint32 receiverID, EOccurenceType occurenceType)\r\n{\r\n\tif (!mp_event_type_hash_table)\r\n\t{\r\n\t\tmp_event_type_hash_table = new Lst::HashTable<EventType>(8);\r\n\t\tScript::CArray *p_event_type_array = Script::GetArray(CRCD(0x8114f90,\"event_type_array\"), Script::ASSERT);\r\n\t\tfor (int i = 0; i < (int) p_event_type_array->GetSize(); i++)\r\n\t\t{\r\n\t\t\tstrcpy(m_event_type_table[i].mName, p_event_type_array->GetString(i));\r\n\t\t\tuint32 name_crc = Script::GenerateCRC(p_event_type_array->GetString(i));\r\n\t\t\tmp_event_type_hash_table->PutItem(name_crc, &m_event_type_table[i]);\r\n\t\t}\r\n\t}\r\n\t\t\t\r\n\tint last_entry = m_next_entry - 1;\r\n\tif (last_entry < 0)\r\n\t\tlast_entry = MAX_LOG_ENTRIES - 1;\r\n\t\r\n\tif (occurenceType == vUPDATE && m_table[last_entry].m_occurence_type == vUPDATE)\r\n\t{\r\n\t\t// no need to keep piling on update entries, just increase tick count\r\n\t\tm_table[last_entry].m_tick_count++;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (occurenceType == vHANDLED)\r\n\t\t\tm_event_depth--;\r\n\r\n\t\tEntry *p_entry = m_table + m_next_entry;\r\n\t\tif (occurenceType == vUPDATE)\r\n\t\t\tp_entry->m_tick_count\t\t= 0;\r\n\t\telse\r\n\t\t\tp_entry->m_type \t\t\t= type;\r\n\t\tp_entry->m_target \t\t\t\t= target;\r\n\t\tp_entry->m_source \t\t\t\t= source;\r\n\t\tp_entry->m_script \t\t\t\t= script;\r\n\t\tp_entry->m_receiver_id\t\t\t= receiverID;\r\n\t\tp_entry->m_occurence_type\t\t= occurenceType;\r\n\t\tp_entry->m_depth\t\t\t\t= m_event_depth;\r\n\t\r\n\t\tm_next_entry++;\r\n\t\tif (m_next_entry == MAX_LOG_ENTRIES)\r\n\t\t{\r\n\t\t\tm_next_entry = 0;\r\n\t\t\tm_wrapped = true;\r\n\t\t}\r\n\t\t\r\n\t\tif (occurenceType == vLAUNCHED)\r\n\t\t\tm_event_depth++;\r\n\t\t\r\n\t\tm_num_new_entries++;\r\n\t\t\r\n\t\t//PrintLatestEntry();\r\n\t}\r\n}\r\n\r\n\r\n\r\nvoid CEventLog::Print(bool onlyPrintNewEntries, int maxEntriesToPrint)\r\n{\r\n\tint index = 0;\r\n\tint count = m_next_entry;\r\n\tif (m_wrapped)\r\n\t{\r\n\t\tindex = m_next_entry;\r\n\t\tcount = MAX_LOG_ENTRIES;\r\n\t}\r\n\r\n\tif (onlyPrintNewEntries)\r\n\t{\r\n\t\tmaxEntriesToPrint = m_num_new_entries;\r\n\t}\r\n\t\r\n\tprintf(\"========================================================\\n\");\r\n\tif (onlyPrintNewEntries)\r\n\t\tprintf(\"PRINTING EVENT LOG (ONLY NEW ENTRIES)\\n\\n\");\r\n\telse\r\n\t\tprintf(\"PRINTING EVENT LOG\\n\\n\");\r\n\t\r\n\twhile(count > 0)\r\n\t{\r\n\t\tif (count <= maxEntriesToPrint)\t\t\r\n\t\t\tprint_entry(index);\r\n\t\tindex++;\r\n\t\tif (index == MAX_LOG_ENTRIES) index = 0;\r\n\t\tcount--;\r\n\t}\r\n\t\r\n\tprintf(\"========================================================\\n\");\r\n\r\n\tm_num_new_entries = 0;\r\n}\r\n\r\n\r\n\r\nvoid CEventLog::PrintLatestEntry()\r\n{\r\n\tint last_entry = m_next_entry - 1;\r\n\tif (last_entry < 0)\r\n\t\tlast_entry = MAX_LOG_ENTRIES - 1;\r\n\tprint_entry(last_entry);\r\n\tm_num_new_entries = 0;\r\n}\r\n\r\n\r\n\r\nvoid CEventLog::print_entry(int index)\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tEntry *p_entry = m_table + index;\r\n\r\n\t//printf(\"%d \", p_entry->m_depth);\r\n\tfor (int i = 0; i < p_entry->m_depth; i++) printf(\" \");\r\n\t\r\n\t// entry format: (<...> denotes optional)\r\n\t// \"ACTION: type=TYPE <target=TARGET> <receiver=RECEIVER> <source=SOURCE> <script=SCRIPT>\"\r\n\t// or: \"ACTION: type=TYPE <target/receiver=TARGET> <source=SOURCE> <script=SCRIPT>\"\r\n\t\r\n\tif (p_entry->m_occurence_type == vLAUNCHED || p_entry->m_occurence_type == vHANDLED || p_entry->m_occurence_type == vREAD) \r\n\t{\r\n\t\tif (p_entry->m_occurence_type == vLAUNCHED) \r\n\t\t\tprintf(\"Launched event: type=%s \", get_type_name(p_entry->m_type));\r\n\t\telse if (p_entry->m_occurence_type == vHANDLED) \r\n\t\t{\r\n\t\t\tif (p_entry->m_receiver_id == CTracker::vID_OBJECT_TRACKER)\r\n\t\t\t\tprintf(\"Event expired: type=%s \", get_type_name(p_entry->m_type));\r\n\t\t\telse\r\n\t\t\t\tprintf(\"Handled event: type=%s \", get_type_name(p_entry->m_type));\r\n\t\t}\r\n\t\telse if (p_entry->m_occurence_type == vREAD) \r\n\t\t\tprintf(\"Read event: type=%s \", get_type_name(p_entry->m_type));\r\n\t\t\r\n\t\tbool reciever_equals_target = (p_entry->m_target == p_entry->m_receiver_id);\r\n\r\n\t\tif (p_entry->m_target != CEvent::vSYSTEM_EVENT) \r\n\t\t{\r\n\t\t\tconst char *p_target_name;\r\n\t\t\tp_target_name = Script::FindChecksumName(p_entry->m_target);\r\n\t\t\t\r\n\t\t\tif (reciever_equals_target)\r\n\t\t\t\tprintf(\"target/receiver=%s \", p_target_name);\r\n\t\t\telse\r\n\t\t\t\tprintf(\"target=%s \", p_target_name);\r\n\t\t}\r\n\t\tif (!reciever_equals_target && p_entry->m_receiver_id != CTracker::vID_UNSPECIFIED_RECEIVER) \r\n\t\t{\r\n\t\t\tconst char *p_receiver_name;\r\n\t\t\tif (p_entry->m_receiver_id == CTracker::vID_SCREEN_ELEMENT_MANAGER) \r\n\t\t\t\tp_receiver_name = \"Screen Element Manager\";\r\n\t\t\telse if (p_entry->m_receiver_id == CTracker::vID_SUSPENDED_SCRIPT) \r\n\t\t\t\tp_receiver_name = \"Suspended Script\";\r\n\t\t\telse if (p_entry->m_receiver_id == CTracker::vID_OBJECT_TRACKER) \r\n\t\t\t\tp_receiver_name = \"(Killed By) Object Tracker\";\r\n\t\t\telse\r\n\t\t\t\tp_receiver_name = Script::FindChecksumName(p_entry->m_target);\r\n\t\t\t\r\n\t\t\tprintf(\"receiver=%s \", p_receiver_name);\r\n\t\t}\r\n\t\tif (p_entry->m_source != CEvent::vSYSTEM_EVENT) \r\n\t\t\tprintf(\"source=%s \", Script::FindChecksumName(p_entry->m_source));\r\n\t\tif (p_entry->m_script) \r\n\t\t\tprintf(\"script=%s \", Script::FindChecksumName(p_entry->m_script));\r\n\t\tprintf(\"\\n\");\r\n\t}\r\n\telse if (p_entry->m_occurence_type == vOBJECT_ADD || p_entry->m_occurence_type == vOBJECT_REMOVE) \r\n\t{\r\n\t\tif (p_entry->m_occurence_type == vOBJECT_ADD)\r\n\t\t\tprintf(\"Added object: %s\", Script::FindChecksumName(p_entry->m_target));\r\n\t\telse\r\n\t\t\tprintf(\"Removed object: %s\", Script::FindChecksumName(p_entry->m_target));\r\n\t\tprintf(\"\\n\");\r\n\t}\r\n\telse if (p_entry->m_occurence_type == vUPDATE) \r\n\t{\r\n\t\tprintf(\"Tick, counts = %d\\n\", p_entry->m_tick_count);\r\n\t}\r\n#endif  \r\n}\r\n\r\n\r\n\r\nconst char *CEventLog::get_type_name(uint32 type)\r\n{\r\n\tEventType *p_type_entry = mp_event_type_hash_table->GetItem(type);\r\n\tif (p_type_entry)\r\n\t{\r\n\t\treturn p_type_entry->mName;\r\n\t}\r\n\telse\r\n\t\treturn Script::FindChecksumName(type);\r\n}\r\n\r\n\r\n\r\nDefineSingletonClass( CTracker, \"CObject Tracker\" );\r\n\r\n\r\n\r\n/*\r\n\tEvery CObject that is registered with a CBaseManager should also be registered with CTracker.\r\n*/\r\nvoid CTracker::addObject(CObject *pObject)\r\n{\r\n\tDbg_MsgAssert(pObject->GetID() != 0xFFFFFFFF, (\"CObject has no ID\"));\r\n\tDbg_MsgAssert(!mp_hash_table->GetItem(pObject->GetID()), (\"CObject with ID %s already in tracking system\", Script::FindChecksumName(pObject->GetID())));\r\n\t\r\n\t// if object ID already being used as alias, remove the alias\r\n\tCObject *p_alias_obj = mp_alias_table->GetItem(pObject->GetID());\r\n\tif (p_alias_obj)\r\n\t{\r\n\t\tp_alias_obj->RemoveReference();\r\n\t\tmp_alias_table->FlushItem(pObject->GetID());\r\n\t}\r\n\t\r\n\tmp_hash_table->PutItem(pObject->GetID(), pObject);\r\n#ifdef __DEBUG_OBJ_MAN__\r\n\tprintf(\"*** Added object %s to global tracker\\n\", Script::FindChecksumName(pObject->GetID()));\r\n#endif\r\n\r\n\tm_event_log.AddEntry(0, pObject->GetID(), CEvent::vSYSTEM_EVENT, 0, 0, CEventLog::vOBJECT_ADD);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tRyan Old Comment: The 'newIdOfObjectBeingMomentarilyRemoved' parameter is set if we are just changing the ID of the object,\r\n\twhich requires removing it, then adding it again. Otherwise, this parameter will be zero (the id of the skater, fool!)\r\n\tMick New comment: now we have an additional boolean passed top indicate if the value in newIdOfObjectBeingMomentarilyRemoved\r\n\tis valid, as it might be 0, if we are changing the id of a client skater back to 0\r\n*/\r\n\r\nvoid CTracker::removeObject(CObject *pObject, uint32 newIdOfObjectBeingMomentarilyRemoved, bool momentary_removal)\r\n{\r\n\tmp_hash_table->FlushItem(pObject->GetID());\r\n\tif (momentary_removal)\r\n\t{\r\n\t\t// go through all the scripts waiting on object, change the ID\r\n\t\tfor (int i = 0; i < vMAX_SCRIPT_ENTRIES; i++)\r\n\t\t{\r\n\t\t\tif (m_waiting_script_tab[i].mObjectId == pObject->GetID())\r\n\t\t\t{\r\n\t\t\t\tm_waiting_script_tab[i].mObjectId = newIdOfObjectBeingMomentarilyRemoved;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// only remove aliases to an object if it is going away \"permanently\"\r\n\t\tremove_aliases(pObject);\r\n\t}\r\n\r\n#ifdef __DEBUG_OBJ_MAN__\r\n\tprintf(\"*** Removed object %s from global tracker\\n\", Script::FindChecksumName(pObject->GetID()));\r\n#endif\r\n\r\n\tm_event_log.AddEntry(0, pObject->GetID(), CEvent::vSYSTEM_EVENT, 0, 0, CEventLog::vOBJECT_REMOVE);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tForwards the event to listeners associated with the object. Handy for forwarding global\r\n\tevents to specific recipients.\r\n\t\r\n\tIf no object specified, event goes to all listeners.\r\n*/\r\nvoid CTracker::forward_event_to_listeners(CEvent *pEvent, CObject *pObject)\r\n{\r\n\tDbg_Assert(pEvent);\r\n\t\r\n\t// Try event on all registered listeners\r\n\t// The ref counting stuff will fire an assert if an\tevent listener gets deleted\r\n\tCEventListener *p_listener = mp_event_listener_list;\r\n\twhile (p_listener)\r\n\t{\r\n\t\t// prevents listener from being deleted (without an assert)\r\n\t\tp_listener->m_ref_count++;\r\n\t\tif (!pObject || p_listener->mp_object == pObject)\r\n\t\t\tp_listener->event_filter(pEvent);\r\n\t\tp_listener->m_ref_count--;\r\n\t\tp_listener = p_listener->mp_next_listener;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tWhen a CObject is removed from tracking, all aliases that point to it must be removed.\r\n*/\r\nvoid CTracker::remove_aliases(CObject *pObject)\r\n{\r\n\twhile(1)\r\n\t{\r\n\t\t//if (mp_alias_table->GetSize() == 0)\r\n\t\t//\tbreak;\r\n\t\t\r\n\t\tmp_alias_table->IterateStart();\r\n\t\tuint32 entry_key;\r\n\t\tCObject *p_entry = mp_alias_table->IterateNext(&entry_key);\r\n\t\twhile(p_entry)\r\n\t\t{\r\n\t\t\tif (p_entry->GetID() == pObject->GetID())\r\n\t\t\t{\r\n\t\t\t\t// Found match. Remove it and repeat outer loop\r\n\t\t\t\tp_entry->RemoveReference();\r\n\t\t\t\tmp_alias_table->FlushItem(entry_key);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tp_entry = mp_alias_table->IterateNext(&entry_key);\r\n\t\t}\r\n\r\n\t\tif (!p_entry)\r\n\t\t\t// no more matches left, we're done\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nCTracker::CTracker()\r\n{\r\n\tmp_hash_table = new Lst::HashTable<CObject>(8);\r\n\tmp_alias_table = new Lst::HashTable<CObject>(4);\r\n\tmp_event_receiver_table = new Lst::HashTable<CEventReceiverList>(8);\t\r\n\t\r\n\tm_id_seed = 0;\r\n\r\n\tmp_event_listener_list = NULL;\r\n\tm_block_event_launching = false;\r\n\tm_event_recurse_depth = 0;\r\n\r\n\tm_next_event_script = 0;\r\n\r\n\tfor (int i = 0; i < vMAX_SCRIPT_ENTRIES; i++) \r\n\t\tm_waiting_script_tab[i].mEventType = vDEAD_SCRIPT_ENTRY;\r\n\t\r\n\t// XXX\r\n\tm_debug = false;\r\n}\r\n\r\n\r\n\r\n\r\nCTracker::~CTracker()\r\n{\r\n\tDbg_MsgAssert(mp_hash_table->GetSize(), (\"entries still in tracker\"));\r\n\tdelete mp_hash_table;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tReturns a pointer to the CObject whose ID matches the one given, returns NULL if not found.\r\n\tWill return the object if it has an alias, which is used in the front end for stuff like \"MainMenu\"\r\n\tBut is also now used for \"Skater\" and \"Skater2\"\r\n*/\r\nCObject *CTracker::GetObject(uint32 id)\r\n{\r\n\tCObject *p_obj = mp_hash_table->GetItem(id);\r\n\tif (!p_obj)\r\n\t{\r\n\t\tp_obj = mp_alias_table->GetItem(id);\r\n\t}\r\n\treturn p_obj;\r\n}\r\n\r\n\r\n\r\n\r\nCObject *CTracker::GetObjectByAlias(uint32 aliasId)\r\n{\r\n\treturn mp_alias_table->GetItem(aliasId);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CTracker::AddAlias(uint32 alias, CObject *pObject)\r\n{\r\n\t// make sure alias not already being used for object ID\r\n\tDbg_MsgAssert(!mp_hash_table->GetItem(alias), (\"CObject with ID %s already in tracking system\", Script::FindChecksumName(alias)));\r\n\t\r\n\t// if desired alias already being used as alias, remove old one\r\n\tCObject *p_alias_obj = mp_alias_table->GetItem(alias);\r\n\tif (p_alias_obj)\r\n\t{\r\n\t\tp_alias_obj->RemoveReference();\r\n\t\tmp_alias_table->FlushItem(alias);\r\n\t}\r\n\r\n\tpObject->AddReference();\r\n\tmp_alias_table->PutItem(alias, pObject);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tReturns an ID that is not currently being used. Pretty high probability of not\r\n\tcolliding with a user-created ID.\r\n*/\r\nuint32 CTracker::GetFreshId()\r\n{\r\n\twhile(1)\r\n\t{\r\n\t\tchar name_string[64];\r\n\t\tsprintf(name_string, \"autoid%d\", m_id_seed++);\r\n\t\tif (m_id_seed >= 1000000)\r\n\t\t\tm_id_seed = 0;\r\n\t\tuint32 id = Script::GenerateCRC(name_string);\r\n\t\tif (!mp_hash_table->GetItem(id))\r\n\t\t{\r\n\t\t\treturn id;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\r\n// Debug function to track down corruption in scripts event handler tables\r\n// we iterate over all the event receivers, and check that the tables that\r\n// they point to are valid\r\n\r\nvoid CTracker::ValidateReceivers()\r\n{\r\n\t\r\n\tmp_event_receiver_table->IterateStart();\r\n\tuint32 entry_key;\r\n\tCEventReceiverList *p_entry = mp_event_receiver_table->IterateNext(&entry_key);\r\n\twhile(p_entry)\r\n\t{\r\n\t\tp_entry = mp_event_receiver_table->IterateNext(&entry_key);\r\n\t\tif (p_entry)\r\n\t\t{\r\n\t\t\t\tLst::Node< Script::CScript >*p_node = p_entry->FirstItem();\r\n\t\t\t\twhile (p_node)\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CScript * p_script =  p_node->GetData();\r\n\t\t\t\t\t// Got a pointer to a node, so first validate that\r\n\t\t\t\t\t// then validate the event handler table\r\n\t\t\t\t\t\r\n#ifndef __PLAT_WN32__\t// These script functions are not necessary from PC tools\r\n\r\n\t\t\t\t\tObj::CEventHandlerTable * p_event_handler_table = p_script->GetEventHandlerTable();\r\n\t\t\t\t\t// Validate the table object\r\n\t\t\t\t\tDbg_MsgAssert(Mem::Valid(p_event_handler_table),(\"Corrupt Event handler table object for event %s\\n\",Script::FindChecksumName(entry_key)));\r\n\t\t\t\t\t// and the table it contains\r\n\t\t\t\t\tDbg_MsgAssert(!p_event_handler_table->m_num_entries || Mem::Valid(p_event_handler_table->mp_tab),(\"Corrupt Event handler table actual table for event %s\\n\",Script::FindChecksumName(entry_key)));\r\n\r\n#endif\r\n\r\n\t\t\t\t\tp_node = p_node->GetNext();\t\t\t\t\t\r\n\t\t\t\t}\r\n\r\n\t\t\t\r\n\t\t}\r\n\t\r\n\t}\r\n}\r\n#endif\r\n\r\n\r\n// returns true if event was handled\r\nbool CTracker::LaunchEvent(uint32 type, uint32 target, uint32 source, Script::CStruct *pData, bool broadcast)\r\n{\r\n//\tprintf(\"launch event, type=%s, target=0x%x, source= 0x%x, pData = %p\\n\", Script::FindChecksumName(type),target,source, pData);\r\n\t\r\n//\tDbg_MsgAssert(!broadcast,(\"Don't use the broadcast flag yet!!!\"));\r\n\t\r\n\tDbg_MsgAssert(!m_block_event_launching, (\"event launches are blocked\"));\r\n\tDbg_MsgAssert(m_event_recurse_depth < vMAX_EVENT_RECURSE_DEPTH, (\"too many nested LaunchEvents -- check your scripts\"));\r\n\t//printf(\"### launch event depth %d\\n\", m_event_recurse_depth);\r\n\tm_event_recurse_depth++;\r\n\t\r\n\t// log event\r\n\tm_event_log.AddEntry(type, target, source, m_next_event_script, 0, CEventLog::vLAUNCHED);\r\n\tm_next_event_script = 0;\r\n\t\r\n\tCEvent event;\r\n\tevent.m_type = type;\r\n\tevent.m_target_id = target;\r\n\tevent.m_source_id = source;\r\n\tevent.mp_data = pData;\r\n\t\r\n\t\r\n\r\n\r\n\t\r\n\tif (broadcast)\r\n\t{\t\r\n\t\t#ifdef __SCRIPT_EVENT_TABLE__\r\n\r\n\t\t// broadcast to each script that has an event handler table\r\n\t\tCEventReceiverList *p_event_list = mp_event_receiver_table->GetItem(type);\r\n\t\tif (p_event_list)\r\n\t\t{\r\n\t\t\tint scripts = p_event_list->CountItems();\r\n\t\t\tDbg_MsgAssert(scripts, (\"Empty list for event %s\",Script::FindChecksumName(type)));\r\n\t\t\tif (scripts == 1)\r\n\t\t\t{\r\n\t\t\t\t// Just one object, so do a quicker sending of the event\r\n\t\t\t\tLst::Node< Script::CScript >*p_node =   p_event_list->FirstItem();\r\n\t\t\t\tScript::CScript *p_script = p_node->GetData();\r\n\t\t\t\tp_script->PassTargetedEvent(&event, broadcast);\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// For multiple scripts, we need to make a copy of the the list of scripts\r\n\t\t\t\t// that will receive this. Otherwise chaos ensues, as scripts change their event handlers based on events. \r\n\t\t\t\t// We also use a list of smart pointers to the mp_reference in a script, so if one event handler deletes\r\n\t\t\t\t// another object (and hence its script)\r\n\t\t\t\t// then we can safely ignore that object (since it no longer exists)\r\n\t\t\t\t// as the pointer will be set to NULL.\t\t\t\r\n\t\t\t\t\r\n\t\t\t\tScript::CScript ** pp_scripts = new Script::CScript*[scripts];\r\n\t\t\t\tCSmtPtr<CRefCounted> * pp_refs = new CSmtPtr<CRefCounted>[scripts];\r\n\t\t\t\t\r\n\t\t\t\tLst::Node< Script::CScript >*p_node = p_event_list->FirstItem();\r\n\t\t\t\tint n=0;\r\n\t\t\t\twhile (p_node)\r\n\t\t\t\t{\r\n\t\t\t\t\tpp_scripts[n] = p_node->GetData();\r\n\t\t\t\t\tCRefCounted * p_ref = &(p_node->GetData()->m_reference_counter);\r\n\t\t\t\t\tpp_refs[n] = p_ref;\r\n\t\t\t\t\t\r\n\t\t\t\t\tn++;\r\n\t\t\t\t\tp_node = p_node->GetNext();\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tfor (n = 0; n<scripts; n++)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (pp_refs[n])\t\t\t// Smart pointer to script reference counter might have been deleted by some other object\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpp_scripts[n]->PassTargetedEvent(&event, broadcast);\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tdelete [] pp_refs;\t \r\n\t\t\t\tdelete [] pp_scripts;\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t}\r\n\t\t\r\n\t\t\r\n\t\t#else\r\n\t\t// broadcast to each object that has an event handler table\r\n\t\tCEventReceiverList *p_event_list = mp_event_receiver_table->GetItem(type);\r\n\t\tif (p_event_list)\r\n\t\t{\r\n\t\t\tint objects = p_event_list->CountItems();\r\n\t\t\tDbg_MsgAssert(objects, (\"Empty list for event %s\",Script::FindChecksumName(type)));\r\n\t\t\tif (objects == 1)\r\n\t\t\t{\r\n\t\t\t\t// Just one object, so do a quicker sending of the event\r\n\t\t\t\tLst::Node< Obj::CObject >*p_node =   p_event_list->FirstItem();\r\n\t\t\t\tObj::CObject *p_obj = p_node->GetData();\r\n\t\t\t\tp_obj->PassTargetedEvent(&event, broadcast);\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// For multiple objects, we need to make a copy of the the list of objects\r\n\t\t\t\t// that will receive this. Otherwise chaos ensues, as objects change their event handlers based on events. \r\n\t\t\t\t// We use a list of smart pointers, so if one object handler deletes another object\r\n\t\t\t\t// then we can safely ignore that object (since it no longer exists)\r\n\t\t\t\t// as the pointer will be set to NULL.\t\t\t\r\n\t\t\t\tCObjectPtr * pp_objects = new CObjectPtr[objects];\r\n\t\t\t\tLst::Node< Obj::CObject >*p_node = p_event_list->FirstItem();\r\n\t\t\t\tint n=0;\r\n\t\t\t\twhile (p_node)\r\n\t\t\t\t{\r\n\t\t\t\t\tpp_objects[n++] = p_node->GetData();\r\n\t\t\t\t\tp_node = p_node->GetNext();\r\n\t\t\t\t}\r\n\t\t\t\tfor (n = 0; n<objects; n++)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (pp_objects[n])\t\t\t// Smart pointer might have been deleted by some other object\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpp_objects[n]->PassTargetedEvent(&event, broadcast);\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tdelete [] pp_objects;\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t}\r\n\t\t#endif\r\n\t}\r\n\telse\r\n\t{\r\n\t\t\r\n\t\t\r\n\t\t// try event on all registered listeners\r\n\t\tforward_event_to_listeners(&event, NULL);\r\n\t\r\n\t\t// if event has a specific target, then send to that CObject\r\n\t\tif (event.m_target_id != CEvent::vSYSTEM_EVENT && !event.WasHandled())\r\n\t\t{\r\n\t\t\t// look for a object with the target id\r\n\t\t\tCObject *p_object = GetObject(event.m_target_id);\r\n\t\t\tif (!p_object)\r\n\t\t\t{\r\n\t\t\t\t// or look for a script with the target id\r\n\t\t\t\tScript::CScript *p_script = Script::FindSpawnedScriptWithID(event.m_target_id);\r\n\t\t\t\t\r\n\t\t\t\tif (!p_script)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_event_log.Print(256);\r\n\t\t\t\t\t#ifdef __NOPT_ASSERT__\t\t\t\r\n\t\t\t\t\tmp_hash_table->PrintContents();\r\n\t\t\t\t\t#endif\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tDbg_MsgAssert(p_script, (\"couldn't find object or script id %s\", Script::FindChecksumName(event.m_target_id)));\r\n\t\t\t\t\r\n\t\t\t\tp_script->PassTargetedEvent(&event);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_object->PassTargetedEvent(&event);\r\n\t\t\t}\r\n\t\t\t// p_object may have been deleted\r\n\t\t}\r\n\t}\r\n\t\r\n\t/* \r\n\t\tSee if any scripts were waiting on the event.\r\n\t\t\r\n\t\tUnblock script if type matches AND:\r\n\t\t-target matches\r\n\t\t-OR script not associated with object\r\n\t\t-OR a system event\r\n\t*/\r\n\tfor (int i = 0; i < vMAX_SCRIPT_ENTRIES; i++)\r\n\t{\r\n\t\t//if (m_waiting_script_tab[i].mEventType == Script::GenerateCRC(\"showed_wait_message\"))\r\n\t\t//\tRyan(\"   hoorah: 0x%x 0x%x\\n\", m_waiting_script_tab[i].mObjectId, target);\r\n\r\n\t\tif (m_waiting_script_tab[i].mEventType == type && \r\n\t\t\t(m_waiting_script_tab[i].mObjectId == target || m_waiting_script_tab[i].mObjectId == 0 || target == CEvent::vSYSTEM_EVENT || broadcast))\r\n\t\t{\t\t\t\r\n\t\t\t// We found a suspended script of the correct type and target.\r\n\t\t\t// Can remove entry.\r\n\t\t\tm_waiting_script_tab[i].mEventType = vDEAD_SCRIPT_ENTRY;\r\n\r\n\t\t\t// does the script actually exist right now?\r\n\t\t\tScript::CScript *p_script = Script::GetScriptWithUniqueId(m_waiting_script_tab[i].mScriptId);\r\n\t\t\tif (p_script)\r\n\t\t\t{\r\n\t\t\t\tp_script->UnBlock();\r\n\t\t\t\tevent.MarkHandled(vID_SUSPENDED_SCRIPT, p_script->mScriptChecksum);\r\n\t\t\t\t//printf(\"unblocking script %s (id=%d)\\n\", Script::FindChecksumName(p_script->mScriptChecksum), m_waiting_script_tab[i].mScriptId);\r\n\t\t\t\t// alright, the event is handled, so leave loop\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//printf(\"script to unblock doesn't exist (id=%d)\\n\", m_waiting_script_tab[i].mScriptId);\r\n\t\t\t}\r\n\r\n\t\t\t// the event is NOT handled\r\n\t\t}\r\n\t}\r\n\r\n\tif (!event.WasHandled())\r\n\t\t// no one handled event, mark as killed by object tracker\r\n\t\tLogEventHandled(&event, vID_OBJECT_TRACKER);\r\n\t\r\n\tm_event_recurse_depth--;\r\n\r\n\treturn event.WasHandled();\r\n}\r\n\r\n\r\n\r\n\r\n// Call right before calling LaunchEvent()\r\nvoid CTracker::LogEventScript(uint32 script)\r\n{\r\n\tm_next_event_script = script;\r\n}\r\n\r\n\r\n\r\nvoid CTracker::LogEventHandled(CEvent *pEvent, uint32 receiverID, uint32 script)\r\n{\r\n\t// log event\r\n\tm_event_log.AddEntry(pEvent->GetType(), pEvent->GetTarget(), pEvent->GetSource(), script, receiverID, CEventLog::vHANDLED);\r\n}\r\n\r\n\r\n\r\nvoid CTracker::LogEventRead(CEvent *pEvent, uint32 receiverID, uint32 script)\r\n{\r\n\t// log event\r\n\tm_event_log.AddEntry(pEvent->GetType(), pEvent->GetTarget(), pEvent->GetSource(), script, receiverID, CEventLog::vREAD);\r\n}\r\n\r\n\r\n\r\nvoid CTracker::LogTick()\r\n{\r\n\tm_event_log.AddEntry(0, 0, 0, 0, 0, CEventLog::vUPDATE);\r\n}\r\n\r\n\r\n\r\nvoid CTracker::PrintEventLog(bool mostRecentOnly, int maxToPrint)\r\n{\r\n\tm_event_log.Print(mostRecentOnly, maxToPrint);\r\n}\r\n\r\n\r\n\r\nvoid CTracker::RegisterEventListener(CEventListener *pListener)\r\n{\r\n\tDbg_MsgAssert(!pListener->m_registered, (\"listener already registered\"));\r\n\r\n\tpListener->mp_next_listener = mp_event_listener_list;\r\n\tmp_event_listener_list = pListener;\r\n\tpListener->m_registered = true;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CTracker::UnregisterEventListener(CEventListener *pListener)\r\n{\r\n\tDbg_MsgAssert(pListener->m_registered, (\"listener not registered\"));\r\n\r\n\tCEventListener *p_prev = NULL;\r\n\tCEventListener *p_current = mp_event_listener_list;\r\n\twhile(p_current)\r\n\t{\r\n\t\tif (p_current == pListener)\r\n\t\t{\r\n\t\t\tif (p_prev)\r\n\t\t\t\tp_prev->mp_next_listener = pListener->mp_next_listener;\r\n\t\t\telse\r\n\t\t\t\tmp_event_listener_list = pListener->mp_next_listener;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tp_prev = p_current;\r\n\t\tp_current = p_current->mp_next_listener;\r\n\t}\r\n\tpListener->m_registered = false;\r\n}\r\n\r\n// Add this object to the list of objects that are listening for\r\n// events of this \"type\", so any broadcast event of this type will go directly there\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\nvoid\t\tCTracker::RegisterEventReceiver(uint32 type, Script::CScript *p_obj)\r\n#else\r\nvoid\t\tCTracker::RegisterEventReceiver(uint32 type, CObject *p_obj)\r\n#endif\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n//\tprintf (\"Registering Event %s from Object %s\\n\",Script::FindChecksumName(type), Script::FindChecksumName(p_obj->GetID()));\r\n// If there is no CEventList in the hash table for \"type\" then create one\r\n\tCEventReceiverList *p_event_list = mp_event_receiver_table->GetItem(type);\r\n\tif (!p_event_list)\r\n\t{\r\n\t\tp_event_list = new CEventReceiverList();\r\n\t\tmp_event_receiver_table->PutItem(type,p_event_list); \r\n\t}\r\n\t\r\n// Add this object to the that list, if it is not already added\r\n\tp_event_list->RegisterEventReceiverObject(p_obj);\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\t\t\r\n}\r\n\r\n\r\n\r\n// Remove this object from the list of objects that are listening for\r\n// events of this \"type\"\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\nvoid\t\tCTracker::UnregisterEventReceiver(uint32 type, Script::CScript *p_obj)\r\n#else\r\nvoid\t\tCTracker::UnregisterEventReceiver(uint32 type, CObject *p_obj)\r\n#endif\r\n{\r\n//\tprintf (\"Unregistering Event %s from Object %s\\n\",Script::FindChecksumName(type), Script::FindChecksumName(p_obj->GetID()));\r\n\t// If there is a reciever list for this \"type\"\r\n\tCEventReceiverList *p_event_list = mp_event_receiver_table->GetItem(type);\r\n\tif (p_event_list)\r\n\t{\r\n\t\t// then remove the object from the CEventList\r\n\t\tp_event_list->UnregisterEventReceiverObject(p_obj);\r\n\t\r\n\t\t// If the list is empty\r\n\t\tif (p_event_list->IsEmpty())\r\n\t\t{\t\t\r\n\t\t\t// Then remove it from the hash table\r\n\t\t\tmp_event_receiver_table->FlushItem(type);\r\n\t\t\t// and delete it\r\n\t\t\tdelete p_event_list; \r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\nCEventReceiverList::CEventReceiverList()\r\n{\r\n\r\n}\r\n\r\n\r\n// Register an object with this event receiver list\r\n// all this does is add it to the list, so events of this \"type\" are sent to it\r\n// it will not be added to the same list twice (just ignores additional registers)\r\n\t\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\nvoid\t\tCEventReceiverList::RegisterEventReceiverObject(Script::CScript *p_script)\r\n{\r\n\t// See if the object is already in the list, and return if it is\r\n\tLst::Node<Script::CScript> * p_search = m_objects.FirstItem();\r\n\twhile (p_search)\r\n\t{\r\n\t\tif (p_search->GetData() == p_script)\r\n\t\t\treturn;\r\n\t\tp_search = p_search->GetNext();\r\n\t}\r\n\t\r\n\t// Create a new node for adding to the list\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\tLst::Node<Script::CScript>* p_node = new Lst::Node<Script::CScript>(p_script);\r\n\tMem::Manager::sHandle().PopContext();\t\r\n\t// Just add it to the tail of the list\r\n\tm_objects.AddToTail(p_node);\r\n}\r\n#else\r\n\r\nvoid\t\tCEventReceiverList::RegisterEventReceiverObject(CObject *p_obj)\r\n{\r\n\t// See if the object is already in the list, and return if it is\r\n\tLst::Node<Obj::CObject> * p_search = m_objects.FirstItem();\r\n\twhile (p_search)\r\n\t{\r\n\t\tif (p_search->GetData() == p_obj)\r\n\t\t\treturn;\r\n\t\tp_search = p_search->GetNext();\r\n\t}\r\n\t\r\n\t// Create a new node for adding to the list\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\tLst::Node<Obj::CObject>* p_node = new Lst::Node<Obj::CObject>(p_obj);\r\n\tMem::Manager::sHandle().PopContext();\t\r\n\t// Just add it to the tail of the list\r\n\tm_objects.AddToTail(p_node);\r\n}\r\n#endif\r\n\r\n// remove an object from this list (if it is in it)\r\n// if it is not in the list, it will just be ignored\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\nvoid\t\tCEventReceiverList::UnregisterEventReceiverObject(Script::CScript *p_script)\r\n{\r\n\t// Get the node from the list\r\n\r\n\tLst::Node<Script::CScript>* p_node = NULL;\r\n\tLst::Node<Script::CScript> * p_search = m_objects.FirstItem();\r\n\twhile (p_search)\r\n\t{\r\n\t\tif (p_search->GetData() == p_script)\r\n\t\t{\r\n\t\t\tp_node = p_search;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tp_search = p_search->GetNext();\r\n\t}\r\n\tif (p_node)\r\n\t{\r\n\t\t\r\n\t\t// Just remove it from the list\r\n\t\tp_node->Remove();\r\n\t\t\r\n\t\t// and delete the node (might be left with an empty list, but the tracker is responsible for cleaning it up)\r\n\t\tdelete p_node;\r\n\t}\t\r\n}\r\n#else\r\n\r\nvoid\t\tCEventReceiverList::UnregisterEventReceiverObject(CObject *p_obj)\r\n{\r\n\t// Get the node from the list\r\n\r\n\tLst::Node<Obj::CObject>* p_node = NULL;\r\n\tLst::Node<Obj::CObject> * p_search = m_objects.FirstItem();\r\n\twhile (p_search)\r\n\t{\r\n\t\tif (p_search->GetData() == p_obj)\r\n\t\t{\r\n\t\t\tp_node = p_search;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tp_search = p_search->GetNext();\r\n\t}\r\n\tif (p_node)\r\n\t{\r\n\t\t\r\n\t\t// Just remove it from the list\r\n\t\tp_node->Remove();\r\n\t\t\r\n\t\t// and delete the node (might be left with an empty list, but the tracker is responsible for cleaning it up)\r\n\t\tdelete p_node;\r\n\t}\t\r\n}\r\n#endif\r\n\r\n\r\n\r\n/*\r\n\tCauses a script to be blocked until the (future) arrival of an event of the designated type.\r\n\tIf the script is associated with an object AND the event has a target, then the target\r\n\tmust be that object.\r\n*/\r\nvoid CTracker::SuspendScriptUntilEvent(Script::CScript *pScript, uint32 event_type)\r\n{\r\n\t// find an unused entry\r\n\r\n\tint unused_entry_index = -1;\r\n\tint i = 0;\r\n\tfor (; i < vMAX_SCRIPT_ENTRIES; i++) \r\n\t{\r\n\t\tif (m_waiting_script_tab[i].mEventType == vDEAD_SCRIPT_ENTRY)\r\n\t\t{\r\n\t\t\tunused_entry_index = i;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (unused_entry_index < 0)\r\n\t{\r\n\t\t// hmm, no unused entries, so find entry whose script is dead\r\n\t\tfor (i = 0; i < vMAX_SCRIPT_ENTRIES; i++) \r\n\t\t{\r\n\t\t\tScript::CScript *p_script = Script::GetScriptWithUniqueId(m_waiting_script_tab[i].mScriptId);\r\n\t\t\tif (!p_script)\r\n\t\t\t{\r\n\t\t\t\tunused_entry_index = i;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (unused_entry_index >= 0)\r\n\t{\r\n\t\t//printf(\"suspending script %s (id=%d)\\n\", Script::FindChecksumName(pScript->mScriptChecksum), pScript->GetUniqueId());\r\n\t\tm_waiting_script_tab[unused_entry_index].mScriptId = pScript->GetUniqueId();\r\n\t\tif (pScript->mpObject)\r\n\t\t\tm_waiting_script_tab[unused_entry_index].mObjectId = pScript->mpObject->GetID();\r\n\t\telse\r\n\t\t\tm_waiting_script_tab[unused_entry_index].mObjectId = 0;\r\n\t\tm_waiting_script_tab[unused_entry_index].mEventType = event_type;\r\n\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tm_waiting_script_tab[unused_entry_index].mScriptName = pScript->mScriptChecksum;\r\n\t\t#endif\r\n\r\n\t\t// suspend the script until later notice\r\n\t\tpScript->Block();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tprintf(\"out of script entries, scripts still waiting for events:\\n\");\r\n\t\tfor (i = 0; i < vMAX_SCRIPT_ENTRIES; i++) \r\n\t\t{\r\n\t\t\tprintf(\"   %s\\n\", Script::FindChecksumName(m_waiting_script_tab[i].mScriptName));\r\n\t\t}\r\n\t\tDbg_MsgAssert(0, (\"%s\\nout of script entries (%d)in WaitForEvent\",pScript->GetScriptInfo(),vMAX_SCRIPT_ENTRIES));\r\n\t\t#endif\r\n\t}\r\n}\r\n\r\n\r\n\r\n#ifndef __PLAT_WN32__\t// These script functions are not necessary from PC tools\r\n\r\n// @script | LaunchEvent | \r\n// @parm name | type | event type\r\n// @parm structure | data | \r\nbool ScriptLaunchEvent(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// Although events aren't necessarily tied to the Screen Element system, it is\r\n\t// convenient to enable this function to support complex ID's, for when we\r\n\t// are dealing with Screen Elements\r\n\tFront::CScreenElementManager* pManager = Front::CScreenElementManager::Instance();\r\n\tuint32 target = pManager->ResolveComplexID(pParams, CRCD(0xb990d003,\"target\"));\r\n\tif (target)\t\r\n\t{\r\n\t\tif (target == CRCD(0x36b2ee74, \"system\"))\r\n\t\t\ttarget = CEvent::vSYSTEM_EVENT;\t\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (pScript->mpObject)\r\n\t\t\ttarget = pScript->mpObject->GetID();\r\n\t\telse\r\n\t\t\ttarget = CEvent::vSYSTEM_EVENT;\r\n\t}\r\n\t\r\n\tuint32 source = pManager->ResolveComplexID(pParams, CRCD(0xa075808c,\"source\"));\r\n\tif (source)\t\r\n\t{\r\n\t\tif (source == CRCD(0x36b2ee74, \"system\"))\r\n\t\t\tsource = CEvent::vSYSTEM_EVENT;\t\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (pScript->mpObject)\r\n\t\t\tsource = pScript->mpObject->GetID();\r\n\t\telse\r\n\t\t\tsource = CEvent::vSYSTEM_EVENT;\r\n\t}\t\r\n\t\t\r\n\tScript::CStruct *pData = NULL;\r\n\tpParams->GetStructure(CRCD(0x520c0c9c,\"data\"), &pData);\r\n\t\r\n\tbool broadcast = pParams->ContainsFlag(CRCD(0x640e830a,\"broadcast\"));\r\n\t\r\n\tCTracker* p_tracker = CTracker::Instance();\t\r\n\t\r\n\tuint32 type;\r\n\tif (pParams->GetChecksum(CRCD(0x7321a8d6,\"type\"), &type))\r\n\t{\r\n\t\tp_tracker->LogEventScript(pScript->mScriptChecksum);\r\n\t\tp_tracker->LaunchEvent(type, target, source, pData, broadcast);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tScript::CArray* pTypes;\r\n\t\tif (pParams->GetArray(CRCD(0x7321a8d6,\"type\"), &pTypes))\r\n\t\t{\r\n\t\t\tDbg_Assert(pTypes->GetType() == ESYMBOLTYPE_NAME)\r\n\t\t\tunsigned num_events = pTypes->GetSize();\r\n\t\t\tfor (unsigned n = 0; n < num_events; n++)\r\n\t\t\t{\r\n\t\t\t\tp_tracker->LogEventScript(pScript->mScriptChecksum);\r\n\t\t\t\tp_tracker->LaunchEvent(pTypes->GetChecksum(n), target, source, pData, broadcast);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tScript::CStruct* pTypes;\r\n\t\t\tif (pParams->GetStructure(CRCD(0x7321a8d6,\"type\"), &pTypes))\r\n\t\t\t{\r\n\t\t\t\tfor (Script::CComponent* pComp = pTypes->GetNextComponent(); pComp; pComp = pTypes->GetNextComponent(pComp))\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert(pComp->mType == ESYMBOLTYPE_NAME);\r\n\t\t\t\t\tp_tracker->LogEventScript(pScript->mScriptChecksum);\r\n\t\t\t\t\tp_tracker->LaunchEvent(pComp->mChecksum, target, source, pData, broadcast);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"can't launch event without type\"));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\nbool ScriptWaitForEvent(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 type;\r\n\tif (!pParams->GetChecksum(CRCD(0x7321a8d6,\"type\"), &type))\r\n\t\tDbg_MsgAssert(0, (\"no event type specified\"));;\r\n\t\r\n\tCTracker* p_tracker = CTracker::Instance();\t\r\n\tp_tracker->SuspendScriptUntilEvent(pScript, type);\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptObjectExists(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// Although events aren't necessarily tied to the Screen Element system, it is\r\n\t// convenient to enable this function to support complex ID's, for when we\r\n\t// are dealing with Screen Elements\r\n\tFront::CScreenElementManager* p_manager = Front::CScreenElementManager::Instance();\r\n\tuint32 id = p_manager->ResolveComplexID(pParams, CRCD(0x40c698af,\"id\"));\r\n\t\r\n\tCTracker* p_tracker = CTracker::Instance();\r\n\treturn (p_tracker->GetObject(id) != NULL);\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptTerminateObjectsScripts(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tFront::CScreenElementManager* p_manager = Front::CScreenElementManager::Instance();\r\n\tuint32 id = p_manager->ResolveComplexID(pParams, CRCD(0x40c698af,\"id\"));\r\n\t\r\n\tCTracker* p_tracker = CTracker::Instance();\r\n\tCObject *p_object = p_tracker->GetObject(id);\r\n\t\r\n\t\r\n\t// Brad - the use_proper_version flag is a last minute fix at the end of THPS4.\r\n\t// StopScriptsUsingThisObject is broken, but fixing it may break other things.  The\r\n\t// proper version works as it always should have.  It is only used when the user \r\n\t// specifically requests it.\r\n\tbool use_proper = pParams->ContainsFlag( CRCD(0xc89f3564,\"use_proper_version\") );\r\n\t\r\n\t// see if array of script names\r\n\tScript::CArray *p_array;\r\n\tif (pParams->GetArray(CRCD(0x22e168c1,\"scripts\"), &p_array))\r\n\t{\r\n\t\tfor (uint i = 0; i < p_array->GetSize(); i++)\r\n\t\t{\r\n\t\t\tif ( use_proper )\r\n\t\t\t\tScript::StopScriptsUsingThisObject_Proper(p_object, p_array->GetChecksum(i));\r\n\t\t\telse\r\n\t\t\t\tScript::StopScriptsUsingThisObject(p_object, p_array->GetChecksum(i));\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tuint32 script_to_stop = 0; // means 'stop all'\r\n\t\tpParams->GetChecksum(CRCD(0x6166f3ad,\"script_name\"), &script_to_stop);\r\n\t\tif ( use_proper )\r\n\t\t\tScript::StopScriptsUsingThisObject_Proper(p_object, script_to_stop);\r\n\t\telse\r\n\t\t\tScript::StopScriptsUsingThisObject(p_object, script_to_stop);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptAssignAlias(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tFront::CScreenElementManager* p_manager = Front::CScreenElementManager::Instance();\r\n\tuint32 id_of_original = p_manager->ResolveComplexID(pParams, CRCD(0x40c698af,\"id\"));\r\n\t\r\n\tCTracker* p_tracker = CTracker::Instance();\t\r\n\tCObject *p_object_to_alias = p_tracker->GetObject(id_of_original);\r\n\tDbg_Assert(p_object_to_alias);\r\n\t\r\n\tuint32 alias;\r\n\tpParams->GetChecksum(CRCD(0x1e93946b,\"alias\"), &alias, Script::ASSERT);\r\n\r\n\tp_tracker->AddAlias(alias, p_object_to_alias);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptSetObjectProperties(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tFront::CScreenElementManager* p_manager = Front::CScreenElementManager::Instance();\r\n\tuint32 id_of_original = p_manager->ResolveComplexID(pParams, CRCD(0x40c698af,\"id\"));\r\n\t\r\n\tCTracker* p_tracker = CTracker::Instance();\t\r\n\tCObject *p_object = p_tracker->GetObject(id_of_original);\r\n\tDbg_Assert(p_object);\r\n\t\r\n\tp_object->SetProperties(pParams);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptPrintEventLog(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tbool only_print_new = true;\r\n\t\r\n\tint num_to_print = CEventLog::MAX_LOG_ENTRIES;\r\n\tif (pParams->GetInteger(NONAME, &num_to_print))\r\n\t\tonly_print_new = false;\r\n\t\r\n\tCTracker* p_tracker = CTracker::Instance();\t\r\n\tp_tracker->PrintEventLog(only_print_new, num_to_print);\r\n\treturn true;\r\n}\r\n\r\n\r\n#endif\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gel/Prefs/Prefs.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tGameNet.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/12/2001\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNetwork Preferences \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n\r\n#include <gel/prefs/prefs.h>\r\n\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Prefs\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPreferences::Preferences()\r\n{\r\n}\r\n   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPreferences::~Preferences()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 Preferences::WriteToBuffer(uint8 *pBuffer, uint32 BufferSize)\r\n{\r\n\treturn Script::WriteToBuffer(&m_root, pBuffer, BufferSize);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Preferences::ReadFromBuffer(uint8 *pBuffer)\r\n{\r\n\tScript::ReadFromBuffer(&m_root,pBuffer);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* Preferences::GetPreference( uint32 field_id )\r\n{\r\n\tScript::CStruct* p_structure = NULL;\r\n\tm_root.GetStructure( field_id, &p_structure );\r\n\treturn p_structure;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CArray* Preferences::GetPreferenceArray( uint32 field_id )\r\n{\r\n\tScript::CArray* p_array = NULL;\r\n\tm_root.GetArray( field_id, &p_array );\r\n\r\n\treturn p_array;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Preferences::RemoveComponent( uint32 field_id, uint32 sub_field_id )\r\n{\r\n\tScript::CStruct* p_structure = NULL;\r\n\tm_root.GetStructure( field_id, &p_structure );\r\n\r\n\tp_structure->RemoveComponent( sub_field_id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Preferences::SetRoot(Script::CStruct* pStuff)\r\n{\r\n\t\r\n\t// OK if pStuff is NULL, so no need to assert\r\n\t// Probably still an error if it is NULL, but AppendStructure won't crash if it is.\r\n\t\r\n\t// Don't clear out the options structure. New stuff should just override old options\r\n\t//m_root.Clear();\r\n\tm_root.AppendStructure(pStuff); \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char* Preferences::GetPreferenceString( uint32 field_id, uint32 sub_field_id )\r\n{\r\n\tScript::CStruct* p_structure = NULL;\r\n\tm_root.GetStructure( field_id, &p_structure );\r\n\r\n\tconst char* p_string;\r\n\tp_structure->GetText( sub_field_id, &p_string, true );\r\n\treturn p_string;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Preferences::GetPreferenceValue( uint32 field_id, uint32 sub_field_id )\r\n{\r\n\tScript::CStruct* p_structure = NULL;\r\n\tm_root.GetStructure( field_id, &p_structure );\r\n\r\n\tint returnVal;\r\n\tp_structure->GetInteger( sub_field_id, &returnVal, true );\r\n\treturn returnVal;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 Preferences::GetPreferenceChecksum( uint32 field_id, uint32 sub_field_id )\r\n{\r\n\tScript::CStruct* p_structure = NULL;\r\n\tm_root.GetStructure( field_id, &p_structure, true );\r\n\r\n\tuint32 returnVal;\r\n\tp_structure->GetChecksum( sub_field_id, &returnVal, true );\r\n\treturn returnVal;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Preferences::SetPreference( uint32 field_id, Script::CStruct* p_to_append )\r\n{\r\n\t\r\n\t\r\n\tScript::CStruct* p_structure = NULL;\r\n\r\n\t// TODO:  Decide if we can add preferences at runtime,\r\n\t// or whether all the categories already exist at load-time\r\n\tif ( !m_root.GetStructure( field_id, &p_structure ) )\r\n\t{\r\n\t\t// structure doesn't already exist, so it's not a valid preference\r\n\t\tDbg_MsgAssert( 0,( \"Trying to add an invalid preference\" ));\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tp_structure->AppendStructure( p_to_append );\r\n\r\n//\tp_structure->PrintContents();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Preferences::SetPreference( uint32 field_id, Script::CArray* p_to_append )\r\n{\r\n\tScript::CArray* p_array = NULL;\r\n\r\n\t// TODO:  Decide if we can add preferences at runtime,\r\n\t// or whether all the categories already exist at load-time\r\n\tif ( !m_root.GetArray( field_id, &p_array ) )\r\n\t{\r\n\t\t// structure doesn't already exist, so it's not a valid preference\r\n\t\tDbg_MsgAssert( 0,( \"Trying to add an invalid preference\" ));\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tm_root.AddArray( field_id, p_to_append );\r\n\r\n\t//PrintContents();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Preferences::Load( uint32 structure_checksum )\r\n{\r\n\t\r\n\r\n\t// Don't clear out the options structure. New stuff should just override old options\r\n\t//Reset();\r\n\t\r\n\tScript::CStruct* p_structure = Script::GetStructure( structure_checksum, Script::ASSERT );\r\n\r\n\tm_root.AppendStructure( p_structure );\r\n\t\r\n#if 0\r\n\tuint8 testbuffer[2048];\r\n\tm_root.WriteToBuffer(testbuffer, 2048);\r\n\tScript::CStruct* p_new_structure = new Script::CStruct;\r\n\tp_new_structure->Clear();\r\n\tp_new_structure->ReadFromBuffer(testbuffer);\r\n\tp_new_structure->PrintContents();\r\n\tdelete p_new_structure;\r\n#endif\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Preferences::Reset()\r\n{\r\n\tm_root.Clear();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Preferences::UpdateUIElement( uint32 control_id, uint32 field_id, bool mask_password )\r\n{\r\n\t\r\n\t\r\n\tScript::CStruct* pStructure = NULL;\r\n\tm_root.GetStructure( field_id, &pStructure, true );\r\n\r\n\tchar buf[256];\r\n\tconst char* pText = NULL;\r\n\tint value = 0;\r\n\tif ( pStructure->GetText( \"ui_string\", &pText ) )\r\n\t{\r\n\t\tDbg_Assert( strlen( pText ) < 256 );\r\n\t\tstrcpy( buf, pText );\r\n\t}\r\n\telse if ( pStructure->GetInteger( \"value\", &value ) )\r\n\t{\r\n\t\tsprintf( buf, \"%d\", value );\r\n\t}\r\n\telse if ( pStructure->GetText( NONAME, &pText, true ) )\r\n\t{\r\n\t\tDbg_Assert( strlen( pText ) < 256 );\r\n\t\tstrcpy( buf, pText );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert( \"Couldn't find valid parameters in %s\",( Script::FindChecksumName( control_id ) ));\r\n\t}\r\n\r\n\tif ( mask_password )\r\n\t{\r\n\t\t// replace all the letters with stars\r\n\t\tfor ( uint32 i = 0; i < strlen(buf); i++ )\r\n\t\t{\r\n\t\t\tbuf[i] = '*';\r\n\t\t}\r\n\t}\r\n\t\r\n\t//Front::SendString( control_id, buf );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Preferences::PrintContents()\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tScript::PrintContents(&m_root);\r\n#endif\r\n}\r\n\r\n} // namespace Prefs\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Prefs/Prefs.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGel\t\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tPrefs.h\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/12/2001\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGeneric Preferences Class\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_PREFS_H\r\n#define __GEL_PREFS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#include <gel/scripting/script.h>\r\n\r\n#ifndef\t__SCRIPTING_STRUCT_H\r\n#include <gel/scripting/struct.h>\r\n#endif\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Prefs\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  Preferences  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic:\r\n\tPreferences();\r\n\tvirtual\t\t\t\t\t\t~Preferences();\r\n\r\npublic:\r\n\tuint32\t\t\t\t\t\tWriteToBuffer(uint8 *pBuffer, uint32 BufferSize);\r\n\tvoid\t\t\t\t\t\tReadFromBuffer(uint8 *pBuffer);\r\n\r\npublic:\r\n\tbool\t\t\t\t\t\tReset();\r\n\tbool\t\t\t\t\t\tLoad( uint32 structure_checksum );\r\n\tvoid\t\t\t\t\t\tPrintContents();\r\n\tbool\t\t\t\t\t\tUpdateUIElement( uint32 control_id, uint32 field_id, bool mask_password = false );\r\n\r\npublic:\r\n\tScript::CScriptStructure*\tGetPreference( uint32 field_id );\r\n\tbool\t\t\t\t\t\tSetPreference( uint32 field_id, Script::CScriptStructure* p_to_append );\r\n\tbool\t\t\t\t\t\tSetPreference( uint32 field_id, Script::CArray* p_to_append );\r\n\tScript::CArray*\t\t\t\tGetPreferenceArray( uint32 field_id );\r\n\tconst char*\t\t\t\t\tGetPreferenceString( uint32 field_id, uint32 sub_field_id );\r\n\tint\t\t\t\t\t\t\tGetPreferenceValue( uint32 field_id, uint32 sub_field_id );\r\n\tuint32\t\t\t\t\t\tGetPreferenceChecksum( uint32 field_id, uint32 sub_field_id );\r\n\tvoid\t\t\t\t\t\tRemoveComponent( uint32 field_id, uint32 sub_field_id );\r\n\r\n\tScript::CScriptStructure*\tGetRoot() {return &m_root;}\r\n\tvoid\t\t\t\t\t\tSetRoot(Script::CScriptStructure* pStuff);\r\n\t\r\nprivate:\r\n\tScript::CScriptStructure\tm_root;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Prefs\r\n\r\n#endif\t// __GEL_PREFS_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/RefCounted.h",
    "content": "#ifndef __GEL_REFCOUNTED_H\r\n#define __GEL_REFCOUNTED_H\r\n\r\nnamespace Obj\r\n{\r\n\r\ntemplate<class T> class CSmtPtr;\r\n\r\n\r\n\r\n\r\nclass CRefCounted : public Spt::Class\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCRefCounted();\r\n\tvirtual\t\t\t\t\t~CRefCounted();\r\n\r\n\tvoid\t\t\t\t\tAddSmartPointer(CSmtPtr<CRefCounted> *pSmtPtr);\r\n\tvoid\t\t\t\t\tRemoveSmartPointer(CSmtPtr<CRefCounted> *pSmtPtr);\r\n\r\n\tvoid \t\t\t\t\tdebug_validate_smart_pointers(CSmtPtr<CRefCounted> *pPtrToCheckForInclusion);\r\n\r\nprotected:\r\n\r\n\tCSmtPtr<CRefCounted> *\tmp_smart_ptr_list;\r\n};\r\n\r\n\r\n\r\n\r\n}\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Scripting/array.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// array.cpp\t\tKSH 22 Oct 2001\r\n//\r\n// CArray class member functions.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <gel/scripting/array.h>\r\n\r\nDefinePoolableClass(Script::CArray);\r\n\r\nnamespace Script\r\n{\r\n\r\nCArray::CArray()\r\n{\r\n\t// Initialise everything. CArray is not derived from CClass so we don't get\r\n\t// the auro-zeroing.\r\n\tm_type=ESYMBOLTYPE_NONE;\r\n\tmp_array_data=NULL;\r\n\tm_size=0;\r\n}\r\n\r\nCArray::~CArray()\r\n{\r\n\tClear();\r\n}\r\n\r\nbool CArray::operator==( const CArray& v ) const\r\n{\r\n\t// TODO ...\r\n\t#ifdef __NOPT_ASSERT__\r\n\tprintf(\"CArray comparisons are not supported yet ... implement when needed\\n\");\r\n\t#endif\r\n\treturn false;\r\n}\r\n\r\nbool CArray::operator!=( const CArray& v ) const\r\n{\r\n\treturn !(*this==v);\r\n}\r\n\r\n// Deletes the array buffer if it exists, asserting if it contains any non-NULL pointers.\r\n// Sets type to NONE and size to 0.\r\nvoid CArray::Clear()\r\n{\r\n\tif (m_size==1)\r\n\t{\r\n\t\t// Memory optimization:\r\n\t\t// Special case for size 1. In this case, no memory block has been allocated.\r\n\t\t\r\n\t\tif (m_union)\r\n\t\t{\r\n\t\t\t// The element is not zero ...\r\n\t\t\t\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t// Check that no references to things remain in the array.\r\n\t\t\tswitch (m_type)\r\n\t\t\t{\r\n\t\t\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t\t\t\t// No need for the user to have zeroed these.\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase ESYMBOLTYPE_STRING:\r\n\t\t\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t\t\t{\r\n\t\t\t\t\t// The array contains a pointer to something.\r\n\t\t\t\t\t// The CArray cannot delete it itself because this would cause cyclic dependencies.\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"Tried to delete a CArray that still contains non-NULL data: size=%d type='%s'\",m_size,GetTypeName(m_type)));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"Bad CArray::m_type of '%s'\",GetTypeName(m_type)));\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\t\t\r\n\t\t\t#endif\r\n\t\t\r\n\t\t\tm_union=0;\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (mp_array_data)\r\n\t\t{\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t// Check that no references to things remain in the array.\r\n\t\t\tswitch (m_type)\r\n\t\t\t{\r\n\t\t\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t\t\t\t// No need for the user to have zeroed these.\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase ESYMBOLTYPE_STRING:\r\n\t\t\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t\t\t{\r\n\t\t\t\t\t// The array is of pointers, so make sure that the user of CArray has deleted and zeroed these before deleting the array.\r\n\t\t\t\t\t// The CArray cannot delete them itself because this would cause cyclic dependencies.\r\n\t\t\t\t\tfor (uint32 i=0; i<m_size; ++i)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_MsgAssert(mp_array_data[i]==0,(\"Tried to delete a CArray that still contains non-NULL data: size=%d type='%s'\",m_size,GetTypeName(m_type)));\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"Bad CArray::m_type of '%s'\",GetTypeName(m_type)));\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\t\t\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tMem::Free(mp_array_data);\r\n\t\t\tmp_array_data=NULL;\r\n\t\t}\t\r\n\t}\r\n\t\t\r\n\tm_type=ESYMBOLTYPE_NONE;\r\n\tm_size=0;\r\n}\r\n\r\n// Calls Clear, sets the size and type, allocates the buffer if necessary and initialises it to all zeroes.\r\nvoid CArray::SetSizeAndType(int size, ESymbolType type)\r\n{\r\n\tswitch (type)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\tcase ESYMBOLTYPE_NAME:\r\n\t\tcase ESYMBOLTYPE_STRING:\r\n\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase ESYMBOLTYPE_NONE:\r\n\t\t\tDbg_MsgAssert(size==0,(\"Array type of NONE with non-zero size sent to CArray::SetSizeAndType\"));\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Bad type of '%s' sent to CArray::SetSizeAndType\",GetTypeName(type)));\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\t\r\n\tClear();\r\n\tm_type=type;\r\n\tm_size=size;\r\n\r\n\tif (size)\r\n\t{\r\n\t\tif (size==1)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(m_union==0,(\"m_union not zero ?\"));\r\n\t\t\t// Nothing to do. No memory block is allocated for arrays of 1 element, to save memory.\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(mp_array_data==NULL,(\"mp_array_data not NULL ?\"));\r\n\t\t\t\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\t\tmp_array_data=(uint32*)Mem::Malloc(m_size*sizeof(uint32));\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\r\n\t\t\tuint32 *p_long_word=mp_array_data;\r\n\t\t\tfor (uint32 i=0; i<m_size; ++i)\r\n\t\t\t{\r\n\t\t\t\t*p_long_word++=0;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Make all zero size arrays have type none.\r\n\t\t// Seems a reasonable thing to do, and in particular this fixed an assert in WriteToBuffer\r\n\t\t// after CSkaterCareer::WriteIntoStructure had added an empty array of structures. (The Gaps array)\r\n\t\tm_type=ESYMBOLTYPE_NONE;\r\n\t}\t\r\n}\r\n\r\nvoid CArray::Resize(uint32 newSize)\r\n{\r\n\tif (newSize==m_size)\r\n\t{\r\n\t\t// Nothing to do\r\n\t\treturn;\r\n\t}\t\r\n\tDbg_MsgAssert(newSize>m_size,(\"Tried to resize CArray to a smaller size, not supported yet ...\"));\r\n\t// TODO: Make it able to make the CArray smaller, if a need arises. To do, factor out some of the\r\n\t// code from CleanUpArray so that the leftover bit can be cleaned up.\r\n\tDbg_MsgAssert(newSize>1,(\"Resizing arrays to size 1 not supported yet ...\"));\r\n\t// TODO: Support the above if need be. Need to not allocate a new buffer in that case.\r\n\t\r\n\t// Allocate the new buffer.\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\tuint32 *p_new_buffer=(uint32*)Mem::Malloc(newSize*sizeof(uint32));\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\t// Copy the contents of the old buffer into the new.\r\n\tuint32 *p_source=GetArrayPointer();\r\n\t// Note: Does not support resizing zero size arrays because it does not know what the type of the \r\n\t// new array should be.\r\n\tDbg_MsgAssert(p_source,(\"NULL array pointer ?\"));\r\n\tuint32 *p_dest=p_new_buffer;\r\n\tuint32 i;\r\n\tfor (i=0; i<m_size; ++i)\r\n\t{\r\n\t\t*p_dest++=*p_source++;\r\n\t}\r\n\t// Zero the remainder of the new buffer.\r\n\tuint32 remainder=newSize-m_size;\r\n\tfor (i=0; i<remainder; ++i)\r\n\t{\r\n\t\t*p_dest++=0;\r\n\t}\r\n\t\r\n\t// Only free mp_array_data if the old size was bigger than 1. \r\n\t// mp_array_data is not allocated for sizes of 1 as a memory optimization.\r\n\tif (m_size > 1)\r\n\t{\r\n\t\tMem::Free(mp_array_data);\r\n\t}\t\r\n\tmp_array_data=p_new_buffer;\r\n\t\r\n\tm_size=newSize;\r\n\tDbg_MsgAssert(m_size>1,(\"Expected array size to be > 1 ??\")); // Just to be sure\r\n}\r\n\r\nuint32 *CArray::GetArrayPointer() const\r\n{\r\n\tif (m_size==1)\r\n\t{\r\n\t\treturn (uint32*)&m_union;\r\n\t}\r\n\treturn mp_array_data;\r\n}\r\n\r\nvoid CArray::SetString(uint32 index, char *p_string)\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_STRING,(\"Called CArray::SetString when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::SetString, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_string==NULL,(\"mp_string expected to be NULL\"));\r\n\t\tmp_string=p_string;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\tDbg_MsgAssert(mpp_strings[index]==NULL,(\"Non-NULL pointer in mpp_strings[index]\"));\r\n\t\tmpp_strings[index]=p_string;\r\n\t}\t\r\n}\r\n\r\nvoid CArray::SetLocalString(uint32 index, char *p_string)\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_LOCALSTRING,(\"Called CArray::SetLocalString when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::SetLocalString, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_local_string==NULL,(\"mp_local_string expected to be NULL\"));\r\n\t\tmp_local_string=p_string;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\tDbg_MsgAssert(mpp_local_strings[index]==NULL,(\"Non-NULL pointer in mpp_local_strings[index]\"));\r\n\t\tmpp_local_strings[index]=p_string;\r\n\t}\t\r\n}\r\n\r\nvoid CArray::SetInteger(uint32 index, int int_val)\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_INTEGER,(\"Called CArray::SetInteger when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::SetInteger, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\tm_integer=int_val;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\tmp_integers[index]=int_val;\r\n\t}\t\r\n}\r\n\r\nvoid CArray::SetFloat(uint32 index, float float_val)\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_FLOAT,(\"Called CArray::SetFloat when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::SetFloat, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\tm_float=float_val;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\tmp_floats[index]=float_val;\r\n\t}\t\r\n}\r\n\r\nvoid CArray::SetChecksum(uint32 index, uint32 checksum)\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_NAME,(\"Called CArray::SetChecksum when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::SetChecksum, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\tm_checksum=checksum;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\tmp_checksums[index]=checksum;\r\n\t}\t\r\n}\r\n\r\nvoid CArray::SetVector(uint32 index, CVector *p_vector)\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_VECTOR,(\"Called CArray::SetVector when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::SetVector, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_vector==NULL,(\"mp_vector expected to be NULL\"));\r\n\t\tmp_vector=p_vector;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\tDbg_MsgAssert(mpp_vectors[index]==NULL,(\"Non-NULL pointer in mpp_vectors[index]\"));\r\n\t\tmpp_vectors[index]=p_vector;\r\n\t}\t\r\n}\r\n\r\nvoid CArray::SetPair(uint32 index, CPair *p_pair)\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_PAIR,(\"Called CArray::SetPair when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::SetPair, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_pair==NULL,(\"mp_pair expected to be NULL\"));\r\n\t\tmp_pair=p_pair;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\tDbg_MsgAssert(mpp_pairs[index]==NULL,(\"Non-NULL pointer in mpp_pairs[index]\"));\r\n\t\tmpp_pairs[index]=p_pair;\r\n\t}\t\r\n}\r\n\r\nvoid CArray::SetStructure(uint32 index, CStruct *p_struct)\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_STRUCTURE,(\"Called CArray::SetStructure when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::SetStructure, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_structure==NULL,(\"mp_structure expected to be NULL\"));\r\n\t\tmp_structure=p_struct;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\tDbg_MsgAssert(mpp_structures[index]==NULL,(\"Non-NULL pointer in mpp_structures[index]\"));\r\n\t\tmpp_structures[index]=p_struct;\r\n\t}\t\r\n}\r\n\r\nvoid CArray::SetArray(uint32 index, CArray *p_array)\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_ARRAY,(\"Called CArray::SetArray when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::SetArray, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array==NULL,(\"mp_array expected to be NULL\"));\r\n\t\tmp_array=p_array;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\tDbg_MsgAssert(mpp_arrays[index]==NULL,(\"Non-NULL pointer in mpp_arrays[index]\"));\r\n\t\tmpp_arrays[index]=p_array;\r\n\t}\t\r\n}\r\n\r\nchar *CArray::GetString(uint32 index) const\r\n{\r\n\t// The game code views local strings & strings as the same type.\r\n\tif (m_type==ESYMBOLTYPE_LOCALSTRING)\r\n\t{\r\n\t\treturn GetLocalString(index);\r\n\t}\t\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_STRING,(\"Called CArray::GetString when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::GetString, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\treturn mp_string;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\treturn mpp_strings[index];\r\n\t}\t\r\n}\r\n\r\nchar *CArray::GetLocalString(uint32 index) const\r\n{\r\n\tif (m_type==ESYMBOLTYPE_STRING)\r\n\t{\r\n\t\treturn GetString(index);\r\n\t}\t\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_LOCALSTRING,(\"Called CArray::GetLocalString when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::GetLocalString, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\treturn mp_local_string;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\treturn mpp_local_strings[index];\r\n\t}\t\r\n}\r\n\r\nint CArray::GetInteger(uint32 index) const\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_INTEGER,(\"Called CArray::GetInteger when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::GetInteger, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\treturn m_integer;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\treturn mp_integers[index];\r\n\t}\t\r\n}\r\n\r\nfloat CArray::GetFloat(uint32 index) const\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_FLOAT || m_type==ESYMBOLTYPE_INTEGER,(\"Called CArray::GetFloat when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::GetFloat, m_size=%d\",index,m_size));\r\n\t\r\n\tif (m_size==1)\r\n\t{\r\n\t\tif (m_type==ESYMBOLTYPE_FLOAT)\r\n\t\t{\r\n\t\t\treturn m_float;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn m_integer;\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\t\r\n\t\tif (m_type==ESYMBOLTYPE_FLOAT)\r\n\t\t{\r\n\t\t\treturn mp_floats[index];\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn mp_integers[index];\t\r\n\t\t}\t\r\n\t}\t\r\n}\r\n\r\nuint32 CArray::GetChecksum(uint32 index) const\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_NAME,(\"Called CArray::GetChecksum when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::GetChecksum, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\treturn m_checksum;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\treturn mp_checksums[index];\r\n\t}\t\r\n}\r\n\r\nCVector\t*CArray::GetVector(uint32 index) const\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_VECTOR,(\"Called CArray::GetVector when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::GetVector, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\treturn mp_vector;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\treturn mpp_vectors[index];\r\n\t}\t\r\n}\r\n\r\nCPair *CArray::GetPair(uint32 index) const\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_PAIR,(\"Called CArray::GetPair when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::GetPair, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\treturn mp_pair;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\treturn mpp_pairs[index];\r\n\t}\t\r\n}\r\n\r\nCStruct *CArray::GetStructure(uint32 index) const\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_STRUCTURE,(\"Called CArray::GetStructure when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::GetStructure, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\treturn mp_structure;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\treturn mpp_structures[index];\r\n\t}\t\r\n}\r\n\r\nCArray *CArray::GetArray(uint32 index) const\r\n{\r\n\tDbg_MsgAssert(m_type==ESYMBOLTYPE_ARRAY,(\"Called CArray::GetArray when m_type was '%s'\",GetTypeName(m_type)));\r\n\tDbg_MsgAssert(index<m_size,(\"Bad index of %d sent to CArray::GetArray, m_size=%d\",index,m_size));\r\n\tif (m_size==1)\r\n\t{\r\n\t\treturn mp_array;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_array_data,(\"NULL mp_array_data ?\"));\r\n\t\treturn mpp_arrays[index];\r\n\t}\t\r\n}\r\n\r\n} // namespace Script\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/array.h",
    "content": "#ifndef\t__SCRIPTING_ARRAY_H\r\n#define\t__SCRIPTING_ARRAY_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __SYS_MEM_POOLABLE_H\r\n#include <sys/mem/poolable.h>\r\n#endif\r\n\r\n#ifndef\t__SCRIPTING_SYMBOLTYPE_H\r\n#include <gel/scripting/symboltype.h> // For ESymbolType\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\r\nclass CVector;\r\nclass CPair;\r\nclass CStruct;\r\n\r\n#ifdef __PLAT_WN32__\r\nclass CArray\r\n#else\r\nclass CArray : public Mem::CPoolable<CArray>\r\n#endif\r\n{\r\n\t// Pointer to the array data.\r\n\tunion\r\n\t{\r\n\t\t// Generic pointer.\r\n\t\t// Used when calling Mem::Free.\r\n\t\tuint32 *mp_array_data;\r\n\t\t\r\n\t\tint *mp_integers;\r\n\t\tfloat *mp_floats;\r\n\t\tuint32 *mp_checksums;\r\n\t\t\r\n\t\tchar **mpp_strings;\r\n\t\tchar **mpp_local_strings;\r\n\t\tCPair **mpp_pairs;\r\n\t\tCVector **mpp_vectors;\r\n\t\tCStruct **mpp_structures;\r\n\t\tCArray **mpp_arrays;\r\n\t\t\r\n\t\t// In the case of the array containing only 1 element, the element itself is\r\n\t\t// stored here, rather than allocating a block of memory for it.\r\n\t\t// This is a memory optimization.\r\n\t\t// Each memory block uses 16 bytes for the header, and the data is padded to\r\n\t\t// occupy 16 bytes. So in the case of an array of 1 element this saves 32 bytes.\r\n\t\t// There are lots of arrays of 1 element, eg the links arrays in each node of \r\n\t\t// the NodeArray often only contain 1 link.\r\n\t\tint m_integer;\r\n\t\tfloat m_float;\r\n\t\tuint32 m_checksum;\r\n\t\tchar *mp_string;\r\n\t\tchar *mp_local_string;\r\n\t\tCPair *mp_pair;\r\n\t\tCVector *mp_vector;\r\n\t\tCStruct *mp_structure;\r\n\t\tCArray *mp_array;\r\n\t\t// Used to zero the single element.\r\n\t\tuint32 m_union;\r\n\t};\r\n\r\n\t// The type of the things in the array.\r\n\tESymbolType m_type;\r\n\t\r\n\t// The number of items in the array.\r\n\tuint32 m_size;\r\n\r\npublic:\r\n\tCArray();\r\n\t~CArray();\r\n\r\n\t// These cannot be defined because it would cause a cyclic dependency, because\r\n\t// a CArray member function can't create things. So declare them but leave them undefined\r\n\t// so that it will not link if they are attempted to be used.\r\n\tCArray( const CArray& rhs );\r\n\tCArray& operator=( const CArray& rhs );\r\n\t\r\n\t// This is used when interpreting switch statements.\r\n\tbool operator==( const CArray& v ) const;\r\n\tbool operator!=( const CArray& v ) const;\r\n\t\r\n\tvoid Clear();\r\n\tvoid SetSizeAndType(int size, ESymbolType type);\r\n\tvoid Resize(uint32 newSize);\r\n\t\r\n\t// TODO: Remove later. Only included for back compatibility.\r\n\tvoid SetArrayType(int size, ESymbolType type) {SetSizeAndType(size,type);}\r\n\t\r\n\tvoid \t  SetString(uint32 index, char *p_string);\r\n\tvoid SetLocalString(uint32 index, char *p_string);\r\n\tvoid \t SetInteger(uint32 index, int int_val);\r\n\tvoid \t   SetFloat(uint32 index, float float_val);\r\n\tvoid \tSetChecksum(uint32 index, uint32 checksum);\r\n\tvoid \t  SetVector(uint32 index, CVector *p_vector);\r\n\tvoid \t\tSetPair(uint32 index, CPair *p_pair);\r\n\tvoid   SetStructure(uint32 index, CStruct *p_struct);\r\n\tvoid \t   SetArray(uint32 index, CArray *p_array);\r\n\r\n\tchar \t\t\t*GetString(uint32 index) const;\r\n\tchar \t   *GetLocalString(uint32 index) const;\r\n\tint \t\t\tGetInteger(uint32 index) const;\r\n\tfloat \t\t\t  GetFloat(uint32 index) const;\r\n\tuint32 \t\t   GetChecksum(uint32 index) const;\r\n\tCVector\t\t\t*GetVector(uint32 index) const;\r\n\tCPair \t\t\t  *GetPair(uint32 index) const;\r\n\tCStruct \t *GetStructure(uint32 index) const;\r\n\tCArray\t\t\t *GetArray(uint32 index) const;\r\n\r\n\t////////////////////////////////////////////////////////////////////////////////////\r\n\t// TODO: Remove these later, only needed for back compatibility.\r\n\tuint32\t   GetNameChecksum(uint32 index) const {return GetChecksum(index);}\r\n\tint \t\t\t\tGetInt(uint32 index) const {return GetInteger(index);}\r\n\t////////////////////////////////////////////////////////////////////////////////////\r\n\t\r\n\tuint32 \t\tGetSize() const {return m_size;};\r\n\tESymbolType GetType() const {return m_type;};\r\n\t\r\n\t// Needed by CleanUpArray and CopyArray in struct.cpp so that they can\r\n\t// quickly scan through the array data without having to use the access functions\r\n\t// to get each element.\r\n\tuint32 *GetArrayPointer() const;\r\n};\r\n\r\n} // namespace Script\r\n\r\n#endif // #ifndef\t__SCRIPTING_ARRAY_H\r\n"
  },
  {
    "path": "Code/Gel/Scripting/checksum.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// checksum.cpp\t\tKSH 22 Oct 2001\r\n//\r\n// Checksum name lookup stuff for use by asserts.\r\n// Uses up a heck of a lot of memory, but only when __NOPT_ASSERT__ is defined.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#ifdef __PLAT_WN32__\r\n#ifdef __QDEBUG__\r\n#include <../tools/src/monitor/stdafx.h> // Needed for the message box\r\n#endif\r\n#endif\r\n\r\n#include <gel/scripting/checksum.h>\r\n#include <string.h>\t// For stricmp\r\n#include <core/crc.h>\r\n#include <sys/config/config.h>\r\n#include <gel/scripting/debugger.h>\r\n\r\n// These are only referenced in the Playstation version.\r\n// They are set in NGPS.lk\r\n#ifdef __PLAT_NGPS__\r\nextern char _script_debugger_start[];\r\nextern char _script_start[];\r\nextern char _script_end[];\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\r\n// The number of bits is set to be high to speed up AddChecksumName, so that\r\n// LoadQB does not take ages to execute.\r\n#define CHECKSUM_LOOKUP_HASH_BITS 16\r\n// This probably does not need to be so big, but we've got lots of memory in debug so it's OK.\r\n#define CHECKSUM_ENTRIES_PER_SLOT 10\r\n\r\n// There are (1<<CHECKSUM_LOOKUP_HASH_BITS) * CHECKSUM_ENTRIES_PER_SLOT of these,\r\n// which uses about 5.2Meg.\r\nstruct SChecksumName\r\n{\r\n\tuint32 mChecksum;\r\n\tconst char *mpName;\r\n};\r\n\r\n// The space available to hold all the checksum names. The names are stored contiguously\r\n// with no wasted space in between. They stay in memory forever.\r\n#define CHECKSUM_NAME_SPACE 5000000\r\n\r\nstatic SChecksumName *sp_checksum_name_hash_table=NULL;\r\nstatic char *sp_checksum_names=NULL;\r\nstatic char *sp_end_of_checksum_names=NULL;\r\n\r\nvoid AllocateChecksumNameLookupTables()\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tDbg_MsgAssert(sp_checksum_name_hash_table==NULL,(\"sp_checksum_name_hash_table not NULL ?\"));\t\t\t\t  \r\n\tDbg_MsgAssert(sp_checksum_names==NULL,(\"sp_checksum_names not NULL ?\"));\t\t\t\t  \r\n\tDbg_MsgAssert(sp_end_of_checksum_names==NULL,(\"sp_end_of_checksum_names not NULL ?\"));\t\t\t\t  \r\n\t\r\n\t#ifdef __PLAT_NGPS__\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\t// Use the chunk of memory that was set aside for script debug stuff in NGPS.lk\r\n\tuint32 script_debug_mem_size=(uint32)(_script_end-_script_start);\r\n\r\n\t// Check there is enough space.\r\n\tuint32 hash_table_size=(1<<CHECKSUM_LOOKUP_HASH_BITS) * CHECKSUM_ENTRIES_PER_SLOT * sizeof(SChecksumName);\t\r\n\tDbg_MsgAssert(script_debug_mem_size>=hash_table_size+CHECKSUM_NAME_SPACE,(\r\n\t\t\t\t  \"Chunk of debug memory reserved for script stuff is not big enough.\\nRequired=%d, got=%d\",\r\n\t\t\t\t  hash_table_size+CHECKSUM_NAME_SPACE, script_debug_mem_size));\r\n\t#endif\t\t\t\t  \r\n\t\t\t\t  \r\n\tsp_checksum_name_hash_table=(SChecksumName*)_script_start;\r\n\tsp_checksum_names=(char*)(sp_checksum_name_hash_table+((1<<CHECKSUM_LOOKUP_HASH_BITS) * CHECKSUM_ENTRIES_PER_SLOT));\r\n\tsp_end_of_checksum_names=sp_checksum_names;\r\n\r\n\t// Set up pointers to the locations of sp_checksum_names and sp_end_of_checksum_names\r\n\t// so that later the script debugger can find the list of names using the target manager API \r\n\t// and register their checksums too.\r\n\tDbg_MsgAssert((uint32)_script_debugger_start==Dbg::SCRIPT_DEBUGGER_MEMORY_START,(\"Need to update SCRIPT_DEBUGGER_MEMORY_START in debugger.h to match the location of the script_debugger group in ngps.lk\"));\r\n\tDbg::SChecksumNameInfo *p_checksum_name_info=(Dbg::SChecksumNameInfo*)_script_debugger_start;\r\n\tp_checksum_name_info->mppStart=&sp_checksum_names;\r\n\tp_checksum_name_info->mppEnd=&sp_end_of_checksum_names;\r\n\t\r\n\t#else\r\n\r\n\t// Just allocate the arrays off the heap.\r\n\t\r\n\t// Checksum-name lookup stuff.\r\n\tsp_checksum_name_hash_table=(SChecksumName*)Mem::Malloc((1<<CHECKSUM_LOOKUP_HASH_BITS) * CHECKSUM_ENTRIES_PER_SLOT * sizeof(SChecksumName));\r\n\tsp_checksum_names=(char*)Mem::Malloc(CHECKSUM_NAME_SPACE);\r\n\tsp_end_of_checksum_names=sp_checksum_names;\r\n\t\r\n\t#endif // __PLAT_NGPS__\r\n\t\r\n\t// Initialise the hash table.\r\n\tfor (int i=0; i<(1<<CHECKSUM_LOOKUP_HASH_BITS) * CHECKSUM_ENTRIES_PER_SLOT; ++i)\r\n\t{\r\n\t\tsp_checksum_name_hash_table[i].mChecksum=0;\r\n\t\tsp_checksum_name_hash_table[i].mpName=NULL;\r\n\t}\r\n\t// Initialise the pile of strings.\r\n\t*sp_checksum_names=0;\r\n}\r\n\r\nvoid DeallocateChecksumNameLookupTables()\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tDbg_MsgAssert(sp_checksum_name_hash_table,(\"NULL sp_checksum_name_hash_table ?\"));\t\t\t\t  \r\n\tDbg_MsgAssert(sp_checksum_names,(\"NULL sp_checksum_names ?\"));\t\t\t\t  \r\n\t\r\n\t#ifdef __PLAT_NGPS__\r\n\t// Nothing to delete on PS2 because the arrays were not dynamically allocated.\r\n\t#else\r\n\tMem::Free(sp_checksum_name_hash_table);\r\n\tMem::Free(sp_checksum_names);\r\n\t#endif\r\n\t\r\n\tsp_checksum_name_hash_table=NULL;\r\n\tsp_checksum_names=NULL;\r\n\tsp_end_of_checksum_names=NULL;\r\n}\t\r\n\r\n// Used by the script debugger code to send the set of checksum names to the debugger program\r\n// running on the PC.\r\nvoid GetChecksumNamesBuffer(char **pp_start, char **pp_end)\r\n{\r\n\tDbg_MsgAssert(pp_start && pp_end,(\"pp_start and pp_end must be non-NULL\"));\r\n\t\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\t*pp_start=NULL;\r\n\t\t*pp_end=NULL;\r\n\t\treturn;\r\n\t}\r\n\r\n\t*pp_start=sp_checksum_names;\r\n\t*pp_end=sp_end_of_checksum_names;\r\n}\t\r\n\r\n//uint32 sNumChecksums=0;\r\nvoid AddChecksumName(uint32 checksum, const char *p_name)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tDbg_MsgAssert(checksum,(\"Zero checksum sent to AddChecksumName\"));\r\n\tDbg_MsgAssert(p_name,(\"NULL p_name sent to AddChecksumName\"));\r\n\tDbg_MsgAssert(sp_checksum_name_hash_table,(\"NULL sp_checksum_name_hash_table\"));\r\n\t\r\n\tSChecksumName *p_first=&sp_checksum_name_hash_table[(checksum&((1<<CHECKSUM_LOOKUP_HASH_BITS)-1))*CHECKSUM_ENTRIES_PER_SLOT];\r\n\tint c=0;\r\n\twhile (p_first->mpName)\r\n\t{\r\n\t\t// Already a name here.\r\n\t\t// See if it has the same checksum.\r\n\t\tif (p_first->mChecksum==checksum)\r\n\t\t{\r\n\t\t\t// It does! Check whether it is the same name.\r\n\t\t\tif (stricmp(p_first->mpName,p_name)==0)\r\n\t\t\t{\r\n\t\t\t\t// Phew, the name matches. No need to do anything.\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Oh bugger, a checksum clash.\r\n\t\t\t\t#ifdef __PLAT_WN32__\r\n\t\t\t\t#ifdef __QDEBUG__\r\n\t\t\t\tchar p_foo[1024];\r\n\t\t\t\tsprintf(p_foo,\"Checksum clash between %s and %s, both have checksum 0x%08x\",p_name,p_first->mpName,checksum);\r\n\t\t\t\tMessageBox(NULL,p_foo,\"Warning\",MB_OK);\r\n\t\t\t\t#endif\r\n\t\t\t\t// Carry on anyway, won't cause a crash.\r\n\t\t\t\t#else\t\t\t\t\r\n\t\t\t\tDbg_MsgAssert(0,(\"Checksum clash between %s and %s, both have checksum 0x%08x\",p_name,p_first->mpName,checksum));\r\n\t\t\t\t#endif\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Not the same checksum. Onto the next entry.\r\n\t\t++c;\r\n\t\tDbg_MsgAssert(c<CHECKSUM_ENTRIES_PER_SLOT,(\"Need to increase CHECKSUM_ENTRIES_PER_SLOT in checksum.cpp\"));\r\n\t\t++p_first;\r\n\t}\r\n\t\r\n\t//++sNumChecksums;\r\n\t//printf(\"sNumChecksums=%d\\n\",sNumChecksums);\r\n\t\r\n\tp_first->mChecksum=checksum;\r\n\tp_first->mpName=sp_end_of_checksum_names;\r\n\t\r\n\tint space_left=CHECKSUM_NAME_SPACE-(sp_end_of_checksum_names-sp_checksum_names);\r\n\twhile (*p_name)\r\n\t{\r\n\t\tDbg_MsgAssert(space_left>0,(\"Need to increase CHECKSUM_NAME_SPACE in checksum.cpp\"));\r\n\t\t*sp_end_of_checksum_names++=*p_name++;\r\n\t\t--space_left;\r\n\t}\t\r\n\tDbg_MsgAssert(space_left>0,(\"Need to increase CHECKSUM_NAME_SPACE in checksum.cpp\"));\r\n\t*sp_end_of_checksum_names++=0;\r\n}\r\n\r\nstatic char sp_unknown_checksum_buf[100];\r\n\r\n// Returns NULL if not found.\r\n// This version is not safe to use in a printf because it may return NULL, but can be handy for\r\n// when the calling code needs to do something special if the name is not found.\r\nconst char *FindChecksumNameNULL(uint32 checksum)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\t\r\n\tDbg_MsgAssert(sp_checksum_name_hash_table,(\"NULL sp_checksum_name_hash_table\"));\r\n\tSChecksumName *p_first=&sp_checksum_name_hash_table[(checksum&((1<<CHECKSUM_LOOKUP_HASH_BITS)-1))*CHECKSUM_ENTRIES_PER_SLOT];\r\n\tint c=CHECKSUM_ENTRIES_PER_SLOT;\r\n\twhile (p_first->mpName)\r\n\t{\r\n\t\tif (p_first->mChecksum==checksum)\r\n\t\t{\r\n\t\t\treturn p_first->mpName;\r\n\t\t}\t\r\n\t\t--c;\r\n\t\tif (c==0)\r\n\t\t{\r\n\t\t\t// Run out of slots.\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t++p_first;\r\n\t}\r\n\t\r\n\treturn NULL;\t\t\r\n}\r\n\r\n// Returns \"Unknown\" if not found.\r\n// This version is always safe to use in a printf.\r\nconst char *FindChecksumName(uint32 checksum)\r\n{\r\n\tconst char *p_name=FindChecksumNameNULL(checksum);\r\n\tif (p_name)\t\r\n\t{\r\n\t\treturn p_name;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t#ifdef __PLAT_WN32__\r\n\t\t// The monitor.exe application requires that the unknown checksum be\r\n\t\t// displayed like this.\r\n\t\tsprintf(sp_unknown_checksum_buf,\"0x%08x\",checksum);\t\r\n\t\t#else\r\n\t\tsprintf(sp_unknown_checksum_buf,\"Unknown(0x%08x)\",checksum);\t\r\n\t\t#endif\r\n\t\treturn sp_unknown_checksum_buf;\t\t\r\n\t}\t\r\n}\r\n\r\n\r\n} // namespace Script\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/checksum.h",
    "content": "#ifndef\t__SCRIPTING_CHECKSUM_H\r\n#define\t__SCRIPTING_CHECKSUM_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\r\nvoid AllocateChecksumNameLookupTables();\r\nvoid DeallocateChecksumNameLookupTables();\r\nvoid GetChecksumNamesBuffer(char **pp_start, char **pp_end);\r\nvoid AddChecksumName(uint32 checksum, const char *pName);\r\nconst char *FindChecksumNameNULL(uint32 checksum);\r\nconst char *FindChecksumName(uint32 checksum);\r\n\r\n} // namespace Script\r\n\r\n#endif // #ifndef\t__SCRIPTING_CHECKSUM_H\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/component.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// component.cpp\t\tKSH 17 Oct 2001\r\n//\r\n// Notes:\r\n// When a CComponent is deleted, it does not delete any CStruct, CArray or string that\r\n// it may contain a pointer to. This is so that a cyclic dependency between component and struct is avoided.\r\n// It is up to the parent CStruct to clean these up before deleting the CComponent.\r\n// \r\n// This cpp just declares the constructor, and the pool statics.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <gel/scripting/component.h>\r\n\r\n#ifndef\t__SCRIPTING_SCRIPTDEFS_H\r\n#include <gel/scripting/scriptdefs.h>\r\n#endif\r\n\r\nDefinePoolableClass(Script::CComponent);\r\n\r\nnamespace Script\r\n{\r\n\r\n// Used in parkgen.cpp, but only in a debug message, so make it just return 0 for now.\r\nuint32 GetNumUsedComponents()\r\n{\r\n\treturn 0;\r\n}\r\n\r\nCComponent::CComponent()\r\n{\r\n\t// Initialise everything. CComponent is not derived from CClass so we don't get\r\n\t// the auro-zeroing.\r\n\tmType=ESYMBOLTYPE_NONE;\r\n\tmNameChecksum=NO_NAME;\r\n\tmScriptSize=0;\r\n\tmUnion=0;\r\n\tmpNext=NULL;\r\n}\r\n\r\n// The destructor does not delete anything to avoid cyclic dependencies, so just assert\r\n// if it look like there could be a non-NULL pointer left.\r\n#ifdef __NOPT_ASSERT__\r\nCComponent::~CComponent()\r\n{\r\n\tDbg_MsgAssert(mUnion==0,(\"CComponent still contains data, possibly an undeleted pointer\"));\r\n\tDbg_MsgAssert(mScriptSize==0,(\"CComponent::mScriptSize not zero in destructor ?\"));\r\n}\r\n#endif\r\n\r\n// Note: No destructor.\r\n// When a CComponent is deleted, it does not delete any CStruct, CArray or string that\r\n// it may contain a pointer to.\r\n// This is so that a cyclic dependency between component and struct is avoided, because to\r\n// delete a CStruct from here would require the inclusion of struct.h.\r\n\r\n// It is up to the parent CStruct to delete anything in the component before deleting the CComponent.\r\n\r\n} // namespace Script\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/component.h",
    "content": "#ifndef\t__SCRIPTING_COMPONENT_H\r\n#define\t__SCRIPTING_COMPONENT_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __SYS_MEM_POOLABLE_H\r\n#include <sys/mem/poolable.h>\r\n#endif\r\n\r\n#ifndef\t__SCRIPTING_SYMBOLTYPE_H\r\n#include <gel/scripting/symboltype.h> // For ESymbolType\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\r\nclass CPair;\r\nclass CVector;\r\nclass CStruct;\r\nclass CArray;\r\n\r\n// Note: This is not derived from CClass to avoid the extra memory overhead due to the virtual destructor.\r\n// There will be loads of CComponents, in THPS3 there were 58000.\r\n#ifdef __PLAT_WN32__\r\nclass CComponent\r\n#else\r\nclass CComponent : public Mem::CPoolable<CComponent>\r\n#endif\r\n{\r\npublic:\t\r\n\tCComponent();\r\n\t#ifdef __NOPT_ASSERT__\r\n\t~CComponent();\r\n\t#endif\r\n\r\n\t// These cannot be defined because it would cause a cyclic dependency, because\r\n\t// a CComponent member function can't create things. So declare them but leave them undefined\r\n\t// so that it will not link if they are attempted to be used.\r\n\tCComponent( const CComponent& rhs );\r\n\tCComponent& operator=( const CComponent& rhs );\r\n\r\n\t// These are used when interpreting switch statements and expressions\r\n\tbool operator==( const CComponent& v ) const;\r\n\tbool operator!=( const CComponent& v ) const;\r\n\tbool operator<( const CComponent& v ) const;\r\n\tbool operator>( const CComponent& v ) const;\r\n\tbool operator<=( const CComponent& v ) const;\r\n\tbool operator>=( const CComponent& v ) const;\r\n\r\n\t// Making this use just one byte keeps the size of CComponent to 16 bytes.\r\n\t// There are 64000 CComponents so they need to be as small as possible.\r\n\t// It seems that the compact pool class has an overhead of one byte, so if the\r\n\t// size of this class is 3 mod 4 it will be making optimal use of space.\r\n\t// Hence we have 2 bytes spare if needed later.\r\n\tuint8 mType;\r\n\t\r\n\t// Well, this has used up those 2 spare bytes mentioned above.\r\n\t// This is the size of the mpScript buffer in the case of mType being ESYMBOLTYPE_QSCRIPT\r\n\t// The size is needed when copying a component, so that the new component knows how big a\r\n\t// buffer to allocate. In theory the size could be calculated, but that would introduce\r\n\t// a circular dependency because struct.cpp would have to include parse.h in order to call\r\n\t// SkipOverScript.\r\n\tuint16 mScriptSize;\r\n\t\r\n\tuint32 mNameChecksum;\t\r\n\tunion\r\n\t{\r\n\t\tint mIntegerValue;\r\n\t\tfloat mFloatValue;\r\n\t\tchar *mpString;\r\n\t\tchar *mpLocalString;\r\n\t\tCPair *mpPair;\r\n\t\tCVector *mpVector;\r\n\t\tCStruct *mpStructure;\r\n\t\tCArray *mpArray;\r\n\t\tuint8 *mpScript;\r\n\t\tuint32 mChecksum;\r\n\t\tuint32 mUnion; // For when all the above need to be zeroed \r\n\t};\r\n\t\r\n\tCComponent *mpNext;\r\n};\r\n\t\r\nvoid AllocateComponentPool(uint32 maxComponents);\r\nvoid DeallocateComponentPool();\r\n\t\r\nuint32 GetNumUsedComponents();\r\n\t\r\n} // namespace Script\r\n\r\n#endif // #ifndef\t__SCRIPTING_COMPONENT_H\r\n"
  },
  {
    "path": "Code/Gel/Scripting/debugger.cpp",
    "content": "#include \"gel/scripting/debugger.h\"\r\n#include \"sk/gamenet/scriptdebugger.h\"\r\n#include \"gel/mainloop.h\"\r\n#include \"gel/scripting\\symboltable.h\"\r\n#include \"gel/scripting\\checksum.h\"\r\n#include \"gel/scripting\\script.h\"\r\n#include \"gel/scripting\\symboltype.h\"\r\n#include \"gel/scripting\\array.h\"\r\n#include \"gel/scripting\\struct.h\"\r\n#include \"gel/scripting\\utils.h\"\r\n#include \"gel/scripting\\component.h\"\r\n#include \"gel/scripting\\scriptcache.h\"\r\n#include \"gel/object/compositeobjectmanager.h\"\r\n#include \"gel/components/modelcomponent.h\"\r\n#include \"gfx/nxviewman.h\"\r\n#include \"sk/modules/skate/skate.h\"\r\n#include \"sk/objects/skater.h\"\r\n#include \"sk/objects/skatercam.h\"\r\n#include \"gel/event.h\"\r\n\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\r\n\r\nnamespace Dbg\r\n{\r\n\r\nuint32 gpDebugInfoBuffer[SCRIPT_DEBUGGER_BUFFER_SIZE/4];\r\n\r\nstatic Script::CScript *s_find_cscript_given_id(uint32 id)\r\n{\r\n\tScript::CScript *p_script=Script::GetNextScript(NULL);\r\n\twhile (p_script)\r\n\t{\r\n\t\tif (p_script->GetUniqueId()==id)\r\n\t\t{\r\n\t\t\treturn p_script;\r\n\t\t}\t\r\n\t\tp_script=Script::GetNextScript(p_script);\r\n\t}\t\r\n\treturn NULL;\r\n}\r\n\r\nstatic Script::CScript *s_find_cscript_given_name(uint32 name)\r\n{\r\n\tScript::CScript *p_script=Script::GetNextScript(NULL);\r\n\twhile (p_script)\r\n\t{\r\n\t\tif (p_script->RefersToScript(name))\r\n\t\t{\r\n\t\t\treturn p_script;\r\n\t\t}\t\r\n\t\tp_script=Script::GetNextScript(p_script);\r\n\t}\t\r\n\treturn NULL;\r\n}\r\n\r\nstatic Obj::CCompositeObject *s_find_nearest_object(int screen_x, int screen_y, float search_radius)\r\n{\r\n\tNx::CViewport *p_viewport = Nx::CViewportManager::sGetActiveViewport();\r\n\tDbg_MsgAssert(p_viewport, (\"Can't find an active viewport\"));\r\n\t\r\n\tLst::Search<Obj::CObject> sh;\r\n\tObj::CObject *p_ob = (Obj::CObject*) sh.FirstItem( Obj::CCompositeObjectManager::Instance()->GetRefObjectList() );\r\n\tObj::CCompositeObject *p_nearest_ob=NULL;\r\n\tfloat min_d=1000000.0f;\r\n\twhile (p_ob)\r\n\t{\r\n\t\tfloat x,y;\r\n\t\tNx::ZBufferValue z;\r\n\t\tp_viewport->TransformToScreenCoord(((Obj::CCompositeObject*)p_ob)->GetPos(),x,y,z);\r\n\t\t\r\n\t\tfloat dx=x-screen_x;\r\n\t\tfloat dy=y-screen_y;\r\n\t\tfloat d=sqrtf(dx*dx+dy*dy);\r\n\t\tif (d<search_radius && d<min_d)\r\n\t\t{\r\n\t\t\tmin_d=d;\r\n\t\t\tp_nearest_ob=(Obj::CCompositeObject*)p_ob;\r\n\t\t}\t\r\n\t\t\r\n\t\tp_ob = sh.NextItem();\r\n\t}\r\n\t\r\n\treturn p_nearest_ob;\r\n}\r\n\r\nstatic Nx::ERenderMode s_change_render_mode(Obj::CCompositeObject *p_ob, Nx::ERenderMode new_render_mode)\r\n{\r\n\tNx::ERenderMode old_render_mode=Nx::vNONE;\r\n\t\r\n\tif (p_ob)\r\n\t{\r\n\t\tObj::CModelComponent *p_model=(Obj::CModelComponent*)p_ob->GetComponent(CRCD(0x286a8d26,\"Model\"));\r\n\t\tif (p_model)\r\n\t\t{\r\n\t\t\tNx::CModel *p_cmodel=p_model->GetModel();\r\n\t\t\tif (p_cmodel)\r\n\t\t\t{\r\n\t\t\t\told_render_mode=p_cmodel->GetRenderMode();\r\n\t\t\t\tp_cmodel->SetRenderMode(new_render_mode);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn old_render_mode;\r\n}\r\n\r\nDefineSingletonClass( CScriptDebugger, \"Script debugger module\" );\r\n\r\nCScriptDebugger::CScriptDebugger()\r\n{\r\n\t// Note: Split message id's start at 1 because 0 is used to indicate no message.\r\n\tm_split_message_id=1;\r\n\t\r\n\tm_state=SCRIPT_DEBUGGER_STATE_IDLE;\r\n\tmp_checksum_names_current_pos=NULL;\r\n\tmp_checksum_names_end=NULL;\r\n\tmp_server=NULL;\r\n\tmp_logic_task=NULL;\r\n\t\r\n\tm_num_watched_scripts=0;\r\n\t\r\n\tm_mouse_on_screen=false;\r\n\tm_got_valid_mouse_position=false;\r\n\tm_mouse_x=0;\r\n\tm_mouse_y=0;\r\n\tmp_currently_selected_object=NULL;\r\n\tm_original_object_render_mode=Nx::vNONE;\r\n\tm_left_button_down=false;\t\r\n\tm_right_button_down=false;\t\r\n\r\n\tm_state_when_left_pressed.mTime=0;\r\n\tm_state_when_left_pressed.mMouseX=0;\r\n\tm_state_when_left_pressed.mMouseY=0;\r\n\tm_state_when_left_pressed.mCamPhi=0.0f;\r\n\tm_state_when_left_pressed.mCamTheta=0.0f;\r\n\t\r\n\tm_state_when_right_pressed.mCamRadius=0.0f;\r\n\tm_state_when_right_pressed.mMouseX=0;\r\n\tm_state_when_right_pressed.mMouseY=0;\r\n\t\r\n\tmp_viewed_object=NULL;\r\n\tsetup_default_camera_viewing_position();\r\n\t\r\n\tm_in_object_single_step_mode=false;\r\n\tm_single_step_object_id=0;\r\n\t\r\n\tm_object_update_total_bytes_sent=0;\r\n\tm_frames_since_last_object_update=0;\r\n}\r\n\r\nCScriptDebugger::~CScriptDebugger()\r\n{\r\n\tif (mp_server)\r\n\t{\r\n\t\tdelete mp_server;\r\n\t}\t\r\n\tif (mp_logic_task)\r\n\t{\r\n\t\tdelete mp_logic_task;\r\n\t}\t\r\n}\r\n\r\nvoid CScriptDebugger::v_start_cb ( void )\r\n{\r\n// Stick it all on the network heap, as it's kind of network releated\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\r\n\tNet::Manager * p_net_man = Net::Manager::Instance();\r\n\tmp_server = p_net_man->CreateNewAppServer( 0, \"Script debugger\", 4, GameNet::vSCRIPT_DEBUG_PORT,\r\n\t\t\t\t\t\t\t\t\t\t\t\tinet_addr( p_net_man->GetLocalIP()), Net::App::mACCEPT_FOREIGN_CONN | Net::App::mDYNAMIC_RESEND );\r\n\t\r\n\t// Note: If the default task priority is used then the 'view object' functionality does not work.\r\n\t// s_logic_code needs to be called after all the normal camera code has executed, so that the camera\r\n\t// position can be overridden. Hence a priority lower than the default needs to be used. \r\n\tmp_logic_task = new Tsk::Task< CScriptDebugger > ( CScriptDebugger::s_logic_code, *this, Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_SCRIPT_DEBUGGER );\r\n\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\tmlp_manager->AddLogicTask( *mp_logic_task );\r\n\t\r\n\tmp_server->m_Dispatcher.AddHandler(\tNet::MSG_ID_CONNECTION_REQ, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_connection_request, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );\r\n\t\t\t\t\t\t\t\t\t\t\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_WATCH_THIS, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_watch_this, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_WATCH_SCRIPT, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_watch_script, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\t\t\t\t\t\t\t\t\t\t\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_STOP, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_stop, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_STEP_INTO, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_step_into, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_STEP_OVER, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_step_over, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_GO, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_go, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_CLEAR_SCRIPT_WATCHES, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_clear_script_watches, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_REFRESH, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_refresh, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\t\t\t\t\t\t\t\t\t\t\r\n\tmp_server->m_Dispatcher.AddHandler(\tNet::MSG_ID_DISCONN_REQ, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_disconnect, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_SEND_CSCRIPT_LIST, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_send_cscript_list, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_SEND_WATCH_LIST, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_send_watch_list, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_STOP_WATCHING_THIS_INDEX, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_stop_watching_this_index, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_STOP_WATCHING_THIS_CSCRIPT, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_stop_watching_this_cscript, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_SEND_COMPOSITE_OBJECT_INFO, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_send_composite_object_info, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_MOUSE_POSITION, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_mouse_position, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_MOUSE_ON_SCREEN, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_mouse_on_screen, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_MOUSE_OFF_SCREEN, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_mouse_off_screen, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_MOUSE_LEFT_BUTTON_DOWN, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_mouse_left_button_down, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_MOUSE_LEFT_BUTTON_UP, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_mouse_left_button_up, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_MOUSE_RIGHT_BUTTON_DOWN, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_mouse_right_button_down, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_MOUSE_RIGHT_BUTTON_UP, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_mouse_right_button_up, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\r\n\t\t\t\t\t\t\t\t\t\t\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_SEND_COMPOSITE_OBJECT_LIST, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_send_composite_object_list, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\t\t\t\t\t\t\t\t\t\t\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_SET_OBJECT_UPDATE_MODE, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_set_object_update_mode, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_VIEW_OBJECT, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_view_object, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\r\n\tmp_server->m_Dispatcher.AddHandler(\tGameNet::vMSG_ID_DBG_SEND_SCRIPT_GLOBAL_INFO, \r\n\t\t\t\t\t\t\t\t\t\ts_handle_send_script_global_info, \r\n\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this);\r\n\t\t\t\t\t\t\t\t\t\t\r\n\tm_paused = false;\r\n\t\r\n\tNet::Manager* net_man = Net::Manager::Instance();\r\n\tnet_man->SetBandwidth( 200000 );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n}\r\n\r\nvoid CScriptDebugger::v_stop_cb ( void )\r\n{\r\n\tmp_logic_task->Remove();\r\n\tmp_server->m_Dispatcher.Deinit();\r\n}\r\n\r\nvoid CScriptDebugger::transmit_cscript_list()\r\n{\r\n\tScript::CStruct *p_list=new Script::CStruct;\r\n\r\n\t//int total_num_return_addresses=0;\r\n\t//int total_scripts_using_big_buffer=0;\r\n\tint num_scripts=0;\r\n\tScript::CScript *p_script=Script::GetNextScript(NULL);\r\n\twhile (p_script)\r\n\t{\r\n\t\t//total_num_return_addresses+=p_script->GetNumReturnAddresses();\r\n\t\t//if (p_script->UsingBigLoopBuffer())\r\n\t\t//{\r\n\t\t//\t++total_scripts_using_big_buffer;\r\n\t\t//}\r\n\t\t\t\r\n\t\tp_script=Script::GetNextScript(p_script);\r\n\t\t++num_scripts;\r\n\t}\t\r\n\tp_list->AddInteger(CRCD(0x62f3d8fa,\"NumScripts\"),num_scripts);\r\n\t//p_list->AddInteger(CRCD(0xed4b5c6e,\"NumScriptsUsingBigBuffer\"),total_scripts_using_big_buffer);\r\n\t//p_list->AddFloat(CRCD(0x4f73b852,\"AverageNumReturnAddresses\"),((float)total_num_return_addresses)/num_scripts);\r\n\r\n\r\n\t// Add the script cache info.\t\r\n\tScript::CScriptCache *p_script_cache=Script::CScriptCache::Instance();\r\n\tDbg_MsgAssert(p_script_cache,(\"NULL p_script_cache\"));\r\n\tp_script_cache->GetDebugInfo(p_list);\r\n\r\n\tp_script=Script::GetNextScript(NULL);\r\n\twhile (p_script)\r\n\t{\r\n\t\tScript::CStruct *p_script_info=new Script::CStruct;\r\n\t\t\r\n\t\tp_script_info->AddChecksum(\"m_unique_id\",p_script->GetUniqueId());\r\n\t\t\r\n\t\t//p_script_info->AddInteger(CRCD(0x46b0d38c,\"NumReturnAddresses\"),p_script->GetNumReturnAddresses());\r\n\t\t//p_script_info->AddInteger(CRCD(0x477f712b,\"UsingBigCallstackBuffer\"),p_script->UsingBigCallstackBuffer());\r\n\t\t\r\n\t\tObj::CObject *p_object=p_script->mpObject;\r\n\t\tif (p_object)\r\n\t\t{\r\n\t\t\tp_script_info->AddChecksum(\"Object\",p_object->GetID());\r\n\t\t}\t\r\n\t\t\r\n\t\tif (p_script->mIsSpawned)\r\n\t\t{\r\n\t\t\tp_script_info->AddChecksum(NONAME,CRCD(0xf697fda7,\"Spawned\"));\r\n\t\t}\r\n\t\t\r\n\t\t#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\t\t\tif (p_script->GetEventHandlerTable())\r\n\t\t\t{\r\n\t\t\t\tp_script->GetEventHandlerTable()->GetDebugInfo(p_script_info);\r\n\t\t\t}\r\n\t\t#endif\r\n\r\n\t\t\r\n\t\t// Convert to microseconds by dividing by 150\r\n\t\tp_script_info->AddInteger(\"CPUTime\",p_script->m_last_time/150);\r\n\r\n\t\t// Create a new structure component for p_script_info, and name it using the name of the script.\r\n\t\t// Then add this component to the p_list structure using AppendComponentPointer.\r\n\t\t// The reason it is done this way rather than simply using AddStructurePointer is that\r\n\t\t// AddStructurePointer will remove any previously added components of the same name.\r\n\t\t// There may be many instances of the same script running, so we want those to all appear.\r\n\t\t// AppendComponentPointer will add the new component to the structure and will leave any\r\n\t\t// existing components untouched. (it was written specially for this function)\r\n\t\tScript::CComponent *p_comp=new Script::CComponent;\r\n\t\tp_comp->mType=ESYMBOLTYPE_STRUCTURE;\r\n\t\tp_comp->mpStructure=p_script_info;\r\n\t\t\r\n\t\tuint32 base_script=p_script->GetBaseScript();\r\n\t\tif (base_script)\r\n\t\t{\r\n\t\t\tp_comp->mNameChecksum=base_script;\r\n\t\t}\r\n\t\telse\t\r\n\t\t{\r\n\t\t\t// Occasionally the base_script might be zero (sometimes when scrolling\r\n\t\t\t// through certain menus)\r\n\t\t\t// Name it using the unique id of the script.\r\n\t\t\tp_comp->mNameChecksum=p_script->GetUniqueId();\r\n\t\t}\r\n\r\n\t\tp_list->AppendComponentPointer(p_comp);\r\n\t\t\t\t\r\n\t\tp_script=Script::GetNextScript(p_script);\r\n\t}\t\r\n\r\n\tint structure_bytes_written=Script::WriteToBuffer(p_list,(uint8*)gpDebugInfoBuffer,SCRIPT_DEBUGGER_BUFFER_SIZE);\r\n\tdelete p_list;\r\n\t\r\n\tNet::MsgDesc msg;\r\n\tmsg.m_Data = gpDebugInfoBuffer;\r\n\tmsg.m_Length = structure_bytes_written;\r\n\tmsg.m_Id = GameNet::vMSG_ID_DBG_CSCRIPT_LIST;\r\n\tStreamMessage(&msg);\r\n}\r\n\r\nvoid CScriptDebugger::transmit_watch_list()\r\n{\r\n\tSWatchInfo *p_watch_info=(SWatchInfo*)gpDebugInfoBuffer;\r\n\tDbg_MsgAssert(m_num_watched_scripts*sizeof(SWatchInfo)<=SCRIPT_DEBUGGER_BUFFER_SIZE,(\"gpDebugInfoBuffer overflow\"));\r\n\r\n\tfor (int i=0; i<m_num_watched_scripts; ++i)\r\n\t{\r\n\t\tp_watch_info->mScriptName=mp_watched_scripts[i].mChecksum;\r\n\t\tp_watch_info->mStopImmediately=mp_watched_scripts[i].mStopScriptImmediately;\r\n\t\t++p_watch_info;\r\n\t}\t\t\r\n\r\n\tNet::MsgDesc msg;\r\n\tmsg.m_Data = gpDebugInfoBuffer;\r\n\tmsg.m_Length = m_num_watched_scripts*sizeof(SWatchInfo);\r\n\tmsg.m_Id = GameNet::vMSG_ID_DBG_WATCH_LIST;\r\n\tStreamMessage(&msg);\r\n}\r\n\r\nvoid CScriptDebugger::transmit_composite_object_list()\r\n{\r\n\tScript::CStruct *p_list=new Script::CStruct;\r\n\t\r\n\tLst::Search<Obj::CObject> sh;\r\n\tObj::CObject *p_ob = (Obj::CObject*) sh.FirstItem( Obj::CCompositeObjectManager::Instance()->GetRefObjectList() );\r\n\twhile (p_ob)\r\n\t{\r\n\t\tScript::CStruct *p_object_info=new Script::CStruct;\r\n\t\tp_object_info->AddInteger(\"CPUTime\",((Obj::CCompositeObject*)p_ob)->GetUpdateTime());\r\n\t\tif (p_ob->GetID())\r\n\t\t{\r\n\t\t\tp_list->AddStructurePointer(p_ob->GetID(),p_object_info);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_list->AddStructurePointer(\"Skater\",p_object_info);\r\n\t\t}\t\r\n\t\t\r\n\t\tp_ob = sh.NextItem();\r\n\t}\r\n\t\r\n\tint structure_bytes_written=Script::WriteToBuffer(p_list,(uint8*)gpDebugInfoBuffer,SCRIPT_DEBUGGER_BUFFER_SIZE);\r\n\tdelete p_list;\r\n\t\r\n\tNet::MsgDesc msg;\r\n\tmsg.m_Data = gpDebugInfoBuffer;\r\n\tmsg.m_Length = structure_bytes_written;\r\n\tmsg.m_Id = GameNet::vMSG_ID_DBG_COMPOSITE_OBJECT_LIST;\r\n\tDbg::CScriptDebugger::Instance()->StreamMessage(&msg);\r\n}\r\n\r\nvoid CScriptDebugger::transmit_compression_lookup_table()\r\n{   \r\n\tScript::CArray *p_table=Script::GetArray(0x35115a20/*WriteToBuffer_CompressionLookupTable_8*/);\r\n\tDbg_MsgAssert(p_table->GetType()==ESYMBOLTYPE_NAME,(\"Bad array type\"));\r\n\tDbg_MsgAssert(p_table->GetSize()<=256,(\"Bad array size\"));\r\n\t\r\n    Net::MsgDesc msg;\r\n\tmsg.m_Data = p_table->GetArrayPointer();\r\n\tmsg.m_Length = p_table->GetSize()*4;\r\n\tmsg.m_Id = GameNet::vMSG_ID_DBG_COMPRESSION_LOOKUP_TABLE;\r\n\tStreamMessage(&msg);\r\n\r\n\tp_table=Script::GetArray(0x25231f42/*WriteToBuffer_CompressionLookupTable_16*/);\r\n\tDbg_MsgAssert(p_table->GetSize()==0,(\"Need to update transmit_compression_lookup_table to handle WriteToBuffer_CompressionLookupTable_16, since it is no longer empty ...\"));\r\n}\t\r\n\r\nSWatchedScript *CScriptDebugger::find_watched_script(uint32 checksum)\r\n{\r\n\tfor (int i=0; i<m_num_watched_scripts; ++i)\r\n\t{\r\n\t\tif (mp_watched_scripts[i].mChecksum==checksum)\r\n\t\t{\r\n\t\t\treturn &mp_watched_scripts[i];\r\n\t\t}\r\n\t}\t\t\r\n\treturn NULL;\r\n}\r\n\r\nvoid CScriptDebugger::add_to_watched_scripts(uint32 checksum, bool stopScriptImmediately)\r\n{\r\n\tScript::CScript *p_script=s_find_cscript_given_name(checksum);\r\n\tif (p_script)\r\n\t{\r\n        p_script->WatchInDebugger(stopScriptImmediately);\r\n\t}\r\n\t\t\r\n\tSWatchedScript *p_watched_script=find_watched_script(checksum);\r\n\tif (p_watched_script)\r\n\t{\r\n\t\tp_watched_script->mStopScriptImmediately=stopScriptImmediately;\r\n\t\treturn;\r\n\t}\r\n\r\n\tDbg_MsgAssert(m_num_watched_scripts<MAX_WATCHED_SCRIPTS,(\"Too many watched scripts\"));\r\n\tmp_watched_scripts[m_num_watched_scripts].mStopScriptImmediately=stopScriptImmediately;\r\n\tmp_watched_scripts[m_num_watched_scripts].mChecksum=checksum;\r\n\t++m_num_watched_scripts;\r\n\t\r\n\ttransmit_watch_list();\r\n}\r\n\r\nvoid CScriptDebugger::refresh()\r\n{\r\n\ttransmit_compression_lookup_table();\r\n\ttransmit_watch_list();\r\n\ttransmit_cscript_list();\r\n\ttransmit_composite_object_list();\r\n\t\r\n\tScript::CScript *p_script=Script::GetNextScript(NULL);\r\n\twhile (p_script)\r\n\t{\r\n\t\tif (p_script->BeingWatchedInDebugger())\r\n\t\t{\r\n\t\t\t// DEFINITELY_TRANSMIT means override the optimization whereby a packet is not\r\n\t\t\t// sent if it's checksum matches that of the last sent.\r\n\t\t\tp_script->TransmitInfoToDebugger(Script::DEFINITELY_TRANSMIT);\r\n\t\t}\t\r\n\t\tp_script=Script::GetNextScript(p_script);\r\n\t}\t\r\n}\r\n\r\nvoid CScriptDebugger::stop_watching_script(int index)\r\n{\r\n\tif (index<0 || index >= m_num_watched_scripts)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\r\n\tif (m_num_watched_scripts)\r\n\t{\r\n\t\tfor (int i=index; i<m_num_watched_scripts-1; ++i)\r\n\t\t{\r\n\t\t\tmp_watched_scripts[i]=mp_watched_scripts[i+1];\r\n\t\t}\r\n\t\t--m_num_watched_scripts;\r\n\t}\r\n\t\r\n\t// Refresh the window in the debugger by transmitting the new watch list.\r\n\ttransmit_watch_list();\r\n}\r\n\r\nint CScriptDebugger::send_composite_object_info(Obj::CCompositeObject* p_obj)\r\n{\r\n\tint num_bytes_sent=0;\r\n\t\r\n\tif (p_obj)\r\n\t{\r\n\t\tScript::CStruct *p_info=new Script::CStruct;\r\n\t\tp_obj->GetDebugInfo(p_info);\r\n\t\t\r\n\t\tDbg_MsgAssert(SCRIPT_DEBUGGER_BUFFER_SIZE>4,(\"Oops\"));\r\n\t\tgpDebugInfoBuffer[0]=p_obj->GetID();\r\n\t\tuint8 *p_buf=(uint8*)(gpDebugInfoBuffer+1);\r\n\t\tint structure_bytes_written=Script::WriteToBuffer(p_info,p_buf,SCRIPT_DEBUGGER_BUFFER_SIZE-4);\r\n\t\tdelete p_info;\r\n\t\t\r\n\t\tNet::MsgDesc msg;\r\n\t\tmsg.m_Data = gpDebugInfoBuffer;\r\n\t\tmsg.m_Length = 4+structure_bytes_written;\r\n\t\tmsg.m_Id = GameNet::vMSG_ID_DBG_COMPOSITE_OBJECT_INFO;\r\n\r\n\t\tStreamMessage(&msg);\r\n\t\tnum_bytes_sent=msg.m_Length;\r\n\t\t\r\n\t\tprintf(\"Sent composite object info for '%s'\\n\",Script::FindChecksumName(p_obj->GetID()));\r\n\t}\t\r\n\treturn num_bytes_sent;\r\n}\r\n\r\nvoid CScriptDebugger::send_composite_object_info(uint32 id)\r\n{\r\n\tsend_composite_object_info((Obj::CCompositeObject*)Obj::CCompositeObjectManager::Instance()->GetObjectByID( id ));\r\n}\r\n\r\nvoid CScriptDebugger::set_object_update_mode(SObjectUpdateMode *pObjectUpdateMode)\r\n{\r\n\t// Make sure the game is not paused, which it will be if in single step mode.\r\n\tDbg::CScriptDebugger::Instance()->ScriptDebuggerUnpause();\r\n\t\r\n\tswitch (pObjectUpdateMode->mMode)\r\n\t{\r\n\t\tcase Dbg::EVERY_FRAME:\r\n\t\t{\r\n\t\t\tObj::CCompositeObject* p_obj=(Obj::CCompositeObject*)Obj::CCompositeObjectManager::Instance()->GetObjectByID(pObjectUpdateMode->mObjectId);\r\n\t\t\tif (p_obj)\r\n\t\t\t{\r\n\t\t\t\tp_obj->SetDebuggerEveryFrameFlag(pObjectUpdateMode->mOn);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase Dbg::SINGLE_STEP:\r\n\t\t\tif (pObjectUpdateMode->mOn)\r\n\t\t\t{\r\n\t\t\t\t// Set the single step mode flag to true, which means that the next time in to\r\n\t\t\t\t// s_logic_code it will send a packet of info for this object, then pause the game.\r\n\t\t\t\t// When paused, it will still respond to incoming messages, so the next time\r\n\t\t\t\t// the user clicks the 'single step' button it will call this function, hence\r\n\t\t\t\t// unpausing the game for one frame until it gets in to s_logic_code again, where\r\n\t\t\t\t// it will send another packet of info, then pause again etc.\r\n\t\t\t\tm_in_object_single_step_mode=true;\r\n\t\t\t\tm_single_step_object_id=pObjectUpdateMode->mObjectId;\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_in_object_single_step_mode=false;\r\n\t\t\t\tm_single_step_object_id=0;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\t\r\n\t\t\tbreak;\r\n\t}\t\r\n}\r\n\r\nvoid CScriptDebugger::view_object(SViewObject *pViewObject)\r\n{\r\n\tObj::CCompositeObject *p_obj=NULL;\r\n\t\r\n\tif (pViewObject->mDoViewObject)\r\n\t{\r\n\t\tp_obj=(Obj::CCompositeObject*)Obj::CCompositeObjectManager::Instance()->GetObjectByID(pViewObject->mObjectId);\r\n\t}\r\n\tmp_viewed_object=p_obj;\r\n\t\r\n\tsetup_default_camera_viewing_position();\r\n}\r\n\r\nvoid CScriptDebugger::send_any_single_step_object_info()\r\n{\r\n\tif (m_in_object_single_step_mode)\r\n\t{\r\n\t\tObj::CCompositeObject* p_obj=(Obj::CCompositeObject*)Obj::CCompositeObjectManager::Instance()->GetObjectByID(m_single_step_object_id);\r\n\t\tif (p_obj)\r\n\t\t{\r\n\t\t\t// Send a packet of info, then pause the game until the user clicks the 'single step'\r\n\t\t\t// button again, which will cause CScriptDebugger::set_object_update_mode to be called.\r\n\t\t\tsend_composite_object_info(p_obj);\r\n\t\t\tDbg::CScriptDebugger::Instance()->ScriptDebuggerPause();\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\nvoid CScriptDebugger::send_script_global_info(uint32 id)\r\n{\r\n\t// Look up the symbol to see if it is the name of some global.\r\n\tScript::CSymbolTableEntry *p_entry=Script::LookUpSymbol(id);\r\n\tif (p_entry)\r\n\t{\r\n\t\tint message_size=0;\t\t\r\n\t\tuint8 *p_buf=(uint8*)gpDebugInfoBuffer;\r\n\r\n\t\t// Write in the name, type, and source file name.\t\t\r\n\t\tDbg_MsgAssert(SCRIPT_DEBUGGER_BUFFER_SIZE > 8,(\"SCRIPT_DEBUGGER_BUFFER_SIZE is like way too small dude\"));\r\n\t\t*(uint32*)p_buf=id;\r\n\t\tp_buf+=4;\r\n\t\t*(uint32*)p_buf=p_entry->mType;\r\n\t\tp_buf+=4;\r\n\t\tmessage_size+=8;\r\n\t\t\r\n\t\tconst char *p_source_filename=Script::FindChecksumName(p_entry->mSourceFileNameChecksum);\r\n\t\tint len=strlen(p_source_filename)+1;\r\n\t\tDbg_MsgAssert(SCRIPT_DEBUGGER_BUFFER_SIZE-message_size > len,(\"SCRIPT_DEBUGGER_BUFFER_SIZE is too small\"));\r\n\t\t\r\n\t\tstrcpy((char*)p_buf,p_source_filename);\r\n\t\tp_buf+=len;\r\n\t\tmessage_size+=len;\r\n\r\n\t\t// For pure data types, write in a structure containing the value.\r\n\t\tswitch (p_entry->mType)\r\n\t\t{\r\n\t\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\tcase ESYMBOLTYPE_STRING:\r\n\t\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t\t{\r\n\t\t\t\t// Copy the name and value into a structure for sending to the\r\n\t\t\t\t// script debugger for display.\r\n\t\t\t\tScript::CStruct *p_struct=new Script::CStruct;\r\n\t\t\r\n\t\t\t\t// Create a structure component and fill it in with the value of the global.\r\n\t\t\t\tScript::CComponent *p_source=new Script::CComponent;\r\n\t\t\t\tp_source->mType=p_entry->mType;\r\n\t\t\t\tp_source->mUnion=p_entry->mUnion; // What mUnion represents depends on mType\r\n\t\t\t\t\r\n\t\t\t\t// Now use CopyComponent to make a copy. This needs to be done because mUnion may\r\n\t\t\t\t// be a pointer to some entity, and we don't want that to be deleted when p_struct\r\n\t\t\t\t// gets deleted.\r\n\t\t\t\tScript::CComponent *p_new=new Script::CComponent;\r\n\t\t\t\tScript::CopyComponent(p_new,p_source);\r\n\t\t\t\t// Delete p_source now that we've got a copy.\r\n\t\t\t\tp_source->mUnion=0;\r\n\t\t\t\tdelete p_source;\r\n\t\t\t\t\r\n\t\t\t\t// Name the component using id so that it appears as expected in the structure.\r\n\t\t\t\t// Ie, if Foo is a global with value 6, then it will appear as Foo=6 in the structure.\r\n\t\t\t\tp_new->mNameChecksum=id;\r\n\t\t\t\tp_struct->AddComponent(p_new);\r\n\t\t\r\n\t\t\t\t\r\n\t\t\t\tint structure_bytes_written=Script::WriteToBuffer(p_struct,p_buf,SCRIPT_DEBUGGER_BUFFER_SIZE-message_size);\r\n\t\t\t\tdelete p_struct;\r\n\t\t\t\t\r\n\t\t\t\tp_buf+=structure_bytes_written;\r\n\t\t\t\tmessage_size+=structure_bytes_written;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tdefault:\t\r\n\t\t\t\tbreak;\r\n\t\t}\t\t\t\r\n\t\t\r\n\t\t// Send the info to the debugger.\r\n\t\tNet::MsgDesc msg;\r\n\t\tmsg.m_Data = gpDebugInfoBuffer;\r\n\t\tmsg.m_Length = message_size;\r\n\t\tmsg.m_Id = GameNet::vMSG_ID_DBG_SCRIPT_GLOBAL_INFO;\r\n\t\tStreamMessage(&msg);\r\n\t}\t\r\n}\r\n\r\nvoid CScriptDebugger::stop_debugging()\r\n{\r\n\tm_num_watched_scripts=0;\r\n\t\r\n\tScript::CScript *p_script=Script::GetNextScript(NULL);\r\n\twhile (p_script)\r\n\t{\r\n\t\tp_script->StopWatchingInDebugger();\r\n\t\tp_script=Script::GetNextScript(p_script);\r\n\t}\t\r\n\r\n\tstop_all_every_frame_object_updates();\r\n\t\r\n\tScriptDebuggerUnpause();\r\n\t\r\n\tswitch_off_mouse_cursor();\r\n}\r\n\r\nint\tCScriptDebugger::s_handle_connection_request( Net::MsgHandlerContext* context )\r\n{   \r\n\tDbg_Assert( context );\r\n\r\n\tDbg_Printf( \"Got Join Request from ip %x port %d\\n\", context->m_Conn->GetIP(), context->m_Conn->GetPort());\r\n\r\n\t// We'll just accept local clients\r\n\tif( context->m_Conn->IsRemote())\r\n\t{\r\n\t\t// Rule out redundancy\r\n\t\tif( context->m_PacketFlags & Net::mHANDLE_FOREIGN )\r\n\t\t{\r\n\t\t\tNet::Conn* conn;\r\n\r\n\t\t\t// Are we currently accepting players?\r\n\t\t\tif( context->m_App->AcceptsForeignConnections() == false )\r\n\t\t\t{\r\n\t\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Create a more permanent connection\r\n\t\t\tconn = context->m_App->NewConnection( context->m_Conn->GetIP(), context->m_Conn->GetPort());\r\n\t\t\tconn->SetBandwidthType( Net::Conn::vNARROWBAND );//Net::Conn::vLAN );\r\n\t\t\tconn->SetSendInterval( 0 );\r\n\t\t\t\r\n\t\t\tcontext->m_Conn->Invalidate();\r\n\t\t\tcontext->m_Conn = conn;\t// the rest of the chain will use this new, valid connection\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t// Make sure that the debugger is updated with the latest info.\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->refresh();\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n// This function is kind of redundant at the moment, since there is now a seperate s_handle_watch_script\r\n// and there will probably soon be a s_handle_watch_object.\r\nint\tCScriptDebugger::s_handle_watch_this( Net::MsgHandlerContext* context )\r\n{   \r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\t\r\n\tDbg_MsgAssert(context->m_MsgLength==4,(\"Unexpected length of %d for vMSG_ID_DBG_WATCH_THIS\", context->m_MsgLength));\r\n\t\r\n\tuint32 checksum=*(uint32*)context->m_Msg;\r\n\r\n\t// Determine what kind of thing the checksum is referring to ...\r\n\t\r\n\tScript::CSymbolTableEntry *p_sym=Script::LookUpSymbol(checksum);\r\n\tif (p_sym)\r\n\t{\r\n\t\tswitch (p_sym->mType)\r\n\t\t{\r\n\t\t\tcase ESYMBOLTYPE_QSCRIPT:\r\n\t\t\t{\r\n\t\t\t\t// false means do not stop the script immediately when detected.\r\n\t\t\t\tp_this->add_to_watched_scripts(checksum,false);\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint\tCScriptDebugger::s_handle_watch_script( Net::MsgHandlerContext* context )\r\n{   \r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\t\r\n\tDbg_MsgAssert(context->m_MsgLength==12,(\"Unexpected length of %d for vMSG_ID_DBG_WATCH_SCRIPT\", context->m_MsgLength));\r\n\t\r\n\tuint32 *p_data=(uint32*)context->m_Msg;   \t\t\t\r\n\tbool stop_script_immediately=p_data[0];\r\n\t\r\n\tuint32 type_of_checksum=p_data[1];\r\n\tuint32 checksum=p_data[2];\r\n\r\n\tif (type_of_checksum==CHECKSUM_IS_SCRIPT_ID)\r\n\t{\r\n\t\tScript::CScript *p_script=s_find_cscript_given_id(checksum);  \r\n\t\tif (p_script)\r\n\t\t{\r\n\t\t\tp_script->WatchInDebugger(stop_script_immediately);\r\n\t\t\t// Make sure the debugger at least gets some info, otherwise it won't get\r\n\t\t\t// any if the scripts update function is not called.\r\n\t\t\tp_script->TransmitInfoToDebugger();\r\n\t\t}\t\r\n\t\treturn Net::HANDLER_CONTINUE;\r\n\t}\r\n\r\n\tp_this->add_to_watched_scripts(checksum,stop_script_immediately);\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\t\r\n}\r\n\r\nint\tCScriptDebugger::s_handle_stop( Net::MsgHandlerContext* context )\r\n{   \r\n\tDbg_MsgAssert(context->m_MsgLength==4,(\"Unexpected length of %d for vMSG_ID_DBG_STOP\", context->m_MsgLength));\r\n\tuint32 id=*(uint32*)context->m_Msg;\r\n\t\r\n\tScript::CScript *p_script=s_find_cscript_given_id(id);\r\n\tif (!p_script)\r\n\t{\r\n\t\treturn Net::HANDLER_CONTINUE;\r\n\t}\r\n\r\n\tp_script->DebugStop();\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint\tCScriptDebugger::s_handle_step_into( Net::MsgHandlerContext* context )\r\n{   \r\n\tDbg_MsgAssert(context->m_MsgLength==4,(\"Unexpected length of %d for vMSG_ID_DBG_STOP\", context->m_MsgLength));\r\n\tuint32 id=*(uint32*)context->m_Msg;\r\n\r\n\tScript::CScript *p_script=s_find_cscript_given_id(id);\r\n\tif (!p_script)\r\n\t{\r\n\t\treturn Net::HANDLER_CONTINUE;\r\n\t}\r\n\t\r\n\tp_script->DebugStepInto();\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint\tCScriptDebugger::s_handle_step_over( Net::MsgHandlerContext* context )\r\n{   \r\n\tDbg_MsgAssert(context->m_MsgLength==4,(\"Unexpected length of %d for vMSG_ID_DBG_STOP\", context->m_MsgLength));\r\n\tuint32 id=*(uint32*)context->m_Msg;\r\n\r\n\tScript::CScript *p_script=s_find_cscript_given_id(id);\r\n\tif (!p_script)\r\n\t{\r\n\t\treturn Net::HANDLER_CONTINUE;\r\n\t}\r\n\t\r\n\tp_script->DebugStepOver();\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint\tCScriptDebugger::s_handle_go( Net::MsgHandlerContext* context )\r\n{   \r\n\tDbg_MsgAssert(context->m_MsgLength==4,(\"Unexpected length of %d for vMSG_ID_DBG_STOP\", context->m_MsgLength));\r\n\tuint32 id=*(uint32*)context->m_Msg;\r\n\r\n\tScript::CScript *p_script=s_find_cscript_given_id(id);\r\n\tif (!p_script)\r\n\t{\r\n\t\treturn Net::HANDLER_CONTINUE;\r\n\t}\r\n\t\r\n\tp_script->DebugGo();\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n// This gets called whenever the \"Clear script watches\" menu option in the script debugger\r\n// is chosen.\r\nint\tCScriptDebugger::s_handle_clear_script_watches( Net::MsgHandlerContext* context )\r\n{   \r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\t\r\n\t// Clear the list of scripts being watched.\r\n\tp_this->m_num_watched_scripts=0;\r\n\t// Make sure the list gets updated in the debugger.\r\n\tp_this->transmit_watch_list();\r\n\t\r\n\t// Then run through all existing scripts making sure none of them are transmitting any more.\r\n\tScript::CScript *p_script=Script::GetNextScript(NULL);\r\n\twhile (p_script)\r\n\t{\r\n\t\tp_script->StopWatchingInDebugger();\r\n\t\t\r\n\t\t// Also force any window open in the debugger for this script to close, by\r\n\t\t// sending a script-died message.\r\n\t\tuint32 id=p_script->GetUniqueId();\r\n\t\tNet::MsgDesc msg;\r\n\t\tmsg.m_Data = &id;;\r\n\t\tmsg.m_Length = 4;\r\n\t\tmsg.m_Id = GameNet::vMSG_ID_DBG_SCRIPT_DIED;\r\n\t\tp_this->StreamMessage(&msg);\r\n\t\t\r\n\t\tp_script=Script::GetNextScript(p_script);\r\n\t}\t\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint\tCScriptDebugger::s_handle_refresh( Net::MsgHandlerContext* context )\r\n{   \r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->refresh();\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint\tCScriptDebugger::s_handle_disconnect( Net::MsgHandlerContext* context )\r\n{   \r\n\tDbg_Printf(\"Got disconnect message from monitor.exe\\n\");\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->stop_debugging();\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_send_cscript_list( Net::MsgHandlerContext* context )\r\n{\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->transmit_cscript_list();\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_send_watch_list( Net::MsgHandlerContext* context )\r\n{\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->transmit_watch_list();\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_send_composite_object_list( Net::MsgHandlerContext* context )\r\n{\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->transmit_composite_object_list();\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_set_object_update_mode( Net::MsgHandlerContext* context )\r\n{\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->set_object_update_mode((SObjectUpdateMode*)context->m_Msg);\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_view_object( Net::MsgHandlerContext* context )\r\n{\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->view_object((SViewObject*)context->m_Msg);\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_stop_watching_this_index( Net::MsgHandlerContext* context )\r\n{\r\n\tuint32 index=*(uint32*)context->m_Msg;\r\n\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->stop_watching_script(index);\r\n\t\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_stop_watching_this_cscript( Net::MsgHandlerContext* context )\r\n{\r\n\tuint32 id=*(uint32*)context->m_Msg;\r\n\t\r\n\tScript::CScript *p_script=s_find_cscript_given_id(id);\r\n\tif (p_script)\r\n\t{\r\n\t\tp_script->StopWatchingInDebugger();\r\n\t}\t\r\n\t\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_send_composite_object_info( Net::MsgHandlerContext* context )\r\n{\r\n\tuint32 id=*(uint32*)context->m_Msg;\r\n\t\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->send_composite_object_info(id);\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_send_script_global_info( Net::MsgHandlerContext* context )\r\n{\r\n\tuint32 id=*(uint32*)context->m_Msg;\r\n\t\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->send_script_global_info(id);\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_mouse_position( Net::MsgHandlerContext* context )\r\n{\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\t\r\n\t// Ignore the message if the m_mouse_on_screen flag is not set, because that would\r\n\t// mean it was a late message, received after the mouse had gone off screen.\r\n\tif (p_this->m_mouse_on_screen)\r\n\t{\r\n\t\tsint16 *p_coords=(sint16*)context->m_Msg;\r\n\t\tint x=p_coords[0];\r\n\t\tint y=p_coords[1];\r\n\t\r\n\t\tp_this->m_mouse_x=x;\t\r\n\t\tp_this->m_mouse_y=y;\t\r\n\t\tp_this->m_got_valid_mouse_position=true;\r\n\t\t\r\n\t\tScript::CStruct *p_params=new Script::CStruct;\r\n\t\tp_params->AddInteger(\"x\",x);\r\n\t\tp_params->AddInteger(\"y\",y);\r\n\t\tScript::RunScript(\"UpdateDebuggerMousePosition\",p_params);\r\n\t\tdelete p_params;\r\n\t}\t\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_mouse_off_screen( Net::MsgHandlerContext* context )\r\n{\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->switch_off_mouse_cursor();\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_mouse_left_button_down( Net::MsgHandlerContext* context )\r\n{\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->left_button_down();\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_mouse_left_button_up( Net::MsgHandlerContext* context )\r\n{\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->left_button_up();\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_mouse_right_button_down( Net::MsgHandlerContext* context )\r\n{\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->right_button_down();\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_mouse_right_button_up( Net::MsgHandlerContext* context )\r\n{\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->m_right_button_down=false;\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nint CScriptDebugger::s_handle_mouse_on_screen( Net::MsgHandlerContext* context )\r\n{\r\n\t// Set the m_mouse_on_screen flag so that mouse position messages are not ignored.\r\n\tCScriptDebugger *p_this=(CScriptDebugger*)context->m_Data;\r\n\tp_this->m_mouse_on_screen=true;\r\n\t\r\n\t// Initialise these flags to false so that the buttons have to be released first.\r\n\tp_this->m_left_button_down=false;\r\n\tp_this->m_right_button_down=false;\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\nvoid CScriptDebugger::EnqueueMessage(Net::MsgDesc *p_message)\r\n{\r\n\tif (mp_server)\r\n\t{\r\n\t\tmp_server->EnqueueMessage(Net::HANDLE_ID_BROADCAST,p_message);\r\n\t}\t\r\n}\r\n\r\nvoid CScriptDebugger::StreamMessage(Net::MsgDesc *p_message)\r\n{\r\n\tif (mp_server)\r\n\t{\r\n\t\tmp_server->StreamMessage(\tNet::HANDLE_ID_BROADCAST,\r\n\t\t\t\t\t\t\t\t\tp_message->m_Id,\r\n\t\t\t\t\t\t\t\t\tp_message->m_Length,\r\n\t\t\t\t\t\t\t\t\tp_message->m_Data,\r\n\t\t\t\t\t\t\t\t\t\"\",\r\n\t\t\t\t\t\t\t\t\tGameNet::vSCRIPT_DEBUG_GROUP );\r\n\t}\t\t\t\t\t\t\t\t\t\r\n}\r\n\r\nvoid CScriptDebugger::send_sub_packet(Net::MsgDesc *p_message, uint32 size, char *p_source,\r\n\t\t\t\t\t\t\t\t\t  int packetIndex, int totalNumPackets)\r\n{\r\n\tif (!mp_server)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tDbg_MsgAssert(size <= SPLIT_MESSAGE_MAX_SIZE,(\"Sub packet size too big\"));\r\n\t\r\n\tstatic char sp_packet_data[sizeof(SSplitMessageHeader)+SPLIT_MESSAGE_MAX_SIZE];\r\n\tSSplitMessageHeader *p_header=(SSplitMessageHeader*)sp_packet_data;\r\n\t\t\r\n\tp_header->mOriginalMessageId=p_message->m_Id;\r\n\tp_header->mOriginalMessageSize=p_message->m_Length;\r\n\tp_header->mThisMessageId=m_split_message_id;\r\n\tp_header->mThisMessageIndex=packetIndex;\r\n\tp_header->mThisMessageSize=size;\r\n\tp_header->mTotalNumMessages=totalNumPackets;\r\n\t\r\n\t//printf(\"Id=%x, index=%d, total packets=%d\\n\",p_header->mThisMessageId,\r\n\t//p_header->mThisMessageIndex,\r\n\t//p_header->mTotalNumMessages);\r\n\t\r\n\tmemcpy(p_header+1,p_source,size);\r\n\t\r\n\tNet::MsgDesc msg;\r\n\tmsg.m_Id = GameNet::vMSG_ID_DBG_PACKET;\r\n\tmsg.m_Data = sp_packet_data;\r\n\tmsg.m_Length = sizeof(SSplitMessageHeader)+size;\r\n\t\r\n\tprintf(\"Transmitting sub packet, size=%d\\n\",size);\r\n\t\r\n\tmp_server->EnqueueMessage(Net::HANDLE_ID_BROADCAST,&msg);\r\n}\r\n\r\n// This can be used in place of EnqueueMessage or StreamMessage when the message\r\n// data is large, ie bigger than the maximum packet size that EnqueueMessage will allow,\r\n// which is about 1300 bytes.\r\n// The advantage of EnqueueMessage is that the messages arrive very quickly at the other end.\r\n// The disadvantage is that it asserts for packet sizes > 1300 bytes or so.\r\n// The advantage of StreamMessage is that it does allow for large packets.\r\n// The disadvantage is that the packets can take a long time to arrive, since it guarantees that they\r\n// arrive in the correct order, a feature that the script debugger does not always need.\r\n// This means that composite object info cannot be sent every frame, because the packets start piling\r\n// up at the PS2 side and it eventually asserts.\r\n\r\n// SplitAndEnqueueMessage tries to get the advantages of both Enqueue and Stream.\r\n// It allows for large packets because it splits them up into smaller packets and sends each of them\r\n// using EnqueueMessage.\r\nvoid CScriptDebugger::SplitAndEnqueueMessage(Net::MsgDesc *p_message)\r\n{\r\n\tif (!mp_server)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\r\n\tprintf(\"Splitting message of size %d\\n\",p_message->m_Length);\r\n\t\r\n\tint num_packets=p_message->m_Length / SPLIT_MESSAGE_MAX_SIZE;\r\n\tint total_num_packets=num_packets;\r\n\tint remainder=p_message->m_Length % SPLIT_MESSAGE_MAX_SIZE;\r\n\tif (remainder)\r\n\t{\r\n\t\t++total_num_packets;\r\n\t}\r\n\t\r\n\tchar *p_source_data=(char*)p_message->m_Data;\r\n\tfor (int i=0; i<num_packets; ++i)\r\n\t{\r\n\t\tsend_sub_packet(p_message,SPLIT_MESSAGE_MAX_SIZE,p_source_data,i,total_num_packets);\r\n\t\tp_source_data+=SPLIT_MESSAGE_MAX_SIZE;\r\n\t}\t\r\n\t\r\n\tif (remainder)\r\n\t{\r\n\t\tsend_sub_packet(p_message,remainder,p_source_data,total_num_packets-1,total_num_packets);\r\n\t}\r\n\t\t\r\n\t++m_split_message_id;\r\n}\r\n\r\nvoid CScriptDebugger::process_net_tasks_loop( void )\r\n{\r\n\tm_paused = true;\r\n\twhile( m_paused )\r\n\t{\r\n\t\tTmr::Time start_loop_time;\r\n\r\n\t\tstart_loop_time = Tmr::GetTime();\r\n\t\tcheck_for_timeouts();\r\n\t\tmp_server->GetReceiveDataTask().vCall();\r\n\t\tmp_server->GetProcessDataTask().vCall();\r\n\t\tmp_server->GetSendDataTask().vCall();\r\n\t\tmp_server->GetNetworkMetricsTask().vCall();\r\n\t\twhile(( Tmr::GetTime() - start_loop_time ) < 17 );\r\n\t}\r\n}\r\n\r\nvoid CScriptDebugger::ScriptDebuggerPause( void )\r\n{\r\n\t//Dbg_Printf( \"Pausing Game\\n\" );\r\n\tprocess_net_tasks_loop();\r\n}\r\n\r\nvoid CScriptDebugger::ScriptDebuggerUnpause( void )\r\n{\r\n\t//Dbg_Printf( \"Unpausing Game\\n\" );\r\n\tm_paused = false;\r\n}\r\n\r\nvoid CScriptDebugger::TransmitExceptionInfo(Obj::SException *p_exception, Obj::CCompositeObject* p_obj)\r\n{\r\n\t#if 0\r\n\tif (mp_server)\r\n\t{\r\n\t\t//SCRIPT_DEBUGGER_BUFFER_SIZE\r\n\t\tgpDebugInfoBuffer[0]=(uint32)(p_obj->GetID());\r\n\t\tgpDebugInfoBuffer[1]=p_exception->ExceptionNameChecksum;\r\n\t\tgpDebugInfoBuffer[2]=p_exception->ScriptChecksum;\r\n\t\t\r\n\t\tNet::MsgDesc msg;\r\n\t\tmsg.m_Data = gpDebugInfoBuffer;\r\n\t\tmsg.m_Length = 3*4;\r\n\t\tmsg.m_Id = GameNet::vMSG_ID_DBG_EXCEPTION_INFO;\r\n\t\tDbg::CScriptDebugger::Instance()->EnqueueMessage(&msg);\r\n\t}\r\n\t#endif\r\n}\r\n\r\n// SPEEDOPT: This gets called by the CScript code whenever the script changes.\r\n// It may need to be optimized ... or maybe not.\r\nSWatchedScript *CScriptDebugger::GetScriptWatchInfo(uint32 checksum)\r\n{\r\n\tfor (int i=0; i<m_num_watched_scripts; ++i)\r\n\t{\r\n\t\tif (mp_watched_scripts[i].mChecksum==checksum)\r\n\t\t{\r\n\t\t\treturn &mp_watched_scripts[i];\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\treturn NULL;\r\n}\t\r\n\r\nvoid CScriptDebugger::check_for_timeouts( void )\r\n{\r\n\tLst::Search< Net::Conn > sh;\r\n\tfor( Net::Conn *conn = mp_server->FirstConnection(&sh); conn; conn = mp_server->NextConnection(&sh) )\r\n\t{\r\n\t\tif (conn->GetNumResends() > 3)\r\n\t\t{\r\n\t\t\tconn->Invalidate();\r\n\t\t\tmp_server->TerminateConnection( conn );\r\n\t\t\tprintf(\"Dropping PC connection due to exceeding 3 resends ...\\n\");\r\n\t\t}\r\n\t}\r\n}\r\n\r\n// A third of a second\r\n#define DOUBLE_CLICK_TIME_WINDOW (150000000/3)\r\nvoid CScriptDebugger::left_button_down()\r\n{\r\n\tm_left_button_down=true;\r\n\t\r\n\t// If a double-click is done then automatically view the object.\r\n\tTmr::CPUCycles time=Tmr::GetTimeInCPUCycles();\r\n\tif (time-m_state_when_left_pressed.mTime < DOUBLE_CLICK_TIME_WINDOW)\r\n\t{\r\n\t\tif (mp_currently_selected_object)\r\n\t\t{\r\n\t\t\tSViewObject v;\r\n\t\t\tv.mDoViewObject=true;\r\n\t\t\tv.mObjectId=mp_currently_selected_object->GetID();\r\n\t\t\tview_object(&v);\r\n\t\t\t\r\n\t\t\tm_left_button_down=false;\r\n\t\t}\r\n\t}\r\n\tm_state_when_left_pressed.mTime=time;\r\n\t\r\n\tm_state_when_left_pressed.mMouseX=m_mouse_x;\r\n\tm_state_when_left_pressed.mMouseY=m_mouse_y;\r\n\tm_state_when_left_pressed.mCamPhi=m_cam_phi;\r\n\tm_state_when_left_pressed.mCamTheta=m_cam_theta;\r\n\t\r\n\tif (0)//mp_viewed_object)\r\n\t{\r\n\t\t// Mouse clicks do not send object info when viewing an object. Instead, holding the left button\r\n\t\t// down allows the mouse to rotate the camera around the object.\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Run a script to make the mouse text do something so that we know the click has had an effect.\r\n\t\tScript::RunScript(\"DoMouseClickEffect\");\r\n\t\tsend_composite_object_info(mp_currently_selected_object);\r\n\t}\t\r\n}\r\n\r\nvoid CScriptDebugger::left_button_up()\r\n{\r\n\tm_left_button_down=false;\r\n}\r\n\r\nvoid CScriptDebugger::right_button_down()\r\n{\r\n\tm_right_button_down=true;\r\n\t\r\n\tm_state_when_right_pressed.mMouseX=m_mouse_x;\r\n\tm_state_when_right_pressed.mMouseY=m_mouse_y;\r\n\tm_state_when_right_pressed.mCamRadius=m_cam_radius;\r\n}\r\n\r\nenum\r\n{\r\n\tMOUSE_PICK_SEARCH_RADIUS=70\r\n};\r\n\t\r\nvoid CScriptDebugger::update_mouse_cursor()\r\n{\r\n\t// The m_got_valid_mouse_position is to prevent glitches due to m_mouse_on_screen being\r\n\t// set but no mouse position message received yet.\r\n\tif (m_mouse_on_screen && m_got_valid_mouse_position)\r\n\t{\r\n\t\tObj::CCompositeObject *p_ob=NULL;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\tif (0)//mp_viewed_object)\r\n\t\t{\r\n\t\t\t// If we are viewing an object, then the mouse will be used to rotate the camera view\r\n\t\t\t// around the object, so don't search for a new object cos the text will just get in the way.\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_ob=s_find_nearest_object(\tm_mouse_x,\r\n\t\t\t\t\t\t\t\t\t\tm_mouse_y,\r\n\t\t\t\t\t\t\t\t\t\tMOUSE_PICK_SEARCH_RADIUS);\r\n\t\t}\r\n\t\t\r\n\t\tif (p_ob != mp_currently_selected_object)\r\n\t\t{\r\n\t\t\ts_change_render_mode(mp_currently_selected_object,m_original_object_render_mode);\r\n\t\t\t\r\n\t\t\tmp_currently_selected_object=p_ob;\r\n\t\t\tm_original_object_render_mode=s_change_render_mode(p_ob,Nx::vBBOX);\r\n\t\t}\r\n\t\t\r\n\t\tif (mp_currently_selected_object)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_struct=new Script::CStruct;\r\n\t\t\tp_struct->AddInteger(\"x\",m_mouse_x);\r\n\t\t\tp_struct->AddInteger(\"y\",m_mouse_y);\r\n\t\t\tp_struct->AddString(\"text\",Script::FindChecksumName(mp_currently_selected_object->GetID()));\r\n\t\t\tScript::RunScript(\"SetMouseText\",p_struct);\r\n\t\t\tdelete p_struct;\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tScript::RunScript(\"DestroyMouseText\");\r\n\t\t}\r\n\t}\t\t\r\n}\r\n\r\nvoid CScriptDebugger::switch_off_mouse_cursor()\r\n{\r\n\t// Destroy the mouse cursor screen elements, then set m_mouse_on_screen to false \r\n\t// so that any late mouse position messages get ignored.\r\n\tScript::RunScript(\"DestroyMouseCursor\");\r\n\tm_mouse_on_screen=false;\r\n\tm_got_valid_mouse_position=false;\r\n\t// Reset these too so that there is no confusion.\r\n\tm_left_button_down=false;\r\n\tm_right_button_down=false;\r\n\t\r\n\t\r\n\tif (mp_currently_selected_object)\r\n\t{\r\n\t\ts_change_render_mode(mp_currently_selected_object,m_original_object_render_mode);\r\n\t}\r\n\tmp_currently_selected_object=NULL;\t\r\n\tm_original_object_render_mode=Nx::vNONE;\r\n\t\r\n}\r\n\r\nvoid CScriptDebugger::do_any_every_frame_object_updates()\r\n{\r\n\t++m_frames_since_last_object_update;\r\n\t\r\n\t// Restrict the rate at which data is sent to be less than 200K per second, as a safeguard.\r\n\tif (m_object_update_total_bytes_sent * 60 / m_frames_since_last_object_update > 200000)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tm_object_update_total_bytes_sent=0;\r\n\tm_frames_since_last_object_update=0;\r\n\t\r\n\tLst::Search<Obj::CObject> sh;\r\n\tObj::CCompositeObject *p_ob = (Obj::CCompositeObject*) sh.FirstItem( Obj::CCompositeObjectManager::Instance()->GetRefObjectList() );\r\n\twhile (p_ob)\r\n\t{\r\n\t\tif (p_ob->GetDebuggerEveryFrameFlag())\r\n\t\t{\r\n\t\t\tm_object_update_total_bytes_sent+=send_composite_object_info(p_ob);\r\n\t\t}\r\n\t\tp_ob = (Obj::CCompositeObject*)sh.NextItem();\r\n\t}\r\n}\r\n\r\nvoid CScriptDebugger::stop_all_every_frame_object_updates()\r\n{\r\n\tLst::Search<Obj::CObject> sh;\r\n\tObj::CCompositeObject *p_ob = (Obj::CCompositeObject*) sh.FirstItem( Obj::CCompositeObjectManager::Instance()->GetRefObjectList() );\r\n\twhile (p_ob)\r\n\t{\r\n\t\tp_ob->SetDebuggerEveryFrameFlag(false);\r\n\t\tp_ob = (Obj::CCompositeObject*)sh.NextItem();\r\n\t}\r\n}\r\n\r\nvoid CScriptDebugger::setup_default_camera_viewing_position()\r\n{\r\n\tint type=SKATE_TYPE_UNDEFINED;\r\n\tif (mp_viewed_object)\r\n\t{\r\n\t\ttype=mp_viewed_object->GetType();\r\n\t}\r\n\t\t\r\n\tswitch (type)\r\n\t{\r\n\tcase SKATE_TYPE_PED:\r\n\tcase SKATE_TYPE_SKATER:\r\n\t\tm_cam_radius=100.0f;\r\n\t\tm_cam_theta=1.107f;\r\n\t\tm_cam_focus_offset=40;\r\n\t\tbreak;\r\n\tcase SKATE_TYPE_CAR:\r\n\t\tm_cam_radius=200.0f;\r\n\t\tm_cam_theta=1.326f;\r\n\t\tm_cam_focus_offset=40;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tm_cam_radius=100.0f;\r\n\t\tm_cam_theta=1.107f;\r\n\t\tm_cam_focus_offset=0;\r\n\t\tbreak;\r\n\t}\r\n\tm_cam_phi=0.0f;\r\n\r\n\tm_state_when_left_pressed.mCamPhi=m_cam_phi;\r\n\tm_state_when_left_pressed.mCamTheta=m_cam_theta;\r\n\tm_state_when_right_pressed.mCamRadius=m_cam_radius;\r\n\t\r\n\t// If the viewed object has a bounding radius defined then add that to the initial camera radius\r\n\t// too, so that the camera does not start off inside big things.\r\n\tif (mp_viewed_object)\r\n\t{\r\n\t\tObj::CModelComponent *p_model_component=(Obj::CModelComponent*)mp_viewed_object->GetComponent(CRCD(0x286a8d26,\"Model\"));\r\n\t\tif (p_model_component)\r\n\t\t{\r\n\t\t\tNx::CModel *p_model=p_model_component->GetModel();\r\n\t\t\tif (p_model)\r\n\t\t\t{\r\n\t\t\t\tMth::Vector r=p_model->GetBoundingSphere();\r\n\t\t\t\t\r\n\t\t\t\t// Apply any scaling, needed for the big alligator in the zoo.\r\n\t\t\t\tMth::Vector scale=p_model->GetScale();\r\n\t\t\t\tfloat s=scale.GetX();\r\n\t\t\t\tif (scale.GetY()>s) s=scale.GetY();\r\n\t\t\t\tif (scale.GetZ()>s) s=scale.GetZ();\r\n\t\t\t\t\r\n\t\t\t\tm_cam_radius+=r.Length()*s;\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\n// This will override the camera position and angles so as to view the mp_viewed_object.\r\nvoid CScriptDebugger::update_camera()\r\n{\r\n\t// Note: mp_viewed_object is a smart pointer, so will become NULL if the object dies.\r\n\tif (!mp_viewed_object)\r\n\t{\r\n\t\t// Nothing to see\r\n\t\treturn;\r\n\t}\t\r\n\r\n\t// Get the skater's camera.\r\n\tMdl::Skate * p_skate_mod =  Mdl::Skate::Instance();\r\n\tObj::CSkater *p_skater = p_skate_mod->GetSkater(0);\r\n\tif (!p_skater)\r\n\t{\r\n\t\t// No skater\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tGfx::Camera *p_skater_cam=p_skater->GetActiveCamera();\r\n\tif (!p_skater_cam)\r\n\t{\r\n\t\t// No skater camera\r\n\t\treturn;\r\n\t}\t\r\n\r\n\r\n\tif (m_mouse_on_screen && m_got_valid_mouse_position)\r\n\t{\r\n\t\tif (m_left_button_down)\r\n\t\t{\r\n\t\t\tm_cam_theta=m_state_when_left_pressed.mCamTheta+Script::GetFloat(\"MouseRotationUpDownFactor\")*(m_mouse_y-m_state_when_left_pressed.mMouseY);\r\n\t\t\t\r\n\t\t\tif (m_cam_theta > Mth::PI-0.01f)\r\n\t\t\t{\r\n\t\t\t\tm_cam_theta = Mth::PI-0.01f;\r\n\t\t\t}\t\r\n\t\t\telse if (m_cam_theta < 0.01f)\r\n\t\t\t{\r\n\t\t\t\tm_cam_theta = 0.01f;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tm_cam_phi=m_state_when_left_pressed.mCamPhi+Script::GetFloat(\"MouseRotationLeftRightFactor\")*(m_mouse_x-m_state_when_left_pressed.mMouseX);\r\n\t\t\tif (m_cam_phi > Mth::PI*2.0f)\r\n\t\t\t{\r\n\t\t\t\tm_cam_phi -= Mth::PI*2.0f;\r\n\t\t\t}\r\n\t\t\telse if (m_cam_phi < -Mth::PI*2.0f)\r\n\t\t\t{\r\n\t\t\t\tm_cam_phi += Mth::PI*2.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\t\r\n\t\tif (m_right_button_down)\r\n\t\t{\r\n\t\t\tm_cam_radius=m_state_when_right_pressed.mCamRadius+Script::GetFloat(\"MouseZoomFactor\")*(m_mouse_y-m_state_when_right_pressed.mMouseY);\r\n\t\t\t\r\n\t\t\tif (m_cam_radius < 0.01f)\r\n\t\t\t{\r\n\t\t\t\tm_cam_radius=0.01f;\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n\r\n\tMth::Vector cam_radius_vector;\r\n\tcam_radius_vector[Y]=cosf(m_cam_theta);\r\n\tfloat s=sinf(m_cam_theta);\r\n\tcam_radius_vector[X]=s*cosf(m_cam_phi);\r\n\tcam_radius_vector[Z]=s*sinf(m_cam_phi);\r\n\tcam_radius_vector.Normalize(); // Just to be sure\r\n\tcam_radius_vector *= m_cam_radius;\r\n\r\n\t// Rotate using the object's matrix so that the camera's frame of\r\n\t// reference is that of the object, otherwise the camera will not turn with the object.\r\n\tcam_radius_vector *= mp_viewed_object->GetDisplayMatrix();\r\n\t\r\n\tMth::Vector focus_pos=mp_viewed_object->GetPos();\r\n\tfocus_pos[Y]+=m_cam_focus_offset;\r\n\tMth::Vector camera_pos=focus_pos+cam_radius_vector;\r\n\r\n\tcamera_pos[W] = 1.0f;\r\n\tp_skater_cam->SetPos(camera_pos);\r\n\r\n\tMth::Matrix mat;\r\n\tmat.Ident();\r\n\tmat[Z]=focus_pos-camera_pos;\r\n\tmat[Z].Normalize();\r\n\tmat[X]\t= Mth::CrossProduct( mat[Y], mat[Z] );\r\n\tmat[X].Normalize();\r\n\tmat[Y]\t= Mth::CrossProduct( mat[Z], mat[X] );\r\n\tmat[Y].Normalize();\r\n\r\n\tMth::Matrix& frame_matrix = p_skater_cam->GetMatrix();\r\n\tframe_matrix[X][X] = -mat[0][0];\r\n\tframe_matrix[X][Y] = -mat[0][1];\r\n\tframe_matrix[X][Z] = -mat[0][2];\r\n\tframe_matrix[Y][X] = mat[1][0];\r\n\tframe_matrix[Y][Y] = mat[1][1];\r\n\tframe_matrix[Y][Z] = mat[1][2];\r\n\tframe_matrix[Z][X] = -mat[2][0];\r\n\tframe_matrix[Z][Y] = -mat[2][1];\r\n\tframe_matrix[Z][Z] = -mat[2][2];\r\n}\r\n\r\nvoid CScriptDebugger::s_logic_code ( const Tsk::Task< CScriptDebugger >& task )\r\n{\r\n\tCScriptDebugger&\tmdl = task.GetData();\r\n\tDbg_AssertType ( &task, Tsk::Task< CScriptDebugger > );\r\n\t\r\n\tmdl.check_for_timeouts();\r\n\r\n\tmdl.update_camera();\r\n\r\n\tmdl.update_mouse_cursor();\t\r\n\r\n\tmdl.do_any_every_frame_object_updates();\r\n\tmdl.send_any_single_step_object_info();\r\n\t\r\n\tswitch (mdl.m_state)\r\n\t{\r\n\tcase SCRIPT_DEBUGGER_STATE_IDLE:\r\n\t{\r\n\t\tbreak;\r\n\t}\r\n\t\t\t\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\t\t\t\r\n}\r\n\r\n} // namespace Dbg\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/Scripting/debugger.h",
    "content": "#ifndef __GEL_SCRIPTING_DEBUGGER_H__\r\n#define __GEL_SCRIPTING_DEBUGGER_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __GEL_MODULE_H\r\n#include <gel/module.h>\r\n#endif\r\n\r\n#ifndef __NET_H__\r\n#include <gel/net/net.h>\r\n#endif\r\n\r\n#ifndef __NETSERV_H__\r\n#include <gel/net/server/netserv.h>\r\n#endif\r\n\r\n#ifndef\t__GFX_NXMODEL_H__\r\n#include <gfx/nxmodel.h>\r\n#endif\r\n\r\n#ifndef __GEL_OBJPTR_H\r\n#include <gel/objptr.h>\r\n#endif\r\n\r\n// This is outside the #ifdef __NOPT_ASSERT__ so that they can be used in the PC code,\r\n// which includes this file but does not have __NOPT_ASSERT__ defined.\r\nnamespace Obj\r\n{\r\n\tclass CObject;\r\n\tclass CCompositeObject;\r\n\tstruct SException;\r\n}\r\n\r\nnamespace Dbg\r\n{\r\n\r\n// Points to the fixed area in high memory where the game code stores stuff for the\r\n// script debugger to read using the target manager API.\r\n// (Note: The script debugger app includes this file, so has access to these defines)\r\n// Currently, the first thing stored there is a SChecksumNameInfo structure.\r\n// The game code will assert if this value does not match the symbol _script_debugger_start\r\nenum\r\n{\r\n\tSCRIPT_DEBUGGER_MEMORY_START=0x06E00080\r\n};\r\n\r\n// Contains pointers to the start and end of the big list of names whose checksums are\r\n// loaded. (Eg, every word in every q file currently loaded)\r\n// This lets the script debugger register all those checksums when it starts up, so that\r\n// it can resolve checksums to names. \r\nstruct SChecksumNameInfo\r\n{\r\n\tchar **mppStart;\r\n\tchar **mppEnd;\r\n};\r\n\r\n\r\n\r\n// Used in the vMSG_ID_DBG_WATCH_SCRIPT packet.\r\nenum\r\n{\r\n\tCHECKSUM_IS_SCRIPT_NAME,\r\n\tCHECKSUM_IS_SCRIPT_ID,\r\n};\r\n\r\n// An array of these gets passed from the PS2 to the debugger in the\r\n// vMSG_ID_DBG_WATCH_LIST meesage\r\nstruct SWatchInfo\r\n{\r\n\tuint32 mScriptName;\r\n\tbool mStopImmediately;\r\n};\r\n\r\nenum EObjectUpdateMode\r\n{\r\n\tEVERY_FRAME,\r\n\tSINGLE_STEP,\r\n};\t\r\n\t\r\n// One of these gets passed to the PS2 from the debugger in the\r\n// vMSG_ID_DBG_SET_OBJECT_UPDATE_MODE message.\r\nstruct SObjectUpdateMode\r\n{\r\n\tuint32 mObjectId;\r\n\tEObjectUpdateMode mMode;\r\n\tbool mOn;\r\n};\r\n\r\n// One of these gets passed to the PS2 from the debugger in the\r\n// vMSG_ID_DBG_VIEW_OBJECT message.\r\n\r\nstruct SViewObject\r\n{\r\n\tuint32 mObjectId;\r\n\tbool mDoViewObject;\r\n};\r\n\r\nstruct SSplitMessageHeader\r\n{\r\n\tchar mOriginalMessageId;\r\n\tuint32 mOriginalMessageSize;\r\n\t\r\n\tint mTotalNumMessages;\r\n\t\r\n\tuint32 mThisMessageId;\r\n\tuint32 mThisMessageSize;\r\n\tint mThisMessageIndex;\r\n};\r\n\r\nenum\r\n{\r\n\t// This makes each sub-packet be as big as possible. Netapp.cpp will assert if the total\r\n\t// packet size is >= Net::Manager::vMAX_PACKET_SIZE - 64\r\n\t// The sub-packet includes a SSplitMessageHeader, hence that size has to be subtracted too.\r\n\tSPLIT_MESSAGE_MAX_SIZE=Net::Manager::vMAX_PACKET_SIZE - 65 - sizeof(SSplitMessageHeader),\r\n};\r\n\r\n}\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\r\nnamespace Net\r\n{\r\n\tclass MsgDesc;\r\n}\t\r\n\r\nnamespace Dbg\r\n{\r\n\r\nenum\r\n{\r\n\tSCRIPT_DEBUGGER_BUFFER_SIZE=60*1024, // Must be a multiple of 4\r\n};\t\r\n\r\nenum EWatchType\r\n{\r\n\tNONE=0,\r\n\tSCRIPT,\r\n\tSCRIPT_GLOBAL,\r\n\tOBJECT_ID,\r\n\tEXCEPTION,\r\n};\r\n\r\n#define MAX_WATCHED_SCRIPTS 100\r\nstruct SWatchedScript\r\n{\r\n\tuint32 mChecksum;\r\n\tbool mStopScriptImmediately;\r\n};\r\n\r\nstruct SStateWhenLeftPressed\r\n{\r\n\tint mMouseX;\r\n\tint mMouseY;\r\n\tfloat mCamTheta;\r\n\tfloat mCamPhi;\r\n\tTmr::CPUCycles mTime;\r\n};\r\n\r\nstruct SStateWhenRightPressed\r\n{\r\n\tint mMouseX;\r\n\tint mMouseY;\r\n\tfloat mCamRadius;\r\n};\r\n\r\nclass CScriptDebugger  : public Mdl::Module\r\n{\r\n\tDeclareSingletonClass( CScriptDebugger );\r\n\r\n\tNet::Server *mp_server;\r\n\t// Used by the SplitAndEnqueueMessage function to give an id to the message\r\n\t// that is being split. Each of the sub-messages that the message is split into\r\n\t// is given this id so that they can be reconstructed at the other end.\r\n\t// It increments by 1 each time it is used.\r\n\tuint32 m_split_message_id;\r\n\tvoid send_sub_packet(Net::MsgDesc *p_message, uint32 size, char *p_source,\r\n\t\t\t\t\t\t int packetIndex, int totalNumPackets);\r\n\t\r\n\tenum EState\r\n\t{\r\n\t\tSCRIPT_DEBUGGER_STATE_IDLE,\r\n\t};\r\n\t\t\r\n\tEState m_state;\r\n\tchar *mp_checksum_names_current_pos;\r\n\tchar *mp_checksum_names_end;\r\n\r\n\tint m_num_watched_scripts;\r\n\tbool m_paused;\r\n\tSWatchedScript mp_watched_scripts[MAX_WATCHED_SCRIPTS];\r\n\t\r\n\tbool m_mouse_on_screen;\r\n\tbool m_got_valid_mouse_position;\r\n\tint m_mouse_x;\r\n\tint m_mouse_y;\r\n\tObj::CCompositeObject *mp_currently_selected_object; // TODO: Change to be a smart pointer !!!\r\n\tNx::ERenderMode m_original_object_render_mode;\r\n\tbool m_left_button_down;\t\r\n\tSStateWhenLeftPressed m_state_when_left_pressed;\r\n\t\r\n\tbool m_right_button_down;\t\r\n\tSStateWhenRightPressed m_state_when_right_pressed;\r\n\t\r\n\tvoid left_button_down();\r\n\tvoid left_button_up();\r\n\tvoid right_button_down();\r\n\r\n\tvoid update_mouse_cursor();\r\n\tvoid switch_off_mouse_cursor();\r\n\t\r\n\tObj::CSmtPtr<Obj::CCompositeObject> mp_viewed_object;\r\n\tbool m_in_object_single_step_mode;\r\n\tuint32 m_single_step_object_id;\r\n\r\n\tint m_object_update_total_bytes_sent;\r\n\tint m_frames_since_last_object_update;\r\n\t\r\n\tfloat m_cam_radius;\r\n\tfloat m_cam_theta;\r\n\tfloat m_cam_phi;\r\n\tfloat m_cam_focus_offset;\r\n\tvoid setup_default_camera_viewing_position();\r\n\tvoid update_camera();\r\n\t\r\n\tvoid v_start_cb ( void );\r\n\tvoid v_stop_cb ( void );\r\n\t\r\n\tstatic Tsk::Task< CScriptDebugger >::Code s_logic_code;       \r\n\tTsk::Task< CScriptDebugger > *mp_logic_task;\r\n\t\r\n\tstatic Net::MsgHandlerCode s_handle_connection_request;\r\n\tstatic Net::MsgHandlerCode s_handle_watch_this;\r\n\tstatic Net::MsgHandlerCode s_handle_watch_script;\r\n\r\n\tstatic Net::MsgHandlerCode s_handle_stop;\r\n\tstatic Net::MsgHandlerCode s_handle_step_into;\r\n\tstatic Net::MsgHandlerCode s_handle_step_over;\r\n\tstatic Net::MsgHandlerCode s_handle_go;\r\n\tstatic Net::MsgHandlerCode s_handle_clear_script_watches;\r\n\tstatic Net::MsgHandlerCode s_handle_refresh;\r\n\tstatic Net::MsgHandlerCode s_handle_disconnect;\r\n\tstatic Net::MsgHandlerCode s_handle_send_cscript_list;\r\n\tstatic Net::MsgHandlerCode s_handle_send_watch_list;\r\n\tstatic Net::MsgHandlerCode s_handle_stop_watching_this_index;\r\n\tstatic Net::MsgHandlerCode s_handle_stop_watching_this_cscript;\r\n\tstatic Net::MsgHandlerCode s_handle_send_composite_object_info;\r\n\tstatic Net::MsgHandlerCode s_handle_mouse_position;\r\n\tstatic Net::MsgHandlerCode s_handle_mouse_on_screen;\r\n\tstatic Net::MsgHandlerCode s_handle_mouse_off_screen;\r\n\tstatic Net::MsgHandlerCode s_handle_mouse_left_button_down;\r\n\tstatic Net::MsgHandlerCode s_handle_mouse_left_button_up;\r\n\tstatic Net::MsgHandlerCode s_handle_mouse_right_button_down;\r\n\tstatic Net::MsgHandlerCode s_handle_mouse_right_button_up;\r\n\tstatic Net::MsgHandlerCode s_handle_send_composite_object_list;\r\n\tstatic Net::MsgHandlerCode s_handle_set_object_update_mode;\r\n\tstatic Net::MsgHandlerCode s_handle_view_object;\r\n\tstatic Net::MsgHandlerCode s_handle_send_script_global_info;\r\n\r\n\tvoid add_to_watched_scripts(uint32 checksum, bool stopScriptImmediately);\r\n\tSWatchedScript *find_watched_script(uint32 checksum);\r\n\tvoid refresh();\r\n\tvoid stop_debugging();\r\n\tvoid stop_watching_script(int index);\r\n\tint  send_composite_object_info(Obj::CCompositeObject* p_obj);\r\n\tvoid send_composite_object_info(uint32 id);\r\n\tvoid send_script_global_info(uint32 id);\r\n\tvoid do_any_every_frame_object_updates();\r\n\tvoid stop_all_every_frame_object_updates();\r\n\tvoid send_any_single_step_object_info();\r\n\t\r\n\tvoid set_object_update_mode(SObjectUpdateMode *pObjectUpdateMode);\r\n\tvoid view_object(SViewObject *pViewObject);\r\n\t\r\n\tvoid process_net_tasks_loop( void );\r\n\tvoid check_for_timeouts( void );\r\n\t\r\n\tvoid transmit_cscript_list();\r\n\tvoid transmit_watch_list();\r\n\tvoid transmit_composite_object_list();\r\n\tvoid transmit_compression_lookup_table();\r\n\r\npublic:\r\n\tCScriptDebugger();\r\n\tvirtual\t~CScriptDebugger();\r\n\t\r\n\tvoid EnqueueMessage(Net::MsgDesc *p_message);\r\n\tvoid StreamMessage(Net::MsgDesc *p_message);\r\n\t\r\n\tvoid SplitAndEnqueueMessage(Net::MsgDesc *p_message);\r\n\t\r\n\tvoid ScriptDebuggerPause( void );\r\n\tvoid ScriptDebuggerUnpause( void );\r\n\r\n\tvoid TransmitExceptionInfo(Obj::SException *p_exception, Obj::CCompositeObject* p_obj);\r\n\tSWatchedScript *GetScriptWatchInfo(uint32 checksum);\r\n};\r\n\r\nextern uint32 gpDebugInfoBuffer[];\r\n\r\n} // namespace Dbg\r\n#endif // __NOPT_ASSERT__\r\n\r\n#endif // #ifndef __GEL_SCRIPTING_DEBUGGER_H__\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/eval.cpp",
    "content": "#include <gel/scripting/eval.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/string.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/parse.h>\r\n\r\nnamespace Script\r\n{\r\n\r\n// This is a static rather than a local var of execute_operation() to prevent the \r\n// constructor being called every time execute_operation is called.\r\n// Saves a tiny bit of time.\r\nCComponent spResult;\r\n\r\nstatic int sPrecedence[]=\r\n{\r\n\t-1, // ESCRIPTTOKEN_ENDOFFILE,\t\t\t// 0\r\n\t-1, // ESCRIPTTOKEN_ENDOFLINE,\t\t\t// 1\r\n\t-1, // ESCRIPTTOKEN_ENDOFLINENUMBER,   // 2\r\n\t-1, // ESCRIPTTOKEN_STARTSTRUCT,       // 3\r\n\t-1, // ESCRIPTTOKEN_ENDSTRUCT,         // 4\r\n\t100, // ESCRIPTTOKEN_STARTARRAY,        // 5\r\n\t-1, // ESCRIPTTOKEN_ENDARRAY,          // 6\r\n\t76, // ESCRIPTTOKEN_EQUALS,            // 7\r\n\t100, // ESCRIPTTOKEN_DOT,               // 8\r\n\t-1, // ESCRIPTTOKEN_COMMA,             // 9\r\n\t98, // ESCRIPTTOKEN_MINUS,             // 10\r\n\t98, // ESCRIPTTOKEN_ADD,               // 11\r\n\t99, // ESCRIPTTOKEN_DIVIDE,            // 12\r\n\t100, // ESCRIPTTOKEN_MULTIPLY,          // 13\r\n\t-1, // ESCRIPTTOKEN_OPENPARENTH,       // 14\r\n\t-1, // ESCRIPTTOKEN_CLOSEPARENTH,      // 15\r\n\t-1, // ESCRIPTTOKEN_DEBUGINFO,\t\t\t// 16\r\n\t-1, // ESCRIPTTOKEN_SAMEAS,\t\t\t// 17\r\n\t80, // ESCRIPTTOKEN_LESSTHAN,\t\t\t// 18\r\n\t79, // ESCRIPTTOKEN_LESSTHANEQUAL,     // 19\r\n\t78, // ESCRIPTTOKEN_GREATERTHAN,       // 20\r\n\t77, // ESCRIPTTOKEN_GREATERTHANEQUAL,  // 21\r\n\t-1, // ESCRIPTTOKEN_NAME,\t\t\t\t// 22\r\n\t-1, // ESCRIPTTOKEN_INTEGER,\t\t\t// 23\r\n\t-1, // ESCRIPTTOKEN_HEXINTEGER,        // 24\r\n    -1, // ESCRIPTTOKEN_ENUM,              // 25\r\n\t-1, // ESCRIPTTOKEN_FLOAT,             // 26\r\n\t-1, // ESCRIPTTOKEN_STRING,            // 27\r\n\t-1, // ESCRIPTTOKEN_LOCALSTRING,       // 28\r\n\t-1, // ESCRIPTTOKEN_ARRAY,             // 29\r\n\t-1, // ESCRIPTTOKEN_VECTOR,            // 30\r\n\t-1, // ESCRIPTTOKEN_PAIR,\t\t\t\t// 31\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_BEGIN,\t\t// 32\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_REPEAT,    // 33\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_BREAK,     // 34\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_SCRIPT,    // 35\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_ENDSCRIPT, // 36\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_IF,        // 37\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_ELSE,      // 38\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_ELSEIF,    // 39\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_ENDIF,\t\t// 40\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_RETURN,\t// 41\r\n    -1, // ESCRIPTTOKEN_UNDEFINED,\t\t\t// 42\r\n\t-1, // ESCRIPTTOKEN_CHECKSUM_NAME,\t\t// 43\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_ALLARGS,\t// 44\r\n\t-1, // ESCRIPTTOKEN_ARG,\t\t\t\t// 45\r\n\t-1, // ESCRIPTTOKEN_JUMP,\t\t\t\t// 46\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_RANDOM,    // 47\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE,\t// 48\r\n\t-1, // ESCRIPTTOKEN_AT,\t\t\t\t// 49\r\n\t58, // ESCRIPTTOKEN_OR,\t\t\t\t// 50\r\n\t60, // ESCRIPTTOKEN_AND,\t\t\t\t// 51\r\n\t59, // ESCRIPTTOKEN_XOR,\t\t\t\t// 52\r\n\t90, // ESCRIPTTOKEN_SHIFT_LEFT,\t\t// 53\r\n\t89, // ESCRIPTTOKEN_SHIFT_RIGHT,\t\t// 54\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_RANDOM2,\t\t// 55\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE2, // 56\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_NOT,\t\t\t// 57\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_AND,\t\t\t// 58\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_OR,            // 59\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_SWITCH,       \t// 60\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_ENDSWITCH,   \t// 61\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_CASE,          // 62\r\n\t-1, // ESCRIPTTOKEN_KEYWORD_DEFAULT,\t\t// 63\r\n\t-1,\t// ESCRIPTTOKEN_KEYWORD_RANDOM_NO_REPEAT,\t// 64\r\n\t-1,\t// ESCRIPTTOKEN_KEYWORD_RANDOM_PERMUTE,\t// 65\r\n\t-1, // ESCRIPTTOKEN_COLON,\t\t// 66\r\n\t-1, // ESCRIPTTOKEN_RUNTIME_CFUNCTION,\t// 67\r\n\t-1, // ESCRIPTTOKEN_RUNTIME_MEMBERFUNCTION, // 68\r\n};\r\n\r\nstatic bool sSameOrLowerPrecedence(EScriptToken a, EScriptToken b)\r\n{\r\n\t//printf(\"Precedence of %s=%d, %s=%d\\n\",GetTokenName(a),sPrecedence[a],GetTokenName(b),sPrecedence[b]);\r\n\tif (a==b)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn sPrecedence[a]<=sPrecedence[b];\r\n}\r\n\r\nCExpressionEvaluator::CExpressionEvaluator()\r\n{\r\n\tClear();\r\n\tEnableErrorChecking();\r\n}\r\n\r\nCExpressionEvaluator::~CExpressionEvaluator()\r\n{\r\n\tClear();\r\n}\r\n\r\nvoid CExpressionEvaluator::Clear()\r\n{\r\n\tint i;\r\n\r\n\tfor (i=0; i<VALUE_STACK_SIZE; ++i)\r\n\t{\r\n\t\tCleanUpComponent(&mp_value_stack[i]);\r\n\t}\t\r\n\tm_value_stack_top=0;\r\n\t\r\n\tm_operator_stack_top=0;\r\n\tfor (i=0; i<OPERATOR_STACK_SIZE; ++i)\r\n\t{\r\n\t\tmp_operator_stack[i].mOperator=NOP;\r\n\t\tmp_operator_stack[i].mParenthesesCount=0;\r\n\t}\t\r\n\tm_got_operators=false;\r\n\t\t\r\n\tmp_error_string=NULL;\r\n}\r\n\r\nvoid CExpressionEvaluator::ClearIfNeeded()\r\n{\r\n\tif (m_value_stack_top || \r\n\t\tmp_value_stack[0].mType!=ESYMBOLTYPE_NONE ||\r\n\t\tm_operator_stack_top || mp_error_string)\r\n\t{\r\n\t\tClear();\r\n\t}\t\r\n}\r\n\r\nvoid CExpressionEvaluator::SetTokenPointer(uint8 *p_token)\r\n{\r\n\tmp_token=p_token;\r\n}\r\n\r\nvoid CExpressionEvaluator::set_error(const char *p_error)\r\n{\r\n\t// TODO: Make this support variable arguments so it works like printf.\r\n\tClear();\r\n\tmp_error_string=p_error;\r\n\t\r\n\t// Sometimes we don't want an assert to go off when there is an error, such as\r\n\t// when scanning though the node scripts looking for EndGap commands.\r\n\t// (See the ScanNodeScripts function in nodearray.cpp)\r\n\tif (m_errors_enabled)\r\n\t{\r\n\t\tif (mp_token)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"Expression evaluator error, file %s, line %d: %s\\n\",Script::GetSourceFile(mp_token),Script::GetLineNumber(mp_token),p_error));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"Expression evaluator error: %s\\n\",p_error));\r\n\t\t}\r\n\t}\t\r\n}\t\r\n\r\nstatic int GetBool(CComponent *p_comp)\r\n{\r\n\tif (p_comp->mType==ESYMBOLTYPE_INTEGER)\r\n\t{\r\n\t\treturn p_comp->mIntegerValue;\r\n\t}\r\n\telse if (p_comp->mType==ESYMBOLTYPE_FLOAT)\r\n\t{\r\n\t\treturn p_comp->mFloatValue?1:0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\t// So that the calling code can set an error message.\r\n\t\t// Not asserting at this point because there is no way of printing the line number of the error.\r\n\t\treturn 2;\r\n\t\t#else\r\n\t\treturn 0;\r\n\t\t#endif\t\r\n\t}\r\n}\r\n\r\nvoid CExpressionEvaluator::execute_operation()\r\n{\r\n\tif (m_value_stack_top<1)\r\n\t{\r\n\t\tset_error(\"Not enough values in stack to execute operation\");\r\n\t\treturn;\r\n\t}\t\r\n\tif (mp_operator_stack[m_operator_stack_top].mParenthesesCount)\r\n\t{\r\n\t\tset_error(\"Non-zero parentheses count\");\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\t// Apply the top operator to the top two values, and replace them with the new value.\r\n\t// Then remove the top operator.\r\n\t\r\n\tEScriptToken op=mp_operator_stack[m_operator_stack_top].mOperator;\r\n\tif (op==NOP)\r\n\t{\r\n\t\tset_error(\"Tried to execute with no operator\");\r\n\t\treturn;\r\n\t}\r\n\r\n\tCComponent *pA=&mp_value_stack[m_value_stack_top-1];\r\n\tCComponent *pB=&mp_value_stack[m_value_stack_top];\r\n\t\r\n\tspResult.mType=ESYMBOLTYPE_NONE;\r\n\tspResult.mUnion=0;\r\n\r\n\t//printf(\"Executing '%s'\\n\",GetTokenName(op));\r\n\tswitch (op)\r\n\t{\r\n\tcase ESCRIPTTOKEN_OR:\r\n\t{\r\n\t\tspResult.mType=ESYMBOLTYPE_INTEGER;\r\n\t\tint a=GetBool(pA);\r\n\t\tint b=GetBool(pB);\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tif (a==2 || b==2)\r\n\t\t{\r\n\t\t\tset_error(\"Bad data types for 'or' operator\");\r\n\t\t}\r\n\t\t#endif\r\n\t\tspResult.mIntegerValue=a | b;\r\n\t\tbreak;\r\n\t}\r\n\tcase ESCRIPTTOKEN_AND:\r\n\t{\r\n\t\tspResult.mType=ESYMBOLTYPE_INTEGER;\r\n\t\tint a=GetBool(pA);\r\n\t\tint b=GetBool(pB);\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tif (a==2 || b==2)\r\n\t\t{\r\n\t\t\tset_error(\"Bad data types for 'or' operator\");\r\n\t\t}\r\n\t\t#endif\r\n\t\tspResult.mIntegerValue=a & b;\r\n\t\tbreak;\r\n\t}\r\n\t\r\n\tcase ESCRIPTTOKEN_EQUALS:\r\n\t\tspResult.mType=ESYMBOLTYPE_INTEGER;\r\n\t\tspResult.mIntegerValue=*pA==*pB;\r\n\t\tbreak;\r\n\t\t\r\n\tcase ESCRIPTTOKEN_LESSTHAN:\r\n\t\tspResult.mType=ESYMBOLTYPE_INTEGER;\r\n\t\tspResult.mIntegerValue=*pA<*pB;\r\n\t\tbreak;\r\n\r\n\tcase ESCRIPTTOKEN_GREATERTHAN:\r\n\t\tspResult.mType=ESYMBOLTYPE_INTEGER;\r\n\t\tspResult.mIntegerValue=*pA>*pB;\r\n\t\tbreak;\r\n\t\r\n\tcase ESCRIPTTOKEN_ADD:\r\n\t\tswitch (pA->mType)\r\n\t\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_INTEGER;\r\n\t\t\t\tspResult.mIntegerValue=pA->mIntegerValue+pB->mIntegerValue;\r\n\t\t\t}\r\n\t\t\telse if (pB->mType==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\t\tspResult.mFloatValue=(float)pA->mIntegerValue+pB->mFloatValue;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Second arg cannot be added to an integer\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\t\tspResult.mFloatValue=pA->mFloatValue+(float)pB->mIntegerValue;\r\n\t\t\t}\r\n\t\t\telse if (pB->mType==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\t\tspResult.mFloatValue=pA->mFloatValue+pB->mFloatValue;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Second arg cannot be added to a float\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t// Checksums may have integers added to them to give a new checksum.\r\n\t\t// This was added cos Steve needed to be able to give new unique id's\r\n\t\t// to some screen elements by adding an offset to a base checksum, \r\n\t\t// using id=(achecksum+1) for example.\r\n \t\tcase ESYMBOLTYPE_NAME:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_NAME;\r\n\t\t\t\tspResult.mChecksum=pA->mChecksum+pB->mIntegerValue;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Second arg cannot be added to a checksum\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_VECTOR)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_VECTOR;\r\n\t\t\t\tspResult.mpVector=new CVector;\r\n\t\t\t\tspResult.mpVector->mX=pA->mpVector->mX+pB->mpVector->mX;\r\n\t\t\t\tspResult.mpVector->mY=pA->mpVector->mY+pB->mpVector->mY;\r\n\t\t\t\tspResult.mpVector->mZ=pA->mpVector->mZ+pB->mpVector->mZ;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Second arg cannot be added to a vector\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_PAIR)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_PAIR;\r\n\t\t\t\tspResult.mpPair=new CPair;\r\n\t\t\t\tspResult.mpPair->mX=pA->mpPair->mX+pB->mpPair->mX;\r\n\t\t\t\tspResult.mpPair->mY=pA->mpPair->mY+pB->mpPair->mY;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Second arg cannot be added to a pair\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_STRING:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_STRING)\r\n\t\t\t{\r\n\t\t\t\tif (strlen(pA->mpString)+strlen(pB->mpString)+1>EVALUATOR_STRING_BUF_SIZE)\r\n\t\t\t\t{\r\n\t\t\t\t\tset_error(\"Result of string addition too long\");\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tspResult.mType=ESYMBOLTYPE_STRING;\r\n\t\t\t\t\tchar p_buf[EVALUATOR_STRING_BUF_SIZE];\r\n\t\t\t\t\tstrcpy(p_buf,pA->mpString);\r\n\t\t\t\t\tstrcat(p_buf,pB->mpString);\r\n\t\t\t\t\tspResult.mpString=CreateString(p_buf);\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Second arg cannot be added to a string\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_LOCALSTRING)\r\n\t\t\t{\r\n\t\t\t\tif (strlen(pA->mpLocalString)+strlen(pB->mpLocalString)+1>EVALUATOR_STRING_BUF_SIZE)\r\n\t\t\t\t{\r\n\t\t\t\t\tset_error(\"Result of local-string addition too long\");\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tspResult.mType=ESYMBOLTYPE_LOCALSTRING;\r\n\t\t\t\t\tchar p_buf[EVALUATOR_STRING_BUF_SIZE];\r\n\t\t\t\t\tstrcpy(p_buf,pA->mpLocalString);\r\n\t\t\t\t\tstrcat(p_buf,pB->mpLocalString);\r\n\t\t\t\t\tspResult.mpLocalString=CreateString(p_buf);\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Second arg cannot be added to a local-string\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t{\r\n\t\t\tif (pB->mType!=ESYMBOLTYPE_STRUCTURE)\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Structure add operator requires 2nd arg to be a structure\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tspResult.mType=ESYMBOLTYPE_STRUCTURE;\r\n\t\t\tspResult.mpStructure=new CStruct;\r\n\t\t\tspResult.mpStructure->AppendStructure(pA->mpStructure);\r\n\t\t\tspResult.mpStructure->AppendStructure(pB->mpStructure);\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tdefault:\r\n\t\t\tset_error(\"Addition not supported for this type\");\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_MINUS:\r\n\t\tswitch (pA->mType)\r\n\t\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_INTEGER;\r\n\t\t\t\tspResult.mIntegerValue=pA->mIntegerValue-pB->mIntegerValue;\r\n\t\t\t}\r\n\t\t\telse if (pB->mType==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\t\tspResult.mFloatValue=(float)pA->mIntegerValue-pB->mFloatValue;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Second arg cannot be subtracted from an integer\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\t\tspResult.mFloatValue=pA->mFloatValue-(float)pB->mIntegerValue;\r\n\t\t\t}\r\n\t\t\telse if (pB->mType==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\t\tspResult.mFloatValue=pA->mFloatValue-pB->mFloatValue;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Second arg cannot be subtracted from a float\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_VECTOR)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_VECTOR;\r\n\t\t\t\tspResult.mpVector=new CVector;\r\n\t\t\t\tspResult.mpVector->mX=pA->mpVector->mX-pB->mpVector->mX;\r\n\t\t\t\tspResult.mpVector->mY=pA->mpVector->mY-pB->mpVector->mY;\r\n\t\t\t\tspResult.mpVector->mZ=pA->mpVector->mZ-pB->mpVector->mZ;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Second arg cannot be subtracted from a vector\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_PAIR)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_PAIR;\r\n\t\t\t\tspResult.mpPair=new CPair;\r\n\t\t\t\tspResult.mpPair->mX=pA->mpPair->mX-pB->mpPair->mX;\r\n\t\t\t\tspResult.mpPair->mY=pA->mpPair->mY-pB->mpPair->mY;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Second arg cannot be subtracted from a pair\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t{\r\n\t\t\t// If the LHS is a structure, then the subtract operator is defined\r\n\t\t\t// so as to allow parameters to be removed from the structure,\r\n\t\t\t// cos that's quite handy.\r\n\t\t\t\r\n\t\t\t// If the RHS is a single name, then all parameter with that name\r\n\t\t\t// will be removed, including flags.\r\n\t\t\t// If the RHS is an array of names then each of those parameters will\r\n\t\t\t// be removed.\r\n\t\t\t// If the RHS is a structure, then all the parameters in the LHS which have\r\n\t\t\t// matching name AND type to something in the RHS will be removed, but if the RHS\r\n\t\t\t// contains unnamed-names then all parameters with that name will be removed.\r\n\t\t\t// So {x=3 x=\"blaa\"}-{x=9} gives {x=\"blaa\"}\r\n\t\t\t// But {x=3 x=\"blaa\"}-{x} gives {}\r\n\t\t\t\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_STRUCTURE;\r\n\t\t\t\tspResult.mpStructure=new CStruct;\r\n\t\t\t\tspResult.mpStructure->AppendStructure(pA->mpStructure);\r\n\t\t\t\tspResult.mpStructure->RemoveComponent(pB->mChecksum);\r\n\t\t\t\tspResult.mpStructure->RemoveFlag(pB->mChecksum);\r\n\t\t\t}\r\n\t\t\telse if (pB->mType==ESYMBOLTYPE_ARRAY)\r\n\t\t\t{\r\n\t\t\t\tScript::CArray *p_array=pB->mpArray;\r\n\t\t\t\tDbg_MsgAssert(p_array,(\"NULL p_array\"));\r\n\t\t\t\t\r\n\t\t\t\tif (!(p_array->GetType() == ESYMBOLTYPE_NAME || \r\n\t\t\t\t\t  p_array->GetType() == ESYMBOLTYPE_NONE)) // Allowing NONE so that empty arrays work.\r\n\t\t\t\t{\r\n\t\t\t\t\tset_error(\"Subtracting an array from a structure requires the array to be an array of names\");\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tspResult.mType=ESYMBOLTYPE_STRUCTURE;\r\n\t\t\t\t\tspResult.mpStructure=new CStruct;\r\n\t\t\t\t\tspResult.mpStructure->AppendStructure(pA->mpStructure);\r\n\t\t\t\t\t\r\n\t\t\t\t\tfor (uint32 i=0; i<p_array->GetSize(); ++i)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tspResult.mpStructure->RemoveComponent(p_array->GetChecksum(i));\r\n\t\t\t\t\t\tspResult.mpStructure->RemoveFlag(p_array->GetChecksum(i));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (pB->mType==ESYMBOLTYPE_STRUCTURE)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_STRUCTURE;\r\n\t\t\t\tspResult.mpStructure=new CStruct;\r\n\t\t\t\tspResult.mpStructure->AppendStructure(pA->mpStructure);\r\n\t\t\t\t\r\n\t\t\t\tScript::CStruct *p_struct=pB->mpStructure;\r\n\t\t\t\tDbg_MsgAssert(p_struct,(\"NULL p_struct\"));\r\n\t\t\t\tScript::CComponent *p_comp=p_struct->GetNextComponent();\r\n\t\t\t\twhile (p_comp)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (p_comp->mNameChecksum)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// If the component is named, remove all components of the same name and type.\r\n\t\t\t\t\t\tspResult.mpStructure->RemoveComponentWithType(p_comp->mNameChecksum,p_comp->mType);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if (p_comp->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// If it's an unnamed-name (ie a flag) remove all components with that name,\r\n\t\t\t\t\t\t// including flags.\r\n\t\t\t\t\t\tspResult.mpStructure->RemoveComponent(p_comp->mChecksum);\r\n\t\t\t\t\t\tspResult.mpStructure->RemoveFlag(p_comp->mChecksum);\r\n\t\t\t\t\t}\t\t\t\t\t\r\n\t\t\t\t\tp_comp=p_struct->GetNextComponent(p_comp);\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Structure minus operator requires 2nd arg to be a name, an array of names, or a structure\");\r\n\t\t\t}\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tdefault:\r\n\t\t\tset_error(\"Subtraction not supported for this type\");\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_MULTIPLY:\r\n\t\tswitch (pA->mType)\r\n\t\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\tswitch (pB->mType)\r\n\t\t\t{\r\n\t\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_INTEGER;\r\n\t\t\t\tspResult.mIntegerValue=pA->mIntegerValue*pB->mIntegerValue;\r\n\t\t\t\tbreak;\r\n\t\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\t\tspResult.mFloatValue=(float)pA->mIntegerValue*pB->mFloatValue;\r\n\t\t\t\tbreak;\r\n\t\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_VECTOR;\r\n\t\t\t\tspResult.mpVector=new CVector;\r\n\t\t\t\tspResult.mpVector->mX=(float)pA->mIntegerValue*pB->mpVector->mX;\r\n\t\t\t\tspResult.mpVector->mY=(float)pA->mIntegerValue*pB->mpVector->mY;\r\n\t\t\t\tspResult.mpVector->mZ=(float)pA->mIntegerValue*pB->mpVector->mZ;\r\n\t\t\t\tbreak;\r\n\t\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_PAIR;\r\n\t\t\t\tspResult.mpPair=new CPair;\r\n\t\t\t\tspResult.mpPair->mX=(float)pA->mIntegerValue*pB->mpPair->mX;\r\n\t\t\t\tspResult.mpPair->mY=(float)pA->mIntegerValue*pB->mpPair->mY;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tset_error(\"Second arg cannot be multiplied by an integer\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\tswitch (pB->mType)\r\n\t\t\t{\r\n\t\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\t\tspResult.mFloatValue=pA->mFloatValue*(float)pB->mIntegerValue;\r\n\t\t\t\tbreak;\r\n\t\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\t\tspResult.mFloatValue=pA->mFloatValue*pB->mFloatValue;\r\n\t\t\t\tbreak;\r\n\t\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_VECTOR;\r\n\t\t\t\tspResult.mpVector=new CVector;\r\n\t\t\t\tspResult.mpVector->mX=pA->mFloatValue*pB->mpVector->mX;\r\n\t\t\t\tspResult.mpVector->mY=pA->mFloatValue*pB->mpVector->mY;\r\n\t\t\t\tspResult.mpVector->mZ=pA->mFloatValue*pB->mpVector->mZ;\r\n\t\t\t\tbreak;\r\n\t\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_PAIR;\r\n\t\t\t\tspResult.mpPair=new CPair;\r\n\t\t\t\tspResult.mpPair->mX=pA->mFloatValue*pB->mpPair->mX;\r\n\t\t\t\tspResult.mpPair->mY=pA->mFloatValue*pB->mpPair->mY;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tset_error(\"Second arg cannot be multiplied by a float\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\tswitch (pB->mType)\r\n\t\t\t{\r\n\t\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\t\t// Take multiplication of two vectors to mean the cross-product.\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_VECTOR;\r\n\t\t\t\tspResult.mpVector=new CVector;\r\n\t\t\t\tspResult.mpVector->mX=pA->mpVector->mY*pB->mpVector->mZ-pA->mpVector->mZ*pB->mpVector->mY;\r\n\t\t\t\tspResult.mpVector->mY=pA->mpVector->mZ*pB->mpVector->mX-pA->mpVector->mX*pB->mpVector->mZ;\r\n\t\t\t\tspResult.mpVector->mZ=pA->mpVector->mX*pB->mpVector->mY-pA->mpVector->mY*pB->mpVector->mX;\r\n\t\t\t\tbreak;\r\n\t\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_VECTOR;\r\n\t\t\t\tspResult.mpVector=new CVector;\r\n\t\t\t\tspResult.mpVector->mX=pA->mpVector->mX*pB->mFloatValue;\r\n\t\t\t\tspResult.mpVector->mY=pA->mpVector->mY*pB->mFloatValue;\r\n\t\t\t\tspResult.mpVector->mZ=pA->mpVector->mZ*pB->mFloatValue;\r\n\t\t\t\tbreak;\r\n\t\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_VECTOR;\r\n\t\t\t\tspResult.mpVector=new CVector;\r\n\t\t\t\tspResult.mpVector->mX=pA->mpVector->mX*(float)pB->mIntegerValue;\r\n\t\t\t\tspResult.mpVector->mY=pA->mpVector->mY*(float)pB->mIntegerValue;\r\n\t\t\t\tspResult.mpVector->mZ=pA->mpVector->mZ*(float)pB->mIntegerValue;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tset_error(\"Vector cannot be multiplied by second arg\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\tswitch (pB->mType)\r\n\t\t\t{\r\n\t\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_PAIR;\r\n\t\t\t\tspResult.mpPair=new CPair;\r\n\t\t\t\tspResult.mpPair->mX=pA->mpPair->mX*pB->mFloatValue;\r\n\t\t\t\tspResult.mpPair->mY=pA->mpPair->mY*pB->mFloatValue;\r\n\t\t\t\tbreak;\r\n\t\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_PAIR;\r\n\t\t\t\tspResult.mpPair=new CPair;\r\n\t\t\t\tspResult.mpPair->mX=pA->mpPair->mX*(float)pB->mIntegerValue;\r\n\t\t\t\tspResult.mpPair->mY=pA->mpPair->mY*(float)pB->mIntegerValue;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tset_error(\"Pair cannot be multiplied by second arg\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tset_error(\"Multiplication not supported for this type\");\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_DIVIDE:\r\n\t\tif (pB->mType==ESYMBOLTYPE_INTEGER)\r\n\t\t{\r\n\t\t\tif (pB->mIntegerValue==0)\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Integer division by zero\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if (pB->mType==ESYMBOLTYPE_FLOAT)\r\n\t\t{\r\n\t\t\tif (pB->mFloatValue==0.0f)\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Float division by zero\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tswitch (pA->mType)\r\n\t\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_INTEGER;\r\n\t\t\t\tspResult.mIntegerValue=pA->mIntegerValue/pB->mIntegerValue;\r\n\t\t\t}\r\n\t\t\telse if (pB->mType==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\t\tspResult.mFloatValue=(float)pA->mIntegerValue/pB->mFloatValue;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Integer cannot be divided by second arg\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\t\tspResult.mFloatValue=pA->mFloatValue/(float)pB->mIntegerValue;\r\n\t\t\t}\r\n\t\t\telse if (pB->mType==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\t\tspResult.mFloatValue=pA->mFloatValue/pB->mFloatValue;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Float cannot be divided by second arg\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_VECTOR;\r\n\t\t\t\tspResult.mpVector=new CVector;\r\n\t\t\t\tspResult.mpVector->mX=pA->mpVector->mX/(float)pB->mIntegerValue;\r\n\t\t\t\tspResult.mpVector->mY=pA->mpVector->mY/(float)pB->mIntegerValue;\r\n\t\t\t\tspResult.mpVector->mZ=pA->mpVector->mZ/(float)pB->mIntegerValue;\r\n\t\t\t}\r\n\t\t\telse if (pB->mType==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_VECTOR;\r\n\t\t\t\tspResult.mpVector=new CVector;\r\n\t\t\t\tspResult.mpVector->mX=pA->mpVector->mX/pB->mFloatValue;\r\n\t\t\t\tspResult.mpVector->mY=pA->mpVector->mY/pB->mFloatValue;\r\n\t\t\t\tspResult.mpVector->mZ=pA->mpVector->mZ/pB->mFloatValue;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Vector cannot be divided by second arg\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\tif (pB->mType==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_PAIR;\r\n\t\t\t\tspResult.mpPair=new CPair;\r\n\t\t\t\tspResult.mpPair->mX=pA->mpPair->mX/(float)pB->mIntegerValue;\r\n\t\t\t\tspResult.mpPair->mY=pA->mpPair->mY/(float)pB->mIntegerValue;\r\n\t\t\t}\r\n\t\t\telse if (pB->mType==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\tspResult.mType=ESYMBOLTYPE_PAIR;\r\n\t\t\t\tspResult.mpPair=new CPair;\r\n\t\t\t\tspResult.mpPair->mX=pA->mpPair->mX/pB->mFloatValue;\r\n\t\t\t\tspResult.mpPair->mY=pA->mpPair->mY/pB->mFloatValue;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Pair cannot be divided by second arg\");\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tset_error(\"Division not supported for this type\");\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_DOT:\r\n\t\tswitch (pA->mType)\r\n\t\t{\r\n\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\tif (pB->mType!=ESYMBOLTYPE_VECTOR)\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Vector can only be dot producted with another vector\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\tspResult.mFloatValue=pA->mpVector->mX*pB->mpVector->mX+\r\n\t\t\t\t\t\t\t\t pA->mpVector->mY*pB->mpVector->mY+\r\n\t\t\t\t\t\t\t\t pA->mpVector->mZ*pB->mpVector->mZ;\r\n\t\t\tbreak;\t\r\n\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\tif (pB->mType!=ESYMBOLTYPE_PAIR)\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Pair can only be dot producted with another pair\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tspResult.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\tspResult.mFloatValue=pA->mpPair->mX*pB->mpPair->mX+\r\n\t\t\t\t\t\t\t\t pA->mpPair->mY*pB->mpPair->mY;\r\n\t\t\tbreak;\t\r\n\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t{\r\n\t\t\tif (pB->mType!=ESYMBOLTYPE_NAME)\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Structure dot operator requires 2nd arg to be a name\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tDbg_MsgAssert(pA->mpStructure,(\"NULL pA->mpStructure\"));\r\n\t\t\tCComponent *p_found=pA->mpStructure->FindNamedComponentRecurse(pB->mChecksum);\r\n\t\t\tif (p_found)\r\n\t\t\t{\r\n\t\t\t\tCopyComponent(&spResult,p_found);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tdefault:\r\n\t\t\tset_error(\"Dot product not supported for this type\");\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_STARTARRAY:\r\n\t{\r\n\t\tif (pA->mType!=ESYMBOLTYPE_ARRAY)\r\n\t\t{\r\n\t\t\tset_error(\"Array element operator not supported for this type\");\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tDbg_MsgAssert(pA->mpArray,(\"NULL pA->mpArray\"));\r\n\t\t\r\n\t\tif (pB->mType!=ESYMBOLTYPE_INTEGER)\r\n\t\t{\r\n\t\t\tset_error(\"[] index must be an integer\");\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tuint32 index=pB->mIntegerValue;\r\n\t\t\r\n\t\tif (index>=pA->mpArray->GetSize())\r\n\t\t{\r\n\t\t\tset_error(\"[] index out of range\");\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tCopyArrayElementIntoComponent(pA->mpArray,index,&spResult);\r\n\t\tif (spResult.mType==ESYMBOLTYPE_NONE)\r\n\t\t{\r\n\t\t\tset_error(\"Array type cannot be accessed using [] yet ...\");\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t\t\t\t\r\n\t\tbreak;\r\n\t}\t\r\n\tdefault:\r\n\t\tset_error(\"Operator not supported\");\r\n\t\tbreak;\r\n\t}\r\n\t\t\t\t\r\n\tCleanUpComponent(pA);\r\n\tCleanUpComponent(pB);\r\n\tpA->mType=spResult.mType;\r\n\tpA->mUnion=spResult.mUnion;\r\n\tspResult.mType=ESYMBOLTYPE_NONE;\r\n\tspResult.mUnion=0;\r\n\t\r\n\t--m_value_stack_top;\r\n\t\r\n\tmp_operator_stack[m_operator_stack_top].mOperator=NOP;\r\n\tif (m_operator_stack_top)\r\n\t{\r\n\t\t--m_operator_stack_top;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_got_operators=false;\r\n\t}\t\r\n\t\r\n\t//printf(\"m_operator_stack_top=%d\\n\",m_operator_stack_top);\r\n}\r\n\r\nvoid CExpressionEvaluator::add_new_operator(EScriptToken op)\r\n{\r\n\t++m_operator_stack_top;\r\n\tif (m_operator_stack_top>=OPERATOR_STACK_SIZE)\r\n\t{\r\n\t\tset_error(\"Operator stack overflow\");\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tmp_operator_stack[m_operator_stack_top].mOperator=op;\t\r\n\tmp_operator_stack[m_operator_stack_top].mParenthesesCount=0;\r\n\t\r\n\tm_got_operators=true;\r\n}\r\n\r\nvoid CExpressionEvaluator::Input(EScriptToken op)\r\n{\r\n\twhile (m_got_operators)\r\n\t{\r\n\t\tif (mp_operator_stack[m_operator_stack_top].mParenthesesCount)\r\n\t\t{\r\n\t\t\t// The most recent operator is 'protected' by parentheses, \r\n\t\t\t// so do not execute it.\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\r\n\t\tif (sSameOrLowerPrecedence(op,mp_operator_stack[m_operator_stack_top].mOperator))\r\n\t\t{\r\n\t\t\t// The new operator has the same or lower precedence than the last, so execute the\r\n\t\t\t// last operator.\r\n\t\t\t// Ie, in 2*3+5, we execute the * once we get the +\r\n\t\t\texecute_operation();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t}\t\r\n\t\t\t\t\r\n\t// Insert the new operator.\r\n\tadd_new_operator(op);\r\n}\r\n\r\nvoid CExpressionEvaluator::Input(const CComponent *p_value)\r\n{\r\n\tif (m_value_stack_top==0 && mp_value_stack[0].mType==ESYMBOLTYPE_NONE)\r\n\t{\r\n\t}\r\n\telse\r\n\t{\r\n\t\t++m_value_stack_top;\r\n\t\tif (m_value_stack_top>=VALUE_STACK_SIZE)\r\n\t\t{\r\n\t\t\tset_error(\"Value stack overflow\");\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tDbg_MsgAssert(p_value,(\"NULL p_value\"));\r\n\tCopyComponent(&mp_value_stack[m_value_stack_top],p_value);\r\n}\r\n\r\nvoid CExpressionEvaluator::OpenParenthesis()\r\n{\r\n\t++mp_operator_stack[m_operator_stack_top].mParenthesesCount;\r\n}\r\n\r\nvoid CExpressionEvaluator::CloseParenthesis()\r\n{\r\n\twhile (true)\r\n\t{\r\n\t\tif (mp_operator_stack[m_operator_stack_top].mParenthesesCount)\r\n\t\t{\r\n\t\t\t--mp_operator_stack[m_operator_stack_top].mParenthesesCount;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\texecute_operation();\r\n\t\t\tif (mp_error_string)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t}\t\r\n}\r\n\r\nbool CExpressionEvaluator::GetResult(CComponent *p_result)\r\n{\r\n\tDbg_MsgAssert(p_result,(\"NULL p_result\"));\r\n\tDbg_MsgAssert(p_result->mType==ESYMBOLTYPE_NONE,(\"Non-empty component sent to GetResult, type = %s\",GetTypeName(p_result->mType)));\r\n\tDbg_MsgAssert(p_result->mUnion==0,(\"CComponent::mUnion not zero, type = %s\",GetTypeName(p_result->mType)));\r\n\t\r\n\twhile (true)\r\n\t{\r\n\t\tif (mp_operator_stack[m_operator_stack_top].mParenthesesCount)\r\n\t\t{\r\n\t\t\tset_error(\"Not enough close parentheses\");\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tif (m_value_stack_top==0)\r\n\t\t{\r\n\t\t\tif (mp_operator_stack[0].mOperator!=0 || m_operator_stack_top)\r\n\t\t\t{\r\n\t\t\t\tset_error(\"Too many operators in expression\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tCopyComponent(p_result,&mp_value_stack[0]);\r\n\t\t\tCleanUpComponent(&mp_value_stack[0]);\r\n\t\t\treturn true;\r\n\t\t}\t\t\t\r\n\t\t\r\n\t\texecute_operation();\r\n\t\tif (mp_error_string)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nconst char *CExpressionEvaluator::GetError()\r\n{\r\n\treturn mp_error_string;\r\n}\r\n\r\n} // namespace Script\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/eval.h",
    "content": "#ifndef\t__SCRIPTING_EVAL_H\r\n#define\t__SCRIPTING_EVAL_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef\t__SCRIPTING_COMPONENT_H\r\n#include <gel/scripting/component.h>\r\n#endif\r\n\r\n#ifndef __SCRIPTING_TOKENS_H\r\n#include <gel/scripting/tokens.h>\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\r\n#define EVALUATOR_STRING_BUF_SIZE 200\r\n\r\n#define NOP ((EScriptToken)0)\r\n\r\n#define VALUE_STACK_SIZE 20\r\n#define OPERATOR_STACK_SIZE VALUE_STACK_SIZE\r\n\r\nstruct SOperator\r\n{\r\n\tEScriptToken mOperator;\r\n\tint mParenthesesCount;\r\n};\r\n\t\r\nclass CExpressionEvaluator : public Spt::Class\r\n{\r\n\tCComponent mp_value_stack[VALUE_STACK_SIZE];\r\n\tint m_value_stack_top;\r\n\t\r\n\tSOperator mp_operator_stack[OPERATOR_STACK_SIZE];\r\n\tint m_operator_stack_top;\r\n\tbool m_got_operators;\r\n\r\n\t// mp_token points to the position in the qb file being parsed.\r\n\t// The expression evaluator itself never does any parsing of the qb data,\r\n\t// it only stores this so that it can print the line number if an error occurs.\r\n\tuint8 *mp_token;\t\r\n\tconst char *mp_error_string;\r\n\t\r\n\t// Sometimes, if an expression contains an error such as a missing parameter value, we\r\n\t// do not want it to assert or print a warning message, but just return a void value instead.\r\n\t// For example, when scanning through all the scripts looking for calls to EndGap, the\r\n\t// function AddComponentsUntilEndOfLine is used, but often parameters are missing then\r\n\t// because the script is not being run, just scanned through. Don't wan't it to stop with\r\n\t// an error in that case.\r\n\tbool m_errors_enabled;\r\n\t\r\n\tvoid set_error(const char *p_error);\r\n\tvoid execute_operation();\r\n\tvoid add_new_operator(EScriptToken op);\r\n\t\t\t\t\t\t\t\t\t \r\npublic:\t\r\n\tCExpressionEvaluator();\r\n\t~CExpressionEvaluator();\r\n\t\r\n\tvoid EnableErrorChecking() {m_errors_enabled=true;}\r\n\tvoid DisableErrorChecking() {m_errors_enabled=false;}\r\n\tbool ErrorCheckingEnabled() {return m_errors_enabled;}\r\n\t\t\t\t\t\t\t \r\n\t// These are not defined, just declared so that the code won't link if they\r\n\t// are attempted to be used.\r\n\tCExpressionEvaluator( const CExpressionEvaluator& rhs );\r\n\tCExpressionEvaluator& operator=( const CExpressionEvaluator& rhs );\r\n\r\n\tvoid Clear();\t\r\n\tvoid ClearIfNeeded();\r\n\tvoid Input(EScriptToken op);\r\n\tvoid Input(const CComponent *p_value);\r\n\tvoid OpenParenthesis();\r\n\tvoid CloseParenthesis();\r\n\tbool GetResult(CComponent *p_result);\r\n\tconst char *GetError();\r\n\tvoid SetTokenPointer(uint8 *p_token);\r\n};\r\n\t\r\n} // namespace Script\r\n\r\n#endif // #ifndef\t__SCRIPTING_EVAL_H\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/file.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// file.cpp\t\tKSH 31 Oct 2001\r\n//\r\n// Functions for loading and unloading qb files.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <gel/scripting/file.h>\r\n#include <gel/scripting/parse.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <core/crc.h> // For Crc::GenerateCRCFromString\r\n#include <sys/file/pip.h>\r\n\r\nnamespace Script\r\n{\r\n// TODO: Need another LoadQB in the game-specific script namespace, which will call this LoadQB\r\n// and then do any game-specific stuff that needs to be done when a qb is reloaded, such as \r\n// generating the node name hash table & prefix info, reloading the skater exceptions, updating the decks on\r\n// the skateshop wall, etc...\r\n\r\nvoid restart_dirty_scripts()\r\n{\r\n\t// For each symbol, check if it got reloaded by the above load, and if it did and it is a script\r\n\t// then run through all the existing CScript's restarting those that referred to it.\r\n\t// This is essential, because otherwise those CScripts' program counter pointers will now be invalid.\r\n\tCSymbolTableEntry *p_sym=GetNextSymbolTableEntry();\r\n\twhile (p_sym)\r\n\t{\r\n\t\tif (p_sym->mGotReloaded && p_sym->mType==ESYMBOLTYPE_QSCRIPT)\r\n\t\t{\r\n\t\t\tCScript *p_script=GetNextScript();\r\n\t\t\twhile (p_script)\r\n\t\t\t{\r\n\t\t\t\tif (p_script->RefersToScript(p_sym->mNameChecksum))\r\n\t\t\t\t{\r\n\t\t\t\t\tp_script->Restart();\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tp_script=GetNextScript(p_script);\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\t// Reset the reloaded flag, otherwise it will stick on forever.\r\n\t\t\tp_sym->mGotReloaded=false;\r\n\t\t}\r\n\t\tp_sym=GetNextSymbolTableEntry(p_sym);\r\n\t}\t\t\r\n}\r\n\r\n// Loads a QB file.\r\n// It will open the file, load it into memory and parse it, creating all the\r\n// symbols (scripts, arrays, integers etc) defined within in.\r\nvoid LoadQB(const char *p_fileName, EBoolAssertIfDuplicateSymbols assertIfDuplicateSymbols)\r\n{\r\n\tDbg_MsgAssert(p_fileName,(\"NULL p_fileName\"));\r\n#ifndef __PLAT_NGC__\r\n\tDbg_MsgAssert(strcmp(p_fileName+strlen(p_fileName)-3,\".qb\")==0,(\"File does not have extension .qb. File %s\",p_fileName));\r\n#endif __PLAT_NGC__\r\n\r\n\t// Mick - Pip::Load is not going to load it from a Pip::Pre, just a regular pre\r\n\t// so I'm sticking it on the top-down heap to avoid fragmentation\t\t\t\t\t\t\t  \r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tuint8 *p_qb=(uint8*)Pip::Load(p_fileName);\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t// Parse the QB, which creates all the symbols defined within it.\r\n\tParseQB(p_fileName,p_qb,assertIfDuplicateSymbols);\r\n\t\r\n\tPip::Unload(p_fileName);\t\r\n\r\n\trestart_dirty_scripts();\r\n}\r\n\r\n// Loads a QB file from memory\r\nvoid LoadQBFromMemory(const char* p_fileName, uint8* p_qb, EBoolAssertIfDuplicateSymbols assertIfDuplicateSymbols)\r\n{\r\n\t// even though there's no actually filename,\r\n\t// we'd still need a dummy string, which will\r\n\t// be used for printing up Assert messages...\r\n\r\n\tDbg_MsgAssert(p_fileName,(\"NULL p_fileName\"));\r\n#ifndef __PLAT_NGC__\r\n\tDbg_MsgAssert(strcmp(p_fileName+strlen(p_fileName)-3,\".qb\")==0,(\"File does not have extension .qb. File %s\",p_fileName));\r\n#endif __PLAT_NGC__\r\n\r\n\t// do not create the hash table if it's not\r\n\t// the node array (it's a 50K memory hog on\r\n\t// the script heap, and it's really only\r\n\t// needed for doing prefix stuff anyway)\r\n\tParseQB(p_fileName,p_qb,assertIfDuplicateSymbols,false);\r\n\r\n\tRemoveChecksumNameLookupHashTable();\r\n\r\n\trestart_dirty_scripts();\r\n}\r\n\r\n// TODO: Need another UnloadQB in the game-specific script namespace, which will call this UnloadQB\r\n// and then do any game-specific stuff that needs to be done when a qb is unloaded, such as \r\n// resetting the node name hash table & prefix info.\r\n\r\n// Deletes all the symbols that were defined in the passed QB file.\r\nvoid UnloadQB(uint32 fileNameChecksum)\r\n{\r\n\t// Do nothing if the checksum is zero. This is essential, because symbols\r\n\t// that have a mSourceFileNameChecksum of 0 are those that did not come\r\n\t// from a qb file, ie C-functions. These must never be deleted.\r\n\tif (!fileNameChecksum)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\t// Scan through all the symbols in the symbol table.\r\n\tCSymbolTableEntry *p_sym=GetNextSymbolTableEntry();\r\n\twhile (p_sym)\r\n\t{\t\t\t\t\t\t\t\t\t\t\t\r\n\t\tif (p_sym->mSourceFileNameChecksum==fileNameChecksum)\r\n\t\t{\r\n\t\t\t// This symbol was defined in the passed qb file, so remove it.\r\n\t\t\tCleanUpAndRemoveSymbol(p_sym);\r\n\t\t\t// Need to start checking from the start of the list again rather than storing\r\n\t\t\t// a p_next pointer before calling CleanUpAndRemoveSymbol.\r\n\t\t\t// This is because CleanUpAndRemoveSymbol may cause the symbol above to move down,\r\n\t\t\t// invalidating p_next.\r\n\t\t\t// SPEEDOPT Starting again from the start of the list is inefficient though, because\r\n\t\t\t// it may have to scan through thousands of symbols just to delete one, and may have to\r\n\t\t\t// delete say a hundred. Optimize later. (Seems fast enough at the moment)\r\n\t\t\tp_sym=NULL;\r\n\t\t}\t\r\n\t\tp_sym=GetNextSymbolTableEntry(p_sym);\r\n\t}\r\n\t\r\n\t// Scan through all the existing CScripts stopping any that are referring to a script\r\n\t// that got deleted above.\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tif (!p_script->AllScriptsInCallstackStillExist())\r\n\t\t{\r\n\t\t\tp_script->ClearScript();\r\n\t\t\tp_script->ClearEventHandlerTable();\r\n\t\t}\r\n\t\r\n\t\tp_script=GetNextScript(p_script);\r\n\t}\t\r\n}\r\n\r\n// Note: There is no Script::UnloadQB(const char *p_fileName)\r\n// This is because we may not want to do a GenerateCRCFromString on the p_fileName as it stands.\r\n// We may want to make sure the file name is prefixed with the complete path before calculating\r\n// the crc.\r\n// Since the path is game specific, the code to do this is in the SkateScript namespace.\r\n// See SkateScript::UnloadQB(const char *p_fileName) and SkateScript::GenerateFileNameChecksum\r\n\r\n} // namespace Script\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/file.h",
    "content": "#ifndef\t__SCRIPTING_FILE_H\r\n#define\t__SCRIPTING_FILE_H\r\n\r\n#ifndef\t__SCRIPTING_SCRIPTDEFS_H\r\n#include <gel/scripting/scriptdefs.h> // For enums\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\t\r\nvoid LoadQB(const char *p_fileName, \r\n\t\t\tEBoolAssertIfDuplicateSymbols assertIfDuplicateSymbols=NO_ASSERT_IF_DUPLICATE_SYMBOLS);\r\nvoid LoadQBFromMemory(const char* p_fileName, uint8* p_qb, EBoolAssertIfDuplicateSymbols assertIfDuplicateSymbols);\r\nvoid UnloadQB(uint32 fileNameChecksum);\r\n\r\n} // namespace Script\r\n\r\n#endif // #ifndef\t__SCRIPTING_FILE_H\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/init.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// init.cpp\t\tKSH 19 Oct 2001\r\n//\r\n// Functions for initialising various script stuff.\r\n// \r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <gel/scripting/init.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/string.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/parse.h>\r\n#include <gel/scripting/scriptcache.h>\r\n#include <core/crc.h>\r\n\r\nnamespace Script\r\n{\r\n\r\n// MEMOPT This is where all the pools of script things get allocated.\r\nvoid AllocatePools()\r\n{\r\n\t// Sets up the checksum name-lookup hash table.\r\n\t// On the PS2 this does not actually do any dynamic allocation, but uses the space set aside\r\n\t// in NGPS.lk and defined by _script_start and _script_end\r\n\t// On other platforms it does dynamically allocate the space.\r\n\t// The function will not do anything if Config::GotExtraMemory() returns false.\r\n\tMem::PushMemProfile(\"AllocateChecksumNameLookupTables\");\r\n\tAllocateChecksumNameLookupTables();\r\n\tMem::PopMemProfile();\r\n\t\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\r\n\t#ifndef __PLAT_WN32__\r\n\t\r\n\t#ifdef NO_SCRIPT_CACHING\r\n\t#else\r\n\tMem::PushMemProfile(\"CScriptCacheEntry\");\r\n\t// 32ish bytes each\r\n\tCScriptCacheEntry::SCreatePool(MAX_DECOMPRESSED_SCRIPTS, \"CScriptCacheEntry\");\r\n\tMem::PopMemProfile();\r\n\t#endif\r\n\t\t\r\n\tMem::PushMemProfile(\"CComponent and Reserve CComponent\");\r\n\t\r\n\t// 16 bytes each\r\n\tCComponent::SCreatePool(84000, \"CComponent\");  // Mick:  increased by 2000 (82000 to 84000) to account for gap lists\r\n\r\n\tMem::PopMemProfile();\r\n\t\r\n\r\n\tMem::PushMemProfile(\"CStruct\");\r\n\t// 4 bytes each  (Actually 8, or 12 with asserts)\r\n\tCStruct::SCreatePool(18800, \"CStruct\");\r\n\tMem::PopMemProfile();\r\n\t\r\n\t// 12 bytes each  (Actually 16)\r\n\tMem::PushMemProfile(\"CVector\");\r\n\tCVector::SCreatePool(9600, \"CVector\");\r\n\tMem::PopMemProfile();\r\n\t\r\n\t// 8 bytes each\t  (Actually 12)\r\n\tMem::PushMemProfile(\"CPair\");\r\n\tCPair::SCreatePool(1000, \"CPair\");\t // Mick: was 5000, but only used 308 at last count\r\n\tMem::PopMemProfile();\r\n\t\r\n\t// 12 bytes each\r\n\tMem::PushMemProfile(\"CArray\");\r\n\t//CArray::SCreatePool(6000, \"CArray\");\r\n\tCArray::SCreatePool(7500, \"CArray\");\r\n\tMem::PopMemProfile();\r\n\t\r\n\t\r\n\t// 12 bytes each (actually 16)\r\n\tMem::PushMemProfile(\"CSymbolTableEntry\");\r\n\tCSymbolTableEntry::SCreatePool(8500, \"CSymbolTableEntry\");\r\n\tMem::PopMemProfile();\r\n\r\n\tMem::PushMemProfile(\"CScript\");\r\n\t// 1080 bytes each, bloody hell (Actually ~1238!!!)\r\n\tCScript::SCreatePool(MAX_CSCRIPTS, \"CScript\");\r\n\tMem::PopMemProfile();\r\n\r\n\tMem::PushMemProfile(\"CStoredRandom\");\r\n\t// 80 bytes each (100)\r\n\tCStoredRandom::SCreatePool(MAX_STORED_RANDOMS,\"CStoredRandom\");\r\n\tMem::PopMemProfile();\r\n\t#endif\r\n\r\n\r\n\t// This will create a further 4096 CSymbolTableEntry's, but as a contiguous array.\r\n//\tMem::PushMemProfile(\"CreateSymbolHashTable\");\r\n//\tCreateSymbolHashTable();\r\n//\tMem::PopMemProfile();\r\n\t\r\n\t// 60500 bytes was needed for foreign languages on THPS3, 48000 for English.\r\n\t// 4000 is the max number of strings.\r\n\t//AllocatePermanentStringHeap(60500,4000);\r\n\tMem::PushMemProfile(\"AllocatePermanentStringHeap\");\r\n\tAllocatePermanentStringHeap(160000,7000);\t\r\n\tMem::PopMemProfile();\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\nvoid DeallocatePools()\r\n{\r\n\tDeallocatePermanentStringHeap();\r\n\tDestroySymbolHashTable();\r\n\t\r\n\t#ifndef __PLAT_WN32__\r\n\tCScript::SRemovePool();\r\n\tCSymbolTableEntry::SRemovePool();\r\n\tCArray::SRemovePool();\r\n\tCStruct::SRemovePool();\r\n\tCPair::SRemovePool();\r\n\tCVector::SRemovePool();\r\n\tCComponent::SRemovePool();\r\n\t#endif\r\n\t\t\r\n\tDeallocateChecksumNameLookupTables();\r\n}\r\n\r\n// Adds all the c-functions listed in the passed array to the symbol table.\r\nvoid RegisterCFunctions(SCFunction *p_cFunctions, uint32 numFunctions)\r\n{\r\n\tDbg_MsgAssert(p_cFunctions,(\"NULL p_cFunctions\"));\r\n\t\r\n\tfor (uint32 i=0; i<numFunctions; ++i)\r\n\t{\r\n\t\tuint32 name_checksum=Crc::GenerateCRCFromString(p_cFunctions[i].mpName);\r\n\r\n\t\tAddChecksumName(name_checksum,p_cFunctions[i].mpName);\r\n\t\t\r\n\t\t// Check that there is no symbol already with this name.\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tCSymbolTableEntry *p_existing_entry=LookUpSymbol(name_checksum);\r\n\t\tDbg_MsgAssert(p_existing_entry==NULL,(\r\n\t\t\t\t\t  \"The C-function named '%s' is already defined in the file %s where it has type '%s'\",\r\n\t\t\t\t\t  p_cFunctions[i].mpName,\r\n\t\t\t\t\t  p_existing_entry->mType==ESYMBOLTYPE_CFUNCTION || p_existing_entry->mType==ESYMBOLTYPE_MEMBERFUNCTION ? \"ftables.cpp\":FindChecksumName(p_existing_entry->mSourceFileNameChecksum),\r\n\t\t\t\t\t  GetTypeName(p_existing_entry->mType)));\r\n\t\t#endif\t\t\r\n\t\t\r\n\t\tCSymbolTableEntry *p_new=CreateNewSymbolEntry(name_checksum);\r\n\t\tDbg_MsgAssert(p_new,(\"NULL p_new ??\"));\r\n\t\r\n\t\tp_new->mType=ESYMBOLTYPE_CFUNCTION;\r\n\t\tp_new->mpCFunction=p_cFunctions[i].mpFunction;\r\n\t\t// Note: Not setting p_new->mSourceFileNameChecksum to anything, just leaving it as 0, since there is no\r\n\t\t// source qb file.\r\n\t}\r\n}\r\n\r\n// Adds all the member functions listed in the passed array to the symbol table.\r\nvoid RegisterMemberFunctions(const char **pp_memberFunctions, uint32 numFunctions)\r\n{\r\n\tDbg_MsgAssert(pp_memberFunctions,(\"NULL pp_memberFunctions\"));\r\n\t\r\n\tfor (uint32 i=0; i<numFunctions; ++i)\r\n\t{\r\n\t\tuint32 name_checksum=Crc::GenerateCRCFromString(pp_memberFunctions[i]);\r\n\t\tAddChecksumName(name_checksum,pp_memberFunctions[i]);\r\n\t\t\r\n\t\t// Check that there is no symbol already with this name.\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tCSymbolTableEntry *p_existing_entry=LookUpSymbol(name_checksum);\r\n\t\tDbg_MsgAssert(p_existing_entry==NULL,(\r\n\t\t\t\t\t  \"The member function named '%s' is already defined in the file %s where it has type '%s'\",\r\n\t\t\t\t\t  pp_memberFunctions[i],\r\n\t\t\t\t\t  p_existing_entry->mType==ESYMBOLTYPE_CFUNCTION || p_existing_entry->mType==ESYMBOLTYPE_MEMBERFUNCTION ? \"ftables.cpp\":FindChecksumName(p_existing_entry->mSourceFileNameChecksum),\r\n\t\t\t\t\t  GetTypeName(p_existing_entry->mType)));\r\n\t\t#endif\r\n\t\t\r\n\t\tCSymbolTableEntry *p_new=CreateNewSymbolEntry(name_checksum);\r\n\t\tDbg_MsgAssert(p_new,(\"NULL p_new ??\"));\r\n\t\r\n\t\tp_new->mType=ESYMBOLTYPE_MEMBERFUNCTION;\r\n\t\t// No need to set the value to anything, since the name of the symbol specifies the member function.\r\n\t\t\r\n\t\t// Note: Not setting p_new->mSourceFileNameChecksum to anything, just leaving it as 0, since there is no\r\n\t\t// source qb file.\r\n\t}\r\n}\r\n\r\n} // namespace Script\r\n"
  },
  {
    "path": "Code/Gel/Scripting/init.h",
    "content": "#ifndef\t__SCRIPTING_INIT_H\r\n#define\t__SCRIPTING_INIT_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\r\nenum\r\n{\r\n\tMAX_CSCRIPTS=300, // If this changes, the script debugger (qdebug.exe) will need to be rebuilt.\r\n};\r\n\t\r\nclass CStruct;\r\nclass CScript;\r\nstruct SCFunction\r\n{\r\n    const char *mpName;\r\n    bool (*mpFunction)(Script::CStruct *, Script::CScript *);\r\n};\r\n\r\nvoid AllocatePools();\r\nvoid DeallocatePools();\r\nvoid RegisterCFunctions(SCFunction *p_cFunctions, uint32 numFunctions);\r\nvoid RegisterMemberFunctions(const char **pp_memberFunctions, uint32 numFunctions);\r\n\r\n} // namespace Script\r\n\r\n#endif // #ifndef __SCRIPTING_INIT_H\r\n"
  },
  {
    "path": "Code/Gel/Scripting/parse.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// parse.cpp\t\tKSH 23 Oct 2001\r\n//\r\n// Functions for parsing qb files.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <gel/scripting/parse.h>\r\n#include <gel/scripting/tokens.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/string.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/eval.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/scriptcache.h>\r\n#include <gel/scripting/script.h>\r\n#include <core/math/math.h> // For Mth::Rnd and Mth::Rnd2\r\n#include <core/crc.h> // For Crc::GenerateCRCFromString\r\n#include <core/compress.h>\r\n\r\n#ifdef __PLAT_NGC__\r\n#include <sys/ngc/p_aram.h>\r\n#include <sys/ngc/p_dma.h>\r\n#endif\t\t// __PLAT_NGC__\r\n\r\nDefinePoolableClass(Script::CStoredRandom);\r\n\r\nnamespace Script\r\n{\r\n\r\nclass CScript;\r\n// Declaring this seperately rather than including script.h to avoid a cyclic dependency.\r\n// The full class declaration of CScript is not required.\r\nextern CScript *GetCurrentScript();\r\n\r\nstatic uint8 *sCalculateRandomRange(uint8 *p_token, CComponent *p_comp, bool useRnd2);\r\nstatic uint8 *sSkipType(uint8 *p_token);\r\nstatic bool   sIsEndOfLine(const uint8 *p_token);\r\nstatic uint8 *sInitArrayFromQB(CArray *p_dest, uint8 *p_token, CStruct *p_args=NULL);\r\nstatic uint8 *sAddComponentFromQB(CStruct *p_dest, uint32 nameChecksum, uint8 *p_token, CStruct *p_args=NULL);\r\nstatic uint8 *sAddComponentsWithinCurlyBraces(CStruct *p_dest, uint8 *p_token, CStruct *p_args=NULL);\r\nstatic CSymbolTableEntry *sCreateScriptSymbol(uint32 nameChecksum, uint32 contentsChecksum, const uint8 *p_data, uint32 size, const char *p_fileName);\r\nstatic uint8 *sCreateSymbolOfTheFormNameEqualsValue(uint8 *p_token, const char *p_fileName, EBoolAssertIfDuplicateSymbols assertIfDuplicateSymbols);\r\nstatic CStoredRandom *sFindStoredRandom(const uint8 *p_token, EScriptToken type, int numItems);\r\nstatic CStoredRandom *sCreateNewStoredRandom();\r\n\r\nstatic CStoredRandom *sp_first_stored_random=NULL;\r\nstatic CStoredRandom *sp_last_stored_random=NULL;\r\nstatic int s_num_stored_randoms=0;\r\n\r\nstatic uint32 s_qb_being_parsed=0;\r\n\r\n// The SkipToken function is in skiptoken.cpp, so that it can also be included in PC code,\r\n// such as qcomp.\r\n#include <gel/scripting/skiptoken.cpp>\r\n\r\n#ifdef __NOPT_ASSERT__\r\nvoid CheckForPossibleInfiniteLoops(uint32 scriptName, uint8 *p_token, const char *p_fileName)\r\n{\r\n\t#define MAX_NESTED_LOOPS 100\r\n\tbool loop_is_ok[MAX_NESTED_LOOPS];\r\n\tint loop_index=0;\r\n\tfor (int i=0; i<MAX_NESTED_LOOPS; ++i)\r\n\t{\r\n\t\tloop_is_ok[i]=false;\r\n\t}\t\r\n\r\n\tScript::CArray *p_ok_scripts=Script::GetArray(CRCD(0x8b860fef,\"DoNotAssertForInfiniteLoopsInTheseScripts\"));\r\n\tScript::CArray *p_blocking_functions=Script::GetArray(CRCD(0x215d13b9,\"BlockingFunctions\"));\r\n\t\r\n\t\t\t\r\n\twhile (*p_token!=ESCRIPTTOKEN_KEYWORD_ENDSCRIPT) \r\n\t{\r\n\t\tswitch (*p_token)\r\n\t\t{\r\n\t\t\tcase ESCRIPTTOKEN_KEYWORD_BEGIN:\r\n\t\t\t\tloop_is_ok[loop_index++]=false; // It's guilty until proven innocent!\r\n\t\t\t\tDbg_MsgAssert(loop_index<=100,(\"Too many nested loops\"));\r\n\t\t\t\tp_token=SkipToken(p_token);\r\n\t\t\t\tbreak;\r\n\t\t\tcase ESCRIPTTOKEN_KEYWORD_BREAK:\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(loop_index,(\"Zero loop_index\"));\r\n\t\t\t\tint i=loop_index-1;\r\n\t\t\t\twhile (i>=0)\r\n\t\t\t\t{\r\n\t\t\t\t\tloop_is_ok[i]=true;\r\n\t\t\t\t\t--i;\r\n\t\t\t\t}\t\r\n\t\t\t\tp_token=SkipToken(p_token);\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase ESCRIPTTOKEN_KEYWORD_REPEAT:\r\n\t\t\t\tp_token=SkipToken(p_token);\r\n\t\t\t\t\r\n\t\t\t\tDbg_MsgAssert(loop_index,(\"Zero loop_index\"));\r\n\t\t\t\tif (*p_token==ESCRIPTTOKEN_ENDOFLINE || *p_token==ESCRIPTTOKEN_ENDOFLINENUMBER)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!loop_is_ok[loop_index-1])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbool allow=false;\r\n\t\t\t\t\t\tif (p_ok_scripts)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tfor (uint32 i=0; i<p_ok_scripts->GetSize(); ++i)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif (p_ok_scripts->GetChecksum(i)==scriptName)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tallow=true;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif (allow)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tDbg_MsgAssert(0, (\"Warning! Possible infinite loop: Line %d of %s\\n\",Script::GetLineNumber(p_token),p_fileName));\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// If repeat is not followed by an end-of-line then it is probably followed by some\r\n\t\t\t\t\t// count value, so it is not an infinite loop.\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t--loop_index;\t\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase ESCRIPTTOKEN_NAME:\r\n\t\t\t{\r\n\t\t\t\t++p_token;\r\n\t\t\t\tuint32 name=Read4Bytes(p_token).mChecksum;\r\n\t\t\t\tp_token+=4;\r\n\t\t\t\t\r\n\t\t\t\tif (p_blocking_functions)\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 *p_function_names=p_blocking_functions->GetArrayPointer();\r\n\t\t\t\t\tuint32 size=p_blocking_functions->GetSize();\r\n\t\t\t\t\t\r\n\t\t\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (name == *p_function_names++)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif (loop_index)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tint i=loop_index-1;\r\n\t\t\t\t\t\t\t\twhile (i>=0)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tloop_is_ok[i]=true;\r\n\t\t\t\t\t\t\t\t\t--i;\r\n\t\t\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\t\t\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\tdefault:\r\n\t\t\t\tp_token=SkipToken(p_token);\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\t\r\n}\r\n#endif\r\n\r\n// Used for evaluating the ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE operator.\r\nstatic uint8 *sCalculateRandomRange(uint8 *p_token, CComponent *p_comp, bool useRnd2)\r\n{\r\n\t// RandomRange token must be followed by a pair.\r\n\tDbg_MsgAssert(*p_token==ESCRIPTTOKEN_PAIR,(\"RandomRange operator must be followed by a pair of values in parentheses, File %s, line %d\",GetSourceFile(p_token),GetLineNumber(p_token)));\r\n\t++p_token;\r\n\t// Get the range values, which are floats cos it's a pair.\r\n\tfloat x=Read4Bytes(p_token).mFloat;\r\n\tp_token+=4;\r\n\tfloat y=Read4Bytes(p_token).mFloat;\r\n\tp_token+=4;\r\n\t\r\n\t// Get the integer values.\r\n\t// Offset the floats up or down by 0.01 to ensure they round down to the expected integer values.\r\n\tint a, b;\r\n\ta=(int)( (x<0) ? x-0.1f:x+0.1f);\r\n\tb=(int)( (y<0) ? y-0.1f:y+0.1f);\r\n\t\r\n\tbool they_are_integers=true;\r\n\tif (fabs(x-a) > 0.00001f || fabs(y-b) > 0.00001f)\r\n\t{\r\n\t\tthey_are_integers=false;\r\n\t}\t\r\n\t\r\n\tif (they_are_integers)\r\n\t{\r\n\t\t// Make sure that a<=b\r\n\t\tif (a>b)\r\n\t\t{\r\n\t\t\t// Swap them.\r\n\t\t\tint temp=a;\r\n\t\t\ta=b;\r\n\t\t\tb=temp;\r\n\t\t}\t\r\n\t\t// Get val, which is between a and b inclusive.\r\n\t\t// This assert is to make sure the calculations in Rnd don't overflow.\r\n\t\tDbg_MsgAssert(b-a+1<=32767,(\"File %s, line %d: RandomRange limits are too far apart, max is 32767\",GetSourceFile(p_token),GetLineNumber(p_token)));\r\n\t\tint val;\r\n\t\tif (useRnd2)\r\n\t\t{\r\n\t\t\tval=a+Mth::Rnd2(b-a+1);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tval=a+Mth::Rnd(b-a+1);\r\n\t\t}\t\r\n\t\t// Make totally sure the value is OK, cos could lead to hard-to-track-down bugs otherwise.\r\n//\t\tDbg_MsgAssert(val>=a && val<=b,(\"File %s, line %d: Internal error in RandomRange (%f %f %f), fire Ken.\",GetSourceFile(p_token),GetLineNumber(p_token),x,y,val));\r\n\t\t\r\n\t\tp_comp->mType=ESYMBOLTYPE_INTEGER;\r\n\t\tp_comp->mIntegerValue=val;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Make sure that x<=y\r\n\t\tif (x>y)\r\n\t\t{\r\n\t\t\t// Swap them.\r\n\t\t\tfloat temp=x;\r\n\t\t\tx=y;\r\n\t\t\ty=temp;\r\n\t\t}\t\r\n\t\t// Get val, which is between x and y inclusive.\r\n\t\tfloat val;\r\n\t\t// Don't make FLOAT_RES bigger than 32766 because the calculations in Rnd will overflow otherwise.\r\n\t\t#define FLOAT_RES 32760.0f\r\n\t\tif (useRnd2)\r\n\t\t{\r\n\t\t\tval=x+((float)Mth::Rnd2((int)(FLOAT_RES+1.0f))*(y-x))/FLOAT_RES;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tval=x+((float)Mth::Rnd((int)(FLOAT_RES+1.0f))*(y-x))/FLOAT_RES;\r\n\t\t}\t\r\n\t\t\r\n\t\t// Make totally sure the value is OK, cos could lead to hard-to-track-down bugs otherwise.\r\n//\t\tDbg_MsgAssert(val>=x && val<=y,(\"File %s, line %d: Internal error in RandomRange (%f %f %f), fire Ken.\",GetSourceFile(p_token),GetLineNumber(p_token),x,y,val));\r\n\t\t\r\n\t\tp_comp->mType=ESYMBOLTYPE_FLOAT;\r\n\t\tp_comp->mFloatValue=val;\r\n\t}\r\n\t\r\n\treturn p_token;\r\n}\r\n\r\n// Skips over a data type token. Eg, if p_token points to a structure, it will\r\n// skip over the whole structure.\r\nstatic uint8 *sSkipType(uint8 *p_token)\r\n{\r\n    switch (*p_token)\r\n    {\r\n        case ESCRIPTTOKEN_NAME:\r\n        case ESCRIPTTOKEN_INTEGER:\r\n        case ESCRIPTTOKEN_HEXINTEGER:\r\n        case ESCRIPTTOKEN_FLOAT:\r\n            p_token+=1+4;\r\n            break;\r\n        case ESCRIPTTOKEN_PAIR:\r\n            p_token+=1+2*4;\r\n            break;\r\n        case ESCRIPTTOKEN_VECTOR:\r\n            p_token+=1+3*4;\r\n            break;\r\n        case ESCRIPTTOKEN_STRING:\r\n        case ESCRIPTTOKEN_LOCALSTRING:\r\n            p_token+=1+4+Read4Bytes(p_token+1).mUInt;\r\n            break;\r\n        case ESCRIPTTOKEN_STARTSTRUCT:\r\n\t\t{\r\n            int StructCount=1;\r\n            while (StructCount)\r\n            {\r\n                p_token=SkipToken(p_token);\r\n                if (*p_token==ESCRIPTTOKEN_STARTSTRUCT) \r\n\t\t\t\t{\r\n\t\t\t\t\t++StructCount;\r\n\t\t\t\t}\t\r\n                else if (*p_token==ESCRIPTTOKEN_ENDSTRUCT)\r\n\t\t\t\t{\r\n                    --StructCount;\r\n\t\t\t\t}\t\r\n            }\r\n            ++p_token;\r\n            break;\r\n\t\t}\t\r\n        case ESCRIPTTOKEN_STARTARRAY:\r\n\t\t{\r\n            int ArrayCount=1;\r\n            while (ArrayCount)\r\n            {\r\n                p_token=SkipToken(p_token);\r\n                if (*p_token==ESCRIPTTOKEN_STARTARRAY)\r\n\t\t\t\t{\r\n                    ++ArrayCount;\r\n\t\t\t\t}\t\r\n                else if (*p_token==ESCRIPTTOKEN_ENDARRAY)\r\n\t\t\t\t{\r\n                    --ArrayCount;\r\n\t\t\t\t}\t\r\n            }\r\n            ++p_token;\r\n            break;\r\n\t\t}\t\r\n        default:\r\n            Dbg_MsgAssert(0,(\"Unrecognized type\"));\r\n            break;\r\n    }\r\n    return p_token;\r\n}\r\n\r\n// Returns true if pToken points to and end-of-line, end-of-line-number or end-of-file token.\r\nstatic bool sIsEndOfLine(const uint8 *p_token)\r\n{\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token\"));\r\n    return (*p_token==ESCRIPTTOKEN_ENDOFLINE || *p_token==ESCRIPTTOKEN_ENDOFLINENUMBER || *p_token==ESCRIPTTOKEN_ENDOFFILE);\r\n}\r\n\r\n// Given that p_token points to a ESCRIPTTOKEN_STARTARRAY token, this will parse the\r\n// array tokens adding the elements to the CArray.\r\n// Gives error messages if all the elements are not of the same type.\r\nstatic uint8 *sInitArrayFromQB(CArray *p_dest, uint8 *p_token, CStruct *p_args)\r\n{\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest\"));\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token\"));\r\n    Dbg_MsgAssert(*p_token==ESCRIPTTOKEN_STARTARRAY,(\"p_token does not point to an array\"));\r\n\t\r\n\t// Remember the start, since we're going to do a first pass through to determine the array type and size.\r\n\tuint8 *p_start=p_token;\t\r\n    \r\n\t// Skip over the startarray token.\r\n    ++p_token;\r\n\t// Execute any random operators.\r\n\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\r\n\tESymbolType type=ESYMBOLTYPE_NONE;\r\n\tuint32 size=0;\r\n\t\r\n    while (*p_token!=ESCRIPTTOKEN_ENDARRAY)\r\n    {\r\n\t\t// Determine type.\r\n        switch (*p_token)\r\n        {\r\n            case ESCRIPTTOKEN_ENDOFLINE:\r\n            case ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n            case ESCRIPTTOKEN_COMMA:\r\n                break;\r\n            case ESCRIPTTOKEN_NAME:\r\n                type=ESYMBOLTYPE_NAME;\r\n                break;\r\n            case ESCRIPTTOKEN_INTEGER:\r\n            case ESCRIPTTOKEN_HEXINTEGER:\r\n\t\t\t\t// Integers don't override floats.\r\n                if (type!=ESYMBOLTYPE_FLOAT) \r\n\t\t\t\t{\r\n\t\t\t\t\ttype=ESYMBOLTYPE_INTEGER;\r\n\t\t\t\t}\t\r\n                break;\r\n            case ESCRIPTTOKEN_FLOAT:\r\n                type=ESYMBOLTYPE_FLOAT;\r\n                break;\r\n            case ESCRIPTTOKEN_PAIR:\r\n                type=ESYMBOLTYPE_PAIR;\r\n                break;\r\n            case ESCRIPTTOKEN_VECTOR:\r\n                type=ESYMBOLTYPE_VECTOR;\r\n                break;\r\n\t        case ESCRIPTTOKEN_STRING:\r\n                type=ESYMBOLTYPE_STRING;\r\n                break;\r\n            case ESCRIPTTOKEN_LOCALSTRING:\r\n                type=ESYMBOLTYPE_LOCALSTRING;\r\n                break;\r\n            case ESCRIPTTOKEN_STARTSTRUCT:\r\n                type=ESYMBOLTYPE_STRUCTURE;\r\n                break;\r\n            case ESCRIPTTOKEN_STARTARRAY:\r\n                type=ESYMBOLTYPE_ARRAY;\r\n                break;\r\n            default:\r\n                Dbg_MsgAssert(0,(\"Unrecognized data type in array, File %s, line %d\\n\",GetSourceFile(p_token),GetLineNumber(p_token)));\r\n                break;\r\n        }\r\n\t\t\r\n\t\t// Update the size and advance p_token.\r\n        switch (*p_token)\r\n        {\r\n            case ESCRIPTTOKEN_ENDOFLINE:\r\n            case ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n            case ESCRIPTTOKEN_COMMA:\r\n                p_token=SkipToken(p_token);\r\n                break;\r\n            case ESCRIPTTOKEN_NAME:\r\n            case ESCRIPTTOKEN_INTEGER:\r\n            case ESCRIPTTOKEN_HEXINTEGER:\r\n            case ESCRIPTTOKEN_FLOAT:\r\n            case ESCRIPTTOKEN_PAIR:\r\n            case ESCRIPTTOKEN_VECTOR:\r\n\t        case ESCRIPTTOKEN_STRING:\r\n            case ESCRIPTTOKEN_LOCALSTRING:\r\n            case ESCRIPTTOKEN_STARTSTRUCT:\r\n            case ESCRIPTTOKEN_STARTARRAY:\r\n                ++size;\r\n                p_token=sSkipType(p_token);\r\n                break;\r\n            default:\r\n                Dbg_MsgAssert(0,(\"Unrecognized data type in array, File %s, line %d\\n\",GetSourceFile(p_token),GetLineNumber(p_token)));\r\n                break;\r\n        }\r\n\t\t\r\n\t\t// Execute any random operators. This has to be done each time p_token is advanced.\r\n\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n    }\r\n\r\n\tif (type==ESYMBOLTYPE_NONE)\r\n\t{\r\n\t\t// Skip over the ESCRIPTTOKEN_ENDARRAY\r\n\t\t++p_token;\r\n\t\t// Finished, empty array.\r\n\t\treturn p_token;\r\n\t}\r\n\r\n\t// Rewind.\t\t\t\t\t\t\t\t\t\t  \r\n\tp_token=p_start;\t\r\n\t\r\n\t// Now that the array size and type are known, set up the CArray and fill it in.\r\n\t\r\n\t// Make sure we're using the script heap, because the CArray is not hard-wired to\r\n\t// allocate it's buffer off it.\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\tp_dest->SetSizeAndType(size,type);\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Just to be totally sure, cos we're about to write into it ...\r\n\tDbg_MsgAssert(p_dest->GetArrayPointer(),(\"NULL array pinter ???\"));\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tint size_check=size;\r\n\t#endif\r\n\t\t\r\n    switch (type)\r\n    {\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t{\r\n\t\t\tint *p_int=(int*)p_dest->GetArrayPointer();\r\n\t\t\t\r\n\t\t\t// Skip over the ESCRIPTTOKEN_STARTARRAY\r\n\t\t\t++p_token;\r\n\t\t\t// Execute any random operators. This has to be done each time p_token is advanced.\r\n\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\twhile (*p_token!=ESCRIPTTOKEN_ENDARRAY)\r\n\t\t\t{\r\n\t\t\t\tswitch (*p_token++)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINE:\r\n\t\t\t\t\tcase ESCRIPTTOKEN_COMMA:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_INTEGER:\r\n\t\t\t\t\tcase ESCRIPTTOKEN_HEXINTEGER:\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\tDbg_MsgAssert(size_check,(\"Array size mismatch\"));\r\n\t\t\t\t\t\t--size_check;\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t*p_int++=Read4Bytes(p_token).mInt;\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"Array elements must be of the same type, File %s, line %d\\n\",GetSourceFile(p_token-1),GetLineNumber(p_token-1)));\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// Execute any random operators. This has to be done each time p_token is advanced.\r\n\t\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\t}    \r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tDbg_MsgAssert(size_check==0,(\"Array size mismatch\"));\r\n\t\t\t#endif\r\n\t\t\t// Skip over the ESCRIPTTOKEN_ENDARRAY                                     \r\n\t\t\t++p_token;\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t{\r\n\t\t\tfloat *p_float=(float*)p_dest->GetArrayPointer();\r\n\t\t\t\r\n\t\t\t// Skip over the ESCRIPTTOKEN_STARTARRAY\r\n\t\t\t++p_token;\r\n\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\twhile (*p_token!=ESCRIPTTOKEN_ENDARRAY)\r\n\t\t\t{\r\n\t\t\t\tswitch (*p_token++)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINE:\r\n\t\t\t\t\tcase ESCRIPTTOKEN_COMMA:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_INTEGER:\r\n\t\t\t\t\tcase ESCRIPTTOKEN_HEXINTEGER:\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\tDbg_MsgAssert(size_check,(\"Array size mismatch\"));\r\n\t\t\t\t\t\t--size_check;\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t*p_float++=Read4Bytes(p_token).mInt;\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_FLOAT:\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\tDbg_MsgAssert(size_check,(\"Array size mismatch\"));\r\n\t\t\t\t\t\t--size_check;\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t*p_float++=Read4Bytes(p_token).mFloat;\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"Array elements must be of the same type, File %s, line %d\\n\",GetSourceFile(p_token-1),GetLineNumber(p_token-1)));\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// Execute any random operators. This has to be done each time p_token is advanced.\r\n\t\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\t}    \r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tDbg_MsgAssert(size_check==0,(\"Array size mismatch\"));\r\n\t\t\t#endif\r\n\t\t\t// Skip over the ESCRIPTTOKEN_ENDARRAY                                     \r\n\t\t\t++p_token;\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t{\r\n\t\t\tuint32 *p_checksum=(uint32*)p_dest->GetArrayPointer();\r\n\t\t\t\r\n\t\t\t// Skip over the ESCRIPTTOKEN_STARTARRAY\r\n\t\t\t++p_token;\r\n\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\twhile (*p_token!=ESCRIPTTOKEN_ENDARRAY)\r\n\t\t\t{\r\n\t\t\t\tswitch (*p_token++)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINE:\r\n\t\t\t\t\tcase ESCRIPTTOKEN_COMMA:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_NAME:\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\tDbg_MsgAssert(size_check,(\"Array size mismatch\"));\r\n\t\t\t\t\t\t--size_check;\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t*p_checksum++=Read4Bytes(p_token).mChecksum;\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"Array elements must be of the same type, File %s, line %d\\n\",GetSourceFile(p_token-1),GetLineNumber(p_token-1)));\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// Execute any random operators. This has to be done each time p_token is advanced.\r\n\t\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\t}    \r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tDbg_MsgAssert(size_check==0,(\"Array size mismatch\"));\r\n\t\t\t#endif\r\n\t\t\t// Skip over the ESCRIPTTOKEN_ENDARRAY                                     \r\n\t\t\t++p_token;\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t{\r\n\t\t\tCStruct **pp_structures=(CStruct**)p_dest->GetArrayPointer();\r\n\r\n\t\t\t// For finding out which node in Chad's qn is causing a syntax error\r\n\t\t\t//int index=0; // REMOVE!\r\n\t\t\t\t\t\t\r\n\t\t\t// Skip over the ESCRIPTTOKEN_STARTARRAY\r\n\t\t\t++p_token;\r\n\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\twhile (*p_token!=ESCRIPTTOKEN_ENDARRAY)\r\n\t\t\t{\r\n\t\t\t\tswitch (*p_token)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINE:\r\n\t\t\t\t\tcase ESCRIPTTOKEN_COMMA:\r\n\t\t\t\t\t\t++p_token;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t\t\t\t\tp_token+=5;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_STARTSTRUCT:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\tDbg_MsgAssert(size_check,(\"Array size mismatch\"));\r\n\t\t\t\t\t\t--size_check;\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// Each structure is individually allocated.\r\n\t\t\t\t\t\tCStruct *p_struct=new CStruct;\r\n\t\t\t\t\t\tp_token=sAddComponentsWithinCurlyBraces(p_struct,p_token,p_args);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t*pp_structures++=p_struct;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t//printf(\"Created array structure %d\\n\",index++); // REMOVE!\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}    \r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"Array elements must be of the same type, File %s, line %d\\n\",GetSourceFile(p_token),GetLineNumber(p_token)));\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// Execute any random operators. This has to be done each time p_token is advanced.\r\n\t\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\t}    \r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tDbg_MsgAssert(size_check==0,(\"Array size mismatch\"));\r\n\t\t\t#endif\r\n\t\t\t// Skip over the ESCRIPTTOKEN_ENDARRAY                                     \r\n\t\t\t++p_token;\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t{\r\n\t\t\tCArray **pp_arrays=(CArray**)p_dest->GetArrayPointer();\r\n\t\t\t\r\n\t\t\t// Skip over the ESCRIPTTOKEN_STARTARRAY\r\n\t\t\t++p_token;\r\n\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\twhile (*p_token!=ESCRIPTTOKEN_ENDARRAY)\r\n\t\t\t{\r\n\t\t\t\tswitch (*p_token++)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINE:\r\n\t\t\t\t\tcase ESCRIPTTOKEN_COMMA:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_STARTARRAY:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\tDbg_MsgAssert(size_check,(\"Array size mismatch\"));\r\n\t\t\t\t\t\t--size_check;\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// Each array is individually allocated.\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\tCArray *p_array=new CArray;\r\n\t\t\t\t\t\t// The -1 is to rewind p_token back to pointing to ESCRIPTTOKEN_STARTARRAY,\r\n\t\t\t\t\t\t// which sInitArrayFromQB requires.\r\n\t\t\t\t\t\tp_token=sInitArrayFromQB(p_array,p_token-1,p_args);\r\n\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t*pp_arrays++=p_array;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"Array elements must be of the same type, File %s, line %d\\n\",GetSourceFile(p_token-1),GetLineNumber(p_token-1)));\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// Execute any random operators. This has to be done each time p_token is advanced.\r\n\t\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\t}    \r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tDbg_MsgAssert(size_check==0,(\"Array size mismatch\"));\r\n\t\t\t#endif\r\n\t\t\t// Skip over the ESCRIPTTOKEN_ENDARRAY                                     \r\n\t\t\t++p_token;\r\n\t\t\tbreak;\r\n\t\t}    \r\n\r\n\t\tcase ESYMBOLTYPE_STRING:\r\n\t\t{\r\n\t\t\tchar **pp_strings=(char**)p_dest->GetArrayPointer();\r\n\t\t\t\r\n\t\t\t// Skip over the ESCRIPTTOKEN_STARTARRAY\r\n\t\t\t++p_token;\r\n\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\twhile (*p_token!=ESCRIPTTOKEN_ENDARRAY)\r\n\t\t\t{\r\n\t\t\t\tswitch (*p_token++)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINE:\r\n\t\t\t\t\tcase ESCRIPTTOKEN_COMMA:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_STRING:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\tDbg_MsgAssert(size_check,(\"Array size mismatch\"));\r\n\t\t\t\t\t\t--size_check;\r\n\t\t\t\t\t\t#endif\r\n\r\n\t\t\t\t\t\tint string_length=Read4Bytes(p_token).mInt;\r\n\t\t\t\t\t\tDbg_MsgAssert(string_length,(\"Zero string_length?\"));\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t*pp_strings++=CreateString((const char *)p_token);\r\n\t\t\t\t\t\tp_token+=string_length;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"Array elements must be of the same type, File %s, line %d\\n\",GetSourceFile(p_token-1),GetLineNumber(p_token-1)));\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// Execute any random operators. This has to be done each time p_token is advanced.\r\n\t\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\t}    \r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tDbg_MsgAssert(size_check==0,(\"Array size mismatch\"));\r\n\t\t\t#endif\r\n\t\t\t// Skip over the ESCRIPTTOKEN_ENDARRAY                                     \r\n\t\t\t++p_token;\r\n\t\t\tbreak;\r\n\t\t}    \r\n\r\n\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t{\r\n\t\t\tchar **pp_strings=(char**)p_dest->GetArrayPointer();\r\n\t\t\t\r\n\t\t\t// Skip over the ESCRIPTTOKEN_STARTARRAY\r\n\t\t\t++p_token;\r\n\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\twhile (*p_token!=ESCRIPTTOKEN_ENDARRAY)\r\n\t\t\t{\r\n\t\t\t\tswitch (*p_token++)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINE:\r\n\t\t\t\t\tcase ESCRIPTTOKEN_COMMA:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_LOCALSTRING:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\tDbg_MsgAssert(size_check,(\"Array size mismatch\"));\r\n\t\t\t\t\t\t--size_check;\r\n\t\t\t\t\t\t#endif\r\n\r\n\t\t\t\t\t\tint string_length=Read4Bytes(p_token).mInt;\r\n\t\t\t\t\t\tDbg_MsgAssert(string_length,(\"Zero string_length?\"));\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t*pp_strings++=CreateString((const char *)p_token);\r\n\t\t\t\t\t\tp_token+=string_length;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"Array elements must be of the same type, File %s, line %d\\n\",GetSourceFile(p_token-1),GetLineNumber(p_token-1)));\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// Execute any random operators. This has to be done each time p_token is advanced.\r\n\t\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\t}    \r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tDbg_MsgAssert(size_check==0,(\"Array size mismatch\"));\r\n\t\t\t#endif\r\n\t\t\t// Skip over the ESCRIPTTOKEN_ENDARRAY                                     \r\n\t\t\t++p_token;\r\n\t\t\tbreak;\r\n\t\t}    \r\n\r\n\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t{\r\n\t\t\tCVector **pp_vectors=(CVector**)p_dest->GetArrayPointer();\r\n\t\t\t\r\n\t\t\t// Skip over the ESCRIPTTOKEN_STARTARRAY\r\n\t\t\t++p_token;\r\n\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\twhile (*p_token!=ESCRIPTTOKEN_ENDARRAY)\r\n\t\t\t{\r\n\t\t\t\tswitch (*p_token++)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINE:\r\n\t\t\t\t\tcase ESCRIPTTOKEN_COMMA:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_VECTOR:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\tDbg_MsgAssert(size_check,(\"Array size mismatch\"));\r\n\t\t\t\t\t\t--size_check;\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tCVector *p_new_vector=new CVector;\r\n\t\t\t\t\t\tp_new_vector->mX=Read4Bytes(p_token).mFloat;\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tp_new_vector->mY=Read4Bytes(p_token).mFloat;\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tp_new_vector->mZ=Read4Bytes(p_token).mFloat;\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t*pp_vectors++=p_new_vector;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"Array elements must be of the same type, File %s, line %d\\n\",GetSourceFile(p_token-1),GetLineNumber(p_token-1)));\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// Execute any random operators. This has to be done each time p_token is advanced.\r\n\t\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\t}    \r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tDbg_MsgAssert(size_check==0,(\"Array size mismatch\"));\r\n\t\t\t#endif\r\n\t\t\t// Skip over the ESCRIPTTOKEN_ENDARRAY                                     \r\n\t\t\t++p_token;\r\n\t\t\tbreak;\r\n\t\t}    \r\n\r\n\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t{\r\n\t\t\tCPair **pp_pairs=(CPair**)p_dest->GetArrayPointer();\r\n\t\t\t\r\n\t\t\t// Skip over the ESCRIPTTOKEN_STARTARRAY\r\n\t\t\t++p_token;\r\n\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\twhile (*p_token!=ESCRIPTTOKEN_ENDARRAY)\r\n\t\t\t{\r\n\t\t\t\tswitch (*p_token++)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINE:\r\n\t\t\t\t\tcase ESCRIPTTOKEN_COMMA:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ESCRIPTTOKEN_PAIR:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\tDbg_MsgAssert(size_check,(\"Array size mismatch\"));\r\n\t\t\t\t\t\t--size_check;\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tCPair *p_new_pair=new CPair;\r\n\t\t\t\t\t\tp_new_pair->mX=Read4Bytes(p_token).mFloat;\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\tp_new_pair->mY=Read4Bytes(p_token).mFloat;\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t*pp_pairs++=p_new_pair;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"Array elements must be of the same type, File %s, line %d\\n\",GetSourceFile(p_token-1),GetLineNumber(p_token-1)));\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// Execute any random operators. This has to be done each time p_token is advanced.\r\n\t\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\t}    \r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tDbg_MsgAssert(size_check==0,(\"Array size mismatch\"));\r\n\t\t\t#endif\r\n\t\t\t// Skip over the ESCRIPTTOKEN_ENDARRAY                                     \r\n\t\t\t++p_token;\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Unsupported array type, File %s, line %d\\n\",GetSourceFile(p_token),GetLineNumber(p_token)));\r\n\t\t\tbreak;\r\n    }\r\n\r\n\treturn p_token;\r\n}\r\n\r\n// Adds one component to p_dest.\r\n// The component is given the name nameChecksum, and it's type and value is defined by whatever\r\n// p_token is pointing to.\r\n// p_args contains the structure defining the value of any args referred to using the <,> operators.\r\n// Returns a pointer to the next token after parsing the value pointed to by p_token.\r\nstatic uint8 *sAddComponentFromQB(CStruct *p_dest, uint32 nameChecksum, uint8 *p_token, CStruct *p_args)\r\n{\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest\"));\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token\"));\r\n\t\r\n\tbool use_rnd2=false;\r\n\t\r\n\tswitch (*p_token++)\r\n\t{\r\n\t\tcase ESCRIPTTOKEN_NAME:\r\n\t\t{\r\n\t\t\tuint32 checksum=Read4Bytes(p_token).mChecksum;\r\n\t\t\tp_token+=4;\r\n\t\t\tp_dest->AddChecksum(nameChecksum,checksum);\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\tcase ESCRIPTTOKEN_INTEGER:\r\n\t\t{\r\n\t\t\tint integer=Read4Bytes(p_token).mInt;\r\n\t\t\tp_token+=4;\r\n\t\t\tp_dest->AddInteger(nameChecksum,integer);\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE2:\r\n\t\t\tuse_rnd2=true;\r\n\t\t\t// Intentional lack of a break here.\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE:\r\n\t\t{\r\n\t\t\tCComponent *p_new_component=new CComponent;\r\n\t\t\tp_token=sCalculateRandomRange(p_token,p_new_component,use_rnd2);\r\n\t\t\tp_new_component->mNameChecksum=nameChecksum;\r\n\t\t\tp_dest->AddComponent(p_new_component);\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\t\r\n\t\tcase ESCRIPTTOKEN_FLOAT:\r\n\t\t{\r\n\t\t\tfloat float_val=Read4Bytes(p_token).mFloat;\r\n\t\t\tp_token+=4;\r\n\t\t\tp_dest->AddFloat(nameChecksum,float_val);\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\tcase ESCRIPTTOKEN_VECTOR:\r\n\t\t{\r\n\t\t\tfloat x=Read4Bytes(p_token).mFloat;\r\n\t\t\tp_token+=4;\r\n\t\t\tfloat y=Read4Bytes(p_token).mFloat;\r\n\t\t\tp_token+=4;\r\n\t\t\tfloat z=Read4Bytes(p_token).mFloat;\r\n\t\t\tp_token+=4;\r\n\t\t\t\r\n\t\t\t// Alert! This next 'if' is kind of game specific ...\r\n\t\t\t// It should probably be the exporter that does not include the angles in the node array if they are \r\n\t\t\t// close to zero, rather than having this remove them from all structures.\r\n\t\t\t// Note: We can't just remove zero angles from the node array after it has loaded, because there\r\n\t\t\t// is not enough memory to store them initially.\r\n\t\t\tif (nameChecksum==CRCD(0x9d2d0915,\"Angles\"))\r\n\t\t\t{\r\n\t\t\t\t// If the vector is close to (0,0,0) then don't bother adding it.\r\n\t\t\t\t// This is a memory optimization. All nodes in levels are getting exported with\r\n\t\t\t\t// an angles component, which most of the time is (0,0,0). \r\n\t\t\t\t// This will work OK so long as whenever GetVector is used in the code to get the angles, \r\n\t\t\t\t// the vector being loaded into is initialised with (0,0,0).\r\n\t\t\t\t// That way, if the vector is not there, it will remain as (0,0,0) as required.\r\n\t\t\t\tfloat dx=x;\r\n\t\t\t\tif (dx<0.0f) dx=-dx;\r\n\t\t\t\tfloat dy=y;\r\n\t\t\t\tif (dy<0.0f) dy=-dy;\r\n\t\t\t\tfloat dz=z;\r\n\t\t\t\tif (dz<0.0f) dz=-dz;\r\n\t\t\t\tif (dx<0.01f && dy<0.01f && dz<0.01f)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tp_dest->AddVector(nameChecksum,x,y,z);\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\tcase ESCRIPTTOKEN_PAIR:\r\n\t\t{\r\n\t\t\tfloat x=Read4Bytes(p_token).mFloat;\r\n\t\t\tp_token+=4;\r\n\t\t\tfloat y=Read4Bytes(p_token).mFloat;\r\n\t\t\tp_token+=4;\r\n\t\t\tp_dest->AddPair(nameChecksum,x,y);\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\tcase ESCRIPTTOKEN_STRING:\r\n\t\t{\r\n\t\t\tint len=Read4Bytes(p_token).mInt;\r\n\t\t\tp_token+=4;\r\n\t\t\tp_dest->AddString(nameChecksum,(const char *)p_token);\r\n\t\t\tp_token+=len;\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\tcase ESCRIPTTOKEN_LOCALSTRING:\r\n\t\t{\r\n\t\t\tint len=Read4Bytes(p_token).mInt;\r\n\t\t\tp_token+=4;\r\n\t\t\tp_dest->AddLocalString(nameChecksum,(const char *)p_token);\r\n\t\t\tp_token+=len;\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\tcase ESCRIPTTOKEN_STARTSTRUCT:\r\n\t\t{\r\n\t\t\t// Rewind p_token to point to ESCRIPTTOKEN_STARTSTRUCT, because the \r\n\t\t\t// sAddComponentsWithinCurlyBraces call requires it.\r\n\t\t\t--p_token;\r\n\t\t\t\r\n\t\t\t// No need to set which heap we're using, cos CStruct's and their CComponent's come off\r\n\t\t\t// their own pools.\r\n\t\t\tCStruct *p_structure=new CStruct;\r\n\t\t\tp_token=sAddComponentsWithinCurlyBraces(p_structure,p_token,p_args);\r\n\t\t\tp_dest->AddStructurePointer(nameChecksum,p_structure);\r\n\t\t\t// Note: Not deleting p_structure, because it has been given to p_dest, which will delete\r\n\t\t\t// it in its destructor.\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\tcase ESCRIPTTOKEN_STARTARRAY:\r\n\t\t{\r\n\t\t\t// Rewind p_token to point to ESCRIPTTOKEN_STARTARRAY, because the CArray::Parse call requires it.\r\n\t\t\t--p_token;\r\n\t\t\t\r\n\t\t\t// The CArray constructor is not hard-wired to use the script heap for it's buffer, so need\r\n\t\t\t// to make sure we're using the script heap here.\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\t\tCArray *p_array=new CArray;\r\n\t\t\tMem::Manager::sHandle().PopContext();\t\t\t\r\n\t\t\t\r\n\t\t\tp_token=sInitArrayFromQB(p_array,p_token,p_args);\r\n\t\t\tp_dest->AddArrayPointer(nameChecksum,p_array);\r\n\t\t\t// Note: Not deleting p_array, because it has been given to p_dest, which will delete\r\n\t\t\t// it in its destructor.\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_SCRIPT:\r\n\t\t{\r\n\t\t\t// When adding a local script defined in a structure, we'd expect the nameChecksum passed to\r\n\t\t\t// this function to be zero, since the name comes after the script keyword.\r\n\t\t\tDbg_MsgAssert(nameChecksum==0,(\"nameChecksum expected to be 0 for a local script ??, File %s, line %d\\n\",GetSourceFile(p_token-1),GetLineNumber(p_token-1)));\r\n\t\t\t\r\n\t\t\tDbg_MsgAssert(*p_token==ESCRIPTTOKEN_NAME,(\"\\nKeyword 'script' must be followed by a name, File %s, line %d\\n\",GetSourceFile(p_token-1),GetLineNumber(p_token-1)));\r\n\t\t\t++p_token; // Skip over the ESCRIPTTOKEN_NAME\r\n\t\t\tnameChecksum=Read4Bytes(p_token).mChecksum;\r\n\t\t\tp_token+=4; // Skip over the name checksum\r\n\t\t\t\r\n\t\t\t// Skip p_token over the script tokens, and calculate the size.\r\n\t\t\tconst uint8 *p_script=p_token;\r\n\t\t\tp_token=SkipOverScript(p_token);\r\n\t\t\tuint32 size=p_token-p_script;\r\n\t\t\t\r\n\t\t\t// This will create a new buffer and copy in the script data.\r\n\t\t\tp_dest->AddScript(nameChecksum,p_script,size);\r\n \t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase ESCRIPTTOKEN_ARG:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(*p_token==ESCRIPTTOKEN_NAME,(\"Expected '<' token to be followed by a name, File %s, line %d\",GetSourceFile(p_token-1),GetLineNumber(p_token-1)));\r\n\t\t\t++p_token;\r\n\t\t\tuint32 arg_checksum=Read4Bytes(p_token).mChecksum;\r\n\t\t\tp_token+=4;\r\n\t\t\tif (p_args)\r\n\t\t\t{\r\n\t\t\t\t// Look for a parameter named arg_checksum in p_args, recursing into any referenced structures\r\n\t\t\t\tCComponent *p_comp=p_args->FindNamedComponentRecurse(arg_checksum);\r\n\t\t\t\tif (p_comp)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (nameChecksum==0 && p_comp->mType==ESYMBOLTYPE_STRUCTURE)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Trying to add an unnamed structure, in which case it's contents\r\n\t\t\t\t\t\t// should be merged onto p_dest.\r\n\t\t\t\t\t\tp_dest->AppendStructure(p_comp->mpStructure);\r\n\t\t\t\t\t\t// Note: OK to call AppendStructure with NULL, so no need to check mpStructure.\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Create a copy of the component and add it to p_dest.\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tCComponent *p_new_component=new CComponent;\r\n\t\t\t\t\t\t// Note: There is no copy-constructor for CComponent, because that would cause a\r\n\t\t\t\t\t\t// cyclic dependency between component.cpp/h and struct.cpp/h.\r\n\t\t\t\t\t\t// Instead, use the CopyComponent function defined in struct.cpp\r\n\t\t\t\t\t\tCopyComponent(p_new_component,p_comp);\r\n\t\t\t\t\t\t// Then change it's name to nameChecksum\r\n\t\t\t\t\t\tp_new_component->mNameChecksum=nameChecksum;\r\n\t\t\t\t\t\t// And add it to p_dest\r\n\t\t\t\t\t\tp_dest->AddComponent(p_new_component);\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// Don't assert if p_args is NULL, cos it will be when this function is used to skip over\r\n\t\t\t// parameter lists in FindReferences\r\n\t\t\tbreak;\t\r\n\t\t}\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ALLARGS:\r\n\t\t{\r\n\t\t\t// Don't assert if p_args is NULL, cos it will be when this function is used to skip over\r\n\t\t\t// parameter lists in FindReferences\r\n\t\t\tif (p_args)\r\n\t\t\t{\r\n\t\t\t\tif (nameChecksum)\r\n\t\t\t\t{\r\n\t\t\t\t\t// If it's a named structure, copy the passed arguments into a new structure and insert a \r\n\t\t\t\t\t// pointer to it.\r\n\t\t\t\t\tCStruct *p_structure=new CStruct;\r\n\t\t\t\t\t*p_structure=*p_args;\r\n\t\t\t\t\tp_dest->AddStructurePointer(nameChecksum,p_structure);\r\n\t\t\t\t}\r\n\t\t\t\telse\t\r\n\t\t\t\t{\r\n\t\t\t\t\t// Otherwise just merge in the passed parameters.\r\n\t\t\t\t\t// Un-named structures are always considered 'part of' the structure that they are in,\r\n\t\t\t\t\t// eg {x=9 {y=3}} is the same as {x=9 y=3}\r\n\t\t\t\t\t*p_dest+=*p_args;\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t\tbreak;\t\r\n\t\t}\r\n\t\tcase ESCRIPTTOKEN_COMMA:\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\t--p_token;\r\n\t\t\tDbg_MsgAssert(0,(\"\\nBad token '%s' encountered when creating component, File %s, line %d\",GetTokenName((EScriptToken)*p_token),GetSourceFile(p_token),GetLineNumber(p_token)));\r\n\t\t\tbreak;\r\n\t}\r\n    return p_token;    \r\n}\r\n\r\n// Parses the components in QB format pointed to by p_token, and adds them to p_dest until the \r\n// close-curly-brace token is reached.\r\n// p_token must initially point to an open-curly-brace token.\r\n// Any end-of-lines in between are ignored.\r\n// For example, p_token may point to: {x=9 foo=\"Blaa\"}\r\n// Used when creating sub-structures and global structures.\r\n// p_args contains the structure defining the value of any args referred to using the <,> operators.\r\n// Returns a pointer to the next token after parsing the tokens pointed to by p_token.\r\nstatic uint8 *sAddComponentsWithinCurlyBraces(CStruct *p_dest, uint8 *p_token, CStruct *p_args)\r\n{\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest\"));\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token\"));\r\n    Dbg_MsgAssert(*p_token==ESCRIPTTOKEN_STARTSTRUCT,(\"p_token expected to point to ESCRIPTTOKEN_STARTSTRUCT, File %s, line %d\",GetSourceFile(p_token),GetLineNumber(p_token)));\r\n\t// Skip over the ESCRIPTTOKEN_STARTSTRUCT\r\n    ++p_token;\r\n\r\n    while (true)\r\n    {\r\n\t\tp_token=SkipEndOfLines(p_token);\r\n\t\t// Execute any random operators. This has to be done each time p_token is advanced.\r\n\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\tif (*p_token==ESCRIPTTOKEN_ENDSTRUCT)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n        switch (*p_token)\r\n        {\r\n            case ESCRIPTTOKEN_NAME:\r\n            {\r\n                uint8 *p_name_token=p_token;\r\n                ++p_token;\r\n                uint32 name_checksum=Read4Bytes(p_token).mChecksum;\r\n                p_token+=4;\r\n                p_token=SkipEndOfLines(p_token);\r\n\t\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n                if (*p_token==ESCRIPTTOKEN_EQUALS)\r\n                {\r\n                    ++p_token;\r\n                    p_token=SkipEndOfLines(p_token);\r\n\t\t\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (*p_token==ESCRIPTTOKEN_OPENPARENTH)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tCComponent *p_comp=new CComponent;\r\n\t\t\t\t\t\tp_token=Evaluate(p_token,p_args,p_comp);\r\n\t\t\t\t\t\tif (p_comp->mType!=ESYMBOLTYPE_NONE)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_comp->mNameChecksum=name_checksum;\r\n\t\t\t\t\t\t\tp_dest->AddComponent(p_comp);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tdelete p_comp;\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_token=sAddComponentFromQB(p_dest,name_checksum,p_token,p_args);\r\n\t\t\t\t\t}\r\n                }\r\n                else\r\n\t\t\t\t{\r\n                    p_token=sAddComponentFromQB(p_dest,NO_NAME,p_name_token,p_args);\r\n\t\t\t\t}\t\r\n                break;\r\n            }    \r\n            case ESCRIPTTOKEN_STARTSTRUCT:\r\n                p_token=sAddComponentsWithinCurlyBraces(p_dest,p_token,p_args);\r\n                break;\r\n\t\t\tcase ESCRIPTTOKEN_COMMA:\t\r\n\t\t\t\t++p_token;\r\n\t\t\t\tbreak;\r\n\t\t\tcase ESCRIPTTOKEN_ENDOFLINE:\r\n\t\t\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t\t\tp_token=SkipEndOfLines(p_token);\t\t\t\t\r\n\t\t\t\tbreak;\r\n            default:\r\n\t\t\t{\r\n\t\t\t\tif (*p_token==ESCRIPTTOKEN_OPENPARENTH)\r\n\t\t\t\t{\r\n\t\t\t\t\tCComponent *p_comp=new CComponent;\r\n\t\t\t\t\tp_token=Evaluate(p_token,p_args,p_comp);\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (p_comp->mType==ESYMBOLTYPE_STRUCTURE)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// The CStruct::AddComponent function does not allow unnamed structure\r\n\t\t\t\t\t\t// components to be added, so merge in the contents of the structure instead.\r\n\t\t\t\t\t\tp_dest->AppendStructure(p_comp->mpStructure);\r\n\t\t\t\t\t\t// Now p_comp does have to be cleaned up and deleted, because it has not\r\n\t\t\t\t\t\t// been given to p_dest.\r\n\t\t\t\t\t\tCleanUpComponent(p_comp);\r\n\t\t\t\t\t\tdelete p_comp;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (p_comp->mType!=ESYMBOLTYPE_NONE)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_comp->mNameChecksum=NO_NAME;\r\n\t\t\t\t\t\t\tp_dest->AddComponent(p_comp);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tdelete p_comp;\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_token=sAddComponentFromQB(p_dest,NO_NAME,p_token,p_args);\r\n\t\t\t\t}\t\r\n                break;\r\n\t\t\t}\t\r\n        }            \r\n    } \r\n\r\n\t// Skip over the ESCRIPTTOKEN_ENDSTRUCT\r\n    ++p_token;\r\n    return p_token;\r\n}\r\n\r\n// Creates a new script symbol entry, allocates memory for the script data and copies it in, prefixing\r\n// the data with the contents checksum.\r\nstatic CSymbolTableEntry *sCreateScriptSymbol(uint32 nameChecksum, uint32 contentsChecksum, const uint8 *p_data, uint32 size, const char *p_fileName)\r\n{\r\n\tDbg_MsgAssert(p_data,(\"NULL p_data ??\"));\r\n\tDbg_MsgAssert(p_fileName,(\"NULL p_fileName\"));\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\t#ifndef __PLAT_WN32__\r\n\tCheckForPossibleInfiniteLoops(nameChecksum,(uint8*)(uint32)p_data, p_fileName);\r\n\t#endif\r\n\t#endif\r\n\r\n\tCSymbolTableEntry *p_new=CreateNewSymbolEntry(nameChecksum);\r\n\tDbg_MsgAssert(p_new,(\"NULL p_new ??\"));\r\n\t\r\n\tp_new->mType=ESYMBOLTYPE_QSCRIPT;\r\n\t\r\n\t#ifdef NO_SCRIPT_CACHING\r\n\t// Allocate space for the content checksum (4 bytes) plus the script data.\r\n\tuint8 *p_new_script=(uint8*)Mem::Malloc(4+size);\r\n\t\r\n\t// Write in the contents checksum.\r\n\t// p_new_script will be long-word aligned so OK to cast to a uint32*\r\n\t*(uint32*)p_new_script=contentsChecksum;\r\n\t\r\n\tuint8 *p_dest=p_new_script+4;\r\n\tconst uint8 *p_source=p_data;\r\n\tfor (uint32 i=0; i<size; ++i)\r\n\t{\r\n\t\t*p_dest++=*p_source++;\r\n\t}\t\r\n\tp_new->mpScript=p_new_script;\r\n\tPreProcessScript(p_new_script+4);\r\n\t\r\n\t#else\t\r\n\t\r\n\t\r\n\tenum\r\n\t{\r\n\t\tCOMPRESS_BUFFER_SIZE=20000,\r\n\t};\t\r\n\tuint8 *p_compress_buffer=(uint8*)Mem::Malloc(COMPRESS_BUFFER_SIZE);\r\n\t\r\n\t// Compress the script data.\r\n\tint compressed_size=Encode((char*)p_data,(char*)p_compress_buffer,size,false);\r\n\tDbg_MsgAssert(compressed_size <= COMPRESS_BUFFER_SIZE,(\"Compress buffer overflow! Compressed size of script %s is %d\",Script::FindChecksumName(nameChecksum),compressed_size));\r\n\t\r\n\t// If it compressed to a bigger size, replace the compressed \r\n\t// data with a copy of the original instead.\r\n\tif (compressed_size >= (int)size)\r\n\t{\r\n\t\tconst uint8 *p_source=p_data;\r\n\t\tuint8 *p_dest=p_compress_buffer;\r\n\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t{\r\n\t\t\t*p_dest++=*p_source++;\r\n\t\t}\t\r\n\t\tcompressed_size=size;\r\n\t}\r\n\t\r\n\t// Allocate space for the content checksum, decompressed size, compressed size, and the compressed data.\r\n\tuint8 *p_new_script=(uint8*)Mem::Malloc(SCRIPT_HEADER_SIZE+compressed_size);\r\n\r\n\t// p_new_script will be long-word aligned so OK to cast to a uint32*\r\n\t*(uint32*)(p_new_script+0)=contentsChecksum;\r\n\t*(uint32*)(p_new_script+4)=size;\r\n\t*(uint32*)(p_new_script+8)=compressed_size;\r\n\t\r\n\tuint8 *p_dest=p_new_script+SCRIPT_HEADER_SIZE;\r\n\tconst uint8 *p_source=p_compress_buffer;\r\n\tfor (int i=0; i<compressed_size; ++i)\r\n\t{\r\n\t\t*p_dest++=*p_source++;\r\n\t}\t\r\n\t\r\n#ifdef __PLAT_NGC__\r\n\tp_new->mScriptOffset = NsARAM::alloc( SCRIPT_HEADER_SIZE+compressed_size, NsARAM::SCRIPT );\r\n\tNsDMA::toARAM( p_new->mScriptOffset, p_new_script, SCRIPT_HEADER_SIZE+compressed_size );\r\n\tMem::Free( p_new_script );\r\n#else\r\n\tp_new->mpScript=p_new_script;\r\n#endif\t\t// __PLAT_NGC__\r\n\t\r\n\tMem::Free(p_compress_buffer);\r\n\t\r\n\t// Now that the new script has been loaded, the script cache needs to be refreshed in case any existing\r\n\t// CScript's are running this script. They will all get restarted later (see file.cpp)\r\n\tScript::CScriptCache *p_script_cache=Script::CScriptCache::Instance();\r\n\t// Not asserting if p_script_cache is NULL, because it will be when all the q-files are loaded on startup.\r\n\tif (p_script_cache)\t\r\n\t{\r\n\t\tp_script_cache->RefreshAfterReload(nameChecksum);\r\n\t}\r\n\t#endif\r\n\r\n\t// Store the name of the source qb in the symbol so that the qb is able to be unloaded.\r\n\tp_new->mSourceFileNameChecksum=Crc::GenerateCRCFromString(p_fileName);\r\n\t\r\n\treturn p_new;\r\n}\r\n\r\n// Creates a symbol defined by a name, followed by equals, followed by a value.\r\nstatic uint8 *sCreateSymbolOfTheFormNameEqualsValue(uint8 *p_token, const char *p_fileName, EBoolAssertIfDuplicateSymbols assertIfDuplicateSymbols)\r\n{\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token\"));\r\n\tDbg_MsgAssert(p_fileName,(\"NULL p_fileName\"));\r\n\t\r\n\tDbg_MsgAssert(*p_token==ESCRIPTTOKEN_NAME,(\"\\nExpected ESCRIPTTOKEN_NAME\"));\r\n\t++p_token;\r\n\tuint32 name_checksum=Read4Bytes(p_token).mChecksum;\r\n\tp_token+=4;\r\n\tp_token=SkipEndOfLines(p_token);\r\n\tDbg_MsgAssert(*p_token==ESCRIPTTOKEN_EQUALS,(\"\\nExpected an equals sign to follow '%s' at line %d, %s\\nThe most likely explanation is that you have a command\\noutside of a script ... endscript\",FindChecksumName(name_checksum),GetLineNumber(p_token),p_fileName));\r\n\t++p_token;\r\n\tp_token=SkipEndOfLines(p_token);\r\n\r\n\t// We have a name followed by an equals, so this is defining some symbol with that name,\r\n\t// eg Foo=6, or Foo=\"Blaa\"\r\n\t// So first of all, see if any symbol already exists with that name, and if it does then\r\n\t// remove it, or assert.\r\n\tCSymbolTableEntry *p_existing_entry=LookUpSymbol(name_checksum);\r\n\tif (p_existing_entry)\r\n\t{\r\n\t\tif (assertIfDuplicateSymbols)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"The symbol '%s' is defined twice, in %s and %s\\n Try running CleanAss \",FindChecksumName(name_checksum),FindChecksumName(p_existing_entry->mSourceFileNameChecksum),p_fileName));\r\n\t\t}\r\n\t\t\r\n\t\tCleanUpAndRemoveSymbol(p_existing_entry);\r\n\t}\t\t\r\n\r\n\t// Create a new symbol with the given name.\r\n\tCSymbolTableEntry *p_new=CreateNewSymbolEntry(name_checksum);\r\n\tDbg_MsgAssert(p_new,(\"NULL p_new ??\"));\r\n\r\n\t// Store the name of the source qb in the symbol so that the qb is able to be unloaded.\r\n\t// Note: This used to be after the switch statement below. Moved it here so that if any\r\n\t// assert goes off in the switch statement the file name info will be present in the symbol.\r\n\tp_new->mSourceFileNameChecksum=Crc::GenerateCRCFromString(p_fileName);\r\n\r\n\t// Now see what type of value follows the equals, and fill in the new symbol accordingly.\r\n\tswitch (*p_token)\r\n\t{\r\n\t\tcase ESCRIPTTOKEN_OPENPARENTH:\r\n\t\t{\r\n\t\t\tCComponent *p_comp=new CComponent;\r\n\t\t\tp_token=Evaluate(p_token,NULL,p_comp);\r\n\t\t\tDbg_MsgAssert(p_comp->mType!=ESYMBOLTYPE_NONE,(\"Global symbol '%s' did not evaluate to anything ...\",FindChecksumName(p_comp->mNameChecksum)));\r\n\t\t\tp_new->mType=p_comp->mType;\r\n\t\t\tp_new->mUnion=p_comp->mUnion;\r\n\t\t\tp_comp->mUnion=0;\r\n\t\t\tdelete p_comp;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase ESCRIPTTOKEN_INTEGER:\r\n\t\tcase ESCRIPTTOKEN_FLOAT:\r\n\t\tcase ESCRIPTTOKEN_VECTOR:\r\n\t\tcase ESCRIPTTOKEN_PAIR:\r\n\t\tcase ESCRIPTTOKEN_STRING:\r\n\t\tcase ESCRIPTTOKEN_LOCALSTRING:\r\n\t\tcase ESCRIPTTOKEN_NAME:\r\n\t\t{\r\n\t\t\tCComponent *p_comp=new CComponent;\r\n\t\t\tp_token=FillInComponentUsingQB(p_token,NULL,p_comp);\r\n\t\t\tp_new->mType=p_comp->mType;\r\n\t\t\tp_new->mUnion=p_comp->mUnion;\r\n\t\t\tp_comp->mUnion=0;\r\n\t\t\tdelete p_comp;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase ESCRIPTTOKEN_STARTSTRUCT:\r\n\t\t{\r\n\t\t\tp_new->mType=ESYMBOLTYPE_STRUCTURE;\r\n\t\t\tp_new->mpStructure=new CStruct;\r\n\t\t\t\r\n\t\t\tp_token=sAddComponentsWithinCurlyBraces(p_new->mpStructure,p_token);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase ESCRIPTTOKEN_STARTARRAY:\r\n\t\t{\r\n\t\t\tp_new->mType=ESYMBOLTYPE_ARRAY;\r\n\t\t\t\r\n\t\t\tp_new->mpArray=new CArray;\r\n\t\t\tp_token=sInitArrayFromQB(p_new->mpArray,p_token);\r\n\t\t\tbreak;                \r\n\t\t}\t\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"\\nUnexpected type value of %d given to symbol '%s', line %d of %s\",*p_token,FindChecksumName(name_checksum),GetLineNumber(p_token),p_fileName));\r\n\t\t\tbreak;\r\n\t} // switch (*p_token)\r\n\t\r\n\treturn p_token;\r\n}\r\n\r\n// Given a pointer to an un-preprocessed script, this will parse through it converting function names\r\n// to either cfunction pointers or member function tokens.\r\nvoid PreProcessScript(uint8 *p_token)\r\n{\r\n\t// Skip over the default params\r\n\tp_token=SkipToStartOfNextLine(p_token);\r\n\t\r\n\twhile (*p_token!=ESCRIPTTOKEN_KEYWORD_ENDSCRIPT) \r\n\t{\r\n\t\tswitch (*p_token)\r\n\t\t{\r\n\t\t\tcase ESCRIPTTOKEN_KEYWORD_IF:\r\n\t\t\t\t++p_token;\r\n\t\t\t\tbreak;\r\n\t\t\t\t\r\n\t\t\tcase ESCRIPTTOKEN_NAME:\r\n\t\t\t{\r\n\t\t\t\t++p_token;\r\n\t\t\t\tuint32 name_checksum=Read4Bytes(p_token).mChecksum;\r\n\t\t\t\tp_token+=4;\r\n\t\r\n\t\t\t\t// Look up the name to see if it is a cfunction or member function.\r\n\t\t\t\tCSymbolTableEntry *p_entry=Resolve(name_checksum);\r\n\t\t\t\t// Must not assert if p_entry is NULL, cos they might just be loading in\r\n\t\t\t\t// a qb file that refers to a script that has not been written yet.\r\n\t\t\t\tif (p_entry)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (p_entry->mType==ESYMBOLTYPE_CFUNCTION)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Change the token type and replace the checksum with the\r\n\t\t\t\t\t\t// function pointer to save having to resolve it later.\r\n\t\t\t\t\t\t*(p_token-5)=ESCRIPTTOKEN_RUNTIME_CFUNCTION;\r\n\t\t\t\t\t\tDbg_MsgAssert(p_entry->mpCFunction,(\"NULL p_entry->mpCFunction\"));\r\n\t\t\t\t\t\tWrite4Bytes(p_token-4, (uint32)p_entry->mpCFunction);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if (p_entry->mType==ESYMBOLTYPE_MEMBERFUNCTION)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Saves having to look up the checksum later to find out that it is\r\n\t\t\t\t\t\t// a member function.\r\n\t\t\t\t\t\t*(p_token-5)=ESCRIPTTOKEN_RUNTIME_MEMBERFUNCTION;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\t\r\n\t\t\t\tp_token=SkipToStartOfNextLine(p_token);\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tdefault:\r\n\t\t\t\tp_token=SkipToStartOfNextLine(p_token);\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\nstatic CStoredRandom *sFindStoredRandom(const uint8 *p_token, EScriptToken type, int numItems)\r\n{\r\n\tCScript *p_current_script=GetCurrentScript();\r\n\t\r\n\tCStoredRandom *p_search=sp_first_stored_random;\r\n\twhile (p_search)\r\n\t{\r\n\t\tif (p_search->mpToken==p_token &&\r\n\t\t\tp_search->mType==type &&\r\n\t\t\tp_search->mNumItems==numItems)\r\n\t\t{\r\n\t\t\tif (p_search->mpScript==p_current_script || p_search->mpScript==NULL)\r\n\t\t\t{\r\n\t\t\t\treturn p_search;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\t\r\n\t\tp_search=p_search->mpNext;\r\n\t}\t\r\n\treturn NULL;\r\n}\r\n\r\nstatic CStoredRandom *sCreateNewStoredRandom()\r\n{\r\n\tif (s_num_stored_randoms>=MAX_STORED_RANDOMS)\r\n\t{\r\n\t\tDbg_MsgAssert(sp_last_stored_random,(\"NULL sp_last_stored_random ?\"));\r\n\t\t\r\n\t\tCStoredRandom *p_new_last=sp_last_stored_random->mpPrevious;\r\n\t\tdelete sp_last_stored_random;\r\n\t\t\r\n\t\tsp_last_stored_random=p_new_last;\r\n\t\tif (p_new_last)\r\n\t\t{\r\n\t\t\tp_new_last->mpNext=NULL;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\tCStoredRandom *p_new=new CStoredRandom;\r\n\tp_new->mpNext=sp_first_stored_random;\r\n\tp_new->mpPrevious=NULL;\r\n\t\r\n\tif (sp_first_stored_random)\r\n\t{\r\n\t\tsp_first_stored_random->mpPrevious=p_new;\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(sp_last_stored_random==NULL,(\"sp_last_stored_random not NULL?\"));\r\n\t\tsp_last_stored_random=p_new;\r\n\t}\r\n\t\r\n\tsp_first_stored_random=p_new;\r\n\treturn p_new;\r\n}\r\n\r\nS4Bytes Read4Bytes(const uint8 *p_long)\r\n{\r\n    S4Bytes four_bytes;\r\n\t\r\n\t#ifdef __PLAT_NGPS__\r\n\tif ( (((uint32)p_long)&3)==0 )\r\n\t{\r\n\t\t// Small speed opt\r\n\t\tfour_bytes.mUInt=*(uint32*)p_long;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfour_bytes.mUInt=(p_long[0])|(p_long[1]<<8)|(p_long[2]<<16)|(p_long[3]<<24);\r\n\t}\t\r\n\t#else\r\n\tfour_bytes.mUInt=(p_long[0])|(p_long[1]<<8)|(p_long[2]<<16)|(p_long[3]<<24);\r\n\t#endif\r\n    return four_bytes;\r\n}\r\n\r\n// Gets 2 bytes from p_short, which may not be long word aligned.\r\nS2Bytes Read2Bytes(const uint8 *p_short)\r\n{\r\n    S2Bytes two_bytes;\r\n    two_bytes.mUInt=p_short[0]|(p_short[1]<<8);\r\n    return two_bytes;\r\n}\r\n\r\n// Used by WriteToBuffer and ReadFromBuffer in utils.cpp\r\n// Moved to parse.cpp just so that all these byte reading/writing functions are in one place.\r\nuint8 *Write4Bytes(uint8 *p_buffer, uint32 val)\r\n{\r\n\t*p_buffer++=val;\r\n\t*p_buffer++=val>>8;\r\n\t*p_buffer++=val>>16;\r\n\t*p_buffer++=val>>24;\r\n\treturn p_buffer;\r\n}\r\n\r\nuint8 *Write4Bytes(uint8 *p_buffer, float floatVal)\r\n{\r\n\tuint32 val=*(uint32*)&floatVal;\r\n\t*p_buffer++=val;\r\n\t*p_buffer++=val>>8;\r\n\t*p_buffer++=val>>16;\r\n\t*p_buffer++=val>>24;\r\n\treturn p_buffer;\r\n}\r\n\r\nuint8 *Write2Bytes(uint8 *p_buffer, uint16 val)\r\n{\r\n\t*p_buffer++=val;\r\n\t*p_buffer++=val>>8;\r\n\treturn p_buffer;\r\n}\r\n\r\n// Skips over end-of-line tokens.    \r\nuint8 *SkipEndOfLines(uint8 *p_token)\r\n{\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token\"));\r\n    while (true)\r\n    {\r\n\t\tif (*p_token==ESCRIPTTOKEN_ENDOFLINE)\r\n\t\t{\r\n            ++p_token;\r\n\t\t}\t\r\n        else if (*p_token==ESCRIPTTOKEN_ENDOFLINENUMBER)\r\n\t\t{\r\n            // ESCRIPTTOKEN_ENDOFLINENUMBER contains the line number of the previous line,\r\n            // so that the line number of errors can be displayed.\r\n            p_token+=5;\r\n\t\t}\t\r\n        else   \r\n\t\t{\r\n            break;\r\n\t\t}\t\r\n    }\r\n    return p_token;\r\n}\r\n\r\nCStoredRandom::CStoredRandom()\r\n{\r\n\tmpNext=NULL;\r\n\tmpPrevious=NULL;\r\n\t\r\n\t++s_num_stored_randoms;\r\n}\r\n\r\nCStoredRandom::~CStoredRandom()\r\n{\r\n\t--s_num_stored_randoms;\r\n}\r\n\r\n// This gets called whenever CScript::ClearScript is called.\r\nvoid ReleaseStoredRandoms(CScript *p_script)\r\n{\r\n\tCStoredRandom *p_search=sp_first_stored_random;\r\n\twhile (p_search)\r\n\t{\r\n\t\tif (p_search->mpScript==p_script)\r\n\t\t{\r\n\t\t\tp_search->mpScript=NULL;\r\n\t\t}\r\n\t\tp_search=p_search->mpNext;\r\n\t}\t\r\n}\r\n\r\nvoid CStoredRandom::InitIndices()\r\n{\r\n\tDbg_MsgAssert(mNumItems<=MAX_RANDOM_INDICES,(\"mNumItems too big\"));\r\n\t\r\n\tfor (uint16 i=0; i<mNumItems; ++i)\r\n\t{\r\n\t\tmpIndices[i]=i;\r\n\t}\t\r\n}\r\n\r\nvoid CStoredRandom::RandomizeIndices(bool makeNewFirstDifferFromOldLast)\r\n{\r\n\tDbg_MsgAssert(mNumItems>=2,(\"mNumItems must be at least 2 for RandomNoRepeat\"));\r\n\tuint8 last=mpIndices[mNumItems-1];\r\n\t\r\n\tuint32 num_iterations=10*mNumItems;\r\n\tfor (uint32 n=0; n<num_iterations; ++n)\r\n\t{\r\n\t\tint a=Mth::Rnd(mNumItems);\r\n\t\tint b=Mth::Rnd(mNumItems);\r\n\t\tuint8 temp=mpIndices[a];\r\n\t\tmpIndices[a]=mpIndices[b];\r\n\t\tmpIndices[b]=temp;\r\n\t}\r\n\t\r\n\tif (makeNewFirstDifferFromOldLast && mpIndices[0]==last)\r\n\t{\r\n\t\tint a=0;\r\n\t\tint b=1+Mth::Rnd(mNumItems-1);\r\n\t\tuint8 temp=mpIndices[a];\r\n\t\tmpIndices[a]=mpIndices[b];\r\n\t\tmpIndices[b]=temp;\r\n\t}\t\r\n}\r\n\r\n// If p_token points to a random or jump token, then this will execute it,\r\n// and repeat until no more randoms or jumps.\r\n//\r\n// Returns the new p_token, which is all this function modifies.\r\nuint8 *DoAnyRandomsOrJumps(uint8 *p_token)\r\n{\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token\"));\r\n\t\r\n\twhile (true)\r\n\t{\r\n\t\tbool finished=false;\r\n\r\n\t\tuint8 token=*p_token;\r\n\t\tswitch (token)\r\n\t\t{\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM2:\r\n\t\t{\r\n\t\t\t++p_token; // Skip over the token.\r\n\t\t\tuint32 num_items=Read4Bytes(p_token).mUInt;\r\n\t\t\tDbg_MsgAssert(num_items,(\"Zero num_items in random operator ?\"));\r\n\t\t\tp_token+=4; \t\t\t\t\t\t\t// Skip over the num_items\r\n\t\t\t\r\n\t\t\t// Calculate the sum of the weights\r\n\t\t\tint sum_of_weights=0;\r\n\t\t\tuint8 *p_weights=p_token;\r\n\t\t\tfor (uint32 i=0; i<num_items; ++i)\r\n\t\t\t{\r\n\t\t\t\tsum_of_weights+=Read2Bytes(p_weights).mInt;\r\n\t\t\t\tp_weights+=2;\r\n\t\t\t}\t\r\n\t\t\tDbg_MsgAssert(sum_of_weights<=32767,(\"sum_of_weights too big\"));\r\n\t\t\tint r;\r\n\t\t\tif (token==ESCRIPTTOKEN_KEYWORD_RANDOM)\r\n\t\t\t{\r\n\t\t\t\tr=Mth::Rnd(sum_of_weights);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\t\t\t \r\n\t\t\t\tr=Mth::Rnd2(sum_of_weights);\r\n\t\t\t}\t\r\n\t\t\tuint32 chosen_index=0;\r\n\t\t\tp_weights=p_token;\r\n\t\t\twhile (true)\r\n\t\t\t{\r\n\t\t\t\tr-=Read2Bytes(p_weights).mInt;\r\n\t\t\t\tif (r<0)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\tp_weights+=2;\r\n\t\t\t\t++chosen_index;\r\n\t\t\t\tDbg_MsgAssert(chosen_index<num_items,(\"chosen_index >= num_items ???\"));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tp_token+=2*num_items;\t\t\t\t\t// Skip over the weights\r\n\t\t\tp_token+=4*chosen_index;\t\t\t\t// Jump to the chosen offset value\r\n\t\t\tsint32 offset=Read4Bytes(p_token).mInt;\t// Get the offset\r\n\t\t\tp_token+=4; \t\t\t\t\t\t\t// Skip over the offset\r\n\t\t\tp_token+=offset;\t\t\t\t\t\t// Jump to the item\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_NO_REPEAT:\r\n\t\t{\r\n\t\t\t++p_token; // Skip over the token.\r\n\t\t\tuint32 num_items=Read4Bytes(p_token).mUInt;\r\n\t\t\tDbg_MsgAssert(num_items>1,(\"num_items must be greater than 1 in RandomNoRepeat operator\"));\r\n\t\t\tp_token+=4; // Skip over the num_items\r\n\t\t\tp_token+=2*num_items;\t\t\t\t\t// TODO: Skip over weights\r\n\t\t\t\r\n\t\t\tCStoredRandom *p_stored=sFindStoredRandom(p_token,ESCRIPTTOKEN_KEYWORD_RANDOM_NO_REPEAT,num_items);\r\n\t\t\tif (!p_stored)\r\n\t\t\t{\r\n\t\t\t\tp_stored=sCreateNewStoredRandom();\r\n\t\t\t\tDbg_MsgAssert(p_stored,(\"NULL return value from sCreateNewStoredRandom()\"));\r\n\t\t\t\tp_stored->mpToken=p_token;\r\n\t\t\t\tp_stored->mType=ESCRIPTTOKEN_KEYWORD_RANDOM_NO_REPEAT;\r\n\t\t\t\tp_stored->mNumItems=num_items;\r\n\t\t\t\t\r\n\t\t\t\tp_stored->mLastIndex=Mth::Rnd(num_items);\r\n\t\t\t}\r\n\t\t\tp_stored->mpScript=GetCurrentScript();\r\n\t\t\t\r\n\t\t\tuint16 jump_index=Mth::Rnd(num_items);\r\n\t\t\t// num_items is bigger than one, so in theory it should never get stuck in\r\n\t\t\t// an infinite loop here ...\r\n\t\t\tint c=0; // But have a counter just in case \r\n\t\t\twhile (jump_index==p_stored->mLastIndex)\r\n\t\t\t{\r\n\t\t\t\t++c;\r\n\t\t\t\tif (c>100) break;\r\n\t\t\t\tjump_index=Mth::Rnd(num_items);\r\n\t\t\t}\t\r\n\t\t\tp_stored->mLastIndex=jump_index;\r\n\t\t\t\r\n\t\t\tp_token+=4*jump_index;\t// Jump to the offset\r\n\t\t\tsint32 offset=Read4Bytes(p_token).mInt;\t// Get the offset\r\n\t\t\tp_token+=4; \t\t\t\t\t\t\t// Skip over the offset\r\n\t\t\tp_token+=offset;\t\t\t\t\t\t// Jump to the item\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_PERMUTE:\r\n\t\t{\r\n\t\t\t++p_token; // Skip over the token.\r\n\t\t\tuint32 num_items=Read4Bytes(p_token).mUInt;\r\n\t\t\tDbg_MsgAssert(num_items,(\"Zero num_items in random operator ?\"));\r\n\t\t\tp_token+=4; // Skip over the num_items\r\n\t\t\tp_token+=2*num_items;\t\t\t\t\t// TODO: Skip over weights\r\n\t\t\t\r\n\t\t\tCStoredRandom *p_stored=sFindStoredRandom(p_token,ESCRIPTTOKEN_KEYWORD_RANDOM_PERMUTE,num_items);\r\n\t\t\tif (!p_stored)\r\n\t\t\t{\r\n\t\t\t\tp_stored=sCreateNewStoredRandom();\r\n\t\t\t\tDbg_MsgAssert(p_stored,(\"NULL return value from sCreateNewStoredRandom()\"));\r\n\t\t\t\tp_stored->mpToken=p_token;\r\n\t\t\t\tp_stored->mType=ESCRIPTTOKEN_KEYWORD_RANDOM_PERMUTE;\r\n\t\t\t\tp_stored->mNumItems=num_items;\r\n\r\n\t\t\t\tp_stored->mCurrentIndex=0;\r\n\t\t\t\tDbg_MsgAssert(num_items<=MAX_RANDOM_INDICES,(\"Too many entries in RandomPermute, max is %d. Line %d of file %s\",MAX_RANDOM_INDICES,GetLineNumber(p_token),GetSourceFile(p_token)));\r\n\t\t\t\r\n\t\t\t\tp_stored->InitIndices();\r\n\t\t\t\tp_stored->RandomizeIndices();\r\n\t\t\t}\r\n\t\t\tp_stored->mpScript=GetCurrentScript();\r\n\t\t\t\r\n\t\t\t++p_stored->mCurrentIndex;\r\n\t\t\tif (p_stored->mCurrentIndex>=p_stored->mNumItems)\r\n\t\t\t{\r\n\t\t\t\tp_stored->RandomizeIndices(MAKE_NEW_FIRST_DIFFER_FROM_OLD_LAST);\r\n\t\t\t\tp_stored->mCurrentIndex=0;\r\n\t\t\t}\r\n\t\t\tuint16 jump_index=p_stored->mpIndices[p_stored->mCurrentIndex];\r\n\t\t\tDbg_MsgAssert(jump_index<num_items,(\"Eh? jump_index out of range ?\"));\r\n\t\t\t\r\n\t\t\tp_token+=4*jump_index;\t// Jump to the offset\r\n\t\t\tsint32 offset=Read4Bytes(p_token).mInt;\t// Get the offset\r\n\t\t\tp_token+=4; \t\t\t\t\t\t\t// Skip over the offset\r\n\t\t\tp_token+=offset;\t\t\t\t\t\t// Jump to the item\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase ESCRIPTTOKEN_JUMP:\r\n\t\t{\r\n\t\t\t++p_token; // Skip over the jump token.\r\n            sint32 offset=Read4Bytes(p_token).mInt;\r\n\t\t\tp_token+=4; // Skip over the offset\r\n\t\t\tp_token+=offset; // Do the jump\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tfinished=true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tif (finished)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t}\r\n\treturn p_token;\r\n}\t\t\r\n\r\n// Returns the pointer to after the script.\r\nuint8 *SkipOverScript(uint8 *p_token)\r\n{\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token\"));\r\n\t\r\n\twhile (*p_token!=ESCRIPTTOKEN_KEYWORD_ENDSCRIPT) \r\n\t{\r\n\t\tp_token=SkipToken(p_token);\r\n\t}\t\r\n\tp_token=SkipToken(p_token); // Skip over the ESCRIPTTOKEN_KEYWORD_ENDSCRIPT\r\n\t\r\n\t// Include any line number info following the endscript. This is for use by the script\r\n\t// debugger, so that GetLineNumber will still work if the passed pointer points to an\r\n\t// endscript token.\r\n\tif (*p_token==ESCRIPTTOKEN_ENDOFLINENUMBER)\r\n\t{\r\n\t\tp_token=SkipToken(p_token);\r\n\t}\r\n\t\t\r\n\treturn p_token;\r\n}\r\n\r\n// Calculates the checksum of a script, but ignores end-of-line tokens.\r\n// This is used when reloading a script to detect whether the script has changed. If a script has\r\n// changed, any instances of that script that are running will get restarted.\r\n// Want to ignore end-of-lines and end-of-line-number tokens so that inserting or\r\n// deleting lines won't cause all the scripts after that line to restart.\r\nuint32 CalculateScriptContentsChecksum(uint8 *p_token)\r\n{\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token\"));\r\n\r\n\tuint32 checksum=0xffffffff;\r\n\t\t\r\n\twhile (*p_token != ESCRIPTTOKEN_KEYWORD_ENDSCRIPT) \r\n\t{\r\n\t\tuint8 *p_last_token=p_token;\r\n\t\tp_token=SkipToken(p_token);\r\n\r\n\t\t// Only include non end-of-line tokens in the checksum calculation.\t\t\r\n\t\tif (*p_last_token != ESCRIPTTOKEN_ENDOFLINE &&\r\n\t\t\t*p_last_token != ESCRIPTTOKEN_ENDOFLINENUMBER)\r\n\t\t{\r\n\t\t\tint num_bytes=p_token-p_last_token;\r\n\t\t\tchecksum=Crc::UpdateCRC((const char*)p_last_token,num_bytes,checksum);\r\n\t\t}\r\n\t}\t\r\n\t\r\n\treturn checksum;\r\n}\r\n\r\n// Given a token pointer, this will return the line number in the source q file.\r\n// If it can't find a line number it returns 0. (Valid line numbers start at 1)\r\n// If it gets to the end of the file it returns -1.\r\n// If it gets to the end of a script it returns -2.\r\n//\r\n// Note: Perhaps make this compile to nothing for X-Box, since it is often used in asserts and I think\r\n// the X-box will always execute functions in asserts, making parsing very slow. (Check with Dave)\r\nint GetLineNumber(uint8 *p_token)\r\n{\r\n\tif (!p_token)\r\n\t{\r\n\t\treturn 0;\r\n\t}\t\r\n\t\r\n    switch (*p_token)\r\n\t{\r\n\t    case ESCRIPTTOKEN_ENDOFFILE:\r\n\t    case ESCRIPTTOKEN_ENDOFLINE:\r\n\t    case ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t    case ESCRIPTTOKEN_STARTSTRUCT:\r\n\t    case ESCRIPTTOKEN_ENDSTRUCT:\r\n\t    case ESCRIPTTOKEN_STARTARRAY:\r\n\t    case ESCRIPTTOKEN_ENDARRAY:\r\n\t    case ESCRIPTTOKEN_EQUALS:\r\n\t    case ESCRIPTTOKEN_DOT:\r\n\t    case ESCRIPTTOKEN_COMMA:\r\n\t    case ESCRIPTTOKEN_MINUS:\r\n\t    case ESCRIPTTOKEN_ADD:\r\n\t    case ESCRIPTTOKEN_DIVIDE:\r\n\t    case ESCRIPTTOKEN_MULTIPLY:\r\n\t    case ESCRIPTTOKEN_OPENPARENTH:\r\n\t    case ESCRIPTTOKEN_CLOSEPARENTH:\r\n\t    case ESCRIPTTOKEN_DEBUGINFO:\r\n\t    case ESCRIPTTOKEN_SAMEAS:\r\n\t    case ESCRIPTTOKEN_LESSTHAN:\r\n\t    case ESCRIPTTOKEN_LESSTHANEQUAL:\r\n\t    case ESCRIPTTOKEN_GREATERTHAN:\r\n\t    case ESCRIPTTOKEN_GREATERTHANEQUAL:\r\n\t    case ESCRIPTTOKEN_NAME:\r\n\t    case ESCRIPTTOKEN_INTEGER:\r\n\t    case ESCRIPTTOKEN_HEXINTEGER:\r\n        case ESCRIPTTOKEN_ENUM:\r\n\t    case ESCRIPTTOKEN_FLOAT:\r\n\t    case ESCRIPTTOKEN_STRING:\r\n\t    case ESCRIPTTOKEN_LOCALSTRING:\r\n\t    case ESCRIPTTOKEN_ARRAY:\r\n\t    case ESCRIPTTOKEN_VECTOR:\r\n\t    case ESCRIPTTOKEN_PAIR:\r\n\t    case ESCRIPTTOKEN_KEYWORD_BEGIN:\r\n\t    case ESCRIPTTOKEN_KEYWORD_REPEAT:\r\n\t    case ESCRIPTTOKEN_KEYWORD_BREAK:\r\n\t    case ESCRIPTTOKEN_KEYWORD_SCRIPT:\r\n\t    case ESCRIPTTOKEN_KEYWORD_ENDSCRIPT:\r\n\t    case ESCRIPTTOKEN_KEYWORD_IF:\r\n\t    case ESCRIPTTOKEN_KEYWORD_ELSE:\r\n\t    case ESCRIPTTOKEN_KEYWORD_ELSEIF:\r\n\t    case ESCRIPTTOKEN_KEYWORD_ENDIF:\r\n\t    case ESCRIPTTOKEN_KEYWORD_RETURN:\r\n\t    case ESCRIPTTOKEN_KEYWORD_NOT:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_SWITCH:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ENDSWITCH:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_CASE:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_DEFAULT:\r\n        case ESCRIPTTOKEN_UNDEFINED:\r\n\t    case ESCRIPTTOKEN_CHECKSUM_NAME:\r\n\t    case ESCRIPTTOKEN_KEYWORD_ALLARGS:\r\n\t    case ESCRIPTTOKEN_ARG:\t\r\n\t\tcase ESCRIPTTOKEN_JUMP:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM2:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_NO_REPEAT:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_PERMUTE:\r\n\t\tcase ESCRIPTTOKEN_OR:\r\n\t\tcase ESCRIPTTOKEN_AND:\r\n\t\tcase ESCRIPTTOKEN_XOR:\r\n\t\tcase ESCRIPTTOKEN_SHIFT_LEFT:\r\n\t\tcase ESCRIPTTOKEN_SHIFT_RIGHT:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE2:\r\n\t\tcase ESCRIPTTOKEN_COLON:\r\n\t\tcase ESCRIPTTOKEN_RUNTIME_CFUNCTION:\r\n\t\tcase ESCRIPTTOKEN_RUNTIME_MEMBERFUNCTION:\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"p_token does not point to a token in call to GetLineNumber\"));\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\t\r\n    while (true)\r\n    {\r\n        switch (*p_token)\r\n\t\t{\r\n\t\tcase ESCRIPTTOKEN_ENDOFLINE:\r\n\t\t\treturn 0;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t\t++p_token;\r\n\t\t\treturn Read4Bytes(p_token).mInt;\r\n            break;\r\n\t\t\r\n\t\tcase ESCRIPTTOKEN_ENDOFFILE:\r\n\t\t\treturn -1;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ENDSCRIPT:\r\n\t\t\tp_token=SkipToken(p_token);\r\n\t\t\tif (*p_token==ESCRIPTTOKEN_ENDOFLINENUMBER)\r\n\t\t\t{\r\n\t\t\t\t// Continue so that the ENDOFLINENUMBER case catches this next time round the loop.\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Cannot continue searching because we've gone off the end\r\n\t\t\t\t// of the memory block allocated for the script.\r\n\t\t\t\treturn -2;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tp_token=SkipToken(p_token);\r\n\t\t\tbreak;\t\t\r\n\t\t}\t\r\n    }\r\n}\r\n\r\n// Returns true if the passed p_token points somewhere in the passed p_script.\r\nbool PointsIntoScript(uint8 *p_token, uint8 *p_script)\r\n{\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token\"));\r\n\tDbg_MsgAssert(p_script,(\"NULL p_script\"));\r\n\t\r\n\t// Scan through the whole script to see if p_token points to\r\n\t// a token in it. Blimey.\r\n\twhile (*p_script!=ESCRIPTTOKEN_KEYWORD_ENDSCRIPT)\r\n\t{\r\n\t\tif (p_script==p_token)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tp_script=SkipToken(p_script);\r\n\t}\t\t\r\n\t\r\n\treturn false;\r\n}\r\n\r\n// Given a pointer to a token, this will try and find out what source file this is in.\r\nconst char *GetSourceFile(uint8 *p_token)\r\n{\r\n\t// It may be that GetSourceFile was called due to an error when creating a script global.\r\n\t// In this case the source file cannot be determined from p_token since the qb is loaded into\r\n\t// a temporary buffer, but ParseQB will have set s_qb_being_parsed.\r\n\tif (s_qb_being_parsed)\r\n\t{\r\n\t\treturn FindChecksumName(s_qb_being_parsed);\r\n\t}\r\n\r\n\t#ifdef NO_SCRIPT_CACHING\r\n\t// If there is no script caching, then the symbol table entries for each script contain pointers\r\n\t// to the uncompressed scripts, so it is possible to scan through them checking if p_token points\r\n\t// into one of them.\r\n\t\r\n\t// Check if pToken points into any of the scripts currently loaded.\r\n\tCSymbolTableEntry *p_sym=GetNextSymbolTableEntry(NULL);\r\n\twhile (p_sym)\r\n\t{\r\n\t\t// For every script ...\r\n\t\tif (p_sym->mType==ESYMBOLTYPE_QSCRIPT)\r\n\t\t{\r\n\t\t\tuint8 *p_script=p_sym->mpScript;\r\n\t\t\tDbg_MsgAssert(p_script,(\"NULL p_sym->mpScript ?\"));\r\n\t\t\t// Skip over the contents checksum.\r\n\t\t\tp_script+=4;\r\n\t\t\t\r\n\t\t\tif (PointsIntoScript(p_token,p_script))\r\n\t\t\t{\r\n\t\t\t\treturn FindChecksumName(p_sym->mSourceFileNameChecksum);\r\n\t\t\t}\t\t\r\n\t\t}\r\n\t\tp_sym=GetNextSymbolTableEntry(p_sym);\r\n\t}\r\n\t#else\r\n\t\r\n\t// Script caching is on, so query the script cache to find out what the script name is.\r\n\t// Cannot scan through the symbols mpScript's as above because when script caching is\r\n\t// on mpScript will point to compressed data, which cannot be stepped through.\r\n\t// So ask the script cache to step through its decompressed scripts instead.\r\n\tScript::CScriptCache *p_script_cache=Script::CScriptCache::Instance();\r\n\tDbg_MsgAssert(p_script_cache,(\"NULL p_script_cache\"));\r\n\treturn p_script_cache->GetSourceFile(p_token);\r\n\t\r\n\t#endif\r\n\t\r\n\t// Oh well.\r\n\treturn \"Unknown\";\t\r\n}\r\n\r\n#if 0\r\nvoid CalcSpaceUsedByLineNumberInfo()\r\n{\r\n\tint space_used=0;\r\n\t\r\n\tCSymbolTableEntry *p_sym=GetNextSymbolTableEntry(NULL);\r\n\twhile (p_sym)\r\n\t{\r\n\t\t// For every script ...\r\n\t\tif (p_sym->mType==ESYMBOLTYPE_QSCRIPT)\r\n\t\t{\r\n\t\t\tuint8 *p_script=p_sym->mpScript;\r\n\t\t\tDbg_MsgAssert(p_script,(\"NULL p_sym->mpScript ?\"));\r\n\t\t\t// Skip over the contents checksum.\r\n\t\t\tp_script+=4;\r\n\t\t\t\r\n\t\t\t// Scan through the whole script looking for line number tokens.\r\n\t\t\twhile (*p_script!=ESCRIPTTOKEN_KEYWORD_ENDSCRIPT)\r\n\t\t\t{\r\n\t\t\t\tif (*p_script==ESCRIPTTOKEN_ENDOFLINENUMBER)\r\n\t\t\t\t{\r\n\t\t\t\t\tspace_used+=4;\r\n\t\t\t\t}\t\r\n\t\t\t\tp_script=SkipToken(p_script);\r\n\t\t\t}\t\t\r\n\t\t}\r\n\t\tp_sym=GetNextSymbolTableEntry(p_sym);\r\n\t}\r\n\tprintf(\"Script heap space used by line number info = %d bytes\\n\");\r\n}\r\n#endif\r\n\r\nuint8 *FillInComponentUsingQB(uint8 *p_token, CStruct *p_args, CComponent *p_comp)\r\n{\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token\"));\r\n\tDbg_MsgAssert(p_comp,(\"NULL p_comp\"));\r\n\tbool use_rnd2=false;\r\n\t\r\n\tswitch (*p_token++)\r\n\t{\r\n\t\tcase ESCRIPTTOKEN_INTEGER:\r\n\t\t\tp_comp->mType=ESYMBOLTYPE_INTEGER;\r\n\t\t\tp_comp->mIntegerValue=Read4Bytes(p_token).mInt;\r\n\t\t\tp_token+=4;\r\n\t\t\tbreak;\r\n\t\tcase ESCRIPTTOKEN_FLOAT:\r\n\t\t\tp_comp->mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\tp_comp->mFloatValue=Read4Bytes(p_token).mFloat;\r\n\t\t\tp_token+=4;\r\n\t\t\tbreak;\r\n\t\tcase ESCRIPTTOKEN_NAME:\r\n\t\t\tp_comp->mType=ESYMBOLTYPE_NAME;\r\n\t\t\tp_comp->mChecksum=Read4Bytes(p_token).mChecksum;\r\n\t\t\tp_token+=4;\r\n\t\t\tbreak;\r\n\t\tcase ESCRIPTTOKEN_STRING:\r\n\t\t{\r\n\t\t\tp_comp->mType=ESYMBOLTYPE_STRING;\r\n\t\t\tint len=Read4Bytes(p_token).mInt;\r\n\t\t\tp_token+=4;\r\n\t\t\tp_comp->mpString=CreateString((const char *)p_token);\r\n\t\t\tp_token+=len;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase ESCRIPTTOKEN_LOCALSTRING:\r\n\t\t{\r\n\t\t\tp_comp->mType=ESYMBOLTYPE_LOCALSTRING;\r\n\t\t\tint len=Read4Bytes(p_token).mInt;\r\n\t\t\tp_token+=4;\r\n\t\t\tp_comp->mpString=CreateString((const char *)p_token);\r\n\t\t\tp_token+=len;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase ESCRIPTTOKEN_VECTOR:\r\n\t\t{\r\n\t\t\tp_comp->mType=ESYMBOLTYPE_VECTOR;\r\n\t\t\tfloat x=Read4Bytes(p_token).mFloat;\r\n\t\t\tp_token+=4;\r\n\t\t\tfloat y=Read4Bytes(p_token).mFloat;\r\n\t\t\tp_token+=4;\r\n\t\t\tfloat z=Read4Bytes(p_token).mFloat;\r\n\t\t\tp_token+=4;\r\n\t\t\tp_comp->mpVector=new CVector;\r\n\t\t\tp_comp->mpVector->mX=x;\r\n\t\t\tp_comp->mpVector->mY=y;\r\n\t\t\tp_comp->mpVector->mZ=z;\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase ESCRIPTTOKEN_PAIR:\r\n\t\t{\r\n\t\t\tp_comp->mType=ESYMBOLTYPE_PAIR;\r\n\t\t\tfloat x=Read4Bytes(p_token).mFloat;\r\n\t\t\tp_token+=4;\r\n\t\t\tfloat y=Read4Bytes(p_token).mFloat;\r\n\t\t\tp_token+=4;\r\n\t\t\tp_comp->mpPair=new CPair;\r\n\t\t\tp_comp->mpPair->mX=x;\r\n\t\t\tp_comp->mpPair->mY=y;\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase ESCRIPTTOKEN_STARTSTRUCT:\r\n\t\t{\r\n\t\t\t// Rewind p_token to point to ESCRIPTTOKEN_STARTSTRUCT, because the \r\n\t\t\t// sAddComponentsWithinCurlyBraces call requires it.\r\n\t\t\t--p_token;\r\n\t\t\t\r\n\t\t\t// No need to set which heap we're using, cos CStruct's and their CComponent's come off\r\n\t\t\t// their own pools.\r\n\t\t\tCStruct *p_structure=new CStruct;\r\n\t\t\tp_token=sAddComponentsWithinCurlyBraces(p_structure,p_token,p_args);\r\n\t\t\t\r\n\t\t\tp_comp->mType=ESYMBOLTYPE_STRUCTURE;\r\n\t\t\tp_comp->mpStructure=p_structure;\r\n\t\t\tbreak;\r\n\t\t}    \r\n\t\tcase ESCRIPTTOKEN_STARTARRAY:\r\n\t\t{\r\n\t\t\t// Rewind p_token to point to ESCRIPTTOKEN_STARTARRAY, because the CArray::Parse call requires it.\r\n\t\t\t--p_token;\r\n\t\t\t\r\n\t\t\t// The CArray constructor is not hard-wired to use the script heap for it's buffer, so need\r\n\t\t\t// to make sure we're using the script heap here.\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\t\tCArray *p_array=new CArray;\r\n\t\t\tMem::Manager::sHandle().PopContext();\t\t\t\r\n\t\t\t\r\n\t\t\tp_token=sInitArrayFromQB(p_array,p_token,p_args);\r\n\t\t\t\r\n\t\t\tp_comp->mType=ESYMBOLTYPE_ARRAY;\r\n\t\t\tp_comp->mpArray=p_array;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE2:\r\n\t\t\tuse_rnd2=true;\r\n\t\t\t// Intentional lack of a break here.\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE:\r\n\t\t{\r\n\t\t\tp_token=sCalculateRandomRange(p_token,p_comp,use_rnd2);\r\n\t\t\tbreak;\r\n\t\t}    \r\n\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_SCRIPT:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(*p_token==ESCRIPTTOKEN_NAME,(\"\\nKeyword 'script' must be followed by a name, line %d (file name not known, sorry)\",GetLineNumber(p_token)));\r\n\t\t\t++p_token; // Skip over the ESCRIPTTOKEN_NAME\r\n\t\t\tp_comp->mNameChecksum=Read4Bytes(p_token).mChecksum;\r\n\t\t\tp_token+=4; // Skip over the name checksum\r\n\t\t\t\r\n\t\t\t// Skip p_token over the script tokens, and calculate the size.\r\n\t\t\tconst uint8 *p_script=p_token;\r\n\t\t\tp_token=SkipOverScript(p_token);\r\n\t\t\tuint32 size=p_token-p_script;\r\n\t\t\t\r\n\t\t\tp_comp->mType=ESYMBOLTYPE_QSCRIPT;\r\n\t\t\t\r\n\t\t\t// Allocate a buffer off the script heap\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\t\tDbg_MsgAssert(size,(\"Zero script size\"));\r\n\t\t\tuint8 *p_new_script=(uint8*)Mem::Malloc(size);\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\r\n\t\t\t// Copy the script into the new buffer.\r\n\t\t\tconst uint8 *p_source=p_script;\r\n\t\t\tuint8 *p_dest=p_new_script;\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\t*p_dest++=*p_source++;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\t// Give the new buffer to the component.\r\n\t\t\tp_comp->mpScript=p_new_script;\r\n\t\t\t\r\n \t\t\tbreak;\r\n\t\t}\t\r\n\r\n\t\tcase ESCRIPTTOKEN_ARG:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(*p_token==ESCRIPTTOKEN_NAME,(\"Expected '<' token to be followed by a name, File %s, line %d\",GetSourceFile(p_token),GetLineNumber(p_token)));\r\n\t\t\t++p_token;\r\n\t\t\tuint32 arg_checksum=Read4Bytes(p_token).mChecksum;\r\n\t\t\tp_token+=4;\r\n\t\t\tif (p_args)\r\n\t\t\t{\r\n\t\t\t\t// Look for a parameter named arg_checksum in p_args, recursing into any referenced structures\r\n\t\t\t\tCComponent *p_found=p_args->FindNamedComponentRecurse(arg_checksum);\r\n\t\t\t\tif (p_found)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Note: There is no copy-constructor for CComponent, because that would cause a\r\n\t\t\t\t\t// cyclic dependency between component.cpp/h and struct.cpp/h.\r\n\t\t\t\t\t// Instead, use the CopyComponent function defined in struct.cpp\r\n\t\t\t\t\tCopyComponent(p_comp,p_found);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\t\r\n\t\t}\r\n\t\t\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ALLARGS:\r\n\t\t{\r\n\t\t\tif (p_args)\r\n\t\t\t{\r\n\t\t\t\tCStruct *p_structure=new CStruct;\r\n\t\t\t\t*p_structure=*p_args;\r\n\t\t\t\t\r\n\t\t\t\tp_comp->mType=ESYMBOLTYPE_STRUCTURE;\r\n\t\t\t\tp_comp->mpStructure=p_structure;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\treturn p_token;\t\r\n}\r\n\r\n// This will evaluate the expression pointed to by p_token.\r\n// Any args referred to by the <,> symbols are looked for in p_args.\r\n\r\n// Expressions are terminated by any token that does not make sense as part of the expression.\r\n// If the expression gets terminated unexpectedly, eg if there are still open braces, \r\n// then it will assert.\r\nstatic CExpressionEvaluator sExpressionEvaluator;\r\n\r\nvoid EnableExpressionEvaluatorErrorChecking()\r\n{\r\n\tsExpressionEvaluator.EnableErrorChecking();\r\n}\r\n\r\nvoid DisableExpressionEvaluatorErrorChecking()\r\n{\r\n\tsExpressionEvaluator.DisableErrorChecking();\r\n}\r\n\t\r\nstatic CComponent sTemp;\r\nuint8 *Evaluate(uint8 *p_token, CStruct *p_args, CComponent *p_result)\r\n{\r\n\tDbg_MsgAssert(p_result,(\"NULL p_result\"));\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token\"));\r\n\t\r\n\t// SPEEDOPT: Make the Clear function faster\r\n\tsExpressionEvaluator.ClearIfNeeded();\r\n\tsExpressionEvaluator.SetTokenPointer(p_token);\r\n\t\r\n\tDbg_MsgAssert(*p_token==ESCRIPTTOKEN_OPENPARENTH,(\"Expected expression to begin with a '(', at line %d of %s\",GetLineNumber(p_token),GetSourceFile(p_token)));\r\n\t++p_token;\r\n\t\r\n\tint parenth_count=0;\r\n\tbool generate_minus_operator=false;\r\n\tbool expecting_value=true;\r\n\tbool operator_is_dot=false;\r\n\t\r\n\tbool in_expression=true;\r\n\twhile (in_expression)\r\n\t{\r\n\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\tuint8 token_value=*p_token;\r\n\t\t\r\n\t\tswitch (token_value)\t\r\n\t\t{\r\n\t\tcase ESCRIPTTOKEN_OPENPARENTH:\r\n\t\t\tif (!expecting_value)\r\n\t\t\t{\r\n\t\t\t\tin_expression=false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t++p_token;\r\n\t\t\tsExpressionEvaluator.OpenParenthesis();\r\n\t\t\tgenerate_minus_operator=false;\r\n\t\t\texpecting_value=true;\r\n\t\t\t++parenth_count;\r\n\t\t\tbreak;\r\n\t\tcase ESCRIPTTOKEN_CLOSEPARENTH:\r\n\t\t\t++p_token;\r\n\t\t\tif (parenth_count)\r\n\t\t\t{\r\n\t\t\t\tsExpressionEvaluator.CloseParenthesis();\r\n\t\t\t\tgenerate_minus_operator=true;\r\n\t\t\t\texpecting_value=false;\r\n\t\t\t\t--parenth_count;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tin_expression=false;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESCRIPTTOKEN_INTEGER:\r\n\t\t\tif (expecting_value)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(!generate_minus_operator,(\"Eh? generate_minus_operator is set?\"));\r\n\t\t\t\tp_token=FillInComponentUsingQB(p_token,p_args,&sTemp);\r\n\t\t\t\t\r\n\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\tCleanUpComponent(&sTemp);\r\n\t\t\t\tgenerate_minus_operator=true;\r\n\t\t\t\texpecting_value=false;\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tuint8 *p_new_token=FillInComponentUsingQB(p_token,p_args,&sTemp);\r\n\t\t\t\t\r\n\t\t\t\tif (sTemp.mIntegerValue<0 && generate_minus_operator)\r\n\t\t\t\t{\r\n\t\t\t\t\tsExpressionEvaluator.Input(ESCRIPTTOKEN_MINUS);\r\n\t\t\t\t\t\r\n\t\t\t\t\tsTemp.mIntegerValue=-sTemp.mIntegerValue;\r\n\t\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\t\tCleanUpComponent(&sTemp);\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_token=p_new_token;\r\n\t\t\t\t\tgenerate_minus_operator=true;\r\n\t\t\t\t\texpecting_value=false;\r\n\t\t\t\t}\t\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tin_expression=false;\r\n\t\t\t\t}\t\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESCRIPTTOKEN_FLOAT:\r\n\t\t\tif (expecting_value)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(!generate_minus_operator,(\"Eh? generate_minus_operator is set?\"));\r\n\t\t\t\tp_token=FillInComponentUsingQB(p_token,p_args,&sTemp);\r\n\t\t\t\t\r\n\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\tCleanUpComponent(&sTemp);\r\n\t\t\t\tgenerate_minus_operator=true;\r\n\t\t\t\texpecting_value=false;\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tuint8 *p_new_token=FillInComponentUsingQB(p_token,p_args,&sTemp);\r\n\t\t\t\t\r\n\t\t\t\tif (sTemp.mFloatValue<0.0f && generate_minus_operator)\r\n\t\t\t\t{\r\n\t\t\t\t\tsExpressionEvaluator.Input(ESCRIPTTOKEN_MINUS);\r\n\t\t\t\t\t\r\n\t\t\t\t\tsTemp.mFloatValue=-sTemp.mFloatValue;\r\n\t\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\t\tCleanUpComponent(&sTemp);\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_token=p_new_token;\r\n\t\t\t\t\tgenerate_minus_operator=true;\r\n\t\t\t\t\texpecting_value=false;\r\n\t\t\t\t}\t\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tin_expression=false;\r\n\t\t\t\t}\t\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESCRIPTTOKEN_NAME:\r\n\t\t{\r\n\t\t\tif (!expecting_value)\r\n\t\t\t{\r\n\t\t\t\tin_expression=false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tp_token=FillInComponentUsingQB(p_token,p_args,&sTemp);\r\n\t\t\t\r\n\t\t\t// TODO: Use ResolveNameComponent instead of this switch ...\r\n            CSymbolTableEntry *p_entry=NULL;\r\n\t\t\tif (operator_is_dot)\r\n\t\t\t{\r\n\t\t\t\t// This is a bit of a hack ...\r\n\t\t\t\t// If the operator is the dot operator, then do not check if the right-hand-side\r\n\t\t\t\t// is a global. This is because when the . is used to access members of a structure,\r\n\t\t\t\t// it may be that the name of the parameter being accessed is also the name of a \r\n\t\t\t\t// global, which if substituted in place of the name would result in a nonsense \r\n\t\t\t\t// expression.\r\n\t\t\t\t// The only disadvantage of this hack is that it means that a vector can no longer be\r\n\t\t\t\t// dot producted with a global vector, at least not directly.\r\n\t\t\t\t// I don't think there even are any global vectors at the moment anyway, and if there\r\n\t\t\t\t// were they could still be dot-producted with by simply copying them into a parameter \r\n\t\t\t\t// and dotting with that instead.\r\n\t\t\t\t\r\n\t\t\t\t// The more general solution to the problem would be to have some sort of special\r\n\t\t\t\t// syntax to indicate when a name is not to be resolved. Eg, Foo.Blaa would mean \r\n\t\t\t\t// that Blaa would be resolved, whereas Foo.~Blaa would tell the interpreter not to\r\n\t\t\t\t// resolve it.\r\n\t\t\t\t// That would be more complex to implement though.\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_entry=Resolve(sTemp.mChecksum);\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tif (p_entry)\r\n\t\t\t{\r\n\t\t\t\tswitch (p_entry->mType)\r\n\t\t\t\t{\r\n\t\t\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\t\t\tsTemp.mType=ESYMBOLTYPE_FLOAT;\r\n\t\t\t\t\tsTemp.mFloatValue=p_entry->mFloatValue;\r\n\t\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\t\t\tsTemp.mType=ESYMBOLTYPE_INTEGER;\r\n\t\t\t\t\tsTemp.mIntegerValue=p_entry->mIntegerValue;\r\n\t\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\t\t\tsTemp.mType=ESYMBOLTYPE_VECTOR;\r\n\t\t\t\t\tsTemp.mpVector=p_entry->mpVector;\r\n\t\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\t\t\tsTemp.mType=ESYMBOLTYPE_PAIR;\r\n\t\t\t\t\tsTemp.mpPair=p_entry->mpPair;\r\n\t\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase ESYMBOLTYPE_STRING:\r\n\t\t\t\t\tsTemp.mType=ESYMBOLTYPE_STRING;\r\n\t\t\t\t\tsTemp.mpString=p_entry->mpString;\r\n\t\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\t\t\tsTemp.mType=ESYMBOLTYPE_LOCALSTRING;\r\n\t\t\t\t\tsTemp.mpLocalString=p_entry->mpLocalString;\r\n\t\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t\t\t\tsTemp.mType=ESYMBOLTYPE_STRUCTURE;\r\n\t\t\t\t\tsTemp.mpStructure=p_entry->mpStructure;\r\n\t\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t\t\t\tsTemp.mType=ESYMBOLTYPE_ARRAY;\r\n\t\t\t\t\tsTemp.mpArray=p_entry->mpArray;\r\n\t\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase ESYMBOLTYPE_CFUNCTION:\r\n\t\t\t\t{\r\n\t\t\t\t\tCScript *p_script=GetCurrentScript();\r\n\t\t\t\t\tDbg_MsgAssert(p_script,(\"Tried to execute the cfunc '%s' in an expression with no parent script, line %d of file %s\",FindChecksumName(sTemp.mChecksum),GetLineNumber(p_token),GetSourceFile(p_token)));\r\n\t\t\t\t\t\r\n\t\t\t\t\tsTemp.mType=ESYMBOLTYPE_INTEGER;\r\n\t\t\t\t\r\n\t\t\t\t\tCStruct *p_function_params=new CStruct;\r\n\t\t\t\t\t// TODO: Problem if AddComponentsUntilEndOfLine calls Evaluate() again,\r\n\t\t\t\t\t// since only one instance of CExpressionEvaluator.\r\n\t\t\t\t\tp_token=AddComponentsUntilEndOfLine(p_function_params,p_token,p_args);\r\n\t                sTemp.mIntegerValue=(*p_entry->mpCFunction)(p_function_params,p_script);\r\n\t\t\t\t\tdelete p_function_params;\r\n\t\t\t\t\t\r\n\t\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\tcase ESYMBOLTYPE_MEMBERFUNCTION:\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"Sorry, cannot have calls to member functions in expressions!\\nTried to call member function '%s' in an expression, line %d of file %s\",FindChecksumName(sTemp.mChecksum),GetLineNumber(p_token),GetSourceFile(p_token)));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t}\r\n\t\t\t// Must not call CleanUpComponent because any pointer in the component will\r\n\t\t\t// have been borrowed from the global symbol.\r\n\t\t\tsTemp.mType=ESYMBOLTYPE_NONE;\r\n\t\t\tsTemp.mUnion=0;\r\n\t\t\tgenerate_minus_operator=true;\r\n\t\t\texpecting_value=false;\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase ESCRIPTTOKEN_STRING:\r\n\t\tcase ESCRIPTTOKEN_LOCALSTRING:\r\n\t\tcase ESCRIPTTOKEN_VECTOR:\r\n\t\tcase ESCRIPTTOKEN_PAIR:\r\n\t\t//case ESCRIPTTOKEN_STARTARRAY:\r\n\t\tcase ESCRIPTTOKEN_STARTSTRUCT:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE:\r\n\t\t\tif (!expecting_value)\r\n\t\t\t{\r\n\t\t\t\tin_expression=false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tp_token=FillInComponentUsingQB(p_token,p_args,&sTemp);\r\n\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\tCleanUpComponent(&sTemp);\r\n\t\t\tgenerate_minus_operator=true;\r\n\t\t\texpecting_value=false;\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase ESCRIPTTOKEN_ARG:\r\n\t\t{\r\n\t\t\tif (!expecting_value)\r\n\t\t\t{\r\n\t\t\t\tin_expression=false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t++p_token;\r\n\t\t\tDbg_MsgAssert(*p_token==ESCRIPTTOKEN_NAME,(\"Expected '<' token to be followed by a name, File %s, line %d\",GetSourceFile(p_token),GetLineNumber(p_token)));\r\n\t\t\t++p_token;\r\n\t\t\tuint32 arg_checksum=Read4Bytes(p_token).mChecksum;\r\n\t\t\tp_token+=4;\r\n\t\t\tif (p_args)\r\n\t\t\t{\r\n\t\t\t\t// Look for a parameter named arg_checksum in p_args, recursing into any referenced structures\r\n\t\t\t\tCComponent *p_comp=p_args->FindNamedComponentRecurse(arg_checksum);\r\n\t\t\t\tif (p_comp)\r\n\t\t\t\t{\r\n\t\t\t\t\tsTemp.mType=p_comp->mType;\r\n\t\t\t\t\tsTemp.mUnion=p_comp->mUnion;\r\n\t\t\t\t\t// It might be a name that resolves to some global, so resolve it.\r\n\t\t\t\t\tResolveNameComponent(&sTemp);\r\n\r\n\t\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Must not call CleanUpComponent because any pointer in the component will\r\n\t\t\t\t\t// have been borrowed from the global symbol or p_comp.\r\n\t\t\t\t\tsTemp.mType=ESYMBOLTYPE_NONE;\r\n\t\t\t\t\tsTemp.mUnion=0;\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t\tgenerate_minus_operator=true;\r\n\t\t\texpecting_value=false;\r\n\t\t\tbreak;\t\r\n\t\t}\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ALLARGS:\r\n\t\t{\r\n\t\t\tif (!expecting_value)\r\n\t\t\t{\r\n\t\t\t\tin_expression=false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t++p_token;\r\n\t\t\t\r\n\t\t\tif (p_args)\r\n\t\t\t{\r\n\t\t\t\tsTemp.mType=ESYMBOLTYPE_STRUCTURE;\r\n\t\t\t\tsTemp.mpStructure=p_args;\r\n\t\t\t\tsExpressionEvaluator.Input(&sTemp);\r\n\t\t\t}\t\r\n\t\t\tgenerate_minus_operator=true;\r\n\t\t\texpecting_value=false;\r\n\t\t\tbreak;\t\r\n\t\t}\r\n\t\t\r\n\t\tcase ESCRIPTTOKEN_ADD:\r\n\t\tcase ESCRIPTTOKEN_MINUS:\r\n\t\tcase ESCRIPTTOKEN_MULTIPLY:\r\n\t\tcase ESCRIPTTOKEN_DIVIDE:\r\n\t\tcase ESCRIPTTOKEN_DOT:\r\n\t\tcase ESCRIPTTOKEN_OR:\r\n\t\tcase ESCRIPTTOKEN_AND:\r\n\t\tcase ESCRIPTTOKEN_LESSTHAN:\r\n\t\tcase ESCRIPTTOKEN_GREATERTHAN:\r\n\t\tcase ESCRIPTTOKEN_EQUALS:\r\n\t\tcase ESCRIPTTOKEN_STARTARRAY:\r\n\t\t\t++p_token;\r\n\t\t\tsExpressionEvaluator.Input((EScriptToken)token_value);\r\n\t\t\tgenerate_minus_operator=false;\r\n\t\t\texpecting_value=true;\r\n\t\t\tif (token_value==ESCRIPTTOKEN_DOT)\r\n\t\t\t{\r\n\t\t\t\toperator_is_dot=true;\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\toperator_is_dot=false;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESCRIPTTOKEN_ENDARRAY:\r\n\t\tcase ESCRIPTTOKEN_ENDOFLINE:\r\n\t\t\t++p_token;\r\n\t\t\tbreak;\r\n\t\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t\tp_token+=5;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESCRIPTTOKEN_ENDOFFILE:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ENDSCRIPT:\r\n\t\tcase ESCRIPTTOKEN_COMMA:\r\n\t\t\tDbg_MsgAssert(0,(\"Unexpected token '%s' in expression, line %d of %s\",GetTokenName((EScriptToken)token_value),GetLineNumber(p_token),GetSourceFile(p_token)));\r\n\t\t\tbreak;\t\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\t// Unrecognized expression\r\n\t\t\tDbg_MsgAssert(0,(\"Don't know how to evaluate '%s', at line %d of %s\",GetTokenName((EScriptToken)token_value),GetLineNumber(p_token),GetSourceFile(p_token)));\r\n\t\t\tbreak;\t\r\n\t\t}\t\r\n\t\t\r\n\t\t// This cannot be commented in all the time, because often the evaluator will report\r\n\t\t// errors when it gets called via the FindReferences function, which scans through scripts\r\n\t\t// but does not execute them. Errors occur in this case when script parameters are used\r\n\t\t// in expressions, because when FindReferences is scanning through the script it has no\r\n\t\t// parameters. Need to fix FindReferences so that it can scan over expressions without\r\n\t\t// executing them.\r\n\t\t//if (sExpressionEvaluator.GetError())\r\n\t\t//{\r\n\t\t//\tDbg_MsgAssert(0,(\"Evaluator error: File %s, line %d\",GetSourceFile(p_token),GetLineNumber(p_token)));\r\n\t\t//}\t\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tif (sExpressionEvaluator.ErrorCheckingEnabled() && sExpressionEvaluator.GetError())\r\n\t\t{\r\n\t\t\tprintf(\"Evaluator error: File %s, line %d\",GetSourceFile(p_token),GetLineNumber(p_token));\r\n\t\t}\t\r\n\t\t#endif\r\n\t}\r\n\t\t\r\n\tsExpressionEvaluator.GetResult(p_result);\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tif (sExpressionEvaluator.ErrorCheckingEnabled() && sExpressionEvaluator.GetError())\r\n\t{\r\n\t\tprintf(\"Evaluator error: File %s, line %d\\n\",GetSourceFile(p_token),GetLineNumber(p_token));\r\n\t}\t\r\n\t#endif\r\n\treturn p_token;\r\n}\r\n\r\n// Parses the components in QB format pointed to by p_token, and adds them to p_dest until the \r\n// end-of-line is reached.\r\n// For example, p_token may point to: x=9 foo=\"Blaa\"\r\n// Used when creating the structure of function parameters, and the structure of default parameters\r\n// for scripts.\r\n// p_args contains the structure defining the value of any args referred to using the <,> operators.\r\n// Returns a pointer to the next token after parsing the tokens pointed to by p_token.\r\n//\r\n// Note: This gets called for every line of script executed, hence is probably a bottleneck in script\r\n// execution speed. Could speed up a lot by pre-generating any function parameters that are constant, ie\r\n// contain no <,> operators.\r\nuint8 *AddComponentsUntilEndOfLine(CStruct *p_dest, uint8 *p_token, CStruct *p_args)\r\n{\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest\"));\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token\"));\r\n\t\r\n    while (true)\r\n    {\r\n\t\t// Execute any random operators.\r\n\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\r\n        if (sIsEndOfLine(p_token)) \r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\t// This is so that function calls can be put in expressions, which are always enclosed\r\n\t\t// in parentheses.\r\n\t\tif (*p_token==ESCRIPTTOKEN_CLOSEPARENTH)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        switch (*p_token)\r\n        {\r\n            case ESCRIPTTOKEN_NAME:\r\n            {\r\n                uint8 *p_name_token=p_token;\r\n                ++p_token;\r\n                uint32 name_checksum=Read4Bytes(p_token).mChecksum;\r\n                p_token+=4;\r\n\t\t\t\t// Execute any random operators. This has to be done each time p_token is advanced.\r\n\t\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\r\n                if (*p_token==ESCRIPTTOKEN_EQUALS)\r\n                {\r\n                    ++p_token;\r\n\t\t\t\t\tp_token=DoAnyRandomsOrJumps(p_token);\r\n\t\t\t\t\t\r\n                    Dbg_MsgAssert(!sIsEndOfLine(p_token),(\"Syntax error, nothing following '=', File %s, line %d\",GetSourceFile(p_token),GetLineNumber(p_token)));\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (*p_token==ESCRIPTTOKEN_OPENPARENTH)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tCComponent *p_comp=new CComponent;\r\n\t\t\t\t\t\tp_token=Evaluate(p_token,p_args,p_comp);\r\n\t\t\t\t\t\tif (p_comp->mType!=ESYMBOLTYPE_NONE)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_comp->mNameChecksum=name_checksum;\r\n\t\t\t\t\t\t\tp_dest->AddComponent(p_comp);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tdelete p_comp;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_token=sAddComponentFromQB(p_dest,name_checksum,p_token,p_args);\t\t\t\t\t\r\n\t\t\t\t\t}\t\r\n                }\r\n                else\r\n\t\t\t\t{\r\n                    p_token=sAddComponentFromQB(p_dest,NO_NAME,p_name_token,p_args);\r\n\t\t\t\t}\t\r\n                break;\r\n            }\r\n\t\t\tcase ESCRIPTTOKEN_KEYWORD_ALLARGS:\r\n                ++p_token;\r\n\t\t\t\tif (p_args)\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_dest+=*p_args;\r\n\t\t\t\t}\t\r\n\t\t\t\tbreak;\r\n            case ESCRIPTTOKEN_STARTSTRUCT:\r\n                p_token=sAddComponentsWithinCurlyBraces(p_dest,p_token,p_args);\r\n                break;\r\n\t\t\tcase ESCRIPTTOKEN_ARG:\r\n\t\t\t\tp_token=sAddComponentFromQB(p_dest,NO_NAME,p_token,p_args);\r\n\t\t\t\tbreak;\r\n            case ESCRIPTTOKEN_ENDOFLINE:\r\n            case ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n                break;\r\n            case ESCRIPTTOKEN_ENDOFFILE:\r\n\t\t\t\tDbg_MsgAssert(0,(\"End of file reached during AddComponentsUntilEndOfLine ?\"));\r\n                break;\r\n\t\t\t\r\n\t\t\tcase ESCRIPTTOKEN_COMMA:\r\n\t\t\t\t++p_token;\r\n\t\t\t\tbreak;\r\n\t\t\t\t\r\n            default:\r\n\t\t\t{\r\n\t\t\t\tif (*p_token==ESCRIPTTOKEN_OPENPARENTH)\r\n\t\t\t\t{\r\n\t\t\t\t\tCComponent *p_comp=new CComponent;\r\n\t\t\t\t\tp_token=Evaluate(p_token,p_args,p_comp);\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (p_comp->mType==ESYMBOLTYPE_STRUCTURE)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// The CStruct::AddComponent function does not allow unnamed structure\r\n\t\t\t\t\t\t// components to be added, so merge in the contents of the structure instead.\r\n\t\t\t\t\t\tp_dest->AppendStructure(p_comp->mpStructure);\r\n\t\t\t\t\t\t// Now p_comp does have to be cleaned up and deleted, because it has not\r\n\t\t\t\t\t\t// been given to p_dest.\r\n\t\t\t\t\t\tCleanUpComponent(p_comp);\r\n\t\t\t\t\t\tdelete p_comp;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (p_comp->mType!=ESYMBOLTYPE_NONE)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_comp->mNameChecksum=NO_NAME;\r\n\t\t\t\t\t\t\tp_dest->AddComponent(p_comp);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tdelete p_comp;\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_token=sAddComponentFromQB(p_dest,NO_NAME,p_token,p_args);\r\n\t\t\t\t}\t\r\n                break;\r\n\t\t\t}\t\r\n        }            \r\n    } \r\n\r\n\t// Note: Does not skip over the end-of-lines. This is so that if any asserts go off during the\r\n\t// C-function or member function call that this structure is going to be used as parameters too,\r\n\t// the assert will print the correct line number, rather than the one following.\r\n    return p_token;\r\n}\r\n\r\n// Deletes any entity pointed to by p_sym, then removes p_sym from the symbol table.\r\nvoid CleanUpAndRemoveSymbol(CSymbolTableEntry *p_sym)\r\n{\r\n\tDbg_MsgAssert(p_sym,(\"NULL p_sym\"));\r\n\tswitch (p_sym->mType)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t\t// Nothing to delete\r\n\t\t\tbreak;\t\t\r\n\t\t\t\r\n\t\tcase ESYMBOLTYPE_STRING:\r\n\t\t\tDbg_MsgAssert(p_sym->mpString,(\"NULL p_sym->mpString\"));\r\n\t\t\tDeleteString(p_sym->mpString);\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\tDbg_MsgAssert(p_sym->mpLocalString,(\"NULL p_sym->mpLocalString\"));\r\n\t\t\tDeleteString(p_sym->mpLocalString);\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\tDbg_MsgAssert(p_sym->mpPair,(\"NULL p_sym->mpPair\"));\r\n\t\t\tdelete p_sym->mpPair;\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\tDbg_MsgAssert(p_sym->mpVector,(\"NULL p_sym->mpVector\"));\r\n\t\t\tdelete p_sym->mpVector;\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_QSCRIPT:\r\n#ifdef __PLAT_NGC__\r\n\t\t\tNsARAM::free( p_sym->mScriptOffset );\r\n#else\r\n\t\t\tDbg_MsgAssert(p_sym->mpScript,(\"NULL p_sym->mpScript\"));\r\n\t\t\tMem::Free(p_sym->mpScript);\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t\tDbg_MsgAssert(p_sym->mpStructure,(\"NULL p_sym->mpStructure\"));\r\n\t\t\tdelete p_sym->mpStructure;\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t\tDbg_MsgAssert(p_sym->mpArray,(\"NULL p_sym->mpArray\"));\r\n\t\t\tCleanUpArray(p_sym->mpArray);\r\n\t\t\tdelete p_sym->mpArray;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Bad type of '%s' in p_sym\",GetTypeName(p_sym->mType)));\r\n\t\t\tbreak;\r\n\t}\r\n\tp_sym->mUnion=0;\r\n\r\n\tRemoveSymbol(p_sym);\r\n}\r\n\r\n// TODO: Remove? Currently used in cfuncs.cpp to delete the NodeArray, but now that we\r\n// have the ability to unload qb files that should not be necessary any more.\r\n// Note: Just found it is also needed in parkgen.cpp, so don't remove after all. \r\nvoid CleanUpAndRemoveSymbol(uint32 checksum)\r\n{\r\n\tCSymbolTableEntry *p_sym=LookUpSymbol(checksum);\r\n\tif (p_sym)\r\n\t{\r\n\t\tCleanUpAndRemoveSymbol(p_sym);\r\n\t}\t\r\n}\r\n\r\nvoid CleanUpAndRemoveSymbol(const char *p_symbolName)\r\n{\r\n\tCleanUpAndRemoveSymbol(Crc::GenerateCRCFromString(p_symbolName));\r\n}\r\n\t\r\n#define HASHBITS 12\r\nstruct SChecksum\r\n{\r\n\tuint32 mChecksum;\r\n\tchar *mpName;\r\n\tSChecksum *mpNext;\r\n};\r\n\r\nstatic SChecksum *sp_hash_table=NULL;\r\n\r\nconst char *GetChecksumNameFromLastQB(uint32 checksum)\r\n{\r\n\tDbg_MsgAssert(sp_hash_table,(\"NULL sp_hash_table\"));\r\n\t\r\n\tSChecksum *p_entry=&sp_hash_table[checksum&((1<<HASHBITS)-1)];\r\n\twhile (p_entry)\r\n\t{\r\n\t\tif (p_entry->mChecksum==checksum)\r\n\t\t{\r\n\t\t\treturn p_entry->mpName;\r\n\t\t}\t\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\t\r\n\t\r\n\treturn NULL;\r\n}\t\r\n\r\nvoid RemoveChecksumNameLookupHashTable()\r\n{\r\n\tif (sp_hash_table)\r\n\t{\r\n\t\tSChecksum *p_entry=sp_hash_table;\r\n\t\tfor (uint32 i=0; i<(1<<HASHBITS); ++i)\r\n\t\t{\r\n\t\t\tSChecksum *p_ch=p_entry->mpNext;\r\n\t\t\twhile (p_ch)\r\n\t\t\t{\r\n\t\t\t\tSChecksum *p_next=p_ch->mpNext;\r\n\t\t\t\t// The dynamically allocated entries must have had their mpName set.\r\n\t\t\t\tDbg_MsgAssert(p_ch->mpName,(\"NULL p_ch->mpName ?\"));\r\n\t\t\t\tMem::Free(p_ch->mpName);\r\n\t\t\t\tMem::Free(p_ch);\r\n\t\t\t\tp_ch=p_next;\r\n\t\t\t}\r\n\t\t\t// The entries in the contiguous array may not have their mpName set.\t\r\n\t\t\tif (p_entry->mpName)\r\n\t\t\t{\r\n\t\t\t\tMem::Free(p_entry->mpName);\r\n\t\t\t}\t\r\n\t\t\t++p_entry;\r\n\t\t}\t\r\n\t\r\n\t\tMem::Free(sp_hash_table);\r\n\t\tsp_hash_table=NULL;\r\n\t}\t\r\n}\r\n\r\nuint8 *SkipToStartOfNextLine(uint8 *p_token)\r\n{\r\n\tint curly_bracket_count=0;\r\n\tint square_bracket_count=0;\r\n\tint parenth_count=0;\r\n\t\r\n\twhile (true)\r\n\t{\r\n\t\tif (*p_token==ESCRIPTTOKEN_STARTSTRUCT) ++curly_bracket_count;\r\n\t\tif (*p_token==ESCRIPTTOKEN_ENDSTRUCT) --curly_bracket_count;\r\n\t\tDbg_MsgAssert(curly_bracket_count>=0,(\"Negative curly_bracket_count ??\"));\r\n\r\n\t\tif (*p_token==ESCRIPTTOKEN_STARTARRAY) ++square_bracket_count;\r\n\t\tif (*p_token==ESCRIPTTOKEN_ENDARRAY) --square_bracket_count;\r\n\t\tDbg_MsgAssert(square_bracket_count>=0,(\"Negative square_bracket_count ??\"));\r\n\r\n\t\tif (*p_token==ESCRIPTTOKEN_OPENPARENTH) ++parenth_count;\r\n\t\tif (*p_token==ESCRIPTTOKEN_CLOSEPARENTH) --parenth_count;\r\n\t\tDbg_MsgAssert(parenth_count>=0,(\"Negative parenth_count, File %s, line %d\",GetSourceFile(p_token),GetLineNumber(p_token)));\r\n\t\t\r\n\t\tif (curly_bracket_count==0 && \r\n\t\t\tsquare_bracket_count==0 &&\r\n\t\t\tparenth_count==0 &&\r\n\t\t\tsIsEndOfLine(p_token))\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t\tp_token=SkipToken(p_token);\r\n\t}\r\n\t\r\n\tp_token=SkipToken(p_token);\r\n\treturn p_token;\r\n}\r\n\r\n// Parses a qb file, creating all the symbols (scripts, arrays etc) defined within.\r\n// If the assertIfDuplicateSymbols is set, then it will assert if any of the symbols in the qb\r\n// exist already.\r\n// This flag is set when loading all the startup qb's, because we don't want clashing symbols.\r\n// It is not set when reloading a qb during development though, since that involves reloading\r\n// existing symbols.\r\n// The file name is also passed so that each symbol knows what qb it came from, which allows\r\n// all the symbols from a particular qb to be unloaded using the UnloadQB function (in file.cpp)\r\nvoid ParseQB(const char *p_fileName, uint8 *p_qb, EBoolAssertIfDuplicateSymbols assertIfDuplicateSymbols, bool allocateChecksumNameLookupTable)\r\n{\r\n\tDbg_MsgAssert(p_fileName,(\"NULL p_fileName\"));\r\n\tDbg_MsgAssert(p_qb,(\"NULL p_qb\"));\r\n\r\n\t// Do a first parse through the qb to register the checksum names.\r\n\t// They get added to a lookup table that can be queried using GetChecksumNameFromLastQB defined above.\r\n\t// The lookup table only contains the checksum names defined in this qb.\r\n\t// GetChecksumNameFromLastQB is currently only used by the game-specific nodearray.cpp to generate a lookup\r\n\t// table of node name prefixes.\r\n\t//\r\n\t// If __NOPT_ASSERT__ is set the checksum names also get added to a big permanent lookup table so that\r\n\t// the FindChecksumName function can be used at any time in asserts.\r\n\t// \r\n    uint8 *p_token=p_qb;\r\n    bool end_of_file=false;\r\n\r\n\t// Remove any existing checksum-name-lookup hash table.\r\n\tRemoveChecksumNameLookupHashTable();\r\n\r\n\t// K: Added the passed flag allocateChecksumNameLookupTable so that we can avoid allocating the table\r\n\t// if we know it will not be needed. Gary needs this for the cutscenes where there is not enough memory\r\n\t// to allocate the table.\r\n\t// By default the flag is set to true however because the table is needed when generating prefix info\r\n\t// for the nodearray, and we don't know whether the qb contains the nodearray until after finishing\r\n\t// parsing it.\r\n\tif (allocateChecksumNameLookupTable)\r\n\t{\r\n\t\t// Reallocate it.\r\n\t\tbool use_debug_heap=false;\r\n\t\t#ifdef\t__NOPT_ASSERT__\t\r\n\t\tif (!assertIfDuplicateSymbols)\r\n\t\t{\r\n\t\t\t// They're doing a qbr ...\r\n\t\t\tif (Mem::Manager::sHandle().GetHeap(0x70cb0238/*DebugHeap*/))\r\n\t\t\t{\r\n\t\t\t\t// The debug heap exists, so use it.\r\n\t\t\t\t// Need to do this because there is often not enough memory otherwise.\r\n\t\t\t\tuse_debug_heap=true;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\t#endif\r\n\t\r\n\t\tif (use_debug_heap)\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\t}\r\n\t\tDbg_MsgAssert(sp_hash_table==NULL,(\"sp_hash_table not NULL ?\"));\r\n\t\tsp_hash_table=(SChecksum*)Mem::Malloc((1<<HASHBITS)*sizeof(SChecksum));\r\n\t\tDbg_MsgAssert(sp_hash_table,(\"NULL sp_hash_table\"));\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\t// Initialise it.\r\n\t\tSChecksum *p_entry=sp_hash_table;\r\n\t\tfor (uint32 i=0; i<(1<<HASHBITS); ++i)\r\n\t\t{\r\n\t\t\tp_entry->mChecksum=0;\r\n\t\t\tp_entry->mpName=NULL;\r\n\t\t\tp_entry->mpNext=NULL;\r\n\t\t\t++p_entry;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\t// Line number info in qb's is excluded when doing a release build to save memory.\r\n\t// Need to stop with an error message if there is line number info when there should not\r\n\t// be, otherwise the release build will run out of memory & it will be hard to track down\r\n\t// why since there will be no asserts.\r\n\t// This flag indicates whether to give the error message or not.\r\n\tbool allow_line_number_info=false;\r\n\tif (!assertIfDuplicateSymbols)\r\n\t{\r\n\t\t// Doing a qbr, so allow line number info, otherwise\r\n\t\t// we won't be able to qbr when __NOPT_ASSERT__ is not defined.\r\n\t\tallow_line_number_info=true;\r\n\t}\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\t// Allow line number info when asserts are on, cos the script heap will have an extra 200K for them.\r\n\tallow_line_number_info=true;\r\n\t#endif\r\n\t#ifdef __PLAT_WN32__\r\n\t// PC has lots of memory.\r\n\tallow_line_number_info=true;\r\n\t#endif\r\n\t\t\r\n\r\n    while (!end_of_file)\r\n\t{\r\n\t\tswitch (*p_token)\r\n\t\t{\r\n\t\tcase ESCRIPTTOKEN_CHECKSUM_NAME: \r\n\t\t{\r\n\t\t\t++p_token;\r\n\t\t\tuint32 checksum=Read4Bytes(p_token).mChecksum;\r\n\t\t\tconst char *p_name=(const char*)(p_token+4);\r\n\t\r\n\t\t\tif (allocateChecksumNameLookupTable)\r\n\t\t\t{\r\n\t\t\t\t// Add it to the table.\r\n\t\t\t\tSChecksum *p_entry=&sp_hash_table[checksum&((1<<HASHBITS)-1)];\r\n\t\t\t\tif (p_entry->mpName)\r\n\t\t\t\t{\r\n\t\t\t\t\t// The first slot is already occupied, so create a new SChecksum and\r\n\t\t\t\t\t// link it in between the first and the rest.\r\n\t\t\t\t\tSChecksum *p_new=(SChecksum*)Mem::Malloc(sizeof(SChecksum));\r\n\t\t\t\t\tp_new->mChecksum=checksum;\r\n\t\t\t\t\tp_new->mpName=(char*)Mem::Malloc(strlen(p_name)+1);\r\n\t\t\t\t\tstrcpy(p_new->mpName,p_name);\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_new->mpNext=p_entry->mpNext;\r\n\t\t\t\t\tp_entry->mpNext=p_new;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// First slot is not occupied, so stick it in there.\r\n\t\t\t\t\tp_entry->mChecksum=checksum;\r\n\t\t\t\t\tp_entry->mpName=(char*)Mem::Malloc(strlen(p_name)+1);\r\n\t\t\t\t\tstrcpy(p_entry->mpName,p_name);\r\n\t\t\t\t\tp_entry->mpNext=NULL;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t// Add to the big lookup table of all checksum names, used by FindChecksumName\r\n\t\t\t// Doing this here rather than the main parsing loop after this one so that the names \r\n\t\t\t// are registered first in case any asserts go off.\r\n\t\t\tAddChecksumName(checksum,p_name);\r\n\t\t\t\t\r\n\t\t\t// Skip over the checksum.\r\n\t\t\tp_token+=4;\r\n\t\t\t// Skip over the name.\r\n\t\t\twhile (*p_token)\r\n\t\t\t{\r\n\t\t\t\t++p_token;\r\n\t\t\t}\r\n\t\t\t// Skip over the terminator.\r\n\t\t\t++p_token;\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        case ESCRIPTTOKEN_ENDOFFILE:\r\n            end_of_file=true;\r\n            break;\r\n\r\n\t\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t{\r\n\t\t\tif (allow_line_number_info)\r\n\t\t\t{\r\n\t\t\t\tp_token=SkipToken(p_token);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tprintf(\"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\\n\\n\");\r\n\t\t\t\tprintf(\"Found line number info in '%s' !\\nLine number info needs to be removed when __NOPT_ASSERT__ is not defined\\nin order to save memory.\\nTry doing a 'cleanass nolinenumbers' and running again.\\n\",p_fileName);\r\n\t\t\t\twhile (1);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n            \r\n        default:\r\n            p_token=SkipToken(p_token);\r\n            break;\r\n        }    \r\n    }\r\n    p_token=p_qb;\r\n\tend_of_file=false;\r\n\t// That's all the checksum names added.\r\n\r\n\r\n\t// Register the file name checksum so that FindChecksumName will be able to find it.\r\n\t// (Required if a script assert goes off that needs to print the source file name)\r\n\tAddChecksumName(Crc::GenerateCRCFromString(p_fileName),p_fileName);\r\n\r\n\t// Store the checksum of the file name so that if an assert goes off during parsing the file name can be printed.\r\n\ts_qb_being_parsed=Crc::GenerateCRCFromString(p_fileName);\r\n\r\n\t// Make sure we're using the script heap, cos we're about to create a bunch of scripty stuff.\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\r\n    while (!end_of_file)\r\n    {\r\n        p_token=SkipEndOfLines(p_token);\r\n\t\t\r\n        switch (*p_token)\r\n        {\r\n\t\t\tcase ESCRIPTTOKEN_NAME:\r\n\t\t\t{\r\n\t\t\t\tp_token=sCreateSymbolOfTheFormNameEqualsValue(p_token,p_fileName,assertIfDuplicateSymbols);\r\n\t\t\t\tbreak;    \r\n\t\t\t}\r\n\t\t\tcase ESCRIPTTOKEN_KEYWORD_SCRIPT:\r\n\t\t\t{\r\n\t\t\t\t// Get the new script's name checksum ...\r\n\t\t\t\t++p_token; // Skip over the ESCRIPTTOKEN_KEYWORD_SCRIPT\r\n\t\t\t\tDbg_MsgAssert(*p_token==ESCRIPTTOKEN_NAME,(\"\\nKeyword 'script' must be followed by a name, line %d of %s\",GetLineNumber(p_token),p_fileName));\r\n\t\t\t\t++p_token; // Skip over the ESCRIPTTOKEN_NAME\r\n\t\t\t\tuint32 name_checksum=Read4Bytes(p_token).mChecksum;\r\n\t\t\t\tp_token+=4; // Skip over the name checksum\r\n\t\r\n\t\r\n\t\t\t\t// Calculate the length of the script data in bytes.\r\n\t\t\t\tuint8 *p_script_data=p_token;\r\n\t\t\t\tp_token=SkipOverScript(p_token);\r\n\t\t\t\tuint32 script_data_size=p_token-p_script_data;\r\n\t\r\n\t\t\t\t\r\n\t\t\t\t// Calculate a checksum of the contents of the new script.\r\n\t\t\t\t// The purpose of the contents checksum is to prevent unnecessary restarting of CScript's\r\n\t\t\t\t// when a qb is reloaded. It may be that only one script in the qb has changed, so we only\r\n\t\t\t\t// want the CScript's that were referencing that script to restart.\r\n\t\t\t\t\r\n\t\t\t\t// Note: The LoadQB function in gel\\scripting\\file.cpp does the restarting of existing\r\n\t\t\t\t// CScripts by checking the mGotReloaded flag in the CSymbolTableEntry for the script.\r\n\t\t\t\t\r\n\t\t\t\tuint32 new_contents_checksum=CalculateScriptContentsChecksum(p_script_data);\r\n\t\t\t\t\r\n\t\t\t\t// Check to see if a script with this name exists already.\t\t\t\r\n\t\t\t\tCSymbolTableEntry *p_existing_entry=LookUpSymbol(name_checksum);\r\n\t\t\t\tif (p_existing_entry)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (assertIfDuplicateSymbols)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"The symbol '%s' is defined twice, in %s and %s\",FindChecksumName(name_checksum),FindChecksumName(p_existing_entry->mSourceFileNameChecksum),p_fileName));\r\n\t\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t\tif (p_existing_entry->mType==ESYMBOLTYPE_QSCRIPT)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// A script with the same name does already exist.\r\n\t\t\t\t\t\t// Compare its contents checksum with the new one.\r\n#ifdef __PLAT_NGC__\r\n\t\t\t\t\t\tuint32 header[(SCRIPT_HEADER_SIZE/4)];\r\n\t\t\t\t\t\tNsDMA::toMRAM( header, p_existing_entry->mScriptOffset, SCRIPT_HEADER_SIZE );\r\n\t\t\t\t\t\tuint32 old_contents_checksum=header[0];\r\n#else\r\n\t\t\t\t\t\tDbg_MsgAssert(p_existing_entry->mpScript,(\"NULL p_existing_entry->mpScript ??\"));\r\n\t\t\t\t\t\tuint32 old_contents_checksum=*(uint32*)(p_existing_entry->mpScript);\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif (new_contents_checksum != old_contents_checksum)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// The contents of the new script differ from the old!\r\n\t\t\t\t\t\t\t// So remove the old one, and create the new.\r\n\t\t\t\t\t\t\tCleanUpAndRemoveSymbol(p_existing_entry);\r\n\t\t\t\t\t\t\tsCreateScriptSymbol(name_checksum,\r\n\t\t\t\t\t\t\t\t\t\t\t\tnew_contents_checksum,\r\n\t\t\t\t\t\t\t\t\t\t\t\tp_script_data,\r\n\t\t\t\t\t\t\t\t\t\t\t\tscript_data_size,\r\n\t\t\t\t\t\t\t\t\t\t\t\tp_fileName);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// The contents of the script have not changed!\r\n\t\t\t\t\t\t\t// So there's nothing to do.\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Remove the existing symbol, whatever it is. (It isn't a script)\r\n\t\t\t\t\t\tCleanUpAndRemoveSymbol(p_existing_entry);\r\n\t\t\t\t\t\t// Create the new script symbol.\r\n\t\t\t\t\t\tsCreateScriptSymbol(name_checksum,new_contents_checksum,p_script_data,script_data_size,p_fileName);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No symbol currently exists with this name, so create the new script symbol.\r\n\t\t\t\t\tsCreateScriptSymbol(name_checksum,new_contents_checksum,p_script_data,script_data_size,p_fileName);\r\n\t\t\t\t}\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\r\n\t\t\tcase ESCRIPTTOKEN_CHECKSUM_NAME: \r\n\t\t\t\t// These have been done already, so skip over.\r\n\t\t\t\tp_token=SkipToken(p_token);\r\n\t\t\t\tbreak;\r\n\t\t\t\t\r\n\t\t\tcase ESCRIPTTOKEN_ENDOFFILE:\r\n\t\t\t\tend_of_file=true;\r\n\t\t\t\tbreak;\r\n\t\t\t\t\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(0,(\"\\nConfused by line %d of %s.\\nExpected either a script definition (Script ... EndScript)\\nor a constant definition (Something=...)\",GetLineNumber(p_token),p_fileName));\r\n\t\t\t\tbreak;\r\n        }    \r\n    }\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\ts_qb_being_parsed=0;\r\n}\r\n\r\n// Used by the EditorCameraComponent when it checks polys to see if they are Kill polys\r\nbool ScriptContainsName(uint8 *p_script, uint32 searchName)\r\n{\r\n\tDbg_MsgAssert(p_script,(\"NULL p_script\"));\r\n\r\n\t//int num_names_found=0;\r\n\t//uint32 last_name=0;\r\n\t\r\n\tuint8 *p_token=p_script;\r\n\twhile (*p_token!=ESCRIPTTOKEN_KEYWORD_ENDSCRIPT) \r\n\t{\r\n\t\tswitch (*p_token)\r\n\t\t{\r\n\t\t\tcase ESCRIPTTOKEN_NAME:\r\n\t\t\t{\r\n\t\t\t\t++p_token;\r\n\t\t\t\tuint32 name=Read4Bytes(p_token).mChecksum;\r\n\t\t\t\tp_token+=4;\r\n\t\t\t\tif (name == searchName)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t//++num_names_found;\r\n\t\t\t\t//last_name=name;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\tdefault:\r\n\t\t\t\tp_token=SkipToken(p_token);\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\t\r\n\t\r\n\t/*\r\n\t// I put this in so that scripts that consist of a single call to another script will have that\r\n\t// scanned. This was to fix a bug where the kill poly over the swimming pool in Hawaii was not\r\n\t// being detected. However, this fix then meant that the kill polys around the hotel would get\r\n\t// detected, meaning that the cursor could never be got off the hotel. So commented it out\r\n\t// for the moment, since at least the first bug does not make the cursor get stuck.\r\n\tif (num_names_found==1)\r\n\t{\r\n\t\tScript::CScriptCache *p_script_cache=Script::CScriptCache::Instance();\r\n\t\tDbg_MsgAssert(p_script_cache,(\"NULL p_script_cache\"));\r\n\t\r\n\t\tp_script=p_script_cache->GetScript(last_name);\r\n\t\tif (p_script)\r\n\t\t{\r\n\t\t\tbool contains_name=ScriptContainsName(p_script, searchName);\r\n\t\t\tp_script_cache->DecrementScriptUsage(last_name);\r\n\t\t\treturn contains_name;\r\n\t\t}\r\n\t}\r\n\t*/\r\n\t\r\n\treturn false;\r\n}\r\n\r\n// Used by the EditorCameraComponent when it checks polys to see if they are Kill polys\r\nbool ScriptContainsAnyOfTheNames(uint32 scriptName, uint32 *p_names, int numNames)\r\n{\r\n\tScript::CScriptCache *p_script_cache=Script::CScriptCache::Instance();\r\n\tDbg_MsgAssert(p_script_cache,(\"NULL p_script_cache\"));\r\n\r\n\tuint8 *p_script=p_script_cache->GetScript(scriptName);\r\n\tDbg_MsgAssert(p_script,(\"NULL p_script for %s\",Script::FindChecksumName(scriptName)));\r\n\r\n\tbool contains_name=false;\r\n\t\r\n\tDbg_MsgAssert(p_names,(\"NULL p_names\"));\r\n\tuint32 *p_name=p_names;\r\n\tfor (int i=0; i<numNames; ++i)\r\n\t{\r\n\t\tif (ScriptContainsName(p_script,*p_name))\r\n\t\t{\r\n\t\t\t//printf(\"Script %s contains %s\\n\",Script::FindChecksumName(scriptName),Script::FindChecksumName(*p_name));\r\n\t\t\tcontains_name=true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t++p_name;\r\n\t}\r\n\t\r\n\tp_script_cache->DecrementScriptUsage(scriptName);\r\n\t\r\n\treturn contains_name;\t\t\r\n}\r\n\r\n} // namespace Script\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/parse.h",
    "content": "#ifndef\t__SCRIPTING_PARSE_H\r\n#define\t__SCRIPTING_PARSE_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef\t__SCRIPTING_SCRIPTDEFS_H\r\n#include <gel/scripting/scriptdefs.h> // For enums\r\n#endif\r\n\r\n#ifndef __SCRIPTING_TOKENS_H\r\n#include <gel/scripting/tokens.h>\r\n#endif\r\n\r\n#ifndef __SYS_MEM_POOLABLE_H\r\n#include <sys/mem/poolable.h>\r\n#endif\r\n\r\n#ifdef __PLAT_NGC__\r\n#define SCRIPT_HEADER_SIZE 32\r\n#else\r\n#define SCRIPT_HEADER_SIZE 12\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\r\nclass CStruct;\r\nclass CComponent;\r\nclass CSymbolTableEntry;\r\nclass CScript;\r\n\r\n// Used when extracting 4 bytes from a .qb, where the 4 bytes could represent\r\n// different types of thing. (Saves messy casting)\r\nstruct S4Bytes\r\n{\r\n    union\r\n    {\r\n        uint32 mChecksum;\r\n\t\tuint32 mUInt;\r\n        int mInt;\r\n        float mFloat;\r\n        bool (*mpCFunction)(CStruct *pParams, CScript *pCScript);\r\n    };\r\n};\r\n\r\n// Same, but for 2 bytes.\r\nstruct S2Bytes\r\n{\r\n    union\r\n    {\r\n\t\tuint16 mUInt;\r\n        sint16 mInt;\r\n    };\r\n};\r\n\r\n// Gets 4 bytes from p_long, which may not be long word aligned.\r\nS4Bytes Read4Bytes(const uint8 *p_long);\r\nS2Bytes Read2Bytes(const uint8 *p_short);\r\nuint8 *Write4Bytes(uint8 *p_buffer, uint32 val);\r\nuint8 *Write4Bytes(uint8 *p_buffer, float floatVal);\r\nuint8 *Write2Bytes(uint8 *p_buffer, uint16 val);\r\n\r\n#define MAX_STORED_RANDOMS 100\r\n\r\n#define MAKE_NEW_FIRST_DIFFER_FROM_OLD_LAST true\r\n#ifdef __PLAT_WN32__\r\nclass CStoredRandom\r\n#else\r\nclass CStoredRandom : public Mem::CPoolable<CStoredRandom>\r\n#endif\r\n{\r\npublic:\t\r\n\tCStoredRandom();\r\n\t~CStoredRandom();\r\n\t\r\n\t// These identify which Random operator this 'belongs' to.\r\n\t// mpToken alone is not enough because there may be two instances of a CScript running\r\n\t// that script.\r\n\tCScript *mpScript;\r\n\tconst uint8 *mpToken;\r\n\t// These are also stored to further verify that this is the correct one if a match for\r\n\t// mpToken is found. They could differ due to a script reload.\r\n\tuint16 mNumItems;\r\n\tEScriptToken mType;\r\n\t\r\n\t// The following members are used by the RandomPermute operator\r\n\tuint16 mCurrentIndex;\r\n\t\r\n\t#define MAX_RANDOM_INDICES 64\r\n\tuint8 mpIndices[MAX_RANDOM_INDICES];\r\n\r\n\tvoid InitIndices();\r\n\tvoid RandomizeIndices(bool makeNewFirstDifferFromOldLast=false);\r\n\t\r\n\t// This is used by the RandomNoRepeat operator\r\n\tuint32 mLastIndex;\r\n\r\n\t\r\n\tCStoredRandom *mpNext;\r\n\tCStoredRandom *mpPrevious;\r\n};\r\n\r\nvoid ReleaseStoredRandoms(CScript *p_script);\r\n\r\n// Used by CScript::Update\r\nuint8 *SkipToken(uint8 *p_token);\r\nuint8 *SkipEndOfLines(uint8 *p_token);\r\nuint8 *DoAnyRandomsOrJumps(uint8 *p_token);\r\n\r\nuint8 *SkipOverScript(uint8 *p_token);\r\n\r\nvoid EnableExpressionEvaluatorErrorChecking();\r\nvoid DisableExpressionEvaluatorErrorChecking();\r\nuint8 *Evaluate(uint8 *p_token, CStruct *p_args, CComponent *p_result);\r\nuint8 *FillInComponentUsingQB(uint8 *p_token, CStruct *p_args, CComponent *p_comp);\r\n\r\n// Exported because needed by CScript when generating the structure of function \r\n// parameters when executing each line of script.\r\nuint8 *AddComponentsUntilEndOfLine(CStruct *p_dest, uint8 *p_token, CStruct *p_args=NULL);\r\n\r\n// Used by UnloadQB in file.cpp\r\nvoid CleanUpAndRemoveSymbol(CSymbolTableEntry *p_sym);\r\n// TODO: Remove? Currently used in cfuncs.cpp to delete the NodeArray, but now that we\r\n// have the ability to unload qb files that should not be necessary any more.\r\n// Note: Just found it is also needed in parkgen.cpp, so don't remove after all. \r\nvoid CleanUpAndRemoveSymbol(uint32 checksum);\r\nvoid CleanUpAndRemoveSymbol(const char *p_symbolName);\r\n\r\n\r\n// Used by various asserts in script.cpp\r\nint GetLineNumber(uint8 *p_token);\r\nconst char *GetSourceFile(uint8 *p_token);\r\nbool PointsIntoScript(uint8 *p_token, uint8 *p_script);\r\n\r\nvoid CheckForPossibleInfiniteLoops(uint32 scriptName, uint8 *p_token, const char *p_fileName);\r\n\r\nconst char *GetChecksumNameFromLastQB(uint32 checksum);\r\nvoid RemoveChecksumNameLookupHashTable();\r\nuint8 *SkipToStartOfNextLine(uint8 *p_token);\r\nvoid PreProcessScript(uint8 *p_token);\r\n\r\n\r\n// Called from LoadQB in file.cpp\r\n\r\n// By default the allocateChecksumNameLookupTable flag is set to true because the table is needed when\r\n// generating prefix info for the nodearray, and we don't know whether the qb contains the nodearray until\r\n// after finishing parsing it.\r\n// The flag can be set to false when we know that checksum lookup info won't be needed & we're short of memory.\r\n// (Eg, Gary uses this when loading qb's for the cutscenes)\r\nvoid ParseQB(const char *p_fileName, uint8 *p_qb, EBoolAssertIfDuplicateSymbols assertIfDuplicateSymbols=NO_ASSERT_IF_DUPLICATE_SYMBOLS, bool allocateChecksumNameLookupTable=true);\r\n\r\nbool ScriptContainsName(uint8 *p_script, uint32 searchName);\r\nbool ScriptContainsAnyOfTheNames(uint32 scriptName, uint32 *p_names, int numNames);\r\n\r\n} // namespace Script\r\n\r\n#endif // #ifndef\t__SCRIPTING_PARSE_H\r\n"
  },
  {
    "path": "Code/Gel/Scripting/script.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// script.cpp\t\tKSH 1 Nov 2001\r\n//\r\n// CScript class member functions and misc script functions.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/scriptcache.h>\r\n#include <gel/scripting/tokens.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/parse.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/utils.h>\r\n#include <core/crc.h>\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/modules/skate/skate.h> // for SKATE_TYPE_SKATER\r\n#include <gel/scripting/debugger.h>\r\n#include <gel/net/client/netclnt.h> // For Net::Client class\r\n#ifndef __PLAT_WN32__\r\n#include <sk/gamenet/gamenet.h> // For GameNet::Manager\r\n#endif\r\n#include <sk/gamenet/scriptdebugger.h>\r\n\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n#include <gel/Event.h>\r\n#include <gel/objtrack.h>\r\n#endif\r\n\r\n//char foo[sizeof(Script::SReturnAddress)/0];\r\n\r\n//#define SEND_SCRIPT_NAMES_TO_DEBUGGER\r\n\r\nDefinePoolableClass(Script::CScript);\r\n\r\nnamespace Obj\r\n{\r\n\t#ifdef __NOPT_ASSERT__\r\n\textern bool DebugSkaterScripts;\r\n\t#endif\r\n\r\n}\r\n\r\nnamespace Script\r\n{\r\n\r\nstatic CScript * sCurrentlyUpdating = NULL;\r\n\r\n// Parse.cpp needs this, for getting the script pointer to send to any cfunc it\r\n// encounters when evaluating an expression.\r\n// It also uses it when processing RandomNoRepeat tokens.\r\nCScript *GetCurrentScript()\r\n{\r\n\treturn sCurrentlyUpdating;\r\n}\r\n\t\r\n#ifdef\t__NOPT_ASSERT__\r\n// for debugging, return the info of script we are currently updating\r\n// as the function that Asserts by it might not have a pointer \r\n// to the script \t\t\t\t\t\t\t\t\t  \r\nconst char  *GetCurrentScriptInfo()\r\n{\r\n\tif (sCurrentlyUpdating)\r\n\t{\r\n\t\treturn sCurrentlyUpdating->GetScriptInfo();\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn \"No Script currently updating\";\r\n\t}\r\n}\r\n\r\n#ifdef SEND_SCRIPT_NAMES_TO_DEBUGGER\r\nstatic void s_send_script_name(uint32 script_name, int numReturnAddresses)\r\n{\r\n\tstatic uint32 sp_ignored_script_names[]=\r\n\t{\r\n\t\tCRCC(0x1f8909cb,\"timeupscript\"),\r\n\t\tCRCC(0x1aef674f,\"game_update\"),\r\n\t\tCRCC(0x18b3b291,\"waitonegameframe\"),\r\n\t\tCRCC(0x7c4264dd,\"checkforswitchvehicles\"),\r\n\t\tCRCC(0x98f4c454,\"just_coasting\"),\r\n\t\tCRCC(0x30e72e33,\"do_random_effect\"),\r\n\t\tCRCC(0x7737d7b8,\"do_random_effect2\"),\r\n\t\tCRCC(0x99443e63,\"do_blur_effect\"),\r\n\t\tCRCC(0x3e6ab5cb,\"do_blur_effect_accept\"),\r\n\t\tCRCC(0x9c9dfcf8,\"disable_two_player_option\"),\r\n\t\tCRCC(0x380ec7a7,\"playbrakeanim\"),\r\n\t\tCRCC(0x838116e9,\"playbrakeidle\"),\r\n\t\tCRCC(0x7ae0d8aa,\"handbrake\"),\r\n\t\tCRCC(0x9f6a63e3,\"playturnanimorturnidle\"),\r\n\t\tCRCC(0x642587a0,\"cessbrake\"),\r\n\t\tCRCC(0x603ea7f3,\"waitanimfinished\"),\r\n\t\tCRCC(0x76792736,\"checkfornetbrake\"),\r\n\t\tCRCC(0xa4f522e9,\"parked_make_set_menu_item\"),\r\n\t\tCRCC(0xbeed50b6,\"make_text_sub_menu_item\"),\r\n\t\tCRCC(0x277b7b33,\"parked_make_piece_menu_item\"),\r\n\t\tCRCC(0x3ee4627d,\"doapush\"),\r\n\t\tCRCC(0x493a52f,\"helper_text_update_element\"),\r\n\t\tCRCC(0x5479735a,\"show_panel_message\"),\r\n\t\tCRCC(0x7a449180,\"DestroyMemStatsScreenElements\"),\r\n\t\tCRCC(0x901fefcf,\"setexception\"),\r\n\t\tCRCC(0xe9242afd,\"vibrateoff\"),\r\n\t\tCRCC(0xc4c8c400,\"switchonboard\"),\r\n\t\tCRCC(0xf8d27a88,\"switchoffboard\"),\r\n\t\tCRCC(0x1195c40a,\"bloodparticlesoff\"),\r\n\t\tCRCC(0x1946686b,\"skaterbloodoff\"),\r\n\t\tCRCC(0x243e716,\"verifyparam\"),\r\n\t\tCRCC(0x2c0c9e7b,\"onexceptionrun\"),\r\n\t\tCRCC(0x64df5e4c,\"WaitAnimWhilstChecking\"),\r\n\t\tCRCC(0xcf14cc35,\"ClothingLandBounce\"),\r\n\t\tCRCC(0x46f7302f,\"OnGroundExceptions\"),\r\n\t\tCRCC(0x500eb95b,\"InAirExceptions\"),\r\n\t\tCRCC(0x10da1c88,\"ClearExceptions\"),\r\n\t\tCRCC(0xaaef4fb5,\"ClearOnExceptionRun\"),\r\n\t\tCRCC(0xac281817,\"model_hide_geom\"),\r\n\t\tCRCC(0x3b9039a5,\"process_cas_command\"),\r\n\t\tCRCC(0xdea7fe56,\"goal_editor_update_cursor_position\"),\r\n\t};\r\n\t\r\n\tuint32 *p_ignored_script_names=sp_ignored_script_names;\r\n\tfor (uint32 i=0; i<sizeof(sp_ignored_script_names)/sizeof(uint32); ++i)\r\n\t{\r\n\t\tif (*p_ignored_script_names++==script_name)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\t\r\n\t}\r\n\r\n\tuint32 p_buf[2];\r\n\tp_buf[0]=script_name;\r\n\tp_buf[1]=numReturnAddresses;\r\n\t\r\n\t// Tell the debugger that this script is being run.\r\n\tNet::MsgDesc msg;\r\n\tmsg.m_Data = p_buf;\r\n\tmsg.m_Length = 8;\r\n\tmsg.m_Id = GameNet::vMSG_ID_DBG_RUNNING_SCRIPT;\r\n\tDbg::CScriptDebugger::Instance()->StreamMessage(&msg);\r\n}\r\n#endif\r\n\r\n#endif\r\n\r\n\r\nstatic CScript *sp_scripts=NULL;\r\nstatic uint32 s_num_cscripts=0;\r\n\r\nstatic bool\ts_done_one_per_frame;\r\n\r\nint CScript::s_next_unique_id = 0;\r\n\r\nuint32 GetNumCScripts()\r\n{\r\n\treturn s_num_cscripts;\r\n}\r\n\t\r\n// For use when external functions want to step through all existing scripts.\r\n// Pass it NULL to get the first CScript.\r\n// Should probably eventually change all the script code to use the iterators in the \r\n// standard container library at some point I guess.\r\nCScript *GetNextScript(CScript *p_script)\r\n{\r\n\tif (p_script==NULL)\r\n\t{\r\n\t\t// They want the first CScript\r\n\t\treturn sp_scripts;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn p_script->mp_next;\r\n\t}\r\n}\r\n\r\nCScript::CScript()\r\n{\r\n\t// Zero all the members. CScript is not derived from CClass so we don't get the auto-zeroing.\r\n\tuint32 size=sizeof(CScript);\r\n\tDbg_MsgAssert((size&3)==0,(\"sizeof(CScript) not a multiple of 4 ??\"));\r\n\tsize>>=2;\r\n\tuint32 *p_longs=(uint32*)this;\r\n\tfor (uint32 i=0; i<size; ++i)\r\n\t{\r\n\t\t*p_longs++=0;\r\n\t}\t\r\n\t\r\n\t// Add to the linked list.\t\t\t  \r\n\tmp_next=sp_scripts;\r\n\tif (sp_scripts) \r\n\t{\r\n\t\tsp_scripts->mp_previous=this;\r\n\t}\t\r\n\tsp_scripts=this;\r\n\r\n\t++s_num_cscripts;\r\n\r\n\tm_unique_id = s_next_unique_id++;\r\n\t\r\n\tmNode = -1;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\t\t\t\t\t\t\t\t\t\t\r\n\tm_last_instruction_time_taken=-1.0f;\r\n\tm_total_instruction_time_taken=0.0f;\r\n\t#endif\r\n\t\r\n\t#if\t0\r\n// if we go over 100 scripts, tell us why\r\n\tstatic uint32 max = 100;\r\n\tif (s_num_cscripts > max)\r\n\t{\r\n\t\tmax = s_num_cscripts;\r\n\t\tprintf (\"Record number of scripts: %d of %d\\nvvvvvvvvvvvvvvvvvvvvvvvvvvv\\n\",CScript::SGetNumUsedItems(),CScript::SGetTotalItems());\r\n\t\tScript::DumpScripts();\r\n\t\tDumpUnwindStack(20,0);\r\n\t\tprintf (\" ^^^^^^^^^^^^^^^^^^^^^^^^\\nRecord number of scripts: %d of %d\\n\",CScript::SGetNumUsedItems(),CScript::SGetTotalItems());\r\n\r\n\t}\r\n\t#endif\r\n\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tmp_event_handler_table = NULL;\r\n#endif\t \r\n\r\n\tmp_return_addresses=mp_return_addresses_small_buffer;\r\n\tmp_loops=mp_loops_small_buffer;\r\n}\r\n\r\nCScript::~CScript()\r\n{\r\n\tClearScript();\r\n\tif (mpCallbackScriptParams)\r\n\t{\r\n\t\tdelete mpCallbackScriptParams;\r\n\t}\r\n\t// Check to see if the script has already been deleted\r\n\t// perhaps we are deleteing it twice???\r\n\t\r\n\tDbg_MsgAssert(mp_next != (CScript *)-1,(\"mp_next is -1 in script we are trying to delete!!!\"));\r\n\tDbg_MsgAssert(mp_previous != (CScript *)-1,(\"mp_previous is -1 in script we are trying to delete!!!\"));\r\n\t\r\n\t// Remove from the linked list.\r\n\tif (mp_previous==NULL) \r\n\t{\r\n\t\tsp_scripts=mp_next;\r\n\t}\t\r\n\tif (mp_next) \r\n\t{\r\n\t\tDbg_MsgAssert(mp_next!=mp_previous,(\"mp_next same as mp_prev for script we are deleting\"));\r\n\t\tmp_next->mp_previous=mp_previous;\r\n\t}\t\r\n\tif (mp_previous) \r\n\t{\r\n\t\tDbg_MsgAssert(mp_next!=mp_previous,(\"mp_next same as mp_prev for script we are deleting\"));\r\n\t\tmp_previous->mp_next=mp_next;\r\n\t}\t\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\t\r\n\tmp_next = (CScript *)-1;\r\n\tmp_previous = (CScript *)-1;\r\n\t#endif\r\n\t\r\n\t// Release any stored RandomNoRepeat or RandomPermute info.\r\n\tReleaseStoredRandoms(this);\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\t\r\n\t#ifndef __PLAT_WN32__\r\n\tif (m_being_watched_in_debugger)\r\n\t{\r\n\t\t// Tell the debugger that this script has died.\r\n\t\tNet::MsgDesc msg;\r\n\t\tmsg.m_Data = &m_unique_id;;\r\n\t\tmsg.m_Length = 4;\r\n\t\tmsg.m_Id = GameNet::vMSG_ID_DBG_SCRIPT_DIED;\r\n\t\tDbg::CScriptDebugger::Instance()->StreamMessage(&msg);\r\n\t}\t\r\n\t#endif\r\n\t#endif\r\n\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tif (mp_event_handler_table)\r\n\t{\r\n\t\t// Remove the references to the event handler from the tracker\r\n\r\n//\t\tmp_event_handler_table->unregister_all(this);\r\n\t\tClearEventHandlerTable();   // Need this to clean up structs and stuff\r\n\t\r\n\t\tif (mp_event_handler_table->m_in_immediate_use_counter)\r\n\t\t{\r\n\t\t\t// table still in use by its pass_event() function,\r\n\t\t\t// so leave it up to that function to destroy the table\r\n\t\t\tmp_event_handler_table->m_valid = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tdelete mp_event_handler_table;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tDbg_MsgAssert(s_num_cscripts,(\"Zero s_num_cscripts\"));\r\n\t--s_num_cscripts;\r\n}\r\n\r\n#ifdef __NOPT_ASSERT__\r\n#ifndef __PLAT_WN32__\r\n\r\n// This gets called whenever mScriptChecksum is changed.\r\nvoid CScript::check_if_needs_to_be_watched_in_debugger()\r\n{\r\n\tDbg::SWatchedScript *p_watched_script_info=Dbg::CScriptDebugger::Instance()->GetScriptWatchInfo(mScriptChecksum);\r\n\tif (p_watched_script_info)\r\n\t{\r\n\t\tWatchInDebugger(p_watched_script_info->mStopScriptImmediately);\r\n\t}\t\r\n}\r\n\r\nuint32 *CScript::write_callstack_entry( uint32 *p_buf, int bufferSize, \r\n\t\t\t\t\t\t\t\t\t\tuint32 scriptNameChecksum, \r\n\t\t\t\t\t\t\t\t\t\tuint8 *p_PC,\r\n\t\t\t\t\t\t\t\t\t\tCStruct *p_params,\r\n\t\t\t\t\t\t\t\t\t\tObj::CObject *p_ob)\r\n{\r\n\tDbg_MsgAssert(bufferSize >= 8,(\"write_callstack_entry buffer overflow\"));\r\n\t*p_buf++=scriptNameChecksum;\r\n\t*p_buf++=Script::GetLineNumber(p_PC);\r\n\tbufferSize-=8;\r\n\t\t\r\n\t// Find out the source file and write it in.\r\n\tconst char *p_source_file_name=\"\";\r\n\tCSymbolTableEntry *p_sym=LookUpSymbol(scriptNameChecksum);\r\n\tif (p_sym)\r\n\t{\r\n\t\tp_source_file_name=FindChecksumName(p_sym->mSourceFileNameChecksum);\r\n\t}\r\n\tint len=strlen(p_source_file_name)+1;\r\n\tlen=(len+3)&~3;\r\n\tDbg_MsgAssert(bufferSize >= len,(\"write_callstack_entry buffer overflow\"));\t\r\n\tstrcpy((char*)p_buf,p_source_file_name);\r\n\tp_buf+=len/4;\r\n\tbufferSize-=len;\r\n\r\n\tDbg_MsgAssert(bufferSize >= 4,(\"write_callstack_entry buffer overflow\"));\r\n\t*p_buf++=(uint32)p_ob;\r\n\tbufferSize -= 4;\r\n\tif (p_ob)\r\n\t{\r\n\t\tDbg_MsgAssert(bufferSize >= 12,(\"write_callstack_entry buffer overflow\"));\r\n\t\t*p_buf++=p_ob->GetType();\r\n\t\t*p_buf++=p_ob->GetID();\r\n\t\t*p_buf++=p_ob->MainScriptIs(this);\r\n\t\tbufferSize -= 12;\r\n\t\t\r\n\t\t// Write out the object's tags.\r\n\t\tint bytes_written=Script::WriteToBuffer(p_ob->GetTags(),(uint8*)p_buf,bufferSize);\r\n\t\tbytes_written=(bytes_written+3)&~3;\r\n\t\tDbg_MsgAssert(bufferSize >= bytes_written,(\"write_callstack_entry buffer overflow\"));\r\n\t\tp_buf+=bytes_written/4;\r\n\t\tbufferSize-=bytes_written;\r\n\t}\r\n\t\r\n\t// Write out the parameters.\r\n\tint bytes_written=Script::WriteToBuffer(p_params,(uint8*)p_buf,bufferSize);\r\n\tbytes_written=(bytes_written+3)&~3;\r\n\tDbg_MsgAssert(bufferSize >= bytes_written,(\"write_callstack_entry buffer overflow\"));\r\n\tp_buf+=bytes_written/4;\r\n\t\r\n\treturn p_buf;\r\n}\r\n\r\n// Sets the comment string, which the script debugger displays.\r\n// This is so that the c-code can describe where the script was created from.\r\nvoid CScript::SetCommentString(const char *p_comment)\r\n{\r\n\tint len=strlen(p_comment);\r\n\tif (len>MAX_COMMENT_STRING_CHARS)\r\n\t{\r\n\t\tlen=MAX_COMMENT_STRING_CHARS;\r\n\t}\r\n\tfor (int i=0; i<len; ++i)\r\n\t{\r\n\t\tmp_comment_string[i]=p_comment[i];\r\n\t}\r\n\tmp_comment_string[len]=0;\r\n}\r\n\r\nvoid CScript::SetOriginatingScriptInfo(int lineNumber, uint32 scriptName)\r\n{\r\n\tm_originating_script_line_number=lineNumber;\r\n\tm_originating_script_name=scriptName;\r\n}\r\n\r\n// This transmits lots of info about the script to the script debugger running on the PC\r\nvoid CScript::TransmitInfoToDebugger(bool definitely_transmit)\r\n{\r\n\tuint32 *p_buf=Dbg::gpDebugInfoBuffer;\r\n\t\r\n\tint space_left=Dbg::SCRIPT_DEBUGGER_BUFFER_SIZE;\r\n\t\r\n\tDbg_MsgAssert(space_left >= 16,(\"Dbg::gpDebugInfoBuffer overflow\"));\r\n\t// Stuff that identifies the CScript\r\n\t*p_buf++=(uint32)this;\r\n\t*p_buf++=m_unique_id;\r\n\t*(float*)p_buf=m_last_instruction_time_taken;\r\n\t++p_buf;\r\n\t*(float*)p_buf=m_total_instruction_time_taken;\r\n\t++p_buf;\r\n\t\r\n\t// The originating script info, ie which script this got spawned from if it was created\r\n\t// by a SpawnScript command. Will be two zeros if no such info is available.\r\n\t*p_buf++=m_originating_script_line_number;\r\n\t*p_buf++=m_originating_script_name;\r\n\tspace_left-=24;\r\n\r\n\t// Write out the comment string.\t\r\n\tint comment_len=strlen(mp_comment_string)+1;\r\n\tint comment_space_needed=(comment_len+3)&~3;\r\n\tDbg_MsgAssert(space_left >= comment_space_needed,(\"Dbg::gpDebugInfoBuffer overflow\"));\r\n\tchar *p_source=mp_comment_string;\r\n\tchar *p_dest=(char*)p_buf;\r\n\tfor (int i=0; i<comment_len; ++i)\r\n\t{\r\n\t\t*p_dest++=*p_source++;\r\n\t}\t\r\n\tp_buf=(uint32*)(((char*)p_buf)+comment_space_needed);\r\n\tspace_left-=comment_space_needed;\r\n\t\r\n\t\t\r\n\t// Write out the function parameters.\r\n\tint structure_bytes_written=Script::WriteToBuffer(mp_function_params,(uint8*)p_buf,space_left);\r\n\tstructure_bytes_written=(structure_bytes_written+3)&~3;\r\n\tDbg_MsgAssert(space_left >= structure_bytes_written,(\"Dbg::gpDebugInfoBuffer overflow\"));\r\n\tp_buf+=structure_bytes_written/4;\r\n\tspace_left-=structure_bytes_written;\r\n\t\r\n\t// Write out the callstack\r\n\tDbg_MsgAssert(space_left >= 4,(\"Dbg::gpDebugInfoBuffer overflow\"));\r\n\t// Adding one because the current script is considered the last entry in the callstack\r\n\t// when displayed in the debugger.\r\n\t*p_buf++=m_num_return_addresses+1;\r\n\tspace_left-=4;\r\n\t\r\n\tuint32 *p_old=p_buf;\r\n    for (int i=0; i<m_num_return_addresses; ++i)\r\n    {\r\n\t\tp_buf=write_callstack_entry(p_buf,space_left,\r\n\t\t\t\t\t\t\t\t\tmp_return_addresses[i].mScriptNameChecksum,\r\n\t\t\t\t\t\t\t\t\tmp_return_addresses[i].mpReturnAddress,\r\n\t\t\t\t\t\t\t\t\tmp_return_addresses[i].mpParams,\r\n\t\t\t\t\t\t\t\t\tmp_return_addresses[i].mpObject);\r\n\t\tspace_left-=(p_buf-p_old)*4;\r\n\t\tp_old=p_buf;\t\t\t\t\t\t\t\t\t\t\t\r\n    }    \r\n\t// Output the current script as though it is the last entry in the callstack\r\n\t// so that it can be displayed simply in the debugger using the same code that\r\n\t// displayed the other callstack entries.\r\n\tp_buf=write_callstack_entry(p_buf,space_left,\r\n\t\t\t\t\t\t\t\tmScriptChecksum,\r\n\t\t\t\t\t\t\t\tmp_pc,\r\n\t\t\t\t\t\t\t\tmp_params,\r\n\t\t\t\t\t\t\t\tmpObject.Convert());\r\n\tspace_left-=(p_buf-p_old)*4;\r\n\r\n\r\n\tDbg_MsgAssert(space_left >= 20,(\"Dbg::gpDebugInfoBuffer overflow\"));\r\n\t\r\n\t// Whether spawned or not\r\n\t*p_buf++=mIsSpawned;\r\n\t\r\n\t// Wait state\r\n\t*p_buf++=m_wait_type;\r\n\t\r\n\t// Paused or not\r\n\t*p_buf++=mPaused;\r\n\t\r\n\t// Whether 'session specific' or not\r\n\t*p_buf++=mNotSessionSpecific;\r\n\t\r\n\t// Script debugger needs this so that it knows to expand and highlight the\r\n\t// last entry in the callstack when it receives the info.\r\n\t*p_buf++=m_single_step_mode;\r\n\t\r\n\tspace_left-=20;\r\n\t\r\n\tint message_size=((uint8*)p_buf)-((uint8*)Dbg::gpDebugInfoBuffer);\r\n\tDbg_MsgAssert(message_size <= Dbg::SCRIPT_DEBUGGER_BUFFER_SIZE,(\"Script info message too big !\"));\r\n\tDbg_MsgAssert(message_size+space_left == Dbg::SCRIPT_DEBUGGER_BUFFER_SIZE,(\"What ??\"));\r\n\t\r\n\tuint32 checksum=Crc::GenerateCRCCaseSensitive((const char *)Dbg::gpDebugInfoBuffer,message_size);\r\n\tif (checksum != m_last_transmitted_info_checksum || definitely_transmit)\r\n\t{\r\n\t\tprintf(\"CScript id=0x%08x Sending script info, message size=%d\\n\",m_unique_id,message_size);\r\n\t\t\r\n\t\tNet::MsgDesc msg;\r\n\t\tmsg.m_Data = Dbg::gpDebugInfoBuffer;\r\n\t\tmsg.m_Length = message_size;\r\n\t\tmsg.m_Id = GameNet::vMSG_ID_DBG_CSCRIPT_INFO;\r\n\t\tDbg::CScriptDebugger::Instance()->StreamMessage(&msg);\r\n\t\t\r\n\t\tm_last_transmitted_info_checksum=checksum;\r\n\t}\t\r\n}\r\n\r\nvoid CScript::TransmitBasicInfoToDebugger()\r\n{\r\n\tuint32 *p_buf=Dbg::gpDebugInfoBuffer;\r\n\t\r\n\t*p_buf++=m_unique_id;\r\n\t*p_buf++=mScriptChecksum;\r\n\t*p_buf++=Script::GetLineNumber(mp_pc);\r\n\t\t\r\n\t// Find out the source file and write it in.\r\n\tconst char *p_source_file_name=\"\";\r\n\tCSymbolTableEntry *p_sym=LookUpSymbol(mScriptChecksum);\r\n\tif (p_sym)\r\n\t{\r\n\t\tp_source_file_name=FindChecksumName(p_sym->mSourceFileNameChecksum);\r\n\t}\r\n\tint len=strlen(p_source_file_name)+1;\r\n\tlen=(len+3)&~3;\r\n\tstrcpy((char*)p_buf,p_source_file_name);\r\n\tp_buf+=len/4;\r\n\r\n\tint message_size=((uint8*)p_buf)-((uint8*)Dbg::gpDebugInfoBuffer);\r\n\tDbg_MsgAssert(message_size <= Dbg::SCRIPT_DEBUGGER_BUFFER_SIZE,(\"Script info message too big !\"));\r\n\t\r\n\t//printf(\"Sending vMSG_ID_DBG_BASIC_CSCRIPT_INFO\\n\");\r\n\tNet::MsgDesc msg;\r\n\tmsg.m_Data = Dbg::gpDebugInfoBuffer;\r\n\tmsg.m_Length = message_size;\r\n\tmsg.m_Id = GameNet::vMSG_ID_DBG_BASIC_CSCRIPT_INFO;\r\n\tDbg::CScriptDebugger::Instance()->StreamMessage(&msg);\r\n}\r\n\r\nvoid CScript::WatchInDebugger(bool stopScriptImmediately)\r\n{\r\n\tm_being_watched_in_debugger=true;\r\n\t\r\n\tif (stopScriptImmediately)\r\n\t{\r\n\t\tm_single_step_mode=STEP_INTO;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_single_step_mode=OFF;\r\n\t}\t\r\n}\r\n\r\nvoid CScript::StopWatchingInDebugger()\r\n{\r\n\tm_being_watched_in_debugger=false;\r\n}\t\r\n\r\nvoid CScript::DebugStop()\r\n{\r\n\tbool was_running=m_single_step_mode==OFF;\r\n\tm_single_step_mode=WAITING;\r\n\t\r\n\tif (was_running)\r\n\t{\r\n\t\t// This is so that the debugger registers the fact that m_single_step_mode has changed\r\n\t\t// and hence updates the window to indicate that the script has stopped.\r\n\t\tTransmitInfoToDebugger();\r\n\t}\t\r\n}\r\n\r\nvoid CScript::DebugStepInto()\r\n{\r\n\tm_single_step_mode=STEP_INTO;\r\n\tDbg::CScriptDebugger::Instance()->ScriptDebuggerUnpause();\t\r\n}\r\n\r\nvoid CScript::DebugStepOver()\r\n{\r\n\tm_single_step_mode=STEP_OVER;\r\n\tDbg::CScriptDebugger::Instance()->ScriptDebuggerUnpause();\t\r\n}\r\n\r\nvoid CScript::DebugGo()\r\n{\r\n\tm_single_step_mode=OFF;\r\n\tDbg::CScriptDebugger::Instance()->ScriptDebuggerUnpause();\t\r\n}\r\n#endif // #ifndef __PLAT_WN32__\r\n#endif // #ifdef __NOPT_ASSERT__\r\n\r\nvoid CScript::SetWait(EWaitType type, Obj::CBaseComponent *p_component)\r\n{\r\n\tm_wait_type=type;\r\n\tDbg_MsgAssert(mp_wait_component==NULL,(\"\\n%s\\nExpected mp_wait_component to be NULL here?\",GetScriptInfo()));\r\n\tmp_wait_component=p_component;\r\n}\r\n\r\nvoid CScript::ClearWait()\r\n{\r\n\tm_wait_type=WAIT_TYPE_NONE;\r\n\tmp_wait_component=NULL;\r\n}\r\n\r\nvoid CScript::Block()\r\n{\r\n\tm_wait_type=WAIT_TYPE_BLOCKED;\r\n}\r\n\r\nvoid CScript::UnBlock()\r\n{\r\n\tm_wait_type=WAIT_TYPE_NONE;\r\n}\r\n\r\nbool CScript::getBlocked()\r\n{\r\n\treturn m_wait_type==WAIT_TYPE_BLOCKED;\r\n}\r\n\r\nbool CScript::GotScript()\r\n{\r\n\treturn mp_pc?true:false;\r\n}\r\n\r\nvoid CScript::SwitchOnIfDebugging()\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tm_if_debug_on=true;\r\n#endif\r\n}\r\n\r\nvoid CScript::SwitchOffIfDebugging()\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tm_if_debug_on=false;\r\n#endif\r\n}\r\n\r\nvoid CScript::set_script(uint32 scriptChecksum, uint8 *p_script, CStruct *p_params, Obj::CObject *p_object)\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\t\r\n\t#ifdef SEND_SCRIPT_NAMES_TO_DEBUGGER\r\n\t// Tell the debugger that this script is begin run.\r\n\ts_send_script_name(scriptChecksum,0);\r\n\t#endif\r\n\t#endif\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (Obj::DebugSkaterScripts)\r\n\t{\r\n\t\tif (p_object && p_object->GetType()==SKATE_TYPE_SKATER)\r\n\t\t{\r\n\t\t\tprintf(\"%d: ############### %s ###############  [%i]\\n\",(int)Tmr::GetRenderFrame(),FindChecksumName(scriptChecksum),m_unique_id);\r\n\t\t}\r\n\t}\t\r\n\t#endif\r\n\r\n\tCStruct *p_params_copy=MakeParamsSafeFromDeletionByClearScript(p_params);\r\n\t\r\n\t// Reset the script.\r\n\tClearScript();\r\n\t\r\n\tDbg_MsgAssert(mp_function_params==NULL,(\"mp_function_params not NULL\"));\r\n\tmp_function_params=new CStruct;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__ \r\n\t// This is so that the structure can print line number info in case one of\r\n\t// the CStruct member function asserts goes off.\r\n\tmp_function_params->SetParentScript(this);\r\n\t#endif\r\n\t\t\r\n\tmScriptChecksum=scriptChecksum;\r\n\t#ifdef __NOPT_ASSERT__ \r\n\tcheck_if_needs_to_be_watched_in_debugger();\r\n\t#endif\t\r\n    mpObject=p_object;\r\n\t\r\n\tDbg_MsgAssert(mp_params==NULL,(\"mp_params not NULL\"));\r\n\tmp_params=new CStruct;\r\n\t#ifdef __NOPT_ASSERT__ \r\n\t// This is so that the structure can print line number info in case one of\r\n\t// the CStruct member function asserts goes off.\r\n\tmp_params->SetParentScript(this);\r\n\t#endif\r\n\t\r\n\tif (p_script)\r\n\t{\r\n\t\tmp_pc=p_script;\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tScript::CScriptCache *p_script_cache=Script::CScriptCache::Instance();\r\n\t\tDbg_MsgAssert(p_script_cache,(\"NULL p_script_cache\"));\r\n\t\r\n\t\tmp_pc=p_script_cache->GetScript(scriptChecksum);\r\n\t\tif (!mp_pc)\r\n\t\t{\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tif (Script::GetInteger(CRCD(0x22d1f89,\"AssertOnMissingScripts\")))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(false, (\"Script %s not found.\",FindChecksumName(scriptChecksum)));\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t\tif (p_params_copy)\r\n\t\t\t{\r\n\t\t\t\tdelete p_params_copy;\r\n\t\t\t}\r\n\t\t\tClearScript();\r\n\t\t\tClearEventHandlerTable();\r\n\t\t\treturn;\t\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Load the default parameters into mp_params\r\n\tmp_pc=AddComponentsUntilEndOfLine(mp_params, mp_pc);\r\n\t\t\r\n\t// Now merge what is in p_params onto mp_params.\r\n\tif (p_params_copy)\r\n\t{\r\n\t\tmp_params->AppendStructure(p_params_copy);\r\n\t\tdelete p_params_copy;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_params->AppendStructure(p_params);\r\n\t}\r\n\t\r\n\tif (GetOnExitScriptChecksum())\r\n\t{\r\n\t\t// Pass in the name of the exception so that certain exceptions can be ignored.\r\n\t\tScript::CStruct *pFoo=new Script::CStruct;\r\n// Mick - that has no meaning now, as this is triggered by everything\r\n//\t\tpFoo->AddComponent(NONAME, ESYMBOLTYPE_NAME, (int)p_entry->exception);\r\n\t\t// RunScript(GetOnExitScriptChecksum(), pFoo, mpObject );\r\n\t\t// Dan: interrupt instead of run\r\n\t\tuint32 checksum = GetOnExitScriptChecksum();\r\n\t\tSetOnExitScriptChecksum(0);\t// clear it once it has been run\r\n\t\tInterrupt(checksum, pFoo);\r\n\t\tdelete pFoo;\r\n\t}\r\n}\r\n\r\nvoid CScript::SetScript(const SStructScript *p_structScript, CStruct *p_params, Obj::CObject *p_object)\r\n{\r\n\tDbg_MsgAssert(p_structScript,(\"NULL p_structScript\"));\r\n\tDbg_MsgAssert(p_structScript->mNameChecksum,(\"Zero p_structScript->mNameChecksum\"));\r\n\tDbg_MsgAssert(p_structScript->mpScriptTokens,(\"NULL p_structScript->mpScriptTokens\"));\r\n\t\r\n\t// Calculate the size of the script\r\n\tuint32 size=SkipOverScript(p_structScript->mpScriptTokens)-p_structScript->mpScriptTokens;\r\n\t\r\n\t// Allocate a buffer and make a copy of the script (since the source may get deleted)\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\tuint8 *p_new_script=(uint8*)Mem::Malloc(size);\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\tuint8 *p_source=p_structScript->mpScriptTokens;\r\n\tuint8 *p_dest=p_new_script;\r\n\tfor (uint32 i=0; i<size; ++i)\r\n\t{\r\n\t\t*p_dest++=*p_source++;\r\n\t}\t\r\n\t\r\n\t// Call set_script, which will set up mp_pc etc.\r\n\tset_script(p_structScript->mNameChecksum,p_new_script,p_params,p_object);\r\n\t\r\n\t// Now set mp_struct_script, so that the buffer can be deleted later.\r\n\t// Note: The setting of mp_struct_script cannot be done before set_script, because set_script calls \r\n\t// ClearScript, which would have deleted mp_struct_script if it was not NULL.\r\n\tmp_struct_script=p_new_script;\r\n}\r\n\r\nvoid CScript::SetScript(uint32 scriptChecksum, CStruct *p_params, Obj::CObject *p_object)\r\n{\r\n\tset_script(scriptChecksum,NULL,p_params,p_object);\r\n}\r\n\r\nvoid CScript::SetScript(const char *p_scriptName, CStruct *p_params, Obj::CObject *p_object)\r\n{\r\n\tSetScript(Crc::GenerateCRCFromString(p_scriptName),p_params,p_object);\r\n}\r\n\r\nCStruct *CScript::MakeParamsSafeFromDeletionByClearScript(CStruct *p_params)\r\n{\r\n\t// It may be that p_params is mp_params or mp_function_params, or is a substructure of one\r\n\t// of those.\r\n\t// For example, when a manual is triggered, the passed p_params will be mp_function_params.\r\n\t// Since ClearScript() deletes both mp_params and mp_function_params,\r\n\t// this will result in p_params getting deleted too.\r\n\t// So if either mp_params or mp_function_params references p_params, store the contents\r\n\t// of p_params in p_new_params & return it.\r\n\t// This is a speed optimization, because it would be slow to always store the contents of\r\n\t// p_params. (Copying structures can be slow)\r\n\tCStruct *p_new_params=NULL;\r\n\tif (p_params)\r\n\t{\r\n\t\tif ((mp_function_params && mp_function_params->References(p_params)) || \r\n\t\t\t(mp_params && mp_params->References(p_params)))\r\n\t\t{\r\n\t\t\tp_new_params=new CStruct;\r\n\t\t\tp_new_params->AppendStructure(p_params);\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\treturn p_new_params;\r\n}\r\n\r\n// Stops the script from executing, and deletes the parameters, clears the stack, etc.\r\n// (REQUIREMENT: Must set mp_pc to NULL, so script will be deleted by UpdateSpawnedScripts)\r\nvoid CScript::ClearScript()\r\n{\r\n\tif (mp_struct_script)\r\n\t{\r\n\t\tMem::Free(mp_struct_script);\r\n\t\tmp_struct_script=NULL;\r\n\t}\r\n\r\n\tScript::CScriptCache *p_script_cache=Script::CScriptCache::Instance();\r\n\tDbg_MsgAssert(p_script_cache,(\"NULL p_script_cache\"));\r\n\tif (mp_pc)\r\n\t{\r\n\t\t// If a script was being executed, then decrement its usage in the script cache since\r\n\t\t// it is no longer needed by this CScript.\r\n\t\tp_script_cache->DecrementScriptUsage(mScriptChecksum);\r\n\t}\r\n\t\r\n\tmp_pc=NULL;\t\r\n\t\r\n\tif (mp_params)\r\n\t{\r\n\t\tdelete mp_params;\r\n\t\tmp_params=NULL;\r\n\t}\r\n\tif (mp_function_params)\r\n\t{\r\n\t\tdelete mp_function_params;\r\n\t\tmp_function_params=NULL;\r\n\t}\t\r\n\t\r\n    for (int i=0; i<m_num_return_addresses; ++i)\r\n    {\r\n\t\tp_script_cache->DecrementScriptUsage(mp_return_addresses[i].mScriptNameChecksum);\r\n\t\t\r\n        Dbg_MsgAssert(mp_return_addresses[i].mpParams,(\"NULL mpParams in return stack\"));\r\n\t\tif (mp_return_addresses[i].mpParams)\r\n\t\t{\r\n\t\t\tdelete mp_return_addresses[i].mpParams;\r\n\t\t\tmp_return_addresses[i].mpParams=NULL;\r\n\t\t}\t\r\n    }    \r\n\t\r\n\tm_num_return_addresses=0;\r\n\tif (mp_return_addresses != mp_return_addresses_small_buffer)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_return_addresses,(\"NULL mp_return_addresses ?\"));\r\n\t\tMem::Free(mp_return_addresses);\r\n\t}\r\n\tmp_return_addresses=mp_return_addresses_small_buffer;\r\n\r\n\r\n\tmp_current_loop=NULL;\r\n\tif (mp_loops != mp_loops_small_buffer)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_loops,(\"NULL mp_loops ?\"));\r\n\t\tMem::Free(mp_loops);\r\n\t}\r\n\tmp_loops=mp_loops_small_buffer;\r\n\t\r\n\t\r\n\tm_wait_timer=0;\r\n\tm_wait_type=WAIT_TYPE_NONE;\r\n\tmp_wait_component=NULL;\r\n\t\r\n\tmpObject=NULL;\r\n\tmScriptChecksum=0;\r\n\r\n\tm_interrupted=false;\r\n\tm_skip_further_process_waits=false;\r\n\t\r\n\t\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tm_if_status=0;\r\n\t#endif\r\n}\r\n\r\n// Cleans up the script's event handler table.  Call after ClearScript if you are not about to reset the script\r\n// (REQUIREMENT: Must set mp_pc to NULL, so script will be deleted by UpdateSpawnedScripts)\r\nvoid CScript::ClearEventHandlerTable()\r\n{\r\n\t#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tif (mp_event_handler_table)\r\n\t{\r\n\t\t// Remove the references to the event handler from the tracker\r\n\t\tmp_event_handler_table->unregister_all(this);\r\n\t\t\r\n\t\tmp_event_handler_table->remove_group(CRCD(0x8b713e0e, \"all_groups\"));\r\n\t}\r\n\t#endif\r\n}\r\n\r\n// Restarts the script.\r\nvoid CScript::Restart()\r\n{\r\n\t// This is a structure for temporarily storing the old parameters, since the SetScript call will clear\r\n\t// everything in the script, including deleting the structure pointed to by mp_params, and the call stack.\r\n\tCStruct *p_params=new CStruct;\r\n\t\r\n\tif (m_num_return_addresses)\r\n\t{\r\n\t\t// If there are things in the call stack, then the script that we want to restart is\r\n\t\t// the first one in the call stack, since this is the original script.\r\n\t\tDbg_MsgAssert(mp_return_addresses[0].mpParams,(\"NULL p_params in return stack\"));\r\n\t\t*p_params=*mp_return_addresses[0].mpParams;\r\n\t\tSetScript(mp_return_addresses[0].mScriptNameChecksum,p_params,mp_return_addresses[0].mpObject);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// If there is nothing in the call stack, restart the current script.\r\n\t\t*p_params=*mp_params;\r\n\t\t// The parameters are now safe in p_params, so restart the script by reinitialising it.\r\n\t\tSetScript(mScriptChecksum,p_params,mpObject);\r\n\t}\r\n\t\t\r\n\t// Delete the temporary structure.\r\n\tdelete p_params;\r\n}\r\n\r\n// Stops the script from being associated with an object, ie, sets mpObject to NULL.\r\n// Allows the script to continue executing though, so the script must not contain any\r\n// further member functions, otherwise the code will assert.\r\n// This function also sets m_wait_type=WAIT_TYPE_NONE; to ensure the Update function does\r\n// not assert if it is waiting for the object to finish doing something.\r\nvoid CScript::DisassociateWithObject(Obj::CObject *pObjectToDisconnectFrom)\r\n{\r\n\tif (!pObjectToDisconnectFrom) return;\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tpObjectToDisconnectFrom->SetLockAssertOff();\t\r\n\t#endif\r\n\r\n\tif (mpObject == pObjectToDisconnectFrom)\r\n\t{\r\n\t\tmpObject=NULL;\r\n\t}\r\n\tfor (int i=0; i<m_num_return_addresses; ++i)\r\n\t{\r\n\t\tif (mp_return_addresses[i].mpObject == pObjectToDisconnectFrom)\r\n\t\t{\r\n\t\t\tmp_return_addresses[i].mpObject = NULL;\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\tClearWait();\r\n}\r\n\r\n#ifdef __NOPT_ASSERT__\r\n#ifndef __PLAT_XBOX__\r\n\r\n#define SCRIPT_INFO_BUF_SIZE 1000\r\nstatic char sp_script_info[SCRIPT_INFO_BUF_SIZE];\r\n\r\nconst char *CScript::GetScriptInfo()\r\n{\r\n\t// if called on a NULL object, then return an appropiate string \r\n\tif (this == NULL)\r\n\t{\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\treturn \"No Script, probably CFunc called from RunScript or ForEachIn\";\r\n\t\t#else\r\n\t\treturn \"\";\r\n\t\t#endif\r\n\t}\r\n\tsprintf(sp_script_info,\"GetScriptInfo: Missing info\");\r\n\r\n\tif (mScriptChecksum)\r\n\t{\r\n\t\tCSymbolTableEntry *p_sym=LookUpSymbol(mScriptChecksum);\r\n\t\r\n\t\tif (p_sym)\r\n\t\t{\r\n\t\t\tif (mp_pc)\r\n\t\t\t{\r\n\t\t\t\tsprintf(sp_script_info,\"Line %d of %s, in script '%s'\",GetLineNumber(mp_pc),FindChecksumName(p_sym->mSourceFileNameChecksum),FindChecksumName(mScriptChecksum));\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsprintf(sp_script_info,\"GetScriptInfo: Script symbol not found. Strange.\");\r\n\t\t}\t\r\n\t}\r\n\t\t\r\n\tstrcat(sp_script_info,\"\\nScript call stack:\\n\");\r\n\tCSymbolTableEntry *p_sym=LookUpSymbol(mScriptChecksum);\r\n\tif (p_sym)\r\n\t{\r\n\t\tstrcat(sp_script_info,FindChecksumName(p_sym->mSourceFileNameChecksum));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tstrcat(sp_script_info,\"Unknown source file\");\r\n\t}\t\r\n\tsprintf(sp_script_info+strlen(sp_script_info),\" line %d, in \",GetLineNumber(mp_pc));\r\n\tstrcat(sp_script_info,FindChecksumName(mScriptChecksum));\r\n\tstrcat(sp_script_info,\"\\n\");\r\n    for (int i=m_num_return_addresses-1; i>=0; --i)\r\n    {\r\n\t\tif (mp_return_addresses[i].mpParams)\r\n\t\t{\r\n\t\t\tsprintf(sp_script_info+strlen(sp_script_info),\" line %d, in \",GetLineNumber(mp_return_addresses[i].mpReturnAddress));\r\n\t\t\tstrcat(sp_script_info,FindChecksumName(mp_return_addresses[i].mScriptNameChecksum));\r\n\t\t\tstrcat(sp_script_info,\"\\n\");\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tstrcat(sp_script_info,\"-\\n\");\r\n\t\t}\t\r\n    }    \r\n\t\t\r\n\t\t\r\n\tDbg_MsgAssert(strlen(sp_script_info)<SCRIPT_INFO_BUF_SIZE,(\"sp_script_info buffer overflow\"));\r\n\treturn sp_script_info;\r\n}\r\n\r\nint CScript::GetCurrentLineNumber(void)\r\n{\r\n\tif (mp_pc)\r\n\t{\r\n\t\treturn GetLineNumber(mp_pc);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 0;\r\n\t}\t\r\n}\r\n\r\nconst char *CScript::GetSourceFile(void)\r\n{\r\n\tCSymbolTableEntry *p_sym=LookUpSymbol(mScriptChecksum);\r\n\tif (p_sym)\r\n\t{\r\n\t\treturn FindChecksumName(p_sym->mSourceFileNameChecksum);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn \"Unknown\";\r\n\t}\r\n}\t\t\r\n#else\r\n// Need these to be fast on Xbox because they are used in Dbg_MsgAsserts(), which will call it\r\n// regardless of whether the assert condition is false.\r\nconst char *CScript::GetScriptInfo()\r\n{\r\n\treturn \"\";\r\n}\r\nint CScript::GetCurrentLineNumber(void)\r\n{\r\n\treturn 0;\r\n}\r\nconst char *CScript::GetSourceFile(void)\r\n{\r\n\treturn \"\";\r\n}\t\t\r\n#endif // #ifndef __PLAT_XBOX__\r\n#endif\r\n\r\n\r\n#ifdef __NOPT_ASSERT__\r\n#ifndef __PLAT_WN32__\r\n// For testing how many scripts end up needing the bigger buffer.\r\nbool CScript::UsingBigCallstackBuffer()\r\n{\r\n\tif (mp_return_addresses == mp_return_addresses_small_buffer)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\t\r\n}\r\n\r\nbool CScript::UsingBigLoopBuffer()\r\n{\r\n\tif (mp_loops == mp_loops_small_buffer)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\t\r\n}\r\n\r\n#endif\r\n#endif\r\n\r\n// Used by CScript::Update when calling a script.\r\n// call_script is also used by CScript::Interrupt below.\r\nvoid CScript::call_script(uint32 newScriptChecksum, uint8 *p_script, CStruct *p_params, Obj::CObject *p_object, bool interrupt)\r\n{\t\t\t  \r\n\t// K: If calling a script when nothing is currently being run, jump to it instead.\r\n\t// This is so that the mp_function_params gets created.\r\n\t// Fixes a bug where when a 2-player trick attack game was started, it would immediately\r\n\t// assert because call_script was called straight away on a newly created CScript.\r\n\t// (CGoal::RunCallbackScript would run a script which would do a MakeSkaterGosub, and the\r\n\t// skater's script was not running anything at that point)\r\n\tif (!mp_pc)\r\n\t{\r\n\t\tset_script(newScriptChecksum,p_script,p_params,p_object);\r\n\t\t\r\n\t\t// This may not really be necessary since there is no script to return to that might be affected,\r\n\t\t// but set it anyway for consistency.\r\n\t\tm_interrupted=interrupt;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Calling a subroutine, so store the current script info on the stack.\r\n\t\r\n\tif (mp_return_addresses == mp_return_addresses_small_buffer && \r\n\t\tm_num_return_addresses == RETURN_ADDRESSES_SMALL_BUFFER_SIZE)\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\tmp_return_addresses=(SReturnAddress*)Mem::Malloc(MAX_RETURN_ADDRESSES * sizeof(SReturnAddress));\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\tfor (int i=0; i<RETURN_ADDRESSES_SMALL_BUFFER_SIZE; ++i)\r\n\t\t{\r\n\t\t\tmp_return_addresses[i]=mp_return_addresses_small_buffer[i];\r\n\t\t\t/*\r\n\t\t\tmp_return_addresses[i].mScriptNameChecksum\t\t  = mp_return_addresses_small_buffer[i].mScriptNameChecksum;  \r\n\t\t\tmp_return_addresses[i].mpParams                   = mp_return_addresses_small_buffer[i].mpParams;             \r\n\t\t\tmp_return_addresses[i].mpReturnAddress            = mp_return_addresses_small_buffer[i].mpReturnAddress;      \r\n\t\t\tmp_return_addresses[i].mpObject                   = mp_return_addresses_small_buffer[i].mpObject.Convert();             \r\n\t\t\tmp_return_addresses_small_buffer[i].mpObject = NULL;\r\n\t\t\tmp_return_addresses[i].mpLoop                     = mp_return_addresses_small_buffer[i].mpLoop;               \r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tmp_return_addresses[i].m_if_status                = mp_return_addresses_small_buffer[i].m_if_status;          \r\n\t\t\t#endif\r\n\t\t\tmp_return_addresses[i].mWaitType                  = mp_return_addresses_small_buffer[i].mWaitType;            \r\n\t\t\tmp_return_addresses[i].mpWaitComponent            = mp_return_addresses_small_buffer[i].mpWaitComponent;      \r\n\t\t\tmp_return_addresses[i].mWaitTimer                 = mp_return_addresses_small_buffer[i].mWaitTimer;           \r\n\t\t\tmp_return_addresses[i].mStartTime                 = mp_return_addresses_small_buffer[i].mStartTime;           \r\n\t\t\tmp_return_addresses[i].mWaitPeriod                = mp_return_addresses_small_buffer[i].mWaitPeriod;          \r\n\t\t\tmp_return_addresses[i].mInterrupted               = mp_return_addresses_small_buffer[i].mInterrupted;         \r\n\t\t\t*/\r\n\t\t}\r\n\t}\r\n\t\t\r\n    Dbg_MsgAssert(m_num_return_addresses<MAX_RETURN_ADDRESSES,(\"\\n%s\\nScript stack overflow when trying to call the script '%s'\",GetScriptInfo(),FindChecksumName(newScriptChecksum)));\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\t\r\n\t#ifdef SEND_SCRIPT_NAMES_TO_DEBUGGER\r\n\t// Tell the debugger that this script is begin run.\r\n\ts_send_script_name(newScriptChecksum,m_num_return_addresses);\r\n\t#endif\r\n\t#endif\r\n\t\r\n\tSReturnAddress *p_stack_top=&mp_return_addresses[m_num_return_addresses++];\r\n\t\r\n    p_stack_top->mScriptNameChecksum=mScriptChecksum;\r\n    p_stack_top->mpParams=mp_params;\r\n    p_stack_top->mpReturnAddress=mp_pc;\r\n\tp_stack_top->mpObject=mpObject;\r\n\tp_stack_top->mpLoop=mp_current_loop;\r\n\t#ifdef __NOPT_ASSERT__\r\n\tp_stack_top->m_if_status=m_if_status;\r\n\t#endif\r\n\t\r\n\tp_stack_top->mWaitType=m_wait_type;\r\n\tp_stack_top->mpWaitComponent=mp_wait_component;\r\n\tp_stack_top->mWaitTimer=m_wait_timer;\r\n\tp_stack_top->mWaitPeriod=m_wait_period;\r\n\tp_stack_top->mStartTime=m_start_time;\r\n\t\r\n\tp_stack_top->mInterrupted=m_interrupted;\r\n    \r\n\t// Set the new mScriptChecksum\r\n    mScriptChecksum=newScriptChecksum;\r\n\t#ifdef __NOPT_ASSERT__ \r\n\tcheck_if_needs_to_be_watched_in_debugger();\r\n\t#endif\t\r\n\t\r\n\t// Set the new mp_pc\r\n    mp_pc=p_script;\r\n    Dbg_MsgAssert(mp_pc,(\"NULL p_script sent to call_script\"));\r\n\t\r\n\t// Create a new parameters structure, and fill it in using the default values listed after\r\n\t// the script name.\r\n\t// Note: Not asserting if mp_params is not NULL, because it probably won't be.\r\n\t// The old value of mp_params has been safely stored in the mp_return_addresses array above.\r\n    mp_params=new CStruct;\r\n\t#ifdef __NOPT_ASSERT__ \r\n\t// This is so that the structure can print line number info in case one of\r\n\t// the CStruct member function asserts goes off.\r\n\tmp_params->SetParentScript(this);\r\n\t#endif\r\n\tmp_pc=AddComponentsUntilEndOfLine(mp_params,mp_pc);\r\n\t\r\n\t// Now overlay the parameters passed to the script.\r\n\tif (p_params)\r\n\t{\r\n\t\t*mp_params+=*p_params;\r\n\t}\t\r\n\t\r\n\t// Set the object pointer, which may get changed if executing another object's\r\n\t// script using the : operator.\r\n\tmpObject=p_object;\r\n\t\r\n\tClearWait();\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\t// Not in an if-statement on starting the new routine.\r\n\tm_if_status=0;\r\n\t#endif\r\n\t\r\n\tm_interrupted=interrupt;\r\n}\r\n\r\n// Uses the above function to implement an interrupt.\r\n// This will jump to the passed script and also do one call to update.\r\n// Once the interrupt script is finished it will return to what it was doing before.\r\nEScriptReturnVal CScript::Interrupt(uint32 newScriptChecksum, CStruct *p_params)\r\n{\r\n\tScript::CScriptCache *p_script_cache=Script::CScriptCache::Instance();\r\n\tDbg_MsgAssert(p_script_cache,(\"NULL p_script_cache\"));\r\n\tuint8 *p_script=p_script_cache->GetScript(newScriptChecksum);\r\n\r\n\t// The true means interrupt the script, which means that the call to Update will not continue\r\n\t// execution of the interrupted script when the called script finishes.\r\n\tcall_script(newScriptChecksum,p_script,p_params,mpObject,true);\r\n\treturn Update();\r\n}\r\n\r\nbool CScript::Finished()\r\n{\r\n\treturn mp_pc && *mp_pc==ESCRIPTTOKEN_KEYWORD_ENDSCRIPT;\r\n}\r\n\r\n#ifdef __NOPT_ASSERT__\r\nstatic bool sExcludeFromSkaterDebug(uint32 name)\r\n{\r\n\tCArray *p_array=GetArray(0xdaa3a3a5/*ExcludeFromSkaterDebug*/,NO_ASSERT);\r\n\tif (!p_array)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\tfor (uint32 i=0; i<p_array->GetSize(); ++i)\r\n\t{\r\n\t\tif (name==p_array->GetChecksum(i))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn false;\t\t\r\n}\r\n#endif\r\n\r\n// This looks at m_wait_type, does the appropriate wait logic, and resets\r\n// m_wait_type back to WAIT_TYPE_NONE if the wait has finished.\r\n// Otherwise m_wait_type is left the same. \r\nvoid CScript::process_waits()\r\n{\r\n\tswitch (m_wait_type)\r\n\t{\r\n\t\tcase WAIT_TYPE_NONE:\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase WAIT_TYPE_COUNTER:\r\n\t\t\tif (m_wait_timer) \r\n\t\t\t{\r\n\t\t\t\t--m_wait_timer;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Finished counting down, so reset wait type \r\n\t\t\t\t// so that script execution continues.\r\n\t\t\t\tm_wait_type=WAIT_TYPE_NONE;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\r\n\t\tcase WAIT_TYPE_ONE_PER_FRAME:\r\n\t\t\tif (m_wait_timer) \r\n\t\t\t{\r\n\t\t\t\t--m_wait_timer;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (s_done_one_per_frame)\r\n\t\t\t\t{\r\n\t\t\t\t\t// already done one this frame\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Finished counting down, so reset wait type \r\n\t\t\t\t\t// so that script execution continues.\r\n\t\t\t\t\ts_done_one_per_frame = true;\r\n\t\t\t\t\tm_wait_type=WAIT_TYPE_NONE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\t\t\r\n\t\tcase WAIT_TYPE_TIMER:\r\n\t\t{\r\n//\t\t\tif (Tmr::ElapsedTime(m_start_time) >= m_wait_period)\r\n\t\t\t// Mick, instead of using global time, we decrement the timer whenever \r\n\t\t\t// the script is updated.  That way paused scripts will be genuinely paused\r\n\t\t\t//\r\n\t\t\t// Note, I use m_start_time as a patch variable\r\n\t\t\t// if it is not zero, I know we have not been round this loop\r\n\t\t\t// at least once.  \r\n\t\t\t// If you feel like changing this, then note that m_start_time gets pushed on the stack \r\n\t\t\t// when calling another script, you you will need to duplicate that functionality\r\n\t\t\t// \r\n\t\t\tint tick = (int) (Tmr::FrameLength() * 1000.0f);\t\t\t\r\n\t\t\tif ((int)m_wait_period < tick)\t\t\t\r\n\t\t\t{\r\n\t\t\t\tif (m_start_time == 0)\t   \t// only if we've waited at least one frame\r\n\t\t\t\t{\r\n\t\t\t\t\t// Finished counting down, so reset wait type \r\n\t\t\t\t\t// so that script execution continues.\r\n\t\t\t\t\tm_wait_type=WAIT_TYPE_NONE;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// finished counting down, but this was the first frame.\r\n\t\t\t\t\t// so we don't want to exit, as we cannot have a zero frame delay if \r\n\t\t\t\t\t// the time specified was not zero\r\n\t\t\t\t\t// be we want for sure to exit next time around, so set the wait period to 0\r\n\t\t\t\t\t//\r\n\t\t\t\t\tm_wait_period = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_wait_period -= tick;\r\n\t\t\t}\r\n\t\t\tm_start_time = 0;\t\t\t// flag that we have waited at least one frame\r\n\t\t\tbreak;\t\r\n\t\t}\t\r\n\t\tcase WAIT_TYPE_BLOCKED:\t\r\n\t\t\t// Nothing to do except wait for whatever blocked this script to unblock it.\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// These are the object wait options, which only apply if the script\r\n\t\t// has a parent object.\t\t\r\n\t\tcase WAIT_TYPE_OBJECT_MOVE:\t\r\n\t\tcase WAIT_TYPE_OBJECT_ANIM_FINISHED:\t\r\n\t\tcase WAIT_TYPE_OBJECT_JUMP_FINISHED:\t\r\n\t\tcase WAIT_TYPE_OBJECT_STOP_FINISHED:\r\n\t\tcase WAIT_TYPE_OBJECT_ROTATE:\r\n\t\tcase WAIT_TYPE_STREAM_FINISHED:\r\n\t\t\t// Call the parent object's wait function.\r\n\t\t\tDbg_MsgAssert(mp_wait_component,(\"\\n%s\\nNULL mp_wait_component, cannot call ProcessWait\",GetScriptInfo()));\r\n\t\t\tmp_wait_component->ProcessWait(this);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nBad wait type value of %d\",GetScriptInfo(),m_wait_type));\r\n\t\t\tbreak;\r\n\t}\t\t\r\n}\r\n\r\nvoid CScript::load_function_params()\r\n{\r\n\t#ifdef STOPWATCH_STUFF\r\n\tpFunctionParamsStopWatch->Start();\r\n\t#endif\r\n\t\r\n\t// Clear the function parameters structure and add the new params, using mp_params to get\r\n\t// any parameters referenced using the <,> operators.\r\n\tDbg_MsgAssert(mp_function_params,(\"NULL mp_function_params\"));\r\n\tmp_function_params->Clear();\r\n\t// AddComponentsUntilEndOfLine will assert if mp_pc is NULL\r\n\tmp_pc=AddComponentsUntilEndOfLine(mp_function_params,mp_pc,mp_params);\r\n\t\r\n\t#ifdef STOPWATCH_STUFF\r\n\tpFunctionParamsStopWatch->Stop();\r\n\t#endif\r\n}\r\n\r\n// Runs the specified member function. Uses mpObject by default, but uses p_substituteObject \r\n// if it is not NULL. p_substituteObject defaults to NULL if it is not specified.\r\n// Does not affect mp_pc\r\nbool CScript::run_member_function(uint32 functionName, Obj::CObject *p_substituteObject)\r\n{\r\n\tObj::CObject *p_obj;\r\n\t// By default member function calls operate on mpObject, but if\r\n\t// a substitute object has been specified use that instead.\r\n\tif (p_substituteObject)\r\n\t{\r\n\t\tp_obj=p_substituteObject;\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tp_obj=mpObject;\r\n\t}\t\r\n\t\r\n\tbool return_value=false;\r\n\t\r\n\tif (p_obj)\r\n\t{\r\n\t\t#ifdef STOPWATCH_STUFF\r\n\t\tpUpdateStopWatch->Stop();\r\n\t\tpCFunctionStopWatch->Start();\r\n\t\t#endif\r\n\t\t\r\n\t\t#ifdef STOPWATCH_STUFF\r\n\t\tTmr::CPUCycles TimeBefore,TimeAfter;\r\n\t\tTimeBefore=Tmr::GetTimeInCPUCycles();\r\n\t\t#endif\r\n\t\t\r\n\t\treturn_value=p_obj->CallMemberFunction(functionName,mp_function_params,this);\r\n\t\t\r\n\t\t#ifdef STOPWATCH_STUFF\r\n\t\tTimeAfter=Tmr::GetTimeInCPUCycles();\r\n\t\tfloat TimeTaken;\r\n\t\tTimeTaken=((int)(TimeAfter-TimeBefore))/150.0f;\r\n\t\tif (TimeTaken>200)\r\n\t\t{\r\n\t\t\t//SSymbolTableEntry *p_sym=LookUpSymbol(mScriptChecksum);\r\n\t\t\t//printf(\"Memb: %s, %f (%s, line %d)\\n\",FindChecksumName(NameChecksum),TimeTaken,p_sym->pFilename,GetLineNumber(mp_pc));\r\n\t\t}\t\r\n\t\t\r\n\t\tp_entry->mAverageExecutionTime = (p_entry->mAverageExecutionTime*p_entry->mNumCalls+TimeTaken)/(p_entry->mNumCalls+1);\r\n\t\t++p_entry->mNumCalls;\r\n\t\tp_entry->mNumCallsInThisFrame=600;\r\n\t\t#endif\r\n\t\t\r\n\t\t#ifdef STOPWATCH_STUFF\r\n\t\tpCFunctionStopWatch->Stop();\r\n\t\tpUpdateStopWatch->Start();\r\n\t\t#endif\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\t#ifdef __PLAT_WN32__\r\n\t\tif (functionName != 0xb3c262ec) // \"DisassociateFromObject\" is okay, no harm in trying to break non-existent association\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nTried to call member function %s from a script\\nnot associated with a CObject\",GetScriptInfo(),FindChecksumName(functionName)));\r\n\t\t}\r\n\t\t#else\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\t\t// It network games, it's expected that some objects will no longer exist by the time\r\n\t\t// some object member functions are called via remote scripts.  One example being, when\r\n\t\t// someone joins a game-in-progress, they will be instructed to execute a series of scripts\r\n\t\t// and it's possible that the objects which originally spawned those scripts are no \r\n\t\t// longer in the game or that the client has yet to create skaters for them.  So in \r\n\t\t// those cases, just print a warning and try to continue processing the script\r\n\t\tif( gamenet_man->InNetGame())\r\n\t\t{   \r\n\t\t\tDbg_Warning( \"\\n%s\\nTried to call member function %s from a script\\nnot associated with a CObject\",GetScriptInfo(),FindChecksumName(functionName));\r\n\t\t}\r\n\t\telse if (functionName != 0xb3c262ec) // \"DisassociateFromObject\" is okay, no harm in trying to break non-existent association\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nTried to call member function %s from a script\\nnot associated with a CObject\",GetScriptInfo(),FindChecksumName(functionName)));\r\n\t\t}\r\n\t\t#endif\r\n\t}\r\n\t\r\n\treturn return_value;\r\n}\r\n\r\n// Executes the passed c-function pointer, using the current mp_function_params as parameters.\r\nbool CScript::run_cfunction(bool (*p_cfunc)(CStruct *pParams, CScript *pCScript))\r\n{\r\n\tDbg_MsgAssert(p_cfunc,(\"\\n%s\\nNULL p_cfunc\",GetScriptInfo()));\r\n\t\r\n\t#ifdef STOPWATCH_STUFF\r\n\tpUpdateStopWatch->Stop();\r\n\tpCFunctionStopWatch->Start();\r\n\t#endif\r\n\t\r\n\t#ifdef STOPWATCH_STUFF\r\n\tTmr::CPUCycles TimeBefore,TimeAfter;\r\n\tTimeBefore=Tmr::GetTimeInCPUCycles();\r\n\t#endif\r\n\r\n\t/*\r\n\tTmr::Time TimeBefore,TimeAfter;\r\n\tTimeBefore=Tmr::GetTimeInCPUCycles();\r\n\t*/\r\n\t\r\n\tbool return_value=(*p_cfunc)(mp_function_params,this);\r\n\r\n\t/*\r\n\tTimeAfter=Tmr::GetTimeInCPUCycles();\r\n\tfloat TimeTaken;\r\n\tTimeTaken=((int)(TimeAfter-TimeBefore))/150.0f;\r\n\tif (TimeTaken>Script::GetFloat(\"Threshold\"))\r\n\t{\r\n\t\tCArray *p_exclude=Script::GetArray(\"Exclude\");\r\n\t\tbool exclude=false;\r\n\t\tfor (uint32 i=0; i<p_exclude->GetSize(); ++i)\r\n\t\t{\r\n\t\t\tif (p_exclude->GetChecksum(i)==name_checksum)\r\n\t\t\t{\r\n\t\t\t\texclude=true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!exclude)\r\n\t\t{\r\n\t\t\tCSymbolTableEntry *p_sym=LookUpSymbol(mScriptChecksum);\r\n\t\t\tprintf(\"CFunc: %s, %f (%s, line %d)\\n\",FindChecksumName(name_checksum),TimeTaken,FindChecksumName(p_sym->mSourceFileNameChecksum),GetLineNumber(mp_pc));\r\n\t\t}\t\r\n\t}\t\r\n\t*/\r\n\r\n\t\r\n\t#ifdef STOPWATCH_STUFF\r\n\tTimeAfter=Tmr::GetTimeInCPUCycles();\r\n\tfloat TimeTaken;\r\n\tTimeTaken=((int)(TimeAfter-TimeBefore))/150.0f;\r\n\tif (TimeTaken>200)\r\n\t{\r\n\t\t//SSymbolTableEntry *p_sym=LookUpSymbol(mScriptChecksum);\r\n\t\t//printf(\"CFunc: %s, %f (%s, line %d)\\n\",FindChecksumName(NameChecksum),TimeTaken,p_sym->pFilename,GetLineNumber(mp_pc));\r\n\t}\t\r\n\tp_entry->mAverageExecutionTime = (p_entry->mAverageExecutionTime*p_entry->mNumCalls+TimeTaken)/(p_entry->mNumCalls+1);\r\n\t++p_entry->mNumCalls;\r\n\tp_entry->mNumCallsInThisFrame=600;\r\n\t#endif\r\n\t\r\n\t\r\n\t#ifdef STOPWATCH_STUFF\r\n\tpCFunctionStopWatch->Stop();\r\n\tpUpdateStopWatch->Start();\r\n\t#endif\r\n\t\r\n\treturn return_value;\r\n}\r\n\r\n// Gets the name from mp_pc.\r\n// If mp_pc points to a <,> type name, it will look up that name in mp_params.\r\n// It will advance mp_pc to after the name.\r\nuint32 CScript::get_name()\r\n{\r\n\tuint32 name_checksum=0;\r\n\t\r\n\tswitch (*mp_pc)\r\n\t{\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ALLARGS:\r\n\t\t{\r\n\t\t\t++mp_pc;\r\n\t\t\tmp_params->GetChecksum(NO_NAME,&name_checksum);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase ESCRIPTTOKEN_ARG:\r\n\t\t{\r\n\t\t\t++mp_pc;\r\n\t\t\tDbg_MsgAssert(*mp_pc==ESCRIPTTOKEN_NAME,(\"\\n%s\\nExpected '<' token to be followed by a name.\",GetScriptInfo()));\r\n\t\t\t++mp_pc;\r\n\t\t\tuint32 arg_checksum=Read4Bytes(mp_pc).mChecksum;\r\n\t\t\tmp_pc+=4;\r\n\t\t\tmp_params->GetChecksum(arg_checksum,&name_checksum);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase ESCRIPTTOKEN_NAME:\r\n\t\t{\r\n\t\t\t++mp_pc;\r\n\t\t\tname_checksum=Read4Bytes(mp_pc).mChecksum;\r\n\t\t\tmp_pc+=4;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nUnexpected '%s' token when expecting some sort of name\",GetScriptInfo(),GetTokenName((EScriptToken)*mp_pc)));\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\treturn name_checksum;\r\n}\r\n\r\n// Executes the command pointed to by mp_pc, and returns true or false, which is the value to\r\n// be used by any preceding if-statement.\r\n// After executing the command, mp_pc will have changed. It might be pointing to the next command in\r\n// the current script, or to a command in a different script, or it might even be NULL, who knows?\r\n// A 'command' is either a cfunc,member func, or script call, in which the command has the form of\r\n// some sort of name followed by a list of parameters to be sent to it.\r\n// It also covers the direct setting of one of the script's parameters, such as <x>=3\r\n// It also covers expressions enclosed in parentheses that can be used in if's, eg if (1>0)\r\n// Note that like in C, expressions on their own are valid commands, eg (23*67), but unless preceded\r\n// by an if their result will be discarded.\r\n//\r\n// The term 'command' does not cover things like if's, begin-repeat's, or switch statements.\r\n// Generally the logic for interpreting that stuff is done in CScript::Update.\r\nbool CScript::execute_command()\r\n{\r\n\tuint8 token=*mp_pc;\r\n\r\n\t// Check for the pre-processed member function token.\r\n\tif (token==ESCRIPTTOKEN_RUNTIME_MEMBERFUNCTION)\r\n\t{\r\n\t\t++mp_pc;\r\n\t\tuint32 member_function_checksum=Read4Bytes(mp_pc).mChecksum;\r\n\t\tmp_pc+=4;\r\n\t\t\r\n\t\tload_function_params();\r\n\t\treturn run_member_function(member_function_checksum);\r\n\t}\r\n\t\t\r\n\t// Check for the pre-processed cfunction token.\r\n\tif (token==ESCRIPTTOKEN_RUNTIME_CFUNCTION)\r\n\t{\r\n\t\t++mp_pc;\r\n        bool (*p_cfunc)(CStruct *pParams, CScript *pCScript)=Read4Bytes(mp_pc).mpCFunction;\r\n\t\tmp_pc+=4;\r\n\t\t\r\n\t\tload_function_params();\r\n\t\treturn run_cfunction(p_cfunc);\t\t\r\n\t}\r\n\r\n\t// Check for an expression enclosed in parentheses\r\n\tif (token==ESCRIPTTOKEN_OPENPARENTH)\r\n\t{\r\n\t\t// Note: Not skipping past the open-parenth token because Evaluate() expects it.\r\n\t\tCComponent *p_comp=new CComponent;\r\n\t\tmp_pc=Evaluate(mp_pc,mp_params,p_comp);\r\n\t\t\t\t\r\n\t\tDbg_MsgAssert(p_comp->mType==ESYMBOLTYPE_INTEGER,(\"\\n%s\\nBad type of '%s' returned by expression, expected integer\",GetScriptInfo(),GetTypeName(p_comp->mType)));\r\n\t\tbool return_value=p_comp->mIntegerValue;\r\n\r\n\t\tCleanUpComponent(p_comp);\r\n\t\tdelete p_comp;\r\n\t\t\r\n\t\treturn return_value;\r\n\t}\t\r\n\t\r\n\t// Otherwise, expect some sort of name, ie Blaa or <Blaa>\r\n\tuint32 name=get_name();\r\n\t\r\n\t// Check if the name is followed by a colon, in which case the name is the id of some object.\r\n\tif (*mp_pc==ESCRIPTTOKEN_COLON)\r\n\t{\r\n\t\tObj::CObject *p_substitute_object = NULL;\r\n\t\t// Find the object\r\n#ifndef __PLAT_WN32__\r\n\t\tp_substitute_object=Obj::ResolveToObject(name);\r\n#endif\r\n\t\tDbg_MsgAssert(p_substitute_object,(\"\\n%s\\nCould not resolve '%s' to a CObject instance\",GetScriptInfo(),FindChecksumName(name)));\r\n\t\tif( p_substitute_object == NULL )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n//\t\tif (p_substitute_object == mpObject)\r\n//\t\t{\r\n//\t\t\tprintf(\"\\n\\n----------------------------------->\\n\\%s\\nThis script is already running on %s\\n\",GetScriptInfo(),FindChecksumName(name));\r\n//\t\t}\r\n\t\t\r\n\t\t++mp_pc;\r\n\t\tmp_pc=DoAnyRandomsOrJumps(mp_pc);\r\n\r\n\t\t// Now we're expecting some sort of function to run on the object.\r\n\t\t\r\n\t\t// Check for a pre-processed member function\r\n\t\tif (*mp_pc==ESCRIPTTOKEN_RUNTIME_MEMBERFUNCTION)\r\n\t\t{\r\n\t\t\t++mp_pc;\r\n\t\t\tuint32 member_function_checksum=Read4Bytes(mp_pc).mChecksum;\r\n\t\t\tmp_pc+=4;\r\n\t\t\t\r\n\t\t\tload_function_params();\r\n\t\t\treturn run_member_function(member_function_checksum,p_substitute_object);\r\n\t\t}\r\n\r\n\t\t// No pre-processed member function, so expect some sort of name.\r\n\t\tuint32 function_checksum=get_name();\r\n\t\t\r\n\t\t// Get the parameters that follow the name.\r\n\t\tload_function_params();\r\n\r\n\t\t// Look-up what kind of function it is.\r\n\t\tCSymbolTableEntry *p_entry=Resolve(function_checksum);\r\n\t\t\r\n\t\t// if the script is \"runmenow\" then a syntax error \r\n\t\t// should just printf a warning and return\r\n\t\tif (!p_entry && mScriptChecksum == 0xfb11e6cd)   // RunMeNow\r\n\t\t{\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tprintf(\"WARNING !! Confused by '%s', which does not appear to be defined anywhere.\\nIf it is a C-function or member function, it needs to be listed in ftables.cpp.\",FindChecksumName(function_checksum));\r\n\t\t\t#endif\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\r\n\t\tDbg_MsgAssert(p_entry,(\"\\n%s\\nConfused by '%s', which does not appear to be defined anywhere.\\nIf it is a C-function or member function, it needs to be listed in ftables.cpp.\",GetScriptInfo(),FindChecksumName(function_checksum)));\r\n\r\n\t\t// Expecting the function to be either a member function, or a script.\t\r\n\t\tswitch (p_entry->mType)\r\n\t\t{\r\n\t\tcase ESYMBOLTYPE_QSCRIPT:\r\n\t\t{\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tif (Obj::DebugSkaterScripts)\r\n\t\t\t{\r\n\t\t\t\tif (p_substitute_object->GetType()==SKATE_TYPE_SKATER)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!sExcludeFromSkaterDebug(function_checksum))\r\n\t\t\t\t\t{\t \r\n\t\t\t\t\t\tprintf(\"%d: Calling %s [%i]\\n\",(int)Tmr::GetRenderFrame(),FindChecksumName(function_checksum),m_unique_id);\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t}\t\t\r\n\t\t\t#endif\r\n\r\n\t\t\tScript::CScriptCache *p_script_cache=Script::CScriptCache::Instance();\r\n\t\t\tDbg_MsgAssert(p_script_cache,(\"NULL p_script_cache\"));\r\n\t\t\tuint8 *p_script=p_script_cache->GetScript(p_entry->mNameChecksum);\r\n\t\t\t\r\n\t\t\tcall_script(function_checksum,p_script,mp_function_params,p_substitute_object);\r\n\t\t\treturn true;\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase ESYMBOLTYPE_MEMBERFUNCTION:\r\n\t\t\treturn run_member_function(function_checksum,p_substitute_object);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\n'%s' is not a member function or script\",GetScriptInfo(),FindChecksumName(function_checksum)));\r\n\t\t\treturn false;\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t}\r\n\t\r\n\t// Check if the name is followed by equals.\r\n\t// In this case, the name is the name of the parameter we want to set.\r\n\tif (*mp_pc==ESCRIPTTOKEN_EQUALS)\r\n\t{\r\n\t\t// The get_name call will have looked up any <,> name in the structure, so re-get the\r\n\t\t// preceding name, because we want both x and <x> to mean x.\r\n\t\tmp_pc-=5;\r\n\t\tDbg_MsgAssert(*mp_pc==ESCRIPTTOKEN_NAME,(\"\\n%s\\nEquals must be preceded by a param name\",GetScriptInfo()));\r\n\t\t++mp_pc;\r\n\t\tname=Read4Bytes(mp_pc).mChecksum;\r\n\t\tmp_pc+=5; // +5 to skip over the equals too.\r\n\r\n\t\tmp_pc=DoAnyRandomsOrJumps(mp_pc);\r\n\r\n\t\t// Calculate the value of whatever follows the equals, and store it in p_comp\t\t\r\n\t\tCComponent *p_comp=new CComponent;\r\n\t\tif (*mp_pc==ESCRIPTTOKEN_OPENPARENTH)\r\n\t\t{\r\n\t\t\t// It's an expression, so evaluate it.\r\n\t\t\tmp_pc=Evaluate(mp_pc,mp_params,p_comp);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// It's not an expression, so just load the value in.\r\n\t\t\tmp_pc=FillInComponentUsingQB(mp_pc,mp_params,p_comp);\r\n\t\t}\r\n\r\n\t\tif (p_comp->mType!=ESYMBOLTYPE_NONE)\r\n\t\t{\r\n\t\t\t// Got some sort of value, so name it and stick it into mp_params.\r\n\t\t\tp_comp->mNameChecksum=name;\r\n\t\t\tmp_params->AddComponent(p_comp);\r\n\t\t\t// Not deleting p_comp because it has been given to mp_params\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Did not get a value, so clean up p_comp\r\n\t\t\tdelete p_comp;\r\n\t\t}\t\r\n\t\t\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\t// The name is not followed by a colon or an equals, so it must be a function call.\r\n\t// Load in the parameters that follow.\r\n\tload_function_params();\r\n\t\r\n\t// Look up the function to see what it is.\r\n    CSymbolTableEntry *p_entry=Resolve(name);\r\n\t\r\n\t// if the script is \"runmenow\" then a syntax error \r\n\t// should just printf a warning and return\r\n\tif (!p_entry && mScriptChecksum == 0xfb11e6cd)   // RunMeNow\r\n\t{\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tprintf(\"WARNING !! Confused by '%s', which does not appear to be defined anywhere.\\nIf it is a C-function or member function, it needs to be listed in ftables.cpp.\",FindChecksumName(name));\r\n\t\t#endif\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (!p_entry)\r\n\t{\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tif (Script::GetInteger(CRCD(0x22d1f89,\"AssertOnMissingScripts\")))\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(p_entry,(\"\\n%s\\nConfused by '%s', which does not appear to be defined anywhere.\\nIf it is a C-function or member function, it needs to be listed in ftables.cpp.\",GetScriptInfo(),FindChecksumName(name)));\r\n\t\t}\r\n\t\telse\r\n\t\t#endif\r\n\t\t{\r\n\t\t\t#ifdef __PLAT_WN32__\r\n\t\t\t// Don't printf if compiling on PC, otherwise LevelAssetLister prints lots\r\n\t\t\t// of warning messages when running the load sound scripts.\r\n\t\t\t#else\r\n\t\t\tprintf (\"WARNING: script %s not found, ignoring in default level.\\n\",FindChecksumName(name));\r\n\t\t\t#endif\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\t\t\t\t\t\t\t\t \r\n\r\n    switch (p_entry->mType)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_CFUNCTION:\r\n\t\t\treturn run_cfunction(p_entry->mpCFunction);\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_MEMBERFUNCTION:\r\n\t\t\treturn run_member_function(name);\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_QSCRIPT:\r\n\t\t{\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tif (Obj::DebugSkaterScripts)\r\n\t\t\t{\r\n\t\t\t\tif (mpObject && mpObject->GetType()==SKATE_TYPE_SKATER)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!sExcludeFromSkaterDebug(name))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tprintf(\"%d: Calling %s [%i]\\n\",(int)Tmr::GetRenderFrame(),FindChecksumName(name),m_unique_id);\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t}\t\t\r\n\t\t\t#endif\r\n\r\n\t\t\tScript::CScriptCache *p_script_cache=Script::CScriptCache::Instance();\r\n\t\t\tDbg_MsgAssert(p_script_cache,(\"NULL p_script_cache\"));\r\n\t\t\tuint8 *p_script=p_script_cache->GetScript(p_entry->mNameChecksum);\r\n\t\t \r\n\t\t\tcall_script(name,p_script,mp_function_params,mpObject);\r\n\t\t\t// Script calls always return true.\r\n\t\t\treturn true;\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\n'%s' cannot be called, because it's a '%s'\",GetScriptInfo(),FindChecksumName(name),GetTypeName(p_entry->mType)));\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\t\r\n\treturn false;\r\n}\r\n\r\nvoid CScript::execute_if()\r\n{\r\n\tDbg_MsgAssert(mp_pc,(\"NULL mp_pc\"));\r\n\tDbg_MsgAssert(*mp_pc==ESCRIPTTOKEN_KEYWORD_IF,(\"Unexpected *mp_pc='%s', expected keyword 'if'\",GetTokenName((EScriptToken)*mp_pc)));\r\n\r\n\t// Skip over the if token.\t\r\n\t++mp_pc;\r\n\t\r\n\tbool negate=false;\r\n\tif (*mp_pc==ESCRIPTTOKEN_KEYWORD_NOT)\r\n\t{\r\n\t\t++mp_pc;\r\n\t\tnegate=true;\r\n\t}\t\r\n\t\t\r\n\tbool return_value=execute_command();\r\n\t\r\n\t// mp_pc will have changed, and might be NULL.\r\n\tif (!mp_pc)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tif (negate)\r\n\t{\r\n\t\treturn_value=!return_value;\r\n\t}\t\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tDbg_MsgAssert((m_if_status&0x80000000)==0,(\"\\n%s\\nToo many nested if's\",GetScriptInfo()));\r\n\tm_if_status<<=1;\r\n\t#endif\r\n\t\r\n\t// If the return value is false, skip forward to the 'else' or 'endif' statement.\r\n\tif (!return_value)\r\n\t{\r\n\t\tint in_nested_if=0;\r\n\r\n\t\t// Skip mp_pc to the current if's 'else' or 'endif',\r\n\t\t// but ignore the else & endifs belonging to nested ifs.\r\n\t\t#ifdef STOPWATCH_STUFF\r\n\t\tpIfSkipStopWatch->Start();\r\n\t\t#endif\r\n\t\twhile (in_nested_if || \r\n\t\t\t   !(*mp_pc==ESCRIPTTOKEN_KEYWORD_ELSE || *mp_pc==ESCRIPTTOKEN_KEYWORD_ENDIF))\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(*mp_pc!=ESCRIPTTOKEN_KEYWORD_ENDSCRIPT,(\"endif or else keywords not found after if keyword.\"));\r\n\t\t\t\r\n\t\t\t// Keep track of nested ifs.\r\n\t\t\tif (*mp_pc==ESCRIPTTOKEN_KEYWORD_IF)\r\n\t\t\t{\r\n\t\t\t\t++in_nested_if;\r\n\t\t\t}\r\n\t\t\telse if (*mp_pc==ESCRIPTTOKEN_KEYWORD_ENDIF)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(in_nested_if,(\"Got endif within true part of if statement without corresponding nested if\"));\r\n\t\t\t\t--in_nested_if;\r\n\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\tmp_pc=SkipToken(mp_pc);\r\n\t\t}    \r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tif (*mp_pc==ESCRIPTTOKEN_KEYWORD_ENDIF)\r\n\t\t{\r\n\t\t\tm_if_status>>=1;\r\n\t\t}\r\n\t\t#endif\r\n\t\t// Skip over the 'else' or 'endif'\r\n\t\t++mp_pc;\r\n\t\t\r\n\t\t#ifdef STOPWATCH_STUFF\r\n\t\tpIfSkipStopWatch->Stop();\r\n\t\t#endif\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Otherwise, if the return value was true, mp_pc remains unchanged so that the instructions\r\n\t\t// following the if get executed.\r\n\t\t\r\n\t\t// Record the if-status so that spurious else's can be detected.\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tm_if_status|=1;\r\n\t\t#endif\r\n\t}\t\r\n\r\n\t// I'm pretty sure if-debug isn't used, check with Scott\r\n\t/*\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (m_if_debug_on)\r\n\t{\r\n\t\tprintf(\"%s: If %s \",FindChecksumName(mScriptChecksum),FindChecksumName(name_checksum));\r\n\t\tif (return_value)\r\n\t\t{\r\n\t\t\tprintf(\"TRUE\\n\");\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tprintf(\"FALSE\\n\");\r\n\t\t}\t\r\n\t}\r\n\t#endif\r\n\t*/\r\n}\r\n\r\n// On entry, mp_pc must point to an else token.\r\n// Skips forward till it hits an endif, then skips over the endif.\r\nvoid CScript::execute_else()\r\n{\r\n\tDbg_MsgAssert(mp_pc,(\"NULL mp_pc\"));\r\n\tDbg_MsgAssert(*mp_pc==ESCRIPTTOKEN_KEYWORD_ELSE,(\"Unexpected *mp_pc='%s', expected keyword 'else'\",GetTokenName((EScriptToken)*mp_pc)));\r\n\t// else's are only allowed in the true blocks of if-statements.\r\n\t// Bit 0 of m_if_status indicates the status of the last if.\r\n\tDbg_MsgAssert(m_if_status&1,(\"\\n%s\\nSpurious 'else'\",GetScriptInfo()));\r\n\t\r\n\t#ifdef STOPWATCH_STUFF\r\n\tpIfSkipStopWatch->Start();\r\n\t#endif\r\n\t\t\t\r\n\t// Skip over the code within the else, since the code before it must have executed.\r\n\tint in_nested_if=0;\r\n\twhile (in_nested_if || *mp_pc!=ESCRIPTTOKEN_KEYWORD_ENDIF)\r\n\t{\r\n\t\tDbg_MsgAssert(*mp_pc!=ESCRIPTTOKEN_KEYWORD_ENDSCRIPT,(\"endif keyword not found after else keyword.\"));\r\n\t\t\r\n\t\t// Keep track of nested ifs.\r\n\t\tif (*mp_pc==ESCRIPTTOKEN_KEYWORD_IF)\r\n\t\t{\r\n\t\t\t++in_nested_if;\r\n\t\t}\r\n\t\telse if (*mp_pc==ESCRIPTTOKEN_KEYWORD_ENDIF)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(in_nested_if,(\"Got endif within else part of if statement without corresponding nested if\"));\r\n\t\t\t--in_nested_if;\r\n\t\t}\t\r\n\t\t\r\n\t\tmp_pc=SkipToken(mp_pc);\r\n\t}    \r\n\t// We've hit the endif, so skip over it.\r\n\t++mp_pc;\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tm_if_status>>=1;\r\n\t#endif\r\n\t\r\n\t#ifdef STOPWATCH_STUFF\r\n\tpIfSkipStopWatch->Stop();\r\n\t#endif\r\n}\r\n\r\n// We can hit an endif either by finishing the 'true' block of an if-statement\r\n// that has no else, or by finishing the 'false' block following an else.\r\n// Either way there is nothing to do, so just skip over it.\r\nvoid CScript::execute_endif()\r\n{\r\n\tDbg_MsgAssert(mp_pc,(\"NULL mp_pc\"));\r\n\tDbg_MsgAssert(*mp_pc==ESCRIPTTOKEN_KEYWORD_ENDIF,(\"Unexpected *mp_pc='%s', expected keyword 'endif'\",GetTokenName((EScriptToken)*mp_pc)));\r\n\t\r\n\t#ifdef STOPWATCH_STUFF\r\n\tpIfSkipStopWatch->Start();\r\n\t#endif\r\n\t\r\n\t++mp_pc;\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tm_if_status>>=1;\r\n\t#endif\r\n\r\n\t#ifdef STOPWATCH_STUFF\r\n\tpIfSkipStopWatch->Stop();\r\n\t#endif\r\n}\t\t\r\n\r\n// Skips mp_pc forward till it finds an endswitch, skipping over any nested switch\r\n// statements in between.\r\n// Afterwards, mp_pc will point to the token following the endswitch.\r\nvoid CScript::skip_to_after_endswitch()\r\n{\r\n\tDbg_MsgAssert(mp_pc,(\"NULL mp_pc\"));\r\n\t\r\n\twhile (*mp_pc!=ESCRIPTTOKEN_KEYWORD_ENDSWITCH)\r\n\t{\r\n\t\tif (*mp_pc==ESCRIPTTOKEN_KEYWORD_SWITCH)\r\n\t\t{\r\n\t\t\t// Skip over the switch\r\n\t\t\t++mp_pc;\r\n\t\t\tskip_to_after_endswitch();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_pc=SkipToken(mp_pc);\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Skip over the endswitch\r\n\t++mp_pc;\r\n}\r\n\r\n// Given that mp_pc points to a switch token, this will skip mp_pc forward to the \r\n// code of the matching case. Or if none matches, it will point to after the endswitch.\r\nvoid CScript::execute_switch()\r\n{\r\n\tDbg_MsgAssert(mp_pc,(\"NULL mp_pc\"));\r\n\tDbg_MsgAssert(*mp_pc==ESCRIPTTOKEN_KEYWORD_SWITCH,(\"Unexpected *mp_pc='%s', expected keyword 'switch'\",GetTokenName((EScriptToken)*mp_pc)));\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\t// Remember the old pc value so that the printed line number is correct if \r\n\t// no endswitch is found before the end of file is hit.\r\n\tuint8 *start_of_switch_pc=mp_pc;\r\n\t#endif\r\n\r\n\t// Skip over the switch token\r\n\t++mp_pc;\r\n\t\r\n\t// Put the parameters following the switch keyword into mp_function_params\r\n\tDbg_MsgAssert(mp_function_params,(\"NULL mp_function_params\"));\r\n\tmp_function_params->Clear();\r\n\tmp_pc=AddComponentsUntilEndOfLine(mp_function_params,mp_pc,mp_params);\r\n\t\r\n\t// Get the first component and make a copy of it, putting it into p_comp.\r\n\t// Making a copy cos mp_function_params is needed later to hold the params following\r\n\t// each case statement that follows.\r\n\tCComponent *p_switch_comp=new CComponent;\r\n\tCComponent *p_first_comp=mp_function_params->GetNextComponent();\r\n\tif (p_first_comp)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_function_params->GetNextComponent(p_first_comp)==NULL,(\"\\n%s\\nswitch argument contains more than one component\",GetScriptInfo()));\r\n\t\tCopyComponent(p_switch_comp,p_first_comp);\r\n\t}\t\t\t\r\n\t\r\n\t// Skip forward till we hit a matching case, or a default, or endswitch\r\n\t// But, if we hit another switch statement whilst looking, \r\n\t// skip over it, ignoring its cases.\r\n\tbool found=false;\r\n\twhile (!found)\r\n\t{\r\n\t\tswitch (*mp_pc)\r\n\t\t{\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_SWITCH:\r\n\t\t{\r\n\t\t\t// Skip over the switch\r\n\t\t\t++mp_pc;\r\n\t\t\tskip_to_after_endswitch();\r\n\t\t\t// mp_pc now points to the token following the ESCRIPTTOKEN_KEYWORD_ENDSCRIPT\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_CASE:\r\n\t\t{\r\n\t\t\t++mp_pc;\r\n\t\t\t\r\n\t\t\tmp_function_params->Clear();\r\n\t\t\tmp_pc=AddComponentsUntilEndOfLine(mp_function_params,mp_pc,mp_params);\r\n\t\t\t\r\n\t\t\tCComponent *p_case_comp=mp_function_params->GetNextComponent();\r\n\t\t\tif (p_case_comp)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(mp_function_params->GetNextComponent(p_case_comp)==NULL,(\"\\n%s\\ncase argument contains more than one component\",GetScriptInfo()));\r\n\t\t\t\t\r\n\t\t\t\tif (*p_switch_comp==*p_case_comp)\r\n\t\t\t\t{\r\n\t\t\t\t\tfound=true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (found)\r\n\t\t\t{\r\n\t\t\t\t// We've found a match, but we need to skip over any case statements\r\n\t\t\t\t// that immediately follow. This is for when multiple cases want to\r\n\t\t\t\t// execute the same chunk of code.\r\n\t\t\t\twhile (true)\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_pc=SkipEndOfLines(mp_pc);\r\n\t\t\t\t\tif (*mp_pc==ESCRIPTTOKEN_KEYWORD_CASE)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t++mp_pc;\r\n\t\t\t\t\t\tmp_function_params->Clear();\r\n\t\t\t\t\t\tmp_pc=AddComponentsUntilEndOfLine(mp_function_params,mp_pc,mp_params);\r\n\t\t\t\t\t}\t\t\t\t\t\t\t\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_DEFAULT:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ENDSWITCH:\r\n\t\t\t++mp_pc;\r\n\t\t\tfound=true;\r\n\t\t\tbreak;\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ENDSCRIPT:\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tmp_pc=start_of_switch_pc;\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nMissing endswitch\",GetScriptInfo()));\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tmp_pc=SkipToken(mp_pc);\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\tCleanUpComponent(p_switch_comp);\r\n\tdelete p_switch_comp;\r\n}\r\n\r\nvoid CScript::execute_begin()\r\n{\r\n\tDbg_MsgAssert(mp_pc,(\"NULL mp_pc\"));\r\n\tDbg_MsgAssert(*mp_pc==ESCRIPTTOKEN_KEYWORD_BEGIN,(\"Unexpected *mp_pc='%s', expected keyword 'begin'\",GetTokenName((EScriptToken)*mp_pc)));\r\n\t++mp_pc;\r\n\t\r\n\t// First, check whether we're about to run out of space on the small statically allocated loop buffer.\r\n\tif (mp_current_loop==mp_loops_small_buffer+NESTED_BEGIN_REPEATS_SMALL_BUFFER_SIZE-1)\r\n\t{\r\n\t\t// There won't be enough room for the new loop!\r\n\r\n\t\t// A quick check, to ensure no memory leaks.\r\n\t\tDbg_MsgAssert(mp_loops==mp_loops_small_buffer,(\"Expected mp_loops==mp_loops_small_buffer, %x, %x\",mp_loops,mp_loops_small_buffer));\r\n\t\t\r\n\t\t// Dynamically allocate a bigger buffer, and change mp_loops to point to that instead\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\tmp_loops=(SLoop*)Mem::Malloc(MAX_NESTED_BEGIN_REPEATS * sizeof(SLoop));\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\t// Then copy over the contents of the small buffer, and update mp_current_loop to point into the new buffer.\r\n\t\tint i;\r\n\r\n\t\tfor (i=0; i<NESTED_BEGIN_REPEATS_SMALL_BUFFER_SIZE; ++i)\r\n\t\t{\r\n\t\t\tmp_loops[i]=mp_loops_small_buffer[i];\r\n\t\t}\r\n\t\tmp_current_loop=mp_loops+NESTED_BEGIN_REPEATS_SMALL_BUFFER_SIZE-1;\r\n\t\t\r\n\t\t// But now, we also have to scan through the call stack and update all the mpLoop pointers to\r\n\t\t// point into the new buffer.\r\n\t\tfor (i=0; i<m_num_return_addresses; ++i)\r\n\t\t{\r\n\t\t\tif (mp_return_addresses[i].mpLoop)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(mp_return_addresses[i].mpLoop >= mp_loops_small_buffer && mp_return_addresses[i].mpLoop < mp_loops_small_buffer+NESTED_BEGIN_REPEATS_SMALL_BUFFER_SIZE,(\"Bad mp_return_addresses[i].mpLoop\"));\r\n\t\t\t\t\r\n\t\t\t\tmp_return_addresses[i].mpLoop=(mp_return_addresses[i].mpLoop-mp_loops_small_buffer)+mp_loops;\r\n\t\t\t}\r\n\t\t}    \r\n\t}\r\n\t\r\n\tif (mp_current_loop)\r\n\t{            \r\n\t\tDbg_MsgAssert(mp_current_loop-mp_loops<MAX_NESTED_BEGIN_REPEATS-1,(\"\\n%s\\nToo many nested begin-repeats\",GetScriptInfo()));\r\n\t\t++mp_current_loop;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_current_loop=mp_loops;\r\n\t}\r\n\t\t\r\n\t// Initialise the new loop ... \r\n\t\r\n\t// Record the start for looping back.\r\n\tmp_current_loop->mpStart=mp_pc;\r\n\t// These get filled in once the repeat is reached.\r\n\tmp_current_loop->mpEnd=NULL;\r\n\tmp_current_loop->mGotCount=false;\r\n\tmp_current_loop->mNeedToReadCount=true;\r\n\tmp_current_loop->mCount=0;\r\n}\r\n\r\n\r\nvoid CScript::execute_repeat()\r\n{\r\n\tDbg_MsgAssert(mp_pc,(\"NULL mp_pc\"));\r\n\tDbg_MsgAssert(*mp_pc==ESCRIPTTOKEN_KEYWORD_REPEAT,(\"Unexpected *mp_pc='%s', expected keyword 'repeat'\",GetTokenName((EScriptToken)*mp_pc)));\r\n\tDbg_MsgAssert(mp_current_loop,(\"\\n%s\\nEncountered repeat with NULL mp_current_loop\",GetScriptInfo()));\r\n\t\r\n\tif (mp_current_loop->mNeedToReadCount)\r\n\t{\r\n\t\t// Skip over the repeat token. \r\n\t\t++mp_pc;\r\n\t\tDbg_MsgAssert(mp_function_params,(\"NULL mp_function_params\"));\r\n\t\tmp_function_params->Clear();\r\n\t\tmp_current_loop->mpEnd=AddComponentsUntilEndOfLine(mp_function_params,mp_pc,mp_params);\r\n\t\tmp_current_loop->mGotCount=mp_function_params->GetInteger(NO_NAME,&mp_current_loop->mCount);\r\n\t\tif (!mp_current_loop->mGotCount)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(mp_current_loop->mpEnd==mp_pc,(\"\\n%s\\nNo count value found following 'repeat'\",GetScriptInfo()));\r\n\t\t}\t\t\r\n\t\t\r\n\t\tmp_current_loop->mNeedToReadCount=false;\r\n\t}\t\r\n\t\t\r\n\tif (!mp_current_loop->mGotCount)\r\n\t{\r\n\t\t// It's an infinite loop.\r\n\t\tmp_pc=mp_current_loop->mpStart;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mp_current_loop->mCount,(\"\\n%s\\nZero count given to a begin-repeat loop\",GetScriptInfo()));\r\n\t\t--mp_current_loop->mCount;\r\n\t\tif (mp_current_loop->mCount)\r\n\t\t{\r\n\t\t\t// Finite loop, but it has not finished yet, so jump back to the start.\r\n\t\t\tmp_pc=mp_current_loop->mpStart;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// The loop has finished!\r\n\t\t\t\r\n\t\t\t// Jump PC to the next instruction after the repeat.\r\n\t\t\tDbg_MsgAssert(mp_current_loop->mpEnd,(\"NULL mp_current_loop->pEnd ??\")); \r\n\t\t\tmp_pc=mp_current_loop->mpEnd;\r\n\t\t\t\r\n\t\t\t// Rewind to the previous loop.\r\n\t\t\tif (mp_current_loop==mp_loops)\r\n\t\t\t{\r\n\t\t\t\tmp_current_loop=NULL;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t--mp_current_loop;\r\n\t\t\t\tDbg_MsgAssert(mp_current_loop>=mp_loops,(\"\\n%s\\nBad mp_current_loop\",GetScriptInfo()));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CScript::execute_break()\r\n{\r\n\tDbg_MsgAssert(mp_pc,(\"NULL mp_pc\"));\r\n\tDbg_MsgAssert(*mp_pc==ESCRIPTTOKEN_KEYWORD_BREAK,(\"Unexpected *mp_pc='%s', expected keyword 'break'\",GetTokenName((EScriptToken)*mp_pc)));\r\n\tDbg_MsgAssert(mp_current_loop,(\"\\n%s\\nEncountered break with NULL mp_current_loop\",GetScriptInfo()));\r\n\t\r\n\t// Step over every token until repeat is reached.\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tint nested_if_count=0;\r\n\t#endif\t\r\n\tint nested_loop_count=0;\r\n\tbool in_loop=true;\r\n\t// Skip mp_pc to the end of the loop.\r\n\twhile (in_loop)\r\n\t{\r\n\t\tswitch (*mp_pc)\r\n\t\t{\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_BEGIN:\r\n\t\t\t++nested_loop_count;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_REPEAT:\r\n\t\t\tif (nested_loop_count)\r\n\t\t\t{\r\n\t\t\t\t--nested_loop_count;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tin_loop=false;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_IF:\r\n\t\t\t++nested_if_count;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ENDIF:\r\n\t\t\tif (nested_if_count)\r\n\t\t\t{\r\n\t\t\t\t--nested_if_count;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Make sure that the stored if-status is rewound back to its\r\n\t\t\t\t// state before the loop was entered, otherwise the\r\n\t\t\t\t// 'too many nested ifs' assert will go off erroneously.\r\n\t\t\t\tm_if_status>>=1;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t#endif\r\n\t\t\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ENDSCRIPT:\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nRepeat keyword not found after break keyword.\",GetScriptInfo()));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tmp_pc=SkipToken(mp_pc);\r\n\t}    \r\n\t\r\n\t// Use AddComponentsUntilEndOfLine just to step over the possible repeat argument.\r\n\t// Ugh! Kind of ugly, but shouldn't be too slow because repeat will probably be followed\r\n\t// by nothing or just an integer.\r\n\tDbg_MsgAssert(mp_function_params,(\"NULL mp_function_params\"));\r\n\tmp_function_params->Clear();\r\n\tmp_pc=AddComponentsUntilEndOfLine(mp_function_params,mp_pc);\r\n\r\n\t\r\n\t// Rewind to the previous loop.\r\n\tif (mp_current_loop==mp_loops)\r\n\t{\r\n\t\tmp_current_loop=NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t--mp_current_loop;\r\n\t\tDbg_MsgAssert(mp_current_loop>=mp_loops,(\"\\n%s\\nBad mp_current_loop\",GetScriptInfo()));\r\n\t}\r\n}\r\n\r\n// Returns from a sub-script by popping the info (mp_pc etc) off the stack.\r\n// If there is nothing on the stack, it sets mp_pc to NULL\r\n// Returns true if the script being returned from was a script triggered by Interrupt.\r\n// This then allows Update() to not continue execution of the script that was interrupted.\r\nbool CScript::execute_return()\r\n{\r\n\t// The current script is finished with, so decrement its usage in the script cache.\r\n\tScript::CScriptCache *p_script_cache=Script::CScriptCache::Instance();\r\n\tDbg_MsgAssert(p_script_cache,(\"NULL p_script_cache\"));\r\n\tp_script_cache->DecrementScriptUsage(mScriptChecksum);\r\n\r\n\tbool was_interrupted=m_interrupted;\r\n\t\r\n\tif (m_num_return_addresses)\r\n\t{\r\n\t\t// This script was called from another, either by a regular call or by an interrupt.\r\n\t\t\r\n\t\t--m_num_return_addresses;\r\n\t\t\r\n\t\t// Delete the current mp_params, because it was created when this routine was called.\r\n\t\tDbg_MsgAssert(mp_params,(\"\\n%s\\nNULL p_params\",GetScriptInfo()));\r\n\t\tdelete mp_params;\r\n\t\t\r\n\t\t// Restore the info stored on the stack.\r\n\t\tSReturnAddress *p_info=mp_return_addresses+m_num_return_addresses;\r\n\t\t\r\n\t\tmScriptChecksum = p_info->mScriptNameChecksum;\r\n\t\tmp_params\t\t= p_info->mpParams;\r\n\t\tmp_pc\t\t\t= p_info->mpReturnAddress;\r\n\t\tmpObject\t\t= p_info->mpObject;\r\n\t\tmp_current_loop = p_info->mpLoop;\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tm_if_status\t\t= p_info->m_if_status;\r\n\t\t#endif\r\n\r\n\t\tm_wait_type\t\t= p_info->mWaitType;\r\n\t\tif (m_wait_type)\r\n\t\t{\r\n\t\t\tm_wait_timer\t= p_info->mWaitTimer;\r\n\t\t\tm_wait_period\t= p_info->mWaitPeriod;\r\n\t\t\tm_start_time\t= p_info->mStartTime;\r\n\t\t\tmp_wait_component = p_info->mpWaitComponent;\r\n\t\t}\t\r\n\t\t\r\n\t\tm_interrupted=p_info->mInterrupted;\r\n\t\t\r\n\t\t#ifdef __NOPT_ASSERT__ \r\n\t\tcheck_if_needs_to_be_watched_in_debugger();\r\n\t\t#endif\t\r\n\t\t\r\n\t\t// Check that the script being returned to does still exist, ie mp_pc is valid.\r\n\t\t// However, if we're running an embedded script, don't do the check, because the\r\n\t\t// script name may be the name of the embedded script rather than a global script.\r\n\t\tif (!mp_struct_script)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(LookUpSymbol(mScriptChecksum),(\"Non-existent script '%s' on call stack\",FindChecksumName(mScriptChecksum)));\r\n\t\t}\r\n\t\t\t\r\n\t\t// Actually, we need a better check to see if mp_pc is still valid, because the\r\n\t\t// script we're returning to might have got reloaded and hence moved in memory.\r\n\t\t// Should use a smart pointer.\r\n\t\t// But, doesn't seem to have caused any problems so far, so leave for the moment ...\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Nothing to return to, so stop the script by setting mp_pc to NULL.\r\n\t\t// This occurs when an endscript is hit.\r\n\t\tmp_pc=NULL;\r\n\t}\t\r\n\t\r\n\treturn was_interrupted;\r\n}\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n#ifndef __PLAT_WN32__\r\nvoid CScript::advance_pc_to_next_line_and_halt()\r\n{\r\n\tif (m_being_watched_in_debugger)\r\n\t{\r\n\t\tif (m_single_step_mode==STEP_OVER || \r\n\t\t\tm_single_step_mode==STEP_INTO)\r\n\t\t{\r\n\t\t\t// Record the current return address count so that it can be detected whether\r\n\t\t\t// the next command is a script call. Needed for stepping over script calls.\r\n\t\t\tm_last_num_return_addresses_when_halted=m_num_return_addresses;\r\n\t\t\t\r\n\t\t\tif (mp_pc)\r\n\t\t\t{\r\n\t\t\t\tmp_pc=SkipEndOfLines(mp_pc);\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tTransmitInfoToDebugger();\r\n\t\t\tm_last_instruction_time_taken=0.0f;\r\n\t\t\tDbg::CScriptDebugger::Instance()->ScriptDebuggerPause();\r\n\t\t}\r\n\t}\r\n}\t\t\t\r\n#endif\r\n#endif\r\n\r\n//static int sInstructionCount=0;\r\n//static uint64 sLastVBlanks=0;\r\n\r\n// Update the script, executing instructions\r\n// REQUIREMENT: is mp_pc is NULL, then return  ESCRIPTRETURNVAL_FINISHED, so the script is deleted by UpdateSpawnedScript\r\nEScriptReturnVal CScript::Update()\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tm_last_instruction_time_taken=0.0f;\t\r\n\tm_total_instruction_time_taken=0.0f;\r\n\tif (m_being_watched_in_debugger)\r\n\t{\r\n\t\tTransmitInfoToDebugger();\r\n\t}\t\r\n\t#endif\r\n\r\n\t#ifdef STOPWATCH_STUFF\r\n\tpUpdateStopWatch->Start();\r\n\t#endif\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tTmr::CPUCycles start_time = Tmr::GetTimeInCPUCycles();\r\n\t#endif\r\n\r\n\r\n\t//if (sLastVBlanks!=Tmr::GetVblanks())\r\n\t//{\r\n\t//\tsLastVBlanks=Tmr::GetVblanks();\r\n\t//\tprintf(\"Instruction count = %d\\n\",sInstructionCount);\r\n\t//\tsInstructionCount=0;\r\n\t//}\t\r\n\t\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\t\r\n\tObj::CObjectPtr p_obj = NULL;\r\n\tif (mpObject)\r\n\t{\r\n\t\tp_obj = mpObject;\t   \t\t\t// remember the object we locked\r\n//\t\tmpObject->SetLockAssertOn();\r\n\t}\r\n\t#endif\r\n\t\r\n\tm_skip_further_process_waits=false;\r\n\t\r\n\t// This loop is going to keep executing script commands until either mp_pc\r\n\t// becomes NULL somehow, or if some sort of wait command gets executed.\r\n    while (true)\r\n    {\r\n\t\tif (!mp_pc) \r\n\t\t{\r\n\t\t\t// Break out if mp_pc became NULL during the execution of the\r\n\t\t\t// last command. \r\n\t\t\t#ifdef STOPWATCH_STUFF\r\n\t\t\tpUpdateStopWatch->Stop();\r\n\t\t\t#endif\r\n\t\t\tsCurrentlyUpdating=NULL;\r\n\t#ifdef\t__NOPT_ASSERT__\t\r\n\t\r\n//\t\t\tif (mpObject)\r\n//\t\t\t{\r\n//\t\t\t\t// check the object we locked is the same one we are unlocking (or deleted)\r\n//\t\t\t\tDbg_MsgAssert(p_obj == mpObject,(\"\\n%s\\nFinished Script has changed objects to %p! Original Object %p Still Locked! Tell Mick\\n\",GetScriptInfo(),mpObject.Convert(),p_obj.Convert()));\r\n//\t\t\t\tmpObject->SetLockAssertOff();\r\n//\t\t\t}\r\n\t\t\t// If script is waiting, then we might be on a different object\r\n\t\t\t// if the original object still exists, then unlock it.\r\n\t\t\tif (p_obj)\r\n\t\t\t{\r\n\t\t\t\tp_obj->SetLockAssertOff();\r\n\t\t\t}\r\n\t#endif\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tstart_time = Tmr::GetTimeInCPUCycles() - start_time;\r\n\t\t\tm_last_time = (int)start_time;\t // experiment with uint etc....\r\n\t\t\tm_total_time += m_last_time;\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\t// Seems like a reasonable thing to do ...\r\n\t\t\tm_interrupted=false;\r\n\t\t\t\r\n\t\t\treturn ESCRIPTRETURNVAL_FINISHED;\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Make sure sCurrentlyUpdating is correct, because it may have\r\n\t\t\t// got changed during the execution of the last command.\r\n\t\t\tsCurrentlyUpdating=this;\r\n\t\t}\t\r\n\t\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tbool was_waiting_before;\r\n\t\tif (m_wait_type==WAIT_TYPE_NONE)\r\n\t\t{\r\n\t\t\twas_waiting_before=false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\twas_waiting_before=true;\r\n\t\t}\r\n\t\t#endif\r\n\t\t\r\n\t\tif (!m_skip_further_process_waits)\r\n\t\t{\r\n\t\t\tprocess_waits();\r\n\t\t}\t\r\n\r\n\t\t// Return straight away if waiting.\r\n\t\tif (m_wait_type!=WAIT_TYPE_NONE)\r\n\t\t{\r\n\t\t\t#ifdef STOPWATCH_STUFF\r\n\t\t\tpUpdateStopWatch->Stop();\r\n\t\t\t#endif\r\n\t\t\tsCurrentlyUpdating=NULL;\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\t\r\n\t\t\t// If script is waiting, then we might be on a different object\r\n\t\t\t// if the original object still exists, then unlock it.\r\n\t\t\tif (p_obj)\r\n\t\t\t{\r\n\t\t\t\tp_obj->SetLockAssertOff();\r\n\t\t\t}\r\n\t#endif\t \r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tstart_time = Tmr::GetTimeInCPUCycles() - start_time;\r\n\t\t\tm_last_time = (int)start_time;\t // experiment with uint etc....\r\n\t\t\tm_total_time += m_last_time;\r\n\t#endif\r\n\t   \t\r\n\t\t\t// If an interrupt script hits a blocking command, then clear the interrupted flag.\r\n\t\t\t// Reason:\r\n\t\t\t// If an interrupt script contains no blocking functions, then a single call to CScript::Update()\r\n\t\t\t// would execute the whole script, and as soon as the endscript was reached it was exit the Update()\r\n\t\t\t// function (due to the interrupt flag being on) hence returning control to the original Update()\r\n\t\t\t// function that was executing the interrupted script, and all would be well.\r\n\t\t\t\r\n\t\t\t// However, if the interrupt script did hit a blocking function, that would cause an early exit from\r\n\t\t\t// the Update() function, leaving it to the original Update() function, ie the one that was executing the\r\n\t\t\t// interrupted script, to finish completion of the interrupt script. In that case, we don't want\r\n\t\t\t// the interrupt flag to be on any more, because otherwise it would cause a premature exit from\r\n\t\t\t// the original Update() function as soon as the endscript was reached.\r\n\t\t\tm_interrupted=false;\r\n\t\r\n\t\t\t// Set this to prevent any previous CScript::Update() loop that the return may return to\r\n\t\t\t// from processing the waits further, otherwise if an interrupt script contains a wait n gameframes\r\n\t\t\t// it will end up waiting only n-1 gameframes, due to the interrupted scripts Update() loop calling\r\n\t\t\t// process_waits again.\r\n\t\t\tm_skip_further_process_waits=true;\r\n\t\t\t\r\n\t\t\tif (m_wait_type==WAIT_TYPE_BLOCKED)\r\n\t\t\t{\r\n\t\t\t\treturn ESCRIPTRETURNVAL_BLOCKED;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn ESCRIPTRETURNVAL_WAITING;\r\n\t\t\t}\r\n\t\t}\t\t\r\n\t\telse\r\n\t\t{\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tif (was_waiting_before)\r\n\t\t\t{\r\n\t\t\t\tadvance_pc_to_next_line_and_halt();\r\n\t\t\t}\t\r\n\t\t\t#endif\r\n\t\t}\t\t\r\n\r\n\t\t// Execute whatever is at mp_pc\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tTmr::CPUCycles instruction_start_time = Tmr::GetTimeInCPUCycles();\r\n\t\t#endif\r\n\t\t\r\n\t\tswitch (*mp_pc)\r\n\t\t{\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_IF:\r\n\t\t\t//++sInstructionCount;\r\n\t\t\t// This will execute the function call or expression following the if,\r\n\t\t\t// and if the command or expression returns false, it will skip\r\n\t\t\t// mp_pc forward to the token after the else or endif.\r\n\t\t\t// Otherwise, mp_pc will be left pointing to the first token of the 'true' block.\r\n\t\t\texecute_if();\r\n\t\t\t// Note: mp_pc may be NULL at this point\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ELSE:\r\n\t\t\t//++sInstructionCount;\r\n\t\t\t// The only time an else token should be hit is at the end of executing\r\n\t\t\t// the 'true' block following the if.\r\n\t\t\t// So this will just skip mp_pc over the 'false' block to after the endif.\r\n\t\t\texecute_else();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ENDIF:\r\n\t\t\t//++sInstructionCount;\r\n\t\t\t// We can hit an endif either by finishing the 'true' block of an if-statement\r\n\t\t\t// that has no else, or by finishing the 'false' block following an else.\r\n\t\t\t// Either way there is nothing to do, so just skip over it, but assert if we're\r\n\t\t\t// not in an if-statement to catch spurious else's.\r\n\t\t\texecute_endif();\r\n\t\t\tbreak;\r\n\r\n        case ESCRIPTTOKEN_KEYWORD_SWITCH:\r\n\t\t\t//++sInstructionCount;\r\n\t\t\t// Skips mp_pc forward to the token following the matching case. \r\n\t\t\t// Or if none matches, it will point to after the endswitch.\r\n\t\t\texecute_switch();\r\n\t\t\tbreak;\r\n\r\n        case ESCRIPTTOKEN_KEYWORD_CASE:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_DEFAULT:\r\n        case ESCRIPTTOKEN_KEYWORD_ENDSWITCH:\r\n\t\t\t//++sInstructionCount;\r\n\t\t\t// If we hit a case, default or endswitch, it must be due to the completion of the\r\n\t\t\t// previous case statement's commands.\r\n\t\t\t// So skip mp_pc forward so that it points to after the endswitch token.\r\n\t\t\tskip_to_after_endswitch();\r\n\t\t\tbreak;\r\n\t\t\t\r\n        case ESCRIPTTOKEN_KEYWORD_BEGIN:\r\n\t\t\t//++sInstructionCount;\r\n\t\t\t// Initialise a new loop counter\r\n\t\t\texecute_begin();\r\n            break;        \r\n\r\n        case ESCRIPTTOKEN_KEYWORD_REPEAT:\r\n\t\t\t//++sInstructionCount;\r\n\t\t\t// This will either jump mp_pc back to the start of the loop,\r\n\t\t\t// or skip it past the repeat if the loop has finished.\r\n\t\t\texecute_repeat();\r\n            break;\r\n\r\n        case ESCRIPTTOKEN_KEYWORD_BREAK:\r\n\t\t\t//++sInstructionCount;\r\n\t\t\t// This will skip mp_pc to after the repeat of the current loop\r\n\t\t\texecute_break();\r\n            break;\r\n\t\t    \r\n        case ESCRIPTTOKEN_KEYWORD_ENDSCRIPT:\r\n\t\t\t//++sInstructionCount;\r\n\t\t\tif (execute_return())\r\n\t\t\t{\r\n\t\t\t\t// If we returned from a script call caused by an interrupt, then do not continue\r\n\t\t\t\t// with execution of the interrupted script, since an interrupt should not affect the\r\n\t\t\t\t// interrupted script.\r\n\t\t\t\treturn ESCRIPTRETURNVAL_FINISHED_INTERRUPT;\r\n\t\t\t}\t\r\n\t\t\t// Note: mp_pc may be NULL at this point, if there is no calling script.\r\n            break;\r\n\t\t\t\r\n        case ESCRIPTTOKEN_KEYWORD_RETURN:\r\n\t\t\t//++sInstructionCount;\r\n\t\t\t\r\n\t\t\t// The return keyword works very similar to hitting the endscript token.\r\n\t\t\t// The difference is that 'return' will merge the parameters that follow the\r\n\t\t\t// return keyword onto the parameters of the calling script, if there is one.\r\n\t\t\t\r\n\t\t\t// Skip over the return token. \r\n\t\t\t++mp_pc;\r\n\t\t\t\r\n\t\t\t// Put any parameters that follow into mp_function_params\r\n\t\t\tDbg_MsgAssert(mp_function_params,(\"NULL mp_function_params\"));\r\n\t\t\tmp_function_params->Clear();\r\n\t\t\tmp_pc=AddComponentsUntilEndOfLine(mp_function_params,mp_pc,mp_params);\r\n\r\n\t\t\tif (execute_return())\r\n\t\t\t{\r\n\t\t\t\t// If we returned from a script call caused by an interrupt, then do not continue\r\n\t\t\t\t// with execution of the interrupted script, since an interrupt should not affect the\r\n\t\t\t\t// interrupted script.\r\n\t\t\t\t// For the same reason we are bailing out here before the returned parameters are merged onto\r\n\t\t\t\t// the interrupted scripts params, so that they will not be affected by the interrupt either.\r\n\t\t\t\treturn ESCRIPTRETURNVAL_FINISHED_INTERRUPT;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\t// Note: mp_pc may be NULL at this point, if there is no calling script.\r\n\r\n\t\t\t// Merge the return values onto the parameters of the calling script.\r\n\t\t\tDbg_MsgAssert(mp_params,(\"NULL mp_params ?\"));\r\n\t\t\tmp_params->AppendStructure(mp_function_params);\r\n\t\t\tbreak;\r\n\r\n        case ESCRIPTTOKEN_KEYWORD_RANDOM:\r\n        case ESCRIPTTOKEN_KEYWORD_RANDOM2:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_NO_REPEAT:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_PERMUTE:\r\n        case ESCRIPTTOKEN_JUMP:\r\n\t\t\t// Modify mp_pc according to any jump or random operators, and repeat until mp_pc no\r\n\t\t\t// longer points to a jump or random.\r\n\t\t\tmp_pc=DoAnyRandomsOrJumps(mp_pc);\r\n\t\t\tbreak;\r\n\r\n        case ESCRIPTTOKEN_ENDOFLINE:\r\n            ++mp_pc;\r\n            break;\r\n            \r\n\t    case ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\t\tmp_pc+=5; // 1 for the token, 4 for the line number.\r\n            break;\r\n\t\t\r\n        default:\r\n\t\t\t//++sInstructionCount;\r\n\t\t\t//printf(\"Running line %d in script '%s'\\n\",GetLineNumber(mp_pc),FindChecksumName(mScriptChecksum));\r\n\t\t\texecute_command();\r\n\t\t\t// Note: mp_pc may be NULL at this point\r\n            break;\r\n\t\t}\t\r\n\t\t\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\r\n\t\tif (m_being_watched_in_debugger)\r\n\t\t{\r\n\t\t\tTmr::CPUCycles t=Tmr::GetTimeInCPUCycles()-instruction_start_time;\r\n\t\t\tfloat last_instruction_time_taken=((float)((int)t))/150.0f;\r\n\t\t\t\r\n\t\t\tm_last_instruction_time_taken+=last_instruction_time_taken;\r\n\t\t\tm_total_instruction_time_taken+=last_instruction_time_taken;\r\n\t\t}\t\t\r\n\t\t\r\n\t\tif (m_single_step_mode==STEP_OVER &&\r\n\t\t\tm_num_return_addresses > m_last_num_return_addresses_when_halted)\r\n\t\t{\r\n\t\t\t// If the number of return addresses has increased beyond what it was when last halted\r\n\t\t\t// in the debugger, then the last command must have been a script call, so do not halt\r\n\t\t\t// but keep executing instructions until the script call has finished, which will be \r\n\t\t\t// indicated by the return address count returning to what it was or lower.\r\n\t\t\t// (It would be lower if say a goto occurred during the script call)\r\n\t\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (m_wait_type == WAIT_TYPE_NONE)\r\n\t\t\t{\r\n\t\t\t\tadvance_pc_to_next_line_and_halt();\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\t#endif\t\r\n    }\r\n}\r\n\r\nvoid CScript::Wait(int num_frames)\r\n{\r\n\tm_wait_type=WAIT_TYPE_COUNTER;\r\n    m_wait_timer=num_frames;\r\n}\r\n\r\nvoid CScript::WaitOnePerFrame(int num_frames)\r\n{\r\n\tm_wait_type=WAIT_TYPE_ONE_PER_FRAME;\r\n    m_wait_timer=num_frames;\t\t \t\t\r\n}\r\n\r\n\r\nvoid CScript::WaitTime(Tmr::Time period)\r\n{\r\n\tm_wait_type=WAIT_TYPE_TIMER;\r\n\tm_wait_period=period;\r\n\t// Record the start time.\r\n\tm_start_time=Tmr::GetTime();\r\n}\r\n\r\nbool CScript::RefersToScript(uint32 checksum)\r\n{\r\n\tif (mScriptChecksum==checksum) \r\n\t{\r\n\t\treturn true;\r\n\t}\t\r\n\t\r\n\tfor (int i=0; i<m_num_return_addresses; ++i)\r\n\t{\r\n\t\tif (mp_return_addresses[i].mScriptNameChecksum==checksum) \r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\treturn false;\r\n}\r\n\r\n// Checks that all the global scripts referred to by this script still exist.\r\n// Used by UnloadQB to stop any script which is missing one of its source scripts.\r\n// This is essential to stop the script from having an invalid program counter pointer.\t\t\t\t\t\t\t\t\t\t\t  \r\nbool CScript::AllScriptsInCallstackStillExist()\r\n{\r\n\tif (m_num_return_addresses==0)\r\n\t{\r\n\t\t// The call stack is empty, so we only have to consider the script being referred to\r\n\t\t// by mScriptChecksum.\r\n\t\tif (mp_struct_script)\r\n\t\t{\r\n\t\t\t// mScriptChecksum is not referring to a global script.\r\n\t\t\t// Rather, the script being run is a local script that was defined in a structure, a copy of which\r\n\t\t\t// is stored in mp_struct_script, so we know that still exists.\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// mScriptChecksum is referring to a global script, so check whether it still exists.\r\n\t\t\tif (LookUpSymbol(mScriptChecksum))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n\r\n\t// There are things in the call stack, so we know that mScriptChecksum (the name of the script\r\n\t// currently being executed) is referring to a global script, because local scripts cannot \r\n\t// call local scripts. So check whether the mScriptChecksum symbol still exists.\r\n\tif (!LookUpSymbol(mScriptChecksum)) \r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\t// Now we have to check that each of the scripts in the call stack still exist.\r\n\t// These must all be global scripts, apart perhaps from the one at index 0. If mp_struct_script is not NULL\r\n\t// then the script at index 0 will be a local script that was defined in a structure, not a global script.\r\n\t// In that case, its mScriptNameChecksum is not referring to a global script, so must not be checked for\r\n\t// existence. (The mScriptNameChecksum will instead be the original parameter name in the structure)\r\n\tint i=0;\r\n\tif (mp_struct_script)\r\n\t{\r\n\t\t// Start checking at index 1 instead, cos we know that the script at index 0 exists. It is contained\r\n\t\t// in mp_struct_script.\r\n\t\ti=1;\r\n\t}\t\r\n\tfor (; i<m_num_return_addresses; ++i)\r\n\t{\r\n\t\tif (!LookUpSymbol(mp_return_addresses[i].mScriptNameChecksum)) \r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\nbool CScript::RefersToObject(Obj::CObject *p_object)\r\n{\r\n\tif (mpObject==p_object) \r\n\t{\r\n\t\treturn true;\r\n\t}\t\r\n\t\r\n\tfor (int i=0; i<m_num_return_addresses; ++i)\r\n\t{\r\n\t\tif (mp_return_addresses[i].mpObject==p_object) \r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\treturn false;\r\n}\r\n\r\nvoid CScript::RemoveReferencesToObject(Obj::CObject *p_object)\r\n{\r\n\tif (mpObject==p_object) \r\n\t{\r\n\t\tmpObject=NULL;\r\n\t}\t\r\n\t\r\n\tfor (int i=0; i<m_num_return_addresses; ++i)\r\n\t{\r\n\t\tif (mp_return_addresses[i].mpObject==p_object) \r\n\t\t{\r\n\t\t\tmp_return_addresses[i].mpObject=NULL;\r\n\t\t}\r\n\t}\t\t\r\n}\r\n\r\n// Returns the base script that is running, not the name of any called scripts that it is currently executing.\r\nuint32 CScript::GetBaseScript()\r\n{\r\n\tif (m_num_return_addresses)\r\n\t{\r\n\t\t// If in a called script, the base script will be the first thing in the stack.\r\n\t\treturn mp_return_addresses[0].mScriptNameChecksum;\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Otherwise return the current script.\r\n\t\treturn mScriptChecksum;\r\n\t}\r\n}\r\n\t\t\r\nvoid SendScript( uint32 scriptChecksum, CStruct *p_params, Obj::CObject *p_object )\r\n{\r\n\t#ifdef __PLAT_WN32__\r\n\t// No GameNet stuff if compiling on PC\r\n\t#else\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tNet::Client* client;\r\n\tGameNet::MsgRunScript msg;\r\n\tint size, msg_size;\r\n\r\n\tif( gamenet_man->InNetGame())\r\n\t{\r\n\t\tNet::MsgDesc msg_desc;\r\n\t\tmsg.m_ScriptName = scriptChecksum;\r\n\t\tmsg.m_ObjID = -1;\r\n\t\tif( p_object )\r\n\t\t{\r\n\t\t\tmsg.m_ObjID = p_object->GetID();\r\n\t\t}\r\n\r\n\t\tsize = WriteToBuffer(p_params, (uint8 *) msg.m_Data, GameNet::MsgRunScript::vMAX_SCRIPT_PARAMS_LEN );\r\n\t\tDbg_MsgAssert( size <= GameNet::MsgRunScript::vMAX_SCRIPT_PARAMS_LEN,( \"Script too large to send over the net\\n\" ));\r\n\t\t\r\n\t\tclient = gamenet_man->GetClient( 0 );\r\n\t\tDbg_Assert( client );\r\n\r\n\t\tmsg_size = ( sizeof( GameNet::MsgRunScript ) - GameNet::MsgRunScript::vMAX_SCRIPT_PARAMS_LEN ) +\r\n\t\t\t\t\tsize;\r\n\t\tmsg_desc.m_Data = &msg;\r\n\t\tmsg_desc.m_Length = msg_size;\r\n\t\tmsg_desc.m_Id = GameNet::MSG_ID_RUN_SCRIPT;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\r\n\t}\r\n\t#endif\r\n}\r\n\r\n#ifdef __NOPT_ASSERT__\r\nstatic const char *sGetRunScriptName(uint32 scriptChecksum, const char *p_scriptName)\r\n{\r\n\tif (p_scriptName)\r\n\t{\r\n\t\treturn p_scriptName;\r\n\t}\r\n\treturn FindChecksumName(scriptChecksum);\r\n}\t\r\n#endif\r\n\r\n// Used for running a simple script from start to end.\r\nvoid RunScript(uint32 scriptChecksum, CStruct *p_params, Obj::CObject *p_object, bool netScript, const char *p_scriptName )\r\n{\r\n\t// First, see what type of symbol scriptChecksum is referring to.\r\n    CSymbolTableEntry *p_entry=Resolve(scriptChecksum);\r\n\tif (!p_entry)\r\n\t{\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tprintf(\"Warning! RunScript could not find '%s'\\n\",sGetRunScriptName(scriptChecksum,p_scriptName));\r\n\t\t#endif\r\n\t\treturn;\r\n\t}\t\r\n\tif (p_entry->mType!=ESYMBOLTYPE_QSCRIPT && \r\n\t\tp_entry->mType!=ESYMBOLTYPE_CFUNCTION &&\r\n\t\tp_entry->mType!=ESYMBOLTYPE_MEMBERFUNCTION)\r\n\t{\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tprintf(\"Warning! RunScript sent '%s' which is not a script, a c-function or a member function. Type=%s\\n\",sGetRunScriptName(scriptChecksum,p_scriptName),GetTypeName(p_entry->mType));\r\n\t\t#endif\r\n\t\treturn;\r\n\t}\r\n\r\n\r\n\tif( netScript )\r\n\t{\r\n\t\tSendScript( scriptChecksum, p_params, p_object );\r\n\t}\r\n\r\n\tswitch (p_entry->mType)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_CFUNCTION:\r\n\t\t{\r\n\t\t\t// If the symbol is actually a c-function rather than a script, then run the c-function.\r\n\t\t\t// This is handy sometimes because it saves having to write a special script just to run \r\n\t\t\t// one c-function.\r\n\t\t\tDbg_MsgAssert(p_entry->mpCFunction,(\"NULL pCFunction\"));\r\n\r\n\t\t\t// Mick:  We now pass in NULL, as creating a dummy script is very slow\t\t\t\r\n\t\t\t(*p_entry->mpCFunction)(p_params,NULL);\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase ESYMBOLTYPE_MEMBERFUNCTION:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(p_object,(\"Tried to run member function '%s' on NULL p_object\",Script::FindChecksumName(scriptChecksum)));\r\n\t\r\n\t\t\t// Mick:  We now pass in NULL, as creating a dummy script is very slow\t\t\t\r\n\t\t\tp_object->CallMemberFunction(scriptChecksum,p_params,NULL);\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase ESYMBOLTYPE_QSCRIPT:\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\t\tCScript *p_script=new CScript;\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tp_script->SetCommentString(\"Created by RunScript(...)\");\r\n\t\t\t#endif\r\n\t\t\tp_script->SetScript(scriptChecksum,p_params,p_object);\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\t\twhile (true)\r\n\t\t\t{\r\n\t\t\t\tEScriptReturnVal ret_val=p_script->Update();\r\n\t\t\t\tif (ret_val==ESCRIPTRETURNVAL_FINISHED)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t//Dbg_MsgAssert(0,(\"\\n%s\\nScript did not finish when run by RunScript.\",p_script->GetScriptInfo()));\r\n\t\t\t\t// Script must not get blocked, otherwise it'll hang in this loop forever.\r\n\t\t\t\tDbg_MsgAssert(ret_val!=ESCRIPTRETURNVAL_BLOCKED,(\"\\n%s\\nScript got blocked when being run by RunScript.\",p_script->GetScriptInfo()));\r\n\t\t\t\t// Note: OK if the script returns ESCRIPTRETURNVAL_WAITING, because the wait period will eventually end.\r\n\t\t\t\r\n\t\t\t}\r\n\t\t\tdelete p_script;\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\r\n}\r\n\r\nvoid RunScript(const char *p_scriptName, CStruct *p_params, Obj::CObject *p_object, bool netScript )\r\n{\r\n\t// Quite often, if a script cannot be found then FindChecksumName will not be able to find\r\n\t// the checksum name either, so since we know the name here it gets passed along to\r\n\t// the other version of RunScript so that the name can be printed in any warning message.\r\n\tRunScript(Crc::GenerateCRCFromString(p_scriptName), p_params, p_object, netScript, p_scriptName);\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////\r\n//\r\n// \t\t\t\t\tSpawning script stuff\r\n//\r\n/////////////////////////////////////////////////////////////////\r\n\r\nstatic bool s_updating_scripts = false;\r\nstatic bool s_delete_scripts_pending = false;\r\n\r\n// This gets called from within DeleteSymbols.\r\nvoid DeleteSpawnedScripts()\r\n{\r\n\t// Guard against deleting spawned scripts while we are updating them\r\n\tif( s_updating_scripts )\r\n\t{\r\n\t\ts_delete_scripts_pending = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tCScript *p_next=GetNextScript(p_script);\r\n\t\t// Don't kill the script if it is not session-specific.\r\n\t\t// This feature is currently used by one of Steve's net scripts which needs to not\r\n\t\t// be killed by ScriptCleanup\r\n\t\tif (p_script->mIsSpawned && !p_script->mNotSessionSpecific)\r\n\t\t{\r\n\t\t\tdelete p_script;\r\n\t\t}\t\r\n\t\tp_script=p_next;\r\n\t}\t\r\n}\r\n\r\n// This gets called from Front::PauseGame\r\nvoid PauseSpawnedScripts(bool status)\r\n{\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tif (p_script->mIsSpawned)\r\n\t\t{\r\n\t\t\tp_script->mPaused=status;\r\n\t\t}\r\n\t\tp_script=GetNextScript(p_script);\r\n\t}\t\r\n}\r\n\r\nvoid UnpauseSpawnedScript(CScript* p_script)\r\n{\r\n\tif (p_script && p_script->mIsSpawned)\r\n\t{\r\n\t\tp_script->mPaused=false;\r\n\t}\r\n}\r\n\r\n// Note: Does this need to be fast?\r\nuint32 NumSpawnedScriptsRunning()\r\n{\r\n\tuint32 num_spawned_scripts=0;\r\n\t\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tif (p_script->mIsSpawned)\r\n\t\t{\r\n\t\t\t++num_spawned_scripts;\r\n\t\t}\r\n\t\tp_script=GetNextScript(p_script);\r\n\t}\t\r\n\t\r\n\treturn num_spawned_scripts;\r\n}\r\n\r\n// Called once a frame. Currently called from Skate::DoUpdate()\r\nvoid UpdateSpawnedScripts()\r\n{\r\n\r\n\ts_updating_scripts = true;\r\n\ts_done_one_per_frame = false;\r\n\t\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tCScript *p_next;\r\n\t\t// get the next actual spawned script\r\n\t\tp_next=GetNextScript(p_script);\t\t\r\n\t\t// skip any non-spawned scripts\r\n\t\t// since they might get deleted in an unsafe manner\r\n\t\twhile (p_next && !p_next->mIsSpawned)\r\n\t\t{\r\n\t\t\tp_next=GetNextScript(p_next);\t\t\t\t\r\n\t\t}\r\n\t\t\r\n\t\tDbg_MsgAssert(GetNextScript(p_next) != (CScript*)-1,(\"Next script in spawned list has been deleted sometime earlier!\"));\r\n\t\tif (p_next == p_script)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"%s\\nLoop in list of spawned scripts!!\",p_script->GetScriptInfo()));\r\n\t\t}\r\n\t\t\r\n\t\t// K: Added the || !p_script->GotScript() so that spawned scripts which have been cleared still get\r\n\t\t// cleaned up when the game is paused. This was to fix a bug (TT1453) where cleared scripts where accumulating\r\n\t\t// during the cutscenes. The scripts were the scripts of goal peds, which got cleared when the peds were\r\n\t\t// killed. \r\n\t\tif (p_script->mIsSpawned && (!p_script->mPaused || !p_script->GotScript()) && (!p_script->mPauseWithObject || !p_script->mpObject || p_script->mpObject->ShouldUpdatePauseWithObjectScripts()))\r\n\t\t{\r\n\t\t\tif (p_script->Update()==ESCRIPTRETURNVAL_FINISHED)\r\n\t\t\t{\r\n\t\t\t\t// just doing the assertion before we delete the script  \r\n\t\t\t\tDbg_MsgAssert(GetNextScript(p_next) != (CScript*)-1,(\"%s\\nNext script in spawned list has been deleted by this script updating\",p_script->GetScriptInfo()));\r\n\t\t\t\t// If it had a callback script specified, run it.\r\n\t\t\t\tif (p_script->mCallbackScript)\r\n\t\t\t\t{\r\n\t\t\t\t\tRunScript(p_script->mCallbackScript,\r\n\t\t\t\t\t\t\t  p_script->mpCallbackScriptParams,\r\n\t\t\t\t\t\t\t  p_script->mpObject);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// just doing the assertion before we delete the script  \r\n\t\t\t\tDbg_MsgAssert(GetNextScript(p_next) != (CScript*)-1,\r\n\t\t\t\t(\"Next script in spawned list has been deleted by callback script (%s)\",FindChecksumName(p_script->mCallbackScript)));\r\n\t\t\t\t// Kill it now that it has finished.\r\n\t\t\t\tdelete p_script;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(GetNextScript(p_next) != (CScript*)-1,(\"%s\\nNext script in spawned list has been deleted by this script\",p_script->GetScriptInfo()));\r\n\t\t\t}\r\n\t\t}\t\r\n\t\t\t\r\n\t\tp_script=p_next;\r\n\t\tDbg_MsgAssert(GetNextScript(p_script) != (CScript*)-1,(\"Next script in spawned list has been deleted by this script\"));\r\n\t}\t\r\n\r\n\r\n\ts_updating_scripts = false;\r\n\tif( s_delete_scripts_pending )\r\n\t{\r\n\t\tDeleteSpawnedScripts();\r\n\t\ts_delete_scripts_pending = false;\r\n\t}\r\n\r\n\r\n}\r\n\r\n// Sned spawn script events to other clients\r\nvoid SendSpawnScript( uint32 scriptChecksum, Obj::CObject *p_object, int node, bool permanent )\r\n{\r\n\t#ifdef __PLAT_WN32__\r\n\t// No GameNet stuff if compiling on PC\r\n\t#else\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tNet::Client* client;\r\n\tGameNet::MsgSpawnAndRunScript msg;\r\n    \r\n\tif( gamenet_man->InNetGame())\r\n\t{\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tmsg.m_ScriptName = scriptChecksum;\r\n\t\tmsg.m_ObjID = -1;\r\n\t\tmsg.m_Node = node;\r\n\t\tmsg.m_Permanent = (char) permanent;\r\n\t\tif( p_object )\r\n\t\t{\r\n\t\t\tmsg.m_ObjID = p_object->GetID();\r\n\t\t}\r\n\r\n\t\tclient = gamenet_man->GetClient( 0 );\r\n\t\tDbg_Assert( client );\r\n\r\n\t\tmsg_desc.m_Data = &msg;\r\n\t\tmsg_desc.m_Length = sizeof( GameNet::MsgSpawnAndRunScript );\r\n\t\tmsg_desc.m_Id = GameNet::MSG_ID_SPAWN_AND_RUN_SCRIPT;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t}\r\n\t#endif\r\n}\r\n\r\n\r\nCScript *GetScriptWithUniqueId(uint32 id)\r\n{\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tif (p_script->GetUniqueId() == id) \r\n\t\t\treturn p_script;\r\n\t\tp_script = GetNextScript(p_script);\r\n\t}\t\r\n\r\n\treturn NULL;\r\n}\r\n\r\n// Called from ScriptSpawnScript in cfuncs.cpp\r\n// also called by the triggering code in skater.cpp\r\n// returns the new script if sucessful, asserts if not\r\n// optional \"node\" parameter is the node number that is\r\n// responsible for spawning this script.\r\n// Also now takes an optional Id, to allow individual spawned script instances to be killed.\r\nCScript* SpawnScript(uint32 scriptChecksum, CStruct *p_scriptParams, uint32 callbackScript, CStruct *p_callbackParams, int node, uint32 id,\r\n\t\t\t\t\t bool netEnabled, bool permanent, bool not_session_specific, bool pause_with_object )\r\n{\r\n\tDbg_MsgAssert(scriptChecksum,(\"Zero checksum sent to SpawnScript\"));\r\n\t\r\n    CSymbolTableEntry *p_entry=Resolve(scriptChecksum);\r\n    if (p_entry)\r\n    {\r\n        if (p_entry->mType==ESYMBOLTYPE_CFUNCTION)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(callbackScript==0,(\"A callbackScript cannot currently be specified when running SpawnScript on a c-function. (cfunc='%s' callback='%s')\",FindChecksumName(scriptChecksum),FindChecksumName(callbackScript)));\r\n\t\t\t\r\n\t\t\t// Creating a dummy script to send to the c-function. Normally the c-function would\r\n\t\t\t// only be called from within a script's update function, and it uses the passed script \r\n\t\t\t// pointer in any call to GetScriptInfo if an assert goes off. \r\n\t\t\t// So we need to pass a dummy rather than NULL so that it does not crash if it\r\n\t\t\t// dereferences the pointer.\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\t\tCScript *p_dummy=new CScript;\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\r\n\t\t\t(*p_entry->mpCFunction)(p_scriptParams,p_dummy);\r\n\t\t\t\r\n\t\t\tdelete p_dummy;\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t\tDbg_MsgAssert(p_entry->mType!=ESYMBOLTYPE_MEMBERFUNCTION,(\"SpawnScript cannot run the member function '%s'\",FindChecksumName(scriptChecksum)));\r\n\t}\t\r\n\t\r\n\t\r\n\tCScript *p_script=new CScript;\r\n\tp_script->SetScript(scriptChecksum, p_scriptParams, NULL);\r\n\t#ifdef __NOPT_ASSERT__\r\n\tp_script->SetCommentString(\"Created by SpawnScript\");\r\n\t#endif\r\n\t\r\n\t\r\n\tp_script->mNode = node;\r\n\tp_script->mIsSpawned = true;\r\n\tp_script->mId = id;\r\n\tp_script->mPaused = false;\r\n\tp_script->mNotSessionSpecific=not_session_specific;\r\n\tp_script->mPauseWithObject = pause_with_object;\r\n\t\r\n\tDbg_MsgAssert(p_script->mpCallbackScriptParams==NULL,(\"p_script->mpCallbackScriptParams not NULL ?\"));\r\n\tif (callbackScript)\r\n\t{\r\n\t\tp_script->mCallbackScript=callbackScript;\r\n\t\tp_script->mpCallbackScriptParams=new CStruct;\r\n\t\tif (p_callbackParams)\r\n\t\t{\r\n\t\t\t*p_script->mpCallbackScriptParams+=*p_callbackParams;\r\n\t\t}\t\r\n\t}\r\n\t\t\r\n\t#ifdef __PLAT_WN32__\r\n\t// No GameNet stuff if compiling on PC\r\n\t#else\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tif( netEnabled && gamenet_man->InNetGame())\r\n\t{\r\n\t\t// TODO: Should pass on the not_session_specific flag ...\r\n\t\tSendSpawnScript( scriptChecksum, NULL, node, permanent );\r\n\t}\r\n\t#endif\r\n\r\n\treturn p_script;\r\n}\r\n\r\n\r\nbool\tScriptExists(uint32 scriptNameChecksum)\r\n{\r\n\tCSymbolTableEntry *p_entry=Resolve(scriptNameChecksum);\r\n\tif (p_entry && p_entry->mType==ESYMBOLTYPE_QSCRIPT)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nCScript* SpawnScript(const char *p_scriptName, CStruct *p_scriptParams, uint32 callbackScript, CStruct *p_callbackParams, int node, uint32 id, \r\n\t\t\t\t\t bool netEnabled, bool permanent, bool not_session_specific, bool pause_with_object )\r\n{\r\n    \r\n\treturn SpawnScript(Crc::GenerateCRCFromString(p_scriptName),p_scriptParams,callbackScript,p_callbackParams,node,id, netEnabled, permanent, not_session_specific, pause_with_object);\r\n}\r\n\r\n// Kills a spawned script, given a pointer to the actual script\r\nvoid KillSpawnedScript(CScript *p_script)\r\n{\r\n    if (p_script && p_script->mIsSpawned)\r\n\t{\r\n\t\tdelete p_script;\r\n\t}\t\r\n}\r\n\r\n\r\n// Kills all spawned scripts that are either currently running this script directly,\r\n// or have it in their call stack somewhere. (Ie, they will return to it later)\r\nvoid KillSpawnedScriptsThatReferTo(uint32 checksum)\r\n{\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tCScript *p_next=GetNextScript(p_script);\r\n\t\tif (p_script->mIsSpawned && p_script->RefersToScript(checksum))\r\n\t\t{\r\n//\t\t\tdelete p_script;\r\n\t\t\tp_script->ClearScript();\r\n\t\t\tp_script->ClearEventHandlerTable();\r\n\t\t}\t\r\n\t\tp_script=p_next;\r\n\t}\t\r\n}\r\n\r\n// Kills all scripts with this particular Id.\r\nvoid KillSpawnedScriptsWithId(uint32 id)\r\n{\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tCScript *p_next=GetNextScript(p_script);\r\n\t\tif (p_script->mIsSpawned && (p_script->mId==id || p_script->GetUniqueId()==id))\r\n\t\t{\r\n// Mick, instead of deleteing the script, we now just clear it\r\n// this stops it from executing, but leaves it in the linked list\r\n// so it can be cleaned up next time around \"UpdateSpawnedScripts\"\r\n// Scripts that have ClearScript() called will automatically be deleted\r\n// as they have mp_pc set to NULL\r\n//\t\t\tdelete p_script;\r\n\t\t\tp_script->ClearScript();\r\n\t\t\tp_script->ClearEventHandlerTable();\r\n\t\t}\t\r\n\t\tp_script=p_next;\r\n\t}\t\r\n}\r\n\r\n// Kills all spawned scripts that have the passed object as their parent object.\r\n// This gets called from within Script::KillAllScriptsWithObject.\r\nvoid KillSpawnedScriptsWithObject(Obj::CObject *p_object)\r\n{\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tCScript *p_next=GetNextScript(p_script);\r\n\t\tif (p_script->mIsSpawned && p_script->RefersToObject(p_object))\r\n\t\t{\r\n//\t\t\tdelete p_script;\r\n\t\t\tp_script->ClearScript();\r\n\t\t\tp_script->ClearEventHandlerTable();\r\n\t\t}\t\r\n\t\tp_script=p_next;\r\n\t}\t\r\n}\r\n\r\n// Kills all spawned scripts with a particular Id & parent object.\r\n// Called by Matt's Obj_KillSpawnedScript CObject script member function.\r\nvoid KillSpawnedScriptsWithObjectAndId(Obj::CObject *p_object, uint32 id, CScript *p_callingScript)\r\n{\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tCScript *p_next=GetNextScript(p_script);\r\n\t\tif (p_script->mIsSpawned && \r\n\t\t\tp_script!=p_callingScript &&\r\n\t\t\tp_script->RefersToObject(p_object) &&\r\n\t\t\tp_script->mId==id)\r\n\t\t{\r\n//\t\t\tdelete p_script;\r\n\t\t\tp_script->ClearScript();\r\n\t\t\tp_script->ClearEventHandlerTable();\r\n\t\t}\t\r\n\t\tp_script=p_next;\r\n\t}\t\r\n}\r\n\r\n// Kills all spawned scripts with a particular Id & parent object.\r\n// Called by Matt's Obj_KillSpawnedScript CObject script member function.\r\nvoid KillSpawnedScriptsWithObjectAndName(Obj::CObject *p_object, uint32 name, CScript *p_callingScript )\r\n{\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tCScript *p_next=GetNextScript(p_script);\r\n\t\tif (p_script->mIsSpawned && \r\n\t\t\tp_script!=p_callingScript &&\r\n\t\t\tp_script->RefersToObject(p_object) &&\r\n\t\t\tp_script->mScriptChecksum==name)\r\n\t\t{\r\n//\t\t\tdelete p_script;\r\n\t\t\tp_script->ClearScript();\r\n\t\t\tp_script->ClearEventHandlerTable();\r\n\t\t}\t\r\n\t\tp_script=p_next;\r\n\t}\t\r\n}\r\n\r\n// Returns: 0 if spawned script has no ID, or if the script isn't a spawned script\r\n// Otherwise, returns the ID:\r\nuint32 FindSpawnedScriptID(CScript *p_script)\r\n{\r\n\tif (!p_script)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\t\r\n\tif (!p_script->mIsSpawned)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\r\n\treturn p_script->mId;\t\t\r\n}\r\n\r\nCScript* FindSpawnedScriptWithID(uint32 id)\r\n{\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tCScript *p_next=GetNextScript(p_script);\r\n\t\tif (p_script->mIsSpawned && \r\n\t\t\tp_script->mId==id)\r\n\t\t{\r\n\t\t\treturn p_script;\r\n\t\t}\t\r\n\t\tp_script=p_next;\r\n\t}\r\n\t\r\n\treturn NULL;\r\n}\r\n\r\n\r\n// TODO: This just included to allow compilation of GenerateCRC, remove later.\r\nuint32 GenerateCRC(const char *p_string)\r\n{\r\n\treturn Crc::GenerateCRCFromString(p_string);\r\n}\r\n\r\n// Stops all scripts.\r\n// Currently only used by the StopAllScripts script function, which currently isn't used\r\n// anywhere, but might be handy one day.\r\nvoid StopAllScripts()\r\n{\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tp_script->ClearScript();\r\n\t\tp_script->ClearEventHandlerTable();\r\n\t\tp_script=GetNextScript(p_script);\r\n\t}\t\r\n}\r\n\r\n// Stops all scripts with a particular object as their parent, but does not delete them.\r\n// They cannot be restarted after being stopped.\r\n// This is basically a way of killing the scripts without actually\r\n// deleting them, so it won't cause any invalid script pointers.\r\n// Currently gets called at the end of the CObject destructor.\r\nvoid StopAllScriptsUsingThisObject(Obj::CObject *p_object)\r\n{\r\n\tStopScriptsUsingThisObject(p_object, 0);\r\n}\r\n\r\n// If scriptCrc != 0, then only stop scripts with that ID, otherwise stop all scripts using object\r\nvoid StopScriptsUsingThisObject(Obj::CObject *p_object, uint32 scriptCrc)\r\n{\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tif (p_script->RefersToObject(p_object) && (!scriptCrc || p_script->mScriptChecksum == scriptCrc))\r\n\t\t{\r\n\t\t\tp_script->ClearScript();\r\n\t\t\tp_script->ClearEventHandlerTable();\r\n\t\t}\t\r\n\t\tp_script=GetNextScript(p_script);\r\n\t}\t\r\n}\r\n\r\n// TODO: brad - this is a last minute fix to StopScriptsUsingThisObject.\r\n// Rather than fixing the existing function so close to release, I've added\r\n// this version to be called only when we know we want to use it.\r\nvoid StopScriptsUsingThisObject_Proper(Obj::CObject *p_object, uint32 scriptCrc)\r\n{\r\n\tCScript *p_script=GetNextScript();\r\n\twhile ( p_script )\r\n\t{\r\n\t\tif ( p_script->RefersToObject( p_object ) && ( !scriptCrc || p_script->RefersToScript( scriptCrc ) ) )\r\n\t\t{\r\n\t\t\tp_script->ClearScript();\r\n\t\t\tp_script->ClearEventHandlerTable();\r\n\t\t}\t\r\n\t\tp_script=GetNextScript( p_script );\r\n\t}\t\r\n}\r\n\r\n\r\n// Kills any stopped scripts, ie scripts with their mpPC null. These\r\n// would be scripts stopped by the above StopAllScriptsUsingThisObject\r\nvoid KillStoppedScripts()\r\n{\r\n\tCScript *p_script=GetNextScript();\r\n\twhile (p_script)\r\n\t{\r\n\t\tCScript *p_next=GetNextScript(p_script);\r\n\t\t\r\n\t\t// Delete the script if it has stopped (mpPC==NULL), but not if it is a spawned script,\r\n\t\t// because otherwise it will leave a dangling pointer in the array of spawned scripts,\r\n\t\t// which will then get dereferenced in UpdateSpawnedScripts and crash.\r\n\t\t// If the script has stopped, the next call to UpdateSpawnedScripts will delete it, so\r\n\t\t// the script is guaranteed to get cleaned up eventually.\r\n\t\t\r\n\t\t#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\t\tif (!p_script->GotScript() && !p_script->mIsSpawned && !p_script->GetEventHandlerTable())\r\n\t\t#else\r\n\t\tif (!p_script->GotScript() && !p_script->mIsSpawned)\r\n\t\t#endif\r\n\t\t{\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tprintf(\"Cleaning up script '%s'\\n\",FindChecksumName(p_script->mScriptChecksum));\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tdelete p_script;\r\n\t\t}\t\r\n\t\t\r\n\t\tp_script=p_next;\r\n\t}\t\r\n}\r\n\r\n// Run by the DumpScripts script function.\r\n// Prints out the names of all the currently existing scripts.\r\nvoid DumpScripts()\r\n{\r\n\t#ifdef __NOPT_ASSERT__\r\n\tprintf(\"###########################################################\\n\\n\");\r\n\tprintf(\"All the CScripts that currently exist ...\\n\\n\");\r\n\t\r\n\tCScript *p_scr=GetNextScript();\r\n\tint n = 0;\r\n\twhile (p_scr)\r\n\t{\r\n\t\tprintf (\"%3d %8d \",p_scr->m_last_time/150, p_scr->m_total_time/150);\r\n\t\tp_scr->m_last_time = 0;\r\n\t\tp_scr->m_total_time = 0;\t\r\n\t\t\t\t\t  \r\n\t\tprintf (\"%3d: \",n++);\r\n\t\tif (p_scr->mIsSpawned)\r\n\t\t{\r\n\t\t\tprintf(\"S \");\r\n\t\t}\t\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tprintf(\"  \");\r\n\t\t}\r\n\r\n\t\tswitch (p_scr->GetWaitType())\r\n\t\t{\r\n\t\tcase WAIT_TYPE_NONE:\r\n\t\t\tprintf(\"None            \");\r\n\t\t\tbreak;\r\n\t\tcase WAIT_TYPE_COUNTER:\r\n\t\t\tprintf(\"Counter         \");\r\n\t\t\tbreak;\r\n\t\tcase WAIT_TYPE_ONE_PER_FRAME:\r\n\t\t\tprintf(\"one_per_frame   \");\r\n\t\t\tbreak;\r\n\t\tcase WAIT_TYPE_TIMER:\r\n\t\t\tprintf(\"Timer           \");\r\n\t\t\tbreak;\r\n\t\tcase WAIT_TYPE_BLOCKED:\r\n\t\t\tprintf(\"Blocked         \");\r\n\t\t\tbreak;\r\n\t\tcase WAIT_TYPE_OBJECT_MOVE:\r\n\t\t\tprintf(\"Ob Move         \");\r\n\t\t\tbreak;\r\n\t\tcase WAIT_TYPE_OBJECT_ANIM_FINISHED:\r\n\t\t\tprintf(\"Ob AnimFinished \");\r\n\t\t\tbreak;\r\n\t\tcase WAIT_TYPE_OBJECT_JUMP_FINISHED:\r\n\t\t\tprintf(\"Ob JumpFinished \");\r\n\t\t\tbreak;\r\n\t\tcase WAIT_TYPE_OBJECT_ROTATE:\r\n\t\t\tprintf(\"Ob Rotate       \");\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tprintf(\"Unknown ??????  \");\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\r\n\t\tif (p_scr->Finished())\r\n\t\t{\r\n\t\t\tprintf(\"[Fin] \");\r\n\t\t}\r\n\t\t\t\r\n\t\tuint32 checksum=p_scr->GetBaseScript();\r\n\t\tif (checksum)\r\n\t\t{\r\n\t\t\tCSymbolTableEntry *p_sym=LookUpSymbol(checksum);\r\n\t\t\tDbg_MsgAssert(p_sym,(\"NULL pSym ??\"));\r\n\t\r\n//\t\t\tprintf(\"%s: %s\\n\",FindChecksumName(p_sym->mSourceFileNameChecksum),FindChecksumName(checksum));\r\n\t\t\tprintf(\"%s\\n\",FindChecksumName(checksum));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tprintf (\", Checksum is NULL, probably dead script\\n\");\r\n\t\t}\r\n\t\t\r\n\t\tp_scr=GetNextScript(p_scr);\r\n\t}\t\r\n\tprintf(\"\\n\");\r\n\t#endif\r\n}\r\n\r\n\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\r\n/*\r\n\tSets up the table that specifies which scripts to run in response to which events.\r\n\t\r\n\tSee object scripting document.\r\n*/\r\nvoid CScript::SetEventHandlers(Script::CArray *pArray, EReplaceEventHandlers replace)\r\n{\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\tif (!mp_event_handler_table)\r\n\t{\r\n\t\tmp_event_handler_table = new Obj::CEventHandlerTable();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_event_handler_table->unregister_all(this);\t\r\n\t}\r\n\tmp_event_handler_table->add_from_script(pArray, replace);\r\n\t\r\n\t// Mick:  We still need the compress_table for this way of adding event handlers\r\n\t// as the \"replace\" logic otherwise leads to a rapidly growing table.\r\n\t// especially on the on-screen keyboard\r\n\tmp_event_handler_table->compress_table();\r\n\t\r\n\tmp_event_handler_table->register_all(this);\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n}\r\n\r\n\r\nvoid\tCScript::SetEventHandler(uint32 ex, uint32 scr, uint32 group, bool exception, CStruct *p_params)\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\r\n\t// Need to create the table if not there\t\r\n\tif (!mp_event_handler_table)\r\n\t{\r\n\t\tmp_event_handler_table = new Obj::CEventHandlerTable();\r\n\t}\r\n\t\r\n\t// Add the event to the table\r\n\tmp_event_handler_table->AddEvent(ex,scr,group, exception, p_params); \t\r\n\r\n\t// Inregistering the event receiver, all we are doing is adding an\r\n\t// script pointer to the list of scripts that handle this \r\n\t// type of exception\r\n\t// there is nothing specific to the actual handler\r\n\t// if the script is already in the list, then nothing needs changing. \r\n\tObj::CTracker::Instance()->RegisterEventReceiver(ex, this); \r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n\r\n\r\n/*\r\n\tRemoves an entry in the event table with the given type id\r\n*/\r\nvoid CScript::RemoveEventHandler(uint32 type)\r\n{\r\n\tif (!mp_event_handler_table) return;\r\n\tmp_event_handler_table->remove_entry(type);\r\n//\tmp_event_handler_table->compress_table();\r\n\r\n// Refresh the Obj::Tracker\r\n\r\n\tObj::CTracker::Instance()->UnregisterEventReceiver(type, this); \r\n\t\t\r\n}\r\n\r\n\r\n\r\n/*\r\n\tRemoves all entries in the event table with the given group id\r\n*/\r\nvoid CScript::RemoveEventHandlerGroup(uint32 group)\r\n{\r\n\tif (!mp_event_handler_table) return;\r\n\t\r\n\tmp_event_handler_table->unregister_all(this);\t\r\n\t\r\n\tmp_event_handler_table->remove_group(group);\r\n//\tmp_event_handler_table->compress_table();\r\n\t\r\n\tmp_event_handler_table->register_all(this);\t\r\n\r\n}\r\n\r\n/*\r\n\tDumps the event table\r\n*/\r\nvoid CScript::PrintEventHandlerTable (   )\r\n{\r\n\tObj::CEventHandlerTable::sPrintTable(mp_event_handler_table);\r\n}\r\n\r\nbool CScript::PassTargetedEvent(Obj::CEvent *pEvent, bool broadcast)\r\n{\r\n\tif (mp_event_handler_table)\r\n\t\tmp_event_handler_table->pass_event(pEvent, this, broadcast);\r\n\treturn true;\r\n}\r\n\r\nvoid \tCScript::SetOnExceptionScriptChecksum(uint32 OnExceptionScriptChecksum) \r\n{\r\n\tmOnExceptionScriptChecksum = OnExceptionScriptChecksum;\r\n}\r\n\r\nuint32 \tCScript::GetOnExceptionScriptChecksum() const \r\n{\r\n\treturn mOnExceptionScriptChecksum;\r\n}\r\n\r\nvoid \tCScript::SetOnExitScriptChecksum(uint32 OnExitScriptChecksum) \r\n{\r\n\tmOnExitScriptChecksum = OnExitScriptChecksum;\r\n}\r\n\r\nuint32 \tCScript::GetOnExitScriptChecksum() const \r\n{\r\n\treturn mOnExitScriptChecksum;\r\n}\r\n\r\n\r\n\r\n#endif\r\n\r\n} // namespace Script\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/script.h",
    "content": "#ifndef\t__SCRIPTING_SCRIPT_H\r\n#define\t__SCRIPTING_SCRIPT_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef\t__SCRIPTING_SCRIPTDEFS_H\r\n// TODO: Remove this at some point, only necessary for the CScriptStructure define, to make everything compile.\r\n#include <gel/scripting/scriptdefs.h>\r\n#endif\r\n\r\n#ifndef __SYS_TIMER_H\r\n#include <sys/timer.h> // For Tmr::Time\r\n#endif\r\n\r\n#ifndef __SYS_MEM_POOLABLE_H\r\n#include <sys/mem/poolable.h>\r\n#endif\r\n\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n\r\n\r\n#include <gel/RefCounted.h>\r\n\r\n\r\nnamespace Obj\r\n{\r\n\tclass CBaseComponent;\r\n\tclass CEvent;\r\n\tclass CEventHandlerTable;\r\n}\r\n\t\r\nnamespace Script\r\n{\r\n\r\n// TODO: Remove this at some point, only necessary to make the other game-code headers compile without having\r\n// go through them all including vecpair.h\r\n// Currently they assume everything is declared in script.h\r\nclass CPair;\r\n\r\nclass CStruct;\r\nclass CSymbolTableEntry;\r\nstruct SStructScript;\r\n\r\n// The maximum level of Begin-Repeat nesting.\r\n#define MAX_NESTED_BEGIN_REPEATS 10\r\n#define NESTED_BEGIN_REPEATS_SMALL_BUFFER_SIZE 1\r\n\r\n// The maximum number of nested calls to other scripts.                              \r\n#define MAX_RETURN_ADDRESSES 16\r\n// The number of SReturnAddress structures in the small buffer in each CScript\r\n// Mostly 2 is all that is needed, so a buffer of MAX_RETURN_ADDRESSES is only allocated when needed.\r\n#define RETURN_ADDRESSES_SMALL_BUFFER_SIZE 2\r\n\r\n// Return values from CScript::Update()\r\nenum EScriptReturnVal\r\n{\r\n    ESCRIPTRETURNVAL_FINISHED,\r\n    ESCRIPTRETURNVAL_BLOCKED,\r\n\tESCRIPTRETURNVAL_WAITING,\r\n    ESCRIPTRETURNVAL_ERROR,\r\n\tESCRIPTRETURNVAL_STOPPED_IN_DEBUGGER,\r\n\tESCRIPTRETURNVAL_FINISHED_INTERRUPT,\r\n};\r\n\r\n// Values for CScript::m_wait_type\r\nenum EWaitType\r\n{\r\n\tWAIT_TYPE_NONE=0,\r\n\tWAIT_TYPE_COUNTER,\r\n\tWAIT_TYPE_TIMER,\r\n\tWAIT_TYPE_BLOCKED,\r\n\tWAIT_TYPE_OBJECT_MOVE,\r\n\tWAIT_TYPE_OBJECT_ANIM_FINISHED,\r\n\tWAIT_TYPE_OBJECT_JUMP_FINISHED,\r\n\tWAIT_TYPE_OBJECT_STOP_FINISHED,\r\n\tWAIT_TYPE_OBJECT_ROTATE,\r\n\tWAIT_TYPE_STREAM_FINISHED,\r\n\tWAIT_TYPE_ONE_PER_FRAME,\r\n};\r\n\r\nenum ESingleStepMode\r\n{\r\n\tOFF=0,\r\n\tWAITING,\r\n\tSTEP_INTO,\r\n\tSTEP_OVER,\r\n};\r\n\r\nenum\r\n{\r\n\tDEFINITELY_TRANSMIT=1\r\n};\r\n\t\r\n// Begin-repeat loop structure.    \r\nstruct SLoop\r\n{\r\n    // Pointer to the start of the loop, which is the\r\n    // token following the Begin.\r\n    uint8 *mpStart;\r\n\t\r\n\t// Pointer to the end of the loop, ie the next instruction after the loop.\r\n\tuint8 *mpEnd;\r\n    \r\n\tbool mGotCount;\t\t\t// Whether it is a finite loop with a count value.\r\n\tbool mNeedToReadCount;\t// Whether the count value following the repeat needs to be read.\r\n    int mCount;\t\t\t\t// Counts down to zero, and skips past the repeat once it reaches zero.\r\n};\r\n\r\n// Saves the original location & other info when calling a subroutine.\r\nstruct SReturnAddress\r\n{\r\n    uint32 mScriptNameChecksum;\r\n    CStruct *mpParams;\r\n    uint8 *mpReturnAddress;\r\n\tObj::CObject *mpObject;\r\n\tSLoop *mpLoop;\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint32 m_if_status;\r\n\t#endif\r\n\tEWaitType mWaitType;\r\n\tObj::CBaseComponent *mpWaitComponent;\r\n    int mWaitTimer;\r\n\tTmr::Time mStartTime;\r\n\tTmr::Time mWaitPeriod;\r\n\tbool mInterrupted;\r\n};\r\n\r\n// Script class.\r\n// To run a script, one must create one of these, then call the SetScript member function to\r\n// set which script it is to run.\r\n//\r\n// Then the Update function must be called repeatedly.\r\n// The script will never die by itself, it must be deleted.\r\n//\r\n// Poolable to speed up allocation & deallocation.\r\n// MEMOPT sizeof(CScript) was 1080 last time I checked, due to the arrays of \r\n// loops, return addresses and if's. Could maybe allocate these off pools instead, if the number\r\n// of CScript's ever gets big enough to be using up a substantial amount of memory.\r\n// There would be a slight speed hit if pools were used, but probably not much, \r\n// allocating/deallocating off a pool is pretty quick.\r\n#ifdef __PLAT_WN32__\r\nclass CScript\r\n#else\r\nclass CScript : public Mem::CPoolable<CScript>\r\n#endif\r\n{\r\n\t// CScripts are linked into a list.\r\n\tCScript *mp_next;\r\n\tCScript *mp_previous;\r\n\tfriend CScript *GetNextScript(CScript *p_script=NULL);\r\n\t\r\n\t// If this CScript got setup using a SStructScript (via the SetScript member function below)\r\n\t// then this will be a pointer to a copy of the script, and mp_pc will point somewhere into it.\r\n\t// Otherwise mp_struct_script will be left as NULL.\r\n\tuint8 *mp_struct_script;\r\n\t\r\n    // The program counter.\r\n    uint8 *mp_pc;\r\n\t\r\n\t// Holds the parameters for passing to function calls.\r\n\tCStruct *mp_function_params;\r\n\r\n    // The input parameters, which get accessed within the script using the <,> operator.\r\n    CStruct *mp_params;\r\n\t\r\n    // Begin-Repeat loop stuff.\r\n    // NULL if not in a loop, otherwise points into the following array.\r\n    SLoop *mp_current_loop;\r\n\t// If the number of loops needs to be bigger than NESTED_BEGIN_REPEATS_SMALL_BUFFER_SIZE then\r\n\t// mp_loops will point to a dynamically allocated array of MAX_NESTED_BEGIN_REPEATS SLoop structures,\r\n\t// otherwise mp_loops will equal mp_loops_small_buffer\r\n    SLoop mp_loops_small_buffer[NESTED_BEGIN_REPEATS_SMALL_BUFFER_SIZE];\r\n\tSLoop *mp_loops;\r\n\t\r\n\t\r\n\r\n    // Call stack.\r\n    int m_num_return_addresses;\r\n    SReturnAddress mp_return_addresses_small_buffer[RETURN_ADDRESSES_SMALL_BUFFER_SIZE];\r\n\t// If the num return addresses needs to be bigger than RETURN_ADDRESSES_SMALL_BUFFER_SIZE then\r\n\t// mp_return_addresses will point to a dynamically allocated array of MAX_RETURN_ADDRESSES SReturnAddress structures,\r\n\t// otherwise mp_return_addresses will equal mp_return_addresses_small_buffer\r\n\tSReturnAddress *mp_return_addresses;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\t// Used to determine when to step-over a script command when the script\r\n\t// is being stepped through in the debugger.\r\n\tint m_last_num_return_addresses_when_halted;\r\n\t#endif\r\n\t\r\n    // Used by the Wait function to cause a script to hiccup.\r\n    int m_wait_timer;\r\n\t\r\n\t// Used by the WaitTime function to cause the script to wait for an\r\n\t// absolute amount of time.\r\n\tTmr::Time m_start_time;\r\n\tTmr::Time m_wait_period;\r\n\r\n\t// How the script is waiting.\r\n\tEWaitType m_wait_type;\r\n\tObj::CBaseComponent *mp_wait_component;\r\n\r\n\t\r\n\r\n\t// a helpful member added by Ryan\r\n\tuint32\tm_unique_id;\r\n\t// used for computing unique IDs\r\n\tstatic int s_next_unique_id;\r\n\t\r\n\t// Gets set to true if the script was forced to call another script by a call to Interrupt.\r\n\t// This will get stored in the call stack.\r\n\t// Needed to prevent the call to Update() that Interrupt does from continuing the execution of\r\n\t// the interrupted script when the called script finishes.\r\n\tbool m_interrupted;\r\n\r\n\tvoid call_script(uint32 newScriptChecksum, uint8 *p_script, CStruct *p_params, Obj::CObject *p_object, bool interrupt=false);\r\n\tvoid set_script(uint32 scriptChecksum, uint8 *p_script, CStruct *p_params, Obj::CObject *p_object);\r\n\t\r\n\t// This flag is to prevent multiple calls to process_waits in nested calls to CScript::Update(),\r\n\t// such as when a script command causes an interrupt to occur on itself.\r\n\tbool m_skip_further_process_waits;\t\r\n\t\r\n\tvoid process_waits();\r\n\t\r\n\tvoid load_function_params();\r\n\tbool run_member_function(uint32 functionName, Obj::CObject *p_substituteObject=NULL);\r\n\tbool run_cfunction(bool (*p_cfunc)(CStruct *pParams, CScript *pCScript));\r\n\tuint32 get_name();\r\n\t\r\n\tbool execute_command();\r\n\t\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tbool \t\t\tm_if_debug_on;\r\n\tuint32 \t\t\tm_if_status; \t\t\t// For detecting spurious else's\r\n\t#endif\r\n\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\t// Used by script debugger code.\r\n\tuint32 m_last_transmitted_info_checksum;\r\n\tbool m_being_watched_in_debugger;\r\n\tESingleStepMode m_single_step_mode;\r\n\tenum\r\n\t{\r\n\t\tMAX_COMMENT_STRING_CHARS=63,\r\n\t};\r\n\tchar mp_comment_string[MAX_COMMENT_STRING_CHARS+1];\r\n\tint m_originating_script_line_number;\r\n\tuint32 m_originating_script_name;\r\n\tfloat m_last_instruction_time_taken;\r\n\tfloat m_total_instruction_time_taken;\r\n\t\r\n\t#ifdef __PLAT_WN32__\r\n\tuint32 *write_callstack_entry(uint32 *p_buf, int bufferSize, uint32 scriptNameChecksum, uint8 *p_PC, CStruct *p_params, Obj::CObject *p_ob) {}\r\n\tvoid check_if_needs_to_be_watched_in_debugger() {}\r\n\tvoid advance_pc_to_next_line_and_halt() {}\r\n\t#else\r\n\tuint32 *write_callstack_entry(uint32 *p_buf, int bufferSize, uint32 scriptNameChecksum, uint8 *p_PC, CStruct *p_params, Obj::CObject *p_ob);\r\n\tvoid check_if_needs_to_be_watched_in_debugger();\r\n\tvoid advance_pc_to_next_line_and_halt();\r\n\t#endif\r\n\t#endif\r\n\t\r\n\tvoid execute_if();\r\n\tvoid execute_else();\r\n\tvoid execute_endif();\r\n\t\r\n\t\r\n\tvoid skip_to_after_endswitch();\r\n\tvoid execute_switch();\r\n\t\r\n\tvoid execute_begin();\r\n\tvoid execute_repeat();\r\n\tvoid execute_break();\r\n\t\r\n\tbool execute_return();\r\n\r\npublic:\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\t#ifdef __PLAT_WN32__\r\n\tvoid SetCommentString(const char *p_comment) {}\r\n\tvoid SetOriginatingScriptInfo(int lineNumber, uint32 scriptName) {}\r\n\tvoid TransmitInfoToDebugger(bool definitely_transmit=false) {}\r\n\tvoid TransmitBasicInfoToDebugger() {}\r\n\tvoid WatchInDebugger(bool stopScriptImmediately) {}\r\n\tbool BeingWatchedInDebugger() {return false;}\r\n\tvoid StopWatchingInDebugger() {}\r\n\tvoid DebugStop() {}\r\n\tvoid DebugStepInto() {}\r\n\tvoid DebugStepOver() {}\r\n\tvoid DebugGo() {}\r\n\t#else\t\r\n\tvoid SetCommentString(const char *p_comment);\r\n\tvoid SetOriginatingScriptInfo(int lineNumber, uint32 scriptName);\r\n\t// This gets called for all CScript's every frame.\r\n\t// It transmits lots of info about the script to the script debugger running on the PC\r\n\tvoid TransmitInfoToDebugger(bool definitely_transmit=false);\r\n\tvoid TransmitBasicInfoToDebugger();\r\n\tvoid WatchInDebugger(bool stopScriptImmediately);\r\n\tbool BeingWatchedInDebugger() {return m_being_watched_in_debugger;}\r\n\tvoid StopWatchingInDebugger();\r\n\tvoid DebugStop();\r\n\tvoid DebugStepInto();\r\n\tvoid DebugStepOver();\r\n\tvoid DebugGo();\r\n\t\r\n\tint GetNumReturnAddresses() {return m_num_return_addresses;}\r\n\tbool UsingBigCallstackBuffer();\r\n\tbool UsingBigLoopBuffer();\r\n\t#endif\r\n\t#endif\r\n\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\t// Event Handler/Exception Stuff\r\n\tvoid\t\t\t\tSetEventHandler(uint32 ex, uint32 scr, uint32 group, bool exception, CStruct* p_params);\r\n\tvoid  \t\t\t\tSetEventHandlers(Script::CArray *pArray, EReplaceEventHandlers replace = DONT_REPLACE_HANDLERS);\r\n\tvoid\t\t\t\tRemoveEventHandler(uint32 type);\r\n\tvoid\t\t\t\tRemoveEventHandlerGroup(uint32 group);\r\n\tvoid \t\t\t\tSetOnExceptionScriptChecksum(uint32 OnExceptionScriptChecksum);\r\n\tuint32 \t\t\t\tGetOnExceptionScriptChecksum() const; \r\n\tvoid \t\t\t\tSetOnExitScriptChecksum(uint32 OnExceptionScriptChecksum);\r\n\tuint32 \t\t\t\tGetOnExitScriptChecksum() const; \r\n\tbool\t\t\t\tPassTargetedEvent(Obj::CEvent *pEvent, bool broadcast = false);\t// return true if object still valid\r\n#endif\r\n\r\n\tvoid\t\t\t\tPrintEventHandlerTable (   );\r\n\t\r\n\tCStruct *GetParams() {Dbg_MsgAssert(mp_params,(\"NULL mp_params ?\")); return mp_params;}\r\n\r\n\tint\tmNode;\t\t// Number of the node that caused this script to be spawned, -1 if none specific\r\n\r\n    // If NULL then the script is a free script, eg StartUp.\r\n    // If non-NULL, then the script is associated with some object.\r\n    Obj::CObjectPtr mpObject;\r\n\r\n    // Checksum of the name of this script.\r\n    uint32 mScriptChecksum;\r\n\r\n\tvoid SetWait(EWaitType type, Obj::CBaseComponent *p_component);\r\n\tvoid ClearWait();\r\n\tEWaitType GetWaitType() {return m_wait_type;}\r\n\r\n\r\n\tbool mIsSpawned:1;\t// True if this is a spawned script.\r\n\t// Note: These next members only apply if the script is spawned.\r\n\tbool mNotSessionSpecific:1; // If this is true then the spawned script will not get\r\n\t\t\t\t\t\t\t\t// deleted by DeleteSpawnedScripts\r\n\tbool mPaused:1;\r\n\tbool mPauseWithObject:1;\t// If this is true then the spawned script will pause when its object's ShouldUpdatePauseWithObjectScripts\r\n\t\t\t\t\t\t\t\t// returns false.  CCompositeObjects return\tfalse when they are paused.\r\n\tuint32 mId;\r\n\t// An optional callback script, which gets run as soon as the spawned script completes.\r\n\tuint32 mCallbackScript;\r\n\tCStruct *mpCallbackScriptParams;\r\n\r\n\tCScript();\r\n    ~CScript();\r\n\r\n    void SetScript(uint32 scriptChecksum, CStruct *p_params=NULL, Obj::CObject *p_object=NULL);\r\n    void SetScript(const char *p_scriptName, CStruct *p_params=NULL, Obj::CObject *p_object=NULL);\r\n    void SetScript(const SStructScript *p_structScript, CStruct *p_params=NULL, Obj::CObject *p_object=NULL);\r\n\t\r\n\tCStruct *MakeParamsSafeFromDeletionByClearScript(CStruct *p_params);\r\n\tvoid ClearScript();\r\n\tvoid ClearEventHandlerTable();\r\n\tbool RefersToScript(uint32 checksum);\r\n\tbool RefersToObject(Obj::CObject *p_object);\r\n\tvoid RemoveReferencesToObject(Obj::CObject *p_object);\r\n\t\r\n\tbool AllScriptsInCallstackStillExist();\r\n\tuint32 GetBaseScript();\r\n\tvoid Restart();\r\n\tEScriptReturnVal Interrupt(uint32 newScriptChecksum, CStruct *p_params=NULL);\r\n\t\r\n    EScriptReturnVal Update();\r\n    bool Finished();\r\n\r\n\tvoid Block();\r\n\tvoid UnBlock();\r\n\tbool getBlocked();\r\n\r\n\tvoid Clear();\r\n    void Wait(int numFrames);\r\n    void WaitOnePerFrame(int numFrames);\r\n\tvoid WaitTime(Tmr::Time period);\r\n\tbool GotScript();\r\n\r\n\tuint32 GetUniqueId() {return m_unique_id;}\r\n\t\r\n\t// Stops the script from being associated with an object, ie, sets mpObject to NULL.\r\n\t// Allows the script to continue executing though, so the script must not contain any\r\n\t// further member functions, otherwise the code will assert.\r\n\t// This function also sets mWaitType=WAIT_TYPE_NONE; to ensure the Update function does\r\n\t// not assert if it is waiting for the object to finish doing something.\r\n\tvoid DisassociateWithObject(Obj::CObject *pObjectToDisconnectFrom);\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tconst char *GetScriptInfo();\r\n\tint GetCurrentLineNumber(void);\r\n\tconst char *GetSourceFile(void);\r\n\t\r\n\t// and let's have it for debugging for now, in case people (Mick!) leave it in by mistake and screw up the build\r\n\tconst inline char *GetScriptInfo( void ) const { return \"\"; }\r\n\t#else // #ifdef __NOPT_ASSERT__\r\n#\tifdef __PLAT_XBOX__\r\n\tconst inline char *GetScriptInfo( void ) const { return \"\"; }\r\n#\tendif // ifdef __PLAT_XBOX__\r\n\r\n\t#ifdef __PLAT_WN32__\r\n\tconst char *GetScriptInfo() const {return \"\";}\r\n\t#endif\r\n\t\r\n\t#endif // #ifdef __NOPT_ASSERT__\r\n\t\r\n\tvoid SwitchOnIfDebugging();\r\n\tvoid SwitchOffIfDebugging();\r\n\r\n// These are pseudo-private, for debugging profiling only\r\n\t#ifdef __NOPT_ASSERT__\r\n\tint\t\t\t\tm_last_time;\t\t\t// time spend in last update\t\r\n\tint \t\t\tm_total_time;\t\t\t// total time spent updating\r\n\t#endif\r\n\t\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\nprivate:\t\r\n\tObj::CEventHandlerTable *\tmp_event_handler_table;\r\n\t\r\n\t// Script to run when there is an exception\t\r\n\t// (needed here, since we are getting rid of CExceptionComponent, to replace it with one \r\n\t// single event system\r\n\tuint32 \t\t\tmOnExceptionScriptChecksum;\r\n\tuint32 \t\t\tmOnExitScriptChecksum;\r\npublic:\r\n\tObj::CEventHandlerTable * GetEventHandlerTable() {return mp_event_handler_table;}\r\n\tObj::CRefCounted\t\t\tm_reference_counter;\t\t// having a reference counter allows us to have a safe smart pointer\t\r\n#endif\t \r\n\r\n\r\n\r\n};\r\n\r\nvoid SendScript( uint32 scriptChecksum, CStruct *p_params, Obj::CObject *p_object );\r\n\r\nvoid RunScript(const char *p_scriptName, CStruct *p_params=NULL, Obj::CObject *p_object=NULL,\r\n\t\t\t\tbool netScript = false );\r\nvoid RunScript(uint32 scriptChecksum, CStruct *p_params=NULL, Obj::CObject *p_object=NULL,\r\n\t\t\t\tbool netScript = false, const char *p_scriptName=NULL );\r\n\r\nvoid DeleteSpawnedScripts();\r\nvoid UpdateSpawnedScripts();\r\nvoid PauseSpawnedScripts(bool status);\r\nvoid UnpauseSpawnedScript(CScript* p_script);\r\nuint32 NumSpawnedScriptsRunning();\r\nbool\tScriptExists(uint32 scriptNameChecksum);\r\n\r\nCScript* SpawnScript(uint32 scriptChecksum, CStruct *p_script_params=NULL, \r\n\t\t\t\t\t uint32 callbackScript=NO_NAME, CStruct *p_callbackParams=NULL,\r\n\t\t\t\t\t int node = -1, uint32 id=0,\r\n\t\t\t\t\t bool netEnabled = false, bool permanent = false, bool not_session_specific=false, bool pause_with_object=false );\r\nCScript* SpawnScript(const char *pScriptName, CStruct *p_script_params=NULL,\r\n\t\t\t\t\t uint32 callbackScript=NO_NAME, CStruct *p_callbackParams=NULL,\r\n\t\t\t\t\t int node = -1, uint32 id=0,\r\n\t\t\t\t\t bool netEnabled = false, bool permanent = false, bool not_session_specific=false, bool pause_with_object=false );\r\nvoid KillSpawnedScript(CScript *p_script);\r\nvoid KillSpawnedScriptsThatReferTo(uint32 checksum);\r\nvoid KillSpawnedScriptsWithId(uint32 id);\r\nvoid KillSpawnedScriptsWithObject(Obj::CObject *p_object);\r\nvoid KillSpawnedScriptsWithObjectAndId(Obj::CObject *p_object, uint32 id, CScript *p_callingScript);\r\nvoid KillSpawnedScriptsWithObjectAndName(Obj::CObject *p_object, uint32 name, CScript *p_callingScript);\r\nuint32 FindSpawnedScriptID(CScript *p_script);\r\nCScript* FindSpawnedScriptWithID(uint32 id);\r\nvoid SendSpawnScript( uint32 scriptChecksum, Obj::CObject *p_object, int node, bool permanent );\r\n\r\n\r\nCScript *GetScriptWithUniqueId(uint32 id);\r\n\r\n// These should not be here, but should be in the game-specific scripting directory.\r\n// Just putting them here for the moment to get things to compile ...\r\nclass CArray;\r\n\r\n// TODO: This just included to allow compilation of GenerateCRC, remove later.\r\nuint32 GenerateCRC(const char *p_string);\r\n\r\nvoid StopAllScripts();\r\nvoid StopAllScriptsUsingThisObject(Obj::CObject *p_object);\r\nvoid StopScriptsUsingThisObject(Obj::CObject *p_object, uint32 scriptCrc);\r\nvoid StopScriptsUsingThisObject_Proper(Obj::CObject *p_object, uint32 scriptCrc);\r\nvoid KillStoppedScripts();\r\nvoid DumpScripts();\r\n\r\nuint32 GetNumCScripts();\r\n\r\nCScript *GetCurrentScript();\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\nconst char * GetCurrentScriptInfo();\r\n#endif\r\n\r\n} // namespace Script\r\n\r\n#endif\t// __SCRIPTING_SCRIPT_H\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/scriptcache.cpp",
    "content": "#include <gel/scripting/scriptcache.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/parse.h>\r\n#include <core/compress.h>\r\n#include <gel/mainloop.h>\r\n\r\n#ifdef __PLAT_NGC__\r\n#include <sys/ngc/p_aram.h>\r\n#include <sys/ngc/p_dma.h>\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n#ifdef NO_SCRIPT_CACHING\r\n#else\r\nDefinePoolableClass(Script::CScriptCacheEntry);\r\n#endif\r\n\r\n// Make CScriptCache::GetDebugInfo determine how much the cache is 'thrashing' (ie, average number of new script\r\n// entries created per frame over last second, & indicate the max)\r\n// Make scripts not get removed from the cache straight away when their usage hits 0, but just\r\n// remove the oldest zero-usage script when the heap is full and a new script needs to go in.\r\n// Make CScriptCache::GetDebugInfo sort the array of scripts in order of usage\r\n\r\n// Implement compression in qcomp.\r\n// Test, test qbr, test size of cache required, test speed.\r\n// Make it possible to switch back to no caching very easily. (mybe even dynamically?)\r\nnamespace Script\r\n{\r\n\r\nDefineSingletonClass( CScriptCache, \"Script cache module\" );\r\n\r\n#ifdef NO_SCRIPT_CACHING\r\nCScriptCache::CScriptCache()\r\n{\r\n}\r\n\r\nCScriptCache::~CScriptCache()\r\n{\r\n}\r\n\r\nvoid CScriptCache::v_start_cb ( void )\r\n{\r\n}\r\n\r\nvoid CScriptCache::v_stop_cb ( void )\r\n{\r\n}\r\n\r\nuint8 *CScriptCache::GetScript(uint32 scriptName)\r\n{\r\n    CSymbolTableEntry *p_entry=Resolve(scriptName);\r\n    if (p_entry)\r\n    {\r\n        Dbg_MsgAssert(p_entry->mType==ESYMBOLTYPE_QSCRIPT,(\"Symbol %s is not a QScript\",FindChecksumName(scriptName)));\r\n        Dbg_MsgAssert(p_entry->mpScript,(\"NULL p_entry->mpScript\"));\r\n\r\n\t\treturn p_entry->mpScript+4; // +4 to skip over the contents checksum\r\n\t}\r\n\t\r\n\treturn NULL;\r\n}\r\n\r\nvoid CScriptCache::DecrementScriptUsage(uint32 scriptName)\r\n{\r\n}\r\n\r\nvoid CScriptCache::RefreshAfterReload(uint32 scriptName)\r\n{\r\n}\r\n\r\nvoid CScriptCache::DeleteZeroUsageStraightAway()\r\n{\r\n}\r\n\r\nvoid CScriptCache::DeleteOldestZeroUsageWhenNecessary()\r\n{\r\n}\r\n\r\n#ifdef __NOPT_ASSERT__\r\nvoid CScriptCache::GetDebugInfo( Script::CStruct* p_info )\r\n{\r\n\tp_info->AddChecksum(NONAME,CRCD(0xf34b1528,\"ScriptCachingDisabled\"));\r\n}\r\n#endif\r\n\r\n#else\r\n\r\nCScriptCacheEntry::CScriptCacheEntry()\r\n{\r\n\tmpDecompressedScript=NULL;\r\n\tmUsage=0;\r\n\tmScriptNameChecksum=0;\r\n\tmpNext=NULL;\r\n\tmpPrevious=NULL;\r\n}\r\n\r\nCScriptCacheEntry::~CScriptCacheEntry()\r\n{\r\n\t// This is just to make sure nothing accidentally deletes an entry in the CScriptCache's\r\n\t// list of zero-usage entries. It won't work if there is only one entry in the list, but\r\n\t// it's better than nothing.\r\n\tDbg_MsgAssert(mpNext==NULL,(\"CScriptCacheEntry::mpNext not NULL !\"));\r\n\tDbg_MsgAssert(mpPrevious==NULL,(\"CScriptCacheEntry::mpPrevious not NULL !\"));\r\n\t\r\n\tif (mpDecompressedScript)\r\n\t{\r\n\t\tMem::Free(mpDecompressedScript);\r\n\t}\t\r\n}\t\r\n\r\nCScriptCache::CScriptCache()\r\n{\r\n\tDbg_MsgAssert(IDEAL_MAX_DECOMPRESSED_SCRIPTS < MAX_DECOMPRESSED_SCRIPTS,(\"IDEAL_MAX_DECOMPRESSED_SCRIPTS should be less than MAX_DECOMPRESSED_SCRIPTS\"));\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tmp_logic_task=NULL;\r\n\tm_current_decompress_count_index=0;\r\n\tfor (int i=0; i<MAX_DECOMPRESS_COUNTS; ++i)\r\n\t{\r\n\t\tmp_decompress_counts[i]=0;\r\n\t}\t\r\n\tm_num_used_scripts=0;\r\n\tm_max_used_scripts=0;\r\n\t#endif\r\n\t\r\n\t// mp_cache_hash_table is allocated here rather than in v_start_cb because v_start_cb does not\r\n\t// get called until the first frame of the game loop, which was causing a problem on XBox\r\n\t// because Nx::CEngine::sStartEngine(); needs to run a script, and that call occurs early in main.cpp\r\n\t// before the main loop.\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\tmp_cache_hash_table = new Lst::HashTable<CScriptCacheEntry>(8);\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\tmp_first_zero_usage=NULL;\r\n\tmp_last_zero_usage=NULL;\r\n\t\r\n\tm_delete_zero_usage_straight_away=false;\r\n}\r\n\r\nCScriptCache::~CScriptCache()\r\n{\r\n\tmp_cache_hash_table->IterateStart();\r\n\tCScriptCacheEntry *p_cache_entry = mp_cache_hash_table->IterateNext();\r\n\twhile (p_cache_entry)\r\n\t{\r\n\t\t// Would it be better to just flush all the items after this loop instead?\r\n\t\t// (Ie, could flushing here confuse IterateNext ?)\r\n\t\tmp_cache_hash_table->FlushItem(p_cache_entry->mScriptNameChecksum);\r\n\t\t\r\n\t\t// Clear these to prevent ~CScriptCacheEntry from asserting.\r\n\t\tp_cache_entry->mpNext=NULL;\r\n\t\tp_cache_entry->mpPrevious=NULL;\r\n\t\tdelete p_cache_entry;\r\n\t\t\r\n\t\tp_cache_entry = mp_cache_hash_table->IterateNext();\r\n\t}\r\n\r\n\tdelete mp_cache_hash_table;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (mp_logic_task)\r\n\t{\r\n\t\tdelete mp_logic_task;\r\n\t}\t\r\n\t#endif\t\r\n}\r\n\r\nvoid CScriptCache::v_start_cb ( void )\r\n{\r\n\t#ifdef __NOPT_ASSERT__\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\tmp_logic_task = new Tsk::Task< CScriptCache > ( CScriptCache::s_logic_code, *this );\r\n\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\tmlp_manager->AddLogicTask( *mp_logic_task );\r\n\tMem::Manager::sHandle().PopContext();\r\n\t#endif\r\n}\r\n\r\nvoid CScriptCache::v_stop_cb ( void )\r\n{\r\n\t#ifdef __NOPT_ASSERT__\r\n\tmp_logic_task->Remove();\r\n\t#endif\r\n}\r\n\r\nvoid CScriptCache::add_to_zero_usage_list(CScriptCacheEntry *p_entry)\r\n{\r\n\tDbg_MsgAssert(p_entry,(\"NULL p_entry sent to add_to_zero_usage_list\"));\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tCScriptCacheEntry *p_search=mp_first_zero_usage;\r\n\twhile (p_search)\r\n\t{\r\n\t\tDbg_MsgAssert(p_search != p_entry,(\"p_entry is already in the zero-usage list !\"));\r\n\t\tp_search=p_search->mpNext;\r\n\t}\t\r\n\t#endif\r\n\t\r\n\tp_entry->mpPrevious=NULL;\r\n\tp_entry->mpNext=mp_first_zero_usage;\r\n\tmp_first_zero_usage=p_entry;\r\n\tif (p_entry->mpNext)\r\n\t{\r\n\t\tp_entry->mpNext->mpPrevious=p_entry;\r\n\t}\r\n\tif (!mp_last_zero_usage)\r\n\t{\r\n\t\tmp_last_zero_usage=mp_first_zero_usage;\r\n\t}\t\r\n}\r\n\r\nvoid CScriptCache::remove_from_zero_usage_list(CScriptCacheEntry *p_entry)\r\n{\r\n\tDbg_MsgAssert(p_entry,(\"NULL p_entry sent to remove_from_zero_usage_list\"));\r\n\t\r\n\t// Unlink the entry from the list.\r\n\tif (p_entry->mpPrevious)\r\n\t{\r\n\t\tp_entry->mpPrevious->mpNext=p_entry->mpNext;\r\n\t}\r\n\tif (p_entry->mpNext)\r\n\t{\r\n\t\tp_entry->mpNext->mpPrevious=p_entry->mpPrevious;\r\n\t}\r\n\t\t\r\n\t// Update mp_last_zero_usage and mp_first_zero_usage\r\n\tif (p_entry==mp_first_zero_usage)\r\n\t{\r\n\t\tmp_first_zero_usage=p_entry->mpNext;\r\n\t}\r\n\tif (p_entry==mp_last_zero_usage)\r\n\t{\r\n\t\tmp_last_zero_usage=p_entry->mpPrevious;\r\n\t}\r\n\t\r\n\tp_entry->mpNext=NULL;\r\n\tp_entry->mpPrevious=NULL;\r\n}\r\n\r\n// This function must be used to delete a CScriptCacheEntry rather than deleting it directly,\r\n// since this function will update the list of zero-usage entries if necessary.\r\nvoid CScriptCache::delete_entry(CScriptCacheEntry *p_entry)\r\n{\r\n\tDbg_MsgAssert(p_entry,(\"NULL p_entry sent to delete_entry\"));\r\n\t\r\n\tmp_cache_hash_table->FlushItem(p_entry->mScriptNameChecksum);\r\n\t// Note: If the entry is not in the zero-usage list, this function won't do anything, so safe to call.\r\n\tremove_from_zero_usage_list(p_entry);\r\n\tdelete p_entry;\r\n}\r\n\r\n// The scriptName is only passed so that the assert can print the name of the script\r\n// if no space could be freed up for it.\r\nvoid CScriptCache::remove_some_old_scripts(int space_required, uint32 scriptName)\r\n{\r\n\twhile (true)\r\n\t{\r\n\t\tint largest_malloc_possible=Mem::Manager::sHandle().ScriptHeap()->LargestFreeBlock();\r\n\t\tlargest_malloc_possible-=128; // Actually, 32 seems OK, but have a bigger margin just to be sure.\r\n\t\t\r\n\t\tif (space_required <= largest_malloc_possible)\r\n\t\t{\r\n\t\t\t// Hurrah! It's all clear to decompress another script since we know there is enough heap to hold it.\r\n\t\t\t\r\n\t\t\t// Try to keep the total number of decompressed scripts within IDEAL_MAX_DECOMPRESSED_SCRIPTS\r\n\t\t\t// by removing unused ones until either enough have been removed or there are no more to remove.\r\n\t\t\t\r\n\t\t\t// This way the average memory usage can be controlled by tweaking IDEAL_MAX_DECOMPRESSED_SCRIPTS\r\n\t\t\t// whilst spikes in the number of scripts are still permitted up to the limit set by\r\n\t\t\t// the pool size of MAX_DECOMPRESSED_SCRIPTS. If that limit is reached, the code will assert.\r\n\t\t\twhile (CScriptCacheEntry::SGetNumUsedItems() >= IDEAL_MAX_DECOMPRESSED_SCRIPTS && mp_last_zero_usage)\r\n\t\t\t{\r\n\t\t\t\tdelete_entry(mp_last_zero_usage);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\r\n\t\t// Free up some space by deleting the oldest zero-usage decompressed script.\r\n\t\t\r\n\t\tif (!mp_last_zero_usage)\r\n\t\t{\r\n\t\t\t// Eeeek! There's nothing left to delete ...\r\n\t\t\tDbg_MsgAssert(0,(\"Script heap overflow when trying to allocate decompressed script '%s' of size %d bytes!\",Script::FindChecksumName(scriptName),space_required));\r\n\t\t}\r\n\t\t\r\n\t\t//printf(\"%d: Deleting %s from cache, new free space = %d\\n\",space_required,Script::FindChecksumName(mp_last_zero_usage->mScriptNameChecksum),Mem::Manager::sHandle().ScriptHeap()->LargestFreeBlock()-128);\r\n\t\tdelete_entry(mp_last_zero_usage);\r\n\t}\t\r\n}\r\n\r\nuint8 *CScriptCache::GetScript(uint32 scriptName)\r\n{\r\n    CSymbolTableEntry *p_entry=Resolve(scriptName);\r\n    if (p_entry)\r\n    {\r\n        Dbg_MsgAssert(p_entry->mType==ESYMBOLTYPE_QSCRIPT,(\"Symbol %s is not a QScript\",FindChecksumName(scriptName)));\r\n#ifndef __PLAT_NGC__\r\n        Dbg_MsgAssert(p_entry->mpScript,(\"NULL p_entry->mpScript\"));\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\r\n\t\t// Change the passed scriptName to be the actual scriptName so that when decompressed it gets registered in\r\n\t\t// the cache under the correct name.\r\n\t\t// Otherwise, if a SpawnScript Foo is done after Foo has been changed using the 'change' command, it\r\n\t\t// will spawn the old script again, since it will be in the cache under Foo.\r\n\t\tscriptName=p_entry->mNameChecksum;\r\n\t}\t\r\n\r\n\r\n\tCScriptCacheEntry *p_cache_entry=mp_cache_hash_table->GetItem(scriptName);\r\n\tif (p_cache_entry)\r\n\t{\r\n\t\t++p_cache_entry->mUsage;\r\n\t\t\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tif (p_cache_entry->mUsage==1)\r\n\t\t{\r\n\t\t\t++m_num_used_scripts;\r\n\t\t\tif (m_num_used_scripts > m_max_used_scripts)\r\n\t\t\t{\r\n\t\t\t\tm_max_used_scripts=m_num_used_scripts;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\t#endif\r\n\t\t\r\n\t\tremove_from_zero_usage_list(p_cache_entry);\r\n\t\treturn p_cache_entry->mpDecompressedScript;\r\n\t}\t\r\n\t\t\r\n    if (p_entry)\r\n    {\r\n#ifdef __PLAT_NGC__\r\n\t\tenum\r\n\t\t{\r\n\t\t\tCOMPRESS_BUFFER_SIZE=20000,\r\n\t\t};\t\r\n\t\tuint8 p_compress_buffer[COMPRESS_BUFFER_SIZE];\r\n\t\tuint32 header[(SCRIPT_HEADER_SIZE/4)];\r\n\t\tNsDMA::toMRAM( header, p_entry->mScriptOffset, SCRIPT_HEADER_SIZE );\r\n\t\tuint32 uncompressed_size\t\t= header[1];\r\n\t\tuint32 compressed_size\t\t\t= header[2];\r\n\t\tNsDMA::toMRAM( p_compress_buffer, p_entry->mScriptOffset + SCRIPT_HEADER_SIZE, compressed_size );\r\n#else\r\n\t\t// Note: The script contents checksum is at offset 0, but it is not needed.\r\n\t\tuint32 uncompressed_size\t\t= *(uint32*)(p_entry->mpScript+4);\r\n\t\tuint32 compressed_size\t\t\t= *(uint32*)(p_entry->mpScript+8);\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\r\n\t\tremove_some_old_scripts(uncompressed_size,scriptName);\r\n\r\n\t\tCScriptCacheEntry *p_cache_entry=new CScriptCacheEntry;\r\n\t\t\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\tuint8 *p_new_script=(uint8*)Mem::Malloc(uncompressed_size);\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\tif (uncompressed_size > compressed_size)\r\n\t\t{\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\t\t\r\n\t\t\tuint8 *p_end=\r\n\t\t\t#endif\r\n#ifdef __PLAT_NGC__\r\n\t\t\t\tDecodeLZSS(p_compress_buffer,p_new_script,compressed_size);\r\n#else\r\n\t\t\t\tDecodeLZSS(p_entry->mpScript+SCRIPT_HEADER_SIZE,p_new_script,compressed_size);\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\tDbg_MsgAssert(p_end==p_new_script+uncompressed_size,(\"Eh? p_end is not right?\"));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// The script is uncompressed so just copy it over. Saves, errr, 1K altogether, oh well.\r\n\t\t\tDbg_MsgAssert(uncompressed_size == compressed_size,(\"Expected uncompressed_size==compressed_size\"));\r\n#ifdef __PLAT_NGC__\r\n\r\n\t\t\tuint8 *p_source=p_compress_buffer;\r\n#else\r\n\t\t\tuint8 *p_source=p_entry->mpScript+SCRIPT_HEADER_SIZE;\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\tuint8 *p_dest=p_new_script;\r\n\t\t\tfor (uint32 i=0; i<uncompressed_size; ++i)\r\n\t\t\t{\r\n\t\t\t\t*p_dest++=*p_source++;\r\n\t\t\t}\t\r\n\t\t}\r\n\t\t\r\n\t\tPreProcessScript(p_new_script);\r\n\t\t\r\n\t\tp_cache_entry->mpDecompressedScript=p_new_script;\r\n\t\tp_cache_entry->mUsage=1;\r\n\t\tp_cache_entry->mScriptNameChecksum=scriptName;\r\n\t\t\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\t++m_num_used_scripts;\r\n\t\tif (m_num_used_scripts > m_max_used_scripts)\r\n\t\t{\r\n\t\t\tm_max_used_scripts=m_num_used_scripts;\r\n\t\t}\t\r\n\t\t#endif\r\n\t\t\r\n\t\t\r\n\t\tmp_cache_hash_table->PutItem(scriptName,p_cache_entry);\r\n\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\t++mp_decompress_counts[m_current_decompress_count_index];\r\n\t\t#endif\r\n\t\t\r\n\t\treturn p_cache_entry->mpDecompressedScript;\r\n\t}\r\n\t\r\n\treturn NULL;\r\n}\r\n\r\nvoid CScriptCache::DecrementScriptUsage(uint32 scriptName)\r\n{\r\n\tCScriptCacheEntry *p_cache_entry=mp_cache_hash_table->GetItem(scriptName);\r\n\tif (p_cache_entry)\r\n\t{\r\n\t\tDbg_MsgAssert(p_cache_entry->mUsage,(\"Zero cache entry usage for script '%s'\",Script::FindChecksumName(scriptName)));\r\n\t\t\r\n\t\t--p_cache_entry->mUsage;\r\n\t\tif (p_cache_entry->mUsage==0)\r\n\t\t{\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t--m_num_used_scripts;\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tif (m_delete_zero_usage_straight_away)\r\n\t\t\t{\r\n\t\t\t\t// For testing\r\n\t\t\t\tdelete_entry(p_cache_entry);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tadd_to_zero_usage_list(p_cache_entry);\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n}\r\n\r\n// Needed for when a script is qbr'd.\r\nvoid CScriptCache::RefreshAfterReload(uint32 scriptName)\r\n{\r\n\tCScriptCacheEntry *p_cache_entry=mp_cache_hash_table->GetItem(scriptName);\r\n\tif (p_cache_entry)\r\n\t{\r\n\t\t// Store the old usage\r\n\t\tuint32 old_usage=p_cache_entry->mUsage;\r\n\t\t\r\n\t\t// Remove from the cache, then add it again so that it is up to date.\r\n\t\tdelete_entry(p_cache_entry);\r\n\t\tGetScript(scriptName);\r\n\t\t\r\n\t\t// Put the usage value back.\r\n\t\tp_cache_entry=mp_cache_hash_table->GetItem(scriptName);\r\n\t\tDbg_MsgAssert(p_cache_entry,(\"NULL p_cache_entry ?\"));\r\n\t\tp_cache_entry->mUsage=old_usage;\r\n\t}\t\r\n}\r\n\r\nvoid CScriptCache::DeleteZeroUsageStraightAway()\r\n{\r\n\tm_delete_zero_usage_straight_away=true;\r\n}\r\n\r\nvoid CScriptCache::DeleteOldestZeroUsageWhenNecessary()\r\n{\r\n\tm_delete_zero_usage_straight_away=false;\r\n}\r\n\r\n// Scans through the currently decompressed scripts looking to see\r\n// which one p_token points into, and returns the name of the script, or Unknown\r\n// if it can;t find it.\r\nconst char *CScriptCache::GetSourceFile(uint8 *p_token)\r\n{\r\n\tmp_cache_hash_table->IterateStart();\r\n\tCScriptCacheEntry *p_cache_entry = mp_cache_hash_table->IterateNext();\r\n\twhile (p_cache_entry)\r\n\t{\r\n\t\tif (PointsIntoScript(p_token,p_cache_entry->mpDecompressedScript))\r\n\t\t{\r\n\t\t    CSymbolTableEntry *p_entry=Resolve(p_cache_entry->mScriptNameChecksum);\r\n\t\t\tDbg_MsgAssert(p_entry,(\"Eh? Decompressed script has no source symbol table entry ?\"));\r\n\t\t\treturn Script::FindChecksumName(p_entry->mSourceFileNameChecksum);\r\n\t\t}\r\n\t\t\r\n\t\tp_cache_entry = mp_cache_hash_table->IterateNext();\t\t\r\n\t}\r\n\t\r\n\treturn \"Unknown\";\r\n}\r\n\r\n#ifdef __NOPT_ASSERT__\r\nvoid CScriptCache::s_logic_code ( const Tsk::Task< CScriptCache >& task )\r\n{\r\n\tCScriptCache&\tmdl = task.GetData();\r\n\tDbg_AssertType ( &task, Tsk::Task< CScriptCache > );\r\n\r\n\t++mdl.m_current_decompress_count_index;\r\n\tif (mdl.m_current_decompress_count_index >= MAX_DECOMPRESS_COUNTS)\r\n\t{\r\n\t\tmdl.m_current_decompress_count_index=0;\r\n\t}\t\r\n\tmdl.mp_decompress_counts[mdl.m_current_decompress_count_index]=0;\r\n}\r\n\r\nvoid CScriptCache::GetDebugInfo( Script::CStruct* p_info )\r\n{\r\n\tScript::CStruct *p_script_cache_info=new Script::CStruct;\r\n\t\r\n\tp_script_cache_info->AddInteger(CRCD(0xe8081c20,\"NumUsedScripts\"),m_num_used_scripts);\r\n\tp_script_cache_info->AddInteger(CRCD(0x746c6f5b,\"MaxUsedScripts\"),m_max_used_scripts);\r\n\t\r\n\tint max=0;\r\n\tint total=0;\r\n\tfor (int i=0; i<MAX_DECOMPRESS_COUNTS; ++i)\r\n\t{\r\n\t\tif (mp_decompress_counts[i] > max)\r\n\t\t{\r\n\t\t\tmax=mp_decompress_counts[i];\r\n\t\t}\r\n\t\ttotal+=mp_decompress_counts[i];\r\n\t}\t\r\n\tp_script_cache_info->AddInteger(CRCD(0xc5eb1eb2,\"MaxDecompressCount\"),max);\r\n\tp_script_cache_info->AddInteger(CRCD(0xdd84ffd8,\"AverageDecompressCount\"),total/MAX_DECOMPRESS_COUNTS);\r\n\t\r\n\tmp_cache_hash_table->IterateStart();\r\n\tint num_scripts_in_cache=0;\r\n\tCScriptCacheEntry *p_cache_entry = mp_cache_hash_table->IterateNext();\r\n\twhile (p_cache_entry)\r\n\t{\r\n\t\t++num_scripts_in_cache;\r\n\t\tp_cache_entry = mp_cache_hash_table->IterateNext();\t\t\r\n\t}\r\n\r\n\tp_script_cache_info->AddInteger(CRCD(0xb6d1536,\"NumScriptsInCache\"),num_scripts_in_cache);\r\n\r\n\tif (num_scripts_in_cache)\r\n\t{\r\n\t\tScript::CArray *p_scripts_array=new Script::CArray;\r\n\t\tp_scripts_array->SetSizeAndType(num_scripts_in_cache,ESYMBOLTYPE_STRUCTURE);\r\n\t\t\r\n\t\tint alloc_total=0;\r\n\t\tmp_cache_hash_table->IterateStart();\r\n\t\tint array_index=0;\r\n\t\tp_cache_entry = mp_cache_hash_table->IterateNext();\r\n\t\twhile (p_cache_entry)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_cache_entry_info=new Script::CStruct;\r\n\t\t\tp_cache_entry_info->AddChecksum(CRCD(0xe37e78c5,\"Script\"),p_cache_entry->mScriptNameChecksum);\r\n\t\t\tp_cache_entry_info->AddInteger(CRCD(0x2f14a18f,\"Usage\"),p_cache_entry->mUsage);\r\n\t\t\t\r\n\t\t\tint alloc_size=Mem::GetAllocSize(p_cache_entry->mpDecompressedScript);\r\n\t\t\tp_cache_entry_info->AddInteger(CRCD(0x454a3b10,\"ScriptSize\"),alloc_size);\r\n\t\t\talloc_total+=alloc_size;\r\n\t\t\t\r\n\t\t\tp_scripts_array->SetStructure(array_index,p_cache_entry_info);\r\n\t\t\tp_cache_entry = mp_cache_hash_table->IterateNext();\t\t\r\n\t\t\t++array_index;\r\n\t\t}\r\n\t\t\r\n\t\tp_script_cache_info->AddInteger(CRCD(0x43dde78c,\"TotalScriptSizes\"),alloc_total);\r\n\t\tp_script_cache_info->AddArrayPointer(CRCD(0xf964b9dd,\"CachedScripts\"),p_scripts_array);\r\n\t}\r\n\t\t\r\n\tp_info->AddStructurePointer(CRCD(0x3d2bde05,\"ScriptCacheInfo\"),p_script_cache_info);\r\n}\r\n#endif // #ifdef __NOPT_ASSERT__\r\n\r\n#endif // #ifdef NO_SCRIPT_CACHING\r\n\r\n} // namespace Script\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/scriptcache.h",
    "content": "#ifndef\t__SCRIPTING_SCRIPTCACHE_H\r\n#define\t__SCRIPTING_SCRIPTCACHE_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __SYS_MEM_POOLABLE_H\r\n#include <sys/mem/poolable.h>\r\n#endif\r\n\r\n#ifndef __CORE_LIST_HASHTABLE_H\r\n#include <core/hashtable.h>\r\n#endif\r\n\r\n#ifndef __GEL_MODULE_H\r\n#include <gel/module.h>\r\n#endif\r\n\r\n// If this is defined then GetScript will just return the mpScript as stored in the\r\n// CSymbolTableEntry.\r\n#ifdef __PLAT_WN32__\r\n// No caching when compiled on PC since it is not needed and would require linking in memory manager stuff.\r\n#define NO_SCRIPT_CACHING\r\n#endif\r\n//#define NO_SCRIPT_CACHING\r\n\r\n// The total size of the CScriptCacheEntry pool.\r\n// This is the max number of decompressed scripts that can exist at once.\r\n// The code will assert if this number of scripts is exceeded.\r\n// This may be set to be quite large since the CScriptCacheEntry is quite small, 24 bytes each.\r\n// It needs to be fairly large to allow for spikes in the number of scripts executing (see TT1417)\r\n#define MAX_DECOMPRESSED_SCRIPTS 300\r\n\r\n// The code will attempt to keep the total number of decompressed scripts to no more than this value\r\n// by deleting unused scripts.\r\n// This allows us to control the average number of decompressed scripts whilst still allowing spikes\r\n// up to MAX_DECOMPRESSED_SCRIPTS without the code asserting.\r\n// Allowing spikes is necessary because sometimes a lot of scripts may exist which don't use up much\r\n// script heap altogether.\r\n\r\n// The larger IDEAL_MAX_DECOMPRESSED_SCRIPTS is, the less often the code will have to\r\n// decompress scripts during gameplay, hence less cpu time will be used.\r\n// However, the bigger it is, the more script heap will be used up storing decompressed scripts.\r\n#define IDEAL_MAX_DECOMPRESSED_SCRIPTS 100\r\n\r\nnamespace Script\r\n{\r\nclass CStruct;\r\n\r\n#ifdef NO_SCRIPT_CACHING\r\n#else\r\nclass CScriptCacheEntry : public Mem::CPoolable<CScriptCacheEntry>\r\n{\r\npublic:\r\n\tCScriptCacheEntry();\r\n\t~CScriptCacheEntry();\r\n\r\n\t// The script name is stored here so that the make_enough_space function\r\n\t// is able to flush entries from the hash table, given only a CScriptCacheEntry pointer.\r\n\t// (Entries can only be flushed from the hash table if their key is known)\r\n\tuint32 mScriptNameChecksum;\r\n\t\r\n\tuint8 *mpDecompressedScript;\r\n\tuint32 mUsage;\r\n\t\r\n\tCScriptCacheEntry *mpNext;\r\n\tCScriptCacheEntry *mpPrevious;\r\n};\r\n#endif // #ifdef NO_SCRIPT_CACHING\r\n\r\n#ifdef NO_SCRIPT_CACHING\r\nclass CScriptCache   // No deriving it from Mdl::Module if not usieng it, as that foces uncessary linkages\r\n#else\r\nclass CScriptCache  : public Mdl::Module\r\n#endif\r\n{\r\n\tDeclareSingletonClass( CScriptCache );\r\n\t\r\n\tvoid v_start_cb ( void );\r\n\tvoid v_stop_cb ( void );\r\n\r\n\t#ifdef NO_SCRIPT_CACHING\r\n\t#else\r\n\r\n\tvoid add_to_zero_usage_list(CScriptCacheEntry *p_entry);\r\n\tvoid remove_from_zero_usage_list(CScriptCacheEntry *p_entry);\r\n\tvoid delete_entry(CScriptCacheEntry *p_entry);\r\n\tvoid remove_some_old_scripts(int space_required, uint32 scriptName);\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tstatic Tsk::Task< CScriptCache >::Code s_logic_code;       \r\n\tTsk::Task< CScriptCache > *mp_logic_task;\r\n\t\r\n\tenum\r\n\t{\r\n\t\tMAX_DECOMPRESS_COUNTS=60\r\n\t};\t\r\n\tint mp_decompress_counts[MAX_DECOMPRESS_COUNTS];\r\n\tint m_current_decompress_count_index;\r\n\t\r\n\tint m_num_used_scripts; // A count of how many script entries have a usage > 0\r\n\tint m_max_used_scripts; // The max value that the above reached, used for choosing a suitable MAX_DECOMPRESSED_SCRIPTS\r\n\t#endif\r\n\t\r\n\tLst::HashTable<CScriptCacheEntry> *mp_cache_hash_table;\r\n\t\r\n\t// Points to the first (youngest) of the zero-usage entries.\r\n\tCScriptCacheEntry *mp_first_zero_usage;\r\n\t// Points to the last (oldest) of the zero-usage entries.\r\n\tCScriptCacheEntry *mp_last_zero_usage;\r\n\t\r\n\tbool m_delete_zero_usage_straight_away;\r\n\r\n\t#endif // #ifdef NO_SCRIPT_CACHING\r\npublic:\r\n\tCScriptCache();\r\n\tvirtual\t~CScriptCache();\r\n\r\n\tuint8 *GetScript(uint32 scriptName);\r\n\tvoid DecrementScriptUsage(uint32 scriptName);\r\n\tvoid RefreshAfterReload(uint32 scriptName);\r\n\r\n\tvoid DeleteZeroUsageStraightAway();\r\n\tvoid DeleteOldestZeroUsageWhenNecessary();\r\n\r\n\t#ifdef NO_SCRIPT_CACHING\r\n\t#else\r\n\tconst char *GetSourceFile(uint8 *p_token);\r\n\t#endif\r\n\t\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tvoid GetDebugInfo( Script::CStruct* p_info );\r\n\t#endif\r\n};\r\n\t\r\n} // namespace Script\r\n\r\n#endif // #ifndef\t__SCRIPTING_SCRIPTCACHE_H\r\n"
  },
  {
    "path": "Code/Gel/Scripting/scriptdefs.h",
    "content": "#ifndef\t__SCRIPTING_SCRIPTDEFS_H\r\n#define\t__SCRIPTING_SCRIPTDEFS_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n// A checksum of 0, used to represent no-name.    \r\n#define NO_NAME ((uint32)0)\r\n\r\nenum EAssertType\r\n{\r\n\tNO_ASSERT=0,\r\n\tASSERT\r\n};\r\n\r\nenum EBoolAssertIfDuplicateSymbols\r\n{\r\n\tNO_ASSERT_IF_DUPLICATE_SYMBOLS=0,\r\n\tASSERT_IF_DUPLICATE_SYMBOLS\r\n};\r\n\t\r\n// So that the old code still compiles without having to change a million things.\r\n#define CScriptStructure CStruct\r\n#define SPair CPair\r\n#define NONAME NO_NAME\r\n\r\n} // namespace Script\r\n\r\n#endif // #ifndef\t__SCRIPTING_SCRIPTDEFS_H\r\n"
  },
  {
    "path": "Code/Gel/Scripting/skiptoken.cpp",
    "content": "// Definition of the SkipToken function.\r\n// This can be #included in the game code, and in PC utilities.\r\n// It is in this file so that only this file needs to be updated when SkipToken\r\n// needs to be modified.\r\n\r\n// If included in PC code, then uint8 and Dbg_MsgAssert will need to be defined.\r\n\r\n\t\t\t\t\t\t\t\t   \r\n// Returns a pointer to the next token after p_token.\r\n// It won't necessarily skip over the complete format of the data that is expected\r\n// to follow, it will just skip over enough that it returns a pointer to a token again.\r\n// For example, ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE must be followed by a ESCRIPTTOKEN_PAIR,\r\n// but SkipToken will not check for that and skip over the pair token too, it will just skip over the\r\n// RANDOM_RANGE token and return a pointer to the ESCRIPTTOKEN_PAIR\r\n// So if SkipToken is passed a pointer to a token, it is guaranteed to return a pointer to token, namely\r\n// the nearest next one.\r\nuint8 *SkipToken(uint8 *p_token)\r\n{\r\n    switch (*p_token)\r\n    {\r\n        case ESCRIPTTOKEN_ENDOFFILE:\r\n            Dbg_MsgAssert(0,(\"Tried to skip past EndOfFile token\"));\r\n            break;\r\n\t    case ESCRIPTTOKEN_ENDOFLINE:\r\n        case ESCRIPTTOKEN_EQUALS:\r\n        case ESCRIPTTOKEN_DOT:\r\n        case ESCRIPTTOKEN_COMMA:\r\n        case ESCRIPTTOKEN_MINUS:\r\n        case ESCRIPTTOKEN_ADD:\r\n        case ESCRIPTTOKEN_DIVIDE:\r\n        case ESCRIPTTOKEN_MULTIPLY:\r\n        case ESCRIPTTOKEN_OPENPARENTH:\r\n        case ESCRIPTTOKEN_CLOSEPARENTH:\r\n        case ESCRIPTTOKEN_SAMEAS:\r\n        case ESCRIPTTOKEN_LESSTHAN:\r\n        case ESCRIPTTOKEN_LESSTHANEQUAL:\r\n        case ESCRIPTTOKEN_GREATERTHAN:\r\n        case ESCRIPTTOKEN_GREATERTHANEQUAL:\r\n        case ESCRIPTTOKEN_STARTSTRUCT:\r\n        case ESCRIPTTOKEN_STARTARRAY:\r\n        case ESCRIPTTOKEN_ENDSTRUCT:\r\n        case ESCRIPTTOKEN_ENDARRAY:\r\n        case ESCRIPTTOKEN_KEYWORD_BEGIN:\r\n        case ESCRIPTTOKEN_KEYWORD_REPEAT:\r\n        case ESCRIPTTOKEN_KEYWORD_BREAK:\r\n        case ESCRIPTTOKEN_KEYWORD_SCRIPT:\r\n        case ESCRIPTTOKEN_KEYWORD_ENDSCRIPT:\r\n        case ESCRIPTTOKEN_KEYWORD_IF:\r\n        case ESCRIPTTOKEN_KEYWORD_ELSE:\r\n        case ESCRIPTTOKEN_KEYWORD_ELSEIF:\r\n        case ESCRIPTTOKEN_KEYWORD_ENDIF:\r\n        case ESCRIPTTOKEN_KEYWORD_RETURN:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ALLARGS:\r\n\t\tcase ESCRIPTTOKEN_ARG:\r\n\t\tcase ESCRIPTTOKEN_OR:\r\n\t\tcase ESCRIPTTOKEN_AND:\r\n\t\tcase ESCRIPTTOKEN_XOR:\r\n\t\tcase ESCRIPTTOKEN_SHIFT_LEFT:\r\n\t\tcase ESCRIPTTOKEN_SHIFT_RIGHT:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE2:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_NOT:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_AND:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_OR:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_SWITCH:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_ENDSWITCH:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_CASE:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_DEFAULT:\r\n\t\tcase ESCRIPTTOKEN_COLON:\r\n            ++p_token;\r\n\t\t\tbreak;\r\n            \r\n        case ESCRIPTTOKEN_NAME:\r\n        case ESCRIPTTOKEN_INTEGER:\r\n        case ESCRIPTTOKEN_HEXINTEGER:\r\n        case ESCRIPTTOKEN_FLOAT:\r\n\t    case ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\tcase ESCRIPTTOKEN_JUMP:\r\n\t\tcase ESCRIPTTOKEN_RUNTIME_MEMBERFUNCTION:\r\n\t\tcase ESCRIPTTOKEN_RUNTIME_CFUNCTION:\r\n\t\t\tp_token+=5;\r\n            break;\r\n        case ESCRIPTTOKEN_VECTOR:\r\n            p_token+=13;\r\n            break;\r\n        case ESCRIPTTOKEN_PAIR:\r\n            p_token+=9;\r\n            break;\r\n\t    case ESCRIPTTOKEN_STRING:\r\n        case ESCRIPTTOKEN_LOCALSTRING:\r\n\t\t{\r\n            ++p_token;\r\n\t\t\tuint32 num_bytes=*p_token++;\r\n\t\t\tnum_bytes+=(*p_token++)<<8;\r\n\t\t\tnum_bytes+=(*p_token++)<<16;\r\n\t\t\tnum_bytes+=(*p_token++)<<24;\r\n            p_token+=num_bytes;\r\n            break;\r\n\t\t}\t\r\n\t\tcase ESCRIPTTOKEN_CHECKSUM_NAME: \r\n\t\t\t// Skip over the token and checksum.\r\n\t\t\tp_token+=5;\r\n\t\t\t// Skip over the string.\r\n\t\t\twhile (*p_token)\r\n\t\t\t{\r\n\t\t\t\t++p_token;\r\n\t\t\t}\r\n\t\t\t// Skip over the terminator.\r\n\t\t\t++p_token;\t\r\n\t\t\tbreak;\t\t\t\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM2:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_NO_REPEAT:\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_PERMUTE:\r\n\t\t{\r\n            ++p_token;\r\n\t\t\t\r\n\t\t\tuint32 num_jumps=*p_token++;\r\n\t\t\tnum_jumps+=(*p_token++)<<8;\r\n\t\t\tnum_jumps+=(*p_token++)<<16;\r\n\t\t\tnum_jumps+=(*p_token++)<<24;\r\n\t\t\t\r\n\t\t\t// Skip over all the weight & jump offsets.\r\n\t\t\tp_token+=2*num_jumps+4*num_jumps;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        default:\r\n            Dbg_MsgAssert(0,(\"Unrecognized script token sent to SkipToken()\"));\r\n            break;\r\n    }\r\n    return p_token;\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/string.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// string.cpp\t\tKSH 17 Oct 2001\r\n//\r\n// Code for managing allocation and deallocation of strings within the script system.\r\n// For example it manages the 'permanent string' heap, which is for strings that get created\r\n// when all the qb's are loaded and never get deleted. They can therefore all be squashed\r\n// together for optimum use of memory.\r\n//\r\n// Note: Not defining a CString class, because it would have to have a char pointer so\r\n// would just be an unneccessary layer of indirection that would waste space.\r\n//\r\n// Instead CreateString and DeleteString are used to allocate and deallocate strings.\r\n//\r\n// Could add cleverer memory management here later, eg a pool of fixed sized strings\r\n// for strings that need to be alloc'd and dealloc'd fast.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n// Note: Small memory saving possible by deleting the sp_permanent_string_checksums array\r\n// once you know that no more permanent strings will need to be allocated. Will save 32K ish,\r\n// depending on maxStrings.\r\n// (There's no function here yet for doing that, but easy to add)\r\n\r\n#include <gel/scripting/string.h>\r\n#ifndef __CORE_CRC_H\r\n#include <core/crc.h>\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\r\nstatic char *sAddToSpecialStringHeap(const char *p_string);\r\n\r\nstatic bool s_use_permanent_string_heap=false;\r\n\r\n// The permanent string buffer.\r\nstatic char *sp_permanent_string_heap=NULL;\r\nstatic char *sp_permanent_string_heap_top=NULL;\r\nstatic uint32 s_permanent_string_heap_size=0;\r\n\r\n// Array of string checksums to allow quick checking to see if a particular string\r\n// is already in the permanent string buffer without having to do string comparisons.\r\n// Needed because when loading several thousand strings, several million string comparisons\r\n// would have to be done, causing a significant pause in loading the game.\r\nstruct SSpecialStringChecksum\r\n{\r\n\tuint32 mChecksum;\r\n\tchar *mpString;\r\n};\r\nstatic SSpecialStringChecksum *sp_permanent_string_checksums=NULL;\r\nstatic uint32 s_num_permanent_string_checksums=0;\r\nstatic uint32 s_max_permanent_string_checksums=0;\r\n\r\n// Needs to be called once at the start of the game.\r\n// For THPS3, maxSize was 48000 for English, 60500 for other languages. maxStrings was 4000\r\nvoid AllocatePermanentStringHeap(uint32 maxSize, uint32 maxStrings)\r\n{\r\n\t// Uses whatever the current heap is set to, which is set to the script heap in Script::AllocatePools\r\n\t// which is where this function is called from.\r\n\ts_permanent_string_heap_size=maxSize;\r\n\ts_max_permanent_string_checksums=maxStrings;\r\n\t\r\n\t// Allocate the string buffer.\r\n\tDbg_MsgAssert(sp_permanent_string_heap==NULL,(\"sp_permanent_string_heap not NULL ???\"));\r\n\tsp_permanent_string_heap=(char*)Mem::Malloc(s_permanent_string_heap_size);\r\n\tsp_permanent_string_heap_top=sp_permanent_string_heap;\r\n\t\r\n\t// Allocate the array of checksums.\r\n\tDbg_MsgAssert(sp_permanent_string_checksums==NULL,(\"sp_permanent_string_checksums not NULL ???\"));\r\n\tsp_permanent_string_checksums=(SSpecialStringChecksum*)Mem::Malloc(s_max_permanent_string_checksums*sizeof(SSpecialStringChecksum));\r\n\ts_num_permanent_string_checksums=0;\r\n}\r\n\r\nvoid DeallocatePermanentStringHeap()\r\n{\r\n\t// Deallocate the string buffer.\r\n\tDbg_MsgAssert(sp_permanent_string_heap,(\"NULL sp_permanent_string_heap ?\"));\r\n\tMem::Free(sp_permanent_string_heap);\r\n\tsp_permanent_string_heap=NULL;\r\n\tsp_permanent_string_heap_top=NULL;\r\n\ts_permanent_string_heap_size=0;\r\n\t\r\n\t// Deallocate the array of checksums.\r\n\t// MEMOPT: TODO: Destroy this when UseRegularStringHeap is called too, to free up memory ?\r\n\tDbg_MsgAssert(sp_permanent_string_checksums,(\"NULL sp_permanent_string_checksums ?\"));\r\n\tMem::Free(sp_permanent_string_checksums);\r\n\tsp_permanent_string_checksums=NULL;\r\n\ts_num_permanent_string_checksums=0;\r\n\ts_max_permanent_string_checksums=0;\r\n}\r\n\r\n// Adds the contents of the passed pString to the special string heap, and returns\r\n// the pointer to the string within the heap.\r\n// If the string is already found in the heap, it won't add it again.\r\nstatic char *sAddToSpecialStringHeap(const char *p_string)\r\n{\r\n\tDbg_MsgAssert(p_string,(\"NULL p_string\"));\r\n\r\n\t// Check to see if it already exists in the special string heap ...\r\n\r\n\t// Calculate the checksum of the string, then search for this in the array of\r\n\t// checksums of all the special strings so far.\r\n\t// Quicker than doing byte comparisons, probably due to the long time it takes to\r\n\t// read single bytes from memory.\r\n\t// Needs to be fast, otherwise it can add a significant delay to the startup time.\r\n\t// This method adds about 0.3 seconds altogether (in THPS3, couple of thousand strings)\r\n\tuint32 len=strlen(p_string);\r\n\tuint32 checksum=Crc::GenerateCRCCaseSensitive(p_string,len);\r\n\t\r\n\tDbg_MsgAssert(sp_permanent_string_checksums,(\"NULL sp_permanent_string_checksums ??\"));\r\n\tSSpecialStringChecksum *p_ch=sp_permanent_string_checksums;\r\n\tfor (uint32 i=0; i<s_num_permanent_string_checksums; ++i)\r\n\t{\r\n\t\tif (p_ch->mChecksum==checksum)\r\n\t\t{\r\n\t\t\treturn p_ch->mpString;\r\n\t\t}\r\n\t\t++p_ch;\r\n\t}\t\t\r\n\r\n\tchar *p_heap_string=NULL;\r\n\t\r\n\t// Not found, so add to the pile of strings.\r\n\tDbg_MsgAssert(sp_permanent_string_heap,(\"NULL sp_permanent_string_heap ??\"));\r\n\t\r\n\tDbg_MsgAssert(s_permanent_string_heap_size-(sp_permanent_string_heap_top-sp_permanent_string_heap)>=len+1,(\"Out of special string heap\"));\r\n\tp_heap_string=sp_permanent_string_heap_top;\r\n\tstrcpy(p_heap_string,p_string);\r\n\t// Update sp_permanent_string_heap_top\r\n\tsp_permanent_string_heap_top+=len;\r\n\t++sp_permanent_string_heap_top; // Skip over the terminator\r\n\r\n\t// Store the checksum too.\r\n\tDbg_MsgAssert(s_num_permanent_string_checksums<s_max_permanent_string_checksums,(\"Ran out of permanent-string checksums\"));\r\n\tsp_permanent_string_checksums[s_num_permanent_string_checksums].mChecksum=checksum;\r\n\tsp_permanent_string_checksums[s_num_permanent_string_checksums].mpString=p_heap_string;\r\n\t++s_num_permanent_string_checksums;\r\n\t\r\n\treturn p_heap_string;\r\n}\r\n\r\nvoid UsePermanentStringHeap()\r\n{\r\n\ts_use_permanent_string_heap=true;\r\n}\r\n\r\nvoid UseRegularStringHeap()\r\n{\r\n\ts_use_permanent_string_heap=false;\r\n\r\n\t// 56K memory saving, though this assumes that UsePermanentStringHeap() won't be called\r\n\t// again after UseRegularStringHeap(). If it is, the code will assert as soon as a string\r\n\t// is attempted to be created.\r\n\t// The current code does not use the permanent string heap again, so use the savings.\r\n\t// (End of THPS6 and memory is tight)\r\n\tif (sp_permanent_string_checksums)\r\n\t{\r\n\t\tMem::Free(sp_permanent_string_checksums);\r\n\t\tsp_permanent_string_checksums=NULL;\r\n\t}\t\r\n}\r\n\r\n// Allocates space for the passed string and copies it in, and returns a pointer to the new string,\r\n// so the original string can safely be deleted.\r\n// I guess this should really return a const char*, but if it did then DeleteString would\r\n// have to take a const char* too, and it can't because then it would not be able to call\r\n// Mem::Free on it.\r\nchar *CreateString(const char *p_string)\r\n{\r\n\tDbg_MsgAssert(p_string,(\"NULL p_string\"));\r\n\t\r\n\tif (s_use_permanent_string_heap)\r\n\t{\r\n\t\treturn sAddToSpecialStringHeap(p_string);\r\n\t}\r\n\r\n\t// Just do a regular allocation.\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\r\n\tchar *p_new_string=(char*)Mem::Malloc(strlen(p_string)+1); // +1 for terminator\r\n\tstrcpy(p_new_string,p_string);\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\treturn p_new_string;\r\n}\r\n\r\nvoid DeleteString(char *p_string)\r\n{\r\n\tDbg_MsgAssert(p_string,(\"NULL p_string\"));\r\n\r\n\t// Check whether the string is in the permanent-string buffer.\r\n\tDbg_MsgAssert(sp_permanent_string_heap,(\"NULL sp_permanent_string_heap ?\"));\r\n\tif (p_string>=sp_permanent_string_heap && p_string<sp_permanent_string_heap+s_permanent_string_heap_size)\r\n\t{\r\n\t\t// It is in the permanent-string buffer, so nothing to do.\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Must have been allocated the usual way, so free it.\r\n\t\tMem::Free(p_string);\r\n\t}\r\n}\r\n\r\n/*\r\n#ifdef __NOPT_ASSERT__\r\nconst char *FindPermanentStringWithChecksum(uint32 ch)\r\n{\r\n\tconst char *p_string=sp_permanent_string_heap;\r\n\twhile (p_string < sp_permanent_string_heap_top)\r\n\t{\r\n\t\t//printf(\"%s\\n\",p_string);\r\n\t\tif (Crc::GenerateCRCFromString(p_string) == ch)\r\n\t\t{\r\n\t\t\treturn p_string;\r\n\t\t}\r\n\t\tp_string=p_string+strlen(p_string)+1; // +1 for the terminating 0\r\n\t}\r\n\treturn NULL;\r\n}\r\n#endif\r\n*/\r\n\t\r\n// Mick's script strings\r\n#define\tMAX_SCRIPT_STRING\t\t1\r\n#define\tSCRIPT_STRING_LENGTH \t128\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\nstatic char sp_script_string[MAX_SCRIPT_STRING][SCRIPT_STRING_LENGTH]={{0}};\r\n\r\n// given a string\r\nvoid SetScriptString(uint32 n, const char *p_string)\r\n{\r\n\tDbg_MsgAssert(n<MAX_SCRIPT_STRING,(\"Bad index of %d sent to SetScriptString, MAX_SCRIPT_STRING=%d\",n,MAX_SCRIPT_STRING));\r\n\tDbg_MsgAssert(p_string,(\"NULL p_string\"));\r\n\t\r\n\tsprintf (sp_script_string[n],p_string);\t\r\n\tDbg_MsgAssert(strlen(sp_script_string[n])<SCRIPT_STRING_LENGTH,(\"Script String %d too big\\n%s\",n,sp_script_string[n]));\r\n}\r\n\r\nchar* GetScriptString(uint32 n)\r\n{\r\n\tDbg_MsgAssert(n<MAX_SCRIPT_STRING,(\"Bad index of %d sent to GetScriptString, MAX_SCRIPT_STRING=%d\",n,MAX_SCRIPT_STRING));\r\n\t\r\n\tDbg_MsgAssert(strlen(sp_script_string[n])<SCRIPT_STRING_LENGTH,(\"Script String %d too big\\n%s\",n,sp_script_string[n]));\r\n\treturn sp_script_string[n];\r\n}\r\n\r\n\r\n} // namespace Script\r\n"
  },
  {
    "path": "Code/Gel/Scripting/string.h",
    "content": "#ifndef\t__SCRIPTING_STRING_H\r\n#define\t__SCRIPTING_STRING_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\r\nvoid AllocatePermanentStringHeap(uint32 maxSize, uint32 maxStrings);\r\nvoid DeallocatePermanentStringHeap();\r\n\r\nvoid UsePermanentStringHeap();\r\nvoid UseRegularStringHeap();\r\n\t\r\nchar *CreateString(const char *p_string);\r\nvoid DeleteString(char *p_string);\r\n\r\nvoid SetScriptString(uint32 n, const char *p_string);\r\nchar* GetScriptString(uint32 n);\r\n\r\n} // namespace Script\r\n\r\n#endif // #ifndef\t__SCRIPTING_STRING_H\r\n"
  },
  {
    "path": "Code/Gel/Scripting/struct.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// struct.cpp\t\tKSH 22 Oct 2001\r\n//\r\n// CStruct class member functions.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/string.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <core/crc.h>\r\n#include <core/math.h>\r\n#include <core/math/vector.h>\r\n\r\n\t\t\t\t\t\t\t \r\n//#define\t__DEBUG_STRUCT_ALLOCS\r\n\t\t\t\t\t\t\t \r\n// This does technically cause a cyclic dependency, but what the heck, it's only needed\r\n// for some debugging. (Making the Get function print the contents of the struct in\r\n// the event of not finding the required parameter)\r\n#include <gel/scripting/utils.h>\r\n\r\nDefinePoolableClass(Script::CStruct);\r\n\r\nnamespace Script\r\n{\r\n\r\n#ifdef\t__DEBUG_STRUCT_ALLOCS\r\n#define\tMAX_LAST\t200\r\nstatic int head = 0;\r\nstatic bool init_last = true;\r\nstatic CStruct * last[MAX_LAST];\r\n#endif\r\n\r\nvoid DumpLastStructs()\r\n{\r\n#ifdef\t__DEBUG_STRUCT_ALLOCS\r\n\tfor (int i=0;i<MAX_LAST;i++)\r\n\t{\r\n\t\tif (last[i])\r\n\t\t{\r\n\t\t\tprintf (\"Final Structure %d\\n\",i);\r\n\t\t\tPrintContents(last[i]);\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\n\r\n// Deletes any entity pointed to by p_comp, so that p_comp can safely be deleted afterwards.\r\nvoid CleanUpComponent(CComponent *p_comp)\r\n{\r\n\tDbg_MsgAssert(p_comp,(\"NULL p_comp\"));\r\n\t\r\n\tswitch (p_comp->mType)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_STRING:\r\n\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\tif (p_comp->mpString)\r\n\t\t\t{\r\n\t\t\t\tDeleteString(p_comp->mpString);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\tif (p_comp->mpPair)\r\n\t\t\t{\r\n\t\t\t\tdelete p_comp->mpPair;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\tif (p_comp->mpVector)\r\n\t\t\t{\r\n\t\t\t\tdelete p_comp->mpVector;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t\tif (p_comp->mpStructure)\r\n\t\t\t{\r\n\t\t\t\tdelete p_comp->mpStructure;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t\tif (p_comp->mpArray)\r\n\t\t\t{\r\n\t\t\t\tCleanUpArray(p_comp->mpArray);\r\n\t\t\t\tdelete p_comp->mpArray;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_QSCRIPT:\r\n            if (p_comp->mpScript)\r\n\t\t\t{\r\n\t\t\t\tMem::Free(p_comp->mpScript);\r\n\t\t\t}\r\n\t\t\tp_comp->mScriptSize=0;\r\n\t\t\tbreak;\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\r\n\t// This will zero the union, which includes all the above pointers.\r\n\tp_comp->mUnion=0;\r\n\t\r\n\tp_comp->mType=ESYMBOLTYPE_NONE;\r\n}\r\n\r\n// Copies the contents of p_source into p_dest, but without copying any pointers over.\r\n// Eg, if p_source contains an array, a new array will be created for p_dest.\r\nvoid CopyComponent(CComponent *p_dest, const CComponent *p_source)\r\n{\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest\"));\r\n\tDbg_MsgAssert(p_source,(\"NULL p_source\"));\r\n\r\n\t// Make sure p_dest is cleaned up first.\t\r\n\tif (p_dest->mUnion) // This 'if' is just a small speed optimization to avoid an unnecessay call\r\n\t{\r\n\t\tCleanUpComponent(p_dest);\r\n\t}\t\r\n\t\r\n\tp_dest->mType=p_source->mType;\r\n\tp_dest->mNameChecksum=p_source->mNameChecksum;\r\n\t\r\n\tswitch (p_source->mType)\r\n\t{\r\n\tcase ESYMBOLTYPE_NONE:\r\n\t\tbreak;\r\n\t\t\r\n    case ESYMBOLTYPE_INTEGER:\r\n    case ESYMBOLTYPE_FLOAT:\r\n\tcase ESYMBOLTYPE_NAME:\r\n\t\tp_dest->mUnion=p_source->mUnion;\r\n\t\tbreak;\r\n\t\t\r\n    case ESYMBOLTYPE_STRING:\r\n\t\tDbg_MsgAssert(p_source->mpString,(\"NULL p_source->mpString ?\"));\r\n\t\tp_dest->mpString=CreateString(p_source->mpString);\r\n\t\tbreak;\r\n\t\t\r\n    case ESYMBOLTYPE_LOCALSTRING:\r\n\t\tDbg_MsgAssert(p_source->mpLocalString,(\"NULL p_source->mpLocalString ?\"));\r\n\t\tp_dest->mpLocalString=CreateString(p_source->mpLocalString);\r\n\t\tbreak;\r\n\t\t\r\n    case ESYMBOLTYPE_PAIR:\r\n\t\tDbg_MsgAssert(p_source->mpPair,(\"NULL p_source->mpPair ?\"));\r\n\t\tp_dest->mpPair=new CPair;\r\n\t\tp_dest->mpPair->mX=p_source->mpPair->mX;\r\n\t\tp_dest->mpPair->mY=p_source->mpPair->mY;\r\n\t\tbreak;\r\n\t\t\r\n    case ESYMBOLTYPE_VECTOR:\r\n\t\tDbg_MsgAssert(p_source->mpVector,(\"NULL p_source->mpVector ?\"));\r\n\t\tp_dest->mpVector=new CVector;\r\n\t\tp_dest->mpVector->mX=p_source->mpVector->mX;\r\n\t\tp_dest->mpVector->mY=p_source->mpVector->mY;\r\n\t\tp_dest->mpVector->mZ=p_source->mpVector->mZ;\r\n\t\tbreak;\r\n\t\t\r\n    case ESYMBOLTYPE_STRUCTURE:\r\n\t\tDbg_MsgAssert(p_source->mpStructure,(\"NULL p_source->mpStructure ?\"));\r\n\t\tp_dest->mpStructure=new CStruct;\r\n\t\t*p_dest->mpStructure=*p_source->mpStructure;\r\n\t\tbreak;\r\n\t\t\r\n    case ESYMBOLTYPE_ARRAY:\r\n\t\tDbg_MsgAssert(p_source->mpArray,(\"NULL p_source->mpArray ?\"));\r\n\t\tp_dest->mpArray=new CArray;\r\n\t\tCopyArray(p_dest->mpArray,p_source->mpArray);\r\n\t\tbreak;\r\n\r\n\tcase ESYMBOLTYPE_QSCRIPT:\r\n\t{\r\n\t\tDbg_MsgAssert(p_source->mpScript,(\"NULL p_source->mpScript ?\"));\r\n\t\t\r\n\t\t// Allocate a buffer off the script heap\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\tDbg_MsgAssert(p_source->mScriptSize,(\"Zero source script size\"));\r\n\t\tp_dest->mpScript=(uint8*)Mem::Malloc(p_source->mScriptSize);\r\n\t\tp_dest->mScriptSize=p_source->mScriptSize;\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\t// Copy the script into the new buffer.\r\n\t\tconst uint8 *p_from=p_source->mpScript;\r\n\t\tuint8 *p_to=p_dest->mpScript;\r\n\t\tfor (uint32 i=0; i<p_source->mScriptSize; ++i)\r\n\t\t{\r\n\t\t\t*p_to++=*p_from++;\r\n\t\t}\r\n\t\t\r\n\t\tbreak;\r\n\t}\r\n\t\t\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0,(\"Bad p_source->mType of '%s'\",GetTypeName(p_source->mType)));\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n// This will run through all the elements of p_array deleting any entities pointed to by it.\r\n// It will also call the array's Clear function to delete the array buffer, so it is not\r\n// necessary to call Clear again after calling this.\r\nvoid CleanUpArray(CArray *p_array)\r\n{\r\n\tDbg_MsgAssert(p_array,(\"NULL p_array\"));\r\n\t\r\n\tESymbolType type=p_array->GetType();\r\n\tuint32 size=p_array->GetSize();\r\n\tuint32 *p_array_data=p_array->GetArrayPointer();\r\n\tif (size)\r\n\t{\r\n\t\tDbg_MsgAssert(p_array_data,(\"NULL p_array_data ?\"));\r\n\t}\t\r\n\t\r\n\tswitch (type)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_NONE:\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t\t// Nothing to delete\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESYMBOLTYPE_STRING:\r\n\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t{\r\n\t\t\tchar **pp_string=(char**)p_array_data;\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (*pp_string)\r\n\t\t\t\t{\r\n\t\t\t\t\tDeleteString(*pp_string);\r\n\t\t\t\t\t*pp_string=NULL;\r\n\t\t\t\t}\r\n\t\t\t\t++pp_string;\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\t\r\n\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t{\r\n\t\t\tCPair **pp_pair=(CPair**)p_array_data;\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (*pp_pair)\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete *pp_pair;\r\n\t\t\t\t\t*pp_pair=NULL;\r\n\t\t\t\t}\r\n\t\t\t\t++pp_pair;\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t{\r\n\t\t\tCVector **pp_vector=(CVector**)p_array_data;\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (*pp_vector)\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete *pp_vector;\r\n\t\t\t\t\t*pp_vector=NULL;\r\n\t\t\t\t}\r\n\t\t\t\t++pp_vector;\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t{\r\n\t\t\tCStruct **pp_structure=(CStruct**)p_array_data;\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (*pp_structure)\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete *pp_structure;\r\n\t\t\t\t\t*pp_structure=NULL;\r\n\t\t\t\t}\r\n\t\t\t\t++pp_structure;\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t{\r\n\t\t\tCArray **pp_array=(CArray**)p_array_data;\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (*pp_array)\r\n\t\t\t\t{\r\n\t\t\t\t\tCleanUpArray(*pp_array);\r\n\t\t\t\t\tdelete *pp_array;\r\n\t\t\t\t\t*pp_array=NULL;\r\n\t\t\t\t}\r\n\t\t\t\t++pp_array;\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Bad CArray::m_type of '%s'\",GetTypeName(type)));\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\t\r\n\t// This will delete the actual array buffer too.\r\n\tp_array->Clear();\r\n}\r\n\r\n// Copies the contents of p_source into p_dest. No pointers will be copied over, new entities will be\r\n// created for p_dest. So p_source can safely be deleted afterwards.\r\nvoid CopyArray(CArray *p_dest, const CArray *p_source)\r\n{\r\n\tDbg_MsgAssert(p_source,(\"NULL p_source ?\"));\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest ?\"));\r\n\t\r\n\t// Make sure that p_dest is cleaned up first.\r\n\tCleanUpArray(p_dest);\r\n\t\t\r\n\tESymbolType type=p_source->GetType();\r\n\tuint32 size=p_source->GetSize();\r\n\t\r\n\tp_dest->SetSizeAndType(size,type);\r\n\r\n\tif (size==0)\r\n\t{\r\n\t\t// Finished.\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tuint32 *p_source_array=p_source->GetArrayPointer();\r\n\tDbg_MsgAssert(p_source_array,(\"NULL p_source_array ?\"));\r\n\t\r\n\tuint32 *p_dest_array=p_dest->GetArrayPointer();\r\n\tDbg_MsgAssert(p_dest_array,(\"NULL p_dest_array ?\"));\r\n\t\t\t\r\n\tswitch (type)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t{\r\n\t\t\tuint32 *p_source_word=p_source_array;\r\n\t\t\tuint32 *p_dest_word=p_dest_array;\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\t*p_dest_word++=*p_source_word++;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\t\r\n\t\tcase ESYMBOLTYPE_STRING:\r\n\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t{\r\n\t\t\tchar **pp_source_string=(char**)p_source_array;\r\n\t\t\tchar **pp_dest_string=(char**)p_dest_array;\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tchar *p_source_string=*pp_source_string;\r\n\t\t\t\tif (p_source_string)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Create a new copy of the source string.\r\n\t\t\t\t\t*pp_dest_string=CreateString(p_source_string);\r\n\t\t\t\t}\t\r\n\t\t\t\t++pp_source_string;\r\n\t\t\t\t++pp_dest_string;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\t\r\n\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t{\r\n\t\t\tCPair **pp_source_pair=(CPair**)p_source_array;\r\n\t\t\tCPair **pp_dest_pair=(CPair**)p_dest_array;\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCPair *p_source_pair=*pp_source_pair;\r\n\t\t\t\tif (p_source_pair)\r\n\t\t\t\t{\r\n\t\t\t\t\tCPair *p_new_pair=new CPair;\r\n\t\t\t\t\t// The default assignement operator works OK for CPair since it contains no pointers.\r\n\t\t\t\t\t*p_new_pair=*p_source_pair;\r\n\t\t\t\t\t*pp_dest_pair=p_new_pair;\r\n\t\t\t\t}\r\n\t\t\t\t++pp_source_pair;\r\n\t\t\t\t++pp_dest_pair;\r\n\t\t\t}\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\t\r\n\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t{\r\n\t\t\tCVector **pp_source_vector=(CVector**)p_source_array;\r\n\t\t\tCVector **pp_dest_vector=(CVector**)p_dest_array;\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCVector *p_source_vector=*pp_source_vector;\r\n\t\t\t\tif (p_source_vector)\r\n\t\t\t\t{\r\n\t\t\t\t\tCVector *p_new_vector=new CVector;\r\n\t\t\t\t\t// The default assignement operator works OK for CVector since it contains no pointers.\r\n\t\t\t\t\t*p_new_vector=*p_source_vector;\r\n\t\t\t\t\t*pp_dest_vector=p_new_vector;\r\n\t\t\t\t}\r\n\t\t\t\t++pp_source_vector;\r\n\t\t\t\t++pp_dest_vector;\r\n\t\t\t}\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t{\r\n\t\t\tCStruct **pp_source_structure=(CStruct**)p_source_array;\r\n\t\t\tCStruct **pp_dest_structure=(CStruct**)p_dest_array;\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCStruct *p_source_structure=*pp_source_structure;\r\n\t\t\t\tif (p_source_structure)\r\n\t\t\t\t{\r\n\t\t\t\t\tCStruct *p_new_structure=new CStruct;\r\n\t\t\t\t\t// Copy the contents using CStruct's assignement operator.\r\n\t\t\t\t\t*p_new_structure=*p_source_structure;\r\n\t\t\t\t\t*pp_dest_structure=p_new_structure;\r\n\t\t\t\t}\r\n\t\t\t\t++pp_source_structure;\r\n\t\t\t\t++pp_dest_structure;\r\n\t\t\t}\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t{\r\n\t\t\tCArray **pp_source_carray=(CArray**)p_source_array;\r\n\t\t\tCArray **pp_dest_carray=(CArray**)p_dest_array;\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCArray *p_source_carray=*pp_source_carray;\r\n\t\t\t\tif (p_source_carray)\r\n\t\t\t\t{\r\n\t\t\t\t\tCArray *p_new_carray=new CArray;\r\n\t\t\t\t\t// No assignement operator defined for CArray (cos it would cause cyclic dependencies) \r\n\t\t\t\t\t// so need to use CopyArray.\r\n\t\t\t\t\tCopyArray(p_new_carray,p_source_carray);\r\n\t\t\t\t\t*pp_dest_carray=p_new_carray;\r\n\t\t\t\t}\r\n\t\t\t\t++pp_source_carray;\r\n\t\t\t\t++pp_dest_carray;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Bad source array type of '%s'\",GetTypeName(type)));\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n\r\n\r\n// Initialises all the members.\r\nvoid CStruct::init()\r\n{\r\n\tmp_components=NULL;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__ \r\n\tmp_parent_script=NULL;\r\n\t#endif\r\n\t\r\n#ifdef\t__DEBUG_STRUCT_ALLOCS\r\n\tif (init_last)\r\n\t{\r\n\t\tfor (int i=0;i<MAX_LAST;i++)\r\n\t\t{\r\n\t\t\tlast[i] = NULL;\r\n\t\t}\r\n\t\thead = 0;\r\n\t\tinit_last = 0;\r\n\t}\r\n\t\r\n\tlast[head++] = this; \r\n\tif (head == MAX_LAST)\r\n\t\thead = 0;\r\n#endif\t\r\n}\r\n\r\n\r\n\r\n\r\nstatic int x = 0;\r\nstatic int max = 18000;\r\n\t\r\n// Usual constructor.\t\r\nCStruct::CStruct()\r\n{\r\n\t// Initialise everything. CStruct is not derived from CClass so we don't get\r\n\t// the auro-zeroing.\r\n\tinit();\r\n\r\n\t#if 0\r\n\t// For tracking down Struct leaks\r\n\t// when we go over a certain maximum, start printing out the callstack of the structs that take us over that max\t\r\n\tif (CStruct::SGetNumUsedItems()>max)\r\n\t{\r\n\t\tmax = CStruct::SGetNumUsedItems();\r\n\t\tDumpUnwindStack(20,0);\r\n\t}\r\n\t#endif\r\n}\r\n\r\n// Copy constructor.\r\nCStruct::CStruct( const CStruct& rhs )\r\n{\r\n\t// Initialise everything. CStruct is not derived from CClass so we don't get\r\n\t// the auro-zeroing.\r\n\tinit();\r\n\r\n\t// use the overridden assignment operator\r\n\t*this = rhs;\r\n\t\r\n\tx++;\r\n\tif (x>max)\r\n\t{\r\n\t\tmax = x;\r\n//\t\tDumpUnwindStack(20,0);\r\n\t}\r\n}\r\n\r\n// Assignement operator.\r\nCStruct& CStruct::operator=( const CStruct& rhs )\r\n{\r\n\t// don't try to assign to yourself\r\n\tif ( &rhs == this )\r\n\t{\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tthis->Clear();\r\n\t*this+=rhs;\r\n\r\n\treturn *this;\r\n}\r\n\r\n// This will merge the contents of the rhs into this structure.\r\n// Functionally the same as the old AppendStructure function, except AppendStructure would accept a NULL pointer.\r\nCStruct& CStruct::operator+=( const CStruct& rhs )\r\n{\r\n\tCComponent *p_source_component=rhs.mp_components;\r\n\twhile (p_source_component)\r\n\t{\r\n\t\tCComponent *p_new=new CComponent;\r\n\t\tCopyComponent(p_new, p_source_component);\r\n\t\tAddComponent(p_new);\r\n\t\tp_source_component=p_source_component->mpNext;\r\n\t}\t\r\n\treturn *this;\r\n}\r\n\r\n// TODO: Remove at some point. Provided for back-compatibility.\r\nvoid CStruct::AppendStructure(const CStruct *p_struct)\r\n{\r\n\tif (p_struct)\r\n\t{\r\n\t\t*this+=*p_struct;\r\n\t}\t\r\n}\r\n\r\n// Written specially for use by CScriptDebugger::transmit_cscript_list.\r\n// This will append the passed component to the structure's list of components\r\n// and will leave the existing list untouched, ie it will not remove any of the same name.\r\n// This is so that the script debugger code can store a list of CScript instances into a structure\r\n// even though many may have the same name.\r\nvoid CStruct::AppendComponentPointer(CComponent *p_comp)\r\n{\r\n\tCComponent *p_last=NULL;\r\n\tCComponent *p_scan=mp_components;\r\n\t\r\n\t// Find p_last, the last component in the list.\r\n\twhile (p_scan)\r\n\t{\r\n\t\tp_last=p_scan;\r\n\t\tp_scan=p_scan->mpNext;\r\n\t}\t\t\r\n\t\r\n\t// Tag p_comp onto the end of the list.\r\n\tif (p_last)\r\n\t{\r\n\t\tp_last->mpNext=p_comp;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_components=p_comp;\r\n\t}\t\r\n\tp_comp->mpNext=NULL;\r\n}\r\n\r\nCStruct::~CStruct()\r\n{\r\n\r\n#ifdef\t__DEBUG_STRUCT_ALLOCS\r\n\tfor (int i=0;i<MAX_LAST;i++)\r\n\t{\r\n\t\tif (last[i] == this)\r\n\t\t{\r\n\t\t\t// step the head back to the last entry added\r\n\t\t\thead--;\r\n\t\t\tif (head <0)\r\n\t\t\t{\r\n\t\t\t\thead = MAX_LAST-1;\r\n\t\t\t}\r\n\t\t\t// if the head is not the entry we just removed \r\n\t\t\t// then copy the head into this slot\r\n\t\t\tif (i!=head)\r\n\t\t\t{\r\n\t\t\t\tlast[i] = last[head];\r\n\t\t\t}\r\n\t\t\t// and clear the head, which now contains the entry we deleted\r\n\t\t\tlast[head] = NULL;\r\n\t\t\t// and we don't need to iterate no more\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n#endif\t\r\n\tClear();\r\n}\r\n\r\n// Deletes all components, deleting any arrays or structures referenced by the components.\r\nvoid CStruct::Clear()\r\n{\r\n\tCComponent *p_comp=mp_components;\r\n\twhile (p_comp)\r\n\t{\r\n\t\tCComponent *p_next=p_comp->mpNext;\r\n\t\t// Note: The CComponent destructor cannot clean up, because that would cause cyclic dependencies.\r\n\t\tCleanUpComponent(p_comp);\r\n\t\tdelete p_comp;\r\n\t\tp_comp=p_next;\r\n\t}\r\n\tmp_components=NULL;\r\n}\r\n\r\nvoid CStruct::RemoveComponent(uint32 nameChecksum)\r\n{\r\n\tCComponent *p_last=NULL;\r\n\tCComponent *p_comp=mp_components;\r\n\twhile (p_comp)\r\n\t{\r\n\t\tCComponent *p_next=p_comp->mpNext;\r\n\t\t\r\n\t\tif (p_comp->mNameChecksum==nameChecksum)\r\n\t\t{\r\n\t\t\t// p_comp must be removed.\r\n\t\t\t\r\n\t\t\t// Unlink it.\r\n\t\t\tif (p_last)\r\n\t\t\t{\r\n\t\t\t\tp_last->mpNext=p_next;\r\n\t\t\t}\r\n\t\t\telse\t\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(p_comp==mp_components,(\"Eh ? p_comp!=mp_components ??\"));\r\n\t\t\t\tmp_components=p_next;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Note: The CComponent destructor cannot clean up, because that would cause cyclic dependencies.\r\n\t\t\tCleanUpComponent(p_comp);\r\n\t\t\tdelete p_comp;\r\n\t\t\t\r\n\t\t\t// Carries on, in case there is more than one component with the given name.\r\n\t\t\tp_comp=p_next;\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_last=p_comp;\r\n\t\t\tp_comp=p_next;\r\n\t\t}\t\r\n\t}\t\r\n}\r\n\r\nvoid CStruct::RemoveComponent(const char *p_name)\r\n{\r\n\tRemoveComponent(Crc::GenerateCRCFromString(p_name));\r\n}\r\n\r\n// Same as RemoveComponent except the type must matched the passed type too.\r\n// Used by eval.cpp when subtracting a structure from another structure.\r\nvoid CStruct::RemoveComponentWithType(uint32 nameChecksum, uint8 type)\r\n{\r\n\tCComponent *p_last=NULL;\r\n\tCComponent *p_comp=mp_components;\r\n\twhile (p_comp)\r\n\t{\r\n\t\tCComponent *p_next=p_comp->mpNext;\r\n\t\t\r\n\t\tif (p_comp->mNameChecksum==nameChecksum && p_comp->mType==type)\r\n\t\t{\r\n\t\t\t// p_comp must be removed.\r\n\t\t\t\r\n\t\t\t// Unlink it.\r\n\t\t\tif (p_last)\r\n\t\t\t{\r\n\t\t\t\tp_last->mpNext=p_next;\r\n\t\t\t}\r\n\t\t\telse\t\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(p_comp==mp_components,(\"Eh ? p_comp!=mp_components ??\"));\r\n\t\t\t\tmp_components=p_next;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Note: The CComponent destructor cannot clean up, because that would cause cyclic dependencies.\r\n\t\t\tCleanUpComponent(p_comp);\r\n\t\t\tdelete p_comp;\r\n\t\t\t\r\n\t\t\t// Carries on, in case there is more than one component with the given name.\r\n\t\t\tp_comp=p_next;\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_last=p_comp;\r\n\t\t\tp_comp=p_next;\r\n\t\t}\t\r\n\t}\t\r\n}\r\n\r\nvoid CStruct::RemoveComponentWithType(const char *p_name, uint8 type)\r\n{\r\n\tRemoveComponentWithType(Crc::GenerateCRCFromString(p_name),type);\r\n}\r\n\r\n// Note: Logical inconsistencies that could be an issue later maybe:\r\n// If the unnamed-name resolves to a global structure, should the component still be removed?\r\n// If there is a referenced global structure, should it have any of the specified flag removed\r\n// too, and so on recursively? (probably not, since global structures should remain constant)\r\nvoid CStruct::RemoveFlag(uint32 checksum)\r\n{\r\n\tCComponent *p_last=NULL;\r\n\tCComponent *p_comp=mp_components;\r\n\twhile (p_comp)\r\n\t{\r\n\t\tCComponent *p_next=p_comp->mpNext;\r\n\t\t\r\n\t\tif (p_comp->mNameChecksum==0 && p_comp->mChecksum==checksum)\r\n\t\t{\r\n\t\t\t// p_comp must be removed.\r\n\t\t\t\r\n\t\t\t// Unlink it.\r\n\t\t\tif (p_last)\r\n\t\t\t{\r\n\t\t\t\tp_last->mpNext=p_next;\r\n\t\t\t}\r\n\t\t\telse\t\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(p_comp==mp_components,(\"Eh ? p_comp!=mp_components ??\"));\r\n\t\t\t\tmp_components=p_next;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Note: The CComponent destructor cannot clean up, because that would cause cyclic dependencies.\r\n\t\t\tCleanUpComponent(p_comp);\r\n\t\t\t// Note: All the CleanUpComponent call will have done will be to zero the union,\r\n\t\t\t// cos a flag component does not contain any pointers that need deleting.\r\n\t\t\t// So I could have just set p_comp->mChecksum to 0 instead. Just calling\r\n\t\t\t// CleanUpComponent for consistency.\r\n\t\t\tdelete p_comp;\r\n\t\t\t\r\n\t\t\t// Carries on, in case there is more than one flag with the given name.\r\n\t\t\t// There shouldn't be, but check anyway.\r\n\t\t\tp_comp=p_next;\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_last=p_comp;\r\n\t\t\tp_comp=p_next;\r\n\t\t}\t\r\n\t}\t\r\n}\r\n\r\nvoid CStruct::RemoveFlag(const char *p_name)\r\n{\r\n\tRemoveFlag(Crc::GenerateCRCFromString(p_name));\r\n}\r\n\r\n// Returns true if the structure contains no components.\r\nbool CStruct::IsEmpty() const\r\n{\r\n\treturn mp_components==NULL;\r\n}\r\n\r\n// Searches for a component with the given name, but will also recurse into substructures.\r\n// Used when resolving the <ParamName> syntax.\r\nCComponent *CStruct::FindNamedComponentRecurse(uint32 nameChecksum) const\r\n{\r\n\tCComponent *p_found=NULL;\r\n\t\r\n    CComponent *p_comp=mp_components;\r\n    while (p_comp)\r\n    {\r\n        if (p_comp->mNameChecksum==nameChecksum) \r\n\t\t{\r\n\t\t\tp_found=p_comp;\r\n\t\t}\t\r\n\t\telse if (p_comp->mNameChecksum==0 && p_comp->mType==ESYMBOLTYPE_NAME)\r\n\t\t{\r\n            CSymbolTableEntry *p_entry=Resolve(p_comp->mChecksum);\r\n            if (p_entry && p_entry->mType==ESYMBOLTYPE_STRUCTURE)\r\n            {\r\n                Dbg_MsgAssert(p_entry->mpStructure,(\"NULL p_entry->mpStructure\"));\r\n                CComponent *p_new_found=p_entry->mpStructure->FindNamedComponentRecurse(nameChecksum);\r\n\t\t\t\tif (p_new_found)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_found=p_new_found;\r\n\t\t\t\t}\t\r\n            }\r\n\t\t}\r\n        p_comp=p_comp->mpNext;\r\n    }\r\n\t\r\n    return p_found;\r\n}\r\n\r\n// If passed NULL this will return the first (leftmost) component.\r\n// If passed non-NULL it return the next component (to the right) \r\n// Returns NULL if the passed component is the last component.\r\nCComponent *CStruct::GetNextComponent(CComponent *p_comp) const\r\n{\r\n\tif (p_comp==NULL)\r\n\t{\r\n\t\treturn mp_components;\r\n\t}\r\n\t\r\n\treturn p_comp->mpNext;\t\r\n}\r\n\r\n// This will copy the contents of this structure into p_dest, but in such a way that\r\n// p_dest will contain no unnamed-structure references, they will all get expanded.\r\n// This was added because sometimes one wants to step through each of the components of\r\n// a structure using GetNextComponent, but GetNextComponent itself cannot recurse into\r\n// unnamed structures, because when it reaches the end of one it won't know how to get back\r\n// to the parent.\r\n// So instead just create a new structure, copy the other structure into it using ExpandInto,\r\n// then step through that using GetNextComponent, then delete the new structure once finished.\r\n// It's a bit memory intensive, but saves having to write special code to resolve unnamed\r\n// structures & recursing whenever one wants to scan through the components.\r\n// Could be handy for other things later too.\r\n// recursionCount is just to catch infinite recursion, so no need to pass it a value. (defaults to 0)\r\nvoid CStruct::ExpandInto(CStruct *p_dest, int recursionCount) const\r\n{\r\n\tDbg_MsgAssert(recursionCount<=20,(\"Possible infinite recursion of CStruct::ExpandInto! More than 20 recursions have occurred.\"));\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest sent to ExpandInto\"));\r\n\t\r\n\tCComponent *p_comp=mp_components;\r\n\twhile (p_comp)\r\n\t{\r\n\t\tbool added_structure=false;\r\n\t\t\r\n\t\tif (p_comp->mNameChecksum==0)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(p_comp->mType!=ESYMBOLTYPE_STRUCTURE,(\"Unexpected unnamed structure in CStruct\"));\r\n\t\t\t\r\n\t\t\tif (p_comp->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t{\r\n\t\t\t\tCSymbolTableEntry *p_global=Resolve(p_comp->mChecksum);\r\n\t\t\t\tif (p_global && p_global->mType==ESYMBOLTYPE_STRUCTURE)\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(p_global->mpStructure,(\"NULL p_global->mpStructure\"));\r\n\t\t\t\t\tp_global->mpStructure->ExpandInto(p_dest,recursionCount+1);\r\n\t\t\t\t\tadded_structure=true;\r\n\t\t\t\t}\t\r\n\t\t\t}\t\r\n\t\t}\r\n\t\t\r\n\t\tif (!added_structure)\r\n\t\t{\r\n\t\t\tCComponent *p_new_component=new CComponent;\r\n\t\t\tCopyComponent(p_new_component,p_comp);\r\n\t\t\tp_dest->AddComponent(p_new_component);\r\n\t\t}\r\n\t\t\r\n\t\tp_comp=p_comp->mpNext;\r\n\t}\r\n}\r\n\r\n// Adds the component p_comp to the end of the list of components, removing any existing components\r\n// that have the same name and type, and asserting if any components exist with the same name but different\r\n// type.\r\n// However, if p_comp is a flag (an un-named component of type ESYMBOLTYPE_NAME) then it will always add it,\r\n// because otherwise we would not be able to have more than one flag in a structure.\r\n//\r\n// Note: Even two identical flags are allowed, because sometimes this is handy. For example I use a list\r\n// of words in a structure as a way for Scott to represent trick button sequences (see airtricks.q) and \r\n// sometimes two of the words might need to be identical.\r\n//\r\n// Another note: This function needs to be pretty fast because it will need to be called many times for\r\n// each line of script executed. Optimize later.\r\n//\r\nvoid CStruct::AddComponent(CComponent *p_comp)\r\n{\r\n\tDbg_MsgAssert(p_comp,(\"NULL p_comp\"));\r\n\r\n\t// Unnamed structure components are not allowed, because to support them would require \r\n\t// modifying the search_for function. No need, since when structures are created from lists\r\n\t// of tokens any substructures get expanded and added component by component at that stage.\r\n\t// So in theory no components of type structure should get added.\r\n\tDbg_MsgAssert(!(p_comp->mNameChecksum==0 && p_comp->mType==ESYMBOLTYPE_STRUCTURE),(\"Tried to add an un-named structure component ...\"));\r\n\r\n\tDbg_MsgAssert(p_comp->mType!=ESYMBOLTYPE_NONE,(\"Tried to add a structure component with no type, name='%s' ...\",FindChecksumName(p_comp->mNameChecksum)));\r\n\t\r\n\tCComponent *p_last=NULL;\r\n\tCComponent *p_scan=mp_components;\r\n    bool remove=false;\r\n\t\r\n\twhile (p_scan)\r\n\t{\r\n\t\tif (p_scan->mNameChecksum==p_comp->mNameChecksum)\r\n\t\t{\r\n\t\t\t// Same name ...\r\n\t\t \r\n\t\t    remove=false;\r\n\t\t\t\r\n\t\t\tif (p_scan->mType==p_comp->mType)\r\n\t\t\t{\r\n\t\t\t\tif (p_scan->mType==ESYMBOLTYPE_NAME && \r\n\t\t\t\t\tp_scan->mNameChecksum==0 && \r\n\t\t\t\t\tp_scan->mChecksum!=p_comp->mChecksum)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Allow multiple un-named checksums if their values are different, because\r\n\t\t\t\t\t// these are flags.\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tremove=true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Consider floats and ints to be the same type, so that x=3.1 overrides x=3 and vice versa\t\t\t\t\r\n\t\t\t\tif ((p_scan->mType==ESYMBOLTYPE_FLOAT && p_comp->mType==ESYMBOLTYPE_INTEGER) ||\r\n\t\t\t\t\t(p_scan->mType==ESYMBOLTYPE_INTEGER && p_comp->mType==ESYMBOLTYPE_FLOAT))\r\n\t\t\t\t{\r\n\t\t\t\t\tremove=true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (remove)\t\t\r\n\t\t\t{\r\n\t\t\t\t// Remove this component.\r\n\t\t\t\tif (p_last)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_last->mpNext=p_scan->mpNext;\r\n\t\t\t\t\tCleanUpComponent(p_scan);\r\n\t\t\t\t\tdelete p_scan;\r\n\t\t\t\t\tp_scan=p_last->mpNext;\r\n\t\t\t\t}\t\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_components=p_scan->mpNext;\r\n\t\t\t\t\tCleanUpComponent(p_scan);\r\n\t\t\t\t\tdelete p_scan;\r\n\t\t\t\t\tp_scan=mp_components;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Same name but different type.\r\n\t\t\t\t// The old code would assert in this case, but the new code allows it.\r\n\t\t\t\t// This is because there is no problem if a structure contains {x=7 x=\"Blaa\"}\r\n\t\t\t\t// Getting an integer called x from it would give 7, getting a string called x would give \"Blaa\"\r\n\t\t\t\t// Also, it would allow {x=7 x=foo} where foo may be defined elsewhere to be a different integer,\r\n\t\t\t\t// which is useful.\r\n\t\t\t\tp_last=p_scan;\r\n\t\t\t\tp_scan=p_scan->mpNext;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_last=p_scan;\r\n\t\t\tp_scan=p_scan->mpNext;\r\n\t\t}\t\r\n\t}\t\r\n\t\r\n\t// Now, p_last points to the last component in the list, and may be NULL.\r\n\t// Tag p_comp onto the end of the list.\r\n\tif (p_last)\r\n\t{\r\n\t\tp_last->mpNext=p_comp;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_components=p_comp;\r\n\t}\t\r\n\tp_comp->mpNext=NULL;\r\n}\r\n\r\n#ifdef __NOPT_ASSERT__ \r\nvoid CStruct::SetParentScript(CScript *p_parentScript)\r\n{\r\n\tmp_parent_script=p_parentScript;\r\n}\r\n\r\nCScript *CStruct::GetParentScript() const\r\n{\r\n\treturn mp_parent_script;\r\n}\r\n#endif\r\n\r\n\r\nvoid CStruct::AddString(uint32 nameChecksum, const char *p_string)\r\n{\r\n\tCComponent *p_new=new CComponent;\r\n\t\r\n\tp_new->mNameChecksum=nameChecksum;\r\n\tp_new->mType=ESYMBOLTYPE_STRING;\r\n\tp_new->mpString=CreateString(p_string);\r\n\t\r\n\tAddComponent(p_new);\r\n}\r\n\r\nvoid CStruct::AddString(const char *p_name, const char *p_string)\r\n{\r\n\tAddString(Crc::GenerateCRCFromString(p_name),p_string);\r\n}\r\n\r\nvoid CStruct::AddLocalString(uint32 nameChecksum, const char *p_string)\r\n{\r\n\tCComponent *p_new=new CComponent;\r\n\t\r\n\tp_new->mNameChecksum=nameChecksum;\r\n\tp_new->mType=ESYMBOLTYPE_LOCALSTRING;\r\n\tp_new->mpString=CreateString(p_string);\r\n\t\r\n\tAddComponent(p_new);\r\n}\r\n\r\nvoid CStruct::AddLocalString(const char *p_name, const char *p_string)\r\n{\r\n\tAddLocalString(Crc::GenerateCRCFromString(p_name),p_string);\r\n}\r\n\r\nvoid CStruct::AddInteger(uint32 nameChecksum, int integer)\r\n{\r\n\tCComponent *p_new=new CComponent;\r\n\t\r\n\tp_new->mNameChecksum=nameChecksum;\r\n\tp_new->mType=ESYMBOLTYPE_INTEGER;\r\n\tp_new->mIntegerValue=integer;\r\n\t\r\n\tAddComponent(p_new);\r\n}\r\n\r\nvoid CStruct::AddInteger(const char *p_name, int integer)\r\n{\r\n\tAddInteger(Crc::GenerateCRCFromString(p_name),integer);\r\n}\r\n\r\nvoid CStruct::AddFloat(uint32 nameChecksum, float float_val)\r\n{\r\n\tCComponent *p_new=new CComponent;\r\n\t\r\n\tp_new->mNameChecksum=nameChecksum;\r\n\tp_new->mType=ESYMBOLTYPE_FLOAT;\r\n\tp_new->mFloatValue=float_val;\r\n\t\r\n\tAddComponent(p_new);\r\n}\r\n\r\nvoid CStruct::AddFloat(const char *p_name, float float_val)\r\n{\r\n\tAddFloat(Crc::GenerateCRCFromString(p_name),float_val);\r\n}\r\n\r\nvoid CStruct::AddChecksum(uint32 nameChecksum, uint32 checksum)\r\n{\r\n\tCComponent *p_new=new CComponent;\r\n\t\r\n\tp_new->mNameChecksum=nameChecksum;\r\n\tp_new->mType=ESYMBOLTYPE_NAME;\r\n\tp_new->mChecksum=checksum;\r\n\t\r\n\tAddComponent(p_new);\r\n}\r\n\r\nvoid CStruct::AddChecksum(const char *p_name, uint32 checksum)\r\n{\r\n\tAddChecksum(Crc::GenerateCRCFromString(p_name),checksum);\r\n}\r\n\r\nvoid CStruct::AddVector(uint32 nameChecksum, float x, float y, float z)\r\n{\r\n\tCComponent *p_new=new CComponent;\r\n\t\r\n\tp_new->mNameChecksum=nameChecksum;\r\n\tp_new->mType=ESYMBOLTYPE_VECTOR;\r\n\tp_new->mpVector=new CVector;\r\n\tp_new->mpVector->mX=x;\r\n\tp_new->mpVector->mY=y;\r\n\tp_new->mpVector->mZ=z;\r\n\t\r\n\tAddComponent(p_new);\r\n}\r\n\r\nvoid CStruct::AddVector(const char *p_name, float x, float y, float z)\r\n{\r\n\tAddVector(Crc::GenerateCRCFromString(p_name),x,y,z);\r\n}\r\n\r\nvoid CStruct::AddVector( uint32 nameChecksum, Mth::Vector vector )\r\n{\r\n\tAddVector( nameChecksum, vector.GetX(), vector.GetY(), vector.GetZ() );\r\n}\r\n\r\nvoid CStruct::AddVector( const char* p_name, Mth::Vector vector )\r\n{\r\n\tAddVector( Crc::GenerateCRCFromString( p_name ), vector.GetX(), vector.GetY(), vector.GetZ() );\r\n}\r\n\r\nvoid CStruct::AddPair(uint32 nameChecksum, float x, float y)\r\n{\r\n\tCComponent *p_new=new CComponent;\r\n\t\r\n\tp_new->mNameChecksum=nameChecksum;\r\n\tp_new->mType=ESYMBOLTYPE_PAIR;\r\n\tp_new->mpPair=new CPair;\r\n\tp_new->mpPair->mX=x;\r\n\tp_new->mpPair->mY=y;\r\n\t\r\n\tAddComponent(p_new);\r\n}\r\n\r\nvoid CStruct::AddPair(const char *p_name, float x, float y)\r\n{\r\n\tAddPair(Crc::GenerateCRCFromString(p_name),x,y);\r\n}\r\n\r\n// Creates a new array & copies in the contents of the passed array.\r\nvoid CStruct::AddArray(uint32 nameChecksum, const CArray *p_array)\r\n{\r\n\tCComponent *p_new=new CComponent;\r\n\t\r\n\tp_new->mNameChecksum=nameChecksum;\r\n\tp_new->mType=ESYMBOLTYPE_ARRAY;\r\n\tp_new->mpArray=new CArray;\r\n\tCopyArray(p_new->mpArray,p_array);\r\n\r\n\tAddComponent(p_new);\r\n}\r\n\r\nvoid CStruct::AddArray(const char *p_name, const CArray *p_array)\r\n{\r\n\tAddArray(Crc::GenerateCRCFromString(p_name),p_array);\r\n}\r\n\r\n// This stores the passed pointer rather than copying the contents, so in this case it\r\n// is important for the calling code not to delete the passed pointer.\r\n// The CStruct will delete it in its destructor.\r\n// Faster than copying the contents.\r\n// Used parse.cpp, when creating the structure for holding function params.\r\nvoid CStruct::AddArrayPointer(uint32 nameChecksum, CArray *p_array)\r\n{\r\n\tCComponent *p_new=new CComponent;\r\n\t\r\n\tp_new->mNameChecksum=nameChecksum;\r\n\tp_new->mType=ESYMBOLTYPE_ARRAY;\r\n\tp_new->mpArray=p_array;\r\n\r\n\tAddComponent(p_new);\r\n}\r\n\r\nvoid CStruct::AddArrayPointer(const char *p_name, CArray *p_array)\r\n{\r\n\tAddArrayPointer(Crc::GenerateCRCFromString(p_name),p_array);\r\n}\r\n\r\n// Creates a new structure & copies in the contents of the passed structure.\r\nvoid CStruct::AddStructure(uint32 nameChecksum, const CStruct *p_structure)\r\n{\r\n\tDbg_MsgAssert(p_structure,(\"NULL p_structure\"));\r\n\t\r\n\tCComponent *p_new=new CComponent;\r\n\t\r\n\tp_new->mNameChecksum=nameChecksum;\r\n\tp_new->mType=ESYMBOLTYPE_STRUCTURE;\r\n\tp_new->mpStructure=new CStruct;\r\n\t*p_new->mpStructure=*p_structure;\r\n\r\n\tAddComponent(p_new);\r\n}\r\n\r\nvoid CStruct::AddStructure(const char *p_name, const CStruct *p_structure)\r\n{\r\n\tAddStructure(Crc::GenerateCRCFromString(p_name),p_structure);\r\n}\r\n\r\n// This stores the passed pointer rather than copying the contents, so in this case it\r\n// is important for the calling code not to delete the passed pointer.\r\n// The CStruct will delete it in its destructor.\r\n// Faster than copying the contents.\r\n// Used parse.cpp, when creating the structure for holding function params.\r\nvoid CStruct::AddStructurePointer(uint32 nameChecksum, CStruct *p_structure)\r\n{\r\n\tDbg_MsgAssert(p_structure,(\"NULL p_structure\"));\r\n\t\r\n\tCComponent *p_new=new CComponent;\r\n\t\r\n\tp_new->mNameChecksum=nameChecksum;\r\n\tp_new->mType=ESYMBOLTYPE_STRUCTURE;\r\n\tp_new->mpStructure=p_structure;\r\n\r\n\tAddComponent(p_new);\r\n}\r\n\r\nvoid CStruct::AddStructurePointer(const char *p_name, CStruct *p_structure)\r\n{\r\n\tAddStructurePointer(Crc::GenerateCRCFromString(p_name),p_structure);\r\n}\r\n\r\nvoid CStruct::AddScript(uint32 nameChecksum, const uint8 *p_scriptTokens, uint32 size)\r\n{\r\n\tCComponent *p_new=new CComponent;\r\n\t\r\n\tp_new->mNameChecksum=nameChecksum;\r\n\tp_new->mType=ESYMBOLTYPE_QSCRIPT;\r\n\tp_new->mScriptSize=size;\r\n\t\r\n\t// Allocate a buffer off the script heap\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\tDbg_MsgAssert(size,(\"Zero script size\"));\r\n\tuint8 *p_new_script=(uint8*)Mem::Malloc(size);\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\t// Copy the script into the new buffer.\r\n\tDbg_MsgAssert(p_scriptTokens,(\"NULL p_scriptTokens\"));\r\n\tconst uint8 *p_source=p_scriptTokens;\r\n\tuint8 *p_dest=p_new_script;\r\n\tfor (uint32 i=0; i<size; ++i)\r\n\t{\r\n\t\t*p_dest++=*p_source++;\r\n\t}\t\r\n\t\r\n\t// Give the new buffer to the new component.\r\n\tp_new->mpScript=p_new_script;\r\n\t\t\r\n\tAddComponent(p_new);\r\n}\r\n\r\nvoid CStruct::AddScript(const char *p_name, const uint8 *p_scriptTokens, uint32 size)\r\n{\r\n\tAddScript(Crc::GenerateCRCFromString(p_name),p_scriptTokens,size);\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// TODO: Remove all these AddComponent functions at some point.\r\n// They are only included to provide back compatibility with the old code without\r\n// having to change thousands of occurrences of calls to AddComponent.\r\n// Gradually phase out the old AddComponent instead.\r\n//\r\n\r\n// String or local string.\r\nvoid CStruct::AddComponent(uint32 nameChecksum, ESymbolType type, const char *p_string)\r\n{\r\n    Dbg_MsgAssert(type==ESYMBOLTYPE_LOCALSTRING || type==ESYMBOLTYPE_STRING,(\"Bad type sent to AddComponent\"));\r\n    Dbg_MsgAssert(p_string,(\"NULL p_string\"));\r\n\r\n\tif (type==ESYMBOLTYPE_STRING)\r\n\t{\r\n\t\tAddString(nameChecksum,p_string);\r\n\t}\r\n\telse\t\r\n\t{\r\n\t\tAddLocalString(nameChecksum,p_string);\r\n\t}\r\n}\r\n\r\n// Integer or any other 4 byte value.\r\nvoid CStruct::AddComponent(uint32 nameChecksum, ESymbolType type, int integer)\r\n{\r\n\tswitch (type)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER: \r\n\t\t\tAddInteger(nameChecksum,integer);\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\tAddFloat(nameChecksum,*(float*)&integer);\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_STRUCTUREPOINTER:\r\n\t\t\tAddStructurePointer(nameChecksum,(CStruct*)integer);\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t\tAddArrayPointer(nameChecksum,(CArray*)integer);\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t\tAddChecksum(nameChecksum,(uint32)integer);\r\n\t\t\tbreak;\r\n\t\tdefault:\t\r\n\t\t\tDbg_MsgAssert(0,(\"Bad type of '%s' sent to AddComponent\",GetTypeName(type)));\r\n\t\t\tbreak;\r\n\t}\t\t\r\n}\r\n\r\n// Vector\r\nvoid CStruct::AddComponent(uint32 nameChecksum, float x, float y, float z)\r\n{\r\n\tAddVector(nameChecksum,x,y,z);\r\n}\r\n\r\n// Pair\r\nvoid CStruct::AddComponent(uint32 nameChecksum, float x, float y)\r\n{\r\n\tAddPair(nameChecksum,x,y);\r\n}\r\n\r\n// Array\r\nvoid CStruct::AddComponent(uint32 nameChecksum, CArray *p_array)\r\n{\r\n\tAddArray(nameChecksum,p_array);\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n\r\n\r\nstruct SWhatever\r\n{\r\n\tunion\r\n\t{\r\n\t\tint mIntegerValue;\r\n\t\tfloat mFloatValue;\r\n\t\tchar *mpString;\r\n\t\tchar *mpLocalString;\r\n\t\tCPair *mpPair;\r\n\t\tCVector *mpVector;\r\n\t\tCStruct *mpStructure;\r\n\t\tCArray *mpArray;\r\n\t\tuint8 *mpScript;\r\n\t\tuint32 mChecksum;\r\n\t\tuint32 mUnion; \r\n\t};\r\n};\r\n\r\n// Infinite recursion of search_for could occur, for example if we have a global structure foo={foo}\r\n// which is trying to include itself.\r\n// This counter will make an assert go off if search_for tries to recurse a suspicious number of times.\r\n#ifdef __NOPT_ASSERT__ \r\nstatic uint32 s_num_search_for_recursions=0;\r\n#endif\r\n\r\nbool CStruct::search_for(uint32 nameChecksum, ESymbolType type, SWhatever *p_value) const\r\n{\r\n\tDbg_MsgAssert(s_num_search_for_recursions<10,(\"Possible infinite recursion of the CStruct::search_for function, bailing out!\\nLast search was for parameter named '%s' of type '%s'\",FindChecksumName(nameChecksum),GetTypeName(type)));\r\n\t#ifdef __NOPT_ASSERT__\r\n\t++s_num_search_for_recursions;\r\n\t#endif\r\n\t\r\n\tDbg_MsgAssert(p_value,(\"NULL p_value\"));\r\n\t\r\n\tbool found=false;\r\n\t\r\n\tCComponent *p_comp=mp_components;\r\n\twhile (p_comp)\r\n\t{\r\n\t\tif (p_comp->mNameChecksum==nameChecksum)\r\n\t\t{\r\n\t\t\t// The name of the component matches that required.\r\n\t\t\tif (p_comp->mType==type)\r\n\t\t\t{\r\n\t\t\t\t// The type also matches, so the required component has been found.\r\n\t\t\t\t// Only set a flag though. Need to keep searching in case the structure\r\n\t\t\t\t// has the form {x=7 x=foo} where foo is a global defined to be an integer,\r\n\t\t\t\t// and which must override the previous 7.\r\n\t\t\t\t\r\n\t\t\t\tp_value->mUnion=p_comp->mUnion;\r\n\t\t\t\tfound=true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// The type does not match.\r\n\t\t\t\tif (p_comp->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t\t{\r\n\t\t\t\t\t// The name of the component matches what we're looking for, but the type\r\n\t\t\t\t\t// does not and is of type name.\r\n\t\t\t\t\t// For example, we might be searching for an integer called x,\r\n\t\t\t\t\t// but we've found a component x=foo\r\n\t\t\t\t\t\r\n\t\t\t\t\t// So, see if foo is the name of a global defined somewhere.\r\n\t\t\t\t\tCSymbolTableEntry *p_global=Resolve(p_comp->mChecksum);\r\n\t\t\t\t\tif (p_global)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// It is! So check if this global has the type that we're looking for ...\r\n\t\t\t\t\t\tif (p_global->mType==type)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// It does! So we have a match.\r\n\t\t\t\t\t\t\t// Just set the found flag though, because we need to keep searching in\r\n\t\t\t\t\t\t\t// case the structure has the form {x=foo x=7} where the later 7 needs to\r\n\t\t\t\t\t\t\t// override what we've just found.\r\n\t\t\t\t\t\t\tp_value->mUnion=p_global->mUnion;\r\n\t\t\t\t\t\t\tfound=true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\t\t\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// The name of the component does not match what we're looking for.\r\n\t\t\t\r\n\t\t\t// See if the component is an un-named name, eg the blaa in {a=3 blaa}\r\n\t\t\tif (p_comp->mNameChecksum==0 && p_comp->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t{\r\n\t\t\t\t// It is, so check whether it resolves to a global structure.\r\n\t\t\t\t// If a global structure is referenced by name in another structure, then\r\n\t\t\t\t// it is considered 'pasted in' to that structure, so it needs to be searched too.\r\n\t\t\t\tCSymbolTableEntry *p_global=Resolve(p_comp->mChecksum);\r\n\t\t\t\tif (p_global)\r\n\t\t\t\t{\r\n\t\t\t\t\t// It is a global something ...\r\n\t\t\t\t\tif (p_global->mType==ESYMBOLTYPE_STRUCTURE)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// It is a structure. So search it for the required component also.\r\n\t\t\t\t\t\tDbg_MsgAssert(p_global->mpStructure,(\"NULL p_global->mpStructure ?\"));\r\n\t\t\t\t\t\tSWhatever value;\r\n\t\t\t\t\t\tif (p_global->mpStructure->search_for(nameChecksum,type,&value))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Found! Load the value, set the found flag and carry on.\r\n\t\t\t\t\t\t\t*p_value=value;\r\n\t\t\t\t\t\t\tfound=true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\t\t\r\n\t\t\t}\t\r\n\t\t}\r\n\t\t\t\r\n\t\tp_comp=p_comp->mpNext;\r\n\t}\t\r\n\r\n\tDbg_MsgAssert(s_num_search_for_recursions,(\"Eh ???\"));\r\n\t#ifdef __NOPT_ASSERT__\r\n\t--s_num_search_for_recursions;\r\n\t#endif\r\n\t\r\n\treturn found;\r\n}\r\n\r\n\r\nbool CStruct::GetString(uint32 nameChecksum, const char **pp_text, EAssertType assert) const\r\n{\r\n\tDbg_MsgAssert(pp_text,(\"NULL pp_text\"));\r\n\t\r\n\tSWhatever value;\r\n\tif (search_for(nameChecksum,ESYMBOLTYPE_STRING,&value))\r\n\t{\r\n\t\t*pp_text=value.mpString;\r\n\t\treturn true;\r\n\t}\r\n\tif (search_for(nameChecksum,ESYMBOLTYPE_LOCALSTRING,&value))\r\n\t{\r\n\t\t*pp_text=value.mpString;\r\n\t\treturn true;\r\n\t}\r\n\tif (assert)\r\n\t{\r\n\t\tPrintContents(this);\r\n\t\tDbg_MsgAssert(0,(\"Could not find string component named '%s' in structure\",FindChecksumName(nameChecksum)));\r\n\t}\t\r\n\treturn false;\t\r\n}\r\n\r\nbool CStruct::GetString(const char *p_paramName, const char **pp_text, EAssertType assert) const\r\n{\r\n\treturn GetString(Crc::GenerateCRCFromString(p_paramName),pp_text,assert);\r\n}\r\n\r\nbool CStruct::GetLocalString(uint32 nameChecksum, const char **pp_text, EAssertType assert) const\r\n{\r\n\treturn GetString(nameChecksum,pp_text,assert);\r\n}\r\n\r\nbool CStruct::GetLocalString(const char *p_paramName, const char **pp_text, EAssertType assert) const\r\n{\r\n\treturn GetString(Crc::GenerateCRCFromString(p_paramName),pp_text,assert);\r\n}\r\n\r\nbool CStruct::GetInteger(uint32 nameChecksum, int *p_integerValue, EAssertType assert) const\r\n{\r\n\tDbg_MsgAssert(p_integerValue,(\"NULL p_integerValue\"));\r\n\t\r\n\tSWhatever value;\r\n\tif (search_for(nameChecksum,ESYMBOLTYPE_INTEGER,&value))\r\n\t{\r\n\t\t*p_integerValue=value.mIntegerValue;\r\n\t\treturn true;\r\n\t}\r\n\tif (assert)\r\n\t{\r\n\t\tPrintContents(this);\r\n\t\tDbg_MsgAssert(0,(\"Could not find integer component named '%s' in structure\",FindChecksumName(nameChecksum)));\r\n\t}\t\r\n\treturn false;\t\r\n}\r\n\r\nbool CStruct::GetInteger(const char *p_paramName, int *p_integerValue, EAssertType assert) const\r\n{\r\n\treturn GetInteger(Crc::GenerateCRCFromString(p_paramName),p_integerValue,assert);\r\n}\r\n\r\nbool CStruct::GetFloat(uint32 nameChecksum, float *p_floatValue, EAssertType assert) const\r\n{\r\n\tDbg_MsgAssert(p_floatValue,(\"NULL p_floatValue\"));\r\n\t\r\n\tSWhatever value;\r\n\tif (search_for(nameChecksum,ESYMBOLTYPE_FLOAT,&value))\r\n\t{\r\n\t\t*p_floatValue=value.mFloatValue;\r\n\t\treturn true;\r\n\t}\r\n\t// If a float was not found, check for any int's with the same name, and if found cast to a float.\r\n\t// Note that the extra search means that {x=3.0} will result in x being found quicker than {x=3}\r\n\t// Could speed this up by making search_for() match integers with floats, but that would slightly slow\r\n\t// down the other Get... functions. Need to do some tests to see what is best.\r\n\tif (search_for(nameChecksum,ESYMBOLTYPE_INTEGER,&value))\r\n\t{\r\n\t\t*p_floatValue=value.mIntegerValue;\r\n\t\treturn true;\r\n\t}\r\n\tif (assert)\r\n\t{\r\n\t\tPrintContents(this);\r\n\t\tDbg_MsgAssert(0,(\"Could not find float component named '%s' in structure\",FindChecksumName(nameChecksum)));\r\n\t}\t\r\n\treturn false;\t\r\n}\r\n\r\nbool CStruct::GetFloat(const char *p_paramName, float *p_floatValue, EAssertType assert) const\r\n{\r\n\treturn GetFloat(Crc::GenerateCRCFromString(p_paramName),p_floatValue,assert);\r\n}\r\n\r\nbool CStruct::GetVector(uint32 nameChecksum, Mth::Vector *p_vector, EAssertType assert) const\r\n{\r\n\tDbg_MsgAssert(p_vector,(\"NULL p_vector\"));\r\n\t\r\n\tSWhatever value;\r\n\tif (search_for(nameChecksum,ESYMBOLTYPE_VECTOR,&value))\r\n\t{\r\n\t\tDbg_MsgAssert(value.mpVector,(\"NULL value.mpVector\"));\r\n\t\tp_vector->Set(value.mpVector->mX,value.mpVector->mY,value.mpVector->mZ);\r\n\t\treturn true;\r\n\t}\r\n\tif (assert)\r\n\t{\r\n\t\tPrintContents(this);\r\n\t\tDbg_MsgAssert(0,(\"Could not find vector component named '%s' in structure\",FindChecksumName(nameChecksum)));\r\n\t}\t\r\n\treturn false;\t\r\n}\r\n\r\nbool CStruct::GetVector(const char *p_paramName, Mth::Vector *p_vector, EAssertType assert) const\r\n{\r\n\treturn GetVector(Crc::GenerateCRCFromString(p_paramName),p_vector,assert);\r\n}\r\n\r\nbool CStruct::GetPair(uint32 nameChecksum, float *p_x, float *p_y,\tEAssertType assert) const\r\n{\r\n\tDbg_MsgAssert(p_x,(\"NULL p_x\"));\r\n\tDbg_MsgAssert(p_y,(\"NULL p_y\"));\r\n\t\r\n\tSWhatever value;\r\n\tif (search_for(nameChecksum,ESYMBOLTYPE_PAIR,&value))\r\n\t{\r\n\t\tDbg_MsgAssert(value.mpPair,(\"NULL value.mpPair\"));\r\n\t\t*p_x=value.mpPair->mX;\r\n\t\t*p_y=value.mpPair->mY;\r\n\t\treturn true;\r\n\t}\r\n\tif (assert)\r\n\t{\r\n\t\tPrintContents(this);\r\n\t\tDbg_MsgAssert(0,(\"Could not find pair component named '%s' in structure\",FindChecksumName(nameChecksum)));\r\n\t}\t\r\n\treturn false;\t\r\n}\r\n\r\nbool CStruct::GetPair(const char *p_paramName, float *p_x, float *p_y, EAssertType assert) const\r\n{\r\n\treturn GetPair(Crc::GenerateCRCFromString(p_paramName),p_x,p_y,assert);\r\n}\r\n\r\nbool CStruct::GetStructure(uint32 nameChecksum, CStruct **pp_structure,\tEAssertType assert) const\r\n{\r\n\tDbg_MsgAssert(pp_structure,(\"NULL pp_structure\"));\r\n\t\r\n\tSWhatever value;\r\n\tif (search_for(nameChecksum,ESYMBOLTYPE_STRUCTURE,&value))\r\n\t{\r\n\t\tDbg_MsgAssert(value.mpStructure,(\"NULL value.mpStructure\"));\r\n\t\t*pp_structure=value.mpStructure;\r\n\t\treturn true;\r\n\t}\r\n\tif (assert)\r\n\t{\r\n\t\tPrintContents(this);\r\n\t\tDbg_MsgAssert(0,(\"Could not find structure component named '%s' in structure\",FindChecksumName(nameChecksum)));\r\n\t}\t\r\n\treturn false;\t\r\n}\r\n\r\nbool CStruct::GetStructure(const char *p_paramName, CStruct **pp_structure,\tEAssertType assert) const\r\n{\r\n\treturn GetStructure(Crc::GenerateCRCFromString(p_paramName),pp_structure,assert);\r\n}\r\n\r\nbool CStruct::GetArray(uint32 nameChecksum, CArray **pp_array, EAssertType assert) const\r\n{\r\n\tDbg_MsgAssert(pp_array,(\"NULL pp_array\"));\r\n\t\r\n\tSWhatever value;\r\n\tif (search_for(nameChecksum,ESYMBOLTYPE_ARRAY,&value))\r\n\t{\r\n\t\tDbg_MsgAssert(value.mpArray,(\"NULL value.mpArray\"));\r\n\t\t*pp_array=value.mpArray;\r\n\t\treturn true;\r\n\t}\r\n\tif (assert)\r\n\t{\r\n\t\tPrintContents(this);\r\n\t\tDbg_MsgAssert(0,(\"Could not find array component named '%s' in structure\",FindChecksumName(nameChecksum)));\r\n\t}\t\r\n\treturn false;\t\r\n}\r\n\r\nbool CStruct::GetArray(const char *p_paramName, CArray **pp_array, EAssertType assert) const\r\n{\r\n\treturn GetArray(Crc::GenerateCRCFromString(p_paramName),pp_array,assert);\r\n}\r\n\r\nbool CStruct::GetScript(uint32 nameChecksum, SStructScript *p_structScript, EAssertType assert) const\r\n{\r\n\tDbg_MsgAssert(p_structScript,(\"NULL p_structScript\"));\r\n\t\r\n\tSWhatever value;\r\n\tif (search_for(nameChecksum,ESYMBOLTYPE_QSCRIPT,&value))\r\n\t{\r\n\t\tDbg_MsgAssert(value.mpScript,(\"NULL value.mpScript\"));\r\n\t\tp_structScript->mNameChecksum=nameChecksum;\r\n\t\tp_structScript->mpScriptTokens=value.mpScript;\r\n\t\treturn true;\r\n\t}\r\n\tif (assert)\r\n\t{\r\n\t\tPrintContents(this);\r\n\t\tDbg_MsgAssert(0,(\"Could not find script component named '%s' in structure\",FindChecksumName(nameChecksum)));\r\n\t}\t\r\n\treturn false;\t\r\n}\r\n\r\nbool CStruct::GetScript(const char *p_paramName, SStructScript *p_structScript, EAssertType assert) const\r\n{\r\n\treturn GetScript(Crc::GenerateCRCFromString(p_paramName),p_structScript,assert);\r\n}\r\n\r\nbool CStruct::GetChecksum(uint32 nameChecksum, uint32 *p_checksum, EAssertType assert) const\r\n{\r\n\tDbg_MsgAssert(p_checksum,(\"NULL p_checksum\"));\r\n\r\n\t// Does not use the search_for function, because GetChecksum needs to ignore unnamed names\r\n\t// that resolve to structures.\r\n\t\r\n\tbool found=false;\r\n\tCComponent *p_comp=mp_components;\r\n\twhile (p_comp)\r\n\t{\r\n\t\tif (p_comp->mNameChecksum==nameChecksum)\r\n\t\t{\r\n\t\t\tif (p_comp->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t{\r\n\t\t\t\tuint32 ch=p_comp->mChecksum;\r\n\t\t\t\t\t\t\r\n\t\t\t\t// The name matches and the type matches, but ignore any un-named names which\r\n\t\t\t\t// resolve to structures since these are considered 'part of' the original structure.\t\t\t\t\r\n\t\t\t\tCSymbolTableEntry *p_entry=Resolve(ch);\t\r\n\t\t\t\tif (p_entry && p_entry->mType==ESYMBOLTYPE_STRUCTURE && p_comp->mNameChecksum==0)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Do nothing.\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_checksum=ch;\r\n\t\t\t\t\tfound=true;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if (p_comp->mNameChecksum==0 && p_comp->mType==ESYMBOLTYPE_NAME)\r\n\t\t{\r\n\t\t\t// It's an unnamed name, so check whether it is a structure.\r\n\t\t\tuint32 ch=p_comp->mChecksum;\r\n\t\t\tCSymbolTableEntry *p_entry=Resolve(ch);\r\n\t\t\tif (p_entry && p_entry->mType==ESYMBOLTYPE_STRUCTURE)\r\n\t\t\t{\r\n\t\t\t\t// It is a structure, so search that.\r\n                Dbg_MsgAssert(p_entry->mpStructure,(\"NULL p_entry->mpStructure\"));\r\n\t\t\t\t// Note: Must not assert if not found, cos could be found later.\r\n                if (p_entry->mpStructure->GetChecksum(nameChecksum,p_checksum)) \r\n\t\t\t\t{\r\n\t\t\t\t\tfound=true;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tp_comp=p_comp->mpNext;\r\n\t}\r\n\tif (assert && !found)\r\n\t{\r\n\t\tPrintContents(this);\r\n\t\tDbg_MsgAssert(0,(\"Checksum parameter '%s' not found in structure\",FindChecksumName(nameChecksum)));\r\n\t}\t\r\n\t\r\n    return found;\r\n}\r\n\r\nbool CStruct::GetChecksum(const char *p_paramName, uint32 *p_checksum, EAssertType assert) const\r\n{\r\n\treturn GetChecksum(Crc::GenerateCRCFromString(p_paramName),p_checksum,assert);\r\n}\r\n\r\n// Looks for a name, and if no name component is found, looks for a string instead, and if found\r\n// calculates the checksum of that.\r\nbool CStruct::GetChecksumOrStringChecksum(uint32 nameChecksum, uint32 *p_checksum, EAssertType assert) const\r\n{\r\n\tDbg_MsgAssert(p_checksum,(\"NULL p_checksum\"));\r\n\t\r\n\tif (GetChecksum(nameChecksum,p_checksum,assert))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tconst char *p_string=NULL;\r\n\tif (GetString(nameChecksum,&p_string,assert))\r\n\t{\r\n\t\tDbg_MsgAssert(p_string,(\"NULL p_string ?\"));\r\n\t\t*p_checksum=Crc::GenerateCRCFromString(p_string);\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\t\r\n}\r\n\r\nbool CStruct::GetChecksumOrStringChecksum(const char *p_paramName, uint32 *p_checksum, EAssertType assert) const\r\n{\r\n\treturn GetChecksumOrStringChecksum(Crc::GenerateCRCFromString(p_paramName),p_checksum,assert);\r\n}\r\n\r\n// Infinite recursion of ContainsComponentNamed could occur, for example if we have a global structure foo={foo}\r\n// which is trying to include itself.\r\n// This counter will make an assert go off if ContainsComponentNamed tries to recurse a suspicious number of times.\r\n#ifdef __NOPT_ASSERT__ \r\nstatic uint32 s_num_contains_component_named_recursions=0;\r\n#endif\r\n\r\n// Checks to see if there is any component with the given name.\r\n// This is similar to ContainsFlag, except it doesn't care what the type is.\r\n// This function is used by the script function GotParam.\r\nbool CStruct::ContainsComponentNamed(uint32 checksum) const\r\n{\r\n\tDbg_MsgAssert(s_num_contains_component_named_recursions<10,(\"Possible infinite recursion of ContainsComponentNamed when searching for component named '%s'\",FindChecksumName(checksum)));\r\n\t#ifdef __NOPT_ASSERT__\r\n\t++s_num_contains_component_named_recursions;\r\n\t#endif\r\n\t\r\n    CComponent *p_comp=mp_components;\r\n    while (p_comp)\r\n    {\r\n\t\tif (p_comp->mNameChecksum==checksum)\r\n\t\t{\r\n\t\t\t// The name of the component matches, so return true.\r\n\t\t\tDbg_MsgAssert(s_num_contains_component_named_recursions,(\"Eh ?\"));\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t--s_num_contains_component_named_recursions;\r\n\t\t\t#endif\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\t\t\r\n\t\tif (p_comp->mNameChecksum==0)\r\n\t\t{\r\n\t\t\t// It's an unnamed component, so maybe it's a single isolated name, or maybe it\r\n\t\t\t// is a name referring to a structure defined elsewhere ...\r\n\t\t\tif (p_comp->mType==ESYMBOLTYPE_NAME)\r\n\t\t\t{\r\n\t\t\t\t// It is a name. Check first to see if it is the name being searched for ...\r\n\t\t\t\tuint32 ch=p_comp->mChecksum;\r\n\t\t\t\tif (ch==checksum)\r\n\t\t\t\t{\r\n\t\t\t\t\t// It is.\r\n\t\t\t\t\tDbg_MsgAssert(s_num_contains_component_named_recursions,(\"Eh ?\"));\r\n\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t--s_num_contains_component_named_recursions;\r\n\t\t\t\t\t#endif\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// Oh well, maybe the name is referring to a global structure ...\r\n\t\t\t\tCSymbolTableEntry *p_global=Resolve(ch);\r\n\t\t\t\tif (p_global)\r\n\t\t\t\t{\r\n\t\t\t\t\t// It is a global ...\r\n\t\t\t\t\tif (p_global->mType==ESYMBOLTYPE_STRUCTURE)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// It is a structure, so call this function on that.\r\n\t\t\t\t\t\tDbg_MsgAssert(p_global->mpStructure,(\"NULL p_global->mpStructure\"));\r\n\t\t\t\t\t\tif (p_global->mpStructure->ContainsComponentNamed(checksum))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tDbg_MsgAssert(s_num_contains_component_named_recursions,(\"Eh ?\"));\r\n\t\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\t\t--s_num_contains_component_named_recursions;\r\n\t\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\t\r\n        p_comp=p_comp->mpNext;\r\n    }\r\n\r\n\tDbg_MsgAssert(s_num_contains_component_named_recursions,(\"Eh ?\"));\r\n\t#ifdef __NOPT_ASSERT__\r\n\t--s_num_contains_component_named_recursions;\r\n\t#endif\r\n\treturn false;\r\n}\r\n\r\nbool CStruct::ContainsComponentNamed(const char *p_name) const\r\n{\r\n\treturn ContainsComponentNamed(Crc::GenerateCRCFromString(p_name));\r\n}\r\n\r\n// Infinite recursion of ContainsFlag could occur, for example if we have a global structure foo={foo}\r\n// which is trying to include itself.\r\n// This counter will make an assert go off if ContainsFlag tries to recurse a suspicious number of times.\r\n#ifdef __NOPT_ASSERT__ \r\nstatic uint32 s_num_contains_flag_recursions=0;\r\n#endif\r\n\r\n// Returns true if the structure contains an unnamed component of type Name, whose checksum\r\n// matches that passed.\r\n// Eg, the structure Foo={Type=type_car Position=(0,0,0) CreatedAtStart} does contain an\r\n// unnamed component of type name, with value GenerateCRC(\"CreatedAtStart\"), so CreatedAtStart\r\n// is like a flag.\r\nbool CStruct::ContainsFlag(uint32 checksum) const\r\n{\r\n\tDbg_MsgAssert(s_num_contains_flag_recursions<10,(\"Possible infinite recursion of ContainsFlag when searching for flag '%s'\",FindChecksumName(checksum)));\r\n\t#ifdef __NOPT_ASSERT__\r\n\t++s_num_contains_flag_recursions;\r\n\t#endif\r\n\t\r\n    CComponent *p_comp=mp_components;\r\n    while (p_comp)\r\n    {\r\n        if (p_comp->mNameChecksum==0 && p_comp->mType==ESYMBOLTYPE_NAME)\r\n\t\t{\r\n\t\t\t// Found an unnamed component of type name.\r\n\t\t\tuint32 name_checksum=p_comp->mChecksum;\r\n\t\t\t\r\n\t\t\tif (name_checksum==checksum)\r\n\t\t\t{\t\r\n\t\t\t\tDbg_MsgAssert(s_num_contains_flag_recursions,(\"Eh ?\"));\r\n\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t--s_num_contains_flag_recursions;\r\n\t\t\t\t#endif\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// The component might be a structure.\r\n\t\t\tCSymbolTableEntry *p_global=Resolve(name_checksum);\r\n\t\t\tif (p_global)\r\n\t\t\t{\r\n\t\t\t\t// It is a global ...\r\n\t\t\t\tif (p_global->mType==ESYMBOLTYPE_STRUCTURE)\r\n\t\t\t\t{\r\n\t\t\t\t\t// It is a structure so check that structure to see if it contains the flag.\r\n\t\t\t\t\tDbg_MsgAssert(p_global->mpStructure,(\"NULL p_global->mpStructure\"));\r\n\t\t\t\t\tif (p_global->mpStructure->ContainsFlag(checksum))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_MsgAssert(s_num_contains_flag_recursions,(\"Eh ?\"));\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\t--s_num_contains_flag_recursions;\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t}\t\r\n\t\t\r\n        p_comp=p_comp->mpNext;\r\n    }\r\n\t\r\n\tDbg_MsgAssert(s_num_contains_flag_recursions,(\"Eh ?\"));\r\n\t#ifdef __NOPT_ASSERT__\r\n\t--s_num_contains_flag_recursions;\r\n\t#endif\r\n    return false;\r\n}\r\n\r\nbool CStruct::ContainsFlag(const char *p_name) const\r\n{\r\n\treturn ContainsFlag(Crc::GenerateCRCFromString(p_name));\r\n}\r\n\r\n// Returns true if this structure contains p_struct as a substructure anywhere.\r\n// This is used in CScript::set_script, to determine whether clearing a structure\r\n// will result in the clearing of another structure.\r\nbool CStruct::References(CStruct *p_struct)\r\n{\r\n\tif (p_struct==this)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n    CComponent *p_comp=mp_components;\r\n    while (p_comp)\r\n    {\r\n        if (p_comp->mType==ESYMBOLTYPE_STRUCTURE)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(p_comp->mpStructure,(\"NULL p_comp->mpStructure\"));\r\n\t\t\tif (p_comp->mpStructure->References(p_struct))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\t\t\r\n        p_comp=p_comp->mpNext;\r\n    }\r\n\t\r\n\treturn false;\r\n}\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// TODO: Remove the following Get... functions at some point.\r\n// They are only included to provide back compatibility with the old code without\r\n// having to change thousands of occurrences.\r\n//\r\nbool CStruct::GetText(uint32 nameChecksum, const char **pp_text, bool assert) const\r\n{\r\n\treturn GetString(nameChecksum,pp_text,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetText(const char *p_paramName, const char **pp_text, bool assert) const\r\n{\r\n\treturn GetString(p_paramName,pp_text,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetLocalText(uint32 nameChecksum, const char **pp_text, bool assert) const\r\n{\r\n\treturn GetString(nameChecksum,pp_text,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetLocalText(const char *p_paramName, const char **pp_text, bool assert) const\r\n{\r\n\treturn GetString(p_paramName,pp_text,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetInteger(uint32 nameChecksum, int *p_integerValue, bool assert) const\r\n{\r\n\treturn GetInteger(nameChecksum,p_integerValue,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetInteger(const char *p_paramName, int *p_integerValue, bool assert) const\r\n{\r\n\treturn GetInteger(p_paramName,p_integerValue,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetFloat(uint32 nameChecksum, float *p_float, bool assert) const\r\n{\r\n\treturn GetFloat(nameChecksum,p_float,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetFloat(const char *p_paramName, float *p_floatValue, bool assert) const\r\n{\r\n\treturn GetFloat(p_paramName,p_floatValue,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetVector(uint32 nameChecksum, Mth::Vector *p_vector, bool assert) const\r\n{\r\n\treturn GetVector(nameChecksum,p_vector,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetVector(const char *p_paramName, Mth::Vector *p_vector, bool assert) const\r\n{\r\n\treturn GetVector(p_paramName,p_vector,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetPair(uint32 nameChecksum, CPair *p_pair, bool assert) const\r\n{\r\n\tfloat x=0.0f;\r\n\tfloat y=0.0f;\r\n\tbool ret_val=GetPair(nameChecksum,&x,&y,assert?ASSERT:NO_ASSERT);\r\n\tDbg_MsgAssert(p_pair,(\"NULL p_pair\"));\r\n\tp_pair->mX=x;\r\n\tp_pair->mY=y;\r\n\treturn ret_val;\r\n}\r\n\r\nbool CStruct::GetPair(const char *p_paramName, CPair *p_pair, bool assert) const\r\n{\r\n\tfloat x=0.0f;\r\n\tfloat y=0.0f;\r\n\tbool ret_val=GetPair(p_paramName,&x,&y,assert?ASSERT:NO_ASSERT);\r\n\tDbg_MsgAssert(p_pair,(\"NULL p_pair\"));\r\n\tp_pair->mX=x;\r\n\tp_pair->mY=y;\r\n\treturn ret_val;\r\n}\r\n\r\nbool CStruct::GetStructure(uint32 nameChecksum, CStruct **pp_struct, bool assert) const\r\n{\r\n\treturn GetStructure(nameChecksum,pp_struct,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetStructure(const char *p_paramName, CStruct **pp_struct, bool assert) const\r\n{\r\n\treturn GetStructure(p_paramName,pp_struct,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetChecksum(uint32 nameChecksum, uint32 *p_checksum, bool assert) const\r\n{\r\n\treturn GetChecksum(nameChecksum,p_checksum,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetChecksum(const char *p_paramName, uint32 *p_checksum, bool assert) const\r\n{\r\n\treturn GetChecksum(p_paramName,p_checksum,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetChecksumOrStringChecksum(uint32 nameChecksum, uint32 *p_checksum, bool assert) const\r\n{\r\n\treturn GetChecksumOrStringChecksum(nameChecksum,p_checksum,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetChecksumOrStringChecksum(const char *p_paramName, uint32 *p_checksum, bool assert) const\r\n{\r\n\treturn GetChecksumOrStringChecksum(p_paramName,p_checksum,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetArray(uint32 nameChecksum, CArray **pp_array, bool assert) const\r\n{\r\n\treturn GetArray(nameChecksum,pp_array,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool CStruct::GetArray(const char *p_paramName, CArray **pp_array, bool assert) const\r\n{\r\n\treturn GetArray(p_paramName,pp_array,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\n#if 0\r\n// Go throught the raw pool and see which entries are valid, and dump them\r\n//\tuint8 *\t\t\t\tmp_buffer;\r\n//\tuint8 *\t\t\t\tmp_buffer_end;\r\n//\tint\t\t\t\t\tm_totalItems; // that we have room for\r\n//\tint\t\t\t\t\tm_itemSize;\r\n\r\n\r\nvoid DumpStructs()\r\n{\r\n\tMem::CCompactPool * p_pool = Mem::CPoolable<CStruct>::sp_pool[Mem::CPoolable<CStruct>::s_currentPool];\r\n\tCStruct *p_struct = (CStruct *)p_pool->mp_buffer;\r\n\twhile (p_struct <  (CStruct *)p_pool->mp_buffer_end)\r\n\t{\r\n\t\tif (p_pool->IsInPool(p_struct))\r\n\t\t{\r\n\t\t\tPrintContents(p_struct);\r\n\t\t}\r\n\t\t\r\n\t\tp_struct++;\t\t\r\n\t}\r\n}\r\n\r\n#endif\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n\t\t\r\n} // namespace Script\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/struct.h",
    "content": "#ifndef\t__SCRIPTING_STRUCT_H\r\n#define\t__SCRIPTING_STRUCT_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __SYS_MEM_POOLABLE_H\r\n#include <sys/mem/poolable.h>\r\n#endif\r\n\r\n#ifndef\t__SCRIPTING_SCRIPTDEFS_H\r\n#include <gel/scripting/scriptdefs.h> // For EAssertType\r\n#endif\r\n\r\n#ifndef\t__SCRIPTING_SYMBOLTYPE_H\r\n#include <gel/scripting/symboltype.h> // For ESymbolType\r\n#endif\r\n\r\nnamespace Mth\r\n{\r\nclass Vector;\r\n}\r\n\r\nnamespace Script\r\n{\r\n\r\nclass CPair; // TODO: Remove once the old GetPair member function is removed.\r\n\r\nclass CComponent;\r\nclass CScript;\r\nclass CArray;\r\nstruct SWhatever;\r\n\r\n// This defines a reference to a script that is defined in a CStruct.\r\n// A pointer to one of these can then be passed to CScript::SetScript.\r\n// Only exists as a convenient way of passing the data from GetScript to SetScript.\r\nstruct SStructScript\r\n{\r\n\t// The name of the script, which is the same as its parameter name in the source structure.\r\n\tuint32 mNameChecksum;\r\n\t// Pointer to the script data in the structure.\r\n\t// Note that this means that this pointer will become invalid once the source structure is deleted.\r\n\t// OK though, because SStructScript is only used to pass the info to CScript::SetScript, which\r\n\t// will make its own copy of the script data.\r\n\tuint8 *mpScriptTokens;\r\n\t\r\n\tSStructScript() {mNameChecksum=NO_NAME; mpScriptTokens=NULL;}\r\n};\r\n\r\n#ifdef __PLAT_WN32__\r\nclass CStruct\r\n#else\r\nclass CStruct : public Mem::CPoolable<CStruct>\r\n#endif\r\n{\r\n\t// Head pointer of the list of components.\r\n\tCComponent *mp_components;\r\n    \r\n\t#ifdef __NOPT_ASSERT__ \r\n\t// The script that created this structure. Only valid (non NULL) if this is \r\n\t// a mpFunctionParams structure created by a script.\r\n\t// Needed so that if the Get... functions assert they can print info about \r\n\t// the parent script, eg the line number of the error.\r\n\tCScript *mp_parent_script;\r\n\t#endif\r\n\r\n\tvoid init();\r\n\tbool search_for(uint32 nameChecksum, ESymbolType type, SWhatever *p_value) const;\r\n\t\r\npublic:\r\n    CStruct();\r\n    ~CStruct();\r\n\r\n\t// These are defined, and will create new instances of any entities pointed to by the\r\n\t// source structure, so the two structures will not share any pointers.\r\n\t// Careful when using these though, because if copying a complex structure with lots\r\n\t// of nested sub-structures and arrays it could potentially take a long time to execute.\r\n\tCStruct( const CStruct& rhs );\r\n\tCStruct& operator=( const CStruct& rhs );\r\n\t\r\n\t// This will merge the contents of the rhs into this structure.\r\n\t// Functionally the same as the old AppendStructure function.\r\n\tCStruct& operator+=( const CStruct& rhs );\r\n\t\r\n    // Deletes all components, deleting any arrays or structures referenced by the components.\r\n    void Clear();\r\n\r\n\t// Removes the component with the given name.\r\n\tvoid RemoveComponent(uint32 nameChecksum);\r\n\tvoid RemoveComponent(const char *p_name);\r\n\r\n\t// Same as RemoveComponent except the type must match too.\r\n\tvoid RemoveComponentWithType(uint32 nameChecksum, uint8 type);\r\n\tvoid RemoveComponentWithType(const char *p_name, uint8 type);\r\n\t\r\n\t// Removes the flag (unnamed name) with the given name.\r\n\tvoid RemoveFlag(uint32 checksum);\r\n\tvoid RemoveFlag(const char *p_name);\r\n\r\n\t// Adds p_comp to the end of the list of components, removing any existing components with\r\n\t// the same name.\r\n\tvoid AddComponent(CComponent *p_comp);\r\n\t\r\n\t#ifdef __NOPT_ASSERT__ \r\n\tvoid SetParentScript(CScript *p_parentScript);\r\n\t#endif\r\n\r\n\t// If a component of the same name and type already exists it will be replaced with the new value.\r\n\t// If a component of the same name but different type exists, it will assert.\r\n\t// NameChecksum can be 0, meaning no name.\r\n\t// If all OK, returns a pointer to the new component.\r\n    \r\n\t// These will copy in the actual string data, not store the pointer.\r\n\tvoid AddString(uint32 nameChecksum, const char *p_string);\r\n\tvoid AddString(const char *p_name, const char *p_string);\r\n\tvoid AddLocalString(uint32 nameChecksum, const char *p_string);\r\n\tvoid AddLocalString(const char *p_name, const char *p_string);\r\n\t\r\n\tvoid AddInteger(uint32 nameChecksum, int integer);\r\n\tvoid AddInteger(const char *p_name, int integer);\r\n\t\r\n\tvoid AddFloat(uint32 nameChecksum, float float_val);\r\n\tvoid AddFloat(const char *p_name, float float_val);\r\n\r\n\tvoid AddChecksum(uint32 nameChecksum, uint32 checksum);\r\n\tvoid AddChecksum(const char *p_name, uint32 checksum);\r\n\t\r\n\tvoid AddVector(uint32 nameChecksum, float x, float y, float z);\r\n\tvoid AddVector(const char* p_name, float x, float y, float z);\r\n\tvoid AddVector( uint32 nameChecksum, Mth::Vector vector );\r\n\tvoid AddVector( const char* p_name, Mth::Vector vector );\r\n\r\n\t\r\n\tvoid AddPair(uint32 nameChecksum, float x, float y);\r\n\tvoid AddPair(const char *p_name, float x, float y);\r\n\r\n\t// Creates a new array & copies in the contents of the passed array.\r\n\tvoid AddArray(uint32 nameChecksum, const CArray *p_array);\r\n\tvoid AddArray(const char *p_name, const CArray *p_array);\r\n\r\n\t// Stores the passed pointer. Faster than copying the contents.\r\n\t// The passed pointer is no longer const because the CStruct will delete it when destroyed.\r\n\tvoid AddArrayPointer(uint32 nameChecksum, CArray *p_array);\r\n\tvoid AddArrayPointer(const char *p_name, CArray *p_array);\r\n\r\n\t// Creates a new structure & copies in the contents of the passed structure.\r\n\tvoid AddStructure(uint32 nameChecksum, const CStruct *p_structure);\r\n\tvoid AddStructure(const char *p_name, const CStruct *p_structure);\r\n\t\r\n\t// Stores the passed pointer. Faster than copying the contents.\r\n\t// The passed pointer is no longer const because the CStruct will delete it when destroyed.\r\n\tvoid AddStructurePointer(uint32 nameChecksum, CStruct *p_structure);\r\n\tvoid AddStructurePointer(const char *p_name, CStruct *p_structure);\r\n\r\n\t// Creates a new script component and copies in the passed script.\r\n\tvoid AddScript(uint32 nameChecksum, const uint8 *p_scriptTokens, uint32 size);\r\n\tvoid AddScript(const char *p_name, const uint8 *p_scriptTokens, uint32 size);\r\n\t\r\n\t///////////////////////////////////////////////////////////////////////////////////\r\n\t// TODO: Remove all these AddComponent functions at some point.\r\n\t// They are only included to provide back compatibility with the old code without\r\n\t// having to change thousands of occurrences of calls to AddComponent.\r\n\t// Gradually phase out the old AddComponent instead.\r\n\t//\r\n\t\r\n    // String or local string.\r\n\tvoid AddComponent(uint32 nameChecksum, ESymbolType type, const char *p_string); // This will copy the actual string data\r\n    // Integer or any other 4 byte value.\r\n\tvoid AddComponent(uint32 nameChecksum, ESymbolType type, int integer);\r\n    // Vector\r\n\tvoid AddComponent(uint32 nameChecksum, float x, float y, float z);\r\n    // Pair\r\n\tvoid AddComponent(uint32 nameChecksum, float x, float y);\r\n\t// Array\r\n\tvoid AddComponent(uint32 nameChecksum, CArray *p_array); // Copies the data in the array\r\n\t///////////////////////////////////////////////////////////////////////////////////\r\n\r\n\r\n\tbool GetString\t\t(uint32 nameChecksum, \t\tconst char **pp_text, \tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetString\t\t(const char *p_paramName, \tconst char **pp_text, \tEAssertType assert=NO_ASSERT) const;\r\n    bool GetLocalString\t(uint32 nameChecksum, \t\tconst char **pp_text, \tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetLocalString\t(const char *p_paramName, \tconst char **pp_text, \tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetInteger\t\t(uint32 nameChecksum, \t\tint *p_integerValue, \tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetInteger\t\t(const char *p_paramName, \tint *p_integerValue, \tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetFloat\t\t(uint32 nameChecksum, \t\tfloat *p_floatValue,\tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetFloat\t\t(const char *p_paramName, \tfloat *p_floatValue, \tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetVector\t\t(uint32 nameChecksum, \t\tMth::Vector *p_vector, \tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetVector\t\t(const char *p_paramName, \tMth::Vector *p_vector, \tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetPair\t\t(uint32 nameChecksum, \t\tfloat *p_x, float *p_y,\tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetPair\t\t(const char *p_paramName, \tfloat *p_x, float *p_y,\tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetStructure\t(uint32 nameChecksum, \t\tCStruct **pp_structure,\tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetStructure\t(const char *p_paramName, \tCStruct **pp_structure,\tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetChecksum\t(uint32 nameChecksum, \t\tuint32 *p_checksum, \tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetChecksum\t(const char *p_paramName, \tuint32 *p_checksum, \tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetArray\t\t(uint32 nameChecksum, \t\tCArray **pp_array, \t\tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetArray\t\t(const char *p_paramName, \tCArray **pp_array, \t\tEAssertType assert=NO_ASSERT) const;\r\n\tbool GetScript\t\t(uint32 nameChecksum, \t\tSStructScript *p_structScript, EAssertType assert=NO_ASSERT) const;\r\n\tbool GetScript\t\t(const char *p_paramName,\tSStructScript *p_structScript, EAssertType assert=NO_ASSERT) const;\r\n\tbool GetChecksumOrStringChecksum(uint32 nameChecksum, uint32 *p_checksum, EAssertType assert=NO_ASSERT) const;\r\n\tbool GetChecksumOrStringChecksum(const char *p_paramName, uint32 *p_checksum, EAssertType assert=NO_ASSERT) const;\r\n\tbool ContainsComponentNamed(uint32 checksum) const;\r\n\tbool ContainsComponentNamed(const char *p_name) const;\r\n\tbool ContainsFlag\t(uint32 checksum) const;\r\n\tbool ContainsFlag\t(const char *p_name) const;\r\n\r\n\t///////////////////////////////////////////////////////////////////////////////////\r\n\t// TODO: Remove all these GetText functions at some point.\r\n\t// They are only included to provide back compatibility with the old code without\r\n\t// having to change thousands of occurrences of calls to GetText.\r\n\t// Some of them do not have a default value for assert given, to prevent ambiguities with the above functions.\r\n    bool GetText(uint32 nameChecksum, const char **pp_text, bool assert=false) const;\r\n\tbool GetText(const char *p_paramName, const char **pp_text, bool assert=false) const;\r\n    bool GetLocalText(uint32 nameChecksum, const char **pp_text, bool assert=false) const;\r\n\tbool GetLocalText(const char *p_paramName, const char **pp_text, bool assert=false) const;\r\n\tbool GetInteger(uint32 nameChecksum, int *p_integerValue, bool assert) const;\r\n\tbool GetInteger(const char *p_paramName, int *p_integerValue, bool assert) const;\r\n\tbool GetFloat(uint32 nameChecksum, float *p_float, bool assert) const;\r\n\tbool GetFloat(const char *p_paramName, float *p_floatValue, bool assert) const;\r\n\tbool GetVector(uint32 nameChecksum, Mth::Vector *p_vector, bool assert) const;\r\n\tbool GetVector(const char *p_paramName, Mth::Vector *p_vector, bool assert) const;\r\n\tbool GetPair(uint32 nameChecksum, CPair *p_pair, bool assert=false) const;\r\n\tbool GetPair(const char *p_paramName, CPair *p_pair, bool assert=false) const;\r\n\tbool GetStructure(uint32 nameChecksum, CStruct **pp_struct, bool assert) const;\r\n\tbool GetStructure(const char *p_paramName, CStruct **pp_struct, bool assert) const;\r\n\tbool GetChecksum(uint32 nameChecksum, uint32 *p_checksum, bool assert) const;\r\n\tbool GetChecksum(const char *p_paramName, uint32 *p_checksum, bool assert) const;\r\n\tbool GetChecksumOrStringChecksum(uint32 nameChecksum, uint32 *p_checksum, bool assert) const;\r\n\tbool GetChecksumOrStringChecksum(const char *p_paramName, uint32 *p_checksum, bool assert) const;\r\n\tbool GetArray(uint32 nameChecksum, CArray **pp_array, bool assert) const;\r\n\tbool GetArray(const char *p_paramName, CArray **pp_array, bool assert) const;\r\n\t///////////////////////////////////////////////////////////////////////////////////\r\n\t\r\n\t// TODO: Remove at some point. Provided for back-compatibility.\r\n\tvoid AppendStructure(const CStruct *p_struct);\r\n\r\n\tvoid AppendComponentPointer(CComponent *p_comp);\r\n\r\n\t// This will copy the contents of this structure into p_dest, but in such a way that\r\n\t// p_dest will contain no unnamed-structure references, they will all get expanded.\r\n\t// This was added because sometimes one wants to step through each of the components of\r\n\t// a structure using GetNextComponent, but GetNextComponent itself cannot recurse into\r\n\t// unnamed structures, because when it reaches the end of one it won't know how to get back\r\n\t// to the parent.\r\n\t// So instead just create a new structure, copy the other structure into it using ExpandInto,\r\n\t// then step through that using GetNextComponent, then delete the new structure once finished.\r\n\t// It's a bit memory intensive, but saves having to write special code to resolve unnamed\r\n\t// structures & recursing whenever one wants to scan through the components.\r\n\t// Could be handy for other things later too.\r\n\t// recursionCount is just to catch infinite recursion, so no need to pass it a value.\r\n\tvoid ExpandInto(CStruct *p_dest, int recursionCount=0) const;\r\n\t\r\n\t// Returns true if the structure contains no components.\r\n\tbool IsEmpty() const;\r\n    \r\n\t// Searches for a component with the given name, but will also recurse into substructures.\r\n\t// Used when resolving the <ParamName> syntax.\r\n\tCComponent *FindNamedComponentRecurse(uint32 nameChecksum) const;\r\n\t\r\n\t// If passed NULL this will return the first (leftmost) component.\r\n\t// If passed non-NULL it return the next component (to the right) \r\n\t// Returns NULL if the passed component is the last component.\r\n\tCComponent *GetNextComponent(CComponent *p_comp=NULL) const;\r\n\r\n\t// Returns true if this structure contains p_struct as a substructure anywhere.\r\n\t// This is used in CScript::set_script, to determine whether clearing a structure\r\n\t// will result in the clearing of another structure.\r\n\tbool References(CStruct *p_struct);\r\n\t\r\n\t#ifdef __NOPT_ASSERT__ \r\n\tCScript *GetParentScript() const;\r\n\tbool CheckForDuplicateFlags() const;\r\n\t#endif\r\n};\r\n\r\nvoid CleanUpComponent(CComponent *p_comp);\r\nvoid CopyComponent(CComponent *p_dest, const CComponent *p_source);\r\nvoid CleanUpArray(CArray *p_array);\r\nvoid CopyArray(CArray *p_dest, const CArray *p_source);\r\n\r\nvoid DumpStructs();\r\n\r\n\r\n} // namespace Script\r\n\r\n#endif // #ifndef\t__SCRIPTING_STRUCT_H\r\n"
  },
  {
    "path": "Code/Gel/Scripting/symboltable.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// symboltable.cpp\t\tKSH 17 Oct 2001\r\n//\r\n// Symbol hash table stuff.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <core/crc.h>\r\n\r\n#include <sys/timer.h>\r\n\r\nDefinePoolableClass(Script::CSymbolTableEntry);\r\n\r\nnamespace Script\r\n{\r\n\r\nCSymbolTableEntry::CSymbolTableEntry()\r\n{\r\n\t// Initialise everything. CSymbolTableEntry is not derived from CClass so we don't get\r\n\t// the auro-zeroing.\r\n\tReset();\r\n}\r\n\r\n// The destructor does not delete anything to avoid cyclic dependencies, so just assert\r\n// if it look like there could be a non-NULL pointer left.\r\n#ifdef __NOPT_ASSERT__\r\nCSymbolTableEntry::~CSymbolTableEntry()\r\n{\r\n\tDbg_MsgAssert(mUnion==0,(\"CSymbolTableEntry still contains data, possibly an undeleted pointer\"));\r\n}\r\n#endif\r\n\r\nvoid CSymbolTableEntry::Reset()\r\n{\r\n    mNameChecksum=NO_NAME;\r\n\tmGotReloaded=false;\r\n    mUsed=false;\r\n    mType=ESYMBOLTYPE_NONE;\r\n\tmUnion=0;\r\n    mpNext=NULL;\r\n\tmSourceFileNameChecksum=NO_NAME;\r\n\t#ifdef COUNT_USAGE\r\n\tmUsage=0;\r\n\t#endif\r\n}\r\n\r\nstatic CSymbolTableEntry *sp_hash_table=NULL;\r\n\r\nvoid CreateSymbolHashTable()\r\n{\r\n\tDbg_MsgAssert(sp_hash_table==NULL,(\"sp_hash_table not NULL ?\"));\r\n\tsp_hash_table=new CSymbolTableEntry[1<<NUM_HASH_BITS];\r\n}\r\n\r\nvoid DestroySymbolHashTable()\r\n{\r\n\tDbg_MsgAssert(sp_hash_table!=NULL,(\"sp_hash_table is NULL ?\"));\r\n\tdelete[] sp_hash_table;\r\n\tsp_hash_table=NULL;\r\n}\r\n\r\n// Searches for the symbol with the passed Checksum.\r\n// If not found, it returns NULL.\r\n/*int LookUpSymbolCount=0;\r\nint ScriptCount=0;\r\nint CFuncCount=0;\r\nint MemberFuncCount=0;\r\nint FloatCount=0;\r\nint IntegerCount=0;\r\nint StructureCount=0;\r\nint ArrayCount=0;\r\nint NothingCount=0;*/\r\n\r\nuint32 LastVBlanks=0;\r\n\r\nCSymbolTableEntry *LookUpSymbol(uint32 checksum)\r\n{\r\n\t/*\r\n\t++LookUpSymbolCount;\r\n\tif (LastVBlanks!=Tmr::GetVblanks())\r\n\t{\r\n\t\tLastVBlanks=Tmr::GetVblanks();\r\n\t\tprintf(\"%d Script:%d CFunc:%d Member Func:%d Float:%d Int:%d Struc:%d Array:%d Nothing:%d\\n\",LookUpSymbolCount,ScriptCount,CFuncCount,MemberFuncCount,FloatCount,IntegerCount,StructureCount,ArrayCount,NothingCount);\r\n\t\tLookUpSymbolCount=0;\r\n\t\tScriptCount=0;\r\n\t\tCFuncCount=0;\r\n\t\tMemberFuncCount=0;\r\n\t\tFloatCount=0;\r\n\t\tIntegerCount=0;\r\n\t\tStructureCount=0;\r\n\t\tArrayCount=0;\r\n\t\tNothingCount=0;\r\n\t}\r\n\t*/\r\n\t\r\n#ifdef __PLAT_WN32__\r\n\t// GJ:  CreateSymbolHashTable was formerly called as part of the\r\n\t// script system initialization, but it was moved earlier to fix some\r\n\t// music bug (see main.cpp), which breaks those Win32 tools that\r\n\t// didn't already call CreateSymbolHashTable() explicitly...\r\n\tDbg_MsgAssert( sp_hash_table, ( \"No symbol table...  was CreateSymbolHashTable() called?\" ) );\r\n#endif\r\n\r\n\t// Instead of asserting if sp_hash_table is NULL, just return NULL.\r\n\t// This is because when the sio_manager is created in main.cpp it calls GetInteger, but this is before\r\n\t// SkateScript::Init has been called.\r\n\t// I didn't want to fiddle with the init order there in case it broke something else, so just made this\r\n\t// not assert instead.\r\n\t// MICK:  Removed that problem, so don't need this test any more.\r\n//\tif (!sp_hash_table)\r\n//\t{\r\n//\t\t//++NothingCount;\r\n//\t\treturn NULL;\r\n//\t}\t\r\n\t\r\n    // Get the first entry in the list for this checksum.\r\n    CSymbolTableEntry *p_sym=&sp_hash_table[ checksum & ((1<<NUM_HASH_BITS)-1) ];\r\n\r\n    // If nothing here, return NULL.\r\n\t// MICK: Don't need to do this anyway, as generally the symbol WILL exists (99.9% of the time)\r\n\t// so we can afford to be slightly slower when it does not.\r\n//    if (!p_sym->mUsed) \r\n//\t{\r\n//\t\t//++NothingCount;\r\n//\t\treturn NULL;\r\n//\t}\t\r\n\r\n#if 0\t\r\n\t//MCozzini 4-30-03 optimization to avoid the p_sym test\r\n\tif(p_sym->mNameChecksum==checksum)\r\n\t{\r\n\t\treturn p_sym;\r\n\t}\r\n\tp_sym=p_sym->mpNext;\r\n\r\n\r\n    // Scan through the linked list until the complete checksum is found.\r\n    while (p_sym && p_sym->mNameChecksum!=checksum) \r\n\t{\r\n\t\tp_sym=p_sym->mpNext;\r\n\t}\t\r\n#else\r\n\t// it it's an unused slot, then both mNameChecksum and mpNext will be 0 (NULL)\r\n\t// so it will just drop through this test\r\n\tdo \r\n\t{\r\n\t\tif(p_sym->mNameChecksum == checksum)\r\n\t\t{\r\n\t\t\treturn p_sym;\t// Quicker to return here than to break\r\n\t\t}\r\n\t\tp_sym=p_sym->mpNext;\r\n\t} while (p_sym && p_sym->mNameChecksum!=checksum);\r\n\t\r\n\t// Here p_sym will be NULL\t\r\n\treturn p_sym;\t\r\n\r\n#endif\r\n\t\r\n\t// p_sym will be NULL if the checksum was not found.\r\n\t/*\r\n\tif (p_sym)\r\n\t{\r\n\t\tif (p_sym->mType==ESYMBOLTYPE_QSCRIPT)\r\n\t\t{\r\n\t\t\t++ScriptCount;\r\n\t\t}\r\n\t\telse if (p_sym->mType==ESYMBOLTYPE_CFUNCTION)\r\n\t\t{\r\n\t\t\t++CFuncCount;\r\n\t\t}\r\n\t\telse if (p_sym->mType==ESYMBOLTYPE_MEMBERFUNCTION)\r\n\t\t{\r\n\t\t\t++MemberFuncCount;\r\n\t\t}\r\n\t\telse if (p_sym->mType==ESYMBOLTYPE_FLOAT)\r\n\t\t{\r\n\t\t\t++FloatCount;\r\n\t\t}\r\n\t\telse if (p_sym->mType==ESYMBOLTYPE_INTEGER)\r\n\t\t{\r\n\t\t\t++IntegerCount;\r\n\t\t}\r\n\t\telse if (p_sym->mType==ESYMBOLTYPE_STRUCTURE)\r\n\t\t{\r\n\t\t\t++StructureCount;\r\n\t\t}\r\n\t\telse if (p_sym->mType==ESYMBOLTYPE_ARRAY)\r\n\t\t{\r\n\t\t\t++ArrayCount;\r\n\t\t}\r\n\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t++NothingCount;\r\n\t}*/\r\n    return p_sym;\r\n}\r\n\r\nCSymbolTableEntry *LookUpSymbol(const char *p_name)\r\n{\r\n\treturn LookUpSymbol(Crc::GenerateCRCFromString(p_name));\r\n}\t\r\n\r\n// Resolves a checksum into a symbol table entry. Does any stepping over of chains of symbols linked by\r\n// name. Eg, Resolving a where a=b, b=c, c=d, d=6 will return the symbol d, with value 6.\r\n// Returns NULL if the checksum cannot be resolved.\r\nCSymbolTableEntry *Resolve(uint32 checksum)\r\n{\r\n    // Look up the checksum.\r\n    CSymbolTableEntry *p_entry=LookUpSymbol(checksum);\r\n\tif (p_entry && p_entry->mType==ESYMBOLTYPE_NAME)\r\n\t{\r\n\t\t// If the symbol is of type name, then it may be that the name is the name of another symbol,\r\n\t\t// in which case we need to find that.\r\n\t\t// Eg we could be trying to resolve a, where a=b, b=c, c=7, in which case we need to find 7.\r\n\t\t// So loop until either a non-name symbol is reached, or no further symbol is reached.\r\n\t\t\r\n\t\t#ifdef __NOPT_ASSERT__ \r\n\t\t// An infinite loop could occur, for example if we have a global a=b where b=a\r\n\t\t// This counter will make an assert go off if we try and loop a suspicious number of times.\r\n\t\tuint32 num_loops=0;\r\n\t\t#endif\r\n\t\r\n\t\twhile (true)\r\n\t\t{\r\n\t\t\tCSymbolTableEntry *p_new=LookUpSymbol(p_entry->mChecksum);\r\n\t\t\tif (!p_new)\r\n\t\t\t{\r\n\t\t\t\t// Reached the end of the chain, so return the last entry, which will have type name.\r\n\t\t\t\treturn p_entry;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tif (p_new->mType!=ESYMBOLTYPE_NAME)\r\n\t\t\t{\r\n\t\t\t\t// Reached something not of type name, so return that.\r\n\t\t\t\treturn p_new;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Repeat.\t\r\n\t\t\tp_entry=p_new;\r\n\t\t\tDbg_MsgAssert(num_loops++<10,(\"Possible infinite recursion of the Resolve function when trying to resolve '%s', bailing out!\",FindChecksumName(checksum)));\r\n\t\t}\r\n\t}\r\n\t\t\t\r\n    return p_entry;\r\n}\r\n\r\nCSymbolTableEntry *Resolve(const char *p_name)\r\n{\r\n\treturn Resolve(Crc::GenerateCRCFromString(p_name));\r\n}\t\r\n\r\n// Removes the symbol from the table.\r\n// Used when reloading a .qb file. \r\n// Note: Will not delete any entities referred to by the symbol, and will assert if any of the\r\n// pointers are not NULL.\r\n// This is to avoid a cyclic dependency between symboltable and struct.\r\n// It is up to the caller to have deleted these before calling this.\r\nvoid RemoveSymbol(CSymbolTableEntry *p_sym)\r\n{\r\n\tDbg_MsgAssert(p_sym,(\"NULL p_sym\"));\r\n\tDbg_MsgAssert(p_sym->mUnion==0,(\"CSymbolTableEntry still contains data, possibly an undeleted pointer. Type='%s'\",GetTypeName(p_sym->mType)));\r\n\tDbg_MsgAssert(p_sym->mUsed,(\"Tried to call RemoveSymbol on an unused CSymbolTableEntry\"));\r\n\tDbg_MsgAssert(sp_hash_table!=NULL,(\"sp_hash_table is NULL ?\"));\r\n\r\n\t// Get the head pointer of the list that p_sym is in (or should be in) \r\n    CSymbolTableEntry *p_head=&sp_hash_table[ p_sym->mNameChecksum & ((1<<NUM_HASH_BITS)-1) ];\r\n\r\n\tif (p_sym==p_head)\r\n    {\r\n        // p_sym is in the hash table itself, so it must not be deleted because it is an element of\r\n\t\t// a contiguous array, not allocated off the pool.\r\n\r\n        // Check if there are further entries in the list. These will have been allocated off the pool.\r\n        if (p_sym->mpNext)\r\n        {\r\n\t\t\t// There are later entries in the list, so copy the first of these down\r\n\t\t\t// to fill the hole.\r\n\t\t\tCSymbolTableEntry *p_source=p_sym->mpNext;\r\n\t\t\t\r\n\t\t\t// Copy the contents. Not using the assignement operator because that won't link.\r\n\t\t\t// It is declared but not defined so as to cause it not to link, to prevent any problems\r\n\t\t\t// with copying pointers if it gets used anywhere else.\r\n\t\t\tuint32 *p_source_word=(uint32*)p_source;\r\n\t\t\tuint32 *p_dest_word=(uint32*)p_sym;\r\n\t\t\tDbg_MsgAssert((sizeof(CSymbolTableEntry)&3)==0,(\"sizeof(CSymbolTableEntry) not a multiple of 4 ?\"));\r\n\t\t\tfor (uint32 i=0; i<sizeof(CSymbolTableEntry)/4; ++i)\r\n\t\t\t{\r\n\t\t\t\t*p_dest_word++=*p_source_word++;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\t// Need to zero the union so that the destructor does not think there is an undeleted\r\n\t\t\t// pointer in it, which will make it assert.\r\n\t\t\tp_source->mUnion=0;  \r\n\t\t\tdelete p_source;\r\n        }\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Just reset the contents of p_sym.\r\n\t\t\tp_sym->Reset();\r\n\t\t}\r\n    }\r\n    else\r\n    {\r\n        // p_sym is not in the hash table, so it must have been allocated off the pool.\r\n\t\t// In order to unlink it from the list we need to find the previous entry in the list.\r\n\t\t// So search through the list until p_sym is found.\t\t\r\n\t\t\t\t\r\n\t\t// Start with mpNext, cos we know p_sym is not p_head\t\t\r\n\t\tCSymbolTableEntry *p_previous=p_head;\r\n\t\tCSymbolTableEntry *p_search=p_head->mpNext;\r\n\t\twhile (p_search)\r\n\t\t{\r\n\t\t\tif (p_search==p_sym)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tp_previous=p_search;\r\n\t\t\tp_search=p_search->mpNext;\r\n\t\t}\r\n\t\t\r\n\t\tDbg_MsgAssert(p_search,(\"p_sym not found in list ? (checksum='%s')\",FindChecksumName(p_sym->mNameChecksum)));\r\n\t\t\r\n\t\t// Unlink p_sym and delete it.\r\n\t\tp_previous->mpNext=p_sym->mpNext;\r\n\t\tdelete p_sym;\r\n\t}\t\r\n}\r\n\r\n// Adds a new checksum to the directory and returns a pointer to the new entry.\r\nCSymbolTableEntry *CreateNewSymbolEntry(uint32 checksum)\r\n{\r\n\t#ifdef __NOPT_ASSERT__\r\n\tCSymbolTableEntry *p_entry=LookUpSymbol(checksum);\r\n    Dbg_MsgAssert(p_entry==NULL,(\"Symbol '%s' defined twice.\",FindChecksumName(checksum)));\r\n\t#endif\r\n    \r\n    // Get the head pointer of the list where the new symbol needs to go.\r\n\tDbg_MsgAssert(sp_hash_table!=NULL,(\"sp_hash_table is NULL ?\"));\r\n    CSymbolTableEntry *p_sym=&sp_hash_table[ checksum & ((1<<NUM_HASH_BITS)-1) ];\r\n\r\n    // If nothing in here, use this one.\r\n    if (!p_sym->mUsed)\r\n    {\r\n\t\tp_sym->Reset();\r\n        // Set the checksum.\r\n        p_sym->mNameChecksum=checksum;\r\n        // Flag it as used.\r\n        p_sym->mUsed=true;\r\n\t\t// Set the mGotReloaded flag so that other game-specific code can see \r\n\t\t// that the symbol has changed in value.\r\n\t\tp_sym->mGotReloaded=true;\r\n        return p_sym;\r\n    }\r\n\r\n    // Find the last element of the linked list, checking for any checksum\r\n    // clashes on the way.\r\n    CSymbolTableEntry *p_previous=NULL;\r\n    while (p_sym)\r\n    {\r\n        Dbg_MsgAssert(p_sym->mNameChecksum!=checksum,(\"Checksum clash in symbol table: '%s'\",FindChecksumName(checksum)));\r\n        p_previous=p_sym;\r\n        p_sym=p_sym->mpNext;\r\n    }\r\n\r\n\t// Get a new entry from the pool.\r\n    CSymbolTableEntry *p_new=new CSymbolTableEntry;\r\n\t\r\n    // Set the checksum & next pointer.\r\n    p_new->mNameChecksum=checksum;\r\n    // Flag it as used.\r\n    p_new->mUsed=true;\r\n\t// Set the mGotReloaded flag so that other game-specific code can see \r\n\t// that the symbol has changed in value.\r\n\tp_new->mGotReloaded=true;\r\n\t\r\n    p_new->mpNext=NULL;\r\n\r\n    // This assert should never go off, but do it just in case.\r\n    Dbg_MsgAssert(p_previous,(\"NULL p_previous ???\"));\r\n    // Stick pNew on the end of the list.\r\n    p_previous->mpNext=p_new;\r\n\r\n    return p_new;\r\n}\r\n\r\n// This function provides an easy way to loop through all the symbols in the symbol table by\r\n// hiding all the messy logic for stepping through the hash table.\r\n//\r\n// If passed NULL, it will return the first entry in the symbol table (or NULL if there is nothing in it)\r\n// If passed a pointer to a CSymbolTableEntry, it will return the next one, or NULL if none left.\r\n//\r\n// So if you want to loop through all the symbols just do something like:\r\n// CSymbolTableEntry *p_sym=GetNextSymbolTableEntry(); // No need to pass NULL, it defaults to it.\r\n// while (p_sym)\r\n// {\r\n// \t\t// ...\r\n//\t\tp_sym=GetNextSymbolTableEntry(p_sym);\r\n// }\r\n//\r\nCSymbolTableEntry *GetNextSymbolTableEntry(CSymbolTableEntry *p_sym)\r\n{\r\n\t// static's for keeping track of where we are in the hash table.\r\n\tstatic uint32 s_current_hash_index=0;\r\n\tstatic CSymbolTableEntry *sp_last=NULL;\r\n\t\r\n\tif (p_sym==NULL)\r\n\t{\r\n\t\t// They want the first symbol.\r\n\t\ts_current_hash_index=0;\r\n\t\tp_sym=sp_hash_table;\r\n\t\t\r\n\t\t// Step through the hash table entries until a used one is found.\r\n\t\twhile (!p_sym->mUsed)\r\n\t\t{\r\n\t\t\t++s_current_hash_index;\r\n\t\t\t++p_sym;\r\n\t\t\t\r\n\t\t\tif (s_current_hash_index>=(1<<NUM_HASH_BITS))\r\n\t\t\t{\r\n\t\t\t\t// Run out of hash table.\r\n\t\t\t\ts_current_hash_index=0;\r\n\t\t\t\tsp_last=NULL;\r\n\t\t\t\treturn NULL;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\t\r\n\t\tsp_last=p_sym;\r\n\t\treturn p_sym;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Check that p_sym is the same as the last one returned by this function.\r\n\t\t\r\n\t\t// Currently this function assumes that the user is going to be calling it on\r\n\t\t// consecutive elements, such as in the example loop given in the comment for this function.\r\n\t\t// In theory it could be made to work when passed an arbitrary member of the symbol table, but this\r\n\t\t// would require it to search forward from the start each time in order to find out what index the\r\n\t\t// list is at.\r\n\t\t// It was easier and faster to just store the index as a static and assert if called on\r\n\t\t// non-consecutive symbols. (Could fix it if it becomes a problem)\r\n\t\tDbg_MsgAssert(p_sym==sp_last,(\"Non-consecutive call to GetNextSymbolTableEntry\"));\r\n\t}\r\n\t\t\r\n\tp_sym=p_sym->mpNext;\r\n\tif (!p_sym)\r\n\t{\r\n\t\t// We've gone off the end of this linked list, so go onto the next entry in the hash table.\r\n\t\t++s_current_hash_index;\r\n\t\tp_sym=sp_hash_table+s_current_hash_index;\r\n\t\t\r\n\t\tif (s_current_hash_index>=(1<<NUM_HASH_BITS))\r\n\t\t{\r\n\t\t\t// Run out of hash table.\r\n\t\t\ts_current_hash_index=0;\r\n\t\t\tsp_last=NULL;\r\n\t\t\treturn NULL;\r\n\t\t}\t\r\n\t\t\r\n\t\t// Step through the hash table entries until a used one is found.\r\n\t\twhile (!p_sym->mUsed)\r\n\t\t{\r\n\t\t\t++s_current_hash_index;\r\n\t\t\t++p_sym;\r\n\t\t\t\r\n\t\t\tif (s_current_hash_index>=(1<<NUM_HASH_BITS))\r\n\t\t\t{\r\n\t\t\t\ts_current_hash_index=0;\r\n\t\t\t\tsp_last=NULL;\r\n\t\t\t\treturn NULL;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t}\r\n\r\n\tsp_last=p_sym;\r\n\treturn p_sym;\r\n}\r\n\r\nfloat GetFloat(uint32 checksum, EAssertType assert)\r\n{\r\n    CSymbolTableEntry *p_entry=Resolve(checksum);\r\n    if (!p_entry)\r\n    {\r\n\t\tDbg_MsgAssert(!assert,(\"Float '%s' not found.\",FindChecksumName(checksum)));\r\n        return 0.0f;\r\n    }    \r\n    \r\n    switch (p_entry->mType)\r\n    {\r\n    case ESYMBOLTYPE_FLOAT:\r\n        return p_entry->mFloatValue;\r\n        break;\r\n    case ESYMBOLTYPE_INTEGER:\r\n        return (float)p_entry->mIntegerValue;\r\n        break;    \r\n    default:\r\n        Dbg_MsgAssert(0,(\"Symbol '%s' of type '%s' cannot be converted to a float.\",FindChecksumName(checksum),GetTypeName(p_entry->mType)));\r\n        return 0.0f;\r\n        break;\r\n    }        \r\n\t\r\n\treturn 0.0f;\r\n}\r\n\r\nfloat GetFloat(const char *p_name, EAssertType assert)\r\n{\r\n\treturn GetFloat(Crc::GenerateCRCFromString(p_name),assert);\r\n}\r\n\r\nint GetInteger(uint32 checksum, EAssertType assert)\r\n{\r\n    CSymbolTableEntry *p_entry=Resolve(checksum);\r\n    if (!p_entry)\r\n    {\r\n\t\tDbg_MsgAssert(!assert,(\"Integer '%s' not found.\",FindChecksumName(checksum)));\r\n        return 0;\r\n    }    \r\n\r\n    switch (p_entry->mType)\r\n    {\r\n    case ESYMBOLTYPE_FLOAT:\r\n        return (int)p_entry->mFloatValue;\r\n        break;\r\n    case ESYMBOLTYPE_INTEGER:\r\n        return p_entry->mIntegerValue;\r\n        break;    \r\n    default:\r\n        Dbg_MsgAssert(0,(\"Symbol '%s' of type '%s' cannot be converted to an integer.\",FindChecksumName(checksum),GetTypeName(p_entry->mType)));\r\n        return 0;\r\n        break;\r\n    }        \r\n\r\n\treturn 0;\r\n}\r\n\r\nint GetInteger(const char *p_name, EAssertType assert)\r\n{\r\n\treturn GetInteger(Crc::GenerateCRCFromString(p_name),assert);\r\n}\r\n\r\nuint32 GetChecksum(uint32 checksum, EAssertType assert)\r\n{\r\n    CSymbolTableEntry *p_entry=Resolve(checksum);\r\n    if (!p_entry)\r\n    {\r\n\t\tDbg_MsgAssert(!assert,(\"Checksum named '%s' not found.\",FindChecksumName(checksum)));\r\n        return 0;\r\n    }    \r\n\r\n    Dbg_MsgAssert(p_entry->mType==ESYMBOLTYPE_NAME,(\"GetChecksum: Symbol '%s' has the wrong type of '%s'\",FindChecksumName(checksum),GetTypeName(p_entry->mType)));\r\n\treturn p_entry->mChecksum;\t\r\n}\r\n\r\nuint32 GetChecksum(const char *p_name, EAssertType assert)\r\n{\r\n\treturn GetChecksum(Crc::GenerateCRCFromString(p_name),assert);\r\n}\r\n\r\nconst char *GetString(uint32 checksum, EAssertType assert)\r\n{\r\n    CSymbolTableEntry *p_entry=Resolve(checksum);\r\n    if (!p_entry)\r\n    {\r\n\t\tDbg_MsgAssert(!assert,(\"String named '%s' not found.\",FindChecksumName(checksum)));\r\n        return \"\";\r\n    }    \r\n\r\n    Dbg_MsgAssert(p_entry->mType==ESYMBOLTYPE_STRING || p_entry->mType==ESYMBOLTYPE_LOCALSTRING,(\"GetString: Symbol '%s' has the wrong type of '%s'\",FindChecksumName(checksum),GetTypeName(p_entry->mType)));\r\n\tDbg_MsgAssert(p_entry->mpString,(\"NULL p_entry->mpString\"));\r\n\treturn p_entry->mpString;\t\r\n}\r\n\r\nconst char *GetString(const char *p_name, EAssertType assert)\r\n{\r\n\treturn GetString(Crc::GenerateCRCFromString(p_name),assert);\r\n}\r\n\r\nconst char *GetLocalString(uint32 checksum, EAssertType assert)\r\n{\r\n    CSymbolTableEntry *p_entry=Resolve(checksum);\r\n    if (!p_entry)\r\n    {\r\n\t\tDbg_MsgAssert(!assert,(\"Local string named '%s' not found.\",FindChecksumName(checksum)));\r\n        return \"\";\r\n    }    \r\n\r\n    Dbg_MsgAssert(p_entry->mType==ESYMBOLTYPE_LOCALSTRING || p_entry->mType==ESYMBOLTYPE_STRING,(\"GetLocalString: Symbol '%s' has the wrong type of '%s'\",FindChecksumName(checksum),GetTypeName(p_entry->mType)));\r\n\tDbg_MsgAssert(p_entry->mpLocalString,(\"NULL p_entry->mpLocalString\"));\r\n\treturn p_entry->mpLocalString;\t\r\n}\r\n\r\nconst char *GetLocalString(const char *p_name, EAssertType assert)\r\n{\r\n\treturn GetLocalString(Crc::GenerateCRCFromString(p_name),assert);\r\n}\r\n\r\nCVector *GetVector(uint32 checksum, EAssertType assert)\r\n{\r\n    CSymbolTableEntry *p_entry=Resolve(checksum);\r\n    if (!p_entry)\r\n    {\r\n\t\tDbg_MsgAssert(!assert,(\"Vector named '%s' not found.\",FindChecksumName(checksum)));\r\n        return NULL;\r\n    }    \r\n\r\n    Dbg_MsgAssert(p_entry->mType==ESYMBOLTYPE_VECTOR,(\"GetVector: Symbol '%s' has the wrong type of '%s'\",FindChecksumName(checksum),GetTypeName(p_entry->mType)));\r\n\tDbg_MsgAssert(p_entry->mpVector,(\"NULL p_entry->mpVector\"));\r\n\treturn p_entry->mpVector;\t\r\n}\r\n\r\nCVector *GetVector(const char *p_name, EAssertType assert)\r\n{\r\n\treturn GetVector(Crc::GenerateCRCFromString(p_name),assert);\r\n}\r\n\r\nCPair *GetPair(uint32 checksum, EAssertType assert)\r\n{\r\n    CSymbolTableEntry *p_entry=Resolve(checksum);\r\n    if (!p_entry)\r\n    {\r\n\t\tDbg_MsgAssert(!assert,(\"Pair named '%s' not found.\",FindChecksumName(checksum)));\r\n        return NULL;\r\n    }    \r\n\r\n    Dbg_MsgAssert(p_entry->mType==ESYMBOLTYPE_PAIR,(\"GetPair: Symbol '%s' has the wrong type of '%s'\",FindChecksumName(checksum),GetTypeName(p_entry->mType)));\r\n\tDbg_MsgAssert(p_entry->mpPair,(\"NULL p_entry->mpPair\"));\r\n\treturn p_entry->mpPair;\t\r\n}\r\n\r\nCPair *GetPair(const char *p_name, EAssertType assert)\r\n{\r\n\treturn GetPair(Crc::GenerateCRCFromString(p_name),assert);\r\n}\r\n\r\nCStruct *GetStructure(uint32 checksum, EAssertType assert)\r\n{\r\n    CSymbolTableEntry *p_entry=Resolve(checksum);\r\n    if (!p_entry)\r\n    {\r\n\t\tDbg_MsgAssert(!assert,(\"Structure named '%s' not found.\",FindChecksumName(checksum)));\r\n        return NULL;\r\n    }    \r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tif (assert)\r\n\t{\r\n\t\tDbg_MsgAssert(p_entry->mType==ESYMBOLTYPE_STRUCTURE,(\"GetStructure: Symbol '%s' has the wrong type of '%s'\",FindChecksumName(checksum),GetTypeName(p_entry->mType)));\r\n\t}\r\n\telse\r\n\t#endif\r\n\t{\r\n\t\tif (p_entry->mType!=ESYMBOLTYPE_STRUCTURE)\r\n\t\t{\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\tDbg_MsgAssert(p_entry->mpStructure,(\"NULL p_entry->mpStructure\"));\r\n\treturn p_entry->mpStructure;\t\r\n}\r\n\r\nCStruct *GetStructure(const char *p_name, EAssertType assert)\r\n{\r\n\treturn GetStructure(Crc::GenerateCRCFromString(p_name),assert);\r\n}\r\n\r\nCArray *GetArray(uint32 checksum, EAssertType assert)\r\n{\r\n    CSymbolTableEntry *p_entry=Resolve(checksum);\r\n    if (!p_entry)\r\n    {\r\n\t\tDbg_MsgAssert(!assert,(\"Array named '%s' not found.\",FindChecksumName(checksum)));\r\n        return NULL;\r\n    }    \r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tif (assert)\r\n\t{\r\n\t\tDbg_MsgAssert(p_entry->mType==ESYMBOLTYPE_ARRAY,(\"GetArray: Symbol '%s' has the wrong type of '%s'\",FindChecksumName(checksum),GetTypeName(p_entry->mType)));\r\n\t}\r\n\telse\r\n\t#endif\r\n\t{\r\n\t\tif (p_entry->mType!=ESYMBOLTYPE_ARRAY)\r\n\t\t{\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t}\r\n\t\t\t\r\n\tDbg_MsgAssert(p_entry->mpArray,(\"NULL p_entry->mpArray\"));\r\n\treturn p_entry->mpArray;\t\r\n}\r\n\r\nCArray *GetArray(const char *p_name, EAssertType assert)\r\n{\r\n\treturn GetArray(Crc::GenerateCRCFromString(p_name),assert);\r\n}\r\n\r\nbool (*GetCFunc(uint32 checksum, EAssertType assert))(CStruct *, CScript *)\r\n{\r\n\tCSymbolTableEntry *p_entry=Resolve(checksum);\r\n\tif (!p_entry)\r\n\t{\r\n\t\tDbg_MsgAssert(!assert,(\"GetCFunc could not find the symbol '%s'. No symbol of any type exists with that name.\",FindChecksumName(checksum)));\r\n\t\treturn NULL;\r\n\t}\r\n\t\t\r\n\tswitch (p_entry->mType)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_CFUNCTION:\r\n\t\t\tDbg_MsgAssert(p_entry->mpCFunction,(\"NULL p_entry->pCFunction ?\"));\r\n\t\t\treturn p_entry->mpCFunction;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESYMBOLTYPE_MEMBERFUNCTION:\r\n\t\t\tDbg_MsgAssert(0,(\"'%s' is not a C-function, it is a member function.\",FindChecksumName(checksum)));\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\t\r\n\t\t\tDbg_MsgAssert(0,(\"'%s' is not a C-function, but has type '%s'\",FindChecksumName(checksum),GetTypeName(p_entry->mType)));\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\treturn NULL;\t\t\t\r\n}\r\n\r\nbool (*GetCFunc(const char *p_name, EAssertType assert))(CStruct *, CScript *)\r\n{\r\n\treturn GetCFunc(Crc::GenerateCRCFromString(p_name),assert);\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// TODO: Remove these next functions at some point.\r\n// They are only included to provide back compatibility with the old code without\r\n// having to change thousands of occurrences.\r\nint GetInt(uint32 checksum, bool assert)\r\n{\r\n\treturn GetInteger(checksum,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nint GetInt(const char *p_name, bool assert)\r\n{\r\n\treturn GetInteger(p_name,assert?ASSERT:NO_ASSERT);\r\n}\r\n\r\nbool (*GetCFuncPointer(uint32 checksum, EAssertType assert))(CStruct *, CScript *)\r\n{\r\n\treturn GetCFunc(checksum, assert);\r\n}\r\n\r\nbool (*GetCFuncPointer(const char *p_name, EAssertType assert))(CStruct *, CScript *)\r\n{\r\n\treturn GetCFunc(p_name, assert);\r\n}\r\n///////////////////////////////////////////////////////////////////////////////////\r\n\r\n} // namespace Script\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/symboltable.h",
    "content": "#ifndef\t__SCRIPTING_SYMBOLTABLE_H\r\n#define\t__SCRIPTING_SYMBOLTABLE_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __SYS_MEM_POOLABLE_H\r\n#include <sys/mem/poolable.h>\r\n#endif\r\n\r\n#ifndef\t__SCRIPTING_SYMBOLTYPE_H\r\n#include <gel/scripting/symboltype.h> // For ESymbolType\r\n#endif\r\n\r\n#ifndef\t__SCRIPTING_SCRIPTDEFS_H\r\n#include <gel/scripting/scriptdefs.h> // For EAssertType\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\r\n// If defined then the usage of each cfunc and member func will be counted on startup\r\n// by scanning through all the scripts.\r\n// Uses a bit of memory so only define on debug builds.\r\n#ifdef __NOPT_ASSERT__\r\n//#define COUNT_USAGE\r\n#endif\r\n\r\n#define NUM_HASH_BITS 12\r\n\r\nclass CPair;\r\nclass CVector;\r\nclass CArray;\r\nclass CStruct;\r\nclass CScript;\r\n\r\n#ifdef __PLAT_WN32__\r\nclass CSymbolTableEntry\r\n#else\r\nclass CSymbolTableEntry : public Mem::CPoolable<CSymbolTableEntry>\r\n#endif\r\n{\r\npublic:\r\n\t// Note: The placement of these bitfielded members is important. The CPoolable class\r\n\t// has an overhead of 1 byte, so by putting the small members here they will use up the 3\r\n\t// byte padding, keeping the size of this class down. There are 4000 or so of these, so\r\n\t// the size needs to be kept as small as possible.\r\n\t\r\n\t// If a symbol is deleted and recreated by parse.cpp then this flag will get set.\r\n\t// This is so that other code can use this to detect whether a symbol has changed due to a reload.\r\n\t// For example, file.cpp checks the script mGotReloaded flags after loading a qb, and if reloaded\r\n\t// it will then restart all existing CScript's that refer to it so that  they do not crash due to \r\n\t// invalid pointers.\r\n\t// Similarly, if a qb gets unloaded any existing CScript's that refer to a script in it must be stopped.\r\n\t// Also, in THPS, if the symbol NodeArray gets reloaded then name prefix information must be regenerated.\r\n\t//\r\n\tuint8 mGotReloaded:1;\r\n\t\r\n\t// The symbols in the contiguous array use this flag to indicate if they are occupied.\r\n    bool mUsed:1;\r\n\t\r\n    uint8 mType;\r\n\t\r\n\t#ifdef COUNT_USAGE\r\n\tuint32 mUsage;\r\n\t#endif\r\n\t\r\n\t// This used to just store the upper checksum bits, because the lower bits are implied\r\n\t// by the index of this entries list in the hash table.\r\n\t// This was just to save space, because of the fairly large (8000ish) number of symbols.\r\n\t// However, it makes the LookUpSymbol function a little bit slower because of the extra bit\r\n\t// operations needed to compare, and also it makes the RemoveSymbol function more complex\r\n\t// and slower because it has to search the whole symbol table in order to find the previous\r\n\t// entry, so that the current one can be unlinked.\r\n\t// In skate4, since we have the ability to unload qb's, this should reduce the requirement\r\n\t// for such a large symbol table, so I decided to store the whole checksum instead.\r\n\t// Simpler, faster and neater! Just uses a wee bit more space. Not a huge amount though,\r\n\t// probably only 25K ish.\r\n    uint32 mNameChecksum;\r\n\t\r\n\t// Required so that all the symbols from a particular a qb can be unloaded.\r\n\t// Also handy for debugging.\r\n\t// Could perhaps make it a 16-bit index into an array of file names rather than a checksum,\r\n\t// then it would pack next to the above mUsed and mType and they would all 3 only use up 4 bytes\r\n\t// altogether rather than 8 ...\r\n\tuint32 mSourceFileNameChecksum;\r\n\r\n    union\r\n    {\r\n        int mIntegerValue;\r\n        float mFloatValue;\r\n        char *mpString;\r\n        char *mpLocalString;\r\n        CPair *mpPair;\r\n        CVector *mpVector;\r\n        CStruct *mpStructure;\r\n#ifdef __PLAT_NGC__\r\n        uint32 mScriptOffset;\r\n#else\r\n        uint8 *mpScript;\r\n#endif\t\t// __PLAT_NGC__\r\n        bool (*mpCFunction)(CStruct *pParams, CScript *pCScript);\r\n        CArray *mpArray;\r\n        uint32 mChecksum; // Used when Type is ESYMBOLTYPE_NAME\r\n\t\tuint32 mUnion; // For when all the above need to be zeroed \r\n    };\r\n\r\n    CSymbolTableEntry *mpNext;\r\n\r\n\tCSymbolTableEntry();\r\n\t#ifdef __NOPT_ASSERT__\r\n\t~CSymbolTableEntry();\r\n\t#endif\r\n\r\n\t// These cannot be defined because it would cause a cyclic dependency, because\r\n\t// a CSymbolTableEntry member function can't create things. So declare them but leave them undefined\r\n\t// so that it will not link if they are attempted to be used.\r\n\tCSymbolTableEntry( const CSymbolTableEntry& rhs );\r\n\tCSymbolTableEntry& operator=( const CSymbolTableEntry& rhs );\r\n\t\r\n\tvoid Reset();\r\n};\r\n\r\nvoid CreateSymbolHashTable();\r\nvoid DestroySymbolHashTable();\r\nCSymbolTableEntry *LookUpSymbol(uint32 checksum);\r\nCSymbolTableEntry *LookUpSymbol(const char *p_name);\r\nCSymbolTableEntry *Resolve(uint32 checksum);\r\nCSymbolTableEntry *Resolve(const char *p_name);\r\nvoid RemoveSymbol(CSymbolTableEntry *p_sym);\r\nCSymbolTableEntry *CreateNewSymbolEntry(uint32 checksum);\r\nCSymbolTableEntry *GetNextSymbolTableEntry(CSymbolTableEntry *p_sym=NULL);\r\n\r\nfloat GetFloat(uint32 checksum, EAssertType assert=NO_ASSERT);\r\nfloat GetFloat(const char *p_name, EAssertType assert=NO_ASSERT);\r\nint GetInteger(uint32 checksum, EAssertType assert=NO_ASSERT);\r\nint GetInteger(const char *p_name, EAssertType assert=NO_ASSERT);\r\nuint32 GetChecksum(uint32 checksum, EAssertType assert=NO_ASSERT);\r\nuint32 GetChecksum(const char *p_name, EAssertType assert=NO_ASSERT);\r\nconst char *GetString(uint32 checksum, EAssertType assert=NO_ASSERT);\r\nconst char *GetString(const char *p_name, EAssertType assert=NO_ASSERT);\r\nconst char *GetLocalString(uint32 checksum, EAssertType assert=NO_ASSERT);\r\nconst char *GetLocalString(const char *p_name, EAssertType assert=NO_ASSERT);\r\nCVector *GetVector(uint32 checksum, EAssertType assert=NO_ASSERT);\r\nCVector *GetVector(const char *p_name, EAssertType assert=NO_ASSERT);\r\nCPair *GetPair(uint32 checksum, EAssertType assert=NO_ASSERT);\r\nCPair *GetPair(const char *p_name, EAssertType assert=NO_ASSERT);\r\nCStruct *GetStructure(uint32 checksum, EAssertType assert=NO_ASSERT);\r\nCStruct *GetStructure(const char *p_name, EAssertType assert=NO_ASSERT);\r\nCArray *GetArray(uint32 checksum, EAssertType assert=NO_ASSERT);\r\nCArray *GetArray(const char *p_name, EAssertType assert=NO_ASSERT);\r\nbool (*GetCFunc(uint32 checksum, EAssertType assert=NO_ASSERT))(CStruct *, CScript *);\r\nbool (*GetCFunc(const char *p_name, EAssertType assert=NO_ASSERT))(CStruct *, CScript *);\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// TODO: Remove these next functions at some point.\r\n// They are only included to provide back compatibility with the old code without\r\n// having to change thousands of occurrences of calls to GetInt\r\nint GetInt(uint32 checksum, bool assert=true);\r\nint GetInt(const char *p_name, bool assert=true);\r\nbool (*GetCFuncPointer(uint32 checksum, EAssertType assert=NO_ASSERT))(CStruct *, CScript *);\r\nbool (*GetCFuncPointer(const char *p_name, EAssertType assert=NO_ASSERT))(CStruct *, CScript *);\r\n///////////////////////////////////////////////////////////////////////////////////\r\n\r\n} // namespace Script\r\n\r\n#endif // #ifndef\t__SCRIPTING_SYMBOLTABLE_H\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/symboltype.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// symboltype.cpp\t\tKSH 22 Oct 2001\r\n//\r\n// Just a utility function for printing a type name.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <core/defines.h>\r\n#include <gel/scripting/symboltype.h>\r\n\r\nnamespace Script\r\n{\r\n\r\n#ifdef __NOPT_ASSERT__\r\nconst char *GetTypeName(uint8 type)\r\n{\r\n\tswitch (type)\r\n\t{\r\n\tcase ESYMBOLTYPE_NONE:\r\n\t\treturn \"None\";\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_INTEGER:\r\n\t\treturn \"Integer\";\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_FLOAT:\r\n\t\treturn \"Float\";\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_STRING:\r\n\t\treturn \"String\";\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_LOCALSTRING:\r\n\t\treturn \"Local String\";\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_PAIR:\r\n\t\treturn \"Pair\";\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_VECTOR:\r\n\t\treturn \"Vector\";\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_QSCRIPT:\r\n\t\treturn \"Script\";\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_CFUNCTION:\r\n\t\treturn \"C-Function\";\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_MEMBERFUNCTION:\r\n\t\treturn \"Member Function\";\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_STRUCTURE:\r\n\t\treturn \"Structure\";\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_STRUCTUREPOINTER:\r\n\t\treturn \"Structure Pointer\";\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_ARRAY:\r\n\t\treturn \"Array\";\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_NAME:\r\n\t\treturn \"Name\";\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn \"Unknown\";\r\n\t\tbreak;\t\t\r\n\t}\r\n}\r\n#else\r\nconst char *GetTypeName(uint8 type)\r\n{\r\n\treturn \"(Hey, don't use GetTypeName on the CD!)\";\r\n}\r\n#endif\r\n\r\n} // namespace Script\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/symboltype.h",
    "content": "#ifndef\t__SCRIPTING_SYMBOLTYPE_H\r\n#define\t__SCRIPTING_SYMBOLTYPE_H\r\n\r\nnamespace Script\r\n{\r\n// Values for CSymbolTableEntry::mType and CComponent::mType\r\nenum ESymbolType\r\n{\r\n    ESYMBOLTYPE_NONE=0,\r\n    ESYMBOLTYPE_INTEGER,\r\n    ESYMBOLTYPE_FLOAT,\r\n    ESYMBOLTYPE_STRING,\r\n    ESYMBOLTYPE_LOCALSTRING,\r\n    ESYMBOLTYPE_PAIR,\r\n    ESYMBOLTYPE_VECTOR,\r\n    ESYMBOLTYPE_QSCRIPT,\r\n    ESYMBOLTYPE_CFUNCTION,\r\n    ESYMBOLTYPE_MEMBERFUNCTION,\r\n    ESYMBOLTYPE_STRUCTURE,\r\n\t// ESYMBOLTYPE_STRUCTUREPOINTER is not really used any more. It is only supported as a valid\r\n\t// type that can be sent to AddComponent, which is an old CStruct member function that is\r\n\t// still supported for back compatibility. mType will never be ESYMBOLTYPE_STRUCTUREPOINTER\r\n    ESYMBOLTYPE_STRUCTUREPOINTER,\r\n    ESYMBOLTYPE_ARRAY,\r\n    ESYMBOLTYPE_NAME,\r\n\t\r\n\t// These symbols are just used for memory optimization by the\r\n\t// CScriptStructure WriteToBuffer and ReadFromBuffer functions.\r\n\tESYMBOLTYPE_INTEGER_ONE_BYTE,\r\n\tESYMBOLTYPE_INTEGER_TWO_BYTES,\r\n\tESYMBOLTYPE_UNSIGNED_INTEGER_ONE_BYTE,\r\n\tESYMBOLTYPE_UNSIGNED_INTEGER_TWO_BYTES,\r\n\tESYMBOLTYPE_ZERO_INTEGER,\r\n\tESYMBOLTYPE_ZERO_FLOAT,\r\n\t\r\n\t// Warning! Don't exceed 256 entries, since Type is a uint8 in SSymbolTableEntry\r\n\t// New warning! Don't exceed 64 entries, because the top two bits of the symbol\r\n\t// type are used to indicate whether the name checksum has been compressed to\r\n\t// a 8 or 16 bit index, when WriteToBuffer writes out parameter names.\r\n};\r\n\r\n// These get masked onto the symbol type in CScriptStructure::WriteToBuffer if\r\n// the following name checksum matches one in the lookup table. (Defined in compress.q)\r\n#define MASK_8_BIT_NAME_LOOKUP (1<<7)\r\n#define MASK_16_BIT_NAME_LOOKUP (1<<6)\r\n\r\nconst char *GetTypeName(uint8 type);\r\n\r\n// TODO: Remove these at some point, they are just to allow compilation of the existing game code\r\n// without having to change all the occurrences.\r\n#define ESYMBOLTYPE_NONE                       Script::ESYMBOLTYPE_NONE                      \r\n#define ESYMBOLTYPE_INTEGER                    Script::ESYMBOLTYPE_INTEGER                   \r\n#define ESYMBOLTYPE_FLOAT                      Script::ESYMBOLTYPE_FLOAT                     \r\n#define ESYMBOLTYPE_STRING                     Script::ESYMBOLTYPE_STRING                    \r\n#define ESYMBOLTYPE_LOCALSTRING                Script::ESYMBOLTYPE_LOCALSTRING               \r\n#define ESYMBOLTYPE_PAIR                       Script::ESYMBOLTYPE_PAIR                      \r\n#define ESYMBOLTYPE_VECTOR                     Script::ESYMBOLTYPE_VECTOR                    \r\n#define ESYMBOLTYPE_QSCRIPT                    Script::ESYMBOLTYPE_QSCRIPT                   \r\n#define ESYMBOLTYPE_CFUNCTION                  Script::ESYMBOLTYPE_CFUNCTION                 \r\n#define ESYMBOLTYPE_MEMBERFUNCTION             Script::ESYMBOLTYPE_MEMBERFUNCTION            \r\n#define ESYMBOLTYPE_STRUCTURE                  Script::ESYMBOLTYPE_STRUCTURE                 \r\n#define ESYMBOLTYPE_STRUCTUREPOINTER           Script::ESYMBOLTYPE_STRUCTUREPOINTER          \r\n#define ESYMBOLTYPE_ARRAY                      Script::ESYMBOLTYPE_ARRAY                     \r\n#define ESYMBOLTYPE_NAME                       Script::ESYMBOLTYPE_NAME                      \r\n#define ESYMBOLTYPE_INTEGER_ONE_BYTE           Script::ESYMBOLTYPE_INTEGER_ONE_BYTE          \r\n#define ESYMBOLTYPE_INTEGER_TWO_BYTES          Script::ESYMBOLTYPE_INTEGER_TWO_BYTES         \r\n#define ESYMBOLTYPE_UNSIGNED_INTEGER_ONE_BYTE  Script::ESYMBOLTYPE_UNSIGNED_INTEGER_ONE_BYTE \r\n#define ESYMBOLTYPE_UNSIGNED_INTEGER_TWO_BYTES Script::ESYMBOLTYPE_UNSIGNED_INTEGER_TWO_BYTES\r\n#define ESYMBOLTYPE_ZERO_INTEGER               Script::ESYMBOLTYPE_ZERO_INTEGER              \r\n#define ESYMBOLTYPE_ZERO_FLOAT                 Script::ESYMBOLTYPE_ZERO_FLOAT                \r\n\r\n\r\n\r\n}\r\n\r\n#endif // #ifndef\t__SCRIPTING_SYMBOLTYPE_H\r\n"
  },
  {
    "path": "Code/Gel/Scripting/tokens.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// tokens.cpp\t\tKSH 22 Oct 2001\r\n//\r\n// Just a function for getting a token name.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <gel/scripting/tokens.h>\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h> // For __NOPT_ASSERT__\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\r\n#ifdef __NOPT_ASSERT__\r\nconst char *GetTokenName(EScriptToken token)\r\n{\r\n\tswitch (token)\r\n\t{\r\n\tcase ESCRIPTTOKEN_ENDOFFILE:\r\n\t\treturn \"ENDOFFILE\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_ENDOFLINE:\r\n\t\treturn \"ENDOFLINE\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_ENDOFLINENUMBER:\r\n\t\treturn \"ENDOFLINENUMBER\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_STARTSTRUCT:\r\n\t\treturn \"{\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_ENDSTRUCT:\r\n\t\treturn \"}\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_STARTARRAY:\r\n\t\treturn \"[\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_ENDARRAY:\r\n\t\treturn \"]\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_EQUALS:\r\n\t\treturn \"=\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_DOT:\r\n\t\treturn \".\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_COMMA:\r\n\t\treturn \",\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_MINUS:\r\n\t\treturn \"-\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_ADD:\r\n\t\treturn \"+\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_DIVIDE:\r\n\t\treturn \"/\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_MULTIPLY:\r\n\t\treturn \"*\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_OPENPARENTH:\r\n\t\treturn \"(\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_CLOSEPARENTH:\r\n\t\treturn \")\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_DEBUGINFO:\r\n\t\treturn \"DEBUGINFO\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_SAMEAS:\r\n\t\treturn \"==\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_LESSTHAN:\r\n\t\treturn \"<\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_LESSTHANEQUAL:\r\n\t\treturn \"<=\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_GREATERTHAN:\r\n\t\treturn \">\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_GREATERTHANEQUAL:\r\n\t\treturn \">=\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_NAME:\r\n\t\treturn \"NAME\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_INTEGER:\r\n\t\treturn \"INTEGER\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_HEXINTEGER:\r\n\t\treturn \"HEXINTEGER\";\r\n\t\tbreak;\r\n    case ESCRIPTTOKEN_ENUM:\r\n\t\treturn \"ENUM\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_FLOAT:\r\n\t\treturn \"FLOAT\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_STRING:\r\n\t\treturn \"STRING\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_LOCALSTRING:\r\n\t\treturn \"LOCALSTRING\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_ARRAY:\r\n\t\treturn \"ARRAY\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_VECTOR:\r\n\t\treturn \"VECTOR\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_PAIR:\r\n\t\treturn \"PAIR\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_BEGIN:\r\n\t\treturn \"BEGIN\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_REPEAT:\r\n\t\treturn \"REPEAT\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_BREAK:\r\n\t\treturn \"BREAK\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_SCRIPT:\r\n\t\treturn \"SCRIPT\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_ENDSCRIPT:\r\n\t\treturn \"ENDSCRIPT\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_IF:\r\n\t\treturn \"IF\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_ELSE:\r\n\t\treturn \"ELSE\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_ELSEIF:\r\n\t\treturn \"ELSEIF\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_ENDIF:\r\n\t\treturn \"ENDIF\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_RETURN:\r\n\t\treturn \"RETURN\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_NOT:\r\n\t\treturn \"NOT\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_SWITCH:\r\n\t\treturn \"SWITCH\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_ENDSWITCH:\r\n\t\treturn \"ENDSWITCH\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_CASE:\r\n\t\treturn \"CASE\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_DEFAULT:\r\n\t\treturn \"DEFAULT\";\r\n\t\tbreak;\r\n    case ESCRIPTTOKEN_UNDEFINED:\r\n\t\treturn \"UNDEFINED\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_CHECKSUM_NAME:\r\n\t\treturn \"CHECKSUM_NAME\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_KEYWORD_ALLARGS:\r\n\t\treturn \"<...>\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_ARG:\t\r\n\t\treturn \"ARG\";\r\n\t\tbreak;\r\n\t\t\r\n\tcase ESCRIPTTOKEN_KEYWORD_RANDOM:\r\n\t\treturn \"RANDOM\";\r\n\t\tbreak;\r\n\r\n\tcase ESCRIPTTOKEN_KEYWORD_RANDOM2:\r\n\t\treturn \"RANDOM2\";\r\n\t\tbreak;\r\n\t\t\r\n\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_NO_REPEAT:\r\n\t\treturn \"RANDOM_NO_REPEAT\";\r\n\t\tbreak;\r\n\r\n\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_PERMUTE:\r\n\t\treturn \"RANDOM_PERMUTE\";\r\n\t\tbreak;\r\n\t\t\r\n\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE:\r\n\t\treturn \"RANDOM_RANGE\";\r\n\t\tbreak;\r\n\r\n\tcase ESCRIPTTOKEN_KEYWORD_RANDOM_RANGE2:\r\n\t\treturn \"RANDOM_RANGE2\";\r\n\t\tbreak;\r\n\t\t\t\r\n\tcase ESCRIPTTOKEN_OR:\r\n\t\treturn \"OR\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_AND:\r\n\t\treturn \"AND\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_XOR:\r\n\t\treturn \"XOR\";\r\n\t\tbreak;\r\n\t\r\n\tcase ESCRIPTTOKEN_SHIFT_LEFT:\r\n\t\treturn \"SHIFT_LEFT\";\r\n\t\tbreak;\r\n\tcase ESCRIPTTOKEN_SHIFT_RIGHT:\r\n\t\treturn \"SHIFT_RIGHT\";\r\n\t\tbreak;\r\n\t\t\r\n\tcase ESCRIPTTOKEN_COLON:\r\n\t\treturn \"COLON\";\r\n\t\tbreak;\r\n\t\t\r\n\tcase ESCRIPTTOKEN_RUNTIME_CFUNCTION:\r\n\t\treturn \"RUNTIME-CFUNCTION\";\r\n\t\tbreak;\r\n\t\t\r\n\tcase ESCRIPTTOKEN_RUNTIME_MEMBERFUNCTION:\r\n\t\treturn \"RUNTIME-MEMBERFUNCTION\";\r\n\t\tbreak;\r\n\t\t\t\r\n\tdefault:\r\n\t\treturn \"Unknown\";\r\n\t\tbreak;\r\n\t}\t\t\r\n}\r\n#endif // #ifdef __NOPT_ASSERT__\r\n\r\n} // namespace Script\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/tokens.h",
    "content": "\r\n// This file gets included in the compiler tool code (qcomp.cpp) as well as\r\n// in the PS2 code. So whenever this file is modified, qcomp must be recompiled.\r\n// qcomp.exe is a PC executable that converts a .q file into a .qb file\r\n// for loading into the PS2.\r\n\r\n// The following are token values used to represent the various things in\r\n// the .qb.\r\n\r\n#ifndef __SCRIPTING_TOKENS_H\r\n#define __SCRIPTING_TOKENS_H\r\n\r\nnamespace Script\r\n{\r\n// Note! Careful if inserting new token values here, because this file also gets\r\n// included in the qcomp tool.\r\n// If the numerical values of the symbols here change, all the .qb's must be\r\n// recompiled. This won't automatically happen, so everyone will have to be\r\n// told to delete their .qb's to force them to be recompiled.\r\n\r\n// When adding a new token value, it would be best to add it to the bottom, to\r\n// prevent having to tell everyone to recompile all the qb's.\r\nenum EScriptToken\r\n{\r\n\t// Misc\r\n\tESCRIPTTOKEN_ENDOFFILE,\t\t\t// 0\r\n\tESCRIPTTOKEN_ENDOFLINE,\t\t\t// 1\r\n\tESCRIPTTOKEN_ENDOFLINENUMBER,   // 2\r\n\tESCRIPTTOKEN_STARTSTRUCT,       // 3\r\n\tESCRIPTTOKEN_ENDSTRUCT,         // 4\r\n\tESCRIPTTOKEN_STARTARRAY,        // 5\r\n\tESCRIPTTOKEN_ENDARRAY,          // 6\r\n\tESCRIPTTOKEN_EQUALS,            // 7\r\n\tESCRIPTTOKEN_DOT,               // 8\r\n\tESCRIPTTOKEN_COMMA,             // 9\r\n\tESCRIPTTOKEN_MINUS,             // 10\r\n\tESCRIPTTOKEN_ADD,               // 11\r\n\tESCRIPTTOKEN_DIVIDE,            // 12\r\n\tESCRIPTTOKEN_MULTIPLY,          // 13\r\n\tESCRIPTTOKEN_OPENPARENTH,       // 14\r\n\tESCRIPTTOKEN_CLOSEPARENTH,      // 15\r\n\r\n\t// This is ignored by the interpreter.\r\n\t// Allows inclusion of source level debugging info, eg line number.\r\n\tESCRIPTTOKEN_DEBUGINFO,\t\t\t// 16\r\n\r\n\t// Comparisons\r\n\tESCRIPTTOKEN_SAMEAS,\t\t\t// 17\r\n\tESCRIPTTOKEN_LESSTHAN,\t\t\t// 18\r\n\tESCRIPTTOKEN_LESSTHANEQUAL,     // 19\r\n\tESCRIPTTOKEN_GREATERTHAN,       // 20\r\n\tESCRIPTTOKEN_GREATERTHANEQUAL,  // 21\r\n\r\n\t// Types\r\n\tESCRIPTTOKEN_NAME,\t\t\t\t// 22\r\n\tESCRIPTTOKEN_INTEGER,\t\t\t// 23\r\n\tESCRIPTTOKEN_HEXINTEGER,        // 24\r\n    ESCRIPTTOKEN_ENUM,              // 25\r\n\tESCRIPTTOKEN_FLOAT,             // 26\r\n\tESCRIPTTOKEN_STRING,            // 27\r\n\tESCRIPTTOKEN_LOCALSTRING,       // 28\r\n\tESCRIPTTOKEN_ARRAY,             // 29\r\n\tESCRIPTTOKEN_VECTOR,            // 30\r\n\tESCRIPTTOKEN_PAIR,\t\t\t\t// 31\r\n\r\n\t// Key words\r\n\tESCRIPTTOKEN_KEYWORD_BEGIN,\t\t// 32\r\n\tESCRIPTTOKEN_KEYWORD_REPEAT,    // 33\r\n\tESCRIPTTOKEN_KEYWORD_BREAK,     // 34\r\n\tESCRIPTTOKEN_KEYWORD_SCRIPT,    // 35\r\n\tESCRIPTTOKEN_KEYWORD_ENDSCRIPT, // 36\r\n\tESCRIPTTOKEN_KEYWORD_IF,        // 37\r\n\tESCRIPTTOKEN_KEYWORD_ELSE,      // 38\r\n\tESCRIPTTOKEN_KEYWORD_ELSEIF,    // 39\r\n\tESCRIPTTOKEN_KEYWORD_ENDIF,\t\t// 40\r\n\tESCRIPTTOKEN_KEYWORD_RETURN,\t// 41\r\n    \r\n    ESCRIPTTOKEN_UNDEFINED,\t\t\t// 42\r\n\t\r\n\t// For debugging\t\t\t\t\t  \r\n\tESCRIPTTOKEN_CHECKSUM_NAME,\t\t// 43\r\n\t\r\n\t// Token for the <...> symbol\t\t\t\t\t\r\n\tESCRIPTTOKEN_KEYWORD_ALLARGS,\t// 44\r\n\t// Token that preceds a name when the name is enclosed in < > in the source.\r\n\tESCRIPTTOKEN_ARG,\t\t\t\t// 45\r\n\t\r\n\t// A relative jump. Used to speed up if-else-endif and break statements, and\r\n\t// used to jump to the end of lists of items in the random operator.\r\n\tESCRIPTTOKEN_JUMP,\t\t\t\t// 46\r\n\t// Precedes a list of items that are to be randomly chosen from.\r\n\tESCRIPTTOKEN_KEYWORD_RANDOM,    // 47\r\n\r\n\t// Precedes two integers enclosed in parentheses.\r\n\tESCRIPTTOKEN_KEYWORD_RANDOM_RANGE,\t// 48\r\n\t\r\n\t// Only used internally by qcomp, never appears in a .qb\r\n\tESCRIPTTOKEN_AT,\t\t\t\t// 49\r\n\t\r\n\t// Logical operators\r\n\tESCRIPTTOKEN_OR,\t\t\t\t// 50\r\n\tESCRIPTTOKEN_AND,\t\t\t\t// 51\r\n\tESCRIPTTOKEN_XOR,\t\t\t\t// 52\r\n\t\t\t\t\t\t\t\t\t\r\n\t// Shift operators\r\n\tESCRIPTTOKEN_SHIFT_LEFT,\t\t// 53\r\n\tESCRIPTTOKEN_SHIFT_RIGHT,\t\t// 54\r\n\t\r\n\t// These versions use the Rnd2 function, for use in certain things so as not to mess up\r\n\t// the determinism of the regular Rnd function in replays.\r\n\tESCRIPTTOKEN_KEYWORD_RANDOM2,\t\t// 55\r\n\tESCRIPTTOKEN_KEYWORD_RANDOM_RANGE2, // 56\r\n\t\r\n\tESCRIPTTOKEN_KEYWORD_NOT,\t\t\t// 57\r\n\tESCRIPTTOKEN_KEYWORD_AND,\t\t\t// 58\r\n\tESCRIPTTOKEN_KEYWORD_OR,            // 59\r\n\tESCRIPTTOKEN_KEYWORD_SWITCH,       \t// 60\r\n\tESCRIPTTOKEN_KEYWORD_ENDSWITCH,   \t// 61\r\n\tESCRIPTTOKEN_KEYWORD_CASE,          // 62\r\n\tESCRIPTTOKEN_KEYWORD_DEFAULT,\t\t// 63\r\n\r\n\tESCRIPTTOKEN_KEYWORD_RANDOM_NO_REPEAT,\t// 64\r\n\tESCRIPTTOKEN_KEYWORD_RANDOM_PERMUTE,\t// 65\r\n\r\n\tESCRIPTTOKEN_COLON,\t\t// 66\r\n\t\r\n\t// These are calculated at runtime in the game code by PreProcessScripts,\r\n\t// so they never appear in a qb file.\r\n\tESCRIPTTOKEN_RUNTIME_CFUNCTION,\t// 67\r\n\tESCRIPTTOKEN_RUNTIME_MEMBERFUNCTION, // 68\r\n\t\r\n\t// Warning! Do not exceed 256 entries, since these are stored in bytes.\r\n};\r\n\r\nconst char *GetTokenName(EScriptToken token);\r\n\r\n} // namespace Script\r\n\r\n#endif // #ifndef __SCRIPTING_TOKENS_H\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/utils.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// utils.cpp\t\tKSH 22 Oct 2001\r\n//\r\n// Misc script utility functions.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/parse.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/string.h>\r\n\r\n// Some defines that affect how PrintContents works:\r\n\r\n// If defined, then if a structure contains a reference to a global structure, PrintContents\r\n// will print the contents of that structure too.\r\n// (Added this define so that it can be disabled for viewing the mem card career-save structure,\r\n// which has lots of references and takes ages to print if they are all expanded)\r\n#define EXPAND_GLOBAL_STRUCTURE_REFERENCES\r\n\r\n// Enables a for-loop to slow down PrintContents so that printf can catch up.\r\n// (Needed for viewing big mem card structures)\r\n//#define SLOW_DOWN_PRINTCONTENTS\r\n\r\nnamespace Script\r\n{\r\n\r\nstatic uint8 *sWriteCompressedName(uint8 *p_buffer, uint8 SymbolType, uint32 NameChecksum);\r\nstatic uint32 sIntegerWriteToBuffer(uint32 Name, int val, uint8 *p_buffer, uint32 BufferSize);\r\nstatic uint32 sFloatWriteToBuffer(uint32 Name, float val, uint8 *p_buffer, uint32 BufferSize);\r\nstatic uint32 sChecksumWriteToBuffer(uint32 Name, uint32 Checksum, uint8 *p_buffer, uint32 BufferSize);\r\nstatic uint32 sStringWriteToBuffer(uint32 Name, const char *pString, uint8 *p_buffer, uint32 BufferSize);\r\nstatic uint32 sLocalStringWriteToBuffer(uint32 Name, const char *pString, uint8 *p_buffer, uint32 BufferSize);\r\nstatic uint32 sPairWriteToBuffer(uint32 Name, CPair *pPair, uint8 *p_buffer, uint32 BufferSize);\r\nstatic uint32 sVectorWriteToBuffer(uint32 Name, CVector *pVector, uint8 *p_buffer, uint32 BufferSize);\r\nstatic uint32 sStructureWriteToBuffer(uint32 Name, CStruct *pStructure, uint8 *p_buffer, uint32 BufferSize, EAssertType assert);\r\nstatic uint32 sArrayWriteToBuffer(uint32 Name, CArray *pArray, uint8 *p_buffer, uint32 BufferSize, EAssertType assert);\r\n\r\n#ifdef __NOPT_ASSERT__\r\nstatic void   sDoIndent(int indent);\r\n\r\nstatic void sDoIndent(int indent)\r\n{\r\n\tfor (int i=0; i<indent; ++i)\r\n\t{\r\n\t\tprintf(\" \");\r\n\t}\r\n}\r\n#endif\r\n\r\nvoid PrintContents(const CArray *p_array, int indent)\r\n{\r\n#ifdef __NOPT_ASSERT__\t\r\n\tDbg_MsgAssert(p_array,(\"NULL p_array\"));\r\n\tint size=p_array->GetSize();\r\n\tESymbolType type=p_array->GetType();\r\n\t\r\n\tif (!indent)\r\n\t{\r\n\t\tprintf(\"Contents of Array=\\n\");\r\n\t}\r\n\t\r\n\tsDoIndent(indent);\r\n\tprintf(\"[\\n\");\r\n\tindent+=3;\r\n\t\r\n\tint int_column_count=0;\r\n\tfor (int i=0; i<size; ++i)\r\n\t{\r\n\t\tif (type!=ESYMBOLTYPE_STRUCTURE && type!=ESYMBOLTYPE_ARRAY)\r\n\t\t{\r\n\t\t\tif (type!=ESYMBOLTYPE_INTEGER || (type==ESYMBOLTYPE_INTEGER && int_column_count==0))\r\n\t\t\t{\r\n\t\t\t\tsDoIndent(indent);\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\t\r\n        switch (type)\r\n        {\r\n        case ESYMBOLTYPE_INTEGER:\r\n\t\t\tif (i<size-1)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"%d,\",p_array->GetInteger(i));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tprintf(\"%d\\n\",p_array->GetInteger(i));\r\n\t\t\t}\t\r\n\t\t\t++int_column_count;\r\n\t\t\tif (int_column_count==15)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"\\n\");\r\n\t\t\t\tint_column_count=0;\r\n\t\t\t}\r\n            break;\r\n        case ESYMBOLTYPE_FLOAT:\r\n            printf(\"%f\\n\",p_array->GetFloat(i));\r\n            break;\r\n        case ESYMBOLTYPE_STRING:\r\n\t\t{\r\n\t\t\tconst char *p_string=p_array->GetString(i);\r\n\t\t\tif (p_string)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"\\\"%s\\\"\\n\",p_string);\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tprintf(\"NULL string\\n\");\r\n\t\t\t}\t\r\n            break;\r\n\t\t}\t\r\n        case ESYMBOLTYPE_LOCALSTRING:\r\n\t\t{\r\n\t\t\tconst char *p_string=p_array->GetLocalString(i);\r\n\t\t\tif (p_string)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"'%s'\\n\",p_string);\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tprintf(\"NULL local string\\n\");\r\n\t\t\t}\t\r\n            break;\r\n\t\t}\t\r\n        case ESYMBOLTYPE_PAIR:\r\n\t\t{\r\n\t\t\tCPair *p_pair=p_array->GetPair(i);\r\n\t\t\tif (p_pair)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"(%f,%f)\\n\",p_pair->mX,p_pair->mY);\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tprintf(\"NULL pair\\n\");\r\n\t\t\t}\t\r\n            break;\r\n\t\t}\t\r\n        case ESYMBOLTYPE_VECTOR:\r\n\t\t{\r\n\t\t\tCVector *p_vector=p_array->GetVector(i);\r\n\t\t\tif (p_vector)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"(%f,%f,%f)\\n\",p_vector->mX,p_vector->mY,p_vector->mZ);\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tprintf(\"NULL vector\\n\");\r\n\t\t\t}\t\r\n            break;\r\n\t\t}\t\r\n        case ESYMBOLTYPE_NAME:\r\n            printf(\"%s\\n\",FindChecksumName(p_array->GetChecksum(i)));\r\n            break;\r\n        case ESYMBOLTYPE_STRUCTURE:\r\n\t\t{\r\n\t\t\tCStruct *p_structure=p_array->GetStructure(i);\r\n\t\t\tif (p_structure)\r\n\t\t\t{\r\n\t\t\t\tPrintContents(p_structure,indent);\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tprintf(\"NULL structure\\n\");\r\n\t\t\t}\t\r\n            break;\r\n\t\t}\t\r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t{\r\n\t\t\tCArray *p_a=p_array->GetArray(i);\r\n\t\t\tif (p_a)\r\n\t\t\t{\r\n\t\t\t\tPrintContents(p_a,indent);\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tprintf(\"NULL array\\n\");\r\n\t\t\t}\t\r\n            break;\r\n\t\t}\t\r\n\t\t\t\r\n        default:\r\n            Dbg_MsgAssert(0,(\"Bad array type\"));\r\n            break;\r\n        }\r\n\r\n\t\t#ifdef SLOW_DOWN_PRINTCONTENTS\r\n\t\t// A delay to let printf catch up so that it doesn't skip stuff when printing big arrays.\t\t\r\n\t\tfor (int i=0; i<10000; ++i);\r\n\t\t#endif\r\n    }\r\n    sDoIndent(indent-3);\r\n\tprintf(\"]\\n\");\r\n#endif\t\r\n}\r\n\r\nvoid PrintContents(const CStruct *p_structure, int indent)\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tDbg_MsgAssert(p_structure,(\"NULL p_structure\"));\r\n\t\r\n\tif (!indent)\r\n\t{\r\n\t\tprintf(\"Contents of CStruct=\\n\");\r\n\t}\r\n\t\r\n\tsDoIndent(indent);\r\n\tprintf(\"{\\n\");\r\n\tindent+=3;\r\n\t\t\r\n    CComponent *p_comp=p_structure->GetNextComponent(NULL);\r\n    while (p_comp)\r\n    {\r\n\t\tsDoIndent(indent);\r\n\t\t\r\n\t\tif (p_comp->mNameChecksum)\r\n\t\t{\r\n\t\t\tprintf(\"%s=\",FindChecksumName(p_comp->mNameChecksum));\r\n\t\t}\t\r\n            \r\n        switch (p_comp->mType)\r\n        {\r\n        case ESYMBOLTYPE_INTEGER:\r\n            printf(\"%d\\n\",p_comp->mIntegerValue);\r\n            break;\r\n        case ESYMBOLTYPE_FLOAT:\r\n            printf(\"%f\\n\",p_comp->mFloatValue);\r\n            break;\r\n        case ESYMBOLTYPE_STRING:\r\n            printf(\"\\\"%s\\\"\\n\",p_comp->mpString);\r\n            break;\r\n        case ESYMBOLTYPE_LOCALSTRING:\r\n            printf(\"'%s'\\n\",p_comp->mpLocalString);\r\n            break;\r\n        case ESYMBOLTYPE_PAIR:\r\n            printf(\"(%f,%f)\\n\",p_comp->mpPair->mX,p_comp->mpPair->mY);\r\n            break;\r\n        case ESYMBOLTYPE_VECTOR:\r\n            printf(\"(%f,%f,%f)\\n\",p_comp->mpVector->mX,p_comp->mpVector->mY,p_comp->mpVector->mZ);\r\n            break;\r\n        case ESYMBOLTYPE_STRUCTURE:\r\n\t\t\tprintf(\"\\n\");\r\n\t\t\tPrintContents(p_comp->mpStructure,indent);\r\n            break;\r\n        case ESYMBOLTYPE_NAME:\r\n            printf(\"%s\\n\",FindChecksumName(p_comp->mChecksum));\r\n\t\t\t\r\n\t\t\t#ifdef EXPAND_GLOBAL_STRUCTURE_REFERENCES\r\n\t\t\tif (p_comp->mNameChecksum==0)\r\n\t\t\t{\r\n\t\t\t\t// It's an un-named name. Maybe it's a global structure ... \r\n\t\t\t\t// If so, print its contents too, which is handy for debugging.\r\n\t\t\t    CSymbolTableEntry *p_entry=Resolve(p_comp->mChecksum);\r\n\t\t\t\tif (p_entry && p_entry->mType==ESYMBOLTYPE_STRUCTURE)\r\n\t\t\t\t{\r\n\t\t\t\t\tsDoIndent(indent);\r\n\t\t\t\t\tprintf(\"... Defined in %s ...\\n\",FindChecksumName(p_entry->mSourceFileNameChecksum));\r\n\t\t\t\t\tDbg_MsgAssert(p_entry->mpStructure,(\"NULL p_entry->mpStructure\"));\r\n\t\t\t\t\tPrintContents(p_entry->mpStructure,indent);\r\n\t\t\t\t}\r\n\t\t\t}\t\t\r\n\t\t\t#endif\r\n            break;\r\n        case ESYMBOLTYPE_QSCRIPT:\r\n\t\t\tprintf(\"(A script)\\n\"); // TODO\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t\tprintf(\"\\n\");\r\n\t\t\tPrintContents(p_comp->mpArray,indent);\r\n            break;\r\n        default:\r\n\t\t\tprintf(\"Component of type '%s', value 0x%08x\\n\",GetTypeName(p_comp->mType),p_comp->mUnion);\r\n            //Dbg_MsgAssert(0,(\"Bad p_comp->Type\"));\r\n            break;\r\n        }\r\n        p_comp=p_structure->GetNextComponent(p_comp);\r\n\t\t\r\n\t\t#ifdef SLOW_DOWN_PRINTCONTENTS\r\n\t\t// A delay to let printf catch up so that it doesn't skip stuff when printing big arrays.\t\t\r\n\t\tfor (int i=0; i<1000000; ++i);\r\n\t\t#endif\r\n    }\r\n\t\r\n    sDoIndent(indent-3);\r\n\tprintf(\"}\\n\");\r\n#endif\r\n}\r\n\r\nstatic uint8 *sWriteCompressedName(uint8 *p_buffer, uint8 symbolType, uint32 nameChecksum)\r\n{\r\n\t#ifdef __PLAT_WN32__\r\n\t// If compiling on PC, the lookup table will not exist, so do no compression.\r\n\t*p_buffer++=symbolType;\r\n\treturn Write4Bytes(p_buffer,nameChecksum);\r\n\t#else\r\n\t\r\n\t// Check if the checksum is in the small array.\r\n\tCArray *p_table=GetArray(0x35115a20/*WriteToBuffer_CompressionLookupTable_8*/);\r\n\tint size=p_table->GetSize();\r\n\tDbg_MsgAssert(size<256,(\"Size of WriteToBuffer_CompressionLookupTable_8 too big\"));\r\n\t\r\n\tfor (int i=0; i<size; ++i)\r\n\t{\r\n\t\tif (p_table->GetChecksum(i)==nameChecksum)\r\n\t\t{\r\n\t\t\t// It is in the array! So write out a 1 byte index.\r\n\t\t\t*p_buffer++=symbolType | MASK_8_BIT_NAME_LOOKUP;\r\n\t\t\t*p_buffer++=i;\r\n\t\t\treturn p_buffer;\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\t// Check if the checksum is in the big array.\r\n\tp_table=GetArray(0x25231f42/*WriteToBuffer_CompressionLookupTable_16*/);\r\n\tsize=p_table->GetSize();\r\n\tDbg_MsgAssert(size<65536,(\"Size of WriteToBuffer_CompressionLookupTable_16 too big\"));\r\n\t\r\n\tfor (int i=0; i<size; ++i)\r\n\t{\r\n\t\tif (p_table->GetChecksum(i)==nameChecksum)\r\n\t\t{\r\n\t\t\t// It is in the array! So write out a 2 byte index.\r\n\t\t\t*p_buffer++=symbolType | MASK_16_BIT_NAME_LOOKUP;\r\n\t\t\treturn Write2Bytes(p_buffer,i);\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\t// Oh well, it is not in either array, so write out the whole 4 byte checksum.\r\n\t*p_buffer++=symbolType;\r\n\treturn Write4Bytes(p_buffer,nameChecksum);\r\n\t#endif\r\n}\r\n\r\nstatic uint32 sIntegerWriteToBuffer(uint32 name, int val, uint8 *p_buffer, uint32 bufferSize)\r\n{\r\n\tuint8 *p_buffer_before=p_buffer;\r\n\t\t\r\n\t// Choose what type of symbol to use so as to minimize the space used.\r\n\t\r\n\tESymbolType symbol_type=ESYMBOLTYPE_INTEGER; // Default to a full 4 bytes.\r\n\t\r\n\tif (val==0)\r\n\t{\r\n\t\tsymbol_type=ESYMBOLTYPE_ZERO_INTEGER;\r\n\t}\r\n\telse if (val>=0 && val<=255)\r\n\t{\r\n\t\tsymbol_type=ESYMBOLTYPE_UNSIGNED_INTEGER_ONE_BYTE;\r\n\t}\r\n\telse if (val>=0 && val<=65535)\t\r\n\t{\r\n\t\tsymbol_type=ESYMBOLTYPE_UNSIGNED_INTEGER_TWO_BYTES;\r\n\t}\r\n\telse if (val>=-128 && val<=127)\r\n\t{\r\n\t\tsymbol_type=ESYMBOLTYPE_INTEGER_ONE_BYTE;\r\n\t}\r\n\telse if (val>=-32768 && val<=32767)\r\n\t{\r\n\t\tsymbol_type=ESYMBOLTYPE_INTEGER_TWO_BYTES;\r\n\t}\r\n\r\n\t\r\n\tuint8 p_temp[20];\r\n\tuint8 *p_end=p_temp;\r\n\t \r\n\tswitch (symbol_type)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\t// Write out the component into p_temp\r\n\t\t\tp_end=sWriteCompressedName(p_temp,symbol_type,name);\r\n\t\t\tp_end=Write4Bytes(p_end,(uint32)val);\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase ESYMBOLTYPE_INTEGER_ONE_BYTE:\r\n\t\tcase ESYMBOLTYPE_UNSIGNED_INTEGER_ONE_BYTE:\r\n\t\t\t// Write out the component into p_temp\r\n\t\t\tp_end=sWriteCompressedName(p_temp,symbol_type,name);\r\n\t\t\t*p_end++=(uint8)val;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESYMBOLTYPE_INTEGER_TWO_BYTES:\r\n\t\tcase ESYMBOLTYPE_UNSIGNED_INTEGER_TWO_BYTES:\r\n\t\t\t// Write out the component.\r\n\t\t\tp_end=sWriteCompressedName(p_temp,symbol_type,name);\r\n\t\t\tp_end=Write2Bytes(p_end,(uint16)val);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESYMBOLTYPE_ZERO_INTEGER:\r\n\t\t\t// Write out the component.\r\n\t\t\tp_end=sWriteCompressedName(p_temp,symbol_type,name);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Bad symbol_type\"));\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tuint32 bytes_written_to_temp=p_end-p_temp;\r\n\t\r\n\t// Check that there is enough space before doing any writing.\r\n\tif (bufferSize < bytes_written_to_temp)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tuint8 *p_source=p_temp;\r\n\tfor (uint32 i=0; i<bytes_written_to_temp; ++i)\r\n\t{\r\n\t\t*p_buffer++=*p_source++;\r\n\t}\t\r\n\t\r\n\treturn p_buffer-p_buffer_before;\t\t\r\n}\r\n\r\nstatic uint32 sFloatWriteToBuffer(uint32 name, float val, uint8 *p_buffer, uint32 bufferSize)\r\n{\r\n\tuint8 *p_buffer_before=p_buffer;\r\n\t\r\n\tfloat abs_val=val;\r\n\tif (abs_val<0.0f) abs_val=-abs_val;\r\n\t\r\n\t// Check if the float value is small enough to be considered zero.\r\n\t// If so, save space by using the ESYMBOLTYPE_ZERO_FLOAT token.\r\n\tif (abs_val<0.0001)\r\n\t{\r\n\t\t// Check that there is enough space before doing any writing.\r\n\t\tif (bufferSize<5)\r\n\t\t{\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\t\r\n\t\t// Write out the component.\r\n\t\tp_buffer=sWriteCompressedName(p_buffer,ESYMBOLTYPE_ZERO_FLOAT,name);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Check that there is enough space before doing any writing.\r\n\t\tif (bufferSize<9)\r\n\t\t{\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\t\r\n\t\t// Write out the component.\r\n\t\tp_buffer=sWriteCompressedName(p_buffer,ESYMBOLTYPE_FLOAT,name);\r\n\t\tp_buffer=Write4Bytes(p_buffer,val);\r\n\t}\t\r\n\treturn p_buffer-p_buffer_before;\r\n}\r\n\r\nstatic uint32 sChecksumWriteToBuffer(uint32 name, uint32 checksum, uint8 *p_buffer, uint32 bufferSize)\r\n{\r\n\tuint8 *p_buffer_before=p_buffer;\r\n\t\r\n\t// Check that there is enough space before doing any writing.\r\n\tif (bufferSize<9)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\t\t\r\n\t// Write out the component.\r\n\tp_buffer=sWriteCompressedName(p_buffer,ESYMBOLTYPE_NAME,name);\r\n\tp_buffer=Write4Bytes(p_buffer,checksum);\r\n\treturn p_buffer-p_buffer_before;\r\n}\r\n\r\nstatic uint32 sStringWriteToBuffer(uint32 name, const char *p_string, uint8 *p_buffer, uint32 bufferSize)\r\n{\r\n\tDbg_MsgAssert(p_string,(\"NULL p_string sent to sStringWriteToBuffer\"));\r\n\tuint8 *p_buffer_before=p_buffer;\r\n\t\t\r\n\tuint32 Len=strlen(p_string);\r\n\t// Check that there is enough space before doing any writing.\r\n\t// The +6 is for the type, the name, and the string terminating 0.\r\n\tif (bufferSize<Len+6)\r\n\t{\r\n\t\treturn 0;\r\n\t}\t\r\n\t\r\n\t// Write out the component.\r\n\tp_buffer=sWriteCompressedName(p_buffer,ESYMBOLTYPE_STRING,name);\r\n\tfor (uint32 i=0; i<Len; ++i)\r\n\t{\r\n\t\t*p_buffer++=*p_string++;\r\n\t}\r\n\t*p_buffer++=0;\t\r\n\t\r\n\treturn p_buffer-p_buffer_before;\r\n}\r\n\r\nstatic uint32 sLocalStringWriteToBuffer(uint32 name, const char *p_string, uint8 *p_buffer, uint32 bufferSize)\r\n{\r\n\tDbg_MsgAssert(p_string,(\"NULL p_string sent to sLocalStringWriteToBuffer\"));\r\n\tuint8 *p_buffer_before=p_buffer;\r\n\t\r\n\tuint32 len=strlen(p_string);\r\n\t// Check that there is enough space before doing any writing.\r\n\t// The +6 is for the type, the name, and the string terminating 0.\r\n\tif (bufferSize<len+6)\r\n\t{\r\n\t\treturn 0;\r\n\t}\t\r\n\t\r\n\t// Write out the component.\r\n\tp_buffer=sWriteCompressedName(p_buffer,ESYMBOLTYPE_LOCALSTRING,name);\r\n\tfor (uint32 i=0; i<len; ++i)\r\n\t{\r\n\t\t*p_buffer++=*p_string++;\r\n\t}\r\n\t*p_buffer++=0;\t\r\n\t\r\n\treturn p_buffer-p_buffer_before;\r\n}\r\n\r\nstatic uint32 sPairWriteToBuffer(uint32 name, CPair *p_pair, uint8 *p_buffer, uint32 bufferSize)\r\n{\r\n\tDbg_MsgAssert(p_pair,(\"NULL p_pair sent to sPairWriteToBuffer\"));\r\n\tuint8 *p_buffer_before=p_buffer;\r\n\t\r\n\t// Check that there is enough space before doing any writing.\r\n\tif (bufferSize<13)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\t\t\r\n\t// Write out the component.\r\n\tp_buffer=sWriteCompressedName(p_buffer,ESYMBOLTYPE_PAIR,name);\r\n\tp_buffer=Write4Bytes(p_buffer,p_pair->mX);\r\n\tp_buffer=Write4Bytes(p_buffer,p_pair->mY);\r\n\t\r\n\treturn p_buffer-p_buffer_before;\r\n}\r\n\r\nstatic uint32 sVectorWriteToBuffer(uint32 name, CVector *p_vector, uint8 *p_buffer, uint32 bufferSize)\r\n{\r\n\tDbg_MsgAssert(p_vector,(\"NULL p_vector sent to sVectorWriteToBuffer\"));\r\n\tuint8 *p_buffer_before=p_buffer;\r\n\t\r\n\t// Check that there is enough space before doing any writing.\r\n\tif (bufferSize<17)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\t\t\r\n\t// Write out the component.\r\n\tp_buffer=sWriteCompressedName(p_buffer,ESYMBOLTYPE_VECTOR,name);\r\n\tp_buffer=Write4Bytes(p_buffer,p_vector->mX);\r\n\tp_buffer=Write4Bytes(p_buffer,p_vector->mY);\r\n\tp_buffer=Write4Bytes(p_buffer,p_vector->mZ);\r\n\t\r\n\treturn p_buffer-p_buffer_before;\r\n}\r\n\r\nstatic uint32 sStructureWriteToBuffer(uint32 name, CStruct *p_structure, uint8 *p_buffer, uint32 bufferSize, EAssertType assert)\r\n{\r\n\tDbg_MsgAssert(p_structure,(\"NULL p_structure sent to sStructureWriteToBuffer\"));\r\n\tuint8 *p_buffer_before=p_buffer;\r\n\t\r\n\t// Check that there is enough space before doing any writing.\r\n\tif (bufferSize<5)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\t\t\r\n\t// Write out the type and name\r\n\tp_buffer=sWriteCompressedName(p_buffer,ESYMBOLTYPE_STRUCTURE,name);\r\n\tint name_bytes_written=p_buffer-p_buffer_before;\r\n\t\r\n\t// That's name_bytes_written bytes written out successfully, but maybe the writing out of the structure will fail ...\r\n\t\r\n\tuint32 structure_bytes_written=WriteToBuffer(p_structure,p_buffer,bufferSize-name_bytes_written,assert);\r\n\t// If writing out the structure failed, return 0.\r\n\tif (!structure_bytes_written)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\t\r\n\t// Otherwise return the total bytes written.\r\n\treturn name_bytes_written+structure_bytes_written;\r\n}\r\n\r\nstatic uint32 sArrayWriteToBuffer(uint32 name, CArray *p_array, uint8 *p_buffer, uint32 bufferSize, EAssertType assert)\r\n{\r\n\tDbg_MsgAssert(p_array,(\"NULL p_array sent to sArrayWriteToBuffer\"));\r\n\tuint8 *p_buffer_before=p_buffer;\r\n\t\r\n\t// Check that there is enough space before doing any writing.\r\n\tif (bufferSize<5)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\r\n\t// Write out the type and name\r\n\tp_buffer=sWriteCompressedName(p_buffer,ESYMBOLTYPE_ARRAY,name);\r\n\tint name_bytes_written=p_buffer-p_buffer_before;\r\n\t\r\n\t// That's name_bytes_written bytes written out successfully, but maybe the writing out of the array will fail ...\r\n\t\r\n\tuint32 array_bytes_written=WriteToBuffer(p_array,p_buffer,bufferSize-name_bytes_written,assert);\r\n\t// If writing out the array failed, return 0.\r\n\tif (!array_bytes_written)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\t\r\n\t// Otherwise return the total bytes written.\r\n\treturn name_bytes_written+array_bytes_written;\r\n}\t\r\n\r\n// Writes the contents of the structure to a buffer.\r\n// The information is outputted in a byte-packed format, so p_buffer does\r\n// not need to be aligned.\r\n// The buffer can then be used to regenerate the original structure by\r\n// passing it to ReadFromBuffer.\r\n// Passed the size of the buffer so that it can check if there is enough space.\r\n// Returns the number of bytes that it actually wrote.\r\n//\r\n// If there was not enough space, and assert is NO_ASSERT, it will return a count of 0.\r\n//\r\nuint32 WriteToBuffer(CStruct *p_structure, uint8 *p_buffer, uint32 bufferSize, EAssertType assert)\r\n{\r\n\tDbg_MsgAssert(p_buffer,(\"NULL p_buffer sent to WriteToBuffer\"));\r\n\tuint32 bytes_left=bufferSize;\r\n\r\n\t// Scan through the components adding each to the buffer.\t\r\n    CComponent *p_comp=NULL;\r\n\tif (p_structure)\r\n\t{\r\n\t\tp_comp=p_structure->GetNextComponent(NULL);\r\n\t}\r\n\t\t\r\n    while (p_comp)\r\n    {\r\n\t\tuint32 component_bytes_written=0;\r\n\t\t\r\n        switch (p_comp->mType)\r\n        {\r\n        case ESYMBOLTYPE_INTEGER:\r\n\t\t\tcomponent_bytes_written=sIntegerWriteToBuffer(p_comp->mNameChecksum,p_comp->mIntegerValue,p_buffer,bytes_left);\r\n\t\t\tbreak;\r\n\t\t\t\r\n        case ESYMBOLTYPE_FLOAT:\r\n\t\t\tcomponent_bytes_written=sFloatWriteToBuffer(p_comp->mNameChecksum,p_comp->mFloatValue,p_buffer,bytes_left);\r\n\t\t\tbreak;\r\n\r\n        case ESYMBOLTYPE_NAME:\r\n\t\t\tcomponent_bytes_written=sChecksumWriteToBuffer(p_comp->mNameChecksum,p_comp->mChecksum,p_buffer,bytes_left);\r\n\t\t\tbreak;\r\n\t\t\t\r\n        case ESYMBOLTYPE_STRING:\r\n\t\t\tcomponent_bytes_written=sStringWriteToBuffer(p_comp->mNameChecksum,p_comp->mpString,p_buffer,bytes_left);\r\n\t\t\tbreak;\r\n\r\n        case ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\tcomponent_bytes_written=sLocalStringWriteToBuffer(p_comp->mNameChecksum,p_comp->mpLocalString,p_buffer,bytes_left);\r\n\t\t\tbreak;\r\n\t\t\t\r\n        case ESYMBOLTYPE_PAIR:\r\n\t\t\tcomponent_bytes_written=sPairWriteToBuffer(p_comp->mNameChecksum,p_comp->mpPair,p_buffer,bytes_left);\r\n\t\t\tbreak;\r\n\t\t\t\r\n        case ESYMBOLTYPE_VECTOR:\r\n\t\t\tcomponent_bytes_written=sVectorWriteToBuffer(p_comp->mNameChecksum,p_comp->mpVector,p_buffer,bytes_left);\r\n\t\t\tbreak;\r\n\r\n        case ESYMBOLTYPE_STRUCTURE:\r\n\t\t\tcomponent_bytes_written=sStructureWriteToBuffer(p_comp->mNameChecksum,p_comp->mpStructure,p_buffer,bytes_left,assert);\r\n\t\t\tbreak;\r\n\r\n        case ESYMBOLTYPE_ARRAY:\r\n\t\t\tcomponent_bytes_written=sArrayWriteToBuffer(p_comp->mNameChecksum,p_comp->mpArray,p_buffer,bytes_left,assert);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase ESYMBOLTYPE_QSCRIPT:\t\r\n\t\t\tcomponent_bytes_written=sChecksumWriteToBuffer(p_comp->mNameChecksum,CRCD(0xb9c4f664,\"InlineScript\"),p_buffer,bytes_left);\r\n            break;\r\n\t\t\t\r\n        default:\r\n            Dbg_MsgAssert(0,(\"Component type of '%s' is not supported in WriteToBuffer\",GetTypeName(p_comp->mType)));\r\n            break;\r\n        }\r\n\t\t\r\n\t\t// If any of the above writes failed due to lack of space, then bail out too.\r\n\t\tif (!component_bytes_written)\r\n\t\t{\r\n\t\t\tif (assert)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0,(\"WriteToBuffer: Buffer not big enough\"));\r\n\t\t\t}\t\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\t\t\r\n\t\tbytes_left-=component_bytes_written;\r\n\t\tp_buffer+=component_bytes_written;\r\n\t\t\r\n        p_comp=p_structure->GetNextComponent(p_comp);\r\n    }\r\n\r\n\t// Add the terminating ESYMBOLTYPE_NONE\r\n\tif (!bytes_left)\r\n\t{\r\n\t\t// Aargh! Not enough room left for the final byte!\r\n\t\tif (assert)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"WriteToBuffer: Buffer not big enough\"));\r\n\t\t}\t\r\n\t\treturn 0;\r\n\t}\t\r\n\t*p_buffer++=ESYMBOLTYPE_NONE;\r\n\t--bytes_left;\r\n\t\r\n\t// Return how many bytes got written.\r\n\treturn bufferSize-bytes_left;\r\n}\r\n\r\n// Calculates how big a buffer will need to be to hold a structure using WriteToBuffer.\r\nuint32 CalculateBufferSize(CStruct *p_structure, uint32 tempBufferSize)\r\n{\r\n\tDbg_MsgAssert(p_structure,(\"NULL p_structure\"));\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap()); // Use the temporary heap\r\n\t\r\n\tuint8 *p_temp=(uint8*)Mem::Malloc(tempBufferSize);\r\n\tDbg_MsgAssert(p_temp,(\"Could not allocate temporary buffer\"));\r\n\tuint32 space_required=WriteToBuffer(p_structure,p_temp,tempBufferSize);\r\n\tMem::Free(p_temp);\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn space_required;\r\n}\r\n\r\n// Sets the structure's contents using the passed buffer, which was generated\r\n// by WriteToBuffer.\r\n// If the structure contained anything to begin with, it will get cleared.\t\r\n//\r\n// Returns a pointer to after the terminating ESYMBOLTYPE_NONE, required\r\n// when this function calls itself.\r\nuint8 *ReadFromBuffer(CStruct *p_structure, uint8 *p_buffer)\r\n{\r\n\tDbg_MsgAssert(p_structure,(\"NULL p_structure\"));\r\n\tDbg_MsgAssert(p_buffer,(\"NULL p_buffer sent to ReadFromBuffer\"));\r\n\tfloat zero_float=0.0f;\r\n\r\n\t// First clear anything currently in the structure.\r\n\tp_structure->Clear();\r\n\r\n\t// Make sure we're using the script heap.\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\r\n\t// Scan through the buffer adding the components until ESYMBOLTYPE_NONE is reached.\r\n\twhile (true)\r\n    {\r\n\t\tfloat x,y,z;\r\n\t\tconst char *p_string;\r\n\t\tCStruct *p_struct;\r\n\t\tCArray *p_array;\r\n\t\t\r\n\t\t// Get the type and the name checksum.\r\n\t\tESymbolType type=(ESymbolType)*p_buffer++;\r\n\t\tif (type==ESYMBOLTYPE_NONE)\r\n\t\t{\r\n\t\t\t// All done.\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// Get the name checksum, which may be stored as an index into a table of checksums\r\n\t\t// to save space.\r\n\t\tuint32 name=0;\r\n\t\tif (type&MASK_8_BIT_NAME_LOOKUP)\t\t\t\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(!(type&MASK_16_BIT_NAME_LOOKUP),(\"Eh? Both lookup-table flags set ?\"));\r\n\t\t\t\r\n\t\t\t#ifdef __PLAT_WN32__\r\n\t\t\t// The lookup table is not loaded when compiling on PC\r\n\t\t\tname=CRCD(0xef5f3f41,\"CompressedName\");\r\n\t\t\t#else\r\n\t\t\tCArray *p_table=GetArray(0x35115a20/*WriteToBuffer_CompressionLookupTable_8*/);\r\n\t\t\tname=p_table->GetChecksum(*p_buffer);\r\n\t\t\t#endif\r\n\t\t\t++p_buffer;\r\n\t\t}\r\n\t\telse if (type&MASK_16_BIT_NAME_LOOKUP)\t\t\t\r\n\t\t{\r\n\t\t\t#ifdef __PLAT_WN32__\r\n\t\t\tname=CRCD(0xef5f3f41,\"CompressedName\");\r\n\t\t\t#else\r\n\t\t\tCArray *p_table=GetArray(0x25231f42/*WriteToBuffer_CompressionLookupTable_16*/);\r\n\t\t\tname=p_table->GetChecksum(Read2Bytes(p_buffer).mUInt);\r\n\t\t\t#endif\r\n\t\t\tp_buffer+=2;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// It's not stored as an index, but as the full 4 byte checksum.\r\n\t\t\tname=Read4Bytes(p_buffer).mChecksum;\r\n\t\t\tp_buffer+=4;\r\n\t\t}\r\n\t\ttype=(ESymbolType)( ((uint32)type) & ~(MASK_8_BIT_NAME_LOOKUP | MASK_16_BIT_NAME_LOOKUP) );\r\n\t\t\t\r\n\t\t\r\n        switch (type)\r\n        {\r\n        case ESYMBOLTYPE_INTEGER:\r\n\t\t\tp_structure->AddInteger(name,Read4Bytes(p_buffer).mInt);\r\n\t\t\tp_buffer+=4;\r\n            break;\r\n        case ESYMBOLTYPE_FLOAT:\r\n\t\t\tp_structure->AddFloat(name,Read4Bytes(p_buffer).mFloat);\r\n\t\t\tp_buffer+=4;\r\n            break;\r\n        case ESYMBOLTYPE_NAME:\r\n\t\t\tp_structure->AddChecksum(name,Read4Bytes(p_buffer).mChecksum);\r\n\t\t\tp_buffer+=4;\r\n            break;\r\n\t\tcase ESYMBOLTYPE_ZERO_FLOAT:\r\n\t\t\tp_structure->AddFloat(name,zero_float);\r\n\t\t\tbreak;\t\r\n\t\tcase ESYMBOLTYPE_ZERO_INTEGER:\r\n\t\t\tp_structure->AddInteger(name,0);\r\n\t\t\tbreak;\t\r\n\t\tcase ESYMBOLTYPE_INTEGER_ONE_BYTE:\r\n\t\t\tp_structure->AddInteger(name,*(sint8*)p_buffer++);\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_UNSIGNED_INTEGER_ONE_BYTE:\r\n\t\t\tp_structure->AddInteger(name,*p_buffer++);\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_INTEGER_TWO_BYTES:\r\n\t\t\tp_structure->AddInteger(name,Read2Bytes(p_buffer).mInt);\r\n\t\t\tp_buffer+=2;\r\n\t\t\tbreak;\t\r\n\t\tcase ESYMBOLTYPE_UNSIGNED_INTEGER_TWO_BYTES:\r\n\t\t\tp_structure->AddInteger(name,Read2Bytes(p_buffer).mUInt);\r\n\t\t\tp_buffer+=2;\r\n\t\t\tbreak;\t\r\n        case ESYMBOLTYPE_STRING:\r\n\t\t\tp_string=(const char *)p_buffer;\r\n\t\t\tp_structure->AddString(name,p_string);\r\n\t\t\tp_buffer+=strlen(p_string);\r\n\t\t\t++p_buffer; // Skip over the terminator too.\r\n            break;\r\n        case ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\tp_string=(const char *)p_buffer;\r\n\t\t\tp_structure->AddLocalString(name,p_string);\r\n\t\t\tp_buffer+=strlen(p_string);\r\n\t\t\t++p_buffer; // Skip over the terminator too.\r\n            break;\r\n        case ESYMBOLTYPE_PAIR:\r\n\t\t\tx=Read4Bytes(p_buffer).mFloat;\r\n\t\t\tp_buffer+=4;\r\n\t\t\ty=Read4Bytes(p_buffer).mFloat;\r\n\t\t\tp_buffer+=4;\r\n\t\t\tp_structure->AddPair(name,x,y);\r\n            break;\r\n        case ESYMBOLTYPE_VECTOR:\r\n\t\t\tx=Read4Bytes(p_buffer).mFloat;\r\n\t\t\tp_buffer+=4;\r\n\t\t\ty=Read4Bytes(p_buffer).mFloat;\r\n\t\t\tp_buffer+=4;\r\n\t\t\tz=Read4Bytes(p_buffer).mFloat;\r\n\t\t\tp_buffer+=4;\r\n\t\t\tp_structure->AddVector(name,x,y,z);\r\n            break;\r\n\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t\t// Create a new structure, and fill it in by calling this function recursively.\r\n\t\t\tp_struct=new CStruct;\r\n\t\t\tp_buffer=ReadFromBuffer(p_struct,p_buffer);\r\n\t\t\t// Add the new component.\r\n\t\t\tp_structure->AddStructurePointer(name,p_struct);\r\n\t\t\tbreak;\t\r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t\t// Create a new array, and fill it in using the array's ReadFromBuffer.\r\n\t\t\tp_array=new CArray;\r\n\t\t\tp_buffer=ReadFromBuffer(p_array,p_buffer);\r\n\t\t\t// Add the new component.\r\n\t\t\tp_structure->AddArrayPointer(name,p_array);\r\n\t\t\tbreak;\t\r\n        default:\r\n            Dbg_MsgAssert(0,(\"Unsupported component type of '%s' encountered in ReadFromBuffer\",GetTypeName(type)));\r\n            break;\r\n        }\r\n    }\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\treturn p_buffer;\r\n}\r\n\r\n// Writes the contents of the array to a buffer.\r\n// The information is outputted in a byte-packed format, so p_buffer does\r\n// not need to be aligned.\r\n// The buffer can then be used to regenerate the original array by\r\n// passing it to ReadFromBuffer.\r\n// Passed the size of the buffer so that it can check if there is enough space.\r\n// Returns the number of bytes that it actually wrote.\r\n//\r\n// If there was not enough space, and assert is false, it will return a count of 0.\r\n//\r\nuint32 WriteToBuffer(CArray *p_array, uint8 *p_buffer, uint32 bufferSize, EAssertType assert)\r\n{\r\n\tDbg_MsgAssert(p_array,(\"NULL p_array\"));\r\n\tDbg_MsgAssert(p_buffer,(\"NULL p_buffer sent to WriteToBuffer\"));\r\n\tuint32 bytes_left=bufferSize;\r\n\r\n\tif (bytes_left<3)\r\n\t{\r\n\t\tif (assert)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"WriteToBuffer: Buffer not big enough\"));\r\n\t\t}\t\r\n\t\treturn 0;\r\n\t}\r\n\t\r\n\tESymbolType type=p_array->GetType();\r\n\tuint32 size=p_array->GetSize();\r\n\t\r\n\t*p_buffer++=type;\r\n\r\n\t// Easy to change WriteToBuffer to support 4 byte sizes, but keeping as 2 for the moment for\r\n\t// backwards compatibility.\r\n\tDbg_MsgAssert(size<0x10000,(\"Size of array too big, currently only 2 bytes used to store size in WriteToBuffer ...\"));\r\n\tp_buffer=Write2Bytes(p_buffer,size);\r\n\tbytes_left-=3;\r\n\t\r\n\tswitch (type)\r\n\t{\r\n        case ESYMBOLTYPE_INTEGER:\r\n        case ESYMBOLTYPE_FLOAT:\r\n        case ESYMBOLTYPE_NAME:\r\n\t\t{\r\n\t\t\tif (size*4>bytes_left)\r\n\t\t\t{\r\n\t\t\t\tif (assert)\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"WriteToBuffer: Buffer not big enough\"));\r\n\t\t\t\t}\t\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tuint32 *p_data=p_array->GetArrayPointer();\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tp_buffer=Write4Bytes(p_buffer,*p_data++);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tbytes_left-=size*4;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        case ESYMBOLTYPE_STRING:\r\n        case ESYMBOLTYPE_LOCALSTRING:\r\n\t\t{\r\n\t\t\tchar **pp_strings=(char**)p_array->GetArrayPointer();\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tconst char *p_string=*pp_strings++;\r\n\t\t\t\tDbg_MsgAssert(p_string,(\"NULL p_string for element %d when attempting to WriteToBuffer\",i));\r\n\r\n\t\t\t\twhile (*p_string)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (bytes_left)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t*p_buffer++=*p_string++;\r\n\t\t\t\t\t\t--bytes_left;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (assert)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tDbg_MsgAssert(0,(\"WriteToBuffer: Buffer not big enough\"));\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\treturn 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (bytes_left)\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_buffer++=0;\r\n\t\t\t\t\t--bytes_left;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif (assert)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"WriteToBuffer: Buffer not big enough\"));\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\treturn 0;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        case ESYMBOLTYPE_PAIR:\r\n\t\t{\r\n\t\t\tif (size*8>bytes_left)\r\n\t\t\t{\r\n\t\t\t\tif (assert)\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"WriteToBuffer: Buffer not big enough\"));\r\n\t\t\t\t}\t\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tCPair **pp_pairs=(CPair**)p_array->GetArrayPointer();\r\n\t\t\tDbg_MsgAssert(pp_pairs,(\"NULL pp_pairs ?\"));\r\n\t\t\t\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCPair *p_pair=*pp_pairs;\r\n\t\t\t\tDbg_MsgAssert(p_pair,(\"NULL p_pair for element %d when attempting to WriteToBuffer\",i));\t\t\t\r\n\t\t\t\tp_buffer=Write4Bytes(p_buffer,p_pair->mX);\r\n\t\t\t\tp_buffer=Write4Bytes(p_buffer,p_pair->mY);\r\n\t\t\t\t++pp_pairs;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tbytes_left-=size*8;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        case ESYMBOLTYPE_VECTOR:\r\n\t\t{\r\n\t\t\tif (size*12>bytes_left)\r\n\t\t\t{\r\n\t\t\t\tif (assert)\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"WriteToBuffer: Buffer not big enough\"));\r\n\t\t\t\t}\t\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tCVector **pp_vectors=(CVector**)p_array->GetArrayPointer();\r\n\t\t\tDbg_MsgAssert(pp_vectors,(\"NULL pp_vectors ?\"));\r\n\t\t\t\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCVector *p_vector=*pp_vectors;\r\n\t\t\t\tDbg_MsgAssert(p_vector,(\"NULL p_vector for element %d when attempting to WriteToBuffer\",i));\t\t\t\r\n\t\t\t\r\n\t\t\t\tp_buffer=Write4Bytes(p_buffer,p_vector->mX);\r\n\t\t\t\tp_buffer=Write4Bytes(p_buffer,p_vector->mY);\r\n\t\t\t\tp_buffer=Write4Bytes(p_buffer,p_vector->mZ);\r\n\t\t\t\t++pp_vectors;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tbytes_left-=size*12;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        case ESYMBOLTYPE_STRUCTURE:\r\n\t\t{\r\n\t\t\tCStruct **pp_structures=(CStruct**)p_array->GetArrayPointer();\r\n\t\t\tDbg_MsgAssert(pp_structures,(\"NULL pp_structures ?\"));\r\n\t\t\t\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCStruct *p_structure=*pp_structures++;\r\n\t\t\t\tDbg_MsgAssert(p_structure,(\"NULL p_structure for element %d when attempting to WriteToBuffer\",i));\t\t\t\r\n\t\t\t\t\r\n\t\t\t\tuint32 bytes_written=WriteToBuffer(p_structure,p_buffer,bytes_left,assert);\r\n\t\t\t\tif (!bytes_written)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (assert)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"WriteToBuffer: Buffer not big enough\"));\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\treturn 0;\r\n\t\t\t\t}\t\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tbytes_left-=bytes_written;\r\n\t\t\t\t\tp_buffer+=bytes_written;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        case ESYMBOLTYPE_ARRAY:\r\n\t\t{\r\n\t\t\tCArray **pp_arrays=(CArray**)p_array->GetArrayPointer();\r\n\t\t\tDbg_MsgAssert(pp_arrays,(\"NULL pp_arrays ?\"));\r\n\t\t\t\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCArray *p_array_element=*pp_arrays++;\r\n\t\t\t\tDbg_MsgAssert(p_array_element,(\"NULL p_array_element for element %d when attempting to WriteToBuffer\",i));\t\t\t\r\n\t\t\t\t\r\n\t\t\t\tuint32 bytes_written=WriteToBuffer(p_array_element,p_buffer,bytes_left,assert);\r\n\t\t\t\tif (!bytes_written)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (assert)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_MsgAssert(0,(\"WriteToBuffer: Buffer not big enough\"));\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\treturn 0;\r\n\t\t\t\t}\t\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tbytes_left-=bytes_written;\r\n\t\t\t\t\tp_buffer+=bytes_written;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        case ESYMBOLTYPE_NONE:\r\n\t\t\t// Empty array\r\n\t\t\tbreak;\r\n\t\t\t\t\t\t\r\n        default:\r\n            Dbg_MsgAssert(0,(\"Array type of '%s' is not supported in WriteToBuffer\",GetTypeName(type)));\r\n            break;\r\n    }\r\n\t\r\n\t// Return how many bytes got written.\r\n\treturn bufferSize-bytes_left;\r\n}\r\n\r\n// Calculates the size of buffer required if wanting to do a call to WriteToBuffer on the passed array.\r\nuint32 CalculateBufferSize(CArray *p_array)\r\n{\r\n\t// Need at least 3 bytes, one for the type, 2 for the size.\r\n\tuint32 space_required=3;\r\n\tuint32 i;\r\n\t\r\n\tuint32 size=p_array->GetSize();\r\n\t// Easy to change WriteToBuffer to support 4 byte sizes, but keeping as 2 for the moment for\r\n\t// backwards compatibility.\r\n\tDbg_MsgAssert(size<0x10000,(\"Size of array too big, currently only 2 bytes used to store size in WriteToBuffer ...\"));\r\n\tESymbolType type=p_array->GetType();\r\n\t\r\n\tswitch (type)\r\n\t{\r\n        case ESYMBOLTYPE_INTEGER:\r\n        case ESYMBOLTYPE_FLOAT:\r\n        case ESYMBOLTYPE_NAME:\r\n\t\t\tspace_required+=size*4;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        case ESYMBOLTYPE_STRING:\r\n\t\t\tfor (i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tconst char *p_string=p_array->GetString(i);\r\n\t\t\t\tDbg_MsgAssert(p_string,(\"NULL GetString() for element %d when attempting to call CalculateBufferSize\",i));\t\t\t\r\n\t\t\t\tspace_required+=strlen(p_string)+1;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n        case ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\tfor (i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tconst char *p_string=p_array->GetLocalString(i);\r\n\t\t\t\tDbg_MsgAssert(p_string,(\"NULL GetLocalString() for element %d when attempting to call CalculateBufferSize\",i));\t\t\t\r\n\t\t\t\tspace_required+=strlen(p_string)+1;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n        case ESYMBOLTYPE_PAIR:\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tfor (i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCPair *p_pair=p_array->GetPair(i);\r\n\t\t\t\tDbg_MsgAssert(p_pair,(\"NULL GetPair() for element %d when attempting to call CalculateBufferSize\",i));\r\n\t\t\t}\t\r\n\t\t\t#endif\r\n\t\t\tspace_required+=size*8;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        case ESYMBOLTYPE_VECTOR:\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tfor (i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCVector *p_vector=p_array->GetVector(i);\r\n\t\t\t\tDbg_MsgAssert(p_vector,(\"NULL GetVector() for element %d when attempting to call CalculateBufferSize\",i));\r\n\t\t\t}\t\r\n\t\t\t#endif\r\n\t\t\tspace_required+=size*12;\r\n\t\t\tbreak;\r\n\t\t\r\n        case ESYMBOLTYPE_STRUCTURE:\r\n\t\t\tfor (i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCStruct *p_structure=p_array->GetStructure(i);\r\n\t\t\t\tDbg_MsgAssert(p_structure,(\"NULL GetStructure() for element %d when attempting to call CalculateBufferSize\",i));\r\n\t\t\t\tspace_required+=CalculateBufferSize(p_structure);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n        case ESYMBOLTYPE_ARRAY:\r\n\t\t\tfor (i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCArray *p_array_element=p_array->GetArray(i);\r\n\t\t\t\tDbg_MsgAssert(p_array_element,(\"NULL GetArray() for element %d when attempting to call CalculateBufferSize\",i));\r\n\t\t\t\tspace_required+=CalculateBufferSize(p_array_element);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n        case ESYMBOLTYPE_NONE:\r\n\t\t\t// Empty array\r\n\t\t\tbreak;\r\n\t\t\t\t\t\t\r\n        default:\r\n            Dbg_MsgAssert(0,(\"Array type of '%s' is not supported in CalculateBufferSize\",GetTypeName(type)));\r\n            break;\r\n    }\r\n\t\r\n\treturn space_required;\r\n}\r\n\r\n// Sets the array's contents using the passed buffer, which was generated\r\n// by WriteToBuffer.\r\n// If the array contained anything to begin with, it will get cleared.\t\r\n\r\n// Returns a pointer to after the read array data.\r\nuint8 *ReadFromBuffer(CArray *p_array, uint8 *p_buffer)\r\n{\r\n\tDbg_MsgAssert(p_array,(\"NULL p_array sent to ReadFromBuffer\"));\r\n\tDbg_MsgAssert(p_buffer,(\"NULL p_buffer sent to ReadFromBuffer\"));\r\n\r\n\t// First clear anything currently in the array.\r\n\tCleanUpArray(p_array);\r\n\r\n\t// Get the type and size\r\n\tESymbolType type=(ESymbolType)*p_buffer++;\r\n\tuint32 size=*p_buffer++;\r\n\tsize+=*p_buffer++<<8; // 2 byte size.\r\n\r\n\t// Make sure we're using the script heap.\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\tp_array->SetSizeAndType(size,type);\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n    switch (type)\r\n    {\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t{\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tp_array->SetInteger(i,Read4Bytes(p_buffer).mInt);\r\n\t\t\t\tp_buffer+=4;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t{\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tp_array->SetFloat(i,Read4Bytes(p_buffer).mFloat);\r\n\t\t\t\tp_buffer+=4;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t{\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tp_array->SetChecksum(i,Read4Bytes(p_buffer).mChecksum);\r\n\t\t\t\tp_buffer+=4;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t\tcase ESYMBOLTYPE_STRING:\r\n\t\t{\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tp_array->SetString(i,CreateString((const char*)p_buffer));\r\n\t\t\t\tp_buffer+=strlen((char*)p_buffer)+1;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t{\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tp_array->SetLocalString(i,CreateString((const char*)p_buffer));\r\n\t\t\t\tp_buffer+=strlen((char*)p_buffer)+1;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t{\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCPair *p_pair=new CPair;\r\n\t\t\t\tp_pair->mX=Read4Bytes(p_buffer).mFloat;\r\n\t\t\t\tp_buffer+=4;\r\n\t\t\t\tp_pair->mY=Read4Bytes(p_buffer).mFloat;\r\n\t\t\t\tp_buffer+=4;\r\n\r\n\t\t\t\tp_array->SetPair(i,p_pair);\r\n\t\t\t}\t\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t{\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCVector *p_vector=new CVector;\r\n\t\t\t\tp_vector->mX=Read4Bytes(p_buffer).mFloat;\r\n\t\t\t\tp_buffer+=4;\r\n\t\t\t\tp_vector->mY=Read4Bytes(p_buffer).mFloat;\r\n\t\t\t\tp_buffer+=4;\r\n\t\t\t\tp_vector->mZ=Read4Bytes(p_buffer).mFloat;\r\n\t\t\t\tp_buffer+=4;\r\n\r\n\t\t\t\tp_array->SetVector(i,p_vector);\r\n\t\t\t}\t\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t{\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCStruct *p_structure=new CStruct;\r\n\t\t\t\tp_buffer=ReadFromBuffer(p_structure,p_buffer);\r\n\t\t\t\tp_array->SetStructure(i,p_structure);\r\n\t\t\t}\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t{\r\n\t\t\tfor (uint32 i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCArray *p_new_array=new CArray;\r\n\t\t\t\tp_buffer=ReadFromBuffer(p_new_array,p_buffer);\r\n\t\t\t\tp_array->SetArray(i,p_new_array);\r\n\t\t\t}\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase ESYMBOLTYPE_NONE:\r\n\t\t\t// Empty array\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Unsupported type of '%s' encountered in ReadFromBuffer\",GetTypeName(type)));\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\treturn p_buffer;\r\n}\r\n\r\n\r\nunion UValue\r\n{\r\n\tint mIntegerValue;\r\n\tfloat mFloatValue;\r\n\tchar *mpString;\r\n\tchar *mpLocalString;\r\n\tCPair *mpPair;\r\n\tCVector *mpVector;\r\n\tCStruct *mpStructure;\r\n\tCArray *mpArray;\r\n\tuint8 *mpScript;\r\n\tuint32 mChecksum;\r\n\tuint32 mUnion;\r\n};\r\n\r\n// This will load type and value from the passed component, resolving it if it refers to a global.\r\nstatic void Resolve(const CComponent& comp, ESymbolType &type, UValue &value)\r\n{\r\n\tvalue.mUnion=comp.mUnion;\r\n\ttype=(ESymbolType)comp.mType;\r\n\t\r\n\tif (type==ESYMBOLTYPE_NAME)\r\n\t{\r\n\t\tCSymbolTableEntry *p_entry=Resolve(value.mChecksum);\r\n\t\tif (p_entry)\r\n\t\t{\r\n\t\t\tvalue.mUnion=p_entry->mUnion;\r\n\t\t\ttype=(ESymbolType)p_entry->mType;\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n// The == operator is used when interpreting switch statements and expressions in script\r\n// This function is here rather than in component.cpp to avoid cyclic dependencies.\r\nbool CComponent::operator==( const CComponent& v ) const\r\n{\r\n\tUValue value_a,value_b;\r\n\tESymbolType type_a,type_b;\r\n\tResolve(*this,type_a,value_a);\r\n\tResolve(v,type_b,value_b);\r\n\t\r\n\tswitch (type_a)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\tif (type_b==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\treturn ((float)value_a.mIntegerValue)==value_b.mFloatValue;\r\n\t\t\t}\r\n\t\t\telse if (type_b==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\treturn value_a.mIntegerValue==value_b.mIntegerValue;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\tif (type_b==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\treturn value_a.mFloatValue==((float)value_b.mIntegerValue);\r\n\t\t\t}\r\n\t\t\telse if (type_b==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\treturn value_a.mFloatValue==value_b.mFloatValue;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_STRING:\r\n\t\t\tif (type_b==ESYMBOLTYPE_STRING)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(value_a.mpString,(\"NULL value_a.mpString ?\"));\r\n\t\t\t\tDbg_MsgAssert(value_b.mpString,(\"NULL value_b.mpString ?\"));\r\n\t\t\t\treturn strcmp(value_a.mpString,value_b.mpString)==0;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\tif (type_b==ESYMBOLTYPE_LOCALSTRING)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(value_a.mpLocalString,(\"NULL value_a.mpLocalString ?\"));\r\n\t\t\t\tDbg_MsgAssert(value_b.mpLocalString,(\"NULL value_b.mpLocalString ?\"));\r\n\t\t\t\treturn strcmp(value_a.mpLocalString,value_b.mpLocalString)==0;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t\tif (type_b==ESYMBOLTYPE_NAME)\r\n\t\t\t{\r\n\t\t\t\treturn value_a.mChecksum==value_b.mChecksum;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\tif (type_b==ESYMBOLTYPE_PAIR)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(value_a.mpPair,(\"NULL value_a.mpPair ?\"));\r\n\t\t\t\tDbg_MsgAssert(value_b.mpPair,(\"NULL value_b.mpPair ?\"));\r\n\t\t\t\treturn value_a.mpPair->mX==value_b.mpPair->mX && \r\n\t\t\t\t\t   value_a.mpPair->mY==value_b.mpPair->mY;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\tif (type_b==ESYMBOLTYPE_VECTOR)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(value_a.mpVector,(\"NULL value_a.mpVector ?\"));\r\n\t\t\t\tDbg_MsgAssert(value_b.mpVector,(\"NULL value_b.mpVector ?\"));\r\n\t\t\t\treturn value_a.mpVector->mX==value_b.mpVector->mX && \r\n\t\t\t\t\t   value_a.mpVector->mY==value_b.mpVector->mY &&\r\n\t\t\t\t\t   value_a.mpVector->mZ==value_b.mpVector->mZ;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_QSCRIPT:\r\n\t\t\tif (type_b==ESYMBOLTYPE_QSCRIPT)\r\n\t\t\t{\r\n\t\t\t\treturn value_a.mpScript==value_b.mpScript;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t\tif (type_b==ESYMBOLTYPE_STRUCTURE)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(value_a.mpStructure,(\"NULL value_a.mpStructure ?\"));\r\n\t\t\t\tDbg_MsgAssert(value_b.mpStructure,(\"NULL value_b.mpStructure ?\"));\r\n\t\t\t\t\r\n\t\t\t\t// The structures definitely match if the pointers match, cos its the \r\n\t\t\t\t// same bloomin' structure.\r\n\t\t\t\tif (value_a.mpStructure==value_b.mpStructure)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t// If the pointers do not match, the structures may still have contents that match.\r\n\t\t\t\t// Structure comparison's ain't supported yet though. Implement when needed.\r\n\t\t\t\t// Note: If this ever get's implemented, you'll need to deal with un-named name \r\n\t\t\t\t// components that resolve to a global structure.\r\n\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\tprintf(\"CStruct comparisons are not supported yet ... implement when needed\\n\");\r\n\t\t\t\t#endif\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t\tif (type_b==ESYMBOLTYPE_ARRAY)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(value_a.mpArray,(\"NULL value_a.mpArray ?\"));\r\n\t\t\t\tDbg_MsgAssert(value_b.mpArray,(\"NULL value_b.mpArray ?\"));\r\n\t\t\t\t\r\n\t\t\t\t// The arrays definitely match if the pointers match.\r\n\t\t\t\tif (value_a.mpArray==value_b.mpArray)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t// If the pointers do not match, the arrays may still have contents that match.\r\n\t\t\t\treturn *value_a.mpArray==*value_b.mpArray;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_CFUNCTION:\r\n\t\t\t// TODO ...\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tprintf(\"C-Function comparisons are not supported yet ... implement when needed\\n\");\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_MEMBERFUNCTION:\r\n\t\t\t// TODO ...\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tprintf(\"Member function comparisons are not supported yet ... implement when needed\\n\");\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_NONE:\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tprintf(\"'%s' with '%s' comparisons are not supported\\n\",GetTypeName(type_a),GetTypeName(type_b));\t\t\t\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\t\r\n\treturn false;\r\n}\r\n\r\nbool CComponent::operator!=( const CComponent& v ) const\r\n{\r\n\treturn !(*this==v);\r\n}\r\n\r\nbool CComponent::operator<( const CComponent& v ) const\r\n{\r\n\tUValue value_a,value_b;\r\n\tESymbolType type_a,type_b;\r\n\tResolve(*this,type_a,value_a);\r\n\tResolve(v,type_b,value_b);\r\n\t\r\n\tswitch (type_a)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\tif (type_b==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\treturn ((float)value_a.mIntegerValue) < value_b.mFloatValue;\r\n\t\t\t}\r\n\t\t\telse if (type_b==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\treturn value_a.mIntegerValue < value_b.mIntegerValue;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\tif (type_b==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\treturn value_a.mFloatValue < ((float)value_b.mIntegerValue);\r\n\t\t\t}\r\n\t\t\telse if (type_b==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\treturn value_a.mFloatValue < value_b.mFloatValue;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_STRING:\r\n\t\t\tif (type_b==ESYMBOLTYPE_STRING)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(value_a.mpString,(\"NULL value_a.mpString ?\"));\r\n\t\t\t\tDbg_MsgAssert(value_b.mpString,(\"NULL value_b.mpString ?\"));\r\n\t\t\t\t// Using string length rather than position in the alphabet, cos it's\r\n\t\t\t\t// probably more useful.\r\n\t\t\t\treturn strlen(value_a.mpString) < strlen(value_b.mpString);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\tif (type_b==ESYMBOLTYPE_LOCALSTRING)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(value_a.mpLocalString,(\"NULL value_a.mpLocalString ?\"));\r\n\t\t\t\tDbg_MsgAssert(value_b.mpLocalString,(\"NULL value_b.mpLocalString ?\"));\r\n\t\t\t\treturn strlen(value_a.mpLocalString) < strlen(value_b.mpLocalString);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tprintf(\"'%s' with '%s' less-than comparisons are not supported\\n\",GetTypeName(type_a),GetTypeName(type_b));\t\t\t\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\t\r\n\treturn false;\r\n}\r\n\r\nbool CComponent::operator>( const CComponent& v ) const\r\n{\r\n\tUValue value_a,value_b;\r\n\tESymbolType type_a,type_b;\r\n\tResolve(*this,type_a,value_a);\r\n\tResolve(v,type_b,value_b);\r\n\t\r\n\tswitch (type_a)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\tif (type_b==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\treturn ((float)value_a.mIntegerValue) > value_b.mFloatValue;\r\n\t\t\t}\r\n\t\t\telse if (type_b==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\treturn value_a.mIntegerValue > value_b.mIntegerValue;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\tif (type_b==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\treturn value_a.mFloatValue > ((float)value_b.mIntegerValue);\r\n\t\t\t}\r\n\t\t\telse if (type_b==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\treturn value_a.mFloatValue > value_b.mFloatValue;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_STRING:\r\n\t\t\tif (type_b==ESYMBOLTYPE_STRING)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(value_a.mpString,(\"NULL value_a.mpString ?\"));\r\n\t\t\t\tDbg_MsgAssert(value_b.mpString,(\"NULL value_b.mpString ?\"));\r\n\t\t\t\t// Using string length rather than position in the alphabet, cos it's\r\n\t\t\t\t// probably more useful.\r\n\t\t\t\treturn strlen(value_a.mpString) > strlen(value_b.mpString);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\tif (type_b==ESYMBOLTYPE_LOCALSTRING)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(value_a.mpLocalString,(\"NULL value_a.mpLocalString ?\"));\r\n\t\t\t\tDbg_MsgAssert(value_b.mpLocalString,(\"NULL value_b.mpLocalString ?\"));\r\n\t\t\t\treturn strlen(value_a.mpLocalString) > strlen(value_b.mpLocalString);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tprintf(\"'%s' with '%s' greater-than comparisons are not supported\\n\",GetTypeName(type_a),GetTypeName(type_b));\t\t\t\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\t\r\n\treturn false;\r\n}\r\n\r\nbool CComponent::operator<=( const CComponent& v ) const\r\n{\r\n\tif (*this<v)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\tif (*this==v)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\t\r\n}\r\n\r\nbool CComponent::operator>=( const CComponent& v ) const\r\n{\r\n\tif (*this>v)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\tif (*this==v)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\t\r\n}\r\n\r\n// This is used in eval.cpp, when evaluating foo[3] say.\r\n// Copies the array element indicated by index into the passed component.\r\n// The type of p_comp may be ESYMBOLTYPE_NONE if the type is not supported yet by not being in\r\n// the switch statement.\r\nvoid CopyArrayElementIntoComponent(CArray *p_array, uint32 index, CComponent *p_comp)\r\n{\r\n\tDbg_MsgAssert(p_array,(\"NULL p_array\"));\r\n\tDbg_MsgAssert(index<p_array->GetSize(),(\"Array index %d out of range, array size is %d\",index,p_array->GetSize()));\r\n\tDbg_MsgAssert(p_comp,(\"NULL p_comp\"));\r\n\t\r\n\tp_comp->mType=p_array->GetType();\r\n\tswitch (p_comp->mType)\r\n\t{\r\n\tcase ESYMBOLTYPE_INTEGER:\r\n\t\tp_comp->mIntegerValue=p_array->GetInteger(index);\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_FLOAT:\r\n\t\tp_comp->mFloatValue=p_array->GetFloat(index);\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_NAME:\r\n\t\tp_comp->mChecksum=p_array->GetChecksum(index);\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\tp_comp->mpStructure=new CStruct;\r\n\t\tp_comp->mpStructure->AppendStructure(p_array->GetStructure(index));\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_ARRAY:\r\n\t\tp_comp->mpArray=new CArray;\r\n\t\tCopyArray(p_comp->mpArray,p_array->GetArray(index));\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_STRING:\r\n\t\tp_comp->mpString=CreateString(p_array->GetString(index));\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_VECTOR:\r\n\t{\r\n\t\tCVector *p_source_vector=p_array->GetVector(index);\r\n\t\tp_comp->mpVector=new CVector;\r\n\t\tp_comp->mpVector->mX=p_source_vector->mX;\r\n\t\tp_comp->mpVector->mY=p_source_vector->mY;\r\n\t\tp_comp->mpVector->mZ=p_source_vector->mZ;\r\n\t\tbreak;\r\n\t}\t\r\n\tcase ESYMBOLTYPE_PAIR:\r\n\t{\r\n\t\tCPair *p_source_pair=p_array->GetPair(index);\r\n\t\tp_comp->mpPair=new CPair;\r\n\t\tp_comp->mpPair->mX=p_source_pair->mX;\r\n\t\tp_comp->mpPair->mY=p_source_pair->mY;\r\n\t\tbreak;\r\n\t}\t\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0,(\"The [] operator is not yet supported when the array element has  type '%s'\",GetTypeName(p_comp->mType)));\r\n\t\tp_comp->mType=ESYMBOLTYPE_NONE;\r\n\t\tp_comp->mUnion=0;\r\n\t\tbreak;\r\n\t}\t\r\n}\r\n\r\n// This is used in parse.cpp, and cfuncs.cpp in sFormatText\r\nvoid ResolveNameComponent(CComponent *p_comp)\r\n{\r\n\tDbg_MsgAssert(p_comp,(\"NULL p_comp\"));\r\n\r\n\tif (p_comp->mType!=ESYMBOLTYPE_NAME)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tCSymbolTableEntry *p_entry=Resolve(p_comp->mChecksum);\r\n\tif (!p_entry)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tswitch (p_entry->mType)\r\n\t{\r\n\tcase ESYMBOLTYPE_FLOAT:\r\n\t\tp_comp->mType=ESYMBOLTYPE_FLOAT;\r\n\t\tp_comp->mFloatValue=p_entry->mFloatValue;\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_INTEGER:\r\n\t\tp_comp->mType=ESYMBOLTYPE_INTEGER;\r\n\t\tp_comp->mIntegerValue=p_entry->mIntegerValue;\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_VECTOR:\r\n\t\tp_comp->mType=ESYMBOLTYPE_VECTOR;\r\n\t\tp_comp->mpVector=p_entry->mpVector;\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_PAIR:\r\n\t\tp_comp->mType=ESYMBOLTYPE_PAIR;\r\n\t\tp_comp->mpPair=p_entry->mpPair;\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_STRING:\r\n\t\tp_comp->mType=ESYMBOLTYPE_STRING;\r\n\t\tp_comp->mpString=p_entry->mpString;\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\tp_comp->mType=ESYMBOLTYPE_LOCALSTRING;\r\n\t\tp_comp->mpLocalString=p_entry->mpLocalString;\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\tp_comp->mType=ESYMBOLTYPE_STRUCTURE;\r\n\t\tp_comp->mpStructure=p_entry->mpStructure;\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_ARRAY:\r\n\t\tp_comp->mType=ESYMBOLTYPE_ARRAY;\r\n\t\tp_comp->mpArray=p_entry->mpArray;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n} // namespace Script\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/utils.h",
    "content": "#ifndef\t__SCRIPTING_UTILS_H\r\n#define\t__SCRIPTING_UTILS_H\r\n\r\n#ifndef\t__SCRIPTING_SCRIPTDEFS_H\r\n#include <gel/scripting/scriptdefs.h> // For EAssertType\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\r\nclass CArray;\r\nclass CStruct;\r\nclass CComponent;\r\n\r\nvoid PrintContents(const CArray *p_array, int indent=0);\r\nvoid PrintContents(const CStruct *p_structure, int indent=0);\r\n\r\nuint32 WriteToBuffer(CStruct *p_structure, uint8 *p_buffer, uint32 bufferSize, EAssertType assert=ASSERT);\r\nuint32 CalculateBufferSize(CStruct *p_structure, uint32 tempBufferSize=100000);\r\nuint8 *ReadFromBuffer(CStruct *p_structure, uint8 *p_buffer);\r\n\r\nuint32 WriteToBuffer(CArray *p_array, uint8 *p_buffer, uint32 bufferSize, EAssertType assert=ASSERT);\r\nuint32 CalculateBufferSize(CArray *p_array);\r\nuint8 *ReadFromBuffer(CArray *p_array, uint8 *p_buffer);\r\n\r\n// This is used in eval.cpp, when evaluating foo[3] say.\r\n// Copies the array element indicated by index into the passed component.\r\n// The type of p_comp may be ESYMBOLTYPE_NONE if the type is not supported yet by not being in\r\n// the switch statement.\r\nvoid CopyArrayElementIntoComponent(CArray *p_array, uint32 index, CComponent *p_comp);\r\nvoid ResolveNameComponent(CComponent *p_comp);\r\n\r\n}\r\n\r\n#endif // #ifndef\t__SCRIPTING_UTILS_H\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/vecpair.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// vecpair.cpp\t\tKSH 17 Oct 2001\r\n//\r\n// Just defines the constructors and pool statics.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <gel/scripting/vecpair.h>\r\n\r\nDefinePoolableClass(Script::CVector);\r\nDefinePoolableClass(Script::CPair);\r\n\r\nnamespace Script\r\n{\r\n\r\nCVector::CVector()\r\n{\r\n\t// Initialise everything. CVector is not derived from CClass so we don't get\r\n\t// the auro-zeroing.\r\n\tmX=mY=mZ=0.0f;\r\n}\r\n\r\n// Note: No destructor needed.\r\n\r\n\r\nCPair::CPair()\r\n{\r\n\t// Initialise everything. CPair is not derived from CClass so we don't get\r\n\t// the auro-zeroing.\r\n\tmX=mY=0.0f;\r\n}\r\n\r\n// Note: No destructor needed.\r\n\r\n} // namespace Script\r\n\r\n"
  },
  {
    "path": "Code/Gel/Scripting/vecpair.h",
    "content": "#ifndef\t__SCRIPTING_VECPAIR_H\r\n#define\t__SCRIPTING_VECPAIR_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __SYS_MEM_POOLABLE_H\r\n#include <sys/mem/poolable.h>\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\r\n// Note: These are not derived from CClass to avoid the extra memory overhead due to the virtual destructor.\r\n\r\n#ifdef __PLAT_WN32__\r\nclass CVector\r\n#else\r\nclass CVector : public Mem::CPoolable<CVector>\r\n#endif\r\n{\r\npublic:\r\n\tCVector();\r\n\t// No copy constructor or assignement operators needed, the defaults will work.\r\n\r\n\tunion\r\n\t{\r\n\t\tCVector *mpNext;\r\n\t\tfloat mX;\r\n\t};\t\r\n\t\r\n\tfloat mY;\r\n\tfloat mZ;\r\n};\r\n\r\n#ifdef __PLAT_WN32__\r\nclass CPair\r\n#else\r\nclass CPair : public Mem::CPoolable<CPair>\r\n#endif\r\n{\r\npublic:\r\n\tCPair();\r\n\t// No copy constructor or assignement operators needed, the defaults will work.\r\n\r\n\tunion\r\n\t{\r\n\t\tCPair *mpNext;\r\n\t\tfloat mX;\r\n\t};\t\r\n\t\r\n\tfloat mY;\r\n};\r\n\r\n} // namespace Script\r\n\r\n#endif // #ifndef\t__SCRIPTING_VECPAIR_H\r\n"
  },
  {
    "path": "Code/Gel/Scripting/win32functions.cpp",
    "content": "#ifdef __PLAT_WN32__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\nnamespace Tmr\r\n{\r\nuint64 GetRenderFrame( void )\r\n{\r\n\treturn 0;\r\n}\r\n\r\nuint64 GetTimeInCPUCycles( void )\r\n{\r\n\treturn 0;\r\n}\r\n}\r\n\r\nnamespace Obj\r\n{\r\n// Needed for asserts to compile\r\nbool DebugSkaterScripts=false;\r\n\r\nclass CObject;\r\n\r\nCObject *ResolveToObject(uint32 id, bool ignoreScreenElements)\r\n{\r\n\treturn NULL;\r\n}\r\n}\r\n\r\nnamespace Pip\r\n{\r\nvoid *Load(const char *p_fileName)\r\n{\r\n\treturn NULL;\r\n}\r\n\r\nvoid Unload(const char *p_fileName)\r\n{\r\n}\r\n}\r\n\r\nnamespace Mem\r\n{\r\n\r\nManager *Manager::sp_instance = NULL;\r\n\r\nManager::Manager( void )\r\n{\r\n\tmemset(this,0,sizeof(Manager));\r\n}\r\n\r\nvoid Manager::sSetUp( void )\r\n{\r\n\tif ( !sp_instance )\r\n\t{\r\n\t\tsp_instance = new Manager;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Warning( \"Already Initialized!\" );\r\n\t}\r\n}\r\n\r\nvoid Manager::sCloseDown( void )\r\n{\r\n}\r\n\r\nvoid Manager::PushContext( Allocator* alloc )\r\n{\r\n}\r\n\r\nvoid Manager::PopContext( void )\r\n{\r\n}\r\n\r\nchar *Manager::GetContextName()\r\n{\r\n\treturn \"\";\r\n}\r\n\r\nMem::Heap *Manager::FirstHeap()\r\n{\r\n\treturn NULL;\r\n}\r\n\r\nHeap* Manager::GetHeap( uint32 whichHeap )\r\n{\r\n\treturn NULL;\r\n}\r\n\r\nMem::Heap *Manager::NextHeap(Mem::Heap * pHeap)\r\n{\r\n\treturn NULL;\r\n}\r\n\r\nvoid SetThreadSafe(bool safe)\r\n{\r\n}\r\n\r\nvoid *Malloc( size_t size )\r\n{\r\n\treturn new char[size];\r\n}\r\n\r\nvoid Free( void *p_mem )\r\n{\r\n\tdelete [] p_mem;\r\n}\r\n\r\nvoid PopMemProfile()\r\n{\r\n}\r\n\r\nvoid PushMemProfile(char *p_type)\r\n{\r\n}\r\n\r\n}\r\n\r\n#endif\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/SoundFX/NGPS/p_sfx.cpp",
    "content": "//--------------------------------------------------------------------------------------------\r\n// Playstation 2 sound effect functionality...\r\n// Taken from samples on Sony website, modified by mjd.\r\n//--------------------------------------------------------------------------------------------\r\n\r\n#include <eetypes.h>\r\n#include <eekernel.h>\r\n#include <stdio.h>\r\n#include <sif.h>\r\n#include <sifdev.h>\r\n#include <sdrcmd.h>\r\n#include <libsdr.h>\r\n#include <sdmacro.h>\r\n#include <string.h>\r\n\r\n#include <core/macros.h>\r\n#include <core/defines.h>\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/soundfx/ngps/p_sfx.h>\r\n#include <gel/music/ngps/pcm/pcm.h>\r\n#include <gel/music/ngps/p_music.h>\r\n#include <gel/music/music.h>\r\n#include <sys/file/filesys.h>\r\n\r\n#include <gel/music/ngps/pcm/pcm.h>\r\n\r\n#define NO_SOUND\t0\r\n\r\nnamespace Pcm\r\n{\r\nextern int\tgNonAllignedIopBuffer;\r\n};\r\n\r\nnamespace Sfx\r\n{\r\n\r\n\r\n\r\n// Macros and constants:\r\n\r\n// This array maps the platform-independent reverb modes specified in reverb.q to the available Ps2 reverb modes.\r\nint ReverbModes[] =\r\n{\r\n\t// put the default first in this list, since the default param to SetReverb() is 0\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_DEFAULT\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_GENERIC\r\n\tSD_REV_MODE_ROOM,\t\t\t// REV_MODE_PADDEDCELL\r\n\tSD_REV_MODE_ROOM,\t\t\t// REV_MODE_ROOM\r\n\tSD_REV_MODE_STUDIO_A,\t\t// REV_MODE_BATHROOM\r\n\tSD_REV_MODE_ROOM,\t\t\t// REV_MODE_LIVINGROOM\r\n\tSD_REV_MODE_STUDIO_C,\t\t// REV_MODE_STONEROOM\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_AUDITORIUM\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_CONCERTHALL\r\n\tSD_REV_MODE_ROOM,\t\t\t// REV_MODE_CAVE\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_ARENA\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_HANGAR\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_CARPETEDHALLWAY\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_HALLWAY\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_STONECORRIDOR\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_ALLEY\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_FOREST\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_CITY\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_MOUNTAINS\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_QUARRY\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_PLAIN\r\n\tSD_REV_MODE_HALL,\t\t\t// REV_MODE_PARKINGLOT\r\n\tSD_REV_MODE_PIPE,\t\t\t// REV_MODE_SEWERPIPE\r\n\tSD_REV_MODE_PIPE,\t\t\t// REV_MODE_UNDERWATER\r\n};\r\n\r\n#define NUM_REVERB_MODES ( ( int )( sizeof( ReverbModes ) / sizeof( int ) ) )\r\n\r\n#if NUM_STREAMS > 3\r\n#error tell matt to handle more than 3 streams in sfx.cpp\r\n#endif\r\n\r\n#if NUM_STREAMS == 3\r\n#define VOICES_MINUS_STREAMS ( 0xFFFFFF & ~( ( 1 << STREAM_VOICE( 0 ) ) | ( 1 << STREAM_VOICE( 1 ) ) | ( 1 << STREAM_VOICE( 2 ) ) ) )\r\n#else\r\n#define VOICES_MINUS_STREAMS ( 0xFFFFFF & ~( ( 1 << MUSIC_L_VOICE ) | ( 1 << MUSIC_R_VOICE ) ) )\r\n#endif\r\n#define VOICES_MINUS_NON_REVERB ( ( ( 1 << NUM_NO_REVERB_VOICES ) - 1 ) << NUM_NO_REVERB_START_VOICE )\r\n\r\n// convert sample rate to pitch setting\r\n#define FREQ2PITCH( x ) ( ( ( float ) ( ( x ) * 100 ) / 48000.0f ) )\r\n\r\n#define DMA_CH\t\t\t\t\t\t0\r\n\r\n#if ( ( CORE_0_EFFECTS_END_ADDRESS - CORE_0_EFFECTS_START_ADDRESS ) < ( RAM_NEEDED_FOR_EFFECTS ) )\r\n#error \"not enough room for effects\"\r\n#endif\r\n\r\nint sTargetReverbDepth = 0;\r\nint sCurrentReverbDepth = 0;\r\n\r\n// allocated SPU RAM\r\nint SpuRAMUsedTemp = 0;\r\nint SpuRAMUsedPerm = 0;\r\n\r\nint LoopingSounds[ NUM_CORES ];\r\n// gotta keep track of voices used, to be able\r\n// to tell whether a voice is free or not...\r\nvolatile int VoicesUsed[ NUM_CORES ];\r\nvolatile int VoicesCleared[ NUM_CORES ];\r\n\r\n// avoid checking voice status more than once per frame:\r\n//uint64\tgLastVoiceAvailableUpdate[ NUM_CORES ];\r\n//int\t\tgAvailableVoices[ NUM_CORES ];\r\nfloat\tgSfxVolume = 100.0f;\r\n\r\n#define MAX_VOLUME\t\t\t\t\t0x3FFF  // max playstation 2 volume...\r\n#define MAX_REVERB_DEPTH\t\t\t0x3FFF\r\n#define MAX_PITCH\t\t\t\t\t0x3FFF\r\n#define UNALTERED_PITCH\t\t\t\t4096\r\n\r\n#define BLOCKHEADER_LOOP_BIT\t( 1 << 9 )\r\n\r\n// Internal function prototypes:\r\n\r\nfloat \tGetPitchValue( VagHeader *VagHdr );\r\nint \tconvertEnd( int inp );\r\nbool\tPS2Sfx_LoadVAG( PlatformWaveInfo *pInfo, const char *filename, bool loadPerm, float *samplePitch = NULL );\r\nint\t\tGetCore( int whichVoice );\r\n\r\nint\t\tPS2Sfx_PlaySound( PlatformWaveInfo *pInfo, int voiceNumber, float volL = 100.0f, float volR = 100.0f, float pitch = 100.0f );\r\nvoid\tPS2Sfx_StopSound( int voiceNumber );\r\nint\t\tPS2Sfx_GetVoiceStatus( int core );\r\n\r\n#define ALLIGN_REQUIREMENT\t64 // EE to IOP\r\n#define SIZE_OF_LEADIN\t\t16\r\n#define USE_CLEVER_TRICK_FOR_CLOBBERED_DATA\t\t1\r\n\r\n// IOP_MIN_TRANSFER must be a power of 2!!!\r\n#define IOP_MIN_TRANSFER\t64\t// iop will clobber memory if you're writing above a sound.  we'll restore the\r\n\t\t\t\t\t\t\t\t// potentially clobbered memory by keeping a buffer containing the beginning of\r\n\t\t\t\t\t\t\t\t// the previously loaded perm sound, and copying that to the end of our new\r\n\t\t\t\t\t\t\t\t// data...\r\n\r\n#if USE_CLEVER_TRICK_FOR_CLOBBERED_DATA\r\n#define\t\tPAD_TO_PREVENT_CLOBBERING\t\t0\r\n#else\r\n#define\t\tPAD_TO_PREVENT_CLOBBERING\t\t64\r\n#endif\r\n\r\n#define FULL_NAME_SIZE\t\t256\r\n\r\nint GetMemAvailable( void )\r\n{\r\n\t\r\n\treturn ( MAX_SPU_RAM_AVAILABLE - ( SpuRAMUsedTemp + SpuRAMUsedPerm ) );\r\n}\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// Function: int EELoadVAG(char *filename ); //, int *samplePitch)\r\n// Description: Transfers specified filename into SPU2 RAM and returns an address value for\r\n//\t\tfor use in the SetVoice() function\r\n// Parameters:  filename to be transfered\r\n//\r\n// Returns: value referencing the vag address in SPU2 RAM\r\n// Notes: This transfers all data in a blocking fashion, but quickly.\r\n//-------------------------------------------------------------------------------------------\r\nbool PS2Sfx_LoadVAG( PlatformWaveInfo *pInfo, const char *filename, bool loadPerm, float *samplePitch)\r\n{\r\n\t\r\n\t\r\n\tuint32 size = 0;\t\t\t\t// file size\r\n\tint vagAddr = 0;\t\t\t// VAG address in SPU2 RAM, returned to calling function\r\n\tVagHeader vagHeader;\r\n\tchar fullname[ FULL_NAME_SIZE ]; // sound names can be HUGE...\r\n\tunsigned int IOPbuffer = 0; // IOP memory buffer\r\n\t\r\n\tDbg_MsgAssert( strlen( filename ) < FULL_NAME_SIZE - 30,( \"Increase buffer for full filename...\" ));\r\n\tsprintf(fullname, \"sounds\\\\vag\\\\%s.vag\", filename);\r\n\t//Matt(\"Loading sound %s\\n\", fullname);\r\n    \r\n\tvoid *fp = File::Open( fullname, \"rb\" );\r\n\tif ( !fp )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"LoadSound: Couldn't find file %s\", filename ));\r\n\t\tprintf( \"load sound failed to find %s\\n\", filename );\r\n\t\treturn ( false );\r\n\t}\r\n\tFile::Seek( fp, 0, SEEK_SET );\r\n\tif ( SIZE_OF_VAGHEADER != File::Read( &vagHeader, 1, SIZE_OF_VAGHEADER, fp ) )\r\n\t{\r\n\t\t// error reading header...\r\n\t\tDbg_MsgAssert( 0,( \"Sorry, young lady, but your VAG is too small\" ));\r\n//\t\tDbg_MsgAssert( 0,( \"Not enough bytes to satisfy our VAG\" ));\r\n\t}\r\n\t/*  this fucked things up...\r\n\tint endType = 0;\r\n\tif ( strncmp( vagHeader.ID, \"VAGp\", 4 ) == 0 )\r\n\t\tendType = 0;\r\n\telse\r\n\t\tendType = 1;\r\n\t\r\n\tsize = ( ( endType == 0 ) ? convertEnd( vagHeader.dataSize ) : vagHeader.dataSize );\r\n\t*/\r\n\tsize = convertEnd( vagHeader.dataSize );\r\n\r\n\tDbg_MsgAssert( size > 0,( \"There's nothing worse than an empty VAG.\" ));\r\n\r\n\t//Dbg_Message( \"vag header size %d data size %d\", SIZE_OF_VAGHEADER, size );\r\n\r\n#if USE_CLEVER_TRICK_FOR_CLOBBERED_DATA\r\n\tuint8 *buffer = new uint8[ size + ALLIGN_REQUIREMENT + IOP_MIN_TRANSFER ];\r\n#else\r\n\tuint8 *buffer = new uint8[ size + ALLIGN_REQUIREMENT ];\r\n#endif\r\n\tFile::Seek( fp, SIZE_OF_VAGHEADER, SEEK_SET );\r\n\t\r\n\tuint8 *allignedBuffer = ( uint8 * )( ( ( int ) buffer + ( ALLIGN_REQUIREMENT - 1 ) ) & ~( ALLIGN_REQUIREMENT - 1 ) );\r\n\t\r\n\tuint32 readsize = File::Read( allignedBuffer, 1, size, fp );\r\n\tif ( size !=  readsize)\r\n\t{\r\n\t\tDbg_Message( \"if non-converted size %d is the correct size of file %s, inconsistent VAG format\", vagHeader.dataSize + SIZE_OF_VAGHEADER, filename );\r\n\t\tDbg_MsgAssert( 0,( \"VAG %s is %d bytes, not as big as she said it would be (%d bytes)\", filename, readsize, size ));\r\n\t}\r\n\tFile::Close( fp );\r\n\t\t\r\n\tif ( samplePitch )\r\n\t{\r\n\t\t*samplePitch = GetPitchValue( &vagHeader );\r\n\t}\r\n//\tDbg_Message( \"Pitch value %f\", GetPitchValue( &vagHeader ) );\r\n\r\n\t// make sure we've got room for this sound in RAM:\r\n\t// sound data must be 16byte aligned in the SPU, so check for that\r\n\t// also, the IOP seems to transfer only in 128 byte chunks, so let's\r\n\t// pad the buffer if we're writing a permanent sound (which stacks from\r\n\t// the bottom if RAM up) and write the potentially clobbered bytes from\r\n\t// the previously loaded permanent sound into the end of the buffer to\r\n\t// be transfered (clever huh?)  NOTE: This didn't seem to work without\r\n\t// flushing the cache...  Gives everything in memory time to settle I\r\n\t// guess?\r\n\t\r\n\tif ( loadPerm )\r\n\t{\r\n#if USE_CLEVER_TRICK_FOR_CLOBBERED_DATA\r\n\t\tint i;\r\n\t\tint overshoot = 0; // need to initialize to zero!\r\n\t\tstatic uint8 prevPermBuffer[ IOP_MIN_TRANSFER ];\r\n\t\tstatic int prevVagAddr;\r\n        if ( !SpuRAMUsedPerm )\r\n\t\t{\r\n\t\t\t// don't store nuthin' first time through...\r\n\t\t\tprevVagAddr = 0;\r\n\t\t}\r\n#endif\r\n\t\t// stack the permanent sounds up from the bottom:\r\n\t\tSpuRAMUsedPerm += ( size + PAD_TO_PREVENT_CLOBBERING );\r\n\t\tif ( ( END_WAVE_DATA_ADDR - SpuRAMUsedPerm ) & 0x0F )\r\n\t\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\t\tint oldSpuRAM = SpuRAMUsedPerm;\r\n#endif\t\t\t\r\n\t\t\tSpuRAMUsedPerm += ( ( END_WAVE_DATA_ADDR - SpuRAMUsedPerm ) & 0x0F );\r\n\t\t\tDbg_MsgAssert( SpuRAMUsedPerm > oldSpuRAM,( \"Duh asshole.\" ));\r\n\t\t}\r\n\t\tvagAddr = END_WAVE_DATA_ADDR - SpuRAMUsedPerm;\r\n\t\tDbg_MsgAssert( !( vagAddr & 0x0F ),( \"Fire Matt please.\" ));\r\n\t\t\r\n#if USE_CLEVER_TRICK_FOR_CLOBBERED_DATA\r\n\t\tif ( prevVagAddr )\r\n\t\t{\r\n\t\t\t// don't have to do this if this is the first loaded perm sound...\r\n\t\t\t// hence condition above...\r\n\t\t\t\r\n\t\t\t// find out how much of the previous perm data we'd be writing\r\n\t\t\t// over, add that to the end of our buffer...\r\n\t\t\tif ( size & ( IOP_MIN_TRANSFER - 1 ) )\r\n\t\t\t{\r\n//\t\t\t\tDbg_Message( \"size %d over 64-byte boundary\", size & ( IOP_MIN_TRANSFER - 1 ) );\r\n\t\t\t\tovershoot = ( IOP_MIN_TRANSFER ) - ( size & ( IOP_MIN_TRANSFER - 1 ) );\r\n//\t\t\t\tDbg_Message( \"overshoot %d\", overshoot );\r\n\t\t\t\tint spaceBetween = prevVagAddr - ( vagAddr + size );\r\n//\t\t\t\tDbg_Message( \"space between %d\", spaceBetween );\r\n\t\t\t\tint numBytesClobbered = overshoot - spaceBetween;\r\n\t\t\t\tDbg_MsgAssert( numBytesClobbered <= IOP_MIN_TRANSFER,( \"how in the world?\" ));\r\n//\t\t\t\tDbg_Message( \"numBytesClobbered = %d\", numBytesClobbered );\r\n\t\t\t\tfor ( i = 0; i < numBytesClobbered; i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\t// store the previous buffer at the end of our buffer,\r\n\t\t\t\t\tallignedBuffer[ size + i + spaceBetween ] = prevPermBuffer[ i ];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tovershoot = 0;\r\n\t\t\t}\t\r\n\t\t\tsize += overshoot;\r\n\t\t\t// add on the size of the overshoot, which in the case of permanent sounds\r\n\t\t\t// has data from a previous sound (which will be clobbered), written in.\r\n//\t\t\tsize += overshoot;\r\n\t\t\tDbg_MsgAssert( !( size & ( IOP_MIN_TRANSFER - 1 ) ),( \"Fire Matt.\" ));\r\n\t\t\t\r\n\t\t}\r\n\t\tfor ( i = 0; i < IOP_MIN_TRANSFER; i++ )\r\n\t\t{\r\n\t\t\t// store the beginning of our new buffer into the static buffer\r\n\t\t\t// for when the next perm sound loads...\r\n\t\t\tprevPermBuffer[ i ] = allignedBuffer[ i ];\r\n\t\t}\r\n\t\tprevVagAddr = vagAddr;\r\n#endif\t\t\r\n\t} // if ( loadPerm )\r\n\telse\r\n\t{\r\n\t\tif ( ( SpuRAMUsedTemp + BASE_WAVE_DATA_ADDR ) & 0x0F )\r\n\t\t{\r\n\t\t\tSpuRAMUsedTemp += 0x10 - ( ( SpuRAMUsedTemp + BASE_WAVE_DATA_ADDR ) & 0x0F );\r\n\t\t}\r\n\t\tvagAddr = BASE_WAVE_DATA_ADDR + SpuRAMUsedTemp;\r\n\t\tSpuRAMUsedTemp += ( size );\r\n\t}\r\n\t\r\n\t// transfer buffer to IOP, it's a DMA operation so FlushCache() to ensure cache is flushed\r\n\tFlushCache( 0 );\r\n\r\n\t// Ken: Instead of borrowing a new chunk of memory from the IOP, (which causes it to often\r\n\t// run out cos we're so tight on memory) use the already existing\r\n\t// gNonAllignedIopBuffer, used by streams and music etc. They have no need of it at this point.\r\n\t//IOPbuffer = ( unsigned int )sceSifAllocIopHeap( size );\r\n\tDbg_MsgAssert(size<TOTAL_IOP_BUFFER_SIZE_NEEDED + ALLIGN_REQUIREMENT,(\"Oops! Vag '%s' too big for iop buffer\",filename));\r\n\tDbg_MsgAssert(Pcm::gNonAllignedIopBuffer,(\"NULL gNonAllignedIopBuffer\"));\r\n\tIOPbuffer=Pcm::gNonAllignedIopBuffer;\r\n\t\r\n\tDbg_MsgAssert( !( IOPbuffer & 3 ),( \"This address should be four byte alligned.\" ));\r\n\tif ( !IOPbuffer )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Failed to allocate IOP memory\\n\" ));\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tif ( sceSdTransToIOP( allignedBuffer, IOPbuffer, size, 1 ) == -1 )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Failed to transfer to IOP\\n\" ));\r\n\t\treturn false;\r\n\t}\r\n\t// now transfer from IOP memory into SPU2 RAM\r\n\t\r\n\tif ( ( SpuRAMUsedTemp + SpuRAMUsedPerm + IOP_MIN_TRANSFER ) > MAX_SPU_RAM_AVAILABLE )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Our VAG space has been RAMed to the hilt\" ));\r\n\t}\r\n\r\n\tif (!CSpuManager::sVoiceTrans(DMA_CH, SD_TRANS_MODE_WRITE | SD_TRANS_BY_DMA, (void *) IOPbuffer, (uint32 *) vagAddr, size))\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Failed to Transfer to SPU2 size %d vagAddr %x IOPBuffer addr %x\\n\", size, vagAddr, IOPbuffer ));\r\n\t}\r\n\r\n\t// Ken: Commented this out because now we're using Pcm::gNonAllignedIopBuffer instead.\r\n\t// Now free up IOP and EE memory, check this return value is zero, as documentation (iopservice.txt v1.5) seems to be wrong\r\n\t//if( sceSifFreeIopHeap( (void * ) IOPbuffer ) != 0 )\r\n\t//{\r\n\t//\tDbg_MsgAssert( 0,( \"Failed to free IOP memory\\n\" ));\r\n\t//}\r\n\r\n\tpInfo->vagAddress = vagAddr;\r\n\tuint16 blockHeader = *( ( uint16 * ) allignedBuffer + SIZE_OF_LEADIN );\r\n\tpInfo->looping = ( blockHeader & BLOCKHEADER_LOOP_BIT ) ? true : false;\r\n\t\r\n\tdelete buffer;\r\n\treturn ( true );\r\n}\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// Function    : float GetPitchValue(char *buffer)\r\n// Description : gets pitch value from VAG header\r\n//\r\n// Parameters  : pointer to VAG header\r\n//\r\n// Returns     : pitch value\r\n// Notes       : \r\n//-------------------------------------------------------------------------------------------\r\nfloat GetPitchValue( VagHeader *VagHdr )\r\n{\r\n\t\r\n/*\tint endType = 0;\r\n\r\n\tif ( strncmp( VagHdr->ID, \"VAGp\", 4 ) == 0 )\r\n\t\tendType = 0;\r\n\telse\r\n\t\tendType = 1;\r\n\r\n\tif(endType == 0)\r\n    {*/\r\n\t\treturn ( ( FREQ2PITCH( convertEnd( VagHdr->sampleFreq ) ) ) );\r\n/*\t}\r\n\telse\r\n\t{\r\n\t\treturn ( FREQ2PITCH( VagHdr->sampleFreq ) );\r\n\t}\r\n\treturn 0;*/\r\n}\r\n\r\n#ifdef __USER_MATT__\r\n//--------------------------------------------------------------------------------------------\r\n// Function    : void PrintVAGDetails(char *buffer)\r\n// Description : debug function to print out VAG details\r\n//\r\n// Parameters  : pointer to VAG header\r\n//\r\n// Returns     : \r\n// Notes       : \r\n//-------------------------------------------------------------------------------------------\r\nvoid PrintVAGDetails(char *buffer)\r\n{\r\n\t\r\n\tVagHeader *VagHdr;\r\n\tint i;\r\n\tint endType = 0;\t// 0 for PC, 1 for MAC\r\n\r\n\tVagHdr = (VagHeader *)buffer;\r\n\r\n\tDbg_Message(\"Checking for VAGp string ..'\");\r\n\tfor(i=0;i<4;i++)\r\n\t{\r\n\t\tDbg_Message(\"%c\",VagHdr->ID[i]);\r\n\t}\r\n\tDbg_Message(\"' found.\\n\");\r\n\r\n\tDbg_Message(\"VAG Details\\n\");\r\n\tDbg_Message(\"===========\\n\");\r\n\r\n\t// check for either little or big endian format (PC or MAC)\r\n\tif(strncmp(VagHdr->ID,\"VAGp\",4) == 0)\r\n\t\tendType = 0;\r\n\telse\r\n\t\tendType = 1;\r\n\r\n\tDbg_Message(\"ID         : \");\r\n\tfor(i=0;i<4;i++)\r\n\t{\r\n\t\tDbg_Message(\"%c\",VagHdr->ID[i]);\r\n\t}\r\n\tDbg_Message(\"\\n\");\r\n\r\n\tDbg_Message(\"VERSION    : \");\r\n\tDbg_Message(\"0x%x\", (endType == 0) ? convertEnd(VagHdr->version) : VagHdr->version);\r\n\tDbg_Message(\"\\n\");\r\n\r\n\tDbg_Message(\"RESERVED   : \");\r\n\tfor(i=0;i<4;i++)\r\n\t{\r\n\t\tDbg_Message(\"%x\",VagHdr->reserved1[i]);\r\n\t}\r\n\tDbg_Message(\"\\n\");\r\n\t\t\r\n\tDbg_Message(\"DATASIZE   : \");\r\n\tDbg_Message(\"0x%x\", (endType == 0) ? convertEnd(VagHdr->dataSize) : VagHdr->dataSize);\r\n\tDbg_Message(\"\\n\");\r\n\r\n\tDbg_Message(\"SAMPLEFREQ : \");\r\n\tDbg_Message(\"0x%x (%d)\", (endType == 0) ? convertEnd(VagHdr->sampleFreq) : VagHdr->sampleFreq, (endType == 0) ? convertEnd(VagHdr->sampleFreq) : VagHdr->sampleFreq);\r\n\tDbg_Message(\"\\n\");\r\n\r\n\tDbg_Message(\"RESERVED   : \");\r\n\tfor(i=0;i<12;i++)\r\n\t{\r\n\t\tDbg_Message(\"%x\",VagHdr->reserved2[i]);\r\n\t}\r\n\tDbg_Message(\"\\n\");\r\n\r\n\tDbg_Message(\"NAME       : \");\r\n\tfor(i=0;i<16;i++)\r\n\t{\r\n\t\tif(VagHdr->name[i] == '\\0')\r\n\t\t\tbreak;\r\n\t\tDbg_Message(\"%c\",VagHdr->name[i]);\r\n\t}\r\n\tDbg_Message(\"\\n\");\r\n\r\n\treturn;\r\n}\r\n#endif\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// Function    : int convertEnd(int inp)\r\n// Description : needed for swopping endian values if VAG has been created by PC\r\n//\r\n// Parameters  : \r\n//\r\n// Returns     : \r\n// Notes       : \r\n//-------------------------------------------------------------------------------------------\r\nint convertEnd(int inp)\r\n{\r\n\t\r\n\t// swap bytes 0 and 4, 1 and 2\r\n\treturn((inp & 0xFF) << 24) | ((inp & 0xFF00) << 8) | ((inp & 0xFF0000) >> 8) | ((inp & 0xFF000000) >> 24);\r\n}\r\n\r\n// Master volumeLevel from 0 to 100 percent...\r\nvoid SetVolumePlease( float volumeLevel )\r\n{\r\n\t\r\n\tgSfxVolume = volumeLevel;\r\n\r\n\tPcm::PCMAudio_SetStreamGlobalVolume( ( unsigned int ) volumeLevel );\r\n/*\r\n\tint vol = ( int )PERCENT( volumeLevel, MAX_VOLUME );\r\n\tif ( vol > MAX_VOLUME )\r\n\t\tvol = MAX_VOLUME;\r\n\t\r\n\tDbg_MsgAssert( vol >= 0.0f,( \"Can't have negative main volume.\" ));\r\n\r\n\tint i;\r\n\t// set master volume for both cores, both blocking\r\n\tfor ( i = 0; i < 2; i++ )\r\n\t{\r\n\t\t\r\n\t\tif ( !CSpuManager::sSendSdRemote( rSdSetParam, i | SD_P_MVOLL, vol ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"Error Setting Left Vol on core %d\\n\",i));\r\n\t\t}\r\n\t\tif ( !CSpuManager::sSendSdRemote( rSdSetParam, i | SD_P_MVOLR, vol ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"Error Setting Right Vol on core %d\\n\",i));\r\n\t\t}\r\n\t}*/\r\n} // end of SetVolumePlease( )\r\n\r\nvoid ReverbOff( void )\r\n{\r\n\t\r\n\tint i;\r\n\tsceSdEffectAttr r_attr;\r\n\r\n\tsTargetReverbDepth = sCurrentReverbDepth = 0;\r\n\t// --- set reverb attribute\r\n\tr_attr.depth_L  = 0;\r\n\tr_attr.depth_R  = 0;\r\n\tr_attr.delay    = 0;\r\n\tr_attr.feedback = 0;\r\n\tr_attr.mode = SD_REV_MODE_OFF;\r\n#if REVERB_ONLY_ON_CORE_0\r\n\ti = 0;  // just set reverb on core 0 (not the music core or any sfx on core 1)\r\n#else\r\n\tfor ( i = 0; i < 2; i++ )\r\n#endif\r\n\t{\r\n\t\t// Shut volume first\r\n\t\tif(!CSpuManager::sSendSdRemote( rSdSetParam, i | SD_P_EVOLL , sTargetReverbDepth ) )\r\n\t\t\tDbg_Message(\"Error setting reverb2\\n\");\r\n\t\tif(!CSpuManager::sSendSdRemote( rSdSetParam, i | SD_P_EVOLR , sTargetReverbDepth ) )\r\n\t\t\tDbg_Message(\"Error setting reverb3\\n\");\r\n\r\n\t\t// just turning off reverb on all voices...\r\n\t\tif(!CSpuManager::sSendSdRemote( rSdSetSwitch, i | SD_S_VMIXEL , 0 ) )\r\n\t\t\tDbg_Message(\"Error setting reverb4\\n\");\r\n\t\tif(!CSpuManager::sSendSdRemote( rSdSetSwitch, i | SD_S_VMIXER , 0 ) )\r\n\t\t\tDbg_Message(\"Error setting reverb5\\n\");\r\n\t\tif( !CSpuManager::sSendSdRemote( rSdSetEffectAttr, i, (uint32) &r_attr ) )\r\n\t\t\tDbg_Message( \"Error setting reverb\\n\" );\r\n\t}\r\n}\r\n\r\n#define REVERB_STEP ( ( MAX_REVERB_DEPTH / 20 ) + 1 )\r\n\r\nvoid DoReverbFade( void )\r\n{\r\n\tint i;\r\n\tif ( sTargetReverbDepth != sCurrentReverbDepth )\r\n\t{\r\n\t\tif ( sCurrentReverbDepth < sTargetReverbDepth )\r\n\t\t{\r\n\t\t\tsCurrentReverbDepth += REVERB_STEP;\r\n\t\t\tif ( sCurrentReverbDepth > sTargetReverbDepth )\r\n\t\t\t{\r\n\t\t\t\tsCurrentReverbDepth = sTargetReverbDepth;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsCurrentReverbDepth -= REVERB_STEP;\r\n\t\t\tif ( sCurrentReverbDepth < sTargetReverbDepth )\r\n\t\t\t{\r\n\t\t\t\tsCurrentReverbDepth = sTargetReverbDepth;\r\n\t\t\t\tif ( !sTargetReverbDepth )\r\n\t\t\t\t{\r\n\t\t\t\t\tReverbOff( );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n#if REVERB_ONLY_ON_CORE_0\r\n\t\ti = 0;  // just set reverb on core 0 (not the music core or any sfx on core 1)\r\n#else\r\n\t\tfor ( i = 0; i < 2; i++ )\r\n#endif\r\n\t\t{\r\n\t\t\tif(!CSpuManager::sSendSdRemote( rSdSetParam, i | SD_P_EVOLL , sCurrentReverbDepth ) )\r\n\t\t\t\tDbg_Message(\"Error setting reverb2\\n\");\r\n\t\t\t\r\n\t\t\tif(!CSpuManager::sSendSdRemote( rSdSetParam, i | SD_P_EVOLR , sCurrentReverbDepth ) )\r\n\t\t\t\tDbg_Message(\"Error setting reverb3\\n\");\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid InitReverbAddr( void )\r\n{\r\n#if REVERB_ONLY_ON_CORE_0\r\n\tif ( !CSpuManager::sSendSdRemote( rSdSetAddr, 0 | SD_A_ESA, CORE_0_EFFECTS_START_ADDRESS ) )\r\n\t\tDbg_Message( \"Error setting reverb\\n\" );\r\n\tif ( !CSpuManager::sSendSdRemote( rSdSetAddr, 0 | SD_A_EEA, CORE_0_EFFECTS_END_ADDRESS ) )\r\n\t\tDbg_Message( \"Error setting reverb\\n\" );\r\n#else\r\n\tif ( !CSpuManager::sSendSdRemote( rSdSetAddr, 0 | SD_A_ESA, CORE_0_EFFECTS_START_ADDRESS ) )\r\n\t\tDbg_Message( \"Error setting reverb\\n\" );\r\n\tif ( !CSpuManager::sSendSdRemote( rSdSetAddr, 0 | SD_A_EEA, CORE_0_EFFECTS_END_ADDRESS ) )\r\n\t\tDbg_Message( \"Error setting reverb\\n\" );\r\n\t\t\r\n\tif ( !CSpuManager::sSendSdRemote( rSdSetAddr, 1 | SD_A_ESA, CORE_1_EFFECTS_START_ADDRESS ) )\r\n\t\tDbg_Message( \"Error setting reverb\\n\" );\r\n\tif ( !CSpuManager::sSendSdRemote( rSdSetAddr, 1 | SD_A_EEA, CORE_1_EFFECTS_END_ADDRESS ) )\r\n\t\tDbg_Message( \"Error setting reverb\\n\" );\r\n#endif\r\n}\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// Function: void SetReverb(void)\r\n// Description: Sets reverb level and type\r\n// Parameters:  none\r\n//\r\n// Returns:\r\n//-------------------------------------------------------------------------------------------\r\nvoid SetReverbPlease( float reverbLevel, int reverbType, bool instant )\r\n{\r\n\t\r\n\tint i;\r\n\tsceSdEffectAttr r_attr;\r\n\r\n\tDbg_MsgAssert( reverbType >= 0,( \"Bad reverb mode.\" ));\r\n\tDbg_MsgAssert( reverbType < NUM_REVERB_MODES,( \"Bad reverb mode...\" ));\r\n\t\r\n\tif ( !reverbLevel )\r\n\t{\r\n\t\tsTargetReverbDepth = 0;\r\n\t\tif ( instant )\r\n\t\t{\r\n\t\t\tReverbOff( );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Calling this in case it wasn't set before.  There is a bug with the SPU reg set code where some\r\n\t\t// messages are lost\r\n\t\tInitReverbAddr();\r\n\r\n\t\tsTargetReverbDepth = ( int )PERCENT( MAX_REVERB_DEPTH, reverbLevel );\r\n\t\t\r\n\t\t// --- set reverb attribute\r\n\t\tr_attr.depth_L  = 0x3fff;\r\n\t\tr_attr.depth_R  = 0x3fff;\r\n\t\tr_attr.delay    = 30;\r\n\t\tr_attr.feedback = 200;\r\n\t\tr_attr.mode = ReverbModes[ reverbType ];\r\n#if REVERB_ONLY_ON_CORE_0\r\n\t\ti = 0;\r\n#else\t\t\r\n\t\tfor( i = 0; i < 2; i++ )\r\n#endif\r\n\t\t{\r\n\t\t\tif( !CSpuManager::sSendSdRemote( rSdSetEffectAttr, i, (uint32) &r_attr ) )\r\n\t\t\t\tDbg_Message( \"Error setting reverb\\n\" );\r\n\t\r\n\t\t\tif(!CSpuManager::sSendSdRemote( rSdSetCoreAttr, i | SD_C_EFFECT_ENABLE, 1 ) )\r\n\t\t\t\tDbg_Message(\"Error setting reverb\\n\");\r\n\t\t\tif ( instant )\r\n\t\t\t{\r\n\t\t\t\tif(!CSpuManager::sSendSdRemote( rSdSetParam, i | SD_P_EVOLL , sTargetReverbDepth ) )\r\n\t\t\t\t\tDbg_Message(\"Error setting reverb2\\n\");\r\n\t\t\t\tif(!CSpuManager::sSendSdRemote( rSdSetParam, i | SD_P_EVOLR , sTargetReverbDepth ) )\r\n\t\t\t\t\tDbg_Message(\"Error setting reverb3\\n\");\r\n\t\t\t\tsCurrentReverbDepth = sTargetReverbDepth;\r\n\t\t\t}\r\n\r\n\t\t\tuint32 reverb_voices = (i == NUM_NO_REVERB_CORE) ? VOICES_MINUS_NON_REVERB : VOICES_MINUS_STREAMS;\r\n\t\t\tif(!CSpuManager::sSendSdRemote( rSdSetSwitch, i | SD_S_VMIXEL , reverb_voices ) )\r\n\t\t\t\tDbg_Message(\"Error setting reverb4\\n\");\r\n\t\t\tif(!CSpuManager::sSendSdRemote( rSdSetSwitch, i | SD_S_VMIXER , reverb_voices ) )\r\n\t\t\t\tDbg_Message(\"Error setting reverb5\\n\");\r\n\t\t\t\r\n\t\t}\r\n\t}\r\n} // end of SetReverb( )\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// Function    : void StopSound(int voiceNumber)\r\n// Description : turns off voice\r\n// Parameters  : voiceNumber - voice to stop\r\n//\r\n// Returns:\r\n// Notes: \r\n//-------------------------------------------------------------------------------------------\r\nvoid PS2Sfx_StopSound(int voiceNumber)\r\n{\r\n\t//Dbg_Message(\"Turning off voice number %d\", voiceNumber);\r\n\r\n\tint coreUsed;\r\n\r\n\tif ( voiceNumber >= NUM_VOICES_PER_CORE )\r\n\t{\r\n\t\tvoiceNumber -= NUM_VOICES_PER_CORE;\r\n\t\tcoreUsed = SD_CORE_1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcoreUsed = SD_CORE_0;\r\n\t}\r\n\r\n\tif ( !CSpuManager::sSendSdRemote( rSdSetSwitch, coreUsed | SD_S_KOFF , 1 << voiceNumber ) )\r\n\t\tDbg_MsgAssert( 0,( \"Failed to turn off\\n\" ));\r\n\r\n\t// turn off looping sound flag (if it's even on...)\r\n\t// Garrett: Took out this line so that we don't possibly turn off and on a voice in the same SPU tick.\r\n\t//LoopingSounds[ coreUsed ] &= ~( 1 << voiceNumber );\r\n//\tSoundsThatWereSwitchedOff[ coreUsed ] |= ( 1 << voiceNumber );\r\n\t// might not want this... can't write too often to a voice...\r\n\t// Garrett: Took out this line so that we don't possibly turn off and on a voice in the same SPU tick.\r\n\t// The only bad thing is this won't be cleared until the next frame.\r\n\t//VoicesUsed[ coreUsed ] &= ~( 1 << voiceNumber );\r\n\tVoicesCleared[ coreUsed ] |= 1 << voiceNumber;\r\n\treturn;\r\n}\r\n\r\nbool LoadSoundPlease( const char *sfxName, uint32 checksum, PlatformWaveInfo *pInfo, bool loadPerm )\r\n{\r\n\t\r\n\tDbg_MsgAssert( pInfo,( \"Null pointer to PlatformWaveInfo.\" ));\r\n\treturn PS2Sfx_LoadVAG( pInfo, sfxName, loadPerm, &pInfo->pitchAdjustmentForSamplingRate );\r\n} // end of LoadSoundPlease( )\r\n\r\nint\tGetCore( int voiceNumber )\r\n{\r\n\t\r\n\tif ( voiceNumber >= NUM_VOICES_PER_CORE )\r\n\t{\r\n\t\tvoiceNumber -= NUM_VOICES_PER_CORE;\r\n\t\tDbg_MsgAssert( voiceNumber < NUM_VOICES_PER_CORE,( \"Bad voice number.\" ));\r\n\t\treturn ( SD_CORE_1 );\r\n\t}\r\n\tDbg_MsgAssert( voiceNumber >= 0,( \"Bad voice number.\" ));\r\n\treturn ( SD_CORE_0 );\r\n\t\r\n} // end of GetCore( )\r\n\r\n//void SetVoiceParameters( int voiceNumber, float volL, float volR, float fPitch )\r\nvoid SetVoiceParameters( int voiceNumber, sVolume *p_vol, float fPitch )\r\n{\r\n\tint coreUsed = GetCore( voiceNumber );\r\n\r\n\tif ( coreUsed == SD_CORE_1 )\r\n\t{\r\n\t\tvoiceNumber -= NUM_VOICES_PER_CORE;\r\n\t}\r\n\tDbg_MsgAssert( voiceNumber < NUM_VOICES_PER_CORE,( \"What in tarnation?  Voice out of range.\" ));\r\n\r\n\t// adjust for SFX Volume level:\r\n\tp_vol->PercentageAdjustment( gSfxVolume );\r\n\r\n\tint lVol = (int)PERCENT( MAX_VOLUME, p_vol->GetChannelVolume( 0 ));\t\r\n\tint rVol = (int)PERCENT( MAX_VOLUME, p_vol->GetChannelVolume( 1 ));\t\r\n\r\n\tif ( lVol > MAX_VOLUME )\r\n\t\tlVol = MAX_VOLUME;\r\n\telse if ( lVol < -MAX_VOLUME )\r\n\t\tlVol = -MAX_VOLUME;\r\n\r\n\tif ( rVol > MAX_VOLUME )\r\n\t\trVol = MAX_VOLUME;\r\n\telse if ( rVol < -MAX_VOLUME )\r\n\t\trVol = -MAX_VOLUME;\r\n\r\n\tif ( fPitch )\r\n\t{\r\n\t\tint pitch = ( int )PERCENT( UNALTERED_PITCH, fPitch );\r\n\t\tif ( pitch > MAX_PITCH )\r\n\t\t\tpitch = MAX_PITCH;\r\n\t\tif ( pitch <= 0 )\r\n\t\t\tpitch = 1;\r\n\t\tif ( !CSpuManager::sSendSdRemote( rSdSetParam, coreUsed | ( voiceNumber << 1 ) | SD_VP_PITCH, pitch ) )\r\n\t\t\tDbg_Message(\"Failed pitch setting\\n\");\r\n\t}\r\n\r\n\t// for phasing effects (of sounds behind you), set the volume\r\n\t// to 0x7fff (left channel will be negative if sound is behind\r\n\t// us)\r\n\tif ( lVol < 0 )\r\n\t{\r\n\t\tlVol = 0x7fff + lVol;\r\n\t}\r\n\tif ( rVol < 0 )\t\t// Just in case we start phase shifting the right side instead\r\n\t{\r\n\t\trVol = 0x7fff + rVol;\r\n\t}\r\n\tif ( !CSpuManager::sSendSdRemote( rSdSetParam, coreUsed | ( voiceNumber << 1 ) | SD_VP_VOLL, lVol ) )\r\n\t\tDbg_Message( \"Error1\\n\" );\r\n\tif ( !CSpuManager::sSendSdRemote( rSdSetParam, coreUsed | ( voiceNumber << 1 ) | SD_VP_VOLR, rVol ) )\r\n\t\tDbg_Message(\"Error2\\n\");\r\n} // end of SetVoiceParameters( )\r\n\r\nint PlaySoundPlease( PlatformWaveInfo *pInfo, sVolume *p_vol, float pitch, bool no_reverb )\r\n{\r\n\t#if NO_SOUND\r\n\treturn ( -1 );\r\n\t#endif\r\n\r\n\tint voiceAvailableFlags;\r\n\tint i;\r\n\r\n\tif ( no_reverb )\r\n\t{\r\n\t\tvoiceAvailableFlags = PS2Sfx_GetVoiceStatus( NUM_NO_REVERB_CORE );\r\n\r\n\t\tfor ( i = NUM_NO_REVERB_START_VOICE; i < ( NUM_NO_REVERB_VOICES + NUM_NO_REVERB_START_VOICE ); i++ )\r\n\t\t{\r\n\t\t\tif ( voiceAvailableFlags & ( 1 << i ) )\r\n\t\t\t{\r\n\t\t\t\treturn ( PS2Sfx_PlaySound( pInfo, i + (NUM_NO_REVERB_CORE * NUM_VOICES_PER_CORE), p_vol->GetChannelVolume( 0 ), p_vol->GetChannelVolume( 1 ), pitch ));\r\n\t\t\t}\r\n\t\t}\r\n\r\n//\t\tDbg_MsgAssert(0, (\"Ran out of NO_REVERB voices\"));\r\n\t\tprintf(\"WARNING: Ran out of NO_REVERB voices - using reverb voices\\n\");\r\n\t}\r\n\r\n\tvoiceAvailableFlags = PS2Sfx_GetVoiceStatus( 0 );\r\n\tfor ( i = 0; i < NUM_VOICES_PER_CORE; i++ )\r\n\t{\r\n\t\tif ( voiceAvailableFlags & ( 1 << i ) )\r\n\t\t{\r\n\t\t\t//gAvailableVoices[ 0 ] &= ~( 1 << i );\r\n\t\t\treturn ( PS2Sfx_PlaySound( pInfo, i, p_vol->GetChannelVolume( 0 ), p_vol->GetChannelVolume( 1 ), pitch ));\r\n\t\t}\r\n\t}\r\n\t\r\n\t// 2nd core ( 1st core busy, all voices used )\r\n\t// For now, allow reverb sounds to use non-reverb voices.  They are at the end, anyway\r\n\tvoiceAvailableFlags = PS2Sfx_GetVoiceStatus( 1 );\r\n\tfor ( i = 0; i < NUM_VOICES_PER_CORE; i++ )\r\n\t{\r\n\t\tif ( voiceAvailableFlags & ( 1 << i ) )\r\n\t\t{\r\n\t\t\t//gAvailableVoices[ 1 ] &= ~( 1 << i );\r\n\t\t\treturn ( PS2Sfx_PlaySound( pInfo, i + NUM_VOICES_PER_CORE, p_vol->GetChannelVolume( 0 ), p_vol->GetChannelVolume( 1 ), pitch ));\r\n\t\t}\r\n\t}\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\tCSpuManager::sPrintStatus();\r\n#endif\r\n\tDbg_MsgAssert(0, (\"Can't play sound.  Out of voices\"));\r\n\treturn ( -1 );\r\n} // end of PlaySoundPlease( )\r\n\r\nvoid StopSoundPlease( int whichVoice )\r\n{\r\n\r\n\t\r\n\tif ( VoiceIsOn( whichVoice ) )\r\n\t{\r\n\t\tPS2Sfx_StopSound( whichVoice );\r\n\t}\r\n} // end of StopSoundPlease( )\r\n\r\nvoid PauseSoundsPlease( void )\r\n{\r\n\tsVolume silent_volume;\r\n\tsilent_volume.SetSilent();\r\n\r\n\t// just turn the volume down on all playing voices...\r\n\tfor( int i = 0; i < NUM_VOICES; i++ )\r\n\t{\r\n\t\tif( VoiceIsOn( i ))\r\n\t\t{\r\n\t\t\tSetVoiceParameters( i, &silent_volume );\r\n\t\t}\r\n\t}\r\n}// end of PauseSounds( )\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// Function    : void StopAllSoundFX(void)\r\n// Description : turns off all voices\r\n// Parameters  : \r\n//\r\n// Returns:\r\n// Notes: \r\n//-------------------------------------------------------------------------------------------\r\nvoid StopAllSoundFX( void )\r\n{\r\n\t\r\n\tint core;\r\n\tPcm::StopMusic( );\r\n\tPcm::StopStreams( );\r\n\tfor ( core = 0; core < NUM_CORES; core++ )\r\n\t{\r\n//\t\tSoundsThatWereSwitchedOff[ core ] = ( ( 1 << NUM_VOICES_PER_CORE ) - 1 );\r\n\t\tVoicesUsed[ core ] = 1;\t\t// So that the KOFF check thinks there are sounds to kill\r\n\t\tVoicesCleared[ core ] = 0;\r\n\t\tLoopingSounds[ core ] = 0;\r\n//\t\tDbg_Message( \"Stopping all sfx -- remind Matt to fix what this is going to do to streams!!!\" );\r\n\t\tCSpuManager::sClean();\r\n\t\tCSpuManager::sSendSdRemote( rSdSetSwitch, core | SD_S_KOFF, VOICES_MINUS_STREAMS );\r\n\t\tCSpuManager::sSendSdRemote( rSdSetSwitch, core | SD_S_ENDX, 0 );\r\n\t\tVoicesUsed[ core ] = 0;\r\n\t}\r\n\treturn;\r\n}\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// Function    : void PlaySound(int voiceNumber,int pitch,int volume)\r\n// Description : Plays voice\r\n// Parameters  : voiceNumber - voice to play\r\n//\t\t pitch - pitch to play at\r\n//\t\t volume - volume to play at\r\n//\r\n// Returns: voice number\r\n//-------------------------------------------------------------------------------------------\r\nint PS2Sfx_PlaySound( PlatformWaveInfo *pInfo, int voiceNumber, float volL, float volR, float pitch )\r\n{\r\n\t\r\n\tint coreUsed = GetCore( voiceNumber );\r\n\tint voiceNumOnCore;\r\n\r\n\tif ( coreUsed == SD_CORE_1 )\r\n\t{\r\n\t\tvoiceNumOnCore = voiceNumber - NUM_VOICES_PER_CORE;\r\n\t}\r\n\telse\r\n\t\tvoiceNumOnCore = voiceNumber;\r\n\r\n\tif ( !CSpuManager::sSendSdRemote( rSdSetAddr, coreUsed | ( voiceNumOnCore << 1 ) | SD_VA_SSA, pInfo->vagAddress ) )\r\n\t\tDbg_Message( \"Error4\\n\" );\r\n\t\r\n\t// adjust pitch to account for lower sampling rates:\r\n\tpitch = PERCENT( pitch, pInfo->pitchAdjustmentForSamplingRate );\r\n\t\r\n\t// should be voiceNumber, not voiceNumOnCore:\r\n\tsVolume vol;\r\n\tvol.SetChannelVolume( 0, volL );\r\n\tvol.SetChannelVolume( 1, volR );\r\n\tSetVoiceParameters( voiceNumber, &vol, pitch );\r\n\t\r\n\tif ( !CSpuManager::sSendSdRemote( rSdSetSwitch, coreUsed | SD_S_KON, 0x1 << voiceNumOnCore ) )\r\n\t\tDbg_Message(\"Failed setswitch\\n\");\r\n\t\r\n\tif ( pInfo->looping )\r\n\t{\r\n\t\tLoopingSounds[ coreUsed ] |= ( 1 << voiceNumOnCore );\r\n\t\t//Dbg_Message(\"Setting looping sound on voice %d core %d\", voiceNumOnCore, coreUsed);\r\n\t\t//Dbg_Assert(0);\r\n\t}\r\n\r\n\t// Set the VoicesUsed flag.\r\n\tVoicesUsed[ coreUsed ] |= 1 << voiceNumOnCore;\r\n//\tprintf( \"voice %d\\n\", voiceNumber );\r\n\t//Dbg_Message(\"Voices Used (%x %x) Cleared (%x %x) Looped (%x %x) Voice Status (%x %x)\", VoicesUsed[0], VoicesUsed[1], VoicesCleared[0], VoicesCleared[1],\r\n\t//\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  LoopingSounds[0], LoopingSounds[1], CSpuManager::sGetVoiceStatus(0), CSpuManager::sGetVoiceStatus(1));\r\n\r\n\treturn ( voiceNumber );\r\n} // end of PS2Sfx_PlaySound( )\r\n\r\nvoid CleanUpSoundFX( void )\r\n{\r\n\t\r\n\tStopAllSoundFX( );\r\n\tSpuRAMUsedTemp = 0;\r\n\tSetReverbPlease( 0 );\r\n}// end of CleanUpSoundFX( )\r\n\r\n#define NUM_VOICES_INCLUDING_STREAMS_PER_CORE 24\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// Function    : void InitSound( void )\r\n// Description : initialise sound system\r\n// Parameters  : \r\n//\t\r\n// Returns:\r\n// Notes: \r\n//--------------------------------------------------------------------------------------------\r\nvoid InitSoundFX( CSfxManager *p_sfx_manager )\r\n{\r\n\t// Set default volume type.\r\n\tif( p_sfx_manager )\r\n\t{\r\n\t\tp_sfx_manager->SetDefaultVolumeType( VOLUME_TYPE_2_CHANNEL_DOLBYII );\r\n\t}\r\n\t\r\n\tint i, j;\r\n\t// set master volume for both cores, both blocking\r\n\tfor ( i = 0; i < 2; i++ )\r\n\t{\r\n\t\t\r\n\t\tif ( !CSpuManager::sSendSdRemote( rSdSetParam, i | SD_P_MVOLL, MAX_VOLUME ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"Error Setting Left Vol on core %d\\n\",i));\r\n\t\t}\r\n\t\tif ( !CSpuManager::sSendSdRemote( rSdSetParam, i | SD_P_MVOLR, MAX_VOLUME ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"Error Setting Right Vol on core %d\\n\",i));\r\n\t\t}\r\n\t}\r\n\t\r\n//\tSetVolumePlease( 100 );\r\n\t\r\n\t// Sets the reverb address registers\r\n\tInitReverbAddr();\r\n\t\t\t\r\n\tCleanUpSoundFX( );\r\n\r\n\t// Set the envelope info at the end because we sometimes lose messages\r\n\tfor ( i = 0; i < 2; i++ )\r\n\t{\r\n\t\tfor ( j = 0; j < NUM_VOICES_INCLUDING_STREAMS_PER_CORE; j++ )\r\n\t\t{\r\n\t\t\tCSpuManager::sSendSdRemote ( rSdSetParam, i | ( j << 1 ) | SD_VP_ADSR1, 0x00ff );\r\n\t\t\tCSpuManager::sSendSdRemote ( rSdSetParam, i | ( j << 1 ) | SD_VP_ADSR2, 0x1fc0 );\r\n\t\t}\r\n\t}\r\n\r\n\treturn;\r\n}\r\n\r\nvoid PS2Sfx_InitCold( void )\r\n{\r\n\t\r\n\r\n\tCSpuManager::sInit();\r\n\r\n//\tint i;\r\n//\tfor ( i = 0; i < NUM_CORES; i++ )\r\n//\t{\r\n//\t\tgLastVoiceAvailableUpdate[ i ] = 0;\r\n//\t\tgAvailableVoices[ i ] = 0;\r\n//\t}\r\n\r\n} // end of PS2Sfx_Init( )\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// Function    : int GetVoiceStatus( int core )\r\n// Description : returns bitmask showing which voices are available\r\n// Parameters  : core - SPU core\r\n//\t\r\n// Returns     : integer value which is the bitmask for voices\r\n//--------------------------------------------------------------------------------------------\r\nint PS2Sfx_GetVoiceStatus( int core )\r\n{\r\n\t\r\n#if 1\r\n\tint availableVoices = CSpuManager::sGetVoiceStatus(core);\r\n#else\r\n\tint availableVoices;\r\n\r\n\tif ( gLastVoiceAvailableUpdate[ core ] != Tmr::GetRenderFrame( ) )\r\n\t{\r\n\t\tgLastVoiceAvailableUpdate[ core ] = Tmr::GetRenderFrame( );\r\n\t\tCSpuManager::sWaitForIO();\r\n\t\tgAvailableVoices[ core ] = sceSdRemote( 1, rSdGetSwitch, core | SD_S_ENDX );\r\n\t}\r\n\t// available voices at this point will show all voices that have reached the end...\r\n\tavailableVoices = gAvailableVoices[ core ];\r\n#endif\r\n\r\n\t// except we've got to remove looping sounds (they set the ENDX flag first time they reach LOOPEND)\r\n\tavailableVoices &= ~LoopingSounds[ core ];\r\n\t// include the voices that have not ever been used yet (if never used,\r\n\t// a voice never has had a chance to set the ENDX register...)\r\n\tavailableVoices |= ~VoicesUsed[ core ];\r\n\t\r\n\treturn ( availableVoices );\r\n}\r\n\r\nbool VoiceIsOn( int whichVoice )\r\n{\r\n\t\r\n\tint whichCore;\r\n\tint voiceAvailableFlags;\r\n\t\t\r\n\tif ( whichVoice < NUM_VOICES_PER_CORE )\r\n\t{\r\n\t\twhichCore = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\twhichCore = 1;\r\n\t\twhichVoice -= NUM_VOICES_PER_CORE;\r\n\t}\r\n\t\r\n\tvoiceAvailableFlags = PS2Sfx_GetVoiceStatus( whichCore );\r\n\treturn ( ( voiceAvailableFlags & ( 1 << whichVoice ) ) ? false : true );\r\n} // end of\tVoiceIsOn( )\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PerFrameUpdate( void )\r\n{\r\n\t\r\n\tDoReverbFade( );\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////////\r\n/// CSpuManager\r\n\r\nvolatile bool\t\t\t\t\tCSpuManager::s_sd_remote_busy;\r\nvolatile bool\t\t\t\t\tCSpuManager::s_sd_transferring_voice;\r\nvolatile uint32\t\t\t\t\tCSpuManager::s_sd_voice_status[NUM_CORES];\r\nvolatile uint32\t\t\t\t\tCSpuManager::s_sd_voice_status_update_frame[NUM_CORES] = { 0, 0 };\r\n\r\nuint32\t\t\t\t\t\t\tCSpuManager::s_spu_reg_kon[NUM_CORES] = { 0, 0 };\r\nuint32\t\t\t\t\t\t\tCSpuManager::s_spu_reg_koff[NUM_CORES] = { 0, 0 };\r\n\r\nSSifCmdSoundRequestPacket\t\tCSpuManager::s_sd_remote_commands[CSpuManager::MAX_QUEUED_COMMANDS] __attribute__ ((aligned(16)));\r\nvolatile int\t\t\t\t\tCSpuManager::s_sd_remote_command_free_index;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCSpuManager::sInit()\r\n{\r\n\t// Init variables\r\n\ts_sd_remote_busy = false;\r\n\ts_sd_remote_command_free_index = 0;\r\n\r\n\tif ( sceSdRemoteInit( ) == -1 )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Error Initialising sound\\n\"));\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Initialise IOP side, blocking call\r\n\tif ( sceSdRemote( 1, rSdInit, SD_INIT_COLD ) == -1 )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Error Initialising IOP\\n\"));\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Make sure the DMA ID's are 0 so we don't wait for random ID's\r\n\tfor (int i = 0; i < MAX_QUEUED_COMMANDS; i++)\r\n\t{\r\n\t\ts_sd_remote_commands[i].m_request.m_ee_dma_id = 0;\r\n\t}\r\n\r\n\tsceSifAddCmdHandler(SOUND_RESULT_COMMAND, s_result_callback, NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCSpuManager::sClean()\r\n{\r\n\tfor (int core = 0; core < NUM_CORES; core++)\r\n\t{\r\n\t\ts_spu_reg_kon[core] = 0;\r\n\t\ts_spu_reg_koff[core] = 0;\r\n\t\ts_sd_voice_status[core] = 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\nvoid\t\t\tCSpuManager::sPrintStatus()\r\n{\r\n\tfor (int core = 0; core < NUM_CORES; core++)\r\n\t{\r\n\t\tDbg_Message(\"Core %d: Voices Used (%x) Cleared (%x) Looped (%x) Voice Status (%x)\", core, VoicesUsed[core], VoicesCleared[core],\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  LoopingSounds[core], sGetVoiceStatus(core));\r\n\t\tDbg_Message(\"        Saved KON value (%x) Saved KOFF value (%x)\", s_spu_reg_kon[core], s_spu_reg_koff[core]);\r\n\t}\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCSpuManager::sWaitForIO()\r\n{\r\n\twhile (s_sd_remote_busy)\r\n\t\t;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCSpuManager::sUpdateStatus()\r\n{\r\n\t//scePrintf(\"******** Doing CSpuManager::sUpdateStatus() on frame %d\\n\", Tmr::GetRenderFrame( ));\r\n\tfor (int core = 0; core < NUM_CORES; core++)\r\n\t{\r\n\t\tsSendSdRemote( rSdGetSwitch, core | SD_S_ENDX, 0 );\r\n\r\n\t\t// Clear out switches\r\n\t\t//s_spu_reg_kon[core] = 0;\r\n\t\t//s_spu_reg_koff[core] = 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\t\t\tCSpuManager::sGetVoiceStatus(int core)\r\n{\r\n\t// For now, just go into a wait loop.  In the future, we can probably use the old value\r\n\twhile (s_sd_voice_status_update_frame[core] != Tmr::GetRenderFrame( ))\r\n\t\t;\r\n\r\n\tif (s_sd_voice_status_update_frame[core] != Tmr::GetRenderFrame( ))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Sound voice status not current: need frame %d but have frame %d\", Tmr::GetRenderFrame( ), s_sd_voice_status_update_frame[core]));\r\n\t}\r\n\r\n\treturn s_sd_voice_status[core];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCSpuManager::sSendSdRemote(uint16 function, uint16 entry, uint32 value)\r\n{\r\n\treturn s_queue_new_command(function, entry, value);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCSpuManager::sVoiceTrans(uint16 channel, uint16 mode, void *p_iop_addr, uint32 *p_spu_addr, uint32 size)\r\n{\r\n\tDbg_Assert(!s_sd_transferring_voice);\r\n\r\n#if 0\r\n\tsceSdRemote(1, rSdVoiceTrans, channel, mode, p_iop_addr, p_spu_addr, size);\r\n\tsceSdRemote(1, rSdVoiceTransStatus, channel, SD_TRANS_STATUS_WAIT);\r\n#else\r\n\ts_sd_transferring_voice = true;\r\n\r\n\t// Send transfer command first\r\n\tif (!s_queue_new_command(rSdVoiceTrans, channel, mode, (uint32) p_iop_addr, (uint32) p_spu_addr, size))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (!s_queue_new_command(rSdVoiceTransStatus, channel, SD_TRANS_STATUS_WAIT))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\ts_wait_for_voice_transfer();\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCSpuManager::s_queue_new_command(uint16 function, uint16 entry, uint32 value, uint32 arg0, uint32 arg1, uint32 arg2)\r\n{\r\n\tstatic int s_num_sound_requests_sent = 0;\r\n\r\n\tif (function == rSdSetSwitch)\r\n\t{\r\n#if 0\r\n\t\t// If we are sending a switch, combine with old settings to make sure we don't overwrite them.\r\n\t\t// Switches are only updated every 1/48000 a second on the SPU.\r\n\t\tvalue = s_get_switch_value(entry, value);\r\n#endif\r\n\t\ts_update_local_status(entry, value);\r\n\t}\r\n\r\n\tint nextFreeIndex = (s_sd_remote_command_free_index + 1) % MAX_QUEUED_COMMANDS;\r\n\tSSifCmdSoundRequestPacket *p_command = &s_sd_remote_commands[s_sd_remote_command_free_index];\r\n\r\n\t// Wait for old send to complete\r\n\tif (p_command->m_request.m_ee_dma_id)\r\n\t{\r\n\t\t//Dbg_Assert(0);\r\n\t\tint wait_num = 0;\r\n\t\twhile(sceSifDmaStat(p_command->m_request.m_ee_dma_id) >= 0)\r\n\t\t{\r\n\t\t\tif ((wait_num++ % 1000) == 0)\r\n\t\t\t\tscePrintf(\"Waiting for sound request buffer\\n\");\r\n\t\t}\r\n\t}\r\n\r\n\tif (function == rSdSetEffectAttr)\r\n\t{\r\n\t\tsceSdEffectAttr *p_attr = (sceSdEffectAttr *) value;\r\n\r\n\t\tp_command->m_request.m_function\t= function;\r\n\t\tp_command->m_request.m_entry\t\t= entry;\r\n\t\tp_command->m_request.m_value\t\t= p_attr->mode;\r\n\t\tp_command->m_request.m_arg_0\t\t= ((uint32) p_attr->depth_L << 16) | (uint32) p_attr->depth_R;\r\n\t\tp_command->m_request.m_arg_1\t\t= p_attr->delay;\r\n\t\tp_command->m_request.m_arg_2\t\t= p_attr->feedback;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_command->m_request.m_function\t= function;\r\n\t\tp_command->m_request.m_entry\t\t= entry;\r\n\t\tp_command->m_request.m_value\t\t= value;\r\n\t\tp_command->m_request.m_arg_0\t\t= arg0;\r\n\t\tp_command->m_request.m_arg_1\t\t= arg1;\r\n\t\tp_command->m_request.m_arg_2\t\t= arg2;\r\n\t}\r\n\tp_command->m_request.m_pad[0] = ++s_num_sound_requests_sent;\r\n\r\n\t// Send the actual command\r\n\t//scePrintf(\"CSpuManager: sending command %x with entry %x and value %x\\n\", function, entry, value);\r\n\tp_command->m_request.m_ee_dma_id = sceSifSendCmd(SOUND_REQUEST_COMMAND, p_command, sizeof(*p_command), 0, 0, 0);\r\n\r\n\ts_sd_remote_command_free_index = nextFreeIndex;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\t\t\tCSpuManager::s_get_switch_value(uint16 entry, uint32 value)\r\n{\r\n\tint core = entry & 0x1;\r\n\tint switch_reg = entry & 0xFF00;\r\n\r\n\tuint32 new_value = value;\r\n\r\n\tswitch (switch_reg)\r\n\t{\r\n\tcase SD_S_KON:\r\n\t\tif(s_spu_reg_koff[core] & value)\r\n\t\t{\r\n\t\t\t//Dbg_MsgAssert(0, (\"Turning on a voice that was turned off this frame.\"));\r\n\t\t\tDbg_Message(\"Turning on a voice that was turned off this frame.\");\r\n\t\t\ts_spu_reg_koff[core] &= ~(s_spu_reg_koff[core] & value);\t// turn off those bits\r\n\t\t}\r\n\r\n\t\ts_spu_reg_kon[core] |= value;\r\n\t\tnew_value = s_spu_reg_kon[core];\r\n\r\n\t\tbreak;\r\n\r\n\tcase SD_S_KOFF:\r\n\t\tif(s_spu_reg_kon[core] & value)\r\n\t\t{\r\n\t\t\t//Dbg_MsgAssert(0, (\"Turning off a voice that was turned on this frame.\"));\r\n\t\t\tDbg_Message(\"Turning off a voice that was turned on this frame.\");\r\n\t\t\ts_spu_reg_kon[core] &= ~(s_spu_reg_kon[core] & value);\t\t// turn off those bits\r\n\t\t}\r\n\r\n\t\ts_spu_reg_koff[core] |= value;\r\n\t\tnew_value = s_spu_reg_koff[core];\r\n\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\treturn new_value;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCSpuManager::s_update_local_status(uint16 entry, uint32 value)\r\n{\r\n\tint core = entry & 0x1;\r\n\tint switch_reg = entry & 0xFF00;\r\n\r\n\tswitch (switch_reg)\r\n\t{\r\n\tcase SD_S_KON:\r\n\t\t//Dbg_Message(\"************ ORing KON%d with %x\", core, value); \r\n\t\tif(s_spu_reg_koff[core] & value)\r\n\t\t{\r\n#ifdef\t__NOPT_ASSERT__\r\n\t\t\tsPrintStatus();\r\n#endif\r\n\t\t\tDbg_Message(\"Core %d: Set KON value (%x)\", core, value);\r\n\t\t\tDbg_MsgAssert(0, (\"Turning on a voice that was turned off this frame.\"));\r\n\t\t\tDbg_Message(\"Turning on a voice that was turned off this frame.\");\r\n\t\t\ts_spu_reg_koff[core] &= ~(s_spu_reg_koff[core] & value);\t// turn off those bits\r\n\t\t}\r\n\r\n\t\ts_spu_reg_kon[core] |= value;\r\n\r\n\t\t// Make sure the voice is not used again before SPU update is done\r\n\t\ts_sd_voice_status[core] &= ~value;\r\n\t\tbreak;\r\n\r\n\tcase SD_S_KOFF:\r\n\t\t//Dbg_Message(\"************ ORing KOFF%d with %x\", core, value); \r\n\t\tif(!(value & ~PS2Sfx_GetVoiceStatus(core)))\r\n\t\t{\r\n#ifdef\t__NOPT_ASSERT__\r\n\t\t\tsPrintStatus();\r\n#endif\r\n\t\t\tDbg_MsgAssert(0, (\"Can't set KOFF with %x: status %x raw status %x\", value, sGetVoiceStatus(core), s_sd_voice_status[core]));\r\n\t\t\tDbg_Message(\"Can't set KOFF with %x: status %x raw status %x\", value, sGetVoiceStatus(core), s_sd_voice_status[core]);\r\n\t\t}\r\n\t\tif(s_spu_reg_kon[core] & value)\r\n\t\t{\r\n#ifdef\t__NOPT_ASSERT__\r\n\t\t\t//sPrintStatus();\r\n#endif\r\n\t\t\t//Dbg_Message(\"Core %d: Set KOFF value (%x)\", core, value);\r\n\t\t\t//Dbg_MsgAssert(0, (\"Turning off a voice that was turned on this frame.\"));\r\n\t\t\tDbg_Message(\"Turning off a voice that was turned on this frame.\");\r\n\t\t\ts_spu_reg_kon[core] &= ~(s_spu_reg_kon[core] & value);\t\t// turn off those bits\r\n\t\t}\r\n\r\n\t\ts_spu_reg_koff[core] |= value;\r\n\r\n\t\t// Lets not clear the voice now.  Wait until we get the SPU status break;\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCSpuManager::s_result_callback(void *p, void *q)\r\n{\r\n\tSSifCmdSoundResultPacket *p_result = (SSifCmdSoundResultPacket *) p;\r\n\r\n\tif (p_result->m_function == rSdVoiceTransStatus)\r\n\t{\r\n\t\ts_sd_transferring_voice = false;\r\n\t}\r\n\telse if (p_result->m_function == rSdGetSwitch)\r\n\t{\r\n\t\tint core = p_result->m_entry & 0x1;\r\n\r\n\t\t//scePrintf(\"************ CSpuManager: received result from command %x with entry %x and result %x for core %d\\n\", p_result->m_function, p_result->m_entry, p_result->m_result, core);\r\n\r\n\t\tif ((p_result->m_entry & 0xFF00) == SD_S_ENDX)\r\n\t\t{\r\n\t\t\ts_sd_voice_status[core] = p_result->m_result;\r\n\t\t\ts_sd_voice_status_update_frame[core] = Tmr::GetRenderFrame( );\r\n\r\n\t\t\t// We can clear this out now since the status is up-to-date\r\n\t\t\tVoicesUsed[ core ] &= ~VoicesCleared[ core ];\r\n\t\t\t//if (LoopingSounds[ core ] & VoicesCleared[ core ])\r\n\t\t//\t{\r\n\t\t//\t\tscePrintf(\"Clearing looping sound voices %x on core %d\\n\", LoopingSounds[ core ] & VoicesCleared[ core ], core);\r\n\t\t//\t}\r\n\t\t\tLoopingSounds[ core ] &= ~VoicesCleared[ core ];\r\n\t\t\tVoicesCleared[ core ] = 0;\r\n\r\n\t\t\t// Keep bits that haven't been updated yet\r\n\t\t\ts_spu_reg_kon[core] &= (s_sd_voice_status[core] | ~VoicesUsed[core]);\r\n\t\t\ts_spu_reg_koff[core] &= ~(s_sd_voice_status[core] | ~VoicesUsed[core]);\r\n\r\n\t\t\t// And remove any leftover KON voices\r\n\t\t\ts_sd_voice_status[core] &= ~s_spu_reg_kon[core];\r\n\t\t}\r\n\t}\r\n\r\n\tif (p_result->m_panic)\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Error on IOP module while processing SPU request %x\", p_result->m_function));\r\n\t}\r\n\r\n\tExitHandler();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCSpuManager::s_wait_for_voice_transfer()\r\n{\r\n\twhile (s_sd_transferring_voice)\r\n\t\t;\r\n}\r\n\r\n} // namespace Sfx\r\n"
  },
  {
    "path": "Code/Gel/SoundFX/NGPS/p_sfx.h",
    "content": "/*\tPlaystation 2 sound support functions.\r\n\tmjd\tjan 10, 2001\r\n*/\r\n#ifndef __MODULES_P_SFX_H\r\n#define __MODULES_P_SFX_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <gel/music/ngps/pcm/pcm.h>\r\n\r\nnamespace Sfx\r\n{\r\n\r\nstruct sVolume;\r\nclass CSfxManager;\r\n\r\n\t\t  \r\n#if NUM_STREAMS > 2\r\n#define NUM_VOICES_PER_CORE\t\t(24 - NUM_STREAMS)  // leave #stream voices per core for streaming audio off the CD and shit...\r\n#else\r\n#define NUM_VOICES_PER_CORE\t\t22  // leave 2 voices per core for streaming audio off the CD and shit...\r\n#endif\r\n\r\n#define NUM_CORES\t\t\t\t2\r\n#define NUM_VOICES\t\t\t\t( NUM_VOICES_PER_CORE * NUM_CORES )\r\n\r\n// Non-reverb voices.  Make sure they are always the last voices on the last core, since we presently allow\r\n// reverb sounds to use all voices.\r\n#define NUM_NO_REVERB_VOICES\t\t10\r\n#define NUM_NO_REVERB_CORE\t\t\tMUSIC_CORE\r\n#define NUM_NO_REVERB_START_VOICE\t( NUM_VOICES_PER_CORE - NUM_NO_REVERB_VOICES )\r\n\r\n// platform specific info needed per wave (stored in the WaveTable):\r\nstruct PlatformWaveInfo{\r\n\tint\t\tvagAddress; //PS2 waves played by setting a voice to the address of the wave on the sound chip...\t\r\n\tbool\tlooping;\r\n\tfloat\tpitchAdjustmentForSamplingRate; // figure out how much to alter the pitch due to lower sampling rates than 48000.\r\n};\r\n\r\n// on startup of the game only...\r\nvoid PS2Sfx_InitCold( void );\r\n\r\nvoid\tInitSoundFX( CSfxManager *p_sfx_manager );\r\nvoid\tCleanUpSoundFX( void );\r\nvoid\tStopAllSoundFX( void );\r\nbool\tLoadSoundPlease( const char *sfxName, uint32 checksum, PlatformWaveInfo *pInfo, bool loadPerm = 0 );\r\n\r\nint\t\tGetMemAvailable( void );\r\n\r\n// returns 0 - ( NUM_VOICES - 1 ), or -1 if no voices are free...\r\nint\t\tPlaySoundPlease( PlatformWaveInfo *pInfo, sVolume *p_vol, float pitch = 100.0f, bool no_reverb = false );\r\n\r\nvoid\tStopSoundPlease( int whichVoice );\r\n\r\n// really just turning down the volume on all playing voices...\r\n// Looping sounds will get the volume adjusted by the owner\r\n// during the next logic loop.\r\n// The non-looping sounds will play (with no volume) then stop.\r\n// This is for when we go into the menus or whatnot...\r\nvoid\tPauseSoundsPlease( void );\r\n\r\n// see reverb types in ReverbModes table (p_sfx.cpp), corresponding to reverb.q script file\r\nvoid\tSetReverbPlease( float reverbLevel = 0.0f, int reverbMode = 0, bool instant = false );\r\n\r\n// volume from -100 to 100 ( negative if the sound is from behind us. ps2 alters the sound... )\r\nvoid\tSetVolumePlease( float volumeLevel );\r\n\r\n// returns true if voice is being used currently.\r\nbool\tVoiceIsOn( int whichVoice );\r\n\r\n// change parameters on an active voice:\r\n// if pitch parameter is zero, pitch won't be changed (lowest pitch is 1)\r\nvoid\tSetVoiceParameters( int whichVoice, sVolume *p_vol, float pitch = 0.0f );\r\n\r\nvoid\tPerFrameUpdate( void );\r\n\r\n\r\n///////////////////////////////////////////////////////////\r\n// SPU Manager class\r\n// All the SPU communication should go through here instead of sceSdRemote().\r\n// It is asynchronous, so it doesn't stall the EE while waiting for the\r\n// IOP (which can be milliseconds!)\r\nclass CSpuManager\r\n{\r\npublic:\r\n\tstatic void\t\t\t\tsInit();\r\n\tstatic void\t\t\t\tsUpdateStatus();\t\t\t\t// Called at the beginning of every frame to get the voice status\r\n\r\n\tstatic uint32\t\t\tsGetVoiceStatus(int core);\t\t// Gets the already requested status\r\n\tstatic void\t\t\t\tsFlush();\r\n\tstatic volatile bool\tsIsBusy();\r\n\tstatic void\t\t\t\tsWaitForIO();\r\n\r\n\tstatic void\t\t\t\tsClean();\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\tstatic void\t\t\t\tsPrintStatus();\r\n#endif\r\n\r\n\t// Transfer functions\r\n\tstatic bool\t\t\t\tsSendSdRemote(uint16 function, uint16 entry, uint32 value);\r\n\tstatic bool\t\t\t\tsVoiceTrans(uint16 channel, uint16 mode, void *p_iop_addr, uint32 *p_spu_addr, uint32 size);\r\n\r\nprivate:\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tMAX_QUEUED_COMMANDS\t= 28,\r\n\t};\r\n\r\n\tstatic void\t\t\t\ts_result_callback(void *p, void *q);\t// SifCmd callback\r\n\r\n\tstatic bool\t\t\t\ts_queue_new_command(uint16 function, uint16 entry, uint32 value, uint32 arg0 = 0, uint32 arg1 = 0, uint32 arg2 = 0);\r\n\tstatic uint32\t\t\ts_get_switch_value(uint16 entry, uint32 value);\r\n\tstatic void\t\t\t\ts_update_local_status(uint16 entry, uint32 value);\r\n\r\n\tstatic void\t\t\t\ts_wait_for_voice_transfer();\r\n\r\n\t// Variables\r\n\tstatic volatile bool\ts_sd_remote_busy;\r\n\tstatic volatile bool\ts_sd_transferring_voice;\r\n\tstatic volatile uint32\ts_sd_voice_status[NUM_CORES];\r\n\tstatic volatile uint32\ts_sd_voice_status_update_frame[NUM_CORES];\r\n\r\n\t// Switch settings made in frame.  Because the SPU only reads registers every 1/48000 of a sec, we may have\r\n\t// to re-send a switch setting so we don't overwrite an old one.\r\n\tstatic uint32\t\t\ts_spu_reg_kon[NUM_CORES];\r\n\tstatic uint32\t\t\ts_spu_reg_koff[NUM_CORES];\r\n\r\n\t// Store multiple request packets, so we don't have to wait for the last DMA to finish before\r\n\t// starting a new one.\r\n\tstatic SSifCmdSoundRequestPacket\ts_sd_remote_commands[MAX_QUEUED_COMMANDS] __attribute__ ((aligned(16)));\r\n\tstatic volatile int\t\t\t\t\ts_sd_remote_command_free_index;\r\n};\r\n\r\n\r\n} // namespace Gel\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/SoundFX/Xbox/p_sfx.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSound effects (Sfx)\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\txbox/p_sfx.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t01/10/01\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXBox Sound effects\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n#include <dsound.h>\r\n//#include <dsstdfx.h>\r\n\r\n#include <core/macros.h>\r\n#include <sys/file/filesys.h>\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/soundfx/xbox/p_sfx.h>\r\n#include <gel/soundfx/xbox/skate5fx.h>\r\n#include <gel/music/music.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint num_buffers = 0;\r\n\r\nnamespace Sfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define RIFFCHUNK_FLAGS_VALID   0x00000001\r\n\r\n// FourCC definitions\r\nconst DWORD FOURCC_RIFF\t\t= 'FFIR';\r\nconst DWORD FOURCC_WAVE\t\t= 'EVAW';\r\nconst DWORD FOURCC_FORMAT\t= ' tmf';\r\nconst DWORD FOURCC_DATA\t\t= 'atad';\r\nconst DWORD FOURCC_SAMPLER\t= 'lpms';\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstruct VoiceEntry\r\n{\r\n\tIDirectSoundBuffer*\tp_buffer;\r\n\tDWORD\t\t\t\tdefault_frequency;\r\n};\r\n\r\ntypedef struct\r\n{\r\n    WCHAR *         szName;\r\n    DSI3DL2LISTENER ds3dl;\r\n} I3DL2ENVIRONMENT;\r\n\r\n/*****************************************************************************\r\n *\r\n * Name: RIFFHEADER\r\n * Desc: For parsing WAV files\r\n *\r\n ****************************************************************************/\r\nstruct RIFFHEADER\r\n{\r\n\tFOURCC  fccChunkId;\r\n\tDWORD   dwDataSize;\r\n};\r\n\r\n\r\nstruct SAMPLERCHUNK\r\n{\r\n\tDWORD\tmanufacturer;\r\n\tDWORD\tproduct;\r\n\tDWORD\tsample_period;\r\n\tDWORD\tMIDI_unity_note;\r\n\tDWORD\tMIDI_pitch_fraction;\r\n\tDWORD\tSMPTE_format;\r\n\tDWORD\tSMPTE_offset;\r\n\tDWORD\tnum_sample_loops;\r\n\tDWORD\tsampler_data;\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n *\r\n * Name: class CRiffChunk\r\n * Desc: RIFF chunk utility class\r\n *\r\n ****************************************************************************/\r\nclass CRiffChunk\r\n{\r\n\tFOURCC\t\t\t\tm_fccChunkId;       // Chunk identifier\r\n\tconst CRiffChunk*\tm_pParentChunk;     // Parent chunk\r\n\tvoid*\t\t\t\tm_hFile;\r\n\tDWORD\t\t\t\tm_dwDataOffset;     // Chunk data offset\r\n\tDWORD\t\t\t\tm_dwDataSize;       // Chunk data size\r\n\tDWORD\t\t\t\tm_dwFlags;          // Chunk flags\r\n\r\n\tpublic:\r\n\r\n    CRiffChunk();\r\n\r\n    // Initialization.\r\n    void\tInitialize( FOURCC fccChunkId, const CRiffChunk* pParentChunk, void* hFile );\r\n\tbool\tOpen();\r\n    bool    IsValid( void )\t\t{ return !!( m_dwFlags & RIFFCHUNK_FLAGS_VALID ); }\r\n\r\n    // Data\r\n    bool\tReadData( LONG lOffset, VOID* pData, DWORD dwDataSize );\r\n\r\n    // Chunk information\r\n    FOURCC  GetChunkId()  { return m_fccChunkId; }\r\n    DWORD   GetDataSize() { return m_dwDataSize; }\r\n};\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n *\r\n * Name: class CWaveFile\r\n * Desc: Wave file utility class\r\n *\r\n ****************************************************************************/\r\nclass CWaveFile\r\n{\r\n\tvoid*\t\tm_hFile;            // File handle\r\n\tCRiffChunk\tm_RiffChunk;        // RIFF chunk\r\n\tCRiffChunk  m_FormatChunk;      // Format chunk\r\n\tCRiffChunk  m_DataChunk;        // Data chunk\r\n\tCRiffChunk  m_SamplerChunk;\t\t// Sampler chunk, may or may not be present\r\n    \r\n\tbool\t\tm_ContainsSamplerChunk;\r\n\r\n\tpublic:\r\n\r\n    CWaveFile( void );\r\n    ~CWaveFile( void );\r\n\r\n    // Initialization\r\n    bool\tOpen( const char* strFileName );\r\n    void    Close( void );\r\n\r\n    // File format\r\n    bool\tGetFormat( WAVEFORMATEX* pwfxFormat, DWORD dwFormatSize );\r\n\r\n    // File data\r\n    bool\tReadSample( DWORD dwPosition, VOID* pBuffer, DWORD dwBufferSize, DWORD* pdwRead );\r\n\r\n    // File properties\r\n    void    GetDuration( DWORD* pdwDuration ) { *pdwDuration = m_DataChunk.GetDataSize(); }\r\n\r\n\tbool\tContainsLoop( void );\r\n};\r\n\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n *\r\n * Name: class CSound\r\n * Desc: Encapsulates functionality of a DirectSound buffer.\r\n *\r\n ****************************************************************************/\r\nclass CXBSound\r\n{\r\n\tpublic:\r\n\tXBOXADPCMWAVEFORMAT\t\tm_WaveFormat;\t\t// This encapsulates WAVEFORMATEX.\r\n    DSBUFFERDESC\t\t\tm_dsbd;\r\n    DWORD\t\t\t\t\tm_dwBufferSize;\r\n\tvoid*\t\t\t\t\tm_pRawData;\r\n\tbool\t\t\t\t\tm_Loops;\r\n\r\n    bool\tCreate( const CHAR* strFileName, DWORD dwFlags = 0L );\r\n    bool\tCreate( const XBOXADPCMWAVEFORMAT* pwfxFormat, DWORD dwFlags, VOID* pBuffer, DWORD dwBytes );\r\n    void    Destroy();\r\n\r\n\tDWORD\tGetSampleRate( void ) const;\r\n\r\n    CXBSound();\r\n    ~CXBSound();\r\n};\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Because we don't use voices in the same way as on PS2, this array simulates\r\n// the system. An entry with a NULL pointer means no sound is playing on that\r\n// 'voice', a valid pointer indicates a sound is playing on that 'voice', and\r\n// provides details of the buffer.\r\nstatic VoiceEntry\t\tVoiceSimulator[NUM_VOICES];\r\nstatic IDirectSound8*\tpDirectSound\t= NULL;\r\n\r\nstatic I3DL2ENVIRONMENT reverbEnvironments[] =\r\n{\r\n    { L\"Default\",           { DSI3DL2_ENVIRONMENT_PRESET_DEFAULT }        },\r\n    { L\"Generic\",           { DSI3DL2_ENVIRONMENT_PRESET_GENERIC }        },\r\n    { L\"Padded Cell\",       { DSI3DL2_ENVIRONMENT_PRESET_PADDEDCELL }     },\r\n    { L\"Room\",              { DSI3DL2_ENVIRONMENT_PRESET_ROOM }           },\r\n    { L\"Bathroom\",          { DSI3DL2_ENVIRONMENT_PRESET_BATHROOM }       },\r\n    { L\"Living Room\",       { DSI3DL2_ENVIRONMENT_PRESET_LIVINGROOM }     },\r\n    { L\"Stone Room\",        { DSI3DL2_ENVIRONMENT_PRESET_STONEROOM }      },\r\n    { L\"Auditorium\",        { DSI3DL2_ENVIRONMENT_PRESET_AUDITORIUM }     },\r\n    { L\"Concert Hall\",      { DSI3DL2_ENVIRONMENT_PRESET_CONCERTHALL }    },\r\n    { L\"Cave\",              { DSI3DL2_ENVIRONMENT_PRESET_CAVE }           },\r\n    { L\"Arena\",             { DSI3DL2_ENVIRONMENT_PRESET_ARENA }          },\r\n    { L\"Hangar\",            { DSI3DL2_ENVIRONMENT_PRESET_HANGAR }         },\r\n    { L\"Carpeted Hallway\",  { DSI3DL2_ENVIRONMENT_PRESET_CARPETEDHALLWAY }},\r\n    { L\"Hallway\",           { DSI3DL2_ENVIRONMENT_PRESET_HALLWAY }        },\r\n    { L\"Stone Corridor\",    { DSI3DL2_ENVIRONMENT_PRESET_STONECORRIDOR }  },\r\n    { L\"Alley\",             { DSI3DL2_ENVIRONMENT_PRESET_ALLEY }          },\r\n    { L\"Forest\",            { DSI3DL2_ENVIRONMENT_PRESET_FOREST }         },\r\n    { L\"City\",              { DSI3DL2_ENVIRONMENT_PRESET_CITY }           },\r\n    { L\"Mountains\",         { DSI3DL2_ENVIRONMENT_PRESET_MOUNTAINS }      },\r\n    { L\"Quarry\",            { DSI3DL2_ENVIRONMENT_PRESET_QUARRY }         },\r\n    { L\"Plain\",             { DSI3DL2_ENVIRONMENT_PRESET_PLAIN }          },\r\n    { L\"Parking Lot\",       { DSI3DL2_ENVIRONMENT_PRESET_PARKINGLOT }     },\r\n    { L\"Sewer Pipe\",        { DSI3DL2_ENVIRONMENT_PRESET_SEWERPIPE }      },\r\n    { L\"Underwater\",        { DSI3DL2_ENVIRONMENT_PRESET_UNDERWATER }     },\r\n};\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Global sfx multiplier, percentage.\r\nfloat\t\t\t\t\tgSfxVolume\t\t= 100.0f;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: CRiffChunk()\r\n// Desc: Object constructor.\r\n//-----------------------------------------------------------------------------\r\nCRiffChunk::CRiffChunk()\r\n{\r\n    // Initialize defaults\r\n    m_fccChunkId   = 0;\r\n    m_pParentChunk = NULL;\r\n    m_hFile        = NULL;\r\n    m_dwDataOffset = 0;\r\n    m_dwDataSize   = 0;\r\n    m_dwFlags      = 0;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Initialize()\r\n// Desc: Initializes the object\r\n//-----------------------------------------------------------------------------\r\nVOID CRiffChunk::Initialize( FOURCC fccChunkId, const CRiffChunk* pParentChunk, void* hFile )\r\n{\r\n    m_fccChunkId   = fccChunkId;\r\n    m_pParentChunk = pParentChunk;\r\n    m_hFile        = hFile;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Open()\r\n// Desc: Opens an existing chunk.\r\n//-----------------------------------------------------------------------------\r\nbool CRiffChunk::Open()\r\n{\r\n    RIFFHEADER rhRiffHeader;\r\n    LONG       lOffset = 0;\r\n\r\n    // Seek to the first byte of the parent chunk's data section\r\n    if( m_pParentChunk )\r\n    {\r\n        lOffset = m_pParentChunk->m_dwDataOffset;\r\n\r\n        // Special case the RIFF chunk\r\n        if( FOURCC_RIFF == m_pParentChunk->m_fccChunkId )\r\n\t\t{\r\n            lOffset += sizeof(FOURCC);\r\n\t\t}\r\n    }\r\n    \r\n    // Read each child chunk header until we find the one we're looking for\r\n//\tRwFileFunctions* fs = RwOsGetFileInterface();\r\n    for( ;; )\r\n    {\r\n//\t\tif( fs->rwfseek( m_hFile, lOffset, SEEK_SET ) != 0 )\r\n\t\tFile::Seek( m_hFile, lOffset, SEEK_SET );\r\n//\t\t{\r\n//\t\t\treturn false;\r\n//\t\t}\r\n\r\n\t\tDWORD dwRead;\r\n//\t\tdwRead = fs->rwfread( &rhRiffHeader, sizeof( rhRiffHeader ), 1, m_hFile );\r\n\t\tdwRead = File::Read( &rhRiffHeader, sizeof( rhRiffHeader ), 1, m_hFile );\r\n\t\tif( dwRead != sizeof( rhRiffHeader ))\r\n\t\t{\r\n            return false;\r\n\t\t}\r\n\r\n\t\t// Check if we found the one we're looking for.\r\n\t\tif( m_fccChunkId == rhRiffHeader.fccChunkId )\r\n        {\r\n\t\t\t// Save the chunk size and data offset.\r\n            m_dwDataOffset = lOffset + sizeof( rhRiffHeader );\r\n            m_dwDataSize   = rhRiffHeader.dwDataSize;\r\n\r\n            // Success.\r\n            m_dwFlags |= RIFFCHUNK_FLAGS_VALID;\r\n\r\n            return true;\r\n\t\t}\r\n\t\tlOffset += sizeof( rhRiffHeader ) + rhRiffHeader.dwDataSize;\r\n    }\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Read()\r\n// Desc: Reads from the file\r\n//-----------------------------------------------------------------------------\r\nbool CRiffChunk::ReadData( LONG lOffset, VOID* pData, DWORD dwDataSize )\r\n{\r\n\t// Seek to the offset\r\n//\tRwFileFunctions* fs = RwOsGetFileInterface();\r\n//\tif( fs->rwfseek( m_hFile, m_dwDataOffset+lOffset, SEEK_SET ) != 0 )\r\n//\tif( File::Seek( m_hFile, m_dwDataOffset+lOffset, SEEK_SET ) != 0 )\r\n\tFile::Seek( m_hFile, m_dwDataOffset + lOffset, SEEK_SET );\r\n//\t{\r\n//\t\treturn false;\r\n//\t}\r\n\r\n    // Read from the file\r\n\tDWORD dwRead;\r\n//\tdwRead = fs->rwfread( pData, dwDataSize, 1, m_hFile );\r\n\tdwRead = File::Read( pData, dwDataSize, 1, m_hFile );\r\n\tif( dwRead != dwDataSize )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: CWaveFile()\r\n// Desc: Object constructor.\r\n//-----------------------------------------------------------------------------\r\nCWaveFile::CWaveFile()\r\n{\r\n    m_hFile = NULL;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ~CWaveFile()\r\n// Desc: Object destructor.\r\n//-----------------------------------------------------------------------------\r\nCWaveFile::~CWaveFile()\r\n{\r\n\tClose();\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Open()\r\n// Desc: Initializes the object.\r\n//-----------------------------------------------------------------------------\r\nbool CWaveFile::Open( const char* strFileName )\r\n{\r\n    // If we're already open, close.\r\n    Close();\r\n    \r\n    // Open the file\r\n\tm_hFile = File::Open( strFileName, \"rb\" );\r\n\r\n//\tRwFileFunctions* fs = RwOsGetFileInterface();\r\n//\tm_hFile = fs->rwfopen( strFileName, \"rb\" );\r\n\r\n\tif( m_hFile == NULL )\r\n\t{\r\n        return false;\r\n\t}\r\n\r\n\t// Initialize the chunk objects.\r\n    m_RiffChunk.Initialize( FOURCC_RIFF, NULL, m_hFile );\r\n    m_FormatChunk.Initialize( FOURCC_FORMAT, &m_RiffChunk, m_hFile );\r\n    m_DataChunk.Initialize( FOURCC_DATA, &m_RiffChunk, m_hFile );\r\n    m_SamplerChunk.Initialize( FOURCC_SAMPLER, &m_RiffChunk, m_hFile );\r\n\r\n    bool hr = m_RiffChunk.Open();\r\n    if( !hr )\r\n\t{\r\n        return hr;\r\n\t}\r\n\r\n    hr = m_FormatChunk.Open();\r\n    if( !hr )\r\n\t{\r\n        return hr;\r\n\t}\r\n\r\n    hr = m_DataChunk.Open();\r\n    if( !hr )\r\n\t{\r\n        return hr;\r\n\t}\r\n\r\n\t// Not a problem if it doesn't, not every file will contain the sampler chunk.\r\n    m_ContainsSamplerChunk\t= m_SamplerChunk.Open();\r\n\r\n    // Validate the file type.\r\n    FOURCC fccType;\r\n    hr = m_RiffChunk.ReadData( 0, &fccType, sizeof( fccType ));\r\n    if( !hr )\r\n\t{\r\n        return hr;\r\n\t}\r\n\r\n    if( FOURCC_WAVE != fccType )\r\n        return false;\r\n\r\n    return true;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: GetFormat()\r\n// Desc: Gets the wave file format\r\n//-----------------------------------------------------------------------------\r\nbool CWaveFile::GetFormat( WAVEFORMATEX* pwfxFormat, DWORD dwFormatSize )\r\n{\r\n    DWORD dwValidSize = m_FormatChunk.GetDataSize();\r\n\r\n    if( NULL == pwfxFormat || 0 == dwFormatSize )\r\n        return false;\r\n\r\n    // Read the format chunk into the buffer\r\n    bool hr = m_FormatChunk.ReadData( 0, pwfxFormat, min( dwFormatSize, dwValidSize ));\r\n\r\n\tif( hr )\r\n\t{\r\n\t    // Zero out remaining bytes, in case enough bytes were not read\r\n\t\tif( dwFormatSize > dwValidSize )\r\n\t\t{\r\n\t        ZeroMemory( (BYTE*)pwfxFormat + dwValidSize, dwFormatSize - dwValidSize );\r\n\t\t}\r\n\t}\r\n\r\n    return hr;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ReadSample()\r\n// Desc: Reads data from the audio file.\r\n//-----------------------------------------------------------------------------\r\nbool CWaveFile::ReadSample( DWORD dwPosition, VOID* pBuffer, DWORD dwBufferSize, DWORD* pdwRead )\r\n{                                   \r\n    // Don't read past the end of the data chunk\r\n    DWORD dwDuration;\r\n    GetDuration( &dwDuration );\r\n\r\n    if( dwPosition + dwBufferSize > dwDuration )\r\n        dwBufferSize = dwDuration - dwPosition;\r\n\r\n    bool hr = true;\r\n    if( dwBufferSize )\r\n        hr = m_DataChunk.ReadData( (LONG)dwPosition, pBuffer, dwBufferSize );\r\n\r\n    if( pdwRead )\r\n        *pdwRead = dwBufferSize;\r\n\r\n    return hr;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: \r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nbool CWaveFile::ContainsLoop( void )\r\n{\r\n\t// Figure out if it is a looping sound.\r\n\tif( m_ContainsSamplerChunk )\r\n\t{\r\n\t\tSAMPLERCHUNK sc;\r\n\t\tm_SamplerChunk.ReadData( 0, &sc, sizeof( sc ));\r\n\t\tif( sc.num_sample_loops > 0 )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\t\t\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Close()\r\n// Desc: Closes the object\r\n//-----------------------------------------------------------------------------\r\nvoid CWaveFile::Close( void )\r\n{\r\n    if( m_hFile != NULL )\r\n    {\r\n//\t\tRwFileFunctions* fs = RwOsGetFileInterface();\r\n//\t\tfs->rwfclose( m_hFile );\r\n//\t\tm_hFile = NULL;\r\n\t\tFile::Close( m_hFile );\r\n    }\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: CXBSound()\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nCXBSound::CXBSound( void )\r\n{\r\n    m_dwBufferSize  = 0L;\r\n\tm_pRawData\t\t= NULL;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ~CXBSound()\r\n// Desc: \r\n//-----------------------------------------------------------------------------\r\nCXBSound::~CXBSound( void )\r\n{\r\n    Destroy();\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Create()\r\n// Desc: Creates the sound. Sound is buffered to memory allocated internally\r\n//       by DirectSound.\r\n//-----------------------------------------------------------------------------\r\nbool CXBSound::Create( const CHAR* strFileName, DWORD dwFlags )\r\n{\r\n    bool\tbr;\r\n\r\n    // Open the .wav file\r\n    CWaveFile waveFile;\r\n\tbr = waveFile.Open( strFileName );\r\n    if( !br )\r\n\t{\r\n        return false;\r\n\t}\r\n\r\n    // Get the WAVEFORMAT structure for the .wav file\r\n    br = waveFile.GetFormat( &m_WaveFormat.wfx, sizeof( WAVEFORMATEX ));\r\n    if( !br )\r\n\t{\r\n        return false;\r\n\t}\r\n\r\n\t// Required if the sound is Xbox ADPCM, will be ignored otherwise.\r\n\tm_WaveFormat.wSamplesPerBlock = 64;\r\n\r\n    // Get the size of the .wav file\r\n    waveFile.GetDuration( &m_dwBufferSize );\r\n\r\n\t// See if the sound is looping.\r\n\tm_Loops = waveFile.ContainsLoop();\r\n\r\n    // Create the sound buffer\r\n    br = Create( &m_WaveFormat, dwFlags, NULL, m_dwBufferSize );\r\n    if( !br )\r\n\t{\r\n        return false;\r\n\t}\r\n\r\n    // Lock the buffer so it can be filled\r\n    VOID* pLock1 = NULL;\r\n    VOID* pLock2 = NULL;\r\n    DWORD dwLockSize1 = 0L;\r\n    DWORD dwLockSize2 = 0L;\r\n\r\n\tpLock1 = new char[m_dsbd.dwBufferBytes];\r\n\r\n    // Read the wave file data into the buffer\r\n    br = waveFile.ReadSample( 0L, pLock1, m_dsbd.dwBufferBytes, NULL );\r\n    if( !br )\r\n\t{\r\n        return false;\r\n\t}\r\n\r\n\t// Store pointer to raw sound data.\r\n    m_pRawData = pLock1;\r\n\r\n    return true;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Create()\r\n// Desc: Creates the sound and tells DirectSound where the sound data will be\r\n//       stored. If pBuffer is NULL, DirectSound handles buffer creation.\r\n//-----------------------------------------------------------------------------\r\nbool CXBSound::Create( const XBOXADPCMWAVEFORMAT* pwfxFormat, DWORD dwFlags, VOID* pBuffer, DWORD dwBytes )\r\n{\r\n\t// Setup the sound buffer description.\r\n\tZeroMemory( &m_dsbd, sizeof(DSBUFFERDESC) );\r\n\tm_dsbd.dwSize      = sizeof(DSBUFFERDESC);\r\n\tm_dsbd.dwFlags     = dwFlags;\r\n\r\n\tif( pwfxFormat->wfx.wFormatTag == WAVE_FORMAT_XBOX_ADPCM )\r\n\t{\r\n\t\tm_dsbd.lpwfxFormat\t= (LPWAVEFORMATEX)&m_WaveFormat;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_dsbd.lpwfxFormat\t= (LPWAVEFORMATEX)&pwfxFormat->wfx;\r\n\t}\r\n\r\n\t// If pBuffer is non-NULL, dwBufferBytes will be zero, which informs\r\n\t// DirectSoundCreateBuffer that we will presently be using SetBufferData().\r\n\t// Otherwise, we set dwBufferBytes to the size of the WAV data, potentially\r\n\t// including alignment bytes.\r\n\tif( pBuffer == NULL )\r\n\t{\r\n\t\tm_dsbd.dwBufferBytes = ( 0 == m_WaveFormat.wfx.nBlockAlign ) ? dwBytes : \r\n\t\t\t\t\t\t\t\t dwBytes - ( dwBytes % m_WaveFormat.wfx.nBlockAlign );\r\n\t}\r\n\r\n\t// If buffer specified, tell DirectSound to use it\r\n\tif( pBuffer != NULL )\r\n\t{\r\n\t\t// Store pointer to raw sound data.\r\n\t\tm_pRawData = pBuffer;\r\n\t}\r\n\r\n    return true;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Destroy()\r\n// Desc: Destroys the resources used by the sound\r\n//-----------------------------------------------------------------------------\r\nVOID CXBSound::Destroy()\r\n{\r\n\tif( m_pRawData )\r\n\t{\r\n\t\tdelete [] m_pRawData;\r\n\t}\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: GetSampleRate\r\n// Desc: Provides the sample rate\r\n//-----------------------------------------------------------------------------\r\nDWORD CXBSound::GetSampleRate( void ) const\r\n{\r\n\treturn m_WaveFormat.wfx.nSamplesPerSec;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int getFreeVoice( void )\r\n{\r\n\tfor( int i = 0; i < NUM_VOICES; ++i )\r\n\t{\r\n\t\tif( VoiceSimulator[i].p_buffer == NULL )\r\n\t\t{\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid InitSoundFX( CSfxManager *p_sfx_manager )\r\n{\r\n\tHRESULT\t\t\t\thr;\r\n    LPDSEFFECTIMAGEDESC\tpDesc;\r\n    DSEFFECTIMAGELOC\tEffectLoc;\r\n\r\n\tDbg_Assert( pDirectSound == NULL );\r\n\r\n\t// Set default volume type.\r\n\tif( p_sfx_manager )\r\n\t{\r\n\t\tp_sfx_manager->SetDefaultVolumeType( VOLUME_TYPE_5_CHANNEL_DOLBY5_1 );\r\n\t}\r\n\r\n\t// Initialize the 'voice' array.\r\n\tfor( int i = 0; i < NUM_VOICES; ++i )\r\n\t{\r\n\t\tVoiceSimulator[i].p_buffer = NULL;\r\n\t}\r\n\r\n\t// Create the DirectSound interface.\r\n\thr = DirectSoundCreate( NULL, &pDirectSound, NULL );\r\n\r\n//\tHANDLE hFile = CreateFile( \"d:\\\\data\\\\sounds\\\\bin\\\\dsstdfx.bin\", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL );\r\n\tHANDLE hFile = CreateFile( \"d:\\\\data\\\\sounds\\\\bin\\\\skate5fx.bin\", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL );\r\n    if( hFile == INVALID_HANDLE_VALUE )\r\n    {\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Determine the size of the scratch image by seeking to the end of the file.\r\n\t\tint size = SetFilePointer( hFile, 0, NULL, FILE_END );\r\n        SetFilePointer( hFile, 0, NULL, FILE_BEGIN );\r\n    \r\n\t\t// Allocate memory to read the scratch image from disk\r\n        BYTE* p_buffer = new BYTE[size];\r\n\r\n        // Read the image in\r\n        DWORD dwBytesRead;\r\n        BOOL bResult = ReadFile( hFile, p_buffer, size, &dwBytesRead, 0 );\r\n\t\tif( !bResult )\r\n        {\r\n\t\t\tDbg_Assert( 0 );\r\n        }\r\n\t\telse\r\n\t    {\r\n\t        // Call DSound API to download the image.\r\n//\t\t\tEffectLoc.dwI3DL2ReverbIndex\t= I3DL2_CHAIN_I3DL2_REVERB;\r\n//\t\t\tEffectLoc.dwCrosstalkIndex\t\t= I3DL2_CHAIN_XTALK;\r\n\t\t\tEffectLoc.dwI3DL2ReverbIndex\t= GraphI3DL2_I3DL2Reverb;\r\n\t\t\tEffectLoc.dwCrosstalkIndex\t\t= GraphXTalk_XTalk;\r\n\t\t\thr = pDirectSound->DownloadEffectsImage( p_buffer, size, &EffectLoc, &pDesc );\r\n\r\n\t\t\tdelete[] p_buffer;\r\n        }\r\n    }\r\n\r\n\tif( hFile != INVALID_HANDLE_VALUE ) \r\n\t{\r\n\t\tCloseHandle( hFile );\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CleanUpSoundFX( void )\r\n{\r\n\t// This just resets the SPU RAM pointer on the PS2. However, on Xbox it needs to explicitly\r\n\t// delete any sounds that were not marked as permanent at load time.\r\n\tStopAllSoundFX();\r\n\tSetReverbPlease( 0 );\r\n\r\n\tfor( int i = 0; i < NumWavesInTable; ++i )\r\n\t{\r\n\t\tPlatformWaveInfo* p_info = &( WaveTable[PERM_WAVE_TABLE_MAX_ENTRIES + i].platformWaveInfo );\r\n\t\tDbg_Assert( p_info->p_sound_data );\r\n\t\tdelete p_info->p_sound_data;\r\n\t\tp_info->p_sound_data = NULL;\r\n\t}\r\n\tNumWavesInTable = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid StopAllSoundFX( void )\r\n{\r\n\tPcm::StopMusic();\r\n\tPcm::StopStreams();\r\n\r\n\tfor( int i = 0; i < NUM_VOICES; ++i )\r\n\t{\r\n\t\tStopSoundPlease( i );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint GetMemAvailable( void )\r\n{\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool LoadSoundPlease( const char *sfxName, uint32 checksum, PlatformWaveInfo *pInfo, bool loadPerm )\r\n{\r\n\tDbg_Assert( pInfo );\r\n\r\n\t// Need to append file type. Copy string into a buffer.\r\n\tstatic char name_buffer[256] = \"sounds\\\\pcm\\\\\";\r\n\tconst int SOUND_PREPEND_START_POS = 11;\r\n\r\n\t// Check there is room to add the extension.\r\n\tint length = strlen( sfxName );\r\n\tDbg_Assert( strlen( sfxName ) <= ( 256 - ( SOUND_PREPEND_START_POS + 4 )));\r\n\tstrcpy( name_buffer + SOUND_PREPEND_START_POS, sfxName );\r\n\tstrcpy( name_buffer + SOUND_PREPEND_START_POS + length, \".pcm\" );\r\n\r\n\tCXBSound* p_sound = new CXBSound();\r\n\r\n\t// Pass the locdefer flag along to prevent this buffer taking up a voice because it will not be played directly.\r\n\tbool result = p_sound->Create( name_buffer, DSBCAPS_LOCDEFER );\r\n\r\n\tif( result )\r\n\t{\r\n\t\tpInfo->p_sound_data = p_sound;\r\n\t\tpInfo->looping\t\t= p_sound->m_Loops;\r\n\t\tpInfo->permanent\t= loadPerm;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tOutputDebugString( name_buffer );\r\n\t\tOutputDebugString( \"\\n\" );\r\n\t\tpInfo->p_sound_data = NULL;\r\n\t\tpInfo->looping\t\t= false;\r\n\t\tpInfo->permanent\t= false;\r\n\t\tdelete p_sound;\r\n\t}\r\n \treturn result;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//int\tPlaySoundPlease( PlatformWaveInfo *pInfo, float volL, float volR, float pitch )\r\nint\tPlaySoundPlease( PlatformWaveInfo *pInfo, sVolume *p_vol, float pitch )\r\n{\r\n\tDbg_Assert( pInfo );\r\n\r\n\tif( pInfo->p_sound_data )\r\n\t{\r\n\t\t// Obtain a free voice.\r\n\t\tint voice = getFreeVoice();\r\n\t\tif( voice >= 0 )\r\n\t\t{\r\n\t\t\t// Create the dynamic buffer. Need to set buffer bytes to 0, since we will be setting our own data below.\r\n\t\t\tDWORD temp_flags\t= pInfo->p_sound_data->m_dsbd.dwFlags;\r\n\t\t\tDWORD buffer_bytes\t= pInfo->p_sound_data->m_dsbd.dwBufferBytes;\r\n\r\n//\t\t\tpInfo->p_sound_data->m_dsbd.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY;\t\t\t\r\n\t\t\tpInfo->p_sound_data->m_dsbd.dwBufferBytes\t= 0;\r\n\r\n\t\t\t// Add in the MixBin setup data.\t\t\t\r\n\t\t\tDSMIXBINS\t\t\tdsmixbins;\r\n\t\t\tDSMIXBINVOLUMEPAIR\tdsmbvp[7];\r\n\t\t\tpInfo->p_sound_data->m_dsbd.lpMixBins\t= &dsmixbins;\r\n\t\t\tdsmixbins.dwMixBinCount\t\t\t\t\t= 7;\r\n\t\t\tdsmixbins.lpMixBinVolumePairs\t\t\t= dsmbvp;\r\n\t\t\tdsmbvp[0].dwMixBin\t\t\t\t\t\t= DSMIXBIN_3D_FRONT_LEFT;\r\n\t\t\tdsmbvp[0].lVolume\t\t\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\tdsmbvp[1].dwMixBin\t\t\t\t\t\t= DSMIXBIN_3D_FRONT_RIGHT;\r\n\t\t\tdsmbvp[1].lVolume\t\t\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\tdsmbvp[2].dwMixBin\t\t\t\t\t\t= DSMIXBIN_FRONT_CENTER;\r\n\t\t\tdsmbvp[2].lVolume\t\t\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\tdsmbvp[3].dwMixBin\t\t\t\t\t\t= DSMIXBIN_LOW_FREQUENCY;\r\n\t\t\tdsmbvp[3].lVolume\t\t\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\tdsmbvp[4].dwMixBin\t\t\t\t\t\t= DSMIXBIN_3D_BACK_LEFT;\r\n\t\t\tdsmbvp[4].lVolume\t\t\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\tdsmbvp[5].dwMixBin\t\t\t\t\t\t= DSMIXBIN_3D_BACK_RIGHT;\r\n\t\t\tdsmbvp[5].lVolume\t\t\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\tdsmbvp[6].dwMixBin\t\t\t\t\t\t= DSMIXBIN_I3DL2;\r\n\t\t\tdsmbvp[6].lVolume\t\t\t\t\t\t= DSBVOLUME_EFFECTIVE_MIN;\r\n\r\n\t\t\tHRESULT hr = DirectSoundCreateBuffer( &pInfo->p_sound_data->m_dsbd, &VoiceSimulator[voice].p_buffer );\r\n\r\n\t\t\t// Reset various buffer description values.\r\n\t\t\tpInfo->p_sound_data->m_dsbd.dwFlags\t\t\t= temp_flags;\r\n\t\t\tpInfo->p_sound_data->m_dsbd.dwBufferBytes\t= buffer_bytes;\r\n\t\t\tpInfo->p_sound_data->m_dsbd.lpMixBins\t\t= NULL;\r\n\r\n\t\t\t++num_buffers;\r\n\r\n\t\t\tif( hr == DS_OK )\r\n\t\t\t{\r\n\t\t\t\t// Set the buffer to point to the raw sound data.\r\n\t\t\t\thr = VoiceSimulator[voice].p_buffer->SetBufferData( pInfo->p_sound_data->m_pRawData, pInfo->p_sound_data->m_dsbd.dwBufferBytes );\r\n\t\t\t\tif( hr == DS_OK )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Set the default sample rate.\r\n\t\t\t\t\tVoiceSimulator[voice].default_frequency = pInfo->p_sound_data->GetSampleRate();\r\n\r\n\t\t\t\t\t// Play the sound.\r\n\t\t\t\t\thr = VoiceSimulator[voice].p_buffer->Play( 0, 0, ( pInfo->looping ) ? DSBPLAY_LOOPING : 0 );\r\n\t\t\t\t\tif( hr == DS_OK )\r\n\t\t\t\t\t{\r\n//\t\t\t\t\t\tSetVoiceParameters( voice, volL, volR, pitch );\r\n\t\t\t\t\t\tSetVoiceParameters( voice, p_vol, pitch );\r\n\t\t\t\t\t\treturn voice;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn -1;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid StopSoundPlease( int voice )\r\n{\r\n\tif( VoiceSimulator[voice].p_buffer )\r\n\t{\r\n\t\tHRESULT hr = VoiceSimulator[voice].p_buffer->Stop();\r\n\t\tDbg_Assert( hr == DS_OK )\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SetVolumePlease( float volumeLevel )\r\n{\r\n\tgSfxVolume = volumeLevel;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PauseSoundsPlease( void )\r\n{\r\n\tsVolume vol;\r\n\tvol.SetSilent();\r\n\t\r\n\t// Just turn the volume down on all playing voices...\r\n\tfor( int i = 0; i < NUM_VOICES; i++ )\r\n\t{\r\n\t\tif( VoiceIsOn( i ))\r\n\t\t{\r\n//\t\t\tSetVoiceParameters( i, 0.0f, 0.0f );\r\n\t\t\tSetVoiceParameters( i, &vol );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SetReverbPlease( float reverbLevel, int reverbMode, bool instant )\r\n{\r\n\tif( reverbMode == 0 )\r\n\t{\r\n\t\t// Default to plain.\r\n\t\treverbMode = 20;\r\n\t}\r\n\treverbMode = 20;\r\n\t\r\n\tHRESULT hr = pDirectSound->SetI3DL2Listener( &reverbEnvironments[reverbMode].ds3dl, DS3D_IMMEDIATE );\r\n\tDbg_Assert( hr == DS_OK );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool VoiceIsOn( int voice )\r\n{\r\n\treturn( VoiceSimulator[voice].p_buffer != NULL );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//void SetVoiceParameters( int voice, float volL, float volR, float pitch )\r\nvoid SetVoiceParameters( int voice, sVolume *p_vol, float pitch )\r\n{\r\n\tif( VoiceSimulator[voice].p_buffer )\r\n\t{\r\n\t\t// This array will hold individual volumes for the five speakers.\r\n\t\t// In order, they are: front left, center, front right, rear right, rear left.\r\n\t\tfloat\tvolumes[5];\r\n\t\tint\t\ti_volumes[5], max_i_volume;\r\n\r\n\t\tmemset( volumes, 0, sizeof( float ) * 5 );\r\n\t\t\r\n\t\tif( p_vol->IsSilent())\r\n\t\t{\r\n\t\t\t// Pointless doing any more work.\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tswitch( p_vol->GetVolumeType())\r\n\t\t\t{\r\n\t\t\t\tcase VOLUME_TYPE_5_CHANNEL_DOLBY5_1:\r\n\t\t\t\t{\r\n\t\t\t\t\t// All the work has been done already - just copy volumes over.\r\n\t\t\t\t\tvolumes[0] = p_vol->GetChannelVolume( 0 );\r\n\t\t\t\t\tvolumes[1] = p_vol->GetChannelVolume( 4 );\r\n\t\t\t\t\tvolumes[2] = p_vol->GetChannelVolume( 1 );\r\n\t\t\t\t\tvolumes[3] = p_vol->GetChannelVolume( 2 );\r\n\t\t\t\t\tvolumes[4] = p_vol->GetChannelVolume( 3 );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcase VOLUME_TYPE_BASIC_2_CHANNEL:\r\n\t\t\t\t{\r\n\t\t\t\t\t// Simple two channel sound, so just setup as such.\r\n\t\t\t\t\tvolumes[0] = p_vol->GetChannelVolume( 0 );\r\n\t\t\t\t\tvolumes[1] = ( p_vol->GetChannelVolume( 0 ) + p_vol->GetChannelVolume( 1 )) * 0.5f;\r\n\t\t\t\t\tvolumes[2] = p_vol->GetChannelVolume( 1 );\r\n\t\t\t\t\tvolumes[3] = p_vol->GetChannelVolume( 0 ) * 0.5f;\r\n\t\t\t\t\tvolumes[4] = p_vol->GetChannelVolume( 1 ) * 0.5f;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcase VOLUME_TYPE_2_CHANNEL_DOLBYII:\r\n\t\t\t\tdefault:\r\n\t\t\t\t{\r\n\t\t\t\t\t// Wes should not get any of these.\r\n\t\t\t\t\tDbg_Assert( 0 );\r\n\r\n#\t\t\t\t\tif 0\r\n\t\t\t\t\t// Get the length of the vector here which will be used to multiply out the normalised speaker volumes.\r\n\t\t\t\t\tMth::Vector test( fabsf( p_vol->GetChannelVolume( 0 )), fabsf( p_vol->GetChannelVolume( 1 )), 0.0f, 0.0f );\r\n\t\t\t\t\tfloat amplitude = test.Length();\r\n\t\t\t\t\r\n\t\t\t\t\t// Look just at the normalized right component to figure the sound angle from Matt's calculations.\r\n\t\t\t\t\ttest.Normalize();\r\n\r\n\t\t\t\t\tfloat angle;\r\n\t\t\t\t\tangle\t= asinf( test[Y] );\r\n\t\t\t\t\tangle\t= ( angle * 2.0f ) - ( Mth::PI * 0.5f );\r\n\t\t\t\t\tangle\t= ( p_vol->GetChannelVolume( 0 ) < 0.0f ) ? ( Mth::PI - angle ) : angle;\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t// Now figure volumes based on speaker coverage.\r\n\t\t\t\t\tangle\t= Mth::RadToDeg( angle );\r\n\r\n\t\t\t\t\t// Left front channel.\r\n\t\t\t\t\tif(( angle >= 225.0f ) || ( angle <= 45.0f ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Because of the discontinuity, shift this angle round to the [0,180] range.\r\n\t\t\t\t\t\tfloat shift_angle = angle + 135;\r\n\t\t\t\t\t\tshift_angle = ( shift_angle >= 360.0f ) ? ( shift_angle - 360.0f ) : shift_angle;\r\n\t\t\t\t\t\tvolumes[0]\t= ( shift_angle / 180.0f ) * Mth::PI;\r\n\t\t\t\t\t\tvolumes[0]\t= sqrtf( sinf( volumes[0] ));\r\n\t\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t\t// Center channel.\r\n\t\t\t\t\tif(( angle >= -60.0f ) && ( angle <= 60.0f ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Scale this into [0,PI] space so we can get smooth fadeout.\r\n\t\t\t\t\t\tvolumes[1]\t= (( angle + 60.0f ) / 120.0f ) * Mth::PI;\r\n\t\t\t\t\t\tvolumes[1]\t= sqrtf( sinf( volumes[1] ));\r\n\t\t\t\t\t}\r\n\t\t\r\n\t\t\t\t\t// Right front channel.\r\n\t\t\t\t\tif(( angle >= -45.0f ) && ( angle <= 135.0f ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Scale this into [0,PI] space so we can get smooth fadeout.\r\n\t\t\t\t\t\tvolumes[2]\t= (( angle + 45.0f ) / 180.0f ) * Mth::PI;\r\n\t\t\t\t\t\tvolumes[2]\t= sqrtf( sinf( volumes[2] ));\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Right rear channel.\r\n\t\t\t\t\tif(( angle >= 45.0f ) && ( angle <= 225.0f ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Scale this into [0,PI] space so we can get smooth fadeout.\r\n\t\t\t\t\t\tvolumes[3]\t= (( angle - 45.0f ) / 180.0f ) * Mth::PI;\r\n\t\t\t\t\t\tvolumes[3]\t= sqrtf( sinf( volumes[3] ));\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Left rear channel.\r\n\t\t\t\t\tif(( angle >= 135.0f ) || ( angle <= -45.0f ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Because of the discontinuity, shift this angle round to the [0,180] range.\r\n\t\t\t\t\t\tfloat shift_angle = angle + 225;\r\n\t\t\t\t\t\tshift_angle = ( shift_angle >= 360.0f ) ? ( shift_angle - 360.0f ) : shift_angle;\r\n\t\t\t\t\t\tvolumes[4]\t= ( shift_angle / 180.0f ) * Mth::PI;\r\n\t\t\t\t\t\tvolumes[4]\t= sqrtf( sinf( volumes[4] ));\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Scale back up to original amplitude.\r\n\t\t\t\t\tfor( int v = 0; v < 5; ++v )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tvolumes[v] *= amplitude;\r\n\t\t\t\t\t}\r\n#\t\t\t\t\tendif\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Now readjust the relative values...\r\n\t\tfor( int v = 0; v < 5; ++v )\r\n\t\t{\r\n\t\t\t// Adjust for SFX volume level, and scale into limits.\r\n\t\t\tvolumes[v] = fabsf( PERCENT( gSfxVolume, volumes[v] ));\r\n\r\n\t\t\t\tif( volumes[v] > 100.0f )\r\n\t\t\t\t\tvolumes[v] = 100.0f;\r\n\t\t}\r\n\t\t\r\n\t\t// Now figure the attenuation of the sound. To convert to a decibel value, figure the ratio of requested\r\n\t\t// volume versus max volume, then calculate the log10 and multiply by (10 * 2). (The 2 is because sound\r\n\t\t// power varies as square of pressure, and squaring doubles the log value).\r\n\t\tmax_i_volume = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\tfor( int v = 0; v < 5; ++v )\r\n\t\t{\r\n\t\t\tif( volumes[v] > 0.0f )\r\n\t\t\t{\r\n\t\t\t\tfloat attenuation\t= 20.0f * log10f( volumes[v] * 0.01f );\r\n\t\t\t\ti_volumes[v]\t\t= DSBVOLUME_MAX + (int)( attenuation * 100.0f );\r\n\t\t\t\tif( i_volumes[v] < DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t\t\t\ti_volumes[v] = DSBVOLUME_EFFECTIVE_MIN;\r\n\r\n\t\t\t\tif( i_volumes[v] > max_i_volume )\r\n\t\t\t\t\tmax_i_volume = i_volumes[v];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ti_volumes[v] = DSBVOLUME_EFFECTIVE_MIN;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Set individual mixbins for panning.\r\n\t\tDSMIXBINS\t\t\tdsmixbins;\r\n\t\tDSMIXBINVOLUMEPAIR\tdsmbvp[DSMIXBIN_ASSIGNMENT_MAX];\r\n\r\n\t\tdsmixbins.dwMixBinCount\t\t\t= 0;\r\n\t\tdsmixbins.lpMixBinVolumePairs\t= dsmbvp;\r\n\r\n\t\tif( i_volumes[0] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_FRONT_LEFT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[0];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\r\n\t\tif( i_volumes[1] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_FRONT_CENTER;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[1];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\r\n\t\tif( i_volumes[2] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_FRONT_RIGHT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[2];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\r\n\t\tif( i_volumes[3] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_BACK_RIGHT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[3];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\r\n\t\tif( i_volumes[4] > DSBVOLUME_EFFECTIVE_MIN )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_3D_BACK_LEFT;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= i_volumes[4];\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\r\n\t\tif( dsmixbins.dwMixBinCount > 0 )\r\n\t\t{\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_LOW_FREQUENCY;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= max_i_volume;\r\n            dsmixbins.dwMixBinCount++;\r\n\r\n            dsmbvp[dsmixbins.dwMixBinCount].dwMixBin\t= DSMIXBIN_I3DL2;\r\n            dsmbvp[dsmixbins.dwMixBinCount].lVolume\t\t= DSBVOLUME_MAX;\r\n            dsmixbins.dwMixBinCount++;\r\n\t\t}\r\n\r\n\t\t// Set all speaker volumes.\r\n\t\tHRESULT hr = VoiceSimulator[voice].p_buffer->SetMixBinVolumes( &dsmixbins );\r\n\r\n\t\t// Set overall buffer volume.\r\n\t\tif( dsmixbins.dwMixBinCount > 0 )\r\n\t\t{\r\n\t\t\thr = VoiceSimulator[voice].p_buffer->SetVolume( DSBVOLUME_MAX );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\thr = VoiceSimulator[voice].p_buffer->SetVolume( DSBVOLUME_EFFECTIVE_MIN );\r\n\r\n\t\t\t// Pointless doing pitch calculation if volume is zero.\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Same kind of deal for pitch. Each consecutive doubling (or halving) of the pitch percentage\r\n\t\t// raises (or lowers) the pitch by 1 octave. So we need to figure x, where 2 ^ x = percentage / 100.\r\n\t\t// Can do this with logs...\r\n\t\tint ipitch;\r\n\r\n\t\t// Matt appears to be doing an extra adjustment to the pitch on the Ps2 to account for sample rates\r\n\t\t// not at 48,000Hz. Whilst this seems an unnecessary step, we need to do the same adjustment here.\r\n\t\t// Adjust pitch to account for lower sampling rates.\r\n//\t\tpitch = PERCENT( pitch, ((float)VoiceSimulator[voice].default_frequency / 48000.0f ) * 100.0f );\r\n\t\t\r\n\t\tif( pitch != 100.0f )\r\n\t\t{\r\n\t\t\tipitch = (int)(( VoiceSimulator[voice].default_frequency * pitch ) * 0.01f );\r\n\t\t\tif( ipitch > DSBFREQUENCY_MAX )\r\n\t\t\t{\r\n\t\t\t\tipitch = DSBFREQUENCY_MAX;\r\n\t\t\t}\r\n\t\t\telse if( ipitch < DSBFREQUENCY_MIN )\r\n\t\t\t{\r\n\t\t\t\tipitch = DSBFREQUENCY_MIN;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tipitch = VoiceSimulator[voice].default_frequency;\r\n\t\t}\r\n\t\thr = VoiceSimulator[voice].p_buffer->SetFrequency( ipitch );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PerFrameUpdate( void )\r\n{\r\n\tDirectSoundDoWork();\r\n\r\n\tint num_used_voices = 0;\r\n\r\n\tfor( int i = 0; i < NUM_VOICES; ++i )\r\n\t{\r\n\t\tif( VoiceSimulator[i].p_buffer )\r\n\t\t{\r\n\t\t\tDWORD status;\r\n\t\t\tHRESULT hr = VoiceSimulator[i].p_buffer->GetStatus( &status );\r\n\t\t\tif(( hr == DS_OK ) && ( status == 0 ))\r\n\t\t\t{\r\n\t\t\t\t// This sound has stopped playing, so we can release the buffer.\r\n\t\t\t\thr = VoiceSimulator[i].p_buffer->Release();\r\n\r\n\t\t\t\t--num_buffers;\r\n\r\n\t\t\t\tDbg_Assert( hr == 0 );\r\n\r\n\t\t\t\tVoiceSimulator[i].p_buffer = NULL;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t++num_used_voices;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Sfx\r\n"
  },
  {
    "path": "Code/Gel/SoundFX/Xbox/p_sfx.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSound effects  (Sfx)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t01/10/2001\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __MODULES_P_SFX_H\r\n#define __MODULES_P_SFX_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Sfx\r\n{\r\n\r\n#define NUM_VOICES_PER_CORE\t\t\t\t24\r\n#define NUM_CORES\t\t\t\t\t\t2\r\n#define NUM_VOICES\t\t\t\t\t\t( NUM_VOICES_PER_CORE * NUM_CORES )\r\n\r\n#define WAVE_TABLE_MAX_ENTRIES\t\t\t256\t// non-permanent sounds\r\n#define PERM_WAVE_TABLE_MAX_ENTRIES\t\t256\t// permanent sounds\r\n#define MAX_POSITIONAL_SOUNDS\t\t\t128\r\n\r\n// (From Xbox docs) Even though DirectSound allows you to set the minimum volume to -100 dB,\r\n// the XBox audio hardware clamps to silence at -64 dB. For efficiency, your game should avoid\r\n// making volume calls and calculations where the volume is below -64 dB, particularly when\r\n// keeping 3D sounds on that are intended to sound distant or far away.\r\n#define DSBVOLUME_EFFECTIVE_MIN\t-6400\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CXBSound;\r\nclass CSfxManager;\r\n\r\n// Platform specific info needed per wave (stored in the WaveTable).\r\nstruct PlatformWaveInfo\r\n{\r\n\tCXBSound*\tp_sound_data;\r\n\tbool\t\tlooping;\t\t// this flag is checked in soundfx.cpp.  might oughtta be added to WaveTableEntry struct...\r\n\tbool\t\tpermanent;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern float\tgSfxVolume;\r\nstruct sVolume;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tInitSoundFX( CSfxManager *p_sfx_manager );\r\nvoid\tCleanUpSoundFX( void );\r\nvoid\tStopAllSoundFX( void );\r\nbool\tLoadSoundPlease( const char *sfxName, uint32 checksum, PlatformWaveInfo *pInfo, bool loadPerm = 0 );\r\n\r\n// returns 0 - ( NUM_VOICES - 1 ), or -1 if no voices are free...\r\n//int\t\tPlaySoundPlease( PlatformWaveInfo *pInfo, float volL = 100.0f, float volR = 100.0f, float pitch = 100.0f );\r\nint\t\tPlaySoundPlease( PlatformWaveInfo *pInfo, sVolume *p_vol, float pitch = 100.0f );\r\n\r\nvoid\tStopSoundPlease( int whichVoice );\r\n\r\nint\t\tGetMemAvailable( void );\r\n\r\n// really just turning down the volume on all playing voices...\r\n// Looping sounds will get the volume adjusted by the owner\r\n// during the next logic loop.\r\n// The non-looping sounds will play (with no volume) then stop.\r\n// This is for when we go into the menus or whatnot...\r\nvoid\tPauseSoundsPlease( void );\r\n\r\n// see reverb types above...\r\nvoid\tSetReverbPlease( float reverbLevel = 0.0f, int reverbMode = 0, bool instant = false );\r\n\r\n// volume from -100 to 100 ( negative if the sound is from behind us. ps2 alters the sound... )\r\nvoid\tSetVolumePlease( float volumeLevel );\r\n\r\n// returns true if voice is being used currently.\r\nbool\tVoiceIsOn( int whichVoice );\r\n\r\n// change parameters on an active voice:\r\n// if pitch parameter is zero, pitch won't be changed (lowest pitch is 1)\r\nvoid\tSetVoiceParameters( int whichVoice, sVolume *p_vol, float pitch = 0.0 );\r\n\r\nvoid\tPerFrameUpdate( void );\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Sfx\r\n\r\n#endif\t// __MODULES_P_SFX_H\r\n"
  },
  {
    "path": "Code/Gel/SoundFX/Xbox/skate5fx.h",
    "content": "\r\n#pragma once\r\n\r\ntypedef enum _DSP_IMAGE_skate5fx_FX_INDICES {\r\n    UserStereoEcho_StereoEcho = 0,\r\n    UserI3DL224KReverb_I3DL224KReverb = 1,\r\n    GraphI3DL2_I3DL2Reverb = 2,\r\n    GraphXTalk_XTalk = 3\r\n} DSP_IMAGE_skate5fx_FX_INDICES;\r\n\r\n#define DSI3DL2_ENVIRONMENT_UserI3DL224KReverb_I3DL224KReverb -1000, -270, 0.000000, 1.490000, 0.860000, -1204, 0.007000, -4, 0.011000, 100.000000, 100.000000, 5000.000000\r\n\r\n#define DSI3DL2_ENVIRONMENT_GraphI3DL2_I3DL2Reverb -1000, -100, 0.000000, 1.490000, 0.830000, -2602, 0.007000, 200, 0.011000, 100.000000, 100.000000, 5000.000000\r\n\r\ntypedef struct _UserStereoEcho_FX0_StereoEcho_STATE {\r\n    DWORD dwScratchOffset;        // Offset in bytes, of scratch area for this FX\r\n    DWORD dwScratchLength;        // Length in DWORDS, of scratch area for this FX\r\n    DWORD dwYMemoryOffset;        // Offset in DSP WORDS, of Y memory area for this FX\r\n    DWORD dwYMemoryLength;        // Length in DSP WORDS, of Y memory area for this FX\r\n    DWORD dwFlags;                // FX bitfield for various flags. See xgpimage documentation\r\n    DWORD dwInMixbinPtrs[2];      // XRAM offsets in DSP WORDS, of input mixbins\r\n    DWORD dwOutMixbinPtrs[2];     // XRAM offsets in DSP WORDS, of output mixbins\r\n} UserStereoEcho_FX0_StereoEcho_STATE, *LPUserStereoEcho_FX0_StereoEcho_STATE;\r\n\r\ntypedef const UserStereoEcho_FX0_StereoEcho_STATE *LPCUserStereoEcho_FX0_StereoEcho_STATE;\r\n\r\ntypedef struct _UserI3DL224KReverb_FX0_I3DL224KReverb_STATE {\r\n    DWORD dwScratchOffset;        // Offset in bytes, of scratch area for this FX\r\n    DWORD dwScratchLength;        // Length in DWORDS, of scratch area for this FX\r\n    DWORD dwYMemoryOffset;        // Offset in DSP WORDS, of Y memory area for this FX\r\n    DWORD dwYMemoryLength;        // Length in DSP WORDS, of Y memory area for this FX\r\n    DWORD dwFlags;                // FX bitfield for various flags. See xgpimage documentation\r\n    DWORD dwInMixbinPtrs[2];      // XRAM offsets in DSP WORDS, of input mixbins\r\n    DWORD dwOutMixbinPtrs[35];     // XRAM offsets in DSP WORDS, of output mixbins\r\n} UserI3DL224KReverb_FX0_I3DL224KReverb_STATE, *LPUserI3DL224KReverb_FX0_I3DL224KReverb_STATE;\r\n\r\ntypedef const UserI3DL224KReverb_FX0_I3DL224KReverb_STATE *LPCUserI3DL224KReverb_FX0_I3DL224KReverb_STATE;\r\n\r\ntypedef struct _GraphI3DL2_FX0_I3DL2Reverb_STATE {\r\n    DWORD dwScratchOffset;        // Offset in bytes, of scratch area for this FX\r\n    DWORD dwScratchLength;        // Length in DWORDS, of scratch area for this FX\r\n    DWORD dwYMemoryOffset;        // Offset in DSP WORDS, of Y memory area for this FX\r\n    DWORD dwYMemoryLength;        // Length in DSP WORDS, of Y memory area for this FX\r\n    DWORD dwFlags;                // FX bitfield for various flags. See xgpimage documentation\r\n    DWORD dwInMixbinPtrs[2];      // XRAM offsets in DSP WORDS, of input mixbins\r\n    DWORD dwOutMixbinPtrs[35];     // XRAM offsets in DSP WORDS, of output mixbins\r\n} GraphI3DL2_FX0_I3DL2Reverb_STATE, *LPGraphI3DL2_FX0_I3DL2Reverb_STATE;\r\n\r\ntypedef const GraphI3DL2_FX0_I3DL2Reverb_STATE *LPCGraphI3DL2_FX0_I3DL2Reverb_STATE;\r\n\r\ntypedef struct _GraphXTalk_FX0_XTalk_STATE {\r\n    DWORD dwScratchOffset;        // Offset in bytes, of scratch area for this FX\r\n    DWORD dwScratchLength;        // Length in DWORDS, of scratch area for this FX\r\n    DWORD dwYMemoryOffset;        // Offset in DSP WORDS, of Y memory area for this FX\r\n    DWORD dwYMemoryLength;        // Length in DSP WORDS, of Y memory area for this FX\r\n    DWORD dwFlags;                // FX bitfield for various flags. See xgpimage documentation\r\n    DWORD dwInMixbinPtrs[4];      // XRAM offsets in DSP WORDS, of input mixbins\r\n    DWORD dwOutMixbinPtrs[4];     // XRAM offsets in DSP WORDS, of output mixbins\r\n} GraphXTalk_FX0_XTalk_STATE, *LPGraphXTalk_FX0_XTalk_STATE;\r\n\r\ntypedef const GraphXTalk_FX0_XTalk_STATE *LPCGraphXTalk_FX0_XTalk_STATE;\r\n"
  },
  {
    "path": "Code/Gel/SoundFX/ngc/p_sfx.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2001 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSound effects (Sfx)\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tngc/p_sfx.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t08/21/01\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNGC Sound effects\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdio.h>\r\n#include <string.h>\r\n#include <core/macros.h>\r\n#include <core/defines.h>\r\n#include\t<sys/file/filesys.h>\r\n#include <sys/ngc/p_dma.h>\r\n#include <gel/soundfx/ngc/p_sfx.h>\r\n#include <gel/music/ngc/pcm/pcm.h>\r\n#include <gel/music/ngc/p_music.h>\r\n#include <gel/music/music.h>\r\n#include <dolphin/mix.h>\r\n#include <dolphin\\dtk.h>\r\n#include \t\"gfx\\ngc\\nx\\nx_init.h\"\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Sfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define\tGAMECUBE_START_DSP_DATA_ADDR\t\t( NxNgc::EngineGlobals.aram_dsp )\r\n#define\tGAMECUBE_END_DSP_DATA_ADDR\t\t\t( NxNgc::EngineGlobals.aram_dsp + aram_dsp_size )\r\n\r\n#define MAX_VOLUME\t\t\t\t\t\t0x7FFF  // Max Gamecube volume.\r\n#define MAX_CHANNEL_VOLUME\t\t\t\t0x3FFF\t// Half of the maximum, so sounds played at 100% will be half max volume.\r\n#define MAX_REVERB_DEPTH\t\t\t\t0x3FFF\r\n#define MAX_PITCH\t\t\t\t\t\t0xFFFFFL\r\n#define UNALTERED_PITCH\t\t\t\t\t0x10000L\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstruct sDSPADPCM\r\n{\r\n\t// for WAV header generation during decode\r\n\tu32 num_samples;\t\t// total number of RAW samples\r\n\tu32 num_adpcm_nibbles;\t// number of ADPCM nibbles (including frame headers)\r\n\tu32 sample_rate;\t\t// Sample rate, in Hz\r\n\r\n\t// DSP addressing and decode context\r\n\tu16 loop_flag; // 1=LOOPED, 0=NOT LOOPED\r\n\tu16 format; // Always 0x0000, for ADPCM\r\n\tu32 sa; // Start offset address for looped samples (zero for non-looped)\r\n\tu32 ea; // End offset address for looped samples\r\n\tu32 ca; // always zero\r\n\tu16 coef[16]; // decode coefficients (eight pairs of 16-bit words)\r\n\r\n\t// DSP decoder initial state\r\n\tu16 gain; // always zero for ADPCM\r\n\tu16 ps; // predictor/scale\r\n\tu16 yn1; // sample history\r\n\tu16 yn2; // sample history\r\n\r\n\t// DSP decoder loop context\r\n\tu16 lps; // predictor/scale for loop context\r\n\tu16 lyn1; // sample history (n-1) for loop context\r\n\tu16 lyn2; // sample history (n-2) for loop context\r\n\tu16 pad[10]; // reserved\r\n};\r\n\r\n\r\n\r\nstruct VoiceEntry\r\n{\r\n\tAXVPB*\t\t\t\tp_axvpb;\t\t// Pointer returned by AXAcquireVoice().\r\n\tstruct sDSPADPCM*\tp_dspadpcm;\t\t// Pointer to sample header data in memory.\r\n};\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Because we don't use voices in the same way as on PS2, this array simulates\r\n// the system. An entry with a NULL pointer means no sound is playing on that\r\n// 'voice', a valid pointer indicates a sound is playing on that 'voice', and\r\n// provides details of the playback.\r\nstatic VoiceEntry\t\tVoiceSimulator[NUM_VOICES];\r\n\r\n// Global sfx multiplier, percentage.\r\nstatic float\t\t\tgSfxVolume\t\t= 100.0f;\r\n\r\n// allocated SPU RAM\r\nint SpuRAMUsedTemp = 0;\r\nint SpuRAMUsedPerm = 0;\r\n\r\n// For maintaining pointers to the temporary sound headers, so they can be wiped\r\n// when cleanup between levels is performed.\r\nstatic void*\t\t\ttempSoundHeaders[200];\r\nstatic int\t\t\t\tnumTempSoundHeaders = 0;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool\t\t\t\t\tisStereo = true;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid AXUserCBack( void )\r\n{\r\n\tfor( int i = 0; i < NUM_VOICES; ++i )\r\n\t{\r\n\t\tif( VoiceSimulator[i].p_axvpb != NULL )\r\n\t\t{\r\n\t\t\tif( VoiceSimulator[i].p_axvpb->pb.state == AX_PB_STATE_STOP )\r\n\t\t\t{\r\n\t\t\t\t// Playback on this voice has ended, so free up the voice.\r\n\t\t\t\tAXFreeVoice( VoiceSimulator[i].p_axvpb );\r\n\t\t\t\tVoiceSimulator[i].p_axvpb = NULL;\r\n//\t\t\t\tOSReport( \"voice %d stopped %d\\n\", i, OSGetTick() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void ax_voice_reacquisition_callback( void* p )\r\n{\r\n\tOSReport( \"Voice was reacquired\\n\" );\r\n\r\n\tfor( int i = 0; i < NUM_VOICES; ++i )\r\n\t{\r\n\t\tif( VoiceSimulator[i].p_axvpb != NULL )\r\n\t\t{\r\n\t\t\tif( (void*)( VoiceSimulator[i].p_axvpb ) == p )\r\n\t\t\t{\r\n\t\t\t\tOSReport( \"Voice was voice %d\\n\", i );\r\n\t\t\t\tVoiceSimulator[i].p_axvpb = NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int getFreeVoice( void )\r\n{\r\n\tfor( int i = 0; i < NUM_VOICES; ++i )\r\n\t{\r\n\t\tif( VoiceSimulator[i].p_axvpb == NULL )\r\n\t\t{\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic bool loadGamecubeDSP( PlatformWaveInfo *pInfo, const char *filename, bool loadPerm, float *samplePitch )\r\n{\r\n\tint vagAddr\t= 0;\t\t\t// VAG address in SPU2 RAM, returned to calling function\r\n\tbool rv = false;\r\n\r\n\tvoid* p_file = File::Open( filename, \"rb\" );\r\n\tif( p_file )\r\n\t{\r\n\t\tint\t\tsize\t\t= File::GetFileSize( p_file );\r\n\t\tif ( size )\r\n\t\t{\r\n\t\t\tint\t\talign_size\t= ( size + 31 ) & ~31;\r\n\t\t\tint\t\tdata_size\t= align_size - 96;\r\n\t\r\n\t\t\t// Grab enough memory to ensure a multiple of 32 bytes data length. To avoid fragmentation, we grab\r\n\t\t\t// memory for the header copy first.\r\n\t\t\tchar*\tp_header_copy\t= (char*)Mem::Malloc( 96 );\r\n//\t\t\tFile::Read( p_header_copy, 1, 96, p_file );\r\n\t\t\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\t\t\tchar*\tp_data\t\t\t= (char*)Mem::Malloc( align_size );\r\n\t\t\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n//\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tint\t\tbytes_read\t\t= File::Read( p_data, 1, size, p_file );\r\n//\t#else\r\n//\t\t\tFile::Read( p_data, 1, size, p_file );\r\n\t\t\tDCFlushRange ( p_data, size );\r\n//\t#endif\t\t//\t__NOPT_ASSERT__\r\n//\t\t\tDbg_Assert( bytes_read == size )\r\n\t\t\tif ( bytes_read != size )\r\n\t\t\t{\r\n\t\t\t\tFile::Close( p_file );\r\n\t\t\t\tdelete p_data;\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n//\t\t\tfile.close();\r\n\t\r\n\t\t\t// Copy the header to the reserved area.\r\n\t\t\tmemcpy( p_header_copy, p_data, 96 );\r\n\t\r\n\t\t\t// Obtain information from the file header.\r\n\t\t\tsDSPADPCM*\tp_header\t= (sDSPADPCM*)p_header_copy;\r\n\t//\t\tOSReport( \"num samples: %d\\n\", p_header->num_samples );\r\n\t//\t\tOSReport( \"sample rate: %d\\n\", p_header->sample_rate );\r\n\t//\t\tOSReport( \"loop flag:\t%d\\n\", p_header->loop_flag );\r\n\t\r\n\t\t\tif( loadPerm )\r\n\t\t\t{\r\n\t\t\t\t// Stack the permanent sounds up from the bottom.\r\n\t\t\t\tSpuRAMUsedPerm += data_size;\r\n\t\t\t\tif(( GAMECUBE_END_DSP_DATA_ADDR - SpuRAMUsedPerm ) & 0x0F )\r\n\t\t\t\t{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\t\t\tint oldSpuRAM = SpuRAMUsedPerm;\r\n\t#endif\t\t//\t__NOPT_ASSERT__\r\n\t\t\t\t\tSpuRAMUsedPerm += (( END_WAVE_DATA_ADDR - SpuRAMUsedPerm ) & 0x0F );\r\n\t\t\t\t\tDbg_MsgAssert( SpuRAMUsedPerm > oldSpuRAM, ( \"Duh asshole.\" ));\r\n\t\t\t\t}\r\n\t\t\t\tvagAddr = GAMECUBE_END_DSP_DATA_ADDR - SpuRAMUsedPerm;\r\n\t\t\t\tDbg_MsgAssert( !( vagAddr & 0x0F ), ( \"Fire Matt please.\" ));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// If a temporary sound, add the details of the header to the cleanup array.\r\n\t\t\t\ttempSoundHeaders[numTempSoundHeaders++]\t= p_header_copy;\r\n\t\r\n\t\t\t\tif(( SpuRAMUsedTemp + GAMECUBE_START_DSP_DATA_ADDR ) & 0x0F )\r\n\t\t\t\t{\r\n\t\t\t\t\tSpuRAMUsedTemp += 0x10 - ( ( SpuRAMUsedTemp + BASE_WAVE_DATA_ADDR ) & 0x0F );\r\n\t\t\t\t}\r\n\t\t\t\tvagAddr = GAMECUBE_START_DSP_DATA_ADDR + SpuRAMUsedTemp;\r\n\t\t\t\tSpuRAMUsedTemp += data_size;\r\n\t\t\t}\r\n\t\t\r\n\t\t\t// Start DMA transfer buffer to sound RAM...\r\n\t\t\tDbg_Assert(((unsigned int)p_data & 31 ) == 0 );\r\n\t\t\tDbg_Assert(((unsigned int)vagAddr & 31 ) == 0 );\r\n\t\r\n\t\t\t// Read data in chunks & DMA.\r\n//\t\t\tint toread = size - 96;\r\n//\t\t\tint offset = 0;\r\n//\t\t\twhile ( toread )\r\n//\t\t\t{\r\n//#define BUFFER_SIZE 16384\r\n//\t\t\t\tchar readBuffer[BUFFER_SIZE];\r\n//\t\t\t\tif ( toread > BUFFER_SIZE )\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// Read a full buffer.\r\n//\t\t\t\t\tFile::Read( readBuffer, 1, BUFFER_SIZE, p_file );\r\n//\t\t\t\t\ttoread -= BUFFER_SIZE;\r\n//\t\t\t\t\toffset += BUFFER_SIZE;\r\n//\t\t\t\t\tNsDMA::toARAM( vagAddr + offset, readBuffer, BUFFER_SIZE );\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// Last chunk\r\n//\t\t\t\t\tFile::Read( readBuffer, 1, toread, p_file );\r\n//\t\t\t\t\tNsDMA::toARAM( vagAddr + offset, readBuffer, ( toread + 31 ) & ~31 );\r\n//\t\t\t\t\ttoread = 0;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\r\n\r\n\t\t\tNsDMA::toARAM( vagAddr, p_data + 96, data_size );\r\n\t\r\n\t\t\tpInfo->headerAddress\t= p_header_copy;\r\n\t\t\tpInfo->vagAddress\t\t= vagAddr;\r\n\t\t\tpInfo->looping\t\t\t= ( p_header->loop_flag > 0 );\r\n\t\r\n\t\t\t// Figure pitch adjustment coefficient.\r\n\t\t\tif( samplePitch )\r\n\t\t\t{\r\n\t\t\t\t*samplePitch = ( (float)p_header->sample_rate * 100.0f ) / 32000.0f;\r\n\t\t\t}\r\n\t\r\n\t\t\t// Release main RAM version of data.\r\n\t\t\tMem::Free( p_data );\r\n\t\r\n\t\t\trv = true;\r\n\t\t}\r\n\t\tFile::Close( p_file );\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tOSReport( 0, \"************ failed to load sound: %s\\n\", filename );\r\n//\t\twhile ( 1== 1 );\r\n\t\t//Dbg_MsgAssert( 0, ( \"failed to load sound: %s\\n\", filename ));\r\n\t}\r\n\treturn rv;\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid GetStreamBufferInfo( int* stream0_base, int* stream1_base, int* stream2_base,\r\n\t\t\t\t\t\t  int* stream0_size, int* stream1_size, int* stream2_size )\r\n{\r\n\t*stream0_base\t= NxNgc::EngineGlobals.aram_stream0;\r\n\t*stream0_size\t= aram_stream0_size;\r\n\t*stream1_base\t= NxNgc::EngineGlobals.aram_stream1;\r\n\t*stream1_size\t= aram_stream1_size;\r\n\t*stream2_base\t= NxNgc::EngineGlobals.aram_stream2;\r\n\t*stream2_size\t= aram_stream2_size;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PerFrameUpdate( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid InitSoundFX( CSfxManager *p_manager )\r\n{\r\n\t// Initialize the 'voice' array.\r\n\tfor( int i = 0; i < NUM_VOICES; ++i )\r\n\t{\r\n\t\tVoiceSimulator[i].p_axvpb = NULL;\r\n\t}\r\n\r\n\t// See whether the unit is in mono or stereo mode.\r\n\tisStereo = !( OSGetSoundMode() == OS_SOUND_MODE_MONO );\r\n\r\n\t// Initialize Audio Interface API.\r\n//\tAIInit( NULL );\r\n\r\n\t// Initialize the AX library, and boot the DSP.\r\n//\tAXInit();\r\n\r\n\t// Set the callback responsible for freeing up voices.\r\n\tAXRegisterCallback( AXUserCBack );\r\n\r\n\t// Zero first 1024 bytes of ARAM - this is where one-shot sounds will end up when they finish.\r\n#\tif aram_zero_size != 1024\r\n#\terror aram zero buffer size has changed\r\n#\tendif\r\n\t\r\n\tchar reset_buffer[1024];\r\n\tmemset( reset_buffer, 0, 1024 );\r\n\tDCFlushRange( reset_buffer, 1024 );\r\n\tNsDMA::toARAM( NxNgc::EngineGlobals.aram_zero, reset_buffer, 1024 );\r\n\r\n\tCleanUpSoundFX();\r\n\r\n\t// Moved this from sioman.cpp since the pcm stuff for ngc needs the sfx stuff initialised first.\r\n\tPcm::Init();\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid ReInitSoundFX( void )\r\n{\r\n\t// Initialize the 'voice' array.\r\n\tfor( int i = 0; i < NUM_VOICES; ++i )\r\n\t{\r\n\t\tVoiceSimulator[i].p_axvpb = NULL;\r\n\t}\r\n\r\n\t// Flush pending ARQ transfers and wait for DMA to finish.\r\n\tARQFlushQueue();\r\n\twhile( ARGetDMAStatus() != 0 );\r\n\r\n\tAXQuit();\r\n\tAIReset();\r\n\tARQReset();\r\n\tARReset();\r\n\r\n\t// Initialize Audio Interface API.\r\n\tAIInit( NULL );\r\n\r\n\t// Initialize the AX library, and boot the DSP.\r\n\tAXInit();\r\n\r\n\t// Set the callback responsible for freeing up voices.\r\n\tAXRegisterCallback( AXUserCBack );\r\n\r\n#ifndef DVDETH\r\n\tDTKInit();\r\n\tDTKSetRepeatMode( DTK_MODE_NOREPEAT );\r\n#endif\t\t// DVDETH\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool VoiceIsOn( int whichVoice )\r\n{\r\n\tif( VoiceSimulator[whichVoice].p_axvpb != NULL )\r\n\t{\r\n\t\t// Check it hasn't already been stopped since then it will be dealt with by the 5ms callback.\r\n//\t\tif( VoiceSimulator[whichVoice].p_axvpb->pb.state != AX_PB_STATE_STOP )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//void SetVoiceParameters( int voiceNumber, float volL, float volR, float fPitch )\r\nvoid\tSetVoiceParameters( int whichVoice, sVolume *p_vol, float pitch )\r\n{\r\n\tunsigned int rpitch = UNALTERED_PITCH;\r\n\tif( pitch != 0.0f )\r\n\t{\r\n\t\trpitch = (unsigned int)PERCENT( UNALTERED_PITCH, pitch );\r\n\t\tif ( rpitch > MAX_PITCH )\r\n\t\t\trpitch = MAX_PITCH;\r\n\t\tif ( rpitch <= 0 )\r\n\t\t\trpitch = 1;\r\n\t}\r\n\t\r\n\tint old = OSDisableInterrupts();\r\n\tif( VoiceSimulator[whichVoice].p_axvpb )\r\n\t{\r\n\t\tAXPB* p_pb = &( VoiceSimulator[whichVoice].p_axvpb->pb );\r\n//\t\tPcm::setDolby( p_pb, VoiceSimulator[voiceNumber].p_axvpb, volL, volR, pitch, true, gSfxVolume );\r\n\t\t//Pcm::setDolby( p_pb, VoiceSimulator[whichVoice].p_axvpb, p_vol->GetChannelVolume( 0 ), p_vol->GetChannelVolume( 1 ), rpitch, true, gSfxVolume );\r\n\t\tif ( p_vol )\r\n\t\t{\r\n\t\t\tPcm::setDolby( p_pb, VoiceSimulator[whichVoice].p_axvpb, p_vol->GetChannelVolume( 0 ), p_vol->GetChannelVolume( 1 ), rpitch, true, gSfxVolume );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tPcm::setDolby( p_pb, VoiceSimulator[whichVoice].p_axvpb, 0.0f, 0.0f, rpitch, true, gSfxVolume );\r\n\t\t}\r\n\t}\r\n\tOSRestoreInterrupts( old );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool LoadSoundPlease( const char *sfxName, uint32 checksum, PlatformWaveInfo *pInfo, bool loadPerm )\r\n{\r\n\tDbg_Assert( pInfo );\r\n\r\n\t// Need to append file type. Copy string into a buffer.\r\n\tstatic char name_buffer[256] = \"sounds\\\\dsp\\\\\";\r\n\tconst int SOUND_PREPEND_START_POS = 11;\r\n\r\n\t// Check there is room to add the extension.\r\n\tint length = strlen( sfxName );\r\n\tDbg_Assert( strlen( sfxName ) <= ( 256 - ( SOUND_PREPEND_START_POS + 4 )));\r\n\tstrcpy( name_buffer + SOUND_PREPEND_START_POS, sfxName );\r\n\tstrcpy( name_buffer + SOUND_PREPEND_START_POS + length, \".dsp\" );\r\n\r\n//\tOSReport( \"Loading sound: %s\\n\", name_buffer );\r\n\r\n\tloadGamecubeDSP( pInfo, name_buffer, loadPerm, &pInfo->pitchAdjustmentForSamplingRate );\r\n\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//int PlaySoundPlease( PlatformWaveInfo *pInfo, float volL, float volR, float pitch )\r\nint PlaySoundPlease( PlatformWaveInfo *pInfo, sVolume *p_vol, float pitch )\r\n{\r\n\t//Dbg_Assert( pInfo->headerAddress != NULL );\r\n\t\r\n//\tSpt::SingletonPtr< Sfx::CSfxManager > sfx_manager;\r\n//\tif ( sfx_manager->GetMainVolume() < 1.0f ) return -1;\r\n\r\n\tint voice = getFreeVoice();\r\n\tif( voice == -1 )\r\n\t{\r\n\t\t// No voice in our array available.\r\n\t\treturn -1;\r\n\t}\r\n\r\n\t// Attempt to grab a voice. Set the priority high if it is a looping sound.\r\n\tsDSPADPCM*\tp_header\t= (sDSPADPCM*)pInfo->headerAddress;\r\n\t// HACK!!!\r\n\tif( !p_header )\r\n\t{\r\n\t\t// No voice available.\r\n\t\treturn -1;\r\n\t}\r\n\tAXVPB*\t\tp_axvpb\t\t= AXAcquireVoice( ( p_header->loop_flag ) ? AX_PRIORITY_NODROP : AX_PRIORITY_LOWEST, ax_voice_reacquisition_callback, 0 );\r\n\tif( p_axvpb == NULL )\r\n\t{\r\n\t\t// No voice available.\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tAXPBADDR\t\taddr;\r\n\tAXPBSRC\t\t\tsrc;\r\n\tAXPBADPCM\t\tadpcm;\r\n\tAXPBADPCMLOOP\tloop;        \r\n\r\n\taddr.loopFlag           = p_header->loop_flag ? AXPBADDR_LOOP_ON : AXPBADDR_LOOP_OFF;\r\n\taddr.format             = AX_PB_FORMAT_ADPCM;   \r\n\r\n\t// Convert from byte to nibble address, and split into low and high words.\r\n\tu32 start_address\t\t= ( pInfo->vagAddress * 2 ) + 2;\r\n\tu32 end_address\t\t\t= ( pInfo->vagAddress * 2 ) + ( p_header->num_adpcm_nibbles - 1 );\r\n\r\n\taddr.currentAddressHi   = (u16)( start_address >> 16 );\r\n\taddr.currentAddressLo   = (u16)( start_address & 0xFFFFU );\r\n\taddr.endAddressHi\t\t= (u16)( end_address >> 16 );\r\n\taddr.endAddressLo\t\t= (u16)( end_address & 0xFFFFU );\r\n\r\n\tif( p_header->loop_flag )\r\n\t{\r\n\t\taddr.loopAddressHi      = (u16)( start_address >> 16 );\r\n\t\taddr.loopAddressLo      = (u16)( start_address & 0xFFFFU );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tu32 zero_buffer_address\t= NxNgc::EngineGlobals.aram_zero * 2;\r\n\t\taddr.loopAddressHi      = (u16)( zero_buffer_address >> 16 );\r\n\t\taddr.loopAddressLo      = (u16)( zero_buffer_address & 0xFFFFU );\r\n\t}\r\n\r\n\tloop.loop_pred_scale    = p_header->lps;\r\n\tloop.loop_yn1           = p_header->lyn1;\r\n\tloop.loop_yn2           = p_header->lyn2;\r\n\r\n//\tuint32 srcBits\t\t\t= (uint32)(0x00010000 * ((f32)p_header->sample_rate / AX_IN_SAMPLES_PER_SEC));\r\n//\tsrc.ratioHi\t\t\t\t= (u16)(srcBits >> 16);\r\n//\tsrc.ratioLo\t\t\t\t= (u16)(srcBits & 0xFFFF);\r\n\tsrc.ratioHi             = 1;\r\n\tsrc.ratioLo             = 0;\r\n\tsrc.currentAddressFrac  = 0;\r\n\tsrc.last_samples[0]     = 0;\r\n\tsrc.last_samples[1]     = 0;\r\n\tsrc.last_samples[2]     = 0;\r\n\tsrc.last_samples[3]     = 0;\r\n\r\n\tmemcpy( &adpcm.a[0][0], p_header->coef, sizeof( u16 ) * 16 );\r\n\tadpcm.gain              = p_header->gain;\r\n\tadpcm.pred_scale        = p_header->ps;\r\n\tadpcm.yn1               = p_header->yn1;\r\n\tadpcm.yn2               = p_header->yn2;\r\n\r\n\tAXPBVE ve;\r\n\tve.currentVolume\t\t= 0x7FFF;\t\t\t\t\t// This is max volume.\r\n\tve.currentDelta\t\t\t= 0x0000;\r\n\r\n\tAXSetVoiceType( p_axvpb, AX_PB_TYPE_NORMAL );\r\n\t\r\n\tAXSetVoiceAddr( p_axvpb, &addr );                   // input addressing\r\n\tAXSetVoiceAdpcm( p_axvpb, &adpcm );                 // ADPCM coefficients\r\n\tAXSetVoiceAdpcmLoop( p_axvpb, &loop );              // ADPCM loop context\r\n\r\n\tAXSetVoiceVe( p_axvpb, &ve );\r\n\t\r\n\tAXSetVoiceSrcType( p_axvpb, AX_SRC_TYPE_LINEAR );   // SRC type\r\n\tAXSetVoiceSrc( p_axvpb, &src );                     // initial SRC settings\r\n\r\n\t// Set the voice to run.\r\n\tAXSetVoiceState( p_axvpb, AX_PB_STATE_RUN );        \r\n\t\r\n\t// Fill in voice details.\r\n\tVoiceSimulator[voice].p_axvpb\t\t=  p_axvpb;\r\n\tVoiceSimulator[voice].p_dspadpcm\t=  p_header;\r\n//\tOSReport( \"voice %d started %d\\n\", voice, OSGetTick() );\r\n\r\n\t// Adjust pitch to account for lower sampling rates:\r\n\tpitch = PERCENT( pitch, pInfo->pitchAdjustmentForSamplingRate );\r\n\r\n\t// This takes the place of AxSetVoiceMix().\r\n\tSetVoiceParameters( voice, p_vol, pitch );\r\n\t\r\n\treturn voice;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid StopSoundPlease( int whichVoice )\r\n{\r\n\tif( VoiceIsOn( whichVoice ))\r\n\t{\r\n\t\tAXSetVoiceState( VoiceSimulator[whichVoice].p_axvpb, AX_PB_STATE_STOP );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid StopAllSoundFX( void )\r\n{\r\n//\tPcm::StopMusic();\r\n//\tPcm::StopStreams();\r\n\r\n\tfor( int i = 0; i < NUM_VOICES; i++ )\r\n\t{\r\n\t\tStopSoundPlease( i );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SetVolumePlease( float volumeLevel )\r\n{\r\n\t// Sets master volume level.\r\n\tgSfxVolume = volumeLevel;\r\n\r\n//\tPcm::PCMAudio_SetStreamGlobalVolume( ( unsigned int ) volumeLevel );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid PauseSoundsPlease( void )\r\n{\r\n//\tsVolume silent_vol;\r\n//\tsilent_vol.SetSilent();\r\n\r\n\t// Just turn the volume down on all playing voices.\r\n\tfor( int i = 0; i < NUM_VOICES; i++ )\r\n\t{\r\n\t\tif( VoiceIsOn( i ))\r\n\t\t{\r\n//\t\t\tSetVoiceParameters( i, 0.0f, 0.0f );\r\n//\t\t\tSetVoiceParameters( i, &silent_vol );\r\n\t\t\tSetVoiceParameters( i, NULL );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CleanUpSoundFX( void )\r\n{\r\n\tStopAllSoundFX();\r\n\tSpuRAMUsedTemp = 0;\r\n\tSetReverbPlease( 0 );\r\n\r\n\tfor( int i = 0; i < numTempSoundHeaders; ++i )\r\n\t{\r\n\t\tDbg_Assert( tempSoundHeaders[i] );\r\n\t\tMem::Free( tempSoundHeaders[i] );\r\n\t\ttempSoundHeaders[i] = NULL;\r\n\t}\r\n\tnumTempSoundHeaders = 0;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n// Macros and constants:\r\n\r\nint ReverbModes[ ] =\r\n{\r\n\t// put the default first in this list, since the default param to SetReverb() is 0\r\n\t0,\r\n//\tSD_REV_MODE_HALL,\r\n//\tSD_REV_MODE_ROOM,\r\n//\tSD_REV_MODE_STUDIO_A,\r\n//\tSD_REV_MODE_STUDIO_B,\r\n//\tSD_REV_MODE_STUDIO_C,\r\n//\tSD_REV_MODE_SPACE,\r\n//\tSD_REV_MODE_ECHO,\r\n//\tSD_REV_MODE_DELAY,\r\n//\tSD_REV_MODE_PIPE,\r\n};\r\n\r\n#define NUM_REVERB_MODES ( ( int )( sizeof( ReverbModes ) / sizeof( int ) ) )\r\n\r\n#if NUM_STREAMS > 3\r\n#error tell matt to handle more than 3 streams in sfx.cpp\r\n#endif\r\n\r\n#if NUM_STREAMS == 3\r\n#define VOICES_MINUS_STREAMS ( 0xFFFFFF & ~( ( 1 << STREAM_VOICE( 0 ) | ( 1 << STREAM_VOICE( 1 ) ) | ( 1 << STREAM_VOICE( 2 ) ) ) )\r\n#else\r\n#define VOICES_MINUS_STREAMS ( 0xFFFFFF & ~( ( 1 << MUSIC_L_VOICE ) | ( 1 << MUSIC_R_VOICE ) ) )\r\n#endif\r\n\r\n// convert sample rate to pitch setting\r\n#define FREQ2PITCH( x ) ( ( float )( ( ( x ) * 100 ) / 48000 ) )\r\n\r\n#define DMA_CH\t\t\t\t\t\t0\r\n\r\n#if ( ( CORE_0_EFFECTS_END_ADDRESS - CORE_0_EFFECTS_START_ADDRESS ) < ( RAM_NEEDED_FOR_EFFECTS ) )\r\n#error \"not enough room for effects\"\r\n#endif\r\n\r\n//int LoopingSounds[ NUM_CORES ];\r\n// gotta keep track of voices used, to be able\r\n// to tell whether a voice is free or not...\r\n//int VoicesUsed[ NUM_CORES ];\r\n\r\n// avoid checking voice status more than once per frame:\r\n//uint64\tgLastVoiceAvailableUpdate[ NUM_CORES ];\r\n//int\t\tgAvailableVoices[ NUM_CORES ];\r\n\r\n\r\n#define BLOCKHEADER_LOOP_BIT\t( 1 << 9 )\r\n\r\n// Internal function prototypes:\r\n\r\nstatic bool\tloadGamecubeDSP( PlatformWaveInfo *pInfo, const char *filename, bool loadPerm, float *samplePitch = NULL );\r\n\r\nint\t\tPS2Sfx_PlaySound( PlatformWaveInfo *pInfo, int voiceNumber, float volL = 100.0f, float volR = 100.0f, float pitch = 100.0f );\r\nvoid\tPS2Sfx_StopSound( int voiceNumber );\r\nint\t\tPS2Sfx_GetVoiceStatus( int core );\r\n\r\n#define ALLIGN_REQUIREMENT\t64 // EE to IOP\r\n#define SIZE_OF_LEADIN\t\t16\r\n#define USE_CLEVER_TRICK_FOR_CLOBBERED_DATA\t\t1\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n// IOP_MIN_TRANSFER must be a power of 2!!!\r\n#define IOP_MIN_TRANSFER\t64\t// iop will clobber memory if you're writing above a sound.  we'll restore the\r\n\t\t\t\t\t\t\t\t// potentially clobbered memory by keeping a buffer containing the beginning of\r\n\t\t\t\t\t\t\t\t// the previously loaded perm sound, and copying that to the end of our new\r\n\t\t\t\t\t\t\t\t// data...\r\n\r\n#if USE_CLEVER_TRICK_FOR_CLOBBERED_DATA\r\n#define\t\tPAD_TO_PREVENT_CLOBBERING\t\t0\r\n#else\r\n#define\t\tPAD_TO_PREVENT_CLOBBERING\t\t64\r\n#endif\r\n\r\n#define FULL_NAME_SIZE\t\t256\r\n\r\n\r\n\r\n\r\n\r\nint GetMemAvailable( void )\r\n{\r\n\treturn ( MAX_SPU_RAM_AVAILABLE - ( SpuRAMUsedTemp + SpuRAMUsedPerm ) );\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// Function: void SetReverb(void)\r\n// Description: Sets reverb level and type\r\n// Parameters:  none\r\n//\r\n// Returns:\r\n//-------------------------------------------------------------------------------------------\r\nvoid SetReverbPlease( float reverbLevel, int reverbMode, bool instant = false )\r\n{\r\n//\tint i;\r\n//\tsceSdEffectAttr r_attr;\r\n//\r\n//\tDbg_MsgAssert( reverbType >= 0,( \"Bad reverb mode.\" ));\r\n//\tDbg_MsgAssert( reverbType < NUM_REVERB_MODES,( \"Bad reverb mode...\" ));\r\n//\t\r\n//\tif ( !reverbLevel )\r\n//\t{\r\n//\t\t// --- set reverb attribute\r\n//\t\tr_attr.depth_L  = 0;\r\n//\t\tr_attr.depth_R  = 0;\r\n//\t\tr_attr.delay    = 0;\r\n//\t\tr_attr.feedback = 0;\r\n//\t\tr_attr.mode = SD_REV_MODE_OFF;\r\n//#if REVERB_ONLY_ON_CORE_0\r\n//\t\ti = 0;  // just set reverb on core 0 (not the music core or any sfx on core 1)\r\n//#else\r\n//\t\tfor ( i = 0; i < 2; i++ )\r\n//#endif\r\n//\t\t{\r\n//\t\t\t// just turning off reverb on all voices...\r\n//\t\t\tif(sceSdRemote( 1, rSdSetSwitch, i | SD_S_VMIXEL , 0 ) == -1 )\r\n//\t\t\t\tDbg_Message(\"Error setting reverb4\\n\");\r\n//\t\t\tif(sceSdRemote( 1, rSdSetSwitch, i | SD_S_VMIXER , 0 ) == -1 )\r\n//\t\t\t\tDbg_Message(\"Error setting reverb5\\n\");\r\n//\t\t\tif( sceSdRemote( 1, rSdSetEffectAttr, i, &r_attr ) == -1 )\r\n//\t\t\t\tDbg_Message( \"Error setting reverb\\n\" );\r\n//\t\t}\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tint reverbDepth = ( int )PERCENT( MAX_REVERB_DEPTH, reverbLevel );\r\n//\t\t\r\n//\t\t// --- set reverb attribute\r\n//\t\tr_attr.depth_L  = 0x3fff;\r\n//\t\tr_attr.depth_R  = 0x3fff;\r\n//\t\tr_attr.delay    = 30;\r\n//\t\tr_attr.feedback = 200;\r\n//\t\tr_attr.mode = ReverbModes[ reverbType ];\r\n//#if REVERB_ONLY_ON_CORE_0\r\n//\t\ti = 0;\r\n//#else\t\t\r\n//\t\tfor( i = 0; i < 2; i++ )\r\n//#endif\r\n//\t\t{\r\n//\t\t\tif( sceSdRemote( 1, rSdSetEffectAttr, i, &r_attr ) == -1 )\r\n//\t\t\t\tDbg_Message( \"Error setting reverb\\n\" );\r\n//\t\r\n//\t\t\tif(sceSdRemote( 1, rSdSetCoreAttr, i | SD_C_EFFECT_ENABLE, 1 ) == -1 )\r\n//\t\t\t\tDbg_Message(\"Error setting reverb\\n\");\r\n//\t\t\tif(sceSdRemote( 1, rSdSetParam, i | SD_P_EVOLL , reverbDepth ) == -1 )\r\n//\t\t\t\tDbg_Message(\"Error setting reverb2\\n\");\r\n//\t\t\tif(sceSdRemote( 1, rSdSetParam, i | SD_P_EVOLR , reverbDepth ) == -1 )\r\n//\t\t\t\tDbg_Message(\"Error setting reverb3\\n\");;\r\n//\t\t\tif(sceSdRemote( 1, rSdSetSwitch, i | SD_S_VMIXEL , VOICES_MINUS_STREAMS ) == -1 )\r\n//\t\t\t\tDbg_Message(\"Error setting reverb4\\n\");\r\n//\t\t\tif(sceSdRemote( 1, rSdSetSwitch, i | SD_S_VMIXER , VOICES_MINUS_STREAMS ) == -1 )\r\n//\t\t\t\tDbg_Message(\"Error setting reverb5\\n\");\r\n//\t\t\t\r\n//\t\t}\r\n//\t}\r\n} // end of SetReverb( )\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n} // namespace Sfx\r\n"
  },
  {
    "path": "Code/Gel/SoundFX/ngc/p_sfx.h",
    "content": "/*\tPlaystation 2 sound support functions.\r\n\tmjd\tjan 10, 2001\r\n*/\r\n#ifndef __MODULES_P_SFX_H\r\n#define __MODULES_P_SFX_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n// Need to include this to get NUM_STREAMS.\r\n#include <gel/music/ngc/pcm/pcm.h>\r\n\r\nnamespace Sfx\r\n{\r\n\t\t  \r\n#define NUM_MUSIC_VOICES\t\t2\r\n#define NUM_VOICES\t\t\t\t( 64 - NUM_STREAMS - NUM_MUSIC_VOICES ) // leave some voices per core for streaming audio off the CD and shit...\r\n\r\nstruct sVolume;\r\n\r\n// platform specific info needed per wave (stored in the WaveTable):\r\nstruct PlatformWaveInfo\r\n{\r\n\tint\t\tvagAddress;\t\t// PS2 waves played by setting a voice to the address of the wave on the sound chip...\t\r\n\tvoid*\theaderAddress;\t// Main memory location of header information.\r\n\tbool\tlooping;\r\n\tfloat\tpitchAdjustmentForSamplingRate; // figure out how much to alter the pitch due to lower sampling rates than 48000.\r\n};\r\n\r\nvoid\tGetStreamBufferInfo( int* stream0_base, int* stream1_base, int* stream2_base, int* stream0_size, int* stream1_size, int* stream2_size );\r\nclass\tCSfxManager;\r\n\r\n// on startup of the game only...\r\nvoid PS2Sfx_InitCold( void );\r\n\r\nvoid\tAXUserCBack( void );\r\n\r\n\r\nvoid\tInitSoundFX( CSfxManager *p_sfx_manager );\r\nvoid\tReInitSoundFX( void );\r\nvoid\tCleanUpSoundFX( void );\r\nvoid\tStopAllSoundFX( void );\r\nbool\tLoadSoundPlease( const char *sfxName, uint32 checksum, PlatformWaveInfo *pInfo, bool loadPerm = 0 );\r\n\r\nint\t\tGetMemAvailable( void );\r\n\r\n// returns 0 - ( NUM_VOICES - 1 ), or -1 if no voices are free...\r\n//int\t\tPlaySoundPlease( PlatformWaveInfo *pInfo, float volL = 100.0f, float volR = 100.0f, float pitch = 100.0f );\r\nint\t\tPlaySoundPlease( PlatformWaveInfo *pInfo, sVolume *p_vol, float pitch = 100.0f );\r\n\r\nvoid\tStopSoundPlease( int whichVoice );\r\n\r\nextern bool\tisStereo;\r\n\r\n// really just turning down the volume on all playing voices...\r\n// Looping sounds will get the volume adjusted by the owner\r\n// during the next logic loop.\r\n// The non-looping sounds will play (with no volume) then stop.\r\n// This is for when we go into the menus or whatnot...\r\nvoid\tPauseSoundsPlease( void );\r\n\r\n// see reverb types in ReverbModes table (p_sfx.cpp), corresponding to reverb.q script file\r\nvoid\tSetReverbPlease( float reverbLevel = 0.0f, int reverbMode = 0, bool instant = false );\r\n\r\n// volume from -100 to 100 ( negative if the sound is from behind us. ps2 alters the sound... )\r\nvoid\tSetVolumePlease( float volumeLevel );\r\n\r\n// returns true if voice is being used currently.\r\nbool\tVoiceIsOn( int whichVoice );\r\n\r\n// change parameters on an active voice:\r\n// if pitch parameter is zero, pitch won't be changed (lowest pitch is 1)\r\n//void\tSetVoiceParameters( int whichVoice, float volL, float volR, float pitch = 0.0f );\r\nvoid\tSetVoiceParameters( int whichVoice, sVolume *p_vol, float pitch = 0.0f );\r\n\r\nvoid\tPerFrameUpdate( void );\r\n\r\n\r\n} // namespace Gel\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gel/SoundFX/soundfx.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSound effects (Sfx)\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsoundfx.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t01/10/01\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSoundFX for the game. These are the sounds that are\t\t**\r\n**\t\t\t\t\tloaded into memory. Streaming SoundFX are in the Music\t**\r\n**\t\t\t\t\tmodules (music.cpp and p_music.cpp) which should\t\t**\r\n**\t\t\t\t\tactually be called the Streaming module.\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gfx/nxviewman.h>\r\n#include <gfx/nxloadscreen.h>\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/music/music.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <modules/frontend/frontend.h>  // until gametimer is moved into lower level stuff..\r\n\r\n#include <sys/config/config.h>\r\n#include <sys/replay/replay.h>\r\n\r\n#include <gel/components/soundcomponent.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/moviecam.h>\r\n#include <sk/objects/movingobject.h>\r\n\r\n// Used by the script debugger code to fill in a structure\r\n// for transmitting to the monitor.exe utility running on the PC.\r\nvoid ObjectSoundInfo::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to ObjectSoundInfo::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddChecksum(\"checksum\",checksum);\r\n\tp_info->AddFloat(\"dropoffDist\",dropoffDist);\r\n\tp_info->AddFloat(\"currentPitch\",currentPitch);\r\n\tp_info->AddFloat(\"currentVolume\",currentVolume);\r\n\tp_info->AddFloat(\"origPitch\",origPitch);\r\n\tp_info->AddFloat(\"origVolume\",origVolume);\r\n\tp_info->AddFloat(\"targetPitch\",targetPitch);\r\n\tp_info->AddFloat(\"targetVolume\",targetVolume);\r\n\tp_info->AddFloat(\"deltaPitch\",deltaPitch);\r\n\tp_info->AddFloat(\"deltaVolume\",deltaVolume);\r\n\tp_info->AddInteger(\"timeForNextDistCheck\",timeForNextDistCheck);\r\n#endif\t\t\t\t \r\n}\r\n\r\nnamespace Sfx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool NoSoundPlease( void )\r\n{\r\n#\tif NO_SOUND_PLEASE\r\n\treturn true;\r\n#\telse\r\n\t// Cannot have sound if building for proview, because there is not enough IOP memory\r\n\t// (ProView uses up some IOP memory with it's monitor)\r\n\tif( Config::GetHardware() == Config::HARDWARE_PS2_PROVIEW )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n#\tendif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nEDropoffFunc\tGetDropoffFunctionFromChecksum(uint32 checksum)\r\n{\r\n\tswitch (checksum)\r\n\t{\r\n\tcase 0xef082878: // standard\r\n\t\treturn DROPOFF_FUNC_STANDARD;\r\n\r\n\tcase 0xf221474c: // linear\r\n\t\treturn DROPOFF_FUNC_LINEAR;\r\n\r\n\tcase 0x9706104b: // exponential\r\n\t\treturn DROPOFF_FUNC_EXPONENTIAL;\r\n\r\n\tcase 0xca64c41: // inv_exponential\r\n\t\treturn DROPOFF_FUNC_INV_EXPONENTIAL;\r\n\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0, (\"Invalid dropoff function type %s (%x)\", Script::FindChecksumName(checksum), checksum));\r\n\t\treturn DROPOFF_FUNC_STANDARD;\r\n\t}\r\n}\r\n\r\n\r\n\r\nDefineSingletonClass( CSfxManager, \"Sound FX\" );\r\n\r\nstatic float\tDefaultDropoffDist = DEFAULT_DROPOFF_DIST;\r\n\r\n\r\nVoiceInfo\t\tVoiceInfoTable[NUM_VOICES];\r\n\r\n// The entries will be permanent entries, followed by temporary entries...\r\nWaveTableEntry\tWaveTable[PERM_WAVE_TABLE_MAX_ENTRIES + WAVE_TABLE_MAX_ENTRIES];\r\n\r\n// This structure is used on sounds that aren't looping, but are long enough that they need to be updated for\r\n// volume and pan (like the things pedestrians are saying to each other for example).\r\nstruct PositionalSoundEntry\r\n{\r\n\tint\t\t\t\t\t\t\tuniqueID;\r\n\tuint32\t\t\t\t\t\tchecksum;\r\n\tuint32\t\t\t\t\t\tflags;\r\n\tObj::CSoundComponent\t\t\t\t*pObj;\r\n\tstruct PositionalSoundEntry\t*pNext;\r\n\tstruct PositionalSoundEntry\t*pPrev;\r\n};\r\n\r\n#define POSITIONAL_SOUND_FLAG_OCCUPIED\t( 1 << 0 )\r\n#define POSITIONAL_SOUND_FLAG_DOPPLER\t( 1 << 1 )\r\n\r\nstatic PositionalSoundEntry\t\t\t\t*GpPositionalSounds = NULL;\r\nstatic PositionalSoundEntry\t\t\t\tPositionalSounds[MAX_POSITIONAL_SOUNDS];\r\n\r\nint\t\t\t\t\t\t\t\t\t\tNumWavesInTable\t\t= 0;\r\nint\t\t\t\t\t\t\t\t\t\tNumWavesInPermTable\t= 0;\r\nint\t\t\t\t\t\t\t\t\t\tNumPositionalSounds = 0;\r\nfloat\t\t\t\t\t\t\t\t\tgVolume\t\t\t\t= 100.0f;\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsVolume::sVolume( void )\r\n{\r\n\t// Set the volume type to be the default volume type of the manager.\r\n\tSfx::CSfxManager * p_manager = Sfx::CSfxManager::Instance();\r\n\tif( p_manager )\r\n\t{\r\n\t\tm_volume_type = p_manager->GetDefaultVolumeType();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_volume_type = VOLUME_TYPE_BASIC_2_CHANNEL;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsVolume::sVolume( EVolumeType type )\r\n{\r\n\tm_volume_type = type;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsVolume::sVolume( const sVolume& rhs )\r\n{\r\n\tm_volume_type = rhs.m_volume_type;\r\n\t\r\n\tuint32 num_channels = ( m_volume_type == VOLUME_TYPE_5_CHANNEL_DOLBY5_1 ) ? 5 : 2;\r\n\tfor( uint32 c = 1; c < num_channels; ++c )\r\n\t{\r\n\t\tm_channels[c] = rhs.m_channels[c];\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsVolume::~sVolume( void )\r\n{\r\n}\r\n\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sVolume::PercentageAdjustment( float percentage )\r\n{\r\n\tuint32 num_channels = ( m_volume_type == VOLUME_TYPE_5_CHANNEL_DOLBY5_1 ) ? 5 : 2;\r\n\tfor( uint32 c = 0; c < num_channels; ++c )\r\n\t{\r\n\t\tm_channels[c] = PERCENT( m_channels[c], percentage );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nfloat sVolume::GetLoudestChannel( void )\r\n{\r\n\tfloat loudest = m_channels[0];\r\n\t\r\n\tuint32 num_channels = ( m_volume_type == VOLUME_TYPE_5_CHANNEL_DOLBY5_1 ) ? 5 : 2;\r\n\tfor( uint32 c = 1; c < num_channels; ++c )\r\n\t{\r\n\t\t// Allow for phase shifting, which would make a channel negative.\r\n\t\tif( fabsf( m_channels[c] ) > fabsf( loudest ))\r\n\t\t\tloudest = m_channels[c];\r\n\t}\r\n\treturn loudest;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool sVolume::IsSilent( void )\r\n{\r\n\t// All volume types have at least two channels.\r\n\tif(( m_channels[0] != 0.0f ) || ( m_channels[1] != 0.0f ))\r\n\t\treturn false;\r\n\t\r\n\t// Check remaining channels for 5.1 type volumes.\r\n\tif( m_volume_type == VOLUME_TYPE_5_CHANNEL_DOLBY5_1 )\r\n\t{\r\n\t\tif(( m_channels[2] != 0.0f ) || ( m_channels[3] != 0.0f ) || ( m_channels[4] != 0.0f ))\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sVolume::SetSilent( void )\r\n{\r\n\t// Strictly speaking, we only need to set as many channels silent as the type\r\n\t// of the volume requires, but it's probably no less efficient to do it this way.\r\n\tmemset( m_channels, 0, sizeof( float ) * MAX_CHANNELS );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool sVolume::operator== ( const sVolume& rhs )\r\n{\r\n\tif (m_volume_type != rhs.m_volume_type)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tuint32 num_channels = ( m_volume_type == VOLUME_TYPE_5_CHANNEL_DOLBY5_1 ) ? 5 : 2;\r\n\tfor( uint32 c = 1; c < num_channels; ++c )\r\n\t{\r\n\t\tif (m_channels[c] != rhs.m_channels[c])\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCSfxManager::CSfxManager( void )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn;\r\n\r\n\t// Set the default volume type to the most basic available - platform specific code\r\n\t// may override this.\r\n\tSetDefaultVolumeType( VOLUME_TYPE_BASIC_2_CHANNEL );\r\n\r\n\tInitSoundFX( this );\r\n\r\n\t// Clear out the uniqueID table. Only has to be done once (even if module is reset).\r\n\tfor( int i = 0; i < NUM_VOICES; i++ )\r\n\t{\r\n\t\tVoiceInfoTable[i].uniqueID = 0;\r\n\t\tVoiceInfoTable[i].controlID = 0;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCSfxManager::~CSfxManager( void )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn;\r\n\r\n\tCleanUp();\t\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSfxManager::CleanUp( void )\r\n{\r\n\t// Call this at the end of a level (or the beginning of the next level before loading sounds, or both).\r\n\tif( NoSoundPlease())\r\n\t\treturn;\r\n\r\n\tGpPositionalSounds\t= NULL;\r\n\tNumPositionalSounds\t= 0;\r\n\tfor( int i = 0; i < MAX_POSITIONAL_SOUNDS; i++ )\r\n\t{\r\n\t\tPositionalSounds[i].flags = 0;\r\n\t}\r\n\t\r\n\t// Should stop all sounds and do whatever cleanup necessary so soundfx can be used in the next phase\r\n\t// (next level, frontend, whatever).\r\n\tCleanUpSoundFX();\r\n\r\n\tNumWavesInTable\t\t= 0;\r\n\tDefaultDropoffDist\t= DEFAULT_DROPOFF_DIST;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSfxManager::IDAvailable(uint32 id)\r\n{\r\n\treturn !SoundIsPlaying(id, NULL);\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CSfxManager::GetVoiceFromID(uint32 id)\r\n{\r\n\tint i;\r\n\r\n\t// Check unique ID's first\r\n\tfor( i = 0; i < NUM_VOICES; i++ )\r\n\t{\r\n\t\tif ((VoiceInfoTable[i].uniqueID == id) && VoiceIsOn(i))\r\n\t\t{\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\r\n\t// Now the control ID's\r\n\tfor( i = 0; i < NUM_VOICES; i++ )\r\n\t{\r\n\t\tif ((VoiceInfoTable[i].controlID == id) && VoiceIsOn(i))\r\n\t\t{\r\n\t\t\tif( Script::GetInteger( 0x6d2e270e /* DebugSoundFxUpdate */, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"Trying to control duplicate sound %s by checksum\", Script::FindChecksumName(id)));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Message(\"ERROR: Trying to control duplicate sound %s by checksum\", Script::FindChecksumName(id));\r\n\t\t\t}\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\r\n\treturn -1;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CSfxManager::GenerateUniqueID(uint32 id)\r\n{\r\n\t// Keep incrementing ID until one works.\r\n\twhile (!IDAvailable(id))\r\n\t\tid++;\r\n\r\n\treturn id;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Different levels might want to have different dropoff\t\t  */\r\n/* distances.\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSfxManager::SetDefaultDropoffDist( float dist )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn;\r\n\r\n\tDbg_MsgAssert( dist > 0.0f, ( \"Can't set dropoff dist to 0 or less.\" ));\r\n\r\n\tDefaultDropoffDist = dist;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSfxManager::StopAllSounds( void )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn;\r\n\t\r\n\tStopAllSoundFX();\r\n\tGpPositionalSounds\t= NULL;\r\n\tNumPositionalSounds\t= 0;\r\n\tfor( int i = 0; i < MAX_POSITIONAL_SOUNDS; i++ )\r\n\t{\r\n\t\tPositionalSounds[i].flags = 0;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSfxManager::PauseSounds( void )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn;\r\n\r\n\tPauseSoundsPlease();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nWaveTableEntry * CSfxManager::GetWaveTableIndex( uint32 checksum )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn NULL;\r\n\r\n\t// Check through list of perm sounds.\r\n\tfor( int i = 0; i < NumWavesInPermTable; i++ )\r\n\t{\r\n\t\tif ( checksum == WaveTable[i].checksum )\r\n\t\t\treturn &WaveTable[i];\r\n\t}\r\n\r\n\t// Check through list of temp sounds.\r\n\tfor( int i = 0; i < NumWavesInTable; i++ )\r\n\t{\r\n\t\tif( checksum == WaveTable[i + PERM_WAVE_TABLE_MAX_ENTRIES].checksum )\r\n\t\t\treturn &WaveTable[i + PERM_WAVE_TABLE_MAX_ENTRIES];\r\n\t}\r\n\r\n\t// Not found.\r\n\treturn NULL;\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CSfxManager::MemAvailable( void )\r\n{\r\n\treturn GetMemAvailable();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSfxManager::PositionalSoundSilenceMode()\r\n{\r\n\t// Add any conditions here where you want to set the positional sound\r\n\t// to 0.\r\n\r\n\t// Don't update if loading screen is active\r\n\tif( Nx::CLoadScreen::sIsActive() )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Don't update if the game is paused\r\n\tif( Mdl::FrontEnd::Instance()->GamePaused() )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n#if 0\t// TT2808: Seemed to cause more problems than it helped.\r\n\t// Don't update if the game is playing a CamAnim\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tif ( skate_mod->GetMovieManager()->IsRolling() )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n#endif\r\n\r\n\t//Dbg_Message(\"Updating sounds frame %d\", Tmr::GetRenderFrame());\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Returns true if sound is still playing.                        */\r\n/* Adjust the pitch for doppler, and the volume and pan for\t\t  */\r\n/* position.\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nbool CSfxManager::AdjustObjectSound( Obj::CSoundComponent *pObj, VoiceInfo *pVoiceInfo, Tmr::Time gameTime )\r\n{\r\n\tDbg_Assert( pVoiceInfo );\r\n\r\n\tObjectSoundInfo *pInfo = &pVoiceInfo->info;\r\n\t\r\n\tfloat dist;\r\n\r\n\t// Get dropoff distance if sent to Obj_PlaySound. If not, get default (set up in LoadSound).\r\n\tfloat dropoffDist = ( pInfo->dropoffDist == 0.0f ) ? DefaultDropoffDist : pInfo->dropoffDist;\r\n\r\n\tGfx::Camera *pCamera = Nx::CViewportManager::sGetClosestCamera( pObj->GetPosition(), &dist );\r\n\tif( !pCamera )\r\n\t{\r\n\t\tDbg_Message( \"Warning: Positional sound, but no camera... Sound won't be updated.\" );\r\n\r\n\t\t// If there is no camera, just don't update the sound but keep it playing the same as before.\r\n\t\t// (If we return false, the object will delete its sound).\r\n\t\t// We might not be able to find the camera at the start of the level or perhaps when changing levels.\r\n\t\treturn true;\r\n\t}\r\n\r\n\tMth::Vector dropoff_pos;\r\n\tMth::Vector *p_dropoff_pos = NULL;\r\n\tif (pObj->GetClosestDropoffPos(pCamera, dropoff_pos))\r\n\t{\r\n\t\tp_dropoff_pos = &dropoff_pos;\r\n\t}\r\n\t// See if the object sound could be turned off (far enough away from the camera).\r\n\telse if( pInfo->timeForNextDistCheck <= gameTime )\r\n\t{\r\n//\t\tDbg_Message( \"checking if we need to turn %s off\", Script::FindChecksumName( pInfo->checksum ) );\r\n\t\tif( dist >= ( dropoffDist + DIST_FROM_DROPOFF_AT_WHICH_TO_STOP_SOUND ))\r\n\t\t{\r\n//\t\t\tDbg_Message( \"sound %s auto off\", Script::FindChecksumName( pInfo->checksum ) );\r\n\r\n\t\t\t// If the sound is looping, let the scripts continue to think the\r\n\t\t\t// sound is still around and keep pitch/volume adjusted for the action.\r\n\t\t\tif( pVoiceInfo->waveIndex->platformWaveInfo.looping )\r\n\t\t\t{\r\n\t\t\t\t// Turn the sound off, monitor the sound from the object update.\r\n\t\t\t\tpObj->SoundOutOfRange( pInfo, gameTime );\r\n\t\t\t}\r\n\r\n\t\t\t// Should cause this sound to be stopped and voice cleared!\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t// Still okay, sound still in range. Continue playing for x more milliseconds.\r\n\t\tpInfo->timeForNextDistCheck = gameTime + 2000;\r\n\t}\r\n\t\r\n\tfloat pitch\t= 100.0f;\r\n\tsVolume vol;\r\n\tvol.SetSilent();\r\n\r\n\t// If dist is beyond dropoff dist, leave volume at zero.\r\n\tif( /*!PositionalSoundSilenceMode() &&*/ ( p_dropoff_pos || (dist < dropoffDist) ) )\r\n\t{\r\n\t\tMth::Vector obj_pos(pObj->GetClosestEmitterPos(pCamera));\r\n\r\n\t\tif( pVoiceInfo->waveIndex->flags & SFX_FLAG_POSITIONAL_UPDATE_WITH_DOPPLER )\r\n\t\t{\r\n\t\t\t// Even if the object didn't move, the camera could have!\r\n\t\t\tAdjustPitchForDoppler( &pitch, obj_pos, pObj->GetClosestOldEmitterPos(pCamera), Tmr::FrameLength(), pCamera );\r\n\t\t}\r\n\t\tSetVolumeFromPos( &vol, obj_pos, dropoffDist, pInfo->dropoffFunction, pCamera, p_dropoff_pos );\r\n\t}\r\n\t\r\n\tif( !Config::CD())\r\n\t{\r\n\t\tif( Script::GetInteger( 0x6d2e270e /* DebugSoundFxUpdate */, Script::NO_ASSERT ) && !vol.IsSilent())\r\n\t\t{\r\n\t\t\tDbg_Message( \"Updating sound %s with volL = %f volR = %f\", Script::FindChecksumName( pInfo->checksum ), vol.GetChannelVolume(0), vol.GetChannelVolume(1));\r\n\t\t}\r\n\t}\t\r\n\r\n\treturn UpdateLoopingSound( pVoiceInfo->uniqueID, &vol, pitch );\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Only updates one sound for frame (since it's slow to send\t  */\r\n/* commands between the EE and the IOP)                           */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nvoid CSfxManager::UpdatePositionalSounds( void )\r\n{\r\n\tPositionalSoundEntry\t*pEntry\t\t= GpPositionalSounds;\r\n\tPositionalSoundEntry\t*pTemp;\r\n\tTmr::Time\t\t\t\tgameTime\t= Tmr::GetTime();\r\n\r\n//\tstatic int\t\t\t\tactive\t\t= 0;\t   // Mick: Only update this one this frame.\r\n//\tint\t\t\t\t\t\tcount\t\t= 0;\t   // Counter for all the sounds.\r\n\r\n//\tuint32 start_time = Tmr::GetTimeInUSeconds();\t\r\n\twhile ( pEntry )\r\n\t{\r\n\t\tpTemp\t= pEntry;\r\n\t\tpEntry\t= pEntry->pNext;\r\n\t\tDbg_MsgAssert( pTemp->flags & POSITIONAL_SOUND_FLAG_OCCUPIED, ( \"Sounds in the list should have 'occupied' turned on.\" ));\r\n\t\t\r\n\t\t// This just filters the current volume/pitch towards the target, and should be done every frame per sound:\r\n\t\tDbg_MsgAssert( pTemp->uniqueID,( \"UniqueID 0 means no sound was played.  Shouldn't have gotten this far.\" ));\r\n\t\r\n\t\tint voiceIndex;\r\n\t\tif( !SoundIsPlaying( pTemp->uniqueID, &voiceIndex ))\r\n\t\t{\r\n\t\t\t// Wasn't a looping sound, and it's done playing.\r\n\t\t\tRemovePositionalSoundFromList( pTemp, false );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tVoiceInfo *pVoiceInfo = &VoiceInfoTable[voiceIndex];\r\n\t\t\tpTemp->pObj->UpdateObjectSound( &pVoiceInfo->info );\r\n\t\t\t\r\n\t\t\t// Only do the low-down nitty gritty positional stuff on one sound per frame.\r\n\t\t\t//if(active == count)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( pTemp->pObj,( \"Null object pointer in positional sound.\" ));\r\n\r\n#\t\t\t\tifdef __USE_PROFILER__\r\n\t\t\t\t//Sys::CPUProfiler->PushContext( 0, 0, 128 );\t\t// blue = this bit of sound code.\r\n#\t\t\t\tendif // __USE_PROFILER__\r\n\t\t\t\t\r\n\t\t\t\tif( !AdjustObjectSound( pTemp->pObj, pVoiceInfo, gameTime ))\r\n\t\t\t\t{\r\n\t\t\t\t\tRemovePositionalSoundFromList( pTemp, true );\r\n\t\t\t\t}\r\n\r\n#\t\t\t\tifdef __USE_PROFILER__\r\n\t\t\t\t//Sys::CPUProfiler->PopContext();\r\n#\t\t\t\tendif // __USE_PROFILER__\r\n\t\t\t}\r\n\t\t}\r\n\t\t//count++;\r\n\t}\r\n\r\n//\tuint32 end_time = Tmr::GetTimeInUSeconds();\t\r\n//\tif ((end_time - start_time) > 250)\r\n//\t\tDbg_Message(\"CSfxManager::UpdatePositionalSounds Frame %d Time %d (%x - %x)\", Tmr::GetVblanks(), (end_time - start_time), end_time, start_time);\r\n\r\n#if 0\t\t// We can update all sounds now\r\n\t// Increment the active sound and wrap based on current count.\r\n\tactive++;\r\n\r\n\t// Wrap based on current count.\r\n\tif( active >= count )\r\n\t{\r\n\t\tactive = 0;\r\n\t}\r\n#endif\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSfxManager::RemovePositionalSoundFromList( PositionalSoundEntry *pEntry, bool stopIfPlaying )\r\n{\r\n\tpEntry->flags = 0;\r\n\t\r\n\t// Stop the sound from playing if it is playing.\r\n\tif( stopIfPlaying && SoundIsPlaying( pEntry->uniqueID ))\r\n\t{\r\n\t\tStopSound( pEntry->uniqueID );\r\n\t}\r\n\r\n\tif( pEntry->pNext )\r\n\t{\r\n\t\tpEntry->pNext->pPrev = pEntry->pPrev;\r\n\t}\r\n\r\n\tif ( pEntry->pPrev )\r\n\t{\r\n\t\tpEntry->pPrev->pNext = pEntry->pNext;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGpPositionalSounds = pEntry->pNext;\r\n\t}\r\n\tNumPositionalSounds--;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Called from the object's destructor.                           */\r\n/* Stops all soundfx and streams associated with the object.\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nvoid CSfxManager::ObjectBeingRemoved( Obj::CSoundComponent *pObj )\r\n{\r\n\tPositionalSoundEntry *pEntry = GpPositionalSounds;\r\n\tPositionalSoundEntry *pTemp;\r\n\twhile( pEntry )\r\n\t{\r\n\t\tpTemp\t= pEntry;\r\n\t\tpEntry\t= pEntry->pNext;\r\n\t\t\r\n\t\tif( pTemp->pObj == pObj )\r\n\t\t{\r\n\t\t\tRemovePositionalSoundFromList( pTemp, true );\r\n\r\n\t\t\t// Keep scanning the list, in case there's more than one...\r\n\t\t}\r\n\t}\r\n\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Stop a sound on an object.\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nvoid CSfxManager::StopObjectSound( Obj::CSoundComponent *pObj, uint32 checksum )\r\n{\r\n\tPositionalSoundEntry *pEntry = GpPositionalSounds;\r\n\tPositionalSoundEntry *pTemp;\r\n\twhile( pEntry )\r\n\t{\r\n\t\tpTemp\t= pEntry;\r\n\t\tpEntry\t= pEntry->pNext;\r\n\t\tif( pTemp->pObj == pObj )\r\n\t\t{\r\n\t\t\tif(( !checksum ) || ( pTemp->checksum == checksum ))\r\n\t\t\t{\r\n\t\t\t\t// This will stop the sound as well as removing it from the list.\r\n\t\t\t\tRemovePositionalSoundFromList( pTemp, true );\r\n\r\n\t\t\t\t// Keep scanning the list, in case there's more than one.\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nvoid CSfxManager::AddPositionalSoundToUpdateList( uint32 uniqueID, uint32 soundChecksum, Obj::CSoundComponent *pObj )\r\n{\r\n\tif( !uniqueID )\r\n\t{\r\n\t\t// Sound play was unsuccessful.\r\n\t\treturn;\r\n\t}\r\n\tif( NumPositionalSounds == MAX_POSITIONAL_SOUNDS )\r\n\t{\r\n\t\tDbg_Message( \"WARNING: Ran out of positional sound slots.\\nIncrease the number of slots, or decrease the number of requests.\" );\r\n\t\treturn;\r\n\t}\r\n\tNumPositionalSounds++;\r\n\tint i;\r\n\tfor( i = 0; i < MAX_POSITIONAL_SOUNDS; i++ )\r\n\t{\r\n\t\tPositionalSoundEntry *pEntry = &PositionalSounds[i];\r\n\r\n\t\tif( !( pEntry->flags & POSITIONAL_SOUND_FLAG_OCCUPIED ))\r\n\t\t{\r\n\t\t\tif( GpPositionalSounds )\r\n\t\t\t{\r\n\t\t\t\tGpPositionalSounds->pPrev = pEntry;\r\n\t\t\t}\r\n\t\t\tpEntry->pNext = GpPositionalSounds;\r\n\t\t\tpEntry->pPrev = NULL;\r\n\t\t\tGpPositionalSounds = pEntry;\r\n\t\t\tpEntry->uniqueID = uniqueID;\r\n\t\t\tpEntry->checksum = soundChecksum;\r\n\t\t\tpEntry->flags = POSITIONAL_SOUND_FLAG_OCCUPIED;\r\n\t\t\tpEntry->pObj = pObj;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tDbg_MsgAssert( 0, ( \"This is impossible.\" ));\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* SFX Name should be the name of the sound, no extension or\t  */\r\n/* path. It will be the responsibility of the loader for each\t  */\r\n/* platform to add the path and append the extension.\t\t\t  */\r\n/* This module assumes the sounds are all loaded at the beginning */\r\n/* of a level or module, and all removed at the end.\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nbool CSfxManager::LoadSound( const char *sfxName,  int flags, float dropoff, float pitch, float volume )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn false;\r\n\r\n\tconst char\t*pNameMinusPath\t= sfxName;\r\n\tint\t\t\tstringLength\t= strlen( sfxName );\r\n\tfor( int i = 0; i < stringLength; i++ )\r\n\t{\r\n\t\tif(( sfxName[i] == '\\\\' ) || ( sfxName[i] == '/' ))\r\n\t\t\tpNameMinusPath = &sfxName[i + 1];\r\n\t}\r\n\t\r\n\tuint32\t\t\tchecksum\t= Script::GenerateCRC( pNameMinusPath );\r\n\tWaveTableEntry\t*pWaveEntry\t= NULL;\r\n\t\r\n\t// See if the sound is already loaded.\r\n\tif( NULL != GetWaveTableIndex( checksum ))\r\n\t{\r\n\t\tif( !Config::CD())\r\n\t\t{\r\n\t\t\tif( Script::GetInt( 0xd7bb618d /* DebugSoundFx */, false )) \r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"Warning: Sound '%s' already loaded (maybe from a different directory)?\", sfxName );\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tif( flags & SFX_FLAG_LOAD_PERM )\r\n\t{\r\n\t\tif( NumWavesInPermTable >= PERM_WAVE_TABLE_MAX_ENTRIES )\r\n\t\t{\r\n\t\t\tDbg_Message( \"Increase PERM_WAVE_TABLE_MAX_ENTRIES, no room for %s\", sfxName );\r\n\t\t\tDbg_MsgAssert( 0,( \"Too many permanent sound waves being loaded.\" ));\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tpWaveEntry = &WaveTable[ NumWavesInPermTable ];\r\n\t\tif( !LoadSoundPlease( sfxName, checksum, &pWaveEntry->platformWaveInfo, 1 ))\r\n\t\t{\r\n\t\t\tDbg_Message( \"failed to load sound %s\", sfxName );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tNumWavesInPermTable++;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( NumWavesInTable >= WAVE_TABLE_MAX_ENTRIES )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Too many sound waves being loaded.\" ));\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tpWaveEntry = &WaveTable[ NumWavesInTable + PERM_WAVE_TABLE_MAX_ENTRIES ];\r\n\t\tif( !LoadSoundPlease( sfxName, checksum, &pWaveEntry->platformWaveInfo ))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tNumWavesInTable++;\r\n\t}\r\n\r\n\tDbg_MsgAssert( volume >= 0.0f,( \"Tweak volume less than zero.\" ));\r\n\tDbg_MsgAssert( volume <= MAX_VOL_ALLOWED,( \"Tweak volume greater than max allowed.\" ));\t\r\n\tDbg_Assert( pWaveEntry );\r\n\r\n\tpWaveEntry->dropoff\t\t= dropoff;\r\n\tpWaveEntry->pitch\t\t= pitch;\r\n\tpWaveEntry->volume\t\t= volume;\r\n\tpWaveEntry->checksum\t= checksum;\r\n\tpWaveEntry->flags\t\t= flags;\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nvoid CSfxManager::TweakVolumeAndPitch( sVolume *p_vol, float *pitch, WaveTableEntry* waveTableIndex )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn;\r\n\r\n\tDbg_Assert( p_vol && pitch );\r\n\t\r\n\t// 100% volume would result in 1/2 the real MAX. This gives headroom for louder sounds!\r\n\tp_vol->PercentageAdjustment( 50.0f );\r\n\t\r\n\t// Apply tweaked volumes, pitches to sound (variables from LoadSound).\r\n\tif( waveTableIndex->volume != 100.0f )\r\n\t{\r\n\t\tp_vol->PercentageAdjustment( waveTableIndex->volume );\r\n\t}\r\n\tif( waveTableIndex->pitch != 100.0f )\r\n\t{\r\n\t\t*pitch = PERCENT( *pitch, waveTableIndex->pitch );\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Returns a unique ID each time a sound is played, 0 on failure. */\r\n/* The 'unique ID' is just a number that is incremented each\t  */\r\n/* time a sound is played.\t\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* For each platform, keep a table that stores these unique ID's  */\r\n/* for each voice. PS2 has 48 voices.\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* If somebody calls \"StopSound\" I check each of the entries in\t  */\r\n/* the table for a match, and if a match is found and that voice  */\r\n/* is playing, I stop the voice.\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* If a match is not found, that means the voice stopped playing  */\r\n/* earlier and somebody else may be using the voice now, so that  */\r\n/* voice shouldn't be stopped\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nuint32 CSfxManager::PlaySound( uint32 checksum, sVolume *p_vol, float pitch, uint32 controlID, SoundUpdateInfo *pUpdateInfo, const char *pSoundName )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn 0;\r\n\r\n\tDbg_Assert( p_vol );\r\n\t\r\n\tWaveTableEntry *waveTableIndex = GetWaveTableIndex( checksum );\r\n\tif( waveTableIndex == NULL )\r\n\t{\r\n\t\t//Dbg_MsgAssert( 0,( \"Couldn't find sound %s\", Script::FindChecksumName( checksum )));\r\n\t\tDbg_Message(\"******** NON-FATAL ERROR: Couldn't find sound %s\", Script::FindChecksumName( checksum ));\r\n\t\treturn 0;\r\n\t}\r\n\r\n\t// Just use checksum if no controlID is set\r\n\tif (controlID == 0)\r\n\t{\r\n\t\tcontrolID = checksum;\r\n\t}\r\n\r\n\tif( !Config::CD())\r\n\t{\r\n\t\tif( Script::GetInteger( 0xd7bb618d /* DebugSoundFx */, Script::NO_ASSERT ))\r\n\t\t{\r\n\t\t\tif (!pUpdateInfo && !IDAvailable(controlID))\r\n\t\t\t{\r\n\t\t\t\tDbg_Message(\"Playing sound %s with same checksum as one already being played, won't be able to control from script directly.\", Script::FindChecksumName(controlID));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tTweakVolumeAndPitch( p_vol, &pitch, waveTableIndex );\r\n\t\r\n\t// Continue to play the sound, even if the volume is zero. We might be starting a looping sound,\r\n\t// so don't second guess this.\r\n\t// For the moment, don't record looping sounds, due to problems with running out of voices due to\r\n\t// voices still being used by game when it is paused. They just have their volume turned down to zero.\r\n\tif( !waveTableIndex->platformWaveInfo.looping )\r\n\t{\r\n\t\t// Only record the sound in the replay if the game is not paused, otherwise the menu sounds in the\r\n\t\t// paused menu will get recorded.\r\n\t\tMdl::FrontEnd* p_frontend = Mdl::FrontEnd::Instance();\r\n\t\tif( !p_frontend->GamePaused())\r\n\t\t{\r\n//\t\t\tReplay::WritePlaySound( checksum, volL, volR, pitch );\r\n\t\t}\t\r\n\t}\r\n\t\r\n\t// In PlaySoundPlease(), clip sounds to the max allowable. If no volume modifiers are listed in the script\r\n\t// commands (LoadSound or PlaySound) and the sound is played without attenuation, volL and volR will be 1/2\r\n\t// the max (so 50 at this point). Find the platform specific volumes like this:\r\n\t// leftVolume = PERCENT( volL, PLATFORM_MAX ). Clip to PLATFORM_MAX (or -PLATFORM_MAX if phasing is supported).\r\n#ifdef __PLAT_NGPS__\r\n\tint whichVoice = PlaySoundPlease( &waveTableIndex->platformWaveInfo, p_vol, pitch, waveTableIndex->flags & SFX_FLAG_NO_REVERB);\r\n#else\r\n\tint whichVoice = PlaySoundPlease( &waveTableIndex->platformWaveInfo, p_vol, pitch );\r\n#endif\r\n\r\n\tif( whichVoice == -1 )\r\n\t{\r\n\t\tDbg_Message( \"Couldn't find free voice.\" );\r\n\t\treturn 0;\r\n\t}\r\n\tDbg_MsgAssert( whichVoice < NUM_VOICES,( \"Voice larger than max allowed.\" ));\r\n\tVoiceInfo *pVoiceInfo = &VoiceInfoTable[whichVoice];\r\n\tpVoiceInfo->controlID = controlID;\r\n\tpVoiceInfo->uniqueID = GenerateUniqueID(controlID);\r\n\r\n\t// So we don't have to look this up every time we query this module for the properties of a sound that's\r\n\t// playing (which we do often for looping sounds).\r\n\tpVoiceInfo->waveIndex\t\t= waveTableIndex;\r\n\tObjectSoundInfo *pInfo\t\t= &pVoiceInfo->info;\r\n\tif ( pUpdateInfo )\r\n\t{\r\n\t\tpInfo->currentPitch\t\t= pUpdateInfo->pitch;\r\n\t\tpInfo->currentVolume\t= pUpdateInfo->volume;\r\n\t\tpInfo->dropoffDist\t\t= pUpdateInfo->dropoffDist ? pUpdateInfo->dropoffDist : waveTableIndex->dropoff;\r\n\t\tpInfo->origPitch\t\t= pInfo->targetPitch = pInfo->currentPitch;\r\n\t\tpInfo->origVolume\t\t= pInfo->targetVolume = pInfo->currentVolume;\r\n\t\tpInfo->deltaPitch\t\t= 0.0f;\r\n\t\tpInfo->deltaVolume\t\t= 0.0f;\r\n\t\tpInfo->dropoffFunction\t= pUpdateInfo->dropoffFunction;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpInfo->currentPitch\t\t= 100.0f;\r\n\t\tpInfo->currentVolume\t= 100.0f;\r\n\t\tpInfo->dropoffDist\t\t= 0.0f;\r\n\t\tpInfo->dropoffFunction\t= DROPOFF_FUNC_STANDARD;\r\n\t}\r\n\tpInfo->checksum = checksum;\r\n\tif( !Config::CD())\r\n\t{\r\n\t\tif( Script::GetInteger( 0xd7bb618d /* DebugSoundFx */, Script::NO_ASSERT ))\r\n\t\t{\r\n\t\t\t//Dbg_Message( \"Playing sound %s\\n\", (pSoundName) ? pSoundName : Script::FindChecksumName( checksum ));\r\n\t\t\tDbg_Message( \"Playing sound %s with volL = %f volR = %f on voice %d\", (pSoundName) ? pSoundName : Script::FindChecksumName( checksum ),\r\n\t\t\t\t\t\t p_vol->GetChannelVolume(0), p_vol->GetChannelVolume(1), whichVoice);\r\n\t\t}\r\n\t}\t\r\n\treturn pVoiceInfo->uniqueID;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Send in the uniqueID returned from PlaySound()\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nbool CSfxManager::StopSound( uint32 uniqueID )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn true;\r\n\r\n\tint whichVoice = GetVoiceFromID(uniqueID);\r\n\r\n\tif (whichVoice >= 0)\r\n\t{\r\n\t\t// Stop the sound if it's playing (platform specific).\r\n\t\tStopSoundPlease( whichVoice );\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\nbool CSfxManager::SetSoundParams( uint32 uniqueID, sVolume *p_vol, float pitch )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn true;\r\n\r\n\tint whichVoice = GetVoiceFromID(uniqueID);\r\n\r\n\tif (whichVoice >= 0)\r\n\t{\r\n\t\tWaveTableEntry *waveTableIndex = VoiceInfoTable[ whichVoice ].waveIndex;\r\n\t\r\n\t\tif( waveTableIndex == NULL )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, ( \"Can't find wave table entry for sound %s\", Script::FindChecksumName( uniqueID ) ) );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tif( !p_vol->IsSilent())\r\n\t\t{\r\n\t\t\t// Tweak the values to designer specs (from LoadSound and PlaySound).\r\n\t\t\tTweakVolumeAndPitch( p_vol, &pitch, waveTableIndex );\r\n\t\t}\r\n\r\n#\t\tif defined( __PLAT_NGPS__ ) || defined( __PLAT_NGC__ )\r\n\t\t// Adjust pitch to account for lower sampling rates.\r\n\t\tpitch = PERCENT( pitch, waveTableIndex->platformWaveInfo.pitchAdjustmentForSamplingRate );\r\n#\t\tendif\r\n\r\n\t\t// And finally, set the parameters.\r\n\t\tSetVoiceParameters( whichVoice, p_vol, pitch );\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif( !Config::CD())\r\n\t{\r\n\t\tif( Script::GetInteger( 0x6d2e270e /* DebugSoundFxUpdate */, Script::NO_ASSERT ))\r\n\t\t{\r\n\t\t\tDbg_Message( \"SetSoundParams: couldn't find sound %s\", Script::FindChecksumName( uniqueID ));\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nvoid CSfxManager::SetMainVolume( float volume )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn;\r\n\t\r\n\tDbg_MsgAssert( volume >= 0.0f, ( \"Volume below 0%\" ));\r\n\tDbg_MsgAssert( volume <= 100.0f, ( \"Volume above 100%\" ));\r\n\t\r\n\tif( Script::GetInteger( 0xd7bb618d /* DebugSoundFx */, Script::NO_ASSERT ))\r\n\t{\r\n\t\tDbg_Message( \"Setting gVolume to %f\\n\",volume );\r\n\t}\r\n\t  \r\n\tgVolume\t= volume;\r\n\tvolume\t= volume * Config::GetMasterVolume() / 100.0f;\r\n\tif( volume < 0.1f )\r\n\t{\r\n\t\tvolume = 0.0f;\r\n\t}\t\r\n\tSetVolumePlease( volume );\r\n\tPcm::SetAmbientVolume( volume );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nfloat CSfxManager::GetMainVolume( void )\r\n{\r\n\treturn gVolume;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nvoid CSfxManager::SetReverb( float reverbLevel, int reverbMode, bool instant )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn;\r\n\r\n\tDbg_MsgAssert( reverbLevel >= 0.0f, ( \"Reverb below 0%\" ));\r\n\tDbg_MsgAssert( reverbLevel <= 100.0f, ( \"Reverb above 100%\" ));\r\n\tSetReverbPlease( reverbLevel, reverbMode, instant );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nbool CSfxManager::SoundIsPlaying( uint32 uniqueID, int *pWhichVoice )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn 0;\r\n\r\n\tint whichVoice;\r\n\r\n\t// Zero is not a valid ID... quickly return.\r\n\tif ( !uniqueID )\r\n\t\treturn false;\r\n\t\t\r\n\tfor( whichVoice = 0; whichVoice < NUM_VOICES; whichVoice++ )\r\n\t{\r\n\t\tif ( VoiceInfoTable[ whichVoice ].uniqueID == uniqueID )\r\n\t\t{\r\n\t\t\tif( !VoiceIsOn( whichVoice ))\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tif( pWhichVoice )\r\n\t\t\t{\r\n\t\t\t\t*pWhichVoice = whichVoice;\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint CSfxManager::GetNumSoundsPlaying()\r\n{\r\n\t// This is not the most efficient way to figure this out, but it doesn't\r\n\t// require any changes below the p-line.  We should add p-line code if\r\n\t// it get used a lot.\r\n\tint voicesUsed = 0;\r\n\r\n\tfor( int whichVoice = 0; whichVoice < NUM_VOICES; whichVoice++ )\r\n\t{\r\n\t\tif( VoiceIsOn( whichVoice ) )\r\n\t\t{\r\n\t\t\tvoicesUsed++;\r\n\t\t}\r\n\t}\r\n\r\n\treturn voicesUsed;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nfloat CSfxManager::GetDropoffDist( uint32 soundChecksum )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn DefaultDropoffDist;\r\n\r\n\tWaveTableEntry *waveIndex = GetWaveTableIndex( soundChecksum );\r\n\tif( waveIndex == NULL )\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\tfloat dropoffDist = waveIndex->dropoff;\r\n\treturn ( dropoffDist ? dropoffDist : DefaultDropoffDist );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nbool CSfxManager::UpdateLoopingSound( uint32 soundID, sVolume *p_vol, float pitch )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn true;\r\n\r\n//    uint32 start_time = Tmr::GetTimeInUSeconds();\r\n\r\n\tint whichVoice;\r\n\tfor( whichVoice = 0; whichVoice < NUM_VOICES; whichVoice++ )\r\n\t{\r\n\t\tif( VoiceInfoTable[whichVoice].uniqueID == soundID )\r\n\t\t{\r\n\t\t\tif( !VoiceIsOn( whichVoice ))\r\n\t\t\t{\r\n\t\t\t\tif( !Config::CD())\r\n\t\t\t\t{\r\n\t\t\t\t\tif( Script::GetInteger( 0x6d2e270e /* DebugSoundFxUpdate */, Script::NO_ASSERT ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_Message( \"Sound %s is done\", Script::FindChecksumName( VoiceInfoTable[whichVoice].info.checksum ));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\r\n\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Tweak sounds for this particular instance of PlaySound (this allows a designer to vary the pitch,\r\n\t\t\t// for example, of a carloop sound on each car, by adding a pitch = parameter to Obj_PlaySound. This\r\n\t\t\t// will be maintained, as will the volume, thanks to this code.\r\n\t\t\tif( !p_vol->IsSilent())\r\n\t\t\t{\r\n\t\t\t\tfloat tweakVolume = VoiceInfoTable[whichVoice].info.currentVolume;\r\n\t\t\t\tif( tweakVolume != 100.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_vol->PercentageAdjustment( tweakVolume );\r\n\t\t\t\t}\r\n\t\t\t\tfloat tweakPitch = VoiceInfoTable[ whichVoice ].info.currentPitch;\r\n\t\t\t\tif( tweakPitch != 100.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tpitch = PERCENT( pitch, tweakPitch );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tWaveTableEntry *waveTableIndex = VoiceInfoTable[ whichVoice ].waveIndex;\r\n\t\t\r\n\t\t\tif( waveTableIndex == NULL )\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"WARNING:  Positional/looping sound error.\" );\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tif( !p_vol->IsSilent())\r\n\t\t\t{\r\n\t\t\t\t// Tweak the values to designer specs (from LoadSound and PlaySound).\r\n\t\t\t\tTweakVolumeAndPitch( p_vol, &pitch, waveTableIndex );\r\n\t\t\t}\r\n\r\n#\t\t\tif defined( __PLAT_NGPS__ ) || defined( __PLAT_NGC__ )\r\n\t\t\t// Adjust pitch to account for lower sampling rates.\r\n\t\t\tpitch = PERCENT( pitch, waveTableIndex->platformWaveInfo.pitchAdjustmentForSamplingRate );\r\n#\t\t\tendif\r\n\r\n\t\t\t// And finally, set the parameters.\r\n\t\t\tSetVoiceParameters( whichVoice, p_vol, pitch );\r\n\r\n//            uint32 end_time = Tmr::GetTimeInUSeconds();\t\r\n//\t\t\tif ((end_time - start_time) > 250)\r\n//\t\t\t\tDbg_Message(\"CSfxManager::UpdateLoopingSound Frame %d Time %d\", Tmr::GetVblanks(), (end_time - start_time));\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tif( !Config::CD())\r\n\t{\r\n\t\tif( Script::GetInteger( 0x6d2e270e /* DebugSoundFxUpdate */, Script::NO_ASSERT ))\r\n\t\t{\r\n\t\t\tDbg_Message( \"UpdateSound: couldn't find sound %s\", Script::FindChecksumName( VoiceInfoTable[whichVoice].info.checksum ));\r\n\t\t}\r\n\t}\t\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Calculates multipliers for front left, front right, rear left, */\r\n/* rear right and center channel speakers.\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nvoid CSfxManager::Get5ChannelMultipliers( const Mth::Vector &sound_source, float *p_multipliers )\r\n{\r\n\tfloat angle\t= Mth::RadToDeg( atan2f( sound_source[X], -sound_source[Z] ));\r\n\tGet5ChannelMultipliers( angle, p_multipliers );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Calculates multipliers for front left, front right, rear left, */\r\n/* rear right and center channel speakers.\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nvoid CSfxManager::Get5ChannelMultipliers( float angle, float *p_multipliers )\r\n{\r\n\tstatic float speakers[5][3]\t= {\t{ 330.00f, 240.01f, 359.99f },\t\t// Front left max angle, min angle0, min angle1\r\n\t\t\t\t\t\t\t\t\t{  30.00f,   0.01f,\t119.99f },\t\t// Front right\r\n\t\t\t\t\t\t\t\t\t{ 240.00f, 120.01f, 329.99f },\t\t// Rear left\r\n\t\t\t\t\t\t\t\t\t{ 120.0f,   30.01f, 239.99f },\t\t// Rear right\r\n\t\t\t\t\t\t\t\t\t{   0.0f,  330.01f,  29.99f }};\t\t// Center\r\n\r\n\t// Ensure angle is in a suitable range.\r\n\tangle = ( angle < 0.0f ) ? ( 360.0f + angle ) : angle;\r\n\r\n\t// Go through and calculate the relative volumes for each speaker.\r\n\tfor( int spkr = 0; spkr < 5; ++spkr )\r\n\t{\r\n\t\tfloat amin0\t= speakers[spkr][1];\r\n\t\tfloat amin1\t= speakers[spkr][2];\r\n\t\tfloat amax\t= speakers[spkr][0];\r\n\t\tfloat mul\t= 0.0f;\r\n\r\n\t\tif( amin0 < amax )\r\n\t\t{\r\n\t\t\t// Regular test.\r\n\t\t\tif(( angle > amin0 ) && ( angle <= amax ))\r\n\t\t\t{\r\n\t\t\t\t// Angle lies between amin0 and amax.\r\n\t\t\t\tmul = ( angle - amin0 ) / ( amax - amin0 );\r\n\t\t\t}\r\n\t\t\telse if(( angle > amax ) && ( angle < amin1 ))\r\n\t\t\t{\r\n\t\t\t\t// Angle lies between amax and amin1.\r\n\t\t\t\tmul = 1.0f - (( angle - amax ) / ( amin1 - amax ));\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Non regular test (center channel). Assumes center at 0.0.\r\n\t\t\tif( angle > amin0 )\r\n\t\t\t{\r\n\t\t\t\tmul = ( angle - amin0 ) / ( 360.0f - amin0 );\r\n\t\t\t}\r\n\t\t\telse if( angle < amin1 )\r\n\t\t\t{\r\n\t\t\t\tmul = ( amin1 - angle ) / ( amin1 );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\t\t\t\t\r\n\t\t// Angle is within scope of this speaker. Figure multiplier.\r\n\t\tDbg_Assert( mul <= 1.0f );\r\n\t\tp_multipliers[spkr] = sinf( mul * Mth::PI * 0.5f );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Sets volume and pan considering all cameras and current\t\t  */\r\n/* position.\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nvoid CSfxManager::SetVolumeFromPos( sVolume *p_vol, const Mth::Vector &soundSource, float dropoffDist, EDropoffFunc dropoff_func,\r\n\t\t\t\t\t\t\t\t\tGfx::Camera *p_camera,  const Mth::Vector *p_dropoff_pos)\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn;\r\n\r\n\tDbg_Assert( p_vol );\r\n\r\n\t// Set the volume to 0\r\n\tp_vol->SetSilent();\r\n\r\n\t// Return if in Silence Mode\r\n\tif( PositionalSoundSilenceMode() )\r\n\t\treturn;\r\n\r\n\t// Find the camera if one wasn't already supplied\r\n\tif (!p_camera)\r\n\t{\r\n\t\tp_camera = Nx::CViewportManager::sGetClosestCamera(soundSource);\r\n\r\n\t\t// If we still can't find a camera, return with the volume set to 0\r\n\t\tif (!p_camera)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\t// Find the dist to the sound\r\n\tfloat dist = Mth::Distance( p_camera->GetPos(), soundSource );\r\n\r\n\t// Calculate the dropoff dist\r\n\tif (p_dropoff_pos)\r\n\t{\r\n\t\tdropoffDist = dist + Mth::Distance( *p_dropoff_pos, p_camera->GetPos());\r\n\t}\r\n\telse if( !dropoffDist )\r\n\t{\r\n\t\tdropoffDist = DefaultDropoffDist;\r\n\t}\r\n\t\r\n\t// If we are outside the dropoff dist, we are out of here\r\n\tif( dist >= dropoffDist )\r\n\t\treturn;\r\n\r\n\t// Sound is within range of this camera.\r\n\tfloat dropOff\t= dist / dropoffDist;\r\n\tfloat volume = 0.0f;\r\n\tswitch (dropoff_func)\r\n\t{\r\n\tcase DROPOFF_FUNC_STANDARD:\r\n\t\tvolume\t= ( 100.0f * \r\n\t\t\t\t  ((( 1.0f - ( dropOff * dropOff )) + \t\t\t// Exponential and...\r\n\t\t\t\t  ( 3.0f * ( 1.0f - ( dropOff )))) / 4.0f ));\t// ...linear averaged together.\r\n\t\tbreak;\r\n\r\n\tcase DROPOFF_FUNC_LINEAR:\r\n\t\tvolume\t= ( 100.0f * ( 1.0f - dropOff ) );\r\n\t\tbreak;\r\n\r\n\tcase DROPOFF_FUNC_EXPONENTIAL:\r\n\t\tvolume\t= ( 100.0f * ( ( 1.0f - dropOff ) * ( 1.0f - dropOff ) ) );\r\n\t\tbreak;\r\n\r\n\tcase DROPOFF_FUNC_INV_EXPONENTIAL:\r\n\t\tvolume\t= ( 100.0f * ( sqrtf ( 1.0f - dropOff ) ) );\r\n\t\tbreak;\r\n\t}\r\n\r\n\tswitch( p_vol->GetVolumeType() )\r\n\t{\r\n\t\tcase VOLUME_TYPE_BASIC_2_CHANNEL:\r\n\t\tcase VOLUME_TYPE_2_CHANNEL_DOLBYII:\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( p_camera );\t\t// We should have returned by now\r\n\r\n\t\t\t\tif( fabsf( volume ) > fabsf( p_vol->GetLoudestChannel()))\r\n\t\t\t\t{\r\n\t\t\t\t\tMth::Vector sound_pos_from_camera = soundSource - p_camera->GetPos();\r\n\t\t\t\t\tsound_pos_from_camera.Normalize();\r\n\r\n\t\t\t\t\tMth::Vector camRightVector = -p_camera->GetMatrix()[X];\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Project the obj_pos vector onto the right vector.\r\n\t\t\t\t\t// For some reason right and left were switched (must be left instead of right!)\r\n\t\t\t\t\tfloat panVal = Mth::DotProduct( sound_pos_from_camera, camRightVector );\r\n\r\n\t\t\t\t\t// +1.0f is all the way on the right, -1.0f is all the way on the left.\r\n\t\t\t\t\t// Doing an exponential curve, so that if the object is right in the middle\r\n\t\t\t\t\t// the right and left volume (at closest dist) is 75%. 100% volume if all\r\n\t\t\t\t\t// the way to the right/left.\r\n\t\t\t\t\tpanVal\t\t+= 1.0f;\t\t// Will now be from 0 to 2 (Lmax to Rmax)..\r\n\t\t\t\t\tpanVal\t\t/= 2.0f;\t\t// ...now from 0 to 1.\r\n\t\t\t\t\tfloat rVol\t= ( 1.0f - ( panVal * panVal )) * volume;\r\n\t\t\t\t\tpanVal\t\t= 1.0f - panVal;\r\n\t\t\t\t\tfloat lVol\t= ( 1.0f - ( panVal * panVal )) * volume;\r\n\r\n\t\t\t\t\tif( p_vol->GetVolumeType() == VOLUME_TYPE_2_CHANNEL_DOLBYII )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbool bSetPhase = false;\r\n\r\n\t\t\t\t\t\tif( lVol > p_vol->GetChannelVolume( 0 ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_vol->SetChannelVolume( 0, lVol );\r\n\t\t\t\t\t\t\tbSetPhase = true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif( rVol > p_vol->GetChannelVolume( 1 ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_vol->SetChannelVolume( 1, rVol );\r\n\t\t\t\t\t\t\tbSetPhase = true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif( bSetPhase )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// If sound is behind the camera, set volume negative and it will sound out of phase.\r\n\t\t\t\t\t\t\tMth::Vector camAtVector = -p_camera->GetMatrix()[Z];\r\n\r\n\t\t\t\t\t\t\tfloat behindCamera = Mth::DotProduct( sound_pos_from_camera, camAtVector );\r\n\t\t\t\t\t\t\tif ( behindCamera < 0.0f )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// Just one channel needs to be reverse phased to get the effect.\r\n\t\t\t\t\t\t\t\tp_vol->SetChannelVolume( 0, p_vol->GetChannelVolume( 0 ) * -1.0f );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( lVol > p_vol->GetChannelVolume( 0 ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_vol->SetChannelVolume( 0, lVol );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif( rVol > p_vol->GetChannelVolume( 1 ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_vol->SetChannelVolume( 1, rVol );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\r\n\t\tcase VOLUME_TYPE_5_CHANNEL_DOLBY5_1:\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( p_camera );\t\t// We should have returned by now\r\n\r\n\t\t\t\tif( fabsf( volume ) > p_vol->GetLoudestChannel())\r\n\t\t\t\t{\r\n\t\t\t\t\t// Transform the sound source into the camera's coordinate space.\r\n\t\t\t\t\tMth::Matrix inv_view\t= p_camera->GetMatrix();\r\n\t\t\t\t\tinv_view.Invert();\r\n\r\n\t\t\t\t\tMth::Vector sound_src\t= soundSource - p_camera->GetPos();\r\n\t\t\t\t\tMth::Vector sound_pos\t= inv_view.Transform( sound_src );\r\n\t\t\t\t\tsound_pos.Normalize();\r\n\r\n\t\t\t\t\tfloat channel_multipliers[5];\r\n                    Get5ChannelMultipliers( sound_pos, &channel_multipliers[0] );\r\n\r\n\t\t\t\t\t// Go through and calculate the relative volumes for each speaker.\r\n\t\t\t\t\tfor( int spkr = 0; spkr < 5; ++spkr )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfloat mul = channel_multipliers[spkr];\r\n\t\t\t\t\t\tif( mul > 0.0f )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Angle is within scope of this speaker. Figure multiplier.\r\n\t\t\t\t\t\t\tDbg_Assert( mul <= 1.0f );\r\n\t\t\t\t\t\t\tfloat vol = volume * mul;\r\n\t\t\t\t\t\t\tif( vol > p_vol->GetChannelVolume( spkr ))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tp_vol->SetChannelVolume( spkr, vol );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Final step is to normalize the channels out and reset to volume level.\r\n\t\t\t\t\tif( !p_vol->IsSilent())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfloat norm = 0.0;\r\n\t\t\t\t\t\tfor( int spkr = 0; spkr < 5; ++spkr )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnorm += p_vol->GetChannelVolume( spkr ) * p_vol->GetChannelVolume( spkr );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tnorm = sqrtf( norm );\r\n\t\t\t\t\t\tfor( int spkr = 0; spkr < 5; ++spkr )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_vol->SetChannelVolume( spkr, ( volume * p_vol->GetChannelVolume( spkr )) / norm );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/* Real speed of sound ~= 760 mph.\t\t\t\t\t\t\t\t  */\r\n/* Lower that for dramatic effect.\t\t\t\t\t\t\t\t  */\r\n#define\tSPEED_OF_OUR_SOUND\tMPH_TO_INCHES_PER_SECOND( 700.0f )\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* This should happen after all other pitch adjustments.\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nvoid CSfxManager::AdjustPitchForDoppler( float *pitch, const Mth::Vector &currentPos, const Mth::Vector &oldPos, float elapsedTime, Gfx::Camera *pCam )\r\n{\r\n#\tifndef __PLAT_NGC__\r\n\tconst float cutoff_dist =  360.0f;\t// in inches\r\n#\tendif\t\t// __PLAT_NGC__\r\n\r\n\tif( NoSoundPlease())\r\n\t\treturn;\r\n\r\n#\tifndef __PLAT_NGC__\r\n\tif ( !pCam )\r\n\t{\r\n\t\tpCam = Nx::CViewportManager::sGetClosestCamera( currentPos );\r\n\t\tif( !pCam )\r\n\t\t\treturn;\r\n\t}\r\n\r\n\tfloat prevDist\t= Mth::Distance( pCam->m_old_pos, oldPos );\r\n\tfloat deltaDist\t= Mth::Distance( pCam->GetPos(), currentPos ) - prevDist;\r\n\r\n\tif(( fabsf( deltaDist ) * Tmr::FrameRatio()) > Tmr::FrameRatio() * cutoff_dist )\r\n\t{\r\n\t\t// TT2794: Large movements in the camera are causing pitch glitches, so\r\n\t\t// it would be better to not change the pitch at all than to try to find\r\n\t\t// a \"good\" change.  Garrett\r\n\t\treturn;\r\n\r\n\t\t// Clip so there aren't high pitched schreeches when camera is moved in net games and such:\r\n\t\tif ( deltaDist < 0.0f )\r\n\t\t{\r\n\t\t\tdeltaDist = -( Tmr::FrameRatio( ) * cutoff_dist );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tdeltaDist = Tmr::FrameRatio( ) * cutoff_dist;\r\n\t\t}\r\n\t}\r\n\tfloat deltaPitch = SPEED_OF_OUR_SOUND * elapsedTime;\r\n\tDbg_MsgAssert( deltaPitch,( \"Divide by zero.\" ));\r\n\tdeltaPitch = (( *pitch ) * deltaDist ) / deltaPitch;\r\n\t*pitch -= deltaPitch;\r\n#\tendif // __PLAT_NGC__\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* This should happen after all other pitch adjustments.\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nObjectSoundInfo *CSfxManager::GetObjectSoundProperties( Obj::CSoundComponent *pObj, uint32 checksum )\r\n{\r\n\tPositionalSoundEntry *pEntry = GpPositionalSounds;\r\n\twhile( pEntry )\r\n\t{\r\n\t\tif(( pEntry->pObj == pObj ) && ( pEntry->checksum == checksum ))\r\n\t\t{\r\n\t\t\t// Change the current volume, pitch.\r\n\t\t\tint voiceIndex;\r\n\t\t\tif( !SoundIsPlaying( pEntry->uniqueID, &voiceIndex ))\r\n\t\t\t{\r\n\t\t\t\treturn NULL;\r\n\t\t\t}\r\n\t\t\treturn &VoiceInfoTable[ voiceIndex ].info;\r\n\t\t}\r\n\t\tpEntry = pEntry->pNext;\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Plays sound, considering camera position(s) from sound source. */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nuint32 CSfxManager::PlaySoundWithPos( uint32 soundChecksum, SoundUpdateInfo *pUpdateInfo, Obj::CSoundComponent *pObj, bool noPosUpdate )\r\n{\r\n\tif( NoSoundPlease())\r\n\t\treturn 0;\r\n\r\n\tWaveTableEntry *waveTableIndex = GetWaveTableIndex( soundChecksum );\r\n\tif( waveTableIndex == NULL )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Asking to play sound that hasn't been loaded %s.\", Script::FindChecksumName( soundChecksum )));\r\n\t\treturn 0;\r\n\t}\r\n\t\r\n\tDbg_MsgAssert( pObj,( \"pObj should be non-NULL\" ));\r\n\r\n\tsVolume vol;\r\n\r\n\t// Garrett: Shouldn't we be calling this here, too?  Or is it not necessary?\r\n//\tif( pVoiceInfo->waveIndex->flags & SFX_FLAG_POSITIONAL_UPDATE_WITH_DOPPLER )\r\n//\t{\r\n//\t\t// Even if the object didn't move, the camera could have!\r\n//\t\tAdjustPitchForDoppler( &pitch, pObj->m_pos, pObj->m_old_pos, Tmr::FrameLength(), pCamera );\r\n//\t}\r\n\r\n\tGfx::Camera *pCamera = Nx::CViewportManager::sGetClosestCamera( pObj->GetPosition() );\r\n\tif( pCamera )\r\n\t{\r\n\t\tMth::Vector dropoff_pos;\r\n\t\tMth::Vector *p_dropoff_pos = NULL;\r\n\t\tif (pObj->GetClosestDropoffPos(pCamera, dropoff_pos))\r\n\t\t{\r\n\t\t\tp_dropoff_pos = &dropoff_pos;\r\n\t\t}\r\n\r\n\t\tSetVolumeFromPos( &vol, pObj->GetClosestEmitterPos(pCamera), pUpdateInfo->dropoffDist ? pUpdateInfo->dropoffDist : waveTableIndex->dropoff,\r\n\t\t\t\t\t\t  pUpdateInfo->dropoffFunction, pCamera, p_dropoff_pos );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tvol.SetSilent();\r\n\t}\r\n\t\r\n\tDbg_MsgAssert(!(noPosUpdate && ( waveTableIndex->flags & SFX_FLAG_POSITIONAL_UPDATE_WITH_DOPPLER )), (\"Trying to play doppler sound with NoPosUpdate\"));\r\n\tif( vol.IsSilent() && noPosUpdate )\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\t\r\n\tvol.PercentageAdjustment( pUpdateInfo->volume );\r\n\t\r\n\tuint32 uniqueID = PlaySound( soundChecksum, &vol, pUpdateInfo->pitch, 0, pUpdateInfo );\r\n\t\r\n\tif( !Config::CD())\r\n\t{\r\n\t\tif( Script::GetInteger( 0x6d2e270e /* DebugSoundFxUpdate */, Script::NO_ASSERT ))\r\n\t\t{\r\n\t\t\tDbg_Message( \"Starting sound %s with volL = %f volR = %f\", Script::FindChecksumName( soundChecksum ), vol.GetChannelVolume(0), vol.GetChannelVolume(1));\r\n\t\t}\r\n\t}\t\r\n\r\n\t// Should be able to have looping sounds, as long as the ones that are manually updated call PlaySound\r\n\t// instead of PlaySoundWithPos.\r\n\tif(!noPosUpdate)\r\n\t{\r\n\t\tAddPositionalSoundToUpdateList( uniqueID, soundChecksum, pObj );\r\n\r\n\t\tif( !Config::CD())\r\n\t\t{\r\n\t\t\tif( Script::GetInteger( 0x6d2e270e /* DebugSoundFxUpdate */, Script::NO_ASSERT ))\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"Added sound %s to update list\", Script::FindChecksumName( soundChecksum ));\r\n\t\t\t}\r\n\t\t}\t\r\n\t}\r\n\treturn uniqueID;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSfxManager::Update( void )\r\n{\r\n\tPerFrameUpdate();\r\n}\r\n\r\n} // namespace Sfx\r\n\r\n"
  },
  {
    "path": "Code/Gel/SoundFX/soundfx.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tsoundfx\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/soundfx/soundfx.h  \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t1/4/01\t-\tmjd\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_SOUNDFX_H\r\n#define __GEL_SOUNDFX_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/list.h>\r\n#include <core/macros.h>\r\n#include <core/math.h>\r\n#include <sys/timer.h>\r\n\r\n#ifdef __PLAT_NGPS__\r\n#include <gel/soundfx/ngps/p_sfx.h>\r\n#elif defined( __PLAT_XBOX__ )\r\n#include <gel/soundfx/xbox/p_sfx.h>\r\n#elif defined( __PLAT_NGC__ )\r\n#include <gel/soundfx/ngc/p_sfx.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// change the following line to compile out soundfx from the game:\r\n#ifdef __PLAT_XBOX__\r\n#define NO_SOUND_PLEASE\t0\r\n#else\r\n#define NO_SOUND_PLEASE\t0\r\n#endif\r\n\r\n// if we need more, NO PROBLEMA!  Change this:\r\n#if defined( __PLAT_NGPS__ )\r\n#define WAVE_TABLE_MAX_ENTRIES\t\t\t256\t// non-permanent sounds\r\n#define PERM_WAVE_TABLE_MAX_ENTRIES\t\t256\t// permanent sounds\r\n#define MAX_POSITIONAL_SOUNDS\t\t\t128\r\n#elif defined( __PLAT_XBOX__ )\r\n#define WAVE_TABLE_MAX_ENTRIES\t\t\t256\t// non-permanent sounds\r\n#define PERM_WAVE_TABLE_MAX_ENTRIES\t\t256\t// permanent sounds\r\n#define MAX_POSITIONAL_SOUNDS\t\t\t128\r\n#else\r\n#define WAVE_TABLE_MAX_ENTRIES\t\t\t256\t// non-permanent sounds\r\n#define PERM_WAVE_TABLE_MAX_ENTRIES\t\t256\t// permanent sounds\r\n#define MAX_POSITIONAL_SOUNDS\t\t\t128\r\n#endif\r\n\r\n#define DIST_FROM_DROPOFF_AT_WHICH_TO_START_SOUND\tFEET_TO_INCHES( 20.0f )\r\n#define DFDAWTSS\t\t\t\t\t\t\t\t\tDIST_FROM_DROPOFF_AT_WHICH_TO_START_SOUND\r\n\r\n// This buffer prevents rapid switching on/off of voices that are right on the border.\r\n#define SOUND_DIST_BUFFER\t\t\t\t\t\t\tFEET_TO_INCHES( 20.0f )\r\n#define DIST_FROM_DROPOFF_AT_WHICH_TO_STOP_SOUND\t( SOUND_DIST_BUFFER + DFDAWTSS )\r\n\r\n#define DEFAULT_DROPOFF_DIST\t\t\t\t\t\tFEET_TO_INCHES( 85.0f )\r\n\r\n// When a voice is set to negative volume on some platforms, it puts the sound 'out of phase' to sound like it's behind you...\r\n#if defined( __PLAT_NGPS__ ) || defined( __PLAT_XBOX__ )\r\n#define PLATFORM_SUPPORTS_VOLUME_PHASING\t\t\t1\r\n#endif\r\n\r\n#define MAX_VOL_ALLOWED\t\t\t\t\t\t\t\t1000 // 1000 percent (10 times)\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Gfx\r\n{\r\n\tclass Camera;\r\n}\r\n\r\nnamespace Obj\r\n{\r\n    class CSoundComponent;\r\n    class CEmitterObject;\r\n}\r\n\r\nenum\r\n{\r\n\tSFX_FLAG_LOAD_PERM\t\t\t\t\t\t= ( 1 << 0 ),\r\n//\tSFX_FLAG_POSITIONAL_UPDATE\t\t\t\t= ( 1 << 1 ),\r\n\tSFX_FLAG_POSITIONAL_UPDATE_WITH_DOPPLER = ( 1 << 2 ),\r\n\tSFX_FLAG_NO_REVERB\t\t\t\t\t\t= ( 1 << 4 ),\r\n};\r\n\r\n\r\n// Function used to calculate volume dropoff\r\nenum EDropoffFunc\r\n{\r\n\tDROPOFF_FUNC_STANDARD,\t\t\t\t// Combination of linear and exponential\r\n\tDROPOFF_FUNC_LINEAR,\r\n\tDROPOFF_FUNC_EXPONENTIAL,\r\n\tDROPOFF_FUNC_INV_EXPONENTIAL,\r\n};\r\n\r\n\r\nstruct ObjectSoundInfo\r\n{\r\n\t// Needed for long sounds played on a per-object basis and positionally updated:\r\n\tuint32\tchecksum;\r\n\tfloat\tdropoffDist;\r\n\tfloat\tcurrentPitch;\r\n\tfloat\tcurrentVolume;\r\n\tfloat\torigPitch;\r\n\tfloat\torigVolume;\r\n\tfloat\ttargetPitch;\r\n\tfloat\ttargetVolume;\r\n\tfloat\tdeltaPitch;\r\n\tfloat\tdeltaVolume;\r\n\tEDropoffFunc dropoffFunction;\r\n\r\n\t// Used to check to see if the sound should be turned off or on, if too far/close to the camera:\r\n\tTmr::Time timeForNextDistCheck;\r\n\t\r\n\t// Used by the script debugger code to fill in a structure\r\n\t// for transmitting to the monitor.exe utility running on the PC.\r\n\tvoid GetDebugInfo(Script::CStruct *p_info);\r\n};\r\n\r\n\r\n#ifdef __PLAT_WN32__\r\nstruct PlatformWaveInfo\r\n{\r\n\t// Stub to compile under win32\r\n};\r\n#endif\r\n\r\nnamespace Sfx\r\n{\r\n\r\nstruct WaveTableEntry\r\n{\r\n\tuint32\t\tchecksum;\t// name of the sound...\r\n\tuint32\t\tflags;\t\t// see SFX_FLAG_ 's in soundfx.h\r\n\r\n\t// All the shit designers want to be able to set in a script file:\r\n\tfloat\t\tpitch;\t\t// tweakable by designers in script file\r\n\tfloat\t\tvolume;\t\t// tweakable by designers in script file\r\n\tfloat\t\tdropoff;\t// tweakable by designers in script file\r\n\r\n\t// Platform dependent info:\r\n\tPlatformWaveInfo platformWaveInfo;\r\n};\r\n\r\n\r\nstruct VoiceInfo\r\n{\r\n\tuint32\t\t\t\tuniqueID;\r\n\tuint32\t\t\t\tcontrolID;\r\n\tWaveTableEntry\t\t*waveIndex;\r\n\tObjectSoundInfo\t\tinfo;\r\n};\r\n\r\n\r\nenum EVolumeType\r\n{\r\n\tVOLUME_TYPE_BASIC_2_CHANNEL,\t\t// Basic 2 channel left/right sound with no volume phasing.\r\n\tVOLUME_TYPE_2_CHANNEL_DOLBYII,\t\t// As above, but with DolbyII volume phasing.\r\n\tVOLUME_TYPE_5_CHANNEL_DOLBY5_1\t\t// Five discreet volumes, as per Dolby 5.1.\r\n};\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstruct sVolume\r\n{\r\n\tenum\r\n\t{\r\n\t\tMAX_CHANNELS = 5\r\n\t};\r\n\tfloat\t\t\t\tm_channels[MAX_CHANNELS];\t// Can store up to five discreet channel volumes.\r\n\tEVolumeType\t\t\tm_volume_type;\t\t\t\t// The type of the volume.\r\n\r\n\t\t\t\t\t\tsVolume( void );\r\n\t\t\t\t\t\tsVolume( EVolumeType type );\r\n\t\t\t\t\t\tsVolume( const sVolume& rhs );\r\n\t\t\t\t\t\t~sVolume( void );\r\n\tbool\t\t\t\toperator== ( const sVolume& rhs );\r\n\tbool\t\t\t\toperator!= ( const sVolume& rhs )\t\t\t{ return !(*this == rhs); }\r\n\tbool\t\t\t\tIsSilent( void );\r\n\tvoid\t\t\t\tSetSilent( void );\r\n\tEVolumeType\t\t\tGetVolumeType( void )\t\t\t\t\t\t{ return m_volume_type; }\r\n\tfloat\t\t\t\tGetChannelVolume( uint32 chan )\t\t\t\t{ return m_channels[chan]; }\r\n\tvoid\t\t\t\tSetChannelVolume( uint32 chan, float vol )\t{ m_channels[chan] = vol; }\r\n\tvoid\t\t\t\tPercentageAdjustment( float percentage );\r\n\tfloat\t\t\t\tGetLoudestChannel( void );\r\n};\r\n\r\nstruct PositionalSoundEntry;\r\n\r\nstruct SoundUpdateInfo\r\n{\r\n\t// So each instance of Obj_PlaySound maintains the values sent in by the designer:\r\n\tfloat pitch; \r\n\tfloat volume;\r\n\tfloat dropoffDist;\r\n\tEDropoffFunc dropoffFunction;\r\n};\r\n\r\n\r\nclass CSfxManager : public Spt::Class\r\n{\r\n\tDeclareSingletonClass( CSfxManager );\r\n\r\npublic:\r\n\t\t\t\t\tCSfxManager( void );\r\n\t\t\t\t    ~CSfxManager( void );\r\n\r\n\tint\t\t\t\tMemAvailable( void );\r\n\r\n\tbool\t\t\tLoadSound( const char *sfxName,  int flags = 0, float dropoff = 0.0f, float pitch = 100.0f, float volume = 100.0f );\r\n\tuint32\t\t\tPlaySound( uint32 checksum, sVolume *p_vol, float pitch = 100.0f, uint32 controlID = 0, SoundUpdateInfo *pUpdateInfo = NULL, const char *pSoundName = NULL );\r\n\tuint32\t\t\tPlaySoundWithPos( uint32 soundChecksum, SoundUpdateInfo *pUpdateInfo, Obj::CSoundComponent *pObj, bool noPosUpdate );\r\n\tObjectSoundInfo\t*GetObjectSoundProperties( Obj::CSoundComponent *pObj, uint32 checksum );\r\n\r\n\tvoid\t\t\tCleanUp( void );\r\n\tvoid\t\t\tStopAllSounds( void );\r\n\tbool\t\t\tStopSound( uint32 uniqueID );\r\n\tbool\t\t\tSetSoundParams( uint32 uniqueID, sVolume *p_vol, float pitch = 100.0f );\t// For non-object sounds\r\n\tvoid\t\t\tStopObjectSound( Obj::CSoundComponent *pObj, uint32 checksum );\r\n\tvoid\t\t\tPauseSounds( void );\r\n\tvoid\t\t\tSetReverb( float reverbLevel, int reverbMode = 0, bool instant = false );\r\n\tbool\t\t\tSoundIsPlaying( uint32 uniqueID, int *pWhichVoice = NULL );\r\n\tint\t\t\t\tGetNumSoundsPlaying();\r\n\tvoid\t\t\tSetMainVolume( float volume );\r\n\tvoid\t\t\tSetDefaultDropoffDist( float dist );\r\n\tvoid\t\t\tSetVolumeFromPos( sVolume *p_vol, const Mth::Vector &soundSource, float dropoffDist,\r\n\t\t\t\t\t\t\t\t\t  EDropoffFunc dropoff_func = DROPOFF_FUNC_STANDARD,\r\n\t\t\t\t\t\t\t\t\t  Gfx::Camera* pCamera = NULL, const Mth::Vector *p_dropoff_pos = NULL );\r\n\tvoid\t\t\tAdjustPitchForDoppler( float *pitch, const Mth::Vector &currentPos, const Mth::Vector &oldPos, float elapsedTime, Gfx::Camera* pCam = NULL );\r\n\tvoid\t\t\tGet5ChannelMultipliers( const Mth::Vector &sound_source, float *p_multipliers );\r\n\tvoid\t\t\tGet5ChannelMultipliers( float angle, float *p_multipliers );\r\n\r\n\t// A per-frame function. Does nothing on PS2, on Xbox checks for stop notification events.\r\n\tvoid\t\t\tUpdate( void );\r\n\tvoid\t\t\tUpdatePositionalSounds( void );\r\n\t\r\n\t// If, for some reason, the sound has stopped playing, this returns false, true otherwise.\r\n\tbool\t\t\tUpdateLoopingSound( uint32 soundID, sVolume *p_vol, float pitch = 100.0f );\r\n\r\n\tfloat\t\t\tGetMainVolume( void );\r\n\tfloat\t\t\tGetDropoffDist( uint32 soundChecksum );\r\n\r\n\t// -1 on failure (sound not loaded)\r\n\tWaveTableEntry*\tGetWaveTableIndex( uint32 checksum );\r\n\r\n\tvoid\t\t\tObjectBeingRemoved( Obj::CSoundComponent *pObj );\r\n\t\t\r\n\tvoid\t\t\tSetDefaultVolumeType( EVolumeType type )\t{ m_default_volume_type = type; }\r\n\tEVolumeType\t\tGetDefaultVolumeType( void )\t\t\t\t{ return m_default_volume_type; }\r\n\r\n\tbool\t\t\tPositionalSoundSilenceMode();\t\t// Returns true if in mode where environment sounds should be a 0 volume\r\n\t\r\nprivate:\r\n\r\n\tEVolumeType\t\tm_default_volume_type;\r\n\r\n\tbool\t\t\tAdjustObjectSound( Obj::CSoundComponent *pObj, VoiceInfo *pVoiceInfo, Tmr::Time gameTime );\r\n\tvoid\t\t\tTweakVolumeAndPitch( sVolume* p_vol, float *pitch, WaveTableEntry* waveTableIndex );\r\n\tvoid\t\t\tRemovePositionalSoundFromList( PositionalSoundEntry *pEntry, bool stopIfPlaying );\r\n\tvoid\t\t\tAddPositionalSoundToUpdateList( uint32 uniqueID, uint32 soundChecksum, Obj::CSoundComponent *pObj = NULL );\r\n\r\n\t// UniqueID functions\r\n\tbool\t\t\tIDAvailable(uint32 id);\r\n\tint\t\t\t\tGetVoiceFromID(uint32 id);\r\n\tuint32\t\t\tGenerateUniqueID(uint32 id);\r\n};\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern int\t\t\t\tNumWavesInTable;\r\nextern int\t\t\t\tNumWavesInPermTable;\r\nextern int\t\t\t\tNumPositionalSounds;\r\nextern WaveTableEntry\tWaveTable[PERM_WAVE_TABLE_MAX_ENTRIES + WAVE_TABLE_MAX_ENTRIES];\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\nbool\t\t\tNoSoundPlease();\r\nEDropoffFunc\tGetDropoffFunctionFromChecksum(uint32 checksum);\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Sfx\r\n\r\n#endif\t// __GEL_SOUNDFX_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/inpman.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tInput  (Inp)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/inpman.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/26/2000\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_INPMAN_H\r\n#define __GEL_INPMAN_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/singleton.h>\r\n#include <core/list.h>\r\n#include <core/task.h>\r\n\r\n#include <sys/sioman.h>\r\n#include <sys/siodev.h>\r\n \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#define PAD_NONE 0\r\n#define PAD_U 1\r\n#define PAD_D 2\r\n#define PAD_L 3\r\n#define PAD_R 4\r\n#define PAD_UL 5\r\n#define PAD_UR 6\r\n#define PAD_DL 7\r\n#define PAD_DR 8\r\n#define PAD_CIRCLE 9\r\n#define PAD_SQUARE 10\r\n#define PAD_X 11\r\n#define PAD_TRIANGLE 12\r\n#define PAD_L1 13\r\n#define PAD_L2 14\r\n#define PAD_L3 15\r\n#define PAD_R1 16\r\n#define PAD_R2 17\r\n#define PAD_R3 18\r\n#define PAD_BLACK 19\r\n#define PAD_WHITE 20\r\n#define PAD_Z 21\r\n#define PAD_NUMBUTTONS 22\r\n\r\nnamespace Inp\r\n{\r\n\r\n\r\n\r\nstatic const int vANALOGUE_TOL      = 50;\t\t\t// Mick, changed back from 32, as our controllers were wandering...\r\nstatic const int vANALOGUE_CENTER   = 128;\r\n\r\n\r\nextern uint32\tgDebugButtons[];\r\nextern uint32\tgDebugBreaks[];\r\nextern uint32\tgDebugMakes[];\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint GetButtonIndex(uint32 Checksum);\r\nuint32 GetButtonChecksum( int whichButton );\r\n\r\nclass  Data  : public Spt::Class\r\n{   \r\n\t\r\n\r\npublic:\r\n\r\n        friend class Server;\r\n\r\n\t\t\t\t\t\tData( void );\r\n\r\n#define vMAX_ANALOG_VALUE   255\r\n\r\n    enum DigitalButtonIndex\r\n\t{      \r\n        vD_L2,\r\n        vD_R2,\r\n        vD_L1,\r\n        vD_R1,\r\n        vD_TRIANGLE,\r\n        vD_CIRCLE,\r\n        vD_X,\r\n        vD_SQUARE,\r\n        vD_SELECT,\r\n        vD_L3,\r\n        vD_R3,\r\n        vD_START,\r\n        vD_UP,\r\n        vD_RIGHT,\r\n        vD_DOWN,\r\n\t\tvD_LEFT,\r\n\t\tvD_BLACK,\t// Only supported on XBox\r\n\t\tvD_WHITE,\t// Only supported on XBox\r\n\t\tvD_Z,\t\t// Only supported on NGC\r\n        vMAX_DIGITAL_EVENTS\r\n    };\r\n       \r\n    enum AnalogButtonIndex\r\n    {\r\n        vA_RIGHT_X,         // Right analog controller stick\r\n\t\tvA_RIGHT_Y,\r\n\t\tvA_LEFT_X,          // Left analog controller stick\r\n\t\tvA_LEFT_Y,\r\n        vA_RIGHT,\r\n        vA_LEFT,\r\n        vA_UP,\r\n        vA_DOWN,\r\n        vA_TRIANGLE,\r\n        vA_CIRCLE,\r\n        vA_X,\r\n        vA_SQUARE,\r\n        vA_L1,\r\n        vA_R1,\r\n        vA_L2,\r\n        vA_R2,\r\n        vA_L3,\r\n        vA_R3,\r\n\t\t// (Mick) Added the following to stop the analog values before they are clamped\r\n\t\t// these values only get clamped if BOTH X and Y are in the middle\r\n\t\t// the above values clamp X and Y independently\r\n\t\t// leading to dead zones when rotating the stick round in a circle\r\n\t\t// a significant loss in accuracy\r\n        vA_RIGHT_X_UNCLAMPED,         // Right analog controller stick\r\n\t\tvA_RIGHT_Y_UNCLAMPED,\r\n\t\tvA_LEFT_X_UNCLAMPED,          // Left analog controller stick\r\n\t\tvA_LEFT_Y_UNCLAMPED,\r\n\t\t\r\n\t\tvA_BLACK,\t\t\t\t\t// Only supported on XBox\r\n\t\tvA_WHITE,\t\t\t\t\t// Only supported on XBox\r\n\t\t\r\n\t\tvA_Z,\t\t\t\t\t\t// Only supported on XBox\r\n\r\n//\t\tvA_SELECT,\t\t\r\n\t\t\t\t\t   \r\n\t\tvMAX_ANALOG_EVENTS\r\n\t};\r\n\r\n\tenum DigitalButtonMask\r\n\t{\r\n        // These map directly to digital input in m_Buttons, m_Prev and m_New\r\n        mD_L2           = nBit( vD_L2 ),\r\n        mD_R2           = nBit( vD_R2 ),\r\n        mD_L1           = nBit( vD_L1 ),\r\n        mD_R1           = nBit( vD_R1 ),\r\n        mD_TRIANGLE     = nBit( vD_TRIANGLE ),\r\n\t\tmD_CIRCLE       = nBit( vD_CIRCLE ),\r\n        mD_X            = nBit( vD_X ),\r\n        mD_SQUARE       = nBit( vD_SQUARE ),\r\n        mD_SELECT       = nBit( vD_SELECT ),\r\n        mD_L3           = nBit( vD_L3 ),\r\n        mD_R3           = nBit( vD_R3 ),\r\n        mD_START        = nBit( vD_START ),\r\n        mD_UP           = nBit( vD_UP ),\r\n        mD_RIGHT        = nBit( vD_RIGHT ),\r\n        mD_DOWN         = nBit( vD_DOWN ),\r\n        mD_LEFT         = nBit( vD_LEFT ),\r\n\t\tmD_BLACK\t\t= nBit( vD_BLACK ),\r\n\t\tmD_WHITE\t\t= nBit( vD_WHITE ),\r\n\t\tmD_Z\t\t\t= nBit( vD_Z ),\r\n        mD_ALL          = 0xffffffff\r\n\t};\r\n\r\n    enum AnalogButtonMask\r\n    {    \r\n        // These map indirectly to analog input in m_Events\r\n\t\tmA_RIGHT_X      = nBit( vA_RIGHT_X ),         // Right analog controller stick\r\n\t\tmA_RIGHT_Y      = nBit( vA_RIGHT_Y ),\r\n\t\tmA_LEFT_X       = nBit( vA_LEFT_X ),          // Left analog controller stick\r\n\t\tmA_LEFT_Y       = nBit( vA_LEFT_Y ),\r\n        mA_RIGHT        = nBit( vA_RIGHT ),\r\n        mA_LEFT         = nBit( vA_LEFT ),\r\n        mA_UP           = nBit( vA_UP ),\r\n        mA_DOWN         = nBit( vA_DOWN ),\r\n        mA_TRIANGLE     = nBit( vA_TRIANGLE ),\r\n        mA_CIRCLE       = nBit( vA_CIRCLE ),\r\n        mA_X            = nBit( vA_X ),\r\n        mA_SQUARE       = nBit( vA_SQUARE ),\r\n        mA_L1           = nBit( vA_L1 ),\r\n        mA_R1           = nBit( vA_R1 ),\r\n        mA_L2           = nBit( vA_L2 ),\r\n        mA_R2           = nBit( vA_R2 ),\r\n        mA_L3           = nBit( vA_L3 ),\r\n        mA_R3           = nBit( vA_R3 ),\r\n        mA_BLACK        = nBit( vA_BLACK ),\r\n        mA_WHITE        = nBit( vA_WHITE ),\r\n        mA_Z\t        = nBit( vA_Z ),\r\n//\t\tmA_SELECT\t\t= nBit( vA_SELECT ),\r\n        mA_ALL          = 0xffffffff\r\n\t};\r\n\t\r\n\r\n\tvoid    MaskDigitalInput( int button_mask );\r\n    void    MaskAnalogInput( int button_mask );\r\n    void    ConvertDigitalToAnalog( void );\r\n\tvoid\tOverrideAnalogPadWithStick( void );\r\n\r\n\tuint8   m_Event[vMAX_ANALOG_EVENTS];\t// Analog info\r\n\tuint    m_Buttons;              // Current accessible button info (digital)   \r\n    uint    m_Makes;                // Depressed this frame\r\n    uint    m_Breaks;               // Released this frame\r\n\r\nprivate:\r\n\r\n\tuint    m_new;                  // Edges (digital)\r\n\tuint    m_cur;              \t// Current INTERNAL button info (digital)\r\n\tuint    m_prev;                 // last frame's trig\r\n\t\r\n    void    handle_analog_tolerance( void );\r\n};\r\n\r\nclass  RecordedData  : public Spt::Class\r\n{\r\n\t\r\n\t\r\n\tfriend class Server;\r\n\r\nprivate:\t\r\n\tsint8\tm_valid;\t\t\t\t\t\t\t\t// Was data valid on this frame?\r\n\tuint8   m_event[Data::vMAX_ANALOG_EVENTS];\t\t// Analog info\r\n\tuint    m_cur;              \t\t\t\t\t// Current INTERNAL button info (digital)     \r\n\t\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  BaseHandler : public  Tsk::BaseTask \r\n{\r\n\t\r\n\r\n    friend class Manager;\r\n\r\npublic:\r\n\tData*           m_Input;          // controller input  \r\n    SIO::Device     *m_Device;        // the device from which this data was obtained\r\n\tint\t\t\t\tm_Index;\r\n\r\nprotected:\r\n                    BaseHandler ( int index, Tsk::BaseTask::Node::Priority pri )\r\n\t\t\t\t\t: Tsk::BaseTask( pri ), m_Index ( index ) \r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_Printf( \"Creating BaseHandler with Pri %d\\n\", pri );\r\n\t\t\t\t\t}\r\n                    \r\n\r\n    virtual         ~BaseHandler ( void ) {}\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nnTemplateSubClass( _T, Handler, BaseHandler )\r\n{\r\n\t\r\n\r\npublic:\r\n\r\n\ttypedef void\t(Code)( const Handler< _T >& );\r\n\r\n\t\t\t\t\tHandler( int index, Code* const code, _T& data, \r\n                             Lst::Node< Tsk::BaseTask >::Priority pri = Lst::Node< Tsk::BaseTask >::vNORMAL_PRIORITY );\r\n\t\t\r\n    virtual         ~Handler ( void );\r\n\r\n\tvirtual void\tvCall( void ) const;\r\n\tvirtual void *\tGetCode(void) const;\r\n\t_T&\t\t\t\tGetData( void ) const;\r\n\r\nprivate :\r\n\r\n\tCode* const\t\tcode;\t\t\t// tasks entry point\r\n\t_T&\t\t\t\tdata;\t\t\t// task defined data                    \r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/                                                                   \r\n                                                                   \r\n//class  Server  : public Spt::Class // note - need compiler fix for delete[] bug!!!\r\nclass Server\r\n{\r\n//\t \r\n\r\n\tfriend class Manager;\r\n\r\npublic:\r\n\t\t\t\tServer();\r\n\t\t\t\t\r\n\tvoid\t\tRecordInput( RecordedData *data_buffer );\r\n\tvoid\t\tPlaybackInput( RecordedData *recorded_input );\r\n\t\r\nprivate:\r\n\r\n    void        service_handlers( void );\r\n\r\n\tSIO::Device                 *m_device;\r\n\tTsk::Stack\t                m_handler_stack;\r\n\tData                        m_data;\r\n\t\r\n\tRecordedData\t\t\t\t*m_data_in;\r\n\tvoid\t\t\t\t\t\t*m_data_in_end;\r\n\tRecordedData\t\t\t\t*m_data_out;\r\n\tvoid\t\t\t\t\t\t*m_data_out_end;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  Manager  : public Spt::Class\r\n{\r\n\t                    \r\n\r\npublic :\r\n\r\n\tvoid                        AddHandler( BaseHandler &handler );\r\n\tvoid\t\t\t\t\t\tReassignHandler( BaseHandler &handler, int new_index );\r\n\tvoid                        AddPushHandler( BaseHandler &handler );\r\n\tTsk::BaseTask&\t\t\t\tGetProcessHandlersTask ( void ) const;\r\n\t\r\n\tvoid\t\t\t\t\t\tRecordInput( int index, RecordedData *data_buffer, int byte_length );\r\n\tvoid\t\t\t\t\t\tPlaybackInput( int index, RecordedData *recorded_input, int byte_length );\r\n\tvoid\t\t\t\t\t\tPushInputLogicTasks( void );\r\n\tvoid\t\t\t\t\t\tPopInputLogicTasks( void );\r\n\tbool\t\t\t\t\t\tActuatorEnabled( int i );\r\n\t\r\n\tvoid\t\t\t\t\t\tDisableActuators( void );\r\n\tvoid\t\t\t\t\t\tDisableActuator( int i );\r\n\t\r\n\tvoid\t\t\t\t\t\tEnableActuators( void );\r\n\tvoid\t\t\t\t\t\tEnableActuator( int i );\r\n\tvoid\t\t\t\t\t\tResetActuators( void );\r\n\r\n\tvoid\t\t\t\t\t\tSetAnalogStickOverride( bool should_override_pad );\r\n\tbool\t\t\t\t\t\tShouldAnalogStickOverride( void );\r\n\r\nprivate :\r\n\t\t\t\t\t\t\t\t~Manager ( void );\r\n\t\t\t\t\t\t\t\tManager ( void );\r\n\r\n\tstatic Tsk::Task< Manager >::Code\tprocess_handlers;\r\n\t\t\t\t\t\t\t\t\r\n\tTsk::Task< Manager >*\t\tm_process_handlers_task;\r\n\tServer                      m_server[SIO::vMAX_DEVICES];\r\n\tbool\t\t\t\t\t\tm_override_pad_with_stick;\r\n\t\r\n\tDeclareSingletonClass( Manager );\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline\tTsk::BaseTask&\tManager::GetProcessHandlersTask ( void ) const\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType ( m_process_handlers_task, Tsk::BaseTask );\r\n\r\n\treturn\t*m_process_handlers_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void Manager::AddHandler ( BaseHandler &handler )\r\n{\r\n\t\r\n\r\n    Dbg_MsgAssert( handler.m_Index < SIO::vMAX_DEVICES,( \"Invalid controller index\" ));\r\n\t\r\n    m_server[handler.m_Index].m_handler_stack.AddTask( handler );\r\n    handler.m_Input = &m_server[handler.m_Index].m_data;\r\n    handler.m_Device = m_server[handler.m_Index].m_device;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void Manager::ReassignHandler( BaseHandler &handler, int new_index )\r\n{\r\n\tDbg_MsgAssert( new_index < SIO::vMAX_DEVICES,( \"Invalid controller index\" ));\r\n\r\n\thandler.Remove();\r\n\tm_server[new_index].m_handler_stack.AddTask( handler );\r\n    handler.m_Input = &m_server[new_index].m_data;\r\n    handler.m_Device = m_server[new_index].m_device;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void Manager::AddPushHandler ( BaseHandler &handler )\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert( handler.m_Index < SIO::vMAX_DEVICES,( \"Invalid controller index\" ));\r\n\t\r\n    m_server[handler.m_Index].m_handler_stack.AddPushTask( handler );\r\n    handler.m_Input = &m_server[handler.m_Index].m_data;\r\n    handler.m_Device = m_server[handler.m_Index].m_device;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline \r\nHandler< _T >::Handler( int index, Code* const _code, _T& _data, Tsk::BaseTask::Node::Priority pri )\r\n: BaseHandler( index, pri ), code( _code ), data( _data ) \r\n{\r\n    \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline \r\nHandler< _T >::~Handler( void )\r\n{\r\n    \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline \r\nvoid\t\tHandler< _T >::vCall( void ) const\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertPtr( code );\r\n\tcode( *this );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline \r\n_T&\t\tHandler< _T >::GetData( void ) const\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( &data, _T );\r\n\treturn data;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline \r\nvoid *\t\tHandler< _T >::GetCode( void ) const\r\n{\r\n\t\r\n\r\n\treturn NULL;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Inp\r\n\r\n#endif\t// __GEL_INPMAN_H\r\n"
  },
  {
    "path": "Code/Gel/mainloop.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMain Loop Module (ML)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/mainloop.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_MAINLOOP_H\r\n#define __GEL_MAINLOOP_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/singleton.h>\r\n#include <core/task.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n   \r\nnamespace Mlp\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  Manager  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic :\r\n\r\n\tenum ELogicMask\r\n\t{\r\n\t\tmNONE\t\t\t= 0,\r\n\t\tmSKATE_MOD \t\t= (1<<1), // skate module\r\n\t\tmGAME_OBJECTS\t= (1<<2), // game objects\r\n\t\tmGFX_MANAGER\t= (1<<3), // gfx manager\r\n\t};\r\n\r\n\tvoid\t\t\t\tRegisterRenderStartHook ( Tsk::BaseHook* start_hook );\r\n\tvoid\t\t\t\tRegisterRenderEndHook ( Tsk::BaseHook* end_hook );\r\n\r\n\tTsk::BaseHook*\t\tGetRenderStartHook( void );\r\n\tTsk::BaseHook*\t\tGetRenderEndHook( void );\r\n\t\r\n\tvoid\t\t\t\tMainLoop ( void );\r\n\tvoid\t\t\t\tQuitLoop ( void );\r\n\tvoid\t\t\t\tDoGameLogic( void );\r\n\r\n\tvoid\t\t\t\tPauseDisplayTasks( bool pause = true );\r\n\tvoid\t\t\t\tRemoveAllDisplayTasks ( void );\r\n\tvoid\t\t\t\tRemoveAllLogicTasks ( void );\r\n\tvoid\t\t\t\tRemoveAllSystemTasks ( void );\r\n\t\r\n\tvoid\t\t\t\tPushLogicTasks ( void );\r\n\tvoid\t\t\t\tPushDisplayTasks ( void );\r\n\tvoid\t\t\t\tPushSystemTasks ( void );\r\n\t\r\n\tvoid\t\t\t\tPopLogicTasks ( void );\r\n\tvoid\t\t\t\tPopDisplayTasks ( void );\r\n\tvoid\t\t\t\tPopSystemTasks ( void );\r\n\r\n\tvoid\t\t\t\tAddLogicTask ( Tsk::BaseTask& task );\r\n\tvoid\t\t\t\tAddDisplayTask ( Tsk::BaseTask& task );\r\n\tvoid\t\t\t\tAddSystemTask ( Tsk::BaseTask& task );\r\n\r\n\tvoid\t\t\t\tAddLogicPushTask ( Tsk::BaseTask& task );\r\n\tvoid\t\t\t\tAddDisplayPushTask ( Tsk::BaseTask& task );\r\n\tvoid\t\t\t\tAddSystemPushTask ( Tsk::BaseTask& task );\r\n\r\n\tvoid\t\t\t\tProfileTasks(int n=1);\r\n\tvoid\t\t\t\tSetLogicMask ( uint mask );\r\n\r\n\tbool\t\t\t\tIsProfiling(){return currently_profiling;}\r\n\t\r\nprivate :\r\n\t\t\t\t\t\tManager ( void );\r\n\t\t\t\t\t\t~Manager ( void );\r\n\r\n\tvoid\t\t\t\tgame_logic ( void );\r\n\tvoid\t\t\t\trender_frame ( void );\r\n\tvoid\t\t\t\tservice_system ( void );\r\n\r\n\tbool\t\t\t\tdone;\r\n\tTsk::Stack\t\t\tlogic_task_stack;\r\n\tTsk::Stack\t\t\tdisplay_task_stack;\r\n\tTsk::Stack\t\t\tsystem_task_stack;\r\n\tTsk::BaseHook*\t\tstart_render_hook;\r\n\tTsk::BaseHook*\t\tend_render_hook;\r\n\r\n\tbool\t\t\t\tdisplay_tasks_paused;\r\n\t\r\n\tint\t\t\t\ttrigger_profiling;\r\n\tint\t\t\t\tcurrently_profiling;\r\n\t\r\n\tDeclareSingletonClass( Manager );\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline\tvoid\t\tManager::RegisterRenderStartHook ( Tsk::BaseHook* start_hook )\r\n{\r\n   \t\r\n\r\n    start_render_hook = start_hook;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::RegisterRenderEndHook ( Tsk::BaseHook* end_hook )\r\n{\r\n   \t\r\n\t\r\n\tend_render_hook = end_hook;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Tsk::BaseHook*\tManager::GetRenderStartHook( void )\r\n{\r\n\t\r\n\r\n\treturn start_render_hook;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Tsk::BaseHook*\tManager::GetRenderEndHook( void )\r\n{\r\n\t\r\n\r\n\treturn end_render_hook;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::AddLogicTask ( Tsk::BaseTask& task )\r\n{\r\n   \t\r\n\t\r\n\tDbg_AssertType ( &task, Tsk::BaseTask );\r\n\r\n\tlogic_task_stack.AddTask ( task );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::SetLogicMask ( uint mask )\r\n{\r\n   \t\r\n\r\n\tlogic_task_stack.SetMask ( (uint) mask );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::AddDisplayTask ( Tsk::BaseTask& task )\r\n{\r\n   \t\r\n\t\r\n\tDbg_AssertType ( &task, Tsk::BaseTask );\r\n\r\n\tdisplay_task_stack.AddTask ( task );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::AddSystemTask ( Tsk::BaseTask& task )\r\n{\r\n   \t\r\n\t\r\n\tDbg_AssertType ( &task, Tsk::BaseTask );\r\n\r\n\tsystem_task_stack.AddTask ( task );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::AddSystemPushTask ( Tsk::BaseTask& task )\r\n{\r\n   \t\r\n\t\r\n\tDbg_AssertType ( &task, Tsk::BaseTask );\r\n\r\n\tsystem_task_stack.AddPushTask ( task );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::AddLogicPushTask ( Tsk::BaseTask& task )\r\n{\r\n   \t\r\n\t\r\n\tDbg_AssertType ( &task, Tsk::BaseTask );\r\n\r\n\tlogic_task_stack.AddPushTask ( task );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::AddDisplayPushTask ( Tsk::BaseTask& task )\r\n{\r\n   \t\r\n\t\r\n\tDbg_AssertType ( &task, Tsk::BaseTask );\r\n\r\n\tdisplay_task_stack.AddPushTask ( task );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::RemoveAllDisplayTasks ( void )\r\n{\r\n   \t\r\n\r\n\tdisplay_task_stack.RemoveAllTasks ();\r\n}\r\n\r\ninline void\t\tManager::PauseDisplayTasks( bool pause )\r\n{\r\n   \t\r\n\tdisplay_tasks_paused = pause;\r\n\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::RemoveAllLogicTasks ( void )\r\n{\r\n   \t\r\n\r\n\tlogic_task_stack.RemoveAllTasks ();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::RemoveAllSystemTasks ( void )\r\n{\r\n   \t\r\n\r\n\tsystem_task_stack.RemoveAllTasks ();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::PushLogicTasks ( void )\r\n{\r\n   \t\r\n\r\n\tlogic_task_stack.Push ();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::PushDisplayTasks ( void )\r\n{\r\n   \t\r\n\r\n\tdisplay_task_stack.Push ();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::PushSystemTasks ( void )\r\n{\r\n   \t\r\n\r\n\tsystem_task_stack.Push ();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::PopLogicTasks ( void )\r\n{\r\n   \t\r\n\r\n\tlogic_task_stack.Pop ();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::PopDisplayTasks ( void )\r\n{\r\n   \t\r\n\r\n\tdisplay_task_stack.Pop ();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tManager::PopSystemTasks ( void )\r\n{\r\n   \t\r\n\r\n\tsystem_task_stack.Pop ();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mlp\r\n\r\n#endif\t// __GEL_MAINLOOP_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gel/modman.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tModule  (MDL)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/modman.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_MODMAN_H\r\n#define __GEL_MODMAN_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/support.h>\r\n#include <core/singleton.h>\r\n#include <core/list.h>\r\n#include <core/task.h>\r\n#include <gel/module.h>\r\n\t\t\t\t\t  \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mdl\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  Manager  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic :\r\n\t\r\n\tvoid\t\t\t\t\t\tRegisterModule ( Module &module );\r\n\tvoid\t\t\t\t\t\tUnregisterModule ( Module &module );\r\n\r\n\tvoid\t\t\t\t\t\tStartModule ( Module &module );\r\n\tvoid\t\t\t\t\t\tRestartModule( Module &module );\r\n\tvoid\t\t\t\t\t\tStopModule ( Module &module );\r\n\tvoid\t\t\t\t\t\tStartAllModules ( void );\r\n\tvoid\t\t\t\t\t\tStopAllModules ( void );\r\n\r\n\tvoid\t\t\t\t\t\tLockAllModules ( void );\r\n\tvoid\t\t\t\t\t\tUnlockAllModules ( void );\r\n\r\n\tTsk::BaseTask&\t\t\t\tGetProcessModulesTask ( void ) const;\r\n\t\r\n\r\nprivate :\r\n\t\t\t\t\t\t\t\tManager ( void );\r\n\t\t\t\t\t\t\t\t~Manager ( void );\r\n\r\n\tstatic Tsk::Task< Manager >::Code\tprocess_modules;\r\n\t\t\t\t\t\t\t\t\r\n\tTsk::Task< Manager >*\t\tprocess_modules_task;\r\n\tLst::Head< Module >\t\t\tmodule_list;\r\n\tbool\t\t\t\t\t\tcontrol_change;\r\n\t\t\r\n\tDeclareSingletonClass( Manager );\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline\tTsk::BaseTask&\tManager::GetProcessModulesTask ( void ) const\r\n{\r\n   \t\r\n\t\r\n\tDbg_AssertType ( process_modules_task, Tsk::BaseTask );\r\n\r\n\treturn\t*process_modules_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mdl\r\n\r\n#endif\t// __GEL_MODMAN_H\r\n"
  },
  {
    "path": "Code/Gel/module.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tModule  (MDL)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/module.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_MODULE_H\r\n#define __GEL_MODULE_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/support.h>\r\n#include <core/task.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mdl\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  Module  : public Spt::Class\r\n{\r\n\t\r\n\r\n\tfriend class\t\t\tManager;\r\n\r\n\tfriend Tsk::Task< Manager >::Code\tMDL_process_modules;\r\n\r\npublic :\r\n\r\n\t\t\t\t\t\t\tModule ( void );\r\n\tvirtual\t \t\t\t\t~Module ( void );\r\n\r\n\tvoid\t\t\t\t\tLock ( void );\r\n\tvoid\t\t\t\t\tUnlock ( void );\r\n\r\n\tbool\t\t\t\t\tRunning ( void ) const;\r\n\tbool\t\t\t\t\tLocked ( void ) const;\r\n\r\nprivate :\r\n\r\n\tenum State\r\n\t{\r\n\t\tvSTOPPED,\r\n\t\tvRUNNING\r\n\t};\r\n\r\n\tenum Command\r\n\t{\r\n\t\tvNONE,\r\n\t\tvSTART,\r\n\t\tvSTOP,\r\n\t\tvRESTART,\r\n\t};\r\n\tvirtual\tvoid\t\t\tv_start_cb ( void ) = 0;\r\n\tvirtual\tvoid\t\t\tv_stop_cb ( void ) = 0;\r\n\r\n\tState\t\t\t\t\tstate;\r\n\tCommand\t\t\t\t\tcommand;\r\n\tbool\t\t\t\t\tlocked;\r\n\tLst::Node<Module>*\t\tnode;\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline void\t\t\tModule::Lock ( void )\r\n{\r\n   \t\r\n\r\n\tlocked = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\tModule::Unlock ( void )\r\n{\r\n   \t\r\n\r\n\tlocked = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tbool\t\tModule::Locked ( void ) const\r\n{\r\n   \t\r\n\r\n\treturn locked;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\tModule::Running ( void ) const\r\n{\r\n   \t\r\n\r\n\treturn ( state == vRUNNING );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mdl\r\n\r\n#endif\t// __GEL_MODULE_H\r\n"
  },
  {
    "path": "Code/Gel/object.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObject (OBJ)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/object.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**  Notes:\r\n**\r\n**  (Mick) This is the base type for all objects in the game.  It contains basic\r\n**  mechanisms for maintaining a list of object associated with Object Servers\r\n**  and procedures for deleting them\r\n**  There are also hooks into the CScript class, in that an object has a \r\n**  reference to a script, and a virtual function CallMember, which allows \r\n**  the script to call a member function by name (actually by checksum of the name)  \r\n**\r\n**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_OBJECT_H\r\n#define __GEL_OBJECT_H\r\n\r\n#define\t__SCRIPT_EVENT_TABLE__\t\t// define this is you want event tables attached to scripts, rather than objects\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/list.h>\r\n#include <core/macros.h>\r\n#include <core/math.h>\r\n\r\n#include <sys/timer.h>\r\n\r\n#include <gel/ObjPtr.h>\r\n#include <gel/RefCounted.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n}\t\r\n\r\nstruct SBBox{\r\n\tMth::Vector m_max;\r\n\tMth::Vector m_min;\r\n\tMth::Vector centerOfGravity;\r\n\tfloat m_radius;  // will give the max distance squared where there may still be a collision.\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define OBJECT_FLAG_INVISIBLE\t1\r\n\r\nnamespace Front\r\n{\r\n\tclass CScreenElementManager;\r\n}\r\n\r\nnamespace Script\r\n{\r\n\tclass CArray;\r\n}\r\n\r\nenum EReplaceEventHandlers\r\n{\r\n\tDONT_REPLACE_HANDLERS = 0,\r\n\tREPLACE_HANDLER\r\n};\r\n\r\n\r\nnamespace Obj\t\t\t \r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CEvent;\r\nclass CEventHandlerTable;\r\nclass CBaseManager;\r\nclass CGeneralManager;\r\nclass CObject;\r\ntypedef CSmtPtr<CObject> CObjectPtr;\r\n\r\n\r\n/*\r\n\tCObject is described in more detail in: Q:\\sk4\\Docs\\programming\\Object Scripting System.htm\r\n\t\r\n\tThe base class for all scriptable objects. Every CObject has a global ID that\r\n\tis unique among all CObjects. It also has a type specifier.\r\n\t\r\n\tA script that is running can reference a CObject. The script can access special\r\n\tcommands for that CObject through CallMemberFunction().\tTags, which are like\r\n\tscriptable member variables, can be attached from CObjects from script, too.\r\n\t\r\n\tEvent handling is supported through the PassTargetedEvent() function.\r\n*/\r\nclass  CObject  : public CRefCounted\r\n{\r\n  \t\r\n\tfriend class\t\tCBaseManager;\r\n\tfriend class\t\tCGeneralManager;\r\n\tfriend class\t\tFront::CScreenElementManager;\r\n\r\npublic :\t\t\t\t\t\t\r\n\t\t\t\t\t\tCObject();\r\n\tvirtual\t\t\t\t~CObject ( void );\r\n\r\n\tvoid\t\t\t\tDestroyIfUnlocked ();\t\t\t\t// Destroy immediately \r\n\r\n\tvoid\t\t\t\tAddReference ( void );\r\n\tvoid\t\t\t\tRemoveReference ( void );\r\n\tbool\t\t\t\tIsReferenced() {return (m_ref_count > 0);}\r\n\r\n\tbool\t\t\t\tIsDead ( void ) const;\t\t\t\t// Access functions for the above\r\n\tbool\t\t\t\tIsLocked ( void ) const;\r\n\t\t\r\n\tuint32\t\t\t\tGetID() const  {return m_id;}\r\n\tsint\t\t\t\tGetType() const {return m_type;}\r\n\tvoid\t\t\t\tSetID(uint32 id);\r\n\tvoid\t\t\t\tSetType(sint type);\r\n\t\r\n\tvoid\t\t\t\tClearStampBit(uint32 stamp_mask) { m_stamp &= ~stamp_mask; }\r\n\tbool\t\t\t\tCheckStampBit(uint32 stamp_mask) const { return m_stamp & stamp_mask; }\r\n\tvoid\t\t\t\tSetStampBit(uint32 stamp_mask) { m_stamp |= stamp_mask; }\r\n\r\n\tuint32\t\t\t\tGetFlags() const {return m_object_flags;}\r\n\tvoid\t\t\t\tSetFlags(uint32 flags) {m_object_flags = flags;}\r\n\tvoid\t\t\t\tSetLockOn() {m_object_flags |= vLOCKED;}\r\n\tvoid\t\t\t\tSetLockOff() {m_object_flags &= ~vLOCKED;}\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\t\t\r\n\tvoid\t\t\t\tSetLockAssertOn() {m_object_flags |= vLOCKEDASSERT;}\r\n\tvoid\t\t\t\tSetLockAssertOff() {m_object_flags &= ~vLOCKEDASSERT;}\r\n\tbool\t\t\t\tGetLockAssert() {return m_object_flags & vLOCKEDASSERT;}\r\n\t#endif\r\n\r\n\tScript::CScript\t*\tGetScript() const {return mp_script;}\r\n\tvoid\t\t\t\tSetScript(Script::CScript* p_script) {mp_script = p_script;}\r\n\r\n\r\n\r\n\tvoid  \t\t\t\tSetEventHandlers(Script::CArray *pArray, EReplaceEventHandlers replace = DONT_REPLACE_HANDLERS);\r\n\tvoid\t\t\t\tRemoveEventHandler(uint32 type);\r\n\tvoid\t\t\t\tRemoveEventHandlerGroup(uint32 group);\r\n\t\r\n\t// See details on tags in object document\r\n\tvoid\t\t\t\tSetIntegerTag(uint32 name, int value);\r\n\tvoid\t\t\t\tSetChecksumTag(uint32 name, uint32 value);\r\n\tvoid\t\t\t\tRemoveFlagTag(uint32 name);\r\n\tbool\t\t\t\tGetIntegerTag(uint32 name, int *pResult) const ;\r\n\tbool\t\t\t\tGetChecksumTag(uint32 name, uint32 *pResult) const;\r\n\tbool\t\t\t\tContainsFlagTag(uint32 name) const;\r\n\tvoid\t\t\t\tSetTagsFromScript(Script::CStruct *pStruct);\r\n\tvoid \t\t\t\tRemoveTagsFromScript(Script::CArray *pNameArray);\r\n\tvoid\t\t\t\tCopyTagsToScriptStruct(Script::CStruct *pStruct);\r\n\tvoid \t\t\t\tSetVectorTag(uint32 name, Mth::Vector\tv);\r\n\tbool \t\t\t\tGetVectorTag(uint32 name, Mth::Vector *pResult) const;\r\n\r\n\r\n\tvoid \t\t\t\tSetOnExceptionScriptChecksum(uint32 OnExceptionScriptChecksum);\r\n\tuint32 \t\t\t\tGetOnExceptionScriptChecksum() const; \r\n\r\n\t\r\n\t// subclasses that extend next three functions should still call CObject versions\r\n\tvirtual void\t\tSetProperties(Script::CStruct *pProps);\r\n\tvirtual bool \t\tCallMemberFunction (uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript);\t// Call a member function based on the checksum of the function name\r\n\tvirtual void\t\tGetDebugInfo(Script::CStruct *p_info);\r\n\t\r\n\t// Called by CTracker singleton to pass events to this CObject\r\n\tvirtual bool\t\tPassTargetedEvent(CEvent *pEvent, bool broadcast = false);\t// return true if object still valid\r\n\r\n\tvirtual void\t\tHideForReplayPlayback() {}\r\n\tvirtual void\t\tRestoreAfterReplayPlayback() {}\r\n\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\tenum\r\n\t{\r\n\t\tvDEAD\t\t\t\t\t\t= ( 1 << 0 ),\r\n\t\t// if locked, can't be deleted\r\n\t\tvLOCKED\t\t\t\t\t\t= ( 1 << 1 ),\r\n\t\tvINVISIBLE\t\t\t\t\t= ( 1 << 2 ),\r\n\r\n\t\t// this flag has been moved to the ExceptionComponent:\r\n\t\t//\t\tvDISABLE_EXCEPTIONS\t\t\t= ( 1 << 3 ),\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\t\r\n\t\tvLOCKEDASSERT\t\t\t\t= ( 1 << 4 ),\r\n\t#endif\r\n\t\tvCOMPOSITE\t\t\t\t= ( 1 << 5 ),\r\n\t\t\r\n\t\t\r\n\t\t// RJM: flags from 8 on are reserved for children of CObject\r\n\t\t\r\n\t};\r\n\r\nprotected:\r\n\r\n\t\t\t\t\t\tCObject ( CBaseManager* );\r\n\t\r\n\tvoid\t\t\t\tallocate_tags_if_needed();\r\n\r\npublic:\t\r\n\tvoid \t\t\t\tAllocateScriptIfNeeded();\r\n\t\r\n\tvoid \t\t\t\tdebug_validate_smart_pointers(CSmtPtr<CObject> *pPtrToCheckForInclusion = NULL);\r\n\tvoid\t\t\t\tMarkAsDead( void );\t\t\t// Safe kill called from within the object's logic\r\n\r\n\tCBaseManager *\t\t\tGetManager() const\t{return mp_manager;}\t// just for exception component stuff\r\n\r\nprotected:\r\n\t\r\n\tuint32\t\t\t\tm_object_flags;\r\n\t\r\n\tCBaseManager *\t\t\tmp_manager;\r\n\t\r\n\t// object script stuff:\r\n\tScript::CScript*\tmp_script;\r\n\t\r\n\t// object ID, globally unique among CObjects\r\n\tuint32\t\t\t\tm_id;\r\n\tsint\t\t\t\tm_type;\t\t\t\t\t\t// Object type game dependent\r\n\tuint32\t\t\t\tm_stamp;\r\n\r\n#ifndef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tCEventHandlerTable *\tmp_event_handler_table;\r\n\t\r\n\t// Script to run when there is an exception\t\r\n\t// (needed here, since we are getting rid of CExceptionComponent, to replace it with one \r\n\t// single event system\r\n\tuint32 \t\t\tmOnExceptionScriptChecksum;\r\n#endif\t \r\n\r\n\t// Tags are basically variables that can be attached and queried by the scripting\r\n\t// system at runtime. Very convenient for providing state info.\r\n\tScript::CStruct\t*\t\tmp_tags;\t \r\n\r\npublic:\r\n\t// (Moved here from CMovingObject)\t\r\n\t// A set of flags that can be set using the SendFlag script command. Used for sending messages to objects.\r\n\tuint32  mScriptFlags;\r\n\tuint32\tGetFlags( Script::CStruct *pParams, Script::CScript *pScript ) const;\r\n\r\n\t// K: Used by CScript::TransmitInfoToDebugger to determine whether the CScript is the\r\n\t// main script of it's parent object.\r\n\tbool\tMainScriptIs(const Script::CScript *p_script) const {return mp_script==p_script;}\r\n\t\r\n\t// standard objects can not be paused; thus, spawned (non-main) scripts running on them should never be paused\r\n\tvirtual bool\t\tShouldUpdatePauseWithObjectScripts (   ) { return true; }\r\n\t\r\n\t// K: Also used by CScript::TransmitInfoToDebugger\r\n\tScript::CStruct *GetTags() const {return mp_tags;}\r\n\r\npublic:\r\n\t// GJ:  Made this public so that components can set their\r\n\t// parent objects' scripts\r\n\tvoid\t\t\t\tSwitchScript( uint32 scriptChecksum, Script::CStruct *pParams );\r\n\tScript::CScript*\tSpawnScriptPlease( uint32 scriptChecksum, Script::CStruct *pParams, int Id = 0, bool pause_with_object = false );\r\n\tvoid\t\t\t\tSpawnAndRunScript( uint32 ScriptChecksum, int node = -1, bool net_script = false, bool permanent = false, Script::CStruct *p_params = NULL );\r\n\tvoid\t\t\t\tSpawnAndRunScript( const char *pScriptName, int node = -1, bool net_script = false, bool permanent = false, Script::CStruct *p_params = NULL );\r\n\r\n\tvoid\t\t\t\tCallScript( uint32 ScriptChecksum, Script::CStruct *pParams );\r\n\r\n\tvoid \t\t\t\tSelfEvent(uint32 event, Script::CStruct *pData = NULL);\r\n\tvoid\t\t\t\tBroadcastEvent(uint32 event, Script::CStruct *pData = NULL, float radius = 0.0f);\r\n\t\r\nprotected:\r\n\tLst::Node< CObject >\tm_node;\r\n\t\r\nprivate:\r\n\tint\t\t\t\t\t\tm_ref_count;\r\n};\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\t\tDestroyIfUnlocked ( CObject* obj, void* data = NULL );\r\nvoid\t\tSetLockOff ( CObject* obj, void* data = NULL );\r\nCObject *\tResolveToObject(uint32 id);\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline\tvoid\t\t\tCObject::AddReference ( void )\r\n{\r\n\tm_ref_count++;\r\n}\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\t\tCObject::RemoveReference ( void )\r\n{\r\n\t//Dbg_Assert(m_ref_count > 0);\r\n\tif (m_ref_count > 0)\r\n\t{\r\n\t\tm_ref_count--;   \t\r\n\t}\r\n\t// XXX\r\n\telse\r\n\t{\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tprintf(\"Aaaah!! Removing more references than there are\\n\");\r\n\t\t#endif\r\n\t\tDbg_Assert(( m_object_flags & ( 1 << 16 )) == 0 );\r\n//\t\tif (m_object_flags & (1<<16)) //Front::CScreenElement::vIS_SCREEN_ELEMENT\r\n//\t\t\tDbg_Assert(0);\r\n\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tbool\t\t\tCObject::IsLocked ( void ) const \r\n{\r\n\treturn ( m_object_flags & ( vLOCKED ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tbool\t\t\tCObject::IsDead ( void ) const \r\n{\r\n   \t\r\n\treturn ( m_object_flags & ( vDEAD ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __GEL_OBJECT_H\r\n"
  },
  {
    "path": "Code/Gel/objman.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObject (OBJ)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/objman.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_OBJMAN_H\r\n#define __GEL_OBJMAN_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/list.h>\r\n#include <core/task.h>\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Lst\r\n{\r\n\ttemplate< class _V > class HashTable;\r\n}\r\n\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\t\r\n\t\r\n\t\r\n/*\r\n\tThis class manages usage of the bits of a uint32.  Use of CBitManager insures that no two sections of the greater code are using the same bit.  When\r\n\ta bit is requested from a CBitManager, no other requests for bits will give that bit until access to the bit has been returned to the manager.\r\n\tBit requests and returns are done in the form of uint32 masks.\r\n*/\r\nclass CBitManager\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCBitManager (   );\r\n\t\r\n\tuint32\t\t\t\t\t\tRequestBit (   );\r\n\tvoid\t\t\t\t\t\tReturnBit ( uint32 mask );\r\n\t\r\nprivate:\r\n\tuint32\t\t\t\t\t\tm_used_bit_mask;\r\n};\r\n\r\n\r\n\r\n\r\n/*\r\n\tSee document for more info on this class: Q:\\sk4\\Docs\\programming\\Object Scripting System.htm\r\n\t\r\n\tThe base class for all object managers. An object manager keeps track of a related\r\n\tset of CObjects (e.g. the screen element manager manages all CScreenElements).\r\n\tThe manager might also be responsible for creation and destruction of its CObjects.\r\n\t\r\n\tAn subclass of CBaseMananger must register its CObjects with the CTracker singleton.\r\n\t\r\n\tThis is a virtual base class.\r\n*/\r\nclass CBaseManager : public Spt::Class\r\n{\r\npublic:\t\r\n\t\r\n\tstatic const uint32\t\t\tvNO_GROUP;\r\n\tstatic const uint32\t\t\tvNO_OBJECT_ID;\r\n\t\t\t\t\t\t\t\t\r\n\tstatic const sint\t\t\tvNO_OBJECT_TYPE;\r\n\r\n\t\t\t\t\t\t\t\tCBaseManager();\r\n\tvirtual \t\t\t\t\t~CBaseManager() {;}\r\n\t\r\n\tvirtual void\t\t\t\tRegisterObject ( CObject& obj );\r\n\tvirtual void\t\t\t\tUnregisterObject ( CObject& obj );\r\n\tvirtual void\t\t\t\tReregisterObject ( CObject& obj, uint32 newId );\r\n\t\r\n\tvirtual void\t\t\t\tSetObjectPriority ( CObject& obj, Lst::Node< CObject >::Priority priority );\r\n\t\r\n\t// Called by CObject::mark_as_dead()\r\n\tvirtual void\t\t\t\tKillObject ( CObject& obj ) = 0;\r\n\t\r\n\tvirtual Lst::Head< CObject > &GetRefObjectList() = 0;\r\n\r\nprotected:\r\n\r\n\tLst::Head< CObject >\t\tm_object_list;\t// list of created objects\r\n\t\r\n\tCBitManager\t\t\t\t\tm_stamp_bit_manager;\r\n\t\r\n\tuint32\t\t\t\t\t\tm_list_changed;\r\n\r\n\t// important in ReregisterObject(); if applicable, set to ID of new object,\r\n\t// otherwise, zero\r\n\tuint32\t\t\t\t\t\tm_new_id_of_object_being_momentarily_removed;\r\n\tbool\t\t\t\t\t\tm_momentary_removal;\r\n};\r\n\r\n\r\n\r\n\r\n/*\r\n\tSee document for more info on this class: Q:\\sk4\\Docs\\programming\\Object Scripting System.htm\r\n\t\r\n\tThe generic implementation of CBaseManager. Use when you want a very\r\n\tbasic manager only.\r\n*/\r\nclass  CGeneralManager  : public CBaseManager\r\n{\r\n\t\r\n\r\npublic :\r\n\t\r\n\ttypedef\tvoid (Callback) ( CObject*, void *data );\r\n\r\n\t\t\t\t\t\t\t\tCGeneralManager ( void );\r\n\t\t\t\t\t\t\t\t~CGeneralManager ( void );\r\n\r\n\tvoid\t\t\t\t\t\tProcessAllObjects ( Callback* process, void* data = NULL );\r\n\tvoid\t\t\t\t\t\tProcessAllObjectsOfType ( sint type, Callback* process, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  void* data = NULL );\r\n\r\n\tvoid\t\t\t\t\t\tDestroyAllObjects ( void );\r\n\tvoid\t\t\t\t\t\tDestroyAllObjectsOfType ( sint type );\r\n\r\n\tvoid\t\t\t\t\t\tUnlockAllObjects ( void );\r\n\tvoid\t\t\t\t\t\tUnlockAllObjectsOfType ( sint type );\r\n\t\r\n\r\n\tvoid\t\t\t\t\t\tKillObject ( CObject& obj );\r\n\r\n\tuint32\t\t\t\t\t\tNewObjectID( void );\r\n\tsint\t\t\t\t\t\tCountObjectsOfType ( sint type );\r\n\tvoid \t\t\t\t\t\tAssertIfObjectsRemainApartFrom( sint *pApartFromThisType );\r\n\r\n\r\n\tvoid \t\t\t\t\t\tFlushDeadObjects();\r\n\r\n\tCObject*\t\t\t\t\tGetObjectByID( uint32 id );\r\n\t\r\n\tLst::Head< CObject > &\t\tGetRefObjectList() {return m_object_list;}\r\n\r\nprotected :\r\n\t\r\n\tstatic Tsk::Task< CGeneralManager >::Code\tflush_dead_objects;\r\n\r\n\tLst::Head< CObject >\t\tm_kill_list;\t\t// list of objects to be killed\r\n\tTsk::Task< CGeneralManager >*\t\tmp_kill_task;\t\t// kill task that processes the kill list\r\n\r\n//\tLst::HashTable<CObject> *\tmp_hash_table;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\t\t\t\tCBitManager::CBitManager (   )\r\n\t:\tm_used_bit_mask(0x00000000)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tuint32\t\tCBitManager::RequestBit (   )\r\n{\r\n\tDbg_MsgAssert(m_used_bit_mask != 0xFFFFFFFF, (\"Out of available bits in CBitManager::RequestBit\"));\r\n\t\r\n\tuint32 ready_mask = nBit(0);\r\n\twhile (m_used_bit_mask & ready_mask)\r\n\t{\r\n\t\tready_mask <<= 1;\r\n\t}\r\n\t\r\n\tm_used_bit_mask |= ready_mask;\r\n\t\r\n\treturn ready_mask;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tCBitManager::ReturnBit ( uint32 returning_mask )\r\n{\r\n\tDbg_MsgAssert((returning_mask & (returning_mask - 1)) == 0, (\"Calling CBitManager::ReturnBit with a mask contining more than a single set bit\"));\r\n\tDbg_MsgAssert(returning_mask & m_used_bit_mask, (\"Returning an unused bit to CBitManager::ReturnBit\"));\r\n\t\r\n\tm_used_bit_mask &= ~returning_mask;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tCGeneralManager::DestroyAllObjects ( void )\r\n{\r\n   \t\r\n\t\r\n\tProcessAllObjects ( DestroyIfUnlocked );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline\tvoid\t\tCGeneralManager::DestroyAllObjectsOfType ( sint type )\r\n{\r\n   \t\r\n\r\n\tProcessAllObjectsOfType ( type, DestroyIfUnlocked );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\t\tCGeneralManager::UnlockAllObjects ( void )\r\n{\r\n   \t\r\n\r\n\tProcessAllObjects ( SetLockOff, NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline\tvoid\t\tCGeneralManager::UnlockAllObjectsOfType ( sint type )\r\n{\r\n   \t\r\n\r\n\tProcessAllObjectsOfType ( type, SetLockOff );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __GEL_OBJMAN_H\r\n"
  },
  {
    "path": "Code/Gel/objsearch.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObjects (OBJ) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/objsearch.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_OBJSEARCH_H\r\n#define __GEL_OBJSEARCH_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n#include <core/list.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  Search : public  Lst::Search< CObject > \r\n{\r\n\t\r\n\r\npublic :\r\n\r\n\tCObject*\t\t\tFindFirstObjectOfType  ( Lst::Head< CObject >& head, sint type );\r\n\r\n\tCObject*\t\t\tFindNextObjectOfType  ( void );\r\n\r\nprivate :\r\n\r\n\tsint\t\t\tobj_type;\r\n\t\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __GEL_OBJSEARCH_H\r\n"
  },
  {
    "path": "Code/Gel/objserv.h",
    "content": "\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGEL (Game Engine Library)\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tBase Object-Server (OS)\t\t\t\t\t\t\t        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgel/server/os_cb.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t07/23/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_OBJSERV_H\r\n#define __GEL_OBJSERV_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/task.h>\r\n#include <core/list.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace ObjServ\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  Object  : public Spt::Class\r\n{\r\n\t\r\n    \r\npublic:\r\n\r\n\tvirtual\t\t~Object( void ) {}\r\n\r\nprotected:\r\n\t\t\t\tObject( void ) {}\r\n\t\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  Server  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic:\r\n\tvirtual void ProcessAllObjects ( void ) = 0;\r\n    virtual void RegisterObject( Object *object ) = 0;\r\n    \r\n    virtual     ~Server( void ) {}\r\n\r\nprotected:\r\n\t\t\t\tServer( void ) {}\r\n    \r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace ObjServ\r\n\r\n#endif\t// __GEL_OBJSERV_H\r\n\r\n"
  },
  {
    "path": "Code/Gel/objtrack.h",
    "content": "#ifndef __GEL_OBJTRACK_H\r\n#define __GEL_OBJTRACK_H\r\n\r\n#include <gel/event.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n}\r\n\r\n\r\nnamespace Front\r\n{\r\n\tclass CScreenElementManager;\r\n}\r\n\r\n\r\nnamespace Lst\r\n{\r\n\ttemplate< class _V > class HashTable;\r\n}\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\nclass CObject;\r\n//class CEvent;\r\nclass CEventListener;\r\n\t\r\n\r\n/*\r\n\tAn instance of this class is attached to the CTracker singleton. It tracks the launching\r\n\tand handling of all events in the system, for debugging purposes.\r\n*/\r\nclass CEventLog\r\n{\r\npublic:\r\n\t\r\n\tenum EOccurenceType\r\n\t{\r\n\t\tvLAUNCHED,\r\n\t\tvHANDLED,\r\n\t\tvREAD,\r\n\t\tvUPDATE,\r\n\t\tvOBJECT_ADD,\r\n\t\tvOBJECT_REMOVE,\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n\t\tMAX_LOG_ENTRIES\t\t\t= 1024,\r\n\t\tMAX_EVENT_TYPES\t\t\t= 256,\r\n\t};\r\n\r\n\t\t\t\t\t\t\t\tCEventLog();\r\n\t\t\t\t\t\t\t\t~CEventLog();\r\n\r\n\tvoid\t\t\t\t\t\tAddEntry(uint32 type, uint32 target, uint32 source, uint32 script, uint32 receiverID, EOccurenceType lifePoint);\r\n\tvoid\t\t\t\t\t\tPrint(bool onlyPrintNewEntries = true, int maxEntriesToPrint = MAX_LOG_ENTRIES);\r\n\tvoid\t\t\t\t\t\tPrintLatestEntry();\r\n\tvoid\t\t\t\t\t\tClear() {m_num_new_entries = 0;}\r\n\r\nprivate:\r\n\r\n\tvoid\t\t\t\t\t\tprint_entry(int index);\r\n\tconst char *\t\t\t\tget_type_name(uint32 type);\r\n\t\r\n\tstruct Entry\r\n\t{\r\n\t\tunion\r\n\t\t{\r\n\t\t\tuint32\t\t\t\tm_type;\r\n\t\t\tint\t\t\t\t\tm_tick_count; // applies to update type entries\r\n\t\t};\r\n\t\tuint32 \t\t\t\t\tm_target;\r\n\t\tuint32 \t\t\t\t\tm_source;\r\n\t\tuint32\t\t\t\t\tm_script;\t\t\t\t\t\r\n\t\tuint32\t\t\t\t\tm_receiver_id;\r\n\t\tEOccurenceType\t\t\tm_occurence_type;\r\n\t\tint\t\t\t\t\t\tm_depth;\r\n\t};\r\n\r\n\tEntry\t\t\t\t\t\tm_table[MAX_LOG_ENTRIES];\r\n\tint\t\t\t\t\t\t\tm_next_entry;\r\n\tbool\t\t\t\t\t\tm_wrapped;\r\n\r\n\tstruct EventType\r\n\t{\r\n\t\t//uint32\t\t\t\t\tmCrc;\r\n\t\tchar\t\t\t\t\tmName[64];\r\n\t};\r\n\tEventType\t\t\t\t\tm_event_type_table[MAX_EVENT_TYPES];\r\n\tLst::HashTable<EventType> *\tmp_event_type_hash_table;\r\n\r\n\tint\t\t\t\t\t\t\tm_event_depth;\r\n\tint\t\t\t\t\t\t\tm_num_new_entries;\r\n};\r\n\r\n\r\n// CEventReceiverList comprises of an event type\r\n// and a list of object that can receive this type of event\r\nclass\tCEventReceiverList : public Spt::Class\r\n{\r\npublic:\r\n\t\t\t\tCEventReceiverList();\r\n\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tvoid\t\tRegisterEventReceiverObject(Script::CScript *p_obj);\r\n\tvoid\t\tUnregisterEventReceiverObject(Script::CScript *p_obj);\r\n\tbool\t\tIsEmpty() {return m_objects.IsEmpty();};\r\n\tLst::Node< Script::CScript >*\tFirstItem() {return m_objects.FirstItem();}\r\n\tint\t\t\tCountItems() {return m_objects.CountItems();}\r\nprivate:\r\n//\tuint32\t\t\t\t\t\tm_type;\t   \t\t\t\t\t// The type of event this is\r\n\tLst::Head<Script::CScript>\t\tm_objects;\t\t\t// a list of objects (SCRIPTS) that are listening for it\r\n#else\r\n\tvoid\t\tRegisterEventReceiverObject(CObject *p_obj);\r\n\tvoid\t\tUnregisterEventReceiverObject(CObject *p_obj);\r\n\tbool\t\tIsEmpty() {return m_objects.IsEmpty();};\r\n\tLst::Node< Obj::CObject >*\tFirstItem() {return m_objects.FirstItem();}\r\n\tint\t\t\tCountItems() {return m_objects.CountItems();}\r\nprivate:\r\n//\tuint32\t\t\t\t\t\tm_type;\t   \t\t\t\t\t// The type of event this is\r\n\tLst::Head<Obj::CObject>\t\tm_objects;\t\t\t// a list of objects that are listening for it\r\n#endif\r\n};\r\n\r\n\r\n/*\r\n\tSee document for more info on this class: Q:\\sk4\\Docs\\programming\\Object Scripting System.htm\r\n\t\r\n\tThis class keeps track of all registered CObjects, and provides functions for retreiving\r\n\tthem by ID. It also takes care of launching and distributing events. It also can reactivate\r\n\tscripts that are suspended while waiting for an event.\r\n*/\r\nclass CTracker : public Spt::Class\r\n{\r\n\tfriend class CBaseManager;\r\n\tfriend class CGeneralManager;\r\n\tfriend class Front::CScreenElementManager;\r\n\r\n\tDeclareSingletonClass( CTracker );\r\n\r\npublic:\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t// In logging\r\n\tenum ELoggingSystem\r\n\t{\r\n\t\tvID_UNSPECIFIED_RECEIVER\t\t\t\t= 0,\r\n\t\tvID_SCREEN_ELEMENT_MANAGER\t\t\t\t= 1,\r\n\t\tvID_SUSPENDED_SCRIPT\t\t\t\t\t= 2,\r\n\t\tvID_OBJECT_TRACKER\t\t\t\t\t\t= 3,\r\n\t};\r\n\r\n\t\t\t\t\t\t\t\tCTracker();\r\n\tvirtual\t\t\t\t\t\t~CTracker();\r\n\r\n\tCObject *\t\t\t\t\tGetObject(uint32 id);\r\n\t\r\n\t// See the menu document for a description of aliases\r\n\tCObject *\t\t\t\t\tGetObjectByAlias(uint32 aliasId);\r\n\tvoid\t\t\t\t\t\tAddAlias(uint32 alias, CObject *pObject);\r\n\r\n\tuint32\t\t\t\t\t\tGetFreshId();\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tvoid \t\t\t\t\t\tValidateReceivers();\r\n\t#endif\r\n\t\r\n\r\n\tbool\t\t\t\t\t\tLaunchEvent(uint32 type, uint32 target = CEvent::vSYSTEM_EVENT, uint32 source = CEvent::vSYSTEM_EVENT, Script::CStruct *pData = NULL, bool broadcast=false);\r\n\tvoid\t\t\t\t\t\tBlockEventLaunching(bool block) {m_block_event_launching = block;}\r\n\t\r\n\tvoid \t\t\t\t\t\tLogEventScript(uint32 script = 0);\r\n\tvoid\t\t\t\t\t\tLogEventHandled(CEvent *pEvent, uint32 receiverID = 0, uint32 script = 0);\r\n\tvoid\t\t\t\t\t\tLogEventRead(CEvent *pEvent, uint32 receiverID = 0, uint32 script = 0);\r\n\tvoid\t\t\t\t\t\tLogTick();\r\n\tvoid \t\t\t\t\t\tPrintEventLog(bool mostRecentOnly, int maxToPrint);\r\n\tvoid\t\t\t\t\t\tEmptyLog() {m_event_log.Clear();}\r\n\r\n// Event Listener are special objects that will get sent all types of events\r\n// and it is up to them to \t\r\n\tvoid \t\t\t\t\t\tRegisterEventListener(CEventListener *pListener);\r\n\tvoid\t\t\t\t\t\tUnregisterEventListener(CEventListener *pListener);\r\n\r\n// Event Receivers are just CObject and they only get sent events that they tell the tracker they are listening for\r\n\t\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tvoid\t\t\t\t\t\tRegisterEventReceiver(uint32 type, Script::CScript *p_obj);\r\n\tvoid\t\t\t\t\t\tUnregisterEventReceiver(uint32 type, Script::CScript *p_obj);\r\n#else\t\r\n\tvoid\t\t\t\t\t\tRegisterEventReceiver(uint32 type, CObject *p_obj);\r\n\tvoid\t\t\t\t\t\tUnregisterEventReceiver(uint32 type, CObject *p_obj);\r\n#endif\t\r\n\t// Note, removing an object should remove all event receivers.\r\n\r\n\tvoid\t\t\t\t\t\tSuspendScriptUntilEvent(Script::CScript *pScript, uint32 event_type);\r\n\r\nprivate:\r\n\r\n\tvoid\t\t\t\t\t\taddObject(CObject *pObject);\r\n\tvoid \t\t\t\t\t\tremoveObject(CObject *pObject, uint32 newIdOfObjectBeingMomentarilyRemoved, bool momentary_removal);\r\n\r\n\tvoid\t\t\t\t\t\tforward_event_to_listeners(CEvent *pEvent, CObject *pObject);\r\n\r\n\tvoid\t\t\t\t\t\tremove_aliases(CObject *pObject);\r\n\t\r\n\tint\t\t\t\t\t\t\tm_id_seed;\r\n\t\r\n\tLst::HashTable<CObject> *\tmp_hash_table;\r\n\tLst::HashTable<CObject> *\tmp_alias_table;\r\n\r\n// The hash table of event listeners is keyed off the \"type\" of the event\r\n// (the \"type\" is the actual event name, as a uint32 CRC)\t\r\n\tLst::HashTable<CEventReceiverList> *\tmp_event_receiver_table;\r\n\t\r\n\tCEventListener *\t\t\tmp_event_listener_list;\r\n\t\r\n\tbool\t\t\t\t\t\tm_block_event_launching;\r\n\tenum \r\n\t{\r\n\t\tvMAX_EVENT_RECURSE_DEPTH = 32,\r\n\t};\r\n\tint\t\t\t\t\t\t\tm_event_recurse_depth;\r\n\r\n\tCEventLog\t\t\t\t\tm_event_log;\r\n\tuint32\t\t\t\t\t\tm_next_event_script;\r\n\t\r\n\t// Used to keep track of of scripts that are suspended while waiting for an event.\r\n\t// No pointers to scripts are kept, in case scripts are destroyed.\r\n\tstruct WaitingScriptEntry\r\n\t{\r\n\t\t// the unique ID of the script\r\n\t\tuint32\t\t\t\t\tmScriptId;\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tuint32\t\t\t\t\tmScriptName;\r\n\t\t#endif\r\n\t\t// 0 denotes a dead entry\r\n\t\tuint32\t\t\t\t  \tmEventType;\r\n\t\t// the object on which the script is running\r\n\t\tuint32\t\t\t\t\tmObjectId;\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n\t\tvMAX_SCRIPT_ENTRIES \t= 40,\r\n\t\tvDEAD_SCRIPT_ENTRY \t\t= 0,\r\n\t};\r\n\r\n\tWaitingScriptEntry\t\t\tm_waiting_script_tab[vMAX_SCRIPT_ENTRIES];\r\n\r\n\tbool\t\t\t\t\t\tm_debug;\r\n};\r\n\t\r\n\r\n\r\nbool ScriptLaunchEvent(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptWaitForEvent(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptObjectExists(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptTerminateObjectsScripts(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAssignAlias(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetObjectProperties(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPrintEventLog(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\n\r\n\r\n} // end namespace\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/2D/BlurEffect.cpp",
    "content": "#include <core/defines.h>\r\n#include <gfx/2D/BlurEffect.h>\r\n\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/vecpair.h>\r\n\r\nnamespace Front\r\n{\r\n\r\n\r\n\r\nCBlurEffect::CBlurEffect()\r\n{\r\n}\r\n\r\n\r\n\r\n\r\nCBlurEffect::~CBlurEffect()\r\n{\r\n}\r\n\r\n\r\n\r\n\r\nvoid CBlurEffect::Update()\r\n{\r\n\tTmr::Time current_time = Tmr::GetTime();\r\n\tfloat motion_grad = (float) (current_time - m_last_time) / (float) m_key_time;\r\n\tif (current_time - m_last_time < m_key_time)\r\n\t\tm_key_time -= current_time - m_last_time;\r\n\telse\r\n\t\tm_key_time = 0;\r\n\tm_last_time = current_time;\r\n\t\r\n\tif (m_key_time)\r\n\t{\r\n\t\tm_current.topAlpha = m_current.topAlpha + (m_target.topAlpha - m_current.topAlpha) * motion_grad;\r\n\t\tm_current.bottomAlpha = m_current.bottomAlpha + (m_target.bottomAlpha - m_current.bottomAlpha) * motion_grad;\r\n\t\tm_current.bottomScaleX = m_current.bottomScaleX + (m_target.bottomScaleX - m_current.bottomScaleX) * motion_grad;\r\n\t\tm_current.bottomScaleY = m_current.bottomScaleY + (m_target.bottomScaleY - m_current.bottomScaleY) * motion_grad;\r\n\t\tm_current.maxDisplacementX = m_current.maxDisplacementX + (m_target.maxDisplacementX - m_current.maxDisplacementX) * motion_grad;\r\n\t\tm_current.maxDisplacementY = m_current.maxDisplacementY + (m_target.maxDisplacementY - m_current.maxDisplacementY) * motion_grad;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_current = m_target;\r\n\t}\r\n\t\r\n\tfor (int i = 0; i < 16; i++)\r\n\t{\r\n\t\tfloat depth_mult = (float) i / 16.0f;\r\n\t\tm_tab[i].SetScreenPos(m_current.maxDisplacementX * depth_mult,\r\n\t\t\t\t\t\t\t  m_current.maxDisplacementY * depth_mult);\r\n\t\tm_tab[i].SetScale(1.0f + (m_current.bottomScaleX - 1.0f) * depth_mult,\r\n\t\t\t\t\t\t  1.0f + (m_current.bottomScaleY - 1.0f) * depth_mult);\r\n\t\tm_tab[i].alpha = (m_current.topAlpha + (m_current.bottomAlpha - m_current.topAlpha) * depth_mult) / 16.0f;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nCScreenElement::ConcatProps &CBlurEffect::GetInfo(int index)\r\n{\r\n\treturn m_tab[index];\r\n}\r\n\r\n\r\n\r\n\r\nvoid CBlurEffect::SetAllTargetProps(const Props &newProps, Tmr::Time time) \r\n{\r\n\tm_target = newProps;\r\n\tSetAnimTime(time);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CBlurEffect::SetAnimTime(Tmr::Time time)\r\n{\r\n\tif (time == 0)\r\n\t\tm_current = m_target;\r\n\t\r\n\tm_key_time = time;\r\n\tm_last_time = Tmr::GetTime();\r\n}\r\n\r\n\r\n\r\n\r\nconst CBlurEffect::Props &CBlurEffect::SetMorph(Script::CStruct *pProps, Tmr::Time *pRetTime)\r\n{\t\r\n\tScript::CPair alpha_pair;\r\n\tif (pProps->GetPair(CRCD(0x21de240c,\"blur_alpha_pair\"), &alpha_pair))\r\n\t{\r\n\t\tSetAlphas(alpha_pair.mX, alpha_pair.mY);\r\n\t}\r\n\r\n\tScript::CPair bottom_scales;\r\n\tif (pProps->GetPair(CRCD(0x3e10436d,\"blur_bottom_scales\"), &bottom_scales))\r\n\t{\r\n\t\tSetBottomScales(bottom_scales.mX, bottom_scales.mY);\r\n\t}\r\n\r\n\tScript::CPair max_displacement;\r\n\tif (pProps->GetPair(CRCD(0x4c2a3cde,\"blur_max_displacement\"), &max_displacement))\r\n\t{\r\n\t\tSetMaxDisplacements(max_displacement.mX, max_displacement.mY);\r\n\t}\r\n\t\r\n\tfloat desired_time;\r\n\tTmr::Time anim_time;\r\n\tif (pProps->GetFloat(CRCD(0x906b67ba,\"time\"), &desired_time))\r\n\t{\r\n\t\tanim_time = (Tmr::Time) (desired_time * (float) Tmr::vRESOLUTION);\r\n\t}\r\n\telse\r\n\t\tanim_time = 0;\r\n\tSetAnimTime(anim_time);\r\n\tif (pRetTime)\r\n\t\t*pRetTime = anim_time;\r\n\r\n\treturn m_target;\r\n}\r\n\r\n\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gfx/2D/BlurEffect.h",
    "content": "#ifndef __GFX_2D_BLUREFFECT_H__\r\n#define __GFX_2D_BLUREFFECT_H__\r\n\r\n#include <gfx/2D/ScreenElement2.h>\r\n#include <sys/timer.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Front\r\n{\r\n\r\nclass CBlurEffect\r\n{\r\npublic:\r\n\r\n\tstruct Props\r\n\t{\r\n\t\tfloat\t\t\t\t\t\ttopAlpha;\r\n\t\tfloat\t\t\t\t\t\tbottomAlpha;\r\n\t\tfloat \t\t\t\t\t\tbottomScaleX;\r\n\t\tfloat\t\t\t\t\t\tbottomScaleY;\t\t\t\t\t\r\n\t\tfloat\t\t\t\t\t\tmaxDisplacementX;\r\n\t\tfloat\t\t\t\t\t\tmaxDisplacementY;\r\n\t};\r\n\t\t\r\n\t\t\t\t\t\t\t\t\tCBlurEffect();\r\n\t\t\t\t\t\t\t\t\t~CBlurEffect();\r\n\r\n\tvoid\t\t\t\t\t\t\tUpdate();\r\n\r\n\tCScreenElement::ConcatProps &\tGetInfo(int index);\r\n\tint\t\t\t\t\t\t\t\tGetNumEntries() {return 16;}\r\n\tImage::RGBA\t\t\t\t\t\tGetRGBA() {return m_rgba;}\r\n\r\n\tvoid\t\t\t\t\t\t\tSetAlphas(float top, float bottom) {m_target.topAlpha = top; m_target.bottomAlpha = bottom;}\r\n\tvoid\t\t\t\t\t\t\tSetBottomScales(float scaleX, float scaleY) {m_target.bottomScaleX = scaleX; m_target.bottomScaleY = scaleY;}\r\n\tvoid\t\t\t\t\t\t\tSetMaxDisplacements(float dispX, float dispY) {m_target.maxDisplacementX = dispX; m_target.maxDisplacementY = dispY;}\r\n\tvoid\t\t\t\t\t\t\tSetRGBA(Image::RGBA rgba) {m_rgba = rgba;}\r\n\tvoid\t\t\t\t\t\t\tSetAllTargetProps(const Props &newProps, Tmr::Time time);\r\n\tvoid\t\t\t\t\t\t\tSetAnimTime(Tmr::Time time);\r\n\r\n\tconst Props &\t\t\t\t\tSetMorph(Script::CStruct *pProps, Tmr::Time *pRetTime = NULL);\r\n\r\nprotected:\r\n\r\n\tCScreenElement::ConcatProps\t\tm_tab[16];\r\n\r\n\tProps\t\t\t\t\t\t\tm_target;\r\n\tProps\t\t\t\t\t\t\tm_current;\r\n\r\n\tTmr::Time\t\t\t\t\t\tm_last_time;\r\n\tTmr::Time\t\t\t\t\t\tm_key_time;\r\n\t\r\n\tImage::RGBA\t\t\t\t\t\tm_rgba;\r\n};\r\n\r\n}\r\n\r\n#endif // __GFX_2D_BLUREFFECT_H__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/2D/Element3d.cpp",
    "content": "#include <core/defines.h>\r\n#include <gfx/2D/Element3d.h>\r\n#include <gfx/2D/ScreenElemMan.h>\r\n#include <gel/assman/assman.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <sk/scripting/nodearray.h>\t\t// <<<<<<<< NEEDS MOVING!!!!\r\n#include <gfx/modelappearance.h>\r\n#include <gfx/modelbuilder.h>\r\n#include <gfx/skeleton.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxgeom.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/nxviewman.h>\r\n#include <gfx/gfxutils.h>\r\n#include <sys/config/config.h>\r\n#include <sys/replay/replay.h>\r\n\r\nnamespace Front\r\n{\r\n\r\n// added by your mother\r\n// returns the scale that needs to be applied to (modelWorldW,modelWorldH) to make it fit (screenW,screenH)\r\nstatic float sGetScaleFromScreenDimensions(float screenW, float screenH, float zOffset, float modelWorldW, float modelWorldH)\r\n{\r\n\t// Inverse project.\r\n\tfloat desired_world_w = screenW * zOffset / (640.0f * (1.0f + screenW / 1280.0f));\r\n\tfloat desired_world_h = screenH * zOffset / (448.0f * (1.0f + screenW / 896.0f));\r\n\r\n\tfloat scale_x = desired_world_w / modelWorldW;\r\n\tfloat scale_y = desired_world_h / modelWorldH;\r\n\treturn (-scale_x < -scale_y) ? -scale_x : -scale_y;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// screenX, screenY indicate where the origin of the model will be located\r\nstatic void sGetWorldMatrixFromScreenPosition(int camera_num, Mth::Matrix *p_world_matrix, float screenX, float screenY, float zOffset, Mth::Vector &model_offs)\r\n{\r\n\tDbg_MsgAssert(p_world_matrix,(\"NULL p_world_matrix\"));\r\n\tDbg_MsgAssert((camera_num >= 0) && (camera_num < Nx::CViewportManager::vMAX_NUM_ACTIVE_VIEWPORTS), (\"Camera number is out of range: %d\", camera_num));\r\n\r\n\tMth::Vector camera_space_pos;\r\n\r\n#ifdef __PLAT_XBOX__\r\n\t// Don't think Mick's assumption below is correct - for 3D objects going through the rendering pipeline, no screen correction is required.\r\n\tscreenX = screenX - ( 640 / 2 );\r\n\tscreenY = screenY - ( 448 / 2 );\r\n\r\n\t// Adjust X for aspect ratio that is different than 4/3 (1.3333333)\r\n\tscreenX *= (Nx::CViewportManager::sGetScreenAspect() / 1.3333333f);\r\n\r\n\t// Also, adjust for 720p (horrible hack).\r\n\tif( NxXbox::EngineGlobals.backbuffer_width > 640 )\r\n\t{\r\n\t\tscreenX *= 0.9f;\r\n\t\tscreenY *= 0.9f;\r\n\t}\r\n\r\n\tcamera_space_pos.Set( -screenX * zOffset / 448.0f, screenY * zOffset / 448.0f, zOffset );\r\n#else\r\n\t// Mick:  Need to convert from logical to physical screen coordinates\r\n\tscreenX = SCREEN_CONV_X(screenX);\r\n\tscreenY = SCREEN_CONV_Y(screenY);\r\n\r\n\t// Make ScreenX and ScreenY relative to the centre of the screen.\r\n\tscreenX -= SCREEN_CONV_X(640)/2;\r\n\tscreenY -= SCREEN_CONV_Y(448)/2;\r\n\r\n\t// Adjust X for aspect ratio that is different than 4/3 (1.3333333)\r\n\tscreenX *= (Nx::CViewportManager::sGetScreenAspect() / 1.3333333f);\r\n\r\n\t// Inverse project.\r\n\tcamera_space_pos.Set(-screenX * zOffset / SCREEN_CONV_X(448),\r\n\t\t\t\t\t\t screenY * zOffset / SCREEN_CONV_Y(448),\r\n\t\t\t\t\t\t zOffset);\r\n#endif // __PLAT_XBOX__\r\n\r\n\tcamera_space_pos += model_offs;\r\n\t\t\t\t\t\t \r\n\t// We now have a 3d vector in camera space, so rotate by the camera matrix\r\n\t// to get world coords.\t\r\n\r\n\tp_world_matrix->Ident();\r\n\r\n\t// Get the camera.\r\n\tGfx::Camera *p_camera = Nx::CViewportManager::sGetActiveCamera(camera_num);\r\n\tif (p_camera)\r\n\t{\r\n\t\tMth::Matrix cam_matrix=p_camera->GetMatrix();\r\n\t\t\r\n\t\t// Camera matrix might have been incorrectly set up with a translation in W\r\n\t\t// so clear it out to be safe\r\n\t\t// Probably should be handled at a higher level.\r\n\t\tcam_matrix[W].Set();\r\n\r\n\t\t// Apply the camera matrix to the camera_space_pos\r\n\t\tMth::Vector world_pos = camera_space_pos * cam_matrix;\r\n\t\t// and add the camera position to get the final world position.\r\n\t\tMth::Vector cam_pos = p_camera->GetPos();\r\n\t\tcam_pos[W] = 0.0f;\r\n\t\tworld_pos += cam_pos;\r\n\t\tworld_pos[W] = 0.0f;\r\n\t\t\r\n\t\r\n\t\t// Make the rotation part of the passed matrix be the camera matrix so that the model \r\n\t\t// always faces the camera.\r\n\t\t*p_world_matrix*=cam_matrix;\r\n\t\t// Then add in the calculated world position.\r\n\t\tp_world_matrix->Translate(world_pos);\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCElement3d::CElement3d()\r\n{\r\n\tfor (int i=0; i<MAX_MODELS_PER_ELEMENT; ++i)\r\n\t{\r\n\t\tmp_models[i].mpModel=NULL;\r\n        mp_models[i].mpSkeleton=NULL;\r\n\t\tmp_models[i].mOffset.Set();\r\n\t}\r\n\tm_num_models=0;\r\n\t\r\n\tm_camera_z=-400;\r\n\tm_angle_x=0.0f;\r\n\tm_angle_y=0.0f;\r\n\tm_angle_z=0.0f;\r\n\tm_angvel_x=0.0f;\r\n\tm_angvel_y=0.0f;\r\n\tm_angvel_z=0.0f;\r\n\tm_point_type=POINT_TYPE_NONE;\r\n\tm_angle_order=ANGLE_ORDER_YXZ;\r\n\tm_node_position_to_point_to.Set();\r\n\tm_id_of_object_to_point_to=0;\r\n\tm_tilt=0.0f;\r\n\t\r\n\tm_parent_object_name=0;\r\n\tm_skater_number=0;\r\n\r\n\tm_scale3d = 1.0f;\r\n\tm_active_viewport_number = 0;\r\n\r\n\tm_scale_with_distance=false;\r\n\tm_scale_multiplier=0.002f;\r\n\tm_max_scale=3.0f;\r\n\r\n\tm_waiting_to_die=false;\t\r\n\tm_model_matrix.Ident();\r\n\t\r\n\tm_pivot_point.Set();\r\n\tm_offset_of_origin_from_center.Set();\r\n\r\n\tSetType(CScreenElement::TYPE_ELEMENT_3D);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCElement3d::~CElement3d()\r\n{\r\n\tUnloadModels();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CElement3d::UnloadModels()\r\n{\r\n\tfor (int i=0; i<MAX_MODELS_PER_ELEMENT; ++i)\r\n\t{\r\n\t\tif (mp_models[i].mpModel)\r\n\t\t{\r\n\t\t\tNx::CEngine::sUninitModel(mp_models[i].mpModel);\r\n\t\t\tmp_models[i].mpModel=NULL;\r\n\t\t}\t\r\n\r\n        if (mp_models[i].mpSkeleton)\r\n        {\r\n            delete mp_models[i].mpSkeleton;\r\n        }\r\n\r\n\t\tmp_models[i].mOffset.Set();\r\n\t}\r\n\tm_num_models=0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGfx::CSkeleton* CElement3d::CreateSkeleton( Nx::CModel* pModel, uint32 skeletonChecksum )\r\n{\r\n    // temporarily moved this function from CModel,\r\n    // in order to make it easier to split off\r\n    // skeleton into its own component.\r\n\r\n\tGfx::CSkeletonData* pSkeletonData = (Gfx::CSkeletonData*) Ass::CAssMan::Instance()->GetAsset( skeletonChecksum, false );\r\n\r\n\tif ( !pSkeletonData )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, (\"Unrecognized skeleton %s. (Is skeleton.q up to date?)\", Script::FindChecksumName(skeletonChecksum)) );\r\n\t}\r\n    \r\n\tGfx::CSkeleton* pSkeleton = new Gfx::CSkeleton( pSkeletonData );\r\n    \r\n    Dbg_Assert( pSkeleton );\r\n    Dbg_Assert( pSkeleton->GetNumBones() > 0 );\r\n\t\r\n    pModel->SetSkeleton( pSkeleton );\r\n\r\n    return pSkeleton;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::CModel* CElement3d::CreateModel( uint32 skeleton_name, Mth::Vector offset )\r\n{\r\n\tDbg_MsgAssert(m_num_models<MAX_MODELS_PER_ELEMENT,(\"Reached max models for one CElement3d\"));\r\n\r\n\tNx::CModel *p_new_model=Nx::CEngine::sInitModel();\r\n\tDbg_MsgAssert(p_new_model,(\"Nx::CEngine::sInitModel() returned NULL\"));\r\n\r\n\tif ( skeleton_name )\r\n\t{\r\n\t\t// load a skeleton, if one was specified\r\n\t\tmp_models[m_num_models].mpSkeleton=this->CreateSkeleton( p_new_model, skeleton_name );\r\n\t}\r\n\r\n\tp_new_model->SetColor(m_rgba.r,m_rgba.g,m_rgba.b,m_rgba.a);\r\n\r\n\tDbg_MsgAssert(mp_models[m_num_models].mpModel==NULL,(\"mp_models[m_num_models].mpModel not NULL ?\"));\r\n\tmp_models[m_num_models].mpModel=p_new_model;\r\n\t\r\n\tmp_models[m_num_models].mOffset=offset;\r\n\t++m_num_models;\r\n\r\n\treturn p_new_model;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CElement3d::AddModel(const char *p_model_name, uint32 skeleton_name, Mth::Vector offset, int texDictOffset)\r\n{\r\n\tDbg_MsgAssert(m_num_models<MAX_MODELS_PER_ELEMENT,(\"Reached max models for one CElement3d\"));\r\n\t\t\r\n\tNx::CModel *p_new_model=Nx::CEngine::sInitModel();\r\n\tDbg_MsgAssert(p_new_model,(\"Nx::CEngine::sInitModel() returned NULL\"));\r\n\t\r\n\tif ( skeleton_name )\r\n\t{\r\n\t\t// load a skeleton, if one was specified\r\n\t\tmp_models[m_num_models].mpSkeleton=this->CreateSkeleton( p_new_model, skeleton_name );\r\n    }\r\n\r\n\tif ( p_model_name )\r\n\t{\r\n\t\t// loads a geom, if one was specified\r\n\t\tStr::String fullModelName;\r\n\t\tfullModelName = Gfx::GetModelFileName(p_model_name, \".mdl\");\r\n\t\tp_new_model->AddGeom(fullModelName.getString(), 0, true, texDictOffset);\r\n\t}\r\n\t\r\n\tp_new_model->SetColor(m_rgba.r,m_rgba.g,m_rgba.b,m_rgba.a);\r\n\t\r\n\tDbg_MsgAssert(mp_models[m_num_models].mpModel==NULL,(\"mp_models[m_num_models].mpModel not NULL ?\"));\r\n\tmp_models[m_num_models].mpModel=p_new_model;\r\n\t\r\n\tmp_models[m_num_models].mOffset=offset;\r\n\t++m_num_models;\r\n\r\n\tupdate_visibility();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CElement3d::AddModelFromSector(uint32 sectorName, Mth::Vector offset)\r\n{\r\n\tDbg_MsgAssert(m_num_models<MAX_MODELS_PER_ELEMENT,(\"Reached max models for one CElement3d\"));\r\n\t\t\r\n\tNx::CModel *p_new_model=Nx::CEngine::sInitModel();\r\n\tDbg_MsgAssert(p_new_model,(\"Nx::CEngine::sInitModel() returned NULL\"));\r\n\t\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(sectorName);\r\n\tDbg_MsgAssert( p_sector, ( \"This is not my beautiful CSector. sGetSector(0x%x) returned NULL (%s)\\n\", sectorName, Script::FindChecksumName(sectorName) ) );\r\n\r\n\tif ( p_sector )\r\n\t{\r\n\t\t// need to clone the source, not the instance?\r\n\t\tNx::CGeom* p_geom = p_sector->GetGeom();\r\n\t\tDbg_Assert(p_geom);\r\n\t\tif( p_geom )\r\n\t\t{\r\n\t\t\tNx::CGeom* p_cloned_geom = p_geom->Clone( true );\r\n\t\t\tp_cloned_geom->SetActive(true);\r\n\t\t\tp_new_model->AddGeom( p_cloned_geom, 0 );\r\n\t\t}\r\n\t}\r\n\t\r\n\tp_new_model->SetColor(m_rgba.r,m_rgba.g,m_rgba.b,m_rgba.a);\r\n\t\r\n\tDbg_MsgAssert(mp_models[m_num_models].mpModel==NULL,(\"mp_models[m_num_models].mpModel not NULL ?\"));\r\n\tmp_models[m_num_models].mpModel=p_new_model;\r\n\t\r\n\tmp_models[m_num_models].mOffset=offset;\r\n\t++m_num_models;\r\n\r\n\tupdate_visibility();\r\n}\r\n\r\n\r\nvoid CElement3d::AutoComputeScale()\r\n{\t\r\n\tMth::Vector element_world_min, element_world_max;\r\n\tfor (int i = 0; i < m_num_models; i++)\r\n\t{\r\n\t\tNx::CGeom *p_geom = mp_models[i].mpModel->GetGeom(0);\r\n\t\tDbg_Assert(p_geom);\r\n\t\tMth::CBBox b_box = p_geom->GetBoundingBox();\r\n\t\tMth::Vector model_min(mp_models[i].mOffset.GetX() + b_box.GetMin().GetX(),\r\n\t\t\t\t\t\t\t  mp_models[i].mOffset.GetY() + b_box.GetMin().GetY(),\r\n\t\t\t\t\t\t\t  mp_models[i].mOffset.GetZ() + b_box.GetMin().GetZ());\r\n\t\tMth::Vector model_max(mp_models[i].mOffset.GetX() + b_box.GetMax().GetX(),\r\n\t\t\t\t\t\t\t  mp_models[i].mOffset.GetY() + b_box.GetMax().GetY(),\r\n\t\t\t\t\t\t\t  mp_models[i].mOffset.GetZ() + b_box.GetMax().GetZ());\r\n\r\n\t\tif (i == 0)\r\n\t\t{\r\n\t\t\telement_world_min = model_min;\r\n\t\t\telement_world_max = model_max;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (model_min[X] < element_world_min[X])\r\n\t\t\t\telement_world_min[X] = model_min[X];\r\n\t\t\tif (model_min[Y] < element_world_min[Y])\r\n\t\t\t\telement_world_min[Y] = model_min[Y];\r\n\t\t\tif (model_min[Z] < element_world_min[Z])\r\n\t\t\t\telement_world_min[Z] = model_min[Z];\r\n\r\n\t\t\tif (model_max[X] > element_world_max[X])\r\n\t\t\t\telement_world_max[X] = model_max[X];\r\n\t\t\tif (model_max[Y] > element_world_max[Y])\r\n\t\t\t\telement_world_max[Y] = model_max[Y];\r\n\t\t\tif (model_max[Z] > element_world_max[Z])\r\n\t\t\t\telement_world_max[Z] = model_max[Z];\r\n\t\t}\r\n\r\n\t\t/*\r\n\t\tRyan(\"offset is (%.2f,%.2f,%.2f), min is (%.2f,%.2f,%.2f), max is (%.2f,%.2f,%.2f)\\n\",\r\n\t\t\t mp_models[i].mOffset.GetX(), mp_models[i].mOffset.GetY(), mp_models[i].mOffset.GetZ(),\r\n\t\t\t b_box.GetMin().GetX(), b_box.GetMin().GetY(), b_box.GetMin().GetZ(),\r\n\t\t\t b_box.GetMax().GetX(), b_box.GetMax().GetY(), b_box.GetMax().GetZ());\r\n\t\t*/\r\n\t}\r\n\r\n\tfloat element_world_w = element_world_max[X] - element_world_min[X];\r\n\tfloat element_world_h = element_world_max[Y] - element_world_min[Y];\r\n\tfloat element_world_l = element_world_max[Z] - element_world_min[Z];\r\n\tm_scale3d = sGetScaleFromScreenDimensions(m_base_w, m_base_h, \r\n\t\t\t\t\t\t\t\t  m_camera_z, \r\n\t\t\t\t\t\t\t\t  (element_world_w > element_world_l) ? element_world_w : element_world_l,\r\n\t\t\t\t\t\t\t\t\telement_world_h);\r\n\t\r\n\t/*\r\n\tRyan(\"yo homies, world dims are: (%.2f,%.2f,%.2f), desired scale is: (%.5f,%.5f), camera_z1 is %.4f, camera_z2 is %.4f\\n\", \r\n\t\t element_world_w, element_world_h, element_world_l,\r\n\t\t scale, scale, m_camera_z, m_camera_z + element_world_max[Z] * scale);\r\n\t*/\r\n\t//CScreenElement::SetScale(scale, scale, false, CScreenElement::FORCE_INSTANT);\r\n\r\n\tm_offset_of_origin_from_center.Set(-(element_world_max[X] + element_world_min[X]) / 2.0f,\r\n\t\t\t\t\t\t\t\t\t   -(element_world_max[Y] + element_world_min[Y]) / 2.0f,\r\n\t\t\t\t\t\t\t\t\t   -(element_world_max[Z] + element_world_min[Z]) / 2.0f,\r\n\t\t\t\t\t\t\t\t\t   0.0f);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// This gets called by the SetProps script command.\r\n// Also gets called when the element is first created by CreateScreenElement, all the params sent\r\n// to CreateScreenElement get dent to this function.\r\nvoid CElement3d::SetProperties(Script::CStruct *p_props)\r\n{\r\n\tCScreenElement::SetProperties(p_props);\r\n\t\r\n\tuint32 skeletonChecksum = 0;\r\n\tp_props->GetChecksum( CRCD(0x9794932,\"skeletonName\"), &skeletonChecksum, false );\r\n\t\r\n\tconst char* p_model_name=\"\";\r\n\tScript::CArray *p_model_array=NULL;\r\n\tuint32 clone_model_name;\r\n\tuint32 sector_name;\r\n\tScript::CArray *p_sector_array=NULL;\r\n\tbool skip_empty_model = false;\r\n    \r\n    int texDictOffset = 0;\r\n    p_props->GetInteger( CRCD(0xf891ac27,\"TexDictOffset\"), &texDictOffset, false );\r\n\t\r\n\tif (p_props->GetChecksum( CRCD(0x73ec4c8,\"CloneModel\"), &clone_model_name ))\r\n\t{\r\n\t\tUnloadModels();\r\n\t\t\r\n\t\tMth::Vector off;\r\n\t\toff.Set();\r\n\r\n\t\t// Clone the geometry off of an existing model\r\n\t\tObj::CCompositeObject* pObject = static_cast<Obj::CCompositeObject *>(Obj::CCompositeObjectManager::Instance()->GetObjectByID(clone_model_name));\r\n\t\tDbg_MsgAssert( pObject, ( \"Couldn't find object id %d to clone\", clone_model_name ) );\r\n\r\n\t\tObj::CModelComponent *p_src_model_comp = GetModelComponentFromObject(pObject);\r\n\t\tDbg_MsgAssert( p_src_model_comp, ( \"Couldn't find model component in object id %d\", clone_model_name ) );\r\n\t\tDbg_MsgAssert( p_src_model_comp->GetModel(), ( \"Couldn't find CModel in model component of object id %d\", clone_model_name ) );\r\n\r\n\t\tScript::CArray *p_geom_array=NULL;\r\n\t\tif (p_props->GetArray(CRCD(0x3cc0910b,\"CloneModelGeoms\"), &p_geom_array))\r\n\t\t{\r\n\t\t\t// Create new model\r\n\t\t\tNx::CModel *p_model = CreateModel(skeletonChecksum, off);\r\n\r\n\t\t\tuint32 geomName;\r\n\t\t\tfor (uint i = 0; i < p_geom_array->GetSize(); i++)\r\n\t\t\t{\r\n\t\t\t\tgeomName = p_geom_array->GetChecksum(i);\r\n\t\t\t\tif (geomName)\r\n\t\t\t\t{\r\n\t\t\t\t\tNx::CGeom *p_orig_geom = p_src_model_comp->GetModel()->GetGeom(geomName);\r\n\t\t\t\t\tDbg_MsgAssert(p_orig_geom, (\"Couldn't find CGeom %s\", Script::FindChecksumName(geomName)));\r\n\r\n\t\t\t\t\tNx::CGeom *p_new_geom = p_orig_geom->Clone(true, p_model);\r\n\t\t\t\t\tDbg_MsgAssert(p_new_geom, (\"Couldn't clone CGeom %s\", Script::FindChecksumName(geomName)));\r\n\r\n\t\t\t\t\tp_new_geom->SetActive(true);\r\n\t\t\t\t\tp_model->AddGeom(p_new_geom, geomName);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Must name geoms for object id %d to clone\", clone_model_name ) );\r\n\t\t}\r\n\r\n\t\tupdate_visibility();\r\n\t\tskip_empty_model = true;\r\n\t}\t\r\n\telse if (p_props->GetString( CRCD(0x286a8d26,\"model\"), &p_model_name ))\r\n\t{\r\n\t\tUnloadModels();\r\n\t\t\r\n\t\tMth::Vector off;\r\n\t\toff.Set();\r\n\t\tAddModel(p_model_name,skeletonChecksum,off,texDictOffset);\r\n\t}\t\r\n\telse if (p_props->GetArray(CRCD(0x1b29cff6,\"models\"),&p_model_array))\r\n\t{\r\n\t\tUnloadModels();\r\n\t\tfor (uint32 i=0; i<p_model_array->GetSize(); ++i)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_struct=p_model_array->GetStructure(i);\r\n\t\t\tp_struct->GetString(NONAME,&p_model_name);\r\n\t\t\tMth::Vector off;\r\n\t\t\toff.Set();\r\n\t\t\tp_struct->GetVector(NONAME,&off);\r\n\t\t\tAddModel(p_model_name,skeletonChecksum,off,texDictOffset);\r\n\t\t}\r\n\t}\t \r\n\tif (p_props->GetChecksum( CRCD(0xb45c2617,\"sector\"), &sector_name ))\r\n\t{\r\n\t\tUnloadModels();\r\n\t\t\r\n\t\tMth::Vector off;\r\n\t\toff.Set();\r\n\t\tAddModelFromSector(sector_name, off);\r\n\t}\t\r\n\telse if (p_props->GetArray(CRCD(0x4a6bf967,\"sectors\"), &p_sector_array))\r\n\t{\r\n\t\tUnloadModels();\r\n\t\tfor (uint32 i=0; i < p_sector_array->GetSize(); ++i)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_struct = p_sector_array->GetStructure(i);\r\n\t\t\tp_struct->GetChecksum(NONAME, &sector_name);\r\n\t\t\tMth::Vector off;\r\n\t\t\toff.Set();\r\n\t\t\tp_struct->GetVector(NONAME, &off);\r\n\t\t\tAddModelFromSector(sector_name, off);\r\n\t\t}\r\n\t}\t \r\n\telse if ( (skeletonChecksum != 0) && !skip_empty_model )\r\n\t{\r\n\t\t// no model was specified, but we might need to create\r\n\t\t// a skeleton anyway (like for the preview models)\r\n\t\tMth::Vector off;\r\n\t\toff.Set();\r\n\t\tAddModel(NULL, skeletonChecksum, off, 0);\r\n\t}\r\n\t\r\n\tp_props->GetFloat(CRCD(0xed7c6031,\"CameraZ\"),&m_camera_z);\r\n\tp_props->GetFloat(CRCD(0xaffd09d,\"AngleX\"),&m_angle_x);\r\n\tp_props->GetFloat(CRCD(0x7df8e00b,\"AngleY\"),&m_angle_y);\r\n\tp_props->GetFloat(CRCD(0xe4f1b1b1,\"AngleZ\"),&m_angle_z);\r\n\tp_props->GetFloat(CRCD(0xc1608989,\"AngVelX\"),&m_angvel_x);\r\n\tp_props->GetFloat(CRCD(0xb667b91f,\"AngVelY\"),&m_angvel_y);\r\n\tp_props->GetFloat(CRCD(0x2f6ee8a5,\"AngVelZ\"),&m_angvel_z);\r\n\r\n\tif (p_props->ContainsFlag(CRCD(0x233f6b18,\"AngleOrderXYZ\"))) m_angle_order = ANGLE_ORDER_XYZ;\r\n\tif (p_props->ContainsFlag(CRCD(0x911b6961,\"AngleOrderXZY\"))) m_angle_order = ANGLE_ORDER_XZY;\r\n\tif (p_props->ContainsFlag(CRCD(0x3be6306e,\"AngleOrderYXZ\"))) m_angle_order = ANGLE_ORDER_YXZ;\r\n\tif (p_props->ContainsFlag(CRCD(0xe7de33c0,\"AngleOrderYZX\"))) m_angle_order = ANGLE_ORDER_YZX;\r\n\tif (p_props->ContainsFlag(CRCD(0xa0a9df8d,\"AngleOrderZXY\"))) m_angle_order = ANGLE_ORDER_ZXY;\r\n\tif (p_props->ContainsFlag(CRCD(0xceb5de5a,\"AngleOrderZYX\"))) m_angle_order = ANGLE_ORDER_ZYX;\r\n\r\n\tif (p_props->ContainsFlag(CRCD(0xf01fdca4,\"DisablePointing\")))\r\n\t{\r\n\t\tm_point_type=POINT_TYPE_NONE;\r\n\t}\r\n\t\t\r\n\tuint32 node_checksum=0;\r\n\tif (p_props->GetChecksum(CRCD(0xb2a86eb5,\"NodeToPointTo\"),&node_checksum))\r\n\t{\r\n\t\tint node_to_point_to=SkateScript::FindNamedNode(node_checksum);\r\n\t\tScript::CStruct *p_node=SkateScript::GetNode(node_to_point_to);\r\n\t\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\t\tSkateScript::GetPosition(p_node,&m_node_position_to_point_to);\r\n\r\n\t\tm_point_type=POINT_TYPE_NODE;\r\n\t}\t\r\n\r\n\tm_id_of_object_to_point_to=0;\r\n\tif (p_props->GetChecksum(CRCD(0xdad39b88,\"ObjectToPointTo\"),&m_id_of_object_to_point_to))\r\n\t{\r\n\t\tm_point_type=POINT_TYPE_OBJECT;\r\n\t}\t\r\n\t\r\n\tm_tilt=0.0f;\r\n\tp_props->GetFloat(CRCD(0xe3c07609,\"Tilt\"),&m_tilt);\r\n\t\r\n\tm_hover_amp=0.0f;\r\n\tm_hover_period=0;\r\n\tScript::CStruct *p_hover_params=NULL;\r\n\tif (p_props->GetStructure(CRCD(0xca1c41,\"HoverParams\"),&p_hover_params))\r\n\t{\r\n\t\tp_hover_params->GetFloat(CRCD(0xc9fde32c,\"Amp\"),&m_hover_amp);\r\n\t\tfloat f=1.0f;\r\n\t\tp_hover_params->GetFloat(CRCD(0xa80bea4a,\"Freq\"),&f);\r\n\t\tm_hover_period=(int)(1000.0f/f);\r\n\t}\r\n\t\r\n\tm_skater_number=0;\r\n\tm_parent_object_name=0;\r\n\tm_parent_node_name=0;\r\n\tm_parent_offset.Set();\r\n\tScript::CStruct *p_parent_params=NULL;\r\n\tif (p_props->GetStructure(CRCD(0x36388933,\"ParentParams\"),&p_parent_params))\r\n\t{\r\n\t\tp_parent_params->GetChecksum(CRCD(0xa1dc81f9,\"Name\"),&m_parent_object_name);\r\n\t\tp_parent_params->GetVector(NONAME,&m_parent_offset);\r\n\t\tif (p_parent_params->GetInteger(CRCD(0x5b8ab877,\"Skater\"),&m_skater_number))\r\n\t\t{\r\n\t\t\tm_parent_object_name=0x5b8ab877/*Skater*/;\r\n\t\t}\t\r\n\t\t// Sometimes they want an arrow to be hovering near an actual node,\r\n\t\t// rather than the instance of some CObject associated with that node.\r\n\t\t// Eg, they may want an arrow hovering over some level geometry.\r\n\t\tp_parent_params->GetChecksum(CRCD(0x7a8017ba,\"Node\"),&m_parent_node_name);\r\n\t\t\r\n\t\tDbg_MsgAssert(!(m_parent_node_name && m_parent_object_name),(\"Cannot specify both a parent object and a parent node for an element3d\"));\r\n\t}\r\n\r\n\tif (p_props->ContainsFlag(CRCD(0x1b399065,\"scale_to_screen_dims\")))\r\n\t{\r\n\t\tAutoComputeScale();\r\n\t}\r\n\telse if (p_props->GetVector(\"PivotPoint\", &m_pivot_point))\r\n\t{\r\n\t\tm_pivot_point[W] = 1.0f;\t\t// force to be a point\r\n\t}\r\n\r\n\tm_scale_with_distance=p_props->ContainsFlag(CRCD(0x4564c8f2,\"ScaleWithDistance\"));\r\n\tm_scale_multiplier=0.002f;\r\n\tp_props->GetFloat(CRCD(0x571f3f3a,\"ScaleMultiplier\"),&m_scale_multiplier);\r\n\tm_max_scale=3.0f;\r\n\tp_props->GetFloat(CRCD(0x31e78f98,\"MaxScale\"),&m_max_scale);\r\n\r\n\r\n\tint viewport;\r\n\tif (p_props->GetInteger(CRCD(0x655ee08e,\"Active_Viewport\"), &viewport))\r\n\t{\r\n\t\tm_active_viewport_number = viewport;\r\n\t\tupdate_visibility();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CElement3d::update()\r\n{\r\n\tif (m_waiting_to_die)\r\n\t{\r\n\t\t// Return straight away to prevent repeated spawnings of the KillElement3d script\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tif (m_num_models)\r\n\t{\t\t\t\t\t\t\t\r\n\t\tif (m_parent_object_name)\r\n\t\t{\r\n\t\t\t// Get a pointer to the parent object.\r\n\t\t\tObj::CMovingObject *p_pos_obj=NULL;\r\n\r\n// Skate module \r\n//\t\t\tif (m_parent_object_name==0x5b8ab877/*Skater*/)\r\n//\t\t\t{\r\n//\t\t\t\t// This is \r\n//\t\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n//\t\t\t\tp_pos_obj=skate_mod->GetSkater(m_skater_number);\r\n//\t\t\t}\r\n//\t\t\telse\t\t\t\r\n\t\t\t{\r\n//\t\t\t\tp_pos_obj=Obj::CMovingObject::m_hash_table.GetItem(m_parent_object_name);\r\n\t\t\t\tp_pos_obj = (Obj::CMovingObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID(m_parent_object_name);\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tif (p_pos_obj)\r\n\t\t\t{\r\n\t\t\t\tm_model_matrix.Ident();\r\n\t\t\t\tm_model_matrix.SetPos(p_pos_obj->m_pos+m_parent_offset*m_model_matrix);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// The parent object has disappeared!\r\n\t\t\t\t// So call the KillElement3d script to safely delete this arrow.\r\n\t\t\t\t\r\n\t\t\t\t// Tried various ways of killing directly from c-code, but they didn't work.\r\n\t\t\t\t// Instant deletion here will mess up the update loop, and calling\r\n\t\t\t\t// Die() to flag the element for deletion later also cause problems, because\r\n\t\t\t\t// the parent element needs to be unlocked at the time of deletion.\r\n\t\t\t\t\r\n\t\t\t\t// Running a script seems to be safe ...\r\n\t\t\t\t// The KillElement3d script will wait a gameframe, then call the usual Die\r\n\t\t\t\tScript::CScript *p_script=Script::SpawnScript(0xa66c1c31/*KillElement3d*/);\r\n\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\tp_script->SetCommentString(\"Created by CElement3d::update()\");\r\n\t\t\t\t#endif\r\n\t\t\t\tp_script->mpObject=this;\r\n\t\t\t\tm_waiting_to_die=true;\r\n\t\t\t}\t\r\n\t\t}\r\n\t\telse if (m_parent_node_name)\r\n\t\t{\r\n\t\t\t// FindNamedNode will assert if it does not find the node.\r\n\t\t\tint node_index=SkateScript::FindNamedNode(m_parent_node_name);\r\n\t\t\tScript::CStruct *p_node=SkateScript::GetNode(node_index);\r\n\t\t\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\t\t\t\r\n\t\t\tMth::Vector pos;\r\n\t\t\tSkateScript::GetPosition(p_node,&pos);\r\n\t\t\t\r\n\t\t\tm_model_matrix.Ident();\r\n\t\t\tm_model_matrix.SetPos( pos + m_parent_offset * m_model_matrix );\r\n\t\t\t// m_model_matrix.SetPos(pos);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tMth::Vector pos_change(m_offset_of_origin_from_center[X] * m_scale3d,\r\n\t\t\t\t\t\t\t\t   m_offset_of_origin_from_center[Y] * m_scale3d,\r\n\t\t\t\t\t\t\t\t   m_offset_of_origin_from_center[Z] * m_scale3d);\r\n\t\t\t/*\r\n\t\t\tMth::Vector pos_change(m_offset_of_origin_from_center[X] * m_summed_props.scalex * m_scale3d,\r\n\t\t\t\t\t\t\t\t   m_offset_of_origin_from_center[Y] * m_summed_props.scaley * m_scale3d,\r\n\t\t\t\t\t\t\t\t   m_offset_of_origin_from_center[Z] * m_summed_props.scalex * m_scale3d);\r\n\t\t\t*/\r\n\t\t\tsGetWorldMatrixFromScreenPosition(m_active_viewport_number, &m_model_matrix, \r\n\t\t\t\t\t\t\t\t\t\t\t  m_summed_props.GetScreenUpperLeftX() + GetAbsW() / 2.0f, \r\n\t\t\t\t\t\t\t\t\t\t\t  m_summed_props.GetScreenUpperLeftY() + GetAbsH() / 2.0f, \r\n\t\t\t\t\t\t\t\t\t\t\t  m_camera_z, \r\n\t\t\t\t\t\t\t\t\t\t\t  pos_change);\r\n\t\r\n\t\t\t// If the model were rendered using m_model_matrix as it is then it will be unscaled\r\n\t\t\t// and facing the camera.\r\n\t\t\t\r\n\t\t\t// If the object is required to point to somewhere in the world then change the rotation\r\n\t\t\t// the be the required one.\r\n\t\t\tMth::Vector position_to_point_to;\r\n\t\t\tswitch (m_point_type)\r\n\t\t\t{\r\n\t\t\tcase POINT_TYPE_NODE:\r\n\t\t\t\tposition_to_point_to=m_node_position_to_point_to;\r\n\t\t\t\tbreak;\r\n\t\t\tcase POINT_TYPE_OBJECT:\r\n\t\t\t{\r\n\t\t\t\t// Get a pointer to the object.\r\n\t\t\t\t// Doing a naughty cast up to a CMovingObject, because it probably will be one, and\r\n\t\t\t\t// won't cause a crash if it isn't, it'll just get a bad position.\r\n\t\t\t\tObj::CMovingObject *p_pos_obj=(Obj::CMovingObject*)Obj::ResolveToObject(m_id_of_object_to_point_to);\r\n\t\t\t\tif (p_pos_obj)\r\n\t\t\t\t{\r\n\t\t\t\t\tposition_to_point_to=p_pos_obj->m_pos;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (m_point_type!=POINT_TYPE_NONE)\r\n\t\t\t{\r\n\t\t\t\t// Save the position\r\n\t\t\t\tMth::Vector model_pos=m_model_matrix.GetPos();\r\n\t\t\t\t// Clear out the rotation calculated by sGetWorldMatrixFromScreenPosition\r\n\t\t\t\tm_model_matrix.Ident();\r\n\t\t\t\t\r\n\t\t\t\tMth::Vector dir=position_to_point_to-model_pos;\r\n\t\t\t\t\r\n\t\t\t\tdir.Normalize();\r\n\t\t\t\tm_model_matrix[Z]=dir;\r\n\t\t\t\t\r\n\t\t\t\tm_model_matrix[X].Set(dir.GetZ(),0.0f,-dir.GetX());\r\n\t\t\t\tm_model_matrix[X].Normalize();\r\n\t\t\t\t\r\n\t\t\t\tm_model_matrix.OrthoNormalizeAbout(Z);\r\n\t\t\t\t\r\n\t\t\t\t// Tilt so that the arrow is not end on to the camera.\r\n\t\t\t\t// However, make the tilt drop linearly down to zero as the\r\n\t\t\t\t// arrow goes towards being vertical so that the arrow never\r\n\t\t\t\t// ends up pointing backwards.\r\n\t\t\t\tfloat r=m_tilt-(-m_model_matrix[Z].GetY()*m_tilt);\r\n\t\t\t\tm_model_matrix.RotateXLocal(Mth::DegToRad(r));\r\n\r\n\t\t\t\t// Put the position back in.\r\n\t\t\t\tm_model_matrix.Translate(model_pos);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\t\t\r\n\t\t// Now create a rotation matrix containing any extra rotation that we want.\r\n\t\tMth::Matrix rot_matrix;\r\n\t\trot_matrix.Ident();\r\n\r\n\t\trot_matrix.Translate(-m_pivot_point);\r\n\r\n\t\t// Update the angles using the angular velocities.\r\n\t\tm_angle_x+=m_angvel_x;\r\n\t\tm_angle_y+=m_angvel_y;\r\n\t\tm_angle_z+=m_angvel_z;\r\n\t\t\r\n\t\t// Reduce modulo 2pi so that the calculations don't go weird after a few days\r\n\t\t// due to the angles getting huge.\r\n\t\tm_angle_x=m_angle_x-((int)(m_angle_x/(2.0f*3.141592654f)))*(2.0f*3.141592654f);\r\n\t\tm_angle_y=m_angle_y-((int)(m_angle_y/(2.0f*3.141592654f)))*(2.0f*3.141592654f);\r\n\t\tm_angle_z=m_angle_z-((int)(m_angle_z/(2.0f*3.141592654f)))*(2.0f*3.141592654f);\r\n\t\t\r\n\t\t//rot_matrix.RotateY(m_angle_y);\r\n\t\t//rot_matrix.RotateX(m_angle_x);\r\n\t\t//rot_matrix.RotateZ(m_angle_z);\r\n\t\ts_apply_rotations(rot_matrix, m_angle_x, m_angle_y, m_angle_z, m_angle_order);\r\n\r\n\t\trot_matrix.Translate(m_pivot_point);\r\n\r\n\t\t// Apply scaling.\r\n\t\t//Ryan(\"oogbat %.4f, %.4f, %.4f\\n\", m_summed_props.scalex, m_scale3d, m_summed_props.scalex * m_scale3d);\r\n\t\tMth::Vector scale(m_summed_props.GetScaleX() * m_scale3d,\r\n\t\t\t\t\t\t  m_summed_props.GetScaleY() * m_scale3d,\r\n\t\t\t\t\t\t  m_summed_props.GetScaleX() * m_scale3d,\r\n\t\t\t\t\t\t  1.0f);\r\n\t\t\t\t\t\t  \r\n\t\t// The ped arrows (or stars) need to scale according to the distance from the camera so that\r\n\t\t// they are visible from a distance. (TT2006)\r\n\t\tif (m_scale_with_distance)\r\n\t\t{\r\n\t\t\tGfx::Camera *p_camera = Nx::CViewportManager::sGetActiveCamera(m_active_viewport_number);\r\n\t\t\tif (p_camera)\r\n\t\t\t{\r\n\t\t\t\tMth::Vector cam_offset=m_model_matrix.GetPos()-p_camera->GetPos();\r\n\t\t\t\tfloat multiplier=cam_offset.Length()*m_scale_multiplier;\r\n\t\t\t\tif (multiplier < 1.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\tmultiplier=1.0f;\r\n\t\t\t\t}\r\n\t\t\t\tif (multiplier > m_max_scale)\r\n\t\t\t\t{\r\n\t\t\t\t\tmultiplier = m_max_scale;\r\n\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\tscale[X]*=multiplier;\r\n\t\t\t\tscale[Y]*=multiplier;\r\n\t\t\t\tscale[Z]*=multiplier;\r\n\t\t\t}\t\r\n\t\t}\r\n\t\t\r\n\t\trot_matrix.Scale(scale);\r\n\r\n\t\t// Apply the rotation and scaling to the m_model_matrix\t\r\n\t\tm_model_matrix=rot_matrix*m_model_matrix;\r\n\r\n\r\n\t\t// Calculate any hover offset that may need to be applied.\t\t\r\n\t\tMth::Vector hover_offset;\r\n\t\tif (m_hover_amp>0.0f)\r\n\t\t{\r\n\t\t\tint t=Tmr::ElapsedTime(0)%m_hover_period;\r\n\t\t\tfloat h=m_hover_amp*sinf(t*2*3.141592653f/m_hover_period);\r\n\t\t\t// Use m_model_matrix[Y] so that it hovers up and down in the model's\r\n\t\t\t// coordinate system.\r\n\t\t\thover_offset=h*m_model_matrix[Y];\r\n\t\t}\r\n\t\t\r\n\t\t// Render the models\r\n\t\tbool show_models = (m_summed_props.alpha >= .0001f);\r\n\t\t\r\n\t\t// If running a replay, hide arrows that are pointing to something,\r\n\t\t// otherwise they go all spazzy. (TT8083 and TT8819)\r\n\t\tif ((m_point_type!=POINT_TYPE_NONE || m_parent_object_name) && Replay::RunningReplay())\r\n\t\t{\r\n\t\t\tshow_models=false;\r\n\t\t}\t\r\n\t\t\r\n\r\n\t\tfor (int i=0; i<m_num_models; ++i)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(mp_models[i].mpModel,(\"NULL mp_models[i].mpModel\"));\r\n\t\t\t\r\n\t\t\tMth::Vector p=mp_models[i].mOffset*m_model_matrix;\r\n\t\t\tMth::Matrix display_matrix=m_model_matrix;\r\n\t\t\t\r\n\t\t\tif (m_hover_amp>0.0f)\r\n\t\t\t{\r\n\t\t\t\tp+=hover_offset;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tdisplay_matrix.SetPos(p);\r\n\t\t\t\r\n\t\t\tmp_models[i].mpModel->SetActive(show_models);\r\n\t\t\tmp_models[i].mpModel->Render(&display_matrix,false,mp_models[i].mpSkeleton);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CElement3d::SetMorph(Script::CStruct *pProps)\r\n{\r\n\tCScreenElement::SetMorph(pProps);\r\n\tif (pProps->ContainsFlag(\"scale_to_screen_dims\"))\r\n\t\tAutoComputeScale();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CElement3d::update_visibility()\r\n{\r\n\t// Make visible for only this viewport\r\n\tuint32 vis_mask = 1 << m_active_viewport_number;\r\n\tfor (int i=0; i<m_num_models; ++i)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_models[i].mpModel,(\"NULL mp_models[i].mpModel\"));\r\n\r\n\t\tmp_models[i].mpModel->SetVisibility(vis_mask);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CElement3d::s_apply_rotations(Mth::Matrix & mat, float x_rot, float y_rot, float z_rot, EAngleOrder rot_order)\r\n{\r\n\tswitch (rot_order)\r\n\t{\r\n\tcase ANGLE_ORDER_XYZ:\r\n\t\tmat.RotateX(x_rot);\r\n\t\tmat.RotateY(y_rot);\r\n\t\tmat.RotateZ(z_rot);\r\n\t\tbreak;\r\n\r\n\tcase ANGLE_ORDER_XZY:\r\n\t\tmat.RotateX(x_rot);\r\n\t\tmat.RotateZ(z_rot);\r\n\t\tmat.RotateY(y_rot);\r\n\t\tbreak;\r\n\r\n\tcase ANGLE_ORDER_YXZ:\r\n\t\tmat.RotateY(y_rot);\r\n\t\tmat.RotateX(x_rot);\r\n\t\tmat.RotateZ(z_rot);\r\n\t\tbreak;\r\n\r\n\tcase ANGLE_ORDER_YZX:\r\n\t\tmat.RotateY(y_rot);\r\n\t\tmat.RotateZ(z_rot);\r\n\t\tmat.RotateX(x_rot);\r\n\t\tbreak;\r\n\r\n\tcase ANGLE_ORDER_ZXY:\r\n\t\tmat.RotateZ(z_rot);\r\n\t\tmat.RotateX(x_rot);\r\n\t\tmat.RotateY(y_rot);\r\n\t\tbreak;\r\n\r\n\tcase ANGLE_ORDER_ZYX:\r\n\t\tmat.RotateZ(z_rot);\r\n\t\tmat.RotateY(y_rot);\r\n\t\tmat.RotateX(x_rot);\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gfx/2D/Element3d.h",
    "content": "#ifndef __GFX_2D_ELEMENT3D_H__\r\n#define __GFX_2D_ELEMENT3D_H__\r\n\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n#include <gfx/2D/ScreenElement2.h>\r\n\r\nnamespace Gfx\r\n{\r\n    class CSkeleton;\r\n};\r\n                     \r\nnamespace Nx\r\n{\r\n    class CModel;\r\n};\r\n\r\nnamespace Script\r\n{\r\n\tclass CScript;\r\n\tclass CStruct;\r\n};\r\n\r\nnamespace Front\r\n{\r\n\r\n#define MAX_MODELS_PER_ELEMENT 25\r\n\r\nstruct SSubModel\r\n{\r\n\tNx::CModel\t*mpModel;\r\n    Gfx::CSkeleton* mpSkeleton;\r\n\tMth::Vector mOffset;\r\n};\r\n\t\r\nclass CElement3d : public CScreenElement\r\n{\r\n\tfriend class CScreenElementManager;\r\n\r\n\tSSubModel mp_models[MAX_MODELS_PER_ELEMENT];\r\n\tint\t\tm_num_models;\r\n\t\r\n\tfloat\tm_camera_z;\r\n\tfloat\tm_angle_x;\r\n\tfloat\tm_angle_y;\r\n\tfloat\tm_angle_z;\r\n\tfloat\tm_angvel_x;\r\n\tfloat\tm_angvel_y;\r\n\tfloat\tm_angvel_z;\r\n\r\n\tMth::Matrix m_model_matrix;\r\n\t\r\n\tenum EPointType\r\n\t{\r\n\t\tPOINT_TYPE_NONE,\r\n\t\tPOINT_TYPE_NODE,\r\n\t\tPOINT_TYPE_OBJECT,\r\n\t};\r\n\tMth::Vector m_node_position_to_point_to;\r\n\tEPointType m_point_type;\r\n\t\r\n\tenum EAngleOrder\r\n\t{\r\n\t\tANGLE_ORDER_XYZ,\r\n\t\tANGLE_ORDER_XZY,\r\n\t\tANGLE_ORDER_YXZ,\r\n\t\tANGLE_ORDER_YZX,\r\n\t\tANGLE_ORDER_ZXY,\r\n\t\tANGLE_ORDER_ZYX,\r\n\t};\r\n\tEAngleOrder m_angle_order;\r\n\r\n\tuint32 m_id_of_object_to_point_to;\r\n\r\n\tfloat m_hover_amp;\r\n\tint m_hover_period;\r\n\r\n\tMth::Vector m_pivot_point;\t\t\t\t// Point in local space for rotations\r\n\r\n\t// These following members are used when the element3d is associated with some 3d position.\r\n\t// The 3d poistion can be got from an instance of a CObject, or from a fixed node.\r\n\r\n\t// Offset from the parent position.\r\n\tMth::Vector m_parent_offset;\r\n\t\t\r\n\tMth::Vector m_offset_of_origin_from_center; // origin - center\r\n\r\n\t// different from 2D scale, is scale of 3D object\r\n\tfloat\t\tm_scale3d;\r\n\r\n\t// These three are used for when the object needs to scale according to the distance from the camera.\r\n\tbool \tm_scale_with_distance;\r\n\tfloat \tm_scale_multiplier;\r\n\tfloat \tm_max_scale;\r\n\r\n\tint\t\t\tm_active_viewport_number; // viewport to draw to\r\n\t\r\n\tuint32 m_parent_object_name;\t// Non-zero if associated with an instance of a CObject\r\n\tint m_skater_number; \t\t\t// Valid if m_parent_object_name is skater\r\n\tuint32 m_parent_node_name;\t\t// Non-zero if associated with a node.\r\n\t\r\n\t// Tilt value. Used for the arrow so that it does not go totally flat, which makes the\r\n\t// direction it is pointing in hard to see. Units are degrees.\r\n\tfloat m_tilt;\r\n\t\r\n\t// These is used to flag the element to be killed if its parent object dies.\t\r\n\tbool m_waiting_to_die;\r\n\t\r\npublic:\r\n\t\t\t\tCElement3d();\r\n\tvirtual\t\t~CElement3d();\r\n\r\n\tvoid\t\tSetProperties(Script::CStruct *p_props);\r\n\tvoid\t\tSetMorph(Script::CStruct *pProps);\r\n\r\n\tvoid\t\tUnloadModels();\r\n\tvoid\t\tAddModel(const char *p_model_name, uint32 skeleton_name, Mth::Vector offset, int texDictOffset);\r\n\tvoid \t\tAddModelFromSector(uint32 sectorName, Mth::Vector offset);\r\n    Nx::CModel* CreateModel( uint32 skeleton_name, Mth::Vector offset );\r\n\tvoid \t\tAutoComputeScale();\r\n\t\r\nprotected:\r\n\r\n\tvoid\t\tupdate();\r\n\tvoid\t\tupdate_visibility();\r\n    Gfx::CSkeleton* CreateSkeleton( Nx::CModel* pModel, uint32 skeletonChecksum );\r\n\r\n\tstatic void\ts_apply_rotations(Mth::Matrix & mat, float x_rot, float y_rot, float z_rot, EAngleOrder rot_order);\r\n};\r\n\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/2D/Menu2.cpp",
    "content": "#include <core/defines.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/Event.h>\r\n#include <gfx/2D/Menu2.h>\r\n#include <gfx/2D/ScreenElemMan.h>\r\n#include <sys/timer.h>\r\n\r\nnamespace Front\r\n{\r\n\r\n\r\n\r\n\r\nCBaseMenu::CBaseMenu()\r\n{\r\n    m_selected_index = -1;\r\n    m_selected_id = 0;\r\n\tm_in_focus = false;\r\n\tm_focus_controller = 0;\r\n\r\n\tm_regular_space_val = 0.0f;\r\n\tm_padding_scale = 1.0f;\r\n\tm_spacing_between = 0.0f;\r\n\r\n\tm_internal_just_x = 0.0f;\r\n\tm_internal_just_y = 0.0f;\r\n\t\r\n\tm_pad_handling_enabled = true;\r\n\tm_allow_wrap = true;\r\n\r\n\tm_current_grid_index = -1;\r\n}\r\n\r\n\r\n\r\n\r\nCBaseMenu::~CBaseMenu()\r\n{\r\n}\r\n\r\n\r\n\r\n\r\nvoid CBaseMenu::SetProperties(Script::CStruct *pProps)\r\n{\r\n\tfloat just[2] = { 0.0f, 0.0f };\r\n\tif (resolve_just(pProps, CRCD(0x67e093e4,\"internal_just\"), just, just+1))\r\n\t\tSetInternalJust(just[0], just[1]);\r\n\t\r\n\tint regular_space_val = 0;\r\n\tif (pProps->GetInteger(CRCD(0xf24adedb,\"regular_space_amount\"), &regular_space_val))\r\n\t\tm_regular_space_val = (float) regular_space_val;\r\n\t\r\n\tpProps->GetFloat(CRCD(0x6d853b88,\"padding_scale\"), &m_padding_scale);\r\n\t\r\n\tint spacing_between = 0;\r\n\tif (pProps->GetInteger(CRCD(0x4b4e14ab,\"spacing_between\"), &spacing_between))\r\n\t\tm_spacing_between = (float) spacing_between;\r\n\t\t\r\n\tif (pProps->ContainsFlag(CRCD(0x4bd08bfe,\"enable_pad_handling\")))\r\n\t\tm_pad_handling_enabled = true;\r\n\telse if (pProps->ContainsFlag(CRCD(0xc22541cc,\"disable_pad_handling\")))\r\n\t\tm_pad_handling_enabled = false;\r\n\r\n\tif (pProps->ContainsFlag(CRCD(0x43a7692d,\"allow_wrap\")))\r\n\t\tm_allow_wrap = true;\r\n\telse if (pProps->ContainsFlag(CRCD(0x5dea5c64,\"dont_allow_wrap\")))\r\n\t\tm_allow_wrap = false;\r\n\t\r\n\tCScreenElement::SetProperties(pProps);\r\n\t\t\r\n\treturn;\r\n}\r\n\r\n\r\n\r\n\r\nbool CBaseMenu::PassTargetedEvent(Obj::CEvent *pEvent, bool broadcast)\r\n{\t\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\t\t\t\t\t\t\t\t\t\t\t\t \r\n\tObj::CSmtPtr<CBaseMenu> p = this;\r\n\tuint32\tdebug_id = m_id;\r\n\t#endif\t\t\r\n\tif (!Obj::CObject::PassTargetedEvent(pEvent))\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\tDbg_MsgAssert(p, (\"BaseMenu (%s) deleted itself in call to PassTargetedEvent\", Script::FindChecksumName(debug_id)));\r\n\t\t\r\n\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n    \r\n\t//printf(\"VMenu receives event of type %s\\n\", Script::FindChecksumName(pEvent->GetType()));\r\n\t\r\n    if (pEvent->GetType() == Obj::CEvent::TYPE_NOTIFY_CHILD_LOCK)\r\n    {\r\n        // The currently selected child might have been removed. Make sure we update\r\n        // references and send new focus event if necessary\r\n        bool need_new_focus_event = false;\r\n        \r\n        if (m_selected_id) \r\n        {\r\n            int current_child_index;\r\n            CScreenElementPtr p_current_child = GetChildById(m_selected_id, &current_child_index);\r\n            \r\n            // see if selected child has disappeared\r\n            if (!p_current_child) \r\n            {\r\n                // child disappeared, see if another one at same index\r\n                CScreenElementPtr p_new_child = GetChildByIndex(m_selected_index);\r\n                if (p_new_child) \r\n                {\r\n                    m_selected_id = p_new_child->GetID();\r\n\t\t\t\t\tsetup_tags();\r\n\t\t\t\t\tneed_new_focus_event = true;\r\n                }\r\n                else\r\n                {\r\n                    // couldn't locate replacement\r\n                    m_selected_index = -1;\r\n\t\t\t\t\t// will set m_selected_id to 0 if no focusable item can be found\r\n\t\t\t\t\tfind_focusable_item(1, true, true);\r\n\t\t\t\t\tneed_new_focus_event = true;\r\n                }\r\n            } // end if\r\n            else\r\n            {\r\n                // selected child is still there, update indices\r\n                m_selected_index = current_child_index;\r\n\t\t\t\tsetup_tags();\r\n            }\r\n        } // end if (m_selected_id)\r\n\t\telse\r\n\t\t{\r\n            // nothing selected, so find something\r\n\t\t\tfind_focusable_item(1, true, true);\r\n\t\t\tneed_new_focus_event = true;\r\n\t\t}\r\n        \r\n        if (need_new_focus_event && m_in_focus) \r\n        {\r\n            find_focusable_item(1, true, true);\r\n            if (m_selected_id)\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct data;\r\n\t\t\t\tdata.AddInteger(CRCD(0xb30d9965,\"controller\"), m_focus_controller);\r\n\t\t\t\tp_tracker->LaunchEvent(Obj::CEvent::TYPE_FOCUS, m_selected_id, Obj::CEvent::vSYSTEM_EVENT, &data);\r\n\t\t\t}\r\n        }\r\n\r\n\t\treposition();\r\n\r\n\t\tpEvent->MarkHandled(m_id);\r\n    }\r\n\tif (pEvent->GetType() == Obj::CEvent::TYPE_FOCUS && !m_in_focus)\r\n\t{\r\n\t\tm_focus_controller = Obj::CEvent::sExtractControllerIndex(pEvent);\r\n\t\t\r\n\t\t//if (!m_is_vertical_menu)\r\n\t\t//\tprintf(\"Menu %s receives focus event, sending to 0x%x\\n\", Script::FindChecksumName(m_id), m_selected_id);\r\n\r\n\t\t// see if event has a child-to-select component\r\n\t\tint desired_grid_index = -1;\r\n\t\tif (pEvent->GetData() && pEvent->GetData()->GetInteger(CRCD(0xfacf9a8b,\"grid_index\"), &desired_grid_index))\r\n\t\t{\r\n\t\t\t// find the child that matches that grid index, if any\r\n\t\t\tint match_index = -1;\r\n\r\n\t\t\tm_current_grid_index = desired_grid_index;\r\n\t\t\t\r\n\t\t\tCScreenElementPtr p_child = mp_child_list;\r\n\t\t\tint current_index = 0;\r\n\t\t\twhile(p_child)\r\n\t\t\t{\r\n\t\t\t\tint found_grid_index = -1;\r\n\t\t\t\tif (p_child->GetIntegerTag(CRCD(0x5b92f8dd, \"tag_grid_x\"), &found_grid_index))\r\n\t\t\t\t{\r\n\t\t\t\t\tif (found_grid_index <= desired_grid_index)\r\n\t\t\t\t\t\tmatch_index = current_index;\r\n\t\t\t\t}\r\n\t\t\t\tp_child = p_child->GetNextSibling();\r\n\t\t\t\tcurrent_index++;\r\n\t\t\t} \r\n\t\t\t\r\n\t\t\tif (match_index != -1)\r\n\t\t\t{\r\n\t\t\t\tm_selected_index = match_index;\r\n\t\t\t\tm_selected_id = 1;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// see if the event has a child_id component \r\n\t\tuint32 desired_child_id;\r\n\t\tif ( pEvent->GetData() && pEvent->GetData()->GetChecksum( CRCD(0x229d3de4,\"child_id\"), &desired_child_id ) )\r\n\t\t{\r\n\t\t\t// printf(\"got a desired child_id of %x\\n\", desired_child_id);\t\t\t\r\n\t\t\t// CScreenElementPtr p_child = GetChildById( desired_child_id );\r\n\t\t\tCScreenElementPtr p_child = mp_child_list;\r\n\r\n\t\t\tint current_index = 0;\r\n\t\t\twhile ( p_child )\r\n\t\t\t{\r\n\t\t\t\tif ( desired_child_id == p_child->GetID() )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_selected_id = desired_child_id;\r\n\t\t\t\t\tm_selected_index = current_index;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcurrent_index++;\r\n\t\t\t\tp_child = p_child->GetNextSibling();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tm_in_focus = true;\r\n\t\tif (m_selected_id) \r\n\t\t{\r\n\t\t\tfind_focusable_item(1, true, false);\r\n            if (m_selected_id)\r\n\t\t\t\tp_tracker->LaunchEvent(Obj::CEvent::TYPE_FOCUS, m_selected_id, Obj::CEvent::vSYSTEM_EVENT, pEvent->GetData());\r\n\t\t}\r\n\t\tpEvent->MarkHandled(m_id);\r\n\t}\r\n\tif (pEvent->GetType() == Obj::CEvent::TYPE_UNFOCUS && m_in_focus)\r\n\t{\r\n\t\t//printf(\"VMenu %s receives unfocus event\\n\", Script::FindChecksumName(m_id));\r\n\t\tm_in_focus = false;\r\n\t\tif (m_selected_id) \r\n\t\t\tp_tracker->LaunchEvent(Obj::CEvent::TYPE_UNFOCUS, m_selected_id);\r\n\t\tpEvent->MarkHandled(m_id);\r\n\t}\r\n\tif (((pEvent->GetType() == Obj::CEvent::TYPE_PAD_UP && m_is_vertical_menu) ||\r\n\t\t (pEvent->GetType() == Obj::CEvent::TYPE_PAD_LEFT && !m_is_vertical_menu)) && \r\n\t\tm_in_focus && m_pad_handling_enabled) \r\n\t{\r\n\t\tchange_selection(-1);\r\n\t\tpEvent->MarkHandled(m_id);\r\n\t}\r\n\tif (((pEvent->GetType() == Obj::CEvent::TYPE_PAD_DOWN && m_is_vertical_menu) ||\r\n\t\t (pEvent->GetType() == Obj::CEvent::TYPE_PAD_RIGHT && !m_is_vertical_menu)) && \r\n\t\tm_in_focus && m_pad_handling_enabled) \r\n\t{\r\n\t\tchange_selection(1);\r\n\t\tpEvent->MarkHandled(m_id);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool CBaseMenu::UsingRegularSpacing(float &rRegularSpaceAmount)\r\n{\r\n\trRegularSpaceAmount = m_regular_space_val;\r\n\treturn (m_regular_space_val > 0.0001f);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CBaseMenu::find_focusable_item(int dir, bool include_current, bool updateGridIndex)\r\n{\r\n\tint count = CountChildren() * 2;\r\n\r\n\tif (m_selected_index < 0)\r\n\t\tm_selected_index = 0;\r\n\t\r\n\twhile(count)\r\n\t{\r\n\t\tif (!include_current)\r\n\t\t{\r\n\t\t\tm_selected_index += dir;\r\n\t\t\tif (m_selected_index >= CountChildren())\r\n\t\t\t{\r\n\t\t\t\tif (m_allow_wrap)\r\n\t\t\t\t\tm_selected_index = 0;\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// go back to previous item, and reverse direction\r\n\t\t\t\t\tdir = -dir;\r\n\t\t\t\t\tm_selected_index = CountChildren() - 1;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (m_selected_index < 0)\r\n\t\t\t{\r\n\t\t\t\tif (m_allow_wrap)\r\n\t\t\t\t\tm_selected_index = CountChildren() - 1;\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// go back to previous item, and reverse direction\r\n\t\t\t\t\tdir = -dir;\r\n\t\t\t\t\tm_selected_index = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tinclude_current = false;\r\n\r\n\t\tCScreenElementPtr p_new_child = GetChildByIndex(m_selected_index);\r\n\t\tDbg_Assert(p_new_child);\r\n\t\tm_selected_id = p_new_child->GetID(); \r\n\t\t\r\n\t\tif (updateGridIndex)\r\n\t\t{\r\n\t\t\t// update grid index that we have stored for selected child\r\n\t\t\tm_current_grid_index = -1;\r\n\t\t\tp_new_child->GetIntegerTag(CRCD(0x5b92f8dd, \"tag_grid_x\"), &m_current_grid_index);\r\n\t\t}\r\n\r\n\t\tif ( !p_new_child->ContainsFlagTag(CRCD(0xf33a3321, \"tag_not_focusable\")) && \r\n\t\t\t !p_new_child->EventsBlocked() )\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcount--;\r\n\t}\r\n\t\r\n\tif (count)\r\n\t{\r\n\t\tsetup_tags();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// nothing selected\r\n\t\tm_selected_index = -1;\r\n\t\tm_selected_id = 0;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CBaseMenu::change_selection(int dir)\r\n{\r\n\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\t\r\n\t// if the child is also\ta menu, it will have a selected index\r\n\tint grid_index_within_child\t= -1;\r\n\t\r\n\tif (m_selected_id) \r\n\t{\r\n\t\tCScreenElementManager* p_manager = CScreenElementManager::Instance();\r\n\t\t\r\n\t\t// figure out which of selected child's children is selected\r\n\t\tCScreenElement *p_child = p_manager->GetElement(m_selected_id);\r\n\t\t// This assert is causing an occasional crash. I can't figure out the problem, so \r\n\t\t// here is the next best solution.\r\n\t\t//Dbg_MsgAssert(p_child, (\"Couldn't find selected child %s\", Script::FindChecksumName(m_selected_id)));\r\n\t\tif (p_child)\r\n\t\t\tp_child->GetIntegerTag(CRCD(0x8321dd71, \"tag_selected_childs_grid_index\"), &grid_index_within_child);\r\n\r\n\t\tp_tracker->LaunchEvent(Obj::CEvent::TYPE_UNFOCUS, m_selected_id);\r\n\t}\r\n\r\n\tfind_focusable_item(dir, false, true);\r\n\r\n\tif (m_selected_id) \r\n\t{\r\n\t\tScript::CStruct data;\r\n\t\tdata.AddInteger(\"controller\", m_focus_controller);\r\n\r\n\t\tif (grid_index_within_child != -1)\r\n\t\t{\r\n\t\t\tdata.AddInteger(\"grid_index\", grid_index_within_child);\r\n\t\t\t//printf(\"child index is %d\\n\", selected_index_of_child);\r\n\t\t}\r\n\r\n\t\tp_tracker->LaunchEvent(Obj::CEvent::TYPE_FOCUS, m_selected_id, Obj::CEvent::vSYSTEM_EVENT, &data);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CBaseMenu::setup_tags()\r\n{\r\n\tSetChecksumTag(CRCD(0xac988ebe, \"tag_selected_id\"), m_selected_id);\r\n\tSetIntegerTag(CRCD(0xf2239871, \"tag_selected_index\"), m_selected_index);\r\n\t//printf(\"setup_tags(), %s\\n\", Script::FindChecksumName(m_id));\r\n\r\n\tSetIntegerTag(CRCD(0x8321dd71, \"tag_selected_childs_grid_index\"), m_current_grid_index);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CBaseMenu::reposition() \r\n{\r\n\tfloat z = 0.0f; // functions as a virtual x or y\r\n\tfloat biggest = 0.0f; // functions as virtual 'widest' or 'highest'\r\n\r\n\tbool use_regular_space = (m_regular_space_val > 0.0001f);\r\n\t\r\n\tif (use_regular_space)\r\n\t{\r\n\t\t// do first pass to find out biggest element, total height of all elements\r\n\t\tCScreenElementPtr p_child = mp_child_list;\r\n\t\twhile(p_child)\r\n\t\t{\r\n\t\t\t// virtual dimensions, 'k' in the direction that menu items are added (i.e. of 'z')\r\n\t\t\tfloat scaled_j;\r\n\t\t\t\t\t\r\n\t\t\tif (m_is_vertical_menu)\r\n\t\t\t\tscaled_j = p_child->GetBaseW() * p_child->GetScaleX();\r\n\t\t\telse\r\n\t\t\t\tscaled_j = p_child->GetBaseH() * p_child->GetScaleY();\r\n\t\t\t\r\n\t\t\tz += m_regular_space_val;\r\n\t\t\t\r\n\t\t\tif (scaled_j > biggest)\r\n\t\t\t\tbiggest = scaled_j;\r\n\t\t\t\r\n\t\t\tp_child = p_child->GetNextSibling();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// do first pass to find out biggest element, total height of all elements\r\n\t\tCScreenElementPtr p_child = mp_child_list;\r\n\t\twhile(p_child)\r\n\t\t{\r\n\t\t\t// virtual dimensions, 'k' in the direction that menu items are added (i.e. of 'z')\r\n\t\t\tfloat scaled_j, scaled_k;\r\n\t\t\t\t\t\r\n\t\t\tif (m_is_vertical_menu)\r\n\t\t\t{\r\n\t\t\t\tscaled_j = p_child->GetBaseW() * m_padding_scale;\r\n\t\t\t\tscaled_k = p_child->GetBaseH() * m_padding_scale;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tscaled_j = p_child->GetBaseH() * m_padding_scale;\r\n\t\t\t\tscaled_k = p_child->GetBaseW() * m_padding_scale;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tz += scaled_k + m_spacing_between;\r\n\t\t\t\r\n\t\t\tif (scaled_j > biggest)\r\n\t\t\t\tbiggest = scaled_j;\r\n\t\t\t\r\n\t\t\tp_child = p_child->GetNextSibling();\r\n\t\t} \r\n\t\tz -= m_spacing_between;\r\n\t}\r\n\t\t\r\n\tif ((m_object_flags & vFORCED_DIMS)) \r\n\t{\r\n\t\t// \"grow\" the menu in case of overflow (disobeying rule of above flag)\r\n\t\tif (m_is_vertical_menu && z > m_base_h) \r\n\t\t\tm_base_h = z;\r\n\t\telse if (!m_is_vertical_menu && z > m_base_w) \r\n\t\t\tm_base_w = z;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// this element is in control of own dimensions\r\n\t\tif (m_is_vertical_menu)\r\n\t\t{\r\n\t\t\tm_base_w = biggest;\r\n\t\t\tm_base_h = z;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_base_w = z;\r\n\t\t\tm_base_h = biggest;\r\n\t\t}\r\n\t}\r\n\tcompute_ul_pos(m_target_local_props);\r\n\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t\r\n\t\t\r\n\t// use vertical\tjustification to figure out starting position\r\n\tif (m_is_vertical_menu)\r\n\t\tz = (m_internal_just_y + 1.0f) * (m_base_h - z) / 2.0f;\r\n\telse\r\n\t\tz = (m_internal_just_x + 1.0f) * (m_base_w - z) / 2.0f;\r\n\t\t\t\r\n\tif (use_regular_space)\r\n\t{\r\n\t\tz += m_regular_space_val / 2.0f;\r\n\t\t\r\n\t\t// now, set positions of everything\r\n\t\tCScreenElementPtr p_child = mp_child_list;\r\n\t\twhile(p_child)\r\n\t\t{\r\n\t\t\tif (m_is_vertical_menu)\r\n\t\t\t{\r\n\t\t\t\tp_child->SetJust(m_internal_just_x, 0.0f);\r\n\t\t\t\tp_child->SetPos((m_internal_just_x + 1.0f) * m_base_w / 2.0f, z, FORCE_INSTANT);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_child->SetJust(0.0f, m_internal_just_y);\r\n\t\t\t\tp_child->SetPos(z, (m_internal_just_y + 1.0f) * m_base_h / 2.0f, FORCE_INSTANT);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tz += m_regular_space_val;\r\n\t\t\tp_child = p_child->GetNextSibling();\r\n\t\t}\r\n\t}\r\n\telse // if !use_regular_space\r\n\t{\r\n\t\t// now, set positions of everything\r\n\t\tCScreenElementPtr p_child = mp_child_list;\r\n\t\twhile(p_child)\r\n\t\t{\r\n\t\t\tif (m_is_vertical_menu)\r\n\t\t\t{\r\n\t\t\t\tfloat inc_value = p_child->GetBaseH() * m_padding_scale / 2.0f;\r\n\t\t\t\tz += inc_value;\r\n\t\t\t\t\r\n\t\t\t\tp_child->SetJust(m_internal_just_x, 0.0f);\r\n\t\t\t\tp_child->SetPos((m_internal_just_x + 1.0f) * m_base_w / 2.0f, z, FORCE_INSTANT);\r\n\t\t\t\t\r\n\t\t\t\tz += inc_value;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfloat inc_value = p_child->GetBaseW() * m_padding_scale / 2.0f;\r\n\t\t\t\tz += inc_value;\r\n\t\t\t\t\r\n\t\t\t\tp_child->SetJust(0.0f, m_internal_just_y);\r\n\t\t\t\tp_child->SetPos(z, (m_internal_just_y + 1.0f) * m_base_h / 2.0f, FORCE_INSTANT);\r\n\t\t\t\t\r\n\t\t\t\tz += inc_value;\r\n\t\t\t}\r\n\t\t\tz += m_spacing_between;\r\n\t\t\t\r\n\t\t\tif (p_child->GetFlags() & vNEEDS_LOCAL_POS_CALC)\r\n\t\t\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t\t\t\r\n\t\t\tp_child = p_child->GetNextSibling();\r\n\t\t}\r\n\t}\r\n    \r\n\tif (!m_selected_id && mp_child_list && m_in_focus) \r\n    {\r\n        m_selected_index = 0;\r\n        find_focusable_item(1, true, true);\r\n\r\n        if (m_selected_id)\r\n\t\t{\r\n\t\t\tScript::CStruct data;\r\n\t\t\tdata.AddInteger(\"controller\", m_focus_controller);\r\n\t\t\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\t\t\tp_tracker->LaunchEvent(Obj::CEvent::TYPE_FOCUS, m_selected_id, Obj::CEvent::vSYSTEM_EVENT, &data);\r\n\t\t}\r\n    }\r\n}\r\n\r\n\r\n\r\n\r\nCVMenu::CVMenu()\r\n{\r\n\tm_is_vertical_menu = true;\r\n\tSetType(CScreenElement::TYPE_VMENU);\r\n}\r\n\r\n\r\n\r\n\r\nCVMenu::~CVMenu()\r\n{\r\n}\r\n\r\n\r\n\r\n\r\nCHMenu::CHMenu()\r\n{\r\n\tm_is_vertical_menu = false;\r\n\t\r\n\tSetType(CScreenElement::TYPE_HMENU);\r\n}\r\n\r\n\r\n\r\n\r\nCHMenu::~CHMenu()\r\n{\r\n}\r\n\r\n\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gfx/2D/Menu2.h",
    "content": "#ifndef __GFX_2D_MENU_H__\r\n#define __GFX_2D_MENU_H__\r\n\r\n#include <gfx/2D/ScreenElement2.h>\r\n\r\nnamespace Front\r\n{\r\n\r\n/*\r\n\tA base menu is an.\r\n*/\r\nclass CBaseMenu : public Front::CScreenElement\r\n{\r\n\tfriend class CVScrollingMenu;\r\n\r\npublic:\r\n\r\n\t\t\t\t\t\t\tCBaseMenu();\r\n\tvirtual\t\t\t\t\t~CBaseMenu();\r\n\r\n\tvoid\t\t\t\t\tSetInternalJust(float h, float v) {m_internal_just_x = h; m_internal_just_y = v;}\t\r\n\t\r\n\tvirtual void\t\t\tSetProperties(Script::CStruct *pProps);\r\n\tvirtual bool\t\t\tPassTargetedEvent(Obj::CEvent *pEvent, bool broadcast = false);\r\n\r\n\tint\t\t\t\t\t\tGetSelectedIndex() { return m_selected_index; }\r\n\r\n\tbool\t\t\t\t\tUsingRegularSpacing(float &rRegularSpaceAmount);\r\n\r\nprotected:\r\n\r\n\tvoid\t\t\t\t\tfind_focusable_item(int dir, bool include_current, bool updateGridIndex);\r\n\tvoid\t\t\t\t\tchange_selection(int dir);\r\n\tvoid\t\t\t\t\tsetup_tags();\r\n\tvoid\t\t\t\t\treposition();\r\n\r\n\t// both m_selected_index and m_selected_id will have matching, valid settings,\r\n\t// or both will be invalid (-1, 0)\r\n\tint                     m_selected_index;\r\n    uint32                  m_selected_id;\r\n\tbool\t\t\t\t\tm_in_focus;\r\n\tint\t\t\t\t\t\tm_focus_controller; // 0 or 1\r\n\r\n\tfloat\t\t\t\t\tm_internal_just_x, m_internal_just_y;\r\n\tbool \t\t\t\t\tm_is_vertical_menu;\r\n\r\n\tfloat\t\t\t\t\tm_regular_space_val;\r\n\tfloat\t\t\t\t\tm_padding_scale;\r\n\tfloat\t\t\t\t\tm_spacing_between;\r\n\r\n\tbool\t\t\t\t\tm_pad_handling_enabled;\r\n\tbool\t\t\t\t\tm_allow_wrap;\r\n\r\n\tint\t\t\t\t\t\tm_current_grid_index; // of selected item, set to -1 when not applicable\r\n\t\t\t\t\t\t\t\t\t\t\t\t  // not necessarily the same as the grid index stored\r\n\t\t\t\t\t\t\t\t\t\t\t\t  // in the child that's selected (for \"remembering\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t  // the column)\r\n};\r\n\r\n\r\n\r\n\r\nclass CVMenu : public CBaseMenu\r\n{\r\npublic:\r\n\r\n\t\t\t\t\t\t\tCVMenu();\r\n\tvirtual\t\t\t\t\t~CVMenu();\r\n};\r\n\r\n\r\n\r\n\r\nclass CHMenu : public CBaseMenu\r\n{\r\npublic:\r\n\r\n\t\t\t\t\t\t\tCHMenu();\r\n\tvirtual\t\t\t\t\t~CHMenu();\r\n};\r\n\r\n\r\n\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/2D/ScreenElemMan.cpp",
    "content": "#include <core/defines.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/Event.h>\r\n#include <gel/Scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gfx/2D/ScreenElemMan.h>\r\n#include <gfx/2D/TextElement.h>\r\n#include <gfx/2D/SpriteElement.h>\r\n#include <gfx/2D/Element3d.h>\r\n                                          \r\n#include <gfx/2D/Window.h>\r\n#include <gfx/2D/Menu2.h>\r\n#include <gfx/2D/ScrollingMenu.h>\r\n#include <gfx/camera.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n// start autoduck documentation\r\n// @DOC ScreenElemMan\r\n// @module ScreenElemMan | None\r\n// @subindex Scripting Database\r\n// @index script | ScreenElemMan\r\n\r\nnamespace Front\r\n{\r\n\r\n\r\n\t\r\nDefineSingletonClass(CScreenElementManager, \"Screen Element Manager\");\r\n\r\n\r\n\r\n\r\nCScreenElementManager::CScreenElementManager()\r\n{\r\n\tmp_root_element = NULL;\r\n\tmp_resolve_temp = NULL;\r\n\r\n\t// register event listener\r\n\tRegisterWithTracker(NULL);\r\n\r\n\tfor (int i = 0; i < NUM_FOCUS_LISTS; i++)\r\n\t{\r\n\t\tmp_focus_list[i] = NULL;\r\n\t\tm_focus_list_changed[i] = false;\r\n\t}\r\n\tfor (int i = 0; i < NUM_FOCUS_NODES; i++)\r\n\t{\r\n\t\tm_focus_node_pool[i].mpElement = NULL;\r\n\t\tm_focus_node_pool[i].mpNextNode = NULL;\r\n\t}\r\n\r\n\tm_num_pad_event_types = 0;\r\n\tfor (int i = 0; i < MAX_PAD_EVENT_TYPES; i++)\r\n\t\tm_pad_event_type_tab[i] = 0;\r\n}\r\n\r\n\r\n\r\n\r\nCScreenElementManager::~CScreenElementManager()\r\n{\r\n\tDbg_MsgAssert(!m_object_list.CountItems(), (\"items still in CScreenElementManager\"));\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tSet 'id' to Obj::CBaseManager::vNO_OBJECT_ID if object to receive automatic ID\r\n*/\r\nCScreenElementPtr CScreenElementManager::CreateElement(uint32 type, uint32 id, Script::CScriptStructure *pProps)\r\n{\r\n\tCScreenElementPtr p_new_element = NULL;\r\n\t\r\n\tuint32 heap_crc;\r\n\tint heap_num = 0;\r\n\tbool switched = false;\r\n\tif (pProps->GetChecksum(\"heap\", &heap_crc))\r\n\t{\r\n\t\tswitch ( heap_crc )\r\n\t\t{\r\n\t\t\tcase 0x477fc6de:\t\t// topdown\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\t\tswitched = true;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0xc80bf12d:\t\t// bottomup \r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t\t\t\tswitched = true;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0xe37e78c5:\t\t// script\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\t\t\t\tswitched = true;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x9f7b7843:\t\t// network\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\t\t\t\tswitched = true;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x03c84a59:\t\t// profiler\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ProfilerHeap());\r\n\t\t\t\tswitched = true;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x935ab858:\t\t// debug\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t\t\t\tswitched = true;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x5b8ab877:\t\t// skater\r\n\t\t\t\tpProps->GetInteger(\"heapnum\", &heap_num);\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterHeap(heap_num));\r\n\t\t\t\tswitched = true;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0xeabd217b:\t\t// skaterinfo\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\t\t\t\tswitched = true;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x39fb63cc:\t\t// skatergeom\r\n\t\t\t\tpProps->GetInteger(\"heapnum\", &heap_num);\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterGeomHeap(heap_num));\r\n\t\t\t\tswitched = true;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0xe3f81b18:\t\t// internettopdown\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\t\t\t\tswitched = true;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0xbaa81175:\t\t// internetbottomup\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\t\t\t\tswitched = true;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x1ca1ff20:\t\t// default (ie don't change context).\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\t// Default = frontend\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\t\t\tswitched = true;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\tswitched = true;\r\n\t}\r\n\r\n\tswitch(type)\r\n\t{\r\n\t\tcase CScreenElement::TYPE_CONTAINER_ELEMENT:\r\n\t\t\tp_new_element = new CContainerElement();\r\n\t\t\tbreak;\r\n\t\tcase CScreenElement::TYPE_TEXT_ELEMENT:\r\n\t\t\tp_new_element = new CTextElement();\r\n\t\t\tbreak;\r\n\t\tcase CScreenElement::TYPE_VMENU:\r\n  \t\t\tp_new_element = new CVMenu();\r\n\t\t\tbreak;\r\n\t\tcase CScreenElement::TYPE_HMENU:\r\n  \t\t\tp_new_element = new CHMenu();\r\n\t\t\tbreak;\r\n\t\tcase CScreenElement::TYPE_TEXT_BLOCK_ELEMENT:\r\n  \t\t\tp_new_element = new CTextBlockElement();\r\n\t\t\tbreak;\r\n\t\tcase CScreenElement::TYPE_SPRITE_ELEMENT:\r\n  \t\t\tp_new_element = new CSpriteElement();\r\n\t\t\tbreak;\r\n\t\tcase CScreenElement::TYPE_VSCROLLING_MENU:\r\n  \t\t\tp_new_element = new CVScrollingMenu();\r\n\t\t\tbreak;\r\n\t\tcase CScreenElement::TYPE_HSCROLLING_MENU:\r\n  \t\t\tp_new_element = new CHScrollingMenu();\r\n\t\t\tbreak;\r\n\t\tcase CScreenElement::TYPE_ELEMENT_3D:\r\n\t\t\tp_new_element = new CElement3d();\r\n\t\t\tbreak;\r\n\t\tcase CScreenElement::TYPE_WINDOW_ELEMENT:\r\n\t\t\tp_new_element = new CWindowElement();\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0, (\"unknown element type 0x%x\", type));\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tp_new_element->SetID(id);\r\n\tRegisterObject(*p_new_element);\r\n\t\r\n\tp_new_element->SetProperties(pProps);\r\n\tp_new_element->SetMorph(pProps);\r\n\t\r\n\tif ( switched ) Mem::Manager::sHandle().PopContext();\r\n\t\r\n\t\r\n\treturn p_new_element;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CScreenElementManager::DestroyElement(uint32 id, ERecurse recurse, EPreserveParent preserveParent, Script::CScript *pCallingScript)\r\n{\r\n\r\n\t\r\n\tCScreenElementPtr p_element = GetElement(id, CScreenElementManager::ASSERT);\r\n\tDbg_Assert(p_element);\r\n\tif (recurse)\r\n\t{\r\n\t\tmark_element_out_of_focus(p_element);\r\n\t\tif (p_element->mp_parent)\r\n\t\t\tp_element->mp_parent->SetChildLockState(CScreenElement::UNLOCK);\r\n\t\tdestroy_element_recursive(preserveParent, p_element, pCallingScript);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmark_element_out_of_focus(p_element);\r\n\t\tif (pCallingScript && p_element)\r\n\t\t\t// must disassociate script from element being destroyed\r\n\t\t\tpCallingScript->DisassociateWithObject(p_element);\r\n\t\t\r\n\t\tUnregisterObject(*p_element);\r\n\t\t#ifdef\t__NOPT_ASSERT__\t\r\n\t\t// Mick:  screen elements are deleted directly, so LockAssert is not applicable.\r\n\t\tp_element->SetLockAssertOff();\r\n\t\t#endif\r\n\t\tp_element.Kill();\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tPassing in pParent = NULL will give the child no parent\r\n*/\r\nvoid CScreenElementManager::SetParent(const CScreenElementPtr &pParent, const CScreenElementPtr &pChild, CScreenElement::EPosRecalc recalculatePosition)\r\n{\r\n\tDbg_Assert(pChild);\r\n\r\n\tCScreenElementPtr p_current_parent = pChild->mp_parent;\r\n\tif (p_current_parent)\t\r\n\t\tDbg_MsgAssert(!(p_current_parent->m_object_flags & CScreenElement::vCHILD_LOCK), (\"can't remove child -- locked\"));\r\n\t\r\n\t// if child was root element, then seek out\ta new root\r\n\tif (pParent && (mp_root_element == pChild || !mp_root_element))\r\n\t{\r\n\t\tmp_root_element = pParent;\r\n\t\twhile(mp_root_element->mp_parent)\r\n\t\t\tmp_root_element = mp_root_element->mp_parent;\r\n\t}\r\n\r\n\tmark_element_out_of_focus(pChild);\r\n\t\r\n\tpChild->set_parent(pParent, recalculatePosition);\r\n}\r\n\r\n\r\n\r\n\r\nCScreenElementPtr CScreenElementManager::GetElement(uint32 id, EAssert assert)\r\n{\r\n\tDbg_MsgAssert(id > 0, (\"can't use 0 as an ID\"));\r\n\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\tObj::CObject *p_object = p_tracker->GetObject(id);\r\n\tif (assert)\r\n\t\tDbg_MsgAssert(p_object, (\"couldn't find screen element %s\", Script::FindChecksumName(id)));\r\n\tif (p_object)\r\n\t{\r\n\t\tCScreenElementPtr p_element = static_cast<CScreenElement *>(p_object);\r\n\t\tDbg_MsgAssert(p_element, (\"%s not a screen element\", Script::FindChecksumName(id)));\r\n\t\treturn p_element;\r\n\t}\r\n\telse\r\n\t\treturn NULL;\r\n}\r\n\r\n\r\n\r\n\r\nCScreenElementPtr CScreenElementManager::GetElement(Script::CStruct *pStructContainingId, uint32 IdSubStructName, EAssert assert)\r\n{\r\n\tuint32 id = ResolveComplexID(pStructContainingId, IdSubStructName);\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif ( assert )\r\n\t{\r\n\t\tif ( !id )\r\n\t\t\tScript::PrintContents(pStructContainingId, 2);\r\n\t\tDbg_MsgAssert(id, (\"could not resolve ID %s\", Script::FindChecksumName(IdSubStructName)));\r\n\t}\r\n\t#endif\r\n\tif ( id )\r\n\t{\r\n\t\treturn GetElement(id, assert);\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\nCScreenElementPtr CScreenElementManager::GetElement(Script::CStruct *pStructContainingId, char *pIdSubStructName, EAssert assert)\r\n{\r\n\treturn GetElement(pStructContainingId,Script::GenerateCRC(pIdSubStructName),ASSERT);\r\n}\r\n\r\n\r\n\r\n/*\r\n\tNo screen element can be destroyed during this phase\r\n*/\r\nvoid CScreenElementManager::Update()\r\n{\r\n\tif (mp_root_element)\r\n\t{\r\n\t\tset_tree_lock_state(CScreenElement::LOCK);\r\n\t\t\r\n\t\t//Ryan(\"in CScreenElementManager::Update(), timer is %d\\n\", Tmr::GetTime());\r\n\t\tmp_root_element->UpdateProperties();\r\n\t\t\r\n\t\tset_tree_lock_state(CScreenElement::UNLOCK);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CScreenElementManager::SetPausedState(bool pause)\r\n{\r\n\t// find a new parentless element to be root element\r\n\tLst::Node<Obj::CObject> *p_node = m_object_list.FirstItem();\r\n\twhile(p_node)\r\n\t{\r\n\t\tCScreenElementPtr p_element = static_cast<CScreenElement *>(p_node->GetData());\r\n\t\tDbg_Assert(p_element);\r\n\t\tp_element->SetMorphPausedState(pause);\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n// locks/unlocks all the screen elements in the tree so they can't/can be deleted without an assert\r\nvoid CScreenElementManager::set_tree_lock_state(CScreenElement::ELockState state)\r\n{\r\n\tif (mp_root_element)\r\n\t{\r\n\t\tCScreenElement* p_stack[32];\r\n\t\tp_stack[0] = mp_root_element;\r\n\t\tint depth = 1;\r\n\t\t\r\n\t\twhile(depth)\r\n\t\t{\r\n\t\t\t// pop top value off stack\r\n\t\t\tCScreenElement* p_node = p_stack[--depth];\r\n\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tp_node->debug_verify_integrity();\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\t// set its lock state\r\n\t\t\tif (state == CScreenElement::LOCK)\r\n\t\t\t\tp_node->AddReference();\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// this\telement may have been ADDED since the call to set_tree_lock_state(LOCK),\r\n\t\t\t\t// so we can't depend on it being referenced\r\n\t\t\t\tif (p_node->IsReferenced())\r\n\t\t\t\t\tp_node->RemoveReference();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tDbg_Assert(depth <= 30);\r\n\t\t\t\r\n\t\t\t// put sibling and child on stack\r\n\t\t\tif (p_node->GetNextSibling())\r\n\t\t\t\tp_stack[depth++] = p_node->GetNextSibling();\r\n\t\t\tif (p_node->GetFirstChild())\r\n\t\t\t\tp_stack[depth++] = p_node->GetFirstChild();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n// Optimization - as event handling become more widespread\r\n// this should only be called on the type of events that \r\n// it actually handles, which is basically the pad_event_types\r\n\r\nvoid CScreenElementManager::pass_event_to_listener(Obj::CEvent *pEvent)\r\n{\r\n\t// Fill in the array of pad event types by copying it from the global \"pad_event_types\" script array\r\n\tif (!m_num_pad_event_types)\r\n\t{\r\n\t\tScript::CArray *p_event_type_array = Script::GetArray(\"pad_event_types\", Script::ASSERT);\r\n\t\tm_num_pad_event_types = p_event_type_array->GetSize();\r\n\t\tDbg_MsgAssert(m_num_pad_event_types <= MAX_PAD_EVENT_TYPES, (\"increase size of MAX_PAD_EVENT_TYPES\"));\r\n\t\tfor (int i = 0; i < m_num_pad_event_types; i++)\r\n\t\t{\r\n\t\t\tm_pad_event_type_tab[i] = p_event_type_array->GetChecksum(i);\r\n\t\t}\r\n\t}\r\n\r\n\t// check that the controller is bound to a skater\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tif ( !skate_mod->IsMultiplayerGame() )\r\n\t{\r\n\t\tif ( skate_mod->m_requested_level != CRCD( 0x9f2bafb7, \"load_skateshop\" ) )\r\n\t\t{\r\n\t\t\tCScreenElementPtr p_element = GetElement( CRCD(0x21f1f4a,\"startup_menu\"), CScreenElementManager::DONT_ASSERT);\r\n\t\t\tif ( !p_element )\r\n\t\t\t{\r\n\t\t\t\tint device_num;\r\n\t\t\t\tScript::CStruct* pEventData = pEvent->GetData();\r\n\t\t\t\tif ( pEventData && pEventData->GetInteger( CRCD(0xc9428a08,\"device_num\"), &device_num, Script::NO_ASSERT ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( skate_mod->m_device_server_map[0] != device_num )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// this controller isn't bound to the skater!\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\t\t\r\n\tif (pEvent->GetType() == Obj::CEvent::TYPE_FOCUS) \r\n\t{\r\n\t\tuint32 focus_id = pEvent->GetTarget();\r\n\t\t// HACK: this assert should be there, but was removed to force a last-minute fix\r\n\t\t//Dbg_MsgAssert(focus_id != Obj::CEvent::vSYSTEM_EVENT, (\"focus event needs specific target\"));\r\n\t\tif (focus_id != Obj::CEvent::vSYSTEM_EVENT)\r\n\t\t{\t\t\r\n\t\t\tCScreenElementPtr p_focus_element = GetElement(focus_id);\r\n\t\t\t// HACK: see above\r\n\t\t\t//Dbg_MsgAssert(p_focus_element, (\"focus screen element doesn't exist\"));\r\n\t\t\tif ( p_focus_element && !p_focus_element->EventsBlocked() )\r\n\t\t\t{\r\n\t\t\t\tint controller = Obj::CEvent::sExtractControllerIndex(pEvent);\r\n\t\t\r\n\t\t\t\tmark_element_in_focus(p_focus_element, controller);\r\n\t\t\t\t\r\n\t\t\t\tpEvent->MarkRead(Obj::CTracker::vID_SCREEN_ELEMENT_MANAGER);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (pEvent->GetType() == Obj::CEvent::TYPE_UNFOCUS)\r\n\t{\r\n\t\tuint32 unfocus_id = pEvent->GetTarget();\r\n\t\t// HACK: this assert should be there, but was removed to force a last-minute fix\r\n\t\t//Dbg_MsgAssert(unfocus_id != Obj::CEvent::vSYSTEM_EVENT, (\"unfocus event needs specific target\"));\r\n\t\tif (unfocus_id != Obj::CEvent::vSYSTEM_EVENT)\r\n\t\t{\t\t\r\n\t\t\tCScreenElementPtr p_unfocus_element = GetElement(unfocus_id);\r\n\t\t\t// HACK: see above\r\n\t\t\t//Dbg_MsgAssert(p_unfocus_element, (\"unfocus screen element %s doesn't exist\", Script::FindChecksumName(unfocus_id)));\r\n\t\t\tif ( p_unfocus_element && !p_unfocus_element->EventsBlocked() )\r\n\t\t\t{\r\n\t\t\t\tmark_element_out_of_focus(p_unfocus_element);\r\n\t\t\t\t\r\n\t\t\t\tpEvent->MarkRead(Obj::CTracker::vID_SCREEN_ELEMENT_MANAGER);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (pEvent->GetType() == Obj::CEvent::TYPE_NOTIFY_CHILD_UNLOCK)\r\n\t{\r\n\t\tuint32 unlock_id = pEvent->GetTarget();\r\n\t\tCScreenElementPtr p_unlocked_element = GetElement(unlock_id);\r\n\t\tDbg_MsgAssert(p_unlocked_element, (\"unlock screen element %s doesn't exist\", Script::FindChecksumName(unlock_id)));\r\n\t\t\r\n\t\t// mark all descendants TEMPORARILY out of focus\r\n\t\tmark_element_out_of_focus(p_unlocked_element, true, true);\r\n\t\t\r\n\t\tpEvent->MarkRead(Obj::CTracker::vID_SCREEN_ELEMENT_MANAGER);\r\n\t}\r\n\tif (pEvent->GetType() == Obj::CEvent::TYPE_NOTIFY_CHILD_LOCK)\r\n\t{\r\n\t\tuint32 lock_id = pEvent->GetTarget();\r\n\t\tCScreenElementPtr p_last_focus_element = GetElement(lock_id);\r\n\t\tDbg_MsgAssert(p_last_focus_element, (\"unlock screen element %s doesn't exist\", Script::FindChecksumName(lock_id)));\r\n\t\t\r\n\t\t// restore children of this element to focus\r\n\t\tremark_temporarily_out_of_focus_elements(p_last_focus_element);\r\n\t\t\r\n\t\tpEvent->MarkRead(Obj::CTracker::vID_SCREEN_ELEMENT_MANAGER);\r\n\t}\r\n\tif (is_pad_event(pEvent->GetType()) &&\r\n\t\tpEvent->GetTarget() == Obj::CEvent::vSYSTEM_EVENT) \r\n\t{\r\n\t\tbool successful_handling = false;\r\n\t\t\r\n\t\tint controller = Obj::CEvent::sExtractControllerIndex(pEvent);\r\n\t\t\r\n\t\t// forward pad events (of global type) to elements in focus \t\t\r\n\t\tFocusNode *p_node = mp_focus_list[controller];\r\n\t\twhile(p_node)\r\n\t\t{\r\n\t\t\tp_node->mProcessed = false;\r\n\t\t\tp_node = p_node->mpNextNode;\r\n\t\t}\r\n\t\t  \r\n\t\tm_focus_list_changed[controller] = true;\r\n\t\twhile(m_focus_list_changed[controller])\r\n\t\t{\r\n\t\t\tm_focus_list_changed[controller] = false;\r\n\t\t\tp_node = mp_focus_list[controller];\r\n\t\t\twhile(p_node)\r\n\t\t\t{\r\n\t\t\t\ttest_focus_node(p_node);\r\n\t\t\t\t\r\n\t\t\t\tif ( !p_node->mProcessed && !p_node->mTempOutOfFocus && !p_node->mpElement->EventsBlocked() )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(p_node->mpElement,(\"Node in focus list has NULL mpElement, entry = %d\", (int) (p_node - m_focus_node_pool)));\r\n\t\t\t\t\t//Ryan(\"   sending pad event %d to %s\\n\", controller, Script::FindChecksumName(p_node->mpElement->GetID()));\r\n\t\t\t\t\tif (p_tracker->LaunchEvent(pEvent->GetType(), p_node->mpElement->GetID(), pEvent->GetSource(), pEvent->GetData()))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsuccessful_handling = true;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tp_node->mProcessed = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// the event just sent may have led to the clearing of this\tnode (and maybe others) -- if \r\n\t\t\t\t// that happens, start again\r\n\t\t\t\tif (m_focus_list_changed[controller])\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\r\n\t\t\t\tp_node = p_node->mpNextNode;\r\n\t\t\t} // end while\r\n\t\t\t\r\n\t\t\tif (successful_handling)\r\n\t\t\t\tbreak;\r\n\t\t} // end while\r\n\t\t\r\n\t\tif (successful_handling)\r\n\t\t\tpEvent->MarkHandled(Obj::CTracker::vID_SCREEN_ELEMENT_MANAGER);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nbool CScreenElementManager::IsComplexID(Script::CStruct *pStructContainingId, char *pIdSubStructName)\r\n{\r\n\tScript::CStruct *p_recurse_struct = NULL;\t\r\n\treturn pStructContainingId->GetStructure(pIdSubStructName, &p_recurse_struct);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tThis function takes a complex ID and reduces it to a regular checksum that designates a single screen\r\n\telement. The following are examples of complex ID's:\r\n\t\r\n\tid=blah1\t\t\t\t\t\t<-- also a regular ID\r\n\tid={blah1 child=0}\t\t\t\t<-- first child of blah1\r\n\tid=<blah1 child={0 child=2}}\t<-- third child of first child of blah1\r\n\t\r\n\tid={blah1 child=local_blah}\t\t<-- returns child of blah1 with *LOCAL* ID local_blah\r\n\t\t\t\t\t\t\t\t\t    (can be recursed as above, or mixed and matched with indices)\r\n\t\r\n\tTO BE SUPPORTED IN FUTURE:\r\n\t\r\n\tid={blah1 parent=0}\t\t\t\t<-- parent of blah1\r\n\tid={blah1 parent=1}\t\t\t\t<-- grandparent of blah1\r\n\t\r\n\tid={blah1 child=all_children}\t<-- all children of blah1\r\n\t\r\n\tReturns 0 if ID could not be resolved, or if nothing matches the name in pIdSubStructName\r\n*/\r\nuint32 CScreenElementManager::ResolveComplexID(Script::CStruct *pStructContainingId, uint32 IdSubStructName)\r\n{\r\n\t// mp_resolve_temp will be NULL when we enter this function at the beginning of a recursion chain,\r\n\t// non-NULL when inside the chain. In the latter case, it points to the element closest to \r\n\t// desired one (so far)\r\n\r\n\tScript::CStruct *p_recurse_struct = NULL;\t\r\n\tuint32 id = 0;\r\n\tint index = -1;\r\n\tif (pStructContainingId->GetStructure(IdSubStructName, &p_recurse_struct))\r\n\t{\r\n\t\t// Expecting the form something={...}\r\n\t\t// May be recursively inside some other ID structure\r\n\t\t\r\n\t\t// grab the 'x' part of structure, where x is something={id ...}\r\n\t\t\r\n\t\t// grab the ID part of something={id ...}\r\n\t\t// we expect either this or a child index (see below)\r\n\t\t// \r\n\t\tuint32 contained_id = 0;\r\n\t\tp_recurse_struct->GetChecksum(NONAME, &contained_id);\r\n\r\n\t\t// grab\tthe child index part of something={child_index ...}\r\n\t\tint child_index = -1;\r\n\t\tp_recurse_struct->GetInteger(NONAME, &child_index);\r\n\t\t\r\n\t\tif (contained_id != 0)\r\n\t\t{\r\n\t\t\tif (!mp_resolve_temp)\r\n\t\t\t\t// we're at the top level of the recursion chain\r\n\t\t\t\tmp_resolve_temp = GetElement(contained_id);\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// we're NOT at the top level of the recursion chain, so treat ID as\r\n\t\t\t\t// a LOCAL id\r\n\t\t\t\tmp_resolve_temp = get_element_by_local_id(mp_resolve_temp, contained_id);\r\n\t\t\t}\r\n\t\t\tif (!mp_resolve_temp)\r\n\t\t\t\treturn 0;\r\n\t\t}\r\n\t\telse if (child_index != -1) \r\n\t\t{\r\n\t\t\tDbg_MsgAssert(mp_resolve_temp, (\"can't map child %d of %s to anything, no parent\", child_index, Script::FindChecksumName(IdSubStructName)));\r\n\t\t\tmp_resolve_temp = mp_resolve_temp->GetChildByIndex(child_index);\r\n\t\t\tif (!mp_resolve_temp)\r\n\t\t\t\treturn 0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tScript::PrintContents(pStructContainingId);\r\n\t\t\tDbg_MsgAssert(0, (\"can't resolve complex ID %s, no ID or index given.  See struct above.\", Script::FindChecksumName(IdSubStructName)));\r\n\t\t\t#endif\r\n\t\t}\r\n\t\t// we can expect to recurse further\r\n\t\tuint32 result_id = ResolveComplexID(p_recurse_struct, CRCD(0xdd4cabd6,\"child\"));\r\n\t\tmp_resolve_temp = NULL;\r\n\r\n\t\treturn result_id;\r\n\t}\r\n\telse if (pStructContainingId->GetChecksum(IdSubStructName, &id))\r\n\t{\r\n\t\t// Expecting the form something=some_checksum\r\n\t\t// May be recursively inside some other ID structure\r\n\t\t\r\n\t\tif (mp_resolve_temp)\r\n\t\t{\r\n\t\t\t// we're NOT at the top level of the recursion chain, so treat ID as\r\n\t\t\t// a LOCAL id\r\n\t\t\tmp_resolve_temp = get_element_by_local_id(mp_resolve_temp, id);\r\n\t\t\tid = mp_resolve_temp->GetID();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// see if ID is really an alias\r\n\t\t\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\t\t\tObj::CObject *p_aliased_obj = p_tracker->GetObjectByAlias(id);\r\n\t\t\tif (p_aliased_obj)\r\n\t\t\t\t// get real ID\r\n\t\t\t\tid = p_aliased_obj->GetID();\r\n\t\t}\r\n\t\t\r\n\t\tmp_resolve_temp = NULL;\r\n\t\treturn id;\r\n\t}\r\n\telse if (pStructContainingId->GetInteger(IdSubStructName, &index))\r\n\t{\r\n\t\t// Expecting the form something=child_index\r\n\t\t// May be recursively inside some other ID structure\r\n\t\t\r\n\t\tDbg_MsgAssert(mp_resolve_temp, (\"can't map child %d to anything, no parent\", index));\r\n\t\tCScreenElementPtr p_child = mp_resolve_temp->GetChildByIndex(index);\r\n\t\tmp_resolve_temp = NULL;\r\n\t\tif (p_child) \t\t\r\n\t\t\treturn p_child->GetID();\r\n\t\telse\r\n\t\t\treturn 0;\r\n\t}\r\n\t\r\n\tmp_resolve_temp = NULL;\r\n\treturn 0;\t\r\n}\r\n\r\n\r\nuint32 CScreenElementManager::ResolveComplexID(Script::CStruct *pStructContainingId, char *pIdSubStructName)\r\n{\r\n\r\n\treturn ResolveComplexID(pStructContainingId, Script::GenerateCRC(pIdSubStructName));\t\r\n}\r\n\r\n\r\n\r\nvoid CScreenElementManager::RegisterObject ( Obj::CObject& obj )\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tCScreenElementPtr p_element = static_cast<CScreenElement *>(&obj);\r\n\tDbg_MsgAssert(p_element, (\"object registered with ScreenElement manager not ScreenElement\"));\r\n\t#endif\t\r\n\t\t\t\t\t\t   \r\n\tCBaseManager::RegisterObject(obj);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CScreenElementManager::UnregisterObject ( Obj::CObject& obj )\r\n{\r\n\tCScreenElementPtr p_unregister_element\t= static_cast<CScreenElement *>(&obj);\r\n\tDbg_Assert(p_unregister_element);\r\n\t\r\n\tDbg_MsgAssert(!p_unregister_element->mp_parent, (\"can't unregister screen element from manager -- still has parent\"));\r\n\tDbg_MsgAssert(!p_unregister_element->GetFirstChild(), (\"can't unregister screen element from manager -- still has children\"));\r\n\tDbg_MsgAssert(!p_unregister_element->GetNextSibling() && !p_unregister_element->GetPrevSibling(), \r\n\t\t\t\t  (\"can't unregister screen element from manager -- still has siblings\"));\r\n\t\r\n\t// see if unregister element is root element\r\n\tif (p_unregister_element && mp_root_element == p_unregister_element)\r\n\t{\r\n\t\tmp_root_element = NULL;\r\n\t\t\r\n\t\t// find a new parentless element to be root element\r\n\t\tLst::Node<Obj::CObject> *p_node = m_object_list.FirstItem();\r\n\t\twhile(p_node)\r\n\t\t{\r\n\t\t\tCScreenElementPtr p_element = static_cast<CScreenElement *>(p_node->GetData());\r\n\t\t\tDbg_Assert(p_element);\r\n\t\t\t// must have no parent, can't be element that we're unregistering\r\n\t\t\tif (!p_element->mp_parent && p_element != p_unregister_element)\r\n\t\t\t{\r\n\t\t\t\tmp_root_element = p_element;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tp_node = p_node->GetNext();\r\n\t\t}\r\n\t}\r\n\t\r\n\tCBaseManager::UnregisterObject(obj);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CScreenElementManager::KillObject ( Obj::CObject& obj )\r\n{\r\n\tDbg_MsgAssert(0, (\"this virtual function not supported\"));\r\n}\r\n\r\n\r\n\r\n\r\nLst::Head< Obj::CObject > &CScreenElementManager::GetRefObjectList()\r\n{\r\n\tDbg_MsgAssert(0, (\"this virtual function not supported\"));\r\n\treturn m_object_list;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CScreenElementManager::destroy_element_recursive(EPreserveParent preserve_parent, const CScreenElementPtr &pElement, Script::CScript *pCallingScript)\r\n{\r\n\tpElement->SetChildLockState(CScreenElement::UNLOCK);\r\n\t\r\n\tCScreenElementPtr p_child = pElement->GetFirstChild();\r\n\twhile(p_child)\r\n\t{\r\n\t\tCScreenElementPtr p_next = p_child->GetNextSibling();\r\n\t\tdestroy_element_recursive(DONT_PRESERVE_PARENT, p_child, pCallingScript);\r\n\t\tp_child = p_next;\r\n\t}\r\n\r\n\tif( !preserve_parent )\r\n\t{\r\n\t\tif (pCallingScript && pElement)\r\n\t\t\t// must disassociate script from element being destroyed\r\n\t\t\tpCallingScript->DisassociateWithObject(pElement);\r\n\t\t\t\r\n\t\tSetParent(NULL, pElement);\r\n\t\tUnregisterObject(*pElement);\r\n\t\t#ifdef\t__NOPT_ASSERT__\t\r\n\t\t// Mick:  screen elements are deleted directly, so LockAssert is not applicable.\r\n\t\tpElement->SetLockAssertOff();;\r\n\t\t#endif\r\n\t\tdelete pElement;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nCScreenElementPtr CScreenElementManager::get_element_by_local_id(const CScreenElementPtr &pParent, uint32 desiredLocalID)\r\n{\r\n\tuint32 crc_tag_local_id = CRCX(\"tag_local_id\");\r\n\r\n\tCScreenElementPtr p_child = pParent->GetFirstChild();\r\n\twhile(p_child)\r\n\t{\r\n\t\tuint32 local_id;\r\n\t\tif (p_child->GetChecksumTag(crc_tag_local_id, &local_id))\r\n\t\t{\r\n\t\t\tif (local_id == desiredLocalID)\r\n\t\t\t\treturn p_child;\r\n\t\t}\r\n\t\tp_child = p_child->GetNextSibling();\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CScreenElementManager::mark_element_in_focus(const CScreenElementPtr &pElement, int controller)\r\n{\r\n\tDbg_Assert(controller >= 0 && controller <= 1);\r\n\tDbg_Assert(pElement);\r\n\t\r\n\tFocusNode *p_prev_node = NULL;\r\n\t// If in the list for the same controller, then exit function.\r\n\t// If in the list for another controller, assert\r\n\tfor (int c = 0; c < NUM_FOCUS_LISTS; c++)\r\n\t{\r\n\t\tFocusNode *p_node = mp_focus_list[c];\r\n\t\twhile (p_node)\r\n\t\t{\r\n\t\t\ttest_focus_node(p_node);\r\n\t\t\tif (p_node->mpElement == pElement)\r\n\t\t\t{\r\n\t\t\t\tif (controller == c) \r\n\t\t\t\t{\r\n\t\t\t\t\t// already in focus, make sure in full focus\r\n\t\t\t\t\tp_node->mTempOutOfFocus = false;\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(0, (\"can't change existing focus to another controller\"));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tp_prev_node = p_node;\r\n\t\t\tp_node = p_node->mpNextNode;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Time to make a new focus node\r\n\t// p_prev_node will point to last element in list, or NULL if no list\r\n\t\r\n\tfor (int i = 0; i < NUM_FOCUS_NODES; i++)\r\n\t{\r\n\t\tif (!m_focus_node_pool[i].mpElement)\r\n\t\t{\r\n\t\t\t//Ryan(\"TTT element %s marked in focus, %d\\n\", Script::FindChecksumName(pElement->GetID()), (int) controller);\r\n\t\t\t\r\n\t\t\tm_focus_node_pool[i].mpElement = pElement;\r\n\t\t\tm_focus_node_pool[i].mId = pElement->GetID();\r\n\t\t\tm_focus_node_pool[i].mpNextNode = NULL;\r\n\t\t\tm_focus_node_pool[i].mTempOutOfFocus = false;\r\n\t\t\t// put in list -- at end of list\r\n\t\t\tif (p_prev_node)\r\n\t\t\t\tp_prev_node->mpNextNode = &m_focus_node_pool[i];\r\n\t\t\telse\r\n\t\t\t\tmp_focus_list[controller] = &m_focus_node_pool[i];\r\n\t\t\tm_focus_list_changed[controller] = true;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tDbg_Assert(0);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CScreenElementManager::mark_element_out_of_focus(const CScreenElementPtr &pElement, bool onlyChildren, bool tempOnly)\r\n{\r\n\tDbg_Assert(pElement);\r\n\t\r\n\tfor (int c = 0; c < NUM_FOCUS_LISTS; c++)\r\n\t{\r\n\t\t// remove from list all elements that are descendents of pElement, and possibly pElement itself\r\n\r\n\t\tFocusNode *p_prev_node = NULL;\r\n\t\tFocusNode *p_node = mp_focus_list[c];\r\n\t\twhile(p_node)\r\n\t\t{\r\n\t\t\ttest_focus_node(p_node);\r\n\t\t\tFocusNode *p_next_node = p_node->mpNextNode;\r\n\r\n\t\t\tbool am_descendent = false;\r\n\t\t\tCScreenElementPtr p_elem = p_node->mpElement;\r\n\t\t\tif (onlyChildren && p_elem)\r\n\t\t\t\tp_elem = p_elem->mp_parent;\r\n\t\t\twhile(p_elem)\r\n\t\t\t{\r\n\t\t\t\tif (p_elem == pElement)\r\n\t\t\t\t{\r\n\t\t\t\t\tam_descendent = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tp_elem = p_elem->mp_parent;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (am_descendent)\r\n\t\t\t{\r\n\t\t\t\tif (tempOnly)\r\n\t\t\t\t{\r\n\t\t\t\t\t// just mark temporarily out of focus\r\n\t\t\t\t\tp_node->mTempOutOfFocus = true;\r\n\t\t\t\t\t//Ryan(\"TTT element %s marked TEMPORARILY out of focus, %d\\n\", Script::FindChecksumName(p_node->mpElement->GetID()), c);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// found a match -- remove from list\r\n\t\t\t\t\tif (p_prev_node)\r\n\t\t\t\t\t\tp_prev_node->mpNextNode = p_next_node;\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tmp_focus_list[c] = p_next_node;\r\n\t\t\t\t\t//Ryan(\"TTT element %s marked OUT OF focus, %d\\n\", Script::FindChecksumName(p_node->mpElement->GetID()), (int) c);\r\n\t\t\t\t\t// remove from pool\r\n\t\t\t\t\tp_node->mpElement = NULL;\r\n\t\t\t\t\tm_focus_list_changed[c] = true;\r\n\r\n\t\t\t\t\tp_node = p_prev_node;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tp_prev_node = p_node;\r\n\t\t\tp_node = p_next_node;\r\n\t\t} // end while p_node\r\n\t} // end for c\r\n}\r\n\r\n\r\n\r\n\r\n// Elements temporarily marked out-of-focus are put back in focus. Only elements that are descendents \r\n// of pElement (or pElement) itself are restored.\r\nvoid CScreenElementManager::remark_temporarily_out_of_focus_elements(const CScreenElementPtr &pElement)\r\n{\r\n\tfor (int c = 0; c < NUM_FOCUS_LISTS; c++)\r\n\t{\r\n\t\tFocusNode *p_node = mp_focus_list[c];\r\n\t\twhile(p_node)\r\n\t\t{\r\n\t\t\tif (p_node->mTempOutOfFocus)\r\n\t\t\t{\t\t\t\t\r\n\t\t\t\t// element still exists, make sure it or its ancestor is pElement\r\n\t\t\t\ttest_focus_node(p_node);\r\n\t\t\t\tCScreenElementPtr p_element = p_node->mpElement;\r\n\t\t\t\twhile (p_element)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (p_element == pElement)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_node->mTempOutOfFocus = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tp_element = p_element->mp_parent;\r\n\t\t\t\t}\r\n\t\t\t}\t\t\t\r\n\t\t\t\r\n\t\t\tp_node = p_node->mpNextNode;\r\n\t\t}\r\n\t} // end for c\r\n}\r\n\r\n\r\n\r\n\r\nvoid CScreenElementManager::test_focus_node(FocusNode *pNode)\r\n{\r\n\t#ifdef __NOPT_ASSERT__\r\n\t// if this element was removed, its node should have been, too\r\n\tDbg_MsgAssert(pNode->mpElement, (\"this node entry shouldn't be in list\"));\r\n\tDbg_MsgAssert(GetElement(pNode->mId), (\"ID of node associated with non-existant element\")); \r\n\tDbg_MsgAssert(GetElement(pNode->mId) == pNode->mpElement, (\"ID of node associated with element other than one pointed to\"));\r\n\t#endif\r\n}\r\n\r\n\r\n\r\n\r\nbool CScreenElementManager::is_pad_event(uint32 eventType)\r\n{\r\n\tfor (int i = 0; i < m_num_pad_event_types; i++)\r\n\t{\r\n\t\tif (eventType == m_pad_event_type_tab[i])\r\n\t\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid CScreenElementManager::SetRootScreenElement( uint32 id )\r\n{\r\n\tCScreenElementPtr p_elem = GetElement( id, ASSERT );\r\n\tmp_root_element = p_elem;\r\n}\r\n\r\n\r\nbool ScriptCreateScreenElement(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 type;\r\n\tif (!pParams->GetChecksum(\"type\", &type))\r\n\t\tDbg_MsgAssert(0, (\"can't create screen element without type\"));\r\n\r\n\tuint32 id = Obj::CBaseManager::vNO_OBJECT_ID;    \r\n    pParams->GetChecksum(CRCD(0x40c698af,\"id\"), &id);\r\n\r\n    // get id of ScreenElement\r\n    CScreenElementManager* pManager = CScreenElementManager::Instance();\r\n    CScreenElementPtr p_Element = pManager->CreateElement(type, id, pParams);\r\n    id = p_Element->GetID();\r\n\r\n    // add id to params - will overwrite if id present\r\n    pScript->GetParams()->AddChecksum(CRCD(0x40c698af,\"id\"), id);\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptDestroyScreenElement(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tuint32 id = pManager->ResolveComplexID(pParams, CRCD(0x40c698af,\"id\"));\r\n\tDbg_MsgAssert(id, (\"\\n%s\\nelement not in manager\",pScript->GetScriptInfo()));\r\n\t\r\n\t// Let's always destroy recursively -- is there any reason not to?\r\n\tCScreenElementManager::ERecurse recurse = \r\n\t\tCScreenElementManager::ERecurse(!pParams->ContainsFlag(\"dont_recurse\"));\r\n\tCScreenElementManager::EPreserveParent preserve_parent = \r\n\t\tCScreenElementManager::EPreserveParent(pParams->ContainsFlag(\"preserve_parent\"));\r\n\t\r\n\t// This combination doesn't really make sense\r\n\t// Warn the user and do nothing since, in effect, it is an empty operation\r\n\tif( !recurse && preserve_parent )\r\n\t{\r\n\t\tDbg_Printf( \"Warning: Destroying an element without recursion and with preserve_parent makes no sense\\n\" );\r\n\t\treturn true;\r\n\t}\r\n\r\n\tpManager->DestroyElement(id, recurse, preserve_parent, pScript);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptRunScriptOnScreenElement(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_elem = pManager->GetElement(pParams, CRCD(0x40c698af,\"id\"), CScreenElementManager::ASSERT);\r\n\t\t\r\n\tuint32 script;\r\n\tpParams->GetChecksum(NONAME, &script, true);\r\n\t\r\n\tuint32 callback = 0;\r\n\tpParams->GetChecksum(CRCD(0x86068bd9,\"callback\"), &callback);\r\n    \r\n    Script::CStruct *p_ScriptParams = NULL;\r\n    pParams->GetStructure(CRCD(0x7031f10c,\"params\"), &p_ScriptParams);\r\n\r\n    Script::CStruct *p_CallbackParams = NULL;\r\n    pParams->GetStructure(CRCD(0xe6cf88c4,\"callback_params\"), &p_CallbackParams);\r\n\r\n\t// K: If script is actually a member function, then call it, for Gary bless him.\r\n\t// G: God bless us, everyone!\r\n    Script::CSymbolTableEntry *p_entry=Script::Resolve(script);\r\n    if (p_entry && p_entry->mType==ESYMBOLTYPE_MEMBERFUNCTION)\r\n    {\r\n\t\tDbg_MsgAssert(p_elem,(\"NULL p_elem\"));\r\n\t\tp_elem->CallMemberFunction(script,p_ScriptParams,pScript);\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tScript::CScript *p_new_script = Script::SpawnScript(script,\tp_ScriptParams, callback, p_CallbackParams);\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tp_new_script->SetCommentString(\"Spawned by script command RunScriptOnScreenElement\");\r\n\t\tp_new_script->SetOriginatingScriptInfo(pScript->GetCurrentLineNumber(),pScript->mScriptChecksum);\r\n\t\t#endif\r\n\t\t\r\n\t\t// K: This 'if' is now required because if script is actually a cfunc, SpawnScript will have run it,\r\n\t\t// then returned NULL cos it did not need to create a script.\r\n\t\tif (p_new_script)\r\n\t\t{\r\n\t\t\tp_new_script->mpObject = p_elem;\r\n\t\t\t// normally, script won't be updated until next frame -- we want it NOW, motherfucker\r\n\t\t\tp_new_script->Update();\r\n\t\t\t//Script::RunScript(script, pParams, pElement);\r\n\t\t}\t\r\n\t}\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptSetScreenElementProps(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_elem = pManager->GetElement(pParams, CRCD(0x40c698af,\"id\"), CScreenElementManager::ASSERT);\r\n\t\t\t\r\n\tp_elem->SetProperties(pParams);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\nCScreenElementPtr KlaabuBaabu()\r\n{\r\n\treturn NULL;\r\n}\r\n*/\r\n\r\nbool ScriptDoScreenElementMorph(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_elem = pManager->GetElement(pParams, CRCD(0x40c698af,\"id\"), CScreenElementManager::ASSERT);\r\n\t\t\t\r\n\tp_elem->SetMorph(pParams);\r\n\t\r\n\t//CScreenElementPtr arg_bat = KlaabuBaabu();\r\n\t//printf(\"KlaabuBaabu 0x%x\\n\", arg_bat.Convert());\r\n\t//printf(\"KlaabuBaabu 0x%x\\n\", KlaabuBaabu().Convert());\r\n\t//Dbg_Assert(0);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptSetScreenElementLock(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_elem = pManager->GetElement(pParams, CRCD(0x40c698af,\"id\"), CScreenElementManager::ASSERT);\r\n\tDbg_MsgAssert(p_elem, (\"element not in manager\"));\r\n\t\t\t\r\n\tif (pParams->ContainsFlag(\"off\"))\r\n\t\tp_elem->SetChildLockState(CScreenElement::UNLOCK);\r\n\telse\r\n\t\tp_elem->SetChildLockState(CScreenElement::LOCK);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptScreenElementSystemInit(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\tCWindowElement *p_window = new CWindowElement();\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tp_window->SetID(Script::GenerateCRC(\"root_window\"));\r\n\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tpManager->RegisterObject(*p_window);\r\n\r\n\treturn true;\r\n}\r\n\r\n/*\r\n\tTemporary hack functions for THPS4. Of course, you the reader are probably now\r\n\tusing them for THPS8! :x\r\n*/\r\n\r\nvoid SetScoreTHPS4(char* score_text, int skater_num)\r\n{\r\n\tFront::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_element = p_screen_elem_man->GetElement(Script::GenerateCRC(\"the_score\") + skater_num );\r\n\tif (p_element)\r\n\t{\r\n\t\tDbg_MsgAssert((uint32)p_element->GetType() == CRCD(0x5200dfb6, \"TextElement\"), (\"type is 0x%x\", p_element->GetType()));\r\n\t\tCTextElement *p_score_element = (CTextElement *) (p_element.Convert());\r\n\t\t\r\n\t\tp_score_element->SetText(score_text);\r\n\t}\r\n}\r\n\r\nbool ScriptGetScreenElementDims(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_elem = pManager->GetElement(pParams, CRCD(0x40c698af,\"id\"), CScreenElementManager::ASSERT);\r\n\t\r\n\tint width = (int)( p_elem->GetBaseW() * p_elem->GetScaleX() );\r\n\tint height = (int)( p_elem->GetBaseH() * p_elem->GetScaleY() );\r\n\r\n\tpScript->GetParams()->AddInteger( \"width\", width );\r\n\tpScript->GetParams()->AddInteger( \"height\", height );\r\n\treturn true;\r\n}\r\n\r\n\r\n// @script | TextElementConcatenate | this will append the given string on the end of the \r\n// current text element's string\r\n// @parm name | id | the id of the element\r\n// @uparm \"string\" | the string to append\r\n// @flag enforce_max_width | Don't allow concatenation on a text block\r\n// element if there's no way to wrap the element and keep it within the\r\n// maximum width.  This has no effect on TextElements.\r\nbool ScriptTextElementConcatenate(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_elem = pManager->GetElement( pParams, CRCD(0x40c698af,\"id\"), CScreenElementManager::ASSERT );\r\n\t\r\n\tconst char* p_concat_string;\r\n\tpParams->GetString( NONAME, &p_concat_string, Script::ASSERT );\r\n\r\n\tuint32 type = p_elem->GetType();\r\n\tif ( type == CRCD( 0x40d92263, \"TextBlockElement\" ) )\r\n\t{\r\n\t\tCTextBlockElement* pTextBlockElement = (CTextBlockElement*)p_elem.Convert();\r\n\t\treturn pTextBlockElement->Concatenate( p_concat_string, pParams->ContainsFlag( CRCD( 0x27e7a420, \"enforce_max_width\" ) ), pParams->ContainsFlag( CRCD(0xb8c08f55,\"last_line\") ) );\r\n\t}\r\n\telse if ( type == CRCD( 0x5200dfb6, \"TextElement\" ) )\r\n\t{\r\n\t\tCTextElement* pTextElement = (CTextElement*)p_elem.Convert();\r\n\t\treturn pTextElement->Concatenate( p_concat_string );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"TextElementConcatenate called on type 0x%x\", p_elem->GetType() ) );\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n// @script | TextElementBackspace | removes one character from the text element.  This will\r\n// return false if the text element is already empty\r\n// @parm name | id | the element id\r\nbool ScriptTextElementBackspace(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_elem = pManager->GetElement( pParams, CRCD(0x40c698af,\"id\"), CScreenElementManager::ASSERT );\r\n\r\n\tuint32 type = p_elem->GetType();\r\n\tswitch ( type )\r\n\t{\r\n\t\tcase CRCC( 0x5200dfb6, \"TextElement\" ):\r\n\t\t{\r\n\t\t\tCTextElement* p_text_element = (CTextElement*)p_elem.Convert();\r\n\t\t\treturn p_text_element->Backspace();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase CRCC( 0x40d92263, \"TextBlockElement\" ):\r\n\t\t{\r\n\t\t\tCTextBlockElement* p_text_block_element = (CTextBlockElement*)p_elem.Convert();\r\n\t\t\treturn p_text_block_element->Backspace();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"TextElementBackspace called on %s, which has type %x\", Script::FindChecksumName( p_elem->GetID() ), p_elem->GetType() ) );\r\n\t\t\treturn false;\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n// @script | GetTextElementString | this returns the current string for the specified \r\n// text element.  The string is returned in the script's params (string).\r\n// @parm name | id | the text element id\r\nbool ScriptGetTextElementString(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_elem = pManager->GetElement( pParams, CRCD(0x40c698af,\"id\"), CScreenElementManager::ASSERT );\r\n\t\r\n\tbool found_text = false;\r\n\tswitch ( (uint32)p_elem->GetType() )\r\n\t{\r\n\t\tcase CRCC( 0x5200dfb6, \"TextElement\" ):\r\n\t\t{\r\n\t\t\tCTextElement* p_text_element = (CTextElement*)p_elem.Convert();\r\n\t\t\tchar *p_text = p_text_element->GetText();\r\n\t\t\tif ( p_text )\r\n\t\t\t{\r\n\t\t\t\tpScript->GetParams()->AddString( \"string\", p_text );\r\n\t\t\t\tfound_text = true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase CRCC( 0x40d92263, \"TextBlockElement\" ):\r\n\t\t{\r\n\t\t\tCTextBlockElement* p_text_block_element = (CTextBlockElement*)p_elem.Convert();\r\n\t\t\tchar text[Front::MAX_EDITABLE_TEXT_BLOCK_LENGTH];\r\n\t\t\tif ( p_text_block_element->GetText( text, Front::MAX_EDITABLE_TEXT_BLOCK_LENGTH ) )\r\n\t\t\t{\r\n\t\t\t\tpScript->GetParams()->AddString( \"string\", text );\r\n\t\t\t\tfound_text = true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"GetScreenElementText called on type %x\", p_elem->GetType() ) );\r\n\t\t\tbreak;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n// @script | GetTextElementLength | returns the length of the specified text element\r\n// in the scripts params (length)\r\n// @parm name | id | the text element's id\r\nbool ScriptGetTextElementLength(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_elem = pManager->GetElement( pParams, CRCD(0x40c698af,\"id\"), CScreenElementManager::ASSERT );\r\n\r\n\tuint32 type = (uint32)p_elem->GetType();\r\n\tint length = 0;\r\n\tswitch ( type )\r\n\t{\r\n\t\tcase CRCC( 0x5200dfb6, \"TextElement\" ):\r\n\t\t{\r\n\t\t\tCTextElement* p_text_element = (CTextElement*) p_elem.Convert();\r\n\t\t\tlength = p_text_element->GetLength();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase CRCC( 0x40d92263, \"TextBlockElement\" ):\r\n\t\t{\r\n\t\t\tCTextBlockElement* p_text_block_element = (CTextBlockElement*) p_elem.Convert();\r\n\t\t\tlength = p_text_block_element->GetLength();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, (\"GetTextElementLength called on screen element with type 0x%x\", type ) );\r\n\t\t\treturn false;\r\n\t\t\tbreak;\r\n\t}\r\n\tpScript->GetParams()->AddInteger( \"length\", length );\r\n\treturn true;\r\n}\r\n\r\nbool ScriptGetScreenElementPosition(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_elem = pManager->GetElement(pParams, CRCD(0x40c698af,\"id\"), CScreenElementManager::ASSERT);\r\n\t\r\n\t//float x = p_elem->GetAbsX();\r\n\t//float y = p_elem->GetAbsY();\r\n\tfloat x, y;\r\n\tp_elem->GetLocalULPos( &x, &y );\r\n\r\n\tpScript->GetParams()->AddPair( \"ScreenElementPos\", x, y );\r\n\treturn true;\r\n}\r\n\r\n// @script | MenuSelectedIndexIs | returns true if the selected item in the vmenu is \r\n// the item specified.  Must be called with either an index, the \"first\" flag, or the \"last\" flag\r\n// @uparmopt 1 | some index value (first item is index 0)\r\n// @flag first | checks if the selected item is the first item\r\n// @flag last | checks if the selected item is the last item\r\nbool ScriptMenuSelectedIndexIs(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_elem = pManager->GetElement(pParams, CRCD(0x40c698af,\"id\"), CScreenElementManager::ASSERT);\r\n\r\n\tDbg_MsgAssert( (uint32) p_elem->GetType() == CRCD( 0x130ef802, \"vmenu\" ), ( \"Screen element has wrong type.\" ) );\r\n\r\n\tCBaseMenu* p_menu = (CBaseMenu*)p_elem.Convert();\r\n\r\n\tint selected_index = p_menu->GetSelectedIndex();\r\n\tif ( selected_index == -1 )\r\n\t\treturn false;\r\n\t\r\n\tbool rv = false;\r\n\t\r\n\tint testIndex;\r\n\tif ( pParams->GetInteger( NONAME, &testIndex, Script::NO_ASSERT ) )\r\n\t\trv = ( testIndex == selected_index );\r\n\telse if ( pParams->ContainsFlag( \"first\" ) )\r\n\t\trv = ( selected_index == 0 );\r\n\telse if ( pParams->ContainsFlag( \"last\" ) )\r\n\t\trv = ( selected_index == ( p_menu->CountChildren() - 1 ) );\r\n\telse\r\n\t\tDbg_MsgAssert( 0, (\"MenuSelectedIndexIs must be called with a number, the \\\"first\\\" flag, or the \\\"last\\\" flag\") );\r\n\r\n\treturn rv;\r\n}\r\n\r\n// @script | ScreenElementExists | returns true if the given screen element exists\r\n// @parm name | id | the id to look for...supports compound id's\r\nbool ScriptScreenElementExists(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_elem = pManager->GetElement( pParams, CRCD(0x40c698af,\"id\"), CScreenElementManager::DONT_ASSERT );\r\n\tif ( p_elem )\r\n\t\treturn true;\r\n\treturn false;\r\n}\r\n\r\n// @script | GetScreenElementProps | writes the props of the given screen element to the \r\n// calling script's params\r\n// @parm name | id | the id of the screen element\r\n// @flag | dont_assert\r\nbool ScriptGetScreenElementProps( Script::CScriptStructure *pParams, Script::CScript *pScript )\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\t  \r\n\tCScreenElementPtr p_elem = NULL;\r\n\tuint32 id = pManager->ResolveComplexID(pParams, CRCD(0x40c698af,\"id\"));\r\n\tif ( id )\r\n\t{\r\n\t\tp_elem = pManager->GetElement(id, CScreenElementManager::DONT_ASSERT);\r\n\t}\r\n\t\r\n\tif ( p_elem )\r\n\t{\r\n\t\tp_elem->WritePropertiesToStruct( pScript->GetParams() );\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( pParams->ContainsFlag( CRCD(0x3d92465e,\"dont_assert\") ) )\r\n\t\t\treturn false;\r\n\t\tDbg_MsgAssert( 0, ( \"%s\\n SetScreenElementProps unable to find screen element %s\",  pScript->GetScriptInfo(),  Script::FindChecksumName(id) ) );\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool ScriptSetRootScreenElement( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCScreenElementManager* pManager = CScreenElementManager::Instance();\t  \r\n\tuint32 id = pManager->ResolveComplexID(pParams, CRCD(0x40c698af,\"id\"));\r\n\tif ( id )\r\n\t{\r\n\t\tpManager->SetRootScreenElement( id );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid SetTimeTHPS4(int minutes, int seconds)\r\n{\r\n\tFront::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_element = p_screen_elem_man->GetElement(CRCD(0xa6343cd4,\"the_time\"));\r\n\tif (p_element)\r\n\t{\r\n\t\tDbg_MsgAssert((uint32) p_element->GetType() == CRCD(0x5200dfb6, \"TextElement\"), (\"type is 0x%x\", p_element->GetType()));\r\n\t\tCTextElement *p_time_element = (CTextElement *) p_element.Convert();\r\n\t\t\r\n\t\tchar time_text[64];\r\n\t\tsprintf(time_text, \"%2d:%.2d\", minutes, seconds);\r\n\t\t\r\n\t\tp_time_element->SetText(time_text);\r\n\t}\r\n}\r\n\r\n\r\nvoid HideTimeTHPS4()\r\n{\r\n    Front::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();\r\n    CScreenElementPtr p_element = p_screen_elem_man->GetElement(CRCD(0xa6343cd4,\"the_time\"));\r\n    if (p_element)\r\n    {\r\n        Dbg_MsgAssert((uint32) p_element->GetType() == CRCD(0x5200dfb6, \"TextElement\"), (\"type is 0x%x\", p_element->GetType()));\r\n        CTextElement *p_time_element = (CTextElement *) p_element.Convert();\r\n        p_time_element->SetText( \"\" );\r\n    }\r\n}\r\n\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gfx/2D/ScreenElemMan.h",
    "content": "#ifndef __GFX_2D_SCREENELEMMAN_H__\r\n#define __GFX_2D_SCREENELEMMAN_H__\r\n\r\n#include <gel/objman.h>\r\n#include <gel/event.h>\r\n#include <gfx/2D/ScreenElement2.h>\r\n\r\n#include <sys/sioman.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CScriptStructure;\r\n\tclass CScript;\r\n}\r\n\r\nnamespace Front\r\n{\r\n\r\n/*\r\n\tManages all screen elements. References the root element of the screen element\r\n\tparent/child tree.\r\n\t\r\n\tKeeps track of which elements are in focus, and makes sure that pad events are\r\n\tpassed to these elements.\r\n*/\r\nclass CScreenElementManager : public Obj::CBaseManager, public Obj::CEventListener\r\n{\r\n\r\n\tDeclareSingletonClass( CScreenElementManager );\r\n\r\npublic:\r\n\t\t\t\t\t\t\t\tCScreenElementManager();\r\n\t\t\t\t\t\t\t\t~CScreenElementManager();\r\n\r\n\tCScreenElementPtr \t\t\tCreateElement(uint32 type, uint32 id, Script::CStruct *pProps);\r\n\tenum \t\t\t\t\t\tERecurse { DONT_RECURSE = 0, RECURSE = 1};\r\n\tenum \t\t\t\t\t\tEPreserveParent { DONT_PRESERVE_PARENT = 0, PRESERVE_PARENT = 1};\r\n\tvoid\t\t\t\t\t\tDestroyElement(uint32 id, ERecurse recurse = RECURSE, EPreserveParent preserveParent = DONT_PRESERVE_PARENT, Script::CScript *pCallingScript = NULL);\r\n\r\n\tvoid\t\t\t\t\t\tSetParent(const CScreenElementPtr &pParent, const CScreenElementPtr &pChild, CScreenElement::EPosRecalc recalculatePosition = CScreenElement::vRECALC_POS);\r\n\tenum EAssert\r\n\t{\r\n\t\tDONT_ASSERT = 0,\r\n\t\tASSERT,\r\n\t};\r\n\tCScreenElementPtr \t\t\tGetElement(uint32 id, EAssert assert = DONT_ASSERT);\r\n\tCScreenElementPtr \t\t\tGetElement(Script::CStruct *pStructContainingId, char *pIdSubStructName, EAssert assert = DONT_ASSERT);\r\n\tCScreenElementPtr \t\t\tGetElement(Script::CStruct *pStructContainingId, uint32 IdSubStructName, EAssert assert);\r\n\r\n\tvoid\t\t\t\t\t\tUpdate();\r\n\tvoid\t\t\t\t\t\tSetPausedState(bool pause);\r\n\t\r\n\tvoid \t\t\t\t\t\tset_tree_lock_state(CScreenElement::ELockState state);\r\n\tvoid\t\t\t\t\t\tpass_event_to_listener(Obj::CEvent *pEvent);\t\r\n\t\r\n\tbool\t\t\t\t\t\tIsComplexID(Script::CStruct *pStructContainingId, char *pIdSubStructName);\r\n\tuint32 \t\t\t\t\t\tResolveComplexID(Script::CStruct *pStructContainingId, uint32 IdSubStructName);\r\n\tuint32\t\t\t\t\t\tResolveComplexID(Script::CStruct *pStructContainingId, char *pIdSubStructName);\r\n\t\r\n\t/*\r\n\t\tVirtual functions from CBaseManager\r\n\t*/\r\n\t\r\n\tvoid\t\t\t\t\t\tRegisterObject ( Obj::CObject& obj );\r\n\tvoid\t\t\t\t\t\tUnregisterObject ( Obj::CObject& obj );\t\r\n\tvoid\t\t\t\t\t\tKillObject ( Obj::CObject& obj );\r\n\tLst::Head< Obj::CObject > &\tGetRefObjectList();\r\n\r\n\tvoid\t\t\t\t\t\tSetRootScreenElement( uint32 id );\r\n\r\nprivate:\r\n\r\n\tstruct FocusNode // in the focus tree\r\n\t{\r\n\t\t//FocusNode *\t\t\t\tmpFirstChild;\r\n\t\t//FocusNode *\t\t\t\tmpSibling;\r\n\t\tCScreenElementPtr \t\tmpElement;\r\n\t\tuint32\t\t\t\t\tmId;\r\n\t\tFocusNode *\t\t\t\tmpNextNode;\r\n\t\tbool\t\t\t\t\tmProcessed;\r\n\t\tbool\t\t\t\t\tmTempOutOfFocus;\r\n\t};\r\n\t\r\n\tvoid\t\t\t\t\t\tdestroy_element_recursive(EPreserveParent preserve_parent, const CScreenElementPtr &pElement, Script::CScript *pCallingScript);\r\n\tCScreenElementPtr \t\t\tget_element_by_local_id(const CScreenElementPtr &pParent, uint32 desiredLocalID);\r\n\r\n\tvoid\t\t\t\t\t\tmark_element_in_focus(const CScreenElementPtr &pElement, int controller);\r\n\tvoid\t\t\t\t\t\tmark_element_out_of_focus(const CScreenElementPtr &pElement, bool onlyChildren = false, bool temporaryOnly = false);\r\n\tvoid\t\t\t\t\t\tremark_temporarily_out_of_focus_elements(const CScreenElementPtr &pElement);\r\n\tvoid \t\t\t\t\t\ttest_focus_node(FocusNode *pNode);\r\n\r\n\tbool\t\t\t\t\t\tis_pad_event(uint32 eventType);\r\n\t\r\n\tCScreenElementPtr\t\t\tmp_root_element;\r\n\r\n\t// a temporary pointer used by ResolveComplexID() for recursion\r\n\tCScreenElementPtr \t\t\tmp_resolve_temp;\r\n\t\r\n\tenum\r\n\t{\r\n\t\tNUM_FOCUS_NODES\t=\t\t48,\t\t\t\t\t// basically, a pool of these\r\n\t\tNUM_FOCUS_LISTS =\t\tSIO::vMAX_DEVICES,\t// one for each controller\r\n\t};\r\n\t\r\n\tFocusNode\t\t\t\t\tm_focus_node_pool[NUM_FOCUS_NODES];\t\r\n\tFocusNode *\t\t\t\t\tmp_focus_list[NUM_FOCUS_LISTS];\r\n\tbool\t\t\t\t\t\tm_focus_list_changed[NUM_FOCUS_LISTS];\r\n\r\n\tenum\r\n\t{\r\n\t\tMAX_PAD_EVENT_TYPES\t\t= 48,\r\n\t};\r\n\tuint32\t\t\t\t\t\tm_pad_event_type_tab[MAX_PAD_EVENT_TYPES];\r\n\tint\t\t\t\t\t\t\tm_num_pad_event_types;\r\n};\r\n\r\n\r\n\r\nbool ScriptCreateScreenElement(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptDestroyScreenElement(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptRunScriptOnScreenElement(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptSetScreenElementProps(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptDoScreenElementMorph(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptSetScreenElementLock(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptScreenElementSystemInit(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptGetScreenElementDims(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptTextElementConcatenate(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptTextElementBackspace(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptGetTextElementString(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptGetTextElementLength(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptGetScreenElementPosition(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptMenuSelectedIndexIs(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptScreenElementExists(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptGetScreenElementProps( Script::CScriptStructure *pParams, Script::CScript *pScript );\r\nbool ScriptSetRootScreenElement( Script::CStruct* pParams, Script::CScript* pScript );\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/2D/ScreenElement2.cpp",
    "content": "#include <core/defines.h>\r\n#include <core/HashTable.h>\r\n#include <gfx/NxFontMan.h>\r\n#include <gfx/NxViewMan.h>\r\n#include <gfx/2D/ScreenElement2.h>\r\n#include <gfx/2D/ScreenElemMan.h>\r\n#include <gfx/2D/Window.h>\r\n#include <gel/Event.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/Scripting/array.h>\r\n#include <gel/Scripting/scriptdefs.h>\r\n#include <gel/Scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/utils.h>\r\n#ifdef\t__PLAT_NGPS__\t\r\n#include <gfx/ngps/nx/line.h>\r\n#endif\r\n\r\n/*\r\n\t=========================================================\r\n\tRTFM!!!!\r\n\t\r\n\tBe sure to check out the user's guide for the menu system\r\n\tto get an idea of what all this code's for. Heurghh!!\r\n\t=========================================================\r\n*/\r\n\r\nnamespace Front\r\n{\r\n\r\n\r\nconst float CScreenElement::vJUST_LEFT\t\t= -1.0f;\r\nconst float CScreenElement::vJUST_TOP\t\t= -1.0f;\r\nconst float CScreenElement::vJUST_CENTER\t= 0.0f;\r\nconst float CScreenElement::vJUST_RIGHT\t\t= 1.0f;\r\nconst float CScreenElement::vJUST_BOTTOM\t= 1.0f;\r\n\r\nconst float CScreenElement::AUTO_Z_SPACE\t= 1.0f;\r\n\r\nCScreenElement::CScreenElement()\r\n\t: CObject()\r\n{\r\n\tm_key_time = 0;\r\n\tmp_parent = NULL;\r\n\tmp_child_list = NULL;\r\n\tmp_prev_sibling = NULL;\r\n\tmp_next_sibling = NULL;\r\n\r\n\tm_local_props.SetScale(1.0f, 1.0f);\r\n\tm_local_props.SetAbsoluteScale(1.0f, 1.0f);\r\n\tm_local_props.SetScreenPos(0.0f, 0.0f);\r\n\tm_local_props.SetRotate( 0.0f );\r\n\tm_local_props.SetWorldPos( Mth::Vector(0.0f, 0.0f, 0.0f) );\r\n\t\r\n\tImage::RGBA default_rgba;\r\n\tdefault_rgba.r = 128;\r\n\tdefault_rgba.g = 128;\r\n\tdefault_rgba.b = 128;\r\n\tdefault_rgba.a = 128;\r\n\tm_local_props.SetRGBA( default_rgba );\r\n\r\n\tm_local_props.alpha = 1.0f;\r\n\tm_target_local_props = m_local_props;\r\n\tm_summed_props = m_local_props;\r\n\r\n\tm_base_w = 0.0f;\r\n\tm_base_h = 0.0f;\r\n\r\n\tm_rgba.r = 128;\r\n\tm_rgba.g = 128;\r\n\tm_rgba.b = 128;\r\n\tm_rgba.a = 128;\r\n\t\r\n\tm_z_priority = 0.0f;\r\n\r\n\tm_originalAlpha = 1.0f;\r\n\t\r\n\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\tm_object_flags |= vIS_SCREEN_ELEMENT;\r\n}\r\n\r\n\r\n\r\n\r\nCScreenElement::~CScreenElement()\r\n{\r\n\tset_parent(NULL, vDONT_RECALC_POS);\r\n\tm_id = 0xDEADBEEF;\r\n}\r\n\r\n\r\n\r\n\r\n// absolute upper-left, last frame's\r\nfloat CScreenElement::GetAbsX()\r\n{\r\n\treturn m_summed_props.GetScreenUpperLeftX();\r\n}\r\n\r\n\r\n\r\n\r\n// absolute upper-left, last frame's\r\nfloat CScreenElement::GetAbsY()\r\n{\r\n\treturn m_summed_props.GetScreenUpperLeftY();\r\n}\r\n\r\n\r\n\r\n\r\n// absolute width, includes scale, last frame's\r\nfloat CScreenElement::GetAbsW()\r\n{\r\n\treturn m_base_w * m_summed_props.GetAbsoluteScaleX();\r\n}\r\n\r\n\r\n\r\n\r\n// absolute height, includes scale, last frame's\r\nfloat CScreenElement::GetAbsH()\r\n{\r\n\treturn m_base_h * m_summed_props.GetAbsoluteScaleY();\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tPosition of anchor point, in parent's space. 'Target' means where it's going,\r\n\tnot necessarily where it is.\r\n*/\r\nvoid CScreenElement::GetLocalPos(float *pX, float *pY)\r\n{\r\n\tDbg_Assert(pX);\r\n\tDbg_Assert(pY);\r\n\t\r\n\t*pX = m_target_local_props.GetScreenPosX();\r\n\t*pY = m_target_local_props.GetScreenPosY();\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tPosition of upper left corner of element, in parent's space. 'Target' means where \r\n\tit's going, not necessarily where it is.\r\n*/\r\nvoid CScreenElement::GetLocalULPos(float *pX, float *pY)\r\n{\r\n\tDbg_Assert(pX);\r\n\tDbg_Assert(pY);\r\n\t\r\n\t*pX = m_target_local_props.GetScreenUpperLeftX();\r\n\t*pY = m_target_local_props.GetScreenUpperLeftY();\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tJustification is a fixed attribute (doesn't morph)\r\n*/\r\nvoid CScreenElement::GetJust(float *pJustX, float *pJustY)\r\n{\r\n\tDbg_Assert(pJustX);\r\n\tDbg_Assert(pJustY);\r\n\t\r\n\t*pJustX = m_just_x;\r\n\t*pJustY = m_just_y;\r\n}\r\n\r\n\r\n\r\n\r\n/* \r\n\tSets desired local position, element will morph from current position to\r\n\tthat position over set morph time (unless force_instant set).\r\n*/\r\nvoid CScreenElement::SetPos(float x, float y, EForceInstant forceInstant)\r\n{\r\n\tDbg_MsgAssert(!(m_object_flags & CScreenElement::v3D_POS), (\"Illegal to set the 2D position of a 3D screen element\"));\r\n\r\n\tif (m_target_local_props.GetScreenPosX() != x || m_target_local_props.GetScreenPosY() != y)\r\n\t{\r\n\t\tm_target_local_props.SetScreenPos(x, y);\r\n\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t\tcompute_ul_pos(m_target_local_props);\r\n\t}\r\n\tif (forceInstant) \r\n\t{\r\n\t\tif (m_local_props.GetScreenPosX() != x || m_local_props.GetScreenPosY() != y)\r\n\t\t{\r\n\t\t\t// on the next update, this element will arrive at the target position\r\n\t\t\tm_local_props.SetScreenPos(x, y);\r\n\t\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/* \r\n\tSets desired world position, element will morph from current position to\r\n\tthat position over set morph time (unless force_instant set).\r\n*/\r\nvoid CScreenElement::SetPos3D(const Mth::Vector & pos3D, EForceInstant forceInstant)\r\n{\r\n\tif (m_target_local_props.GetWorldPos() != pos3D )\r\n\t{\r\n\t\tm_target_local_props.SetWorldPos(pos3D);\r\n\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t\tcompute_ul_pos(m_target_local_props);\r\n\t}\r\n\tif (forceInstant) \r\n\t{\r\n\t\tif (m_local_props.GetWorldPos() != pos3D )\r\n\t\t{\r\n\t\t\t// on the next update, this element will arrive at the target position\r\n\t\t\tm_local_props.SetWorldPos(pos3D);\r\n\t\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t\t}\r\n\t}\r\n\r\n\tm_object_flags |= CScreenElement::v3D_POS;\r\n}\r\n\r\n\r\n/*\r\n\tSet 'force' if dims being set from outside element. When that happens, element cannot\r\n\tchange own dims.\r\n\t\r\n\tWell, actually it can (VMenu), but 'force' is taken is a suggestion.\r\n*/\r\nvoid CScreenElement::SetDims(float w, float h, EForceDims force)\r\n{\r\n\tif (m_base_w != w || m_base_h != h)\r\n\t{\r\n\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t\tm_base_w = w;\r\n\t\tm_base_h = h;\r\n\t\tcompute_ul_pos(m_target_local_props);\r\n\t}\r\n\t\r\n\tif (force) \r\n\t\tm_object_flags |= vFORCED_DIMS;\r\n\telse\r\n\t\tm_object_flags &= ~vFORCED_DIMS;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tJustification effects where the upper-left corner of an element is relative to \r\n\tthe element's assigned position (anchor point). \r\n\t\r\n\t(-1.0, -1.0):\tanchor is at upper-left of element\r\n\t(0.0, 0.0):\t\tanchor is in center of element\r\n\t(1.0, 1.0):\t\tanchor is at lower-right of element\r\n\t\r\n\tYou can figure out the meaning of other numbers.\r\n*/\r\nvoid CScreenElement::SetJust(float justX, float justY)\r\n{\r\n\tif (m_just_x != justX || m_just_y != justY)\r\n\t{\r\n\t\t// calculate justification differences and adjust new position so the item still appears to\r\n\t\t// have the same location as before\r\n\t\tfloat x_diff = m_local_props.GetScaleX() * m_base_w * (justX - m_just_x) / 2.0f;\r\n\t\tfloat y_diff = m_local_props.GetScaleY() * m_base_h * (justY - m_just_y) / 2.0f;\r\n\t\tm_local_props.SetScreenPos(m_local_props.GetScreenPosX() + x_diff, m_local_props.GetScreenPosY() + y_diff);\r\n\t\tm_target_local_props.SetScreenPos(m_target_local_props.GetScreenPosX() + x_diff, m_target_local_props.GetScreenPosY() + y_diff);\r\n\t\t//m_local_props.ulx += x_diff;\r\n\t\t//m_local_props.uly += y_diff;\r\n\r\n\t\tm_just_x = justX;\r\n\t\tm_just_y = justY;\r\n\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t\t\r\n\t\tcompute_ul_pos(m_target_local_props);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/* \r\n\tSets desired local scale, element will morph from current scale to\r\n\tthat scale over set morph time (unless force_instant set).\r\n*/\r\nvoid CScreenElement::SetScale(float scaleX, float scaleY, bool relative, EForceInstant forceInstant )\r\n{\r\n\tif (m_target_local_props.GetScaleX() != scaleX || m_target_local_props.GetScaleY() != scaleY || relative)\r\n\t{\r\n\t\tif ( !relative )\r\n\t\t{\r\n\t\t\tm_target_local_props.SetAbsoluteScale(scaleX, scaleY);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tscaleX *= m_target_local_props.GetAbsoluteScaleX();\r\n\t\t\tscaleY *= m_target_local_props.GetAbsoluteScaleY();\r\n\t\t}\r\n\t\tm_target_local_props.SetScale(scaleX, scaleY);\r\n\t\tcompute_ul_pos(m_target_local_props);\r\n\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t}\r\n\tif (forceInstant) \r\n\t{\r\n\t\tif (m_local_props.GetScaleX() != scaleX || m_local_props.GetScaleY() != scaleY)\r\n\t\t{\r\n\t\t\t// on the next update, this element will arrive at the target scale\r\n\t\t\tm_local_props.SetScale(scaleX, scaleY);\r\n\t\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/* \r\n\tSets desired local alpha, element will morph from current alpha to\r\n\tthat alpha over set morph time (unless force_instant set).\r\n*/\r\nvoid CScreenElement::SetAlpha(float alpha, EForceInstant forceInstant)\r\n{\r\n\tif (m_target_local_props.alpha != alpha)\r\n\t{\r\n\t\tm_target_local_props.alpha = alpha;\r\n\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t}\r\n\tif (forceInstant) \r\n\t{\r\n\t\tif (m_local_props.alpha != alpha)\r\n\t\t{\r\n\t\t\t// on the next update, this element will arrive at the target alpha\r\n\t\t\tm_local_props.alpha = alpha;\r\n\t\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tSpecifies the amount of time over which this element will changes from its\r\n\tcurrent morphable properties (pos, scale, alpha) to the target ones. If\r\n\tan animation already in progress, override previously set time.\r\n*/\r\nvoid CScreenElement::SetAnimTime(Tmr::Time animTime)\r\n{\r\n\tm_base_time = Tmr::GetTime();\r\n\tm_key_time = animTime;\r\n\tm_last_motion_grad = 0.0f;\r\n\tm_last_pct_changed = 0.0f;\r\n\t\r\n\tif (!animTime)\r\n\t{\r\n\t\tm_local_props = m_target_local_props;\r\n\t}\r\n\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\tm_object_flags &= ~vMORPHING_PAUSED;\r\n\tm_object_flags &= ~vMORPHING_PAUSED2;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tNote: The alpha component here is multiplied by the alpha from SetAlpha() to\r\n\tdetermine final alpha.\r\n*/\r\nvoid CScreenElement::SetRGBA( Image::RGBA rgba, EForceInstant forceInstant )\r\n{\r\n\tImage::RGBA target_rgba = m_target_local_props.GetRGBA();\r\n\tif ( target_rgba.r != rgba.r || target_rgba.g != rgba.g || target_rgba.b != rgba.b || target_rgba.a != rgba.a )\r\n\t{\r\n\t\tm_target_local_props.SetRGBA( rgba );\r\n\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t}\r\n\tif ( forceInstant )\r\n\t{\r\n\t\tm_local_props.SetRGBA( rgba );\r\n\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t}\r\n}\r\n\r\n\r\n/*\r\n\tUsed to force drawing order entry (instead of it being automatically assigned). Client code should be \r\n\twritten using knowledge of how these values work.\r\n*/\r\nvoid CScreenElement::SetZPriority(float zPriority)\r\n{\r\n\tm_z_priority = zPriority;\r\n\tm_object_flags |= vCHANGED_STATIC_PROPS;\r\n\tm_object_flags |= vCUSTOM_Z_PRIORITY;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CScreenElement::SetMorphPausedState(bool pause)\r\n{\r\n\tif (pause)\r\n\t\tm_object_flags |= vMORPHING_PAUSED;\r\n\telse\r\n\t{\r\n\t\tm_object_flags &= ~vMORPHING_PAUSED;\r\n\t\tm_object_flags &= ~vMORPHING_PAUSED2;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tWhen element is unlocked, children can be added or removed, otherwise they can't. Really just an \r\n\toptimization so that lots of children can be added en masse without slowdown.\r\n\t\r\n\tNote: The children you add to an element don't officially exist until you lock the element again,\r\n\tso don't forget to do this.\r\n*/\r\nvoid CScreenElement::SetChildLockState(CScreenElement::ELockState lockState)\r\n{\r\n\tELockState current_lock_state = UNLOCK;\r\n\tif (m_object_flags & CScreenElement::vCHILD_LOCK) current_lock_state = LOCK;\r\n\tif (lockState == current_lock_state)\r\n\t\treturn;\r\n\r\n\tif (lockState == LOCK)\r\n\t\tm_object_flags |= CScreenElement::vCHILD_LOCK;\r\n\telse\r\n\t\tm_object_flags &= ~CScreenElement::vCHILD_LOCK;\r\n\r\n\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\t\r\n\tif (lockState == LOCK) \r\n\t{\t\r\n\t\t//Ryan(\"Setting child lock on, item %s\\n\", Script::FindChecksumName(m_id));\r\n\t\t\r\n\t\t// send out notice that child lock has been turned on\r\n\t\tp_tracker->LaunchEvent(Obj::CEvent::TYPE_NOTIFY_CHILD_LOCK, m_id);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//Ryan(\"Setting child lock off, item %s\\n\", Script::FindChecksumName(m_id));\r\n\t\t\r\n\t\t// send out notice that child lock has been turned off\r\n\t\tp_tracker->LaunchEvent(Obj::CEvent::TYPE_NOTIFY_CHILD_UNLOCK, m_id);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nCScreenElement* CScreenElement::GetLastChild()\r\n{\r\n\tCScreenElement* pChild = mp_child_list;\r\n\twhile(pChild)\r\n\t{\r\n\t\tif (!pChild->GetNextSibling())\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tpChild = pChild->GetNextSibling();\r\n\t}\r\n\r\n\treturn pChild;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tReturns a pointer to the child with that ID.\r\n*/\r\nCScreenElement* CScreenElement::GetChildById(uint32 id, int *pIndex)\r\n{\r\n\treturn get_child_by_id_or_index(id, pIndex);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tReturns a pointer to the Nth child, where N = index.\r\n\t\r\n\tThe children are indexed in the order they are added. If one is removed,\r\n\tthen the indices of all subsequent children are shifted down a notch.\r\n*/\r\nCScreenElement* CScreenElement::GetChildByIndex(int index)\r\n{\r\n\treturn get_child_by_id_or_index(0, &index);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tReturns number of children.\r\n*/\r\nint CScreenElement::CountChildren()\r\n{\r\n\tCScreenElementPtr p_child = mp_child_list;\r\n\tint count = 0;\r\n\twhile(p_child)\r\n\t{\r\n\t\tp_child = p_child->GetNextSibling();\r\n\t\tcount++;\r\n\t}\r\n\treturn count;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tAn important entry point to CScreenElement from script. Sets the elements static\r\n\t(as opposed to morphable) properties.\r\n\t\r\n\tNote: a virtual function, so can be extended by subclasses\r\n\tNote: SetProperties() in a subclass should call this function before doing its own logic\r\n*/\r\nvoid CScreenElement::SetProperties(Script::CStruct *pProps)\r\n{\r\n\tCScreenElementManager *pManager = static_cast<CScreenElementManager *>(mp_manager);\r\n\tDbg_Assert(pManager);\r\n\r\n\tScript::CPair pos;\r\n\tif (pProps->GetPair(CRCD(0x7f261953,\"pos\"), &pos))\r\n\t{\r\n\t\t// in this case, position will be forced instantly to the specified position\r\n\t\tSetPos(pos.mX, pos.mY, FORCE_INSTANT);\r\n\t}\r\n\r\n\tMth::Vector pos3D;\r\n\tif (pProps->GetVector(CRCD(0x4b491900,\"pos3D\"), &pos3D))\r\n\t{\r\n\t\tpos3D[W] = 1.0f;\t\t// force to be a point\r\n\t\t//Dbg_Message(\"************ position (%f, %f, %f)\", pos3D[X], pos3D[Y], pos3D[Z]);\r\n\t\tSetPos3D(pos3D, FORCE_INSTANT);\r\n\t}\r\n\r\n\tScript::CPair dims;\r\n\tif (pProps->GetPair(CRCD(0x34a68574,\"dims\"), &dims))\r\n\t{\r\n\t\tSetDims(dims.mX, dims.mY, FORCE_DIMS);\r\n\t}\r\n\r\n\tuint32 parent_id = pManager->ResolveComplexID(pProps, CRCD(0xc2719fb0,\"parent\"));\r\n\tif (parent_id)\r\n\t{\r\n\t\tCScreenElementPtr pParent = pManager->GetElement(parent_id);\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\r\n\t\tif (pParent->GetType() == CScreenElement::TYPE_TEXT_BLOCK_ELEMENT)\r\n\t\t{\r\n\t\t\tif (GetType() != CScreenElement::TYPE_TEXT_ELEMENT)\r\n\t\t\t{\r\n\t\t\t\tScript::PrintContents(pProps);\r\n\t\t\t\tDbg_MsgAssert(0,(\"TextBlockElement %s parenting child %s that is NOT a CTextElement (it's %s)\\nIn CScreenElement::SetProperties\\n^^^ SEE STRUCTURE ABOVE MEM DUMP & TELL BRAD^^^\\n\",\r\n\t\t\t\t\tScript::FindChecksumName(pParent->GetID()), Script::FindChecksumName(GetID()), Script::FindChecksumName(GetType())));\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif (!pParent)\r\n\t\t{\r\n\t\t\tScript::PrintContents(pProps, 2);\r\n\t\t\tDbg_MsgAssert(0, (\"could not resolve parent, see struct above\"));\r\n\t\t}\r\n\t\t#endif\r\n\t\tpManager->SetParent(pParent, this);\r\n\t}\r\n\r\n\tfloat just[2] = { 0.0f, 0.0f };\r\n\tif (resolve_just(pProps, CRCD(0x8b60022f,\"just\"), just, just+1))\r\n\t\tSetJust(just[0], just[1]);\r\n\t\r\n\t\r\n\tImage::RGBA rgba;\r\n\tif (resolve_rgba(pProps, CRCD(0x3f6bcdba,\"rgba\"), &rgba))\r\n\t{\r\n\t\tSetRGBA(rgba);\r\n\t}\r\n\t\t\r\n\tfloat z_priority;\r\n\tif (pProps->GetFloat(CRCD(0x57710f31,\"z_priority\"), &z_priority))\r\n\t{\r\n\t\tSetZPriority(z_priority);\r\n\t}\r\n\t\r\n\tif (pProps->ContainsFlag(CRCD(0x1d944426,\"not_focusable\")))\r\n\t{\r\n\t\t// sets a flag\r\n\t\tSetChecksumTag(NONAME, CRCD(0xf33a3321,\"tag_not_focusable\"));\r\n\t}\r\n\telse if (pProps->ContainsFlag(CRCD(0x5cdecf29,\"focusable\")))\r\n\t{\r\n\t\tRemoveFlagTag(CRCD(0xf33a3321,\"tag_not_focusable\"));\r\n\t}\r\n\t\r\n\tuint32 local_id;\r\n\tif (pProps->GetChecksum(CRCD(0xa2a5defe,\"local_id\"), &local_id))\r\n\t{\r\n\t\tSetChecksumTag(CRCD(0x9494a525,\"tag_local_id\"), local_id); \r\n\t}\r\n\r\n\tif (pProps->ContainsFlag(CRCD(0xff85d4d7,\"unpause\")))\r\n\t{\r\n\t\tSetMorphPausedState(false);\r\n\t}\r\n\r\n\tif ( pProps->ContainsFlag( CRCD(0xe5d6fe3e,\"block_events\") ) )\r\n\t{\r\n\t\tm_object_flags |= vEVENTS_BLOCKED;\r\n\t}\r\n\telse if ( pProps->ContainsFlag( CRCD(0xd5614a50,\"unblock_events\") ) )\r\n\t{\r\n\t\tm_object_flags &= ~vEVENTS_BLOCKED;\r\n\t}\r\n\r\n\tif ( pProps->ContainsFlag( CRCD(0x5b6634d4,\"hide\") ) )\r\n\t{\r\n\t\tm_object_flags |= vHIDDEN;\r\n\t}\r\n\telse if ( pProps->ContainsFlag( CRCD(0xb60d1f35,\"unhide\") ) )\r\n\t{\r\n\t\tm_object_flags &= ~vHIDDEN;\r\n\t\tm_object_flags |= vCHANGED_STATIC_PROPS;\r\n\t}\r\n\t\r\n\tCObject::SetProperties(pProps);\r\n\t\t\r\n\treturn;\r\n}\r\n\r\n\r\nvoid CScreenElement::WritePropertiesToStruct( Script::CStruct *pStruct )\r\n{\r\n\t// alpha value\r\n\tpStruct->AddFloat( CRCD(0x2f1fc695,\"alpha\"), m_local_props.alpha );\r\n\t\r\n\t// rgba array\r\n\tImage::RGBA current_rgba = m_local_props.GetRGBA();\r\n\tScript::CArray* p_rgba = new Script::CArray();\r\n\tp_rgba->SetSizeAndType( 4, ESYMBOLTYPE_INTEGER );\r\n\tp_rgba->SetInteger( 0, current_rgba.r );\r\n\tp_rgba->SetInteger( 1, current_rgba.g );\r\n\tp_rgba->SetInteger( 2, current_rgba.b );\r\n\tp_rgba->SetInteger( 3, current_rgba.a );\r\n\tpStruct->AddArray( CRCD(0x3f6bcdba,\"rgba\"), p_rgba );\r\n\tScript::CleanUpArray( p_rgba );\r\n\tdelete p_rgba;\r\n\r\n\t// scale value\r\n\tfloat scaleX = m_local_props.GetScaleX();\r\n\tfloat scaleY = m_local_props.GetScaleY();\r\n\t// only add a pair if they're different\r\n\tif ( scaleX == scaleY )\r\n\t\tpStruct->AddFloat( CRCD(0x13b9da7b,\"scale\"), scaleX );\r\n\telse\r\n\t\tpStruct->AddPair( CRCD(0x13b9da7b,\"scale\"), scaleX, scaleY );\r\n\t\t\r\n\t// position\r\n\tpStruct->AddPair( CRCD(0x7f261953,\"pos\"), m_local_props.GetScreenPosX(), m_local_props.GetScreenPosY() );\r\n\r\n\t// are the events blocked?\r\n\tif ( EventsBlocked() )\r\n\t\tpStruct->AddInteger( CRCD(0x73cb6d65,\"events_blocked\"), 1 );\r\n\telse\r\n\t\tpStruct->AddInteger( CRCD(0x73cb6d65,\"events_blocked\"), 0 );\r\n}\r\n\r\n\r\n/*\r\n\tAnother important entry point to CScreenElement from script. Sets the elements morphable\r\n\t(as opposed to static) properties.\r\n\t\r\n\tNote: a virtual function, so can be extended by subclasses.\r\n\tNote: SetMorph() in a subclass should call this function before doing its own logic\r\n*/\r\nvoid CScreenElement::SetMorph(Script::CStruct *pProps)\r\n{\t\r\n\tfloat pos_x, pos_y;\r\n\tif (resolve_pos(pProps, &pos_x, &pos_y))\r\n\t{\r\n\t\tSetPos(pos_x, pos_y);\r\n\t}\r\n\r\n\t// TODO: temp hack for restoring alpha values\r\n\tif ( pProps->ContainsFlag( CRCD(0x5d8bb535,\"restore_alpha\") ) )\r\n\t\tSetAlpha( m_originalAlpha );\r\n\t\r\n\tfloat alpha;\r\n\tif ( pProps->GetFloat(CRCD(0x2f1fc695,\"alpha\"), &alpha) )\r\n\t{\r\n\t\t// TODO: temp hack for remembering alpha values\t\t\r\n\t\tif ( pProps->ContainsFlag( CRCD(0xff8df26b,\"remember_alpha\") ) )\r\n\t\t\tm_originalAlpha = m_local_props.alpha;\r\n\t\t\r\n\t\tSetAlpha( alpha );\r\n\t}\r\n\r\n\tfloat scale;\r\n\tint relative_scale = 0;\r\n\tif ( pProps->ContainsFlag( CRCD(0xe1f4711f,\"relative_scale\") ) )\r\n\t\trelative_scale = 1;\r\n\tif (pProps->GetFloat(CRCD(0x13b9da7b,\"scale\"), &scale))\r\n\t{\r\n\t\tSetScale(scale, scale, relative_scale );\r\n\t}\r\n\tScript::CPair scale_pair;\r\n\tif (pProps->GetPair(CRCD(0x13b9da7b,\"scale\"), &scale_pair))\r\n\t{\r\n\t\tSetScale(scale_pair.mX, scale_pair.mY, relative_scale);\r\n\t}\r\n\r\n\tfloat desired_time;\r\n\tTmr::Time anim_time;\r\n\tif (pProps->GetFloat(CRCD(0x906b67ba,\"time\"), &desired_time))\r\n\t{\r\n\t\tanim_time = (Tmr::Time) (desired_time * (float) Tmr::vRESOLUTION);\r\n\t}\r\n\telse\r\n\t\tanim_time = 0;\r\n\tSetAnimTime(anim_time);\r\n\r\n\tuint32 anim_type = 0;\r\n\t// clear affected bits\r\n\tm_object_flags &= ~(vANIM_BIT_MASK << vANIM_FIRST_BIT);\r\n\tif (pProps->GetChecksum(CRCD(0x98549ba4,\"anim\"), &anim_type))\r\n\t{\r\n\t\tif (anim_type == CRCD(0xf5b95ce4, \"fast_out\"))\r\n\t\t\tm_object_flags |= vANIM_FAST_OUT << vANIM_FIRST_BIT;\r\n\t\telse if (anim_type == CRCD(0x6aa7dd49, \"fast_in\"))\r\n\t\t\tm_object_flags |= vANIM_FAST_IN << vANIM_FIRST_BIT;\r\n\t\telse if (anim_type == CRCD(0x768f6843, \"gentle\"))\r\n\t\t\tm_object_flags |= vANIM_SLOW_INOUT << vANIM_FIRST_BIT;\r\n\t}\r\n\tif (!anim_type)\r\n\t{\r\n\t\tm_object_flags |= (vANIM_LINEAR << vANIM_FIRST_BIT);\r\n\t}\r\n\r\n\t// rgba values\r\n\tImage::RGBA rgba;\r\n\tif ( resolve_rgba( pProps, CRCD(0x3f6bcdba,\"rgba\"), &rgba ) )\r\n\t{\r\n\t\tSetRGBA( rgba, DONT_FORCE_INSTANT );\r\n\t}\r\n\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tThis function must be implemented for access to member commands from script.\r\n*/\r\nbool CScreenElement::CallMemberFunction( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tif (Checksum == CRCD(0x6c63c7c5, \"SetProps\"))\r\n\t{\r\n\t\tSetProperties(pParams);\r\n\t}\r\n    else if (Checksum == CRCD(0xdd0c8df3, \"DoMorph\"))\r\n\t{\r\n\t\tfloat time;\r\n\t\tif (pParams->GetFloat(CRCD(0x906b67ba,\"time\"), &time))\r\n\t\t{\r\n\t\t\tTmr::Time anim_time = (Tmr::Time) (time * (float) Tmr::vRESOLUTION);\r\n\t\t\tpScript->WaitTime(anim_time);\r\n\t\t}\r\n\r\n\t\tSetMorph(pParams);\r\n\t}\r\n\telse if (Checksum == CRCD(0xc6870028, \"Die\"))\r\n\t{\r\n\t\tCScreenElementManager* p_manager = CScreenElementManager::Instance();\t\t\r\n\t\t\r\n\t\tCScreenElementPtr p_parent = mp_parent;\r\n\t\tp_parent->SetChildLockState(UNLOCK);\r\n\t\t\r\n\t\t// will kill this screen element and all its children\r\n\t\t// THIS IS POTENTIALLY DANGEROUS, LEAVE THIS FUNCTION ASAP\r\n\t\tp_manager->DestroyElement(m_id, CScreenElementManager::RECURSE, CScreenElementManager::DONT_PRESERVE_PARENT, pScript);\r\n\t\t\r\n\t\tp_parent->SetChildLockState(LOCK);\r\n\t\treturn true;\r\n\t}\r\n\telse if ( Checksum == CRCD(0x9492f814, \"GetProps\" ) )\r\n\t{\r\n\t\tWritePropertiesToStruct( pScript->GetParams() );\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn CObject::CallMemberFunction(Checksum, pParams, pScript);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tUpdate Procedure:\r\n\t\r\n\t(Recurse through all elements in tree, starting at root)\r\n\t\r\n\tFor each element:\r\n\t1. Update local position, scale, alpha\r\n\t2. Update summed position, scale, alpha\r\n\t3. Update: (optional)\r\n\t\t-properties of children\r\n\t\t-underlying CSprite or CText object(s)\r\n\t\t-underlying 3D object(s)\r\n\t\t-own base_w, base_h dimensions\r\n\t4. Run these steps on all children\r\n\r\n\tEvents may be launched at various points.\r\n*/\r\nvoid CScreenElement::UpdateProperties()\r\n{\r\n\t#ifdef __NOPT_ASSERT__\r\n\tdebug_verify_integrity();\r\n\t#endif\r\n\t//Dbg_MsgAssert(m_id && m_id != 0xDEADBEEF, (\"this screen element seems to have been deleted\"));\r\n\t\r\n\tTmr::Time current_time = Tmr::GetTime();\r\n\t\r\n\tAddReference();\r\n\t\r\n\t// for convenience -- once element is being used, we can assume it's locked\r\n\tSetChildLockState(LOCK);\r\n\t\r\n\t// only do expensive calculation when change occurs\r\n\tbool needs_summed_pos_calc = false;\r\n\r\n\t// Update 3D position, if any\r\n\tif (m_object_flags & CScreenElement::v3D_POS)\r\n\t{\r\n\t\tNx::CViewport *p_viewport = Nx::CViewportManager::sGetActiveViewport();\r\n\t\tDbg_MsgAssert(p_viewport, (\"Can't find an active viewport\"));\r\n\r\n\t\tfloat screen_pos_x, screen_pos_y;\r\n\t\tNx::ZBufferValue screen_pos_z;\r\n\t\tfloat scale_3d;\r\n\t\tscale_3d = p_viewport->TransformToScreenCoord(m_target_local_props.GetWorldPos(), screen_pos_x, screen_pos_y, screen_pos_z);\r\n\t\tif (scale_3d >= 0.0f)\r\n\t\t{\r\n\t\t\tm_target_local_props.SetScreenPos(screen_pos_x, screen_pos_y, screen_pos_z);\r\n\t\t\tSetScale(scale_3d, scale_3d, true);\t\t// set to relative scale\r\n\t\t\tm_object_flags &= ~CScreenElement::v3D_CULLED;\r\n\t\t} else {\r\n\t\t\tm_target_local_props.SetScreenPos(-320.0f, -224.0f);\r\n\t\t\tm_object_flags |= CScreenElement::v3D_CULLED;\r\n\t\t}\r\n\t\tcompute_ul_pos(m_target_local_props);\r\n\r\n\t\tif (mp_parent)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(!(mp_parent->m_object_flags & CScreenElement::v3D_POS), (\"Can't handle having 3D parent\"));\r\n\t\t}\r\n\r\n\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t}\r\n\r\n\t// continue animation of this element\r\n\tif ((m_object_flags & vNEEDS_LOCAL_POS_CALC) && !(m_object_flags & vMORPHING_PAUSED2))\r\n\t{\r\n\t\tif (m_key_time)\r\n\t\t{\r\n\t\t\tfloat pct_changed = (float) (current_time - m_base_time) / (float) m_key_time;\r\n\t\t\t// if element has reached its new destination, end animation\r\n\t\t\tif (current_time - m_base_time >= m_key_time)\r\n\t\t\t{\r\n\t\t\t\tpct_changed = 1.0f;\r\n\t\t\t\tm_key_time = 0;\r\n\t\t\t}\r\n\t\r\n\t\t\tfloat motion_grad;\r\n\t\t\tint anim_type = ((m_object_flags >> vANIM_FIRST_BIT) & vANIM_BIT_MASK);\r\n\t\t\tswitch (anim_type)\r\n\t\t\t{\r\n\t\t\t\tcase vANIM_FAST_OUT:\r\n\t\t\t\t\tmotion_grad = 2.0f * pct_changed - pct_changed * pct_changed;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vANIM_FAST_IN:\r\n\t\t\t\t\tmotion_grad = pct_changed * pct_changed;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vANIM_SLOW_INOUT:\r\n\t\t\t\t\tmotion_grad = (3.0f - 2.0f * pct_changed) * pct_changed * pct_changed;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tmotion_grad = pct_changed;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tfloat motion_inc = (motion_grad - m_last_motion_grad) / (1.0f - m_last_motion_grad);\r\n\t\t\tfloat pct_changed_inc = (pct_changed - m_last_pct_changed) / (1.0f - m_last_pct_changed);\r\n\t\t\tm_local_props.SetScreenPos(m_local_props.GetScreenPosX() + (m_target_local_props.GetScreenPosX() - m_local_props.GetScreenPosX()) * motion_inc, \r\n\t\t\t\t\t\t\t\t\t   m_local_props.GetScreenPosY() + (m_target_local_props.GetScreenPosY() - m_local_props.GetScreenPosY()) * motion_inc);\r\n\t\t\tm_local_props.SetScale(m_local_props.GetScaleX() + (m_target_local_props.GetScaleX() - m_local_props.GetScaleX()) * pct_changed_inc,\r\n\t\t\t\t\t\t\t\t   m_local_props.GetScaleY() + (m_target_local_props.GetScaleY() - m_local_props.GetScaleY()) * pct_changed_inc);\r\n\t\t\t\r\n\t\t\tm_local_props.SetRotate( m_local_props.GetRotate() + ( m_target_local_props.GetRotate() - m_local_props.GetRotate() ) * pct_changed_inc);\r\n\t\t\t\r\n\t\t\tm_local_props.alpha = m_local_props.alpha + (m_target_local_props.alpha - m_local_props.alpha) * pct_changed_inc;\r\n\t\t\tcompute_ul_pos(m_local_props);\r\n\r\n\t\t\t// figure any new rgba values \r\n\t\t\tImage::RGBA current_rgba = m_local_props.GetRGBA();\r\n\t\t\tImage::RGBA target_rgba = m_target_local_props.GetRGBA();\r\n\t\t\tImage::RGBA new_rgba;\r\n\t\t\tnew_rgba.r = (int)( current_rgba.r + ( target_rgba.r - current_rgba.r ) * pct_changed_inc );\r\n\t\t\tnew_rgba.g = (int)( current_rgba.g + ( target_rgba.g - current_rgba.g ) * pct_changed_inc );\r\n\t\t\tnew_rgba.b = (int)( current_rgba.b + ( target_rgba.b - current_rgba.b ) * pct_changed_inc );\r\n\t\t\tnew_rgba.a = (int)( current_rgba.a + ( target_rgba.a - current_rgba.a ) * pct_changed_inc );\r\n\t\t\tm_local_props.SetRGBA( new_rgba );\r\n\t\t\t\r\n\t\t\tm_last_motion_grad = motion_grad;\r\n\t\t\tm_last_pct_changed = pct_changed;\r\n\t\t\r\n\t\t\t/*\r\n\t\t\tif (m_key_time == 0)\r\n\t\t\t{\r\n\t\t\t\t//m_local_props = m_target_local_props;\r\n\t\t\t\tm_local_props.ulx = m_local_props.x - m_local_props.scalex * m_base_w * (m_just_x + 1.0f) / 2.0f;\r\n\t\t\t\tm_local_props.uly = m_local_props.y - m_local_props.scaley * m_base_h * (m_just_y + 1.0f) / 2.0f;\r\n\t\t\t\tprintf(\"Hurk!! target UL=(%.2f,%.2f) local UL=(%.2f,%.2f)\\n\", \r\n\t\t\t\t\t   m_target_local_props.ulx, m_target_local_props.uly,\r\n\t\t\t\t\t   m_local_props.ulx, m_local_props.uly);\r\n\t\t\t}\r\n\t\t\t*/\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_local_props = m_target_local_props;\r\n\t\t\tm_object_flags &= ~vNEEDS_LOCAL_POS_CALC;\r\n\t\t}\r\n\t\tneeds_summed_pos_calc = true;\r\n\t\t\r\n\t\t/*\r\n\t\tif (GetID() == Script::GenerateCRC(\"test_h_menu\"))\r\n\t\t\tprintf(\"local_pos=(%.2f,%.2f), ul=(%.2f,%.2f), dims=(%.2f,%.2f)\\n\", \r\n\t\t\t\t   m_local_props.x, m_local_props.y, \r\n\t\t\t\t   m_local_props.ulx, m_local_props.uly, \r\n\t\t\t\t   m_base_w, m_base_h);\r\n\t\t*/\r\n\t} // end if\r\n\r\n\tif (mp_parent && (mp_parent->m_object_flags & vDID_SUMMED_POS_CALC))\r\n\t\tneeds_summed_pos_calc = true;\r\n\tm_object_flags &= ~vDID_SUMMED_POS_CALC;\r\n\t\r\n\tif (needs_summed_pos_calc)\r\n\t{\r\n\t\tif (mp_parent && !(m_object_flags & CScreenElement::v3D_POS))\r\n\t\t{\r\n\t\t\tm_summed_props.SetScale(m_local_props.GetScaleX() * mp_parent->m_summed_props.GetScaleX(),\r\n\t\t\t\t\t\t\t\t\tm_local_props.GetScaleY() * mp_parent->m_summed_props.GetScaleY());\r\n\t\t\tm_summed_props.SetScreenPos(mp_parent->m_summed_props.GetScreenUpperLeftX() + m_local_props.GetScreenPosX() * mp_parent->m_summed_props.GetScaleX(),\r\n\t\t\t\t\t\t\t\t\t\tmp_parent->m_summed_props.GetScreenUpperLeftY() + m_local_props.GetScreenPosY() * mp_parent->m_summed_props.GetScaleY());\r\n\t\t\tm_summed_props.alpha = m_local_props.alpha * mp_parent->m_summed_props.alpha;\r\n\t\t\tm_summed_props.SetScreenUpperLeft(mp_parent->m_summed_props.GetScreenUpperLeftX() + m_local_props.GetScreenUpperLeftX() * mp_parent->m_summed_props.GetScaleX(),\r\n\t\t\t\t\t\t\t\t\t\t\t  mp_parent->m_summed_props.GetScreenUpperLeftY() + m_local_props.GetScreenUpperLeftY() * mp_parent->m_summed_props.GetScaleY());\r\n\t\t}\r\n\t\telse\r\n\t\t\tm_summed_props = m_local_props;\r\n\t\tm_object_flags |= vDID_SUMMED_POS_CALC;\r\n\t} // end if\r\n\r\n\tupdate();\r\n\t\r\n\tm_object_flags &= ~vCHANGED_STATIC_PROPS;\r\n\tif (m_object_flags & vMORPHING_PAUSED)\r\n\t\tm_object_flags |= vMORPHING_PAUSED2;\r\n\r\n\t// update all children\r\n\t//CScreenElementPtr pChild = mp_child_list;\r\n\tCScreenElement * pChild = mp_child_list;\r\n\twhile(pChild)\r\n\t{\r\n\t\tpChild->UpdateProperties();\r\n\t\tpChild = pChild->GetNextSibling();\r\n\t}\r\n\r\n\tRemoveReference();\r\n}\r\n\r\n\r\n\r\n\r\nCScreenElementPtr CScreenElement::get_child_by_id_or_index(uint32 id, int *pIndex)\r\n{\r\n\tint count = 0;\r\n\tCScreenElementPtr pChild = mp_child_list;\r\n\twhile(pChild)\r\n\t{\r\n\t\t// if we are getting by index\r\n\t\tif (id == 0) \r\n\t\t{\r\n\t\t\tif (*pIndex == count)\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\t// if we are getting by ID\r\n\t\telse if (pChild->GetID() == id) \r\n\t\t{\r\n\t\t\t// save index\r\n\t\t\tif (pIndex)\r\n\t\t\t\t*pIndex = count;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tpChild = pChild->GetNextSibling();\r\n\t\tcount++;\r\n\t}\r\n\r\n\treturn pChild;\r\n}\r\n\r\n\r\nCScreenElementPtr CScreenElement::get_parent()\r\n{\r\n\treturn mp_parent;\r\n}\r\n\r\n\r\nCWindowElement * CScreenElement::get_window()\r\n{\r\n\tCScreenElement * p_parent = get_parent();\r\n\twhile (p_parent)\r\n\t{\r\n\t\tif (p_parent->GetType() == (sint) TYPE_WINDOW_ELEMENT)\r\n\t\t{\r\n\t\t\treturn static_cast<CWindowElement *>(p_parent);\r\n\t\t}\r\n\r\n\t\tp_parent = p_parent->get_parent();\r\n\t}\r\n\r\n\tDbg_MsgAssert(0, (\"Could not find window for CScreenElement.\"));\r\n\treturn NULL;\r\n}\r\n\r\n/*\r\n\tPrivate function, should not be called by anything except\r\n\tCScreenElementManager.\r\n*/\r\nvoid CScreenElement::set_parent(const CScreenElementPtr &pParent, EPosRecalc recalculatePosition)\r\n{\r\n\tif (pParent)\t\r\n\t{\r\n\t\tDbg_MsgAssert(!(pParent->m_object_flags & CScreenElement::vCHILD_LOCK), (\"can't add child %s -- locked parent - %s\", Script::FindChecksumName(m_id), Script::FindChecksumName( pParent->GetID())));\r\n\t\t//Ryan(\"parent of screen element %s is now %s\\n\", Script::FindChecksumName(GetID()), Script::FindChecksumName(pParent->GetID()));\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tif (pParent->GetType() == CScreenElement::TYPE_TEXT_BLOCK_ELEMENT)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(GetType() == CScreenElement::TYPE_TEXT_ELEMENT,(\"TextBlockElement %s parenting child %s that is NOT a CTextElement (it's %s)\\n\",\r\n\t\t\tScript::FindChecksumName(pParent->GetID()), Script::FindChecksumName(GetID()), Script::FindChecksumName(GetType())));\r\n\t\t}\r\n\t\t#endif\r\n\t}\r\n\r\n\r\n\r\n\tif (mp_parent)\r\n\t{\r\n\t\t// remove from existing parent's child list before setting new\r\n\t\t// (there are max. 5 references to remove)\r\n\t\t\r\n\t\t\r\n\t\tCScreenElementPtr p_elem = mp_parent->mp_child_list;\r\n\t\twhile(p_elem)\r\n\t\t{\r\n\t\t\tif (p_elem == this)\r\n\t\t\t{\r\n\t\t\t\tif (GetPrevSibling())\r\n\t\t\t\t{\r\n\t\t\t\t\tGetPrevSibling()->mp_next_sibling = GetNextSibling();\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// ref count won't change for next sibling, since was ref'd by this\r\n\t\t\t\t\tmp_parent->mp_child_list = GetNextSibling();\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (GetNextSibling())\r\n\t\t\t\t{\r\n\t\t\t\t\t// Either original parent or original prev sibling is now pointing to original next sibling\r\n\t\t\t\t\t// Would both add and remove a reference on next, but they cancel each other, so do nothing\r\n\r\n\t\t\t\t\tGetNextSibling()->mp_prev_sibling = GetPrevSibling();\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tp_elem = p_elem->GetNextSibling();\r\n\t\t}\r\n\t}\r\n\r\n\t// add to new parent's child list\r\n\t// (at end of list)\r\n\tmp_parent = pParent;\r\n\tif (mp_parent) \r\n\t{\r\n\t\tCScreenElementPtr p_prev_sib = mp_parent->GetFirstChild();\r\n\t\tif (p_prev_sib)\r\n\t\t{\r\n\t\t\twhile(p_prev_sib->GetNextSibling())\r\n\t\t\t\tp_prev_sib = p_prev_sib->GetNextSibling();\r\n\t\t\tp_prev_sib->mp_next_sibling = this;\r\n\t\t}\r\n\t\telse\r\n\t\t\tmp_parent->mp_child_list = this;\r\n\t\tmp_prev_sibling = p_prev_sib;\r\n\t}\r\n\telse\r\n\t\t// no parent, therefore no siblings\r\n\t\tmp_prev_sibling = NULL;\r\n\tmp_next_sibling = NULL;\r\n\r\n\tif (pParent)\r\n\t\tauto_set_z_priorities_recursive(pParent->m_z_priority + AUTO_Z_SPACE);\r\n\telse\r\n\t\tauto_set_z_priorities_recursive(0.0f);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\t...given element's dimensions, justification, scale, and target position.\r\n*/\r\nvoid CScreenElement::compute_ul_pos(ConcatProps &props)\r\n{\r\n\tprops.SetScreenUpperLeft(props.GetScreenPosX() - props.GetScaleX() * m_base_w * (m_just_x + 1.0f) / 2.0f,\r\n\t\t\t\t\t\t\t props.GetScreenPosY() - props.GetScaleY() * m_base_h * (m_just_y + 1.0f) / 2.0f);\r\n}\r\n\r\n\r\n\r\n\r\n// called by set_parent()\r\nvoid CScreenElement::auto_set_z_priorities_recursive(float topPriority)\r\n{\r\n\tif (!(m_object_flags & vCUSTOM_Z_PRIORITY))\r\n\t{\r\n\t\tm_object_flags |= vCHANGED_STATIC_PROPS;\r\n\t\tm_z_priority = topPriority;\r\n\t}\r\n\t\r\n\tCScreenElementPtr pChild = mp_child_list;\r\n\twhile(pChild)\r\n\t{\r\n\t\tpChild->auto_set_z_priorities_recursive(topPriority + AUTO_Z_SPACE);\r\n\t\tpChild = pChild->GetNextSibling();\r\n\t}\t\r\n}\r\n\r\n\r\n\r\n\r\n/* \r\n\tResolves position info stored in a script structure:\r\n\t\r\n\tpos=(x y)\r\n\tpos={relative (x y)}\r\n\tpos={proportional (x y)}\r\n\t\r\n\tReturns false if no position info found.\r\n*/\r\nbool CScreenElement::resolve_pos(Script::CStruct *pProps, float *pX, float *pY)\r\n{\r\n\tScript::CPair pos_pair;\r\n\tScript::CStruct *p_pos_struct;\r\n\tif (pProps->GetStructure(CRCD(0x7f261953,\"pos\"), &p_pos_struct))\r\n\t{\r\n\t\tp_pos_struct->GetPair(NONAME, &pos_pair, true);\r\n\t\tif (p_pos_struct->ContainsFlag(0x91a4c826)) // \"relative\"\r\n\t\t{\r\n\t\t\t*pX = m_target_local_props.GetScreenPosX() + pos_pair.mX;\r\n\t\t\t*pY = m_target_local_props.GetScreenPosY() + pos_pair.mY;\r\n\t\t}\r\n\t\telse if (p_pos_struct->ContainsFlag(0xb922906a)) // \"proportional\"\r\n\t\t{\r\n\t\t\tDbg_Assert(mp_parent);\r\n\t\t\t*pX = pos_pair.mX * mp_parent->GetBaseW();\r\n\t\t\t*pY = pos_pair.mY * mp_parent->GetBaseH();\r\n\t\t}\r\n\t\telse\r\n\t\t\tDbg_MsgAssert(0, (\"position needs 'relative' or 'proportional' flag\"));\r\n\t\treturn true;\r\n\t}\t\r\n\telse if (pProps->GetPair(CRCD(0x7f261953,\"pos\"), &pos_pair))\r\n\t{\r\n\t\t*pX = pos_pair.mX;\r\n\t\t*pY = pos_pair.mY;\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\n/* \r\n\tResolves justification info stored in a script structure, e.g.:\r\n\t\r\n\tjust=[left top]\r\n\tjust=[center center]\r\n\tjust=[right bottom]\r\n\tjust=(-1.0 1.0)\r\n\tjust=(.65 3.75)\r\n\t\r\n\tReturns false if no justification info found.\r\n*/\r\nbool CScreenElement::resolve_just(Script::CStruct *pProps, const uint32 RefName, float *pHJust, float *pVJust)\r\n{\r\n\tScript::CArray *p_just;\r\n\tif (pProps->GetArray(RefName, &p_just))\r\n\t{\r\n\t\tScript::ESymbolType type = (Script::ESymbolType) p_just->GetType();\r\n\t\tswitch(type)\r\n\t\t{\r\n\t\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\t\t*pHJust = p_just->GetFloat(0);\r\n\t\t\t\t*pVJust = p_just->GetFloat(1);\r\n\t\t\t\tbreak;\r\n\t\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t\t{\r\n\t\t\t\tfloat just[2];\r\n\t\t\t\tfor (int i = 0; i < 2; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 crc = p_just->GetNameChecksum(i); \r\n\t\t\t\t\tif (crc == CRCD(0x85981897, \"left\") || crc == CRCD(0xe126e035, \"top\"))\r\n\t\t\t\t\t\tjust[i] = -1.0f;\r\n\t\t\t\t\telse if (crc == CRCD(0x4b358aeb, \"right\") || crc == CRCD(0x76a08d5b, \"bottom\"))\r\n\t\t\t\t\t\tjust[i] = 1.0f;\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tjust[i] = 0;\r\n\t\t\t\t}\r\n\t\t\t\t*pHJust = just[0];\r\n\t\t\t\t*pVJust = just[1];\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(0, (\"wrong type for justification\"));\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tRetrieves RGBA information from a script struct.\r\n*/\r\nbool CScreenElement::resolve_rgba(Script::CStruct *pProps, const uint32 RefName, Image::RGBA *pRGBA)\r\n{\r\n\tScript::CArray *p_color;\r\n\tif (pProps->GetArray(RefName, &p_color))\r\n\t{\r\n\t\tuint32 rgba = 0;\r\n\t\tint size = p_color->GetSize();\r\n\t\tDbg_MsgAssert(size >= 3 && size <= 4, (\"wrong size %d for color array\", size));\r\n\t\tfor (int i = 0; i < size; i++) \r\n\t\t{\r\n\t\t\trgba |= (p_color->GetInteger(i) & 255) << (i*8);\r\n\t\t}\r\n#ifdef __PLAT_NGC__\r\n\t\trgba = ( ( rgba & 0xff000000 ) >> 24 ) | ( ( rgba & 0xff0000 ) >> 8 ) | ( ( rgba & 0xff00 ) << 8 ) | ( ( rgba & 0xff ) << 24 );\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t*pRGBA = *((Image::RGBA *) &rgba);\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\n#ifdef __NOPT_ASSERT__\r\n/*\r\n\tUsed to verify that screen element has not been corrupted.\r\n*/\r\nvoid CScreenElement::debug_verify_integrity()\r\n{\r\n\t\r\n// Mick - Removed for now, as it's taking up rather a lot of time....\t\r\n\treturn;\r\n\t\r\n\tDbg_MsgAssert(Mem::Valid(this), (\"not a valid block!\"));\r\n\tDbg_MsgAssert(m_id, (\"screen element has id of 0, that shouldn't happen\"));\r\n\tDbg_MsgAssert(m_id != 0xDEADBEEF, (\"screen element has been deleted\"));\r\n\r\n\tCScreenElementManager* p_manager = CScreenElementManager::Instance();\r\n\tCScreenElementPtr p_in_tracker = p_manager->GetElement(m_id);\r\n\tDbg_MsgAssert(p_in_tracker == this, (\"this element seems to have been lost from tracking\"));\r\n\t\r\n\tif (mp_parent)\r\n\t{\r\n\t\tDbg_MsgAssert(!((uint) mp_parent.Convert() & 3), (\"parent has goofy address\"));\r\n\t\tDbg_MsgAssert(Mem::Valid(mp_parent), (\"parent not a valid block!\"));\r\n\t\tCScreenElementPtr p_sib = mp_parent->mp_child_list;\r\n\t\twhile(p_sib)\r\n\t\t{\r\n\t\t\tif (p_sib == this)\r\n\t\t\t\tbreak;\r\n\t\t\tp_sib = p_sib->GetNextSibling();\r\n\t\t}\r\n\t\tDbg_MsgAssert(p_sib, (\"this element not in its parent's child list\"));\r\n\t}\r\n\r\n\tCScreenElementPtr p_child = mp_child_list;\r\n\twhile(p_child)\r\n\t{\r\n\t\tDbg_MsgAssert(!((uint) (p_child.Convert()) & 3), (\"child has goofy address\"));\r\n\t\tDbg_MsgAssert(Mem::Valid(p_child), (\"child not a valid block!\"));\r\n\t\tDbg_MsgAssert(p_child->mp_parent == this, (\"this element not parent of child\"));\r\n\t\tp_child = p_child->GetNextSibling();\r\n\t}\r\n}\r\n#endif\r\n\r\n\r\n\r\n\r\nCContainerElement::CContainerElement()\r\n{\r\n\t//Ryan(\"I am a new CContainerElement\\n\");\r\n\tm_focusable_child = 0;\r\n\r\n\tSetType(CScreenElement::TYPE_CONTAINER_ELEMENT);\r\n}\r\n\r\n\r\n\r\n\r\nCContainerElement::~CContainerElement()\r\n{\r\n\t//Ryan(\"Destroying CContainerElement\\n\");\r\n}\r\n\r\n\r\n\r\n\r\nvoid CContainerElement::SetProperties(Script::CStruct *pProps)\r\n{\r\n\tpProps->GetChecksum(\"focusable_child\", &m_focusable_child);\r\n\t\r\n\tCScreenElement::SetProperties(pProps);\r\n}\r\n\r\n\r\n\r\n\r\nbool CContainerElement::PassTargetedEvent(Obj::CEvent *pEvent, bool broadcast)\r\n{\r\n\tif (!Obj::CObject::PassTargetedEvent(pEvent))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tif (pEvent->GetType() == Obj::CEvent::TYPE_FOCUS || pEvent->GetType() == Obj::CEvent::TYPE_UNFOCUS)\r\n\t{\r\n\t\t// forward events of these types to specified focusable child\r\n\t\tif (m_focusable_child) \r\n\t\t{\r\n\t\t\tint controller = Obj::CEvent::sExtractControllerIndex(pEvent);\r\n\t\t\tScript::CStruct data;\r\n\t\t\tdata.AddInteger(CRCD(0xb30d9965,\"controller\"), controller);\r\n\r\n\t\t\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\t\t\tp_tracker->LaunchEvent(pEvent->GetType(), m_focusable_child, Obj::CEvent::vSYSTEM_EVENT, &data);\r\n\t\t}\r\n\t\tpEvent->MarkHandled(m_id);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool CScreenElement::EventsBlocked()\r\n{\r\n\t// recurse back up through the parents to find any parent that is hidden\r\n\tif ( ( m_object_flags & vEVENTS_BLOCKED) || ( mp_parent && mp_parent->EventsBlocked() ) )\r\n\t\t return true;\r\n\treturn false;\r\n}\r\n\r\nbool CScreenElement::IsHidden()\r\n{\r\n\t// recurse back up through the parents to find any parent that is hidden\r\n\tif ( ( m_object_flags & vHIDDEN ) || ( mp_parent && mp_parent->IsHidden() ) )\r\n\t\t return true;\r\n\treturn false;\r\n}\r\n\r\n} // end namespace\r\n"
  },
  {
    "path": "Code/Gfx/2D/ScreenElement2.h",
    "content": "#ifndef __GFX_2D_SCREENELEMENT2_H__\r\n#define __GFX_2D_SCREENELEMENT2_H__\r\n\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n#include <gel/event.h>\r\n\r\n#include <gfx/image/imagebasic.h>\r\n#include <gfx/NxViewport.h>\r\n\r\n\r\nnamespace Front\r\n{\r\n\r\nclass CScreenElement;\r\nclass CWindowElement;\r\ntypedef Obj::CSmtPtr<CScreenElement> CScreenElementPtr;\r\n\r\n\r\n\r\n\r\n/*\r\n\tThe base class for all screen elements. Screen elements include things like onscreen text, HUD sprites,\r\n\titems in menus, etc. Every screen element has 2D coordinates and (rectangular) dimensions. Screen elements\r\n\tcan be \"children\" of other screen elements, whereby the child uses coordinates relative the upper left corner\r\n\tof the parent. If the parent is moved, all its children will be moved along with it.\r\n\t\r\n\tA screen element also has a pair of scale values, which are independent of its base width and height. A\r\n\tscreen element will generally have a fixed base width and height, but the scale can be varied for animation\r\n\tpurposes, making the element appear to grow or shrink in size. Scale changes to an element are also passed to\r\n\tchildren.\r\n\t\r\n\tThe same idea applies to alpha and RGBA. RGBA is a static setting for the screen element, but alpha is a \r\n\tseparate morpheable multiplier that can be used for animation.  \r\n*/\r\nclass CScreenElement : public Obj::CObject\r\n{\r\n\tfriend class CScreenElementManager;\r\n\r\npublic:\r\n\r\n\tenum EScreenElementType\r\n\t{\r\n\t\tTYPE_CONTAINER_ELEMENT\t\t\t\t\t\t= 0x5b9da842,\r\n\t\tTYPE_TEXT_ELEMENT\t\t\t\t\t\t\t= 0x5200dfb6,\r\n\t\tTYPE_VMENU\t\t\t\t\t\t\t\t\t= 0x130ef802,\r\n\t\tTYPE_HMENU\t\t\t\t\t\t\t\t\t= 0xccded1e1,\r\n\t\tTYPE_TEXT_BLOCK_ELEMENT\t\t\t\t\t\t= 0x40d92263,\r\n\t\tTYPE_SPRITE_ELEMENT\t\t\t\t\t\t\t= 0xb12b510a,\r\n\t\tTYPE_VSCROLLING_MENU\t\t\t\t\t\t= 0x84298a3c,\r\n\t\tTYPE_HSCROLLING_MENU\t\t\t\t\t\t= 0x2900e3d0,\r\n\t\tTYPE_ELEMENT_3D\t\t\t\t\t\t\t\t= 0x82c59d78,\r\n\t\tTYPE_WINDOW_ELEMENT\t\t\t\t\t\t\t= 0xa13adbb7,\r\n\t};\r\n\r\n\tenum EPosRecalc\r\n\t{\r\n\t\tvDONT_RECALC_POS\t= 0,\r\n\t\tvRECALC_POS\t\t\t= 1,\r\n\t};\r\n\t\r\n\t// flags 8-23 belong to CScreenElement, 24-31 can be used by subclasses\r\n\tenum \r\n\t{\r\n\t\t// One of these values will fill bits 8-9\r\n\t\t// in m_object_flags\r\n\t\tvANIM_LINEAR\t\t= 0,\r\n\t\tvANIM_FAST_OUT\t\t= 1,\r\n\t\tvANIM_FAST_IN \t\t= 2,\r\n\t\tvANIM_SLOW_INOUT\t= 3,\r\n\t\tvANIM_FIRST_BIT\t\t= 8,\r\n\t\tvANIM_BIT_MASK\t\t= 3,\r\n\t\t\r\n\t\t/* \r\n\t\t\tShould be set whenever one of the following changes:\r\n\t\t\t\t-a morpheable property (pos, alpha, scale, etc...)\r\n\t\t\t\t-active morph time\r\n\t\t\t\t-justification\r\n\t\t\t\t-base width, height\r\n\t\t\t\t\r\n\t\t\tUpdateProperties() will respond by calculating current morph frame,\r\n\t\t\tOnce element has finished morph, flag will be turned off.\r\n\t\t*/ \r\n\t\tvNEEDS_LOCAL_POS_CALC \t= (1<<10),\r\n\t\t/*\r\n\t\t\tSet by UpdatePropertie\r\n\t\t\ts() after fresh absolute morph attributes (pos, scale, alpha,\r\n\t\t\tetc.) are computed. This happens a) after new morph frame calculated for element, or\r\n\t\t\tb) after new absolute morph attributes computed for parent.\r\n\t\t\r\n\t\t\tCleared upon next call to UpdateProperties (if not set again). Can be used by update()\r\n\t\t\tto decide whether or not to do expensive calculations that are only necessary when\r\n\t\t\telement moves.\r\n\t\t*/\r\n\t\tvDID_SUMMED_POS_CALC \t= (1<<11),\r\n\t\t/* \r\n\t\t\tShould be set when change made to a static property (i.e. a non-morpheable one).\r\n\t\t\tVirtual update() function can use to decide whether or not to do expensive\r\n\t\t\tcalculation.\r\n\t\t\t\r\n\t\t\tCleared by UpdateProperties() after call to virtual update() function\r\n\t\t*/\r\n\t\tvCHANGED_STATIC_PROPS \t= (1<<12),\r\n\t\t// if set dimensions have been set from outside, don't allow to resize self\r\n\t\tvFORCED_DIMS\t\t\t= (1<<13),\r\n\t\t// can't add children if this flags is set\r\n\t\tvCHILD_LOCK\t\t\t\t= (1<<14),\r\n\t\t// if set, this element (and all its children) will\r\n\t\tvCUSTOM_Z_PRIORITY\t\t= (1<<15),\r\n\t\tvIS_SCREEN_ELEMENT\t\t= (1<<16),\r\n\t\tvMORPHING_PAUSED\t\t= (1<<17),\r\n\t\tvMORPHING_PAUSED2\t\t= (1<<18), // a second stage is necessary to allow one update\r\n\t\tv3D_POS\t\t\t\t\t= (1<<19), // Element is in 3D space\r\n\t\tv3D_CULLED\t\t\t\t= (1<<20), // Element in 3D space is culled\r\n\t\tvEVENTS_BLOCKED\t\t\t= (1<<21), // Element is not accepting any events\r\n\t\tvHIDDEN\t\t\t\t\t= (1<<22), // Element is hiddden\r\n\t};\r\n\t\r\n\t/* \r\n\t\tThese are properties which can be concatenated down the parent-child tree.\r\n\t\t\r\n\t\tThere are local properties (relative to parent), and absolute properties\r\n\t\t(concatenation of own local properties with all those of ancestors).\r\n\t*/\r\n\tstruct ConcatProps\r\n\t{\r\n\tpublic:\r\n\t\tvoid\t\t\t\tSetScreenPos(float x, float y);\r\n\t\tvoid\t\t\t\tSetScreenPos(float x, float y, Nx::ZBufferValue z);\r\n\t\tvoid\t\t\t\tSetScreenUpperLeft(float x, float y);\r\n\t\tvoid\t\t\t\tSetWorldPos(const Mth::Vector & pos);\r\n\t\tvoid\t\t\t\tSetScale(float scale_x, float scale_y);\r\n\t\tvoid\t\t\t\tSetAbsoluteScale(float scale_x, float scale_y);\r\n\r\n\t\tvoid\t\t\t\tSetRotate( float rot );\r\n\t\tvoid\t\t\t\tSetRGBA( Image::RGBA rgba );\r\n\r\n\t\tfloat\t\t\t\tGetScreenPosX() const;\r\n\t\tfloat\t\t\t\tGetScreenPosY() const;\r\n\t\tNx::ZBufferValue\tGetScreenPosZ() const;\r\n\t\tfloat\t\t\t\tGetScreenUpperLeftX() const;\r\n\t\tfloat\t\t\t\tGetScreenUpperLeftY() const;\r\n\t\tconst Mth::Vector &\tGetWorldPos() const;\r\n\t\tfloat\t\t\t\tGetScaleX() const;\r\n\t\tfloat\t\t\t\tGetScaleY() const;\r\n\t\tfloat\t\t\t\tGetAbsoluteScaleX() const;\r\n\t\tfloat\t\t\t\tGetAbsoluteScaleY() const;\r\n\t\t\r\n\t\tfloat\t\t\t\tGetRotate() const;\r\n\t\tImage::RGBA\t\t\tGetRGBA() const;\r\n\r\n\t\t// These values do not need to be protected, since they aren't treated differently in 3D\r\n\r\n\t\t// Alpha value\r\n\t\tfloat\t\t\t\talpha;\r\n\r\n\tprivate:\r\n\t\t// 3D position of anchor point\r\n\t\tMth::Vector\t\t\tworld_pos;\r\n\r\n\t\t// 2D position of anchor point\r\n\t\tfloat\t\t\t\tscreen_x, screen_y;\r\n\t\tNx::ZBufferValue\tscreen_z;\t\t\t\t// If using z-buffer sorting\r\n\r\n\t\t// position of upper-left hand corner (for quick lookup)\r\n\t\tfloat\t\t\t\tulx, uly;\r\n\r\n\t\t// final render scale\r\n\t\tfloat\t\t\t\tscalex, scaley;\r\n\t\t\r\n\t\t// absolute scale used for calling DoMorph with a relative scale and now for 3D positions\r\n\t\tfloat\t\t\t\tabsoluteScalex;\r\n\t\tfloat\t\t\t\tabsoluteScaley;\r\n\r\n\t\tfloat\t\t\t\tm_rot_angle;\r\n\t\tImage::RGBA\t\t\tm_rgba;\r\n\t};\r\n\r\n\tstatic const float vJUST_LEFT;\r\n\tstatic const float vJUST_TOP;\r\n\tstatic const float vJUST_CENTER;\r\n\tstatic const float vJUST_RIGHT;\r\n\tstatic const float vJUST_BOTTOM;\r\n\r\n\t\t\t\t\t\t\tCScreenElement();\r\n\tvirtual\t\t\t\t\t~CScreenElement();\r\n\r\n\t// \"absolute\" means concatenated\r\n\tfloat\t\t\t\t\tGetAbsX();\r\n\tfloat\t\t\t\t\tGetAbsY();\r\n\tfloat\t\t\t\t\tGetAbsW();\r\n\tfloat\t\t\t\t\tGetAbsH();\r\n\tfloat \t\t\t\t\tGetBaseW() {return m_base_w;}\r\n\tfloat \t\t\t\t\tGetBaseH() {return m_base_h;}\r\n\tfloat\t\t\t\t\tGetScaleX() {return m_local_props.GetScaleX();}\r\n\tfloat\t\t\t\t\tGetScaleY() {return m_local_props.GetScaleY();}\r\n\tvoid\t\t\t\t\tGetLocalPos(float *pX, float *pY);\r\n\tvoid\t\t\t\t\tGetLocalULPos(float *pX, float *pY);\r\n\tvoid\t\t\t\t\tGetJust(float *pJustX, float *pJustY);\r\n\t\r\n\tenum EForceInstant\r\n\t{\r\n\t\tDONT_FORCE_INSTANT\t= 0,\r\n\t\tFORCE_INSTANT,\r\n\t};\r\n\tvoid\t\t\t\t\tSetPos(float x, float y, EForceInstant forceInstant = DONT_FORCE_INSTANT);\r\n\tvoid\t\t\t\t\tSetPos3D(const Mth::Vector &pos3D, EForceInstant forceInstant = DONT_FORCE_INSTANT);\r\n\tenum EForceDims\r\n\t{\r\n\t\tDONT_FORCE_DIMS\t\t= 0,\r\n\t\tFORCE_DIMS,\r\n\t};\r\n\tvoid\t\t\t\t\tSetDims(float w, float h, EForceDims force = DONT_FORCE_DIMS);\r\n\tvoid\t\t\t\t\tSetJust(float justX, float justY);\r\n\tvoid\t\t\t\t\tSetScale(float scaleX, float scaleY, bool relative = false, EForceInstant forceInstant = DONT_FORCE_INSTANT);\r\n\tvoid\t\t\t\t\tSetAlpha(float alpha, EForceInstant forceInstant = DONT_FORCE_INSTANT);\r\n\tvoid\t\t\t\t\tSetAnimTime(Tmr::Time animTime);\r\n\tvoid\t\t\t\t\tSetRGBA( Image::RGBA rgba, EForceInstant forceInstant = FORCE_INSTANT );\r\n\tvoid\t\t\t\t\tSetZPriority(float zPriority);\r\n\tvoid\t\t\t\t\tSetMorphPausedState(bool pause);\r\n\r\n\tenum ELockState\r\n\t{\r\n\t\tUNLOCK,\r\n\t\tLOCK,\r\n\t};\r\n\tvoid\t\t\t\t\tSetChildLockState(ELockState lockState);\r\n\r\n\t// These don't need to return smart pointers\t\r\n\tCScreenElement*\t\tGetFirstChild() {return mp_child_list;}\r\n\tCScreenElement*\t\tGetLastChild();\r\n\tCScreenElement*\t\tGetPrevSibling() {return mp_prev_sibling;}\r\n\tCScreenElement*\t\tGetNextSibling() {return mp_next_sibling;}\r\n\tCScreenElement*\t\tGetChildById(uint32 id, int *pIndex = NULL);\r\n\tCScreenElement*\t\tGetChildByIndex(int index);\r\n\t\r\n\tint\t\t\t\t\t\tCountChildren();\r\n\t\r\n\t// See notes before function definition\r\n\tvoid\t\t\t\t\tUpdateProperties();\r\n  \t//void\t\t\t\t\tDraw();\r\n\r\n\t/* \r\n\t\tVersions of SetProperties(), SetMorph(), CallMemberFunction() in subclasses \r\n\t\tshould call versions in this class.\r\n\t*/\r\n\tvirtual void\t\t\tSetProperties(Script::CStruct *pProps);\r\n\tvirtual void\t\t\tWritePropertiesToStruct( Script::CStruct *pStruct );\r\n\tvirtual void\t\t\tSetMorph(Script::CStruct *pProps);\r\n\tvirtual bool \t\t\tCallMemberFunction( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\n\tbool\t\t\t\t\tEventsBlocked();\r\n\tbool\t\t\t\t\tIsHidden();\r\n\r\nprotected:\r\n\r\n\tCScreenElementPtr\t\tget_child_by_id_or_index(uint32 id, int *pIndex);\r\n\tCScreenElementPtr\t\tget_parent();\r\n\tCWindowElement *\t\tget_window();\r\n\tvoid\t\t\t\t\tset_parent(const CScreenElementPtr &pParent, EPosRecalc recalculatePosition = vRECALC_POS);\r\n\tvoid\t\t\t\t\tcompute_ul_pos(ConcatProps &props);\r\n\tvoid\t\t\t\t\tauto_set_z_priorities_recursive(float topPriority);\r\n\t\r\n\tbool\t\t\t\t\tresolve_pos(Script::CStruct *pProps, float *pX, float *pY);\r\n\tbool\t\t\t\t\tresolve_just(Script::CStruct *pProps, const uint32 RefName, float *pHJust, float *pVJust);\r\n\tbool\t\t\t\t\tresolve_rgba(Script::CStruct *pProps, const uint32 RefName, Image::RGBA *pRGBA);\r\n\t\r\npublic:\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\t// a debugging function\r\n\tvoid\t\t\t\t\tdebug_verify_integrity();\r\n\t#endif\r\nprotected:\r\n\t\r\n\t/* \r\n\t\tSee notes on UpdateProperties() about what this function can do.\r\n\t\t\r\n\t\tWhat it *CAN'T* do:\r\n\t\t-use the summed pos values from children (these will be a frame out of date)\r\n\t\t-changed the properties of the parent (the changes won't be converted to\r\n\t\t\tlocal and summed positions until the next frame)\r\n\t*/\r\n\tvirtual void\t\t\tupdate() {;}\r\n\t\r\n\tCScreenElementPtr\t\tmp_parent;\r\n\tCScreenElementPtr\t\tmp_child_list;\r\n\tCScreenElementPtr\t\tmp_next_sibling;\r\n\tCScreenElementPtr\t\tmp_prev_sibling;\r\n\t\r\n\tConcatProps\t\t\t\tm_local_props;\r\n\tConcatProps\t\t\t\tm_target_local_props;\r\n\r\n\tTmr::Time\t\t\t\tm_base_time;\r\n\t// how much time must elapse since m_base_time for animation to end\r\n\t// set to 0 when animation complete\r\n\tTmr::Time\t\t\t\tm_key_time;\r\n\tfloat\t\t\t\t\tm_last_motion_grad;\r\n\tfloat\t\t\t\t\tm_last_pct_changed;\r\n\t\r\n\t// the concatenation of local props in ancestors and this\r\n\tConcatProps\t\t\t\tm_summed_props;\r\n\r\n\t// determines offset of upper-left corner of screen element\r\n\t// relative\tto anchor point\r\n\t// -1.0\t= left/top\r\n\t//\t0\t= center\r\n\t//  1.0\t= bottom/right\r\n\tfloat\t\t\t\t\tm_just_x, m_just_y;\r\n\t\r\n\t// the dimensions of this screen element before scaling is applied\r\n\t// (in pixels) (local)\r\n\tfloat\t\t\t\t\tm_base_w, m_base_h;\r\n\r\n\tImage::RGBA\t\t\t\tm_rgba;\r\n\r\n\tstatic const float\t\tAUTO_Z_SPACE;\r\n\t\r\n\tfloat\t\t\t\t\tm_z_priority;\r\n\r\n\t// TODO: temp hack to get preserve_original_alpha and restore_original_alpha working\r\n\tfloat\t\t\t\t\tm_originalAlpha;\r\n};\r\n\r\n\r\n\r\n\r\nclass CContainerElement : public CScreenElement\r\n{\r\n\tfriend class CScreenElementManager;\r\n\r\npublic:\r\n\t\t\t\t\t\t\tCContainerElement();\r\n\tvirtual\t\t\t\t\t~CContainerElement();\r\n\r\n\tvoid\t\t\t\t\tSetProperties(Script::CStruct *pProps);\r\n\tvirtual bool\t\t\tPassTargetedEvent(Obj::CEvent *pEvent, bool broadcast = false);\r\n\t\r\nprotected:\r\n\r\n\tuint32\t\t\t\t\tm_focusable_child;\r\n};\r\n\r\n\r\ninline void\t\t\t\t\tCScreenElement::ConcatProps::SetScreenPos(float x, float y)\r\n{\r\n\tscreen_x = x;\r\n\tscreen_y = y;\r\n}\r\n\r\ninline void\t\t\t\t\tCScreenElement::ConcatProps::SetScreenPos(float x, float y, Nx::ZBufferValue z)\r\n{\r\n\tSetScreenPos(x, y);\r\n\tscreen_z = z;\r\n}\r\n\r\ninline void\t\t\t\t\tCScreenElement::ConcatProps::SetScreenUpperLeft(float x, float y)\r\n{\r\n\tulx = x;\r\n\tuly = y;\r\n}\r\n\r\ninline void\t\t\t\t\tCScreenElement::ConcatProps::SetWorldPos(const Mth::Vector & pos)\r\n{\r\n\tworld_pos = pos;\r\n}\r\n\r\ninline void\t\t\t\t\tCScreenElement::ConcatProps::SetScale(float scale_x, float scale_y)\r\n{\r\n\tscalex = scale_x;\r\n\tscaley = scale_y;\r\n}\r\n\r\ninline void\t\t\t\t\tCScreenElement::ConcatProps::SetAbsoluteScale(float scale_x, float scale_y)\r\n{\r\n\tabsoluteScalex = scale_x;\r\n\tabsoluteScaley = scale_y;\r\n}\r\n\r\ninline void\t\t\t\t\tCScreenElement::ConcatProps::SetRotate( float rot_angle )\r\n{\r\n\tm_rot_angle = rot_angle;\r\n}\r\n\r\ninline void\t\t\t\t\tCScreenElement::ConcatProps::SetRGBA( Image::RGBA rgba )\r\n{\r\n\tm_rgba.r = rgba.r;\r\n\tm_rgba.g = rgba.g;\r\n\tm_rgba.b = rgba.b;\r\n\tm_rgba.a = rgba.a;\r\n}\r\n\r\ninline float\t\t\t\tCScreenElement::ConcatProps::GetScreenPosX() const\r\n{\r\n\treturn screen_x;\r\n}\r\n\r\ninline float\t\t\t\tCScreenElement::ConcatProps::GetScreenPosY() const\r\n{\r\n\treturn screen_y;\r\n}\r\n\r\ninline Nx::ZBufferValue\t\tCScreenElement::ConcatProps::GetScreenPosZ() const\r\n{\r\n\treturn screen_z;\r\n}\r\n\r\ninline float\t\t\t\tCScreenElement::ConcatProps::GetScreenUpperLeftX() const\r\n{\r\n\treturn ulx;\r\n}\r\n\r\ninline float\t\t\t\tCScreenElement::ConcatProps::GetScreenUpperLeftY() const\r\n{\r\n\treturn uly;\r\n}\r\n\r\ninline const Mth::Vector &\tCScreenElement::ConcatProps::GetWorldPos() const\r\n{\r\n\treturn world_pos;\r\n}\r\n\r\ninline float\t\t\t\tCScreenElement::ConcatProps::GetScaleX() const\r\n{\r\n\treturn scalex;\r\n}\r\n\r\ninline float\t\t\t\tCScreenElement::ConcatProps::GetScaleY() const\r\n{\r\n\treturn scaley;\r\n}\r\n\r\ninline float\t\t\t\tCScreenElement::ConcatProps::GetAbsoluteScaleX() const\r\n{\r\n\treturn absoluteScalex;\r\n}\r\n\r\ninline float\t\t\t\tCScreenElement::ConcatProps::GetAbsoluteScaleY() const\r\n{\r\n\treturn absoluteScaley;\r\n}\r\n\r\ninline float\t\t\t\tCScreenElement::ConcatProps::GetRotate() const\r\n{\r\n\treturn m_rot_angle;\r\n}\r\n\r\ninline Image::RGBA\t\t\tCScreenElement::ConcatProps::GetRGBA() const\r\n{\r\n\treturn m_rgba;\r\n}\r\n\r\n\r\n\r\n} // end namespace\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/2D/ScrollingMenu.cpp",
    "content": "#include <core/defines.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/Event.h>\r\n#include <gfx/2D/ScrollingMenu.h>\r\n#include <gfx/2D/Menu2.h>\r\n\r\nnamespace Front\r\n{\r\n\r\n\r\n\r\n\r\nCBaseScrollingMenu::CBaseScrollingMenu()\r\n{\r\n\tRegisterWithTracker(this);\r\n\tmp_the_menu = NULL;\r\n\tm_selected_element_id = 0;\r\n\r\n\tm_in_focus = false;\r\n\tm_needs_update = false;\r\n\r\n\tm_top_or_left_line = 0.0f;\r\n\t// a very large number\r\n\tm_scroll_speed = 10000.0f;\r\n\r\n\tm_num_items_to_display = -1;\r\n\tm_window_dimension = 0.0f;\r\n\tm_regular_space_amount = -1.0f;\r\n\t\r\n\tSetType(CScreenElement::TYPE_VSCROLLING_MENU);\r\n}\r\n\r\n\r\n\r\n\r\nCBaseScrollingMenu::~CBaseScrollingMenu()\r\n{\r\n}\r\n\r\n\r\n\r\n\r\nvoid CBaseScrollingMenu::SetProperties(Script::CStruct *pProps)\r\n{\r\n\tfloat just[2] = { 0.0f, 0.0f };\r\n\tif (resolve_just(pProps, CRCD(0x67e093e4,\"internal_just\"), just, just+1))\r\n\t\tSetInternalJust(just[0], just[1]);\r\n\t\r\n\tint scroll_speed;\r\n\tif (pProps->GetInteger(CRCD(0x9020a1d1,\"scroll_speed\"), &scroll_speed))\r\n\t\tm_scroll_speed = (float) scroll_speed;\r\n\t\r\n\tpProps->GetInteger(CRCD(0xc855511c,\"num_items_to_show\"), &m_num_items_to_display);\r\n\r\n\tif (pProps->ContainsFlag(CRCD(0xed889e1f,\"reset_window_top\")))\r\n\t{\r\n\t\tm_top_or_left_line = 0;\r\n\t\tm_needs_update = true;\r\n\t}\r\n\telse if (pProps->ContainsFlag(CRCD(0xc3a894f6,\"reset_window_bottom\")))\r\n\t{\r\n\t\tCScreenElementPtr p_child = mp_the_menu->GetLastChild();\r\n\t\tfloat element_x, element_z, element_w, element_l;\r\n\t\tcompute_element_area(p_child, element_x, element_z, element_w, element_l);\r\n\t\tm_top_or_left_line = element_z + element_l - m_window_dimension;\r\n\t\tm_needs_update = true;\r\n\t}\r\n\telse if ( pProps->ContainsFlag( CRCD(0xa1f3b8bb,\"reset_window\") ) )\r\n\t{\r\n\t\tm_needs_update = true;\r\n\t}\r\n\t\r\n\tCScreenElement::SetProperties(pProps);\r\n}\r\n\r\n\r\n\r\n\r\nbool CBaseScrollingMenu::PassTargetedEvent(Obj::CEvent *pEvent, bool broadcast)\r\n{\r\n\t\r\n\tif (!Obj::CObject::PassTargetedEvent(pEvent))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n    \r\n    if (pEvent->GetType() == Obj::CEvent::TYPE_NOTIFY_CHILD_LOCK)\r\n    {\r\n        // we can assume that VMenu child is in place now, find it\r\n\t\tget_the_menu();\r\n\t\tm_needs_update = true;\r\n\t\tupdate();\r\n\r\n\t\tpEvent->MarkHandled(m_id);\r\n    }\r\n\tif (pEvent->GetType() == Obj::CEvent::TYPE_FOCUS)\r\n\t{\r\n\t\tif (!mp_the_menu)\r\n\t\t\tget_the_menu();\r\n\t\t\r\n\t\t// event is for this scrolling menu\t\t\t\r\n\t\tif (!m_in_focus)\r\n\t\t{\r\n\t\t\t//printf(\"VMenu %s receives focus event, sending to 0x%x\\n\", Script::FindChecksumName(m_id), m_selected_id);\r\n\t\t\tm_in_focus = true;\r\n\t\t\tp_tracker->LaunchEvent(Obj::CEvent::TYPE_FOCUS, mp_the_menu->GetID(), Obj::CEvent::vSYSTEM_EVENT, pEvent->GetData());\t\t\r\n\t\t\tpEvent->MarkHandled(m_id);\r\n\t\t}\r\n\t}\r\n\tif (pEvent->GetType() == Obj::CEvent::TYPE_UNFOCUS && m_in_focus)\r\n\t{\r\n\t\tget_the_menu();\r\n\t\t\r\n\t\t//printf(\"VMenu %s receives focus event, sending to 0x%x\\n\", Script::FindChecksumName(m_id), m_selected_id);\r\n\t\tm_in_focus = false;\r\n\t\tp_tracker->LaunchEvent(Obj::CEvent::TYPE_UNFOCUS, mp_the_menu->GetID());\t\t\r\n\t\tpEvent->MarkHandled(m_id);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CBaseScrollingMenu::pass_event_to_listener(Obj::CEvent *pEvent)\r\n{\r\n\t//printf(\"VMenu receives event of type %s\\n\", Script::FindChecksumName(pEvent->GetType()));\r\n\t\r\n    if (pEvent->GetType() == Obj::CEvent::TYPE_NOTIFY_CHILD_LOCK && mp_the_menu)\r\n    {\r\n        if (pEvent->GetTarget() == mp_the_menu->GetID())\r\n\t\t{\r\n\t\t\tm_needs_update = true;\r\n\t\t\tupdate();\r\n\t\t}\r\n\t\t\r\n\t\t//Obj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\t\t//p_tracker->PrintEventLog(true, 100);\r\n\t\t\r\n\t\tpEvent->MarkRead(m_id);\r\n    }\r\n\tif (pEvent->GetType() == Obj::CEvent::TYPE_FOCUS)\r\n\t{\r\n\t\tif (!mp_the_menu)\r\n\t\t\tget_the_menu();\r\n\t\t\r\n\t\t// see if focus event is for one of contained menu's children\r\n\t\tCScreenElementPtr p_child = mp_the_menu->GetFirstChild();\r\n\t\twhile(p_child)\r\n\t\t{\r\n\t\t\tif (p_child->GetID() == pEvent->GetTarget())\r\n\t\t\t{\r\n\t\t\t\tput_element_in_view(p_child);\r\n\t\t\t\tpEvent->MarkRead(m_id);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tp_child = p_child->GetNextSibling();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CBaseScrollingMenu::get_the_menu()\r\n{\r\n\tCScreenElementPtr p_child = GetFirstChild();\r\n\twhile(p_child)\r\n\t{\r\n\t\tif ((uint32) p_child->GetType() == CRCX(\"vmenu\") && m_is_vertical)\r\n\t\t\tmp_the_menu = (CBaseMenu *) p_child.Convert();\r\n\t\telse if ((uint32) p_child->GetType() == CRCX(\"hmenu\") && !m_is_vertical)\r\n\t\t\tmp_the_menu = (CBaseMenu *) p_child.Convert();\r\n\t\tp_child = p_child->GetNextSibling();\r\n\t}\r\n\t\r\n\tDbg_MsgAssert(mp_the_menu || !m_is_vertical, (\"could not find VMenu\"));\r\n\tDbg_MsgAssert(mp_the_menu || m_is_vertical, (\"could not find HMenu\"));\r\n\r\n\tfloat space_amount = -1.0f;\r\n\tif (mp_the_menu->UsingRegularSpacing(space_amount) && m_num_items_to_display >= 0)\r\n\t{\r\n\t\tm_window_dimension = space_amount * m_num_items_to_display;\r\n\t\tm_regular_space_amount = space_amount;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_num_items_to_display = -1;\r\n\t\tm_window_dimension = (m_is_vertical) ? m_base_h : m_base_w;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CBaseScrollingMenu::put_element_in_view(const CScreenElementPtr &pElement)\r\n{\r\n\tDbg_Assert(mp_the_menu);\r\n\tm_selected_element_id = pElement->GetID();\r\n\tm_needs_update = true;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CBaseScrollingMenu::update()\r\n{\r\n\tCScreenElementPtr pElement = NULL;\r\n\tint element_index = 0;\r\n\t\r\n\tfloat center_menu_offset_up = 0.0f;\r\n\tfloat center_menu_offset_down = 0.0f;\r\n\t\r\n\tif ( mp_the_menu )\r\n\t{\r\n\t\tif ( m_selected_element_id )\r\n\t\t\tpElement = mp_the_menu->GetChildById(m_selected_element_id, &element_index);\r\n\t\telse\r\n\t\t\tpElement = mp_the_menu->GetChildByIndex( 0 );\r\n\t\r\n\t\tif ( pElement )\r\n\t\t{\r\n\t\t\tint num_children = mp_the_menu->CountChildren();\r\n\t\r\n\t\t\t// Good doggy. Now find out if the selection needs to be centered in the window\r\n\t\t\tif (m_regular_space_amount >= 0.0f)\r\n\t\t\t{\r\n\t\t\t\tif (element_index >= (m_num_items_to_display / 2))\r\n\t\t\t\t{\r\n\t\t\t\t\tcenter_menu_offset_up = m_regular_space_amount * ((m_num_items_to_display - 1) / 2);\r\n\t\t\t\t}\r\n\t\t\t\tif (element_index < num_children - (m_num_items_to_display / 2))\r\n\t\t\t\t{\r\n\t\t\t\t\tcenter_menu_offset_down = m_regular_space_amount * (m_num_items_to_display / 2);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (pElement)\r\n\t{\t\r\n\t\tfloat menu_x, menu_y;\r\n\t\tmp_the_menu->SetJust(-1.0f, -1.0f);\r\n\t\tmp_the_menu->GetLocalPos(&menu_x, &menu_y);\r\n\r\n\t\t// get upper-left of element, local coordinates (in relation to VMenu)\r\n\t\tfloat element_x, element_y, element_w, element_h;\r\n\t\tfloat element_z, element_l;\r\n\t\tif (m_is_vertical)\r\n\t\t{\r\n\t\t\tcompute_element_area(pElement, element_x, element_z, element_w, element_l);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcompute_element_area(pElement, element_z, element_y, element_l, element_h);\r\n\t\t}\r\n\t\tif (m_regular_space_amount >= 0.0f) \r\n\t\t{\r\n\t\t\telement_z = m_regular_space_amount * element_index;\r\n\t\t\telement_l = m_regular_space_amount;\r\n\t\t}\r\n\t\t\r\n\t\t// if element top is above window top\r\n\t\tif (element_z < m_top_or_left_line + center_menu_offset_up)\r\n\t\t{\r\n\t\t\t// scroll up\r\n\t\t\tm_top_or_left_line -= m_scroll_speed;\r\n\t\t\tif (m_top_or_left_line < element_z)\r\n\t\t\t\tm_top_or_left_line = element_z - center_menu_offset_up;\r\n\t\t\tm_needs_update = true;\r\n\t\t}\r\n\t\t// if element bottom is below window bottom\r\n\t\telse if (element_z + element_l > m_top_or_left_line + m_window_dimension - center_menu_offset_down)\r\n\t\t{\r\n\t\t\t// scroll down\r\n\t\t\tm_top_or_left_line += m_scroll_speed;\r\n\t\t\tif (m_top_or_left_line + m_window_dimension > element_z + element_l)\r\n\t\t\t\tm_top_or_left_line = element_z + element_l - m_window_dimension + center_menu_offset_down;\r\n\t\t\tm_needs_update = true;\r\n\t\t}\r\n\t\t\t\r\n\t\tif (m_needs_update)\r\n\t\t{\r\n\t\t\tif (m_is_vertical)\r\n\t\t\t\tmp_the_menu->SetPos(menu_x, -m_top_or_left_line, FORCE_INSTANT);\r\n\t\t\telse\r\n\t\t\t\tmp_the_menu->SetPos(-m_top_or_left_line, menu_y, FORCE_INSTANT);\r\n\t\t\r\n\t\t\t//printf(\"m_top_or_left_line is %.2f\\n\", m_top_or_left_line);\r\n\t\t\t\r\n\t\t\t// make elements visible or invisible\r\n\t\t\telement_index = 0;\r\n\t\t\tCScreenElementPtr p_child = mp_the_menu->GetFirstChild();\r\n\t\t\twhile(p_child)\r\n\t\t\t{\r\n\t\t\t\tif (m_is_vertical)\r\n\t\t\t\t{\r\n\t\t\t\t\tcompute_element_area(p_child, element_x, element_z, element_w, element_l);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tcompute_element_area(p_child, element_z, element_y, element_l, element_h);\r\n\t\t\t\t}\r\n\t\t\t\tif (m_regular_space_amount >= 0.0f) \r\n\t\t\t\t{\r\n\t\t\t\t\telement_z = m_regular_space_amount * element_index;\r\n\t\t\t\t\telement_l = m_regular_space_amount;\r\n\t\t\t\t\t//Ryan(\"oog\\n\");\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tconst float TOLERANCE = 0.0f;\r\n\t\t\t\tif (element_z >= m_top_or_left_line - TOLERANCE && element_z + element_l <= m_top_or_left_line + m_window_dimension + TOLERANCE)\r\n\t\t\t\t{\r\n\t\t\t\t\t// top is (mostly) in window, bottom is (mostly) in window\r\n\t\t\t\t\tp_child->SetAlpha(1.0f, FORCE_INSTANT);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_child->SetAlpha(0.0f, FORCE_INSTANT);\r\n\t\t\t\t}\r\n\t\t\r\n\t\t\t\tp_child = p_child->GetNextSibling();\r\n\t\t\t\telement_index++;\r\n\t\t\t}\r\n\t\t\tm_needs_update = false;\r\n\t\t}\r\n\t} // end if pElement\r\n}\r\n\r\n\r\n\r\n\r\n// finds area of element in coordinates relative to this scrolling menu\r\nvoid CBaseScrollingMenu::compute_element_area(const CScreenElementPtr &pElement, float &elementX, float &elementY, float &elementW, float &elementH)\r\n{\r\n\tpElement->GetLocalPos(&elementX, &elementY);\r\n\telementX *= mp_the_menu->GetScaleX();\r\n\telementY *= mp_the_menu->GetScaleY();\r\n\telementW = pElement->GetBaseW() * pElement->GetScaleX() * mp_the_menu->GetScaleX();\r\n\telementH = pElement->GetBaseH() * pElement->GetScaleY() * mp_the_menu->GetScaleY();\r\n\tfloat element_just_x, element_just_y;\r\n\tpElement->GetJust(&element_just_x, &element_just_y);\r\n\telementX -= (element_just_x + 1.0f) * elementW / 2.0f;\r\n\telementY -= (element_just_y + 1.0f) * elementH / 2.0f;\r\n}\r\n\r\n\r\n\r\n\r\nCVScrollingMenu::CVScrollingMenu()\r\n{\r\n\tm_is_vertical = true;\r\n}\r\n\r\n\r\n\r\n\r\nCVScrollingMenu::~CVScrollingMenu()\r\n{\r\n}\r\n\r\n\r\n\r\n\r\nCHScrollingMenu::CHScrollingMenu()\r\n{\r\n\tm_is_vertical = false;\r\n}\r\n\r\n\r\n\r\n\r\nCHScrollingMenu::~CHScrollingMenu()\r\n{\r\n}\r\n\r\n\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gfx/2D/ScrollingMenu.h",
    "content": "#ifndef __GFX_2D_SCROLLINGMENU_H__\r\n#define __GFX_2D_SCROLLINGMENU_H__\r\n\r\n#include <gfx/2D/ScreenElement2.h>\r\n\r\nnamespace Front\r\n{\r\n\r\nclass CBaseMenu;\r\n\t\r\nclass CBaseScrollingMenu : public Front::CScreenElement, public Obj::CEventListener\r\n{\r\npublic:\r\n\r\n\t\t\t\t\t\t\tCBaseScrollingMenu();\r\n\tvirtual\t\t\t\t\t~CBaseScrollingMenu();\r\n\r\n\tvoid\t\t\t\t\tSetInternalJust(float h, float v) {m_internal_just_x = h; m_internal_just_y = v;}\t\r\n\t\r\n\tvirtual void\t\t\tSetProperties(Script::CStruct *pProps);\r\n\tvirtual bool\t\t\tPassTargetedEvent(Obj::CEvent *pEvent, bool broadcast = false);\r\n\r\nprotected:\r\n\r\n\tvoid\t\t\t\t\tpass_event_to_listener(Obj::CEvent *pEvent);\r\n\tvirtual void \t\t\tupdate();\r\n\r\n\tvoid\t\t\t\t\tget_the_menu();\r\n\tvoid\t\t\t\t\tput_element_in_view(const CScreenElementPtr &pElement);\r\n    \t\r\n\tvoid\t\t\t\t\tcompute_element_area(const CScreenElementPtr &pElement, float &elementX, float &elementY, float &elementW, float &elementH);\r\n\t\r\n\tCBaseMenu *\t\t\t\tmp_the_menu;\r\n\tuint32\t\t\t\t\tm_selected_element_id;\r\n\t\r\n\tfloat\t\t\t\t\tm_internal_just_x, m_internal_just_y;\r\n\r\n\tbool\t\t\t\t\tm_in_focus;\r\n\tbool\t\t\t\t\tm_needs_update;\r\n\r\n\tfloat\t\t\t\t\tm_top_or_left_line;\r\n\tfloat\t\t\t\t\tm_scroll_speed;\r\n\r\n\t// set to negative if we aren't limiting\r\n\tint\t\t\t\t\t\tm_num_items_to_display;\r\n\tfloat\t\t\t\t\tm_window_dimension;\r\n\t// set to negative if not used\r\n\tfloat\t\t\t\t\tm_regular_space_amount;\r\n\r\n\tbool\t\t\t\t\tm_is_vertical;\r\n};\r\n\r\n\r\n\r\n\r\nclass CVScrollingMenu : public CBaseScrollingMenu\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCVScrollingMenu();\r\n\tvirtual\t\t\t\t\t~CVScrollingMenu();\r\n};\r\n\r\n\r\n\r\n\r\nclass CHScrollingMenu : public CBaseScrollingMenu\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCHScrollingMenu();\r\n\tvirtual\t\t\t\t\t~CHScrollingMenu();\r\n};\r\n\r\n\r\n\r\n\r\n};\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/2D/SpriteElement.cpp",
    "content": "#include <core/defines.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gfx/2D/ScreenElemMan.h>\r\n#include <gfx/2D/SpriteElement.h>\r\n#include <gfx/2D/Window.h>\r\n#include <gfx/Nx.h>\r\n#include <gfx/nxtexture.h>\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/NxSprite.h>\r\n\r\nnamespace Front\r\n{\r\n\r\n\r\n\r\n\r\nCSpriteElement::CSpriteElement()\r\n{\r\n\t//m_rgba = 0x40909090;\r\n\tm_texture = 0;\r\n\tmp_sprite = Nx::CEngine::sCreateSprite(NULL);\r\n\t\r\n\tSetType(CScreenElement::TYPE_SPRITE_ELEMENT);\r\n}\r\n\r\n\r\n\r\n\r\nCSpriteElement::~CSpriteElement()\r\n{\r\n\tif (mp_sprite)\r\n\t{\r\n\t\tNx::CEngine::sDestroySprite(mp_sprite);\r\n\t}\r\n\t//Ryan(\"Destroying CSpriteElement\\n\");\r\n}\r\n\r\n\r\n\r\n\r\nvoid CSpriteElement::SetProperties(Script::CStruct *pProps)\r\n{\r\n\tCScreenElement::SetProperties(pProps);\r\n\r\n\tuint32 texture_crc;\r\n\tif (pProps->GetChecksum(\"texture\", &texture_crc))\r\n\t\tSetTexture(texture_crc);\r\n\tfloat rot_angle;\r\n\tif ( pProps->GetFloat( \"rot_angle\", &rot_angle ) )\r\n\t\tSetRotate( rot_angle );\r\n\t// Dbg_MsgAssert(m_texture, (\"no texture loaded\"));\r\n}\r\n\r\nvoid CSpriteElement::SetMorph( Script::CStruct *pProps )\r\n{\r\n\tCScreenElement::SetMorph( pProps );\r\n\r\n\tfloat rot_angle;\r\n\tif ( pProps->GetFloat( \"rot_angle\", &rot_angle ) )\r\n\t\tSetRotate( rot_angle, DONT_FORCE_INSTANT );\r\n}\r\n\r\n\r\nvoid CSpriteElement::SetTexture(uint32 texture_checksum)\r\n{\r\n\tNx::CTexture *p_texture;\r\n\r\n\tm_texture = texture_checksum;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_sprite_tex_dict->GetTexture(texture_checksum);\r\n\tDbg_MsgAssert(p_texture, (\"no texture found for sprite 0x%x %s on element 0x%x %s\",\r\n\t\t\t\t\ttexture_checksum,Script::FindChecksumName(texture_checksum),\r\n\t\t\t\t\tm_id,Script::FindChecksumName(m_id)));\r\n\tmp_sprite->SetTexture(p_texture);\r\n\t\r\n\tDbg_MsgAssert(!(m_object_flags & vFORCED_DIMS), (\"Trying to override sprite texture size\"));\r\n\tSetDims(p_texture->GetWidth(), p_texture->GetHeight());\r\n\r\n\tm_object_flags |= CScreenElement::vCHANGED_STATIC_PROPS;\t\r\n}\r\n\r\n\r\n\r\nvoid CSpriteElement::SetRotate( float angle, EForceInstant forceInstant )\r\n{\r\n\tfloat rot = angle * Mth::PI / 180.0f;\r\n\trot += 0.001f;\r\n\tDbg_Assert( mp_sprite );\r\n\r\n\tif ( m_target_local_props.GetRotate() != rot )\r\n\t{\r\n\t\tm_target_local_props.SetRotate( rot );\r\n\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t}\r\n\tif ( forceInstant )\r\n\t{\r\n\t\tif ( m_local_props.GetRotate() != rot )\r\n\t\t{\r\n\t\t\t// on the next update, this element will arrive at the target alpha\r\n\t\t\tmp_sprite->SetRotation( rot );\r\n\t\t\tm_local_props.SetRotate( rot );\r\n\t\t\tm_object_flags |= vNEEDS_LOCAL_POS_CALC;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\nvoid CSpriteElement::update()\r\n{\r\n\t// HACK\r\n\tbool offscreen = false;\r\n\tif (m_summed_props.GetScreenUpperLeftY() < -200.0f || m_summed_props.GetScreenUpperLeftY() > 648.0f)\r\n\t\toffscreen = true;\r\n\t\r\n\t// IsHidden can be relatively slow (it's recursive), so only call once\r\n\tbool hidden = IsHidden();\r\n\r\n\tmp_sprite->SetHidden( hidden );\r\n\r\n\t// only change state of underlying sprite if there's been a change to CScreenElement/CSpriteElement visual state\r\n\tif ( ( m_object_flags & CScreenElement::vDID_SUMMED_POS_CALC ) || ( m_object_flags & CScreenElement::vCHANGED_STATIC_PROPS ) )\r\n\t{\r\n\t\tImage::RGBA true_rgba = m_local_props.GetRGBA();\r\n\t\tif (m_summed_props.alpha >= .0001f)\r\n\t\t\ttrue_rgba.a = (uint8) ((float) m_local_props.GetRGBA().a * m_summed_props.alpha);\r\n\t\telse\r\n\t\t\ttrue_rgba.a = 0;\r\n\t\t\r\n\t\t// GARRETT: \r\n\t\t// Do all drawing here\r\n\t\t//\r\n\t\t// -screen coordinates of upper-left of sprite: m_summed_props.ulx, m_summed_props.uly\r\n\t\t// -scale to apply: m_summed_props.scale\r\n\t\t// -screen W,H of sprite (if needed): m_summed_props.scale * m_base_w, m_summed_props.scale * m_base_h\r\n\t\t//mp_sprite->SetPos(m_summed_props.ulx, m_summed_props.uly);\r\n\t\tmp_sprite->SetPos(m_summed_props.GetScreenPosX(), m_summed_props.GetScreenPosY());\r\n\t\tmp_sprite->SetSize(m_base_w, m_base_h);\r\n\t\tmp_sprite->SetAnchor(m_just_x, m_just_y);\r\n\t\tmp_sprite->SetScale(m_summed_props.GetScaleX(), m_summed_props.GetScaleY());\r\n\t\t\r\n\t\tif ( m_object_flags & CScreenElement::v3D_POS )\r\n\t\t{\r\n\t\t\tmp_sprite->SetZValue(m_summed_props.GetScreenPosZ());\r\n\t\t\tmp_sprite->SetHidden( ( ( m_object_flags & CScreenElement::v3D_CULLED ) || hidden ) );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_sprite->SetPriority( m_z_priority );\r\n\t\t\tmp_sprite->SetHidden( offscreen || hidden );\r\n\t\t}\r\n\t\t\r\n\t\tmp_sprite->SetRGBA(true_rgba);\r\n\t\t// mp_sprite->SetHidden( ( offscreen || hidden ) );\r\n\t\r\n\r\n#if 0  // Garrett: Can't find window\r\n\t\t// Update the clip window.  This should only be done at init time, instead.\r\n\t\tCWindowElement *p_window = get_window();\r\n\t\tmp_sprite->SetWindow(p_window->GetClipWindow());\r\n#endif\r\n\r\n\t\t// update the rotation angle\r\n\t\tmp_sprite->SetRotation( m_local_props.GetRotate() );\r\n\t\t// mp_sprite->SetRotation(mp_sprite->GetRotation() + 0.001f);\r\n\r\n\t}\r\n}\r\n\r\nvoid CSpriteElement::WritePropertiesToStruct( Script::CStruct* pStruct )\r\n{\r\n\tCScreenElement::WritePropertiesToStruct( pStruct );\r\n\r\n\t// rotation angle\r\n\tpStruct->AddFloat( \"rot_angle\", m_local_props.GetRotate() );\r\n\r\n\t// texture name\r\n\tpStruct->AddChecksum( \"texture\", this->m_texture );\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gfx/2D/SpriteElement.h",
    "content": "#ifndef __GFX_2D_SPRITEELEMENT_H__\r\n#define __GFX_2D_SPRITEELEMENT_H__\r\n\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n#include <gfx/2D/ScreenElement2.h>\r\n\r\nnamespace Nx\r\n{\r\n\tclass CSprite;\r\n}\r\n\r\nnamespace Front\r\n{\r\n\r\nclass CSpriteElement : public CScreenElement\r\n{\r\n\tfriend class CScreenElementManager;\r\n\r\npublic:\r\n\t\t\t\t\t\t\tCSpriteElement();\r\n\tvirtual\t\t\t\t\t~CSpriteElement();\r\n\r\n\tvoid\t\t\t\t\tSetProperties(Script::CStruct *pProps);\r\n\tvoid\t\t\t\t\tSetMorph(Script::CStruct *pProps);\r\n\t\r\n\tvoid \t\t\t\t\tSetTexture(uint32 texture_checksum);\r\n\tvoid\t\t\t\t\tSetRotate( float angle, EForceInstant forceInstant = FORCE_INSTANT );\r\n\r\n\tvoid\t\t\t\t\tWritePropertiesToStruct( Script::CStruct *pStruct );\r\n\t\r\nprotected:\r\n\r\n\tvoid\t\t\t\t\tupdate();\r\n\r\n\tuint32\t\t\t\t\tm_texture;\r\n\r\n\tNx::CSprite *\t\t\tmp_sprite;\r\n};\r\n\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/2D/TextElement.cpp",
    "content": "#include <core/defines.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gfx/NxFontMan.h>\r\n#include <gfx/NxFont.h>\r\n#include <gfx/2D/ScreenElement2.h>\r\n#include <gfx/2D/ScreenElemMan.h>\r\n#include <gfx/2D/TextElement.h>\r\n#include <gfx/2D/BlurEffect.h>\r\n#include <gfx/2D/Window.h>\r\n\r\n#define BLUR_EFFECT_ON 1\r\n\r\nnamespace Front\r\n{\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTextElement::CTextElement() :\r\n\tm_shadow_rgba(0, 0, 0, 128)\r\n{\r\n\t//Ryan(\"I am a new CTextElement\\n\");\r\n\tm_font_checksum = 0;\r\n\tmp_font = NULL;\r\n\tmp_text = NULL;\r\n\tmp_blur_effect = NULL;\r\n\tm_use_shadow = false;\r\n\tcreate_text_instances(1);\r\n\r\n\tm_override_encoded_rgba = false;\r\n\tm_previous_override_rgba_state = false;\r\n\t\r\n\tSetType(CScreenElement::TYPE_TEXT_ELEMENT);\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTextElement::~CTextElement()\r\n{\r\n\t//Ryan(\"Destroying CTextElement\\n\");\r\n\tDetachBlurEffect();\r\n\tdestroy_text_instances();\r\n\tif (mp_text)\r\n\t\tdelete mp_text;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextElement::SetProperties(Script::CStruct *pProps)\r\n{\r\n\tCScreenElement::SetProperties(pProps);\r\n\r\n\tuint32 font_crc;\r\n\tif (pProps->GetChecksum(CRCD(0x2f6bf72d,\"font\"), &font_crc))\r\n\t\tSetFont(font_crc);\r\n\tDbg_MsgAssert(m_font_checksum, (\"no font loaded\"));\r\n\t\r\n\tconst char *p_text;\r\n\tif (pProps->GetText(CRCD(0xc4745838,\"text\"), &p_text))\r\n\t\tSetText(p_text);\r\n\r\n\tDbg_MsgAssert(m_id != Obj::CBaseManager::vNO_OBJECT_ID, (\"what, no ID\"));\r\n\r\n\tif (pProps->ContainsFlag(CRCD(0xd1653c6c,\"blur_effect\")))\r\n\t\tAttachBlurEffect();\r\n\tif (pProps->ContainsFlag(CRCD(0x4b73e4f8,\"no_blur_effect\")))\r\n\t\tDetachBlurEffect();\r\n\r\n\tImage::RGBA blur_rgba;\r\n\tif (resolve_rgba(pProps, CRCD(0x4f0e1182,\"blur_rgba\"), &blur_rgba) && mp_blur_effect)\r\n\t\tmp_blur_effect->SetRGBA(blur_rgba);\r\n\r\n\tScript::CPair shadow_offs;\r\n\tif (pProps->GetPair(CRCD(0x2a1fe0cc,\"shadow_offs\"), &shadow_offs))\r\n\t{\r\n\t\tSetShadowOff(shadow_offs.mX, shadow_offs.mY);\r\n\t}\r\n\t\r\n\tif (pProps->ContainsFlag(CRCD(0x8a897dd2,\"shadow\")))\r\n\t\tSetShadowState(true);\r\n\tif (pProps->ContainsFlag(CRCD(0x95b5b9a0,\"no_shadow\")))\r\n\t\tSetShadowState(false);\r\n\t\r\n\tresolve_rgba(pProps, CRCD(0x1e7bb1f5,\"shadow_rgba\"), &m_shadow_rgba);\r\n\t\r\n\tif ( pProps->ContainsFlag( CRCD(0xbf51a0c,\"remember_override_rgba_state\") ) )\r\n\t{\r\n\t\tDbg_MsgAssert( !pProps->ContainsFlag( CRCD(0x61b7b58b,\"restore_override_rgba_state\") ), ( \"restore_override_rgba_state and remember_override_rgba_state?\" ) );\r\n\t\tm_previous_override_rgba_state = m_override_encoded_rgba;\r\n\t}\r\n\tif ( pProps->ContainsFlag( CRCD(0x61b7b58b,\"restore_override_rgba_state\") ) )\r\n\t{\r\n\t\tDbg_MsgAssert( !pProps->ContainsFlag( CRCD(0xbf51a0c,\"remember_override_rgba_state\") ), ( \"restore_override_rgba_state and remember_override_rgba_state?\" ) );\r\n\t\tm_override_encoded_rgba = m_previous_override_rgba_state;\r\n\t}\r\n\t\r\n\tif (pProps->ContainsFlag(CRCD(0xb7686f92,\"override_encoded_rgba\")))\r\n\t\tm_override_encoded_rgba = true;\r\n\tif (pProps->ContainsFlag(CRCD(0xd25bc6cd,\"dont_override_encoded_rgba\")))\r\n\t\tm_override_encoded_rgba = false;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextElement::SetMorph(Script::CStruct *pProps)\r\n{\t\r\n\tif (mp_blur_effect)\r\n\t{\r\n\t\tmp_blur_effect->SetMorph(pProps);\r\n\t}\r\n\r\n\tCScreenElement::SetMorph(pProps);\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextElement::SetFont(uint32 font_checksum)\r\n{\r\n\tm_font_checksum = font_checksum;\r\n\tmp_font = Nx::CFontManager::sGetFont(m_font_checksum);\r\n\tDbg_MsgAssert(Nx::CFontManager::sTestFontLoaded(m_font_checksum), (\"font %s isn't loaded\", Script::FindChecksumName(m_font_checksum)));\r\n\tm_object_flags |= CScreenElement::vCHANGED_STATIC_PROPS;\t\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextElement::SetText(const char *pText)\r\n{\r\n\tint new_length = strlen(pText) + 1;\r\n\tDbg_MsgAssert(new_length < vMAX_TEXT_LENGTH, (\"string too long %d\", new_length));\r\n\r\n\t// if the old string is not big enough, then we need to allocate a new one\t\r\n\t// otherwize, overwrite it, as allocations are slow\r\n\tif (!mp_text || (int)(strlen(mp_text)) < new_length-1)\t\t  // note, does not account for actual allocated size, but will work is string are same size\r\n\t{\r\n\t\tif (mp_text)\r\n\t\t\tdelete mp_text;\t\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\tmp_text = new char[new_length];\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\t// copy pText to mp_text, replacing '\\m' tags with '\\b' tags\r\n\tconst char *p_in = pText;\r\n\tchar *p_out = mp_text;\r\n\twhile(*p_in)\r\n\t{\r\n\t\tif (*p_in == '\\\\' && *(p_in+1) == '\\\\')\r\n\t\t{\r\n\t\t\t// output \"\\\\\" tag unchanged\r\n\t\t\t*p_out++ = *p_in++;\r\n\t\t\t*p_out++ = *p_in++;\r\n\t\t}\r\n\t\t// ignore sticky space\r\n\t\telse if (*p_in == '\\\\' && *(p_in+1) == '_')\r\n\t\t{\r\n\t\t\tp_in++;\r\n\t\t\tp_in++;\r\n\t\t\t*p_out++ = ' ';\r\n\t\t}\r\n\t\telse if (*p_in == '\\\\' && *(p_in+1) == 'm')\r\n\t\t{\r\n\t\t\t*p_out++ = *p_in++;\r\n\t\t\t*p_out++ = 'b';\r\n\t\t\tp_in++;\r\n\t\t\t*p_out++ = Nx::CFontManager::sMapMetaCharacterToButton(p_in++);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t*p_out++ = *p_in++;\r\n\t\t}\r\n\t}\r\n\t*p_out = '\\0';\r\n\t\r\n\tif( mp_font )\r\n\t{\r\n\t\tfloat w, h;\r\n\t\tmp_font->QueryString(mp_text, w, h);\t// width and height in pixels\r\n\r\n\t\tif (!(m_object_flags & vFORCED_DIMS)) \r\n\t\t{\r\n\t\t\tSetDims(w, h);\r\n\t\t}\r\n\t}\r\n\r\n\tm_object_flags |= CScreenElement::vCHANGED_STATIC_PROPS;\t\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CTextElement::GetLength()\r\n{\r\n\treturn strlen( mp_text );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTextElement::Concatenate( const char *pText )\r\n{\r\n\tint old_length = 0;\r\n\tif ( mp_text )\r\n\t\told_length += strlen( mp_text );\r\n\tint length  = old_length + strlen( pText );\r\n\t\r\n\tif ( length + 1 >= vMAX_TEXT_LENGTH )\r\n\t{\r\n\t\t// new string would be too long...\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif ( length > 0 )\r\n\t{\r\n\t\tchar new_string[vMAX_TEXT_LENGTH];\r\n\t\t\r\n\t\t// initialize string\r\n\t\tstrcpy( new_string, \"\" );\r\n\t\tif ( mp_text )\r\n\t\t\tstrcpy( new_string, mp_text );\r\n\r\n\t\t// add new text\r\n\t\tstrcat( new_string, pText );\r\n\t\r\n\t\tSetText( new_string );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTextElement::Backspace()\r\n{\r\n\tif ( !mp_text )\r\n\t\treturn false;\r\n\t\r\n\tint length = strlen( mp_text );\r\n\r\n\tif ( length == 0 )\r\n\t\treturn false;\r\n\r\n\t// copy string\r\n\tchar new_string[vMAX_TEXT_LENGTH];\r\n\tstrcpy( new_string, mp_text );\r\n\t\r\n\t// take care of escaped backslash char (ASCII code 92)\r\n\tif ( length > 1 && new_string[length - 1] == 92 && new_string[length - 2] == 92 )\r\n\t\tnew_string[length - 2] = '\\0';\r\n\t\r\n\t// terminate\r\n\tnew_string[length - 1] = '\\0';\r\n\tSetText( new_string );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextElement::AttachBlurEffect()\r\n{\r\n\t#if BLUR_EFFECT_ON\r\n\tif (!mp_blur_effect)\r\n\t{\r\n\t\tdestroy_text_instances();\r\n\t\t\r\n\t\t// create blur effect according to specs\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\tmp_blur_effect = new CBlurEffect();\r\n\t\t// mp_blur_effect->SetRGBA(m_rgba);\r\n\t\tmp_blur_effect->SetRGBA( m_local_props.GetRGBA() );\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\t\t// get number of CText objects needed\r\n\t\t// create 'em\r\n\t\tcreate_text_instances(mp_blur_effect->GetNumEntries() + 1);\r\n\t}\r\n\t#endif\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextElement::DetachBlurEffect()\r\n{\r\n\tif (mp_blur_effect)\r\n\t{\r\n\t\tdestroy_text_instances();\r\n\t\tdelete mp_blur_effect;\r\n\t\tmp_blur_effect = NULL;\r\n\t\tcreate_text_instances(1);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextElement::SetShadowState(bool shadowOn)\r\n{\r\n\tif (shadowOn && !m_use_shadow)\r\n\t{\r\n\t\tm_use_shadow = true;\r\n\t\tcreate_text_instances(m_num_tab_entries, true);\r\n\t}\r\n\telse if (!shadowOn && m_use_shadow)\r\n\t{\r\n\t\tm_use_shadow = false;\r\n\t\tdestroy_text_instances(true);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextElement::SetShadowOff(float offX, float offY)\r\n{\r\n\tm_shadow_off_x = offX;\r\n\tm_shadow_off_y = offY;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextElement::update()\r\n{\r\n\t//Dbg_Message(\"I am drawing text element at (%.1f,%.1f), scale %.1f\\n\", m_summed_props.ulx, m_summed_props.uly, m_summed_props.scalex);\r\n#if 0\r\n\tif( mp_font )\r\n\t{\r\n\t\tmp_font->BeginText( *((uint32 *) &m_local_props.GetRGBA() ), m_summed_props.scalex);\r\n\t\tmp_font->DrawString(mp_text, m_summed_props.ulx, m_summed_props.uly);\r\n\t\tmp_font->EndText();\r\n\t}\r\n#else\r\n\r\n\tif (!mp_text) return;\r\n\t\r\n\tbool offscreen = false;\r\n\t// HACK\r\n\tif (m_summed_props.GetScreenUpperLeftY() < -200.0f || m_summed_props.GetScreenUpperLeftY() > 648.0f)\r\n\t\toffscreen = true;\r\n\r\n\tif (m_num_tab_entries)\r\n\t{\r\n\t\tImage::RGBA true_rgba = m_local_props.GetRGBA();\r\n\t\tif (m_summed_props.alpha >= .0001f)\r\n\t\t\ttrue_rgba.a = (uint8) ((float) m_local_props.GetRGBA().a * m_summed_props.alpha);\r\n\t\telse\r\n\t\t\ttrue_rgba.a = 0;\r\n\t\t\r\n\t\t/* \r\n\t\t\t-pass current pos, scale, alpha (local) to blur effect\r\n\t\t\t-for each entry in table\r\n\t\t\t\t-get pos, scale, alpa (in local, relative to current)\r\n\t\t*/\r\n\t\t\r\n\t\tmpp_text_req_tab[0]->SetFont(mp_font);\r\n\t\tmpp_text_req_tab[0]->SetPos(m_summed_props.GetScreenUpperLeftX(), m_summed_props.GetScreenUpperLeftY());\r\n\t\tmpp_text_req_tab[0]->SetRGBA(true_rgba, m_override_encoded_rgba);\r\n\t\tmpp_text_req_tab[0]->SetScale(m_summed_props.GetScaleX(), m_summed_props.GetScaleY());\r\n\t\tmpp_text_req_tab[0]->SetString(mp_text);\r\n\t\tif (m_object_flags & CScreenElement::v3D_POS)\r\n\t\t{\r\n\t\t\tmpp_text_req_tab[0]->SetZValue(m_summed_props.GetScreenPosZ());\r\n\t\t\tmpp_text_req_tab[0]->SetHidden( ( ( m_object_flags & CScreenElement::v3D_CULLED ) || IsHidden() ) );\r\n\t\t} else {\r\n\t\t\tmpp_text_req_tab[0]->SetPriority(m_z_priority);\r\n\t\t\tmpp_text_req_tab[0]->SetHidden( ( offscreen || IsHidden() ) );\r\n\t\t}\r\n\r\n#if 0  // Garrett: Can't find window\r\n\t\t// Update the clip window.  This should only be done at init time, instead.\r\n\t\tCWindowElement *p_window = get_window();\r\n\t\tmpp_text_req_tab[0]->SetWindow(p_window->GetClipWindow());\r\n#endif\r\n\r\n\r\n\t\tif (m_use_shadow)\r\n\t\t{\r\n\t\t\tImage::RGBA true_rgba = m_shadow_rgba;\r\n\t\t\tif (m_summed_props.alpha >= .0001f)\r\n\t\t\t\ttrue_rgba.a = (uint8) ((float) m_shadow_rgba.a * m_summed_props.alpha);\r\n\t\t\telse\r\n\t\t\t\ttrue_rgba.a = 0;\r\n\t\t\tmpp_shadow_req_tab[0]->SetFont(mp_font);\r\n\t\t\tmpp_shadow_req_tab[0]->SetPos(m_summed_props.GetScreenUpperLeftX() + m_shadow_off_x, m_summed_props.GetScreenUpperLeftY() + m_shadow_off_y);\r\n\t\t\tmpp_shadow_req_tab[0]->SetRGBA(true_rgba, m_override_encoded_rgba);\r\n\t\t\tmpp_shadow_req_tab[0]->SetScale(m_summed_props.GetScaleX(), m_summed_props.GetScaleY());\r\n\t\t\tmpp_shadow_req_tab[0]->SetString(mp_text);\r\n\t\t\tif (m_object_flags & CScreenElement::v3D_POS)\r\n\t\t\t{\r\n\t\t\t\tmpp_shadow_req_tab[0]->SetZValue(m_summed_props.GetScreenPosZ());\r\n\t\t\t\tmpp_shadow_req_tab[0]->SetHidden( ( ( m_object_flags & CScreenElement::v3D_CULLED ) || IsHidden() ) );\r\n\t\t\t} else {\r\n\t\t\t\tmpp_shadow_req_tab[0]->SetPriority(m_z_priority - .005f);\r\n\t\t\t\tmpp_shadow_req_tab[0]->SetHidden( ( offscreen || IsHidden() ) );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif(mp_blur_effect)\r\n\t{\r\n\t\t/* \r\n\t\t\t-pass current center pos, scale, alpha (local) to blur effect\r\n\t\t\t-for each entry in table\r\n\t\t\t\t-get center pos, scale, alpa (in local, relative to current)\r\n\t\t*/\r\n\r\n\t\tDbg_MsgAssert(!(m_object_flags & CScreenElement::v3D_POS), (\"Can't use motion blur on 3D positioned text\"));\r\n\r\n\t\tmp_blur_effect->Update();\r\n\r\n\t\t// work out absolute center of this element\r\n\t\tfloat center_x = m_summed_props.GetScreenUpperLeftX() + m_summed_props.GetScaleX() * m_base_w / 2.0f;\r\n\t\tfloat center_y = m_summed_props.GetScreenUpperLeftY() + m_summed_props.GetScaleY() * m_base_h / 2.0f;\r\n\r\n\t\tfor (int i = 1; i < m_num_tab_entries; i++)\r\n\t\t{\r\n\t\t\tConcatProps &blur_entry = mp_blur_effect->GetInfo(i-1);\r\n\t\t\t\r\n\t\t\tImage::RGBA true_rgba = mp_blur_effect->GetRGBA();\r\n\t\t\ttrue_rgba.a = (uint8) ((float) true_rgba.a * blur_entry.alpha);\r\n\t\t\t\r\n\t\t\tfloat draw_pos_x = center_x - (blur_entry.GetScreenPosX() + m_base_w * blur_entry.GetScaleX() / 2.0f) * m_summed_props.GetScaleX();\r\n\t\t\tfloat draw_pos_y = center_y - (blur_entry.GetScreenPosY() + m_base_h * blur_entry.GetScaleY() / 2.0f) * m_summed_props.GetScaleY();\r\n\t\t\tfloat draw_scale_x = m_summed_props.GetScaleX() * blur_entry.GetScaleX();\r\n\t\t\tfloat draw_scale_y = m_summed_props.GetScaleY() * blur_entry.GetScaleY();\r\n\t\t\t\r\n\t\t\tmpp_text_req_tab[i]->SetPos(draw_pos_x, draw_pos_y);\r\n\t\t\tmpp_text_req_tab[i]->SetRGBA(true_rgba, m_override_encoded_rgba);\r\n\t\t\tmpp_text_req_tab[i]->SetScale(draw_scale_x, draw_scale_y);\r\n\t\t\tmpp_text_req_tab[i]->SetPriority(m_z_priority - i * .01f);\r\n\t\t\t\r\n\t\t\tmpp_text_req_tab[i]->SetFont(mp_font);\r\n\t\t\tmpp_text_req_tab[i]->SetString(mp_text);\r\n\t\t\tmpp_text_req_tab[i]->SetHidden( ( offscreen || IsHidden() ) );\r\n\r\n\t\t\tif (m_use_shadow)\r\n\t\t\t{\r\n\t\t\t\tImage::RGBA true_rgba = m_shadow_rgba;\r\n\t\t\t\tif (m_summed_props.alpha >= .0001f)\r\n\t\t\t\t\ttrue_rgba.a = (uint8) ((float) m_shadow_rgba.a * m_summed_props.alpha);\r\n\t\t\t\telse\r\n\t\t\t\t\ttrue_rgba.a = 0;\r\n\t\t\t\tmpp_shadow_req_tab[i]->SetPos(draw_pos_x + m_shadow_off_x * draw_scale_x, \r\n\t\t\t\t\t\t\t\t\t\t\tdraw_pos_y + m_shadow_off_y * draw_scale_y);\r\n\t\t\t\tmpp_shadow_req_tab[i]->SetRGBA(true_rgba, m_override_encoded_rgba);\r\n\t\t\t\tmpp_shadow_req_tab[i]->SetScale(draw_scale_x, draw_scale_y);\r\n\t\t\t\tmpp_shadow_req_tab[i]->SetPriority(m_z_priority - i * .01f - .005f);\r\n\r\n\t\t\t\tmpp_shadow_req_tab[i]->SetFont(mp_font);\r\n\t\t\t\tmpp_shadow_req_tab[i]->SetString(mp_text);\r\n\t\t\t\tmpp_shadow_req_tab[i]->SetHidden( ( offscreen || IsHidden() ) );\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n#endif\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextElement::create_text_instances(int numEntries, bool shadow_only)\r\n{\r\n\tDbg_Assert(!mpp_shadow_req_tab);\r\n\r\n\tif (m_use_shadow)\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\tmpp_shadow_req_tab = new Nx::CText*[numEntries];\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\tfor (int i = 0; i < numEntries; i++)\r\n\t\t{\r\n\t\t\tmpp_shadow_req_tab[i] = Nx::CTextMan::sGetTextInstance();\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (!shadow_only)\r\n\t{\r\n\t\tDbg_Assert(!m_num_tab_entries);\r\n\t\r\n\t\tm_num_tab_entries = numEntries;\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\tmpp_text_req_tab = new Nx::CText*[numEntries];\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\tfor (int i = 0; i < numEntries; i++)\r\n\t\t{\r\n\t\t\tmpp_text_req_tab[i] = Nx::CTextMan::sGetTextInstance();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextElement::destroy_text_instances(bool shadow_only)\r\n{\r\n\tif (mpp_shadow_req_tab)\r\n\t{\r\n\t\tfor (int i = 0; i < m_num_tab_entries; i++)\r\n\t\t{\r\n\t\t\tNx::CTextMan::sFreeTextInstance(mpp_shadow_req_tab[i]);\r\n\t\t}\r\n\t\tdelete mpp_shadow_req_tab;\r\n\t\tmpp_shadow_req_tab = NULL;\r\n\t}\r\n\t\r\n\tif (!shadow_only)\r\n\t{\r\n\t\tDbg_Assert(m_num_tab_entries);\r\n\t\t\r\n\t\tfor (int i = 0; i < m_num_tab_entries; i++)\r\n\t\t{\r\n\t\t\tNx::CTextMan::sFreeTextInstance(mpp_text_req_tab[i]);\r\n\t\t}\r\n\t\tdelete mpp_text_req_tab;\r\n\t\tm_num_tab_entries = 0;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTextBlockElement::CTextBlockElement() :\r\n\tm_shadow_rgba(0, 0, 0, 128)\r\n{\r\n\t//Ryan(\"I am a new CTextBlockElement\\n\");\r\n\tm_font = 0;\r\n\tm_internal_scale = 1.0f;\r\n    m_line_spacing_scale = 1.0f;\r\n\tm_total_height = 0.0f;\r\n\tm_total_out_lines = 0;\r\n\r\n\tmp_blur_effect = NULL;\r\n\tm_allow_expansion = false;\r\n\r\n\tm_override_encoded_rgba = false;\r\n\tm_previous_override_rgba_state = false;\r\n\t\r\n\tSetType(CScreenElement::TYPE_TEXT_BLOCK_ELEMENT);\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTextBlockElement::~CTextBlockElement()\r\n{\t\r\n\t//Ryan(\"Destroying CTextBlockElement\\n\");\r\n\tif (mp_blur_effect)\r\n\t\tdelete mp_blur_effect;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextBlockElement::SetProperties(Script::CStruct *pProps)\r\n{\r\n\tCScreenElement::SetProperties(pProps);\r\n\r\n\t// must find this before setting font\r\n\tif (pProps->GetFloat(CRCD(0x1fe341d2,\"internal_scale\"), &m_internal_scale))\r\n\t\tm_object_flags |= CScreenElement::vCHANGED_STATIC_PROPS;\r\n\r\n    pProps->GetFloat(CRCD(0xe3fa22fc,\"line_spacing\"), &m_line_spacing_scale);\r\n    \r\n\tuint32 font_crc;\r\n\tif (pProps->GetChecksum(CRCD(0x2f6bf72d,\"font\"), &font_crc))\r\n\t\tSetFont(font_crc);\r\n\tDbg_MsgAssert(m_font, (\"no font loaded\"));\r\n\t\r\n\r\n\tif (resolve_just(pProps, CRCD(0x67e093e4,\"internal_just\"), &m_internal_just_x, &m_internal_just_y))\r\n\t\tm_object_flags |= CScreenElement::vCHANGED_STATIC_PROPS;\r\n\t\r\n\r\n\tconst char *pp_line_tab[32];\r\n\tScript::CArray *p_text_array;\r\n\t\r\n\tif (pProps->ContainsFlag( CRCD(0x322839a2,\"allow_expansion\") ))\r\n\t\tm_allow_expansion = true;\r\n\t\r\n\tif (pProps->GetText(CRCD(0xc4745838,\"text\"), pp_line_tab))\r\n\t{\r\n\t\tSetText(pp_line_tab, 1);\r\n\t}\r\n\telse if (pProps->GetArray(CRCD(0xc4745838,\"text\"), &p_text_array))\r\n\t{\r\n\t\tint num_entries = p_text_array->GetSize();\r\n\t\tfor (int i = 0; i < num_entries; i++)\r\n\t\t\tpp_line_tab[i] = p_text_array->GetString(i);\r\n\r\n\t\tSetText(pp_line_tab, num_entries);\r\n\t}\r\n\r\n\t/*\r\n\t\tProperty changes to be forwared to children follow:\t\r\n\t*/\r\n\t\r\n\tif (pProps->ContainsFlag(CRCD(0xd1653c6c,\"blur_effect\")) && !mp_blur_effect)\r\n\t{\r\n\t\t#if BLUR_EFFECT_ON\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\tmp_blur_effect = new CBlurEffect();\r\n\t\t// mp_blur_effect->SetRGBA(m_rgba);\r\n\t\tmp_blur_effect->SetRGBA( m_local_props.GetRGBA() );\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t#endif\r\n\t}\r\n\telse if (pProps->ContainsFlag(CRCD(0x4b73e4f8,\"no_blur_effect\")) && mp_blur_effect)\r\n\t{\r\n\t\tdelete mp_blur_effect;\r\n\t\tmp_blur_effect = NULL;\r\n\t}\r\n\t\r\n\tImage::RGBA blur_rgba;\r\n\tif (resolve_rgba(pProps, CRCD(0x4f0e1182,\"blur_rgba\"), &blur_rgba) && mp_blur_effect)\r\n\t{\r\n\t\tmp_blur_effect->SetRGBA(blur_rgba);\r\n\t}\r\n\r\n\tScript::CPair shadow_offs;\r\n\tif (pProps->GetPair(CRCD(0x2a1fe0cc,\"shadow_offs\"), &shadow_offs))\r\n\t{\r\n\t\tm_shadow_off_x = shadow_offs.mX;\r\n\t\tm_shadow_off_y = shadow_offs.mY;\r\n\t}\r\n\t\r\n\tif (pProps->ContainsFlag(CRCD(0x8a897dd2,\"shadow\")))\r\n\t\tm_use_shadow = true;\r\n\tif (pProps->ContainsFlag(CRCD(0x95b5b9a0,\"no_shadow\")))\r\n\t\tm_use_shadow = false;\r\n\r\n\tresolve_rgba(pProps, CRCD(0x1e7bb1f5,\"shadow_rgba\"), &m_shadow_rgba);\r\n\t\r\n\tif ( pProps->ContainsFlag( CRCD(0xbf51a0c,\"remember_override_rgba_state\") ) )\r\n\t{\r\n\t\tDbg_MsgAssert( !pProps->ContainsFlag( CRCD(0x61b7b58b,\"restore_override_rgba_state\") ), ( \"restore_override_rgba_state and remember_override_rgba_state?\" ) );\r\n\t\tm_previous_override_rgba_state = m_override_encoded_rgba;\r\n\t}\r\n\tif ( pProps->ContainsFlag( CRCD(0x61b7b58b,\"restore_override_rgba_state\") ) )\r\n\t{\r\n\t\tDbg_MsgAssert( !pProps->ContainsFlag( CRCD(0xbf51a0c,\"remember_override_rgba_state\") ), ( \"restore_override_rgba_state and remember_override_rgba_state?\" ) );\r\n\t\tm_override_encoded_rgba = m_previous_override_rgba_state;\r\n\t}\r\n\t\r\n\tif (pProps->ContainsFlag(CRCD(0xb7686f92,\"override_encoded_rgba\")))\r\n\t\tm_override_encoded_rgba = true;\r\n\tif (pProps->ContainsFlag(CRCD(0xd25bc6cd,\"dont_override_encoded_rgba\")))\r\n\t\tm_override_encoded_rgba = false;\r\n\t\r\n\tforward_properties_to_children();\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextBlockElement::SetMorph(Script::CStruct *pProps)\r\n{\t\r\n\tif (mp_blur_effect)\r\n\t{\r\n\t\t// Distribute blur effect settings to children, account for different \r\n\t\t// vertical positions of children relative to center of this\r\n\t\t\r\n\t\t// cheap hack, update self so that contained elements have proper position\r\n\t\tupdate();\r\n\t\t\r\n\t\tTmr::Time target_time;\r\n\t\tconst CBlurEffect::Props &blur_target = mp_blur_effect->SetMorph(pProps, &target_time);\r\n\t\t//printf(\"%f\\n\", blur_target.topAlpha);\r\n\t\t// hook up blur effect to children\r\n\t\t\r\n\t\tCScreenElementPtr p_child = CScreenElement::GetFirstChild();\r\n\t\twhile(p_child)\r\n\t\t{\r\n\t\t\t\r\n\t\t\tDbg_MsgAssert(p_child->GetType() == CScreenElement::TYPE_TEXT_ELEMENT,(\"TextBlockElement %s has child %s that is NOT a CTextElement (it's %s)\\n\",\r\n\t\t\tScript::FindChecksumName(GetID()), Script::FindChecksumName(p_child->GetID()), Script::FindChecksumName(p_child->GetType())));\r\n\r\n\t\t\t\r\n\t\t\t// \"child blur target\"\r\n\t\t\tCBlurEffect::Props cbt = blur_target;\r\n\r\n\t\t\t// find center of child relative to center of this\r\n\t\t\t// (we know we'll be getting top of child, since that's the just this class sets)\r\n\t\t\tfloat child_center_x, child_center_y;\r\n\t\t\tp_child->GetLocalPos(&child_center_x, &child_center_y);\r\n\t\t\tchild_center_y += p_child->GetBaseH() / 2.0f;\r\n\t\t\tfloat disp_y = m_base_h / 2.0f - child_center_y;\r\n\t\t\tcbt.maxDisplacementY += blur_target.bottomScaleY * disp_y - disp_y;\r\n\t\t\t\r\n\t\t\tCBlurEffect *p_child_blur = ((CTextElement *) ((CScreenElement *) p_child))->GetBlurEffect();\r\n\t\t\tDbg_Assert(p_child_blur);\r\n\t\t\tp_child_blur->SetAllTargetProps(cbt, target_time);\r\n\t\t\tp_child = p_child->GetNextSibling();\r\n\t\t}\r\n\t}\r\n\r\n\tCScreenElement::SetMorph(pProps);\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextBlockElement::SetFont(uint32 font_checksum)\r\n{\r\n\tDbg_MsgAssert(!m_font, (\"font already set\"));\r\n\tm_font = font_checksum;\r\n\tDbg_MsgAssert(Nx::CFontManager::sTestFontLoaded(m_font), (\"font %s isn't loaded\", Script::FindChecksumName(m_font)));\r\n\r\n\t// how many lines will fit?\r\n\t\r\n\tNx::CFont* p_font = Nx::CFontManager::sGetFont(m_font);\r\n\tDbg_MsgAssert(p_font, (\"no font found\"));\r\n\t\r\n\t// see if word wraps past end of element\r\n\tfloat word_w, word_h;\r\n\tp_font->QueryString(\"AAA\", word_w, word_h);\t// width and height in pixels\r\n\r\n\tm_num_visible_lines = (int) m_base_h / (int) (word_h * m_internal_scale);\r\n\tm_object_flags |= CScreenElement::vCHANGED_STATIC_PROPS;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextBlockElement::SetText(const char **ppTextLines, int numLines)\r\n{\r\n\tDbg_MsgAssert(m_object_flags & vFORCED_DIMS, (\"no dimensions have been set\"));\r\n\tDbg_MsgAssert(numLines < 256, (\"large number of lines, probably not good\"));\r\n\r\n//\tchar parsed_lines[MAX_LINES][MAX_CHARS]; \r\n\t\t\t\t\t\t\t\t  \r\n\tCScreenElementManager* p_manager = CScreenElementManager::Instance();\r\n\t\r\n\t// destroy any children that are present\r\n\tSetChildLockState( UNLOCK );\r\n\tCScreenElementPtr p_child = GetFirstChild();\r\n\twhile ( p_child )\r\n\t{\r\n\t\tCScreenElementPtr p_next = p_child->GetNextSibling();\r\n\t\tp_manager->DestroyElement(p_child->GetID());\r\n\t\tp_child = p_next;\r\n\t}\r\n\tDbg_Assert( !GetFirstChild() );\r\n\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().FrontEndHeap() );\r\n\tmpp_parsed_lines = new char*[MAX_LINES];\r\n\t// (Mick) in order to avoid doing multiple allocations, we just\r\n\t// allocate a single array big enough for all the lines\r\n\tmpp_parsed_lines[0] = new char[MAX_CHARS * MAX_LINES];\r\n\tMem::Manager::sHandle().PopContext();\r\n\t// then calculate the pointers for all the other lines, as an offset to this\r\n\tfor ( int l = 1; l < MAX_LINES; l++ )\r\n\t{\r\n\t\tmpp_parsed_lines[l] = mpp_parsed_lines[0] + MAX_CHARS*l;\r\n\t}\r\n\tfor( int i = 0; i < MAX_LINES; i++ )\r\n\t{\r\n\t\tmpp_parsed_lines[i][0] = '\\0';\r\n\t}\r\n\r\n\tm_out_char = 0;\r\n\tm_virtual_out_line = 0;\r\n\tm_out_line = 0;\r\n\tm_current_line_width = 0.0f;\r\n\t\r\n\t// reset number of visible lines\r\n\tif ( m_allow_expansion )\r\n\t{\r\n\t\tm_base_h = 0.0f;\r\n\t\tm_num_visible_lines = 0;\r\n\t}\r\n\t\r\n\tfor ( int in_line = 0; in_line < numLines; in_line++ )\r\n\t\tread_in_text_line( ppTextLines[in_line] );\r\n\t\t\r\n\t// printf(\"line %d: %s\\n\", m_out_line, mpp_parsed_lines[m_out_line]);\r\n\t// want to handle the \"no text\" case\r\n\tif (numLines)\r\n\t{\r\n\t\tm_virtual_out_line++;\r\n\t\tm_out_line++;\r\n\t}\r\n\r\n\t// we only to want to use the N most recent lines,\r\n\t// where N is the number of lines that will fit\r\n\tint buf_use_line = 0;\r\n\tm_total_out_lines = m_out_line;\r\n\tif ( m_virtual_out_line >= m_num_visible_lines )\r\n\t{\r\n\t\t// expand the element if we're supposed to\r\n\t\tif ( m_allow_expansion )\r\n\t\t{\r\n\t\t\tNx::CFont* p_font = Nx::CFontManager::sGetFont(m_font);\r\n\t\t\tDbg_MsgAssert(p_font, (\"no font found\"));\r\n\t\t\t\r\n\t\t\t// change the height of the element\r\n\t\t\tfloat word_w, word_h;\r\n\t\t\tp_font->QueryString(\"AAA\", word_w, word_h );\t// width and height in pixels\r\n\t\t\tm_base_h = m_virtual_out_line * (word_h * m_internal_scale * m_line_spacing_scale );\r\n\r\n\t\t\tm_num_visible_lines = (int) m_base_h / (int) (word_h * m_internal_scale * m_line_spacing_scale );\r\n\r\n\t\t\t// re-parse the text now that m_num_visible_lines has changed\r\n// Mick: no need for this, since they are fixed size, we just overwrite them\r\n//\t\t\tfor (int l = 0; l < MAX_LINES; l++)\r\n//\t\t\t{\r\n//\t\t\t\tdelete mpp_parsed_lines[l];\r\n//\t\t\t\tmpp_parsed_lines[l] = new char[MAX_CHARS];\r\n//\t\t\t}\r\n\t\t\tm_out_char = 0;\r\n\t\t\tm_virtual_out_line = 0;\r\n\t\t\tm_out_line = 0;\r\n\t\t\tm_current_line_width = 0.0f;\r\n\t\t\tfor (int i = 0; i < numLines; i++)\r\n\t\t\t\tread_in_text_line(ppTextLines[i]);\r\n\r\n\t\t\t// printf(\"changing m_total_out_lines from %i to %i\\n\", m_total_out_lines, m_num_visible_lines);\r\n\t\t\tm_total_out_lines = m_num_visible_lines;\r\n\t\t}\r\n\t\telse \r\n\t\t{\r\n\t\t\tDbg_MsgAssert( m_num_visible_lines, (\"Text block element too small for one line\") );\r\n            buf_use_line = m_virtual_out_line % m_num_visible_lines;\r\n\t\t\tm_total_out_lines = m_num_visible_lines;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t// create new children\r\n\tm_total_height = 0.0f;\r\n\tfor (int i = 0; i < m_total_out_lines; i++)\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\tCTextElement *p_new_elem = new CTextElement();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\tp_manager->RegisterObject(*p_new_elem);\r\n\t\tp_manager->SetParent(this, p_new_elem);\r\n\t\tp_new_elem->SetFont(m_font);\r\n\t\tp_new_elem->SetText(&mpp_parsed_lines[buf_use_line][0]);\r\n\t\tp_new_elem->SetScale(m_internal_scale, m_internal_scale);\r\n\t\r\n\t\t\r\n\t\tm_total_height += p_new_elem->GetBaseH() * m_internal_scale * m_line_spacing_scale;\r\n\t\tbuf_use_line++;\r\n\t\tif (buf_use_line >= m_num_visible_lines)\r\n\t\t\tbuf_use_line = 0;\r\n\t}\r\n\r\n\t// delete the lines, now we've used them\r\n// Mick: Now we just delete the array of chars, and the array of pointers\r\n//\tfor (int l = 0; l < MAX_LINES; l++)\r\n//\t{\r\n//\t\tdelete mpp_parsed_lines[l];\r\n//\t\tmpp_parsed_lines[l] = NULL;\t\t\t\r\n//\t}\r\n\tdelete mpp_parsed_lines[0];\r\n\tdelete mpp_parsed_lines;\r\n\r\n\t\r\n\tSetChildLockState(LOCK);\r\n\r\n\tm_object_flags |= CScreenElement::vCHANGED_STATIC_PROPS;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextBlockElement::SetText(const char *pTextLine)\r\n{\r\n\tSetText(&pTextLine, 1);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTextBlockElement::GetText( char* p_text, int size )\r\n{\r\n\tstrcpy( p_text, \"\" );\r\n\tint total_length = 0;\r\n\t\r\n\tCScreenElementPtr p_child = GetFirstChild();\r\n\twhile( p_child )\r\n\t{\r\n\t\tDbg_MsgAssert(p_child->GetType() == CScreenElement::TYPE_TEXT_ELEMENT,(\"TextBlockElement %s has child %s that is NOT a CTextElement (it's %s)\\n\",\r\n\t\tScript::FindChecksumName(GetID()), Script::FindChecksumName(p_child->GetID()), Script::FindChecksumName(p_child->GetType())));\r\n\r\n\t\r\n\t\tCScreenElementPtr p_next = p_child->GetNextSibling();\r\n\t\tCTextElement* p_text_element = (CTextElement*)p_child.Convert();\r\n\r\n\t\tchar* p_text_element_string = p_text_element->GetText();\r\n\t\ttotal_length += strlen( p_text_element_string );\r\n\t\t\r\n\t\tif ( p_next )\r\n\t\t\ttotal_length += 1;\r\n\t\r\n\t\tif ( total_length < size )\r\n\t\t{\r\n\t\t\tstrcat( p_text, p_text_element_string );\r\n\t\t\t\r\n\t\t\t// add a space between lines if this isn't the last line\r\n\t\t\tif ( p_next )\r\n\t\t\t\tstrcat( p_text, \" \" );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"TextBlockElement::GetText - text too long\" ) );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tp_child = p_next;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CTextBlockElement::GetLength()\r\n{\r\n\t// printf( \"CTextBlockElement::GetLength called on %s\\n\", Script::FindChecksumName( m_id ) );\r\n\tint total_length = 0;\r\n\t\r\n\tCScreenElementPtr p_child = GetFirstChild();\r\n\twhile( p_child )\r\n\t{\r\n\t\tDbg_MsgAssert(p_child->GetType() == CScreenElement::TYPE_TEXT_ELEMENT,(\"TextBlockElement %s has child %s that is NOT a CTextElement (it's %s)\\n\",\r\n\t\tScript::FindChecksumName(GetID()), Script::FindChecksumName(p_child->GetID()), Script::FindChecksumName(p_child->GetType())));\r\n\t\t\r\n\t\tCScreenElementPtr p_next = p_child->GetNextSibling();\r\n\t\tCTextElement* p_text_element = (CTextElement*)p_child.Convert();\r\n\t\ttotal_length += p_text_element->GetLength();\r\n\t\t\r\n\t\tif ( p_next )\r\n\t\t\ttotal_length += 1;\r\n\t\t\r\n\t\tp_child = p_next;\r\n\t}\t\r\n\treturn total_length;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTextBlockElement::Backspace()\r\n{\r\n\tint length = GetLength();\r\n\r\n\tif ( length == 0 )\r\n\t\treturn false;\r\n\r\n\tDbg_MsgAssert( length < MAX_EDITABLE_TEXT_BLOCK_LENGTH, ( \"Backspace failed - string too long\" ) );\r\n\tchar new_string[MAX_EDITABLE_TEXT_BLOCK_LENGTH];\r\n\tGetText( new_string, MAX_EDITABLE_TEXT_BLOCK_LENGTH );\r\n\t\r\n\tif ( !new_string )\r\n\t\treturn false;\r\n\t\r\n\t// take care of escaped backslash char (ASCII code 92)\r\n\tif ( length > 1 && new_string[length - 1] == 92 && new_string[length - 2] == 92 )\r\n\t\tnew_string[length - 2] = '\\0';\r\n\t\r\n\t// terminate\r\n\tnew_string[length - 1] = '\\0';\r\n\tSetText( new_string );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\n\tCalled from read_in_text_line()\r\n*/\r\nCTextBlockElement::EParseResult CTextBlockElement::parse_next_word(char *pWordBuf, const char **ppSource)\r\n{\r\n\tbool keep_scanning = true;\r\n\tEParseResult result = NORMAL; \r\n\t\r\n\tchar *p_out = pWordBuf;\r\n\t\r\n\twhile (keep_scanning)\r\n\t{\r\n\t\tswitch(**ppSource)\r\n\t\t{\r\n\t\t\tcase ' ':\r\n\t\t\t\t*p_out++ = **ppSource;\r\n\t\t\t\t(*ppSource)++;\r\n\t\t\t\tkeep_scanning = false;\r\n\t\t\t\tbreak;\r\n\t\t\tcase '\\\\':\r\n\t\t\t{\r\n\t\t\t\t(*ppSource)++;\r\n\t\t\t\tif (**ppSource == '_')\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_out++ = ' ';\r\n\t\t\t\t\t(*ppSource)++;\r\n\t\t\t\t}\r\n\t\t\t\telse if (**ppSource == 'n')\r\n\t\t\t\t{\r\n\t\t\t\t\t(*ppSource)++;\r\n\t\t\t\t\tresult = NEXT_LINE;\r\n\t\t\t\t\tkeep_scanning = false;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// is \\?, where ? is some character\r\n\t\t\t\t\t// output both\r\n\t\t\t\t\t*p_out++ = '\\\\';\r\n\t\t\t\t\t*p_out++ = **ppSource;\r\n\t\t\t\t\t(*ppSource)++;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t} // end case\r\n\t\t\tcase '\\0':\r\n\t\t\t\tresult = END_OF_BUFFER;\r\n\t\t\t\tkeep_scanning = false;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t{\r\n\t\t\t\t*p_out++ = **ppSource;\r\n\t\t\t\t(*ppSource)++;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t} // end switch\r\n\r\n\t\tDbg_Assert((int) p_out - (int) pWordBuf < MAX_CHARS - 1);\r\n\t}\r\n\r\n\t*p_out++ = '\\0';\r\n\treturn result;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCalled from SetText()\r\n*/\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nvoid CTextBlockElement::read_in_text_line(const char *pText)\r\n{\r\n\tNx::CFont* p_font = Nx::CFontManager::sGetFont(m_font);\r\n\tDbg_MsgAssert(p_font, (\"no font found\"));\r\n\t\r\n\tconst char *p_in = pText;\r\n\r\n\tchar p_word[MAX_CHARS];\r\n\r\n\tEParseResult last_result = NORMAL;\r\n\t\r\n\t// printf(\"reading in: %s\\n\", pText);\r\n\t\r\n\twhile ( last_result != END_OF_BUFFER )\r\n\t{\r\n\t\tEParseResult result = parse_next_word( p_word, &p_in );\r\n\t\t\r\n\t\t// see if word wraps past end of element\r\n\t\tfloat word_w, word_h;\r\n\t\tp_font->QueryString(p_word, word_w, word_h);\t// width and height in pixels\r\n\t\tword_w *= m_internal_scale;\r\n\t\t\r\n\t\t// printf(\"result = %d, word = '%s', screen_w = %.2f\\n\", result, p_word, word_w);\r\n\r\n\t\t// if adding this word makes the line too long\r\n\t\t// or we had a newline char or similar\r\n\t\t// or this word will overflow the buffer (unlikely, but possible)\r\n\t\tif ( ( m_current_line_width > 0.0f && m_current_line_width + word_w > m_base_w )\r\n\t\t\t ||  ( last_result == NEXT_LINE )\r\n\t\t\t ||  ( m_out_char + strlen( p_word ) >= MAX_CHARS )\r\n\t\t   )\r\n\t\t{\r\n\t\t\t// printf(\"m_current_line_width = %f, word_w = %f, m_base_w = %f\\n\", m_current_line_width, word_w, m_base_w);\r\n\t\t\t// printf(\"line %d: %s\\n\", m_out_line, mpp_parsed_lines[m_out_line]);\r\n\t\t\t\r\n\t\t\t// if last character on line is a space, do away with it\r\n\t\t\tif ( mpp_parsed_lines[m_out_line][m_out_char-1] == ' ' )\r\n\t\t\t\tmpp_parsed_lines[m_out_line][m_out_char-1] = '\\0';\r\n\t\t\t\r\n\t\t\t// Wrap to next\tline.\r\n\t\t\t// Once we fill all visible lines, we start recycling the buffer,\r\n\t\t\t// keeping only the most recent lines, hence the virtual line stuff.\r\n\t\t\tm_virtual_out_line++;\r\n\t\t\tm_out_line++;\r\n\t\t\tif ( m_out_line >= m_num_visible_lines )\r\n\t\t\t\tm_out_line = 0;\r\n\t\t\tm_out_char = 0;\r\n\t\t\tm_current_line_width = 0.0f;\r\n\t\t}\r\n\t\t\r\n\t\tDbg_Assert(m_out_line < MAX_LINES); // need to increase MAX_LINES if triggered\r\n\t\tDbg_MsgAssert(m_out_char + strlen(p_word) < MAX_CHARS, (\"overflow, max allowed = %d, needed = %d\\n%s%s\\n\", MAX_CHARS, m_out_char + strlen(p_word),&mpp_parsed_lines[m_out_line][0],p_word));\r\n\t\tchar *p_out = &mpp_parsed_lines[m_out_line][0] + m_out_char;\r\n\t\tstrcpy(p_out, p_word);\r\n\t\tm_out_char += strlen(p_word);\r\n\t\tm_current_line_width += word_w;\r\n\r\n\t\tlast_result = result;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextBlockElement::update()\r\n{\r\n\tif (m_object_flags & CScreenElement::vCHANGED_STATIC_PROPS)\r\n\t{\r\n\t\tDbg_Assert(m_total_height > .00001f || !m_total_out_lines);\r\n\t\t\r\n\t\t// position children\r\n\t\tfloat y = (m_internal_just_y + 1.0f) * (m_base_h - m_total_height) / 2.0f;\r\n\t\tCScreenElementPtr p_child = GetFirstChild();\r\n\t\tfor (int i = 0; i < m_total_out_lines; i++)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(p_child->GetType() == CScreenElement::TYPE_TEXT_ELEMENT,(\"TextBlockElement %s has child %s that is NOT a CTextElement (it's %s)\\n\",\r\n\t\t\tScript::FindChecksumName(GetID()), Script::FindChecksumName(p_child->GetID()), Script::FindChecksumName(p_child->GetType())));\r\n\t\t\t\r\n\t\t\tp_child->SetJust(m_internal_just_x, -1.0f);\r\n\t\t\t// p_child->SetRGBA(m_rgba);\r\n\t\t\tp_child->SetRGBA( m_local_props.GetRGBA() );\r\n\t\t\tp_child->SetPos((m_internal_just_x + 1.0f) * m_base_w / 2.0f, y);\r\n\r\n\t\t\ty += p_child->GetBaseH() * m_internal_scale * m_line_spacing_scale;\r\n\t\t\tp_child = p_child->GetNextSibling();\r\n\t\t}\r\n\t\tforward_properties_to_children();\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTextBlockElement::forward_properties_to_children()\r\n{\r\n\tCScreenElementPtr p_child = CScreenElement::GetFirstChild();\r\n\twhile(p_child)\r\n\t{\r\n\t\t\r\n\t\tDbg_MsgAssert(p_child->GetType() == CScreenElement::TYPE_TEXT_ELEMENT,(\"TextBlockElement %s has child %s that is NOT a CTextElement (it's %s)\\n\",\r\n\t\t\tScript::FindChecksumName(GetID()), Script::FindChecksumName(p_child->GetID()), Script::FindChecksumName(p_child->GetType())));\r\n\t\t\r\n\t\tif (mp_blur_effect)\r\n\t\t\t((CTextElement *) ((CScreenElement *) p_child))->AttachBlurEffect();\r\n\t\telse\r\n\t\t\t((CTextElement *) ((CScreenElement *) p_child))->DetachBlurEffect();\r\n\t\tif (m_use_shadow)\r\n\t\t\t((CTextElement *) ((CScreenElement *) p_child))->SetShadowState(true);\r\n\t\telse\r\n\t\t\t((CTextElement *) ((CScreenElement *) p_child))->SetShadowState(false);\r\n\t\t((CTextElement *) ((CScreenElement *) p_child))->SetShadowOff(m_shadow_off_x, m_shadow_off_y);\r\n\t\t((CTextElement *) ((CScreenElement *) p_child))->SetShadowRGBA(m_shadow_rgba);\r\n\t\t((CTextElement *) ((CScreenElement *) p_child))->SetEncodedRGBAOverride(m_override_encoded_rgba);\r\n\t\tp_child = p_child->GetNextSibling();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// if enforce_max_width is true, the function will fail if a single word is\r\n// bigger than the width of a line.  That is, if the text would go outside\r\n// the specified width and there's no way to wrap, concatenation will fail.\r\n// Only the end of the string is checked.  The text already in the element\r\n// is assumed to be safe.  Thus it's possible to have a textblock element go\r\n// outside it's box by using SetText directly, rather than using concatenate\r\nbool CTextBlockElement::Concatenate( const char* pText, bool enforce_max_width, bool last_line )\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tint length = GetLength();\r\n\tDbg_MsgAssert( length < (int)( MAX_EDITABLE_TEXT_BLOCK_LENGTH - strlen( pText ) ), ( \"TextBlock too long to concatenate\" ) );\r\n#endif\r\n\t\r\n\t// setup new, unwrapped string\r\n\tchar* p_new_string = new char[MAX_EDITABLE_TEXT_BLOCK_LENGTH];\r\n\tGetText( p_new_string, Front::MAX_EDITABLE_TEXT_BLOCK_LENGTH );\r\n\tstrcat( p_new_string, pText );\r\n\r\n\t// enforce max width but allow them to add a space.\r\n\tif ( (enforce_max_width && strcmp( pText, \" \" ) != 0) || last_line)\r\n\t{\r\n\t\tNx::CFont* p_font = Nx::CFontManager::sGetFont( m_font );\r\n\t\tDbg_MsgAssert( p_font, ( \"no font found\" ) );\r\n\r\n\t\t// parse through the new text word by word\r\n\t\tconst char *p_in = p_new_string;\r\n\t\tchar p_word[MAX_CHARS];\r\n\r\n\t\t// skip up to the last word\r\n\t\tEParseResult last_result = NORMAL;\r\n\t\twhile ( last_result != END_OF_BUFFER )\r\n\t\t{\t\t\t\r\n\t\t\tlast_result = parse_next_word( p_word, &p_in );\r\n\t\t}\r\n\t\t\t\r\n\t\t// check that each word is not longer than the max width\r\n\t\tfloat word_w, word_h;\r\n\t\tp_font->QueryString( p_word, word_w, word_h );\t// width and height in pixels\r\n\t\tword_w *= m_internal_scale;\r\n\t\tif ( word_w > m_base_w )\r\n\t\t{\r\n\t\t\t// too long!\r\n\t\t\tdelete p_new_string;\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\r\n\tSetText( p_new_string );\r\n\tdelete p_new_string;\r\n\treturn true;\r\n}\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gfx/2D/TextElement.h",
    "content": "#ifndef __GFX_2D_TEXTELEMENT_H__\r\n#define __GFX_2D_TEXTELEMENT_H__\r\n\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n#include <gfx/2D/ScreenElement2.h>\r\n\r\n#define TEXT_ELEMENT_MAX_LENGTH 96\r\n\r\nnamespace Nx\r\n{\r\n\tclass CFont;\r\n\tclass CText;\r\n}\r\n\r\nnamespace Front\r\n{\r\n\tclass CBlurEffect;\r\n\r\n\tenum\r\n\t{\r\n\t\tMAX_EDITABLE_TEXT_BLOCK_LENGTH = 512,\r\n\t};\r\n\r\n\r\nclass CTextElement : public CScreenElement\r\n{\r\n\tfriend class CScreenElementManager;\r\n\tfriend class CTextBlockElement;\r\n\r\npublic:\r\n\t\t\t\t\t\t\tCTextElement();\r\n\tvirtual\t\t\t\t\t~CTextElement();\r\n\r\n\tvoid\t\t\t\t\tSetProperties(Script::CStruct *pProps);\r\n\tvoid\t\t\t\t\tSetMorph(Script::CStruct *pProps);\r\n\t\r\n\tvoid \t\t\t\t\tSetFont(uint32 font_checksum);\r\n\tvoid\t\t\t\t\tSetText(const char *pText);\r\n\tchar*\t\t\t\t\tGetText() { return mp_text; }\r\n\tint\t\t\t\t\t\tGetLength();\r\n\r\n    bool\t\t\t\t\tConcatenate( const char *pText );\r\n\tbool\t\t\t\t\tBackspace();\r\n\t\r\n\tvoid\t\t\t\t\tAttachBlurEffect();\r\n\tvoid\t\t\t\t\tDetachBlurEffect();\r\n\tCBlurEffect\t*\t\t\tGetBlurEffect() {return mp_blur_effect;}\r\n\r\n\tvoid\t\t\t\t\tSetShadowState(bool shadowOn);\r\n\tvoid\t\t\t\t\tSetShadowOff(float offX, float offY);\r\n\tvoid\t\t\t\t\tSetShadowRGBA(Image::RGBA shadowRGBA) {m_shadow_rgba = shadowRGBA;}\r\n\r\n\tvoid\t\t\t\t\tSetEncodedRGBAOverride(bool override) {m_override_encoded_rgba = override;}\r\n\r\nprotected:\r\n\r\n\tvoid\t\t\t\t\tcreate_text_instances(int numInstances, bool shadowOnly = false);\r\n\tvoid\t\t\t\t\tdestroy_text_instances(bool shadowOnly = false);\r\n\t\r\n\tenum\r\n\t{\r\n\t\tvMAX_TEXT_LENGTH\t= TEXT_ELEMENT_MAX_LENGTH,\r\n\t};\r\n\t\r\n\tvoid\t\t\t\t\tupdate();\r\n\r\n\tchar *\t\t\t\t\tmp_text;\r\n\r\n\tuint32\t\t\t\t\tm_font_checksum;\r\n\tNx::CFont *\t\t\t\tmp_font;\r\n\tNx::CText **\t\t\tmpp_text_req_tab;\r\n\tNx::CText **\t\t\tmpp_shadow_req_tab;\r\n\tint\t\t\t\t\t\tm_num_tab_entries;\r\n\r\n\tCBlurEffect\t*\t\t\tmp_blur_effect;\r\n\r\n\tbool\t\t\t\t\tm_use_shadow;\r\n\tfloat\t\t\t\t\tm_shadow_off_x;\r\n\tfloat\t\t\t\t\tm_shadow_off_y;\r\n\tImage::RGBA\t\t\t\tm_shadow_rgba;\r\n\r\n\tbool\t\t\t\t\tm_override_encoded_rgba;\r\n\tbool\t\t\t\t\tm_previous_override_rgba_state;\r\n};\r\n\r\n\r\n\r\n\r\nclass CTextBlockElement : public CScreenElement\r\n{\r\n\tfriend class CScreenElementManager;\r\n\r\npublic:\r\n\t\t\t\t\t\t\tCTextBlockElement();\r\n\tvirtual\t\t\t\t\t~CTextBlockElement();\r\n\r\n\tvoid\t\t\t\t\tSetProperties(Script::CStruct *pProps);\r\n\tvoid\t\t\t\t\tSetMorph(Script::CStruct *pProps);\r\n\t\r\n\tvoid \t\t\t\t\tSetFont(uint32 font_checksum);\r\n\tvoid\t\t\t\t\tSetText(const char **ppTextLines, int numLines);\r\n\tvoid\t\t\t\t\tSetText(const char *pTextLine);\r\n\r\n\tbool\t\t\t\t\tGetText( char* p_text, int size );\r\n\tint\t\t\t\t\t\tGetLength();\r\n\tbool\t\t\t\t\tBackspace();\r\n\tbool\t\t\t\t\tConcatenate( const char* pText, bool enforce_max_width = false, bool last_line = false );\r\n\r\nprotected:\r\n\r\n\tenum EParseResult\r\n\t{ \r\n\t\tNORMAL,\r\n\t\tNEXT_LINE,\r\n\t\tEND_OF_BUFFER,\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n\t\tMAX_LINES\t\t\t= 20,\r\n\t\tMAX_CHARS\t\t\t= TEXT_ELEMENT_MAX_LENGTH,\r\n\t};\r\n\t\r\n\tEParseResult \t\t\tparse_next_word(char *pWordBuf, const char **ppSource);\r\n\tvoid \t\t\t\t\tread_in_text_line(const char *pText);\r\n\tvoid\t\t\t\t\tupdate();\r\n\tvoid \t\t\t\t\tforward_properties_to_children();\r\n\r\n\tuint32\t\t\t\t\tm_font;\r\n\r\n\tchar **\t\t\t\t\tmpp_parsed_lines;\r\n\t// Line of text \"outputted\" so far. With a lot of text lines, only most recent ones are used.\r\n\tint\t\t\t\t\t\tm_virtual_out_line;\t\r\n\tint \t\t\t\t\tm_out_line;\t// line of mpp_parsed_lines currently being written to\r\n\tint \t\t\t\t\tm_out_char; // on m_out_line\r\n\tfloat \t\t\t\t\tm_current_line_width;\r\n\r\n\tint\t\t\t\t\t\tm_num_visible_lines;\r\n\r\n\tfloat\t\t\t\t\tm_internal_just_x, m_internal_just_y;\r\n\tfloat\t\t\t\t\tm_internal_scale;\r\n    float\t\t\t\t\tm_line_spacing_scale;\r\n\tfloat\t\t\t\t\tm_total_height; // of contained TextElements\r\n\tint\t\t\t\t\t\tm_total_out_lines; // number of contained TextElements\r\n\t\r\n\tCBlurEffect\t*\t\t\tmp_blur_effect;\r\n\tbool\t\t\t\t\tm_use_shadow;\r\n\tbool\t\t\t\t\tm_allow_expansion;\r\n\tfloat\t\t\t\t\tm_shadow_off_x;\r\n\tfloat\t\t\t\t\tm_shadow_off_y;\r\n\tImage::RGBA\t\t\t\tm_shadow_rgba;\r\n\t\r\n\tbool\t\t\t\t\tm_override_encoded_rgba;\r\n\tbool\t\t\t\t\tm_previous_override_rgba_state;\r\n};\r\n\r\n\r\n\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/2D/Window.cpp",
    "content": "#include <core/defines.h>\r\n#include <gfx/2D/Window.h>\r\n#include <gfx/NxWin2D.h>\r\n\r\n#ifdef\t__PLAT_NGPS__ \r\n#include <gfx/NGPS/NX/chars.h>\r\n#endif\r\n\r\nnamespace Front\r\n{\r\n\r\n\r\n\r\n\r\nCWindowElement::CWindowElement()\r\n{\r\n\tSetType(CScreenElement::TYPE_WINDOW_ELEMENT);\r\n\tmp_clip_window = Nx::CWindow2DManager::sGetWindowInstance(0, 0, 640, 448);\r\n}\r\n\r\n\r\n\r\n\r\nCWindowElement::~CWindowElement()\r\n{\r\n\tDbg_Assert(mp_clip_window);\r\n\tNx::CWindow2DManager::sFreeWindowInstance(mp_clip_window);\r\n}\r\n\r\n\r\nNx::CWindow2D *\tCWindowElement::GetClipWindow() const\r\n{\r\n\treturn mp_clip_window;\r\n}\r\n\r\n\r\n#if 0\r\nvoid CWindowElement::drawMainPart()\r\n{\r\n#ifdef\t__PLAT_NGPS__ \r\n\tNxPs2::SetTextWindow(0,639,0,447);\t\t\t\t\t\t// a full-screen clipping window\r\n#else\r\n\tprintf (\"WARNING: drawMainPart not the same on this platform....\\n\");\r\n#endif\r\n}\r\n#endif\r\n\r\n\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gfx/2D/Window.h",
    "content": "#ifndef __GFX_2D_WINDOW_H__\r\n#define __GFX_2D_WINDOW_H__\r\n\r\n#include <gfx/2D/ScreenElement2.h>\r\n\r\nnamespace Nx\r\n{\r\n\tclass CWindow2D;\r\n}\r\n\r\nnamespace Front\r\n{\r\n\r\nclass CWindowElement : public Front::CScreenElement\r\n{\r\npublic:\r\n\r\n\t\t\t\t\t\t\tCWindowElement();\r\n\tvirtual\t\t\t\t\t~CWindowElement();\r\n\r\n\tvoid\t\t\t\t\tSetClipWindow(Nx::CWindow2D *p_window);\t\t// This should probably be protected or private\r\n\tNx::CWindow2D *\t\t\tGetClipWindow() const;\r\n\r\nprotected:\r\n\tNx::CWindow2D *\t\t\tmp_clip_window;\r\n\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/AnimController.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       AnimChannel.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/13/01\r\n//****************************************************************************\r\n\r\n// Current state of an animation.  There should be no\r\n// references to skeletons or geometry;  this is purely \r\n// a time-keeping class).\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/animcontroller.h>\r\n                                  \r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n\t\t\t\t\t\t\t\t   \r\n#include <sys/timer.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CAnimChannel::get_new_anim_time( void )\r\n{\r\n#ifdef __NOPT_ASSERT__\t\r\n\tfloat old_time = m_currentTime;\r\n#endif\r\n\r\n\tfloat new_time=0;\r\n\tfloat new_hold_time=0;\r\n\tfloat new_loop_time=0;\r\n\r\n\tm_animComplete = false;\r\n\r\n\tif ( m_loopingType == LOOPING_WOBBLE )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Was not expecting a wobble looping type in this controller\" ) );\r\n\t\treturn 0.0f;\r\n\t}\r\n\t\r\n\tif ( m_direction == ANIM_DIR_FORWARDS )\r\n\t{\r\n\t\tnew_time = m_currentTime + ( m_animSpeed * Tmr::FrameRatio() );\r\n\t\tm_animComplete = new_time > m_endTime;\r\n\t\t\r\n\t\tif (m_startTime == m_endTime)\r\n\t\t{\r\n\t\t\tnew_loop_time = m_endTime;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tnew_loop_time = m_startTime + ( new_time - m_endTime );\r\n\t\t\twhile ( new_loop_time > m_endTime )\r\n\t\t\t{\r\n\t\t\t\t// when the FrameRatio() > 1.0f, it's possible that\r\n\t\t\t\t// we need to subtract more than once, esp. with short anims\r\n\t\t\t\tnew_loop_time = m_startTime + ( new_loop_time - m_endTime );\r\n\t\t\t}\r\n\t\t}\r\n\t\tnew_hold_time = m_endTime;\r\n\t}\r\n\telse if ( m_direction == ANIM_DIR_BACKWARDS )\r\n\t{\r\n\t\tnew_time = m_currentTime - ( m_animSpeed * Tmr::FrameRatio() );\r\n\t\tm_animComplete = new_time < m_startTime;\r\n\t\tif (m_startTime == m_endTime)\r\n\t\t{\r\n\t\t\tnew_loop_time = m_endTime;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tnew_loop_time = m_endTime + ( new_time - m_startTime );\r\n\t\t\twhile ( new_loop_time < m_startTime )\r\n\t\t\t{\r\n\t\t\t\t// when the FrameRatio() > 1.0f, it's possible that\r\n\t\t\t\t// we need to subtract more than once, esp. with short anims\r\n\t\t\t\tnew_loop_time = m_endTime + ( new_loop_time - m_startTime );\r\n\t\t\t}\r\n\t\t}\r\n\t\tnew_hold_time = m_startTime;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n\r\n\tif ( m_animComplete )\r\n\t{\r\n\t\tif ( m_loopingType == LOOPING_HOLD )\r\n\t\t{\r\n\t\t\tnew_time = new_hold_time;\r\n\t\t}\r\n\t\telse if ( m_loopingType == LOOPING_PINGPONG )\r\n\t\t{\r\n\t\t\tm_direction = ( m_direction == ANIM_DIR_FORWARDS ) ? ANIM_DIR_BACKWARDS : ANIM_DIR_FORWARDS;\r\n\t\t\tnew_time = new_hold_time;\r\n\t\t}\r\n        else if ( m_loopingType == LOOPING_CYCLE )\r\n        {\r\n            new_time = new_loop_time;\r\n\t\t}\r\n\t}\r\n\r\n\t// Ken: This is temporary, to prevent the following assert going off when running a replay.\r\n\t// Eventually the replays will be fixed to always recreate the correct new_time\r\n    if ( new_time < m_startTime )\r\n\t{\r\n\t\tnew_time = m_startTime;\r\n\t}\t\r\n\tif ( new_time > m_endTime )\r\n\t{\r\n\t\tnew_time = m_endTime;\r\n\t}\t\r\n\r\n#ifdef __NOPT_ASSERT__\r\n    if ( new_time < m_startTime || new_time > m_endTime )\r\n    {\r\n        Dbg_Message( \"old_time = %f\", old_time );\r\n        Dbg_Message( \"new_time = %f\", new_time );\r\n        Dbg_Message( \"new_loop_time = %f\", new_loop_time );\r\n        Dbg_Message( \"new_hold_time = %f\", new_hold_time );\r\n        Dbg_Message( \"m_startTime = %f\", m_startTime );\r\n        Dbg_Message( \"m_endTime = %f\", m_endTime );\r\n        Dbg_Message( \"m_loopingType = %d\", m_loopingType );\r\n        Dbg_Message( \"m_direction = %d\", m_direction );\r\n        Dbg_Message( \"m_animComplete = %d\", m_animComplete );\r\n        Dbg_Message( \"m_animName = %s\", Script::FindChecksumName( m_animName ) );\r\n\t\tDbg_Assert( 0 );\r\n    }\r\n#endif\r\n\r\n\treturn new_time;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCAnimChannel::CAnimChannel() : Lst::Node<CAnimChannel>(this)\r\n{\r\n    Reset();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCAnimChannel::~CAnimChannel()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimChannel::Reset()\r\n{\r\n\tm_startTime = 0.0f;\r\n    m_currentTime = 0.0f;\r\n    m_endTime = 0.0f;\r\n    m_animSpeed = 0.0f;\r\n    m_direction = ANIM_DIR_FORWARDS;\r\n    m_loopingType = LOOPING_CYCLE;\r\n    m_animComplete = false;\r\n\r\n\t// Ken: Changed this to be a hard wired checksum rather than calling Script::GenerateCRC\r\n\t// The reason for this is that CAnimChannel::Reset() gets called from \r\n\t// CSkaterTrackingInfo::Reset() in replay.cpp, which gets called from the CSkaterTrackingInfo\r\n\t// constructor. There is a static instance of a CSkaterTrackingInfo in replay.cpp, so the\r\n\t// constructor will get called at some point before main(). Since Script::GenerateCRC accesses\r\n\t// an array of data, there is a chance that it might get called before the array is initialised,\r\n\t// since the order of execution is not well defined.\r\n\t// It probably would be OK, I just want to be safe.\r\n\tm_animName = 0xf60c9090;\t\t// unassigned <-- just giving it a non-zero value, so that\r\n\t\t\t\t\t\t\t\t\t// we can be sure it's getting initialized correctly...\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CAnimChannel::GetCurrentAnim( void )\r\n{\r\n    return m_animName;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CAnimChannel::GetCurrentAnimTime( void )\r\n{\r\n    return m_currentTime;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimChannel::GetAnimTimes(float *pStart, float *pCurrent, float *pEnd)\r\n{\r\n  \tDbg_MsgAssert( pStart, (\"NULL pStart\") );\r\n\tDbg_MsgAssert( pCurrent, (\"NULL pCurrent\") );\r\n\tDbg_MsgAssert( pEnd, (\"NULL pEnd\") );\r\n\r\n\t*pCurrent = m_currentTime;\r\n\t\r\n    if ( m_direction == ANIM_DIR_FORWARDS )\r\n\t{\r\n\t\t*pStart = m_startTime;\r\n\t\t*pEnd = m_endTime;\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\t*pStart = m_endTime;\r\n\t\t*pEnd = m_startTime;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimChannel::AddTime( float incVal )\r\n{\r\n\t// GJ:  a way to fool the animation controller\r\n\t// into incrementing its time (frame rate\r\n\t// independent) for the viewer object\r\n\r\n\tfloat oldAnimSpeed = m_animSpeed;\r\n\r\n\tm_animSpeed = 0.0f;\r\n\r\n\tm_currentTime += incVal;\r\n\r\n\tCAnimChannel::Update();\r\n\r\n\tm_animSpeed = oldAnimSpeed;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimChannel::Update()\r\n{\r\n\tm_currentTime = get_new_anim_time();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Returns whether the animation has completed.  This is only     */\r\n/* valid with \"hold on last frame\" animations.\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAnimChannel::IsAnimComplete( void )\r\n{\r\n\tif ( m_loopingType == LOOPING_HOLD )\r\n\t{\r\n\t\tif ( m_direction == ANIM_DIR_FORWARDS )\r\n\t\t{\r\n\t\t\treturn ( m_currentTime == m_endTime );\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn ( m_currentTime == m_startTime );\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CAnimChannel::IsLoopingAnim( void )\r\n{\t\r\n\t// Returns whether the current animation will loop forever.\r\n\t// Used in skater.cpp, to determine whether or not it should\r\n\t// wait for an animation to finish.\r\n\treturn ( m_loopingType == LOOPING_CYCLE || m_loopingType == LOOPING_PINGPONG );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimChannel::SetAnimSpeed( float speed )\r\n{\r\n\tm_animSpeed = speed / 60.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CAnimChannel::GetAnimSpeed( void )\r\n{\r\n\treturn ( m_animSpeed * 60.0f );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimChannel::ReverseDirection( void )\r\n{\r\n\tif ( m_direction == ANIM_DIR_FORWARDS )\r\n\t{\r\n\t\tm_direction = ANIM_DIR_BACKWARDS;\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tm_direction = ANIM_DIR_FORWARDS;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimChannel::SetLoopingType( EAnimLoopingType type )\r\n{\r\n\tm_loopingType = type;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimChannel::PlaySequence( uint32 anim_name, float start_time, float end_time, EAnimLoopingType loop_type, float blend_period, float speed )\r\n{\t\t   \r\n// Don't reset any more, because this will call the CBlendChannel's virtual\r\n// virtual function, which makes the animation status inactive...\r\n//\tReset();\r\n\r\n\tm_startTime\t\t\t\t\t\t\t    = (start_time < end_time) ? start_time : end_time;\r\n\tm_currentTime\t\t\t\t\t\t\t= start_time;\r\n\tm_endTime\t\t\t\t\t\t\t\t= (start_time < end_time) ? end_time : start_time;\r\n\tm_animSpeed\t\t\t\t\t\t\t    = speed / 60.0f;\r\n\tm_direction\t\t\t\t\t\t\t\t= (start_time < end_time) ? ANIM_DIR_FORWARDS : ANIM_DIR_BACKWARDS;\r\n\tm_loopingType\t\t\t\t\t\t\t= loop_type;\r\n\tm_animComplete\t\t\t\t\t\t\t= false;\r\n\tm_animName\t\t\t\t\t\t\t\t= anim_name;\r\n\r\n//\tDbg_MsgAssert(m_startTime != m_endTime,(\"m_startTime == m_endTime (%f) TELL MICK\",m_startTime));\r\n//\tm_wobbleTargetTime\t\t\t\t\t    = (start_time + end_time) / 2;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAnimChannel::GetDebugInfo( Script::CStruct* p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert( p_info, ( \"NULL p_info sent to CAnimChannel::GetDebugInfo\" ) );\r\n\r\n\t// put the name first\r\n\tp_info->AddChecksum( \"m_animName\", m_animName );\r\n\t\r\n\tuint32 looping_type_checksum = 0;\r\n\tswitch ( m_loopingType )\r\n\t{\r\n\tcase 0:\r\n\t\tlooping_type_checksum = CRCD( 0x3f00df04, \"LOOPING_HOLD\" );\r\n\t\tbreak;\r\n\tcase 1:\r\n\t\tlooping_type_checksum = CRCD( 0xfbada576, \"LOOPING_CYCLE\" );\r\n\t\tbreak;\r\n\tcase 2:\r\n\t\tlooping_type_checksum = CRCD( 0x792b924b, \"LOOPING_PINGPONG\" );\r\n\t\tbreak;\r\n\tcase 3:\r\n\t\tlooping_type_checksum = CRCD( 0x90423ff2, \"LOOPING_WOBBLE\" );\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tDbg_MsgAssert( 0, ( \"Unknown looping type found in CAnimChannel::GetDebugInfo.  Was the enum changed?\" ) );\r\n\t\tbreak;\r\n\t}\r\n\tif ( looping_type_checksum )\r\n\t\tp_info->AddChecksum( CRCD(0x84b06b3,\"m_loopingType\"), looping_type_checksum );\r\n\r\n\tswitch ( m_direction )\r\n\t{\r\n\tcase 0:\r\n\t\tp_info->AddChecksum( CRCD(0x9f648df4,\"m_direction\"), CRCD( 0xdf8b2509, \"ANIM_DIR_FORWARDS\" ) );\r\n\t\tbreak;\r\n\tcase -1:\r\n\t\tp_info->AddChecksum( CRCD(0x9f648df4,\"m_direction\"), CRCD( 0xfdf0c4a4, \"ANIM_DIR_BACKWARDS\" ) );\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tDbg_MsgAssert( 0, ( \"Unknown direction found in CAnimChannel::GetDebugInfo.  Was the enum changed?\" ) );\r\n\t\tbreak;\r\n\t}\r\n\r\n\tp_info->AddFloat( CRCD(0x8fbac25e,\"m_startTime\"), m_startTime );\r\n\tp_info->AddFloat( CRCD(0xb73f0945,\"m_currentTime\"), m_currentTime );\r\n\tp_info->AddFloat( CRCD(0xf1cef774,\"m_endTime\"), m_endTime );\r\n\tp_info->AddFloat( CRCD(0xaa1e73de,\"m_animSpeed\"), m_animSpeed );\r\n\tp_info->AddInteger( CRCD(0x2d574054,\"m_animComplete\"), m_animComplete );\r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Gfx\r\n"
  },
  {
    "path": "Code/Gfx/AnimController.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       AnimChannel.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/13/01\r\n//****************************************************************************\r\n\r\n// Current state of an animation.  There should be no\r\n// references to skeletons or geometry;  this is purely \r\n// a time-keeping class).\r\n\r\n#ifndef __GFX_ANIMCHANNEL_H\r\n#define __GFX_ANIMCHANNEL_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <core/list.h>\r\n\r\n#include <gfx/bonedanimtypes.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n}\r\n\t\t\t\t\t\t\r\nnamespace Gfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CAnimChannel : public Lst::Node<CAnimChannel>\r\n{\r\npublic:\r\n    CAnimChannel();\r\n    virtual ~CAnimChannel();\r\n\r\n    virtual void        Reset();\r\n    virtual void        Update();\r\n\tuint32\t\t\t\tGetCurrentAnim();\r\n\t\r\n    float               GetCurrentAnimTime( void );\r\n    void                GetAnimTimes( float*, float*, float* );\r\n    bool                IsAnimComplete( void );\r\n    bool                IsLoopingAnim( void );\r\n    void                SetAnimSpeed( float );\r\n    float               GetAnimSpeed( void );\r\n\tvoid\t\t\t\tReverseDirection( void );\r\n    void                SetLoopingType( EAnimLoopingType );\r\n\tEAnimLoopingType\tGetLoopingType() const {\r\n\t\treturn m_loopingType;\r\n\t}\r\n    virtual void        PlaySequence( uint32 animName, float start_time, float end_time, EAnimLoopingType loop_type, float blend_period, float speed );\r\n\tvoid\t\t\t\tAddTime( float incVal );\r\n\r\n\tvirtual void\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\t// made this public while i'm changing over to new anim controllers\r\n\r\n//protected:\r\npublic:\r\n    float\t\t\t\tget_new_anim_time( void );\r\n    \r\n    float\t\t\t\tm_startTime;\r\n    float\t\t\t\tm_currentTime;\r\n    float\t\t\t\tm_endTime;\r\n    float\t\t\t\tm_animSpeed;\r\n    EAnimDirection\t\tm_direction;\r\n    EAnimLoopingType\tm_loopingType;\r\n    bool\t\t\t\tm_animComplete;\r\n\tuint32\t\t\t\tm_animName;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // namespace Gfx\r\n\r\n#endif\t// __GFX_ANIMCHANNEL_H\r\n"
  },
  {
    "path": "Code/Gfx/BonedAnim.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       bonedanim.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  11/14/2001\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/bonedanim.h>\r\n\r\n#include <gfx/bonedanimtypes.h>\r\n#include <gfx/nxquickanim.h>\r\n#include <sys/file/AsyncFilesys.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/mem/memman.h>\r\n#include <gel/object.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <sys/config/config.h>\r\n#include <core/string/stringutils.h>\r\n#include <sys/file/pip.h>\r\n\r\n#ifdef __PLAT_NGC__\r\n#include <dolphin.h>\r\n#include \"sys/ngc/p_dma.h\"\r\n#include \"sys\\ngc\\p_aram.h\"\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __PLAT_NGC__\r\n#define __ARAM__\r\n#endif\r\n\r\n#ifdef __PLAT_NGC__\r\n#define _16(a) (((a>>8)&0x00ff)|((a<<8)&0xff00))\r\n#define _32(a) (((a>>24)&0x000000ff)|((a>>8)&0x0000ff00)|((a<<8)&0x00ff0000)|((a<<24)&0xff000000)) \r\n#else\r\n#define _16(a) a\r\n#define _32(a) a\r\n#endif\t\t// __PLAT_NGC__\r\n\r\nnamespace Gfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// In order to compress the data, we convert the animation quat into\r\n// a unit quat and then discard the W value during export-time/load-time.  \r\n// Given the X, Y, Z values, we can rebuild the W value at run-time.\r\n// The code uses the following tolerance to when comparing the rebuilt W value\r\n// to the original value.  I chose the number pretty arbitrarily, based\r\n// on the existing (THPS3) skater and pedestrian animations.\r\n//(0.0005 radians ~= 0.028 degrees)\r\nconst float nxUNITQUAT_TOLERANCE_RADIANS = 0.0005f;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// The following structures are only needed until new data\r\n// is exported in the correct format\r\n\r\nstruct SBonedAnimFileHeader\r\n{\r\n\tuint32 \t    version;\r\n\tuint32    \tflags;\r\n\tfloat\t    duration;\r\n};\r\n\r\nstruct SPlatformFileHeader\r\n{\r\n    uint32      numBones;\r\n    uint32      numQKeys;\r\n    uint32      numTKeys;\r\n    uint32      numCustomAnimKeys;\r\n};\r\n\r\nstruct SStandardAnimFramePointers\r\n{\r\n\tunsigned char\tnumQKeys;\r\n\tunsigned char\tnumTKeys;\r\n};\r\n\r\nstruct SHiResAnimFramePointers\r\n{\r\n\tshort\t\t\tnumQKeys;\r\n\tshort\t\t\tnumTKeys;\r\n};\r\n\r\n//#define nxBONEDANIMFLAGS_UNUSED\t\t\t(1<<31)\r\n#define nxBONEDANIMFLAGS_INTERMEDIATE   \t(1<<30)\r\n#define nxBONEDANIMFLAGS_UNCOMPRESSED   \t(1<<29)\r\n#define nxBONEDANIMFLAGS_PLATFORM      \t\t(1<<28)\t\r\n#define nxBONEDANIMFLAGS_CAMERADATA    \t\t(1<<27)\t\r\n#define nxBONEDANIMFLAGS_COMPRESSEDTIME \t(1<<26)\r\n#define nxBONEDANIMFLAGS_PREROTATEDROOT \t(1<<25)\r\n#define nxBONEDANIMFLAGS_OBJECTANIMDATA\t\t(1<<24)\r\n#define nxBONEDANIMFLAGS_USECOMPRESSTABLE\t(1<<23)\r\n#define nxBONEDANIMFLAGS_HIRESFRAMEPOINTERS\t(1<<22)\r\n#define nxBONEDANIMFLAGS_CUSTOMKEYSAT60FPS\t(1<<21)\r\n#define nxBONEDANIMFLAGS_CUTSCENEDATA\t\t(1<<20)\r\n#define nxBONEDANIMFLAGS_PARTIALANIM\t\t(1<<19)\r\n\r\n// to be phased out...\r\n#define nxBONEDANIMFLAGS_OLDPARTIALANIM\t\t(1<<18)\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __ARAM__\r\n#define ARAM_CACHE_SIZE (64*1024)\r\n#define MAX_BONE_COUNT 128\r\n\r\nstatic char qqq[ARAM_CACHE_SIZE] ATTRIBUTE_ALIGN(32); \r\n\r\nstatic uint16\t\t\t\tframecount[MAX_BONE_COUNT*2] ATTRIBUTE_ALIGN(32);\r\n//static uint32\t\t\t\tpartial[8] ATTRIBUTE_ALIGN(32);\r\n\r\nvolatile uint8\t\t\t\tframecount_active = 0;\r\nstatic int\t\t\t\t\tframecount_size = 0;\r\nARQRequest\t\t\t\t\tframecount_request;\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// compress tables take up 4K,\r\n// which are a waste on Xbox and GC\r\n// (should PLAT_NGPS it once it's working)\r\n\r\nstruct CBonedAnimCompressEntry\r\n{\r\n\tshort x48;\r\n\tshort y48;\r\n\tshort z48;\r\n\tshort n8;\r\n};\r\n\r\nCBonedAnimCompressEntry sQTable[256];\r\nCBonedAnimCompressEntry sTTable[256];\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool init_48_table( void* pStream, CBonedAnimCompressEntry* pEntry )\r\n{\r\n\tfor ( int i = 0; i < 256; i++ )\r\n\t{\r\n\t\tif ( !File::Read( (int*)&pEntry->x48, sizeof(short), 1, pStream ) )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\r\n\t\tif ( !File::Read( (int*)&pEntry->y48, sizeof(short), 1, pStream ) )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\r\n\t\tif ( !File::Read( (int*)&pEntry->z48, sizeof(short), 1, pStream ) )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tif ( !File::Read( (int*)&pEntry->n8, sizeof(short), 1, pStream ) )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\r\n\t\tpEntry->x48 = _16( pEntry->x48 );\r\n\t\tpEntry->y48 = _16( pEntry->y48 );\r\n\t\tpEntry->z48 = _16( pEntry->z48 );\r\n\t\tpEntry->n8 = _16( pEntry->n8 );\r\n\r\n\t\tpEntry++;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n#ifdef __ARAM__\r\n//static volatile bool\tdmaComplete;\r\n\r\nstatic void arqCallback( u32 pointerToARQRequest )\r\n{\r\n//\tARQRequest * p_arq = (ARQRequest *)pointerToARQRequest;\r\n\r\n//\tif ( p_arq->owner == 0x55555555 )\r\n//\t{\r\n\t\tframecount_active = 0;\r\n//\t}\r\n}\r\n\r\nvoid dma_count( uint32 p_source_base, int size )\r\n{\r\n\t// DMA the count info.\r\n\tsize = ( ( size + 31 ) & ~31 ); \r\n\tDCFlushRange ( framecount, size );\r\n\tframecount_size = size;\r\n\tframecount_active = 1;\r\n\tARQPostRequest\t(\t&framecount_request,\r\n\t\t\t\t\t\t0x55555555,\t\t\t\t\t\t\t\t\t\t\t// Owner.\r\n\t\t\t\t\t\tARQ_TYPE_ARAM_TO_MRAM,\t\t\t\t\t\t\t\t// Type.\r\n\t\t\t\t\t\tARQ_PRIORITY_HIGH,\t\t\t\t\t\t\t\t\t// Priority.\r\n\t\t\t\t\t\tp_source_base,\t\t\t\t\t\t\t\t\t\t// Source.\r\n\t\t\t\t\t\t(uint32)framecount,\t\t\t\t\t\t\t\t\t// Dest.\r\n\t\t\t\t\t\tsize,\t\t\t\t\t\t\t\t\t\t\t\t// Length.\r\n\t\t\t\t\t\tarqCallback );\t\t\t\t\t\t\t\t\t\t// Callback\r\n}\r\n\r\n//void dma_partial( uint32 p_source_base )\r\n//{\r\n//\twhile ( framecount_active );\r\n//\t// DMA the count info.\r\n//\tDCFlushRange ( partial, 32 );\r\n//\tframecount_size = 32;\r\n//\tframecount_active = 1;\r\n//\tARQPostRequest\t(\t&framecount_request,\r\n//\t\t\t\t\t\t0x55555555,\t\t\t\t\t\t\t\t\t\t\t// Owner.\r\n//\t\t\t\t\t\tARQ_TYPE_ARAM_TO_MRAM,\t\t\t\t\t\t\t\t// Type.\r\n//\t\t\t\t\t\tARQ_PRIORITY_HIGH,\t\t\t\t\t\t\t\t\t// Priority.\r\n//\t\t\t\t\t\tp_source_base,\t\t\t\t\t\t\t\t\t\t// Source.\r\n//\t\t\t\t\t\t(uint32)partial,\t\t\t\t\t\t\t\t\t// Dest.\r\n//\t\t\t\t\t\t32,\t\t\t\t\t\t\t\t\t\t\t\t\t// Length.\r\n//\t\t\t\t\t\tarqCallback );\t\t\t\t\t\t\t\t\t\t// Callback\r\n//}\r\n\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool InitQ48Table( const char* pFileName, bool assertOnFail )\r\n{\r\n\tbool success = false;\r\n\t\r\n\t// open the file as a stream\r\n\tvoid* pStream = File::Open( pFileName, \"rb\" );\r\n\t\r\n    // make sure the file is valid\r\n\tif ( !pStream )\r\n\t{\r\n\t\tDbg_MsgAssert( !assertOnFail, (\"Load of %s failed - file not found?\", pFileName) );\r\n\t\tgoto exit;\r\n\t}\r\n\r\n\tsuccess = init_48_table( pStream, &sQTable[0] );\r\n\r\nexit:\r\n\tDbg_MsgAssert( success, (\"Parse of %s failed\", pFileName) );\r\n\tFile::Close( pStream );\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool InitT48Table( const char* pFileName, bool assertOnFail )\r\n{\r\n\tbool success = false;\r\n\r\n\t// open the file as a stream\r\n\tvoid* pStream = File::Open( pFileName, \"rb\" );\r\n\r\n\t// make sure the file is valid\r\n\tif ( !pStream )\r\n\t{\r\n\t\tDbg_MsgAssert( assertOnFail, (\"Load of %s failed - file not found?\", pFileName) );\r\n\t\tgoto exit;\r\n\t}\r\n\r\n\tsuccess = init_48_table( pStream, &sTTable[0] );\r\n\r\n\t//Dbg_Assert( 0 );\r\n\r\nexit:\r\n\tDbg_MsgAssert( success, (\"Parse of %s failed\", pFileName) );\r\n\tFile::Close( pStream );\t\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                 */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float timeDown(short theSource)\r\n{\r\n    return (float)theSource;\r\n}\t  \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline short timeUp(float theSource)\r\n{\r\n\tshort retVal = (short)((theSource * 60.0f) + 0.5f);\r\n\r\n    return retVal;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline short transUp(float theSource, float scaleFactor)\r\n{\r\n    return (short)(theSource * scaleFactor);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float transDown(short theSource, float scaleFactor)\r\n{\r\n    return (float)(theSource / scaleFactor);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline short quatUp(float theSource)\r\n{\r\n    return (short)(theSource * 16384.0f);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float quatDown(short theSource)\r\n{\r\n    return (float)(theSource / 16384.0f);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void get_rotation_from_key( CAnimQKey* p_in, Mth::Quat* pQuat, bool isHiRes )\r\n{\r\n\tif ( isHiRes )\r\n\t{\r\n\t\t(*pQuat)[X] = ((CHiResAnimQKey*)p_in)->qx;\r\n\t\t(*pQuat)[Y] = ((CHiResAnimQKey*)p_in)->qy;\r\n\t\t(*pQuat)[Z] = ((CHiResAnimQKey*)p_in)->qz;\r\n//  \t(*pQuat)[W] = ((CHiResAnimQKey*)p_in)->qw;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t(*pQuat)[X] = quatDown( ((CStandardAnimQKey*)p_in)->qx );\r\n\t\t(*pQuat)[Y] = quatDown( ((CStandardAnimQKey*)p_in)->qy );\r\n\t\t(*pQuat)[Z] = quatDown( ((CStandardAnimQKey*)p_in)->qz );\r\n//\t\t(*pQuat)[W] = quatDown( ((CStandardAnimQKey*)p_in)->qw );\r\n\t}\r\n\t\r\n\tfloat qx = (*pQuat)[X];\r\n\tfloat qy = (*pQuat)[Y];\r\n\tfloat qz = (*pQuat)[Z];\r\n\r\n\t// Dave note: added 09/12/02 - a simple check to ensure we don't try to take the square root of a negative\r\n\t// number, which will hose Nan-sensitive platforms later on...\r\n\tfloat sum\t= 1.0f - qx * qx - qy * qy - qz * qz;\r\n\t(*pQuat)[W] = sqrtf(( sum >= 0.0f ) ? sum : 0.0f );\r\n\t\r\n\tif ( p_in->signBit )\r\n\t{\r\n\t\t(*pQuat)[W] = -(*pQuat)[W];\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void set_key_from_rotation( CAnimQKey* p_in, float x, float y, float z, float w, bool isHiRes )\r\n{\r\n\tif ( isHiRes )\r\n\t{\r\n\t\t((CHiResAnimQKey*)p_in)->qx = x;\r\n\t\t((CHiResAnimQKey*)p_in)->qy = y;\r\n\t\t((CHiResAnimQKey*)p_in)->qz = z;\r\n//\t\t((CHiResAnimQKey*)p_in)->qw = w;\r\n\t\t((CHiResAnimQKey*)p_in)->signBit = ( w < 0.0f ) ? 1 : 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t((CStandardAnimQKey*)p_in)->qx = quatUp( x );\r\n\t\t((CStandardAnimQKey*)p_in)->qy = quatUp( y );\r\n\t\t((CStandardAnimQKey*)p_in)->qz = quatUp( z );\r\n//\t\t((CStandardAnimQKey*)p_in)->qw = quatUp( w );\r\n\t\t((CStandardAnimQKey*)p_in)->signBit = ( w < 0.0f ) ? 1 : 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void get_translation_from_key( CAnimTKey* p_in, Mth::Vector* pVector, bool isHiRes )\r\n{\r\n\tif ( isHiRes )\r\n\t{\r\n\t\t(*pVector)[X] = ((CHiResAnimTKey*)p_in)->tx;\r\n\t\t(*pVector)[Y] = ((CHiResAnimTKey*)p_in)->ty;\r\n\t\t(*pVector)[Z] = ((CHiResAnimTKey*)p_in)->tz;\r\n\t\t(*pVector)[W] = 1.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t(*pVector)[X] = transDown( ((CStandardAnimTKey*)p_in)->tx, 32.0f );\r\n\t\t(*pVector)[Y] = transDown( ((CStandardAnimTKey*)p_in)->ty, 32.0f );\r\n\t\t(*pVector)[Z] = transDown( ((CStandardAnimTKey*)p_in)->tz, 32.0f );\r\n\t\t(*pVector)[W] = 1.0f;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ninline void get_rotation_from_standard_key( CStandardAnimQKey* p_in, Mth::Quat* pQuat )\r\n{\r\n\tif ( p_in->qx == 0 && p_in->qy == 0 && p_in->qz == 0 )\r\n\t{\r\n\t\t// Optimization: this handles the identity rotation, which is so common that it's not\r\n\t\t// worth doing a square root...\r\n\t\tpQuat->SetVector( 0.0f, 0.0f, 0.0f );\r\n\t\tpQuat->SetScalar( 1.0f );\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tfloat qx = quatDown( p_in->qx );\r\n\tfloat qy = quatDown( p_in->qy );\r\n\tfloat qz = quatDown( p_in->qz );\r\n\r\n\t// Dave note: added 09/12/02 - a simple check to ensure we don't try\r\n\t// to take the square root of a negative number, which will hose \r\n\t// Nan-sensitive platforms later on...\r\n\tfloat sum = 1.0f - qx * qx - qy * qy - qz * qz;\r\n\t\r\n// This assert was firing off in one of the cutscenes...\r\n// probably worth looking into later...\r\n//\tDbg_Assert( sum >= 0.0f );\r\n\tif ( sum < 0.0f )\r\n\t{\r\n\t\tsum = 0.0f;\r\n\t}\r\n\r\n\t(*pQuat)[X] = qx;\r\n\t(*pQuat)[Y] = qy;\r\n\t(*pQuat)[Z] = qz;\r\n\t(*pQuat)[W] = ( p_in->signBit ) ? -sqrtf( sum ) : sqrtf( sum );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void get_translation_from_standard_key( CStandardAnimTKey* p_in, Mth::Vector* pVector )\r\n{\r\n\t(*pVector)[X] = transDown( p_in->tx, 32.0f );\r\n\t(*pVector)[Y] = transDown( p_in->ty, 32.0f );\r\n\t(*pVector)[Z] = transDown( p_in->tz, 32.0f );\r\n\t(*pVector)[W] = 1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t\t  \r\ninline void set_key_from_translation( CAnimTKey* p_in, float x, float y, float z, bool isHiRes )\r\n{\r\n\tif ( isHiRes )\r\n\t{\r\n\t\t((CHiResAnimTKey*)p_in)->tx = x;\r\n\t\t((CHiResAnimTKey*)p_in)->ty = y;\r\n\t\t((CHiResAnimTKey*)p_in)->tz = z;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t((CStandardAnimTKey*)p_in)->tx = transUp( x, 32.0f );\r\n\t\t((CStandardAnimTKey*)p_in)->ty = transUp( y, 32.0f );\r\n\t\t((CStandardAnimTKey*)p_in)->tz = transUp( z, 32.0f );\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ninline void interpolate_q_frame(Mth::Quat* p_out, CAnimQKey* p_in1, CAnimQKey* p_in2, float alpha, bool isHiRes)\r\n{\r\n\tif ( alpha == 0.0f )\r\n\t{\r\n\t\t// don't need to slerp, because it's the start time\r\n\t\tget_rotation_from_key( p_in1, p_out, isHiRes );\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( alpha == 1.0f )\r\n\t{\r\n\t\t// don't need to slerp, because it's the end time\r\n\t\tget_rotation_from_key( p_in2, p_out, isHiRes );\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// INTERPOLATE Q-COMPONENT\r\n\r\n\tMth::Quat\tqIn1;\r\n\tMth::Quat   qIn2;\r\n\t\r\n\tget_rotation_from_key( p_in1, &qIn1, isHiRes );\r\n\tget_rotation_from_key( p_in2, &qIn2, isHiRes );\r\n    \r\n\t// Faster slerp, stolen from game developer magazine.\r\n\t*p_out = Mth::FastSlerp( qIn1, qIn2, alpha );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void interpolate_t_frame(Mth::Vector* p_out, CAnimTKey* p_in1, CAnimTKey* p_in2, float alpha, bool isHiRes)\r\n{\r\n\tif ( alpha == 0.0f )\r\n\t{\r\n\t\t// don't need to lerp, because it's the start time\r\n\t\tget_translation_from_key( p_in1, p_out, isHiRes );\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( alpha == 1.0f )\r\n\t{\r\n\t\t// don't need to slerp, because it's the end time\r\n\t\tget_translation_from_key( p_in2, p_out, isHiRes );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// INTERPOLATE T-COMPONENT\r\n\r\n    Mth::Vector   tIn1;\t\t\t\t\t  \r\n\tMth::Vector   tIn2;\r\n\t\r\n\tget_translation_from_key( p_in1, &tIn1, isHiRes );\r\n\t\r\n\tget_translation_from_key( p_in2, &tIn2, isHiRes );\r\n\r\n    /* Linearly interpolate positions */\r\n    *p_out = Mth::Lerp( tIn1, tIn2, alpha );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t\t  \r\ninline void interpolate_standard_q_frame(Mth::Quat* p_out, CStandardAnimQKey* p_in1, CStandardAnimQKey* p_in2, float alpha)\r\n{\r\n\tif ( alpha == 0.0f )\r\n\t{\r\n\t\t// don't need to slerp, because it's the start time\r\n\t\tget_rotation_from_standard_key( p_in1, p_out );\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( alpha == 1.0f )\r\n\t{\r\n\t\t// don't need to slerp, because it's the end time\r\n\t\tget_rotation_from_standard_key( p_in2, p_out );\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// INTERPOLATE Q-COMPONENT\r\n\tMth::Quat\tqIn1;\r\n\tMth::Quat   qIn2;\r\n\tget_rotation_from_standard_key( p_in1, &qIn1 );\r\n\tget_rotation_from_standard_key( p_in2, &qIn2 );\r\n\r\n\t// Faster slerp, stolen from game developer magazine.\r\n\t*p_out = Mth::FastSlerp( qIn1, qIn2, alpha );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void interpolate_standard_t_frame(Mth::Vector* p_out, CStandardAnimTKey* p_in1, CStandardAnimTKey* p_in2, float alpha)\r\n{\r\n\tif ( alpha == 0.0f )\r\n\t{\r\n\t\t// don't need to lerp, because it's the start time\r\n\t\tget_translation_from_standard_key( p_in1, p_out );\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( alpha == 1.0f )\r\n\t{\r\n\t\t// don't need to slerp, because it's the end time\r\n\t\tget_translation_from_standard_key( p_in2, p_out );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// INTERPOLATE T-COMPONENT\r\n\r\n    Mth::Vector   tIn1;\t\t\t\t\t  \r\n\tMth::Vector   tIn2;\r\n\t\r\n\tget_translation_from_standard_key( p_in1, &tIn1 );\r\n\t\r\n\tget_translation_from_standard_key( p_in2, &tIn2 );\r\n\r\n    /* Linearly interpolate positions */\r\n    *p_out = Mth::Lerp( tIn1, tIn2, alpha );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// eventually, this will go in the plat-specific version of CBonedAnimFrameData\r\n\r\nbool CBonedAnimFrameData::plat_dma_to_aram( int qbytes, int tbytes, uint32 flags )\r\n{\r\n\t// GameCube: DMA to ARAM.\r\n#ifdef __ARAM__\r\n\r\n\tif ( qbytes && tbytes )\r\n\t{\r\n\t\tuint32 address;\r\n\t\tuint size;\r\n//   \tuint32 header[8];\r\n\r\n//\t\t// Want this to happen even if asserts turned off.\r\n//\t\tif ( qbytes > (ARAM_CACHE_SIZE) )\r\n//\t\t{\r\n//\t\t\tOSReport( \"Too many q keys (%d)!!!\\n\", qbytes );\r\n//\t\t\twhile (1);\r\n//\t\t}\r\n//\r\n//\t\tif ( tbytes > (ARAM_CACHE_SIZE) )\r\n//\t\t{\r\n//\t\t\tOSReport( \"Too many t keys (%d)!!!\\n\", tbytes );\r\n//\t\t\twhile (1);\r\n//\t\t}\r\n//\r\n//\t\tif ( m_numBones > MAX_BONE_COUNT )\r\n//\t\t{\r\n//\t\t\tOSReport( \"Too many bones (%d)!!!\\n\", m_numBones );\r\n//\t\t\twhile (1);\r\n//\t\t}\r\n\r\n//\t\t// DMA partial animation data.\r\n//\t\tif ( m_flags & nxBONEDANIMFLAGS_PARTIALANIM )\r\n//\t\t{\r\n//\t\t\taddress = NsARAM::alloc( 32 );\r\n//\t\t\tNsDMA::toARAM( address, mp_partialAnimData, 32 );\r\n//\t\t\tmp_partialAnimData = (uint32*)address;\r\n//\t\t}\r\n\r\n\t\t// DMA per-bone frame count data.\r\n\t\tsize = m_numBones * sizeof(uint16) * 2;\r\n\t\tmemcpy( qqq, mp_perBoneQFrameSize, size );\r\n\t\tint part_size = 0;\r\n\t\tint frame_size = size;\r\n\t\tif ( m_flags & nxBONEDANIMFLAGS_PARTIALANIM )\r\n\t\t{\r\n\t\t\tpart_size = ( 1 + (( *mp_partialAnimData - 1 )/ 32) + 1 ) * sizeof( uint32 );\r\n\t\t\tmemcpy( &qqq[size], mp_partialAnimData, part_size );\r\n\t\t\tsize += part_size;\r\n\t\t}\r\n\t\tsize = ( ( size + 31 ) & ~31 ); \r\n\t\taddress = NsARAM::alloc( size );\r\n\t\tNsDMA::toARAM( address, qqq, size );\r\n\r\n\t\tmp_perBoneQFrameSize = (uint16*)address;\r\n\t\tmp_perBoneTFrameSize = (uint16*)address;\r\n\t\tif ( m_flags & nxBONEDANIMFLAGS_PARTIALANIM )\r\n\t\t{\r\n\t\t\tmp_partialAnimData = (uint32*)( address + frame_size );\r\n\t\t}\r\n\r\n//\t\tsize = m_numBones * sizeof(uint16) * 2;\r\n//\t\tsize = ( ( size + 31 ) & ~31 ); \r\n//\t\taddress = NsARAM::alloc( size );\r\n//\t\tNsDMA::toARAM( address, mp_perBoneQFrameSize, size );\r\n//\r\n//\t\tmp_perBoneQFrameSize = (uint16*)address;\r\n//\t\tmp_perBoneTFrameSize = (uint16*)address;\r\n\r\n\t\t// DMA Q frames to ARAM, delete RAM version & assign ARAM pointer.\r\n\t\tsize = qbytes/* + 32*/;\r\n\t\tsize = ( ( size + 31 ) & ~31 ); \r\n//\t\theader[0] = size;\r\n\t\taddress = NsARAM::alloc( size );\r\n//\t\tNsDMA::toARAM( address, header, 32 );\r\n\t\tNsDMA::toARAM( address/*+32*/, mp_qFrames, size );\r\n//\t\tdelete mp_qFrames;\r\n\t\tmp_qFrames = (char*)address;\r\n\r\n\t\t// DMA T frames to ARAM, delete RAM version & assign ARAM pointer.\r\n\t\tsize = tbytes/* + 32*/;\r\n\t\tsize = ( ( size + 31 ) & ~31 ); \r\n//\t\theader[0] = size;\r\n\t\taddress = NsARAM::alloc( size );\r\n//\t\tNsDMA::toARAM( address, header, 32 );\r\n\t\tNsDMA::toARAM( address/*+32*/, mp_tFrames, size );\r\n//\t\tdelete mp_tFrames;\r\n\t\tmp_tFrames = (char*)address;\r\n\r\n\t\t// hijack this pointer as it won't be used.\r\n\t\tmp_boneNames = (uint32*)( ( qbytes << 16 ) | tbytes );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( is_hires() )\r\n\t\t{\r\n\t\t\tuint32 address;\r\n\t\t\tuint size;\r\n\r\n//\t\t\t// Want this to happen even if asserts turned off.\r\n//\t\t\tif ( ( m_num_qFrames * sizeof( CHiResAnimQKey ) ) > (ARAM_CACHE_SIZE) )\r\n//\t\t\t{\r\n//\t\t\t\tOSReport( \"Too many q keys (%d)!!!\\n\", m_num_qFrames );\r\n//\t\t\t\twhile (1);\r\n//\t\t\t}\r\n//\r\n//\t\t\tif ( ( m_num_tFrames * sizeof( CHiResAnimTKey ) ) > (ARAM_CACHE_SIZE) )\r\n//\t\t\t{\r\n//\t\t\t\tOSReport( \"Too many t keys (%d)!!!\\n\", m_num_tFrames );\r\n//\t\t\t\twhile (1);\r\n//\t\t\t}\r\n//\r\n\r\n//\t\t\t// DMA partial animation data.\r\n//\t\t\tif ( m_flags & nxBONEDANIMFLAGS_PARTIALANIM )\r\n//\t\t\t{\r\n//\t\t\t\tuint32 * pData = mp_partialAnimData;\r\n//\t\t\t\tint numBones = *pData;\r\n//\r\n//\t\t\t\tint numMasks = (( numBones - 1 )/ 32) + 1;\t\t\r\n//\t\t\t\tsize = sizeof( int ) + ( numMasks * sizeof( uint32 ) ); \r\n//\r\n//\t\t\t\theader[0] = size;\r\n//\t\t\t\taddress = NsARAM::alloc( size );\r\n//\t\t\t\tNsDMA::toARAM( address, header, 32 );\r\n//\t\t\t\tNsDMA::toARAM( address+32, mp_partialAnimData, size );\r\n//\t\t\t\tmp_partialAnimData = (char*)address;\r\n//\t\t\t}\r\n\t\t\tmp_partialAnimData = NULL;\r\n\r\n\t\t\t// DMA per-bone frame count data.\r\n\t\t\tvoid * ptr;\r\n\t\t\tif ( m_flags & nxBONEDANIMFLAGS_OBJECTANIMDATA )\r\n\t\t\t{\r\n\t\t\t\tsize = ( m_numBones * sizeof(uint32) );\r\n\t\t\t\tptr = mp_boneNames;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsize = 0;\r\n\t\t\t\tptr = mp_perBoneFrames;\r\n\t\t\t}\r\n\r\n\t\t\tif ( m_flags & nxBONEDANIMFLAGS_HIRESFRAMEPOINTERS )\r\n\t\t\t{\r\n\t\t\t\tsize += ( m_numBones * sizeof(SHiResAnimFramePointers) );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsize += ( m_numBones * sizeof(SStandardAnimFramePointers) );\r\n\t\t\t}\r\n\r\n\t\t\tif ( size > ( MAX_BONE_COUNT * 2 * sizeof(uint16) ) )\r\n\t\t\t{\r\n\t\t\t\tOSReport( \"Too many bones (%d)!!!\\n\", m_numBones );\r\n\t\t\t\twhile (1);\r\n\t\t\t}\r\n\r\n\t\t\tsize = ( ( size + 31 ) & ~31 ); \r\n\t\t\taddress = NsARAM::alloc( size );\r\n\t\t\tNsDMA::toARAM( address, ptr, size );\r\n\r\n\t\t\tmp_perBoneFrames = (uint16*)address;\r\n\t\t\tmp_perBoneQFrameSize = (uint16*)address;\t\t// So that it can be deallocated.\r\n\r\n\t\t\t// DMA Q frames to ARAM, delete RAM version & assign ARAM pointer.\r\n//\t\t\tDbg_MsgAssert( m_num_qFrames <= (ARAM_CACHE_SIZE), ( \"Too many hires Q keys (%d) - maximum is %d\", m_num_qFrames, (ARAM_CACHE_SIZE) ) );\r\n\t\t\tsize = sizeof( CHiResAnimQKey ) * m_num_qFrames;\r\n\t\t\tsize = ( ( size + 31 ) & ~31 ); \r\n\t\t\taddress = NsARAM::alloc( size );\r\n\t\t\tNsDMA::toARAM( address, mp_qFrames, size );\r\n//\t\t\tdelete mp_qFrames;\r\n\t\t\tmp_qFrames = (char*)address;\r\n\r\n\t\t\t// DMA T frames to ARAM, delete RAM version & assign ARAM pointer.\r\n//\t\t\tDbg_MsgAssert( m_num_tFrames <= (ARAM_CACHE_SIZE), ( \"Too many hires T keys (%d) - maximum is %d\", m_num_tFrames, (ARAM_CACHE_SIZE) ) );\r\n\t\t\tsize = sizeof( CHiResAnimTKey ) * m_num_tFrames;\r\n\t\t\tsize = ( ( size + 31 ) & ~31 ); \r\n\t\t\taddress = NsARAM::alloc( size );\r\n\t\t\tNsDMA::toARAM( address, mp_tFrames, size );\r\n//\t\t\tdelete mp_tFrames;\r\n\t\t\tmp_tFrames = (char*)address;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tuint32 address;\r\n\t\t\tuint size;\r\n\r\n//\t\t\t// Want this to happen even if asserts turned off.\r\n//\t\t\tif ( ( m_num_qFrames * sizeof( CStandardAnimQKey ) ) > (ARAM_CACHE_SIZE) )\r\n//\t\t\t{\r\n//\t\t\t\tOSReport( \"Too many q keys (%d)!!!\\n\", m_num_qFrames );\r\n//\t\t\t\twhile (1);\r\n//\t\t\t}\r\n//\r\n//\t\t\tif ( ( m_num_tFrames * sizeof( CStandardAnimTKey ) ) > (ARAM_CACHE_SIZE) )\r\n//\t\t\t{\r\n//\t\t\t\tOSReport( \"Too many t keys (%d)!!!\\n\", m_num_tFrames );\r\n//\t\t\t\twhile (1);\r\n//\t\t\t}\r\n//\r\n\r\n//\t\t\t// DMA partial animation data.\r\n//\t\t\tif ( m_flags & nxBONEDANIMFLAGS_PARTIALANIM )\r\n//\t\t\t{\r\n//\t\t\t\tuint32 * pData = mp_partialAnimData;\r\n//\t\t\t\tint numBones = *pData;\r\n//\r\n//\t\t\t\tint numMasks = (( numBones - 1 )/ 32) + 1;\t\t\r\n//\t\t\t\tsize = sizeof( int ) + ( numMasks * sizeof( uint32 ) ); \r\n//\r\n//\t\t\t\theader[0] = size;\r\n//\t\t\t\taddress = NsARAM::alloc( size );\r\n//\t\t\t\tNsDMA::toARAM( address, header, 32 );\r\n//\t\t\t\tNsDMA::toARAM( address+32, mp_partialAnimData, size );\r\n//\t\t\t\tmp_partialAnimData = (char*)address;\r\n//\t\t\t}\r\n\t\t\tmp_partialAnimData = NULL;\r\n\r\n\t\t\t// DMA per-bone frame count data.\r\n\t\t\tvoid * ptr;\r\n\t\t\tif ( m_flags & nxBONEDANIMFLAGS_OBJECTANIMDATA )\r\n\t\t\t{\r\n\t\t\t\tsize = ( m_numBones * sizeof(uint32) );\r\n\t\t\t\tptr = mp_boneNames;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsize = 0;\r\n\t\t\t\tptr = mp_perBoneFrames;\r\n\t\t\t}\r\n\r\n\t\t\tif ( m_flags & nxBONEDANIMFLAGS_HIRESFRAMEPOINTERS )\r\n\t\t\t{\r\n\t\t\t\tsize += ( m_numBones * sizeof(SHiResAnimFramePointers) );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsize += ( m_numBones * sizeof(SStandardAnimFramePointers) );\r\n\t\t\t}\r\n\r\n\t\t\tif ( size > ( MAX_BONE_COUNT * 2 * sizeof(uint16) ) )\r\n\t\t\t{\r\n\t\t\t\tOSReport( \"Too many bones (%d)!!!\\n\", m_numBones );\r\n\t\t\t\twhile (1);\r\n\t\t\t}\r\n\r\n\t\t\tsize = ( ( size + 31 ) & ~31 ); \r\n\t\t\taddress = NsARAM::alloc( size );\r\n\t\t\tNsDMA::toARAM( address, ptr, size );\r\n\r\n\t\t\tmp_perBoneFrames = (uint16*)address;\r\n\t\t\tmp_perBoneQFrameSize = (uint16*)address;\t\t// So that it can be deallocated.\r\n\r\n\t\t\t// DMA Q frames to ARAM, delete RAM version & assign ARAM pointer.\r\n//\t\t\tDbg_MsgAssert( m_num_qFrames <= (short)MAX_STANDARD_Q, ( \"Too many standard Q keys (%d) - maximum is %d\", m_num_qFrames, MAX_STANDARD_Q ) );\r\n\t\t\tsize = sizeof( CStandardAnimQKey ) * m_num_qFrames;\r\n\t\t\tsize = ( ( size + 31 ) & ~31 ); \r\n\t\t\taddress = NsARAM::alloc( size );\r\n\t\t\tNsDMA::toARAM( address, mp_qFrames, size );\r\n//\t\t\tdelete mp_qFrames;\r\n\t\t\tmp_qFrames = (char*)address;\r\n\r\n\t\t\t// DMA T frames to ARAM, delete RAM version & assign ARAM pointer.\r\n//\t\t\tDbg_MsgAssert( m_num_tFrames <= (short)MAX_STANDARD_T, ( \"Too many standard T keys (%d) - maximum is %d\", m_num_tFrames, MAX_STANDARD_T ) );\r\n\t\t\tsize = sizeof( CStandardAnimTKey ) * m_num_tFrames;\r\n\t\t\tsize = ( ( size + 31 ) & ~31 ); \r\n\t\t\taddress = NsARAM::alloc( size );\r\n\t\t\tNsDMA::toARAM( address, mp_tFrames, size );\r\n//\t\t\tdelete mp_tFrames;\r\n\t\t\tmp_tFrames = (char*)address;\r\n\t\t}\r\n\t}\r\n\r\n#endif\t\t// __ARAM__\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CBonedAnimFrameData::plat_read_compressed_stream(uint8* pData, bool delete_buffer)\r\n{\r\n\tDbg_Assert( pData );\r\n\r\n\tSPlatformFileHeader *pThePlatformHeader = (SPlatformFileHeader *) pData;\r\n\tpData += sizeof(SPlatformFileHeader);\r\n\r\n\tm_numBones = pThePlatformHeader->numBones;\r\n\tm_num_qFrames = pThePlatformHeader->numQKeys;\r\n\tm_num_tFrames = pThePlatformHeader->numTKeys;\r\n\t\r\n\tuint32 qAllocSize = *((uint32*)pData);\r\n\tpData += sizeof(uint32);\r\n\r\n\tuint32 tAllocSize = *((uint32*)pData);\r\n\tpData += sizeof(uint32);\r\n\r\n\tmp_perBoneQFrameSize = (uint16*)pData;\r\n\tpData += ( m_numBones * sizeof(uint16) );\r\n\t\r\n\tmp_perBoneTFrameSize = (uint16*)pData;\r\n\tpData += ( m_numBones * sizeof(uint16) );\r\n\r\n\t// long-align\r\n\tif ( (uint32)pData & 0x3 )\r\n\t{\r\n\t\tpData += ( 4 - ((uint32)pData & 0x3) );\r\n\t}\r\n\t\r\n\t// first read in object anim bone names, if any\r\n\tif ( m_flags & nxBONEDANIMFLAGS_OBJECTANIMDATA )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Wasn't expecting object anims to be compressed\" ) );\r\n\t\tmp_boneNames = NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_boneNames = NULL;\r\n\t}\r\n\t\r\n\tif ( m_flags & nxBONEDANIMFLAGS_PARTIALANIM )\r\n\t{\r\n\t\tDbg_Assert(!((uint32)pData & 0x3));\r\n\t\t\r\n\t\tmp_partialAnimData = (uint32*)pData;\r\n\t\t\r\n\t\t// skip original number of bones\r\n\t\tint numBones = *((uint32*)pData);\r\n\t\tpData += sizeof( int );\r\n\t\t\r\n\t\tint numMasks = (( numBones - 1 )/ 32) + 1;\t\t\r\n\t\tpData += ( numMasks * sizeof( uint32 ) );\r\n\t}\r\n\r\n\t// long-align\r\n\tif ( (uint32)pData & 0x3 )\r\n\t{\r\n\t\tpData += ( 4 - ((uint32)pData & 0x3) );\r\n\t}\r\n\t\t\r\n\tif ( is_hires() )\r\n\t{\r\n\t\tDbg_MsgAssert( !is_hires(), ( \"Hi res format not supported for compressed anims\" ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_qFrames = (char*)pData;\r\n\t\tpData += qAllocSize;\r\n\t\t\r\n\t\tmp_tFrames = (char*)pData;\r\n\t\tpData += tAllocSize;\r\n\t}\r\n\t\r\n\tDbg_Assert( mp_perBoneFrames == NULL );\r\n\tDbg_Assert( mp_qFrames );\r\n\tDbg_Assert( mp_tFrames );\r\n    \r\n\t// dma to aram here...\r\n\tplat_dma_to_aram( qAllocSize, tAllocSize );\r\n\r\n\t// GJ:  be able to PIP the custom keys in as well\r\n\r\n\t// long-align\r\n\tif ( (uint32)pData & 0x3 )\r\n\t{\r\n\t\tpData += ( 4 - ((uint32)pData & 0x3) );\r\n\t}\r\n   \r\n\t// create an array of pointers to the custom keys\r\n\tif ( !pThePlatformHeader->numCustomAnimKeys )\r\n\t{\r\n\t\tmpp_customAnimKeyList = NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmpp_customAnimKeyList = (CCustomAnimKey **)(Mem::Malloc(pThePlatformHeader->numCustomAnimKeys*sizeof(CCustomAnimKey *)));\r\n\t\t\r\n\t\t// read custom keys\r\n\t\tfor ( uint32 i = 0; i < pThePlatformHeader->numCustomAnimKeys; i++ )\r\n\t\t{\r\n\t\t\tCCustomAnimKey* pKey = ReadCustomAnimKey( &pData );\r\n\t\t\tif ( !pKey )\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"Failed while reading custom data\" );\r\n\t\t\t\treturn false;\r\n\t\t\t}\t\t\r\n\t\t\tmpp_customAnimKeyList[i] = pKey;\r\n\t\t}\r\n\t}\t\t\r\n\r\n\tm_num_customKeys = pThePlatformHeader->numCustomAnimKeys;\r\n\r\n#ifdef __ARAM__\r\n\tif ( delete_buffer )\r\n\t{\r\n\t\tdelete mp_fileBuffer;\r\n\t}\r\n\tmp_fileBuffer = NULL;\r\n#endif\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBonedAnimFrameData::plat_read_stream(uint8* pData, bool delete_buffer)\r\n{\r\n\tDbg_Assert( pData );\r\n\r\n\tSPlatformFileHeader* pThePlatformHeader = (SPlatformFileHeader*)pData;\r\n\tpData += sizeof(SPlatformFileHeader);\r\n\tDbg_Assert(!((uint) pData & 0x3));\r\n\r\n\tm_numBones = pThePlatformHeader->numBones;\r\n\tm_num_qFrames = pThePlatformHeader->numQKeys;\r\n\tm_num_tFrames = pThePlatformHeader->numTKeys;\r\n\t\r\n\tDbg_Assert( !mp_perBoneFrames );\r\n\tDbg_Assert( !mp_qFrames );\r\n\tDbg_Assert( !mp_tFrames );\r\n\t\r\n\t// first read in object anim bone names, if any\r\n\tif ( m_flags & nxBONEDANIMFLAGS_OBJECTANIMDATA )\r\n\t{\r\n\t\tDbg_Assert(!((uint) pData & 0x3));\r\n\t\tmp_boneNames = (uint32*)pData;\r\n\t\tpData += ( m_numBones * sizeof(uint32) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_boneNames = NULL;\r\n\t}\r\n\r\n\tif ( m_flags & nxBONEDANIMFLAGS_PARTIALANIM )\r\n\t{\r\n\t\tDbg_Assert(!((uint32)pData & 0x3));\r\n\t\t\r\n\t\tmp_partialAnimData = (uint32*)pData;\r\n\t\t\r\n\t\t// skip original number of bones\r\n\t\tint numBones = *((uint32*)pData);\r\n\t\tpData += sizeof( int );\r\n\t\t\r\n\t\tint numMasks = (( numBones - 1 )/ 32) + 1;\t\t\r\n\t\tpData += ( numMasks * sizeof( uint32 ) );\r\n\t}\r\n\r\n\t// now, read in the per-bone frames of the correct size\r\n\tif ( m_flags & nxBONEDANIMFLAGS_HIRESFRAMEPOINTERS )\r\n\t{\r\n\t\tmp_perBoneFrames = pData;\r\n\t\tpData += ( m_numBones * sizeof(SHiResAnimFramePointers) );\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_perBoneFrames = pData;\r\n\t\tpData += ( m_numBones * sizeof(SStandardAnimFramePointers) );\t\t\r\n\t}\r\n\r\n\t// long-align\r\n\tif ( (uint32)pData & 0x3 )\r\n\t{\r\n\t\tpData += ( 4 - ((uint32)pData & 0x3) );\r\n\t}\r\n   \r\n\t// count to make sure the number of keys per bone didn't overflow\r\n\tint runningQCount = 0;\r\n\tint runningTCount = 0;\r\n\r\n\tfor ( int i = 0; i < m_numBones; i++ )\r\n\t{\r\n\t\trunningQCount += get_num_qkeys( mp_perBoneFrames, i );\r\n\t\trunningTCount += get_num_tkeys( mp_perBoneFrames, i );\r\n\t}\r\n\r\n\tDbg_MsgAssert( runningQCount == m_num_qFrames, ( \"Wrong number of qframes in %x %d %d\", m_fileNameCRC, runningQCount, m_num_qFrames ) );\r\n\tDbg_MsgAssert( runningTCount == m_num_tFrames, ( \"Wrong number of tframes in %x %d %d\", m_fileNameCRC, runningTCount, m_num_tFrames ) );\r\n\r\n\tif ( is_hires() )\r\n\t{\r\n\t\tDbg_Assert(!((uint) pData & 0x3));\r\n\t\tmp_qFrames = (char*)pData;\r\n\t\tpData += ( m_num_qFrames * sizeof(CHiResAnimQKey) );\r\n\t\t\r\n\t\tDbg_Assert(!((uint) pData & 0x3));\r\n\t\tmp_tFrames = (char*)pData;\r\n\t\tpData += ( m_num_tFrames * sizeof(CHiResAnimTKey) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Assert(!((uint) pData & 0x3));\r\n\t\tmp_qFrames = (char*)pData;\r\n\t\tpData += ( m_num_qFrames * sizeof(CStandardAnimQKey) );\r\n\t\t\r\n\t\tDbg_Assert(!((uint) pData & 0x3));\r\n\t\tmp_tFrames = (char*)pData;\r\n\t\tpData += ( m_num_tFrames * sizeof(CStandardAnimTKey) );\r\n\t}\r\n\t\r\n\tDbg_Assert( mp_perBoneFrames );\r\n\tDbg_Assert( mp_qFrames );\r\n\tDbg_Assert( mp_tFrames );\r\n    \r\n\t// dma to aram here...\r\n\tplat_dma_to_aram( 0, 0, m_flags );\r\n\r\n\t// GJ:  be able to PIP the custom keys in as well\r\n\r\n\t// long-align\r\n\tif ( (uint32)pData & 0x3 )\r\n\t{\r\n\t\tpData += ( 4 - ((uint32)pData & 0x3) );\r\n\t}\r\n   \r\n\t// create an array of pointers to the custom keys\r\n\tif ( !pThePlatformHeader->numCustomAnimKeys )\r\n\t{\r\n\t\tmpp_customAnimKeyList = NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmpp_customAnimKeyList = (CCustomAnimKey **)(Mem::Malloc(pThePlatformHeader->numCustomAnimKeys*sizeof(CCustomAnimKey *)));\r\n\t\t\r\n\t\t// read custom keys\r\n\t\tfor ( uint32 i = 0; i < pThePlatformHeader->numCustomAnimKeys; i++ )\r\n\t\t{\r\n\t\t\tCCustomAnimKey* pKey = ReadCustomAnimKey( &pData );\r\n\t\t\tif ( !pKey )\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"Failed while reading custom data\" );\r\n\t\t\t\treturn false;\r\n\t\t\t}\t\t\r\n\t\t\tmpp_customAnimKeyList[i] =  pKey;\r\n\t\t}\r\n\t}\t\t\r\n\r\n\tm_num_customKeys = pThePlatformHeader->numCustomAnimKeys;\r\n\r\n#ifdef __ARAM__\r\n\tif ( delete_buffer )\r\n\t{\r\n\t\tdelete mp_fileBuffer;\r\n\t}\r\n\tmp_fileBuffer = NULL;\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CBonedAnimFrameData::get_num_qkeys( void * p_frame_data, int boneIndex ) const\r\n{\r\n\tif ( m_flags & nxBONEDANIMFLAGS_HIRESFRAMEPOINTERS )\r\n\t{\r\n\t\tSHiResAnimFramePointers* pFramePointers = (SHiResAnimFramePointers*)p_frame_data;\r\n\t\t\r\n\t\tpFramePointers += boneIndex;\r\n\r\n\t\treturn pFramePointers->numQKeys;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSStandardAnimFramePointers* pFramePointers = (SStandardAnimFramePointers*)p_frame_data;\r\n\t\t\r\n\t\tpFramePointers += boneIndex;\r\n\r\n\t\treturn pFramePointers->numQKeys;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CBonedAnimFrameData::get_num_tkeys( void * p_frame_data, int boneIndex ) const\r\n{\r\n\tif ( m_flags & nxBONEDANIMFLAGS_HIRESFRAMEPOINTERS )\r\n\t{\r\n\t\tSHiResAnimFramePointers* pFramePointers = (SHiResAnimFramePointers*)p_frame_data;\r\n\t\t\r\n\t\tpFramePointers += boneIndex;\r\n\r\n\t\treturn pFramePointers->numTKeys;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSStandardAnimFramePointers* pFramePointers = (SStandardAnimFramePointers*)p_frame_data;\r\n\t\t\r\n\t\tpFramePointers += boneIndex;\r\n\r\n\t\treturn pFramePointers->numTKeys;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CBonedAnimFrameData::is_hires() const\r\n{\r\n\treturn ( m_flags & nxBONEDANIMFLAGS_CAMERADATA ) || ( m_flags & nxBONEDANIMFLAGS_OBJECTANIMDATA );\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBonedAnimFrameData::CBonedAnimFrameData()\r\n{\r\n\tm_duration = 0.0f;\r\n\tm_numBones = 0;\r\n\r\n\tmp_fileBuffer = NULL;\r\n\tmp_fileHandle = NULL;\r\n\tm_dataLoaded = false;\r\n\r\n\tmp_qFrames = NULL;\t\r\n\tmp_tFrames = NULL;\r\n\r\n\tmp_perBoneFrames = NULL;\r\n\tmp_boneNames = NULL;\r\n\r\n\tmp_perBoneQFrameSize = NULL;\r\n\tmp_perBoneTFrameSize = NULL;\r\n\r\n\tm_printDebugInfo = false;\r\n\r\n\tm_num_customKeys = 0;\r\n\r\n\tmpp_customAnimKeyList = NULL;\r\n\tm_fileNameCRC = 0;\r\n\tm_pipped = false;\r\n\r\n\tmp_partialAnimData = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBonedAnimFrameData::~CBonedAnimFrameData()\r\n{\r\n\r\n\tfor (int i=0;i<m_num_customKeys;i++)\r\n\t{\r\n\t\tdelete mpp_customAnimKeyList[i];\r\n\t}\r\n\r\n\tif ( mpp_customAnimKeyList )\r\n\t{\r\n\t\tMem::Free( mpp_customAnimKeyList );\r\n\t}\r\n\r\n\tif ( m_pipped )\r\n\t{\r\n\t\tPip::Unload( m_fileNameCRC );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (mp_fileBuffer)\r\n\t\t{\r\n\t\t\tMem::Free(mp_fileBuffer);\r\n\t\t}\r\n\t}\r\n\r\n\tif (mp_fileHandle)\r\n\t{\r\n\t\tDbg_MsgAssert(m_dataLoaded, (\"Can't delete CBonedAnimFrameData while it is still being loaded\"));\r\n\t\tFile::CAsyncFileLoader::sClose( mp_fileHandle );\r\n\t}\r\n\r\n#ifdef __ARAM__\r\n\t// This relies on all level-specific anims being deallocated (a reasonable dependency).\r\n\t// Animations can be deleted in any order, the lowest address is the base address for the next level.\r\n\tNsARAM::free( (uint32)mp_perBoneQFrameSize );\r\n\tNsARAM::free( (uint32)mp_qFrames );\r\n\tNsARAM::free( (uint32)mp_tFrames );\r\n//\tif ( ( m_flags & nxBONEDANIMFLAGS_PARTIALANIM ) && mp_partialAnimData )\r\n//\t{\r\n//\t\tNsARAM::free( (uint32)mp_partialAnimData ); \r\n//\t}\r\n#else\r\n\r\n#endif\t\t// __ARAM__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CBonedAnimFrameData::Load(uint32* pData, int file_size, bool assertOnFail)\r\n{\r\n\t// TODO:  We should read in the entire file into memory first, because\r\n\t// using streams is slow.\r\n\r\n\tDbg_Assert( !m_dataLoaded );\r\n\r\n\tm_fileNameCRC = 0;\r\n\r\n\tDbg_MsgAssert( pData, ( \"No data pointer specified\" ) );\r\n\tDbg_MsgAssert(file_size, (\"Anim file size is 0\"));\r\n\tDbg_Assert(!mp_fileBuffer);\r\n\r\n#ifdef __ARAM__\r\n\tmp_fileBuffer = pData;\r\n\treturn PostLoad(assertOnFail, file_size, false);\r\n#else\r\n//\tNow that we're pipping it, we don't have to force this on the top-down heap\r\n//\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tmp_fileBuffer = (void *) Mem::Malloc( file_size );\r\n//\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\t// copy the data into the temporary buffer\r\n\tmemcpy( mp_fileBuffer, pData, file_size );\r\n\r\n//\tprintf( \"Loading data:  %08x %08x %08x %d\\n\", *pData, mp_fileBuffer, pData, file_size );\r\n\r\n\treturn PostLoad(assertOnFail, file_size);\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CBonedAnimFrameData::Load(const char* p_fileName, bool assertOnFail, bool async, bool use_pip)\r\n{         \r\n\t// TODO:  We should read in the entire file into memory first, because\r\n\t// using streams is slow.\r\n\r\n\tDbg_Assert( p_fileName );\r\n\tDbg_Assert( !m_dataLoaded );\r\n\r\n\tchar test[256];\r\n\tstrcpy( test, p_fileName );\r\n\tStr::LowerCase( test );\r\n\tm_fileNameCRC = Crc::GenerateCRCFromString( test );\r\n\r\n\tint file_size = 0;\r\n\r\n\tchar filename[256];\r\n\tstrcpy( filename, p_fileName );\r\n\r\n\t// Turn off async for platforms that don't support it\r\n\tif (!File::CAsyncFileLoader::sAsyncSupported())\r\n\t{\r\n\t\tasync = false;\r\n\t}\r\n\r\n\tif ( async )\r\n\t{\r\n\t\tDbg_MsgAssert( !use_pip, ( \"Pip-files do not work with async-loaded anims\" ) );\r\n\r\n\t\t// Pre-load\r\n\t\tDbg_Assert(!mp_fileHandle);\r\n\r\n\t\tmp_fileHandle = File::CAsyncFileLoader::sOpen( p_fileName, !async );\r\n\r\n\t\t// make sure the file is valid\r\n\t\tif ( !mp_fileHandle )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( assertOnFail, (\"Load of %s failed - file not found?\", p_fileName) );\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tfile_size = mp_fileHandle->GetFileSize();\r\n\r\n\t\tDbg_MsgAssert(file_size, (\"Anim file size is 0\"));\r\n\r\n\t\tDbg_Assert(!mp_fileBuffer);\r\n//\t\tNow that we're pipping it, we don't have to force this on the top-down heap\r\n//\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\tmp_fileBuffer = (void *) Mem::Malloc( file_size );\r\n//\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t// Set the callback\r\n\t\tmp_fileHandle->SetCallback(async_callback, (unsigned int) this, (unsigned int) assertOnFail);\r\n\r\n\t\t// read the file in\r\n\t\tmp_fileHandle->Read( mp_fileBuffer, 1, file_size );\r\n\t\t//Dbg_Message(\"Started read of %x\", this);\r\n\r\n\t\t//mp_fileHandle->WaitForIO();\r\n\t\t//Dbg_Message(\"Done waiting for %x\", this);\r\n\r\n\t\t// Should be the callback\r\n\t\treturn true; //PostLoad(assertOnFail, file_size);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint file_size = 0;\r\n\r\n\t\tif ( use_pip )\r\n\t\t{\r\n\t\t\tmp_fileBuffer = Pip::Load( p_fileName );\r\n\t\t\tfile_size = Pip::GetFileSize( p_fileName );\r\n\t\t\tDbg_MsgAssert(file_size, (\"Anim file size is 0\"));\r\n\t\t\tm_pipped = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// open the file as a stream\r\n\t\t\tvoid* pStream = File::Open( p_fileName,\"rb\" );\r\n\t\t\t// make sure the file is valid\r\n\t\t\tif ( !pStream )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( assertOnFail, (\"Load of %s failed - file not found?\", p_fileName) );\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\tfile_size = File::GetFileSize(pStream);\r\n\t\t\tDbg_MsgAssert(file_size, (\"Anim file size is 0\"));\r\n\t\t\tDbg_Assert(!mp_fileBuffer);\r\n\t//\t\tNow that we're pipping it, we don't have to force this on the top-down heap\r\n\t//\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\tmp_fileBuffer = (void *) Mem::Malloc( file_size );\r\n\t//\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t\t// read the file in\r\n\t\t\tif ( !File::Read( mp_fileBuffer, 1, file_size, pStream ) )\r\n\t\t\t{\r\n\t\t\t\tMem::Free(mp_fileBuffer);\r\n\t\t\t\tmp_fileBuffer = NULL;\r\n\t\t\t\tFile::Close( pStream );\r\n\r\n\t\t\t\tDbg_MsgAssert( assertOnFail, (\"Load of %s failed - bad format?\", p_fileName) );\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tFile::Close(pStream);\r\n\t\t}\r\n\r\n\t\treturn PostLoad(assertOnFail, file_size);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBonedAnimFrameData::async_callback(File::CAsyncFileHandle *, File::EAsyncFunctionType function,\r\n\t\t\t\t\t\t\t\t\t\t int result, unsigned int arg0, unsigned int arg1)\r\n{\r\n\t//Dbg_Message(\"Got callback from %x\", arg0);\r\n\tif (function == File::FUNC_READ)\r\n\t{\r\n\t\tCBonedAnimFrameData *p_data = (CBonedAnimFrameData *) arg0;\r\n\t\tbool assert = (bool) arg1;\r\n\r\n\t\tp_data->PostLoad(assert, result);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBonedAnimFrameData::PostLoad(bool assertOnFail, int file_size, bool delete_buffer)\r\n{\r\n\tbool success = false;\r\n\r\n\t//Dbg_Message(\"PostLoad of %x\", this);\r\n\r\n\t// Handle end of async, if that was used\r\n\tif (mp_fileHandle)\r\n\t{\r\n#if 0\r\n\t\tif (mp_fileHandle->WaitForIO() != file_size)\r\n\t\t{\r\n\t\t\tMem::Free(mp_fileBuffer);\r\n\t\t\tmp_fileBuffer = NULL;\r\n\t\t\tFile::CAsyncFileLoader::sClose( mp_fileHandle );\r\n\t\t\tmp_fileHandle = NULL;\r\n\r\n\t\t\tDbg_MsgAssert( assertOnFail, (\"PostLoad of anim file failed - bad format?\") );\r\n\t\t\treturn false;\r\n\t\t}\r\n#endif\r\n\t\tFile::CAsyncFileLoader::sClose( mp_fileHandle );\r\n\t\tmp_fileHandle = NULL;\r\n\t}\r\n\r\n\tuint8 *pFileData = (uint8 *) mp_fileBuffer;\r\n\r\n\t// read in header information\r\n\tSBonedAnimFileHeader* pTheHeader = (SBonedAnimFileHeader*)pFileData;\r\n\tpFileData += sizeof(SBonedAnimFileHeader);\r\n\r\n\t// store header information\r\n\tm_duration = pTheHeader->duration;\r\n\r\n\tm_flags = pTheHeader->flags;\r\n\r\n\t// trying to phase out the old partial anim format here...\r\n\tDbg_MsgAssert( ( m_flags & nxBONEDANIMFLAGS_OLDPARTIALANIM ) == 0, ( \"No longer supporting old partial anim format\" ) ); \r\n\r\n\t// the anim converter should automatically do this,\r\n\t// so that we don't have to do it at runtime...\r\n\tDbg_MsgAssert( pTheHeader->flags & nxBONEDANIMFLAGS_COMPRESSEDTIME, ( \"Expected the anim times to be in frames\" ) );\r\n\tDbg_MsgAssert( pTheHeader->flags & nxBONEDANIMFLAGS_PREROTATEDROOT, ( \"Expected the root bones to be prerotated\" ) );\r\n\r\n\t// some debugging information\r\n//\tDbg_Message( \"Loading animation %s\", p_fileName );\r\n//\tDbg_Message( \"Duration = %f\", m_duration );\r\n//\tDbg_Message( \"Flags = %08x\", theHeader.flags );\r\n\r\n\t// read the stream differently based on whether it's compressed...\r\n    if ( pTheHeader->flags & nxBONEDANIMFLAGS_PLATFORM )\r\n    {\r\n\t\tDbg_Assert( (pTheHeader->flags & nxBONEDANIMFLAGS_USECOMPRESSTABLE) == 0 );\r\n\t\tsuccess = this->plat_read_stream( pFileData, delete_buffer );\r\n    }\r\n    else if ( pTheHeader->flags & nxBONEDANIMFLAGS_USECOMPRESSTABLE )\r\n    {\r\n\t\tDbg_Assert( (pTheHeader->flags & nxBONEDANIMFLAGS_PLATFORM) == 0 );\r\n\t\tsuccess = this->plat_read_compressed_stream( pFileData, delete_buffer );\r\n    }\r\n    else\r\n    {\r\n        Dbg_MsgAssert( 0, (\"Unrecognized file format (flags = %08x)...\", pTheHeader->flags) );\r\n    }\r\n\r\n\t// handle failure\r\n\tDbg_MsgAssert( success || !assertOnFail, (\"PostLoad of anim file failed - bad format?\") );\r\n\r\n\tif ( !m_pipped )\r\n\t{\r\n\t// Done with temp buffer (since it's pipped, don't delete the file buffer)\r\n//\tMem::Free(mp_fileBuffer);\r\n//\tmp_fileBuffer = NULL;\r\n\t}\r\n\tm_dataLoaded = success;\r\n\r\n    return success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBonedAnimFrameData::IsValidTime( float time )\r\n{\r\n\treturn ( time >= 0.0f && time < m_duration );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float get_alpha( float timeStamp1, float timeStamp2, float time )\r\n{\r\n\tDbg_MsgAssert(timeStamp1 <= time && timeStamp2 >= time, ( \"%f should be within [%f %f]\", time, timeStamp1, timeStamp2 ));\r\n    \r\n\treturn (( time - timeStamp1 ) / ( timeStamp2 - timeStamp1 ));\r\n}\r\n\r\n// THE FOLLOWING 2 FUNCTIONS SHOULD BE REFACTORED?\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBonedAnimFrameData::GetInterpolatedCameraFrames(Mth::Quat* pRotations, Mth::Vector* pTranslations, float time, Nx::CQuickAnim* pQuickAnim )\r\n{\r\n    Dbg_Assert( pRotations );\r\n    Dbg_Assert( pTranslations );\r\n\r\n\tDbg_Assert( is_hires() );\r\n\t\r\n\tfloat qAlpha = 0.0f;\r\n\tfloat tAlpha = 0.0f;\r\n\r\n\t// DMA the animation data here.\r\n#ifdef __ARAM__\r\n\tint\t\tsize;\r\n\tif ( m_flags & nxBONEDANIMFLAGS_OBJECTANIMDATA )\r\n\t{\r\n\t\tsize = ( m_numBones * sizeof(uint32) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsize = 0;\r\n\t}\r\n\r\n\tif ( m_flags & nxBONEDANIMFLAGS_HIRESFRAMEPOINTERS )\r\n\t{\r\n\t\tsize += ( m_numBones * sizeof(SHiResAnimFramePointers) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsize += ( m_numBones * sizeof(SStandardAnimFramePointers) );\r\n\t}\r\n\tdma_count( (uint32)mp_perBoneFrames, size );\r\n\twhile ( framecount_active );\r\n//\tif ( m_flags & nxBONEDANIMFLAGS_PARTIALANIM )\r\n//\t{\r\n//\t\tdma_partial( (uint32)mp_partialAnimData, ( m_numBones * sizeof( uint16 ) * 2 ) );\r\n//\t}\r\n//\twhile ( framecount_active );\r\n\r\n//\tNsDMA::toMRAM( qqq, (uint32)mp_qFrames, m_num_qFrames * sizeof( CHiResAnimQKey ) );\r\n//\tNsDMA::toMRAM( ttt, (uint32)mp_tFrames, m_num_tFrames * sizeof( CHiResAnimTKey ) );\r\n\r\n//\twhile( framecount_active );\r\n#endif\t\t// __ARAM__\r\n\r\n\t// find the nearest 2 keyframes\r\n\tfloat qTimeStamp = time * 60.0f;\r\n\tfloat tTimeStamp = time * 60.0f;\r\n\t\r\n\tCHiResAnimQKey* pStartQFrame = NULL;\r\n\tCHiResAnimQKey* pEndQFrame = NULL;\r\n\r\n\tCHiResAnimTKey* pStartTFrame = NULL;\r\n\tCHiResAnimTKey* pEndTFrame = NULL;\r\n\r\n\tCHiResAnimQKey* pCurrentQFrame = NULL;\r\n\tCHiResAnimTKey* pCurrentTFrame = NULL;\r\n\t\r\n#ifdef __ARAM__\r\n//\tpStartQFrame = p_hqqq;\r\n//\tpEndQFrame = p_hqqq;\r\n//\r\n//\tpStartTFrame = p_httt;\r\n//\tpEndTFrame = p_httt;\r\n//\t\r\n//\tpCurrentQFrame = p_hqqq;\r\n//\tpCurrentTFrame = p_httt;\r\n\r\n\tuint32 anim_q_offset = (uint32)mp_qFrames;\r\n\tuint32 anim_t_offset = (uint32)mp_tFrames;\r\n\r\n\tvoid * p_bone_frames;\r\n\tif ( m_flags & nxBONEDANIMFLAGS_OBJECTANIMDATA )\r\n\t{\r\n\t\tp_bone_frames = &framecount[m_numBones*2];\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_bone_frames = framecount;\r\n\t}\r\n\r\n#else\r\n\tpStartQFrame = (CHiResAnimQKey*)mp_qFrames;\r\n\tpEndQFrame = pStartQFrame;\r\n\tpCurrentQFrame = pStartQFrame;\r\n\r\n\tpStartTFrame = (CHiResAnimTKey*)mp_tFrames;\r\n\tpEndTFrame = pStartTFrame;\r\n\tpCurrentTFrame = pStartTFrame;\r\n\r\n\tvoid * p_bone_frames = mp_perBoneFrames;\r\n#endif\t\t// __aram__\r\n\r\n\tfor ( int i = 0; i < m_numBones; i++ )\r\n\t{\r\n\t\tint numQKeys = get_num_qkeys( p_bone_frames, i );\r\n\t\tint numTKeys = get_num_tkeys( p_bone_frames, i );\r\n\r\n#ifdef __ARAM__\r\n\t\tint q_off = 0;\r\n\t\t{\r\n\t\t\t// DMA this q track.\r\n\t\t\tint aligned_off = ( anim_q_offset & ~31 );\r\n\t\t\tint size = ( ( ( sizeof( CHiResAnimQKey ) * numQKeys ) - ( aligned_off - anim_q_offset ) ) + 31 ) & ~31;\r\n\t\t\tDCFlushRange ( qqq, size );\r\n\t\t\tframecount_size = size;\r\n\t\t\tframecount_active = 1;\r\n\t\t\tARQPostRequest\t(\t&framecount_request,\r\n\t\t\t\t\t\t\t\t0x55555555,\t\t\t\t\t\t\t\t\t\t\t// Owner.\r\n\t\t\t\t\t\t\t\tARQ_TYPE_ARAM_TO_MRAM,\t\t\t\t\t\t\t\t// Type.\r\n\t\t\t\t\t\t\t\tARQ_PRIORITY_HIGH,\t\t\t\t\t\t\t\t\t// Priority.\r\n\t\t\t\t\t\t\t\t(u32)aligned_off,\t\t\t\t\t\t\t\t\t// Source.\r\n\t\t\t\t\t\t\t\t(uint32)qqq,\t\t\t\t\t\t\t\t\t\t// Dest.\r\n\t\t\t\t\t\t\t\tsize,\t\t\t\t\t\t\t\t\t\t\t\t// Length.\r\n\t\t\t\t\t\t\t\tarqCallback );\t\t\t\t\t\t\t\t\t\t// Callback\r\n\t\t\twhile ( framecount_active );\r\n\t\t\tq_off = anim_q_offset - aligned_off;\r\n\r\n\t\t\tpStartQFrame = (CHiResAnimQKey*)&qqq[q_off];\r\n\t\t\tpEndQFrame = (CHiResAnimQKey*)&qqq[q_off];\r\n\t\t\tpCurrentQFrame = (CHiResAnimQKey*)&qqq[q_off];\r\n\t\t}\r\n#endif\t\t// __ARAM__\r\n\r\n\t\tfor ( int j = 0; j < numQKeys; j++ )\r\n\t\t{\r\n\t\t\tif ( j == (numQKeys-1) )\r\n\t\t\t{\r\n\t\t\t\t// last frame\r\n\t\t\t\tpStartQFrame = pCurrentQFrame + j;\r\n\t\t\t\tpEndQFrame = pCurrentQFrame + j;\r\n\t\t\t\tqAlpha = 0.0f;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse if ( qTimeStamp >= timeDown(pCurrentQFrame[j].timestamp) \r\n\t\t\t\t && qTimeStamp <= timeDown(pCurrentQFrame[j+1].timestamp) )\r\n\t\t\t{\r\n\t\t\t\tpStartQFrame = pCurrentQFrame + j;\r\n\t\t\t\tpEndQFrame = pCurrentQFrame + j + 1;\r\n\t\t\t\tqAlpha = get_alpha( timeDown(pStartQFrame->timestamp), timeDown(pEndQFrame->timestamp), qTimeStamp );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tinterpolate_q_frame( pRotations, \r\n\t\t\t\t\t\t pStartQFrame, \r\n\t\t\t\t\t\t pEndQFrame,\r\n\t\t\t\t\t\t qAlpha,\r\n\t\t\t\t\t\t is_hires() );\r\n\r\n#ifdef __ARAM__\r\n\t\tint t_off = 0;\r\n\t\t{\r\n\t\t\t// DMA this t track.\r\n\t\t\tint aligned_off = ( anim_t_offset & ~31 );\r\n\t\t\tint size = ( ( ( sizeof( CHiResAnimTKey ) * numTKeys ) - ( aligned_off - anim_t_offset ) ) + 31 ) & ~31;\r\n\t\t\tDCFlushRange ( qqq, size );\r\n\t\t\tframecount_size = size;\r\n\t\t\tframecount_active = 1;\r\n\t\t\tARQPostRequest\t(\t&framecount_request,\r\n\t\t\t\t\t\t\t\t0x55555555,\t\t\t\t\t\t\t\t\t\t\t// Owner.\r\n\t\t\t\t\t\t\t\tARQ_TYPE_ARAM_TO_MRAM,\t\t\t\t\t\t\t\t// Type.\r\n\t\t\t\t\t\t\t\tARQ_PRIORITY_HIGH,\t\t\t\t\t\t\t\t\t// Priority.\r\n\t\t\t\t\t\t\t\t(u32)aligned_off,\t\t\t\t\t\t\t\t\t// Source.\r\n\t\t\t\t\t\t\t\t(uint32)qqq,\t\t\t\t\t\t\t\t\t\t// Dest.\r\n\t\t\t\t\t\t\t\tsize,\t\t\t\t\t\t\t\t\t\t\t\t// Length.\r\n\t\t\t\t\t\t\t\tarqCallback );\t\t\t\t\t\t\t\t\t\t// Callback\r\n\t\t\twhile ( framecount_active );\r\n\t\t\tt_off = anim_t_offset - aligned_off;\r\n\r\n\t\t\tpStartTFrame = (CHiResAnimTKey*)&qqq[t_off];\r\n\t\t\tpEndTFrame = (CHiResAnimTKey*)&qqq[t_off];\r\n\t\t\tpCurrentTFrame = (CHiResAnimTKey*)&qqq[t_off];\r\n\t\t}\r\n#endif\t\t// __ARAM__\r\n\r\n\t\tfor ( int j = 0; j < numTKeys; j++ )\r\n\t\t{\r\n\t\t\tif ( j == (numTKeys-1) )\r\n\t\t\t{\r\n\t\t\t\t// last frame\r\n\t\t\t\tpStartTFrame = pCurrentTFrame + j;\r\n\t\t\t\tpEndTFrame = pCurrentTFrame + j;\r\n\t\t\t\ttAlpha = 0.0f;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse if ( tTimeStamp >= timeDown(pCurrentTFrame[j].timestamp) \r\n\t\t\t\t && tTimeStamp <= timeDown(pCurrentTFrame[j+1].timestamp) )\r\n\t\t\t{\r\n\t\t\t\tpStartTFrame = pCurrentTFrame + j;\r\n\t\t\t\tpEndTFrame = pCurrentTFrame + j + 1;\r\n\t\t\t\ttAlpha = get_alpha( timeDown(pStartTFrame->timestamp), timeDown(pEndTFrame->timestamp), tTimeStamp );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// theStartFrame and theEndFrame should contain the\r\n\t\t// two closest keyframes here.  now interpolate between them\r\n\t\t// TODO:  we might be able to cache some of this data...\r\n\t\tinterpolate_t_frame( pTranslations, \r\n\t\t\t\t\t\t\t pStartTFrame, \r\n\t\t\t\t\t\t\t pEndTFrame,\r\n\t\t\t\t\t\t\t tAlpha,\r\n\t\t\t\t\t\t\t is_hires() );\r\n\r\n#if 0\r\n\t\tif ( m_printDebugInfo )\r\n\t\t{\r\n\t\t\t// for debug info, if necessary\r\n\t\t}\r\n#endif\r\n\t\t\r\n#ifdef __ARAM__\r\n\t\tanim_q_offset += ( sizeof( CHiResAnimQKey ) * numQKeys );\r\n\t\tanim_t_offset += ( sizeof( CHiResAnimTKey ) * numTKeys );\r\n#else\r\n\t\tpCurrentQFrame += numQKeys;\r\n\t\tpCurrentTFrame += numTKeys;\r\n#endif\t// __ARAM__\r\n\t\tpRotations++;\r\n\t\tpTranslations++;\r\n\t}\r\n\r\n    return true;\r\n}\r\n\r\n#ifdef __ARAM__\r\ninline int get_compressed_q_frame( char* pData, CStandardAnimQKey* pReturnData )\r\n#else\r\ninline char * get_compressed_q_frame( char* pData, CStandardAnimQKey* pReturnData )\r\n#endif\t\t// __ARAM__\r\n{\r\n\tunsigned char* p_data = (unsigned char*)pData;\r\n\r\n\tshort data = (short)(( p_data[1]<<8 ) | p_data[0] );\r\n\tpReturnData->timestamp = data & 0x3fff;\r\n\tpReturnData->signBit = data & 0x8000 ? 1 : 0;\r\n\t\r\n\t// skip the timestamp\r\n\tp_data += sizeof( short );\r\n\r\n\tif ( data & 0x4000 )\r\n\t{\r\n\t\tif ( !(data & 0x3800) )\r\n\t\t{\r\n\t\t\tunsigned char d = *p_data;\r\n\r\n\t\t\t// a char* defaults to a signed char*,\r\n\t\t\t// which means you'll try\r\n\t\t\t// to access outside the array\r\n\t\t\t// boundaries...  brutal!\r\n\t\t\t//Dbg_Assert( *p_data == d );\r\n\r\n\t\t\tCBonedAnimCompressEntry* pEntry = &sQTable[d];\r\n\t\t\tpReturnData->qx = pEntry->x48;\r\n\t\t\tpReturnData->qy = pEntry->y48;\r\n\t\t\tpReturnData->qz = pEntry->z48;\r\n\t\t\tp_data += sizeof( char );\r\n\r\n\t\t\t// remove the bits\r\n\t\t\tpReturnData->timestamp &= 0x07ff;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( data & 0x2000 )\r\n\t\t\t{\r\n\t\t\t\tpReturnData->qx = p_data[0];\r\n\t\t\t\tp_data += sizeof( char );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpReturnData->qx = (p_data[1]<<8) | p_data[0];\r\n\t\t\t\tp_data += sizeof( short );\r\n\t\t\t}\r\n\r\n\t\t\tif ( data & 0x1000 )\r\n\t\t\t{\r\n\t\t\t\tpReturnData->qy = p_data[0];\r\n\t\t\t\tp_data += sizeof( char );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpReturnData->qy = (p_data[1]<<8) | p_data[0];\r\n\t\t\t\tp_data += sizeof( short );\r\n\t\t\t}\r\n\r\n\t\t\tif ( data & 0x0800 )\r\n\t\t\t{\r\n\t\t\t\tpReturnData->qz = p_data[0];\r\n\t\t\t\tp_data += sizeof( char );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpReturnData->qz = (p_data[1]<<8) | p_data[0];\r\n\t\t\t\tp_data += sizeof( short );\r\n\t\t\t}\r\n\r\n\t\t\t// remove the bits\r\n\t\t\tpReturnData->timestamp &= 0x07ff;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// no compression\r\n\t\tpReturnData->qx = (p_data[1]<<8) | p_data[0];\r\n\t\tpReturnData->qy = (p_data[3]<<8) | p_data[2];\r\n\t\tpReturnData->qz = (p_data[5]<<8) | p_data[4];\r\n\t\tp_data += 6;\r\n\t}\r\n\r\n#ifdef __ARAM__\r\n\treturn (int)p_data - (int)pData;\r\n#else\r\n\treturn (char*)p_data;\r\n#endif\t\t// __ARAM__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef __ARAM__\r\ninline int get_compressed_t_frame( char* pData, CStandardAnimTKey* pReturnData )\r\n#else\r\ninline char * get_compressed_t_frame( char* pData, CStandardAnimTKey* pReturnData )\r\n#endif\t\t// __ARAM__\r\n{\r\n\tunsigned char* p_data = (unsigned char*)pData;\r\n\t\r\n\tbool useLookupTable = false;\r\n\t\r\n\tunsigned char flags = *p_data;\r\n\tp_data += sizeof( char );\r\n\t\r\n\tif ( flags & 0x80 )\r\n\t{\t\t\t\t\t\r\n\t\tuseLookupTable = true;\r\n\t}\r\n\r\n\tif ( flags & 0x40 )\r\n\t{\r\n\t\t// expand the timestamp\r\n\t\tpReturnData->timestamp = (unsigned short)(flags & 0x3f);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// read another short\r\n\t\tpReturnData->timestamp = (unsigned short)(p_data[1]<<8) | p_data[0];\r\n\t\tp_data += sizeof( short );\r\n\t}\r\n\r\n\tif ( useLookupTable )\r\n\t{\r\n\t\tunsigned char d = *p_data;\r\n\r\n\t\t// defaults to signed char,\r\n\t\t// which means you'll try\r\n\t\t// to access outside the array\r\n\t\t// boundaries...  brutal!\r\n\t\t//Dbg_Assert( *p_data == d );\r\n\t\t\r\n\t\tCBonedAnimCompressEntry* pEntry = &sTTable[d];\r\n\t\tpReturnData->tx = pEntry->x48;\r\n\t\tpReturnData->ty = pEntry->y48;\r\n\t\tpReturnData->tz = pEntry->z48;\r\n\t\tp_data += sizeof( char );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// no compression\r\n\t\tpReturnData->tx = (p_data[1]<<8) | p_data[0];\r\n\t\tpReturnData->ty = (p_data[3]<<8) | p_data[2];\r\n\t\tpReturnData->tz = (p_data[5]<<8) | p_data[4];\r\n\t\tp_data += 6;\r\n\t}\r\n\r\n#ifdef __ARAM__\r\n\treturn (int)p_data - (int)pData;\r\n#else\r\n\treturn (char*)p_data;\r\n#endif\t\t// __ARAM__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBonedAnimFrameData::GetCompressedInterpolatedFrames(Mth::Quat* pRotations, Mth::Vector* pTranslations, float time, Nx::CQuickAnim* pQuickAnim )\r\n{\r\n    Dbg_Assert( pRotations );\r\n    Dbg_Assert( pTranslations );\r\n\r\n\tDbg_Assert( !is_hires() );\r\n\r\n\tCStandardAnimQKey theStartQFrame;\r\n\tCStandardAnimQKey theEndQFrame;\r\n\tCStandardAnimQKey* pStartQFrame = &theStartQFrame;\r\n\tCStandardAnimQKey* pEndQFrame = &theEndQFrame;\r\n\t\r\n\tCStandardAnimTKey theStartTFrame;\r\n\tCStandardAnimTKey theEndTFrame;\r\n\tCStandardAnimTKey* pStartTFrame = &theStartTFrame;\r\n\tCStandardAnimTKey* pEndTFrame = &theEndTFrame;\r\n\t\r\n#ifdef __ARAM__\r\n\tchar* pCurrentQFrame = mp_qFrames;//&mp_qFrames[32];\r\n\tchar* pCurrentTFrame = mp_tFrames;//&mp_tFrames[32];\r\n\r\n\t// Pre-dma framecount sizes.\r\n\tdma_count( (uint32)mp_perBoneQFrameSize, ( m_numBones * sizeof( uint16 ) * 2 ) + 16 );\t\t// +16 should cover partial mask data.\r\n//\tif ( m_flags & nxBONEDANIMFLAGS_PARTIALANIM )\r\n//\t{\r\n//\t\twhile ( framecount_active );\r\n//\t\tdma_partial( (uint32)mp_partialAnimData );\r\n//\t}\r\n//\tuint32 * partial = (uint32 *)&framecount[( (uint32)mp_partialAnimData - (uint32)mp_perBoneQFrameSize ) * 2];\r\n\tuint32 * partial = (uint32 *)&framecount[( (uint32)mp_partialAnimData - (uint32)mp_perBoneQFrameSize ) / 2];\r\n\r\n\t// Pre-DMA all data.\r\n//\tuint32 q_lines = ((uint32)mp_boneNames) >> 16;\r\n//\tuint32 t_lines = ((uint32)mp_boneNames) & 0xffff;\r\n//\tq_lines = ( ( q_lines + ( ARAM_CACHE_LINE_SIZE - 1 ) ) / ARAM_CACHE_LINE_SIZE ); \r\n//\tt_lines = ( ( t_lines + ( ARAM_CACHE_LINE_SIZE - 1 ) ) / ARAM_CACHE_LINE_SIZE ); \r\n\r\n//\tfor ( uint32 lp = 0; lp < q_lines; lp++ ) dma_q_entry( ((uint32)mp_qFrames), lp );\r\n//\tfor ( uint32 lp = 0; lp < t_lines; lp++ ) dma_t_entry( ((uint32)mp_tFrames), lp );\r\n\r\n\tuint16* pQSizes = &framecount[0];\r\n\tuint16* pTSizes = &framecount[m_numBones];\r\n\r\n\t// Make sure framecount sizes have been DMA'd.\r\n\twhile ( framecount_active );\r\n#else\r\n\tDbg_Assert( mp_qFrames );\r\n\tDbg_Assert( mp_tFrames );\r\n\r\n\tchar* pCurrentQFrame = (char*)mp_qFrames;\r\n\tchar* pCurrentTFrame = (char*)mp_tFrames;\r\n\r\n\tuint16* pQSizes = &mp_perBoneQFrameSize[0];\r\n\tuint16* pTSizes = &mp_perBoneTFrameSize[0];\r\n#endif\t\t// __aram__\r\n\t\r\n\t// find the nearest 2 keyframes\r\n\tfloat qTimeStamp = time * 60.0f;\r\n\tfloat tTimeStamp = time * 60.0f;\r\n\t\r\n\t// Precalculate the skip index mask for speed.\r\n\tuint32 skip_index_mask = ( pQuickAnim && pQuickAnim->m_quickAnimPointers.valid ) ? ( 1 << pQuickAnim->m_quickAnimPointers.skipIndex ) : 0;\r\n\r\n\tfor ( int i = 0; i < m_numBones; i++ )\r\n\t{\r\n\t\t// See if the QuickAnim data indicates that this bone may be skipped.\r\n\t\tbool skip_this_bone = ( skip_index_mask ) ? (( pQuickAnim->m_quickAnimPointers.pSkipList[i] & skip_index_mask ) > 0 ) : false;\r\n\r\n\t\tif ( m_flags & nxBONEDANIMFLAGS_PARTIALANIM )\r\n\t\t{\r\n#ifdef __ARAM__\r\n\t\t\tuint32* pBoneMask = ( partial + 1 ) + ( i / 32 );\r\n#else\r\n\t\t\tuint32* pBoneMask = ( mp_partialAnimData + 1 ) + ( i / 32 );\r\n#endif\t\t// __ARAM__\r\n\t\t\tskip_this_bone = ( ( (*pBoneMask) & ( 1 << (i%32) ) ) == 0 );\r\n//\t\t\tskip_this_bone = ( ( (*pBoneMask) & ( (1<<31) >> (i%32) ) ) == 0 );\r\n\t\t}\r\n\r\n\t\tif( !skip_this_bone )\r\n\t\t{\r\n\t\t\tfloat qAlpha = 0.0f;\r\n\t\t\tfloat tAlpha = 0.0f;\r\n\r\n\t\t\tchar* pNextQFrame = pCurrentQFrame;\r\n\t\t\tchar* pNextQBone = pCurrentQFrame + *pQSizes;\r\n\t\t\r\n\t\t\tchar* pNextTFrame = pCurrentTFrame;\r\n    \t\tchar* pNextTBone = pCurrentTFrame + *pTSizes;\r\n\r\n\t\t\tif ( pQuickAnim && pQuickAnim->m_quickAnimPointers.valid )\r\n\t\t\t{\r\n\t\t\t\tpNextQFrame = pQuickAnim->m_quickAnimPointers.pQuickQKey[i];\r\n\t\t\t\tpNextTFrame = pQuickAnim->m_quickAnimPointers.pQuickTKey[i];\r\n\t\t\t}\r\n\t \r\n#ifdef __ARAM__\r\n\t\t\tint q_off = 0;\r\n\t\t\t{\r\n\t\t\t\t// DMA this q track.\r\n\t\t\t\tuint aligned_off = ( (int)pNextQFrame & ~31 );\r\n\t\t\t\tuint size = ( ( *pQSizes - ( aligned_off - (int)pCurrentQFrame ) ) + 31 ) & ~31;\r\n\t\t\t\tDCFlushRange ( qqq, size );\r\n\t\t\t\tframecount_size = size;\r\n\t\t\t\tframecount_active = 1;\r\n\t\t\t\tARQPostRequest\t(\t&framecount_request,\r\n\t\t\t\t\t\t\t\t\t0x55555555,\t\t\t\t\t\t\t\t\t\t\t// Owner.\r\n\t\t\t\t\t\t\t\t\tARQ_TYPE_ARAM_TO_MRAM,\t\t\t\t\t\t\t\t// Type.\r\n\t\t\t\t\t\t\t\t\tARQ_PRIORITY_HIGH,\t\t\t\t\t\t\t\t\t// Priority.\r\n\t\t\t\t\t\t\t\t\t(u32)aligned_off,\t\t\t\t\t\t\t\t\t// Source.\r\n\t\t\t\t\t\t\t\t\t(uint32)qqq,\t\t\t\t\t\t\t\t\t\t// Dest.\r\n\t\t\t\t\t\t\t\t\tsize,\t\t\t\t\t\t\t\t\t\t\t\t// Length.\r\n\t\t\t\t\t\t\t\t\tarqCallback );\t\t\t\t\t\t\t\t\t\t// Callback\r\n\t\t\t\tq_off = (int)pNextQFrame - aligned_off;\r\n\t\t\t}\r\n#endif\t\t// __ARAM__\r\n\r\n\t\t\twhile ( 1 )\r\n\t\t\t{\r\n\t\t\t\tif ( pQuickAnim )\r\n\t\t\t\t{\r\n\t\t\t\t\tpQuickAnim->m_quickAnimPointers.pQuickQKey[i] = (char*)pNextQFrame;\r\n\t\t\t\t}\r\n\r\n#\t\t\t\tifdef __ARAM__\r\n\t\t\t\twhile ( framecount_active );\r\n#\t\t\t\tendif\t\t// __ARAM__\r\n\r\n#ifdef __ARAM__\r\n\t\t\t\tint bytes = get_compressed_q_frame( &qqq[q_off], pStartQFrame );\r\n\t\t\t\tq_off += bytes;\r\n\t\t\t\tpNextQFrame = &pNextQFrame[bytes];\r\n#else\r\n\t\t\t\tpNextQFrame = get_compressed_q_frame( pNextQFrame, pStartQFrame );\r\n#endif\t\t// __ARAM__\r\n\t\t\t\tif ( pNextQFrame >= pNextQBone )\r\n\t\t\t\t{\r\n\t\t\t\t\t// last frame\r\n\t\t\t\t\t*pEndQFrame = *pStartQFrame;\r\n\t\t\t\t\tqAlpha = 0.0f;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n#ifdef __ARAM__\r\n\t\t\t\tget_compressed_q_frame( &qqq[q_off], pEndQFrame );\r\n#else\r\n\t\t\t\tget_compressed_q_frame( pNextQFrame, pEndQFrame );\r\n#endif\t\t// __ARAM__\r\n\t\t\t\tif ( qTimeStamp >= timeDown(pStartQFrame->timestamp) && qTimeStamp <= timeDown(pEndQFrame->timestamp) )\r\n\t\t\t\t{\r\n\t\t\t\t\tqAlpha = get_alpha( timeDown(pStartQFrame->timestamp), timeDown(pEndQFrame->timestamp), qTimeStamp );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// theStartFrame and theEndFrame should contain the\r\n\t\t\t// two closest keyframes here.  now interpolate between them\r\n\t\t\t// TODO:  we might be able to cache some of this data...\r\n\t\t\tinterpolate_standard_q_frame( pRotations, pStartQFrame, pEndQFrame, qAlpha );\r\n\t\t\t\r\n#ifdef __ARAM__\r\n\t\t\tint t_off = 0;\r\n\t\t\t{\r\n\t\t\t\t// DMA this q track.\r\n\t\t\t\tint aligned_off = ( (int)pNextTFrame & ~31 );\r\n\t\t\t\tint size = ( ( *pTSizes - ( aligned_off - (int)pCurrentTFrame ) ) + 31 ) & ~31;\r\n\t\t\t\tDCFlushRange ( qqq, size );\r\n\t\t\t\tframecount_size = size;\r\n\t\t\t\tframecount_active = 1;\r\n\t\t\t\tARQPostRequest\t(\t&framecount_request,\r\n\t\t\t\t\t\t\t\t\t0x55555555,\t\t\t\t\t\t\t\t\t\t\t// Owner.\r\n\t\t\t\t\t\t\t\t\tARQ_TYPE_ARAM_TO_MRAM,\t\t\t\t\t\t\t\t// Type.\r\n\t\t\t\t\t\t\t\t\tARQ_PRIORITY_HIGH,\t\t\t\t\t\t\t\t\t// Priority.\r\n\t\t\t\t\t\t\t\t\t(u32)aligned_off,\t\t\t\t\t\t\t\t\t// Source.\r\n\t\t\t\t\t\t\t\t\t(uint32)qqq,\t\t\t\t\t\t\t\t\t\t// Dest.\r\n\t\t\t\t\t\t\t\t\tsize,\t\t\t\t\t\t\t\t\t\t\t\t// Length.\r\n\t\t\t\t\t\t\t\t\tarqCallback );\t\t\t\t\t\t\t\t\t\t// Callback\r\n\t\t\t\tt_off = (int)pNextTFrame - aligned_off;\r\n\t\t\t}\r\n#endif\t\t// __ARAM__\r\n\r\n\t\t\twhile ( 1 )\r\n\t\t\t{\r\n\t\t\t\tif ( pQuickAnim )\r\n\t\t\t\t{\r\n\t\t\t\t\tpQuickAnim->m_quickAnimPointers.pQuickTKey[i] = (char*)pNextTFrame;\r\n\t\t\t\t}\r\n\r\n#\t\t\t\tifdef __ARAM__\r\n\t\t\t\twhile ( framecount_active );\r\n#\t\t\t\tendif\t\t// __ARAM__\r\n\r\n#ifdef __ARAM__\r\n\t\t\t\tint bytes = get_compressed_t_frame( &qqq[t_off], pStartTFrame );\r\n\t\t\t\tt_off += bytes;\r\n\t\t\t\tpNextTFrame = &pNextTFrame[bytes];\r\n#else\r\n\t\t\t\tpNextTFrame = get_compressed_t_frame( pNextTFrame, pStartTFrame );\r\n#endif\t\t// __ARAM__\r\n\t\t\t\tif ( pNextTFrame >= pNextTBone )\r\n\t\t\t\t{\r\n\t\t\t\t\t// last frame\r\n\t\t\t\t\t*pEndTFrame = *pStartTFrame;\r\n\t\t\t\t\ttAlpha = 0.0f;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n#ifdef __ARAM__\r\n\t\t\t\tget_compressed_t_frame( &qqq[t_off], pEndTFrame );\r\n#else\r\n\t\t\t\tget_compressed_t_frame( pNextTFrame, pEndTFrame );\r\n#endif\t\t// __ARAM__\r\n\t\t\t\tif ( tTimeStamp >= timeDown(pStartTFrame->timestamp) && tTimeStamp <= timeDown(pEndTFrame->timestamp) )\r\n\t\t\t\t{\r\n\t\t\t\t\ttAlpha = get_alpha( timeDown(pStartTFrame->timestamp), timeDown(pEndTFrame->timestamp), tTimeStamp );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tinterpolate_standard_t_frame( pTranslations, pStartTFrame, pEndTFrame, tAlpha );\r\n\t\t}\r\n\t\t\r\n\t\tpCurrentQFrame += *pQSizes;\r\n\t\tpCurrentTFrame += *pTSizes;\r\n\t\tpQSizes++;\r\n\t\tpTSizes++;\r\n\t\tpRotations++;\r\n\t\tpTranslations++;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBonedAnimFrameData::GetInterpolatedFrames(Mth::Quat* pRotations, Mth::Vector* pTranslations, float time, Nx::CQuickAnim* pQuickAnim )\r\n{\r\n\tif ( m_flags & nxBONEDANIMFLAGS_USECOMPRESSTABLE )\r\n\t{\r\n\t\t// new partial anims now use the standard GetCompressedInterpolatedFrames function\r\n\t\treturn GetCompressedInterpolatedFrames(pRotations, pTranslations, time, pQuickAnim);\r\n\t}\r\n\r\n\tif ( m_flags & nxBONEDANIMFLAGS_PARTIALANIM )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Non-compressed partial animations are not supported yet\" ) );\r\n\t}\r\n\r\n    Dbg_Assert( pRotations );\r\n    Dbg_Assert( pTranslations );\r\n\r\n\tDbg_Assert( !is_hires() );\r\n    \r\n\tfloat qAlpha = 0.0f;\r\n\tfloat tAlpha = 0.0f;\r\n\r\n\t// DMA the animation data here.\r\n#ifdef __ARAM__\r\n\tint\t\tsize;\r\n\tif ( m_flags & nxBONEDANIMFLAGS_OBJECTANIMDATA )\r\n\t{\r\n\t\tsize = ( m_numBones * sizeof(uint32) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsize = 0;\r\n\t}\r\n\r\n\tif ( m_flags & nxBONEDANIMFLAGS_HIRESFRAMEPOINTERS )\r\n\t{\r\n\t\tsize += ( m_numBones * sizeof(SHiResAnimFramePointers) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsize += ( m_numBones * sizeof(SStandardAnimFramePointers) );\r\n\t}\r\n\tdma_count( (uint32)mp_perBoneFrames, size );\r\n\twhile ( framecount_active );\r\n//\tif ( m_flags & nxBONEDANIMFLAGS_PARTIALANIM )\r\n//\t{\r\n//\t\tdma_partial( (uint32)mp_partialAnimData, ( m_numBones * sizeof( uint16 ) * 2 ) );\r\n//\t}\r\n//\twhile ( framecount_active );\r\n\r\n//\tNsDMA::toMRAM( p_sqqq, (uint32)mp_qFrames, m_num_qFrames * sizeof( CStandardAnimQKey ) );\r\n//\tNsDMA::toMRAM( p_sttt, (uint32)mp_tFrames, m_num_tFrames * sizeof( CStandardAnimTKey ) );\r\n\r\n//\twhile( framecount_active );\r\n#endif\t\t// __ARAM__\r\n\r\n\t// find the nearest 2 keyframes\r\n\tfloat qTimeStamp = time * 60.0f;\r\n\tfloat tTimeStamp = time * 60.0f;\r\n\t\r\n\tCStandardAnimQKey* pStartQFrame = NULL;\r\n\tCStandardAnimQKey* pEndQFrame = NULL;\r\n\r\n\tCStandardAnimTKey* pStartTFrame = NULL;\r\n\tCStandardAnimTKey* pEndTFrame = NULL;\r\n\r\n\tCStandardAnimQKey* pCurrentQFrame = NULL;\r\n\tCStandardAnimTKey* pCurrentTFrame = NULL;\r\n\t\r\n#ifdef __ARAM__\r\n//\tpStartQFrame = p_sqqq;\r\n//\tpEndQFrame = p_sqqq;\r\n//\r\n//\tpStartTFrame = p_sttt;\r\n//\tpEndTFrame = p_sttt;\r\n//\t\r\n//\tpCurrentQFrame = p_sqqq;\r\n//\tpCurrentTFrame = p_sttt;\r\n\r\n\tuint32 anim_q_offset = (uint32)mp_qFrames;\r\n\tuint32 anim_t_offset = (uint32)mp_tFrames;\r\n\r\n\tvoid * p_bone_frames;\r\n\tif ( m_flags & nxBONEDANIMFLAGS_OBJECTANIMDATA )\r\n\t{\r\n\t\tp_bone_frames = &framecount[m_numBones*2];\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_bone_frames = framecount;\r\n\t}\r\n#else\r\n\tpStartQFrame = (CStandardAnimQKey*)mp_qFrames;\r\n\tpEndQFrame = (CStandardAnimQKey*)mp_qFrames;\r\n\r\n\tpStartTFrame = (CStandardAnimTKey*)mp_tFrames;\r\n\tpEndTFrame = (CStandardAnimTKey*)mp_tFrames;\r\n\t\r\n\tpCurrentQFrame = (CStandardAnimQKey*)mp_qFrames;\r\n\tpCurrentTFrame = (CStandardAnimTKey*)mp_tFrames;\r\n\r\n\tvoid * p_bone_frames = mp_perBoneFrames;\r\n#endif\t\t// __aram__\r\n\r\n\tfor ( int i = 0; i < m_numBones; i++ )\r\n\t{\r\n\t\tint numQKeys = get_num_qkeys( p_bone_frames, i );\r\n\t\tint numTKeys = get_num_tkeys( p_bone_frames, i );\r\n\r\n#ifdef __ARAM__\r\n\t\tint q_off = 0;\r\n\t\t{\r\n\t\t\t// DMA this q track.\r\n\t\t\tint aligned_off = ( anim_q_offset & ~31 );\r\n\t\t\tint size = ( ( ( sizeof( CStandardAnimQKey ) * numQKeys ) - ( aligned_off - anim_q_offset ) ) + 31 ) & ~31;\r\n\t\t\tDCFlushRange ( qqq, size );\r\n\t\t\tframecount_size = size;\r\n\t\t\tframecount_active = 1;\r\n\t\t\tARQPostRequest\t(\t&framecount_request,\r\n\t\t\t\t\t\t\t\t0x55555555,\t\t\t\t\t\t\t\t\t\t\t// Owner.\r\n\t\t\t\t\t\t\t\tARQ_TYPE_ARAM_TO_MRAM,\t\t\t\t\t\t\t\t// Type.\r\n\t\t\t\t\t\t\t\tARQ_PRIORITY_HIGH,\t\t\t\t\t\t\t\t\t// Priority.\r\n\t\t\t\t\t\t\t\t(u32)aligned_off,\t\t\t\t\t\t\t\t\t// Source.\r\n\t\t\t\t\t\t\t\t(uint32)qqq,\t\t\t\t\t\t\t\t\t\t// Dest.\r\n\t\t\t\t\t\t\t\tsize,\t\t\t\t\t\t\t\t\t\t\t\t// Length.\r\n\t\t\t\t\t\t\t\tarqCallback );\t\t\t\t\t\t\t\t\t\t// Callback\r\n\t\t\twhile ( framecount_active );\r\n\t\t\tq_off = anim_q_offset - aligned_off;\r\n\r\n\t\t\tpStartQFrame = (CStandardAnimQKey*)&qqq[q_off];\r\n\t\t\tpEndQFrame = (CStandardAnimQKey*)&qqq[q_off];\r\n\t\t\tpCurrentQFrame = (CStandardAnimQKey*)&qqq[q_off];\r\n\t\t}\r\n#endif\t\t// __ARAM__\r\n\r\n\t\tfor ( int j = 0; j < numQKeys; j++ )\r\n\t\t{\r\n\t\t\tif ( j == (numQKeys-1) )\r\n\t\t\t{\r\n\t\t\t\t// last frame\r\n\t\t\t\tpStartQFrame = pCurrentQFrame + j;\r\n\t\t\t\tpEndQFrame = pCurrentQFrame + j;\r\n\t\t\t\tqAlpha = 0.0f;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse if ( qTimeStamp >= timeDown(pCurrentQFrame[j].timestamp) \r\n\t\t\t\t && qTimeStamp <= timeDown(pCurrentQFrame[j+1].timestamp) )\r\n\t\t\t{\r\n\t\t\t\tpStartQFrame = pCurrentQFrame + j;\r\n\t\t\t\tpEndQFrame = pCurrentQFrame + j + 1;\r\n\t\t\t\tqAlpha = get_alpha( timeDown(pStartQFrame->timestamp), timeDown(pEndQFrame->timestamp), qTimeStamp );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tinterpolate_q_frame( pRotations, \r\n\t\t\t\t\t\t pStartQFrame, \r\n\t\t\t\t\t\t pEndQFrame,\r\n\t\t\t\t\t\t qAlpha,\r\n\t\t\t\t\t\t is_hires() );\r\n\r\n#ifdef __ARAM__\r\n\t\tint t_off = 0;\r\n\t\t{\r\n\t\t\t// DMA this t track.\r\n\t\t\tint aligned_off = ( anim_t_offset & ~31 );\r\n\t\t\tint size = ( ( ( sizeof( CStandardAnimTKey ) * numTKeys ) - ( aligned_off - anim_t_offset ) ) + 31 ) & ~31;\r\n\t\t\tDCFlushRange ( qqq, size );\r\n\t\t\tframecount_size = size;\r\n\t\t\tframecount_active = 1;\r\n\t\t\tARQPostRequest\t(\t&framecount_request,\r\n\t\t\t\t\t\t\t\t0x55555555,\t\t\t\t\t\t\t\t\t\t\t// Owner.\r\n\t\t\t\t\t\t\t\tARQ_TYPE_ARAM_TO_MRAM,\t\t\t\t\t\t\t\t// Type.\r\n\t\t\t\t\t\t\t\tARQ_PRIORITY_HIGH,\t\t\t\t\t\t\t\t\t// Priority.\r\n\t\t\t\t\t\t\t\t(u32)aligned_off,\t\t\t\t\t\t\t\t\t// Source.\r\n\t\t\t\t\t\t\t\t(uint32)qqq,\t\t\t\t\t\t\t\t\t\t// Dest.\r\n\t\t\t\t\t\t\t\tsize,\t\t\t\t\t\t\t\t\t\t\t\t// Length.\r\n\t\t\t\t\t\t\t\tarqCallback );\t\t\t\t\t\t\t\t\t\t// Callback\r\n\t\t\twhile ( framecount_active );\r\n\t\t\tt_off = anim_t_offset - aligned_off;\r\n\r\n\t\t\tpStartTFrame = (CStandardAnimTKey*)&qqq[t_off];\r\n\t\t\tpEndTFrame = (CStandardAnimTKey*)&qqq[t_off];\r\n\t\t\tpCurrentTFrame = (CStandardAnimTKey*)&qqq[t_off];\r\n\t\t}\r\n#endif\t\t// __ARAM__\r\n\r\n\t\tfor ( int j = 0; j < numTKeys; j++ )\r\n\t\t{\r\n\t\t\tif ( j == (numTKeys-1) )\r\n\t\t\t{\r\n\t\t\t\t// last frame\r\n\t\t\t\tpStartTFrame = pCurrentTFrame + j;\r\n\t\t\t\tpEndTFrame = pCurrentTFrame + j;\r\n\t\t\t\ttAlpha = 0.0f;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse if ( tTimeStamp >= timeDown(pCurrentTFrame[j].timestamp) \r\n\t\t\t\t && tTimeStamp <= timeDown(pCurrentTFrame[j+1].timestamp) )\r\n\t\t\t{\r\n\t\t\t\tpStartTFrame = pCurrentTFrame + j;\r\n\t\t\t\tpEndTFrame = pCurrentTFrame + j + 1;\r\n\t\t\t\ttAlpha = get_alpha( timeDown(pStartTFrame->timestamp), timeDown(pEndTFrame->timestamp), tTimeStamp );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// theStartFrame and theEndFrame should contain the\r\n\t\t// two closest keyframes here.  now interpolate between them\r\n\t\t// TODO:  we might be able to cache some of this data...\r\n\t\tinterpolate_t_frame( pTranslations, \r\n\t\t\t\t\t\t\t pStartTFrame, \r\n\t\t\t\t\t\t\t pEndTFrame,\r\n\t\t\t\t\t\t\t tAlpha,\r\n\t\t\t\t\t\t\t is_hires() );\r\n\r\n#if 0\r\n\t\tif ( m_printDebugInfo )\r\n\t\t{\r\n\t\t\t// for debug info, if necessary\r\n\t\t}\r\n#endif\r\n\r\n#ifdef __ARAM__\r\n\t\tanim_q_offset += ( sizeof( CStandardAnimQKey ) * numQKeys );\r\n\t\tanim_t_offset += ( sizeof( CStandardAnimTKey ) * numTKeys );\r\n#else\r\n\t\tpCurrentQFrame += numQKeys;\r\n\t\tpCurrentTFrame += numTKeys;\r\n#endif\t// __ARAM__\r\n\t\tpRotations++;\r\n\t\tpTranslations++;\r\n\t}\r\n\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CBonedAnimFrameData::GetBoneName( int index )\r\n{\r\n\t// only the object anim stores the name of the bones\r\n\tDbg_MsgAssert( m_flags & nxBONEDANIMFLAGS_OBJECTANIMDATA, ( \"Bone names are only stored with object anims\" ) );\r\n\t\r\n\tDbg_MsgAssert( index >= 0 && index < m_numBones, ( \"Bone name request out of range %d (0-%d)\", index, m_numBones ) );\r\n\r\n\tDbg_Assert( mp_boneNames );\r\n\r\n#ifdef __ARAM__\r\n\tint\t\tsize;\r\n\tif ( m_flags & nxBONEDANIMFLAGS_OBJECTANIMDATA )\r\n\t{\r\n\t\tsize = ( m_numBones * sizeof(uint32) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsize = 0;\r\n\t}\r\n\tdma_count( (uint32)mp_perBoneFrames, size );\r\n\twhile ( framecount_active );\r\n\r\n\tuint32 * p32 = (uint32*)framecount;\r\n\treturn p32[index];\r\n#else\r\n\treturn mp_boneNames[index];\r\n#endif\t\t// __ARAM__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CBonedAnimFrameData::get_num_customkeys()\r\n{\r\n\treturn m_num_customKeys;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCustomAnimKey* CBonedAnimFrameData::get_custom_key( int index )\r\n{\r\n\tDbg_Assert( index >= 0 && index < get_num_customkeys() );\r\n\tDbg_MsgAssert( mpp_customAnimKeyList, ( \"custom key list doesn't exist\" ) );\r\n\treturn mpp_customAnimKeyList[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBonedAnimFrameData::ResetCustomKeys()\r\n{\r\n\t// this assumes that there's only going to be one \r\n\t// animcontroller calling this frame data...\r\n\t// eventually, we might need to move this\r\n\t// into CReferencedFrameData...\r\n\r\n\tint customKeyCount = get_num_customkeys();\r\n\tfor ( int i = 0; i < customKeyCount; i++ )\r\n\t{\t\t\t\t\t \r\n\t\tCCustomAnimKey* pKey = get_custom_key(i);\r\n\t\tpKey->SetActive( true );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBonedAnimFrameData::ProcessCustomKeys( float startTime, float endTime, Obj::CObject* pObject, bool inclusive )\r\n{\r\n\t// for each key,\r\n\t// see if it's between the start and end time\r\n\t// start_time <= time < end_time\r\n\r\n\t// get it into frames...\r\n\tstartTime *= 60.0f;\r\n\tendTime *= 60.0f;\r\n\r\n\tint customKeyCount = get_num_customkeys();\r\n\tfor ( int i = 0; i < customKeyCount; i++ )\r\n\t{\r\n\t\tCCustomAnimKey* pKey = get_custom_key(i);\r\n\t\tif ( pKey->WithinRange( startTime, endTime, inclusive ) )\r\n\t\t{\r\n//\t\t\tprintf( \"Processing key at %f (%f %f)\\n\", custom_key_time, startTime, endTime );\r\n\t\t\tpKey->ProcessKey( pObject );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n//\t\t\tprintf( \"Not processing key at %f (%f %f)\\n\", custom_key_time, startTime, endTime );\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/BonedAnim.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       bonedanim.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  11/14/2001\r\n//****************************************************************************\r\n\r\n#ifndef __GFX_BONEDANIM_H\r\n#define __GFX_BONEDANIM_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/math.h>\r\n\r\n#include <core/string/cstring.h>\r\n\r\n#include <sys/file/AsyncFilesys.h>\r\n\r\n#include <gfx/customanimkey.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\tclass CQuickAnim;\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\tclass CObject;\r\n}\r\n\r\nnamespace File\r\n{\r\n\tclass CAsyncFileHandle;\r\n}\r\n\t\t\t \r\nnamespace Gfx\r\n{\r\n\tclass CAnimQKey;\r\n\tclass CAnimTKey;\r\n\tstruct SAnimCustomKey;\r\n\tstruct SQuickAnimPointers;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Raw Animation Data\r\nclass CBonedAnimFrameData\r\n{\r\npublic:\r\n    CBonedAnimFrameData();\r\n    ~CBonedAnimFrameData();\r\n\r\npublic:\r\n    bool    \t\t\t   \tLoad(uint32* pData, int file_size, bool assertOnFail);\r\n    bool    \t\t\t   \tLoad(const char* p_fileName, bool assertOnFail, bool async, bool use_pip = false);\r\n    bool    \t\t\t   \tPostLoad(bool assertOnFail, int file_size, bool delete_buffer = true);\r\n\tbool\t\t\t\t\tLoadFinished();\r\n\tbool\t\t\t\t\tIsValidTime(float time);\r\n\tfloat\t\t\t\t\tGetDuration();\r\n\tint\t\t\t\t\t\tGetNumBones();\r\n\tuint32\t\t\t\t\tGetBoneName( int index );\r\n    bool\t\t\t\t    GetInterpolatedFrames(Mth::Quat* pRotations, Mth::Vector* pTranslations, float time, Nx::CQuickAnim* = NULL);\r\n    bool\t\t\t\t    GetCompressedInterpolatedFrames(Mth::Quat* pRotations, Mth::Vector* pTranslations, float time, Nx::CQuickAnim* = NULL);\r\n    bool\t\t\t\t    GetCompressedInterpolatedPartialFrames(Mth::Quat* pRotations, Mth::Vector* pTranslations, float time, Nx::CQuickAnim* = NULL);\r\n    bool\t\t\t\t    GetInterpolatedCameraFrames(Mth::Quat* pRotations, Mth::Vector* pTranslations, float time, Nx::CQuickAnim* = NULL);\r\n\tbool\t\t\t\t\tResetCustomKeys( void );\r\n\tbool\t\t\t\t\tProcessCustomKeys( float startTimeInclusive, float endTimeExclusive, Obj::CObject* pObject, bool endInclusive = false );\r\n\r\n\tCAnimQKey*\t\t\t\tGetQFrames( void ) { return (CAnimQKey*)mp_qFrames; }\r\n\tCAnimTKey*\t\t\t\tGetTFrames( void ) { return (CAnimTKey*)mp_tFrames; }\r\n\r\n\tvoid\t\t\t\t\tSetQFrames( CAnimQKey * p_q ) { mp_qFrames = (char*)p_q; }\r\n\tvoid\t\t\t\t\tSetTFrames( CAnimTKey * p_t ) { mp_tFrames = (char*)p_t; }\r\n\r\nprotected:\t\r\n\tint\t\t\t\t\t\tget_num_customkeys();\r\n\tCCustomAnimKey*\t\t\tget_custom_key( int index );\r\n\tint\t\t\t\t\t\tget_num_qkeys( void * p_frame_data, int boneIndex ) const;\r\n\tint\t\t\t\t\t\tget_num_tkeys( void * p_frame_data, int boneIndex ) const;\r\n\tvoid\t\t\t\t\tset_num_qkeys( int boneIndex, int numKeys );\r\n\tvoid\t\t\t\t\tset_num_tkeys( int boneIndex, int numKeys );\r\n\tbool\t\t\t\t\tis_hires() const;\r\n\r\n\tstatic void \t\t\tasync_callback(File::CAsyncFileHandle *, File::EAsyncFunctionType function,\r\n\t\t\t\t\t\t\t\t\t\t   int result, unsigned int arg0, unsigned int arg1);\r\n\r\nprotected:\r\n//\tbool\t\t\t\t   \tintermediate_read_stream(void* pStream);\r\n    bool                    plat_read_stream(uint8* pData, bool delete_buffer = true);\r\n    bool                    plat_read_compressed_stream(uint8* pData, bool delete_buffer = true);\r\n\tbool\t\t\t\t\tplat_dma_to_aram( int qbytes = 0, int tbytes = 0, uint32 flags = 0 );\r\n\t\r\nprotected:\r\n\tfloat\t\t\t\t   \tm_duration;\t\t  // could be a short\r\n\tuint32\t\t\t\t\tm_flags;\r\n\tint\t\t\t\t\t\tm_numBones;\r\n\r\n\t// file buffer (the only malloc'ed pointer)\r\n\tvoid*\t\t\t\t\tmp_fileBuffer;\r\n\tFile::CAsyncFileHandle* mp_fileHandle;\r\n\tint\t\t\t\t\t\tm_fileSize;\r\n\r\n\t// massive block of all Q-frames and T-frames\r\n\tchar*\t\t   \t\t\tmp_qFrames;\r\n\tchar*\t\t   \t\t\tmp_tFrames;\r\n\r\n\t// per-bone pointers into the massive block of Q-frames and T-frames\r\n\tvoid*\t\t\t\t\tmp_perBoneFrames;\r\n\r\n\t// list of bone names (for object anims only)\r\n\tuint32*\t\t\t\t\tmp_boneNames;\r\n\t\t\r\n\t// original number of bones + list of bone masks (for partial anims only)\r\n\tuint32*\t\t\t\t\tmp_partialAnimData;\r\n\r\n\tuint32\t\t\t\t\tm_fileNameCRC;\r\n\r\n\t// custom keys (for cameras, changing parent bones, etc.)\r\n\tCCustomAnimKey** \t\tmpp_customAnimKeyList;\r\n\r\n\tuint16*\t\t\t\t\tmp_perBoneQFrameSize;\r\n\tuint16*\t\t\t\t\tmp_perBoneTFrameSize;\r\n\t\r\n\tshort\t\t\t\t\tm_num_qFrames;\r\n\tshort\t\t\t\t\tm_num_tFrames;\r\n\tshort\t\t\t\t\tm_num_customKeys;\r\n\t\r\n\tshort\t\t\t\t\tm_printDebugInfo:1;\r\n\tshort\t\t\t\t\tm_dataLoaded:1;\r\n\tshort\t\t\t\t\tm_pipped:1;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool InitQ48Table( const char* pFileName, bool assertOnFail = true );\r\nbool InitT48Table( const char* pFileName, bool assertOnFail = true );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline float CBonedAnimFrameData::GetDuration()\r\n{\r\n\treturn m_duration;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline int CBonedAnimFrameData::GetNumBones()\r\n{\r\n\treturn m_numBones;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline bool CBonedAnimFrameData::LoadFinished()\r\n{\r\n\treturn m_dataLoaded;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // namespace Gfx\r\n\r\n#endif\t// __GFX_BONEDANIM_H\r\n"
  },
  {
    "path": "Code/Gfx/BonedAnimTypes.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       BonedAnimTypes.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  02/04/2003\r\n//****************************************************************************\r\n\r\n#ifndef __GFX_BONEDANIMTYPES_H\r\n#define __GFX_BONEDANIMTYPES_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CAnimQKey\r\n{\r\npublic:\r\n#ifdef __PLAT_NGC__\r\n\tshort\t\t\tsignBit:1;\t// 1 = negative\r\n\tshort\t\t\ttimestamp:15;\r\n#else\r\n\tshort\t\t\ttimestamp:15;\r\n\tshort\t\t\tsignBit:1;\t// 1 = negative\r\n#endif\t\t// __PLAT_NGC__\r\n\r\nprotected:\r\n\tCAnimQKey() {}\r\n};\r\n\r\nclass CStandardAnimQKey\t: public CAnimQKey\r\n{\r\npublic:\r\n    short           qx;\r\n    short           qy;\r\n    short           qz;\r\n};\r\n\r\nclass CHiResAnimQKey : public CAnimQKey\r\n{\r\npublic:\r\n    float           qx;\r\n    float           qy;\r\n    float           qz;\r\n};\r\n\r\nclass CAnimTKey\r\n{\r\npublic:\r\n\tshort\t\t\ttimestamp;\r\n\r\nprotected:\r\n\tCAnimTKey() {}\r\n};\r\n\r\nclass CStandardAnimTKey\t: public CAnimTKey\r\n{\r\npublic:\r\n    short           tx;\r\n    short           ty;\r\n    short           tz;\r\n};\r\n\r\nclass CHiResAnimTKey : public CAnimTKey\r\n{\r\npublic:\r\n    float           tx;\r\n    float           ty;\r\n    float           tz;\r\n};\r\n\r\nstruct SQuickAnimPointers\r\n{\r\n\tchar* \t\t\t\tpQuickQKey[64];\r\n\tchar*\t\t\t\tpQuickTKey[64];\r\n\tCStandardAnimQKey\ttheStartQKey[64];\r\n\tCStandardAnimQKey\ttheEndQKey[64];\r\n\tCStandardAnimTKey\ttheStartTKey[64];\r\n\tCStandardAnimTKey\ttheEndTKey[64];\r\n//\tchar\t\t\t\tqSkip[64];\r\n//\tchar\t\t\t\ttSkip[64];\r\n\tbool\t\t\t\tvalid;\r\n\tuint32*\t\t\t\tpSkipList;\r\n\tuint32\t\t\t\tskipIndex;\r\n};\r\n\r\n// NOTE: if you change this enum, update the CAnimChannel::GetDebugInfo switch statement!\t\r\nenum EAnimLoopingType\r\n{\r\n\tLOOPING_HOLD\t\t\t\t= 0,\t// holds on last frame\r\n\tLOOPING_CYCLE,\t\t\t\t\t\t// cycles the animation forever\r\n\tLOOPING_PINGPONG,\t\t\t\t\t// pingpongs the animation forever\r\n\tLOOPING_WOBBLE,\t\t\t\t\t\t// Aims towards wobble_target_time whilst wobbling a bit. Used for manuals & grinds.\r\n\r\n// these are samples of other possible looping types,\r\n// although they have not yet been implemented\r\n//\tLOOPING_CYCLE_X_TIMES,\t\t\t\t// cycles the same animation x times\r\n//\tLOOPING_PINGPONG_X_TIMES\t\t\t// pingpongs the animation x times\r\n};\r\n\t\r\n// NOTE: if you change this enum, update the CAnimChannel::GetDebugInfo switch statement!\t\r\nenum EAnimDirection \r\n{\r\n\tANIM_DIR_FORWARDS\t\t\t= 0,\r\n\tANIM_DIR_BACKWARDS\t\t\t= -1\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\r\n} // namespace Gfx\r\n\r\n#endif // __GFX_BONEDANIMTYPES_H"
  },
  {
    "path": "Code/Gfx/CasUtils.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       CasUtils.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  ?/??/????\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/casutils.h>\r\n\r\n#include <core/math/math.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h> \r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Cas\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 get_desc_id_from_structure( Script::CStruct* pStructure )\r\n{\r\n\tDbg_Assert( pStructure );\r\n\r\n\tuint32 descId;\r\n\tpStructure->GetChecksum( CRCD(0x4bb2084e,\"desc_id\"), &descId, true );\r\n\treturn descId;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool IsValidOption( uint32 partChecksum, uint32 lookFor )\r\n{\r\n\treturn ( GetOptionStructure( partChecksum, lookFor ) != NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* GetOptionStructure( uint32 partChecksum, uint32 lookFor, bool assertOnFail )\r\n{\r\n\tScript::CArray* pArray;\r\n\tpArray = Script::GetArray( partChecksum, Script::ASSERT );\r\n\r\n\tScript::CStruct* pReturnStructure = NULL;\r\n\r\n\tif ( lookFor == 0 )\r\n\t{\r\n\t\t// special checksum, meaning to return NULL\r\n\t\t// (handy when preprocessing random descs)\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tfor ( uint32 i = 0; i < pArray->GetSize(); i++ )\r\n\t{\r\n\t\tScript::CStruct* pCurrDesc = pArray->GetStructure( i );\r\n\t\tuint32 desc_id = get_desc_id_from_structure( pCurrDesc );\r\n\t\tif ( desc_id == lookFor )\r\n\t\t{\r\n\t\t\tpReturnStructure = pCurrDesc;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( assertOnFail )\r\n\t{\r\n\t\tDbg_MsgAssert( pReturnStructure, ( \"Couldn't find %s %s\", Script::FindChecksumName(partChecksum), Script::FindChecksumName(lookFor) ) );\r\n\t}\r\n\r\n\treturn pReturnStructure;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* GetFirstOptionStructure( uint32 partChecksum )\r\n{\r\n\tScript::CArray* pArray;\r\n\tpArray = Script::GetArray( partChecksum, Script::ASSERT );\r\n\r\n\treturn pArray->GetStructure( 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid BuildRandomSetList( uint32 partChecksum, uint32 random_set, Script::CStruct** ppReturnStructs, int* pReturnNumStructs )\r\n{\r\n\tScript::CArray* pArray;\r\n\tpArray = Script::GetArray( partChecksum, Script::ASSERT );\r\n\r\n\t// reset the return value\r\n\t*pReturnNumStructs = 0;\r\n\r\n\tint part_array_size = pArray->GetSize();\r\n\tfor ( int i = 0; i < part_array_size; i++ )\r\n\t{\r\n\t\tScript::CStruct* pStruct = pArray->GetStructure( i );\r\n\t\tint allowed_to_pick = 0;\r\n\t\tpStruct->GetInteger( CRCD(0x355f9467,\"allowed_to_pick\"), &allowed_to_pick, Script::ASSERT );\r\n\t\t\r\n\t\tif ( allowed_to_pick )\r\n\t\t{\r\n\t\t\t// if a random_set was specified, then\r\n\t\t\t// make sure that this item works with it\r\n\t\t\t// (used for matching skin tones)\r\n\t\t\tuint32 this_random_set = 0;\r\n\t\t\tpStruct->GetChecksum( CRCD(0x0d7260fd,\"random_set\"), &this_random_set, Script::NO_ASSERT );\r\n\r\n\t\t\tif ( this_random_set == random_set )\r\n\t\t\t{\r\n\t\t\t\t*ppReturnStructs = pStruct;\r\n\t\t\t\tppReturnStructs++;\r\n\r\n\t\t\t\t(*pReturnNumStructs)++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* GetRandomOptionStructure( uint32 partChecksum, uint32 random_set )\r\n{\r\n\tScript::CArray* pArray;\r\n\tpArray = Script::GetArray( partChecksum, Script::ASSERT );\r\n\r\n\tconst int vMAX_CAS_ITEMS = 32;\r\n\tScript::CStruct* pAllowedStructs[vMAX_CAS_ITEMS];\r\n\tbool alreadySelected[vMAX_CAS_ITEMS];\r\n\tint allowRandomCount = 0;\r\n\t\r\n\tint part_array_size = pArray->GetSize();\r\n\tfor ( int i = 0; i < part_array_size; i++ )\r\n\t{\r\n\t\tScript::CStruct* pStruct = pArray->GetStructure( i );\r\n\t\tint allow_random = !pStruct->ContainsFlag( CRCD(0xf6f8e158,\"no_random\") );\r\n\t\tpStruct->GetInteger( CRCD(0xf1e3cd22,\"allow_random\"), &allow_random, Script::ASSERT );\r\n\t\t\r\n\t\tif ( random_set )\r\n\t\t{\r\n\t\t\t// if a random_set was specified, then\r\n\t\t\t// make sure that this item works with it\r\n\t\t\t// (used for matching skin tones)\r\n\t\t\tuint32 this_random_set = 0;\r\n\t\t\tif ( pStruct->GetChecksum( CRCD(0x0d7260fd,\"random_set\"), &this_random_set, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tif ( this_random_set != random_set )\r\n\t\t\t\t{\r\n\t\t\t\t\tallow_random = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif ( allow_random )\r\n\t\t{\r\n\t\t\tDbg_Assert( allowRandomCount < vMAX_CAS_ITEMS );\r\n\t\t\tpAllowedStructs[allowRandomCount] = pStruct;\r\n\t\t\t\r\n\t\t\tint already_selected;\r\n\t\t\tpStruct->GetInteger( CRCD(0x92bddfd9,\"already_selected\"), &already_selected, true );\r\n\t\t\talreadySelected[allowRandomCount] = already_selected;\r\n\t\t\t\r\n\t\t\tallowRandomCount++;\r\n\t\t}\r\n\t}\r\n\r\n\t// make sure there's at least one allow_random,\r\n\t// or else we'll get into an infinite loop\r\n\tDbg_MsgAssert( allowRandomCount > 0, ( \"No allow_random was found in this array %s (Tell Gary!)\", Script::FindChecksumName(partChecksum) ) );\r\n\r\n\t// count how many of them are already unselected\r\n\tint unselected_count = 0;\r\n\tfor ( int i = 0; i < allowRandomCount; i++ )\r\n\t{\r\n\t\tif ( !alreadySelected[i] )\r\n\t\t{\r\n\t\t\tunselected_count++;\r\n\t\t}\r\n\t}\r\n\r\n\t// the following makes sure that all the \"allow_random\" parts\r\n\t// are used at least once, before duplicates begin.\r\n\tif ( unselected_count == 0 )\r\n\t{\r\n\t\tfor ( int i = 0; i < allowRandomCount; i++ )\r\n\t\t{\r\n\t\t\talreadySelected[i] = false;\r\n\t\t}\r\n\t}\r\n\r\n\t// now get rid of all the already selected items\r\n\tint currentCount = 0;\r\n\tfor ( int i = 0; i < allowRandomCount; i++ )\r\n\t{\r\n\t\tif ( !alreadySelected[i] )\r\n\t\t{\r\n\t\t\tpAllowedStructs[currentCount] = pAllowedStructs[i];\r\n\t\t\talreadySelected[currentCount] =\talreadySelected[i];\r\n\t\t\tcurrentCount++;\r\n\t\t}\r\n\t}\r\n\tallowRandomCount = currentCount;\r\n\t\r\n\tDbg_MsgAssert( allowRandomCount >= 1, ( \"No part to pick\" ) );\r\n\tint index = Mth::Rnd( allowRandomCount );\r\n\tDbg_Assert( index >= 0 && index < allowRandomCount );\r\n\tScript::CStruct* pReturnStruct = pAllowedStructs[index];\r\n\r\n\tDbg_Assert( pReturnStruct );\r\n\tpReturnStruct->AddInteger( CRCD(0x92bddfd9,\"already_selected\"), 1 );\r\n\r\n//\tuint32 checksum;\r\n//\tpStruct->GetChecksum( \"desc_id\", &checksum, true );\r\n//\tDbg_Message( \"Choosing random part %s\", Script::FindChecksumName( checksum ) );\r\n\r\n\treturn pReturnStruct;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* GetRandomOptionStructureByIndex( uint32 partChecksum, int desired_index, uint32 random_set )\r\n{\r\n\tScript::CArray* pArray;\r\n\tpArray = Script::GetArray( partChecksum, Script::ASSERT );\r\n\r\n\tint part_array_size = pArray->GetSize();\r\n\r\n\tif ( !random_set )\r\n\t{\r\n\t\tfor ( int i = 0; i < part_array_size; i++ )\r\n\t\t{\r\n\t\t\tScript::CStruct* pStruct = pArray->GetStructure( i );\r\n\r\n\t\t\tint random_index = -1;\r\n\t\t\tif ( pStruct->GetInteger( CRCD(0x4b833e64,\"random_index\"), &random_index, Script::ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tif ( random_index == desired_index )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn pStruct;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// GJ FIX FOR SK5:TT12579:  \"NJ - Goal peds being created with mismached skin colors\"\r\n\t\t// if a random_set (skintone) was specified, then find the n-th item that actually works with this\r\n\t\t// random set\r\n\t\twhile ( 1 )\r\n\t\t{\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tint current_random_index = desired_index;\r\n\t\t\t#endif\r\n\r\n\t\t\tfor ( int i = 0; i < part_array_size; i++ )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pStruct = pArray->GetStructure( i );\r\n\r\n\t\t\t\tint allow_random = !pStruct->ContainsFlag( CRCD(0xf6f8e158,\"no_random\") );\r\n\t\t\t\tpStruct->GetInteger( CRCD(0xf1e3cd22,\"allow_random\"), &allow_random, Script::ASSERT );\r\n\r\n\t\t\t\tuint32 this_random_set = 0;\r\n\t\t\t\tpStruct->GetChecksum( CRCD(0x0d7260fd,\"random_set\"), &this_random_set, Script::NO_ASSERT );\r\n\t\t\t\tbool is_universal_item = ( this_random_set == 0 );\r\n\r\n\t\t\t\tif ( allow_random && ( ( this_random_set == random_set ) || is_universal_item ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( desired_index <= 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn pStruct;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tdesired_index--;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// once we get to the end of the array, we need to start over\r\n\t\t\t// (basically, we're doing a modulo of the desired_index)...\r\n\t\t\t// the following checks for an infinite loop in which there\r\n\t\t\t// were no items found that works with this random set\r\n\t\t\tDbg_MsgAssert( current_random_index != desired_index, ( \"Couldn't find 'random_index' %d for ped part %s (are there any that fit this skintone %s?)\", desired_index, Script::FindChecksumName(partChecksum), Script::FindChecksumName(random_set) ) );\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert( 0, ( \"Couldn't find 'random_index' %d for ped part %s\", desired_index, Script::FindChecksumName(partChecksum) ) );\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // end namespace\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/CasUtils.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       CasUtils.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  ?/??/????\r\n//****************************************************************************\r\n\r\n#ifndef __GFX_CASUTILS_H\r\n#define __GFX_CASUTILS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Cas\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// for searching/traversing an actual optionset\r\nbool\t\t\t\tIsValidOption( uint32 partChecksum, uint32 descId );\r\nScript::CStruct*\tGetOptionStructure( uint32 partChecksum, uint32 descId, bool assertOnFail = true );\r\nScript::CStruct*\tGetFirstOptionStructure( uint32 partChecksum );\r\nScript::CStruct*\tGetNullOptionStructure( uint32 partChecksum );\r\nvoid\t\t\t\tBuildRandomSetList( uint32 partChecksum, uint32 random_set, Script::CStruct** ppReturnStructs, int* pReturnCount );\r\nScript::CStruct*\tGetRandomOptionStructure( uint32 partChecksum, uint32 random_set = 0 );\r\nScript::CStruct*\tGetRandomOptionStructureByIndex( uint32 partChecksum, int index, uint32 random_set = 0 );\r\n\r\n} // end namespace\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/CustomAnimKey.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       CustomAnimKey.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  02/11/2002\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/customanimkey.h>\r\n\t\t\t\t\t\t\t\t   \r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/utils.h>\r\n#include <sys/file/filesys.h>\r\n\r\n#include <core/math/quat.h>\r\n#include <core/math/vector.h>\r\n#include <gfx/camera.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// all custom keys must have 32-bit data, for the animconv's\r\n// byte-swapping algorithm to work properly\r\n\r\nstruct SIntermediateCustomAnimKeyHeader\r\n{\r\n\tuint32\ttimeStamp;\r\n\tuint32\tkeyType;\r\n\tuint32\tsize;\r\n};\r\n\r\ntypedef enum\r\n{\r\n\tvUNUSED1 = 0,\r\n\tvCHANGE_FOCAL_LENGTH,\r\n\tvCHANGE_CAMERA_RT,\r\n\tvCHANGE_CAMERA_RT_IGNORE,\r\n\tvRUN_SCRIPT,\r\n\tvCREATE_OBJECT_FROM_STRUCT,\r\n\tvKILL_OBJECT_FROM_STRUCT,\r\n\tvCHANGE_CAMERA_RT_ENDKEY,\r\n};\r\n\r\n// class CChangeFOVKey\r\nclass CChangeFOVKey : public CCustomAnimKey\r\n{\r\npublic:\r\n\tCChangeFOVKey( int frame, float fov );\r\n\r\npublic:\r\n\tvirtual\tbool\tprocess_key( Obj::CObject* pObject );\r\n\r\nprotected:\r\n\tfloat\tm_fov;\r\n};\r\n\r\n// class CRunScriptKey\r\nclass CRunScriptKey : public CCustomAnimKey\r\n{\r\npublic:\r\n\tCRunScriptKey( int frame, uint32 scriptName );\r\n\r\npublic:\r\n\tvirtual\tbool\tprocess_key( Obj::CObject* pObject );\r\n\r\nprotected:\r\n\tuint32\tm_scriptName;\r\n};\r\n\r\n// class CChangeCameraRTKey\r\nclass CChangeCameraRTKey : public CCustomAnimKey\r\n{\r\npublic:\r\n\tCChangeCameraRTKey( int frame, const Mth::Quat& theQuat, const Mth::Vector& theVector, bool endKey );\r\n\r\npublic:\r\n\tvirtual\tbool\tprocess_key( Obj::CObject* pObject );\r\n\tvirtual bool\tWithinRange( float startFrame, float endFrame, bool inclusive );\r\n\r\nprotected:\r\n\tMth::Quat\tm_rot;\r\n\tMth::Vector\tm_trans;\r\n\tbool\t\tm_endKey;\r\n};\r\n\r\n// class CEmptyKey\r\nclass CEmptyKey : public CCustomAnimKey\r\n{\r\npublic:\r\n\tCEmptyKey( int frame );\r\n\r\npublic:\r\n\tvirtual\tbool\tprocess_key( Obj::CObject* pObject );\r\n};\r\n\r\n// class CCreateObjectFromStructKey\r\nclass CCreateObjectFromStructKey : public CCustomAnimKey\r\n{\r\npublic:\r\n\tCCreateObjectFromStructKey( int frame, uint32 objectStructName );\r\n\r\npublic:\r\n\tvirtual\tbool\tprocess_key( Obj::CObject* pObject );\r\n\r\nprotected:\r\n\tuint32\tm_objectStructName;\r\n};\r\n\r\n// class CKillObjectFromStructKey\r\nclass CKillObjectFromStructKey : public CCustomAnimKey\r\n{\r\npublic:\r\n\tCKillObjectFromStructKey( int frame, uint32 objectStructName );\r\n\r\npublic:\r\n\tvirtual\tbool\tprocess_key( Obj::CObject* pObject );\r\n\r\nprotected:\r\n\tuint32\tm_objectStructName;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCustomAnimKey::CCustomAnimKey( int frame ) : Lst::Node<CCustomAnimKey>( this ), m_frame( frame )\r\n{\r\n\t// defaults to inactive\r\n\tm_active = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCustomAnimKey::WithinRange( float startFrame, float endFrame, bool inclusive )\r\n{\r\n\tif ( inclusive )\r\n\t{\r\n\t\tif ( startFrame < endFrame )\r\n\t\t{\r\n\t\t\t// forwards\r\n\t\t\treturn ( m_frame >= startFrame && m_frame <= endFrame );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// backwards\r\n\t\t\treturn ( m_frame <= startFrame && m_frame >= endFrame );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( startFrame < endFrame )\r\n\t\t{\r\n\t\t\t// forwards\r\n\t\t\treturn ( m_frame >= startFrame && m_frame < endFrame );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// backwards\r\n\t\t\treturn ( m_frame <= startFrame && m_frame > endFrame );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCustomAnimKey::SetActive( bool active )\r\n{\r\n\tm_active = active;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCustomAnimKey::ProcessKey( Obj::CObject* pObject )\r\n{\r\n\tif ( !m_active )\r\n\t{\r\n\t\tDbg_Message( \"Key at %d was not active...  ignored!\", m_frame );\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// once it's run, don't run it again...\r\n\t// (this is in case you pause a movie camera\r\n\t// on the same frame that it's running a key)\r\n\tthis->SetActive( false );\r\n\r\n\treturn process_key( pObject );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCChangeFOVKey::CChangeFOVKey( int frame, float fov ) : CCustomAnimKey( frame ), m_fov( fov )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CChangeFOVKey::process_key( Obj::CObject* pObject )\r\n{\r\n\tif ( Script::GetInt( CRCD(0x2f510f45,\"moviecam_debug\"), false ) )\r\n\t{\r\n\t\tDbg_Message( \"Processing Change FOV key (fov = %f, %f) (%d)!\", m_fov, Mth::RadToDeg(m_fov), m_frame );\r\n\t}\r\n\r\n\tScript::CScriptStructure* pParams = new Script::CScriptStructure;\r\n\tpParams->AddFloat( NONAME, m_fov );\r\n\tScript::RunScript( \"ChangeCameraFov\", pParams, pObject );\r\n\tdelete pParams;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\t\t\t\t\r\n\r\nCRunScriptKey::CRunScriptKey( int frame, uint32 scriptName ) : CCustomAnimKey( frame ), m_scriptName( scriptName )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CRunScriptKey::process_key( Obj::CObject* pObject )\r\n{\r\n\tif ( Script::GetInt( CRCD(0x2f510f45,\"moviecam_debug\"), false ) )\r\n\t{\r\n\t\tDbg_Message( \"Processing Run Script key (script = %s) @ %d!\", Script::FindChecksumName( m_scriptName ), m_frame );\r\n\t}\r\n\tScript::RunScript( m_scriptName, NULL, pObject );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCChangeCameraRTKey::CChangeCameraRTKey( int frame, const Mth::Quat& theQuat, const Mth::Vector& theVector, bool isEndKey ) : CCustomAnimKey( frame )\r\n{\r\n\t// rotate by 90 degrees,\r\n\t// eventually, we should do this in the build tools\r\n\t\r\n\tMth::Quat rotQuat( Mth::Vector(1,0,0), Mth::DegToRad(90.0f) );\r\n\tm_rot = theQuat * rotQuat;\r\n\r\n\tm_trans[X] = theVector[X];\r\n\tm_trans[Y] = theVector[Z];\r\n\tm_trans[Z] = -theVector[Y];\r\n\tm_trans[W] = 1.0f;\r\n\r\n\tm_endKey = isEndKey;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CChangeCameraRTKey::process_key( Obj::CObject* pObject )\r\n{\r\n\t// GJ:  This key is a kludge to fix the problem with camera\r\n\t// double-cuts in the cutscene (where we're trying to\r\n\t// interpolate from one camera to the next, rather\r\n\t// than just jumping)...  the way it works is that\r\n\t// 2 of these keys need to be inserted right before\r\n\t// a camera change, which will override the interpolated\r\n\t// camera values.  we need 2 because we're guaranteed\r\n\t// that the minimum time increment is 1/60th of a second\r\n\t// so we need to stick these keys in every 1/60th of\r\n\t// a second between the two cameras.  note that this\r\n\t// won't work properly if we do anim speed changes\r\n\t// or setslomo, because then the minimum time increment\r\n\t// is actually less than 1/60th of a second, then it's\r\n\t// possible that there will be a camera update, without\r\n\t// an accompanying CChangeCamera key found\r\n\t// i'd eventually like to look at how WithinRange() works, \r\n\t// to see if there's a better way to do this.\r\n\t\r\n\tif ( m_frame == 0 )\r\n\t{\r\n\t\t// GJ KLUDGE:  there's an exporter bug that writes out extra camera RT\r\n\t\t// keys at the beginning of the cutscene.  this skips\r\n\t\t// those extra keys\r\n\t\tDbg_Message( \"Skipping Change Camera RT key @ %d!\", m_frame );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif ( Script::GetInt( CRCD(0x2f510f45,\"moviecam_debug\"), false ) )\r\n\t{\r\n\t\tDbg_Message( \"Processing Change Camera RT key @ %d!\", m_frame );\r\n\t\tDbg_Message( \"Quat: %f %f %f %f\", m_rot[X], m_rot[Y], m_rot[Z], m_rot[W] );\r\n\t\tDbg_Message( \"Trans: %f %f %f %f\", m_trans[X], m_trans[Y], m_trans[Z], m_trans[W] );\r\n\t}\r\n\r\n\tGfx::Camera* pCamera = (Gfx::Camera*)pObject;\r\n\r\n\tMth::Vector& camPos = pCamera->GetPos();\r\n\tMth::Matrix& camMatrix = pCamera->GetMatrix();\r\n\t\r\n\t// update the camera position\r\n\tcamPos = m_trans;\r\n\r\n\t// update the camera orientation\r\n\tMth::Vector nullTrans;\r\n\tnullTrans.Set(0.0f,0.0f,0.0f,1.0f);\t\t// Mick: added separate initialization\r\n\t\r\n\t// QuatVecToMatrix destroys the input data, so need to pass in a temp variable\r\n\tMth::Quat theQuat = m_rot;\r\n\tMth::QuatVecToMatrix( &theQuat, &nullTrans, &camMatrix );\r\n\r\n\t// need this because of our 1-frame range check\r\n\tthis->SetActive( true );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CChangeCameraRTKey::WithinRange( float startFrame, float endFrame, bool inclusive )\r\n{\r\n\t// good for 1 frame...\t\t\t  1/60th of a frame\r\n\r\n\tif ( inclusive )\r\n\t{\r\n\t\tif ( startFrame < endFrame )\r\n\t\t{\r\n\t\t\t// this end key business is used to fix a cutscene glitch\r\n\t\t\t// during camera cuts.  the problem is that the keys come\r\n\t\t\t// in sets of 3:\r\n\t\t\t// KEY[-2]    KEY[-1]    KEY[0]\r\n\t\t\t// old camera old camera new camera\r\n\t\t\t// we basically take the current frame (stored\r\n\t\t\t// in endFrame) and figure out which of the\r\n\t\t\t// three keys should handle it...  formerly,\r\n\t\t\t// all three keys handled it, effectively\r\n\t\t\t// causing the last key's camera data to be \r\n\t\t\t// used.  to fix the glitch, we need to only\r\n\t\t\t// run the correct key...\r\n\t\t\tif ( m_endKey )\r\n\t\t\t{\r\n\t\t\t\tif ( endFrame > m_frame )\r\n\t\t\t\t{\r\n\t\t\t\t\t// let it interpolate\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( m_frame < ( endFrame - 1.0f ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t// there's an end key coming, so let someone else handle it\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n  \t\t\t\r\n\t\t\t// forwards\r\n\t\t\treturn ( m_frame >= ( startFrame - 1.0f ) && m_frame <= endFrame );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// backwards\r\n\t\t\treturn ( m_frame <= ( startFrame + 1.0f ) && m_frame >= endFrame );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( startFrame < endFrame )\r\n\t\t{\r\n\t\t\tif ( m_endKey )\r\n\t\t\t{\r\n\t\t\t\tif ( endFrame > m_frame )\r\n\t\t\t\t{\r\n\t\t\t\t\t// let it interpolate\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( m_frame < ( endFrame - 1.0f ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t// there's an end key coming, so let someone else handle it\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n  \t\t\t\r\n\t\t\t// forwards\r\n\t\t\treturn ( m_frame >= ( startFrame - 1.0f ) && m_frame < endFrame );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// backwards\r\n\t\t\treturn ( m_frame <= ( startFrame + 1.0f ) && m_frame > endFrame );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCEmptyKey::CEmptyKey( int frame ) : CCustomAnimKey( frame )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CEmptyKey::process_key( Obj::CObject* pObject )\r\n{\r\n\t// do nothing\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCEventKey::CEventKey( int frame, uint32 eventType, Script::CStruct* pEventParams ) : CCustomAnimKey( frame )\r\n{\r\n\tm_eventType = eventType;\r\n\tmp_eventParams = new Script::CStruct;\r\n\tmp_eventParams->AppendStructure( pEventParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCEventKey::~CEventKey()\r\n{\r\n\tif ( mp_eventParams )\r\n\t{\r\n\t\tdelete mp_eventParams;\r\n\t\tmp_eventParams = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CEventKey::process_key( Obj::CObject* pObject )\r\n{\r\n\tpObject->SelfEvent( m_eventType, mp_eventParams );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\t\t\t\t\r\n\r\nCCreateObjectFromStructKey::CCreateObjectFromStructKey( int frame, uint32 objectStructName ) : CCustomAnimKey( frame ), m_objectStructName( objectStructName )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCreateObjectFromStructKey::process_key( Obj::CObject* pObject )\r\n{\r\n\tif ( Script::GetInt( CRCD(0x2f510f45,\"moviecam_debug\"), false ) )\r\n\t{\r\n\t\tDbg_Message( \"Processing Create Object From Struct key (struct = %s) @ %d!\", Script::FindChecksumName( m_objectStructName ), m_frame );\r\n\t}\r\n\r\n\tScript::CStruct* pObjectStruct = Script::GetStructure( m_objectStructName, Script::ASSERT );\r\n\tif ( pObjectStruct )\r\n\t{\r\n\t\tScript::RunScript( CRCD(0xbdf7f843,\"CreateFromStructure\"), pObjectStruct );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\t\t\t\t\r\n\r\nCKillObjectFromStructKey::CKillObjectFromStructKey( int frame, uint32 objectStructName ) : CCustomAnimKey( frame ), m_objectStructName( objectStructName )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CKillObjectFromStructKey::process_key( Obj::CObject* pObject )\r\n{\r\n\tif ( Script::GetInt( CRCD(0x2f510f45,\"moviecam_debug\"), false ) )\r\n\t{\r\n\t\tDbg_Message( \"Processing Kill Object From Struct key (script = %s) @ %d!\", Script::FindChecksumName( m_objectStructName ), m_frame );\r\n\t}\r\n\t\r\n\tScript::CStruct* pObjectStruct = Script::GetStructure( m_objectStructName, Script::ASSERT );\r\n\tif ( pObjectStruct )\r\n\t{\r\n\t\tuint32 objectName;\r\n\t\tpObjectStruct->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &objectName, Script::ASSERT );\r\n\t\t\r\n\t\tObj::CObject* pObject = (Obj::CObject*)Obj::ResolveToObject( objectName );\r\n\t\tpObject->MarkAsDead();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCustomAnimKey* ReadCustomAnimKey( uint8** pData )\r\n{\r\n\t// factory function for generating a custom key...\r\n\r\n\t// TODO:  might need to push the heap context\r\n\r\n\tSIntermediateCustomAnimKeyHeader theIntermediateHeader;\r\n\tmemcpy(&theIntermediateHeader, *pData, sizeof(SIntermediateCustomAnimKeyHeader));\r\n\t*pData += sizeof(SIntermediateCustomAnimKeyHeader);\r\n\r\n\tswitch ( theIntermediateHeader.keyType )\r\n\t{\r\n\t\tcase vCHANGE_FOCAL_LENGTH:\r\n\t\t\t{\r\n\t\t\t\tfloat fov;\r\n\t\t\t\tmemcpy(&fov, *pData, sizeof(float));\t\t\t\t// May not be word-aligned in memory\r\n\t\t\t\t*pData += sizeof(float);\r\n\t\t\t\treturn new CChangeFOVKey( theIntermediateHeader.timeStamp, fov );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase vRUN_SCRIPT:\r\n\t\t\t{\r\n\t\t\t\tuint32 script_name;\r\n\t\t\t\tmemcpy(&script_name, *pData, sizeof(uint32));\t\t// May not be word-aligned in memory\r\n\t\t\t\t*pData += sizeof(uint32);\r\n\t\t\t\treturn new CRunScriptKey( theIntermediateHeader.timeStamp, script_name );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase vCHANGE_CAMERA_RT:\r\n\t\t\t{\r\n\t\t\t\tMth::Quat theQuat;\r\n\t\t\t\tMth::Vector theVector;\r\n\t\t\t\tmemcpy(&theVector, *pData, sizeof(Mth::Vector));\r\n\t\t\t\t*pData += sizeof(Mth::Vector);\r\n\t\t\t\tmemcpy(&theQuat, *pData, sizeof(Mth::Quat));\r\n\t\t\t\t*pData += sizeof(Mth::Quat);\r\n\t\t\t\treturn new CChangeCameraRTKey( theIntermediateHeader.timeStamp, theQuat, theVector, false );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase vCHANGE_CAMERA_RT_ENDKEY:\r\n\t\t\t{\r\n\t\t\t\tMth::Quat theQuat;\r\n\t\t\t\tMth::Vector theVector;\r\n\t\t\t\tmemcpy(&theVector, *pData, sizeof(Mth::Vector));\r\n\t\t\t\t*pData += sizeof(Mth::Vector);\r\n\t\t\t\tmemcpy(&theQuat, *pData, sizeof(Mth::Quat));\r\n\t\t\t\t*pData += sizeof(Mth::Quat);\r\n\t\t\t\treturn new CChangeCameraRTKey( theIntermediateHeader.timeStamp, theQuat, theVector, true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase vCHANGE_CAMERA_RT_IGNORE:\r\n\t\t\t{\r\n           \t\t// GJ:  There's a bug in the exporter where\r\n\t\t\t\t// 2 camera RT keys with different positions\r\n\t\t\t\t// are listed for the same time...  this causes\r\n\t\t\t\t// a glitch during certain camera transitions.\r\n\t\t\t\t// To fix, I will replace the second key with one\r\n\t\t\t\t// that does nothing...\r\n\t\t\t\t*pData += sizeof(Mth::Vector);\r\n\t\t\t\t*pData += sizeof(Mth::Quat);\r\n\r\n\t\t\t\treturn new CEmptyKey( theIntermediateHeader.timeStamp );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase vCREATE_OBJECT_FROM_STRUCT:\r\n\t\t\t{\r\n\t\t\t\tuint32 object_struct_name;\r\n\t\t\t\tmemcpy(&object_struct_name, *pData, sizeof(uint32));\t\t// May not be word-aligned in memory\r\n\t\t\t\t*pData += sizeof(uint32);\r\n\t\t\t\treturn new CCreateObjectFromStructKey( theIntermediateHeader.timeStamp, object_struct_name );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase vKILL_OBJECT_FROM_STRUCT:\r\n\t\t\t{\r\n\t\t\t\tuint32 object_struct_name;\r\n\t\t\t\tmemcpy(&object_struct_name, *pData, sizeof(uint32));\t\t// May not be word-aligned in memory\r\n\t\t\t\t*pData += sizeof(uint32);\r\n\t\t\t\treturn new CKillObjectFromStructKey( theIntermediateHeader.timeStamp, object_struct_name );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"Warning:  Ignoring custom anim key (type %08x is currently unsupported).\", theIntermediateHeader.keyType );\r\n\r\n\t\t\t\t// just skip past the size\r\n\t\t\t\tDbg_Assert( theIntermediateHeader.size - sizeof(SIntermediateCustomAnimKeyHeader) < 512 );\r\n\t\t\t\t*pData += theIntermediateHeader.size;\r\n\t\t\t\tDbg_Assert(!((uint) *pData & 0x3));\r\n\r\n\t\t\t\treturn NULL;\r\n\t\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Gfx\r\n"
  },
  {
    "path": "Code/Gfx/CustomAnimKey.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       CustomAnimKey.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  02/08/2002\r\n//****************************************************************************\r\n\r\n#ifndef __GFX_CUSTOMANIMKEY_H\r\n#define __GFX_CUSTOMANIMKEY_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <core/list/node.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\tclass CObject;\r\n}\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Gfx\r\n{\r\n\tenum RangeFlags\r\n\t{\r\n\t\tmSTART_INCLUSIVE = ( 1 << 0 ),\r\n\t\tmSTART_EXCLUSIVE = ( 1 << 1 ),\r\n\t\tmEND_INCLUSIVE = ( 1 << 2 ),\r\n\t\tmEND_EXCLUSIVE = ( 1 << 3 ),\r\n\t};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// interface to all the custom keys\r\n// (the custom keys are defined in the CPP file)\r\n// there should be no allocation going on in these keys\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// class CCustomAnimKey\r\nclass CCustomAnimKey : public Lst::Node<CCustomAnimKey>\r\n{\r\npublic:\r\n\tCCustomAnimKey( int time );\r\n\tvirtual bool\tWithinRange( float startFrame, float endFrame, bool inclusive = false );\r\n\tvoid\t\t\tSetActive( bool active );\r\n\r\npublic:\r\n\tbool\t\t\tProcessKey( Obj::CObject* pObject );\r\n\r\nprotected:\r\n\tvirtual bool\tprocess_key( Obj::CObject* pObject ) = 0;\r\n\r\nprotected:\r\n\tint\t\t\t\tm_frame;\r\n\tbool\t\t\tm_active;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// class CEventKey\r\nclass CEventKey : public CCustomAnimKey\r\n{\r\npublic:\r\n\tCEventKey( int time, uint32 eventType, Script::CStruct* pParams );\r\n\tvirtual ~CEventKey();\r\n\r\npublic:\r\n\tvirtual\tbool\t\tprocess_key( Obj::CObject* pObject );\r\n\r\nprotected:\r\n\tuint32\t\t\t\tm_eventType;\r\n\tScript::CStruct*\tmp_eventParams;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCCustomAnimKey* ReadCustomAnimKey( uint8** pData );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // namespace Gfx\r\n\r\n#endif\t// __GFX_CUSTOMANIMKEY_H\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/FaceMassage.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// FaceMassage.cpp\r\n\r\n#include <core/math.h>\r\n\r\n#include <gel/Scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n\r\n#include <gfx/NxTexture.h>\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/FaceMassage.h>\r\n\r\nnamespace\tNx\r\n{\r\n\r\n#ifdef __NOPT_ASSERT__\r\nvoid\t\t\tSFacePoints::PrintData()\r\n{\r\n\tDbg_Message(\"FacePoints left_eye (%d, %d)\", m_left_eye[X], m_left_eye[Y]);\r\n\tDbg_Message(\"FacePoints right_eye (%d, %d)\", m_right_eye[X], m_right_eye[Y]);\r\n\tDbg_Message(\"FacePoints nose (%d, %d)\", m_nose[X], m_nose[Y]);\r\n\tDbg_Message(\"FacePoints lips (%d, %d)\", m_lips[X], m_lips[Y]);\r\n\tDbg_Message(\"FacePoints adjust HSV (%s)\", m_adjust_hsv ? \"true\" : \"false\");\r\n\tif (m_adjust_hsv)\r\n\t{\r\n\t\tDbg_Message(\"FacePoints H offset (%f)\", m_h_offset);\r\n\t\tDbg_Message(\"FacePoints S scale (%f)\", m_s_scale);\r\n\t\tDbg_Message(\"FacePoints V scale (%f)\", m_v_scale);\r\n\t}\r\n\tDbg_Message(\"FacePoints texture size (%d, %d)\", m_texture_width, m_texture_height);\r\n}\r\n#endif // __NOPT_ASSERT__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSFacePoints s_default_face_points = {\r\n\t{  49,  54 },\t\t// Left eye\r\n\t{  76,  54 },\t\t// Right eye\r\n\t{  64,  75 },\t\t// Nose\r\n\t{  64,  89 },\t\t// Lips\r\n\tfalse,\t\t\t\t// Adjust HSV\r\n\t0.0f,\t\t\t\t// H offset\r\n\t1.0f,\t\t\t\t// S scale\r\n\t1.0f,\t\t\t\t// V scale\r\n\t128,\t\t\t\t// Texture width\r\n\t128\t\t\t\t\t// Texture height\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Utility functions\r\nvoid SetDefaultFacePoints(SFacePoints* pFacePoints)\r\n{\r\n\tDbg_MsgAssert( pFacePoints, ( \"No face points\" ) );\r\n\r\n\t*pFacePoints = s_default_face_points;\r\n}  \r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// CFaceTexMassager\r\n\r\n// copy over default face points\r\nSFacePoints\t\tCFaceTexMassager::s_model_face_points = s_default_face_points;\r\n\r\nCTexture *\t\tCFaceTexMassager::sp_face_texture_overlay = NULL;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCFaceTexMassager::sSetModelFacePoints(const SFacePoints &f_points)\r\n{\r\n\ts_model_face_points = f_points;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCFaceTexMassager::sSetFaceTextureOverlay(CTexture *p_texture)\r\n{\r\n\tif (p_texture)\r\n\t{\r\n\t\tDbg_MsgAssert(p_texture->GetWidth() == s_model_face_points.m_texture_width, (\"Face texture overlay width is not equal to the face points width\"));\r\n\t\tDbg_MsgAssert(p_texture->GetHeight() == s_model_face_points.m_texture_height, (\"Face texture overlay height is not equal to the face points height\"));\r\n\t}\r\n\r\n\tsp_face_texture_overlay = p_texture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#define PRINT_TIMES 0\r\n\r\nbool\t\t\tCFaceTexMassager::sMassageTexture(CTexture *p_face_texture, const SFacePoints &c_texture_points, bool palette_gen,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  bool use_fill_color, Image::RGBA fill_color)\r\n{\r\n\tDbg_Assert(p_face_texture);\r\n\r\n#if PRINT_TIMES\r\n\tuint32 start_time = Tmr::GetTimeInUSeconds();\r\n#endif\r\n\r\n\t// Convert texture to 32-bit, if not already (speeds conversion)\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\tp_face_texture->Generate32BitImage();\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Adjust the texture based on the model face points\r\n\tsAdjustTextureToModel(p_face_texture, c_texture_points, use_fill_color, fill_color);\r\n\r\n\t// Adjust the texture colors\r\n\tsAdjustTextureColors(p_face_texture, c_texture_points);\r\n\r\n\t// And put overlay on top, if any\r\n\tif (sp_face_texture_overlay)\r\n\t{\r\n\t\tp_face_texture->CombineTextures(sp_face_texture_overlay, palette_gen);\r\n\t}\r\n\r\n\t// Put 32-bit image into texture\r\n\tp_face_texture->Put32BitImageIntoTexture(palette_gen);\r\n\r\n#if PRINT_TIMES\r\n\tuint32 end_time = Tmr::GetTimeInUSeconds();\r\n\tDbg_Message(\"sMassageTexture Update time %d us\", end_time - start_time);\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCFaceTexMassager::sAdjustTextureToModel(CTexture *p_face_texture, const SFacePoints &c_texture_points,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbool use_fill_color, Image::RGBA fill_color)\r\n{\r\n\tDbg_Assert(p_face_texture);\r\n\tDbg_MsgAssert(p_face_texture->GetWidth() == s_model_face_points.m_texture_width, (\"Face texture width is not equal to the face points width\"));\r\n\tDbg_MsgAssert(p_face_texture->GetHeight() == s_model_face_points.m_texture_height, (\"Face texture height is not equal to the face points height\"));\r\n\r\n\t// Make a local copy of the texture points, as we might need to modify it to make it safe\t\t\t\t\t\t\t\t\t\t\t \r\n\tSFacePoints texture_points = c_texture_points;\r\n\t\t\t\t\t\t\t\t\t\t\t \r\n// Make the values \"safe\" (should also do this at the user interface stage)\r\n\r\n\r\n// if eyes are flipped, then flip them back\r\n\tint t;\r\n\tif (texture_points.m_left_eye[X] > texture_points.m_right_eye[X])\r\n\t{\r\n\t\tt = texture_points.m_left_eye[X];\r\n\t\ttexture_points.m_left_eye[X] = texture_points.m_right_eye[X];\r\n\t\ttexture_points.m_right_eye[X] = t;\r\n\t}\r\n\t\r\n\t\r\n// If Left eye is below the nose then put it above it.\t\r\n\tif (texture_points.m_left_eye[Y] > texture_points.m_nose[Y])\r\n\t{\r\n\t\ttexture_points.m_left_eye[Y] = texture_points.m_nose[Y]-1;\r\n\t}\r\n\r\n\r\n// If Right eye is below the nose then put it above it.\t\r\n\tif (texture_points.m_right_eye[Y] >= texture_points.m_nose[Y])\r\n\t{\r\n\t\ttexture_points.m_right_eye[Y] = texture_points.m_nose[Y]-2;\r\n\t}\r\n\r\n// if Lips is above the nose, then put it below\r\n\tif (texture_points.m_lips[Y] <= texture_points.m_nose[Y])\r\n\t{\r\n\t\ttexture_points.m_lips[Y] = texture_points.m_nose[Y]+2;\r\n\t}\r\n\r\n\t// All stretching and shrinking will be done at the nose point\r\n\tint x_axis_point = s_model_face_points.m_nose[X];\r\n\tint y_axis_point = s_model_face_points.m_nose[Y];\r\n\r\n\t// First, offset the texture by the difference in nose points\r\n\tint x_offset = s_model_face_points.m_nose[X] - texture_points.m_nose[X];\r\n\tint y_offset = s_model_face_points.m_nose[Y] - texture_points.m_nose[Y];\r\n\tp_face_texture->Offset(x_offset, y_offset);\r\n\r\n\tint model_eyeline_y = (s_model_face_points.m_left_eye[Y] + s_model_face_points.m_right_eye[Y]) >> 1;\r\n\tint texture_eyeline_y = ((texture_points.m_left_eye[Y] + texture_points.m_right_eye[Y]) >> 1) + y_offset;\r\n\r\n\t// Calculate the ratios to find how much we need to pull/push a texture section\r\n\tfloat left_eye_to_nose_width = texture_points.m_nose[X] - texture_points.m_left_eye[X];\r\n\tfloat left_nose_width = texture_points.m_nose[X] + x_offset;\r\n\tfloat left_eye_ratio = left_nose_width / left_eye_to_nose_width;\r\n\r\n\tfloat right_eye_to_nose_width = texture_points.m_right_eye[X] - texture_points.m_nose[X];\r\n\tfloat right_nose_width = p_face_texture->GetWidth() - (texture_points.m_nose[X] + x_offset);\r\n\tfloat right_eye_ratio = right_nose_width / right_eye_to_nose_width;\r\n\r\n\tfloat eyeline_to_nose_height = (texture_points.m_nose[Y] + y_offset) - texture_eyeline_y;\r\n\tfloat top_nose_height = texture_points.m_nose[Y] + y_offset;\r\n\tfloat eyeline_ratio = top_nose_height / eyeline_to_nose_height;\r\n\r\n\tfloat lips_to_nose_height = texture_points.m_lips[Y] - texture_points.m_nose[Y];\r\n\tfloat bottom_nose_height = p_face_texture->GetHeight() - (texture_points.m_nose[Y] + y_offset);\r\n\tfloat lips_ratio = bottom_nose_height / lips_to_nose_height;\r\n\r\n\t// Move the left eye along the X axis\r\n\tint left_eye_pixels = s_model_face_points.m_left_eye[X] - (texture_points.m_left_eye[X] + x_offset);\r\n\t//Dbg_Message(\"Left eye pixels before %d\", left_eye_pixels);\r\n\t//Dbg_Message(\"Left eye to_nose %f width %f\", left_eye_to_nose_width, left_nose_width);\r\n\tleft_eye_pixels = (int) ((left_eye_pixels * left_eye_ratio) + 0.5f);\r\n\t//Dbg_Message(\"Left eye pixels after %d\", left_eye_pixels);\r\n\tif (left_eye_pixels < 0)\r\n\t{\r\n\t\t// Stretch out\r\n\t\tp_face_texture->PullToEdge(x_axis_point, X, left_eye_pixels);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Shrink\r\n\t\tp_face_texture->PushToPoint(x_axis_point, X, left_eye_pixels, use_fill_color, fill_color);\r\n\t}\r\n\r\n\t// Move the right eye along the X axis\r\n\tint right_eye_pixels = s_model_face_points.m_right_eye[X] - (texture_points.m_right_eye[X] + x_offset);\r\n\t//Dbg_Message(\"Right eye pixels before %d\", right_eye_pixels);\r\n\t//Dbg_Message(\"Right eye to_nose %f width %f\", right_eye_to_nose_width, right_nose_width);\r\n\tright_eye_pixels = (int) ((right_eye_pixels * right_eye_ratio) + 0.5f);\r\n\t//Dbg_Message(\"Right eye pixels after %d\", right_eye_pixels);\r\n\tif (right_eye_pixels >= 0)\r\n\t{\r\n\t\t// Stretch out\r\n\t\tp_face_texture->PullToEdge(x_axis_point, X, right_eye_pixels);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Shrink\r\n\t\tp_face_texture->PushToPoint(x_axis_point, X, right_eye_pixels, use_fill_color, fill_color);\r\n\t}\r\n\r\n\t// Move the eyeline along the Y axis\r\n\tint eyeline_pixels = model_eyeline_y - texture_eyeline_y;\r\n\teyeline_pixels = (int) ((eyeline_pixels * eyeline_ratio) + 0.5f);\r\n\tif (eyeline_pixels < 0)\r\n\t{\r\n\t\t// Stretch out\r\n\t\tp_face_texture->PullToEdge(y_axis_point, Y, eyeline_pixels);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Shrink\r\n\t\tp_face_texture->PushToPoint(y_axis_point, Y, eyeline_pixels, use_fill_color, fill_color);\r\n\t}\r\n\r\n\t// Move the lips along the Y axis\r\n\tint lips_pixels = s_model_face_points.m_lips[Y] - (texture_points.m_lips[Y] + y_offset);\r\n\tlips_pixels = (int) ((lips_pixels * lips_ratio) + 0.5f);\r\n\tif (lips_pixels >= 0)\r\n\t{\r\n\t\t// Stretch out\r\n\t\tp_face_texture->PullToEdge(y_axis_point, Y, lips_pixels);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Shrink\r\n\t\tp_face_texture->PushToPoint(y_axis_point, Y, lips_pixels, use_fill_color, fill_color);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCFaceTexMassager::sAdjustTextureColors(CTexture *p_face_texture, const SFacePoints &texture_points)\r\n{\r\n\tDbg_Assert(p_face_texture);\r\n\r\n\tif (texture_points.m_adjust_hsv)\r\n\t{\r\n\t\tp_face_texture->AdjustHSV(texture_points.m_h_offset, texture_points.m_s_scale, texture_points.m_v_scale, false);\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCFaceTexMassager::sCombineTextureWithOverlay(CTexture *p_face_texture)\r\n{\r\n\tDbg_Assert(p_face_texture);\r\n\r\n\tif (sp_face_texture_overlay)\r\n\t{\r\n\t\tp_face_texture->CombineTextures(sp_face_texture_overlay, false);\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////\r\n// Script functions\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool SetFacePointsStruct(const SFacePoints& face_points, Script::CStruct *p_struct)\r\n{\r\n\tDbg_Assert(p_struct);\r\n\r\n\tScript::CArray* p_left_eye = new Script::CArray;\r\n\tp_left_eye->SetSizeAndType( 2, ESYMBOLTYPE_INTEGER );\r\n\tp_left_eye->SetInteger( 0, face_points.m_left_eye[X] );\r\n\tp_left_eye->SetInteger( 1, face_points.m_left_eye[Y] );\r\n\t\r\n\tScript::CArray* p_right_eye = new Script::CArray;\r\n\tp_right_eye->SetSizeAndType( 2, ESYMBOLTYPE_INTEGER );\r\n\tp_right_eye->SetInteger( 0, face_points.m_right_eye[X] );\r\n\tp_right_eye->SetInteger( 1, face_points.m_right_eye[Y] );\r\n\t\r\n\tScript::CArray* p_nose = new Script::CArray;\r\n\tp_nose->SetSizeAndType( 2, ESYMBOLTYPE_INTEGER );\r\n\tp_nose->SetInteger( 0, face_points.m_nose[X] );\r\n\tp_nose->SetInteger( 1, face_points.m_nose[Y] );\r\n\t\r\n\tScript::CArray* p_lips = new Script::CArray;\r\n\tp_lips->SetSizeAndType( 2, ESYMBOLTYPE_INTEGER );\r\n\tp_lips->SetInteger( 0, face_points.m_lips[X] );\r\n\tp_lips->SetInteger( 1, face_points.m_lips[Y] );\r\n\r\n\tp_struct->AddArrayPointer( CRCD(0x08bf1d3f,\"left_eye\"), p_left_eye );\r\n\tp_struct->AddArrayPointer( CRCD(0xb0b44396,\"right_eye\"), p_right_eye );\r\n\tp_struct->AddArrayPointer( CRCD(0x7f03932c,\"nose\"), p_nose );\r\n\tp_struct->AddArrayPointer( CRCD(0x0e7ec187,\"lips\"), p_lips );\r\n\r\n\tif (face_points.m_adjust_hsv)\r\n\t{\r\n\t\tp_struct->AddFloat(CRCD(0x6e94f918,\"h\"), face_points.m_h_offset);\r\n\t\tp_struct->AddFloat(CRCD(0xe4f130f4,\"s\"), face_points.m_s_scale);\r\n\t\tp_struct->AddFloat(CRCD(0x949bc47b,\"v\"), face_points.m_v_scale);\r\n\t}\r\n\r\n\tp_struct->AddInteger( CRCD(0x73e5bad0,\"width\"), face_points.m_texture_width );\r\n\tp_struct->AddInteger( CRCD(0x0ab21af0,\"height\"), face_points.m_texture_height );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool GetFacePointsStruct(SFacePoints &face_points, Script::CStruct *p_struct)\r\n{\r\n\tDbg_Assert(p_struct);\r\n\r\n\tScript::CArray *p_left_eye = NULL;\r\n\tScript::CArray *p_right_eye = NULL;\r\n\tScript::CArray *p_nose = NULL;\r\n\tScript::CArray *p_lips = NULL;\r\n\r\n\t// Left eye\r\n\tp_struct->GetArray( CRCD(0x08bf1d3f,\"left_eye\"), &p_left_eye );\r\n\tif (p_left_eye)\r\n\t{\r\n\t\tface_points.m_left_eye[X] = p_left_eye->GetInteger(0);\r\n\t\tface_points.m_left_eye[Y] = p_left_eye->GetInteger(1);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Couldn't find member left_eye\"))\r\n\t\treturn false;\t\r\n\t}\r\n\r\n\t// Right eye\r\n\tp_struct->GetArray( CRCD(0xb0b44396,\"right_eye\"), &p_right_eye );\r\n\tif (p_right_eye)\r\n\t{\r\n\t\tface_points.m_right_eye[X] = p_right_eye->GetInteger(0);\r\n\t\tface_points.m_right_eye[Y] = p_right_eye->GetInteger(1);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Couldn't find member right_eye\"))\r\n\t\treturn false;\t\r\n\t}\r\n\r\n\t// Nose\r\n\tp_struct->GetArray( CRCD(0x7f03932c,\"nose\"), &p_nose );\r\n\tif (p_nose)\r\n\t{\r\n\t\tface_points.m_nose[X] = p_nose->GetInteger(0);\r\n\t\tface_points.m_nose[Y] = p_nose->GetInteger(1);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Couldn't find member nose\"))\r\n\t\treturn false;\t\r\n\t}\r\n\r\n\t// Lips\r\n\tp_struct->GetArray( CRCD(0x0e7ec187,\"lips\"), &p_lips );\r\n\tif (p_lips)\r\n\t{\r\n\t\tface_points.m_lips[X] = p_lips->GetInteger(0);\r\n\t\tface_points.m_lips[Y] = p_lips->GetInteger(1);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Couldn't find member lips\"))\r\n\t\treturn false;\t\r\n\t}\r\n\r\n\t// Grab color adjustment values, if any\r\n\tface_points.m_adjust_hsv = p_struct->GetFloat(CRCD(0x6e94f918,\"h\"), &face_points.m_h_offset);\r\n\tface_points.m_adjust_hsv = p_struct->GetFloat(CRCD(0xe4f130f4,\"s\"), &face_points.m_s_scale) && face_points.m_adjust_hsv;\r\n\tface_points.m_adjust_hsv = p_struct->GetFloat(CRCD(0x949bc47b,\"v\"), &face_points.m_v_scale) && face_points.m_adjust_hsv;\r\n\r\n\tif (face_points.m_adjust_hsv)\r\n\t{\r\n\t\tDbg_MsgAssert((face_points.m_h_offset >= 0.0f) && (face_points.m_h_offset <= 360.0f), (\"h must be in the range of 0-360\"));\r\n\t\tDbg_MsgAssert(face_points.m_s_scale >= 0.0f, (\"s cannot be negative\"));\r\n\t\tDbg_MsgAssert(face_points.m_v_scale >= 0.0f, (\"v cannot be negative\"));\r\n\t}\r\n\r\n\t// Width and height (some functions may not care, so init them to 0)\r\n\tface_points.m_texture_width = 0;\r\n\tface_points.m_texture_height = 0;\r\n\tp_struct->GetInteger( CRCD(0x73e5bad0,\"width\"), &face_points.m_texture_width );\r\n\tp_struct->GetInteger( CRCD(0x0ab21af0,\"height\"), &face_points.m_texture_height );\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | SetModelFaceTexturePoints | Sets the face points for the face texture of the model\r\n// @parm struct | face_points | face points structure\r\nbool ScriptSetModelFaceTexturePoints(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tSFacePoints face_points;\r\n\r\n\tScript::CStruct *pFacePointsStruct = NULL;\r\n\tpParams->GetStructure(\"face_points\", &pFacePointsStruct);\r\n\r\n\tif (pFacePointsStruct)\r\n\t{\r\n\t\tGetFacePointsStruct(face_points, pFacePointsStruct);\r\n\r\n\t\tDbg_MsgAssert(face_points.m_texture_width != 0, (\"Must set texture width\"));\r\n\t\tDbg_MsgAssert(face_points.m_texture_height != 0, (\"Must set texture height\"));\r\n\r\n\t\tCFaceTexMassager::sSetModelFacePoints(face_points);\r\n\t\t//face_points.PrintData();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"The face_points structure needs to be supplied\"));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | SetFaceMassageTextureOverlay | Sets the texture that is used as an overlay to the massaged face texture \r\n// @parm name |  | name of texture\r\nbool ScriptSetFaceMassageTextureOverlay(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(NONAME, &checksum))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\tif (p_texture)\r\n\t{\r\n\t\tCFaceTexMassager::sSetFaceTextureOverlay(p_texture);\r\n\t} else {\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to adjust\", Script::FindChecksumName(checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | MassageFaceTexture | Transform the supplied face texture to one that can be used with a model\r\n// @parm name | texture | name of texture\r\n// @parm struct | face_points | face points structure\r\n// @parmopt flag | no_palette_gen | | use original palette (faster)\r\nbool ScriptMassageFaceTexture(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(CRCD(0x7d99f28d,\"texture\"), &checksum))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\tif (p_texture)\r\n\t{\r\n\t\tbool palette_gen = true;\r\n\t\tSFacePoints face_points;\r\n\r\n\t\tScript::CStruct *pFacePointsStruct = NULL;\r\n\t\tpParams->GetStructure(CRCD(0xac3cd84c,\"face_points\"), &pFacePointsStruct);\r\n\r\n\t\tif (pParams->ContainsFlag(CRCD(0x5905256b,\"no_palette_gen\")))\r\n\t\t{\r\n\t\t\tpalette_gen = false;\r\n\t\t}\r\n\r\n\t\tif (pFacePointsStruct)\r\n\t\t{\r\n\t\t\tGetFacePointsStruct(face_points, pFacePointsStruct);\r\n\r\n\t\t\tCFaceTexMassager::sMassageTexture(p_texture, face_points, palette_gen);\r\n\t\t\t//CFaceTexMassager::sMassageTexture(p_texture, face_points, palette_gen, true, Image::RGBA(255, 0, 0, 128));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"The face_points structure needs to be supplied\"));\r\n\t\t}\r\n\r\n\t} else {\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to massage\", Script::FindChecksumName(checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | AdjustFaceTextureToModel | Pulls portions of the face texture from the supplied points to the model points\r\n// @parm name | texture | name of texture\r\n// @parm struct | face_points | face points structure\r\nbool ScriptAdjustFaceTextureToModel(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(CRCD(0x7d99f28d,\"texture\"), &checksum))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\tif (p_texture)\r\n\t{\r\n\t\tSFacePoints face_points;\r\n\r\n\t\tScript::CStruct *pFacePointsStruct = NULL;\r\n\t\tpParams->GetStructure(CRCD(0xac3cd84c,\"face_points\"), &pFacePointsStruct);\r\n\r\n\t\tif (pFacePointsStruct)\r\n\t\t{\r\n\t\t\tGetFacePointsStruct(face_points, pFacePointsStruct);\r\n\r\n\t\t\tCFaceTexMassager::sAdjustTextureToModel(p_texture, face_points);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"The face_points structure needs to be supplied\"));\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to adjust\", Script::FindChecksumName(checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | AdjustFaceTextureColors | Does all the requested color adjustments to the face texture.\r\n// @parm name | texture | name of texture\r\n// @parm struct | face_points | face points structure\r\nbool ScriptAdjustFaceTextureColors(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(CRCD(0x7d99f28d,\"texture\"), &checksum))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\tif (p_texture)\r\n\t{\r\n\t\tSFacePoints face_points;\r\n\r\n\t\tScript::CStruct *pFacePointsStruct = NULL;\r\n\t\tpParams->GetStructure(CRCD(0xac3cd84c,\"face_points\"), &pFacePointsStruct);\r\n\r\n\t\tif (pFacePointsStruct)\r\n\t\t{\r\n\t\t\tGetFacePointsStruct(face_points, pFacePointsStruct);\r\n\r\n\t\t\tCFaceTexMassager::sAdjustTextureColors(p_texture, face_points);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"The face_points structure needs to be supplied\"));\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to adjust\", Script::FindChecksumName(checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | CombineFaceTextureWithOverlay | Puts overlay texture on top of face texture and combines them.\r\n// @parm name | texture | name of texture\r\nbool ScriptCombineFaceTextureWithOverlay(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(CRCD(0x7d99f28d,\"texture\"), &checksum))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\tif (p_texture)\r\n\t{\r\n\t\tCFaceTexMassager::sCombineTextureWithOverlay(p_texture);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to combine\", Script::FindChecksumName(checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n} // namespace Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/FaceMassage.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// FaceMassage.h\r\n\r\n#ifndef\t__GFX_FACE_MASSAGE_H__\r\n#define\t__GFX_FACE_MASSAGE_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gfx/image/imagebasic.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\n// Forward declarations\r\nclass CTexture;\r\n\r\n////////////////////////////////////////////////////////////////////////////\r\n// Holds all the face coordinates\r\nstruct SFacePoints\r\n{\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tNUM_AXES\t= 2,\t\t\t// Just two axes for 2D coordinates\r\n\t};\r\n\r\n\t// Eye points\r\n\tint\t\t\t\tm_left_eye[NUM_AXES];\r\n\tint\t\t\t\tm_right_eye[NUM_AXES];\r\n\r\n\t// Nose point (between the nostrils)\r\n\tint\t\t\t\tm_nose[NUM_AXES];\r\n\r\n\t// Lips point (center)\r\n\tint\t\t\t\tm_lips[NUM_AXES];\r\n\r\n\t// Color HSV adjustments\r\n\tbool\t\t\tm_adjust_hsv;\r\n\tfloat\t\t\tm_h_offset;\t\t\t\t// Added to each pixel H value (0 - 360)\r\n\tfloat\t\t\tm_s_scale;\t\t\t\t// Scale applied to each pixel S value (1=no change)\r\n\tfloat\t\t\tm_v_scale;\t\t\t\t// Scale applied to each pixel V value (1=no change)\r\n\r\n\t// Texture size\r\n\tint\t\t\t\tm_texture_width;\r\n\tint\t\t\t\tm_texture_height;\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tvoid\t\t\tPrintData();\r\n#endif // __NOPT_ASSERT__\r\n};\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n// Transforms a face texture into one that can be used by a model.\r\nclass CFaceTexMassager\r\n{\r\npublic:\r\n\t// Set data\r\n\tstatic void\t\t\t\tsSetModelFacePoints(const SFacePoints &f_points);\r\n\tstatic void\t\t\t\tsSetFaceTextureOverlay(CTexture *p_texture);\r\n\r\n\t// Massage the face texture into a usable face texture for a model (overwrites old texture pixel data)\r\n\tstatic bool\t\t\t\tsMassageTexture(CTexture *p_face_texture, const SFacePoints &texture_points, bool palette_gen = true,\r\n\t\t\t\t\t\t\t\t\t\t\tbool use_fill_color = false, Image::RGBA fill_color = Image::RGBA(128, 128, 128, 128));\r\n\r\n\t// Individual massage steps (mainly for editor).  Note that these functions do not convert to 32-bit or back to\r\n\t// 8-bit at the end.  These functions need to be called separately.\r\n\tstatic bool\t\t\t\tsAdjustTextureToModel(CTexture *p_face_texture, const SFacePoints &texture_points,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  bool use_fill_color = false, Image::RGBA fill_color = Image::RGBA(128, 128, 128, 128));\r\n\tstatic bool\t\t\t\tsAdjustTextureColors(CTexture *p_face_texture, const SFacePoints &texture_points);\r\n\tstatic bool\t\t\t\tsCombineTextureWithOverlay(CTexture *p_face_texture);\r\n\r\nprotected:\r\n\r\n\tstatic SFacePoints\t\ts_model_face_points;\t\t// Face points needed for a model\r\n\r\n\tstatic CTexture *\t\tsp_face_texture_overlay;  \t// The texture that needs to go over the top of a supplied face texture\r\n\r\n};\r\n\r\n// Script functions\r\nbool ScriptSetModelFaceTexturePoints(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetFaceMassageTextureOverlay(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptMassageFaceTexture(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAdjustFaceTextureToModel(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAdjustFaceTextureColors(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCombineFaceTextureWithOverlay(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\n// Utility functions\r\nvoid SetDefaultFacePoints(SFacePoints* pFacePoints);\r\nbool SetFacePointsStruct(const SFacePoints &face_points, Script::CStruct *p_struct);\r\nbool GetFacePointsStruct(SFacePoints &face_points, Script::CStruct *p_struct);\r\n\r\n}\r\n\r\n#endif //\t__GFX_FACE_MASSAGE_H__\r\n\r\n"
  },
  {
    "path": "Code/Gfx/FaceTexture.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       FaceTexture.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  4/29/2003\r\n//****************************************************************************\r\n\r\n#include <gfx/facetexture.h>\r\n\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n// for temporary texture\r\n#include <sys/file/filesys.h>\r\n\r\nnamespace Gfx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCFaceTexture::CFaceTexture()\r\n{\r\n\tm_isValid = false;\r\n\r\n\tSetDefaultFacePoints( &m_points );\r\n\t\r\n\tSetOverlayTextureName( \"faces\\\\CS_NSN_Head_wht_alpha\" );\r\n\r\n/*\r\n\t// should already be cleared out\r\n\tmemset( m_rawData, 0, vFACE_TEXTURE_SIZE );\r\n*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFaceTexture::LoadFace( const char* pFaceName, bool fullPathIncluded )\r\n{\r\n\t// As a test, set the freak image\r\n\t// (otherwise, we'd need to go through the face download interface)\r\n\tchar extended_filename[512];\r\n\tint file_size;\r\n\r\n\tif ( fullPathIncluded )\r\n\t{\r\n\t\tsprintf( extended_filename, \"%s.img.ps2\", pFaceName );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsprintf( extended_filename, \"images\\\\%s.img.ps2\", pFaceName );\t\r\n\t}\r\n\r\n\tchar* pData = (char*)File::LoadAlloc( extended_filename, &file_size );\r\n\tmemcpy( m_rawData, pData, file_size );\r\n\tDbg_MsgAssert( file_size <= vRAW_TEXTURE_SIZE, ( \"File too big (file is %d, buffer is %d)\", file_size, vRAW_TEXTURE_SIZE ) );\r\n\tMem::Free( pData );\r\n\t\r\n\tm_isValid = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8* CFaceTexture::ReadTextureDataFromBuffer(uint8* pBuffer, int bufferSize)\r\n{\r\n\t// READ RAW IMG.PS2 DATA ONLY, NOT FACE POINT OR OVERLAY INFO\r\n\r\n\t// if a safety-check was specified...\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tif ( bufferSize )\r\n\t{\r\n\t\tint totalSize = vRAW_TEXTURE_SIZE;\r\n\t\tDbg_MsgAssert( bufferSize >= totalSize, ( \"Buffer size (%d bytes) must <= %d bytes\", bufferSize, totalSize ) );\r\n\t}\r\n\t#endif\r\n\t\r\n\tmemcpy( &m_rawData[0], pBuffer, vRAW_TEXTURE_SIZE );\r\n\r\n\tpBuffer += vRAW_TEXTURE_SIZE;\r\n\t\r\n\treturn pBuffer;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CFaceTexture::WriteToBuffer( uint8* pBuffer, int bufferSize )\r\n{\r\n\tint totalSize = 0;\r\n\t\t\r\n\ttotalSize += vRAW_TEXTURE_SIZE;\r\n\tDbg_MsgAssert( bufferSize >= totalSize, ( \"Buffer size (%d bytes) must >= %d bytes\", bufferSize, totalSize ) );\r\n\tmemcpy( pBuffer, &m_rawData[0], vRAW_TEXTURE_SIZE );\r\n\tpBuffer += vRAW_TEXTURE_SIZE;\r\n\t\r\n\ttotalSize += sizeof(Nx::SFacePoints);\r\n\tDbg_MsgAssert( bufferSize >= totalSize, ( \"Buffer size (%d bytes) must >= %d bytes\", bufferSize, totalSize ) );\r\n\tmemcpy( pBuffer, &m_points, sizeof(Nx::SFacePoints) );\r\n\tpBuffer += sizeof(Nx::SFacePoints);\r\n\r\n\ttotalSize += ( strlen( m_overlayTextureName ) + 1 );\r\n\tDbg_MsgAssert( bufferSize >= totalSize, ( \"Buffer size (%d bytes) must >= %d bytes\", bufferSize, totalSize ) );\r\n\tmemcpy( pBuffer, m_overlayTextureName, strlen( m_overlayTextureName ) + 1 );\r\n\tpBuffer += ( strlen( m_overlayTextureName ) + 1 );\r\n\r\n\treturn totalSize;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8* CFaceTexture::ReadFromBuffer( uint8* pBuffer, int bufferSize )\r\n{\r\n\tint totalSize = 0;\r\n\t\r\n\ttotalSize += vRAW_TEXTURE_SIZE;\r\n\tif ( bufferSize )\r\n\t{\r\n\t\t// if a safety-check was specified...\r\n\t\tDbg_MsgAssert( bufferSize >= totalSize, ( \"Buffer size (%d bytes) must <= %d bytes\", bufferSize, totalSize ) );\r\n\t}\r\n\tmemcpy( &m_rawData[0], pBuffer, vRAW_TEXTURE_SIZE );\r\n\tpBuffer += vRAW_TEXTURE_SIZE;\r\n\t\r\n\ttotalSize += sizeof(Nx::SFacePoints);\r\n\tif ( bufferSize )\r\n\t{\r\n\t\t// if a safety-check was specified...\r\n\t\tDbg_MsgAssert( bufferSize >= totalSize, ( \"Buffer size (%d bytes) must <= %d bytes\", bufferSize, totalSize ) );\r\n\t}\r\n\tmemcpy( &m_points, pBuffer, sizeof(Nx::SFacePoints) );\r\n\tpBuffer += sizeof(Nx::SFacePoints);\r\n\r\n\tint overlayNameLength = strlen( (char*)pBuffer );\r\n\tif ( overlayNameLength >= vMAX_OVERLAY_NAME_SIZE )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Unusual length for overlay name\" ) );\r\n\t}\r\n\t\r\n\ttotalSize += ( overlayNameLength + 1 );\r\n\tif ( bufferSize )\r\n\t{\r\n\t\t// if a safety-check was specified...\r\n\t\tDbg_MsgAssert( bufferSize >= totalSize, ( \"Buffer size (%d bytes) must <= %d bytes\", bufferSize, totalSize ) );\r\n\t}\r\n\tmemcpy( m_overlayTextureName, pBuffer, overlayNameLength + 1 );\r\n\tpBuffer += ( overlayNameLength + 1 );\r\n\r\n\treturn pBuffer;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CFaceTexture::WriteIntoStructure( Script::CStruct* pSubStruct )\r\n{\r\n\tDbg_Assert( pSubStruct );        \r\n\tDbg_MsgAssert( IsValid(), ( \"Face texture is not valid!\" ) );\r\n\r\n\tScript::CArray* pRawTextureArray = new Script::CArray;\r\n\tDbg_MsgAssert( ( vRAW_TEXTURE_SIZE ) % 4 == 0, ( \"Was expecting raw texture size to be a multiple of 4\", vRAW_TEXTURE_SIZE ) ); \r\n\tpRawTextureArray->SetSizeAndType( vRAW_TEXTURE_SIZE / 4, ESYMBOLTYPE_NAME );\r\n\r\n\tuint32* pFaceData = (uint32*)&m_rawData[0];\r\n\r\n\tfor ( int i = 0; i < (vRAW_TEXTURE_SIZE / 4); i++ )\r\n\t{\r\n\t\t\r\n\t\tpRawTextureArray->SetChecksum( i, *pFaceData );\r\n\t\tpFaceData++;\r\n\t}\r\n\r\n\tpSubStruct->AddArrayPointer( CRCD(0x99790d96,\"rawTextureData\"), pRawTextureArray );\r\n\tpSubStruct->AddString( CRCD(0xa7e7a264,\"overlayTextureName\"), m_overlayTextureName );\r\n\tNx::SetFacePointsStruct( m_points, pSubStruct );\r\n\r\n\t// readfromstructure should also set the valid flag\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CFaceTexture::ReadFromStructure( Script::CStruct* pSubStruct )\r\n{\r\n\tDbg_Assert( pSubStruct );\r\n\r\n\tScript::CArray* pRawTextureArray;\r\n\tpSubStruct->GetArray( CRCD(0x99790d96,\"rawTextureData\"), &pRawTextureArray, Script::ASSERT );\r\n\t\r\n\tuint32* pFaceData = (uint32*)&m_rawData[0];\r\n\tDbg_Assert( pRawTextureArray->GetSize() * sizeof(uint32) == vRAW_TEXTURE_SIZE );\r\n\tfor ( uint32 i = 0; i < pRawTextureArray->GetSize(); i++ )\r\n\t{\r\n\t\t*pFaceData = pRawTextureArray->GetChecksum( i );\r\n\t\tpFaceData++;\r\n\t}\r\n\t\r\n\tconst char* pOverlayTextureName;\r\n\tpSubStruct->GetString( CRCD(0xa7e7a264,\"overlayTextureName\"), &pOverlayTextureName, Script::ASSERT );\r\n\tstrcpy( m_overlayTextureName, pOverlayTextureName );\r\n\r\n\tNx::GetFacePointsStruct( m_points, pSubStruct );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CFaceTexture::PrintContents()\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tm_points.PrintData();\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CFaceTexture::IsValid() const\r\n{\r\n\treturn m_isValid;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFaceTexture::SetValid( bool valid )\r\n{\r\n\tm_isValid = valid;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nuint8* CFaceTexture::GetTextureData()\r\n{\r\n\treturn m_rawData;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CFaceTexture::GetTextureSize() const\r\n{\r\n\treturn vRAW_TEXTURE_SIZE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::SFacePoints CFaceTexture::GetFacePoints() const\r\n{\r\n\treturn m_points;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFaceTexture::SetFacePoints( const Nx::SFacePoints& facePoints )\r\n{\r\n\tm_points = facePoints;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFaceTexture::SetOverlayTextureName(const char* pTextureName)\r\n{\r\n\tDbg_MsgAssert( pTextureName, ( \"No texture name specified\" ) );\r\n\tDbg_MsgAssert( strlen(pTextureName) < vMAX_OVERLAY_NAME_SIZE, ( \"Overlay name is too long %s (max=%d)\", pTextureName, vMAX_OVERLAY_NAME_SIZE ) );\r\n\r\n\tstrcpy( m_overlayTextureName, pTextureName );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char* CFaceTexture::GetOverlayTextureName()\r\n{\r\n\treturn m_overlayTextureName;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/FaceTexture.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       FaceTexture.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  4/29/2003\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_FACE_TEXTURE_H__\r\n#define\t__GFX_FACE_TEXTURE_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n// for SFacePoints\r\n#include <gfx/facemassage.h>\r\n\r\nnamespace Gfx\r\n{\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n// This encapsulates all the face texture-related data\r\n// (raw texture data, and any tweaks needed for correct\r\n// mapping).  The \"WriteToBuffer/ReadFromBuffer\" is\r\n// used to store this data to a memory card, to a skater\r\n// profile, or for use in network games.\r\nclass CFaceTexture : public Spt::Class\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\t// TODO:  Find out how big the data really needs to be...\r\n\t\t// (right now, it's 16K for the texture data, and 1K for the palette data)\r\n\t\tvRAW_TEXTURE_SIZE = ( 17440 ),\r\n\t\tvMAX_OVERLAY_NAME_SIZE = 64,\r\n\t\tvTOTAL_CFACETEXTURE_SIZE = vRAW_TEXTURE_SIZE + sizeof(Nx::SFacePoints) + vMAX_OVERLAY_NAME_SIZE,\r\n\t};\r\n\r\n\tCFaceTexture();\r\n\r\npublic:\r\n\t// general accessors\r\n\tbool\t\t\t\tIsValid() const;\r\n\tvoid\t\t\t\tSetValid( bool valid );\r\n\tuint8*\t\t\t\tGetTextureData();\r\n\tint\t\t\t\t\tGetTextureSize() const;\r\n\tNx::SFacePoints\t\tGetFacePoints() const;\r\n\tvoid\t\t\t\tSetFacePoints( const Nx::SFacePoints& facePoints );\r\n\tvoid\t\t\t\tSetOverlayTextureName(const char* pTexture);\r\n\tconst char*\t\t\tGetOverlayTextureName();\r\n\r\n\t// debug face\r\n\tvoid\t\t\t\tLoadFace( const char* pFaceName, bool fullPathIncluded );\r\n\tvoid\t\t\t\tPrintContents();\r\n\r\npublic:\r\n\t// for downloading faces\r\n\t// (handles raw IMG.PS2 data only)\r\n\tuint8*\t\t\t\tReadTextureDataFromBuffer(uint8* pBuffer, int bufferSize);\r\n\r\npublic:\r\n\t// for network message handling\r\n\t// (handles raw IMG.PS2 data, face points, overlay information)\r\n\tint\t\t\t\t\tWriteToBuffer(uint8* pBuffer, int bufferSize );\r\n\tuint8*\t\t\t\tReadFromBuffer(uint8* pBuffer, int bufferSize );\r\n\t\r\npublic:\r\n\t// for memory card loading/saving\r\n\t// (handles raw IMG.PS2 data, face points, overlay information)\r\n\tvoid \t\t\t\tWriteIntoStructure( Script::CStruct* pStuff );\r\n\tvoid \t\t\t\tReadFromStructure( Script::CStruct* pStuff );\r\n\r\nprotected:\r\n\tbool\t\t\t\tm_isValid;\r\n\tNx::SFacePoints\t\tm_points;\r\n\tuint8\t\t\t\tm_rawData[vRAW_TEXTURE_SIZE];\r\n\tchar\t\t\t\tm_overlayTextureName[vMAX_OVERLAY_NAME_SIZE];\r\n};\r\n\r\n}\r\n\r\n#endif //\t__GFX_FACE_TEXTURE_H__\r\n\r\n"
  },
  {
    "path": "Code/Gfx/Image/ImageBasic.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t            \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t              \t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t                    \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:     rjm        \t\t\t\t    \t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t                                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_IMAGE_IMAGEBASIC_H\r\n#define __GFX_IMAGE_IMAGEBASIC_H\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Image\r\n{\r\n\r\nenum JustX\r\n{\r\n\tvJUST_LEFT \t\t= 0,\r\n\tvJUST_CENTER_X,\r\n\tvJUST_RIGHT,\r\n};\r\n\r\nenum JustY\r\n{\r\n\tvJUST_TOP\t\t= 0,\r\n\tvJUST_CENTER_Y,\t\r\n\tvJUST_BOTTOM,\r\n};\r\n\r\n\r\nstruct RGBA\r\n{\r\n\tRGBA() { }\r\n\tRGBA(uint8 red, uint green, uint blue, uint alpha) :\r\n\t\tr(red),\r\n\t\tg(green),\r\n\t\tb(blue),\r\n\t\ta(alpha) { }\r\n\r\n\tvoid\tBlend128(const RGBA & rgba);\r\n\tvoid\tBlend255(const RGBA & rgba);\r\n\r\n\tuint8 r;\r\n\tuint8 g;\r\n\tuint8 b;\r\n\tuint8 a;\r\n};\r\n\r\n////////////////////////\r\n// Inlines\r\n\r\ninline void RGBA::Blend128(const RGBA & rgba)\r\n{\r\n\tint blend_val;\r\n\r\n\tblend_val = r * rgba.r;\r\n\tr = (uint8) (blend_val >> 7);\r\n\tblend_val = g * rgba.g;\r\n\tg = (uint8) (blend_val >> 7);\r\n\tblend_val = b * rgba.b;\r\n\tb = (uint8) (blend_val >> 7);\r\n\tblend_val = a * rgba.a;\r\n\ta = (uint8) (blend_val >> 7);\r\n}\r\n\r\ninline void RGBA::Blend255(const RGBA & rgba)\r\n{\r\n\tint blend_val;\r\n\r\n\tblend_val = r * rgba.r;\r\n\tr = (uint8) (blend_val / 255);\r\n\tblend_val = g * rgba.g;\r\n\tg = (uint8) (blend_val / 255);\r\n\tblend_val = b * rgba.b;\r\n\tb = (uint8) (blend_val / 255);\r\n\tblend_val = a * rgba.a;\r\n\ta = (uint8) (blend_val >> 7);\t\t// Alpha is always 128 == 1.0\r\n}\r\n\r\n}\r\n\r\n#endif //__GFX_IMAGE_IMAGEBASIC_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/ModelAppearance.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       ModelAppearance.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  4/2/2000\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/modelappearance.h>\r\n\r\n#include <gfx/casutils.h>\r\n#include <gfx/facetexture.h>\r\n#include <gfx/modelbuilder.h>\r\n\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n// NOTES:\r\n\r\n// A CModelAppearance contains one script structure, whose\r\n// contents look something like this:\r\n//\t{\r\n//\t\thead\t\t\t= { desc_id=#\"Andrew Reynolds\" h = 0 s = 50 v = 100 use_default_hsv = 1 }\r\n//\t\ttorso\t\t\t= { desc_id=#\"Long Sleeve - Collar\" h = 0 s = 50 v = 100 use_default_hsv = 1 }\r\n//\t\tlegs\t\t\t= { desc_id=#\"Reynolds's Pants\" h = 0 s = 50 v = 100 use_default_hsv = 1 }\r\n//\t\tshoes\t\t\t= { desc_id=#\"Reynolds's\" h = 0 s = 50 v = 100 use_default_hsv = 1 }\r\n//\t\tboardup\t\t\t= { desc_id=#\"Solid\" }\t\r\n//\t\tboarddown\t\t= { desc_id=#\"Green Brand Logo\" h = 0 s = 50 v = 100 use_default_hsv = 1 }\r\n//\t\tscale\t\t\t= 1.02\r\n//\t\tweight_scale\t= 0.97\r\n//\t}\r\n\r\n// Basically, it's a bunch of \"virtual structures\", each \r\n// assigned to a \"part checksum\" (head, torso, etc.).  \r\n// Each part checksum corresponds to the name of a global\r\n// array containing a list of read-only \"actual structures\".\r\n// Given a part checksum and a desc_id in the CModelAppearance, \r\n// we can lookup the appropriate global array and find the \r\n// appropriate actual structure.\r\n\r\n// CModelAppearance is really just a wrapper around the\r\n// CStruct class, but after some consideration,\r\n// I decided not to subclass from it.  This is so that\r\n// I'd be able to replace the underlying implementation\r\n// while keeping the same interface.\r\n\r\n// There shouldn't be anything skater- (or even player-)\r\n// specific hardcoded here.  The intent is that we use\r\n// this same class for any kind of customizable model\r\n// (such as Create-a-Peds, Create-a-Cars, or even\r\n// Create-a-Spaceships for future games).\r\n\t\r\n// The CModelAppearance should have no knowledge of the full\r\n// list of possible part checksums;  this list should be\r\n// completely in script.  This implies that the code should\r\n// never have to iterate through a list of part checksums,\r\n// (unlike THPS3, which had many explicit references to\r\n// \"editable_cas_options\", Cas::GetBodyPartCount(), and\r\n// Cas::GetBodyPartName()).\r\n\r\n// One of the reset types used to be \"randomized\", but\r\n// that is something that is more appropriate at the skater\r\n// profile level (or, even better, in script), which has\r\n// a better understanding of what parts should be disqualified \r\n// from working with a particular skater instance.  If \r\n// randomization were to be implemented at this level, it should\r\n// be a purely naive randomization (no weighting, no part\r\n// disqualification).\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 get_desc_id_from_structure( Script::CStruct* pStructure )\r\n{\r\n\t// This function is purely for convenience.  It grabs\r\n\t// the \"desc_id\" field from the supplied structure.\r\n\t\r\n\tuint32 descId = 0;\r\n\tpStructure->GetChecksum( CRCD(0x4bb2084e,\"desc_id\"), &descId, Script::NO_ASSERT );\r\n\treturn descId;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelAppearance::resolve_randomized_desc_ids()\r\n{\r\n\t// for each structure component, see whether\r\n\t// it's got any randomized desc ids.  if so,\r\n\t// select one to be used every time this\r\n\t// appearance instance is used\r\n\r\n\t// sometimes the skin tone must be consistent \r\n\t// among all the body parts...  if any structure\r\n\t// contains a \"random_set\" checksum, then\r\n\t// make sure all future random parts get\r\n\t// this selected as well\r\n\tuint32 random_set = 0;\r\n\r\n\tScript::CComponent* p_comp = m_appearance.GetNextComponent( NULL );\r\n\twhile ( p_comp )\r\n\t{\r\n\t\tScript::CComponent* p_next = m_appearance.GetNextComponent( p_comp );\t\t\r\n\t\t\r\n\t\tif ( p_comp->mType == ESYMBOLTYPE_STRUCTURE )\r\n\t\t{\r\n\t\t\tuint32 partChecksum = p_comp->mNameChecksum;\r\n\t\t\tint randomIndex;\r\n\r\n\t\t\tif ( p_comp->mpStructure->ContainsFlag( CRCD(0xd81c03b0,\"randomized_desc_id\") ) )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pActualStruct = Cas::GetRandomOptionStructure( partChecksum, random_set );\r\n\t\t\t\tDbg_MsgAssert( pActualStruct, ( \"Unrecognized part checksum to randomize %s\", Script::FindChecksumName(partChecksum) ) );\r\n\t\t\t\t\r\n\t\t\t\t// remember the random_set, if any\r\n\t\t\t\tpActualStruct->GetChecksum( CRCD(0x0d7260fd,\"random_set\"), &random_set, Script::NO_ASSERT );\r\n\t\t\t\t\r\n\t\t\t\tp_comp->mpStructure->Clear();\r\n\t\t\t\tp_comp->mpStructure->AddChecksum( CRCD(0x4bb2084e,\"desc_id\"), get_desc_id_from_structure(pActualStruct) );\r\n\t\t\t}\r\n\t\t\telse if ( p_comp->mpStructure->GetInteger( CRCD(0x4b833e64,\"random_index\"), &randomIndex, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pActualStruct = Cas::GetRandomOptionStructureByIndex( partChecksum, randomIndex, random_set );\r\n\t\t\t\tDbg_MsgAssert( pActualStruct, ( \"Unrecognized part checksum to randomize %s\", Script::FindChecksumName(partChecksum) ) );\r\n\t\t\t\t\r\n\t\t\t\t// remember the random_set, if any\r\n\t\t\t\tpActualStruct->GetChecksum( CRCD(0x0d7260fd,\"random_set\"), &random_set, Script::NO_ASSERT );\r\n\t\t\t\t\r\n\t\t\t\tp_comp->mpStructure->Clear();\r\n\t\t\t\tp_comp->mpStructure->AddChecksum( CRCD(0x4bb2084e,\"desc_id\"), get_desc_id_from_structure(pActualStruct) );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_comp = p_next;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelAppearance::clear_part(uint32 partChecksum)\r\n{\r\n\tm_appearance.RemoveComponent(partChecksum);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelAppearance::set_part(uint32 partChecksum, uint32 descID, Script::CStruct* pParams)\r\n{\r\n\tScript::CStruct* pStruct;\r\n\t\r\n\t// if the structure doesn't already exist, then add it...\r\n\tif ( !m_appearance.GetStructure(partChecksum, &pStruct) )\r\n\t{\r\n\t\tpStruct = new Script::CStruct;\r\n\t\tm_appearance.AddComponent(partChecksum, ESYMBOLTYPE_STRUCTUREPOINTER, (int)pStruct);\r\n\t}\r\n\r\n\tpStruct->Clear();\r\n\r\n\t// check for extra color parameters\r\n\tint use_default_hsv = 1;\r\n\tpParams->GetInteger( CRCD(0x97dbdde6,\"use_default_hsv\"), &use_default_hsv, Script::NO_ASSERT );\r\n\t\r\n\tif ( !use_default_hsv )\r\n\t{\r\n\t\tint h, s, v;\r\n\t\tpParams->GetInteger( CRCD(0x6e94f918,\"h\"), &h, Script::ASSERT );\r\n\t\tpParams->GetInteger( CRCD(0xe4f130f4,\"s\"), &s, Script::ASSERT );\r\n\t\tpParams->GetInteger( CRCD(0x949bc47b,\"v\"), &v, Script::ASSERT );\r\n\t\t\r\n\t\tpStruct->AddInteger( CRCD(0x97dbdde6,\"use_default_hsv\"), 0 );\r\n\t\tpStruct->AddInteger( CRCD(0x6e94f918,\"h\"), h );\r\n\t\tpStruct->AddInteger( CRCD(0xe4f130f4,\"s\"), s );\r\n\t\tpStruct->AddInteger( CRCD(0x949bc47b,\"v\"), v );\r\n\t}\r\n\r\n\tpStruct->AddChecksum( CRCD(0x4bb2084e,\"desc_id\"), descID );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelAppearance::set_checksum(uint32 fieldChecksum, uint32 valueChecksum)\r\n{\r\n\tm_appearance.AddChecksum( fieldChecksum, valueChecksum );\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCModelAppearance::CModelAppearance( void )\r\n{\r\n\tmp_faceTexture = NULL;\r\n\r\n\tm_willEventuallyHaveFaceTexture = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModelAppearance::CModelAppearance( const CModelAppearance& rhs )\r\n{\r\n\tmp_faceTexture = NULL;\r\n\r\n\t// use the overridden assignment operator\r\n\t*this = rhs;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCModelAppearance::~CModelAppearance()\r\n{\r\n\tif ( mp_faceTexture )\r\n\t{\r\n\t\tdelete mp_faceTexture;\r\n\t\tmp_faceTexture = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModelAppearance& CModelAppearance::operator=( const CModelAppearance& rhs )\r\n{\r\n\tif ( &rhs == this )\r\n\t{\r\n\t\treturn *this;\r\n\t}\r\n\r\n\t// it shouldn't be necessary to define this function, as\r\n\t// this is what the default assignment operator is supposed\r\n\t// to do.  However, the compiler gives me warnings if I\r\n\t// don't define it (\"statement with no effect\").\r\n\tm_appearance = rhs.m_appearance;\r\n\r\n\t// get rid of old face texture\r\n\tif ( mp_faceTexture )\r\n\t{\r\n\t\tdelete mp_faceTexture;\r\n\t\tmp_faceTexture = NULL;\r\n\r\n\t}\r\n\r\n\tif ( rhs.mp_faceTexture )\r\n\t{\r\n\t\tCreateFaceTexture();\r\n\t\tDbg_Assert( mp_faceTexture );\r\n\t\t*mp_faceTexture = *rhs.mp_faceTexture;\r\n\t}\r\n\r\n\tm_willEventuallyHaveFaceTexture = rhs.m_willEventuallyHaveFaceTexture;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelAppearance::Init()\r\n{\r\n\tm_appearance.Clear();\r\n\r\n\tif ( mp_faceTexture )\r\n\t{\r\n\t\t// reset the face texture\r\n\t\tmp_faceTexture->SetValid( false );\r\n\t}\r\n\r\n\t// everyone should have certain items defined, \r\n\t// such as sleeves for doing sleeve colors.\r\n\tScript::CStruct* pResetStructure = Script::GetStructure( CRCD(0xfe54486d,\"appearance_init_structure\"), Script::NO_ASSERT );\r\n\tif ( pResetStructure )\r\n\t{\r\n\t\tm_appearance.AppendStructure( pResetStructure );\r\n\t}\r\n\r\n\tm_willEventuallyHaveFaceTexture = false;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelAppearance::Load( Script::CStruct* pStructure, bool resolve_randoms )\r\n{\r\n\tDbg_Assert( pStructure );\r\n\r\n\t// In THPS3, we didn't clear the m_appearance first when\r\n\t// loading from a memory card, so that if the saved data is \r\n\t// missing anything, it won't matter because the default \r\n\t// will already be in m_appearance.  (This prevents asserts\r\n\t// on autoloading when a new component has been added to \r\n\t// m_appearance which is not present on the memory card)\r\n\t// However, for THPS4, the appearances should be a lot more\r\n\t// flexible, and should no longer fail when there are missing items.\r\n\tInit();\r\n\r\n#if 1\r\n\t// in case there are any global structure names,\r\n\t// resolve them\r\n\tpStructure->ExpandInto(\t&m_appearance, 0 );\r\n#else\r\n\t// add the new desired data\r\n\tm_appearance.AppendStructure( pStructure );\r\n#endif\r\n\t\r\n   // at this point, all the randomized_desc_ids\r\n\t// should be resolved\r\n\tif ( resolve_randoms )\r\n\t{\r\n\t\tresolve_randomized_desc_ids();\r\n\t}\r\n\t\t\r\n#ifdef\t__NOPT_ASSERT__\r\n\t// Make sure that the m_appearance does not contain any flag members,\r\n\t// which would potentially cause leaks as we append any structures.\r\n\tuint32 dummy = 0;\r\n\tDbg_MsgAssert( !m_appearance.GetChecksum( NONAME, &dummy ), ( \"m_appearance contains a flag '%s'\", Script::FindChecksumName(dummy) ) );\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelAppearance::Load( uint32 structure_name, bool resolve_randoms )\r\n{\r\n\tScript::CStruct* pStructure;\r\n\r\n\tpStructure = Script::GetStructure( structure_name, Script::ASSERT );\r\n\r\n\treturn Load( pStructure, resolve_randoms );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifndef __PLAT_NGC__\r\nvoid compress_model_appearance( Script::CStruct* pStruct )\r\n{\r\n\t// the worst-case is too big to fit into a network packet\r\n\t// so this will remove some of the more unnecessary items\r\n\t// from the structure.\r\n\tpStruct->RemoveComponent( CRCD(0xb1d19000,\"deck_layer1\") );\r\n\tpStruct->RemoveComponent( CRCD(0x28d8c1ba,\"deck_layer2\") );\r\n\tpStruct->RemoveComponent( CRCD(0x5fdff12c,\"deck_layer3\") );\r\n\tpStruct->RemoveComponent( CRCD(0xc1bb648f,\"deck_layer4\") );\r\n\tpStruct->RemoveComponent( CRCD(0xb6bc5419,\"deck_layer5\") );\r\n\r\n\tpStruct->RemoveComponent( CRCD(0x3fa9b96e,\"head_tattoo\") );\r\n\tpStruct->RemoveComponent( CRCD(0x283dea37,\"left_bicep_tattoo\") );\r\n\tpStruct->RemoveComponent( CRCD(0xde55864b,\"left_forearm_tattoo\") );\r\n\tpStruct->RemoveComponent( CRCD(0xd408fa96,\"right_bicep_tattoo\") );\r\n\tpStruct->RemoveComponent( CRCD(0x74fee7b2,\"right_forearm_tattoo\") );\r\n\tpStruct->RemoveComponent( CRCD(0x8eba2bc9,\"chest_tattoo\") );\r\n\tpStruct->RemoveComponent( CRCD(0x233b7bba,\"back_tattoo\") );\r\n\tpStruct->RemoveComponent( CRCD(0x2b359a94,\"left_leg_tattoo\") );\r\n\tpStruct->RemoveComponent( CRCD(0x609432ca,\"right_leg_tattoo\") );\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CModelAppearance::WriteToBuffer(uint8 *pBuffer, uint32 BufferSize, bool ignoreFaceData )\r\n{\r\n\t// for network message building\r\n\t// (note that the face texture is not included in this buffer\r\n\t// because the buffer is too small...  face textures will\r\n\t// be sent in a separate net packet)\r\n\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\tpTempStructure->AppendStructure( &m_appearance );\r\n\tuint32 size = Script::WriteToBuffer(pTempStructure, pBuffer, BufferSize);\r\n\r\n#ifndef __PLAT_NGC__\r\n\t// GJ:  Need to compress the model appearances for Xbox and PS2\r\n\t// versions, or else the worst-case model appearance will crash\r\n\t// the server if he quits his own game (because it overflows the\r\n\t// max net packet size).  MAX_MODEL_APPEARANCE_SIZE is a guess \r\n\t// based on the existing model appearance size, but it really\r\n\t// depends on how big the info/tricks get...  700 bytes seems safe\r\n\tconst uint32 MAX_MODEL_APPEARANCE_SIZE = 700;\r\n\tif ( size > MAX_MODEL_APPEARANCE_SIZE )\r\n\t{\r\n\t\t// if the model appearance is too big, then\tstrip out\r\n\t\t// some of the cosmetic stuff...\r\n\t\tcompress_model_appearance( pTempStructure );\r\n\t\tsize = Script::WriteToBuffer(pTempStructure, pBuffer, BufferSize);\r\n\t}\r\n#endif\r\n\r\n\tdelete pTempStructure;\r\n\r\n\t// skip to the next chunk\r\n\tpBuffer += size;\r\n\tBufferSize -= size;\r\n\r\n\t// we do, however, still need to send a flag that says it\r\n\t// will eventually have a face texture...  so that the model \r\n\t// builder knows to use the face-mapped head rather than\r\n\t// the non-facemapped head\r\n\tif( ignoreFaceData )\r\n\t{\r\n\t\t\r\n\t\t*pBuffer = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t*pBuffer = ( ( GetFaceTexture() && GetFaceTexture()->IsValid() ) || m_willEventuallyHaveFaceTexture ) ? 1 : 0;\t\t\r\n\t}\r\n\t\r\n\tpBuffer += 1;\r\n\tBufferSize -= 1;\r\n\tsize += 1;\r\n\t\r\n\treturn size;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8* CModelAppearance::ReadFromBuffer(uint8 *pBuffer)\r\n{\r\n\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\tpBuffer = Script::ReadFromBuffer( pTempStructure, pBuffer );\r\n\tm_appearance.Clear();\r\n\tm_appearance.AppendStructure( pTempStructure );\r\n\tdelete pTempStructure;\r\n\t\r\n\t// we do, however, still need to send a flag that says it\r\n\t// will eventually have a face texture...  so that the model \r\n\t// builder knows to use the face-mapped head rather than\r\n\t// the non-facemapped head\r\n\tm_willEventuallyHaveFaceTexture = *pBuffer;\r\n\tpBuffer++;\r\n\t\r\n\treturn pBuffer;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelAppearance::PrintContents( const Script::CStruct* p_structure )\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\t//Script::PrintContents( &m_appearance );\r\n\r\n\tif(!p_structure)\r\n\t{\r\n\t\tp_structure = &m_appearance;\r\n\t}\r\n\t//const Script::CStruct* p_structure= &m_appearance;\r\n\r\n\tDbg_MsgAssert(p_structure,(\"NULL p_structure\"));\r\n\t  \r\n\t//printf(\" \");\r\n\t\r\n\t\r\n\tprintf(\"{\");\r\n\t\t\t\r\n    Script::CComponent *p_comp=p_structure->GetNextComponent(NULL);\r\n\r\n    while (p_comp)\r\n    {\r\n\t\t\r\n\t\tif (p_comp->mNameChecksum)\r\n\t\t{\r\n\t\t\tprintf(\" %s=\",Script::FindChecksumName(p_comp->mNameChecksum));\r\n\t\t}\t\r\n            \r\n        switch (p_comp->mType)\r\n        {\r\n        case ESYMBOLTYPE_INTEGER:\r\n            printf(\"%d\",p_comp->mIntegerValue);\r\n            break;\r\n        case ESYMBOLTYPE_FLOAT:\r\n            printf(\"%f\",p_comp->mFloatValue);\r\n            break;\r\n        case ESYMBOLTYPE_STRING:\r\n            printf(\"#\\\"%s\\\"\",p_comp->mpString);\r\n            break;\r\n        case ESYMBOLTYPE_LOCALSTRING:\r\n            printf(\"'%s'\",p_comp->mpLocalString);\r\n            break;\r\n\t\t/*case ESYMBOLTYPE_PAIR:\r\n            printf(\"(%f,%f) \",p_comp->mpPair->mX,p_comp->mpPair->mY);\r\n            break;\r\n        case ESYMBOLTYPE_VECTOR:\r\n            printf(\"(%f,%f,%f) \",p_comp->mpVector->mX,p_comp->mpVector->mY,p_comp->mpVector->mZ);\r\n            break;*/\r\n        case ESYMBOLTYPE_STRUCTURE:\r\n\t\t\t//printf(\" \");\r\n\t\t\tCModelAppearance::PrintContents(p_comp->mpStructure);\r\n            break;\r\n        case ESYMBOLTYPE_NAME:\r\n            printf(\"#\\\"%s\\\"\",Script::FindChecksumName(p_comp->mChecksum));\r\n\t\t\t\r\n\t\t\t#ifdef EXPAND_GLOBAL_STRUCTURE_REFERENCES\r\n\t\t\tif (p_comp->mNameChecksum==0)\r\n\t\t\t{\r\n\t\t\t\t// It's an un-named name. Maybe it's a global structure ... \r\n\t\t\t\t// If so, print its contents too, which is handy for debugging.\r\n\t\t\t    CSymbolTableEntry *p_entry=Resolve(p_comp->mChecksum);\r\n\t\t\t\tif (p_entry && p_entry->mType==ESYMBOLTYPE_STRUCTURE)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf(\"... Defined in %s ...\\n\",Script::FindChecksumName(p_entry->mSourceFileNameChecksum));\r\n\t\t\t\t\tDbg_MsgAssert(p_entry->mpStructure,(\"NULL p_entry->mpStructure\"));\r\n\t\t\t\t\tCModelAppearance::PrintContents(p_entry->mpStructure);\r\n\t\t\t\t}\r\n\t\t\t}\t\t\r\n\t\t\t#endif\r\n            break;\r\n        case ESYMBOLTYPE_QSCRIPT:\r\n\t\t\tprintf(\"(A script) \"); // TODO\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t\t//printf(\" \");\r\n\t\t\tScript::PrintContents(p_comp->mpArray,0);\r\n            break;\r\n        default:\r\n\t\t\tprintf(\"Component of type '%s', value 0x%08x\\n\",Script::GetTypeName(p_comp->mType),p_comp->mUnion);\r\n            //Dbg_MsgAssert(0,(\"Bad p_comp->Type\"));\r\n            break;\r\n        }\r\n        p_comp=p_structure->GetNextComponent(p_comp);\r\n\t\t\r\n\t\t#ifdef SLOW_DOWN_PRINTCONTENTS\r\n\t\t// A delay to let printf catch up so that it doesn't skip stuff when printing big arrays.\t\t\r\n\t\tfor (int i=0; i<1000000; ++i);\r\n\t\t#endif\r\n    }\r\n\t\r\n\tprintf(\"}\\n\");\r\n\r\n\r\n\t/*if ( mp_faceTexture && mp_faceTexture->IsValid() )\r\n\t{\r\n\t\tmp_faceTexture->PrintContents();\r\n\t}*/\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* CModelAppearance::GetActualDescStructure( uint32 partChecksum )\r\n{\r\n\tScript::CStruct* pStructure;\r\n\tif ( m_appearance.GetStructure( partChecksum, &pStructure, Script::NO_ASSERT ) )\r\n\t{\r\n\t\treturn Cas::GetOptionStructure( partChecksum, get_desc_id_from_structure( pStructure ), false );\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* CModelAppearance::GetVirtualDescStructure( uint32 partChecksum )\r\n{\r\n\tScript::CStruct* pStructure = NULL;\r\n\tm_appearance.GetStructure( partChecksum, &pStructure, Script::NO_ASSERT );\r\n\treturn pStructure;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelAppearance::CallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( checksum )\r\n\t{\r\n\t\tcase 0x0a23400c:\t\t// ClearPart\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(pParams, (\"No params supplied to model appearance\"));\r\n\r\n\t\t\tuint32 partChecksum;\r\n\t\t\tpParams->GetChecksum( CRCD(0xb6f08f39,\"part\"), &partChecksum, Script::ASSERT );\r\n\t\t\tclear_part(partChecksum);\r\n\t\t}\r\n\t\treturn true;\r\n\t\t\r\n\t\tcase 0x83339d0b:\t\t// SetPart\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(pParams, (\"No params supplied to model appearance\"));\r\n\r\n\t\t\tuint32 partChecksum;\r\n\t\t\tpParams->GetChecksum( CRCD(0xb6f08f39,\"part\"), &partChecksum, Script::ASSERT );\r\n\t\r\n\t\t\tuint32 descChecksum;\r\n\t\t\tpParams->GetChecksum( CRCD(0x4bb2084e,\"desc_id\"), &descChecksum, Script::ASSERT );\r\n\t\t\t\r\n\t\t\tset_part(partChecksum, descChecksum, pParams);\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0x10a225d6:\t\t// GetPart\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(pParams, (\"No params supplied to model appearance\"));\r\n\t\t\r\n\t\t\tuint32 partChecksum;\r\n\t\t\tpParams->GetChecksum( CRCD(0xb6f08f39,\"part\"), &partChecksum, Script::ASSERT );\r\n\t\r\n\t\t\tScript::CStruct* pVirtualDescStructure = GetVirtualDescStructure( partChecksum );\r\n\r\n\t\t\tif ( pVirtualDescStructure )\r\n\t\t\t{\r\n\t\t\t\t// return all the parameters, including desc_id, use_default_hsv, h, s, v\r\n\t\t\t\tpScript->GetParams()->AppendStructure( pVirtualDescStructure );\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0xd27427ff:\t\t// SetChecksum\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(pParams, (\"No params supplied to model appearance\"));\r\n\r\n\t\t\tuint32 fieldChecksum;\r\n\t\t\tpParams->GetChecksum( CRCD(0xa40abaa7,\"field\"), &fieldChecksum, Script::ASSERT );\r\n\t\r\n\t\t\tuint32 valueChecksum;\r\n\t\t\tpParams->GetChecksum( CRCD(0xe288a7cb,\"value\"), &valueChecksum, Script::ASSERT );\r\n\t\t\t\r\n\t\t\tset_checksum(fieldChecksum, valueChecksum);\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0xb13906b0:\t\t// GotPart\r\n\t\t{\r\n\t\t\tuint32 partChecksum;\r\n\t\t\tpParams->GetChecksum( CRCD(0xb6f08f39,\"part\"), &partChecksum, Script::ASSERT );\r\n\t\t\treturn ( GetActualDescStructure( partChecksum ) );\r\n\t\t}\r\n\r\n\t\tcase 0xe961bafa:\t\t// PartGotFlag\r\n\t\t{\r\n\t\t\tuint32 partChecksum;\r\n\t\t\tpParams->GetChecksum( CRCD(0xb6f08f39,\"part\"), &partChecksum, Script::ASSERT );\r\n\t\t\tuint32 flagChecksum;\r\n\t\t\tpParams->GetChecksum( CRCD(0x2e0b1465,\"flag\"), &flagChecksum, Script::ASSERT );\r\n\r\n\t\t\tScript::CStruct* pActualDescStructure = GetActualDescStructure( partChecksum );\r\n\r\n\t\t\tif ( pActualDescStructure )\r\n\t\t\t{\r\n\t\t\t\treturn pActualDescStructure->ContainsFlag( flagChecksum );\r\n\t\t\t}\r\n\r\n\t\t\tDbg_MsgAssert( 0, ( \"part %s was not defined (need it for disqualification script)\", Script::FindChecksumName(partChecksum) ) );\r\n\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn Obj::CObject::CallMemberFunction(checksum, pParams, pScript);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCFaceTexture* CModelAppearance::GetFaceTexture()\r\n{\r\n\treturn mp_faceTexture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t\t\t\t\t\t\t  \r\nvoid CModelAppearance::CreateFaceTexture()\r\n{\r\n\tDbg_MsgAssert( !mp_faceTexture, ( \"Model appearance already has a face texture\" ) );\r\n\t\r\n\t// the face texture should always go on the skater info heap\r\n\t// these may be permanent, or they might be temporary...\r\n\tmp_faceTexture = new CFaceTexture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t\t\t\t\t\t\t  \r\nvoid CModelAppearance::DestroyFaceTexture()\r\n{\r\n\tif ( mp_faceTexture )\r\n\t{\r\n\t\tdelete mp_faceTexture;\r\n\t\tmp_faceTexture = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelAppearance::WillEventuallyHaveFaceTexture()\r\n{\r\n\treturn m_willEventuallyHaveFaceTexture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Gfx\r\n"
  },
  {
    "path": "Code/Gfx/ModelAppearance.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       ModelAppearance.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  4/2/2000\r\n//****************************************************************************\r\n\r\n#ifndef __GFX_MODELAPPEARANCE_H\r\n#define __GFX_MODELAPPEARANCE_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object.h>\r\n\r\n#include <gel/scripting/struct.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\tclass CFaceTexture;\r\n\r\n// A CModelAppearance contains all the data associated with\r\n// generating a rendered model (NxModel).\r\n\t\t\t\r\nclass CModelAppearance : public Obj::CObject\r\n{\r\npublic:\r\n\tCModelAppearance();\r\n\tCModelAppearance( const CModelAppearance& rhs );\r\n\tCModelAppearance&\toperator=( const CModelAppearance& rhs );\r\n\tvirtual \t\t\t~CModelAppearance();\r\n\r\npublic:\r\n\tvirtual bool\t\tCallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\npublic:\r\n\t// Init: Clears it out to nothing\r\n\tbool\t\t\t\tInit();\r\n\r\n\t// Load: Appends a structure\r\n\tbool\t\t\t\tLoad( Script::CStruct* pStructure, bool resolve_randoms = true );\r\n\tbool\t\t\t\tLoad( uint32 structure_name, bool resolve_randoms = true );\r\n\r\npublic:\r\n\t// for network message building\r\n\t// (note that the face texture is not included in this buffer\r\n\t// because the buffer is too small...  face textures need to\r\n\t// be sent through a separate pathway)\r\n\tuint32\t\t\t\tWriteToBuffer(uint8* pBuffer, uint32 bufferSize, bool ignoreFaceData = false);\r\n\tuint8*\t\t\t\tReadFromBuffer(uint8* pBuffer);\r\n\r\npublic:\r\n\t// for debugging\r\n\tvoid\t\t\t\tPrintContents(const Script::CStruct* p_structure = 0);\r\n\r\npublic:\r\n\t// used by builder, to apply the desired appearance to a particular SkinModel\r\n\tScript::CStruct*\tGetActualDescStructure( uint32 partChecksum );\r\n\tScript::CStruct*\tGetVirtualDescStructure( uint32 partChecksum );\r\n\tScript::CStruct*\tGetStructure() { return &m_appearance; }\r\n\tGfx::CFaceTexture*\tGetFaceTexture();\r\n\tvoid\t\t\t\tCreateFaceTexture();\r\n\tvoid\t\t\t\tDestroyFaceTexture();\r\n\t\t\r\nprotected:\r\n\tvoid\t\t\t\tresolve_randomized_desc_ids();\r\n\tvoid\t\t\t\tset_part(uint32 partChecksum, uint32 descID, Script::CStruct* pParams);\r\n\tvoid\t\t\t\tclear_part(uint32 partChecksum);\r\n\tvoid\t\t\t\tset_checksum(uint32 fieldChecksum, uint32 valueChecksum);\r\n\r\nprotected:\r\n\tScript::CStruct\t\tm_appearance;\r\n\tGfx::CFaceTexture*\tmp_faceTexture;\r\n\t\r\npublic:\r\n\t// the following is needed because skaters created in net games \r\n\t// don't have a face texture during initial model building (the\r\n\t// face texture will eventually come in a later net packet),\r\n\t// but the model builder still needs to know if there will eventually\r\n\t// be a face texture so that it can load up the correct head geometry\r\n\tbool\t\t\t\tWillEventuallyHaveFaceTexture();\r\n\r\nprotected:\r\n\tbool\t\t\t\tm_willEventuallyHaveFaceTexture;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n#endif\t// __OBJECTS_MODELAPPEARANCE_H\r\n"
  },
  {
    "path": "Code/Gfx/ModelBuilder.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       ModelBuilder.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/16/2001\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/modelbuilder.h>\r\n\r\n#include <gfx/facetexture.h>\r\n#include <gfx/GfxUtils.h>\r\n#include <gfx/modelappearance.h>\r\n#include <gfx/Nx.h>\r\n#include <gfx/NxModel.h>\r\n#include <gfx/nxtexman.h>\r\n#include <gfx/nxtexture.h>\r\n#include <gfx/skeleton.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n// NOTES:\r\n\r\n// Given a CModelAppearance, the CModelBuilder generates the \r\n// appropriate Nx::CModel (creating its Nx::CGeoms, modulating\r\n// its color, replacing its textures, etc.)\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// some handy checksums\r\nconst uint32 vCHECKSUM_PART = 0xb6f08f39;\t\t\t\t\t\t\t// part\r\nconst uint32 vCHECKSUM_USE_DEFAULT_HSV = 0x97dbdde6;\t\t\t\t// use_default_hsv\r\nconst uint32 vCHECKSUM_HUE = 0x6e94f918;\t\t\t\t\t\t\t// h\r\nconst uint32 vCHECKSUM_SATURATION = 0xe4f130f4;\t\t\t\t\t\t// s\r\nconst uint32 vCHECKSUM_VALUE = 0x949bc47b;\t\t\t\t\t\t\t// v\r\nconst uint32 vCHECKSUM_USE_DEFAULT_SCALE = 0x5a96985d;\t\t\t\t// use_default_scale\r\nconst uint32 vCHECKSUM_X = 0x7323e97c;\t\t\t\t\t\t\t\t// x\r\nconst uint32 vCHECKSUM_Y = 0x0424d9ea;\t\t\t\t\t\t\t\t// y\r\nconst uint32 vCHECKSUM_Z = 0x9d2d8850;\t\t\t\t\t\t\t\t// z\r\nconst uint32 vCHECKSUM_REPLACE = 0xf362dbba;\t\t\t\t\t\t// replace\r\nconst uint32 vCHECKSUM_WITH = 0x676f1df1;\t\t\t\t\t\t\t// with\r\nconst uint32 vCHECKSUM_IN = 0xa01371b1;\t\t\t\t\t\t\t\t// in\r\nconst uint32 vCHECKSUM_REPLACE1 = 0x7a993873;\t\t\t\t\t\t// replace1\r\nconst uint32 vCHECKSUM_WITH1 = 0x9b03adad;\t\t\t\t\t\t\t// with1\r\nconst uint32 vCHECKSUM_IN1 = 0xed189051;\t\t\t\t\t\t\t// in1\r\nconst uint32 vCHECKSUM_REPLACE2 = 0xe39069c9;\t\t\t\t\t\t// replace2\r\nconst uint32 vCHECKSUM_WITH2 = 0x020afc17;\t\t\t\t\t\t\t// with2\r\nconst uint32 vCHECKSUM_IN2 = 0x7411c1eb;\t\t\t\t\t\t\t// in2\r\nconst uint32 vCHECKSUM_REPLACE3 = 0x9497595f;\t\t\t\t\t\t// replace3\r\nconst uint32 vCHECKSUM_WITH3 = 0x750dcc81;\t\t\t\t\t\t\t// with3\r\nconst uint32 vCHECKSUM_IN3 = 0x0316f17d;\t\t\t\t\t\t\t// in3\r\nconst uint32 vCHECKSUM_REPLACE4 = 0x0af3ccfc;\t\t\t\t\t\t// replace4\r\nconst uint32 vCHECKSUM_WITH4 = 0xeb695922;\t\t\t\t\t\t\t// with4\r\nconst uint32 vCHECKSUM_IN4 = 0x9d7264de;\t\t\t\t\t\t\t// in4\r\nconst uint32 vCHECKSUM_REPLACE5 = 0x7df4fc6a;\t\t\t\t\t\t// replace5\r\nconst uint32 vCHECKSUM_WITH5 = 0x9c6e69b4;\t\t\t\t\t\t\t// with5\r\nconst uint32 vCHECKSUM_IN5 = 0xea755448;\t\t\t\t\t\t\t// in5\r\nconst uint32 vCHECKSUM_REPLACE6 = 0xe4fdadd0;\t\t\t\t\t\t// replace6\r\nconst uint32 vCHECKSUM_WITH6 = 0x0567380e;\t\t\t\t\t\t\t// with6\r\nconst uint32 vCHECKSUM_IN6 = 0x737c05f2;\t\t\t\t\t\t\t// in6\r\nconst uint32 vCHECKSUM_MESH = 0x1e90c5a9;\t\t\t\t\t\t\t// mesh\r\nconst uint32 vCHECKSUM_MESH1 = 0xfeca8bb3;\t\t\t\t\t\t\t// mesh1\r\nconst uint32 vCHECKSUM_MESH2 = 0x67c3da09;\t\t\t\t\t\t\t// mesh2\r\nconst uint32 vCHECKSUM_MESH3 = 0x10c4ea9f;\t\t\t\t\t\t\t// mesh3\r\nconst uint32 vCHECKSUM_MESH4 = 0x8ea07f3c;\t\t\t\t\t\t\t// mesh4\r\nconst uint32 vCHECKSUM_REMOVE = 0x977fe2cf;\t\t\t\t\t\t\t// remove\r\nconst uint32 vCHECKSUM_TARGET = 0xb990d003;\t\t\t\t\t\t\t// target\r\nconst uint32 vCHECKSUM_BODY_SHAPE = 0x812684ef;\t\t\t\t\t\t// body_shape\r\nconst uint32 vCHECKSUM_APPLY_NORMAL_MODE = 0x2700a288;\t\t\t\t// apply_normal_mode\r\nconst uint32 vCHECKSUM_BODY = 0x2457f44d;\t\t\t\t\t\t\t// body\r\nconst uint32 vCHECKSUM_NO_SCALING_ALLOWED = 0xb25e39fd;\t\t\t\t// no_scaling_allowed\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nNx::CModel* CModelBuilder::mp_model = NULL;\r\nGfx::CSkeleton* CModelBuilder::mp_skeleton = NULL;\r\nCModelAppearance* CModelBuilder::mp_appearance = NULL;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModelBuilder::CModelBuilder( bool useAssetManager, uint32 texDictOffset )\r\n{\r\n\t// parameters that will be used for the duration of\r\n\t// the model-building:\r\n\r\n\t// whether the asset manager should be used\r\n\t// (it should NOT, for skaters and other\r\n\t// things that do texture replacement/poly\r\n\t// removal)\r\n\tm_useAssetManager = useAssetManager;\r\n\r\n\t// used for unique-ifying the texture dictionaries\r\n\t// when you've got multiple skaters\r\n\tm_texDictOffset = texDictOffset;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModelBuilder::BuildModel( CModelAppearance* pAppearance, Nx::CModel* pModel, Gfx::CSkeleton* pSkeleton, uint32 buildScriptName )\r\n{\r\n//\tTmr::Time baseTime = Tmr::ElapsedTime(0);\r\n\r\n\tDbg_Assert( pAppearance );\r\n\tDbg_Assert( pModel );\r\n\r\n\t// don't destroy the existing model...\r\n\t// leave it up to the particular buildscript\r\n//\tpModel->ClearGeoms();\r\n\r\n\tDbg_MsgAssert( !mp_model, ( \"Static temporary model already exists\" ) );\r\n\tmp_model = pModel;\r\n\t\r\n\tDbg_MsgAssert( !mp_skeleton, ( \"Static skeleton already exists\" ) );\r\n\tmp_skeleton = pSkeleton;\r\n\t\r\n\tDbg_MsgAssert( !mp_appearance, ( \"Static temporary appearance already exists\" ) );\r\n\tmp_appearance = new CModelAppearance;\r\n\t\r\n\t// clear it out from the previous use\r\n\tmp_appearance->Init();\r\n\r\n\t// GJ 9/8/03:  since it's a temporary variable, we don't want \r\n\t// it on the skater geom heap (which would fragment it on the\r\n\t// PS2 with 17K worth of face texture data)\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n  \t// copy over the desired appearance\r\n\t// (must make a copy, so that we can\r\n\t// make changes to it)\r\n\t*mp_appearance = *pAppearance;\r\n\t\r\n   \tMem::Manager::sHandle().PopContext();\r\n\r\n\t// this script is responsible for looping\r\n\t// through all the supported partChecksums\r\n\t// and running all the supported operations\r\n\t// on them.  Which partChecksums and operations\r\n\t// are \"supported\" should be completely in\r\n\t// script.\r\n//    Dbg_Message( \"BuildModel - %s\", Script::FindChecksumName(buildScriptName) );\r\n    Script::RunScript( buildScriptName, NULL, this );\r\n    \r\n\tmp_model = NULL;\r\n\tmp_skeleton = NULL;\r\n\r\n\tdelete mp_appearance;\r\n\tmp_appearance = NULL;\r\n\r\n//\tDbg_Message( \"BuildModel took %d ms\", Tmr::ElapsedTime( baseTime ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::CallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( checksum )\r\n\t{\r\n\t\tcase 0x30e2951d:\t\t// DebugPrintAppearance\r\n\t\t{\r\n\t\t\t// print out the appearance to make sure\r\n\t\t\t// it's coming through correctly in net games\r\n\t\t\tmp_appearance->PrintContents();\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0x53da94f1:\t\t// ModelAddGeom\r\n\t\t{\r\n\t\t\tuint32 partChecksum;\r\n\t\t\tpParams->GetChecksum( vCHECKSUM_PART, &partChecksum, Script::ASSERT );\r\n\t\t\tmodel_add_geom(partChecksum);\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0x681a03af:\t\t// ModelHideGeom\r\n\t\t{\r\n\t\t\tuint32 partChecksum;\r\n\t\t\tpParams->GetChecksum( vCHECKSUM_PART, &partChecksum, Script::ASSERT );\r\n\t\t\r\n\t\t\tint hidden;\r\n\t\t\tpParams->GetInteger( NONAME, &hidden, Script::ASSERT );\r\n\r\n\t\t\tmodel_hide_geom(partChecksum, hidden);\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0xaee6e915:\t\t// GeomModulateColor\r\n\t\t{\r\n\t\t\tgeom_modulate_color( pParams );\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0x18924da1:\t\t// GeomSetUVOffset\r\n\t\t{\r\n\t\t\tuint32 partChecksum;\r\n\t\t\tpParams->GetChecksum( vCHECKSUM_PART, &partChecksum, Script::ASSERT );\r\n\t\t\t\r\n\t\t\tuint32 material;\r\n\t\t\tpParams->GetChecksum( CRCD(0x83418a6a,\"material\"), &material, Script::ASSERT );\r\n\r\n\t\t\tint pass;\r\n\t\t\tpParams->GetInteger( CRCD(0x318f2bdb,\"pass\"), &pass, Script::ASSERT );\r\n\r\n\t\t\tgeom_set_uv_offset(partChecksum, material, pass);\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0x3bf41299:\t\t// GeomAllocateUVMatrixParams\r\n\t\t{\r\n\t\t\tuint32 material;\r\n\t\t\tpParams->GetChecksum( CRCD(0x83418a6a,\"material\"), &material, Script::ASSERT );\r\n\r\n\t\t\tint pass;\r\n\t\t\tpParams->GetInteger( CRCD(0x318f2bdb,\"pass\"), &pass, Script::ASSERT );\r\n\r\n\t\t\tgeom_allocate_uv_matrix_params(material, pass);\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0xaa42a104:\t\t// GeomReplaceTexture\r\n\t\t{\r\n\t\t\tuint32 partChecksum;\r\n\t\t\tpParams->GetChecksum( vCHECKSUM_PART, &partChecksum, Script::ASSERT );\r\n\t\t\tgeom_replace_texture(partChecksum);\r\n\t\t}\r\n\t\treturn true;\r\n\t\t\r\n\t\tcase 0x9041e901:\t\t// ModelRemovePolys\r\n\t\t{\r\n\t\t\tmodel_remove_polys();\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0x50f1285b:\t\t// ModelApplyObjectScale\r\n\t\t{\r\n\t\t\tScript::CStruct* pBodyShapeStructure = NULL;\r\n\t\t\tif ( pParams->GetStructure( vCHECKSUM_BODY_SHAPE, &pBodyShapeStructure, false ) )\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec = mp_model->GetScale();\r\n\t\t\t\t\r\n\t\t\t\tMth::Vector theScale( 1.0f, 1.0f, 1.0f, 1.0f );\r\n\t\t\t\tif ( Gfx::GetScaleFromParams( &theScale, pBodyShapeStructure ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tvec[X] *= theScale[X];\r\n\t\t\t\t\tvec[Y] *= theScale[Y];\r\n\t\t\t\t\tvec[Z] *= theScale[Z];\r\n\t\t\t\t\tvec[W] *= theScale[W];\r\n\r\n\t\t\t\t\t// if the body shape has a scale\r\n\t\t\t\t\tmp_model->SetScale( vec );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmodel_apply_object_scale();\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t\t\r\n\t\tcase 0x21aec583:\t\t// ModelApplyBoneScale\r\n\t\t{\r\n\t\t\tif ( pParams->ContainsComponentNamed( CRCD(0x3f5f5bc2,\"bone_scaling\") ) )\r\n\t\t\t{\r\n\t\t\t\tuint32 partChecksum;\r\n\t\t\t\tpParams->GetChecksum( vCHECKSUM_PART, &partChecksum, Script::ASSERT );\r\n\t\t\t\tmodel_apply_bone_scale( partChecksum );\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t\t\r\n\t\tcase 0xc0bc8271:\t\t// ModelApplyBodyShape\r\n\t\t{\r\n\t\t\tScript::CStruct* pBodyShapeStructure = NULL;\r\n\t\t\tif ( pParams->GetStructure( vCHECKSUM_BODY_SHAPE, &pBodyShapeStructure, false ) )\r\n\t\t\t{\r\n\t\t\t\t// GJ:  PATCH TO FIX STEVE CABALLERO'S INCORRECT WEIGHTING IN BIGHEAD MODE\r\n\t\t\t\tScript::CStruct* pActualStruct = mp_appearance->GetActualDescStructure( CRCD(0x650fab6d,\"skater_m_head\") );\r\n\t\t\t\tif ( pActualStruct && pParams->ContainsFlag( CRCD(0x3c4d849d,\"is_bighead_cheat\") ) ) \r\n\t\t\t\t{\r\n\t\t\t\t   pActualStruct->GetStructure( CRCD(0x1ade0dd8,\"bighead_scale_info\"), &pBodyShapeStructure );\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// if a body shape was explicitly specified\r\n\t\t\t\t// (for kid and gorilla modes)\r\n\t\t\t\tif ( mp_skeleton )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn mp_skeleton->ApplyBoneScale( pBodyShapeStructure );\r\n\t\t\t\t}\r\n\t        }\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmodel_apply_body_shape();\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0x73ab02bc:\t\t// ModelApplyFaceTexture\r\n\t\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\t\tbool success = true;\r\n\r\n\t\t\tGfx::CFaceTexture* pFaceTexture = mp_appearance->GetFaceTexture() ;\r\n\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\t\t\tif ( pFaceTexture && pFaceTexture->IsValid() )\r\n\t\t\t{\r\n\t\t\t\tif ( mp_model )\r\n\t\t\t\t{\r\n\t\t\t\t\tconst char* pSrcTexture;\r\n\t\t\t\t\tpParams->GetText( CRCD(0x9fbbdb72,\"src\"), &pSrcTexture, Script::ASSERT );\r\n\r\n\t\t\t\t\t// by default, it searches globally in the model for the correct texture\r\n\t\t\t\t\tuint32 partChecksumToReplace = Nx::CModel::vREPLACE_GLOBALLY;\r\n\t\t\t\t\tpParams->GetChecksum( CRCD(0xa01371b1,\"in\"), &partChecksumToReplace, Script::NO_ASSERT );\r\n                    \r\n\t\t\t\t\tsuccess = mp_model->ApplyFaceTexture( pFaceTexture, pSrcTexture, partChecksumToReplace );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn success;\r\n#else\r\n\t\t\t// X-box and NGC don't have to implement these\r\n\t\t\t// because they don't do face textures...\r\n\t\t\treturn true;\r\n#endif\r\n\t\t}\r\n\r\n\t\tcase 0x6516b484:\t\t// AppearanceAllowScalingCheat\r\n\t\t{\r\n\t\t\tScript::CStruct* pActualStruct = mp_appearance->GetActualDescStructure( vCHECKSUM_BODY );\r\n\t\t\tif ( pActualStruct ) \r\n\t\t\t{\r\n\t\t\t\treturn !pActualStruct->ContainsFlag( vCHECKSUM_NO_SCALING_ALLOWED );\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0xcdeea636:\t\t// ModelResetScale\r\n\t\t{\r\n\t\t\tmodel_reset_scale();\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0xbff957a9:\t\t// ModelClearGeom\r\n\t\t{\r\n\t\t\tuint32 partChecksum;\r\n\t\t\tpParams->GetChecksum( vCHECKSUM_PART, &partChecksum, Script::ASSERT );\r\n\t\t\tmodel_clear_geom( partChecksum );\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0x0ecf0248:\t\t// ModelClearAllGeoms\r\n\t\t{\r\n\t\t\tmodel_clear_all_geoms();\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0xb1c39a54:\t\t// ModelRunScript\r\n\t\t{\r\n\t\t\tuint32 partChecksum;\r\n\t\t\tpParams->GetChecksum( vCHECKSUM_PART, &partChecksum, Script::ASSERT );\r\n\t\t\t\r\n\t\t\tuint32 targetChecksum;\r\n\t\t\tpParams->GetChecksum( vCHECKSUM_TARGET, &targetChecksum, Script::ASSERT );\r\n\r\n\t\t\t// runs an embedded script\r\n\t\t\tmodel_run_script(partChecksum, targetChecksum);\r\n\t\t}\r\n\t\treturn true;\r\n\r\n\t\tcase 0xcefe8478:\t\t// ModelFinalize\r\n\t\t{\r\n\t\t\tmodel_finalize();\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn Obj::CObject::CallMemberFunction( checksum, pParams, pScript );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::model_hide_geom( uint32 partChecksum, bool hidden )\r\n{\r\n\tDbg_Assert( mp_model );\r\n\tDbg_Assert( mp_appearance );\r\n\r\n/*\r\n\tif ( !Script::GetArray( partChecksum, Script::NO_ASSERT ) )\r\n\t{\r\n\t\t// no array involved\r\n\t\treturn false;\r\n\t}\r\n*/\r\n\r\n\tmp_model->HideGeom( partChecksum, hidden );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::model_add_geom( uint32 partChecksum )\r\n{\r\n\tDbg_Assert( mp_model );\r\n\tDbg_Assert( mp_appearance );\r\n\r\n\tScript::CStruct* pActualStruct = mp_appearance->GetActualDescStructure( partChecksum );\r\n\tif ( pActualStruct ) \r\n\t{\r\n\t\tint supports_multiple_colors = 0;\r\n\t\tpActualStruct->GetInteger( CRCD(0x92b43e79,\"multicolor\"), &supports_multiple_colors, Script::NO_ASSERT );\r\n\r\n#ifdef __PLAT_NGPS__\r\n\t\tGfx::CFaceTexture* pFaceTexture = mp_appearance->GetFaceTexture() ;\r\n\r\n\t\t// GJ:  THPS5 KLUDGE\r\n\t\t// WillEventuallyHaveFaceTexture is a flag used in net games...\r\n\t\t// this is needed because there is no face texture pointer\r\n\t\t// in net games (because it's handled in a separate net packet)...\r\n\r\n\t\tif ( ( pFaceTexture && pFaceTexture->IsValid() ) || ( mp_appearance->WillEventuallyHaveFaceTexture() ) )\r\n\t\t{\r\n\t\t\t// if the special parameter doesn't exist, then\r\n\t\t\t// fall through to the normal mesh-loading code...\r\n\t\t\t\r\n\t\t\tconst char* pMeshName;\r\n\t\t\tif ( pActualStruct->GetString( CRCD(0xc9aed80f,\"mesh_if_facemapped\"), &pMeshName, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tmp_model->AddGeom( pMeshName, partChecksum, m_useAssetManager, m_texDictOffset, false, supports_multiple_colors );\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n#endif\r\n\t\t{\r\n\t\t\tconst char* pMeshName;\r\n\t\t\tif ( pActualStruct->GetString( vCHECKSUM_MESH, &pMeshName, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tmp_model->AddGeom( pMeshName, partChecksum, m_useAssetManager, m_texDictOffset, false, supports_multiple_colors );\r\n\t\t\t}\r\n\t\t\tif ( pActualStruct->GetString( vCHECKSUM_MESH1, &pMeshName, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tmp_model->AddGeom( pMeshName, partChecksum, m_useAssetManager, m_texDictOffset, false, supports_multiple_colors );\r\n\t\t\t}\r\n\t\t\tif ( pActualStruct->GetString( vCHECKSUM_MESH2, &pMeshName, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tmp_model->AddGeom( pMeshName, partChecksum, m_useAssetManager, m_texDictOffset, false, supports_multiple_colors );\r\n\t\t\t}\r\n\t\t\tif ( pActualStruct->GetString( vCHECKSUM_MESH3, &pMeshName, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tmp_model->AddGeom( pMeshName, partChecksum, m_useAssetManager, m_texDictOffset, false, supports_multiple_colors );\r\n\t\t\t}\r\n\t\t\tif ( pActualStruct->GetString( vCHECKSUM_MESH4, &pMeshName, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tmp_model->AddGeom( pMeshName, partChecksum, m_useAssetManager, m_texDictOffset, false, supports_multiple_colors );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::model_clear_geom( uint32 partChecksum )\r\n{\r\n\tDbg_Assert( mp_model );\r\n\tDbg_Assert( mp_appearance );\r\n\r\n\t// it's destructive, so make sure you're not \r\n\t// doing it to the \"real\" appearance...\r\n\tmp_appearance->GetStructure()->RemoveComponent( partChecksum );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::model_clear_all_geoms( void )\r\n{\r\n\tDbg_Assert( mp_model );\r\n\tDbg_Assert( mp_appearance );\r\n\r\n\tmp_model->ClearGeoms();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::model_reset_scale()\r\n{\r\n\tDbg_Assert( mp_model );\r\n\tDbg_Assert( mp_skeleton );\r\n\tDbg_Assert( mp_appearance );\r\n\r\n\tMth::Vector theBoneScaleVector( 1.0f, 1.0f, 1.0f, 1.0f );\r\n\tmp_model->SetScale( theBoneScaleVector );\r\n\t\r\n\tif ( mp_skeleton )\r\n\t{\r\n\t\tmp_skeleton->ResetScale();\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::model_apply_body_shape()\r\n{\r\n\tDbg_Assert( mp_model );\r\n\tDbg_Assert( mp_skeleton );\r\n\tDbg_Assert( mp_appearance );\r\n\r\n\tScript::CStruct* pStructure = mp_appearance->GetStructure();\r\n\tDbg_Assert( pStructure );\r\n\t\r\n\tScript::CStruct* pBodyShapeStructure = NULL;\r\n\tif ( pStructure->GetStructure( vCHECKSUM_BODY_SHAPE, &pBodyShapeStructure, false ) )\r\n\t{\r\n\t\treturn mp_skeleton->ApplyBoneScale( pBodyShapeStructure );\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::model_apply_bone_scale( uint32 partChecksum )\r\n{\r\n\tDbg_Assert( mp_model );\r\n\tDbg_Assert( mp_skeleton );\r\n\tDbg_Assert( mp_appearance );\r\n\t\r\n\tScript::CStruct* pVirtualStruct = mp_appearance->GetVirtualDescStructure( partChecksum );\r\n\tif ( pVirtualStruct ) \r\n\t{\r\n\t\tif ( !pVirtualStruct->ContainsComponentNamed( vCHECKSUM_USE_DEFAULT_SCALE ) )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tint use_default_scale;\r\n\t\tpVirtualStruct->GetInteger( vCHECKSUM_USE_DEFAULT_SCALE, &use_default_scale );\r\n\t\r\n\t\tif ( use_default_scale )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tint x, y, z;\r\n\t\tif ( pVirtualStruct->GetInteger( vCHECKSUM_X, &x, false )\r\n\t\t\t && pVirtualStruct->GetInteger( vCHECKSUM_Y, &y, false )\r\n\t\t\t && pVirtualStruct->GetInteger( vCHECKSUM_Z, &z, false ) )\r\n\t\t{\r\n\t\t\tScript::CArray* pBoneGroupArray = Script::GetArray( partChecksum, Script::NO_ASSERT );\r\n\t\t\tif ( pBoneGroupArray )\r\n\t\t\t{\r\n\t\t\t\tMth::Vector theBoneScaleVector;\r\n//\t\t\t\ttheBoneScaleVector[X] = (float)x / 100.0f;\r\n//\t\t\t\ttheBoneScaleVector[Y] = (float)y / 100.0f;\r\n//\t\t\t\ttheBoneScaleVector[Z] = (float)z / 100.0f;\r\n\t\t\t\ttheBoneScaleVector[W] = 1.0f;\r\n\r\n\t\t\t\tfor ( uint32 i = 0; i < pBoneGroupArray->GetSize(); i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 boneChecksum = pBoneGroupArray->GetChecksum(i);\r\n\r\n\t\t\t\t\t// get the existing scale...\r\n\t\t\t\t\tmp_skeleton->GetBoneScale( boneChecksum, &theBoneScaleVector );\r\n\r\n\t\t\t\t\t// then combine it with the new desired bone scale...\r\n\t\t\t\t\ttheBoneScaleVector[X] *= ( (float)x / 100.0f );\r\n\t\t\t\t\ttheBoneScaleVector[Y] *= ( (float)y / 100.0f );\r\n\t\t\t\t\ttheBoneScaleVector[Z] *= ( (float)z / 100.0f );\r\n\r\n\t\t\t\t\tbool isLocalScale = true;\r\n\r\n\t\t\t\t\t// GJ:  The shoulder bones are handled slightly differently\r\n\t\t\t\t\t// so that the female skaters aren't so broad-shouldered.\r\n\t\t\t\t\tScript::CArray* pShoulderScalingArray = Script::GetArray( CRCD(0x20d9ac2f,\"nonlocal_bones\"), Script::NO_ASSERT );\r\n\t\t\t\t\tif ( pShoulderScalingArray )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfor ( uint32 i = 0; i < pShoulderScalingArray->GetSize(); i++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( pShoulderScalingArray->GetChecksum(i) == boneChecksum )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tisLocalScale = false;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tmp_skeleton->SetBoneScale( boneChecksum, theBoneScaleVector, isLocalScale );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::model_apply_object_scale()\r\n{\r\n\tDbg_Assert( mp_model );\r\n\tDbg_Assert( mp_appearance );\r\n\r\n\tMth::Vector theScale( 1.0f, 1.0f, 1.0f );\r\n\tif ( Gfx::GetScaleFromParams( &theScale, mp_appearance->GetStructure() ) )\r\n\t{\r\n\t\tmp_model->SetScale( theScale );\r\n\t\treturn true;\r\n\t}\r\n\r\n\tScript::CStruct* pStructure = mp_appearance->GetStructure();\r\n\tDbg_Assert( pStructure );\r\n\t\r\n\t// sometimes the object scale can be found in the bone params\r\n\tScript::CStruct* pBodyShapeStructure = NULL;\r\n\tif ( pStructure->GetStructure( vCHECKSUM_BODY_SHAPE, &pBodyShapeStructure, false ) )\r\n\t{\r\n\t\tif ( Gfx::GetScaleFromParams( &theScale, pBodyShapeStructure ) )\r\n\t\t{\r\n\t\t\tmp_model->SetScale( theScale );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tScript::CStruct* pVirtualStruct = mp_appearance->GetVirtualDescStructure( CRCD(0x8b314358,\"object_scaling\") );\r\n\tif ( pVirtualStruct ) \r\n\t{\r\n\t\tif ( !pVirtualStruct->ContainsComponentNamed( vCHECKSUM_USE_DEFAULT_SCALE ) )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}  \t\r\n\r\n\t\tint use_default_scale;\r\n\t\tpVirtualStruct->GetInteger( vCHECKSUM_USE_DEFAULT_SCALE, &use_default_scale );\r\n\t\t\r\n\t\tif ( use_default_scale )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tint x, y, z;\r\n\t\tif ( pVirtualStruct->GetInteger( vCHECKSUM_X, &x, false )\r\n\t\t\t && pVirtualStruct->GetInteger( vCHECKSUM_Y, &y, false )\r\n\t\t\t && pVirtualStruct->GetInteger( vCHECKSUM_Z, &z, false ) )\r\n\t\t{\r\n\t\t\tMth::Vector theBoneScaleVector;\r\n\t\t\ttheBoneScaleVector[X] = (float)x / 100.0f;\r\n\t\t\ttheBoneScaleVector[Y] = (float)y / 100.0f;\r\n\t\t\ttheBoneScaleVector[Z] = (float)z / 100.0f;\r\n\t\t\ttheBoneScaleVector[W] = 1.0f;\r\n\r\n\t\t\tmp_model->SetScale( theBoneScaleVector );\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::model_remove_polys()\r\n{\r\n\tDbg_Assert( mp_model );\r\n\tDbg_Assert( mp_appearance );\r\n\r\n\tmp_model->RemovePolys();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::geom_modulate_color( Script::CStruct* pParams )\r\n{\r\n\tuint32 partChecksum;\r\n\tpParams->GetChecksum( vCHECKSUM_PART, &partChecksum, Script::ASSERT );\r\n\t\t\t\r\n\tDbg_Assert( mp_model );\r\n\tDbg_Assert( mp_appearance );\r\n\r\n\tScript::CStruct* pVirtualStruct = mp_appearance->GetVirtualDescStructure( partChecksum );\r\n\tif ( pVirtualStruct ) \r\n\t{\r\n\t\tint use_default_hsv = 0;\r\n\r\n\t\tif ( !pVirtualStruct->ContainsComponentNamed( vCHECKSUM_USE_DEFAULT_HSV ) )\r\n\t\t{\r\n\t\t\tuse_default_hsv = 1;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpVirtualStruct->GetInteger( vCHECKSUM_USE_DEFAULT_HSV, &use_default_hsv );\r\n\t\t}\r\n\t\r\n\t\tif ( use_default_hsv )\r\n\t\t{\r\n\t\t\tScript::CStruct* pActualStruct = mp_appearance->GetActualDescStructure( partChecksum );\r\n\t\t\tint h, s, v;\r\n\t\t\tif ( pActualStruct\r\n\t\t\t\t && pActualStruct->GetInteger( CRCD(0xc6cc7f7f,\"default_h\"), &h, Script::NO_ASSERT )\r\n\t\t\t\t && pActualStruct->GetInteger( CRCD(0x4ca9b693,\"default_s\"), &s, Script::NO_ASSERT )\r\n\t\t\t\t && pActualStruct->GetInteger( CRCD(0x3cc3421c,\"default_v\"), &v, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\t// set the default color that's specified in the actual structure\r\n\t\t\t\tmp_model->SetColor( pParams, h, (float)s / 100.0f, (float)v / 100.0f );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// otherwise, clear out the color   \r\n\t\t\t\tmp_model->ClearColor( pParams );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tint h, s, v;\r\n\t\t\tif ( pVirtualStruct->GetInteger( vCHECKSUM_HUE, &h, false )\r\n\t\t\t\t && pVirtualStruct->GetInteger( vCHECKSUM_SATURATION, &s, false )\r\n\t\t\t\t && pVirtualStruct->GetInteger( vCHECKSUM_VALUE, &v, false ) )\r\n\t\t\t{\r\n\t\t\t\t// set the non-default color that's specified in the virtual structure\r\n\t\t\t\tmp_model->SetColor( pParams, h, (float)s / 100.0f, (float)v / 100.0f );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::geom_allocate_uv_matrix_params( uint32 matChecksum, int pass )\r\n{\r\n\tDbg_Assert(mp_model);\r\n\tmp_model->AllocateUVMatrixParams(matChecksum, pass);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::geom_set_uv_offset( uint32 partChecksum, uint32 matChecksum, int pass )\r\n{\r\n#if 0\r\n// debugging\r\n\tif ( mp_appearance->GetActualDescStructure( Script::GenerateCRC(\"skater_m_head\") ) )\r\n\t{\r\n\t\tmp_model->SetMaterialColor(matChecksum, pass, Image::RGBA(0,0,128,128));\r\n\t}\r\n#endif\t\r\n\tScript::CStruct* pVirtualStruct = mp_appearance->GetVirtualDescStructure( partChecksum );\r\n\tif ( pVirtualStruct ) \r\n\t{\r\n\t\tif ( !pVirtualStruct->ContainsComponentNamed( CRCD(0x8602f6ee,\"use_default_uv\") ) )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\r\n\t\tint use_default_uv;\r\n\t\tpVirtualStruct->GetInteger( CRCD(0x8602f6ee,\"use_default_uv\"), &use_default_uv );\r\n\t\r\n\t\tif ( use_default_uv )\r\n\t\t{\r\n// \t\t\t(do nothing;  keep the default UVs)\r\n//\t\t\t(assumes that we're starting from an unmodified model)\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tfloat u_offset;\r\n        pVirtualStruct->GetFloat(CRCD(0xcf6aa087,\"uv_u\"), &u_offset, Script::ASSERT);\r\n\t\t\r\n\t\tfloat v_offset;\r\n\t\tpVirtualStruct->GetFloat(CRCD(0x5663f13d,\"uv_v\"), &v_offset, Script::ASSERT);\r\n\t\t\r\n\t\tfloat uv_scale;\r\n\t\tpVirtualStruct->GetFloat(CRCD(0x266932c8,\"uv_scale\"), &uv_scale, Script::ASSERT);\r\n\t\t\r\n\t\tfloat uv_rot;\r\n\t\tpVirtualStruct->GetFloat(CRCD(0x1256b6c6,\"uv_rot\"), &uv_rot, Script::ASSERT);\r\n\t\t\r\n\t\t// GJ:  seems if you want a bigger image, you need smaller UV values...\r\n\t\t// is that right?\r\n\r\n\t\tMth::Matrix theMat;\r\n\t\ttheMat.Ident();\r\n\t\ttheMat.Translate( Mth::Vector( -0.5f, -0.5f, 0.0f, 0.0f ) );\r\n\t\ttheMat.Scale( Mth::Vector(uv_scale / 100.0f, uv_scale / 100.0f, uv_scale / 100.0f, 1.0f ) );\r\n\t\ttheMat.Rotate( Mth::Vector( 0.0f, 0.0f, 1.0f, 1.0f ), Mth::DegToRad(uv_rot) );  // in degrees\r\n\t\ttheMat.Translate( Mth::Vector( 0.5f, 0.5f, 0.0f, 0.0f ) );\r\n\t\t\r\n\t\ttheMat.TranslateLocal( Mth::Vector( u_offset / 100.0f, v_offset / 100.0f, 0.0f, 0.0f ) );\r\n\t\t\r\n\t\tDbg_Assert(mp_model);\r\n\t\tmp_model->SetUVMatrix(matChecksum, pass, theMat);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::geom_replace_texture( uint32 partChecksum )\r\n{\r\n\tDbg_Assert( mp_model );\r\n\tDbg_Assert( mp_appearance );\r\n\r\n\tbool success = false;\r\n\r\n/*\r\n\tif ( !Script::GetArray( partChecksum, Script::NO_ASSERT ) )\r\n\t{\r\n\t\t// no array involved\r\n\t\treturn false;\r\n\t}\r\n*/\r\n\r\n\tScript::CStruct* pActualStruct = mp_appearance->GetActualDescStructure( partChecksum );\r\n\tif ( pActualStruct ) \r\n\t{\r\n\t\tconst char* pSrcTexture;\r\n\t\tconst char* pDestTexture;\r\n\t\t\r\n\t\tif ( pActualStruct->GetText( vCHECKSUM_REPLACE, &pSrcTexture, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tpActualStruct->GetText( vCHECKSUM_WITH, &pDestTexture, Script::ASSERT );\r\n\r\n\t\t\tuint32 partChecksumToReplace = partChecksum;\r\n\t\t\tpActualStruct->GetChecksum( vCHECKSUM_IN, &partChecksumToReplace, Script::NO_ASSERT );\r\n\t\t\tsuccess = mp_model->ReplaceTexture( partChecksumToReplace, pSrcTexture, pDestTexture );\r\n\t\t}\r\n\t\tif ( pActualStruct->GetText( vCHECKSUM_REPLACE1, &pSrcTexture, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tpActualStruct->GetText( vCHECKSUM_WITH1, &pDestTexture, Script::ASSERT );\r\n\r\n\t\t\tuint32 partChecksumToReplace = partChecksum;\r\n\t\t\tpActualStruct->GetChecksum( vCHECKSUM_IN1, &partChecksumToReplace, Script::NO_ASSERT );\r\n\t\t\tsuccess = mp_model->ReplaceTexture( partChecksumToReplace, pSrcTexture, pDestTexture );\r\n\t\t}\r\n\t\tif ( pActualStruct->GetText( vCHECKSUM_REPLACE2, &pSrcTexture, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tpActualStruct->GetText( vCHECKSUM_WITH2, &pDestTexture, Script::ASSERT );\r\n\r\n\t\t\tuint32 partChecksumToReplace = partChecksum;\r\n\t\t\tpActualStruct->GetChecksum( vCHECKSUM_IN2, &partChecksumToReplace, Script::NO_ASSERT );\r\n\t\t\tsuccess = mp_model->ReplaceTexture( partChecksumToReplace, pSrcTexture, pDestTexture );\r\n\t\t}\r\n\t\tif ( pActualStruct->GetText( vCHECKSUM_REPLACE3, &pSrcTexture, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tpActualStruct->GetText( vCHECKSUM_WITH3, &pDestTexture, Script::ASSERT );\r\n\r\n\t\t\tuint32 partChecksumToReplace = partChecksum;\r\n\t\t\tpActualStruct->GetChecksum( vCHECKSUM_IN3, &partChecksumToReplace, Script::NO_ASSERT );\r\n\t\t\tsuccess = mp_model->ReplaceTexture( partChecksumToReplace, pSrcTexture, pDestTexture );\r\n\t\t}\r\n\t\tif ( pActualStruct->GetText( vCHECKSUM_REPLACE4, &pSrcTexture, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tpActualStruct->GetText( vCHECKSUM_WITH4, &pDestTexture, Script::ASSERT );\r\n\r\n\t\t\tuint32 partChecksumToReplace = partChecksum;\r\n\t\t\tpActualStruct->GetChecksum( vCHECKSUM_IN4, &partChecksumToReplace, Script::NO_ASSERT );\r\n\t\t\tsuccess = mp_model->ReplaceTexture( partChecksumToReplace, pSrcTexture, pDestTexture );\r\n\t\t}\r\n\t\tif ( pActualStruct->GetText( vCHECKSUM_REPLACE5, &pSrcTexture, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tpActualStruct->GetText( vCHECKSUM_WITH5, &pDestTexture, Script::ASSERT );\r\n\r\n\t\t\tuint32 partChecksumToReplace = partChecksum;\r\n\t\t\tpActualStruct->GetChecksum( vCHECKSUM_IN5, &partChecksumToReplace, Script::NO_ASSERT );\r\n\t\t\tsuccess = mp_model->ReplaceTexture( partChecksumToReplace, pSrcTexture, pDestTexture );\r\n\t\t}\r\n\t\tif ( pActualStruct->GetText( vCHECKSUM_REPLACE6, &pSrcTexture, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tpActualStruct->GetText( vCHECKSUM_WITH6, &pDestTexture, Script::ASSERT );\r\n\r\n\t\t\tuint32 partChecksumToReplace = partChecksum;\r\n\t\t\tpActualStruct->GetChecksum( vCHECKSUM_IN6, &partChecksumToReplace, Script::NO_ASSERT );\r\n\t\t\tsuccess = mp_model->ReplaceTexture( partChecksumToReplace, pSrcTexture, pDestTexture );\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::model_finalize()\r\n{\r\n\tDbg_Assert( mp_model );\r\n\tDbg_Assert( mp_appearance );\r\n\r\n\tmp_model->Finalize();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelBuilder::model_run_script( uint32 partChecksum, uint32 targetChecksum )\r\n{\r\n\tDbg_Assert( mp_model );\r\n\tDbg_Assert( mp_appearance );\r\n\r\n/*\r\n\tif ( !Script::GetArray( partChecksum, Script::NO_ASSERT ) )\r\n\t{\r\n\t\t// no array involved\r\n\t\treturn false;\r\n\t}\r\n*/\r\n\r\n\tScript::CStruct* pActualStruct = mp_appearance->GetActualDescStructure( partChecksum );\r\n\tif ( pActualStruct ) \r\n\t{\r\n\t\tScript::SStructScript* pStructScript = new Script::SStructScript;\r\n\t\tif ( pActualStruct->GetScript( targetChecksum, pStructScript, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\t// construct a script and run it\r\n\t\t\tScript::CScript* pScript = new Script::CScript;\r\n\t\t\tpScript->SetScript( pStructScript, NULL, mp_appearance );\t\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tpScript->SetCommentString(\"Created in CModelBuilder::model_run_script(...)\");\r\n\t\t\t#endif\r\n\t\t\tint ret_val;\r\n\t\t\twhile ((ret_val = pScript->Update()) != Script::ESCRIPTRETURNVAL_FINISHED)\r\n\t\t\t{\r\n\t\t\t\t// Script must not get blocked, otherwise it'll hang in this loop forever.\r\n\t\t\t\tDbg_MsgAssert(ret_val != Script::ESCRIPTRETURNVAL_BLOCKED,(\"\\n%s\\nScript got blocked when being run by RunScript.\",pScript->GetScriptInfo()));\r\n\t\t\t}\r\n\t\t\tdelete pScript;\r\n\t\t}\r\n\t\tdelete pStructScript;\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n#if 0\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelScalingModifier::ApplyModifier( Model* pModel, CModelAppearance* pAppearance )\r\n{\r\n\tDbg_Assert( pModel );\r\n\tDbg_Assert( pAppearance );\r\n\r\n\t// Enforce that it's a skin model, for now...\r\n\t// TODO:  Move some skin model functionality into model class...\r\n\tModel* pModel = static_cast<Model*> ( pModel );\r\n\tif ( !pModel )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tMth::Vector vec = pModel->GetScale();\r\n\r\n\t// always reset the guy when scaling\r\n\tvec[X] = 1.0f;\r\n\tvec[Y] = 1.0f;\r\n\tvec[Z] = 1.0f;\r\n\t\r\n\tfloat heightScale = pAppearance->GetFloat( vCHECKSUM_HEIGHT_SCALE );\r\n\t\r\n\tvec.Scale( heightScale );\r\n\r\n\tpModel->SetScale( vec );\r\n\r\n\t// reset scaling mode...  for the most part,\r\n\t// it will be apply_normal_mode\r\n\t// unless someone overrides it in script\r\n\tuint32 scalingMode = vCHECKSUM_APPLY_NORMAL_MODE;\r\n\r\n\tpAppearance->GetChecksum( vCHECKSUM_SCALING_MODE, &scalingMode );\r\n\r\n\t// apply the desired scaling script here...\r\n//\tDbg_Message( \"Applying %s scaling mode\\n\", Script::FindChecksumName( scalingMode ) );\r\n\tScript::RunScript( scalingMode, NULL, pModel );\r\n\r\n\tpModel->ApplyScaling();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModelWeightModifier::ApplyModifier( Model* pModel, CModelAppearance* pAppearance )\r\n{\r\n\tDbg_Assert( pModel );\r\n\tDbg_Assert( pAppearance );\r\n\r\n\t// Enforce that it's a skin model, for now...\r\n\t// TODO:  Move some skin model functionality into model class...\r\n\tModel* pModel = static_cast<Model*> ( pModel );\r\n\tif ( !pModel )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// should automatically be reset to identity...\r\n\tCScalingTable scaling_table;\r\n\r\n\tScript::CScriptStructure* pTempStructure = new Script::CScriptStructure;\r\n\tfloat weight = pAppearance->GetFloat( \"weight_scale\" );\r\n\tscaling_table.SetWeightScale( weight );\r\n\tdelete pTempStructure;\r\n\r\n\tpModel->ApplyScaling( &scaling_table );\r\n\t\r\n\treturn true;\r\n}\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/ModelBuilder.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       ModelBuilder.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/16/2001\r\n//****************************************************************************\r\n\r\n#ifndef __GFX_MODELBUILDER_H\r\n#define __GFX_MODELBUILDER_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <gel/object.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n    class CModel;\r\n};\r\n                \r\nnamespace Gfx\r\n{\r\n\tclass CModelAppearance;\r\n\tclass CSkeleton;\r\n\t\r\n\tconst uint32 vCHECKSUM_CREATE_MODEL_FROM_APPEARANCE = 0x91c1ec93;\t// create_model_from_appearance\r\n\tconst uint32 vCHECKSUM_COLOR_MODEL_FROM_APPEARANCE = 0xd2c041c2;\t// color_model_from_appearance\r\n\tconst uint32 vCHECKSUM_SCALE_MODEL_FROM_APPEARANCE = 0xaee1af7d;\t// scale_model_from_appearance\r\n\tconst uint32 vCHECKSUM_HIDE_MODEL_FROM_APPEARANCE = 0xb1a55798;\t\t// hide_model_from_appearance\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CModelBuilder\t: public Obj::CObject\r\n{\r\n\tpublic:\r\n\t\tCModelBuilder( bool useAssetManager, uint32 texDictOffset );\r\n\r\n\tpublic:\r\n\t\tvirtual void\tBuildModel( CModelAppearance* pAppearance, Nx::CModel* pModel, Gfx::CSkeleton* pSkeleton, uint32 scriptName = vCHECKSUM_CREATE_MODEL_FROM_APPEARANCE );\r\n\t\tvirtual bool\tCallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\t\r\n\tprotected:\r\n\t\tvirtual bool\tmodel_add_geom( uint32 partChecksum );\r\n\t\tvirtual bool\tmodel_clear_geom( uint32 partChecksum );\r\n\t\tvirtual bool\tmodel_hide_geom( uint32 partChecksum, bool hidden );\r\n\t\tvirtual bool\tgeom_modulate_color( Script::CStruct* pParams );\r\n\t\tvirtual bool\tgeom_set_uv_offset( uint32 partChecksum, uint32 matChecksum, int pass );\r\n\t\tvirtual bool\tgeom_allocate_uv_matrix_params( uint32 matChecksum, int pass );\r\n\t\tvirtual bool\tgeom_replace_texture( uint32 partChecksum );\r\n\t\tvirtual bool\tmodel_clear_all_geoms();\r\n\t\tvirtual bool\tmodel_remove_polys();\r\n\t\tvirtual bool\tmodel_reset_scale();\r\n\t\tvirtual bool\tmodel_apply_body_shape();\r\n\t\tvirtual bool\tmodel_apply_bone_scale( uint32 partChecksum );\r\n\t\tvirtual bool\tmodel_apply_object_scale();\r\n\t\tvirtual bool\tmodel_finalize();\r\n\t\tvirtual bool\tmodel_run_script( uint32 partChecksum, uint32 targetChecksum );\r\n\t\t\r\n\tprotected:\r\n\t\t// temporary pointer to the model, so that CallMemberFunctions\r\n\t\t// can operate on the Nx::CModel.  This only exists for the\r\n\t\t// duration of the BuildModel() function call.\r\n\t\tstatic Nx::CModel*\t\t\tmp_model;\r\n\t\tstatic Gfx::CSkeleton*\t\tmp_skeleton;\r\n\t\tstatic CModelAppearance*\tmp_appearance;\r\n\t\tbool\t\t\t\t\t\tm_useAssetManager;\r\n\t\tuint32\t\t\t\t\t\tm_texDictOffset;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __GFX_MODELBUILDER_H\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/anim.cpp",
    "content": "#include <stdio.h>\r\n#include <stdlib.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <core/HashTable.h>\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n#include <sys/file/filesys.h>\r\n\r\n#include \"nx_init.h\"\r\n#include \"mesh.h\"\r\n#include \"scene.h\"\r\n#include \"anim.h\"\r\n\r\nnamespace NxNgc\r\n{\r\n//\t// Material color attenuation.\r\n//\tstatic DWORD WeightedMeshVertexShader0Decl[] = {\r\n//\tD3DVSD_STREAM( 0 ),\r\n//\tD3DVSD_REG( VSD_REG_POS,\t\tD3DVSDT_FLOAT3 ),\t// Position.\r\n//\tD3DVSD_REG( VSD_REG_WEIGHTS,\tD3DVSDT_FLOAT4 ),\t// Weights.\r\n//\tD3DVSD_REG( VSD_REG_INDICES,\tD3DVSDT_SHORT4 ),\t// Indices.\r\n//\tD3DVSD_REG( VSD_REG_NORMAL,\t\tD3DVSDT_FLOAT3 ),\t// Normals.\r\n//\tD3DVSD_REG( VSD_REG_TEXCOORDS,\tD3DVSDT_FLOAT2 ),\t// Texture coordinates.\r\n//\tD3DVSD_END() };\r\n//\r\n//\t// Vertex color attenuation.\r\n//\tstatic DWORD WeightedMeshVertexShader1Decl[] = {\r\n//\tD3DVSD_STREAM( 0 ),\r\n//\tD3DVSD_REG( VSD_REG_POS,\t\tD3DVSDT_FLOAT3 ),\t// Position.\r\n//\tD3DVSD_REG( VSD_REG_WEIGHTS,\tD3DVSDT_FLOAT4 ),\t// Weights.\r\n//\tD3DVSD_REG( VSD_REG_INDICES,\tD3DVSDT_SHORT4 ),\t// Indices.\r\n//\tD3DVSD_REG( VSD_REG_NORMAL,\t\tD3DVSDT_FLOAT3 ),\t// Normals.\r\n//\tD3DVSD_REG( VSD_REG_COLOR,\t\tD3DVSDT_D3DCOLOR ),\t// Diffuse color.\r\n//\tD3DVSD_REG( VSD_REG_TEXCOORDS,\tD3DVSDT_FLOAT2 ),\t// Texture coordinates.\r\n//\tD3DVSD_END() };\r\n//\r\n//\r\n//\r\n//DWORD WeightedMeshVertexShader0;\r\n//DWORD WeightedMeshVertexShader1;\r\n//\r\n//\r\n////DWORD GetVertexShader( bool vertex_colors )\r\n////{\r\n////\tif( vertex_colors )\r\n////\t{\r\n////\t\treturn WeightedMeshVertexShader1;\r\n////\t}\r\n////\r\n////\treturn WeightedMeshVertexShader0;\r\n////}\r\n//\r\n//\r\n\r\n//void CreateWeightedMeshVertexShaders( void )\r\n//{\r\n//\tstatic bool created_shaders = false;\r\n//\r\n//\tif( !created_shaders )\r\n//\t{\r\n//\t\tcreated_shaders = true;\r\n//\r\n//\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShader0Decl,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedmeshvertexshader0VertexShader,\t// Defined in the header file from xsasm.\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVertexShader0,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n//\t\t{\r\n//\t\t\texit( 0 );\r\n//\t\t}\r\n//\r\n//\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShader1Decl,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedmeshvertexshader1VertexShader,\t// Defined in the header file from xsasm.\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVertexShader1,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n//\t\t{\r\n//\t\t\texit( 0 );\r\n//\t\t}\r\n//\t}\r\n//}\r\n\r\n\r\n\r\n\r\n//static void MatrixInvertOrthoNormalized( D3DXMATRIX *matrix, const D3DXMATRIX *matrixIn )\r\n//{\r\n//    /*\r\n//     * Inverse of upper left 3x3 sub matrix\r\n//     * is a simple transpose\r\n//     */\r\n////    matrix->right.x = matrixIn->right.x;\r\n////    matrix->right.y = matrixIn->up.x;\r\n////    matrix->right.z = matrixIn->at.x;\r\n////    matrix->up.x = matrixIn->right.y;\r\n////    matrix->up.y = matrixIn->up.y;\r\n////    matrix->up.z = matrixIn->at.y;\r\n////    matrix->at.x = matrixIn->right.z;\r\n////    matrix->at.y = matrixIn->up.z;\r\n////    matrix->at.z = matrixIn->at.z;\r\n//\tmatrix->m[0][0] = matrixIn->m[0][0];\r\n//\tmatrix->m[0][1] = matrixIn->m[1][0];\r\n//\tmatrix->m[0][2] = matrixIn->m[2][0];\r\n//\tmatrix->m[0][3] = 0.0f;\r\n//\tmatrix->m[1][0] = matrixIn->m[0][1];\r\n//\tmatrix->m[1][1] = matrixIn->m[1][1];\r\n//\tmatrix->m[1][2] = matrixIn->m[2][1];\r\n//\tmatrix->m[1][3] = 0.0f;\r\n//\tmatrix->m[2][0] = matrixIn->m[0][2];\r\n//\tmatrix->m[2][1] = matrixIn->m[1][2];\r\n//\tmatrix->m[2][2] = matrixIn->m[2][2];\r\n//\tmatrix->m[2][3] = 0.0f;\r\n//\r\n//    /*\r\n//     * calculate translation componennt of inverse\r\n//     */\r\n////    matrix->pos.x = -RwV3dDotProductMacro(&matrixIn->pos, &matrixIn->right);\r\n////    matrix->pos.y = -RwV3dDotProductMacro(&matrixIn->pos, &matrixIn->up);\r\n////    matrix->pos.z = -RwV3dDotProductMacro(&matrixIn->pos, &matrixIn->at);\r\n//    matrix->m[3][0] = -(( matrixIn->m[3][0] * matrixIn->m[0][0] ) + ( matrixIn->m[3][1] * matrixIn->m[0][1] ) + ( matrixIn->m[3][2] * matrixIn->m[0][2] ));\r\n//    matrix->m[3][1] = -(( matrixIn->m[3][0] * matrixIn->m[1][0] ) + ( matrixIn->m[3][1] * matrixIn->m[1][1] ) + ( matrixIn->m[3][2] * matrixIn->m[1][2] ));\r\n//    matrix->m[3][2] = -(( matrixIn->m[3][0] * matrixIn->m[2][0] ) + ( matrixIn->m[3][1] * matrixIn->m[2][1] ) + ( matrixIn->m[3][2] * matrixIn->m[2][2] ));\r\n//    matrix->m[3][3] = 1.0f;\r\n//}\r\n\r\n\r\n\r\n\r\n\r\n//void setup_weighted_mesh_vertex_shader( void *p_root_matrix, void *p_bone_matrices, int num_bone_matrices )\r\n//{\r\n//\tD3DXMATRIX\tdest_matrix;\r\n//\tD3DXMATRIX\tinverse_view_matrix;\r\n//\tD3DXMATRIX\ttemp_matrix;\r\n//\tD3DXMATRIX\tprojMatrix;\r\n//\tD3DXMATRIX\tviewMatrix;\r\n//\tD3DXMATRIX\tworldMatrix;\r\n//\r\n//\t// Projection matrix.\r\n//\tprojMatrix.m[0][0] = EngineGlobals.projection_matrix.m[0][0];\r\n//    projMatrix.m[0][1] = EngineGlobals.projection_matrix.m[1][0];\r\n//    projMatrix.m[0][2] = EngineGlobals.projection_matrix.m[2][0];\r\n//    projMatrix.m[0][3] = EngineGlobals.projection_matrix.m[3][0];\r\n//    projMatrix.m[1][0] = EngineGlobals.projection_matrix.m[0][1];\r\n//\tprojMatrix.m[1][1] = EngineGlobals.projection_matrix.m[1][1];\r\n//    projMatrix.m[1][2] = EngineGlobals.projection_matrix.m[2][1];\r\n//    projMatrix.m[1][3] = EngineGlobals.projection_matrix.m[3][1];\r\n//\r\n//    projMatrix.m[2][0] = 0.0f;\r\n//    projMatrix.m[2][1] = 0.0f;\r\n////    projMatrix.m[2][2] = camera->farPlane / ( camera->farPlane - camera->nearPlane );\r\n//    projMatrix.m[2][2] = 20000.0f / ( 20000.0f - 2.0f );\r\n////\tprojMatrix.m[2][3] = -projMatrix.m[2][2] * camera->nearPlane;\r\n//\tprojMatrix.m[2][3] = -projMatrix.m[2][2] * 2.0f;\r\n//\r\n//    projMatrix.m[3][0] = 0.0f;\r\n//    projMatrix.m[3][1] = 0.0f;\r\n//    projMatrix.m[3][2] = 1.0f;\r\n//    projMatrix.m[3][3] = 0.0f;\r\n//\r\n//\t// View matrix.\r\n//\tD3DXMATRIX\tview_matrix = EngineGlobals.view_matrix;\r\n//\t\r\n//\tviewMatrix.m[0][0] = -view_matrix.m[0][0];\r\n//    viewMatrix.m[0][1] = view_matrix.m[1][0];\r\n//    viewMatrix.m[0][2] = -view_matrix.m[2][0];\r\n//    viewMatrix.m[0][3] = view_matrix.m[3][0];\r\n//    viewMatrix.m[1][0] = -view_matrix.m[0][1];\r\n//    viewMatrix.m[1][1] = view_matrix.m[1][1];\r\n//    viewMatrix.m[1][2] = -view_matrix.m[2][1];\r\n//    viewMatrix.m[1][3] = view_matrix.m[3][1];\r\n//    viewMatrix.m[2][0] = view_matrix.m[0][2];\r\n//    viewMatrix.m[2][1] = -view_matrix.m[1][2];\r\n//    viewMatrix.m[2][2] = view_matrix.m[2][2];\r\n//    viewMatrix.m[2][3] = -view_matrix.m[3][2];\r\n//    viewMatrix.m[3][0] = 0.0f;\r\n//    viewMatrix.m[3][1] = 0.0f;\r\n//    viewMatrix.m[3][2] = 0.0f;\r\n//    viewMatrix.m[3][3] = 1.0f;\r\n//\t\r\n//\t// World space transformation matrix.\r\n//\tworldMatrix.m[0][0] = ((float*)p_root_matrix )[0];\r\n//\tworldMatrix.m[0][1] = ((float*)p_root_matrix )[1];\r\n//\tworldMatrix.m[0][2] = ((float*)p_root_matrix )[2];\r\n//\tworldMatrix.m[0][3] = ((float*)p_root_matrix )[3];\r\n//    worldMatrix.m[1][0] = ((float*)p_root_matrix )[4];\r\n//    worldMatrix.m[1][1] = ((float*)p_root_matrix )[5];\r\n//    worldMatrix.m[1][2] = ((float*)p_root_matrix )[6];\r\n//    worldMatrix.m[1][3] = ((float*)p_root_matrix )[7];\r\n//    worldMatrix.m[2][0] = ((float*)p_root_matrix )[8];\r\n//    worldMatrix.m[2][1] = ((float*)p_root_matrix )[9];\r\n//    worldMatrix.m[2][2] = ((float*)p_root_matrix )[10];\r\n//    worldMatrix.m[2][3] = ((float*)p_root_matrix )[11];\r\n//    worldMatrix.m[3][0] = 0.0f;\r\n//    worldMatrix.m[3][1] = 0.0f;\r\n//    worldMatrix.m[3][2] = 0.0f;\r\n//    worldMatrix.m[3][3] = 1.0f;\r\n//\r\n//\t// Calculate composite world->view->projection matrix.\r\n//\tD3DXMatrixMultiply( &temp_matrix, &viewMatrix, &worldMatrix );\r\n//\tD3DXMatrixMultiply( &dest_matrix, &projMatrix, &temp_matrix );\r\n//\r\n//\t// Switch to 192 constant mode, removing the lock on the reserved constants c-38 and c-37.\r\n//\tD3DDevice_SetShaderConstantMode( D3DSCM_192CONSTANTS | D3DSCM_NORESERVEDCONSTANTS );\r\n//\r\n//\t// Load up the combined world, camera & projection matrix.\r\n//\tfor( int i = 0; i < 16; ++i )\r\n//\t{\r\n//\t\tif( fabsf(((float*)dest_matrix.m )[i] ) < 0.001f )\r\n//\t\t{\r\n//\t\t\t((float*)dest_matrix.m )[i] = 0.0f;\r\n//\t\t}\r\n//\t}\r\n//\t\r\n//\tD3DDevice_SetVertexShaderConstant( VSCONST_REG_TRANSFORM_OFFSET, (void*)&dest_matrix, VSCONST_REG_TRANSFORM_SIZE );\r\n//\tD3DDevice_SetVertexShaderConstant( VSCONST_REG_WORLD_TRANSFORM_OFFSET,\t(void*)&worldMatrix, VSCONST_REG_WORLD_TRANSFORM_SIZE );\r\n//\r\n//\t// Load up the directional light data.\r\n//\tstatic float directional_light_color[24] = {\r\n//\t0.0f, -1.0f, 0.0f, 0.0f,\t// Dir 0\r\n//\t0.7f, 0.6f, 0.5f, 1.0f,\t\t// Col 0\r\n//\t1.0f, 0.0f, 0.0f, 0.0f,\t\t// Dir 1\r\n//\t0.35f, 0.4f, 0.4f, 1.0f,\t\t// Col 1\r\n//\t0.0f, 0.0f, 1.0f, 0.0f,\t\t// Dir 2\r\n//\t0.3f, 0.3f, 0.2f, 1.0f };\t// Col 2\r\n//\t\r\n//\tD3DDevice_SetVertexShaderConstant( VSCONST_REG_DIR_LIGHT_OFFSET,\t\t(void*)directional_light_color, VSCONST_REG_DIR_LIGHT_SIZE );\r\n//\r\n//\t// Load up the ambient light color.\r\n//\tstatic float ambient_light_color[4] = { 0.4f, 0.4f, 0.4f, 1.0f };\r\n//\tD3DDevice_SetVertexShaderConstant( VSCONST_REG_AMB_LIGHT_OFFSET, (void*)ambient_light_color, 1 );\r\n//\t\r\n//\t// Load up the material color.\r\n//\tstatic float material_color[4] = { 1.0f, 1.0f, 1.0f, 1.0f };\r\n//\tD3DDevice_SetVertexShaderConstant( VSCONST_REG_MATERIAL_OFFSET, (void*)material_color, 1 );\r\n//\r\n//\t// Load up the bone transforms, in sets of 40.\r\n//\tint offset = 0;\r\n//\twhile( num_bone_matrices > 0 )\r\n//\t{\r\n//\t\tif( num_bone_matrices >= 10 )\r\n//\t\t{\r\n//\t\t\tD3DDevice_SetVertexShaderConstant( VSCONST_REG_MATRIX_OFFSET + offset, (float*)p_bone_matrices + ( offset * 4 ), 10 * 3 );\r\n//\t\t\toffset += 10 * 3;\r\n//\t\t\tnum_bone_matrices -= 10;\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tD3DDevice_SetVertexShaderConstant( VSCONST_REG_MATRIX_OFFSET + offset, (float*)p_bone_matrices + ( offset * 4 ), num_bone_matrices * 3 );\r\n//\t\t\tnum_bone_matrices = 0;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t// Load up the replacement registers for c-38 and c-37.\r\n//\tstatic float homogenous_to_screen_reg[8] = { 320.0f, -240.0f, 1.67772e7f, 0.0f, 320.03125f, 240.03125f, 0.0f, 0.0f };\r\n//\tD3DDevice_SetVertexShaderConstant( 94, (void*)homogenous_to_screen_reg, 2 );\r\n//}\r\n\r\n\r\n\r\n//void shutdown_weighted_mesh_vertex_shader( void )\r\n//{\r\n//\t// Switch back to 96 constant mode.\r\n//\tD3DDevice_SetShaderConstantMode( D3DSCM_96CONSTANTS );\r\n//}\r\n\r\n\r\n} // namespace NxNgc"
  },
  {
    "path": "Code/Gfx/NGC/NX/anim.h",
    "content": "#ifndef __ANIM_H\r\n#define __ANIM_H\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n//DWORD\tGetVertexShader( bool vertex_colors );\r\n//void\tCreateWeightedMeshVertexShaders( void );\r\n//void\tsetup_weighted_mesh_vertex_shader( void *p_root_matrix, void *p_bone_matrices, int num_bone_matrices );\r\n//void\tshutdown_weighted_mesh_vertex_shader( void );\r\n\r\n\r\n} // namespace NxNgc\r\n\r\n#endif // __ANIM_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/chars.cpp",
    "content": "#include <stdlib.h>\r\n#include <string.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <core/string/stringutils.h>\r\n#include <core/macros.h>\r\n#include <sys/file/filesys.h>\r\n\r\n#include \"nx_init.h\"\r\n#include \"chars.h\"\r\n\r\n#include <sys/ngc/p_prim.h>\r\n#include <sys/ngc/p_camera.h>\r\n#include <sys/ngc/p_render.h>\r\n#include <sys/ngc/p_display.h>\r\n#include <sys/ngc/p_gx.h>\r\n#include <sys/config/config.h>\r\n\r\n#include <gfx/nxfontman.h>\r\n\r\n/*\r\n\r\n\r\n\t\r\n.fnt file format (by Ryan)\r\n--------------------------\r\n\r\n\t4\tFile size in bytes\r\n\t4\tNumber of characters\r\n\t4\tDefault height\r\n\t4\tDefault base\r\n\t\r\n\t?\tCharacter table (see below)\r\n\t?\tTexture (see below)\r\n\r\n\tCharacter\r\n\t2\tBaseline (how many pixels down relative to top of image)\r\n\t2\tAscii value\r\n\r\n\tTexture\r\n\t4\tSize of texture\r\n\t2\tWidth\r\n\t2\tHeight\r\n\t2\tBit depth\r\n\t6\tPadding\r\n\tW*H\tRaw data\r\n\t0-3\tPadding for uint32 alignment\r\n\t1K\tPalette data\r\n\t4\tNumber of subtextures\r\n\t?\tSubtexture table (see below)\r\n\r\n\tSubtexture\r\n\t2\tX\r\n\t2\tY\r\n\t2\tW\r\n\t2\tH\r\n\t\r\n*/\r\n\r\n// This is the function generated by the makefile when building permanent font files.\r\nextern void * get_font_file_address( const char * p_filename );\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n\r\nfloat CurrentScale;\r\nuint32 FontVramBase;\r\nSFont *pFontList;\r\nSFont *pButtonsFont = NULL;\r\n\r\nfloat wx0 = 0.0f;\r\nfloat wy0 = 0.0f;\r\nfloat wx1 = 640.0f;\r\nfloat wy1 = 448.0f;\r\n\r\nSFont *SText::spOverrideFont = NULL;\r\n\r\nSFont *LoadFont( const char *Filename )\r\n{\r\n\tSFont\t*pFont;\r\n\tSChar\t*pChar;\r\n\tuint8\t*pData;\r\n//\tint\t\ti,Len,NumChars,Width,Height,Depth,NumBytes;\r\n\tint\t\ti,NumChars,Width,Height,Depth,NumBytes;\r\n\r\n\tchar * p8 = (char *)Filename;\r\n\twhile ( *p8 != '\\0' )\r\n\t{\r\n\t\tif ( ( *p8 >= 'A' ) && ( *p8 <= 'Z' ) )\r\n\t\t{\r\n\t\t\t*p8 = *p8 - ( 'A' - 'a' );\r\n\t\t}\r\n\t\tp8++;\r\n\t}\r\n\tunsigned char * p_fnt = (unsigned char *)get_font_file_address( Filename );\r\n\tDbg_MsgAssert( p_fnt, ( \"Font file '%s' not found in permanent data.\", Filename ));\r\n\r\n#define get_bytes(p,n) { memcpy( p, p_fnt, n ); p_fnt += n; }\r\n\r\n\t// Allocate memory for the font structure.\r\n\tpFont = new SFont();\r\n\r\n\t// Allocate a temporary buffer.\r\n\tuint8 FontBuf[2048];\r\n\r\n\t// Load file header.\r\n\tget_bytes( FontBuf, 16 );\r\n//\tLen = File::Read( FontBuf, 16, 1, p_FH );\r\n//\tDbg_MsgAssert( Len==16, ( \"couldn't read file header from font file %s\", Filename ));\r\n\tNumChars\t\t\t = ((uint32 *)FontBuf)[1];\r\n\tpFont->DefaultHeight = ((uint32 *)FontBuf)[2];\r\n\tpFont->DefaultBase\t = ((uint32 *)FontBuf)[3];\r\n\r\n#ifdef __PLAT_NGC__\r\n\t// PJR - This needs to disappear once we start converting .ska to .ska.ngc etc.\r\n\tNumChars\t\t\t\t= nReverse32( NumChars );\r\n\tpFont->DefaultHeight\t= nReverse32( pFont->DefaultHeight );\r\n\tpFont->DefaultBase\t\t= nReverse32( pFont->DefaultBase );\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\t// Clear character map to zero.\r\n\tmemset( pFont->Map, 0, 256 );\r\n\tmemset(pFont->SpecialMap, 0, 32);\r\n\r\n\t// Allocate memory for character table.\r\n\tpFont->pChars = new SChar[NumChars];\r\n\r\n\t// Load character map and character table.\r\n\tget_bytes( FontBuf, NumChars << 2 );\r\n//\tLen = File::Read( FontBuf, NumChars << 2, 1, p_FH );\r\n//\tDbg_MsgAssert( Len == ( NumChars << 2 ), ( \"couldn't read character table in font file %s\", Filename ));\r\n\r\n\tfor( i = 0, pChar = pFont->pChars, pData = FontBuf; i < NumChars; i++,pChar++,pData += 4 )\r\n\t{\r\n#ifdef __PLAT_NGC__\r\n\t\t// PJR - This needs to disappear once we start converting .ska to .ska.ngc etc.\r\n\t\tpChar->Baseline = nReverse32( pChar->Baseline );\r\n\t\tpChar->Baseline = nReverse16( ((uint16 *)pData)[0] );\r\n\t\tsint16 ascii_val = nReverse16(((sint16*) pData)[1]);\r\n\t\tif (ascii_val >= 0)\r\n\t\t\tpFont->Map[(uint8) ascii_val] = i;\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Assert(ascii_val >= -32)\r\n\t\t\tpFont->SpecialMap[(uint8) (-ascii_val - 1)] = i;\r\n\t\t}\r\n#else\r\n\t\tpChar->Baseline\t\t\t\t\t\t\t= ((uint16 *)pData)[0];\r\n\t\tpFont->Map[(uint8)((uint16*)pData)[1]]\t= i;\r\n#endif\t\t// __PLAT_NGC__\r\n\t}\r\n\r\n\t// now, if there is a null character in the font, make characters that could not be found\r\n\t// in the font display that instead of 'A'\r\n\tif (pFont->SpecialMap[31] != 0)\r\n\t{\r\n\t\tfor (i = 0; i < 256; i++) \r\n\t\t{\r\n\t\t\tif (pFont->Map[i] == 0 && i != 'A' && i != 'a') pFont->Map[i] = pFont->SpecialMap[31];\r\n\t\t\tif (i < 31 && pFont->SpecialMap[i] == 0) pFont->SpecialMap[i] = pFont->SpecialMap[31];\r\n\t\t}\r\n\t}\t\r\n\t\r\n\t// Load texture header.\r\n\tget_bytes( FontBuf, 16 );\r\n//\tLen = File::Read( FontBuf, 16, 1, p_FH );\r\n//\tDbg_MsgAssert( Len == 16, ( \"couldn't read texture header from font file %s\", Filename ));\r\n\tWidth\t= ((uint16 *)FontBuf)[2];\r\n\tHeight\t= ((uint16 *)FontBuf)[3];\r\n\tDepth\t= ((uint16 *)FontBuf)[4];\r\n\r\n#ifdef __PLAT_NGC__\r\n\t// PJR - This needs to disappear once we start converting .ska to .ska.ngc etc.\r\n\tWidth\t= nReverse16( Width );\r\n\tHeight\t= nReverse16( Height );\r\n\tDepth\t= nReverse16( Depth );\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\t// Create texture.\r\n\tDbg_Assert( Depth == 8 );\r\n\r\n\tNumBytes = ( Width * Height + 3 ) & 0xFFFFFFFC;\r\n\t\r\n\t// Align texture to 32 bytes & point up.\r\n\tint size = ( Width * Height ) + ( 256 * 2 );\r\n\tunsigned char * p_align = (unsigned char*)OSRoundUp32B( p_fnt );\r\n\tfor ( int lp = ( size - 1 ); lp >= 0; lp-- ) p_align[lp] = p_fnt[lp];\r\n\tDCFlushRange( p_align, size );\r\n\tpFont->mp_texture = p_align;\r\n\tpFont->mp_palette = &p_align[( Width * Height )];\r\n\tp_fnt += ( Width * Height );\t\t// Texture\r\n\tp_fnt += ( 256 * 2 );\t\t\t\t// Palette\r\n\tp_fnt += 32;\t\t\t\t\t\t// Padding\r\n\r\n//\tpFont->mp_texture = new char[ ( Width * Height ) ];\r\n//\tLen = File::Read( pFont->mp_texture, ( Width * Height ), 1, p_FH );\r\n//\tDbg_MsgAssert( Len == ( Width * Height ), ( \"couldn't read texture data from font file %s\", Filename ));\r\n//\r\n//\tpFont->mp_palette = new char[ ( 256 * 4 ) ];\r\n//\tLen = File::Read( pFont->mp_palette, ( 256 * 4 ), 1, p_FH );\r\n//\tDbg_MsgAssert( Len == ( 256 * 4 ), ( \"couldn't read palette data from font file %s\", Filename ));\r\n\r\n\tpFont->m_width = Width;\r\n\tpFont->m_height = Height;\r\n\r\n\t// Skip numsubtextures, and load subtextures.\r\n\tget_bytes( FontBuf, ( NumChars << 3 ) + 4 );\r\n//\tLen = File::Read( FontBuf, ( NumChars << 3 ) + 4, 1, p_FH );\r\n//\tDbg_MsgAssert( Len == ( NumChars << 3 ) + 4, ( \"couldn't read subtexture table from font file %s\", Filename ));\r\n\tfor( i = 0, pChar = pFont->pChars, pData = FontBuf + 4; i < NumChars; i++, pChar++, pData += 8 )\r\n\t{\r\n\t\tuint16 x = ((uint16 *)pData )[0];\r\n\t\tuint16 y = ((uint16 *)pData )[1];\r\n\t\tuint16 w = ((uint16 *)pData )[2];\r\n\t\tuint16 h = ((uint16 *)pData )[3];\r\n\t\t\r\n#ifdef __PLAT_NGC__\r\n\t\tx = nReverse16( x );\r\n\t\ty = nReverse16( y );\r\n\t\tw = nReverse16( w );\r\n\t\th = nReverse16( h );\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\t\tpChar->w\t= w;\r\n\t\tpChar->h\t= h;\r\n\t\tpChar->u0\t= ( ((float)x + 0.5f) / (float)Width );\r\n\t\tpChar->v0\t= ( ((float)y + 0.5f) / (float)Height );\r\n\t\tpChar->u1\t= pChar->u0 + ((float)w / (float)Width );\r\n\t\tpChar->v1\t= pChar->v0 + ((float)h / (float)Height );\r\n\t}\r\n\r\n\t// Add font to font list.\r\n\tpFont->pNext\t= pFontList;\r\n\tpFontList\t\t= pFont;\r\n\r\n\t// We're done with the font file now.\r\n//\tFile::Close( p_FH );\r\n\t\r\n\t// this will serve as the default spacing\r\n\tpFont->mSpaceSpacing = pFont->pChars[pFont->Map['I']].w;\r\n\t\r\n\treturn pFont;\r\n}\r\n\r\n\r\n\r\nvoid UnloadFont(SFont *pFont)\r\n{\r\n\tSFont *pPrevFont;\r\n\tint found=0;\r\n\r\n\t// find font and unchain from list\r\n\tif (pFontList == pFont)\r\n\t{\r\n\t\tfound=1;\r\n\t\tpFontList = pFontList->pNext;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor (pPrevFont=pFontList; pPrevFont->pNext; pPrevFont=pPrevFont->pNext)\r\n\t\t{\r\n\t\t\tif (pPrevFont->pNext == pFont)\r\n\t\t\t{\r\n\t\t\t\tfound=1;\r\n\t\t\t\tpPrevFont->pNext = pFont->pNext;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert(found, (\"attempt to unload font which has not been loaded\"));\r\n\r\n\t// free memory\r\n\tfree( pFont->pChars );\r\n\tfree( pFont );\r\n}\r\n\r\nuint32 SFont::GetDefaultHeight() const\r\n{\r\n\treturn DefaultHeight << 4;\r\n}\r\n\r\nuint32 SFont::GetDefaultBase() const\r\n{\r\n\treturn DefaultBase << 4;\r\n}\r\n\r\nvoid SFont::QueryString(char *String, float &width, float &height)\r\n{\r\n\tSChar *pChar;\r\n\tchar *pLetter;\r\n\tfloat u0,v0,x0,u1,v1,x1;\r\n\r\n\tx0 = 0;\r\n\r\n\t//sint16 char_spacing = 16 + (mCharSpacing<<4);\r\n\tfloat char_spacing = mCharSpacing;\r\n\tfloat space_spacing = mSpaceSpacing;\r\n\t\r\n\tfor (pLetter=String;; pLetter++)\r\n\t{\r\n\t\tpChar = NULL;\r\n\t\t// may be overridden by the '\\b' tag\r\n\t\tSFont *p_font = this;\r\n\t\t\r\n\t\t// acount for tags (might be multiple ones in a row)\r\n\t\tbool got_char_tag = false; // tag resulting in output of character\r\n\t\twhile (*pLetter == '\\\\' && !got_char_tag)\r\n\t\t{\r\n\t\t\tpLetter++;\r\n\t\t\tif (*pLetter == '\\\\')\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tswitch(*pLetter)\r\n\t\t\t{\r\n\t\t\t\tcase '\\\\':\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 'c':\r\n\t\t\t\tcase 'C':\r\n\t\t\t\t\tpLetter += 2; // skip over \"c#\"\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 's':\r\n\t\t\t\tcase 'S':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++; // skip \"s\"\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\tpChar = pChars + SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase 'b':\r\n\t\t\t\tcase 'B':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++; // skip \"b\"\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// switch over to buttons font, the regular font will be used again on the next character\r\n\r\n\t\t\t\t\tp_font = pButtonsFont;\r\n\t\t\t\t\tDbg_Assert(p_font);\r\n\t\t\t\t\tpChar = p_font->pChars + p_font->SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase 'm':\r\n\t\t\t\tcase 'M':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++; // skip \"m\"\r\n\t\t\t\t\tchar button_char = Nx::CFontManager::sMapMetaCharacterToButton(pLetter);\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(&button_char);\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_font = pButtonsFont;\r\n\t\t\t\t\tDbg_Assert(p_font);\r\n\t\t\t\t\tpChar = p_font->pChars + p_font->SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDbg_MsgAssert(0, (\"unknown tag %c\", *pLetter));\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t} // end while\r\n\t\t\r\n\t\tif (*pLetter == '\\0') break;\r\n\r\n\t\tif (*pLetter != ' ' || pChar)\r\n\t\t{\r\n\t\t\tif (!pChar)\r\n\t\t\t\tpChar = p_font->pChars + p_font->Map[(uint8)*pLetter];\r\n\t\t\tu0 = pChar->u0;\r\n\t\t\tv0 = pChar->v0;\r\n\t\t\tu1 = pChar->u1;\r\n\t\t\tv1 = pChar->v1;\r\n\t\t\tx1 = x0+((u1-u0)*m_width);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tx1 = x0 + space_spacing;\r\n\t\t}\r\n\t\t\r\n\t\tx0 = x1+char_spacing;\r\n\t}\r\n\r\n\twidth  = (float)x0;\r\n\theight = (float)DefaultHeight;\r\n}\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nSText::SText( float pri ) : SDraw2D( pri, true )\r\n{\r\n}\r\n\r\n\r\nSText::~SText( void )\r\n{\r\n}\r\n\r\n\r\nvoid SText::BeginDraw( void )\r\n{\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SText::Draw( void )\r\n{\r\n\tbool uploaded = false;\r\n\tbool new_color = true;\r\n\tSChar *pChar = NULL;\r\n\tchar *pLetter;\r\n\tfloat u0,v0,x0,y0,u1,v1,x1,y1,yt;\r\n\r\n\tx0 = m_xpos + wx0;\r\n\ty0 = m_ypos + wy0;\r\n\r\n\t//sint16 char_spacing = 16 + (mp_font->mCharSpacing<<4);\r\n\tfloat char_spacing = (float) mp_font->mCharSpacing * m_xscale;\r\n\tfloat space_spacing = (float) mp_font->mSpaceSpacing * m_xscale;\r\n\t\r\n\tGXColor current_color;\r\n\tcurrent_color.a = (m_rgba&0xff);\r\n\tcurrent_color.b = ((m_rgba&0xff00)>>8);\r\n\tcurrent_color.g = ((m_rgba&0xff0000)>>16);\r\n\tcurrent_color.r = ((m_rgba&0xff000000)>>24);\r\n\t\r\n\tfor (pLetter=mp_string;; pLetter++)\r\n\t{\r\n\t\tpChar = NULL;\r\n\t\tSFont *p_font = (spOverrideFont) ? spOverrideFont : mp_font;\r\n\t\t\r\n\t\t// acount for tags (might be multiple ones in a row)\r\n\t\tbool got_char_tag = false; // tag resulting in output of character\r\n\t\twhile (*pLetter == '\\\\' && !got_char_tag)\r\n\t\t{\r\n\t\t\tpLetter++;\r\n\r\n\t\t\tswitch(*pLetter)\r\n\t\t\t{\r\n\t\t\t\tcase '\\\\':\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 'c':\r\n\t\t\t\tcase 'C':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++;\t// skip \"c\"\t\t\t\t\t\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\tpLetter++; // skip \"#\"\r\n\r\n\t\t\t\t\t// set active color from font\r\n\t\t\t\t\tuint32 trgba;\r\n\t\t\t\t\tif (digit != 0 && !m_color_override)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttrgba = mp_font->mRGBATab[digit-1];\r\n\t\t\t\t\t\tcurrent_color.r = (trgba&0xff);\r\n\t\t\t\t\t\tcurrent_color.g = ((trgba&0xff00)>>8);\r\n\t\t\t\t\t\tcurrent_color.b = ((trgba&0xff0000)>>16);\r\n\t\t\t\t\t\tcurrent_color.a = ((trgba&0xff000000)>>24);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttrgba = m_rgba;\r\n\t\t\t\t\t\tcurrent_color.a = (trgba&0xff);\r\n\t\t\t\t\t\tcurrent_color.b = ((trgba&0xff00)>>8);\r\n\t\t\t\t\t\tcurrent_color.g = ((trgba&0xff0000)>>16);\r\n\t\t\t\t\t\tcurrent_color.r = ((trgba&0xff000000)>>24);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t//GX::SetChanAmbColor( GX_COLOR0A0, current_color );\r\n\t\t\t\t\tnew_color = true;\r\n\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase 's':\r\n\t\t\t\tcase 'S':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++;\t// skip \"s\"\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\t\r\n\t\t\t\t\tpChar = mp_font->pChars + mp_font->SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase 'b':\r\n\t\t\t\tcase 'B':\r\n\t\t\t\t{\r\n\t\t\t\t\t// 'B' stands for button, accesses the button font\r\n\r\n\t\t\t\t\tpLetter++; // skip \"b\"\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// switch to the buttons font!\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_font = pButtonsFont;\r\n\t\t\t\t\tDbg_Assert(p_font);\r\n\t\t\t\t\tpChar = p_font->pChars + p_font->SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\t\r\n\t\t\t\t\tspOverrideFont = p_font;\r\n\t\t\t\t\t//EndDraw();\r\n\t\t\t\t\t//BeginDraw();\r\n\t\t\t\t\tuploaded = false;\r\n\t\t\t\t\t// we can now return to using the regular font (no override)\r\n\t\t\t\t\tspOverrideFont = NULL;\r\n\t\t\t\t\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDbg_MsgAssert(0, (\"unknown tag %c\", *pLetter));\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t} // end while\r\n\r\n\t\tif (*pLetter == '\\0') break;\r\n\t\t\r\n\t\tif (*pLetter != ' ' || pChar)\r\n\t\t{\r\n\t\t\tif (!pChar)\r\n\t\t\t\tpChar = p_font->pChars + p_font->Map[(uint8) *pLetter];\r\n\t\t\tyt = y0 + (float)(p_font->DefaultBase - pChar->Baseline) * m_yscale;\r\n\t\t\tu0 = pChar->u0;\r\n\t\t\tv0 = pChar->v0;\r\n\t\t\tu1 = pChar->u1;\r\n\t\t\tv1 = pChar->v1;\r\n\t\t\tx1 = x0+(((u1-u0)*p_font->m_width)*m_xscale);\r\n\t\t\ty1 = yt+(((v1-v0)*p_font->m_height)*m_yscale);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tx0 += (space_spacing + char_spacing);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif ( !uploaded && current_color.a )\r\n\t\t{\r\n\t\t\tuploaded = true;\r\n\t\t\t// Upload the texture & alpha map.\r\n\t\t\tGX::UploadTexture( p_font->mp_texture,\r\n\t\t\t\t\t\t\t   p_font->m_width,\r\n\t\t\t\t\t\t\t   p_font->m_height,\r\n\t\t\t\t\t\t\t   GX_TF_C8,\r\n\t\t\t\t\t\t\t   GX_CLAMP,\r\n\t\t\t\t\t\t\t   GX_CLAMP,\r\n\t\t\t\t\t\t\t   GX_FALSE,\r\n\t\t\t\t\t\t\t   GX_LINEAR,\r\n\t\t\t\t\t\t\t   GX_LINEAR,\r\n\t\t\t\t\t\t\t   0.0f,\r\n\t\t\t\t\t\t\t   0.0f,\r\n\t\t\t\t\t\t\t   0.0f,\r\n\t\t\t\t\t\t\t   GX_FALSE,\r\n\t\t\t\t\t\t\t   GX_FALSE,\r\n\t\t\t\t\t\t\t   GX_ANISO_1,\r\n\t\t\t\t\t\t\t   GX_TEXMAP0 );\r\n\r\n\t\t\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, p_font->m_width, p_font->m_height );\r\n\t\r\n\t\t\tGX::UploadPalette( p_font->mp_palette,\r\n\t\t\t\t\t\t\t   GX_TL_RGB5A3,\r\n\t\t\t\t\t\t\t   GX_TLUT_256,\r\n\t\t\t\t\t\t\t   GX_TEXMAP0 );\r\n\r\n//\t\t\tGXTexObj\ttexObj;\r\n//\t\t\tGXInitTexObjCI(\r\n//\t\t\t\t&texObj,\r\n//\t\t\t\tp_font->mp_texture,\r\n//\t\t\t\tp_font->m_width,\r\n//\t\t\t\tp_font->m_height,\r\n//\t\t\t\tGX_TF_C8,\r\n//\t\t\t\tGX_CLAMP,\r\n//\t\t\t\tGX_CLAMP,\r\n//\t\t\t\tGX_FALSE,\r\n//\t\t\t\tGX_TLUT0 );\r\n//\t\t\tGXInitTexObjLOD(&texObj, GX_LINEAR, GX_LINEAR, 0, 0, 0, 0, 0, GX_ANISO_1);\r\n//\t\t\tGXLoadTexObj( &texObj, GX_TEXMAP0 );\r\n//\t\r\n//\t\t\tGXTlutObj\tpalObj;\r\n//\t\t\tGXInitTlutObj( &palObj, p_font->mp_palette, GX_TL_RGB5A3, 16 );\r\n//\t\t\tGXLoadTlut ( &palObj, GX_TLUT0 );\r\n\t\r\n\t\r\n\t\t//\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP1 );       // Alpha map is in Green channel, so use this to swap it to the alpha channel.\r\n\t\t//\tGX::SetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP1, GX_COLOR0A0 );\r\n\t\t//\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\t//\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\t//\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO );\r\n\t\t//\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n\t\r\n\t\r\n\t\t\tGX::SetTexChanTevIndCull( 1, 1, 1, 0, GX_CULL_NONE );\r\n\t\t\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n\t\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\t\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_RASA, GX_CA_TEXA, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n\r\n\r\n\t\t//\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n\t\r\n\t\t\t// Set current vertex descriptor to enable position and color0.\r\n\t\t\t// Both use 8b index to access their data arrays.\r\n\t\t\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\t\r\n\t\t\t// Set material color.\r\n\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n\t\r\n\t\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\t\t}\r\n\r\n\t\tif ( current_color.a )\r\n\t\t{\r\n\t\t\tif ( new_color )\r\n\t\t\t{\r\n\t\t\t\tGX::SetChanAmbColor( GX_COLOR0A0, current_color );\r\n\t\t\t\tnew_color = false;\r\n\t\t\t}\r\n\t\t\t// Send coordinates.\r\n\t\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\t\t\tGX::Position3f32(x0, yt, -1.0f);\r\n\t\t\t\tGX::TexCoord2f32(u0, v0);\r\n\t\t\t\tGX::Position3f32(x1, yt, -1.0f);\r\n\t\t\t\tGX::TexCoord2f32(u1, v0);\r\n\t\t\t\tGX::Position3f32(x1, y1, -1.0f);\r\n\t\t\t\tGX::TexCoord2f32(u1, v1);\r\n\t\t\t\tGX::Position3f32(x0, y1, -1.0f);\r\n\t\t\t\tGX::TexCoord2f32(u0, v1);\r\n\t\t\tGX::End();\r\n\t\t}\r\n\r\n\t\tx0 = x1 + char_spacing;\r\n\r\n\t\tif (p_font != mp_font)\r\n\t\t{\r\n\t\t\t// we just used the button font, so return to the regular one\r\n\t\t\tuploaded = false;\r\n\t\t\t//EndDraw();\r\n\t\t\t//BeginDraw();\r\n\t\t}\r\n\t} // end for\r\n}\r\n\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SText::EndDraw( void )\r\n{\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nvoid SetTextWindow( uint16 x0, uint16 x1, uint16 y0, uint16 y1 )\r\n{\r\n\twx0 = (float)x0;\r\n\twy0 = (float)y0;\r\n\twx1 = (float)x1;\r\n\twy1 = (float)y1;\r\n//\tTextRegSCISSOR = (uint64)x0 | (uint64)x1<<16 | (uint64)y0<<32 | (uint64)y1<<48;\r\n}\r\n\r\nvoid SText::DrawSingle( void )\r\n{\r\n\tBeginDraw();\r\n\tDraw();\r\n\tEndDraw();\r\n}\r\n\r\n} // namespace Ngc\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/chars.h",
    "content": "#ifndef __CHARS_H\r\n#define __CHARS_H\r\n\r\n#include <gfx/Ngc/nx/sprite.h>\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n\r\ntypedef struct\r\n{\r\n\tfloat\tu0, v0, u1, v1;\r\n\tuint16\tw, h;\r\n\tuint16\tBaseline;\r\n}\r\nSChar;\r\n\r\n\r\nstruct SFont\r\n{\r\npublic:\r\n\tuint32\t\tGetDefaultHeight() const;\r\n\tuint32\t\tGetDefaultBase() const;\r\n\r\n//\tvoid\t\tBeginText(uint32 rgba, float Scale);\r\n//\tvoid\t\tDrawString(char *String, float x0, float y0);\r\n//\tvoid\t\tEndText(void);\r\n\tvoid\t\tQueryString(char *String, float &width, float &height);\r\n\r\n\t//char Name[16];\r\n\tuint32\t\tDefaultHeight, DefaultBase;\r\n\tSChar\t\t*pChars;\r\n\tuint8\t\tMap[256];\r\n\tuint8\t\tSpecialMap[32];\r\n//\tuint8\t\t*pVifData;\r\n//\tuint32\t\tVifSize;\r\n//\tuint64\t\tRegTEX0, RegTEX1;\r\n\tSFont\t\t*pNext;\r\n\r\n\tvoid*\t\tmp_texture;\r\n\tvoid*\t\tmp_palette;\r\n\tint\t\t\tm_width;\r\n\tint\t\t\tm_height;\r\n\r\n\tfloat\t\tmCharSpacing;\r\n\tfloat\t\tmSpaceSpacing;\r\n\tuint32\t\tmRGBATab[16];\r\n\r\n//\tIDirect3DTexture8*\tpD3DTexture;\t\t// To do - these should probably be replaced with an sTexture.\r\n//\tIDirect3DPalette8*\tpD3DPalette;\r\n};\r\n\r\n\r\n\r\nSFont *\t\tLoadFont( const char *Filename );\r\nvoid\t\tUnloadFont( SFont * );\r\nvoid\t\tSetTextWindow( uint16 x0, uint16 x1, uint16 y0, uint16 y1 );\r\n\r\n\r\nstruct SText : public SDraw2D\r\n{\r\n\tpublic:\r\n\t\t\t\t\tSText( float pri = 0.0f );\r\n\tvirtual\t\t\t~SText();\r\n\r\n\tvoid\t\t\tDrawSingle( void );\r\n\r\n\tSFont\t\t\t*mp_font;\r\n\r\n\tchar\t\t\t*mp_string;\r\n\tfloat\t\t\tm_xpos;\r\n\tfloat\t\t\tm_ypos;\r\n\tfloat\t\t\tm_xscale;\r\n\tfloat\t\t\tm_yscale;\r\n\tuint32\t\t\tm_rgba;\r\n\tbool\t\t\tm_color_override;\r\n\t\r\n\t// used in conjunction with BeginDraw()\r\n\t// if set, use specified font instead of mp_font\r\n\t// if not, use mp_font\r\n\tstatic SFont *\tspOverrideFont;\r\n\r\nprivate:\r\n\r\n\tvoid\t\t\tBeginDraw( void );\r\n\tvoid\t\t\tDraw( void );\r\n\tvoid\t\t\tEndDraw( void );\r\n};\r\n\r\nvoid SwizzleTexture( void *dstBuffer, void *srcBuffer, int width, int height, int32 depth, int32 stride );\r\n\r\nextern uint32 FontVramBase;\r\nextern SFont *pFontList;\r\nextern SFont *pButtonsFont;\r\n\r\n\r\n} // namespace NxNgc\r\n\r\n\r\n#endif // __CHARS_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/geomnode.cpp",
    "content": "///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n//**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//******************************************************************************\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tProject:\t\t<project name>\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tModule:\t\t\t<module name>\t\t\t \t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tFile name:\t\t<filename>.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tCreated by:\t\t00/00/00\t-\tinitials\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tDescription:\t<description>\t\t \t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//#include <core/defines.h>\r\n//#include <core/math.h>\r\n//#include \"render.h\"\r\n//#include \"geomnode.h\"\r\n//#include <gfx\\ngc\\nx\\nx_init.h>\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//namespace NxNgc\r\n//{\r\n//\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//CGeomNode CGeomNode::sWorld;\r\n//CGeomNode CGeomNode::sDatabase;\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//\r\n//CGeomNode::CGeomNode()\r\n//{\r\n//\tm_flags = 0;\r\n//\r\n//\tm_bounding_sphere[0] = 0.0f;\r\n//\tm_bounding_sphere[1] = 0.0f;\r\n//\tm_bounding_sphere[2] = 0.0f;\r\n//\tm_bounding_sphere[3] = (float)1.0e+30;\r\n//\r\n//\tmp_properties\t= NULL;\r\n//\tmp_child\t\t= NULL;\r\n//\tmp_sibling\t\t= NULL;\r\n//\tmp_dma\t\t\t= NULL;\r\n//\tmp_group\t\t= NULL;\r\n//}\r\n//\r\n//\r\n//void CGeomNode::Init()\r\n//{\r\n//\tm_flags = 0;\r\n//\r\n//\tm_bounding_sphere[0] = 0.0f;\r\n//\tm_bounding_sphere[1] = 0.0f;\r\n//\tm_bounding_sphere[2] = 0.0f;\r\n//\tm_bounding_sphere[3] = (float)1.0e+30;\r\n//\r\n//\tmp_properties\t= NULL;\r\n//\tmp_child\t\t= NULL;\r\n//\tmp_sibling\t\t= NULL;\r\n//\tmp_dma\t\t\t= NULL;\r\n//\tmp_group\t\t= NULL;\r\n//}\r\n//\r\n//\r\n//CGeomNode::CGeomNode(const CGeomNode &node)\r\n//{\r\n//\tm_flags\t\t\t\t= node.m_flags;\r\n//\tm_bounding_sphere\t= node.m_bounding_sphere;\r\n//\tmp_properties\t\t= node.mp_properties;\r\n//\tmp_child\t\t\t= node.mp_child;\r\n//\tmp_sibling\t\t\t= node.mp_sibling;\r\n//\tmp_dma\t\t\t\t= node.mp_dma;\r\n//\tmp_group\t\t\t= node.mp_group;\r\n//}\r\n//\r\n//\r\n//\r\n//\r\n//#define GET_FLAG(FLAG) (m_flags & (FLAG) ? true : false)\r\n//#define SET_FLAG(FLAG) m_flags = yes ? m_flags|FLAG : m_flags&~FLAG\r\n//\r\n//bool CGeomNode::IsLeaf()\r\n//{\r\n//\treturn GET_FLAG(NODEFLAG_LEAF);\r\n//}\r\n//\r\n//\r\n//bool CGeomNode::IsObject()\r\n//{\r\n//\treturn GET_FLAG(NODEFLAG_OBJECT);\r\n//}\r\n//\r\n//\r\n//bool CGeomNode::IsActive()\r\n//{\r\n//\treturn GET_FLAG(NODEFLAG_ACTIVE);\r\n//}\r\n//\r\n//\r\n//bool CGeomNode::IsTransformed()\r\n//{\r\n//\treturn GET_FLAG(NODEFLAG_TRANSFORMED);\r\n//}\r\n//\r\n//\r\n//void CGeomNode::SetLeaf(bool yes)\r\n//{\r\n//\tSET_FLAG(NODEFLAG_LEAF);\r\n//}\r\n//\r\n//\r\n//void CGeomNode::SetObject(bool yes)\r\n//{\r\n//\tSET_FLAG(NODEFLAG_OBJECT);\r\n//}\r\n//\r\n//\r\n//void CGeomNode::SetActive(bool yes)\r\n//{\r\n//\tSET_FLAG(NODEFLAG_ACTIVE);\r\n//}\r\n//\r\n//\r\n//void CGeomNode::SetTransformed(bool yes)\r\n//{\r\n//\tSET_FLAG(NODEFLAG_TRANSFORMED);\r\n//}\r\n//\r\n//\r\n//uint32 CGeomNode::GetChecksum()\r\n//{\r\n//\treturn m_checksum;\r\n//}\r\n//\r\n//\r\n//void CGeomNode::SetChecksum(uint32 checksum)\r\n//{\r\n//\tm_checksum = checksum;\r\n//}\r\n//\r\n//\r\n//void CGeomNode::SetBoundingSphere(float x, float y, float z, float R)\r\n//{\r\n//\tm_bounding_sphere[0] = x;\r\n//\tm_bounding_sphere[1] = y;\r\n//\tm_bounding_sphere[2] = z;\r\n//\tm_bounding_sphere[3] = R;\r\n//}\r\n//\r\n//\r\n//uint8 *CGeomNode::GetDma()\r\n//{\r\n//\treturn mp_dma;\r\n//}\r\n//\r\n//\r\n//void CGeomNode::SetDma(uint8 *pDma)\r\n//{\r\n//\tmp_dma = pDma;\r\n//}\r\n//\r\n//\r\n//CGeomNode *CGeomNode::GetChild()\r\n//{\r\n//\treturn mp_child;\r\n//}\r\n//\r\n//\r\n//void CGeomNode::SetChild(CGeomNode *pChild)\r\n//{\r\n//\tmp_child = pChild;\r\n//}\r\n//\r\n//\r\n//CGeomNode *CGeomNode::GetSibling()\r\n//{\r\n//\treturn mp_sibling;\r\n//}\r\n//\r\n//\r\n//void CGeomNode::SetSibling(CGeomNode *pSibling)\r\n//{\r\n//\tmp_sibling = pSibling;\r\n//}\r\n//\r\n//\r\n//sGroup *CGeomNode::GetGroup()\r\n//{\r\n//\treturn mp_group;\r\n//}\r\n//\r\n//\r\n//void CGeomNode::SetGroup(sGroup *pGroup)\r\n//{\r\n//\tmp_group = pGroup;\r\n//}\r\n//\r\n//\r\n//Mth::Matrix& CGeomNode::GetMatrix()\r\n//{\r\n//\tDbg_MsgAssert(IsTransformed(), (\"trying to access matrix of a non-transformed CGeomNode\"));\r\n//\tDbg_MsgAssert(mp_properties, (\"trying to access matrix of a CGeomNode which has no properties\"));\r\n//\treturn *((Mth::Matrix *)mp_properties);\r\n//}\r\n//\r\n//\r\n//void CGeomNode::SetMatrix(Mth::Matrix *p_mat)\r\n//{\r\n//\tmp_properties = (void *)p_mat;\r\n//\tSetTransformed(p_mat ? true : false);\r\n//}\r\n//\r\n//\r\n//void *CGeomNode::GetProperties()\r\n//{\r\n//\treturn mp_properties;\r\n//}\r\n//\r\n//\r\n//void CGeomNode::SetProperties(void *pProperties)\r\n//{\r\n//\tmp_properties = pProperties;\r\n//}\r\n//\r\n//\r\n//#ifdef __PLAT_WN32__\r\n//\r\n//void CGeomNode::Preprocess(uint8 *p_baseAddress)\r\n//{\r\n//\t// recursively process any children\r\n//\tCGeomNode *p_child, *p_sibling;\r\n//\tfor (p_child=mp_child; p_child; p_child=p_sibling)\r\n//\t{\r\n//\t\tp_sibling = p_child->mp_sibling;\r\n//\t\tp_child->Preprocess(p_baseAddress);\r\n//\t}\r\n//\r\n//\t// convert properties pointer to offset\r\n//\tif (mp_properties)\r\n//\t\tmp_properties = (void *) ( (uint8 *)mp_properties - p_baseAddress );\r\n//\telse\r\n//\t\tmp_properties = (void *)(-1);\r\n//\r\n//\t// convert dma pointer to offset\r\n//\tif (mp_dma)\r\n//\t\tmp_dma = (uint8 *)( mp_dma - p_baseAddress );\r\n//\telse\r\n//\t\tmp_dma = (uint8 *)(-1);\r\n//\r\n//\t// leave group ID alone\r\n//\r\n//\t// convert child pointer to offset\r\n//\tif (mp_child)\r\n//\t{\r\n//\t\tmp_child = (CGeomNode *) ( (uint8 *)mp_child - p_baseAddress );\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tmp_child = (CGeomNode *)(-1);\r\n//\t}\r\n//\r\n//\t// convert sibling pointer to offset\r\n//\tif (mp_sibling)\r\n//\t{\r\n//\t\tmp_sibling = (CGeomNode *) ( (uint8 *)mp_sibling - p_baseAddress );\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tmp_sibling = (CGeomNode *)(-1);\r\n//\t}\r\n//}\r\n//\r\n//#endif\r\n//\r\n//\r\n//\r\n//CGeomNode* CGeomNode::CreateInstance(Mth::Matrix *p_mat)\r\n//{\r\n//\t// copy node\r\n//\tCGeomNode *p_node = new CGeomNode(*this);\r\n//\r\n//\t// set matrix\r\n//\tp_node->SetMatrix(p_mat);\r\n//\r\n////\t// add to world\r\n////\tp_node->BecomesChildOf(&sWorld);\r\n////\r\n////\t// activate!\r\n////\tp_node->SetActive(true);\r\n//\r\n//\t// return new node\r\n//\treturn p_node;\r\n//}\r\n//\r\n//\r\n//void CGeomNode::DeleteInstance()\r\n//{\r\n////\tRemoveFrom(&sWorld);\r\n//\tdelete this;\r\n//}\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//\r\n//} // namespace NxNgc\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/geomnode.h",
    "content": "///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n//**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//******************************************************************************\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tProject:\t\tTHPS4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tModule:\t\t\tNxNgc\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tFile name:\t\tgeometry.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tCreated by:\t\t02/08/02\t-\tmrd\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tDescription:\tclasses for Ngc geometry\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//#ifndef __GFX_NGC_NX_GEOMETRY_H\r\n//#define __GFX_NGC_NX_GEOMETRY_H\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//\r\n//namespace NxNgc\r\n//{\r\n//\t// Forward declarations\r\n//\tstruct\tsGroup;\r\n//\r\n//\r\n//#define NODEFLAG_ACTIVE\t\t\t(1<<0)\r\n//#define NODEFLAG_LEAF\t\t\t(1<<1)\r\n//#define NODEFLAG_OBJECT\t\t\t(1<<2)\r\n//#define NODEFLAG_TRANSFORMED\t(1<<3)\r\n//#define NODEFLAG_COLOURED\t\t(1<<4)\r\n//\r\n//#define LOADFLAG_RENDERNOW\t\t(1<<0)\r\n//\r\n//// put these here temporarily\r\n//#define RENDERFLAG_CULL\t\t\t(1<<0)\r\n//#define RENDERFLAG_CLIP\t\t\t(1<<1)\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//struct STransformContext\r\n//{\r\n//\tMth::Matrix\tmatrix;\r\n//\tMth::Matrix\tadjustedMatrix;\r\n//\tMth::Vector\ttranslation;\r\n//};\r\n//\r\n//\r\n//class CGeomNode\r\n//{\r\n//public:\r\n//\r\n//\r\n//\r\n//\t#ifdef __PLAT_NGC__\r\n//\tvoid\t\t\t\tRender(STransformContext& transformContext, uint32 renderFlags);\r\n//\t#endif\r\n//\r\n//\tbool\t\t\t\tIsLeaf();\r\n//\tbool\t\t\t\tIsActive();\r\n//\tbool\t\t\t\tIsTransformed();\r\n//\tbool\t\t\t\tIsObject();\r\n//\r\n//\tvoid\t\t\t\tSetLeaf(bool yes);\r\n//\tvoid\t\t\t\tSetActive(bool yes);\r\n//\tvoid\t\t\t\tSetTransformed(bool yes);\r\n//\tvoid\t\t\t\tSetObject(bool yes);\r\n//\r\n//\tvoid\t\t\t\tSetChecksum(uint32 checksum);\r\n//\tvoid\t\t\t\tSetBoundingSphere(float x, float y, float z, float R);\t// change args to const Mth::Vector sphere\r\n//\tvoid\t\t\t\tSetDma(uint8 *pDma);\r\n//\tvoid\t\t\t\tSetChild(CGeomNode *pChild);\r\n//\tvoid\t\t\t\tSetSibling(CGeomNode *pSibling);\r\n//\tvoid\t\t\t\tSetGroup(sGroup *pGroup);\r\n//\tvoid\t\t\t\tSetMatrix(Mth::Matrix *p_mat);\r\n//\tvoid\t\t\t\tSetProperties(void *pProperties);\r\n//\r\n//\tuint32\t\t\t\tGetChecksum();\r\n//\tMth::Matrix&\t\tGetMatrix();\r\n//\tvoid*\t\t\t\tGetProperties();\r\n//\tCGeomNode*\t\t\tGetChild();\r\n//\tCGeomNode*\t\t\tGetSibling();\r\n//\tuint8*\t\t\t\tGetDma();\r\n//\tsGroup*\t\t\t\tGetGroup();\r\n//\r\n//\t#ifdef __PLAT_WN32__\r\n//\tvoid \t\t\t\tPreprocess(uint8 *p_baseAddress);\r\n//\t#endif\r\n//\r\n//\t#ifdef __PLAT_NGC__\r\n//\tstatic CGeomNode*\tsProcessInPlace(uint8 *pPipData, uint32 loadFlags);\r\n//\tvoid\t\t\t\tCleanup();\r\n//\t\r\n//\tCGeomNode*\t\t\tCreateInstance(Mth::Matrix *p_mat);\r\n//\tvoid\t\t\t\tDeleteInstance();\r\n//\tCGeomNode*\t\t\tCreateCopy();\r\n//\t#endif\r\n//\t\r\n//\tvoid\t\t\t\tInit();\r\n//\r\n//\t\t\t\t\t\tCGeomNode();\r\n//\t\t\t\t\t\tCGeomNode(const CGeomNode &node);\r\n//\t\t\t\t\t\t~CGeomNode() {}\r\n//\r\n//\r\n//\t\t\t\t\t\tstatic CGeomNode\tsWorld;\r\n//\t\t\t\t\t\tstatic CGeomNode\tsDatabase;\r\n//\r\n//\r\n//\r\n//private:\r\n//\r\n//\t#ifdef __PLAT_NGC__\r\n//\tbool\t\t\t\tIsOutsideViewVolume(Mth::Vector &s);\r\n//\tbool\t\t\t\tIsInsideOuterVolume(Mth::Vector &s);\r\n//\tbool\t\t\t\tNeedsClipping(Mth::Vector &s);\r\n//\r\n//\tvoid\t\t\t\tSendVu1Context(STransformContext& tc);\r\n//\tvoid\t\t\t\tLinkDma(uint8 *p_newTail);\r\n//\r\n//\tvoid \t\t\t\tProcessNodeInPlace(uint8 *p_baseAddress);\r\n//\r\n//\tvoid \t\t\t\tBecomesChildOf(CGeomNode *p_parent);\r\n//\tvoid\t\t\t\tRemoveFrom(CGeomNode *p_parent);\r\n//\r\n//\t#endif\r\n//\r\n//\tMth::Vector\t\t\tm_bounding_sphere;\r\n//\tuint32\t\t\t\tm_flags;\r\n//\tvoid *\t\t\t\tmp_properties;\r\n//\tCGeomNode *\t\t\tmp_child;\r\n//\tCGeomNode *\t\t\tmp_sibling;\r\n//\tuint8 *\t\t\t\tmp_dma;\r\n//\tsGroup *\t\t\tmp_group;\r\n//\tuint32\t\t\t\tm_checksum;\r\n//\tuint32\t\t\t\tpad[1];\r\n//};\r\n//\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//\r\n//} // namespace NxNgc\r\n//\r\n//#endif\t// __GFX_NGC_NX_GEOMETRY_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/grass.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// File: XBFur.cpp\r\n//\r\n// Desc: routines for generating and displaying a patch of fur,\r\n//       which is a series of layers that give the appearance of\r\n//       hair, fur, grass, or other fuzzy things.\r\n//\r\n// Copyright (c) Microsoft Corporation. All rights reserved.\r\n//-----------------------------------------------------------------------------\r\n#include <assert.h>\r\n#include <stdlib.h>\r\n#include <stdio.h>\r\n\r\n#include <core\\defines.h>\r\n#include <core\\crc.h>\r\n#include \"nx_init.h\"\r\n#include \"render.h\"\r\n#include \"grass.h\"\r\n//#include \"mipmap.h\"\r\n\r\n////extern LPDIRECT3DDEVICE8 NxNgc::EngineGlobals.p_Device;\r\n//\r\n//#define irand(a) ((rand()*(a))>>15)\r\n//#define frand(a) ((float)rand()*(a)/32768.0f)\r\n//\r\n//#define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }\r\n//\r\n//\r\n//float g_fOneInch = 0.01f;\r\n//\r\n//\r\n//extern CXBFur *p_fur;\r\n//\r\n//\r\n//\r\n//\r\n////-----------------------------------------------------------------------------\r\n//// Name: Constructor\r\n//// Desc: \r\n////-----------------------------------------------------------------------------\r\n//CXBFur::CXBFur()\r\n//{\r\n//    DWORD i;\r\n//    ZeroMemory(this, sizeof(CXBFur));\r\n//\r\n//    // init default patch\r\n//    m_fXSize = 0.1f;\r\n//    m_fZSize = 0.1f;\r\n//\r\n//    // init default fuzzlib\r\n//    m_dwNumFuzzLib = 0;\r\n//    m_pFuzzLib = NULL;\r\n//    m_fuzzCenter.colorBase = D3DXCOLOR(1.f, 1.f, 1.f, 1.f);\r\n//    m_fuzzCenter.colorTip = D3DXCOLOR(1.f, 1.f, 1.f, 0.f);\r\n//    m_fuzzCenter.dp.y = 1.0f;\r\n//\r\n//    // init default fuzz\r\n//    m_dwNumSegments = 4;\r\n//    m_pFuzz = NULL;\r\n//\r\n//    // init default volume\r\n//    m_dwNumSlices = 0;\r\n//    m_dwSliceXSize = 0;\r\n//    m_dwSliceZSize = 0;\r\n//    for(i=0; i<XBFUR_MAXSLICE*2-1; i++)\r\n//        m_apSliceTexture[i] = NULL;\r\n//    m_pHairLightingTexture = NULL;\r\n//    m_pFinTexture = NULL;\r\n//    m_dwNumSlicesLOD = 0;\r\n//    m_pSliceTextureLOD = m_apSliceTexture;\r\n//    \r\n//    InitFuzz(1, 1);\r\n//}\r\n//\r\n////-----------------------------------------------------------------------------\r\n//// Name: Destructor\r\n//// Desc: \r\n////-----------------------------------------------------------------------------\r\n//CXBFur::~CXBFur()\r\n//{\r\n//    DWORD i;\r\n//    if(m_pFuzzLib)\r\n//        delete m_pFuzzLib;\r\n//    if(m_pFuzz)\r\n//        delete m_pFuzz;\r\n//    for(i=0; i<XBFUR_MAXSLICE*2-1; i++)\r\n//        SAFE_RELEASE(m_apSliceTexture[i]);\r\n//    SAFE_RELEASE(m_pHairLightingTexture);\r\n//}\r\n//\r\n////-----------------------------------------------------------------------------\r\n//// Name: InitFuzz\r\n//// Desc: Initializes the individual strands of fuzz in the patch.\r\n////       Only a small number of individual fuzzes are generated\r\n////       (determined by m_dwNumFuzzLib) because each one in the patch\r\n////       does not need to be unique.\r\n////-----------------------------------------------------------------------------\r\n//void CXBFur::InitFuzz(DWORD nfuzz, DWORD nfuzzlib)\r\n//{\r\n//    DWORD i;\r\n//    float y;\r\n//\r\n//    if(nfuzz<=0 || nfuzzlib<0)\r\n//        return;\r\n//        \r\n//    // handle memory allocation\r\n//    if(m_dwNumFuzz!=nfuzz)                // if nfuzz has changed\r\n//    {\r\n//        if(m_pFuzz)\r\n//            delete m_pFuzz;                // nuke existing\r\n//        m_pFuzz = new FuzzInst[nfuzz];    // and get new fuzz memory\r\n//    }\r\n//\r\n//    if(m_dwNumFuzzLib!=nfuzzlib)\r\n//    {\r\n//        if(m_pFuzzLib)\r\n//            delete m_pFuzzLib;\r\n//\r\n//        m_pFuzzLib = new Fuzz[nfuzzlib];\r\n//    }\r\n//\r\n//    m_dwNumFuzz = nfuzz;\r\n//    m_dwNumFuzzLib = nfuzzlib;\r\n//\r\n//    // generate the individual fuzzes in the library\r\n//    m_fYSize = 0.0f;\r\n//    srand(m_dwSeed);\r\n//    for(i=0; i<m_dwNumFuzzLib; i++)\r\n//    {\r\n//        m_pFuzzLib[i].dp.x = (m_fuzzCenter.dp.x + m_fuzzRandom.dp.x*(2*frand(1.0f)-1.0f))*g_fOneInch;\r\n//        m_pFuzzLib[i].dp.y = (m_fuzzCenter.dp.y + m_fuzzRandom.dp.y*(2*frand(1.0f)-1.0f))*g_fOneInch;\r\n//        m_pFuzzLib[i].dp.z = (m_fuzzCenter.dp.z + m_fuzzRandom.dp.z*(2*frand(1.0f)-1.0f))*g_fOneInch;\r\n//\r\n//        m_pFuzzLib[i].ddp.x = (m_fuzzCenter.ddp.x + m_fuzzRandom.ddp.x*(2*frand(1.0f)-1.0f))*g_fOneInch;\r\n//        m_pFuzzLib[i].ddp.y = (m_fuzzCenter.ddp.y + m_fuzzRandom.ddp.y*(2*frand(1.0f)-1.0f))*g_fOneInch;\r\n//        m_pFuzzLib[i].ddp.z = (m_fuzzCenter.ddp.z + m_fuzzRandom.ddp.z*(2*frand(1.0f)-1.0f))*g_fOneInch;\r\n//\r\n//        m_pFuzzLib[i].colorBase = m_fuzzCenter.colorBase + (2*frand(1.f)-1.f)*m_fuzzRandom.colorBase;\r\n//        m_pFuzzLib[i].colorTip = m_fuzzCenter.colorTip + (2*frand(1.f)-1.f)*m_fuzzRandom.colorTip;\r\n//\r\n//        y = m_pFuzzLib[i].dp.y + 0.5f*m_pFuzzLib[i].ddp.y;\r\n//        if(y>m_fYSize)\r\n//            m_fYSize = y;\r\n//    }\r\n//\r\n//     // initialize the fuzz locations & pick a random fuzz from the library\r\n//    srand(m_dwSeed*54795);\r\n//    for(i=0; i<m_dwNumFuzz; i++)\r\n//    {\r\n//        m_pFuzz[i].x = (frand(1.0f)-0.5f)*m_fXSize;\r\n//        m_pFuzz[i].z = (frand(1.0f)-0.5f)*m_fZSize;\r\n//        m_pFuzz[i].lidx = irand(m_dwNumFuzzLib);\r\n//    }\r\n//}\r\n//\r\n////-----------------------------------------------------------------------------\r\n//// Name: GenSlices\r\n//// Desc: Generate the fuzz volume by rendering the geometry repeatedly\r\n////       with different z-clip ranges.\r\n////-----------------------------------------------------------------------------\r\n//void CXBFur::GenSlices( DWORD nslices, DWORD slicexsize, DWORD slicezsize )\r\n//{\r\n//\tassert(nslices <= XBFUR_MAXSLICE);\r\n//    \r\n//    // Check the format of the textures\r\n//    bool bFormatOK = true;\r\n//    if (m_dwNumSlices > 0)\r\n//    {\r\n//        D3DSURFACE_DESC desc;\r\n//        m_apSliceTexture[0]->GetLevelDesc(0, &desc);\r\n//        if (desc.Format != D3DFMT_A8R8G8B8)\r\n//            bFormatOK = false;\r\n//    }\r\n//\r\n//    // make sure volume info is up to date\r\n//    if(m_dwSliceXSize!=slicexsize \r\n//       || m_dwSliceZSize!=slicezsize\r\n//       || !bFormatOK)\r\n//    {\r\n//        m_dwNumSlices = 0;\r\n//        m_dwNumSlicesLOD = 0;\r\n//        for(UINT i=0; i<XBFUR_MAXSLICE*2-1; i++)\r\n//            SAFE_RELEASE(m_apSliceTexture[i]);\r\n//    }\r\n//\r\n//    m_dwSliceXSize = slicexsize;\r\n//    m_dwSliceZSize = slicezsize;\r\n//    m_dwSliceSize = slicexsize*slicezsize;\r\n//\r\n//    // create textures if necessary\r\n//    if(m_dwNumSlices!=nslices)\r\n//    {\r\n//        UINT i;\r\n//        // count number of level-of-detail layers needed\r\n//        UINT nLOD = 0;\r\n//        for (i = 1; (1u << i) <= nslices; i++)\r\n//            nLOD += nslices >> i;\r\n//        m_dwLODMax = i - 1;\r\n//\r\n//        // create new layers and level-of-detail layers\r\n//        for(i=0; i<nslices+nLOD; i++)\r\n//            if(!m_apSliceTexture[i])\r\n//                NxNgc::EngineGlobals.p_Device->CreateTexture(slicexsize, slicezsize, 0, 0, D3DFMT_A8R8G8B8, 0, &m_apSliceTexture[i]);\r\n//            \r\n//        // release unused layers\r\n//        for(i=nslices+nLOD; i<XBFUR_MAXSLICE*2-1; i++)\r\n//            SAFE_RELEASE(m_apSliceTexture[i]);\r\n//\r\n//    }\r\n//    m_dwNumSlices = nslices;\r\n//\r\n//    // save current back buffer, z buffer, and transforms\r\n//    struct {\r\n//        IDirect3DSurface8 *pBackBuffer, *pZBuffer;\r\n//        D3DMATRIX matWorld, matView, matProjection;\r\n//    } save;\r\n//    NxNgc::EngineGlobals.p_Device->GetRenderTarget(&save.pBackBuffer);\r\n//    NxNgc::EngineGlobals.p_Device->GetDepthStencilSurface(&save.pZBuffer);\r\n//    NxNgc::EngineGlobals.p_Device->GetTransform( D3DTS_WORLD, &save.matWorld);\r\n//    NxNgc::EngineGlobals.p_Device->GetTransform( D3DTS_VIEW, &save.matView);\r\n//    NxNgc::EngineGlobals.p_Device->GetTransform( D3DTS_PROJECTION, &save.matProjection);\r\n//        \r\n//    // make a new depth buffer\r\n//    IDirect3DSurface8 *pZBuffer = NULL;\r\n//    NxNgc::EngineGlobals.p_Device->CreateDepthStencilSurface(slicexsize, slicezsize, D3DFMT_LIN_D24S8, D3DMULTISAMPLE_NONE, &pZBuffer);\r\n//    D3DXVECTOR3 va(-0.5f*m_fXSize, 0.f, -0.5f*m_fZSize), vb(0.5f*m_fXSize, m_fYSize, 0.5f*m_fZSize); // bounds of fuzz patch\r\n//    D3DXVECTOR3 vwidth(vb-va), vcenter(0.5f*(vb+va)); // width and center of fuzz patch\r\n//        \r\n//    // set world transformation to scale model to unit cube [-1,1] in all dimensions\r\n//    D3DXMATRIX matWorld, matTranslate, matScale;\r\n//    D3DXMatrixTranslation(&matTranslate, -vcenter.x, -vcenter.y, -vcenter.z);\r\n//    D3DXMatrixScaling(&matScale, 2.f/vwidth.x, 2.f/vwidth.y, 2.f/vwidth.z);\r\n//    matWorld = matTranslate * matScale;\r\n//    NxNgc::EngineGlobals.p_Device->SetTransform( D3DTS_WORLD, &matWorld);\r\n//        \r\n//    // set view transformation to flip z and look down y axis, with bottom-most slice scaled and translated to map to [0,1]\r\n//    D3DMATRIX matView;\r\n//    matView.m[0][0] = 1.f;    matView.m[0][1] =  0.f;    matView.m[0][2] = 0.f;                matView.m[0][3] = 0.f;\r\n//    matView.m[1][0] = 0.f;    matView.m[1][1] =  0.f;    matView.m[1][2] = 0.5f * nslices;    matView.m[1][3] = 0.f;\r\n//    matView.m[2][0] = 0.f;    matView.m[2][1] = -1.f;    matView.m[2][2] = 0.f;                matView.m[2][3] = 0.f;\r\n//    matView.m[3][0] = 0.f;    matView.m[3][1] =  0.f;    matView.m[3][2] = 0.5f * nslices;    matView.m[3][3] = 1.f;\r\n//        \r\n//    // set projection matrix to orthographic\r\n//    D3DXMATRIX matProjection;\r\n//    D3DXMatrixIdentity(&matProjection);\r\n//    NxNgc::EngineGlobals.p_Device->SetTransform( D3DTS_PROJECTION, &matProjection);\r\n//    UINT numLines = m_dwNumFuzz*m_dwNumSegments;\r\n//    IDirect3DVertexBuffer8 *pVB;\r\n//    GetLinesVertexBuffer(&pVB);\r\n//    NxNgc::EngineGlobals.p_Device->SetTexture(0, NULL);\r\n//    NxNgc::EngineGlobals.p_Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);\r\n//    NxNgc::EngineGlobals.p_Device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);\r\n//    NxNgc::EngineGlobals.p_Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); // premultiplied alpha\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_LIGHTING, FALSE);\r\n//\r\n//    NxNgc::EngineGlobals.p_Device->SetPixelShader( 0 );\r\n//    NxNgc::EngineGlobals.p_Device->SetVertexShader(FVF_XYZDIFF);\r\n//    NxNgc::EngineGlobals.p_Device->SetStreamSource(0, pVB, sizeof(FVFT_XYZDIFF));\r\n//        \r\n//    // draw each slice\r\n//    for (int i = 0; i < (int)nslices; i++)\r\n//    {\r\n//        // get destination surface & set as render target, then draw the fuzz slice\r\n//        LPDIRECT3DTEXTURE8 pTexture = m_apSliceTexture[i];\r\n//        IDirect3DSurface8 *pSurface;\r\n//        pTexture->GetSurfaceLevel(0, &pSurface);\r\n//        NxNgc::EngineGlobals.p_Device->SetRenderTarget(pSurface, pZBuffer);\r\n//        NxNgc::EngineGlobals.p_Device->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, D3DCOLOR_RGBA(0x10,0x20,0x10,0), 1.0f, 0 );\r\n//        matView.m[1][2] = 0.5f * nslices;\r\n//        matView.m[3][2] = 0.5f * nslices - (float)i;    // offset to next slice\r\n//        \r\n//        // We want the texture to wrap, so draw multiple times with offsets in the plane so that \r\n//        // the boundaries will be filled in by the overlapping geometry.\r\n//        for (int iX = -1; iX <= 1; iX++)\r\n//        {\r\n//            for (int iY = -1; iY <= 1; iY++)\r\n//            {\r\n//                matView.m[3][0] = 2.f * iX;\r\n//                matView.m[3][1] = 2.f * iY;\r\n//                NxNgc::EngineGlobals.p_Device->SetTransform( D3DTS_VIEW, &matView);\r\n//                NxNgc::EngineGlobals.p_Device->DrawPrimitive(D3DPT_LINELIST, 0, numLines);\r\n//            }\r\n//        }\r\n//        pSurface->Release();\r\n//        GenerateMipmaps(pTexture, 0);\r\n//    }\r\n//    \r\n//    // clean up\r\n//    pVB->Release();\r\n//    pZBuffer->Release();\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderTarget(save.pBackBuffer, save.pZBuffer);\r\n//    save.pBackBuffer->Release();\r\n//    save.pZBuffer->Release();\r\n//    NxNgc::EngineGlobals.p_Device->SetTransform( D3DTS_WORLD, &save.matWorld);\r\n//    NxNgc::EngineGlobals.p_Device->SetTransform( D3DTS_VIEW, &save.matView);\r\n//    NxNgc::EngineGlobals.p_Device->SetTransform( D3DTS_PROJECTION, &save.matProjection);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_LIGHTING, TRUE);\r\n//\r\n//\r\n//\t// Compress the textures.\r\n//\tfor( int i = 0; i < (int)nslices; i++ )\r\n//    {\r\n//\t\tLPDIRECT3DTEXTURE8 pTextureSrc = m_apSliceTexture[i];\r\n//        LPDIRECT3DTEXTURE8 pTextureDst = NULL;\r\n//\t\tCompressTexture( &pTextureDst, D3DFMT_DXT4, pTextureSrc );\r\n//\t\tm_apSliceTexture[i] = pTextureDst;\r\n//\t\tpTextureSrc->Release();\r\n//\t}\r\n//}\r\n//\r\n////-----------------------------------------------------------------------------\r\n//// Name: GenFin\r\n//// Desc: Generate the fin texture in a similar way as GenSlices.\r\n////-----------------------------------------------------------------------------\r\n//void CXBFur::GenFin(DWORD finWidth, DWORD finHeight, float fFinXFraction, float fFinZFraction)\r\n//{\r\n//    m_fFinXFraction = fFinXFraction;\r\n//    m_fFinZFraction = fFinZFraction;\r\n//\r\n//    // Check the format of the textures\r\n//    bool bFormatOK = true;\r\n//    if (m_pFinTexture != NULL)\r\n//    {\r\n//        D3DSURFACE_DESC desc;\r\n//        m_pFinTexture->GetLevelDesc(0, &desc);\r\n//        if (desc.Format != D3DFMT_A8R8G8B8)\r\n//            bFormatOK = false;\r\n//    }\r\n//\r\n//    // make sure fin info is up to date\r\n//    if(m_finWidth != finWidth\r\n//       || m_finHeight != finHeight\r\n//       || !bFormatOK)\r\n//    {\r\n//        SAFE_RELEASE(m_pFinTexture);\r\n//    }\r\n//    m_finWidth = finWidth;\r\n//    m_finHeight = finHeight;\r\n//\r\n//    // create fin texture if needed\r\n//    if (m_pFinTexture == NULL)\r\n//        NxNgc::EngineGlobals.p_Device->CreateTexture(finWidth, finHeight, 0, 0, D3DFMT_A8R8G8B8, 0, &m_pFinTexture);\r\n//\r\n//    // save current back buffer, z buffer, and transforms\r\n//    struct {\r\n//        IDirect3DSurface8 *pBackBuffer, *pZBuffer;\r\n//        D3DMATRIX matWorld, matView, matProjection;\r\n//    } save;\r\n//    NxNgc::EngineGlobals.p_Device->GetRenderTarget(&save.pBackBuffer);\r\n//    NxNgc::EngineGlobals.p_Device->GetDepthStencilSurface(&save.pZBuffer);\r\n//    NxNgc::EngineGlobals.p_Device->GetTransform( D3DTS_WORLD, &save.matWorld);\r\n//    NxNgc::EngineGlobals.p_Device->GetTransform( D3DTS_VIEW, &save.matView);\r\n//    NxNgc::EngineGlobals.p_Device->GetTransform( D3DTS_PROJECTION, &save.matProjection);\r\n//\r\n//    // make a new depth buffer\r\n//    IDirect3DSurface8 *pZBuffer = NULL;\r\n//    NxNgc::EngineGlobals.p_Device->CreateDepthStencilSurface(finWidth, finHeight, D3DFMT_LIN_D24S8, D3DMULTISAMPLE_NONE, &pZBuffer);\r\n//    D3DXVECTOR3 va(-0.5f*m_fXSize, 0.f, -0.5f*m_fZSize), vb(0.5f*m_fXSize, m_fYSize, 0.5f*m_fZSize); // bounds of fuzz patch\r\n//    D3DXVECTOR3 vwidth(vb-va), vcenter(0.5f*(vb+va)); // width and center of fuzz patch\r\n//\r\n//    // set world transformation to scale model to unit cube [-1,1] in all dimensions\r\n//    D3DXMATRIX matWorld, matTranslate, matScale;\r\n//    D3DXMatrixTranslation(&matTranslate, -vcenter.x, -vcenter.y, -vcenter.z);\r\n//    D3DXMatrixScaling(&matScale, 2.f/vwidth.x, 2.f/vwidth.y, 2.f/vwidth.z);\r\n//    matWorld = matTranslate * matScale;\r\n//    NxNgc::EngineGlobals.p_Device->SetTransform( D3DTS_WORLD, &matWorld);\r\n//\r\n//    // set view transformation to look down z axis, with z range [0,1]\r\n//    float fXFraction = m_fFinXFraction;\r\n//    float fYFraction = 1.f;\r\n//    float fZFraction = m_fFinZFraction; \r\n//    float fXScale = 1.f / fXFraction;\r\n//    float fYScale = 1.f / fYFraction;\r\n//    float fZScale = 1.f / fZFraction;\r\n//    D3DMATRIX matView;\r\n//    matView.m[0][0] = fXScale;    matView.m[0][1] =  0.f;        matView.m[0][2] = 0.f;                matView.m[0][3] = 0.f;\r\n//    matView.m[1][0] = 0.f;        matView.m[1][1] = -fYScale;    matView.m[1][2] = 0.f;                matView.m[1][3] = 0.f;\r\n//    matView.m[2][0] = 0.f;        matView.m[2][1] =  0.f;        matView.m[2][2] = 0.5f * fZScale;    matView.m[2][3] = 0.f;\r\n//    matView.m[3][0] = 0.f;        matView.m[3][1] =  0.f;     matView.m[3][2] = 0.5f * fZScale;    matView.m[3][3] = 1.f;\r\n//    NxNgc::EngineGlobals.p_Device->SetTransform( D3DTS_VIEW, &matView);\r\n//    // set projection matrix to orthographic\r\n//\r\n//    D3DXMATRIX matProjection;\r\n//    D3DXMatrixIdentity(&matProjection);\r\n//    NxNgc::EngineGlobals.p_Device->SetTransform( D3DTS_PROJECTION, &matProjection);\r\n//    UINT numLines = m_dwNumFuzz*m_dwNumSegments;\r\n//    IDirect3DVertexBuffer8 *pVB;\r\n//    GetLinesVertexBuffer(&pVB);\r\n//    NxNgc::EngineGlobals.p_Device->SetTexture(0, NULL);\r\n//    NxNgc::EngineGlobals.p_Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);\r\n//    NxNgc::EngineGlobals.p_Device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);\r\n//    NxNgc::EngineGlobals.p_Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); // premultiplied alpha\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_LIGHTING, FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetVertexShader(FVF_XYZDIFF);\r\n//    NxNgc::EngineGlobals.p_Device->SetStreamSource(0, pVB, sizeof(FVFT_XYZDIFF));\r\n//    \r\n//    // draw fuzz into the fin texture, looking from the side\r\n//    LPDIRECT3DTEXTURE8 pTexture = m_pFinTexture;\r\n//    IDirect3DSurface8 *pSurface;\r\n//    pTexture->GetSurfaceLevel(0, &pSurface);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderTarget(pSurface, pZBuffer);\r\n//    NxNgc::EngineGlobals.p_Device->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, \r\n//                         D3DCOLOR_RGBA(0,0,0,0), 1.0f, 0 );\r\n//    NxNgc::EngineGlobals.p_Device->DrawPrimitive(D3DPT_LINELIST, 0, numLines);\r\n//    pSurface->Release();\r\n//    GenerateMipmaps(pTexture, 0, D3DTADDRESS_WRAP, D3DTADDRESS_CLAMP);\r\n//\r\n//    // clean up\r\n//    pVB->Release();\r\n//    pZBuffer->Release();\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderTarget(save.pBackBuffer, save.pZBuffer);\r\n//    save.pBackBuffer->Release();\r\n//    save.pZBuffer->Release();\r\n//    NxNgc::EngineGlobals.p_Device->SetTransform( D3DTS_WORLD, &save.matWorld);\r\n//    NxNgc::EngineGlobals.p_Device->SetTransform( D3DTS_VIEW, &save.matView);\r\n//    NxNgc::EngineGlobals.p_Device->SetTransform( D3DTS_PROJECTION, &save.matProjection);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_LIGHTING, TRUE);\r\n//}\r\n//\r\n////-----------------------------------------------------------------------------\r\n//// Name: GetLinesVertexBuffer\r\n//// Desc: Create and fill in a vertex buffer as a series of individual lines from the fuzz library.\r\n////-----------------------------------------------------------------------------\r\n//void CXBFur::GetLinesVertexBuffer(IDirect3DVertexBuffer8 **ppVB)\r\n//{\r\n//    IDirect3DVertexBuffer8 *pVB;\r\n//    UINT numVertices = m_dwNumFuzz*m_dwNumSegments*2;\r\n//    NxNgc::EngineGlobals.p_Device->CreateVertexBuffer(numVertices*sizeof(FVFT_XYZDIFF), 0, FVF_XYZDIFF, 0, &pVB);\r\n//    assert(pVB!=NULL);\r\n//    DWORD i, j, vidx, lidx;\r\n//    FVFT_XYZDIFF *verts;\r\n//    float x0, y0, z0;\r\n//    float dx, dy, dz;\r\n//    float ddx, ddy, ddz;\r\n//    float step, cp;\r\n//    UINT startseg = 0;\r\n//    step = 1.0f/(float)m_dwNumSegments;\r\n//    pVB->Lock(0, numVertices*sizeof(FVFT_XYZDIFF), (BYTE **)&verts, 0);\r\n//    vidx = 0;\r\n//    D3DXCOLOR colorBase, colorDelta;\r\n//    for(i=0; i<m_dwNumFuzz; i++)\r\n//    {\r\n//        // get location and index from fuzz instances\r\n//        lidx = m_pFuzz[i].lidx;\r\n//        x0 = m_pFuzz[i].x;\r\n//        y0 = 0.0f;\r\n//        z0 = m_pFuzz[i].z;\r\n//\r\n//        // get params from fuzz lib\r\n//        dx = m_pFuzzLib[lidx].dp.x;\r\n//        dy = m_pFuzzLib[lidx].dp.y;\r\n//        dz = m_pFuzzLib[lidx].dp.z;\r\n//        ddx = m_pFuzzLib[lidx].ddp.x;\r\n//        ddy = m_pFuzzLib[lidx].ddp.y;\r\n//        ddz = m_pFuzzLib[lidx].ddp.z;\r\n//        colorBase = m_pFuzzLib[lidx].colorBase;\r\n//        colorDelta = m_pFuzzLib[lidx].colorTip - colorBase;\r\n//\r\n//        // build linelist\r\n//        cp = (float)startseg*step;\r\n//        D3DXCOLOR color;\r\n//        for(j=startseg; j<m_dwNumSegments; j++)\r\n//        {\r\n//            verts[vidx].v.x = x0 + cp*dx + 0.5f*cp*cp*ddx;\r\n//            verts[vidx].v.y = y0 + cp*dy + 0.5f*cp*cp*ddy;\r\n//            verts[vidx].v.z = z0 + cp*dz + 0.5f*cp*cp*ddz;\r\n//            color = colorBase + cp * cp * colorDelta;\r\n//            verts[vidx].diff = color;\r\n//            vidx++;\r\n//            cp += step;\r\n//\r\n//            verts[vidx].v.x = x0 + cp*dx + 0.5f*cp*cp*ddx;\r\n//            verts[vidx].v.y = y0 + cp*dy + 0.5f*cp*cp*ddy;\r\n//            verts[vidx].v.z = z0 + cp*dz + 0.5f*cp*cp*ddz;\r\n//            color = colorBase + cp * cp * colorDelta;\r\n//            verts[vidx].diff = color;\r\n//            vidx++;\r\n//        }\r\n//    }\r\n//    pVB->Unlock();\r\n//    *ppVB = pVB;\r\n//}\r\n//\r\n////-----------------------------------------------------------------------------\r\n//// Name: RenderLines\r\n//// Desc: Draw the fuzz patch as a series of individual lines.\r\n////-----------------------------------------------------------------------------\r\n//void CXBFur::RenderLines()\r\n//{\r\n//    UINT numLines = m_dwNumFuzz*m_dwNumSegments;\r\n//    IDirect3DVertexBuffer8 *pVB;\r\n//    GetLinesVertexBuffer(&pVB);\r\n//    NxNgc::EngineGlobals.p_Device->SetTexture(0, NULL);\r\n//    NxNgc::EngineGlobals.p_Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);\r\n//    NxNgc::EngineGlobals.p_Device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);\r\n//    NxNgc::EngineGlobals.p_Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); // premultiplied alpha\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_LIGHTING, FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetVertexShader(FVF_XYZDIFF);\r\n//    NxNgc::EngineGlobals.p_Device->SetStreamSource(0, pVB, sizeof(FVFT_XYZDIFF));\r\n//    NxNgc::EngineGlobals.p_Device->DrawPrimitive(D3DPT_LINELIST, 0, numLines);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_LIGHTING, TRUE);\r\n//    pVB->Release();\r\n//}\r\n//\r\n//\r\n//\r\n//#if 0\r\n//\r\n////-----------------------------------------------------------------------------\r\n//// Desc: File routines for saving and loading patch files.\r\n////       Saving is only relevant if used on a Windows platform.\r\n////-----------------------------------------------------------------------------\r\n//struct _fphdr\r\n//{\r\n//    char sig[5];\r\n//    int flags;\r\n//};\r\n//\r\n//void CXBFur::Save(char *fname, int flags)\r\n//{\r\n//    HANDLE hFile;\r\n//    struct _fphdr hdr;\r\n//\r\n//    DWORD dwNumBytesWritten;\r\n//    hFile = CreateFile(fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,\r\n//                       OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\r\n//    if(hFile == INVALID_HANDLE_VALUE)\r\n//        return;\r\n//\r\n//    // write file header\r\n//    strcpy(hdr.sig, \"FUZ2\");\r\n//    hdr.flags = flags;\r\n//\r\n//    WriteFile(hFile, &hdr, sizeof(struct _fphdr), &dwNumBytesWritten, NULL);\r\n//    \r\n//\r\n//    // write fpatch data\r\n//    WriteFile(hFile, &m_dwSeed, sizeof(DWORD), &dwNumBytesWritten, NULL);\r\n//    \r\n//    WriteFile(hFile, &m_fXSize, sizeof(float), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_fYSize, sizeof(float), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_fZSize, sizeof(float), &dwNumBytesWritten, NULL);\r\n//\r\n//    WriteFile(hFile, &m_dwNumSegments, sizeof(DWORD), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_fFinXFraction, sizeof(float), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_fFinZFraction, sizeof(float), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_fuzzCenter.colorBase, sizeof(D3DXCOLOR), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_fuzzRandom.colorBase, sizeof(D3DXCOLOR), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_fuzzCenter.colorTip, sizeof(D3DXCOLOR), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_fuzzRandom.colorTip, sizeof(D3DXCOLOR), &dwNumBytesWritten, NULL);\r\n//    \r\n//    WriteFile(hFile, &m_fuzzCenter.dp, sizeof(D3DVECTOR), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_fuzzRandom.dp, sizeof(D3DVECTOR), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_fuzzCenter.ddp, sizeof(D3DVECTOR), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_fuzzRandom.ddp, sizeof(D3DVECTOR), &dwNumBytesWritten, 0);\r\n//\r\n//    WriteFile(hFile, &m_dwNumFuzzLib, sizeof(DWORD), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_dwNumFuzz, sizeof(DWORD), &dwNumBytesWritten, NULL);\r\n//\r\n//    WriteFile(hFile, &m_dwNumSlices, sizeof(DWORD), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_dwSliceXSize, sizeof(DWORD), &dwNumBytesWritten, NULL);\r\n//    WriteFile(hFile, &m_dwSliceZSize, sizeof(DWORD), &dwNumBytesWritten, NULL);\r\n//    \r\n//    return;\r\n//\r\n//\r\n//\r\n//    // write volume data if available and flag is set\r\n//    {\r\n//    }\r\n//\r\n//    // cleanup\r\n//    CloseHandle(hFile);\r\n//}\r\n//\r\n//void CXBFur::Load(char *fname)\r\n//{\r\n//    HANDLE hFile;\r\n//    struct _fphdr hdr;\r\n//    DWORD numfuzzlib, numfuzz;\r\n//    DWORD numslices, slicexsize, slicezsize;\r\n//\r\n//    DWORD dwNumBytesRead;\r\n//    hFile = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL,\r\n//                       OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);\r\n//    if(hFile == INVALID_HANDLE_VALUE)\r\n//        return;\r\n//    \r\n//    // read file header\r\n//    ReadFile(hFile, &hdr, sizeof(struct _fphdr), &dwNumBytesRead, 0);\r\n//\r\n//    // verify signature\r\n//    bool bFUZ1 = !strcmp(hdr.sig, \"FUZ1\");\r\n//    bool bFUZ2 = !strcmp(hdr.sig, \"FUZ2\");\r\n//    if (!bFUZ1 && !bFUZ2)\r\n//        return;    // signature not understood\r\n//\r\n//    // read patch data\r\n//\r\n//    ReadFile(hFile, &m_dwSeed, sizeof(DWORD), &dwNumBytesRead, NULL);\r\n//    ReadFile(hFile, &m_fXSize, sizeof(float), &dwNumBytesRead, NULL);\r\n//    ReadFile(hFile, &m_fYSize, sizeof(float), &dwNumBytesRead, NULL);\r\n//    ReadFile(hFile, &m_fZSize, sizeof(float), &dwNumBytesRead, NULL);\r\n//    \r\n//\r\n//    ReadFile(hFile, &m_dwNumSegments, sizeof(DWORD), &dwNumBytesRead, NULL);\r\n//    \r\n//    if (bFUZ1)\r\n//    {\r\n//        m_fFinXFraction = 1.f;\r\n//        m_fFinZFraction = 0.05f;\r\n//\r\n//        ReadFile(hFile, &m_fuzzCenter.colorBase, sizeof(D3DXCOLOR), &dwNumBytesRead, NULL);\r\n//        m_fuzzCenter.colorTip = m_fuzzCenter.colorBase;\r\n//        m_fuzzRandom.colorBase = m_fuzzRandom.colorTip = 0ul;\r\n//    }\r\n//    else\r\n//    {\r\n//\r\n//        ReadFile(hFile, &m_fFinXFraction, sizeof(float), &dwNumBytesRead, NULL);\r\n//        ReadFile(hFile, &m_fFinZFraction, sizeof(float), &dwNumBytesRead, NULL);\r\n//        ReadFile(hFile, &m_fuzzCenter.colorBase, sizeof(D3DXCOLOR), &dwNumBytesRead, NULL);\r\n//        ReadFile(hFile, &m_fuzzRandom.colorBase, sizeof(D3DXCOLOR), &dwNumBytesRead, NULL);\r\n//        ReadFile(hFile, &m_fuzzCenter.colorTip, sizeof(D3DXCOLOR), &dwNumBytesRead, NULL);\r\n//        ReadFile(hFile, &m_fuzzRandom.colorTip, sizeof(D3DXCOLOR), &dwNumBytesRead, NULL);\r\n//    }\r\n//\r\n//    ReadFile(hFile, &m_fuzzCenter.dp, sizeof(D3DVECTOR), &dwNumBytesRead, NULL);  // velocity center\r\n//    ReadFile(hFile, &m_fuzzRandom.dp, sizeof(D3DVECTOR), &dwNumBytesRead, NULL);  // velocity random\r\n//    ReadFile(hFile, &m_fuzzCenter.ddp, sizeof(D3DVECTOR), &dwNumBytesRead, NULL); // acceleration center\r\n//    ReadFile(hFile, &m_fuzzRandom.ddp, sizeof(D3DVECTOR), &dwNumBytesRead, NULL); // acceleration random\r\n//    \r\n//\r\n//    ReadFile(hFile, &numfuzzlib, sizeof(DWORD), &dwNumBytesRead, NULL);\r\n//    ReadFile(hFile, &numfuzz, sizeof(DWORD), &dwNumBytesRead, NULL);\r\n//        \r\n//    ReadFile(hFile, &numslices, sizeof(DWORD), &dwNumBytesRead, NULL);\r\n//    ReadFile(hFile, &slicexsize, sizeof(DWORD), &dwNumBytesRead, NULL);\r\n//    ReadFile(hFile, &slicezsize, sizeof(DWORD), &dwNumBytesRead, NULL);\r\n//       \r\n//    // read volume data if available and flag is set\r\n//    {\r\n//    }\r\n//\r\n//    CloseHandle(hFile);\r\n//\r\n//    InitFuzz(numfuzz, numfuzzlib);\r\n//    GenSlices(numslices, slicexsize, slicezsize);\r\n//    ComputeLevelOfDetailTextures();\r\n//    SetLevelOfDetail(0.f);\r\n//}\r\n//\r\n////////////////////////////////////////////////////////////////////////\r\n//// Lighting Model\r\n////////////////////////////////////////////////////////////////////////\r\n//\r\n//inline float\r\n//Luminance(const D3DXCOLOR &c)\r\n//{\r\n//    return (0.229f * c.r) + (0.587f * c.g) + (0.114f * c.b);\r\n//}\r\n//\r\n//inline float\r\n//MaxChannel(const D3DXCOLOR &c)\r\n//{\r\n//    if (c.r > c.g)\r\n//    {\r\n//        if (c.r > c.b)\r\n//            return c.r;\r\n//        else\r\n//            return c.b;\r\n//    }\r\n//    else\r\n//    {\r\n//        if (c.g > c.b)\r\n//            return c.g;\r\n//        else\r\n//            return c.b;\r\n//    }\r\n//}\r\n//\r\n//inline D3DXCOLOR \r\n//Lerp(const D3DXCOLOR &c1, const D3DXCOLOR &c2, float s)\r\n//{\r\n//    return c1 + s * (c2 - c1);\r\n//}\r\n//\r\n//inline D3DXCOLOR\r\n//Desaturate(const D3DXCOLOR &rgba)\r\n//{\r\n//    float alpha = rgba.a;\r\n//    if (alpha > 1.f)\r\n//        alpha = 1.f;\r\n//    float fMaxChan = MaxChannel(rgba);\r\n//    if (fMaxChan > alpha) \r\n//    {\r\n//        D3DXCOLOR rgbGray(alpha, alpha, alpha, alpha);\r\n//        float fYOld = Luminance(rgba);\r\n//        if (fYOld >= alpha)\r\n//            return rgbGray;\r\n//        // scale color to preserve hue\r\n//        D3DXCOLOR rgbNew;\r\n//        float fInvMaxChan = 1.f / fMaxChan;\r\n//        rgbNew.r = rgba.r * fInvMaxChan;\r\n//        rgbNew.g = rgba.g * fInvMaxChan;\r\n//        rgbNew.b = rgba.b * fInvMaxChan;\r\n//        rgbNew.a = alpha;\r\n//        float fYNew = Luminance(rgbNew);\r\n//        // add gray to preserve luminance\r\n//        return Lerp(rgbNew, rgbGray, (fYOld - fYNew) / (alpha - fYNew));\r\n//    }\r\n//    return rgba;\r\n//}\r\n//\r\n//inline D3DXCOLOR &operator *=(D3DXCOLOR &p, const D3DXCOLOR &q)\r\n//{\r\n//    p.r *= q.r;\r\n//    p.g *= q.g;\r\n//    p.b *= q.b;\r\n//    p.a *= q.a;\r\n//    return p;\r\n//}\r\n//\r\n//inline D3DXCOLOR operator *(const D3DXCOLOR &p, const D3DXCOLOR &q)\r\n//{\r\n//    D3DXCOLOR r;\r\n//    r.r = p.r * q.r;\r\n//    r.g = p.g * q.g;\r\n//    r.b = p.b * q.b;\r\n//    r.a = p.a * q.a;\r\n//    return r;\r\n//}\r\n//\r\n////-----------------------------------------------------------------------------\r\n////  HairLighting\r\n////-----------------------------------------------------------------------------\r\n//struct HairLighting {\r\n//    // like D3DMATERIAL8, except populated with D3DXCOLOR's so that color arithmetic works\r\n//    D3DXCOLOR m_colorDiffuse;\r\n//    D3DXCOLOR m_colorSpecular;\r\n//    float m_fSpecularExponent;\r\n//    D3DXCOLOR m_colorAmbient;\r\n//    D3DXCOLOR m_colorEmissive;\r\n//\r\n//    HRESULT Initialize(LPDIRECT3DDEVICE8 pDevice, D3DMATERIAL8 *pMaterial);\r\n//    HRESULT CalculateColor(D3DXCOLOR *pColor, float LT, float HT);\r\n//    HRESULT CalculateClampedColor(D3DXCOLOR *pColor, float LT, float HT);\r\n//};\r\n//\r\n//HRESULT HairLighting::Initialize(LPDIRECT3DDEVICE8 pDevice, D3DMATERIAL8 *pMaterial)\r\n//{\r\n//    // Get current colors modulated by light 0 and global ambient\r\n//    // ignore current alphas\r\n//    m_colorDiffuse = D3DXCOLOR(pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, 1.f);\r\n//    m_colorSpecular = D3DXCOLOR(pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, 1.f);\r\n//    m_fSpecularExponent = pMaterial->Power;\r\n//    m_colorAmbient = D3DXCOLOR(pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, 1.f);\r\n//    m_colorEmissive = D3DXCOLOR(pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, 1.f);\r\n//    return S_OK;\r\n//}\r\n//\r\n///* Zockler et al's technique worked with streamlines, and used dot(V,T) instead of the simpler dot(H,T) */\r\n//#define ZOCKLER 0 \r\n//#if ZOCKLER\r\n//\r\n//HRESULT HairLighting::CalculateColor(D3DXCOLOR *pColor, float LT, float VT)\r\n//{\r\n//    // Zockler et al 1996\r\n//    float fDiffuseExponent = 2.f;    // Banks used 4.8\r\n//    float fDiffuse = powf(sqrtf(1.f - LT*LT), fDiffuseExponent);\r\n//    float VR = LT*VT - sqrtf(1.f - LT*LT) * sqrtf(1.f - VT*VT);\r\n//    float fSpecular = powf(VR, m_fSpecularExponent);\r\n//    *pColor = m_colorEmissive + m_colorAmbient + fSpecular * m_colorSpecular + fDiffuse * m_colorDiffuse;\r\n//    return S_OK;\r\n//}\r\n//\r\n//#else\r\n//\r\n//HRESULT HairLighting::CalculateColor(D3DXCOLOR *pColor, float LT, float HT)\r\n//{\r\n//    float fDiffuseExponent = 2.f;    // Banks used 4.8\r\n//    float fDiffuse = powf(sqrtf(1.f - LT*LT), fDiffuseExponent);\r\n//    float fSpecular = powf(sqrtf(1.f - HT*HT), m_fSpecularExponent);\r\n//    *pColor = m_colorEmissive + m_colorAmbient + fSpecular * m_colorSpecular + fDiffuse * m_colorDiffuse;\r\n//    return S_OK;\r\n//}\r\n//\r\n//#endif\r\n//\r\n//HRESULT HairLighting::CalculateClampedColor(D3DXCOLOR *pColor, float LT, float HT)\r\n//{\r\n//    D3DXCOLOR color;\r\n//    HRESULT hr = CalculateColor(&color, LT, HT);\r\n//    *pColor = Desaturate(color);    // bring back to 0,1 range\r\n//    return hr;\r\n//}\r\n//\r\n////////////////////////////////////////////////////////////////////////\r\n//// \r\n//// Create a hair lighting lookup-table texture\r\n//// \r\n////////////////////////////////////////////////////////////////////////\r\n//HRESULT FillHairLightingTexture(D3DMATERIAL8 *pMaterial, LPDIRECT3DTEXTURE8 pTexture)\r\n//{\r\n//    /* \r\n//    The hair lighting texture maps U as the dot product of the hair\r\n//    tangent T with the light direction L and maps V as the dot product\r\n//    of the tangent with the half vector H.  Since the lighting is a\r\n//    maximum when the tangent is perpendicular to L (or H), the maximum\r\n//    is at zero.  The minimum is at 0.5, 0.5 (or -0.5, -0.5, since\r\n//    wrapping is turned on.)  For the mapped T.H, we raise the map\r\n//    value to a specular power.\r\n//    */\r\n//    HRESULT hr;\r\n//    D3DSURFACE_DESC desc;\r\n//    pTexture->GetLevelDesc(0, &desc);\r\n//    if (desc.Format != D3DFMT_A8R8G8B8)\r\n//        return E_NOTIMPL;\r\n//    DWORD dwPixelStride = 4;\r\n//    D3DLOCKED_RECT lockedRect;\r\n//    hr = pTexture->LockRect(0, &lockedRect, NULL, 0l);\r\n//    if (FAILED(hr))\r\n//        return hr;\r\n//    HairLighting lighting;\r\n//    lighting.Initialize(NxNgc::EngineGlobals.p_Device, pMaterial);\r\n//    Swizzler s(desc.Width, desc.Height, 0);\r\n//    s.SetV(s.SwizzleV(0));\r\n//    s.SetU(s.SwizzleU(0));\r\n//    for (UINT v = 0; v < desc.Height; v++)\r\n//    {\r\n//        for (UINT u = 0; u < desc.Width; u++)\r\n//        {\r\n//            BYTE *p = (BYTE *)lockedRect.pBits + dwPixelStride * s.Get2D();\r\n//            // vertical is specular lighting\r\n//            // horizontal is diffuse lighting\r\n//            D3DXCOLOR color;\r\n//#if ZOCKLER\r\n//            // Zockler et al 1996\r\n//            float LT = 2.f * u / desc.Width - 1.0f;\r\n//            float VT = 2.f * v / desc.Height - 1.0f;\r\n//            lighting.CalculateClampedColor(&color, LT, VT);\r\n//#else\r\n//            float LT = 2.f * u / desc.Width;\r\n//            if (LT > 1.f) LT -= 2.f;\r\n//            float HT = 2.f * v / desc.Height;\r\n//            if (HT > 1.f) HT -= 2.f;\r\n//            lighting.CalculateClampedColor(&color, LT, HT);\r\n//#endif\r\n//            int r, g, b;\r\n//            r = (BYTE)(255 * color.r);\r\n//            g = (BYTE)(255 * color.g);\r\n//            b = (BYTE)(255 * color.b);\r\n//            *p++ = (BYTE)b;\r\n//            *p++ = (BYTE)g;\r\n//            *p++ = (BYTE)r;\r\n//            *p++ = 255;    // alpha\r\n//            s.IncU();\r\n//        }\r\n//        s.IncV();\r\n//    }\r\n//    pTexture->UnlockRect(0);\r\n//    return S_OK;\r\n//}\r\n//\r\n////-----------------------------------------------------------------------------\r\n//// Name: SetHairLightingMaterial\r\n//// Desc: Create and fill the hair lighting texture\r\n////-----------------------------------------------------------------------------\r\n//HRESULT CXBFur::SetHairLightingMaterial(D3DMATERIAL8 *pMaterial)\r\n//{\r\n//    // Create and fill the hair lighting texture\r\n//    HRESULT hr;\r\n//    m_HairLightingMaterial = *pMaterial;\r\n//    if (!m_pHairLightingTexture)\r\n//    {\r\n//        DWORD dwWidth = 8; // an extremely small texture suffices when the exponents are low\r\n//        DWORD dwHeight = 8;\r\n//        D3DFORMAT surfaceFormat = D3DFMT_A8R8G8B8;\r\n//        DWORD nMipMap = 1;\r\n//        hr = D3DXCreateTexture(NxNgc::EngineGlobals.p_Device, dwWidth, dwHeight, nMipMap, 0, surfaceFormat, 0, &m_pHairLightingTexture);\r\n//        if (FAILED(hr)) goto e_Exit;\r\n//    }\r\n//    hr = FillHairLightingTexture(pMaterial, m_pHairLightingTexture);\r\n//    if (FAILED(hr)) goto e_Exit;\r\n//e_Exit:\r\n//    if (FAILED(hr))\r\n//        SAFE_RELEASE(m_pHairLightingTexture);\r\n//    return hr;\r\n//}\r\n//\r\n////-----------------------------------------------------------------------------\r\n//// Choose level of detail \r\n////\r\n//// 0       = finest detail, all slices of original source textures\r\n//// ...\r\n//// i       = reduced number of slices, N / (1 << i)\r\n//// i + f   = odd slices fade to clear, texLOD[2*j+1] = tex[2*j+1] * (1-f) + clear * f\r\n////           even slices compensate,   texLOD[2*j] = (tex[2*j+1] * f) OVER tex[2*j]\r\n//// i + 1   = reduced number of slices, N / (1 << (i+1))\r\n//// ...\r\n//// log2(N) = coarsest, one slice with composite of all source textures\r\n////-----------------------------------------------------------------------------\r\n//HRESULT CXBFur::SetLevelOfDetail(float fLevelOfDetail)\r\n//{\r\n//    // Choose number of LOD slices\r\n//    if (fLevelOfDetail < 0.f)\r\n//    {\r\n//        m_fLevelOfDetail = 0.f;\r\n//        m_iLOD = 0;\r\n//        m_fLODFraction = 0.f;\r\n//    }\r\n//    else if (fLevelOfDetail > (float)m_dwLODMax)\r\n//    {\r\n//        m_fLevelOfDetail = (float)m_dwLODMax;\r\n//        m_iLOD = m_dwLODMax;\r\n//        m_fLODFraction = 0.f;\r\n//    }\r\n//    else\r\n//    {\r\n//        m_fLevelOfDetail = fLevelOfDetail;\r\n//        m_iLOD = (UINT)floorf(fLevelOfDetail);\r\n//        m_fLODFraction = fLevelOfDetail - (float)m_iLOD;\r\n//    }\r\n//    m_dwNumSlicesLOD = LevelOfDetailCount(m_iLOD);\r\n//    UINT index = LevelOfDetailIndex(m_iLOD);\r\n//    m_pSliceTextureLOD = m_apSliceTexture + index;\r\n//    return S_OK;\r\n//}\r\n//\r\n////-----------------------------------------------------------------------------\r\n////\r\n//// Generate level-of-detail textures by compositing together alternating layers.\r\n////\r\n////-----------------------------------------------------------------------------\r\n//HRESULT CXBFur::ComputeLevelOfDetailTextures()\r\n//{\r\n//    // All the textures must have the same number of mip levels.\r\n//    DWORD nMip = m_apSliceTexture[0]->GetLevelCount();\r\n//\r\n//    // save current back buffer and z buffer\r\n//    struct {\r\n//        IDirect3DSurface8 *pBackBuffer, *pZBuffer;\r\n//    } save;\r\n//    NxNgc::EngineGlobals.p_Device->GetRenderTarget(&save.pBackBuffer);\r\n//    NxNgc::EngineGlobals.p_Device->GetDepthStencilSurface(&save.pZBuffer);\r\n//\r\n//    // set render state for compositing textures\r\n//    NxNgc::EngineGlobals.p_Device->SetVertexShader(D3DFVF_XYZRHW|D3DFVF_TEX1);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_LIGHTING, FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_STENCILENABLE, FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_FOGENABLE, FALSE);\r\n//\r\n//    // use pixel shaders to composite two or three layers at a time\r\n//#pragma warning(push)\r\n//#pragma warning(disable: 4245)    // conversion from int to DWORD\r\n//    DWORD dwPS2 = 0;\r\n//    {\r\n//#include \"comp2.inl\"\r\n//        NxNgc::EngineGlobals.p_Device->CreatePixelShader(&psd, &dwPS2);\r\n//    }\r\n//    DWORD dwPS3 = 0;\r\n//    {\r\n//#include \"comp3.inl\"\r\n//        NxNgc::EngineGlobals.p_Device->CreatePixelShader(&psd, &dwPS3);\r\n//    }\r\n//#pragma warning(pop)\r\n//\r\n//    // set default texture stage states\r\n//    UINT xx; // texture stage index\r\n//    for (xx = 0; xx < 4; xx++)\r\n//    {\r\n//        NxNgc::EngineGlobals.p_Device->SetTexture(xx, NULL);\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_COLOROP, D3DTOP_DISABLE);    // Are the COLOROP and ALPHAOP needed since we're using a pixel shader?\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_ALPHAOP, D3DTOP_DISABLE);\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);    // pass texture coords without transformation\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_TEXCOORDINDEX, 0);            // all the textures use the same tex coords\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_MAGFILTER, D3DTEXF_POINT);\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_MINFILTER, D3DTEXF_POINT);\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_MIPFILTER, D3DTEXF_POINT);\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_MIPMAPLODBIAS, 0);\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_MAXMIPLEVEL, 0);\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_COLORKEYOP, D3DTCOLORKEYOP_DISABLE);\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_COLORSIGN, 0);\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_ALPHAKILL, D3DTALPHAKILL_DISABLE);\r\n//    }\r\n//    \r\n//    // Compute all the level-of-detail textures\r\n//    for (UINT iLOD = 1; m_dwNumSlices >> iLOD; iLOD++)\r\n//    {\r\n//        UINT nSliceSrc = LevelOfDetailCount(iLOD-1);\r\n//        LPDIRECT3DTEXTURE8 *apTextureSrc = m_apSliceTexture + LevelOfDetailIndex(iLOD - 1);\r\n//        UINT nSliceDst = LevelOfDetailCount(iLOD);\r\n//        LPDIRECT3DTEXTURE8 *apTextureDst = m_apSliceTexture + LevelOfDetailIndex(iLOD);\r\n//        \r\n//        // Composite source textures into LOD textures\r\n//        UINT iMipNotHandled = (UINT)-1;\r\n//        for (UINT iSliceDst = 0; iSliceDst < nSliceDst; iSliceDst++)\r\n//        {\r\n//            LPDIRECT3DTEXTURE8 pTextureDst = apTextureDst[iSliceDst];\r\n//            UINT nComp;\r\n//            if (iSliceDst == nSliceDst-1 && nSliceSrc > nSliceDst * 2)\r\n//            {\r\n//                // composite 3 textures into the top-most level when number of source textures is odd\r\n//                nComp = 3;\r\n//                NxNgc::EngineGlobals.p_Device->SetPixelShader(dwPS3);\r\n//            }\r\n//            else\r\n//            {\r\n//                // composite 2 textures (this is the default)\r\n//                nComp = 2;\r\n//                NxNgc::EngineGlobals.p_Device->SetPixelShader(dwPS2);\r\n//            }\r\n//            for (xx = 0; xx < nComp; xx++)\r\n//            {\r\n//                NxNgc::EngineGlobals.p_Device->SetTexture(xx, apTextureSrc[ iSliceDst * 2 + xx]);\r\n//                NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_COLOROP, D3DTOP_SELECTARG1);\r\n//                NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);\r\n//            }\r\n//            for (; xx<4; xx++)\r\n//            {\r\n//                NxNgc::EngineGlobals.p_Device->SetTexture(xx, NULL);\r\n//                NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_COLOROP, D3DTOP_DISABLE);\r\n//                NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_ALPHAOP, D3DTOP_DISABLE);\r\n//            }\r\n//            for (UINT iMip = 0; iMip < nMip; iMip++)\r\n//            {\r\n//                DWORD width = m_dwSliceXSize / (1 << iMip);\r\n//                if (width == 0) width = 1;\r\n//                DWORD height = m_dwSliceZSize / (1 << iMip);\r\n//                if (height == 0) height = 1;\r\n//\r\n//                // Ngc render target must of be at least 16x16\r\n//                if (width*4 < 64 || width * height < 64)            \r\n//                {\r\n//                    iMipNotHandled = iMip;\r\n//                    break; // skip rest of coarser mipmaps and go to next slice\r\n//                }\r\n//\r\n//                // Use a screen space quad to do the compositing.\r\n//                struct quad {\r\n//                    float x, y, z, w;\r\n//                    float u, v;\r\n//                } aQuad[4] =\r\n//                {\r\n//                    {-0.5f,        -0.5f,         1.0f, 1.0f, 0.0f, 0.0f},\r\n//                    {width - 0.5f, -0.5f,         1.0f, 1.0f, 1.0f, 0.0f},\r\n//                    {-0.5f,        height - 0.5f, 1.0f, 1.0f, 0.0f, 1.0f},\r\n//                    {width - 0.5f, height - 0.5f, 1.0f, 1.0f, 1.0f, 1.0f}\r\n//                };\r\n//\r\n//                // get destination surface and set as render target\r\n//                IDirect3DSurface8 *pSurface;\r\n//                pTextureDst->GetSurfaceLevel(iMip, &pSurface);\r\n//                NxNgc::EngineGlobals.p_Device->SetRenderTarget(pSurface, NULL); // no depth buffering\r\n//                NxNgc::EngineGlobals.p_Device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, aQuad, sizeof(quad)); // one quad blends 2 or 3 textures\r\n//                pSurface->Release();\r\n//            }\r\n//        }\r\n//        if (iMipNotHandled > 0 && iMipNotHandled != -1)\r\n//        {\r\n//            // fill in the small mips with filtered versions of the previous levels\r\n//            for (UINT iSliceDst = 0; iSliceDst < nSliceDst; iSliceDst++)\r\n//            {\r\n//                LPDIRECT3DTEXTURE8 pTextureDst = apTextureDst[iSliceDst];\r\n//                GenerateMipmaps(pTextureDst, iMipNotHandled - 1, D3DTADDRESS_MIRROR, D3DTADDRESS_MIRROR);\r\n//            }\r\n//        }\r\n//    }\r\n//\r\n//    // clean up pixel shaders\r\n//    NxNgc::EngineGlobals.p_Device->SetPixelShader(0);\r\n//    NxNgc::EngineGlobals.p_Device->DeletePixelShader(dwPS2);\r\n//    NxNgc::EngineGlobals.p_Device->DeletePixelShader(dwPS3);\r\n//    \r\n//    // restore render states\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_LIGHTING, TRUE);\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);\r\n//\r\n//    // restore texture stage states\r\n//    for (xx=0; xx<4; xx++)\r\n//    {\r\n//        NxNgc::EngineGlobals.p_Device->SetTexture(xx, NULL);\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_COLOROP, D3DTOP_DISABLE);\r\n//        NxNgc::EngineGlobals.p_Device->SetTextureStageState(xx, D3DTSS_ALPHAOP, D3DTOP_DISABLE);\r\n//    }\r\n//\r\n//    // restore back buffer and z buffer\r\n//    NxNgc::EngineGlobals.p_Device->SetRenderTarget(save.pBackBuffer, save.pZBuffer);\r\n//    save.pBackBuffer->Release();\r\n//    save.pZBuffer->Release();\r\n//    return S_OK;\r\n//}\r\n//\r\n////-----------------------------------------------------------------------------\r\n////  Divide alpha channel into color channel.  Leave alpha unchanged.\r\n////-----------------------------------------------------------------------------\r\n//HRESULT AlphaDivide(LPDIRECT3DTEXTURE8 pTexture)\r\n//{\r\n//    HRESULT hr;\r\n//    DWORD nMip = pTexture->GetLevelCount();\r\n//    for (UINT iMip = 0; iMip < nMip; iMip++)\r\n//    {\r\n//        D3DSURFACE_DESC desc;\r\n//        hr = pTexture->GetLevelDesc(iMip, &desc);\r\n//        if (FAILED(hr))\r\n//            return hr;\r\n//        if (desc.Format != D3DFMT_A8R8G8B8)\r\n//            return E_NOTIMPL;\r\n//        D3DLOCKED_RECT lockedRect;\r\n//        hr = pTexture->LockRect(iMip, &lockedRect, NULL, 0l);\r\n//        if (FAILED(hr))\r\n//            return hr;\r\n//        UINT dwPixelSize = 4;\r\n//        UINT nPixel = desc.Size / dwPixelSize;\r\n//        DWORD *pPixel = (DWORD *)lockedRect.pBits;\r\n//        while (nPixel--)\r\n//        {\r\n//            D3DXCOLOR c(*pPixel);\r\n//            if (c.a > 0.f)\r\n//            {\r\n//                D3DXCOLOR d;\r\n//                d.r = c.r / c.a;\r\n//                d.g = c.g / c.a;\r\n//                d.b = c.b / c.a;\r\n//                d.a = c.a;\r\n//                *pPixel = d;\r\n//            }\r\n//            pPixel++;\r\n//        }\r\n//        pTexture->UnlockRect(iMip);\r\n//    }\r\n//    return S_OK;\r\n//}\r\n//\r\n////-----------------------------------------------------------------------------\r\n////  Multiply alpha channel into color channel.  Leave alpha unchanged.\r\n////-----------------------------------------------------------------------------\r\n//HRESULT AlphaMultiply(LPDIRECT3DTEXTURE8 pTexture)\r\n//{\r\n//    HRESULT hr;\r\n//    DWORD nMip = pTexture->GetLevelCount();\r\n//    for (UINT iMip = 0; iMip < nMip; iMip++)\r\n//    {\r\n//        D3DSURFACE_DESC desc;\r\n//        hr = pTexture->GetLevelDesc(iMip, &desc);\r\n//        if (FAILED(hr))\r\n//            return hr;\r\n//        if (desc.Format != D3DFMT_A8R8G8B8)\r\n//            return E_NOTIMPL;\r\n//        D3DLOCKED_RECT lockedRect;\r\n//        hr = pTexture->LockRect(iMip, &lockedRect, NULL, 0l);\r\n//        if (FAILED(hr))\r\n//            return hr;\r\n//        UINT dwPixelSize = 4;\r\n//        UINT nPixel = desc.Size / dwPixelSize;\r\n//        DWORD *pPixel = (DWORD *)lockedRect.pBits;\r\n//        while (nPixel--)\r\n//        {\r\n//            D3DXCOLOR c(*pPixel);\r\n//            D3DXCOLOR d;\r\n//            d.r = c.r * c.a;\r\n//            d.g = c.g * c.a;\r\n//            d.b = c.b * c.a;\r\n//            d.a = c.a;\r\n//            *pPixel = d;\r\n//            pPixel++;\r\n//        }\r\n//        pTexture->UnlockRect(iMip);\r\n//    }\r\n//    return S_OK;\r\n//}\r\n//\r\n////-----------------------------------------------------------------------------\r\n////\r\n//// Copy textures to new texture format\r\n////\r\n////-----------------------------------------------------------------------------\r\n//HRESULT CXBFur::CompressNextTexture(D3DFORMAT fmtNew, UINT *pIndex)\r\n//{\r\n//    HRESULT hr;\r\n//    for (UINT iTexture = 0; iTexture < XBFUR_MAXSLICE * 2 - 1; iTexture++)    // convert all the slice textures\r\n//    {\r\n//        LPDIRECT3DTEXTURE8 pTextureDst = NULL;\r\n//        LPDIRECT3DTEXTURE8 pTextureSrc = m_apSliceTexture[iTexture];\r\n//        if (pTextureSrc == NULL)\r\n//            break;    // we're done\r\n//\r\n//        // See if this texture needs to be compressed\r\n//        D3DSURFACE_DESC desc0;\r\n//        pTextureSrc->GetLevelDesc(0, &desc0);\r\n//        if (desc0.Format == fmtNew)\r\n//            continue;    // we've already compressed this one, go to the next\r\n//\r\n//        // We've found a texture that needs to be compressed\r\n//        hr = CompressTexture(&pTextureDst, fmtNew, pTextureSrc);\r\n//        if (FAILED(hr))\r\n//            return hr;\r\n//        m_apSliceTexture[iTexture] = pTextureDst; // already addref'd\r\n//        pTextureSrc->Release();    // we're done with the old texture\r\n//        if (pIndex != NULL)\r\n//            *pIndex = iTexture;    // return index of the texture we just compressed\r\n//        return S_FALSE;    // more textures are pending\r\n//    }\r\n//    return S_OK;\r\n//}\r\n//\r\n//\r\n//#endif\r\n//\r\n//\r\n//static bool grass_mats = false;\r\n//static NxNgc::sMaterial*\tp_grass_mats[16];\r\n//\r\n//\r\n//static void createGrassMats( void )\r\n//{\r\n//\tif( !grass_mats )\r\n//\t{\r\n//\t\tgrass_mats = true;\r\n//\r\n//\t\tfor( int layer = 0; layer < 8; ++layer )\r\n//\t\t{\r\n//\t\t\tNxNgc::sTexture *p_tex\t\t= new NxNgc::sTexture();\r\n//\t\t\tp_tex->pD3DTexture\t\t\t= p_fur->m_apSliceTexture[layer];\r\n//\t\t\tp_tex->pD3DPalette\t\t\t= NULL;\r\n//\r\n//\t\t\t\r\n//\t\t\tNxNgc::sMaterial *p_mat\t= new NxNgc::sMaterial();\r\n//\r\n//\t\t\tp_mat->m_no_bfc\t\t\t\t= false;\r\n//\t\t\tp_mat->Passes\t\t\t\t= 1;\r\n//\t\t\tp_mat->pTex[0]\t\t\t\t= p_tex;\r\n//\r\n//\t\t\tif( layer < 3 )\r\n//\t\t\t{\r\n//\t\t\t\tp_mat->Flags[0]\t\t\t\t= 0x00;\r\n//\t\t\t\tp_mat->RegALPHA[0]\t\t\t= NxNgc::vBLEND_MODE_DIFFUSE;\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\tp_mat->Flags[0]\t\t\t\t= 0x40;\t// Transparent.\r\n//\t\t\t\tp_mat->RegALPHA[0]\t\t\t= NxNgc::vBLEND_MODE_BLEND;\r\n//\t\t\t}\r\n//\r\n//\t\t\tp_mat->UVAddressing[0]\t\t= 0x00000000UL;\r\n//\t\t\tp_mat->AlphaCutoff\t\t\t= 1;\r\n//\t\t\tp_mat->Color[0][0]\t\t\t= 1.0f;\r\n//\t\t\tp_mat->Color[0][1]\t\t\t= 1.0f;\r\n//\t\t\tp_mat->Color[0][2]\t\t\t= 1.0f;\r\n//\t\t\tp_mat->Color[0][3]\t\t\t= 1.0f;\r\n//\t\t\tp_mat->m_sorted\t\t\t\t= false;\r\n//\t\t\tp_mat->m_draw_order\t\t\t= 0;\r\n//\t\t\tp_mat->mp_wibble_vc_colors\t= NULL;\r\n//\r\n//\t\t\tp_grass_mats[layer]\t\t\t= p_mat;\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n\r\n\r\n\r\nbool AddGrass( Nx::CNgcGeom *p_geom, NxNgc::sMesh *p_mesh )\r\n{\r\n#if 0\r\n\tbool add_grass = false;\r\n\t\r\n\tif( p_mesh->mp_material && p_mesh->mp_material->m_grassify )\r\n\t{\r\n\t\tadd_grass = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// At this stage we know we want to add grass.\r\n\tDbg_Assert( p_mesh->mp_material->m_grass_layers > 0 );\r\n//\tfloat height_per_layer = p_mesh->mp_material->m_grass_height / p_mesh->mp_material->m_grass_layers;\r\n\t\r\n\tfor( int layer = 0; layer < p_mesh->mp_material->m_grass_layers; ++layer )\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().BottomUpHeap());\r\n\t\tNxNgc::sMesh *p_grass_mesh = p_mesh->Clone( false );\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t// No longer any shadow cast on the base mesh.\r\n//\t\tp_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_NO_SKATER_SHADOW;\r\n\t\t\r\n\t\tif( layer != 2 )\r\n\t\t\tp_grass_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_NO_SKATER_SHADOW;\r\n\t\t\r\n\t\t// Now point the mesh to a different material, first build the material checksum from the name of the parent\r\n\t\t// material (Grass) and the name of the sub material (Grass_LayerX)...\r\n\t\tchar material_name[64];\r\n\t\tsprintf( material_name, \"Grass-Grass_Layer%d\", layer );\r\n\t\tuint32 material_checksum\t= Crc::GenerateCRCCaseSensitive( material_name, strlen( material_name ));\r\n\r\n\t\t// ...then use the checksum to lookup the material.\r\n\t\tp_grass_mesh->mp_material\t= p_geom->mp_scene->GetEngineScene()->GetMaterial( material_checksum );\r\n\r\n\t\t// We need also to override the mesh pixel shader, which may have been setup for a multipass material.\r\n//\t\tNxNgc::GetPixelShader( p_grass_mesh->mp_material, &p_grass_mesh->m_pixel_shader, &p_grass_mesh->m_pixel_shader_no_mcm );\r\n\t\t\r\n\t\t// Add transparent flag to the material.\r\n\t\tp_grass_mesh->mp_material->Flags[0]\t\t|= 0x40;\r\n\r\n\t\t// Set the draw order to ensure meshes are drawn from the bottom up.\r\n\t\tp_grass_mesh->mp_material->m_sorted\t\t = false;\r\n\t\tp_grass_mesh->mp_material->m_draw_order\t = layer * 0.1f;\r\n\t\t\r\n\t\t// Go through and move all the vertices up a little, and calculate new texture coordinates based on the x-z space of the vertex positions.\r\n//\t\tchar *p_byte_dest;\r\n//\t\tp_grass_mesh->mp_vertex_buffer[0]->Lock( 0, 0, &p_byte_dest, 0 );\r\n//\r\n//\t\tfor( uint32 vert = 0; vert < p_grass_mesh->m_num_vertices; ++vert )\r\n//\t\t{\r\n//\t\t\tD3DXVECTOR3 *p_pos = (D3DXVECTOR3*)( p_byte_dest + ( vert * p_grass_mesh->m_vertex_stride ));\r\n//\t\t\tp_pos->y += ( height_per_layer * ( layer + 1 ));\r\n//\r\n//\t\t\tfloat u\t\t\t= fabsf( p_pos->x ) / 48.0f;\r\n//\t\t\tfloat v\t\t\t= fabsf( p_pos->z ) / 48.0f;\r\n//\t\t\tfloat *p_tex\t= (float*)( p_byte_dest + p_grass_mesh->m_uv0_offset + ( vert * p_grass_mesh->m_vertex_stride ));\r\n//\t\t\tp_tex[0]\t\t= u;\t\t\r\n//\t\t\tp_tex[1]\t\t= v;\r\n//\t\t}\r\n\r\n\t\tp_geom->AddMesh( p_grass_mesh );\r\n\t}\r\n\t\r\n/*\t\r\n\t\r\n\tif( p_mesh->mp_material && p_mesh->mp_material->pTex[0] )\r\n\t{\r\n\t\tif( p_mesh->mp_material->Passes == 1 )\r\n\t\t{\r\n\t\t\tif( p_mesh->mp_material->pTex[0]->Checksum == 0x8d9b6a64 )\r\n\t\t\t\tadd_grass = true;\r\n\t\t}\r\n\t}\r\n\r\n\tif( !add_grass )\r\n\t\treturn false;\r\n\r\n\tcreateGrassMats();\r\n\r\n\t// At this stage we know we want to add grass.\r\n\tfor( int layer = 0; layer < 6; ++layer )\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().BottomUpHeap());\r\n\t\tNxNgc::sMesh *p_grass_mesh = p_mesh->Clone( false );\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t// No longer any shadow cast on the base mesh.\r\n//\t\tp_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_NO_SKATER_SHADOW;\r\n\t\t\r\n\t\tif( layer != 2 )\r\n\t\t\tp_grass_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_NO_SKATER_SHADOW;\r\n\t\t\r\n\t\t// Now point the mesh to a different material.\r\n\t\tp_grass_mesh->mp_material = p_grass_mats[layer];\r\n\r\n\t\t// Go through and move all the vertices up a little, and calculate new texture coordinates based on the x-z space of the vertex positions.\r\n\t\tBYTE *p_byte_dest;\r\n\t\tp_grass_mesh->mp_vertex_buffer[0]->Lock( 0, 0, &p_byte_dest, 0 );\r\n\r\n\t\tfor( uint32 vert = 0; vert < p_grass_mesh->m_num_vertices; ++vert )\r\n\t\t{\r\n\t\t\tD3DXVECTOR3 *p_pos = (D3DXVECTOR3*)( p_byte_dest + ( vert * p_grass_mesh->m_vertex_stride ));\r\n\t\t\tp_pos->y += ( 1.0f * ( layer + 1 ));\r\n\r\n\t\t\tfloat u\t\t\t= fabsf( p_pos->x ) / 48.0f;\r\n\t\t\tfloat v\t\t\t= fabsf( p_pos->z ) / 48.0f;\r\n\t\t\tfloat *p_tex\t= (float*)( p_byte_dest + p_grass_mesh->m_uv0_offset + ( vert * p_grass_mesh->m_vertex_stride ));\r\n\t\t\tp_tex[0]\t\t= u;\t\t\r\n\t\t\tp_tex[1]\t\t= v;\r\n\t\t}\r\n\r\n\t\tp_geom->AddMesh( p_grass_mesh );\r\n\t}\r\n*/\r\n#endif\r\n\treturn true;\r\n}\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/grass.h",
    "content": "//-----------------------------------------------------------------------------\r\n// File: XBFur.h\r\n//\r\n// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.\r\n//-----------------------------------------------------------------------------\r\n//#include \"xfvf.h\"\r\n#include <gfx/Ngc/p_nxgeom.h>\r\n\r\n//#define XBFUR_MAXSLICE_LOG2 5\r\n//#define XBFUR_MAXSLICE (1 << XBFUR_MAXSLICE_LOG2)\r\n//\r\n//extern float g_fOneInch;\r\n//\r\n//#define FVF_XYZDIFF (D3DFVF_XYZ|D3DFVF_DIFFUSE)\r\n//\r\n//typedef struct sFVFT_XYZDIFF\r\n//{\r\n//    D3DVECTOR v;\r\n//    DWORD diff;\r\n//} FVFT_XYZDIFF;\r\n//\r\n//\r\n//// patch generation\r\n//\r\n//// a fuzz is a single hair follicle, blade of grass, etc.\r\n//struct Fuzz\r\n//{\r\n//    D3DVECTOR dp;            // velocity\r\n//    D3DVECTOR ddp;            // acceleration\r\n//    D3DXCOLOR colorBase;\r\n//    D3DXCOLOR colorTip;\r\n//};\r\n//\r\n//// a fuzz instance is a single instance of a fuzz\r\n//// located at x, z on the patch\r\n//// we create only a limited number of unique fuzzes\r\n//// and index the library with lidx.\r\n//struct FuzzInst\r\n//{\r\n//    float x, z;                // fuzz location\r\n//    int lidx;                // library index\r\n//};\r\n//\r\n//// a fur patch is a volume that holds fuzzes.\r\n//// xsize and zsize are chosen by the user\r\n//// ysize is calculated using the height of the \r\n//// tallest fuzz\r\n//class CXBFur\r\n//{\r\n//    friend class CXBFurMesh;\r\n//public:\r\n//    DWORD m_dwSeed;            // patch seed\r\n//    \r\n//    float m_fXSize;            // patch size in world coords\r\n//    float m_fYSize;\r\n//    float m_fZSize;\r\n//\r\n//    // fuzz library\r\n//    DWORD m_dwNumSegments;    // # of segments in highest LOD\r\n//    Fuzz m_fuzzCenter;        // fuzz constant\r\n//    Fuzz m_fuzzRandom;        // random offset around center\r\n//    DWORD m_dwNumFuzzLib;    // # of fuzz in the library\r\n//    Fuzz *m_pFuzzLib;        // fuzz library\r\n//\r\n//    // fuzz instances\r\n//    DWORD m_dwNumFuzz;        // # of fuzz in this patch\r\n//    FuzzInst *m_pFuzz;\r\n//\r\n//    // patch volume\r\n//    DWORD m_dwNumSlices;    // # of layers in the volume\r\n//    DWORD m_dwSliceSize;        // width*height\r\n//    DWORD m_dwSliceXSize;        // width of volume texture slice\r\n//    DWORD m_dwSliceZSize;        // height of volume texture slice\r\n//    LPDIRECT3DTEXTURE8 m_apSliceTexture[XBFUR_MAXSLICE * 2 - 1];    // slices of volume texture\r\n//                    // ... followed by level-of-detail textures  N/2, N/4, N/8, ... 1\r\n//\r\n//    // LOD textures\r\n//    DWORD m_dwNumSlicesLOD; // number of slices in current level of detail\r\n//    float m_fLevelOfDetail;    // current LOD value\r\n//    DWORD m_iLOD;            // current integer LOD value\r\n//    float m_fLODFraction;    // fraction towards next coarser level-of-detail\r\n//    DWORD m_dwLODMax;        // maximum LOD index\r\n//    LPDIRECT3DTEXTURE8 *m_pSliceTextureLOD; // current level of detail pointer into m_apSliceTexture array\r\n//\r\n//    // hair lighting texture\r\n//    D3DMATERIAL8 m_HairLightingMaterial;\r\n//    LPDIRECT3DTEXTURE8 m_pHairLightingTexture;\r\n//\r\n//    // fin texture\r\n//    DWORD m_finWidth, m_finHeight;        // size of fin texture\r\n//    float m_fFinXFraction, m_fFinZFraction;    // portion of hair texture to put into fin\r\n//    LPDIRECT3DTEXTURE8 m_pFinTexture;    // texture projected from the side\r\n//\r\n//    CXBFur();\r\n//    ~CXBFur();\r\n//    void InitFuzz(DWORD nfuzz, DWORD nfuzzlib);\r\n//    void GenSlices(DWORD nslices, DWORD slicexsize, DWORD slicezsize);\r\n//    void GenFin(DWORD finWidth, DWORD finHeight, float fFinXFraction, float fFinZFraction);\r\n//    void GetLinesVertexBuffer(IDirect3DVertexBuffer8 **ppVB);\r\n//    void RenderLines();\r\n//    void Save(char *fname, int flags);\r\n//    void Load(char *fname);\r\n//    HRESULT SetHairLightingMaterial(D3DMATERIAL8 *pMaterial);\r\n//    void SetPatchSize(float x, float z)\r\n//    {\r\n//        m_fXSize = x;\r\n//        m_fZSize = z;\r\n//        InitFuzz(m_dwNumFuzz, m_dwNumFuzzLib);    // re-init the fuzz. automatically sets ysize\r\n//    };\r\n//    void SetFVel(float cx, float cy, float cz, float rx, float ry, float rz)\r\n//    {\r\n//        m_fuzzCenter.dp.x = cx; m_fuzzCenter.dp.y = cy; m_fuzzCenter.dp.z = cz;\r\n//        m_fuzzRandom.dp.x = rx; m_fuzzRandom.dp.y = ry; m_fuzzRandom.dp.z = rz;\r\n//    };\r\n//    void SetFAcc(float cx, float cy, float cz, float rx, float ry, float rz)\r\n//    {\r\n//        m_fuzzCenter.ddp.x = cx; m_fuzzCenter.ddp.y = cy; m_fuzzCenter.ddp.z = cz;\r\n//        m_fuzzRandom.ddp.x = rx; m_fuzzRandom.ddp.y = ry; m_fuzzRandom.ddp.z = rz;\r\n//    };\r\n//\r\n//    // fLevelOfDetail can range from 0 to log2(NumSlices)\r\n//    HRESULT SetLevelOfDetail(float fLevelOfDetail);\r\n//    HRESULT ComputeLevelOfDetailTextures();\r\n//    inline UINT LevelOfDetailCount(UINT iLOD)\r\n//    {\r\n//        return m_dwNumSlices >> iLOD;\r\n//    }\r\n//    inline UINT LevelOfDetailIndex(UINT iLOD)\r\n//    {\r\n//        UINT offset = 0;\r\n//        for (UINT i = 1; i <= iLOD; i++)\r\n//            offset += LevelOfDetailCount(i-1);\r\n//        return offset;\r\n//    }\r\n//    inline UINT TotalTextureCount()\r\n//    {\r\n//        UINT TextureCount = 0;\r\n//        for (UINT iLOD = 0; m_dwNumSlices >> iLOD; iLOD++)\r\n//            TextureCount += LevelOfDetailCount(iLOD);\r\n//        return TextureCount;\r\n//    }\r\n//\r\n//    // Compress textures one at a time until all are done.\r\n//    // Returns S_OK when all the textures are in fmtNew format.\r\n//    // Returns S_FALSE if there are textures still to be done.\r\n//    HRESULT CompressNextTexture(D3DFORMAT fmtNew, UINT *pTextureIndex);\r\n//};\r\n//\r\n//HRESULT FillHairLightingTexture(D3DMATERIAL8 *pMaterial, LPDIRECT3DTEXTURE8 pTexture);\r\nbool AddGrass( Nx::CNgcGeom *p_geom, NxNgc::sMesh *p_mesh );\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/import.cpp",
    "content": "#include <core/defines.h>\r\n#include <sys/file/filesys.h>\r\n\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <string.h>\r\n#include \"texture.h\"\r\n#include \"gfx/ngc/p_nxtexture.h\"\r\n#include \"mesh.h\"\r\n#include \"import.h\"\r\n\t\r\nnamespace NxNgc\r\n{\r\n\r\nuint8 *pData, *TextureLoadPos;\r\n\r\n//----------------------------------------------------------------------------------------\r\n//\t\tL O A D   T E X T U R E   F I L E\r\n//----------------------------------------------------------------------------------------\r\n\r\nvoid LoadTextureFile( const char* Filename, Lst::HashTable<Nx::CTexture> * p_texture_table )\r\n{\r\n\tuint32 temp;\r\n\t\r\n\tDbg_Message( \"Loading texture file %s\\n\", Filename );\r\n\r\n\t// Open the texture file.\r\n\tvoid *p_FH = File::Open( Filename, \"rb\" );\r\n\tif( !p_FH )\r\n\t{\r\n\t\tDbg_Message( \"Couldn't open texture file %s\\n\", Filename );\r\n//\t\treturn 0;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Read the texture file version.\r\n\tint version;\r\n\tFile::Read( &version, sizeof( int ), 1, p_FH );\r\n\r\n\t// Read the number of textures.\t\r\n\tint num_textures;\r\n\tFile::Read( &num_textures, sizeof( int ), 1, p_FH );\r\n\t\r\n//\tNumTextures\t\t\t\t+= num_textures;\r\n\r\n\tNxNgc::sTexture ** p_tex = new (Mem::Manager::sHandle().TopDownHeap()) NxNgc::sTexture *[num_textures];\r\n\tunsigned short * p_resolvem = new (Mem::Manager::sHandle().TopDownHeap()) unsigned short[num_textures];\r\n\tunsigned short * p_resolvec = new (Mem::Manager::sHandle().TopDownHeap()) unsigned short[num_textures];\r\n\tint num_resolve = 0;\r\n\r\n\tfor( int t = 0; t < num_textures; ++t )\r\n\t{\r\n\t\tsTexture *p_texture = new sTexture;\r\n\t\t\r\n\t\tp_tex[t] = p_texture;\r\n\r\n\t\tFile::Read( &p_texture->Checksum,\t\tsizeof( uint32 ), 1, p_FH );\r\n\t\tFile::Read( &temp,\t\tsizeof( uint32 ), 1, p_FH );\r\n\t\tp_texture->BaseWidth = (uint16)temp;\r\n\t\tFile::Read( &temp,\t\tsizeof( uint32 ), 1, p_FH );\r\n\t\tp_texture->BaseHeight = (uint16)temp;\r\n\t\tFile::Read( &temp,\t\tsizeof( uint32 ), 1, p_FH );\r\n\t\tp_texture->Levels = (uint16)temp;\r\n\r\n\t\tp_texture->ActualWidth = ( p_texture->BaseWidth + 3 ) & ~3;\r\n\t\tp_texture->ActualHeight = ( p_texture->BaseHeight + 3 ) & ~3;\r\n\r\n\t\tint tex_format;\r\n\t\tint channel;\r\n\t\tint index;\r\n\t\tFile::Read( &tex_format, sizeof( uint32 ), 1, p_FH );\r\n\t\tchannel = ( tex_format >> 8 ) & 0xff;\r\n\t\tindex = ( tex_format >> 16 ) & 0xffff;\r\n\t\ttex_format = tex_format & 0xff;\r\n\r\n\t\tswitch ( tex_format ) {\r\n\t\t\tcase 0:\r\n\t\t\t\tp_texture->format = GX_TF_CMPR;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1:\r\n\t\t\t\tp_texture->format = GX_TF_CMPR;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\tp_texture->format = GX_TF_RGBA8;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert( false, (\"Illegal texture format: %d\\n\", tex_format ));\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tp_texture->flags = 0;\r\n\r\n\t\tint has_holes;\r\n\t\tFile::Read( &has_holes, sizeof( uint32 ), 1, p_FH );\r\n\t\tp_texture->flags |= has_holes ? NxNgc::sTexture::TEXTURE_FLAG_HAS_HOLES : 0;\r\n\r\n\t\tuint8 * p8[8];\r\n\t\tint bytes;\r\n\t\tint mipbytes[8];\r\n\r\n\t\t// Read color maps.\r\n\t\tbytes = 0;\r\n\t\tfor( uint32 mip_level = 0; mip_level < p_texture->Levels; ++mip_level )\r\n\t\t{\r\n\t\t\tuint32 texture_level_data_size;\r\n\t\t\tFile::Read( &texture_level_data_size,\t\t\tsizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t\tp8[mip_level] = new (Mem::Manager::sHandle().TopDownHeap()) uint8[texture_level_data_size];\r\n\t\t\tmipbytes[mip_level] = texture_level_data_size;\r\n\t\t\tbytes += texture_level_data_size;\r\n\r\n\t\t\tFile::Read( p8[mip_level], texture_level_data_size, 1, p_FH );\r\n\t\t}\r\n\t\t// Copy all textures & delete the originals.\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\t\tp_texture->pTexelData = new uint8[bytes];\r\n\t\tp_texture->byte_size = bytes;\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\t\tuint8 * pTex = p_texture->pTexelData;\r\n\t\tfor( uint32 mip_level = 0; mip_level < p_texture->Levels; ++mip_level )\r\n\t\t\t{\r\n\t\t\tmemcpy( pTex, p8[mip_level], mipbytes[mip_level] );\r\n\t\t\tdelete p8[mip_level];\r\n\t\t\tpTex += mipbytes[mip_level];\r\n\t\t}\r\n\r\n\t\t// Read alpha maps.\r\n\t\tif ( tex_format == 1 )\r\n\t\t{\r\n\t\t\tif ( channel == 0 )\r\n\t\t\t{\r\n\t\t\t\tbytes = 0;\r\n\t\t\t\tfor( uint32 mip_level = 0; mip_level < p_texture->Levels; ++mip_level )\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 texture_level_data_size;\r\n\t\t\t\t\tFile::Read( &texture_level_data_size,\t\t\tsizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t\t\t\tp8[mip_level] = new (Mem::Manager::sHandle().TopDownHeap()) uint8[texture_level_data_size];\r\n\t\t\t\t\tmipbytes[mip_level] = texture_level_data_size;\r\n\t\t\t\t\tbytes += texture_level_data_size;\r\n\r\n\t\t\t\t\tFile::Read( p8[mip_level], texture_level_data_size, 1, p_FH );\r\n\t\t\t\t}\r\n\t\t\t\t// Copy all textures & delete the originals.\r\n\t\t\t\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\t\t\t\tp_texture->pAlphaData = new uint8[bytes];\r\n\t\t\t\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\t\t\t\tuint8 * pTex = p_texture->pAlphaData;\r\n\t\t\t\tfor( uint32 mip_level = 0; mip_level < p_texture->Levels; ++mip_level )\r\n\t\t\t\t{\r\n\t\t\t\t\tmemcpy( pTex, p8[mip_level], mipbytes[mip_level] );\r\n\t\t\t\t\tdelete p8[mip_level];\r\n\t\t\t\t\tpTex += mipbytes[mip_level];\r\n\t\t\t\t}\r\n\t\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA;\r\n\r\n\t\t\t\tp_resolvem[num_resolve] = t;\r\n\t\t\t\tp_resolvec[num_resolve] = index;\r\n\t\t\t\tnum_resolve++;\r\n\t\t\t}\r\n\t\t\tswitch ( channel )\r\n\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_GREEN;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_RED;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_BLUE;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_SINGLE_OWNER;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No unique alpha map.\r\n\t\t\tp_texture->pAlphaData = NULL;\r\n\t\t\tp_texture->flags &= ~NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA;\r\n\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_GREEN;\r\n\t\t}\r\n\r\n\t\t// Add this texture to the table.\r\n//\t\tpTextureTable->PutItem( p_texture->Checksum, p_texture );\r\n\t\tNx::CNgcTexture *p_Ngc_texture = new Nx::CNgcTexture();\r\n\t\tp_Ngc_texture->SetEngineTexture( p_texture );\r\n\t\tif ( p_texture_table )\r\n\t\t{\r\n\t\t\tp_texture_table->PutItem( p_texture->Checksum, p_Ngc_texture );\r\n\t\t}\r\n\t}\r\n\r\n\t// Resolve alpha maps.\r\n\tfor ( int r = 0; r < num_resolve; r++ )\r\n\t{\r\n\t\tp_tex[p_resolvem[r]]->pAlphaData = p_tex[p_resolvec[r]]->pAlphaData;\r\n\t\tp_tex[p_resolvec[r]]->flags &= ~NxNgc::sTexture::TEXTURE_FLAG_SINGLE_OWNER;\r\n\t}\r\n\r\n\tFile::Close( p_FH );\r\n\r\n\tdelete p_tex;\r\n\tdelete p_resolvem;\r\n\tdelete p_resolvec;\r\n\r\n//\treturn pTextureTable;\r\n}\r\n\r\n\r\n\r\n\r\n//void Error(int err)\r\n//{\r\n//\tprintf(\"Error = %d\\n\", err);\r\n//\texit(1);\r\n//}\r\n\r\n} // namespace NxNgc\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/import.h",
    "content": "#ifndef __IMPORT_H\r\n#define __IMPORT_H\r\n\r\n#include <core/HashTable.h>\r\n#include \"texture.h\"\r\n#include \"gfx/nxtexture.h\"\r\n\r\nnamespace NxNgc\r\n{\r\n\r\nvoid LoadTextureFile( const char* Filename, Lst::HashTable<Nx::CTexture> * p_texture_table );\r\n\r\n} // namespace NxNgc\r\n\r\n\r\n#endif // __IMPORT_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/instance.cpp",
    "content": "#include \"nx_init.h\"\r\n#include \"instance.h\"\r\n#include \"anim.h\"\r\n#include \"render.h\"\r\n#include \"gfx\\camera.h\"\r\n#include \"gfx\\nx.h\"\r\n#include \"occlude.h\"\r\n#include \"charpipeline\\skinning.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n#include \"sys/ngc/p_aram.h\"\r\n#include \"sys/ngc/p_dma.h\"\r\n#include <gfx\\NxLight.h>\r\n#include \"sys/ngc/p_buffer.h\"\r\n#include <sys/profiler.h>\r\n#include \"sys/ngc/p_display.h\"\r\n\r\n#include \"dolphin/base/ppcwgpipe.h\"\r\n#include \"dolphin/gx/gxvert.h\"\r\n\r\nbool g_in_cutscene = false;\r\n\r\nint g_twiddle = 900;\r\n\r\nint g_hash_items = 0;\r\n\r\nint g_count = 0;\r\n\r\nfloat g_tweak = 0.0f;\r\n\r\nfloat NEAR_Z = 50.0f;\r\nfloat FAR_Z = 150.0f;\r\n\r\nfloat MIN_LEN = 10.0f;\r\nfloat MAX_LEN = 80.0f;\r\n\r\nextern int gNewRender;\r\nextern int g_object;\r\n\r\nextern bool g_mc_hack;\r\n\r\n//#define DEBUG_SPHERES\r\n\r\nextern \"C\" {\r\n\r\nextern void TransformSingle\t( ROMtx m, s16 * srcBase, s16 * dstBase, u32 count );\r\nextern void TransformDouble\t( ROMtx m0, ROMtx m1, s16 * wtBase, s16 * srcBase, s16 * dstBase, u32 count );\r\nextern void TransformAcc\t( ROMtx m, u16 count, s16 * srcBase, s16 * dstBase, u16 * indices, s16 * weights );\r\nextern void ConvertFixed196ToFloat\t( s16 * p_source, float * p_dest, int count );\r\nextern void CalculateDotProducts\t( s16 * p_xyz, u16 * p_index_list, float * p_dot, int count, float px, float py, float pz );\r\nextern void RenderShadows\t\t\t( s16 * p_xyz, u16 * p_index_list, NxNgc::sShadowEdge * p_neighbor_list, float * p_dot, int count, float px, float py, float pz, float tx, float ty, float tz );\r\n\r\n}\r\n\r\n//static char doubleBuffer0[(100*1024)+32];\r\n//static char doubleBuffer1[(100*1024)+32];\r\n//static uint32 *p_double[2] = { (uint32 *)OSRoundUp32B(doubleBuffer0), (uint32 *)OSRoundUp32B(doubleBuffer1) };\r\n//\r\n//static volatile bool\tdmaComplete;\r\n//\r\n//static void arqCallback( u32 pointerToARQRequest )\r\n//{\r\n//\tdmaComplete = true;\r\n//}\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n\r\n//Lst::HashTable< CInstance > *pInstanceTable\t= NULL;\r\n\r\nstatic Mth::Matrix\t*pLastBoneTransforms\t= NULL;\r\nCInstance\t\t\t*pFirstInstance\t\t\t= NULL;\r\n#if 0\r\nstatic CInstance\t*pAnimInstance[256];\r\nstatic int\t\t\tinstanceCount = 0;\r\n#endif\r\n\r\n#define INSTANCE_ARRAY_SIZE\t2048\r\nstatic CInstance *p_instances[INSTANCE_ARRAY_SIZE];\r\nint current_index = 0;\r\n\r\nvoid InitialiseInstanceTable( void )\r\n{\r\n//\tif( pInstanceTable == NULL )\r\n//\t{\r\n//\t\tpInstanceTable = new Lst::HashTable<CInstance>( 8 );\r\n//\t}\r\n}\r\n\r\n\r\n//bool frustum_check_sphere( NsVector * p_center, float radius )\r\n//{\r\n//\tbool visible = true;\r\n//\r\n//\tNsVector out;\r\n//\r\n//\tEngineGlobals.local_to_camera.multiply( p_center, &out );\r\n//\r\n//\tfloat x = out.x;\r\n//\tfloat y = out.y;\r\n//\tfloat z = out.z;\r\n//\tfloat R = radius;\r\n//\t\r\n//\tif (R<z-EngineGlobals.near || R<EngineGlobals.far-z || R<EngineGlobals.sy*z+EngineGlobals.cy*y || R<EngineGlobals.sy*z-EngineGlobals.cy*y || R<EngineGlobals.sx*z-EngineGlobals.cx*x || R<EngineGlobals.sx*z+EngineGlobals.cx*x) visible = false;\r\n//\r\n//\treturn visible;\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#ifdef DEBUG_SPHERES\r\nstatic void debug_render_sphere( Mth::Vector sphere, GXColor color )\r\n{\r\n\tGX::SetPointSize( 6, GX_TO_ONE );\r\n\r\n\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\r\n\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,\r\n\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t   GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\r\n\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n\tGX::SetChanMatColor( GX_COLOR0A0, color );\r\n\r\n\tGX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n\r\n\tGX::Begin( GX_LINES, GX_VTXFMT0, 6 ); \r\n\t\tGX::Position3f32( sphere[X] - sphere[W] , sphere[Y] , sphere[Z] );\r\n\t\tGX::Position3f32( sphere[X] + sphere[W] , sphere[Y] , sphere[Z] );\r\n\t\tGX::Position3f32( sphere[X] , sphere[Y] - sphere[W] , sphere[Z] );\r\n\t\tGX::Position3f32( sphere[X] , sphere[Y] + sphere[W] , sphere[Z] );\r\n\t\tGX::Position3f32( sphere[X] , sphere[Y] , sphere[Z] - sphere[W] );\r\n\t\tGX::Position3f32( sphere[X] , sphere[Y] , sphere[Z] + sphere[W] );\r\n\tGX::End();\r\n\r\n#define NUM_SEGMENTS 32\r\n#define SEGMENT_STEP ( 1.0f / (float)NUM_SEGMENTS )\r\n\r\n\tGX::Begin( GX_LINESTRIP, GX_VTXFMT0, NUM_SEGMENTS + 1 ); \r\n\tfor ( int lp = 0; lp < (NUM_SEGMENTS+1); lp++ )\r\n\t{\r\n\t\tGX::Position3f32( sphere[X] + ( sinf( Mth::PI * 2.0f * ( SEGMENT_STEP * (float)lp ) ) * sphere[W] ),\r\n\t\t\t\t\t\t  sphere[Y] + ( cosf( Mth::PI * 2.0f * ( SEGMENT_STEP * (float)lp ) ) * sphere[W] ),\r\n\t\t\t\t\t\t  sphere[Z] );\r\n\t}\r\n\tGX::End();\r\n\r\n\tGX::Begin( GX_LINESTRIP, GX_VTXFMT0, NUM_SEGMENTS + 1 ); \r\n\tfor ( int lp = 0; lp < (NUM_SEGMENTS+1); lp++ )\r\n\t{\r\n\t\tGX::Position3f32( sphere[X] + ( sinf( Mth::PI * 2.0f * ( SEGMENT_STEP * (float)lp ) ) * sphere[W] ),\r\n\t\t\t\t\t\t  sphere[Y],\r\n\t\t\t\t\t\t  sphere[Z] + ( cosf( Mth::PI * 2.0f * ( SEGMENT_STEP * (float)lp ) ) * sphere[W] ) );\r\n\t}\r\n\tGX::End();\r\n\r\n\tGX::Begin( GX_LINESTRIP, GX_VTXFMT0, NUM_SEGMENTS + 1 ); \r\n\tfor ( int lp = 0; lp < (NUM_SEGMENTS+1); lp++ )\r\n\t{\r\n\t\tGX::Position3f32( sphere[X],\r\n\t\t\t\t\t\t  sphere[Y] + ( sinf( Mth::PI * 2.0f * ( SEGMENT_STEP * (float)lp ) ) * sphere[W] ),\r\n\t\t\t\t\t\t  sphere[Z] + ( cosf( Mth::PI * 2.0f * ( SEGMENT_STEP * (float)lp ) ) * sphere[W] ) );\r\n\t}\r\n\tGX::End();\r\n}\r\n#endif DEBUG_SPHERES\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int sort_by_bone_transform( const void *p1, const void *p2 )\r\n{\r\n\tCInstance\t*p_mesh1\t\t= *((CInstance**)p1 );\r\n\tCInstance\t*p_mesh2\t\t= *((CInstance**)p2 );\r\n\r\n//\tMth::Matrix *p_mat1\t\t\t= p_mesh1->GetBoneTransforms();\r\n//\tMth::Matrix *p_mat2\t\t\t= p_mesh2->GetBoneTransforms();\r\n\t\r\n\t// Setup some required pointers for both transforms.\r\n\tuint32 p_mat1 = (uint32)p_mesh1->GetScene()->mp_dl->mp_object_header->m_num_skin_verts;\r\n\tuint32 p_mat2 = (uint32)p_mesh2->GetScene()->mp_dl->mp_object_header->m_num_skin_verts;\r\n\r\n\tif(( p_mat1 == 0 ) || ( p_mesh1->GetScene()->m_numHierarchyObjects > 0 ))\r\n\t{\r\n\t\tif(( p_mat2 == NULL ) || ( p_mesh2->GetScene()->m_numHierarchyObjects > 0 ))\r\n\t\t{\r\n\t\t\tint num_st1 = p_mesh1->GetScene()->m_num_filled_meshes - p_mesh1->GetScene()->m_num_opaque_meshes;\r\n\t\t\tint num_st2 = p_mesh2->GetScene()->m_num_filled_meshes - p_mesh2->GetScene()->m_num_opaque_meshes;\r\n\r\n\t\t\tif( num_st1 == num_st2 )\r\n\t\t\t{\r\n\t\t\t\t// Try sorting on the material draw order of the first semitransparent mesh.\r\n\t\t\t\tif( num_st1 > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tNxNgc::sMaterialHeader\t*p_material1 = p_mesh1->GetScene()->mpp_mesh_list[p_mesh1->GetScene()->m_num_opaque_meshes]->mp_dl->m_material.p_header;\r\n\t\t\t\t\tNxNgc::sMaterialHeader\t*p_material2 = p_mesh2->GetScene()->mpp_mesh_list[p_mesh2->GetScene()->m_num_opaque_meshes]->mp_dl->m_material.p_header; \r\n\r\n\t\t\t\t\tif( p_material1 && p_material2 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn ( p_material1->m_draw_order > p_material2->m_draw_order ) ? 1 : (( p_material1->m_draw_order < p_material2->m_draw_order ) ? -1 : 0 );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\r\n\t\t\treturn ( num_st1 > num_st2 ) ? 1 : -1;\r\n\t\t}\r\n\t\treturn 1;\r\n\t}\r\n\telse if(( p_mat2 == 0 ) || ( p_mesh2->GetScene()->m_numHierarchyObjects > 0 ))\r\n\t{\r\n\t\treturn -1;\r\n\t}\r\n\r\n\t// At this stage we know both instances have bone transforms.\r\n\tif( p_mat1 == p_mat2 )\r\n\t{\r\n\t\tint num_st1 = p_mesh1->GetScene()->m_num_filled_meshes - p_mesh1->GetScene()->m_num_opaque_meshes;\r\n\t\tint num_st2 = p_mesh2->GetScene()->m_num_filled_meshes - p_mesh2->GetScene()->m_num_opaque_meshes;\r\n\t\r\n\t\tif( num_st1 == num_st2 )\r\n\t\t\treturn 0;\r\n\t\r\n\t\treturn ( num_st1 > num_st2 ) ? 1 : -1;\r\n\t}\r\n\r\n\treturn((uint32)p_mat1 > (uint32)p_mat2 ) ? 1 : -1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid render_instance( CInstance *p_instance, uint32 flags )\r\n{\r\n//\t// Seed the static pointer off to NULL, otherwise if there is only one object with bone transforms, it will never update.\r\n//\tpLastBoneTransforms = NULL;\r\n//\r\n//\tif( p_instance->GetActive())\r\n//\t{\r\n//\t\t// Check whether this instance is visible.\r\n//\t\tset_frustum_bbox_transform( p_instance->GetTransform());\r\n//\t\tfloat sphere[4];\r\n//\t\tsphere[0] = p_instance->GetScene()->m_sphere_center.x;\r\n//\t\tsphere[1] = p_instance->GetScene()->m_sphere_center.y;\r\n//\t\tsphere[2] = p_instance->GetScene()->m_sphere_center.z;\r\n//\t\tsphere[3] = p_instance->GetScene()->m_sphere_radius;\r\n//\t\tif( frustum_check_sphere( sphere ))\r\n//\t\t{\r\n//\t\t\tif( !TestSphereAgainstOccluders( (Mth::Vector*)&p_instance->GetScene()->m_sphere_center, p_instance->GetScene()->m_sphere_radius ))\r\n//\t\t\t{\r\n//\t\t\t\tp_instance->Render( flags | vRENDER_OPAQUE | vRENDER_SEMITRANSPARENT );\r\n//\r\n////\t\t\t\t// Restore world transform to identity.\r\n////\t\t\t\tD3DDevice_SetTransform( D3DTS_WORLD, &EngineGlobals.world_matrix );\r\n////\t\t\t\tset_frustum_bbox_transform( NULL );\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid render_instances( uint32 flags )\r\n{\r\n\tint save_g_object = g_object;\r\n\r\n\tif( current_index > 0 )\r\n\t{\r\n\t\tint i = 0;\r\n\r\n//\t\tMth::Matrix *pLast = NULL;\r\n//\t\tROMtx bone_mtx[80];\r\n\r\n\t\tfor( ; i < current_index; ++i )\r\n\t\t{\r\n#ifndef __NOPT_FINAL__\r\n\t\t\tg_object = p_instances[i]->m_object_num;\r\n#endif\t\t// __NOPT_FINAL__\r\n//\t\t\tif ( ( flags & NxNgc::vRENDER_TRANSFORM ) && ( p_instances[i]->GetFlags() & NxNgc::CInstance::INSTANCE_FLAG_TRANSFORM_ME ) )\r\n//\t\t\t{\r\n////\t\t\t\tp_instances[i]->Transform( 0 /*flags*/ | vRENDER_OPAQUE | vRENDER_SEMITRANSPARENT, bone_mtx, pLast );\r\n////\t\t\t\tpLast = p_instances[i]->GetBoneTransforms();\r\n//\t\t\t\tp_instances[i]->ClearFlag( NxNgc::CInstance::INSTANCE_FLAG_TRANSFORM_ME );\r\n//\t\t\t}\r\n\r\n\t\t\tif(( p_instances[i]->GetBoneTransforms() == NULL ) || ( p_instances[i]->GetScene()->m_numHierarchyObjects > 0 ))\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tif(( flags & vRENDER_OPAQUE ) || (( flags & vRENDER_SEMITRANSPARENT ) && ( flags & vRENDER_INSTANCE_PRE_WORLD_SEMITRANSPARENT )))\r\n\t\t\t{\r\n\t\t\t\tp_instances[i]->Render( flags );\r\n//\t\t\t\tp_instances[i]->SetFlag( NxNgc::CInstance::INSTANCE_FLAG_TRANSFORM_ME );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfor( ; i < current_index; ++i )\r\n\t\t{\r\n#ifndef __NOPT_FINAL__\r\n\t\t\tg_object = p_instances[i]->m_object_num;\r\n#endif\t\t// __NOPT_FINAL__\r\n\r\n//\t\t\tif(( p_instances[i]->GetBoneTransforms()) && ( p_instances[i]->GetScene()->m_numHierarchyObjects == 0 ))\r\n//\t\t\t\tbreak;\r\n\r\n\t\t\tif(( flags & vRENDER_OPAQUE ) || (( flags & vRENDER_SEMITRANSPARENT ) && ( flags & vRENDER_INSTANCE_POST_WORLD_SEMITRANSPARENT )))\r\n\t\t\t{\r\n\t\t\t\tp_instances[i]->Render( flags );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tg_object = save_g_object;\r\n}\r\n\r\nvoid CInstance::Transform( uint32 flags, ROMtx * p_mtx_buffer, Mth::Matrix *p_mtx_last )\r\n{\r\n//#\tifdef __USE_PROFILER__\r\n////\tSys::VUProfiler->PushContext( 128,0,0 );\r\n//#\tendif\t\t// __USE_PROFILER__\r\n\r\n//\tif ( gNewRender ) render_flags |= NxNgc::vRENDER_NEW_TEST;\r\n\r\n\tif( GetBoneTransforms() && ( GetScene()->m_numHierarchyObjects == 0 ) )\r\n\t{\r\n\t\t// Has bone transforms, is therefore an animated object such as a skater, pedestrian etc.\r\n\t\tmp_posNormRenderBuffer = GetPosNormalBuffer( 0 );\r\n\r\n\t\tif ( !p_mtx_last || ( GetBoneTransforms() != p_mtx_last ) )\r\n\t\t{\r\n\t\t\tfloat * ps;\r\n\t\t\tfloat * pd;\r\n\t\t\tfor( int i = 0; i < GetNumBones(); ++i )\r\n\t\t\t{\r\n\t\t\t\tps = (float*)&GetBoneTransforms()[i];\r\n\t\t\t\tpd = (float*)&p_mtx_buffer[i][0][0];\r\n\r\n\t\t\t\t*pd++ = *ps++;\r\n\t\t\t\t*pd++ = *ps++;\r\n\t\t\t\t*pd++ = *ps++;\r\n\t\t\t\tps++;\r\n\t\t\t\t*pd++ = *ps++;\r\n\t\t\t\t*pd++ = *ps++;\r\n\t\t\t\t*pd++ = *ps++;\r\n\t\t\t\tps++;\r\n\t\t\t\t*pd++ = *ps++;\r\n\t\t\t\t*pd++ = *ps++;\r\n\t\t\t\t*pd++ = *ps++;\r\n\t\t\t\tps++;\r\n\t\t\t\t*pd++ = *ps++;\r\n\t\t\t\t*pd++ = *ps++;\r\n\t\t\t\t*pd++ = *ps++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Setup some required pointers for both transforms.\r\n//\t\tsMesh*\tp_mesh = GetScene()->mpp_mesh_list[0];\r\n//\t\tif ( GetScene()->m_num_opaque_entries )\r\n//\t\t{\r\n//\t\t\tp_mesh = GetScene()->m_opaque_meshes[0];\r\n//\t\t}\r\n//\t\telse if ( GetScene()->m_num_semitransparent_entries )\r\n//\t\t{\r\n//\t\t\tp_mesh = GetScene()->m_semitransparent_meshes[0];\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tDbg_MsgAssert(0, (\"No meshes in scene.\"));\r\n//\t\t\tp_mesh = NULL;\r\n//\t\t}\r\n\r\n\t\t// Transform the single lists.\r\n\t\tuint32*\tp32 = (uint32 *)GetScene()->mp_dl->mp_object_header->m_skin.p_data;\r\n\t\ts16*\tp_pos = mp_posNormRenderBuffer;\r\n\t\tfor ( uint32 lp = 0; lp < GetScene()->mp_dl->mp_object_header->m_num_single_lists; lp++ ) {\r\n\t\t\tuint32\t\tpairs = *p32++;\r\n\t\t\tuint32\t\tmtx = *p32++;\r\n\t\t\ts16*\t\tp_pn = (s16 *)p32;\r\n\t\t\tROMtxPtr\tp_bone = p_mtx_buffer[mtx];\r\n\t\r\n\t\t\tTransformSingle( p_bone, p_pn, p_pos, pairs == 1 ? 2 : pairs ); \r\n\t\t\tp_pos += (6 * pairs);\r\n\t\t\tp32 = (uint32 *)&p_pn[pairs*6];\r\n\t\t}\r\n\r\n\t\t// Transform the double lists.\r\n\t\tfor ( uint32 lp = 0; lp < GetScene()->mp_dl->mp_object_header->m_num_double_lists; lp++ ) {\r\n\t\t\tuint32\t\tpairs = *p32++;\r\n\t\t\tuint32\t\tmtx = *p32++;\r\n\t\t\ts16*\t\tp_pn = (s16 *)p32;\r\n\t\t\tROMtxPtr\tp_bone0 = p_mtx_buffer[mtx&255];\r\n\t\t\tROMtxPtr\tp_bone1 = p_mtx_buffer[(mtx>>8)&255];\r\n\t\t\ts16*\t\tp_weight = (s16 *)&p_pn[(6*pairs)];\r\n\t\r\n\t\t\tTransformDouble( p_bone0, p_bone1, p_weight, p_pn, p_pos, pairs == 1 ? 2 : pairs ); \r\n\t\t\tp_pos += (6 * pairs);\r\n\t\t\tp32 = (uint32 *)&p_weight[pairs*2];\r\n\t\t}\r\n\r\n\t\t// Transform the acc lists.\r\n\t\tfor ( uint32 lp = 0; lp < GetScene()->mp_dl->mp_object_header->m_num_add_lists; lp++ ) {\r\n\t\t\tuint32\t\tsingles = *p32++;\r\n\t\t\tuint32\t\tmtx = *p32++;\r\n\t\t\ts16*\t\tp_pn = (s16 *)p32;\r\n\t\t\tROMtxPtr\tp_bone = p_mtx_buffer[mtx];\r\n\t\t\ts16*\t\tp_weight = (s16 *)&p_pn[(6*singles)];\r\n\t\t\tuint16*\t\tp_index = (uint16 *)&p_weight[singles];\r\n\t\t\t\r\n\t\t\tTransformAcc( p_bone, singles, p_pn, mp_posNormRenderBuffer, p_index, p_weight ); \r\n//\t\t\tp32 = (uint32 *)&p_index[singles+(singles&1)];\r\n\t\t\tp32 = (uint32 *)&p_index[singles];\r\n\t\t}\r\n\r\n\r\n\r\n//\t\tint num_vertex;\r\n//\t\tif ( mp_scene->m_num_opaque_entries )\r\n//\t\t{\r\n//\t\t\tnum_vertex = mp_scene->m_opaque_meshes[0]->m_num_vertex;\r\n//\t\t}\r\n//\t\telse if ( mp_scene->m_num_semitransparent_entries )\r\n//\t\t{\r\n//\t\t\tnum_vertex = mp_scene->m_semitransparent_meshes[0]->m_num_vertex;\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tDbg_MsgAssert(0, (\"No meshes in scene.\"));\r\n//\t\t\tnum_vertex = 0;\r\n//\t\t}\r\n//\r\n\t\tint num_vertex = GetScene()->mp_dl->mp_object_header->m_num_skin_verts;\r\n\t\tDCFlushRange ( mp_posNormRenderBuffer, sizeof ( s16 ) * 6 * ( num_vertex + 1 ) );\r\n\t}\r\n//#\tifdef __USE_PROFILER__\r\n////\tSys::VUProfiler->PopContext(  );\r\n//#\tendif\t\t// __USE_PROFILER__\r\n}\r\n\r\n\r\n\r\nvoid CInstance::Render( uint32 flags )\r\n{\r\n\tuint32 render_flags = flags;\r\n//\tif ( gNewRender ) render_flags |= NxNgc::vRENDER_NEW_TEST;\r\n\r\n\tNsMatrix\troot;\r\n\r\n\troot.setRightX( GetTransform()->GetRight()[X] );\r\n\troot.setRightY( GetTransform()->GetUp()[X] );\r\n\troot.setRightZ( GetTransform()->GetAt()[X] );\r\n\r\n\troot.setUpX( GetTransform()->GetRight()[Y] ); \r\n\troot.setUpY( GetTransform()->GetUp()[Y] );    \r\n\troot.setUpZ( GetTransform()->GetAt()[Y] );    \r\n\r\n\troot.setAtX( GetTransform()->GetRight()[Z] ); \r\n\troot.setAtY( GetTransform()->GetUp()[Z] );    \r\n\troot.setAtZ( GetTransform()->GetAt()[Z] );    \r\n\r\n\troot.setPosX( GetTransform()->GetPos()[X] );\r\n\troot.setPosY( GetTransform()->GetPos()[Y] );\r\n\troot.setPosZ( GetTransform()->GetPos()[Z] );\r\n\r\n//\tMth::Vector world_sphere(GetScene()->m_sphere_center.x,GetScene()->m_sphere_center.y,GetScene()->m_sphere_center.z);\r\n//\tworld_sphere[W] = 1.0f;\r\n//\tworld_sphere *= *GetTransform();\t\t\t\t\t\t\t// => use mp_transform\r\n//\tif (TestSphereAgainstOccluders( &world_sphere, GetScene()->m_sphere_radius ))\r\n//\t{\r\n//\t\treturn;\r\n//\t}\r\n\r\n\t// Create & upload current view matrix.\r\n\tNsMatrix\ttr;\r\n\ttr.cat( EngineGlobals.world_to_camera, root );\r\n\tGX::LoadPosMtxImm( (MtxPtr)&tr, GX_PNMTX0 );\r\n\r\n\t// Need to force the current matrix to be just incase hierarchical models change it to 1.\r\n\tif ( render_flags & vRENDER_SHADOW_1ST_PASS )\r\n\t{\r\n\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\t}\r\n\r\n//\tif ( !( render_flags & vRENDER_SHADOW_1ST_PASS ) )\r\n\t{\r\n\t\t//NsMatrix inv;\r\n\t\t//inv.invert( root );\r\n\t\t//GX::LoadNrmMtxImm((MtxPtr)&inv, GX_PNMTX0);\r\n//\t\ttr.cat( EngineGlobals.camera, root );\r\n//\t\ttr.invert( root/*EngineGlobals.world_to_camera*/ );\r\n\t\r\n\t\tNx::CModelLights *p_lights = GetModel() ? GetModel()->GetModelLights() : NULL;\r\n\t\tif( p_lights )\r\n\t\t{\r\n\t\t\tp_lights->UpdateEngine( GetTransform()->GetPos(), true );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tNx::CLightManager::sUpdateEngine();\r\n\t\t}\r\n\t}\r\n\tMTXCopy ( (MtxPtr)&tr, EngineGlobals.current_uploaded );\r\n\r\n\tEngineGlobals.local_to_camera.copy( tr );\r\n\r\n\tEngineGlobals.object_pos.x = tr.getPosX();\r\n\tEngineGlobals.object_pos.y = tr.getPosY();\r\n\tEngineGlobals.object_pos.z = tr.getPosZ();\r\n\r\n\r\n\r\n\r\n#ifdef DEBUG_SPHERES\r\n\tif( GetBoneTransforms() && ( GetScene()->m_numHierarchyObjects == 0 ) )\r\n\t{\r\n\t\tMth::Vector sphere = GetScene()->mpp_mesh_list[0]->mp_dl->mp_object_header->m_sphere;\r\n\t\tdebug_render_sphere( sphere, (GXColor){255,0,0,255} );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( GetScene()->m_numHierarchyObjects && GetBoneTransforms() )\r\n\t\t{\r\n\t\t\t// Car or something...\r\n\t\t\tMth::Vector sphere = GetScene()->m_sphere;\t//mpp_mesh_list[0]->mp_dl->mp_object_header->m_sphere;\r\n\t\t\tdebug_render_sphere( sphere, (GXColor){0,255,0,255} );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No bones, just render normally. Must be a trashcan or something.\r\n\t\t\tMth::Vector sphere = GetScene()->mpp_mesh_list[0]->mp_dl->mp_object_header->m_sphere;\r\n\t\t\tdebug_render_sphere( sphere, (GXColor){0,0,255,255} );\r\n\t\t}\r\n\t}\r\n#endif\t\t// DEBUG_SPHERES\r\n\r\n\r\n\r\n\r\n\r\n\tGXLightObj light_obj[3];\r\n\r\n\t// Always set ambient & diffuse colors.\r\n\tGX::SetChanAmbColor( GX_COLOR0A0, NxNgc::EngineGlobals.ambient_light_color );\r\n//\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){128,128,128,255} );\r\n//\t\t\t\tGX::SetChanAmbColor( GX_COLOR1A1, NxNgc::EngineGlobals.ambient_light_color );\r\n\r\n\tGX::InitLightColor( &light_obj[0], NxNgc::EngineGlobals.diffuse_light_color[0] );\r\n\tGX::InitLightPos( &light_obj[0], NxNgc::EngineGlobals.light_x[0], NxNgc::EngineGlobals.light_y[0], NxNgc::EngineGlobals.light_z[0] );\r\n\tGX::LoadLightObjImm( &light_obj[0], GX_LIGHT0 );\r\n\r\n\tGX::InitLightColor( &light_obj[1], NxNgc::EngineGlobals.diffuse_light_color[1] );\r\n\tGX::InitLightPos( &light_obj[1], NxNgc::EngineGlobals.light_x[1], NxNgc::EngineGlobals.light_y[1], NxNgc::EngineGlobals.light_z[1] );\r\n\tGX::LoadLightObjImm( &light_obj[1], GX_LIGHT1 );\r\n\r\n\tGX::InitLightColor( &light_obj[2], NxNgc::EngineGlobals.diffuse_light_color[2] );\r\n\tGX::InitLightPos( &light_obj[2], NxNgc::EngineGlobals.light_x[2], NxNgc::EngineGlobals.light_y[2], NxNgc::EngineGlobals.light_z[2] );\r\n\tGX::LoadLightObjImm( &light_obj[2], GX_LIGHT2 );\r\n\r\n\t// Set channel control for diffuse.\r\n\tGX::SetChanCtrl( GX_COLOR0, GX_ENABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT0|GX_LIGHT1|GX_LIGHT2, GX_DF_CLAMP, GX_AF_NONE );\r\n\tGX::SetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ); \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\tif( GetBoneTransforms() && ( GetScene()->m_numHierarchyObjects == 0 ) )\r\n\t{\r\n\t\t// Has bone transforms, is therefore an animated object such as a skater, pedestrian etc.\r\n\r\n//\t\tif ( ( flags & vRENDER_SHADOW_1ST_PASS ) && GetScene()->mp_scene_data && GetScene()->mp_scene_data->m_num_shadow_faces && !g_in_cutscene )\r\n//\t\t{\r\n//\t\t\tf32 p_pm[GX_PROJECTION_SZ];\r\n//\t\t\tGX::GetProjectionv( p_pm );\r\n//\t\t\tfloat value = p_pm[6] + ( (float)(-g_twiddle) ) * p_pm[5];\r\n//\r\n//\t\t\tGXWGFifo.u8 = GX_LOAD_XF_REG;\r\n//\t\t\tGXWGFifo.u16 = 0;\r\n//\t\t\tGXWGFifo.u16 = 0x1025;\r\n//\t\t\tGXWGFifo.f32 = value;\r\n//\r\n//\r\n//\t\t\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_FRONT ); \r\n//\t\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n//\t\t\tGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0 );\r\n//\r\n//\t\t\tGX::SetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0,\r\n//\t\t\t\t\t\t\t\t\t\t   GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );\r\n//\r\n//\t\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0,\tGX_CA_KONST, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\tGX::SetTevColorInOp( GX_TEVSTAGE0,\t\tGX_CC_KONST, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\r\n//\t\t\tGX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n//\r\n//\t\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\r\n////\t\t\tGX::SetZMode( GX_TRUE, GX_GREATER, GX_FALSE );\r\n////\t\t\tGX::SetZMode( GX_TRUE, GX_GREATER, GX_FALSE );\r\n//\t\t\tGX::SetZMode(GX_TRUE, GX_LEQUAL, GX_FALSE);\r\n//\r\n//\t\t\tGX::SetTevKColor( GX_KCOLOR0, (GXColor){4,4,4,4} );\r\n//\t\t\tGX::SetTevKSel( GX_TEVSTAGE0, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A );\r\n//\r\n////\t\t\tif ( !g_in_cutscene ) GX::SetClipMode( GX_CLIP_DISABLE );\r\n//\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\r\n//\r\n//\t\t\tfloat px = 0.0f;\t//NxNgc::EngineGlobals.skater_shadow_dir.x;\r\n//\t\t\tfloat py = -1.0f;    //NxNgc::EngineGlobals.skater_shadow_dir.y * 3.0f;\r\n//\t\t\tfloat pz = 0.0f;    //NxNgc::EngineGlobals.skater_shadow_dir.z;\r\n//\r\n//\t\t\tfloat l = sqrtf( ( px * px ) + ( py * py ) + ( pz * pz ) );\r\n//\r\n//\t\t\tpx /= l;\r\n//\t\t\tpy /= l;\r\n//\t\t\tpz /= l;\r\n//\r\n////#define NEAR_Z 50.0f\r\n////#define FAR_Z 120.0f\r\n////\r\n////#define MIN_LEN 10.0f\r\n////#define MAX_LEN 100.0f\r\n//\r\n//\t\t\t// Shorten length if:\r\n//\t\t\t// 1. light vector & object vector are opposing.\r\n//\t\t\t// AND\r\n//\t\t\t// 2. camera is not above player.\r\n//\t\t\t// AND\r\n//\t\t\t// 3. camera is close to the object.\r\n//\t\t\tfloat base_length = MAX_LEN;\r\n//\r\n////\t\t\tfloat cx = NxNgc::EngineGlobals.camera.getPosX() - GetTransform()->GetPos()[X];\r\n////\t\t\tfloat cy = NxNgc::EngineGlobals.camera.getPosY() - GetTransform()->GetPos()[Y];\r\n////\t\t\tfloat cz = NxNgc::EngineGlobals.camera.getPosZ() - GetTransform()->GetPos()[Z];\r\n//\r\n////\t\t\tfloat obj_len = sqrtf( ( cx * cx ) + /*( cy * cy ) +*/ ( cz * cz ) );\r\n//\r\n////\r\n////\t\t\t// Fabricate a worst-case vector.\r\n////\t\t\t// 1st, pick a point at the head of the skater.\r\n////\t\t\tfloat wx = 0.0f;\r\n////\t\t\tfloat wy = 12.0f * 7.0f;\t\t// Assuming 7ft skater.\r\n////\t\t\tfloat wz = 0.0f;\r\n////\r\n////\t\t\t// 2nd, move towards camera by average value.\r\n////\t\t\twx += ( cx / obj_len ) * ( 12.0f * 3.0f );\r\n////\t\t\twy += ( cy / obj_len ) * ( 12.0f * 3.0f );\r\n////\t\t\twz += ( cz / obj_len ) * ( 12.0f * 3.0f );\r\n////\r\n//\t\t\t\r\n////\t\t\tfloat cam_dir_dot = ( px * cx ) + /*( py * cy ) +*/ ( pz * cz );\r\n////\r\n//////\t\t\tOSReport( \"Object len: %8.3f\\n\", obj_len );\r\n////\r\n////\t\t\tif ( ( ( cam_dir_dot > -0.0f ) || ( obj_len <= NEAR_Z ) ) && ( cy < 100.0f ) )\r\n////\t\t\t{\r\n////\t\t\t\t// Opposing, get length.\r\n////\t\t\t\tif ( obj_len < FAR_Z )\r\n////\t\t\t\t{\r\n////\t\t\t\t\tif ( obj_len > NEAR_Z )\r\n////\t\t\t\t\t{\r\n////\t\t\t\t\t\t// Close enough, adjust base length.\r\n////\t\t\t\t\t\tbase_length = MIN_LEN + ( ( ( obj_len - NEAR_Z ) * ( MAX_LEN - MIN_LEN ) ) / ( FAR_Z - NEAR_Z ) );\r\n////\t\t\t\t\t}\r\n////\t\t\t\t\telse\r\n////\t\t\t\t\t{\r\n////\t\t\t\t\t\t// Close enough, adjust base length.\r\n////\t\t\t\t\t\tbase_length = MIN_LEN;\r\n////\t\t\t\t\t}\r\n////\t\t\t\t}\r\n////\t\t\t}\r\n////\r\n//\t\t\tfloat length = NxNgc::EngineGlobals.skater_height + base_length;\r\n//\r\n//\t\t\troot.setRightX( GetTransform()->GetRight()[X] );\r\n//\t\t\troot.setRightY( GetTransform()->GetRight()[Y] );\r\n//\t\t\troot.setRightZ( GetTransform()->GetRight()[Z] );\r\n//\r\n//\t\t\troot.setUpX( GetTransform()->GetUp()[X] );\r\n//\t\t\troot.setUpY( GetTransform()->GetUp()[Y] );\r\n//\t\t\troot.setUpZ( GetTransform()->GetUp()[Z] );\r\n//\r\n//\t\t\troot.setAtX( GetTransform()->GetAt()[X] );\r\n//\t\t\troot.setAtY( GetTransform()->GetAt()[Y] );\r\n//\t\t\troot.setAtZ( GetTransform()->GetAt()[Z] );\r\n//\r\n//\t\t\troot.setPosX( 0.0f );\r\n//\t\t\troot.setPosY( 0.0f );\r\n//\t\t\troot.setPosZ( 0.0f );\r\n//\r\n//\t\t\tNsVector in, out;\r\n//\r\n//\t\t\tin.x = px;\r\n//\t\t\tin.y = py;\r\n//\t\t\tin.z = pz;\r\n//\t\t\troot.multiply( &in, &out );\r\n//\t\t\tpx = out.x;\r\n//\t\t\tpy = out.y;\r\n//\t\t\tpz = out.z;\r\n//\r\n//\t\t\tfloat tx = px * g_tweak;\r\n//\t\t\tfloat ty = py * g_tweak;\r\n//\t\t\tfloat tz = pz * g_tweak;\r\n//\r\n//\t\t\tpx *= length;\r\n//\t\t\tpy *= length;\r\n//\t\t\tpz *= length;\r\n//\r\n//\t\t\tint num_shadow_faces = GetScene()->mp_scene_data->m_num_shadow_faces;\r\n//\r\n//\t\t\tfloat p_dot[4096];\r\n//\t\t\tCalculateDotProducts( mp_posNormRenderBuffer, GetScene()->mp_shadow_volume_mesh, p_dot, num_shadow_faces, px, py, pz );\r\n//#if 1\r\n//\t\t\tRenderShadows( mp_posNormRenderBuffer, GetScene()->mp_shadow_volume_mesh, GetScene()->mp_shadow_edge, p_dot, num_shadow_faces, px, py, pz, tx, ty, tz );\r\n//#else\r\n//\t\t\tfloat * p_xyz = new float[mp_scene->mp_dl->mp_object_header->m_num_skin_verts*3];\r\n//\t\t\tConvertFixed196ToFloat( mp_posNormRenderBuffer, p_xyz, mp_scene->mp_dl->mp_object_header->m_num_skin_verts );\r\n//\r\n//\t\t\tfor ( uint lp = 0; lp < GetScene()->mp_scene_data->m_num_shadow_faces; lp++ )\r\n//\t\t\t{\r\n//\t\t\t\tfloat dot = p_dot[lp];\r\n//\r\n//\t\t\t\tif ( dot > 0 )\r\n//\t\t\t\t{\r\n////\t\t\t\t\t// See if we have to draw all sides.\r\n////\t\t\t\t\t// Check 01.\r\n//\t\t\t\t\tint shape = 0;\r\n//\t\t\t\t\tif ( ( GetScene()->mp_shadow_edge[lp].neighbor[0] == -1 ) || ( p_dot[ GetScene()->mp_shadow_edge[lp].neighbor[0] ] <= 0 ) )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tshape |= (1<<0);\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\t// Check 12.\r\n//\t\t\t\t\tif ( ( GetScene()->mp_shadow_edge[lp].neighbor[1] == -1 ) || ( p_dot[ GetScene()->mp_shadow_edge[lp].neighbor[1] ] <= 0 ) )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tshape |= (1<<1);\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\t// Check 23.\r\n//\t\t\t\t\tif ( ( GetScene()->mp_shadow_edge[lp].neighbor[2] == -1 ) || ( p_dot[ GetScene()->mp_shadow_edge[lp].neighbor[2] ] <= 0 ) )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tshape |= (1<<2);\r\n//\t\t\t\t\t}\r\n//\r\n//\t\t\t\t\tunsigned short idx0 = GetScene()->mp_shadow_volume_mesh[(lp*3)+0];\r\n//\t\t\t\t\tunsigned short idx1 = GetScene()->mp_shadow_volume_mesh[(lp*3)+1];\r\n//\t\t\t\t\tunsigned short idx2 = GetScene()->mp_shadow_volume_mesh[(lp*3)+2];\r\n//\r\n//\t\t\t\t\tfloat x0 = p_xyz[(idx0*3)+0];\r\n//\t\t\t\t\tfloat y0 = p_xyz[(idx0*3)+1];\r\n//\t\t\t\t\tfloat z0 = p_xyz[(idx0*3)+2];\r\n//\r\n//\t\t\t\t\tfloat x1 = p_xyz[(idx1*3)+0];\r\n//\t\t\t\t\tfloat y1 = p_xyz[(idx1*3)+1];\r\n//\t\t\t\t\tfloat z1 = p_xyz[(idx1*3)+2];\r\n//\r\n//\t\t\t\t\tfloat x2 = p_xyz[(idx2*3)+0];\r\n//\t\t\t\t\tfloat y2 = p_xyz[(idx2*3)+1];\r\n//\t\t\t\t\tfloat z2 = p_xyz[(idx2*3)+2];\r\n//\r\n//\t\t\t\t\tfloat x3 = x0 + px;\r\n//\t\t\t\t\tfloat y3 = y0 + py;\r\n//\t\t\t\t\tfloat z3 = z0 + pz;\r\n//\t\r\n//\t\t\t\t\tfloat x4 = x1 + px;\r\n//\t\t\t\t\tfloat y4 = y1 + py;\r\n//\t\t\t\t\tfloat z4 = z1 + pz;\r\n//\t\r\n//\t\t\t\t\tfloat x5 = x2 + px;\r\n//\t\t\t\t\tfloat y5 = y2 + py;\r\n//\t\t\t\t\tfloat z5 = z2 + pz;\r\n//\r\n//\t\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_FALSE, GX_TRUE, GX_FALSE );\r\n//\r\n//\t\t\t\t\tswitch ( shape )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tcase 0:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLES, GX_VTXFMT0, 3 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLES, GX_VTXFMT0, 3 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 1:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 2:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 3:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 8 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 4:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 5:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 8 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 6:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 8 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 7:\r\n//\t\t\t\t\t\tdefault:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 10 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\tGX::SetBlendMode ( GX_BM_SUBTRACT, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_FALSE, GX_TRUE, GX_FALSE );\r\n//\r\n//\t\t\t\t\tswitch ( shape )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tcase 0:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLES, GX_VTXFMT0, 3 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLES, GX_VTXFMT0, 3 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 1:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 2:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 3:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 8 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 4:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 5:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 8 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 6:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 8 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 7:\r\n//\t\t\t\t\t\tdefault:\r\n//\t\t\t\t\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 10 ); \r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x1, y1, z1 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x4, y4, z4 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x3, y3, z3 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x5, y5, z5 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x0, y0, z0 );\r\n//\t\t\t\t\t\t\tGX::Position3f32( x2, y2, z2 );\r\n//\t\t\t\t\t\t\tGX::End();\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\tdelete p_xyz;\r\n//#endif\r\n//\t\t\tGX::SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);\r\n////\t\t\tif ( !g_in_cutscene ) GX::SetClipMode( GX_CLIP_ENABLE );\r\n//\t\t\tGX::SetProjectionv( p_pm );\r\n//\t\t}\r\n//\t\telse\r\n\t\t{\r\n\t\t\tGX::LoadNrmMtxImm((MtxPtr)&root, GX_PNMTX0);\r\n\t\t\t// Render the scene & see if any meshes were drawn. If so, transform the\r\n\t\t\t// vertex buffer for use when the GPU comes to actually render it..\r\n\t\t\tNxNgc::EngineGlobals.poly_culling = false;\r\n\r\n\t\t\tmake_scene_visible( GetScene() );\r\n\t\t\tGX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );\r\n\t\t\tGX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );\r\n\t\t\tGX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );\r\n\t\t\tGX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );\r\n\t\t\tGX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );\r\n\t\t\tGX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );\r\n\t\t\trender_scene( GetScene(), mp_posNormRenderBuffer, render_flags | vRENDER_NO_CULLING );\r\n\t\t\tGX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n\t\t\tGX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n\t\t\tGX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n\t\t\tGX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n\t\t\tGX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n\t\t\tGX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( ( m_flags & CInstance::INSTANCE_FLAG_LIGHTING_ALLOWED ) == 0 ) render_flags |= NxNgc::vRENDER_LIT;\r\n\t\tGX::LoadNrmMtxImm((MtxPtr)&tr, GX_PNMTX0);\r\n\t\tif ( GetScene()->m_numHierarchyObjects && GetBoneTransforms() )\r\n\t\t{\r\n\t\t\t// Car or something...\r\n\t\t\tNxNgc::EngineGlobals.poly_culling = true;\r\n\t\t\tmake_scene_visible( GetScene() );\r\n\t\t\trender_scene( GetScene(), NULL, render_flags | vRENDER_NO_CULLING, GetBoneTransforms(), GetTransform(), GetNumBones() );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif( ( m_flags & CInstance::INSTANCE_FLAG_LIGHTING_ALLOWED ) == 0 ) render_flags |= NxNgc::vRENDER_LIT;\r\n\t\t\t// No bones, just render normally. Must be a trashcan or something.\r\n\t\t\tNxNgc::EngineGlobals.poly_culling = false;\r\n\t\t\tmake_scene_visible( GetScene() );\r\n//\t\t\tint meshes_rendered = cull_scene( GetScene(), vRENDER_OCCLUDED, GetTransform() ); \r\n\t\t\trender_scene( GetScene(), NULL, render_flags );\r\n//\t\t\tSetMeshesRendered( meshes_rendered );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\nvoid process_instances( void )\r\n{\r\n\tcurrent_index = 0;\r\n\t\r\n\tif ( g_mc_hack ) return;\r\n\r\n\t// Seed the static pointer off to NULL, otherwise if there is only one object with bone transforms, it will never update.\r\n\tpLastBoneTransforms = NULL;\r\n\t\r\n\t// First go through and build a list of the visible instances.\r\n\tCInstance *p_instance = pFirstInstance;\r\n\twhile( p_instance )\r\n\t{\r\n#ifndef __NOPT_FINAL__\r\n\t\tp_instance->m_object_num = g_object;\r\n\t\tg_object++;\r\n#endif\t\t// __NOPT_FINAL__\r\n\t\tif( p_instance->GetActive() && p_instance->GetScene()->mp_scene_data )\r\n\t\t{\r\n\t\t\tp_instances[current_index++] = p_instance;\r\n\t\t}\r\n\t\tp_instance = p_instance->GetNextInstance();\r\n\t}\r\n\r\n\tint save_g_object = g_object;\r\n\r\n\t// Now sort the list based on bone transform and number of semitransparent objects in scene.\r\n\tif( current_index > 0 )\r\n\t{\r\n\t\tif( current_index > 1 ) qsort( p_instances, current_index, sizeof( CInstance* ), sort_by_bone_transform );\r\n\t\r\n\t\tint i = 0;\r\n\t\tMth::Matrix *pLast = NULL;\r\n\t\tROMtx bone_mtx[60];\r\n\r\n\t\tfor( ; i < current_index; ++i )\r\n\t\t{\r\n#ifndef __NOPT_FINAL__\r\n\t\t\tg_object = p_instances[i]->m_object_num;\r\n#endif\t\t// __NOPT_FINAL__\r\n\r\n\t\t\tif(( p_instances[i]->GetBoneTransforms() == NULL ) || ( p_instances[i]->GetScene()->m_numHierarchyObjects > 0 ))\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tp_instances[i]->Transform( 0 /*flags*/ | vRENDER_OPAQUE | vRENDER_SEMITRANSPARENT, bone_mtx, pLast );\r\n\t\t\tpLast = p_instances[i]->GetBoneTransforms();\r\n\t\t}\r\n\r\n//\t\tfor( ; i < current_index; ++i )\r\n//\t\t{\r\n//#ifndef __NOPT_FINAL__\r\n//\t\t\tg_object = p_instances[i]->m_object_num;\r\n//#endif\t\t// __NOPT_FINAL__\r\n//\r\n//\t\t\tp_instances[i]->Transform( 0 /*flags*/ | vRENDER_OPAQUE | vRENDER_SEMITRANSPARENT, NULL, NULL );\r\n//\t\t}\r\n\t}\r\n\tg_object = save_g_object;\r\n}\r\n\r\n\r\n\r\ns16\t*CInstance::GetPosNormalBuffer( int buffer )\r\n{\r\n\tint num_vertex = mp_scene->mp_dl->mp_object_header->m_num_skin_verts;\r\n\tDbg_MsgAssert(num_vertex, (\"No verts in scene.\"));\r\n\r\n\ts16 * rv = (s16*)NsBuffer::alloc( sizeof(s16) * 6 * (num_vertex+1) ); \r\n\treturn rv;\r\n}\r\n\r\nCInstance::CInstance( sScene *pScene, Mth::Matrix &transform, int numBones, Mth::Matrix *pBoneTransforms )\r\n{\r\n\tSetTransform( transform );\r\n\tmp_bone_transforms\t= pBoneTransforms;\r\n\tm_num_bones\t\t\t= numBones;\r\n\tmp_scene\t\t\t= pScene;\r\n\tm_active\t\t\t= true;\r\n\tm_flags\t\t\t\t= 0;\r\n\tmp_model\t\t\t= NULL;\r\n\r\n\tmp_next_instance\t= pFirstInstance;\r\n\tpFirstInstance\t\t= this;\r\n\r\n\tmp_posNormBuffer = NULL;\r\n\tm_visibility_mask = 0xff;\r\n\r\n\t// Check to see whether this instance is allowed to be lit or not (for non-skinned instances).\r\n\t// Currently, we assume that instances with a model containing valid normals requires lighting, except in the\r\n\t// situation where that model contains a mesh specifically flagged not to be lit.\r\n\tif(( pBoneTransforms == NULL ) || ( GetScene()->m_numHierarchyObjects > 0 ))\r\n\t{\r\n\t\tfor( int m = 0; m < pScene->m_num_filled_meshes; ++m )\r\n\t\t{\r\n\t\t\tNxNgc::sMesh *p_mesh = pScene->mpp_mesh_list[m];\r\n\t\t\tif( !pScene->mp_scene_data->m_num_nrm )\r\n\t\t\t\treturn;\r\n\t\t\tif( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<7) )\r\n\t\t\t\treturn;\r\n\t\t}\r\n\t\tm_flags |= CInstance::INSTANCE_FLAG_LIGHTING_ALLOWED;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nCInstance::~CInstance()\r\n{\r\n\tif( m_flags & INSTANCE_FLAG_DELETE_ATTACHED_SCENE )\r\n\t{\r\n\t\tif( mp_scene )\r\n\t\t{\r\n\t\t\tdelete mp_scene;\r\n\t\t\tmp_scene = NULL;\r\n\t\t}\r\n\t}\r\n\t\r\n//\tif ( mp_posNormBuffer )\r\n//\t{\r\n//\t\tdelete  mp_posNormBuffer;\r\n//\t\tmp_posNormBuffer = NULL;\r\n//\t}\r\n\r\n\t// Remove this instance from the list.\r\n\tCInstance **pp_instance = &pFirstInstance;\r\n\twhile( *pp_instance )\r\n\t{\r\n\t\tif( *pp_instance == this )\r\n\t\t{\r\n\t\t\t*pp_instance = mp_next_instance;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpp_instance = &(( *pp_instance )->mp_next_instance );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace NxNgc\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/instance.h",
    "content": "#ifndef __INSTANCE_H\r\n#define __INSTANCE_H\r\n\r\n\r\n#include <core/defines.h>\r\n#include <gfx/NxModel.h>\r\n#include \"scene.h\"\r\n\r\nnamespace NxNgc\r\n{\r\n\r\nclass CInstance\r\n{\r\npublic:\r\n\tenum EInstanceFlag\r\n\t{\r\n\t\tINSTANCE_FLAG_DELETE_ATTACHED_SCENE\t= 0x01,\r\n\t\tINSTANCE_FLAG_TRANSFORM_ME\t\t\t= 0x02,\r\n\t\tINSTANCE_FLAG_LIGHTING_ALLOWED\t\t= 0x04\r\n\r\n\t};\r\n\t\r\n\tvoid\t\tSetTransform( Mth::Matrix &transform )\t{ m_transform = transform; }\r\n\tMth::Matrix\t*GetTransform(void)\t\t\t\t\t\t{ return &m_transform; }\r\n\tint\t\t\tGetNumBones( void )\t\t\t\t\t\t{ return m_num_bones; }\r\n\tMth::Matrix\t*GetBoneTransforms( void )\t\t\t\t{ return mp_bone_transforms; }\r\n\tvoid\t\tSetBoneTransforms( Mth::Matrix * p )\t{ mp_bone_transforms = p; }\r\n\tsScene\t\t*GetScene( void )\t\t\t\t\t\t{ return mp_scene; }\r\n\tvoid\t\tSetActive( bool active )\t\t\t\t{ m_active = (uint16)active; }\r\n\tbool\t\tGetActive( void )\t\t\t\t\t\t{ return (bool)m_active; }\r\n\tvoid\t\tSetFlag( EInstanceFlag flag )\t\t\t{ m_flags |= flag; }\r\n\tuint32\t\tGetFlags( void )\t\t\t\t\t\t{ return m_flags; }\r\n\tvoid\t\tClearFlag( EInstanceFlag flag )\t\t\t{ m_flags &= ~flag; }\r\n\ts16\t\t\t*GetPosNormalBuffer( int buffer );\r\n\tvoid\t\tSetVisibility( uint32 mask )\t\t\t{ m_visibility_mask\t= mask; }\r\n\tuint32\t\tGetVisibility( void )\t\t\t\t\t{ return m_visibility_mask; }\r\n\tCInstance\t*GetNextInstance( void )\t\t\t\t{ return mp_next_instance; }\r\n\r\n\tvoid\t\tSetModel( Nx::CModel *p_model )\t\t\t{ mp_model = p_model; }\r\n\tNx::CModel\t*GetModel( void )\t\t\t\t\t\t{ return mp_model; }\r\n\r\n\tint\t\t\tGetMeshesRendered( void )\t\t\t\t{ return m_meshes_rendered; }\r\n\tvoid\t\tSetMeshesRendered( int n )\t\t\t\t{ m_meshes_rendered = n; }\r\n\r\n\tCInstance( sScene *pScene, Mth::Matrix &transform, int numBones, Mth::Matrix *pBoneTransforms );\r\n\t~CInstance();\r\n\r\n\tvoid\t\tTransform( uint32 flags, ROMtx * p_mtx_buffer, Mth::Matrix *p_mtx_last );\r\n\tvoid\t\tRender( uint32 flags );\r\n\r\n\ts16*\t\tGetPosNormRenderBuffer() { return mp_posNormRenderBuffer; }\r\n\tvoid\t\tSetPosNormRenderBuffer( s16* p ) { mp_posNormRenderBuffer = p; }\r\n\r\n\t#ifndef __NOPT_FINAL__\r\n\tint\t\t\tm_object_num;\r\n\t#endif\t\t// __NOPT_FINAL__\r\n\r\nprivate:\r\n\tuint32\t\tm_flags;\r\n\tMth::Matrix\tm_transform;\r\n\tMth::Matrix\t*mp_bone_transforms;\r\n\tint\t\t\tm_num_bones;\r\n\tuint16\t\tm_active;\r\n\tuint16\t\tm_meshes_rendered;\r\n\tsScene\t\t*mp_scene;\r\n\r\n\tuint32\t\tm_visibility_mask;\r\n\r\n\tNx::CModel\t*mp_model;\t\t// Required in order to get pointer to CXboxLights structure at render time.\r\n\r\n\ts16*\t\tmp_posNormBuffer;\r\n\ts16*\t\tmp_posNormRenderBuffer;\r\n\r\n\tCInstance\t*mp_next_instance;\r\n};\r\n\r\n\r\nvoid\tInitialiseInstanceTable( void );\r\nvoid\trender_instance( CInstance *p_instance, uint32 flags );\r\nvoid\trender_instances( uint32 flags );\r\nvoid\tprocess_instances( void );\r\n\r\n\r\n} // namespace NxNgc\r\n\r\n\r\n#endif // __INSTANCE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/light.cpp",
    "content": "#include <core/defines.h>\r\n#include \"light.h\"\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n\r\n// Statics\r\nCLightGroup\t\tCLightGroup::s_default_lights;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCLightGroup::CLightGroup()\r\n{\r\n\t// Don't use new lights unless someone sets them\r\n\tm_flags = 0;\r\n\r\n\t// Init to default lights\r\n\tm_light_vector = s_default_lights.m_light_vector;\r\n\r\n\tm_diffuse_base_color = s_default_lights.m_diffuse_base_color;\r\n\tm_diffuse_mod_color = s_default_lights.m_diffuse_base_color;\r\n\r\n\tm_ambient_base_color = s_default_lights.m_ambient_base_color;\r\n\tm_ambient_mod_color = s_default_lights.m_ambient_base_color;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCLightGroup::~CLightGroup()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\t\tCLightGroup::GetDirection(int idx) const\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\tif (m_flags & (mUSE_DIFFUSE_0 << idx))\r\n\t{\r\n\t\treturn m_light_vector[idx];\r\n\t} else {\r\n\t\treturn s_default_lights.m_light_vector[idx];\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\t\tCLightGroup::GetBaseAmbientColor() const\r\n{\r\n\tif (m_flags & mUSE_AMBIENT)\r\n\t{\r\n\t\treturn m_ambient_base_color;\r\n\t} else {\r\n\t\treturn s_default_lights.m_ambient_base_color;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\t\tCLightGroup::GetBaseDiffuseColor(int idx) const\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\tif (m_flags & (mUSE_DIFFUSE_0 << idx))\r\n\t{\r\n\t\treturn m_diffuse_base_color[idx];\r\n\t} else {\r\n\t\treturn s_default_lights.m_diffuse_base_color[idx];\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\t\tCLightGroup::GetAmbientColor() const\r\n{\r\n\tif (m_flags & (mUSE_AMBIENT | mMODULATING_AMBIENT))\r\n\t{\r\n\t\treturn m_ambient_mod_color;\r\n\t} else {\r\n\t\treturn s_default_lights.m_ambient_base_color;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\t\tCLightGroup::GetDiffuseColor(int idx) const\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\tif (m_flags & ((mUSE_DIFFUSE_0 | mMODULATING_DIFFUSE_0) << idx))\r\n\t{\r\n\t\treturn m_diffuse_mod_color[idx];\r\n\t} else {\r\n\t\treturn s_default_lights.m_diffuse_base_color[idx];\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\t\tCLightGroup::SetDirection(int idx, const Mth::Vector & direction)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\t//Dbg_Assert(m_flags & (mUSE_DIFFUSE_0 << idx));\r\n\tm_flags |= (mUSE_DIFFUSE_0 << idx);  // turn on light if it isn't already on\r\n\r\n\tm_light_vector[idx] = direction;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\t\tCLightGroup::SetBaseAmbientColor(const Mth::Vector & color)\r\n{\r\n\t//Dbg_Assert(m_flags & mUSE_AMBIENT);\r\n\tm_flags |= mUSE_AMBIENT;\t\t// turn on light if it isn't already on\r\n\r\n\tm_ambient_base_color = color;\r\n\r\n\tif (!(m_flags & mMODULATING_AMBIENT))\r\n\t{\r\n\t\tm_ambient_mod_color = color;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\t\tCLightGroup::SetBaseDiffuseColor(int idx, const Mth::Vector & color)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\t//Dbg_Assert(m_flags & (mUSE_DIFFUSE_0 << idx));\r\n\tm_flags |= (mUSE_DIFFUSE_0 << idx);  // turn on light if it isn't already on\r\n\r\n\tm_diffuse_base_color[idx] = color;\r\n\r\n\tif (!(m_flags & (mMODULATING_DIFFUSE_0 << idx)))\r\n\t{\r\n\t\tm_diffuse_mod_color[idx] = color;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\t\tCLightGroup::EnableAmbientLight(bool enable)\r\n{\r\n\tif (enable)\r\n\t{\r\n\t\tm_flags |= mUSE_AMBIENT;\r\n\t} else {\r\n\t\tm_flags &= ~mUSE_AMBIENT;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\t\tCLightGroup::EnableDiffuseLight(int idx, bool enable)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\tif (enable)\r\n\t{\r\n\t\tm_flags |= (mUSE_DIFFUSE_0 << idx);\r\n\t} else {\r\n\t\tm_flags &= ~(mUSE_DIFFUSE_0 << idx);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\t\tCLightGroup::IsAmbientLightEnabled() const\r\n{\r\n\treturn (m_flags & mUSE_AMBIENT);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\t\tCLightGroup::IsDiffuseLightEnabled(int idx) const\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\treturn (m_flags & (mUSE_DIFFUSE_0 << idx));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\t\tCLightGroup::SetAmbientBrightness(float brightness)\r\n{\r\n\tm_ambient_mod_color = GetBaseAmbientColor() * brightness;\r\n\r\n\tm_flags |= mMODULATING_AMBIENT;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\t\tCLightGroup::SetDiffuseBrightness(int idx, float brightness)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\tm_diffuse_mod_color[idx] = GetBaseDiffuseColor(idx) * brightness;\r\n\r\n\tm_flags |= (mMODULATING_DIFFUSE_0 << idx);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\t\tCLightGroup::sGetDefaultDirection(int idx)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\treturn s_default_lights.m_light_vector[idx];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\t\tCLightGroup::sGetDefaultAmbientColor()\r\n{\r\n\treturn s_default_lights.m_ambient_base_color;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\t\tCLightGroup::sGetDefaultDiffuseColor(int idx)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\treturn s_default_lights.m_diffuse_base_color[idx];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\t\tCLightGroup::sSetDefaultDirection(int idx, const Mth::Vector & direction)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\ts_default_lights.m_light_vector[idx] = direction;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\t\tCLightGroup::sSetDefaultAmbientColor(const Mth::Vector & color)\r\n{\r\n\ts_default_lights.m_ambient_base_color = color;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\t\tCLightGroup::sSetDefaultDiffuseColor(int idx, const Mth::Vector & color)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\ts_default_lights.m_diffuse_base_color[idx] = color;\r\n}\r\n\r\n} // namespace NxNgc\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/light.h",
    "content": "#ifndef __LIGHT_H\r\n#define __LIGHT_H\r\n\r\n#include\t<core/defines.h>\r\n#include\t<core/math.h>\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n// Forward declarations\r\nclass CLightGroup;\r\n\r\nclass CBaseLightGroup\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCBaseLightGroup();\r\n\tvirtual\t\t\t\t\t\t~CBaseLightGroup();\r\n\r\n\tvirtual const Mth::Vector &\tGetDirection(int idx) const;\r\n\r\n\tvirtual const Mth::Vector &\tGetAmbientColor() const;\r\n\tvirtual const Mth::Vector &\tGetDiffuseColor(int idx) const;\r\n\r\nprotected:\r\n\t// Directional light vectors\r\n\tMth::Vector\t\t\t\t\tm_light_vector[2];\r\n\r\n\t// Light base colors\r\n\tMth::Vector \t\t\t\tm_diffuse_base_color[2];\r\n\tMth::Vector \t\t\t\tm_ambient_base_color;\r\n\r\n\tfriend CLightGroup;\r\n};\r\n\r\nclass CLightGroup/* : public CBaseLightGroup*/\r\n{\r\n\r\npublic:\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tMAX_DIFFUSE_LIGHTS = 2,\r\n\t};\r\n\r\n\t\t\t\t\t\t\t\tCLightGroup();\r\n\t\t\t\t\t\t\t\t~CLightGroup();\r\n\t//virtual\t\t\t\t\t\t~CLightGroup();\r\n\r\n\tconst Mth::Vector &\t\t\tGetDirection(int idx) const;\r\n\t//virtual const Mth::Vector &\tGetDirection(int idx) const;\r\n\r\n\tconst Mth::Vector &\t\t\tGetBaseAmbientColor() const;\r\n\tconst Mth::Vector &\t\t\tGetBaseDiffuseColor(int idx) const;\r\n\r\n\tconst Mth::Vector &\t\t\tGetAmbientColor() const;\r\n\tconst Mth::Vector &\t\t\tGetDiffuseColor(int idx) const;\r\n\t//virtual const Mth::Vector &\tGetAmbientColor() const;\r\n\t//virtual const Mth::Vector &\tGetDiffuseColor(int idx) const;\r\n\r\n\tvoid\t\t\t\t\t\tSetDirection(int idx, const Mth::Vector & direction);\r\n\tvoid\t\t\t\t\t\tSetBaseAmbientColor(const Mth::Vector & color);\r\n\tvoid\t\t\t\t\t\tSetBaseDiffuseColor(int idx, const Mth::Vector & color);\r\n\r\n\t// Enable lights\r\n\tvoid\t\t\t\t\t\tEnableAmbientLight(bool enable);\r\n\tvoid\t\t\t\t\t\tEnableDiffuseLight(int idx, bool enable);\r\n\tbool\t\t\t\t\t\tIsAmbientLightEnabled() const;\r\n\tbool\t\t\t\t\t\tIsDiffuseLightEnabled(int idx) const;\r\n\r\n\t// Set brightness of lights\r\n\tbool\t\t\t\t\t\tSetAmbientBrightness(float brightness);\r\n\tbool\t\t\t\t\t\tSetDiffuseBrightness(int idx, float brightness);\r\n\r\n\t// Default lights\r\n\tstatic const Mth::Vector &\tsGetDefaultDirection(int idx);\r\n\tstatic const Mth::Vector &\tsGetDefaultAmbientColor();\r\n\tstatic const Mth::Vector &\tsGetDefaultDiffuseColor(int idx);\r\n\r\n\tstatic void\t\t\t\t\tsSetDefaultDirection(int idx, const Mth::Vector & direction);\r\n\tstatic void\t\t\t\t\tsSetDefaultAmbientColor(const Mth::Vector & color);\r\n\tstatic void\t\t\t\t\tsSetDefaultDiffuseColor(int idx, const Mth::Vector & color);\r\n\r\nprotected:\r\n\t// Internal flags.\r\n\tenum {\r\n\t\tmUSE_AMBIENT\t\t\t\t= 0x0001,\t\t\t\t\t// Use ambient light\r\n\t\tmUSE_DIFFUSE_0\t\t\t\t= 0x0002,\t\t\t\t\t// Use diffuse light 0\r\n\t\tmUSE_DIFFUSE_1\t\t\t\t= 0x0004,\t\t\t\t\t// rest of diffuse must follow 0\r\n\t\tmMODULATING_AMBIENT\t\t\t= 0x0008,\t\t\t\t\t// setting ambient brightness\r\n\t\tmMODULATING_DIFFUSE_0\t\t= 0x0010,\t\t\t\t\t// setting diffuse brightness 0\r\n\t\tmMODULATING_DIFFUSE_1\t\t= 0x0020,\t\t\t\t\t// rest of diffuse must follow 0\r\n\t};\r\n\r\n\tuint32\t\t\t\t\tm_flags;\r\n\r\n\t// Directional light vectors\r\n\tMth::Vector\t\t\t\tm_light_vector[2];\r\n\r\n\t// Light base colors\r\n\tMth::Vector \t\t\tm_diffuse_base_color[2];\r\n\tMth::Vector \t\t\tm_ambient_base_color;\r\n\r\n\t// Light modulated colors (modified base colors)\r\n\tMth::Vector \t\t\tm_diffuse_mod_color[2];\r\n\tMth::Vector \t\t\tm_ambient_mod_color;\r\n\r\n\t// Default lights\r\n//\tstatic Mth::Vector\t\ts_default_directions[2];\r\n//\tstatic CBaseLightGroup\ts_default_colors;\r\n\tstatic CLightGroup\t\ts_default_lights;\r\n\r\n}; // class CLightGroup\r\n\r\n\r\n\r\n} // namespace NxNgc\r\n\r\n\r\n\r\n#endif // __LIGHT_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/line.cpp",
    "content": "#include \"line.h\"\r\n#include \"render.h\"\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\nvoid BeginLines2D(uint32 rgba)\r\n{\r\n//\t// dma tag\r\n//\tdma::BeginTag(dma::cnt, 0);\r\n//\r\n//\tvu1::Buffer = vu1::Loc;\r\n//\r\n//\t// GS context\r\n//\tgs::BeginPrim(ABS,0,0);\r\n//\tgs::Reg1(gs::ALPHA_1, PackALPHA(0,1,0,1,0));\r\n//\tgs::Reg1(gs::RGBAQ,   (uint64)rgba);\r\n//\tgs::EndPrim(0);\r\n//\r\n//\t// unpack giftag\r\n//\tvif::UNPACK(0, V4_32, 1, ABS, UNSIGNED, 0);\r\n//\tgif::BeginTagImmediate(gs::XYZ2, 1, PACKED, LINE|ABE, 1, VU1_ADDR(GSPrim));\r\n//\r\n//\t// begin unpack for coordinates\r\n//\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, 1);\r\n}\r\n\r\n\r\n\r\nvoid DrawLine2D(float x0, float y0, float z0, float x1, float y1, float z1)\r\n{\r\n//\tvif::StoreV4_32(0x6C00+(sint32)(x0*16),0x7200+(sint32)(y0*16),0xFFFFFF,0);\r\n//\tvif::StoreV4_32(0x6C00+(sint32)(x1*16),0x7200+(sint32)(y1*16),0xFFFFFF,0);\r\n//\r\n//\tif (((dma::pLoc - gif::pTag)>>4) >= 250)\r\n//\t{\r\n//\t\tvif::EndUNPACK();\r\n//\t\tgif::EndTagImmediate(1,0);\r\n//\t\tvif::MSCAL(VU1_ADDR(Parser));\r\n//\t\tvif::UNPACK(0, V4_32, 1, ABS, UNSIGNED, 0);\r\n//\t\tgif::BeginTagImmediate(gs::XYZ2, 1, PACKED, LINE|ABE, 1, VU1_ADDR(GSPrim));\r\n//\t\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, 1);\r\n//\t}\r\n//\r\n}\r\n\r\n\r\nvoid EndLines2D(void)\r\n{\r\n//\tvif::EndUNPACK();\r\n//\tgif::EndTagImmediate(1,0);\r\n//\tvif::MSCAL(VU1_ADDR(Parser));\r\n//\tdma::EndTag();\r\n}\r\n\r\n\r\n\r\nvoid BeginLines3D(uint32 rgba)\r\n{\r\n//\t// dma tag\r\n//\tdma::BeginTag(dma::cnt, 0);\r\n//\r\n//\tvu1::Buffer = vu1::Loc;\r\n//\r\n//\t// VU context\r\n//\tvu1::BeginPrim(ABS, VU1_ADDR(L_VF10));\r\n//\tvu1::StoreVec(ViewportScale);\t\t// VF10\r\n//\tvu1::StoreVec(ViewportOffset);\t\t// VF11\r\n//\tvu1::StoreMat(WorldToFrustum);\t\t// VF12-15\r\n//\tvu1::EndPrim(0);\r\n//\r\n//\t// GS context\r\n//\tgs::BeginPrim(ABS,0,0);\r\n//\tgs::Reg1(gs::ALPHA_1, PackALPHA(0,1,0,1,0));\r\n//\tgs::Reg1(gs::RGBAQ,   (uint64)rgba);\r\n//\tgs::EndPrim(0);\r\n//\r\n//\t// all lines will be rendered with simple culling\r\n//\tvif::ITOP(CULL);\r\n//\r\n//\t// unpack giftag\r\n//\tvif::UNPACK(0, V4_32, 1, ABS, UNSIGNED, 0);\r\n//\tgif::BeginTagImmediate(gs::XYZ2, 1, PACKED, LINE|ABE, 1, VU1_ADDR(ProjLine));\r\n//\r\n//\t// offset mode\r\n//\tvif::STMOD(1);\r\n//\r\n//\t// begin unpack for coordinates\r\n//\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, 1);\r\n}\r\n\r\n\r\nvoid DrawLine3D(float x0, float y0, float z0, float x1, float y1, float z1)\r\n{\r\n//\tvif::StoreV4_32((sint32)(x0*256.0f), (sint32)(y0*256.0f), (sint32)(z0*256.0f), 0);\r\n//\tvif::StoreV4_32((sint32)(x1*256.0f), (sint32)(y1*256.0f), (sint32)(z1*256.0f), 0);\r\n//\r\n//\tif (((dma::pLoc - gif::pTag)>>4) >= 250)\r\n//\t{\r\n//\t\tvif::EndUNPACK();\r\n//\t\tgif::EndTagImmediate(1,1);\r\n//\t\tvif::STMOD(0);\r\n//\t\tvif::MSCAL(VU1_ADDR(Parser));\r\n//\t\tvif::UNPACK(0, V4_32, 1, ABS, UNSIGNED, 0);\r\n//\t\tgif::BeginTagImmediate(gs::XYZ2, 1, PACKED, LINE|ABE, 1, VU1_ADDR(ProjLine));\r\n//\t\tvif::STMOD(1);\r\n//\t\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, 1);\r\n//\t}\r\n//\r\n}\r\n\r\n\r\nvoid EndLines3D(void)\r\n{\r\n//\tvif::EndUNPACK();\r\n//\r\n//\tif (vif::UnpackSize)\r\n//\t{\r\n//\t\tgif::EndTagImmediate(1,1);\r\n//\t\tvif::STMOD(0);\r\n//\t\tvif::MSCAL(VU1_ADDR(Parser));\r\n//\t}\r\n//\telse\r\n//\t\tdma::pLoc -= 24;\r\n//\r\n//\tdma::EndTag();\r\n}\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/line.h",
    "content": "#ifndef __LINE_H\r\n#define __LINE_H\r\n\r\n#include \"types.h\"\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n\r\nvoid BeginLines2D(uint32 rgba);\r\nvoid DrawLine2D(float x0, float y0, float z0, float x1, float y1, float z1);\r\nvoid EndLines2D(void);\r\nvoid BeginLines3D(uint32 rgba);\r\nvoid DrawLine3D(float x0, float y0, float z0, float x1, float y1, float z1);\r\nvoid EndLines3D(void);\r\n\r\n} // namespace NxNgc\r\n\r\n\r\n#endif // __LINE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/material.cpp",
    "content": "#include <string.h>\r\n#include <sys/timer.h>\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <sys/file/filesys.h>\r\n//#include \"import.h\"\r\n#include \"material.h\"\r\n#include \"scene.h\"\r\n#include \"render.h\"\r\n#include \"gfx/ngc/p_nxtexture.h\"\r\n#include \"nx_init.h\"\r\n\r\n#include <sys/ngc/p_display.h>\r\n#include <sys/ngc/p_gx.h>\r\n\r\n//int gMatBytes = 0;\r\n\r\nextern u16 colorMap[];\r\n\r\nbool gCorrectColor = false;\r\n\r\nextern bool gMeshUseCorrection;\r\nextern bool gMeshUseAniso;\r\n\r\nint g_mat = 0;\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//sMaterial::sMaterial( void )\r\n//{\r\n//\tm_num_wibble_vc_anims\t= 0;\r\n//\tmp_wibble_vc_params\t\t= NULL;\r\n//\tmp_wibble_vc_colors\t\t= NULL;\r\n//\tm_uv_wibble\t\t\t\t= false;\r\n//\tfor( int p = 0; p < MAX_PASSES; ++p )\r\n//\t{\r\n//\t\tFlags[p]\t\t\t = 0;\r\n//\t\tmp_UVWibbleParams[p] = NULL;\r\n//\t}\r\n//}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//sMaterial::~sMaterial( void )\r\n//{\r\n////\tif( mp_wibble_vc_params\t)\r\n////\t{\r\n////\t\tfor( uint32 i = 0; i < m_num_wibble_vc_anims; ++i )\r\n////\t\t{\r\n////\t\t\tdelete [] mp_wibble_vc_params[i].mp_keyframes;\r\n////\t\t}\r\n////\t\tdelete [] mp_wibble_vc_params;\r\n////\t}\r\n////\tif( mp_wibble_vc_colors\t)\r\n////\t{\r\n////\t\tdelete [] mp_wibble_vc_colors;\r\n////\t}\r\n//}\r\n\r\n\r\n\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void sMaterial::figure_wibble_uv( void )\r\n//{\r\n//\tfloat uoff, voff, t;\r\n//\r\n//\tm_wibble_uv_time\t= (float)Tmr::GetTime();\r\n//\tt\t\t\t\t\t= m_wibble_uv_time * 0.001f;\r\n//\tm_wibble_uv_update\t= 0;\r\n//\r\n//\tfor( uint32 p = 0; p < Passes; ++p )\r\n//\t{\r\n//\t\t// Figure out UV offsets for wibbling if required.\r\n//\t\tif( Flags[p] & MATFLAG_UV_WIBBLE )\r\n//\t\t{\r\n//\t\t\tm_wibble_uv_update |= ( 1 << p );\r\n//\t\t\r\n//\t\t\tuoff\t= ( t * m_pUVControl->UVWibbleParams[p].m_UVel ) + ( m_pUVControl->UVWibbleParams[p].m_UAmplitude * sinf( m_pUVControl->UVWibbleParams[p].m_UFrequency * t + m_pUVControl->UVWibbleParams[p].m_UPhase ));\r\n////\t\t\tuoff\t-= (float)(int)uoff;\r\n//\t\r\n//\t\t\tvoff\t= ( t * m_pUVControl->UVWibbleParams[p].m_VVel ) + ( m_pUVControl->UVWibbleParams[p].m_VAmplitude * sinf( m_pUVControl->UVWibbleParams[p].m_VFrequency * t + m_pUVControl->UVWibbleParams[p].m_VPhase ));\r\n////\t\t\tvoff\t-= (float)(int)voff;\r\n//\r\n//\t\t\tm_pUVControl->UVWibbleOffset[p][0]\t= uoff;\r\n//\t\t\tm_pUVControl->UVWibbleOffset[p][1]\t= voff;\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void sMaterial::figure_wibble_vc( void )\r\n//{\r\n//\t// The vertex color wibble flag is placed in pass 0.\r\n//\tif( Flags[0] & MATFLAG_VC_WIBBLE )\r\n//\t{\r\n//\t\tint current_time = (int)Tmr::GetTime();\r\n//\r\n//\t\tfor( uint32 i = 0; i < m_num_wibble_vc_anims; ++i )\r\n//\t\t{\r\n//\t\t\tstruct sVCWibbleParams\t*p_sequence\t\t= mp_wibble_vc_params + i;\r\n//\t\t\t\r\n//\t\t\t// Get phase-shift.\r\n//\t\t\tint\t\t\t\t\t\tphase_shift\t\t= p_sequence->m_phase;\r\n//\r\n//\t\t\t// Time parameters.\r\n//\t\t\tint\t\t\t\t\t\tnum_keys\t\t= p_sequence->m_num_keyframes;\r\n//\t\t\tint\t\t\t\t\t\tstart_time\t\t= p_sequence->mp_keyframes[0].m_time;\r\n//\t\t\tint\t\t\t\t\t\tend_time\t\t= p_sequence->mp_keyframes[num_keys - 1].m_time;\r\n//\t\t\tint\t\t\t\t\t\tperiod\t\t\t= end_time - start_time;\r\n//\t\t\tint\t\t\t\t\t\ttime\t\t\t= start_time + (( current_time + phase_shift ) % period );\r\n//\r\n//\t\t\t// Locate the keyframe.\r\n//\t\t\tint key;\r\n//\t\t\tfor( key = num_keys - 1; key >= 0; --key )\r\n//\t\t\t{\r\n//\t\t\t\tif( time >= p_sequence->mp_keyframes[key].m_time )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\t\r\n//\t\t\t// Parameter expressing how far we are between between this keyframe and the next.\r\n//\t\t\tfloat\t\t\t\t\tt\t\t\t\t= (float)( time - start_time ) / (float)period;\r\n//\r\n//\t\t\t// Interpolate the color.\r\n//\t\t\tGXColor\trgba;\r\n//\t\t\trgba.r = (uint8)((( 1.0f - t ) * p_sequence->mp_keyframes[key].m_color.r ) + ( t * p_sequence->mp_keyframes[key + 1].m_color.r ));\r\n//\t\t\trgba.g = (uint8)((( 1.0f - t ) * p_sequence->mp_keyframes[key].m_color.g ) + ( t * p_sequence->mp_keyframes[key + 1].m_color.g ));\r\n//\t\t\trgba.b = (uint8)((( 1.0f - t ) * p_sequence->mp_keyframes[key].m_color.b ) + ( t * p_sequence->mp_keyframes[key + 1].m_color.b ));\r\n//\t\t\trgba.a = (uint8)((( 1.0f - t ) * p_sequence->mp_keyframes[key].m_color.a ) + ( t * p_sequence->mp_keyframes[key + 1].m_color.a ));\r\n//\r\n//\t\t\tmp_wibble_vc_colors[i] = *((uint32*)&rgba);\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\t\r\n//static int\tstage_id = 0;\t// 0-15\r\n//static int\ttev_id = 0;\t\t\t\t\t// 0-3\r\n//static int\tuv_id = 0;\t\t\t\t\t// 0-7\r\n//static int\tmap_id = 0;\t\t\t\t\t// 0-3\r\n//static int\tlayer_id = 1;\t\t\t\t\t// 1-3\r\n//static bool correct_color = false;\r\n//\r\n//static void multi_start ( int passes )\r\n//{\r\n//\t// Set everything to 0.\r\n//\tstage_id\t= 0;\r\n//\ttev_id\t\t= 0;\r\n//\tuv_id\t\t= 0;\r\n//\tmap_id\t\t= 0;\r\n//\tlayer_id\t= 1;\r\n//\r\n//\t// Don't forget these!\r\n////\tGXSetNumChans(2);\r\n////\tGX::SetNumTexGens(2);\r\n////\tGX::SetNumTevStages(2);\r\n//\r\n//\tif ( gCorrectColor && gMeshUseCorrection )\r\n//\t{\r\n//\t\tGXTexObj\ttexObj;\r\n//\t\tGXInitTexObj( &texObj, colorMap, 256, 256, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE );\r\n//\t\tGXLoadTexObj( &texObj, GX_TEXMAP7 );\r\n//\r\n//\t\t// Tev 0: Use rasterization lookup table (RG)\r\n//\t\t// Note: Blue = 0 and Alpha = 0;\r\n//\t\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\tGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);\r\n//\t\tGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO);\r\n//\t\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG1);\r\n//\t\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG1);\r\n//\t\tstage_id++;\r\n//\r\n//\t\t// Tev 1: Use rasterization lookup table (BA),\r\n//\t\t// then add previous tev (RG + BA)\r\n//\t\tGX::SetTevSwapMode( GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP3 );\r\n//\t\tGX::SetTevColorIn(GX_TEVSTAGE1, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C1);\r\n//\t\tGX::SetTevAlphaIn(GX_TEVSTAGE1, GX_CA_TEXA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A1);\r\n//\t\tGX::SetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG2);\r\n//\t\tGX::SetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG2);\r\n//\t\tstage_id++;\r\n//\t\tcorrect_color = true;\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tcorrect_color = false;\r\n//\t}\r\n//\r\n////\t// Create 2 dummy stages.\r\n////\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n////\r\n////\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR_NULL );\r\n////\tGX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n////\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n////\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n////\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n////\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n////\tstage_id++;\r\n////\r\n////\ts_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n////\t\r\n////\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR0A0 );\r\n////\tGX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n////\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG2 );\r\n////\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG2 );\r\n////\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n////\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n////\tstage_id++;\r\n//\r\n////\tif ( !gCorrectColor || !gMeshUseCorrection )\r\n////\t{\r\n//////\t\t// Create 2 dummy stages.\r\n//////\t\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n//////\r\n//////\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR0A0 );\r\n//////\t\tGX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//////\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG2 );\r\n//////\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG2 );\r\n//////\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n//////\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n//////\t\tstage_id++;\r\n////\t\tcorrect_color = false;\r\n////\t}\r\n//}\r\n//\r\n//static void multi_add_layer ( BlendModes blend, int raw_fix )\r\n//{\r\n//\t// Set inputs.\r\n//\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n//\t\r\n//\tint reg_id = layer_id;\t//( layer_id > 1 ) ? 1 : layer_id;\t//( tev_id == 3 ) ? 2 : tev_id;\t\t// CPREV, C0, C1, C0.\r\n//  //  int reg_id = layer_id;\t//( layer_id == 3 ) ? 2 : layer_id;\t\t// CPREV, C0, C1, C0.\r\n//\r\n////\tGXTevAlphaArg newa = (GXTevAlphaArg)(((int)GX_CA_APREV)+layer_id);\r\n//\tGXTevColorArg newc = (GXTevColorArg)(((int)GX_CC_CPREV)+(reg_id*2));\r\n//\tGXTevColorArg newca= (GXTevColorArg)(((int)GX_CC_APREV)+(reg_id*2));\r\n//\r\n//\r\n//    // out_reg = (d (op) ((1.0 - c)*a + c*b) + bias) * scale;\r\n//\r\n//\tint fix = ( raw_fix >= 128 ) ? 255 : raw_fix * 2;\r\n//\r\n//\tswitch ( blend ) {\r\n//\t\tcase vBLEND_MODE_ADD:\r\n//\t\tcase vBLEND_MODE_ADD_FIXED:\r\n//\t\t\t// Add using texture or fixed alpha.\r\n//\t\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR_NULL );\r\n//            GX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV );\r\n//\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, newc, newca, GX_CC_CPREV );\r\n//\t\t\tstage_id++;\r\n//\t\t\tbreak;\r\n//\t\tcase vBLEND_MODE_SUBTRACT:\r\n//\t\tcase vBLEND_MODE_SUB_FIXED:\r\n//\t\t\t// Subtract using texture or fixed alpha.\r\n//\t\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR_NULL );\r\n//            GX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_SUB, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevColorOp(s_id, GX_TEV_SUB, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV );\r\n//\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, newc, newca, GX_CC_CPREV );\r\n//\t\t\tstage_id++;\r\n//\t\t\tbreak;\r\n//\t\tcase vBLEND_MODE_BLEND:\r\n//\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n//\t\t\t// Blend using texture or fixed alpha.\r\n//\t\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR_NULL );\r\n//            GX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV );\r\n//\t\t\tGX::SetTevColorIn ( s_id, GX_CC_CPREV, newc, newca, GX_CC_ZERO );\r\n//\t\t\tstage_id++;\r\n//\t\t\tbreak;\r\n//\t\tcase vBLEND_MODE_MODULATE:\r\n//\t\t\t// Modulate current layer with previous layer.\r\n//\t\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR_NULL );\r\n//            GX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV );\r\n//\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, newca, GX_CC_CPREV, GX_CC_ZERO );\r\n//\t\t\tstage_id++;\r\n//\t\t\tbreak;\r\n//\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n//\t\t\t// Modulate current layer with fixed alpha.\r\n//\t\t\tGX::SetTevKAlphaSel( s_id, (GXTevKAlphaSel)(((int)GX_TEV_KASEL_K0_A)+layer_id) );\r\n//\t\t\tGX::SetTevKColorSel( s_id, (GXTevKColorSel)(((int)GX_TEV_KCSEL_K0_A)+layer_id) );\r\n//\t\t\tGX::SetTevKColor( (GXTevKColorID)(((int)GX_KCOLOR0)+layer_id), (GXColor){fix,fix,fix,fix} );\r\n//\t\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR_NULL );\r\n//            GX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV );\r\n//\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_CPREV, GX_CC_KONST, GX_CC_ZERO );\r\n//\t\t\tstage_id++;\r\n//\t\t\tbreak;\r\n//\t\tcase vBLEND_MODE_BRIGHTEN:\r\n//\t\t\t// Modulate current layer with previous layer, & add current layer.\r\n//\t\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR_NULL );\r\n//            GX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV );\r\n//\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, newca, GX_CC_CPREV, GX_CC_CPREV );\r\n//\t\t\tstage_id++;\r\n//\t\t\tbreak;\r\n//\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n//\t\t\t// Modulate current layer with fixed alpha, & add current layer.\r\n//\t\t\tGX::SetTevKAlphaSel( s_id, (GXTevKAlphaSel)(((int)GX_TEV_KASEL_K0_A)+layer_id) );\r\n//\t\t\tGX::SetTevKColorSel( s_id, (GXTevKColorSel)(((int)GX_TEV_KCSEL_K0_A)+layer_id) );\r\n//\t\t\tGX::SetTevKColor( (GXTevKColorID)(((int)GX_KCOLOR0)+layer_id), (GXColor){fix,fix,fix,fix} );\r\n//\t\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR_NULL );\r\n//            GX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV );\r\n//\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_CPREV, GX_CC_KONST, GX_CC_CPREV );\r\n//\t\t\tstage_id++;\r\n//\t\t\tbreak;\r\n//\t\tcase vBLEND_MODE_DIFFUSE:\r\n//\t\tdefault:\r\n//\t\t\t// Replace with this texture. Shouldn't ever be used, but here for compatibility.\r\n//\t\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR_NULL );\r\n//            GX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV );\r\n//\t\t\tGX::SetTevColorIn ( s_id, newc, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n//\t\t\tstage_id++;\r\n//\t\t\tbreak;\r\n//\t}\r\n////\tlayer_id++;\r\n//}\r\n//\r\n//static void multi_add_texture ( sTexture * p_texture, GXColor matcol, GXTexWrapMode umode, GXTexWrapMode vmode, BlendModes blend, int fix, uint32 flags, char * p_uv_slot, float k )\r\n//{\r\n//\tif ( map_id >= 8 ) return;\r\n//\t\r\n//\tvoid * p_tex_data = p_texture->pTexelData;\r\n//\tvoid * p_alpha_data = p_texture->has_alpha ? p_texture->pAlphaData : NULL;\r\n//\tint width = p_texture->ActualWidth;\r\n//\tint height = p_texture->ActualHeight;\r\n//\tint levels = p_texture->Levels;\r\n//\tint reg_id = ( tev_id > 1 ) ? 1 : tev_id;\t//( tev_id == 3 ) ? 2 : tev_id;\t\t// CPREV, C0, C1, C0.\r\n//\t\r\n//\tGXTevAlphaArg rasa;\r\n//\tGXTevColorArg rasc;\r\n//\tif ( correct_color )\r\n//\t{\r\n//\t\trasa = GX_CA_A2;\r\n//\t\trasc = GX_CC_C2;\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\trasa = GX_CA_RASA;\r\n//\t\trasc = GX_CC_RASC;\r\n//\t}\r\n//\r\n//\tint cur_map = map_id + 1;\r\n//\tint alpha_map = -1;\r\n//\tbool uniqueMaterialColor = false;\r\n//\r\n//\tif ( ( matcol.r == 128 ) && ( matcol.g == 128 ) && ( matcol.b == 128 ) && ( matcol.a == 255 ) )\r\n//\t{\r\n//\t\tuniqueMaterialColor = false;\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tuniqueMaterialColor = true;\r\n//\t}\r\n//\r\n//\tif ( p_alpha_data )\r\n//\t{\r\n//\t\tswitch ( blend )\r\n//\t\t{\r\n//\t\t\tcase vBLEND_MODE_ADD:\r\n//\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n//\t\t\tcase vBLEND_MODE_BLEND:\r\n//\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n//\t\t\tcase vBLEND_MODE_MODULATE:\r\n//\t\t\tcase vBLEND_MODE_DIFFUSE:\r\n//\t\t\t\tif ( cur_map < 8 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\talpha_map = cur_map;\r\n//\t\t\t\t\tcur_map++;\r\n//\t\t\t\t}\r\n//\t\t\t\tbreak;\r\n//\t\t\tdefault:\r\n//\t\t\t\tbreak;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tGXTexObj\ttexObj;\r\n//\tGXInitTexObj( &texObj, p_tex_data, width, height, ((GXTexFmt)p_texture->format), umode, vmode, levels > 1 ? GX_TRUE : GX_FALSE );\r\n//\tif ( levels > 1 )\r\n//\t{\r\n//\t\tif ( gMeshUseAniso && ( tev_id == 0 ) )\r\n//\t\t{\r\n//\t\t\t// If we're correcting the color, we also want ANISO_4.\r\n//\t\t\tGXInitTexObjLOD( &texObj, GX_LIN_MIP_LIN, GX_LINEAR, 0.0f, levels - 1, k, GX_FALSE, GX_TRUE, GX_ANISO_4 );\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tGXInitTexObjLOD( &texObj, GX_LIN_MIP_LIN, GX_LINEAR, 0.0f, levels - 1, k, GX_FALSE, GX_TRUE, GX_ANISO_1 );\r\n//\t\t}\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tGXInitTexObjLOD( &texObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, k, GX_FALSE, GX_TRUE, GX_ANISO_1 );\r\n//\t}\r\n//\tGXLoadTexObj( &texObj, (GXTexMapID)(((int)GX_TEXMAP0)+map_id) );\r\n//\r\n//\tif ( alpha_map >= 0 )\r\n//\t{\r\n//\t\tswitch ( blend )\r\n//\t\t{\r\n//\t\t\tcase vBLEND_MODE_ADD:\r\n//\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n//\t\t\tcase vBLEND_MODE_BLEND:\r\n//\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n//\t\t\tcase vBLEND_MODE_MODULATE:\r\n//\t\t\tcase vBLEND_MODE_DIFFUSE:\r\n//\t\t\t\tGXTexObj\talphaObj;\r\n//\t\t\t\tGXInitTexObj( &alphaObj, p_alpha_data, width, height, ((GXTexFmt)p_texture->format), umode, vmode, levels > 1 ? GX_TRUE : GX_FALSE );\r\n//\t\t\t\tif ( levels > 1 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif ( gMeshUseAniso && ( tev_id == 0 ) )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\t// If we're correcting the color, we also want ANISO_4.\r\n//\t\t\t\t\t\tGXInitTexObjLOD( &alphaObj, GX_LIN_MIP_LIN, GX_LINEAR, 0.0f, levels - 1, k, GX_FALSE, GX_TRUE, GX_ANISO_4 );\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\telse\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tGXInitTexObjLOD( &alphaObj, GX_LIN_MIP_LIN, GX_LINEAR, 0.0f, levels - 1, k, GX_FALSE, GX_TRUE, GX_ANISO_1 );\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tGXInitTexObjLOD( &alphaObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, k, GX_FALSE, GX_TRUE, GX_ANISO_1 );\r\n//\t\t\t\t}\r\n//\t\t\t\tGXLoadTexObj( &alphaObj, (GXTexMapID)(((int)GX_TEXMAP0)+alpha_map) );\r\n//\t\t\t\tbreak;\r\n//\t\t\tdefault:\r\n//\t\t\t\tp_alpha_data = NULL;\r\n//\t\t\t\tbreak;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tGXTexMapID t_id = (GXTexMapID)(((int)GX_TEXMAP0)+map_id);\r\n//\tGXTexCoordID u_id = (GXTexCoordID)(((int)GX_TEXCOORD0)+uv_id);\r\n//\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n//\r\n//\t// Modulate material color if required.\r\n//\tif ( uniqueMaterialColor )\r\n//\t{\r\n//\t\tGX::SetTevKColor( (GXTevKColorID)(((int)GX_KCOLOR0)+tev_id), (GXColor){matcol.r,matcol.g,matcol.b,fix} );\r\n//\t\tGX::SetTevKColorSel( s_id, (GXTevKColorSel)(((int)GX_TEV_KCSEL_K0)+tev_id) );\r\n//\r\n//\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR0A0 );\r\n//\t\tGX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n//\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n//\t\tGX::SetTevAlphaIn ( s_id, rasa, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, rasc, GX_CC_KONST, GX_CC_ZERO );\r\n//\t\tstage_id++;\r\n//\t\ts_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n//\t}\r\n//\t\r\n//\t// Set texture coordinates. Note: If p_tex is NULL, it means this layer is environment mapped.\r\n////\tif ( !(flags & MATFLAG_ENVIRONMENT) )\r\n////\t{\r\n//\t\t*p_uv_slot = uv_id;\r\n//\t\tuv_id++;\r\n////\t} else {\r\n////\t\t*p_uv_slot = -1;\r\n////\t}\r\n//\r\n//\t// Load this texture up into a temporary register for use later.\r\n//\t// Note: conveniently, the 1st texture ends up in TEVPREV which means it will be fine\r\n//\t// if no blends are performed.\r\n//\tswitch ( blend )\r\n//\t{\r\n//\t\tcase vBLEND_MODE_ADD_FIXED:\r\n//\t\tcase vBLEND_MODE_SUB_FIXED:\r\n//\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n//\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n//\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n//\t\t\tGX::SetTevKAlphaSel( s_id, (GXTevKAlphaSel)(((int)GX_TEV_KASEL_K0_A)+tev_id) );\r\n//\t\t\tif ( !uniqueMaterialColor ) GX::SetTevKColor( (GXTevKColorID)(((int)GX_KCOLOR0)+tev_id), (GXColor){fix,fix,fix,fix} );\r\n//\t\t\tGX::SetTevOrder( s_id, u_id, t_id, GX_COLOR0A0 );\r\n//            GX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n//\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n//\t\t\tif ( uniqueMaterialColor )\r\n//\t\t\t{\r\n//\t\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_KONST, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\t\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_TEXC, (GXTevColorArg)(((int)GX_CC_CPREV)+(reg_id*2)), GX_CC_ZERO );\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_KONST, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\t\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_TEXC, rasc, GX_CC_ZERO );\r\n//\t\t\t}\r\n//\t\t\tstage_id++;\r\n//\t\t\tbreak;\r\n//\t\tcase vBLEND_MODE_ADD:\r\n//\t\tcase vBLEND_MODE_SUBTRACT:\r\n//\t\tcase vBLEND_MODE_BLEND:\r\n//\t\tcase vBLEND_MODE_BRIGHTEN:\r\n//\t\tcase vBLEND_MODE_MODULATE:\r\n//\t\tcase vBLEND_MODE_DIFFUSE:\r\n//\t\tdefault:\r\n//\t\t\t// We need to add a stage, if we have an alpha map.\r\n//\t\t\tif ( alpha_map >= 0 )\r\n//\t\t\t{\r\n//\t\t\t\t// Set inputs.\r\n//\t\t\t\tGXTexMapID a_id = (GXTexMapID)(((int)GX_TEXMAP0)+alpha_map);\r\n//\r\n//\t\t\t\tGX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP1 );       // Alpha map is in Green channel, so use this to swap it to the alpha channel.\r\n//\t\t\t\tGX::SetTevOrder( s_id, u_id, a_id, GX_COLOR0A0 );\r\n//\t\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n//\t\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n//\t\t\t\tif ( uniqueMaterialColor )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_TEXA, (GXTevAlphaArg)(((int)GX_CA_APREV)+reg_id), GX_CA_ZERO );\r\n//\t\t\t\t\tGX::SetTevColorIn ( s_id, (GXTevColorArg)(((int)GX_CC_CPREV)+(reg_id*2)), GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_TEXA, rasa, GX_CA_ZERO );\r\n//\t\t\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n//\t\t\t\t}\r\n//\t\t\t\tstage_id++;\r\n//\t\t\t\ts_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n//\t\t\t\tGX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\t\tGX::SetTevOrder( s_id, u_id, t_id, GX_COLOR0A0 );\r\n//\t\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n//\t\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n//\t\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, (GXTevAlphaArg)(((int)GX_CA_APREV)+reg_id), GX_CA_TEXA, GX_CA_ZERO );\r\n//\t\t\t\tif ( uniqueMaterialColor )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_TEXC, (GXTevColorArg)(((int)GX_CC_CPREV)+(reg_id*2)), GX_CC_ZERO );\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_TEXC, rasc, GX_CC_ZERO );\r\n//\t\t\t\t}\r\n//\t\t\t\tstage_id++;\r\n//\t\t\t} else {\r\n//\t\t\t\tGX::SetTevOrder( s_id, u_id, t_id, GX_COLOR0A0 );\r\n//\t\t\t\tGX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n//\t\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n//\t\t\t\tif ( uniqueMaterialColor )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_TEXA, (GXTevAlphaArg)(((int)GX_CA_APREV)+reg_id), GX_CA_ZERO );\r\n//\t\t\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_TEXC, (GXTevColorArg)(((int)GX_CC_CPREV)+(reg_id*2)), GX_CC_ZERO );\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_TEXA, rasa, GX_CA_ZERO );\r\n//\t\t\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_TEXC, rasc, GX_CC_ZERO );\r\n//\t\t\t\t}\r\n//\t\t\t\tstage_id++;\r\n//\t\t\t}\r\n//\r\n//\t\t\tbreak;\r\n//\t}\r\n//\r\n//\tif ( tev_id > 0 ) {\r\n//\t\tmulti_add_layer ( blend, fix );\r\n//\t} else {\r\n//\t\t// Set blend mode for base layer.\r\n//\t\tswitch ( blend )\r\n//\t\t{\r\n//\t\t\tcase vBLEND_MODE_ADD:\r\n//\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n//\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR );\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n//\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n//\t\t\t\tGX::SetBlendMode ( GX_BM_SUBTRACT, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR );\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase vBLEND_MODE_BLEND:\r\n//\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n//\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR );\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n//\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n////\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ONE, GX_LO_CLEAR );\r\n//\t\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n//\t\t\tcase vBLEND_MODE_MODULATE:\r\n////\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ZERO, GX_LO_CLEAR );\r\n//\t\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase vBLEND_MODE_DIFFUSE:\r\n//\t\t\tdefault:\r\n//\t\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );\r\n//\t\t\t\tbreak;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\ttev_id++;\r\n//\tmap_id = cur_map;\r\n//}\r\n//\r\n//static void multi_end ( BlendModes blend, uint32 alphacutoff )\r\n//{\r\n//\t// Special case. If the base layer uses subtractive mode, we need to add a stage to\r\n//\t// modulate the color & alpha.\r\n//\tswitch ( blend )\r\n//\t{\r\n////\t\tcase vBLEND_MODE_DIFFUSE:\r\n////\t\t\tGX::SetAlphaCompare(GX_GEQUAL, 0, GX_AOP_AND, GX_GEQUAL, 0 );\r\n////\t\t\tif ( alphacutoff == 0 )\r\n////\t\t\t{\r\n////\t\t\t\tGXSetZCompLoc( GX_TRUE );\r\n////\t\t\t}\r\n////\t\t\telse\r\n////\t\t\t{\r\n////\t\t\t\tGXSetZCompLoc( GX_FALSE );\t\t// Textures with holes will not write to the z buffer when a<=cutoff.\r\n////\t\t\t}\r\n////\t\t\tbreak;\r\n//\t\tcase vBLEND_MODE_SUB_FIXED:\r\n//\t\tcase vBLEND_MODE_SUBTRACT:\r\n//\t\t\t{\r\n//\t\t\t\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n//\r\n//\t\t\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR_NULL );\r\n//\t\t\t\tGX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV );\r\n//\t\t\t\tGX::SetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_CPREV, GX_CC_APREV, GX_CC_ZERO );\r\n//\t\t\t\tstage_id++;\r\n//\t\t\t\t//GX::SetAlphaCompare(GX_GEQUAL, 0, GX_AOP_AND, GX_GEQUAL, 0 );\r\n////\t\t\t\tGXSetZCompLoc( GX_FALSE );\r\n//\t\t\t}\r\n//\t\t\tbreak;\r\n//\t\tdefault:\r\n//\t\t\t//GX::SetAlphaCompare(GX_GEQUAL, alphacutoff, GX_AOP_AND, GX_GEQUAL, alphacutoff );\r\n////\t\t\tif ( alphacutoff == 0 )\r\n////\t\t\t{\r\n////\t\t\t\tGXSetZCompLoc( GX_TRUE );\r\n////\t\t\t}\r\n////\t\t\telse\r\n////\t\t\t{\r\n////\t\t\t\tGXSetZCompLoc( GX_FALSE );\t\t// Textures with holes will not write to the z buffer when a<=cutoff.\r\n////\t\t\t}\r\n//\t\t\tbreak;\r\n//\t}\r\n//\r\n////\tif ( blend == vBLEND_MODE_DIFFUSE )\r\n////\t{\r\n////\t\t//Always pass pixels with multi-texturing as the base must be opaque.\r\n////\t\tGX::SetAlphaCompare(GX_GEQUAL, 0, GX_AOP_AND, GX_GEQUAL, 0 );\r\n////\t\tGXSetZCompLoc( GX_TRUE );\r\n////\t}\r\n////\telse\r\n////\t{\r\n////\t}\r\n//\r\n//\tif ( correct_color )\r\n//\t{\r\n//\t\tGXTexCoordID u_id;\r\n//\t\t// Convert color0 to s,t for 2-D texture lookup (RG)\r\n//\t\tu_id = (GXTexCoordID)(((int)GX_TEXCOORD0)+uv_id);\r\n//\t\tGX::SetTexCoordGen(u_id, GX_TG_SRTG, GX_TG_COLOR0, GX_IDENTITY);\r\n//\t\tGX::SetTevOrder(GX_TEVSTAGE0, u_id, GX_TEXMAP7, GX_COLOR_NULL);\r\n//\t\tuv_id++;\r\n//\t\r\n//\t\t// Convert color1 to s,t for 2-D texture lookup (BA)\r\n//\t\tu_id = (GXTexCoordID)(((int)GX_TEXCOORD0)+uv_id);\r\n//\t\tGX::SetTexCoordGen(u_id, GX_TG_SRTG, GX_TG_COLOR1, GX_IDENTITY);\r\n//\t\tGX::SetTevOrder(GX_TEVSTAGE1, u_id, GX_TEXMAP7, GX_COLOR_NULL);\r\n//\t\tuv_id++;\r\n//\t\tGX::SetNumChans( 2 );\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tGX::SetNumChans( 1 );\r\n//\t}\r\n//\r\n//\t// Set final number of textures/stages.\r\n//\tGX::SetNumTexGens( uv_id );\r\n//    GX::SetNumTevStages( stage_id );\r\n//}\r\n//\r\n////sMaterial\t\t\t\t\t*Materials;\r\n//uint32\t\t\t\t\t\tNumMaterials;\r\n////Lst::HashTable< sMaterial > *pMaterialTable\t= NULL;\r\n//\r\n//void sMaterial::Submit( uint32 mesh_flags, GXColor mesh_color )\r\n//{\r\n//\t// Figure uv and vc wibble updates if required.\r\n//\tfigure_wibble_uv();\r\n//\tfigure_wibble_vc();\r\n//\r\n//\t\r\n//\r\n//\tfor ( uint layer = 0; layer < Passes; layer++ )\r\n//\t{\r\n//\t\tif( Flags[layer] & MATFLAG_UV_WIBBLE )\r\n//\t\t{\r\n//\t\t\t// Set up the texture generation matrix here.\r\n//\t\t\tMtx\tm;\r\n//\t\t\tMTXTrans( m, m_pUVControl->UVWibbleOffset[layer][0], m_pUVControl->UVWibbleOffset[layer][1], 0.0f );\r\n//\t\t\tswitch ( layer )\r\n//\t\t\t{\r\n//\t\t\t\tcase 0:\r\n//\t\t\t\t\tGX::LoadTexMtxImm( m, GX_TEXMTX0, GX_MTX2x4 );\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\tcase 1:\r\n//\t\t\t\t\tGX::LoadTexMtxImm( m, GX_TEXMTX1, GX_MTX2x4 );\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\tcase 2:\r\n//\t\t\t\t\tGX::LoadTexMtxImm( m, GX_TEXMTX2, GX_MTX2x4 );\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\tcase 3:\r\n//\t\t\t\t\tGX::LoadTexMtxImm( m, GX_TEXMTX3, GX_MTX2x4 );\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\tdefault:\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\t\r\n//\t\t\t}\r\n//\r\n////\t\t\t// Handle UV wibbling.\r\n////\t\t\tD3DXMATRIX mat;\r\n////\t\t\tmat._11 = 1.0f;\t\t\t\t\tmat._12 = 0.0f; \r\n////\t\t\tmat._21 = 0.0f;\t\t\t\t\tmat._22 = 1.0f;\r\n////\t\t\tmat._31 = UVWibbleOffset[p][0];\tmat._32 = UVWibbleOffset[p][1];\r\n////\t\t\tmat._41 = 0.0f;\t\t\t\t\tmat._42 = 0.0f;\r\n////\t\t\tD3DDevice_SetTransform((D3DTRANSFORMSTATETYPE)( D3DTS_TEXTURE0 + p ), &mat );\r\n////\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );\r\n////\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | p );\r\n//\t\t}\r\n//\t}\r\n//\r\n////\t// Generate display list.\r\n////\r\n////\tmulti_start ( Passes );\r\n////\tfor ( uint layer = 0; layer < Passes ; layer++ )\r\n////\t{\r\n////\t\tGXTexWrapMode u_mode;\r\n////\t\tGXTexWrapMode v_mode;\r\n////\t\tif ( Flags[layer] & MATFLAG_ENVIRONMENT )\r\n////\t\t{\r\n////\t\t\tu_mode = GX_REPEAT;\r\n////\t\t\tv_mode = GX_REPEAT;\r\n////\t\t}\r\n////\t\telse\r\n////\t\t{\r\n////\t\t\tu_mode = UVAddressing[layer] & (1<<0)  ? GX_CLAMP : GX_REPEAT;\r\n////\t\t\tv_mode = UVAddressing[layer] & (1<<1) ? GX_CLAMP : GX_REPEAT;\r\n////\t\t}\r\n////\r\n////\t\tif ( pTex[layer] )\r\n////\t\t{\r\n////\t\t\tmulti_add_texture ( pTex[layer],\r\n////\t\t\t\t\t\t\t\tmatcol[layer],\r\n////\t\t\t\t\t\t\t\tu_mode,\r\n////\t\t\t\t\t\t\t\tv_mode,\r\n////\t\t\t\t\t\t\t\t(BlendModes)blendMode[layer],\r\n////\t\t\t\t\t\t\t\tfixAlpha[layer],\r\n////\t\t\t\t\t\t\t\tFlags[layer],\r\n////\t\t\t\t\t\t\t\t&uv_slot[layer],\r\n////\t\t\t\t\t\t\t\tK[layer] );\r\n////\t\t}\r\n////\t\telse\r\n////\t\t{\r\n////\t\t\t// Untextured.\r\n////\t\t\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n////\t\t\tBlendModes blend = (BlendModes)blendMode[layer];\r\n////\t\t\tuint32 fix = fixAlpha[layer];\r\n////\r\n////\t\t\tuv_slot[layer] = -1;\r\n////\r\n////\t\t\tswitch ( blend )\r\n////\t\t\t{\r\n////\t\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n////\t\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n////\t\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n////\t\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n////\t\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n////\t\t\t\t\tGX::SetTevKAlphaSel( s_id, (GXTevKAlphaSel)(((int)GX_TEV_KASEL_K0_A)+tev_id) );\r\n////\t\t\t\t\tGX::SetTevKColor( (GXTevKColorID)(((int)GX_KCOLOR0)+tev_id), (GXColor){fix,fix,fix,fix} );\r\n////\t\t\t\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR0A0 );\r\n////\t\t\t\t\tGX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n////\t\t\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id) );\r\n////\t\t\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id) );\r\n////\t\t\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_KONST, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n////\t\t\t\t\tGX::SetTevColorIn ( s_id, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n////\t\t\t\t\tstage_id++;\r\n////\t\t\t\t\tbreak;\r\n////\t\t\t\tcase vBLEND_MODE_ADD:\r\n////\t\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n////\t\t\t\tcase vBLEND_MODE_BLEND:\r\n////\t\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n////\t\t\t\tcase vBLEND_MODE_MODULATE:\r\n////\t\t\t\tcase vBLEND_MODE_DIFFUSE:\r\n////\t\t\t\tdefault:\r\n////\t\t\t\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR0A0 );\r\n////\t\t\t\t\tGX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n////\t\t\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id) );\r\n////\t\t\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id) );\r\n////\t\t\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_RASA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n////\t\t\t\t\tGX::SetTevColorIn ( s_id, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n////\t\t\t\t\tstage_id++;\r\n////\t\t\t\t\tbreak;\r\n////\t\t\t}\r\n////\r\n////\t\t\tif ( tev_id > 0 ) {\r\n////\t\t\t\tmulti_add_layer ( blend, fix );\r\n////\t\t\t} else {\r\n////\t\t\t\t// Set blend mode for base layer.\r\n////\t\t\t\tswitch ( blend )\r\n////\t\t\t\t{\r\n////\t\t\t\t\tcase vBLEND_MODE_ADD:\r\n////\t\t\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n////\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR );\r\n////\t\t\t\t\t\tbreak;\r\n////\t\t\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n////\t\t\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n////\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_SUBTRACT, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR );\r\n////\t\t\t\t\t\tbreak;\r\n////\t\t\t\t\tcase vBLEND_MODE_BLEND:\r\n////\t\t\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n////\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR );\r\n////\t\t\t\t\t\tbreak;\r\n////\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n////\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n////\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ONE, GX_LO_CLEAR );\r\n////\t\t\t\t\t\tbreak;\r\n////\t\t\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n////\t\t\t\t\tcase vBLEND_MODE_MODULATE:\r\n////\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ZERO, GX_LO_CLEAR );\r\n////\t\t\t\t\t\tbreak;\r\n////\t\t\t\t\tcase vBLEND_MODE_DIFFUSE:\r\n////\t\t\t\t\tdefault:\r\n////\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );\r\n////\t\t\t\t\t\tbreak;\r\n////\t\t\t\t}\r\n////\t\t\t}\r\n////\t\t\ttev_id++;\r\n////\t\t}\r\n////\t}\r\n////\r\n////\tmulti_end( (BlendModes)blendMode[0], AlphaCutoff );\r\n//\r\n//\r\n//\t// Set the cull mode, but only if the calling code didn't override this by setting CULL_NONE.\r\n//\tif ( EngineGlobals.poly_culling )\r\n//\t{\r\n//\t\tGX::SetCullMode ( m_no_bfc ? GX_CULL_NONE : GX_CULL_FRONT );\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tGX::SetCullMode ( GX_CULL_NONE );\r\n//\t}\r\n//\r\n//#ifdef __USE_MAT_DL__\r\n//\tif ( mp_display_list )\r\n//\t{\r\n//\t\tGXCallDisplayList ( mp_display_list, m_display_list_size ); \r\n//\t}\r\n//#else\r\n//\tInitialize( mesh_flags, mesh_color );\r\n//#endif\t\t// __USE_MAT_DL__\r\n//\r\n//\t// See if we need to set the comp location (just check the base layer).\r\n//\tif ( pTex[0] )\r\n//\t{\r\n//\t\tif ( pTex[0]->HasHoles )\r\n//\t\t{\r\n//\t\t\tGX::SetZCompLoc( GX_FALSE );\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n////\t\t\tGX::SetZCompLoc( GX_FALSE );\r\n//\t\t\tGX::SetZCompLoc( GX_TRUE );\r\n////\t\t\tGX::SetAlphaCompare(GX_GEQUAL, 0, GX_AOP_AND, GX_GEQUAL, 0 );\r\n//\t\t}\r\n//\t}\r\n//\tGX::SetAlphaCompare(GX_GEQUAL, AlphaCutoff, GX_AOP_AND, GX_GEQUAL, AlphaCutoff );\r\n//\r\n////\tif ( mp_display_list )\r\n////\t{\r\n////\t\tGXCallDisplayList ( mp_display_list, m_display_list_size ); \r\n////\t}\r\n////\telse\r\n////\t{\r\n////\t\t// If no material, default to purple, untextured.\r\n////\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);\r\n////\t\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n////\t\tGX::SetNumTexGens( 0 );\r\n////\t\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n////\t\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n////\t\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n////\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );\r\n////\t\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n////\t\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n////\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,0,255,255} );\r\n////\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){128,128,128,255} );\r\n////\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n////\t}\r\n//}\r\n//\r\n//void sMaterial::Initialize( uint32 mesh_flags, GXColor mesh_color )\r\n//{\r\n//#ifdef __USE_MAT_DL__\r\n//\t// Generate display list.\r\n//\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n//#define DL_BUILD_SIZE (32*1024)\r\n//\tuint8 * p_build_dl = new (Mem::Manager::sHandle().TopDownHeap()) uint8[DL_BUILD_SIZE];\r\n//\tDCFlushRange ( p_build_dl, DL_BUILD_SIZE );\r\n//\r\n//\tGXBeginDisplayList ( p_build_dl, DL_BUILD_SIZE );\r\n//\tGXResetWriteGatherPipe();\r\n//#endif\t\t// __USE_MAT_DL__\r\n//\r\n//\tmulti_start ( Passes );\r\n//\tfor ( uint layer = 0; layer < Passes ; layer++ )\r\n//\t{\r\n//\t\tGXTexWrapMode u_mode;\r\n//\t\tGXTexWrapMode v_mode;\r\n//\t\tif ( Flags[layer] & MATFLAG_ENVIRONMENT )\r\n//\t\t{\r\n//\t\t\tu_mode = GX_REPEAT;\r\n//\t\t\tv_mode = GX_REPEAT;\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tu_mode = UVAddressing[layer] & (1<<0)  ? GX_CLAMP : GX_REPEAT;\r\n//\t\t\tv_mode = UVAddressing[layer] & (1<<1) ? GX_CLAMP : GX_REPEAT;\r\n//\t\t}\r\n//\r\n//\t\tGXColor col;\r\n//\r\n//\t\tif ( mesh_flags & sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE && !( Flags[layer] & 0x80 ) )\r\n//\t\t{\r\n//\t\t\tcol = mesh_color;\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tcol = matcol[layer];\r\n//\t\t}\r\n//\r\n//\t\tif ( pTex[layer] )\r\n//\t\t{\r\n//\t\t\tmulti_add_texture ( pTex[layer],\r\n//\t\t\t\t\t\t\t\tcol,\r\n//\t\t\t\t\t\t\t\tu_mode,\r\n//\t\t\t\t\t\t\t\tv_mode,\r\n//\t\t\t\t\t\t\t\t(BlendModes)blendMode[layer],\r\n//\t\t\t\t\t\t\t\tfixAlpha[layer],\r\n//\t\t\t\t\t\t\t\tFlags[layer],\r\n//\t\t\t\t\t\t\t\t&uv_slot[layer],\r\n//\t\t\t\t\t\t\t\tK[layer] );\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\t// Untextured.\r\n//\t\t\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n//\t\t\tBlendModes blend = (BlendModes)blendMode[layer];\r\n//\t\t\tuint32 fix = fixAlpha[layer];\r\n//\r\n//\t\t\tuv_slot[layer] = -1;\r\n//\r\n//\t\t\tswitch ( blend )\r\n//\t\t\t{\r\n//\t\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n//\t\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n//\t\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n//\t\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n//\t\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n//\t\t\t\t\tGX::SetTevKAlphaSel( s_id, (GXTevKAlphaSel)(((int)GX_TEV_KASEL_K0_A)+tev_id) );\r\n//\t\t\t\t\tGX::SetTevKColor( (GXTevKColorID)(((int)GX_KCOLOR0)+tev_id), (GXColor){fix,fix,fix,fix} );\r\n//\t\t\t\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR0A0 );\r\n//\t\t\t\t\tGX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id) );\r\n//\t\t\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id) );\r\n//\t\t\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_KONST, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\t\t\t\t\tGX::SetTevColorIn ( s_id, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n//\t\t\t\t\tstage_id++;\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\tcase vBLEND_MODE_ADD:\r\n//\t\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n//\t\t\t\tcase vBLEND_MODE_BLEND:\r\n//\t\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n//\t\t\t\tcase vBLEND_MODE_MODULATE:\r\n//\t\t\t\tcase vBLEND_MODE_DIFFUSE:\r\n//\t\t\t\tdefault:\r\n//\t\t\t\t\tGX::SetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR0A0 );\r\n//\t\t\t\t\tGX::SetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\t\t\tGX::SetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id) );\r\n//\t\t\t\t\tGX::SetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id) );\r\n//\t\t\t\t\tGX::SetTevAlphaIn ( s_id, GX_CA_RASA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\t\t\t\t\tGX::SetTevColorIn ( s_id, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n//\t\t\t\t\tstage_id++;\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t}\r\n//\r\n//\t\t\tif ( tev_id > 0 ) {\r\n//\t\t\t\tmulti_add_layer ( blend, fix );\r\n//\t\t\t} else {\r\n//\t\t\t\t// Set blend mode for base layer.\r\n//\t\t\t\tswitch ( blend )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tcase vBLEND_MODE_ADD:\r\n//\t\t\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n//\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n//\t\t\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n//\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_SUBTRACT, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tcase vBLEND_MODE_BLEND:\r\n//\t\t\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n//\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n//\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n//\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ONE, GX_LO_CLEAR );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n//\t\t\t\t\tcase vBLEND_MODE_MODULATE:\r\n//\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ZERO, GX_LO_CLEAR );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tcase vBLEND_MODE_DIFFUSE:\r\n//\t\t\t\t\tdefault:\r\n//\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\ttev_id++;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tmulti_end( (BlendModes)blendMode[0], AlphaCutoff );\r\n//\r\n//#ifdef __USE_MAT_DL__\r\n//\tint size = GXEndDisplayList();\r\n//\r\n//\t// If we already have a display list & this one will fit, just use the existing piece of memory.\r\n//\tuint8 * p_dl;\r\n//\tif ( mp_display_list && ( size <= m_display_list_size ) )\r\n//\t{\r\n//\t\tp_dl = mp_display_list;\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tif ( mp_display_list )\r\n//\t\t{\r\n//\t\t\t//gMatBytes -= m_display_list_size;\r\n//\t\t\tdelete mp_display_list;\r\n//\t\t}\r\n//\t\tp_dl = new uint8[size];\r\n//\t\t//gMatBytes += size;\r\n//\t}\r\n//\r\n//\tmemcpy ( p_dl, p_build_dl, size );\r\n//\tDCFlushRange ( p_dl, size );\r\n//\r\n//\tdelete p_build_dl;\r\n//\r\n//\tmp_display_list = p_dl;\r\n//\tm_display_list_size = size;\r\n//\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n//#endif\t\t// __USE_MAT_DL__\r\n//}\r\n\r\n\r\n\r\n\r\nsMaterial* GetMaterial( uint32 checksum, sScene *p_scene )\r\n{\r\n//\tfor ( int lp = 0; lp < p_scene->m_num_materials; lp++ )\r\n//\t{\r\n//\t\tif( p_scene->mp_material_array[lp].Checksum == checksum )\r\n//\t\t{\r\n//\t\t\treturn &p_scene->mp_material_array[lp];\r\n//\t\t}\r\n//\t}\r\n\treturn NULL;\r\n}\r\n\r\nvoid InitializeMaterial( sMaterial* p_material )\r\n{\r\n//\tp_material->Initialize();\r\n\tp_material->uv_slot[0] = 0;\r\n\tp_material->uv_slot[1] = 1;\r\n\tp_material->uv_slot[2] = 2;\r\n\tp_material->uv_slot[3] = 3;\r\n}\r\n\r\n#define MemoryRead( dst, size, num, src )\tmemcpy(( dst ), ( src ), (( num ) * ( size )));\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t( src ) += (( num ) * ( size ))\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsMaterial * LoadMaterialsFromMemory( void **pp_mem, Lst::HashTable< Nx::CTexture > *p_texture_table, int * p_num_materials )\r\n{\r\n\tuint8\t*p_data = (uint8*)( *pp_mem );\r\n\tuint32 MMAG, MMIN, K, L, NumSeqs, seq, NumKeys;\r\n\tuint32 i;\r\n\r\n\t// Get number of materials.\r\n\tuint32 new_materials;\r\n\tMemoryRead( &new_materials, sizeof( uint32 ), 1, p_data );\r\n\t\r\n\tif ( p_num_materials ) *p_num_materials = new_materials;\r\n\r\n\t// Create array of materials.\r\n\tsMaterial * p_mat_array = new sMaterial[new_materials];\r\n\t\r\n\t// Loop over materials.\r\n\tfor( i = 0; i < new_materials; ++i )\r\n\t{\r\n\t\t// Create new material.\r\n\t\tsMaterial *pMat = &p_mat_array[i];\r\n\t\t\r\n\t\tpMat->m_num_wibble_vc_anims\t= 0;\r\n\t\tpMat->mp_wibble_vc_params\t= NULL;\r\n\t\tpMat->mp_wibble_vc_colors\t= NULL;\r\n\r\n\t\t// Get material checksum.\r\n\t\tMemoryRead( &pMat->Checksum, sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t// Get number of passes.\r\n\t\tuint32 pass;\r\n\t\tMemoryRead( &pass, sizeof( uint32 ), 1, p_data );\r\n\t\tpMat->Passes = pass;\r\n\r\n\t\t// Get alpha cutoff value.\r\n\t\tuint32 ac;\r\n\t\tMemoryRead( &ac, sizeof( uint32 ), 1, p_data );\r\n\t\tpMat->AlphaCutoff = ac;\t\t//( ac >= 128 ) ? 255 : ( ac * 2 );\r\n\r\n\t\t// Get sorted flag.\r\n\t\tbool sorted;\r\n\t\tMemoryRead( &sorted, sizeof( bool ), 1, p_data );\r\n\t\tpMat->m_sorted = sorted;\r\n\t\t\r\n\t\t// Get draw order.\r\n\t\tMemoryRead( &pMat->m_draw_order, sizeof( float ), 1, p_data );\r\n\t\t\r\n\t\t// Get backface cull flag.\r\n\t\tbool bfc;\r\n\t\tMemoryRead( &bfc, sizeof( bool ), 1, p_data );\r\n\t\tpMat->m_no_bfc = bfc;\r\n\r\n//\t\t// Get grassify flag and (optionally) grassify data.\r\n//\t\tbool grassify;\r\n//\t\tMemoryRead( &grassify, sizeof( bool ), 1, p_data );\r\n//\t\tpMat->m_grassify = (uint8)grassify;\r\n//\t\tif( grassify )\r\n//\t\t{\r\n//\t\t\tMemoryRead( &pMat->m_grass_height, sizeof( float ), 1, p_data );\r\n//\t\t\tint layers;\r\n//\t\t\tMemoryRead( &layers, sizeof( int ), 1, p_data );\r\n//\t\t\tpMat->m_grass_layers = (uint8)layers;\r\n//\t\t}\r\n\r\n\t\tGXColor mat_col[MAX_PASSES];\r\n\r\n\t\tpMat->m_pUVControl = NULL;\r\n\t\tfor( uint32 pass = 0; pass < pMat->Passes; ++pass )\r\n\t\t{\r\n\t\t\t// Get texture checksum.\r\n\t\t\tuint32 TextureChecksum;\r\n\t\t\tMemoryRead( &TextureChecksum, sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t\t// Get material flags.\r\n\t\t\tMemoryRead( &pMat->Flags[pass], sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t\t// Get ALPHA register value.\r\n\t\t\tuint64 ra;\r\n\t\t\tMemoryRead( &ra, sizeof( uint64 ), 1, p_data );\r\n\t\t\tpMat->blendMode[pass] = ra & 0xff;\r\n\t\t\tpMat->fixAlpha[pass] = ( ra >> 32 ) & 0xff;\r\n\r\n\t\t\t// Backface cull test - if this is an alpha blended material, turn off backface culling.\r\n\t\t\tif(( pass == 0 ) && (( ra & 0xFF ) != 0x00 ))\r\n\t\t\t{\r\n\t\t\t\tpMat->m_no_bfc = true;\r\n\t\t\t}\r\n\r\n\t\t\t// Get UV addressing types.\r\n\t\t\tuint32 u_addressing, v_addressing;\r\n\t\t\tMemoryRead( &u_addressing, sizeof( uint32 ), 1, p_data );\r\n\t\t\tMemoryRead( &v_addressing, sizeof( uint32 ), 1, p_data );\r\n\t\t\tpMat->UVAddressing[pass] = (( v_addressing << 1 ) | u_addressing );\r\n\t\t\t\r\n\t\t\t// Step past material colors, currently unsupported.\r\n\t\t\tfloat col[9];\r\n\t\t\tMemoryRead( col, sizeof( float ) * 9, 1, p_data );\r\n\r\n\t\t\tmat_col[pass].r = (u8)((col[0] * 255.0f) + 0.5f);\r\n\t\t\tmat_col[pass].g = (u8)((col[1] * 255.0f) + 0.5f);\r\n\t\t\tmat_col[pass].b = (u8)((col[2] * 255.0f) + 0.5f);\r\n\t\t\tmat_col[pass].a = 255;\r\n\r\n\t\t\t// Read uv wibble data if present.\r\n\t\t\tif( pMat->Flags[pass] & MATFLAG_UV_WIBBLE )\r\n\t\t\t{\r\n\t\t\t\tif ( !pMat->m_pUVControl ) pMat->m_pUVControl = new sUVControl;\r\n\t\t\t\tMemoryRead( &( pMat->m_pUVControl->UVWibbleParams[pass] ), sizeof( sUVWibbleParams ), 1, p_data );\r\n\t\t\t}\r\n\r\n\t\t\t// Step past vc wibble data, currently unsupported.\r\n\t\t\tif(( pass == 0 ) && ( pMat->Flags[0] & MATFLAG_VC_WIBBLE ))\r\n\t\t\t{\r\n\t\t\t\tMemoryRead( &NumSeqs, sizeof( uint32 ), 1, p_data );\r\n\t\t\t\tpMat->m_num_wibble_vc_anims = NumSeqs;\r\n\r\n\t\t\t\t// Create sequence data array.\r\n\t\t\t\tpMat->mp_wibble_vc_params = new sVCWibbleParams[NumSeqs];\r\n\t\t\t\t\r\n\t\t\t\t// Create resultant color array.\r\n\t\t\t\tpMat->mp_wibble_vc_colors = new uint32[NumSeqs];\r\n\r\n\t\t\t\tfor( seq = 0; seq < NumSeqs; ++seq )\r\n\t\t\t\t{ \r\n\t\t\t\t\tMemoryRead( &NumKeys, sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t\t\t\tint phase;\r\n\t\t\t\t\tMemoryRead( &phase, sizeof( int ), 1, p_data );\r\n\r\n\t\t\t\t\t// Create array for keyframes.\r\n\t\t\t\t\tpMat->mp_wibble_vc_params[seq].m_num_keyframes\t= NumKeys;\r\n\t\t\t\t\tpMat->mp_wibble_vc_params[seq].m_phase\t\t\t= phase;\r\n\t\t\t\t\tpMat->mp_wibble_vc_params[seq].mp_keyframes\t\t= new sVCWibbleKeyframe[NumKeys];\r\n\r\n\t\t\t\t\t// Read keyframes into array.\r\n\t\t\t\t\tMemoryRead( pMat->mp_wibble_vc_params[seq].mp_keyframes, sizeof( sVCWibbleKeyframe ), NumKeys, p_data );\r\n\r\n\t\t\t\t\tfor ( uint lp = 0; lp < NumKeys; lp++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tuint8 r = pMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.r;\r\n\t\t\t\t\t\tuint8 g = pMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.g;\r\n\t\t\t\t\t\tuint8 b = pMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.b;\r\n\t\t\t\t\t\tuint8 a = pMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.a;\r\n\t\t\t\t\t\tpMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.r = b;\r\n\t\t\t\t\t\tpMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.g = r;\r\n\t\t\t\t\t\tpMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.b = g;\r\n\t\t\t\t\t\tpMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.a = a;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif( TextureChecksum )\r\n\t\t\t{\r\n\t\t\t\t// If textured, resolve texture checksum...\r\n\t\t\t\tNx::CNgcTexture *p_ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture_table->GetItem( TextureChecksum ) );\r\n\t\t\t\tsTexture *pTex = ( p_ngc_texture ) ? p_ngc_texture->GetEngineTexture() : NULL;\r\n\r\n\t\t\t\t// Bail if checksum not found.\r\n\t\t\t\tif( pTex == NULL )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Message( \"error: couldn't find texture checksum %08X\\n\", TextureChecksum );\r\n//\t\t\t\t\texit( 1 );\r\n\t\t\t\t\tpMat->pTex[pass] = NULL;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Set texture pointer.\r\n\t\t\t\t\tpMat->pTex[pass] = pTex;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Get mipmap info.\r\n\t\t\t\tMemoryRead( &MMAG, sizeof( uint32 ), 1, p_data );\r\n\t\t\t\tMemoryRead( &MMIN, sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t\t\tMemoryRead( &K, sizeof( uint32 ), 1, p_data );\r\n\t\t\t\tMemoryRead( &L, sizeof( uint32 ), 1, p_data );\r\n\t\t\t\t\r\n\t\t\t\t// Default PS2 value for K appears to be -8.0f - we are interested in deviations from this value.\r\n\t\t\t\tpMat->K[pass]\t= ( *(float*)&K ) + 8.0f;\r\n\t\t\t\r\n\t\t\t\t// Dave note 08/03/02 - having MIPs selected earlier than normal seems to cause some problems, since Xbox\r\n\t\t\t\t// MIP selection is so different to Ps2. Limit the k value such that Xbox can never select smaller MIPs\r\n\t\t\t\t// earlier than it would do by default.\r\n\t\t\t\tif( pMat->K[pass] > 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tpMat->K[pass] = 0.0f;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// ...otherwise just step past mipmap info.\r\n\t\t\t\tpMat->pTex[pass] = NULL;\r\n\t\t\t\tuint32 mip[4];\r\n\t\t\t\tMemoryRead( mip, sizeof( uint32 ) * 4, 1, p_data );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Generate material colors.\r\n\t\tfor( uint32 pass = 0; pass < pMat->Passes; ++pass )\r\n\t\t{\r\n\t\t\tif ( ( mat_col[0].r == mat_col[pass].r ) &&\r\n\t\t\t\t ( mat_col[0].g == mat_col[pass].g ) && \r\n\t\t\t\t ( mat_col[0].b == mat_col[pass].b ) && \r\n\t\t\t\t ( mat_col[0].a == mat_col[pass].a ) )\r\n\t\t\t{\r\n\t\t\t\t// Do nothing.\r\n\t\t\t\tpMat->matcol[pass] = (GXColor){128,128,128,255};\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Work out the texture color.\r\n\t\t\t\tGXColor tc;\r\n\t\t\t\tfloat base_r = (float)(mat_col[0].r > 0 ? mat_col[0].r : 1 );\r\n\t\t\t\tfloat base_g = (float)(mat_col[0].g > 0 ? mat_col[0].g : 1 );\r\n\t\t\t\tfloat base_b = (float)(mat_col[0].b > 0 ? mat_col[0].b : 1 );\r\n\t\t\t\tfloat base_a = (float)(mat_col[0].a > 0 ? mat_col[0].a : 1 );\r\n\t\t\t\tfloat r = ( ((float)mat_col[pass].r) / base_r ) * 128.0f;\r\n\t\t\t\tfloat g = ( ((float)mat_col[pass].g) / base_g ) * 128.0f;\r\n\t\t\t\tfloat b = ( ((float)mat_col[pass].b) / base_b ) * 128.0f;\r\n\t\t\t\tfloat a = ( ((float)mat_col[pass].a) / base_a ) * 255.0f;\r\n\t\t\t\tint _r = (int)r;\r\n\t\t\t\tint _g = (int)g;\r\n\t\t\t\tint _b = (int)b;\r\n\t\t\t\tint _a = (int)a;\r\n\t\t\t\tif ( _r > 255 ) _r = 255;\r\n\t\t\t\tif ( _g > 255 ) _g = 255;\r\n\t\t\t\tif ( _b > 255 ) _b = 255;\r\n\t\t\t\tif ( _a > 255 ) _a = 255;\r\n\t\t\t\ttc.r = (u8)( _r );\r\n\t\t\t\ttc.g = (u8)( _g );\r\n\t\t\t\ttc.b = (u8)( _b );\r\n\t\t\t\ttc.a = (u8)( _a );\r\n\t\t\t\tpMat->matcol[pass] = tc;\r\n\t\t\t}\r\n\t\t}\r\n\r\n//\t\tpMat->mp_display_list = NULL;\r\n//\t\tpMat->Initialize();\r\n\t\tpMat->uv_slot[0] = 0;\r\n\t\tpMat->uv_slot[1] = 1;\r\n\t\tpMat->uv_slot[2] = 2;\r\n\t\tpMat->uv_slot[3] = 3;\r\n\t}\r\n\t*pp_mem = p_data;\r\n\r\n\treturn p_mat_array;\r\n}\r\n\r\nsMaterial *LoadMaterials( void *p_FH, Lst::HashTable< Nx::CTexture > *p_texture_table, int * p_num_materials )\r\n{\r\n\tuint32 MMAG, MMIN, K, L, NumSeqs, seq, NumKeys;\r\n\tuint32 i;\r\n\r\n\t// Get number of materials.\r\n\tuint32 new_materials;\r\n\tFile::Read( &new_materials, sizeof( uint32 ), 1, p_FH );\r\n\t\r\n\tif ( p_num_materials ) *p_num_materials = new_materials;\r\n\r\n\t// Create array of materials.\r\n\tsMaterial * p_mat_array = new sMaterial[new_materials];\r\n\t\r\n\t// Loop over materials.\r\n\tfor( i = 0; i < new_materials; ++i )\r\n\t{\r\n\t\t// Create new material.\r\n\t\tsMaterial *pMat = &p_mat_array[i];\r\n\t\t\r\n\t\tpMat->m_num_wibble_vc_anims\t= 0;\r\n\t\tpMat->mp_wibble_vc_params\t= NULL;\r\n\t\tpMat->mp_wibble_vc_colors\t= NULL;\r\n\r\n\t\t// Get material checksum.\r\n\t\tFile::Read( &pMat->Checksum, sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t// Get number of passes.\r\n\t\tuint32 pass;\r\n\t\tFile::Read( &pass, sizeof( uint32 ), 1, p_FH );\r\n\t\tpMat->Passes = pass;\r\n\r\n\t\t// Get alpha cutoff value.\r\n\t\tuint32 ac;\r\n\t\tFile::Read( &ac, sizeof( uint32 ), 1, p_FH );\r\n\t\tpMat->AlphaCutoff = ac;\t\t//( ac >= 128 ) ? 255 : ( ac * 2 );\r\n\r\n\t\t// Get sorted flag.\r\n\t\tbool sorted;\r\n\t\tFile::Read( &sorted, sizeof( bool ), 1, p_FH );\r\n\t\tpMat->m_sorted = sorted;\r\n\t\t\r\n\t\t// Get draw order.\r\n\t\tFile::Read( &pMat->m_draw_order, sizeof( float ), 1, p_FH );\r\n\t\t\r\n\t\t// Get backface cull flag.\r\n\t\tbool bfc;\r\n\t\tFile::Read( &bfc, sizeof( bool ), 1, p_FH );\r\n\t\tpMat->m_no_bfc = bfc;\r\n\r\n//\t\t// Get grassify flag and (optionally) grassify data.\r\n//\t\tbool grassify;\r\n//\t\tFile::Read( &grassify, sizeof( bool ), 1, p_FH );\r\n//\t\tpMat->m_grassify = (uint8)grassify;\r\n//\t\tif( grassify )\r\n//\t\t{\r\n//\t\t\tFile::Read( &pMat->m_grass_height, sizeof( float ), 1, p_FH );\r\n//\t\t\tint layers;\r\n//\t\t\tFile::Read( &layers, sizeof( int ), 1, p_FH );\r\n//\t\t\tpMat->m_grass_layers = (uint8)layers;\r\n//\t\t}\r\n\r\n\t\tGXColor mat_col[MAX_PASSES];\r\n\r\n\t\tpMat->m_pUVControl = NULL;\r\n\t\tfor( uint32 pass = 0; pass < pMat->Passes; ++pass )\r\n\t\t{\r\n\t\t\t// Get texture checksum.\r\n\t\t\tuint32 TextureChecksum;\r\n\t\t\tFile::Read( &TextureChecksum, sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t\t// Get material flags.\r\n\t\t\tFile::Read( &pMat->Flags[pass], sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t\t// Get ALPHA register value.\r\n\t\t\tuint64 ra;\r\n\t\t\tFile::Read( &ra, sizeof( uint64 ), 1, p_FH );\r\n\t\t\tpMat->blendMode[pass] = ra & 0xff;\r\n\t\t\tpMat->fixAlpha[pass] = ( ra >> 32 ) & 0xff;\r\n\r\n\t\t\t// Backface cull test - if this is an alpha blended material, turn off backface culling.\r\n\t\t\tif(( pass == 0 ) && (( ra & 0xFF ) != 0x00 ))\r\n\t\t\t{\r\n\t\t\t\tpMat->m_no_bfc = true;\r\n\t\t\t}\r\n\r\n\t\t\t// Get UV addressing types.\r\n\t\t\tuint32 u_addressing, v_addressing;\r\n\t\t\tFile::Read( &u_addressing, sizeof( uint32 ), 1, p_FH );\r\n\t\t\tFile::Read( &v_addressing, sizeof( uint32 ), 1, p_FH );\r\n\t\t\tpMat->UVAddressing[pass] = (( v_addressing << 1 ) | u_addressing );\r\n\t\t\t\r\n\t\t\t// Step past material colors, currently unsupported.\r\n\t\t\tfloat col[9];\r\n\t\t\tFile::Read( col, sizeof( float ) * 9, 1, p_FH );\r\n\r\n\t\t\tmat_col[pass].r = (u8)((col[0] * 255.0f) + 0.5f);\r\n\t\t\tmat_col[pass].g = (u8)((col[1] * 255.0f) + 0.5f);\r\n\t\t\tmat_col[pass].b = (u8)((col[2] * 255.0f) + 0.5f);\r\n\t\t\tmat_col[pass].a = 255;\r\n\r\n\t\t\t// Read uv wibble data if present.\r\n\t\t\tif( pMat->Flags[pass] & MATFLAG_UV_WIBBLE )\r\n\t\t\t{\r\n\t\t\t\tif ( !pMat->m_pUVControl ) pMat->m_pUVControl = new sUVControl;\r\n\t\t\t\tFile::Read( &( pMat->m_pUVControl->UVWibbleParams[pass] ), sizeof( sUVWibbleParams ), 1, p_FH );\r\n\t\t\t}\r\n\r\n\t\t\t// Step past vc wibble data, currently unsupported.\r\n\t\t\tif(( pass == 0 ) && ( pMat->Flags[0] & MATFLAG_VC_WIBBLE ))\r\n\t\t\t{\r\n\t\t\t\tFile::Read( &NumSeqs, sizeof( uint32 ), 1, p_FH );\r\n\t\t\t\tpMat->m_num_wibble_vc_anims = NumSeqs;\r\n\r\n\t\t\t\t// Create sequence data array.\r\n\t\t\t\tpMat->mp_wibble_vc_params = new sVCWibbleParams[NumSeqs];\r\n\t\t\t\t\r\n\t\t\t\t// Create resultant color array.\r\n\t\t\t\tpMat->mp_wibble_vc_colors = new uint32[NumSeqs];\r\n\r\n\t\t\t\tfor( seq = 0; seq < NumSeqs; ++seq )\r\n\t\t\t\t{ \r\n\t\t\t\t\tFile::Read( &NumKeys, sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t\t\t\tint phase;\r\n\t\t\t\t\tFile::Read( &phase, sizeof( int ), 1, p_FH );\r\n\r\n\t\t\t\t\t// Create array for keyframes.\r\n\t\t\t\t\tpMat->mp_wibble_vc_params[seq].m_num_keyframes\t= NumKeys;\r\n\t\t\t\t\tpMat->mp_wibble_vc_params[seq].m_phase\t\t\t= phase;\r\n\t\t\t\t\tpMat->mp_wibble_vc_params[seq].mp_keyframes\t\t= new sVCWibbleKeyframe[NumKeys];\r\n\r\n\t\t\t\t\t// Read keyframes into array.\r\n\t\t\t\t\tFile::Read( pMat->mp_wibble_vc_params[seq].mp_keyframes, sizeof( sVCWibbleKeyframe ), NumKeys, p_FH );\r\n\r\n\t\t\t\t\tfor ( uint lp = 0; lp < NumKeys; lp++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tuint8 r = pMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.r;\r\n\t\t\t\t\t\tuint8 g = pMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.g;\r\n\t\t\t\t\t\tuint8 b = pMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.b;\r\n\t\t\t\t\t\tuint8 a = pMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.a;\r\n\t\t\t\t\t\tpMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.r = b;\r\n\t\t\t\t\t\tpMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.g = r;\r\n\t\t\t\t\t\tpMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.b = g;\r\n\t\t\t\t\t\tpMat->mp_wibble_vc_params[seq].mp_keyframes[lp].m_color.a = a;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif( TextureChecksum )\r\n\t\t\t{\r\n\t\t\t\t// If textured, resolve texture checksum...\r\n\t\t\t\tNx::CNgcTexture *p_ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture_table->GetItem( TextureChecksum ) );\r\n\t\t\t\tsTexture *pTex = ( p_ngc_texture ) ? p_ngc_texture->GetEngineTexture() : NULL;\r\n\r\n\t\t\t\t// Bail if checksum not found.\r\n\t\t\t\tif( pTex == NULL )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Message( \"error: couldn't find texture checksum %08X\\n\", TextureChecksum );\r\n//\t\t\t\t\texit( 1 );\r\n\t\t\t\t\tpMat->pTex[pass] = NULL;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Set texture pointer.\r\n\t\t\t\t\tpMat->pTex[pass] = pTex;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Get mipmap info.\r\n\t\t\t\tFile::Read( &MMAG, sizeof( uint32 ), 1, p_FH );\r\n\t\t\t\tFile::Read( &MMIN, sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t\t\tFile::Read( &K, sizeof( uint32 ), 1, p_FH );\r\n\t\t\t\tFile::Read( &L, sizeof( uint32 ), 1, p_FH );\r\n\t\t\t\t\r\n\t\t\t\t// Default PS2 value for K appears to be -8.0f - we are interested in deviations from this value.\r\n\t\t\t\tpMat->K[pass]\t= ( *(float*)&K ) + 8.0f;\r\n\t\t\t\r\n\t\t\t\t// Dave note 08/03/02 - having MIPs selected earlier than normal seems to cause some problems, since Xbox\r\n\t\t\t\t// MIP selection is so different to Ps2. Limit the k value such that Xbox can never select smaller MIPs\r\n\t\t\t\t// earlier than it would do by default.\r\n\t\t\t\tif( pMat->K[pass] > 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tpMat->K[pass] = 0.0f;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// ...otherwise just step past mipmap info.\r\n\t\t\t\tpMat->pTex[pass] = NULL;\r\n\t\t\t\tuint32 mip[4];\r\n\t\t\t\tFile::Read( mip, sizeof( uint32 ) * 4, 1, p_FH );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Generate material colors.\r\n\t\tfor( uint32 pass = 0; pass < pMat->Passes; ++pass )\r\n\t\t{\r\n\t\t\tif ( ( mat_col[0].r == mat_col[pass].r ) &&\r\n\t\t\t\t ( mat_col[0].g == mat_col[pass].g ) && \r\n\t\t\t\t ( mat_col[0].b == mat_col[pass].b ) && \r\n\t\t\t\t ( mat_col[0].a == mat_col[pass].a ) )\r\n\t\t\t{\r\n\t\t\t\t// Do nothing.\r\n\t\t\t\tpMat->matcol[pass] = (GXColor){128,128,128,255};\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Work out the texture color.\r\n\t\t\t\tGXColor tc;\r\n\t\t\t\tfloat base_r = (float)(mat_col[0].r > 0 ? mat_col[0].r : 1 );\r\n\t\t\t\tfloat base_g = (float)(mat_col[0].g > 0 ? mat_col[0].g : 1 );\r\n\t\t\t\tfloat base_b = (float)(mat_col[0].b > 0 ? mat_col[0].b : 1 );\r\n\t\t\t\tfloat base_a = (float)(mat_col[0].a > 0 ? mat_col[0].a : 1 );\r\n\t\t\t\tfloat r = ( ((float)mat_col[pass].r) / base_r ) * 128.0f;\r\n\t\t\t\tfloat g = ( ((float)mat_col[pass].g) / base_g ) * 128.0f;\r\n\t\t\t\tfloat b = ( ((float)mat_col[pass].b) / base_b ) * 128.0f;\r\n\t\t\t\tfloat a = ( ((float)mat_col[pass].a) / base_a ) * 255.0f;\r\n\t\t\t\tint _r = (int)r;\r\n\t\t\t\tint _g = (int)g;\r\n\t\t\t\tint _b = (int)b;\r\n\t\t\t\tint _a = (int)a;\r\n\t\t\t\tif ( _r > 255 ) _r = 255;\r\n\t\t\t\tif ( _g > 255 ) _g = 255;\r\n\t\t\t\tif ( _b > 255 ) _b = 255;\r\n\t\t\t\tif ( _a > 255 ) _a = 255;\r\n\t\t\t\ttc.r = (u8)( _r );\r\n\t\t\t\ttc.g = (u8)( _g );\r\n\t\t\t\ttc.b = (u8)( _b );\r\n\t\t\t\ttc.a = (u8)( _a );\r\n\t\t\t\tpMat->matcol[pass] = tc;\r\n\t\t\t}\r\n\t\t}\r\n\r\n//\t\tpMat->mp_display_list = NULL;\r\n//\t\tpMat->Initialize();\r\n\t\tpMat->uv_slot[0] = 0;\r\n\t\tpMat->uv_slot[1] = 1;\r\n\t\tpMat->uv_slot[2] = 2;\r\n\t\tpMat->uv_slot[3] = 3;\r\n\t}\r\n\r\n\treturn p_mat_array;\r\n}\r\n\r\n} // namespace NxNgc\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/material.h",
    "content": "#ifndef __MATERIAL_H\r\n#define __MATERIAL_H\r\n\r\n#include <core/HashTable.h>\r\n#include \"texture.h\"\r\n#include <gfx/nxtexture.h>\r\n\r\n//#define __USE_MAT_DL__\t\t// Comment out to save memory.\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n// Material Flags\r\n#define MATFLAG_UV_WIBBLE   (1<<0)\r\n#define MATFLAG_VC_WIBBLE   (1<<1)\r\n#define MATFLAG_TEXTURED    (1<<2)\r\n#define MATFLAG_ENVIRONMENT (1<<3)\r\n#define MATFLAG_DECAL       (1<<4)\r\n#define MATFLAG_SMOOTH      (1<<5)\r\n#define MATFLAG_TRANSPARENT (1<<6)\r\n\r\n\r\nconst uint32 MAX_PASSES = 4;\r\n\r\n\t\r\nstruct sUVWibbleParams\r\n{\r\n\tfloat\tm_UVel;\r\n\tfloat\tm_VVel;\r\n\tfloat\tm_UFrequency;\r\n\tfloat\tm_VFrequency;\r\n\tfloat\tm_UAmplitude;\r\n\tfloat\tm_VAmplitude;\r\n\tfloat\tm_UPhase;\r\n\tfloat\tm_VPhase;\r\n};\r\n\r\nstruct sUVControl\r\n{\r\n\tsUVWibbleParams\tUVWibbleParams[MAX_PASSES];         // 128\r\n\tfloat\t\t\tUVWibbleOffset[MAX_PASSES][2];\t\t// 32\r\n};\r\n\r\nstruct sVCWibbleKeyframe\r\n{\r\n\tint\t\t\tm_time;\r\n\tImage::RGBA\tm_color;\r\n};\r\n\r\n\r\n\r\nstruct sVCWibbleParams\r\n{\r\n\tuint32\t\t\t\tm_num_keyframes;\r\n\tint\t\t\t\t\tm_phase;\r\n\tsVCWibbleKeyframe\t*mp_keyframes;\r\n};\r\n\r\n\r\n\r\n\r\nstruct sMaterial\r\n{\r\n//\tsMaterial( void );\r\n//\t~sMaterial( void );\r\n\r\n\tvoid\t\t\tSubmit( uint32 mesh_flags, GXColor mesh_color );\r\n\tvoid\t\t\tInitialize( uint32 mesh_flags, GXColor mesh_color );\r\n\tvoid\t\t\tfigure_wibble_uv( void );\r\n\tvoid\t\t\tfigure_wibble_vc( void );\r\n\t\t\r\n\tuint32\t\t\tChecksum;\t\t\t\t\t\t\t// 4\r\n\tuint8\t\t\tPasses;                             // 1\r\n\tuint8\t\t\tm_sorted;                           // 1\r\n\tuint8\t\t\tm_no_bfc;                           // 1\r\n\tuint8\t\t\tAlphaCutoff;                        // 1\r\n\tfloat\t\t\tm_draw_order;                       // 4\r\n\tuint32\t\t\tFlags[MAX_PASSES];                  // 16\r\n\tsTexture*\t\tpTex[MAX_PASSES];                   // 16\r\n\tuint8\t\t\tblendMode[MAX_PASSES];              // 4\r\n\tuint8\t\t\tfixAlpha[MAX_PASSES];               // 4\r\n\tuint8\t\t\tUVAddressing[MAX_PASSES];           // 4\r\n\tfloat\t\t\tK[MAX_PASSES];\t\t\t\t\t\t// 16\r\n\r\n\tchar\t\t\tuv_slot[MAX_PASSES];\t\t\t\t// 4\r\n\tGXColor\t\t\tmatcol[4];\t\t\t\t\t\t\t// 16\r\n\r\n#ifdef __USE_MAT_DL__\r\n\tuint8*\t\t\tmp_display_list;\t\t\t\t\t// 4\r\n\tuint16\t\t\tm_display_list_size;\t\t\t\t// 2\r\n#endif\t\t// __USE_MAT_DL__\r\n\tuint8\t\t\tm_wibble_uv_update;\t\t\t\t\t// 1\r\n\tuint8\t\t\tm_num_wibble_vc_anims;\t\t\t\t// 1\r\n\tuint16\t\t\tpad;\r\n//\tuint8\t\t\tm_grassify;\r\n//\tuint8\t\t\tm_grass_layers;\r\n//\tfloat\t\t\tm_grass_height;\r\n\r\n\tsUVControl*\t\tm_pUVControl;\t\t\t\t\t\t// 4\r\n\r\n\tfloat\t\t\tm_wibble_uv_time;\t\t\t\t\t// 4\r\n\tsVCWibbleParams\t*mp_wibble_vc_params;\t\t\t\t// 4\r\n\tuint32\t\t\t*mp_wibble_vc_colors;\t\t\t\t// 4 (116) Max of eight banks of vertex color wibble infortation.\r\n};\r\n\r\n\r\nsMaterial * LoadMaterials( void *p_FH, Lst::HashTable< Nx::CTexture > *p_texture_table, int * p_num_materials );\r\nsMaterial * LoadMaterialsFromMemory( void **pp_mem, Lst::HashTable< Nx::CTexture > *p_texture_table, int * p_num_materials );\r\nvoid InitializeMaterial( sMaterial* p_material );\r\n\r\n//extern Lst::HashTable< sMaterial > *pMaterialTable;\r\nextern uint32 NumMaterials;\r\n\r\n} // namespace NxNgc\r\n\r\n#endif // __MATERIAL_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/mesh.cpp",
    "content": "#include <sys/file/filesys.h>\r\n#include <sys/timer.h>\r\n\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include \"import.h\"\r\n#include \"scene.h\"\r\n#include \"mesh.h\"\r\n#include \"nx_init.h\"\r\n#include \"sys/ngc/p_aram.h\"\r\n#include \"sys/ngc/p_dma.h\"\r\n#include <sk/modules/skate/skate.h>\r\n\r\n#include <dolphin.h>\r\n\r\nextern bool gCorrectColor;\r\n\r\nnamespace NxNgc\r\n{\r\n\r\nextern sint32 *pVertex;\r\nint TotalNumVertices;\r\n\r\nuint NumMeshes;\r\n\r\n\r\n// Globals used for cutscene head scaling.\r\nbool\t\t\ts_meshScalingEnabled\t= false;\r\nchar*\t\t\ts_pWeightIndices\t\t= NULL;\r\nfloat*\t\t\ts_pWeights\t\t\t\t= NULL;\r\nMth::Vector*\ts_pBonePositions\t\t= NULL;\r\nMth::Vector*\ts_pBoneScales\t\t\t= NULL;\r\nint\t\t\t\ts_currentVertIndex\t\t= 0;\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SetMeshScalingParameters( Nx::SMeshScalingParameters* pParams )\r\n{\r\n\tDbg_Assert( pParams );\r\n\r\n\ts_meshScalingEnabled\t= true;\r\n\ts_pWeights\t\t\t\t= pParams->pWeights;\r\n\ts_pWeightIndices\t\t= pParams->pWeightIndices;\r\n\ts_pBoneScales\t\t\t= pParams->pBoneScales;\r\n\ts_pBonePositions\t\t= pParams->pBonePositions;\r\n\ts_currentVertIndex\t\t= 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid DisableMeshScaling( void )\r\n{\r\n\ts_meshScalingEnabled\t= false;\r\n\ts_pWeights\t\t\t\t= NULL;\r\n\ts_pWeightIndices\t\t= NULL;\r\n\ts_pBoneScales\t\t\t= NULL;\r\n\ts_pBonePositions\t\t= NULL;\r\n\ts_currentVertIndex\t\t= 0;\r\n}\r\n\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline Mth::Vector get_bone_scale( int bone_index )\r\n{\r\n\tMth::Vector returnVec( 1.0f, 1.0f, 1.0f, 1.0f );\r\n\r\n\tif( bone_index >= 29 && bone_index <= 33 )\r\n\t{\r\n\t\t// this only works with the thps5 skeleton, whose\r\n\t\t// head bones are between 29 and 33...\r\n\t\t// (eventually, we can remove the subtract 29\r\n\t\t// once the exporter is massaging the data correctly)\r\n\t\treturnVec = s_pBoneScales[ bone_index - 29 ];\r\n\t\t\r\n\t\t// Y & Z are reversed...  odd!\r\n\t\tMth::Vector tempVec = returnVec;\r\n\t\treturnVec[Y] = tempVec[Z];\r\n\t\treturnVec[Z] = tempVec[Y];\r\n\t}\r\n\telse if( bone_index == -1 )\r\n\t{\r\n\t\t// implies that it's not weighted to a bone\r\n\t\treturn returnVec;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// implies that it's weighted to the wrong bone\r\n\t\treturn returnVec;\r\n\t}\r\n\treturn returnVec;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline Mth::Vector get_bone_pos( int bone_index )\r\n{\r\n\tMth::Vector returnVec( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\t\r\n\tif( bone_index >= 29 && bone_index <= 33 )\r\n\t{\r\n\t\t// this only works with the thps5 skeleton, whose\r\n\t\t// head bones are between 29 and 33...\r\n\t\t// (eventually, we can remove the subtract 29\r\n\t\t// once the exporter is massaging the data correctly)\r\n\t\treturnVec = s_pBonePositions[ bone_index - 29 ];\r\n\t}\r\n\telse if( bone_index == -1 )\r\n\t{\r\n\t\t// implies that it's not weighted to a bone\r\n\t\treturn returnVec;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// implies that it's weighted to the wrong bone\r\n\t\treturn returnVec;\r\n\t}\r\n\treturnVec[W] = 1.0f;\r\n\r\n\treturn returnVec;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid ApplyMeshScaling( NxNgc::sObjectHeader * p_object )\r\n{\r\n\tif( s_meshScalingEnabled )\r\n\t{\r\n\t\tfloat orig_pool[3*1500];\r\n\t\tint pool_size = 0;\r\n\t\r\n\t\t// First, build an array from the skin data.\r\n\t\r\n\t\t// Singles.\r\n\t\tuint32*\tp32 = (uint32 *)p_object->m_skin.p_data;\r\n\t\tfor ( uint32 lp = 0; lp < p_object->m_num_single_lists; lp++ ) {\r\n\t\t\tuint32\t\tpairs = *p32++;\r\n\t\t\t/*uint32\t\tmtx = **/p32++;\r\n\t\t\ts16*\t\tp_pn = (s16 *)p32;\r\n\t\r\n\t\t\tfor ( uint32 lp2 = 0; lp2 < pairs; lp2++ )\r\n\t\t\t{\r\n\t\t\t\torig_pool[(pool_size*3)+0] = (float)p_pn[(lp2*6)+0] / (float)(1 << 6);\r\n\t\t\t\torig_pool[(pool_size*3)+1] = (float)p_pn[(lp2*6)+1] / (float)(1 << 6);\r\n\t\t\t\torig_pool[(pool_size*3)+2] = (float)p_pn[(lp2*6)+2] / (float)(1 << 6);\r\n\t\t\t\tpool_size++;\r\n\t\t\t}\r\n\t\r\n\t\t\tp32 = (uint32 *)&p_pn[pairs*6];\r\n\t\t}\r\n\t\r\n\t\t// Doubles.\r\n\t\tfor ( uint32 lp = 0; lp < p_object->m_num_double_lists; lp++ ) {\r\n\t\t\tuint32\t\tpairs = *p32++;\r\n\t\t\t/*uint32\t\tmtx = **/p32++;\r\n\t\t\ts16*\t\tp_pn = (s16 *)p32;\r\n\t\t\ts16*\t\tp_weight = (s16 *)&p_pn[(6*pairs)];\r\n\t\r\n\t\t\tfor ( uint32 lp2 = 0; lp2 < pairs; lp2++ )\r\n\t\t\t{\r\n\t\t\t\torig_pool[(pool_size*3)+0] = (float)p_pn[(lp2*6)+0] / (float)(1 << 6);\r\n\t\t\t\torig_pool[(pool_size*3)+1] = (float)p_pn[(lp2*6)+1] / (float)(1 << 6);\r\n\t\t\t\torig_pool[(pool_size*3)+2] = (float)p_pn[(lp2*6)+2] / (float)(1 << 6);\r\n\t\t\t\tpool_size++;\r\n\t\t\t}\r\n\t\r\n\t\t\tp32 = (uint32 *)&p_weight[pairs*2];\r\n\t\t}\r\n\t\r\n\t\t// Now scale the verts.\r\n\t\tfloat * p_vertices = orig_pool;\r\n\t\tfor( int v = 0; v < pool_size; ++v, p_vertices += 3 )\r\n\t\t{\r\n\t\t\tfloat x = p_vertices[0];\r\n\t\t\tfloat y = p_vertices[1];\r\n\t\t\tfloat z = p_vertices[2];\r\n\r\n    \t\tMth::Vector origPos( x, y, z, 1.0f );\r\n\r\n\t\t\tMth::Vector bonePos0 = get_bone_pos( s_pWeightIndices[v * 3] );\r\n\t\t\tMth::Vector bonePos1 = get_bone_pos( s_pWeightIndices[v * 3 + 1] );\r\n\t\t\tMth::Vector bonePos2 = get_bone_pos( s_pWeightIndices[v * 3 + 2] );\r\n\r\n\t\t\t// Need to scale each vert relative to its parent bone.\r\n\t\t\tMth::Vector localPos0 = origPos - bonePos0;\r\n\t\t\tMth::Vector localPos1 = origPos - bonePos1;\r\n\t\t\tMth::Vector localPos2 = origPos - bonePos2;\r\n\r\n\t\t\tlocalPos0.Scale( get_bone_scale( s_pWeightIndices[v * 3] ) );\r\n\t\t\tlocalPos1.Scale( get_bone_scale( s_pWeightIndices[v * 3 + 1] ) );\r\n\t\t\tlocalPos2.Scale( get_bone_scale( s_pWeightIndices[v * 3 + 2] ) );\r\n\r\n\t\t\tlocalPos0 += bonePos0;\r\n\t\t\tlocalPos1 += bonePos1;\r\n\t\t\tlocalPos2 += bonePos2;\r\n\t\t\t\r\n\t\t\tMth::Vector scaledPos = ( localPos0 * s_pWeights[v * 3] ) +\r\n\t\t\t\t\t\t\t\t\t( localPos1 * s_pWeights[v * 3 + 1] ) +\r\n\t\t\t\t\t\t\t\t\t( localPos2 * s_pWeights[v * 3 + 2] );\r\n\r\n\t\t\tp_vertices[0] = scaledPos[X];\r\n\t\t\tp_vertices[1] = scaledPos[Y];\r\n\t\t\tp_vertices[2] = scaledPos[Z];\r\n\t\t} \t\r\n\r\n\t\t// Now copy back.\r\n\t\tpool_size = 0;\r\n\t\r\n\t\t// Singles.\r\n\t\tp32 = (uint32 *)p_object->m_skin.p_data;\r\n\t\tfor ( uint32 lp = 0; lp < p_object->m_num_single_lists; lp++ ) {\r\n\t\t\tuint32\t\tpairs = *p32++;\r\n\t\t\t/*uint32\t\tmtx = **/p32++;\r\n\t\t\ts16*\t\tp_pn = (s16 *)p32;\r\n\t\r\n\t\t\tfor ( uint32 lp2 = 0; lp2 < pairs; lp2++ )\r\n\t\t\t{\r\n\t\t\t\tp_pn[(lp2*6)+0] = (s16)(orig_pool[(pool_size*3)+0] * (float)(1 << 6 ));\r\n\t\t\t\tp_pn[(lp2*6)+1] = (s16)(orig_pool[(pool_size*3)+1] * (float)(1 << 6 ));\r\n\t\t\t\tp_pn[(lp2*6)+2] = (s16)(orig_pool[(pool_size*3)+2] * (float)(1 << 6 ));\r\n\t\t\t\tpool_size++;\r\n\t\t\t}\r\n\t\r\n\t\t\tp32 = (uint32 *)&p_pn[pairs*6];\r\n\t\t}\r\n\t\r\n\t\t// Doubles.\r\n\t\tfor ( uint32 lp = 0; lp < p_object->m_num_double_lists; lp++ ) {\r\n\t\t\tuint32\t\tpairs = *p32++;\r\n\t\t\t/*uint32\t\tmtx = **/p32++;\r\n\t\t\ts16*\t\tp_pn = (s16 *)p32;\r\n\t\t\ts16*\t\tp_weight = (s16 *)&p_pn[(6*pairs)];\r\n\t\r\n\t\t\tfor ( uint32 lp2 = 0; lp2 < pairs; lp2++ )\r\n\t\t\t{\r\n\t\t\t\tp_pn[(lp2*6)+0] = (s16)(orig_pool[(pool_size*3)+0] * (float)(1 << 6 ));\r\n\t\t\t\tp_pn[(lp2*6)+1] = (s16)(orig_pool[(pool_size*3)+1] * (float)(1 << 6 ));\r\n\t\t\t\tp_pn[(lp2*6)+2] = (s16)(orig_pool[(pool_size*3)+2] * (float)(1 << 6 ));\r\n\t\t\t\tpool_size++;\r\n\t\t\t}\r\n\t\r\n\t\t\tp32 = (uint32 *)&p_weight[pairs*2];\r\n\t\t}\r\n\t\r\n\t\t// Accumulation.\r\n\t\tfor ( uint32 lp = 0; lp < p_object->m_num_add_lists; lp++ ) {\r\n\t\t\tuint32\t\tsingles = *p32++;\r\n\t\t\t/*uint32\t\tmtx = **/p32++;\r\n\t\t\ts16*\t\tp_pn = (s16 *)p32;\r\n\t\t\ts16*\t\tp_weight = (s16 *)&p_pn[(6*singles)];\r\n\t\t\tuint16*\t\tp_index = (uint16 *)&p_weight[singles];\r\n\t\r\n\t\t\tfor ( uint32 lp2 = 0; lp2 < singles; lp2++ )\r\n\t\t\t{\r\n\t\t\t\tint index = p_index[lp2];\r\n\t\t\t\tp_pn[(lp2*6)+0] = (s16)(orig_pool[(index*3)+0] * (float)(1 << 6 ));\r\n\t\t\t\tp_pn[(lp2*6)+1] = (s16)(orig_pool[(index*3)+1] * (float)(1 << 6 ));\r\n\t\t\t\tp_pn[(lp2*6)+2] = (s16)(orig_pool[(index*3)+2] * (float)(1 << 6 ));\r\n\t\t\t}\r\n\t\r\n\t\t\tp32 = (uint32 *)&p_index[singles];\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nsMesh::sMesh( void )\r\n{\r\n\tm_flags\t\t\t\t= 0;\r\n\tSetActive( true );\r\n//\tmp_vc_wibble_data\t= NULL;\r\n//\r\n//\tm_offset_x = 0.0f;\r\n//\tm_offset_y = 0.0f;\r\n//\tm_offset_z = 0.0f;\r\n\r\n\tm_visibility_mask = 0xff;\r\n\r\n\tmp_dl = NULL;\r\n\r\n\t// It's the end of teh project - time for a hack!!!\r\n\tMdl::Skate * p_skate_mod =  Mdl::Skate::Instance();\r\n\tif (p_skate_mod->m_requested_level == CRCD(0x9f2bafb7,\"load_skateshop\"))\r\n\t{\r\n\t\tm_base_color.r = 64;\r\n\t\tm_base_color.g = 64;\r\n\t\tm_base_color.b = 64;\r\n\t\tm_base_color.a = 128;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_base_color.r = 128;\r\n\t\tm_base_color.g = 128;\r\n\t\tm_base_color.b = 128;\r\n\t\tm_base_color.a = 128;\r\n\t}\r\n}\r\n\r\n\r\n\r\nsMesh::~sMesh( void )\r\n{\r\n\tif( !( m_flags & MESH_FLAG_IS_INSTANCE ))\r\n\t{\r\n\t\tif( m_flags & MESH_FLAG_IS_CLONED )\r\n\t\t{\r\n//\t\t\tif ( m_localMeshIndex == 0 )\r\n//\t\t\t{\r\n//\t\t\t\tif( mp_posBuffer )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tdelete [] mp_posBuffer;\r\n//\t\t\t\t\tmp_posBuffer = NULL;\r\n//\t\t\t\t}\r\n//\t\t\t\tif( mp_normBuffer )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tdelete [] mp_normBuffer;\r\n//\t\t\t\t\tmp_normBuffer = NULL;\r\n//\t\t\t\t}\r\n//\t\t\t\tif( mp_colBuffer )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tdelete [] mp_colBuffer;\r\n//\t\t\t\t\tmp_colBuffer = NULL;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n//\t\t\tif ( mp_dl->mp_texture_dl )\r\n//\t\t\t{\r\n//\t\t\t\tdelete [] mp_dl->mp_texture_dl;\r\n//\t\t\t}\r\n\r\n//\t\t\tif( mp_display_list\t)\r\n//\t\t\t{\r\n//\t\t\t\tdelete mp_display_list;\r\n//\t\t\t\tmp_display_list = NULL;\r\n//\t\t\t}\r\n\r\n//\t\t\tif ( mp_dl && mp_dl->dl_owner )\r\n//\t\t\t{\r\n//\t\t\t\tif ( mp_dl->mp_material_dl )\r\n//\t\t\t\tdelete [] mp_dl->mp_material_dl;\r\n//\t\t\t}\r\n\r\n//\t\t\t// If we're the 0th mesh, we can delete the shared pools.\r\n//\t\t\tif ( m_localMeshIndex == 0 )\r\n//\t\t\t{\r\n//\t\t\t\tif( mp_posBuffer )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tdelete [] mp_posBuffer;\r\n//\t\t\t\t\tmp_posBuffer = NULL;\r\n//\t\t\t\t}\r\n//\t\t\t\tif( mp_normBuffer )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tdelete [] mp_normBuffer;\r\n//\t\t\t\t\tmp_normBuffer = NULL;\r\n//\t\t\t\t}\r\n//\t\t\t\tif( mp_uvBuffer )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tdelete [] mp_uvBuffer;\r\n//\t\t\t\t\tmp_uvBuffer = NULL;\r\n//\t\t\t\t}\r\n//\t\t\t\tif( mp_envBuffer )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tdelete [] mp_envBuffer;\r\n//\t\t\t\t\tmp_envBuffer = NULL;\r\n//\t\t\t\t}\r\n//\t\t\t\tif( mp_colBuffer )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tdelete [] mp_colBuffer;\r\n//\t\t\t\t\tmp_colBuffer = NULL;\r\n//\t\t\t\t}\r\n//\t\t\t\tif( mp_doubleWeight )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tdelete [] mp_doubleWeight;\r\n//\t\t\t\t\tmp_doubleWeight = NULL;\r\n//\t\t\t\t}\r\n//\t\t\t\tif( mp_vc_wibble_data )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tdelete mp_vc_wibble_data;\r\n//\t\t\t\t\tmp_vc_wibble_data = NULL;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::wibble_normals( void )\r\n{\r\n//\t// Angle in the range [-PI/16, PI/16], period is 1 second.\r\n//\tfloat time = (float)Tmr::GetTime() * 0.0005f;\r\n//\r\n//\tif( m_flags & MESH_FLAG_WATER_HACK )\r\n//\t{\r\n//\t\tBYTE\t\t*p_byte;\r\n//\t\tfloat\t\t*p_normal;\r\n//\t\tfloat\t\t*p_pos;\r\n//\t\tmp_vertex_buffer2->Lock( 0, 0, &p_byte, 0 );\r\n//\t\tp_pos\t\t= (float*)( p_byte + 0 );\r\n//\t\tp_normal\t= (float*)( p_byte + m_normal_offset );\r\n//\r\n//\t\tfor( uint32 i = 0; i < m_num_vertices; ++i )\r\n//\t\t{\r\n//\t\t\tfloat x\t\t\t\t= p_pos[0] - m_sphere[0];\r\n//\t\t\tfloat z\t\t\t\t= p_pos[2] - m_sphere[2];\r\n//\t\t\t\r\n//\t\t\tfloat time_offset_x\t= time + (( x / m_sphere_radius ) * 0.5f );\r\n//\t\t\tfloat time_offset_z\t= time + (( z / m_sphere_radius ) * 0.5f );\r\n//\r\n//\t\t\tfloat angle_x\t\t= ( Mth::PI * ( 1.0f / 64.0f ) * (float)fabs( sinf( time_offset_x * Mth::PI ))) - ( Mth::PI * ( 1.0f / 128.0f ));\r\n//\t\t\tfloat angle_z\t\t= ( Mth::PI * ( 1.0f / 64.0f ) * (float)fabs( sinf( time_offset_z * Mth::PI ))) - ( Mth::PI * ( 1.0f / 129.0f ));\r\n//\t\t\t\r\n//\t\t\tMth::Vector\tn( sinf( angle_x ), cosf(( angle_x + angle_z ) * 0.5f ), sinf( angle_z ));\r\n//\t\t\tn.Normalize();\r\n//\t\t\t\r\n//\t\t\tp_normal[0]\t\t\t= n[X];\r\n//\t\t\tp_normal[1]\t\t\t= n[Y];\r\n//\t\t\tp_normal[2]\t\t\t= n[Z];\r\n//\t\t\t\r\n//\t\t\tp_pos\t\t\t\t= (float*)((BYTE*)p_pos + m_vertex_stride );\r\n//\t\t\tp_normal\t\t\t= (float*)((BYTE*)p_normal + m_vertex_stride );\r\n//\t\t}\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::wibble_vc( void )\r\n{\r\n//\tif( mp_vc_wibble_data )\r\n//\t{\r\n//\t\t// Grab byte pointer to current 'write' vertex buffer.\r\n////\t\tGXColor\t\t*p_byte = (char *)mp_colBuffer;\r\n//\t\tuint32\t\t*p_color = mp_colBuffer;\r\n////\t\tp_color = (GXColor*)( p_byte + m_diffuse_offset );\r\n//\r\n//\t\t// Scan through each vertex, setting the new color.\r\n//\t\tfor( uint32 i = 0; i < m_num_vertex; ++i )\r\n//\t\t{\r\n//\t\t\t// An index of zero means no update for this vert.\r\n//\t\t\tuint32 index\t= mp_vc_wibble_data[i];\r\n//\t\t\tif( ( index > 0 ) && ( m_flags & MESH_FLAG_VERTEX_COLOR_WIBBLE ) && mp_material->mp_wibble_vc_colors )\r\n//\t\t\t{\r\n//\t\t\t\t*p_color\t= mp_material->mp_wibble_vc_colors[index - 1];\r\n//\t\t\t}\r\n//\t\t\tp_color++;\r\n//\t\t}\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::Submit( void )\r\n{\r\n//\twibble_vc();\r\n////\twibble_normals();\r\n//\r\n//\tif ( mp_display_list )\r\n//\t{\r\n//\t\tGXCallDisplayList ( mp_display_list, m_display_list_size ); \r\n//\t}\r\n////\t// Horribly inefficient, but will have to do for now until we get bucket rendering going.\r\n////\tif( mp_material )\r\n////\t{\r\n////\t\tmp_material->Submit();\r\n////\t}\r\n////\t\r\n////\t// Set pixel and vertex shader.\r\n////\tD3DDevice_SetPixelShader( m_pixel_shader );\r\n////\tD3DDevice_SetVertexShader( m_fvf_flags );\r\n////\r\n////\t// Set the stream source.\r\n////\tD3DDevice_SetStreamSource( 0, mp_vertex_buffer, m_vertex_stride );\r\n////\r\n////\t// Submit.\r\n////\tD3DDevice_DrawIndexedVertices( m_primitive_type, m_num_indices, mp_index_buffer );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsMesh *sMesh::Clone( bool instance )\r\n{\r\n\tsMesh *p_clone = new sMesh();\r\n\r\n\t// Copy over basic details.\r\n\tmemcpy( p_clone, this, sizeof( sMesh ));\r\n\tp_clone->m_flags &= ~(MESH_FLAG_CLONED_POS|MESH_FLAG_CLONED_COL);\r\n\r\n\tif( instance )\r\n\t{\r\n\t\tp_clone->m_flags |= MESH_FLAG_IS_INSTANCE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_clone->m_flags |= MESH_FLAG_IS_CLONED;\r\n\r\n\t\t// Clone the display list.\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\t\tp_clone->mp_dl = (NxNgc::sDLHeader*)new char[sizeof(NxNgc::sDLHeader)+mp_dl->m_size];\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\t\tmemcpy( p_clone->mp_dl, mp_dl, sizeof(NxNgc::sDLHeader)+mp_dl->m_size );\r\n\t\tp_clone->m_flags |= NxNgc::sMesh::MESH_FLAG_CLONED_DL;\r\n\r\n\r\n\r\n//\t\tp_clone->m_flags |= MESH_FLAG_IS_INSTANCE;\r\n\r\n//\t\tif ( m_localMeshIndex == 0 )\r\n//\t\t{\r\n//\t\t\tif ( mp_posBuffer )\r\n//\t\t\t{\r\n//#ifdef SHORT_VERT\r\n//\t\t\t\tp_clone->mp_posBuffer = new s16[3*m_num_vertex];\r\n//\t\t\t\tmemcpy( p_clone->mp_posBuffer, mp_posBuffer, 3 * m_num_vertex * sizeof( s16 ) );\r\n//\t\t\t\tDCFlushRange( p_clone->mp_posBuffer, 3 * m_num_vertex * sizeof( s16 ) );\r\n//#else\r\n//\t\t\t\tp_clone->mp_posBuffer = new float[3*m_num_vertex];\r\n//\t\t\t\tmemcpy( p_clone->mp_posBuffer, mp_posBuffer, 3 * m_num_vertex * sizeof( float ) );\r\n//\t\t\t\tDCFlushRange( p_clone->mp_posBuffer, 3 * m_num_vertex * sizeof( float ) );\r\n//#endif\t\t// SHORT_VERT \r\n//\t\t\t}\r\n//\t\t\tif ( mp_normBuffer )\r\n//\t\t\t{\r\n//\t\t\t\tp_clone->mp_normBuffer = new s16[3*m_num_vertex];\r\n//\t\t\t\tmemcpy( p_clone->mp_normBuffer, mp_normBuffer, 3 * m_num_vertex * sizeof( s16 ) );\r\n//\t\t\t\tDCFlushRange( p_clone->mp_normBuffer, 3 * m_num_vertex * sizeof( s16 ) );\r\n//\t\t\t}\r\n//\r\n//\t\t\tif ( mp_colBuffer )\r\n//\t\t\t{\r\n//\t\t\t\tp_clone->mp_colBuffer = new uint32[m_num_vertex];\r\n//\t\t\t\tmemcpy( p_clone->mp_colBuffer, mp_colBuffer, m_num_vertex * sizeof( uint32 ) );\r\n//\t\t\t\tDCFlushRange( p_clone->mp_colBuffer, m_num_vertex * sizeof( uint32 ) );\r\n//\t\t\t}\r\n//\t\t}\r\n\t}\r\n\treturn p_clone;\r\n\r\n//\tDbg_MsgAssert( false, ( \"Not yet implmented!!!!!!!!\" ) );\r\n//\treturn NULL;\r\n}\r\n\r\n\r\n\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void sMesh::Initialize( int num_vertices,\r\n//\t\t\t\t\t\tfloat* p_positions,\r\n//#ifdef SHORT_VERT\r\n//\t\t\t\t\t\ts16* p_positions16,\r\n//\t\t\t\t\t\tint shift,\r\n//\t\t\t\t\t\tfloat off_x,\r\n//\t\t\t\t\t\tfloat off_y,\r\n//\t\t\t\t\t\tfloat off_z,\r\n//#endif\t\t// SHORT_VERT\r\n//\t\t\t\t\t\ts16* p_normals,\r\n//\t\t\t\t\t\tfloat* p_tex_coords,\r\n//\t\t\t\t\t\tfloat* p_env_buffer,\r\n//\t\t\t\t\t\tint num_tc_sets,\r\n//\t\t\t\t\t\tuint32* p_colors,\r\n//\t\t\t\t\t\tint num_indices,\r\n//\t\t\t\t\t\tuint16* p_pos_indices,\r\n//\t\t\t\t\t\tuint16* p_col_indices,\r\n//\t\t\t\t\t\tuint16* p_uv_indices,\r\n//\t\t\t\t\t\tunsigned long material_checksum,\r\n//\t\t\t\t\t\tvoid *p_scene,\r\n//\t\t\t\t\t\tint num_double,\r\n//\t\t\t\t\t\tuint32 * p_double,\r\n//\t\t\t\t\t\tint num_single,\r\n//\t\t\t\t\t\tint localMeshIndex,\r\n//\t\t\t\t\t\tGXPrimitive primitive_type,\r\n//\t\t\t\t\t\tint bone_idx,\r\n//\t\t\t\t\t\tchar *p_vc_wibble_anims )\r\n//\r\n//{\r\n//\tm_num_indices\t\t= 0;\r\n//\tm_vertex_stride\t\t= 0;\r\n//\tm_num_vertex\t\t= num_vertices;\r\n//\r\n//\tm_bone_idx\t\t\t= bone_idx;\r\n//\r\n////\tm_primitive_type\t= D3DPT_TRIANGLESTRIP;\r\n////\tm_fvf_flags\t\t\t= 0;\r\n////\tm_pixel_shader\t\t= 0;\r\n//\t\r\n////\tmp_posBuffer = NULL;\t//p_positions;\r\n////\tmp_normBuffer = p_normals;\r\n////\tmp_uvBuffer = NULL;\t//p_tex_coords;\r\n////\tmp_colBuffer = NULL;\t//p_colors;\r\n////\tmp_index_buffer = NULL;\t//p_indices;\r\n//\r\n//\tmp_normBuffer = p_normals;\r\n//\tmp_uvBuffer = p_tex_coords;\r\n//\tmp_colBuffer = p_colors;\r\n//\tm_num_uv_sets = num_tc_sets;\r\n//\r\n//\tm_numDouble = num_double;\r\n//\tm_numSingle = num_single;\r\n//\tmp_doubleWeight = p_double;\r\n//\r\n//\tm_localMeshIndex = localMeshIndex;\r\n//\r\n//\t// First thing to do is grab the material pointer for this mesh.\r\n//\tmp_material\t\t\t= ((sScene*)p_scene )->GetMaterial( material_checksum );\r\n////\tif( mp_material == NULL )\r\n////\t{\r\n////\t\texit( 0 );\r\n////\r\n////\t\t// Try with the dummy material for now.\r\n////\t\t// mp_material = GetMaterial( 0 );\r\n////\t}\r\n//\t\r\n////\tif( num_indices == 0 )\r\n////\t{\r\n////\t\treturn;\r\n////\t}\r\n////\t\r\n////\t// Figure the min and max indices for this mesh.\r\n////\tuint16 min_index\t= p_indices[0];\r\n////\tuint16 max_index\t= p_indices[0];\r\n////\tfor( int i = 1; i < num_indices; ++i )\r\n////\t{\r\n////\t\tif( p_indices[i] > max_index )\r\n////\t\t{\r\n////\t\t\tmax_index = p_indices[i];\r\n////\t\t}\r\n////\t\telse if( p_indices[i] < min_index )\r\n////\t\t{\r\n////\t\t\tmin_index = p_indices[i];\r\n////\t\t}\r\n////\t}\r\n//\t\r\n//\t// See if any vertex color alpha valus are less than any of the texture's cutoff values.\r\n//\t// If so, make sure that the texture is specified as having holes.\r\n//\tfor ( int lp = 0; lp < num_vertices; lp++ )\r\n//\t{\r\n//\t\tif ( ( p_colors[lp] & 255 ) < mp_material->AlphaCutoff )\r\n//\t\t{\r\n//\t\t\tfor ( int pass = 0; pass < mp_material->Passes; pass++ )\r\n//\t\t\t{\r\n////\t\t\t\tif ( mp_material->pTex[pass] ) mp_material->pTex[pass]->HasHoles = 1;\r\n//\t\t\t\tif ( mp_material->pTex[pass] )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif ( !mp_material->pTex[pass]->HasHoles )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tmp_material->pTex[pass]->HasHoles = 1;\r\n//\t\t\t\t\t\tOSReport( \"Material found that was incorrectly flagged.\\n\" );\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\tbreak;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t// See if any of the material layers require environment mapping.\r\n//\tmp_envBuffer = NULL;\r\n//\tfor ( int pass = 0; pass < mp_material->Passes; pass++ )\r\n//\t{\r\n//\t\tif ( mp_material->Flags[pass] & MATFLAG_ENVIRONMENT )\r\n//\t\t{\r\n//\t\t\tif ( p_env_buffer )\r\n//\t\t\t{\r\n//\t\t\t\t// Already allocated one, so just assign it.\r\n//\t\t\t\tmp_envBuffer = p_env_buffer;\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\t// Has environment mapping, so allocate an environment map uv buffer.\r\n//\t\t\t\tmp_envBuffer = new float[2*num_vertices];\r\n//\t\t\t}\r\n//\t\t\t// Break so that we only allocate once.\r\n//\t\t\tbreak;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t// Set the bounding box.\r\n//\tif ( p_positions )\r\n//\t{\r\n//\t\t// Non-skinned.\r\n//\t\tfor( int v = 0; v < num_vertices; ++v )\r\n//\t\t{\r\n//\t\t\t// Do bounding box setting.\r\n//\t\t\tMth::Vector p( p_positions[(v*3)+0], p_positions[(v*3)+1], p_positions[(v*3)+2] );\r\n//\t\t\tm_bbox.AddPoint( p );\r\n//\t\t}\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\t// Skinned.\r\n//\t\tuint32*\tp32 = p_double;\r\n//\t\tfor ( int lp = 0; lp < num_double; lp++ ) {\r\n//\t\t\tuint32\t\tpairs = *p32++;\r\n//\t\t\t/*uint32\t\tmtx = **/p32++;\r\n//\t\t\tfloat*\t\tp_pn = (float *)p32;\r\n//\t\t\tfloat*\t\t\tp_weight = (float *)&p_pn[(6*pairs)];\r\n//\r\n//\t\t\tfor( uint v = 0; v < pairs; ++v )\r\n//\t\t\t{\r\n//\t\t\t\t// Do bounding box setting.\r\n//\t\t\t\tMth::Vector p( p_pn[(v*6)+0], p_pn[(v*6)+1], p_pn[(v*6)+2] );\r\n//\t\t\t\tm_bbox.AddPoint( p );\r\n//\t\t\t}\r\n//\r\n//\t\t\tp32 = (uint32 *)&p_weight[pairs*2];\r\n//\t\t}\r\n//\t}\r\n//\tfloat x = ( m_bbox.GetMax().GetX() + m_bbox.GetMin().GetX() ) / 2;\r\n//\tfloat y = ( m_bbox.GetMax().GetY() + m_bbox.GetMin().GetY() ) / 2;\r\n//\tfloat z = ( m_bbox.GetMax().GetZ() + m_bbox.GetMin().GetZ() ) / 2;\r\n//\tfloat r = ( m_bbox.GetMax().GetX() - m_bbox.GetMin().GetX() ) * ( m_bbox.GetMax().GetX() - m_bbox.GetMin().GetX() );\r\n//\tr += ( m_bbox.GetMax().GetY() - m_bbox.GetMin().GetY() ) * ( m_bbox.GetMax().GetY() - m_bbox.GetMin().GetY() );\r\n//\tr += ( m_bbox.GetMax().GetZ() - m_bbox.GetMin().GetZ() ) * ( m_bbox.GetMax().GetZ() - m_bbox.GetMin().GetZ() );\r\n//\tr = sqrtf( r );\r\n//\tr = r / 2.0f;\r\n//\tm_sphere[0] = x;\r\n//\tm_sphere[1] = y;\r\n//\tm_sphere[2] = z;\r\n//\tm_sphere[3] = r;\r\n//\r\n//\t// Set the position buffer & offset.\r\n//#ifdef SHORT_VERT\r\n//\tmp_posBuffer = p_positions16;\r\n//#else\r\n//\tmp_posBuffer = p_positions;\r\n//#endif\t\t// SHORT_VERT\r\n//\r\n//\tif ( p_positions )\r\n//\t{\r\n//#ifdef SHORT_VERT\r\n//\t\t// Non-skinned.\r\n//\t\tswitch ( shift )\r\n//\t\t{\r\n//\t\t\tcase 1:\r\n//\t\t\t\tm_vertex_format = GX_VTXFMT2;\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase 2:\r\n//\t\t\t\tm_vertex_format = GX_VTXFMT3;\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase 3:\r\n//\t\t\t\tm_vertex_format = GX_VTXFMT4;\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase 4:\r\n//\t\t\t\tm_vertex_format = GX_VTXFMT5;\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase 5:\r\n//\t\t\t\tm_vertex_format = GX_VTXFMT6;\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase 6:\r\n//\t\t\t\tm_vertex_format = GX_VTXFMT7;\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase 0:\r\n//\t\t\tdefault:\r\n//\t\t\t\tm_vertex_format = GX_VTXFMT1;\r\n//\t\t\t\tbreak;\r\n//\t\t}\r\n//#else\r\n//\t\tm_vertex_format = GX_VTXFMT6;\r\n//#endif\t\t// SHORT_VERT\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\t// Skinned.\r\n//\t\tm_vertex_format = GX_VTXFMT7;\r\n//\t}\r\n//\r\n//#ifdef SHORT_VERT\r\n//\tm_offset_x = off_x;\r\n//\tm_offset_y = off_y;\r\n//\tm_offset_z = off_z;\r\n//#endif\t\t// SHORT_VERT\r\n//\r\n////\tif( max_index >= num_vertices )\r\n////\t{\r\n////\t\t// Error!\r\n////\t\texit( 0 );\r\n////\t}\r\n//\t\r\n//\t// Now figure the total number of vertices required for this mesh, to span the min->max indices.\r\n////\tuint16 vertices_for_this_mesh = max_index - min_index + 1;\r\n//\r\n//\t// Create the index buffer (should be 16byte aligned for best performance).\r\n////\tmp_index_buffer\t= new uint16[num_indices];\r\n//\r\n//\t// Set our count of the number of indices.\r\n//\tm_num_indices = num_indices - 2;\t\t// Only used for skinned - subtract count & trailing 0.\r\n//\r\n//\t// Copy in index data, normaling the indices for this vertex buffer (i.e. so the lowest index will reference\r\n//\t// vertex 0 in the buffer built specifically for this mesh).\r\n////\tfor( int i = 0; i < num_indices; ++i )\r\n////\t{\r\n////\t\tmp_index_buffer[i] = p_indices[i];\t// - min_index;\r\n////\t}\r\n//\r\n//\t// Use the material flags to figure the vertex format.\r\n//\tint vertex_size\t\t\t= 3 * sizeof( float );\r\n//\r\n//\t// Include weights (for weighted animation) if present.\r\n////\tif( p_weights )\r\n////\t{\r\n////\t\tDbg_Assert( p_matrix_indices );\r\n////\t\tvertex_size\t+= sizeof( float ) * 4;\r\n////\t}\r\n//\r\n//\t// Include indices (for weighted animation) if present.\r\n////\tif( p_matrix_indices )\r\n////\t{\r\n////\t\tDbg_Assert( p_weights );\r\n////\t\tvertex_size\t+= sizeof( uint16 ) * 4;\r\n////\t}\r\n//\t\r\n//\t// Texture coordinates.\r\n//\tuint32\ttex_coord_pass\t= 0;\r\n////\tbool\tenv_mapped\t\t= false;\r\n//\tif( p_tex_coords )\r\n//\t{\r\n//\t\tfor( uint32 pass = 0; pass < mp_material->Passes; ++pass )\r\n//\t\t{\r\n////\t\t\tif( mp_material->Flags[pass] & MATFLAG_ENVIRONMENT )\r\n////\t\t\t{\r\n////\t\t\t\tenv_mapped\t\t= true;\r\n////\t\t\t}\r\n//\r\n//\t\t\t// Only need UV's for this stage if it is *not* environment mapped.\r\n//\t\t\tif(( mp_material->pTex[pass] ) /*&& ( !( mp_material->Flags[pass] & MATFLAG_ENVIRONMENT ))*/)\r\n//\t\t\t{\r\n//\t\t\t\t// Will need uv for this pass and all before it.\r\n//\t\t\t\ttex_coord_pass\t= pass + 1; \r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tfor( uint32 pass = 0; pass < mp_material->Passes; ++pass )\r\n//\t\t{\r\n////\t\t\tif( mp_material->Flags[pass] & MATFLAG_ENVIRONMENT )\r\n////\t\t\t{\r\n////\t\t\t\tenv_mapped\t\t= true;\r\n////\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tif( tex_coord_pass > 0 )\r\n//\t{\r\n//\t\tvertex_size += 2 * sizeof( float ) * tex_coord_pass;\r\n//\t}\r\n//\r\n//\t// Assume no normals for now.\r\n//\tif( 0 )\r\n//\t{\r\n//\t\t// We want vertex colors in this mesh,\r\n//\t\tif( 0 )\r\n//\t\t{\r\n//\t\t\t// The raw vertex data does not contain vertex colors.\r\n//\t\t\texit( 0 );\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\t// The raw vertex data does contain vertex colors.\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tbool use_colors = false;\r\n//\tif( p_colors )\r\n//\t{\r\n//\t\t// We want vertex colors in this mesh,\r\n//\t\tif( 0 )\r\n//\t\t{\r\n//\t\t\t// The raw vertex data does not contain vertex colors.\r\n//\t\t\texit( 0 );\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\t// The raw vertex data does contain vertex colors.\r\n//\t\t\tvertex_size\t+= sizeof( uint32 );\r\n//\t\t\tuse_colors\t= true;\r\n//\t\t}\r\n//\t}\r\n//\t\r\n//\t// Create the vertex color wibble array if data is present.\r\n//\tif( p_vc_wibble_anims )\r\n//\t{\r\n//\t\tmp_vc_wibble_data = p_vc_wibble_anims;\r\n//\t}\r\n//\r\n////\tif ( p_double )\r\n////\t{\r\n////\t\tmp_doubleWeight = 1;\r\n////\t}\r\n////\telse\r\n////\t{\r\n////\t\tmp_doubleWeight = 0;\r\n////\t}\r\n//\r\n//\tm_primitive_type = primitive_type;\r\n//\r\n//\tBuild( num_indices, p_pos_indices, p_col_indices, p_uv_indices );\r\n//\r\n//\t// Find the index list in the display list data.\r\n//\tmp_index_buffer = NULL;\r\n//\t{\r\n//\t\tunsigned char * p8;\r\n//\t\tunsigned char search[3];\r\n//\r\n//\t\tp8 = (unsigned char *)mp_display_list;\r\n//\r\n//\t\tsearch[0] = *p8++;\r\n//\t\tsearch[1] = *p8++;\r\n//\t\tfor ( int ss = 2; ss < m_display_list_size; ss++ ) {\r\n//\t\t\tsearch[2] = *p8++;\r\n//\r\n//\t\t\tif (\t( ( search[0] & 0xf8 ) == m_primitive_type ) &&\r\n//\t\t\t\t\t( ( ( search[1] << 8 ) | search[2] ) == (int)*p_pos_indices ) ) {\r\n//\t\t\t\t// Found it!!!\r\n//\t\t\t\tif ( num_double )\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// Skinned mesh.\r\n//\t\t\t\t\tmp_index_buffer = (unsigned short *)p8;\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// Non-skinned mesh.\r\n//\t\t\t\t\tmp_index_buffer = (unsigned short *)&p8[-2];\r\n//\t\t\t\t}\r\n//\t\t\t\tbreak;\r\n//\t\t\t}\r\n//\t\t\tsearch[0] = search[1];\r\n//\t\t\tsearch[1] = search[2];\r\n//\t\t}\r\n//\t}\r\n//\r\n////\tif ( p_double )\r\n////\t{\r\n////\t\tdouble_bytes = dbytes;\r\n////\t\tsingle_bytes = sbytes;\r\n////\t\t\r\n////\t\tif ( m_localMeshIndex == 0 )\r\n////\t\t{\r\n////\t\t\tNsARAM::HEAPTYPE heap = NsARAM::BOTTOMUP;\r\n////\r\n////\t\t\tif ( Mem::Manager::sHandle().GetContextAllocator() == Mem::Manager::sHandle().SkaterGeomHeap(0) )\r\n////\t\t\t{\r\n////\t\t\t\theap = NsARAM::SKATER0;\r\n////\t\t\t}\r\n////\t\t\tif ( Mem::Manager::sHandle().GetContextAllocator() == Mem::Manager::sHandle().SkaterGeomHeap(1) )\r\n////\t\t\t{\r\n////\t\t\t\theap = NsARAM::SKATER1;\r\n////\t\t\t}\r\n////\r\n////\t\t\t//OSReport( \"Allocating %d ARAM bytes %s\\n\", dbytes + sbytes, Mem::Manager::sHandle().GetContextName() );\r\n////\t\t\tmp_doubleWeight = NsARAM::alloc( (dbytes + sbytes) * 4, heap );\r\n////\t\t\tNsDMA::toARAM( mp_doubleWeight, p_double, ( dbytes + sbytes ) * 4 );\r\n////\t\t}\r\n////\t}\r\n////\telse\r\n////\t{\r\n////\t\tmp_doubleWeight = 0;\r\n////\t\tdouble_bytes = dbytes;\r\n////\t\tsingle_bytes = sbytes;\r\n////\t}\r\n//\r\n//\tdelete p_pos_indices;\r\n//}\r\n\r\n//void sMesh::Build( int num_indices, uint16* p_pos_indices, uint16* p_col_indices, uint16* p_uv_indices, bool rebuild )\r\n//{\r\n//\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n//\tEngineGlobals.gpuBusy = true;\r\n//\t// Turn the index list into a display list.\r\n//\tmp_display_list = NULL;\r\n//#define DL_BUILD_SIZE (32*1024)\r\n//\tuint8 * p_build_dl = new (Mem::Manager::sHandle().TopDownHeap()) uint8[DL_BUILD_SIZE];\r\n//\tDCFlushRange ( p_build_dl, DL_BUILD_SIZE );\r\n//\r\n//\tGXBeginDisplayList ( p_build_dl, DL_BUILD_SIZE );\r\n//\tGXResetWriteGatherPipe();\r\n//\r\n//\tGXClearVtxDesc();\r\n//\tGXSetVtxDesc( GX_VA_POS, GX_INDEX16 );\r\n//\tm_vertex_stride = 1;\r\n//\tif ( mp_normBuffer || mp_doubleWeight )\r\n//\t{\r\n//\t\tGXSetVtxDesc( GX_VA_NRM, GX_INDEX16 );\r\n//\t\tm_vertex_stride++;\r\n//\t}\r\n//\tif ( mp_colBuffer )\r\n//\t{\r\n//\t\tGXSetVtxDesc( GX_VA_CLR0, GX_INDEX16 );\r\n//\t\tm_vertex_stride++;\r\n//\t\tif ( !mp_doubleWeight && gCorrectColor )\r\n//\t\t{\r\n//\t\t\t// Before we go wading in and allow a 2nd color index list, see if it's necessary.\r\n//\t\t\t// Check every poly in the mesh and see if the color difference is greater than a threshold.\r\n//\t\t\tbool needs_fixing = false;\r\n//\t\t\tuint32 color0;\r\n//\t\t\tuint32 color1 = mp_colBuffer[p_col_indices[p_pos_indices[0]]];\r\n//\t\t\tuint32 color2 = mp_colBuffer[p_col_indices[p_pos_indices[1]]];\r\n//\t\t\tfor ( int lp = 2; lp < num_indices; lp++ )\r\n//\t\t\t{\r\n//\t\t\t\t// Grab new color to form triangle.\r\n//\t\t\t\tcolor0 = color1;\r\n//\t\t\t\tcolor1 = color2;\r\n//\t\t\t\tcolor2 = mp_colBuffer[p_col_indices[p_pos_indices[lp]]];\r\n//\r\n//\t\t\t\tint diff0_a = abs( ( ( color1 >> 24 ) & 255 ) - ( ( color0 >> 24 ) & 255 ) );\r\n//\t\t\t\tint diff1_a = abs( ( ( color2 >> 24 ) & 255 ) - ( ( color1 >> 24 ) & 255 ) );\r\n//\t\t\t\tint diff2_a = abs( ( ( color0 >> 24 ) & 255 ) - ( ( color2 >> 24 ) & 255 ) );\r\n//\t\t\t\tint diff0_r = abs( ( ( color1 >> 16 ) & 255 ) - ( ( color0 >> 16 ) & 255 ) );\r\n//\t\t\t\tint diff1_r = abs( ( ( color2 >> 16 ) & 255 ) - ( ( color1 >> 16 ) & 255 ) );\r\n//\t\t\t\tint diff2_r = abs( ( ( color0 >> 16 ) & 255 ) - ( ( color2 >> 16 ) & 255 ) );\r\n//\t\t\t\tint diff0_g = abs( ( ( color1 >>  8 ) & 255 ) - ( ( color0 >>  8 ) & 255 ) );\r\n//\t\t\t\tint diff1_g = abs( ( ( color2 >>  8 ) & 255 ) - ( ( color1 >>  8 ) & 255 ) );\r\n//\t\t\t\tint diff2_g = abs( ( ( color0 >>  8 ) & 255 ) - ( ( color2 >>  8 ) & 255 ) );\r\n//\t\t\t\tint diff0_b = abs( ( ( color1 >>  0 ) & 255 ) - ( ( color0 >>  0 ) & 255 ) );\r\n//\t\t\t\tint diff1_b = abs( ( ( color2 >>  0 ) & 255 ) - ( ( color1 >>  0 ) & 255 ) );\r\n//\t\t\t\tint diff2_b = abs( ( ( color0 >>  0 ) & 255 ) - ( ( color2 >>  0 ) & 255 ) );\r\n//\r\n//\t\t\t\tint wdiff = diff0_a;\r\n//\t\t\t\tif ( diff1_a > wdiff ) wdiff = diff1_a;\r\n//\t\t\t\tif ( diff2_a > wdiff ) wdiff = diff2_a;\r\n//\t\t\t\tif ( diff0_r > wdiff ) wdiff = diff0_r;\r\n//\t\t\t\tif ( diff1_r > wdiff ) wdiff = diff1_r;\r\n//\t\t\t\tif ( diff2_r > wdiff ) wdiff = diff2_r;\r\n//\t\t\t\tif ( diff0_g > wdiff ) wdiff = diff0_g;\r\n//\t\t\t\tif ( diff1_g > wdiff ) wdiff = diff1_g;\r\n//\t\t\t\tif ( diff2_g > wdiff ) wdiff = diff2_g;\r\n//\t\t\t\tif ( diff0_b > wdiff ) wdiff = diff0_b;\r\n//\t\t\t\tif ( diff1_b > wdiff ) wdiff = diff1_b;\r\n//\t\t\t\tif ( diff2_b > wdiff ) wdiff = diff2_b;\r\n//\r\n//\t\t\t\tif ( wdiff > 8 ) needs_fixing = true;\r\n//\t\t\t}\r\n//\r\n//\t\t\tif ( needs_fixing )\r\n//\t\t\t{\r\n//\t\t\t\tm_flags |= MESH_FLAG_DOUBLE_COLOR_IDX;\r\n//\t\t\t\tGXSetVtxDesc( GX_VA_CLR1, GX_INDEX16 );\r\n//\t\t\t\tm_vertex_stride++;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tint coord = 0;\r\n//\tfor ( uint layer = 0; layer < mp_material->Passes; layer++ )\r\n//\t{\r\n//\t\tGXSetVtxDesc( (GXAttr)(((int)GX_VA_TEX0)+coord), GX_INDEX16 );\r\n//\t\tm_vertex_stride++;\r\n//\t\tcoord++;\r\n//\t}\r\n//\r\n//\tif ( rebuild )\r\n//\t{\r\n//\t\t// Send coordinates.\r\n//\t\tGXBegin( (GXPrimitive)m_primitive_type, (GXVtxFmt)m_vertex_format, num_indices ); \r\n//\t\tfor ( int lp = 0; lp < num_indices; lp++ )\r\n//\t\t{\r\n//\t\t\t// Send coordinates.\r\n//\t\t\tint pindex = p_pos_indices[lp];\r\n//\t\t\tint cindex = p_col_indices[pindex];\r\n//\t\t\tGXPosition1x16(pindex);\r\n//\t\t\tif ( mp_normBuffer || mp_doubleWeight ) GXNormal1x16(pindex);\r\n//\t\t\tif ( mp_colBuffer ) GXColor1x16(cindex);\r\n//\t\t\tif ( m_flags & MESH_FLAG_DOUBLE_COLOR_IDX ) GXColor1x16(cindex);\r\n//\t\t\tfor ( uint layer = 0; layer < mp_material->Passes; layer++ )\r\n//\t\t\t{\r\n//\t\t\t\tint uindex = pindex;\r\n//\t\t\t\tif ( p_uv_indices ) uindex = p_uv_indices[pindex+(layer*m_num_vertex)];\r\n//\t\t\t\tGXTexCoord1x16(uindex);\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\tGXEnd();\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\t// Parse index list & turn into gxbegin/end pairs.\r\n//\t\tint v = 0;\r\n//\t\twhile ( p_pos_indices[v] )\r\n//\t\t{\r\n//\t\t\tuint16 num = p_pos_indices[v];\r\n//\t\t\tv++;\r\n//\r\n//\t\t\tGXBegin( (GXPrimitive)m_primitive_type, (GXVtxFmt)m_vertex_format, num ); \r\n//\r\n//\t\t\tfor ( int vv = 0; vv < num; vv++ )\r\n//\t\t\t{\r\n//\t\t\t\t// Send coordinates.\r\n//\t\t\t\tint pindex = p_pos_indices[v+vv];\r\n//\t\t\t\tint cindex = p_col_indices[pindex];\r\n//\t\t\t\tGXPosition1x16(pindex);\r\n//\t\t\t\tif ( mp_normBuffer || mp_doubleWeight ) GXNormal1x16(pindex);\r\n//\t\t\t\tif ( mp_colBuffer ) GXColor1x16(cindex);\r\n//\t\t\t\tif ( m_flags & MESH_FLAG_DOUBLE_COLOR_IDX ) GXColor1x16(cindex);\r\n//\t\t\t\tfor ( uint layer = 0; layer < mp_material->Passes; layer++ )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tint uindex = pindex;\r\n//\t\t\t\t\tif ( p_uv_indices ) uindex = p_uv_indices[pindex+(layer*m_num_vertex)];\r\n//\t\t\t\t\tGXTexCoord1x16(uindex);\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\tv += num;\r\n//\t\t\tGXEnd();\r\n//\t\t}\t\t\t\r\n//\t}\r\n//\r\n//\tint size = GXEndDisplayList();\r\n//\t\r\n//\tmp_index_buffer = NULL;\r\n//\r\n//\tuint8 * p_dl = new uint8[size];\r\n//\tmemcpy ( p_dl, p_build_dl, size );\r\n//\tDCFlushRange ( p_dl, size );\r\n//\r\n//\tdelete p_build_dl;\r\n//\r\n//\tmp_display_list = p_dl;\r\n//\tm_display_list_size = size;\r\n//\tEngineGlobals.gpuBusy = false;\r\n//\r\n//\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n//}\r\n//\r\n//void sMesh::Rebuild( int num_indices, uint16* p_indices )\r\n//{\r\n//\tuint16 * p_temp_col_remap = NULL;\r\n//\tuint16 * p_temp_uv_remap = NULL;\r\n//\tp_temp_uv_remap = m_num_uv_sets ? new (Mem::Manager::sHandle().TopDownHeap()) uint16[m_num_vertex*m_num_uv_sets] : NULL;\r\n//\tp_temp_col_remap = mp_colBuffer ? new (Mem::Manager::sHandle().TopDownHeap()) uint16[m_num_vertex] : NULL;\r\n//\r\n//\tfor ( int c = 0; c < m_num_vertex; c++ )\r\n//\t{\r\n//\t\tfor ( int u = 0; u < m_num_uv_sets; u++ )\r\n//\t\t{\r\n//\t\t\tp_temp_uv_remap[(u*m_num_vertex)+c] = (u*m_num_vertex)+c;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tfor ( int c = 0; c < m_num_vertex; c++ )\r\n//\t{\r\n//\t\tp_temp_col_remap[c] = c;\r\n//\t}\r\n//\r\n//\tdelete [] mp_display_list;\r\n//\r\n////\tBuild( num_indices, p_indices, p_indices, p_indices, true );\r\n//\tBuild( num_indices, p_indices, p_temp_col_remap, p_temp_uv_remap, true );\r\n//\t// Update to new number of indices.\r\n//\tm_num_indices = num_indices;\r\n//\r\n//\tdelete [] p_temp_col_remap;\r\n//\tdelete [] p_temp_uv_remap;\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::SetPosition( Mth::Vector &pos )\r\n{\r\n\r\n\r\n//\t// Figure what we need to add to each vertex, based on current position.\r\n//\tMth::Vector offset(\tpos[X] - m_offset_x,\r\n//\t\t\t\t\t\tpos[Y] - m_offset_y,\r\n//\t\t\t\t\t\tpos[Z] - m_offset_z );\r\n//\tm_offset_x = pos[X];\r\n//\tm_offset_y = pos[Y];\r\n//\tm_offset_z = pos[Z];\r\n//\r\n//\t// We also need to adjust the bounding box and sphere information for this mesh.\r\n//\tm_sphere[0] += offset[X];\r\n//\tm_sphere[1] += offset[Y];\r\n//\tm_sphere[2] += offset[Z];\r\n//\r\n//\tm_bbox.SetMin( m_bbox.GetMin() + offset );\r\n//\tm_bbox.SetMax( m_bbox.GetMax() + offset );\r\n//\r\n//#ifndef SHORT_VERT\r\n//\tif ( m_localMeshIndex != 0 ) return;\r\n//\r\n//\tfor( uint32 bv = 0; bv < m_num_vertex; ++bv )\r\n//\t{\r\n//\t\tmp_posBuffer[(bv*3)+0] += offset[X];\r\n//\t\tmp_posBuffer[(bv*3)+1] += offset[Y];\r\n//\t\tmp_posBuffer[(bv*3)+2] += offset[Z];\r\n//\t}\r\n//\tDCFlushRange( mp_posBuffer, 3 * sizeof( float ) * m_num_vertex );\r\n//#endif\t\t// SHORT_VERT\r\n//\r\n}\r\n\t\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::GetPosition( Mth::Vector *p_pos )\r\n{\r\n//\tp_pos->Set( m_offset_x, m_offset_y, m_offset_z );\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::SetYRotation( Mth::ERot90 rot )\r\n{\r\n//\tif( ( rot > Mth::ROT_0 ) && ( m_localMeshIndex == 0 ) )\r\n//\t{\r\n//\t\ts16 nx, nz;\r\n//#ifdef SHORT_VERT\r\n//\t\ts16 xo = 0;\r\n//\t\ts16 zo = 0;\r\n//\t\ts16 x, z;\r\n//#else\r\n//\t\tfloat x, z;\r\n//\t\tfloat xo = m_offset_x;\r\n//\t\tfloat zo = m_offset_z;\r\n//#endif\t\t// SHORT_VERT \r\n//\t\tswitch( rot )\r\n//\t\t{\r\n//\t\t\tcase Mth::ROT_90:\r\n//\t\t\t{\r\n//\t\t\t\tif ( m_localMeshIndex == 0 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tfor( uint32 v = 0; v < m_num_vertex; ++v )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tx = mp_posBuffer[(v*3)+0] - xo;\r\n//\t\t\t\t\t\tz = mp_posBuffer[(v*3)+2] - zo;\r\n//\t\t\t\t\t\tmp_posBuffer[(v*3)+0] = z + xo;\r\n//\t\t\t\t\t\tmp_posBuffer[(v*3)+2] = -x + zo;\r\n//\t\t\t\t\t\tif ( mp_normBuffer )\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tnx = mp_normBuffer[(v*3)+0];\r\n//\t\t\t\t\t\t\tnz = mp_normBuffer[(v*3)+2];\r\n//\t\t\t\t\t\t\tmp_normBuffer[(v*3)+0] = nz;\r\n//\t\t\t\t\t\t\tmp_normBuffer[(v*3)+2] = -nx;\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t\t// Adjust the bounding sphere information for this mesh.\r\n//\t\t\t\tm_sphere[0]\t-= m_offset_x;\r\n//\t\t\t\tm_sphere[2]\t-= m_offset_z;\r\n//\t\t\t\tfloat t\t\t\t\t= m_sphere[0];\r\n//\t\t\t\tm_sphere[0]\t= m_sphere[2] + m_offset_x;\r\n//\t\t\t\tm_sphere[2]\t= -t + m_offset_z;\r\n//\r\n//\t\t\t\t// Adjust the bounding box information for this mesh.\r\n//\t\t\t\tMth::Vector m[4];\r\n//\r\n//\t\t\t\tm[0].Set( m_bbox.GetMin()[X], 0.0f, m_bbox.GetMin()[Z] );\r\n//\t\t\t\tm[1].Set( m_bbox.GetMin()[X], 0.0f, m_bbox.GetMax()[Z] );\r\n//\t\t\t\tm[2].Set( m_bbox.GetMax()[X], 0.0f, m_bbox.GetMin()[Z] );\r\n//\t\t\t\tm[3].Set( m_bbox.GetMax()[X], 0.0f, m_bbox.GetMax()[Z] );\r\n//\r\n//\t\t\t\tfor( int i = 0; i < 4; ++i )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tm[i][X] -= m_offset_x;\r\n//\t\t\t\t\tm[i][Z] -= m_offset_z;\r\n//\t\t\t\t\tfloat t = m[i][X];\r\n//\t\t\t\t\tm[i][X] = m[i][Z];\r\n//\t\t\t\t\tm[i][Z] = -t;\r\n//\t\t\t\t\tm[i][X] += m_offset_x;\r\n//\t\t\t\t\tm[i][Z] += m_offset_z;\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tMth::Vector mmin( m[0][X], m_bbox.GetMin()[Y], m[0][Z] );\r\n//\t\t\t\tMth::Vector mmax( m[0][X], m_bbox.GetMax()[Y], m[0][Z] );\r\n//\t\t\t\tfor( int i = 1; i < 4; ++i )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( m[i][X] < mmin[X] )\r\n//\t\t\t\t\t\tmmin[X] = m[i][X];\r\n//\t\t\t\t\tif( m[i][X] > mmax[X] )\r\n//\t\t\t\t\t\tmmax[X] = m[i][X];\r\n//\r\n//\t\t\t\t\tif( m[i][Z] < mmin[Z] )\r\n//\t\t\t\t\t\tmmin[Z] = m[i][Z];\r\n//\t\t\t\t\tif( m[i][Z] > mmax[Z] )\r\n//\t\t\t\t\t\tmmax[Z] = m[i][Z];\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tm_bbox.SetMin( mmin );\r\n//\t\t\t\tm_bbox.SetMax( mmax );\r\n//\t\t\t\tbreak;\r\n//\t\t\t}\r\n//\t\t\tcase Mth::ROT_180:\r\n//\t\t\t{\r\n//\t\t\t\tif ( m_localMeshIndex == 0 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tfor( uint32 v = 0; v < m_num_vertex; ++v )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tx = mp_posBuffer[(v*3)+0] - xo;\r\n//\t\t\t\t\t\tz = mp_posBuffer[(v*3)+2] - zo;\r\n//\t\t\t\t\t\tmp_posBuffer[(v*3)+0] = -x + xo;\r\n//\t\t\t\t\t\tmp_posBuffer[(v*3)+2] = -z + zo;\r\n//\t\t\t\t\t\tif ( mp_normBuffer )\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tnx = mp_normBuffer[(v*3)+0];\r\n//\t\t\t\t\t\t\tnz = mp_normBuffer[(v*3)+2];\r\n//\t\t\t\t\t\t\tmp_normBuffer[(v*3)+0] = -nx;\r\n//\t\t\t\t\t\t\tmp_normBuffer[(v*3)+2] = -nz;\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t\t// Adjust the bounding sphere information for this mesh.\r\n//\t\t\t\tm_sphere[0]\t-= m_offset_x;\r\n//\t\t\t\tm_sphere[2]\t-= m_offset_z;\r\n//\t\t\t\tm_sphere[0]\t= -m_sphere[0] + m_offset_x;\r\n//\t\t\t\tm_sphere[2]\t= -m_sphere[2] + m_offset_z;\r\n//\r\n//\t\t\t\t// Adjust the bounding box information for this mesh.\r\n//\t\t\t\tMth::Vector m[4];\r\n//\r\n//\t\t\t\tm[0].Set( m_bbox.GetMin()[X], 0.0f, m_bbox.GetMin()[Z] );\r\n//\t\t\t\tm[1].Set( m_bbox.GetMin()[X], 0.0f, m_bbox.GetMax()[Z] );\r\n//\t\t\t\tm[2].Set( m_bbox.GetMax()[X], 0.0f, m_bbox.GetMin()[Z] );\r\n//\t\t\t\tm[3].Set( m_bbox.GetMax()[X], 0.0f, m_bbox.GetMax()[Z] );\r\n//\r\n//\t\t\t\tfor( int i = 0; i < 4; ++i )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tm[i][X] -= m_offset_x;\r\n//\t\t\t\t\tm[i][Z] -= m_offset_z;\r\n//\t\t\t\t\tm[i][X] = -m[i][X];\r\n//\t\t\t\t\tm[i][Z] = -m[i][Z];\r\n//\t\t\t\t\tm[i][X] += m_offset_x;\r\n//\t\t\t\t\tm[i][Z] += m_offset_z;\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tMth::Vector mmin( m[0][X], m_bbox.GetMin()[Y], m[0][Z] );\r\n//\t\t\t\tMth::Vector mmax( m[0][X], m_bbox.GetMax()[Y], m[0][Z] );\r\n//\t\t\t\tfor( int i = 1; i < 4; ++i )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( m[i][X] < mmin[X] )\r\n//\t\t\t\t\t\tmmin[X] = m[i][X];\r\n//\t\t\t\t\tif( m[i][X] > mmax[X] )\r\n//\t\t\t\t\t\tmmax[X] = m[i][X];\r\n//\r\n//\t\t\t\t\tif( m[i][Z] < mmin[Z] )\r\n//\t\t\t\t\t\tmmin[Z] = m[i][Z];\r\n//\t\t\t\t\tif( m[i][Z] > mmax[Z] )\r\n//\t\t\t\t\t\tmmax[Z] = m[i][Z];\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tm_bbox.SetMin( mmin );\r\n//\t\t\t\tm_bbox.SetMax( mmax );\r\n//\t\t\t\tbreak;\r\n//\t\t\t}\r\n//\t\t\tcase Mth::ROT_270:\r\n//\t\t\t{\r\n//\t\t\t\tif ( m_localMeshIndex == 0 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tfor( uint32 v = 0; v < m_num_vertex; ++v )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tx = mp_posBuffer[(v*3)+0] - xo;\r\n//\t\t\t\t\t\tz = mp_posBuffer[(v*3)+2] - zo;\r\n//\t\t\t\t\t\tmp_posBuffer[(v*3)+0] = -z + xo;\r\n//\t\t\t\t\t\tmp_posBuffer[(v*3)+2] = x + zo;\r\n//\t\t\t\t\t\tif ( mp_normBuffer )\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tnx = mp_normBuffer[(v*3)+0];\r\n//\t\t\t\t\t\t\tnz = mp_normBuffer[(v*3)+2];\r\n//\t\t\t\t\t\t\tmp_normBuffer[(v*3)+0] = -nz;\r\n//\t\t\t\t\t\t\tmp_normBuffer[(v*3)+2] = nx;\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t\t// Adjust the bounding sphere information for this mesh.\r\n//\t\t\t\tm_sphere[0]\t-= m_offset_x;\r\n//\t\t\t\tm_sphere[2]\t-= m_offset_z;\r\n//\t\t\t\tfloat t\t\t\t\t= m_sphere[0];\r\n//\t\t\t\tm_sphere[0]\t= -m_sphere[2] + m_offset_x;\r\n//\t\t\t\tm_sphere[2]\t= t + m_offset_z;\r\n//\r\n//\t\t\t\t// Adjust the bounding box information for this mesh.\r\n//\t\t\t\tMth::Vector m[4];\r\n//\r\n//\t\t\t\tm[0].Set( m_bbox.GetMin()[X], 0.0f, m_bbox.GetMin()[Z] );\r\n//\t\t\t\tm[1].Set( m_bbox.GetMin()[X], 0.0f, m_bbox.GetMax()[Z] );\r\n//\t\t\t\tm[2].Set( m_bbox.GetMax()[X], 0.0f, m_bbox.GetMin()[Z] );\r\n//\t\t\t\tm[3].Set( m_bbox.GetMax()[X], 0.0f, m_bbox.GetMax()[Z] );\r\n//\r\n//\t\t\t\tfor( int i = 0; i < 4; ++i )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tm[i][X] -= m_offset_x;\r\n//\t\t\t\t\tm[i][Z] -= m_offset_z;\r\n//\t\t\t\t\tfloat t = m[i][X];\r\n//\t\t\t\t\tm[i][X] = -m[i][Z];\r\n//\t\t\t\t\tm[i][Z] = t;\r\n//\t\t\t\t\tm[i][X] += m_offset_x;\r\n//\t\t\t\t\tm[i][Z] += m_offset_z;\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tMth::Vector mmin( m[0][X], m_bbox.GetMin()[Y], m[0][Z] );\r\n//\t\t\t\tMth::Vector mmax( m[0][X], m_bbox.GetMax()[Y], m[0][Z] );\r\n//\t\t\t\tfor( int i = 1; i < 4; ++i )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( m[i][X] < mmin[X] )\r\n//\t\t\t\t\t\tmmin[X] = m[i][X];\r\n//\t\t\t\t\tif( m[i][X] > mmax[X] )\r\n//\t\t\t\t\t\tmmax[X] = m[i][X];\r\n//\r\n//\t\t\t\t\tif( m[i][Z] < mmin[Z] )\r\n//\t\t\t\t\t\tmmin[Z] = m[i][Z];\r\n//\t\t\t\t\tif( m[i][Z] > mmax[Z] )\r\n//\t\t\t\t\t\tmmax[Z] = m[i][Z];\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tm_bbox.SetMin( mmin );\r\n//\t\t\t\tm_bbox.SetMax( mmax );\r\n//\t\t\t\tbreak;\r\n//\t\t\t}\r\n//\t\t\tdefault:\r\n//\t\t\t\t// Do nothing.\r\n//\t\t\t\tbreak;\r\n//\t\t}\r\n//#ifdef SHORT_VERT\r\n//\t\tDCFlushRange( mp_posBuffer, 3 * m_num_vertex * sizeof( s16 ) );\r\n//#else\r\n//\t\tDCFlushRange( mp_posBuffer, 3 * m_num_vertex * sizeof( float ) );\r\n//#endif\t\t// SHORT_VERT\r\n//\t\tif ( mp_normBuffer ) DCFlushRange( mp_normBuffer, 3 * m_num_vertex * sizeof( s16 ) );\r\n//\t}\r\n}\r\n\t\r\n} // namespace NxNgc\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/mesh.h",
    "content": "#ifndef __MESH_H\r\n#define __MESH_H\r\n\r\n#include <core\\math.h>\r\n#include <core\\math\\geometry.h>\r\n#include <gfx\\nx.h>\r\n#include \"material.h\"\r\n#include <sys\\ngc\\p_gx.h>\r\n\r\n// Comment in for 16 bit vertices.\r\n//#define SHORT_VERT\r\n\r\nnamespace NxNgc\r\n{\r\n\r\nstruct sDLHeader;\t// Forward reference.\r\n\r\n//#define MESHFLAG_TEXTURE     (1<<0)\r\n//#define MESHFLAG_COLOURS     (1<<1)\r\n//#define MESHFLAG_NORMALS     (1<<2)\r\n\r\n//#define OBJFLAG_TEXTURE      (1<<0)\r\n//#define OBJFLAG_COLOURS      (1<<1)\r\n//#define OBJFLAG_NORMALS      (1<<2)\r\n//#define OBJFLAG_TRANSPARENT\t (1<<3)\r\n\r\nstruct sCASData\r\n{\r\n\tuint32\tmask;\r\n\tuint32\tdata0;\r\n\tuint32\tdata1;\r\n};\r\n\t\r\n// Starting to turn this into a class, but since engine is still\r\n// C-style, I'm keeping everything public.  Garrett\r\nstruct sMesh\r\n{\r\npublic:\r\n\tenum EMeshFlags\r\n\t{\r\n\t\tMESH_FLAG_IS_INSTANCE\t\t\t\t= (1<<0),\r\n\t\tMESH_FLAG_ACTIVE\t\t\t\t\t= (1<<1),\r\n\t\tMESH_FLAG_IS_CLONED\t\t\t\t\t= (1<<2),\r\n\t\tMESH_FLAG_VISIBLE\t\t\t\t\t= (1<<3),\t\t// Used for batch culling.\r\n\t\tMESH_FLAG_CLONED_POS\t\t\t\t= (1<<4),\r\n\t\tMESH_FLAG_CLONED_COL\t\t\t\t= (1<<5),\r\n\t\tMESH_FLAG_INDEX_COUNT_SET\t\t\t= (1<<6),\r\n\t\tMESH_FLAG_NO_SKATER_SHADOW\t\t\t= (1<<7),\r\n\t\tMESH_FLAG_CLONED_DL\t\t\t\t\t= (1<<8),\r\n\t};\r\n\r\n\t\t\t\t\tsMesh( void );\r\n\t\t\t\t\t~sMesh( void );\r\n\r\n\t// Functions\r\n\tvoid\t\t\twibble_vc( void );\r\n\tvoid\t\t\twibble_normals( void );\r\n\tuint32\t\t\tGetChecksum()\tconst { return Checksum; }\r\n\tuint32\t\t\tGetFlags()\t\tconst\t\t\t{ return m_flags; }\r\n\t\r\n\tvoid\t\t\tSetActive( bool active )\t\t{ m_flags = ( m_flags & ~MESH_FLAG_ACTIVE ) | ( active ? MESH_FLAG_ACTIVE : 0 ); }\r\n\tvoid\t\t\tSetPosition( Mth::Vector &pos );\r\n\tvoid\t\t\tGetPosition( Mth::Vector *p_pos );\r\n\tvoid\t\t\tSetYRotation( Mth::ERot90 rot );\r\n\tvoid\t\t\tSetVisibility( uint32 mask )\t{ m_visibility_mask\t= mask; }\r\n\tuint32\t\t\tGetVisibility( void )\t\t\t{ return m_visibility_mask; }\r\n\tsMesh\t\t\t*Clone( bool instance = false );\r\n//\tvoid\t\t\tInitialize( int num_vertices,\r\n//\t\t\t\t\t\t\t\tfloat* p_positions,\r\n//#ifdef SHORT_VERT\r\n//\t\t\t\t\t\t\t\ts16* p_positions16,\r\n//\t\t\t\t\t\t\t\tint shift,\r\n//\t\t\t\t\t\t\t\tfloat off_x,\r\n//\t\t\t\t\t\t\t\tfloat off_y,\r\n//\t\t\t\t\t\t\t\tfloat off_z,\r\n//#endif\t\t// SHORT_VERT\r\n//\t\t\t\t\t\t\t\ts16* p_normals,\r\n//\t\t\t\t\t\t\t\tfloat* p_tex_coords,\r\n//\t\t\t\t\t\t\t\tfloat* p_env_buffer,\r\n//\t\t\t\t\t\t\t\tint num_tc_sets,\r\n//\t\t\t\t\t\t\t\tuint32* p_colors,\r\n//\t\t\t\t\t\t\t\tint num_indices,\r\n//\t\t\t\t\t\t\t\tuint16* p_pos_indices,\r\n//\t\t\t\t\t\t\t\tuint16* p_col_indices,\r\n//\t\t\t\t\t\t\t\tuint16* p_uv_indices,\r\n//\t\t\t\t\t\t\t\tunsigned long material_checksum,\r\n//\t\t\t\t\t\t\t\tvoid *p_scene,\r\n//\t\t\t\t\t\t\t\tint num_double,\r\n//\t\t\t\t\t\t\t\tuint32* p_double,\r\n//\t\t\t\t\t\t\t\tint num_single,\r\n//\t\t\t\t\t\t\t\tint localMeshIndex,\r\n//\t\t\t\t\t\t\t\tGXPrimitive primitive_type,\r\n//\t\t\t\t\t\t\t\tint bone_idx,\r\n//\t\t\t\t\t\t\t\tchar *p_vc_wibble_anims  = NULL );\r\n\r\n\tvoid\t\t\tBuild( int num_indices, uint16* p_pos_indices, uint16* p_col_indices, uint16* p_uv_indices, bool rebuild = false );\r\n\tvoid\t\t\tRebuild( int num_indices, uint16* p_indices );\r\n\r\n\t// Note: localMeshIndex is the nth instance of a mesh in a sector.\r\n\tvoid\t\t\tSubmit( void );\r\n\r\n\t// Members\r\n\tuint32\t\t\t\t\tChecksum;\r\n\tuint16\t\t\t\t\tm_flags;\r\n\tint16\t\t\t\t\tm_bone_idx;\r\n\tuint32\t\t\t\t\tm_visibility_mask;\r\n\tfloat\t\t\t\t\tm_bottom_y;\t// Use this to cull meshes above the skater for shadows.\r\n\r\n//\tsMaterial*\t\t\t\tmp_material;\r\n//\t\r\n//\tuint16\t\t\t\t\tm_num_indices;\r\n//\tuint16\t\t\t\t\tm_num_vertex;\r\n//\tuint8\t\t\t\t\tm_vertex_stride;\r\n//\tuint8\t\t\t\t\tm_num_uv_sets;\r\n//\r\n//\tuint16\t\t\t\t\tm_display_list_size;\r\n//\tuint8\t\t\t\t\tm_primitive_type;\r\n//\tuint8\t\t\t\t\tm_vertex_format;\r\n//\tuint16\t\t\t\t\tm_localMeshIndex;\r\n//\r\n//\tuint16*\t\t\t\t\tmp_index_buffer;\r\n//#ifdef SHORT_VERT\r\n//\ts16*\t\t\t\t\tmp_posBuffer;\r\n//#else\r\n//\tfloat*\t\t\t\t\tmp_posBuffer;\r\n//#endif\t\t// SHORT_VERT\r\n//\tfloat\t\t\t\t\tm_offset_x;\r\n//\tfloat\t\t\t\t\tm_offset_y;\r\n//\tfloat\t\t\t\t\tm_offset_z;\r\n//\ts16*\t\t\t\t\tmp_normBuffer;\r\n//\tfloat*\t\t\t\t\tmp_uvBuffer;\r\n//\tfloat*\t\t\t\t\tmp_envBuffer;\r\n//\tuint32*\t\t\t\t\tmp_colBuffer;\r\n//\r\n//\tuint8*\t\t\t\t\tmp_display_list;\r\n//\r\n//\tMth::CBBox\t\t\t\tm_bbox;\r\n//\tfloat\t\t\t\t\tm_sphere[4];\r\n//\r\n//\tuint16\t\t\t\t\tm_numDouble;\r\n//\tuint16\t\t\t\t\tm_numSingle;\r\n//\tuint32*\t\t\t\t\tmp_doubleWeight;\r\n//\r\n//\tchar\t\t\t\t\t*mp_vc_wibble_data;\r\n//\r\n//\tGXColor\t\t\t\t\tm_material_color_override;\r\n\r\n//\tMth::Vector\t\t\t\tm_sphere;\r\n\r\n\tsDLHeader*\t\t\t\tmp_dl;\r\n//\tvoid *\t\t\t\t\tmp_texture_dl;\r\n//\tuint32\t\t\t\t\tm_texture_dl_size;\r\n//\r\n//\tbool\t\t\t\t\tdl_owner;\r\n\r\n\tGXColor\t\t\t\t\tm_base_color;\r\n};\r\n\r\n/*\r\n// Starting to turn this into a class, but since engine is still\r\n// C-style, I'm keeping everything public.  Garrett\r\nstruct sGroup\r\n{\r\npublic:\r\n\t// Functions\r\n\tsMesh*\t\t\tGetMeshArray(); \r\n\tuint\t\t\tGetNumMeshes() const { return NumMeshes; }\r\n\r\n\t// Members\r\n\tuint32 ID;\r\n\tuint8 *pUpload[2];\r\n\tuint8 *pRender[2];\r\n\tuint FirstMeshIndex;\r\n\tuint NumMeshes;\r\n};\r\n\r\n\r\nsGroup*\t\t\tNewMeshGroup(uint32 group_ID, uint32 num_meshes);\r\nsGroup*\t\t\tLoadMeshGroup(void *p_FH);\r\nvoid\t\t\tLoadVertices(void *p_FH, sMesh *pMesh, sMaterial *pMat);\r\n\r\nextern sMesh *Meshes;\r\nextern uint NumMeshes, NumMeshGroups;\r\nextern uint NumMeshesInGroup[32];\r\nextern int TotalNumVertices;\r\n*/\r\n\r\nvoid SetMeshScalingParameters( Nx::SMeshScalingParameters* pParams );\r\nvoid DisableMeshScaling( void );\r\nvoid ApplyMeshScaling( NxNgc::sObjectHeader * p_object );\r\n\r\n} // namespace NxNgc\r\n\r\n#endif // __MESH_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/nx_init.cpp",
    "content": "#include \"nx_init.h\"\r\n#include \"instance.h\"\r\n#include \"render.h\"\r\n#include \"sys/ngc/p_buffer.h\"\r\n\r\n\r\nnamespace NxNgc\r\n{\r\n\r\nsEngineGlobals\tEngineGlobals;\r\n\t\r\n\t\r\n\r\n\r\nvoid InitialiseRenderstates( void )\r\n{\r\n//\tEngineGlobals.lighting_enabled\t\t= false;\r\n//\tD3DDevice_SetRenderState( D3DRS_LIGHTING, FALSE );\r\n//\r\n//\tEngineGlobals.cull_mode\t\t\t\t= D3DCULL_NONE;\r\n//\tD3DDevice_SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );\r\n//\r\n//\tEngineGlobals.dither_enable\t\t\t= TRUE;\r\n//\tD3DDevice_SetRenderState( D3DRS_DITHERENABLE, TRUE );\r\n//\r\n//\tEngineGlobals.z_test_enabled\t\t= TRUE;\r\n//\tD3DDevice_SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );\r\n//\r\n//\tEngineGlobals.z_write_enabled\t\t= TRUE;\r\n//\tD3DDevice_SetRenderState( D3DRS_ZWRITEENABLE, TRUE );\r\n//\t\r\n//\tEngineGlobals.alpha_blend_enable\t= TRUE;\r\n//\tD3DDevice_SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );\r\n//\r\n//\tEngineGlobals.alpha_test_enable\t\t= TRUE;\r\n//\tD3DDevice_SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );\r\n//\r\n//\tEngineGlobals.alpha_ref\t\t\t\t= 0;\r\n//\tD3DDevice_SetRenderState( D3DRS_ALPHAREF, 0x00 );\r\n//\r\n//\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );\r\n//    D3DDevice_SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );\r\n//    D3DDevice_SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );\r\n//\r\n//    D3DDevice_SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );\r\n//    D3DDevice_SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );\r\n//\r\n//    D3DDevice_SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL );\r\n//    D3DDevice_SetRenderState( D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL );\r\n//    D3DDevice_SetRenderState( D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL );\r\n//\r\n//\t// Set these up so they will get reset first time through.\r\n//\tEngineGlobals.blend_mode_value\t\t\t= 0xDEADBABE;\r\n//\tEngineGlobals.blend_mode_fixed_alpha\t= 0xDEADBABE;\r\n\r\n\tinit_render_system();\r\n}\r\n\r\n\r\nvoid InitialiseEngine( void )\r\n{\r\n\r\n//\tD3DPRESENT_PARAMETERS   params;\r\n//\tDWORD\t\t\t\t\tvideo_flags = XGetVideoFlags();\r\n//\r\n//\tZeroMemory( &params, sizeof( D3DPRESENT_PARAMETERS ));\r\n//\r\n//\t// This setting required for any multisample presentation.\r\n//\tparams.SwapEffect\t\t\t\t\t\t= D3DSWAPEFFECT_DISCARD;\r\n//\r\n//\t// Let D3D create the depth-stencil buffer for us.\r\n//\tparams.EnableAutoDepthStencil\t\t\t= TRUE;\r\n//\r\n//\t// Select default refresh rate and presentation interval. Note: When we switch to the December SDK\r\n//\t// we can use the ONE_OR_IMMEDIATE value (if the tearing looks okay).\r\n//\tparams.FullScreen_RefreshRateInHz\t\t= D3DPRESENT_RATE_DEFAULT;\r\n//\tparams.FullScreen_PresentationInterval\t= D3DPRESENT_INTERVAL_ONE;\r\n//\r\n//\t// Set up the back buffer format.\r\n//\tparams.BackBufferCount\t\t\t\t\t= 1;\r\n//\tparams.BackBufferWidth\t\t\t\t\t= 640;\r\n//\tparams.BackBufferHeight\t\t\t\t\t= 480;\r\n////\tparams.BackBufferFormat\t\t\t\t\t= D3DFMT_LIN_R5G6B5;\r\n//\tparams.BackBufferFormat\t\t\t\t\t= D3DFMT_X8R8G8B8;\r\n//\r\n//\t// Set up the Z-stencil buffer format and multisample format.\r\n//\tparams.AutoDepthStencilFormat\t\t\t= D3DFMT_D24S8;\r\n//    params.MultiSampleType\t\t\t\t\t= D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_LINEAR;\r\n//\r\n//\t// Set flag for progrssive scan where appropriate.\r\n//\tif( video_flags & XC_VIDEO_FLAGS_HDTV_480p )\r\n//\t{\r\n//\t\tparams.Flags\t\t\t\t\t\t= D3DPRESENTFLAG_PROGRESSIVE;\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tparams.Flags\t\t\t\t\t\t= D3DPRESENTFLAG_INTERLACED;\r\n//\t}\r\n//\t\r\n//\tif( D3D_OK != Direct3D_CreateDevice(\tD3DADAPTER_DEFAULT,\r\n//\t\t\t\t\t\t\t\t\t\t\tD3DDEVTYPE_HAL,\r\n//\t\t\t\t\t\t\t\t\t\t\tNULL,\r\n//\t\t\t\t\t\t\t\t\t\t\tD3DCREATE_HARDWARE_VERTEXPROCESSING,\t// Note: may want to consider adding the PUREDEVICE flag here also.\r\n//\t\t\t\t\t\t\t\t\t\t\t&params,\r\n//\t\t\t\t\t\t\t\t\t\t\t&EngineGlobals.p_Device ))\r\n//\t{\r\n//\t\t// Failed to start up engine. Bad!\r\n//\t\treturn;\r\n//\t}\r\n//\r\n//\t// Obtain pointers to the render and Z-stencil surfaces. Doing this increases their reference counts, so release\r\n//\t// them following the operation.\r\n//\tD3DDevice_GetRenderTarget( &EngineGlobals.p_RenderSurface );\r\n//\tD3DDevice_GetDepthStencilSurface( &EngineGlobals.p_ZStencilSurface );\r\n//\r\n//    D3DResource_Release((D3DResource*)&EngineGlobals.p_RenderSurface );\r\n//    D3DResource_Release((D3DResource*)&EngineGlobals.p_ZStencilSurface );\r\n//\r\n\t// Set default directional lights\r\n\tEngineGlobals.light_x[0] = -0.5f;\t\t// Dir0\r\n\tEngineGlobals.light_y[0] = -0.8660254f;\r\n\tEngineGlobals.light_z[0] = 0.0f;\r\n\tEngineGlobals.diffuse_light_color[0] = (GXColor){143,143,143,255};\r\n\t\r\n\tEngineGlobals.light_x[1] = 1.0f;\t\t// Dir1 \r\n\tEngineGlobals.light_y[1] = 0.0f;\r\n\tEngineGlobals.light_z[1] = 0.0f;\r\n\tEngineGlobals.diffuse_light_color[1] = (GXColor){0,0,0,255};\r\n\r\n\t// Set default ambient light.\r\n\tEngineGlobals.ambient_light_color = (GXColor){150,150,150,255};\r\n\r\n\tEngineGlobals.gpuBusy = false;\r\n\r\n\tEngineGlobals.screen_brightness = 1.0f;\r\n\r\n\tEngineGlobals.frameCount = 0;\r\n\r\n\tEngineGlobals.use_480p\t\t\t= false;\r\n\tEngineGlobals.use_60hz\t\t\t= false;\r\n\tEngineGlobals.letterbox_active\t= false;\r\n\r\n\tEngineGlobals.reduceColors = true;\r\n\r\n\t// Set our renderstate to a known state.\r\n\tInitialiseRenderstates();\r\n\r\n\t// Create our instance table.\r\n\tInitialiseInstanceTable();\r\n\r\n\tEngineGlobals.disableReset = false;\r\n\tEngineGlobals.resetToIPL = false; \r\n\r\n\tNsBuffer::init( ( 1024 * 512 ) - ( 50 * 1024 ) );\r\n}\r\n\r\n\r\n} // namespace NxNgc\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/nx_init.h",
    "content": "#ifndef __NX_INIT_H\r\n#define __NX_INIT_H\r\n\r\n#include <core/defines.h>\r\n#include <sys/ngc/p_camera.h>\r\n\r\nnamespace NxNgc\r\n{\r\n\r\nvoid InitialiseEngine( void );\r\n\r\ntypedef struct\r\n{\r\n//\tIDirect3DDevice8*\tp_Device;\r\n//\tIDirect3DSurface8*\tp_RenderSurface;\r\n//\tIDirect3DSurface8*\tp_ZStencilSurface;\r\n\r\n\tuint32\t\t\t\tblend_mode_value;\r\n\tuint32\t\t\t\tblend_mode_fixed_alpha;\r\n\r\n\t// These renderstates should go in their own structure.\r\n\tbool\t\t\t\talpha_blend_enable;\r\n\tbool\t\t\t\talpha_test_enable;\r\n\tuint32\t\t\t\talpha_ref;\r\n\tbool\t\t\t\tlighting_enabled;\r\n\tbool\t\t\t\tdither_enable;\r\n\tbool\t\t\t\tz_write_enabled;\r\n\tbool\t\t\t\tz_test_enabled;\r\n\tint\t\t\t\t\tcull_mode;\r\n\tbool\t\t\t\tpoly_culling;\r\n\r\n\tNsMatrix\t\t\tlocal_to_camera;\r\n\tNsMatrix\t\t\tworld_to_camera;\r\n\tNsMatrix\t\t\tcamera;\r\n\tNsMatrix\t\t\tshadow_camera;\r\n\tVec\t\t\t\t\tobject_pos;\r\n\tMtx\t\t\t\t\tcurrent_uploaded;\r\n\r\n\tfloat\t\t\t\ttx;\r\n\tfloat\t\t\t\tty;\r\n\tfloat\t\t\t\tsx;\r\n\tfloat\t\t\t\tsy;\r\n\tfloat\t\t\t\tcx;\r\n\tfloat\t\t\t\tcy;\r\n\tfloat\t\t\t\tnear;\r\n\tfloat\t\t\t\tfar;\r\n\r\n\tGXColor\t\t\t\tambient_light_color;\r\n\tGXColor\t\t\t\tdiffuse_light_color[3];\r\n\tfloat\t\t\t\tlight_x[3];\r\n\tfloat\t\t\t\tlight_y[3];\r\n\tfloat\t\t\t\tlight_z[3];\r\n\r\n\tfloat\t\t\t\tscreen_brightness;\t// 0 = black, 1 = normal, 2 = saturated.\r\n\r\n\tuint32\t\t\t\tframeCount;\r\n\r\n\tvolatile bool\t\tgpuBusy;\r\n\r\n\t// ARAM defines.\r\n\t#define aram_zero_size\t\t1024\r\n\t#define\taram_dsp_size\t\t1024 * 1900\r\n\t#define\taram_stream0_size\t1024 * 32\r\n\t#define aram_stream1_size\taram_stream0_size\r\n\t#define aram_stream2_size\taram_stream1_size\r\n\t#define aram_music_size\t\t1024 * 32\r\n\t\r\n\tuint32\t\t\t\taram_zero;\r\n\tuint32\t\t\t\taram_dsp;\r\n\tuint32\t\t\t\taram_stream0;\r\n\tuint32\t\t\t\taram_stream1;\r\n\tuint32\t\t\t\taram_stream2;\r\n\tuint32\t\t\t\taram_music;\r\n\r\n\tbool\t\t\t\tuse_480p;\r\n\tbool\t\t\t\tuse_60hz;\r\n\tbool\t\t\t\tuse_widescreen;\r\n\tbool\t\t\t\tletterbox_active;\r\n\r\n\tbool\t\t\t\treduceColors;\r\n\r\n\tbool\t\t\t\tdisableReset;\r\n\tbool\t\t\t\tresetToIPL;\r\n\r\n\tuint32\t\t\t\tviewport;\t\t// Expressed as a bit ( 1 << v ).\r\n\r\n\tNsVector\t\t\tskater_shadow_dir;\r\n\tfloat\t\t\t\tskater_height;\r\n\tNsVector\t\t\tped_shadow_dir;\r\n}\r\nsEngineGlobals;\r\n\r\nextern sEngineGlobals EngineGlobals;\r\n\r\n\r\n\r\n} // namespace NxNgc\r\n\r\n#endif // __NX_INIT_H\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/occlude.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics (GFX)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tocclude.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t04/02/02\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tOcclusion testing code\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n//#define\tOCCLUDER_USES_SCRATCHPAD\r\n//#define\tOCCLUDER_USES_VU0_MACROMODE\r\n//#define\tOCCLUDER_USES_VU0_MICROMODE\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\r\n#include <core/math.h>\r\n#include <gfx/debuggfx.h>\r\n#include \"occlude.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//extern D3DXMATRIX *p_bbox_transform;\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nconst uint32 MAX_NEW_OCCLUSION_POLYS_TO_CHECK_PER_FRAME = 4;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Structure used to store details of a single poly. A list of these will be built at geometry load time.\r\nstruct sOcclusionPoly\r\n{\r\n\tbool\t\tin_use;\t\t// Whether the poly is currently being used for occlusion.\r\n\tbool\t\tavailable;\t// Whether the poly is available for selection for occlusion.\r\n\tuint32\t\tchecksum;\t// Name checksum of the occlusion poly.\r\n\tMth::Vector\tverts[4];\r\n\tMth::Vector\tnormal;\r\n};\r\n\t\r\nconst uint32\tMAX_OCCLUDERS\t\t\t\t= 8;\r\nconst uint32\tMAX_VIEWS_PER_OCCLUDER\t\t= 2;\r\n\r\nstruct sOccluder\r\n{\r\n\tstatic uint32\t\tNumOccluders;\r\n\tstatic sOccluder\tOccluders[MAX_OCCLUDERS];\r\n\r\n\tstatic void\t\t\tadd_to_stack( sOcclusionPoly *p_poly );\r\n\tstatic void\t\t\tsort_stack( void );\r\n\tstatic void\t\t\ttidy_stack( void );\r\n\r\n\tsOcclusionPoly\t*p_poly;\r\n\tMth::Vector\t\tplanes[5];\r\n\tint\t\t\t\tscore[MAX_VIEWS_PER_OCCLUDER];\t// Current rating on quality of occlusion - based on number of meshes occluded last frame.\r\n};\r\n\r\nconst uint32\tMAX_OCCLUSION_POLYS\t\t\t= 512;\r\nuint32\t\t\tNumOcclusionPolys\t\t\t= 0;\r\nuint32\t\t\tNextOcclusionPolyToCheck\t= 0;\r\nint\t\t\t\tCurrentView\t\t\t\t\t= 0;\r\nsOcclusionPoly\tOcclusionPolys[MAX_OCCLUSION_POLYS];\r\n\r\nuint32\t\tsOccluder::NumOccluders\t\t\t\t= 0;\r\nsOccluder\tsOccluder::Occluders[MAX_OCCLUDERS];\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sOccluder::add_to_stack( sOcclusionPoly *p_poly )\r\n{\r\n\tif( NumOccluders < MAX_OCCLUDERS )\r\n\t{\r\n\t\tDbg_Assert( p_poly->available );\r\n\r\n\t\tOccluders[NumOccluders].p_poly\t= p_poly;\r\n\t\tp_poly->in_use\t\t\t\t\t= true;\r\n\r\n\t\t// Reset scores for all views.\r\n\t\tmemset( Occluders[NumOccluders].score, 0, sizeof( int ) * MAX_VIEWS_PER_OCCLUDER );\r\n\r\n\t\t++NumOccluders;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int cmp( const void *p1, const void *p2 )\r\n{\r\n\t// Sort based on the sum total of scores in all views.\r\n\tint score1 = 0;\r\n\tint score2 = 0;\r\n\tfor( uint v = 0; v < MAX_VIEWS_PER_OCCLUDER; ++v )\r\n\t{\r\n\t\t// Zero the score for any occlusion poly that is no longer available. This will force it out of the stack.\r\n\t\tif(((sOccluder*)p1)->p_poly->available == false )\r\n\t\t\t((sOccluder*)p1)->score[v] = 0;\r\n\r\n\t\tif(((sOccluder*)p2)->p_poly->available == false )\r\n\t\t\t((sOccluder*)p2)->score[v] = 0;\r\n\r\n\t\tscore1 += ((sOccluder*)p1)->score[v];\r\n\t\tscore2 += ((sOccluder*)p2)->score[v];\r\n\t}\r\n\r\n\treturn score1 < score2 ? 1 : score1 > score2 ? -1 : 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sOccluder::sort_stack( void )\r\n{\r\n\tqsort( Occluders, NumOccluders, sizeof( sOccluder ), cmp );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sOccluder::tidy_stack( void )\r\n{\r\n\tif( NumOccluders > 0 )\r\n\t{\r\n\t\t// Sort in descending score order.\r\n\t\tsort_stack();\r\n\r\n\t\t// Count backwards so we know we get all the bad occluders.\r\n\t\tfor( int i = NumOccluders - 1; i >= 0; --i )\r\n\t\t{\r\n\t\t\t// If we have hit an occluder with zero meshes culled, cut off the stack at this point.\r\n\t\t\tint total_score = 0;\r\n\t\t\tfor( uint v = 0; v < MAX_VIEWS_PER_OCCLUDER; ++v )\r\n\t\t\t{\r\n\t\t\t\ttotal_score += Occluders[i].score[v];\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif( total_score == 0 )\r\n\t\t\t{\r\n\t\t\t\t// No longer using this poly.\r\n\t\t\t\tOccluders[i].p_poly->in_use = false;\r\n\r\n\t\t\t\t// One less occluder to worry about.\r\n\t\t\t\t--NumOccluders;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Reset the good occluders.\r\n\t\t\t\tOccluders[i].score[CurrentView] = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Used to add an occlusion poly to the list. Likely to be called */\r\n/* as geometry is spooled in.                                     */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid AddOcclusionPoly( Mth::Vector &v0, Mth::Vector &v1, Mth::Vector &v2, Mth::Vector &v3, uint32 checksum )\r\n{\r\n\tDbg_Assert( NumOcclusionPolys < MAX_OCCLUSION_POLYS );\t\r\n\t\r\n\tOcclusionPolys[NumOcclusionPolys].in_use\t= false;\r\n\tOcclusionPolys[NumOcclusionPolys].available\t= true;\r\n\tOcclusionPolys[NumOcclusionPolys].checksum\t= checksum;\r\n\tOcclusionPolys[NumOcclusionPolys].verts[0]\t= v0;\r\n\tOcclusionPolys[NumOcclusionPolys].verts[1]\t= v1;\r\n\tOcclusionPolys[NumOcclusionPolys].verts[2]\t= v2;\r\n\tOcclusionPolys[NumOcclusionPolys].verts[3]\t= v3;\r\n\tOcclusionPolys[NumOcclusionPolys].normal\t= Mth::CrossProduct( v1 - v0, v3 - v0 );\r\n\tOcclusionPolys[NumOcclusionPolys].normal.Normalize();\r\n\t\r\n\t++NumOcclusionPolys;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Used to toggle whether an occlusion poly can be used or not\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid EnableOcclusionPoly( uint32 checksum, bool available )\r\n{\r\n\tfor( uint32 i = 0; i < NumOcclusionPolys; ++i )\r\n\t{\r\n\t\tif( OcclusionPolys[i].checksum == checksum )\r\n\t\t{\r\n\t\t\tOcclusionPolys[i].available\t= available;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Used to clear all occlusion polys (when a level is unloaded)   */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid RemoveAllOcclusionPolys( void )\r\n{\r\n\tDbg_Assert( NumOcclusionPolys < MAX_OCCLUSION_POLYS );\t\r\n\t\r\n \tsOccluder::NumOccluders\t\t= 0;\r\n\tNumOcclusionPolys\t\t\t= 0;\r\n\tNextOcclusionPolyToCheck\t= 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CheckForOptimalOccluders( Mth::Vector &cam_pos, Mth::Vector &view_direction )\r\n{\r\n\tif( NumOcclusionPolys > 0 )\r\n\t{\r\n\t\tuint32 added\t= 0;\r\n\t\tuint32 checked\t= 0;\r\n\r\n\t\twhile( added < MAX_NEW_OCCLUSION_POLYS_TO_CHECK_PER_FRAME )\r\n\t\t{\r\n\t\t\t// Given the current position of the camera, check through the unused, available occlusion polys to see if one scores higher\r\n\t\t\t// than the lowest scoring occlusion poly in use.\r\n\t\t\tsOcclusionPoly *poly_to_check = &OcclusionPolys[NextOcclusionPolyToCheck++];\r\n\t\t\tif(( !poly_to_check->in_use ) && ( poly_to_check->available ))\r\n\t\t\t{\r\n\t\t\t\tsOccluder::add_to_stack( poly_to_check );\r\n\t\t\t\t++added;\r\n\t\t\t}\r\n\t\t\t++checked;\r\n\r\n\t\t\t// Ensure we are always checking within bounds.\r\n\t\t\tif( NextOcclusionPolyToCheck >= NumOcclusionPolys )\r\n\t\t\t{\r\n\t\t\t\tNextOcclusionPolyToCheck = 0;\r\n\t\t\t}\r\n\r\n\t\t\t// Quit out if we have less available occluders than spaces to fill.\r\n\t\t\tif( checked >= NumOcclusionPolys )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n//char scratch[16384];\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid BuildOccluders( Mth::Vector *p_cam_pos, int view )\r\n{\r\n//\tfor( uint32 i = 0; i < NumOcclusionPolys; ++i )\r\n//\t{\r\n//\t\tGfx::AddDebugLine( OcclusionPolys[i].verts[0], OcclusionPolys[i].verts[1], 0, 0, 1 );\r\n//\t\tGfx::AddDebugLine( OcclusionPolys[i].verts[1], OcclusionPolys[i].verts[2], 0, 0, 1 );\r\n//\t\tGfx::AddDebugLine( OcclusionPolys[i].verts[2], OcclusionPolys[i].verts[3], 0, 0, 1 );\r\n//\t\tGfx::AddDebugLine( OcclusionPolys[i].verts[3], OcclusionPolys[i].verts[0], 0, 0, 1 );\r\n//\t}\r\n\t\r\n\t// Set the current view - this will remain active until another call to this function.\r\n\tDbg_Assert( (uint32)view < MAX_VIEWS_PER_OCCLUDER );\r\n\tCurrentView\t= view;\r\n\t\r\n\t// Tidy up from last frame.\r\n\tsOccluder::tidy_stack();\r\n\t\r\n\t// Cyclically add more occluders for checking.\r\n\tCheckForOptimalOccluders( *p_cam_pos, *p_cam_pos );\r\n\t\r\n\t// Build all 5 planes for each occluder.\r\n\tMth::Vector u0, u1, p;\r\n\r\n\t// The order in which the verts are used to build tha planes depends upon where the camera is in relation to the occlusion\r\n\t// poly. We use the default order when the viewpoint is on the side of the poly on which the default poly normal faces.\r\n\tfor( uint32 i = 0; i < sOccluder::NumOccluders; ++i )\r\n\t{\r\n\t\tsOcclusionPoly *p_poly = sOccluder::Occluders[i].p_poly;\r\n\r\n//\t\tGfx::AddDebugLine( p_poly->verts[0], p_poly->verts[1], 0, 0, 1 );\r\n//\t\tGfx::AddDebugLine( p_poly->verts[1], p_poly->verts[2], 0, 0, 1 );\r\n//\t\tGfx::AddDebugLine( p_poly->verts[2], p_poly->verts[3], 0, 0, 1 );\r\n//\t\tGfx::AddDebugLine( p_poly->verts[3], p_poly->verts[0], 0, 0, 1 );\r\n\t\t\r\n\t\tif( Mth::DotProduct( *p_cam_pos - p_poly->verts[0], p_poly->normal ) >= 0.0f )\r\n\t\t{\r\n\t\t\t// Start with the front. We want to reverse the order of the front plane to ensure that objects *behind* the plane\r\n\t\t\t// are considered occluded. (1->3->4)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[2] - p_poly->verts[0];\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[3] - p_poly->verts[0];\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, p_poly->verts[0] );\r\n\t\t\tsOccluder::Occluders[i].planes[0]\t= p;\r\n\r\n\t\t\t// ...then left (0->1->2)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[0] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[1] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[1]\t= p;\r\n\r\n\t\t\t// ...then right (0->3->4)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[2] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[3] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[2]\t= p;\r\n\r\n\t\t\t// ...then top (0->2->3)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[1] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[2] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[3]\t= p;\r\n\r\n\t\t\t// ...then bottom (0->4->1)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[3] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[0] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[4]\t= p;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Start with the front. We want to reverse the order of the front plane to ensure that objects *behind* the plane\r\n\t\t\t// are considered occluded. (1->4->3)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[3] - p_poly->verts[0];\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[2] - p_poly->verts[0];\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, p_poly->verts[0] );\r\n\t\t\tsOccluder::Occluders[i].planes[0]\t= p;\r\n\r\n\t\t\t// ...then left (0->2->1)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[1] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[0] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[1]\t= p;\r\n\r\n\t\t\t// ...then right (0->4->3)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[3] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[2] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[2]\t= p;\r\n\r\n\t\t\t// ...then top (0->3->2)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[2] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[1] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[3]\t= p;\r\n\r\n\t\t\t// ...then bottom (0->1->4)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[0] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[3] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[4]\t= p;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool TestSphereAgainstOccluders( Mth::Vector *p_sphere, uint32 meshes )\r\n{\r\n\t// Test against each occluder.\r\n\tfor( uint32 o = 0; o < sOccluder::NumOccluders; ++o )\r\n\t{\r\n\t\tbool occluded = true;\r\n\r\n\t\t// Test against each plane in the occluder.\r\n\t\tfor( uint32 p = 0; p < 5; ++p )\r\n\t\t{\r\n\t\t\tfloat result =\t( sOccluder::Occluders[o].planes[p][X] * p_sphere->GetX() ) +\r\n\t\t\t\t\t\t\t( sOccluder::Occluders[o].planes[p][Y] * p_sphere->GetY() ) +\r\n\t\t\t\t\t\t\t( sOccluder::Occluders[o].planes[p][Z] * p_sphere->GetZ() ) -\r\n\t\t\t\t\t\t\t( sOccluder::Occluders[o].planes[p][W] );\r\n\t\t\tif( result >= -p_sphere->GetW() )\r\n\t\t\t{\r\n\t\t\t\t// Outside of this plane, therefore not occluded by this occluder.\r\n\t\t\t\toccluded = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( occluded )\r\n\t\t{\r\n\t\t\t// Inside all planes, therefore occluded. Increase score for this occluder.\r\n\t\t\tsOccluder::Occluders[o].score[CurrentView] += meshes;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/occlude.h",
    "content": "#ifndef\t__OCCLUDE_H__\r\n#define\t__OCCLUDE_H__\r\n\r\nnamespace NxNgc\r\n{\r\n\tvoid AddOcclusionPoly( Mth::Vector &v0, Mth::Vector &v1, Mth::Vector &v2, Mth::Vector &v3, uint32 checksum = 0 );\r\n\tvoid EnableOcclusionPoly( uint32 checksum, bool available );\r\n\tvoid RemoveAllOcclusionPolys( void );\r\n\tvoid BuildOccluders( Mth::Vector *p_cam_pos, int view );\r\n\tbool TestSphereAgainstOccluders( Mth::Vector *p_sphere, uint32 meshes = 1 );\r\n}\r\n\r\n#endif\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/particles.cpp",
    "content": "//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n//**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//******************************************************************************\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tModule:\t\t\tGraphics (GFX)\t\t \t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tFile name:\t\tparticle.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tCreated:\t\t03/27/02\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tDescription:\tLow level particle rendering code\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//int gParticleMem = 0;\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\t\t\r\n//#include <core/math.h>\r\n//#include <gfx/debuggfx.h>\r\n//#include \"render.h\"\r\n//#include \"particles.h\"\r\n//#include \"scene.h\"\r\n//#include <gfx/ngc/nx/instance.h>\r\n//#include <gfx/ngc/p_nxmesh.h>\r\n//#include <gfx/NxTexMan.h>\r\n//#include <gfx/ngc/p_nxtexture.h>\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//namespace NxNgc\r\n//{\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//static BlendModes get_texture_blend( uint32 blend_checksum )\r\n//{\r\n//\tBlendModes rv = NxNgc::vBLEND_MODE_DIFFUSE;\r\n//\tswitch ( blend_checksum )\r\n//\t{\r\n//\t\tcase 0x54628ed7:\t\t// Blend\r\n//\t\t\trv = NxNgc::vBLEND_MODE_BLEND;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x02e58c18:\t\t// Add\r\n//\t\t\trv = NxNgc::vBLEND_MODE_ADD;\r\n//\t\t\tbreak;\r\n//\t\tcase 0xa7fd7d23:\t\t// Sub\r\n//\t\tcase 0xdea7e576:\t\t// Subtract\r\n//\t\t\trv = NxNgc::vBLEND_MODE_SUBTRACT;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x40f44b8a:\t\t// Modulate\r\n//\t\t\trv = NxNgc::vBLEND_MODE_MODULATE;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x68e77f40:\t\t// Brighten\r\n//\t\t\trv = NxNgc::vBLEND_MODE_BRIGHTEN;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x18b98905:\t\t// FixBlend\r\n//\t\t\trv = NxNgc::vBLEND_MODE_BLEND_FIXED;\r\n//\t\t\tbreak;\r\n//\t\tcase 0xa86285a1:\t\t// FixAdd\r\n//\t\t\trv = NxNgc::vBLEND_MODE_ADD_FIXED;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x0d7a749a:\t\t// FixSub\r\n//\t\tcase 0x0eea99ff:\t\t// FixSubtract\r\n//\t\t\trv = NxNgc::vBLEND_MODE_SUB_FIXED;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x90b93703:\t\t// FixModulate\r\n//\t\t\trv = NxNgc::vBLEND_MODE_MODULATE_FIXED;\r\n//\t\t\tbreak;\r\n//\t\tcase 0xb8aa03c9:\t\t// FixBrighten\r\n//\t\t\trv = NxNgc::vBLEND_MODE_BRIGHTEN_FIXED;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x515e298e:\t\t// Diffuse\r\n//\t\tcase 0x806fff30:\t\t// None\r\n//\t\t\trv = NxNgc::vBLEND_MODE_DIFFUSE;\r\n//\t\t\tbreak;\r\n//\t\tdefault:\r\n//\t\t\tDbg_MsgAssert(0,(\"Illegal blend mode specified. Please use (fix)blend/add/sub/modulate/brighten or diffuse/none.\"));\r\n//\t\t\tbreak;\r\n//\t}\r\n//\treturn rv;\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//sParticleSystem::sParticleSystem( uint32 max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix )\r\n//{\r\n//\t// Create a scene to store the mesh.\r\n//\tmp_scene = new sScene();\r\n//\r\n//\t// Get the texture.\r\n//\r\n//\tuint32 flags = MATFLAG_TRANSPARENT;\r\n//\tNx::CTexture *p_texture;\r\n//\tNx::CNgcTexture *p_ngc_texture;\r\n//\tNxNgc::sTexture * p_engine_texture = NULL;\r\n//\r\n//\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n//\tp_ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n//\tif ( p_ngc_texture )\r\n//\t{\r\n//\t\tp_engine_texture = p_ngc_texture->GetEngineTexture(); \r\n//\t\tflags |=MATFLAG_TEXTURED;\r\n//\t}\r\n//\r\n//\t// Create a material used to render the mesh.\r\n//\tsMaterial *p_material\t\t\t\t= new sMaterial();\r\n//\tp_material->m_sorted\t\t\t\t= 0;\r\n//\tp_material->m_no_bfc\t\t\t\t= 1;\r\n//\tp_material->Flags[0]\t\t\t\t= flags;\t\t// 0x40 makes it semitransparent.\r\n//\tp_material->Checksum\t\t\t\t= 0x5c41d978;\t// particle_system\t//(uint32)rand() * (uint32)rand();\r\n//\tp_material->Passes\t\t\t\t\t= 1;\r\n//\tp_material->pTex[0]\t\t\t\t\t= p_engine_texture;\r\n//\tp_material->blendMode[0]\t\t\t= (uint8)get_texture_blend( blendmode_checksum );\r\n//\tp_material->fixAlpha[0]\t\t\t\t= fix & 255;\r\n//\tp_material->UVAddressing[0]\t\t\t= 0;\r\n//\tp_material->matcol[0]\t\t\t\t= (GXColor){128,128,128,255};\r\n//\tp_material->AlphaCutoff\t\t\t\t= 1;\r\n//\tp_material->m_num_wibble_vc_anims\t= 0;\r\n//\tp_material->mp_wibble_vc_params\t\t= NULL;\r\n//\tp_material->mp_wibble_vc_colors\t\t= NULL;\r\n//\tp_material->m_pUVControl\t\t\t= NULL;\r\n//\r\n//\t// Create a hash table to store the material...\r\n//\tmp_scene->mp_material_array = p_material;\r\n//\tmp_scene->m_num_materials = 1;\r\n//\r\n//\t// Initialize the material (builds the display list).\r\n//\tInitializeMaterial( p_material );\r\n//\r\n//\t// Create a mesh which will be used to render the system.\r\n//\tmp_mesh = new sMesh();\r\n//\r\n//\t// Create a position buffer.\r\n//#ifdef SHORT_VERT\r\n//\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n//\tfloat *p_pos\t\t= new float[max_particles * 3 * 4];\r\n//\tMem::Manager::sHandle().PopContext();\r\n//\ts16 *p_pos16\t\t= new s16[max_particles * 3 * 4];\r\n//\tgParticleMem += max_particles * 3 * 4 * 2;\r\n//#else\r\n//\tfloat *p_pos\t\t= new float[max_particles * 3 * 4];\r\n//#endif\t\t// SHORT_VERT\r\n//\r\n//\tfor( uint32 lp = 0; lp < ( max_particles * 3 * 4 ); ++lp )\r\n//\t{\r\n//\t\tp_pos[lp] = 1024.0f;\r\n//#ifdef SHORT_VERT\r\n//\t\tp_pos16[lp] = (s16)(1024.0f*(1 << 0));\r\n//#endif\t\t// SHORT_VERT\r\n//\t}\r\n//\t\r\n//\t// Save pointer to bounding sphere so that the particle system can update it.\r\n//\tmp_sphere = mp_mesh->m_sphere;\r\n//\r\n//\t// Create an index buffer.\r\n//\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n//\tuint16 *p_indices\t= new uint16[(max_particles * 4)+2];\r\n//\tgParticleMem += ( (max_particles * 4)+2 ) * 2;\r\n//\tMem::Manager::sHandle().PopContext();\r\n//\r\n//\t// Fill the index buffer.\r\n//\tuint16 *p16 = p_indices;\r\n//\t*p16++ = max_particles * 4;\r\n//\tfor( uint32 i = 0; i < max_particles; ++i )\r\n//\t{\r\n//\t\t*p16++ = (uint16)i * 4 + 0;\r\n//\t\t*p16++ = (uint16)i * 4 + 1;\r\n//\t\t*p16++ = (uint16)i * 4 + 2;\r\n//\t\t*p16++ = (uint16)i * 4 + 3;\r\n//\t}\r\n//\t*p16++ = 0;\r\n//\t\r\n//\t// Create texture coordinates.\r\n//\ts16 *p_uv = NULL;\r\n//\tif ( p_engine_texture )\r\n//\t{\r\n//\t\tp_uv = new s16[max_particles * 2 * 4];\r\n//\t\tgParticleMem += max_particles * 2 * 4 * 2;\r\n//\r\n//\t\tfor( uint32 lp = 0; lp < max_particles; ++lp )\r\n//\t\t{\r\n//\t\t\tp_uv[(lp*2*4)+0] = (s16)(0.0f * ((float)(1<<10)));\r\n//\t\t\tp_uv[(lp*2*4)+1] = (s16)(0.0f * ((float)(1<<10)));\r\n//\t\t\tp_uv[(lp*2*4)+2] = (s16)(1.0f * ((float)(1<<10)));\r\n//\t\t\tp_uv[(lp*2*4)+3] = (s16)(0.0f * ((float)(1<<10)));\r\n//\t\t\tp_uv[(lp*2*4)+4] = (s16)(1.0f * ((float)(1<<10)));\r\n//\t\t\tp_uv[(lp*2*4)+5] = (s16)(1.0f * ((float)(1<<10)));\r\n//\t\t\tp_uv[(lp*2*4)+6] = (s16)(0.0f * ((float)(1<<10)));\r\n//\t\t\tp_uv[(lp*2*4)+7] = (s16)(1.0f * ((float)(1<<10)));\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t// Create Color list.\r\n//\tGXColor* p_color = new GXColor[max_particles * 4];\r\n//\tgParticleMem += max_particles * 4 * 2;\r\n//\r\n//\tfor( uint32 cc = 0; cc < max_particles; ++cc )\r\n//\t{\r\n//\t\tp_color[(cc*4)+0] = (GXColor){128,128,128,255};\r\n//\t\tp_color[(cc*4)+1] = (GXColor){128,128,128,255};\r\n//\t\tp_color[(cc*4)+2] = (GXColor){128,128,128,255};\r\n//\t\tp_color[(cc*4)+3] = (GXColor){128,128,128,255};\r\n//\t}\r\n//\t\r\n//\t// Set up the mesh.\r\n//\tmp_mesh->Initialize( max_particles * 4,\t\t// Num vertices\r\n//\t\t\t\t\t\tp_pos,\t\t\t\t\t// Positions\r\n//#ifdef SHORT_VERT\r\n//\t\t\t\t\t\tp_pos16,\r\n//\t\t\t\t\t\t0,\r\n//\t\t\t\t\t\t0.0f,\r\n//\t\t\t\t\t\t0.0f,\r\n//\t\t\t\t\t\t0.0f,\r\n//#endif\t\t// SHORT_VERT\r\n//\t\t\t\t\t\tNULL,\t\t\t\t\t// Normals\r\n//\t\t\t\t\t\tp_uv,\t\t\t\t\t// Texture coordinates\r\n//\t\t\t\t\t\t1,\t\t\t\t\t\t// Number of tc sets\r\n//\t\t\t\t\t\t(uint32*)p_color,\t\t// Colors\r\n//\t\t\t\t\t\tmax_particles * 4,\t\t// Num indices (4 per particle)\r\n//\t\t\t\t\t\tp_indices,\r\n//\t\t\t\t\t\tp_material->Checksum,\t// Material checksum\r\n//\t\t\t\t\t\tmp_scene,\r\n//\t\t\t\t\t\t0,\t\t\t\t\t\t// Double lists.\r\n//\t\t\t\t\t\tNULL,\r\n//\t\t\t\t\t\t0,\t\t\t\t\t\t// Single lists.\r\n//\t\t\t\t\t\t0,\t\t\t\t\t\t// local index of 0 means data will be deleted.\r\n//\t\t\t\t\t\tGX_QUADS,\t\t\t\t// Type of mesh. \r\n//\t\t\t\t\t\t0,\t\t\t\t\t\t// flags\r\n//\t\t\t\t\t\tNULL );\t\t\t\t\t// Wibble.\r\n//\r\n//#ifdef SHORT_VERT\r\n//\tdelete p_pos;\r\n//#endif\t\t// SHORT_VERT\r\n//\r\n////\t// Also adjust the bounding sphere and bounding box of the mesh.\r\n////\tp_mesh->m_sphere_center = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );\r\n////\tp_mesh->m_sphere_radius = 360.0f;\r\n////\tp_mesh->m_bbox.SetMin( Mth::Vector( -360.0f, -360.0f, -360.0f ));\r\n////\tp_mesh->m_bbox.SetMax( Mth::Vector(  360.0f,  360.0f,  360.0f ));\r\n//\t\r\n//\t// Now add the mesh to the scene.\r\n//\tmp_scene->CountMeshes( 1, &mp_mesh );\r\n//\tmp_scene->CreateMeshArrays();\r\n//\tmp_scene->AddMeshes( 1, &mp_mesh );\r\n//\tmp_scene->SortMeshes();\r\n//\r\n//\t// Create an instance and attach the mesh to it.\r\n//\tMth::Matrix temp;\r\n//\ttemp.GetRight().Set( 1.0f, 0.0f, 0.0f );\r\n//\ttemp.GetUp().Set( 0.0f, 1.0f, 0.0f );\r\n//\ttemp.GetAt().Set( 0.0f, 0.0f, 1.0f );\r\n//\ttemp.GetPos().Set( 0.0f, 0.0f, 0.0f );\r\n//\tmp_instance = new NxNgc::CInstance( mp_scene, temp, 1, NULL );\r\n//\r\n//\tmp_material = p_material;\r\n//\r\n//\tmp_engine_texture = p_engine_texture;\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//sParticleSystem::~sParticleSystem()\r\n//{\r\n// \t// Delete the single sMesh from the scene.\r\n//\tDbg_Assert( mp_scene->m_num_opaque_entries == 0 );\r\n//\tDbg_Assert( mp_scene->m_num_semitransparent_entries == 1 );\r\n//\tdelete mp_scene->m_semitransparent_meshes[0];\r\n//\t\r\n//\t// Deleting the sScene will also remove the material table (which removes the material).\r\n//\tDeleteScene( mp_scene );\r\n//\r\n//\tif ( mp_instance ) delete mp_instance;\r\n////\tmp_scene->RemoveMeshes( &mp_mesh );\r\n////\tdelete mp_mesh;\r\n////\tdelete mp_scene;\r\n////\tdelete mp_instance;\r\n//}\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void sParticleSystem::Render( void )\r\n//{\r\n////\trender_scene( mp_scene, NULL, vRENDER_OPAQUE );\r\n//\r\n////\t// Switch vertex buffers on the mesh.\r\n////\tmp_scene->m_opaque_meshes[0]->SwapVertexBuffers();\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//#ifdef SHORT_VERT\r\n//s16 *sParticleSystem::GetVertexWriteBuffer( void )\r\n//#else\r\n//float *sParticleSystem::GetVertexWriteBuffer( void )\r\n//#endif\t\t// SHORT_VERT\r\n//{\r\n//\treturn mp_scene->m_semitransparent_meshes[0]->mp_posBuffer;\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//GXColor *sParticleSystem::GetColorWriteBuffer( void )\r\n//{\r\n//\treturn (GXColor*)mp_scene->m_semitransparent_meshes[0]->mp_colBuffer;\r\n//}\r\n//\r\n//} // namespace NxNgc\r\n//\r\n//\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/particles.h",
    "content": "#ifndef\t__PARTICLE_H__\r\n#define\t__PARTICLE_H__\r\n\r\n#include \"gfx\\Ngc\\nx\\scene.h\"\r\n#include \"gfx\\Ngc\\nx\\instance.h\"\r\n#include \"gfx/ngc/nx/mesh.h\"\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n\r\nstruct sParticleSystem\r\n{\r\npublic:\r\n\t\t\t\tsParticleSystem( uint32 max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix );\r\n\t\t\t\t~sParticleSystem( void );\r\n\r\n\tvoid\t\tRender();\r\n#ifdef SHORT_VERT\r\n\ts16\t\t\t*GetVertexWriteBuffer( void );\r\n#else\r\n\tfloat\t\t*GetVertexWriteBuffer( void );\r\n#endif\t\t// SHORT_VERT\r\n\tGXColor\t\t*GetColorWriteBuffer( void );\r\n\tsMaterial*\tGetMaterial( void )\t\t\t{ return mp_material; }\r\n\tNxNgc::sTexture * GetTexture( void )\t{ return mp_engine_texture; }\r\n\r\n\tsScene*\t\tmp_scene;\r\n\r\n\tfloat* \t\tmp_sphere;\r\n\r\n\tCInstance*\tmp_instance;\r\n\r\n\tsMaterial*\tmp_material;\r\n\r\n\tsMesh*\t\tmp_mesh;\r\n\r\n\tNxNgc::sTexture * mp_engine_texture;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/render.cpp",
    "content": "#include <sys/profiler.h>\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <core/HashTable.h>\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include \"nx_init.h\"\r\n#include \"scene.h\"\r\n#include \"render.h\"\r\n#include <gfx\\ngc\\p_nxgeom.h>\r\n#include <gfx\\nxflags.h>\r\n#include \"occlude.h\"\r\n#include \t\"gfx/ngc/nx/mesh.h\"\r\n#include \"charpipeline\\skinning.h\"\r\n#include\t\"gfx\\NxMiscFX.h\"\r\n\r\n#include\t<sys/ngc\\p_camera.h>\r\n#include\t<sys/ngc\\p_frame.h>\r\n#include\t<sys/ngc\\p_prim.h>\r\n#include\t<sys/ngc\\p_render.h>\r\n\r\n#include \"dolphin/base/ppcwgpipe.h\"\r\n#include \"dolphin/gx/gxvert.h\"\r\n\r\nextern int g_object;\r\nextern int g_view_object;\r\nextern int g_material;\r\nextern NxNgc::sScene * g_view_scene;\r\n\r\n//extern u16 colorMap[];\r\n\r\nbool g_skip_correctable = 0;\r\n\r\n#define SHADOW_TEXTURE_SIZE 256\r\nextern uint8 * shadowTextureData;\r\nextern uint16 shadowPalette[16];\r\nextern uint8 * zTextureData;\r\nextern uint8 * blurTextureData;\r\nNxNgc::sMaterial * p_last_material = NULL;\r\nuint32 last_color_override = 0;\r\nuint16\tlast_mesh_flags = 0;\r\nbool last_correct = true;\r\nbool reload_camera = false;\r\n\r\nMtx g_matrix0;\r\nMtx g_matrix90;\r\nMtx g_matrix180;\r\nMtx g_matrix270;\r\n\r\nMth::Vector g_shadow_object_pos;\r\n\r\nint g_kill_layer = -1;\r\n\r\nextern \"C\"\r\n{\r\nextern void FakeEnvMap( ROMtx m, s16 * srcPos, s16 * srcNorm, float * dstBase, u32 count );\r\nextern void FakeEnvMapSkin( ROMtx m, s16 * srcPosNorm, float * dstBase, u32 count );\r\nextern void FakeEnvMapFloat( ROMtx m, float * srcPos, s16 * srcNorm, float * dstBase, u32 count );\r\n}\r\n\r\nstatic float * sLastUV = NULL;\r\n\r\nstatic bool first_mat = false;\r\n//static bool one_mat = false;\r\n\r\nextern uint16 shadowPalette[16];\r\n\r\n//bool gOverDraw = false;\r\n\r\nbool gMeshUseCorrection = false;\r\nbool gMeshUseAniso = false;\r\n\r\nconst float CORRECTION_CUTOFF = ( 25.0f * 12.0f );\r\nconst float ANISO_CUTOFF = ( 100.0f * 12.0f );\r\n\r\nint meshes_considered = 0;\r\n\r\nnamespace NxNgc\r\n{\r\n\r\nLst::HashTable< sTextureProjectionDetails >\t*pTextureProjectionDetailsTable = NULL;\r\n\r\nNsCamera\tcurrent_cam;\r\n\r\n#ifdef SHORT_VERT\r\nstatic void cam_offset( float x, float y, float z )\r\n{\r\n\tMtx m;\r\n\r\n\tMTXTrans( m, x, y, z );\r\n\tMTXConcat( EngineGlobals.current_uploaded, m, m );\r\n\r\n    GX::LoadPosMtxImm( m, GX_PNMTX0 );\r\n}\r\n#endif\t\t// SHORT_VERT\r\n\r\n//static void reflect_uvs( sMesh * p_mesh, float * p_tex, s16 * p_posBuffer, s16 * p_normBuffer, int step )\r\n//{\r\n//\tif ( sLastUV == p_tex ) return;\r\n//\r\n//\t// Inverse transform the camera position by the local to world matrix.\r\n//\tNsMatrix mp;\r\n////\tNsMatrix mi;\r\n//\r\n//\tmp.copy( *((NsMatrix*)EngineGlobals.current_uploaded) );\r\n////\tmp.copy( EngineGlobals.camera );\r\n//#ifdef SHORT_VERT\r\n//\tNsVector v( p_mesh->m_offset_x, p_mesh->m_offset_y, p_mesh->m_offset_z );\r\n//\tmp.translate( &v, NsMatrix_Combine_Post );\r\n//#endif\t\t// SHORT_VERT\r\n////\tmi.invert( mp );\r\n////\tmp.setRight( mi.getRight() );\r\n////\tmp.setUp( mi.getUp() );\r\n////\tmp.setAt( mi.getAt() );\r\n//\r\n////\tmp.invert();\r\n//\r\n////\tmp.setPosX( mi.getPosX() );\r\n////\tmp.setPosY( mi.getPosY() );\r\n////\tmp.setPosZ( mi.getPosZ() );\r\n//\t\r\n//\tROMtx sm;\r\n//\r\n//\tsm[0][0] = mp.getRightX();\r\n//\tsm[1][0] = mp.getRightY();\r\n//\tsm[2][0] = mp.getRightZ();\r\n//\t\t\t\t\t   \r\n//\tsm[0][1] = mp.getUpX();\r\n//\tsm[1][1] = mp.getUpY();\r\n//\tsm[2][1] = mp.getUpZ();\r\n//\t\t\t\t\t   \r\n//\tsm[0][2] = mp.getAtX();\r\n//\tsm[1][2] = mp.getAtY();\r\n//\tsm[2][2] = mp.getAtZ();\r\n//\t\t\t     \r\n//\tsm[3][0] = mp.getPosX();\r\n//\tsm[3][1] = mp.getPosY();\r\n//\tsm[3][2] = mp.getPosZ();\r\n//\r\n//\tif ( step == 6 )\r\n//\t{\r\n//\t\t// Skinned\r\n//\t\tFakeEnvMapSkin( sm, p_posBuffer, p_tex, p_mesh->m_num_vertex );\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\t// Not Skinned\r\n//\t\tGQRSetup6( p_mesh->m_vertex_format - 1,\t\t// Pos\r\n//\t\t\t\t   GQR_TYPE_S16,\r\n//\t\t\t\t   0,\t\t\t\t\t// UV\r\n//\t\t\t\t   GQR_TYPE_F32 );\r\n//\r\n//\t\tGQRSetup7( 14,\t\t// Normal\r\n//\t\t\t\t   GQR_TYPE_S16,\r\n//\t\t\t\t   0,\t\t\t\t\t// UV\r\n//\t\t\t\t   GQR_TYPE_F32 );\r\n//\r\n////\t\tNsMatrix mn;\r\n////\t\tmn.copy( mp );\r\n//////\t\tmn.invert(;\r\n////\t\tmn.setPos( 0.0f, 0.0f, 0.0f );\r\n////\r\n////\t\tfloat shift = (float)(1<<(p_mesh->m_vertex_format-1));\r\n////\t\tfor ( int lp = 0; lp < p_mesh->m_num_vertex; lp++ )\r\n////\t\t{\r\n////\t\t\tNsVector in, tpos, tnorm;\r\n////\t\t\tin.x = (((float)p_posBuffer[(lp*3)+0])/shift);\r\n////\t\t\tin.y = (((float)p_posBuffer[(lp*3)+1])/shift);\r\n////\t\t\tin.z = (((float)p_posBuffer[(lp*3)+2])/shift);\r\n////\t\t\tmp.multiply( &in, &tpos );\r\n////\t\t\tin.x = (((float)p_normBuffer[(lp*3)+0])/(float)(1<<14));\r\n////\t\t\tin.y = (((float)p_normBuffer[(lp*3)+1])/(float)(1<<14));\r\n////\t\t\tin.z = (((float)p_normBuffer[(lp*3)+2])/(float)(1<<14));\r\n////\t\t\tmn.multiply( &in, &tnorm );\r\n//////\t\t\tfloat z1 = 1.0f / 2000.0f;\r\n//////\t\t\tp_tex[(lp*2)+0] = ( ( ( ( ( tpos.x / (tpos.z+(float)gAdd) ) * (float)gScale ) + tnorm.x ) + 1.0f ) * 0.5f ) * (float)gRepeat;\r\n//////\t\t\tp_tex[(lp*2)+1] = ( ( ( ( ( tpos.y / (tpos.z+(float)gAdd) ) * (float)gScale )  + tnorm.y ) + 1.0f ) * 0.5f ) * (float)gRepeat;\r\n////\t\t\t\r\n////\t\t\tp_tex[(lp*2)+0] = ( ( ( ( ( tpos.x / ( tpos.z > 1 ? 1 : tpos.z ) ) + tnorm.x ) * 1.0f ) * 0.5f ) + 0.5f );\r\n////\t\t\tp_tex[(lp*2)+1] = ( ( ( ( ( tpos.y / ( tpos.z > 1 ? 1 : tpos.z ) ) + tnorm.y ) * 1.0f ) * 0.5f ) + 0.5f );\r\n////\r\n//////\t\t\tp_tex[(lp*2)+0] = ( ( ( ( tpos.x + ( tnorm.x * tpos.z ) ) * ( 0.5f * tpos.z ) ) * ( 3.0f * tpos.z ) ) + ( 0.5f * tpos.z ) );\r\n//////\t\t\tp_tex[(lp*2)+1] = ( ( ( ( tpos.y + ( tnorm.y * tpos.z ) ) * ( 0.5f * tpos.z ) ) * ( 3.0f * tpos.z ) ) + ( 0.5f * tpos.z ) );\r\n////\t\t\t\r\n//////\t\t\tp_tex[(lp*2)+0] = ( ( tnorm.x ) + 1.0f ) * 0.5f;\r\n//////\t\t\tp_tex[(lp*2)+1] = ( ( tnorm.y ) + 1.0f ) * 0.5f;\r\n////\t\t}\r\n//\r\n//\t\tFakeEnvMap( sm, p_posBuffer, p_normBuffer, p_tex, p_mesh->m_num_vertex );\r\n//\r\n//\t\t// GQR back to normal.\r\n//\t\tGQRSetup7( GQR_SCALE_128,\t\t// Pos/Normal\r\n//\t\t\t\t   GQR_TYPE_S16,\r\n//\t\t\t\t   GQR_SCALE_128,\r\n//\t\t\t\t   GQR_TYPE_S16 );\r\n//\t\tGQRSetup6( GQR_SCALE_256,\t\t// Weights\r\n//\t\t\t\t   GQR_TYPE_U8,\r\n//\t\t\t\t   GQR_SCALE_256,\r\n//\t\t\t\t   GQR_TYPE_U8 );\r\n//\t}\r\n//\tsLastUV = p_tex;\r\n//}\r\n\r\n#ifndef SHORT_VERT\r\n//static void float_reflect_uvs( sMesh * p_mesh, float * p_tex, float * p_posBuffer, s16 * p_normBuffer, int step )\r\n//{\r\n//\tif ( sLastUV == p_tex ) return;\r\n//\r\n//\t// Inverse transform the camera position by the local to world matrix.\r\n//\tNsMatrix mp;\r\n//\r\n//\tmp.copy( *((NsMatrix*)EngineGlobals.current_uploaded) );\r\n//\t\r\n//\tROMtx sm;\r\n//\r\n//\tsm[0][0] = mp.getRightX();\r\n//\tsm[1][0] = mp.getRightY();\r\n//\tsm[2][0] = mp.getRightZ();\r\n//\t\t\t\t\t   \r\n//\tsm[0][1] = mp.getUpX();\r\n//\tsm[1][1] = mp.getUpY();\r\n//\tsm[2][1] = mp.getUpZ();\r\n//\t\t\t\t\t   \r\n//\tsm[0][2] = mp.getAtX();\r\n//\tsm[1][2] = mp.getAtY();\r\n//\tsm[2][2] = mp.getAtZ();\r\n//\t\t\t     \r\n//\tsm[3][0] = mp.getPosX();\r\n//\tsm[3][1] = mp.getPosY();\r\n//\tsm[3][2] = mp.getPosZ();\r\n//\r\n////\tGQRSetup6( 0,\t\t\t\t\t// Pos\r\n////\t\t\t   GQR_TYPE_F32,\r\n////\t\t\t   0,\t\t\t\t\t// UV\r\n////\t\t\t   GQR_TYPE_F32 );\r\n////\r\n////\tGQRSetup7( 14,\t\t\t\t\t// Normal\r\n////\t\t\t   GQR_TYPE_S16,\r\n////\t\t\t   0,\t\t\t\t\t// UV\r\n////\t\t\t   GQR_TYPE_F32 );\r\n//\r\n//\tFakeEnvMapFloat( sm, p_posBuffer, p_normBuffer, p_tex, p_mesh->m_num_vertex );\r\n//\r\n////\t// GQR back to normal.\r\n////\tGQRSetup7( GQR_SCALE_128,\t\t// Pos/Normal\r\n////\t\t\t   GQR_TYPE_S16,\r\n////\t\t\t   GQR_SCALE_128,\r\n////\t\t\t   GQR_TYPE_S16 );\r\n////\tGQRSetup6( GQR_SCALE_256,\t\t// Weights\r\n////\t\t\t   GQR_TYPE_U8,\r\n////\t\t\t   GQR_SCALE_256,\r\n////\t\t\t   GQR_TYPE_U8 );\r\n//\tsLastUV = p_tex;\r\n//}\r\n#endif\t// SHORT_VERT\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid init_render_system( void )\r\n{\r\n\tpTextureProjectionDetailsTable = new Lst::HashTable< sTextureProjectionDetails >( 8 );\r\n\r\n\tMTXRotDeg( g_matrix0, 'y', 0.0f );\r\n\tMTXRotDeg( g_matrix90, 'y', 90.0f );\r\n\tMTXRotDeg( g_matrix180, 'y', 180.0f );\r\n\tMTXRotDeg( g_matrix270, 'y', 270.0f );\r\n}\r\n\r\nvoid set_blend_mode( uint64 mode )\r\n{\r\n\t// Low 32 bits contain the mode, high 32 bits contain the fixed alpha value.\r\n\tuint32 actual_mode\t= (uint32)mode;\r\n//\tuint32 fixed_alpha\t= (uint32)( mode >> 32 );\r\n\r\n\t// Only do something if the blend mode is changing.\r\n//\tif( actual_mode != EngineGlobals.blend_mode_value )\r\n\t{\r\n\t\tswitch( actual_mode )\r\n\t\t{\r\n\t\t\tcase vBLEND_MODE_ADD:\r\n\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\t\t\tGX::SetBlendMode ( GX_BM_SUBTRACT, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase vBLEND_MODE_BLEND:\r\n\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\tcase vBLEND_MODE_MODULATE:\r\n\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase vBLEND_MODE_DIFFUSE:\r\n\t\t\tdefault:\r\n\t\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\nvoid set_render_state( uint32 type, uint32 state )\r\n{\r\n\tswitch( type )\r\n\t{\r\n\t\tcase RS_ZWRITEENABLE:\r\n\t\t{\r\n\t\t\tif( state > 0 )\r\n\t\t\t{\r\n\t\t\t\tif( EngineGlobals.z_write_enabled == FALSE )\r\n\t\t\t\t{\r\n\t\t\t\t\tGX::SetZMode ( EngineGlobals.z_test_enabled ? GX_TRUE : GX_FALSE, EngineGlobals.z_test_enabled ? GX_LEQUAL : GX_ALWAYS, GX_TRUE );\r\n\t\t\t\t\tEngineGlobals.z_write_enabled = TRUE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( EngineGlobals.z_write_enabled == TRUE )\r\n\t\t\t\t{\r\n\t\t\t\t\tGX::SetZMode ( EngineGlobals.z_test_enabled ? GX_TRUE : GX_FALSE, EngineGlobals.z_test_enabled ? GX_LEQUAL : GX_ALWAYS, GX_FALSE );\r\n\t\t\t\t\tEngineGlobals.z_write_enabled = FALSE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase RS_ZTESTENABLE:\r\n\t\t{\r\n\t\t\tif( state > 0 )\r\n\t\t\t{\r\n\t\t\t\tif( EngineGlobals.z_test_enabled == FALSE )\r\n\t\t\t\t{\r\n\t\t\t\t\tGX::SetZMode ( GX_TRUE, GX_LEQUAL, EngineGlobals.z_write_enabled ? GX_TRUE : GX_FALSE );\r\n\t\t\t\t\tEngineGlobals.z_test_enabled = TRUE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( EngineGlobals.z_test_enabled == TRUE )\r\n\t\t\t\t{\r\n\t\t\t\t\tGX::SetZMode ( GX_FALSE, GX_ALWAYS, EngineGlobals.z_write_enabled ? GX_TRUE : GX_FALSE );\r\n\t\t\t\t\tEngineGlobals.z_test_enabled = FALSE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase RS_ALPHACUTOFF:\r\n\t\t{\r\n//\t\t\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t\t\t// Convert from state (where 1 means \"render all pixels with alpha 1 or higher\") to the D3D\r\n//\t\t\tif( state != EngineGlobals.alpha_ref )\r\n//\t\t\t{\r\n//\t\t\t\tEngineGlobals.alpha_ref = state;\r\n//\t\t\t\tif( state > 0 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_ALPHAFUNC,\t\t\tD3DCMP_GREATEREQUAL );\r\n//\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_ALPHAREF,\t\t\tstate );\r\n//\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_ALPHATESTENABLE,\tTRUE );\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_ALPHATESTENABLE,\tFALSE );\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nfloat frustum_sort_mid( Mth::Vector& p_sphere )\r\n{\r\n\tNsVector\ttest_in;\r\n\tNsVector\ttest_mid;\r\n\t\r\n//\tD3DXMATRIX *p_world_transform;\r\n//\t\r\n//\t// Build the composite transform if required.\r\n//\tif( p_bbox_transform )\r\n//\t{\r\n//\t\tp_world_transform = p_bbox_transform;\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tp_world_transform = NULL;\r\n//\t}\r\n\t\r\n\ttest_in.x\t= p_sphere[X];\r\n\ttest_in.y\t= p_sphere[Y];\r\n\ttest_in.z\t= p_sphere[Z];\r\n\r\n\tEngineGlobals.local_to_camera.multiply( &test_in, &test_mid );\r\n\t\r\n//\tif( p_world_transform )\r\n//\t{\r\n//\t\tD3DXVec3Transform( &test_mid, &test_in, p_world_transform );\r\n//\t\ttest_in.x = test_mid.x;\r\n//\t\ttest_in.y = test_mid.y;\r\n//\t\ttest_in.z = test_mid.z;\r\n//\t}\r\n//\tD3DXVec3Transform( &test_mid, &test_in, &EngineGlobals.view_matrix );\r\n\treturn test_mid.z;\r\n}\t\t\r\n\r\n\r\n\r\nstruct sSortedMeshEntry\r\n{\r\n\tsMesh\t\t\t\t*p_mesh;\r\n\tfloat\t\t\t\tsort;\r\n\tsSortedMeshEntry\t*pNext;\r\n};\r\n\r\n\r\n//static sSortedMeshEntry\tsortedMeshArray[1000];\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int cmp( const void *p1, const void *p2 )\r\n{\r\n\treturn((sSortedMeshEntry*)p1)->sort < ((sSortedMeshEntry*)p2)->sort ? -1 : ((sSortedMeshEntry*)p1)->sort > ((sSortedMeshEntry*)p2)->sort ? 1 : 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid create_texture_projection_details( sTexture *p_texture, Nx::CNgcModel *p_model, sScene *p_scene )\r\n{\r\n\tsTextureProjectionDetails *p_details = new sTextureProjectionDetails;\r\n\r\n\tp_details->p_model\t\t= p_model;\r\n\tp_details->p_scene\t\t= p_scene;\r\n\tp_details->p_texture\t= p_texture;\r\n\t\r\n\t// Flag this scene as receiving shadows.\r\n//\tp_scene->m_flags\t\t|= SCENE_FLAG_RECEIVE_SHADOWS;\r\n\t\r\n\tpTextureProjectionDetailsTable->PutItem((uint32)p_texture, p_details );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid destroy_texture_projection_details( sTexture *p_texture )\r\n{\r\n\tsTextureProjectionDetails *p_details = pTextureProjectionDetailsTable->GetItem((uint32)p_texture );\r\n\tif( p_details )\r\n\t{\r\n\t\tpTextureProjectionDetailsTable->FlushItem((uint32)p_texture );\r\n\t\tdelete p_details;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid set_texture_projection_camera( sTexture *p_texture, NsVector * p_pos, NsVector * p_at )\r\n{\r\n//\tNsMatrix view_matrix;\r\n\r\n\tsTextureProjectionDetails *p_details = pTextureProjectionDetailsTable->GetItem((uint32)p_texture );\r\n\tif( p_details )\r\n\t{\r\n\t\tNsVector\tup;\r\n\t\t// Check for 'straight down' vector.\r\n\t\tif(( p_pos->x == p_at->x ) && ( p_pos->z == p_at->z ))\r\n\t\t{\r\n//\t\t\tD3DXMatrixLookAtRH( &p_details->view_matrix, p_pos, p_at, &D3DXVECTOR3( 0.0f, 0.0f, 1.0f ));\r\n\r\n\r\n\t\t\tup.set( 0.0f, 0.0f, 1.0f );\r\n\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tup.set( 0.0f, 1.0f, 0.0f );\r\n//\t\t\tD3DXMatrixLookAtRH( &p_details->view_matrix, p_pos, p_at, &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ));\r\n\t\t}\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n//\t\tNsVector screen_right;\r\n//\t\tNsVector screen_up;\r\n//\t\tscreen_right.cross( *p_at, up );\r\n//\t\tscreen_up.cross( screen_right, *p_at );\r\n//\r\n//\t\tscreen_right.normalize();\r\n//\t\tscreen_up.normalize();\r\n//\r\n//\t\tp_details->view_matrix.setRight( &screen_right );\r\n//\t\tp_details->view_matrix.setUp( &screen_up );\r\n//\t\tp_details->view_matrix.setAt( p_at );\r\n//\t\tp_details->view_matrix.setPos( p_pos );\r\n\t\tp_details->view_matrix.lookAt( p_pos, &up, p_at );\r\n\r\n\t\r\n\r\n//\t\tD3DXMatrixOrthoRH( &p_details->projection_matrix, 96.0f, 96.0f, 1.0f, 512.0f );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n//static D3DXMATRIX\tworld;\r\n//static D3DXMATRIX\tview;\r\n//static D3DXMATRIX\tprojection;\r\n\r\nvoid set_camera( Mth::Matrix *p_matrix, Mth::Vector *p_position, float screen_angle, float aspect_ratio, float scale )\r\n{\r\n\tNsMatrix\tm;\r\n\tNsFrame\t\tf;\r\n\r\n\tEngineGlobals.tx = 2.0f * tanf(screen_angle*8.72664626e-03f);\t\t// tan of half (angle in radians)\r\n\tEngineGlobals.ty = -(EngineGlobals.tx / aspect_ratio);\r\n\tEngineGlobals.near\t= -2.0;\r\n\tEngineGlobals.far\t= -40000.0;\r\n\r\n\tcurrent_cam.perspective( EngineGlobals.tx, -EngineGlobals.ty, -EngineGlobals.near, -EngineGlobals.far * 2 );\r\n\r\n//\tif ( scale > 1.0f )\r\n//\t{\r\n//\t\tcurrent_cam.SetViewMatrix( 2, 2, -0.999999f );\r\n//\t\tcurrent_cam.SetViewMatrix( 3, 2, 0.0f );\r\n//\t}\r\n\r\n\tEngineGlobals.tx = tanf( Mth::DegToRad( screen_angle * 0.5f )); ;\t\t// tan of half (angle in radians)\r\n\tEngineGlobals.ty = -(EngineGlobals.tx / aspect_ratio);\r\n\tEngineGlobals.sx\t= 1.0f/sqrtf(1.0f+1.0f/(EngineGlobals.tx*EngineGlobals.tx));\r\n\tEngineGlobals.sy\t= 1.0f/sqrtf(1.0f+1.0f/(EngineGlobals.ty*EngineGlobals.ty));\r\n\tEngineGlobals.cx\t= 1.0f/sqrtf(1.0f+EngineGlobals.tx*EngineGlobals.tx);\r\n\tEngineGlobals.cy\t= 1.0f/sqrtf(1.0f+EngineGlobals.ty*EngineGlobals.ty);\r\n//\tEngineGlobals.near\t= -2.0;\r\n//\tEngineGlobals.far\t= -40000.0;\r\n\r\n\tm.setRight( -p_matrix->GetRight().GetX(), -p_matrix->GetRight().GetY(), -p_matrix->GetRight().GetZ() );\r\n\tm.setUp( p_matrix->GetUp().GetX(), p_matrix->GetUp().GetY(), p_matrix->GetUp().GetZ() );\r\n\tm.setAt( -p_matrix->GetAt().GetX(), -p_matrix->GetAt().GetY(), -p_matrix->GetAt().GetZ() );\r\n\tm.setPos( p_position->GetX(), p_position->GetY(), p_position->GetZ() );\r\n\r\n\tf.setModelMatrix( &m );\r\n\tcurrent_cam.setFrame( &f );\r\n\tcurrent_cam.begin();\t\t// No need to end...\r\n\r\n\tEngineGlobals.world_to_camera = *current_cam.getCurrent();\r\n\tEngineGlobals.local_to_camera = *current_cam.getCurrent();\r\n\tEngineGlobals.camera = m;\r\n\r\n\tEngineGlobals.object_pos.x = 0.0f;\r\n\tEngineGlobals.object_pos.y = 0.0f;\r\n\tEngineGlobals.object_pos.z = 0.0f;\r\n\r\n\tMTXCopy ( (MtxPtr)current_cam.getCurrent(), EngineGlobals.current_uploaded );\r\n\r\n\r\n//\tNsVector wscale( 1.0f, 1.0f, 1.0f );\t//scale, scale, scale );\r\n\tNsVector wscale( scale, scale, scale );\r\n\tNsMatrix ms;\r\n\tms.copy( m );\r\n\tms.scale( &wscale, NsMatrix_Combine_Pre );\r\n\r\n\tf.setModelMatrix( &ms );\r\n\tcurrent_cam.setFrame( &f );\r\n\tcurrent_cam.end();\r\n\tcurrent_cam.begin();\t\t// No need to end...\r\n\r\n//\tNsMatrix ms;\r\n//\tms.setRight( m.getRightX() * scale, m.getRightY() * scale, m.getRightZ() * scale );\r\n//\tms.setUp( m.getUpX() * scale, m.getUpY() * scale, m.getUpZ() * scale );\r\n//\tms.setAt( m.getAtX() * scale, m.getAtY() * scale, m.getAtZ() * scale );\r\n//\tms.setPos( m.getPosX(), m.getPosY(), m.getPosZ() );\r\n\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Checks a bounding box against the current view frustum\t\t  */\r\n/* (iBgnoring far clipping),\t\t\t\t\t\t\t\t\t\t  */\r\n/* returns true if any part is visible.\t\t\t\t\t\t\t  */\r\n/* Horribly inefficient at present.\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool frustum_check_box( Mtx m, Mth::CBBox& box )\r\n{\r\n\tVec\ttest_in, test_out;\r\n\t\r\n\tuint32\tcumulative_projection_space_outcode\t= 0xFF;\r\n\tfloat\tmin_x = box.GetMin().GetX();\r\n\tfloat\tmin_y = box.GetMin().GetY();\r\n\tfloat\tmin_z = box.GetMin().GetZ();\r\n\tfloat\tmax_x = box.GetMax().GetX();\r\n\tfloat\tmax_y = box.GetMax().GetY();\r\n\tfloat\tmax_z = box.GetMax().GetZ();\r\n\r\n\tfor( uint32 v = 0; v < 8; ++v )\r\n\t{\r\n\t\tuint32 projection_space_outcode = 0;\r\n\r\n\t\ttest_in.x = ( v & 0x04 ) ? max_x : min_x;\r\n\t\ttest_in.y = ( v & 0x02 ) ? max_y : min_y;\r\n\t\ttest_in.z = ( v & 0x01 ) ? max_z : min_z;\r\n\r\n\t\t// At this point it's important to check to see whether the point is in postive or negative z-space, since\r\n\t\t// after the projection transform, both very large camera space z values and camera space z values where z < 0\r\n\t\t// will give results with z > 1. (Camera space values in the range [0,near] give negative projection space z values).\r\n\t\tMTXMultVec( m, &test_in, &test_out );\r\n\r\n//\t\tif(( -test_mid.z < 0.0f ) && ( !EngineGlobals.is_orthographic ))\r\n//\t\t{\r\n//\t\t\ttest_out.x = -test_out.x;\r\n//\t\t\ttest_out.y = -test_out.y;\r\n//\t\t}\r\n\r\n\t\tif( test_out.x > 1.0f )\r\n\t\t{\r\n\t\t\tprojection_space_outcode |= 0x01;\r\n\t\t}\r\n\t\telse if( test_out.x < -1.0f )\r\n\t\t{\r\n\t\t\tprojection_space_outcode |= 0x02;\r\n\t\t}\r\n\r\n\t\tif( test_out.y > 1.0f )\r\n\t\t{\r\n\t\t\tprojection_space_outcode |= 0x04;\r\n\t\t}\r\n\t\telse if( test_out.y < -1.0f )\r\n\t\t{\r\n\t\t\tprojection_space_outcode |= 0x08;\r\n\t\t}\r\n\r\n\t\tcumulative_projection_space_outcode\t&= projection_space_outcode;\r\n\r\n\t\tif( cumulative_projection_space_outcode == 0 )\r\n\t\t{\r\n\t\t\t// Early out.\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool frustum_check_sphere( Mtx m, Mth::Vector& p_sphere )\r\n{\r\n//\tVec in;\r\n//\tVec out;\r\n//\r\n//\tin.x = p_sphere[X];\r\n//\tin.y = p_sphere[Y];\r\n//\tin.z = p_sphere[Z];\r\n//\r\n////\tNsMatrix mat;\r\n////\tmat.copy( EngineGlobals.local_to_camera );\r\n////\tNsVector s( 0.5f, 0.5f, 0.5f );\r\n////\tmat.scale( &s, NsMatrix_Combine_Post );\r\n////\r\n////\r\n////\tmat.multiply( &in, &out );\r\n////\tEngineGlobals.local_to_camera.multiply( &in, &out );\r\n//\r\n//\tMTXMultVec( m, &in, &out );\r\n//\r\n//\tfloat x = out.x;\r\n//\tfloat y = out.y;\r\n//\tfloat z = out.z;\r\n//\tfloat R = p_sphere[W];\r\n//\r\n//\tif ( R < ( z - EngineGlobals.near ) ) return false;\r\n//\tif ( R < ( EngineGlobals.far - z ) ) return false;\r\n//\r\n//\tfloat sx_z = EngineGlobals.sx * z;\r\n//\tfloat cx_x = EngineGlobals.cx * x;\r\n//\tif ( R < ( sx_z - cx_x ) ) return false;\r\n//\tif ( R < ( sx_z + cx_x ) ) return false; \r\n//\r\n//\tfloat sy_z = EngineGlobals.sy * z;\r\n//\tfloat cy_y = EngineGlobals.cy * y;\r\n//\tif ( R < ( sy_z - cy_y ) ) return false;\r\n//\tif ( R < ( sy_z + cy_y ) ) return false; \r\n//\r\n//\treturn true;\r\n\r\n\tMth::CBBox bbox;\r\n\tMth::Vector p;\r\n\t\r\n\tp.Set( p_sphere[X] + p_sphere[W], p_sphere[Y], p_sphere[Z] ); bbox.AddPoint( p );\r\n\tp.Set( p_sphere[X] - p_sphere[W], p_sphere[Y], p_sphere[Z] ); bbox.AddPoint( p );\r\n\tp.Set( p_sphere[X] , p_sphere[Y]+ p_sphere[W], p_sphere[Z] ); bbox.AddPoint( p );\r\n\tp.Set( p_sphere[X] , p_sphere[Y]- p_sphere[W], p_sphere[Z] ); bbox.AddPoint( p );\r\n\tp.Set( p_sphere[X] , p_sphere[Y], p_sphere[Z]+ p_sphere[W] ); bbox.AddPoint( p );\r\n\tp.Set( p_sphere[X] , p_sphere[Y], p_sphere[Z]- p_sphere[W] ); bbox.AddPoint( p );\r\n\r\n\treturn frustum_check_box( m, bbox );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Checks a bounding box against the current view frustum\t\t  */\r\n/* (iBgnoring far clipping),\t\t\t\t\t\t\t\t\t\t  */\r\n/* returns true if any part is visible.\t\t\t\t\t\t\t  */\r\n/* Horribly inefficient at present.\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool frustum_check_box( Mth::CBBox& box )\r\n{\r\n\tint\t\t\t\tlp;\r\n\tunsigned int\tcode;\r\n\tunsigned int\tcodeAND;\r\n\tf32\t\t\t\trx[8], ry[8], rz[8];\r\n\tf32\t\t\t\tp[GX_PROJECTION_SZ];\r\n\tf32\t\t\t\tvp[GX_VIEWPORT_SZ];\r\n\tu32\t\t\t\tclip_x;\r\n\tu32\t\t\t\tclip_y;\r\n\tu32\t\t\t\tclip_w;\r\n\tu32\t\t\t\tclip_h;\r\n\tfloat\t\t\tclip_l;\r\n\tfloat\t\t\tclip_t;\r\n\tfloat\t\t\tclip_r;\r\n\tfloat\t\t\tclip_b;\r\n\tMtxPtr\t\t\tview;\r\n\tfloat\t\t\tminx, miny, minz;\r\n\tfloat\t\t\tmaxx, maxy, maxz;\r\n\r\n\tGX::GetProjectionv( p );\r\n\tGX::GetViewportv( vp );\r\n\tGX::GetScissor ( &clip_x, &clip_y, &clip_w, &clip_h );\r\n\tclip_l = (float)clip_x;\r\n\tclip_t = (float)clip_y;\r\n\tclip_r = (float)(clip_x + clip_w);\r\n\tclip_b = (float)(clip_y + clip_h);\r\n\r\n\tview = (MtxPtr)&EngineGlobals.local_to_camera;\r\n\r\n\tminx = box.GetMin().GetX();\r\n\tminy = box.GetMin().GetY();\r\n\tminz = box.GetMin().GetZ();\r\n\tmaxx = box.GetMax().GetX();\r\n\tmaxy = box.GetMax().GetY();\r\n\tmaxz = box.GetMax().GetZ();\r\n\tGX::Project ( minx, miny, minz, view, p, vp, &rx[0], &ry[0], &rz[0] );\r\n\tGX::Project ( minx, maxy, minz, view, p, vp, &rx[1], &ry[1], &rz[1] );\r\n\tGX::Project ( maxx, miny, minz, view, p, vp, &rx[2], &ry[2], &rz[2] );\r\n\tGX::Project ( maxx, maxy, minz, view, p, vp, &rx[3], &ry[3], &rz[3] );\r\n\tGX::Project ( minx, miny, maxz, view, p, vp, &rx[4], &ry[4], &rz[4] );\r\n\tGX::Project ( minx, maxy, maxz, view, p, vp, &rx[5], &ry[5], &rz[5] );\r\n\tGX::Project ( maxx, miny, maxz, view, p, vp, &rx[6], &ry[6], &rz[6] );\r\n\tGX::Project ( maxx, maxy, maxz, view, p, vp, &rx[7], &ry[7], &rz[7] );\r\n\r\n\t// Generate clip code. {page 178, Procedural Elements for Computer Graphics}\r\n\t// 1001|1000|1010\r\n\t//     |    |\r\n\t// ----+----+----\r\n\t// 0001|0000|0010\r\n\t//     |    |\r\n\t// ----+----+----\r\n\t// 0101|0100|0110\r\n\t//     |    |\r\n\t//\r\n\t// Addition: Bit 4 is used for z behind.\r\n\r\n\tcodeAND\t= 0x001f;\r\n\tfor ( lp = 0; lp < 8; lp++ ) {\r\n\t\t// Only check x/y if z is valid (if z is invalid, the x/y values will be garbage).\r\n\t\tif ( rz[lp] > 1.0f   ) {\r\n\t\t\tcode = (1<<4);\r\n\t\t} else {\r\n\t\t\tcode = 0;\r\n\t\t\tif ( rx[lp] < clip_l ) code |= (1<<0);\r\n\t\t\tif ( rx[lp] > clip_r ) code |= (1<<1);\r\n\t\t\tif ( ry[lp] > clip_b ) code |= (1<<2);\r\n\t\t\tif ( ry[lp] < clip_t ) code |= (1<<3);\r\n\t\t}\r\n\t\tcodeAND\t&= code;\r\n\t\tif ( !codeAND ) return true;\r\n\t}\r\n\tif ( !codeAND ) return true;\r\n\treturn false;\r\n//\tm_cull.clipCodeAND = codeAND;\r\n//\t// If any bits are set in the AND code, the object is invisible.\r\n//\tif ( codeAND ) {\r\n//\t\tm_cull.visible = 0;\r\n//\t}\r\n//\t\r\n//\treturn !m_cull.visible;\t\t// 0 = not culled, 1 = culled.\r\n\r\n\r\n//\r\n//\tNsVector test_in, test_out;\r\n//\t\r\n//\tuint32\tcumulative_projection_space_outcode\t= 0xFF;\r\n//\tfloat\tmin_x = box.GetMin().GetX();\r\n//\tfloat\tmin_y = box.GetMin().GetY();\r\n//\tfloat\tmin_z = box.GetMin().GetZ();\r\n//\tfloat\tmax_x = box.GetMax().GetX();\r\n//\tfloat\tmax_y = box.GetMax().GetY();\r\n//\tfloat\tmax_z = box.GetMax().GetZ();\r\n//\r\n//\tfor( uint32 v = 0; v < 8; ++v )\r\n//\t{\r\n//\t\tuint32 projection_space_outcode = 0;\r\n//\r\n//\t\ttest_in.x = ( v & 0x04 ) ? max_x : min_x;\r\n//\t\ttest_in.y = ( v & 0x02 ) ? max_y : min_y;\r\n//\t\ttest_in.z = ( v & 0x01 ) ? max_z : min_z;\r\n//\r\n//\t\t// At this point it's important to check to see whether the point is in postive or negative z-space, since\r\n//\t\t// after the projection transform, both very large camera space z values and camera space z values where z < 0\r\n//\t\t// will give results with z > 1. (Camera space values in the range [0,near] give negative projection space z values).\r\n//\t\tEngineGlobals.local_to_camera.multiply( &test_in, &test_out );\r\n////\t\tMTXMultVec( m, &test_in, &test_out );\r\n//\r\n////\t\tif(( -test_mid.z < 0.0f ) && ( !EngineGlobals.is_orthographic ))\r\n////\t\t{\r\n////\t\t\ttest_out.x = -test_out.x;\r\n////\t\t\ttest_out.y = -test_out.y;\r\n////\t\t}\r\n//\r\n//\t\tif( test_out.x > 1.0f )\r\n//\t\t{\r\n//\t\t\tprojection_space_outcode |= 0x01;\r\n//\t\t}\r\n//\t\telse if( test_out.x < -1.0f )\r\n//\t\t{\r\n//\t\t\tprojection_space_outcode |= 0x02;\r\n//\t\t}\r\n//\r\n//\t\tif( test_out.y > 1.0f )\r\n//\t\t{\r\n//\t\t\tprojection_space_outcode |= 0x04;\r\n//\t\t}\r\n//\t\telse if( test_out.y < -1.0f )\r\n//\t\t{\r\n//\t\t\tprojection_space_outcode |= 0x08;\r\n//\t\t}\r\n//\r\n//\t\tcumulative_projection_space_outcode\t&= projection_space_outcode;\r\n//\r\n//\t\tif( cumulative_projection_space_outcode == 0 )\r\n//\t\t{\r\n//\t\t\t// Early out.\r\n//\t\t\treturn true;\r\n//\t\t}\r\n//\t}\r\n//\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/* Quick determination of if something is visible or not, uses\t  */\r\n/* the previously calculated s and c vectors and the\t\t\t  */\r\n/* WorldToCamera transform (note, no attempt is made to ensure\t  */\r\n/* this is the same camera that the object will eventually be\t  */\r\n/* rendered with.\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nbool IsVisible( Mth::Vector &sphere )\r\n{\r\n\tNsVector in;\r\n\tNsVector out;\r\n\r\n\tin.x = sphere.GetX();\r\n\tin.y = sphere.GetY();\r\n\tin.z = sphere.GetZ();\r\n\r\n\tEngineGlobals.world_to_camera.multiply( &in, &out );\r\n\r\n\tfloat x = out.x;\r\n\tfloat y = out.y;\r\n\tfloat z = out.z;\r\n\tfloat R = sphere[W];\r\n\t\r\n\tif(\t//( -z + R < EngineGlobals.near ) ||\r\n//\t   if ( R < ( -10000.0f/*EngineGlobals.far*/ - z ) ) return false;\r\n\t   ( R < ( z - EngineGlobals.near ) ) ||\r\n\t   ( R < ( EngineGlobals.far - z ) ) ||\r\n\r\n\t   ( R < EngineGlobals.sy * z + EngineGlobals.cy * y ) ||\r\n\t   ( R < EngineGlobals.sy * z - EngineGlobals.cy * y ) ||\r\n\t   ( R < EngineGlobals.sx * z - EngineGlobals.cx * x ) ||\r\n\t   ( R < EngineGlobals.sx * z + EngineGlobals.cx * x ))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( TestSphereAgainstOccluders( &sphere ))\r\n\t\t{\r\n\t\t\t// Occluded.\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n//\tif (R<z-near || R<far-z || R<sy*z+cy*y || R<sy*z-cy*y || R<sx*z-cx*x || R<sx*z+cx*x) visible = false;\r\n\r\n}\r\n\r\nbool frustum_check_sphere( Mth::Vector& p_sphere )\r\n{\r\n\tNsVector in;\r\n\tNsVector out;\r\n\r\n\tin.x = p_sphere[X];\r\n\tin.y = p_sphere[Y];\r\n\tin.z = p_sphere[Z];\r\n\r\n//\tNsMatrix mat;\r\n//\tmat.copy( EngineGlobals.local_to_camera );\r\n//\tNsVector s( 0.5f, 0.5f, 0.5f );\r\n//\tmat.scale( &s, NsMatrix_Combine_Post );\r\n//\r\n//\r\n//\tmat.multiply( &in, &out );\r\n\tEngineGlobals.local_to_camera.multiply( &in, &out );\r\n\r\n\tfloat x = out.x;\r\n\tfloat y = out.y;\r\n\tfloat z = out.z;\r\n\tfloat R = p_sphere[W];\r\n\t\r\n//\t// See if mesh is close enough to use color correction.\r\n//\tif ( ( -z - R ) < CORRECTION_CUTOFF )\r\n//\t{\r\n//\t\tgMeshUseCorrection = true;\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tgMeshUseCorrection = false;\r\n//\t}\r\n//\r\n//\t// See if mesh is close enough to use anisotropic filtering.\r\n//\tif ( ( -z - R ) < ANISO_CUTOFF )\r\n//\t{\r\n//\t\tgMeshUseAniso = true;\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tgMeshUseAniso = false;\r\n//\t}\r\n\r\n\tif ( R < ( z - EngineGlobals.near ) ) return false;\r\n\tif ( R < ( EngineGlobals.far - z ) ) return false;\r\n\r\n\tfloat sx_z = EngineGlobals.sx * z;\r\n\tfloat cx_x = EngineGlobals.cx * x;\r\n\tif ( R < ( sx_z - cx_x ) ) return false;\r\n\tif ( R < ( sx_z + cx_x ) ) return false; \r\n\r\n\tfloat sy_z = EngineGlobals.sy * z;\r\n\tfloat cy_y = EngineGlobals.cy * y;\r\n\tif ( R < ( sy_z - cy_y ) ) return false;\r\n\tif ( R < ( sy_z + cy_y ) ) return false; \r\n\r\n\treturn true;\r\n}\r\n\r\nbool frustum_check_sphere( Mth::Vector& p_sphere, float * p_z )\r\n{\r\n\tbool visible = true;\r\n\r\n\tNsVector in;\r\n\tNsVector out;\r\n\r\n\tin.x = p_sphere[X];\r\n\tin.y = p_sphere[Y];\r\n\tin.z = p_sphere[Z];\r\n\r\n\tEngineGlobals.local_to_camera.multiply( &in, &out );\r\n\r\n\tfloat x = out.x;\r\n\tfloat y = out.y;\r\n\tfloat z = out.z;\r\n\tfloat R = p_sphere[W];\r\n\t\r\n\tif (R<z-EngineGlobals.near || R<EngineGlobals.far-z || R<EngineGlobals.sy*z+EngineGlobals.cy*y || R<EngineGlobals.sy*z-EngineGlobals.cy*y || R<EngineGlobals.sx*z-EngineGlobals.cx*x || R<EngineGlobals.sx*z+EngineGlobals.cx*x) visible = false;\r\n\r\n\tif ( p_z ) *p_z = out.z;\r\n\r\n\treturn visible;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid calculate_tex_proj_matrix( NsMatrix * p_tex_view_matrix, NsMatrix * p_tex_proj_matrix, NsMatrix * p_tex_transform_matrix, NsMatrix * p_world_matrix )\r\n{\r\n\t// Get the current view matrix.\r\n\tNsMatrix matView, matInvView;\r\n\r\n\tmatView.copy( EngineGlobals.camera );\r\n\tmatInvView.invert( matView );\r\n\r\n\tNsMatrix matBiasScale;\r\n    matBiasScale.identity();\r\n\r\n//#\tifdef TEST_SB\r\n//\tstatic float x0 = 256.0f;\r\n//\tstatic float y0 = 256.0f;\r\n//\t\r\n//\tmatBiasScale._11 = x0 * 0.5f;\r\n//\tmatBiasScale._22 = y0 * -0.5f;\r\n////\tmatBiasScale._11 = 0.5f;\r\n////\tmatBiasScale._22 = -0.5f;\r\n////\tmatBiasScale._33 = D3DZ_MAX_D16;\r\n//\tmatBiasScale._33 = D3DZ_MAX_D24S8;\r\n//#\telse\r\n//\tmatBiasScale._11 = 0.5f;\r\n//\tmatBiasScale._22 = -0.5f;\r\n//#\tendif\t\r\n\tmatBiasScale.setUpY( 0.5f );\r\n\tmatBiasScale.setAtZ( -0.5f );\r\n\r\n//#\tifdef TEST_SB\r\n//\tstatic float x1 = 256.0f;\r\n//\tstatic float y1 = 256.0f;\r\n//\t\r\n//\tmatBiasScale._41 = x1 * 0.5f + 0.5f;\r\n//\tmatBiasScale._42 = y1 * 0.5f + 0.5f;\r\n////\tmatBiasScale._41 = 0.5f;\r\n////\tmatBiasScale._42 = 0.5f;\r\n//#\telse\r\n//\tmatBiasScale._41 = 0.5f;\r\n//\tmatBiasScale._42 = 0.5f;\r\n//#\tendif\t\r\n\tmatBiasScale.setPosY( 0.5f );\r\n\tmatBiasScale.setPosZ( -0.5f );\r\n\r\n\tNsMatrix m_matTexProj;\r\n//#\tif defined( TEST_SB )\r\n//\t// Don't bother with inverse view transform for Shadow Buffer, since we are picking up world-space coordinates directly.\r\n//\tif( p_world_matrix )\r\n//\t{\r\n//\t\tm_matTexProj = *p_world_matrix;\t\t\t\t\t\t\t\t\t\t\t\t// Transform to world space.\r\n//\t\tD3DXMatrixMultiply( &m_matTexProj, &m_matTexProj, p_tex_view_matrix );\t\t// Transform to projection camera space.\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tm_matTexProj = *p_tex_view_matrix;\t\t\t\t\t\t\t\t\t\t\t// Transform to projection camera space.\r\n//\t}\r\n//\tD3DXMatrixMultiply( &m_matTexProj, &m_matTexProj, p_tex_proj_matrix );\t\t\t// Situate verts relative to projector's view\r\n//    D3DXMatrixMultiply( p_tex_transform_matrix, &m_matTexProj, &matBiasScale );\t\t// Scale and bias to map the near clipping plane to texcoords\r\n//#\telse\r\n//\tm_matTexProj = matInvView;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Transform cameraspace position to worldspace\r\n//\tD3DXMatrixMultiply( &m_matTexProj, &m_matTexProj, p_tex_view_matrix );\t\t\t// Transform to projection camera space.\r\n//    D3DXMatrixMultiply( &m_matTexProj, &m_matTexProj, p_tex_proj_matrix );\t\t\t// Situate verts relative to projector's view\r\n//    D3DXMatrixMultiply( p_tex_transform_matrix, &m_matTexProj, &matBiasScale );\t\t// Scale and bias to map the near clipping plane to texcoords\r\n//#\tendif\r\n\tm_matTexProj = matInvView;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Transform cameraspace position to worldspace\r\n\tm_matTexProj.cat( m_matTexProj, *p_tex_view_matrix );\r\n\tm_matTexProj.cat( m_matTexProj, *p_tex_proj_matrix );\r\n\tp_tex_transform_matrix->cat( m_matTexProj, matBiasScale );\r\n\r\n\t// This is just for displaying the frustum lines.\r\n/*\r\n    // Convert from homogeneous texmap coords to worldspace\r\n    D3DXMATRIX matInvTexView, matInvTexProj;\r\n    D3DXMatrixInverse( &matInvTexView, NULL, &matTexView );\r\n    D3DXMatrixInverse( &matInvTexProj, NULL, &matTexProj );          \r\n\r\n    for( int i = 0; i < 8; i++ )\r\n    {\r\n        D3DXVECTOR4 vT( 0.0f, 0.0f, 0.0f, 1.0f );\r\n        vT.x = (i%2) * ( i&0x2 ? -1.0f : 1.0f );\r\n        vT.y = (i%2) * ( i&0x4 ? -1.0f : 1.0f );\r\n        vT.z = (i%2) * ( 1.0f );\r\n\r\n        D3DXVec4Transform( &vT, &vT, &matInvTexProj );\r\n        D3DXVec4Transform( &vT, &vT, &matInvTexView );\r\n\r\n        g_FrustumLines[i].x = vT.x / vT.w;\r\n        g_FrustumLines[i].y = vT.y / vT.w;\r\n        g_FrustumLines[i].z = vT.z / vT.w;\r\n    }\r\n*/\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid render_shadow_targets( void )\r\n{\r\n\tGX::SetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE);\r\n//\tD3DXMATRIX stored_view_matrix\t\t= EngineGlobals.view_matrix;\r\n//\tD3DXMATRIX stored_projection_matrix\t= EngineGlobals.projection_matrix;\r\n\t\r\n\t// Goes through the list of render target textures, rendering to each one in turn.\r\n\tpTextureProjectionDetailsTable->IterateStart();\r\n\tsTextureProjectionDetails *p_details = pTextureProjectionDetailsTable->IterateNext();\r\n//\r\n//\t// Set the basic pixel shader that just copies a single color (in C0) over.\r\n//\tEngineGlobals.pixel_shader_constants[0]\t\t= 1.0f;\r\n//\tEngineGlobals.pixel_shader_constants[1]\t\t= 1.0f;\r\n//\tEngineGlobals.pixel_shader_constants[2]\t\t= 1.0f;\r\n//\tEngineGlobals.pixel_shader_constants[3]\t\t= 1.0f;\r\n//\tEngineGlobals.upload_pixel_shader_constants\t= true;\r\n//\tset_pixel_shader( PixelShader3 );\r\n//\tEngineGlobals.pixel_shader_override\t\t\t= PixelShader3;\r\n//\t\r\n\t// Clear background of shadow.\r\n//\tNsCamera cam;\r\n//\tcam.orthographic( 0, 0, 640, 448 );\r\n//\tcam.begin();\r\n//\r\n//\tGX::SetZMode ( GX_FALSE, GX_ALWAYS, GX_TRUE );\r\n//\t//NsPrim::box( 0, 0, 256, 256, (GXColor){128,128,128,255} );\r\n//\tfloat zf = -( EngineGlobals.far + 0.5f );\r\n//\tNsPrim::quad( 0, 0, zf, 640, 0, zf, 640, 448, zf, 0, 448, zf, (GXColor){128,128,128,255} );\r\n//\tcam.end();\r\n\r\n\twhile( p_details )\r\n\t{\r\n\t\tif( p_details->p_model )\r\n\t\t{\r\n\t\t\t// Set the new render target.\r\n///\t\t\tD3DDevice_SetRenderTarget( p_details->p_texture->pD3DSurface, NULL );\r\n//\r\n//\t\t\tD3DDevice_Clear( 0, 0, D3DCLEAR_TARGET, 0, 1.0f, 0 );\r\n\r\n\t\t\t// Set the view and projection transforms.\r\n//\t\t\tEngineGlobals.view_matrix\t\t= p_details->view_matrix;\r\n//\t\t\tEngineGlobals.projection_matrix\t= p_details->projection_matrix;\r\n//\t\t\tEngineGlobals.is_orthographic\t= true;\r\n\r\n\t\t\t// Render all instances for the CGeom's contained in this model.\r\n\t\t\tint num_geoms = p_details->p_model->GetNumGeoms();\r\n\t\t\tfor( int i = 0; i < num_geoms; ++i )\r\n\t\t\t{\r\n\t\t\t\tNx::CNgcGeom *p_ngc_geom\t= static_cast<Nx::CNgcGeom*>( p_details->p_model->GetGeomByIndex( i ));\r\n\t\t\t\tCInstance *p_instance\t\t= p_ngc_geom->GetInstance();\r\n\t\t\t\t\r\n\t\t\t\tif( p_instance->GetActive())\r\n\t\t\t\t{\r\n\t\t\t\t\t// Create the camera and attach a frame.\r\n\t\t\t\t\tNsCamera cam;\r\n\t\t\t\t\t//NsFrame frame;\r\n\t\t\t\t\t//cam.setFrame( &frame );\r\n\t\r\n\t\t\t\t\t// Assume parallel projection in this case.\r\n\t\t\t\t\tcam.orthographic();\r\n\t\t\t\t\tcam.orthographic( 0, 0, 256, 256 );\r\n\t\t\t\t\tcam.setViewWindow( 128, 128 );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Position the camera somewhere near the object, pointing directly at it.\r\n\t\t\t\t\tfloat\tat[3];\r\n\t\t\t\t\tfloat\tpos[3];\r\n\t\r\n\t\t\t\t\tat[0]\t= p_instance->GetTransform()->GetPos()[X];\r\n\t\t\t\t\tat[1]\t= p_instance->GetTransform()->GetPos()[Y];\r\n\t\t\t\t\tat[2]\t= p_instance->GetTransform()->GetPos()[Z];\r\n\t\r\n\t\t\t\t\tpos[0]\t= p_instance->GetTransform()->GetPos()[X];\r\n\t\t\t\t\tpos[1]\t= p_instance->GetTransform()->GetPos()[Y] + 64.0f;\r\n\t\t\t\t\tpos[2]\t= p_instance->GetTransform()->GetPos()[Z];\r\n\t\r\n\t\t\t\t\tg_shadow_object_pos = p_instance->GetTransform()->GetPos();\r\n\t\t\t\t\tg_shadow_object_pos[Y] += ( 12.0f * 3.0f );\t\t// Amount of leeway...\r\n\r\n\t\t\t\t\t// Also need to take account of the view offset.\r\n\t\t\t\t\tMth::Vector object_up\t= p_instance->GetTransform()->GetUp();\r\n\t\t\t\t\tat[0]\t+= object_up.GetX() * 36.0f;\r\n\t\t\t\t\tat[1]\t+= object_up.GetY() * 36.0f;\r\n\t\t\t\t\tat[2]\t+= object_up.GetZ() * 36.0f;\r\n\t\t\t\t\tpos[0]\t+= object_up.GetX() * 36.0f;\r\n\t\t\t\t\tpos[1]\t+= object_up.GetY() * 36.0f;\r\n\t\t\t\t\tpos[2]\t+= object_up.GetZ() * 36.0f;\r\n\t\r\n\t\t\t\t\tcam.pos( pos[0], pos[1], pos[2] );\r\n\t\t\t\t\tcam.up( 1.0f, 0.0f, 0.0f );\r\n\t\t\t\t\tcam.lookAt( at[0], at[1], at[2] );\r\n\t\r\n//\t\t\t\t\tEngineGlobals.world_to_camera.identity();\r\n//\t\t\t\t\tEngineGlobals.world_to_camera.setPos( pos[0], pos[1], pos[2] );\r\n//\t\t\t\t\tEngineGlobals.world_to_camera.setRight( 1.0f, 0.0f, 0.0f );\r\n//\t\t\t\t\tEngineGlobals.world_to_camera.setUp( 0.0f, 0.0f, 1.0f );\r\n//\t\t\t\t\tEngineGlobals.world_to_camera.setAt( 0.0f, -1.0f, 0.0f );\r\n\t\r\n\t\t\t\t\tcam.begin();\r\n\t\t\t\t\tMTXCopy ( (MtxPtr)cam.getCurrent(), EngineGlobals.current_uploaded );\r\n\t\r\n\t\t\t\t\tEngineGlobals.world_to_camera.copy( *cam.getCurrent() );\r\n\t\t\t\t\tEngineGlobals.shadow_camera.copy( *cam.getCurrent() );\r\n\t\r\n\t\t\t\t\t// Flag the scene as having the shadow version rendered.\r\n\t\t\t\t\tp_instance->GetScene()->m_flags |= SCENE_FLAG_RENDERING_SHADOW;\r\n\t\r\n\t\t\t\t\t// Render the model.\r\n//\t\t\t\t\tROMtx bone_mtx[60];\r\n//\t\t\t\t\tp_instance->Transform( vRENDER_SHADOW_1ST_PASS, bone_mtx, NULL );\r\n//\t\t\t\t\tp_instance->ClearFlag( NxNgc::CInstance::INSTANCE_FLAG_TRANSFORM_ME );\r\n\t\t\t\t\tp_instance->Render( vRENDER_SHADOW_1ST_PASS );\r\n\t\r\n\t\t\t\t\t// Clear the flag the scene as having the shadow version rendered.\r\n\t\t\t\t\tp_instance->GetScene()->m_flags &= ~SCENE_FLAG_RENDERING_SHADOW;\r\n\t\t\t\t\r\n\t\t\t\t\t// Flag the scene as self shadowing.\r\n\t\t\t\t\tp_instance->GetScene()->m_flags |= SCENE_FLAG_SELF_SHADOWS;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tp_details = pTextureProjectionDetailsTable->IterateNext();\r\n\t}\r\n//\r\n//\t// Pixel shader override no longer required.\r\n//\tEngineGlobals.pixel_shader_override = 0;\r\n//\t\r\n//\t// Restore the view and projection transforms.\r\n//\tEngineGlobals.view_matrix\t\t= stored_view_matrix;\r\n//\tEngineGlobals.projection_matrix\t= stored_projection_matrix;\r\n//\tEngineGlobals.is_orthographic\t= false;\r\n//\r\n//\t// Restore the world transform.\r\n//\tD3DDevice_SetTransform( D3DTS_WORLD, &EngineGlobals.world_matrix );\r\n//\t\r\n//\t// Restore the default render target.\r\n//\tD3DDevice_SetRenderTarget( EngineGlobals.p_RenderSurface, EngineGlobals.p_ZStencilSurface );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid render_shadow_meshes( sScene *p_scene, int *p_mesh_indices, int num_meshes )\r\n{\r\n}\r\n\r\n\r\nvoid figure_wibble_vc( sScene *p_scene )\r\n{\r\n\tif ( !p_scene->mp_scene_data ) return;\r\n\r\n\t// The vertex color wibble flag is placed in pass 0.\r\n\tNxNgc::sMaterialVCWibbleKeyHeader *\tp_key_header\t= p_scene->mp_vc_wibble; \r\n\tNxNgc::sMaterialVCWibbleKey *\t\tp_key\t\t\t= (NxNgc::sMaterialVCWibbleKey *)&p_key_header[1]; \r\n\r\n\tint current_time = (int)Tmr::GetTime();\r\n\r\n\tuint32 * p_col = p_scene->mp_col_pool;\r\n\r\n\tfor ( int wibble = 0; wibble < p_scene->mp_scene_data->m_num_vc_wibbles; wibble++ )\r\n\t{\r\n\t\tint\t\t\t\t\t\tnum_keys\t\t= p_key_header->m_num_frames;\r\n\t\tint\t\t\t\t\t\tphase_shift\t\t= p_key_header->m_phase;\r\n\r\n\t\t// Time parameters.\r\n\t\tint\t\t\t\t\t\tstart_time\t\t= p_key[0].m_time;\r\n\t\tint\t\t\t\t\t\tend_time\t\t= p_key[(num_keys - 1)].m_time;\r\n\t\tint\t\t\t\t\t\tperiod\t\t\t= end_time - start_time;\r\n\t\tint\t\t\t\t\t\ttime\t\t\t= start_time + (( current_time + phase_shift ) % period );\r\n\r\n\t\t// Locate the keyframe.\r\n\t\tint key;\r\n\t\tfor( key = num_keys - 1; key >= 0; --key )\r\n\t\t{\r\n\t\t\tif( time >= p_key[key].m_time )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Parameter expressing how far we are between between this keyframe and the next.\r\n\t\tfloat t = (float)( time - p_key[key].m_time ) / (float)( p_key[key+1].m_time - p_key[key].m_time );\r\n\r\n\t\t// Interpolate the color.\r\n\t\tGXColor\trgba;\r\n\t\trgba.r = (uint8)((( 1.0f - t ) * p_key[key].m_color.r ) + ( t * p_key[key + 1].m_color.r ));\r\n\t\trgba.g = (uint8)((( 1.0f - t ) * p_key[key].m_color.g ) + ( t * p_key[key + 1].m_color.g ));\r\n\t\trgba.b = (uint8)((( 1.0f - t ) * p_key[key].m_color.b ) + ( t * p_key[key + 1].m_color.b ));\r\n\t\trgba.a = (uint8)((( 1.0f - t ) * p_key[key].m_color.a ) + ( t * p_key[key + 1].m_color.a ));\r\n\r\n\t\tp_col[wibble] = *((uint32*)&rgba);\r\n\r\n\t\t// Next wibble sequence.\r\n\t\tp_key_header\t= (NxNgc::sMaterialVCWibbleKeyHeader *)&p_key[num_keys];\r\n\t\tp_key\t\t\t= (NxNgc::sMaterialVCWibbleKey *)&p_key_header[1]; \r\n\t}\r\n}\r\n\r\n\t\t\t//sMaterialHeader * p_mat = p_mesh->mp_dl->m_material.p_header;\r\n\t\t\t//sMaterialPassHeader * p_pass = (sMaterialPassHeader *)&p_mat[1];\r\n\r\n// Cached GX commands.\r\n\r\nfloat *\tg_p_pos\t\t= NULL;\r\nchar *\tg_p_col0\t= NULL;\r\n//char *\tg_p_col1\t= NULL;\r\nGXColor g_col0\t\t= (GXColor){0,0,0,0};\r\n//GXColor g_col1\t\t= (GXColor){0,0,0,0};\r\n\r\nstatic void _reset( void )\r\n{\r\n\tg_p_pos\t\t= NULL;\r\n\tg_p_col0\t= NULL;\r\n//\tg_p_col1\t= NULL;\r\n\tg_col0\t\t= (GXColor){0,0,0,0};\r\n//\tg_col1\t\t= (GXColor){0,0,0,0};\r\n\tGX::SetChanMatColor( GX_COLOR0A0, g_col0 );\r\n//\tGX::SetChanMatColor( GX_COLOR0A0, g_col1 );\r\n}\r\n\r\nstatic void _set_pos( float * p_pos )\r\n{\r\n\tif ( g_p_pos != p_pos )\r\n\t{\r\n\t\tGX::SetArray( GX_VA_POS, p_pos, sizeof( float ) * 3 );\r\n\t\tg_p_pos = p_pos;\r\n\t}\r\n}\r\n\r\nstatic void _set_col0( char * p_col0 )\r\n{\r\n\tif ( g_p_col0 != p_col0 )\r\n\t{\r\n\t\tGX::SetArray( GX_VA_CLR0, p_col0, sizeof( uint32 ) );\r\n\t\tg_p_col0 = p_col0;\r\n\t}\r\n}\r\n\r\n//static void _set_col1( char * p_col1 )\r\n//{\r\n//\tif ( g_p_col1 != p_col1 )\r\n//\t{\r\n//\t\tGX::SetArray( GX_VA_CLR1, p_col1, sizeof( uint32 ) );\r\n//\t\tg_p_col1 = p_col1;\r\n//\t}\r\n//}\r\n\r\nstatic void _set_mat0( GXColor col )\r\n{\r\n\tif ( ( col.r != g_col0.r ) || ( col.g != g_col0.g ) || ( col.b != g_col0.b ) || ( col.a != g_col0.a ) )\r\n\t{\r\n\t\tg_col0 = col;\r\n\t\tGX::SetChanMatColor( GX_COLOR0A0, col );\r\n\t}\r\n}\r\n\r\n//static void _set_mat1( GXColor col )\r\n//{\r\n//\tif ( ( col.r != g_col1.r ) || ( col.g != g_col1.g ) || ( col.b != g_col1.b ) || ( col.a != g_col1.a ) )\r\n//\t{\r\n//\t\tg_col1 = col;\r\n//\t\tGX::SetChanMatColor( GX_COLOR1A1, col );\r\n//\t}\r\n//}\r\n\r\nstatic void submit_mesh( sScene *p_scene, sMesh * p_mesh, s16* p_posNormBuffer, Mth::Matrix * p_bone_xform, Mth::Matrix * p_instance_xform, int * p_array_base, int * p_col_base, int * p_layer, float * p_pm, GXColor * p_base_color, bool * set_base_color, bool * p_world_fog, uint32 flags )\r\n{\r\n//\tif ( g_skip_correctable && p_mesh->mp_dl->m_material.p_header->m_flags & (1<<6) ) return;\r\n\tif ( (int)p_mesh->mp_dl->m_material.p_header->m_layer_id == g_kill_layer ) return;\r\n\r\n\tif ( !p_posNormBuffer )\r\n\t{\r\n\t\t// Deal with cloned pos pools.\r\n\t\tif ( p_mesh->mp_dl->mp_pos_pool )\r\n\t\t{\r\n\t\t\t_set_pos( p_mesh->mp_dl->mp_pos_pool );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Deal with verts outside of 65535.\r\n\t\t\t_set_pos( &p_scene->mp_pos_pool[p_mesh->mp_dl->m_array_base*3] );\r\n\t\t}\r\n\t}\r\n\r\n\t// Deal with cloned color pools.\r\n\tif ( p_mesh->mp_dl->mp_col_pool )\r\n\t{\r\n\t\t_set_col0( &((char*)p_mesh->mp_dl->mp_col_pool)[0] );\r\n//\t\tif ( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<6) )\r\n//\t\t{\r\n//\t\t\t_set_col1( &((char*)p_mesh->mp_dl->mp_col_pool)[2] );\r\n//\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Deal with resetting cloned color pools.\r\n\t\t// Assumes that this isn't a skinned object.\r\n\t\t_set_col0( &((char*)p_scene->mp_col_pool)[0] );\r\n//\t\tif ( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<6) )\r\n//\t\t{\r\n//\t\t\t_set_col1( &((char*)p_scene->mp_col_pool)[2] );\r\n//\t\t}\r\n\t}\r\n\r\n\t// Deal with zbias.\r\n\tif ( (int)p_mesh->mp_dl->m_material.p_header->m_layer_id != *p_layer )\r\n\t{\r\n\t\t*p_layer = p_mesh->mp_dl->m_material.p_header->m_layer_id;\r\n\r\n\t\tfloat layer = p_mesh->mp_dl->m_material.p_header->m_layer_id;\r\n\r\n\t\tfloat value = p_pm[6] + ( 150.0f * layer ) * p_pm[5];\r\n\r\n\t\tGXWGFifo.u8 = GX_LOAD_XF_REG;\r\n\t\tGXWGFifo.u16 = 0;\r\n\t\tGXWGFifo.u16 = 0x1025;\r\n\t\tGXWGFifo.f32 = value;\r\n\t}\r\n\r\n\r\n\r\n\t// Billboard tweaking.\r\n//\tenum BillboardType\r\n//\t{\r\n//\t\tBBT_NOT_BILLBOARD,\r\n//\t\tBBT_SCREEN_ALIGNED,\r\n//\t\tBBT_AXIAL_ALIGNED,\r\n//\t};\r\n\t\r\n//\tif ( p_mesh->mp_mod )\r\n//\t{\r\n//\t\tMtx t;\r\n//\t\tMtx m;\r\n//\r\n////\t\tMTXTrans( m, p_mesh->mp_mod.offset->GetX(), p_mesh->mp_mod.offset->GetY(), p_mesh->mp_mod.offset->GetZ() );\r\n////\r\n////\t\tMTXRotAxisDeg( \r\n//\r\n//\t\tfloat w = p_mesh->mp_mod->offset[W];\r\n//\t\tMth::ERot90 rot = *((Mth::ERot90*)&w);\r\n//\r\n//\t\tif ( p_mesh->mp_mod->scale[X] > 1.0f ) OSReport( \"X Scale > 1.0f: %8.3f\\n\", p_mesh->mp_mod->scale[X] );\r\n//\t\tif ( p_mesh->mp_mod->scale[Y] > 1.0f ) OSReport( \"Y Scale > 1.0f: %8.3f\\n\", p_mesh->mp_mod->scale[Y] );\r\n//\t\tif ( p_mesh->mp_mod->scale[Z] > 1.0f ) OSReport( \"Z Scale > 1.0f: %8.3f\\n\", p_mesh->mp_mod->scale[Z] );\r\n//\r\n//\t\tswitch ( rot )\r\n//\t\t{\r\n//\t\t\tdefault:\r\n//\t\t\tcase Mth::ROT_0:\r\n//\t\t\t\tMTXScaleApply( g_matrix0, t, p_mesh->mp_mod->scale[X], p_mesh->mp_mod->scale[Y], p_mesh->mp_mod->scale[Z] );\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase Mth::ROT_90:\r\n//\t\t\t\tMTXScaleApply( g_matrix90, t, p_mesh->mp_mod->scale[X], p_mesh->mp_mod->scale[Y], p_mesh->mp_mod->scale[Z] );\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase Mth::ROT_180:\r\n//\t\t\t\tMTXScaleApply( g_matrix180, t, p_mesh->mp_mod->scale[X], p_mesh->mp_mod->scale[Y], p_mesh->mp_mod->scale[Z] );\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase Mth::ROT_270:\r\n//\t\t\t\tMTXScaleApply( g_matrix270, t, p_mesh->mp_mod->scale[X], p_mesh->mp_mod->scale[Y], p_mesh->mp_mod->scale[Z] );\r\n//\t\t\t\tbreak;\r\n//\t\t}\r\n//\t\tt[0][3] = p_mesh->mp_mod->offset[X];\r\n//\t\tt[1][3] = p_mesh->mp_mod->offset[Y];\r\n//\t\tt[2][3] = p_mesh->mp_mod->offset[Z];\r\n//\t\tMTXConcat( EngineGlobals.current_uploaded, t, m );\r\n//\r\n//\t\tGX::LoadPosMtxImm( m, GX_PNMTX0 );\r\n//\t\treload_camera = true;\r\n//\t}\r\n\r\n\t// Set Fog color if necessary.\r\n\tbool mesh_world_fog = true;\r\n\tif ( p_mesh->mp_dl->m_material.p_header )\r\n\t{\r\n\t\tswitch ( p_mesh->mp_dl->m_material.p_header->m_base_blend )\r\n\t\t{\r\n\t\t\tcase vBLEND_MODE_ADD:\r\n\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\t\t\tmesh_world_fog = false;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif ( mesh_world_fog != *p_world_fog )\r\n\t{\r\n\t\t*p_world_fog = mesh_world_fog;\r\n\t\tif ( mesh_world_fog )\r\n\t\t{\r\n\t\t\tNx::CFog::sSetFogColor();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tGX::SetFogColor( (GXColor){0,0,0,0} );\r\n\t\t}\r\n\t}\r\n\r\n\r\n\tMaterialSubmit( p_mesh, p_scene );\r\n\r\n\tswitch ( p_mesh->mp_dl->mp_object_header->m_billboard_type )\r\n\t{\r\n\t\tcase 2:\r\n\t\t\t{\r\n\t\t\t\tNsMatrix*\tp_matrix\t= &EngineGlobals.world_to_camera;\r\n\t\t\t\tNsVector\tat = *p_matrix->getAt();\r\n//\t\t\t\tat.x = -at.x;\r\n//\t\t\t\tat.y = -at.y;\r\n//\t\t\t\tat.z = -at.z;\r\n\r\n\t\t\t\tNsVector screen_right;\r\n\t\t\t\tNsVector screen_up;\r\n\t\t\t\tNsVector screen_at;\r\n\r\n\t\t\t\tNsMatrix\troot;\r\n\r\n\t\t\t\t// Create coordinate system based on camera at & pivot axis.\r\n\t\t\t\tscreen_up.set( p_mesh->mp_dl->mp_object_header->m_axis[X], p_mesh->mp_dl->mp_object_header->m_axis[Y], p_mesh->mp_dl->mp_object_header->m_axis[Z] );\r\n//\t\t\t\tscreen_right.cross( *p_matrix->getAt(), screen_up );\r\n\t\t\t\tscreen_right.cross( at, screen_up );\r\n\t\t\t\tscreen_at.cross( screen_up, screen_right );\r\n\r\n\t\t\t\tscreen_right.normalize();\r\n\t\t\t\tscreen_at.normalize();\r\n\r\n\t\t\t\troot.setRightX( screen_right.x );\r\n\t\t\t\troot.setRightY( screen_up.x    );\r\n\t\t\t\troot.setRightZ( screen_at.x    );\r\n\r\n\t\t\t\troot.setUpX( screen_right.y );\r\n\t\t\t\troot.setUpY( screen_up.y    );\r\n\t\t\t\troot.setUpZ( screen_at.y    );\r\n\r\n\t\t\t\troot.setAtX( screen_right.z );\r\n\t\t\t\troot.setAtY( screen_up.z    );\r\n\t\t\t\troot.setAtZ( screen_at.z    );\r\n\r\n//\t\t\t\troot.setRightX( screen_right.x );\r\n//\t\t\t\troot.setRightY( screen_right.y );\r\n//\t\t\t\troot.setRightZ( screen_right.z );\r\n//\r\n//\t\t\t\troot.setUpX( screen_up.x );\r\n//\t\t\t\troot.setUpY( screen_up.y );\r\n//\t\t\t\troot.setUpZ( screen_up.z );\r\n//\r\n//\t\t\t\troot.setAtX( screen_at.x );\r\n//\t\t\t\troot.setAtY( screen_at.y );\r\n//\t\t\t\troot.setAtZ( screen_at.z );\r\n\r\n\t\t\t\troot.setPosX( p_mesh->mp_dl->mp_object_header->m_origin[X] );\r\n\t\t\t\troot.setPosY( p_mesh->mp_dl->mp_object_header->m_origin[Y] );\r\n\t\t\t\troot.setPosZ( p_mesh->mp_dl->mp_object_header->m_origin[Z] );\r\n\r\n\t\t\t\troot.cat( EngineGlobals.world_to_camera, root );\r\n\r\n\t\t\t\tGX::LoadPosMtxImm( (MtxPtr)&root, GX_PNMTX0 );\r\n\t\t\t\t//GXSetCurrentMtx( GX_PNMTX1 );\r\n\t\t\t\treload_camera = true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\t{\r\n\t\t\t\tNsMatrix*\tp_matrix\t= &EngineGlobals.world_to_camera;\r\n\r\n\t\t\t\tNsMatrix\troot;\r\n\r\n\t\t\t\t// Just transpose the matrix for screen-facing.\r\n\t\t\t\troot.setRightX( p_matrix->getRightX() );\r\n\t\t\t\troot.setRightY( p_matrix->getUpX()    );\r\n\t\t\t\troot.setRightZ( p_matrix->getAtX()    );\r\n\r\n\t\t\t\troot.setUpX( p_matrix->getRightY() );\r\n\t\t\t\troot.setUpY( p_matrix->getUpY()    );\r\n\t\t\t\troot.setUpZ( p_matrix->getAtY()    );\r\n\r\n\t\t\t\troot.setAtX( p_matrix->getRightZ() );\r\n\t\t\t\troot.setAtY( p_matrix->getUpZ()    );\r\n\t\t\t\troot.setAtZ( p_matrix->getAtZ()    );\r\n\r\n\t\t\t\troot.setPosX( p_mesh->mp_dl->mp_object_header->m_origin[X] );\r\n\t\t\t\troot.setPosY( p_mesh->mp_dl->mp_object_header->m_origin[Y] );\r\n\t\t\t\troot.setPosZ( p_mesh->mp_dl->mp_object_header->m_origin[Z] );\r\n\r\n\t\t\t\troot.cat( EngineGlobals.world_to_camera, root );\r\n\r\n\t\t\t\tGX::LoadPosMtxImm( (MtxPtr)&root, GX_PNMTX0 );\r\n\t\t\t\t//GXSetCurrentMtx( GX_PNMTX1 );\r\n\t\t\t\treload_camera = true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\t// Don't do anything - not a billboard.\r\n\t\t\t//GXSetCurrentMtx( GX_PNMTX0 );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n//\t// Create array of bone matrices if required.\r\n//\tNsMatrix\tbone_xform[80];\r\n//\tif ( p_scene->m_numHierarchyObjects && p_bone_xform )\r\n//\t{\r\n//\t\tfor ( int bone = 0; bone < num_bones; bone++ )\r\n//\t\t{\r\n//\t\t\tMth::Matrix temp = p_bone_xform[bone] * *p_instance_xform;\r\n//\t\t\tNsMatrix\tlocal;\r\n//\r\n//\t\t\tlocal.setRightX( temp.GetRight()[X] );\r\n//\t\t\tlocal.setRightY( temp.GetUp()[X] );\r\n//\t\t\tlocal.setRightZ( temp.GetAt()[X] );\r\n//\r\n//\t\t\tlocal.setUpX( temp.GetRight()[Y] ); \r\n//\t\t\tlocal.setUpY( temp.GetUp()[Y] );    \r\n//\t\t\tlocal.setUpZ( temp.GetAt()[Y] );    \r\n//\r\n//\t\t\tlocal.setAtX( temp.GetRight()[Z] ); \r\n//\t\t\tlocal.setAtY( temp.GetUp()[Z] );    \r\n//\t\t\tlocal.setAtZ( temp.GetAt()[Z] );    \r\n//\r\n//\t\t\tlocal.setPosX( temp.GetPos()[X] );\r\n//\t\t\tlocal.setPosY( temp.GetPos()[Y] );\r\n//\t\t\tlocal.setPosZ( temp.GetPos()[Z] );\r\n//\r\n//\t\t\tbone_xform[bone].cat( EngineGlobals.world_to_camera, local );\r\n//\t\t}\r\n//\t}\r\n\r\n\r\n\tif ( p_scene->m_numHierarchyObjects && p_bone_xform )\r\n\t{\r\n\t\tNsMatrix\tbone_xform;\r\n\t\tMth::Matrix temp = p_bone_xform[p_mesh->m_bone_idx] * *p_instance_xform;\r\n\t\tNsMatrix\tlocal;\r\n\r\n\t\tlocal.setRightX( temp.GetRight()[X] );\r\n\t\tlocal.setRightY( temp.GetUp()[X] );\r\n\t\tlocal.setRightZ( temp.GetAt()[X] );\r\n\r\n\t\tlocal.setUpX( temp.GetRight()[Y] ); \r\n\t\tlocal.setUpY( temp.GetUp()[Y] );    \r\n\t\tlocal.setUpZ( temp.GetAt()[Y] );    \r\n\r\n\t\tlocal.setAtX( temp.GetRight()[Z] ); \r\n\t\tlocal.setAtY( temp.GetUp()[Z] );    \r\n\t\tlocal.setAtZ( temp.GetAt()[Z] );    \r\n\r\n\t\tlocal.setPosX( temp.GetPos()[X] );\r\n\t\tlocal.setPosY( temp.GetPos()[Y] );\r\n\t\tlocal.setPosZ( temp.GetPos()[Z] );\r\n\r\n\t\tbone_xform.cat( EngineGlobals.world_to_camera, local );\r\n\r\n\t\tGX::LoadPosMtxImm( (MtxPtr)&bone_xform, GX_PNMTX0 );\r\n\t\treload_camera = true;\r\n\r\n\t\tGX::LoadNrmMtxImm((MtxPtr)&bone_xform, GX_PNMTX0);\r\n\r\n\t}\r\n\r\n\tif ( /*p_scene->mp_scene_data->m_num_nrm ||*/ p_posNormBuffer || ( p_scene->m_numHierarchyObjects && p_bone_xform ) )\r\n\t{\r\n//\t\tGXLightObj light_obj[3];\r\n//\r\n//\t\t// Always set ambient & diffuse colors.\r\n//\t\tGX::SetChanAmbColor( GX_COLOR0A0, NxNgc::EngineGlobals.ambient_light_color );\r\n////\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){128,128,128,255} );\r\n////\t\t\t\tGX::SetChanAmbColor( GX_COLOR1A1, NxNgc::EngineGlobals.ambient_light_color );\r\n//\t\r\n//\t\tGX::InitLightColor( &light_obj[0], NxNgc::EngineGlobals.diffuse_light_color[0] );\r\n//\t\tGX::InitLightPos( &light_obj[0], NxNgc::EngineGlobals.light_x[0], NxNgc::EngineGlobals.light_y[0], NxNgc::EngineGlobals.light_z[0] );\r\n//\t\tGX::LoadLightObjImm( &light_obj[0], GX_LIGHT0 );\r\n//\t\r\n//\t\tGX::InitLightColor( &light_obj[1], NxNgc::EngineGlobals.diffuse_light_color[1] );\r\n//\t\tGX::InitLightPos( &light_obj[1], NxNgc::EngineGlobals.light_x[1], NxNgc::EngineGlobals.light_y[1], NxNgc::EngineGlobals.light_z[1] );\r\n//\t\tGX::LoadLightObjImm( &light_obj[1], GX_LIGHT1 );\r\n//\r\n//\t\t// Set channel control for diffuse.\r\n//\t\tGX::SetChanCtrl( GX_COLOR0, GX_ENABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT0|GX_LIGHT1, GX_DF_CLAMP, GX_AF_NONE );\r\n//\t\tGX::SetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ); \r\n//\r\n////\t\tif ( p_mesh->mp_dl->m_material.p_header->m_shininess > 0.0f )\r\n////\t\t{\r\n////\t\t\t// Set channel control for specular.\r\n////\t\t\tVec  ldir;\r\n////\r\n////\t\t\tldir.x = 0.0f;\t//NxNgc::EngineGlobals.light_x[0] * ( 1.0f / 200000.0f );\r\n////\t\t\tldir.y = 0.0f;  //NxNgc::EngineGlobals.light_y[0] * ( 1.0f / 200000.0f );\r\n////\t\t\tldir.z = -1.0f;  //NxNgc::EngineGlobals.light_z[0] * ( 1.0f / 200000.0f );\r\n////\r\n////\t\t\tGX::InitSpecularDirv( &light_obj[2], &ldir );\r\n////\t\t\tGX::InitLightShininess( &light_obj[2], 8.0f );\r\n////\t\t\tGX::InitLightColor( &light_obj[2], (GXColor){255,255,255,255} );\r\n////\t\t\tGX::LoadLightObjImm( &light_obj[2], GX_LIGHT2 );\r\n////\r\n////\t\t\tGX::SetChanCtrl( GX_COLOR1, GX_ENABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT2, GX_DF_NONE, GX_AF_SPEC );\r\n////\t\t\tGX::SetChanCtrl( GX_ALPHA1, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ); \r\n////\t\t}\r\n//\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( !*set_base_color )\r\n\t\t{\r\n\t\t\tGX::SetChanCtrl( GX_COLOR0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\t\t\tGX::SetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ); \r\n////\t\t\tif ( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<6) )\r\n//\t\t\t{\r\n//\t\t\t\tGX::SetChanCtrl( GX_COLOR1, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\t\t\t\tGX::SetChanCtrl( GX_ALPHA1, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ); \r\n//\t\t\t}\r\n\t\t\t*set_base_color = true;\r\n\t\t}\r\n//\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){128,128,128,255} );\r\n//\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){32,32,32,255} );\r\n\t\tGXColor col;\r\n\t\tcol.r = p_mesh->m_base_color.r;\r\n\t\tcol.g = p_mesh->m_base_color.g;\r\n\t\tcol.b = p_mesh->m_base_color.b;\r\n\t\tcol.a = 255;\r\n\r\n////\t\tif ( !(p_mesh->mp_dl->m_material.p_header->m_flags & (1<<7)) )\r\n//\t\tif ( !(flags & vRENDER_LIT) )\r\n//\t\t{\r\n//\t\t\t// Not sure why we need to force this to be set...\r\n////\t\t\t_set_mat0( col );\r\n////\t\t\tGX::SetChanMatColor( GX_COLOR0A0, col );\r\n////\t\t\tif ( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<6) )\r\n//\t\t\t{\r\n////\t\t\t\t_set_mat1( col );\r\n////\t\t\t\tGX::SetChanMatColor( GX_COLOR1A1, col );\r\n//\t\t\t}\r\n////\t\t\t*((uint32*)p_base_color) = *((uint32*)&col);\r\n//\r\n//\t\t\tcol.r = col.r >> 1;\r\n//\t\t\tcol.g = col.g >> 1;\r\n//\t\t\tcol.b = col.b >> 1;\r\n//\t\t}\r\n\r\n//\t\tif ( *((uint32*)p_base_color) !=  *((uint32*)&col) )\r\n\t\t{\r\n//\t\t\tp_mesh->m_base_color.a = 255;\r\n//\t\t\tGX::SetChanMatColor( GX_COLOR0A0, col );\r\n\r\n\t\t\t_set_mat0( col );\r\n//\t\t\tif ( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<6) )\r\n//\t\t\t{\r\n////\t\t\t\tGX::SetChanMatColor( GX_COLOR1A1, col );\r\n//\t\t\t\t_set_mat1( (GXColor){col.b,col.a,0,0} );\r\n//\t\t\t}\r\n//\t\t\t*((uint32*)p_base_color) = *((uint32*)&col);\r\n\t\t}\r\n\r\n//\t\tGX::SetChanCtrl( GX_COLOR1A1, GX_DISABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\t\tGX::SetChanMatColor( GX_COLOR1A1, (GXColor){128,128,128,255} );\r\n//\t\tGX::SetChanAmbColor( GX_COLOR1A1, (GXColor){128,128,128,255} );\r\n//\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){64,64,64,128} );\r\n//\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){64,64,64,128} );\r\n\t}\r\n\r\n\t// Major hack!!!\r\n//   if ( p_posNormBuffer )\r\n//\t{\r\n//\t\tunsigned char * p8 = (unsigned char *)&p_mesh->mp_dl[1];\r\n//\t\tfor ( uint lp = 0; lp < p_mesh->mp_dl->m_size; lp++ ) GXWGFifo.u8 = *p8++;\r\n//\t}\r\n//\telse\r\n//\t{\r\n\t/*if ( !p_mesh->mp_dl->mp_pos_pool )*/ GX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );\r\n//\t}\r\n\r\n\tif ( reload_camera )\r\n\t{\r\n\t\tGX::LoadPosMtxImm( EngineGlobals.current_uploaded, GX_PNMTX0 );\r\n//\t\tGX::LoadPosMtxImm( (Mtx)current_cam.getCurrent(), GX_PNMTX0 );\r\n\t\treload_camera = false;\r\n\t}\r\n\r\n//\t// Reload color texture if necessary.\r\n//\tif ( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<5) )\r\n//\t{\r\n//\t\t// Make sure color map is uploaded.\r\n//\t\tGX::UploadTexture(\tcolorMap,\r\n//\t\t\t\t\t\t\t64,\t//COLOR_MAP_SIZE,\r\n//\t\t\t\t\t\t\t64, //COLOR_MAP_SIZE,\r\n//\t\t\t\t\t\t\tGX_TF_RGBA8,\r\n//\t\t\t\t\t\t\tGX_CLAMP,\r\n//\t\t\t\t\t\t\tGX_CLAMP,\r\n//\t\t\t\t\t\t\tGX_FALSE,\r\n//\t\t\t\t\t\t\tGX_LINEAR,\r\n//\t\t\t\t\t\t\tGX_LINEAR,\r\n//\t\t\t\t\t\t\t0.0f,\r\n//\t\t\t\t\t\t\t0.0f,\r\n//\t\t\t\t\t\t\t0.0f,\r\n//\t\t\t\t\t\t\tGX_FALSE,\r\n//\t\t\t\t\t\t\tGX_TRUE,\r\n//\t\t\t\t\t\t\tGX_ANISO_1,\r\n//\t\t\t\t\t\t\tGX_TEXMAP7 ); \r\n//\t}\r\n}\r\n\r\nvoid render_scene( sScene *p_scene, s16* p_posNormBuffer, uint32 flags, Mth::Matrix * p_bone_xform, Mth::Matrix * p_instance_xform, int num_bones )\r\n{\r\n\t// Don't render dictionary scenes.\r\n\tif( p_scene->m_is_dictionary )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n//\t// This forces the texture to go into the unusable region.\r\n//\tGX::UploadTexture(\tcolorMap,\r\n//\t\t\t\t\t\t64,\r\n//\t\t\t\t\t\t64,\r\n//\t\t\t\t\t\tGX_TF_RGBA8,\r\n//\t\t\t\t\t\tGX_CLAMP,\r\n//\t\t\t\t\t\tGX_CLAMP,\r\n//\t\t\t\t\t\tGX_FALSE,\r\n//\t\t\t\t\t\tGX_LINEAR,\r\n//\t\t\t\t\t\tGX_LINEAR,\r\n//\t\t\t\t\t\t0.0f,\r\n//\t\t\t\t\t\t0.0f,\r\n//\t\t\t\t\t\t0.0f,\r\n//\t\t\t\t\t\tGX_FALSE,\r\n//\t\t\t\t\t\tGX_TRUE,\r\n//\t\t\t\t\t\tGX_ANISO_1,\r\n//\t\t\t\t\t\tGX_TEXMAP7 ); \r\n\r\n\tsLastUV = NULL;\r\n\r\n\tfirst_mat = true;\r\n\r\n\tp_last_material = NULL;\r\n\tlast_correct = false;\r\n//\tif ( p_scene->m_numHierarchyObjects == 0 )\r\n//\t{\r\n//\t\t// Not hierarchical, set to matrix 0.\r\n//\t\tGXSetCurrentMtx( GX_PNMTX0 );\r\n//\t}\r\n\r\n\tResetMaterialChange();\r\n//\tint meshes_rendered\t\t= 0;\r\n\r\n\tfigure_wibble_vc( p_scene );\r\n\r\n#define MAX_SHADOW_MESHES 512\r\n\r\n//\tint shadow_meshes = 0;\r\n//\tsMesh *pShadow[MAX_SHADOW_MESHES];\r\n\r\n//\tsMesh\t*visible_mesh_array[2000];\r\n//\tint\t\tvisible_mesh_array_index = 0;\r\n\r\n\t// Increment the scene framestamp.\r\n//_scene->m_framestamp++;\r\n\r\n\t// Set up the texture generation matrix here.\r\n//\tMtx light;\r\n//\tMTXLightOrtho( light, -128.0f, 128.0f, -128.0f, 128.0f, 0.5f, 0.5f, 0.5f, 0.5f );\r\n//\tMTXConcat( light, (Mtx)&EngineGlobals.shadow_camera, light );\r\n//#ifndef SHORT_VERT\r\n//\tGX::LoadTexMtxImm( light, GX_TEXMTX7, GX_MTX3x4 );\r\n//#endif\t\t// SHORT_VERT\r\n\r\n\tif ( p_posNormBuffer )\r\n\t{\r\n\t\tGX::SetArray( GX_VA_POS,  p_posNormBuffer, sizeof( uint16 ) * 6 );\r\n\t\tGX::SetArray( GX_VA_NRM,  &p_posNormBuffer[3], sizeof( uint16 ) * 6 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGX::SetArray( GX_VA_POS,  p_scene->mp_pos_pool, sizeof( float ) * 3 );\r\n\t\tGX::SetArray( GX_VA_NRM,  p_scene->mp_nrm_pool, sizeof( uint16 ) * 3 );\r\n\t}\r\n\tint array_base = 0;\r\n\tint col_base = 2;\r\n\tint layer = -1;\r\n\tbool set_chan = false;\r\n\tGXColor base_color = { 0, 0, 0, 0 };\r\n\tbool world_fog = true;\r\n\tNx::CFog::sSetFogColor();\r\n\tGX::SetChanMatColor( GX_COLOR0A0, base_color );\r\n\tGX::SetChanMatColor( GX_COLOR1A1, base_color );\r\n\tf32 pm[GX_PROJECTION_SZ];\r\n\tGX::GetProjectionv( pm );\r\n\r\n\r\n//\tif ( flags & vRENDER_NEW_TEST )\r\n\t{\r\n\t\t// Pool setup.\r\n\t\tGX::SetArray( GX_VA_CLR0, &((char*)p_scene->mp_col_pool)[0], sizeof( uint32 ) );\r\n\t\tGX::SetArray( GX_VA_CLR1, &((char*)p_scene->mp_col_pool)[2], sizeof( uint32 ) );\r\n\r\n//\t\tGX::SetArray( GX_VA_CLR1, p_scene->mp_col_pool, sizeof( uint32 ) );\r\n//\t\tGX::SetArray( GX_VA_TEX0, p_scene->mp_tex_pool, sizeof( float ) * 2 );\r\n//\r\n//\t\tGX::SetArray( GX_VA_TEX1, p_scene->mp_tex_pool, sizeof( float ) * 2 );\r\n//\t\tGX::SetArray( GX_VA_TEX2, p_scene->mp_tex_pool, sizeof( float ) * 2 );\r\n//\t\tGX::SetArray( GX_VA_TEX3, p_scene->mp_tex_pool, sizeof( float ) * 2 );\r\n\r\n\t\tGX::SetArray( GX_VA_TEX0, p_scene->mp_tex_pool, sizeof( uint16 ) * 2 );\r\n\t\tGX::SetArray( GX_VA_TEX1, p_scene->mp_tex_pool, sizeof( uint16 ) * 2 );\r\n\t\tGX::SetArray( GX_VA_TEX2, p_scene->mp_tex_pool, sizeof( uint16 ) * 2 );\r\n\t\tGX::SetArray( GX_VA_TEX3, p_scene->mp_tex_pool, sizeof( uint16 ) * 2 );\r\n\r\n//\t\tGXSetArray( GX_VA_TEX4, p_scene->mp_tex_pool, sizeof( float ) * 2 );\r\n//\t\tGXSetArray( GX_VA_TEX5, p_scene->mp_tex_pool, sizeof( float ) * 2 );\r\n//\t\tGXSetArray( GX_VA_TEX6, p_scene->mp_tex_pool, sizeof( float ) * 2 );\r\n//\t\tGXSetArray( GX_VA_TEX7, p_scene->mp_tex_pool, sizeof( float ) * 2 );\r\n\t\t//GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n\t}\r\n\r\n\r\n\r\n\r\n\r\n\tif ( g_object == g_view_object ) g_view_scene = p_scene;\r\n\r\n\t// Render all meshes.\r\n#\tifdef __USE_PROFILER__\r\n\t\t\t\t\t\tSys::VUProfiler->PushContext( 128,0,0 );\r\n#\tendif\t\t// __USE_PROFILER__\r\n\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tGX::SetFog( GX_FOG_NONE, 0.0f, 0.0f, 0.0f, 0.0f, (GXColor){0,0,0,0} );\r\n//\t\t\t\t\t\t\tGX::SetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );\r\n//\r\n//\t\t\t\t\t\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_KONST,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\r\n//\t\t\t\t\t\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_KONST,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\r\n//\t\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n//\r\n//\t\t\t\t\t\t\tGX::SetTevKSel( GX_TEVSTAGE0, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A );\r\n//\t\t\t\t\t\t\tGX::SetTevKColor( GX_KCOLOR0, (GXColor){8,8,8,255} );\r\n//\t\t\t\t\t\t\tGX::SetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ); \r\n//\t\t\t\t\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255});\r\n//\t\t\t\t\t\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255});\r\n//\r\n//\t\t\t\t\t\t\tGX::SetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE);\r\n//\t\t\t\t\t\t\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE ); \r\n//\t\t\t\t\t\t}\r\n\r\n\t///////////////////////////////////////////////////////////////////////////////////////////\r\n\t// Shadow Target.\r\n\t///////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n\tif ( flags & vRENDER_SHADOW_1ST_PASS )\r\n\t{\r\n//\t\tGX::SetFog( GX_FOG_NONE, 0.0f, 0.0f, 0.0f, 0.0f, (GXColor){0,0,0,0} );\r\n\t\tGX::SetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );\r\n\r\n\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_KONST,\r\n\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\r\n\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_KONST,\r\n\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\r\n\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\t\t// Replace\r\n\r\n\t\tGX::SetTevKSel( GX_TEVSTAGE0, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A );\r\n\t\tGX::SetTevKColor( GX_KCOLOR0, (GXColor){64,64,64,255} );\r\n\t\tGX::SetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ); \r\n\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255});\r\n\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255});\r\n\t\tGX::SetChanMatColor( GX_COLOR1A1, (GXColor){255,255,255,255});\r\n\t\tGX::SetChanAmbColor( GX_COLOR1A1, (GXColor){255,255,255,255});\r\n\t\tbase_color = (GXColor){ 255, 255, 255, 255 };\r\n\r\n//\t\tGX::SetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE);\r\n\t\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE ); \r\n\r\n\t\tfor ( int mesh = 0; mesh < p_scene->m_num_filled_meshes; mesh++ )\r\n\t\t{\r\n\t\t\tsMesh * p_mesh = p_scene->mpp_mesh_list[mesh];\r\n\r\n\t\t\tif ( ( p_mesh->m_flags & sMesh::MESH_FLAG_VISIBLE ) &&\r\n\t\t\t\t ( ( g_object != g_view_object ) || ( &p_scene->mp_material_header[g_material] != p_mesh->mp_dl->m_material.p_header ) ) )\r\n\t\t\t{\r\n\t\t\t\tGX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );\r\n\r\n\r\n//\t\t\t\tsubmit_mesh( p_scene, p_mesh, p_posNormBuffer, p_bone_xform, p_instance_xform, &array_base, &col_base, &layer, pm, &world_fog, flags );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t///////////////////////////////////////////////////////////////////////////////////////////\r\n\t// Opaque meshes.\r\n\t///////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n\t_reset();\r\n\tif ( flags & vRENDER_OPAQUE )\r\n\t{\r\n//\t\tGX::SetZMode( GX_TRUE, GX_LEQUAL, GX_TRUE );\r\n\t\tfor ( int mesh = 0; mesh < p_scene->m_num_opaque_meshes; mesh++ )\r\n\t\t{\r\n\t\t\tsMesh * p_mesh = p_scene->mpp_mesh_list[mesh];\r\n\r\n\t\t\tif ( ( p_mesh->m_flags & sMesh::MESH_FLAG_VISIBLE ) &&\r\n\t\t\t\t ( ( g_object != g_view_object ) || ( &p_scene->mp_material_header[g_material] != p_mesh->mp_dl->m_material.p_header ) ) )\r\n\t\t\t{\r\n\t\t\t\tsubmit_mesh( p_scene, p_mesh, p_posNormBuffer, p_bone_xform, p_instance_xform, &array_base, &col_base, &layer, pm, &base_color, &set_chan, &world_fog, flags );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t///////////////////////////////////////////////////////////////////////////////////////////\r\n\t// Semitransparent meshes.\r\n\t///////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n\tif ( flags & vRENDER_SEMITRANSPARENT )\r\n\t{\r\n//\t\tGX::SetZMode( GX_TRUE, GX_LEQUAL, GX_TRUE );\r\n\t\tint opaque\t\t= p_scene->m_num_opaque_meshes;\r\n\t\tint presemi\t\t= opaque + p_scene->m_num_pre_semitrans_meshes;\r\n\t\tint dynsemi\t\t= presemi + p_scene->m_num_dynamic_semitrans_meshes;\r\n\t\tint postsemi\t= dynsemi + p_scene->m_num_post_semitrans_meshes;\r\n\r\n\t\t// Pre meshes.\r\n\t\t_reset();\r\n\t\tfor ( int mesh = opaque; mesh < presemi; mesh++ )\r\n\t\t{\r\n\t\t\tsMesh * p_mesh = p_scene->mpp_mesh_list[mesh];\r\n\r\n\t\t\tif ( ( p_mesh->m_flags & sMesh::MESH_FLAG_VISIBLE ) &&\r\n\t\t\t\t ( ( g_object != g_view_object ) || ( &p_scene->mp_material_header[g_material] != p_mesh->mp_dl->m_material.p_header ) ) )\r\n\t\t\t{\r\n\t\t\t\tsubmit_mesh( p_scene, p_mesh, p_posNormBuffer, p_bone_xform, p_instance_xform, &array_base, &col_base, &layer, pm, &base_color, &set_chan, &world_fog, flags );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Dynamic meshes.\r\n\t\tsSortedMeshEntry sortedMeshArray[1000];\r\n\t\tint next_sorted_mesh_entry\t= 0;\r\n\r\n\t\tfor ( int mesh = presemi; mesh < dynsemi; mesh++ )\r\n\t\t{\r\n\t\t\tsMesh * p_mesh = p_scene->mpp_mesh_list[mesh];\r\n\r\n\t\t\tif ( ( p_mesh->m_flags & sMesh::MESH_FLAG_VISIBLE ) &&\r\n\t\t\t\t ( ( g_object != g_view_object ) || ( &p_scene->mp_material_header[g_material] != p_mesh->mp_dl->m_material.p_header ) ) )\r\n\t\t\t{\r\n\t\t\t\tsortedMeshArray[next_sorted_mesh_entry].p_mesh\t= p_mesh;\r\n\t\t\t\tsortedMeshArray[next_sorted_mesh_entry].sort\t= frustum_sort_mid( p_mesh->mp_dl->m_sphere );\r\n\t\t\t\t++next_sorted_mesh_entry;\r\n\t\t\t}\r\n\t\t}\r\n\t\tqsort( sortedMeshArray, next_sorted_mesh_entry, sizeof( sSortedMeshEntry ), cmp );\r\n\r\n\t\t_reset();\r\n\t\tfor( int m = 0; m < next_sorted_mesh_entry; ++m )\r\n\t\t{\r\n\t\t\tsubmit_mesh( p_scene, sortedMeshArray[m].p_mesh, p_posNormBuffer, p_bone_xform, p_instance_xform, &array_base, &col_base, &layer, pm, &base_color, &set_chan, &world_fog, flags );\r\n\t\t}\r\n\r\n\t\t// Post meshes.\r\n\t\t_reset();\r\n\t\tfor ( int mesh = dynsemi; mesh < postsemi; mesh++ )\r\n\t\t{\r\n\t\t\tsMesh * p_mesh = p_scene->mpp_mesh_list[mesh];\r\n\r\n\t\t\tif ( ( p_mesh->m_flags & sMesh::MESH_FLAG_VISIBLE ) &&\r\n\t\t\t\t ( ( g_object != g_view_object ) || ( &p_scene->mp_material_header[g_material] != p_mesh->mp_dl->m_material.p_header ) ) )\r\n\t\t\t{\r\n\t\t\t\tsubmit_mesh( p_scene, p_mesh, p_posNormBuffer, p_bone_xform, p_instance_xform, &array_base, &col_base, &layer, pm, &base_color, &set_chan, &world_fog, flags );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\r\n\r\n\t///////////////////////////////////////////////////////////////////////////////////////////\r\n\t// Shadow Mesh.\r\n\t///////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n\tif ( flags & vRENDER_SHADOW_2ND_PASS )\r\n\t{\r\n\t\tNx::CFog::sEnableFog( false );\r\n\t\tMtx light;\r\n\t\tMTXLightOrtho( light, -128.0f, 128.0f, -128.0f, 128.0f, 0.5f, 0.5f, 0.5f, 0.5f );\r\n\t\tMTXConcat( light, (Mtx)&EngineGlobals.shadow_camera, light );\r\n\t\tGX::LoadTexMtxImm( light, GX_TEXMTX7, GX_MTX3x4 );\r\n\t\tGX::SetZMode( GX_TRUE, GX_LEQUAL, GX_FALSE );\r\n\r\n\t\tGX::SetZCompLoc( GX_TRUE );\r\n\t\tGX::UploadTexture(  shadowTextureData,\r\n\t\t\t\t\t\t\tSHADOW_TEXTURE_SIZE,\r\n\t\t\t\t\t\t\tSHADOW_TEXTURE_SIZE,\r\n\t\t\t\t\t\t\tGX_TF_I4,\r\n\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\tGX_TRUE,\r\n\t\t\t\t\t\t\tGX_ANISO_1,\r\n\t\t\t\t\t\t\tGX_TEXMAP0 ); \r\n\t\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, SHADOW_TEXTURE_SIZE, SHADOW_TEXTURE_SIZE );\r\n\r\n\t\tGX::UploadPalette( shadowPalette,\r\n\t\t\t\t\t\t   GX_TL_RGB5A3,\r\n\t\t\t\t\t\t   GX_TLUT_16,\r\n\t\t\t\t\t\t   GX_TEXMAP0 );\r\n\r\n\t\tGX::SetTexChanTevIndCull( 1, 0, 1, 0, GX_CULL_NONE );\r\n\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_FALSE, GX_PTIDENTITY );\r\n\r\n\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t\tGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0 );\r\n//\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\t\t// Replace\r\n\t\tGX::SetBlendMode( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_TEXMTX7, GX_TEXMTX7, GX_TEXMTX7, GX_TEXMTX7 );\r\n\r\n\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ONE, GX_CC_ZERO, GX_CC_TEXC, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n\r\n\r\n//out_reg = (d (op) ((1.0 - c)*a + c*b) + bias) * scale;\r\n\r\n\t\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\r\n//\t\tvisible_mesh_array[visible_mesh_array_index++] = p_scene->m_semitransparent_meshes[e];\r\n//\t\tfor ( int mesh = 0; mesh < p_scene->m_num_filled_meshes; mesh++ )\r\n\r\n\t\tlayer = 5;\t\t// Force subsequent materials to reset the layer.\r\n\r\n//\t\tfloat value = pm[6] + ( 80.0f * p_mesh->mp_dl->m_material.p_header->m_layer_id ) * pm[5];\r\n\t\tfloat value = pm[6] + ( 150.0f * 5 ) * pm[5];\r\n\r\n\t\tGXWGFifo.u8 = GX_LOAD_XF_REG;\r\n\t\tGXWGFifo.u16 = 0;\r\n\t\tGXWGFifo.u16 = 0x1025;\r\n\t\tGXWGFifo.f32 = value;\r\n\r\n//\t\tfor ( int mesh = 0; mesh < ( p_scene->m_num_opaque_meshes + p_scene->m_num_pre_semitrans_meshes ); mesh++ )\r\n\t\tfor ( int mesh = 0; mesh < ( p_scene->m_num_filled_meshes ); mesh++ )\r\n\r\n\t\t{\r\n\t\t\tsMesh * p_mesh = p_scene->mpp_mesh_list[mesh];\r\n\r\n//\t\t\tif( frustum_check_sphere( light, p_scene->m_opaque_meshes[e]->m_sphere ))\r\n\t\t\tfloat by;\r\n\r\n//\t\t\tif ( p_mesh->mp_mod )\r\n//\t\t\t{\r\n////\t\t\t\tby = ( p_mesh->m_bottom_y * p_mesh->mp_mod->scale[Y] ) + p_mesh->mp_mod->offset[Y];\r\n//\t\t\t\tby = p_mesh->mp_mod->offset[Y];\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n\t\t\t\tby = p_mesh->m_bottom_y;\r\n//\t\t\t}\r\n\r\n\t\t\tif ( ( p_mesh->m_flags & sMesh::MESH_FLAG_VISIBLE ) &&\r\n\t\t\t\t frustum_check_sphere( light, p_mesh->mp_dl->m_sphere ) &&\r\n\t\t\t\t ( g_shadow_object_pos[Y] > by ) &&\r\n\t\t\t\t !( p_mesh->m_flags & sMesh::MESH_FLAG_NO_SKATER_SHADOW ) )\r\n\t\t\t{\r\n\r\n//\t\t\t\tif ( (int)p_mesh->mp_dl->m_material.p_header->m_layer_id == g_kill_layer ) return;\r\n\r\n\t\t\t\t// Deal with cloned pos pools.\r\n\t\t\t\tif ( p_mesh->mp_dl->mp_pos_pool )\r\n\t\t\t\t{\r\n\t\t\t\t\tarray_base = -1;\r\n\t\t\t\t\tGX::SetArray( GX_VA_POS, p_mesh->mp_dl->mp_pos_pool, sizeof( float ) * 3 );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Deal with verts outside of 65535.\r\n\t\t\t\t\tif ( p_mesh->mp_dl->m_array_base != (uint32)array_base )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tarray_base = p_mesh->mp_dl->m_array_base;\r\n\r\n\t\t\t\t\t\t// Assumes that this isn't a skinned object.\r\n\t\t\t\t\t\tGX::SetArray( GX_VA_POS, &p_scene->mp_pos_pool[p_mesh->mp_dl->m_array_base*3], sizeof( float ) * 3 );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tGX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );\r\n\r\n\r\n//\t\t\t\tsubmit_mesh( p_scene, p_mesh, p_posNormBuffer, p_bone_xform, p_instance_xform, &array_base, &col_base, &layer, pm, &world_fog, flags );\r\n\t\t\t}\r\n\t\t}\r\n\t\tNx::CFog::sEnableFog( true );\r\n\t\tworld_fog = true;\r\n\t}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n//\t// Render opaque meshes.\r\n//\tif( (flags & vRENDER_OPAQUE) && !(flags & vRENDER_SHADOW_1ST_PASS) )\r\n//\t{\r\n//\t\tfor( int e = 0; e < p_scene->m_num_opaque_entries; ++e )\r\n//\t\t{\r\n//\t\t\tif ( p_scene->m_opaque_meshes[e]->m_flags & sMesh::MESH_FLAG_VISIBLE )\r\n//\t\t\t{\r\n//\t\t\t\tsMesh * p_mesh = p_scene->m_opaque_meshes[e];\r\n//\t\t\r\n////\t\t\t\tset_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );\r\n//\r\n//\t\t\t\tif ( flags & vRENDER_NEW_TEST )\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// Textured.\r\n//\t\t\t\t\t// First pass material setup.\r\n//\t\t\t\t\tsMaterialHeader * p_mat = p_mesh->mp_dl->m_material.p_header;\r\n//\t\t\t\t\tsMaterialPassHeader * p_pass = (sMaterialPassHeader *)&p_mat[1];\r\n//\r\n//\t\t\t\t\tif ( p_pass[0].m_texture.p_data )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tif ( first_mat || !one_mat )\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tfirst_mat = false;\r\n//\r\n//\t\t\t\t\t\t\tMaterialSubmit( p_mesh );\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t\tGX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size ); \r\n//\t\t\t\t\t}\r\n//\t\t\t\t\telse\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\t// Untextured.\r\n//\t\t\t\t\t\tif ( !(p_mesh->mp_dl->m_flags & 0x00200000) )\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tGXSetNumTevStages( 1 );\r\n//\t\t\t\t\t\t\tGXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);\r\n//\t\t\t\t\t\t\tGXSetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\t\t\t\t\tGXSetNumTexGens( 0 );\r\n//\t\t\t\t\t\t\tGXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\t\t\t\t\tGXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n////\t\t\t\t\t\t\tGXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t\t\t\t\t\t\tGXSetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n//\t\t\t\t\t\t\tGXSetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n//\t\t\t\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n//\t\t\t\t\t\t\tGXSetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\t\t\t\t\t\t\tGXSetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n////\t\t\t\t\t\t\tGXSetChanMatColor( GX_COLOR0A0, p_pass->m_color );\r\n//\r\n//\t\t\t\t\t\t\tGX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size ); \r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tmulti_mesh( p_mesh, p_posNormBuffer );\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\t// Now draw the opaque meshes with shadow mapped on them.\r\n//\t\t\t\tif( p_scene->m_flags & SCENE_FLAG_RECEIVE_SHADOWS )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( !( p_mesh->m_flags & sMesh::MESH_FLAG_NO_SKATER_SHADOW ) )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tif( frustum_check_sphere( light, p_scene->m_opaque_meshes[e]->m_sphere ))\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t//if( frustum_check_box( light, p_scene->m_opaque_meshes[e]->m_bbox ))\r\n//\t\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t\tif ( shadow_meshes <  MAX_SHADOW_MESHES )\r\n//\t\t\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t\t\tpShadow[shadow_meshes] = p_mesh;\r\n//\t\t\t\t\t\t\t\t\tshadow_meshes++;\r\n//\t\t\t\t\t\t\t\t}\r\n//\t\t\t\t\t\t\t}\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t}\t\t\t\r\n//\t}\t\t\t\r\n//\r\n//// Render semi-transparent meshes.\r\n//\tif( (flags & vRENDER_SEMITRANSPARENT) && !(flags & vRENDER_SHADOW_1ST_PASS) )\r\n//\t{\r\n//\t\tint e = 0;\r\n//\t\tint next_sorted_mesh_entry = 0;\r\n//\t\t\r\n//\t\t// Semitransparent rendering is done in three stages.\r\n//\t\t// The first stage is meshes in the list up to the point where dynamic sorting starts.\r\n//\t\t// The second stage is meshes in the list which use dynamic sorting.\r\n//\t\t// The third stage is meshes in the list beyond the point where dynamic sorting ends.\r\n//\t\tfor( ; e < p_scene->m_first_dynamic_sort_entry; ++e )\r\n//\t\t{\r\n//\t\t\tif ( p_scene->m_semitransparent_meshes[e]->m_flags & sMesh::MESH_FLAG_VISIBLE )\r\n//\t\t\t{\r\n//\t\t\t\tsMesh * p_mesh = p_scene->m_semitransparent_meshes[e];\r\n//\t\t\r\n////\t\t\t\tset_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );\r\n//\r\n//\t\t\t\t++meshes_rendered;\r\n//\r\n//\t\t\t\tif ( flags & vRENDER_NEW_TEST )\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// Textured.\r\n//\t\t\t\t\t// First pass material setup.\r\n//\t\t\t\t\tsMaterialHeader * p_mat = p_mesh->mp_dl->m_material.p_header;\r\n//\t\t\t\t\tsMaterialPassHeader * p_pass = (sMaterialPassHeader *)&p_mat[1];\r\n//\r\n//\t\t\t\t\tif ( p_pass[0].m_texture.p_data )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tif ( first_mat || !one_mat )\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tfirst_mat = false;\r\n//\r\n//\t\t\t\t\t\t\tMaterialSubmit( p_mesh );\r\n//\t\t\t\t\t\t}\r\n//\r\n//\t\t\t\t\t\tGX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size ); \r\n//\t\t\t\t\t}\r\n//\t\t\t\t\telse\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\t// Untextured.\r\n//\t\t\t\t\t\tif ( !(p_mesh->mp_dl->m_flags & 0x00200000) )\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tGXSetNumTevStages( 1 );\r\n//\t\t\t\t\t\t\tGXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);\r\n//\t\t\t\t\t\t\tGXSetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\t\t\t\t\tGXSetNumTexGens( 0 );\r\n//\t\t\t\t\t\t\tGXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\t\t\t\t\tGXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\t\t\t\t\tGXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t\t\t\t\t\t\tGXSetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n//\t\t\t\t\t\t\tGXSetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n//\t\t\t\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n//\t\t\t\t\t\t\tGXSetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\t\t\t\t\t\t\tGXSetChanMatColor( GX_COLOR0A0, p_pass->m_color );\r\n//\r\n//\t\t\t\t\t\t\tGX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size ); \r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tmulti_mesh( p_mesh, p_posNormBuffer );\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t}\r\n//\r\n//\t\tif( p_scene->m_num_dynamic_sort_entries > 0 )\r\n//\t\t{\r\n//\t\t\t// Second stage - dynamically sorted meshes.\r\n//\t\t\tint last_dynamic_sort_entry = p_scene->m_first_dynamic_sort_entry + p_scene->m_num_dynamic_sort_entries;\r\n//\t\t\tfor( ; e < last_dynamic_sort_entry; ++e )\r\n//\t\t\t{\r\n//\t\t\t\tif ( p_scene->m_semitransparent_meshes[e]->m_flags & sMesh::MESH_FLAG_VISIBLE )\r\n//\t\t\t\t{\r\n//\t\t\t\t\t++meshes_rendered;\r\n//\t\t\t\t\t// Figure the midpoint of this mesh, and sort it into the render list.\r\n//\t\t\t\t\tfloat midpoint = frustum_sort_mid( p_scene->m_semitransparent_meshes[e]->m_sphere );\r\n//\r\n////\t\t\t\t\t// Add this mesh to the visible list.\r\n////\t\t\t\t\tif( !( p_scene->m_semitransparent_meshes[e]->m_flags & sMesh::MESH_FLAG_NO_SKATER_SHADOW ))\r\n////\t\t\t\t\t{\r\n////\t\t\t\t\t\tvisible_mesh_array[visible_mesh_array_index++] = p_scene->m_semitransparent_meshes[e];\r\n////\t\t\t\t\t}\r\n//\r\n//\t\t\t\t\tsortedMeshArray[next_sorted_mesh_entry].p_mesh\t= p_scene->m_semitransparent_meshes[e];\r\n//\t\t\t\t\tsortedMeshArray[next_sorted_mesh_entry].sort\t= midpoint;\r\n//\t\t\t\t\t++next_sorted_mesh_entry;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\tif( next_sorted_mesh_entry > 0 )\r\n//\t\t\t{\r\n//\t\t\t\t// Sort the array into ascending sort order.\r\n//\t\t\t\tqsort( sortedMeshArray, next_sorted_mesh_entry, sizeof( sSortedMeshEntry ), cmp );\r\n//\t\t\r\n//\t\t\t\tfor( int m = 0; m < next_sorted_mesh_entry; ++m )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tsMesh * p_mesh = sortedMeshArray[m].p_mesh;\r\n//\r\n////\t\t\t\t\tset_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );\r\n//\r\n//\t\t\t\t\tif ( flags & vRENDER_NEW_TEST )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\t// Textured.\r\n//\t\t\t\t\t\t// First pass material setup.\r\n//\t\t\t\t\t\tsMaterialHeader * p_mat = p_mesh->mp_dl->m_material.p_header;\r\n//\t\t\t\t\t\tsMaterialPassHeader * p_pass = (sMaterialPassHeader *)&p_mat[1];\r\n//\r\n//\t\t\t\t\t\tif ( p_pass[0].m_texture.p_data )\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tif ( first_mat || !one_mat )\r\n//\t\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t\tfirst_mat = false;\r\n//\r\n//\t\t\t\t\t\t\t\tMaterialSubmit( p_mesh );\r\n//\t\t\t\t\t\t\t}\r\n//\r\n//\t\t\t\t\t\t\tGX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size ); \r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t\telse\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t// Untextured.\r\n//\t\t\t\t\t\t\tif ( !(p_mesh->mp_dl->m_flags & 0x00200000) )\r\n//\t\t\t\t\t\t\t{\r\n//\t    \t\t\t\t\t\tGXSetNumTevStages( 1 );\r\n//\t\t\t\t\t\t\t\tGXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);\r\n//\t\t\t\t\t\t\t\tGXSetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\t\t\t\t\t\tGXSetNumTexGens( 0 );\r\n//\t\t\t\t\t\t\t\tGXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\t\t\t\t\t\tGXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\t\t\t\t\t\tGXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t\t\t\t\t\t\t\tGXSetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n//\t\t\t\t\t\t\t\tGXSetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n//\t\t\t\t\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n//\t\t\t\t\t\t\t\tGXSetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\t\t\t\t\t\t\t\tGXSetChanMatColor( GX_COLOR0A0, p_pass->m_color );\r\n//\r\n//\t\t\t\t\t\t\t\tGX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size ); \r\n//\t\t\t\t\t\t\t}\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\telse\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tmulti_mesh( p_mesh, p_posNormBuffer );\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\r\n//\t\t\t// Third stage - meshes after the dynamically sorted set.\r\n//\t\t\tfor( ; e < p_scene->m_num_semitransparent_entries; ++e )\r\n//\t\t\t{\r\n//\t\t\t\tif ( p_scene->m_semitransparent_meshes[e]->m_flags & sMesh::MESH_FLAG_VISIBLE )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tsMesh * p_mesh = p_scene->m_semitransparent_meshes[e];\r\n//\r\n////\t\t\t\t\tset_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );\r\n//\r\n//\t\t\t\t\t++meshes_rendered;\r\n//\r\n//\t\t\t\t\tif ( flags & vRENDER_NEW_TEST )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\t// Textured.\r\n//\t\t\t\t\t\t// First pass material setup.\r\n//\t\t\t\t\t\tsMaterialHeader * p_mat = p_mesh->mp_dl->m_material.p_header;\r\n//\t\t\t\t\t\tsMaterialPassHeader * p_pass = (sMaterialPassHeader *)&p_mat[1];\r\n//\r\n//\t\t\t\t\t\tif ( p_pass[0].m_texture.p_data )\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tif ( first_mat || !one_mat )\r\n//\t\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t\tfirst_mat = false;\r\n//\r\n//\t\t\t\t\t\t\t\tMaterialSubmit( p_mesh );\r\n//\t\t\t\t\t\t\t}\r\n//\r\n//\t\t\t\t\t\t\tGX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size ); \r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t\telse\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t// Untextured.\r\n//\t\t\t\t\t\t\tif ( !(p_mesh->mp_dl->m_flags & 0x00200000) )\r\n//\t\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t\tGXSetNumTevStages( 1 );\r\n//\t\t\t\t\t\t\t\tGXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);\r\n//\t\t\t\t\t\t\t\tGXSetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\t\t\t\t\t\tGXSetNumTexGens( 0 );\r\n//\t\t\t\t\t\t\t\tGXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\t\t\t\t\t\tGXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\t\t\t\t\t\tGXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t\t\t\t\t\t\t\tGXSetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n//\t\t\t\t\t\t\t\tGXSetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n//\t\t\t\t\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n//\t\t\t\t\t\t\t\tGXSetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\t\t\t\t\t\t\t\tGXSetChanMatColor( GX_COLOR0A0, p_pass->m_color );\r\n//\r\n//\t\t\t\t\t\t\t\tGX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size ); \r\n//\t\t\t\t\t\t\t}\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\telse\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tmulti_mesh( p_mesh, p_posNormBuffer );\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t}\r\n//\r\n////\t\t// Now draw the semitransparent meshes with shadow mapped on them.\r\n////\t\tif( p_scene->m_flags & SCENE_FLAG_RECEIVE_SHADOWS )\r\n////\t\t{\r\n////\t\t\trender_shadow_meshes( p_scene, visible_mesh_array, visible_mesh_array_index );\r\n////\t\t}\r\n//\t}\r\n//\r\n////\tif ( 0 )\r\n//\t{\r\n//\t// Render shadow meshes.\r\n//\tif( flags & vRENDER_SHADOW_1ST_PASS )\r\n//\t{\r\n//\t\tint e;\r\n//\t\tfor( e = 0; e < p_scene->m_num_opaque_entries; ++e )\r\n//\t\t{\r\n//\t\t\tif ( p_scene->m_opaque_meshes[e]->m_flags & sMesh::MESH_FLAG_VISIBLE )\r\n//\t\t\t{\r\n//\t\t\t\tsMesh * p_mesh = p_scene->m_opaque_meshes[e];\r\n//\t\t\r\n////\t\t\t\tset_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );\r\n//\r\n//\t\t\t\tif ( p_posNormBuffer ) {\r\n//\t\t\t\t\t// Skinned.\r\n//\t\t\t\t\tmulti_start_16 ( &p_posNormBuffer[0], &p_posNormBuffer[3], 6, 6 );\r\n//\t\t\t\t} else {\r\n//\t\t\t\t\t// Not skinned.\r\n//#ifdef SHORT_VERT\r\n//\t\t\t\t\tcam_offset( p_mesh->m_offset_x, p_mesh->m_offset_y, p_mesh->m_offset_z );\r\n//\t\t\t\t\tmulti_start_16 ( p_mesh->mp_posBuffer, p_mesh->mp_normBuffer, 3, 3 );\r\n//#else\r\n//\t\t\t\t\tmulti_start ( p_mesh->mp_posBuffer, p_mesh->mp_normBuffer, 3, 3 );\r\n//#endif\t\t// SHORT_VERT\r\n//\t\t\t\t}\r\n//\t\t\t\t\r\n//\t\t\t\tmulti_end( p_mesh, vRENDER_SHADOW_1ST_PASS );\r\n//\t\t\t}\r\n//\t\t}\t\t\t\r\n//\r\n//\t\tfor( e = 0; e < p_scene->m_num_semitransparent_entries; ++e )\r\n//\t\t{\r\n//\t\t\tif ( p_scene->m_semitransparent_meshes[e]->m_flags & sMesh::MESH_FLAG_VISIBLE )\r\n//\t\t\t{\r\n//\t\t\t\tsMesh * p_mesh = p_scene->m_semitransparent_meshes[e];\r\n//\r\n////\t\t\t\tset_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );\r\n//\r\n//\t\t\t\tif ( p_posNormBuffer ) {\r\n//\t\t\t\t\t// Skinned.\r\n//\t\t\t\t\tmulti_start_16 ( &p_posNormBuffer[0], &p_posNormBuffer[3], 6, 6 );\r\n//\t\t\t\t} else {\r\n//\t\t\t\t\t// Not skinned.\r\n//#ifdef SHORT_VERT\r\n//\t\t\t\t\tcam_offset( p_mesh->m_offset_x, p_mesh->m_offset_y, p_mesh->m_offset_z );\r\n//\t\t\t\t\tmulti_start_16 ( p_mesh->mp_posBuffer, p_mesh->mp_normBuffer, 3, 3 );\r\n//#else\r\n//\t\t\t\t\tmulti_start ( p_mesh->mp_posBuffer, p_mesh->mp_normBuffer, 3, 3 );\r\n//#endif\t\t// SHORT_VERT\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tmulti_end( p_mesh, vRENDER_SHADOW_1ST_PASS );\r\n//\t\t\t}\r\n//\t\t}\t\t\t\r\n//\t}\t\t\t\r\n//\r\n//\t// Render shadows from list.\r\n//#if 1\r\n//\tfor ( int lp = 0; lp < shadow_meshes; lp++ )\r\n//\t{\r\n//\t\tGXTlutObj\tpalObj;\r\n//\t\tGXInitTlutObj( &palObj, &shadowPalette, GX_TL_RGB5A3, 16 );\r\n//\t\tGXLoadTlut ( &palObj, GX_TLUT0 );\r\n//\r\n//\t\t// Set up shadow map texture\r\n//#define SHADOW_TEXTURE_SIZE 256\r\n//#define BLUR_TEXTURE_SIZE 64\r\n//\t\tGXTexObj blurTexture;\r\n//\t\tGXTexObj shadowTexture;\r\n//\t\tGXInitTexObjCI(\r\n//\t\t\t&blurTexture,\r\n//\t\t\tblurTextureData,\t\t//shadowTextureData,\r\n//\t\t\tBLUR_TEXTURE_SIZE,\t\t//SHADOW_TEXTURE_SIZE,\r\n//\t\t\tBLUR_TEXTURE_SIZE,        //SHADOW_TEXTURE_SIZE,\r\n//\t\t\tGX_TF_C4,\r\n//\t\t\tGX_CLAMP,\r\n//\t\t\tGX_CLAMP,\r\n//\t\t\tGX_FALSE,\r\n//\t\t\tGX_TLUT0 );\r\n////\tGXInitTexObjLOD(&blurTexture, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);\r\n//\t\tGXLoadTexObj( &blurTexture, GX_TEXMAP5 );\r\n//\t\tGXInitTexObjCI(\r\n//\t\t\t&shadowTexture,\r\n//\t\t\tshadowTextureData,\r\n//\t\t\tSHADOW_TEXTURE_SIZE,\r\n//\t\t\tSHADOW_TEXTURE_SIZE,\r\n//\t\t\tGX_TF_C4,\r\n//\t\t\tGX_CLAMP,\r\n//\t\t\tGX_CLAMP,\r\n//\t\t\tGX_FALSE,\r\n//\t\t\tGX_TLUT0 );\r\n////\tGXInitTexObjLOD(&shadowTexture, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);\r\n//\t\tGXLoadTexObj( &shadowTexture, GX_TEXMAP6 );\r\n//\t\r\n//\t\t// Offset the texture matrix.\r\n//#ifdef SHORT_VERT\r\n//\t\tMtx m;\r\n//\t\tMTXTrans( m, pShadow[lp]->m_offset_x, pShadow[lp]->m_offset_y, pShadow[lp]->m_offset_z );\r\n//\t\tMTXConcat( light, m, m );\r\n//\t\tGXLoadTexMtxImm( m, GX_TEXMTX7, GX_MTX3x4 );\r\n//#endif\t\t// SHORT_VERT\r\n//\r\n//\t\tif ( p_posNormBuffer ) {\r\n//\t\t\t// Skinned.\r\n//\t\t\tmulti_start_16 ( &p_posNormBuffer[0], &p_posNormBuffer[3], 6, 6 );\r\n//\t\t} else {\r\n//\t\t\t// Not skinned.\r\n//#ifdef SHORT_VERT\r\n//\t\t\tcam_offset( pShadow[lp]->m_offset_x, pShadow[lp]->m_offset_y, pShadow[lp]->m_offset_z );\r\n//\t\t\tmulti_start_16 ( pShadow[lp]->mp_posBuffer, pShadow[lp]->mp_normBuffer, 3, 3 );\r\n//#else\r\n//\t\t\tmulti_start ( pShadow[lp]->mp_posBuffer, pShadow[lp]->mp_normBuffer, 3, 3 );\r\n//#endif\t\t// SHORT_VERT\r\n//\t\t}\r\n//\r\n//\t\tmulti_end( pShadow[lp], vRENDER_SHADOW_2ND_PASS );\r\n//\t}\r\n//#endif\r\n//\t}\r\n//\r\n////\tif( flags & vRENDER_SEMITRANSPARENT )\r\n////\t{\r\n////\t\t// Sort semi-transparent meshes.\r\n////\t\tint bucket_size = p_scene->m_num_semitransparent_entries * 2;\r\n////\t\tsMesh * sorted_meshes[bucket_size];\r\n////\t\tmemset( sorted_meshes, 0, bucket_size * 4 );\r\n////\t\tfor( int e = 0; e < p_scene->m_num_semitransparent_entries; ++e )\r\n////\t\t{\r\n////\t\t\tif( p_scene->m_semitransparent_meshes[e]->m_flags & sMesh::MESH_FLAG_ACTIVE )\r\n////\t\t\t{\r\n////\t\t\t\t// Frustum cull this set of meshes, using the associated bounding box.\r\n////\t\t\t\tfloat z;\r\n////\t\t\t\tif( frustum_check_sphere( p_scene->m_semitransparent_meshes[e]->m_sphere, &z ))\r\n////\t\t\t\t{\r\n////\t\t\t\t\tint index = (int)( z / ( 20000.0f / bucket_size ) );\r\n////\t\t\t\t\tif ( index < 0 ) index = 0;\r\n////\t\t\t\t\tif ( index > (bucket_size - 1) ) index = (bucket_size - 1);\r\n////\t\r\n////\t\t\t\t\tif ( index >= (bucket_size / 2) )\r\n////\t\t\t\t\t{\r\n////\t\t\t\t\t\t// Search backwards to find an empty slot.\r\n////\t\t\t\t\t\twhile ( sorted_meshes[index] ) index--;\r\n////\t\t\t\t\t\tif ( index >= 0 )\r\n////\t\t\t\t\t\t{\r\n////\t\t\t\t\t\t\tsorted_meshes[index] = p_scene->m_semitransparent_meshes[e];\r\n////\t\t\t\t\t\t}\r\n////\t\t\t\t\t}\r\n////\t\t\t\t\telse\r\n////\t\t\t\t\t{\r\n////\t\t\t\t\t\t// Search forwards to find an empty slot.\r\n////\t\t\t\t\t\twhile ( sorted_meshes[index] ) index++;\r\n////\t\t\t\t\t\tif ( index < bucket_size )\r\n////\t\t\t\t\t\t{\r\n////\t\t\t\t\t\t\tsorted_meshes[index] = p_scene->m_semitransparent_meshes[e];\r\n////\t\t\t\t\t\t}\r\n////\t\t\t\t\t}\r\n////\t\t\t\t}\r\n////\t\t\t}\r\n////\t\t}\r\n////\t\r\n////\t\t// Render semi-transparent meshes.\r\n////\t\tfor( int e = 0; e < bucket_size; ++e )\r\n////\t\t{\r\n////\t\t\tif( sorted_meshes[e] )\r\n////\t\t\t{\r\n////\t\t\t\t++meshes_rendered;\r\n////\t\r\n////\t\t\t\tsMesh * p_mesh = sorted_meshes[e];\r\n////\t\t\t\t\r\n////\t\t\t\tset_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );\r\n////\r\n//////\t\t\t\tif ( p_mesh->mp_uvBuffer && p_mesh->mp_material->pTex[0] )\r\n////\t\t\t\t{\r\n////\t\t\t\t\tuint32 layer;\r\n////\r\n////\t\t\t\t\tif ( p_posNormBuffer ) {\r\n////\t\t\t\t\t\t// Skinned.\r\n////\t\t\t\t\t\tmulti_start ( &p_posNormBuffer[0], &p_posNormBuffer[3], 6, 6 );\r\n////\t\t\t\t\t} else {\r\n////\t\t\t\t\t\t// Not skinned.\r\n////\t\t\t\t\t\tmulti_start ( p_mesh->mp_posBuffer, p_mesh->mp_normBuffer, 3, 3 );\r\n////\t\t\t\t\t}\r\n////\t\t\t\t\tmulti_add_color ( p_mesh->mp_colBuffer );\r\n////\t\t\t\t\tint uv_set = 0;\r\n////\t\t\t\t\tfloat * p_tex;\r\n////\t\t\t\t\tfor ( layer = 0; layer < p_mesh->mp_material->Passes ; layer++ )\r\n////\t\t\t\t\t{\r\n////\t\t\t\t\t\tGXTexWrapMode u_mode;\r\n////\t\t\t\t\t\tGXTexWrapMode v_mode;\r\n////\t\t\t\t\t\tif ( p_mesh->mp_material->Flags[layer] & MATFLAG_ENVIRONMENT )\r\n////\t\t\t\t\t\t{\r\n////\t\t\t\t\t\t\tp_tex = NULL;\r\n////\t\t\t\t\t\t\tu_mode = GX_REPEAT;\r\n////\t\t\t\t\t\t\tv_mode = GX_REPEAT;\r\n////\t\t\t\t\t\t}\r\n////\t\t\t\t\t\telse\r\n////\t\t\t\t\t\t{\r\n////\t\t\t\t\t\t\tp_tex = &p_mesh->mp_uvBuffer[2*uv_set];\r\n////\t\t\t\t\t\t\tu_mode = p_mesh->mp_material->UVAddressing[layer] & (1<<0)  ? GX_CLAMP : GX_REPEAT;\r\n////\t\t\t\t\t\t\tv_mode = p_mesh->mp_material->UVAddressing[layer] & (1<<1) ? GX_CLAMP : GX_REPEAT;\r\n////\t\t\t\t\t\t}\r\n////\t\t\t\t\t\tuv_set++;\r\n////\r\n////\t\t\t\t\t\tmulti_add_texture ( p_tex, p_mesh->m_num_uv_sets, p_mesh->mp_material->uv_slot[layer], p_mesh->mp_material->Flags[layer], layer );\r\n////\t\t\t\t\t}\r\n////\r\n////\t\t\t\t\tmulti_end( p_mesh, 0 );\r\n////\t\t\t\t}\r\n////\t\t\t}\r\n////\t\t}\t\t\t\r\n////\t}\t\t\t\r\n//\t\r\n//\tif ( p_scene->m_numHierarchyObjects != 0 )\r\n//\t{\r\n//\t\t// Hierarchical, set to matrix 0.\r\n//\t\tGXSetCurrentMtx( GX_PNMTX0 );\r\n//\t}\r\n\tGX::SetProjectionv( pm );\r\n\tg_object++;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Sets MESH_FLAG_VISIBLE if visible for all meshes in this scene */\r\n/*                                                                */\r\n/******************************************************************/\r\nint cull_scene( sScene *p_scene, uint32 flags )\r\n{\r\n\tint meshes_visible = 0;\r\n\r\n\t// Cull all meshes.\r\n\tsMesh ** pp_mesh = p_scene->mpp_mesh_list;\r\n\r\n\tfor( int e = 0; e < p_scene->m_num_filled_meshes; ++e )\r\n\t{\r\n\t\tsMesh * p_mesh = pp_mesh[e];\r\n\t\tif( ( p_mesh->m_flags & sMesh::MESH_FLAG_ACTIVE ) && ( p_mesh->GetVisibility() & EngineGlobals.viewport ) )\r\n\t\t{\r\n\t\t\tMth::Vector sphere = p_mesh->mp_dl->m_sphere;\r\n\r\n\t\t\t// Frustum cull this set of meshes, using the associated bounding box.\r\n\t\t\tif( frustum_check_sphere( sphere ))\r\n\t\t\t{\r\n\t\t\t\t// Sphere is visible.\r\n\t\t\t\tif( ( flags & vRENDER_OCCLUDED ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( TestSphereAgainstOccluders( &sphere ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Occluded.\r\n\t\t\t\t\t\tp_mesh->m_flags &= ~sMesh::MESH_FLAG_VISIBLE;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Not occluded.\r\n\t\t\t\t\t\tp_mesh->m_flags |= sMesh::MESH_FLAG_VISIBLE;\r\n\t\t\t\t\t\t++meshes_visible;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Sphere being visible is enough.\r\n\t\t\t\t\tp_mesh->m_flags |= sMesh::MESH_FLAG_VISIBLE;\r\n\t\t\t\t\t++meshes_visible;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Sphere not visible.\r\n\t\t\t\tp_mesh->m_flags &= ~sMesh::MESH_FLAG_VISIBLE;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Force to be not visible.\r\n\t\t\tp_mesh->m_flags &= ~sMesh::MESH_FLAG_VISIBLE;\r\n\t\t}\r\n\t}\r\n\treturn meshes_visible;\r\n\r\n//\tmake_scene_visible( p_scene );\r\n//\treturn p_scene->m_num_filled_meshes;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Sets MESH_FLAG_VISIBLE for all meshes in this scene.\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid make_scene_visible( sScene *p_scene )\r\n{\r\n\t// Set all meshes to be visible.\r\n\tsMesh ** pp_mesh = p_scene->mpp_mesh_list;\r\n\r\n\tfor( int e = 0; e < p_scene->m_num_filled_meshes; ++e )\r\n\t{\r\n\t\tif( ( pp_mesh[e]->m_flags & sMesh::MESH_FLAG_ACTIVE ) && ( pp_mesh[e]->GetVisibility() & EngineGlobals.viewport ) )\r\n\t\t{\r\n\t\t\tpp_mesh[e]->m_flags |= sMesh::MESH_FLAG_VISIBLE;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid render_begin( void )\r\n{\r\n\r\n}\r\n\r\nvoid render_end( void )\r\n{\r\n\r\n}\r\n\r\n} // namespace NxNgc\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/render.h",
    "content": "#ifndef __RENDER_H\r\n#define __RENDER_H\r\n\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n#include <gfx/ngc/p_nxmodel.h>\r\n#include \"mesh.h\"\r\n#include \"scene.h\"\r\n#include <sys/ngc/p_vector.h>\r\n#include <sys/ngc/p_matrix.h>\r\n\r\n#define\t\tRS_ZWRITEENABLE\t\t\t1\r\n#define\t\tRS_ZTESTENABLE\t\t\t2\r\n#define\t\tRS_ALPHACUTOFF\t\t\t3\r\n#define\t\tRS_UVADDRESSMODE0\t\t4\r\n#define\t\tRS_UVADDRESSMODE1\t\t5\r\n#define\t\tRS_UVADDRESSMODE2\t\t6\r\n#define\t\tRS_UVADDRESSMODE3\t\t7\r\n\r\nnamespace NxNgc\r\n{\r\n\tstruct sTextureProjectionDetails\r\n\t{\r\n\t\tsTexture\t\t*p_texture;\r\n\t\tNx::CNgcModel\t*p_model;\r\n\t\tsScene\t\t\t*p_scene;\r\n\t\tNsMatrix\t\tview_matrix;\r\n\t\tNsMatrix\t\tprojection_matrix;\r\n\t\tNsMatrix\t\ttexture_projection_matrix;\r\n\t};\r\n\r\n\textern Lst::HashTable< sTextureProjectionDetails > *pTextureProjectionDetailsTable;\r\n\t\r\n\ttypedef enum\r\n\t{\r\n\t\tvBLEND_MODE_DIFFUSE,\t\t\t\t\t\t// ( 0 - 0 ) * 0 + Src\r\n\t\tvBLEND_MODE_ADD,\t\t\t\t\t\t\t// ( Src - 0 ) * Src + Dst\r\n\t\tvBLEND_MODE_ADD_FIXED,\t\t\t\t\t\t// ( Src - 0 ) * Fixed + Dst\r\n\t\tvBLEND_MODE_SUBTRACT,\t\t\t\t\t\t// ( 0 - Src ) * Src + Dst\r\n\t\tvBLEND_MODE_SUB_FIXED,\t\t\t\t\t\t// ( 0 - Src ) * Fixed + Dst\r\n\t\tvBLEND_MODE_BLEND,\t\t\t\t\t\t\t// ( Src * Dst ) * Src + Dst\t\r\n\t\tvBLEND_MODE_BLEND_FIXED,\t\t\t\t\t// ( Src * Dst ) * Fixed + Dst\t\r\n\t\tvBLEND_MODE_MODULATE,\t\t\t\t\t\t// ( Dst - 0 ) * Src + 0\r\n\t\tvBLEND_MODE_MODULATE_FIXED,\t\t\t\t\t// ( Dst - 0 ) * Fixed + 0\t\r\n\t\tvBLEND_MODE_BRIGHTEN,\t\t\t\t\t\t// ( Dst - 0 ) * Src + Dst\r\n\t\tvBLEND_MODE_BRIGHTEN_FIXED,\t\t\t\t\t// ( Dst - 0 ) * Fixed + Dst\t\r\n\t\tvBLEND_MODE_GLOSS_MAP,\t\t\t\t\t\t// Specular = Specular * Src\t- special mode for gloss mapping\r\n\t\tvBLEND_MODE_BLEND_PREVIOUS_MASK,\t\t\t// ( Src - Dst ) * Dst + Dst\r\n\t\tvBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK,\t// ( Dst - Src ) * Dst + Src\r\n\r\n\t\tvNUM_BLEND_MODES\r\n\t} BlendModes; \r\n\r\n\ttypedef enum\r\n\t{\r\n\t\tvRENDER_OPAQUE\t\t\t= 1,\t\t\t\t\t\t\r\n\t\tvRENDER_SEMITRANSPARENT\t= 2,\r\n\t\tvRENDER_OCCLUDED\t\t= 4,\r\n\t\tvRENDER_NO_CULLING\t\t= 8,\t\t// Used for instances which have already been culled at a higher level\r\n\t\tvRENDER_SHADOW_1ST_PASS = 16,\r\n\t\tvRENDER_SHADOW_2ND_PASS = 32,\r\n\t\tvRENDER_NEW_TEST\t\t= 64,\r\n\t\tvRENDER_INSTANCE_PRE_WORLD_SEMITRANSPARENT\t= 128,\t\t// Used to indicate that this instance rendering is happening prior to semitransparent world rendering\r\n\t\tvRENDER_INSTANCE_POST_WORLD_SEMITRANSPARENT\t= 256,\t\t// Used to indicate that this instance rendering is happening after semitransparent world rendering\r\n\t\tvRENDER_TRANSFORM\t\t= 512,\r\n\t\tvRENDER_LIT\t\t\t\t= 1024,\r\n\t\tvNUM_SCENE_RENDER_FLAGS\r\n\t} SceneRenderFlags; \r\n\r\n\tvoid\tinit_render_system();\r\n\tvoid\tset_render_state( uint32 type, uint32 state );\r\n\tvoid\tset_blend_mode( uint64 mode );\r\n\r\n\tvoid\tcreate_texture_projection_details( sTexture *p_texture, Nx::CNgcModel *p_model, sScene *p_scene );\r\n\tvoid\tdestroy_texture_projection_details( sTexture *p_texture );\r\n\tvoid\tset_texture_projection_camera( sTexture *p_texture, NsVector * p_pos, NsVector * p_at );\r\n\tvoid\tcalculate_tex_proj_matrix( NsMatrix * p_tex_view_matrix, NsMatrix * p_tex_proj_matrix, NsMatrix * p_tex_transform_matrix, NsMatrix * p_world_matrix = NULL );\r\n\t\r\n\tvoid\tset_camera( Mth::Matrix *p_matrix, Mth::Vector *p_position, float screen_angle, float aspect_ratio, float scale = 1.0f );\r\n\tvoid\tset_frustum_bbox_transform( Mth::Matrix *p_transform );\r\n\tbool\tfrustum_check_box( Mth::CBBox& box );\r\n\tbool\tfrustum_check_sphere( Mth::Vector& p_sphere );\r\n\tbool\tfrustum_check_sphere( Mth::Vector& p_sphere, float * p_z );\r\n\tvoid\trender_scene( sScene *p_scene, s16* p_posNormBuffer, uint32 flags = ( vRENDER_OPAQUE | vRENDER_SEMITRANSPARENT ), Mth::Matrix * p_bone_xform = NULL, Mth::Matrix * p_instance_xform = NULL, int num_bones = 0 );\r\n\tbool\tIsVisible( Mth::Vector &sphere );\r\n\tvoid\trender_shadow_targets();\r\n\r\n\tint\t\tcull_scene( sScene *p_scene, uint32 flags = 0 );\r\n\tvoid\tmake_scene_visible( sScene *p_scene );\r\n\r\n\tvoid\trender_begin( void );\r\n\tvoid\trender_end( void );\r\n} // namespace NxNgc\r\n\r\n#endif // __RENDER_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/scene.cpp",
    "content": "#include <sys/file/filesys.h>\r\n\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <string.h>\r\n#include \"texture.h\"\r\n#include \"mesh.h\"\r\n#include \"scene.h\"\r\n#include \"render.h\"\r\n#include <sys/ngc/p_gx.h>\r\n#include \"nx_init.h\"\r\n#include <sys/timer.h>\r\n#include <dolphin\\gd.h>\r\n#include <gel/music/Ngc/p_music.h>\r\n\r\n#define ENV_MAP_SCROLL_SCALE ( 1.0f / 32768.0f )\r\n\r\nint g_dl = 1;\r\n\r\nbool gOverDraw = false;\r\n\r\nnamespace NxNgc\r\n{\r\n\r\nstatic s32\tlast_audio_update = 0;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void do_audio_update( void )\r\n{\r\n\ts32 t = OSGetTick();\r\n\tif(( t < last_audio_update ) || ( OSDiffTick( t, last_audio_update ) > (s32)( OS_TIMER_CLOCK / 60 )))\r\n\t{\r\n\t\tlast_audio_update = t;\r\n\t\tPcm::PCMAudio_Update();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int sort_by_material_draw_order( const void *p1, const void *p2 )\r\n{\r\n\tsMesh\t\t\t*p_mesh1\t\t= *((sMesh**)p1 );\r\n\tsMesh\t\t\t*p_mesh2\t\t= *((sMesh**)p2 );\r\n\tsMaterialHeader\t*p_material1\t= p_mesh1->mp_dl->m_material.p_header;\r\n\tsMaterialHeader\t*p_material2\t= p_mesh2->mp_dl->m_material.p_header;\r\n\t\r\n\tDbg_Assert( p_material1 != NULL );\r\n\tDbg_Assert( p_material2 != NULL );\r\n\r\n\tif( p_material1->m_draw_order == p_material2->m_draw_order )\r\n\t{\r\n\t\t// Have to do some special case processing for the situation where two or more meshes have the same draw order, but only some are\r\n\t\t// marked as being dynamically sorted. In such a situation the non dynamically sorted ones should come first.\r\n\t\tif( ( p_material1->m_flags & (1<<0) ) == ( p_material2->m_flags & (1<<0) ) )\r\n\t\t{\r\n\t\t\tif( p_material1 == p_material2 )\r\n\t\t\t{\r\n\t\t\t\t// Same material, no further sorting required.\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// If the blend mode is the same, sort by material address.\r\n\t\t\t\tif( p_material1->m_base_blend == p_material2->m_base_blend )\r\n\t\t\t\t{\r\n\t\t\t\t\t// If the pixel shaders are the same, sort by material address, otherwise sort by pixel shader value.\r\n\t\t\t\t\tif( p_material1->m_texture_dl_id == p_material2->m_texture_dl_id )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn ((uint32)p_material1 > (uint32)p_material2 ) ? 1 : -1;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn ((uint32)p_material1->m_texture_dl_id < (uint32)p_material2->m_texture_dl_id ) ? 1 : -1;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\treturn ((uint32)p_material1->m_base_blend > (uint32)p_material2->m_base_blend ) ? 1 : -1;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( p_material1->m_flags & (1<<0) )\r\n\t\t{\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t\treturn -1;\r\n\t}\r\n\treturn ( p_material1->m_draw_order > p_material2->m_draw_order ) ? 1 : -1;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#define INDEX_WORKBUFFER_SIZE\t1700\r\n#define MAX_STRIPS\t\t\t\t1024\r\n#define MAX_INDEX_WIDTH\t\t\t7\r\n\r\n// Maximum index width:\r\n// 1 position\r\n// 1 normal\r\n// 2 colors\r\n// 4 tex coord\r\n\t\r\nstatic void hide_mesh( uint32 mask, sCASData *p_cas_data, uint32 num_entries, sMesh * p_mesh )\r\n{\r\n\tuint16\tindex_workbuffer[INDEX_WORKBUFFER_SIZE][MAX_INDEX_WIDTH];\r\n\tuint32\tnew_indices_index = 0;\r\n\r\n\tint\t\tindex_strip_len[MAX_STRIPS];\r\n\tint\t\tnum_strips = 0;\r\n\r\n\t// Clear strips.\r\n\tfor ( int lp = 0; lp < MAX_STRIPS; lp++ )\r\n\t{\r\n\t\tindex_strip_len[lp] = 0;\r\n\t}\r\n\r\n\tunsigned char * p_start = (unsigned char *)&p_mesh->mp_dl[1];\r\n\tunsigned char * p_end = &p_start[p_mesh->mp_dl->m_size];\r\n\tp_start = &p_start[p_mesh->mp_dl->m_index_offset];\t\t// Skip to actual 1st GDBegin.\r\n\tunsigned char * p8 = p_start;\r\n\r\n\tuint8 begin_token = p8[0];\t\t// Save token for use when rebuilding mesh.\r\n\r\n\tint stride = p_mesh->mp_dl->m_index_stride;\r\n\r\n\tint w;\r\n\r\n\twhile ( p8 < p_end )\r\n\t{\r\n\t\tif ( ( p8[0] & 0xf8 ) == GX_TRIANGLESTRIP )\r\n\t\t{\r\n\t\t\t// Found a triangle strip - parse it.\r\n\t\t\tint num_verts = ( p8[1] << 8 ) | p8[2];\r\n\t\t\tp8 += 3;\t\t// Skip GDBegin\r\n\r\n\t\t\tuint16 idx0[MAX_INDEX_WIDTH];\r\n\t\t\tuint16 idx1[MAX_INDEX_WIDTH];\r\n\t\t\tuint16 idx2[MAX_INDEX_WIDTH];\r\n\r\n\t\t\tfor ( w = 0; w < stride; w++ ) { idx1[w] = ( p8[0] << 8 ) | p8[1]; p8 += 2; }\r\n\t\t\tfor ( w = 0; w < stride; w++ ) { idx2[w] = ( p8[0] << 8 ) | p8[1]; p8 += 2; }\r\n\r\n\t\t\tfor ( int v = 2; v < num_verts; v++ )\r\n\t\t\t{\r\n\t\t\t\t// Read next index to form triangle.\r\n\t\t\t\tfor ( w = 0; w < stride; w++ ) idx0[w] = idx1[w];\r\n\t\t\t\tfor ( w = 0; w < stride; w++ ) idx1[w] = idx2[w];\r\n\t\t\t\tfor ( w = 0; w < stride; w++ ) { idx2[w] = ( p8[0] << 8 ) | p8[1]; p8 += 2; } \r\n\r\n\t\t\t\t// There shuold be no degenerate triangles.\r\n\t\t\t\t// ...check against every CAS entry.\r\n\t\t\t\tbool keep = true;\r\n\t\t\t\tfor( uint32 entry = 0; entry < num_entries; ++entry )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Check this CAS entry has the correct mask...\r\n\t\t\t\t\tif( p_cas_data[entry].mask & mask )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// ...and the right mesh...\r\n\t\t\t\t\t\tuint32 mesh = p_cas_data[entry].data0 >> 16;\r\n\t\r\n\t\t\t\t\t\t// The CAS data is ordered first in increasing mesh size - so we can early out here if applicable.\r\n\t\t\t\t\t\tif ( mesh > p_mesh->mp_dl->m_mesh_index )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\r\n\t\t\t\t\t\tif ( mesh == p_mesh->mp_dl->m_mesh_index )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// ...and the correct index.\r\n\t\t\t\t\t\t\tuint32 i0 = ( p_cas_data[entry].data0 & 0xFFFF );\r\n\t\r\n\t\t\t\t\t\t\t// The CAS data is next ordered in increasing size of i0 - so we can early out here if applicable.\r\n\t\t\t\t\t\t\tif ( i0 > idx0[0] )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t}\r\n\t\r\n\t\t\t\t\t\t\tuint32 i1 = ( p_cas_data[entry].data1 >> 16 );\r\n\t\t\t\t\t\t\tuint32 i2 = ( p_cas_data[entry].data1 & 0xFFFF );\r\n\t\t\t\t\t\t\tif ( ( i0 == idx0[0] ) && ( i1 == idx1[0] ) && ( i2 == idx2[0] ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tkeep = false;\r\n\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Copy index.\r\n\t\t\t\tif ( keep )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( index_strip_len[num_strips] )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Already put 1st triangle in, just add index.\r\n\t\t\t\t\t\tfor ( w = 0; w < stride; w++ ) index_workbuffer[new_indices_index][w] = idx2[w];\r\n\t\t\t\t\t\tnew_indices_index++;\r\n\t\t\t\t\t\tindex_strip_len[num_strips]++;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// 1st triangle, so add all 3 verts.\r\n\t\t\t\t\t\tfor ( w = 0; w < stride; w++ ) index_workbuffer[new_indices_index][w] = idx0[w];\r\n\t\t\t\t\t\tnew_indices_index ++;\r\n\t\t\t\t\t\tfor ( w = 0; w < stride; w++ ) index_workbuffer[new_indices_index][w] = idx1[w];\r\n\t\t\t\t\t\tnew_indices_index ++;\r\n\t\t\t\t\t\tfor ( w = 0; w < stride; w++ ) index_workbuffer[new_indices_index][w] = idx2[w];\r\n\t\t\t\t\t\tnew_indices_index ++;\r\n\t\t\t\t\t\tindex_strip_len[num_strips] += 3;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// If we don't keep this tri & we already started a strip, we need\r\n\t\t\t\t\t// to start a new strip.\r\n\t\t\t\t\tif ( index_strip_len[num_strips] )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Need to start a new strip.\r\n\t\t\t\t\t\tnum_strips++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// Start a new strip if we put data in this one.\r\n\t\t\tif ( index_strip_len[num_strips] )\r\n\t\t\t{\r\n\t\t\t\t// Need to start a new strip.\r\n\t\t\t\tnum_strips++;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tdo_audio_update();\r\n\r\n\tDbg_MsgAssert( new_indices_index <= INDEX_WORKBUFFER_SIZE, ( \"Too many indices in new mesh: %d\\n\", new_indices_index ) );\r\n\r\n\t// See if we'll fit in the existing buffer.\r\n\tuint32 new_size = ( 3 * num_strips ) + ( sizeof( uint16 ) * stride * new_indices_index ) + p_mesh->mp_dl->m_index_offset;\r\n\r\n//\tOSReport( \"New: %d Old: %d Diff: %d\\n\", new_size, p_mesh->mp_dl->m_size, p_mesh->mp_dl->m_size - new_size );\r\n\r\n//\tif ( new_size > p_mesh->mp_dl->m_original_dl_size )\r\n//\t{\r\n//\t\t// Need to allocate a new buffer for this.\r\n//\t}\r\n\r\n\tif ( new_size <= p_mesh->mp_dl->m_original_dl_size )\r\n\t{\r\n\t\tp8 = p_start;\r\n\t\tint buffer_index = 0;\r\n\r\n\t\tfor ( int strip = 0; strip < num_strips; strip++ )\r\n\t\t{\r\n\t\t\t*p8++ = begin_token;\r\n\t\t\t*p8++ = (uint8)(index_strip_len[strip] >> 8 );\r\n\t\t\t*p8++ = (uint8)(index_strip_len[strip] & 0xff );\r\n\t\t\tfor ( int index = 0; index < index_strip_len[strip]; index++ )\r\n\t\t\t{\r\n\t\t\t\tfor ( w = 0; w < stride; w++ )\r\n\t\t\t\t{\r\n\t\t\t\t\t*p8++ = (uint8)(index_workbuffer[buffer_index][w] >> 8 );\r\n\t\t\t\t\t*p8++ = (uint8)(index_workbuffer[buffer_index][w] & 0xff );\r\n\t\t\t\t}\r\n\t\t\t\tbuffer_index++;\r\n\t\t\t}\r\n\t\t}\r\n\t\t// Set new size of display list.\r\n\t\tint new_rounded_size = ( new_size + 31 ) & ~31;\r\n\t\tp_mesh->mp_dl->m_size = new_rounded_size;\r\n\r\n\t\t// Pad the DL with 0s to avoid spurious crap at the end & flush cache.\r\n\t\tint pad_size = new_rounded_size - new_size;\r\n\t\tfor ( int pad = 0; pad < pad_size; pad++ ) *p8++ = 0;\r\n\r\n\t\tDCFlushRange( &p_mesh->mp_dl[1], new_rounded_size );\r\n\t}\r\n\telse\r\n\t{\r\n#ifdef __NOPT_FINAL__\r\n\t\tOSReport( \"Warning: DL too big after hide_mesh - New: %d Old: %d Diff: %d\\n\", new_size, p_mesh->mp_dl->m_size, p_mesh->mp_dl->m_size - new_size );\r\n#else\r\n\t\tDbg_MsgAssert( false, ( \"Error: DL too big after hide_mesh - New: %d Old: %d Diff: %d\\n\", new_size, p_mesh->mp_dl->m_size, p_mesh->mp_dl->m_size - new_size ) );\r\n#endif\t\t// __NOPT_FINAL__\r\n\t}\r\n\tdo_audio_update();\r\n}\r\n\r\nsScene::sScene( void )\r\n{\r\n\tm_flags\t\t\t\t\t= 0;\r\n\r\n\tm_num_meshes\t\t\t= 0;\t\t// No meshes as yet.\r\n\tm_num_filled_meshes\t\t= 0;\r\n\tmpp_mesh_list\t\t\t= NULL;\r\n\r\n\tmp_hierarchyObjects\t\t= NULL;\r\n\tm_numHierarchyObjects\t= 0;\r\n\r\n\tmp_scene_data\t\t\t= NULL;\r\n\tmp_dl\t\t\t\t\t= NULL;\r\n\r\n\tmp_blend_dl\t\t\t\t= NULL;\r\n\tmp_material_header\t\t= NULL;\r\n\r\n\tmp_hierarchyObjects\t\t= NULL;\r\n\tm_numHierarchyObjects\t= 0;\r\n\r\n\tm_is_dictionary\t\t\t= false;\r\n}\r\n\r\nsScene::~sScene( void )\r\n{\r\n\t// Remove the material table.\r\n//\tif( mp_material_array )\r\n//\t{\r\n//\t\tdelete mp_material_array;\r\n//\t}\r\n//\r\n//\tif( m_opaque_meshes != NULL )\r\n//\t{\r\n//\t\tdelete [] m_opaque_meshes;\r\n//\t}\r\n//\tif( m_semitransparent_meshes != NULL )\r\n//\t{\r\n//\t\tdelete [] m_semitransparent_meshes;\r\n//\t}\r\n//\r\n//\tif ( mp_hierarchyObjects )\r\n//\t{\r\n//\t\tdelete [] mp_hierarchyObjects;\r\n//\t}\r\n//\r\n\r\n//\t// Go through, and see if any DLs got allocated.\r\n//\tint dl = 0;\r\n//\tfor( uint s = 0; s < mp_scene_data->m_num_objects; ++s )\r\n//\t{\r\n//\t\tint num_mesh = mp_dl[dl].mp_object_header->m_num_meshes;\r\n//\t\tfor ( int m = 0; m < num_mesh; m++ )\r\n//\t\t{\r\n//\t\t\tif ( mp_dl[dl].mp_pos_pool )\r\n//\t\t\t{\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n\r\n\r\n\tif ( mp_scene_data && !( m_flags & SCENE_FLAG_CLONED_GEOM ) )\r\n\t{\r\n\t\tdelete [] mp_scene_data;\r\n\t}\r\n\r\n\tif ( mpp_mesh_list )\r\n\t{\r\n\t\tdelete [] mpp_mesh_list;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sScene::AddMeshes( int num_meshes, sMesh **pp_meshes )\r\n{\r\n\t// Add each mesh.\r\n\tfor( int m = 0; m < num_meshes; ++m )\r\n\t{\r\n\t\tif ( m_num_filled_meshes < m_num_meshes )\r\n\t\t{\r\n\t\t\tmpp_mesh_list[m_num_filled_meshes] = pp_meshes[m];\r\n\t\t\t++m_num_filled_meshes;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( false, ( \"Too many meshes being added.\" ) );\r\n\t\t}\r\n\t}\r\n\r\n//\tfor( int m = 0; m < num_meshes; ++m )\r\n//\t{\r\n//\t\tsMaterialHeader *\t\tp_material = pp_meshes[m]->mp_dl->m_material.p_header;\r\n//\t\tsMaterialPassHeader *\tp_pass = &mp_material_pass[p_material->m_pass_item];\r\n//\r\n//\t\tbool transparent = (( p_material ) && ( p_pass->m_flags & (1<<3) ));\r\n//\r\n//\t\tif ( transparent )\r\n//\t\t{\r\n//\t\t\tif ( m_num_filled_meshes < m_num_meshes )\r\n//\t\t\t{\r\n//\t\t\t\tmpp_mesh_list[m_num_filled_meshes] = pp_meshes[m];\r\n//\t\t\t\t++m_num_filled_meshes;\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\tDbg_MsgAssert( false, ( \"Too many meshes being added.\" ) );\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tfor( int m = 0; m < num_meshes; ++m )\r\n//\t{\r\n//\t\tsMaterialHeader *\t\tp_material = pp_meshes[m]->mp_dl->m_material.p_header;\r\n//\t\tsMaterialPassHeader *\tp_pass = &mp_material_pass[p_material->m_pass_item];\r\n//\r\n//\t\tbool transparent = (( p_material ) && ( p_pass->m_flags & (1<<3) ));\r\n//\r\n//\t\tif ( !transparent )\r\n//\t\t{\r\n//\t\t\tif ( m_num_filled_meshes < m_num_meshes )\r\n//\t\t\t{\r\n//\t\t\t\tmpp_mesh_list[m_num_filled_meshes] = pp_meshes[m];\r\n//\t\t\t\t++m_num_filled_meshes;\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\tDbg_MsgAssert( false, ( \"Too many meshes being added.\" ) );\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sScene::CountMeshes( int num_meshes, sMesh **pp_meshes )\r\n{\r\n\tm_num_meshes += (uint16)num_meshes;\r\n\r\n\r\n//\t// Count each mesh.\r\n//\tfor( int m = 0; m < num_meshes; ++m )\r\n//\t{\r\n//\t\t++m_num_meshes;\r\n////\t\tbool transparent = (( pp_meshes[m]->mp_material ) && ( pp_meshes[m]->mp_material->Flags[0] & 0x40 ));\r\n////\t\tif( transparent )\r\n////\t\t{\r\n////\t\t\t++m_num_semitransparent_entries;\r\n////\t\t}\r\n////\t\telse\r\n////\t\t{\r\n////\t\t\t++m_num_opaque_entries;\r\n////\t\t}\r\n//\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sScene::CreateMeshArrays( void )\r\n{\r\n\tif ( m_num_meshes > 0 )\r\n\t{\r\n\t\tmpp_mesh_list = new sMesh*[m_num_meshes];\r\n\t}\r\n\r\n//\tif( m_num_semitransparent_entries > 0 )\r\n//\t{\r\n//\t\tm_semitransparent_meshes = new sMesh*[m_num_semitransparent_entries];\r\n//\t}\r\n//\t\r\n//\tif( m_num_opaque_entries > 0 )\r\n//\t{\r\n//\t\tm_opaque_meshes = new sMesh*[m_num_opaque_entries];\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sScene::FigureBoundingVolumes( void )\r\n{\r\n//\t// Figure bounding sphere assuming bounding box has already been set up (during individual mesh initialisation).\r\n//\tMth::Vector radial\t= ( m_bbox.GetMax() - m_bbox.GetMin() ) * 0.5f;\r\n//\tMth::Vector center\t= m_bbox.GetMin() + radial;\r\n//\tm_sphere_center.set( center[X], center[Y], center[Z] );\r\n//\tm_sphere_radius\t\t= sqrtf(( radial[X] * radial[X] ) +\t( radial[Y] * radial[Y] ) + ( radial[Z] * radial[Z] ));\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nvoid sScene::RemoveMeshes( int num_meshes, sMesh **pp_meshes )\r\n{\r\n\tint num_opaque_entries_removed\t\t\t\t\t= 0;\r\n\tint num_pre_semitransparent_entries_removed\t\t= 0;\r\n\tint num_dynamic_semitransparent_entries_removed\t= 0;\r\n\tint num_post_semitransparent_entries_removed\t= 0;\r\n\t\r\n\tint opaque\t\t= m_num_opaque_meshes;\r\n\tint presemi\t\t= opaque + m_num_pre_semitrans_meshes;\r\n\tint dynsemi\t\t= presemi + m_num_dynamic_semitrans_meshes;\r\n\tint postsemi\t= dynsemi + m_num_post_semitrans_meshes;\r\n\r\n\tfor( int m = 0; m < num_meshes; ++m )\r\n\t{\r\n\t\tsMesh *p_mesh = pp_meshes[m];\r\n\r\n\t\tbool found = false;\r\n\t\t// Search Opaque\r\n\t\tfor ( int i = 0; i < opaque; i++ )\r\n\t\t{\r\n\t\t\tif( mpp_mesh_list[i] == p_mesh )\r\n\t\t\t{\r\n\t\t\t\tfound = true;\r\n\t\t\t\tmpp_mesh_list[i] = NULL;\r\n\t\t\t\t++num_opaque_entries_removed;\r\n\t\t\t\t--m_num_opaque_meshes;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif( found ) continue;\r\n\r\n\t\t// Search Pre Semitransparent\r\n\t\tfor ( int i = opaque; i < presemi; i++ )\r\n\t\t{\r\n\t\t\tif( mpp_mesh_list[i] == p_mesh )\r\n\t\t\t{\r\n\t\t\t\tfound = true;\r\n\t\t\t\tmpp_mesh_list[i] = NULL;\r\n\t\t\t\t++num_pre_semitransparent_entries_removed;\r\n\t\t\t\t--m_num_pre_semitrans_meshes;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( found ) continue;\r\n\r\n\t\t// Search Dynamic Semitransparent\r\n\t\tfor ( int i = presemi; i < dynsemi; i++ )\r\n\t\t{\r\n\t\t\tif( mpp_mesh_list[i] == p_mesh )\r\n\t\t\t{\r\n\t\t\t\tfound = true;\r\n\t\t\t\tmpp_mesh_list[i] = NULL;\r\n\t\t\t\t++num_dynamic_semitransparent_entries_removed;\r\n\t\t\t\t--m_num_dynamic_semitrans_meshes;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( found ) continue;\r\n\r\n\t\t// Search Post Semitransparent\r\n\t\tfor ( int i = dynsemi; i < postsemi; i++ )\r\n\t\t{\r\n\t\t\tif( mpp_mesh_list[i] == p_mesh )\r\n\t\t\t{\r\n\t\t\t\tfound = true;\r\n\t\t\t\tmpp_mesh_list[i] = NULL;\r\n\t\t\t\t++num_post_semitransparent_entries_removed;\r\n\t\t\t\t--m_num_post_semitrans_meshes;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tDbg_Assert( found );\t\r\n\t}\r\n\t\r\n\t// Now go through and compact the arrays.\r\n\r\n//\tint total = m_num_opaque_meshes + m_num_pre_semitrans_meshes + m_num_dynamic_semitrans_meshes + m_num_post_semitrans_meshes;\r\n\tint total_removed = num_opaque_entries_removed +\r\n\t\t\t\t\t\tnum_pre_semitransparent_entries_removed +\r\n\t\t\t\t\t\tnum_dynamic_semitransparent_entries_removed\t+\r\n\t\t\t\t\t\tnum_post_semitransparent_entries_removed;\r\n\r\n\tfor ( int lp = 0; lp < total_removed; lp++ )\r\n\t{\r\n\t\tfor ( int i = 0; i < m_num_filled_meshes; i++ )\r\n\t\t{\r\n\t\t\tif( !mpp_mesh_list[i] )\r\n\t\t\t{\r\n//\t\t\t\tm_num_filled_meshes--;\r\n//\t\t\t\tmpp_mesh_list[i] = mpp_mesh_list[m_num_filled_meshes];\r\n\r\n\r\n\t\t\t\t// Only worth copying if there is anything beyond this mesh.\r\n\t\t\t\tif( i < ( m_num_filled_meshes - 1 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tmemcpy( &mpp_mesh_list[i], &mpp_mesh_list[i + 1], sizeof( sMesh* ) * ( m_num_filled_meshes - ( i + 1 )));\r\n\t\t\t\t}\r\n\t\t\t\tm_num_filled_meshes--;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n//\tSortMeshes();\r\n//\tm_num_filled_meshes -= total_removed;\r\n}\r\n\r\n\r\n\r\nvoid sScene::SortMeshes( void )\r\n{\r\n\t// Sort the list of meshes.\r\n\tqsort( mpp_mesh_list, m_num_filled_meshes, sizeof( sMesh* ), sort_by_material_draw_order );\r\n\r\n\tif ( mp_scene_data )\r\n\t{\r\n\t\tm_num_opaque_meshes\t\t\t\t= 0;\r\n\t\tm_num_pre_semitrans_meshes\t\t= 0;\r\n\t\tm_num_dynamic_semitrans_meshes\t= 0;\r\n\t\tm_num_post_semitrans_meshes\t\t= 0;\r\n\r\n\t\t// Force opaque to be before semitrans.\r\n\t\tsMesh *p_mesh[8192];\r\n\t\tint mesh_entry = 0;\r\n\t\tDbg_MsgAssert( m_num_filled_meshes < 8192, ( \"Too many meshes for temporary sort buffer.\" ) );\r\n\r\n\t\t// Find 1st dynamic entry.\r\n\t\tint first_dynamic = -1;\r\n\t\tfor( int i = 0; i < m_num_filled_meshes; ++i )\r\n\t\t{\r\n\t\t\tif ( mpp_mesh_list[i] )\r\n\t\t\t{\r\n\t\t\t\tbool sorted = mpp_mesh_list[i]->mp_dl->m_material.p_header->m_flags & (1<<0) ? true : false;\r\n\r\n\t\t\t\tif ( ( first_dynamic == -1 ) && sorted ) first_dynamic = i;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\r\n\t\tfor ( int pass = 0; pass < 4; pass++ )\r\n\t\t{\r\n\t\t\tfor( int i = 0; i < m_num_filled_meshes; ++i )\r\n\t\t\t{\r\n\t\t\t\tif ( mpp_mesh_list[i] )\r\n\t\t\t\t{\r\n\t\t\t\t\tbool transparent = ( mp_material_pass[mpp_mesh_list[i]->mp_dl->m_material.p_header->m_pass_item].m_flags & (1<<3) );\r\n//\t\t\t\t\tbool transparent = ( mpp_mesh_list[i]->mp_dl->m_material.p_header->m_flags & (1<<3) ) ? true : false;\r\n\r\n\t\t\t\t\tbool sorted = mpp_mesh_list[i]->mp_dl->m_material.p_header->m_flags & (1<<0) ? true : false;\r\n\r\n\t\t\t\t\tif ( ( first_dynamic == -1 ) && sorted ) first_dynamic = i;\r\n\r\n\t\t\t\t\tswitch ( pass )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcase 0:\t\t// Opaque\r\n\t\t\t\t\t\t\tif ( !transparent )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tp_mesh[mesh_entry] = mpp_mesh_list[i];\r\n\t\t\t\t\t\t\t\tmpp_mesh_list[i] = NULL;\r\n\t\t\t\t\t\t\t\tmesh_entry++;\r\n\t\t\t\t\t\t\t\tm_num_opaque_meshes++;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 1:\t\t// Pre semi\r\n\t\t\t\t\t\t\tif ( transparent && !sorted && ( i < first_dynamic ) )\r\n\t\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t\tif ( mpp_mesh_list[i]->mp_dl ) printf( \"Pre Semi: %d, %8.3f\\n\", i, mpp_mesh_list[i]->mp_dl->m_material.p_header->m_draw_order );\r\n\t\t\t\t\t\t\t\tp_mesh[mesh_entry] = mpp_mesh_list[i];\r\n\t\t\t\t\t\t\t\tmpp_mesh_list[i] = NULL;\r\n\t\t\t\t\t\t\t\tmesh_entry++;\r\n\t\t\t\t\t\t\t\tm_num_pre_semitrans_meshes++;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 2:\t\t// Dynamic semi\r\n\t\t\t\t\t\t\tif ( transparent && sorted )\r\n\t\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t\tif ( mpp_mesh_list[i]->mp_dl ) printf( \"Dyn Semi: %d, %8.3f\\n\", i, mpp_mesh_list[i]->mp_dl->m_material.p_header->m_draw_order );\r\n\t\t\t\t\t\t\t\tp_mesh[mesh_entry] = mpp_mesh_list[i];\r\n\t\t\t\t\t\t\t\tmpp_mesh_list[i] = NULL;\r\n\t\t\t\t\t\t\t\tmesh_entry++;\r\n\t\t\t\t\t\t\t\tm_num_dynamic_semitrans_meshes++;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 3:\t\t// Post semi (everything else)...\r\n//\t\t\t\t\t\t\tif ( transparent && !sorted && ( ( i >= first_dynamic ) && ( first_dynamic != -1 ) ) )\r\n\t\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t\tif ( mpp_mesh_list[i]->mp_dl ) printf( \"Pst Semi: %d, %8.3f\\n\", i, mpp_mesh_list[i]->mp_dl->m_material.p_header->m_draw_order );\r\n\t\t\t\t\t\t\t\tp_mesh[mesh_entry] = mpp_mesh_list[i];\r\n\t\t\t\t\t\t\t\tmpp_mesh_list[i] = NULL;\r\n\t\t\t\t\t\t\t\tmesh_entry++;\r\n\t\t\t\t\t\t\t\tm_num_post_semitrans_meshes++;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tDbg_MsgAssert( false, ( \"This should never happen.\" ) );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tDbg_MsgAssert( m_num_filled_meshes == mesh_entry, ( \"Sorted meshes differs from actual meshes.\" ) );\r\n\r\n//\t\tfloat order = p_mesh[0]->mp_dl->m_material.p_header->m_draw_order;\r\n\t\tfor( int i = 0; i < m_num_filled_meshes; ++i )\r\n\t\t{\r\n//\t\t\tDbg_MsgAssert( p_mesh[i]->mp_dl->m_material.p_header->m_draw_order >= order, ( \"Out of order on entry %d: last=%f, current = %f\", i, order, p_mesh[i]->mp_dl->m_material.p_header->m_draw_order ) );\r\n//\t\t\torder = p_mesh[i]->mp_dl->m_material.p_header->m_draw_order;\r\n\t\t\tmpp_mesh_list[i] = p_mesh[i];\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_num_opaque_meshes\t\t\t\t= m_num_filled_meshes;\r\n\t\tm_num_pre_semitrans_meshes\t\t= 0;\r\n\t\tm_num_dynamic_semitrans_meshes\t= 0;\r\n\t\tm_num_post_semitrans_meshes\t\t= 0;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\nsMaterial *sScene::GetMaterial( uint32 checksum )\r\n{\r\n//\tfor ( int lp = 0; lp < m_num_materials; lp++ )\r\n//\t{\r\n//\t\tif( mp_material_array[lp].Checksum == checksum )\r\n//\t\t{\r\n//\t\t\treturn &mp_material_array[lp];\r\n//\t\t}\r\n//\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid sScene::HidePolys( uint32 mask, sCASData *p_cas_data, uint32 num_entries )\r\n{\r\n\tif(( num_entries == 0 ) || ( mask == 0 ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// For each mesh, need to find all cas data which references verts in that mesh.\r\n\tfor( int m = 0; m < this->m_num_filled_meshes; ++m )\r\n\t{\r\n\t\tsMesh *p_mesh = mpp_mesh_list[m];\r\n\r\n\t\thide_mesh( mask, p_cas_data, num_entries, p_mesh );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsScene *LoadScene( const char *Filename, sScene *pScene )\r\n{\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\nvoid DeleteScene( sScene *pScene )\r\n{\r\n//\t// Iterate through the table of materials, deleting them.\r\n//\tfor ( int lp = 0; lp < pScene->m_num_materials; lp++ )\r\n//\t{\r\n//\t\tif( pScene->mp_material_array[lp].mp_wibble_vc_params\t)\r\n//\t\t{\r\n//\t\t\tfor( uint32 i = 0; i < pScene->mp_material_array[lp].m_num_wibble_vc_anims; ++i )\r\n//\t\t\t{\r\n//\t\t\t\tdelete [] pScene->mp_material_array[lp].mp_wibble_vc_params[i].mp_keyframes;\r\n//\t\t\t}\r\n//\t\t\tdelete [] pScene->mp_material_array[lp].mp_wibble_vc_params;\r\n//\t\t}\r\n//\t\tif( pScene->mp_material_array[lp].mp_wibble_vc_colors\t)\r\n//\t\t{\r\n//\t\t\tdelete [] pScene->mp_material_array[lp].mp_wibble_vc_colors;\r\n//\t\t}\r\n//\t\tif( pScene->mp_material_array[lp].m_pUVControl\t)\r\n//\t\t{\r\n//\t\t\tdelete [] pScene->mp_material_array[lp].m_pUVControl;\r\n//\t\t}\r\n//\t}\r\n//\tdelete pScene->mp_material_array;\r\n//\tpScene->mp_material_array = NULL;\r\n//\r\n//\t// Delete the scene itself.\r\n\tdelete pScene;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid MaterialBuild(  sMesh * p_mesh, sScene * p_scene, bool bl, bool tx )\r\n{\r\n\tif ( !p_mesh->mp_dl->m_material.p_header ) return;\r\n\r\n\t// Construct the DLs.\r\n\tuint32 size;\r\n\r\n\tMem::Manager::sHandle().TopDownHeap()->PushAlign( 32 );\r\n#define DL_BUILD_SIZE (8*1024)\r\n\tuint8 * p_build_dl = new (Mem::Manager::sHandle().TopDownHeap()) uint8[DL_BUILD_SIZE];\r\n\r\n\t// Build the texture upload DL.\r\n\tDCFlushRange ( p_build_dl, DL_BUILD_SIZE );\r\n\r\n\tGX::begin( p_build_dl, DL_BUILD_SIZE );\r\n\r\n//\tmulti_mesh( p_mesh, p_scene );\r\n\r\n\tmulti_mesh( p_mesh->mp_dl->m_material.p_header,\r\n\t\t\t\t&p_scene->mp_material_pass[p_mesh->mp_dl->m_material.p_header->m_pass_item],\r\n\t\t\t\tbl,\r\n\t\t\t\ttx );\r\n\r\n\tsize = GX::end();\r\n\r\n\tDCFlushRange ( p_build_dl, DL_BUILD_SIZE );\r\n\r\n\tif ( size && ( size <= p_scene->mp_texture_dl[p_mesh->mp_dl->m_material.p_header->m_texture_dl_id].m_dl_size ) )\r\n\t{\r\n//\t\tp_mesh->mp_dl->mp_texture_dl = new uint8[size];\r\n\r\n\t\tmemcpy ( p_scene->mp_texture_dl[p_mesh->mp_dl->m_material.p_header->m_texture_dl_id].mp_dl, p_build_dl, size );\r\n\t\tDCFlushRange ( p_scene->mp_texture_dl[p_mesh->mp_dl->m_material.p_header->m_texture_dl_id].mp_dl, size );\r\n\r\n\t\tp_scene->mp_texture_dl[p_mesh->mp_dl->m_material.p_header->m_texture_dl_id].m_dl_size = (uint16)size;\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tp_mesh->mp_dl->mp_texture_dl = NULL;\r\n//\t\tp_mesh->mp_dl->m_texture_dl_size = 0;\r\n\t}\r\n\r\n\tMem::Manager::sHandle().TopDownHeap()->PopAlign();\r\n\r\n\t// Done constructing DL.\r\n\tdelete p_build_dl;\r\n}\r\n\r\nint g_material_id = -1;\r\nGXBool g_comploc = (GXBool)2;\r\n\r\nvoid ResetMaterialChange( void )\r\n{\r\n\tg_material_id = -1; \r\n\tg_comploc = (GXBool)2; \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n//static void MyGXProject ( \r\n//    f32  x,          // model coordinates\r\n//    f32  y,\r\n//    f32  z,\r\n//    f32  mtx[3][4],  // model-view matrix\r\n//    f32* pm,         // projection matrix, as returned by GXGetProjectionv\r\n//    f32* vp,         // viewport, as returned by GXGetViewportv\r\n//    f32* sx,         // screen coordinates\r\n//    f32* sy,\r\n//    f32* sz ) \r\n//{\r\n//    Vec   peye;\r\n//    f32   xc, yc, zc, wc;\r\n//\r\n//    ASSERTMSG(pm && vp && sx && sy && sz, GXERR_GET_NULL_PTR);\r\n//\r\n//    // transform to eye space\r\n//    peye.x = mtx[0][0]*x + mtx[0][1]*y + mtx[0][2]*z + mtx[0][3];\r\n//    peye.y = mtx[1][0]*x + mtx[1][1]*y + mtx[1][2]*z + mtx[1][3];\r\n//    peye.z = mtx[2][0]*x + mtx[2][1]*y + mtx[2][2]*z + mtx[2][3];\r\n//\r\n//\t// My addition: Just a frig to stop stuff messing up as it gets close to the near plane.\r\n//\tpeye.z -= 512.0f;\r\n//\tif ( peye.z > -1.0f ) peye.z = -1.0f;\r\n//\r\n//    // transform to clip space\r\n//    if (pm[0] == (f32)GX_PERSPECTIVE) { // perspective\r\n//        xc = peye.x * pm[1] + peye.z * pm[2];\r\n//        yc = peye.y * pm[3] + peye.z * pm[4];\r\n//        zc = peye.z * pm[5] + pm[6];\r\n//        wc = 1.0f / -peye.z;\r\n//    } else { // ortho\r\n//        xc = peye.x * pm[1] + pm[2];\r\n//        yc = peye.y * pm[3] + pm[4];\r\n//        zc = peye.z * pm[5] + pm[6];\r\n//        wc = 1.0f;\r\n//    }\r\n//\r\n//    // compute screen scale and offset\r\n//    *sx = xc * vp[2]/2 * wc + vp[0] + vp[2]/2;\r\n//    *sy = -yc * vp[3]/2 * wc + vp[1] + vp[3]/2;\r\n//    *sz = zc * (vp[5] - vp[4]) * wc + vp[5];\r\n//}\r\n//\r\n\r\nvoid MaterialSubmit( sMesh * p_mesh, sScene *pScene = NULL )\r\n{\r\n\tif ( !pScene->mp_scene_data ) return;\r\n\tif ( !p_mesh->mp_dl->m_material.p_header ) return;\r\n//\tif ( !p_mesh->mp_dl->mp_texture_dl ) return;\r\n\r\n\tif ( gOverDraw )\r\n\t{\r\n\t\tGX::SetFog( GX_FOG_NONE, 0.0f, 0.0f, 0.0f, 0.0f, (GXColor){0,0,0,0} );\r\n\t\tGX::SetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );\r\n\r\n\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_KONST,\r\n\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\t\r\n\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_KONST,\r\n\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\r\n\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\r\n\t\tGX::SetTevKSel( GX_TEVSTAGE0, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A );\r\n\t\tGX::SetTevKColor( GX_KCOLOR0, (GXColor){8,8,8,255} );\r\n\t\tGX::SetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ); \r\n\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255});\r\n\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255});\r\n\r\n\t\tGX::SetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE);\r\n\t\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE ); \r\n\t\treturn;\r\n\t}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n//\tif ( g_dl /*&& !( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<3) )*/ )\r\n//\tif ( g_dl/* && !( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<3) )*/ )\r\n\tif ( g_dl && !( p_mesh->mp_dl->m_material.p_header->m_flags & ((1<<3)|(1<<4)) ) )\r\n\t{\r\n////\t\tif ( p_mesh->mp_dl->m_material.p_header->m_material_dl_id != g_material_id )\r\n//\t\t{\r\n//\t\t\tg_material_id = p_mesh->mp_dl->m_material.p_header->m_material_dl_id;\r\n//\r\n//\t\t\tif ( pScene->mp_blend_dl[g_material_id].mp_dl && pScene->mp_blend_dl[g_material_id].m_dl_size )\r\n//\t\t\t{\r\n////\t\t\t\tGX::CallDisplayList( pScene->mp_blend_dl[g_material_id].mp_dl, pScene->mp_blend_dl[g_material_id].m_dl_size );\r\n//\t\t\t\tmulti_mesh( p_mesh->mp_dl->m_material.p_header,\r\n//\t\t\t\t\t\t\t&pScene->mp_material_pass[p_mesh->mp_dl->m_material.p_header->m_pass_item],\r\n//\t\t\t\t\t\t\ttrue,\r\n//\t\t\t\t\t\t\tfalse );\r\n//\t\t\t}\r\n//\t\t}\r\n\r\n\t\tint tex_id = (int)p_mesh->mp_dl->m_material.p_header->m_texture_dl_id;\r\n\t\tGX::CallDisplayList( pScene->mp_texture_dl[tex_id].mp_dl, pScene->mp_texture_dl[tex_id].m_dl_size );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmulti_mesh( p_mesh->mp_dl->m_material.p_header,\r\n\t\t\t\t\t&pScene->mp_material_pass[p_mesh->mp_dl->m_material.p_header->m_pass_item],\r\n\t\t\t\t\ttrue,\r\n\t\t\t\t\ttrue,\r\n\t\t\t\t\tp_mesh->mp_dl->m_material.p_header->m_flags & (1<<6) ? true : false,\r\n\t\t\t\t\tp_mesh->mp_dl->mp_object_header->m_num_skin_verts ? false : true );\r\n\t}\r\n\r\n\t// See if we need to upload env mapping matrices.\r\n\tsMaterialHeader * p_mat = p_mesh->mp_dl->m_material.p_header;\r\n\tsMaterialPassHeader *p_pass = &pScene->mp_material_pass[p_mat->m_pass_item];\r\n\r\n\t// Set Comploc\r\n\tu8 alphacutoff = p_mesh->mp_dl->m_material.p_header->m_alpha_cutoff;\r\n\tGXBool comploc;\r\n//\tif ( p_pass->m_texture.p_data && ( p_pass->m_texture.p_data->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_HOLES ) )\r\n\tif ( alphacutoff > 0 )\r\n\t{\r\n\t\tcomploc = GX_FALSE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcomploc = GX_TRUE;\r\n\t}\r\n\tcomploc = GX_FALSE;\r\n\r\n\tif ( g_comploc != comploc )\r\n\t{\r\n\t\tg_comploc = comploc;\r\n\t\tGX::SetZCompLoc( comploc );\r\n\t}\r\n\r\n//\tGX::SetAlphaCompare(GX_GEQUAL, alphacutoff, GX_AOP_AND, GX_GEQUAL, alphacutoff );\r\n//\tGX::SetZCompLoc( GX_FALSE );\r\n\tGX::SetAlphaCompare(GX_GEQUAL, alphacutoff, GX_AOP_AND, GX_GEQUAL, alphacutoff );\r\n\r\n\tfor ( int lp = 0; lp < p_mat->m_passes; lp++, p_pass++ )\r\n\t{\r\n\t\tif ( p_pass->m_flags & ( (1<<1) | (1<<2) ) )\r\n\t\t{\r\n\t\t\t// UV Wibbled or Environment mapped.\r\n\t\t\tGXTexMtx mtx;\r\n\t\t\tswitch ( lp )\r\n\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tmtx = GX_TEXMTX0;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tmtx = GX_TEXMTX1;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tmtx = GX_TEXMTX2;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\tmtx = GX_TEXMTX3;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tmtx = GX_IDENTITY;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tif( p_pass->m_flags & (1<<1) )\r\n\t\t\t{\r\n\t\t\t\t// Env mapping.\r\n\t\t\t\tMtx s, t, e, mv;\r\n\r\n\t\t\t\tMTXInvXpose((Mtx)&EngineGlobals.local_to_camera, mv );\r\n\r\n\t\t\t\t// Project bounding sphere into screen space to get a metric to scroll the environment map.\r\n\t\t\t\tf32\t\t\t\tp[GX_PROJECTION_SZ];\r\n\t\t\t\tf32\t\t\t\tvp[GX_VIEWPORT_SZ];\r\n\t\t\t\tfloat\t\t\trx, ry;\t//, rz;\r\n\r\n\t\t\t\tGX::GetProjectionv( p );\r\n\t\t\t\tGX::GetViewportv( vp );\r\n\r\n\t\t\t\tfloat x = EngineGlobals.local_to_camera.getPosX();\r\n\t\t\t\tfloat y = EngineGlobals.local_to_camera.getPosY();\r\n//\t\t\t\tfloat z = EngineGlobals.local_to_camera.getPosZ();\r\n\r\n\t\t\t\trx = -x;\t//EngineGlobals.local_to_camera.getRightX()*x + EngineGlobals.local_to_camera.getRightY()*y + EngineGlobals.local_to_camera.getRightZ()*z;\r\n\t\t\t\try = -y;\t//EngineGlobals.local_to_camera.getUpX()*x + EngineGlobals.local_to_camera.getUpY()*y + EngineGlobals.local_to_camera.getUpZ()*z;\r\n\r\n\r\n//\t\t\t\tMyGXProject( p_mesh->mp_dl->m_sphere[X],\r\n//\t\t\t\t\t\t   p_mesh->mp_dl->m_sphere[Y],\r\n//\t\t\t\t\t\t   p_mesh->mp_dl->m_sphere[Z],\r\n//\t\t\t\t\t\t   (Mtx)&EngineGlobals.local_to_camera,\r\n//\t\t\t\t\t\t   p, vp, &rx, &ry, &rz );\r\n\r\n\t\t\t\tfloat u;\r\n\t\t\t\tfloat v;\r\n\r\n\t\t\t\tfloat ut = (float)p_pass->m_u_tile;\r\n\t\t\t\tfloat vt = (float)p_pass->m_v_tile;\r\n\t\t\t\tut = ( ut * (1.0f / (float)(1<<12)) );\r\n\t\t\t\tvt = ( vt * (1.0f / (float)(1<<12)) );\r\n\r\n\t\t\t\tu = ( rx * ( ENV_MAP_SCROLL_SCALE * ut ) );\r\n\t\t\t\tv = ( ry * ( ENV_MAP_SCROLL_SCALE * vt ) );\r\n\r\n\t\t\t\tu -= (float)(int)u;\t\t// Keep within +/-1.\r\n\t\t\t\tv -= (float)(int)v;\r\n\r\n\t\t\t\t// Create the rotational component.\r\n\t\t\t\tMTXScale( s, 0.5f * ut, -0.5f * vt, 0.0f );\r\n\t\t\t\tMTXTrans( t, 0.5f, 0.5f, 1.0f );\r\n\t\t\t\tMTXConcat( t, s, e );\r\n\r\n\t\t\t\tMTXConcat(e, mv, e);\r\n\r\n\t\t\t\te[0][3] += u;\r\n\t\t\t\te[1][3] += v;\r\n\r\n\t\t\t\tGX::LoadTexMtxImm(e, mtx, GX_MTX2x4);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( p_pass->m_uv_enabled )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Explicit matrix.\r\n\t\t\t\t\tMtx real;\r\n//\t\t\t\t\tMTXCopy( p_pass->mp_explicit_wibble->m_matrix, real );\r\n\r\n//\t\t\t\t\treal[0][3] = ( p_pass->mp_explicit_wibble->m_matrix[0][3] * -real[0][0] ) + ( p_pass->mp_explicit_wibble->m_matrix[1][3] * -real[0][1] );\r\n//\t\t\t\t\treal[1][3] = ( p_pass->mp_explicit_wibble->m_matrix[0][3] * -real[1][0] ) + ( p_pass->mp_explicit_wibble->m_matrix[1][3] * -real[1][1] );\r\n\r\n\t\t\t\t\treal[0][0] = ( (float)p_pass->m_uv_mat[0] ) * ( 1.0f / ((float)(1<<12)) );\r\n\t\t\t\t\treal[0][1] = -( (float)p_pass->m_uv_mat[1] ) * ( 1.0f / ((float)(1<<12)) );\r\n\t\t\t\t\treal[0][2] = 1.0f;\r\n\t\t\t\t\treal[0][3] = ( (float)p_pass->m_uv_mat[2] ) * ( 1.0f / ((float)(1<<12)) ) - 1.0f;\r\n\r\n\t\t\t\t\treal[1][0] = ( (float)p_pass->m_uv_mat[1] ) * ( 1.0f / ((float)(1<<12)) );\r\n\t\t\t\t\treal[1][1] = ( (float)p_pass->m_uv_mat[0] ) * ( 1.0f / ((float)(1<<12)) );\r\n\t\t\t\t\treal[1][2] = 1.0f;\r\n\t\t\t\t\treal[1][3] = ( (float)p_pass->m_uv_mat[3] ) * ( 1.0f / ((float)(1<<12)) ) - 1.0f;\r\n\t\t\t\t\tGX::LoadTexMtxImm( real, mtx, GX_MTX2x4 );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Wibbled.\r\n\t\t\t\t\tfloat uoff, voff, t;\r\n\r\n\t\t\t\t\tt = (float)Tmr::GetTime() * 0.001f;\r\n\r\n\t\t\t\t\tMtx\tm;\r\n\r\n\t\t\t\t\tsMaterialUVWibble * p_uv = &pScene->mp_uv_wibble[p_pass->m_uv_wibble_index];\r\n\r\n\t\t\t\t\tuoff\t= ( t * p_uv->m_u_vel ) + ( p_uv->m_u_amp * sinf( p_uv->m_u_freq * t + p_uv->m_u_phase ));\r\n\t\t\t\t\tvoff\t= ( t * p_uv->m_v_vel ) + ( p_uv->m_v_amp * sinf( p_uv->m_v_freq * t + p_uv->m_v_phase ));\r\n\r\n\t\t\t\t\t// Reduce offset mod 16 and put it in the range -8 to +8.\r\n\t\t\t\t\tuoff\t+= 8.0f;\r\n\t\t\t\t\tuoff\t-= (float)(( (int)uoff >> 4 ) << 4 );\r\n\t\t\t\t\tvoff\t+= 8.0f;\r\n\t\t\t\t\tvoff\t-= (float)(( (int)voff >> 4 ) << 4 );\r\n\r\n\t\t\t\t\tuoff = ( uoff < 0.0f ) ? ( uoff + 8.0f ) : ( uoff - 8.0f ); \r\n\t\t\t\t\tvoff = ( voff < 0.0f ) ? ( voff + 8.0f ) : ( voff - 8.0f ); \r\n\r\n\t\t\t\t\tMTXTrans( m, uoff, voff, 0.0f );\r\n\r\n\t\t\t\t\tGX::LoadTexMtxImm(m, mtx, GX_MTX2x4);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace NxNgc\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/scene.h",
    "content": "#ifndef __SCENE_H\r\n#define __SCENE_H\r\n\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n#include \"texture.h\"\r\n#include \"mesh.h\"\r\n#include \"material.h\"\r\n#include \"anim.h\"\r\n#include <sys/ngc/p_vector.h>\r\n#include <sys/ngc/p_gx.h>\r\n#include <gfx/nxhierarchy.h>\r\n\r\nnamespace NxNgc\r\n{\r\n\r\nstruct sMeshEntry\r\n{\r\n\tsMesh*\t\t\t\t\tmp_mesh;\t\t\t// Pointer to mesh.\r\n\tint\t\t\t\t\t\tm_bbox;\t\t\t\t// Bounding box index.\r\n};\r\n\r\n#define SCENE_FLAG_RENDERING_SHADOW\t\t( 1 << 7 )\r\n#define SCENE_FLAG_RECEIVE_SHADOWS\t\t( 1 << 8 )\r\n#define SCENE_FLAG_SELF_SHADOWS\t\t\t( 1 << 9 )\r\n#define SCENE_FLAG_CLONED_GEOM\t\t\t( 1 << 10 )\r\n\r\nstruct sScene\r\n{\r\n\t\t\t\t\t\t\t\tsScene( void );\r\n\t\t\t\t\t\t\t\t~sScene( void );\r\n\r\n\tsMaterial *\t\t\t\t\tsScene::GetMaterial( uint32 checksum );\r\n\tvoid\t\t\t\t\t\tAddMeshes( int num_meshes, sMesh **pp_meshes );\r\n\tvoid\t\t\t\t\t\tCountMeshes( int num_meshes, sMesh **pp_meshes );\r\n\tvoid\t\t\t\t\t\tCreateMeshArrays( void );\r\n\tvoid\t\t\t\t\t\tRemoveMeshes( int num_meshes, sMesh **pp_meshes );\r\n\tvoid\t\t\t\t\t\tSortMeshes( void );\r\n\tvoid\t\t\t\t\t\tFigureBoundingVolumes( void );\r\n\tvoid\t\t\t\t\t\tHidePolys( uint32 mask, sCASData *p_cas_data, uint32 num_entries );\r\n\r\n//\tuint32\t\t\t\t\t\tm_flags;\r\n//\tint\t\t\t\t\t\t\tNumTextures;\r\n//\tuint8\t\t\t\t\t\t*pTexBuffer;\r\n//\tuint8\t\t\t\t\t\t*pTexDma;\r\n//\tsTexture\t\t\t\t\t*pTextures;\r\n//\r\n//\tint\t\t\t\t\t\t\tm_num_materials;\r\n//\tsMaterial *\t\t\t\t\tmp_material_array;\r\n//\t\r\n//\t// New style, with separate opaque and semitransparent mesh lists.\r\n//\tsMesh\t\t\t\t\t\t**m_opaque_meshes;\r\n//\tint\t\t\t\t\t\t\tm_num_opaque_entries;\r\n//\tint\t\t\t\t\t\t\tm_num_filled_opaque_entries;\r\n//\tsMesh\t\t\t\t\t\t**m_semitransparent_meshes;\r\n//\tint\t\t\t\t\t\t\tm_num_semitransparent_entries;\r\n//\tint\t\t\t\t\t\t\tm_num_filled_semitransparent_entries;\r\n//\tint\t\t\t\t\t\t\tm_first_dynamic_sort_entry;\r\n//\tint\t\t\t\t\t\t\tm_num_dynamic_sort_entries;\r\n////\tint\t\t\t\t\t\t\tm_num_bboxes;\r\n//\t\r\n////\tclass CInstance\t\t\t\t*pInstances;\r\n////\r\n////\tsScene\t\t\t\t\t\t*pNext;\r\n////\r\n////\tstatic sScene\t\t\t\t*pHead;\r\n//\r\n//\t\r\n\tbool\t\t\t\t\t\tm_is_dictionary;\r\n//\r\n//\tMth::CBBox\t\t\t\t\tm_bbox;\t\r\n\r\n\r\n\t// New stuff.\r\n\tuint32\t\t\t\t\t\tm_flags;\r\n\r\n\tsSceneHeader *\t\t\t\tmp_scene_data;\t\t// This is all data for pointers below.\r\n\tfloat *\t\t\t\t\t\tmp_pos_pool;\r\n\ts16 *\t\t\t\t\t\tmp_nrm_pool;\r\n\tuint32 *\t\t\t\t\tmp_col_pool;\r\n\ts16 *\t\t\t\t\t\tmp_tex_pool;\r\n\tsDLHeader *\t\t\t\t\tmp_dl;\r\n\tsMaterialDL *\t\t\t\tmp_blend_dl;\r\n\tsTextureDL *\t\t\t\tmp_texture_dl;\r\n\tsMaterialVCWibbleKeyHeader *mp_vc_wibble;\r\n\tsMaterialHeader *\t\t\tmp_material_header;\r\n\tsMaterialUVWibble *\t\t\tmp_uv_wibble;\r\n\tsMaterialPassHeader *\t\tmp_material_pass;\r\n\tuint16 *\t\t\t\t\tmp_shadow_volume_mesh;\r\n\tsShadowEdge *\t\t\t\tmp_shadow_edge;\r\n\r\n\tMth::Vector\t\t\t\t\tm_sphere;\r\n\r\n\tsMesh\t\t\t\t\t\t**mpp_mesh_list;\r\n\tuint16\t\t\t\t\t\tm_num_meshes;\r\n\tuint16\t\t\t\t\t\tm_num_filled_meshes;\r\n\r\n\tuint16\t\t\t\t\t\tm_num_opaque_meshes;\r\n\tuint16\t\t\t\t\t\tm_num_pre_semitrans_meshes;\r\n\tuint16\t\t\t\t\t\tm_num_dynamic_semitrans_meshes;\r\n\tuint16\t\t\t\t\t\tm_num_post_semitrans_meshes;\r\n\r\n//\tuint16\t\t\t\t\t\tm_num_opaque_entries;\r\n//\tuint16\t\t\t\t\t\tm_num_semitrans_entries;\r\n\r\n\t// For mesh heirarchies\r\n\tNx::CHierarchyObject*\t\tmp_hierarchyObjects;\t\t\t\t\t\t// array of hierarchy objects\r\n\tint\t\t\t\t\t\t\tm_numHierarchyObjects;\t\t\t\t\t\t// number of hierarchy objects\r\n};\r\n\r\n\r\nsScene\t*LoadScene( const char *Filename, sScene *pScene );\r\nvoid\tDeleteScene( sScene *pScene );\r\n\r\n#define MATERIAL_GROUP_SU\t(1<<0)\r\n#define MATERIAL_GROUP_CP\t(1<<1)\r\n#define MATERIAL_GROUP_A\t(1<<2)\r\n#define MATERIAL_GROUP_B\t(1<<3)\r\n#define MATERIAL_GROUP_C\t(1<<4)\r\n\r\nvoid ResetMaterialChange( void );\r\nvoid MaterialSubmit( sMesh * p_mesh, sScene *pScene = NULL );\r\n\r\nvoid MaterialBuild(  sMesh * p_mesh, sScene * p_scene, bool bl, bool tx ); \r\n\r\n} // namespace NxNgc\r\n\r\n\r\n#endif // __SCENE_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/sprite.cpp",
    "content": "#include <string.h>\r\n#include <core/defines.h>\r\n#include <core/macros.h>\r\n#include <core/debug.h>\r\n#include <sys/file/filesys.h>\r\n#include \"nx_init.h\"\r\n#include \"scene.h\"\r\n#include \"render.h\"\r\n#include \"sprite.h\"\r\n\r\n#include <sys/ngc/p_prim.h>\r\n#include <sys/ngc/p_camera.h>\r\n#include <sys/ngc/p_render.h>\r\n#include <sys/ngc/p_display.h>\r\n#include <sys/config/config.h>\r\n#include <sys/ngc/p_gx.h>\r\n#include <dolphin\\gd.h>\r\n#include <dolphin\\gx\\gxvert.h>\r\n\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* SDraw2D\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSDraw2D *SDraw2D::sp_2D_draw_list = NULL;\r\n\r\n\r\nSDraw2D::SDraw2D( float pri, bool hide )\r\n{\r\n\tm_hidden = hide;\r\n\tm_pri = pri;\r\n\r\n\tmp_next = NULL;\r\n\r\n\t// add to draw list\r\n\tif( !m_hidden )\r\n\t{\r\n\t\tInsertDrawList();\r\n\t}\r\n}\r\n\r\n\r\n\r\nSDraw2D::~SDraw2D()\r\n{\r\n\t// Try removing from draw list\r\n\tRemoveDrawList();\r\n}\r\n\r\n\r\n\r\nvoid SDraw2D::SetPriority( float pri )\r\n{\r\n\tif (m_pri != pri)\r\n\t{\r\n\t\tm_pri = pri;\r\n\r\n\t\t// By removing and re-inserting, we re-sort the list\r\n\t\tif (!m_hidden)\r\n\t\t{\r\n\t\t\tRemoveDrawList();\r\n\t\t\tInsertDrawList();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\nvoid SDraw2D::SetHidden( bool hide )\r\n{\r\n\tif (m_hidden != hide)\r\n\t{\r\n\t\tm_hidden = hide;\r\n\t\tif (hide)\r\n\t\t{\r\n\t\t\tRemoveDrawList();\r\n\t\t} else {\r\n\t\t\tInsertDrawList();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\nvoid SDraw2D::DrawAll()\r\n{\r\n\tset_blend_mode( vBLEND_MODE_BLEND );\r\n\r\n\tSDraw2D *pDraw = sp_2D_draw_list;\r\n\twhile (pDraw)\r\n\t{\r\n\t\tif (!pDraw->m_hidden)\r\n\t\t{\r\n\t\t\tpDraw->BeginDraw();\r\n\t\t\tpDraw->Draw();\r\n\t\t\tpDraw->EndDraw();\r\n\t\t}\r\n\t\tpDraw = pDraw->mp_next;\r\n\t}\r\n}\r\n\r\n\r\n\r\nvoid SDraw2D::InsertDrawList()\r\n{\r\n\tif (!sp_2D_draw_list ||\t\t\t\t\t\t\t// Empty List\r\n\t\t(m_pri <= sp_2D_draw_list->m_pri))\t// Start List\r\n\t{\r\n\t\tmp_next = sp_2D_draw_list;\r\n\t\tsp_2D_draw_list = this;\r\n\t} else {\t\t\t\t// Insert\r\n\t\tSDraw2D *p_cur = sp_2D_draw_list;\r\n\t\r\n\t\t// Find where to insert\r\n\t\twhile(p_cur->mp_next)\r\n\t\t{\r\n\t\t\tif (m_pri <= p_cur->mp_next->m_pri)\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tp_cur = p_cur->mp_next;\r\n\t\t}\r\n\r\n\t\t// Insert at this point\r\n\t\tmp_next = p_cur->mp_next;\r\n\t\tp_cur->mp_next = this;\r\n\t}\r\n}\r\n\r\n\r\n\r\nvoid SDraw2D::RemoveDrawList()\r\n{\r\n\t// Take out from draw list\r\n\tif (sp_2D_draw_list == this)\r\n\t{\r\n\t\tsp_2D_draw_list = mp_next;\r\n\t} \r\n\telse if (sp_2D_draw_list)\r\n\t{\r\n\t\tSDraw2D *p_cur = sp_2D_draw_list;\r\n\r\n\t\twhile(p_cur->mp_next)\r\n\t\t{\r\n\t\t\tif (p_cur->mp_next == this)\r\n\t\t\t{\r\n\t\t\t\tp_cur->mp_next = mp_next;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tp_cur = p_cur->mp_next;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\t\r\n\r\n//typedef struct\r\n//{\r\n//\tfloat\t\tx, y, z;\r\n//\tfloat\t\trhw;\r\n//\tD3DCOLOR\tcol;\r\n//\tfloat\t\tu, v;\r\n//}\r\n//sSpriteVert;\r\n\r\n\r\n\r\nsSprite::sSprite( float pri ) : SDraw2D( pri, true )\r\n{\r\n\tmp_texture = NULL;\r\n\t\r\n//\tif( D3D_OK != D3DDevice_CreateVertexBuffer(\tsizeof( sSpriteVert ) * 6,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t0,\t\t\t\t\t\t\t\t\t\t// Usage - ignored.\r\n//\t\t\t\t\t\t\t\t\t\t\t\t0,\t\t\t\t\t\t\t\t\t\t// FVF - ignored.\r\n//\t\t\t\t\t\t\t\t\t\t\t\t0,\t\t\t\t\t\t\t\t\t\t// Pool - ignored.\r\n//\t\t\t\t\t\t\t\t\t\t\t\t&p_vertex_buffer ))\r\n//\t{\r\n//\t\texit( 0 );\r\n//\t}\r\n//\r\n//\r\n}\r\n\r\nsSprite::~sSprite()\r\n{\r\n//\tp_vertex_buffer->Release();\r\n}\r\n\r\n\r\n\r\n\r\n\r\nvoid sSprite::BeginDraw( void )\r\n{\r\n\t// Nothing required here right now.\r\n}\r\n\r\n//static inline void _GDWriteXFCmd(u16 addr, u32 val)\r\n//{\r\n//\tGXWGFifo.u8 = GX_LOAD_XF_REG;\r\n//\tGXWGFifo.u16 = 0; // 0 means one value follows\r\n//\tGXWGFifo.u16 = addr;\r\n//\tGXWGFifo.u32 = val;\r\n//}\r\n//\r\n//static inline void _GDWriteBPCmd(u32 regval)\r\n//{\r\n//\tGXWGFifo.u8 = GX_LOAD_BP_REG;\r\n//\tGXWGFifo.u32 = regval;\r\n//}\r\n//\r\n//void _SetGenMode( u8\t\t\tnTexGens,\r\n//\t\t\t\t u8\t\t\tnChans,\r\n//\t\t\t\t u8\t\t\tnTevs,\r\n//\t\t\t\t u8\t\t\tnInds,\r\n//\t\t\t\t GXCullMode\tcm )\r\n//{\r\n//\tstatic u8 cm2hw[] = { 0, 2, 1, 3 };\r\n//\t_GDWriteXFCmd( XF_NUMTEX_ID, XF_NUMTEX( nTexGens ));\r\n//\t_GDWriteXFCmd( XF_NUMCOLORS_ID, XF_NUMCOLORS( nChans ));\r\n//\t_GDWriteBPCmd( GEN_MODE( nTexGens, nChans, 0, (nTevs-1),\r\n//\t\t\t\t\t\t\tcm2hw[cm], nInds, 0, GEN_MODE_ID ));\r\n//}\r\n\r\n\r\nvoid sSprite::Draw( void )\r\n{\r\n\tGXColor current_color;\r\n\tcurrent_color.a = (m_rgba&0xff);\r\n\tif ( current_color.a == 0 ) return;\r\n\tcurrent_color.b = ((m_rgba&0xff00)>>8);\r\n\tcurrent_color.g = ((m_rgba&0xff0000)>>16);\r\n\tcurrent_color.r = ((m_rgba&0xff000000)>>24);\r\n\r\n\tfloat start_screen_x = m_xpos;\r\n\tfloat start_screen_y = m_ypos;\r\n\r\n\tfloat x0,y0,x1,y1;\r\n\r\n\tfloat u0 = 0.0f;\r\n\tfloat v0 = 0.0f;\r\n\tfloat u1 = 0.0f;\r\n\tfloat v1 = 0.0f;\r\n\r\n\tif ( mp_texture )\r\n\t{\r\n\t\tu0 = 0.0f;\r\n\t\tv0 = 1.0f;\r\n\t\tu1 = (float)mp_texture->BaseWidth / (float)mp_texture->ActualWidth;       \r\n\t\tv1 = 1.0f - ( (float)mp_texture->BaseHeight / (float)mp_texture->ActualHeight ); \r\n\t}\r\n\r\n\t// Check for flip\r\n\tfloat abs_scale_x = m_scale_x;\r\n\tfloat abs_scale_y = m_scale_y;\r\n\tif (abs_scale_x < 0.0f)\r\n\t{\r\n\t\tfloat temp = u0;\r\n\t\tu0 = u1;\r\n\t\tu1 = temp;\r\n\t\tabs_scale_x = -abs_scale_x;\r\n\t}\r\n\tif (abs_scale_y < 0.0f)\r\n\t{\r\n\t\tfloat temp = v0;\r\n\t\tv0 = v1;\r\n\t\tv1 = temp;\r\n\t\tabs_scale_y = -abs_scale_y;\r\n\t}\r\n\r\n\tx0 = (-m_xhot * abs_scale_x);\r\n\ty0 = (-m_yhot * abs_scale_y);\r\n\r\n\tif ( mp_texture )\r\n\t{\r\n\t\tx1 = x0 + ( /*m_width*/mp_texture->BaseWidth * abs_scale_x);\r\n\t\ty1 = y0 + ( /*m_height*/mp_texture->BaseHeight * abs_scale_y);\r\n\t//\tx1 = x0 + ( m_width * abs_scale_x);\r\n\t//\ty1 = y0 + ( m_height * abs_scale_y);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tx1 = x0 + ( m_width * abs_scale_x);\r\n\t\ty1 = y0 + ( m_height * abs_scale_y);\r\n\t}\r\n\t\r\n\tMth::Vector p0(x0, y0, 0.0f, 0.0f);\r\n\tMth::Vector p1(x1, y0, 0.0f, 0.0f);\r\n\tMth::Vector p2(x0, y1, 0.0f, 0.0f);\r\n\tMth::Vector p3(x1, y1, 0.0f, 0.0f);\r\n\r\n\tif (m_rot != 0.0f)\r\n\t{\r\n\t\tp0.RotateZ(m_rot);\r\n\t\tp1.RotateZ(m_rot);\r\n\t\tp2.RotateZ(m_rot);\r\n\t\tp3.RotateZ(m_rot);\r\n\t}\r\n\r\n\tp0[X] += start_screen_x;\r\n\tp1[X] += start_screen_x;\r\n\tp2[X] += start_screen_x;\r\n\tp3[X] += start_screen_x;\r\n\t\r\n\tp0[Y] += start_screen_y;\r\n\tp1[Y] += start_screen_y;\r\n\tp2[Y] += start_screen_y;\r\n\tp3[Y] += start_screen_y;\r\n\r\n\tif( mp_texture == NULL )\r\n\t{\r\n\t\t// No alpha map.\r\n\t\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE ); \r\n\r\n\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,\r\n\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\tGX::SetTevColorInOp(\t GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC,\r\n\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\tGX::SetTevOrder( \t\t GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL );\r\n\r\n//\t\tGX::SetNumTexGens( 0 );\r\n//\t\tGX::SetNumTevStages( 1 );\r\n\t\t//GX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY );\r\n//\t\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\r\n//\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);\r\n//\t\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n//\t\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n\t\r\n\t\t// Set current vertex descriptor to enable position and color0.\r\n\t\t// Both use 8b index to access their data arrays.\r\n\t\tGX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n\t\r\n\t\t// Set material color.\r\n\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n\t\tGX::SetChanAmbColor( GX_COLOR0A0, current_color );\r\n\t\r\n\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\t\r\n\t\t// Send coordinates.\r\n\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\t\tGX::Position3f32(p0[X], p0[Y], -1.0f);\r\n\t\t\tGX::Position3f32(p1[X], p1[Y], -1.0f);\r\n\t\t\tGX::Position3f32(p3[X], p3[Y], -1.0f);\r\n\t\t\tGX::Position3f32(p2[X], p2[Y], -1.0f);\r\n\t\tGX::End();\r\n\t\r\n\t\treturn;\r\n\t}\r\n\t\r\n//\t// Upload the texture.\r\n//\tGXTexObj\ttexObj;\r\n//\tGXInitTexObj(\t&texObj,\r\n//\t\t\t\t\tmp_texture->pTexelData,\r\n//\t\t\t\t\tmp_texture->ActualWidth,\r\n//\t\t\t\t\tmp_texture->ActualHeight,\r\n//\t\t\t\t\t(GXTexFmt)mp_texture->format,\r\n//\t\t\t\t\tGX_CLAMP,\r\n//\t\t\t\t\tGX_CLAMP,\r\n//\t\t\t\t\tGX_FALSE );\r\n//\tGXLoadTexObj(\t&texObj,\r\n//\t\t\t\t\tGX_TEXMAP0 );\r\n\r\n\tGX::UploadTexture( mp_texture->pTexelData,\r\n\t\t\t\t\t   mp_texture->ActualWidth,\r\n\t\t\t\t\t   mp_texture->ActualHeight,\r\n\t\t\t\t\t   (GXTexFmt)mp_texture->format,\r\n\t\t\t\t\t   GX_CLAMP,\r\n\t\t\t\t\t   GX_CLAMP,\r\n\t\t\t\t\t   GX_FALSE,\r\n\t\t\t\t\t   GX_LINEAR,\r\n\t\t\t\t\t   GX_LINEAR,\r\n\t\t\t\t\t   0.0f,\r\n\t\t\t\t\t   0.0f,\r\n\t\t\t\t\t   0.0f,\r\n\t\t\t\t\t   GX_FALSE,\r\n\t\t\t\t\t   GX_FALSE,\r\n\t\t\t\t\t   GX_ANISO_1,\r\n\t\t\t\t\t   GX_TEXMAP0 );\r\n\r\n\tif ( ( mp_texture->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA ) && mp_texture->pAlphaData )\r\n\t{\r\n//\t\t// Upload alpha map.\r\n//\t\tGXTexObj\talphaObj;\r\n//\t\tGXInitTexObj(\t&alphaObj,\r\n//\t\t\t\t\t\tmp_texture->pAlphaData,\r\n//\t\t\t\t\t\tmp_texture->ActualWidth,\r\n//\t\t\t\t\t\tmp_texture->ActualHeight,\r\n//\t\t\t\t\t\t(GXTexFmt)mp_texture->format,\r\n//\t\t\t\t\t\tGX_CLAMP,\r\n//\t\t\t\t\t\tGX_CLAMP,\r\n//\t\t\t\t\t\tGX_FALSE );\r\n//\t\tGXLoadTexObj(\t&alphaObj,\r\n//\t\t\t\t\t\tGX_TEXMAP1 );\r\n\r\n\t\tGX::UploadTexture( mp_texture->pAlphaData,\r\n\t\t\t\t\t\t   mp_texture->ActualWidth,\r\n\t\t\t\t\t\t   mp_texture->ActualHeight,\r\n\t\t\t\t\t\t   (GXTexFmt)mp_texture->format,\r\n\t\t\t\t\t\t   GX_CLAMP,\r\n\t\t\t\t\t\t   GX_CLAMP,\r\n\t\t\t\t\t\t   GX_FALSE,\r\n\t\t\t\t\t\t   GX_LINEAR,\r\n\t\t\t\t\t\t   GX_LINEAR,\r\n\t\t\t\t\t\t   0.0f,\r\n\t\t\t\t\t\t   0.0f,\r\n\t\t\t\t\t\t   0.0f,\r\n\t\t\t\t\t\t   GX_FALSE,\r\n\t\t\t\t\t\t   GX_FALSE,\r\n\t\t\t\t\t\t   GX_ANISO_1,\r\n\t\t\t\t\t\t   GX_TEXMAP1 );\r\n\r\n\t\t// Has alpha map.\r\n\t\tGX::SetTexChanTevIndCull( 2, 1, 2, 0, GX_CULL_NONE ); \r\n\t\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n\t\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, mp_texture->ActualWidth, mp_texture->ActualHeight );\r\n\t\tGX::SetTexCoordScale( GX_TEXCOORD1, GX_TRUE, mp_texture->ActualWidth, mp_texture->ActualHeight );\r\n\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\t\tGX::SetTexCoordGen( GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0);\r\n\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVREG0,\r\n\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVREG0 );\r\n\r\n\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP1 );\r\n\t\tGX::SetTevColorInOp( GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0,\r\n\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// No alpha map.\r\n\t\tGX::SetTexChanTevIndCull( 1, 1, 1, 0, GX_CULL_NONE ); \r\n\t\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n\t\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, mp_texture->ActualWidth, mp_texture->ActualHeight );\r\n\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n\t}\r\n\r\n\t// Set current vertex descriptor to enable position and color0.\r\n\t// Both use 8b index to access their data arrays.\r\n\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\r\n\t// Set material color.\r\n\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n\tGX::SetChanAmbColor( GX_COLOR0A0, current_color );\r\n\r\n\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\tGX::SetNumChans( 1 );\r\n\r\n//\tfloat uone = u1;\t\t//(float)mp_texture->BaseWidth / (float)mp_texture->ActualWidth;\r\n//\tfloat vzro = v1;\t\t//( (float)mp_texture->BaseHeight / (float)mp_texture->ActualHeight );\r\n\r\n\t// Send coordinates.\r\n\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\tGX::Position3f32(p0[X], p0[Y], -1.0f);\r\n\t\tGX::TexCoord2f32(u0, v0);\r\n\t\tGX::Position3f32(p1[X], p1[Y], -1.0f);\r\n\t\tGX::TexCoord2f32(u1, v0);\r\n\t\tGX::Position3f32(p3[X], p3[Y], -1.0f);\r\n\t\tGX::TexCoord2f32(u1, v1);\r\n\t\tGX::Position3f32(p2[X], p2[Y], -1.0f);\r\n\t\tGX::TexCoord2f32(u0, v1);\r\n\tGX::End();\r\n}\r\n\r\n\r\n\r\nvoid sSprite::EndDraw( void )\r\n{\r\n//\tif( mp_texture == NULL )\r\n//\t{\r\n//\t\treturn;\r\n//\t}\r\n//\r\n//\tD3DDevice_SetPixelShader( 0 );\r\n//\tset_vertex_shader( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2( 0 ));\r\n//\tD3DDevice_SetRenderState( D3DRS_LIGHTING, FALSE );\r\n//\r\n//\tD3DDevice_SetTexture( 0, (LPDIRECT3DBASETEXTURE8)mp_texture->pD3DTexture );\r\n//\tif( mp_texture->pD3DPalette )\r\n//\t{\r\n//\t\tD3DDevice_SetPalette( 0, mp_texture->pD3DPalette );\r\n//\t}\r\n//\t\r\n//\tD3DDevice_SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE2X );\r\n//\tD3DDevice_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE );\r\n//\tD3DDevice_SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE );\r\n//\tD3DDevice_SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE2X );\r\n//\tD3DDevice_SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );\r\n//\tD3DDevice_SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE );\r\n//\r\n//\tD3DDevice_SetStreamSource( 0, p_vertex_buffer, sizeof( sSpriteVert ));\r\n//\tEngineGlobals.p_Device->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n} // namespace NxNgc\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/sprite.h",
    "content": "#ifndef __SPRITE_H\r\n#define __SPRITE_H\r\n\r\n#include \"texture.h\"\r\n\r\nnamespace NxNgc\r\n{\r\n\r\nstruct SDraw2D\r\n{\r\n\t\t\t\t\tSDraw2D( float pri = 0.0f, bool hide = true );\r\n\tvirtual\t\t\t~SDraw2D( void );\r\n\r\n\tvoid\t\t\tSetPriority( float pri );\r\n\tfloat\t\t\tGetPriority( void ) const;\r\n\r\n\tvoid\t\t\tSetHidden( bool hide );\r\n\tbool\t\t\tIsHidden( void ) const;\r\n\r\n\t// members\r\n\tSDraw2D\t\t\t*mp_next;\r\n\r\n\t// Statics\r\n\tstatic void\t\tDrawAll( void );\r\n\r\nprivate:\r\n\tvoid\t\t\tInsertDrawList( void );\r\n\tvoid\t\t\tRemoveDrawList( void );\r\n\r\n\tvirtual void\tBeginDraw( void ) = 0;\r\n\tvirtual void\tDraw( void ) = 0;\r\n\tvirtual void\tEndDraw( void ) = 0;\r\n\r\n\t// Not even the derived classes should have direct access\r\n\tbool\t\t\tm_hidden;\r\n\tfloat\t\t\tm_pri;\r\n\r\n\t// 2D draw list (sorted by priority);\r\n\tstatic SDraw2D\t*sp_2D_draw_list;\r\n};\r\n\r\n\r\nstruct sSprite : public SDraw2D\r\n{\r\n\tpublic:\r\n\t\t\t\t\tsSprite( float pri = 0.0f );\r\n\t\t\t\t\t~sSprite();\r\n\r\n\tsTexture\t\t*mp_texture;\r\n\r\n\tfloat\t\t\tm_xpos;\r\n\tfloat\t\t\tm_ypos;\r\n\tuint16\t\t\tm_width;\r\n\tuint16\t\t\tm_height;\r\n\tfloat\t\t\tm_scale_x;\r\n\tfloat\t\t\tm_scale_y;\r\n\tfloat\t\t\tm_xhot;\r\n\tfloat\t\t\tm_yhot;\r\n\tfloat\t\t\tm_rot;\r\n\tuint32\t\t\tm_rgba;\r\n\r\nprivate:\r\n\r\n//\tIDirect3DVertexBuffer8\t*p_vertex_buffer;\r\n\t\r\n\tvoid\t\t\t\t\tBeginDraw();\r\n\tvoid\t\t\t\t\tDraw();\r\n\tvoid\t\t\t\t\tEndDraw(void);\r\n};\r\n\r\n\r\n} // namespace NxNgc\r\n\r\n\r\n#endif // __SPRITE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/texture.cpp",
    "content": "#include <string.h>\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <sys/file/filesys.h>\r\n#include \"chars.h\"\r\n#include \"texture.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\nnamespace NxNgc\r\n{\r\n\r\nuint8*\t\t\t\t\tTextureBuffer;\r\n//sTexture* Textures\t\t= NULL;\r\nuint32 NumTextures\t\t= 0;\r\nuint32 NumTextureGroups\t= 0;\r\nLst::HashTable< sTexture > *pTextureTable\t= NULL;\r\n\r\n\r\n\r\n\r\nsTexture::sTexture()\r\n{\r\n\tpTexelData = NULL;\r\n\tpAlphaData = NULL;\r\n\tpOldAlphaData = NULL;\r\n\tflags = 0;\r\n}\r\n\r\nsTexture::~sTexture()\r\n{\r\n\tif ( pTexelData )\r\n\t{\r\n\t\tdelete pTexelData;\r\n\t}\r\n\tif ( pAlphaData && ( ( flags & TEXTURE_FLAG_CHANNEL_MASK ) == TEXTURE_FLAG_CHANNEL_GREEN ) )\r\n\t{\r\n\t\tdelete pAlphaData;\r\n\t}\r\n\tif ( ( flags & TEXTURE_FLAG_OLD_DATA ) && pOldAlphaData )\r\n\t{\r\n\t\tdelete pOldAlphaData;\r\n\t}\r\n}\r\n\r\n\r\n\r\n// Eeeek - the .img contains PS2 specific register values for bit depth.\r\n// Use these values to convert them.\r\n#define PSMCT32\t\t0x00\r\n#define PSMCT24\t\t0x01\r\n#define PSMCT16\t\t0x02\r\n#define PSMCT16S\t0x0A\r\n#define PS_GPU24\t0x12\r\n#define PSMT8\t\t0x13\r\n#define PSMT4\t\t0x14\r\n#define PSMT8H\t\t0x1B\r\n#define PSMT4HL\t\t0x24\r\n#define PSMT4HH\t\t0x2C\r\n#define PSMZ32\t\t0x30\r\n#define PSMZ24\t\t0x31\r\n#define PSMZ16\t\t0x32\r\n#define PSMZ16S\t\t0x3A\r\n\r\nconst static uint32 TEXTURE_VERSION = 2;\r\n\r\nsTexture *LoadTexture( const char *p_filename )\r\n{\r\n\tsTexture *p_texture = NULL;\r\n\r\n\tvoid *p_FH = File::Open( p_filename, \"rb\" );\r\n\r\n\tif( p_FH )\r\n\t{\r\n\t\tuint32 version;\r\n\t\tuint32 checksum;\r\n\t\tuint32 width;\r\n\t\tuint32 height;\r\n\t\tuint32 depth;\r\n\t\tuint32 levels;\r\n\t\tuint32 rwidth;\r\n\t\tuint32 rheight;\r\n\t\tuint16 alphamap;\r\n\t\tuint16 hasholes;\r\n\r\n\t\tuint32 FileSize = File::GetFileSize(p_FH);\r\n\r\n\t\t// Load the actual texture\r\n\r\n\t\tp_texture = new sTexture();\r\n\r\n\t\tFile::Read( &version,  4, 1, p_FH );\r\n\t\tFile::Read( &checksum, 4, 1, p_FH );\r\n\t\tFile::Read( &width,    4, 1, p_FH );\r\n\t\tFile::Read( &height,   4, 1, p_FH );\r\n\t\tFile::Read( &depth,    4, 1, p_FH );\r\n\t\tFile::Read( &levels,   4, 1, p_FH );\r\n\t\tFile::Read( &rwidth,   4, 1, p_FH );\r\n\t\tFile::Read( &rheight,  4, 1, p_FH );\r\n\t\tFile::Read( &alphamap, 2, 1, p_FH );\r\n\t\tFile::Read( &hasholes, 2, 1, p_FH );\r\n\r\n\t\tDbg_MsgAssert( version <= TEXTURE_VERSION, (\"Illegal texture version number: %d (The newest version we deal with is: %d)\\n\", version, TEXTURE_VERSION ));\r\n\t\tDbg_MsgAssert( depth == 32, (\"We only deal with 32-bit textures.\\n\"));\r\n\t\r\n\t\tuint tsize = FileSize-(9*4);\r\n\r\n\t\tp_texture->flags = 0;\r\n\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_GREEN;\r\n\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\t\tif ( tsize == ( width * height * 4 ) )\r\n\t\t{\r\n\t\t\tp_texture->format\t\t= (uint8)GX_TF_RGBA8;\r\n\t\t\r\n\t\t\tp_texture->pTexelData = new uint8[tsize];\r\n\t\t\tp_texture->byte_size = tsize;\r\n\t\t\tDbg_MsgAssert(p_texture->pTexelData, (\"couldn't allocate buffer for texture file %s\\n\", p_filename));\r\n\t\t\tFile::Read( p_texture->pTexelData, 1, tsize, p_FH );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_texture->format\t\t= (uint8)GX_TF_CMPR;\r\n\t\t\r\n\t\t\tif ( alphamap )\r\n\t\t\t{\r\n\t\t\t\ttsize = tsize / 2;\r\n\t\t\t}\r\n\r\n\t\t\tp_texture->pTexelData = new uint8[tsize];\r\n\t\t\tp_texture->byte_size = tsize;\r\n\t\t\tDbg_MsgAssert(p_texture->pTexelData, (\"couldn't allocate buffer for texture file %s\\n\", p_filename));\r\n\t\t\tFile::Read( p_texture->pTexelData, 1, tsize, p_FH );\r\n\r\n\t\t\tif ( alphamap )\r\n\t\t\t{\r\n\t\t\t\tp_texture->pAlphaData = new uint8[tsize];\r\n\t\t\t\tDbg_MsgAssert(p_texture->pAlphaData, (\"couldn't allocate buffer for alpha file %s\\n\", p_filename));\r\n\t\t\t\tFile::Read( p_texture->pAlphaData, 1, tsize, p_FH );\r\n\t\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA;\r\n\t\t\t}\r\n\t\t}\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\r\n\t\tp_texture->Checksum\t\t= checksum;\r\n\t\tp_texture->BaseWidth\t= width;\r\n\t\tp_texture->BaseHeight\t= height;\r\n\t\tp_texture->Levels\t\t= levels;\r\n\t\tp_texture->ActualWidth\t= rwidth;\r\n\t\tp_texture->ActualHeight\t= rheight;\r\n\t\tp_texture->flags |= hasholes ? NxNgc::sTexture::TEXTURE_FLAG_HAS_HOLES : 0;\r\n\r\n\t\tFile::Close( p_FH );\r\n\t}\r\n\t\r\n\treturn p_texture;\r\n}\r\n\r\n\r\n\r\n\r\n\r\nsTexture* GetTexture( uint32 checksum )\r\n{\r\n\tif( pTextureTable )\r\n\t{\r\n\t\tpTextureTable->IterateStart();\r\n\t\tsTexture *p_tex = pTextureTable->IterateNext();\r\n\t\twhile( p_tex )\r\n\t\t{\r\n\t\t\tif( p_tex->Checksum == checksum )\r\n\t\t\t{\r\n\t\t\t\treturn p_tex;\r\n\t\t\t}\r\n\t\t\tp_tex = pTextureTable->IterateNext();\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n\r\n\r\nbool sTexture::SetRenderTarget( int width, int height, int depth, int z_depth )\r\n{\r\n//\tChecksum\t\t= 0;;\r\n//\tBaseWidth\t\t= width;\r\n//\tBaseHeight\t\t= height;\r\n//\tActualWidth\t\t= width;\r\n//\tActualHeight\t= height;\r\n//\tLevels\t\t\t= 0;\r\n//\tpAlphaData\t\t= NULL;\r\n//\tformat\t\t\t= GX_TF_RGBA8;\r\n//\t\r\n//\tpTexelData\t\t= new uint8[width*height*4];\r\n//\r\n\treturn true;\r\n}\r\n\r\nextern int g_id;\r\n\r\nGXTexMapID sTexture::Upload( GXTexMapID id, uint8 flags, float k )\r\n{\r\n\tGXTexMapID\trv = id;\r\n\r\n\t// Texels.\r\n\tGX::UploadTexture(  pTexelData,\r\n\t\t\t\t\t\tActualWidth,\r\n\t\t\t\t\t\tActualHeight,\r\n\t\t\t\t\t\t((GXTexFmt)format),\r\n\t\t\t\t\t\tflags & (1<<5) ? GX_CLAMP : GX_REPEAT,\r\n\t\t\t\t\t\tflags & (1<<6) ? GX_CLAMP : GX_REPEAT,\r\n\t\t\t\t\t\tLevels > 1 ? GX_TRUE : GX_FALSE,\r\n\t\t\t\t\t\tLevels > 1 ? GX_LIN_MIP_LIN : GX_LINEAR,\r\n\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\tLevels > 1 ? Levels - 1 : 0.0f,\r\n\t\t\t\t\t\tLevels > 1 ? k : 0.0f,\r\n\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\tGX_TRUE,\r\n\t\t\t\t\t\tGX_ANISO_1,\r\n\t\t\t\t\t\trv ); \r\n\trv = (GXTexMapID)(((int)rv)+1);\r\n\r\n\t// Alpha.\r\n\tif ( flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA )\r\n\t{\r\n\t\tGX::UploadTexture(  pAlphaData,\r\n\t\t\t\t\t\t\tActualWidth,\r\n\t\t\t\t\t\t\tActualHeight,\r\n\t\t\t\t\t\t\t((GXTexFmt)format),\r\n\t\t\t\t\t\t\tflags & (1<<5) ? GX_CLAMP : GX_REPEAT,\r\n\t\t\t\t\t\t\tflags & (1<<6) ? GX_CLAMP : GX_REPEAT,\r\n\t\t\t\t\t\t\tLevels > 1 ? GX_TRUE : GX_FALSE,\r\n\t\t\t\t\t\t\tLevels > 1 ? GX_LIN_MIP_LIN : GX_LINEAR,\r\n\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\tLevels > 1 ? Levels - 1 : 0.0f,\r\n\t\t\t\t\t\t\tLevels > 1 ? k : 0.0f,\r\n\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\tGX_TRUE,\r\n\t\t\t\t\t\t\tGX_ANISO_1,\r\n\t\t\t\t\t\t\trv ); \r\n\t\trv = (GXTexMapID)(((int)rv)+1);\r\n\t}\r\n\r\n\treturn rv;\r\n}\r\n\r\n\r\n} // namespace NxNgc\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/texture.h",
    "content": "#ifndef __TEXTURE_H\r\n#define __TEXTURE_H\r\n\r\n#include <core/HashTable.h>\r\n#include <dolphin.h>\r\n\r\nnamespace NxNgc\r\n{\r\n\r\nstruct sTexture\r\n{\r\n\tenum ETextureFlags\r\n\t{\r\n\t\tTEXTURE_FLAG_HAS_HOLES\t\t\t\t= (1<<0),\r\n\t\tTEXTURE_FLAG_HAS_ALPHA\t\t\t\t= (1<<1),\r\n\t\tTEXTURE_FLAG_CHANNEL_GREEN\t\t\t= (1<<2),\r\n\t\tTEXTURE_FLAG_CHANNEL_RED\t\t\t= (1<<3),\r\n\t\tTEXTURE_FLAG_CHANNEL_BLUE\t\t\t= (1<<4),\r\n\t\tTEXTURE_FLAG_SINGLE_OWNER\t\t\t= (1<<5),\r\n\t\tTEXTURE_FLAG_OLD_DATA\t\t\t\t= (1<<6),\r\n\t\tTEXTURE_FLAG_REPLACED\t\t\t\t= (1<<7),\r\n\r\n\t\tTEXTURE_FLAG_CHANNEL_MASK\t\t\t= ( TEXTURE_FLAG_CHANNEL_GREEN | TEXTURE_FLAG_CHANNEL_RED | TEXTURE_FLAG_CHANNEL_BLUE )\r\n\t};\r\n\r\n\t\t\t\t\t\tsTexture();\r\n\t\t\t\t\t\t~sTexture();\r\n\t\r\n\tbool\t\t\t\tSetRenderTarget( int width, int height, int depth, int z_depth );\r\n\r\n\tGXTexMapID\t\t\tUpload( GXTexMapID id, uint8 flags, float k );\r\n\r\n\tuint32\t\t\t\tChecksum;\r\n\tuint16\t\t\t\tBaseWidth, BaseHeight;\t\t// The size of the D3D texture (will be power of 2).\r\n\tuint16\t\t\t\tActualWidth, ActualHeight;\t// The size of the texture itself (may not be power of 2).\r\n\tuint8\t\t\t\tLevels;\r\n//\tuint8\t\t\t\tHasHoles;\r\n\tuint8\t\t\t\tformat;\r\n//\tuint8\t\t\t\thas_alpha;\r\n//\tuint16\t\t\t\tchannel;\r\n//\tuint16\t\t\t\tsingle_owner;\t\t\t// 1 means single owner.\r\n\tuint16\t\t\t\tflags;\r\n\tuint32\t\t\t\tbyte_size;\r\n\tuint8*\t\t\t\tpTexelData;\r\n\tuint8*\t\t\t\tpAlphaData;\r\n\tuint8*\t\t\t\tpOldAlphaData;\r\n};\r\n\r\n\r\nsTexture* GetTexture( uint32 checksum );\r\n\r\nsTexture\t*LoadTexture( const char *p_filename );\r\nvoid LoadTextureGroup(int Group);\r\n\r\nextern uint8 *TextureBuffer;\r\n//extern sTexture *Textures;\r\nextern Lst::HashTable< sTexture > *pTextureTable;\r\n\r\nextern uint32 NumTextures, NumTextureGroups;\r\nextern uint NextTBP, LastCBP;\r\n\r\n} // namespace NxNgc\r\n\r\n#endif // __TEXTURE_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/NX/types.h",
    "content": "#ifndef __TYPES_H\r\n#define __TYPES_H\r\n\r\ntypedef unsigned int \t\tuint;\r\ntypedef unsigned long long\tuint64;\r\ntypedef unsigned int\t\tuint32;\r\ntypedef unsigned short\t\tuint16;\r\ntypedef unsigned char\t\tuint8;\r\n\r\ntypedef signed int \t\t\tsint;\r\ntypedef signed long long\tsint64;\r\ntypedef signed int\t\t\tsint32;\r\ntypedef signed short\t\tsint16;\r\ntypedef signed char\t\t\tsint8;\r\n\r\n#endif // __TYPES_H\r\n"
  },
  {
    "path": "Code/Gfx/NGC/blur.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics (GFX)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tblur.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t06/21/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMotion-Blur effect\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#include <eetypes.h>\r\n//#include <eestruct.h>\r\n//#include <eekernel.h>\r\n//#include <eeregs.h>\r\n//\t\t\t\t \r\n//#include <core/defines.h>\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//extern int skyFrameBit;\r\n//\r\n//namespace Gfx\r\n//{\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//typedef struct\r\n//{\r\n//\tsceGifTag       giftag;\r\n//\tu_int       \tdata_buf[0x80];\r\n//} GsClearData __attribute__((aligned(16)));\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//void copy_frame(void)\r\n//{\r\n//\tint i,nloop;\r\n//\tGsClearData gcd;\r\n//\r\n//\tnloop = 25;\r\n//\r\n//\tSCE_GIF_CLEAR_TAG(&gcd.giftag);\r\n//\tgcd.giftag.NLOOP = nloop;\r\n//\tgcd.giftag.EOP = 1;\r\n//\tgcd.giftag.NREG = 1;\r\n//\tgcd.giftag.REGS0 = 0xe;\t// A_D\r\n//\r\n//\ti=0;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x0000001a; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000001; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x0000004c; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x000a0046; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000047; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000040; gcd.data_buf[i+1] = (u_int)0x00df0000; gcd.data_buf[i] = (u_int)0x027f0000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000042; gcd.data_buf[i+1] = (u_int)0x00000040; gcd.data_buf[i] = (u_int)0x00000064; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000008; gcd.data_buf[i+1] = (u_int)0x0000037c; gcd.data_buf[i] = (u_int)0x009fc00a; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000018; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000046; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000001; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000049; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000006; gcd.data_buf[i+1] = (u_int)0x00000006; gcd.data_buf[i] = (u_int)0xa8028000; i+=4;\r\n//\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000014; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000060; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x0000003b; gcd.data_buf[i+1] = (u_int)0x00000080; gcd.data_buf[i] = (u_int)0x00000080; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000001; gcd.data_buf[i+1] = (u_int)0x3f800000; gcd.data_buf[i] = (u_int)0x80808080; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000000; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x0000015e; i+=4;\r\n//\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000003; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000004; gcd.data_buf[i+1] = (u_int)0x00000001; gcd.data_buf[i] = (u_int)0x00100000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000003; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x0e002800; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000004; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x0e102800; i+=4;\r\n//\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x0000003f; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000000; i+=4;\r\n//\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000003; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00100000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000004; gcd.data_buf[i+1] = (u_int)0x00000001; gcd.data_buf[i] = (u_int)0x00100000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000003; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x0e102800; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000004; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x0e102800; i+=4;\r\n//\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x0000003f; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000008; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000005; i+=4;\r\n//\r\n//\tFlushCache(0);\r\n//\r\n//\t*D2_QWC = gcd.giftag.NLOOP+1;\r\n//\r\n//\t*D2_MADR = (u_int)&gcd.giftag & 0x0fffffff;\r\n//\tFlushCache(0);\r\n//\t*D2_CHCR = (1 << 8) | 1;\r\n//\r\n//\twhile( (*D2_CHCR & 0x0100) || (*GIF_STAT & 0x0c00) || ((*GS_CSR & 0x4000) == 0) );\r\n//\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//\r\n//void copy_frame1(void)\r\n//{\r\n//\tint i,nloop;\r\n//\tGsClearData gcd;\r\n//\r\n//\tnloop = 25;\r\n//\r\n//\tSCE_GIF_CLEAR_TAG(&gcd.giftag);\r\n//\tgcd.giftag.NLOOP = nloop;\r\n//\tgcd.giftag.EOP = 1;\r\n//\tgcd.giftag.NREG = 1;\r\n//\tgcd.giftag.REGS0 = 0xe;\t// A_D\r\n//\r\n//\ti=0;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x0000001a; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000001; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x0000004c; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x000a0000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000047; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000040; gcd.data_buf[i+1] = (u_int)0x00df0000; gcd.data_buf[i] = (u_int)0x027f0000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000042; gcd.data_buf[i+1] = (u_int)0x00000040; gcd.data_buf[i] = (u_int)0x00000064; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000008; gcd.data_buf[i+1] = (u_int)0x0000037c; gcd.data_buf[i] = (u_int)0x009fc00a; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000018; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00080008; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000046; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000001; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000049; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000006; gcd.data_buf[i+1] = (u_int)0x00000006; gcd.data_buf[i] = (u_int)0xa80288c0; i+=4;\r\n//\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000014; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000060; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x0000003b; gcd.data_buf[i+1] = (u_int)0x00000080; gcd.data_buf[i] = (u_int)0x00000080; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000001; gcd.data_buf[i+1] = (u_int)0x3f800000; gcd.data_buf[i] = (u_int)0x80808080; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000000; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x0000015e; i+=4;\r\n//\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000003; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000004; gcd.data_buf[i+1] = (u_int)0x00000001; gcd.data_buf[i] = (u_int)0x00000000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000003; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x0e002800; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000004; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x0e002800; i+=4;\r\n//\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x0000003f; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000000; i+=4;\r\n//\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000003; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00100000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000004; gcd.data_buf[i+1] = (u_int)0x00000001; gcd.data_buf[i] = (u_int)0x00000000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000003; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x0e102800; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000004; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x0e002800; i+=4;\r\n//\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x0000003f; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000000; i+=4;\r\n//\tgcd.data_buf[i+3] = (u_int)0x0; gcd.data_buf[i+2] = (u_int)0x00000008; gcd.data_buf[i+1] = (u_int)0x00000000; gcd.data_buf[i] = (u_int)0x00000005; i+=4;\r\n//\r\n//\tFlushCache(0);\r\n//\r\n//\t*D2_QWC = gcd.giftag.NLOOP+1;\r\n//\r\n//\t*D2_MADR = (u_int)&gcd.giftag & 0x0fffffff;\r\n//\tFlushCache(0);\r\n//\t*D2_CHCR = (1 << 8) | 1;\r\n//\r\n//\twhile( (*D2_CHCR & 0x0100) || (*GIF_STAT & 0x0c00) || ((*GS_CSR & 0x4000) == 0) );\r\n//\r\n//}\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//void\tBlur( void )\r\n//{\r\n//\tif (skyFrameBit & 0x1)\r\n//\t{\r\n//\t\tcopy_frame1();\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tcopy_frame();\r\n//\t}\r\n//\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//\r\n//\r\n//} // namespace Gfx\r\n//\r\n//"
  },
  {
    "path": "Code/Gfx/NGC/p_NxGeom.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxGeom.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  3/4/2002\r\n//****************************************************************************\r\n\r\n#include <gfx/Ngc/p_nxgeom.h>\r\n\r\n#include <core/math.h>\r\n\r\n#include <gfx/skeleton.h>\r\n#include <gfx/Ngc/p_nxmesh.h>\r\n#include <gfx/Ngc/p_nxmodel.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n#include <gfx/Ngc/nx/instance.h>\r\n#include <gel/music/Ngc/p_music.h>\r\n\r\n#include <gel/collision/collision.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\r\nstatic s32\tlast_audio_update = 0;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void do_audio_update( void )\r\n{\r\n\ts32 t = OSGetTick();\r\n\tif(( t < last_audio_update ) || ( OSDiffTick( t, last_audio_update ) > (s32)( OS_TIMER_CLOCK / 60 )))\r\n\t{\r\n\t\tlast_audio_update = t;\r\n\t\tPcm::PCMAudio_Update();\r\n\t}\r\n}\r\n\t\r\n\t\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcGeom::CNgcGeom() : mp_init_mesh_list( NULL ), m_mesh_array( NULL ), m_visible( 0x55 )\r\n{\r\n\tmp_instance = NULL;\r\n//\tmp_sector\t= NULL;\r\n\tm_active\t= true;\r\n\tm_mod.offset[X] = 0.0f;\r\n\tm_mod.offset[Y] = 0.0f;\r\n\tm_mod.offset[Z] = 0.0f;\r\n\tm_mod.offset[W] = 0.0f;\r\n\tm_mod.scale[X] = 1.0f;\r\n\tm_mod.scale[Y] = 1.0f;\r\n\tm_mod.scale[Z] = 1.0f;\r\n\tm_mod.scale[W] = 1.0f;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcGeom::~CNgcGeom( void )\r\n{\r\n\tDestroyMeshArray();\r\n\r\n\tif( mp_instance != NULL )\r\n\t{\r\n\t\tdelete mp_instance;\r\n\t\tmp_instance = NULL;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Mesh List Functions\r\n//\r\n// The mesh list is only for initialization of the CGeom.  As we find all the\r\n// meshes for the CGeoms, we add them to the temporary lists.  When we are\r\n// done, the list is copied into a permanent array.\r\n//\r\n// All the list functions use the TopDownHeap for memory allocation.\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::InitMeshList( void )\r\n{\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().TopDownHeap());\r\n\tmp_init_mesh_list = new Lst::Head< NxNgc::sMesh >;\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::AddMesh( NxNgc::sMesh *mesh )\r\n{\r\n\tDbg_Assert( mp_init_mesh_list );\r\n\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().TopDownHeap());\r\n\tLst::Node< NxNgc::sMesh > *node = new Lst::Node< NxNgc::sMesh > (mesh);\r\n\tmp_init_mesh_list->AddToTail( node );\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::CreateMeshArray( void )\r\n{\r\n\tif( !m_mesh_array )\r\n\t{\r\n\t\tDbg_Assert( mp_init_mesh_list );\r\n\r\n\t\tm_num_mesh = mp_init_mesh_list->CountItems();\r\n\t\tif (m_num_mesh)\r\n\t\t{\r\n\t\t\tLst::Node< NxNgc::sMesh > *mesh, *next;\r\n\r\n\t\t\tm_mesh_array = new NxNgc::sMesh*[m_num_mesh];\r\n\t\t\tint k = 0;\r\n\t\t\tfor( mesh = mp_init_mesh_list->GetNext(); mesh; mesh = next )\r\n\t\t\t{\r\n\t\t\t\tnext\t\t\t= mesh->GetNext();\r\n\t\t\t\tm_mesh_array[k]\t= mesh->GetData();\r\n\t\t\t\tdelete mesh;\r\n\t\t\t\tk++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Delete temporary list.\r\n\t\tdelete mp_init_mesh_list;\r\n\t\tmp_init_mesh_list = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nLst::Head< NxNgc::sMesh >\t*CNgcGeom::GetMeshList( void )\r\n{\r\n\treturn mp_init_mesh_list;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcGeom::RegisterMeshArray( bool just_count )\r\n{\r\n\t// Tells the engine to count or add the meshes for this sector to the rendering list for supplied scene id.\r\n\tif( just_count )\r\n\t{\r\n\t\tmp_scene->GetEngineScene()->CountMeshes( m_num_mesh, m_mesh_array );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_scene->GetEngineScene()->AddMeshes( m_num_mesh, m_mesh_array );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::DestroyMeshArray( void )\r\n{\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\t// Tells the engine to remove the meshes for this sector from the rendering list for supplied scene id.\r\n\t\tif( mp_scene && mp_scene->GetEngineScene())\r\n\t\t{\r\n\t\t\tmp_scene->GetEngineScene()->RemoveMeshes( m_num_mesh, m_mesh_array );\r\n\t\t}\r\n\r\n\t\t// Now actually go through and delete each mesh.\r\n\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxNgc::sMesh *p_mesh = m_mesh_array[m];\r\n\r\n\t\t\t// Delete pools.\r\n\t\t\tif ( p_mesh->m_flags & NxNgc::sMesh::MESH_FLAG_CLONED_POS )\r\n\t\t\t{\r\n\t\t\t\tdelete p_mesh->mp_dl->mp_pos_pool;\r\n\t\t\t}\r\n\r\n\t\t\tif ( p_mesh->m_flags & NxNgc::sMesh::MESH_FLAG_CLONED_COL )\r\n\t\t\t{\r\n\t\t\t\tdelete p_mesh->mp_dl->mp_col_pool;\r\n\t\t\t}\r\n\r\n\t\t\t// Delete copied dl if it's there.\r\n\t\t\tif ( p_mesh->m_flags & NxNgc::sMesh::MESH_FLAG_CLONED_DL )\r\n\t\t\t{\r\n\t\t\t\tdelete p_mesh->mp_dl;\r\n\t\t\t}\r\n\r\n\t\t\tdelete p_mesh;\r\n\t\t}\r\n\r\n\t\tdelete [] m_mesh_array;\r\n\t\tm_mesh_array = NULL;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Generates an entirely new engine scene.                        */\r\n/* Used when instance-cloning CGeoms.                             */\r\n/*                                                                */\r\n/******************************************************************/\r\nNxNgc::sScene* CNgcGeom::GenerateScene( void )\r\n{\r\n\tNxNgc::sScene *p_scene = new NxNgc::sScene();\r\n\r\n\tmemcpy( p_scene, mp_scene->GetEngineScene(), sizeof( NxNgc::sScene ) );\r\n\r\n\tp_scene->m_flags\t\t\t\t= SCENE_FLAG_CLONED_GEOM;\r\n\tp_scene->m_is_dictionary\t\t= false;\r\n\r\n\tp_scene->m_num_meshes\t\t\t= 0;\t\t// No meshes as yet.\r\n\tp_scene->m_num_filled_meshes\t= 0;\r\n\tp_scene->mpp_mesh_list\t\t\t= NULL;\r\n\r\n\tp_scene->mp_hierarchyObjects\t= NULL;\r\n\tp_scene->m_numHierarchyObjects\t= 0;\r\n\r\n\tp_scene->CountMeshes( m_num_mesh, m_mesh_array );\r\n\tp_scene->CreateMeshArrays();\r\n\tp_scene->AddMeshes( m_num_mesh, m_mesh_array );\r\n\tp_scene->SortMeshes();\r\n\r\n\r\n\r\n\t// Set the bounding box and bounding sphere.\r\n//\tp_scene->m_bbox = m_bbox;\r\n//\tp_scene->FigureBoundingVolumes();\r\n\t\r\n\treturn p_scene;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CNgcGeom::plat_load_geom_data(CMesh* pMesh, CModel* pModel, bool color_per_material)\r\n{\r\n//\t// The skeleton must exist by this point (unless it's a hacked up car).\r\n//\tint numBones;\r\n//\tnumBones = pModel->GetSkeleton() ? pModel->GetSkeleton()->GetNumBones() : 1;\r\n//\t\r\n//\tMth::Matrix temp;\r\n//\tCNgcMesh *p_Ngc_mesh = static_cast<CNgcMesh*>( pMesh );\r\n//\tmp_instance = new NxNgc::CInstance( p_Ngc_mesh->GetScene()->GetEngineScene(), temp, numBones, pModel->GetBoneTransforms() );\r\n//\r\n//    return true;\r\n\t\r\n\t\r\n\t// The skeleton must exist by this point (unless it's a hacked up car).\r\n\tint numBones;\r\n\tnumBones = pModel->GetNumBones();\r\n\t\r\n\tMth::Matrix temp;\r\n\tCNgcMesh *p_Ngc_mesh = static_cast<CNgcMesh*>( pMesh );\r\n\t\r\n\t// Store a pointer to the CNgcMesh, used for obtaining CAS poly removal data.\r\n\tmp_mesh = p_Ngc_mesh;\r\n\r\n//\tCNgcModel *p_Ngc_model = static_cast<CNgcModel*>( pModel );\r\n\tNxNgc::CInstance *p_instance = new NxNgc::CInstance( p_Ngc_mesh->GetScene()->GetEngineScene(), temp, numBones, pModel->GetBoneTransforms());\r\n\tSetInstance( p_instance );\r\n\tp_instance->SetModel( pModel );\r\n\r\n    return true;\r\n\r\n\r\n//\tint numBones;\r\n//\tnumBones = pModel->GetSkeleton() ? pModel->GetSkeleton()->GetNumBones() : 0;\r\n//\r\n//\tNxNgc::Mat temp;\r\n//\tNxNgc::MatIdentity(temp);\r\n//\tDbg_Assert( mp_instance == NULL );\r\n//\r\n//\tDbg_Assert( pMesh );\r\n//\tDbg_Assert( pMesh->GetTextureDictionary() );\r\n//\tNxNgc::sScene* pScene = ((Nx::CNgcTexDict*)pMesh->GetTextureDictionary())->GetEngineTextureDictionary();\r\n//\tDbg_Assert( pScene );\r\n//\r\n//\tif ( numBones )\r\n//\t{\r\n//\t\tmp_matrices = ((CNgcModel*)pModel)->GetMatrices();\r\n//\t}\r\n//\tmp_instance = new NxNgc::CInstance(pScene, temp, numBones, mp_matrices ); \r\n//\r\n//\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_set_active( bool active )\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\tmp_instance->SetActive( active );\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tm_active = active;\r\n\t\tif( m_mesh_array )\r\n\t\t{\r\n\t\t\tfor( uint m = 0; m < m_num_mesh; ++m )\r\n\t\t\t{\r\n\t\t\t\tNxNgc::sMesh *p_mesh = m_mesh_array[m];\r\n\t\t\t\tp_mesh->SetActive( active );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcGeom::plat_is_active( void ) const\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\treturn mp_instance->GetActive();\r\n\t}\t\r\n\treturn m_active;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_set_world_position( const Mth::Vector& pos )\r\n{\r\n//\treturn;\r\n\t// Ensure w component is correct.\r\n\r\n\tif( mp_instance )\r\n\t{\r\n\t\tmp_instance->GetTransform()->SetPos( pos );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Go through and adjust the individual meshes.\r\n//\t\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n\t\t{\r\n//\t\t\tNxNgc::sMesh *p_mesh = m_mesh_array[i];\r\n//\t\t\tp_mesh->mp_mod = &m_mod;\r\n\r\n\t\t\tMth::Vector delta_pos = pos - m_mod.offset;\r\n\r\n\t\t\tm_mod.offset[X] = pos[X];\r\n\t\t\tm_mod.offset[Y] = pos[Y];\r\n\t\t\tm_mod.offset[Z] = pos[Z];\r\n\r\n\t\t\tint num = plat_get_num_render_verts();\r\n\t\t\tMth::Vector * p_verts = new Mth::Vector[num];\r\n\t\t\tplat_get_render_verts( p_verts );\r\n\t\t\tfor ( int lp = 0; lp < num; lp++ )\r\n\t\t\t{\r\n\t\t\t\tp_verts[lp] += delta_pos;\r\n\t\t\t}\r\n\t\t\tplat_set_render_verts( p_verts );\r\n\t\t\tdelete p_verts;\r\n\r\n\r\n//\t\t\tMth::Vector delta_pos( pos[X] - m_offset[X], pos[Y] - m_offset[Y], pos[Z] - m_offset[Z], 1.0f );\r\n//\t\t\tp_mesh->mp_dl->m_sphere[X] += delta_pos[X];\r\n//\t\t\tp_mesh->mp_dl->m_sphere[Y] += delta_pos[Y];\r\n//\t\t\tp_mesh->mp_dl->m_sphere[Z] += delta_pos[Z];\r\n//\t\t\tp_mesh->SetPosition( proper_pos );\r\n\t\t}\r\n\r\n//\t\tif ( mp_scene->GetEngineScene()->mp_scene_data )\r\n//\t\t{\r\n//\t\t\tMth::Vector proper_pos( pos[X] - m_offset[X], pos[Y] - m_offset[Y], pos[Z] - m_offset[Z], 1.0f );\r\n//\t\r\n//\t\t\tfloat * pos = mp_scene->GetEngineScene()->mp_pos_pool;\r\n//\t\t\tfor ( int lp = 0; lp += mp_scene->GetEngineScene()->mp_scene_data->m_num_pos; lp++ )\r\n//\t\t\t{\r\n//\t\t\t\tpos[0] += proper_pos[X];\r\n//\t\t\t\tpos[1] += proper_pos[Y];\r\n//\t\t\t\tpos[2] += proper_pos[Z];\r\n//\t\t\t\tpos += 3;\r\n//\t\t\t}\r\n//\t\t\tm_offset[X] = proper_pos[X];\r\n//\t\t\tm_offset[Y] = proper_pos[Y];\r\n//\t\t\tm_offset[Z] = proper_pos[Z];\r\n//\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\tCNgcGeom::plat_get_world_position() const\r\n{\r\n\tstatic Mth::Vector pos;\r\n\tpos.Set( m_mod.offset[X], m_mod.offset[Y], m_mod.offset[Z], 1.0f );\r\n\treturn pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::CBBox & CNgcGeom::plat_get_bounding_box( void ) const\r\n{\r\n\tDbg_Assert(mp_coll_tri_data);\r\n\treturn mp_coll_tri_data->GetBBox();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_set_bounding_sphere( const Mth::Vector& boundingSphere )\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\tNxNgc::sScene *p_scene = mp_instance->GetScene();\r\n\t\tif( p_scene )\r\n\t\t{\r\n\t\t\tif ( mp_instance->GetBoneTransforms() && p_scene->m_numHierarchyObjects )\r\n\t\t\t{\r\n\t\t\t\t// Car or something...\r\n\t\t\t\tp_scene->m_sphere = boundingSphere;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( p_scene->mpp_mesh_list[0] )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_scene->mpp_mesh_list[0]->mp_dl->mp_object_header->m_sphere = boundingSphere;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::Vector CNgcGeom::plat_get_bounding_sphere( void ) const\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\tNxNgc::sScene *p_scene = mp_instance->GetScene();\r\n\t\tif( p_scene )\r\n\t\t{\r\n\t\t\tif ( mp_instance->GetBoneTransforms() && p_scene->m_numHierarchyObjects )\r\n\t\t\t{\r\n\t\t\t\t// Car or something...\r\n\t\t\t\treturn p_scene->m_sphere;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( p_scene->mpp_mesh_list[0] )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn p_scene->mpp_mesh_list[0]->mp_dl->mp_object_header->m_sphere;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn Mth::Vector( 0.0f, 0.0f, 0.0f, 10000.0f );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcGeom::plat_render(Mth::Matrix* pRootMatrix, Mth::Matrix* pBoneMatrices, int numBones)\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\tmp_instance->SetTransform( *pRootMatrix );\r\n\t}\r\n    return true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_set_bone_matrix_data( Mth::Matrix* pBoneMatrices, int numBones )\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\tMth::Matrix* p_bone_matrices\t= mp_instance->GetBoneTransforms();\r\n\t\tmemcpy( p_bone_matrices, pBoneMatrices, numBones * sizeof( Mth::Matrix ));\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcGeom::plat_hide_polys( uint32 mask )\r\n{\r\n\tif( mp_mesh )\r\n\t{\r\n\t\t// Obtain a pointer to the Ngc scene.\r\n\t\tNxNgc::sScene *p_engine_scene = GetInstance()->GetScene();\r\n\r\n\t\t// Request the scene to hide the relevant polys.\r\n\t\tp_engine_scene->HidePolys( mask, mp_mesh->GetCASData(), mp_mesh->GetNumCASData());\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_set_visibility( uint32 mask )\r\n{\r\n\t// Set values\r\n\tm_visible = mask & 0xff;\r\n\r\n\tif( mp_instance )\r\n\t{\r\n\t\tmp_instance->SetVisibility( mask & 0xff );\r\n\t}\t\r\n//\telse\r\n//\t{\r\n\t\tif( m_mesh_array )\r\n\t\t{\r\n\t\t\tfor( uint m = 0; m < m_num_mesh; ++m )\r\n\t\t\t{\r\n\t\t\t\tNxNgc::sMesh *p_mesh = m_mesh_array[m];\r\n\t\t\t\tp_mesh->SetVisibility( mask & 0xff );\r\n\t\t\t}\r\n\t\t}\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 CNgcGeom::plat_get_visibility( void ) const\r\n{\r\n\treturn m_visible | 0xFFFFFF00;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_set_color( Image::RGBA rgba )\r\n{\r\n\tif( mp_instance && mp_instance->GetBoneTransforms() )\r\n\t{\r\n\t\tif( mp_instance && mp_instance->GetScene())\r\n\t\t{\r\n\t\t\tfor( int m = 0; m < mp_instance->GetScene()->m_num_filled_meshes; ++m )\r\n\t\t\t{\r\n\t\t\t\tNxNgc::sMesh\t\t\t*p_mesh\t= mp_instance->GetScene()->mpp_mesh_list[m];\r\n\t\t\t\tNxNgc::sMaterialHeader\t*p_mat\t= p_mesh->mp_dl->m_material.p_header;\r\n\t\t\t\tif( p_mat )\r\n\t\t\t\t{\r\n\t\t\t\t\tNxNgc::sMaterialPassHeader * p_pass = &mp_instance->GetScene()->mp_material_pass[p_mat->m_pass_item];\r\n\t\t\t\t\tfor ( int pass = 0; pass < p_mat->m_passes; pass++, p_pass++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_pass->m_color.r = rgba.r;\r\n\t\t\t\t\t\tp_pass->m_color.g = rgba.g;\r\n\t\t\t\t\t\tp_pass->m_color.b = rgba.b;\r\n\r\n//\t\t\t\t\t\tNxNgc::sTextureDL* p_dl = &mp_instance->GetScene()->mp_texture_dl[p_mat->m_texture_dl_id];\r\n//\t\t\t\t\t\tGX::begin( p_dl->mp_dl, p_dl->m_dl_size );\r\n//\t\t\t\t\t\tmulti_mesh( p_mat, p_pass, true, true );\r\n//\t\t\t\t\t\tp_dl->m_dl_size = GX::end();\r\n\r\n//\t\t\t\t\t\tint size = mp_instance->GetScene()->mp_texture_dl[p_mat->m_texture_dl_id].m_dl_size;\r\n//\t\t\t\t\t\tvoid * p_dl = mp_instance->GetScene()->mp_texture_dl[p_mat->m_texture_dl_id].mp_dl;\r\n//\t\t\t\t\t\tGX::ChangeMaterialColor( (unsigned char *)p_dl, size, p_pass->m_color, pass );\r\n\r\n\t\t\t\t\t\tp_mat->m_flags |= (1<<4);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( m_mesh_array != NULL )\r\n\t{\r\n\t\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n\t\t{\r\n\t\t\tNxNgc::sMesh *p_mesh = m_mesh_array[i];\r\n\t\t\tp_mesh->m_base_color.r = rgba.r;\r\n\t\t\tp_mesh->m_base_color.g = rgba.g;\r\n\t\t\tp_mesh->m_base_color.b = rgba.b;\r\n\t\t\tp_mesh->m_base_color.a = rgba.a;\r\n\t\t}\r\n\t}\r\n\r\n//\t// Oofa, nasty hack.\r\n//\tif( mp_instance )\r\n//\t{\r\n//\t\t// Grab the engine scene from the geom, and set all meshes to the color.\r\n//\t\tNxNgc::sScene *p_scene = mp_instance->GetScene();\r\n//\t\tfor( int i = 0; i < p_scene->m_num_opaque_entries; ++i )\r\n//\t\t{\r\n//\t\t\tNxNgc::sMesh *p_mesh = p_scene->m_opaque_meshes[i];\r\n//\t\t\tp_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE;\r\n//\t\t\tp_mesh->m_material_color_override.r = rgba.r;\r\n//\t\t\tp_mesh->m_material_color_override.g = rgba.g;\r\n//\t\t\tp_mesh->m_material_color_override.b = rgba.b;\r\n//\t\t\tp_mesh->m_material_color_override.a = rgba.a;\r\n//\t\t}\r\n//\t\tfor( int i = 0; i < p_scene->m_num_semitransparent_entries; ++i )\r\n//\t\t{\r\n//\t\t\tNxNgc::sMesh *p_mesh = p_scene->m_semitransparent_meshes[i];\r\n//\t\t\tp_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE;\r\n//\t\t\tp_mesh->m_material_color_override.r = rgba.r;\r\n//\t\t\tp_mesh->m_material_color_override.g = rgba.g;\r\n//\t\t\tp_mesh->m_material_color_override.b = rgba.b;\r\n//\t\t\tp_mesh->m_material_color_override.a = rgba.a;\r\n//\t\t}\r\n//\t}\r\n//\telse if( m_mesh_array != NULL )\r\n//\t{\r\n//\t\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n//\t\t{\r\n//\t\t\tNxNgc::sMesh *p_mesh = m_mesh_array[i];\r\n//\t\t\tp_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE;\r\n//\t\t\tp_mesh->m_material_color_override.r = rgba.r;\r\n//\t\t\tp_mesh->m_material_color_override.g = rgba.g;\r\n//\t\t\tp_mesh->m_material_color_override.b = rgba.b;\r\n//\t\t\tp_mesh->m_material_color_override.a = rgba.a;\r\n//\t\t}\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_clear_color( void )\r\n{\r\n\tif( mp_instance && mp_instance->GetBoneTransforms() )\r\n\t{\r\n\t\tif( mp_instance && mp_instance->GetScene())\r\n\t\t{\r\n\t\t\tfor( int m = 0; m < mp_instance->GetScene()->m_num_filled_meshes; ++m )\r\n\t\t\t{\r\n\t\t\t\tNxNgc::sMesh\t\t\t*p_mesh\t= mp_instance->GetScene()->mpp_mesh_list[m];\r\n\t\t\t\tNxNgc::sMaterialHeader\t*p_mat\t= p_mesh->mp_dl->m_material.p_header;\r\n\t\t\t\tif( p_mat )\r\n\t\t\t\t{\r\n\t\t\t\t\tNxNgc::sMaterialPassHeader * p_pass = &mp_instance->GetScene()->mp_material_pass[p_mat->m_pass_item];\r\n\t\t\t\t\tfor ( int pass = 0; pass < p_mat->m_passes; pass++, p_pass++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_pass->m_color.r = 128;\r\n\t\t\t\t\t\tp_pass->m_color.g = 128;\r\n\t\t\t\t\t\tp_pass->m_color.b = 128;\r\n//\t\t\t\t\t\tNxNgc::sTextureDL* p_dl = &mp_instance->GetScene()->mp_texture_dl[p_mat->m_texture_dl_id];\r\n//\t\t\t\t\t\tGX::begin( p_dl->mp_dl, p_dl->m_dl_size );\r\n//\t\t\t\t\t\tmulti_mesh( p_mat, p_pass, true, true );\r\n//\t\t\t\t\t\tp_dl->m_dl_size = GX::end();\r\n\r\n//\t\t\t\t\t\tint size = mp_instance->GetScene()->mp_texture_dl[p_mat->m_texture_dl_id].m_dl_size;\r\n//\t\t\t\t\t\tvoid * p_dl = mp_instance->GetScene()->mp_texture_dl[p_mat->m_texture_dl_id].mp_dl;\r\n//\t\t\t\t\t\tGX::ChangeMaterialColor( (unsigned char *)p_dl, size, p_pass->m_color, pass );\r\n\t\t\t\t\t\tp_mat->m_flags |= (1<<4);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( m_mesh_array != NULL )\r\n\t{\r\n\t\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n\t\t{\r\n\t\t\tNxNgc::sMesh *p_mesh = m_mesh_array[i];\r\n\t\t\tp_mesh->m_base_color.r = 128;\r\n\t\t\tp_mesh->m_base_color.g = 128;\r\n\t\t\tp_mesh->m_base_color.b = 128;\r\n\t\t\tp_mesh->m_base_color.a = 255;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nImage::RGBA\tCNgcGeom::plat_get_color( void ) const\r\n{\r\n\tImage::RGBA rgba( 0, 0, 0, 0 );\r\n\r\n\tif( mp_instance && mp_instance->GetBoneTransforms() )\r\n\t{\r\n\t\tif( mp_instance && mp_instance->GetScene())\r\n\t\t{\r\n\t\t\tif ( mp_instance->GetScene()->m_num_filled_meshes > 0 )\r\n\t\t\t{\r\n\t\t\t\tNxNgc::sMesh\t\t\t*p_mesh\t= mp_instance->GetScene()->mpp_mesh_list[0];\r\n\t\t\t\tNxNgc::sMaterialHeader\t*p_mat\t= p_mesh->mp_dl->m_material.p_header;\r\n\t\t\t\tif( p_mat )\r\n\t\t\t\t{\r\n\t\t\t\t\tNxNgc::sMaterialPassHeader * p_pass = &mp_instance->GetScene()->mp_material_pass[p_mat->m_pass_item];\r\n\r\n\t\t\t\t\trgba.r = p_pass->m_color.r;\r\n\t\t\t\t\trgba.g = p_pass->m_color.g;\r\n\t\t\t\t\trgba.b = p_pass->m_color.b;\r\n\t\t\t\t\trgba.a = p_pass->m_color.a;\r\n\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( m_mesh_array != NULL )\r\n\t{\r\n\t\tNxNgc::sMesh *p_mesh = m_mesh_array[0];\r\n\t\trgba.r = p_mesh->m_base_color.r;\r\n\t\trgba.g = p_mesh->m_base_color.g;\r\n\t\trgba.b = p_mesh->m_base_color.b;\r\n\t\trgba.a = p_mesh->m_base_color.a;\r\n\t}\r\n\r\n\treturn rgba;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcGeom::plat_set_material_color( uint32 mat_name_checksum, int pass, Image::RGBA rgba )\r\n{\r\n\tbool something_changed = false;\r\n\r\n\tif( mp_instance && mp_instance->GetScene())\r\n\t{\r\n\t\tfor( int m = 0; m < mp_instance->GetScene()->m_num_filled_meshes; ++m )\r\n\t\t{\r\n\t\t\tNxNgc::sMesh\t\t\t*p_mesh\t= mp_instance->GetScene()->mpp_mesh_list[m];\r\n\t\t\tNxNgc::sMaterialHeader\t*p_mat\t= p_mesh->mp_dl->m_material.p_header;\r\n\t\t\tif( p_mat )\r\n\t\t\t{\r\n\t\t\t\tbool\twant_this_material\t= false;\r\n\t\t\t\tint\t\tadjusted_pass\t\t= pass;\r\n\r\n\t\t\t\t// We are searching for materials with a matching name. However there is a caveat in that the\r\n\t\t\t\t// conversion process sometimes creates new materials for geometry flagged as 'render as separate', or for\r\n\t\t\t\t// geometry which is mapped with only certain passes of a multipass material (or both cases).\r\n\t\t\t\t// In such a case, the new material name checksum will differ from the original material name checksum,\r\n\t\t\t\t// with the following bits having significance (i.e. consider bitflags = new_namechecksum - old_namechecksum ):\r\n\t\t\t\t//\r\n\t\t\t\t// Bits 3->6\tPass flags indicating which passes of the original material this material uses\r\n\t\t\t\t// Bits 0->2\tAbsolute number ('render as separate' flagged geometry) indicating which single pass of the material this material represents.\r\n\t\t\t\tif( p_mat->m_materialNameChecksum == mat_name_checksum )\r\n\t\t\t\t\twant_this_material = true;\r\n\t\t\t\telse if(( p_mat->m_materialNameChecksum > mat_name_checksum ) && (( p_mat->m_materialNameChecksum - mat_name_checksum ) <= 0x7F ))\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 checksum_diff\t\t= p_mat->m_materialNameChecksum - mat_name_checksum;\r\n\t\t\t\t\tint render_separate_pass\t= checksum_diff & 0x07;\r\n\t\t\t\t\tuint32 pass_flags\t\t\t= checksum_diff >> 3;\r\n\r\n\t\t\t\t\tif( render_separate_pass )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( render_separate_pass == ( pass + 1 ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\twant_this_material = true;\r\n\r\n\t\t\t\t\t\t\t// Readjust the pass to zero, since this material was formed as a single pass of a multipass material.\r\n\t\t\t\t\t\t\tadjusted_pass = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( pass_flags )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// This material was created during scene conversion from another material with more passes.\r\n\t\t\t\t\t\tif( pass_flags & ( 1 << pass ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\twant_this_material = true;\r\n\t\t\t\t\t\t\tfor( int p = 0; p < pass; ++p )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif(( pass_flags & ( 1 << p )) == 0 )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Readjust the pass down by 1, since this material was created as a subset of another material.\r\n\t\t\t\t\t\t\t\t\t--adjusted_pass;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( want_this_material )\r\n\t\t\t\t{\r\n//\t\t\t\t\tDbg_Assert((uint32)adjusted_pass < p_mat->m_passes );\r\n\t\t\r\n\t\t\t\t\tif ( adjusted_pass < p_mat->m_passes )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tNxNgc::sMaterialPassHeader * p_pass = &mp_instance->GetScene()->mp_material_pass[p_mat->m_pass_item+adjusted_pass];\r\n\r\n\t\t\t\t\t\tif( !( p_pass->m_flags & (1<<4) ))\t\t// COLOR_LOCKED\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_pass->m_color.r = rgba.r;\r\n\t\t\t\t\t\t\tp_pass->m_color.g = rgba.g;\r\n\t\t\t\t\t\t\tp_pass->m_color.b = rgba.b;\r\n\r\n//\t\t\t\t\t\t\tvoid * p_dl = mp_instance->GetScene()->mp_texture_dl[p_mat->m_texture_dl_id].mp_dl;\r\n//\t\t\t\t\t\t\tint size = mp_instance->GetScene()->mp_texture_dl[p_mat->m_texture_dl_id].m_dl_size;\r\n//\r\n//\t\t\t\t\t\t\tGX::ChangeMaterialColor( (unsigned char *)p_dl, size, p_pass->m_color, adjusted_pass );\r\n\r\n\t\t\t\t\t\t\t// Flag as being direct for ever more.\r\n\t\t\t\t\t\t\tp_mat->m_flags |= (1<<4);\r\n\r\n\t\t\t\t\t\t\tsomething_changed = true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn something_changed;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcGeom *CNgcGeom::plat_clone( bool instance, CScene *p_dest_scene )\r\n{\r\n//\tinstance = true;\r\n\r\n\tCNgcGeom *p_clone = NULL;\r\n\r\n\t// This is a CNgcGeom 'hanging' from a sector. Create a new CNgcGeom which will store the CInstance.\r\n\tp_clone = new CNgcGeom();\r\n\tp_clone->mp_scene = mp_scene;\r\n\r\n\t// Create new meshes for the clone.\r\n\tp_clone->m_mesh_array\t= m_num_mesh ? new NxNgc::sMesh*[m_num_mesh] : NULL;\r\n\tp_clone->m_num_mesh\t\t= m_num_mesh;\r\n//\tNxNgc::sMesh * p_mesh0 = NULL;\r\n\tfor( uint32 m = 0; m < p_clone->m_num_mesh; ++m )\r\n\t{\r\n//\t\tif ( mp_instance )\r\n//\t\t{\r\n//\t\t\t// Instances don't need display lists cloning...\r\n//\t\t\tp_clone->m_mesh_array[m] = m_mesh_array[m]->Clone( false );\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n\t\t\tp_clone->m_mesh_array[m] = m_mesh_array[m]->Clone( instance );\r\n//\t\t}\r\n\r\n//\t\tif ( m_mesh_array[m]->m_localMeshIndex == 0 )\r\n//\t\t{\r\n//\t\t\tp_mesh0 = p_clone->m_mesh_array[m];\r\n//\t\t}\r\n\t}\r\n//\tif ( p_mesh0 )\r\n//\t{\r\n//\t\tfor( uint32 m = 0; m < p_clone->m_num_mesh; ++m )\r\n//\t\t{\r\n//\t\t\tif ( p_clone->m_mesh_array[m]->m_localMeshIndex != 0 )\r\n//\t\t\t{\r\n//\t\t\t\tp_clone->m_mesh_array[m]->mp_posBuffer = p_mesh0->mp_posBuffer;\r\n//\t\t\t\tp_clone->m_mesh_array[m]->mp_normBuffer = p_mesh0->mp_normBuffer;\r\n//\t\t\t\tp_clone->m_mesh_array[m]->mp_colBuffer = p_mesh0->mp_colBuffer;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n\r\n\tif( instance == false )\r\n\t{\r\n\t\tp_clone->SetActive( true );\r\n\r\n\t\t// In this situation, we need to add the individual meshes to the scene.\r\n\t\t// Grab a temporary workspace buffer.\r\n\t\tNx::CNgcScene *p_Ngc_scene\t\t\t\t\t\t= static_cast<CNgcScene*>( p_dest_scene );\r\n\t\tNxNgc::sScene *p_scene\t\t\t\t\t\t\t\t= p_Ngc_scene->GetEngineScene();\r\n\t\tNxNgc::sMesh **p_temp_mesh_buffer\t\t\t\t= ( p_scene->m_num_meshes > 0 ) ? new NxNgc::sMesh*[p_scene->m_num_meshes] : NULL;\r\n\r\n\t\t// Set the scene pointer for the clone.\r\n\t\tp_clone->SetScene( p_Ngc_scene );\r\n\t\t\r\n\t\t// Copy meshes over into the temporary workspace buffer.\r\n\t\tfor( int i = 0; i < p_scene->m_num_meshes; ++i )\r\n\t\t{\r\n\t\t\tp_temp_mesh_buffer[i] = p_scene->mpp_mesh_list[i];\r\n\t\t}\r\n\r\n\t\t// Store how many meshes were present.\r\n\t\tint old_num_entries\t\t\t= p_scene->m_num_meshes;\r\n\t\t\r\n\t\t// Delete current mesh arrays.\r\n\t\tdelete [] p_scene->mpp_mesh_list;\r\n\r\n\t\t// Important to set these to NULL.\r\n\t\tp_scene->mpp_mesh_list\t\t\t= NULL;\r\n\t\t\r\n\t\t// Include new meshes in count.\r\n\t\tp_scene->CountMeshes( m_num_mesh, m_mesh_array );\r\n\r\n\t\t// Allocate new mesh arrays.\r\n\t\tp_scene->CreateMeshArrays();\r\n\r\n\t\t// Copy old mesh data back in.\r\n\t\tfor( int i = 0; i < old_num_entries; ++i )\r\n\t\t{\r\n\t\t\tp_scene->mpp_mesh_list[i] = p_temp_mesh_buffer[i];\r\n\t\t}\r\n\r\n\t\t// Remove temporary arrays.\r\n\t\tdelete [] p_temp_mesh_buffer;\r\n\t\t\r\n\t\t// Add new meshes.\r\n\t\tp_scene->AddMeshes( p_clone->m_num_mesh, p_clone->m_mesh_array );\r\n\r\n\t\t// Sort the meshes.\r\n\t\tp_scene->SortMeshes();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Create a new scene which will be attached via the instance.\r\n\t\tp_clone->m_bbox\t\t\t= m_bbox;\r\n\t\tNxNgc::sScene *p_scene = p_clone->GenerateScene();\r\n\r\n\t\tp_clone->SetActive( true );\r\n\t\r\n\t\t// Create the instance.\r\n\t\tMth::Matrix temp;\r\n\t\ttemp.Identity();\r\n\t\tNxNgc::CInstance *p_instance = new NxNgc::CInstance( p_scene, temp, 1, NULL );\r\n\t\t\r\n\t\t// This instance will be the only object maintaining a reference to the attached scene, so we want to delete\r\n\t\t// the scene when the instance gets removed.\r\n\t\tp_instance->SetFlag( NxNgc::CInstance::INSTANCE_FLAG_DELETE_ATTACHED_SCENE );\r\n\r\n\t\t// Hook the clone up to the instance.\t\t\r\n\t\tp_clone->SetInstance( p_instance );\r\n\r\n\t\tp_clone->mp_scene = NULL;\r\n\t}\r\n\r\n\treturn p_clone;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_set_model_lights( CModelLights* p_model_lights )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcGeom *CNgcGeom::plat_clone( bool instance, CModel* pDestModel )\r\n{\r\n\tCNgcGeom *p_clone = NULL;\r\n\r\n\t// This is a CNgcGeom 'hanging' from a sector. Create a new CNgcGeom which will store the CInstance.\r\n\tNx::CNgcScene *p_Ngc_scene = new CNgcScene;\r\n\tp_Ngc_scene->SetEngineScene( mp_instance->GetScene() );\r\n\r\n\tp_clone = new CNgcGeom();\r\n\tp_clone->mp_scene = p_Ngc_scene;\r\n\r\n\tint num_mesh = mp_instance->GetScene()->m_num_filled_meshes;\r\n\r\n\t// Create new meshes for the clone.\r\n\tp_clone->m_mesh_array\t= num_mesh ? new NxNgc::sMesh*[num_mesh] : NULL;\r\n\tp_clone->m_num_mesh\t\t= num_mesh;\r\n\tfor( uint32 m = 0; m < p_clone->m_num_mesh; ++m )\r\n\t{\r\n\t\tp_clone->m_mesh_array[m] = mp_instance->GetScene()->mpp_mesh_list[m]->Clone( instance );\r\n\t}\r\n\t// Create a new scene which will be attached via the instance.\r\n\tp_clone->m_bbox\t\t\t= m_bbox;\r\n\tNxNgc::sScene *p_scene = p_clone->GenerateScene();\r\n\r\n\t// Kill the temp scene.\r\n\tp_Ngc_scene->SetEngineScene( NULL );\r\n\tdelete p_Ngc_scene;\r\n\tp_clone->mp_scene = NULL;\r\n\r\n\tp_clone->SetActive( true );\r\n\r\n\tint numBones;\r\n\tnumBones = pDestModel->GetNumBones();\r\n\r\n\tMth::Matrix * p_bone = new Mth::Matrix[numBones];\r\n\r\n\tfor ( int i = 0; i < numBones; i++ )\r\n\t{\r\n\t\tp_bone[i].Identity();\r\n\t}\r\n\r\n//\t((CNgcModel*)pDestModel)->GetInstance()->SetBoneTransforms( p_bone );\r\n\r\n\t// Create the instance.\r\n\tMth::Matrix temp;\r\n\ttemp.Identity();\r\n\tNxNgc::CInstance *p_instance = new NxNgc::CInstance( p_scene, temp, numBones, p_bone );\r\n\t\r\n\t((CNgcModel*)pDestModel)->SetInstance( p_instance );\r\n\r\n\t// This instance will be the only object maintaining a reference to the attached scene, so we want to delete\r\n\t// the scene when the instance gets removed.\r\n\tp_instance->SetFlag( NxNgc::CInstance::INSTANCE_FLAG_DELETE_ATTACHED_SCENE );\r\n\r\n\t// Hook the clone up to the instance.\t\t\r\n\tp_clone->SetInstance( p_instance );\r\n\r\n\treturn p_clone;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcGeom::plat_set_orientation(const Mth::Matrix& orient)\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\t// Set values\r\n\t\tmp_instance->GetTransform()->GetRight() = orient[X];\r\n\t\tmp_instance->GetTransform()->GetUp() = orient[Y];\r\n\t\tmp_instance->GetTransform()->GetAt() = orient[Z];\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcGeom::plat_rotate_y(Mth::ERot90 rot)\r\n{\r\n\tif( rot != Mth::ROT_0 )\r\n\t{\r\n\t\tif( mp_instance )\r\n\t\t{\r\n\t\t\tMth::Matrix *p_matrix = mp_instance->GetTransform();\r\n\r\n\t\t\t// Zero out translation component.\r\n\t\t\tMth::Matrix\tinstance_transform = *p_matrix;\r\n\t\t\tinstance_transform[W] = Mth::Vector(0.0f, 0.0f, 0.0f, 1.0f);\r\n\r\n\t\t\t// Build rotation matrix.\r\n\t\t\tMth::Matrix\trot_mat;\r\n\t\t\tfloat\t\trad = (float)((int)rot) * ( Mth::PI * 0.5f );\r\n\t\t\tMth::CreateRotateYMatrix( rot_mat, rad );\r\n\r\n\t\t\t// Rotate matrix.\r\n\t\t\trot_mat\t= instance_transform * rot_mat;\r\n\r\n\t\t\t// Replace translation component.\r\n\t\t\trot_mat[W] = p_matrix->GetPos();\r\n\r\n\t\t\tmp_instance->SetTransform( rot_mat );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t*((Mth::ERot90*)&m_mod.offset[W]) = rot;\r\n\r\n\t\t\tint num = plat_get_num_render_verts();\r\n\t\t\tMth::Vector * p_verts = new Mth::Vector[num];\r\n\t\t\tplat_get_render_verts( p_verts );\r\n\t\t\tfor ( int lp = 0; lp < num; lp++ )\r\n\t\t\t{\r\n\t\t\t\tfloat x;\r\n\t\t\t\tfloat z;\r\n\t\t\t\tswitch ( rot )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase Mth::ROT_90:\r\n\t\t\t\t\t\tx = p_verts[lp][X] - m_mod.offset[X];\r\n\t\t\t\t\t\tz = p_verts[lp][Z] - m_mod.offset[Z];\r\n\t\t\t\t\t\tp_verts[lp][X] =  z + m_mod.offset[X];\r\n\t\t\t\t\t\tp_verts[lp][Z] = -x + m_mod.offset[Z];\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase Mth::ROT_180:\r\n\t\t\t\t\t\tx = p_verts[lp][X] - m_mod.offset[X];\r\n\t\t\t\t\t\tz = p_verts[lp][Z] - m_mod.offset[Z];\r\n\t\t\t\t\t\tp_verts[lp][X] = -x + m_mod.offset[X];\r\n\t\t\t\t\t\tp_verts[lp][Z] = -z + m_mod.offset[Z];\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase Mth::ROT_270:\r\n\t\t\t\t\t\tx = p_verts[lp][X] - m_mod.offset[X];\r\n\t\t\t\t\t\tz = p_verts[lp][Z] - m_mod.offset[Z];\r\n\t\t\t\t\t\tp_verts[lp][X] = -z + m_mod.offset[X];\r\n\t\t\t\t\t\tp_verts[lp][Z] = x + m_mod.offset[Z];\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\tcase Mth::ROT_0:\r\n\t\t\t\t\t\t// Do nothing.\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tplat_set_render_verts( p_verts );\r\n\t\t\tdelete p_verts;\r\n\t\t}\r\n\t}\r\n\t*((Mth::ERot90*)&m_mod.offset[W]) = rot;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcGeom::plat_set_transform(const Mth::Matrix& transform)\r\n{\r\n\t// Set values\r\n\t*mp_instance->GetTransform() = transform;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Matrix &\tCNgcGeom::plat_get_transform() const\r\n{\r\n\treturn *mp_instance->GetTransform();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CNgcGeom::build_index_map( int * p_pos_index, int * p_col_index )\r\n{\r\n\tint num_used = 0;\r\n\t// Need to go through every index and find unique pos/color pairs.\r\n\tif ( mp_scene->GetEngineScene()->mp_scene_data )\r\n\t{\r\n\t\tfor ( uint mesh = 0; mesh < m_num_mesh; mesh++ )\r\n\t\t{\r\n\t\t\tNxNgc::sMesh * p_mesh = m_mesh_array[mesh];\r\n\r\n\t\t\t// Parse display list looking for this pos index, then get the color index.\r\n\t\t\tunsigned char * p_start = (unsigned char *)&p_mesh->mp_dl[1];\r\n\t\t\tunsigned char * p_end = &p_start[p_mesh->mp_dl->m_size];\r\n\t\t\tp_start = &p_start[p_mesh->mp_dl->m_index_offset];\t\t// Skip to actual 1st GDBegin.\r\n\t\t\tunsigned char * p8 = p_start;\r\n\r\n\t\t\tint stride = p_mesh->mp_dl->m_index_stride * 2;\r\n\t\t\tint offset = p_mesh->mp_dl->m_color_offset * 2;\r\n\r\n\t\t\twhile ( p8 < p_end )\r\n\t\t\t{\r\n\t\t\t\tif ( ( p8[0] & 0xf8 ) == GX_TRIANGLESTRIP )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Found a triangle strip - parse it.\r\n\t\t\t\t\tint num_idx = ( p8[1] << 8 ) | p8[2];\r\n\t\t\t\t\tp8 += 3;\t\t// Skip GDBegin\r\n\r\n\t\t\t\t\tfor ( int v = 0; v < num_idx; v++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint index = ( ( p8[0] << 8 ) | p8[1] ) + p_mesh->mp_dl->m_array_base;\r\n\t\t\t\t\t\tint cindex = ( p8[offset+0] << 8 ) | p8[offset+1];\r\n\r\n\t\t\t\t\t\t// See if this is a unique pair.\r\n\t\t\t\t\t\tbool found = false;\r\n\t\t\t\t\t\tfor ( int lp = 0; lp < num_used; lp++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( ( p_pos_index[lp] == index ) && ( p_col_index[lp] == cindex ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tfound = true;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( !found )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_pos_index[num_used] = index;\r\n\t\t\t\t\t\t\tp_col_index[num_used] = cindex;\r\n\t\t\t\t\t\t\tnum_used++;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tp8 += stride;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn num_used;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#define MAX_INDEX 2500\r\n\r\nint CNgcGeom::plat_get_num_render_verts( void )\r\n{\r\n\tif ( mp_scene->GetEngineScene()->mp_scene_data )\r\n\t{\r\n\t\tNxNgc::sMesh * p_mesh = m_mesh_array[0];\r\n\r\n\t\tif ( p_mesh->m_flags & NxNgc::sMesh::MESH_FLAG_INDEX_COUNT_SET )\r\n\t\t{\r\n\t\t\treturn p_mesh->mp_dl->m_num_indices;\r\n\t\t}\r\n\t}\r\n\r\n\tint pos_index[MAX_INDEX];\r\n\tint col_index[MAX_INDEX];\r\n\r\n\tint num_verts = build_index_map( pos_index, col_index );\r\n//\tPcm::PCMAudio_Update();\r\n\tdo_audio_update();\r\n\r\n\treturn num_verts;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcGeom::plat_get_render_verts( Mth::Vector *p_verts )\r\n{\r\n\t// See if pool has been copied already.\r\n\tif ( mp_scene->GetEngineScene()->mp_scene_data )\r\n\t{\r\n\t\tNxNgc::sMesh * p_mesh = m_mesh_array[0];\r\n\r\n\t\tif ( p_mesh->m_flags & NxNgc::sMesh::MESH_FLAG_CLONED_POS )\r\n\t\t{\r\n\t\t\tfor ( int lp = 0; lp < p_mesh->mp_dl->m_num_indices; lp++ )\r\n\t\t\t{\r\n\t\t\t\tp_verts[lp][X] = p_mesh->mp_dl->mp_pos_pool[(lp*3)+0];\r\n\t\t\t\tp_verts[lp][Y] = p_mesh->mp_dl->mp_pos_pool[(lp*3)+1];\r\n\t\t\t\tp_verts[lp][Z] = p_mesh->mp_dl->mp_pos_pool[(lp*3)+2];\r\n\t\t\t\tp_verts[lp][W] = 1.0f;\r\n\t\t\t}\r\n//\t\t\tPcm::PCMAudio_Update();\r\n\t\t\tdo_audio_update();\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tint pos_index[MAX_INDEX];\r\n\tint col_index[MAX_INDEX];\r\n\r\n\tint num_verts = build_index_map( pos_index, col_index );\r\n//\tPcm::PCMAudio_Update();\r\n\tdo_audio_update();\r\n\r\n\t// Copy from original pool.\r\n\tfor ( int lp = 0; lp < num_verts; lp++ )\r\n\t{\r\n\t\tp_verts[lp][X] = mp_scene->GetEngineScene()->mp_pos_pool[(pos_index[lp]*3)+0];\r\n\t\tp_verts[lp][Y] = mp_scene->GetEngineScene()->mp_pos_pool[(pos_index[lp]*3)+1];\r\n\t\tp_verts[lp][Z] = mp_scene->GetEngineScene()->mp_pos_pool[(pos_index[lp]*3)+2];\r\n\t\tp_verts[lp][W] = 1.0f;\r\n\r\n\t}\r\n//\tPcm::PCMAudio_Update();\r\n\tdo_audio_update();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_get_render_colors( Image::RGBA *p_colors )\r\n{\r\n\t// See if pool has been copied already.\r\n\tif ( mp_scene->GetEngineScene()->mp_scene_data )\r\n\t{\r\n\t\tNxNgc::sMesh * p_mesh = m_mesh_array[0];\r\n\r\n\t\tif ( p_mesh->m_flags & NxNgc::sMesh::MESH_FLAG_CLONED_COL )\r\n\t\t{\r\n\t\t\tfor ( int lp = 0; lp < p_mesh->mp_dl->m_num_indices; lp++ )\r\n\t\t\t{\r\n\t\t\t\tp_colors[lp].r = ( p_mesh->mp_dl->mp_col_pool[lp] >> 24 ) & 0xff;\r\n\t\t\t\tp_colors[lp].g = ( p_mesh->mp_dl->mp_col_pool[lp] >> 16 ) & 0xff;\r\n\t\t\t\tp_colors[lp].b = ( p_mesh->mp_dl->mp_col_pool[lp] >>  8 ) & 0xff;\r\n\t\t\t\tp_colors[lp].a = ( p_mesh->mp_dl->mp_col_pool[lp] >>  0 ) & 0xff;\r\n\t\t\t}\r\n//\t\t\tPcm::PCMAudio_Update();\r\n\t\t\tdo_audio_update();\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tint pos_index[MAX_INDEX];\r\n\tint col_index[MAX_INDEX];\r\n\r\n\tint num_verts = build_index_map( pos_index, col_index );\r\n//\tPcm::PCMAudio_Update();\r\n\tdo_audio_update();\r\n\r\n\t// Copy from original pool.\r\n\tfor ( int lp = 0; lp < num_verts; lp++ )\r\n\t{\r\n\t\tp_colors[lp].r = ( mp_scene->GetEngineScene()->mp_col_pool[col_index[lp]] >> 24 ) & 0xff;\r\n\t\tp_colors[lp].g = ( mp_scene->GetEngineScene()->mp_col_pool[col_index[lp]] >> 16 ) & 0xff;\r\n\t\tp_colors[lp].b = ( mp_scene->GetEngineScene()->mp_col_pool[col_index[lp]] >>  8 ) & 0xff;\r\n\t\tp_colors[lp].a = ( mp_scene->GetEngineScene()->mp_col_pool[col_index[lp]] >>  0 ) & 0xff;\r\n\t}\r\n//\tPcm::PCMAudio_Update();\r\n\tdo_audio_update();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_set_render_verts( Mth::Vector *p_verts )\r\n{\r\n\t// See if we need to create a new pool.\r\n\tbool need_to_create = false;\r\n\tif ( mp_scene->GetEngineScene()->mp_scene_data )\r\n\t{\r\n\t\tNxNgc::sMesh * p_mesh = m_mesh_array[0];\r\n\t\tif ( ( p_mesh->m_flags & NxNgc::sMesh::MESH_FLAG_CLONED_POS ) == 0 )\r\n\t\t{\r\n\t\t\tneed_to_create = true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Create new pos pool if necessary.\r\n\tfloat * p_new_pos;\r\n\tint num_verts;\r\n\tif ( need_to_create && mp_scene->GetEngineScene()->mp_scene_data )\r\n\t{\r\n\t\tint pos_index[MAX_INDEX];\r\n\t\tint col_index[MAX_INDEX];\r\n\r\n\t\tnum_verts = build_index_map( pos_index, col_index );\r\n//\t\tPcm::PCMAudio_Update();\r\n\t\tdo_audio_update();\r\n\r\n\t\t// Allocate space for new pool.\r\n\t\tp_new_pos = new float[3*num_verts];\r\n\r\n\t\tfor ( uint mesh = 0; mesh < m_num_mesh; mesh++ )\r\n\t\t{\r\n\t\t\tNxNgc::sMesh * p_mesh = m_mesh_array[mesh];\r\n\r\n\t\t\tif ( !p_mesh->mp_dl->mp_pos_pool )\r\n\t\t\t{\r\n\t\t\t\tp_mesh->mp_dl->mp_pos_pool = p_new_pos;\r\n\r\n\t\t\t\tif ( mesh == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_CLONED_POS;\r\n\t\t\t\t\tp_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_INDEX_COUNT_SET;\r\n\t\t\t\t\tp_mesh->mp_dl->m_num_indices = num_verts;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Remap the DL.\r\n\t\t\t\t// Parse display list looking for this pos index, then get the color index.\r\n\t\t\t\tunsigned char * p_start = (unsigned char *)&p_mesh->mp_dl[1];\r\n\t\t\t\tunsigned char * p_end = &p_start[p_mesh->mp_dl->m_size];\r\n\t\t\t\tp_start = &p_start[p_mesh->mp_dl->m_index_offset];\t\t// Skip to actual 1st GDBegin.\r\n\t\t\t\tunsigned char * p8 = p_start;\r\n\r\n\t\t\t\tint stride = p_mesh->mp_dl->m_index_stride * 2;\r\n\t\t\t\tint offset = p_mesh->mp_dl->m_color_offset * 2;\r\n\r\n\t\t\t\twhile ( p8 < p_end )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( ( p8[0] & 0xf8 ) == GX_TRIANGLESTRIP )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Found a triangle strip - parse it.\r\n\t\t\t\t\t\tint num_idx = ( p8[1] << 8 ) | p8[2];\r\n\t\t\t\t\t\tp8 += 3;\t\t// Skip GDBegin\r\n\r\n\t\t\t\t\t\tfor ( int v = 0; v < num_idx; v++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Find the remapped index.\r\n\t\t\t\t\t\t\tint index = ( ( p8[0] << 8 ) | p8[1] ) + p_mesh->mp_dl->m_array_base;\r\n\t\t\t\t\t\t\tint cindex = ( p8[offset+0] << 8 ) | p8[offset+1];\r\n\r\n\t\t\t\t\t\t\tfor ( int lp = 0; lp < num_verts; lp++ )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif ( ( pos_index[lp] == index ) && ( col_index[lp] == cindex ) )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tp8[0] = ( lp >> 8 ) & 0xff;\r\n\t\t\t\t\t\t\t\t\tp8[1] = lp & 0xff;\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tp8 += stride;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tDCFlushRange( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );\r\n\t\t\t}\r\n\t\t\tp_mesh->mp_dl->m_array_base = 0;\r\n\r\n//\t\t\tPcm::PCMAudio_Update();\r\n\t\t\tdo_audio_update();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_new_pos = m_mesh_array[0]->mp_dl->mp_pos_pool;\r\n\t\tnum_verts = m_mesh_array[0]->mp_dl->m_num_indices;\r\n\t}\r\n\r\n\t// Copy actual data over.\r\n\tMth::CBBox bbox;\r\n\tfor ( int v = 0; v < num_verts; v++ )\r\n\t{\r\n\t\tp_new_pos[(v*3)+0] = p_verts[v][X];\r\n\t\tp_new_pos[(v*3)+1] = p_verts[v][Y];\r\n\t\tp_new_pos[(v*3)+2] = p_verts[v][Z];\r\n\t\tbbox.AddPoint( p_verts[v] );\r\n\t}\r\n\tDCFlushRange( p_new_pos, sizeof( float ) * 3 * num_verts );\r\n\r\n\tif ( mp_scene->GetEngineScene()->mp_scene_data )\r\n\t{\r\n\t\tfor ( uint mesh = 0; mesh < m_num_mesh; mesh++ )\r\n\t\t{\r\n\t\t\tNxNgc::sMesh * p_mesh = m_mesh_array[mesh];\r\n\r\n\t\t\t// Now refigure the bounding sphere.\r\n\t\t\tMth::Vector sphere_center\t= bbox.GetMin() + ( 0.5f * ( bbox.GetMax() - bbox.GetMin()));\r\n\t\t\tp_mesh->mp_dl->m_sphere[X] = sphere_center[X];\r\n\t\t\tp_mesh->mp_dl->m_sphere[Y] = sphere_center[Y];\r\n\t\t\tp_mesh->mp_dl->m_sphere[Z] = sphere_center[Z];\r\n\t\t\tp_mesh->mp_dl->m_sphere[W] = ( bbox.GetMax() - sphere_center ).Length(); \r\n\r\n\t\t\tp_mesh->m_bottom_y = bbox.GetMin()[Y];\r\n\t\t}\r\n\t}\r\n//\tPcm::PCMAudio_Update();\r\n\tdo_audio_update();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_set_render_colors( Image::RGBA *p_colors )\r\n{\r\n\t// See if we need to create a new pool.\r\n\tbool need_to_create = false;\r\n\tif ( mp_scene->GetEngineScene()->mp_scene_data )\r\n\t{\r\n\t\tNxNgc::sMesh * p_mesh = m_mesh_array[0];\r\n\t\tif ( !( p_mesh->m_flags & NxNgc::sMesh::MESH_FLAG_CLONED_COL ) )\r\n\t\t{\r\n\t\t\tneed_to_create = true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Create new col pool if necessary.\r\n\tuint32 * p_new_col;\r\n\tint num_verts;\r\n\tif ( need_to_create && mp_scene->GetEngineScene()->mp_scene_data )\r\n\t{\r\n\t\tint pos_index[MAX_INDEX];\r\n\t\tint col_index[MAX_INDEX];\r\n\r\n\t\tnum_verts = build_index_map( pos_index, col_index );\r\n//\t\tPcm::PCMAudio_Update();\r\n\t\tdo_audio_update();\r\n\r\n\t\t// Allocate space for new pool.\r\n\t\tp_new_col = new uint32[num_verts];\r\n\r\n\t\tfor ( uint mesh = 0; mesh < m_num_mesh; mesh++ )\r\n\t\t{\r\n\t\t\tNxNgc::sMesh * p_mesh = m_mesh_array[mesh];\r\n\r\n\t\t\tif ( !p_mesh->mp_dl->mp_col_pool )\r\n\t\t\t{\r\n\t\t\t\tp_mesh->mp_dl->mp_col_pool = p_new_col;\r\n\r\n\t\t\t\tif ( mesh == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_CLONED_COL;\r\n\t\t\t\t\tp_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_INDEX_COUNT_SET;\r\n\t\t\t\t\tp_mesh->mp_dl->m_num_indices = num_verts;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Remap the DL.\r\n\t\t\t\t// Parse display list looking for this pos index, then get the color index.\r\n\t\t\t\tunsigned char * p_start = (unsigned char *)&p_mesh->mp_dl[1];\r\n\t\t\t\tunsigned char * p_end = &p_start[p_mesh->mp_dl->m_size];\r\n\t\t\t\tp_start = &p_start[p_mesh->mp_dl->m_index_offset];\t\t// Skip to actual 1st GDBegin.\r\n\t\t\t\tunsigned char * p8 = p_start;\r\n\r\n\t\t\t\tint stride = p_mesh->mp_dl->m_index_stride * 2;\r\n\t\t\t\tint offset = p_mesh->mp_dl->m_color_offset * 2;\r\n\r\n\t\t\t\twhile ( p8 < p_end )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( ( p8[0] & 0xf8 ) == GX_TRIANGLESTRIP )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Found a triangle strip - parse it.\r\n\t\t\t\t\t\tint num_idx = ( p8[1] << 8 ) | p8[2];\r\n\t\t\t\t\t\tp8 += 3;\t\t// Skip GDBegin\r\n\r\n\t\t\t\t\t\tfor ( int v = 0; v < num_idx; v++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Find the remapped index.\r\n\t\t\t\t\t\t\tint index = ( ( p8[0] << 8 ) | p8[1] ) + p_mesh->mp_dl->m_array_base;\r\n\t\t\t\t\t\t\tint cindex = ( p8[offset+0] << 8 ) | p8[offset+1];\r\n\r\n\t\t\t\t\t\t\tfor ( int lp = 0; lp < num_verts; lp++ )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif ( ( pos_index[lp] == index ) && ( col_index[lp] == cindex ) )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tp8[offset+0] = ( lp >> 8 ) & 0xff;\r\n\t\t\t\t\t\t\t\t\tp8[offset+1] = lp & 0xff;\r\n\t\t\t\t\t\t\t\t\tif ( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<6)/*m_correctable*/ )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\tp8[offset+2] = ( lp >> 8 ) & 0xff;\r\n\t\t\t\t\t\t\t\t\t\tp8[offset+3] = lp & 0xff;\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tp8 += stride;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tDCFlushRange( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );\r\n\t\t\t}\r\n//\t\t\tp_mesh->mp_dl->m_array_base = 0;\r\n\r\n//\t\t\tPcm::PCMAudio_Update();\r\n\t\t\tdo_audio_update();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_new_col = m_mesh_array[0]->mp_dl->mp_col_pool;\r\n\t\tnum_verts = m_mesh_array[0]->mp_dl->m_num_indices;\r\n\t}\r\n\r\n\t// Copy actual data over.\r\n\tfor ( int v = 0; v < num_verts; v++ )\r\n\t{\r\n\t\tp_new_col[v] = ( p_colors[v].r << 24 ) | ( p_colors[v].g << 16 ) | ( p_colors[v].b << 8 ) | p_colors[v].a;\r\n\t}\r\n\tDCFlushRange( p_new_col, sizeof( uint32 ) * num_verts );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_set_scale(const Mth::Vector & scale)\r\n{\r\n\t// Ensure w component is correct.\r\n\r\n\tif( mp_instance )\r\n\t{\r\n//\t\tmp_instance->GetTransform()->SetScale( scale );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint num = plat_get_num_render_verts();\r\n\t\tMth::Vector * p_verts = new Mth::Vector[num];\r\n\t\tplat_get_render_verts( p_verts );\r\n\t\tfor ( int lp = 0; lp < num; lp++ )\r\n\t\t{\r\n\t\t\tp_verts[lp][X] = ( ( p_verts[lp][X] - m_mod.offset[X] ) * scale[X] ) + m_mod.offset[X];\r\n\t\t\tp_verts[lp][Y] = ( ( p_verts[lp][Y] - m_mod.offset[Y] ) * scale[Y] ) + m_mod.offset[Y];\r\n\t\t\tp_verts[lp][Z] = ( ( p_verts[lp][Z] - m_mod.offset[Z] ) * scale[Z] ) + m_mod.offset[Z];\r\n\t\t}\r\n\t\tplat_set_render_verts( p_verts );\r\n\t\tdelete p_verts;\r\n\r\n//\t\t// Go through and adjust the individual meshes.\r\n//\t\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n//\t\t{\r\n//\t\t\tNxNgc::sMesh *p_mesh = m_mesh_array[i];\r\n//\t\t\tp_mesh->mp_mod = &m_mod;\r\n//\r\n////\t\t\tMth::Vector delta_pos( pos[X] - m_offset[X], pos[Y] - m_offset[Y], pos[Z] - m_offset[Z], 1.0f );\r\n////\t\t\tp_mesh->mp_dl->m_sphere[X] += delta_pos[X];\r\n////\t\t\tp_mesh->mp_dl->m_sphere[Y] += delta_pos[Y];\r\n////\t\t\tp_mesh->mp_dl->m_sphere[Z] += delta_pos[Z];\r\n////\t\t\tp_mesh->SetPosition( proper_pos );\r\n//\t\t}\r\n//\r\n////\t\tif ( mp_scene->GetEngineScene()->mp_scene_data )\r\n////\t\t{\r\n////\t\t\tMth::Vector proper_pos( pos[X] - m_offset[X], pos[Y] - m_offset[Y], pos[Z] - m_offset[Z], 1.0f );\r\n////\t\r\n////\t\t\tfloat * pos = mp_scene->GetEngineScene()->mp_pos_pool;\r\n////\t\t\tfor ( int lp = 0; lp += mp_scene->GetEngineScene()->mp_scene_data->m_num_pos; lp++ )\r\n////\t\t\t{\r\n////\t\t\t\tpos[0] += proper_pos[X];\r\n////\t\t\t\tpos[1] += proper_pos[Y];\r\n////\t\t\t\tpos[2] += proper_pos[Z];\r\n////\t\t\t\tpos += 3;\r\n////\t\t\t}\r\n////\t\t\tm_offset[X] = proper_pos[X];\r\n////\t\t\tm_offset[Y] = proper_pos[Y];\r\n////\t\t\tm_offset[Z] = proper_pos[Z];\r\n////\t\t}\r\n\t}\r\n\tm_mod.scale = scale;\r\n\r\n\r\n\r\n//\tDbg_MsgAssert( m_mesh_array, ( \"Invalid for instanced sectors\" ));\r\n//\r\n//\tm_scale = scale;\r\n//\r\n//\tif( m_mesh_array )\r\n//\t{\r\n//\t\tNxNgc::sMesh *p_mesh = m_mesh_array[0];\r\n//\r\n//\t\t// Scale each vertex.\r\n//#ifdef SHORT_VERT\r\n//\t\tfor( uint32 v = 0; v < p_mesh->m_num_vertex; ++v )\r\n//\t\t{\r\n//\t\t\tp_mesh->mp_posBuffer[(v*3)+0] = (s16)( (float)p_mesh->mp_posBuffer[(v*3)+0] * scale[X] );\r\n//\t\t\tp_mesh->mp_posBuffer[(v*3)+1] = (s16)( (float)p_mesh->mp_posBuffer[(v*3)+1] * scale[Y] );\r\n//\t\t\tp_mesh->mp_posBuffer[(v*3)+2] = (s16)( (float)p_mesh->mp_posBuffer[(v*3)+2] * scale[Z] );\r\n//\t\t}\r\n//\t\tDCFlushRange( p_mesh->mp_posBuffer, 3 * sizeof( s16 ) * p_mesh->m_num_vertex );\r\n//#else\r\n//\t\tfor( uint32 v = 0; v < p_mesh->m_num_vertex; ++v )\r\n//\t\t{\r\n//\t\t\tp_mesh->mp_posBuffer[(v*3)+0] = ( ( p_mesh->mp_posBuffer[(v*3)+0] - p_mesh->m_offset_x ) * scale[X] ) + p_mesh->m_offset_x;\r\n//\t\t\tp_mesh->mp_posBuffer[(v*3)+1] = ( ( p_mesh->mp_posBuffer[(v*3)+1] - p_mesh->m_offset_y ) * scale[Y] ) + p_mesh->m_offset_y;\r\n//\t\t\tp_mesh->mp_posBuffer[(v*3)+2] = ( ( p_mesh->mp_posBuffer[(v*3)+2] - p_mesh->m_offset_z ) * scale[Z] ) + p_mesh->m_offset_z;\r\n//\t\t}\r\n//\t\tDCFlushRange( p_mesh->mp_posBuffer, 3 * sizeof( float ) * p_mesh->m_num_vertex );\r\n//#endif\t\t// SHORT_VERT \r\n//\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nMth::Vector CNgcGeom::plat_get_scale() const\r\n{\r\n\treturn m_mod.scale;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_set_uv_wibble_params( float u_vel, float u_amp, float u_freq, float u_phase,\r\n\t\t\t\t\t\t\t\t\t\t   float v_vel, float v_amp, float v_freq, float v_phase )\r\n{\r\n//\tif( m_mesh_array )\r\n//\t{\r\n//\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n//\t\t{\r\n//\t\t\tNxNgc::sMesh\t\t*p_mesh\t= m_mesh_array[m];\r\n//\t\t\tNxNgc::sMaterial\t*p_mat\t= p_mesh->mp_material;\r\n//\t\t\tif( p_mat )\r\n//\t\t\t{\r\n//\t\t\t\t// Find the first pass that wibbles.\r\n//\t\t\t\tfor( uint32 p = 0; p < p_mat->m_passes; ++p )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( p_mat->mp_UVWibbleParams[p] )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UVel\t\t\t= u_vel;\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_VVel\t\t\t= v_vel;\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UAmplitude\t= u_amp;\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_VAmplitude\t= v_amp;\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UFrequency\t= u_freq;\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_VFrequency\t= v_freq;\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UPhase\t\t= u_phase;\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_VPhase\t\t= v_phase;\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_use_explicit_uv_wibble( bool yes )\r\n{\r\n//\tif( mp_instance && mp_instance->GetScene())\r\n//\t{\r\n//\t\tfor( int m = 0; m < mp_instance->GetScene()->m_num_mesh_entries; ++m )\r\n//\t\t{\r\n//\t\t\tNxNgc::sMesh\t\t*p_mesh\t= mp_instance->GetScene()->m_meshes[m];\r\n//\t\t\tNxNgc::sMaterial\t*p_mat\t= p_mesh->mp_material;\r\n//\t\t\tif( p_mat )\r\n//\t\t\t{\r\n//\t\t\t\tfor( uint32 p = 0; p < p_mat->m_passes; ++p )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( p_mat->mp_UVWibbleParams[p] )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tp_mat->m_flags[p] |= MATFLAG_EXPLICIT_UV_WIBBLE;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcGeom::plat_set_uv_wibble_offsets( float u_offset, float v_offset )\r\n{\r\n//\tif( m_mesh_array )\r\n//\t{\r\n//\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n//\t\t{\r\n//\t\t\tNxNgc::sMesh\t\t*p_mesh\t= m_mesh_array[m];\r\n//\t\t\tNxNgc::sMaterial\t*p_mat\t= p_mesh->mp_material;\r\n//\t\t\tif( p_mat )\r\n//\t\t\t{\r\n//\t\t\t\t// Find the first pass that wibbles.\r\n//\t\t\t\tfor( uint32 p = 0; p < p_mat->m_passes; ++p )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( p_mat->mp_UVWibbleParams[p] )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UVMatrix[2] = u_offset;\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UVMatrix[3] = v_offset;\r\n//\t\t\t\t\t\tplat_use_explicit_uv_wibble( true );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcGeom::plat_set_uv_wibble_offsets( uint32 mat_name_checksum, int pass, float u_offset, float v_offset )\r\n{\r\n//\tif( m_mesh_array )\r\n//\t{\r\n//\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n//\t\t{\r\n//\t\t\tNxNgc::sMesh\t\t*p_mesh\t= m_mesh_array[m];\r\n//\t\t\tNxNgc::sMaterial\t*p_mat\t= p_mesh->mp_material;\r\n//\t\t\tif( p_mat && ( p_mat->m_name_checksum == mat_name_checksum ))\r\n//\t\t\t{\r\n//\t\t\t\t// Find the first pass that wibbles.\r\n////\t\t\t\tfor( uint32 p = 0; p < p_mat->m_passes; ++p )\r\n////\t\t\t\t{\r\n////\t\t\t\t\tif( p_mat->mp_UVWibbleParams[p] )\r\n////\t\t\t\t\t{\r\n////\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UWibbleOffset = u_offset;\r\n////\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_VWibbleOffset = v_offset;\r\n////\t\t\t\t\t\tplat_use_explicit_uv_wibble( true );\r\n////\t\t\t\t\t\tbreak;\r\n////\t\t\t\t\t}\r\n////\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcGeom::plat_set_uv_matrix( uint32 mat_name_checksum, int pass, const Mth::Matrix& mat )\r\n{\r\n\tif( mp_instance && mp_instance->GetScene())\r\n\t{\r\n\t\tfor( int m = 0; m < mp_instance->GetScene()->m_num_filled_meshes; ++m )\r\n\t\t{\r\n\t\t\tNxNgc::sMesh\t\t\t*p_mesh\t= mp_instance->GetScene()->mpp_mesh_list[m];\r\n\t\t\tNxNgc::sMaterialHeader\t*p_mat\t= p_mesh->mp_dl->m_material.p_header;\r\n\t\t\tif( p_mat )\r\n\t\t\t{\r\n\t\t\t\tbool\twant_this_material\t= false;\r\n\t\t\t\tint\t\tadjusted_pass\t\t= pass;\r\n\r\n\t\t\t\t// We are searching for materials with a matching name. However there is a caveat in that the\r\n\t\t\t\t// conversion process sometimes creates new materials for geometry flagged as 'render as separate', or for\r\n\t\t\t\t// geometry which is mapped with only certain passes of a multipass material (or both cases).\r\n\t\t\t\t// In such a case, the new material name checksum will differ from the original material name checksum,\r\n\t\t\t\t// with the following bits having significance (i.e. consider bitflags = new_namechecksum - old_namechecksum ):\r\n\t\t\t\t//\r\n\t\t\t\t// Bits 3->6\tPass flags indicating which passes of the original material this material uses\r\n\t\t\t\t// Bits 0->2\tAbsolute number ('render as separate' flagged geometry) indicating which single pass of the material this material represents.\r\n\t\t\t\tif( p_mat->m_materialNameChecksum == mat_name_checksum )\r\n\t\t\t\t{\r\n\t\t\t\t\twant_this_material = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if(( p_mat->m_materialNameChecksum > mat_name_checksum ) && (( p_mat->m_materialNameChecksum - mat_name_checksum ) <= 0x7F ))\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 checksum_diff\t\t= p_mat->m_materialNameChecksum - mat_name_checksum;\r\n\t\t\t\t\tint render_separate_pass\t= checksum_diff & 0x07;\r\n\t\t\t\t\tuint32 pass_flags\t\t\t= checksum_diff >> 3;\r\n\r\n\t\t\t\t\tif( render_separate_pass )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( render_separate_pass == ( pass + 1 ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\twant_this_material = true;\r\n\r\n\t\t\t\t\t\t\t// Readjust the pass to zero, since this material was formed as a single pass of a multipass material.\r\n\t\t\t\t\t\t\tadjusted_pass = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( pass_flags )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// This material was created during scene conversion from another material with more passes.\r\n\t\t\t\t\t\tif( pass_flags & ( 1 << pass ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\twant_this_material = true;\r\n\t\t\t\t\t\t\tfor( int p = 0; p < pass; ++p )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif(( pass_flags & ( 1 << p )) == 0 )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Readjust the pass down by 1, since this material was created as a subset of another material.\r\n\t\t\t\t\t\t\t\t\t--adjusted_pass;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( want_this_material )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( adjusted_pass < p_mat->m_passes )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Create the wibble params if they don't exist already.\r\n\t\t\t\t\t\tNxNgc::sMaterialPassHeader * p_pass = &mp_instance->GetScene()->mp_material_pass[p_mat->m_pass_item+adjusted_pass];\r\n\r\n\t\t\t\t\t\t// Force this to be used.\r\n\t\t\t\t\t\tp_pass->m_flags |= (1<<2);\r\n\t\t\t\t\t\tp_pass->m_uv_enabled = 1;\r\n\t\t\t\t\t\tp_mat->m_flags |= (1<<4);\r\n\t//\r\n\t//\r\n\t//\r\n\t////\t\t\t\t\t// Set the matrix values.\r\n\t//\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[0][0] = mat[0][0];\r\n\t//\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[0][1] = mat[0][1];\r\n\t//\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[1][0] = mat[1][0];\r\n\t//\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[1][1] = mat[1][1];\r\n\t//\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[2][0] = 1.0f;\r\n\t//\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[2][1] = 1.0f;\r\n\t//\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[0][3] = mat[3][0];\r\n\t//\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[1][3] = mat[3][1];\r\n\r\n\t\t\t\t\t\tp_pass->m_uv_mat[0] = (short)(mat[0][0] * ((float)(1<<12)));\r\n\t\t\t\t\t\tp_pass->m_uv_mat[1] = (short)(mat[0][1] * ((float)(1<<12)));\r\n\t\t\t\t\t\tp_pass->m_uv_mat[2] = (short)(mat[3][0] * ((float)(1<<12)));\r\n\t\t\t\t\t\tp_pass->m_uv_mat[3] = (short)(mat[3][1] * ((float)(1<<12)));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcGeom::plat_allocate_uv_matrix_params( uint32 mat_name_checksum, int pass )\r\n{\r\n\tif( mp_instance && mp_instance->GetScene())\r\n\t{\r\n\t\tfor( int m = 0; m < mp_instance->GetScene()->m_num_filled_meshes; ++m )\r\n\t\t{\r\n\t\t\tNxNgc::sMesh\t\t\t*p_mesh\t= mp_instance->GetScene()->mpp_mesh_list[m];\r\n\t\t\tNxNgc::sMaterialHeader\t*p_mat\t= p_mesh->mp_dl->m_material.p_header;\r\n\t\t\tif( p_mat )\r\n\t\t\t{\r\n\t\t\t\tbool\twant_this_material\t= false;\r\n\t\t\t\tint\t\tadjusted_pass\t\t= pass;\r\n\r\n\t\t\t\t// We are searching for materials with a matching name. However there is a caveat in that the\r\n\t\t\t\t// conversion process sometimes creates new materials for geometry flagged as 'render as separate', or for\r\n\t\t\t\t// geometry which is mapped with only certain passes of a multipass material (or both cases).\r\n\t\t\t\t// In such a case, the new material name checksum will differ from the original material name checksum,\r\n\t\t\t\t// with the following bits having significance (i.e. consider bitflags = new_namechecksum - old_namechecksum ):\r\n\t\t\t\t//\r\n\t\t\t\t// Bits 3->6\tPass flags indicating which passes of the original material this material uses\r\n\t\t\t\t// Bits 0->2\tAbsolute number ('render as separate' flagged geometry) indicating which single pass of the material this material represents.\r\n\t\t\t\tif( p_mat->m_materialNameChecksum == mat_name_checksum )\r\n\t\t\t\t\twant_this_material = true;\r\n\t\t\t\telse if(( p_mat->m_materialNameChecksum > mat_name_checksum ) && (( p_mat->m_materialNameChecksum - mat_name_checksum ) <= 0x7F ))\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 checksum_diff\t\t= p_mat->m_materialNameChecksum - mat_name_checksum;\r\n\t\t\t\t\tint render_separate_pass\t= checksum_diff & 0x07;\r\n\t\t\t\t\tuint32 pass_flags\t\t\t= checksum_diff >> 3;\r\n\r\n\t\t\t\t\tif( render_separate_pass )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( render_separate_pass == ( pass + 1 ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\twant_this_material = true;\r\n\r\n\t\t\t\t\t\t\t// Readjust the pass to zero, since this material was formed as a single pass of a multipass material.\r\n\t\t\t\t\t\t\tadjusted_pass = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( pass_flags )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// This material was created during scene conversion from another material with more passes.\r\n\t\t\t\t\t\tif( pass_flags & ( 1 << pass ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\twant_this_material = true;\r\n\t\t\t\t\t\t\tfor( int p = 0; p < pass; ++p )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif(( pass_flags & ( 1 << p )) == 0 )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Readjust the pass down by 1, since this material was created as a subset of another material.\r\n\t\t\t\t\t\t\t\t\t--adjusted_pass;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( want_this_material )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( adjusted_pass < p_mat->m_passes )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tNxNgc::sMaterialPassHeader * p_pass = &mp_instance->GetScene()->mp_material_pass[p_mat->m_pass_item+adjusted_pass];\r\n\t\r\n\t\t\t\t\t\tp_pass->m_flags |= (1<<2);\r\n\t\t\t\t\t\tp_pass->m_uv_enabled = 1;\r\n\t\t\t\t\t\tp_pass->m_uv_mat[0] = (1<<12);\r\n\t\t\t\t\t\tp_pass->m_uv_mat[1] = 0;\r\n\t\t\t\t\t\tp_pass->m_uv_mat[2] = 0;\r\n\t\t\t\t\t\tp_pass->m_uv_mat[3] = 0;\r\n\t\t\t\t\t}\r\n\r\n//\t\t\t\t\tif ( p_pass->mp_explicit_wibble == NULL )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tp_pass->mp_explicit_wibble = new NxNgc::sExplicitMaterialUVWibble;\r\n//\t\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[0][0] = 1.0f;\r\n//\t\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[0][1] = 0.0f;\r\n//\t\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[0][2] = 1.0f;\r\n//\t\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[0][3] = 0.0f;\r\n//\t\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[1][0] = 0.0f;\r\n//\t\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[1][1] = 1.0f;\r\n//\t\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[1][2] = 1.0f;\r\n//\t\t\t\t\t\tp_pass->mp_explicit_wibble->m_matrix[1][3] = 0.0f;\r\n//\t\t\t\t\t\tp_pass->m_flags |= (1<<2);\r\n//\t\t\t\t\t\treturn true;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\t// Create the wibble params if they don't exist already.\r\n//\t\t\t\t\tif( p_mat->mp_UVWibbleParams[pass] == NULL )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[pass]\t= new NxNgc::sUVWibbleParams;\r\n//\r\n//\t\t\t\t\t\t// Need to set flags to indicate that uv wibble is now in effect.\r\n//\t\t\t\t\t\tp_mat->m_uv_wibble\t\t\t\t= true;\r\n//\t\t\t\t\t\tp_mat->m_flags[pass]\t\t   |= MATFLAG_UV_WIBBLE | MATFLAG_EXPLICIT_UV_WIBBLE;\r\n//\t\t\t\t\t\treturn true;\r\n//\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#if 0\r\n\tif( mp_instance && mp_instance->GetScene())\r\n\t{\r\n\t\tfor( int m = 0; m < mp_instance->GetScene()->m_num_filled_meshes; ++m )\r\n\t\t{\r\n\t\t\tNxNgc::sMesh\t\t\t*p_mesh\t= mp_instance->GetScene()->mpp_mesh_list[m];\r\n\t\t\tNxNgc::sMaterialHeader\t*p_mat\t= p_mesh->mp_dl->m_material.p_header;\r\n\t\t\tif( p_mat )\r\n\t\t\t{\r\n\t\t\t\tbool\twant_this_material\t= false;\r\n\r\n\t\t\t\t// We are searching for materials with a matching name. However there is one caveat in that the\r\n\t\t\t\t// conversion process sometimes creates new materials for geometry flagged as 'render as separate.\r\n\t\t\t\t// In such a case, the new material name checksum = original name checksum + pass + 1.\r\n\t\t\t\tif( p_mat->m_materialNameChecksum == mat_name_checksum )\r\n\t\t\t\t\twant_this_material = true;\r\n\t\t\t\telse if( p_mat->m_materialNameChecksum == ( mat_name_checksum + pass + 1 ) )\r\n\t\t\t\t{\r\n\t\t\t\t\twant_this_material = true;\r\n\r\n\t\t\t\t\tpass = 0;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( want_this_material )\r\n\t\t\t\t{\r\n//\t\t\t\t\t// Create the wibble params if they don't exist already.\r\n//\t\t\t\t\tif( p_mat->mp_UVWibbleParams[pass] == NULL )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[pass]\t= new NxNgc::sUVWibbleParams;\r\n//\r\n//\t\t\t\t\t\t// Need to set flags to indicate that uv wibble is now in effect.\r\n//\t\t\t\t\t\tp_mat->m_uv_wibble\t\t\t\t= true;\r\n//\t\t\t\t\t\tp_mat->m_flags[pass]\t\t   |= MATFLAG_UV_WIBBLE | MATFLAG_EXPLICIT_UV_WIBBLE;\r\n//\t\t\t\t\t\treturn true;\r\n//\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\r\n} // Nx\r\n\t\t\t\t\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_NxGeom.h",
    "content": "\t//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxGeom.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  3/5/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_GEOM_H__\r\n#define\t__GFX_P_NX_GEOM_H__\r\n    \r\n#include \"gfx/nxgeom.h\"\r\n#include \"gfx/Ngc/p_nxsector.h\"\r\n#include \"gfx/Ngc/p_nxmesh.h\"\r\n\r\nnamespace Mth\r\n{\r\n\tclass Matrix;\r\n}\r\n\r\nnamespace NxNgc\r\n{\r\n\tclass CInstance;\r\n}\r\n\t\t\t\t\t\t   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CGeom\r\nclass CNgcGeom : public CGeom\r\n{\r\n                                      \r\npublic:\r\n\t\t\t\t\t\t\t\tCNgcGeom();\r\n\tvirtual \t\t\t\t\t~CNgcGeom();\r\n\tvoid\t\t\t\t\t\tSetInstance( NxNgc::CInstance *p_instance )\t\t{ mp_instance = p_instance; }\r\n\tNxNgc::CInstance\t\t\t*GetInstance( void )\t\t\t\t\t\t\t\t{ return mp_instance; }\r\n\tvoid\t\t\t\t\t\tInitMeshList();\r\n\tvoid\t\t\t\t\t\tClearMeshList();\r\n\tvoid\t\t\t\t\t\tAddMesh( NxNgc::sMesh * );\r\n\tLst::Head< NxNgc::sMesh >\t*GetMeshList();\r\n\r\n\tvoid\t\t\t\t\t\tCreateMeshArray();\r\n\tbool\t\t\t\t\t\tRegisterMeshArray( bool just_count );\r\n\tvoid\t\t\t\t\t\tDestroyMeshArray( void );\r\n\r\n\tconst Mth::CBBox &\t\t\tGetBoundingBox( void )\t\t\t{ return m_bbox; }\r\n\tvoid\t\t\t\t\t\tSetScene( CNgcScene *p_scene )\t{ mp_scene = p_scene; }\r\n\tNxNgc::sScene\t\t\t\t*GenerateScene( void );\r\n\r\n\tMth::Vector *\t\t\t\tGetOffset( void ) { return &m_mod.offset; }\r\n\tMth::Vector *\t\t\t\tGetScale( void ) { return &m_mod.scale; }\r\n\r\nprivate:\t\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvirtual\tbool\t\t\t\t\tplat_load_geom_data( CMesh *pMesh, CModel *pModel, bool color_per_material );\r\n\tvirtual\tvoid\t\t\t\t\tplat_set_active( bool active );\r\n\tvirtual bool\t\t\t\t\tplat_is_active( void ) const;\r\n\tconst Mth::CBBox &\t\t\t\tplat_get_bounding_box( void ) const;\r\n\tvirtual void\t\t\t\t\tplat_set_bounding_sphere( const Mth::Vector& boundingSphere );\r\n\tvirtual const Mth::Vector\t\tplat_get_bounding_sphere( void ) const;\r\n\tvirtual void\t\t\t\t\tplat_set_world_position( const Mth::Vector& pos );\r\n\tvirtual const Mth::Vector &\t\tplat_get_world_position() const;\r\n\tvirtual bool\t\t\t\t\tplat_render( Mth::Matrix* pRootMatrix, Mth::Matrix* ppBoneMatrices, int numBones );\r\n\tvirtual void\t\t\t\t\tplat_set_bone_matrix_data( Mth::Matrix* pBoneMatrices, int numBones );\r\n\tvirtual bool\t\t\t\t\tplat_hide_polys( uint32 mask );\r\n\tvirtual uint32\t\t\t\t\tplat_get_visibility( void ) const;\r\n\tvirtual\tvoid\t\t\t\t\tplat_set_visibility( uint32 mask );\r\n\tvirtual void\t\t\t\t\tplat_set_color( Image::RGBA rgba );\r\n\tvirtual void\t\t\t\t\tplat_clear_color( void );\r\n\tvirtual Image::RGBA\t\t\t\tplat_get_color( void ) const;\r\n\tvirtual CNgcGeom\t\t\t\t*CNgcGeom::plat_clone( bool instance, CScene *p_dest_scene = NULL );\r\n\tvirtual CNgcGeom\t\t\t\t*CNgcGeom::plat_clone( bool instance, CModel* pDestModel );\r\n\tvirtual void\t\t\t\t\tplat_set_orientation(const Mth::Matrix& orient);\r\n\tvirtual void \t\t\t\t\tplat_rotate_y(Mth::ERot90 rot);\r\n\tvirtual void\t\t\t\t\tplat_set_transform(const Mth::Matrix& transform);\r\n\tvirtual const \t\t\t\t\tMth::Matrix &\tplat_get_transform() const;\r\n\tvirtual\tint\t\t\t\t\t\tplat_get_num_render_verts( void );\r\n\tvirtual\tvoid\t\t\t\t\tplat_get_render_verts( Mth::Vector *p_verts );\r\n\tvirtual\tvoid\t\t\t\t\tplat_get_render_colors( Image::RGBA *p_colors );\r\n\tvirtual void\t\t\t\t\tplat_set_render_verts( Mth::Vector *p_verts );\r\n\tvirtual\tvoid\t\t\t\t\tplat_set_render_colors( Image::RGBA *p_colors );\r\n\tvirtual void\t\t\t\t\tplat_set_model_lights( CModelLights* p_model_lights );\r\n\tvirtual void\t\t\t\t\tplat_set_scale(const Mth::Vector& scale);\r\n\tvirtual Mth::Vector \t\t\tplat_get_scale() const;\r\n\tvirtual bool\t\t\t\t\tplat_set_material_color( uint32 mat_name_checksum, int pass, Image::RGBA rgba );\r\n\tvirtual void\t\t\t\t\tplat_set_uv_wibble_params( float u_vel, float u_amp, float u_freq, float u_phase, float v_vel, float v_amp, float v_freq, float v_phase );\r\n\tvirtual void\t\t\t\t\tplat_use_explicit_uv_wibble( bool yes );\r\n\tvirtual void\t\t\t\t\tplat_set_uv_wibble_offsets( float u_offset, float v_offset );\r\n\tvirtual bool\t\t\t\t\tplat_set_uv_wibble_offsets( uint32 mat_name_checksum, int pass, float u_offset, float v_offset );\r\n\tvirtual bool\t\t\t\t\tplat_set_uv_matrix( uint32 mat_name_checksum, int pass, const Mth::Matrix& mat );\r\n\tvirtual bool\t\t\t\t\tplat_allocate_uv_matrix_params( uint32 mat_checksum, int pass );\r\n\r\npublic:\r\n\tMth::CBBox\t\t\t\t\t\tm_bbox;\t\r\n\t\r\n\tCNgcScene *\t\t\t\t\tmp_scene;\r\n\tLst::Head< NxNgc::sMesh >\t\t*mp_init_mesh_list;   \r\n\tNxNgc::sMesh **\t\t\t\tm_mesh_array;\r\n\tuint\t\t\t\t\t\t\tm_num_mesh;\r\n\tuint32\t\t\t\t\t\t\tm_visible;\r\n\tbool\t\t\t\t\t\t\tm_active;\r\n\r\nprivate:\r\n\tNxNgc::CInstance\t\t\t\t*mp_instance;\r\n\tCNgcMesh\t\t\t\t\t\t*mp_mesh;\t\t// Used for obtaining CAS poly removal data.\r\n\tNxNgc::sMeshMod\t\t\t\t\tm_mod;\r\n\r\n\tint\t\t\t\t\t\t\t\tbuild_index_map( int * p_pos_index, int * p_col_index );\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n#endif \r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_NxImposter.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxImposter.cpp\r\n\r\n#include \t\"gfx/ngc/p_NxGeom.h\"\r\n#include \t\"gfx/ngc/p_NxImposter.h\"\r\n\r\nnamespace Nx\r\n{\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCImposterGroup* CImposterManager::plat_create_imposter_group( void )\r\n{\r\n\treturn new CNgcImposterGroup;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterManager::plat_pre_render_imposters( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterManager::plat_post_render_imposters( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CImposterGroup\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcImposterGroup::CNgcImposterGroup()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcImposterGroup::~CNgcImposterGroup()\r\n{\r\n}\r\n\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_NxImposter.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxFont.h\r\n\r\n#ifndef\t__GFX_P_NX_IMPOSTER_H__\r\n#define\t__GFX_P_NX_IMPOSTER_H__\r\n\r\n#include \t\"gfx/NxImposter.h\"\r\n\r\nnamespace Nx\r\n{\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CImposterGroup\r\nclass CNgcImposterGroup : public CImposterGroup\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\t\tCNgcImposterGroup();\r\n\tvirtual\t\t\t\t\t\t~CNgcImposterGroup();\r\n\r\n\r\n\tprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\r\n\t// Machine specific members\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_NxLightMan.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxLightMan.cpp - Ngc platform specific interface to CLightManager\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/NxLightMan.h\"\r\n#include \"gfx/Ngc/p_NxLight.h\"\r\n#include \"gfx/Ngc/nx/nx_init.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLightManager::s_plat_update_engine( void )\r\n{\r\n\tint difr = (int)((float)s_world_lights.m_light_ambient_rgba.r * s_ambient_brightness);\r\n\tint difg = (int)((float)s_world_lights.m_light_ambient_rgba.g * s_ambient_brightness);\r\n\tint difb = (int)((float)s_world_lights.m_light_ambient_rgba.b * s_ambient_brightness);\r\n\tNxNgc::EngineGlobals.ambient_light_color.r = difr > 255 ? 255 : (u8)difr;  \r\n\tNxNgc::EngineGlobals.ambient_light_color.g = difg > 255 ? 255 : (u8)difg;  \r\n\tNxNgc::EngineGlobals.ambient_light_color.b = difb > 255 ? 255 : (u8)difb;  \r\n\r\n//\tNxNgc::EngineGlobals.ambient_light_color.r = NxNgc::EngineGlobals.ambient_light_color.r < 128 ? NxNgc::EngineGlobals.ambient_light_color.r * 2 : 255;\r\n//\tNxNgc::EngineGlobals.ambient_light_color.g = NxNgc::EngineGlobals.ambient_light_color.g < 128 ? NxNgc::EngineGlobals.ambient_light_color.g * 2 : 255;\r\n//\tNxNgc::EngineGlobals.ambient_light_color.b = NxNgc::EngineGlobals.ambient_light_color.b < 128 ? NxNgc::EngineGlobals.ambient_light_color.b * 2 : 255;\r\n\r\n\tfor( int i = 0; i < 2; ++i )\r\n\t{\r\n\t\tImage::RGBA\tdif = CLightManager::sGetLightDiffuseColor( i );\r\n\t\tint difr = (int)((float)dif.r * s_diffuse_brightness[i]);\r\n\t\tint difg = (int)((float)dif.g * s_diffuse_brightness[i]);\r\n\t\tint difb = (int)((float)dif.b * s_diffuse_brightness[i]);\r\n\t\tNxNgc::EngineGlobals.diffuse_light_color[i].r = difr > 255 ? 255 : (u8)difr;\r\n\t\tNxNgc::EngineGlobals.diffuse_light_color[i].g = difg > 255 ? 255 : (u8)difg;\r\n\t\tNxNgc::EngineGlobals.diffuse_light_color[i].b = difb > 255 ? 255 : (u8)difb;\r\n\r\n//\t\tNxNgc::EngineGlobals.diffuse_light_color[i].r = NxNgc::EngineGlobals.diffuse_light_color[i].r < 128 ? NxNgc::EngineGlobals.diffuse_light_color[i].r * 2 : 255;\r\n//\t\tNxNgc::EngineGlobals.diffuse_light_color[i].g = NxNgc::EngineGlobals.diffuse_light_color[i].g < 128 ? NxNgc::EngineGlobals.diffuse_light_color[i].g * 2 : 255;\r\n//\t\tNxNgc::EngineGlobals.diffuse_light_color[i].b = NxNgc::EngineGlobals.diffuse_light_color[i].b < 128 ? NxNgc::EngineGlobals.diffuse_light_color[i].b * 2 : 255;\r\n\r\n\t\tMth::Vector dir = CLightManager::sGetLightDirection( i );\r\n\t\tdir.Normalize();\r\n\t\tNxNgc::EngineGlobals.light_x[i] = dir[X] * 200000.0f;\r\n\t\tNxNgc::EngineGlobals.light_y[i] = dir[Y] * 200000.0f;\r\n\t\tNxNgc::EngineGlobals.light_z[i] = dir[Z] * 200000.0f;\r\n\t}\r\n\t// Set lighting.\r\n//\tGXLightObj light_obj[2];\r\n//\r\n////\tGX::SetChanAmbColor( GX_COLOR0A0, NxNgc::EngineGlobals.ambient_light_color );\r\n//\r\n////\tGXInitLightColor( &light_obj[0], NxNgc::EngineGlobals.diffuse_light_color[0] );\r\n////\tGXInitLightPos( &light_obj[0], NxNgc::EngineGlobals.light_x[0], NxNgc::EngineGlobals.light_y[0], NxNgc::EngineGlobals.light_z[0] );\r\n////\tGXLoadLightObjImm( &light_obj[0], GX_LIGHT0 );\r\n////\tGXInitSpecularDir( &light_obj[2], -NxNgc::EngineGlobals.light_x[0] / 200000.0f, -NxNgc::EngineGlobals.light_y[0] / 200000.0f, -NxNgc::EngineGlobals.light_z[0] / 200000.0f );\r\n////\tGXInitLightShininess( &light_obj[2], 5.0f );\r\n////\r\n////\tGXInitLightColor( &light_obj[1], NxNgc::EngineGlobals.diffuse_light_color[1] );\r\n////\tGXInitLightPos( &light_obj[1], NxNgc::EngineGlobals.light_x[1], NxNgc::EngineGlobals.light_y[1], NxNgc::EngineGlobals.light_z[1] );\r\n////\tGXLoadLightObjImm( &light_obj[1], GX_LIGHT1 );\r\n////\tGXInitSpecularDir( &light_obj[2], -NxNgc::EngineGlobals.light_x[1] / 200000.0f, -NxNgc::EngineGlobals.light_y[1] / 200000.0f, -NxNgc::EngineGlobals.light_z[1] / 200000.0f );\r\n////\tGXInitLightShininess( &light_obj[2], 5.0f );\r\n//\r\n//    Vec  ldir;\r\n//    f32  theta, phi;\r\n//\r\n//    // Light position\r\n//    theta = (f32)90 * Mth::PI / 180.0F;\r\n//    phi   = (f32)0   * Mth::PI / 180.0F;\r\n//    ldir.x = - 1.0F * cosf(phi) * sinf(theta);\r\n//    ldir.y = - 1.0F * sinf(phi);\r\n//    ldir.z = - 1.0F * cosf(phi) * cosf(theta);\r\n//\r\n//    // Convert light position into view space\r\n//    Vec  dir0;\r\n//    Vec  dir1;\r\n//    MTXMultVecSR(NxNgc::EngineGlobals.current_uploaded, &ldir, &dir0);\r\n//    MTXMultVecSR(NxNgc::EngineGlobals.current_uploaded, &ldir, &dir1);\r\n//\r\n//////\tGXInitSpecularDir( &light_obj[0], NxNgc::EngineGlobals.light_x[0] / 200000.0f, NxNgc::EngineGlobals.light_y[0] / 200000.0f, NxNgc::EngineGlobals.light_z[0] / 200000.0f );\r\n////\tGXInitSpecularDirv( &light_obj[0], &dir0 );\r\n////\tGXInitLightShininess( &light_obj[0], 16.0f );\r\n////\tGXInitLightColor( &light_obj[0], (GXColor){0,0,0,0}/*NxNgc::EngineGlobals.diffuse_light_color[0]*/ );\r\n////\tGXLoadLightObjImm( &light_obj[0], GX_LIGHT0 );\r\n//\r\n////\tGXInitSpecularDir( &light_obj[1], NxNgc::EngineGlobals.light_x[1] / 200000.0f, NxNgc::EngineGlobals.light_y[1] / 200000.0f, NxNgc::EngineGlobals.light_z[1] / 200000.0f );\r\n//\tGXInitSpecularDirv( &light_obj[0], &dir0 );\r\n//\tGXInitLightShininess( &light_obj[0], 5.0f );\r\n//\tGXInitLightColor( &light_obj[0], NxNgc::EngineGlobals.diffuse_light_color[1] );\r\n//\tGXLoadLightObjImm( &light_obj[0], GX_LIGHT0 );\r\n//\r\n//\tGXSetChanAmbColor( GX_COLOR0A0, (GXColor){0,0,0,255} );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLightManager::s_plat_update_lights( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CLightManager::s_plat_set_light_ambient_color()\r\n{\r\n\tint difr = (int)((float)s_world_lights.m_light_ambient_rgba.r * s_ambient_brightness);\r\n\tint difg = (int)((float)s_world_lights.m_light_ambient_rgba.g * s_ambient_brightness);\r\n\tint difb = (int)((float)s_world_lights.m_light_ambient_rgba.b * s_ambient_brightness);\r\n\tNxNgc::EngineGlobals.ambient_light_color.r = difr > 255 ? 255 : (u8)difr;\r\n\tNxNgc::EngineGlobals.ambient_light_color.g = difg > 255 ? 255 : (u8)difg;\r\n\tNxNgc::EngineGlobals.ambient_light_color.b = difb > 255 ? 255 : (u8)difb;\r\n\t\r\n\tNxNgc::EngineGlobals.ambient_light_color.r = NxNgc::EngineGlobals.ambient_light_color.r < 128 ? NxNgc::EngineGlobals.ambient_light_color.r * 2 : 255;\r\n\tNxNgc::EngineGlobals.ambient_light_color.g = NxNgc::EngineGlobals.ambient_light_color.g < 128 ? NxNgc::EngineGlobals.ambient_light_color.g * 2 : 255;\r\n\tNxNgc::EngineGlobals.ambient_light_color.b = NxNgc::EngineGlobals.ambient_light_color.b < 128 ? NxNgc::EngineGlobals.ambient_light_color.b * 2 : 255;\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nImage::RGBA\tCLightManager::s_plat_get_light_ambient_color()\r\n{\r\n\treturn s_world_lights.m_light_ambient_rgba;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CLightManager::s_plat_set_light_direction( int light_index )\r\n{\r\n\tNxNgc::EngineGlobals.light_x[light_index] = -s_world_lights.m_light_direction[light_index][X];\r\n\tNxNgc::EngineGlobals.light_y[light_index] = -s_world_lights.m_light_direction[light_index][Y];\r\n\tNxNgc::EngineGlobals.light_z[light_index] = -s_world_lights.m_light_direction[light_index][Z];\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::Vector & CLightManager::s_plat_get_light_direction( int light_index )\r\n{\r\n\tstatic Mth::Vector dir;\r\n\tdir.Set( s_world_lights.m_light_direction[light_index][X], s_world_lights.m_light_direction[light_index][Y], s_world_lights.m_light_direction[light_index][Z] );\r\n\treturn dir;\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CLightManager::s_plat_set_light_diffuse_color( int light_index )\r\n{\r\n\tNxNgc::EngineGlobals.diffuse_light_color[light_index].r = (u8)((float)s_world_lights.m_light_diffuse_rgba[light_index].r * s_diffuse_brightness[light_index]);\r\n\tNxNgc::EngineGlobals.diffuse_light_color[light_index].g = (u8)((float)s_world_lights.m_light_diffuse_rgba[light_index].g * s_diffuse_brightness[light_index]);\r\n\tNxNgc::EngineGlobals.diffuse_light_color[light_index].b = (u8)((float)s_world_lights.m_light_diffuse_rgba[light_index].b * s_diffuse_brightness[light_index]);\r\n\t\r\n\tNxNgc::EngineGlobals.diffuse_light_color[light_index].r = NxNgc::EngineGlobals.diffuse_light_color[light_index].r < 128 ? NxNgc::EngineGlobals.diffuse_light_color[light_index].r * 2 : 255;\r\n\tNxNgc::EngineGlobals.diffuse_light_color[light_index].g = NxNgc::EngineGlobals.diffuse_light_color[light_index].g < 128 ? NxNgc::EngineGlobals.diffuse_light_color[light_index].g * 2 : 255;\r\n\tNxNgc::EngineGlobals.diffuse_light_color[light_index].b = NxNgc::EngineGlobals.diffuse_light_color[light_index].b < 128 ? NxNgc::EngineGlobals.diffuse_light_color[light_index].b * 2 : 255;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nImage::RGBA\tCLightManager::s_plat_get_light_diffuse_color( int light_index )\r\n{\r\n\treturn s_world_lights.m_light_diffuse_rgba[light_index];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLightManager::s_plat_update_colors( void )\r\n{\r\n\ts_plat_set_light_ambient_color();\r\n\tfor( int i = 0; i < MAX_LIGHTS; ++i )\r\n\t{\r\n\t\ts_plat_set_light_diffuse_color( i );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCModelLights *CLightManager::s_plat_create_model_lights()\r\n{\r\n\treturn new CNgcModelLights;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CLightManager::s_plat_free_model_lights( CModelLights *p_model_lights )\r\n{\r\n\tDbg_Assert( p_model_lights );\r\n\r\n\tdelete p_model_lights;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n} \r\n \r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_NxMesh.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxMesh.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/15/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include <core/string/stringutils.h>\r\n#include <sys/file/filesys.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxtexman.h>\r\n#include <gfx/Ngc/p_nxmesh.h>\r\n#include <gfx/Ngc/p_nxscene.h>\r\n#include <gfx/Ngc/nx/scene.h>\r\n#include <gfx/Ngc/nx/texture.h>\r\n\r\n//extern Nx::CNgcScene *p_skater;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int cmp( const void *p1, const void *p2 )\r\n{\r\n\tNxNgc::sCASData *p_casdata1 = (NxNgc::sCASData*)p1;\r\n\tNxNgc::sCASData *p_casdata2 = (NxNgc::sCASData*)p2;\r\n\t\r\n\tuint32 mesh1 = p_casdata1->data0 >> 16;\r\n\tuint32 mesh2 = p_casdata2->data0 >> 16;\r\n\t\r\n\tif( mesh1 > mesh2 )\r\n\t{\r\n\t\treturn 1;\r\n\t}\r\n\telse if( mesh1 < mesh2 )\r\n\t{\r\n\t\treturn -1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tuint32 indexzero1 = p_casdata1->data0 & 0xFFFF;\r\n\t\tuint32 indexzero2 = p_casdata2->data0 & 0xFFFF;\r\n\t\tif( indexzero1 > indexzero2 )\r\n\t\t{\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t\telse if( indexzero1 < indexzero2 )\r\n\t\t{\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcMesh::build_casdata_table( const char* pFileName )\r\n{\r\n\tvoid *pFile = File::Open( pFileName, \"rb\" );\r\n\tDbg_MsgAssert( pFile, ( \"Couldn't open CAS data file %s\\n\", pFileName ));\r\n\r\n\tuint32 version;\r\n\tFile::Read( &version, sizeof( uint32 ), 1, pFile );\r\n\r\n\tif( version >= 2 )\r\n\t{\r\n\t\tFile::Read( &m_CASRemovalMask, sizeof( uint32 ), 1, pFile );\r\n\t}\r\n\t\r\n\tFile::Read( &m_numCASData, sizeof( int ), 1, pFile );\r\n\r\n\tif( m_numCASData > 0 )\r\n\t{\r\n\t\t// CAS flags.\r\n\t\tmp_CASData = new NxNgc::sCASData[m_numCASData];\r\n\t\tFile::Read( &mp_CASData[0].mask,\tsizeof( uint32 ) * 3 * m_numCASData, 1, pFile );\r\n\t\r\n\t\t// Sort the CAS data based first on mesh, then on the first tri index, lowest to highest. This allows some efficient early-out checking\r\n\t\t// during the poly removal.\r\n\t\tqsort( mp_CASData, m_numCASData, sizeof( NxNgc::sCASData ), cmp );\r\n\t}\r\n\r\n\tFile::Close( pFile );\r\n\treturn ( m_numCASData > 0 );\r\n}\r\n\r\n#define MemoryRead( dst, size, num, src )\tmemcpy(( dst ), ( src ), (( num ) * ( size )));\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t( src ) += (( num ) * ( size ))\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcMesh::build_casdata_table_from_memory( void **pp_mem )\r\n{\r\n\tuint8 *p_data = (uint8*)( *pp_mem );\r\n\r\n\tuint32 version;\r\n\tMemoryRead( &version, sizeof( uint32 ), 1, p_data );\r\n\r\n\tif( version >= 2 )\r\n\t{\r\n\t\tMemoryRead( &m_CASRemovalMask, sizeof( uint32 ), 1, p_data );\r\n\t}\r\n\t\r\n\tMemoryRead( &m_numCASData, sizeof( int ), 1, p_data );\r\n\r\n\tif( m_numCASData > 0 )\r\n\t{\r\n\t\t// CAS flags.\r\n\t\tmp_CASData = new NxNgc::sCASData[m_numCASData];\r\n\r\n\t\tfor( uint32 i = 0; i < m_numCASData; ++i )\r\n\t\t{\r\n\t\t\tMemoryRead( &mp_CASData[i].mask, sizeof( uint32 ) * 3, 1, p_data );\r\n\t\t}\r\n\r\n\t\t// Sort the CAS data based first on mesh, then on the first tri index, lowest to highest. This allows some efficient early-out checking\r\n\t\t// during the poly removal.\r\n\t\tqsort( mp_CASData, m_numCASData, sizeof( NxNgc::sCASData ), cmp );\r\n\t}\r\n\t\r\n\t// Set the data pointer to the new position on return.\r\n\t*pp_mem = p_data;\r\n\r\n\treturn ( m_numCASData > 0 );\r\n}\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcMesh::CNgcMesh( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcMesh::CNgcMesh( const char *pMeshFileName )\r\n{\r\n\t// Only do the CAS flag building for skinned objects.\r\n\tif( strstr( pMeshFileName, \"skin\" ))\r\n\t{\r\n\t\tchar CASFileName[256];\r\n\t\tstrcpy( CASFileName, pMeshFileName );\r\n\t\tStr::LowerCase( CASFileName );\r\n\t\tchar *pExt = strstr( CASFileName, \"skin.ngc\" );\r\n\t\tif( pExt )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( pExt, ( \"Couldn't find skin.ngc extension in %s\", CASFileName ));\r\n\t\t\tstrcpy( pExt, \"cas.ngc\" );\r\n\t\t\tbuild_casdata_table( CASFileName );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcMesh::~CNgcMesh( void )\r\n{\r\n\t// unload textures\r\n//\tNxNgc::DeleteTextures( mp_scene );\r\n\r\n\tif( mp_CASData )\r\n\t{\r\n\t\tdelete [] mp_CASData;\r\n\t}\r\n\t\r\n\tif( mp_scene )\r\n\t{\r\n\t\tCEngine::sUnloadScene( mp_scene );\r\n//\t\tNxNgc::DeleteScene( mp_engine_scene );\r\n\t}\r\n}\r\n\r\n\r\nvoid CNgcMesh::SetScene( CNgcScene *p_scene )\r\n{\r\n\tmp_scene = p_scene;\r\n\t// Copy the hierarchy info from the scene so that above the p-line stuff can access it.\r\n\tmp_hierarchyObjects = mp_scene->GetEngineScene()->mp_hierarchyObjects;\r\n\tm_numHierarchyObjects = mp_scene->GetEngineScene()->m_numHierarchyObjects;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcMesh::SetCASData( uint8 *p_cas_data )\r\n{\r\n\tif( p_cas_data )\r\n\t{\r\n\t\tbuild_casdata_table_from_memory((void**)&p_cas_data );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n\t\t\t\t\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_NxMesh.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxMesh.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/15/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_MESH_H__\r\n#define\t__GFX_P_NX_MESH_H__\r\n    \r\n#include \"gfx/nxmesh.h\"\r\n#include \"p_nxscene.h\"\r\n\r\nnamespace NxNgc\r\n{\r\n\tstruct sScene;\r\n}\r\n\t\t\t \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CMesh\r\n    \r\nclass CNgcMesh : public CMesh\r\n{\r\n                                      \r\npublic:\r\n\t\t\t\t\t\tCNgcMesh( void );\r\n\t\t\t\t\t\tCNgcMesh( const char *pMeshFileName );\r\n\tvirtual \t\t\t~CNgcMesh();\r\n\tvoid\t\t\t\tSetScene( CNgcScene *p_scene );\r\n\r\n\tvoid\t\t\t\tSetTexDict( Nx::CTexDict *p_tex_dict )\t{ mp_texDict = p_tex_dict; }\r\n\tvoid\t\t\t\tSetCASData( uint8 *p_cas_data );\r\n\tCNgcScene\t\t\t*GetScene( void )\t\t\t\t\t\t{ return mp_scene; }\r\n\r\n\tNxNgc::sCASData\t\t*GetCASData( void )\t\t\t\t\t\t{ return mp_CASData; }\r\n\tuint32\t\t\t\tGetNumCASData( void )\t\t\t\t\t{ return m_numCASData; }\r\n\r\nprotected:\r\n\tbool\t\t\t\tbuild_casdata_table(const char* pFileName);\r\n\tbool\t\t\t\tbuild_casdata_table_from_memory( void **pp_mem );\r\n\t\r\n\tNxNgc::sCASData\t\t*mp_CASData;\r\n\tuint32\t\t\t\tm_numCASData;\r\n\r\nprivate:\r\n\tCNgcScene\t\t\t*mp_scene;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n#endif \r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_NxSprite.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxSprite.cpp\r\n\r\n#include \t\"Gfx/Ngc/p_NxSprite.h\"\r\n#include \t\"Gfx/Ngc/p_NxTexture.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CSprite\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNgcSprite::CNgcSprite()\r\n{\r\n\tmp_plat_sprite = new NxNgc::sSprite();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNgcSprite::~CNgcSprite()\r\n{\r\n\tdelete mp_plat_sprite;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcSprite::plat_initialize()\r\n{\r\n\tplat_update_engine();\r\n\tplat_update_priority();\r\n\tplat_update_hidden();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcSprite::plat_update_hidden()\r\n{\r\n\t// Take sprite on or off draw list\r\n\tmp_plat_sprite->SetHidden( m_hidden );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcSprite::plat_update_engine()\r\n{\r\n\tCNgcTexture *p_Ngc_texture = static_cast<CNgcTexture *>( mp_texture );\r\n\r\n\t// Rebuild sprite primitives\r\n\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_plat_sprite->mp_texture\t= p_Ngc_texture->GetEngineTexture();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_plat_sprite->mp_texture\t= NULL;\r\n\t}\r\n\r\n\tmp_plat_sprite->m_xpos\t\t= m_pos_x;\r\n\tmp_plat_sprite->m_ypos\t\t= m_pos_y;\r\n\tmp_plat_sprite->m_width\t\t= m_width;\r\n\tmp_plat_sprite->m_height\t= m_height;\r\n\tmp_plat_sprite->m_scale_x\t= m_scale_x;\r\n\tmp_plat_sprite->m_scale_y\t= m_scale_y;\r\n\r\n\tmp_plat_sprite->m_xhot\t\t= (( m_anchor_x + 1.0f ) * 0.5f) * ( m_width );\r\n\tmp_plat_sprite->m_yhot\t\t= (( m_anchor_y + 1.0f ) * 0.5f) * ( m_height );\r\n\r\n\tmp_plat_sprite->m_rot\t\t= m_rotation;\r\n\tmp_plat_sprite->m_rgba\t\t= *((uint32 *) &m_rgba);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcSprite::plat_update_priority()\r\n{\r\n\tif( mp_plat_sprite )\r\n\t{\r\n\t\tmp_plat_sprite->SetPriority( m_priority );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCSprite::plat_enable_constant_z_value(bool enable)\r\n{\r\n\t//NxPs2::SSprite::EnableConstantZValue(enable);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCSprite::plat_set_constant_z_value(Nx::ZBufferValue z)\r\n{\r\n\t//NxPs2::SSprite::SetConstantZValue(z);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::ZBufferValue\tCSprite::plat_get_constant_z_value()\r\n{\r\n\t//return NxPs2::SSprite::GetConstantZValue();\r\n\treturn 0;\r\n}\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_NxSprite.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxScene.h\r\n\r\n#ifndef\t__GFX_P_NX_SPRITE_H__\r\n#define\t__GFX_P_NX_SPRITE_H__\r\n\r\n#include \t\"Gfx/NxSprite.h\"\r\n#include \t\"Gfx/Ngc/NX/texture.h\"\r\n#include \t\"Gfx/Ngc/NX/sprite.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Machine specific implementation of the CSprite\r\nclass\tCNgcSprite : public CSprite\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCNgcSprite();\r\n\tvirtual\t\t\t\t\t\t~CNgcSprite();\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\tvirtual void\t\t\t\tplat_initialize();\r\n\r\n\tvirtual void\t\t\t\tplat_update_hidden();\t\t// Tell engine of update\r\n\tvirtual void\t\t\t\tplat_update_engine();\t\t// Update engine primitives\r\n\tvirtual void\t\t\t\tplat_update_priority();\r\n\r\n\tNxNgc::sSprite *\t\t\tmp_plat_sprite;\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_NxTextured3dPoly.cpp",
    "content": "#include \t\"Gfx/ngc/p_NxTextured3dPoly.h\"\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CTextured3dPoly\r\n\r\nCNgcTextured3dPoly::CNgcTextured3dPoly()\r\n{\r\n}\r\n\r\nCNgcTextured3dPoly::~CNgcTextured3dPoly()\r\n{\r\n}\r\n\r\nvoid CNgcTextured3dPoly::plat_set_texture(uint32 texture_checksum)\r\n{\r\n}\t\r\n\r\nvoid CNgcTextured3dPoly::plat_render()\r\n{\r\n}\r\n\r\n} // Namespace NxNgc  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_NxTextured3dPoly.h",
    "content": "#ifndef\t__GFX_P_NX_TEXTURED_3D_POLY_H__\r\n#define\t__GFX_P_NX_TEXTURED_3D_POLY_H__\r\n\r\n#include \t<gfx/nxtextured3dpoly.h>\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n// Machine specific implementation of CTextured3dPoly\r\nclass\tCNgcTextured3dPoly : public Nx::CTextured3dPoly\r\n{\r\npublic:\r\n\t\t   \t\t\t\t\tCNgcTextured3dPoly();\r\n\tvirtual\t\t\t\t\t~CNgcTextured3dPoly();\r\nprivate:\r\n\tvoid\t\t\t\t\tplat_render();\r\n\tvoid\t\t\t\t\tplat_set_texture(uint32 texture_checksum);\r\n};\r\n\r\n}\t// namespace NxNgc\r\n\r\n#endif\r\n\t\t\t\t   \r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_NxViewport.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxViewport.cpp\r\n\r\n#include \t\"Gfx/NGC/p_NxViewport.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CViewport\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNgcViewport::CNgcViewport()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNgcViewport::CNgcViewport( const Mth::Rect* rect, Gfx::Camera* cam) :\r\n\tCViewport(rect, cam)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNgcViewport::~CNgcViewport()\r\n{\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_NxViewport.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxViewport.h\r\n\r\n#ifndef\t__GFX_P_NX_VIEWPORT_H__\r\n#define\t__GFX_P_NX_VIEWPORT_H__\r\n\r\n#include \t\"Gfx/NxViewport.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Machine specific implementation of the CViewport\r\nclass\tCNgcViewport : public CViewport\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCNgcViewport();\r\n\t\t\t\t\t\t\t\tCNgcViewport(const Mth::Rect* rect, Gfx::Camera* cam = NULL);\r\n\tvirtual\t\t\t\t\t\t~CNgcViewport();\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\t//virtual void\t\t\t\tplat_initialize();\r\n\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_NxWin2D.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxWin2D.cpp\r\n\r\n#include \t\"Gfx/Ngc/p_NxWin2D.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of the CText\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNgcWindow2D::CNgcWindow2D(int x, int y, int width, int height) : CWindow2D(x, y, width, height)\r\n{\r\n//\tmp_plat_window = new NxNgc::SScissorWindow();\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNgcWindow2D::~CNgcWindow2D()\r\n{\r\n//\tif (mp_plat_window)\r\n//\t{\r\n//\t\tdelete mp_plat_window;\r\n//\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCNgcWindow2D::plat_update_engine()\r\n{\r\n\tDbg_Assert(m_xpos >= 0);\r\n\tDbg_Assert(m_ypos >= 0);\r\n\r\n\tint x1 = m_xpos + m_width - 1;\r\n\tint y1 = m_ypos + m_height - 1;\r\n\r\n\tDbg_Assert(x1 >= 0);\r\n\tDbg_Assert(y1 >= 0);\r\n\r\n//\tmp_plat_window->SetScissor(m_xpos, m_ypos, x1, y1);\r\n\tm_left\t\t= m_xpos;\r\n\tm_top\t\t= m_ypos;\r\n\tm_right \t= x1;\r\n\tm_bottom\t= y1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCWindow2DManager::s_plat_alloc_window2d_pool()\r\n{\r\n\tfor (int i = 0; i < vMAX_WINDOW_INSTANCES; i++)\r\n\t{\r\n\t   \tCNgcWindow2D *p_window = new CNgcWindow2D;\r\n\t\tp_window->mp_next = sp_window_list;\r\n\t\tsp_window_list = p_window;\r\n\t}\r\n}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_gfxman.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics (GFX)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_gfxman.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t07/26/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGraphics device manager\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\r\n#include <gfx/gfxman.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#define SELECT_VIDEO_MODE\r\n// Some defines for gamma settings.\r\n#define gammaDefault\t1.0f\r\n#define gammaDomain\t\t256\r\n#define gammaRange\t\t256.0f\r\n#define MIN_GAMMA\t\t0.0f\r\n#define MAX_GAMMA\t\t2.0f\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//static D3DGAMMARAMP\tgammaTable;\r\n//static float\t\tgammaValueR = gammaDefault;\t// Current red gamma value.\r\n//static float\t\tgammaValueG = gammaDefault;\t// Current green gamma value.\r\n//static float\t\tgammaValueB = gammaDefault;\t// Current blue gamma value.\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//static void gammaInitTable( void )\r\n//{\r\n//\t// Create the gamma intensity lookup table.\r\n//\t// It works like this: given a colour value r [0,255] do r' = gammaTable.red[r] etc.\r\n//\tfor( int i = 0; i < gammaDomain; ++i )\r\n//\t{\r\n//\t\tgammaTable.red[i]\t= (BYTE)((float)gammaRange * pow(((float)i / (float)gammaDomain ), 1.0f / gammaValueR ));\r\n//\t\tgammaTable.green[i]\t= (BYTE)((float)gammaRange * pow(((float)i / (float)gammaDomain ), 1.0f / gammaValueG ));\r\n//\t\tgammaTable.blue[i]\t= (BYTE)((float)gammaRange * pow(((float)i / (float)gammaDomain ), 1.0f / gammaValueB ));\r\n//\t}\r\n//}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid gammaSetValue( float gr, float gg, float gb )\r\n{\r\n//\tgammaValueR = gr;\r\n//\tgammaValueG = gg;\r\n//\tgammaValueB = gb;\r\n//\r\n//\t// Create the table.\r\n//\tgammaInitTable();\r\n//\r\n//\t// Pass the table along to the hardware.\r\n//\tD3DDevice_SetGammaRamp( D3DSGR_NO_CALIBRATION, &gammaTable );\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//void Manager::SetGammaNormalized( float fr, float fg, float fb )\r\n//{\r\n//\t// Cap it....\r\n//\tfr = ( fr < 0.0f ) ? 0.0f : (( fr > 1.0f ) ? 1.0f : fr );\r\n//\tfg = ( fg < 0.0f ) ? 0.0f : (( fg > 1.0f ) ? 1.0f : fg );\r\n//\tfb = ( fb < 0.0f ) ? 0.0f : (( fb > 1.0f ) ? 1.0f : fb );\r\n//\r\n//\t// Scale it....\r\n//\tfr *= MAX_GAMMA;\r\n//\tfg *= MAX_GAMMA;\r\n//\tfb *= MAX_GAMMA;\r\n//\r\n//\t// Offset it.\r\n//\tfr += 0.5f;\r\n//\tfg += 0.5f;\r\n//\tfb += 0.5f;\r\n//\r\n//\t// f<col> now goes from 0.5 to 2.5.\r\n//\tgammaSetValue( fr, fg, fb );\r\n//}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::DumpVRAMUsage( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::ScreenShot( const char *fileroot )\r\n{\r\n//\tchar fileName[32];\r\n//\tchar fullFileName[64];\r\n//\r\n////\tSkate3 code, disabled for now.\r\n//#\tif 0\r\n//\t\r\n//\t// Try to find a good filename of the format filebasexxx.bmp. \"Good\" is defined here as one that isn't already used.\r\n//\tRwFileFunctions* fileFunctions = RwOsGetFileInterface();\r\n//\tfor( int i = 0;; ++i )\r\n//\t{\r\n//\t\tsprintf( fileName, \"screens\\\\%s%03d.bmp\", fileroot, i );\r\n//\r\n//\t\t// Found an unused one! Yay!\r\n//\t\tif( !fileFunctions->rwfexist( fileName ))\r\n//\t\t{\r\n//\t\t\tsprintf( fullFileName, \"d:\\\\data\\\\screens\\\\%s%03d.bmp\", fileroot, i );\r\n//\t\t\tbreak;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t// Obtain the render surface.\r\n//\tIDirect3DSurface8* p_render_target;\r\n//\tD3DDevice_GetRenderTarget( &p_render_target );\r\n//\r\n//\t// Get the surface description, just for s and g.\r\n//\tD3DSURFACE_DESC surface_desc;\r\n//\tp_render_target->GetDesc( &surface_desc );\r\n//\r\n//\t// This is great - this function spits surfaces straight out into a file.\r\n//\tHRESULT hr = XGWriteSurfaceToFile( p_render_target, fullFileName );\r\n//\tDbg_Assert( hr == S_OK );\r\n//\r\n//#\tendif\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n} // namespace Gfx\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_loadscreen.cpp",
    "content": "///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n//**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//******************************************************************************\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tProject:\t\tGfx\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tModule:\t\t\tLoadScreen\t\t\t \t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tFile name:\t\tp_loadscreen.cpp\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tCreated by:\t\t05/08/02\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tDescription:\tPS2-specific loading screen calls\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//#include <core/defines.h>\r\n//\r\n//#include <sys/file/filesys.h>\r\n//#include <sys/timer.h>\r\n//\r\n//#include <gel/mainloop.h>\r\n//\r\n//#include <gfx/ngc/p_memview.h>\r\n//#include <sys/ngc/p_display.h>\r\n//#include <sys/ngc/p_camera.h>\r\n//#include <sys/ngc/p_render.h>\r\n//#include <sys/ngc/p_prim.h>\r\n//#include <sys/ngc/p_texman.h>\r\n//#include <sys/ngc/p_file.h>\r\n//#include <sys/ngc/p_dvd.h>\r\n//\r\n//#include \"sys/ngc/p_profile.h\"\r\n//\r\n//#include <gfx/nx.h>\r\n//\r\n//NsProfile _gpu( \"GPU\", 256 );\r\n//NsProfile _cpu( \"CPU\", 256 );\r\n//static volatile int _open = 0;\r\n//\r\n//NsCamera\t\t\tcamera2D;\r\n//int heaperror = 0;\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//extern void\t(*pIconCallback)( void );\r\n//\r\n////extern void* copyXFB;\r\n////extern void* dispXFB;\r\n////extern void* myXFB1;\r\n////extern void* myXFB2;\r\n//\r\n//namespace LoadScreen\r\n//{\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//#define vMAX_PIXEL_DATA_SIZE\t( 32767 * 16 )\r\n//\r\n//#define\tENABLE_LOADING_ICON\t\t1\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//class LoadingIconData\r\n//{\r\n//public:\r\n//\tint\t\t\tm_X;\r\n//\tint\t\t\tm_Y;\r\n//\tint\t\t\tm_FrameDelay;\r\n//\tNsTexture**\tm_Rasters;\r\n//\tint\t\t\tm_NumFrames;\r\n//};\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//static bool\t\t\t\ts_loading_screen_on\t\t= false;\r\n//static OSThread\t\t\ts_load_icon_thread;\r\n//static OSAlarm\t\t\ts_alarm;\r\n//static LoadingIconData\ts_load_icon_data\t\t= { 0 };\r\n////static char\t\t\t\ts_load_icon_thread_stack[4096]\t__attribute__ (( aligned( 16 )));\r\n//static volatile bool\ts_terminate_thread\t\t= false;\r\n//static volatile bool\ts_terminate_thread_done\t= false;\r\n//static bool\t\t\t\ts_thread_exists\t\t\t= false;\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void s_thread_loading_icon_alarm_handler( OSAlarm* alarm, OSContext* context )\r\n//{\r\n//\t// Check the thread has not been resumed yet...\r\n//\tif( OSIsThreadSuspended( &s_load_icon_thread ))\r\n//\t{\r\n//\t\tOSResumeThread( &s_load_icon_thread );\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void s_non_threaded_loading_icon( void )\r\n//{\r\n//\tLoadingIconData* p_data = (LoadingIconData*)&s_load_icon_data;\r\n//\r\n//\tstatic int\t\t\tcurrent_image = 0;\r\n//\tstatic Tmr::Time\ttime = 0;\r\n//\r\n//\tTmr::Time\t\t\ttime_now = Tmr::GetVblanks();\r\n//\r\n//\tif(( time_now < time ) || ( time_now > ( time +\tp_data->m_FrameDelay )))\r\n//\t{\r\n//\t\ttime = time_now;\r\n//\r\n//\t\tNsTexture* p_texture = p_data->m_Rasters[current_image];\r\n//\r\n//\t\tNsDisplay::begin();\r\n//\r\n//\t\tNsRender::begin();\r\n//\r\n////\t\tNsPrim::begin();\r\n//\t    GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\t\t// 3 = positions & uvs.\r\n//\t\tGXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n//\r\n//\t\tcamera2D.orthographic( 0, 0, 640, 448 );\r\n//\r\n//\t\tNsRender::setBlendMode( NsBlendMode_None, p_texture, (unsigned char)0 );\r\n//\r\n//\t\tGXClearVtxDesc();\r\n//\t\tGXSetVtxDesc( GX_VA_POS, GX_DIRECT );\r\n//\t\tGXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );\r\n//\t\tGX::SetChanMatColor( GX_COLOR0, (GXColor){ 128,128,128,128 });\r\n//\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\r\n//\t\tp_texture->upload( NsTexture_Wrap_Clamp );\r\n//\r\n//\t\tGXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t\tGXPosition3f32((float)p_data->m_X, (float)p_data->m_Y, -1.0f );\r\n//\t\tGXTexCoord2f32( 0.0f, 0.0f );\r\n//\t\tGXPosition3f32((float)p_data->m_X + (float)p_texture->m_width, (float)p_data->m_Y, -1.0f );\r\n//\t\tGXTexCoord2f32( 1.0f, 0.0f );\r\n//\t\tGXPosition3f32((float)p_data->m_X + (float)p_texture->m_width, (float)p_data->m_Y + (float)p_texture->m_height, -1.0f );\r\n//\t\tGXTexCoord2f32( 1.0f, 1.0f );\r\n//\t\tGXPosition3f32((float)p_data->m_X, (float)p_data->m_Y + (float)p_texture->m_height, -1.0f );\r\n//\t\tGXTexCoord2f32( 0.0f, 1.0f );\r\n//\t\tGXEnd();\r\n//\r\n////\t\tNsPrim::end();\r\n//\r\n//\t\tcamera2D.end();\r\n//\r\n//\t\tNsRender::end();\r\n//\r\n//\t\tNsDisplay::end( false );\r\n//\r\n//\t\tcurrent_image = ( current_image + 1 ) % p_data->m_NumFrames ;\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void* s_threaded_loading_icon( void* data )\r\n//{\r\n//\tLoadingIconData* p_data = (LoadingIconData*)data;\r\n//\r\n//\tint\t\tcurrent_image = 0;\r\n//\r\n//\twhile( 1 )\r\n//\t{\r\n//\t\tif( s_terminate_thread )\r\n//\t\t{\r\n//\t\t\t// This thread is done...\r\n//\t\t\ts_terminate_thread_done\t= true;\r\n//\t\t\treturn NULL;\r\n//\t\t}\r\n//\r\n//\t\tbool busy = /*NsModel::busy() | DVDError() |*/ heaperror;\r\n//\r\n//\t\t// Don't want to do draw anything whilst display lists are being built. Come back in a bit.\r\n//\t\tif( !busy )\r\n//\t\t{\r\n//\t\t\tNsTexture* p_texture = p_data->m_Rasters[current_image];\r\n//\r\n//\t\t\tNsDisplay::begin();\r\n//\t\t\tNsRender::begin();\r\n//\r\n//\t\t    GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\t\t// 3 = positions & uvs.\r\n//\t\t\tGXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n//\r\n//\t\t\tcamera2D.orthographic( 0, 0, 640, 448 );\r\n//\r\n//\t\t\tNsRender::setBlendMode( NsBlendMode_None, p_texture, (unsigned char)0 );\r\n//\r\n//\t\t\tGXClearVtxDesc();\r\n//\t\t\tGXSetVtxDesc( GX_VA_POS, GX_DIRECT );\r\n//\t\t\tGXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );\r\n//\t\t\tGX::SetChanMatColor( GX_COLOR0, (GXColor){ 128,128,128,128 });\r\n//\t\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\r\n//\t\t\tp_texture->upload( NsTexture_Wrap_Clamp );\r\n//\r\n//\t\t\tGXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t\t\tGXPosition3f32((float)p_data->m_X, (float)p_data->m_Y, -1.0f );\r\n//\t\t\tGXTexCoord2f32( 0.0f, 0.0f );\r\n//\t\t\tGXPosition3f32((float)p_data->m_X + (float)p_texture->m_width, (float)p_data->m_Y, -1.0f );\r\n//\t\t\tGXTexCoord2f32( 1.0f, 0.0f );\r\n//\t\t\tGXPosition3f32((float)p_data->m_X + (float)p_texture->m_width, (float)p_data->m_Y + (float)p_texture->m_height, -1.0f );\r\n//\t\t\tGXTexCoord2f32( 1.0f, 1.0f );\r\n//\t\t\tGXPosition3f32((float)p_data->m_X, (float)p_data->m_Y + (float)p_texture->m_height, -1.0f );\r\n//\t\t\tGXTexCoord2f32( 0.0f, 1.0f );\r\n//\t\t\tGXEnd();\r\n//\r\n//\t\t\tcamera2D.end();\r\n//\r\n//\t\t\tNsRender::end();\r\n//\t\t\tNsDisplay::end( false );\r\n//\r\n//\t\t\tcurrent_image = ( current_image + 1 ) % p_data->m_NumFrames ;\r\n//\t\t}\r\n//\r\n//\t\t// Go to sleep.\r\n//\t\tif( busy )\r\n//\t\t{\r\n//\t\t\t// Come back shortly.\r\n//\t\t\tOSSetAlarm( &s_alarm, OSMillisecondsToTicks( 50 ), s_thread_loading_icon_alarm_handler );\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\t// Come back in the proper time.\r\n//\t\t\tOSSetAlarm( &s_alarm, OSMillisecondsToTicks( s_load_icon_data.m_FrameDelay ), s_thread_loading_icon_alarm_handler );\r\n//\t\t}\r\n//\r\n//\t\tOSSuspendThread( &s_load_icon_thread );\r\n//\t}\r\n//}\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void SetLoadingIconProperties( int x, int y, int frame_delay, int num_frames, char* basename, char* ext )\r\n//{\r\n////\tint i;\r\n////\r\n////\tif( s_load_icon_data.m_NumFrames > 0  )\r\n////\t{   \r\n////\t\tfor( i = 0; i < s_load_icon_data.m_NumFrames; i++ )\r\n////\t\t{\r\n////\t\t\tdelete s_load_icon_data.m_Rasters[i];\r\n////\t\t}\r\n////\t\tdelete [] s_load_icon_data.m_Rasters;\r\n////\t}\r\n////\r\n////\ts_load_icon_data.m_X\t\t\t= x;\r\n////\ts_load_icon_data.m_Y\t\t\t= y;\r\n////\ts_load_icon_data.m_FrameDelay\t= ( frame_delay * 1000 ) / 60;\t\t// Convert from frames to milliseconds.\r\n//////\ts_load_icon_data.m_FrameDelay\t= frame_delay;\r\n////\ts_load_icon_data.m_NumFrames\t= num_frames;\r\n////\ts_load_icon_data.m_Rasters\t\t= new NsTexture*[s_load_icon_data.m_NumFrames];\r\n////\r\n////\tfor( i = 0; i < s_load_icon_data.m_NumFrames; i++ )\r\n////\t{\r\n////\t\tNsFile file;\r\n////\r\n////\t\tchar image_name[64];\r\n////\t\tsprintf( image_name, \"%s%d.%s\", basename, i+1, ext );\r\n////\r\n//// \t\tfile.open( image_name );\r\n////\t\tint filesize\t\t= file.size();\r\n////\t\tuint8 *pData\t\t= (uint8*)new uint8[filesize + 31];\r\n////\t\tpData\t\t\t\t= (uint8*)OSRoundUp32B( pData );\r\n////\t\tfile.read( pData, filesize );\r\n////\t\tfile.close();\r\n////\r\n////\t\tNsTexture *pTex\t\t= (NsTexture*)pData;\r\n////\t\tpData\t\t\t\t= (uint8*)&pTex[1];\r\n////\t\tpTex->m_pImage\t\t= pData;\r\n////\t\tpData\t\t\t   += ( pTex->m_width * pTex->m_height * pTex->m_depth ) / 8;\r\n////\t\tpTex->m_pPalette\t= pData;\r\n////\r\n////\t\ts_load_icon_data.m_Rasters[i] = pTex;\r\n////\t}\r\n//}\r\n//\r\n//void _start( void )\r\n//{\r\n//\t_gpu.start();\r\n//\t_open = 1;\r\n//}\r\n//\r\n//void _end( void )\r\n//{\r\n//\t_gpu.stop();\r\n//\t_open = 0;\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void Display( char* filename, bool just_freeze, bool blank )\r\n//{\r\n////\tfloat y = 0;\r\n////\r\n////\twhile ( 1 )\r\n////\t{\r\n////\t\tNx::CEngine::sPreRender();\t\t\r\n////\t\t\t\t\t \r\n//////\t\tNx::CEngine::sRenderWorld();\t\t\r\n////\r\n//////--------------------------------------------------\r\n////\r\n////\t\tNsCamera cam;\r\n////\t\tcam.orthographic( 0, 0, 640, 448 );\r\n////\r\n////\t\t// Draw the screen.\r\n////\t\tNsPrim::begin();\r\n////\r\n////\t\tcam.begin();\r\n////\r\n////\t\tNsRender::setBlendMode( NsBlendMode_None, NULL, (unsigned char)0 );\r\n////\r\n////\t\tNsPrim::box( 64, 64 + y, 640-64, 64+80 + y, (GXColor){0,32,64,128} );\r\n////\r\n////\t\ty += 1.0f;\r\n////\t\tif ( y > 256.0f ) y -= 256.0f;\r\n////\r\n////\t\tcam.end();\r\n////\r\n////\t\tNsPrim::end();\r\n////\r\n//////--------------------------------------------------\r\n////\r\n////\t\tNx::CEngine::sPostRender();\t\t\r\n////\t}\r\n//\t\r\n////\tSpt::SingletonPtr< Mlp::Manager > mlp_man;\r\n////\tTmr::Time start_time;\r\n////\r\n////#if 0\r\n////\tNsDisplay::setRenderStartCallback( _start );\r\n////\tNsDisplay::setRenderEndCallback( _end );\r\n////\r\n////\tcamera2D.orthographic ( 0, 0, 640, 448 );\r\n////\tint col = 0;\r\n////\r\n////\tNsDisplay::setRenderStartCallback( _start );\r\n////\tNsDisplay::setRenderEndCallback( _end );\r\n////\r\n////\twhile ( 1 ) {\r\n////\t\tNsDisplay::setBackgroundColor ( (GXColor){0,0,255,0} );\r\n////\t\tcol+=2;\r\n////\t\tif (col == 256) col = 0;\r\n////\r\n////\t\t// Draw the screen.\r\n////\t\tNsDisplay::begin();\r\n////\t\tNsRender::begin();\r\n////\t\tNsPrim::begin();\r\n////\r\n////\t\tcamera2D.begin();\r\n////\r\n////\t\t_cpu.start();\r\n////\r\n////\t\tNsRender::setBlendMode( NsBlendMode_None, NULL, (unsigned char)128 );\r\n////\r\n////\t\t\r\n////\t\tGXClearVtxDesc();\r\n////\t\tGXSetVtxDesc( GX_VA_POS, GX_DIRECT );\r\n////\r\n////\t\t// Set material color.\r\n////\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,col,128} );\r\n////\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n////\r\n////\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n////\r\n////\t\t\r\n////\t\tfor (int lp = 0; lp < 3000; lp++) {\r\n////\t\t\tfloat l = 64+col;\r\n////\t\t\tfloat t = 64;\r\n////\t\t\tfloat r = 64+2+col;\r\n////\t\t\tfloat b = 64+2;\r\n//////\t\t\tNsPrim::box ( 64+col, 64, 80+col, 80, (GXColor){255,255,col,128} );\r\n////\t\t\r\n////\t\t\t// Send coordinates.\r\n////\t\t\tGXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n////\t\t\t\tGXPosition3f32(l, t, -1.0f);\r\n////\t\t\t\tGXPosition3f32(r, t, -1.0f);\r\n////\t\t\t\tGXPosition3f32(r, b, -1.0f);\r\n////\t\t\t\tGXPosition3f32(l, b, -1.0f);\r\n////\t\t\tGXEnd();\r\n////\t\t}\r\n////\r\n////\t\t_cpu.stop();\r\n////\r\n//////\t\twhile ( _open );\r\n////\t\t_gpu.histogram( 576, 32, 608, 416, (GXColor){255,0,0,128} );\r\n////\t\t_cpu.histogram( 544, 32, 576, 416, (GXColor){0,255,0,128} );\r\n////\r\n////\t\tcamera2D.end();\r\n////\r\n////\t\tNsPrim::end();\r\n////\t\tNsRender::end();\r\n////\t\tNsDisplay::end( true );\r\n////\t}\r\n////#endif\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\r\n////\tif( s_loading_screen_on )\r\n////\t{\r\n////\t\treturn;\r\n////\t}\r\n////\r\n////\tstart_time = Tmr::GetTime();\r\n////\r\n////\tif( !just_freeze && !blank )\r\n////\t{\r\n////\t\t// Load in the screen.\r\n////\t\tNsFile\tfile;\r\n////\t\tNsTexture * pTex = (NsTexture *)file.load( filename );\r\n////\r\n////\t\t// Skip data.\r\n////\t\tuint8 * pData = (uint8 *)&pTex[1];\r\n////\t\tpTex->m_pImage = pData;\r\n////\t\tpData += ( pTex->m_width * pTex->m_height * pTex->m_depth ) / 8;\r\n////\t\tpTex->m_pPalette = pData;\r\n////\r\n////\t\tcamera2D.orthographic ( 0, 0, 640, 448 );\r\n////\t\tNsDisplay::setBackgroundColor ( (GXColor){0,0,0,0} );\r\n////\r\n////\t\tfor ( int lp = 0; lp < 2; lp++ )\r\n////\t\t{\r\n////\t\t\t// Draw the screen.\r\n////\t\t\tNsDisplay::begin();\r\n////\t\t\tNsRender::begin();\r\n////\t\t\tNsPrim::begin();\r\n////\r\n////\t\t\tcamera2D.begin();\r\n////\r\n////\t\t\tNsRender::setBlendMode( NsBlendMode_None, pTex, (unsigned char)0 );\r\n////\t\t\tNsPrim::sprite ( pTex, 0.0f, 0.0f, -1.0f );\r\n////\r\n////\t\t\tcamera2D.end();\r\n////\r\n////\t\t\tNsPrim::end();\r\n////\t\t\tNsRender::end();\r\n////\t\t\tNsDisplay::end( false );\r\n////\t\t}\r\n////\r\n////\t\t// Wait for it to finish.\r\n////\t\tNsDisplay::flush();\r\n////\r\n////\t\t// We're done.\r\n////\t\tdelete pTex;\r\n////\r\n////\t\t// Start the thread to display the animated loading icon.\r\n////#\t\tif ENABLE_LOADING_ICON\r\n//////\t\tpIconCallback = s_non_threaded_loading_icon;\r\n////\t\tBOOL rv = true;\r\n////\r\n////\t\ts_terminate_thread = false;\r\n////\r\n////\t\tmemset( &s_load_icon_thread, 0, sizeof( OSThread ));\r\n////\t\trv = OSCreateThread(\t&s_load_icon_thread,\r\n////\t\t\t\t\t\t\t\ts_threaded_loading_icon,\t\t\t\t\t\t\t\t\t\t// Entry function.\r\n////\t\t\t\t\t\t\t\t&s_load_icon_data,\t\t\t\t\t\t\t\t\t\t\t\t// Argument for start function.\r\n////\t\t\t\t\t\t\t\ts_load_icon_thread_stack + sizeof( s_load_icon_thread_stack ),\t// Stack base (stack grows down).\r\n////\t\t\t\t\t\t\t\tsizeof( s_load_icon_thread_stack ),\t\t\t\t\t\t\t\t// Stack size in bytes.\r\n////\t\t\t\t\t\t\t\t1,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Thread priority.\r\n////\t\t\t\t\t\t\t\tOS_THREAD_ATTR_DETACH  );\t\t\t\t\t\t\t\t\t\t// Thread attributes.\r\n////\t\tDbg_MsgAssert( rv, ( \"Failed to create thread\" ));\r\n////\r\n////\t\tif( rv )\r\n////\t\t{\r\n////\t\t\ts_thread_exists = true;\r\n//////\t\t\tOSResumeThread( &s_load_icon_thread );\r\n////\t\t\tOSSetAlarm( &s_alarm, OSMillisecondsToTicks( s_load_icon_data.m_FrameDelay ), s_thread_loading_icon_alarm_handler );\r\n////\t\t}\r\n////#\t\tendif // ENABLE_LOADING_ICON\r\n////\t}\r\n////\telse\r\n////\t{\r\n////\t\t// Wait a couple of VBlanks for RW stuff to disappear\r\n////\t\t// Mick: so there is no pending page flip\r\n////\t\twhile( Tmr::GetVblanks() - start_time < 2 );\t\t\r\n////\t\t\r\n////\t\t// not loading, just freezing, maybe should copy current buffer over second buffer?\r\n////\t\tif( blank )\r\n////\t\t{\r\n////\t\t\t// Need to clear the screen here.\r\n//////\t\t\tRpSkySuspend( );\t // Turn or Renderwware inputs and stuff\r\n//////\t\t    Flx::clearGsMem(0x00, 0x00, 0x00, 640, 448*2);\r\n//////\t\t\tRpSkyResume( );\t\t // and trun em back on, with the screen nice and blank...\r\n////\t\t}\r\n////\t}\r\n////\ts_loading_screen_on = true;\r\n////\r\n////\tmlp_man->PauseDisplayTasks( true ); \r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//\r\n//void Hide( void )\r\n//{\r\n//#\tif ENABLE_LOADING_ICON\r\n//\tif( s_thread_exists )\r\n//\t{\r\n//\t\ts_terminate_thread_done\t= false;\r\n//\t\ts_terminate_thread = true;\r\n//\r\n//\t\t// Cancel the alarm and resume the thread.\r\n////\t\tOSCancelAlarm( &s_alarm );\r\n////\t\tOSResumeThread( &s_load_icon_thread );\r\n//\r\n//\t\twhile( !s_terminate_thread_done );\r\n//\r\n//\t\ts_thread_exists = false;\r\n////\t\tpIconCallback = NULL;\r\n//\r\n//\t\tVISetBlack( TRUE );\r\n//\t\tVIFlush();\r\n//\t\tVIWaitForRetrace();\r\n//\t\tNsDisplay::flush();\r\n//\t\tVISetBlack( FALSE );\r\n//\t\tVIFlush();\r\n//\t\tVIWaitForRetrace();\r\n//\t}\r\n//#\tendif // ENABLE_LOADING_ICON\r\n//\r\n//\tSpt::SingletonPtr< Mlp::Manager >\tmlp_man;\r\n//\tmlp_man->PauseDisplayTasks( false ); \r\n//\r\n//\tif( !s_loading_screen_on )\r\n//\t{\r\n//\t\treturn;\r\n//\t}\r\n//\r\n//\ts_loading_screen_on = false;\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//\r\n//void\tStartProgressBar( char* tick_image, int num_ticks, int x, int y )\r\n//{\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//\r\n//void\tProgressTick( int num_ticks )\r\n//{\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//\r\n//void\tEndProgressBar( void )\r\n//{\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//\r\n//} // namespace LoadScreen\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_memview.cpp",
    "content": "//////////////////////////////////////////////////////\r\n// p_memview.cpp\r\n//\r\n// code for tracking memory usage, and displaying it in a graphical manner\r\n// keeps extra info about allocated blocks\r\n// including the call stack, so we can print out information\r\n// about specific allocated blocks\r\n// which we will select using the graphical memory browser\r\n//\r\n//\r\n// tried to use a little of the task system as possible\r\n// so we can run the inspector\r\n// without it messing with the heap it inspects\r\n//\r\n//\r\n\r\n\r\nextern char _mem_dump_start[];\r\nextern char _map_file_start[];\r\nextern char _symbols_start[];\r\nextern char _callstack_start[];\r\nextern char _code_end[];\r\nextern char\t_std_mem_end[];\r\nextern char\t_stack_size[];\r\n\r\nextern char __text_org[];\r\nextern char __data_org[];\r\nextern char __rodata_org[];\r\nextern char __bss_org[];\r\n\r\nextern char __rodata_orgend[];\r\nextern char __bss_objend[];\r\nextern char __text_objend[];\r\n\r\n//extern char _rwheapdebug_start[];\r\n\r\n\t\t\t \r\n#define\tSTACKDEPTH  30\t\t\t \r\n\r\n\r\n\t\t\t \r\nextern \"C\"\t\t\t\t \r\n{\r\nextern void* ENTRYPOINT;\t\t\r\n}\r\n\r\n#include <gfx/gfxman.h>\r\n#include <gfx/nxviewport.h>\r\n#include <gel/inpman.h>\t\t\t\t\t// needed for buttons\r\n#include <gfx/ngps/p_memview.h>\r\n#include <sys/file/filesys.h> \t\t\t// needed for loading map file\r\n#include <gel/scripting/script.h>\r\n\r\n#include <stdio.h>\r\n#include <string.h>\r\n\r\n\r\n#include <sys\\mem\\memman.h>\r\n#include <sys\\mem\\heap.h>\r\n#include <sys\\mem\\region.h>\r\n#include <sys/config/config.h>\r\n\r\n// needed for some VerticalMenu specific debugging\t\t\t\t\t\t\t\r\n#include <core/support.h>\r\n#include <core/list.h>\r\n#include <core/String/CString.h>\r\n\r\n\r\nextern volatile int\ttest_vblanks;\r\n\r\n\r\nclass CCallStack\r\n{\r\npublic:\r\n\tvoid Append(CCallStack *p);\r\n\tvoid Remove();\r\n\tvoid InitHead();\r\n\tint\tused;\r\n\tint\tsize;\r\n\tCCallStack *pNext;\r\n\tCCallStack *pPrev;\r\n\tint\taddr[STACKDEPTH];\r\n\tuint32\tflags;\r\n\tMem::Allocator::BlockHeader * pBlock;\t// pointer to block that has this callstack\r\n\r\n};\r\n\r\nCCallStack\t\tfree_list;\t// list of created objects\r\nCCallStack\t\tused_list;\t// list of created objects\r\n\r\n// init a node, so it can act as the head\t\t\t \r\ninline void CCallStack::InitHead()\r\n{\r\n\tpPrev = this;\r\n\tpNext = this;\r\n}\r\n\t\r\n// append node p to this node (after it)\t\t\t\t\t\t\t\t\t \r\ninline void CCallStack::Append(CCallStack *p)\r\n{\r\n\r\n\tp->pNext = this->pNext;\r\n\tp->pPrev = this;\r\n\tthis->pNext = p;\r\n\tp->pNext->pPrev = p;\r\n}\r\n\r\n// simply unlink it from the list\t\t\t   \r\ninline void CCallStack::Remove()\r\n{\r\n\tpPrev->pNext = pNext;\r\n\tpNext->pPrev = pPrev;\r\n}\r\n\r\n\r\n\t\t\t\t\t\t\r\n//CCallStack * CallStack_FirstFree;\r\n//CCallStack * CallStack_FirstUsed; \r\n\r\nstatic int MemView_Active = 0;\r\n\r\n\r\n\r\n#define\tMAX_CALLSTACK (8192 * 8)\t\t// we got 8 mb, woo woo.\r\n\r\n\r\nstatic float step = 128.0f;\r\n\r\n\r\n//static char HexByte(char a)\r\n//{\r\n//\tif (a >= '0' && a <='9')\r\n//\t{\r\n//\t\treturn a-'0';\r\n//\t}\r\n//\tif (a >= 'A' && a <='F')\r\n//\t{\r\n//\t\treturn 10 + a-'A';\r\n//\t}\r\n//\tif (a >= 'a' && a <='f')\r\n//\t{\r\n//\t\treturn 10 + a-'a';\r\n//\t}\r\n//\r\n//\t// should really be an error, but just ignore it and return 0\r\n//\t// as this is only used for parsing the map file\t\r\n//\treturn 0;\r\n//\t\r\n//\t\r\n//}\r\n//\r\n//\r\n//static int doneonce = 0;\r\n\r\n\r\nchar *MemView_GetFunctionName(int pc, int *p_size)\r\n{\r\n//\r\n//\tif (!pc)\r\n//\t{\r\n//\t\treturn \"NULL\";\r\n//\t}\r\n//\t\t\t\t   \r\n//\t// given an address, return the name of the function\r\n//\t// does this by intially loading and buuilding a list of\r\n//\t// all the start points, and names, of all the functions\r\n//\t// by loading the skate3.map\r\n//\r\n//\t\r\n//\tstatic int symbols = 0;\r\n//\t\r\n//\tif (!doneonce)\r\n//\t{\r\n//\t\r\n////\t\tmdl.m_fd = sceOpen( \"host:ctrl_out.dat\", SCE_RDWR );\r\n/////\t\tsceRead( mdl.m_fd, mdl.m_recorded_data, 72000 * sizeof( Inp::RecordedData ));\r\n////\t\tsceClose( mdl.m_fd );\r\n//\r\n//\r\n//\t\t#ifdef\t__NOPT_CDROM__OLD\r\n//\t\tint pFP= sceOpen(\"host:..\\\\build\\\\ngpsgnu\\\\skate4c.map\", SCE_RDONLY);\t\t\r\n//\t\t#else\r\n//\t\tint pFP= sceOpen(\"host:..\\\\build\\\\ngpsgnu\\\\skate4.map\", SCE_RDONLY);\t\t\r\n//\t\t#endif\r\n//\r\n//\t\tif (!pFP)\r\n//\t\t{\r\n//\t\t\treturn \"(skate4.map not loaded yet)\";\r\n//\t\t}\r\n//\r\n//\r\n//\t\tdoneonce = 1;\r\n//\t\r\n//\t\t// Open the qb file and load it into memory.\r\n//\t\t//int FileSize = ((skyFile*)pFP)->SOF\t\t\r\n////\t\tint FileSize = File::GetFileSize(pFP);\r\n//\t\tchar *pQB= _map_file_start ;\r\n//\t\tsceRead(pFP,pQB,4000000);\r\n//\t\tsceClose(pFP);\r\n//\t\t\r\n//\t\t// Now the file is loaded, we need to extract all the functions\r\n//\t\t// so, search for the text \r\n//\t\t\r\n//\t\tchar *p = strstr(pQB,\"address order\");\r\n//\t\tint\t *d = (int*)_symbols_start; \r\n//\t\twhile (*p!=0x0a) p++;\t\t// skip to start of next line\r\n//\t\tp++;\t\t\t\t\t\t// skip over 0a\r\n//\t\twhile (*p)\r\n//\t\t{\r\n//\t\t\tp++;\t\t\t\t\t// skip over the space\r\n//\t\t\t// the next 8 characters are the address in upper case hex\r\n//\t\t\tint addr = 0;\r\n//\t\t\tfor (int i=0;i<8;i++)\r\n//\t\t\t{\r\n//\t\t\t\taddr <<= 4;\r\n//\t\t\t\taddr += HexByte(*p++);\r\n//\t\t\t}\r\n//\t\t\tp+= 2;\t\t\t// skip two spaces\r\n//\t\t\t\r\n//\t\t\t// the next 8 characters are the size in upper case hex\r\n//\t\t\tint size = 0;\r\n//\t\t\tfor (int i=0;i<8;i++)\r\n//\t\t\t{\r\n//\t\t\t\tsize <<= 4;\r\n//\t\t\t\tsize += HexByte(*p++);\r\n//\t\t\t}\r\n//\t\t\t\r\n//\t\t\tp+= 2;\t\t\t// skip two spaces\r\n//\t\t\t\r\n//\r\n//\t\t\t// only store symbols of non-zero size\r\n//\t\t\t// otherwise, we get confused by having things like _bss_size in there\r\n//\t\t\t// as they are not addresses, they just look like them, being so big...\r\n//\t\t\tif (size || (addr >(int) __text_objend))\r\n//\t\t\t{\r\n//\t\t\t\t*d++ = addr;\t\t// store the address of the symbol\r\n//\t\t\t\t*d++ = (int)p;\t\t\t// store the start of the symbol name\r\n//\t\t\t\tsymbols++;\t\t \t// one more symbol\r\n//\t\t\t}\r\n//\t\t\t\r\n//\t\t\t// search for first space, or CF, and replace with a 0\r\n//\t\t\t// that way we ignore the \"unmangled\" version of the function\r\n//\t\t\twhile (*p && /**p!=' ' &&*/ *p!=0x0a && *p!='(' && *p != 0x0d) p++;\t\r\n//\t\t\t*p++ = 0;\r\n//\t\t\t\r\n//\r\n//\t\t\t// skip to LF, and replace the \t\t\t\r\n//\t\t\twhile (*p && *p!=0x0a) p++;\t\t// skip to start of next line\r\n//\t\t\tp++;\t\t\t\t\t\t// skip over 0a, will now be at the space on next line\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t\r\n//\tint\t *s = (int*)_symbols_start; \r\n//\r\n//// just serach the table\r\n//// (might want a binary search, but no real need for speed)\r\n//\tfor (int i=0;i<symbols;i++)\r\n//\t{\r\n//\t\r\n//\t\tint addr = *s;\r\n//\t\tif (addr > pc)\t \t\t// if this one is above the pc\r\n//\t\t{\r\n//\t\t\t*p_size = addr-s[-2];\t\t// calculate the size of the function\r\n//\t\t\treturn (char*) (s[-1]);\t\t// then the previous one is the function\r\n//\t\t}\r\n//\t\ts += 2;\t\r\n//\t}\r\n\t\t \r\n\treturn \"UNKNOWN\";\r\n\t\r\n}\r\n\r\n// Modifed version of Jamie's unwind stack function\r\n// ignores the fp, and just goes directly off the sp\r\n// seems to work much better (and faster too)\r\nint DumpUnwindStack( int iMaxDepth, int *pDest )\r\n{\r\n//\tuint32* ra;\r\n//\tuint64* sp;\t\t\t\t\t\t\t\t\t\t\t// frame pointer\r\n//\tra = ((uint32*)DumpUnwindStack)+64;\t\t\t\t// fake point in function to unwind from (\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t\t// after the sd ra,0(sp), but before getting it back\r\n////\tasm ( \"daddu %0, $29, $0\" : \"=r\" (sp) );\t\t\t// get current sp\r\n//\tsp = (uint64*)OSGetStackPointer();\r\n//\r\n//\tif (!pDest)\r\n//\t{\r\n//\t\tprintf(\"\\n\");\r\n//\t}\r\n//\t\t\r\n//\tint icd = iMaxDepth;\t   \t\t\t\t\t\t\t// depth counter\r\n//\tuint32* last_ra = NULL;\r\n//\twhile ( icd-- )\r\n//\t{\r\n//\t\t\t/* scan instruction*/\r\n//\t\tuint32* pc = ra;\t\t\t\t\t\t\t\t// current pc, somewehre in middle of function\r\n//\t\tuint32 count = 4096;\t\t\t\t\t\t\t// enought to cover large functions\t(16k)\r\n//\t\twhile ( count-- )\r\n//\t\t{\r\n//\t\t\tuint32 ins = *pc;\t\t \t\t\t\t\t// get 32 bit instruction\r\n//\t\t\tif (((ins >> 16) & 0x7fff) == 0x7fbf)\t\t// sd ra,offset(sp)  (or sq, for .C files)\r\n//\t\t\t{\r\n//\t\t\t\tuint32 offset = *(short*)pc;\t\t\t// get offset (bottom 16 bits)\r\n//\t\t\t\tra = (uint32*)(sp[offset>>3]);\t\t\t\t\t// >>3 as it's at 64 bit word pointer\r\n//\t\t\t\tbreak;\r\n//\t\t\t}\r\n//\t\t\tpc--;\r\n//\t\t}\r\n//\t\twhile ( count--)\r\n//\t\t{\r\n//\t\t\tuint32 ins = *pc;\t\t \t\t\t\t\t// get 32 bit instruction\r\n//\t\t\tif ((ins >> 16) == 0x27bd)\t\t\t\t\t// addiu sp,sp,offset\r\n//\t\t\t{\r\n//\t\t\t\tint offset = *(short*)pc;\t\t\t\t// get offset (bottom 16 bits)\r\n//\t\t\t\tif (offset & 0x8000)\r\n//\t\t\t\t{\r\n//\t\t\t\t\toffset |= 0xffff0000;\r\n//\t\t\t\t}\r\n//\t\t\t\tsp = (uint64*)( (int)(sp) - (offset));\t   \r\n//\t\t\t\tbreak; \t\r\n//\t\t\t}\t\t\t\r\n//\t\t\tpc--;\r\n//\t\t}\r\n//\r\n////\t\tif (last_ra == ra)\r\n////\t\t{\r\n////\t\t\ticd++;\t\t\t// one more please....\r\n////\t\t}\r\n////\t\telse\r\n//\t\t{\r\n//\t\t\tlast_ra = ra;\r\n//\t\t\tif (pDest)\r\n//\t\t\t{\r\n//\t\t\t\t*pDest++ = (int)ra;\r\n//\t\t\t\t*pDest = 0;\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\tint size;\r\n//\t//\t\t\tprintf (\"sp = %p, ra = %p %s\\n\",sp,ra,MemView_GetFunctionName((int)ra));\r\n//\t\t\t\tprintf (\"%p: %s\\n\",ra,MemView_GetFunctionName((int)ra,&size));\r\n//\t\t\t}\r\n//\t\t}\r\n//\t    \r\n//\t\t// test to see if we have recursed up all the way...\r\n//\t\tif (abs(int((int)ra - (int)&ENTRYPOINT)) < 1024\r\n//\t\t   || (int)ra &3 \r\n//\t\t   || (int)ra < 0x100000\r\n//\t\t   || (int)ra > (int)_code_end\t\t// and check it's not totally crazy....\r\n//\t\t   )\r\n//\t\t{\r\n//\t\t\treturn 0;\r\n//\t\t}\r\n//\t\r\n//\t}\r\n//\treturn iMaxDepth - icd;\r\n\treturn 0;\r\n}\r\n\t\t\t\t   \r\n\t\t\t\t   \r\n//        mD_L2           = nBit( vD_L2 ),\r\n//        mD_R2           = nBit( vD_R2 ),\r\n//        mD_L1           = nBit( vD_L1 ),\r\n//        mD_R1           = nBit( vD_R1 ),\r\n//        mD_TRIANGLE     = nBit( vD_TRIANGLE ),\r\n//\t      mD_CIRCLE       = nBit( vD_CIRCLE ),\r\n//        mD_X            = nBit( vD_X ),\r\n//        mD_SQUARE       = nBit( vD_SQUARE ),\r\n//        mD_SELECT       = nBit( vD_SELECT ),\r\n//        mD_L3           = nBit( vD_L3 ),\r\n//        mD_R3           = nBit( vD_R3 ),\r\n//        mD_START        = nBit( vD_START ),\r\n//        mD_UP           = nBit( vD_UP ),\r\n//        mD_RIGHT        = nBit( vD_RIGHT ),\r\n//        mD_DOWN         = nBit( vD_DOWN ),\r\n//        mD_LEFT         = nBit( vD_LEFT ),\r\n\r\n\r\nvoid MemViewToggle()\r\n{\r\n\tMemView_Active ^=1;\r\n}\r\n\r\n\r\n\t \r\n\r\nvoid MemView_Alloc( void *v)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\r\n\r\n#ifdef\t__NOPT_CDROM__OLD\r\n   return;\r\n#endif \t\r\n\r\n#endif\r\n}\r\n\r\nvoid MemView_Free( void *v)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\t// Need to remove it from the used list\r\n\t// and add it back to the full list\r\n\t\r\n\tMem::Allocator::BlockHeader *p = (Mem::Allocator::BlockHeader *)v;\t\t\t\t\t\t  \r\n\t\t\t\t\t\t  \r\n#ifdef\t__NOPT_CDROM__OLD\r\n//   return;\r\n#endif \t\r\n\r\n\tCCallStack *c = (CCallStack*)p->mp_debug_data;\t\r\n\t\r\n\tif (!c)\r\n\t{\r\n\t\t// no debug data, so probably a re-alloc\r\n\t\t// should probably handle those later\r\n\t\treturn;\r\n\t}\r\n\r\n\t// we clear it, in case this header is re-used later \r\n\t// I'm not entirely sure how well this will work\r\n\tp->mp_debug_data = NULL;\t\r\n\tc->Remove();\r\n\tfree_list.Append(c);\r\n\t\r\n#endif\t\r\n}\r\n\r\n\r\nMem::Allocator::BlockHeader *MemView_FindBlock( int addr)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\r\n\t\r\n\tMem::Allocator::BlockHeader *pSmallestBlock\t= NULL;\r\n\tuint32 smallest_block_size = 100000000;\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\tfor (Mem::Heap* heap = mem_man.FirstHeap(); heap != NULL; heap = mem_man.NextHeap(heap))\r\n\t{\r\n\t\tMem::Allocator::BlockHeader *pBlock = (Mem::Allocator::BlockHeader *) heap->find_block((void*)addr);\t\r\n\t\tif (pBlock)\r\n\t\t{\r\n\t\t\tif (pBlock->mSize < smallest_block_size)\r\n\t\t\t{\r\n\t\t\t\tsmallest_block_size = pBlock->mSize;\r\n\t\t\t\tpSmallestBlock = pBlock;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn pSmallestBlock;\r\n#else\r\n\treturn NULL;\r\n#endif\r\n}\r\n\r\nchar * MemView_GetClassName(CCallStack *c)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\tint *ra = (int*)(c->addr[4]);\r\n\tif (!ra) return NULL;\r\n\tint count = STACKDEPTH-4;\r\n\twhile (count--)\r\n\t{\r\n\t\tint instruction = *ra++;\r\n\t\tif (instruction >> 24 == 0x0c)\r\n\t\t{\r\n\t\t\tint code = (instruction & 0xffffff)<<2;\r\n\t\t\tint size;\r\n\t\t\tchar *p = MemView_GetFunctionName(code,&size); \r\n\t\t\t// to tell if this is class or not\r\n\t\t\t// we see if the text is of the form  \r\n\t\t\t//    classname::classname (teminated by a 0)\r\n\t\t\t// as that indicates that it is a constructor\r\n\t\t\t// dude... this is where we need a regular expression....\r\n\t\t\tchar *end = p;\r\n\t\t\twhile (*end) end++;\t   \t\t\t\t\t\t// scan to end\r\n\t\t\twhile (end[-1] != ':' && end > p)\tend--;\t// skip to char after the last :\r\n\t\t\tchar *other = strstr(p,end);\t\t\t\t// find fist occurance of end of string\r\n\t\t\tif (other != end)\t\t\t\t\t\t\t// if different, then this is it!!\r\n\t\t\t{\r\n\t\t\t\treturn MemView_GetFunctionName(code,&size);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\r\n\treturn NULL;\r\n}\r\n\r\n\r\nvoid MemView_DumpBlockInfo(int cursor)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\t\r\n\tMem::Allocator::BlockHeader *pBlock = MemView_FindBlock(cursor);\r\n\tif (!pBlock)\r\n\t{\r\n\t\t// should search free blocks here???\r\n\t}\r\n\t// find this in the allocators used list\r\n\t// and say if it is free, or not\t\r\n\tif (pBlock == NULL)\r\n\t{\r\n//\t\tif (cursor > (int)__text_org && cursor < (int)__bss_objend)\t\t// check to see if in code/data\r\n//\t\t{\r\n//\t\t\t\r\n//\t\t\tif (cursor < (int)__data_org)\r\n//\t\t\t\tprintf(\"Code: \");\r\n//\t\t\telse if (cursor < (int)__rodata_org)\r\n//\t\t\t\tprintf(\"Data: \");\r\n//\t\t\telse if (cursor < (int)__bss_org)\r\n//\t\t\t\tprintf(\"RO-Data: \");\r\n//\t\t\telse \r\n//\t\t\t\tprintf(\"BSS: \");\r\n//\t\t\t\r\n//\t\t\r\n//\t\t\tint size;\r\n//\t\t\tchar *p_name = MemView_GetFunctionName(cursor,&size);\r\n//\t\t\tprintf ( \"%s, size %d\\n\",p_name,size);\r\n//\t\t}\r\n//\t\telse\r\n\t\t{\r\n\t\t\tprintf (\"Block Not Found\\n\");\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tvoid * p_start = (void*)((uint)pBlock + Mem::Allocator::BlockHeader::sSize);\r\n\t\tprintf (\"Block found, addr = %p, size = %d (Header = %d)\\n\",p_start,pBlock->mSize,Mem::Allocator::BlockHeader::sSize);\r\n\t\tCCallStack *c = (CCallStack*)pBlock->mp_debug_data;\r\n\t\tif (!c)\r\n\t\t{\r\n\t\t\t//printf (\"Block with No Debug Info!!\\n\");\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// assume this is a \"new\", then the fourth callstack ra will point to the \r\n\t\t\t// jal xxxxxx  instruction, where xxxxx is the constructor for the \r\n\t\t\t// or it might be sortly thereafter, so check 16 instructions\r\n\t\t\t\r\n\t\t\tchar * classname = MemView_GetClassName(c);\r\n\t\t\t\t\t\t\r\n\t\t\tif (classname)\r\n\t\t\t{\r\n\t\t\t\tprintf (\"CLASS: %s\\n\",classname);\t\t\r\n\t\t\t}\r\n\r\n\t\t\t// then list out the call stack (skipping the MemView_Alloc, as that's a given, and irrelevant);\t\t\t\r\n\t\t\r\n\t\t\tint *p = c->addr + 1;\r\n\t\t\twhile (p[1])\t\t\t// also skip the ENTRYPOINT, just go back to main()\r\n\t\t\t{\r\n\t\t\t\tint size;\r\n\t\t\t\tprintf (\"%p: %s\\n\",(void*)*p,MemView_GetFunctionName(*p,&size));\r\n\t\t\t\tp++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\nstatic\tint\tblockstart;\r\n\r\nstatic float cursor;\r\n\r\nvoid \t\tMemView_Display()\r\n{\r\n\r\n//#ifdef\t__NOPT_CDROM__OLD\r\n//   return;\r\n//#endif \t\r\n//\r\n//\r\n//\tif (!MemView_Active)\r\n//\t{\r\n//\t\treturn;\r\n//\t}\r\n//\r\n//\tFlushCache( 0 );\r\n//\tsceGsSyncPath( 0, 0 );\r\n//\t\r\n//\t//perfrom the copying\r\n//\t// there are 512x256 words in the rectangle\r\n//\t// and 32768*1024 bytes in memory\r\n//\t// giving us a step of 256 (i.e, sample every 256th bytes)\r\n//\t\r\n//\t\r\n//\t// The start of the middle line will be at \r\n//\t//       start + 512 * 2 * 128 * step;\r\n//\t// then  start1 + 512 * 2 * 128 * step1\r\n//\t// for them to be the same, start + 512 * 2 * 128 * step = start1 + 512 * 2 * 128 * step1\r\n//\t// so start1 =  start + 512 * 2 * 128 * (step - step1)\r\n//\t\r\n//\t\r\n//\r\n//\tblockstart = 0;\r\n//\tint blockend = 0;\r\n//\t\r\n//\tstatic float last_start;\t\t\t\t \r\n//\t\r\n//\tfloat start = cursor - (512.0f * 2.0f * 128.0f * step);\r\n//\t\r\n//\tint i_cursor = (int)cursor;\r\n//\t\r\n//\tMem::Allocator::BlockHeader *pBlock = MemView_FindBlock(i_cursor);\r\n//\r\n//\tif (pBlock)\r\n//\t{\r\n//\t\tblockstart = (int)((uint)pBlock + Mem::Allocator::BlockHeader::sSize);\r\n//\t\tint size = pBlock->mSize;\r\n//\t\tblockend = (int)((int)blockstart + size);\r\n//\t}\r\n//\t\r\n//\tif (start != last_start)\r\n//\t{\r\n//\t\tlast_start = start;\r\n//\t\tprintf (\"\\nCursor Addr = %p\\n\",(void*)i_cursor);   \t\r\n//\t\tMemView_DumpBlockInfo(i_cursor);\r\n//\t}\r\n//\t\r\n//\t\r\n//\tstatic int color = 10 + (10<<5) ;\r\n////\tcolor ^= 5 << 10;\r\n//\t\r\n//\tfloat f_source = start;\r\n//\tfloat f_off = 0.0f;\r\n////\tuint16 *source = (uint16*)(intstart&~1);   \t\t// converting from a float to a pointer... yowza!!!\r\n//\tuint16 *dest  =  (uint16*)_mem_dump_start;\r\n//\tfor (int i=0;i<512*256-4096;i++)\r\n//\t{\r\n//\t\tuint16 *source = (uint16*)((int)(f_source + f_off) &~1);\t\t\r\n//\t\r\n//\t\tuint32 word;\r\n//\t\tif (source < (uint16*)0x00100000 || source >= (uint16*)(0x08000000))\r\n//\t\t{\r\n//\t\t\tword = (3<<10)+(3<<5)+(3);\t\t\t// grey for outside of memory\t\t\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tif (blockstart && (int)(source)>=blockstart && (int)(source) <blockend)\r\n//\t\t\t{\r\n//\t\t\t\tword = *source;\r\n//\t\t\t   \tword |= color;\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\tword = *source;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\t\t\r\n//\t\t*dest++ = word;\r\n//\t\t*dest++ = word;\r\n////\t\tsource += intstep;\t\t\t// 128 words = 256 bytes\r\n//\t\tf_off += step*2.0f;\t\t\t// 128 words = 256 bytes\t\t\r\n//\t}\r\n//\r\n//\t// need a flush cache, as the data probably has not been written yet...\r\n//\tFlushCache( 0 );\r\n//\r\n//\t//for (int i=0;i<1000000;i++);\t\t\t// bit more of a delay, to stop flickering\r\n//\r\n//\tsceGsLoadImage gs_simage;\r\n//\tsceGsLoadImage gs_pointer;\r\n//\t\r\n//\t\r\n//\tfor (int i=0;i<2;i++)\r\n//\t{\r\n//\t\tsceGsSetDefLoadImage( &gs_simage , 0 , 640 / 64, SCE_GS_PSMCT32,  \t\t// was SCE_GS_PSMCT16S\r\n//\t\t\t\t\t\t\t   64, 64 + 128*i, 512, 128 );\r\n//\t\tsceGsSetDefLoadImage( &gs_pointer, 0 , 640 / 64, SCE_GS_PSMCT32,\r\n//\t\t\t\t\t\t\t   32, 64 + 127, 32, 3 );\r\n//\t\t\r\n//\t\tFlushCache( 0 );\t\t\r\n//\t\tsceGsExecLoadImage( &gs_simage, ( u_long128 * )(_mem_dump_start + (512*128*4*i))\t\t );\r\n//\t\tsceGsExecLoadImage( &gs_pointer, ( u_long128 * )MemView_Display );\r\n//\t\tsceGsSyncPath( 0, 0 );\r\n//\t}\r\n//\r\n//\r\n//\t\r\n//\treturn;\r\n//\r\n}\r\n\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\r\n//static int num_used;\r\n//\r\n//static void ScanRegion(uint32 *p_start, uint32 *p_end)\r\n//{\r\n//\r\n//\tprintf (\"scanning from %p to %p\\n\",p_start,p_end);\r\n//\t// scan the whole range of memeory\r\n//\twhile (p_start<p_end)\r\n//\t{\r\n//\t\t// get value that might be a pointer\r\n//\t\tuint32 x = *p_start++;\r\n//\t\t// check to see if it's not odd, and it lays in the heap area\r\n//\t\tif (!(x&3) && x > (uint32)_code_end /*&& x < (uint32)_std_mem_end*/) // don't check for end now, as we have some debug heaps up there we want to include\r\n//\t\t{\r\n//\t\t\t// check to see if it points to one of the heap members\r\n//\t\t\t\r\n//\t\t\tuint32 *p_refs = (uint32*)_mem_dump_start;\r\n//\t\t\t\r\n//\t\t#if 0\r\n//\t\t\tfor (int i=0;i<num_used;i++)\r\n//\t\t\t{\r\n//\t\t\t\tif (*p_refs == x)\t  \t\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// got it, increment the reference counter\r\n//\t\t\t\t\tp_refs[1]++;\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\t}\r\n//\t\t\t\tp_refs+=2;\r\n//\t\t\t} \r\n//\t\t\t\r\n//\t\t#else\r\n//\t\t\r\n//\t\t\t// we want to do it twice, once for x, and once for x+16\r\n//\t\t\t// the reason being, a class this is allocated with\r\n//\t\t\t// the [] operator will actually start 16 bytes before the ref\r\n//\t\t\t// so we need to go back 16 bytes when looking for the block\r\n//\r\n//\t\t\tint oldx = x;\r\n//\t\t\tfor (int i=0;i<2;i++)\r\n//\t\t\t{\r\n//\t\t\t\r\n//\t\t\t\t// binary search folks.....\r\n//\t\t\t\tint low = 0;\r\n//\t\t\t\tint high = num_used-1;\r\n//\t\t\t\twhile (1)\r\n//\t\t\t\t{\r\n//\t\t\t\t\tint mid = (low + high) /2;\r\n//\t\t\t\t\tif (p_refs[mid<<1] == x)\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tp_refs[(mid<<1)+1] ++;\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\tif (high == low)\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\tif (p_refs[mid<<1] > x)\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\thigh = mid;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\telse\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\t// if the low point is already the same as the mid point\r\n//\t\t\t\t\t\t// then the only way to go is up!\r\n//\t\t\t\t\t\t// as this will only occur when low + 1 == high\r\n//\t\t\t\t\t\tif (low == mid)\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tlow = high;\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t\telse\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tlow = mid;\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t}\t\t\t\t\r\n//\t\t\t\t}\r\n//\t\t\t\tx -= 16;\r\n//\t\t\t}\r\n//\t\t\tx = oldx;\r\n//\t\t#endif\t\t\t\t\t\t  \t\t\r\n//\t\t}\r\n//\t}\r\n//\t\r\n//\t\r\n//}\r\n#endif\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__\r\nstatic uint32 *p_used;\t\t\r\n#endif\r\n\r\nint MemView_CountBlocks(Mem::Allocator::BlockHeader *p_header)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\tint num_used = 0;\r\n\twhile ( p_header )\r\n\t{\r\n\t\tvoid * p_start = (void*)((uint)p_header + Mem::Allocator::BlockHeader::sSize);\r\n\t\t\r\n\t\t*p_used++ = (uint32)p_start;\t \t\t// store the start of the block\r\n\t\t*p_used++ = 0;\t\t\t\t\t\t\t// store a count\r\n\t\tp_header = p_header->mp_next_used;\r\n\t\tnum_used++;\r\n\t}\r\n\treturn num_used;\r\n#else\r\n\treturn 0;\r\n#endif\r\n}\r\n\r\n\r\nint blockCompFunc( const void *arg1, const void *arg2 )\r\n{\r\n\tuint32 addr1 = (*(uint32*)arg1);\r\n\tuint32 addr2 = (*(uint32*)arg2);\r\n\r\n\tif ( addr1 == addr2 )\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\telse if ( addr1 < addr2 )\r\n\t{\r\n\t\treturn 1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn -1;\r\n\t}\r\n\r\n}\r\n\r\n\r\n// Find memory leaks\r\n// the algorithm is quite simple:\r\n// 1) Make a list of all \"used\" memory blocks, and set their usage count to 0\r\n// 2) Scan all of the heap, and the stack, for each word that looks like a pointer, \r\n//    check to see if it is in the list of \"used\", and increment the usage count if so\r\n// 3) Scan the list of used pointers, and check for any with usage == 0\r\n\r\n// NEED OT EXTEND FOR TOP_DOWN heap.....\t\t\r\n\t\t\r\nvoid MemView_FindLeaks()\r\n{\r\n//#ifdef\t__LINKED_LIST_HEAP__\r\n//\t\tp_used  =  (uint32*)_mem_dump_start;\t\t\r\n//\t\tnum_used = 0;\r\n//\t\tprintf (\"Counting blocks....\");\t\t\r\n//\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().BottomUpHeap()->first_block()); \r\n//\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().TopDownHeap()->first_block()); \r\n//\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().FrontEndHeap()->first_block()); \r\n//\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().NetworkHeap()->first_block()); \r\n//\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().ScriptHeap()->first_block()); \r\n//\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().SkaterHeap(0)->first_block()); \r\n////\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().DebugHeap()->first_block()); \r\n//\t\tprintf (\" %d\\n\",num_used);\r\n//\t\tprintf (\"Sorting .....\\n\");\t\t\t\r\n//\t\t// Now we've done that, let's sort the list, so we can use a binary search later\r\n//\t\t\r\n//\t\t\r\n//\t\t#if 1\r\n//\t\tuint32 *p_top  =  (uint32*)_mem_dump_start;\t\t\r\n//\t\tfor\t(int i = 0;i<num_used-1;i++)\r\n//\t\t{\r\n//\t\t\tuint32 top = *p_top;\r\n//\t\t\tuint32 *p_scan  =  p_top+2;\t  \r\n//\t\t\tuint32 *p_best = p_top;  \t\t\t\r\n//\t\t\tfor (int j = i;j<num_used-1;j++)\r\n//\t\t\t{\r\n//\t\t\t\tuint32 scan = *p_scan;\r\n//\t\t\t\tif (scan < top)\r\n//\t\t\t\t{\r\n//\t\t\t\t\ttop = scan;\r\n//\t\t\t\t\tp_best = p_scan;\r\n//\t\t\t\t}\r\n//\t\t\t\tp_scan+=2;\r\n//\t\t\t}\r\n//\t\t\tuint64 t = *(uint64*)p_top;\r\n//\t\t\t*(uint64*)p_top = *(uint64*)p_best;\r\n//\t\t\t*(uint64*)p_best = t;\t\t\r\n//\t\t\tp_top +=2;\r\n//\t\t}\r\n//\t\t#else\r\n//\r\n//\t\t// Use a quicksort\r\n//\t\t// (NOT WORKING)\r\n//\t\tqsort( (uint32*)_mem_dump_start, num_used, 8, blockCompFunc );\r\n//\t\t\r\n//\t\t#endif\r\n//\r\n//\r\n//\r\n//\t\t// now scan all appropiate regions of memory\r\n//\t\t\r\n//\t\t// First scan the code, data and regular heap\r\n//\t\tScanRegion((uint32*)_code_end,(uint32*)_std_mem_end);\r\n//\r\n//\t\t// Next scan the alternate area or memory, where the script heap goes\r\n////\t\tScanRegion((uint32*)(_rwheapdebug_start),(uint32*)(_rwheapdebug_start + 0x04970000 - 0x04500000));\r\n//\r\n//\t\t// then scan the stack\r\n//\t\tuint64* sp;\t\t\t\t\t\t\t\t\t\t\t// frame pointer\r\n////\t\tasm ( \"daddu %0, $29, $0\" : \"=r\" (sp) );\t\t\t// get current sp\r\n//\t\tsp = (uint64*)OSGetStackPointer();\r\n//\t\tuint32 *stack_start = (uint32*)sp;\r\n//\t\t// stack end is stack start rounded up by the stack size\r\n//\t\t// assumes that things are nice powers of 2\r\n//\t\tuint32 *stack_end = (uint32*)(((int)(stack_start) + (int)_stack_size-4) & ~(int)(_stack_size-1));\r\n//\t\tScanRegion(stack_start,stack_end);\r\n//\t\t\r\n//\t\t\r\n//\r\n//\r\n//\r\n//\r\n//\t\tbool\tLeaksFound = false;\r\n//\r\n//\t\t// then check for any with zero reference\r\n//\t\tuint32 *p_refs = (uint32*)_mem_dump_start;\r\n//\t\tfor (int i=0;i<num_used;i++)\r\n//\t\t{\r\n//\t\t\tif (!p_refs[1])\t  \t\r\n//\t\t\t{\r\n//\t\t\t\tuint32 addr = *p_refs;\r\n//\t\t\t\tif (!LeaksFound)\r\n//\t\t\t\t{\r\n//\t\t\t\t\tprintf (\"-----------------------------------------------------------------------\\n\");\r\n//\t\t\t\t\tprintf (\"-----------  LEAKS FOUND !!!!!!!!!!!!!!           ---------------------\\n\");\r\n//\t\t\t\t\tprintf (\"-----------------------------------------------------------------------\\n\");\r\n//\t\t\t\t\tLeaksFound = true;\r\n//\t\t\t\t}\r\n//\t\t\t\tprintf (\"\\nPossible leak, addr %p\\n\",(void*)addr);\t\t\t\t\r\n//\t\t\t\tMemView_DumpBlockInfo(addr);\r\n//\t\t\t}\r\n//\t\t\tp_refs+=2;\r\n//\t\t}\t\t\t\r\n//\t\t\r\n//\t\tif (LeaksFound)\r\n//\t\t{\r\n//\t\t\tprintf (\"-----------------------------------------------------------------------\\n\");\r\n//\t\t\tprintf (\"-----------  END OF LEAKS                         ---------------------\\n\");\r\n//\t\t\tprintf (\"-----------------------------------------------------------------------\\n\");\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tprintf (\"-----------  NO LEAKS DETECTED!!!  ---------------------\\n\");\r\n//\t\t}\r\n//#endif\r\n}\r\n\r\n\r\n// Given a block addr, then search all the other blocks to see \r\n// which block contains a reference to this block\r\n// and recursivly step back through the blocks until\r\n// we can't find another reference, or the address is not in a block\r\nvoid MemView_DumpRefs(int addr)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\tprintf (\"\\n\\nDumping references for %p\\n\",(void*)addr);\r\n\tMemView_DumpBlockInfo(addr);\r\n\tuint32 *p_first = NULL;\t\r\n\tint last_addr = 0;\r\n\tint count = 0 ;\r\n\twhile (1)\r\n\t{\r\n\t\t// now just do a simple search through the heap reagion\r\n\t\t// to find another reference\r\n\t\tuint32 *p_start = (uint32*)_code_end;\r\n\t\tuint32 *p_end = (uint32*)_std_mem_end;\r\n\t\twhile (p_start<p_end && count < 10)\r\n\t\t{\r\n\t\t\tif (*p_start == (uint32)addr && p_start != (uint32*)&blockstart)\r\n\t\t\t{\r\n\t\t\t\tcount++;\r\n\t\t\t\tprintf (\"\\nReference level %d in %p\\n\",count,(void*)p_start);\r\n\t\t\t\tMemView_DumpBlockInfo((int)p_start);\r\n\t\t\t\taddr = (int)p_start;\r\n\r\n\r\n\t\t\t\tMem::Allocator::BlockHeader *pBlock = MemView_FindBlock(addr);\t\t\t\t\r\n\t\t\t\taddr = (int)((uint)pBlock + Mem::Allocator::BlockHeader::sSize);\r\n\t\t\t\tif (addr == (int) p_first || addr == last_addr)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf (\"LOOPING .....\\n\");\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tlast_addr = addr;\r\n\t\t\t\tif (!p_first)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_first = (uint32*)addr;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\tp_start++;\r\n\t\t}\r\n\t\tif (count >= 10)\r\n\t\t{\r\n\t\t\tprintf (\"Stopping after %d refs\\n\",count);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (p_start >= p_end)\r\n\t\t{\r\n\t\t\tprintf (\"No more References Found in heap \\n\");\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\n// Find the first block in the free list\r\n// if no free blocks, then return\r\n// scan all used blocks, and print out the info for all the blocks\r\n// that have an address above the first free block\r\nvoid MemView_DumpFragments(Mem::Heap *pHeap)\r\n{\r\n\t#ifdef\t__LINKED_LIST_HEAP__    \r\n\r\n\tif (!pHeap->mFreeBlocks.m_count)\r\n\t{\r\n\t\tprintf (\"NO Fragmentation\\n\");\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif (!pHeap->mp_context->mp_free_list)\r\n\t{\r\n\t\tprintf (\"!!!!!! No free list, but there are %d free blocks???\\n\",pHeap->mFreeBlocks.m_count);\r\n\t\treturn;\r\n\t}\r\n\r\n\tMem::Allocator::BlockHeader *p_free = pHeap->mp_context->mp_free_list;\r\n\t\r\n\twhile (p_free->mSize < 10000)\r\n\t{\r\n\t\tMem::Allocator::BlockHeader *p_next = p_free->mpNext;\r\n\t\tif (!p_next)\r\n\t\t{\r\n\t\t\tprintf (\"Did not find a free block >10K ?????\\n\");\r\n\t\t}\t\t\r\n\t\tp_free = p_next;\r\n\t}\r\n\t\r\n\tMem::Allocator::BlockHeader *p_full = pHeap->mp_context->mp_used_list;\r\n\t\r\n\tprintf (\"!!!!!! Free list starts at %p\\n\",p_free);\r\n\t\r\n\r\n\t// The first p_free will be the start of fragmentations\r\n\twhile (p_full)\r\n\t{\r\n\t\tif (p_full > p_free)\r\n\t\t{\r\n\t\t\t//printf (\"\\nFramgented Block\\n\\n\");\r\n\t\t\tvoid * p_start = (void*)((uint)p_full + Mem::Allocator::BlockHeader::sSize);\r\n\t\t\tMemView_DumpBlockInfo((int)p_start);\r\n\t\t\tfor (int xx=0;xx<1000000;xx++);\t\t// little delay, to allow printfs to work\r\n\t\t}\r\n\t\tp_full = p_full->mp_next_used;\r\n\t}\r\n\t#endif\r\n}\r\n\r\nvoid MemView_DumpHeap(Mem::Heap *pHeap, uint32 mask)\r\n{\r\n\t#ifdef\t__LINKED_LIST_HEAP__    \r\n\r\n//\tMem::Allocator::BlockHeader *p_free = pHeap->mp_context->mp_free_list;\r\n\tMem::Allocator::BlockHeader *p_full = pHeap->mp_context->mp_used_list;\r\n\t\r\n\t// The first p_free will be the start of fragmentations\r\n\twhile (p_full)\r\n\t{\r\n//\t\tif (p_full > p_free)\r\n//\t\tCCallStack *c = (CCallStack*)p_full->mp_debug_data;\t\r\n//\t\tif (!mask || !c || !(c->flags && mask))\r\n\t\t{\r\n\t\t\tprintf (\"\\n\");\r\n\t\t\tvoid * p_start = (void*)((uint)p_full + Mem::Allocator::BlockHeader::sSize);\r\n\t\t\tMemView_DumpBlockInfo((int)p_start);\r\n\t\t}\r\n\t\tp_full = p_full->mp_next_used;\r\n\t}\r\n\t#endif\r\n}\r\n\r\n\r\n\r\nvoid MemView_DumpBottomFragments()\r\n{\r\n\r\n\tMemView_DumpFragments(Mem::Manager::sHandle().BottomUpHeap());\r\n}\r\n\r\nvoid MemView_DumpTopFragments()\r\n{\r\n\r\n\tMemView_DumpFragments(Mem::Manager::sHandle().TopDownHeap());\r\n}\r\n\r\n\r\n\r\n/*\r\nclass CCallStack\r\n{\r\npublic:\r\n\tvoid Append(CCallStack *p);\r\n\tvoid Remove();\r\n\tvoid InitHead();\r\n\tint\tused;\r\n\tint\tsize;\r\n\tCCallStack *pNext;\r\n\tCCallStack *pPrev;\r\n\tint\taddr[STACKDEPTH];\r\n\r\n};\r\n*/\r\n\r\nstruct SBlockType\r\n{\r\n\tint\treturn_addr; \t\t\t// first meaningful return addr \r\n\t\r\n\tint\tsize;\t\t\t\t\t// size of block (if we want to sort by it\r\n\tint\ttotal;\t\t\t\t\t// total size of this type\r\n\tint\tactual;\t\t\t\t\t// actual total size, including headers\r\n\tchar *p_class;\t\t\t\t// points to class node \r\n\t\r\n\tint\tcount;\r\n};\r\n\r\n// scan throught the list of \"used\" blocks\r\n// and sort them into a list, organized by \"type\"\r\n// the \"type\" is determined by the first return address after\r\n// a callstack entry that is either \"Malloc\" or \"Spt::Class::operator new\"\r\n// the \"type\" is furthur sorted by either \"size\" or \"Class\"\r\n// where \"size\" is the size of the block (for a Malloc)\r\n// and \"Class\" is the type of class that constructed this block \r\n\r\n#define\tMAX_TYPES 10000\r\n\r\n\r\nvoid MemView_DumpAnalysis( SBlockType* blocks, int numBlocksToPrint )\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\t// Sorts the types, and print out totals\r\n\r\n\tint temp;\r\n\r\n\tfor (int i = 0; i < numBlocksToPrint; i++)\r\n\t{\r\n\t\tfor (int j = i+1;j<numBlocksToPrint;j++)\r\n\t\t{\r\n\t\t\tbool swap = false;\r\n\t\t\tif (blocks[i].actual < blocks[j].actual)\r\n\t\t\t{\r\n\t\t\t\tswap = true;\r\n\t\t\t}\r\n\r\n\t\t\tif (swap)\r\n\t\t\t{\r\n\t\t\t\tSBlockType t = blocks[i];\r\n\t\t\t\tblocks[i] = blocks[j];\r\n\t\t\t\tblocks[j] = t;\t\t\t\t\r\n\t\t\t}\t\t\t\r\n\t\t}\r\n\r\n\t\t// i is sorted, so print it out\r\n\t\tprintf (\"%7d bytes, (%6d hdrs) %4d blks, avg %6d bytes, class %s, function %s\\n\", \t\t\r\n\t\t\t\tblocks[i].actual,\r\n\t\t\t\tblocks[i].actual-blocks[i].total,\r\n\t\t\t\tblocks[i].count,\t\t\t\t \r\n\t\t\t\tblocks[i].total/blocks[i].count,\r\n\t\t\t\tblocks[i].p_class,\r\n\t\t\t\tMemView_GetFunctionName(blocks[i].return_addr,&temp)\r\n\t\t\t   );\t   \r\n\t\tfor (int xx=0;xx<2000000;xx++);\t\t// little delay, to allow printfs to work\r\n\t}\r\n#endif\r\n}\r\n\r\nvoid MemView_AnalyzeCallStack( CCallStack* pCallStack, SBlockType* pBlocks, int& num )\r\n{\r\n\t// for each block we find the three things:\r\n\t//  return_addr after Malloc or Spt::Class::operator new\r\n\t//  size\r\n\t//  class\r\n\r\n\tint\tsize = pCallStack->size;\t  \t// size is the only thing we know for sure\r\n\tint\treturn_addr = 0;\t\t\t\t// default unknown return address\r\n\tchar *p_class = \"not a class\";\r\n\tint latest = 1;\r\n\tint i = 0;\r\n\t\r\n\tfor ( i = 1; i < 8; i++ )\r\n\t{\r\n\t\tint xsize;\r\n\r\n\t\t/*\r\n\t\t// the types of call stack we may encounter:\r\n\t\t// need to \r\n\t\t\t0x10be48: Mem::Heap::allocate                                                   \r\n\t\t\t0x109914: Mem::Manager::New                                                     \r\n\t\t\t0x1035b0: Spt::Class::operator new                                              \r\n\t\t\t0x161094: Front::KeyboardControl::sCreateInstance   \r\n\r\n\t\t\t0x10be48: Mem::Heap::allocate                                                   \r\n\t\t\t0x109914: Mem::Manager::New                                                     \r\n\t\t\t0x10a150: Malloc                                                                \r\n\t\t\t0x222df8: _SkyBuildPktForUpLoadAlignedContiguousRectangle  \r\n\r\n\t\t\t0x10be48: Mem::Heap::allocate                                                   \r\n\t\t\t0x109914: Mem::Manager::New                                                     \r\n\t\t\t0x10a210: Malloc_FreeList                                                       \r\n\t\t\t0x257034: _rwFreeListAllocReal\r\n\t\t*/\r\n\r\n\t\tchar *p_name = MemView_GetFunctionName(pCallStack->addr[i],&xsize);\r\n\t\tif (!strcmp(\"Malloc\",p_name) \r\n\t\t\t|| !strcmp(\"Spt::Class::operator new\",p_name)\r\n\t\t\t|| !strcmp(\"Mem::Manager::New\",p_name)\r\n\t\t\t|| !strcmp(\"_rwFreeListAllocReal\",p_name))\r\n\t\t{\r\n\t\t\tlatest = i;\r\n\t\t}\r\n\t}\r\n\r\n\tif (latest != 1)\r\n\t{\r\n\t\treturn_addr = pCallStack->addr[latest+1];\r\n\t}\r\n\r\n\tp_class = MemView_GetClassName(pCallStack);\t\t\t\t// get class\r\n\t// right, now we have all the info on this block\r\n\t// let's see if we've got one just like it\r\n\r\n\t//\t\tif (!p_class && !MemView_GetFunctionName(return_addr,&temp))\r\n\t/*\t\t\r\n\t\t\tif (!return_addr)\r\n\t\t\t{\r\n\t\t\t\tfor (int i = 0;i<STACKDEPTH;i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf (\"%2d: >>%s<<\\n\",i,MemView_GetFunctionName(p->addr[i],&temp));\r\n\r\n\t\t\t\t}\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\t*/\r\n\t\r\n\t\t\t\t\t\t\t\t\t  \r\n\t// check if it is a string, and print it out, if so\t\t\t\t\t\r\n/*\t\r\n\tint temp;\t\t\t\t  \r\n\tif (!strcmp(\"Str::String::copy\",MemView_GetFunctionName(return_addr,&temp)))\r\n\t{\r\n\t\tprintf (\"String <%s>\\n\",(char*)((char*)(pCallStack->pBlock)+32)); \r\n\t}\r\n\t\r\n\t\r\n\tif (!strcmp(\"Front::VerticalMenu::sCreateInstance\",MemView_GetFunctionName(return_addr,&temp)))\r\n\t{\r\n\t\tvoid *p_start  =  (void*)((char*)(pCallStack->pBlock)+32);\r\n\t\tprintf (\"\\nVertical Menu \"); \r\n\t\t\r\n\t\tFront::ScreenElement *pV =  (Front::ScreenElement *)p_start;\r\n\t\tprintf (\" id = %s\\n\", Script::FindChecksumName(pV->GetID()));\r\n//\t\tMemView_DumpBlockInfo((int)p_start);\r\n\t\t\r\n\t}\t\r\n*/\t\r\n\r\n\t// check to see if this block is already included\r\n\tfor ( i = 0; i < num; i++ )\r\n\t{\r\n\t\tif ( pBlocks[i].p_class == p_class\r\n\t\t\t/*&& pBlocks[i].size == size */\r\n\t\t\t && pBlocks[i].return_addr == return_addr )\r\n\t\t{\r\n\t\t\tpBlocks[i].count++;\r\n\t\t\tpBlocks[i].total += size;\r\n\t\t\tpBlocks[i].actual += size + Mem::Allocator::BlockHeader::sSize;\r\n\t\t\tbreak;\t\t\t\t\r\n\t\t}\r\n\t}\r\n\r\n\t// if not, then add the block\r\n\tif ( i == num )\r\n\t{\r\n\t\tpBlocks[i].p_class = p_class;\r\n\t\tpBlocks[i].size = size;\r\n\t\tpBlocks[i].total = size;\r\n\t\tpBlocks[i].actual = size + Mem::Allocator::BlockHeader::sSize;\r\n\t\tpBlocks[i].return_addr = return_addr;\r\n\t\tpBlocks[i].count = 1;\r\n\t\tnum++;\r\n\t}\r\n}\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n//static int bbb = 0;\t   \t// compiler patch var, see below\r\n#endif\r\n\r\nvoid MemView_AnalyzeBlocks(uint32 mask)\r\n{\r\n//#ifdef\t__LINKED_LIST_HEAP__\r\n//\tSBlockType  *pBlocks = (SBlockType  *)_mem_dump_start;\t// temp memory\r\n//\tint\tnum_blocks = 0;\r\n//\tint num = 0;\r\n//\r\n//\tprintf (\"\\nAnalyzing blocks....\\n\");\r\n//\t\r\n//\tCCallStack *p = used_list.pNext;  \r\n//\twhile (p != &used_list)\r\n//\t{\r\n//\t\t// Get the actualy block we referred to\r\n////\t\tMem::Allocator::BlockHeader * pBlock = p->pBlock;\r\n////\t\tvoid * p_start = (void*)((uint)pBlock + Mem::Allocator::BlockHeader::sSize);\r\n//\t\t// Otionally check to see if it on the front end heap\r\n////\t\tif (Mem::SameContext(p_start,Mem::Manager::sHandle().FrontEndHeap()))\r\n//\t\t{\r\n//\t\t\tif (!mask || !(p->flags & mask))\r\n//\t\t\t{\r\n//\t\t\t\tMemView_AnalyzeCallStack( p, pBlocks, num );\t\t\t\r\n//\t\t\t\tnum_blocks++;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\tp = p->pNext; \r\n//\t}\r\n//\t\r\n//\tprintf (\"%d types, in %d total blocks\\n\", num, num_blocks); \r\n//\r\n//\tMemView_DumpAnalysis( pBlocks, num );\r\n//\tif (bbb)\r\n//\t{\r\n//\t\tMemView_DumpBottomFragments();\t\t\t// just to get it compiling \r\n//\t\tMemView_DumpTopFragments();\t\t\t// just to get it compiling \r\n//\t}\t\t\r\n//#endif\r\n}\r\n\r\n\r\nvoid MemView_MarkBlocks(uint32 mask)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\r\n\tCCallStack *p = used_list.pNext;  \r\n\twhile (p != &used_list)\r\n\t{\r\n\t\tp->flags |= mask;\r\n\t\t\r\n\t\tp = p->pNext;\r\n\t}\r\n#endif\r\n}\r\n\r\n\r\n\r\nvoid MemView_Input(uint buttons, uint makes, uint breaks)\r\n{\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n//\tif (makes & Inp::Data::mD_TRIANGLE)\r\n//\t{\r\n//\t\tMemView_Active = !MemView_Active;\r\n//\t}\r\n\r\n\r\n\tif (!MemView_Active)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t\t\t\t\t  \r\n\tfloat step1 = step;\r\n\t\r\n\tfloat zoom = 1.1f;\r\n\t\r\n\tfloat scroll = 4.0f;\r\n\r\n\t\r\n\r\n\r\n\r\n\tif (buttons & Inp::Data::mD_LEFT)\r\n\t{\r\n\t\tstep1 = step * zoom;\r\n\t}\r\n\tif (buttons & Inp::Data::mD_RIGHT)\r\n\t{\r\n\t\tstep1 = step / zoom;\r\n\t}\r\n\t\r\n\tif (buttons & Inp::Data::mD_UP)\r\n\t{\r\n//\t\tstart = start - scroll * 512.0f * 2.0f * step;\r\n\t\tcursor = cursor - scroll * 512.0f * 2.0f * step;\r\n\t}\r\n\tif (buttons & Inp::Data::mD_DOWN)\r\n\t{\r\n//\t\tstart = start + scroll * 512.0f * 2.0f * step;\r\n\t\tcursor = cursor + scroll * 512.0f * 2.0f * step;\r\n\t}\r\n\r\n\tif (buttons & Inp::Data::mD_L1)\r\n\t{\r\n//\t\tstart = start - scroll * 512.0f * 2.0f * step / 256.0f;\r\n\t\tcursor = cursor - scroll * 2.0f * 2.0f * step;\r\n\t}\r\n\tif (buttons & Inp::Data::mD_L2)\r\n\t{\r\n//\t\tstart = start + scroll * 512.0f * 2.0f * step / 256.0f;\r\n\t\tcursor = cursor + scroll * 2.0f * 2.0f * step;\r\n\t}\r\n\r\n#define \tMMMIN \t(0.0078125f)\r\n\t \t\t\t\t\r\n\tif (step1 <MMMIN)\r\n\t{\r\n\t\tstep1 = MMMIN;\r\n\t}\r\n\t\r\n\tif (step1>1024.0f)\r\n\t{\r\n\t\tstep1 = 1024.0f;\r\n\t}\r\n\r\n//\tstart = start + (512.0f * 2.0f * 128.0f * (step - step1));\r\n\r\n\tstep = step1;\r\n\r\n\tif (makes & Inp::Data::mD_CIRCLE)\r\n\t{\r\n\t\tif (blockstart)\r\n\t\t{\r\n\t\t\tMemView_DumpRefs(blockstart);\r\n\t\t}\r\n//\t\tMemView_MarkBlocks(1);\r\n\t}\r\n\r\n\t// We don't look for leaks automatically now, so I'v put it on \"SQUARE\"\t\r\n\tif (makes & Inp::Data::mD_SQUARE)\r\n\t{\r\n\t\tMemView_FindLeaks();\r\n//\tMem::Manager& mem_man = Mem::Manager::sHandle();\t\tMemView_DumpHeap(1);\r\n//\theap\t= mem_man.TopDownHeap();\r\n//\tMemView_DumpFragments(heap);\r\n//\tMemView_DumpHeap(heap,1);\r\n\r\n\t}\r\n\r\n\tif (makes & Inp::Data::mD_X)\r\n\t{\r\n\t\tMemView_AnalyzeBlocks();\r\n\t}\r\n\r\n\t// Triangle = Dump Fragmentation\r\n/*\tif (makes & Inp::Data::mD_TRIANGLE)\r\n\t{\r\n\t\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\t\tMem::Heap* heap = mem_man.BottomUpHeap();\r\n\t\tMem::Region* region = heap->ParentRegion();\r\n\t\tprintf (\"BottomUp Frag %dK, %d Blocks\\n\",heap->mFreeMem.m_count / 1024, heap->mFreeBlocks.m_count);\r\n\t\tprintf (\"Region %d/%d K\", region->MemAvailable() / 1024, region->TotalSize() / 1024 );\r\n\t\tMemView_DumpFragments(heap);\r\n\t}\r\n*/\t\r\n\r\n}\r\n\r\nvoid MemView_AnalyzeHeap(Mem::Heap *pHeap)\r\n{\r\n\tif ( !pHeap )\r\n\t\treturn;\r\n\t\r\n//#ifdef\t__LINKED_LIST_HEAP__\r\n//\tSBlockType  *pBlocks = (SBlockType  *)_mem_dump_start;\t// temp memory\r\n//\tint\tnum_blocks = 0;\r\n//\tint num = 0;\r\n//\r\n//\tMem::Allocator::BlockHeader *p_full = pHeap->mp_context->mp_used_list;\r\n//\r\n//\twhile (p_full)\r\n//\t{\r\n//\t\tCCallStack* pCallStack = (CCallStack*)p_full->mp_debug_data;\r\n//\r\n//\t\tif ( pCallStack )\r\n//\t\t{\r\n//\t\t\tMemView_AnalyzeCallStack( pCallStack, pBlocks, num );\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tprintf (\"Block with No Debug Info!!\\n\");\r\n//\t\t}\r\n//\r\n//\t\tp_full = p_full->mp_next_used;\r\n//\t}\r\n//\r\n//\tprintf (\"%d types, in %d total blocks\\n\", num, num_blocks); \r\n//\r\n//\tMemView_DumpAnalysis( pBlocks, num );\r\n//#endif\r\n}\r\n  \r\n  \r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_memview.h",
    "content": "////\r\n\r\n#ifndef\t__P_MEMVIEW_H__\r\n#define\t__P_MEMVIEW_H__\r\n\r\nvoid MemView_Display();\r\nvoid MemView_Input(uint buttons, uint makes, uint breaks);\r\nvoid MemView_Alloc( void *v);\r\nvoid MemView_Free( void *v);\r\nvoid MemViewToggle();\r\nvoid MemView_FindLeaks();\r\nint DumpUnwindStack( int iMaxDepth, int *pDest );\r\nchar *MemView_GetFunctionName(int pc, int *p_size);\r\nvoid MemView_DumpFragments(Mem::Heap *pHeap);\r\nvoid MemView_AnalyzeBlocks(uint32 mask = 0);\r\nvoid MemView_MarkBlocks(uint32 flags = 1 );\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nx.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\t\t\t \t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgfx/ngc/p_nx.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/16/2002\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tngc platform specific interface to the engine\t\t\t**\r\n**\t\t\t\t\tThis is ngc SPECIFIC!!!!!! If there is anything in\t\t**\r\n**\t\t\t\t\there that is not ngc specific, then it needs to be\t\t**\r\n**\t\t\t\t\tin nx.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sys/profiler.h>\r\n#include\t<sys/file/filesys.h>\r\n\r\n#include <gfx/nxfontman.h>\r\n#include <gfx/ngc/p_nxfont.h>\r\n\r\n#include\t\"gfx\\camera.h\"\r\n#include\t\"gfx\\nx.h\"\r\n#include\t\"gfx\\nxquickanim.h\"\r\n#include\t\"gfx\\nxviewman.h\"\r\n#include\t\"gfx\\ngc\\p_NxGeom.h\"\r\n#include\t\"gfx\\NGc\\p_NxMesh.h\"\r\n#include\t\"gfx\\NxParticleMgr.h\"\r\n#include\t\"gfx\\NxWeather.h\"\r\n#include\t\"gfx\\ngc\\p_nxWeather.h\"\r\n#include\t\"gfx\\NxMiscFX.h\"\r\n#include\t\"gfx\\NGc\\p_NxModel.h\"\r\n#include\t\"gfx\\ngc\\p_NxSector.h\"\r\n#include\t\"gfx\\ngc\\p_NxScene.h\"\r\n#include\t\"gfx\\ngc\\p_NxSprite.h\"\r\n#include\t\"gfx\\ngc\\p_NxTexture.h\"\r\n#include\t\"gfx\\ngc\\p_NxTextured3dPoly.h\"\r\n#include\t\"gfx\\ngc\\p_NxNewParticleMgr.h\"\r\n#include\t\"core\\math.h\"\r\n#include \t\"sk\\engine\\SuperSector.h\"\t\t\t\t\t\r\n#include \t\"gel\\scripting\\script.h\"\r\n#include\t\"gfx\\debuggfx.h\"\r\n\r\n#include \t\"gfx\\ngc\\nx\\nx_init.h\"\r\n#include \t\"gfx\\ngc\\nx\\import.h\"\r\n#include \t\"gfx\\ngc\\nx\\material.h\"\r\n#include \t\"gfx\\ngc\\nx\\mesh.h\"\r\n#include \t\"gfx\\ngc\\nx\\render.h\"\r\n#include \t\"gfx\\ngc\\nx\\occlude.h\"\r\n#include \t\"gfx\\ngc\\nx\\scene.h\"\r\n#include \t\"gfx\\ngc\\nx\\chars.h\"\r\n#include\t\"gfx\\ngc\\nx\\nx_init.h\"\r\n\r\n#include\t<sys/ngc\\p_display.h>\r\n#include\t<sys/ngc\\p_prim.h>\r\n#include\t<sys/ngc\\p_render.h>\r\n#include\t<gel/movies/ngc\\p_movies.h>\r\n#include\t<sys/ngc\\p_dvd.h>\r\n#include\t<sys/ngc\\p_buffer.h>\r\n\r\n#include\t\"sys/ngc/p_gx.h\"\r\n\r\nextern bool gCorrectColor;\r\n\r\nstatic bool s_correctable = true;\r\n\r\nint gOffy = 0;\r\n\r\nint g_object = 0;\r\nint g_view_object = 0;\r\nNxNgc::sScene * g_view_scene = NULL;\r\nint g_material = -1;\r\nint g_scroll_material = 0;\r\n\r\nint g_mip = 0;\r\nint g_passes = -1;\r\n\r\nextern unsigned char uv_col_map[][2];\r\n\r\nextern u8 g_blur;\r\nu8 sBlur = 0;\r\nextern bool\t\tgLoadingScreenActive;\r\n\r\nextern PADStatus padData[PAD_MAX_CONTROLLERS]; // game pad state\r\n\r\nextern int g_dl;\r\n\r\nextern bool g_in_cutscene;\r\n\r\n#define COLOR_MAP_SIZE 64\r\n\t\r\n//u16 colorMap[(COLOR_MAP_SIZE*COLOR_MAP_SIZE)*2] __attribute__ (( aligned( 32 )));\r\n//bool color_map_created = false;\r\n\r\n//extern NxNgc::sMaterialHeader *\tp_u_mat[2048];\r\n//extern int\t\t\t\t\tu_mat_count[2048];\r\n//extern int\t\t\t\t\tnum_u_mat;\r\n//bool gPrintMatStats = false;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#if 0\r\nstatic u8 sample_pattern[12][2] =\r\n{\r\n//\t{1,1},{3,3},{5,5},\r\n//\t{11,1},{9,3},{7,5},\r\n//\t{5,7},{3,9},{1,11},\r\n//\t{7,7},{9,9},{11,11}\r\n\t{3,2},{9,2},{3,10},\r\n\t{3,2},{9,2},{9,10},\r\n\t{3,2},{3,10},{9,10},\r\n\t{9,2},{3,10},{9,10},\r\n};\r\n#endif\r\n\r\nextern int meshes_considered;\r\n\r\n#ifndef __NOPT_FINAL__\r\nbool gDumpHeap = false;\r\n#endif\t\t// __NOPT_FINAL__\r\n\r\n#define SHADOW_TEXTURE_SIZE 256\r\n//#define BLUR_TEXTURE_SIZE 64\r\n//#define BLUR_BORDER 2\r\n//\r\n//#define BLUR_1 ( ( (float)BLUR_TEXTURE_SIZE - (float)BLUR_BORDER ) / (float)BLUR_TEXTURE_SIZE )\r\n//#define BLUR_0 ( (float)BLUR_BORDER / (float)BLUR_TEXTURE_SIZE )\r\n\r\nuint8 * shadowTextureData = NULL;\r\n//uint8 * volumeTextureData = NULL;\r\n//uint8 * zTextureDataH = NULL;\r\n//uint8 * zTextureDataL = NULL;\r\n//uint8 * screenTextureData = NULL;\r\n//uint8 * focusTextureData = NULL;\r\n//uint8 * blurTextureData = NULL;\r\n\r\n//int gFocus = 1;\r\n//\r\n// Set global palette for shadow & blur.\r\n\r\nuint16 shadowPalette[16] __attribute__ (( aligned( 32 ))) = {\r\n\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0x00 ),\t\t// 0\r\n\tGXPackedRGB5A3( 0x11, 0x11, 0x11, 0xff ),       // 1\r\n\tGXPackedRGB5A3( 0x22, 0x22, 0x22, 0xff ),       // 2\r\n\tGXPackedRGB5A3( 0x33, 0x33, 0x33, 0xff ),       // 3\r\n\tGXPackedRGB5A3( 0x44, 0x44, 0x44, 0xff ),       // 4\r\n\tGXPackedRGB5A3( 0x55, 0x55, 0x55, 0xff ),       // 5\r\n\tGXPackedRGB5A3( 0x66, 0x66, 0x66, 0xff ),       // 6\r\n\tGXPackedRGB5A3( 0x77, 0x77, 0x77, 0xff ),       // 7\r\n\tGXPackedRGB5A3( 0x88, 0x88, 0x88, 0xff ),       // 8\r\n\tGXPackedRGB5A3( 0x99, 0x99, 0x99, 0xff ),       // 9\r\n\tGXPackedRGB5A3( 0xaa, 0xaa, 0xaa, 0xff ),       // 10\r\n\tGXPackedRGB5A3( 0xbb, 0xbb, 0xbb, 0xff ),       // 11\r\n\tGXPackedRGB5A3( 0xcc, 0xcc, 0xcc, 0xff ),       // 12\r\n\tGXPackedRGB5A3( 0xdd, 0xdd, 0xdd, 0xff ),       // 13\r\n\tGXPackedRGB5A3( 0xee, 0xee, 0xee, 0xff ),       // 14\r\n\tGXPackedRGB5A3( 0xff, 0xff, 0xff, 0xff ),       // 15\r\n};\r\n\r\n//uint16 shadowPalette[16] __attribute__ (( aligned( 32 ))) = {\r\n//\tGXPackedRGB5A3( 0xff, 0xff, 0xff, 0xff ),       // 15\r\n//\tGXPackedRGB5A3( 0xee, 0xee, 0xee, 0xff ),       // 14\r\n//\tGXPackedRGB5A3( 0xdd, 0xdd, 0xdd, 0xff ),       // 13\r\n//\tGXPackedRGB5A3( 0xcc, 0xcc, 0xcc, 0xff ),       // 12\r\n//\tGXPackedRGB5A3( 0xbb, 0xbb, 0xbb, 0xff ),       // 11\r\n//\tGXPackedRGB5A3( 0xaa, 0xaa, 0xaa, 0xff ),       // 10\r\n//\tGXPackedRGB5A3( 0x99, 0x99, 0x99, 0xff ),       // 9\r\n//\tGXPackedRGB5A3( 0x88, 0x88, 0x88, 0xff ),       // 8\r\n//\tGXPackedRGB5A3( 0x77, 0x77, 0x77, 0xff ),       // 7\r\n//\tGXPackedRGB5A3( 0x66, 0x66, 0x66, 0xff ),       // 6\r\n//\tGXPackedRGB5A3( 0x55, 0x55, 0x55, 0xff ),       // 5\r\n//\tGXPackedRGB5A3( 0x44, 0x44, 0x44, 0xff ),       // 4\r\n//\tGXPackedRGB5A3( 0x33, 0x33, 0x33, 0xff ),       // 3\r\n//\tGXPackedRGB5A3( 0x22, 0x22, 0x22, 0xff ),       // 2\r\n//\tGXPackedRGB5A3( 0x11, 0x11, 0x11, 0xff ),       // 1\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0x00 ),\t\t// 0\r\n//};\r\n\r\n//uint16 zPalette[256] __attribute__ (( aligned( 32 ))) = {\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),\t\t// 0x00\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0x01\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0x02\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0x03\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0x04\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0x05\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x06\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x07\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x08\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x09\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x0a\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x0b\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x0c\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x0d\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x0e\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x0f\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),\t\t// 0x10\r\n//\tGXPackedRGB5A3( 0x11, 0x11, 0x11, 0xff ),       // 0x11\r\n//\tGXPackedRGB5A3( 0x12, 0x12, 0x12, 0xff ),       // 0x12\r\n//\tGXPackedRGB5A3( 0x13, 0x13, 0x13, 0xff ),       // 0x13\r\n//\tGXPackedRGB5A3( 0x14, 0x14, 0x14, 0xff ),       // 0x14\r\n//\tGXPackedRGB5A3( 0x15, 0x15, 0x15, 0xff ),       // 0x15\r\n//\tGXPackedRGB5A3( 0x16, 0x16, 0x16, 0xff ),       // 0x16\r\n//\tGXPackedRGB5A3( 0x17, 0x17, 0x17, 0xff ),       // 0x17\r\n//\tGXPackedRGB5A3( 0x18, 0x18, 0x18, 0xff ),       // 0x18\r\n//\tGXPackedRGB5A3( 0x19, 0x19, 0x19, 0xff ),       // 0x19\r\n//\tGXPackedRGB5A3( 0x1a, 0x1a, 0x1a, 0xff ),       // 0x1a\r\n//\tGXPackedRGB5A3( 0x1b, 0x1b, 0x1b, 0xff ),       // 0x1b\r\n//\tGXPackedRGB5A3( 0x1c, 0x1c, 0x1c, 0xff ),       // 0x1c\r\n//\tGXPackedRGB5A3( 0x1d, 0x1d, 0x1d, 0xff ),       // 0x1d\r\n//\tGXPackedRGB5A3( 0x1e, 0x1e, 0x1e, 0xff ),       // 0x1e\r\n//\tGXPackedRGB5A3( 0x1f, 0x1f, 0x1f, 0xff ),       // 0x1f\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),\t\t// 0x20\r\n//\tGXPackedRGB5A3( 0x21, 0x21, 0x21, 0xff ),       // 0x21\r\n//\tGXPackedRGB5A3( 0x22, 0x22, 0x22, 0xff ),       // 0x22\r\n//\tGXPackedRGB5A3( 0x23, 0x23, 0x23, 0xff ),       // 0x23\r\n//\tGXPackedRGB5A3( 0x24, 0x24, 0x24, 0xff ),       // 0x24\r\n//\tGXPackedRGB5A3( 0x25, 0x25, 0x25, 0xff ),       // 0x25\r\n//\tGXPackedRGB5A3( 0x26, 0x26, 0x26, 0xff ),       // 0x26\r\n//\tGXPackedRGB5A3( 0x27, 0x27, 0x27, 0xff ),       // 0x27\r\n//\tGXPackedRGB5A3( 0x28, 0x28, 0x28, 0xff ),       // 0x28\r\n//\tGXPackedRGB5A3( 0x29, 0x29, 0x29, 0xff ),       // 0x29\r\n//\tGXPackedRGB5A3( 0x2a, 0x2a, 0x2a, 0xff ),       // 0x2a\r\n//\tGXPackedRGB5A3( 0x2b, 0x2b, 0x2b, 0xff ),       // 0x2b\r\n//\tGXPackedRGB5A3( 0x2c, 0x2c, 0x2c, 0xff ),       // 0x2c\r\n//\tGXPackedRGB5A3( 0x2d, 0x2d, 0x2d, 0xff ),       // 0x2d\r\n//\tGXPackedRGB5A3( 0x2e, 0x2e, 0x2e, 0xff ),       // 0x2e\r\n//\tGXPackedRGB5A3( 0x2f, 0x2f, 0x2f, 0xff ),       // 0x2f\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),\t\t// 0x30\r\n//\tGXPackedRGB5A3( 0x31, 0x31, 0x31, 0xff ),       // 0x31\r\n//\tGXPackedRGB5A3( 0x32, 0x32, 0x32, 0xff ),       // 0x32\r\n//\tGXPackedRGB5A3( 0x33, 0x33, 0x33, 0xff ),       // 0x33\r\n//\tGXPackedRGB5A3( 0x34, 0x34, 0x34, 0xff ),       // 0x34\r\n//\tGXPackedRGB5A3( 0x35, 0x35, 0x35, 0xff ),       // 0x35\r\n//\tGXPackedRGB5A3( 0x36, 0x36, 0x36, 0xff ),       // 0x36\r\n//\tGXPackedRGB5A3( 0x37, 0x37, 0x37, 0xff ),       // 0x37\r\n//\tGXPackedRGB5A3( 0x38, 0x38, 0x38, 0xff ),       // 0x38\r\n//\tGXPackedRGB5A3( 0x39, 0x39, 0x39, 0xff ),       // 0x39\r\n//\tGXPackedRGB5A3( 0x3a, 0x3a, 0x3a, 0xff ),       // 0x3a\r\n//\tGXPackedRGB5A3( 0x3b, 0x3b, 0x3b, 0xff ),       // 0x3b\r\n//\tGXPackedRGB5A3( 0x3c, 0x3c, 0x3c, 0xff ),       // 0x3c\r\n//\tGXPackedRGB5A3( 0x3d, 0x3d, 0x3d, 0xff ),       // 0x3d\r\n//\tGXPackedRGB5A3( 0x3e, 0x3e, 0x3e, 0xff ),       // 0x3e\r\n//\tGXPackedRGB5A3( 0x3f, 0x3f, 0x3f, 0xff ),       // 0x3f\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),\t\t// 0x40\r\n//\tGXPackedRGB5A3( 0x41, 0x41, 0x41, 0xff ),       // 0x41\r\n//\tGXPackedRGB5A3( 0x42, 0x42, 0x42, 0xff ),       // 0x42\r\n//\tGXPackedRGB5A3( 0x43, 0x43, 0x43, 0xff ),       // 0x43\r\n//\tGXPackedRGB5A3( 0x44, 0x44, 0x44, 0xff ),       // 0x44\r\n//\tGXPackedRGB5A3( 0x45, 0x45, 0x45, 0xff ),       // 0x45\r\n//\tGXPackedRGB5A3( 0x46, 0x46, 0x46, 0xff ),       // 0x46\r\n//\tGXPackedRGB5A3( 0x47, 0x47, 0x47, 0xff ),       // 0x47\r\n//\tGXPackedRGB5A3( 0x48, 0x48, 0x48, 0xff ),       // 0x48\r\n//\tGXPackedRGB5A3( 0x49, 0x49, 0x49, 0xff ),       // 0x49\r\n//\tGXPackedRGB5A3( 0x4a, 0x4a, 0x4a, 0xff ),       // 0x4a\r\n//\tGXPackedRGB5A3( 0x4b, 0x4b, 0x4b, 0xff ),       // 0x4b\r\n//\tGXPackedRGB5A3( 0x4c, 0x4c, 0x4c, 0xff ),       // 0x4c\r\n//\tGXPackedRGB5A3( 0x4d, 0x4d, 0x4d, 0xff ),       // 0x4d\r\n//\tGXPackedRGB5A3( 0x4e, 0x4e, 0x4e, 0xff ),       // 0x4e\r\n//\tGXPackedRGB5A3( 0x4f, 0x4f, 0x4f, 0xff ),       // 0x4f\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),\t\t// 0x50\r\n//\tGXPackedRGB5A3( 0x51, 0x51, 0x51, 0xff ),       // 0x51\r\n//\tGXPackedRGB5A3( 0x52, 0x52, 0x52, 0xff ),       // 0x52\r\n//\tGXPackedRGB5A3( 0x53, 0x53, 0x53, 0xff ),       // 0x53\r\n//\tGXPackedRGB5A3( 0x54, 0x54, 0x54, 0xff ),       // 0x54\r\n//\tGXPackedRGB5A3( 0x55, 0x55, 0x55, 0xff ),       // 0x55\r\n//\tGXPackedRGB5A3( 0x56, 0x56, 0x56, 0xff ),       // 0x56\r\n//\tGXPackedRGB5A3( 0x57, 0x57, 0x57, 0xff ),       // 0x57\r\n//\tGXPackedRGB5A3( 0x58, 0x58, 0x58, 0xff ),       // 0x58\r\n//\tGXPackedRGB5A3( 0x59, 0x59, 0x59, 0xff ),       // 0x59\r\n//\tGXPackedRGB5A3( 0x5a, 0x5a, 0x5a, 0xff ),       // 0x5a\r\n//\tGXPackedRGB5A3( 0x5b, 0x5b, 0x5b, 0xff ),       // 0x5b\r\n//\tGXPackedRGB5A3( 0x5c, 0x5c, 0x5c, 0xff ),       // 0x5c\r\n//\tGXPackedRGB5A3( 0x5d, 0x5d, 0x5d, 0xff ),       // 0x5d\r\n//\tGXPackedRGB5A3( 0x5e, 0x5e, 0x5e, 0xff ),       // 0x5e\r\n//\tGXPackedRGB5A3( 0x5f, 0x5f, 0x5f, 0xff ),       // 0x5f\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),\t\t// 0x60\r\n//\tGXPackedRGB5A3( 0x61, 0x61, 0x61, 0xff ),       // 0x61\r\n//\tGXPackedRGB5A3( 0x62, 0x62, 0x62, 0xff ),       // 0x62\r\n//\tGXPackedRGB5A3( 0x63, 0x63, 0x63, 0xff ),       // 0x63\r\n//\tGXPackedRGB5A3( 0x64, 0x64, 0x64, 0xff ),       // 0x64\r\n//\tGXPackedRGB5A3( 0x65, 0x65, 0x65, 0xff ),       // 0x65\r\n//\tGXPackedRGB5A3( 0x66, 0x66, 0x66, 0xff ),       // 0x66\r\n//\tGXPackedRGB5A3( 0x67, 0x67, 0x67, 0xff ),       // 0x67\r\n//\tGXPackedRGB5A3( 0x68, 0x68, 0x68, 0xff ),       // 0x68\r\n//\tGXPackedRGB5A3( 0x69, 0x69, 0x69, 0xff ),       // 0x69\r\n//\tGXPackedRGB5A3( 0x6a, 0x6a, 0x6a, 0xff ),       // 0x6a\r\n//\tGXPackedRGB5A3( 0x6b, 0x6b, 0x6b, 0xff ),       // 0x6b\r\n//\tGXPackedRGB5A3( 0x6c, 0x6c, 0x6c, 0xff ),       // 0x6c\r\n//\tGXPackedRGB5A3( 0x6d, 0x6d, 0x6d, 0xff ),       // 0x6d\r\n//\tGXPackedRGB5A3( 0x6e, 0x6e, 0x6e, 0xff ),       // 0x6e\r\n//\tGXPackedRGB5A3( 0x6f, 0x6f, 0x6f, 0xff ),       // 0x6f\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),\t\t// 0x70\r\n//\tGXPackedRGB5A3( 0x71, 0x71, 0x71, 0xff ),       // 0x71\r\n//\tGXPackedRGB5A3( 0x72, 0x72, 0x72, 0xff ),       // 0x72\r\n//\tGXPackedRGB5A3( 0x73, 0x73, 0x73, 0xff ),       // 0x73\r\n//\tGXPackedRGB5A3( 0x74, 0x74, 0x74, 0xff ),       // 0x74\r\n//\tGXPackedRGB5A3( 0x75, 0x75, 0x75, 0xff ),       // 0x75\r\n//\tGXPackedRGB5A3( 0x76, 0x76, 0x76, 0xff ),       // 0x76\r\n//\tGXPackedRGB5A3( 0x77, 0x77, 0x77, 0xff ),       // 0x77\r\n//\tGXPackedRGB5A3( 0x78, 0x78, 0x78, 0xff ),       // 0x78\r\n//\tGXPackedRGB5A3( 0x79, 0x79, 0x79, 0xff ),       // 0x79\r\n//\tGXPackedRGB5A3( 0x7a, 0x7a, 0x7a, 0xff ),       // 0x7a\r\n//\tGXPackedRGB5A3( 0x7b, 0x7b, 0x7b, 0xff ),       // 0x7b\r\n//\tGXPackedRGB5A3( 0x7c, 0x7c, 0x7c, 0xff ),       // 0x7c\r\n//\tGXPackedRGB5A3( 0x7d, 0x7d, 0x7d, 0xff ),       // 0x7d\r\n//\tGXPackedRGB5A3( 0x7e, 0x7e, 0x7e, 0xff ),       // 0x7e\r\n//\tGXPackedRGB5A3( 0x7f, 0x7f, 0x7f, 0xff ),       // 0x7f\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),\t\t// 0x80\r\n//\tGXPackedRGB5A3( 0x81, 0x81, 0x81, 0xff ),       // 0x81\r\n//\tGXPackedRGB5A3( 0x82, 0x82, 0x82, 0xff ),       // 0x82\r\n//\tGXPackedRGB5A3( 0x83, 0x83, 0x83, 0xff ),       // 0x83\r\n//\tGXPackedRGB5A3( 0x84, 0x84, 0x84, 0xff ),       // 0x84\r\n//\tGXPackedRGB5A3( 0x85, 0x85, 0x85, 0xff ),       // 0x85\r\n//\tGXPackedRGB5A3( 0x86, 0x86, 0x86, 0xff ),       // 0x86\r\n//\tGXPackedRGB5A3( 0x87, 0x87, 0x87, 0xff ),       // 0x87\r\n//\tGXPackedRGB5A3( 0x88, 0x88, 0x88, 0xff ),       // 0x88\r\n//\tGXPackedRGB5A3( 0x89, 0x89, 0x89, 0xff ),       // 0x89\r\n//\tGXPackedRGB5A3( 0x8a, 0x8a, 0x8a, 0xff ),       // 0x8a\r\n//\tGXPackedRGB5A3( 0x8b, 0x8b, 0x8b, 0xff ),       // 0x8b\r\n//\tGXPackedRGB5A3( 0x8c, 0x8c, 0x8c, 0xff ),       // 0x8c\r\n//\tGXPackedRGB5A3( 0x8d, 0x8d, 0x8d, 0xff ),       // 0x8d\r\n//\tGXPackedRGB5A3( 0x8e, 0x8e, 0x8e, 0xff ),       // 0x8e\r\n//\tGXPackedRGB5A3( 0x8f, 0x8f, 0x8f, 0xff ),       // 0x8f\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),\t\t// 0x90\r\n//\tGXPackedRGB5A3( 0x91, 0x91, 0x91, 0xff ),       // 0x91\r\n//\tGXPackedRGB5A3( 0x92, 0x92, 0x92, 0xff ),       // 0x92\r\n//\tGXPackedRGB5A3( 0x93, 0x93, 0x93, 0xff ),       // 0x93\r\n//\tGXPackedRGB5A3( 0x94, 0x94, 0x94, 0xff ),       // 0x94\r\n//\tGXPackedRGB5A3( 0x95, 0x95, 0x95, 0xff ),       // 0x95\r\n//\tGXPackedRGB5A3( 0x96, 0x96, 0x96, 0xff ),       // 0x96\r\n//\tGXPackedRGB5A3( 0x97, 0x97, 0x97, 0xff ),       // 0x97\r\n//\tGXPackedRGB5A3( 0x98, 0x98, 0x98, 0xff ),       // 0x98\r\n//\tGXPackedRGB5A3( 0x99, 0x99, 0x99, 0xff ),       // 0x99\r\n//\tGXPackedRGB5A3( 0x9a, 0x9a, 0x9a, 0xff ),       // 0x9a\r\n//\tGXPackedRGB5A3( 0x9b, 0x9b, 0x9b, 0xff ),       // 0x9b\r\n//\tGXPackedRGB5A3( 0x9c, 0x9c, 0x9c, 0xff ),       // 0x9c\r\n//\tGXPackedRGB5A3( 0x9d, 0x9d, 0x9d, 0xff ),       // 0x9d\r\n//\tGXPackedRGB5A3( 0x9e, 0x9e, 0x9e, 0xff ),       // 0x9e\r\n//\tGXPackedRGB5A3( 0x9f, 0x9f, 0x9f, 0xff ),       // 0x9f\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),\t\t// 0xa0\r\n//\tGXPackedRGB5A3( 0xa1, 0xa1, 0xa1, 0xff ),       // 0xa1\r\n//\tGXPackedRGB5A3( 0xa2, 0xa2, 0xa2, 0xff ),       // 0xa2\r\n//\tGXPackedRGB5A3( 0xa3, 0xa3, 0xa3, 0xff ),       // 0xa3\r\n//\tGXPackedRGB5A3( 0xa4, 0xa4, 0xa4, 0xff ),       // 0xa4\r\n//\tGXPackedRGB5A3( 0xa5, 0xa5, 0xa5, 0xff ),       // 0xa5\r\n//\tGXPackedRGB5A3( 0xa6, 0xa6, 0xa6, 0xff ),       // 0xa6\r\n//\tGXPackedRGB5A3( 0xa7, 0xa7, 0xa7, 0xff ),       // 0xa7\r\n//\tGXPackedRGB5A3( 0xa8, 0xa8, 0xa8, 0xff ),       // 0xa8\r\n//\tGXPackedRGB5A3( 0xa9, 0xa9, 0xa9, 0xff ),       // 0xa9\r\n//\tGXPackedRGB5A3( 0xaa, 0xaa, 0xaa, 0xff ),       // 0xaa\r\n//\tGXPackedRGB5A3( 0xab, 0xab, 0xab, 0xff ),       // 0xab\r\n//\tGXPackedRGB5A3( 0xac, 0xac, 0xac, 0xff ),       // 0xac\r\n//\tGXPackedRGB5A3( 0xad, 0xad, 0xad, 0xff ),       // 0xad\r\n//\tGXPackedRGB5A3( 0xae, 0xae, 0xae, 0xff ),       // 0xae\r\n//\tGXPackedRGB5A3( 0xaf, 0xaf, 0xaf, 0xff ),       // 0xaf\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),\t\t// 0xb0\r\n//\tGXPackedRGB5A3( 0xb1, 0xb1, 0xb1, 0xff ),       // 0xb1\r\n//\tGXPackedRGB5A3( 0xb2, 0xb2, 0xb2, 0xff ),       // 0xb2\r\n//\tGXPackedRGB5A3( 0xb3, 0xb3, 0xb3, 0xff ),       // 0xb3\r\n//\tGXPackedRGB5A3( 0xb4, 0xb4, 0xb4, 0xff ),       // 0xb4\r\n//\tGXPackedRGB5A3( 0xb5, 0xb5, 0xb5, 0xff ),       // 0xb5\r\n//\tGXPackedRGB5A3( 0xb6, 0xb6, 0xb6, 0xff ),       // 0xb6\r\n//\tGXPackedRGB5A3( 0xb7, 0xb7, 0xb7, 0xff ),       // 0xb7\r\n//\tGXPackedRGB5A3( 0xb8, 0xb8, 0xb8, 0xff ),       // 0xb8\r\n//\tGXPackedRGB5A3( 0xb9, 0xb9, 0xb9, 0xff ),       // 0xb9\r\n//\tGXPackedRGB5A3( 0xba, 0xba, 0xba, 0xff ),       // 0xba\r\n//\tGXPackedRGB5A3( 0xbb, 0xbb, 0xbb, 0xff ),       // 0xbb\r\n//\tGXPackedRGB5A3( 0xbc, 0xbc, 0xbc, 0xff ),       // 0xbc\r\n//\tGXPackedRGB5A3( 0xbd, 0xbd, 0xbd, 0xff ),       // 0xbd\r\n//\tGXPackedRGB5A3( 0xbe, 0xbe, 0xbe, 0xff ),       // 0xbe\r\n//\tGXPackedRGB5A3( 0xbf, 0xbf, 0xbf, 0xff ),       // 0xbf\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),\t\t// 0xc0\r\n//\tGXPackedRGB5A3( 0xc1, 0xc1, 0xc1, 0xff ),       // 0xc1\r\n//\tGXPackedRGB5A3( 0xc2, 0xc2, 0xc2, 0xff ),       // 0xc2\r\n//\tGXPackedRGB5A3( 0xc3, 0xc3, 0xc3, 0xff ),       // 0xc3\r\n//\tGXPackedRGB5A3( 0xc4, 0xc4, 0xc4, 0xff ),       // 0xc4\r\n//\tGXPackedRGB5A3( 0xc5, 0xc5, 0xc5, 0xff ),       // 0xc5\r\n//\tGXPackedRGB5A3( 0xc6, 0xc6, 0xc6, 0xff ),       // 0xc6\r\n//\tGXPackedRGB5A3( 0xc7, 0xc7, 0xc7, 0xff ),       // 0xc7\r\n//\tGXPackedRGB5A3( 0xc8, 0xc8, 0xc8, 0xff ),       // 0xc8\r\n//\tGXPackedRGB5A3( 0xc9, 0xc9, 0xc9, 0xff ),       // 0xc9\r\n//\tGXPackedRGB5A3( 0xca, 0xca, 0xca, 0xff ),       // 0xca\r\n//\tGXPackedRGB5A3( 0xcb, 0xcb, 0xcb, 0xff ),       // 0xcb\r\n//\tGXPackedRGB5A3( 0xcc, 0xcc, 0xcc, 0xff ),       // 0xcc\r\n//\tGXPackedRGB5A3( 0xcd, 0xcd, 0xcd, 0xff ),       // 0xcd\r\n//\tGXPackedRGB5A3( 0xce, 0xce, 0xce, 0xff ),       // 0xce\r\n//\tGXPackedRGB5A3( 0xcf, 0xcf, 0xcf, 0xff ),       // 0xcf\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),\t\t// 0xd0\r\n//\tGXPackedRGB5A3( 0xd1, 0xd1, 0xd1, 0xff ),       // 0xd1\r\n//\tGXPackedRGB5A3( 0xd2, 0xd2, 0xd2, 0xff ),       // 0xd2\r\n//\tGXPackedRGB5A3( 0xd3, 0xd3, 0xd3, 0xff ),       // 0xd3\r\n//\tGXPackedRGB5A3( 0xd4, 0xd4, 0xd4, 0xff ),       // 0xd4\r\n//\tGXPackedRGB5A3( 0xd5, 0xd5, 0xd5, 0xff ),       // 0xd5\r\n//\tGXPackedRGB5A3( 0xd6, 0xd6, 0xd6, 0xff ),       // 0xd6\r\n//\tGXPackedRGB5A3( 0xd7, 0xd7, 0xd7, 0xff ),       // 0xd7\r\n//\tGXPackedRGB5A3( 0xd8, 0xd8, 0xd8, 0xff ),       // 0xd8\r\n//\tGXPackedRGB5A3( 0xd9, 0xd9, 0xd9, 0xff ),       // 0xd9\r\n//\tGXPackedRGB5A3( 0xda, 0xda, 0xda, 0xff ),       // 0xda\r\n//\tGXPackedRGB5A3( 0xdb, 0xdb, 0xdb, 0xff ),       // 0xdb\r\n//\tGXPackedRGB5A3( 0xdc, 0xdc, 0xdc, 0xff ),       // 0xdc\r\n//\tGXPackedRGB5A3( 0xdd, 0xdd, 0xdd, 0xff ),       // 0xdd\r\n//\tGXPackedRGB5A3( 0xde, 0xde, 0xde, 0xff ),       // 0xde\r\n//\tGXPackedRGB5A3( 0xdf, 0xdf, 0xdf, 0xff ),       // 0xdf\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),\t\t// 0xe0\r\n//\tGXPackedRGB5A3( 0xe1, 0xe1, 0xe1, 0xff ),       // 0xe1\r\n//\tGXPackedRGB5A3( 0xe2, 0xe2, 0xe2, 0xff ),       // 0xe2\r\n//\tGXPackedRGB5A3( 0xe3, 0xe3, 0xe3, 0xff ),       // 0xe3\r\n//\tGXPackedRGB5A3( 0xe4, 0xe4, 0xe4, 0xff ),       // 0xe4\r\n//\tGXPackedRGB5A3( 0xe5, 0xe5, 0xe5, 0xff ),       // 0xe5\r\n//\tGXPackedRGB5A3( 0xe6, 0xe6, 0xe6, 0xff ),       // 0xe6\r\n//\tGXPackedRGB5A3( 0xe7, 0xe7, 0xe7, 0xff ),       // 0xe7\r\n//\tGXPackedRGB5A3( 0xe8, 0xe8, 0xe8, 0xff ),       // 0xe8\r\n//\tGXPackedRGB5A3( 0xe9, 0xe9, 0xe9, 0xff ),       // 0xe9\r\n//\tGXPackedRGB5A3( 0xea, 0xea, 0xea, 0xff ),       // 0xea\r\n//\tGXPackedRGB5A3( 0xeb, 0xeb, 0xeb, 0xff ),       // 0xeb\r\n//\tGXPackedRGB5A3( 0xec, 0xec, 0xec, 0xff ),       // 0xec\r\n//\tGXPackedRGB5A3( 0xed, 0xed, 0xed, 0xff ),       // 0xed\r\n//\tGXPackedRGB5A3( 0xee, 0xee, 0xee, 0xff ),       // 0xee\r\n//\tGXPackedRGB5A3( 0xef, 0xef, 0xef, 0xff ),       // 0xef\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),\t\t// 0xf0\r\n//\tGXPackedRGB5A3( 0xf1, 0xf1, 0xf1, 0xff ),       // 0xf1\r\n//\tGXPackedRGB5A3( 0xf2, 0xf2, 0xf2, 0xff ),       // 0xf2\r\n//\tGXPackedRGB5A3( 0xf3, 0xf3, 0xf3, 0xff ),       // 0xf3\r\n//\tGXPackedRGB5A3( 0xf4, 0xf4, 0xf4, 0xff ),       // 0xf4\r\n//\tGXPackedRGB5A3( 0xf5, 0xf5, 0xf5, 0xff ),       // 0xf5\r\n//\tGXPackedRGB5A3( 0xf6, 0xf6, 0xf6, 0xff ),       // 0xf6\r\n//\tGXPackedRGB5A3( 0xf7, 0xf7, 0xf7, 0xff ),       // 0xf7\r\n//\tGXPackedRGB5A3( 0xf8, 0xf8, 0xf8, 0xff ),       // 0xf8\r\n//\tGXPackedRGB5A3( 0xf9, 0xf9, 0xf9, 0xff ),       // 0xf9\r\n//\tGXPackedRGB5A3( 0xfa, 0xfa, 0xfa, 0xff ),       // 0xfa\r\n//\tGXPackedRGB5A3( 0xfb, 0xfb, 0xfb, 0xff ),       // 0xfb\r\n//\tGXPackedRGB5A3( 0xfc, 0xfc, 0xfc, 0xff ),       // 0xfc\r\n//\tGXPackedRGB5A3( 0xfd, 0xfd, 0xfd, 0xff ),       // 0xfd\r\n//\tGXPackedRGB5A3( 0xfe, 0xfe, 0xfe, 0xff ),       // 0xfe\r\n//\tGXPackedRGB5A3( 0xff, 0xff, 0xff, 0xff ),       // 0xff\r\n//};\r\n\r\n//uint16 zPaletteH[256] __attribute__ (( aligned( 32 ))) = {\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),\t\t// 0x00\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x01\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x02\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x03\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x04\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x05\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x06\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x07\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x08\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x09\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x0a\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x0b\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x0c\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x0d\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x0e\r\n//\tGXPackedRGB5A3( 0xf0, 0xf0, 0xf0, 0xff ),       // 0x0f\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),\t\t// 0x10\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x11\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x12\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x13\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x14\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x15\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x16\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x17\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x18\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x19\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x1a\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x1b\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x1c\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x1d\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x1e\r\n//\tGXPackedRGB5A3( 0xe0, 0xe0, 0xe0, 0xff ),       // 0x1f\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),\t\t// 0x20\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x21\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x22\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x23\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x24\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x25\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x26\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x27\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x28\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x29\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x2a\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x2b\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x2c\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x2d\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x2e\r\n//\tGXPackedRGB5A3( 0xd0, 0xd0, 0xd0, 0xff ),       // 0x2f\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),\t\t// 0x30\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x31\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x32\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x33\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x34\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x35\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x36\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x37\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x38\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x39\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x3a\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x3b\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x3c\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x3d\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x3e\r\n//\tGXPackedRGB5A3( 0xc0, 0xc0, 0xc0, 0xff ),       // 0x3f\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),\t\t// 0x40\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x41\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x42\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x43\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x44\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x45\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x46\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x47\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x48\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x49\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x4a\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x4b\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x4c\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x4d\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x4e\r\n//\tGXPackedRGB5A3( 0xb0, 0xb0, 0xb0, 0xff ),       // 0x4f\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),\t\t// 0x50\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x51\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x52\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x53\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x54\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x55\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x56\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x57\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x58\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x59\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x5a\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x5b\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x5c\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x5d\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x5e\r\n//\tGXPackedRGB5A3( 0xa0, 0xa0, 0xa0, 0xff ),       // 0x5f\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),\t\t// 0x60\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x61\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x62\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x63\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x64\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x65\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x66\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x67\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x68\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x69\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x6a\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x6b\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x6c\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x6d\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x6e\r\n//\tGXPackedRGB5A3( 0x90, 0x90, 0x90, 0xff ),       // 0x6f\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),\t\t// 0x70\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x71\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x72\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x73\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x74\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x75\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x76\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x77\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x78\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x79\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x7a\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x7b\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x7c\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x7d\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x7e\r\n//\tGXPackedRGB5A3( 0x80, 0x80, 0x80, 0xff ),       // 0x7f\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),\t\t// 0x80\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x81\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x82\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x83\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x84\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x85\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x86\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x87\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x88\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x89\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x8a\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x8b\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x8c\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x8d\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x8e\r\n//\tGXPackedRGB5A3( 0x70, 0x70, 0x70, 0xff ),       // 0x8f\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),\t\t// 0x90\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x91\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x92\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x93\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x94\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x95\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x96\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x97\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x98\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x99\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x9a\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x9b\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x9c\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x9d\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x9e\r\n//\tGXPackedRGB5A3( 0x60, 0x60, 0x60, 0xff ),       // 0x9f\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),\t\t// 0xa0\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xa1\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xa2\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xa3\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xa4\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xa5\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xa6\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xa7\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xa8\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xa9\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xaa\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xab\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xac\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xad\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xae\r\n//\tGXPackedRGB5A3( 0x50, 0x50, 0x50, 0xff ),       // 0xaf\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),\t\t// 0xb0\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xb1\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xb2\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xb3\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xb4\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xb5\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xb6\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xb7\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xb8\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xb9\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xba\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xbb\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xbc\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xbd\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xbe\r\n//\tGXPackedRGB5A3( 0x40, 0x40, 0x40, 0xff ),       // 0xbf\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),\t\t// 0xc0\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xc1\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xc2\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xc3\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xc4\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xc5\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xc6\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xc7\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xc8\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xc9\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xca\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xcb\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xcc\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xcd\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xce\r\n//\tGXPackedRGB5A3( 0x30, 0x30, 0x30, 0xff ),       // 0xcf\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),\t\t// 0xd0\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xd1\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xd2\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xd3\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xd4\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xd5\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xd6\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xd7\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xd8\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xd9\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xda\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xdb\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xdc\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xdd\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xde\r\n//\tGXPackedRGB5A3( 0x20, 0x20, 0x20, 0xff ),       // 0xdf\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),\t\t// 0xe0\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xe1\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xe2\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xe3\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xe4\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xe5\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xe6\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xe7\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xe8\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xe9\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xea\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xeb\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xec\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xed\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xee\r\n//\tGXPackedRGB5A3( 0x10, 0x10, 0x10, 0xff ),       // 0xef\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),\t\t// 0xf0\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf1\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf2\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf3\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf4\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf5\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf6\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf7\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf8\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf9\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xfa\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xfb\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xfc\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xfd\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xfe\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xff\r\n//};\r\n//\r\n//uint16 zPaletteL[256] __attribute__ (( aligned( 32 ))) = {\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),\t\t// 0x00\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x01\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x02\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x03\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x04\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x05\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x06\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x07\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x08\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x09\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x0a\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x0b\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x0c\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x0d\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x0e\r\n//\tGXPackedRGB5A3( 0x0f, 0x0f, 0x0f, 0xff ),       // 0x0f\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),\t\t// 0x10\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x11\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x12\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x13\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x14\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x15\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x16\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x17\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x18\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x19\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x1a\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x1b\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x1c\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x1d\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x1e\r\n//\tGXPackedRGB5A3( 0x0e, 0x0e, 0x0e, 0xff ),       // 0x1f\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),\t\t// 0x20\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x21\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x22\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x23\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x24\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x25\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x26\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x27\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x28\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x29\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x2a\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x2b\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x2c\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x2d\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x2e\r\n//\tGXPackedRGB5A3( 0x0d, 0x0d, 0x0d, 0xff ),       // 0x2f\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),\t\t// 0x30\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x31\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x32\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x33\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x34\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x35\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x36\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x37\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x38\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x39\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x3a\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x3b\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x3c\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x3d\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x3e\r\n//\tGXPackedRGB5A3( 0x0c, 0x0c, 0x0c, 0xff ),       // 0x3f\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),\t\t// 0x40\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x41\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x42\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x43\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x44\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x45\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x46\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x47\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x48\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x49\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x4a\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x4b\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x4c\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x4d\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x4e\r\n//\tGXPackedRGB5A3( 0x0b, 0x0b, 0x0b, 0xff ),       // 0x4f\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),\t\t// 0x50\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x51\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x52\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x53\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x54\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x55\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x56\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x57\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x58\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x59\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x5a\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x5b\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x5c\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x5d\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x5e\r\n//\tGXPackedRGB5A3( 0x0a, 0x0a, 0x0a, 0xff ),       // 0x5f\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),\t\t// 0x60\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x61\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x62\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x63\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x64\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x65\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x66\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x67\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x68\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x69\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x6a\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x6b\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x6c\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x6d\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x6e\r\n//\tGXPackedRGB5A3( 0x09, 0x09, 0x09, 0xff ),       // 0x6f\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),\t\t// 0x70\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x71\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x72\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x73\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x74\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x75\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x76\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x77\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x78\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x79\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x7a\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x7b\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x7c\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x7d\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x7e\r\n//\tGXPackedRGB5A3( 0x08, 0x08, 0x08, 0xff ),       // 0x7f\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),\t\t// 0x80\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x81\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x82\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x83\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x84\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x85\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x86\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x87\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x88\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x89\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x8a\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x8b\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x8c\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x8d\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x8e\r\n//\tGXPackedRGB5A3( 0x07, 0x07, 0x07, 0xff ),       // 0x8f\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),\t\t// 0x90\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x91\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x92\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x93\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x94\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x95\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x96\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x97\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x98\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x99\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x9a\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x9b\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x9c\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x9d\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x9e\r\n//\tGXPackedRGB5A3( 0x06, 0x06, 0x06, 0xff ),       // 0x9f\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),\t\t// 0xa0\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xa1\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xa2\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xa3\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xa4\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xa5\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xa6\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xa7\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xa8\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xa9\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xaa\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xab\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xac\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xad\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xae\r\n//\tGXPackedRGB5A3( 0x05, 0x05, 0x05, 0xff ),       // 0xaf\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),\t\t// 0xb0\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xb1\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xb2\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xb3\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xb4\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xb5\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xb6\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xb7\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xb8\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xb9\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xba\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xbb\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xbc\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xbd\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xbe\r\n//\tGXPackedRGB5A3( 0x04, 0x04, 0x04, 0xff ),       // 0xbf\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),\t\t// 0xc0\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xc1\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xc2\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xc3\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xc4\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xc5\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xc6\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xc7\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xc8\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xc9\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xca\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xcb\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xcc\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xcd\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xce\r\n//\tGXPackedRGB5A3( 0x03, 0x03, 0x03, 0xff ),       // 0xcf\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),\t\t// 0xd0\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xd1\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xd2\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xd3\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xd4\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xd5\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xd6\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xd7\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xd8\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xd9\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xda\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xdb\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xdc\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xdd\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xde\r\n//\tGXPackedRGB5A3( 0x02, 0x02, 0x02, 0xff ),       // 0xdf\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),\t\t// 0xe0\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xe1\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xe2\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xe3\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xe4\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xe5\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xe6\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xe7\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xe8\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xe9\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xea\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xeb\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xec\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xed\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xee\r\n//\tGXPackedRGB5A3( 0x01, 0x01, 0x01, 0xff ),       // 0xef\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),\t\t// 0xf0\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf1\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf2\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf3\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf4\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf5\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf6\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf7\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf8\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xf9\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xfa\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xfb\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xfc\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xfd\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xfe\r\n//\tGXPackedRGB5A3( 0x00, 0x00, 0x00, 0xff ),       // 0xff\r\n//};\r\n//\r\n//uint8 zPalette8[256] __attribute__ (( aligned( 32 ))) = {\r\n//\t0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,\r\n//\t0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,\r\n//\t0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,\r\n//\t0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,\r\n//\t0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,\r\n//\t0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,\r\n//\t0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,\r\n//\t0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,\r\n//\t0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,\r\n//\t0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,\r\n//\t0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,\r\n//\t0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,\r\n//\t0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,\r\n//\t0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,\r\n//\t0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,\r\n//\t0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff\r\n//};\r\n//\r\n//#define _H(a)  (((a<<(8+6))&0xc000)|((a<<6)&0x00c0))\r\n//\r\n//uint16 zPalette8H[256] __attribute__ (( aligned( 32 ))) = {\r\n//\t_H(0x00),_H(0x01),_H(0x02),_H(0x03),_H(0x04),_H(0x05),_H(0x06),_H(0x07),_H(0x08),_H(0x09),_H(0x0a),_H(0x0b),_H(0x0c),_H(0x0d),_H(0x0e),_H(0x0f),\r\n//\t_H(0x10),_H(0x11),_H(0x12),_H(0x13),_H(0x14),_H(0x15),_H(0x16),_H(0x17),_H(0x18),_H(0x19),_H(0x1a),_H(0x1b),_H(0x1c),_H(0x1d),_H(0x1e),_H(0x1f),\r\n//\t_H(0x20),_H(0x21),_H(0x22),_H(0x23),_H(0x24),_H(0x25),_H(0x26),_H(0x27),_H(0x28),_H(0x29),_H(0x2a),_H(0x2b),_H(0x2c),_H(0x2d),_H(0x2e),_H(0x2f),\r\n//\t_H(0x30),_H(0x31),_H(0x32),_H(0x33),_H(0x34),_H(0x35),_H(0x36),_H(0x37),_H(0x38),_H(0x39),_H(0x3a),_H(0x3b),_H(0x3c),_H(0x3d),_H(0x3e),_H(0x3f),\r\n//\t_H(0x40),_H(0x41),_H(0x42),_H(0x43),_H(0x44),_H(0x45),_H(0x46),_H(0x47),_H(0x48),_H(0x49),_H(0x4a),_H(0x4b),_H(0x4c),_H(0x4d),_H(0x4e),_H(0x4f),\r\n//\t_H(0x50),_H(0x51),_H(0x52),_H(0x53),_H(0x54),_H(0x55),_H(0x56),_H(0x57),_H(0x58),_H(0x59),_H(0x5a),_H(0x5b),_H(0x5c),_H(0x5d),_H(0x5e),_H(0x5f),\r\n//\t_H(0x60),_H(0x61),_H(0x62),_H(0x63),_H(0x64),_H(0x65),_H(0x66),_H(0x67),_H(0x68),_H(0x69),_H(0x6a),_H(0x6b),_H(0x6c),_H(0x6d),_H(0x6e),_H(0x6f),\r\n//\t_H(0x70),_H(0x71),_H(0x72),_H(0x73),_H(0x74),_H(0x75),_H(0x76),_H(0x77),_H(0x78),_H(0x79),_H(0x7a),_H(0x7b),_H(0x7c),_H(0x7d),_H(0x7e),_H(0x7f),\r\n//\t_H(0x80),_H(0x81),_H(0x82),_H(0x83),_H(0x84),_H(0x85),_H(0x86),_H(0x87),_H(0x88),_H(0x89),_H(0x8a),_H(0x8b),_H(0x8c),_H(0x8d),_H(0x8e),_H(0x8f),\r\n//\t_H(0x90),_H(0x91),_H(0x92),_H(0x93),_H(0x94),_H(0x95),_H(0x96),_H(0x97),_H(0x98),_H(0x99),_H(0x9a),_H(0x9b),_H(0x9c),_H(0x9d),_H(0x9e),_H(0x9f),\r\n//\t_H(0xa0),_H(0xa1),_H(0xa2),_H(0xa3),_H(0xa4),_H(0xa5),_H(0xa6),_H(0xa7),_H(0xa8),_H(0xa9),_H(0xaa),_H(0xab),_H(0xac),_H(0xad),_H(0xae),_H(0xaf),\r\n//\t_H(0xb0),_H(0xb1),_H(0xb2),_H(0xb3),_H(0xb4),_H(0xb5),_H(0xb6),_H(0xb7),_H(0xb8),_H(0xb9),_H(0xba),_H(0xbb),_H(0xbc),_H(0xbd),_H(0xbe),_H(0xbf),\r\n//\t_H(0xc0),_H(0xc1),_H(0xc2),_H(0xc3),_H(0xc4),_H(0xc5),_H(0xc6),_H(0xc7),_H(0xc8),_H(0xc9),_H(0xca),_H(0xcb),_H(0xcc),_H(0xcd),_H(0xce),_H(0xcf),\r\n//\t_H(0xd0),_H(0xd1),_H(0xd2),_H(0xd3),_H(0xd4),_H(0xd5),_H(0xd6),_H(0xd7),_H(0xd8),_H(0xd9),_H(0xda),_H(0xdb),_H(0xdc),_H(0xdd),_H(0xde),_H(0xdf),\r\n//\t_H(0xe0),_H(0xe1),_H(0xe2),_H(0xe3),_H(0xe4),_H(0xe5),_H(0xe6),_H(0xe7),_H(0xe8),_H(0xe9),_H(0xea),_H(0xeb),_H(0xec),_H(0xed),_H(0xee),_H(0xef),\r\n//\t_H(0xf0),_H(0xf1),_H(0xf2),_H(0xf3),_H(0xf4),_H(0xf5),_H(0xf6),_H(0xf7),_H(0xf8),_H(0xf9),_H(0xfa),_H(0xfb),_H(0xfc),_H(0xfd),_H(0xfe),_H(0xff)\r\n//};\r\n//\r\n//#define _L(a)  (((a<<(8-2))&0x3f00)|((a>>2)&0x003f))\r\n////#define _L(a)  ((a<<8)|a)\r\n//\r\n//uint16 zPalette8L[256] __attribute__ (( aligned( 32 ))) = {\r\n//\t_L(0x00),_L(0x01),_L(0x02),_L(0x03),_L(0x04),_L(0x05),_L(0x06),_L(0x07),_L(0x08),_L(0x09),_L(0x0a),_L(0x0b),_L(0x0c),_L(0x0d),_L(0x0e),_L(0x0f),\r\n//\t_L(0x10),_L(0x11),_L(0x12),_L(0x13),_L(0x14),_L(0x15),_L(0x16),_L(0x17),_L(0x18),_L(0x19),_L(0x1a),_L(0x1b),_L(0x1c),_L(0x1d),_L(0x1e),_L(0x1f),\r\n//\t_L(0x20),_L(0x21),_L(0x22),_L(0x23),_L(0x24),_L(0x25),_L(0x26),_L(0x27),_L(0x28),_L(0x29),_L(0x2a),_L(0x2b),_L(0x2c),_L(0x2d),_L(0x2e),_L(0x2f),\r\n//\t_L(0x30),_L(0x31),_L(0x32),_L(0x33),_L(0x34),_L(0x35),_L(0x36),_L(0x37),_L(0x38),_L(0x39),_L(0x3a),_L(0x3b),_L(0x3c),_L(0x3d),_L(0x3e),_L(0x3f),\r\n//\t_L(0x40),_L(0x41),_L(0x42),_L(0x43),_L(0x44),_L(0x45),_L(0x46),_L(0x47),_L(0x48),_L(0x49),_L(0x4a),_L(0x4b),_L(0x4c),_L(0x4d),_L(0x4e),_L(0x4f),\r\n//\t_L(0x50),_L(0x51),_L(0x52),_L(0x53),_L(0x54),_L(0x55),_L(0x56),_L(0x57),_L(0x58),_L(0x59),_L(0x5a),_L(0x5b),_L(0x5c),_L(0x5d),_L(0x5e),_L(0x5f),\r\n//\t_L(0x60),_L(0x61),_L(0x62),_L(0x63),_L(0x64),_L(0x65),_L(0x66),_L(0x67),_L(0x68),_L(0x69),_L(0x6a),_L(0x6b),_L(0x6c),_L(0x6d),_L(0x6e),_L(0x6f),\r\n//\t_L(0x70),_L(0x71),_L(0x72),_L(0x73),_L(0x74),_L(0x75),_L(0x76),_L(0x77),_L(0x78),_L(0x79),_L(0x7a),_L(0x7b),_L(0x7c),_L(0x7d),_L(0x7e),_L(0x7f),\r\n//\t_L(0x80),_L(0x81),_L(0x82),_L(0x83),_L(0x84),_L(0x85),_L(0x86),_L(0x87),_L(0x88),_L(0x89),_L(0x8a),_L(0x8b),_L(0x8c),_L(0x8d),_L(0x8e),_L(0x8f),\r\n//\t_L(0x90),_L(0x91),_L(0x92),_L(0x93),_L(0x94),_L(0x95),_L(0x96),_L(0x97),_L(0x98),_L(0x99),_L(0x9a),_L(0x9b),_L(0x9c),_L(0x9d),_L(0x9e),_L(0x9f),\r\n//\t_L(0xa0),_L(0xa1),_L(0xa2),_L(0xa3),_L(0xa4),_L(0xa5),_L(0xa6),_L(0xa7),_L(0xa8),_L(0xa9),_L(0xaa),_L(0xab),_L(0xac),_L(0xad),_L(0xae),_L(0xaf),\r\n//\t_L(0xb0),_L(0xb1),_L(0xb2),_L(0xb3),_L(0xb4),_L(0xb5),_L(0xb6),_L(0xb7),_L(0xb8),_L(0xb9),_L(0xba),_L(0xbb),_L(0xbc),_L(0xbd),_L(0xbe),_L(0xbf),\r\n//\t_L(0xc0),_L(0xc1),_L(0xc2),_L(0xc3),_L(0xc4),_L(0xc5),_L(0xc6),_L(0xc7),_L(0xc8),_L(0xc9),_L(0xca),_L(0xcb),_L(0xcc),_L(0xcd),_L(0xce),_L(0xcf),\r\n//\t_L(0xd0),_L(0xd1),_L(0xd2),_L(0xd3),_L(0xd4),_L(0xd5),_L(0xd6),_L(0xd7),_L(0xd8),_L(0xd9),_L(0xda),_L(0xdb),_L(0xdc),_L(0xdd),_L(0xde),_L(0xdf),\r\n//\t_L(0xe0),_L(0xe1),_L(0xe2),_L(0xe3),_L(0xe4),_L(0xe5),_L(0xe6),_L(0xe7),_L(0xe8),_L(0xe9),_L(0xea),_L(0xeb),_L(0xec),_L(0xed),_L(0xee),_L(0xef),\r\n//\t_L(0xf0),_L(0xf1),_L(0xf2),_L(0xf3),_L(0xf4),_L(0xf5),_L(0xf6),_L(0xf7),_L(0xf8),_L(0xf9),_L(0xfa),_L(0xfb),_L(0xfc),_L(0xfd),_L(0xfe),_L(0xff)\r\n//};\r\n//\r\n//#define _64(a)\t((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),\\\r\n//\t\t\t\t((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),\\\r\n//\t\t\t\t((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),\\\r\n//\t\t\t\t((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),\\\r\n//\t\t\t\t((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),\\\r\n//\t\t\t\t((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),\\\r\n//\t\t\t\t((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),\\\r\n//\t\t\t\t((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a),((a<<8)|a)\r\n//\r\n//#define _I(a)\t((a<<8)|a)\r\n//\r\n//uint16 zPalette16[65536] __attribute__ (( aligned( 32 ))) = {\r\n//\r\n//\t_64(0x00),_64(0x01),_64(0x02),_64(0x03),_64(0x04),_64(0x05),_64(0x06),_64(0x07),_64(0x08),_64(0x09),_64(0x0a),_64(0x0b),_64(0x0c),_64(0x0d),_64(0x0e),_64(0x0f),\r\n//\t_64(0x10),_64(0x11),_64(0x12),_64(0x13),_64(0x14),_64(0x15),_64(0x16),_64(0x17),_64(0x18),_64(0x19),_64(0x1a),_64(0x1b),_64(0x1c),_64(0x1d),_64(0x1e),_64(0x1f),\r\n//\t_64(0x20),_64(0x21),_64(0x22),_64(0x23),_64(0x24),_64(0x25),_64(0x26),_64(0x27),_64(0x28),_64(0x29),_64(0x2a),_64(0x2b),_64(0x2c),_64(0x2d),_64(0x2e),_64(0x2f),\r\n//\t_64(0x30),_64(0x31),_64(0x32),_64(0x33),_64(0x34),_64(0x35),_64(0x36),_64(0x37),_64(0x38),_64(0x39),_64(0x3a),_64(0x3b),_64(0x3c),_64(0x3d),_64(0x3e),_64(0x3f),\r\n//\t_64(0x40),_64(0x41),_64(0x42),_64(0x43),_64(0x44),_64(0x45),_64(0x46),_64(0x47),_64(0x48),_64(0x49),_64(0x4a),_64(0x4b),_64(0x4c),_64(0x4d),_64(0x4e),_64(0x4f),\r\n//\t_64(0x50),_64(0x51),_64(0x52),_64(0x53),_64(0x54),_64(0x55),_64(0x56),_64(0x57),_64(0x58),_64(0x59),_64(0x5a),_64(0x5b),_64(0x5c),_64(0x5d),_64(0x5e),_64(0x5f),\r\n//\t_64(0x60),_64(0x61),_64(0x62),_64(0x63),_64(0x64),_64(0x65),_64(0x66),_64(0x67),_64(0x68),_64(0x69),_64(0x6a),_64(0x6b),_64(0x6c),_64(0x6d),_64(0x6e),_64(0x6f),\r\n//\t_64(0x70),_64(0x71),_64(0x72),_64(0x73),_64(0x74),_64(0x75),_64(0x76),_64(0x77),_64(0x78),_64(0x79),_64(0x7a),_64(0x7b),_64(0x7c),_64(0x7d),_64(0x7e),_64(0x7f),\r\n//\t_64(0x80),_64(0x81),_64(0x82),_64(0x83),_64(0x84),_64(0x85),_64(0x86),_64(0x87),_64(0x88),_64(0x89),_64(0x8a),_64(0x8b),_64(0x8c),_64(0x8d),_64(0x8e),_64(0x8f),\r\n//\t_64(0x90),_64(0x91),_64(0x92),_64(0x93),_64(0x94),_64(0x95),_64(0x96),_64(0x97),_64(0x98),_64(0x99),_64(0x9a),_64(0x9b),_64(0x9c),_64(0x9d),_64(0x9e),_64(0x9f),\r\n//\t_64(0xa0),_64(0xa1),_64(0xa2),_64(0xa3),_64(0xa4),_64(0xa5),_64(0xa6),_64(0xa7),_64(0xa8),_64(0xa9),_64(0xaa),_64(0xab),_64(0xac),_64(0xad),_64(0xae),_64(0xaf),\r\n//\t_64(0xb0),_64(0xb1),_64(0xb2),_64(0xb3),_64(0xb4),_64(0xb5),_64(0xb6),_64(0xb7),_64(0xb8),_64(0xb9),_64(0xba),_64(0xbb),_64(0xbc),_64(0xbd),_64(0xbe),_64(0xbf),\r\n//\t_64(0xc0),_64(0xc1),_64(0xc2),_64(0xc3),_64(0xc4),_64(0xc5),_64(0xc6),_64(0xc7),_64(0xc8),_64(0xc9),_64(0xca),_64(0xcb),_64(0xcc),_64(0xcd),_64(0xce),_64(0xcf),\r\n//\t_64(0xd0),_64(0xd1),_64(0xd2),_64(0xd3),_64(0xd4),_64(0xd5),_64(0xd6),_64(0xd7),_64(0xd8),_64(0xd9),_64(0xda),_64(0xdb),_64(0xdc),_64(0xdd),_64(0xde),_64(0xdf),\r\n//\t_64(0xe0),_64(0xe1),_64(0xe2),_64(0xe3),_64(0xe4),_64(0xe5),_64(0xe6),_64(0xe7),_64(0xe8),_64(0xe9),_64(0xea),_64(0xeb),_64(0xec),_64(0xed),_64(0xee),_64(0xef),\r\n//\t_64(0xf0),_64(0xf1),_64(0xf2),_64(0xf3),_64(0xf4),_64(0xf5),_64(0xf6),_64(0xf7),_64(0xf8),_64(0xf9),_64(0xfa),_64(0xfb),_64(0xfc),_64(0xfd),_64(0xfe),_64(0xff),\r\n//\r\n//\t_64(0x00),_64(0x01),_64(0x02),_64(0x03),_64(0x04),_64(0x05),_64(0x06),_64(0x07),_64(0x08),_64(0x09),_64(0x0a),_64(0x0b),_64(0x0c),_64(0x0d),_64(0x0e),_64(0x0f),\r\n//\t_64(0x10),_64(0x11),_64(0x12),_64(0x13),_64(0x14),_64(0x15),_64(0x16),_64(0x17),_64(0x18),_64(0x19),_64(0x1a),_64(0x1b),_64(0x1c),_64(0x1d),_64(0x1e),_64(0x1f),\r\n//\t_64(0x20),_64(0x21),_64(0x22),_64(0x23),_64(0x24),_64(0x25),_64(0x26),_64(0x27),_64(0x28),_64(0x29),_64(0x2a),_64(0x2b),_64(0x2c),_64(0x2d),_64(0x2e),_64(0x2f),\r\n//\t_64(0x30),_64(0x31),_64(0x32),_64(0x33),_64(0x34),_64(0x35),_64(0x36),_64(0x37),_64(0x38),_64(0x39),_64(0x3a),_64(0x3b),_64(0x3c),_64(0x3d),_64(0x3e),_64(0x3f),\r\n//\t_64(0x40),_64(0x41),_64(0x42),_64(0x43),_64(0x44),_64(0x45),_64(0x46),_64(0x47),_64(0x48),_64(0x49),_64(0x4a),_64(0x4b),_64(0x4c),_64(0x4d),_64(0x4e),_64(0x4f),\r\n//\t_64(0x50),_64(0x51),_64(0x52),_64(0x53),_64(0x54),_64(0x55),_64(0x56),_64(0x57),_64(0x58),_64(0x59),_64(0x5a),_64(0x5b),_64(0x5c),_64(0x5d),_64(0x5e),_64(0x5f),\r\n//\t_64(0x60),_64(0x61),_64(0x62),_64(0x63),_64(0x64),_64(0x65),_64(0x66),_64(0x67),_64(0x68),_64(0x69),_64(0x6a),_64(0x6b),_64(0x6c),_64(0x6d),_64(0x6e),_64(0x6f),\r\n//\t_64(0x70),_64(0x71),_64(0x72),_64(0x73),_64(0x74),_64(0x75),_64(0x76),_64(0x77),_64(0x78),_64(0x79),_64(0x7a),_64(0x7b),_64(0x7c),_64(0x7d),_64(0x7e),_64(0x7f),\r\n//\t_64(0x80),_64(0x81),_64(0x82),_64(0x83),_64(0x84),_64(0x85),_64(0x86),_64(0x87),_64(0x88),_64(0x89),_64(0x8a),_64(0x8b),_64(0x8c),_64(0x8d),_64(0x8e),_64(0x8f),\r\n//\t_64(0x90),_64(0x91),_64(0x92),_64(0x93),_64(0x94),_64(0x95),_64(0x96),_64(0x97),_64(0x98),_64(0x99),_64(0x9a),_64(0x9b),_64(0x9c),_64(0x9d),_64(0x9e),_64(0x9f),\r\n//\t_64(0xa0),_64(0xa1),_64(0xa2),_64(0xa3),_64(0xa4),_64(0xa5),_64(0xa6),_64(0xa7),_64(0xa8),_64(0xa9),_64(0xaa),_64(0xab),_64(0xac),_64(0xad),_64(0xae),_64(0xaf),\r\n//\t_64(0xb0),_64(0xb1),_64(0xb2),_64(0xb3),_64(0xb4),_64(0xb5),_64(0xb6),_64(0xb7),_64(0xb8),_64(0xb9),_64(0xba),_64(0xbb),_64(0xbc),_64(0xbd),_64(0xbe),_64(0xbf),\r\n//\t_64(0xc0),_64(0xc1),_64(0xc2),_64(0xc3),_64(0xc4),_64(0xc5),_64(0xc6),_64(0xc7),_64(0xc8),_64(0xc9),_64(0xca),_64(0xcb),_64(0xcc),_64(0xcd),_64(0xce),_64(0xcf),\r\n//\t_64(0xd0),_64(0xd1),_64(0xd2),_64(0xd3),_64(0xd4),_64(0xd5),_64(0xd6),_64(0xd7),_64(0xd8),_64(0xd9),_64(0xda),_64(0xdb),_64(0xdc),_64(0xdd),_64(0xde),_64(0xdf),\r\n//\t_64(0xe0),_64(0xe1),_64(0xe2),_64(0xe3),_64(0xe4),_64(0xe5),_64(0xe6),_64(0xe7),_64(0xe8),_64(0xe9),_64(0xea),_64(0xeb),_64(0xec),_64(0xed),_64(0xee),_64(0xef),\r\n//\t_64(0xf0),_64(0xf1),_64(0xf2),_64(0xf3),_64(0xf4),_64(0xf5),_64(0xf6),_64(0xf7),_64(0xf8),_64(0xf9),_64(0xfa),_64(0xfb),_64(0xfc),_64(0xfd),_64(0xfe),_64(0xff),\r\n//\r\n//\t_64(0x00),_64(0x01),_64(0x02),_64(0x03),_64(0x04),_64(0x05),_64(0x06),_64(0x07),_64(0x08),_64(0x09),_64(0x0a),_64(0x0b),_64(0x0c),_64(0x0d),_64(0x0e),_64(0x0f),\r\n//\t_64(0x10),_64(0x11),_64(0x12),_64(0x13),_64(0x14),_64(0x15),_64(0x16),_64(0x17),_64(0x18),_64(0x19),_64(0x1a),_64(0x1b),_64(0x1c),_64(0x1d),_64(0x1e),_64(0x1f),\r\n//\t_64(0x20),_64(0x21),_64(0x22),_64(0x23),_64(0x24),_64(0x25),_64(0x26),_64(0x27),_64(0x28),_64(0x29),_64(0x2a),_64(0x2b),_64(0x2c),_64(0x2d),_64(0x2e),_64(0x2f),\r\n//\t_64(0x30),_64(0x31),_64(0x32),_64(0x33),_64(0x34),_64(0x35),_64(0x36),_64(0x37),_64(0x38),_64(0x39),_64(0x3a),_64(0x3b),_64(0x3c),_64(0x3d),_64(0x3e),_64(0x3f),\r\n//\t_64(0x40),_64(0x41),_64(0x42),_64(0x43),_64(0x44),_64(0x45),_64(0x46),_64(0x47),_64(0x48),_64(0x49),_64(0x4a),_64(0x4b),_64(0x4c),_64(0x4d),_64(0x4e),_64(0x4f),\r\n//\t_64(0x50),_64(0x51),_64(0x52),_64(0x53),_64(0x54),_64(0x55),_64(0x56),_64(0x57),_64(0x58),_64(0x59),_64(0x5a),_64(0x5b),_64(0x5c),_64(0x5d),_64(0x5e),_64(0x5f),\r\n//\t_64(0x60),_64(0x61),_64(0x62),_64(0x63),_64(0x64),_64(0x65),_64(0x66),_64(0x67),_64(0x68),_64(0x69),_64(0x6a),_64(0x6b),_64(0x6c),_64(0x6d),_64(0x6e),_64(0x6f),\r\n//\t_64(0x70),_64(0x71),_64(0x72),_64(0x73),_64(0x74),_64(0x75),_64(0x76),_64(0x77),_64(0x78),_64(0x79),_64(0x7a),_64(0x7b),_64(0x7c),_64(0x7d),_64(0x7e),_64(0x7f),\r\n//\t_64(0x80),_64(0x81),_64(0x82),_64(0x83),_64(0x84),_64(0x85),_64(0x86),_64(0x87),_64(0x88),_64(0x89),_64(0x8a),_64(0x8b),_64(0x8c),_64(0x8d),_64(0x8e),_64(0x8f),\r\n//\t_64(0x90),_64(0x91),_64(0x92),_64(0x93),_64(0x94),_64(0x95),_64(0x96),_64(0x97),_64(0x98),_64(0x99),_64(0x9a),_64(0x9b),_64(0x9c),_64(0x9d),_64(0x9e),_64(0x9f),\r\n//\t_64(0xa0),_64(0xa1),_64(0xa2),_64(0xa3),_64(0xa4),_64(0xa5),_64(0xa6),_64(0xa7),_64(0xa8),_64(0xa9),_64(0xaa),_64(0xab),_64(0xac),_64(0xad),_64(0xae),_64(0xaf),\r\n//\t_64(0xb0),_64(0xb1),_64(0xb2),_64(0xb3),_64(0xb4),_64(0xb5),_64(0xb6),_64(0xb7),_64(0xb8),_64(0xb9),_64(0xba),_64(0xbb),_64(0xbc),_64(0xbd),_64(0xbe),_64(0xbf),\r\n//\t_64(0xc0),_64(0xc1),_64(0xc2),_64(0xc3),_64(0xc4),_64(0xc5),_64(0xc6),_64(0xc7),_64(0xc8),_64(0xc9),_64(0xca),_64(0xcb),_64(0xcc),_64(0xcd),_64(0xce),_64(0xcf),\r\n//\t_64(0xd0),_64(0xd1),_64(0xd2),_64(0xd3),_64(0xd4),_64(0xd5),_64(0xd6),_64(0xd7),_64(0xd8),_64(0xd9),_64(0xda),_64(0xdb),_64(0xdc),_64(0xdd),_64(0xde),_64(0xdf),\r\n//\t_64(0xe0),_64(0xe1),_64(0xe2),_64(0xe3),_64(0xe4),_64(0xe5),_64(0xe6),_64(0xe7),_64(0xe8),_64(0xe9),_64(0xea),_64(0xeb),_64(0xec),_64(0xed),_64(0xee),_64(0xef),\r\n//\t_64(0xf0),_64(0xf1),_64(0xf2),_64(0xf3),_64(0xf4),_64(0xf5),_64(0xf6),_64(0xf7),_64(0xf8),_64(0xf9),_64(0xfa),_64(0xfb),_64(0xfc),_64(0xfd),_64(0xfe),_64(0xff),\r\n//\r\n//\t_64(0x00),_64(0x01),_64(0x02),_64(0x03),_64(0x04),_64(0x05),_64(0x06),_64(0x07),_64(0x08),_64(0x09),_64(0x0a),_64(0x0b),_64(0x0c),_64(0x0d),_64(0x0e),_64(0x0f),\r\n//\t_64(0x10),_64(0x11),_64(0x12),_64(0x13),_64(0x14),_64(0x15),_64(0x16),_64(0x17),_64(0x18),_64(0x19),_64(0x1a),_64(0x1b),_64(0x1c),_64(0x1d),_64(0x1e),_64(0x1f),\r\n//\t_64(0x20),_64(0x21),_64(0x22),_64(0x23),_64(0x24),_64(0x25),_64(0x26),_64(0x27),_64(0x28),_64(0x29),_64(0x2a),_64(0x2b),_64(0x2c),_64(0x2d),_64(0x2e),_64(0x2f),\r\n//\t_64(0x30),_64(0x31),_64(0x32),_64(0x33),_64(0x34),_64(0x35),_64(0x36),_64(0x37),_64(0x38),_64(0x39),_64(0x3a),_64(0x3b),_64(0x3c),_64(0x3d),_64(0x3e),_64(0x3f),\r\n//\t_64(0x40),_64(0x41),_64(0x42),_64(0x43),_64(0x44),_64(0x45),_64(0x46),_64(0x47),_64(0x48),_64(0x49),_64(0x4a),_64(0x4b),_64(0x4c),_64(0x4d),_64(0x4e),_64(0x4f),\r\n//\t_64(0x50),_64(0x51),_64(0x52),_64(0x53),_64(0x54),_64(0x55),_64(0x56),_64(0x57),_64(0x58),_64(0x59),_64(0x5a),_64(0x5b),_64(0x5c),_64(0x5d),_64(0x5e),_64(0x5f),\r\n//\t_64(0x60),_64(0x61),_64(0x62),_64(0x63),_64(0x64),_64(0x65),_64(0x66),_64(0x67),_64(0x68),_64(0x69),_64(0x6a),_64(0x6b),_64(0x6c),_64(0x6d),_64(0x6e),_64(0x6f),\r\n//\t_64(0x70),_64(0x71),_64(0x72),_64(0x73),_64(0x74),_64(0x75),_64(0x76),_64(0x77),_64(0x78),_64(0x79),_64(0x7a),_64(0x7b),_64(0x7c),_64(0x7d),_64(0x7e),_64(0x7f),\r\n//\t_64(0x80),_64(0x81),_64(0x82),_64(0x83),_64(0x84),_64(0x85),_64(0x86),_64(0x87),_64(0x88),_64(0x89),_64(0x8a),_64(0x8b),_64(0x8c),_64(0x8d),_64(0x8e),_64(0x8f),\r\n//\t_64(0x90),_64(0x91),_64(0x92),_64(0x93),_64(0x94),_64(0x95),_64(0x96),_64(0x97),_64(0x98),_64(0x99),_64(0x9a),_64(0x9b),_64(0x9c),_64(0x9d),_64(0x9e),_64(0x9f),\r\n//\t_64(0xa0),_64(0xa1),_64(0xa2),_64(0xa3),_64(0xa4),_64(0xa5),_64(0xa6),_64(0xa7),_64(0xa8),_64(0xa9),_64(0xaa),_64(0xab),_64(0xac),_64(0xad),_64(0xae),_64(0xaf),\r\n//\t_64(0xb0),_64(0xb1),_64(0xb2),_64(0xb3),_64(0xb4),_64(0xb5),_64(0xb6),_64(0xb7),_64(0xb8),_64(0xb9),_64(0xba),_64(0xbb),_64(0xbc),_64(0xbd),_64(0xbe),_64(0xbf),\r\n//\t_64(0xc0),_64(0xc1),_64(0xc2),_64(0xc3),_64(0xc4),_64(0xc5),_64(0xc6),_64(0xc7),_64(0xc8),_64(0xc9),_64(0xca),_64(0xcb),_64(0xcc),_64(0xcd),_64(0xce),_64(0xcf),\r\n//\t_64(0xd0),_64(0xd1),_64(0xd2),_64(0xd3),_64(0xd4),_64(0xd5),_64(0xd6),_64(0xd7),_64(0xd8),_64(0xd9),_64(0xda),_64(0xdb),_64(0xdc),_64(0xdd),_64(0xde),_64(0xdf),\r\n//\t_64(0xe0),_64(0xe1),_64(0xe2),_64(0xe3),_64(0xe4),_64(0xe5),_64(0xe6),_64(0xe7),_64(0xe8),_64(0xe9),_64(0xea),_64(0xeb),_64(0xec),_64(0xed),_64(0xee),_64(0xef),\r\n//\t_64(0xf0),_64(0xf1),_64(0xf2),_64(0xf3),_64(0xf4),_64(0xf5),_64(0xf6),_64(0xf7),_64(0xf8),_64(0xf9),_64(0xfa),_64(0xfb),/*_64(0xfc),_64(0xfd),_64(0xfe),_64(0xff)*/\r\n//\r\n//\t_I(0x00),\r\n//\t_I(0x01),\r\n//\t_I(0x02),\r\n//\t_I(0x03),\r\n//\t_I(0x04),\r\n//\t_I(0x05),\r\n//\t_I(0x06),\r\n//\t_I(0x07),\r\n//\t_I(0x08),\r\n//\t_I(0x09),\r\n//\t_I(0x0a),\r\n//\t_I(0x0b),\r\n//\t_I(0x0c),\r\n//\t_I(0x0d),\r\n//\t_I(0x0e),\r\n//\t_I(0x0f),\r\n//\t_I(0x10),\r\n//\t_I(0x11),\r\n//\t_I(0x12),\r\n//\t_I(0x13),\r\n//\t_I(0x14),\r\n//\t_I(0x15),\r\n//\t_I(0x16),\r\n//\t_I(0x17),\r\n//\t_I(0x18),\r\n//\t_I(0x19),\r\n//\t_I(0x1a),\r\n//\t_I(0x1b),\r\n//\t_I(0x1c),\r\n//\t_I(0x1d),\r\n//\t_I(0x1e),\r\n//\t_I(0x1f),\r\n//\t_I(0x20),\r\n//\t_I(0x21),\r\n//\t_I(0x22),\r\n//\t_I(0x23),\r\n//\t_I(0x24),\r\n//\t_I(0x25),\r\n//\t_I(0x26),\r\n//\t_I(0x27),\r\n//\t_I(0x28),\r\n//\t_I(0x29),\r\n//\t_I(0x2a),\r\n//\t_I(0x2b),\r\n//\t_I(0x2c),\r\n//\t_I(0x2d),\r\n//\t_I(0x2e),\r\n//\t_I(0x2f),\r\n//\t_I(0x30),\r\n//\t_I(0x31),\r\n//\t_I(0x32),\r\n//\t_I(0x33),\r\n//\t_I(0x34),\r\n//\t_I(0x35),\r\n//\t_I(0x36),\r\n//\t_I(0x37),\r\n//\t_I(0x38),\r\n//\t_I(0x39),\r\n//\t_I(0x3a),\r\n//\t_I(0x3b),\r\n//\t_I(0x3c),\r\n//\t_I(0x3d),\r\n//\t_I(0x3e),\r\n//\t_I(0x3f),\r\n//\t_I(0x40),\r\n//\t_I(0x41),\r\n//\t_I(0x42),\r\n//\t_I(0x43),\r\n//\t_I(0x44),\r\n//\t_I(0x45),\r\n//\t_I(0x46),\r\n//\t_I(0x47),\r\n//\t_I(0x48),\r\n//\t_I(0x49),\r\n//\t_I(0x4a),\r\n//\t_I(0x4b),\r\n//\t_I(0x4c),\r\n//\t_I(0x4d),\r\n//\t_I(0x4e),\r\n//\t_I(0x4f),\r\n//\t_I(0x50),\r\n//\t_I(0x51),\r\n//\t_I(0x52),\r\n//\t_I(0x53),\r\n//\t_I(0x54),\r\n//\t_I(0x55),\r\n//\t_I(0x56),\r\n//\t_I(0x57),\r\n//\t_I(0x58),\r\n//\t_I(0x59),\r\n//\t_I(0x5a),\r\n//\t_I(0x5b),\r\n//\t_I(0x5c),\r\n//\t_I(0x5d),\r\n//\t_I(0x5e),\r\n//\t_I(0x5f),\r\n//\t_I(0x60),\r\n//\t_I(0x61),\r\n//\t_I(0x62),\r\n//\t_I(0x63),\r\n//\t_I(0x64),\r\n//\t_I(0x65),\r\n//\t_I(0x66),\r\n//\t_I(0x67),\r\n//\t_I(0x68),\r\n//\t_I(0x69),\r\n//\t_I(0x6a),\r\n//\t_I(0x6b),\r\n//\t_I(0x6c),\r\n//\t_I(0x6d),\r\n//\t_I(0x6e),\r\n//\t_I(0x6f),\r\n//\t_I(0x70),\r\n//\t_I(0x71),\r\n//\t_I(0x72),\r\n//\t_I(0x73),\r\n//\t_I(0x74),\r\n//\t_I(0x75),\r\n//\t_I(0x76),\r\n//\t_I(0x77),\r\n//\t_I(0x78),\r\n//\t_I(0x79),\r\n//\t_I(0x7a),\r\n//\t_I(0x7b),\r\n//\t_I(0x7c),\r\n//\t_I(0x7d),\r\n//\t_I(0x7e),\r\n//\t_I(0x7f),\r\n//\t_I(0x80),\r\n//\t_I(0x81),\r\n//\t_I(0x82),\r\n//\t_I(0x83),\r\n//\t_I(0x84),\r\n//\t_I(0x85),\r\n//\t_I(0x86),\r\n//\t_I(0x87),\r\n//\t_I(0x88),\r\n//\t_I(0x89),\r\n//\t_I(0x8a),\r\n//\t_I(0x8b),\r\n//\t_I(0x8c),\r\n//\t_I(0x8d),\r\n//\t_I(0x8e),\r\n//\t_I(0x8f),\r\n//\t_I(0x90),\r\n//\t_I(0x91),\r\n//\t_I(0x92),\r\n//\t_I(0x93),\r\n//\t_I(0x94),\r\n//\t_I(0x95),\r\n//\t_I(0x96),\r\n//\t_I(0x97),\r\n//\t_I(0x98),\r\n//\t_I(0x99),\r\n//\t_I(0x9a),\r\n//\t_I(0x9b),\r\n//\t_I(0x9c),\r\n//\t_I(0x9d),\r\n//\t_I(0x9e),\r\n//\t_I(0x9f),\r\n//\t_I(0xa0),\r\n//\t_I(0xa1),\r\n//\t_I(0xa2),\r\n//\t_I(0xa3),\r\n//\t_I(0xa4),\r\n//\t_I(0xa5),\r\n//\t_I(0xa6),\r\n//\t_I(0xa7),\r\n//\t_I(0xa8),\r\n//\t_I(0xa9),\r\n//\t_I(0xaa),\r\n//\t_I(0xab),\r\n//\t_I(0xac),\r\n//\t_I(0xad),\r\n//\t_I(0xae),\r\n//\t_I(0xaf),\r\n//\t_I(0xb0),\r\n//\t_I(0xb1),\r\n//\t_I(0xb2),\r\n//\t_I(0xb3),\r\n//\t_I(0xb4),\r\n//\t_I(0xb5),\r\n//\t_I(0xb6),\r\n//\t_I(0xb7),\r\n//\t_I(0xb8),\r\n//\t_I(0xb9),\r\n//\t_I(0xba),\r\n//\t_I(0xbb),\r\n//\t_I(0xbc),\r\n//\t_I(0xbd),\r\n//\t_I(0xbe),\r\n//\t_I(0xbf),\r\n//\t_I(0xc0),\r\n//\t_I(0xc1),\r\n//\t_I(0xc2),\r\n//\t_I(0xc3),\r\n//\t_I(0xc4),\r\n//\t_I(0xc5),\r\n//\t_I(0xc6),\r\n//\t_I(0xc7),\r\n//\t_I(0xc8),\r\n//\t_I(0xc9),\r\n//\t_I(0xca),\r\n//\t_I(0xcb),\r\n//\t_I(0xcc),\r\n//\t_I(0xcd),\r\n//\t_I(0xce),\r\n//\t_I(0xcf),\r\n//\t_I(0xd0),\r\n//\t_I(0xd1),\r\n//\t_I(0xd2),\r\n//\t_I(0xd3),\r\n//\t_I(0xd4),\r\n//\t_I(0xd5),\r\n//\t_I(0xd6),\r\n//\t_I(0xd7),\r\n//\t_I(0xd8),\r\n//\t_I(0xd9),\r\n//\t_I(0xda),\r\n//\t_I(0xdb),\r\n//\t_I(0xdc),\r\n//\t_I(0xdd),\r\n//\t_I(0xde),\r\n//\t_I(0xdf),\r\n//\t_I(0xe0),\r\n//\t_I(0xe1),\r\n//\t_I(0xe2),\r\n//\t_I(0xe3),\r\n//\t_I(0xe4),\r\n//\t_I(0xe5),\r\n//\t_I(0xe6),\r\n//\t_I(0xe7),\r\n//\t_I(0xe8),\r\n//\t_I(0xe9),\r\n//\t_I(0xea),\r\n//\t_I(0xeb),\r\n//\t_I(0xec),\r\n//\t_I(0xed),\r\n//\t_I(0xee),\r\n//\t_I(0xef),\r\n//\t_I(0xf0),\r\n//\t_I(0xf1),\r\n//\t_I(0xf2),\r\n//\t_I(0xf3),\r\n//\t_I(0xf4),\r\n//\t_I(0xf5),\r\n//\t_I(0xf6),\r\n//\t_I(0xf7),\r\n//\t_I(0xf8),\r\n//\t_I(0xf9),\r\n//\t_I(0xfa),\r\n//\t_I(0xfb),\r\n//\t_I(0xfc),\r\n//\t_I(0xfd),\r\n//\t_I(0xfe),\r\n//\t_I(0xff),\r\n//};\r\n\r\n//static uint16 sBlurBuffer[640*448];\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n\t// extern void\ttest_render(Mth::Matrix* camera_orient, Mth::Vector* camera_pos);\r\n\t// extern void\ttest_init();\t\t\t\r\n\r\n} // namespace NxNgc\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n//\t    // Set camera configuration\r\n//\t    sc->light.cam.cfg = ( sc->projMode ) ?\r\n//\t                        DefaultLightCamera1 : DefaultLightCamera0;\r\n//\t    SetCamera(&sc->light.cam);\r\n//\t    \r\n//\t    // Light camera\r\n//\t    sc->projMode           = 0;\r\n//\t    sc->light.cam.theta    = 0;\r\n//\t    sc->light.cam.phi      = 60;\r\n//\t    sc->light.cam.distance = 3000.0F;\r\n//\t\r\n//\t\r\n//\t\tstatic void SetCamera( MyCameraObj* cam )\r\n//\t\t{\r\n//\t\t\tf32  r_theta, r_phi;\r\n//\t\t\t\r\n//\t\t\tr_theta = (f32)cam->theta * PI / 180.0F;\r\n//\t\t\tr_phi   = (f32)cam->phi   * PI / 180.0F;\r\n//\t\t\r\n//\t\t\tcam->cfg.location.x =\r\n//\t\t\t\tcam->distance * cosf(r_theta) * cosf(r_phi);\r\n//\t\t\tcam->cfg.location.y =\r\n//\t\t\t\tcam->distance * sinf(r_theta) * cosf(r_phi);\r\n//\t\t\tcam->cfg.location.z =\r\n//\t\t\t\tcam->distance * sinf(r_phi);\r\n//\t\t\r\n//\t\t\tMTXLookAt(\r\n//\t\t\t\tcam->view,\r\n//\t\t\t\t&cam->cfg.location,\r\n//\t\t\t\t&cam->cfg.up,\r\n//\t\t\t\t&cam->cfg.target );    \r\n//\t\t\r\n//\t\t\tif ( cam->cfg.type == GX_PERSPECTIVE )\r\n//\t\t\t{\r\n//\t\t\t\tMTXFrustum(\r\n//\t\t\t\t\tcam->proj,\r\n//\t\t\t\t\tcam->cfg.top,\r\n//\t\t\t\t\t- (cam->cfg.top),\r\n//\t\t\t\t\tcam->cfg.left,\r\n//\t\t\t\t\t- (cam->cfg.left),\r\n//\t\t\t\t\tcam->cfg.znear,\r\n//\t\t\t\t\tcam->cfg.zfar );\r\n//\t\t\t}\r\n//\t\t\telse // ( cam->cfg.type == GX_ORTHOGRAPHIC )\r\n//\t\t\t{\r\n//\t\t\t\tMTXOrtho(\r\n//\t\t\t\t\tcam->proj,\r\n//\t\t\t\t\tcam->cfg.top,\r\n//\t\t\t\t\t- (cam->cfg.top),\r\n//\t\t\t\t\tcam->cfg.left,\r\n//\t\t\t\t\t- (cam->cfg.left),\r\n//\t\t\t\t\tcam->cfg.znear,\r\n//\t\t\t\t\tcam->cfg.zfar );\r\n//\t\t\t}\r\n//\t\t\t\r\n//\t\t\tGXSetProjection(cam->proj, cam->cfg.type);\r\n//\t\t}\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_start_engine( void )\r\n{\r\n    uint32\tsize;\r\n\r\n\tNxNgc::InitialiseEngine();\r\n\r\n\t\r\n\tmp_particle_manager = new CNgcNewParticleManager;\r\n\r\n//\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n//\r\n//\t// Allocate memory for shadow map\r\n\tsize = GX::GetTexBufferSize( SHADOW_TEXTURE_SIZE, SHADOW_TEXTURE_SIZE, GX_TF_I4, GX_FALSE, 0 );\r\n\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n    shadowTextureData = new uint8[size];\r\n\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n//\r\n//\tsize = GXGetTexBufferSize( 320, 224, GX_TF_Z8, GX_FALSE, 0 );\r\n//\tzTextureDataH = new uint8[size];\r\n//\tzTextureDataL = new uint8[size];\r\n//\r\n//\tsize = GXGetTexBufferSize( 320, 224, GX_TF_RGBA8, GX_FALSE, 0 );\r\n//\tscreenTextureData = new uint8[size];\r\n//\r\n//\tsize = GXGetTexBufferSize( 320, 224, GX_TF_RGBA8, GX_FALSE, 0 );\r\n//\tfocusTextureData = new uint8[size];\r\n//\r\n//\tsize = GXGetTexBufferSize( BLUR_TEXTURE_SIZE, BLUR_TEXTURE_SIZE, GX_TF_I4, GX_FALSE, 0 );\r\n//    blurTextureData = new uint8[size];\r\n//\r\n//\tsize = GXGetTexBufferSize( 640, 448, GX_TF_A8, GX_FALSE, 0 );\r\n//\tvolumeTextureData = new uint8[size];\r\n//\r\n//\r\n//\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\r\n\tif( NxNgc::EngineGlobals.use_widescreen )\r\n\t{\r\n\t\tScript::RunScript( \"screen_setup_widescreen\" );\r\n\t}\r\n\tmp_weather = new CNgcWeather;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_pre_render( void )\r\n{\r\n\t//NsDisplay::begin();\r\n\t//NsRender::begin();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_post_render( void )\r\n{\r\n\t//NsRender::end();\r\n\t//NsDisplay::end();\r\n//\tD3DDevice_Swap( D3DSWAP_DEFAULT );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_render_world( void )\r\n{\r\n\tif ( gLoadingScreenActive ) return;\r\n\r\n\tNsBuffer::begin();\r\n\r\n\tg_object = 0;\r\n\tg_view_scene = NULL;\r\n//\tif ( gPrintMatStats )\r\n//\t{\r\n//\t\tgPrintMatStats = false;\r\n//\r\n//\t\tchar *blend_text[] =\r\n//\t\t{\r\n//\t\t\t\"DIFFUSE        \",\r\n//\t\t\t\"ADD            \",\r\n//\t\t\t\"ADD_FIXED      \",\r\n//\t\t\t\"SUBTRACT       \",\r\n//\t\t\t\"SUB_FIXED      \",\r\n//\t\t\t\"BLEND          \",\r\n//\t\t\t\"BLEND_FIXED    \",\r\n//\t\t\t\"MODULATE       \",\r\n//\t\t\t\"MODULATE_FIXED \",\r\n//\t\t\t\"BRIGHTEN       \",\r\n//\t\t\t\"BRIGHTEN_FIXED \",\r\n//\t\t};\r\n//\r\n//\t\tOSReport( \"Unique blend modes: %d\\n\\n\", num_u_mat );\r\n//\r\n//\t\tfor ( int um = 0; um < num_u_mat; um++ )\r\n//\t\t{\r\n//\t\t\tOSReport( \"%d: (%4d) \", p_u_mat[um]->m_passes, u_mat_count[um] );\r\n//\r\n//\t\t\tNxNgc::sMaterialPassHeader * p_u_pass = (NxNgc::sMaterialPassHeader *)&p_u_mat[um][1];\r\n//\t\t\tfor ( int p = 0; p < p_u_mat[um]->m_passes; p++ )\r\n//\t\t\t{\r\n//\t\t\t\tif ( p_u_pass[p].m_blend_mode <= 10 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tOSReport( \"%s\", blend_text[p_u_pass[p].m_blend_mode] );\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tOSReport( \"<unknown>      \" );\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\tOSReport( \"\\n\" );\r\n//\t\t}\r\n//\t\t\r\n//\t}\r\n\t\r\n\tNsCamera cam;\r\n\tMtx light;\r\n\tMTXIdentity( light );\r\n\r\n\tNxNgc::EngineGlobals.gpuBusy = true;\r\n\r\n#ifndef __NOPT_FINAL__\r\n\tif ( gDumpHeap )\r\n\t{\r\n\t\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\t\r\n\t\tOSReport (\"MEM CONTEXT: %s\\n\",Mem::Manager::sHandle().GetContextName());\r\n\t\tOSReport(\"Name            Used  Frag  Free   Blocks\\n\");\r\n\t\tOSReport(\"--------------- ----- ----- ------ ------\\n\");\r\n\t\tMem::Heap* heap;\r\n\t\tfor (heap = mem_man.FirstHeap(); heap != NULL; heap = mem_man.NextHeap(heap))\r\n\t\t{\t\t\r\n\t\t\t\tMem::Region* region = heap->ParentRegion();\t\t\t\r\n\t\t\t\tOSReport( \"%12s: %6dK %6dK %6dK   %6d \\n\",\r\n\t\t\t\t\t\theap->GetName(),\r\n\t\t\t\t\t\theap->mUsedMem.m_count / 1024,\r\n\t\t\t\t\t\theap->mFreeMem.m_count / 1024,\r\n\t\t\t\t\t\tregion->MemAvailable() / 1024,\r\n\t\t\t\t\t\theap->mUsedBlocks.m_count\r\n\t\t\t\t\t\t);\t\t\t\t\t\t\t\t\t\t\r\n\t\t}\r\n\t\tgDumpHeap = false;\r\n\t}\r\n#endif\t\t// __NOPT_FINAL__\r\n\r\n//\tNsPrim::end();\r\n//\tNsRender::end();\r\n//\r\n////\tif ( movies )\r\n////\t{\r\n////\t\tNsDisplay::end( false );\r\n////\t}\r\n////\telse\r\n////\t{\r\n//\t\tNsDisplay::end( true );\r\n////\t}\r\n\r\n\r\n\tNxNgc::process_instances();\r\n\r\n\tNsDisplay::begin();\r\n//\tNsDisplay::end();\r\n//\tNsDisplay::begin();\r\n\r\n\r\n//\t// Create color map if necessary.\r\n//\tif ( !color_map_created )\r\n//\t{\r\n//\t\tcolor_map_created = true;\r\n//\r\n//\t\tfor ( int y = 0; y < COLOR_MAP_SIZE; y++ )\r\n//\t\t{\r\n//\t\t\tfor ( int x = 0; x < COLOR_MAP_SIZE; x++ )\r\n//\t\t\t{\r\n//\t\t\t\tint r;\r\n//\t\t\t\tint g;\r\n//\r\n//\t\t\t\tr = 0;\r\n//\t\t\t\tr += ( x / 4 ) * 32;\r\n//\t\t\t\tr += ( x & 3 );\r\n//\t\t\t\tr += ( ( y / 4 ) * ( COLOR_MAP_SIZE * 4 * 2 ) );\r\n//\t\t\t\tr += ( ( y & 3 ) * 4 );\r\n//\r\n//\t\t\t\tg = 16;\r\n//\t\t\t\tg += ( x / 4 ) * 32;\r\n//\t\t\t\tg += ( x & 3 );\r\n//\t\t\t\tg += ( ( y / 4 ) * ( COLOR_MAP_SIZE * 4 * 2 ) );\r\n//\t\t\t\tg += ( ( y & 3 ) * 4 );\r\n//\r\n//\t\t\t\t// Red across.\r\n//\t\t\t\tcolorMap[r] = ( x * 256 ) / COLOR_MAP_SIZE;\r\n//\t\t\t\t// Green down.\r\n//\t\t\t\tcolorMap[g] = ( ( ( y * 256 ) / COLOR_MAP_SIZE ) << 8 );\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n\r\n\r\n\r\n\r\n\t// Clear to black with alpha of 124.\r\n\t// This is important as the shadow volume stuff uses the alpha channel as a stencil buffer.\r\n\t// With destination alpha, the RGBA channels each have 6 bits, so they are only accurate to multiples of 4.\r\n\t// To save having to copy the alpha map to a texture, we do a 2-pass full-screen polygon.\r\n\t// 1. And the alpha channel with 128. As it was set to 124, anything positive will have bit (128) set.\r\n\t// 2. Blend alpha with framebuffer.\r\n//\tNsDisplay::setBackgroundColor( (GXColor){0,0,0,124} );\r\n\tNsDisplay::setBackgroundColor( (GXColor){0,0,0,255} );\r\n\tNsRender::begin();\r\n\tNsPrim::begin();\r\n\r\n//\tcam.orthographic( 0, 0, 640, 448 );\r\n//\tcam.begin();\r\n//\r\n//\tGX::SetNumTevStages(1);\r\n//\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetNumTexGens( 0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE, GX_TRUE, GX_FALSE, GX_FALSE );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n//\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\r\n//\tNsPrim::quad(   0.0f,   0.0f, -9999.0f,\r\n//\t\t\t\t  640.0f,   0.0f, -9999.0f,\r\n//\t\t\t\t  640.0f, 448.0f, -9999.0f,\r\n//\t\t\t\t    0.0f, 448.0f, -9999.0f,\r\n//\t\t\t\t  (GXColor){128,128,128,0} );\r\n//\r\n//\tcam.end();\r\n\r\n//\tbool movies = Flx::Movie_Render();\r\n\r\n\t//--------------------------------------------------------------\r\n\t//--------------------------------------------------------------\r\n\t//--------------------------------------------------------------\r\n\r\n#\tifdef __USE_PROFILER__\r\n\tSys::VUProfiler->PushContext( 128,128,0 );\r\n#\tendif\t\t// __USE_PROFILER__\r\n\tif( sp_loaded_scenes[0] != NULL )\r\n\t{\r\n\t\tGX::SetZMode ( GX_FALSE, GX_ALWAYS, GX_FALSE );\r\n\t\r\n\r\n\r\n\r\n\t//\t// 8bit mode\r\n\t//\tshCpFmt = GX_TF_Z8;\r\n\t//\tshFmt   = GX_TF_I8;\r\n\t//\r\n\t\t//-------------------------------------------\r\n\t\t//  1st. pass\r\n\t\t//  Make an image viewed from the light\r\n\t\t//-------------------------------------------\r\n\t\r\n\t\t// Color update is disabled. Only Z will be updated.\r\n\t//\t\tGXSetColorUpdate(GX_DISABLE);\r\n\t\r\n\t\t// To draw \"second\" surfaces from the light\r\n\t\t//GX::SetCullMode(GX_CULL_FRONT);\r\n\t\r\n\t\t// Set viewport for making shadow texture\r\n\t//\t\tGXSetViewport(0, 0, SHADOW_TEXTURE_SIZE, SHADOW_TEXTURE_SIZE, 0.0F, 1.0F);\r\n\t//\t\tGXSetScissor(0, 0, (u32)SHADOW_TEXTURE_SIZE, (u32)SHADOW_TEXTURE_SIZE);\r\n\t\r\n\t\t// Set up the camera..\r\n\t\t//NxNgc::set_camera( &( cur_camera->GetMatrix()), &( cur_camera->GetPos()), cur_camera->GetAdjustedHFOV(), p_cur_viewport->GetAspectRatio());\r\n\t\r\n\t\t// Set render mode to use only constant color\r\n\t\t// because we need only depth buffer\r\n\t//\t\tGXSetNumChans(1);\r\n\t\tGX::SetChanCtrl(\r\n\t\t\tGX_COLOR0A0,\r\n\t\t\tGX_DISABLE,    // disable channel\r\n\t\t\tGX_SRC_REG,    // amb source\r\n\t\t\tGX_SRC_REG,    // mat source\r\n\t\t\tGX_LIGHT_NULL, // light mask\r\n\t\t\tGX_DF_CLAMP,   // diffuse function\r\n\t\t\tGX_AF_NONE );\r\n\t\r\n\t\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );\r\n\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\tGX::SetTevColorInOp( GX_TEVSTAGE0,\t   GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV );\r\n\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\r\n\t\r\n\t\t// Draw models\r\n\t//\t\tMTXCopy(sc->light.cam.view, tmo.view);\r\n\t//\t\tDrawModels(&tmo, sc->modelRot);\r\n\t//\t\r\n//\t\tNxNgc::render_instances( true );\r\n\t\tNxNgc::EngineGlobals.poly_culling = false;\r\n\t\tNxNgc::render_shadow_targets();\r\n\t\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t// Draw line around border.\r\n\t\tcam.orthographic( 0, 0, 640, 448 );\r\n\t\tcam.begin();\r\n\r\n\t\tGX::SetPointSize( 6, GX_TO_ONE );\r\n\t\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );\r\n\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\r\n\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\r\n\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){0,0,0,255} );\r\n\r\n\t\tGX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n\r\n\t\tfor ( int vvv = 0; vvv < 8; vvv++ )\r\n\t\t{\r\n\t\t\tfloat min = -1.0f + ( (float)vvv / 4.0f );\r\n\t\t\tfloat max = (float)SHADOW_TEXTURE_SIZE - ( (float)vvv / 4.0f );\r\n\t\t\tGX::Begin( GX_LINESTRIP, GX_VTXFMT0, 5 ); \r\n\t\t\t\tGX::Position3f32(min, min, -1.0f);\r\n\t\t\t\tGX::Position3f32(max, min, -1.0f);\r\n\t\t\t\tGX::Position3f32(max, max, -1.0f);\r\n\t\t\t\tGX::Position3f32(min, max, -1.0f);\r\n\t\t\t\tGX::Position3f32(min, min, -1.0f);\r\n\t\t\tGX::End();\r\n\t\t}\r\n\t\tcam.end();\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t//\t\t// Copy shadow image into texture\r\n\t//\t\tGXSetTexCopySrc(0, 0, SHADOW_TEXTURE_SIZE, SHADOW_TEXTURE_SIZE);\r\n\t//\t\tGXSetTexCopyDst(SHADOW_TEXTURE_SIZE, SHADOW_TEXTURE_SIZE, GX_TF_Z16, GX_FALSE);\r\n\t//\t\tGXCopyTex(zTextureData, GX_FALSE);\r\n\t//\r\n\t//\t\t// Wait for finishing the copy task in the graphics pipeline\r\n\t//\t\tGXPixModeSync();\r\n\t\r\n//\t\t// Draw line around border.\r\n//\r\n//\t\tcam.orthographic( 0, 0, 640, 448 );\r\n//\t\tcam.begin();\r\n//\r\n//\t\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );\r\n//\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,\r\n//\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV,\r\n//\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\tGX::SetTevColorInOp( GX_TEVSTAGE0,\t   GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC,\r\n//\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\t\tGX::SetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL );\r\n//\r\n//\t\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n//\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){128,128,128,255} );\r\n//\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\t\r\n//\t\tGX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n//\t\r\n//\t\tfor ( int vvv = 0; vvv < 8; vvv++ )\r\n//\t\t{\r\n//\t\t\tfloat min = -1.0f + ( (float)vvv / 4.0f );\r\n//\t\t\tfloat max = (float)SHADOW_TEXTURE_SIZE - ( (float)vvv / 4.0f );\r\n//\t\t\tGX::Begin( GX_LINESTRIP, GX_VTXFMT0, 5 ); \r\n//\t\t\t\tGX::Position3f32(min, min, -1.0f);\r\n//\t\t\t\tGX::Position3f32(max, min, -1.0f);\r\n//\t\t\t\tGX::Position3f32(max, max, -1.0f);\r\n//\t\t\t\tGX::Position3f32(min, max, -1.0f);\r\n//\t\t\t\tGX::Position3f32(min, min, -1.0f);\r\n//\t\t\tGX::End();\r\n//\t\t}\r\n\r\n\r\n\t\t// Copy shadow image into texture\r\n\t\tGX::SetTexCopySrc(0, 0, SHADOW_TEXTURE_SIZE, SHADOW_TEXTURE_SIZE);\r\n\t\tGX::SetTexCopyDst(SHADOW_TEXTURE_SIZE, SHADOW_TEXTURE_SIZE, GX_CTF_R4, GX_FALSE);\r\n\t\tGX::CopyTex(shadowTextureData, GX_FALSE);\r\n\t\r\n\t\t// Wait for finishing the copy task in the graphics pipeline\r\n\t\tGX::PixModeSync();\r\n\t\r\n\t\t// Enable color update\r\n\t//\t\tGXSetColorUpdate(GX_ENABLE);\r\n\t\r\n\t\t// Restore culling mode to normal\r\n\t\t//GX::SetCullMode(GX_CULL_BACK);\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n//\t\t//--------------------------------------------------------------\r\n//\t\t//--------------------------------------------------------------\r\n//\t\t//--------------------------------------------------------------\r\n//\t\r\n//\t\t// Horrible hack - this should be somewhere else ASAP.\r\n//\t\r\n//\t\r\n//\t\tGX::UploadTexture( shadowTextureData,\r\n//\t\t\t\t\t\t   SHADOW_TEXTURE_SIZE,\r\n//\t\t\t\t\t\t   SHADOW_TEXTURE_SIZE,\r\n//\t\t\t\t\t\t   GX_TF_C4,\r\n//\t\t\t\t\t\t   GX_CLAMP,\r\n//\t\t\t\t\t\t   GX_CLAMP,\r\n//\t\t\t\t\t\t   GX_FALSE,\r\n//\t\t\t\t\t\t   GX_LINEAR,\r\n//\t\t\t\t\t\t   GX_LINEAR,\r\n//\t\t\t\t\t\t   0.0f,\r\n//\t\t\t\t\t\t   0.0f,\r\n//\t\t\t\t\t\t   0.0f,\r\n//\t\t\t\t\t\t   GX_FALSE,\r\n//\t\t\t\t\t\t   GX_FALSE,\r\n//\t\t\t\t\t\t   GX_ANISO_1,\r\n//\t\t\t\t\t\t   GX_TEXMAP0 );\r\n//\r\n//\t\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, SHADOW_TEXTURE_SIZE, SHADOW_TEXTURE_SIZE );\r\n//\r\n//\t\tGX::UploadPalette( &shadowPalette,\r\n//\t\t\t\t\t\t   GX_TL_RGB5A3,\r\n//\t\t\t\t\t\t   GX_TLUT_16,\r\n//\t\t\t\t\t\t   GX_TEXMAP0 ); \r\n//\r\n//\r\n//\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n//\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n//\t\r\n//\t\tGX::SetTexChanTevIndCull( 1, 1, 1, 0, GX_CULL_NONE );\r\n//\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n//\r\n//\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO,\r\n//\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV,\r\n//\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_RASC, GX_CC_ZERO,\r\n//\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\r\n//\t\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n//\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){128,128,128,255} );\r\n//\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\t\r\n//\t\tMtx mv;\r\n//\t\tMTXIdentity( mv );\r\n//\t\tGX::LoadTexMtxImm(mv, GX_TEXMTX0, GX_MTX3x4);\r\n//\t\r\n//\t\t// Set current vertex descriptor to enable position and color0.\r\n//\t\t// Both use 8b index to access their data arrays.\r\n//\t\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n//\t\r\n//\t\t// Send coordinates.\r\n//\t//\t\tGXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t//\t\t\tGXPosition3f32(-BLUR_BORDER, -BLUR_BORDER, -1.0f);\r\n//\t//\t\t\tGXTexCoord2f32(0.0f, 0.0f);\r\n//\t//\t\t\tGXPosition3f32(BLUR_TEXTURE_SIZE+BLUR_BORDER, -BLUR_BORDER, -1.0f);\r\n//\t//\t\t\tGXTexCoord2f32(1.0f, 0.0f);\r\n//\t//\t\t\tGXPosition3f32(BLUR_TEXTURE_SIZE+BLUR_BORDER, BLUR_TEXTURE_SIZE+BLUR_BORDER, -1.0f);\r\n//\t//\t\t\tGXTexCoord2f32(1.0f, 1.0f);\r\n//\t//\t\t\tGXPosition3f32(-BLUR_BORDER, BLUR_TEXTURE_SIZE+BLUR_BORDER, -1.0f);\r\n//\t//\t\t\tGXTexCoord2f32(0.0f, 1.0f);\r\n//\t//\t\tGXEnd();\r\n//\t\r\n//\t\r\n//\t\r\n//\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t\t\tGX::Position3f32(0.0f, 0.0f, -1.0f);\r\n//\t\t\tGX::TexCoord2f32(BLUR_0, BLUR_0);\r\n//\t\t\tGX::Position3f32(BLUR_TEXTURE_SIZE, 0.0f, -1.0f);\r\n//\t\t\tGX::TexCoord2f32(BLUR_1, BLUR_0);\r\n//\t\t\tGX::Position3f32(BLUR_TEXTURE_SIZE, BLUR_TEXTURE_SIZE, -1.0f);\r\n//\t\t\tGX::TexCoord2f32(BLUR_1, BLUR_1);\r\n//\t\t\tGX::Position3f32(0.0f, BLUR_TEXTURE_SIZE, -1.0f);\r\n//\t\t\tGX::TexCoord2f32(BLUR_0, BLUR_1);\r\n//\t\tGX::End();\r\n//\t\r\n//\t\t// Draw line around blur texture.\r\n//\t\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );\r\n//\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n//\r\n//\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,\r\n//\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV,\r\n//\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\r\n//\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC,\r\n//\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\r\n//\t\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n//\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){128,128,128,255} );\r\n//\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\t\r\n//\t\tGX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n//\t\r\n//\t\tGX::Begin( GX_LINESTRIP, GX_VTXFMT0, 5 ); \r\n//\t\t\tGX::Position3f32(0.0f, 0.0f, -1.0f);\r\n//\t\t\tGX::Position3f32(BLUR_TEXTURE_SIZE-1, 0.0f, -1.0f);\r\n//\t\t\tGX::Position3f32(BLUR_TEXTURE_SIZE-1, BLUR_TEXTURE_SIZE-1, -1.0f);\r\n//\t\t\tGX::Position3f32(0.0f, BLUR_TEXTURE_SIZE-1, -1.0f);\r\n//\t\t\tGX::Position3f32(0.0f, 0.0f, -1.0f);\r\n//\t\tGX::End();\r\n//\r\n//\t\t// Copy blur image into texture\r\n//\t\tGX::SetTexCopySrc(0, 0, BLUR_TEXTURE_SIZE, BLUR_TEXTURE_SIZE);\r\n//\t\tGX::SetTexCopyDst(BLUR_TEXTURE_SIZE, BLUR_TEXTURE_SIZE, GX_CTF_R4, GX_FALSE);\r\n//\t\tGX::CopyTex(blurTextureData, GX_TRUE);\r\n//\t\r\n//\t\t// Wait for finishing the copy task in the graphics pipeline\r\n//\t\tGX::PixModeSync();\r\n//\t\r\n//\t\r\n//\t//\t\t// Clear screen to black.\r\n//\t//\t\tGX::SetNumTevStages(1);\r\n//\t//\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);\r\n//\t//\t\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t//\t\tGX::SetNumTexGens( 0 );\r\n//\t//\t\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t//\t\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t//\t\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t//\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n//\t//\t\tGX::SetTevKColorSel( GX_TEVSTAGE0, GX_TEV_KCSEL_K0 );\r\n//\t//\t\tGX::SetTevKAlphaSel( GX_TEVSTAGE0, GX_TEV_KASEL_K0_A );\r\n//\t//\t\tGX::SetTevKColor( GX_KCOLOR0, (GXColor){0,0,0,255} );\r\n//\t//\t\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_KONST );\r\n//\t//\t\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_KONST );\r\n//\t//\r\n//\t//\t\tGXSetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n//\t//\r\n//\t//\t\t// Send coordinates.\r\n//\t//\t\tGXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t//\t\t\tGXPosition3f32(0.0f,   0.0f,   -50000.0f);\r\n//\t//\t\t\tGXPosition3f32(640.0f, 0.0f,   -50000.0f);\r\n//\t//\t\t\tGXPosition3f32(640.0f, 480.0f, -50000.0f);\r\n//\t//\t\t\tGXPosition3f32(0.0f,   480.0f, -50000.0f);\r\n//\t//\t\tGXEnd();\r\n//\t\r\n//\t\tcam.end();\r\n\r\n\t\t// Clear to bg color.\r\n\t\tcam.orthographic( 0, 0, 640, 448 );\r\n\t\tcam.begin();\r\n\r\n\t\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );\r\n\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\r\n\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\r\n\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n\r\n\t\tGX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n\r\n\t\tif ( g_in_cutscene )\r\n\t\t{\r\n\t\t\t// Bars must be black.\r\n\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){0,0,0,255} );\r\n\t\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\t\t\tGX::Position3f32( -4.0f, -4.0f, -1.0f );\r\n\t\t\t\tGX::Position3f32( -4.0f+648.0f, -4.0f, -1.0f );\r\n\t\t\t\tGX::Position3f32( -4.0f+648.0f, -4.0f+488.0f, -1.0f );\r\n\t\t\t\tGX::Position3f32( -4.0f, -4.0f+488.0f, -1.0f );\r\n\t\t\tGX::End();\r\n\r\n\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){0x50,0x60,0x70,255} );\r\n\t\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\t\t\tGX::Position3f32( -4.0f, 56.0f, -1.0f );\r\n\t\t\t\tGX::Position3f32( -4.0f+648.0f, 56.0f, -1.0f );\r\n\t\t\t\tGX::Position3f32( -4.0f+648.0f, 336.0f, -1.0f );\r\n\t\t\t\tGX::Position3f32( -4.0f, 336.0f, -1.0f );\r\n\t\t\tGX::End();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Set to sky color.\r\n\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){0x50,0x60,0x70,255} );\r\n\t\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\t\t\tGX::Position3f32( -4.0f, -4.0f, -1.0f );\r\n\t\t\t\tGX::Position3f32( -4.0f+648.0f, -4.0f, -1.0f );\r\n\t\t\t\tGX::Position3f32( -4.0f+648.0f, -4.0f+488.0f, -1.0f );\r\n\t\t\t\tGX::Position3f32( -4.0f, -4.0f+488.0f, -1.0f );\r\n\t\t\tGX::End();\r\n\t\t}\r\n\t\tcam.end();\r\n\t}\r\n#\tifdef __USE_PROFILER__\r\n\tSys::VUProfiler->PopContext();\r\n#\tendif\t\t// __USE_PROFILER__\r\n\r\n\t//--------------------------------------------------------------\r\n\t//--------------------------------------------------------------\r\n\t//--------------------------------------------------------------\r\n\tint rendered = 0;\r\n\tint considered = 0;\r\n\tmeshes_considered = 0;\r\n\r\n\tNx::CFog::sFogUpdate();\r\n\r\n\t// Note: this method of setting up the camera must change\r\n\t// so that the p_nx module does not reference things higher up the hierarchy.\r\n\tint num_viewports = CViewportManager::sGetNumActiveViewports();\r\n\tfor( int v = 0; v < num_viewports; ++v )\r\n\t{\r\n\t\tNxNgc::render_begin();\r\n\r\n\t\tNxNgc::EngineGlobals.viewport = ( 1 << v );\r\n\t\tCViewport *p_cur_viewport = CViewportManager::sGetActiveViewport( v );\r\n\t\tGfx::Camera *cur_camera = NULL;\r\n\t\tif ( p_cur_viewport ) cur_camera = p_cur_viewport->GetCamera();\r\n\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::VUProfiler->PushContext( 0,128,0 );\r\n#\tendif\t\t// __USE_PROFILER__\r\n\t\tif( cur_camera && ( sp_loaded_scenes[0] != NULL ))\r\n\t\t{\r\n//\t\t\tNxNgc::EngineGlobals.viewport.X\t\t= (DWORD)( p_cur_viewport->GetOriginX() * NxNgc::EngineGlobals.backbuffer_width );\r\n//\t\t\tNxNgc::EngineGlobals.viewport.Y\t\t= (DWORD)( p_cur_viewport->GetOriginY() * NxNgc::EngineGlobals.backbuffer_height );\r\n//\t\t\tNxNgc::EngineGlobals.viewport.Width\t= (DWORD)( p_cur_viewport->GetWidth() * NxNgc::EngineGlobals.backbuffer_width );\r\n//\t\t\tNxNgc::EngineGlobals.viewport.Height\t= (DWORD)( p_cur_viewport->GetHeight() * NxNgc::EngineGlobals.backbuffer_height );\r\n//\t\t\tNxNgc::EngineGlobals.viewport.MinZ\t\t= 0.0f;\r\n//\t\t\tNxNgc::EngineGlobals.viewport.MaxZ\t\t= 1.0f;\r\n//\t\t\tD3DDevice_SetViewport( &NxNgc::EngineGlobals.viewport );\r\n\r\n\t\t\tfloat vx = p_cur_viewport->GetOriginX() * 640.0f;\r\n\t\t\tfloat vy = p_cur_viewport->GetOriginY() * 448.0f;\r\n\t\t\tfloat vw = p_cur_viewport->GetWidth() * 640.0f;\r\n\t\t\tfloat vh = p_cur_viewport->GetHeight() * 448.0f;\r\n\t\t\t\r\n\t\t\tif( NxNgc::EngineGlobals.letterbox_active )\r\n\t\t\t{\r\n\t\t\t\tvy += 448.0f / 8.0f;\r\n\t\t\t\tvh -= 448.0f / 4.0f;\r\n\t\t\t}\r\n\r\n            GX::SetViewport( vx, vy, vw, vh, 0.0f, 1.0f );\r\n            GX::SetScissor( (u32)vx, (u32)vy, (u32)vw, (u32)vh );\r\n\r\n\t\t\tNxNgc::set_camera( &( cur_camera->GetMatrix()), &( cur_camera->GetPos()), cur_camera->GetAdjustedHFOV(), p_cur_viewport->GetAspectRatio());\r\n\r\n\t\t\t// There is no bounding box transform for rendering the world.\r\n\t//\t\tNxNgc::set_frustum_bbox_transform( NULL );\r\n\r\n\t\t\t// Render objects of interest for the render target (shadow objects).\r\n\t//\t\tNxNgc::render_shadow_targets();\r\n\r\n\t\t\t// Render the world. At this stage, non-sky scenes are rendered using just the opaque sections.\r\n\r\n\t\t\tGX::LoadNrmMtxImm( light, GX_PNMTX0);\r\n\t\t\tfor( int i = 0; i < MAX_LOADED_SCENES; i++ )\r\n\t\t\t{\r\n\t\t\t\tif( sp_loaded_scenes[i] )\r\n\t\t\t\t{\r\n\t\t\t\t\tCNgcScene *pNgcScene = static_cast<CNgcScene *>( sp_loaded_scenes[i] );\r\n\r\n\t\t\t\t\t// If this is a sky scene, disable z buffer reads and writes, otherwise enable them.\r\n\t\t\t\t\tif( pNgcScene->IsSky())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tNxNgc::EngineGlobals.poly_culling = false;\r\n\t\t\t\t\t\t// Set up the camera.\r\n\t\t\t\t\t\tMth::Vector\tcentre_pos( 0.0f, 0.0f, 0.0f );\r\n\t\t\t\t\t\tNxNgc::set_camera( &( cur_camera->GetMatrix()), &centre_pos, cur_camera->GetAdjustedHFOV(), p_cur_viewport->GetAspectRatio(), ( 30000.0f / pNgcScene->GetEngineScene()->m_sphere[W] ) );\r\n\t\r\n\t\t\t\t\t\tGX::SetZMode ( GX_FALSE, GX_ALWAYS, GX_FALSE );\r\n\t\r\n\t\t\t\t\t\tuint32 flags = ( NxNgc::vRENDER_OPAQUE | NxNgc::vRENDER_SEMITRANSPARENT | NxNgc::vRENDER_LIT );\r\n\r\n\t\t\t\t\t\tNxNgc::make_scene_visible( pNgcScene->GetEngineScene() );\r\n\t\t\t\t\t\tNxNgc::render_scene( pNgcScene->GetEngineScene(), NULL, flags );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tNxNgc::EngineGlobals.poly_culling = true;\r\n\t\t\t\t\t\t// Set up the camera..\r\n\t\t\t\t\t\tNxNgc::set_camera( &( cur_camera->GetMatrix()), &( cur_camera->GetPos()), cur_camera->GetAdjustedHFOV(), p_cur_viewport->GetAspectRatio());\r\n\r\n\t\t\t\t\t\t// Build relevant occlusion poly list, now that the camera is set.\r\n\t\t\t\t\t\tNxNgc::BuildOccluders( &( cur_camera->GetPos()), v);\r\n\r\n\t\t\t\t\t\t// Build relevant occlusion poly list, now that the camera is set.\r\n\t\t\t\t\t\tGX::SetZMode ( GX_TRUE, GX_LEQUAL, GX_TRUE );\r\n\r\n\t\t\t\t\t\t// Flag this scene as receiving shadows.\r\n\t\t\t\t\t\tpNgcScene->GetEngineScene()->m_flags |= SCENE_FLAG_RECEIVE_SHADOWS;\r\n\r\n\t\t\t\t\t\tuint32 flags = ( NxNgc::vRENDER_OPAQUE | NxNgc::vRENDER_OCCLUDED | NxNgc::vRENDER_LIT );\r\n\r\n\t\t\t\t\t\tgCorrectColor = true;\r\n\t\t\t\t\t\trendered = NxNgc::cull_scene( pNgcScene->GetEngineScene(), NxNgc::vRENDER_OCCLUDED );\r\n\t\t\t\t\t\tNxNgc::render_scene( pNgcScene->GetEngineScene(), NULL, flags );\r\n\t\t\t\t\t\tconsidered = meshes_considered;\r\n\t\t\t\t\t\tgCorrectColor = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::VUProfiler->PopContext();\r\n#\tendif\t\t// __USE_PROFILER__\r\n\r\n//\t\t// Process data for instances. Specifically, transform the verts.\r\n//\t\tSys::VUProfiler->PushContext( 0,128,128 );\r\n//\t\tNxNgc::process_instances();\r\n//\t\tSys::VUProfiler->PopContext();\r\n\r\n\t\t// Render all opaque instances.\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::VUProfiler->PushContext( 128,0,0 );\r\n#\tendif\t\t// __USE_PROFILER__\r\n\t\tGX::SetZMode ( GX_TRUE, GX_LEQUAL, GX_TRUE );\r\n\t\tNxNgc::render_instances( NxNgc::vRENDER_OPAQUE | NxNgc::vRENDER_TRANSFORM );\r\n\t\tNxNgc::render_instances( NxNgc::vRENDER_SEMITRANSPARENT | NxNgc::vRENDER_INSTANCE_PRE_WORLD_SEMITRANSPARENT );\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::VUProfiler->PopContext();\r\n#\tendif\t\t// __USE_PROFILER__\r\n\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::VUProfiler->PushContext( 0,128,0 );\r\n#\tendif\t\t// __USE_PROFILER__\r\n\r\n\t\t// Render all the non-sky semitransparent scene geometry.\r\n\t\tNxNgc::EngineGlobals.poly_culling = true;\r\n\t\tif( cur_camera && ( sp_loaded_scenes[0] != NULL ))\r\n\t\t{\r\n\t\t\t// There is no bounding box transform for rendering the world.\r\n\t//\t\tNxNgc::set_frustum_bbox_transform( NULL );\r\n\r\n\t\t\tGX::LoadNrmMtxImm( light, GX_PNMTX0);\r\n\t\t\tfor( int i = 0; i < MAX_LOADED_SCENES; i++ )\r\n\t\t\t{\r\n\t\t\t\tif( sp_loaded_scenes[i] )\r\n\t\t\t\t{\r\n\t\t\t\t\tCNgcScene *pNgcScene = static_cast<CNgcScene *>( sp_loaded_scenes[i] );\r\n\r\n\t\t\t\t\t// Only interested in non-sky scenes, this time round.\r\n\t\t\t\t\tif( !pNgcScene->IsSky())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Set up the camera..\r\n\t\t\t\t\t\tNxNgc::set_camera( &( cur_camera->GetMatrix()), &( cur_camera->GetPos()), cur_camera->GetAdjustedHFOV(), p_cur_viewport->GetAspectRatio());\r\n\r\n\t\t\t\t\t\t// Build relevant occlusion poly list, now that the camera is set.\r\n\t\t\t\t\t\tGX::SetZMode ( GX_TRUE, GX_LEQUAL, GX_TRUE );\r\n\r\n\r\n\t\t\t\t\t\tgCorrectColor = true;\r\n\t\t\t\t\t\t//rendered += NxNgc::cull_scene( pNgcScene->GetEngineScene(), NxNgc::vRENDER_OCCLUDED );\r\n\t\t\t\t\t\tuint32 flags;\r\n\t\t\t\t\t\tflags = ( NxNgc::vRENDER_SEMITRANSPARENT | NxNgc::vRENDER_OCCLUDED | NxNgc::vRENDER_LIT );\r\n\t\t\t\t\t\tNxNgc::render_scene( pNgcScene->GetEngineScene(), NULL, flags );\r\n\t\t\t\t\t\tflags = ( NxNgc::vRENDER_SHADOW_2ND_PASS );\r\n\t\t\t\t\t\tNxNgc::render_scene( pNgcScene->GetEngineScene(), NULL, flags );\r\n\t\t\t\t\t\t//considered += meshes_considered;\r\n\t\t\t\t\t\tgCorrectColor = false;\r\n\t\t\t\t\t\t//OSReport( \"Meshes rendered: %d of %d\\n\", rendered, considered );\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\telse\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\t// Draw sky after opaque world polys.\r\n//\t\t\t\t\t\t// Set up the camera.\r\n//\t\t\t\t\t\tMth::Vector\tcentre_pos( 0.0f, 0.0f, 0.0f );\r\n//\t\t\t\t\t\tNxNgc::set_camera( &( cur_camera->GetMatrix()), &centre_pos, cur_camera->GetAdjustedHFOV(), p_cur_viewport->GetAspectRatio(), 30.0f);\r\n//\r\n//\t\t\t\t\t\tGX::SetZMode ( GX_TRUE, GX_LEQUAL, GX_FALSE );\r\n//\r\n//\t\t\t\t\t\tgCorrectColor = true;\r\n//\t\t\t\t\t\tNxNgc::render_scene( pNgcScene->GetEngineScene(), NULL );\r\n//\t\t\t\t\t\tgCorrectColor = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tGX::SetZMode ( GX_TRUE, GX_LEQUAL, GX_TRUE );\r\n\t\tNxNgc::render_instances( NxNgc::vRENDER_SEMITRANSPARENT | NxNgc::vRENDER_INSTANCE_POST_WORLD_SEMITRANSPARENT );\r\n\r\n#\tifdef __USE_PROFILER__\r\n\t\tSys::VUProfiler->PopContext();\r\n#\tendif\t\t// __USE_PROFILER__\r\n\r\n\t\tNxNgc::render_end();\r\n\r\n\t\t// Render other stuff.\r\n\t\tif( cur_camera && ( sp_loaded_scenes[0] != NULL ))\r\n\t\t{\r\n\t\t\tGX::SetFog( GX_FOG_NONE, 0.0f, 0.0f, 0.0f, 0.0f, (GXColor){0,0,0,0} );\t\t// Turn fog off.\r\n\t\t\tNxNgc::set_camera( &( cur_camera->GetMatrix()), &( cur_camera->GetPos()), cur_camera->GetAdjustedHFOV(), p_cur_viewport->GetAspectRatio());\r\n\t\t\r\n\t\t\tGX::SetZMode ( GX_TRUE, GX_LEQUAL, GX_FALSE );\r\n\t\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n\t\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n\t\t\trender_particles();\r\n\t\t\tmp_weather->Process( Tmr::FrameLength() );\r\n\t\t\tmp_weather->Render();\r\n\r\n\t\t\t// New style particles. Update should probably be somewhere else.\r\n\t\t\tNx::CFog::sFogUpdate();\t\t// Restore fog to its' former glory.\r\n\t\t\tNxNgc::set_camera( &( cur_camera->GetMatrix()), &( cur_camera->GetPos()), cur_camera->GetAdjustedHFOV(), p_cur_viewport->GetAspectRatio());\r\n\t\t\tmp_particle_manager->UpdateParticles();\r\n\t\t\tmp_particle_manager->RenderParticles();\r\n\r\n\t\t\tGX::SetZMode ( GX_TRUE, GX_LEQUAL, GX_TRUE );\r\n\t\t\tNx::ShatterRender();\r\n\t\t\tNx::TextureSplatRender();\r\n\t\t\tGX::SetZMode ( GX_TRUE, GX_LEQUAL, GX_FALSE );\r\n\t\t}\r\n\r\n//\t\tGfx::DebugGfx_Draw();\r\n\r\n//\t\t// Render all semi-transparent instances.\r\n//\t\tGX::SetZMode ( GX_TRUE, GX_LEQUAL, GX_TRUE );\r\n//#\tifdef __USE_PROFILER__\r\n//\t\tSys::VUProfiler->PushContext( 128,0,0 );\r\n//#\tendif\t\t// __USE_PROFILER__\r\n//\t\tNxNgc::render_instances( NxNgc::vRENDER_SHADOW_1ST_PASS );\r\n//#\tifdef __USE_PROFILER__\r\n//\t\tSys::VUProfiler->PopContext();\r\n//#\tendif\t\t// __USE_PROFILER__\r\n\t\r\n\t}\r\n\r\n\tGX::SetViewport( 0.0f, 0.0f, 640.0f, 448.0f, 0.0f, 1.0f );\r\n\tGX::SetScissor( 0, 0, 640, 448 );\r\n\r\n\t// Horrible hack - this should be somewhere else ASAP.\r\n\tGX::SetZMode ( GX_FALSE, GX_ALWAYS, GX_FALSE );\r\n\r\n\tcam.orthographic( 0, 0, 640, 448 );\r\n\tcam.begin();\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n#ifndef __NOPT_FINAL__\r\n\r\n\t// 2nd pad controls texture display.\r\n\tstatic int tick;\r\n\tstatic unsigned short last;\r\n\tunsigned short current = padData[1].button;\r\n\tunsigned short press = ( current ^ last ) & current;\r\n\tlast = current;\r\n\r\n\tif ( press & ( PAD_BUTTON_UP | PAD_BUTTON_DOWN | PAD_BUTTON_X | PAD_BUTTON_Y ) )\r\n\t{\r\n\t\ttick = 0;\r\n\t}\r\n\r\n\r\n\tif ( current & ( PAD_BUTTON_UP | PAD_BUTTON_DOWN | PAD_BUTTON_X | PAD_BUTTON_Y ) )\r\n\t{\r\n\t\tif ( tick == 20 )\r\n\t\t{\r\n\t\t\tpress |= current;\r\n\t\t}\r\n\t\tif ( ( ( ( tick - 20 ) % 2 ) == 0 ) && ( tick > 20 ) )\r\n\t\t{\r\n\t\t\tpress |= current;\r\n\t\t}\r\n\r\n\t\ttick++;\r\n\t}\r\n\r\n\tif ( press & PAD_BUTTON_UP ) g_scroll_material++;\r\n\tif ( press & PAD_BUTTON_DOWN ) g_scroll_material--;\r\n\tif ( ( press & PAD_BUTTON_UP ) && ( current & PAD_BUTTON_B ) ) g_scroll_material+=99;\r\n\tif ( ( press & PAD_BUTTON_DOWN ) && ( current & PAD_BUTTON_B ) ) g_scroll_material-=99;\r\n\tif ( g_view_scene )\r\n\t{\r\n\t\tif ( g_scroll_material < 0 ) g_scroll_material = 0;\r\n\t\tif ( g_scroll_material > ( g_view_scene->mp_scene_data->m_num_materials - 1 ) ) g_scroll_material = g_view_scene->mp_scene_data->m_num_materials - 1;\r\n\t}\r\n\r\n\tif ( press & PAD_BUTTON_X ) g_view_object++;\r\n\tif ( press & PAD_BUTTON_Y ) g_view_object--;\r\n\tif ( g_view_object < 0 ) g_view_object = 0;\r\n\tif ( g_view_object > g_object ) g_view_object = g_object;\r\n\r\n\tif ( press & PAD_BUTTON_A )\r\n\t{\r\n\t\tif ( g_material == -1 )\r\n\t\t{\r\n\t\t\tg_material = g_scroll_material;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tg_material = -1;\r\n\t\t}\r\n\t}\r\n\tif ( g_material != -1 )\r\n\t{\r\n\t\tg_material = g_scroll_material;\r\n\t}\r\n\r\n\tif ( press & PAD_TRIGGER_Z )\r\n\t{\r\n\t\tg_dl ^= 1;\r\n\t}\r\n\r\n\tif ( press & PAD_TRIGGER_R ) g_mip++;\r\n\tif ( g_mip > 5 ) g_mip = 0;\r\n\r\n\tif ( press & PAD_TRIGGER_L ) g_passes++;\r\n\tif ( g_passes > 3 ) g_passes = -1;\r\n\r\n\tif ( !g_view_scene )\r\n\t{\r\n\t\t// Draw Object number & \"NO SCENE\" info.\r\n\t\t{\r\n\t\t\tNxNgc::SText message;\r\n\t\t\tNx::CFont * p_cfont;\r\n\t\t\tconst char * p_font_name = \"testtitle\";\r\n\t\t\tchar p_text[128];\r\n\r\n\t\t\t// We can only draw a text string if we have a font & a string.\r\n\t\t\tp_cfont = Nx::CFontManager::sGetFont( p_font_name );\r\n\t\t\tif ( !p_cfont )\r\n\t\t\t{\r\n\t\t\t\tNx::CFontManager::sLoadFont( p_font_name );\r\n\t\t\t\tp_cfont = Nx::CFontManager::sGetFont( p_font_name );\r\n\t\t\t}\r\n\t\t\tmessage.mp_string = p_text;\r\n\t\t\tmessage.m_rgba = 0x808080ff;\r\n\r\n\t\t\tNx::CNgcFont * p_nfont = static_cast<Nx::CNgcFont*>( p_cfont );\r\n\t\t\tNxNgc::SFont * p_font = p_nfont->GetEngineFont();\r\n\t\t\tmessage.mp_font = p_font;\r\n\t\t\tmessage.m_xscale = 0.75f;\r\n\t\t\tmessage.m_yscale = 1.2f;\r\n\r\n\t\t\tmessage.m_color_override = false;\r\n\r\n\t\t\tif ( p_font )\r\n\t\t\t{\r\n\t\t\t\tsprintf( p_text, \"OBJ %d / %d - NOT VISIBLE\", g_view_object, g_object + 1 );\r\n\t\t\t\tmessage.m_xpos = 28.0f;\r\n\t\t\t\tmessage.m_ypos = 72.0f;\r\n\t\t\t\tmessage.DrawSingle();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( ( g_material >= 0 ) && ( g_material < g_view_scene->mp_scene_data->m_num_materials ) )\r\n\t\t{\r\n\t\t\t// Draw material.\r\n\r\n\t\t\tNxNgc::sMaterialHeader * p_mat = &g_view_scene->mp_material_header[g_material];\r\n\r\n\t\t\tuint8 save_passes = p_mat->m_passes;\r\n\t\t\tp_mat->m_passes = ( g_passes == -1 ) ? p_mat->m_passes : ( g_passes + 1 );\r\n\r\n\t\t\t// Adjust mip to render.\r\n\t\t\tint mip_off[4] = { 0, 0, 0, 0 };\r\n\t\t\t{\r\n\t\t\t\tNxNgc::sMaterialPassHeader * p_pass = &g_view_scene->mp_material_pass[p_mat->m_pass_item];\r\n\t\t\t\tfor ( int tex = 0; tex < p_mat->m_passes; tex++, p_pass++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( p_pass->m_texture.p_data )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfor ( int mm = 0; mm < g_mip; mm++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tint mw = p_pass->m_texture.p_data->ActualWidth >> mm;\r\n\t\t\t\t\t\t\tint mh = p_pass->m_texture.p_data->ActualHeight >> mm;\r\n\t\t\t\t\t\t\tmip_off[tex] += ( mw * mh ) >> 1;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tp_pass->m_texture.p_data->pTexelData += mip_off[tex];\r\n\t\t\t\t\t\tp_pass->m_texture.p_data->pAlphaData += mip_off[tex];\r\n\t\t\t\t\t\tp_pass->m_texture.p_data->ActualWidth >>= g_mip;\r\n\t\t\t\t\t\tp_pass->m_texture.p_data->ActualHeight >>= g_mip;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tmulti_mesh( p_mat,\r\n\t\t\t\t\t\t&g_view_scene->mp_material_pass[p_mat->m_pass_item],\r\n\t\t\t\t\t\ttrue,\r\n\t\t\t\t\t\ttrue );\r\n\t\t\tp_mat->m_passes = save_passes;\r\n\t\t\t// Adjust mip back.\r\n\t\t\t{\r\n\t\t\t\tNxNgc::sMaterialPassHeader * p_pass = &g_view_scene->mp_material_pass[p_mat->m_pass_item];\r\n\t\t\t\tfor ( int tex = 0; tex < p_mat->m_passes; tex++, p_pass++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( p_pass->m_texture.p_data )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_pass->m_texture.p_data->pTexelData -= mip_off[tex];\r\n\t\t\t\t\t\tp_pass->m_texture.p_data->pAlphaData -= mip_off[tex];\r\n\t\t\t\t\t\tp_pass->m_texture.p_data->ActualWidth <<= g_mip;\r\n\t\t\t\t\t\tp_pass->m_texture.p_data->ActualHeight <<= g_mip;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){64,64,64,128} );\r\n\t\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){64,64,64,128} );\r\n\r\n\t\t\tGX::SetVtxDesc( 5, GX_VA_POS,  GX_DIRECT,\r\n\t\t\t\t\t\t\t   GX_VA_TEX0, GX_DIRECT,\r\n\t\t\t\t\t\t\t   GX_VA_TEX1, GX_DIRECT,\r\n\t\t\t\t\t\t\t   GX_VA_TEX2, GX_DIRECT,\r\n\t\t\t\t\t\t\t   GX_VA_TEX3, GX_DIRECT );\r\n\r\n\t\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\t\t\tGX::Position3f32(32.0f, 96.0f, -1.0f);\r\n\t\t\t\tGX::TexCoord2f32(0.0f, 1.0f);\r\n\t\t\t\tGX::TexCoord2f32(0.0f, 1.0f);\r\n\t\t\t\tGX::TexCoord2f32(0.0f, 1.0f);\r\n\t\t\t\tGX::TexCoord2f32(0.0f, 1.0f);\r\n\t\t\t\tGX::Position3f32(160.0f, 96.0f, -1.0f);\r\n\t\t\t\tGX::TexCoord2f32(1.0f, 1.0f);\r\n\t\t\t\tGX::TexCoord2f32(1.0f, 1.0f);\r\n\t\t\t\tGX::TexCoord2f32(1.0f, 1.0f);\r\n\t\t\t\tGX::TexCoord2f32(1.0f, 1.0f);\r\n\t\t\t\tGX::Position3f32(160.0f, 222.0f, -1.0f);\r\n\t\t\t\tGX::TexCoord2f32(1.0f, 0.0f);\r\n\t\t\t\tGX::TexCoord2f32(1.0f, 0.0f);\r\n\t\t\t\tGX::TexCoord2f32(1.0f, 0.0f);\r\n\t\t\t\tGX::TexCoord2f32(1.0f, 0.0f);\r\n\t\t\t\tGX::Position3f32(32.0f, 222.0f, -1.0f);\r\n\t\t\t\tGX::TexCoord2f32(0.0f, 0.0f);\r\n\t\t\t\tGX::TexCoord2f32(0.0f, 0.0f);\r\n\t\t\t\tGX::TexCoord2f32(0.0f, 0.0f);\r\n\t\t\t\tGX::TexCoord2f32(0.0f, 0.0f);\r\n\t\t\tGX::End();\r\n\r\n\t\t\tfloat\ttx[8] = { 32.0f, 98.0f, 164.0f, 230.0f, 296.0f, 362.0f, 428.0f, 494.0f };\r\n\t\t\tfloat\tty[8] = { 230.0f, 230.0f, 230.0f, 230.0f, 230.0f, 230.0f, 230.0f, 230.0f };\r\n\t\t\tint\t\ttr = 0;\r\n\r\n\t\t\t// Draw Object & material number.\r\n\t\t\t{\r\n\t\t\t\tNxNgc::SText message;\r\n\t\t\t\tNx::CFont * p_cfont;\r\n\t\t\t\tconst char * p_font_name = \"testtitle\";\r\n\t\t\t\tchar p_text[128];\r\n\r\n\t\t\t\t// We can only draw a text string if we have a font & a string.\r\n\t\t\t\tp_cfont = Nx::CFontManager::sGetFont( p_font_name );\r\n\t\t\t\tif ( !p_cfont )\r\n\t\t\t\t{\r\n\t\t\t\t\tNx::CFontManager::sLoadFont( p_font_name );\r\n\t\t\t\t\tp_cfont = Nx::CFontManager::sGetFont( p_font_name );\r\n\t\t\t\t}\r\n\t\t\t\tmessage.mp_string = p_text;\r\n\t\t\t\tmessage.m_rgba = 0x808080ff;\r\n\r\n\t\t\t\tNx::CNgcFont * p_nfont = static_cast<Nx::CNgcFont*>( p_cfont );\r\n\t\t\t\tNxNgc::SFont * p_font = p_nfont->GetEngineFont();\r\n\t\t\t\tmessage.mp_font = p_font;\r\n\t\t\t\tmessage.m_xscale = 0.75f;\r\n\t\t\t\tmessage.m_yscale = 1.2f;\r\n\r\n\t\t\t\tmessage.m_color_override = false;\r\n\r\n\t\t\t\tif ( p_font )\r\n\t\t\t\t{\r\n\t\t\t\t\tchar * p_pass_string = \"***\";\r\n\t\t\t\t\tif ( g_passes == -1 ) p_pass_string = \"ALL\";\r\n\t\t\t\t\tif ( g_passes == 0 ) p_pass_string = \"P1\";\r\n\t\t\t\t\tif ( g_passes == 1 ) p_pass_string = \"P2\";\r\n\t\t\t\t\tif ( g_passes == 2 ) p_pass_string = \"P3\";\r\n\t\t\t\t\tif ( g_passes == 3 ) p_pass_string = \"P4\";\r\n\t\t\t\t\tsprintf( p_text, \"OBJ %d / %d - MAT %d / %d DO: %6.3f AC: %3d M: %d %s\", g_view_object, g_object + 1, g_material, g_view_scene->mp_scene_data->m_num_materials, p_mat->m_draw_order, p_mat->m_alpha_cutoff, g_mip, p_pass_string );\r\n\t\t\t\t\tmessage.m_xpos = 28.0f;\r\n\t\t\t\t\tmessage.m_ypos = 72.0f;\r\n\t\t\t\t\tmessage.DrawSingle();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tNxNgc::sMaterialPassHeader * p_pass = &g_view_scene->mp_material_pass[p_mat->m_pass_item];\r\n\t\t\tfor ( int tex = 0; tex < p_mat->m_passes; tex++, p_pass++ )\r\n\t\t\t{\r\n\t\t\t\tif ( p_pass->m_texture.p_data )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Draw texture.\r\n\t\t\t\t\tint w = p_pass->m_texture.p_data->ActualWidth >> g_mip;\r\n\t\t\t\t\tint h = p_pass->m_texture.p_data->ActualHeight >> g_mip;\r\n\t\t\t\t\tint mip_off = 0;\r\n\t\t\t\t\tfor ( int mm = 0; mm < g_mip; mm++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint mw = p_pass->m_texture.p_data->ActualWidth >> mm;\r\n\t\t\t\t\t\tint mh = p_pass->m_texture.p_data->ActualHeight >> mm;\r\n\t\t\t\t\t\tmip_off += ( mw * mh ) >> 1;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tGX::UploadTexture(  &p_pass->m_texture.p_data->pTexelData[mip_off],\r\n\t\t\t\t\t\t\t\t\t\tw,\r\n\t\t\t\t\t\t\t\t\t\th,\r\n\t\t\t\t\t\t\t\t\t\tGX_TF_CMPR,\r\n\t\t\t\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\t\t\t\tGX_TRUE,\r\n\t\t\t\t\t\t\t\t\t\tGX_ANISO_1,\r\n\t\t\t\t\t\t\t\t\t\tGX_TEXMAP0 ); \r\n\t\t\t\t\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, w, h );\r\n\r\n\t\t\t\t\tGX::SetTexChanTevIndCull( 1, 0, 1, 0, GX_CULL_NONE );\r\n\t\t\t\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\t\t\t\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t\t\t\t\tGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0 );\r\n\t\t\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\t\t// Replace\r\n\r\n\t\t\t\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\t\t\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n\r\n\t\t\t\t\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\r\n\t\t\t\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\t\t\t\t\tGX::Position3f32(tx[tr], ty[tr], -1.0f);\r\n\t\t\t\t\t\tGX::TexCoord2f32(0.0f, 1.0f);\r\n\t\t\t\t\t\tGX::Position3f32(tx[tr] + 62.0f, ty[tr], -1.0f);\r\n\t\t\t\t\t\tGX::TexCoord2f32(1.0f, 1.0f);\r\n\t\t\t\t\t\tGX::Position3f32(tx[tr] + 62.0f, ty[tr] + 62.0f, -1.0f);\r\n\t\t\t\t\t\tGX::TexCoord2f32(1.0f, 0.0f);\r\n\t\t\t\t\t\tGX::Position3f32(tx[tr], ty[tr] + 62.0f, -1.0f);\r\n\t\t\t\t\t\tGX::TexCoord2f32(0.0f, 0.0f);\r\n\t\t\t\t\tGX::End();\r\n\t\t\t\t\tif ( p_pass->m_texture.p_data->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Draw alpha.\r\n\t\t\t\t\t\tint w = p_pass->m_texture.p_data->ActualWidth >> g_mip;\r\n\t\t\t\t\t\tint h = p_pass->m_texture.p_data->ActualHeight >> g_mip;\r\n\t\t\t\t\t\tint mip_off = 0;\r\n\t\t\t\t\t\tfor ( int mm = 0; mm < g_mip; mm++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tint mw = p_pass->m_texture.p_data->ActualWidth >> mm;\r\n\t\t\t\t\t\t\tint mh = p_pass->m_texture.p_data->ActualHeight >> mm;\r\n\t\t\t\t\t\t\tmip_off += ( mw * mh ) >> 1;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tGX::UploadTexture(  &p_pass->m_texture.p_data->pAlphaData[mip_off],\r\n\t\t\t\t\t\t\t\t\t\t\tw,\r\n\t\t\t\t\t\t\t\t\t\t\th,\r\n\t\t\t\t\t\t\t\t\t\t\tGX_TF_CMPR,\r\n\t\t\t\t\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\t\t\t\t\tGX_TRUE,\r\n\t\t\t\t\t\t\t\t\t\t\tGX_ANISO_1,\r\n\t\t\t\t\t\t\t\t\t\t\tGX_TEXMAP0 ); \r\n\t\t\t\t\t\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, w, h );\r\n\r\n\t\t\t\t\t\tGX::SetTexChanTevIndCull( 1, 0, 1, 0, GX_CULL_NONE );\r\n\t\t\t\t\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\t\t\t\t\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t\t\t\t\t\tGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0 );\r\n\t\t\t\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\t\t// Replace\r\n\r\n\t\t\t\t\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\r\n\t\t\t\t\t\tGXTevSwapSel alpha_swap = GX_TEV_SWAP1;\r\n\t\t\t\t\t\tswitch ( ( p_pass->m_texture.p_data->flags & NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_MASK ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tcase NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_GREEN:\r\n\t\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\t\talpha_swap = GX_TEV_SWAP1;\t\t// Green\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\tcase NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_RED:\r\n\t\t\t\t\t\t\t\talpha_swap = GX_TEV_SWAP2;\t\t// Red\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\tcase NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_BLUE:\r\n\t\t\t\t\t\t\t\talpha_swap = GX_TEV_SWAP3;\t\t// Blue\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t GX_TEV_SWAP0, alpha_swap );\r\n\t\t\t\t\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n\r\n\t\t\t\t\t\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\r\n\t\t\t\t\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\t\t\t\t\t\tGX::Position3f32(tx[tr+1], ty[tr+1], -1.0f);\r\n\t\t\t\t\t\t\tGX::TexCoord2f32(0.0f, 1.0f);\r\n\t\t\t\t\t\t\tGX::Position3f32(tx[tr+1] + 62.0f, ty[tr+1], -1.0f);\r\n\t\t\t\t\t\t\tGX::TexCoord2f32(1.0f, 1.0f);\r\n\t\t\t\t\t\t\tGX::Position3f32(tx[tr+1] + 62.0f, ty[tr+1] + 62.0f, -1.0f);\r\n\t\t\t\t\t\t\tGX::TexCoord2f32(1.0f, 0.0f);\r\n\t\t\t\t\t\t\tGX::Position3f32(tx[tr+1], ty[tr+1] + 62.0f, -1.0f);\r\n\t\t\t\t\t\t\tGX::TexCoord2f32(0.0f, 0.0f);\r\n\t\t\t\t\t\tGX::End();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Draw pass info.\r\n\t\t\t\tchar * blendmode[14] = {\r\n\t\t\t\t\t\"DIFF\",\r\n\t\t\t\t\t\"ADD\",\r\n\t\t\t\t\t\"ADDF\",\r\n\t\t\t\t\t\"SUB\",\r\n\t\t\t\t\t\"SUBF\",\r\n\t\t\t\t\t\"BLND\",\r\n\t\t\t\t\t\"BLNDF\",\r\n\t\t\t\t\t\"MOD\",\r\n\t\t\t\t\t\"MODF\",\r\n\t\t\t\t\t\"BRT\",\r\n\t\t\t\t\t\"BRTF\",\r\n\t\t\t\t\t\"GLOSS\",\r\n\t\t\t\t\t\"BLPV\",\r\n\t\t\t\t\t\"BLPVI\"\r\n\t\t\t\t};\r\n\r\n\t\t\t\tNxNgc::SText message;\r\n\t\t\t\tNx::CFont * p_cfont;\r\n\t\t\t\tconst char * p_font_name = \"testtitle\";\r\n\t\t\t\tchar p_text[128];\r\n\r\n\t\t\t\t// We can only draw a text string if we have a font & a string.\r\n\t\t\t\tp_cfont = Nx::CFontManager::sGetFont( p_font_name );\r\n\t\t\t\tif ( !p_cfont )\r\n\t\t\t\t{\r\n\t\t\t\t\tNx::CFontManager::sLoadFont( p_font_name );\r\n\t\t\t\t\tp_cfont = Nx::CFontManager::sGetFont( p_font_name );\r\n\t\t\t\t}\r\n\t\t\t\tmessage.mp_string = p_text;\r\n\t\t\t\tmessage.m_rgba = 0x808080ff;\r\n\r\n\t\t\t\tNx::CNgcFont * p_nfont = static_cast<Nx::CNgcFont*>( p_cfont );\r\n\t\t\t\tNxNgc::SFont * p_font = p_nfont->GetEngineFont();\r\n\t\t\t\tmessage.mp_font = p_font;\r\n\t\t\t\tmessage.m_xscale = 0.75f;\r\n\t\t\t\tmessage.m_yscale = 1.2f;\r\n\r\n\t\t\t\tmessage.m_color_override = false;\r\n\r\n# define toupper(c) ( ( (c) >= 'a' ) && ( (c) <= 'z' ) ) ? (c) += ( 'A' - 'a' ) : (c)\r\n\r\n\t\t\t\tif ( p_font )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( p_pass->m_texture.p_data )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsprintf( p_text, \"%d,%d\", p_pass->m_texture.p_data->ActualWidth, p_pass->m_texture.p_data->ActualHeight );\r\n\t\t\t\t\t\tmessage.m_xpos = tx[tr];\r\n\t\t\t\t\t\tmessage.m_ypos = ty[tr] + 66.0f + ( 16.0 * 0.0f );\r\n\t\t\t\t\t\tmessage.DrawSingle();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tsprintf( p_text, \"%s\", blendmode[p_pass->m_blend_mode] );\r\n\t\t\t\t\tmessage.m_xpos = tx[tr];\r\n\t\t\t\t\tmessage.m_ypos = ty[tr] + 66.0f + ( 16.0 * 1.0f );\r\n\t\t\t\t\tmessage.DrawSingle();\r\n\r\n\t\t\t\t\tsprintf( p_text, \"%02x %02x\", p_pass->m_color.r, p_pass->m_color.g );\r\n\t\t\t\t\tp_text[0] = toupper( p_text[0] );\r\n\t\t\t\t\tp_text[1] = toupper( p_text[1] );\r\n\t\t\t\t\tp_text[3] = toupper( p_text[3] );\r\n\t\t\t\t\tp_text[4] = toupper( p_text[4] );\r\n\t\t\t\t\tmessage.m_xpos = tx[tr];\r\n\t\t\t\t\tmessage.m_ypos = ty[tr] + 66.0f + ( 16.0 * 2.0f );\r\n\t\t\t\t\tmessage.DrawSingle();\r\n\r\n\t\t\t\t\tsprintf( p_text, \"%02x %02x\", p_pass->m_color.b, p_pass->m_color.a );\r\n\t\t\t\t\tp_text[0] = toupper( p_text[0] );\r\n\t\t\t\t\tp_text[1] = toupper( p_text[1] );\r\n\t\t\t\t\tp_text[3] = toupper( p_text[3] );\r\n\t\t\t\t\tp_text[4] = toupper( p_text[4] );\r\n\t\t\t\t\tmessage.m_xpos = tx[tr];\r\n\t\t\t\t\tmessage.m_ypos = ty[tr] + 66.0f + ( 16.0 * 3.0f );\r\n\t\t\t\t\tmessage.DrawSingle();\r\n\r\n\t\t\t\t\tsprintf( p_text, \"%02x %02x\", p_pass->m_alpha_fix, p_pass->m_flags );\r\n\t\t\t\t\tp_text[0] = toupper( p_text[0] );\r\n\t\t\t\t\tp_text[1] = toupper( p_text[1] );\r\n\t\t\t\t\tp_text[3] = toupper( p_text[3] );\r\n\t\t\t\t\tp_text[4] = toupper( p_text[4] );\r\n\t\t\t\t\tmessage.m_xpos = tx[tr];\r\n\t\t\t\t\tmessage.m_ypos = ty[tr] + 66.0f + ( 16.0 * 4.0f );\r\n\t\t\t\t\tmessage.DrawSingle();\r\n\r\n\t\t\t\t\tif ( p_pass->m_texture.p_data )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsprintf( p_text, \"%3.1f %d\", (float)(p_pass->m_k) * (1.0f / (float)(1<<8)), p_pass->m_texture.p_data->Levels );\r\n\t\t\t\t\t\tmessage.m_xpos = tx[tr];\r\n\t\t\t\t\t\tmessage.m_ypos = ty[tr] + 66.0f + ( 16.0 * 5.0f );\r\n\t\t\t\t\t\tmessage.DrawSingle();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\ttr++;\r\n\t\t\t\tif ( p_pass->m_texture.p_data && p_pass->m_texture.p_data->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA ) tr++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n//\t// Draw texture.\r\n//\tGX::UploadTexture(  shadowTextureData,\r\n//\t\t\t\t\t\tSHADOW_TEXTURE_SIZE,\r\n//\t\t\t\t\t\tSHADOW_TEXTURE_SIZE,\r\n//\t\t\t\t\t\tGX_TF_I4,\r\n//\t\t\t\t\t\tGX_CLAMP,\r\n//\t\t\t\t\t\tGX_CLAMP,\r\n//\t\t\t\t\t\tGX_FALSE,\r\n//\t\t\t\t\t\tGX_LINEAR,\r\n//\t\t\t\t\t\tGX_LINEAR,\r\n//\t\t\t\t\t\t0.0f,\r\n//\t\t\t\t\t\t0.0f,\r\n//\t\t\t\t\t\t0.0f,\r\n//\t\t\t\t\t\tGX_FALSE,\r\n//\t\t\t\t\t\tGX_TRUE,\r\n//\t\t\t\t\t\tGX_ANISO_1,\r\n//\t\t\t\t\t\tGX_TEXMAP0 ); \r\n//\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, SHADOW_TEXTURE_SIZE, SHADOW_TEXTURE_SIZE );\r\n//\r\n//\tGX::UploadPalette( shadowPalette,\r\n//\t\t\t\t\t   GX_TL_RGB5A3,\r\n//\t\t\t\t\t   GX_TLUT_16,\r\n//\t\t\t\t\t   GX_TEXMAP0 );\r\n//\r\n//\tGX::SetTexChanTevIndCull( 1, 0, 1, 0, GX_CULL_NONE );\r\n//\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n//\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n//\r\n//\tGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0 );\r\n//\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\t\t// Replace\r\n//\r\n//\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n//\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n//\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV,\r\n//\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n//\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n//\r\n//\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n//\r\n//\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 );\r\n//\t\tGX::Position3f32( 32.0f,  32.0f, -1.9f);\r\n//\t\tGX::TexCoord2f32(0.0f, 0.0f);\r\n//\t\tGX::Position3f32(288.0f,  32.0f, -1.9f);\r\n//\t\tGX::TexCoord2f32(1.0f, 0.0f);\r\n//\t\tGX::Position3f32(288.0f, 288.0f, -1.9f);\r\n//\t\tGX::TexCoord2f32(1.0f, 1.0f);\r\n//\t\tGX::Position3f32( 32.0f, 288.0f, -1.9f);\r\n//\t\tGX::TexCoord2f32(0.0f, 1.0f);\r\n//\tGX::End();\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n//\t// Shadow volume stage 1.\r\n//\t// And the alpha channel with 128. Pixels in shadow will have alpha of 128, not will be 0.\r\n//\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );\r\n//\tGX::SetBlendMode ( GX_BM_LOGIC, GX_BL_SRCALPHA, GX_BL_DSTALPHA, GX_LO_AND, GX_FALSE, GX_TRUE, GX_FALSE );\r\n//\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n//\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_KONST, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n//\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV,\r\n//\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n//\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n//\tGX::SetTevKColor( GX_KCOLOR0, (GXColor){0,0,0,128} );\r\n//\tGX::SetTevKSel( GX_TEVSTAGE0, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A );\r\n//\r\n//\tGX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n//\r\n//\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t\tGX::Position3f32(0.0f, 0.0f, -1.0f);\r\n//\t\tGX::Position3f32(640.0f, 0.0f, -1.0f);\r\n//\t\tGX::Position3f32(640.0f, 448.0f, -1.0f);\r\n//\t\tGX::Position3f32(0.0f, 448.0f, -1.0f);\r\n//\tGX::End();\r\n//\r\n//\t// Shadow volume stage 2.\r\n//\t// Blend alpha with shadow color.\r\n//\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );\r\n//\tGX::SetBlendMode( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_INVDSTALPHA, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n//\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n//\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_KONST, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n//\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV,\r\n//\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_KONST, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n//\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n//\tGX::SetTevKColor( GX_KCOLOR0, (GXColor){0,0,0,128} );\r\n//\tGX::SetTevKSel( GX_TEVSTAGE0, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A );\r\n//\r\n//\tGX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n//\r\n//\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t\tGX::Position3f32(0.0f, 0.0f, -1.0f);\r\n//\t\tGX::Position3f32(640.0f, 0.0f, -1.0f);\r\n//\t\tGX::Position3f32(640.0f, 448.0f, -1.0f);\r\n//\t\tGX::Position3f32(0.0f, 448.0f, -1.0f);\r\n//\tGX::End();\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n#if 0\r\n\t// Copy framebuffer to 320x224 texture.\r\n\tGXSetCopyFilter( GX_FALSE, NULL, GX_FALSE, NULL );\r\n\tGXSetTexCopySrc(0, 0, 640, 448);\r\n\tGXSetTexCopyDst(320, 224, GX_TF_Z8, GX_TRUE);\r\n\tGXCopyTex(zTextureDataH, GX_FALSE);\r\n\tGXPixModeSync();\r\n\r\n\tGXSetCopyFilter( GX_FALSE, NULL, GX_FALSE, NULL );\r\n\tGXSetTexCopySrc(0, 0, 640, 448);\r\n\tGXSetTexCopyDst(320, 224, GX_CTF_Z8M, GX_TRUE);\r\n\tGXCopyTex(zTextureDataL, GX_FALSE);\r\n\tGXPixModeSync();\r\n\r\n\t// Copy top-corner of screen.\r\n\tGXSetCopyFilter( GX_FALSE, NULL, GX_FALSE, NULL );\r\n\tGXSetTexCopySrc(0, 0, 320, 224);\r\n\tGXSetTexCopyDst(320, 224, GX_TF_RGBA8, GX_FALSE);\r\n\tGXCopyTex(screenTextureData, GX_FALSE);\r\n\tGXPixModeSync();\r\n\r\n\t// Copy screen and filter down.\r\n\tGXSetCopyFilter( GX_TRUE, sample_pattern, GX_TRUE, GXNtsc480IntAa.vfilter );\r\n\tGXSetTexCopySrc(0, 0, 640, 448);\r\n\tGXSetTexCopyDst(320, 224, GX_TF_RGBA8, GX_TRUE);\r\n\tGXCopyTex(focusTextureData, GX_FALSE);\r\n\tGXPixModeSync();\r\n\r\n\t// Shrink down the focus texture.\r\n\tGXTexObj\tfocusTexture;\r\n\tGXInitTexObj(\r\n\t\t&focusTexture,\r\n\t\tfocusTextureData,\r\n\t\t320,\r\n\t\t224,\r\n\t\tGX_TF_RGBA8,\r\n\t\tGX_CLAMP,\r\n\t\tGX_CLAMP,\r\n\t\tGX_FALSE );\r\n\tGXInitTexObjLOD(&focusTexture, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);\r\n\tGXLoadTexObj( &focusTexture, GX_TEXMAP0 );\r\n\r\n\tGX::SetNumChans(0);\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\tGX::SetNumTevStages( 1 );\r\n\tGX::SetNumTexGens( 1 );\r\n\tGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0 );\r\n\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\t\t// Replace\r\n\r\n\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n\r\n\tGXSetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\r\n\tGXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\tGXPosition3f32(0.0f, 0.0f, -1.0f);\r\n\t\tGXTexCoord2f32(0.0f, 0.0f);\r\n\t\tGXPosition3f32(320.0f, 0.0f, -1.0f);\r\n\t\tGXTexCoord2f32(1.0f, 0.0f);\r\n\t\tGXPosition3f32(320.0f, 224.0f, -1.0f);\r\n\t\tGXTexCoord2f32(1.0f, 1.0f);\r\n\t\tGXPosition3f32(0.0f, 224.0f, -1.0f);\r\n\t\tGXTexCoord2f32(0.0f, 1.0f);\r\n\tGXEnd();\r\n\r\n\tGXSetCopyFilter( GX_TRUE, sample_pattern, GX_TRUE, GXNtsc480IntAa.vfilter );\r\n\tGXSetTexCopySrc(0, 0, 320, 224);\r\n\tGXSetTexCopyDst(160, 112, GX_TF_RGBA8, GX_TRUE);\r\n\tGXCopyTex(focusTextureData, GX_FALSE);\r\n\tGXPixModeSync();\r\n\r\n\t// Draw top-corner screen area we wrote over.\r\n\tGXTexObj\tscreenTexture;\r\n\tGXInitTexObj(\r\n\t\t&screenTexture,\r\n\t\tscreenTextureData,\r\n\t\t320,\r\n\t\t224,\r\n\t\tGX_TF_RGBA8,\r\n\t\tGX_CLAMP,\r\n\t\tGX_CLAMP,\r\n\t\tGX_FALSE );\r\n\tGXInitTexObjLOD(&screenTexture, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);\r\n\tGXLoadTexObj( &screenTexture, GX_TEXMAP0 );\r\n\r\n\tGXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\tGXPosition3f32(0.0f, 0.0f, -1.0f);\r\n\t\tGXTexCoord2f32(0.0f, 0.0f);\r\n\t\tGXPosition3f32(320.0f, 0.0f, -1.0f);\r\n\t\tGXTexCoord2f32(1.0f, 0.0f);\r\n\t\tGXPosition3f32(320.0f, 224.0f, -1.0f);\r\n\t\tGXTexCoord2f32(1.0f, 1.0f);\r\n\t\tGXPosition3f32(0.0f, 224.0f, -1.0f);\r\n\t\tGXTexCoord2f32(0.0f, 1.0f);\r\n\tGXEnd();\r\n\r\n\t// Setup z textures\r\n\tGXTexObj\tzTextureH;\r\n\tGXTexObj\tzTextureL;\r\n\tGXTlutObj\tzPalH;\r\n\tGXTlutObj\tzPalL;\r\n\r\n\tGXInitTlutObj( &zPalH, &zPalette8H, GX_TL_IA8, 256 );\r\n\tGXLoadTlut ( &zPalH, GX_TLUT0 );\r\n\r\n\tGXInitTlutObj( &zPalL, &zPalette8L, GX_TL_IA8, 256 );\r\n\tGXLoadTlut ( &zPalL, GX_TLUT1 );\r\n\r\n\tGXInitTexObjCI(\r\n\t\t&zTextureH,\r\n\t\tzTextureDataH,\r\n\t\t320,\r\n\t\t224,\r\n\t\tGX_TF_C8,\r\n\t\tGX_CLAMP,\r\n\t\tGX_CLAMP,\r\n\t\tGX_FALSE,\r\n\t\tGX_TLUT0 );\r\n\tGXInitTexObjLOD(&zTextureH, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);\r\n\tGXLoadTexObj( &zTextureH, GX_TEXMAP0 );\r\n\r\n\tGXInitTexObjCI(\r\n\t\t&zTextureL,\r\n\t\tzTextureDataL,\r\n\t\t320,\r\n\t\t224,\r\n\t\tGX_TF_C8,\r\n\t\tGX_CLAMP,\r\n\t\tGX_CLAMP,\r\n\t\tGX_FALSE,\r\n\t\tGX_TLUT1 );\r\n\tGXInitTexObjLOD(&zTextureL, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);\r\n\tGXLoadTexObj( &zTextureL, GX_TEXMAP1 );\r\n\r\n\tGXInitTexObj(\r\n\t\t&focusTexture,\r\n\t\tfocusTextureData,\r\n\t\t160,\r\n\t\t112,\r\n\t\tGX_TF_RGBA8,\r\n\t\tGX_CLAMP,\r\n\t\tGX_CLAMP,\r\n\t\tGX_FALSE );\r\n\tGXInitTexObjLOD(&focusTexture, GX_LINEAR, GX_LINEAR, 0, 0, 0, 0, 0, GX_ANISO_1);\r\n\tGXLoadTexObj( &focusTexture, GX_TEXMAP2 );\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n//\tGXTexObj\tzTexture;\r\n//\tGXTlutObj\tzPal;\r\n//\r\n//\tGXInitTlutObj( &zPal, &zPalette16, GX_TL_IA8, 65535 );\r\n//\tGXLoadTlut ( &zPal, GX_TLUT0 );\r\n//\r\n//\tGXInitTexObjCI(\r\n//\t\t&zTexture,\r\n//\t\tzTextureData,\r\n//\t\t320,\r\n//\t\t224,\r\n//\t\tGX_TF_C14X2,\r\n//\t\tGX_CLAMP,\r\n//\t\tGX_CLAMP,\r\n//\t\tGX_FALSE,\r\n//\t\tGX_TLUT0 );\r\n//\tGXInitTexObjLOD(&zTexture, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);\r\n//\tGXLoadTexObj( &zTexture, GX_TEXMAP0 );\r\n\r\n\tGX::SetTexChanTevIndCull( 3, 0, 3, 0, GX_CULL_NONE ); \r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetTexCoordGen( GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetTexCoordGen( GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\tGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0 );\r\n\r\n//\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE ); // Replace alpha\r\n//\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );\t\t// Replace\r\n\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\t\t// Blend\r\n\r\n//\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_DISABLE, GX_TEVPREV );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_DISABLE, GX_TEVPREV );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_TEXA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n//\r\n//\tGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_DISABLE, GX_TEVREG1 );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_DISABLE, GX_TEVREG1 );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE1, GX_CA_APREV, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE1, GX_CC_CPREV, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n//\r\n//\tGX::SetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE2, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVREG0 );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVREG0 );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE2, GX_CA_A1, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE2, GX_CC_C1, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n//\r\n//\tGX::SetTevKColorSel( GX_TEVSTAGE3, GX_TEV_KCSEL_K0_A );\r\n//\tGX::SetTevKColor( GX_KCOLOR0, (GXColor){16,16,16,16} );\r\n//\r\n//\tGX::SetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR_NULL);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE3, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE3, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG1 );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE3, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG1 );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE3, GX_CA_ZERO, GX_CA_KONST, GX_CA_TEXA, GX_CA_ZERO );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE3, GX_CC_ZERO, GX_CC_KONST, GX_CC_TEXC, GX_CC_ZERO );\r\n//\r\n//\tGX::SetTevOrder(GX_TEVSTAGE4, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE4, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE4, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE4, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE4, GX_CA_A0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A1 );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE4, GX_CC_C0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C1 );\r\n\r\n\r\n\r\n//\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG0 );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG0 );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC );\r\n//\r\n//\tGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR_NULL);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n////\tGX::SetTevAlphaIn ( GX_TEVSTAGE1, GX_CA_A0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA );\r\n////\tGX::SetTevColorIn ( GX_TEVSTAGE1, GX_CC_C0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC );\r\n////\tGX::SetTevAlphaIn ( GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA );\r\n////\tGX::SetTevColorIn ( GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE1, GX_CA_A0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE1, GX_CC_C0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n\r\n\r\n\r\n\r\n//\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_DISABLE, GX_TEVPREV );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_DISABLE, GX_TEVPREV );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_ONE, GX_CC_ZERO, GX_CC_TEXC, GX_CC_ZERO );\r\n//\r\n//\tGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_DISABLE, GX_TEVREG1 );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_DISABLE, GX_TEVREG1 );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE1, GX_CC_CPREV, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n//\r\n//\tGX::SetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE2, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVREG0 );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVREG0 );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE2, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE2, GX_CC_C1, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n//\r\n//\tGX::SetTevKColorSel( GX_TEVSTAGE3, GX_TEV_KCSEL_K0_A );\r\n//\tGX::SetTevKColor( GX_KCOLOR0, (GXColor){16,16,16,16} );\r\n//\r\n//\tGX::SetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR_NULL);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE3, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE3, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE3, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE3, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE3, GX_CC_ONE, GX_CC_ZERO, GX_CC_TEXC, GX_CC_C0 );\r\n\r\n\r\n\r\n\r\n\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR_NULL);\r\n\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVREG0 );\r\n\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVREG0 );\r\n\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_TEXA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n\r\n\tGX::SetTevSwapMode( GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\tGX::SetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVREG1 );\r\n\tGX::SetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVREG1 );\r\n\tGX::SetTevAlphaIn ( GX_TEVSTAGE1, GX_CA_TEXA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0 );\r\n\tGX::SetTevColorIn ( GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n\r\n\tGX::SetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD2, GX_TEXMAP2, GX_COLOR_NULL, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGX::SetTevSwapMode( GX_TEVSTAGE2, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\tGX::SetTevAlphaOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n\tGX::SetTevColorOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n\tGX::SetTevAlphaIn ( GX_TEVSTAGE2, GX_CA_A1, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n\tGX::SetTevColorIn ( GX_TEVSTAGE2, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE2, GX_CA_A1, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE2, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n\r\n\r\n\r\n//    GXSetTevSwapModeTable( GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_RED );\r\n//    GXSetTevSwapModeTable( GX_TEV_SWAP2, GX_CH_GREEN, GX_CH_GREEN, GX_CH_GREEN, GX_CH_GREEN );\r\n//    GXSetTevSwapModeTable( GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE );\r\n\r\n//\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n\r\n\r\n\r\n//\tif ( gFocus )\r\n//\t{\r\n//\t\t// Set current vertex descriptor to enable position and color0.\r\n//\t\t// Both use 8b index to access their data arrays.\r\n//\t\tGXSetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n//\r\n//\t\tGXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t\t\tGXPosition3f32(0.0f, 0.0f, -1.0f);\r\n//\t\t\tGXTexCoord2f32(0.0f, 0.0f);\r\n//\t\t\tGXPosition3f32(640.0f, 0.0f, -1.0f);\r\n//\t\t\tGXTexCoord2f32(1.0f, 0.0f);\r\n//\t\t\tGXPosition3f32(640.0f, 448.0f, -1.0f);\r\n//\t\t\tGXTexCoord2f32(1.0f, 1.0f);\r\n//\t\t\tGXPosition3f32(0.0f, 448.0f, -1.0f);\r\n//\t\t\tGXTexCoord2f32(0.0f, 1.0f);\r\n//\t\tGXEnd();\r\n//\t\t\r\n//\t}\r\n#endif\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n\r\n\r\n\tGX::SetZMode ( GX_FALSE, GX_ALWAYS, GX_FALSE );\r\n\tNxNgc::set_blend_mode( NxNgc::vBLEND_MODE_ADD );\r\n\tNxNgc::SDraw2D::DrawAll();\r\n\r\n//\tif ( NsDisplay::shouldReset() && NxNgc::EngineGlobals.disableReset )\r\n//\t{\r\n//\t\tGX::SetNumTevStages(1);\r\n//\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);\r\n//\t\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\tGX::SetNumTexGens( 0 );\r\n//\t\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\t\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\t\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n//\t\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n//\t\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n//\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){0,0,0,255} );\r\n//\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\r\n//\t\tGXSetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n//\r\n//\t\tGXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t\t\tGXPosition3f32(128.0f, 224.0f - 64.0f, -1.0f);\r\n//\t\t\tGXPosition3f32(640.0f - 128.0f, 224.0f - 64.0f, -1.0f);\r\n//\t\t\tGXPosition3f32(640.0f - 128.0f, 224.0f + 64.0f, -1.0f);\r\n//\t\t\tGXPosition3f32(128.0f, 224.0f + 64.0f, -1.0f);\r\n//\t\tGXEnd();\r\n//\r\n//\t\tScript::RunScript( \"ngc_reset\" );\r\n//\t}\r\n\r\n//\t// Set up shadow map texture\r\n//\tGXTexObj shadowTexture;\r\n//\tGXInitTexObj(\r\n//\t\t&shadowTexture,\r\n//\t\tshadowTextureData,\r\n//\t\tSHADOW_TEXTURE_SIZE,\r\n//\t\tSHADOW_TEXTURE_SIZE,\r\n//\t\tGX_TF_RGBA8,\r\n//\t\tGX_CLAMP,\r\n//\t\tGX_CLAMP,\r\n//\t\tGX_FALSE );\r\n//\tGXInitTexObjLOD(&shadowTexture, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);\r\n//\tGXLoadTexObj( &shadowTexture, GX_TEXMAP0 );\r\n//\r\n//    GXSetNumChans(1);\r\n//\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_TEX0, GX_IDENTITY );\r\n//\r\n//    GX::SetNumTevStages(1);\r\n//\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetNumTexGens( 1 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_RASC, GX_CC_ZERO );\r\n//\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){128,128,128,255} );\r\n//\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\r\n//    Mtx mv;\r\n//\tMTXIdentity( mv );\r\n//    GX::LoadTexMtxImm(mv, GX_TEXMTX0, GX_MTX3x4);\r\n//    GX::LoadTexMtxImm(mv, GX_TEXMTX1, GX_MTX3x4);\r\n//\r\n//\t// Set current vertex descriptor to enable position and color0.\r\n//\t// Both use 8b index to access their data arrays.\r\n//\tGXSetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n//\r\n//\t// Send coordinates.\r\n//\tGXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t\tGXPosition3f32(320, 32, -1.0f);\r\n//\t\tGXTexCoord2f32(0.0f, 0.0f);\r\n//\t\tGXPosition3f32(576, 32, -1.0f);\r\n//\t\tGXTexCoord2f32(1.0f, 0.0f);\r\n//\t\tGXPosition3f32(576, 288, -1.0f);\r\n//\t\tGXTexCoord2f32(1.0f, 1.0f);\r\n//\t\tGXPosition3f32(320, 288, -1.0f);\r\n//\t\tGXTexCoord2f32(0.0f, 1.0f);\r\n//\tGXEnd();\r\n\r\n\r\n\t// Blur.\r\n//\tif ( sBlur > 0 )\r\n//\t{\r\n//\t\t\r\n//\t}\r\n//\r\n//sBlurBuffer\r\n\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n//\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, 64, 64 );\r\n//\t\r\n//\tGX::SetTexChanTevIndCull( 1, 0, 1, 0, GX_CULL_NONE );\r\n//\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n//\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n//\t\r\n//\tGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0 );\r\n//\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\t\t// Replace\r\n//\t\r\n//\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP7, GX_COLOR_NULL, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n//\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n//\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV,\r\n//\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n//\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n//\t\r\n//\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\t\r\n//\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n//\t\r\n//\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t\tGX::Position3f32(64.0f, 64.0f, -1.0f);\r\n//\t\tGX::TexCoord2f32(0.0f, 0.0f);\r\n//\t\tGX::Position3f32(64.0f + 64.0f, 64.0f, -1.0f);\r\n//\t\tGX::TexCoord2f32(1.0f, 0.0f);\r\n//\t\tGX::Position3f32(64.0f + 64.0f, 64.0f + 64.0f, -1.0f);\r\n//\t\tGX::TexCoord2f32(1.0f, 1.0f);\r\n//\t\tGX::Position3f32(64.0f, 64.0f + 64.0f, -1.0f);\r\n//\t\tGX::TexCoord2f32(0.0f, 1.0f);\r\n//\tGX::End();\r\n//\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\tcam.end();\r\n\tNsPrim::end();\r\n\tNsRender::end();\r\n\r\n//\tif ( movies )\r\n//\t{\r\n//\t\tNsDisplay::end( false );\r\n//\t}\r\n//\telse\r\n//\t{\r\n\t\t//NsDisplay::end( true );\r\n//\t}\r\n\tNsBuffer::end();\r\n\r\n\tNxNgc::EngineGlobals.gpuBusy = false;\r\n\r\n\tNxNgc::EngineGlobals.frameCount = ( NxNgc::EngineGlobals.frameCount + 1 ) & 1;\r\n\r\n\tNsDisplay::end(true);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCScene\t*\tCEngine::s_plat_create_scene(const char *p_name, CTexDict *p_tex_dict, bool add_super_sectors)\r\n{\r\n\t// Create scene class instance\r\n\tCNgcScene\t*p_Ngc_scene\t= new CNgcScene;\r\n\tCScene\t\t*p_new_scene\t= p_Ngc_scene;\r\n\tp_new_scene->SetInSuperSectors( add_super_sectors );\r\n\tp_new_scene->SetIsSky( false );\r\n\r\n\t// Create a new sScene so the engine can track assets for this scene.\r\n\tNxNgc::sScene *p_engine_scene = new NxNgc::sScene();\r\n\tp_Ngc_scene->SetEngineScene( p_engine_scene );\r\n\r\n\treturn p_new_scene;\r\n}\r\n\r\n#define MemoryRead( dst, size, num, src )\tmemcpy(( dst ), ( src ), (( num ) * ( size )));\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t( src ) += (( num ) * ( size ))\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int s_plat_scene_size( void *p_mem, CTexDict *p_tex_dict, bool add_super_sectors, bool is_sky, bool is_dictionary )\r\n{\r\n\tvoid * p_start = p_mem;\r\n\r\n\t// Setup pointer to actual data.\r\n\tNxNgc::sSceneHeader * p_scene_header = (NxNgc::sSceneHeader *)p_mem;\r\n\tunsigned int * p32 = (unsigned int *)&p_scene_header[1];\r\n\r\n\t// Setup material DL pointer.\r\n\tNxNgc::sMaterialDL * blend_dl = (NxNgc::sMaterialDL *)p32; \r\n\tNxNgc::sTextureDL * tex_dl = (NxNgc::sTextureDL *)&blend_dl[p_scene_header->m_num_blend_dls];\r\n\tunsigned char * p8 = (unsigned char *)&tex_dl[p_scene_header->m_num_materials];\r\n\r\n\tint bytes = ( p_scene_header->m_num_blend_dls * sizeof( NxNgc::sMaterialDL ) ) + ( p_scene_header->m_num_materials * sizeof( NxNgc::sTextureDL ) );\r\n\tint rounded_bytes = ( bytes + 31 ) & ~31;\r\n\tint pad_bytes = rounded_bytes - bytes;\r\n\r\n\tp8 = &p8[pad_bytes];\r\n\r\n\t// Assign blend dl pointers.\r\n\tfor ( uint bdl = 0; bdl < p_scene_header->m_num_blend_dls; bdl++ )\r\n\t{\r\n\t\tp8 += blend_dl[bdl].m_dl_size;\r\n\t}\r\n\r\n\t// Assign texture dl pointers.\r\n\tfor ( uint tdl = 0; tdl < p_scene_header->m_num_materials; tdl++ )\r\n\t{\r\n\t\tp8 += tex_dl[tdl].m_dl_size;\r\n\t}\r\n\tp32 = (unsigned int *)p8;\r\n\r\n\t// Point past pool data.\r\n\tNxNgc::sObjectHeader* p_data = (NxNgc::sObjectHeader*)&((char*)p32)[p_scene_header->m_num_pool_bytes];\r\n\r\n\t// Setup VC wibble data.\r\n\tNxNgc::sMaterialVCWibbleKeyHeader *\tp_key_header\t= (NxNgc::sMaterialVCWibbleKeyHeader *)p32; \r\n\tNxNgc::sMaterialVCWibbleKey *\t\tp_key\t\t\t= (NxNgc::sMaterialVCWibbleKey *)&p_key_header[1]; \r\n\tfor ( int vc = 0; vc < p_scene_header->m_num_vc_wibbles; vc++ )\r\n\t{\r\n\t\tp_key_header = (NxNgc::sMaterialVCWibbleKeyHeader *)&p_key[p_key_header->m_num_frames]; \r\n\t\tp_key = (NxNgc::sMaterialVCWibbleKey *)&p_key_header[1];  \r\n\t}\r\n\tp32 = (uint32 *)p_key_header;\r\n\r\n\t// Setup material header data.\r\n\tNxNgc::sMaterialHeader *material_header = (NxNgc::sMaterialHeader *)p32;\r\n\tp32 = (uint32 *)&material_header[p_scene_header->m_num_materials];\r\n\r\n\t// Setup UV wibble data.\r\n\tNxNgc::sMaterialUVWibble *uv_wibble = (NxNgc::sMaterialUVWibble *)p32;\r\n\tp32 = (uint32 *)&uv_wibble[p_scene_header->m_num_uv_wibbles];\r\n\r\n\t// Setup material pass data.\r\n\tNxNgc::sMaterialPassHeader *material_pass = (NxNgc::sMaterialPassHeader *)p32;\r\n\tp32 = (uint32 *)&material_pass[p_scene_header->m_num_pass_items];\r\n\r\n\tif ( p_scene_header->m_num_pos )\r\n\t{\r\n\t\tp32 = &((unsigned int *)p32)[p_scene_header->m_num_pos*3];\r\n\t}\r\n\r\n\tif ( p_scene_header->m_num_nrm )\r\n\t{\r\n\t\tp32 = &((unsigned int *)p32)[p_scene_header->m_num_nrm*3];\r\n\t}\r\n\r\n\tif ( p_scene_header->m_num_col )\r\n\t{\r\n\t\tp32 = &((unsigned int *)p32)[p_scene_header->m_num_col];\r\n\t}\r\n\r\n\tif ( p_scene_header->m_num_tex )\r\n\t{\r\n\t\tp32 = &((unsigned int *)p32)[p_scene_header->m_num_tex*2];\r\n\t}\r\n\r\n\tif ( p_scene_header->m_num_shadow_faces )\r\n\t{\r\n\t\tp32 = (unsigned int *)(&((unsigned short *)p32)[p_scene_header->m_num_shadow_faces*3]);\r\n\t\tp32 = (unsigned int *)(&((NxNgc::sShadowEdge *)p32)[p_scene_header->m_num_shadow_faces]);\r\n\t}\r\n\r\n\tfor( uint s = 0; s < p_scene_header->m_num_objects; ++s )\r\n\t{\r\n\t\tint num_mesh = p_data->m_num_meshes;\r\n\r\n\t\tchar * p_skin = (char *)&p_data[1];\r\n\t\tint nbytes = p_data->m_skin.num_bytes;\r\n\t\tNxNgc::sDLHeader* p_dl = (NxNgc::sDLHeader*)&p_skin[nbytes];\r\n\r\n\t\tfor( int m = 0; m < num_mesh; ++m )\r\n\t\t{\r\n\t\t\tif ( p_dl->m_size )\r\n\t\t\t{\r\n\t\t\t\tp_dl = (NxNgc::sDLHeader*)&(((char *)&p_dl[1])[p_dl->m_size]);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_data = (NxNgc::sObjectHeader*)p_dl;\r\n\t}\r\n\r\n\t// Point up hierarchy.\r\n\tuint32 * p_h = (uint32 *)p_data;\r\n\tuint32 num_hobj = *p_h++;\r\n\r\n\tCHierarchyObject * p_end = (CHierarchyObject *)p_h;\r\n\r\n\tp_end = &p_end[num_hobj];\r\n\r\n\treturn (int)p_end - (int)p_start;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic CScene * s_plat_load_scene_guts( void *p_mem, CTexDict *p_tex_dict, bool add_super_sectors, bool is_sky, bool is_dictionary )\r\n{\r\n\tif ( s_correctable ) gCorrectColor = true;\r\n\r\n\tCSector*\t\tpSector;\r\n\tCNgcSector*\tpNgcSector;\r\n\r\n\t// Create scene class instance.\r\n\tCScene\t*new_scene;\r\n\tif( add_super_sectors )\r\n\t{\r\n\t\t// Use default size sector table.\r\n\t\tnew_scene = new CNgcScene();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Use minimum size sector table.\r\n\t\tnew_scene = new CNgcScene( 1 );\r\n\t}\r\n\r\n\tnew_scene->SetInSuperSectors( add_super_sectors );\r\n\tnew_scene->SetIsSky( is_sky );\r\n\r\n\t// Get a scene id from the engine.\r\n\tCNgcScene *p_new_ngc_scene = static_cast<CNgcScene *>( new_scene );\r\n\r\n\t// Create a new sScene so the engine can track assets for this scene.\r\n\tNxNgc::sScene *p_engine_scene = new NxNgc::sScene();\r\n\tp_new_ngc_scene->SetEngineScene( p_engine_scene );\r\n\r\n\t// Set the dictionary flag.\r\n\tp_engine_scene->m_is_dictionary\t= is_dictionary;\r\n\r\n\r\n\r\n//------------------------------------------------------------------------------------\r\n\r\n\t// Setup pointer to actual data.\r\n\tp_engine_scene->mp_scene_data = (NxNgc::sSceneHeader *)p_mem;\r\n\tunsigned int * p32 = (unsigned int *)&p_engine_scene->mp_scene_data[1];\r\n\r\n\t// Setup material DL pointer.\r\n\tDbg_MsgAssert( p_engine_scene->mp_scene_data->m_num_blend_dls < 256, ( \"Too many (>255) unique material DLs (%d)\\n\", p_engine_scene->mp_scene_data->m_num_blend_dls ) );\r\n\tp_engine_scene->mp_blend_dl = (NxNgc::sMaterialDL *)p32; \r\n\tp_engine_scene->mp_texture_dl = (NxNgc::sTextureDL *)&p_engine_scene->mp_blend_dl[p_engine_scene->mp_scene_data->m_num_blend_dls];\r\n\tunsigned char * p8 = (unsigned char *)&p_engine_scene->mp_texture_dl[p_engine_scene->mp_scene_data->m_num_materials];\r\n\r\n\tint bytes = ( p_engine_scene->mp_scene_data->m_num_blend_dls * sizeof( NxNgc::sMaterialDL ) ) + ( p_engine_scene->mp_scene_data->m_num_materials * sizeof( NxNgc::sTextureDL ) );\r\n\tint rounded_bytes = ( bytes + 31 ) & ~31;\r\n\tint pad_bytes = rounded_bytes - bytes;\r\n\r\n\tp8 = &p8[pad_bytes];\r\n\r\n\t// Assign blend dl pointers.\r\n\tfor ( uint bdl = 0; bdl < p_engine_scene->mp_scene_data->m_num_blend_dls; bdl++ )\r\n\t{\r\n\t\tp_engine_scene->mp_blend_dl[bdl].mp_dl = p8;\r\n\t\tp8 += p_engine_scene->mp_blend_dl[bdl].m_dl_size;\r\n\t}\r\n\r\n\t// Assign texture dl pointers.\r\n\tfor ( uint tdl = 0; tdl < p_engine_scene->mp_scene_data->m_num_materials; tdl++ )\r\n\t{\r\n\t\tp_engine_scene->mp_texture_dl[tdl].mp_dl = p8;\r\n\t\tp8 += p_engine_scene->mp_texture_dl[tdl].m_dl_size;\r\n\t}\r\n\tp32 = (unsigned int *)p8;\r\n\r\n\t// Point past pool data.\r\n\tNxNgc::sObjectHeader* p_data = (NxNgc::sObjectHeader*)&((char*)p32)[p_engine_scene->mp_scene_data->m_num_pool_bytes];\r\n\r\n\t// Setup VC wibble data.\r\n\tp_engine_scene->mp_vc_wibble = (NxNgc::sMaterialVCWibbleKeyHeader *)p32;\r\n\tNxNgc::sMaterialVCWibbleKeyHeader *\tp_key_header\t= p_engine_scene->mp_vc_wibble;\r\n\tNxNgc::sMaterialVCWibbleKey *\t\tp_key\t\t\t= (NxNgc::sMaterialVCWibbleKey *)&p_key_header[1]; \r\n\tfor ( int vc = 0; vc < p_engine_scene->mp_scene_data->m_num_vc_wibbles; vc++ )\r\n\t{\r\n\t\tp_key_header = (NxNgc::sMaterialVCWibbleKeyHeader *)&p_key[p_key_header->m_num_frames]; \r\n\t\tp_key = (NxNgc::sMaterialVCWibbleKey *)&p_key_header[1];  \r\n\t}\r\n\tp32 = (uint32 *)p_key_header;\r\n\r\n\t// Setup material header data.\r\n\tp_engine_scene->mp_material_header = (NxNgc::sMaterialHeader *)p32;\r\n\tp32 = (uint32 *)&p_engine_scene->mp_material_header[p_engine_scene->mp_scene_data->m_num_materials];\r\n\r\n\t// Setup UV wibble data.\r\n\tp_engine_scene->mp_uv_wibble = (NxNgc::sMaterialUVWibble *)p32;\r\n\tp32 = (uint32 *)&p_engine_scene->mp_uv_wibble[p_engine_scene->mp_scene_data->m_num_uv_wibbles];\r\n\r\n\t// Setup material pass data.\r\n\tp_engine_scene->mp_material_pass = (NxNgc::sMaterialPassHeader *)p32;\r\n\tp32 = (uint32 *)&p_engine_scene->mp_material_pass[p_engine_scene->mp_scene_data->m_num_pass_items];\r\n\r\n\t// Setup material data texture pointers.\r\n\tNxNgc::sMaterialHeader * p_mat = p_engine_scene->mp_material_header;\r\n\tfor ( unsigned int lp = 0; lp < p_engine_scene->mp_scene_data->m_num_materials; lp++ )\r\n\t{\r\n\t\tp_mat->m_alpha_cutoff = p_mat->m_alpha_cutoff >= 128 ? 255 : p_mat->m_alpha_cutoff * 2;\r\n\t\t// Need to compensate for possible errors in alpha map.\r\n//\t\tint cut = (int)p_mat->m_alpha_cutoff - 16;\r\n//\t\tif ( cut < 0 ) cut = 0;\r\n//\t\tp_mat->m_alpha_cutoff = cut;\r\n\r\n\t\t// Setup texture pointer.\r\n\t\tNxNgc::sMaterialPassHeader * p_pass = &p_engine_scene->mp_material_pass[p_mat->m_pass_item];\r\n\r\n\t\t// Copy base pass blend mode to material.\r\n\t\tp_mat->m_base_blend = p_pass->m_blend_mode;\r\n\r\n\t\tfor ( int pass = 0; pass < p_mat->m_passes; pass++ )\r\n\t\t{\r\n\t\t\t// If textured, resolve texture checksum...\r\n\t\t\tNx::CNgcTexture *p_ngc_texture = static_cast<Nx::CNgcTexture*>( p_tex_dict->GetTexLookup()->GetItem( p_pass->m_texture.checksum ) );\r\n\t\t\tp_pass->m_texture.p_data = ( p_ngc_texture ) ? p_ngc_texture->GetEngineTexture() : NULL;\r\n\r\n\t\t\t// Temp HACK\r\n//\t\t\tp_pass->m_k = (1<<8);\r\n//\t\t\tp_pass->m_u_tile = (1<<12);\r\n//\t\t\tp_pass->m_v_tile = (1<<12);\r\n//\t\t\tp_pass->m_uv_enabled = 0;\r\n//\t\t\tp_pass->m_uv_mat[0] = (1<<12);\r\n//\t\t\tp_pass->m_uv_mat[1] = 0;\r\n//\t\t\tp_pass->m_uv_mat[2] = 0;\r\n//\t\t\tp_pass->m_uv_mat[3] = 0;\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n//\t\t\tif ( p_pass->m_texture.checksum && !p_ngc_texture )\r\n//\t\t\t{\r\n//\t\t\t\tOSReport( \"Failed to hook up texture!!!!!!!!!!! %08x\\n\", p_pass->m_texture.checksum );\r\n//\t\t\t}\r\n\r\n//\t\t\t// Adjust K value.\r\n//\t\t\tp_pass->m_mip_k += 8;\r\n\r\n\t\t\t// Switch color values.\r\n//\t\t\tu8 r;\r\n//\t\t\tu8 g;\r\n//\t\t\tu8 b;\r\n//\t\t\tu8 a;\r\n//\t\t\tr = p_pass->m_color.r;\r\n//\t\t\tg = p_pass->m_color.g;\r\n//\t\t\tb = p_pass->m_color.b;\r\n//\t\t\ta = p_pass->m_color.a;\r\n//\r\n//\t\t\tp_pass->m_color.r = b;\r\n//\t\t\tp_pass->m_color.g = g;\r\n//\t\t\tp_pass->m_color.b = r;\r\n//\t\t\tp_pass->m_color.a = a;\r\n\r\n//\t\t\tp_pass->m_color.a = 255;\r\n\r\n//\t\t\tp_pass->m_alpha_fix = ( p_pass->m_alpha_fix ) >= 128 ? 255 : p_pass->m_alpha_fix * 2;\r\n\r\n\t\t\t// Next pass structure.\r\n\t\t\t++p_pass;\r\n\t\t}\r\n\r\n\t\t// Scan texture DL and patch texture address pointers.\r\n\t\t// Search for SetMode0/1 SetImage0/1/2/3.\r\n\t\tNxNgc::sTextureDL * p_dl = &p_engine_scene->mp_texture_dl[lp]; \r\n\t\tp_pass = &p_engine_scene->mp_material_pass[p_mat->m_pass_item];\r\n\r\n//\t\tint search_size = ( p_dl->m_dl_size > ((5*5)+4) ) ? p_dl->m_dl_size - ((5*5)+4) : 0;\r\n\r\n//\t\tfor ( int s = 0; s < search_size ; s++ )\r\n\t\t//for ( int s = 0; s < (int)p_dl->m_dl_size ; s++ )\r\n\r\n\t\tGX::ResolveDLTexAddr( p_dl, p_pass, p_mat->m_passes );\r\n\r\n//\t\tGX::begin( p_dl->mp_dl, p_dl->m_dl_size );\r\n//\t\tmulti_mesh( p_mat, p_pass, true, true );\r\n//\t\tp_dl->m_dl_size = GX::end();\r\n\r\n\t\t++p_mat;\r\n\t}\r\n\r\n\t// Setup vertex data.\r\n\tp_engine_scene->mp_pos_pool\t= NULL;\r\n\tp_engine_scene->mp_nrm_pool\t= NULL;\r\n\tp_engine_scene->mp_col_pool\t= NULL;\r\n\tp_engine_scene->mp_tex_pool\t= NULL;\r\n\r\n\tif ( p_engine_scene->mp_scene_data->m_num_pos )\r\n\t{\r\n\t\tp_engine_scene->mp_pos_pool = (float *)p32;\r\n\t\tp32 = &((unsigned int *)p32)[p_engine_scene->mp_scene_data->m_num_pos*3];\r\n\t}\r\n\r\n\tif ( p_engine_scene->mp_scene_data->m_num_col )\r\n\t{\r\n\t\tp_engine_scene->mp_col_pool = (unsigned int *)p32;\r\n\t\tp32 = &((unsigned int *)p32)[p_engine_scene->mp_scene_data->m_num_col];\r\n\t}\r\n\r\n\tif ( p_engine_scene->mp_scene_data->m_num_tex )\r\n\t{\r\n\t\tp_engine_scene->mp_tex_pool = (s16 *)p32;\r\n\t\tp32 = (unsigned int *)&p_engine_scene->mp_tex_pool[p_engine_scene->mp_scene_data->m_num_tex*2];\r\n\t}\r\n\r\n\tif ( p_engine_scene->mp_scene_data->m_num_nrm )\r\n\t{\r\n\t\tp_engine_scene->mp_nrm_pool = (s16 *)p32;\r\n\t\tp32 = (unsigned int*)&p_engine_scene->mp_nrm_pool[p_engine_scene->mp_scene_data->m_num_nrm*3];\r\n\t}\r\n\r\n\tif ( p_engine_scene->mp_scene_data->m_num_shadow_faces )\r\n\t{\r\n\t\tp_engine_scene->mp_shadow_volume_mesh = (uint16*)p32;\r\n\t\tp32 = (unsigned int *)(&((unsigned short *)p32)[p_engine_scene->mp_scene_data->m_num_shadow_faces*3]);\r\n\t\tp_engine_scene->mp_shadow_edge = (NxNgc::sShadowEdge *)p32; \r\n\t\tp32 = (unsigned int *)(&((NxNgc::sShadowEdge *)p32)[p_engine_scene->mp_scene_data->m_num_shadow_faces]);\r\n\t}\r\n\r\n\t// Calculate radius.\r\n\tp_engine_scene->m_sphere[X] = 0.0f;\r\n\tp_engine_scene->m_sphere[Y] = 0.0f;\r\n\tp_engine_scene->m_sphere[Z] = 0.0f;\r\n\tp_engine_scene->m_sphere[W] = 0.0f;\r\n\r\n\tfor ( uint32 lp = 0; lp < p_engine_scene->mp_scene_data->m_num_pos; lp++ )\r\n\t{\r\n\t\tNsVector v;\r\n\t\tv.x = p_engine_scene->mp_pos_pool[(lp*3)+0];\r\n\t\tv.y = p_engine_scene->mp_pos_pool[(lp*3)+1];\r\n\t\tv.z = p_engine_scene->mp_pos_pool[(lp*3)+2];\r\n\t\tfloat l = v.length();\r\n\r\n\t\tif ( l > p_engine_scene->m_sphere[W] ) p_engine_scene->m_sphere[W] = l;\r\n\t}\r\n\r\n\t// Setup display list pointer.\r\n\tp_engine_scene->mp_dl = (NxNgc::sDLHeader *)&(((char*)&p_data[1])[p_data->m_skin.num_bytes]);\r\n\r\n\tfor( uint s = 0; s < p_engine_scene->mp_scene_data->m_num_objects; ++s )\r\n\t{\r\n\t\t// Create a new sector to hold the incoming details.\r\n\t\tpSector\t\t\t\t\t\t= p_new_ngc_scene->CreateSector();\r\n\t\tpNgcSector\t\t\t\t\t= static_cast<CNgcSector*>( pSector );\r\n\r\n\t\t// Generate a hanging geom for the sector, used for creating level objects etc.\r\n\t\tCNgcGeom\t*p_Ngc_geom\t= new CNgcGeom();\r\n\t\tp_Ngc_geom->SetScene( p_new_ngc_scene );\r\n\t\tpNgcSector->SetGeom( p_Ngc_geom );\r\n\r\n\t\t// Prepare CNgcGeom for receiving data.\r\n\t\tp_Ngc_geom->InitMeshList();\r\n\r\n\t\t// Load sector data.\r\n\t\tp_data = pNgcSector->LoadFromFile( p_data );\r\n\t\tnew_scene->AddSector( pSector );\r\n\r\n//\t\tif( ( p_data = pNgcSector->LoadFromFile( p_file, p_data ) ) )\r\n//\t\t{\r\n//\t\t\tnew_scene->AddSector( pSector );\r\n//\t\t}\r\n\t}\r\n\r\n\t// At this point we can process any scaling that may need to be applied to the positions.\r\n\tif ( p_engine_scene->mp_dl->mp_object_header->m_skin.p_data )\r\n\t{\r\n\t\tNxNgc::ApplyMeshScaling( p_engine_scene->mp_dl->mp_object_header );\r\n\t}\r\n\r\n\t// Point up hierarchy.\r\n\tuint32 * p_h = (uint32 *)p_data;\r\n\tuint32 num_hobj = *p_h++;\r\n\r\n\tif ( num_hobj )\r\n\t{\r\n\t\tp_engine_scene->mp_hierarchyObjects = (CHierarchyObject *)p_h;\r\n\t\tp_engine_scene->m_numHierarchyObjects = num_hobj;\r\n\t\t//p32 = (uint32 *)&p_engine_scene->mp_hierarchyObjects[num_hobj];\r\n\r\n//\t\tp_engine_scene->mp_hierarchyObjects = new CHierarchyObject[num_hobj];\r\n//\r\n//\t\tFile::Read( p_engine_scene->mp_hierarchyObjects, sizeof( CHierarchyObject ), num_hobj, p_file );\r\n//\r\n//\t\tp_engine_scene->m_numHierarchyObjects = num_hobj;\r\n\r\n\t\t// Fix up hierarchical object sphere.\r\n\t\tLst::HashTable< Nx::CSector > *p_sector_list = new_scene->GetSectorList();\r\n\t\tif( p_sector_list )\r\n\t\t{\r\n\t\t\tp_sector_list->IterateStart();\t\r\n\t\t\tNx::CSector *p_sector = p_sector_list->IterateNext();\r\n\t\t\twhile( p_sector )\r\n\t\t\t{\r\n\t\t\t\tpNgcSector = static_cast<CNgcSector*>( p_sector );\r\n\t\t\t\tCNgcGeom *p_Ngc_geom = static_cast<CNgcGeom *>( pNgcSector->GetGeom() );\r\n\r\n\t\t\t\tLst::Head< NxNgc::sMesh >\t*p_mesh_list = p_Ngc_geom->GetMeshList();\r\n\t\t\t\tint num_mesh = p_mesh_list->CountItems();\r\n\t\t\t\tif (num_mesh)\r\n\t\t\t\t{\r\n\t\t\t\t\tLst::Node< NxNgc::sMesh > *mesh = p_mesh_list->GetNext();\r\n\t\t\t\t\tmesh->GetData()->mp_dl->mp_object_header->m_sphere[W] *= 2.0f;  \r\n\t\t\t\t}\r\n\t\t\t\tp_sector = p_sector_list->IterateNext();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif ( s_correctable ) gCorrectColor = false;\r\n\r\n\treturn new_scene;\r\n\r\n//------------------------------------------------------------------------------------\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n//\t// Open the scene file.\r\n//\tvoid* p_file = File::Open( p_name, \"rb\" );\r\n//\tif( !p_file )\r\n//\t{\r\n//\t\tDbg_MsgAssert( p_file, ( \"Couldn't open scene file %s\\n\", p_name ));\r\n//\t\tif ( s_correctable ) gCorrectColor = false;\r\n//\t\treturn NULL;\r\n//\t}\r\n//\t\r\n//\t// Version numbers.\r\n//\tuint32 mat_version, mesh_version, vert_version;\r\n//\tFile::Read( &mat_version, sizeof( uint32 ), 1, p_file );\r\n//\tFile::Read( &mesh_version, sizeof( uint32 ), 1, p_file );\r\n//\tFile::Read( &vert_version, sizeof( uint32 ), 1, p_file );\r\n//\tDbg_Message( \"material version %d\\n\", mat_version );\r\n//\tDbg_Message( \"mesh version %d\\n\", mesh_version );\r\n//\tDbg_Message( \"vertex version %d\\n\", vert_version );\r\n//\r\n//\t// Import materials (they will now be associated at the engine-level with this scene).\r\n//\tp_engine_scene->mp_material_array = NxNgc::LoadMaterials( p_file, p_tex_dict->GetTexLookup(), &p_engine_scene->m_num_materials );\r\n//\r\n//\t// Read number of sectors.\r\n//\tint num_sectors;\r\n//\tFile::Read( &num_sectors, sizeof( int ), 1, p_file );\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\tNxNgc::sDLHeader* p_data = (NxNgc::sDLHeader*)p_engine_scene->mp_dl;\r\n//\r\n//\tfor( int s = 0; s < num_sectors; ++s )\r\n//\t{\r\n//\t\t// Create a new sector to hold the incoming details.\r\n//\t\tpSector\t\t\t\t\t\t= p_new_ngc_scene->CreateSector();\r\n//\t\tpNgcSector\t\t\t\t\t= static_cast<CNgcSector*>( pSector );\r\n//\t\t\r\n//\t\t// Generate a hanging geom for the sector, used for creating level objects etc.\r\n//\t\tCNgcGeom\t*p_Ngc_geom\t= new CNgcGeom();\r\n//\t\tp_Ngc_geom->SetScene( p_new_ngc_scene );\r\n//\t\tpNgcSector->SetGeom( p_Ngc_geom );\r\n//\t\t\r\n//\t\t// Prepare CNgcGeom for receiving data.\r\n//\t\tp_Ngc_geom->InitMeshList();\r\n//\t\t\r\n//\t\t// Load sector data.\r\n//\t\tp_data = pNgcSector->LoadFromFile( p_file, p_data );\r\n//\t\tnew_scene->AddSector( pSector );\r\n//\r\n////\t\tif( ( p_data = pNgcSector->LoadFromFile( p_file, p_data ) ) )\r\n////\t\t{\r\n////\t\t\tnew_scene->AddSector( pSector );\r\n////\t\t}\r\n//\t}\r\n//\r\n//\t// Load hierarchy.\r\n//\tuint32 num_hobj;\r\n//\tFile::Read( &num_hobj, sizeof( uint32 ), 1, p_file );\r\n//\r\n//\tif ( num_hobj )\r\n//\t{\r\n//\t\tp_engine_scene->mp_hierarchyObjects = new CHierarchyObject[num_hobj];\r\n//\r\n//\t\tFile::Read( p_engine_scene->mp_hierarchyObjects, sizeof( CHierarchyObject ), num_hobj, p_file );\r\n//\r\n//\t\tp_engine_scene->m_numHierarchyObjects = num_hobj;\r\n//\t}\r\n//\r\n//\t// At this point get the engine scene to figure it's bounding volumes.\r\n//\tp_engine_scene->FigureBoundingVolumes();\r\n//\t\r\n//\tFile::Close( p_file );\r\n//\r\n//\tif ( s_correctable ) gCorrectColor = false;\r\n//\r\n//\treturn new_scene;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCScene *CEngine::s_plat_load_scene_from_memory( void *p_mem, CTexDict *p_tex_dict, bool add_super_sectors, bool is_sky, bool is_dictionary )\r\n{\r\n\tint size = s_plat_scene_size( p_mem, p_tex_dict, add_super_sectors, is_sky, is_dictionary );\r\n\r\n\tint mem_available;\r\n\tbool need_to_pop = false;\r\n\tif ( g_in_cutscene )\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().FrontEndHeap() );\r\n\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\tif ( size < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t{\r\n\t\t\tneed_to_pop = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ThemeHeap() );\r\n\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\tif ( size < ( mem_available - ( 5 * 1024 ) ) )\r\n\t\t\t{\r\n\t\t\t\tneed_to_pop = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ScriptHeap() );\r\n\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\tif ( size < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\tchar * p_scene_data = new char[size]; \r\n\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\r\n\tif ( need_to_pop )\r\n\t{\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\r\n\tmemcpy( p_scene_data, p_mem, size );\r\n\tDCFlushRange( p_scene_data, size );\r\n\r\n\treturn s_plat_load_scene_guts( p_scene_data, p_tex_dict, add_super_sectors, is_sky, is_dictionary );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCScene*\tCEngine::s_plat_load_scene( const char *p_name, CTexDict *p_tex_dict, bool add_super_sectors, bool is_sky, bool is_dictionary )\r\n{\r\n\tDbg_Message( \"loading scene from file %s\\n\", p_name );\r\n\r\n\t// Open the scene file.\r\n\tchar gdname[128];\r\n\tsprintf( gdname, \"%s\", p_name );\r\n\tvoid* p_gd_file = File::Open( gdname, \"rb\" );\r\n\tif( !p_gd_file )\r\n\t{\r\n\t\tDbg_MsgAssert( p_gd_file, ( \"Couldn't open scene file %s\\n\", gdname ));\r\n\t\tif ( s_correctable ) gCorrectColor = false;\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\t// Read all data.\r\n\tint size = File::GetFileSize( p_gd_file );\r\n\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\tchar * p_scene_data = new char[size]; \r\n\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\tFile::Read( p_scene_data, size, 1, p_gd_file );\r\n\t\r\n\tFile::Close( p_gd_file );\r\n\r\n\tDCFlushRange( p_scene_data, size );\r\n\treturn s_plat_load_scene_guts( p_scene_data, p_tex_dict, add_super_sectors, is_sky, is_dictionary );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CEngine::s_plat_add_scene( CScene *p_scene, const char *p_filename )\r\n{\r\n\t// Function to incrementally add geometry to a scene - should NOT be getting called on GameCube.\r\n\tDbg_Assert( 0 );\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CEngine::s_plat_unload_scene( CScene *p_scene )\r\n{\r\n\tDbg_MsgAssert( p_scene,( \"Trying to delete a NULL scene\" ));\r\n\r\n\tCNgcScene *p_ngc_scene = (CNgcScene*)p_scene;\r\n\r\n\t// Ask the engine to remove the associated meshes for each sector in the scene.\r\n\tp_ngc_scene->DestroySectorMeshes();\r\n\r\n\t// Get the engine specific scene data and pass it to the engine to delete.\r\n\tNxNgc::DeleteScene( p_ngc_scene->GetEngineScene());\r\n\tp_ngc_scene->SetEngineScene( NULL );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModel*\t\tCEngine::s_plat_init_model( void )\r\n{\r\n\tCNgcModel* pModel = new CNgcModel;\r\n\r\n\treturn pModel;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCEngine::s_plat_uninit_model(CModel* pModel)\r\n{\r\n\tDbg_Assert( pModel );\r\n\r\n\tdelete pModel;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMesh* CEngine::s_plat_load_mesh( const char* pMeshFileName, Nx::CTexDict* pTexDict, uint32 texDictOffset, bool isSkin, bool doShadowVolume )\r\n{\r\n\ts_correctable = false;\r\n\t// Load the scene.\r\n\tNx::CScene *p_scene = Nx::CEngine::s_plat_load_scene( pMeshFileName, pTexDict, false, false, false );\r\n\tp_scene->SetID(Script::GenerateCRC( pMeshFileName )); \t// store the checksum of the scene name\r\n\tp_scene->SetTexDict( pTexDict );\r\n\tp_scene->PostLoad( pMeshFileName );\r\n\t\r\n\t// Disable any scaling.\r\n\tNxNgc::DisableMeshScaling();\r\n\t\r\n\tCNgcMesh *pMesh = new CNgcMesh( pMeshFileName );\r\n\tNx::CNgcScene *p_Ngc_scene = static_cast<Nx::CNgcScene*>( p_scene );\r\n\tpMesh->SetScene( p_Ngc_scene );\r\n\tpMesh->SetTexDict( pTexDict );\r\n\ts_correctable = true;\r\n\treturn pMesh;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCMesh* CEngine::s_plat_load_mesh( uint32 id, uint32 *p_model_data, int model_data_size, uint8 *p_cas_data, Nx::CTexDict* pTexDict, uint32 texDictOffset, bool isSkin, bool doShadowVolume )\r\n{\r\n\t// Convert the id into a usable string.\r\n\tDbg_Assert( id > 0 );\r\n\tchar id_as_string[16];\r\n\tsprintf( id_as_string, \"%d\\n\", id );\r\n\r\n\t// Load the scene.\r\n\tNx::CScene *p_scene = Nx::CEngine::s_plat_load_scene_from_memory( p_model_data, pTexDict, false, false, false );\r\n\r\n\t// Store the checksum of the scene name.\r\n\tp_scene->SetID( Script::GenerateCRC( id_as_string ));\r\n\r\n\tp_scene->SetTexDict( pTexDict );\r\n\tp_scene->PostLoad( id_as_string );\r\n\t\r\n\t// Disable any scaling.\r\n\tNxNgc::DisableMeshScaling();\r\n\t\r\n\tCNgcMesh *pMesh = new CNgcMesh();\r\n\r\n\t// Set CAS data for mesh.\r\n\tpMesh->SetCASData( p_cas_data );\r\n\r\n\tNx::CNgcScene *p_Ngc_scene = static_cast<Nx::CNgcScene*>( p_scene );\r\n\tpMesh->SetScene( p_Ngc_scene );\r\n\tpMesh->SetTexDict( pTexDict );\r\n\treturn pMesh;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCEngine::s_plat_unload_mesh(CMesh* pMesh)\r\n{\r\n\tDbg_Assert( pMesh );\r\n\r\n\tdelete pMesh;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_set_mesh_scaling_parameters( SMeshScalingParameters* pParams )\r\n{\r\n\tNxNgc::SetMeshScalingParameters( pParams );\r\n}\r\n\r\n\r\n\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//CTexDict* CEngine::s_plat_load_textures( const char* p_name )\r\n//{\r\n////\tNxNgc::LoadTextureFile( p_name );\r\n//\treturn NULL;\r\n//}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCSprite *\tCEngine::s_plat_create_sprite(CWindow2D *p_window)\r\n{\r\n\treturn new CNgcSprite;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CEngine::s_plat_destroy_sprite( CSprite *p_sprite )\r\n{\r\n\tdelete p_sprite;\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTextured3dPoly *\tCEngine::s_plat_create_textured_3d_poly()\r\n{\r\n\treturn new NxNgc::CNgcTextured3dPoly;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCEngine::s_plat_destroy_textured_3d_poly(CTextured3dPoly *p_poly)\r\n{\r\n\tdelete p_poly;\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::CTexture *CEngine::s_plat_create_render_target_texture( int width, int height, int depth, int z_depth )\r\n{\r\n\t// Create the CNgcTexture (just a container class for the NxNgc::sTexture).\r\n\tCNgcTexture *p_texture = new CNgcTexture();\r\n\r\n\t// Create the NxNgc::sTexture.\r\n\tNxNgc::sTexture *p_engine_texture = new NxNgc::sTexture;\r\n\tp_texture->SetEngineTexture( p_engine_texture );\r\n\t\r\n\t// Set the texture as a render target.\r\n\tp_engine_texture->SetRenderTarget( width, height, depth, z_depth );\r\n\t\r\n\treturn p_texture;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CEngine::s_plat_project_texture_into_scene( Nx::CTexture *p_texture, Nx::CModel *p_model, Nx::CScene *p_scene )\r\n{\r\n\tNx::CNgcTexture\t\t*p_ngc_texture\t= static_cast<CNgcTexture*>( p_texture );\r\n\tNx::CNgcModel\t\t*p_ngc_model\t= static_cast<CNgcModel*>( p_model );\r\n//\tNx::CNgcScene\t\t*p_ngc_scene\t= static_cast<CNgcScene*>( p_scene );\r\n//\tNxNgc::create_texture_projection_details( p_ngc_texture->GetEngineTexture(), p_ngc_model, p_ngc_scene->GetEngineScene());\r\n\tNxNgc::create_texture_projection_details( p_ngc_texture->GetEngineTexture(), p_ngc_model, NULL);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CEngine::s_plat_set_projection_texture_camera( Nx::CTexture *p_texture, Gfx::Camera *p_camera )\r\n{\r\n\tNx::CNgcTexture\t\t*p_ngc_texture\t= static_cast<CNgcTexture*>( p_texture );\r\n\tNsVector\t\t\tpos( p_camera->GetPos()[X], p_camera->GetPos()[Y], p_camera->GetPos()[Z] );\r\n\tNsVector\t\t\tat( pos.x + p_camera->GetMatrix()[Z][X], pos.y + p_camera->GetMatrix()[Z][Y], pos.z + p_camera->GetMatrix()[Z][Z] );\r\n\t\r\n\tNxNgc::set_texture_projection_camera( p_ngc_texture->GetEngineTexture(), &pos, &at );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CEngine::s_plat_stop_projection_texture( Nx::CTexture *p_texture )\r\n{\r\n\tNx::CNgcTexture *p_ngc_texture = static_cast<CNgcTexture*>( p_texture );\r\n\tNxNgc::destroy_texture_projection_details( p_ngc_texture->GetEngineTexture());\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_add_occlusion_poly( uint32 num_verts, Mth::Vector *p_vert_array, uint32 checksum )\r\n{\r\n\tif( num_verts == 4 )\r\n\t{\r\n\t\tNxNgc::AddOcclusionPoly( p_vert_array[0], p_vert_array[1], p_vert_array[2], p_vert_array[3], checksum );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_enable_occlusion_poly( uint32 checksum, bool enable )\r\n{\r\n\tNxNgc::EnableOcclusionPoly( checksum, enable );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_remove_all_occlusion_polys( void )\r\n{\r\n\tNxNgc::RemoveAllOcclusionPolys();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// returns true if the sphere at \"center\", with the \"radius\"\r\n// is visible to the current camera\r\n// (note, currently this is the last frame's camera on PS2)\r\n\r\nbool CEngine::s_plat_is_visible( Mth::Vector&\tcenter, float radius  )\r\n{\r\n\tMth::Vector v;\r\n\tv[X] = center[X];\r\n\tv[Y] = center[Y];\r\n\tv[Z] = center[Z];\r\n\tv[W] = radius;\r\n\r\n\treturn NxNgc::IsVisible( v );\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst char* CEngine::s_plat_get_platform_extension( void )\r\n{\r\n\t// String literals are statically allocated so can be returned safely, (Bjarne, p90)\r\n\treturn \"ngc\";\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom* CEngine::s_plat_init_geom( void )\r\n{\r\n\tCNgcGeom* pGeom = new CNgcGeom;\r\n\r\n\treturn pGeom;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCEngine::s_plat_uninit_geom(CGeom* pGeom)\r\n{\r\n\tDbg_Assert( pGeom );\r\n\r\n\tdelete pGeom;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCQuickAnim* CEngine::s_plat_init_quick_anim()\r\n{\r\n\tCQuickAnim* pQuickAnim = new CQuickAnim;\r\n\r\n\treturn pQuickAnim;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CEngine::s_plat_uninit_quick_anim(CQuickAnim* pQuickAnim)\r\n{\r\n\tDbg_Assert( pQuickAnim );\r\n\r\n\tdelete pQuickAnim;\r\n\r\n\treturn;\r\n}\r\n\r\n/******************************************************************/\r\n// Wait for any pending asyncronous rendering to finish, so rendering\r\n// data can be unloaded\r\n/******************************************************************/\r\n\r\nvoid CEngine::s_plat_finish_rendering()\r\n{\r\n\t// TODO:  Flush pending rendering, so data can be unloaded\r\n\tNsDisplay::flush();\r\n} \r\n\r\n/******************************************************************/\r\n// Set the amount that the previous frame is blended with this frame\r\n// 0 = none\t  \t(just see current frame) \t\r\n// 128 = 50/50\r\n// 255 = 100% \t(so you only see the previous frame)\t\t\t\t\t\t\t\t\t\t\t\t  \r\n/******************************************************************/\r\n\r\nvoid CEngine::s_plat_set_screen_blur(uint32 amount )\r\n{\r\n//\tg_blur = ( amount * 8 ) / 255;\r\n//\tsBlur = amount;\r\n} \r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\ts_plat_get_num_soundtracks()\r\n{\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char* s_plat_get_soundtrack_name( int soundtrack_number )\r\n{\r\n\treturn NULL;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint\tCEngine::s_plat_get_num_soundtracks( void )\r\n{\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char* CEngine::s_plat_get_soundtrack_name( int soundtrack_number )\r\n{\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_set_max_multipass_distance(float dist)\r\n{\r\n//\tNxPs2::render::sMultipassMaxDist = dist;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_set_letterbox( bool letterbox )\r\n{\r\n\t// Letterbox mode is designed for use on a regular 4:3 screen.\r\n\t// It should use the same, wider viewing angle as for widescreen mode, but shrink the resultant image down\r\n\t// vertically by 25%.\r\n\tif( letterbox )\r\n\t{\r\n\t\tif( NxNgc::EngineGlobals.letterbox_active == false )\r\n\t\t{\r\n\t\t\t// Need to adjust the screen y offset and multiplier to ensure sprites are scaled properly for this mode.\r\n//\t\t\tNxNgc::EngineGlobals.screen_conv_y_offset\t\t+= ( NxXbox::EngineGlobals.backbuffer_height / 4 ) / 2;\r\n//\t\t\tNxNgc::EngineGlobals.screen_conv_y_multiplier\t= 0.75f;\r\n\t\t\tNxNgc::EngineGlobals.letterbox_active\t\t\t= true;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( NxNgc::EngineGlobals.letterbox_active == true )\r\n\t\t{\r\n\t\t\t// Restore the screen y offset and multiplier.\r\n//\t\t\tNxNgc::EngineGlobals.screen_conv_y_offset\t\t-= ( NxXbox::EngineGlobals.backbuffer_height / 4 ) / 2;\r\n//\t\t\tNxNgc::EngineGlobals.screen_conv_y_multiplier\t= 1.0f;\r\n\t\t\tNxNgc::EngineGlobals.letterbox_active\t\t\t= false;\r\n\t\t}\r\n\t}\r\n} \r\n \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_set_color_buffer_clear( bool clear )\r\n{\r\n}\r\n\r\n\r\n\r\n} // namespace Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxanimcache.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_NxAnimCache.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  5/06/2002\r\n//****************************************************************************\r\n\r\n#include <gfx/ngc/p_nxanimcache.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNgcAnimCache::CNgcAnimCache( int lookupTableSize ) : CAnimCache( lookupTableSize )\r\n{\r\n\t// Machine specific code here ............\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNgcAnimCache::~CNgcAnimCache()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n\t\t\t\t\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxanimcache.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_NxAnimCache.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  5/06/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NXANIMCACHE_H__\r\n#define\t__GFX_P_NXANIMCACHE_H__\r\n    \r\n#include <gfx/nxanimcache.h>\r\n\r\nnamespace Nx\r\n{\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CGeom\r\n    \r\nclass CNgcAnimCache : public CAnimCache\r\n{\r\n                                      \r\npublic:\r\n\t\t\t\t\t\tCNgcAnimCache( int lookupTableSize );\r\n\tvirtual \t\t\t~CNgcAnimCache();\r\n\r\nprivate:\t\t\t\t// It's all private, as it is machine specific\r\n};\r\n\r\n} // Nx\r\n\r\n#endif \r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxfont.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxFont.cpp\r\n\r\n#include \t\"gfx/Ngc/p_nxfont.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CFont\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNgcFont::CNgcFont() : mp_plat_font(NULL)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNgcFont::~CNgcFont()\r\n{\r\n\tif (mp_plat_font)\r\n\t{\r\n\t\tplat_unload();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcFont::plat_load(const char *filename)\r\n{\r\n\tmp_plat_font = NxNgc::LoadFont(filename);\r\n\r\n\treturn (mp_plat_font != NULL);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcFont::plat_set_spacings(int charSpacing, int spaceSpacing)\r\n{\r\n\tmp_plat_font->mCharSpacing = charSpacing;\r\n\tif (spaceSpacing > 0)\r\n\t\tmp_plat_font->mSpaceSpacing = spaceSpacing;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcFont::plat_set_rgba_table(Image::RGBA *pTab)\r\n{\r\n\tfor (int i = 0; i < 16; i++)\r\n\t\tmp_plat_font->mRGBATab[i] = *((uint32 *) &pTab[i]);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcFont::plat_mark_as_button_font(bool isButton)\r\n{\r\n\tNxNgc::pButtonsFont = (isButton) ? mp_plat_font : NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcFont::plat_unload()\r\n{\r\n\tNxNgc::UnloadFont(mp_plat_font);\r\n\tmp_plat_font = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 CNgcFont::plat_get_default_height() const\r\n{\r\n\tDbg_Assert(mp_plat_font);\r\n\r\n\treturn mp_plat_font->GetDefaultHeight();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 CNgcFont::plat_get_default_base() const\r\n{\r\n\tDbg_Assert(mp_plat_font);\r\n\r\n\treturn mp_plat_font->GetDefaultBase();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//void CNgcFont::plat_begin_text(uint32 rgba, float Scale)\r\n//{\r\n//\tDbg_Assert(mp_plat_font);\r\n//\r\n//\tmp_plat_font->BeginText(rgba, Scale);\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//void CNgcFont::plat_draw_string(char *String, float x0, float y0)\r\n//{\r\n//\tDbg_Assert(mp_plat_font);\r\n//\r\n//\tmp_plat_font->DrawString(String, x0, y0);\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//void CNgcFont::plat_end_text(void)\r\n//{\r\n//\tDbg_Assert(mp_plat_font);\r\n//\r\n//\tmp_plat_font->EndText();\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcFont::plat_query_string(char *String, float &width, float &height) const\r\n{\r\n\tDbg_Assert(mp_plat_font);\r\n\r\n\tmp_plat_font->QueryString(String, width, height);\r\n}\r\n\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of the CText\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcText::CNgcText()\r\n{\r\n\tmp_plat_text = new NxNgc::SText();\r\n\r\n\tplat_initialize();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcText::~CNgcText()\r\n{\r\n\tif( mp_plat_text )\r\n\t{\r\n\t\tdelete mp_plat_text;\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcText::plat_initialize()\r\n{\r\n\tplat_update_engine();\r\n\tplat_update_priority();\r\n\tplat_update_hidden();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcText::plat_update_hidden()\r\n{\r\n\tmp_plat_text->SetHidden(m_hidden);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcText::plat_update_engine()\r\n{\r\n\tCNgcFont *p_Ngc_font = static_cast<CNgcFont *>( mp_font );\r\n\r\n\tmp_plat_text->mp_string\t= m_string;\r\n\tif( p_Ngc_font)\r\n\t{\r\n\t\tmp_plat_text->mp_font = p_Ngc_font->GetEngineFont();\r\n\t}\r\n\r\n\tmp_plat_text->m_xpos\t= m_xpos;\r\n\tmp_plat_text->m_ypos\t= m_ypos;\r\n\tmp_plat_text->m_xscale\t= m_xscale;\r\n\tmp_plat_text->m_yscale\t= m_yscale;\r\n\tmp_plat_text->m_rgba\t= *((uint32 *) &m_rgba);\r\n\tmp_plat_text->m_color_override = m_color_override;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcText::plat_update_priority( void )\r\n{\r\n\t// Update draw list\r\n\tmp_plat_text->SetPriority( m_priority );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CTextMan::s_plat_alloc_text_pool( void )\r\n{\r\n\tfor( int i = 0; i < vMAX_TEXT_INSTANCES; ++i )\r\n\t{\r\n\t   \tCNgcText *p_text\t\t= new CNgcText;\r\n\t\tp_text->mp_next\t\t\t= sp_dynamic_text_list;\r\n\t\tsp_dynamic_text_list\t= p_text;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxfont.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxFont.h\r\n\r\n#ifndef\t__GFX_P_NX_FONT_H__\r\n#define\t__GFX_P_NX_FONT_H__\r\n\r\n#include \t\"gfx/nxfont.h\"\r\n#include \t\"gfx/Ngc/nx/chars.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CFont\r\nclass CNgcFont : public CFont\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCNgcFont();\r\n\tvirtual\t\t\t\t\t\t~CNgcFont();\r\n\tNxNgc::SFont\t\t\t\t*GetEngineFont() const;\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\tvirtual\tbool\t\t\t\tplat_load(const char *filename);\r\n\tvirtual void\t\t\t\tplat_set_spacings(int charSpacing, int spaceSpacing);\r\n\tvirtual void\t\t\t\tplat_set_rgba_table(Image::RGBA *pTab);\r\n\tvirtual void \t\t\t\tplat_mark_as_button_font(bool isButton);\r\n\tvirtual void\t\t\t\tplat_unload();\r\n\r\n\tvirtual\tuint32\t\t\t\tplat_get_default_height() const;\r\n\tvirtual\tuint32\t\t\t\tplat_get_default_base() const;\r\n//\tvirtual void\t\t\t\tplat_begin_text(uint32 rgba, float Scale);\r\n//\tvirtual void\t\t\t\tplat_draw_string(char *String, float x0, float y0);\r\n//\tvirtual void\t\t\t\tplat_end_text(void);\r\n\tvirtual void\t\t\t\tplat_query_string(char *String, float &width, float &height) const;\r\n\r\n\t// Machine specific members\r\n\tNxNgc::SFont *\t\t\t\tmp_plat_font;\t\t// Pointer to engine font\r\n};\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of the CText\r\nclass\tCNgcText : public CText\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCNgcText();\r\n\tvirtual\t\t\t\t\t\t~CNgcText();\r\n\r\nprivate:\r\n\t//\r\n\tvirtual void\t\t\t\tplat_initialize();\r\n\r\n\tvirtual void\t\t\t\tplat_update_hidden();\t\t// Tell engine of update\r\n\tvirtual void\t\t\t\tplat_update_engine();\t\t// Update engine primitives\r\n\tvirtual void\t\t\t\tplat_update_priority();\r\n\r\n\t// Machine specific members\r\n\tNxNgc::SText\t\t\t\t*mp_plat_text;\t\t// Pointer to engine text\r\n};\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ninline NxNgc::SFont *CNgcFont::GetEngineFont() const\r\n{\r\n\treturn mp_plat_font;\r\n}\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxfontman.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\t\t\t \t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgfx/Ngc/p_nxfontman.cpp\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/16/2002\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNgc platform specific interface to the Font Manager\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include\t\"gfx\\nx.h\"\r\n#include\t\"gfx\\NxFontMan.h\"\r\n#include\t\"gfx\\Ngc\\p_NxFont.h\"\r\n#include \t\"gfx\\Ngc\\nx\\chars.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCFont* CFontManager::s_plat_load_font( const char* pName )\r\n{\r\n\tCNgcFont *p_new_font = new CNgcFont;\r\n\tp_new_font->Load( pName );\r\n\treturn p_new_font;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CFontManager::s_plat_unload_font( CFont* pFont )\r\n{\r\n\tpFont->Unload();\r\n}\r\n\r\n} // namespace Nx\r\n \r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxlight.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxLight.cpp - Ngc platform specific interface to CModelLights\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gfx/Ngc/p_NxLight.h>\r\n#include <gfx/Ngc/nx/nx_init.h>\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcModelLights::CNgcModelLights()\r\n{\r\n\tm_flags = 0;\r\n\r\n\tEnableAmbientLight( false );\r\n\tfor( int i = 0; i < CLightManager::MAX_LIGHTS; ++i )\r\n\t{\r\n\t\tEnableDiffuseLight( i, false );\r\n\t}\r\n\t\r\n\t// Set valid default direction.\r\n\tm_diffuse_direction[0].Set( 0.0f, 1.0f, 0.0f );\r\n\tm_diffuse_direction[1].Set( 0.0f, 1.0f, 0.0f );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcModelLights::~CNgcModelLights()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcModelLights::plat_update_brightness()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcModelLights::plat_update_engine( Mth::Vector & pos, bool add_scene_light )\r\n{\r\n\tif( m_flags & mUSE_MODEL_AMBIENT )\r\n\t{\r\n\t\t// Use the local ambient color, modulate it with the local ambient brightness.\r\n\t\tint difr = (int)((float)m_ambient_color.r * m_ambient_brightness);\r\n\t\tint difg = (int)((float)m_ambient_color.g * m_ambient_brightness);\r\n\t\tint difb = (int)((float)m_ambient_color.b * m_ambient_brightness);\r\n\t\tNxNgc::EngineGlobals.ambient_light_color.r = difr > 255 ? 255 : (u8)difr; \r\n\t\tNxNgc::EngineGlobals.ambient_light_color.g = difg > 255 ? 255 : (u8)difg; \r\n\t\tNxNgc::EngineGlobals.ambient_light_color.b = difb > 255 ? 255 : (u8)difb; \r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Use the default ambient color, but modulate it with the local ambient brightness.\r\n\t\tImage::RGBA\tamb = CLightManager::sGetLightAmbientColor();\r\n\t\tint difr = (int)((float)amb.r * m_ambient_brightness);\r\n\t\tint difg = (int)((float)amb.g * m_ambient_brightness);\r\n\t\tint difb = (int)((float)amb.b * m_ambient_brightness);\r\n\t\tNxNgc::EngineGlobals.ambient_light_color.r = difr > 255 ? 255 : (u8)difr;  \r\n\t\tNxNgc::EngineGlobals.ambient_light_color.g = difg > 255 ? 255 : (u8)difg;  \r\n\t\tNxNgc::EngineGlobals.ambient_light_color.b = difb > 255 ? 255 : (u8)difb;  \r\n\t}\r\n\r\n//\tNxNgc::EngineGlobals.ambient_light_color.r = NxNgc::EngineGlobals.ambient_light_color.r < 128 ? NxNgc::EngineGlobals.ambient_light_color.r * 2 : 255;\r\n//\tNxNgc::EngineGlobals.ambient_light_color.g = NxNgc::EngineGlobals.ambient_light_color.g < 128 ? NxNgc::EngineGlobals.ambient_light_color.g * 2 : 255;\r\n//\tNxNgc::EngineGlobals.ambient_light_color.b = NxNgc::EngineGlobals.ambient_light_color.b < 128 ? NxNgc::EngineGlobals.ambient_light_color.b * 2 : 255;\r\n\r\n\tfor( int i = 0; i < 2; ++i )\r\n\t{\r\n\t\tif( m_flags & (( i == 0 ) ? mUSE_MODEL_DIFFUSE_0 : mUSE_MODEL_DIFFUSE_1 ))\r\n\t\t{\r\n\t\t\t// Use the local directional color, modulate it with the local directional brightness.\r\n\t\t\tint difr = (int)((float)m_diffuse_color[i].r * m_diffuse_brightness[i] * 0.5f);\r\n\t\t\tint difg = (int)((float)m_diffuse_color[i].g * m_diffuse_brightness[i] * 0.5f);\r\n\t\t\tint difb = (int)((float)m_diffuse_color[i].b * m_diffuse_brightness[i] * 0.5f);\r\n\t\t\tNxNgc::EngineGlobals.diffuse_light_color[i].r = difr > 255 ? 255 : (u8)difr;\r\n\t\t\tNxNgc::EngineGlobals.diffuse_light_color[i].g = difg > 255 ? 255 : (u8)difg;\r\n\t\t\tNxNgc::EngineGlobals.diffuse_light_color[i].b = difb > 255 ? 255 : (u8)difb;\r\n\r\n\t\t\t// Use the local direction.\r\n\t\t\tm_diffuse_direction[i].Normalize();\r\n\t\t\tNxNgc::EngineGlobals.light_x[i] = m_diffuse_direction[i][X] * 200000.0f;\r\n\t\t\tNxNgc::EngineGlobals.light_y[i] = m_diffuse_direction[i][Y] * 200000.0f;\r\n\t\t\tNxNgc::EngineGlobals.light_z[i] = m_diffuse_direction[i][Z] * 200000.0f;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Use the default directional color, but modulate it with the local directional brightness.\r\n\t\t\tImage::RGBA\tdif = CLightManager::sGetLightDiffuseColor( i );\r\n\t\t\tint difr = (int)((float)dif.r * m_diffuse_brightness[i] * 0.5f);\r\n\t\t\tint difg = (int)((float)dif.g * m_diffuse_brightness[i] * 0.5f);\r\n\t\t\tint difb = (int)((float)dif.b * m_diffuse_brightness[i] * 0.5f);\r\n\t\t\tNxNgc::EngineGlobals.diffuse_light_color[i].r = difr > 255 ? 255 : (u8)difr;\r\n\t\t\tNxNgc::EngineGlobals.diffuse_light_color[i].g = difg > 255 ? 255 : (u8)difg;\r\n\t\t\tNxNgc::EngineGlobals.diffuse_light_color[i].b = difb > 255 ? 255 : (u8)difb;\r\n\r\n\t\t\t// Use the default direction.\r\n\t\t\tMth::Vector dir = CLightManager::sGetLightDirection( i );\r\n\t\t\tdir.Normalize();\r\n\t\t\tNxNgc::EngineGlobals.light_x[i] = dir[X] * 200000.0f;\r\n\t\t\tNxNgc::EngineGlobals.light_y[i] = dir[Y] * 200000.0f;\r\n\t\t\tNxNgc::EngineGlobals.light_z[i] = dir[Z] * 200000.0f;\r\n\t\t}\r\n//\t\tNxNgc::EngineGlobals.diffuse_light_color[i].r = NxNgc::EngineGlobals.diffuse_light_color[i].r < 128 ? NxNgc::EngineGlobals.diffuse_light_color[i].r * 2 : 255;\r\n//\t\tNxNgc::EngineGlobals.diffuse_light_color[i].g = NxNgc::EngineGlobals.diffuse_light_color[i].g < 128 ? NxNgc::EngineGlobals.diffuse_light_color[i].g * 2 : 255;\r\n//\t\tNxNgc::EngineGlobals.diffuse_light_color[i].b = NxNgc::EngineGlobals.diffuse_light_color[i].b < 128 ? NxNgc::EngineGlobals.diffuse_light_color[i].b * 2 : 255;\r\n\t}\r\n\r\n\tif( add_scene_light )\r\n\t{\r\n\t\tNx::CSceneLight *p_scene_light = CLightManager::sGetOptimumSceneLight( pos );\r\n\t\tif( p_scene_light )\r\n\t\t{\r\n\t\t\tMth::Vector light_pos = p_scene_light->GetLightPosition();\r\n\r\n\t\t\tfloat dist\t= Mth::Distance( pos, light_pos );\r\n\t\t\tfloat ratio\t= dist * p_scene_light->GetLightReciprocalRadius();\r\n\r\n\t\t\tlight_pos = ( pos - light_pos ).Normalize();\r\n\r\n\t\t\t// Figure the direction...\r\n\t\t\tNxNgc::EngineGlobals.light_x[2] = -light_pos[X] * 200000.0f;\r\n\t\t\tNxNgc::EngineGlobals.light_y[2] = -light_pos[Y] * 200000.0f;\r\n\t\t\tNxNgc::EngineGlobals.light_z[2] = -light_pos[Z] * 200000.0f;\r\n\r\n\t\t\t// ...and the color.\r\n\t\t\tratio = sqrtf( 1.0f - ratio ) * p_scene_light->GetLightIntensity();\r\n\t\t\tint difr = (int)((float)p_scene_light->GetLightColor().r * ratio * 0.5f);\r\n\t\t\tint difg = (int)((float)p_scene_light->GetLightColor().g * ratio * 0.5f);\r\n\t\t\tint difb = (int)((float)p_scene_light->GetLightColor().b * ratio * 0.5f);\r\n\t\t\tNxNgc::EngineGlobals.diffuse_light_color[2].r\t= difr > 255 ? 255 : (u8)difr;\r\n\t\t\tNxNgc::EngineGlobals.diffuse_light_color[2].g\t= difg > 255 ? 255 : (u8)difg;\r\n\t\t\tNxNgc::EngineGlobals.diffuse_light_color[2].b\t= difb > 255 ? 255 : (u8)difb;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Disbale this light by setting zero color.\r\n\t\t\tNxNgc::EngineGlobals.diffuse_light_color[2].r = 0;\r\n\t\t\tNxNgc::EngineGlobals.diffuse_light_color[2].g = 0;\r\n\t\t\tNxNgc::EngineGlobals.diffuse_light_color[2].b = 0;\r\n\t\t}\r\n\t}\r\n\r\n//\t// Set lighting.\r\n//\tGXLightObj light_obj[2];\r\n//\r\n//\tGX::SetChanAmbColor( GX_COLOR0A0, NxNgc::EngineGlobals.ambient_light_color );\r\n//\tGX::SetChanAmbColor( GX_COLOR1A1, NxNgc::EngineGlobals.ambient_light_color );\r\n//\r\n//\tGXInitLightColor( &light_obj[0], NxNgc::EngineGlobals.diffuse_light_color[0] );\r\n//\tGXInitLightPos( &light_obj[0], NxNgc::EngineGlobals.light_x[0], NxNgc::EngineGlobals.light_y[0], NxNgc::EngineGlobals.light_z[0] );\r\n//\tGXLoadLightObjImm( &light_obj[0], GX_LIGHT0 );\r\n//\r\n//\tGXInitLightColor( &light_obj[1], NxNgc::EngineGlobals.diffuse_light_color[1] );\r\n//\tGXInitLightPos( &light_obj[1], NxNgc::EngineGlobals.light_x[1], NxNgc::EngineGlobals.light_y[1], NxNgc::EngineGlobals.light_z[1] );\r\n//\tGXLoadLightObjImm( &light_obj[1], GX_LIGHT1 );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcModelLights::plat_set_light_ambient_color( const Image::RGBA &rgba )\r\n{\r\n\tm_ambient_color = rgba;\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nImage::RGBA\tCNgcModelLights::plat_get_light_ambient_color() const\r\n{\r\n\treturn m_ambient_color;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcModelLights::plat_set_light_direction( int light_index, const Mth::Vector &direction )\r\n{\r\n\tm_diffuse_direction[light_index] = direction;\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::Vector &\tCNgcModelLights::plat_get_light_direction( int light_index ) const\r\n{\r\n\tif( plat_is_diffuse_light_enabled( light_index ))\r\n\t\treturn m_diffuse_direction[light_index];\r\n\telse\r\n\t\treturn Nx::CLightManager::sGetLightDirection( light_index );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcModelLights::plat_set_light_diffuse_color( int light_index, const Image::RGBA &rgba )\r\n{\r\n\tm_diffuse_color[light_index] = rgba;\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nImage::RGBA\tCNgcModelLights::plat_get_light_diffuse_color( int light_index ) const\r\n{\r\n\treturn m_diffuse_color[light_index];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcModelLights::plat_enable_ambient_light( bool enable )\r\n{\r\n\tif( enable )\r\n\t\tm_flags |= mUSE_MODEL_AMBIENT;\r\n\telse\r\n\t\tm_flags &= ~mUSE_MODEL_AMBIENT;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcModelLights::plat_enable_diffuse_light( int light_index, bool enable )\r\n{\r\n\tif( enable )\r\n\t\tm_flags |= ( light_index == 0 ) ? mUSE_MODEL_DIFFUSE_0 : mUSE_MODEL_DIFFUSE_1;\r\n\telse\r\n\t\tm_flags &= ~(( light_index == 0 ) ? mUSE_MODEL_DIFFUSE_0 : mUSE_MODEL_DIFFUSE_1 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcModelLights::plat_is_ambient_light_enabled() const\r\n{\r\n\treturn ( m_flags & mUSE_MODEL_AMBIENT ) > 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcModelLights::plat_is_diffuse_light_enabled( int light_index ) const\r\n{\r\n\treturn (( light_index == 0 ) ? (( m_flags & mUSE_MODEL_DIFFUSE_0 ) > 0 ) : (( m_flags & mUSE_MODEL_DIFFUSE_1 ) > 0 ));\r\n}\r\n\r\n} \r\n \r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxlight.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// p_NxLight.H - Neversoft Engine, Rendering portion, Platform dependent interface\r\n\r\n#ifndef\t__GFX_P_NX_LIGHT_H__\r\n#define\t__GFX_P_NX_LIGHT_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/math.h>\r\n#include <gfx/image/imagebasic.h>\r\n#include <gfx/nxlight.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// Nx::CNgcModelLights\r\nclass\tCNgcModelLights : public CModelLights\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCNgcModelLights();\r\n\tvirtual\t\t\t\t\t\t~CNgcModelLights();\r\n\r\nprivate:\t\r\n\r\n\t// Platform-specific calls\r\n\tvirtual void\t\t\t\tplat_update_engine( Mth::Vector & pos, bool add_scene_light );\r\n\tvirtual bool\t\t\t\tplat_set_light_ambient_color(const Image::RGBA &rgba);\r\n\tvirtual bool\t\t\t\tplat_set_light_direction(int light_index, const Mth::Vector &direction);\r\n\tvirtual bool\t\t\t\tplat_set_light_diffuse_color(int light_index, const Image::RGBA &rgba);\r\n\tvirtual Image::RGBA\t\t\tplat_get_light_ambient_color() const;\r\n\tvirtual const Mth::Vector &\tplat_get_light_direction(int light_index) const;\r\n\tvirtual Image::RGBA\t\t\tplat_get_light_diffuse_color(int light_index) const;\r\n\r\n\tvirtual void\t\t\t\tplat_update_brightness();\r\n\r\n\tvirtual void\t\t\t\tplat_enable_ambient_light(bool enable);\r\n\tvirtual void\t\t\t\tplat_enable_diffuse_light(int light_index, bool enable);\r\n\tvirtual bool\t\t\t\tplat_is_ambient_light_enabled() const;\r\n\tvirtual bool\t\t\t\tplat_is_diffuse_light_enabled(int light_index) const;\r\n\r\n\tuint32\t\t\t\t\t\tm_flags;\r\n\tImage::RGBA\t\t\t\t\tm_ambient_color;\r\n\tImage::RGBA\t\t\t\t\tm_diffuse_color[CLightManager::MAX_LIGHTS];\r\n\tMth::Vector\t\t\t\t\tm_diffuse_direction[CLightManager::MAX_LIGHTS];\r\n};\r\n\r\n\r\n}\r\n\r\n\r\n#endif\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxloadscreen.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxLoadScreen.cpp - PS2 platform specific interface for the load screen\r\n//\r\n// This is PS2 SPECIFIC!!!!!!  So might get a bit messy\r\n//\r\n\r\n#include\t\"gfx\\Nx.h\"\r\n#include\t\"gfx\\NxLoadScreen.h\"\r\n#include\t\"gfx\\ngc\\p_NxTexture.h\"\r\n#include\t\"gfx\\ngc\\p_NxSprite.h\"\r\n#include\t\"gfx\\ngc\\NX\\sprite.h\"\r\n#include\t\"gfx\\ngc\\NX\\render.h\"\r\n#include <sys/file/filesys.h>\r\n\r\n#include\t\"core\\macros.h\"\r\n#include\t\"sys/config/config.h\"\r\n\r\n#include <sys/ngc/p_prim.h>\r\n#include <sys/ngc/p_camera.h>\r\n#include <sys/ngc/p_render.h>\r\n#include <sys/ngc/p_display.h>\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include\t<sys/ngc\\p_dvd.h>\r\n#include <sys/File/PRE.h>\r\n\r\nbool\t\tgReload = false;\r\nbool\t\tgLoadingLoadScreen = false;\r\nbool\t\tgLoadingBarActive = false;\r\nbool\t\tgLoadingScreenActive = false;\r\nint\t\t\tgLoadBarTotalFrames;\t\t// Number of frames it takes for loading bar to go to 100%\r\nint\t\t\tgLoadBarNumFrames;\t\t\t// Number of frames so far\r\nint\t\t\tgLoadBarX = 150;\t\t\t// Bar position\r\nint\t\t\tgLoadBarY = 400;\r\nint\t\t\tgLoadBarWidth = 340;\t\t// Bar size\r\nint\t\t\tgLoadBarHeight = 20;\r\nint\t\t\tgLoadBarStartColor[4] = {  255,    0,   0,  128 };\r\nint\t\t\tgLoadBarDeltaColor[4] = { -255,  255,   0,  128 };\r\nint\t\t\tgLoadBarBorderWidth = 5;\t// Border width\r\nint\t\t\tgLoadBarBorderHeight = 5;\t// Border height\r\nint\t\t\tgLoadBarBorderColor[4] = {  40, 40, 40, 128 };\r\n\r\n//static bool\t\t\t\ts_loading_screen_on\t\t= false;\r\nstatic OSThread\t\t\ts_load_icon_thread;\r\nstatic OSAlarm\t\t\ts_alarm;\r\n//static LoadingIconData\ts_load_icon_data\t\t= { 0 };\r\n//static char\t\t\t\ts_load_icon_thread_stack[4096]\t__attribute__ (( aligned( 16 )));\r\nstatic volatile bool\ts_terminate_thread\t\t= false;\r\nstatic volatile bool\ts_terminate_thread_done\t= false;\r\nbool\t\t\t\ts_thread_exists\t\t\t= false;\r\n\r\nextern char * g_p_buffer;\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\nNx::CNgcTexture\t*sp_load_screen_texture;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid s_thread_loading_icon_alarm_handler( OSAlarm* alarm, OSContext* context )\r\n{\r\n\t// Check the thread has not been resumed yet...\r\n\tif( OSIsThreadSuspended( &s_load_icon_thread ))\r\n\t{\r\n\t\tOSResumeThread( &s_load_icon_thread );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid* s_threaded_loading_icon( void* data )\r\n{\r\n\twhile( 1 )\r\n\t{\r\n\t\tif( s_terminate_thread )\r\n\t\t{\r\n\t\t\t// This thread is done...\r\n\t\t\ts_terminate_thread_done\t= true;\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\r\n\t\tgLoadBarNumFrames++;\r\n\r\n\t\tbool busy = NxNgc::EngineGlobals.gpuBusy;\r\n\r\n//\t\t// Don't want to do draw anything whilst display lists are being built. Come back in a bit.\r\n//\t\tif( !busy )\r\n\t\t{\r\n//\t\t\tNsTexture* p_texture = p_data->m_Rasters[current_image];\r\n\r\n//\t\t\tNsDisplay::begin();\r\n//\t\t\tNsRender::begin();\r\n//\t\t\tNsPrim::begin();\r\n//\r\n////\t\t    GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\t\t// 3 = positions & uvs.\r\n////\t\t\tGXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n////\r\n//\t\t\tNsCamera camera2D;\r\n//\t\t\tcamera2D.orthographic( 0, 0, 640, 448 );\r\n//\r\n//\t\t\tcamera2D.begin();\r\n//\r\n////\t\t\tNsRender::setBlendMode( NsBlendMode_None, NULL, (unsigned char)0 );\r\n////\r\n////\t\t\tGXClearVtxDesc();\r\n////\t\t\tGXSetVtxDesc( GX_VA_POS, GX_DIRECT );\r\n////\t\t\tGXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );\r\n////\t\t\tGX::SetChanMatColor( GX_COLOR0, (GXColor){ 128,128,128,128 });\r\n////\t\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n////\r\n////\t\t\tp_texture->upload( NsTexture_Wrap_Clamp );\r\n////\r\n////\t\t\tGXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n////\t\t\tGXPosition3f32((float)p_data->m_X, (float)p_data->m_Y, -1.0f );\r\n////\t\t\tGXTexCoord2f32( 0.0f, 0.0f );\r\n////\t\t\tGXPosition3f32((float)p_data->m_X + (float)p_texture->m_width, (float)p_data->m_Y, -1.0f );\r\n////\t\t\tGXTexCoord2f32( 1.0f, 0.0f );\r\n////\t\t\tGXPosition3f32((float)p_data->m_X + (float)p_texture->m_width, (float)p_data->m_Y + (float)p_texture->m_height, -1.0f );\r\n////\t\t\tGXTexCoord2f32( 1.0f, 1.0f );\r\n////\t\t\tGXPosition3f32((float)p_data->m_X, (float)p_data->m_Y + (float)p_texture->m_height, -1.0f );\r\n////\t\t\tGXTexCoord2f32( 0.0f, 1.0f );\r\n////\t\t\tGXEnd();\r\n//\r\n//\t\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);\r\n//\t\t\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t\tGX::SetNumTexGens( 0 );\r\n//\t\t\tGX::SetNumTevStages( 1 );\r\n//\t\t\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );\r\n//\t\t\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_RASA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\t\t\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n//\r\n//\t\t\t// Set current vertex descriptor to enable position and color0.\r\n//\t\t\t// Both use 8b index to access their data arrays.\r\n//\t\t\tGXClearVtxDesc();\r\n//\t\t\tGXSetVtxDesc( GX_VA_POS, GX_DIRECT );\r\n//\t\t\tGXSetVtxDesc( GX_VA_CLR0, GX_DIRECT );\r\n//\r\n//\t\t\t// Set material color.\r\n//\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\r\n//\t\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\r\n//\t\t\tGX::SetCullMode ( GX_CULL_NONE );\r\n//\r\n//\t\t\tint cur_width = (gLoadBarWidth - 1);\r\n//\t\t\tif (gLoadBarNumFrames < gLoadBarTotalFrames)\r\n//\t\t\t{\r\n//\t\t\t\tcur_width = (cur_width * gLoadBarNumFrames) / gLoadBarTotalFrames;\r\n//\t\t\t}\r\n//\r\n//\t\t\tint x1 = gLoadBarX;\r\n//\t\t\tint y1 = gLoadBarY;\r\n//\t\t\tint x2 = x1 + cur_width;\r\n//\t\t\tint y2 = y1 + (gLoadBarHeight - 1);\r\n//\r\n//\t\t\tint end_color[4];\r\n//\t\t\tif (gLoadBarNumFrames < gLoadBarTotalFrames)\r\n//\t\t\t{\r\n//\t\t\t\tend_color[0] = gLoadBarStartColor[0] + ((gLoadBarDeltaColor[0] * gLoadBarNumFrames) / gLoadBarTotalFrames);\r\n//\t\t\t\tend_color[1] = gLoadBarStartColor[1] + ((gLoadBarDeltaColor[1] * gLoadBarNumFrames) / gLoadBarTotalFrames);\r\n//\t\t\t\tend_color[2] = gLoadBarStartColor[2] + ((gLoadBarDeltaColor[2] * gLoadBarNumFrames) / gLoadBarTotalFrames);\r\n//\t\t\t\tend_color[3] = gLoadBarStartColor[3] + ((gLoadBarDeltaColor[3] * gLoadBarNumFrames) / gLoadBarTotalFrames);\r\n//\t\t\t} else {\r\n//\t\t\t\tend_color[0] = gLoadBarStartColor[0] + gLoadBarDeltaColor[0];\r\n//\t\t\t\tend_color[1] = gLoadBarStartColor[1] + gLoadBarDeltaColor[1];\r\n//\t\t\t\tend_color[2] = gLoadBarStartColor[2] + gLoadBarDeltaColor[2];\r\n//\t\t\t\tend_color[3] = gLoadBarStartColor[3] + gLoadBarDeltaColor[3];\r\n//\t\t\t}\r\n//\r\n//\t\t\tint border_x1 = x1 - gLoadBarBorderWidth;\r\n//\t\t\tint border_y1 = y1 - gLoadBarBorderHeight;\r\n//\t\t\tint border_x2 = x1 + (gLoadBarWidth - 1) + gLoadBarBorderWidth;\r\n//\t\t\tint border_y2 = y2 + gLoadBarBorderHeight;\r\n//\r\n//\t\t\tu32 bc = gLoadBarBorderColor[3]|(gLoadBarBorderColor[2]<<8)|(gLoadBarBorderColor[1]<<16)|(gLoadBarBorderColor[0]<<24);\r\n//\t\t\tu32 sc = gLoadBarStartColor[3]|(gLoadBarStartColor[2]<<8)|(gLoadBarStartColor[1]<<16)|(gLoadBarStartColor[0]<<24); \r\n//\t\t\tu32 ec = end_color[3]|(end_color[2]<<8)|(end_color[1]<<16)|(end_color[0]<<24);\r\n//\r\n//\t\t\t// Border\r\n//\t\t\tGXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t\t\t\tGXPosition3f32(border_x1, border_y1, -1.0f);\r\n//\t\t\t\tGXColor1u32( bc );\r\n//\t\t\t\tGXPosition3f32(border_x1, border_y2, -1.0f);\r\n//\t\t\t\tGXColor1u32( bc );\r\n//\t\t\t\tGXPosition3f32(border_x2, border_y2, -1.0f);\r\n//\t\t\t\tGXColor1u32( bc );\r\n//\t\t\t\tGXPosition3f32(border_x2, border_y1, -1.0f);\r\n//\t\t\t\tGXColor1u32( bc );\r\n//\t\t\tGXEnd();\r\n//\t\t\t\r\n//\t\t\t// Bar\r\n//\t\t\tGXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t\t\t\tGXPosition3f32(x1, y1, -1.0f);\r\n//\t\t\t\tGXColor1u32( sc );\r\n//\t\t\t\tGXPosition3f32(x1, y2, -1.0f);\r\n//\t\t\t\tGXColor1u32( sc );\r\n//\t\t\t\tGXPosition3f32(x2, y2, -1.0f);\r\n//\t\t\t\tGXColor1u32( ec );\r\n//\t\t\t\tGXPosition3f32(x2, y1, -1.0f);\r\n//\t\t\t\tGXColor1u32( ec );\r\n//\t\t\tGXEnd();\r\n//\r\n//\t\t\tcamera2D.end();\r\n//\r\n//\t\t\tNsPrim::end();\r\n//\t\t\tNsRender::end();\r\n//\t\t\tNsDisplay::end( false );\r\n//\r\n////\t\t\tcurrent_image = ( current_image + 1 ) % p_data->m_NumFrames ;\r\n\t\t}\r\n\r\n\t\t// Go to sleep.\r\n\t\tif( busy )\r\n\t\t{\r\n\t\t\t// Come back shortly.\r\n\t\t\tOSSetAlarm( &s_alarm, OSMillisecondsToTicks( 500 ), s_thread_loading_icon_alarm_handler );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Come back in the proper time.\r\n\t\t\tOSSetAlarm( &s_alarm, OSMillisecondsToTicks( (long long int)( 1000.0f / 60.0f ) ), s_thread_loading_icon_alarm_handler );\r\n\t\t}\r\n\r\n\t\tOSSuspendThread( &s_load_icon_thread );\r\n\t}\r\n}\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n#define USE_SPRITES 0\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::s_plat_display(const char* filename, bool just_freeze, bool blank)\r\n{\r\n\t// See if we need to just flag that a loading screen is active to disable draws.\r\n\tif ( just_freeze )\r\n\t{\r\n\t\tgLoadingScreenActive = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// See if we need to clear the screen to black.\r\n\tif ( blank )\r\n\t{\r\n\t\tfor ( int lp = 0; lp < 2; lp++ )\r\n\t\t{\r\n\t\t\tNsDisplay::begin();\r\n\t\t\tNsRender::begin();\r\n\t\t\tNsRender::end();\r\n\t\t\tNsDisplay::end();\r\n\t\t}\r\n\r\n\t\tgLoadingScreenActive = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tNxNgc::EngineGlobals.gpuBusy = true;\r\n\r\n\tchar name[256];\r\n\tchar pre[256];\r\n\r\n\tFile::PreMgr* pre_mgr = File::PreMgr::Instance();\r\n\r\n\t// Hmm seems we need to prepend 'images\\\\' to the start of this string...\r\n\tstrcpy( name, \"images\\\\\" );\r\n\tswitch( Config::GetLanguage())\r\n\t{\r\n\t\tcase Config::LANGUAGE_GERMAN:\r\n\t\t\tstrcpy( pre, filename );\r\n\t\t\tstrcat( pre, \".prd\" );\r\n\t\t\tpre_mgr->LoadPre( pre, false );\r\n\t\t\tstrcat( name, \"grimages_ngc\\\\\" );\r\n\t\t\tbreak;\r\n\t\tcase Config::LANGUAGE_FRENCH:\r\n\t\t\tstrcpy( pre, filename );\r\n\t\t\tstrcat( pre, \".prf\" );\r\n\t\t\tpre_mgr->LoadPre( pre, false );\r\n\t\t\tstrcat( name, \"frimages_ngc\\\\\" );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\tstrcat( name, filename );\r\n\t\r\n\t// ...and append '.img.ngc' to the end.\r\n\tstrcat( name, \".img.ngc\" );\r\n\t\r\n\t// Load the texture a few lines at a time & render to the display.\r\n\tgLoadingLoadScreen = true;\r\n\tvoid *p_FH = File::Open( name, \"rb\" );\r\n\r\n\tif( p_FH )\r\n\t{\r\n\t\tuint32 version;\r\n\t\tuint32 checksum;\r\n\t\tuint32 width;\r\n\t\tuint32 height;\r\n\t\tuint32 depth;\r\n\t\tuint32 levels;\r\n\t\tuint32 rwidth;\r\n\t\tuint32 rheight;\r\n\t\tuint16 alphamap;\r\n\t\tuint16 hasholes;\r\n\r\n\t\t// Load the actual texture\r\n\r\n\t\tFile::Read( &version,  4, 1, p_FH );\r\n\t\tFile::Read( &checksum, 4, 1, p_FH );\r\n\t\tFile::Read( &width,    4, 1, p_FH );\r\n\t\tFile::Read( &height,   4, 1, p_FH );\r\n\t\tFile::Read( &depth,    4, 1, p_FH );\r\n\t\tFile::Read( &levels,   4, 1, p_FH );\r\n\t\tFile::Read( &rwidth,   4, 1, p_FH );\r\n\t\tFile::Read( &rheight,  4, 1, p_FH );\r\n\t\tFile::Read( &alphamap, 2, 1, p_FH );\r\n\t\tFile::Read( &hasholes, 2, 1, p_FH );\r\n\r\n//\t\tDbg_MsgAssert( version <= TEXTURE_VERSION, (\"Illegal texture version number: %d (The newest version we deal with is: %d)\\n\", version, TEXTURE_VERSION ));\r\n\t\tDbg_MsgAssert( depth == 32, (\"We only deal with 32-bit textures.\\n\"));\r\n\r\n#define LINES 16\r\n\r\n\t\t// Load in 8 line chunks.\r\n//\t\tuint16 temp_buffer[width*LINES*2];\r\n//\t\tuint32 tex_buffer[width*LINES];\r\n\r\n\t\tuint16 * temp_buffer = (uint16 *)g_p_buffer;\r\n\t\tuint32 * tex_buffer = (uint32 *)&temp_buffer[width*LINES*2];\r\n\r\n\t\tNsDisplay::begin();\r\n\t\tNsRender::begin();\r\n\r\n\t\tGX::PokeColorUpdate( GX_TRUE );\r\n\t\tGX::PokeAlphaUpdate( GX_FALSE );\r\n\t\tuint yy = 0;\r\n\t\twhile ( yy < height )\r\n\t\t{\r\n\t\t\tint lines = ( height - yy ) > LINES ? LINES : ( height - yy );\r\n\r\n\t\t\tFile::Read( temp_buffer, width * 4 * lines, 1, p_FH );\r\n\r\n\t\t\tif ( gReload )\r\n\t\t\t{\r\n\t\t\t\tgReload = false;\r\n\t\t\t\tyy = 0;\r\n\t\t\t\tFile::Close( p_FH );\r\n\t\t\t\tvoid *p_FH = File::Open( name, \"rb\" );\r\n\t\t\t\tFile::Read( &version,  4, 1, p_FH );\r\n\t\t\t\tFile::Read( &checksum, 4, 1, p_FH );\r\n\t\t\t\tFile::Read( &width,    4, 1, p_FH );\r\n\t\t\t\tFile::Read( &height,   4, 1, p_FH );\r\n\t\t\t\tFile::Read( &depth,    4, 1, p_FH );\r\n\t\t\t\tFile::Read( &levels,   4, 1, p_FH );\r\n\t\t\t\tFile::Read( &rwidth,   4, 1, p_FH );\r\n\t\t\t\tFile::Read( &rheight,  4, 1, p_FH );\r\n\t\t\t\tFile::Read( &alphamap, 2, 1, p_FH );\r\n\t\t\t\tFile::Read( &hasholes, 2, 1, p_FH );\r\n\t\t\t\tNsDisplay::begin();\r\n\t\t\t\tNsRender::begin();\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// Need to swizzle data we just read.\r\n\t\t\tfor ( int lp = 0; lp < lines; lp += 4 )\r\n\t\t\t{\r\n\t\t\t\tint xx = lp * width;\r\n\t\t\t\tfor ( uint lp2 = 0; lp2 < width; lp2 += 4 )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int lp3 = 0; lp3 < 16; lp3++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tuint16 p0 = temp_buffer[lp3+(lp2*8)+(xx*2)];\r\n\t\t\t\t\t\tuint16 p1 = temp_buffer[16+lp3+(lp2*8)+(xx*2)];\r\n\t\t\t\t\t\ttex_buffer[(lp3&3)+(width*(lp3>>2))+lp2+xx] =\t( ( p0 << 16 ) & 0xff000000 ) |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( ( p0 << 16 ) & 0x00ff0000 ) | \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( ( p1 <<  0 ) & 0x0000ff00 ) | \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( ( p1 <<  0 ) & 0x000000ff );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tfor ( int yp = 0; yp < lines; yp++ )\r\n\t\t\t{\r\n\t\t\t\tuint y_pos = ( ( height - 1 ) - ( yy + yp ) );\r\n\t\t\t\tfor ( uint xp = 0; xp < width; xp++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tGX::PokeARGB( xp, y_pos, tex_buffer[(width*yp)+xp] );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tyy += lines;\r\n\t\t}\r\n\t\tNsRender::end();\r\n\t\tNsDisplay::end(false);\r\n\r\n\t\tFile::Close( p_FH );\r\n\t}\r\n\tgLoadingLoadScreen = false;\r\n\r\n\tswitch( Config::GetLanguage())\r\n\t{\r\n\t\tcase Config::LANGUAGE_GERMAN:\r\n\t\tcase Config::LANGUAGE_FRENCH:\r\n\t\t\tpre_mgr->UnloadPre( pre );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n//\tNsDisplay::flush();\r\n\r\n\tNxNgc::EngineGlobals.gpuBusy = false;\r\n\r\n\tgLoadingScreenActive = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::s_plat_hide()\r\n{\r\n\tif( s_thread_exists )\r\n\t{\r\n\t\ts_terminate_thread_done\t= false;\r\n\t\ts_terminate_thread = true;\r\n\r\n\t\t// Cancel the alarm and resume the thread.\r\n//\t\tOSCancelAlarm( &s_alarm );\r\n//\t\tOSResumeThread( &s_load_icon_thread );\r\n\r\n\t\twhile( !s_terminate_thread_done );\r\n\r\n\t\ts_thread_exists = false;\r\n//\t\tpIconCallback = NULL;\r\n\r\n\t\t//VISetBlack( TRUE );\r\n\t\t//VIFlush();\r\n\t\t//VIWaitForRetrace();\r\n\t\t//NsDisplay::flush();\r\n\t\t//VISetBlack( FALSE );\r\n\t\t//VIFlush();\r\n\t\t//VIWaitForRetrace();\r\n\t}\r\n\r\n//#if !USE_SPRITES\r\n//\tNxPs2::EnableFlipCopy(true);\r\n//#endif // USE_SPRITES\r\n\tgLoadingBarActive = false;\r\n\tgLoadingScreenActive = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::s_plat_clear()\r\n{\r\n//\tif (sp_load_screen_sprite)\r\n//\t{\r\n//\t\tCEngine::sDestroySprite(sp_load_screen_sprite);\r\n//\t\tsp_load_screen_sprite = NULL;\r\n//\t}\r\n//\r\n//\tif (sp_load_screen_texture)\r\n//\t{\r\n//\t\tdelete sp_load_screen_texture;\r\n//\t\tsp_load_screen_texture = NULL;\r\n//\t}\r\n\tgLoadingBarActive = false;\r\n\tgLoadingScreenActive = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::s_plat_start_loading_bar(float seconds)\r\n{\r\n//\tNsDisplay::flush();\r\n\r\n\tgLoadBarTotalFrames = (int) (seconds * 1.15f * Config::FPS());\r\n\tgLoadBarNumFrames = 0;\r\n\r\n//\r\n////\tNxPs2::StartLoadingBar((int) (seconds * Config::FPS()));\r\n//\r\n//\t// Start the thread to display the animated loading icon.\r\n////\tpIconCallback = s_non_threaded_loading_icon;\r\n//\tBOOL rv = true;\r\n//\r\n//\ts_terminate_thread = false;\r\n//\r\n//\tmemset( &s_load_icon_thread, 0, sizeof( OSThread ));\r\n//\trv = OSCreateThread(\t&s_load_icon_thread,\r\n//\t\t\t\t\t\t\ts_threaded_loading_icon,\t\t\t\t\t\t\t\t\t\t// Entry function.\r\n//\t\t\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Argument for start function.\r\n//\t\t\t\t\t\t\ts_load_icon_thread_stack + sizeof( s_load_icon_thread_stack ),\t// Stack base (stack grows down).\r\n//\t\t\t\t\t\t\tsizeof( s_load_icon_thread_stack ),\t\t\t\t\t\t\t\t// Stack size in bytes.\r\n//\t\t\t\t\t\t\t1,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Thread priority.\r\n//\t\t\t\t\t\t\tOS_THREAD_ATTR_DETACH  );\t\t\t\t\t\t\t\t\t\t// Thread attributes.\r\n//\tDbg_MsgAssert( rv, ( \"Failed to create thread\" ));\r\n//\r\n//\tif( rv )\r\n//\t{\r\n//\t\ts_thread_exists = true;\r\n////\t\tOSResumeThread( &s_load_icon_thread );\r\n//\t\tOSSetAlarm( &s_alarm, OSMillisecondsToTicks( (long long int)( 1000.0f / 60.0f ) ), s_thread_loading_icon_alarm_handler );\r\n//\t}\r\n\tgLoadingBarActive = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::s_plat_update_bar_properties()\r\n{\r\n\t// Bar size and position\r\n\tgLoadBarX = s_bar_x;\r\n\tgLoadBarY = s_bar_y;\r\n\tgLoadBarWidth = s_bar_width;\r\n\tgLoadBarHeight = s_bar_height;\r\n\r\n\t// Bar colors\r\n\tgLoadBarStartColor[0] = s_bar_start_color.r;\r\n\tgLoadBarStartColor[1] = s_bar_start_color.g;\r\n\tgLoadBarStartColor[2] = s_bar_start_color.b;\r\n\tgLoadBarStartColor[3] = s_bar_start_color.a;\r\n\tgLoadBarDeltaColor[0] = (int) s_bar_end_color.r - gLoadBarStartColor[0];\r\n\tgLoadBarDeltaColor[1] = (int) s_bar_end_color.g - gLoadBarStartColor[1];\r\n\tgLoadBarDeltaColor[2] = (int) s_bar_end_color.b - gLoadBarStartColor[2];\r\n\tgLoadBarDeltaColor[3] = (int) s_bar_end_color.a - gLoadBarStartColor[3];\r\n\r\n\t// Border size\r\n\tgLoadBarBorderWidth = s_bar_border_width;\r\n\tgLoadBarBorderHeight = s_bar_border_height;\r\n\r\n\t// Border color\r\n\tgLoadBarBorderColor[0] = s_bar_border_color.r;\r\n\tgLoadBarBorderColor[1] = s_bar_border_color.g;\r\n\tgLoadBarBorderColor[2] = s_bar_border_color.b;\r\n\tgLoadBarBorderColor[3] = s_bar_border_color.a;\r\n}\r\n\r\n} \r\n \r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxmiscfx.cpp",
    "content": "#include <core/defines.h>\r\n\r\n#include <gel/collision/collision.h>\r\n#include <gel/collision/colltridata.h>\r\n#include <gel/collision/movcollman.h>\r\n#include <gel/collision/batchtricoll.h>\r\n#include <engine/SuperSector.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/nxtexman.h>\r\n#include <gfx/debuggfx.h>\r\n#include <gfx/NxViewMan.h>\r\n#include <gfx/NxMiscFX.h>\r\n\r\n#include <gfx/Ngc/p_nxgeom.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n\r\n#include <gfx/Ngc/nx/render.h>\r\n\r\n#include <sys/ngc/p_prim.h>\r\n#include <sys/ngc/p_gx.h>\r\n#include \"dolphin/base/ppcwgpipe.h\"\r\n#include \"dolphin/gx/gxvert.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n#define\tDRAW_DEBUG_LINES\t\t0\r\n\r\n#\tif DRAW_DEBUG_LINES\r\nstatic float debugpos[10240*6];\r\nstatic GXColor debugcol[10240];\r\nstatic int nLines = 0;\r\n#\tendif\t\t// DRAW_DEBUG_LINES\r\n\r\n#define ADD_LINE(_s,_e,_r,_g,_b) {\tdebugpos[(nLines*6)+0] = _s[X];\t\\\r\n\t\t\t\t\t\t\t\t\tdebugpos[(nLines*6)+1] = _s[Y];    \\\r\n\t\t\t\t\t\t\t\t\tdebugpos[(nLines*6)+2] = _s[Z];    \\\r\n\t\t\t\t\t\t\t\t\tdebugpos[(nLines*6)+3] = _e[X];    \\\r\n\t\t\t\t\t\t\t\t\tdebugpos[(nLines*6)+4] = _e[Y];    \\\r\n\t\t\t\t\t\t\t\t\tdebugpos[(nLines*6)+5] = _e[Z];    \\\r\n\t\t\t\t\t\t\t\t\tdebugcol[nLines] = (GXColor){_r,_g,_b,255};\t\t\t\\\r\n\t\t\t\t\t\t\t\t\tnLines++; }\t\t\t\t\t\t\t\\\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sNgcScreenFlashVert\r\n{\r\n\tfloat\t\tx, y, z;\r\n\tGXColor\t\tcol;\r\n\tfloat\t\tu, v;\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sNgcVert\r\n{\r\n\tMth::Vector\t\tpos;\r\n\tGXColor\t\t\tcol;\r\n\ts16\t\t\t\tu, v;\r\n};\r\n\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#if 0\r\nstruct sNgcSplatInstanceDetails : public sSplatInstanceDetails\r\n{\r\n\t// Platform specific part.\r\n\tNxNgc::CInstance\t*mp_instance;\r\n//\tNxNgc::sMaterialHeader\t\tm_mat;\r\n//\tNxNgc::sMaterialPassHeader\tm_pass;\r\n\tNxNgc::sTexture *\tmp_texture;\r\n\tsNgcVert\t\t\tm_verts[SPLAT_POLYS_PER_MESH * 3];\r\n};\r\n#endif\t\t// 0\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sNgcShatterInstanceDetails : public sShatterInstanceDetails\r\n{\r\n\t// Platform specific part.\r\n\r\n\t\t\t\t\t\tsNgcShatterInstanceDetails( int num_tris, NxNgc::sMesh *p_mesh, NxNgc::sScene *p_scene, GXVtxFmt format );\r\n\t\t\t\t\t\t~sNgcShatterInstanceDetails( void );\r\n\t\r\n\tNxNgc::sMesh\t\t*mp_mesh;\r\n\tNxNgc::sScene\t\t*mp_scene;\r\n\tsNgcVert\t\t\t*mp_vertex_buffer;\r\n\tGXVtxFmt\t\t\tm_vertex_format;\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsNgcShatterInstanceDetails::sNgcShatterInstanceDetails( int num_tris, NxNgc::sMesh *p_mesh, NxNgc::sScene *p_scene, GXVtxFmt format ) : sShatterInstanceDetails( num_tris )\r\n{\r\n\tmp_mesh\t\t\t\t= p_mesh;\r\n\tmp_scene\t\t\t= p_scene;\r\n\tmp_vertex_buffer\t= new sNgcVert[num_tris * 3];\r\n\tm_vertex_format\t\t= format;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsNgcShatterInstanceDetails::~sNgcShatterInstanceDetails( void )\r\n{\r\n\tdelete [] mp_vertex_buffer;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#if 0\r\nsNgcSplatInstanceDetails * getDetailsForTextureSplat( NxNgc::sTexture *p_texture )\r\n{\r\n\r\n\tsNgcSplatInstanceDetails *p_Ngc_details;\r\n\r\n\tDbg_Assert( p_splat_details_table );\r\n\t\r\n\t// Check to see whether we have a scene already created for this type of texture splat.\r\n\tp_splat_details_table->IterateStart();\r\n\tsSplatInstanceDetails *p_details = p_splat_details_table->IterateNext();\r\n\twhile( p_details )\r\n\t{\r\n\t\tp_Ngc_details\t\t\t\t\t= static_cast<sNgcSplatInstanceDetails*>( p_details );\r\n//\t\tif( p_Ngc_details->m_pass.m_texture.p_data == p_texture )\r\n\t\tif( p_Ngc_details->mp_texture == p_texture )\r\n\t\t{\r\n\t\t\t// This scene contains a material with the required texture, so use this scene.\r\n\t\t\treturn p_Ngc_details;\r\n\t\t}\r\n\t\tp_details = p_splat_details_table->IterateNext();\r\n\t}\r\n\t\r\n\t// Create an (opaque) material used to render the mesh.\r\n\tp_Ngc_details = new sNgcSplatInstanceDetails;\r\n\r\n\tp_Ngc_details->mp_texture\t\t\t\t= p_texture;\r\n\r\n\tp_Ngc_details->m_highest_active_splat\t= 0;\r\n\tmemset( p_Ngc_details->m_lifetimes, 0, sizeof( int ) * SPLAT_POLYS_PER_MESH );\r\n\r\n\tfor( int v = 0; v < SPLAT_POLYS_PER_MESH * 3; ++v )\r\n\t{\r\n\t\tp_Ngc_details->m_verts[v].pos = Mth::Vector(0.0f, 0.0f, 0.0f, 1.0f);\r\n\t\tp_Ngc_details->m_verts[v].col = (GXColor){ 0x80, 0x80, 0x80, 0xff };\r\n\t}\r\n\t\r\n\tp_splat_details_table->PutItem((uint32)p_Ngc_details, p_Ngc_details );\r\n\r\n\treturn p_Ngc_details;\r\n}\r\n#endif\t\t// 0\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool subdivide_tri_stack( sNgcVert **p_write, NxNgc::sMesh *p_mesh )\r\n{\r\n\t// If there are elements on the stack, pop off the top three vertices and subdivide if necessary.\r\n\tif( triSubdivideStack.IsEmpty())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Three temporary buffers.\r\n\tsNgcVert v0;\r\n\tsNgcVert v1;\r\n\tsNgcVert v2;\r\n\t\r\n\tsNgcVert\t*p_v0 = &v0;\r\n\tsNgcVert\t*p_v1 = &v1;\r\n\tsNgcVert\t*p_v2 = &v2;\r\n\t\r\n\t// Stack is LIFO, so Pop() off in reverse order.\r\n\ttriSubdivideStack.Pop( p_v2 );\r\n\ttriSubdivideStack.Pop( p_v1 );\r\n\ttriSubdivideStack.Pop( p_v0 );\r\n\t\r\n\t// Calculate the area of this tri.\r\n\tMth::Vector p(\tp_v1->pos[X] - p_v0->pos[X], p_v1->pos[Y] - p_v0->pos[Y], p_v1->pos[Z] - p_v0->pos[Z] );\r\n\tMth::Vector q(\tp_v2->pos[X] - p_v0->pos[X], p_v2->pos[Y] - p_v0->pos[Y], p_v2->pos[Z] - p_v0->pos[Z] );\r\n\tMth::Vector r(( p[Y] * q[Z] ) - ( q[Y] * p[Z] ), ( p[Z] * q[X] ) - ( q[Z] * p[X] ), ( p[X] * q[Y] ) - ( q[X] * p[Y] ));\r\n\tfloat area_squared = r.LengthSqr();\r\n\r\n\tif( area_squared > shatterAreaTest )\r\n\t{\r\n\t\t// Three temporary buffers.\r\n\t\tsNgcVert i01 = v0;\r\n\t\tsNgcVert i12 = v0;\r\n\t\tsNgcVert i20 = v0;\r\n\r\n\t\t// Deal with positions (always present).\r\n\t\ti01.pos[X] = p_v0->pos[X] + (( p_v1->pos[X] - p_v0->pos[X] ) * 0.5f );\r\n\t\ti01.pos[Y] = p_v0->pos[Y] + (( p_v1->pos[Y] - p_v0->pos[Y] ) * 0.5f );\r\n\t\ti01.pos[Z] = p_v0->pos[Z] + (( p_v1->pos[Z] - p_v0->pos[Z] ) * 0.5f );\r\n\t\t      \r\n\t\ti12.pos[X] = p_v1->pos[X] + (( p_v2->pos[X] - p_v1->pos[X] ) * 0.5f );\r\n\t\ti12.pos[Y] = p_v1->pos[Y] + (( p_v2->pos[Y] - p_v1->pos[Y] ) * 0.5f );\r\n\t\ti12.pos[Z] = p_v1->pos[Z] + (( p_v2->pos[Z] - p_v1->pos[Z] ) * 0.5f );\r\n\t\t      \r\n\t\ti20.pos[X] = p_v2->pos[X] + (( p_v0->pos[X] - p_v2->pos[X] ) * 0.5f );\r\n\t\ti20.pos[Y] = p_v2->pos[Y] + (( p_v0->pos[Y] - p_v2->pos[Y] ) * 0.5f );\r\n\t\ti20.pos[Z] = p_v2->pos[Z] + (( p_v0->pos[Z] - p_v2->pos[Z] ) * 0.5f );\r\n\r\n\t\t// Deal with colors (not always present).\r\n//\t\tif ( p_mesh->mp_colBuffer )\r\n\t\t{\r\n\t\t\ti01.col.r\t\t= v0.col.r + (u8)(( v1.col.r - v0.col.r ) >> 1 );\r\n\t\t\ti12.col.r\t\t= v1.col.r + (u8)(( v2.col.r - v1.col.r ) >> 1 );\r\n\t\t\ti20.col.r\t\t= v2.col.r + (u8)(( v0.col.r - v2.col.r ) >> 1 );\r\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\r\n\t\t\ti01.col.g\t\t= v0.col.g + (u8)(( v1.col.g - v0.col.g ) >> 1 );\r\n\t\t\ti12.col.g\t\t= v1.col.g + (u8)(( v2.col.g - v1.col.g ) >> 1 );\r\n\t\t\ti20.col.g\t\t= v2.col.g + (u8)(( v0.col.g - v2.col.g ) >> 1 );\r\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\r\n\t\t\ti01.col.b\t\t= v0.col.b + (u8)(( v1.col.b - v0.col.b ) >> 1 );\r\n\t\t\ti12.col.b\t\t= v1.col.b + (u8)(( v2.col.b - v1.col.b ) >> 1 );\r\n\t\t\ti20.col.b\t\t= v2.col.b + (u8)(( v0.col.b - v2.col.b ) >> 1 );\r\n\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\r\n\t\t\ti01.col.a\t\t= v0.col.a + (u8)(( v1.col.a - v0.col.a ) >> 1 );\r\n\t\t\ti12.col.a\t\t= v1.col.a + (u8)(( v2.col.a - v1.col.a ) >> 1 );\r\n\t\t\ti20.col.a\t\t= v2.col.a + (u8)(( v0.col.a - v2.col.a ) >> 1 );\r\n\t\t}\r\n\r\n\t\t// Deal with uv0 (not always present).\r\n//\t\tif ( p_mesh->mp_uvBuffer )\r\n\t\t{\r\n\t\t\ti01.u\t\t= v0.u + (( v1.u - v0.u ) >> 1 );\r\n\t\t\ti01.v\t\t= v0.v + (( v1.v - v0.v ) >> 1 );\r\n\t\t\ti12.u\t\t= v1.u + (( v2.u - v1.u ) >> 1 );\r\n\t\t\ti12.v\t\t= v1.v + (( v2.v - v1.v ) >> 1 );\r\n\t\t\ti20.u\t\t= v2.u + (( v0.u - v2.u ) >> 1 );\r\n\t\t\ti20.v\t\t= v2.v + (( v0.v - v2.v ) >> 1 );\r\n\t\t}\r\n\t\t\r\n\t\t// Push the four new tris onto the stack.\r\n\t\ttriSubdivideStack.Push( &v0 );\r\n\t\ttriSubdivideStack.Push( &i01 );\r\n\t\ttriSubdivideStack.Push( &i20 );\r\n\r\n\t\ttriSubdivideStack.Push( &i01 );\r\n\t\ttriSubdivideStack.Push( &v1 );\r\n\t\ttriSubdivideStack.Push( &i12 );\r\n\r\n\t\ttriSubdivideStack.Push( &i01 );\r\n\t\ttriSubdivideStack.Push( &i12 );\r\n\t\ttriSubdivideStack.Push( &i20 );\r\n\r\n\t\ttriSubdivideStack.Push( &i20 );\r\n\t\ttriSubdivideStack.Push( &i12 );\r\n\t\ttriSubdivideStack.Push( &v2 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Just copy the tri into the next available slot.\r\n\t\t**p_write = v0;\r\n\t\t(*p_write)++;\r\n\t\t**p_write = v1;\r\n\t\t(*p_write)++;\r\n\t\t**p_write = v2;\r\n\t\t(*p_write)++;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic bool same_side( Mth::Vector &p1, Mth::Vector &p2, Mth::Vector &a, Mth::Vector &b )\r\n{\r\n\tMth::Vector cp1 = Mth::CrossProduct( b - a, p1 - a );\r\n\tMth::Vector cp2 = Mth::CrossProduct( b - a, p2 - a );\r\n\tif( Mth::DotProduct( cp1, cp2 ) >= 0.0f )\r\n\t\treturn true;\r\n    else\r\n\t\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic bool point_in_triangle( Mth::Vector &p, Mth::Vector &a, Mth::Vector &b, Mth::Vector &c )\r\n{\r\n\tif( same_side( p, a, b, c ) && same_side( p, b, a, c ) && same_side( p, c, a, b ))\r\n\t\treturn true;\r\n    else\r\n\t\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline bool line_segment_intersection( float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4 )\r\n{\r\n\tfloat den = (( y4 - y3 ) * ( x2 - x1 )) - (( x4 - x3 ) * ( y2 - y1 ));\r\n\r\n\tif( den == 0.0f )\r\n\t{\r\n\t\t// Parallel lines.\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tfloat num_a = (( x4 - x3 ) * ( y1 - y3 )) - (( y4 - y3 ) * ( x1 - x3 ));\r\n\tfloat num_b = (( x2 - x1 ) * ( y1 - y3 )) - (( y2 - y1 ) * ( x1 - x3 ));\r\n\r\n\tnum_a /= den;\r\n\tnum_b /= den;\r\n\r\n\tif(( num_a <= 1.0f ) && ( num_b <= 1.0f ))\r\n\t\treturn true;\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline bool tri_texture_intersect( float u0, float v0, float u1, float v1, float u2, float v2 )\r\n{\r\n\t// Trivial check to see if all three points are outside range of texture.\r\n\tif(( u0 < -1.0f ) && ( u1 < -1.0f ) && ( u2 < -1.0f ))\r\n\t\treturn false;\r\n\tif(( u0 > 1.0f ) && ( u1 > 1.0f ) && ( u2 > 1.0f ))\r\n\t\treturn false;\r\n\tif(( v0 < -1.0f ) && ( v1 < -1.0f ) && ( v2 < -1.0f ))\r\n\t\treturn false;\r\n\tif(( v0 > 1.0f ) && ( v1 > 1.0f ) && ( v2 > 1.0f ))\r\n\t\treturn false;\r\n\t\r\n\t// Check that at least one corner of the texture falls within the tri.\r\n\tMth::Vector texture_square[4] = {\tMth::Vector( -1.0f, -1.0f, 0.0f, 0.0f ),\r\n\t\t\t\t\t\t\t\t\t\tMth::Vector(  1.0f, -1.0f, 0.0f, 0.0f ),\r\n\t\t\t\t\t\t\t\t\t\tMth::Vector(  1.0f,  1.0f, 0.0f, 0.0f ),\r\n\t\t\t\t\t\t\t\t\t\tMth::Vector( -1.0f,  1.0f, 0.0f, 0.0f )};\r\n\r\n\tMth::Vector a( u0, v0, 0.0f );\r\n\tMth::Vector b( u1, v1, 0.0f );\r\n\tMth::Vector c( u2, v2, 0.0f );\r\n\r\n\tfor( int p = 0; p < 4; ++p )\r\n\t{\r\n\t\tif( point_in_triangle( texture_square[p], a, b, c ))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// No corners of the texture fall within the tri. There are 3 possible explanations:\r\n\t// 1) The tri intersects the texture, but does not contain a texture corner.\r\n\t// 2) The texture lies entirely outside of the tri.\r\n\t// 3) The tri falls entirely within the texture.\r\n\t// Given the relatively small size of the textures, case (3) is extremely unlikely.\r\n\r\n\t// Perform a trivial check to see whether a corner of the tri lies within the texture. This will catch (3) and sometimes (1).\r\n\tif(( u0 >= -1.0f ) && ( u0 <= 1.0f ) && ( v0 >= -1.0f ) && ( v0 <= 1.0f ))\r\n\t\treturn true;\r\n\tif(( u1 >= -1.0f ) && ( u1 <= 1.0f ) && ( v1 >= -1.0f ) && ( v1 <= 1.0f ))\r\n\t\treturn true;\r\n\tif(( u2 >= -1.0f ) && ( u2 <= 1.0f ) && ( v2 >= -1.0f ) && ( v2 <= 1.0f ))\r\n\t\treturn true;\r\n\r\n\t// Perform the complete check to see if any line segment forming the tri intersects any line segment forming the texture.\r\n\tfor( int p = 0; p < 4; ++p )\r\n\t{\r\n\t\tint q = ( p + 1 ) % 4;\r\n\t\tif( line_segment_intersection( u0, v0, u1, v1, texture_square[p][X], texture_square[p][Y], texture_square[q][X], texture_square[q][Y] ))\r\n\t\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_screen_flash_render( sScreenFlashDetails *p_details )\r\n{\r\n\t// Create an (opaque) material used to render the mesh.\r\n\tNxNgc::sMaterialHeader\t\tmat;\r\n\tNxNgc::sMaterialPassHeader\tpass;\r\n\r\n\t// Header.\r\n\tmat.m_checksum\t\t\t= 0xa9db601e;   // particle \r\n\tmat.m_passes\t\t\t= 1;\r\n\tmat.m_alpha_cutoff\t\t= 1;\r\n\tmat.m_flags\t\t\t\t= (1<<1);\t\t// 2 sided.\r\n//\tmat.m_shininess\t\t\t= 0.0f;\r\n\r\n\t// Pass 0.\r\n\tpass.m_texture.p_data\t= NULL;\r\n\tpass.m_flags\t\t\t= (1<<5) | (1<<6);\t\t// clamped.\r\n\tpass.m_filter\t\t\t= 0;\r\n\tpass.m_blend_mode\t\t= (unsigned char)NxNgc::vBLEND_MODE_BLEND;\r\n\tpass.m_alpha_fix\t\t= (unsigned char)0; \r\n\tpass.m_k\t\t\t\t= 0;\r\n\tpass.m_color.r\t\t\t= 128;\r\n\tpass.m_color.g\t\t\t= 128;\r\n\tpass.m_color.b\t\t\t= 128;\r\n\tpass.m_color.a\t\t\t= 255;\r\n\r\n\t// Get viewport details.\r\n\tCViewport *p_vp = CViewportManager::sGetActiveViewport( p_details->m_viewport );\r\n\r\n\tsNgcScreenFlashVert verts[4];\r\n\r\n\tverts[0].x\t= p_vp->GetOriginX() * 640;\r\n\tverts[0].y\t= p_vp->GetOriginY() * 448;\r\n\tverts[0].z\t= p_details->m_z;\r\n\t\r\n\tverts[1].x\t= verts[0].x + ( p_vp->GetWidth() * 640 );\r\n\tverts[1].y\t= verts[0].y;\r\n\tverts[1].z\t= verts[0].z;\r\n\r\n\tverts[2].x\t= verts[0].x + ( p_vp->GetWidth() * 640 );\r\n\tverts[2].y\t= verts[0].y + ( p_vp->GetHeight() * 448 );\r\n\tverts[2].z\t= verts[0].z;\r\n\r\n\tverts[3].x\t= verts[0].x;\r\n\tverts[3].y\t= verts[0].y + ( p_vp->GetHeight() * 448 );\r\n\tverts[3].z\t= verts[0].z;\r\n\r\n\tfor( int v = 0; v < 4; ++v )\r\n\t{\r\n\t\tverts[v].col = (GXColor){ p_details->m_current.r, p_details->m_current.g, p_details->m_current.b, p_details->m_current.a };\r\n\t}\r\n\r\n\tif( p_details->mp_texture )\r\n\t{\r\n\t\tverts[0].u\t= 0.0f;\r\n\t\tverts[0].v\t= 0.0f;\r\n\t\tverts[1].u\t= 1.0f;\r\n\t\tverts[1].v\t= 0.0f;\r\n\t\tverts[2].u\t= 1.0f;\r\n\t\tverts[2].v\t= 1.0f;\r\n\t\tverts[3].u\t= 0.0f;\r\n\t\tverts[3].v\t= 1.0f;\r\n\r\n\t\tNx::CNgcTexture *p_Ngc_texture = static_cast<CNgcTexture*>( p_details->mp_texture );\r\n\t\tpass.m_texture.p_data = p_Ngc_texture->GetEngineTexture();\r\n\t\tpass.m_flags |= (1<<0);\r\n\t}\r\n\tGX::SetZMode ( GX_FALSE, GX_ALWAYS, GX_FALSE );\r\n\r\n\tNxNgc::multi_mesh( &mat, &pass, true, false );\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t// Render the triangles\r\n\tif( p_details->mp_texture )\r\n\t{\r\n\t\tGX::SetVtxDesc( 3, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\t}\r\n\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\tfor (int i = 0; i < 4; i++ )\r\n\t{\r\n\t\tGX::Position3f32( verts[i].x, verts[i].y, verts[i].z );\r\n\t\tGX::Color1u32(*((u32*)&(verts[i].col)));\r\n\t\tif( p_details->mp_texture ) GX::TexCoord2f32( verts[i].u, verts[i].v );\r\n\t}\r\n\tGX::End();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_texture_splat_initialize( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_texture_splat_cleanup( void )\r\n{\r\n#if 0\r\n\tsNgcSplatInstanceDetails *p_Ngc_details;\r\n\r\n\tDbg_Assert( p_splat_details_table );\r\n\t\r\n\tp_splat_details_table->IterateStart();\r\n\tsSplatInstanceDetails *p_details = p_splat_details_table->IterateNext();\r\n\twhile( p_details )\r\n\t{\r\n\t\tp_Ngc_details = static_cast<sNgcSplatInstanceDetails*>( p_details );\r\n\r\n\t\t//delete p_Ngc_details->mp_material;\r\n\t\t\r\n\t\tp_details = p_splat_details_table->IterateNext();\r\n\r\n\t\tp_splat_details_table->FlushItem((uint32)p_Ngc_details );\r\n\t\tdelete p_Ngc_details;\r\n\t}\r\n#endif\t\t// 0\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_texture_splat_reset_poly( sSplatInstanceDetails *p_details, int index )\r\n{\r\n#if 0\r\n\t// Cast the details to Ngc details.\r\n\tsNgcSplatInstanceDetails *p_Ngc_details = static_cast<sNgcSplatInstanceDetails *>( p_details );\r\n\t\r\n\t// Force this poly to be degenerate.\r\n\tp_Ngc_details->m_verts[index * 3 + 1]\t= p_Ngc_details->m_verts[index * 3];\r\n\tp_Ngc_details->m_verts[index * 3 + 2]\t= p_Ngc_details->m_verts[index * 3];\r\n#endif\t\t// 0\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool plat_texture_splat( Nx::CSector **pp_sectors, Nx::CCollStatic **pp_collision, Mth::Vector& start, Mth::Vector& end, float size, float lifetime, Nx::CTexture *p_texture, Nx::sSplatTrailInstanceDetails *p_trail_details )\r\n{\r\n#if 0\r\n\tMth::Matrix view_matrix, ortho_matrix, projection_matrix;\r\n\r\n#\tif DRAW_DEBUG_LINES\r\n//\tGfx::AddDebugLine( start, end, MAKE_RGB( 200, 200, 0 ), MAKE_RGB( 200, 200, 0 ), 1 );\r\n\tADD_LINE( start, end, 200, 200, 0 );\r\n#\tendif // DRAW_DEBUG_LINES\r\n\t\r\n\t// The length of the start->end line defines the view depth of the frustum.\r\n\tMth::Vector\tsplat_vector\t= end - start;\r\n\tfloat\t\tview_depth\t\t= splat_vector.Length();\r\n\tsplat_vector.Normalize();\r\n\t\r\n\t// Calculate the parallel projection matrix. Generally the projection vector will tend to point downwards, so we use a\r\n\t// random vector in the x-z plane to define the up vector for the projection. However if this splat is part of a trail,\r\n\t// use the previous point to generate the up vector.\r\n\tif( p_trail_details )\r\n\t{\r\n\t\tMth::Vector up( start[X] - p_trail_details->m_last_pos[X], start[Y] - p_trail_details->m_last_pos[Y], start[Z] - p_trail_details->m_last_pos[Z], 0.0f );\r\n\r\n\t\t// The height of the viewport is defined by the distance between the two points.\r\n\t\tfloat height = up.Length() * 0.5f;\r\n\r\n\t\tstart\t-= up * 0.5f;\r\n\t\tend\t\t-= up * 0.5f;\r\n\r\n\t\tup.Normalize();\r\n\r\n\t\tMth::CreateMatrixLookAt( view_matrix, start, end, up );\r\n\t\tMth::CreateMatrixOrtho( ortho_matrix, size, height, 0.1f, view_depth );\r\n\t}\r\n\telse if( fabsf( splat_vector[Y] ) > 0.5f )\r\n\t{\r\n\t\tfloat angle = ((float)rand() * 2.0f * Mth::PI ) / (float)RAND_MAX;\r\n\t\tMth::CreateMatrixLookAt( view_matrix, start, end, Mth::Vector( sinf( angle ), 0.0f, cosf( angle ), 0.0f ));\r\n\t\tMth::CreateMatrixOrtho( ortho_matrix , size, size, 0.1f, view_depth );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMth::CreateMatrixLookAt( view_matrix, start, end, Mth::Vector( 0.0f, 1.0f, 0.0f, 0.0f ));\r\n\t\tMth::CreateMatrixOrtho( ortho_matrix , size, size, 0.1f, view_depth );\r\n\t}\r\n\r\n\tprojection_matrix = view_matrix * ortho_matrix;\r\n\r\n\t// Pointer to the mesh we will be modifying. (Don't want to set the pointer up until we know for\r\n\t// sure that we will be adding some polys).\r\n\tsNgcSplatInstanceDetails\t*p_details\t\t= NULL;\r\n\tsNgcVert\t\t\t\t\t*p_target_verts\t= NULL;\r\n\r\n\tNx::CSector *p_sector;\r\n\twhile( (p_sector = *pp_sectors) )\r\n\t{\r\n\t\tNx::CNgcGeom *p_Ngc_geom = static_cast<Nx::CNgcGeom*>( p_sector->GetGeom());\r\n\r\n\t\tif( p_Ngc_geom )\r\n\t\t{\r\n#\t\t\tif DRAW_DEBUG_LINES\r\n\t\t\tMth::Vector min = p_Ngc_geom->GetBoundingBox().GetMin();\r\n\t\t\tMth::Vector max = p_Ngc_geom->GetBoundingBox().GetMax();\r\n\r\n\t\t\tMth::Vector box[8];\r\n\t\t\tbox[0] = box[1] = box[2] = box[3] = max;\r\n\t\t\tbox[1][X] = min[X];\r\n\t\t\tbox[2][Y] = min[Y];\r\n\t\t\tbox[3][Z] = min[Z];\r\n\t\t\tbox[5] = box[6] = box[7] = box[4] = min;;\r\n\t\t\tbox[5][X] = max[X];\r\n\t\t\tbox[6][Y] = max[Y];\r\n\t\t\tbox[7][Z] = max[Z];\r\n\r\n\t\t\tfor ( int i = 1; i < 4; i++ )\r\n\t\t\t{\r\n//\t\t\t\tGfx::AddDebugLine( box[0], box[i], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\t\tADD_LINE( box[0], box[i], 200, 0, 0 );\r\n\t\t\t}\r\n\t\t\tfor ( int i = 5; i < 8; i++ )\r\n\t\t\t{\r\n//\t\t\t\tGfx::AddDebugLine( box[4], box[i], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\t\tADD_LINE( box[4], box[i], 200, 0, 0 );\r\n\t\t\t}\r\n//\t\t\tGfx::AddDebugLine( box[1], box[6], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n//\t\t\tGfx::AddDebugLine( box[1], box[7], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n//\t\t\tGfx::AddDebugLine( box[2], box[5], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n//\t\t\tGfx::AddDebugLine( box[2], box[7], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n//\t\t\tGfx::AddDebugLine( box[3], box[5], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n//\t\t\tGfx::AddDebugLine( box[3], box[6], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\tADD_LINE( box[1], box[6], 200, 0, 0 );\r\n\t\t\tADD_LINE( box[1], box[7], 200, 0, 0 );\r\n\t\t\tADD_LINE( box[2], box[5], 200, 0, 0 );\r\n\t\t\tADD_LINE( box[2], box[7], 200, 0, 0 );\r\n\t\t\tADD_LINE( box[3], box[5], 200, 0, 0 );\r\n\t\t\tADD_LINE( box[3], box[6], 200, 0, 0 );\r\n#\t\t\tendif // DRAW_DEBUG_LINES\r\n\t\t\t\r\n\t\t\t// For each mesh in the geom...\r\n\t\t\tfor( uint32 m = 0; m < p_Ngc_geom->m_num_mesh; ++m )\r\n\t\t\t{\r\n\t\t\t\tNxNgc::sMesh *p_mesh = p_Ngc_geom->m_mesh_array[m];\r\n\t\t\t\t\r\n\t\t\t\tNxNgc::sScene *p_scene = p_Ngc_geom->mp_scene->GetEngineScene();\r\n\r\n\t\t\t\t// Not allowed on meshes which are flagged not to shadow.\r\n\t\t\t\tif( p_mesh->m_flags & NxNgc::sMesh::MESH_FLAG_NO_SKATER_SHADOW )\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t\r\n\t\t\t\t// Count indices.\r\n\t\t\t\tint num_indices = 0;\r\n\t\t\t\tunsigned char * p_start = (unsigned char *)&p_mesh->mp_dl[1];\r\n//\t\t\t\tuint32 cp = (p_start[2]<<24)|(p_start[3]<<16)|(p_start[4]<<8)|p_start[5];\r\n\t\t\t\tunsigned char * p_end = &p_start[p_mesh->mp_dl->m_size];\r\n\t\t\t\tp_start = &p_start[p_mesh->mp_dl->m_index_offset];\t\t// Skip to actual 1st GDBegin.\r\n\t\t\t\tunsigned char * p8 = p_start;\r\n\r\n\t\t\t\tint stride = p_mesh->mp_dl->m_index_stride;\r\n\r\n\t\t\t\tunsigned char * p_index_buffer  = &p8[1];\r\n\r\n\t\t\t\twhile ( p8 < p_end )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( ( p8[0] & 0xf8 ) == GX_TRIANGLESTRIP )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Found a triangle strip - parse it.\r\n\t\t\t\t\t\tint num_verts = ( p8[1] << 8 ) | p8[2];\r\n\t\t\t\t\t\tp8 += 3;\t\t// Skip GDBegin\r\n\r\n\t\t\t\t\t\tnum_indices += num_verts;\r\n\r\n\t\t\t\t\t\tp8 += stride * 2 * num_verts;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( p_index_buffer )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Create the index buffer.\r\n\t\t\t\t\tuint polys = 0;\r\n\t\t\t\t\tuint16 idxbuf[2048*3];\t\t// 12k.\r\n\t\t\t\t\tuint16 * p_dest = idxbuf;\r\n\t\t\t\t\tuint8 * p_source = (uint8*)p_index_buffer;\r\n\t\t\t\t\tuint16 total = 0;\r\n\t\t\t\t\twhile ( total < num_indices )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tuint16 num = ( p_source[0] << 8 ) | p_source[1];\r\n\t\t\t\t\t\tp_source += 2;\r\n\t\t\t\t\t\tuint16 i0;\r\n\t\t\t\t\t\tuint16 i1 = ( p_source[0] << 8 ) | p_source[1];\r\n\t\t\t\t\t\tp_source += stride * 2;\r\n\t\t\t\t\t\tuint16 i2 = ( p_source[0] << 8 ) | p_source[1];\r\n\t\t\t\t\t\tp_source += stride * 2;\r\n\t\t\t\t\t\tfor ( int vv = 2; vv < num; vv++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ti0 = i1;\r\n\t\t\t\t\t\t\ti1 = i2;\r\n\t\t\t\t\t\t\ti2 = ( p_source[0] << 8 ) | p_source[1];\r\n\t\t\t\t\t\t\tp_source += stride * 2;\r\n\t\t\t\t\t\t\t*p_dest++ = i0;\r\n\t\t\t\t\t\t\t*p_dest++ = i1;\r\n\t\t\t\t\t\t\t*p_dest++ = i2;\r\n\t\t\t\t\t\t\tpolys++;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tp_source += 1;\r\n\t\t\t\t\t\ttotal += num + 1;\t\t// Count each index + the count.\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Now scan through each non-degenerate tri, checking the verts to see if they are within scope.\r\n\t\t\t\t\tfor( uint32 i = 0; i < polys; ++i )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Wrap the indices round.\r\n\t\t\t\t\t\tuint16 index0 = idxbuf[(i*3)+0];\r\n\t\t\t\t\t\tuint16 index1 = idxbuf[(i*3)+1];\r\n\t\t\t\t\t\tuint16 index2 = idxbuf[(i*3)+2];\r\n\r\n\t\t\t\t\t\tif(( index0 != index1 ) && ( index0 != index2 ) && ( index1 != index2 ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tMth::Vector v0( p_scene->mp_pos_pool[(index0*3)+0],\r\n\t\t\t\t\t\t\t\t\t\t\tp_scene->mp_pos_pool[(index0*3)+1],\r\n\t\t\t\t\t\t\t\t\t\t\tp_scene->mp_pos_pool[(index0*3)+2] );\r\n\t\t\t\t\t\t\tMth::Vector v1( p_scene->mp_pos_pool[(index1*3)+0],\r\n\t\t\t\t\t\t\t\t\t\t\tp_scene->mp_pos_pool[(index1*3)+1],\r\n\t\t\t\t\t\t\t\t\t\t\tp_scene->mp_pos_pool[(index1*3)+2] );\r\n\t\t\t\t\t\t\tMth::Vector v2( p_scene->mp_pos_pool[(index2*3)+0],\r\n\t\t\t\t\t\t\t\t\t\t\tp_scene->mp_pos_pool[(index2*3)+1],\r\n\t\t\t\t\t\t\t\t\t\t\tp_scene->mp_pos_pool[(index2*3)+2] );\r\n\r\n\t\t\t\t\t\t\tv0[W] = v1[W] = v2[W] = 1.0f;\t\t// Make sure they are points, not vectors\r\n\r\n\t//\t\t\t\t\t\tOSReport( \"Looking at: (%6.3f, %6.3f, %6.3f) (%6.3f, %6.3f, %6.3f) (%6.3f, %6.3f, %6.3f)\\n\", v0[X], v0[Y], v0[Z], v1[X], v1[Y], v1[Z], v2[X], v2[Y], v2[Z] );\r\n\r\n\t\t\t\t\t\t\tMth::Vector uvprojections[3];\r\n\t\t\t\t\t\t\tuvprojections[0] = v0 * projection_matrix;\r\n\t\t\t\t\t\t\tuvprojections[1] = v1 * projection_matrix;\r\n\t\t\t\t\t\t\tuvprojections[2] = v2 * projection_matrix;\r\n\r\n\t\t\t\t\t\t\t// Check that they are in the frustum\r\n//\t\t\t\t\t\t\tif(( uvprojections[0][X] < -1.0f ) && ( uvprojections[1][X] < -1.0f ) && ( uvprojections[2][X] < -1.0f ))\r\n//\t\t\t\t\t\t\t\tcontinue;\r\n//\t\t\t\t\t\t\tif(( uvprojections[0][Y] < -1.0f ) && ( uvprojections[1][Y] < -1.0f ) && ( uvprojections[2][Y] < -1.0f ))\r\n//\t\t\t\t\t\t\t\tcontinue;\r\n//\t\t\t\t\t\t\tif(( uvprojections[0][X] > 1.0f ) && ( uvprojections[1][X] > 1.0f ) && ( uvprojections[2][X] > 1.0f ))\r\n//\t\t\t\t\t\t\t\tcontinue;\r\n//\t\t\t\t\t\t\tif(( uvprojections[0][Y] > 1.0f ) && ( uvprojections[1][Y] > 1.0f ) && ( uvprojections[2][Y] > 1.0f ))\r\n//\t\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t\tif(( uvprojections[0][Z] < -1.0f ) && ( uvprojections[1][Z] < -1.0f ) && ( uvprojections[2][Z] < -1.0f ))\r\n\t\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t\tif(( uvprojections[0][Z] > 1.0f ) && ( uvprojections[1][Z] > 1.0f ) && ( uvprojections[2][Z] > 1.0f ))\r\n\t\t\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\t\t\t// Okay, this tri lies within the projection frustum. Now check that it intersects the texture\r\n\t\t\t\t\t\t\tif( !tri_texture_intersect( uvprojections[0][X], uvprojections[0][Y],\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tuvprojections[1][X], uvprojections[1][Y],\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tuvprojections[2][X], uvprojections[2][Y] ))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t\t}\r\n\r\n//#ifdef SHORT_VERT\r\n\t\t\t\t\t\t\tMth::Vector\ts = v1 - v0;\r\n\t\t\t\t\t\t\tMth::Vector\tt = v2 - v0;\r\n\t\t\t\t\t\t\tMth::Vector normal = Mth::CrossProduct( s, t );\r\n\t\t\t\t\t\t\tnormal.Normalize();\r\n\r\n\t\t\t\t\t\t\tv0 -= normal;\r\n\t\t\t\t\t\t\tv1 -= normal;\r\n\t\t\t\t\t\t\tv2 -= normal;\r\n//#endif\t\t// SHORT_VERT \r\n\r\n\t//\t\t\t\t\t\tOSReport( \"Added: (%5.1f, %5.1f, %5.1f) (%5.1f, %5.1f, %5.1f) (%5.1f, %5.1f, %5.1f)\\n\", v0[X], v0[Y], v0[Z], v1[X], v1[Y], v1[Z], v2[X], v2[Y], v2[Z] );\r\n\r\n\t\t\t\t\t\t\t// Okay, this tri lies within the projection frustum. Get a pointer to the mesh used for rendering texture splats\r\n\t\t\t\t\t\t\t// with the given texture. (Note this will create a new instance to handle texture splats of this texture if one\r\n\t\t\t\t\t\t\t// does not already exist).\r\n\t\t\t\t\t\t\tif( p_target_verts == NULL )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tCNgcTexture *p_Ngc_texture\t= static_cast<CNgcTexture*>( p_texture );\r\n\t\t\t\t\t\t\t\tp_details\t\t\t\t\t\t= getDetailsForTextureSplat( p_Ngc_texture->GetEngineTexture());\r\n\t\t\t\t\t\t\t\tp_target_verts\t\t\t\t\t= p_details->m_verts;\r\n\t\t\t\t\t\t\t\tDbg_Assert( p_target_verts );\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// If we have trails, scale up the mapping by one pixel in all directions.\r\n\t\t\t\t\t\t\t// (effectively 2 pixels in u and 2 pixels in v ).\r\n\t\t\t\t\t\t\tfloat up_one_u_pixel;\r\n\t\t\t\t\t\t\tfloat up_one_v_pixel;\r\n\t\t\t\t\t\t\tif( p_trail_details )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tup_one_u_pixel = 1.0f - ( 1.0f / ( p_texture->GetWidth() / 2.0f ) );\r\n\t\t\t\t\t\t\t\tup_one_v_pixel = 1.0f - ( 1.0f / ( p_texture->GetHeight() / 2.0f ) );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tup_one_u_pixel = 1.0f;\r\n\t\t\t\t\t\t\t\tup_one_v_pixel = 1.0f;\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// Scan through the lifetimes, finding a 'dead' poly (lifetime == 0), or the oldest.\r\n\t\t\t\t\t\t\tuint32 idx\t\t\t\t\t\t= p_details->GetOldestSplat();\r\n\r\n\t\t\t\t\t\t\t// Convert lifetime from seconds to milliseconds.\r\n\t\t\t\t\t\t\tp_details->m_lifetimes[idx]\t\t= (int)( lifetime * 1000.0f );\r\n\r\n\t\t\t\t\t\t\t// Set up the corresponding vertices. First write the positions.\r\n\t\t\t\t\t\t\tuint32 index\t\t\t\t\t= idx * 3;\r\n\t\t\t\t\t\t\tp_target_verts[index + 0].pos\t= v0;\r\n\t\t\t\t\t\t\tp_target_verts[index + 1].pos\t= v1;\r\n\t\t\t\t\t\t\tp_target_verts[index + 2].pos\t= v2;\r\n\r\n\t\t\t\t\t\t\t// Then the uv's.\r\n\t\t\t\t\t\t\tp_target_verts[index + 0].u\t\t= (s16)( ( ( ( uvprojections[0][X] * 0.5f ) + 0.5f ) * up_one_u_pixel ) * 256.0f );\r\n\t\t\t\t\t\t\tp_target_verts[index + 0].v\t\t= (s16)( ( ( ( uvprojections[0][Y] * 0.5f ) + 0.5f ) * up_one_v_pixel ) * 256.0f );\r\n\t\t\t\t\t\t\tp_target_verts[index + 1].u\t\t= (s16)( ( ( ( uvprojections[1][X] * 0.5f ) + 0.5f ) * up_one_u_pixel ) * 256.0f );\r\n\t\t\t\t\t\t\tp_target_verts[index + 1].v\t\t= (s16)( ( ( ( uvprojections[1][Y] * 0.5f ) + 0.5f ) * up_one_v_pixel ) * 256.0f );\r\n\t\t\t\t\t\t\tp_target_verts[index + 2].u\t\t= (s16)( ( ( ( uvprojections[2][X] * 0.5f ) + 0.5f ) * up_one_u_pixel ) * 256.0f );\r\n\t\t\t\t\t\t\tp_target_verts[index + 2].v\t\t= (s16)( ( ( ( uvprojections[2][Y] * 0.5f ) + 0.5f ) * up_one_v_pixel ) * 256.0f );\r\n\r\n\t\t\t\t\t\t\t// Now the colors\r\n\t\t\t\t\t\t\tp_target_verts[index + 0].col = (GXColor){128,128,128,255};\t\t// p_coll_geom->GetVertexRGBA(p_coll_geom->GetFaceVertIndex(*p_face_indexes, 0));\r\n\t\t\t\t\t\t\tp_target_verts[index + 1].col = (GXColor){128,128,128,255};     // p_coll_geom->GetVertexRGBA(p_coll_geom->GetFaceVertIndex(*p_face_indexes, 1));\r\n\t\t\t\t\t\t\tp_target_verts[index + 2].col = (GXColor){128,128,128,255};     // p_coll_geom->GetVertexRGBA(p_coll_geom->GetFaceVertIndex(*p_face_indexes, 2));\r\n//.col\r\n\r\n\t\t\t\t\t\t\tMth::Vector\t*p_v0 = &( p_target_verts[index + 0].pos );\r\n\t\t\t\t\t\t\tMth::Vector\t*p_v1 = &( p_target_verts[index + 1].pos );\r\n\t\t\t\t\t\t\tMth::Vector\t*p_v2 = &( p_target_verts[index + 2].pos );\r\n\t\t\t\t\t\t\tMth::Vector pv(\tp_v1->GetX() - p_v0->GetX(), p_v1->GetY() - p_v0->GetY(), p_v1->GetZ() - p_v0->GetZ() );\r\n\t\t\t\t\t\t\tMth::Vector qv(\tp_v2->GetX() - p_v0->GetX(), p_v2->GetY() - p_v0->GetY(), p_v2->GetZ() - p_v0->GetZ() );\r\n\t\t\t\t\t\t\tMth::Vector r(( pv[Y] * qv[Z] ) - ( qv[Y] * pv[Z] ), ( pv[Z] * qv[X] ) - ( qv[Z] * pv[X] ), ( pv[X] * qv[Y] ) - ( qv[X] * pv[Y] ));\r\n\t\t\t\t\t\t\tfloat area_squared = r.LengthSqr();\r\n\t\t\t\t\r\n\t\t\t\t\t\t\t// Set the shatter test to ensure that we don't subdivide too far. Note that each successive subdivision will quarter\r\n\t\t\t\t\t\t\t// the area of each triangle, which means the area *squared* of each triangle will become 1/16th of the previous value.\r\n\t\t\t\t\t\t\tshatterAreaTest = area_squared / 128.0f;\r\n\t\t\t\t\r\n\t\t\t\t\t\t\ttriSubdivideStack.Reset();\r\n\t\t\t\t\t\t\ttriSubdivideStack.SetBlockSize( sizeof(sNgcVert) );\r\n\t\t\t\t\t\t\ttriSubdivideStack.Push( &p_target_verts[index + 0] );\r\n\t\t\t\t\t\t\ttriSubdivideStack.Push( &p_target_verts[index + 1] );\r\n\t\t\t\t\t\t\ttriSubdivideStack.Push( &p_target_verts[index + 2] );\r\n\t\t\t\t\r\n\t\t\t\t\t\t\t// Allocate a block of memory into which the subdivision stack will write the results.\r\n\t\t\t\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\t\t\t\t\tsNgcVert\t\t*p_array\t\t= new sNgcVert[1024];\r\n\t\t\t\t\t\t\tsNgcVert\t\t*p_array_start\t= p_array;\r\n\t\t\t\t\t\t\tsNgcVert\t\t*p_array_loop\t= p_array;\r\n\t\t\t\t\t\t\t//memset( p_array, 0, sizeof(sNgcVert) * 1024 );\r\n\t\t\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\r\n\t\t\t\t\t\t\twhile( subdivide_tri_stack( &p_array, NULL ));\r\n\t\t\t\t\r\n\t\t\t\t\t\t\t// Ensure we haven't overrun the buffer.\r\n\t\t\t\t\t\t\tDbg_Assert((uint32)p_array - (uint32)p_array_loop < ( sizeof(sNgcVert) * 1024 ));\r\n\t\t\t\t\r\n\t\t\t\t\t\t\tfloat oo_up_one_u_pixel = 1.0f / up_one_u_pixel;\r\n\t\t\t\t\t\t\tfloat oo_up_one_v_pixel = 1.0f / up_one_v_pixel;\r\n\t\t\t\t\r\n\t\t\t\t//\t\t\tint vert_idx = 0;\r\n\t\t\t\t\t\t\tbool no_polys = true;\r\n\t\t\t\t\r\n\t\t\t\t\t\t\twhile( p_array_loop != p_array )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tDbg_Assert(((uint32) p_array_loop) < ((uint32) p_array));\r\n\t\t\t\t//\t\t\t\tDbg_Message(\"Looking at vert %d\", vert_idx);\r\n\t\t\t\t\t\t\t\t// Add this triangle, *if* it is valid.\r\n\t\t\t\t\t\t\t\tif( tri_texture_intersect(((p_array_loop[0].u * oo_up_one_u_pixel) - 0.5f) * 2.0f,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  ((p_array_loop[0].v * oo_up_one_v_pixel) - 0.5f) * 2.0f,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  ((p_array_loop[1].u * oo_up_one_u_pixel) - 0.5f) * 2.0f,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  ((p_array_loop[1].v * oo_up_one_v_pixel) - 0.5f) * 2.0f,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  ((p_array_loop[2].u * oo_up_one_u_pixel) - 0.5f) * 2.0f,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  ((p_array_loop[2].v * oo_up_one_v_pixel) - 0.5f) * 2.0f ))\r\n\t\t\t\t//\t\t\t\tif( tri_texture_intersect((p_array_loop[0].u * 2.0f * oo_up_one_u_pixel) - 1.0f,\r\n\t\t\t\t//\t\t\t\t\t\t\t\t\t\t  (p_array_loop[0].v * 2.0f * oo_up_one_v_pixel) - 1.0f,\r\n\t\t\t\t//\t\t\t\t\t\t\t\t\t\t  (p_array_loop[1].u * 2.0f * oo_up_one_u_pixel) - 1.0f,\r\n\t\t\t\t//\t\t\t\t\t\t\t\t\t\t  (p_array_loop[1].v * 2.0f * oo_up_one_v_pixel) - 1.0f,\r\n\t\t\t\t//\t\t\t\t\t\t\t\t\t\t  (p_array_loop[2].u * 2.0f * oo_up_one_u_pixel) - 1.0f,\r\n\t\t\t\t//\t\t\t\t\t\t\t\t\t\t  (p_array_loop[2].v * 2.0f * oo_up_one_v_pixel) - 1.0f ))\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t//\t\t\t\t\tDbg_Message(\"Accepted vert %d\", vert_idx);\r\n\t\t\t\t\t\t\t\t\t// Convert lifetime from seconds to milliseconds.\r\n\t\t\t\t\t\t\t\t\tp_details->m_lifetimes[idx]\t\t= (int)( lifetime * 1000.0f );\r\n\t\t\t\t\r\n\t\t\t\t\t\t\t\t\tp_target_verts[index + 0].pos\t= p_array_loop[0].pos;\r\n\t\t\t\t\t\t\t\t\tp_target_verts[index + 1].pos\t= p_array_loop[1].pos;\r\n\t\t\t\t\t\t\t\t\tp_target_verts[index + 2].pos\t= p_array_loop[2].pos;\r\n\t\t\t\t\r\n\t\t\t\t\t\t\t\t\tp_target_verts[index + 0].u\t\t= p_array_loop[0].u;\r\n\t\t\t\t\t\t\t\t\tp_target_verts[index + 0].v\t\t= p_array_loop[0].v;\r\n\t\t\t\t\t\t\t\t\tp_target_verts[index + 1].u\t\t= p_array_loop[1].u;\r\n\t\t\t\t\t\t\t\t\tp_target_verts[index + 1].v\t\t= p_array_loop[1].v;\r\n\t\t\t\t\t\t\t\t\tp_target_verts[index + 2].u\t\t= p_array_loop[2].u;\r\n\t\t\t\t\t\t\t\t\tp_target_verts[index + 2].v\t\t= p_array_loop[2].v;\r\n\t\t\t\t\r\n\t\t\t\t\t\t\t\t\tp_target_verts[index + 0].col\t= p_array_loop[0].col;\r\n\t\t\t\t\t\t\t\t\tp_target_verts[index + 1].col\t= p_array_loop[1].col;\r\n\t\t\t\t\t\t\t\t\tp_target_verts[index + 2].col\t= p_array_loop[2].col;\r\n\t\t\t\t\r\n\t\t\t\t\t\t\t\t\tidx\t\t\t\t\t\t\t\t= p_details->GetOldestSplat();\r\n\t\t\t\t\t\t\t\t\tindex\t\t\t\t\t\t\t= idx * 3;\r\n\t\t\t\t\t\t\t\t\tDbg_Assert((index + 2) < (SPLAT_POLYS_PER_MESH * 3));\r\n\t\t\t\t\t\t\t\t\tno_polys \t\t\t\t\t\t= false;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t\t\t\t\tp_array_loop\t\t\t\t\t+= 3;\r\n\t\t\t\t//\t\t\t\tvert_idx++;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t\t\t\tdelete [] p_array_start;\r\n\t\t\t\t\r\n\t\t\t\t\t\t\t// Check if all the new polys were rejected.  Don't know why this happens, but we want\r\n\t\t\t\t\t\t\t// to get rid of the original texture.\r\n\t\t\t\t\t\t\tif (no_polys)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tplat_texture_splat_reset_poly( p_details, idx );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t\r\n\r\n\t//\t\t\t\t\t\tOSReport( \"Add U0: %6.1f %6.1f\\n\", p_target_verts[index + 0].u, p_target_verts[index + 0].v );\r\n\t//\t\t\t\t\t\tOSReport( \"Add U1: %6.1f %6.1f\\n\", p_target_verts[index + 1].u, p_target_verts[index + 1].v );\r\n\t//\t\t\t\t\t\tOSReport( \"Add U2: %6.1f %6.1f\\n\", p_target_verts[index + 2].u, p_target_verts[index + 2].v );\r\n\r\n\t#\t\t\t\t\t\tif DRAW_DEBUG_LINES\r\n\t//\t\t\t\t\t\tD3DXVECTOR3* p_d3dvert;\r\n\t//\t\t\t\t\t\tp_d3dvert = (D3DXVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index0 ));\r\n\t//\t\t\t\t\t\tMth::Vector v0( p_d3dvert->x, p_d3dvert->y, p_d3dvert->z );\r\n\t//\t\t\t\t\t\tp_d3dvert = (D3DXVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index1 ));\r\n\t//\t\t\t\t\t\tMth::Vector v1( p_d3dvert->x, p_d3dvert->y, p_d3dvert->z );\r\n\t//\t\t\t\t\t\tp_d3dvert = (D3DXVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index2 ));\r\n\t//\t\t\t\t\t\tMth::Vector v2( p_d3dvert->x, p_d3dvert->y, p_d3dvert->z );\r\n\t//\t\t\t\t\t\tGfx::AddDebugLine( v0, v1, MAKE_RGB( 0, 200, 200 ), MAKE_RGB( 0, 200, 200 ), 1 );\r\n\t//\t\t\t\t\t\tGfx::AddDebugLine( v1, v2, MAKE_RGB( 0, 200, 200 ), MAKE_RGB( 0, 200, 200 ), 1 );\r\n\t//\t\t\t\t\t\tGfx::AddDebugLine( v2, v0, MAKE_RGB( 0, 200, 200 ), MAKE_RGB( 0, 200, 200 ), 1 );\r\n\r\n\t//\t\t\t\t\t\tv0[Y] += 10;\r\n\t//\t\t\t\t\t\tv1[Y] += 10;\r\n\t//\t\t\t\t\t\tv2[Y] += 10;\r\n\r\n\t\t\t\t\t\t\tADD_LINE( v0, v1, 0, 200, 200 );\r\n\t\t\t\t\t\t\tADD_LINE( v1, v2, 0, 200, 200 );\r\n\t\t\t\t\t\t\tADD_LINE( v2, v0, 0, 200, 200 );\r\n\t#\t\t\t\t\t\tendif // DRAW_DEBUG_LINES\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t++pp_sectors;\r\n\t}\r\n#endif\t\t// 0\r\n\t\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_texture_splat_render( void )\r\n{\r\n#if 0\r\n//#\tif DRAW_DEBUG_LINES\r\n//#\tendif \t\t//DRAW_DEBUG_LINES\r\n//\r\n\r\n\r\n\tsNgcSplatInstanceDetails *p_Ngc_details;\r\n\r\n\tDbg_Assert( p_splat_details_table );\r\n\r\n\tp_splat_details_table->IterateStart();\r\n\tsSplatInstanceDetails *p_details = p_splat_details_table->IterateNext();\r\n\twhile( p_details )\r\n\t{\r\n\t\tp_Ngc_details = static_cast<sNgcSplatInstanceDetails*>( p_details );\r\n\r\n\t\tif( p_Ngc_details->m_highest_active_splat >= 0 )\r\n\t\t{\r\n//\t\t\tNxNgc::multi_mesh( &p_Ngc_details->m_mat, &p_Ngc_details->m_pass, true, true );\r\n\r\n\t\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\t\t\r\n//\t\t\tNxNgc::sMaterialHeader mat;\r\n//\t\t\tNxNgc::sMaterialPassHeader pass;\r\n//\t\t\r\n//\t\t\tmat.m_checksum\t\t\t= 0;\r\n//\t\t\tmat.m_passes\t\t\t= 1;\r\n//\t\t\tmat.m_alpha_cutoff\t\t= 0;\r\n//\t\t\tmat.m_flags\t\t\t\t= 0;\r\n//\t\t\tmat.m_material_dl_id\t= 0;\r\n//\t\t\tmat.m_draw_order\t\t= 0;\r\n//\t\t\tmat.m_pass_item\t\t\t= 0;\r\n//\t\t\tmat.m_texture_dl_id\t\t= 0;\r\n//\t\t\r\n//\t\t\tpass.m_texture.p_data\t= p_Ngc_details->mp_texture;\r\n//\t\t\tpass.m_flags\t\t\t= (1<<0)|(1<<5)|(1<<6);\r\n//\t\t\tpass.m_filter\t\t\t= 0;\r\n//\t\t\tpass.m_blend_mode\t\t= (unsigned char)NxNgc::vBLEND_MODE_BLEND;\r\n//\t\t\tpass.m_alpha_fix\t\t= 128;\r\n//\t\t\tpass.m_uv_wibble_index\t= 0;\r\n//\t\t\tpass.m_color\t\t\t= (GXColor){128,128,128,255};\r\n//\t\t\tpass.m_k\t\t\t\t= 0;\r\n//\t\t\tpass.m_u_tile\t\t\t= 0;\r\n//\t\t\tpass.m_v_tile\t\t\t= 0;\r\n//\t\t\r\n//\t\t\tmulti_mesh( &mat, &pass, true, true );\r\n\r\n\r\n\r\n\r\n\r\n//\t\t\tGX::SetPointSize( 6, GX_TO_ONE );\r\n//\r\n//\t\t\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );\r\n//\t\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n//\t\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n//\t\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n//\r\n//\t\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\r\n//\t\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n//\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n//\t\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\t\t\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,0,255,255} );\r\n//\r\n//\t\t\tGX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n//\r\n//\t\t\tsNgcVert *p_vert_array = p_Ngc_details->m_verts;\r\n//\t\t\tfor (int i = 0; i < ( p_details->m_highest_active_splat + 1 ); i++, p_vert_array += 3)\r\n//\t\t\t{\r\n////\t\t\t\tprintf( \"Splat Tri:\\n%8.3f %8.3f %8.3f\\n\", p_vert_array[0].pos[X], p_vert_array[0].pos[Y], p_vert_array[0].pos[Z] );\r\n////\t\t\t\tprintf( \"%8.3f %8.3f %8.3f\\n\", p_vert_array[1].pos[X], p_vert_array[1].pos[Y], p_vert_array[1].pos[Z] );\r\n////\t\t\t\tprintf( \"%8.3f %8.3f %8.3f\\n\", p_vert_array[2].pos[X], p_vert_array[2].pos[Y], p_vert_array[2].pos[Z] );\r\n//\t\t\t\tGX::Begin( GX_LINES, GX_VTXFMT0, 2 ); \r\n//\t\t\t\tGX::Position3f32( p_vert_array[0].pos[X], p_vert_array[0].pos[Y], p_vert_array[0].pos[Z] );\r\n//\t\t\t\tGX::Position3f32( p_vert_array[1].pos[X], p_vert_array[1].pos[Y], p_vert_array[1].pos[Z] );\r\n//\t\t\t\tGX::End(); \r\n//\t\t\t\tGX::Begin( GX_LINES, GX_VTXFMT0, 2 ); \r\n//\t\t\t\tGX::Position3f32( p_vert_array[1].pos[X], p_vert_array[1].pos[Y], p_vert_array[1].pos[Z] );\r\n//\t\t\t\tGX::Position3f32( p_vert_array[2].pos[X], p_vert_array[2].pos[Y], p_vert_array[2].pos[Z] );\r\n//\t\t\t\tGX::End(); \r\n//\t\t\t\tGX::Begin( GX_LINES, GX_VTXFMT0, 2 ); \r\n//\t\t\t\tGX::Position3f32( p_vert_array[2].pos[X], p_vert_array[2].pos[Y], p_vert_array[2].pos[Z] );\r\n//\t\t\t\tGX::Position3f32( p_vert_array[0].pos[X], p_vert_array[0].pos[Y], p_vert_array[0].pos[Z] );\r\n//\t\t\t\tGX::End(); \r\n//\t\t\t}\r\n////\t\t\tGX::End();\r\n//\r\n//\r\n\r\n\r\n\r\n\r\n\r\n\t\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t\t\tGX::UploadTexture(  p_Ngc_details->mp_texture->pTexelData,\r\n\t\t\t\t\t\t\t\tp_Ngc_details->mp_texture->ActualWidth,\r\n\t\t\t\t\t\t\t\tp_Ngc_details->mp_texture->ActualHeight,\r\n\t\t\t\t\t\t\t\tGX_TF_CMPR,\r\n\t\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\t\tGX_TRUE,\r\n\t\t\t\t\t\t\t\tGX_ANISO_1,\r\n\t\t\t\t\t\t\t\tGX_TEXMAP0 ); \r\n\t\t\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, p_Ngc_details->mp_texture->ActualWidth, p_Ngc_details->mp_texture->ActualHeight );\r\n\t\t\r\n\t\t\tGX::SetTexChanTevIndCull( 1, 0, 1, 0, GX_CULL_NONE );\r\n\t\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\t\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\t\t\r\n\t\t\tGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0 );\r\n\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\t\t// Replace\r\n//\t\t\tGX::SetBlendMode( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\r\n\t\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\t\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );\r\n\r\n\r\n\t\t\tf32 pm[GX_PROJECTION_SZ];\r\n\t\t\tGX::GetProjectionv( pm );\r\n\t\t\tfloat value = pm[6] + ( 150.0f * 5 ) * pm[5];\r\n\r\n\t\t\tGXWGFifo.u8 = GX_LOAD_XF_REG;\r\n\t\t\tGXWGFifo.u16 = 0;\r\n\t\t\tGXWGFifo.u16 = 0x1025;\r\n\t\t\tGXWGFifo.f32 = value;\r\n\r\n\r\n//\t\t\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n//\t\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t\t\t// Render the triangles\r\n\t\t\tGX::SetVtxDesc( 3, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n//\t\t\tGX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n\t\t\tGX::Begin( GX_TRIANGLES, GX_VTXFMT6, ( p_details->m_highest_active_splat + 1 ) * 3 ); \r\n\t\t\tsNgcVert *p_vert_array = p_Ngc_details->m_verts;\r\n\t\t\tfor (int i = 0; i < ( p_details->m_highest_active_splat + 1 ); i++, p_vert_array += 3)\r\n\t\t\t{\r\n\t\t\t\tGX::Position3f32( p_vert_array[0].pos[X], p_vert_array[0].pos[Y], p_vert_array[0].pos[Z] );\r\n\t\t\t\tGX::Color1u32(*((u32*)&(p_vert_array[0].col)));\r\n\t\t\t\tGX::TexCoord2s16( p_vert_array[0].u, p_vert_array[0].v );\r\n\r\n\t\t\t\tGX::Position3f32( p_vert_array[1].pos[X], p_vert_array[1].pos[Y], p_vert_array[1].pos[Z] );\r\n\t\t\t\tGX::Color1u32(*((u32*)&(p_vert_array[1].col)));\r\n\t\t\t\tGX::TexCoord2s16( p_vert_array[1].u, p_vert_array[1].v );\r\n\r\n\t\t\t\tGX::Position3f32( p_vert_array[2].pos[X], p_vert_array[2].pos[Y], p_vert_array[2].pos[Z] );\r\n\t\t\t\tGX::Color1u32(*((u32*)&(p_vert_array[2].col)));\r\n\t\t\t\tGX::TexCoord2s16( p_vert_array[2].u, p_vert_array[2].v );\r\n\r\n//\t\t\t\tGX::Position3f32( 0.0f, 0.0f, 0.0f );\r\n//\t\t\t\tGX::Position3f32( 0.0f, 0.0f, 0.0f );\r\n//\t\t\t\tGX::Position3f32( 0.0f, 0.0f, 0.0f );\r\n//\t\t\t\tGX::Position3f32( 0.0f, 0.0f, 0.0f );\r\n//  \t\t\tGX::Position3f32( 0.0f, 0.0f, 0.0f );\r\n//\t\t\t\tGX::Position3f32( 0.0f, 0.0f, 0.0f );\r\n\t\t\t}\r\n\t\t\tGX::End();\r\n\t\t}\r\n\t\t\r\n\t\tp_details = p_splat_details_table->IterateNext();\r\n\t}\r\n#endif\t\t// 0\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_shatter_initialize( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_shatter_cleanup( void )\r\n{\r\n\tsNgcShatterInstanceDetails *p_Ngc_details;\r\n\r\n\tDbg_Assert( p_shatter_details_table );\r\n\t\r\n\tp_shatter_details_table->IterateStart();\r\n\tsShatterInstanceDetails *p_details = p_shatter_details_table->IterateNext();\r\n\twhile( p_details )\r\n\t{\r\n\t\tp_Ngc_details = static_cast<sNgcShatterInstanceDetails*>( p_details );\r\n\t\t\r\n\t\tp_details = p_shatter_details_table->IterateNext();\r\n\r\n\t\tp_shatter_details_table->FlushItem((uint32)p_Ngc_details );\r\n\t\tdelete p_Ngc_details;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_shatter( CGeom *p_geom )\r\n{\r\n#if 1\r\n\tCNgcGeom *p_Ngc_geom = static_cast<CNgcGeom*>( p_geom );\r\n\r\n\t// For each mesh in the geom...\r\n\tfor( uint32 m = 0; m < p_Ngc_geom->m_num_mesh; ++m )\r\n\t{\r\n\t\tNxNgc::sMesh *p_mesh = p_Ngc_geom->m_mesh_array[m];\r\n\r\n\t\tNxNgc::sScene *p_scene = p_Ngc_geom->mp_scene->GetEngineScene();\r\n\r\n\t\t// Count indices.\r\n\t\tint num_indices = 0;\r\n\t\tunsigned char * p_start = (unsigned char *)&p_mesh->mp_dl[1];\r\n\t\tuint32 cp = (p_start[2]<<24)|(p_start[3]<<16)|(p_start[4]<<8)|p_start[5];\r\n\t\tunsigned char * p_end = &p_start[p_mesh->mp_dl->m_size];\r\n\t\tp_start = &p_start[p_mesh->mp_dl->m_index_offset];\t\t// Skip to actual 1st GDBegin.\r\n\t\tunsigned char * p8 = p_start;\r\n\r\n\t\tint stride = p_mesh->mp_dl->m_index_stride;\r\n\r\n\t\tunsigned char * p_index_buffer  = &p8[1];\r\n\r\n\t\tint off = 2 + ( ( cp & ((1<<11)|(1<<12)) ) ? 2 : 0 );\r\n\r\n\t\tGXVtxFmt format = GX_VTXFMT2;\r\n\r\n\t\twhile ( p8 < p_end )\r\n\t\t{\r\n\t\t\tif ( ( p8[0] & 0xf8 ) == GX_TRIANGLESTRIP )\r\n\t\t\t{\r\n\t\t\t\tformat = (GXVtxFmt)(p8[0] & 7);\r\n\t\t\t\t// Found a triangle strip - parse it.\r\n\t\t\t\tint num_verts = ( p8[1] << 8 ) | p8[2];\r\n\t\t\t\tp8 += 3;\t\t// Skip GDBegin\r\n\r\n\t\t\t\tnum_indices += num_verts;\r\n\r\n\t\t\t\tp8 += stride * 2 * num_verts;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( num_indices >= 3 )\r\n\t\t{\r\n\t\t\ttriSubdivideStack.SetBlockSize( sizeof( sNgcVert ) );\r\n\r\n\t\t\t// Create the index buffer.\r\n\t\t\tuint polys = 0;\r\n\t\t\tuint16 idxbuf[1024*3];\t\t// 6k.\r\n\t\t\tuint16 cidxbuf[1024*3];\t\t// 6k.\r\n\t\t\tuint16 tidxbuf[1024*3];\t\t// 6k.\r\n\t\t\tuint16 * p_dest = idxbuf;\r\n\t\t\tuint16 * p_cdest = cidxbuf;\r\n\t\t\tuint16 * p_tdest = tidxbuf;\r\n\t\t\tuint8 * p_source = (uint8*)p_index_buffer;\r\n\t\t\tuint16 total = 0;\r\n\r\n\t\t\twhile ( total < num_indices )\r\n\t\t\t{\r\n\t\t\t\tuint16 num = ( p_source[0] << 8 ) | p_source[1];\r\n\t\t\t\tp_source += 2;\r\n\t\t\t\tuint16 i0, ci0, ti0;\r\n\t\t\t\tuint16 i1 = ( p_source[0] << 8 ) | p_source[1];\r\n\t\t\t\tuint16 ci1 = ( p_source[off+0] << 8 ) | p_source[off+1];\r\n\t\t\t\tuint16 ti1 = ( p_source[off+2] << 8 ) | p_source[off+3];\r\n\t\t\t\tp_source += stride * 2;\r\n\t\t\t\tuint16 i2 = ( p_source[0] << 8 ) | p_source[1];\r\n\t\t\t\tuint16 ci2 = ( p_source[off+0] << 8 ) | p_source[off+1];\r\n\t\t\t\tuint16 ti2 = ( p_source[off+2] << 8 ) | p_source[off+3];\r\n\t\t\t\tp_source += stride * 2;\r\n\t\t\t\tfor ( int vv = 2; vv < num; vv++ )\r\n\t\t\t\t{\r\n\t\t\t\t\ti0 = i1;\r\n\t\t\t\t\ti1 = i2;\r\n\t\t\t\t\ti2 = ( p_source[0] << 8 ) | p_source[1];\r\n\t\t\t\t\tci0 = ci1;\r\n\t\t\t\t\tci1 = ci2;\r\n\t\t\t\t\tci2 = ( p_source[off+0] << 8 ) | p_source[off+1];\r\n\t\t\t\t\tti0 = ti1;\r\n\t\t\t\t\tti1 = ti2;\r\n\t\t\t\t\tti2 = ( p_source[off+2] << 8 ) | p_source[off+3];\r\n\t\t\t\t\tp_source += stride * 2;\r\n\t\t\t\t\t*p_dest++ = i0;\r\n\t\t\t\t\t*p_dest++ = i1;\r\n\t\t\t\t\t*p_dest++ = i2;\r\n\t\t\t\t\t*p_cdest++ = ci0;\r\n\t\t\t\t\t*p_cdest++ = ci1;\r\n\t\t\t\t\t*p_cdest++ = ci2;\r\n\t\t\t\t\t*p_tdest++ = ti0;\r\n\t\t\t\t\t*p_tdest++ = ti1;\r\n\t\t\t\t\t*p_tdest++ = ti2;\r\n\t\t\t\t\tpolys++;\r\n\t\t\t\t}\r\n\t\t\t\tp_source += 1;\r\n\t\t\t\ttotal += num + 1;\t\t// Count each index + the count.\r\n\t\t\t}\r\n\r\n\t\t\t// First scan through each non-degenerate tri, counting them to see how many verts we'll need.\r\n\t\t\t// We also have to figure the area of the tris here, since we need to calculate the worst case given the requirements for subdivision.\r\n\t\t\tuint32 valid_tris\t= 0;\r\n\t\t\tfor( uint32 i = 0; i < polys; ++i )\r\n\t\t\t{\r\n\t\t\t\t// Wrap the indices round.\r\n\t\t\t\tuint16 index0 = idxbuf[(i*3)+0];\r\n\t\t\t\tuint16 index1 = idxbuf[(i*3)+1];\r\n\t\t\t\tuint16 index2 = idxbuf[(i*3)+2];\r\n\r\n\t\t\t\tuint16 cindex0 = cidxbuf[(i*3)+0];\r\n\t\t\t\tuint16 cindex1 = cidxbuf[(i*3)+1];\r\n\t\t\t\tuint16 cindex2 = cidxbuf[(i*3)+2];\r\n\r\n\t\t\t\tuint16 tindex0 = tidxbuf[(i*3)+0];\r\n\t\t\t\tuint16 tindex1 = tidxbuf[(i*3)+1];\r\n\t\t\t\tuint16 tindex2 = tidxbuf[(i*3)+2];\r\n\r\n\t\t\t\tif(( index0 != index1 ) && ( index0 != index2 ) && ( index1 != index2 ))\r\n\t\t\t\t{\r\n\t\t\t\t\t++valid_tris;\r\n\r\n\t\t\t\t\tsNgcVert v0;\r\n\t\t\t\t\tsNgcVert v1;\r\n\t\t\t\t\tsNgcVert v2;\r\n\r\n\t\t\t\t\tif ( p_mesh->mp_dl->mp_pos_pool )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tv0.pos.Set( p_mesh->mp_dl->mp_pos_pool[(index0*3)+0],\r\n\t\t\t\t\t\t\t\t\tp_mesh->mp_dl->mp_pos_pool[(index0*3)+1],\r\n\t\t\t\t\t\t\t\t\tp_mesh->mp_dl->mp_pos_pool[(index0*3)+2] );\r\n\t\t\t\t\t\tv1.pos.Set( p_mesh->mp_dl->mp_pos_pool[(index1*3)+0],\r\n\t\t\t\t\t\t\t\t\tp_mesh->mp_dl->mp_pos_pool[(index1*3)+1],\r\n\t\t\t\t\t\t\t\t\tp_mesh->mp_dl->mp_pos_pool[(index1*3)+2] );\r\n\t\t\t\t\t\tv2.pos.Set( p_mesh->mp_dl->mp_pos_pool[(index2*3)+0],\r\n\t\t\t\t\t\t\t\t\tp_mesh->mp_dl->mp_pos_pool[(index2*3)+1],\r\n\t\t\t\t\t\t\t\t\tp_mesh->mp_dl->mp_pos_pool[(index2*3)+2] );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tv0.pos.Set( p_scene->mp_pos_pool[(index0*3)+0],\r\n\t\t\t\t\t\t\t\t\tp_scene->mp_pos_pool[(index0*3)+1],\r\n\t\t\t\t\t\t\t\t\tp_scene->mp_pos_pool[(index0*3)+2] );\r\n\t\t\t\t\t\tv1.pos.Set( p_scene->mp_pos_pool[(index1*3)+0],\r\n\t\t\t\t\t\t\t\t\tp_scene->mp_pos_pool[(index1*3)+1],\r\n\t\t\t\t\t\t\t\t\tp_scene->mp_pos_pool[(index1*3)+2] );\r\n\t\t\t\t\t\tv2.pos.Set( p_scene->mp_pos_pool[(index2*3)+0],\r\n\t\t\t\t\t\t\t\t\tp_scene->mp_pos_pool[(index2*3)+1],\r\n\t\t\t\t\t\t\t\t\tp_scene->mp_pos_pool[(index2*3)+2] );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( p_scene->mp_col_pool )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( p_mesh->mp_dl->mp_col_pool )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tv0.col = *((GXColor*)&p_mesh->mp_dl->mp_col_pool[cindex0]);\r\n\t\t\t\t\t\t\tv1.col = *((GXColor*)&p_mesh->mp_dl->mp_col_pool[cindex1]);\r\n\t\t\t\t\t\t\tv2.col = *((GXColor*)&p_mesh->mp_dl->mp_col_pool[cindex2]);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tv0.col = *((GXColor*)&p_scene->mp_col_pool[cindex0]);\r\n\t\t\t\t\t\t\tv1.col = *((GXColor*)&p_scene->mp_col_pool[cindex1]);\r\n\t\t\t\t\t\t\tv2.col = *((GXColor*)&p_scene->mp_col_pool[cindex2]);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( p_scene->mp_tex_pool )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tv0.u = p_scene->mp_tex_pool[(tindex0*2)+0];\r\n\t\t\t\t\t\tv0.v = p_scene->mp_tex_pool[(tindex0*2)+1];\r\n\t\t\t\t\t\tv1.u = p_scene->mp_tex_pool[(tindex1*2)+0];\r\n\t\t\t\t\t\tv1.v = p_scene->mp_tex_pool[(tindex1*2)+1];\r\n\t\t\t\t\t\tv2.u = p_scene->mp_tex_pool[(tindex2*2)+0];\r\n\t\t\t\t\t\tv2.v = p_scene->mp_tex_pool[(tindex2*2)+1];\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tv0.pos[W] = v1.pos[W] = v2.pos[W] = 1.0f;\t\t// Make sure they are points, not vectors\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Push this tri onto the stack.\r\n\t\t\t\t\ttriSubdivideStack.Push( &v0 );\r\n\t\t\t\t\ttriSubdivideStack.Push( &v1 );\r\n\t\t\t\t\ttriSubdivideStack.Push( &v2 );\r\n\r\n\t\t\t\t\t// Figure the area of this tri.\r\n\t\t\t\t\tMth::Vector p( v1.pos[X] - v0.pos[X], v1.pos[Y] - v0.pos[Y], v1.pos[Z] - v0.pos[Z], 0.0f );\r\n\t\t\t\t\tMth::Vector q( v2.pos[X] - v0.pos[X], v2.pos[Y] - v0.pos[Y], v2.pos[Z] - v0.pos[Z], 0.0f );\r\n\t\t\t\t\tMth::Vector r(( p[Y] * q[Z] ) - ( q[Y] * p[Z] ), ( p[Z] * q[X] ) - ( q[Z] * p[X] ), ( p[X] * q[Y] ) - ( q[X] * p[Y] ), 0.0f);\r\n\t\t\t\t\tfloat area_squared = r.LengthSqr();\r\n\t\t\t\t\tif( area_squared > shatterAreaTest )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// We will need to subdivide - each subdivision will result in an area one quarter the previous area\r\n\t\t\t\t\t\t// (and thusly the square of the area will be one sixteenth the previous area).\r\n\t\t\t\t\t\tint num_extra_tris = 1;\r\n\t\t\t\t\t\twhile( area_squared > shatterAreaTest )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnum_extra_tris *= 4;\r\n\t\t\t\t\t\t\tarea_squared *= ( 1.0f / 16.0f );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t// This original tri will not be added...\r\n\t\t\t\t\t\t--valid_tris;\r\n\r\n\t\t\t\t\t\t// ...however, the subdivided versions will.\r\n\t\t\t\t\t\tvalid_tris += num_extra_tris;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif( valid_tris == 0 )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Create a tracking structure for this mesh.\r\n\t\t\tsNgcShatterInstanceDetails *p_details\t\t= new sNgcShatterInstanceDetails( valid_tris, p_mesh, p_scene, format );\r\n\t\t\tsNgcVert\t\t\t\t   *p_write_vertex\t= p_details->mp_vertex_buffer;\r\n\t\t\tuint32\t\t\t\t\t\tdetails_index\t= 0;\r\n\r\n\t\t\tMth::Vector\t\t\t\t\tspread_center\t= shatterVelocity * -shatterSpreadFactor;\r\n\t\t\tfloat\t\t\t\t\t\tbase_speed\t\t= shatterVelocity.Length();\r\n\r\n\t\t\tspread_center[X] += p_mesh->mp_dl->m_sphere[0];\r\n\t\t\tspread_center[Y] += p_mesh->mp_dl->m_sphere[1];\r\n\t\t\tspread_center[Z] += p_mesh->mp_dl->m_sphere[2];\r\n\t\t\t\r\n\t\t\t// Add the tracking structure to the table.\r\n\t\t\tp_shatter_details_table->PutItem((uint32)p_details, p_details );\r\n\t\t\t\r\n\t\t\t// Process-subdivide the entire stack.\r\n\t\t\tsNgcVert *p_copy_vertex = p_write_vertex;\r\n\t\t\twhile( subdivide_tri_stack( &p_write_vertex, p_mesh ));\r\n\t\t\t\t\t\r\n\t\t\t// Copy the (possibly subdivided) vertex data over.\r\n\t\t\twhile( p_copy_vertex < p_write_vertex )\r\n\t\t\t{\r\n\t\t\t\tMth::Vector *p_vert0 = &p_copy_vertex[0].pos;\r\n\t\t\t\tMth::Vector *p_vert1 = &p_copy_vertex[1].pos;\r\n\t\t\t\tMth::Vector *p_vert2 = &p_copy_vertex[2].pos;\r\n\t\t\t\t\r\n\t\t\t\t// Calculate position as the midpoint of the three vertices per poly.\r\n\t\t\t\tp_details->mp_positions[details_index][X] = ( p_vert0->GetX() + p_vert1->GetX() + p_vert2->GetX() ) * ( 1.0f / 3.0f );\r\n\t\t\t\tp_details->mp_positions[details_index][Y] = ( p_vert0->GetY() + p_vert1->GetY() + p_vert2->GetY() ) * ( 1.0f / 3.0f );\r\n\t\t\t\tp_details->mp_positions[details_index][Z] = ( p_vert0->GetZ() + p_vert1->GetZ() + p_vert2->GetZ() ) * ( 1.0f / 3.0f );\r\n\r\n\t\t\t\t// Calculate the vector <velocity> back from the bounding box of the object. Then use this to figure the 'spread' of the\r\n\t\t\t\t// shards by calculating the vector from this position to the center of each shard.\r\n\t\t\t\tfloat speed = base_speed + ( base_speed * (( shatterVelocityVariance * rand() ) / RAND_MAX ));\r\n\t\t\t\tp_details->mp_velocities[details_index] = ( p_details->mp_positions[details_index] - spread_center ).Normalize( speed );\r\n\r\n\t\t\t\tMth::Vector axis( -1.0f + ( 2.0f * (float)rand() / RAND_MAX ), -1.0f + ( 2.0f * (float)rand() / RAND_MAX ), -1.0f + ( 2.0f * (float)rand() / RAND_MAX ));\r\n\t\t\t\taxis.Normalize();\r\n\t\t\t\tp_details->mp_matrices[details_index].Ident();\r\n\t\t\t\tp_details->mp_matrices[details_index].Rotate( axis, 0.1f * ((float)rand() / RAND_MAX ));\r\n\r\n\t\t\t\tp_copy_vertex += 3;\r\n\t\t\t\t\t\t\r\n\t\t\t\t++details_index;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\n\r\n\r\n/******************************************************************************\r\n *\r\n * \r\n *****************************************************************************/\r\nvoid plat_shatter_update( sShatterInstanceDetails *p_details, float framelength )\r\n{\r\n\tsNgcShatterInstanceDetails *p_Ngc_details = static_cast<sNgcShatterInstanceDetails*>( p_details );\r\n\t\r\n\tsNgcVert *p_vert_data = p_Ngc_details->mp_vertex_buffer;\r\n\t\r\n\tfor( int i = 0; i < p_details->m_num_triangles; ++i )\r\n\t{\r\n\t\tMth::Vector *p_v0\t= &p_vert_data[(i*3)+0].pos;\r\n\t\tMth::Vector *p_v1\t= &p_vert_data[(i*3)+1].pos;\r\n\t\tMth::Vector *p_v2\t= &p_vert_data[(i*3)+2].pos;\r\n\t\t// To move the shatter pieces:\r\n\t\t// 1) subtract position from each vertex\r\n\t\t// 2) rotate\r\n\t\t// 3) update position with velocity\r\n\t\t// 4) add new position to each vertex\r\n\r\n\t\t// The matrix holds 3 vectors at once.\r\n\t\tMth::Matrix m;\r\n\t\tm[X].Set( p_v0->GetX() - p_details->mp_positions[i][X], p_v0->GetY() - p_details->mp_positions[i][Y], p_v0->GetZ() - p_details->mp_positions[i][Z] );\r\n\t\tm[Y].Set( p_v1->GetX() - p_details->mp_positions[i][X], p_v1->GetY() - p_details->mp_positions[i][Y], p_v1->GetZ() - p_details->mp_positions[i][Z] );\r\n\t\tm[Z].Set( p_v2->GetX() - p_details->mp_positions[i][X], p_v2->GetY() - p_details->mp_positions[i][Y], p_v2->GetZ() - p_details->mp_positions[i][Z] );\r\n         \r\n\t\tm[X].Rotate( p_details->mp_matrices[i] );\r\n\t\tm[Y].Rotate( p_details->mp_matrices[i] );\r\n\t\tm[Z].Rotate( p_details->mp_matrices[i] );\r\n\r\n\t\t// Update the position and velocity of the shatter piece, dealing with bouncing if necessary.\r\n\t\tp_details->UpdateParameters( i, framelength );\r\n      \r\n\t\tm[X] += p_details->mp_positions[i]; \r\n\t\tm[Y] += p_details->mp_positions[i]; \r\n\t\tm[Z] += p_details->mp_positions[i];\r\n\r\n\t\tp_v0->Set( m[X][X], m[X][Y], m[X][Z] );\r\n\t\tp_v1->Set( m[Y][X], m[Y][Y], m[Y][Z] );\r\n\t\tp_v2->Set( m[Z][X], m[Z][Y], m[Z][Z] );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************************\r\n *\r\n * \r\n *****************************************************************************/\r\nvoid plat_shatter_render( sShatterInstanceDetails *p_details )\r\n{\r\n\tsNgcShatterInstanceDetails *p_Ngc_details = static_cast<sNgcShatterInstanceDetails*>( p_details );\r\n\r\n\tDbg_Assert( p_Ngc_details );\r\n\r\n//\tp_Ngc_details->mp_mesh->mp_material->Submit( 0, (GXColor){0,0,0,0} );\r\n\r\n\tNxNgc::MaterialSubmit( p_Ngc_details->mp_mesh, p_Ngc_details->mp_scene );\r\n\tGX::SetChanCtrl( GX_COLOR0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\tGX::SetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ); \r\n//\tGX::SetChanMatColor( GX_COLOR0A0, p_Ngc_details->mp_mesh->m_base_color );\r\n\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){128,128,128,255} );\r\n\r\n//\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_IDENTITY );\r\n\r\n\t// Render the triangles\r\n\tGX::SetVtxDesc( 3, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\tGX::Begin( GX_TRIANGLES, p_Ngc_details->m_vertex_format, p_Ngc_details->m_num_triangles * 3 ); \r\n\tsNgcVert *p_vert_array = p_Ngc_details->mp_vertex_buffer;\r\n\tfor (int i = 0; i < p_Ngc_details->m_num_triangles; i++, p_vert_array += 3)\r\n\t{\r\n\t\tGX::Position3f32( p_vert_array[0].pos[X], p_vert_array[0].pos[Y], p_vert_array[0].pos[Z] );\r\n\t\tGX::Color1u32(*((u32*)&(p_vert_array[0].col)));\r\n\t\tGX::TexCoord2s16( p_vert_array[0].u, p_vert_array[0].v );\r\n\r\n\t\tGX::Position3f32( p_vert_array[1].pos[X], p_vert_array[1].pos[Y], p_vert_array[1].pos[Z] );\r\n\t\tGX::Color1u32(*((u32*)&(p_vert_array[1].col)));\r\n\t\tGX::TexCoord2s16( p_vert_array[1].u, p_vert_array[1].v );\r\n\r\n\t\tGX::Position3f32( p_vert_array[2].pos[X], p_vert_array[2].pos[Y], p_vert_array[2].pos[Z] );\r\n\t\tGX::Color1u32(*((u32*)&(p_vert_array[2].col)));\r\n\t\tGX::TexCoord2s16( p_vert_array[2].u, p_vert_array[2].v );\r\n\t}\r\n\tGX::End();\r\n}\r\n\r\n\t\r\n\t\r\n///////////////////////////////////////////////////////////////////\r\n//\r\n// FOG\r\n//\r\n///////////////////////////////////////////////////////////////////\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic bool\t\tfogEnabled\t\t\t= false;\r\nstatic GXColor\tfogColor\t\t\t= (GXColor){ 0, 0, 0, 0 };\r\nstatic float\tfogNear\t\t\t\t= 0.0f;\r\nstatic float\tfogFar\t\t\t\t= 0.0f;\r\n\r\nvoid\t\tCFog::s_plat_enable_fog(bool enable)\r\n{\r\n\tif( enable != fogEnabled )\r\n\t{\r\n\t\t// If we're disabling, reset to default values.\r\n\t\tif ( !enable )\r\n\t\t{\r\n\t\t\tfogColor\t= (GXColor){ 0, 0, 0, 0 };\r\n\t\t\tfogNear\t\t= 0.0f;\r\n\t\t\tfogFar\t\t= 0.0f;\r\n\t\t}\r\n\r\n\t\tfogEnabled = enable;\r\n\t}\r\n}\r\n\r\nvoid\t\tCFog::s_plat_set_fog_exponent(float exponent)\r\n{\r\n//\tDbg_Message(\"Stub: CFog::SetFogExponent()\");\r\n}\r\n\r\nvoid\t\tCFog::s_plat_set_fog_rgba(Image::RGBA rgba)\r\n{\r\n\tfogColor.r = rgba.r;\r\n\tfogColor.g = rgba.g;\r\n\tfogColor.b = rgba.b;\r\n\tfogColor.a = rgba.a;\r\n//\tfogFar = 1000.0f * ( 128.0f / (float)fogColor.a );\r\n\tfogFar = 20000.0f * ( 128.0f / (float)fogColor.a ); \r\n}\r\n\r\nvoid\t\tCFog::s_plat_set_fog_near_distance(float distance)\r\n{\r\n\tfogNear = distance;\r\n//\tfogFar = 1000.0f * ( 128.0f / (float)fogColor.a );\r\n\tfogFar = 20000.0f * ( 128.0f / (float)fogColor.a ); \r\n}\r\n\r\nvoid\t\tCFog::s_plat_set_fog_color( void )\r\n{\r\n\tGX::SetFogColor( fogColor );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CFog::s_plat_fog_update( void )\r\n{\r\n\tif( fogEnabled )\r\n\t{\r\n\t\tGX::SetFog( GX_FOG_EXP, fogNear, fogFar, 2.0f, 20000.0f, fogColor );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGX::SetFog( GX_FOG_NONE, 0.0f, 0.0f, 0.0f, 0.0f, fogColor );\r\n\t}\r\n}\r\n\t\r\n\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxmodel.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxModel.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/21/2002\r\n//****************************************************************************\r\n\r\n#include <core/math.h>\r\n\r\n#include \"gfx/nxmodel.h\"\r\n#include \"gfx/skeleton.h\"\r\n#include <gfx/Ngc/p_nxmesh.h>\r\n#include \"gfx/Ngc/p_nxmodel.h\"\r\n#include \"gfx/Ngc/p_nxscene.h\"\r\n#include \"gfx/Ngc/nx/import.h\"\r\n#include \"gfx/Ngc/nx/render.h\"\r\n#include \"gfx/Ngc/p_nxgeom.h\"\r\n\r\n#include <sys/ngc/p_display.h>\r\n\r\n\t\t\t   \r\n#include <gel/assman/assman.h>\r\n#include <gel/assman/skinasset.h>\r\n\r\nint\t\t\ttest_num_bones\t\t\t= 0;\r\nMth::Matrix\t*p_test_bone_matrices\t= NULL;\r\nMth::Matrix\ttest_root_matrix;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CNgcModel::plat_init_skeleton( int numBones )\r\n{\r\n//\tif ( !mp_instance ) return false;\r\n//\tMth::Matrix * p_bone = new Mth::Matrix[numBones];\r\n//\r\n//\tmp_instance->SetBoneTransforms( p_bone );\r\n//\tfor ( int i = 0; i < numBones; i++ )\r\n//\t{\r\n//\t\tp_bone[i].Identity();\r\n//\t}\r\n    \r\n\treturn true;\r\n}\r\n\r\n\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//\t\r\n///*\r\n//\tbool CNgcModel::plat_load_file(const char* p_fileName)\r\n//{\r\n//\t// Machine specific code here ............\r\n//\t\r\n//\t// TODO:  Make this more generalized\r\n//\r\n//\t// Load in the texture dictionary for the model.\r\n//\tLst::HashTable< NxNgc::sTexture > *p_texture_table = NxNgc::LoadTextureFile( \"models/testskin/testskin.tex.xbx\" );\r\n//\r\n//    return true;\r\n//}\r\n//*/\r\n//\r\n//\r\n//bool CNgcModel::plat_load_mesh( CMesh* pMesh )\r\n//{\r\n//\t// The skeleton must exist by this point (unless it's a hacked up car).\r\n//\tint numBones;\r\n//\tnumBones = mp_skeleton ? mp_skeleton->GetNumBones() : 1;\r\n//\t\r\n//\tMth::Matrix temp;\r\n//\tCNgcMesh *p_Ngc_mesh = static_cast<CNgcMesh*>( pMesh );\r\n//\tmp_instance = new NxNgc::CInstance( p_Ngc_mesh->GetScene()->GetEngineScene(), temp, numBones, mp_boneTransforms );\r\n//\r\n//    return true;\r\n//}\r\n//\t\r\n//\t\r\n//\t\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//bool CNgcModel::plat_unload_mesh( void )\r\n//{\r\n//\tif ( mp_instance != NULL )\r\n//\t{\r\n//\t\tdelete mp_instance;\r\n//\t\tmp_instance = NULL;\r\n//\t}\r\n//\r\n//\treturn true;\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//\t\r\n//bool CNgcModel::plat_set_render_mode(ERenderMode mode)\r\n//{\r\n//\t// Machine specific code here ............\r\n//    return true;\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//\t\r\n//bool CNgcModel::plat_set_color(uint8 r, uint8 g, uint8 b, uint8 a)\r\n//{\r\n//\t// Machine specific code here ............\r\n//    return true;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//bool CNgcModel::plat_set_visibility(uint32 mask)\r\n//{\r\n//    return true;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//bool CNgcModel::plat_set_active( bool active )\r\n//{\r\n//\tif( mp_instance )\r\n//\t{\r\n//\t\tmp_instance->SetActive( active );\r\n//\t}\r\n//\treturn true;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//bool CNgcModel::plat_set_scale(float scaleFactor)\r\n//{\r\n//\t// Machine specific code here ............\r\n//    return true;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//bool CNgcModel::plat_replace_texture(char* p_srcFileName, char* p_dstFileName)\r\n//{\r\n//\t// Machine specific code here ............\r\n//    return true;\r\n//}\r\n//\r\n//\r\n//\r\n//void ConvertMatrix(Mth::Matrix* pMatrix, void *pMat)\r\n//{\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//bool CNgcModel::plat_render( Mth::Matrix *pRootMatrix, Mth::Matrix *pBoneMatrices, int numBones )\r\n//{\r\n//\tif( mp_instance )\r\n//\t{\r\n//\t\tmp_instance->SetTransform( *pRootMatrix );\r\n//\t}\r\n//    return true;\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CNgcModel::plat_prepare_materials( void )\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CNgcModel::plat_refresh_materials( void )\r\n{\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( int i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tNxNgc::CInstance *p_instance = NULL;\r\n\t\tCNgcGeom * p_ngc_geom = static_cast<CNgcGeom*>( mp_geom[i] ); \r\n\t\tp_instance = p_ngc_geom->GetInstance();\r\n\t\tNxNgc::sScene *p_scene = p_instance->GetScene();\r\n\r\n\t\t// Setup material data texture pointers.\r\n\t\tfor ( unsigned int lp = 0; lp < p_scene->mp_scene_data->m_num_materials; lp++ )\r\n\t\t{\r\n\t\t\tNxNgc::sMaterialHeader * p_mat = &p_scene->mp_material_header[lp];\r\n\t\t\tNxNgc::sTextureDL * p_dl = &p_scene->mp_texture_dl[lp]; \r\n\t\t\tNxNgc::sMaterialPassHeader * p_pass = &p_scene->mp_material_pass[p_mat->m_pass_item];\r\n\r\n\t\t\tGX::ResolveDLTexAddr( p_dl, p_pass, p_mat->m_passes );\r\n\r\n//\t\t\tGX::begin( p_dl->mp_dl, p_dl->m_dl_size );\r\n//\t\t\tmulti_mesh( p_mat, p_pass, true, true );\r\n//\t\t\tp_dl->m_dl_size = GX::end();\r\n\r\n\t\t\t// See if any textures have alpha, but the texture DL doesn't set it up. If so, flag material as\r\n\t\t\t// not using display list.\r\n\t\t\tbool direct = false;\r\n\t\t\tfor ( int p = 0; p < p_mat->m_passes; p++, p_pass++ )\r\n\t\t\t{\r\n\t\t\t\tif ( p_pass->m_texture.p_data )\r\n\t\t\t\t{\r\n//\t\t\t\t\tbool current_alpha = ( p_pass->m_texture.p_data->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA ) ? true : false;\r\n//\t\t\t\t\tbool dl_alpha = p_dl->m_alpha_offset[p] ? true : false;\r\n//\t\t\t\t\tif ( current_alpha != dl_alpha )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\t// Must use direct setup mode.\r\n//\t\t\t\t\t\tdirect = true;\r\n//\t\t\t\t\t}\r\n\t\t\t\t\tif ( p_pass->m_texture.p_data->flags & NxNgc::sTexture::TEXTURE_FLAG_REPLACED )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdirect = true;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif ( direct )\r\n\t\t\t{\r\n\t\t\t\tp_mat->m_flags |= (1<<3);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_mat->m_flags &= ~(1<<3);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcModel::CNgcModel()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcModel::~CNgcModel()\r\n{\r\n\tif ( mp_instance && mp_instance->GetBoneTransforms() )\r\n\t{\r\n\t\tdelete mp_instance->GetBoneTransforms();\r\n\t\tmp_instance->SetBoneTransforms( NULL );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CNgcModel::plat_get_bounding_sphere()\r\n{\r\n\tMth::Vector sphere, sphere1, sum, diff;\r\n\tfloat dist;\r\n\r\n\t// this should probably never happen\r\n\tif (m_numGeoms == 0)\r\n\t\treturn Mth::Vector(0.0f, 0.0f, 0.0f, 0.0f);\r\n\r\n\t// combine the spheres of all geoms\r\n\t// (this should really be done once at load time)\r\n\r\n\t// start with first sphere\r\n\tsphere = mp_geom[0]->GetBoundingSphere();\r\n\r\n\t// loop over remaining spheres, expanding as necessary\r\n\tfor (int i=1; i<m_numGeoms; i++)\r\n\t{\r\n\t\t// get next sphere\r\n\t\tsphere1 = mp_geom[i]->GetBoundingSphere();\r\n\r\n\t\t// centre-to-centre vector, and distance\r\n\t\tdiff = sphere1-sphere;\r\n\t\tdist = diff.Length();\r\n\r\n\t\t// test for sphere1 inside sphere\r\n\t\tif (dist+sphere1[3] <= sphere[3])\r\n\t\t\tcontinue;\t\t\t// keep sphere\r\n\r\n\t\t// test for sphere inside sphere1\r\n\t\tif (dist+sphere[3] <= sphere1[3])\r\n\t\t{\r\n\t\t\tsphere = sphere1;\t// replace sphere\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// otherwise make a larger sphere that contains both\r\n\t\tsum       = sphere+sphere1;\r\n\t\tsphere    = 0.5f * (sum + (diff[3]/dist) * diff);\r\n\t\tsphere[3] = 0.5f * (dist + sum[3]);\r\n\t}\r\n\r\n\treturn sphere;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcModel::plat_set_bounding_sphere( const Mth::Vector& boundingSphere )\r\n{\r\n\t// loop over all spheres\r\n\tfor ( int i = 0; i < m_numGeoms; i++ )\r\n\t{\r\n\t\tmp_geom[i]->SetBoundingSphere( boundingSphere );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n\r\n\t\t\t\t\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxmodel.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxModel.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  1/8/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_MODEL_H__\r\n#define\t__GFX_P_NX_MODEL_H__\r\n    \r\n#include \"gfx/nxmodel.h\"\r\n#include \"gfx/Ngc/nx/instance.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CModel\r\n    \r\nclass CNgcModel : public CModel\r\n{\r\npublic:\r\n\t\t\t\t\t\tCNgcModel();\r\n\tvirtual \t\t\t~CNgcModel();\r\n\r\n\tNxNgc::CInstance    *GetInstance() { return mp_instance; }\r\n\tvoid\t\t\t\tSetInstance( NxNgc::CInstance * p ) { mp_instance = p; }\r\nprivate:\t\t\t\t// It's all private, as it is machine specific\r\n//\tbool\t\t\t\tplat_load_mesh( CMesh* pMesh );\r\n//\tbool\t\t\t\tplat_unload_mesh();\r\n//\tbool\t\t\t\tplat_set_render_mode(ERenderMode mode);\r\n//\tbool\t\t\t\tplat_set_color(uint8 r, uint8 g, uint8 b, uint8 a);\r\n//\tbool\t\t\t\tplat_set_visibility(uint32 mask);\r\n//\tbool\t\t\t\tplat_set_active( bool active );\r\n//    bool\t\t\t\tplat_set_scale( float scaleFactor );\r\n//    bool\t\t\t\tplat_replace_texture( char* p_srcFileName, char* p_dstFileName );\r\n//\tbool\t\t\t\tplat_render(Mth::Matrix* pRootMatrix, Mth::Matrix* ppBoneMatrices, int numBones);\r\n\r\n\tbool\t\t\t\tplat_init_skeleton( int numBones );\r\n\r\n\tbool\t\t\t\tplat_prepare_materials( void );\r\n\tbool\t\t\t\tplat_refresh_materials( void );\r\n\r\n\tMth::Vector \t\tplat_get_bounding_sphere();\r\n\tvoid\t\t\t\tplat_set_bounding_sphere( const Mth::Vector& boundingSphere );\r\n\r\n\tNxNgc::CInstance\t*mp_instance;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n#endif \r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxnewparticle.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_NxNewParticle.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/25/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNgc new parametric particle system\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gfx/Ngc/p_nxnewparticle.h>\r\n\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n#include <gfx/Ngc/nx/nx_init.h>\r\n#include <gfx/Ngc/nx/render.h>\r\n\r\n#include \"gfx/ngc/p_nxparticle.h\"\r\n\r\n#include \"dolphin/base/ppcwgpipe.h\"\r\n#include \"dolphin/gx/gxvert.h\"\r\n#include <charpipeline/GQRSetup.h>\r\n\r\n\r\nextern \"C\"\r\n{\r\n\r\nextern float ReciprocalEstimate_ASM( float f );\r\n\r\nextern void RenderNewParticles( Nx::CParticleStream * p_stream, float lifetime, float midpercent, bool use_mid_color, Image::RGBA * p_color0, Mth::Vector * p0, Mth::Vector * sr, Mth::Vector * su, float * p_params, float nearz );\r\n\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//static int rand_seed;\r\n//static int rand_a\t= 314159265;\r\n//static int rand_b\t= 178453311;\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//static void seed_particle_rnd( int s, int a, int b )\r\n//{\r\n//\trand_seed\t\t= s;\r\n//\trand_a\t\t\t= a;\r\n//\trand_b\t\t\t= b;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//static int particle_rnd( int n )\r\n//{\r\n//\trand_seed\t= rand_seed * rand_a + rand_b;\r\n//\trand_a\t\t= ( rand_a ^ rand_seed ) + ( rand_seed >> 4 );\r\n//\trand_b\t\t+= ( rand_seed >> 3 ) - 0x10101010L;\r\n//\treturn (int)(( rand_seed & 0xffff ) * n ) >> 16;\r\n//}\r\n//\r\n//\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CParticleStream::AdvanceSeed( int num_places )\r\n{\r\n//\t// Seed the random number generator back to the current seed.\r\n//\tseed_particle_rnd( m_rand_seed, m_rand_a, m_rand_b );\r\n//\r\n//\t// Each particle will call the random function four times.\r\n//\tfor( int i = 0; i < ( num_places * 4 ); i++ )\r\n//\t{\r\n//\t\tparticle_rnd( 1 );\r\n//\t}\r\n//\r\n//\tm_rand_seed = rand_seed;\r\n//\tm_rand_a\t= rand_a;\r\n//\tm_rand_b\t= rand_b;\r\n\r\n\t// Seed the random number generator back to the current seed.\r\n\tuint32 rand_current = m_rand_current;\r\n\r\n\t// Each particle will call the random function four times.\r\n\tfor( int i = 0; i < ( num_places * 4 ); i++ )\r\n\t{\r\n\t\trand_current = ( rand_current & 1 ) ? ( rand_current >> 1 ) ^ 0x3500 : ( rand_current >> 1 );\r\n\t}\r\n\r\n\tm_rand_current = rand_current;\r\n}\r\n\t\r\n\t\r\n\t\r\n//inline DWORD FtoDW( FLOAT f ) { return *((DWORD*)&f); }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcNewParticle::plat_render( void )\r\n{\r\n\tCParticleStream* p_stream;\r\n\tint i;\r\n\r\n\t// Process the streams.\r\n\tif( m_params.m_EmitRate && ( !m_emitting || ( m_params.m_EmitRate != mp_newest_stream->m_rate )))\r\n\t{\t\r\n\t\tif( m_num_streams < m_max_streams )\r\n\t\t{\r\n\t\t\t// Add new stream to cyclic buffer\r\n\t\t\tm_num_streams++;\r\n\t\t\tmp_newest_stream++;\r\n\t\t\tif( mp_newest_stream == mp_stream + m_max_streams )\r\n\t\t\t{\r\n\t\t\t\tmp_newest_stream = mp_stream;\r\n\t\t\t}\r\n\r\n\t\t\t// Initialise new stream.\r\n\t\t\tmp_newest_stream->m_rate\t\t\t= m_params.m_EmitRate;\r\n\t\t\tmp_newest_stream->m_interval\t\t= 1.0f / m_params.m_EmitRate;\r\n\t\t\tmp_newest_stream->m_oldest_age\t\t= 0.0f;\r\n\t\t\tmp_newest_stream->m_num_particles\t= 0;\r\n//\t\t\tmp_newest_stream->m_rand_seed\t\t= rand();\r\n//\t\t\tmp_newest_stream->m_rand_a\t\t\t= 314159265;\r\n//\t\t\tmp_newest_stream->m_rand_b\t\t\t= 178453311;\r\n\t\t\tmp_newest_stream->m_rand_current\t= rand() & ( 16384 - 1 );\r\n\t\t\tif ( mp_newest_stream->m_rand_current == 0 ) mp_newest_stream->m_rand_current = 1;\r\n\t\t\tm_emitting = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_emitting = false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_emitting = m_params.m_EmitRate;\r\n\t}\r\n\r\n\tif( !m_num_streams )\r\n\t\treturn;\r\n\r\n\t// Age all streams.\r\n\tfor( i = 0, p_stream = mp_oldest_stream; i < m_num_streams; ++i )\r\n\t{\r\n\t\t// Increase age of oldest particle.\r\n\t\tp_stream->m_oldest_age += 1.0f / 60.0f;\r\n\r\n\t\t// Step pointer within cyclic buffer.\r\n\t\tp_stream++;\r\n\t\tif( p_stream == mp_stream + m_max_streams )\r\n\t\t{\r\n\t\t\tp_stream = mp_stream;\r\n\t\t}\r\n\t}\r\n\r\n\t// Births into newest stream.\r\n\tif( m_emitting )\r\n\t{\r\n\t\t// How many particles so far emitted?\r\n\t\tmp_newest_stream->m_num_particles = (int)( mp_newest_stream->m_oldest_age * mp_newest_stream->m_rate + 1.0f );\r\n\t}\r\n\r\n\t// Deaths from oldest stream.\r\n\tif( mp_oldest_stream->m_oldest_age > m_params.m_Lifetime )\r\n\t{\r\n\t\t// Work out number dead.\r\n\t\tint particles_dead = (int)(( mp_oldest_stream->m_oldest_age - m_params.m_Lifetime ) * mp_oldest_stream->m_rate + 1.0f );\r\n\r\n\t\t// Remove dead particles.\r\n\t\tmp_oldest_stream->m_num_particles -= particles_dead;\r\n\r\n\t\t// Should we keep processing the oldest stream?\r\n\t\tif( mp_oldest_stream->m_num_particles > 0 || ( m_num_streams == 1 && m_emitting ))\r\n\t\t{\r\n\t\t\t// Adjust age of oldest particle.\r\n\t\t\tmp_oldest_stream->m_oldest_age -= (float)particles_dead * mp_oldest_stream->m_interval;\r\n\r\n\t\t\t// Advance seed.\r\n\t\t\tmp_oldest_stream->AdvanceSeed( particles_dead );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Remove oldest stream and wrap in cyclic buffer if necessary.\r\n\t\t\tm_num_streams--;\r\n\t\t\tmp_oldest_stream++;\r\n\t\t\tif( mp_oldest_stream == mp_stream + m_max_streams )\r\n\t\t\t{\r\n\t\t\t\tmp_oldest_stream = mp_stream;\r\n\t\t\t}\r\n\t\t\tif( !m_num_streams )\r\n\t\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n//\t// Now render the streams. after checking the bounding sphere is visible.\r\n//\tD3DXVECTOR3\tcenter( m_bsphere[X], m_bsphere[Y], m_bsphere[Z] );\r\n//\tif( !NxNgc::frustum_check_sphere( &center, m_bsphere[W] ))\r\n//\t{\r\n//\t\treturn;\r\n//\t}\r\n\tif( !m_params.m_LocalCoord )\r\n\t{\r\n\t\tif ( !NxNgc::frustum_check_sphere( m_bsphere ) ) return;\r\n\t}\r\n //   if ( NxNgc::TestSphereAgainstOccluders( &sphere ) )\r\n\r\n\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\r\n\tNxNgc::sMaterialHeader mat;\r\n\tNxNgc::sMaterialPassHeader pass;\r\n\r\n\tmat.m_checksum\t\t\t= 0;\r\n\tmat.m_passes\t\t\t= 1;\r\n\tmat.m_alpha_cutoff\t\t= 0;\r\n\tmat.m_flags\t\t\t\t= 0;\r\n//\tmat.m_material_dl_id\t= 0;\r\n\tmat.m_draw_order\t\t= 0;\r\n\tmat.m_pass_item\t\t\t= 0;\r\n\tmat.m_texture_dl_id\t\t= 0;\r\n//\tmat.m_shininess\t\t\t= 0;\r\n//\tmat.m_specular_color\t= (GXColor){255,255,255,255};\r\n\r\n\tpass.m_texture.p_data\t= mp_texture;\r\n\tpass.m_flags\t\t\t= (1<<0)|(1<<5)|(1<<6);\r\n\tpass.m_filter\t\t\t= 0;\r\n\tpass.m_blend_mode\t\t= m_blend;\r\n\tpass.m_alpha_fix\t\t= m_fix;\r\n\tpass.m_uv_wibble_index\t= 0;\r\n\tpass.m_color\t\t\t= (GXColor){64,64,64,255};\r\n\tpass.m_k\t\t\t\t= 0;\r\n\tpass.m_u_tile\t\t\t= 0;\r\n\tpass.m_v_tile\t\t\t= 0;\r\n\tpass.m_uv_enabled\t\t= false;\r\n\r\n\tmulti_mesh( &mat, &pass, true, true );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tNsMatrix*\tp_matrix\t= &NxNgc::EngineGlobals.camera;\r\n\r\n\tNsVector\tup( 0.0f, 1.0f, 0.0f );\r\n\tNsVector screen_right;\r\n\tNsVector screen_up;\r\n\tscreen_right.cross( *p_matrix->getAt(), up );\r\n\tscreen_up.cross( screen_right, *p_matrix->getAt());\r\n\r\n\tscreen_right.normalize();\r\n\tscreen_up.normalize();\r\n\t\r\n\tMth::Vector sr;\r\n\tMth::Vector su;\r\n\tsr[X] = screen_right.x;\r\n\tsr[Y] = screen_right.y;\r\n\tsr[Z] = screen_right.z;\r\n\tsr[W] = 1.0f;\r\n\r\n\tsu[X] = screen_up.x;\r\n\tsu[Y] = screen_up.y;\r\n\tsu[Z] = screen_up.z;\r\n\tsu[W] = 1.0f;\r\n\r\n\tGQRSetup6( GQR_SCALE_64,\t\t// Pos\r\n\t\t\t   GQR_TYPE_S16,\r\n\t\t\t   GQR_SCALE_64,\r\n\t\t\t   GQR_TYPE_S16 );\r\n\tGQRSetup7( 14,\t\t// Normal\r\n\t\t\t   GQR_TYPE_S16,\r\n\t\t\t   14,\r\n\t\t\t   GQR_TYPE_S16 );\r\n\r\n\tf32\t\t\t\tpm[GX_PROJECTION_SZ];\r\n\tf32\t\t\t\tvp[GX_VIEWPORT_SZ];\r\n\r\n\tGX::GetProjectionv( pm );\r\n\tGX::GetViewportv( vp );\r\n\tNsMatrix * p_mtx = &NxNgc::EngineGlobals.local_to_camera;\r\n\r\n\tfloat params[6];\r\n\tparams[0] = p_mtx->getAtX();\r\n\tparams[1] = p_mtx->getAtY();\r\n\tparams[2] = p_mtx->getPosZ();\r\n\tparams[3] = p_mtx->getAtZ();\r\n\tparams[4] = pm[1];\r\n\tparams[5] = vp[2];\r\n\r\n\t// Construct a packet with data for each stream.\r\n\tfor( i = 0, p_stream = mp_oldest_stream; i < m_num_streams; i++, p_stream++ )\r\n\t{\r\n\t\tDbg_MsgAssert( p_stream->m_num_particles < 65536, ( \"particle limit reached\" ));\r\n\r\n\t\t// Wrap at end of cyclic buffer.\r\n\t\tif( p_stream == mp_stream + m_max_streams )\r\n\t\t{\r\n\t\t\tp_stream = mp_stream;\r\n\t\t}\r\n\r\n#if 1\r\n\t\tRenderNewParticles( p_stream,\r\n\t\t\t\t\t\t\tm_params.m_Lifetime,\r\n\t\t\t\t\t\t\tm_params.m_ColorMidpointPct,\r\n\t\t\t\t\t\t\tm_params.m_UseMidcolor,\r\n\t\t\t\t\t\t\t&m_params.m_Color[0],\r\n\t\t\t\t\t\t\t&m_s0,\r\n\t\t\t\t\t\t\t&sr,\r\n\t\t\t\t\t\t\t&su,\r\n\t\t\t\t\t\t\tparams,\r\n\t\t\t\t\t\t\t256.0f );\r\n\r\n#else\r\n\t\tfloat t\t\t\t\t= p_stream->m_oldest_age;\r\n\t\tfloat midpoint_time = m_params.m_Lifetime * ( m_params.m_ColorMidpointPct * 0.01f );\r\n\r\n\t\t// Seed the random number generators for this stream.\r\n//\t\tseed_particle_rnd( p_stream->m_rand_seed, p_stream->m_rand_a, p_stream->m_rand_b );\r\n\t\tuint32 rand_current = p_stream->m_rand_current;\r\n\r\n\t\tfor( int p = 0; p < p_stream->m_num_particles; ++p )\r\n\t\t{\r\n\t\t\t// Generate random vector. Each component in the range [1.0, 2.0].\r\n//\t\t\tMth::Vector r( 1.0f + ((float)particle_rnd( 16384 ) / 16384 ),\r\n//\t\t\t\t\t\t   1.0f + ((float)particle_rnd( 16384 ) / 16384 ),\r\n//\t\t\t\t\t\t   1.0f + ((float)particle_rnd( 16384 ) / 16384 ),\r\n//\t\t\t\t\t\t   1.0f + ((float)particle_rnd( 16384 ) / 16384 ));\r\n\r\n\t\t\tMth::Vector r;\r\n\t\t\tr[X] = 1.0f + ((float)( rand_current = ( ( rand_current & 1 ) ? ( rand_current >> 1 ) ^ 0x3500 : ( rand_current >> 1 ) ) ) / 16384.0f );\r\n\t\t\tr[Y] = 1.0f + ((float)( rand_current = ( ( rand_current & 1 ) ? ( rand_current >> 1 ) ^ 0x3500 : ( rand_current >> 1 ) ) ) / 16384.0f );\r\n\t\t\tr[Z] = 1.0f + ((float)( rand_current = ( ( rand_current & 1 ) ? ( rand_current >> 1 ) ^ 0x3500 : ( rand_current >> 1 ) ) ) / 16384.0f );\r\n\t\t\tr[W] = 1.0f + ((float)( rand_current = ( ( rand_current & 1 ) ? ( rand_current >> 1 ) ^ 0x3500 : ( rand_current >> 1 ) ) ) / 16384.0f );\r\n\r\n\t\t\tfloat color_interpolator;\r\n\t\t\tImage::RGBA\tcol0, col1;\r\n\r\n\t\t\tif( m_params.m_UseMidcolor )\r\n\t\t\t{\r\n\t\t\t\tif( t > midpoint_time )\r\n\t\t\t\t{\r\n\t\t\t\t\tcolor_interpolator\t= ( t - midpoint_time ) * ReciprocalEstimate_ASM( m_params.m_Lifetime - midpoint_time );\r\n\t\t\t\t\tcol0\t\t\t\t= m_params.m_Color[1];\r\n\t\t\t\t\tcol1\t\t\t\t= m_params.m_Color[2];\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tcolor_interpolator\t= t * ReciprocalEstimate_ASM( midpoint_time );\r\n\t\t\t\t\tcol0\t\t\t\t= m_params.m_Color[0];\r\n\t\t\t\t\tcol1\t\t\t\t= m_params.m_Color[1];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse \r\n\t\t\t{\r\n\t\t\t\tcolor_interpolator\t\t= t * ReciprocalEstimate_ASM( m_params.m_Lifetime );\r\n\t\t\t\tcol0\t\t\t\t\t= m_params.m_Color[0];\r\n\t\t\t\tcol1\t\t\t\t\t= m_params.m_Color[2];\r\n\t\t\t}\r\n\r\n\r\n//; Calculate the position of the particle, from:\r\n// pos = ( m_p0 + ( t * m_p1 ) + (( t * t ) * m_p2 )) + ( m_s0 + ( t * m_s1 ) + (( t * t ) * m_s2 )).Scale( r );\r\n\t\t\tMth::Vector pos = ( m_p0 + ( t * m_p1 ) + (( t * t ) * m_p2 )) + ( m_s0 + ( t * m_s1 ) + (( t * t ) * m_s2 )).Scale( r );\r\n\r\n\t\t\tGXColor matcol;\r\n\t\t\tmatcol.r = col0.r + (uint8)( ( (float)col1.r - (float)col0.r ) * color_interpolator );\r\n\t\t\tmatcol.g = col0.g + (uint8)( ( (float)col1.g - (float)col0.g ) * color_interpolator );\r\n\t\t\tmatcol.b = col0.b + (uint8)( ( (float)col1.b - (float)col0.b ) * color_interpolator );\r\n\t\t\tmatcol.a = col0.a + (uint8)( ( (float)col1.a - (float)col0.a ) * color_interpolator );\r\n\r\n\t\t\tGX::SetChanMatColor( GX_COLOR0A0, matcol );\r\n\t\t\tGX::SetChanAmbColor( GX_COLOR0A0, matcol );\r\n\r\n//\t\t\tNsVector sr;\r\n//\t\t\tsr.x = screen_right.x * pos[W];\r\n//\t\t\tsr.y = screen_right.y * pos[W];\r\n//\t\t\tsr.z = screen_right.z * pos[W];\r\n//\r\n//\t\t\tfloat sx, sy, sz;\r\n//\t\t\tfloat tx, ty, tz;\r\n//\t\t\tfloat sc;\r\n//\t\t\tGX::Project( pos[X], pos[Y], pos[Z], (Mtx)p_mtx, pm, vp, &sx, &sy, &sz );\r\n//\t\t\tGX::Project( pos[X]+sr.x, pos[Y]+sr.y, pos[Z]+sr.z, (Mtx)p_mtx, pm, vp, &tx, &ty, &tz );\r\n//\t\t\tsc = tx - sx;\t//sqrtf( ( ( tx - sx ) * ( tx - sx ) ) + ( ( ty - sy ) * ( ty - sy ) ) + ( ( tz - sz ) * ( tz - sz ) ) );\r\n\r\n\t\t\t// Calculate size.\r\n//\t\t\tfloat x = p_mtx->getRightX()*pos[W];\r\n\t\t\tfloat z = p_mtx->getAtX()*pos[X] + p_mtx->getAtY()*pos[Y] + p_mtx->getAtZ()*pos[Z] + p_mtx->getPosZ();\r\n\t\t\tfloat xc = pos[W] * pm[1];\t// + z * pm[2];\r\n\t\t\tfloat wc = ( 1.0f / z );\r\n\t\t\tfloat sc = xc * vp[2] * wc;\t// + vp[0] + vp[2]/2;\r\n\r\n\t\t\tsc = fabsf( sc );\r\n\r\n\t\t\tint size = (int)(sc * 6.0f);\r\n\t\t\tif ( size <= 255 )\r\n\t\t\t{\r\n\t\t\t\tGX::SetPointSize( size, GX_TO_ONE );\r\n\t\t\t\tGX::Begin( GX_POINTS, GX_VTXFMT0, 1 ); \r\n\t\t\t\tGXWGFifo.f32 = pos[X];\r\n\t\t\t\tGXWGFifo.f32 = pos[Y];\r\n\t\t\t\tGXWGFifo.f32 = pos[Z];\r\n\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\t\t\t\tGX::End();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( sc > 256.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tpos[W] = ( pos[W] * 256.0f ) / sc;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tNsVector sr;\r\n\t\t\t\tsr.x = screen_right.x * pos[W];\r\n\t\t\t\tsr.y = screen_right.y * pos[W];\r\n\t\t\t\tsr.z = screen_right.z * pos[W];\r\n\t\t\t\tNsVector su;\r\n\t\t\t\tsu.x = screen_up.x * pos[W];\r\n\t\t\t\tsu.y = screen_up.y * pos[W];\r\n\t\t\t\tsu.z = screen_up.z * pos[W];\r\n\t\t\r\n\t\t\t\tfloat v0x = pos[X] - su.x;\r\n\t\t\t\tfloat v0y = pos[Y] - su.y;\r\n\t\t\t\tfloat v0z = pos[Z] - su.z;\r\n\t\r\n\t\t\t\tfloat v1x = pos[X] + su.x;\r\n\t\t\t\tfloat v1y = pos[Y] + su.y;\r\n\t\t\t\tfloat v1z = pos[Z] + su.z;\r\n\r\n\t\t\t\t// Send coordinates.\r\n\t\t\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\t\t\t\tGXWGFifo.f32 = v1x - sr.x;\r\n\t\t\t\t\tGXWGFifo.f32 = v1y - sr.y;\r\n\t\t\t\t\tGXWGFifo.f32 = v1z - sr.z;\r\n\t\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\t\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\r\n\t\t\t\t\tGXWGFifo.f32 = v1x + sr.x;\r\n\t\t\t\t\tGXWGFifo.f32 = v1y + sr.y;\r\n\t\t\t\t\tGXWGFifo.f32 = v1z + sr.z;\r\n\t\t\t\t\tGXWGFifo.f32 = 1.0f;\r\n\t\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\r\n\t\t\t\t\tGXWGFifo.f32 = v0x + sr.x;\r\n\t\t\t\t\tGXWGFifo.f32 = v0y + sr.y;\r\n\t\t\t\t\tGXWGFifo.f32 = v0z + sr.z;\r\n\t\t\t\t\tGXWGFifo.f32 = 1.0f;\r\n\t\t\t\t\tGXWGFifo.f32 = 1.0f;\r\n\r\n\t\t\t\t\tGXWGFifo.f32 = v0x - sr.x;\r\n\t\t\t\t\tGXWGFifo.f32 = v0y - sr.y;\r\n\t\t\t\t\tGXWGFifo.f32 = v0z - sr.z;\r\n\t\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\t\t\t\t\tGXWGFifo.f32 = 1.0f;\r\n\t\t\t\tGX::End();\r\n\t\t\t}\r\n\r\n\r\n\r\n\t\t\t// Reduce t by particle interval.\r\n\t\t\tt -= p_stream->m_interval;\r\n\t\t}\r\n#endif\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcNewParticle::update_position( void )\r\n{\r\n\t// Convert 3-point -> PVA format\r\n\tfloat t1 = m_params.m_Lifetime * m_params.m_MidpointPct * 0.01f;\r\n\tfloat t2 = m_params.m_Lifetime;\r\n\tMth::Vector u, a_;\r\n\r\n\tMth::Vector x0\t= m_params.m_BoxPos[0];\r\n\tx0[3]\t\t\t= m_params.m_Radius[0];\r\n\tMth::Vector x1\t= m_params.m_BoxPos[1];\r\n\tx1[3]\t\t\t= m_params.m_Radius[1];\r\n\tMth::Vector x2\t= m_params.m_BoxPos[2];\r\n\tx2[3]\t\t\t= m_params.m_Radius[2];\r\n\r\n\tif( m_params.m_UseMidpoint )\r\n\t{\r\n\t\tu  = ( t2 * t2 * ( x1 - x0 ) - t1 * t1 * ( x2 - x0 )) / ( t1 * t2 * ( t2 - t1 ));\r\n\t\ta_ = ( t1 * ( x2 - x0 ) - t2 * ( x1 - x0 )) / ( t1 * t2 * ( t2 - t1 ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tu  = ( x2 - x0 ) / t2;\r\n\t\ta_.Set( 0, 0, 0, 0 );\r\n\t}\r\n\r\n\tm_p0 = x0 - 1.5f * m_s0;\r\n\tm_p1 = u  - 1.5f * m_s1;\r\n\tm_p2 = a_ - 1.5f * m_s2;\r\n\tm_p0[3] = x0[3] - 1.5f * m_s0[3];\r\n\tm_p1[3] = u[3]  - 1.5f * m_s1[3];\r\n\tm_p2[3] = a_[3] - 1.5f * m_s2[3];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcNewParticle::plat_update( void )\r\n{\r\n\r\n\tif (m_params.m_LocalCoord)\r\n\t{\r\n\t\tupdate_position();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcNewParticle::plat_build( void )\r\n{\r\n\t// Adjust some of the stream params to improve performance.\r\n\tm_params.m_EmitRate\t= m_params.m_EmitRate * 0.25f;\r\n\t\r\n\t// Initialise streams.\r\n\tm_max_streams\t\t= 5;\r\n\tm_num_streams\t\t= 0;\r\n\r\n\tmp_stream\t\t\t= new CParticleStream[m_max_streams]; \r\n\tmp_newest_stream\t= mp_stream + m_max_streams - 1;\r\n\tmp_oldest_stream\t= mp_stream;\r\n\tm_emitting\t\t\t= false;\r\n\r\n\t// Create a (semi-transparent) material used to render the mesh.\r\n//\tmp_material\t\t\t= new NxNgc::sMaterial;\r\n//\tmemset( mp_material, 0, sizeof( NxNgc::sMaterial ));\r\n\r\n//\tmp_material->m_flags[0]\t\t= MATFLAG_TRANSPARENT | MATFLAG_TEXTURED;\r\n//\tmp_material->m_passes\t\t= 1;\r\n//\tmp_material->m_alpha_cutoff\t= 1;\r\n//\tmp_material->m_no_bfc\t\t= true;\r\n//\tmp_material->m_color[0][0]\t= 0.5f;\r\n//\tmp_material->m_color[0][1]\t= 0.5f;\r\n//\tmp_material->m_color[0][2]\t= 0.5f;\r\n//\tmp_material->m_color[0][3]\t= m_params.m_FixedAlpha * ( 1.0f /  128.0f );\r\n//\tmp_material->m_reg_alpha[0]\t= NxNgc::GetBlendMode( m_params.m_BlendMode );\r\n//\r\n//\t// Get texture.\r\n//\tNx::CTexture*\t\tp_texture;\r\n//\tNx::CNgcTexture*\tp_Ngc_texture;\r\n//\tmp_material->mp_tex[0]\t= NULL;\r\n//\tp_texture\t\t\t\t= Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( m_params.m_Texture );\r\n//\tp_Ngc_texture\t\t\t= static_cast<Nx::CNgcTexture*>( p_texture );\r\n//\tif( p_Ngc_texture )\r\n//\t{\r\n//\t\tmp_material->mp_tex[0] = p_Ngc_texture->GetEngineTexture();\r\n//\t}\r\n\r\n\t// Have already set m_Lifetime, which is called m_life in newflat.\r\n\r\n\t// x-component will be overwritten by vu1 code, so can store midtime there\r\n//\t*(float *)&m_systemDmaData.m_tagx = m_params.m_UseMidcolor ?\r\n//\t\t\t\t\t\t\t\t\t\tm_params.m_Lifetime * m_params.m_ColorMidpointPct * 0.01f :\r\n//\t\t\t\t\t\t\t\t\t\t0.0f;\r\n\r\n\r\n\t// Set Texture & blend mode.\r\n\tNx::CTexture *p_texture;\r\n\tNx::CNgcTexture *p_Ngc_texture;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( m_params.m_Texture );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\tm_blend = get_texture_blend( m_params.m_BlendMode ); \r\n\tm_fix = m_params.m_FixedAlpha;\r\n\r\n\r\n\t// and now a load of redundant duplication of data, which should later be removed...\r\n\r\n\t// Convert 3-point -> PVA format.\r\n\tfloat t1 = m_params.m_Lifetime * m_params.m_MidpointPct * 0.01f;\r\n\tfloat t2 = m_params.m_Lifetime;\r\n\tMth::Vector x0,x1,x2,u,a_;\r\n\r\n\tx0    = m_params.m_BoxDims[0];\r\n\tx0[3] = m_params.m_RadiusSpread[0];\r\n\tx1    = m_params.m_BoxDims[1];\r\n\tx1[3] = m_params.m_RadiusSpread[1];\r\n\tx2    = m_params.m_BoxDims[2];\r\n\tx2[3] = m_params.m_RadiusSpread[2];\r\n\r\n\tif( m_params.m_UseMidpoint )\r\n\t{\r\n\t\tu  = ( t2 * t2 * ( x1 - x0 ) - t1 * t1 * ( x2 - x0 )) / ( t1 * t2 * ( t2 - t1 ));\r\n\t\ta_ = ( t1 * ( x2 - x0 ) - t2 * ( x1 - x0 )) / ( t1 * t2 * ( t2 - t1 ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tu  = ( x2 - x0 ) / t2;\r\n\t\ta_.Set(0,0,0,0);\r\n\t}\r\n\r\n\tm_s0 = x0;\r\n\tm_s1 = u;\r\n\tm_s2 = a_;\r\n\r\n\tx0    = m_params.m_BoxPos[0];\r\n\tx0[3] = m_params.m_Radius[0];\r\n\tx1    = m_params.m_BoxPos[1];\r\n\tx1[3] = m_params.m_Radius[1];\r\n\tx2    = m_params.m_BoxPos[2];\r\n\tx2[3] = m_params.m_Radius[2];\r\n\r\n\tif( m_params.m_UseMidpoint )\r\n\t{\r\n\t\tu  =  ( t2 * t2 * ( x1 - x0 ) - t1 * t1 * ( x2 - x0 )) / ( t1 * t2 * ( t2 - t1 ));\r\n\t\ta_ =  ( t1 * ( x2 - x0 ) - t2 * ( x1 - x0 )) / ( t1 * t2 * ( t2 - t1 ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tu  = ( x2 - x0 ) / t2;\r\n\t\ta_.Set(0,0,0,0);\r\n\t}\r\n\r\n\tm_p0\t= x0 - 1.5f * m_s0;\r\n\tm_p1\t= u  - 1.5f * m_s1;\r\n\tm_p2\t= a_ - 1.5f * m_s2;\r\n\tm_p0[3]\t= x0[3] - 1.5f * m_s0[3];\r\n\tm_p1[3]\t= u[3]  - 1.5f * m_s1[3];\r\n\tm_p2[3]\t= a_[3] - 1.5f * m_s2[3];\r\n\r\n\tupdate_position();\r\n\r\n\t// Color.\r\n\tif( m_params.m_UseMidcolor )\r\n\t{\r\n//\t\tfloat q0 = 100.0f / ( m_params.m_Lifetime * m_params.m_ColorMidpointPct );\r\n//\t\tfloat q1 = 100.0f / ( m_params.m_Lifetime * ( 100.0f - m_params.m_ColorMidpointPct ));\r\n\r\n//\t\tm_systemDmaData.m_c0[0] = ((float)m_params.m_Color[1].r - (float)m_params.m_Color[0].r) * q0;\r\n//\t\tm_systemDmaData.m_c0[1] = ((float)m_params.m_Color[1].g - (float)m_params.m_Color[0].g) * q0;\r\n//\t\tm_systemDmaData.m_c0[2] = ((float)m_params.m_Color[1].b - (float)m_params.m_Color[0].b) * q0;\r\n//\t\tm_systemDmaData.m_c0[3] = ((float)m_params.m_Color[1].a - (float)m_params.m_Color[0].a) * q0;\r\n\r\n//\t\tm_systemDmaData.m_c1[0] = (float)m_params.m_Color[1].r;\r\n//\t\tm_systemDmaData.m_c1[1] = (float)m_params.m_Color[1].g;\r\n//\t\tm_systemDmaData.m_c1[2] = (float)m_params.m_Color[1].b;\r\n//\t\tm_systemDmaData.m_c1[3] = (float)m_params.m_Color[1].a;\r\n\r\n//\t\tm_systemDmaData.m_c2[0] = ((float)m_params.m_Color[2].r - (float)m_params.m_Color[1].r) * q1;\r\n//\t\tm_systemDmaData.m_c2[1] = ((float)m_params.m_Color[2].g - (float)m_params.m_Color[1].g) * q1;\r\n//\t\tm_systemDmaData.m_c2[2] = ((float)m_params.m_Color[2].b - (float)m_params.m_Color[1].b) * q1;\r\n//\t\tm_systemDmaData.m_c2[3] = ((float)m_params.m_Color[2].a - (float)m_params.m_Color[1].a) * q1;\r\n\t}\r\n\telse // else suppress mid-colour\r\n\t{\r\n//\t\tfloat q = 1.0f / m_params.m_Lifetime;\r\n\r\n//\t\tm_systemDmaData.m_c1[0] = (float)m_params.m_Color[0].r;\r\n//\t\tm_systemDmaData.m_c1[1] = (float)m_params.m_Color[0].g;\r\n//\t\tm_systemDmaData.m_c1[2] = (float)m_params.m_Color[0].b;\r\n//\t\tm_systemDmaData.m_c1[3] = (float)m_params.m_Color[0].a;\r\n\r\n//\t\tm_systemDmaData.m_c2[0] = ((float)m_params.m_Color[2].r - (float)m_params.m_Color[0].r) * q;\r\n//\t\tm_systemDmaData.m_c2[1] = ((float)m_params.m_Color[2].g - (float)m_params.m_Color[0].g) * q;\r\n//\t\tm_systemDmaData.m_c2[2] = ((float)m_params.m_Color[2].b - (float)m_params.m_Color[0].b) * q;\r\n//\t\tm_systemDmaData.m_c2[3] = ((float)m_params.m_Color[2].a - (float)m_params.m_Color[0].a) * q;\r\n\t}\r\n\r\n\t// Rotation matrix.\r\n//\tm_rotation = m_params.m_RotMatrix;\r\n\tm_rotation.Identity();\r\n\r\n\t#if 0\r\n\t// invert rotation and apply to spatial params\r\n\t// leaving this code a bit shoddy and slow until full transition to new-style params\r\n\tMth::Matrix mat;\r\n\tmat=m_rotation;\r\n\tmat.Transpose();\r\n\tMth::Vector vec;\r\n\r\n\tvec = m_systemDmaData.m_p0 + 1.5f * m_systemDmaData.m_s0;\r\n\tvec *= mat;\r\n\tm_systemDmaData.m_p0 = vec - 1.5f * m_systemDmaData.m_s0;\r\n\r\n\tvec = m_systemDmaData.m_p1 + 1.5f * m_systemDmaData.m_s1;\r\n\tvec *= mat;\r\n\tm_systemDmaData.m_p1 = vec - 1.5f * m_systemDmaData.m_s1;\r\n\r\n\tvec = m_systemDmaData.m_p2 + 1.5f * m_systemDmaData.m_s2;\r\n\tvec *= mat;\r\n\tm_systemDmaData.m_p2 = vec - 1.5f * m_systemDmaData.m_s2;\r\n\t#endif\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcNewParticle::plat_destroy( void )\r\n{\r\n\tif( mp_stream )\r\n\t{\r\n\t\tdelete [] mp_stream;\r\n\t}\r\n\r\n//\tif( mp_material )\r\n//\t{\r\n//\t\tdelete mp_material;\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxnewparticle.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_NxNewParticle.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/24/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNgc implementation of new parametric particle system\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_Ngc_P_NXNEWPARTICLE_H__\r\n#define __GFX_Ngc_P_NXNEWPARTICLE_H__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/nxnewparticle.h>\r\n#include <gfx/Ngc/nx/material.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n                        \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CParticleStream\r\n{\r\npublic:\r\n\tint\t\t\t\t\t\tm_num_particles;\r\n\tfloat\t\t\t\t\tm_rate;\r\n\tfloat\t\t\t\t\tm_interval;\r\n\tfloat\t\t\t\t\tm_oldest_age;\r\n//\tuint32\t\t\t\t\tm_rand_seed;\r\n//\tuint32\t\t\t\t\tm_rand_a;\r\n//\tuint32\t\t\t\t\tm_rand_b;\r\n\tuint32\t\t\t\t\tm_rand_current;\r\n\tvoid\t\t\t\t\tAdvanceSeed( int num_places );\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CNgcNewParticle : public CNewParticle\r\n{\r\n\tbool\t\t\t\tm_emitting;\r\n\tint\t\t\t\t\tm_max_streams;\r\n\tint\t\t\t\t\tm_num_streams;\r\n\tCParticleStream*\tmp_stream;\r\n\tCParticleStream*\tmp_newest_stream;\r\n\tCParticleStream*\tmp_oldest_stream;\r\n\tMth::Matrix \t\tm_rotation;\r\n\tMth::Matrix\t\t\tm_new_matrix;\r\n//\tNxNgc::sMaterial*\tmp_material;\r\n\tNxNgc::sTexture *\tmp_texture;\r\n\tuint8\t\t\t\tm_blend;\r\n\tuint8\t\t\t\tm_fix;\r\n\r\n\tMth::Vector\t\t\tm_s0;\r\n\tMth::Vector\t\t\tm_s1;\r\n\tMth::Vector\t\t\tm_s2;\r\n\tMth::Vector\t\t\tm_p0;\r\n\tMth::Vector\t\t\tm_p1;\r\n\tMth::Vector\t\t\tm_p2;\r\n\r\nprotected:\r\n\tvoid\tplat_build( void );\r\n\tvoid\tplat_destroy( void );\r\n\tvoid\tplat_render( void );\r\n\tvoid\tplat_update( void );\r\n\tvoid\tupdate_position( void );\r\n};\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n#endif\t// __GFX_Ngc_P_NXNEWPARTICLE_H__\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxnewparticlemgr.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_NxNewParticleMgr.cpp\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/25/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNgc-specific parametric particle system manager\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gfx/Ngc/p_nxnewparticle.h>\r\n#include <gfx/Ngc/p_nxnewparticlemgr.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCNewParticle*\tCNgcNewParticleManager::plat_create_particle( void )\r\n{\r\n\treturn new CNgcNewParticle;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxnewparticlemgr.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5 \t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_nxnewparticlemgr.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/24/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNgc-specific new parametric particle system manager\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_NGC_P_NXNEWPARTICLEMGR_H__\r\n#define __GFX_NGC_P_NXNEWPARTICLEMGR_H__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/nxnewparticlemgr.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CNgcNewParticleManager : public CNewParticleManager\r\n{\r\nprotected:\r\n\tvirtual\tCNewParticle*\tplat_create_particle( void );\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n#endif\t// __GFX_NGC_P_NXNEWPARTICLEMGR_H__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticle.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n\r\n#include \"gfx/Ngc/nx/mesh.h\"\r\n#include \"gfx/Ngc/p_nxparticleflat.h\"\r\n#include \"gfx/Ngc/p_nxparticleshaded.h\"\r\n#include \"gfx/Ngc/p_nxparticlesmooth.h\"\r\n#include \"gfx/Ngc/p_nxparticleglow.h\"\r\n#include \"gfx/Ngc/p_nxparticlestar.h\"\r\n#include \"gfx/Ngc/p_nxparticlesmoothstar.h\"\r\n#include \"gfx/Ngc/p_nxparticleline.h\"\r\n#include \"gfx/Ngc/p_nxparticleribbon.h\"\r\n#include \"gfx/Ngc/p_nxparticleribbontrail.h\"\r\n#include \"gfx/Ngc/p_nxparticlesmoothribbon.h\"\r\n#include \"gfx/Ngc/p_nxparticleglowribbontrail.h\"\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\nNxNgc::BlendModes get_texture_blend( uint32 blend_checksum )\r\n{\r\n\tNxNgc::BlendModes rv = NxNgc::vBLEND_MODE_DIFFUSE;\r\n\tswitch ( blend_checksum )\r\n\t{\r\n\t\tcase 0x54628ed7:\t\t// Blend\r\n\t\t\trv = NxNgc::vBLEND_MODE_BLEND;\r\n\t\t\tbreak;\r\n\t\tcase 0x02e58c18:\t\t// Add\r\n\t\t\trv = NxNgc::vBLEND_MODE_ADD;\r\n\t\t\tbreak;\r\n\t\tcase 0xa7fd7d23:\t\t// Sub\r\n\t\tcase 0xdea7e576:\t\t// Subtract\r\n\t\t\trv = NxNgc::vBLEND_MODE_SUBTRACT;\r\n\t\t\tbreak;\r\n\t\tcase 0x40f44b8a:\t\t// Modulate\r\n\t\t\trv = NxNgc::vBLEND_MODE_MODULATE;\r\n\t\t\tbreak;\r\n\t\tcase 0x68e77f40:\t\t// Brighten\r\n\t\t\trv = NxNgc::vBLEND_MODE_BRIGHTEN;\r\n\t\t\tbreak;\r\n\t\tcase 0x18b98905:\t\t// FixBlend\r\n\t\t\trv = NxNgc::vBLEND_MODE_BLEND_FIXED;\r\n\t\t\tbreak;\r\n\t\tcase 0xa86285a1:\t\t// FixAdd\r\n\t\t\trv = NxNgc::vBLEND_MODE_ADD_FIXED;\r\n\t\t\tbreak;\r\n\t\tcase 0x0d7a749a:\t\t// FixSub\r\n\t\tcase 0x0eea99ff:\t\t// FixSubtract\r\n\t\t\trv = NxNgc::vBLEND_MODE_SUB_FIXED;\r\n\t\t\tbreak;\r\n\t\tcase 0x90b93703:\t\t// FixModulate\r\n\t\t\trv = NxNgc::vBLEND_MODE_MODULATE_FIXED;\r\n\t\t\tbreak;\r\n\t\tcase 0xb8aa03c9:\t\t// FixBrighten\r\n\t\t\trv = NxNgc::vBLEND_MODE_BRIGHTEN_FIXED;\r\n\t\t\tbreak;\r\n\t\tcase 0x515e298e:\t\t// Diffuse\r\n\t\tcase 0x806fff30:\t\t// None\r\n\t\t\trv = NxNgc::vBLEND_MODE_DIFFUSE;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Illegal blend mode specified. Please use (fix)blend/add/sub/modulate/brighten or diffuse/none.\"));\r\n\t\t\tbreak;\r\n\t}\r\n\treturn rv;\r\n}\r\n\r\nCParticle* plat_create_particle( uint32 checksum, uint32 type_checksum, int max_particles, int max_streams, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\t// Types to add:\r\n\t// 1. x Flat color quad\r\n\t// 2. x Gouraud quad\r\n\t// 3. x Quad with center point & outer color\r\n\t// 4. x n sided glow (center color + outer color)\r\n\t// 5. x n sided 2 layer glow ( center color + mid color + outer color)\r\n\t// 6. x n spiked star (center color + mid color + spike color)\r\n\t// 7. Lines (current color + previous color)\r\n\t// 8. Ribbons - volumetric lines made from quads (current color + previous color)\r\n\r\n\tswitch ( type_checksum )\r\n\t{\r\n\t\tcase 0xf4d8d486:\t\t// Shaded\r\n\t\t\t{\r\n\t\t\t\tCNgcParticleShaded* p_particle = new CNgcParticleShaded( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x8addac1f:\t\t// Smooth\r\n\t\t\t{\r\n\t\t\t\tCNgcParticleSmooth* p_particle = new CNgcParticleSmooth( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x15834eea:\t\t// Glow\r\n\t\t\t{\r\n\t\t\t\tCNgcParticleGlow* p_particle = new CNgcParticleGlow( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x3624a5eb:\t\t// Star\r\n\t\t\t{\r\n\t\t\t\tCNgcParticleStar* p_particle = new CNgcParticleStar( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x97cb7a9:\t\t// SmoothStar\r\n\t\t\t{\r\n\t\t\t\tCNgcParticleSmoothStar* p_particle = new CNgcParticleSmoothStar( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x2eeb4b09:\t\t// Line\r\n\t\t\t{\r\n\t\t\t\tCNgcParticleLine* p_particle = new CNgcParticleLine( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0xee6fc5b:\t\t// Ribbon\r\n\t\t\t{\r\n\t\t\t\tCNgcParticleRibbon* p_particle = new CNgcParticleRibbon( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0xc4d5a4cb:\t\t// RibbonTrail\r\n\t\t\t{\r\n\t\t\t\tCNgcParticleRibbonTrail* p_particle = new CNgcParticleRibbonTrail( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x3f109fcc:\t\t// SmoothRibbon\r\n\t\t\t{\r\n\t\t\t\tCNgcParticleSmoothRibbon* p_particle = new CNgcParticleSmoothRibbon( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x7ec7252d:\t\t// GlowRibbonTrail\r\n\t\t\t{\r\n\t\t\t\tCNgcParticleGlowRibbonTrail* p_particle = new CNgcParticleGlowRibbonTrail( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0xaab555bb:\t\t// Flat\r\n\t\tdefault:\r\n\t\t\t{\r\n\t\t\t\tCNgcParticleFlat* p_particle = new CNgcParticleFlat( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\t\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticle.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLE_H__\r\n#define\t__GFX_P_NX_PARTICLE_H__\r\n    \r\n#include \"gfx/nxparticle.h\"\r\n#include \"gfx/ngc/nx/render.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nNxNgc::BlendModes get_texture_blend( uint32 blend_checksum );\r\n\t\r\n} // Nx\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleflat.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/Ngc/nx/render.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n#include \"gfx/Ngc/nx/mesh.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\n#include \"gfx/Ngc/p_nxparticleflat.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleFlat::CNgcParticleFlat()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleFlat::CNgcParticleFlat( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxNgc::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CNgcTexture *p_Ngc_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = (uint8)get_texture_blend( blendmode_checksum );\r\n\tm_fix = fix;\r\n\r\n\t// Default color.\r\n\tm_start_color.r = 128;\r\n\tm_start_color.g = 128;\r\n\tm_start_color.b = 128;\r\n\tm_start_color.a = 128;\r\n\tm_mid_color.r = 128;\r\n\tm_mid_color.g = 128;\r\n\tm_mid_color.b = 128;\r\n\tm_mid_color.a = 128;\r\n\tm_end_color.r = 128;\r\n\tm_end_color.g = 128;\r\n\tm_end_color.b = 128;\r\n\tm_end_color.a = 128;\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleFlat::~CNgcParticleFlat()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleFlat::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleFlat::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleFlat::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CNgcParticleFlat::plat_get_num_particle_colors( void ) { return 1; }\r\nint CNgcParticleFlat::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CNgcParticleFlat::plat_set_sr( int entry, uint8 value ) { m_start_color.r = value; }\r\nvoid CNgcParticleFlat::plat_set_sg( int entry, uint8 value ) { m_start_color.g = value; }\r\nvoid CNgcParticleFlat::plat_set_sb( int entry, uint8 value ) { m_start_color.b = value; }\r\nvoid CNgcParticleFlat::plat_set_sa( int entry, uint8 value ) { m_start_color.a = value; }\r\nvoid CNgcParticleFlat::plat_set_mr( int entry, uint8 value ) { m_mid_color.r = value; }\r\nvoid CNgcParticleFlat::plat_set_mg( int entry, uint8 value ) { m_mid_color.g = value; }\r\nvoid CNgcParticleFlat::plat_set_mb( int entry, uint8 value ) { m_mid_color.b = value; }\r\nvoid CNgcParticleFlat::plat_set_ma( int entry, uint8 value ) { m_mid_color.a = value; }\r\nvoid CNgcParticleFlat::plat_set_er( int entry, uint8 value ) { m_end_color.r = value; }\r\nvoid CNgcParticleFlat::plat_set_eg( int entry, uint8 value ) { m_end_color.g = value; }\r\nvoid CNgcParticleFlat::plat_set_eb( int entry, uint8 value ) { m_end_color.b = value; }\r\nvoid CNgcParticleFlat::plat_set_ea( int entry, uint8 value ) { m_end_color.a = value; }\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleFlat::plat_render( void )\r\n{\r\n\tNxNgc::sMaterialHeader\t\tmat;\r\n\tNxNgc::sMaterialPassHeader\tpass;\r\n\r\n\t// Header.\r\n\tmat.m_checksum\t\t\t= 0xa9db601e;   // particle \r\n\tmat.m_passes\t\t\t= 1;\r\n\tmat.m_alpha_cutoff\t\t= 1;\r\n\tmat.m_flags\t\t\t\t= (1<<1);\t\t// 2 sided.\r\n//\tmat.m_shininess\t\t\t= 0.0f;\r\n\r\n\t// Pass 0.\r\n\tpass.m_texture.p_data\t= mp_engine_texture;\r\n\tpass.m_flags\t\t\t= ( mp_engine_texture ? (1<<0) : 0 ) | (1<<5) | (1<<6);\t\t// textured, clamped.\r\n\tpass.m_filter\t\t\t= 0;\r\n\tpass.m_blend_mode\t\t= (unsigned char)m_blend;\r\n\tpass.m_alpha_fix\t\t= (unsigned char)m_fix; \r\n\tpass.m_k\t\t\t\t= 0;\r\n\tpass.m_color.r\t\t\t= 128;\r\n\tpass.m_color.g\t\t\t= 128;\r\n\tpass.m_color.b\t\t\t= 128;\r\n\tpass.m_color.a\t\t\t= 255;\r\n\r\n\tNxNgc::multi_mesh( &mat, &pass, true, true );\r\n\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t// Draw the particles.\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\tNsMatrix*\tp_matrix\t= &NxNgc::EngineGlobals.camera;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\r\n\tNsVector\tup( 0.0f, 1.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tNsVector screen_right;\r\n\tNsVector screen_up;\r\n\tscreen_right.cross( *p_matrix->getAt(), up );\r\n\tscreen_up.cross( screen_right, *p_matrix->getAt());\r\n\r\n\tscreen_right.normalize();\r\n\tscreen_up.normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tif ( mp_engine_texture )\r\n\t{\r\n\t\tGX::SetVtxDesc( 3, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\t}\r\n\tif ( m_num_particles > 0 ) GX::Begin( GX_QUADS, GX_VTXFMT0, m_num_particles * 4 );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v = mp_vertices; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\t\t\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[4];\r\n\t\r\n\t\tVECScale((Vec*)&screen_right, (Vec*)&ss_right, w );\r\n\t\tVECScale((Vec*)&screen_up, (Vec*)&ss_up, h );\r\n\t\r\n\t\ttmp[0]\t\t= pos - ss_right + ss_up;\r\n\t\ttmp[1]\t\t= pos + ss_right + ss_up;\t\t\r\n\t\ttmp[2]\t\t= pos + ss_right - ss_up;\t\t\r\n\t\ttmp[3]\t\t= pos - ss_right - ss_up;\t\t\r\n\t\r\n\t\tGXColor color;\r\n\t\tGXColor *p_col0;\r\n\t\tGXColor *p_col1;\r\n\t\t\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = &m_start_color;\r\n\t\t\t\tp_col1 = &m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = &m_mid_color;\r\n\t\t\t\tp_col1 = &m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = &m_start_color;\r\n\t\t\tp_col1 = &m_end_color;\r\n\t\t}\r\n\r\n\t\tGXColor start = *p_col0;\r\n\t\tGXColor end = *p_col1;\r\n\r\n\t\tcolor.r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\tcolor.g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\tcolor.b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\tcolor.a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\r\n\t\tGX::Position3f32( tmp[0][X], tmp[0][Y], tmp[0][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 0.0f, 0.0f );\r\n\r\n\t\tGX::Position3f32( tmp[1][X], tmp[1][Y], tmp[1][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 1.0f, 0.0f );\r\n\r\n\t\tGX::Position3f32( tmp[2][X], tmp[2][Y], tmp[2][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 1.0f, 1.0f );\r\n\r\n\t\tGX::Position3f32( tmp[3][X], tmp[3][Y], tmp[3][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 0.0f, 1.0f );\r\n\t}\r\n\r\n\tif ( m_num_particles > 0 ) GX::End();\r\n}\r\n\r\n} // Nx\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleflat.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLEFLAT_H__\r\n#define\t__GFX_P_NX_PARTICLEFLAT_H__\r\n    \r\n#include \"gfx/Ngc/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CNgcParticleFlat : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCNgcParticleFlat();\r\n\t\t\t\t\t\t\tCNgcParticleFlat( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CNgcParticleFlat();\r\n\r\n//\tNxNgc::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\t//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint8\t\t\t\t\tm_blend;\r\n\tuint8\t\t\t\t\tm_fix;\r\n\tuint8\t\t\t\t\tm_pad0;\r\n\tuint8\t\t\t\t\tm_pad1;\r\n\r\n\tGXColor\t\t\t\t\tm_start_color;\t\t\t\t// Start color for each corner.\r\n\tGXColor\t\t\t\t\tm_mid_color;\t\t\t\t// Mid color for each corner.\r\n\tGXColor\t\t\t\t\tm_end_color;\t\t\t\t// End color for each corner.\r\n\tNxNgc::sTexture *\t\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleglow.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/Ngc/nx/render.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n#include \"gfx/Ngc/nx/mesh.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\n#include \"gfx/Ngc/p_nxparticleGlow.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleGlow::CNgcParticleGlow()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleGlow::CNgcParticleGlow( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxNgc::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CNgcTexture *p_Ngc_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = (uint8)get_texture_blend( blendmode_checksum );\r\n\tm_fix = fix;\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 3; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n\r\n\tm_num_segments = num_segments;\r\n\tm_split = split;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleGlow::~CNgcParticleGlow()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleGlow::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleGlow::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleGlow::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CNgcParticleGlow::plat_get_num_particle_colors( void ) { return 3; }\r\nint CNgcParticleGlow::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CNgcParticleGlow::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CNgcParticleGlow::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CNgcParticleGlow::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CNgcParticleGlow::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CNgcParticleGlow::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CNgcParticleGlow::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CNgcParticleGlow::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CNgcParticleGlow::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CNgcParticleGlow::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CNgcParticleGlow::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CNgcParticleGlow::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CNgcParticleGlow::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleGlow::plat_render( void )\r\n{\r\n\tNxNgc::sMaterialHeader\t\tmat;\r\n\tNxNgc::sMaterialPassHeader\tpass;\r\n\r\n\t// Header.\r\n\tmat.m_checksum\t\t\t= 0xa9db601e;   // particle \r\n\tmat.m_passes\t\t\t= 1;\r\n\tmat.m_alpha_cutoff\t\t= 1;\r\n\tmat.m_flags\t\t\t\t= (1<<1);\t\t// 2 sided.\r\n//\tmat.m_shininess\t\t\t= 0.0f;\r\n\r\n\t// Pass 0.\r\n\tpass.m_texture.p_data\t= mp_engine_texture;\r\n\tpass.m_flags\t\t\t= ( mp_engine_texture ? (1<<0) : 0 ) | (1<<5) | (1<<6);\t\t// textured, clamped.\r\n\tpass.m_filter\t\t\t= 0;\r\n\tpass.m_blend_mode\t\t= (unsigned char)m_blend;\r\n\tpass.m_alpha_fix\t\t= (unsigned char)m_fix; \r\n\tpass.m_k\t\t\t\t= 0;\r\n\tpass.m_color.r\t\t\t= 128;\r\n\tpass.m_color.g\t\t\t= 128;\r\n\tpass.m_color.b\t\t\t= 128;\r\n\tpass.m_color.a\t\t\t= 255;\r\n\r\n\tNxNgc::multi_mesh( &mat, &pass, true, true );\r\n\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t// Draw the particles.\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\tNsMatrix*\tp_matrix\t= &NxNgc::EngineGlobals.camera;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\r\n\tNsVector\tup( 0.0f, 1.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tNsVector screen_right;\r\n\tNsVector screen_up;\r\n\tscreen_right.cross( *p_matrix->getAt(), up );\r\n\tscreen_up.cross( screen_right, *p_matrix->getAt());\r\n\r\n\tscreen_right.normalize();\r\n\tscreen_up.normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v = mp_vertices; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[4];\r\n\t\r\n\t\tVECScale((Vec*)&screen_right, (Vec*)&ss_right, w );\r\n\t\tVECScale((Vec*)&screen_up, (Vec*)&ss_up, h );\r\n\t\r\n\t\tGXColor color[3];\r\n\t\tGXColor *p_col0;\r\n\t\tGXColor *p_col1;\r\n\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 3; c++ )\r\n\t\t{\r\n\t\t\tGXColor start = *p_col0++;\r\n\t\t\tGXColor end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\r\n\t\ttmp[0]  = pos;\r\n\t\ttmp[0] += ss_right * sinf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\t\ttmp[0] += ss_up    * cosf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\r\n\t\ttmp[2]  = pos;\r\n\t\ttmp[2] += ss_right * sinf( Mth::DegToRad( 0.0f ) );\r\n\t\ttmp[2] += ss_up    * cosf( Mth::DegToRad( 0.0f ) );\r\n\r\n\t\tfor ( int lp2 = 0; lp2 < m_num_segments; lp2++ )\r\n\t\t{\r\n\t\t\ttmp[1]  = pos;\r\n\t\t\ttmp[1] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\t\t\ttmp[1] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\r\n\t\t\ttmp[3]  = pos;\r\n\t\t\ttmp[3] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) );\r\n\t\t\ttmp[3] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) );\r\n\r\n\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 5 );\r\n\r\n\t\t\tGX::Position3f32( pos[X], pos[Y], pos[Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[0][X], tmp[0][Y], tmp[0][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[1][X], tmp[1][Y], tmp[1][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[2][X], tmp[2][Y], tmp[2][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[2]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[3][X], tmp[3][Y], tmp[3][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[2]) );\r\n\r\n\t\t\tGX::End();\r\n\r\n\t\t\ttmp[0] = tmp[1];\r\n\t\t\ttmp[2] = tmp[3];\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleglow.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLEGlow_H__\r\n#define\t__GFX_P_NX_PARTICLEGlow_H__\r\n    \r\n#include \"gfx/Ngc/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CNgcParticleGlow : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCNgcParticleGlow();\r\n\t\t\t\t\t\t\tCNgcParticleGlow( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CNgcParticleGlow();\r\n\r\n//\tNxNgc::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint8\t\t\t\t\tm_blend;\r\n\tuint8\t\t\t\t\tm_fix;\r\n\tuint8\t\t\t\t\tm_pad0;\r\n\tuint8\t\t\t\t\tm_pad1;\r\n\r\n//\tNxNgc::sParticleSystem*\tmp_engine_particle;\r\n\tint\t\t\t\t\t\tm_num_segments;\r\n\tfloat\t\t\t\t\tm_split;\r\n\tGXColor\t\t\t\t\tm_start_color[3];\t\t\t// Start color for each corner.\r\n\tGXColor\t\t\t\t\tm_mid_color[3];\t\t\t\t// Mid color for each corner.\r\n\tGXColor\t\t\t\t\tm_end_color[3];\t\t\t\t// End color for each corner.\r\n\tNxNgc::sTexture *\t\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleglowribbontrail.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/Ngc/nx/render.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n#include \"gfx/Ngc/nx/mesh.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\n#include \"gfx/Ngc/p_nxparticleGlowRibbonTrail.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleGlowRibbonTrail::CNgcParticleGlowRibbonTrail()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleGlowRibbonTrail::CNgcParticleGlowRibbonTrail( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float*[( history + 1)];\r\n\tfor ( int lp = 0; lp < ( history + 1 ); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxNgc::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CNgcTexture *p_Ngc_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = (uint8)get_texture_blend( blendmode_checksum );\r\n\tm_fix = fix;\r\n\r\n\t// Default color.\r\n\tm_start_color = new GXColor[m_num_vertex_buffers+3];\r\n\tm_mid_color = new GXColor[m_num_vertex_buffers+3];\r\n\tm_end_color = new GXColor[m_num_vertex_buffers+3];\r\n\tfor ( int lp = 0; lp < (m_num_vertex_buffers+3); lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n\r\n\tm_num_segments = num_segments;\r\n\tm_split = split;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleGlowRibbonTrail::~CNgcParticleGlowRibbonTrail()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\r\n\tdelete [] m_start_color;\r\n\tdelete [] m_mid_color;\r\n\tdelete [] m_end_color;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleGlowRibbonTrail::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleGlowRibbonTrail::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleGlowRibbonTrail::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CNgcParticleGlowRibbonTrail::plat_get_num_particle_colors( void ) { return m_num_vertex_buffers + 3; }\r\nint CNgcParticleGlowRibbonTrail::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CNgcParticleGlowRibbonTrail::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CNgcParticleGlowRibbonTrail::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CNgcParticleGlowRibbonTrail::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CNgcParticleGlowRibbonTrail::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CNgcParticleGlowRibbonTrail::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CNgcParticleGlowRibbonTrail::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CNgcParticleGlowRibbonTrail::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CNgcParticleGlowRibbonTrail::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CNgcParticleGlowRibbonTrail::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CNgcParticleGlowRibbonTrail::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CNgcParticleGlowRibbonTrail::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CNgcParticleGlowRibbonTrail::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleGlowRibbonTrail::plat_render( void )\r\n{\r\n\tNxNgc::sMaterialHeader\t\tmat;\r\n\tNxNgc::sMaterialPassHeader\tpass;\r\n\r\n\t// Header.\r\n\tmat.m_checksum\t\t\t= 0xa9db601e;   // particle \r\n\tmat.m_passes\t\t\t= 1;\r\n\tmat.m_alpha_cutoff\t\t= 1;\r\n\tmat.m_flags\t\t\t\t= (1<<1);\t\t// 2 sided.\r\n//\tmat.m_shininess\t\t\t= 0.0f;\r\n\r\n\t// Pass 0.\r\n\tpass.m_texture.p_data\t= mp_engine_texture;\r\n\tpass.m_flags\t\t\t= ( mp_engine_texture ? (1<<0) : 0 ) | (1<<5) | (1<<6);\t\t// textured, clamped.\r\n\tpass.m_filter\t\t\t= 0;\r\n\tpass.m_blend_mode\t\t= (unsigned char)m_blend;\r\n\tpass.m_alpha_fix\t\t= (unsigned char)m_fix; \r\n\tpass.m_k\t\t\t\t= 0;\r\n\tpass.m_color.r\t\t\t= 128;\r\n\tpass.m_color.g\t\t\t= 128;\r\n\tpass.m_color.b\t\t\t= 128;\r\n\tpass.m_color.a\t\t\t= 255;\r\n\r\n\tNxNgc::multi_mesh( &mat, &pass, true, true );\r\n\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t// Draw the ribbontrail.\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\tNsMatrix*\tp_matrix\t= &NxNgc::EngineGlobals.camera;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tMth::Vector at( p_matrix->getAtX(), p_matrix->getAtY(), p_matrix->getAtZ(), 0.0f );\r\n\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\tscreen_right.Normalize();\r\n\tscreen_up.Normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tGXColor color[3];\r\n\tGXColor *p_col0;\r\n\tGXColor *p_col1;\r\n\r\n\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array; lp < m_num_particles; lp++, p_particle++ )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tMth::Vector\tpos[2];\r\n\t\tp_v = &mp_vertices[0][lp*3];\r\n\t\tpos[0].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tp_v = &mp_vertices[1][lp*3];\r\n\t\tpos[1].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\r\n\t\tMth::Vector\tpart_vec = pos[1] - pos[0];\r\n\t\tMth::Vector perp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\tperp_vec.Normalize();\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\t\t\r\n\t\tMth::Vector tmp[4];\r\n\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = &m_start_color[3];\r\n\t\t\t\tp_col1 = &m_mid_color[3];\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = &m_mid_color[3];\r\n\t\t\t\tp_col1 = &m_end_color[3];\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = &m_start_color[3];\r\n\t\t\tp_col1 = &m_end_color[3];\r\n\t\t}\r\n\r\n\t\tGXColor start = *p_col0++;\r\n\t\tGXColor end = *p_col1++;\r\n\r\n\t\tcolor[0].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\tcolor[0].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\tcolor[0].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\tcolor[0].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\r\n\t\ttmp[0]\t\t= pos[0] + ( perp_vec * w * m_split );\r\n\t\ttmp[1]\t\t= pos[0] - ( perp_vec * w * m_split );\r\n\r\n\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 * ( m_num_vertex_buffers - 1 ) );\r\n\r\n\t\tfor ( int c = 1; c < m_num_vertex_buffers; c++ )\r\n\t\t{\r\n\t\t\tstart = *p_col0++;\r\n\t\t\tend = *p_col1++;\r\n\r\n\t\t\tcolor[1].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[1].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[1].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[1].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\r\n\t\t\tif ( c > 1 )\r\n\t\t\t{\r\n\t\t\t\tp_v = &mp_vertices[c][lp*3];\r\n\t\t\t\tpos[1].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\t\t\tpart_vec = pos[1] - pos[0];\r\n\t\t\t\tperp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\t\t\tperp_vec.Normalize();\r\n\t\t\t}\r\n\r\n\t\t\ttmp[2]\t\t= pos[1] - ( perp_vec * w * m_split );\r\n\t\t\ttmp[3]\t\t= pos[1] + ( perp_vec * w * m_split );\r\n\r\n\t\t\tGX::Position3f32( tmp[0][X], tmp[0][Y], tmp[0][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[1][X], tmp[1][Y], tmp[1][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[2][X], tmp[2][Y], tmp[2][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[3][X], tmp[3][Y], tmp[3][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\t\tcolor[0] = color[1];\r\n\t\t\tpos[0] = pos[1];\r\n\t\t\ttmp[0] = tmp[3];\r\n\t\t\ttmp[1] = tmp[2];\r\n\t\t}\r\n\r\n\t\tGX::End();\r\n\r\n\t\t// Draw the glow.\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tp_v = &mp_vertices[0][lp*3];\r\n\t\tpos[0].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\r\n\t\tss_right\t= screen_right * w;\r\n\t\tss_up\t\t= screen_up * h;\r\n\t\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 3; c++ )\r\n\t\t{\r\n\t\t\tGXColor start = *p_col0++;\r\n\t\t\tGXColor end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\r\n\t\ttmp[0]  = pos[0];\r\n\t\ttmp[0] += ss_right * sinf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\t\ttmp[0] += ss_up    * cosf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\r\n\t\ttmp[2]  = pos[0];\r\n\t\ttmp[2] += ss_right * sinf( Mth::DegToRad( 0.0f ) );\r\n\t\ttmp[2] += ss_up    * cosf( Mth::DegToRad( 0.0f ) );\r\n\r\n\t\tfor ( int lp2 = 0; lp2 < m_num_segments; lp2++ )\r\n\t\t{\r\n\t\t\ttmp[1]  = pos[0];\r\n\t\t\ttmp[1] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\t\t\ttmp[1] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\r\n\t\t\ttmp[3]  = pos[0];\r\n\t\t\ttmp[3] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) );\r\n\t\t\ttmp[3] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) );\r\n\r\n\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 5 );\r\n\r\n\t\t\tGX::Position3f32( pos[0][X], pos[0][Y], pos[0][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[0][X], tmp[0][Y], tmp[0][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[1][X], tmp[1][Y], tmp[1][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[2][X], tmp[2][Y], tmp[2][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[2]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[3][X], tmp[3][Y], tmp[3][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[2]) );\r\n\r\n\t\t\tGX::End();\r\n\r\n\t\t\ttmp[0] = tmp[1];\r\n\t\t\ttmp[2] = tmp[3];\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleglowribbontrail.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLEGlowRibbonTrail_H__\r\n#define\t__GFX_P_NX_PARTICLEGlowRibbonTrail_H__\r\n    \r\n#include \"gfx/Ngc/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CNgcParticleGlowRibbonTrail : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCNgcParticleGlowRibbonTrail();\r\n\t\t\t\t\t\t\tCNgcParticleGlowRibbonTrail( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CNgcParticleGlowRibbonTrail();\r\n\r\n//\tNxNgc::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\t//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tint\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tfloat**\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint8\t\t\t\t\tm_blend;\r\n\tuint8\t\t\t\t\tm_fix;\r\n\tuint8\t\t\t\t\tm_pad0;\r\n\tuint8\t\t\t\t\tm_pad1;\r\n\r\n\tint\t\t\t\t\t\tm_num_segments;\r\n\tfloat\t\t\t\t\tm_split;\r\n\tGXColor*\t\t\t\tm_start_color;\t\t\t\t// Start color for each corner.\r\n\tGXColor*\t\t\t\tm_mid_color;\t\t\t\t// Mid color for each corner.\r\n\tGXColor*\t\t\t\tm_end_color;\t\t\t\t// End color for each corner.\r\n\tNxNgc::sTexture *\t\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleline.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/Ngc/nx/render.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n#include \"gfx/Ngc/nx/mesh.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\n#include \"gfx/Ngc/p_nxparticleLine.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleLine::CNgcParticleLine()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleLine::CNgcParticleLine( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffers.\r\n\tmp_vertices = new float*[( history + 1)];\r\n\tfor ( int lp = 0; lp < ( history + 1 ); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxNgc::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CNgcTexture *p_Ngc_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = (uint8)get_texture_blend( blendmode_checksum );\r\n\tm_fix = fix;\r\n\r\n\t// Default color.\r\n\tm_start_color = new GXColor[m_num_vertex_buffers];\r\n\tm_mid_color = new GXColor[m_num_vertex_buffers];\r\n\tm_end_color = new GXColor[m_num_vertex_buffers];\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleLine::~CNgcParticleLine()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleLine::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleLine::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleLine::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CNgcParticleLine::plat_get_num_particle_colors( void ) { return 2; }\r\nint CNgcParticleLine::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CNgcParticleLine::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CNgcParticleLine::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CNgcParticleLine::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CNgcParticleLine::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CNgcParticleLine::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CNgcParticleLine::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CNgcParticleLine::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CNgcParticleLine::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CNgcParticleLine::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CNgcParticleLine::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CNgcParticleLine::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CNgcParticleLine::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleLine::plat_render( void )\r\n{\r\n\tNxNgc::sMaterialHeader\t\tmat;\r\n\tNxNgc::sMaterialPassHeader\tpass;\r\n\r\n\t// Header.\r\n\tmat.m_checksum\t\t\t= 0xa9db601e;   // particle \r\n\tmat.m_passes\t\t\t= 1;\r\n\tmat.m_alpha_cutoff\t\t= 1;\r\n\tmat.m_flags\t\t\t\t= (1<<1);\t\t// 2 sided.\r\n//\tmat.m_shininess\t\t\t= 0.0f;\r\n\r\n\t// Pass 0.\r\n\tpass.m_texture.p_data\t= mp_engine_texture;\r\n\tpass.m_flags\t\t\t= ( mp_engine_texture ? (1<<0) : 0 ) | (1<<5) | (1<<6);\t\t// textured, clamped.\r\n\tpass.m_filter\t\t\t= 0;\r\n\tpass.m_blend_mode\t\t= (unsigned char)m_blend;\r\n\tpass.m_alpha_fix\t\t= (unsigned char)m_fix; \r\n\tpass.m_k\t\t\t\t= 0;\r\n\tpass.m_color.r\t\t\t= 128;\r\n\tpass.m_color.g\t\t\t= 128;\r\n\tpass.m_color.b\t\t\t= 128;\r\n\tpass.m_color.a\t\t\t= 255;\r\n\r\n\tNxNgc::multi_mesh( &mat, &pass, true, true );\r\n\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t// Draw the particles.\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v0;\r\n\tfloat\t\t\t*p_v1;\r\n\r\n\tGXColor color[2];\r\n\tGXColor *p_col0;\r\n\tGXColor *p_col1;\r\n\r\n\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\r\n\tif ( m_num_particles > 0 ) GX::Begin( GX_LINES, GX_VTXFMT0, m_num_particles * 2 );\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v0 = mp_vertices[0], p_v1 = mp_vertices[(m_num_vertex_buffers-1)]; lp < m_num_particles; lp++, p_particle++, p_v0 += 3, p_v1 += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 2; c++ )\r\n\t\t{\r\n\t\t\tGXColor start = *p_col0++;\r\n\t\t\tGXColor end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos0( p_v0[0] + m_pos[X], p_v0[1] + m_pos[Y], p_v0[2] + m_pos[Z] );\r\n\t\tMth::Vector\tpos1( p_v1[0] + m_pos[X], p_v1[1] + m_pos[Y], p_v1[2] + m_pos[Z] );\r\n\t\r\n\t\tGX::Position3f32( pos0[X], pos0[Y], pos0[Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\t\r\n\t\tGX::Position3f32( pos1[X], pos1[Y], pos1[Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\t}\r\n\tif ( m_num_particles > 0 ) GX::End();\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleline.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLELine_H__\r\n#define\t__GFX_P_NX_PARTICLELine_H__\r\n    \r\n#include \"gfx/Ngc/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CNgcParticleLine : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCNgcParticleLine();\r\n\t\t\t\t\t\t\tCNgcParticleLine( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CNgcParticleLine();\r\n\r\n//\tNxNgc::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\t//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tint\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tfloat**\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint8\t\t\t\t\tm_blend;\r\n\tuint8\t\t\t\t\tm_fix;\r\n\tuint8\t\t\t\t\tm_pad0;\r\n\tuint8\t\t\t\t\tm_pad1;\r\n\r\n\tGXColor*\t\t\t\tm_start_color;\t\t\t\t// Start color for each corner.\r\n\tGXColor*\t\t\t\tm_mid_color;\t\t\t\t// Mid color for each corner.\r\n\tGXColor*\t\t\t\tm_end_color;\t\t\t\t// End color for each corner.\r\n\tNxNgc::sTexture *\t\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleribbon.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/Ngc/nx/render.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n#include \"gfx/Ngc/nx/mesh.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\n#include \"gfx/Ngc/p_nxparticleRibbon.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleRibbon::CNgcParticleRibbon()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleRibbon::CNgcParticleRibbon( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float*[( history + 1)];\r\n\tfor ( int lp = 0; lp < ( history + 1 ); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxNgc::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CNgcTexture *p_Ngc_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = (uint8)get_texture_blend( blendmode_checksum );\r\n\tm_fix = fix;\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 2; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleRibbon::~CNgcParticleRibbon()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleRibbon::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleRibbon::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleRibbon::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CNgcParticleRibbon::plat_get_num_particle_colors( void ) { return 2; }\r\nint CNgcParticleRibbon::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CNgcParticleRibbon::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CNgcParticleRibbon::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CNgcParticleRibbon::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CNgcParticleRibbon::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CNgcParticleRibbon::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CNgcParticleRibbon::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CNgcParticleRibbon::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CNgcParticleRibbon::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CNgcParticleRibbon::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CNgcParticleRibbon::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CNgcParticleRibbon::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CNgcParticleRibbon::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleRibbon::plat_render( void )\r\n{\r\n\tNxNgc::sMaterialHeader\t\tmat;\r\n\tNxNgc::sMaterialPassHeader\tpass;\r\n\r\n\t// Header.\r\n\tmat.m_checksum\t\t\t= 0xa9db601e;   // particle \r\n\tmat.m_passes\t\t\t= 1;\r\n\tmat.m_alpha_cutoff\t\t= 1;\r\n\tmat.m_flags\t\t\t\t= (1<<1);\t\t// 2 sided.\r\n//\tmat.m_shininess\t\t\t= 0.0f;\r\n\r\n\t// Pass 0.\r\n\tpass.m_texture.p_data\t= mp_engine_texture;\r\n\tpass.m_flags\t\t\t= ( mp_engine_texture ? (1<<0) : 0 ) | (1<<5) | (1<<6);\t\t// textured, clamped.\r\n\tpass.m_filter\t\t\t= 0;\r\n\tpass.m_blend_mode\t\t= (unsigned char)m_blend;\r\n\tpass.m_alpha_fix\t\t= (unsigned char)m_fix; \r\n\tpass.m_k\t\t\t\t= 0;\r\n\tpass.m_color.r\t\t\t= 128;\r\n\tpass.m_color.g\t\t\t= 128;\r\n\tpass.m_color.b\t\t\t= 128;\r\n\tpass.m_color.a\t\t\t= 255;\r\n\r\n\tNxNgc::multi_mesh( &mat, &pass, true, true );\r\n\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t// Draw the particles.\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v0;\r\n\tfloat\t\t\t*p_v1;\r\n\r\n\tGXColor color[2];\r\n\tGXColor *p_col0;\r\n\tGXColor *p_col1;\r\n\r\n\tNsMatrix*\tp_matrix\t= &NxNgc::EngineGlobals.camera;\r\n\tMth::Vector at( p_matrix->getAtX(), p_matrix->getAtY(), p_matrix->getAtZ(), 0.0f );\r\n\r\n\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\r\n\tif ( m_num_particles > 0 ) GX::Begin( GX_QUADS, GX_VTXFMT0, m_num_particles * 4 );\r\n\t\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v0 = mp_vertices[0], p_v1 = mp_vertices[(m_num_vertex_buffers-1)]; lp < m_num_particles; lp++, p_particle++, p_v0 += 3, p_v1 += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\t\t\r\n\t\tMth::Vector\tpos0( p_v0[0] + m_pos[X], p_v0[1] + m_pos[Y], p_v0[2] + m_pos[Z] );\r\n\t\tMth::Vector\tpos1( p_v1[0] + m_pos[X], p_v1[1] + m_pos[Y], p_v1[2] + m_pos[Z] );\r\n\r\n\t\tMth::Vector\tpart_vec = pos1 - pos0;\r\n\t\tMth::Vector perp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\tperp_vec.Normalize();\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector tmp[4];\r\n\t\r\n\t\ttmp[0]\t\t= pos0 + ( perp_vec * w );\r\n\t\ttmp[1]\t\t= pos0 - ( perp_vec * w );\r\n\t\ttmp[2]\t\t= pos1 - ( perp_vec * w );\r\n\t\ttmp[3]\t\t= pos1 + ( perp_vec * w );\r\n\t\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 2; c++ )\r\n\t\t{\r\n\t\t\tGXColor start = *p_col0++;\r\n\t\t\tGXColor end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\r\n\t\tGX::Position3f32( tmp[0][X], tmp[0][Y], tmp[0][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\r\n\t\tGX::Position3f32( tmp[1][X], tmp[1][Y], tmp[1][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\r\n\t\tGX::Position3f32( tmp[2][X], tmp[2][Y], tmp[2][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\tGX::Position3f32( tmp[3][X], tmp[3][Y], tmp[3][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\t}\r\n\t\r\n\tif ( m_num_particles > 0 ) GX::End();\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleribbon.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLERibbon_H__\r\n#define\t__GFX_P_NX_PARTICLERibbon_H__\r\n    \r\n#include \"gfx/Ngc/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CNgcParticleRibbon : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCNgcParticleRibbon();\r\n\t\t\t\t\t\t\tCNgcParticleRibbon( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CNgcParticleRibbon();\r\n\r\n//\tNxNgc::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\t//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tint\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tfloat**\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint8\t\t\t\t\tm_blend;\r\n\tuint8\t\t\t\t\tm_fix;\r\n\tuint8\t\t\t\t\tm_pad0;\r\n\tuint8\t\t\t\t\tm_pad1;\r\n\r\n\tGXColor\t\t\t\t\tm_start_color[2];\t\t\t// Start color for each corner.\r\n\tGXColor\t\t\t\t\tm_mid_color[2];\t\t\t\t// Mid color for each corner.\r\n\tGXColor\t\t\t\t\tm_end_color[2];\t\t\t\t// End color for each corner.\r\n\tNxNgc::sTexture *\t\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleribbontrail.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/Ngc/nx/render.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n#include \"gfx/Ngc/nx/mesh.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\n#include \"gfx/Ngc/p_nxparticleRibbonTrail.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleRibbonTrail::CNgcParticleRibbonTrail()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleRibbonTrail::CNgcParticleRibbonTrail( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float*[( history + 1)];\r\n\tfor ( int lp = 0; lp < ( history + 1 ); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxNgc::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CNgcTexture *p_Ngc_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = (uint8)get_texture_blend( blendmode_checksum );\r\n\tm_fix = fix;\r\n\r\n\t// Default color.\r\n\tm_start_color = new GXColor[m_num_vertex_buffers];\r\n\tm_mid_color = new GXColor[m_num_vertex_buffers];\r\n\tm_end_color = new GXColor[m_num_vertex_buffers];\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleRibbonTrail::~CNgcParticleRibbonTrail()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\r\n\tdelete [] m_start_color;\r\n\tdelete [] m_mid_color;\r\n\tdelete [] m_end_color;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleRibbonTrail::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleRibbonTrail::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleRibbonTrail::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CNgcParticleRibbonTrail::plat_get_num_particle_colors( void ) { return m_num_vertex_buffers; }\r\nint CNgcParticleRibbonTrail::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CNgcParticleRibbonTrail::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CNgcParticleRibbonTrail::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CNgcParticleRibbonTrail::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CNgcParticleRibbonTrail::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CNgcParticleRibbonTrail::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CNgcParticleRibbonTrail::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CNgcParticleRibbonTrail::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CNgcParticleRibbonTrail::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CNgcParticleRibbonTrail::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CNgcParticleRibbonTrail::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CNgcParticleRibbonTrail::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CNgcParticleRibbonTrail::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleRibbonTrail::plat_render( void )\r\n{\r\n\tNxNgc::sMaterialHeader\t\tmat;\r\n\tNxNgc::sMaterialPassHeader\tpass;\r\n\r\n\t// Header.\r\n\tmat.m_checksum\t\t\t= 0xa9db601e;   // particle \r\n\tmat.m_passes\t\t\t= 1;\r\n\tmat.m_alpha_cutoff\t\t= 1;\r\n\tmat.m_flags\t\t\t\t= (1<<1);\t\t// 2 sided.\r\n//\tmat.m_shininess\t\t\t= 0.0f;\r\n\r\n\t// Pass 0.\r\n\tpass.m_texture.p_data\t= mp_engine_texture;\r\n\tpass.m_flags\t\t\t= ( mp_engine_texture ? (1<<0) : 0 ) | (1<<5) | (1<<6);\t\t// textured, clamped.\r\n\tpass.m_filter\t\t\t= 0;\r\n\tpass.m_blend_mode\t\t= (unsigned char)m_blend;\r\n\tpass.m_alpha_fix\t\t= (unsigned char)m_fix; \r\n\tpass.m_k\t\t\t\t= 0;\r\n\tpass.m_color.r\t\t\t= 128;\r\n\tpass.m_color.g\t\t\t= 128;\r\n\tpass.m_color.b\t\t\t= 128;\r\n\tpass.m_color.a\t\t\t= 255;\r\n\r\n\tNxNgc::multi_mesh( &mat, &pass, true, true );\r\n\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t// Draw the particles.\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tGXColor color[2];\r\n\tGXColor *p_col0;\r\n\tGXColor *p_col1;\r\n\r\n\tNsMatrix*\tp_matrix\t= &NxNgc::EngineGlobals.camera;\r\n\tMth::Vector at( p_matrix->getAtX(), p_matrix->getAtY(), p_matrix->getAtZ(), 0.0f );\r\n\r\n\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array; lp < m_num_particles; lp++, p_particle++ )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\t\t\r\n\t\tMth::Vector\tpos[2];\r\n\t\tp_v = &mp_vertices[0][lp*3];\r\n\t\tpos[0].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tp_v = &mp_vertices[1][lp*3];\r\n\t\tpos[1].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\r\n\t\tMth::Vector\tpart_vec = pos[1] - pos[0];\r\n\t\tMth::Vector perp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\tperp_vec.Normalize();\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector tmp[4];\r\n\t\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tGXColor start = *p_col0++;\r\n\t\tGXColor end = *p_col1++;\r\n\r\n\t\tcolor[0].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\tcolor[0].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\tcolor[0].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\tcolor[0].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\r\n\t\ttmp[0]\t\t= pos[0] + ( perp_vec * w );\r\n\t\ttmp[1]\t\t= pos[0] - ( perp_vec * w );\r\n\r\n\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 * ( m_num_vertex_buffers - 1 ) );\r\n\r\n\t\tfor ( int c = 1; c < m_num_vertex_buffers; c++ )\r\n\t\t{\r\n\t\t\tstart = *p_col0++;\r\n\t\t\tend = *p_col1++;\r\n\r\n\t\t\tcolor[1].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[1].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[1].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[1].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\r\n\t\t\tif ( c > 1 )\r\n\t\t\t{\r\n\t\t\t\tp_v = &mp_vertices[c][lp*3];\r\n\t\t\t\tpos[1].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\t\t\tpart_vec = pos[1] - pos[0];\r\n\t\t\t\tperp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\t\t\tperp_vec.Normalize();\r\n\t\t\t}\r\n\r\n\t\t\ttmp[2]\t\t= pos[1] - ( perp_vec * w );\r\n\t\t\ttmp[3]\t\t= pos[1] + ( perp_vec * w );\r\n\r\n\t\t\tGX::Position3f32( tmp[0][X], tmp[0][Y], tmp[0][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[1][X], tmp[1][Y], tmp[1][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[2][X], tmp[2][Y], tmp[2][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[3][X], tmp[3][Y], tmp[3][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\t\tcolor[0] = color[1];\r\n\t\t\tpos[0] = pos[1];\r\n\t\t\ttmp[0] = tmp[3];\r\n\t\t\ttmp[1] = tmp[2];\r\n\t\t}\r\n\t\tGX::End();\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleribbontrail.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLERibbonTrail_H__\r\n#define\t__GFX_P_NX_PARTICLERibbonTrail_H__\r\n    \r\n#include \"gfx/Ngc/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CNgcParticleRibbonTrail : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCNgcParticleRibbonTrail();\r\n\t\t\t\t\t\t\tCNgcParticleRibbonTrail( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CNgcParticleRibbonTrail();\r\n\r\n//\tNxNgc::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\t//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tint\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tfloat**\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint8\t\t\t\t\tm_blend;\r\n\tuint8\t\t\t\t\tm_fix;\r\n\tuint8\t\t\t\t\tm_pad0;\r\n\tuint8\t\t\t\t\tm_pad1;\r\n\r\n\tGXColor*\t\t\t\tm_start_color;\t\t\t\t// Start color for each corner.\r\n\tGXColor*\t\t\t\tm_mid_color;\t\t\t\t// Mid color for each corner.\r\n\tGXColor*\t\t\t\tm_end_color;\t\t\t\t// End color for each corner.\r\n\tNxNgc::sTexture *\t\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleshaded.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/Ngc/nx/render.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n#include \"gfx/Ngc/nx/mesh.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\n#include \"gfx/Ngc/p_nxparticleShaded.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleShaded::CNgcParticleShaded()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleShaded::CNgcParticleShaded( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxNgc::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CNgcTexture *p_Ngc_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = (uint8)get_texture_blend( blendmode_checksum );\r\n\tm_fix = fix;\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 4; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleShaded::~CNgcParticleShaded()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleShaded::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleShaded::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleShaded::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CNgcParticleShaded::plat_get_num_particle_colors( void ) { return 4; }\r\nint CNgcParticleShaded::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CNgcParticleShaded::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CNgcParticleShaded::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CNgcParticleShaded::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CNgcParticleShaded::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CNgcParticleShaded::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CNgcParticleShaded::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CNgcParticleShaded::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CNgcParticleShaded::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CNgcParticleShaded::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CNgcParticleShaded::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CNgcParticleShaded::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CNgcParticleShaded::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleShaded::plat_render( void )\r\n{\r\n\tNxNgc::sMaterialHeader\t\tmat;\r\n\tNxNgc::sMaterialPassHeader\tpass;\r\n\r\n\t// Header.\r\n\tmat.m_checksum\t\t\t= 0xa9db601e;   // particle \r\n\tmat.m_passes\t\t\t= 1;\r\n\tmat.m_alpha_cutoff\t\t= 1;\r\n\tmat.m_flags\t\t\t\t= (1<<1);\t\t// 2 sided.\r\n//\tmat.m_shininess\t\t\t= 0.0f;\r\n\r\n\t// Pass 0.\r\n\tpass.m_texture.p_data\t= mp_engine_texture;\r\n\tpass.m_flags\t\t\t= ( mp_engine_texture ? (1<<0) : 0 ) | (1<<5) | (1<<6);\t\t// textured, clamped.\r\n\tpass.m_filter\t\t\t= 0;\r\n\tpass.m_blend_mode\t\t= (unsigned char)m_blend;\r\n\tpass.m_alpha_fix\t\t= (unsigned char)m_fix; \r\n\tpass.m_k\t\t\t\t= 0;\r\n\tpass.m_color.r\t\t\t= 128;\r\n\tpass.m_color.g\t\t\t= 128;\r\n\tpass.m_color.b\t\t\t= 128;\r\n\tpass.m_color.a\t\t\t= 255;\r\n\r\n\tNxNgc::multi_mesh( &mat, &pass, true, true );\r\n\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t// Draw the particles.\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\tNsMatrix*\tp_matrix\t= &NxNgc::EngineGlobals.camera;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\r\n\tNsVector\tup( 0.0f, 1.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tNsVector screen_right;\r\n\tNsVector screen_up;\r\n\tscreen_right.cross( *p_matrix->getAt(), up );\r\n\tscreen_up.cross( screen_right, *p_matrix->getAt());\r\n\r\n\tscreen_right.normalize();\r\n\tscreen_up.normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tif ( mp_engine_texture )\r\n\t{\r\n\t\tGX::SetVtxDesc( 3, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\t}\r\n\tif ( m_num_particles > 0 ) GX::Begin( GX_QUADS, GX_VTXFMT0, m_num_particles * 4 );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v = mp_vertices; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\t\t\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[4];\r\n\t\r\n\t\tVECScale((Vec*)&screen_right, (Vec*)&ss_right, w );\r\n\t\tVECScale((Vec*)&screen_up, (Vec*)&ss_up, h );\r\n\t\r\n\t\ttmp[0]\t\t= pos - ss_right + ss_up;\r\n\t\ttmp[1]\t\t= pos + ss_right + ss_up;\t\t\r\n\t\ttmp[2]\t\t= pos + ss_right - ss_up;\t\t\r\n\t\ttmp[3]\t\t= pos - ss_right - ss_up;\t\t\r\n\t\r\n\t\tGXColor color[4];\r\n\t\tGXColor *p_col0;\r\n\t\tGXColor *p_col1;\r\n\t\t\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 4; c++ )\r\n\t\t{\r\n\t\t\tGXColor start = *p_col0++;\r\n\t\t\tGXColor end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\t\r\n\t\tGX::Position3f32( tmp[0][X], tmp[0][Y], tmp[0][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 0.0f, 0.0f );\r\n\r\n\t\tGX::Position3f32( tmp[1][X], tmp[1][Y], tmp[1][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 1.0f, 0.0f );\r\n\r\n\t\tGX::Position3f32( tmp[2][X], tmp[2][Y], tmp[2][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[2]) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 1.0f, 1.0f );\r\n\r\n\t\tGX::Position3f32( tmp[3][X], tmp[3][Y], tmp[3][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[3]) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 0.0f, 1.0f );\r\n\t}\r\n\r\n\tif ( m_num_particles > 0 ) GX::End();\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticleshaded.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLEShaded_H__\r\n#define\t__GFX_P_NX_PARTICLEShaded_H__\r\n    \r\n#include \"gfx/Ngc/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CNgcParticleShaded : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCNgcParticleShaded();\r\n\t\t\t\t\t\t\tCNgcParticleShaded( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CNgcParticleShaded();\r\n\r\n//\tNxNgc::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint8\t\t\t\t\tm_blend;\r\n\tuint8\t\t\t\t\tm_fix;\r\n\tuint8\t\t\t\t\tm_pad0;\r\n\tuint8\t\t\t\t\tm_pad1;\r\n\r\n\tGXColor\t\t\t\t\tm_start_color[4];\t\t\t// Start color for each corner.\r\n\tGXColor\t\t\t\t\tm_mid_color[4];\t\t\t\t// Mid color for each corner.\r\n\tGXColor\t\t\t\t\tm_end_color[4];\t\t\t\t// End color for each corner.\r\n\tNxNgc::sTexture *\t\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticlesmooth.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/Ngc/nx/render.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n#include \"gfx/Ngc/nx/mesh.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\n#include \"gfx/Ngc/p_nxparticleSmooth.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleSmooth::CNgcParticleSmooth()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleSmooth::CNgcParticleSmooth( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxNgc::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CNgcTexture *p_Ngc_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = (uint8)get_texture_blend( blendmode_checksum );\r\n\tm_fix = fix;\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 2; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleSmooth::~CNgcParticleSmooth()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleSmooth::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleSmooth::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleSmooth::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CNgcParticleSmooth::plat_get_num_particle_colors( void ) { return 2; }\r\nint CNgcParticleSmooth::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CNgcParticleSmooth::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CNgcParticleSmooth::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CNgcParticleSmooth::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CNgcParticleSmooth::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CNgcParticleSmooth::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CNgcParticleSmooth::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CNgcParticleSmooth::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CNgcParticleSmooth::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CNgcParticleSmooth::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CNgcParticleSmooth::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CNgcParticleSmooth::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CNgcParticleSmooth::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleSmooth::plat_render( void )\r\n{\r\n\tNxNgc::sMaterialHeader\t\tmat;\r\n\tNxNgc::sMaterialPassHeader\tpass;\r\n\r\n\t// Header.\r\n\tmat.m_checksum\t\t\t= 0xa9db601e;   // particle \r\n\tmat.m_passes\t\t\t= 1;\r\n\tmat.m_alpha_cutoff\t\t= 1;\r\n\tmat.m_flags\t\t\t\t= (1<<1);\t\t// 2 sided.\r\n//\tmat.m_shininess\t\t\t= 0.0f;\r\n\r\n\t// Pass 0.\r\n\tpass.m_texture.p_data\t= mp_engine_texture;\r\n\tpass.m_flags\t\t\t= ( mp_engine_texture ? (1<<0) : 0 ) | (1<<5) | (1<<6);\t\t// textured, clamped.\r\n\tpass.m_filter\t\t\t= 0;\r\n\tpass.m_blend_mode\t\t= (unsigned char)m_blend;\r\n\tpass.m_alpha_fix\t\t= (unsigned char)m_fix; \r\n\tpass.m_k\t\t\t\t= 0;\r\n\tpass.m_color.r\t\t\t= 128;\r\n\tpass.m_color.g\t\t\t= 128;\r\n\tpass.m_color.b\t\t\t= 128;\r\n\tpass.m_color.a\t\t\t= 255;\r\n\r\n\tNxNgc::multi_mesh( &mat, &pass, true, true );\r\n\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t// Draw the particles.\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\tNsMatrix*\tp_matrix\t= &NxNgc::EngineGlobals.camera;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\r\n\tNsVector\tup( 0.0f, 1.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tNsVector screen_right;\r\n\tNsVector screen_up;\r\n\tscreen_right.cross( *p_matrix->getAt(), up );\r\n\tscreen_up.cross( screen_right, *p_matrix->getAt());\r\n\r\n\tscreen_right.normalize();\r\n\tscreen_up.normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tif ( mp_engine_texture )\r\n\t{\r\n\t\tGX::SetVtxDesc( 3, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\t}\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v = mp_vertices; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\t\t\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[4];\r\n\t\r\n\t\tVECScale((Vec*)&screen_right, (Vec*)&ss_right, w );\r\n\t\tVECScale((Vec*)&screen_up, (Vec*)&ss_up, h );\r\n\t\r\n\t\ttmp[0]\t\t= pos - ss_right + ss_up;\r\n\t\ttmp[1]\t\t= pos + ss_right + ss_up;\t\t\r\n\t\ttmp[2]\t\t= pos + ss_right - ss_up;\t\t\r\n\t\ttmp[3]\t\t= pos - ss_right - ss_up;\t\t\r\n\t\r\n\t\tGXColor color[2];\r\n\t\tGXColor *p_col0;\r\n\t\tGXColor *p_col1;\r\n\t\t\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 2; c++ )\r\n\t\t{\r\n\t\t\tGXColor start = *p_col0++;\r\n\t\t\tGXColor end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\t\tGX::Begin( GX_TRIANGLEFAN, GX_VTXFMT0, 6 );\r\n\t\r\n\t\tGX::Position3f32( pos[X], pos[Y], pos[Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 0.5f, 0.5f );\r\n\r\n\t\tGX::Position3f32( tmp[0][X], tmp[0][Y], tmp[0][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 0.0f, 0.0f );\r\n\r\n\t\tGX::Position3f32( tmp[1][X], tmp[1][Y], tmp[1][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 1.0f, 0.0f );\r\n\r\n\t\tGX::Position3f32( tmp[2][X], tmp[2][Y], tmp[2][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 1.0f, 1.0f );\r\n\r\n\t\tGX::Position3f32( tmp[3][X], tmp[3][Y], tmp[3][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 0.0f, 1.0f );\r\n\r\n\t\tGX::Position3f32( tmp[0][X], tmp[0][Y], tmp[0][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\t\tif ( mp_engine_texture ) GX::TexCoord2f32( 0.0f, 0.0f );\r\n\r\n\t\tGX::End();\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticlesmooth.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLESmooth_H__\r\n#define\t__GFX_P_NX_PARTICLESmooth_H__\r\n    \r\n#include \"gfx/Ngc/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CNgcParticleSmooth : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCNgcParticleSmooth();\r\n\t\t\t\t\t\t\tCNgcParticleSmooth( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CNgcParticleSmooth();\r\n\r\n//\tNxNgc::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint8\t\t\t\t\tm_blend;\r\n\tuint8\t\t\t\t\tm_fix;\r\n\tuint8\t\t\t\t\tm_pad0;\r\n\tuint8\t\t\t\t\tm_pad1;\r\n\r\n\tGXColor\t\t\t\t\tm_start_color[2];\t\t\t// Start color for each corner.\r\n\tGXColor\t\t\t\t\tm_mid_color[2];\t\t\t\t// Mid color for each corner.\r\n\tGXColor\t\t\t\t\tm_end_color[2];\t\t\t\t// End color for each corner.\r\n\tNxNgc::sTexture *\t\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticlesmoothribbon.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/Ngc/nx/render.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n#include \"gfx/Ngc/nx/mesh.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\n#include \"gfx/Ngc/p_nxparticleSmoothRibbon.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleSmoothRibbon::CNgcParticleSmoothRibbon()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleSmoothRibbon::CNgcParticleSmoothRibbon( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float*[( history + 1)];\r\n\tfor ( int lp = 0; lp < ( history + 1 ); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxNgc::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CNgcTexture *p_Ngc_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = (uint8)get_texture_blend( blendmode_checksum );\r\n\tm_fix = fix;\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 4; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleSmoothRibbon::~CNgcParticleSmoothRibbon()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleSmoothRibbon::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleSmoothRibbon::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleSmoothRibbon::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CNgcParticleSmoothRibbon::plat_get_num_particle_colors( void ) { return 4; }\r\nint CNgcParticleSmoothRibbon::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CNgcParticleSmoothRibbon::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CNgcParticleSmoothRibbon::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CNgcParticleSmoothRibbon::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CNgcParticleSmoothRibbon::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CNgcParticleSmoothRibbon::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CNgcParticleSmoothRibbon::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CNgcParticleSmoothRibbon::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CNgcParticleSmoothRibbon::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CNgcParticleSmoothRibbon::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CNgcParticleSmoothRibbon::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CNgcParticleSmoothRibbon::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CNgcParticleSmoothRibbon::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleSmoothRibbon::plat_render( void )\r\n{\r\n\tNxNgc::sMaterialHeader\t\tmat;\r\n\tNxNgc::sMaterialPassHeader\tpass;\r\n\r\n\t// Header.\r\n\tmat.m_checksum\t\t\t= 0xa9db601e;   // particle \r\n\tmat.m_passes\t\t\t= 1;\r\n\tmat.m_alpha_cutoff\t\t= 1;\r\n\tmat.m_flags\t\t\t\t= (1<<1);\t\t// 2 sided.\r\n//\tmat.m_shininess\t\t\t= 0.0f;\r\n\r\n\t// Pass 0.\r\n\tpass.m_texture.p_data\t= mp_engine_texture;\r\n\tpass.m_flags\t\t\t= ( mp_engine_texture ? (1<<0) : 0 ) | (1<<5) | (1<<6);\t\t// textured, clamped.\r\n\tpass.m_filter\t\t\t= 0;\r\n\tpass.m_blend_mode\t\t= (unsigned char)m_blend;\r\n\tpass.m_alpha_fix\t\t= (unsigned char)m_fix; \r\n\tpass.m_k\t\t\t\t= 0;\r\n\tpass.m_color.r\t\t\t= 128;\r\n\tpass.m_color.g\t\t\t= 128;\r\n\tpass.m_color.b\t\t\t= 128;\r\n\tpass.m_color.a\t\t\t= 255;\r\n\r\n\tNxNgc::multi_mesh( &mat, &pass, true, true );\r\n\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t// Draw the particles.\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v0;\r\n\tfloat\t\t\t*p_v1;\r\n\r\n\tGXColor color[4];\r\n\tGXColor *p_col0;\r\n\tGXColor *p_col1;\r\n\r\n\tNsMatrix*\tp_matrix\t= &NxNgc::EngineGlobals.camera;\r\n\tMth::Vector at( p_matrix->getAtX(), p_matrix->getAtY(), p_matrix->getAtZ(), 0.0f );\r\n\r\n\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\t\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v0 = mp_vertices[0], p_v1 = mp_vertices[(m_num_vertex_buffers-1)]; lp < m_num_particles; lp++, p_particle++, p_v0 += 3, p_v1 += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\t\t\r\n\t\tMth::Vector\tpos0( p_v0[0] + m_pos[X], p_v0[1] + m_pos[Y], p_v0[2] + m_pos[Z] );\r\n\t\tMth::Vector\tpos1( p_v1[0] + m_pos[X], p_v1[1] + m_pos[Y], p_v1[2] + m_pos[Z] );\r\n\r\n\t\tMth::Vector\tpart_vec = pos1 - pos0;\r\n\t\tMth::Vector perp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\tperp_vec.Normalize();\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector tmp[4];\r\n\t\r\n\t\ttmp[0]\t\t= pos0 + ( perp_vec * w );\r\n\t\ttmp[1]\t\t= pos0 - ( perp_vec * w );\r\n\t\ttmp[2]\t\t= pos1 - ( perp_vec * w );\r\n\t\ttmp[3]\t\t= pos1 + ( perp_vec * w );\r\n\t\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 4; c++ )\r\n\t\t{\r\n\t\t\tGXColor start = *p_col0++;\r\n\t\t\tGXColor end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\r\n\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 );\r\n\r\n\t\tGX::Position3f32( tmp[0][X], tmp[0][Y], tmp[0][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\tGX::Position3f32( tmp[3][X], tmp[3][Y], tmp[3][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[2]) );\r\n\r\n\t\tGX::Position3f32( pos0[X], pos0[Y], pos0[Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\r\n\t\tGX::Position3f32( pos1[X], pos1[Y], pos1[Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[3]) );\r\n\t\t\r\n\t\tGX::Position3f32( tmp[1][X], tmp[1][Y], tmp[1][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\tGX::Position3f32( tmp[2][X], tmp[2][Y], tmp[2][Z] );\r\n\t\tGX::Color1u32( *((uint32*)&color[2]) );\r\n\r\n\t\tGX::End();\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticlesmoothribbon.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLESmoothRibbon_H__\r\n#define\t__GFX_P_NX_PARTICLESmoothRibbon_H__\r\n    \r\n#include \"gfx/Ngc/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CNgcParticleSmoothRibbon : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCNgcParticleSmoothRibbon();\r\n\t\t\t\t\t\t\tCNgcParticleSmoothRibbon( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CNgcParticleSmoothRibbon();\r\n\r\n//\tNxNgc::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\t//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tint\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tfloat**\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint8\t\t\t\t\tm_blend;\r\n\tuint8\t\t\t\t\tm_fix;\r\n\tuint8\t\t\t\t\tm_pad0;\r\n\tuint8\t\t\t\t\tm_pad1;\r\n\r\n\tGXColor\t\t\t\t\tm_start_color[4];\t\t\t// Start color for each corner.\r\n\tGXColor\t\t\t\t\tm_mid_color[4];\t\t\t\t// Mid color for each corner.\r\n\tGXColor\t\t\t\t\tm_end_color[4];\t\t\t\t// End color for each corner.\r\n\tNxNgc::sTexture *\t\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticlesmoothstar.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/Ngc/nx/render.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n#include \"gfx/Ngc/nx/mesh.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\n#include \"gfx/Ngc/p_nxparticleSmoothStar.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleSmoothStar::CNgcParticleSmoothStar()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleSmoothStar::CNgcParticleSmoothStar( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxNgc::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CNgcTexture *p_Ngc_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = (uint8)get_texture_blend( blendmode_checksum );\r\n\tm_fix = fix;\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 3; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n\r\n\tm_num_segments = num_segments;\r\n\tm_split = split;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleSmoothStar::~CNgcParticleSmoothStar()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleSmoothStar::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleSmoothStar::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleSmoothStar::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CNgcParticleSmoothStar::plat_get_num_particle_colors( void ) { return 3; }\r\nint CNgcParticleSmoothStar::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CNgcParticleSmoothStar::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CNgcParticleSmoothStar::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CNgcParticleSmoothStar::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CNgcParticleSmoothStar::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CNgcParticleSmoothStar::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CNgcParticleSmoothStar::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CNgcParticleSmoothStar::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CNgcParticleSmoothStar::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CNgcParticleSmoothStar::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CNgcParticleSmoothStar::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CNgcParticleSmoothStar::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CNgcParticleSmoothStar::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleSmoothStar::plat_render( void )\r\n{\r\n\tNxNgc::sMaterialHeader\t\tmat;\r\n\tNxNgc::sMaterialPassHeader\tpass;\r\n\r\n\t// Header.\r\n\tmat.m_checksum\t\t\t= 0xa9db601e;   // particle \r\n\tmat.m_passes\t\t\t= 1;\r\n\tmat.m_alpha_cutoff\t\t= 1;\r\n\tmat.m_flags\t\t\t\t= (1<<1);\t\t// 2 sided.\r\n//\tmat.m_shininess\t\t\t= 0.0f;\r\n\r\n\t// Pass 0.\r\n\tpass.m_texture.p_data\t= mp_engine_texture;\r\n\tpass.m_flags\t\t\t= ( mp_engine_texture ? (1<<0) : 0 ) | (1<<5) | (1<<6);\t\t// textured, clamped.\r\n\tpass.m_filter\t\t\t= 0;\r\n\tpass.m_blend_mode\t\t= (unsigned char)m_blend;\r\n\tpass.m_alpha_fix\t\t= (unsigned char)m_fix; \r\n\tpass.m_k\t\t\t\t= 0;\r\n\tpass.m_color.r\t\t\t= 128;\r\n\tpass.m_color.g\t\t\t= 128;\r\n\tpass.m_color.b\t\t\t= 128;\r\n\tpass.m_color.a\t\t\t= 255;\r\n\r\n\tNxNgc::multi_mesh( &mat, &pass, true, true );\r\n\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t// Draw the particles.\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\tNsMatrix*\tp_matrix\t= &NxNgc::EngineGlobals.camera;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\r\n\tNsVector\tup( 0.0f, 1.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tNsVector screen_right;\r\n\tNsVector screen_up;\r\n\tscreen_right.cross( *p_matrix->getAt(), up );\r\n\tscreen_up.cross( screen_right, *p_matrix->getAt());\r\n\r\n\tscreen_right.normalize();\r\n\tscreen_up.normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v = mp_vertices; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[4];\r\n\t\r\n\t\tVECScale((Vec*)&screen_right, (Vec*)&ss_right, w );\r\n\t\tVECScale((Vec*)&screen_up, (Vec*)&ss_up, h );\r\n\t\r\n\t\tGXColor color[3];\r\n\t\tGXColor *p_col0;\r\n\t\tGXColor *p_col1;\r\n\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 3; c++ )\r\n\t\t{\r\n\t\t\tGXColor start = *p_col0++;\r\n\t\t\tGXColor end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\r\n\t\ttmp[1]  = pos;\r\n\t\ttmp[1] += ss_right * sinf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\t\ttmp[1] += ss_up    * cosf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\r\n\t\tfor ( int lp2 = 0; lp2 < m_num_segments; lp2++ )\r\n\t\t{\r\n\t\t\ttmp[0]  = pos;\r\n\t\t\ttmp[0] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) ) * m_split;\r\n\t\t\ttmp[0] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) ) * m_split;\r\n\t\t\t\r\n\t\t\ttmp[3]  = pos;\r\n\t\t\ttmp[3] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 2 ) ) ) ) * m_split;\r\n\t\t\ttmp[3] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 2 ) ) ) ) * m_split;\r\n\t\t\t\r\n\t\t\ttmp[2]  = pos;\r\n\t\t\ttmp[2] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) );\r\n\t\t\ttmp[2] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) );\r\n\r\n\t\t\tGX::Begin( GX_TRIANGLEFAN, GX_VTXFMT0, 6 );\r\n\r\n\t\t\tGX::Position3f32( tmp[0][X], tmp[0][Y], tmp[0][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[1][X], tmp[1][Y], tmp[1][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[2]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[2][X], tmp[2][Y], tmp[2][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[2]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[3][X], tmp[3][Y], tmp[3][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[2]) );\r\n\r\n\t\t\tGX::Position3f32( pos[X], pos[Y], pos[Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[1][X], tmp[1][Y], tmp[1][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[2]) );\r\n\r\n\t\t\tGX::End();\r\n\r\n\t\t\ttmp[1] = tmp[3];\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticlesmoothstar.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLESmoothStar_H__\r\n#define\t__GFX_P_NX_PARTICLESmoothStar_H__\r\n    \r\n#include \"gfx/Ngc/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CNgcParticleSmoothStar : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCNgcParticleSmoothStar();\r\n\t\t\t\t\t\t\tCNgcParticleSmoothStar( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CNgcParticleSmoothStar();\r\n\r\n//\tNxNgc::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint8\t\t\t\t\tm_blend;\r\n\tuint8\t\t\t\t\tm_fix;\r\n\tuint8\t\t\t\t\tm_pad0;\r\n\tuint8\t\t\t\t\tm_pad1;\r\n\r\n\tint\t\t\t\t\t\tm_num_segments;\r\n\tfloat\t\t\t\t\tm_split;\r\n\tGXColor\t\t\t\t\tm_start_color[3];\t\t\t// SmoothStart color for each corner.\r\n\tGXColor\t\t\t\t\tm_mid_color[3];\t\t\t\t// Mid color for each corner.\r\n\tGXColor\t\t\t\t\tm_end_color[3];\t\t\t\t// End color for each corner.\r\n\tNxNgc::sTexture *\t\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticlestar.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/Ngc/nx/render.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/Ngc/p_nxtexture.h>\r\n#include \"gfx/Ngc/nx/mesh.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include \"sys/ngc/p_gx.h\"\r\n\r\n#include \"gfx/Ngc/p_nxparticleStar.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleStar::CNgcParticleStar()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleStar::CNgcParticleStar( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxNgc::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CNgcTexture *p_Ngc_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = (uint8)get_texture_blend( blendmode_checksum );\r\n\tm_fix = fix;\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 3; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n\r\n\tm_num_segments = num_segments;\r\n\tm_split = split;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcParticleStar::~CNgcParticleStar()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleStar::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleStar::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleStar::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CNgcParticleStar::plat_get_num_particle_colors( void ) { return 3; }\r\nint CNgcParticleStar::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CNgcParticleStar::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CNgcParticleStar::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CNgcParticleStar::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CNgcParticleStar::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CNgcParticleStar::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CNgcParticleStar::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CNgcParticleStar::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CNgcParticleStar::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CNgcParticleStar::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CNgcParticleStar::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CNgcParticleStar::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CNgcParticleStar::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcParticleStar::plat_render( void )\r\n{\r\n\tNxNgc::sMaterialHeader\t\tmat;\r\n\tNxNgc::sMaterialPassHeader\tpass;\r\n\r\n\t// Header.\r\n\tmat.m_checksum\t\t\t= 0xa9db601e;   // particle \r\n\tmat.m_passes\t\t\t= 1;\r\n\tmat.m_alpha_cutoff\t\t= 1;\r\n\tmat.m_flags\t\t\t\t= (1<<1);\t\t// 2 sided.\r\n//\tmat.m_shininess\t\t\t= 0.0f;\r\n\r\n\t// Pass 0.\r\n\tpass.m_texture.p_data\t= mp_engine_texture;\r\n\tpass.m_flags\t\t\t= ( mp_engine_texture ? (1<<0) : 0 ) | (1<<5) | (1<<6);\t\t// textured, clamped.\r\n\tpass.m_filter\t\t\t= 0;\r\n\tpass.m_blend_mode\t\t= (unsigned char)m_blend;\r\n\tpass.m_alpha_fix\t\t= (unsigned char)m_fix; \r\n\tpass.m_k\t\t\t\t= 0;\r\n\tpass.m_color.r\t\t\t= 128;\r\n\tpass.m_color.g\t\t\t= 128;\r\n\tpass.m_color.b\t\t\t= 128;\r\n\tpass.m_color.a\t\t\t= 255;\r\n\r\n\tNxNgc::multi_mesh( &mat, &pass, true, true );\r\n\r\n\tGX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );\r\n\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t// Draw the particles.\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\tNsMatrix*\tp_matrix\t= &NxNgc::EngineGlobals.camera;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\r\n\tNsVector\tup( 0.0f, 1.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tNsVector screen_right;\r\n\tNsVector screen_up;\r\n\tscreen_right.cross( *p_matrix->getAt(), up );\r\n\tscreen_up.cross( screen_right, *p_matrix->getAt());\r\n\r\n\tscreen_right.normalize();\r\n\tscreen_up.normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v = mp_vertices; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[3];\r\n\t\r\n\t\tVECScale((Vec*)&screen_right, (Vec*)&ss_right, w );\r\n\t\tVECScale((Vec*)&screen_up, (Vec*)&ss_up, h );\r\n\t\r\n\t\tGXColor color[3];\r\n\t\tGXColor *p_col0;\r\n\t\tGXColor *p_col1;\r\n\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 3; c++ )\r\n\t\t{\r\n\t\t\tGXColor start = *p_col0++;\r\n\t\t\tGXColor end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\r\n\t\ttmp[0]  = pos;\r\n\t\ttmp[0] += ss_right * sinf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\t\ttmp[0] += ss_up    * cosf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\r\n\t\tfor ( int lp2 = 0; lp2 < m_num_segments; lp2++ )\r\n\t\t{\r\n\t\t\ttmp[1]  = pos;\r\n\t\t\ttmp[1] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\t\t\ttmp[1] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\r\n\t\t\ttmp[2]  = pos;\r\n\t\t\ttmp[2] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) );\r\n\t\t\ttmp[2] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) );\r\n\r\n\t\t\tGX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 4 );\r\n\r\n\t\t\tGX::Position3f32( pos[X], pos[Y], pos[Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[0]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[0][X], tmp[0][Y], tmp[0][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[1][X], tmp[1][Y], tmp[1][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[1]) );\r\n\r\n\t\t\tGX::Position3f32( tmp[2][X], tmp[2][Y], tmp[2][Z] );\r\n\t\t\tGX::Color1u32( *((uint32*)&color[2]) );\r\n\r\n\t\t\tGX::End();\r\n\r\n\t\t\ttmp[0] = tmp[1];\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxparticlestar.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLEStar_H__\r\n#define\t__GFX_P_NX_PARTICLEStar_H__\r\n    \r\n#include \"gfx/Ngc/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CNgcParticleStar : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCNgcParticleStar();\r\n\t\t\t\t\t\t\tCNgcParticleStar( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CNgcParticleStar();\r\n\r\n//\tNxNgc::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint8\t\t\t\t\tm_blend;\r\n\tuint8\t\t\t\t\tm_fix;\r\n\tuint8\t\t\t\t\tm_pad0;\r\n\tuint8\t\t\t\t\tm_pad1;\r\n\r\n\tint\t\t\t\t\t\tm_num_segments;\r\n\tfloat\t\t\t\t\tm_split;\r\n\tGXColor\t\t\t\t\tm_start_color[3];\t\t\t// Start color for each corner.\r\n\tGXColor\t\t\t\t\tm_mid_color[3];\t\t\t\t// Mid color for each corner.\r\n\tGXColor\t\t\t\t\tm_end_color[3];\t\t\t\t// End color for each corner.\r\n\tNxNgc::sTexture *\t\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxscene.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxScene.cpp\r\n\r\n#include \t\"gfx/Ngc/p_NxScene.h\"\r\n#include \t\"gfx/Ngc/p_NxSector.h\"\r\n#include \t\"gfx/Ngc/p_NxGeom.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcScene::CNgcScene( int sector_table_size ) : CScene( sector_table_size )\r\n{\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcScene::DestroySectorMeshes( void )\r\n{\r\n\t// Iterate through the list of sectors, removing each one in turn, and requesting the engine to\r\n\t// remove the meshes.\r\n\tmp_sector_table->IterateStart();\r\n\tCSector* pSector = mp_sector_table->IterateNext();\r\n\twhile( pSector )\r\n\t{\r\n\t\t// Access platform dependent data.\r\n//\t\tCNgcSector* pNgcSector = static_cast<CNgcSector *>(pSector);\r\n\r\n\t\t// Remove this mesh array from the engine.\r\n//\t\tpNgcSector->DestroyMeshArray();\r\n\r\n\t\tpSector = mp_sector_table->IterateNext();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CScene\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcScene::plat_post_load()\r\n{\r\n\t// Now turn the temporary mesh lists into mesh arrays.\r\n\tmp_sector_table->IterateStart();\r\n\tCSector* pSector = mp_sector_table->IterateNext();\r\n\twhile( pSector )\r\n\t{\r\n\t\tCNgcGeom *p_Ngc_geom = static_cast<CNgcGeom*>(pSector->GetGeom());\r\n\r\n\t\tp_Ngc_geom->CreateMeshArray();\r\n\r\n\t\t// First time through we just want to count the meshes,\r\n\t\tp_Ngc_geom->RegisterMeshArray( true );\r\n\r\n\t\tpSector = mp_sector_table->IterateNext();\r\n\t}\r\n\r\n\t// Now we have counted all the meshes, tell the engine to create the arrays to hold them.\r\n\tGetEngineScene()->CreateMeshArrays();\r\n\t\r\n\t// Now go through and actually add the meshes.\r\n\tmp_sector_table->IterateStart();\r\n\tpSector = mp_sector_table->IterateNext();\r\n\twhile( pSector )\r\n\t{\r\n\t\t// Access platform dependent data.\r\n\t\tCNgcGeom *p_Ngc_geom = static_cast<CNgcGeom*>(pSector->GetGeom());\r\n\r\n\t\tp_Ngc_geom->RegisterMeshArray( false );\r\n\r\n\t\tpSector = mp_sector_table->IterateNext();\r\n\t}\r\n\r\n\t// Now all meshes are registered, tell the engine to sort them.\r\n\tGetEngineScene()->SortMeshes();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcScene::plat_load_textures(const char* p_name)\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcScene::plat_load_collision(const char* p_name)\r\n{\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcScene::plat_unload_add_scene( void )\r\n{\r\n\t// Not sure what this is supposed to do, but added for now to remove annoying stub output.\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Create an empty sector\r\nCSector\t*\t\t\tCNgcScene::plat_create_sector()\r\n{\r\n\tCNgcSector *p_Ngc_sector\t= new CNgcSector();\r\n\treturn p_Ngc_sector;\r\n}\r\n\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxscene.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxScene.h\r\n\r\n#ifndef\t__GFX_P_NX_SCENE_H__\r\n#define\t__GFX_P_NX_SCENE_H__\r\n\r\n#include \"Gfx/Nx.h\"\r\n#include \"Gfx/Ngc/nx/scene.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CScene\r\nclass\tCNgcScene : public CScene\r\n{\r\npublic:\r\n\r\n\t\t\t\t\t\t\t\tCNgcScene( int sector_table_size = 10 );\r\n\tNxNgc::sScene *\t\t\tGetEngineScene() const\t\t\t\t\t\t{ return mp_engine_scene; }\r\n\tvoid\t\t\t\t\t\tSetEngineScene( NxNgc::sScene *p_scene )\t{ mp_engine_scene = p_scene; }\r\n\tvoid\t\t\t\t\t\tDestroySectorMeshes( void );\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\tvirtual void\t\t\t\tplat_post_load();\t\r\n\tvirtual bool\t\t\t\tplat_load_textures( const char *p_name );\t// load textures \r\n\tvirtual bool\t\t\t\tplat_load_collision( const char *p_name );\t// load collision data\r\n\tvirtual bool\t\t\t\tplat_unload_add_scene( void );\r\n\tvirtual\tCSector\t*\t\t\tplat_create_sector();\t \t\t\t\t\t// empty sector\r\n\r\n\r\n\tNxNgc::sScene\t\t\t\t*mp_engine_scene;\r\n\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxsector.cpp",
    "content": "\r\n///////////////////////////////////////////////////////////////////////////////\r\n// p_NxSector.cpp\r\n\r\n#include\t<sys/file/filesys.h>\r\n\r\n#include \t\"gfx/ngc/p_NxSector.h\"\r\n#include \t\"gfx/ngc/p_NxGeom.h\"\r\n#include \t\"gfx/Image/ImageBasic.h\"\r\n#include \t\"gfx/ngc/nx/render.h\"\r\n#include \t\"gfx/ngc/nx/mesh.h\"\r\n#include \t\"gfx/NxMiscFX.h\"\r\n#include \t\"gfx\\ngc\\nx\\nx_init.h\"\r\n#include\t<dolphin/gd.h>\r\n\r\n//NxNgc::sMesh *\tp_u_mat[256];\r\n//int\t\t\t\tu_mat_count[256];\r\n//int\t\t\t\tnum_u_mat = 0;\r\n\r\nnamespace Nx\r\n{\r\n\r\n#ifdef SHORT_VERT\r\n\r\nstatic int round_float( float f, int shift, float off, float cen )\r\n{\r\n\tfloat mul = ((float)( 1 << shift ));\r\n\tint i_f = (int)( ( f - cen ) * mul );\r\n\r\n\tint adjust = 0;\r\n\tif ( i_f > 0 )\r\n\t{\r\n\t\tadjust = 1;\r\n\t}\r\n//\tif ( i_f < 0 )\r\n//\t{\r\n//\t\tadjust = -1;\r\n//\t}\r\n\r\n\ti_f = (int)( ( f - off ) * mul );\r\n\ti_f += adjust;\r\n\treturn i_f;\r\n\r\n//\tfloat mul = ((float)( 1 << shift ));\r\n//\tint i_f = (int)( f * mul );\r\n//\tfloat d_f = ( f * mul ) - ((float)i_f);\r\n//\r\n//\tif ( d_f >= 0.0f )\r\n//\t{\r\n//\t\tif( d_f < 0.5f )\r\n//\t\t{\r\n//\t\t\treturn i_f;\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\treturn i_f + 1;\r\n//\t\t}\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tif( d_f < -0.5f )\r\n//\t\t{\r\n//\t\t\treturn i_f;\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\treturn i_f - 1;\r\n//\t\t}\r\n//\t}\r\n}\r\n#endif\t\t// SHORT_VERT\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n//CNgcSector::CNgcSector() : mp_init_mesh_list( NULL ), m_mesh_array( NULL ), m_visible( 0xDEADBEEF )\r\nCNgcSector::CNgcSector()\r\n{\r\n\tm_pos_offset.Set( 0.0f, 0.0f, 0.0f );\r\n//\tm_active = true;\t\t\t\t\t\t// default to be active....\r\n//\tmp_scene = NULL;\r\n}\r\n\r\n\r\n\r\n\r\n#define MemoryRead( dst, size, num, src )\tmemcpy(( dst ), ( src ), (( num ) * ( size )));\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t( src ) += (( num ) * ( size ))\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nNxNgc::sObjectHeader* CNgcSector::LoadFromMemory( NxNgc::sObjectHeader* p_data )\r\n{\r\n//\tuint8\t\t*p_file_data\t= (uint8*)( *pp_mem );\r\n//\r\n//\tDbg_Assert( mp_geom );\r\n//\r\n//\tCNgcGeom *p_geom = static_cast<CNgcGeom*>( mp_geom );\r\n//\t\r\n//\t// Read sector checksum.\r\n//\tuint32 sector_checksum;\r\n//\tMemoryRead( &sector_checksum, sizeof( uint32 ), 1, p_file_data );\r\n//\t\r\n//\tSetChecksum( sector_checksum );\r\n//\r\n//\t// Read bone index.\r\n//\tint bone_idx;\r\n//\tMemoryRead( &bone_idx, sizeof( int ), 1, p_file_data );\r\n//\r\n//\t// Read sector flags.\r\n//\tuint32 flags;\r\n//\tMemoryRead( &flags, sizeof( int ), 1, p_file_data );\r\n//\tm_flags = flags;\r\n//\r\n//\t// Read number of meshes.\r\n//\tint num_mesh;\r\n//\tMemoryRead( &num_mesh, sizeof( uint ), 1, p_file_data );\r\n//\tp_geom->m_num_mesh = num_mesh;\r\n//\r\n//\t// Read bounding box.\r\n//\tfloat bbox[6];\r\n//\tMemoryRead( &bbox[0], sizeof( float ), 6, p_file_data );\r\n//\tMth::Vector\tinf( bbox[0], bbox[1], bbox[2] );\r\n//\tMth::Vector\tsup( bbox[3], bbox[4], bbox[5] );\r\n//\tp_geom->m_bbox.Set( inf, sup );\r\n//\t\t\r\n//\t// Read bounding sphere.\r\n//\tfloat bsphere[4];\r\n//\tMemoryRead( &bsphere[0], sizeof( float ), 4, p_file_data );\r\n//\t\t\r\n//\t// Read num vertices.\r\n//\tint num_vertices;\r\n//\tMemoryRead( &num_vertices, sizeof( int ), 1, p_file_data );\r\n//\t\r\n//\t// Read vertex data stride.\r\n//\tint vertex_data_stride;\r\n//\tMemoryRead( &vertex_data_stride, sizeof( int ), 1, p_file_data );\r\n//\t\r\n//\t// Only read vertex/normal pools if skinned.\r\n//\tint dbytes = 0;\r\n//\tint sbytes = 0;\r\n//\tfloat* p_vertex_positions = NULL;\r\n//\ts16* p_vertex_normals = NULL;\r\n//\tuint32* p_double = NULL;\r\n//\tuint32* p_temp = NULL;\r\n//\tint num_double = 0;\r\n//\tint num_single = 0;\r\n//#ifdef SHORT_VERT\r\n//\ts16* p_vertex_positions16 = NULL;\r\n//\tint shift = 0;\r\n//\tfloat off_x = 0.0f;\r\n//\tfloat off_y = 0.0f;\r\n//\tfloat off_z = 0.0f;\r\n//#endif\t\t// SHORT_VERT\r\n//\tif ( !(m_flags & 0x10) )\r\n//\t{\r\n//\t\t// Grab a buffer for the raw vertex data position stream, and read it.\r\n//#ifdef SHORT_VERT\r\n//\t\tp_vertex_positions = new (Mem::Manager::sHandle().TopDownHeap()) float[num_vertices * 3];\r\n//#else\r\n//\t\tp_vertex_positions = new float[num_vertices * 3];\r\n//#endif\t\t// SHORT_VERT\r\n//\t\tMemoryRead( p_vertex_positions, sizeof( float ) * 3, num_vertices, p_file_data );\r\n//\r\n//#ifdef SHORT_VERT\r\n//\t\tint lp;\r\n//\r\n//\t\t// Calculate the largest dimension.\r\n//\t\tfloat smallest_x = p_vertex_positions[0];\r\n//\t\tfloat smallest_y = p_vertex_positions[1];\r\n//\t\tfloat smallest_z = p_vertex_positions[2];\r\n//\t\tfloat largest_x = p_vertex_positions[0];\r\n//\t\tfloat largest_y = p_vertex_positions[1];\r\n//\t\tfloat largest_z = p_vertex_positions[2];\r\n//\t\tfor ( lp = 1; lp < num_vertices; lp++ )\r\n//\t\t{\r\n//\t\t\tif ( p_vertex_positions[(lp*3)+0] > largest_x ) largest_x = p_vertex_positions[(lp*3)+0];\r\n//\t\t\tif ( p_vertex_positions[(lp*3)+1] > largest_y ) largest_y = p_vertex_positions[(lp*3)+1];\r\n//\t\t\tif ( p_vertex_positions[(lp*3)+2] > largest_z ) largest_z = p_vertex_positions[(lp*3)+2];\r\n//\t\t\tif ( p_vertex_positions[(lp*3)+0] < smallest_x ) smallest_x = p_vertex_positions[(lp*3)+0];\r\n//\t\t\tif ( p_vertex_positions[(lp*3)+1] < smallest_y ) smallest_y = p_vertex_positions[(lp*3)+1];\r\n//\t\t\tif ( p_vertex_positions[(lp*3)+2] < smallest_z ) smallest_z = p_vertex_positions[(lp*3)+2];\r\n//\t\t}\r\n//\t\tfloat biggest = largest_x;\r\n//\t\tif ( largest_y > biggest ) biggest = largest_y;\r\n//\t\tif ( largest_z > biggest ) biggest = largest_z;\r\n//\t\tif ( -smallest_x > biggest ) biggest = -smallest_x;\r\n//\t\tif ( -smallest_y > biggest ) biggest = -smallest_y;\r\n//\t\tif ( -smallest_z > biggest ) biggest = -smallest_z;\r\n//\r\n//\t\tfloat c_x = ( smallest_x + largest_x ) / 2.0f;\r\n//\t\tfloat c_y = ( smallest_y + largest_y ) / 2.0f;\r\n//\t\tfloat c_z = ( smallest_z + largest_z ) / 2.0f;\r\n//\r\n//\t\t// Work out the shift amount.\r\n//\t\tif ( biggest > ( ( 1 << 15 ) - 1 ) )\r\n//\t\t{\r\n//\t\t\t// Work out how to offset it.\r\n//\t\t\toff_x = ( smallest_x + largest_x ) / 2.0f;\r\n//\t\t\toff_y = ( smallest_y + largest_y ) / 2.0f;\r\n//\t\t\toff_z = ( smallest_z + largest_z ) / 2.0f;\r\n//\t\t\tbiggest = ( largest_x - smallest_x ) / 2.0f;\r\n//\t\t\tif ( ( ( largest_y - smallest_y ) / 2.0f ) > biggest ) biggest = ( ( largest_y - smallest_y ) / 2.0f );\r\n//\t\t\tif ( ( ( largest_z - smallest_z ) / 2.0f ) > biggest ) biggest = ( ( largest_z - smallest_z ) / 2.0f );\r\n//\r\n//\t\t\tif ( ( largest_x - smallest_x ) > 65535 )\r\n//\t\t\t{\r\n//\t\t\t\tOSReport( \"Cannot deal with meshes larger than 65535 X units, this mesh is %6.3f\\n\", ( largest_x - smallest_x ) );\r\n//\t\t\t\twhile ( 1 == 1 );\r\n//\t\t\t}\r\n//\r\n//\t\t\tif ( ( largest_y - smallest_y ) > 65535 )\r\n//\t\t\t{\r\n//\t\t\t\tOSReport( \"Cannot deal with meshes larger than 65535 Y units, this mesh is %6.3f\\n\", ( largest_y - smallest_y ) );\r\n//\t\t\t\twhile ( 1 == 1 );\r\n//\t\t\t}\r\n//\r\n//\t\t\tif ( ( largest_z - smallest_z ) > 65535 )\r\n//\t\t\t{\r\n//\t\t\t\tOSReport( \"Cannot deal with meshes larger than 65535 Z units, this mesh is %6.3f\\n\", ( largest_z - smallest_z ) );\r\n//\t\t\t\twhile ( 1 == 1 );\r\n//\t\t\t}\r\n//\t\t\tshift = 0;\r\n//\t\t}\r\n//\r\n//\t\tif ( biggest > ( ( 1 << 14 ) - 1 ) )\r\n//\t\t{\r\n//\t\t\tshift = 0;\r\n//\t\t}\r\n//\t\telse\r\n//\t\tif ( biggest > ( ( 1 << 13 ) - 1 ) )\r\n//\t\t{\r\n//\t\t\tshift = 1;\r\n//\t\t}\r\n//\t\telse\r\n//\t\tif ( biggest > ( ( 1 << 12 ) - 1 ) )\r\n//\t\t{\r\n//\t\t\tshift = 2;\r\n//\t\t}\r\n//\t\telse\r\n//\t\tif ( biggest > ( ( 1 << 11 ) - 1 ) )\r\n//\t\t{\r\n//\t\t\tshift = 3;\r\n//\t\t}\r\n//\t\telse\r\n//\t\tif ( biggest > ( ( 1 << 10 ) - 1 ) )\r\n//\t\t{\r\n//\t\t\tshift = 4;\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tshift = 5;\r\n//\t\t}\r\n////\t\tif ( biggest > ( ( 1 << 9 ) - 1 ) )\r\n////\t\t{\r\n////\t\t\tshift = 5;\r\n////\t\t}\r\n////\t\telse\r\n////\t\t{\r\n////\t\t\tshift = 6;\r\n////\t\t}\r\n//\r\n//\t\t// Now, we need to squeeze the vertex positions down to s16s (1:9:6)\r\n//\t\tp_vertex_positions16 = new s16[num_vertices * 3];\r\n//\t\tfor ( lp = 0; lp < num_vertices; lp++ )\r\n//\t\t{\r\n//\t\t\tp_vertex_positions16[(lp*3)+0] = (s16)( round_float( p_vertex_positions[(lp*3)+0], shift, off_x, c_x ) );\r\n//\t\t\tp_vertex_positions16[(lp*3)+1] = (s16)( round_float( p_vertex_positions[(lp*3)+1], shift, off_y, c_y ) );\r\n//\t\t\tp_vertex_positions16[(lp*3)+2] = (s16)( round_float( p_vertex_positions[(lp*3)+2], shift, off_z, c_z ) );\r\n//\t\t}\r\n//#endif\t\t// SHORT_VERT\r\n//\r\n//\t\t// Grab a buffer for the raw vertex data normal stream (if present), and read it.\r\n//\t\tp_vertex_normals = ( m_flags & 0x04 ) ? new s16[num_vertices * 3] : NULL;\r\n//\t\tif( p_vertex_normals )\r\n//\t\t{\r\n//\t\t\tMemoryRead( p_vertex_normals, sizeof( s16 ) * 3, num_vertices, p_file_data );\r\n//\t\t}\r\n//\t} else {\r\n//\t\tint bytes = 0;\r\n//\t\t// This is a skinned model, read in the double data.\r\n//\t\tMemoryRead( &bytes, sizeof( int ), 1, p_file_data );\r\n//\t\tMemoryRead( &num_double, sizeof( int ), 1, p_file_data );\r\n//\r\n//\t\tdbytes = ( bytes + 3 ) / 4;\r\n//\t\tp_temp = new uint32[dbytes];\r\n//\t\tMemoryRead( p_temp, bytes, 1, p_file_data );\r\n//\r\n//\t\t// Read the single data.\r\n//\t\tMemoryRead( &bytes, sizeof( int ), 1, p_file_data );\r\n//\t\tMemoryRead( &num_single, sizeof( int ), 1, p_file_data );\r\n//\r\n//\t\tsbytes = ( bytes + 3 ) / 4;\r\n//\t\tp_double = new /*(Mem::Manager::sHandle().TopDownHeap())*/ uint32[dbytes + sbytes];\r\n//\t\tmemcpy( p_double, p_temp, dbytes * 4 );\r\n//\t\tMemoryRead( &p_double[dbytes], bytes, 1, p_file_data );\r\n//\r\n//\t\tdelete p_temp;\r\n//\t}\r\n//\r\n////\t// Grab a buffer for the raw vertex data weights stream (if present), and read it.\r\n////\tfloat* p_vertex_weights = ( m_flags & 0x10 ) ? new float[num_vertices * 3] : NULL;\r\n////\tif( p_vertex_weights )\r\n////\t{\r\n////\t\tMemoryRead( p_vertex_weights, sizeof( float ) * 3, num_vertices, p_file_data );\r\n////\t}\r\n////\t\r\n////\t// Grab a buffer for the raw vertex data bone indices stream (if present), and read it.\r\n////\tuint16* p_vertex_bone_indices = ( m_flags & 0x10 ) ? new uint16[num_vertices * 3] : NULL;\r\n////\tif( p_vertex_bone_indices )\r\n////\t{\r\n////\t\tMemoryRead( p_vertex_bone_indices, sizeof( uint16 ) * 3, num_vertices, p_file_data );\r\n////\t}\r\n//\r\n//\tuint16 * p_temp_col_remap = NULL;\r\n//\tuint16 * p_temp_uv_remap = NULL;\r\n//\r\n//\t// Grab a buffer for the raw vertex texture coordinate stream (if present), and read it.\r\n//\tint\t\tnum_tc_sets\t\t\t= 0;\r\n//\tfloat*\tp_vertex_tex_coords\t= NULL;\r\n//\tif( m_flags & 0x01 )\r\n//\t{\r\n//\t\tMemoryRead( &num_tc_sets, sizeof( int ), 1, p_file_data );\r\n//\t\t\r\n//\t\tfloat * p_temp_tex_coords = new (Mem::Manager::sHandle().TopDownHeap()) float[num_vertices * 2 * num_tc_sets];\r\n//\t\tp_vertex_tex_coords = new float[num_vertices * 2 * num_tc_sets];\r\n//\t\tMemoryRead( p_temp_tex_coords, sizeof( float ) * 2 * num_tc_sets, num_vertices, p_file_data );\r\n//\r\n//\t\t// Convert to friendlier non-interleaved format.\r\n//\t\tfor ( int lp = 0; lp < num_vertices; lp++ )\r\n//\t\t{\r\n//\t\t\tfor ( int lp2 = 0; lp2 < num_tc_sets; lp2++ )\r\n//\t\t\t{\r\n//\t\t\t\tp_vertex_tex_coords[(lp2*2*num_vertices)+(lp*2)+0] = p_temp_tex_coords[(lp2*2)+(lp*2*num_tc_sets)+0];\r\n//\t\t\t\tp_vertex_tex_coords[(lp2*2*num_vertices)+(lp*2)+1] = p_temp_tex_coords[(lp2*2)+(lp*2*num_tc_sets)+1];\r\n//\t\t\t}\r\n//\t\t}\r\n//\r\n//\t\t// Create temp uv mapping buffer.\r\n//\t\tp_temp_uv_remap = num_tc_sets ? new (Mem::Manager::sHandle().TopDownHeap()) uint16[num_vertices*num_tc_sets] : NULL;\r\n//\r\n//\t\tfor ( int c = 0; c < num_vertices; c++ )\r\n//\t\t{\r\n//\t\t\tfor ( int u = 0; u < num_tc_sets; u++ )\r\n//\t\t\t{\r\n//\t\t\t\tp_temp_uv_remap[(u*num_vertices)+c] = (u*num_vertices)+c;\r\n//\t\t\t}\r\n//\t\t}\r\n//\r\n//\t\tbool reduce = true;\r\n//\t\tif ( m_flags & 0x04 ) reduce = false;\t// No uv reduction if normals are present.\r\n//\r\n//\t\tif ( reduce )\r\n//\t\t{\r\n//\t\t\t// Copy back to temp coords.\r\n//\t\t\tmemcpy( p_temp_tex_coords, p_vertex_tex_coords, num_vertices * num_tc_sets * 2 * sizeof( float ) );\r\n//\t\t\tdelete [] p_vertex_tex_coords;\r\n//\t\t\tfloat * p_unique_tex_coords = new (Mem::Manager::sHandle().TopDownHeap()) float[num_vertices * 2 * num_tc_sets];\r\n//\r\n//\t\t\t// Now, squeeze down to only unique uvs.\r\n//\t\t\tint numUnique = 0;\r\n//\t\t\tfor ( int lp = 0; lp < num_vertices; lp++ )\r\n//\t\t\t{\r\n//\t\t\t\tfor ( int lp2 = 0; lp2 < num_tc_sets; lp2++ )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tbool found = false;\r\n//\t\t\t\t\tfor ( int lp3 = 0; lp3 < numUnique; lp3++ )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tif ( ( p_unique_tex_coords[(lp3*2)+0] == p_temp_tex_coords[(lp2*2*num_vertices)+(lp*2)+0] ) &&\r\n//\t\t\t\t\t\t\t ( p_unique_tex_coords[(lp3*2)+1] == p_temp_tex_coords[(lp2*2*num_vertices)+(lp*2)+1] ) )\r\n//\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t// Found a match.\r\n//\t\t\t\t\t\t\tp_temp_uv_remap[(lp2*num_vertices)+lp] = lp3;\r\n//\t\t\t\t\t\t\tfound = true;\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\tif ( !found )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tp_unique_tex_coords[(numUnique*2)+0] = p_temp_tex_coords[(lp2*2*num_vertices)+(lp*2)+0];\r\n//\t\t\t\t\t\tp_unique_tex_coords[(numUnique*2)+1] = p_temp_tex_coords[(lp2*2*num_vertices)+(lp*2)+1];\r\n//\t\t\t\t\t\tp_temp_uv_remap[(lp2*num_vertices)+lp] = numUnique;\r\n//\t\t\t\t\t\tnumUnique++;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\t// Allocate only the space we need.\r\n//\t\t\tp_vertex_tex_coords = new float[numUnique * 2];\r\n//\t\t\tmemcpy( p_vertex_tex_coords, p_unique_tex_coords, numUnique * 2 * sizeof( float ) );\r\n//\t\t\tdelete [] p_unique_tex_coords;\r\n//\t\t}\r\n//\r\n//\t\tdelete p_temp_tex_coords;\r\n//\t}\r\n//\t\r\n//\t// Grab a buffer for the raw vertex colors stream (if present), and read it.\r\n//\tuint32* p_vertex_colors = ( m_flags & 0x02 ) ? new uint32[num_vertices] : NULL;\r\n//\tif( p_vertex_colors )\r\n//\t{\r\n//\t\tMemoryRead( p_vertex_colors, sizeof( uint32 ), num_vertices, p_file_data );\r\n//\t\r\n//\t\t// Create temp col mapping buffer.\r\n//\t\tp_temp_col_remap = p_vertex_colors ? new (Mem::Manager::sHandle().TopDownHeap()) uint16[num_vertices] : NULL;\r\n//\r\n//\t\tfor ( int c = 0; c < num_vertices; c++ )\r\n//\t\t{\r\n//\t\t\tp_temp_col_remap[c] = c;\r\n//\t\t}\r\n//\r\n//\t\tbool reduce = true;\r\n//\t\tif ( m_flags & 0x04 ) reduce = false;\t// No color reduction if normals are present.\r\n//\t\tif ( m_flags & 0x800 ) reduce = false;\t// No color reduction if vc wibble data is present.\r\n//\t\tif ( !NxNgc::EngineGlobals.reduceColors ) reduce = false;\t// No color reduction if vc wibble data is present.\r\n//\r\n//\t\tif ( reduce )\r\n//\t\t{\r\n//\t\t\tuint32 * p_temp_colors = new (Mem::Manager::sHandle().TopDownHeap()) uint32[num_vertices];\r\n//\t\t\tmemcpy( p_temp_colors, p_vertex_colors, num_vertices * 4 );\r\n//\t\t\tdelete [] p_vertex_colors;\r\n//\t\t\tuint32* p_unique_colors = new (Mem::Manager::sHandle().TopDownHeap()) uint32[num_vertices];\r\n//\r\n//\t\t\t// Now, squeeze down to only unique uvs.\r\n//\t\t\tint numUnique = 0;\r\n//\t\t\tfor ( int lp = 0; lp < num_vertices; lp++ )\r\n//\t\t\t{\r\n//\t\t\t\tbool found = false;\r\n//\t\t\t\tfor ( int lp2 = 0; lp2 < numUnique; lp2++ )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif ( p_unique_colors[lp2] == p_temp_colors[lp] )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\t// Found a match.\r\n//\t\t\t\t\t\tp_temp_col_remap[lp] = lp2;\r\n//\t\t\t\t\t\tfound = true;\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t\tif ( !found )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tp_unique_colors[numUnique] = p_temp_colors[lp];\r\n//\t\t\t\t\tp_temp_col_remap[lp] = numUnique;\r\n//\t\t\t\t\tnumUnique++;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\t// Allocate only the space we need.\r\n//\t\t\tp_vertex_colors = new uint32[numUnique];\r\n//\t\t\tmemcpy( p_vertex_colors, p_unique_colors, numUnique * 4 );\r\n//\t\t\tdelete [] p_unique_colors;\r\n//\t\t\tdelete p_temp_colors;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t// Grab a buffer for the raw vertex colors stream (if present), and read it.\r\n//\tchar* p_vc_wibble_indices = ( m_flags & 0x800 ) ? new char[num_vertices] : NULL;\r\n//\tif( p_vc_wibble_indices )\r\n//\t{\r\n//\t\tMemoryRead( p_vc_wibble_indices, sizeof( char ), num_vertices, p_file_data );\r\n//\t}\r\n//\t\r\n//\tNxNgc::sMesh*\tp_mesh0 = NULL;\r\n//\r\n//\tfor( uint m = 0; m < p_geom->m_num_mesh; ++m )\r\n//\t{\r\n//\t\tunsigned long\tmaterial_checksum;\r\n//\t\tuint32\t\t\tflags;\r\n//\t\tint\t\t\t\tnum_indices;\r\n//\t\tfloat\t\t\tsphere[4];\r\n//\r\n//\t\tNxNgc::sMesh*\tp_mesh = new NxNgc::sMesh;\r\n//\t\tif ( m == 0 )\r\n//\t\t{\r\n//\t\t\tp_mesh0 = p_mesh;\r\n//\t\t\tp_mesh0->mp_envBuffer = NULL;\r\n//\t\t}\r\n//\t\t\r\n//\t\tMemoryRead( &material_checksum,\tsizeof( unsigned long ), 1, p_file_data );\r\n//\t\tMemoryRead( &flags,\tsizeof( uint32 ), 1, p_file_data );\r\n//\t\tMemoryRead( sphere, sizeof( float ), 4, p_file_data );\r\n//\t\tMemoryRead( &num_indices, sizeof( int ), 1, p_file_data );\r\n//\r\n//\t\tuint16* p_indices = new uint16[num_indices];\r\n//\t\tMemoryRead( p_indices, sizeof( uint16 ), num_indices, p_file_data );\r\n//\r\n//\t\t// Deal with skater shadow flag.\r\n//\t\tif( flags & (0x4000|0x400) )\r\n//\t\t{\r\n//\t\t\tp_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_NO_SKATER_SHADOW;\r\n//\t\t}\r\n//\t\t// Deal with vertex color wibble flag.\r\n//\t\tif( flags & (0x800) )\r\n//\t\t{\r\n//\t\t\tp_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_VERTEX_COLOR_WIBBLE;\r\n//\t\t}\r\n//\t\t\r\n//\t\tif( m_flags & (0x80000) )\r\n//\t\t{\r\n//\t\t\tp_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_GRASS;\r\n//\t\t}\r\n//\t\t\r\n//\t\t// Create the mesh from the raw data.\r\n//\t\tp_mesh->Initialize( num_vertices,\r\n//\t\t\t\t\t\t\tp_vertex_positions,\r\n//#ifdef SHORT_VERT\r\n//\t\t\t\t\t\t\tp_vertex_positions16,\r\n//\t\t\t\t\t\t\tshift,\r\n//\t\t\t\t\t\t\toff_x,\r\n//\t\t\t\t\t\t\toff_y,\r\n//\t\t\t\t\t\t\toff_z,\r\n//#endif\t\t// SHORT_VERT\r\n//\t\t\t\t\t\t\tp_vertex_normals,\r\n//\t\t\t\t\t\t\tp_vertex_tex_coords,\r\n//\t\t\t\t\t\t\tp_mesh0->mp_envBuffer,\r\n//\t\t\t\t\t\t\tnum_tc_sets,\r\n//\t\t\t\t\t\t\tp_vertex_colors,\r\n//\t\t\t\t\t\t\tnum_indices,\r\n//\t\t\t\t\t\t\tp_indices,\t\t// pos\r\n//\t\t\t\t\t\t\tp_temp_col_remap,\t\t// color\r\n//\t\t\t\t\t\t\tp_temp_uv_remap,\t\t// uv\r\n//\t\t\t\t\t\t\tmaterial_checksum,\r\n//\t\t\t\t\t\t\tp_geom->mp_scene->GetEngineScene(),\r\n//\t\t\t\t\t\t\tnum_double,\r\n//\t\t\t\t\t\t\tp_double,\r\n//\t\t\t\t\t\t\tnum_single,\r\n//\t\t\t\t\t\t\tm,\r\n//\t\t\t\t\t\t\tGX_TRIANGLESTRIP,\r\n//\t\t\t\t\t\t\tbone_idx,\r\n//\t\t\t\t\t\t\tp_vc_wibble_indices );\r\n//\r\n//\t\t// Assign env buffer to mesh 0 if assigned.\r\n//\t\tif ( ( m > 0 ) && p_mesh->mp_envBuffer ) p_mesh0->mp_envBuffer = p_mesh->mp_envBuffer;\r\n//\t\t\r\n//\t\t// Add the mesh to the sector.\r\n//\t\tp_geom->AddMesh( p_mesh );\r\n//\t\r\n//\t\t// Done with the raw index data.\r\n////\t\tdelete[] p_indices;\r\n\r\n//\t\tif ( p_data->m_size )\r\n//\t\t{\r\n//\t\t\t// Setup the DL.\r\n//\t\t\tp_mesh->mp_dl = p_data;\r\n//\t\t\tp_data = (NxNgc::sDLHeader*)(&((char*)&p_data[1])[p_data->m_size]);\r\n//\r\n//\t\t\tp_mesh->mp_dl->mp_material_dl = NULL;\r\n//\t\t\tp_mesh->mp_dl->m_material_dl_size = 0;\r\n//\r\n//\t\t\t// Find the material.\r\n//\t\t\tNxNgc::sMaterialHeader * p_mat_list = p_geom->mp_scene->GetEngineScene()->mp_material_list;\r\n//\t\t\tbool found = false;\r\n//\t\t\tfor ( unsigned int lp = 0; lp < p_geom->mp_scene->GetEngineScene()->mp_scene_data->m_num_materials; lp++ )\r\n//\t\t\t{\r\n//\t\t\t\tif ( p_mat_list->m_checksum == p_mesh->mp_dl->m_material.checksum )\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// Found it!\r\n//\t\t\t\t\tp_mesh->mp_dl->m_material.p_header = p_mat_list;\r\n//\r\n//\t\t\t\t\t// Construct the DL.\r\n//\t\t\t\t\tMem::Manager::sHandle().TopDownHeap()->PushAlign( 32 );\r\n//#define DL_BUILD_SIZE (4*1024)\r\n//\t\t\t\t\tuint8 * p_build_dl = new (Mem::Manager::sHandle().TopDownHeap()) uint8[DL_BUILD_SIZE];\r\n//\t\t\t\t\tDCFlushRange ( p_build_dl, DL_BUILD_SIZE );\r\n//\r\n//\t\t\t\t\tGXBeginDisplayList ( p_build_dl, DL_BUILD_SIZE );\r\n//\t\t\t\t\tGXResetWriteGatherPipe();\r\n//\r\n////\t\t\t\t\t// ---------------- Begin Generate display list.\r\n//////\t\t\t\t\tGXSetNumTevStages( 1 );\r\n////\t\t\t\t\tGXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);\r\n////\t\t\t\t\tGXSetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//////\t\t\t\t\tGXSetNumTexGens( 0 );\r\n////\t\t\t\t\tGXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n////\t\t\t\t\tGXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n////////\t\t\t\t\tGXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n////\t\t\t\t\tGXSetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );\r\n////\t\t\t\t\tGXSetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n////\t\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n////\t\t\t\t\tGXSetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n////\t\t\t\t\tGXSetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\r\n//\t\t\t\t\tNxNgc::sMaterialHeader * p_mat = p_mesh->mp_dl->m_material.p_header;\r\n//\t\t\t\t\tNxNgc::sMaterialPassHeader * p_pass = (NxNgc::sMaterialPassHeader *)&p_mat[1];\r\n//\r\n//\t\t\t\t\tint lp;\r\n//\r\n//\t\t\t\t\tNxNgc::MaterialBegin(); for ( lp = 0; lp < p_mat->m_passes; lp++ ) NxNgc::MaterialLayer( p_pass, lp, MATERIAL_GROUP_CP );\tNxNgc::MaterialEnd( &p_mesh->mp_dl->m_tev_stages, &p_mesh->mp_dl->m_tex_gens );\r\n//\t\t\t\t\tNxNgc::MaterialBegin(); for ( lp = 0; lp < p_mat->m_passes; lp++ ) NxNgc::MaterialLayer( p_pass, lp, MATERIAL_GROUP_SU );   NxNgc::MaterialEnd( &p_mesh->mp_dl->m_tev_stages, &p_mesh->mp_dl->m_tex_gens );\r\n//\t\t\t\t\tNxNgc::MaterialBegin(); for ( lp = 0; lp < p_mat->m_passes; lp++ ) NxNgc::MaterialLayer( p_pass, lp, MATERIAL_GROUP_B );    NxNgc::MaterialEnd( &p_mesh->mp_dl->m_tev_stages, &p_mesh->mp_dl->m_tex_gens );\r\n//\t\t\t\t\tNxNgc::MaterialBegin(); for ( lp = 0; lp < p_mat->m_passes; lp++ ) NxNgc::MaterialLayer( p_pass, lp, MATERIAL_GROUP_C );    NxNgc::MaterialEnd( &p_mesh->mp_dl->m_tev_stages, &p_mesh->mp_dl->m_tex_gens );\r\n//\t\t\t\t\tNxNgc::MaterialBegin(); for ( lp = 0; lp < p_mat->m_passes; lp++ ) NxNgc::MaterialLayer( p_pass, lp, MATERIAL_GROUP_A );    NxNgc::MaterialEnd( &p_mesh->mp_dl->m_tev_stages, &p_mesh->mp_dl->m_tex_gens );\r\n//\r\n//\t\t\t\t\tGXSetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\t\t\t\t\tGXSetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\t\t\t\t\tGXSetAlphaCompare(GX_GREATER, p_mat->m_alpha_cutoff, GX_AOP_AND, GX_GREATER, p_mat->m_alpha_cutoff );\r\n//\t\t\t\t\t// ---------------- End Generate display list.\r\n//\r\n//\t\t\t\t\tuint32 size = GXEndDisplayList();\r\n//\r\n////\t\t\t\t\t// If we already have a display list & this one will fit, just use the existing piece of memory.\r\n////\t\t\t\t\tuint8 * p_dl;\r\n////\t\t\t\t\tif ( mp_display_list && ( size <= m_display_list_size ) )\r\n////\t\t\t\t\t{\r\n////\t\t\t\t\t\tp_dl = mp_display_list;\r\n////\t\t\t\t\t}\r\n////\t\t\t\t\telse\r\n////\t\t\t\t\t{\r\n////\t\t\t\t\t\tif ( mp_display_list )\r\n////\t\t\t\t\t\t{\r\n////\t\t\t\t\t\t\t//gMatBytes -= m_display_list_size;\r\n////\t\t\t\t\t\t\tdelete mp_display_list;\r\n////\t\t\t\t\t\t}\r\n//\t\t\t\t\t\tp_mesh->mp_dl->mp_material_dl = new uint8[size];\r\n//\t\t\t\t\t\t//gMatBytes += size;\r\n////\t\t\t\t\t}\r\n//\r\n//\t\t\t\t\tmemcpy ( p_mesh->mp_dl->mp_material_dl, p_build_dl, size );\r\n//\t\t\t\t\tDCFlushRange ( p_mesh->mp_dl->mp_material_dl, size );\r\n//\r\n//\t\t\t\t\tdelete p_build_dl;\r\n//\r\n//\t\t\t\t\tp_mesh->mp_dl->m_material_dl_size = size;\r\n//\t\t\t\t\tMem::Manager::sHandle().TopDownHeap()->PopAlign();\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\t\t\t\t\tfound = true;\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\t}\r\n//\t\t\t\tp_mat_list = (NxNgc::sMaterialHeader *)&(((char*)(&p_mat_list[1]))[p_mat_list->m_skip_bytes]);\r\n//\t\t\t}\r\n//\t\t\tif ( !found )\r\n//\t\t\t{\r\n//\t\t\t\tDbg_MsgAssert( 0, ( \"Unable to find material checksum 0x%08x\\n\", p_mesh->mp_dl->m_material.checksum ));\r\n//\t\t\t\tp_mesh->mp_dl->m_material.p_header = NULL;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n\r\n//\tif ( p_temp_col_remap ) delete [] p_temp_col_remap;\r\n//\tif ( p_temp_uv_remap ) delete [] p_temp_uv_remap;\r\n////\tif ( p_double ) delete p_double;\r\n//\r\n//\t// Done with the raw vertex data.\r\n////\tdelete[] p_vertex_colors;\r\n////\tdelete[] p_vertex_tex_coords;\r\n////\tdelete[] p_vertex_normals;\r\n//#ifdef SHORT_VERT\r\n//\tdelete[] p_vertex_positions;\r\n//#endif\t\t// SHORT_VERT\r\n//\r\n//\t// Set the data pointer to the new position on return.\r\n//\t*pp_mem = p_file_data;\r\n//\r\n//\treturn p_data;\r\n\r\n\tDbg_MsgAssert( false, ( \"Not yet implented!!!!!!!\" ) );\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nNxNgc::sObjectHeader* CNgcSector::LoadFromFile( NxNgc::sObjectHeader* p_data )\r\n{\r\n\tDbg_Assert( mp_geom );\r\n\r\n\tCNgcGeom *p_geom = static_cast<CNgcGeom*>( mp_geom );\r\n\t\r\n\t// Hook up vars.\r\n\tp_geom->m_num_mesh = p_data->m_num_meshes;\r\n//  \tp_geom->mp_scene->GetEngineScene()->mp_dl->mp_object_header = p_data;\r\n\r\n\tchar * p_skin = (char *)&p_data[1];\r\n\tint nbytes = p_data->m_skin.num_bytes;\r\n\tp_data->m_skin.p_data = p_skin;\r\n\tNxNgc::sDLHeader* p_dl = (NxNgc::sDLHeader*)&p_skin[nbytes];\r\n\r\n\tm_flags = p_dl->m_flags;\r\n\tSetChecksum( p_dl->m_checksum );\r\n\r\n\tfor( uint m = 0; m < p_geom->m_num_mesh; ++m )\r\n\t{\r\n\t\tNxNgc::sMesh*\tp_mesh = new NxNgc::sMesh;\r\n\r\n\t\tp_geom->AddMesh( p_mesh );\r\n\r\n\t\t// Setup mesh flags.\r\n\t\tif ( *((uint32*)(&p_dl->mp_col_pool)) & ( 0x00000100 | 0x00000400 ) )\r\n\t\t{\r\n\t\t\tp_mesh->m_flags |= NxNgc::sMesh::MESH_FLAG_NO_SKATER_SHADOW;\r\n\t\t}\r\n\t\tp_dl->mp_col_pool = NULL;\r\n\r\n\t\t// Setup bottom y.\r\n\t\tp_mesh->m_bottom_y = *((float*)(&p_dl->mp_pos_pool));\r\n\t\tp_dl->mp_pos_pool = NULL;\r\n\r\n\t\tif ( p_dl->m_size )\r\n\t\t{\r\n\t\t\t// Setup the DL.\r\n\t\t\tp_mesh->mp_dl = p_dl;\r\n\t\t\tp_mesh->mp_dl->mp_object_header = p_data;\r\n\t\t\tp_mesh->m_bone_idx = p_mesh->mp_dl->mp_object_header->m_bone_index;\r\n\r\n\t\t\t// Fix up the bounding sphere for billboards.\r\n\t\t\tswitch ( p_mesh->mp_dl->mp_object_header->m_billboard_type )\r\n\t\t\t{\r\n\t\t\t\tcase 1:\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tp_mesh->mp_dl->m_sphere[X] += p_mesh->mp_dl->mp_object_header->m_origin[X];\r\n\t\t\t\t\tp_mesh->mp_dl->m_sphere[Y] += p_mesh->mp_dl->mp_object_header->m_origin[Y];\r\n\t\t\t\t\tp_mesh->mp_dl->m_sphere[Z] += p_mesh->mp_dl->mp_object_header->m_origin[Z];\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tp_dl = (NxNgc::sDLHeader*)&(((char *)&p_dl[1])[p_dl->m_size]);\r\n\r\n\t\t\t// Find the material.\r\n\t\t\tNxNgc::sMaterialHeader * p_mat_list = p_geom->mp_scene->GetEngineScene()->mp_material_header;\r\n\t\t\tbool found = false;\r\n\t\t\tfor ( unsigned int lp = 0; lp < p_geom->mp_scene->GetEngineScene()->mp_scene_data->m_num_materials; lp++ )\r\n\t\t\t{\r\n\t\t\t\tif ( p_mat_list->m_checksum == p_mesh->mp_dl->m_material.checksum )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Found it!\r\n\t\t\t\t\tp_mesh->mp_dl->m_material.p_header = p_mat_list;\r\n\r\n//\t\t\t\t\tNxNgc::MaterialBuild( p_mesh, p_geom->mp_scene->GetEngineScene(), false, true ); \r\n\r\n\t\t\t\t\tfound = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t++p_mat_list;\r\n\t\t\t}\r\n\t\t\tif ( !found )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"Unable to find material checksum 0x%08x\\n\", p_mesh->mp_dl->m_material.checksum ));\r\n\t\t\t\tp_mesh->mp_dl->m_material.p_header = NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn (NxNgc::sObjectHeader*)p_dl;\r\n}\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CSector\r\n// and we will also have a CNgcSector, CNgcSector, even a CPcSector\r\n// maybe in the future we will have a CPS3Sector?\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcSector::plat_set_color(Image::RGBA rgba)\r\n{\r\n\t// Set values\r\n\tm_rgba = rgba;\r\n\r\n\t// Engine call here\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcSector::plat_clear_color()\r\n{\r\n\t// Set to white\r\n\tplat_set_color(Image::RGBA(128, 128, 128, 128));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcSector::plat_set_visibility(uint32 mask)\r\n{\r\n//\t// Set values\r\n//\tm_visible = mask;\r\n//\r\n//\t// Engine call here\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcSector::plat_set_active( bool on )\r\n{\r\n//\t// Set values\r\n//\tm_active = on;\r\n//\r\n//\tif( m_mesh_array )\r\n//\t{\r\n//\t\tfor( uint m = 0; m < m_num_mesh; ++m )\r\n//\t\t{\r\n//\t\t\tNxNgc::sMesh *p_mesh = m_mesh_array[m];\r\n//\t\t\tp_mesh->SetActive( on );\r\n//\t\t}\r\n//\t}\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n//bool CNgcSector::plat_is_active() const\r\n//{\r\n//\treturn m_active;\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n void CNgcSector::plat_set_world_position(const Mth::Vector& pos)\r\n {\r\n/*\r\n\tMth::Vector new_offset = pos - m_pos_offset;\r\n\r\n\t// Go through and adjust the individual meshes.\r\n\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n\t{\r\n\t\tNxNgc::sMesh *p_mesh = m_mesh_array[i];\r\n\t\tp_mesh->Move( new_offset );\r\n\t}\r\n*/\r\n }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::CBBox &CNgcSector::plat_get_bounding_box( void ) const\r\n{\r\n\tstatic Mth::CBBox dummy;\r\n\t\r\n\t//\treturn m_bbox;\r\n\treturn dummy;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\tCNgcSector::plat_get_world_position() const\r\n{\r\n\treturn m_pos_offset;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n//void CNgcSector::plat_set_y_rotation(Mth::ERot90 rot)\r\n//{\r\n//\t// Engine call here\r\n//\t// Garrett: TEMP just set the world matrix\r\n//\tMth::Matrix rot_mat;\r\n//\tCreateRotateYMatrix(rot_mat, (float) rot * (Mth::PI * 0.5f));\r\n//\r\n//\tm_world_matrix[X] = rot_mat[X];\r\n//\tm_world_matrix[Y] = rot_mat[Y];\r\n//\tm_world_matrix[Z] = rot_mat[Z];\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CNgcSector::plat_set_shatter(bool on)\t\r\n{\r\n\tif( on && mp_geom )\r\n\t{\r\n\t\tShatter( mp_geom );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSector * CNgcSector::plat_clone(bool instance, CScene *p_dest_scene)\r\n{\r\n\tCNgcSector *p_Ngc_sector = new CNgcSector();\r\n\r\n\t/*\r\n\r\n\r\n\t// Copies over much of the standard stuff, individual stuff will be overwritten later.\r\n\tCopyMemory( p_Ngc_sector, this, sizeof( CNgcSector ));\r\n\r\n\tif( instance )\r\n\t{\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Need to create a new set of meshes. First create the mesh pointer array...\r\n\t\tp_Ngc_sector->m_mesh_array = new NxNgc::sMesh*[m_num_mesh];\r\n\r\n\t\t// ...then clone the meshes themselves.\r\n\t\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n\t\t{\r\n\t\t\tp_Ngc_sector->m_mesh_array[i] = m_mesh_array[i]->Clone();\r\n\t\t}\r\n\r\n\t\t// Grab a temporary workspace buffer.\r\n\t\tNxNgc::sScene *p_scene\t\t\t\t\t\t\t\t= ( static_cast<CNgcScene*>( p_dest_scene ))->GetEngineScene();\r\n\t\tNxNgc::sMesh **p_temp_opaque_mesh_buffer\t\t\t= new NxNgc::sMesh*[p_scene->m_num_opaque_entries];\r\n\t\tNxNgc::sMesh **p_temp_semitransparent_mesh_buffer\t= new NxNgc::sMesh*[p_scene->m_num_semitransparent_entries];\r\n\r\n\t\t// Copy meshes over into the temporary workspace buffer.\r\n\t\tfor( int i = 0; i < p_scene->m_num_opaque_entries; ++i )\r\n\t\t{\r\n\t\t\tp_temp_opaque_mesh_buffer[i] = p_scene->m_opaque_meshes[i];\r\n\t\t}\r\n\t\tfor( int i = 0; i < p_scene->m_num_semitransparent_entries; ++i )\r\n\t\t{\r\n\t\t\tp_temp_semitransparent_mesh_buffer[i] = p_scene->m_semitransparent_meshes[i];\r\n\t\t}\r\n\r\n\t\t// Delete current mesh arrays.\r\n\t\tdelete [] p_scene->m_opaque_meshes;\r\n\t\tdelete [] p_scene->m_semitransparent_meshes;\r\n\r\n\t\t// Include new meshes in count.\r\n\t\tp_scene->CountMeshes( p_Ngc_sector->m_num_mesh, p_Ngc_sector->m_mesh_array );\r\n\r\n\t\t// Allocate new mesh arrays.\r\n\t\tp_scene->CreateMeshArrays();\r\n\r\n\t\t// Copy old mesh data back in.\r\n\t\tfor( int i = 0; i < p_scene->m_num_opaque_entries; ++i )\r\n\t\t{\r\n\t\t\tp_scene->m_opaque_meshes[i] = p_temp_opaque_mesh_buffer[i];\r\n\t\t}\r\n\t\tfor( int i = 0; i < p_scene->m_num_semitransparent_entries; ++i )\r\n\t\t{\r\n\t\t\tp_scene->m_semitransparent_meshes[i] = p_temp_semitransparent_mesh_buffer[i];\r\n\t\t}\r\n\r\n\t\t// Add new meshes.\r\n\t\tp_scene->AddMeshes( p_Ngc_sector->m_num_mesh, p_Ngc_sector->m_mesh_array );\r\n\r\n\t\t// Sort the meshes.\r\n\t\tp_scene->SortMeshes();\r\n\t}\r\n*/\r\n\treturn p_Ngc_sector;\r\n}\r\n\r\n\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxsector.h",
    "content": "#ifndef\t__GFX_P_NX_SECTOR_H__\r\n#define\t__GFX_P_NX_SECTOR_H__\r\n\r\n#include \t<core\\math.h>\r\n#include \t<core\\math\\geometry.h>\r\n#include \t\"gfx\\NxSector.h\"\r\n#include \t\"gfx\\Image\\ImageBasic.h\"\r\n\r\n#include \t\"gfx\\ngc\\p_nxscene.h\"\r\n#include \t\"gfx\\ngc\\nx\\mesh.h\"\r\n#include \t\"gfx\\ngc\\nx\\geomnode.h\"\r\n\r\n#include \t<gfx/nxsector.h>\r\n\r\nnamespace NxNgc\r\n{\r\n\tclass CGeomNode;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CSector\r\nclass CNgcSector : public CSector\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\t\tCNgcSector();\r\n\r\n\tNxNgc::sObjectHeader*\t\tLoadFromFile( NxNgc::sObjectHeader* p_data );\r\n\tNxNgc::sObjectHeader*\t\tLoadFromMemory( NxNgc::sObjectHeader* p_data );\r\n\t\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\tvirtual void\t\t\t\tplat_set_color(Image::RGBA rgba);\r\n\tvirtual void\t\t\t\tplat_clear_color();\r\n\tvirtual void\t\t\t\tplat_set_visibility(uint32 mask);\r\n\tvirtual void\t\t\t\tplat_set_active(bool on);\t\r\n\tvirtual void\t\t\t\tplat_set_world_position(const Mth::Vector& pos);\r\n\tvirtual const Mth::CBBox\t&plat_get_bounding_box( void ) const;\r\n\tvirtual const Mth::Vector &\tplat_get_world_position() const;\r\n\tvirtual void\t\t\t\tplat_set_shatter( bool on );\r\n\tvirtual CSector *\t\t\tplat_clone(bool instance, CScene *p_dest_scene);\r\n\r\n\tint\t\t\t\t\t\t\t\tm_flags;\r\n\r\n\tMth::Vector\t\t\t\t\t\tm_pos_offset;\r\n\r\n\tImage::RGBA\t\t\t\t\t\tm_rgba;\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif"
  },
  {
    "path": "Code/Gfx/NGC/p_nxtexman.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxTexMan.cpp - Ngc platform specific interface to CTexMan\r\n//\r\n\r\n#include <core/defines.h>\r\n\r\n#include \"gfx/NxTexMan.h\"\r\n#include \"gfx/Ngc/p_NxTexture.h\"\r\n#include \"gfx/Ngc/nx/import.h\"\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCTexDict* CTexDictManager::s_plat_load_texture_dictionary( const char *p_tex_dict_name, bool is_level_data, uint32 texDictOffset, bool isSkin, bool forceTexDictLookup )\r\n{\r\n//\tNxNgc::LoadTextureFile( p_tex_dict_name );\r\n\treturn new CNgcTexDict( p_tex_dict_name, forceTexDictLookup );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCTexDict* CTexDictManager::s_plat_load_texture_dictionary( uint32 checksum, uint32 *p_data, int data_size, bool is_level_data, uint32 texDictOffset, bool is_skin, bool forceTexDictLookup )\r\n{\r\n\tCNgcTexDict *p_dict = new CNgcTexDict( checksum );\r\n\tp_dict->LoadTextureDictionaryFromMemory( p_data );\r\n\treturn p_dict;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCTexDict* CTexDictManager::s_plat_create_texture_dictionary( uint32 checksum )\r\n{\r\n\treturn new CNgcTexDict( checksum );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CTexDictManager::s_plat_unload_texture_dictionary( CTexDict* p_tex_dict )\r\n{\r\n\tdelete p_tex_dict;\r\n\treturn true;\r\n}\r\n\r\n\r\n} \r\n \r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxtexture.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxTexture.cpp\r\n\r\n#include \t\"Gfx/Nx.h\"\r\n#include \t\"Gfx/Ngc/p_NxTexture.h\"\r\n#include \t\"Gfx/Ngc/NX/import.h\"\r\n\r\nextern bool g_in_cutscene;\r\n\r\nnamespace Nx\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CTexture\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcTexture::CNgcTexture() :  mp_texture( NULL )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcTexture::~CNgcTexture()\r\n{\r\n\tif( mp_texture )\r\n\t{\r\n\t\tdelete mp_texture;\r\n\t}\r\n}\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcTexture::plat_load_texture( const char *p_texture_name, bool sprite, bool alloc_vram )\r\n{\r\n\tchar filename[256];\r\n\r\n\tstrcpy( filename, p_texture_name );\r\n\t\r\n\t// append '.img.ngc' to the end.\r\n\tstrcat( filename, \".img.ngc\" );\r\n\t\r\n\tmp_texture = NxNgc::LoadTexture( filename );\r\n\t\r\n\treturn mp_texture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcTexture::plat_replace_texture( CTexture *p_texture )\r\n{\t\t\t\t\t\t  \r\n\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\r\n\tDbg_Assert(p_texture);\r\n\t\r\n\tCNgcTexture *p_Ngc_texture = static_cast<CNgcTexture *>( p_texture );\r\n\r\n\t// Go through and copy the texture.\r\n\tNxNgc::sTexture *p_src\t= p_Ngc_texture->GetEngineTexture();\r\n\tNxNgc::sTexture *p_dst\t= GetEngineTexture();\r\n\r\n\t// Couple of problem cases.\r\n//\tDbg_MsgAssert( p_src->format == p_dst->format, ( \"Cannot replace textures of different formats.\\n\" ));\r\n//\tif ( p_src->pAlphaData && !p_dst->pAlphaData )\r\n//\t{\r\n//\t\tDbg_MsgAssert( false, ( \"Cannot assign a texture with alpha to a texture without alpha.\\n\" ));\r\n//\t}\r\n//\tif ( !p_src->pAlphaData && p_dst->pAlphaData )\r\n//\t{\r\n//\t\tDbg_MsgAssert( false, ( \"Cannot assign a texture without alpha to a texture with alpha.\\n\" ));\r\n//\t}\r\n\r\n\t// Delete & re-allocate alpha space if new image is bigger, or not single owner alpha, or not channel 0.\r\n\tif ( p_src->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA )\r\n\t{\r\n\t\t// See if this texture needs to be stored in pOldAlpha.\r\n\t\tif ( !( p_dst->flags & NxNgc::sTexture::TEXTURE_FLAG_SINGLE_OWNER ) &&\r\n\t\t\t ( ( p_dst->flags & NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_MASK ) == NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_GREEN ) )\r\n\t\t{\r\n\t\t\tp_dst->pOldAlphaData = p_dst->pAlphaData;\r\n\t\t\tp_dst->flags |= NxNgc::sTexture::TEXTURE_FLAG_OLD_DATA;\r\n\t\t}\r\n\r\n\t\tif ( ( p_dst->byte_size < p_src->byte_size ) ||\r\n\t\t\t !( p_dst->flags & NxNgc::sTexture::TEXTURE_FLAG_SINGLE_OWNER ) ||\r\n\t\t\t ( ( p_dst->flags & NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_MASK ) != NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_GREEN ) )\r\n\t\t{\r\n\t\t\tif( p_dst->pAlphaData &&\r\n\t\t\t\t( p_dst->byte_size < p_src->byte_size ) &&\r\n\t\t\t\t( p_dst->flags & NxNgc::sTexture::TEXTURE_FLAG_SINGLE_OWNER ) &&\r\n\t\t\t\t( ( p_dst->flags & NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_MASK ) == NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_GREEN ) )\r\n\t\t\t{\r\n\t\t\t\tdelete [] p_dst->pAlphaData;\r\n\t\t\t}\r\n\t\t\tp_dst->pAlphaData = new uint8[p_src->byte_size];\r\n\t\t}\r\n\t}\r\n\r\n\t// Delete & re-allocate texture space if new image is bigger.\r\n\tif ( p_dst->byte_size < p_src->byte_size )\r\n\t{\r\n\t\tif( p_dst->pTexelData )\r\n\t\t{\r\n\t\t\tdelete [] p_dst->pTexelData;\r\n\t\t}\r\n\t\tp_dst->pTexelData = new uint8[p_src->byte_size];\r\n\t\tp_dst->byte_size = p_src->byte_size;\r\n\t}\r\n\r\n\tp_dst->BaseWidth\t= p_src->BaseWidth;\r\n\tp_dst->BaseHeight\t= p_src->BaseHeight;\r\n\tp_dst->ActualWidth\t= p_src->ActualWidth;\r\n\tp_dst->ActualHeight\t= p_src->ActualHeight;\r\n\r\n\tp_dst->flags\t\t= ( p_dst->flags & ~NxNgc::sTexture::TEXTURE_FLAG_HAS_HOLES ) | ( p_src->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_HOLES );\r\n\r\n\t// Copy the pixel data.\r\n\tmemcpy( p_dst->pTexelData, p_src->pTexelData, p_src->byte_size );\r\n\tDCFlushRange ( p_dst->pTexelData, p_src->byte_size );\r\n\r\n\t// Copy the alpha data if necessary.\r\n\tif ( p_src->pAlphaData && p_dst->pAlphaData )\r\n\t{\r\n\t\tmemcpy( p_dst->pAlphaData, p_src->pAlphaData, p_src->byte_size );\r\n\t\tDCFlushRange ( p_dst->pAlphaData, p_src->byte_size );\r\n\t\tp_dst->flags\t\t= ( p_dst->flags & ~NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA ) | ( p_src->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA );\r\n\t\tp_dst->flags\t\t= ( p_dst->flags & ~NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_MASK ) | NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_GREEN;\r\n\t\tp_dst->flags\t\t= p_dst->flags | NxNgc::sTexture::TEXTURE_FLAG_SINGLE_OWNER;\r\n\t}\r\n\r\n\t// If the replacement texture doesn't have alpha, but the original does, twiddle the flag.\r\n\tif ( p_dst->pAlphaData && !p_src->pAlphaData )\r\n\t{\r\n\t\tp_dst->flags\t\t= ( p_dst->flags & ~NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA );\r\n\t}\r\n\t\r\n\t// Replacement texture does not mip-map.\r\n\tp_dst->Levels = 0;\r\n\r\n\t// So that if the regular texture is 32-bit, it can have a CMPR texture copied over it.\r\n\tp_dst->format\t\t= p_src->format;\r\n\r\n\t// Flag this texture as having been replaced.\r\n\tp_dst->flags |= NxNgc::sTexture::TEXTURE_FLAG_REPLACED;\r\n\r\n\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcTexture::plat_add_to_vram( void )\r\n{\t\t\t\t\t\t\t\t \t\r\n\t// Meaningless on Ngc, added to remove annoying debug stub output.\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcTexture::plat_remove_from_vram( void )\r\n{\t\t\t\t\t\t\t\t \t\r\n\t// Meaningless on Ngc, added to remove annoying debug stub output.\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint16\tCNgcTexture::plat_get_width() const\r\n{\r\n\tif( mp_texture )\r\n\t{\r\n\t\treturn mp_texture->BaseWidth;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint16\tCNgcTexture::plat_get_height() const\r\n{\r\n\tif( mp_texture )\r\n\t{\r\n\t\treturn mp_texture->BaseHeight;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\tCNgcTexture::plat_get_bitdepth() const\r\n{\r\n\tswitch ( ((GXTexFmt)mp_texture->format) )\r\n\t{\r\n\t\tcase GX_TF_I4:\r\n\t\tcase GX_TF_IA4:\r\n\t\tcase GX_TF_CMPR:\r\n\t\t\treturn 4;\r\n\t\t\tbreak;\r\n\r\n\t\tcase GX_TF_I8:\r\n\t\tcase GX_TF_IA8:\r\n\t\tcase GX_TF_A8:\r\n\t\tcase GX_TF_Z8:\r\n\t\t\treturn 8;\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase GX_TF_RGB565:\r\n\t\tcase GX_TF_RGB5A3:\r\n\t\tcase GX_TF_Z16:\r\n\t\t\treturn 16;\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\tcase GX_TF_RGBA8:\r\n\t\tcase GX_TF_Z24X8:\r\n\t\t\treturn 32;\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\tCNgcTexture::plat_get_num_mipmaps() const\r\n{\r\n\treturn mp_texture->Levels;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCNgcTexture::plat_is_transparent() const\r\n{\r\n\treturn false;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CTexDict\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNgcTexDict::CNgcTexDict( uint32 checksum ) : CTexDict( checksum )\r\n{\r\n\t// Load nothing\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNgcTexDict::CNgcTexDict( const char *p_tex_dict_name, bool forceTexDictLookup ) : CTexDict( p_tex_dict_name, true )\r\n{\r\n\t LoadTextureDictionary( p_tex_dict_name, forceTexDictLookup );\t// the derived class will does this\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNgcTexDict::~CNgcTexDict()\r\n{\r\n\tUnloadTextureDictionary();\t\t\t\t// the derived class does this\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcTexDict::LoadTextureDictionary( const char *p_tex_dict_name, bool forceTexDictLookup )\r\n{\r\n\tNxNgc::LoadTextureFile( p_tex_dict_name, mp_texture_lookup );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcTexDict::LoadTextureDictionaryFromMemory( void *p_mem )\r\n{\r\n\tNx::LoadTextureFileFromMemory( &p_mem, mp_texture_lookup );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcTexDict::UnloadTextureDictionary()\r\n{\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCTexture *CNgcTexDict::plat_load_texture(const char *p_texture_name, bool sprite, bool alloc_vram )\r\n{\r\n\tCNgcTexture *p_texture = new CNgcTexture;\r\n\tif( !p_texture->LoadTexture( p_texture_name, sprite ))\r\n\t{\r\n\t\tDbg_Error(\"Can't load texture %s\", p_texture_name);\r\n\t}\r\n\treturn p_texture;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCTexture *CNgcTexDict::plat_reload_texture( const char *p_texture_name )\r\n{\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcTexDict::plat_unload_texture( CTexture *p_texture )\r\n{\r\n\tdelete p_texture;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcTexDict::plat_add_texture( CTexture *p_texture )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CNgcTexDict::plat_remove_texture( CTexture *p_texture )\r\n{\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n#define MemoryRead( dst, size, num, src )\tmemcpy(( dst ), ( src ), (( num ) * ( size )));\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t( src ) += (( num ) * ( size ))\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid LoadTextureFileFromMemory( void **pp_mem, Lst::HashTable<Nx::CTexture> *p_texture_table )\r\n{\r\n\tuint8 *p_data = (uint8*)( *pp_mem );\r\n\r\n\tuint32 temp;\r\n\t\r\n\t// Open the texture file.\r\n//\tvoid *p_FH = File::Open( Filename, \"rb\" );\r\n//\tif( !p_FH )\r\n//\t{\r\n//\t\tDbg_Message( \"Couldn't open texture file %s\\n\", Filename );\r\n////\t\treturn 0;\r\n//\t\treturn;\r\n//\t}\r\n\r\n\t// Read the texture file version.\r\n\tint version;\r\n\tMemoryRead( &version, sizeof( int ), 1, p_data );\r\n\r\n\t// Read the number of textures.\t\r\n\tint num_textures;\r\n\tMemoryRead( &num_textures, sizeof( int ), 1, p_data );\r\n\t\r\n//\tNumTextures\t\t\t\t+= num_textures;\r\n\r\n\tint bytes;\r\n\tbool need_to_pop;\r\n\r\n\tNxNgc::sTexture ** p_tex = new (Mem::Manager::sHandle().TopDownHeap()) NxNgc::sTexture *[num_textures];\r\n\tunsigned short * p_resolvem = new (Mem::Manager::sHandle().TopDownHeap()) unsigned short[num_textures];\r\n\tunsigned short * p_resolvec = new (Mem::Manager::sHandle().TopDownHeap()) unsigned short[num_textures];\r\n\tint num_resolve = 0;\r\n\r\n\tint mem_available;\r\n\tfor( int t = 0; t < num_textures; ++t )\r\n\t{\r\n\t\tneed_to_pop = false;\r\n\t\tbytes = sizeof( NxNgc::sTexture );\r\n\t\tif ( g_in_cutscene )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().FrontEndHeap() );\r\n\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\tif ( bytes < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t{\r\n\t\t\t\tneed_to_pop = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ThemeHeap() );\r\n\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\tif ( bytes < ( mem_available - ( 5 * 1024 ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ScriptHeap() );\r\n\t\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\t\tif ( bytes < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tNxNgc::sTexture *p_texture = new NxNgc::sTexture;\r\n\t\t\r\n\t\tif ( need_to_pop )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t}\r\n\r\n\t\tp_tex[t] = p_texture;\r\n\r\n\t\tMemoryRead( &p_texture->Checksum,\t\tsizeof( uint32 ), 1, p_data );\r\n\t\tMemoryRead( &temp,\t\tsizeof( uint32 ), 1, p_data );\r\n\t\tp_texture->BaseWidth = (uint16)temp;\r\n\t\tMemoryRead( &temp,\t\tsizeof( uint32 ), 1, p_data );\r\n\t\tp_texture->BaseHeight = (uint16)temp;\r\n\t\tMemoryRead( &temp,\t\tsizeof( uint32 ), 1, p_data );\r\n\t\tp_texture->Levels = (uint16)temp;\r\n\r\n\t\tp_texture->ActualWidth = ( p_texture->BaseWidth + 3 ) & ~3;\r\n\t\tp_texture->ActualHeight = ( p_texture->BaseHeight + 3 ) & ~3;\r\n\r\n\t\tint tex_format;\r\n\t\tint channel;\r\n\t\tint index;\r\n\t\tMemoryRead( &tex_format, sizeof( uint32 ), 1, p_data );\r\n\t\tchannel = ( tex_format >> 8 ) & 0xff;\r\n\t\tindex = ( tex_format >> 16 ) & 0xffff;\r\n\t\ttex_format = tex_format & 0xff;\r\n\r\n\t\tswitch ( tex_format ) {\r\n\t\t\tcase 0:\r\n\t\t\t\tp_texture->format = GX_TF_CMPR;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1:\r\n\t\t\t\tp_texture->format = GX_TF_CMPR;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\tp_texture->format = GX_TF_RGBA8;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert( false, (\"Illegal texture format: %d\\n\", tex_format ));\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tp_texture->flags = 0;\r\n\r\n\t\tint has_holes;\r\n\t\tMemoryRead( &has_holes, sizeof( uint32 ), 1, p_data );\r\n\t\tp_texture->flags |= has_holes ? NxNgc::sTexture::TEXTURE_FLAG_HAS_HOLES : 0;\r\n\r\n\t\tuint8 * p8[8];\r\n\t\tint mipbytes[8];\r\n\r\n\t\t// Read color maps.\r\n\t\tbytes = 0;\r\n\t\tfor( uint32 mip_level = 0; mip_level < p_texture->Levels; ++mip_level )\r\n\t\t{\r\n\t\t\tuint32 texture_level_data_size;\r\n\t\t\tMemoryRead( &texture_level_data_size,\t\t\tsizeof( uint32 ), 1, p_data );\r\n\r\n\t\t\tp8[mip_level] = new (Mem::Manager::sHandle().TopDownHeap()) uint8[texture_level_data_size];\r\n\t\t\tmipbytes[mip_level] = texture_level_data_size;\r\n\t\t\tbytes += texture_level_data_size;\r\n\r\n\t\t\tMemoryRead( p8[mip_level], texture_level_data_size, 1, p_data );\r\n\t\t}\r\n\t\t// Copy all textures & delete the originals.\r\n\r\n\t\tneed_to_pop = false;\r\n\t\tif ( g_in_cutscene )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().FrontEndHeap() );\r\n\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\tif ( bytes < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t{\r\n\t\t\t\tneed_to_pop = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ThemeHeap() );\r\n\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\tif ( bytes < ( mem_available - ( 5 * 1024 ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ScriptHeap() );\r\n\t\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\t\tif ( bytes < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\t\tp_texture->pTexelData = new uint8[bytes];\r\n\t\tp_texture->byte_size = bytes;\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\r\n\t\tif ( need_to_pop )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t}\r\n\r\n\t\tuint8 * pTex = p_texture->pTexelData;\r\n\t\tfor( uint32 mip_level = 0; mip_level < p_texture->Levels; ++mip_level )\r\n\t\t{\r\n\t\t\tmemcpy( pTex, p8[mip_level], mipbytes[mip_level] );\r\n\t\t\tdelete p8[mip_level];\r\n\t\t\tpTex += mipbytes[mip_level];\r\n\t\t}\r\n\r\n\t\t// Read alpha maps.\r\n\t\tif ( tex_format == 1 )\r\n\t\t{\r\n\t\t\tif ( channel == 0 )\r\n\t\t\t{\r\n\t\t\t\tbytes = 0;\r\n\t\t\t\tfor( uint32 mip_level = 0; mip_level < p_texture->Levels; ++mip_level )\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 texture_level_data_size;\r\n\t\t\t\t\tMemoryRead( &texture_level_data_size,\t\t\tsizeof( uint32 ), 1, p_data );\r\n\r\n\t\t\t\t\tp8[mip_level] = new (Mem::Manager::sHandle().TopDownHeap()) uint8[texture_level_data_size];\r\n\t\t\t\t\tmipbytes[mip_level] = texture_level_data_size;\r\n\t\t\t\t\tbytes += texture_level_data_size;\r\n\r\n\t\t\t\t\tMemoryRead( p8[mip_level], texture_level_data_size, 1, p_data );\r\n\t\t\t\t}\r\n\t\t\t\t// Copy all textures & delete the originals.\r\n\r\n\t\t\t\tneed_to_pop = false;\r\n\t\t\t\tif ( g_in_cutscene )\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().FrontEndHeap() );\r\n\t\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\t\tif ( bytes < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ThemeHeap() );\r\n\t\t\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\t\t\tif ( bytes < ( mem_available - ( 5 * 1024 ) ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ScriptHeap() );\r\n\t\t\t\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\t\t\t\tif ( bytes < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\t\t\t\tp_texture->pAlphaData = new uint8[bytes];\r\n\t\t\t\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\r\n\t\t\t\tif ( need_to_pop )\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuint8 * pTex = p_texture->pAlphaData;\r\n\t\t\t\tfor( uint32 mip_level = 0; mip_level < p_texture->Levels; ++mip_level )\r\n\t\t\t\t{\r\n\t\t\t\t\tmemcpy( pTex, p8[mip_level], mipbytes[mip_level] );\r\n\t\t\t\t\tdelete p8[mip_level];\r\n\t\t\t\t\tpTex += mipbytes[mip_level];\r\n\t\t\t\t}\r\n\t\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA;\r\n\r\n\t\t\t\tp_resolvem[num_resolve] = t;\r\n\t\t\t\tp_resolvec[num_resolve] = index;\r\n\t\t\t\tnum_resolve++;\r\n\t\t\t}\r\n\t\t\tswitch ( channel )\r\n\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_GREEN;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_RED;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_BLUE;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_SINGLE_OWNER;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No unique alpha map.\r\n\t\t\tp_texture->pAlphaData = NULL;\r\n\t\t\tp_texture->flags &= ~NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA;\r\n\t\t\tp_texture->flags |= NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_GREEN;\r\n\t\t}\r\n\r\n\t\t// Add this texture to the table.\r\n//\t\tpTextureTable->PutItem( p_texture->Checksum, p_texture );\r\n\t\tneed_to_pop = false;\r\n\r\n\t\tbytes = sizeof( Nx::CNgcTexture );\r\n\t\tif ( g_in_cutscene )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().FrontEndHeap() );\r\n\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\tif ( bytes < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t{\r\n\t\t\t\tneed_to_pop = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ThemeHeap() );\r\n\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\tif ( bytes < ( mem_available - ( 5 * 1024 ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ScriptHeap() );\r\n\t\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\t\tif ( bytes < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tNx::CNgcTexture *p_Ngc_texture = new Nx::CNgcTexture();\r\n\r\n\t\tif ( need_to_pop )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t}\r\n\r\n\t\tp_Ngc_texture->SetEngineTexture( p_texture );\r\n\t\tif ( p_texture_table )\r\n\t\t{\r\n\t\t\tp_texture_table->PutItem( p_texture->Checksum, p_Ngc_texture );\r\n\t\t}\r\n\t}\r\n\r\n\t// Resolve alpha maps.\r\n\tfor ( int r = 0; r < num_resolve; r++ )\r\n\t{\r\n\t\tp_tex[p_resolvem[r]]->pAlphaData = p_tex[p_resolvec[r]]->pAlphaData;\r\n\t\tp_tex[p_resolvec[r]]->flags &= ~NxNgc::sTexture::TEXTURE_FLAG_SINGLE_OWNER;\r\n\t}\r\n\r\n\tdelete p_tex;\r\n\tdelete p_resolvem;\r\n\tdelete p_resolvec;\r\n//\treturn pTextureTable;\r\n}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxtexture.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxScene.h\r\n\r\n#ifndef\t__GFX_P_NX_TEXTURE_H__\r\n#define\t__GFX_P_NX_TEXTURE_H__\r\n\r\n#include \t\"Gfx/NxTexture.h\"\r\n#include \t\"Gfx/Ngc/nx/texture.h\"\r\n#include \t\"Gfx/Ngc/nx/material.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Machine specific implementation of the CTexture\r\nclass\tCNgcTexture : public CTexture\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCNgcTexture();\r\n\tvirtual\t\t\t\t\t\t~CNgcTexture();\r\n\r\n\tNxNgc::sTexture\t\t\t*GetEngineTexture() const;\r\n\tvoid\t\t\t\t\t\tSetEngineTexture( NxNgc::sTexture *p_texture )\t{ mp_texture = p_texture; }\r\n\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\tvirtual bool\t\t\t\tplat_load_texture( const char *p_texture_name, bool sprite, bool alloc_vram );\r\n\tvirtual bool\t\t\t\tplat_replace_texture( CTexture *p_texture );\r\n\tvirtual bool\t\t\t\tplat_add_to_vram( void );\r\n\tvirtual bool\t\t\t\tplat_remove_from_vram( void );\r\n\r\n\tvirtual uint16\t\t\t\tplat_get_width() const;\r\n\tvirtual uint16\t\t\t\tplat_get_height() const;\r\n\tvirtual uint8\t\t\t\tplat_get_bitdepth() const;\r\n\tvirtual uint8\t\t\t\tplat_get_num_mipmaps() const;\r\n\tvirtual bool\t\t\t\tplat_is_transparent() const;\r\n\r\n\t// The actual data in the engine\r\n\tNxNgc::sTexture *\t\t\tmp_texture;\r\n\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ninline NxNgc::sTexture\t*CNgcTexture::GetEngineTexture() const\r\n{\r\n\treturn mp_texture;\r\n}\r\n\r\n\r\n\r\n//////////////////////////////////////////////////////////////////////////////////\r\n// Machine specific implementation of the CMaterial\r\nclass\tCNgcMaterial : public CMaterial\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCNgcMaterial();\r\n\tvirtual\t\t\t\t\t\t~CNgcMaterial();\r\n\r\nprivate:\r\n\tImage::RGBA\t\t\t\t\tplat_get_rgba() const;\r\n\tvoid\t\t\t\t\t\tplat_set_rgba(Image::RGBA rgba);\r\n\tvoid\t\t\t\t\t\tplat_set_texture();\r\n\r\n\tImage::RGBA\t\t\t\t\tm_rgba;\r\n\r\n\t// The actual data in the engine\r\n\tNxNgc::sMaterial *\t\t\tmp_material;\r\n};\r\n\r\n//////////////////////////////////////////////////////////////////////////////////\r\n// Machine specific implementation of the CTexDict\r\nclass\tCNgcTexDict : public CTexDict\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCNgcTexDict( uint32 checksum );\t\t// loads nothing\r\n\t\t\t\t\t\t\t\tCNgcTexDict(const char *p_tex_dict_name, bool forceTexDictLookup = false);\r\n\tvirtual\t\t\t\t\t\t~CNgcTexDict();\r\n\r\n\tbool\t\t\t\t\t\tLoadTextureDictionary(const char *p_tex_dict_name, bool forceTexDictLookup = false);\r\n\tbool\t\t\t\t\t\tLoadTextureDictionaryFromMemory( void *p_mem );\r\n\tbool\t\t\t\t\t\tUnloadTextureDictionary();\r\n\r\nprivate:\r\n\t// Platform-specific calls\r\n\tvirtual CTexture *\t\t\tplat_load_texture( const char *p_texture_name, bool sprite, bool alloc_vram );\r\n\tvirtual CTexture *\t\t\tplat_reload_texture(const char *p_texture_name);\r\n\tvirtual bool\t\t\t\tplat_unload_texture(CTexture *p_texture);\r\n\tvirtual void\t\t\t\tplat_add_texture(CTexture *p_texture);\r\n\tvirtual bool\t\t\t\tplat_remove_texture(CTexture *p_texture);\r\n\r\n//\tNxNgc::sScene *\t\t\tmp_tex_dict;\t\t// Platform-dependent data\r\n\r\n};\r\n\r\nvoid LoadTextureFile( const char *Filename, Lst::HashTable<Nx::CTexture> *p_texture_table );\r\nvoid LoadTextureFileFromMemory( void **pp_mem, Lst::HashTable<Nx::CTexture> *p_texture_table );\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxviewman.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxViewMan.cpp - Ngc platform specific interface to CViewportManager\r\n//\r\n// This is Ngc SPECIFIC!!!!!!  So might get a bit messy\r\n\r\n#include <core/defines.h>\r\n\r\n#include \"gfx/NxViewMan.h\"\r\n#include \"gfx/NGC/p_NxViewport.h\"\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCViewport *\t\tCViewportManager::s_plat_create_viewport(const Mth::Rect* rect, Gfx::Camera* cam)\r\n{\r\n\treturn new CNgcViewport(rect, cam);\r\n}\r\n\r\n} \r\n \r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxweather.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxWeather.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  6/2/2003\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngc/nx/render.h\"\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n\r\n#include \"gfx/ngc/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngc/p_nxtexture.h>\r\n\r\n#include \"gfx/ngc/nx/mesh.h\"\r\n\r\n#include \"gfx/ngc/p_nxweather.h\"\r\n#include \"gfx/ngc/p_nxparticle.h\"\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/skater.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <engine/SuperSector.h>\r\n#include \"gfx/nx.h\"\r\n#include <sys\\ngc\\p_gx.h>\r\n\r\n#include \"dolphin/base/ppcwgpipe.h\"\r\n#include \"dolphin/gx/gxvert.h\"\r\n\r\n#define FEELER_START 50000.0f\r\n\r\nunsigned char grid_bytes[45*1024];\r\n\r\n#define RENDER_DIST 16\r\n//#define RAIN_HEIGHT 2000\r\n//#define RAIN_FRAMES 40\r\n//#define RAIN_LENGTH 100.0f\r\n#define SEQ_START 411\t\t// Between 1 and 4095.\r\n#define SEQ_MASK 0x0240\r\n//#define SEQ_MASK 0x0ca0\r\n//#define NUM_DROPS_PER_FRAME 25\r\n\r\n//1-3: 0x03\r\n//1-7: 0x06\r\n//1-15: 0x0C\r\n//1-31: 0x14\r\n//1-63: 0x30\r\n//1-127: 0x60\r\n//1-255: 0xB8\r\n//1-511: 0x0110\r\n//1-1023: 0x0240\r\n//1-2047: 0x0500\r\n//1-4095: 0x0CA0\r\n//1-8191: 0x1B00\r\n//1-16383: 0x3500\r\n//1-32767: 0x6000\r\n//1-65535: 0xB400\r\n//0x00012000\r\n//0x00020400\r\n//0x00072000\r\n//0x00090000\r\n//0x00140000\r\n//0x00300000\r\n//0x00400000\r\n//0x00D80000\r\n//0x01200000\r\n//0x03880000\r\n//0x07200000\r\n//0x09000000\r\n//0x14000000\r\n//0x32800000\r\n//0x48000000\r\n//0xA3000000\r\n\r\n\r\n//#define DEBUG_LINES\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcWeather::CNgcWeather()\r\n{\r\n\tmp_roof_height_index = NULL;\r\n\tmp_rain_texture = NULL;\r\n\tmp_snow_texture = NULL;\r\n\r\n\tm_rain_blend = get_texture_blend( CRCD(0xa86285a1,\"fixadd\") );\t\t// FixAdd / 64\r\n\tm_splash_blend = get_texture_blend( CRCD(0xa86285a1,\"fixadd\") );\t\t// FixAdd / 64\r\n\tm_snow_blend = get_texture_blend( CRCD(0xa86285a1,\"fixadd\") );\t\t// FixAdd / 64\r\n\r\n\tm_rain_blend_fix = 64;\r\n\tm_splash_blend_fix = 64;\r\n\tm_snow_blend_fix = 64;\r\n\r\n\tm_rain_rate = 0.0f;\r\n\tm_splash_rate = 0.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCNgcWeather::~CNgcWeather()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcWeather::plat_update_grid( void )\r\n{\r\n\tm_system_active = false;\r\n\t// Get super sector manager.\r\n\tSSec::Manager *ss_man;\r\n\tMth::Line line;\r\n\tss_man = Nx::CEngine::sGetNearestSuperSectorManager( line );\t\t// Line is ignored, 1st manager is returned.\r\n\tif ( !ss_man ) return;\r\n\r\n\t// Calculate the size of the world in cels.\r\n\tint min_x = ( ((int)ss_man->GetWorldBBox()->GetMin()[X]) / WEATHER_CEL_SIZE ) - 1;\r\n\tint max_x = ( ((int)ss_man->GetWorldBBox()->GetMax()[X]) / WEATHER_CEL_SIZE ) + 1;\r\n\tint min_z = ( ((int)ss_man->GetWorldBBox()->GetMin()[Z]) / WEATHER_CEL_SIZE ) - 1;\r\n\tint max_z = ( ((int)ss_man->GetWorldBBox()->GetMax()[Z]) / WEATHER_CEL_SIZE ) + 1;\r\n\r\n\t// Define a maximum...\r\n\tif ( ( max_x - min_x ) > 350 )\r\n\t{\r\n\t\tint wid = ( max_x - min_x );\r\n\t\tint excess = ( wid - 350 );\r\n\t\tmin_x += ( excess / 2 );\r\n\t\tmax_x -= ( excess / 2 );\r\n\t}\r\n\r\n\tif ( ( max_z - min_z ) > 300 )\r\n\t{\r\n\t\tint wid = ( max_z - min_z );\r\n\t\tint excess = ( wid - 300 );\r\n\t\tmin_z += ( excess / 2 );\r\n\t\tmax_z -= ( excess / 2 );\r\n\t}\r\n\r\n\t// This is the actual width;\r\n\tm_width = ( max_x - min_x ) + 1;\r\n\tm_height = ( max_z - min_z ) + 1;\r\n\r\n\t// Allocate a new piece of memory for the grid.\r\n//\tif ( mp_roof_height_index ) delete mp_roof_height_index;\r\n//\tmp_roof_height_index = new unsigned char[m_width * m_height];\r\n\r\n//\tmp_roof_height_index = grid_bytes;\r\n\r\n\tm_min_x = ( min_x * WEATHER_CEL_SIZE );\r\n\tm_min_z = ( min_z * WEATHER_CEL_SIZE );\r\n\r\n\t// Temporary buffer for the raw array.\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tunsigned char * p8 = new unsigned char[m_width*m_height];\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Go through and get the height for each cel corner.\r\n\tCFeeler feeler;\r\n\tint num_heights = 0;\r\n\tint xx, zz;\r\n\tfor ( zz = min_z; zz <= max_z; zz++ )\r\n\t{\r\n\t\tfor ( xx = min_x; xx <= max_x; xx++ )\r\n\t\t{\r\n\t\t\t// The cel to fill.\r\n\t\t\tint cel = ( ( zz - min_z ) * m_width ) + ( xx - min_x );\r\n\r\n\t\t\t// The position to check.\r\n\t\t\tMth::Vector pos;\r\n\t\t\tpos[X] = (float)( xx * WEATHER_CEL_SIZE );\r\n\t\t\tpos[Y] = FEELER_START;\r\n\t\t\tpos[Z] = (float)( zz * WEATHER_CEL_SIZE );\r\n\t\t\tpos[W] = 1.0f;\r\n\r\n\t\t\tfeeler.SetStart( pos );\r\n\t\t\tpos[Y] = -FEELER_START;\r\n\t\t\tfeeler.SetEnd( pos );\r\n\r\n\t\t\t// Get the y position.\r\n\t\t\tfloat y;\r\n\t\t\tif ( feeler.GetCollision( false, false ) )\t\t// No movables, nearest collision.\r\n\t\t\t{\r\n\t\t\t\ty = feeler.GetPoint()[Y];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ty = FEELER_START;\r\n\t\t\t}\r\n\r\n\t\t\t// See if a close enough y pos already exists.\r\n\t\t\tint found = -1;\r\n\t\t\tfor ( int lp = 0; lp < num_heights; lp++ )\r\n\t\t\t{\r\n\t\t\t\tif ( fabsf( ( m_roof_height[lp] - y ) ) < HEIGHT_TOLERANCE )\r\n\t\t\t\t{\r\n\t\t\t\t\tfound = lp;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Fill in the cel.\r\n\t\t\tif ( found != -1 )\r\n\t\t\t{\r\n\t\t\t\t// Existing height.\r\n\t\t\t\tp8[cel] = found;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// New height.\r\n\t\t\t\tp8[cel] = num_heights;\r\n\t\t\t\tm_roof_height[num_heights] = y;\r\n\t\t\t\tnum_heights++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Work out highest height for each cel.\r\n\tfor ( zz = min_z; zz <= max_z; zz++ )\r\n\t{\r\n\t\tfor ( xx = min_x; xx <= max_x; xx++ )\r\n\t\t{\r\n\t\t\t// The cel to fill.\r\n\t\t\tint cel = ( ( zz - min_z ) * m_width ) + ( xx - min_x );\r\n\t\t\tint celx = ( ( zz - min_z ) * m_width ) + ( ( xx + 1 ) - min_x );\r\n\t\t\tint celz = ( ( ( zz + 1 ) - min_z ) * m_width ) + ( xx - min_x );\r\n\t\t\tint celxz = ( ( ( zz + 1 ) - min_z ) * m_width ) + ( ( xx + 1 ) - min_x );\r\n\r\n\t\t\tif ( m_roof_height[p8[celx]] > m_roof_height[p8[cel]] ) p8[cel] = p8[celx];\r\n\t\t\tif ( m_roof_height[p8[celz]] > m_roof_height[p8[cel]] ) p8[cel] = p8[celz];\r\n\t\t\tif ( m_roof_height[p8[celxz]] > m_roof_height[p8[cel]] ) p8[cel] = p8[celxz];\r\n\t\t}\r\n\t}\r\n\r\n\t// Create a sparse array.\r\n\tmp_roof_row = (sRowEntry *)grid_bytes;\r\n\tmp_roof_height_index = (unsigned char *)&mp_roof_row[m_height];\r\n\r\n\t// 0 = offset\r\n\t// 1 = width\r\n\t// 2 = index\r\n\r\n\tunsigned short index = 0;\r\n\tfor ( zz = 0; zz <= m_height; zz++ )\r\n\t{\r\n\t\tunsigned short start = 0;\r\n\t\tunsigned short end = m_width - 1;\r\n\r\n\t\t// Scan to find the start.\r\n\t\tbool start_set = false;\r\n\t\tfor ( xx = 0; xx < m_width; xx++ )\r\n\t\t{\r\n\t\t\tint cel = ( zz * m_width ) + xx;\r\n\r\n\t\t\tif ( m_roof_height[p8[cel]] != FEELER_START )\r\n\t\t\t{\r\n\t\t\t\tif ( !start_set )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Set start value.\r\n\t\t\t\t\tstart = xx;\r\n\t\t\t\t\tstart_set = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Set end value.\r\n\t\t\t\t\tend = xx;\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Copy data & set row entry.\r\n\t\tif ( start < end )\r\n\t\t{\r\n\t\t\tmp_roof_row[zz].start = start;\r\n\t\t\tmp_roof_row[zz].end = end;\r\n\t\t\tmp_roof_row[zz].index = index;\r\n\t\t\tfor ( xx = start; xx <= end ; xx++ )\r\n\t\t\t{\r\n\t\t\t\tint cel = ( zz * m_width ) + xx;\r\n\r\n\t\t\t\tmp_roof_height_index[index] = p8[cel];\r\n\t\t\t\tindex++;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Row doesn't exist.\r\n\t\t\tmp_roof_row[zz].start = 16384;\r\n\t\t\tmp_roof_row[zz].end = 0;\r\n\t\t\tmp_roof_row[zz].index = 0;\r\n\t\t}\r\n\t}\r\n\r\n\tdelete p8;\r\n\r\n#ifndef __NOPT_FINAL__\r\n\tint new_size = ( m_height * 6 ) + index;\r\n\r\n\tprintf( \"Grid Size: Old: %d New: %d Num Heights: %d\\n\", ( m_width * m_height ), new_size, num_heights );\r\n#endif\t\t// __NOPT_FINAL__\r\n//\tprintf( \"Num Weather Grid Heights: %d (%d x %d)\\n\", num_heights, m_width, m_height );\r\n\r\n\t// Set all drip time counters to 255.\r\n\t// 255 means the drop won't be rendered.\r\n\t// Setting to anything other than 255 will mean that it will increment to 255 and stop.\r\n\tfor ( int lp = 0; lp < ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ); lp++ )\r\n\t{\r\n\t\tm_drop_time[lp] = 255;\r\n\t\tm_x_offset[lp] = Mth::Rnd( 255 );\r\n\t\tm_z_offset[lp] = Mth::Rnd( 255 );\r\n\t}\r\n\tm_active_drops = 0;\r\n\r\n\tm_seq = SEQ_START;\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CNgcTexture *p_Ngc_texture;\r\n\r\n\t// Set Rain Texture.\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( CRCD(0x45c7eb0f,\"splash\") );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_rain_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\r\n\t// Set Snow Texture.\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( CRCD(0xc97c5a4c,\"snow\") );\r\n\tp_Ngc_texture = static_cast<Nx::CNgcTexture*>( p_texture );\r\n\tif ( p_Ngc_texture )\r\n\t{\r\n\t\tmp_snow_texture = p_Ngc_texture->GetEngineTexture(); \r\n\t}\r\n\r\n\tm_system_active = true;\r\n\r\n\t// Zero out the splashes.\r\n\tfor ( int sp = 0; sp < NUM_SPLASH_ACTIVE; sp++ )\r\n\t{\r\n\t\tm_splash_current_life[sp] = 0;\r\n\t}\r\n\tm_current_splash = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcWeather::plat_process( float delta_time )\r\n{\r\n\tif ( !m_system_active ) return;\r\n\r\n\tif ( m_raining )\r\n\t{\r\n\t\t// It's raining.\r\n\t\tfloat rate = m_rain_drops_per_frame;\r\n\t\tif ( rate > (float)( ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ) / m_rain_frames ) ) rate = (float)( ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ) / m_rain_frames );\r\n\r\n\t\tfloat last = m_rain_rate;\r\n\t\tm_rain_rate += rate;\r\n\t\tint new_drops = (int)m_rain_rate - (int)last;\r\n\r\n\t\tfor ( int lp = 0; lp < new_drops; lp++ )\r\n\t\t{\r\n\t\t\t// If this cel is not inactive, we caught up with ourselves.\r\n\t\t\tif ( m_drop_time[m_seq] != 255 ) break;\r\n\r\n\t\t\t// Setup the drop.\r\n\t\t\tm_drop_time[m_seq] = ( 254 - m_rain_frames );\r\n\t\t\tm_x_offset[m_seq] = Mth::Rnd( 255 );\r\n\t\t\tm_z_offset[m_seq] = Mth::Rnd( 255 );\r\n\t\t\tm_active_drops++;\r\n\r\n\t\t\t// Calculate next sequence value. Notice hack to get entry 0 into the sequence.\r\n\t\t\tswitch ( m_seq )\r\n\t\t\t{\r\n\t\t\t\tcase SEQ_START:\r\n\t\t\t\t\tm_seq = 0;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tm_seq = SEQ_START;\r\n\t\t\t\t\t// Fall through to default case...\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tif ( m_seq & 1 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_seq = ( m_seq >> 1 ) ^ SEQ_MASK;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_seq = ( m_seq >> 1 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// It's snowing.\r\n\t\tfloat rate = m_snow_flakes_per_frame;\r\n\t\tif ( rate > (float)( ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ) / m_snow_frames ) ) rate = (float)( ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ) / m_snow_frames );\r\n\r\n\t\tfloat last = m_snow_rate;\r\n\t\tm_snow_rate += rate;\r\n\t\tint new_drops = (int)m_snow_rate - (int)last;\r\n\r\n\t\tfor ( int lp = 0; lp < new_drops; lp++ )\r\n\t\t{\r\n\t\t\t// If this cel is not inactive, we caught up with ourselves.\r\n\t\t\tif ( m_drop_time[m_seq] != 255 ) break;\r\n\r\n\t\t\t// Setup the drop.\r\n\t\t\tm_drop_time[m_seq] = ( 254 - m_snow_frames );\r\n\t\t\tm_x_offset[m_seq] = Mth::Rnd( 255 );\r\n\t\t\tm_z_offset[m_seq] = Mth::Rnd( 255 );\r\n\t\t\tm_active_drops++;\r\n\r\n\t\t\t// Calculate next sequence value. Notice hack to get entry 0 into the sequence.\r\n\t\t\tswitch ( m_seq )\r\n\t\t\t{\r\n\t\t\t\tcase SEQ_START:\r\n\t\t\t\t\tm_seq = 0;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tm_seq = SEQ_START;\r\n\t\t\t\t\t// Fall through to default case...\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tif ( m_seq & 1 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_seq = ( m_seq >> 1 ) ^ SEQ_MASK;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_seq = ( m_seq >> 1 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcWeather::plat_render_snow( float skx, float skz )\r\n{\r\n\t// Early out if no drops to draw.\r\n\tif ( !m_active_drops ) return;\r\n\r\n\t// Get skater position.\r\n\tint x = (int)( ( skx - m_min_x ) / WEATHER_CEL_SIZE );\r\n\tint z = (int)( ( skz - m_min_z ) / WEATHER_CEL_SIZE );\r\n\r\n\t// Calculate area to render.\r\n\tint sx = x - RENDER_DIST;\r\n\tint ex = x + DROP_SIZE;\t//RENDER_DIST;\r\n\tint sz = z - RENDER_DIST;\r\n\tint ez = z + DROP_SIZE;\t//RENDER_DIST;\r\n\r\n\t// Clip z values.\r\n\tif ( ez < 0 ) return;\r\n\tif ( sz > ( m_height - 1 ) ) return;\r\n\r\n//\tif ( sz < 0 ) sz = 0;\r\n//\tif ( ez > ( m_height - 1 ) ) ez = ( m_height - 1 );\r\n\r\n\tGX::UploadTexture(  mp_snow_texture->pTexelData,\r\n\t\t\t\t\t\tmp_snow_texture->ActualWidth,\r\n\t\t\t\t\t\tmp_snow_texture->ActualHeight,\r\n\t\t\t\t\t\tGX_TF_CMPR,\r\n\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\tGX_TRUE,\r\n\t\t\t\t\t\tGX_ANISO_1,\r\n\t\t\t\t\t\tGX_TEXMAP0 ); \r\n\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, mp_snow_texture->ActualWidth, mp_snow_texture->ActualHeight );\r\n\r\n\tif ( mp_snow_texture->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA )\r\n\t{\r\n\t\tGX::UploadTexture(  mp_snow_texture->pAlphaData,\r\n\t\t\t\t\t\t\tmp_snow_texture->ActualWidth,\r\n\t\t\t\t\t\t\tmp_snow_texture->ActualHeight,\r\n\t\t\t\t\t\t\tGX_TF_CMPR,\r\n\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\tGX_TRUE,\r\n\t\t\t\t\t\t\tGX_ANISO_1,\r\n\t\t\t\t\t\t\tGX_TEXMAP1 ); \r\n\t\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, mp_snow_texture->ActualWidth, mp_snow_texture->ActualHeight );\r\n\t\tGX::SetTexChanTevIndCull( 2, 1, 2, 0, GX_CULL_NONE );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGX::SetTexChanTevIndCull( 1, 1, 1, 0, GX_CULL_NONE );\r\n\t}\r\n\r\n\tGX::SetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP1, GX_COLOR0A0 );\r\n\r\n\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,\r\n\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t   GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\r\n\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_RASC, GX_CC_ZERO, \r\n\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n\r\n\tif ( mp_snow_texture->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA )\r\n\t{\r\n\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_SWAP0, GX_TEV_SWAP1 );\r\n\r\n\t\tGX::SetTevColorInOp( GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_CPREV,\r\n\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n\r\n\t}\r\n\r\n\tswitch ( m_snow_blend )\r\n\t{\r\n\t\tcase NxNgc::vBLEND_MODE_ADD:\r\n\t\tcase NxNgc::vBLEND_MODE_ADD_FIXED:\r\n\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\tbreak;\r\n\t\tcase NxNgc::vBLEND_MODE_SUBTRACT:\r\n\t\tcase NxNgc::vBLEND_MODE_SUB_FIXED:\r\n\t\t\tGX::SetBlendMode ( GX_BM_SUBTRACT, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\tbreak;\r\n\t\tcase NxNgc::vBLEND_MODE_BLEND:\r\n\t\tcase NxNgc::vBLEND_MODE_BLEND_FIXED:\r\n\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\tbreak;\r\n\t\tcase NxNgc::vBLEND_MODE_BRIGHTEN:\r\n\t\tcase NxNgc::vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\tbreak;\r\n\t\tcase NxNgc::vBLEND_MODE_MODULATE_FIXED:\r\n\t\tcase NxNgc::vBLEND_MODE_MODULATE:\r\n\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\tbreak;\r\n\t\tcase NxNgc::vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\tcase NxNgc::vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\tcase NxNgc::vBLEND_MODE_DIFFUSE:\r\n\t\tdefault:\r\n\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tGX::SetChanCtrl( GX_COLOR0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\tGX::SetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ); \r\n\t\r\n\tswitch ( m_snow_blend )\r\n\t{\r\n\t\tcase NxNgc::vBLEND_MODE_ADD_FIXED:\r\n\t\tcase NxNgc::vBLEND_MODE_SUB_FIXED:\r\n\t\tcase NxNgc::vBLEND_MODE_BLEND_FIXED:\r\n\t\tcase NxNgc::vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\tcase NxNgc::vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\t{\r\n\t\t\t\tuint8 fix = m_snow_blend_fix >= 128 ? 255 : m_snow_blend_fix * 2;\r\n\t\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){fix,fix,fix,fix} );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\tGXColor col = (GXColor){ m_snow_color.r, m_snow_color.g, m_snow_color.b, m_snow_color.a };\r\n\tGX::SetChanAmbColor( GX_COLOR0A0, col );\r\n\r\n\r\n\r\n\r\n\r\n\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\r\n\tfloat minx = m_min_x;\r\n\tfloat minz = m_min_z;\r\n//\tfloat rlength = m_rain_length;\r\n\t\r\n\t// Calculate drop height list.\r\n\tint lp;\r\n\tfloat y_off[256];\r\n\r\n\tfor ( lp = ( 254 - m_snow_frames ); lp < 256; lp++ )\r\n\t{\r\n\t\ty_off[lp] = m_snow_height - ( ( (float)( ( lp - 254 ) + m_snow_frames ) / (float)m_snow_frames ) * m_snow_height );\r\n\t}\r\n\r\n\t// Calculate xz offset list.\r\n\tfloat xz_off[256];\r\n\r\n\tfor ( lp = 0; lp < 256; lp++ )\r\n\t{\r\n\t\txz_off[lp] = ( (float)lp * (float)( WEATHER_CEL_SIZE / 2 ) ) / 255.0f;\r\n\t}\r\n\r\n\t// Calculate sine wave.\r\n\tfloat sin_off[256];\r\n\r\n\tfor ( lp = 0; lp < 256; lp++ )\r\n\t{\r\n\t\tsin_off[lp] = sinf( Mth::PI * 2.0f * ( (float)lp / 256.0f ) ) * ( WEATHER_CEL_SIZE / 2 );\r\n//\t\tsin_off[lp] = sinf( Mth::PI * 2.0f * (float)lp ) * 128.0f;\r\n\t}\r\n\r\n\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tNsMatrix*\tp_matrix\t= &NxNgc::EngineGlobals.camera;\r\n\r\n\tNsVector\tup( 0.0f, 1.0f, 0.0f );\r\n\tNsVector screen_right;\r\n\tNsVector screen_up;\r\n\tscreen_right.cross( *p_matrix->getAt(), up );\r\n\tscreen_up.cross( screen_right, *p_matrix->getAt());\r\n\r\n\tscreen_right.normalize();\r\n\tscreen_up.normalize();\r\n\t\r\n\tscreen_right.x *= m_snow_size;\r\n\tscreen_right.y *= m_snow_size;\r\n\tscreen_right.z *= m_snow_size;\r\n\r\n\tscreen_up.x *= m_snow_size;\r\n\tscreen_up.y *= m_snow_size;\r\n\tscreen_up.z *= m_snow_size;\r\n\r\n\tfor ( int lzz = sz; lzz <= ez; lzz++ )\r\n\t{\r\n\t\tint zz = ( lzz < 0 ) ? 0 : ( lzz > ( m_height - 1 ) ) ? ( m_height - 1 ) : lzz;\r\n\r\n\t\tif ( mp_roof_row[zz].start == 16384 ) continue;\r\n\r\n//\t\t// Calculate actual span to scan.\r\n//\t\tint rsx = sx > mp_roof_row[zz].start ? sx : mp_roof_row[zz].start;\r\n//\t\tint rex = ex < mp_roof_row[zz].end ? ex : mp_roof_row[zz].end;\r\n//\r\n//\t\t// Start position.\r\n//\t\tfloat vx = ( rsx * WEATHER_CEL_SIZE ) + minx;\r\n//\t\tfloat vz = ( zz * WEATHER_CEL_SIZE ) + minz;\r\n\r\n\t\tfloat vx = ( (float)sx * (float)WEATHER_CEL_SIZE ) + minx;\r\n\t\tfloat vz = ( (float)zz * (float)WEATHER_CEL_SIZE ) + minz;\r\n\r\n\t\tint cel = mp_roof_row[zz].index + ( sx - mp_roof_row[zz].start );\r\n\r\n\t\tint drop_cel_z = ( ( zz & ( DROP_SIZE - 1 ) ) << DROP_SIZE_SHIFT );\r\n\r\n//\t\tfor ( int xx = rsx; xx <= rex; xx++, cel++ )\r\n\t\tfor ( int lxx = sx; lxx <= ex; lxx++, cel++ )\r\n\t\t{\r\n\t\t\tint xx = ( lxx > mp_roof_row[zz].start ) ? ( ( lxx < mp_roof_row[zz].end ) ? lxx : mp_roof_row[zz].end ) : mp_roof_row[zz].start;\r\n\r\n\t\t\t// Get the current drop value. Skip this one if it's inactive.\r\n\t\t\tint drop_cel = drop_cel_z + ( xx & ( DROP_SIZE - 1 ) );\r\n\r\n\t\t\tvx += (float)WEATHER_CEL_SIZE;\r\n\t\t\tfloat vy = m_roof_height[mp_roof_height_index[cel]];\r\n\r\n\t\t\tfor ( int d = 0; d < DROP_LAYERS; d++, drop_cel += ( DROP_SIZE * DROP_SIZE ) )\r\n\t\t\t{\r\n\t\t\t\tif ( m_drop_time[drop_cel] == 255 ) continue;\r\n\r\n\t\t\t\t// Create the position for rendering.\r\n\t\t\t\tfloat v0x = vx + xz_off[m_x_offset[drop_cel]] + sin_off[(m_z_offset[drop_cel]+m_drop_time[drop_cel])&255];\r\n\t\t\t\tfloat v0y = vy + y_off[m_drop_time[drop_cel]] + m_snow_size;\r\n\t\t\t\tfloat v0z = vz + xz_off[m_z_offset[drop_cel]] + sin_off[(m_x_offset[drop_cel]+m_drop_time[drop_cel])&255];\r\n\r\n\t\t\t\tfloat v1x = v0x + screen_up.x;\r\n\t\t\t\tfloat v1y = v0y + screen_up.y;\r\n\t\t\t\tfloat v1z = v0z + screen_up.z;\r\n\r\n\t\t\t\tv0x -= screen_up.x;\r\n\t\t\t\tv0y -= screen_up.y;\r\n\t\t\t\tv0z -= screen_up.z;\r\n\r\n\t\t\t\t// Send coordinates.\r\n\t\t\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\t\t\t\tGXWGFifo.f32 = v1x - screen_right.x;\r\n\t\t\t\t\tGXWGFifo.f32 = v1y - screen_right.y;\r\n\t\t\t\t\tGXWGFifo.f32 = v1z - screen_right.z;\r\n\t\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\t\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\r\n\t\t\t\t\tGXWGFifo.f32 = v1x + screen_right.x;\r\n\t\t\t\t\tGXWGFifo.f32 = v1y + screen_right.y;\r\n\t\t\t\t\tGXWGFifo.f32 = v1z + screen_right.z;\r\n\t\t\t\t\tGXWGFifo.f32 = 1.0f;\r\n\t\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\r\n\t\t\t\t\tGXWGFifo.f32 = v0x + screen_right.x;\r\n\t\t\t\t\tGXWGFifo.f32 = v0y + screen_right.y;\r\n\t\t\t\t\tGXWGFifo.f32 = v0z + screen_right.z;\r\n\t\t\t\t\tGXWGFifo.f32 = 1.0f;\r\n\t\t\t\t\tGXWGFifo.f32 = 1.0f;\r\n\r\n\t\t\t\t\tGXWGFifo.f32 = v0x - screen_right.x;\r\n\t\t\t\t\tGXWGFifo.f32 = v0y - screen_right.y;\r\n\t\t\t\t\tGXWGFifo.f32 = v0z - screen_right.z;\r\n\t\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\t\t\t\t\tGXWGFifo.f32 = 1.0f;\r\n//\t\t\t\t\tGX::Position3f32( v1x - screen_right.x, v1y - screen_right.y, v1z - screen_right.z );\r\n//\t\t\t\t\tGX::Position3f32( v1x + screen_right.x, v1y + screen_right.y, v1z + screen_right.z );\r\n//\t\t\t\t\tGX::Position3f32( v0x + screen_right.x, v0y + screen_right.y, v0z + screen_right.z );\r\n//\t\t\t\t\tGX::Position3f32( v0x - screen_right.x, v0y - screen_right.y, v0z - screen_right.z );\r\n\t\t\t\tGX::End();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcWeather::plat_render_rain( float skx, float skz )\r\n{\r\n\t// Early out if no drops to draw.\r\n\tif ( !m_active_drops ) return;\r\n\r\n\t// Get skater position.\r\n\tint x = (int)( ( skx - m_min_x ) / WEATHER_CEL_SIZE );\r\n\tint z = (int)( ( skz - m_min_z ) / WEATHER_CEL_SIZE );\r\n\r\n\t// Calculate area to render.\r\n\tint sx = x - RENDER_DIST;\r\n\tint ex = x + DROP_SIZE;\t//RENDER_DIST;\r\n\tint sz = z - RENDER_DIST;\r\n\tint ez = z + DROP_SIZE;\t//RENDER_DIST;\r\n\r\n\t// Clip z values.\r\n\tif ( ez < 0 ) return;\r\n\tif ( sz > ( m_height - 1 ) ) return;\r\n\r\n//\tif ( sz < 0 ) sz = 0;\r\n//\tif ( ez > ( m_height - 1 ) ) ez = ( m_height - 1 );\r\n\r\n\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );\r\n\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\r\n\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,\r\n\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t   GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\r\n\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC,\r\n\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_ENABLE, GX_TEVPREV );\r\n\r\n\t// Set blend mode for base layer.\r\n\tswitch ( m_rain_blend )\r\n\t{\r\n\t\tcase NxNgc::vBLEND_MODE_ADD:\r\n\t\tcase NxNgc::vBLEND_MODE_ADD_FIXED:\r\n\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\tbreak;\r\n\t\tcase NxNgc::vBLEND_MODE_SUBTRACT:\r\n\t\tcase NxNgc::vBLEND_MODE_SUB_FIXED:\r\n\t\t\tGX::SetBlendMode ( GX_BM_SUBTRACT, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\tbreak;\r\n\t\tcase NxNgc::vBLEND_MODE_BLEND:\r\n\t\tcase NxNgc::vBLEND_MODE_BLEND_FIXED:\r\n\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\tbreak;\r\n\t\tcase NxNgc::vBLEND_MODE_BRIGHTEN:\r\n\t\tcase NxNgc::vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\tbreak;\r\n\t\tcase NxNgc::vBLEND_MODE_MODULATE_FIXED:\r\n\t\tcase NxNgc::vBLEND_MODE_MODULATE:\r\n\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\tbreak;\r\n\t\tcase NxNgc::vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\tcase NxNgc::vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\tcase NxNgc::vBLEND_MODE_DIFFUSE:\r\n\t\tdefault:\r\n\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\t\r\n\tswitch ( m_rain_blend )\r\n\t{\r\n\t\tcase NxNgc::vBLEND_MODE_ADD_FIXED:\r\n\t\tcase NxNgc::vBLEND_MODE_SUB_FIXED:\r\n\t\tcase NxNgc::vBLEND_MODE_BLEND_FIXED:\r\n\t\tcase NxNgc::vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\tcase NxNgc::vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\t{\r\n\t\t\t\tuint8 fix = m_rain_blend_fix >= 128 ? 255 : m_rain_blend_fix * 2;\r\n\t\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){fix,fix,fix,fix} );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\r\n\tfloat minx = m_min_x;\r\n\tfloat minz = m_min_z;\r\n\tfloat rlength = m_rain_length;\r\n\t\r\n\t// Calculate drop height list.\r\n\tint lp;\r\n\tfloat y_off[256];\r\n\r\n\tfor ( lp = ( 254 - m_rain_frames ); lp < 256; lp++ )\r\n\t{\r\n\t\ty_off[lp] = ( m_rain_height - ( (float)( ( lp - 254 ) + m_rain_frames ) / (float)m_rain_frames ) * m_rain_height );\r\n\t}\r\n\r\n\t// Calculate xz offset list.\r\n\tfloat xz_off[256];\r\n\r\n\tfor ( lp = 0; lp < 256; lp++ )\r\n\t{\r\n\t\txz_off[lp] = ( (float)lp * (float)WEATHER_CEL_SIZE ) / 255.0f;\r\n\t}\r\n\r\n\tGXColor colb = (GXColor){ m_rain_bottom_color.r, m_rain_bottom_color.g, m_rain_bottom_color.b, m_rain_bottom_color.a };\r\n\tGXColor colt = (GXColor){ m_rain_top_color.r, m_rain_top_color.g, m_rain_top_color.b, m_rain_top_color.a };\r\n\r\n\tfor ( int lzz = sz; lzz <= ez; lzz++ )\r\n\t{\r\n\t\tint zz = ( lzz < 0 ) ? 0 : ( lzz > ( m_height - 1 ) ) ? ( m_height - 1 ) : lzz;\r\n\r\n\t\tif ( mp_roof_row[zz].start == 16384 ) continue;\r\n\r\n//\t\t// Calculate actual span to scan.\r\n//\t\tint rsx = sx > mp_roof_row[zz].start ? sx : mp_roof_row[zz].start;\r\n//\t\tint rex = ex < mp_roof_row[zz].end ? ex : mp_roof_row[zz].end;\r\n//\r\n//\t\t// Start position.\r\n//\t\tfloat vx = ( rsx * WEATHER_CEL_SIZE ) + minx;\r\n//\t\tfloat vz = ( zz * WEATHER_CEL_SIZE ) + minz;\r\n\r\n\t\tfloat vx = (float)( sx << WEATHER_CEL_SIZE_SHIFT ) + minx;\r\n\t\tfloat vz = (float)( zz << WEATHER_CEL_SIZE_SHIFT ) + minz;\r\n\r\n\t\tint cel = mp_roof_row[zz].index + ( sx - mp_roof_row[zz].start );\r\n\r\n\t\tint drop_cel_z = ( ( zz & ( DROP_SIZE - 1 ) ) << DROP_SIZE_SHIFT );\r\n\r\n//\t\tfor ( int xx = rsx; xx <= rex; xx++, cel++ )\r\n\t\tfor ( int lxx = sx; lxx <= ex; lxx++, cel++ )\r\n\t\t{\r\n\t\t\tint xx = ( lxx > mp_roof_row[zz].start ) ? ( ( lxx < mp_roof_row[zz].end ) ? lxx : mp_roof_row[zz].end ) : mp_roof_row[zz].start;\r\n\r\n\t\t\t// Get the current drop value. Skip this one if it's inactive.\r\n\t\t\tint drop_cel = drop_cel_z + ( xx & ( DROP_SIZE - 1 ) );\r\n\r\n\t\t\tvx += (float)WEATHER_CEL_SIZE;\r\n\t\t\tfloat vy = m_roof_height[mp_roof_height_index[cel]];\r\n\r\n\t\t\tfor ( int d = 0; d < DROP_LAYERS; d++, drop_cel += ( DROP_SIZE * DROP_SIZE ) )\r\n\t\t\t{\r\n\t\t\t\tif ( m_drop_time[drop_cel] == 255 ) continue;\r\n\r\n\t\t\t\t// Create the position for rendering.\r\n\t\t\t\tfloat v0x = vx + xz_off[m_x_offset[drop_cel]];\r\n\t\t\t\tfloat v0y = vy + y_off[m_drop_time[drop_cel]]; \r\n\t\t\t\tfloat v0z = vz + xz_off[m_z_offset[drop_cel]];\r\n\r\n\t\t\t\tfloat v1y = v0y + rlength;\r\n\r\n\t\t\t\t// Send coordinates.\r\n\t\t\t\tGX::Begin( GX_LINES, GX_VTXFMT0, 2 ); \r\n\t\t\t\t\tGX::Position3f32( v0x, v0y, v0z );\r\n\t\t\t\t\tGX::Color1u32( *((uint32*)&colb) );\r\n\t\t\t\t\tGX::Position3f32( v0x, v1y, v0z );\r\n\t\t\t\t\tGX::Color1u32( *((uint32*)&colt) );\r\n\t\t\t\tGX::End();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcWeather::plat_render_splashes( float skx, float skz )\r\n{\r\n\t// Create a new splash if required.\r\n\tfloat last = m_splash_rate;\r\n\tm_splash_rate += m_splash_per_frame;\r\n\tint new_splashes = (int)m_splash_rate - (int)last;\r\n\r\n\tif ( new_splashes )\r\n\t{\r\n\t\tCFeeler feeler;\r\n\t\tMth::Vector pos;\r\n\r\n\t\tpos[X] = NxNgc::EngineGlobals.camera.getPosX();\t// + ( Mth::Rnd( ( WEATHER_CEL_SIZE * RENDER_DIST * 2 ) ) ) - ( WEATHER_CEL_SIZE * RENDER_DIST );\r\n\t\tpos[Y] = FEELER_START;\r\n\t\tpos[Z] = NxNgc::EngineGlobals.camera.getPosZ();\t// + ( Mth::Rnd( ( WEATHER_CEL_SIZE * RENDER_DIST * 2 ) ) ) - ( WEATHER_CEL_SIZE * RENDER_DIST ); \r\n\t\tpos[W] = 1.0f;\r\n\r\n\t\tMth::Vector dir;\r\n\t\tdir[X] = skx - NxNgc::EngineGlobals.camera.getPosX();\r\n\t\tdir[Y] = 0.0f;\r\n\t\tdir[Z] = skz - NxNgc::EngineGlobals.camera.getPosZ();\r\n\t\tdir[W] = 1.0f;\r\n\t\tdir.Normalize();\r\n\r\n\t\t// Add distance.\r\n\t\tfloat r1 = (float)Mth::Rnd( 32768 ) / 32768.0f;\r\n\t\tpos += ( dir * ( (float)WEATHER_CEL_SIZE * RENDER_DIST * r1 ) );\r\n\r\n\t\t// Add lateral.\r\n\t\tMth::Vector lat;\r\n\t\tlat[X] = dir[Z];\r\n\t\tlat[Y] = 0.0f;\r\n\t\tlat[Z] = -dir[X];\r\n\t\tlat[W] = 1.0f;\r\n\r\n\t\tfloat r2 = 1.0f - ( (float)Mth::Rnd( 32768 ) / 32768.0f );\r\n\t\tif ( m_current_splash & 1 )\r\n\t\t{\r\n\t\t\tpos += ( lat * ( (float)WEATHER_CEL_SIZE * RENDER_DIST * r1 * r2 ) );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpos += ( lat * ( (float)WEATHER_CEL_SIZE * RENDER_DIST * r1 * -r2 ) );\r\n\t\t}\r\n\r\n\t\tfeeler.SetStart( pos );\r\n\t\tpos[Y] = -FEELER_START;\r\n\t\tfeeler.SetEnd( pos );\r\n\r\n\t\t// Get the y position.\r\n\t\tfloat y;\r\n\t\tif ( feeler.GetCollision( false, false ) )\t\t// No movables, nearest collision.\r\n\t\t{\r\n\t\t\ty = feeler.GetPoint()[Y];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ty = FEELER_START;\r\n\t\t}\r\n\r\n\t\tm_splash_x[m_current_splash] = pos[X];\r\n\t\tm_splash_y[m_current_splash] = y + m_splash_size;\r\n\t\tm_splash_z[m_current_splash] = pos[Z];\r\n\t\tm_splash_current_life[m_current_splash] = m_splash_life;\r\n\r\n\t\tm_current_splash++;\r\n\t\tm_current_splash %= NUM_SPLASH_ACTIVE;\r\n\t}\r\n\t\r\n\t// Count active splashes.\r\n\tint splashes = 0;\r\n\tfor ( int spl = 0; spl < NUM_SPLASH_ACTIVE; spl++ )\r\n\t{\r\n\t\tif ( m_splash_current_life[spl] != 0 ) splashes++;\r\n\t}\r\n\r\n\tif ( splashes )\r\n\t{\r\n\t\tGX::UploadTexture(  mp_rain_texture->pTexelData,\r\n\t\t\t\t\t\t\tmp_rain_texture->ActualWidth,\r\n\t\t\t\t\t\t\tmp_rain_texture->ActualHeight,\r\n\t\t\t\t\t\t\tGX_TF_CMPR,\r\n\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\tGX_TRUE,\r\n\t\t\t\t\t\t\tGX_ANISO_1,\r\n\t\t\t\t\t\t\tGX_TEXMAP0 ); \r\n\t\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, mp_rain_texture->ActualWidth, mp_rain_texture->ActualHeight );\r\n\r\n\t\tif ( mp_rain_texture->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA )\r\n\t\t{\r\n\t\t\tGX::UploadTexture(  mp_rain_texture->pAlphaData,\r\n\t\t\t\t\t\t\t\tmp_rain_texture->ActualWidth,\r\n\t\t\t\t\t\t\t\tmp_rain_texture->ActualHeight,\r\n\t\t\t\t\t\t\t\tGX_TF_CMPR,\r\n\t\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\t\tGX_CLAMP,\r\n\t\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\t\tGX_TRUE,\r\n\t\t\t\t\t\t\t\tGX_ANISO_1,\r\n\t\t\t\t\t\t\t\tGX_TEXMAP1 ); \r\n\t\t\tGX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, mp_rain_texture->ActualWidth, mp_rain_texture->ActualHeight );\r\n\t\t\tGX::SetTexChanTevIndCull( 2, 1, 2, 0, GX_CULL_NONE );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tGX::SetTexChanTevIndCull( 1, 1, 1, 0, GX_CULL_NONE );\r\n\t\t}\r\n\r\n\t\tGX::SetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP1, GX_COLOR0A0 );\r\n\r\n\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\r\n\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_RASC, GX_CC_ZERO, \r\n\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n\r\n\t\tif ( mp_rain_texture->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA )\r\n\t\t{\r\n\t\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_SWAP0, GX_TEV_SWAP1 );\r\n\r\n\t\t\tGX::SetTevColorInOp( GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_CPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n\r\n\t\t}\r\n\r\n\t\tswitch ( m_splash_blend )\r\n\t\t{\r\n\t\t\tcase NxNgc::vBLEND_MODE_ADD:\r\n\t\t\tcase NxNgc::vBLEND_MODE_ADD_FIXED:\r\n\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase NxNgc::vBLEND_MODE_SUBTRACT:\r\n\t\t\tcase NxNgc::vBLEND_MODE_SUB_FIXED:\r\n\t\t\t\tGX::SetBlendMode ( GX_BM_SUBTRACT, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase NxNgc::vBLEND_MODE_BLEND:\r\n\t\t\tcase NxNgc::vBLEND_MODE_BLEND_FIXED:\r\n\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase NxNgc::vBLEND_MODE_BRIGHTEN:\r\n\t\t\tcase NxNgc::vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase NxNgc::vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\tcase NxNgc::vBLEND_MODE_MODULATE:\r\n\t\t\t\tGX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase NxNgc::vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\t\tcase NxNgc::vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\t\tcase NxNgc::vBLEND_MODE_DIFFUSE:\r\n\t\t\tdefault:\r\n\t\t\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n//\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\t\tGX::SetChanCtrl( GX_COLOR0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\t\tGX::SetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ); \r\n\r\n\t\tswitch ( m_splash_blend )\r\n\t\t{\r\n\t\t\tcase NxNgc::vBLEND_MODE_ADD_FIXED:\r\n\t\t\tcase NxNgc::vBLEND_MODE_SUB_FIXED:\r\n\t\t\tcase NxNgc::vBLEND_MODE_BLEND_FIXED:\r\n\t\t\tcase NxNgc::vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\tcase NxNgc::vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\t\t{\r\n\t\t\t\t\tuint8 fix = m_splash_blend_fix >= 128 ? 255 : m_splash_blend_fix * 2;\r\n\t\t\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){fix,fix,fix,fix} );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tGXColor col = (GXColor){ m_splash_color.r, m_splash_color.g, m_splash_color.b, m_splash_color.a };\r\n\t\tGX::SetChanAmbColor( GX_COLOR0A0, col );\r\n\r\n\r\n\r\n\r\n\r\n\t\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\t\tNsMatrix*\tp_matrix\t= &NxNgc::EngineGlobals.camera;\r\n\r\n\t\tNsVector\tup( 0.0f, 1.0f, 0.0f );\r\n\t\tNsVector screen_right;\r\n\t\tNsVector screen_up;\r\n\t\tscreen_right.cross( *p_matrix->getAt(), up );\r\n\t\tscreen_up.cross( screen_right, *p_matrix->getAt());\r\n\r\n\t\tscreen_right.normalize();\r\n\t\tscreen_up.normalize();\r\n\r\n\t\tscreen_right.x *= m_splash_size;\r\n\t\tscreen_right.y *= m_splash_size;\r\n\t\tscreen_right.z *= m_splash_size;\r\n\r\n\t\tscreen_up.x *= m_splash_size;\r\n\t\tscreen_up.y *= m_splash_size;\r\n\t\tscreen_up.z *= m_splash_size;\r\n\r\n\t\t// Render the splashes.\r\n\t//\tint u = mp_rain_texture->GetWidth() << 4;\r\n\t//\tint v = mp_rain_texture->GetHeight() << 4;\r\n\t//\tuint32 col = *((uint32 *)&m_splash_color); \r\n\r\n\t\tfor ( int spl = 0; spl < NUM_SPLASH_ACTIVE; spl++ )\r\n\t\t{\r\n\t\t\tif ( m_splash_current_life[spl] == 0 ) continue;\r\n\r\n\t\t\t// Interpolate color.\r\n\t\t\tGXColor\ticol;\r\n\t\t\ticol.r = (uint8)( ( (int)m_splash_color.r * m_splash_current_life[spl] ) / m_splash_life );\r\n\t\t\ticol.g = (uint8)( ( (int)m_splash_color.g * m_splash_current_life[spl] ) / m_splash_life );\r\n\t\t\ticol.b = (uint8)( ( (int)m_splash_color.b * m_splash_current_life[spl] ) / m_splash_life );\r\n\t\t\ticol.a = (uint8)( ( (int)m_splash_color.a * m_splash_current_life[spl] ) / m_splash_life );\r\n\r\n\t\t\tfloat v0x = m_splash_x[spl] - screen_up.x;\r\n\t\t\tfloat v0y = m_splash_y[spl] - screen_up.y;\r\n\t\t\tfloat v0z = m_splash_z[spl] - screen_up.z;\r\n\r\n\t\t\tfloat v1x = m_splash_x[spl] + screen_up.x; \r\n\t\t\tfloat v1y = m_splash_y[spl] + screen_up.y; \r\n\t\t\tfloat v1z = m_splash_z[spl] + screen_up.z; \r\n\r\n\t\t\t// Draw splashes...\r\n\t\t\tGX::SetChanMatColor( GX_COLOR0A0, icol );\r\n\t\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\t\t\tGXWGFifo.f32 = v1x - screen_right.x;\r\n\t\t\t\tGXWGFifo.f32 = v1y - screen_right.y;\r\n\t\t\t\tGXWGFifo.f32 = v1z - screen_right.z;\r\n\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\t\r\n\t\t\t\tGXWGFifo.f32 = v1x + screen_right.x;\r\n\t\t\t\tGXWGFifo.f32 = v1y + screen_right.y;\r\n\t\t\t\tGXWGFifo.f32 = v1z + screen_right.z;\r\n\t\t\t\tGXWGFifo.f32 = 1.0f;\r\n\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\t\r\n\t\t\t\tGXWGFifo.f32 = v0x + screen_right.x;\r\n\t\t\t\tGXWGFifo.f32 = v0y + screen_right.y;\r\n\t\t\t\tGXWGFifo.f32 = v0z + screen_right.z;\r\n\t\t\t\tGXWGFifo.f32 = 1.0f;\r\n\t\t\t\tGXWGFifo.f32 = 1.0f;\r\n\t\r\n\t\t\t\tGXWGFifo.f32 = v0x - screen_right.x;\r\n\t\t\t\tGXWGFifo.f32 = v0y - screen_right.y;\r\n\t\t\t\tGXWGFifo.f32 = v0z - screen_right.z;\r\n\t\t\t\tGXWGFifo.f32 = 0.0f;\r\n\t\t\t\tGXWGFifo.f32 = 1.0f;\r\n\t\t\tGX::End();\r\n\r\n\t\t\tm_splash_current_life[spl]--;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CNgcWeather::plat_render( void )\r\n{\r\n\tif ( !m_system_active ) return;\r\n\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = pSkate->GetSkater(0);\r\n\r\n\tfloat skx = pSkater->m_pos[X];\r\n\tfloat skz = pSkater->m_pos[Z];\r\n\r\n\tGX::LoadPosMtxImm( (MtxPtr)&NxNgc::EngineGlobals.world_to_camera, GX_PNMTX0 );\r\n\tGX::SetZMode( GX_TRUE, GX_LEQUAL, GX_FALSE );\r\n\r\n\tif ( m_raining )\r\n\t{\r\n\t\tplat_render_splashes( skx, skz );\r\n\t\tplat_render_rain( skx, skz );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tplat_render_snow( skx, skz );\r\n\t}\r\n\r\n\t// Increment rain drop/snow flake positions.\r\n\tif ( m_active_drops )\r\n\t{\r\n\t\tfor ( int lp = 0; lp < ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ); lp++ )\r\n\t\t{\r\n\t\t\tswitch ( m_drop_time[lp] )\r\n\t\t\t{\r\n\t\t\t\tcase 255:\r\n\t\t\t\t\t// Inactive.\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 254:\r\n\t\t\t\t\t// About to become inactive, so decrement active drops.\r\n\t\t\t\t\tm_active_drops--;\r\n\t\t\t\t\t// Deliberately falls through...\r\n\t\t\t\tdefault:\r\n\t\t\t\t\t// Increment time.\r\n\t\t\t\t\tm_drop_time[lp]++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcWeather::plat_set_rain_blend_mode( uint32 blendmode_checksum, int fix )\r\n{\r\n\tm_rain_blend = get_texture_blend( blendmode_checksum );\r\n\tm_rain_blend_fix = fix;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcWeather::plat_set_splash_blend_mode( uint32 blendmode_checksum, int fix )\r\n{\r\n\tm_splash_blend = get_texture_blend( blendmode_checksum );\r\n\tm_splash_blend_fix = fix;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNgcWeather::plat_set_snow_blend_mode( uint32 blendmode_checksum, int fix )\r\n{\r\n\tm_snow_blend = get_texture_blend( blendmode_checksum );\r\n\tm_snow_blend_fix = fix;\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxweather.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_WEATHER_H__\r\n#define\t__GFX_P_NX_WEATHER_H__\r\n    \r\n#include \"gfx/nxweather.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n//#define WEATHER_GRID_W 65\r\n//#define WEATHER_GRID_H 65\r\n//\r\n//#define WEATHER_CEL_W 32\r\n//#define WEATHER_CEL_H 32\r\n\r\n#define WEATHER_CEL_SIZE 128\r\n#define WEATHER_CEL_SIZE_SHIFT 7\r\n#define HEIGHT_TOLERANCE 30.0f\r\n#define DROP_SIZE 16\r\n#define DROP_SIZE_SHIFT 4\r\n#define DROP_LAYERS 4\r\n\r\n#define NUM_SPLASH_ACTIVE 32\r\n\r\ntypedef struct\r\n{\r\n\tunsigned short start;\r\n\tunsigned short end;\r\n\tunsigned short index;\r\n} sRowEntry;\r\n\r\nclass CNgcWeather : public CWeather\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCNgcWeather();\r\n\tvirtual \t\t\t\t~CNgcWeather();\r\n\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_update_grid( void );\r\n\tvoid\t\t\t\t\tplat_process( float delta_time );\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_set_rain_blend_mode( uint32 blendmode_checksum, int fix );\r\n\tvoid\t\t\t\t\tplat_set_splash_blend_mode( uint32 blendmode_checksum, int fix );\r\n\tvoid\t\t\t\t\tplat_set_snow_blend_mode( uint32 blendmode_checksum, int fix );\r\n\r\n\tvoid\t\t\t\t\tplat_render_splashes( float skx, float skz );\r\n\tvoid\t\t\t\t\tplat_render_rain( float skx, float skz );\r\n\tvoid\t\t\t\t\tplat_render_snow( float skx, float skz );\r\n\r\n\tNxNgc::sTexture *\tmp_rain_texture;\r\n\tNxNgc::sTexture *\tmp_snow_texture;\r\n\r\n\tunsigned char *\t\tmp_roof_height_index;\r\n\tsRowEntry *\t\t\tmp_roof_row;\r\n\tfloat\t\t\t\tm_roof_height[256];\r\n\tint\t\t\t\t\tm_width;\r\n\tint\t\t\t\t\tm_height;\r\n\r\n\tfloat\t\t\t\tm_min_x;\r\n\tfloat\t\t\t\tm_min_z;\r\n\r\n\tfloat\t\t\t\tm_rain_rate;\r\n\tfloat\t\t\t\tm_splash_rate;\r\n\tfloat\t\t\t\tm_snow_rate;\r\n\r\n\tMth::Vector\t\t\tm_grid_base;\r\n\r\n\tunsigned char\t\tm_drop_time[DROP_SIZE*DROP_SIZE*DROP_LAYERS];\r\n\tunsigned char\t\tm_x_offset[DROP_SIZE*DROP_SIZE*DROP_LAYERS];\r\n\tunsigned char\t\tm_z_offset[DROP_SIZE*DROP_SIZE*DROP_LAYERS];\r\n\r\n\tuint32\t\t\t\tm_seq;\r\n\r\n\tuint8\t\t\t\tm_rain_blend;\r\n\tuint8\t\t\t\tm_splash_blend;\r\n\tuint8\t\t\t\tm_snow_blend;\r\n\r\n\tuint8\t\t\t\tm_rain_blend_fix;\r\n\tuint8\t\t\t\tm_splash_blend_fix;\r\n\tuint8\t\t\t\tm_snow_blend_fix;\r\n\r\n\tfloat\t\t\t\tm_splash_x[NUM_SPLASH_ACTIVE];\r\n\tfloat\t\t\t\tm_splash_y[NUM_SPLASH_ACTIVE];\r\n\tfloat\t\t\t\tm_splash_z[NUM_SPLASH_ACTIVE];\r\n\tint\t\t\t\t\tm_splash_current_life[NUM_SPLASH_ACTIVE]; \r\n\tint\t\t\t\t\tm_current_splash;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGC/p_nxwin2D.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxWin2D.h\r\n\r\n#ifndef\t__GFX_P_NX_WIN2D_H__\r\n#define\t__GFX_P_NX_WIN2D_H__\r\n\r\n#include \t\"Gfx/NxWin2D.h\"\r\n#include \t\"Gfx/Ngc/NX/sprite.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of the CWindow2D\r\nclass\tCNgcWindow2D : public CWindow2D\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCNgcWindow2D(int x = 0, int y = 0, int width = 640, int height = 448);\r\n\t\t\t\t\t\t\t\tCNgcWindow2D(const Mth::Rect & win_rect);\r\n\tvirtual\t\t\t\t\t\t~CNgcWindow2D();\r\n\r\n//\tNxNgc::SScissorWindow *\t\tGetEngineWindow() const;\r\n\r\nprivate:\r\n\t//\r\n\tvirtual void\t\t\t\tplat_update_engine();\t\t// Update engine primitives\r\n\r\n\t// Machine specific members\r\n//\tNxNgc::SScissorWindow *\t\tmp_plat_window;\t\t\t\t// Pointer to engine window\r\n\tshort\t\t\t\t\t\tm_left, m_right, m_top, m_bottom;\r\n};\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n//inline NxNgc::SScissorWindow *\tCNgcWindow2D::GetEngineWindow() const\r\n//{\r\n//\treturn mp_plat_window;\r\n//}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/Makefile",
    "content": "\r\nTOP         = /usr/local/sce/ee\r\nLIBDIR      = $(TOP)/lib\r\nINCDIR      = $(TOP)/include\r\n\r\nTARGET      = main\r\nOBJS        = crt0.o        \\\r\n              $(TARGET).o   \\\r\n              dma.o         \\\r\n              vif.o         \\\r\n              vu.o          \\\r\n              gif.o         \\\r\n              gs.o          \\\r\n              pcrtc.o       \\\r\n              dmacalls.o    \\\r\n              mikemath.o    \\\r\n              render.o      \\\r\n              import.o      \\\r\n              texture.o     \\\r\n              material.o    \\\r\n              mesh.o        \\\r\n              nx_init.o     \\\r\n              line.o        \\\r\n              chars.o       \\\r\n              microcode.o   \\\r\n              /skate4/code/sys/file/ngps/p_filesys.o    \\\r\n              /skate4/code/core/debug/Debug.o           \\\r\n              /skate4/code/core/debug/Assert.o          \\\r\n\r\nLCFILE      = app.cmd\r\n\r\nLIBS        = $(LIBDIR)/libsn.a    \\\r\n              $(LIBDIR)/libgraph.a \\\r\n              $(LIBDIR)/libdma.a   \\\r\n              $(LIBDIR)/libdev.a   \\\r\n              $(LIBDIR)/libpad.a   \\\r\n              $(LIBDIR)/libpkt.a   \\\r\n              $(LIBDIR)/libvu0.a\r\n\r\nPREFIX      = ee\r\nAS          = $(PREFIX)-gcc\r\nCC          = $(PREFIX)-gcc\r\nLD          = $(PREFIX)-gcc\r\nDVPASM      = ps2dvpas\r\nOBJDUMP     = $(PREFIX)-objdump\r\nRUN         = ps2run -r\r\nRM          = del\r\n\r\nCFLAGS      = -O0 -g  -Wall -Werror -fno-common\r\nCXXFLAGS    = -O0 -Wall -Werror -fno-exceptions -fno-common\r\nASFLAGS     = -c -xassembler-with-cpp\r\nDVPASMFLAGS = -g -W\r\nLDFLAGS     = -Wl,-Map,$(TARGET).map -nostartfiles -L$(LIBDIR) -lm\r\nTMPFLAGS    =\r\n\r\n.SUFFIXES: .c .s .cc .dsm .vsm\r\n\r\nall: $(TARGET).elf\r\n\r\nmain.elf: $(OBJS) $(LIBS)\r\n\t$(LD) -o $@ -T $(LCFILE) $(OBJS) $(LIBS) $(LDFLAGS)\r\n\r\ncrt0.o: crt0.s\r\n\t$(AS) $(ASFLAGS) $(TMPFLAGS) -o $@ $<\r\n\r\n.s.o:\r\n\t$(AS) $(ASFLAGS) $(TMPFLAGS) -I$(INCDIR) -o $@ $<\r\n\r\n.dsm.o:\r\n\t$(DVPASM) $(DVPASMFLAGS) -I$(INCDIR) -o $@ $<\r\n\r\n.vsm.o:\r\n\t$(DVPASM) $(DVPASMFLAGS) -I$(INCDIR) -o $@ $<\r\n\r\n.cpp.o:\r\n\t$(CC) $(CFLAGS) $(TMPFLAGS) -I$(INCDIR) -I/skate4/code -I/skate4/code/core/STL \\\r\n    -I/usr/local/sce/common/include -D__PLAT_NGPS__ -c $< -o $*.o \\\r\n\r\n\r\n.cc.o:\r\n\t$(CC) $(CXXFLAGS) $(TMPFLAGS) -I$(INCDIR) -c $< -o $*.o\r\n\r\nrun: $(TARGET).elf\r\n\t$(RUN) $(TARGET).elf\r\n\r\nclean:\r\n\t$(RM) *.o\r\n\t$(RM) *.map\r\n\t$(RM) *.dis\r\n\t$(RM) *.elf\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/asmdma.dsm",
    "content": "\r\n\r\n;------------------------------------------------------------------------------------------------------------------------------------\r\n; post-process fog effect\r\n; (this will be replaced by a vu1 routine)\r\n\r\n.global FogDma\r\n.global FogPalette\r\n\r\n.align 7\t; align to multiple of 8 qwords (2^7 bytes) to give fastest dma transfer\r\nFogDma:\r\n\r\n\r\n\t\t; preswizzled 256-colour palette, 32-bit entries\r\n\r\n\r\nDMAcnt\t*\r\n\r\n\tDIRECT *\r\n\t\r\n\t\t; set registers for palette transfer to vram\r\n\t\t.quad\t0x00000000_0000000E_10000000_00000004\t\t; GifTag\t(GS_A_D,1,PACKED,0,0,0,4)\r\n\t\t.quad\t0x00000000_00000050_00013000_00000000\t\t; BITBLTBUF\t(0,0,0,0x3000,1,PSMCT32)\r\n\t\t.quad\t0x00000000_00000051_00000000_00000000\t\t; TRXPOS\t(0,0,0,0,0)\r\n\t\t.quad\t0x00000000_00000052_00000010_00000010\t\t; TRXREG\t(16,16)\r\n\t\t.quad   0x00000000_00000053_00000000_00000000\t\t; TRXDIR\t(0)\r\n\t\t\r\n\t\t; image mode giftag for palette\r\n\t\t.quad\t0x00000000_00000000_08000000_00000040\t\t; GifTag\t(0,0,IMAGE,0,0,0,64)\r\n\r\nFogPalette:\r\n\r\n\t\t; the palette itself (which is filled in at run-time)\r\n\t\t.rept\t256\r\n\t\t.int\t0\r\n\t\t.endr\r\n\r\n\r\n\r\n\t\t.quad\t0x00000000_0000000E_10AB4000_00008008\t\t; GifTag\t(GS_A_D,1,PACKED,SPRITE|TME|ABE|FST,1,1,8)\r\n\t\t.quad\t0x00000000_0000003F_00000000_00000000\t\t; TEXFLUSH\t(0)\r\n\t\t.quad\t0x00000000_00000014_00000000_00000001\t\t; TEX1_1\t(1,0,NEAREST,NEAREST,0,0,0)\r\n\t\t.quad\t0x00000000_00000008_00000000_00003F73\t\t; CLAMP_1\t(REGION_REPEAT,REPEAT,0x3F7,0,0,0)\r\n\t\t.quad\t0x00000000_00000040_01BF0000_027F0000\t\t; SCISSOR_1\t(0,447,0,639)\r\n\t\t.quad\t0x00000000_00000042_00000000_00000044\t\t; ALPHA_1\t(Cs,Cd,As,Cd,0)\r\n\t\t.quad\t0x00000000_00000047_00000000_00050000\t\t; TEST_1\t(ZGEQUAL,1,0,0,0,0,0,0)\r\n\t\t.quad\t0x00000000_0000004C_00000000_000A0000\t\t; FRAME_1\t(0,10,PSMCT32,0)\r\n\t\t.quad\t0x00000000_0000004E_00000001_010000D2\t\t; ZBUF_1\t(0xD2,PSMZ24,1)\r\n\t\t\r\n\t.EndDirect\r\n\t\r\n.EndDmaData\r\n\r\n\r\n\r\n; break screen into halves, otherwise source texture > 1024 in width\r\n; left half\r\nDMAcall *,HalfScreen\r\n\r\n\tDIRECT *\r\n\t\r\n\t\t; set up source and dest coordinate origins\r\n\t\t.quad\t0x00000000_0000000E_10AB4000_00008002\t\t; GifTag\t(GS_A_D,1,PACKED,SPRITE|TME|ABE|FST,1,1,1)\r\n\t\t.quad\t0x00000000_00000006_2006000E_A9351A40\t\t; TEX0_1\t(0x1A40,20,PSMT8,10,10,RGBA,DECAL,0x3000,PSMCT32,CSM1,0,1)\r\n\t\t.quad\t0x00000000_00000018_00000000_00001400\t\t; XYOFFSET_1(0x1400,0)\r\n\t\t\r\n\t.EndDirect\r\n\r\n.EndDmaData\r\n\r\n\r\n\r\n; right half\r\nDMAcall *,HalfScreen\r\n\r\n\tDIRECT *\r\n\t\r\n\t\t; set up source and dest coordinate origins\r\n\t\t.quad\t0x00000000_0000000E_10AB4000_00008002\t\t; GifTag\t(GS_A_D,1,PACKED,SPRITE|TME|ABE|FST,1,1,1)\r\n\t\t.quad\t0x00000000_00000006_2006000E_A9351AE0\t\t; TEX0_1\t(0x1AE0,20,PSMT8,10,10,RGBA,DECAL,0x3000,PSMCT32,CSM1,0,1)\r\n\t\t.quad\t0x00000000_00000018_00000000_00000000\t\t; XYOFFSET_1(0,0)\r\n\t\t\r\n\t.EndDirect\r\n\r\n.EndDmaData\r\n\r\n\r\n\r\n; restore and return\r\nDMAret *\r\n\r\n\tDIRECT *\r\n\t\r\n\t\t; restore any GS regs that we shouldn't have knackered\r\n\t\t.quad\t0x00000000_0000000E_10000000_00008001\t\t; GifTag\t(GS_A_D,1,PACKED,0,0,1,1)\r\n\t\t.quad\t0x00000000_00000008_00000000_00000000\t\t; CLAMP_1\t(REPEAT,REPEAT,0,0,0,0)\r\n\r\n\t.EndDirect\r\n\r\n.EndDmaData\r\n\r\n\r\n\r\n; apply fogging effect to half of the screen (left or right)\r\n\r\n.align 7\t\t; align to 8 qwords\r\nHalfScreen:\r\n\r\n; This innocent-looking piece of assembler generates 280K of dma data!\r\n; (It will eventually be replaced with a small VU1 progam that generates it on the fly, saving memory and dma bandwidth.)\r\n\r\nDMAret *\r\n\r\n\tDIRECT *\r\n\r\n.if 0\t ; Change to 1 to get the full-screen fog back, and lose 280K of memory\r\n\t\t.quad\t0x00000000_00005353_44000000_0000A300\t\t; GifTag\t(UV|XYZ2<<4|UV<<8|XYZ2<<12,4,REGLIST,0,0,1,8960)\r\n\r\n\t\t; loop over quarter-pages\t\t\r\n\t\tqpageX = 0\r\n\t\t.rept 10\r\n\r\n\t\t\t; use diagonally facing quarter-page as the source\t\t\r\n\t\t\tqpageU = (qpageX^0x200)*2+8\r\n\t\t\r\n\t\t\tqpageY = 0\r\n\t\t\t.rept 28\r\n\t\t\t\r\n\t\t\t\t; use diagonally facing quarter-page as the source\t\t\r\n\t\t\t\tqpageV = (qpageY^0x100)*2+8\r\n\t\t\t\t\r\n\t\t\t\tX = qpageX+0x1400\r\n\t\t\t\tU = qpageU\r\n\t\t\t\t.rept 4\r\n\t\t\t\t\r\n\t\t\t\t\tY = qpageY\r\n\t\t\t\t\tV = qpageV+0x20\r\n\t\t\t\t\t.rept 4\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t; even column\r\n\t\t\t\t\t\t.short U+0x40,V,0,0\r\n\t\t\t\t\t\t.short X,Y,0xFFFF,0x0080\r\n\t\t\t\t\t\t.short U+0xC0,V+0x20,0,0\r\n\t\t\t\t\t\t.short X+0x80,Y+0x20,0xFFFF,0x0080\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t; odd column\r\n\t\t\t\t\t\t.short U,V+0x40,0,0\r\n\t\t\t\t\t\t.short X,Y+0x20,0xFFFF,0x0080\r\n\t\t\t\t\t\t.short U+0x80,V+0x60,0,0\r\n\t\t\t\t\t\t.short X+0x80,Y+0x40,0xFFFF,0x0080\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tY = Y+0x40\r\n\t\t\t\t\t\tV = V+0x80\r\n\t\t\t\t\t.endr\r\n\t\t\t\t\r\n\t\t\t\t\tX = X+0x80\r\n\t\t\t\t\tU = U+0x100\r\n\t\t\t\t.endr\r\n\t\t\r\n\t\t\t\tqpageY = qpageY+0x100\r\n\t\t\t.endr\r\n\t\t\r\n\t\t\tqpageX = qpageX+0x200\r\n\t\t.endr\r\n.else\r\n; Mick:  Just bunged in something to make it not crash\r\n\t\t.quad\t0x00000000_0000000E_10000000_00008001\t\t; GifTag\t(GS_A_D,1,PACKED,0,0,1,1)\r\n\t\t.quad\t0x00000000_00000008_00000000_00000000\t\t; CLAMP_1\t(REPEAT,REPEAT,0,0,0,0)\r\n.endif\r\n\t\r\n\t.EndDirect\r\n\r\n.EndDmaData\r\n\r\n;------------------------------------------------------------------------------------------------------------------------------------\r\n\r\n.if 0\r\n\r\n; BILLBOARD TEST\r\n\r\n.global BillboardDma\r\n.global BillboardContext\r\n.global BillboardMats\r\n\r\n.align 4\r\nBillboardDma:\r\nDMAret *\r\n\r\n\tUNPACK\t1, 1, V4_32, 0, *\r\n\t\r\n\t; VU context... 32\r\n\t.quad\t0x0000000C_0000000F_10000020_3400000C\r\nBillboardContext:\r\n\t.quad\t0,0,0,0\r\nBillboardMats:\r\n\t.quad\t0,0,0,0\t\t\t\t\t\t\t\t\t; world to camera matrix\r\n\t.quad\t0,0,0,0\t\t\t\t\t\t\t\t\t; camera to screen matrix\r\n\t\r\n\t; axial billboards... 86\r\n\t.quad\t0x00000024_00000512_300E4056_35C0000C\r\n\t\r\n\t.float\t0,0,1,0\t\t\t\t\t\t\t\t\t; stq0\r\n\t.int\t90,45,15,128\t\t\t\t\t\t\t; rgba0\r\n\t.float\t0,100,0,0\t\t\t\t\t\t\t\t; xyz\r\n\t.float\t1,0,1,0\t\t\t\t\t\t\t\t\t; stq1\r\n\t.int\t30,15,5,128\t\t\t\t\t\t\t\t; rgba1\r\n\t.float\t10,100,0,0\t\t\t\t\t\t\t\t; w/2,h/2\r\n\t.float\t0,1,1,0\t\t\t\t\t\t\t\t\t; stq2\r\n\t.int\t90,45,15,128\t\t\t\t\t\t\t; rgba2\r\n\t.float\t0,0,0,0\t\t\t\t\t\t\t\t\t; tx,ty,tz\r\n\t.float\t1,1,1,0\t\t\t\t\t\t\t\t\t; stq3\r\n\t.int\t30,15,5,128\t\t\t\t\t\t\t\t; rgba3\r\n\t.float\t0,1,0,0\t\t\t\t\t\t\t\t\t; axis\r\n\t\r\n\t.float\t0,0,1,0\t\t\t\t\t\t\t\t\t; stq0\r\n\t.int\t90,45,15,128\t\t\t\t\t\t\t; rgba0\r\n\t.float\t70.71,270.71,0,0\t\t\t\t\t\t; xyz\r\n\t.float\t1,0,1,0\t\t\t\t\t\t\t\t\t; stq1\r\n\t.int\t30,15,5,128\t\t\t\t\t\t\t\t; rgba1\r\n\t.float\t10,100,0,0\t\t\t\t\t\t\t\t; w/2,h/2\r\n\t.float\t0,1,1,0\t\t\t\t\t\t\t\t\t; stq2\r\n\t.int\t90,45,15,128\t\t\t\t\t\t\t; rgba2\r\n\t.float\t0,0,0,0\t\t\t\t\t\t\t\t\t; tx,ty,tz\r\n\t.float\t1,1,1,0\t\t\t\t\t\t\t\t\t; stq3\r\n\t.int\t30,15,5,128\t\t\t\t\t\t\t\t; rgba3\r\n\t.float\t0.7071,0.7071,0,0\t\t\t\t\t\t; axis\r\n\t\r\n\t.float\t0,0,1,0\t\t\t\t\t\t\t\t\t; stq0\r\n\t.int\t90,45,15,128\t\t\t\t\t\t\t; rgba0\r\n\t.float\t-70.71,270.71,0,0\t\t\t\t\t\t; xyz\r\n\t.float\t1,0,1,0\t\t\t\t\t\t\t\t\t; stq1\r\n\t.int\t30,15,5,128\t\t\t\t\t\t\t\t; rgba1\r\n\t.float\t10,100,0,0\t\t\t\t\t\t\t\t; w/2,h/2\r\n\t.float\t0,1,1,0\t\t\t\t\t\t\t\t\t; stq2\r\n\t.int\t90,45,15,128\t\t\t\t\t\t\t; rgba2\r\n\t.float\t0,0,0,0\t\t\t\t\t\t\t\t\t; tx,ty,tz\r\n\t.float\t1,1,1,0\t\t\t\t\t\t\t\t\t; stq3\r\n\t.int\t30,15,5,128\t\t\t\t\t\t\t\t; rgba3\r\n\t.float\t-0.7071,0.7071,0,0\t\t\t\t\t\t; axis\r\n\t\r\n\t; screen-aligned billboards... 84\r\n\t.quad\t0x00000018_00000512_302E4054_35C08008\r\n\t\r\n\t.float\t0,0,1,0\t\t\t\t\t\t\t\t\t; stq0\r\n\t.int\t0,100,0,64\t\t\t\t\t\t\t\t; rgba0\r\n\t.float\t141.42,341.42,0,0\t\t\t\t\t\t; xyz\r\n\t.float\t1,0,1,0\t\t\t\t\t\t\t\t\t; stq1\r\n\t.int\t0,100,0,64\t\t\t\t\t\t\t\t; rgba1\r\n\t.float\t60,60,0,0\t\t\t\t\t\t\t\t; w/2,h/2\r\n\t.float\t0,1,1,0\t\t\t\t\t\t\t\t\t; stq2\r\n\t.int\t0,100,0,64\t\t\t\t\t\t\t\t; rgba2\r\n\t.float\t0,0,10,0\t\t\t\t\t\t\t\t; tx,ty,tz\r\n\t.float\t1,1,1,0\t\t\t\t\t\t\t\t\t; stq3\r\n\t.int\t0,100,0,64\t\t\t\t\t\t\t\t; rgba3\r\n\t.float\t0,0,0,0\t\t\t\t\t\t\t\t\t; axis\r\n\t\r\n\t.float\t0,0,1,0\t\t\t\t\t\t\t\t\t; stq0\r\n\t.int\t0,100,0,64\t\t\t\t\t\t\t\t; rgba0\r\n\t.float\t-141.42,341.42,0,0\t\t\t\t\t\t; xyz\r\n\t.float\t1,0,1,0\t\t\t\t\t\t\t\t\t; stq1\r\n\t.int\t0,100,0,64\t\t\t\t\t\t\t\t; rgba1\r\n\t.float\t60,60,0,0\t\t\t\t\t\t\t\t; w/2,h/2\r\n\t.float\t0,1,1,0\t\t\t\t\t\t\t\t\t; stq2\r\n\t.int\t0,100,0,64\t\t\t\t\t\t\t\t; rgba2\r\n\t.float\t0,0,10,0\t\t\t\t\t\t\t\t; tx,ty,tz\r\n\t.float\t1,1,1,0\t\t\t\t\t\t\t\t\t; stq3\r\n\t.int\t0,100,0,64\t\t\t\t\t\t\t\t; rgba3\r\n\t.float\t0,0,0,0\t\t\t\t\t\t\t\t\t; axis\r\n\t.EndUnpack\r\n\r\n.EndDmaData\r\n\r\n.endif\r\n\r\n;------------------------------------------------------------------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/asmdma.h",
    "content": "#ifndef __ASMDMA_H\r\n#define __ASMDMA_H\r\n\r\nextern uint32 FogPalette[256];\r\nextern uint   FogDma;\r\n\r\nextern uint BillboardDma;\r\nextern uint BillboardContext;\r\nextern uint BillboardMats;\r\n\r\n#endif //__ASMDMA_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/chars.cpp",
    "content": "#include <string.h>\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <core/string/stringutils.h>\r\n#include <sys/file/filesys.h>\r\n#include <sifdev.h>\r\n#include <stdlib.h>\r\n#include <gfx/nxfontman.h>\r\n#include \"chars.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n#include \"vu1code.h\"\r\n#include \"texturemem.h\"\r\n#include \"render.h\"\r\n#include \"switches.h\"\r\n\r\n/*\r\n\r\n\r\n\t\r\n.fnt file format (by Ryan)\r\n--------------------------\r\n\r\n\t4\tFile size in bytes\r\n\t4\tNumber of characters\r\n\t4\tDefault height\r\n\t4\tDefault base\r\n\t\r\n\t?\tCharacter table (see below)\r\n\t?\tTexture (see below)\r\n\r\n\tCharacter\r\n\t2\tBaseline (how many pixels down relative to top of image)\r\n\t2\tAscii value\r\n\r\n\tTexture\r\n\t4\tSize of texture\r\n\t2\tWidth\r\n\t2\tHeight\r\n\t2\tBit depth\r\n\t6\tPadding\r\n\tW*H\tRaw data\r\n\t0-3\tPadding for uint32 alignment\r\n\t1K\tPalette data\r\n\t4\tNumber of subtextures\r\n\t?\tSubtexture table (see below)\r\n\r\n\tSubtexture\r\n\t2\tX\r\n\t2\tY\r\n\t2\tW\r\n\t2\tH\r\n\r\n\t\r\n\t\r\n\t\r\nfont->vram upload format\r\n------------------------\r\n\r\n\r\n\tGIFtag PACKED 4\r\n\tBITBLTBUF ?\r\n\tTRXPOS 0\r\n\tTRXREG w,h\r\n\tTRXDIR 0\r\n\t\r\n\tGIFtag IMAGE (w*h+15)/16\r\n\t... (tex data)\r\n\t\r\n\tGIFtag PACKED 4\r\n\tBITBLTBUF ?\r\n\tTRXPOS 0\r\n\tTRXREG w,h\r\n\tTRXDIR 0\r\n\t\r\n\tGIFtag IMAGE 64\r\n\t... (clut data)\r\n\t\r\n\t\r\n\t\r\n\ttotal size in bytes = 12*16+((w*h+15)/16)*16+1024 = 1216+((w*h+15)/16)*16\r\n\t\r\n\tthis will be referenced as follows:\r\n\t\r\n\tdma ref\r\n\tNOP\r\n\tDIRECT 76+(w*h+15)/16\r\n\t\r\n\t\r\n*/\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\nfloat CurrentScale;\r\nuint32 FontVramStart;\r\nuint32 FontVramBase;\r\nSFont *pFontList;\r\nSFont *pButtonsFont = NULL;\r\n\r\n\r\n// Garrett: Now uses both 648K buffers at once, so we'd need to undo this if we want to\r\n// implement double buffering.\r\nconst uint32 FontVramSize = 0xA20 * 2;\t// 648K * 2\r\n\r\nextern TextureMemoryLayout TexMemLayout;\r\n\r\nSFont *SText::spOverrideFont = NULL;\r\n\r\nvoid * OpenExtended(const char *Filename)\r\n{\r\n\tchar *ExtendedFilename;\r\n\r\n\t// allocate memory for extended name\r\n\tExtendedFilename = (char *)Mem::Malloc(strlen(Filename)+17);\t// 12 for \"fonts/\" plus 4 for \".fnt\" plus 1 for \\0\r\n\tDbg_MsgAssert(ExtendedFilename, (\"couldn't malloc memory for extended filename fonts/%s\", Filename));\r\n\r\n\t// copy and extend name\r\n\tstrcpy(ExtendedFilename, \"fonts/\");\r\n\tstrcat(ExtendedFilename, Filename);\r\n\tstrcat(ExtendedFilename, \".fnt.ps2\");\r\n\r\n\t// open file\r\n\tvoid *pFile = File::Open(ExtendedFilename, \"rb\");\r\n\tDbg_MsgAssert(pFile>=0, (\"couldn't open file %s\", Filename));\r\n\r\n\t// free memory\r\n\tMem::Free(ExtendedFilename);\r\n\r\n\treturn pFile;\r\n}\r\n\r\n\r\n\r\n\r\n\r\nSFont * LoadFont(const char *Filename)\r\n{\r\n\tSFont *pFont;\r\n\tSChar *pChar;\r\n\tuint8 *pData;\r\n\tvoid *pFile;\r\n\tint i,j,Len,NumChars,Width,Height,NumQWords,NumBytes;\r\n\tuint32 TW,TH,TBW;\r\n\tuint32 temp;\r\n\r\n\t\t  \r\n\tuint8*\told_dma_loc = dma::pLoc;\t\t  \r\n\r\n\t// open the font file\r\n\tpFile = OpenExtended(Filename);\r\n\r\n\r\n\t// allocate memory for the font structure\r\n\tpFont = (SFont *)Mem::Malloc(sizeof(SFont));\r\n\tDbg_MsgAssert(pFont, (\"couldn't malloc memory for SFont\"));\r\n\r\n\r\n\t// allocate a temporary buffer\r\n\tuint8 FontBuf[2048];\r\n\tDbg_MsgAssert(FontBuf, (\"couldn't malloc memory for FontBuf\"));\r\n\r\n\r\n\t// load file header\r\n\tLen = File::Read(FontBuf, 1, 16, pFile);\r\n\tDbg_MsgAssert(Len==16, (\"couldn't read file header from font file %s\", Filename));\r\n\tNumChars\t\t\t = ((uint32 *)FontBuf)[1];\r\n\tpFont->DefaultHeight = ((uint32 *)FontBuf)[2] << 4;\t\t// *16 for texel coords\r\n\tpFont->DefaultBase\t = ((uint32 *)FontBuf)[3] << 4;\t\t// *16 for texel coords\r\n\r\n\r\n\t// clear character map to zero\r\n\tmemset(pFont->Map, 0, 256);\r\n\tmemset(pFont->SpecialMap, 0, 32);\r\n\r\n\r\n\t// allocate memory for character table\r\n\tpFont->pChars = (SChar *)Mem::Malloc(NumChars*sizeof(SChar));\r\n\tDbg_MsgAssert(pFont->pChars, (\"couldn't malloc memory for font character table\"));\r\n\r\n\r\n\t// load character map and character table\r\n\tLen = File::Read(FontBuf, 1, NumChars<<2, pFile);\r\n\tDbg_MsgAssert(Len==(NumChars<<2), (\"couldn't read character table in font file %s\", Filename));\r\n\r\n\tfor (i=0,pChar=pFont->pChars,pData=FontBuf; i<NumChars; i++,pChar++,pData+=4)\r\n\t{\r\n\t\tpChar->Baseline = ((uint16 *)pData)[0] << 4;\t\t// *16 for texel coords\r\n\t\tsint16 ascii_val = ((sint16 *)pData)[1];\r\n\t\tif (ascii_val >= 0)\r\n\t\t\tpFont->Map[(uint8) ascii_val] = i;\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Assert(ascii_val >= -32)\r\n\t\t\tpFont->SpecialMap[(uint8) (-ascii_val - 1)] = i;\r\n\t\t}\r\n\t}\r\n\r\n\t// now, if there is a null character in the font, make characters that could not be found\r\n\t// in the font display that instead of 'A'\r\n\tif (pFont->SpecialMap[31] != 0)\r\n\t{\r\n\t\tfor (i = 0; i < 256; i++) \r\n\t\t{\r\n\t\t\tif (pFont->Map[i] == 0 && i != 'A' && i != 'a') pFont->Map[i] = pFont->SpecialMap[31];\r\n\t\t\tif (i < 31 && pFont->SpecialMap[i] == 0) pFont->SpecialMap[i] = pFont->SpecialMap[31];\r\n\t\t}\r\n\t}\t\r\n\t\r\n\t// load texture header\r\n\tLen = File::Read(FontBuf, 1, 16, pFile);\r\n\tDbg_MsgAssert(Len==16, (\"couldn't read texture header from font file %s\", Filename));\r\n\tWidth  = ((uint16 *)FontBuf)[2];\r\n\tHeight = ((uint16 *)FontBuf)[3];\r\n\r\n\r\n\t// allocate memory for vif stream\r\n\tpFont->VifSize = 1216 + (((Width*Height+15)>>4)<<4);\r\n\tpFont->pVifData = (uint8 *)Mem::Malloc(pFont->VifSize);\r\n\tDbg_MsgAssert(pFont->pVifData, (\"couldn't malloc memory for vif data\"));\r\n\tDbg_MsgAssert(((uint32)pFont->pVifData & 15) == 0, (\"vif data not qword aligned\"));\r\n\r\n\r\n\r\n\t// build dma data in this buffer\r\n\tdma::pLoc = pFont->pVifData;\r\n\r\n\t// Calculate memory needed\r\n\tint min_width = Width, min_height = Height;\r\n\tTexMemLayout.getMinSize(min_width, min_height, PSMT8);\r\n\tpFont->m_NumTexVramBlocks = TexMemLayout.getImageSize(min_width, min_height, PSMT8);\r\n\tpFont->m_NumClutVramBlocks = 4;\r\n\r\n\r\n\t// set base pointers and texture buffer width\r\n\tpFont->m_CBP = FontVramBase;\r\n\tpFont->m_TBP = FontVramBase + pFont->m_NumClutVramBlocks;\r\n\tTBW = (Width+63) >> 6;\r\n\tif (TBW<2)\r\n\t\tTBW=2;\r\n\r\n\r\n\t// texture upload format:\r\n\t//\r\n\t// GIFtag PACKED 4\r\n\t// BITBLTBUF ?\r\n\t// TRXPOS 0\r\n\t// TRXREG w,h\r\n\t// TRXDIR 0\r\n\t//\r\n\t// GIFtag IMAGE (w*h+15)/16\r\n\t// ... (tex data)\r\n\r\n\t// texture upload header\r\n\tNumQWords = (Width*Height+15)>>4;\r\n\tgif::Tag2(gs::A_D,1,PACKED,0,0,0,4);\r\n\tpFont->mp_TexBitBltBuf = gs::Reg2_pData(gs::BITBLTBUF,PackBITBLTBUF(0,0,0,pFont->m_TBP,TBW,PSMT8));\r\n\tgs::Reg2(gs::TRXPOS,\tPackTRXPOS(0,0,0,0,0));\r\n\tgs::Reg2(gs::TRXREG,\tPackTRXREG(Width,Height));\r\n\tgs::Reg2(gs::TRXDIR,\t0);\r\n\tgif::Tag2(0, 0, IMAGE, 0, 0, 0, NumQWords);\r\n\r\n\t// read texture bitmap data\r\n\tNumBytes = (Width*Height+3)&0xFFFFFFFC;\r\n\tLen = File::Read(dma::pLoc, 1, NumBytes, pFile);\r\n\tDbg_MsgAssert(Len==NumBytes, (\"couldn't read texture bitmap from font file %s\", Filename));\r\n\tdma::pLoc += NumQWords<<4;\r\n\r\n\r\n\t// clut upload format:\r\n\t//\r\n\t// GIFtag PACKED 4\r\n\t// BITBLTBUF ?\r\n\t// TRXPOS 0\r\n\t// TRXREG w,h\r\n\t// TRXDIR 0\r\n\t//\r\n\t// GIFtag IMAGE 64\r\n\t// ... (clut data)\r\n\r\n\t// clut upload header\r\n\tgif::Tag2(gs::A_D,1,PACKED,0,0,0,4);\r\n\tpFont->mp_ClutBitBltBuf = gs::Reg2_pData(gs::BITBLTBUF,PackBITBLTBUF(0,0,0,pFont->m_CBP,1,PSMCT32));\r\n\tgs::Reg2(gs::TRXPOS,\tPackTRXPOS(0,0,0,0,0));\r\n\tgs::Reg2(gs::TRXREG,\tPackTRXREG(16,16));\r\n\tgs::Reg2(gs::TRXDIR,\t0);\r\n\tgif::Tag2(0,0,IMAGE,0,0,0,64);\r\n\r\n\t// read clut bitmap data\r\n\tLen = File::Read(dma::pLoc, 1, 1024, pFile);\r\n\tDbg_MsgAssert(Len==1024, (\"couldn't read clut bitmap from font file %s\", Filename));\r\n\t\r\n\t// swizzle the clut data\r\n\tfor (i=0; i<256; i+=32)\r\n\t\tfor (j=0; j<8; j++)\r\n\t\t{\r\n\t\t\ttemp = ((uint32 *)dma::pLoc)[i+j+8];\r\n\t\t\t((uint32 *)dma::pLoc)[i+j+8] = ((uint32 *)dma::pLoc)[i+j+16];\r\n\t\t\t((uint32 *)dma::pLoc)[i+j+16] = temp;\r\n\t\t}\r\n\t\r\n\t// step dma location\r\n\tdma::pLoc += 1024;\r\n\r\n\r\n\t// skip numsubtextures, and load subtextures\r\n\tLen = File::Read(FontBuf, 1, (NumChars<<3)+4, pFile);\r\n\tDbg_MsgAssert(Len==(NumChars<<3)+4, (\"couldn't read subtexture table from font file %s\", Filename));\r\n\tfor (i=0,pChar=pFont->pChars,pData=FontBuf+4; i<NumChars; i++,pChar++,pData+=8)\r\n\t{\r\n\t\tpChar->u0 = (((uint16 *)pData)[0] << 4) + 8;\r\n\t\tpChar->v0 = (((uint16 *)pData)[1] << 4) + 8;\r\n\t\tpChar->u1 = pChar->u0 + (((uint16 *)pData)[2] << 4);\r\n\t\tpChar->v1 = pChar->v0 + (((uint16 *)pData)[3] << 4);\r\n\t}\r\n\r\n\t// set font GS context\r\n\tfor (TW=0; (1<<TW)<Width; TW++)\r\n\t\t;\r\n\tfor (TH=0; (1<<TH)<Height; TH++)\r\n\t\t;\r\n\tpFont->RegTEX0 = PackTEX0(pFont->m_TBP,TBW,PSMT8,TW,TH,1,MODULATE,pFont->m_CBP,PSMCT32,0,0,1);\r\n\tpFont->RegTEX1 = PackTEX1(1,0,LINEAR,LINEAR,0,0,0);\r\n\r\n\r\n\t// update vram base pointer\r\n\t//FontVramBase = (((pFont->TBP<<8) + (TBW << 6)*Height + 0x1FFF) & 0xFFFFE000) >> 8;\r\n\tFontVramBase +=\t(pFont->m_NumTexVramBlocks + pFont->m_NumClutVramBlocks);\r\n\tDbg_MsgAssert(FontVramBase < (FontVramStart + FontVramSize), (\"Font: 2D VRAM Buffer Full: %x.\", FontVramBase));\r\n\r\n\r\n\t// add font to font list\r\n\tpFont->pNext = pFontList;\r\n\tpFontList = pFont;\r\n\r\n\t// we're done with the font file now\r\n\tFile::Close(pFile);\r\n\t\r\n\t// And restore the CurrentDMALoc, which we were just using temporarily.\r\n\tdma::pLoc = old_dma_loc;\t  \r\n\r\n\t// this will serve as the default spacing\r\n\tpFont->mSpaceSpacing = (pFont->pChars[pFont->Map['I']].u1 - pFont->pChars[pFont->Map['I']].u0) >> 4;\r\n\t\r\n\treturn pFont;\r\n}\r\n\r\n\r\n\r\nvoid UnloadFont(SFont *pFont)\r\n{\r\n\tSFont *pPrevFont;\r\n\tint found=0;\r\n\r\n\t// find font and unchain from list\r\n\tif (pFontList == pFont)\r\n\t{\r\n\t\tfound=1;\r\n\t\tpFontList = pFontList->pNext;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor (pPrevFont=pFontList; pPrevFont->pNext; pPrevFont=pPrevFont->pNext)\r\n\t\t{\r\n\t\t\tif (pPrevFont->pNext == pFont)\r\n\t\t\t{\r\n\t\t\t\tfound=1;\r\n\t\t\t\tpPrevFont->pNext = pFont->pNext;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert(found, (\"attempt to unload font which has not been loaded\"));\r\n\r\n\t// free memory\r\n\tMem::Free(pFont->pChars);\r\n\tMem::Free(pFont->pVifData);\r\n\tMem::Free(pFont);\r\n\r\n\t// and re-do VRAM allocation\r\n\tVRAMNeedsUpdating();\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SFont::ReallocateVRAM()\r\n{\r\n\t// calculate TBP\r\n\tm_TBP = FontVramBase;\r\n\tFontVramBase += m_NumTexVramBlocks;\r\n\r\n\t// calculate CBP\r\n\tm_CBP = FontVramBase;\r\n\tFontVramBase += m_NumClutVramBlocks;\r\n\r\n\t// bail if VRAM would become over-packed\r\n\tif (FontVramBase > (FontVramStart + FontVramSize))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"SingleTexture Realloc: 2D VRAM Buffer Full: %x.\", FontVramBase));\r\n\t}\r\n\r\n\t// Modify the data\r\n\tgs::ModifyTBP(gs::TEX0_1, (uint32 *) &RegTEX0, m_TBP, m_CBP);\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SFont::UpdateDMA()\r\n{\r\n\t// Modify the packets\r\n\tgs::ModifyTBP(gs::BITBLTBUF, mp_TexBitBltBuf, m_TBP);\r\n\tif (mp_ClutBitBltBuf)\r\n\t{\r\n\t\tgs::ModifyTBP(gs::BITBLTBUF, mp_ClutBitBltBuf, m_CBP);\r\n\t}\r\n}\r\n\r\nuint32 SFont::GetDefaultHeight() const\r\n{\r\n\treturn DefaultHeight;\r\n}\r\n\r\nuint32 SFont::GetDefaultBase() const\r\n{\r\n\treturn DefaultBase;\r\n}\r\n\r\nvoid SFont::QueryString(char *String, float &width, float &height)\r\n{\r\n\tSChar *pChar;\r\n\tchar *pLetter;\r\n\tuint16 u0,v0,x0,u1,v1,x1;\r\n\r\n\tx0 = 0;\r\n\r\n\t//sint16 char_spacing = 16 + (mCharSpacing<<4);\r\n\tsint16 char_spacing = mCharSpacing<<4;\r\n\tsint16 space_spacing = mSpaceSpacing<<4;\r\n\t\r\n\tfor (pLetter=String;; pLetter++)\r\n\t{\r\n\t\tpChar = NULL;\r\n\t\t// may be overridden by the '\\b' tag\r\n\t\tSFont *p_font = this;\r\n\t\t\r\n\t\t// acount for tags (might be multiple ones in a row)\r\n\t\tbool got_char_tag = false; // tag resulting in output of character\r\n\t\twhile (*pLetter == '\\\\' && !got_char_tag)\r\n\t\t{\r\n\t\t\tpLetter++;\r\n\t\t\tif (*pLetter == '\\\\')\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tswitch(*pLetter)\r\n\t\t\t{\r\n\t\t\t\tcase '\\\\':\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 'c':\r\n\t\t\t\tcase 'C':\r\n\t\t\t\t\tpLetter += 2; // skip over \"c#\"\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 's':\r\n\t\t\t\tcase 'S':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++; // skip \"s\"\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\tpChar = pChars + SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase 'b':\r\n\t\t\t\tcase 'B':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++; // skip \"b\"\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// switch over to buttons font, the regular font will be used again on the next character\r\n\r\n\t\t\t\t\tp_font = pButtonsFont;\r\n\t\t\t\t\tDbg_Assert(p_font);\r\n\t\t\t\t\tpChar = p_font->pChars + p_font->SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase 'm':\r\n\t\t\t\tcase 'M':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++; // skip \"m\"\r\n\t\t\t\t\tchar button_char = Nx::CFontManager::sMapMetaCharacterToButton(pLetter);\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(&button_char);\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_font = pButtonsFont;\r\n\t\t\t\t\tDbg_Assert(p_font);\r\n\t\t\t\t\tpChar = p_font->pChars + p_font->SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDbg_MsgAssert(0, (\"unknown tag %c\", *pLetter));\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t} // end while\r\n\t\t\r\n\t\tif (*pLetter == '\\0') break;\r\n\r\n\t\tif (*pLetter != ' ' || pChar)\r\n\t\t{\r\n\t\t\tif (!pChar)\r\n\t\t\t\tpChar = p_font->pChars + p_font->Map[(uint8)*pLetter];\r\n\t\t\tu0 = pChar->u0;\r\n\t\t\tv0 = pChar->v0;\r\n\t\t\tu1 = pChar->u1;\r\n\t\t\tv1 = pChar->v1;\r\n\t\t\tx1 = x0+u1-u0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tx1 = x0 + space_spacing;\r\n\t\t}\r\n\t\t\r\n\t\tx0 = x1+char_spacing;\r\n\t}\r\n\r\n\twidth  = (float)x0/16.0f;\r\n\theight = (float)DefaultHeight/16.0f;\r\n}\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nSText::SText(float pri) : SDraw2D(pri, true)\r\n{\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nSText::~SText()\r\n{\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SText::BeginDraw()\r\n{\r\n\t//printf(\"Trying to draw: %s with %x at (%f, %f) of scale %f\\n\", mp_string, m_rgba, m_xpos, m_ypos, m_scale);\r\n\r\n\t// Subsequent processing within Draw() will use this font\r\n\t// Draw() may call this function to temporarily switch fonts\r\n\tSFont *p_font = (spOverrideFont) ? spOverrideFont : mp_font;\r\n\t\r\n\t// dma tag\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\r\n\tvu1::Buffer = vu1::Loc;\r\n\r\n\tDbg_Assert(GetScissorWindow());\r\n\r\n\t// GS context\r\n\tgs::BeginPrim(ABS,0,0);\r\n\tgs::Reg1(gs::SCISSOR_1, GetScissorWindow()->GetScissorReg());\r\n\tgs::Reg1(gs::TEX0_1,\t p_font->RegTEX0);\r\n\tgs::Reg1(gs::TEX1_1,\t p_font->RegTEX1);\r\n\tgs::Reg1(gs::ALPHA_1,\t PackALPHA(0,1,0,1,0));\r\n\tgs::Reg1(gs::COLCLAMP,\t PackCOLCLAMP(1));\r\n\tgs::Reg1(gs::RGBAQ,\t (uint64)m_rgba);\r\n\tgs::EndPrim(0);\r\n\r\n\t// unpack giftag\r\n\tvif::UNPACK(0, V4_32, 1, ABS, UNSIGNED, 0);\r\n\tgif::BeginTagImmediate(gs::UV|gs::XYZ2<<4, 2, PACKED, SPRITE|TME|FST|ABE, 1, VU1_ADDR(GSPrim));\r\n\r\n\t// begin unpack for uv/xyz's\r\n\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, 1);\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SText::Draw()\r\n{\r\n\tSChar *pChar = NULL;\r\n\tchar *pLetter;\r\n\tuint16 u0,v0,u1,v1;\r\n\tuint32 x0,y0,x1,y1,yt,z;\r\n\r\n\tDbg_Assert(GetScissorWindow());\r\n\r\n\tx0 = (int)(m_xpos * s_screen_scale_x * 16.0f) + XOFFSET + ((GetScissorWindow()->GetScissorReg() & 0x7FF) << 4);\r\n\ty0 = (int)(m_ypos * s_screen_scale_y * 16.0f) + YOFFSET + ((GetScissorWindow()->GetScissorReg() >> 32 & 0x7FF) << 4);\r\n\tz = s_constant_z_enabled ? s_constant_z : GetZValue();\r\n\r\n\t//sint16 char_spacing = 16 + (mp_font->mCharSpacing<<4);\r\n\tfloat char_spacing = (float) (mp_font->mCharSpacing<<4) * m_xscale * s_screen_scale_x;\r\n\tfloat space_spacing = (float) (mp_font->mSpaceSpacing<<4) * m_xscale * s_screen_scale_x;\r\n\t\r\n\t// XXX\r\n\t//printf(\"   spacing=%f, %d\\n\", char_spacing, mp_font->mCharSpacing);\r\n\r\n\tfor (pLetter=mp_string;; pLetter++)\r\n\t{\r\n\t\tpChar = NULL;\r\n\t\tSFont *p_font = mp_font;\r\n\t\t\r\n\t\t// acount for tags (might be multiple ones in a row)\r\n\t\tbool got_char_tag = false; // tag resulting in output of character\r\n\t\twhile (*pLetter == '\\\\' && !got_char_tag)\r\n\t\t{\r\n\t\t\tpLetter++;\r\n\r\n\t\t\tswitch(*pLetter)\r\n\t\t\t{\r\n\t\t\t\tcase '\\\\':\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 'c':\r\n\t\t\t\tcase 'C':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++;\t// skip \"c\"\t\t\t\t\t\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\tpLetter++; // skip \"#\"\r\n\r\n\t\t\t\t\t// BIG MIKE\t(remove #if below, replace active_color_gs_register_thingy with GS code)\r\n\t\t\t\t\t#if 1\r\n\t\t\t\t\t// set active color from font\r\n\t\t\t\t\tuint32\ttemp_rgba = m_rgba;\r\n\t\t\t\t\tif (digit != 0 && !m_color_override)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_rgba = mp_font->mRGBATab[digit-1];\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// This method is not optimal, but it's not done very often\r\n\t\t\t\t\t// we just turn off text, and turn it on with new colors\r\n\t\t\t\t\tEndDraw();\r\n\t\t\t\t\tBeginDraw();\r\n\t\t\t\t\tm_rgba = temp_rgba;\r\n\t\t\t\t\t#endif\r\n\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase 's':\r\n\t\t\t\tcase 'S':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++;\t// skip \"s\"\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\t\r\n\t\t\t\t\tpChar = mp_font->pChars + mp_font->SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase 'b':\r\n\t\t\t\tcase 'B':\r\n\t\t\t\t{\r\n\t\t\t\t\t// 'B' stands for button, accesses the button font\r\n\r\n\t\t\t\t\tpLetter++; // skip \"b\"\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// switch to the buttons font!\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_font = pButtonsFont;\r\n\t\t\t\t\tDbg_Assert(p_font);\r\n\t\t\t\t\tpChar = p_font->pChars + p_font->SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\t\r\n\t\t\t\t\tspOverrideFont = p_font;\r\n\t\t\t\t\tEndDraw();\r\n\t\t\t\t\tBeginDraw();\r\n\t\t\t\t\t// we can now return to using the regular font (no override)\r\n\t\t\t\t\tspOverrideFont = NULL;\r\n\t\t\t\t\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDbg_MsgAssert(0, (\"unknown tag %c\", *pLetter));\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t} // end while\r\n\r\n\t\tif (*pLetter == '\\0') break;\r\n\t\t\r\n\t\tif (*pLetter != ' ' || pChar)\r\n\t\t{\r\n\t\t\tif (!pChar)\r\n\t\t\t\tpChar = p_font->pChars + p_font->Map[(uint8) *pLetter];\r\n\t\t\tyt = y0 + (int)((float)(p_font->DefaultBase - pChar->Baseline) * m_yscale * s_screen_scale_y);\r\n\t\t\tu0 = pChar->u0;\r\n\t\t\tv0 = pChar->v0;\r\n\t\t\tu1 = pChar->u1;\r\n\t\t\tv1 = pChar->v1;\r\n\t\t\tx1 = x0+(int)((float)(u1-u0)*m_xscale * s_screen_scale_x);\r\n\t\t\ty1 = yt+(int)((float)(v1-v0)*m_yscale * s_screen_scale_y);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tx0 += (int) (space_spacing + char_spacing);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (!NeedsCulling() || !((x0 | x1 | y0 | y1) & 0xFFFF0000))\r\n\t\t{\r\n\t\t\tvif::StoreV4_32(u0,v0,0,0);\r\n\t\t\tvif::StoreV4_32(x0,yt,z,0);\r\n\t\t\tvif::StoreV4_32(u1,v1,0,0);\r\n\t\t\tvif::StoreV4_32(x1,y1,z,0);\r\n\t\t}\r\n\r\n\t\tx0 = x1 + (int) char_spacing;\r\n\r\n\t\t// kick and start a new buffer if this one is full\r\n\t\tif (((dma::pLoc - gif::pTag)>>4) >= 250)\r\n\t\t{\r\n\t\t\tvif::EndUNPACK();\r\n\t\t\tgif::EndTagImmediate(1);\r\n\t\t\tvif::MSCAL(VU1_ADDR(Parser));\r\n\t\t\tvif::UNPACK(0, V4_32, 1, ABS, UNSIGNED, 0);\r\n\t\t\tgif::BeginTagImmediate(gs::UV|gs::XYZ2<<4, 2, PACKED, SPRITE|TME|FST|ABE, 1, VU1_ADDR(GSPrim));\r\n\t\t\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, 1);\r\n\t\t}\r\n\t\t\r\n\t\tif (p_font != mp_font)\r\n\t\t{\r\n\t\t\t// we just used the button font, so return to the regular one\r\n\t\t\tEndDraw();\r\n\t\t\tBeginDraw();\r\n\t\t}\r\n\t} // end for\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SText::EndDraw(void)\r\n{\r\n\tvif::EndUNPACK();\r\n\tgif::EndTagImmediate(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n\tdma::EndTag();\r\n}\r\n\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/chars.h",
    "content": "#ifndef __CHARS_H\r\n#define __CHARS_H\r\n\r\n#include <Gfx/NGPS/NX/sprite.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\ntypedef struct\r\n{\r\n\tuint16 u0,v0,u1,v1;\r\n\tuint16 Baseline;\r\n}\r\nSChar;\r\n\r\n\r\nstruct SFont\r\n{\r\npublic:\r\n\tuint32\t\tGetDefaultHeight() const;\r\n\tuint32\t\tGetDefaultBase() const;\r\n\r\n\tvoid\t\tQueryString(char *String, float &width, float &height);\r\n\r\n\tvoid\t\tReallocateVRAM();\r\n\tvoid\t\tUpdateDMA();\r\n\r\n\t//char Name[16];\r\n\tuint32\t\tDefaultHeight, DefaultBase;\r\n\tSChar\t\t*pChars;\r\n\tuint8\t\tMap[256];\r\n\tuint8\t\tSpecialMap[32];\r\n\tuint8\t\t*pVifData;\r\n\tuint32\t\tVifSize;\r\n\tuint64\t\tRegTEX0, RegTEX1;\r\n\tuint32 \t\t*mp_TexBitBltBuf;\t\t// Note these register pointers point to data in the DMA buffer,\r\n\tuint32 \t\t*mp_ClutBitBltBuf;\t\t// so they should only be used for writing, and only after drawing is done.\r\n\tuint16\t\tm_NumTexVramBlocks;\r\n\tuint16\t\tm_NumClutVramBlocks;\r\n\tuint16\t\tm_TBP;\r\n\tuint16\t\tm_CBP;\r\n\tsint16\t\tmCharSpacing;\r\n\tsint16\t\tmSpaceSpacing;\r\n\tuint32\t\tmRGBATab[16];\r\n\tSFont\t\t*pNext;\r\n};\r\n\r\n\r\n\r\nSFont *\t\tLoadFont(const char *Filename);\r\nvoid\t\tUnloadFont(SFont *);\r\nvoid\t\tSetTextWindow(uint16 x0, uint16 x1, uint16 y0, uint16 y1);\r\n\r\n\r\nstruct SText : public SDraw2D\r\n{\r\npublic:\r\n\t\t\t\t\tSText(float pri = 0.0f);\r\n\tvirtual\t\t\t~SText();\r\n\r\n\tSFont\t\t\t*mp_font;\r\n\r\n\tchar\t\t\t*mp_string;\r\n\tfloat\t\t\tm_xpos;\r\n\tfloat\t\t\tm_ypos;\r\n\tfloat\t\t\tm_xscale;\r\n\tfloat\t\t\tm_yscale;\r\n\tuint32\t\t\tm_rgba;\r\n\tbool\t\t\tm_color_override;\r\n\t\r\n\t// used in conjunction with BeginDraw()\r\n\t// if set, use specified font instead of mp_font\r\n\t// if not, use mp_font\r\n\tstatic SFont *\tspOverrideFont;\r\n\r\nprivate:\r\n\r\n\tvoid\t\t\tBeginDraw();\r\n\tvoid\t\t\tDraw(void);\r\n\tvoid\t\t\tEndDraw(void);\r\n};\r\n\r\nextern uint32\t\tFontVramStart;\r\nextern uint32\t\tFontVramBase;\r\nextern const uint32\tFontVramSize;\r\nextern SFont\t\t*pFontList;\r\nextern SFont *\t\tpButtonsFont;\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n#endif // __CHARS_H\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/dma.cpp",
    "content": "#include <core/defines.h>\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n#include \"gs.h\"\r\n#include \"group.h\"\r\n#include \"render.h\"\r\n#include \"vu1code.h\"\r\n#include \"switches.h\"\r\n#include \"geomnode.h\"\r\n\r\n/*\r\n\r\n Mick Notes:\r\n\r\n The calls the the DMA functions suggest that you are immediately executing something.\r\n You are not.  You are simply building a list of DMA commands that get executed the next frame\r\n \r\n The DMA list is the primary mechanism for initiating rendering on the PS2.\r\n \r\n To render something (like a line), you \"simply\" need to generate the appropiate DMA\r\n packets that contain GIF packets, containing GS primitives, and then link this into the \r\n main DMA list.\r\n \r\n Things such as world sectors have pre-build DMA lists that contain commands\r\n to upload lists of vertices to VU1 micro-memory, and then upload lists of\r\n triangles, and then trigger the appropiate VU1 microcode to transform and render them.\r\n \r\n These pre-built lists are linked in each frame with the appropiate transformation \r\n matricies that are needed based on the current camera position and the current\r\n object position (if it is a moving object)\r\n \r\n Thus, each object is mostly pre-build, and so rendering it requires very little CPU time.\r\n\r\n Each frame, we build a series of dynamic DMA lists.\r\n \r\n There are two lists for each group (see group.cpp).\r\n \r\n The first list is the texture upload.  This is pretty simple, just uploading a few textures.\r\n Texture uploading happens asyncrnously with rendering, so we can be executing a DMA list\r\n of rendering stuff at the same time as we are uploading the textures for the next group.   \r\n\r\n A lot of the DMA code is in DMA.H, as it is small inline functions.  \r\n\r\n The Runtime buffer is dynamically allocated in InitializeEngine().  Last time I looked it\r\n was 512K in size (note though, this is increased to 16MB for the debugging wireframe mode)\r\n \r\n The Runtime DMA lists are double buffered. You are executing one whilst building the next one.\r\n \r\n The pRunTimeBuffer is split in two, and pointers to the base of each half are stored in \r\n pList[0] and pList[1]   \r\n\r\n The integer varaible \"Field\" is 0 or 1, and indicates which field (odd or even) we are rendering to.  \r\n \r\n The DMA lists are build using a global variable char * pLoc.  \r\n \r\n At the start of a frame, pLoc is initilized like:\r\n \r\n \tdma::pLoc = dma::pList[Field];\r\n\r\n So it points to the start of one of our 256K DMA buffers (remember the other is being executed)\r\n \r\n DMA packets are now built using calls to the functions here and in DMA.H, for example: \r\n \r\n\tdma::Tag(dma::ref, ((uint8 *)&MPGEnd-(uint8 *)&MPGStart+15)/16, (uint)&MPGStart);\r\n\tvif::NOP();\r\n\tvif::NOP();\r\n\t\r\n (the above simply transfers the microcode from RAM to VU1 micromem)\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n Now, it's important to note that DMA execution does NOT simply start at pList[Field] and\r\n then run all the way through a frame's worth of data.  There are actually several DMA lists,\r\n which are fired off individually.  Some of these (the groups) are logically connected so that \r\n the end of one group's DMA (and the GS/VU activity it triggers) causes an interrupt,\r\n which the CPU handles by starting the DMA for another group (see interrupt.cpp)\r\n\r\n After the groups, there is the \"immediate mode\" DMA list, triggered by pEpilogue->pRender[Field]\r\n this is simply a raw DMA list that you can put anything you want into.  It starts at the value\r\n of pLoc after RenderWorld has been called (a terrible hack, as noted in the code :)\r\n \r\n All of the \"immediate mode\" rendering is considered to be part of pEpilogue.  It is terminated \r\n by the RenderEpilogue() function, which just links in a final interrupt trigger, which will \r\n get picked up by GsHandler(), and sGroup::pRenderGroup will be set to NULL, which is what\r\n WaitForRendering() uses to determine if rendering has finished.\r\n \r\n \t\t\t\t\t\t  \r\n\t\t\t\t\t\t  \r\n\r\n*/\r\n\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n\r\n// begin a subroutine\r\n\r\nvoid dma::BeginSub(eTag ID)\r\n{\r\n\tAlign(0,16);\r\n\tpSub = pLoc;\r\n\tdma::ID = ID;\r\n\tvu1::Loc = vu1::Buffer = 0;\r\n}\r\n\r\n\r\n// end a subroutine and return its address\r\n\r\nuint64 dma::EndSub(void)\r\n{\r\n\tuint64 GosubTag;\r\n\tAlign(0,16);\r\n\tGosubTag = ((uint64)pSub<<32) | ((uint64)ID<<28) | (vu1::Loc & 0x3FF) << 16;\r\n\tDbg_MsgAssert(ID!=refe && ID!=refs, (\"refe and refs not supported in dma tag!\"));\r\n\tif (ID==ref)\r\n\t{\r\n\t\tGosubTag |= (pLoc - pSub) >> 4;\r\n\t}\r\n\treturn GosubTag;\r\n}\r\n\r\n\r\n// call a subroutine (using a dma::call or a dma::ref)\r\n\r\nvoid dma::Gosub(uint Num, uint Path)\r\n{\r\n\tregister uint64 Tag = Gosubs[Num];\r\n\r\n\tStore64(Tag);\r\n\r\n\tswitch (Path)\r\n\t{\r\n\tcase 1:\r\n\t\tvif::BASE(vu1::Loc);\r\n\t\tvif::OFFSET(0);\r\n\t\tvu1::Loc += (Tag>>16) & 0x3FF;\t\t\t// VUMem size\r\n\t\tbreak;\r\n\r\n\tcase 2:\r\n\t\tvif::NOP();\r\n\t\tvif::NOP();\r\n\t\tbreak;\r\n\r\n\tcase 3:\r\n\t\tpLoc += 8;\t\t\t\t\t\t\t\t// no need to write anything since TTE=0\r\n\t\tbreak;\r\n\r\n\t#ifdef __PLAT_NGPS__\r\n\tdefault:\r\n\t\tprintf(\"error: dma::Gosub() called with unrecognised path number\\n\");\r\n\t\texit(1);\r\n\t#endif\r\n\t}\r\n\r\n}\r\n\r\n\r\n\r\n// begin a 3D subroutine\r\n\r\nvoid dma::BeginSub3D(void)\r\n{\r\n\tAlign(0,16);\r\n\tpSub = pLoc;\r\n\tvu1::Loc = vu1::Buffer = 0;\r\n}\r\n\r\n\r\n// end a 3D subroutine and return its address\r\n\r\nuint8 *dma::EndSub3D(void)\r\n{\r\n\t((uint16 *)pSub)[1] |= vu1::Loc&0x3FF;\r\n\treturn pSub;\r\n}\r\n\r\n\r\n// call a 3D subroutine (always using a dma::call)\r\n\r\nvoid dma::Gosub3D(uint8 *pSub, uint RenderFlags)\r\n{\r\n\tBeginTag(call,(uint)pSub);\r\n\tvif::BASE(vu1::Loc);\r\n\tvif::OFFSET(0);\r\n\tvif::ITOP(RenderFlags);\r\n\tEndTag();\r\n\tvu1::Loc += ((uint16 *)pSub)[1];\r\n}\r\n\r\n\r\n\r\n// dma list traversal function\r\nuint8 *dma::NextTag(uint8 *pTag, bool stepInto)\r\n{\r\n\tDbg_MsgAssert((*(uint32 *)pTag&0x80000000)==0, (\"IRQ bit set in dma tag\"));\r\n\tDbg_MsgAssert(*(uint32 *)pTag!=refe<<28 && *(uint32 *)pTag!=refs<<28, (\"refe and refs not supported in dma tag!\"));\r\n\tswitch (*(uint32 *)pTag>>28)\r\n\t{\r\n\tcase cnt:\r\n\t\treturn pTag + 16 + ((uint)((uint16 *)pTag)[0] << 4);\r\n\r\n\tcase next:\r\n\t\treturn ((uint8 **)pTag)[1];\r\n\r\n\tcase ref:\r\n\t\treturn pTag + 16;\r\n\r\n\tcase call:\r\n\t\tDbg_MsgAssert(sp<2, (\"dma call stack overflow\"));\r\n\t\tif (stepInto)\r\n\t\t{\r\n\t\t\tStack[sp++] = pTag + 16 + ((uint)((uint16 *)pTag)[0] << 4);\r\n\t\t\treturn ((uint8 **)pTag)[1];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn pTag + 16 + ((uint)((uint16 *)pTag)[0] << 4);\r\n\t\t}\r\n\r\n\tcase ret:\r\n\t\tDbg_MsgAssert(sp>0, (\"dma call stack underflow\"));\r\n\t\treturn Stack[--sp];\r\n\r\n\tcase end:\r\n\tdefault:\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\n// auxilliary comparison function for dma sort\r\nint dma::Cmp(const void *p1, const void *p2)\r\n{\r\n\treturn ((SSortElement *)p1)->z < ((SSortElement *)p2)->z ? -1 :\r\n\t\t   ((SSortElement *)p1)->z > ((SSortElement *)p2)->z ? +1 :\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0 ;\r\n}\r\n\r\n\r\n#if 0\r\n\r\n// original version\r\n\r\n// sort a dma list of mesh packets on z\r\n// the z is stored in the unused ADDR word of the first cnt tag of the mesh packet\r\n\r\nuint8 *dma::SortGroup(uint8 *pList)\r\n{\r\n\tint num_elements;\r\n\tSSortElement *p_element;\r\n\tuint8 *p_tag, *p_end_tag, *p_prev_tag=NULL;\r\n\teTag ID;\r\n\r\n\t// set array base at start of scratchpad\r\n\tSSortElement *p_array = (SSortElement *)0x70000000;\r\n\r\n\t// copy the addresses and z-values into array\r\n\tp_element = p_array;\r\n\tp_tag = pList;\r\n\tsp = 0;\t\t\t\t// starting at top level of dma list\r\n    while ((ID = (eTag)(*(uint32 *)p_tag>>28)) != end)\r\n\t{\r\n\t\tif (ID == cnt)\r\n\t\t{\r\n\t\t\tp_element->address = p_tag;\r\n\t\t\tp_element->z = ((float *)p_tag)[1];\r\n\t\t\tp_element++;\r\n\t\t}\r\n\t\tp_tag = NextTag(p_tag, false);\r\n\t}\r\n\r\n\t// check array fits within scratchpad\r\n\tnum_elements = p_element-p_array;\r\n\tDbg_MsgAssert(num_elements*sizeof(SSortElement)<=16384, (\"Can't fit array in scratchpad\"));\r\n\r\n\t// record address of end tag\r\n\tp_end_tag = p_tag;\r\n\r\n\t// sort the array\r\n\tqsort(p_array, num_elements, sizeof(SSortElement), Cmp);\r\n\r\n\t// reorder the dma list according to the sorted array\r\n\tfor (p_element=p_array; p_element<p_array+num_elements; p_element++)\r\n\t{\r\n\t\tp_tag = p_element->address;\r\n\r\n\t\tdo\r\n\t\t{\r\n\t\t\tp_prev_tag = p_tag;\r\n\t\t\tp_tag = NextTag(p_tag, false);\r\n\t\t\tID = (eTag)(*(uint32 *)p_tag >> 28);\r\n\t\t} while (ID!=cnt && ID!=end);\r\n\r\n\t\t((uint8 **)p_prev_tag)[1] = (p_element+1)->address;\r\n\t}\r\n\r\n\t// patch up the final dma::next tag to point to the dma::end tag\r\n\t((uint8 **)p_prev_tag)[1] = p_end_tag;\r\n\r\n\t// chain through the whole list to adjust vu1 base pointers\r\n\tvu1::Loc = 0;\r\n\tfor (p_tag = p_array->address; *(uint32 *)p_tag>>28 != end; p_tag = NextTag(p_tag, false))\r\n\t{\r\n\t\t//if (*(uint32 *)p_tag & 0x03FF0000)\r\n\t\tif (((uint8 *)p_tag)[11] == 0x03)\r\n\t\t{\r\n\t\t\t((uint16 *)p_tag)[4] &= ~0x3FF;\r\n\t\t\t((uint16 *)p_tag)[4] |= vu1::Loc;\r\n\t\t\tvu1::Loc += ((uint16 *)p_tag)[1];\r\n\t\t}\r\n\t}\r\n\r\n\t// return the address of the head tag\r\n\treturn p_array->address;\r\n}\r\n\r\n#else\r\n\r\n// new version:\r\n// the list is sorted in segments corresponding to viewports\r\n\r\n// sort a dma list of mesh packets on z\r\n// the z is stored in the unused ADDR word of the first cnt tag of the mesh packet\r\n\r\nuint8 *dma::SortGroup(uint8 *pList)\r\n{\r\n\tint num_elements, i, num_segments;\r\n\tSSortElement *p_element, *p_segment[4];\r\n\tuint8 *p_tag, *p_end_tag, *p_prev_tag=NULL;\r\n\teTag ID;\r\n\r\n\t// set array base at start of scratchpad\r\n\tSSortElement *p_array = (SSortElement *)0x70000000;\r\n\r\n\t// copy the addresses and z-values into array\r\n\tp_element = p_array;\r\n\tp_tag = pList;\r\n\tsp = 0;\t\t\t\t// starting at top level of dma list\r\n\tnum_segments = 0;\r\n    while ((ID = (eTag)(*(uint32 *)p_tag>>28)) != end)\r\n\t{\r\n\t\tfor (i=0; i<render::sMarkerIndex; i++)\r\n\t\t{\r\n\t\t\tif ((int)p_tag == render::sSortedListMarker[i])\r\n\t\t\t{\r\n\t\t\t\t//printf(\"matched marker %d\\n\", i);\r\n\t\t\t\tp_segment[num_segments++] = p_element;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (ID == cnt)\r\n\t\t{\r\n\t\t\tp_element->address = p_tag;\r\n\t\t\tp_element->z = ((float *)p_tag)[1];\r\n\t\t\tp_element++;\r\n\t\t}\r\n\t\tp_tag = NextTag(p_tag, false);\r\n\t}\r\n\r\n\t// check array fits within scratchpad\r\n\tnum_elements = p_element-p_array;\r\n\tDbg_MsgAssert(num_elements*sizeof(SSortElement)<=16384, (\"Can't fit array in scratchpad\"));\r\n\r\n\t// record address of end tag\r\n\tp_end_tag = p_tag;\r\n\r\n\t// sort the array in segments\r\n\tif (num_segments)\r\n\t{\r\n\t\tfor (i=0; i<num_segments-1; i++)\r\n\t\t{\r\n\t\t\t//printf(\"sorting from %08X to %08X\\n\", p_segment[i], p_segment[i+1]);\r\n\t\t\tqsort(p_segment[i], p_segment[i+1]-p_segment[i], sizeof(SSortElement), Cmp);\r\n\t\t}\r\n\t\t//printf(\"sorting from %08X to %08X\\n\", p_segment[i], p_element);\r\n\t\tqsort(p_segment[i], p_element-p_segment[i], sizeof(SSortElement), Cmp);\r\n\t}\r\n\r\n\t// reorder the dma list according to the sorted array\r\n\tfor (p_element=p_array; p_element<p_array+num_elements; p_element++)\r\n\t{\r\n\t\tp_tag = p_element->address;\r\n\r\n\t\tdo\r\n\t\t{\r\n\t\t\tp_prev_tag = p_tag;\r\n\t\t\tp_tag = NextTag(p_tag, false);\r\n\t\t\tID = (eTag)(*(uint32 *)p_tag >> 28);\r\n\t\t} while (ID!=cnt && ID!=end);\r\n\r\n\t\t((uint8 **)p_prev_tag)[1] = (p_element+1)->address;\r\n\t}\r\n\r\n\t// patch up the final dma::next tag to point to the dma::end tag\r\n\t((uint8 **)p_prev_tag)[1] = p_end_tag;\r\n\r\n\t// chain through the whole list to adjust vu1 base pointers\r\n\tvu1::Loc = 0;\r\n\tfor (p_tag = p_array->address; *(uint32 *)p_tag>>28 != end; p_tag = NextTag(p_tag, false))\r\n\t{\r\n\t\tif (*(uint32 *)p_tag & 0x3FF0000)\r\n\t\t{\r\n\t\t\t((uint16 *)p_tag)[4] &= ~0x3FF;\r\n\t\t\t((uint16 *)p_tag)[4] |= vu1::Loc;\r\n\t\t\tvu1::Loc += ((uint16 *)p_tag)[1];\r\n\t\t}\r\n\t}\r\n\r\n\t// return the address of the head tag\r\n\treturn p_array->address;\r\n}\r\n\r\n#endif\r\n\r\n\r\n#endif\r\n\r\n\r\nvoid dma::BeginList(void *pGroup)\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\t// assume group isn't used\r\n\t((sGroup *)pGroup)->Used[render::Field] = false;\r\n\r\n\t// set the dma list pointer\r\n\t((sGroup *)pGroup)->pRender[render::Field] = pLoc;\r\n\r\n\t// VIF1 and VU1 setup\r\n\tBeginTag(cnt, 0xFF000000);\t\t// bit of a cheat, so it will stay at the start of any sorted list\r\n\tvif::FLUSH();\r\n\tvif::STMASK(0);\r\n\tvif::STMOD(0);\r\n\tvif::STCYCL(1,1);\r\n\tvif::BASE(0);\r\n\tvif::OFFSET(0);\r\n\tvif::MSCAL(VU1_ADDR(Setup));\r\n\tEndTag();\r\n\r\n\tdma::Tag(dma::next, 0, 0);\r\n\tvif::NOP();\r\n\tvif::NOP();\r\n\r\n\t((sGroup *)pGroup)->vu1_loc = 0;\r\n\t((sGroup *)pGroup)->p_tag = pTag;\r\n#endif\r\n}\r\n\r\n\r\nvoid dma::EndList(void *pGroup)\r\n{\r\n\r\n\tSetList(pGroup);\r\n\r\n\t// end dma list for this group\r\n\tBeginTag(end, 0);\r\n\t#if USE_INTERRUPTS\r\n\t//vif::BASE(((sGroup *)pGroup)->vu1_loc);\r\n\tvif::BASE(vu1::Loc);\r\n\tvif::OFFSET(0);\r\n\tvu1::Loc = 0;   \t\t\t\t\t\t\t// must do this as a relative prim for a sortable list...\r\n\tgs::BeginPrim(REL,0,0);\r\n\tgs::Reg1(gs::SIGNAL, PackSIGNAL(1,1));\t\t// signal the end of rendering this group\r\n\tgs::EndPrim(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n\t#endif\r\n\tEndTag();\r\n\t((uint16 *)pTag)[1] |= vu1::Loc & 0x3FF;\t// must write some code for doing this automatically\r\n}\r\n\r\n\r\nvoid dma::ReallySetList(void *pGroup)\r\n{\r\n\r\n\t// finish with the previous dma context\r\n\tif (sp_group)\r\n\t{\r\n\t\t// ensure the last tag was a 'next'...\r\n\r\n\t\t// get the tag ID\r\n\t\tuint ID = *(uint32 *)pTag>>28;\r\n\r\n\t\t// take care of 'refe' and 'refs'\r\n\t\tDbg_MsgAssert(ID!=refe && ID!=refs, (\"refe and refs not supported in dma tag!\"));\r\n\r\n\t\t// take care of 'call' and 'ref'\r\n\t\tif (ID==call || ID==ref)\r\n\t\t{\r\n\t\t\tTag(next, 0, 0);\r\n\t\t\tvif::NOP();\r\n\t\t\tvif::NOP();\r\n\t\t}\r\n\r\n\t\t// take care of 'cnt'\r\n\t\telse if (ID==cnt)\r\n\t\t{\r\n\t\t\tpTag[3] = next<<4;\r\n\t\t}\r\n\r\n\t\t// 'end' and 'ret' won't have anything after them in the same context\r\n\t\t// and 'next' is fine as it is\r\n\r\n\t\t// save the vu1 location and dma tag location\r\n\t\t((sGroup *)sp_group)->vu1_loc = vu1::Loc;\r\n\t\t((sGroup *)sp_group)->p_tag = pTag;\r\n\t}\r\n\r\n\t// change bucket\r\n\tsp_group = pGroup;\r\n\r\n\t// set up the new bucket\r\n\tif (pGroup)\r\n\t{\r\n\t\t// restore the vu1 location and dma tag location\r\n\t\tvu1::Loc = ((sGroup *)pGroup)->vu1_loc;\r\n\t\tpTag = ((sGroup *)pGroup)->p_tag;\r\n\r\n\t\t// patch the pointer of the dangling 'next' tag\r\n\t\t((uint32 *)pTag)[1] = (uint32)pLoc;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nint dma::GetDmaSize(uint8 *pTag)\r\n{\r\n\treturn (*(uint16 *)pTag + 1) << 4;\t// (QWC+1)*16 bytes\r\n}\r\n\r\n\r\n\r\nint dma::GetNumVertices(uint8 *pTag)\r\n{\r\n\t// get start and end of dma packet\r\n\tuint8 *p_start = pTag + 8;\r\n\tuint8 *p_end   = pTag + 16 + (*(uint16 *)pTag << 4);\r\n\r\n\t// parse vifcodes\r\n\tuint8 *p_code = p_start;\r\n\tint   num_verts = 0;\r\n\tdo\r\n\t{\r\n\t\tif (((p_code[3] & 0x7F) == 0x05) && (p_code[0] == 1))\t\t// look for STMOD(1)\r\n\t\t{\r\n\t\t\tp_code = vif::NextCode(p_code);\r\n\t\t\tDbg_MsgAssert((p_code[3] & 0x7E)==0x6C, (\"0x%08X: expected UNPACK V4_16 or V4_32\", *(uint32 *)p_code));\r\n\t\t\tnum_verts += p_code[2];\r\n\t\t}\r\n\r\n\t\tp_code=vif::NextCode(p_code);\r\n\t}\r\n\twhile (p_code < p_end);\r\n\r\n\treturn num_verts;\r\n}\r\n\r\n\r\n\r\nint dma::GetNumTris(uint8 *pTag)\r\n{\r\n\t// get start and end of dma packet\r\n\tuint8 *p_start = pTag + 8;\r\n\tuint8 *p_end   = pTag + 16 + (*(uint16 *)pTag << 4);\r\n\r\n\t// parse vifcodes\r\n\tuint8 *p_code = p_start;\r\n\tint   num_tris = 0;\r\n\tint   num_verts;\r\n\tdo\r\n\t{\r\n\t\tif (((p_code[3] & 0x7F) == 0x05) && (p_code[0] == 1))\t\t// look for STMOD(1)\r\n\t\t{\r\n\t\t\tp_code = vif::NextCode(p_code);\r\n\t\t\tDbg_MsgAssert((p_code[3] & 0x7E)==0x6C, (\"0x%08X: expected UNPACK V4_16 or V4_32\", *(uint32 *)p_code));\r\n\t\t\tnum_verts = p_code[2];\r\n\r\n\t\t\t// loop over verts, counting the adc bits which are zero\r\n\t\t\tif (p_code[3] & 0x01)\t// V4_16\r\n\t\t\t{\r\n\t\t\t\tuint16 *p_adc = ((uint16 *)p_code)+5;\r\n\t\t\t\tfor (int i=0; i<num_verts; i++,p_adc+=4)\r\n\t\t\t\t{\r\n\t\t\t\t\tif ((*p_adc & 0x8000) == 0)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnum_tris++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\t\t\t\t\t// V4_32\r\n\t\t\t{\r\n\t\t\t\tuint32 *p_adc = ((uint32 *)p_code)+4;\r\n\t\t\t\tfor (int i=0; i<num_verts; i++,p_adc+=4)\r\n\t\t\t\t{\r\n\t\t\t\t\tif ((*p_adc & 0x00008000) == 0)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnum_tris++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_code=vif::NextCode(p_code);\r\n\t}\r\n\twhile (p_code < p_end);\r\n\r\n\treturn num_tris;\r\n}\r\n\r\n\r\n\r\nvoid dma::Copy(uint8 *pTag, uint8 *pDest)\r\n{\r\n\tmemcpy(pDest, pTag, (*(uint16 *)pTag + 1) << 4);\r\n}\r\n\r\n\r\n\r\nvoid dma::TransferValues(uint8 *pTag, uint8 *pArray, int size, int dir, uint32 vifcodeMask, uint32 vifcodePattern)\r\n{\r\n\t// get start and end of dma packet\r\n\tuint8 *p_start = pTag + 8;\r\n\tuint8 *p_end   = pTag + 16 + (*(uint16 *)pTag << 4);\r\n\r\n\t// parse vifcodes\r\n\tuint8 *p_code = p_start;\r\n\tuint32 *pSource, *pDest;\r\n\tint i, num_words;\r\n\r\n\t*(dir ? &pSource : &pDest) = (uint32 *)pArray;\r\n\r\n\tdo\r\n\t{\r\n\t\tif ((*(uint32 *)p_code & vifcodeMask) == vifcodePattern)\r\n\t\t{\r\n\t\t\t*(!dir ? &pSource : &pDest) = (uint32 *)(p_code+4);\r\n\r\n\t\t\tnum_words = (p_code[2] * size) >> 2;\r\n\t\t\tfor (i=0; i<num_words; i++)\r\n\t\t\t{\r\n\t\t\t\t*pDest++ = *pSource++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_code=vif::NextCode(p_code);\r\n\t}\r\n\twhile (p_code < p_end);\r\n}\r\n\r\n\r\nvoid dma::TransferColours(uint8 *pTag, uint8 *pArray, int dir)\r\n{\r\n\t// get start and end of dma packet\r\n\tuint8 *p_start = pTag + 8;\r\n\tuint8 *p_end   = pTag + 16 + (*(uint16 *)pTag << 4);\r\n\r\n\t// parse vifcodes\r\n\tuint8 *p_code = p_start;\r\n\tuint8 *pSource, *pDest;\r\n\tint i, num_words;\r\n\r\n\t*(dir ? &pSource : &pDest) = (uint8 *)pArray;\r\n\r\n\tdo\r\n\t{\r\n\t\tif ((*(uint32 *)p_code & 0x7B000000) == 0x6A000000)\r\n\t\t{\r\n\t\t\tif ((*(uint32 *)p_code & 0x7F000000) == 0x6E000000)\r\n\t\t\t{\r\n\t\t\t\tTransferValues(pTag, pArray, 4, dir, 0x7F000000, 0x6E000000);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t*(!dir ? &pSource : &pDest) = p_code+4;\r\n\r\n\t\t\tnum_words = p_code[2];\r\n\t\t\tfor (i=0; i<num_words; i++)\r\n\t\t\t{\r\n\t\t\t\t*pDest++ = *pSource++;\r\n\t\t\t\t*pDest++ = *pSource++;\r\n\t\t\t\t*pDest++ = *pSource++;\r\n\t\t\t\t(*(dir ? &pSource : &pDest))++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_code=vif::NextCode(p_code);\r\n\t}\r\n\twhile (p_code < p_end);\r\n}\r\n\r\n\r\n\r\n\r\nint dma::GetBitLengthXYZ(uint8 *pTag)\r\n{\r\n\t// get start and end of dma packet\r\n\tuint8 *p_start = pTag + 8;\r\n\tuint8 *p_end   = pTag + 16 + (*(uint16 *)pTag << 4);\r\n\r\n\t// parse vifcodes\r\n\tuint8 *p_code = p_start;\r\n\tint   bit_length = 0;\r\n\tdo\r\n\t{\r\n\t\tif (((p_code[3] & 0x7F) == 0x05) && (p_code[0] == 1))\t\t// look for STMOD(1)\r\n\t\t{\r\n\t\t\tp_code = vif::NextCode(p_code);\r\n\t\t\tDbg_MsgAssert((p_code[3] & 0x7E)==0x6C, (\"0x%08X: expected UNPACK V4_16 or V4_32\", *(uint32 *)p_code));\r\n\t\t\tbit_length = 32 >> (p_code[3] & 0x03);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tp_code=vif::NextCode(p_code);\r\n\t}\r\n\twhile (p_code < p_end);\r\n\r\n\treturn bit_length;\r\n}\r\n\r\n\r\nvoid dma::ExtractXYZs(uint8 *pTag, uint8 *pArray)\r\n{\r\n\t// get start and end of dma packet\r\n\tuint8 *p_start = pTag + 8;\r\n\tuint8 *p_end   = pTag + 16 + (*(uint16 *)pTag << 4);\r\n\r\n\t// parse vifcodes\r\n\tuint8 *p_code = p_start;\r\n\tint i, num_words;\r\n\tsint32 *p_dest = (sint32 *)pArray;\r\n\r\n\tdo\r\n\t{\r\n\t\tif ((*(uint32 *)p_code & 0x7F000001) == 0x05000001)\r\n\t\t{\r\n\t\t\tp_code = vif::NextCode(p_code);\r\n\t\t\tDbg_MsgAssert((p_code[3] & 0x7E)==0x6C, (\"0x%08X: expected UNPACK V4_16 or V4_32\", *(uint32 *)p_code));\r\n\r\n\t\t\tnum_words = (int)((((uint32)p_code[2]-1)&0xFF)+1) << 2;\r\n\r\n\t\t\tif ((p_code[3] & 0x7F) == 0x6C)\r\n\t\t\t{\r\n\t\t\t\t// 32 bit\r\n\t\t\t\tsint32 *p_source = (sint32 *)(p_code+4);\r\n\t\t\t\tfor (i=0; i<num_words; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_dest++ = *p_source++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// 16 bit\r\n\t\t\t\tsint16 *p_source = (sint16 *)(p_code+4);\r\n\t\t\t\tfor (i=0; i<num_words; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_dest++ = (sint32)*p_source++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tp_code=vif::NextCode(p_code);\r\n\t}\r\n\twhile (p_code < p_end);\r\n}\r\n\r\n\r\nvoid dma::ReplaceXYZs(uint8 *pTag, uint8 *pArray, bool skipW)\r\n{\r\n\t//printf(\"Replacing XYZs...\\n\");\r\n\r\n\t// get start and end of dma packet\r\n\tuint8 *p_start = pTag + 8;\r\n\tuint8 *p_end   = pTag + 16 + (*(uint16 *)pTag << 4);\r\n\r\n\t// parse vifcodes\r\n\tuint8 *p_code = p_start;\r\n\tint i, num_words;\r\n\tsint32 *p_source = (sint32 *)pArray;\r\n\r\n\tdo\r\n\t{\r\n\t\tif ((*(uint32 *)p_code & 0x7F000001) == 0x05000001)\r\n\t\t{\r\n\t\t\tp_code = vif::NextCode(p_code);\r\n\t\t\tDbg_MsgAssert((p_code[3] & 0x7E)==0x6C, (\"0x%08X: expected UNPACK V4_16 or V4_32\", *(uint32 *)p_code));\r\n\r\n\t\t\tnum_words = (int)((((uint32)p_code[2]-1)&0xFF)+1) << 2;\r\n\r\n\t\t\tif ((p_code[3] & 0x7F) == 0x6C)\r\n\t\t\t{\r\n\t\t\t\t// 32 bit\r\n\t\t\t\tsint32 *p_dest = (sint32 *)(p_code+4);\r\n\t\t\t\tif (skipW)\r\n\t\t\t\t{\r\n\t\t\t\t\tfor (i=0; i<num_words; i++, p_dest++, p_source++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ((i & 3) == W)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t*p_dest = *p_source;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tfor (i=0; i<num_words; i++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t*p_dest++ = *p_source++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// 16 bit\r\n\t\t\t\tsint16 *p_dest = (sint16 *)(p_code+4);\r\n\t\t\t\tif (skipW)\r\n\t\t\t\t{\r\n\t\t\t\t\tfor (i=0; i<num_words; i++, p_dest++, p_source++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ((i & 3) == W)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t*p_dest = (sint32)*p_source;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tfor (i=0; i<num_words; i++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t*p_dest++ = (sint32)*p_source++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tp_code=vif::NextCode(p_code);\r\n\t}\r\n\twhile (p_code < p_end);\r\n}\r\n\r\n\r\nvoid dma::ExtractRGBAs(uint8 *pTag, uint8 *pArray)\r\n{\r\n\t//TransferValues(pTag, pArray, 4, 0, 0x7F000000, 0x6E000000);\r\n\tTransferColours(pTag, pArray, 0);\r\n}\r\n\r\n\r\nvoid dma::ReplaceRGBAs(uint8 *pTag, uint8 *pArray)\r\n{\r\n\t//TransferValues(pTag, pArray, 4, 1, 0x7F000000, 0x6E000000);\r\n\tTransferColours(pTag, pArray, 1);\r\n}\r\n\r\n\r\nvoid dma::ExtractSTs(uint8 *pTag, uint8 *pArray)\r\n{\r\n\t// get start and end of dma packet\r\n\tuint8 *p_start = pTag + 8;\r\n\tuint8 *p_end   = pTag + 16 + (*(uint16 *)pTag << 4);\r\n\r\n\t// parse vifcodes\r\n\tuint8 *p_code = p_start;\r\n\tint i, num_words;\r\n\tsint32 *p_dest = (sint32 *)pArray;\r\n\r\n\tdo\r\n\t{\r\n\t\tif ((*(uint32 *)p_code & 0x7E000000) == 0x64000000)\r\n\t\t{\r\n\t\t\tnum_words = (int)((((uint32)p_code[2]-1)&0xFF)+1) << 1;\r\n\r\n\t\t\tif ((p_code[3] & 0x7F) == 0x64)\r\n\t\t\t{\r\n\t\t\t\t// 32-bit\r\n\t\t\t\tsint32 *p_source = (sint32 *)(p_code+4);\r\n\t\t\t\tfor (i=0; i<num_words; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_dest++ = *p_source++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// 16-bit\r\n\t\t\t\tsint16 *p_source = (sint16 *)(p_code+4);\r\n\t\t\t\tfor (i=0; i<num_words; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_dest++ = *p_source++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_code=vif::NextCode(p_code);\r\n\t}\r\n\twhile (p_code < p_end);\r\n}\r\n\r\n\r\nvoid dma::ReplaceSTs(uint8 *pTag, uint8 *pArray)\r\n{\r\n\t// get start and end of dma packet\r\n\tuint8 *p_start = pTag + 8;\r\n\tuint8 *p_end   = pTag + 16 + (*(uint16 *)pTag << 4);\r\n\r\n\t// parse vifcodes\r\n\tuint8 *p_code = p_start;\r\n\tint i, num_words;\r\n\tsint32 *p_source = (sint32 *)pArray;\r\n\r\n\tdo\r\n\t{\r\n\t\tif ((*(uint32 *)p_code & 0x7E000000) == 0x64000000)\r\n\t\t{\r\n\t\t\tnum_words = (int)((((uint32)p_code[2]-1)&0xFF)+1) << 1;\r\n\r\n\t\t\tif ((p_code[3] & 0x7F) == 0x64)\r\n\t\t\t{\r\n\t\t\t\t// 32-bit\r\n\t\t\t\tsint32 *p_dest = (sint32 *)(p_code+4);\r\n\t\t\t\tfor (i=0; i<num_words; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_dest++ = *p_source++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// 16-bit\r\n\t\t\t\tsint16 *p_dest = (sint16 *)(p_code+4);\r\n\t\t\t\tfor (i=0; i<num_words; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_dest++ = *p_source++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_code=vif::NextCode(p_code);\r\n\t}\r\n\twhile (p_code < p_end);\r\n}\r\n\r\n\r\nvoid dma::TransformSTs(uint8 *pTag, const Mth::Matrix &mat)\r\n{\r\n\t// get start and end of dma packet\r\n\tuint8 *p_start = pTag + 8;\r\n\tuint8 *p_end   = pTag + 16 + (*(uint16 *)pTag << 4);\r\n\r\n\t// parse vifcodes\r\n\tuint8 *p_code = p_start;\r\n\tint i, num_verts;\r\n\tMth::Vector texcoords;\r\n\t\r\n\tdo\r\n\t{\r\n\t\tif ((p_code[3] & 0x6E) == 0x64)\r\n\t\t{\r\n\t\t\tnum_verts = (int)((((uint32)p_code[2]-1)&0xFF)+1);\r\n\r\n\t\t\tif ((p_code[3] & 0x6F) == 0x64)\r\n\t\t\t{\r\n\t\t\t\t// 32-bit float st's\r\n\t\t\t\tfloat *p_coords = (float *)(p_code+4);\r\n\t\t\t\tfor (i=0; i<num_verts; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\ttexcoords[0] = p_coords[0];\r\n\t\t\t\t\ttexcoords[1] = p_coords[1];\r\n\t\t\t\t\ttexcoords[2] = 0.0f;\r\n\t\t\t\t\ttexcoords[3] = 1.0f;\r\n\t\t\t\t\ttexcoords *= mat;\r\n\t\t\t\t\t*p_coords++ = texcoords[0];\r\n\t\t\t\t\t*p_coords++ = texcoords[1];\r\n\t\t\t\t\t//printf(\"(%g, %g)\\n\", texcoords[0], texcoords[1]);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// 16-bit fixed uv's\r\n\t\t\t\tsint16 *p_coords = (sint16 *)(p_code+4);\r\n\t\t\t\tfor (i=0; i<num_verts; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\ttexcoords[0] = (float)(p_coords[0]-0x2000);\r\n\t\t\t\t\ttexcoords[1] = (float)(p_coords[1]-0x2000);\r\n\t\t\t\t\ttexcoords[2] = 0.0f;\r\n\t\t\t\t\ttexcoords[3] = 1024.0f;\t\t// this should really be \"texture width * 16\",\r\n\t\t\t\t\t\t\t\t\t\t\t\t// but we don't have access to texture width here\r\n\t\t\t\t\ttexcoords *= mat;\r\n\t\t\t\t\t*p_coords++ = (sint16)texcoords[0] + 0x2000;\r\n\t\t\t\t\t*p_coords++ = (sint16)texcoords[1] + 0x2000;\r\n\t\t\t\t\t//printf(\"(%g, %g)\\n\", texcoords[0], texcoords[1]);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_code=vif::NextCode(p_code);\r\n\t}\r\n\twhile (p_code < p_end);\r\n}\r\n\r\n\r\n\r\nvoid dma::SqueezeADC(uint8 *pTag)\r\n{\r\n\tuint8  *p_code, *p_end, *p_unpack[5];\r\n\tuint16 addr, vumem_size;\r\n\tuint32 nloop=0, nreg=0, texcrds_size, *p_giftag=NULL, i, num_squeezed, addr_diff;\r\n\tuint32 *p_texcrds_source, *p_texcrds_dest;\r\n\tuint8  *p_weights_source, *p_weights_dest;\r\n\tuint16 *p_normal_source,  *p_normal_dest;\r\n\tuint32 *p_colour_source,  *p_colour_dest;\r\n\tuint32 *p_coords_source,  *p_coords_dest;\r\n\tint    unpack_num;\r\n\tbool   seenMSCAL;\r\n\r\n\t// get start and end of vifcode packet\r\n\tp_code = pTag + 8;\r\n\tp_end  = pTag + 16 + (*(uint16 *)pTag << 4);\r\n\r\n\t// initialise state\r\n\taddr_diff = 0;\r\n\tunpack_num = -1;\r\n\tseenMSCAL  = true;\r\n\r\n\t// parse vifcodes\r\n\twhile (p_code < p_end)\r\n\t{\r\n\t\tif ((p_code[3] & 0x60) == 0x60)\t\t// if it's an unpack\r\n\t\t{\r\n\t\t\t// adjust ADDR field\r\n\t\t\taddr = *(uint16 *)p_code;\r\n\t\t\taddr -= addr_diff;\r\n\t\t\taddr &= 0x3FF;\r\n\t\t\t*(uint16 *)p_code = *(uint16 *)p_code & 0xFC00 | addr;\r\n\r\n\t\t\t// if we have a VU1_ADR(Jump) in a giftag, reset offset\r\n\t\t\tif (((uint16 *)p_code)[1]==0x6C01 && ((uint32 *)p_code)[1]==0x00008000 && ((uint32 *)p_code)[2]==0x00000052)\r\n\t\t\t\taddr_diff = 0;\r\n\r\n\t\t\t// look for vertex packets\r\n\t\t\tif (vif::WL==1 && vif::CL>1 && seenMSCAL)\r\n\t\t\t{\r\n\t\t\t\t// look for giftag\r\n\t\t\t\tif (unpack_num==-1)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_giftag = (uint32 *)p_code + 1;\r\n\t\t\t\t\tnloop = p_giftag[0] & 0x7FFF;\r\n\t\t\t\t\tnreg  = p_giftag[1] >> 28;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// look for vertex elements\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_unpack[unpack_num] = p_code;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// next element\r\n\t\t\t\tunpack_num++;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ((p_code[3] & 0x7F) == 0x14)\t\t// mscal\r\n\t\t\t{\r\n\t\t\t\tseenMSCAL = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// step to next vifcode\r\n\t\tp_code = vif::NextCode(p_code);\r\n\r\n\t\t// have we found all 5 unpacks of a vertex packet?\r\n\t\tif (unpack_num==5)\r\n\t\t{\r\n\t\t\t// perform compression...\r\n\r\n\t\t\t// set element pointers\r\n\t\t\tp_texcrds_source = p_texcrds_dest = (uint32 *)(p_unpack[0]+4);\r\n\t\t\tp_weights_source = p_weights_dest = (uint8  *)(p_unpack[1]+4);\r\n\t\t\tp_normal_source\t = p_normal_dest  = (uint16 *)(p_unpack[2]+4);\r\n\t\t\tp_colour_source\t = p_colour_dest  = (uint32 *)(p_unpack[3]+4);\r\n\t\t\tp_coords_source\t = p_coords_dest  = (uint32 *)(p_unpack[4]+4);\r\n\r\n\t\t\t// set datasize for tex coords\r\n\t\t\ttexcrds_size = ((p_unpack[0][3] & 0x07) == 0x04) ? 2 : 1;\r\n\r\n\t\t\t// loop over source vertices\r\n\t\t\tnum_squeezed = 0;\r\n\t\t\tfor (i=0; i<nloop; i++)\r\n\t\t\t{\r\n\t\t\t\t// skip if vertex is redundant\r\n\t\t\t\tif (   (i<=nloop-3)\t&& (p_coords_source[1] & 0x80000000)\r\n\t\t\t\t\t\t\t\t\t&& (p_coords_source[3] & 0x80000000)\r\n\t\t\t\t\t\t\t\t\t&& (p_coords_source[5] & 0x80000000)\r\n\t\t\t\t\t|| (i==nloop-2)\t&& (p_coords_source[1] & 0x80000000)\r\n\t\t\t\t\t\t\t\t\t&& (p_coords_source[3] & 0x80000000)\r\n\t\t\t\t\t|| (i==nloop-1)\t&& (p_coords_source[1] & 0x80000000))\r\n\t\t\t\t{\r\n\t\t\t\t\tp_texcrds_source += texcrds_size;\r\n\t\t\t\t\tp_weights_source += 3;\r\n\t\t\t\t\tp_normal_source  += 3;\r\n\t\t\t\t\tp_colour_source  += 1;\r\n\t\t\t\t\tp_coords_source\t += 2;\r\n\t\t\t\t\tnum_squeezed++;\r\n\t\t\t\t}\r\n\t\t\t\telse if (p_coords_source != p_coords_dest)\r\n\t\t\t\t// copy vertex\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_texcrds_dest++ = *p_texcrds_source++;\r\n\t\t\t\t\tif (texcrds_size==2)\r\n\t\t\t\t\t\t*p_texcrds_dest++ = *p_texcrds_source++;\r\n\t\t\t\t\t*p_weights_dest++ = *p_weights_source++;\r\n\t\t\t\t\t*p_weights_dest++ = *p_weights_source++;\r\n\t\t\t\t\t*p_weights_dest++ = *p_weights_source++;\r\n\t\t\t\t\t*p_normal_dest++  = *p_normal_source++;\r\n\t\t\t\t\t*p_normal_dest++  = *p_normal_source++;\r\n\t\t\t\t\t*p_normal_dest++  = *p_normal_source++;\r\n\t\t\t\t\t*p_colour_dest++  = *p_colour_source++;\r\n\t\t\t\t\t*p_coords_dest++  = *p_coords_source++;\r\n\t\t\t\t\t*p_coords_dest++  = *p_coords_source++;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t// just inc pointers\r\n\t\t\t\t{\r\n\t\t\t\t\tp_texcrds_source += texcrds_size;\r\n\t\t\t\t\tp_weights_source += 3;\r\n\t\t\t\t\tp_normal_source  += 3;\r\n\t\t\t\t\tp_colour_source  += 1;\r\n\t\t\t\t\tp_coords_source\t += 2;\r\n\t\t\t\t\tp_texcrds_dest\t += texcrds_size;\r\n\t\t\t\t\tp_weights_dest\t += 3;\r\n\t\t\t\t\tp_normal_dest\t += 3;\r\n\t\t\t\t\tp_colour_dest\t += 1;\r\n\t\t\t\t\tp_coords_dest\t += 2;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// reduce nloop\r\n\t\t\tnloop -= num_squeezed;\r\n\r\n\t\t\t// make sure there are at least 2 vertices left\r\n\t\t\tif (nloop < 2)\r\n\t\t\t{\r\n\t\t\t\tnum_squeezed -= 2-nloop;\r\n\t\t\t\tp_texcrds_dest += (2-nloop) * texcrds_size;\r\n\t\t\t\tp_weights_dest += (2-nloop) * 3;\r\n\t\t\t\tp_normal_dest  += (2-nloop) * 3;\r\n\t\t\t\tp_colour_dest  += (2-nloop) * 1;\r\n\t\t\t\tp_coords_dest  += (2-nloop) * 2;\r\n\t\t\t\tnloop = 2;\r\n\t\t\t}\r\n\r\n\t\t\t// adjust SIZE fields in unpacks\r\n\t\t\tfor (i=0; i<5; i++)\r\n\t\t\t{\r\n\t\t\t\tp_unpack[i][2] = nloop;\r\n\t\t\t}\r\n\r\n\t\t\t// pad the dead space after each unpack with vif NOPs\r\n\t\t\tfor (i=0; i<num_squeezed; i++)\r\n\t\t\t{\r\n\t\t\t\t*p_texcrds_dest++ = 0;\r\n\t\t\t\tif (texcrds_size==2)\r\n\t\t\t\t\t*p_texcrds_dest++ = 0;\r\n\t\t\t\t*p_weights_dest++ = 0;\r\n\t\t\t\t*p_weights_dest++ = 0;\r\n\t\t\t\t*p_weights_dest++ = 0;\r\n\t\t\t\t*p_normal_dest++  = 0;\r\n\t\t\t\t*p_normal_dest++  = 0;\r\n\t\t\t\t*p_normal_dest++  = 0;\r\n\t\t\t\t*p_colour_dest++  = 0;\r\n\t\t\t\t*p_coords_dest++  = 0;\r\n\t\t\t\t*p_coords_dest++  = 0;\r\n\t\t\t}\r\n\r\n\t\t\t// adjust NLOOP and SIZE in giftag\r\n\t\t\tp_giftag[0] = p_giftag[0] & 0xFFFF8000 | nloop;\r\n\t\t\tp_giftag[3] = nloop*nreg;\r\n\r\n\t\t\t// accumulate savings\r\n\t\t\taddr_diff += num_squeezed * 5;\r\n\r\n\t\t\t// reset for next vertex packet\r\n\t\t\tunpack_num = -1;\r\n\t\t\tseenMSCAL  = false;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// adjust vu-mem size in dma tag\r\n\tvumem_size = ((uint16 *)pTag)[1];\r\n\tvumem_size -= addr_diff;\r\n\tvumem_size &= 0x3FF;\r\n\t((uint16 *)pTag)[1] = ((uint16 *)pTag)[1] & 0xFC00 | vumem_size;\r\n\r\n}\r\n\r\n\r\n\r\n\r\nvoid dma::SqueezeNOP(uint8 *pTag)\r\n{\r\n\tuint8  *p_code, *p_end;\r\n\tuint32 *p_source, *p_dest;\r\n\r\n\t// get start and end of vifcode packet\r\n\tp_code = pTag + 8;\r\n\tp_end  = pTag + 16 + (*(uint16 *)pTag << 4);\r\n\r\n\t// setup\r\n\tp_source = p_dest = (uint32 *)p_code;\r\n\r\n\t// parse vifcodes\r\n\twhile (p_code < p_end)\r\n\t{\r\n\t\tif (p_code[3] == 0x00)\t// NOP\r\n\t\t{\r\n\t\t\tp_code = vif::NextCode(p_code);\r\n\t\t\tp_source++;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_code = vif::NextCode(p_code);\r\n\r\n\t\t\t// copy memory\r\n\t\t\twhile (p_source < (uint32 *)p_code)\r\n\t\t\t{\r\n\t\t\t\t*p_dest++ = *p_source++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// pad to qword boundary with nops\r\n\twhile ((uint)p_dest & 0xF)\r\n\t\t*p_dest++ = 0;\r\n\r\n\t// adjust dma size in dma tag\r\n\t((uint16 *)pTag)[0] = ((uint8 *)p_dest - pTag - 16) >> 4;\r\n}\r\n\r\n\r\n\r\n\r\n//---------------------------------\r\n//\t\tS T A T I C   D A T A\r\n//---------------------------------\r\n\r\nuint8 *\t\tdma::pBase;\t\t\t// base of dynamic DMA buffer for this frame\r\nuint8 *\t\tdma::pLoc;\t\t\t// current position in it that we are building DMA packets\r\nuint8 *\t\tdma::pTag;\r\nuint8 *\t\tdma::pPrebuiltBuffer;\r\nuint8 *\t\tdma::pDummyBuffer;\t\t// (Mick) used to simulate memory usage\r\nuint8 *\t\tdma::pRuntimeBuffer;\r\nuint8 *\t\tdma::pList[2];\r\nuint64 *\tdma::Gosubs;\r\nuint8 *\t\tdma::pSub;\r\ndma::eTag\tdma::ID;\r\nint    \t\tdma::sp;\r\nuint8 *\t\tdma::Stack[2];\r\nvoid *\t\tdma::sp_group;\r\nint\t\t\tdma::size;\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/dma.h",
    "content": "#ifndef __DMA_H\r\n#define __DMA_H\r\n\r\n#include \"render.h\"\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\nclass CGeomNode;\r\n\r\n\r\n\r\n#define PREBUILT_DMA_BUFFER_SIZE 32768\t\t    \t\t\r\n\r\n// Random crashes in the engine can frequntly be traced to DMA buffer overflow\r\n// We probably need to add some cheking for this.\r\n//#define SPLIT_SCREEN_DMA_BUFFER_SIZE  \t(675000 * 2)\t\t\t// split screen needs more\r\n//#define NON_DEBUG_DMA_BUFFER_SIZE  \t\t(500000 * 2)\t\t\t// non split screen needs less\r\n#define NON_DEBUG_DMA_BUFFER_SIZE  \t\t((int)((675000 * 2)&0xffffffe0))\t\t\t// non split screen needs less\r\n#define DEBUG_DMA_BUFFER_SIZE  \t\t\t((int)(16256000 & 0xffffffe0))\t\t\t\t// Mick, 12 MB for debugging....\r\n\r\nclass dma\r\n{\r\n\r\npublic:\r\n\r\n\tenum eTag\r\n\t{\trefe = 0,\r\n\t\tcnt  = 1,\r\n\t\tnext = 2,\r\n\t\tref  = 3,\r\n\t\trefs = 4,\r\n\t\tcall = 5,\r\n\t\tret  = 6,\r\n\t\tend  = 7\r\n\t};\r\n\r\n\tstruct SSortElement\r\n\t{\r\n\t\tfloat z;\r\n\t\tuint8 *address;\r\n\t};\r\n\r\n\t//-------------------------------------------\r\n\t//\t\tS T A T I C   F U N C T I O N S\r\n\t//-------------------------------------------\r\n\r\n\tstatic void   Align(uint Offset, uint Boundary);\r\n\tstatic void   Align();\r\n\tstatic void   Store32(uint32 Data);\r\n\tstatic void   Store32(uint32 Data1, uint32 Data2 );\r\n\tstatic void   Store32(uint32 Data1, uint32 Data2, uint32 Data3 );\r\n\tstatic void   Store32(uint32 Data1, uint32 Data2, uint32 Data3, uint32 Data4 );\r\n\tstatic void   Store64(uint64 Data);\r\n\tstatic void   Tag(eTag ID, uint QWC, uint ADDR);\r\n\tstatic void   BeginTag(eTag ID, uint ADDR);\r\n\tstatic void   EndTag(void);\r\n\tstatic void   BeginSub(eTag ID);\r\n\tstatic uint64 EndSub(void);\r\n\tstatic void   Gosub(uint Num, uint Path);\r\n\tstatic void   BeginSub3D(void);\r\n\tstatic uint8 *EndSub3D(void);\r\n\tstatic void   Gosub3D(uint8 *pSub, uint RenderFlags);\r\n\tstatic uint8 *NextTag(uint8 *pTag, bool stepInto);\r\n\tstatic int    Cmp(const void *p1, const void *p2);\r\n\tstatic uint8 *SortGroup(uint8 *pList);\r\n\tstatic void   BeginList(void *pGroup);\r\n\tstatic void   EndList(void *pGroup);\r\n\tstatic void   SetList(void *pGroup);\r\n\tstatic void   ReallySetList(void *pGroup);\r\n\tstatic int    GetDmaSize(uint8 *pTag);\r\n\tstatic int    GetNumVertices(uint8 *pTag);\r\n\tstatic int    GetNumTris(uint8 *pTag);\r\n\tstatic void   Copy(uint8 *pTag, uint8 *pDest);\r\n\tstatic int    GetBitLengthXYZ(uint8 *pTag);\r\n\tstatic void   TransferValues(uint8 *pTag, uint8 *pArray, int size, int dir, uint32 vifcodeMask, uint32 vifcodePattern);\r\n\tstatic void   TransferColours(uint8 *pTag, uint8 *pArray, int dir);\r\n\tstatic void   ExtractXYZs(uint8 *pTag, uint8 *pArray);\r\n\tstatic void   ReplaceXYZs(uint8 *pTag, uint8 *pArray, bool skipW = false);\r\n\tstatic void   ExtractRGBAs(uint8 *pTag, uint8 *pArray);\r\n\tstatic void   ReplaceRGBAs(uint8 *pTag, uint8 *pArray);\r\n\tstatic void   ExtractSTs(uint8 *pTag, uint8 *pArray);\r\n\tstatic void   ReplaceSTs(uint8 *pTag, uint8 *pArray);\r\n\tstatic void   TransformSTs(uint8 *pTag, const Mth::Matrix &mat);\r\n\tstatic void\t  ConvertXYZToFloat(Mth::Vector &vec, sint32 *p_xyz);\r\n\tstatic void\t  ConvertXYZToFloat(Mth::Vector &vec, sint32 *p_xyz, const Mth::Vector &center);\r\n\tstatic void\t  ConvertXYZToFloat(Mth::Vector &vec, sint32 *p_xyz, const sint32 *p_center);\r\n\tstatic void\t  ConvertSTToFloat(float & s, float & t, sint32 *p_st);\r\n\tstatic void\t  ConvertFloatToXYZ(sint32 *p_xyz, Mth::Vector &vec);\r\n\tstatic void\t  ConvertFloatToXYZ(sint32 *p_xyz, Mth::Vector &vec, const Mth::Vector &center);\r\n\tstatic void\t  ConvertFloatToXYZ(sint32 *p_xyz, Mth::Vector &vec, const sint32 *p_center);\r\n\tstatic void\t  ConvertFloatToST(sint32 *p_st, float & s, float & t);\r\n\tstatic void   SqueezeADC(uint8 *pTag);\r\n\tstatic void   SqueezeNOP(uint8 *pTag);\r\n\r\n\r\n\t//---------------------------------\r\n\t//\t\tS T A T I C   D A T A\r\n\t//---------------------------------\r\n\r\n\tstatic uint8 *\t\tpBase;\r\n\tstatic uint8 *\t\tpLoc;\r\n\tstatic uint8 *\t\tpTag;\r\n\tstatic uint8 *\t\tpPrebuiltBuffer;\r\n\tstatic uint8 *\t\tpDummyBuffer;\r\n\tstatic uint8 *\t\tpRuntimeBuffer;\r\n\tstatic uint8 *\t\tpList[2];\r\n\tstatic uint64 *\t\tGosubs;\r\n\tstatic uint8 *\t\tpSub;\r\n\tstatic eTag\t\t\tID;\r\n\tstatic int\t\t\tsp;\r\n\tstatic uint8 *\t\tStack[2];\r\n\tstatic void *\t\tsp_group;\r\n\tstatic int\t\t\tsize;\r\n\r\n}; // class dma\r\n\r\n\r\n// -------------------------------------------------\r\n//        INLINE FUNCTIONS\r\n// -------------------------------------------------\r\n\r\n\r\n\r\n// align to Boundary, then add Offset\r\n// Boundary must be a power of 2\r\n\r\ninline void dma::Align(uint Offset, uint Boundary)\r\n{\r\n\tuint8 *NewDmaLoc = (uint8 *)((((uint)pLoc - Offset + Boundary - 1) & ((uint)(-(int)Boundary))) + Offset);\r\n\twhile (pLoc < NewDmaLoc)\r\n\t\t*pLoc++ = 0;\r\n}\r\n\r\n\r\n// quick version for dma list building; assumes pLoc already word-aligned and you want it quadword-aligned\r\n\r\ninline void dma::Align()\r\n{\r\n\twhile ((uint)pLoc & 0xF)\r\n\t{\r\n\t\t*(uint32 *)pLoc = 0;\r\n\t\tpLoc += 4;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n// store a word\r\n\r\ninline void dma::Store32(uint32 Data)\r\n{\r\n\t#if 0\r\n\t*(uint32 *)pLoc = Data;\r\n\tpLoc += 4;\r\n\t#else\r\n\tuint32 *p_loc = (uint32*)pLoc;\r\n\tp_loc[0] = Data;\r\n\tpLoc = (uint8*) (p_loc + 1);\r\n\t#endif\t\r\n}\r\n\r\n// Store two words, quicker this way, as we only have to update pLoc once\r\ninline void dma::Store32(uint32 Data1, uint32 Data2)\r\n{\r\n\tuint32 *p_loc = (uint32*)pLoc;\r\n\tp_loc[0] = Data1;\r\n\tp_loc[1] = Data2;\r\n\tpLoc = (uint8*) (p_loc + 2);\r\n}\r\n\r\n// Store three words, quicker this way, as we only have to update pLoc once\r\ninline void dma::Store32(uint32 Data1, uint32 Data2, uint32 Data3)\r\n{\r\n\tuint32 *p_loc = (uint32*)pLoc;\r\n\tp_loc[0] = Data1;\r\n\tp_loc[1] = Data2;\r\n\tp_loc[2] = Data3;\r\n\tpLoc = (uint8*) (p_loc + 3);\r\n}\r\n\r\n// Store four words, quicker this way, as we only have to update pLoc once\r\ninline void dma::Store32(uint32 Data1, uint32 Data2, uint32 Data3, uint32 Data4)\r\n{\r\n\tuint32 *p_loc = (uint32*)pLoc;\r\n\tp_loc[0] = Data1;\r\n\tp_loc[1] = Data2;\r\n\tp_loc[2] = Data3;\r\n\tp_loc[3] = Data4;\r\n\tpLoc = (uint8*) (p_loc + 4);\r\n}\r\n\r\n\r\n// store a dword\r\n\r\ninline void dma::Store64(uint64 Data)\r\n{\r\n\t((uint32 *)pLoc)[0] = (uint32)Data;\t\t// break into 2 words\r\n\t((uint32 *)pLoc)[1] = (uint32)(Data>>32);\t// because pLoc is only word-aligned\r\n\tpLoc += 8;\r\n}\r\n\r\n\r\n\r\n//--------------------------\r\n//\t\tD M A   T A G S\r\n//--------------------------\r\n\r\n\r\n\r\n// generic source chain tag\r\n//\r\n//\t 63  62                        32 31  30  28 27 26 25     16 15            0\r\n//\tĿ\r\n//\tSPR          ADDR          0000IRQ  ID   PCE     -          QWC      \r\n//\t\r\n\r\ninline void dma::Tag(eTag ID, uint QWC, uint ADDR)\r\n{\r\n\t// assumes pLoc already qword aligned\r\n\tpTag = pLoc;\r\n\tStore32(ID<<28 | QWC, ADDR);\r\n}\r\n\r\n\r\n// Begin-End style\r\n\r\ninline void dma::BeginTag(eTag ID, uint ADDR)\r\n{\r\n\t// assumes pLoc already qword aligned\r\n\tpTag = pLoc;\t\t\t\t\t\t\t\t\t// record tag location for patching later\r\n\tStore32(ID<<28, ADDR);\r\n}\r\n\r\n\r\n// Begin-End style\r\n\r\ninline void dma::EndTag(void)\r\n{\r\n\tuint ID = (*(uint32 *)pTag >> 28) & 7;\t\t\t\t// get the tag ID field\r\n\tAlign();\t\t\t\t\t\t\t\t\t\t\t// align to qword boundary\r\n\tif (ID!=ref && ID!=refe && ID!=refs)\t\t\t\t// check that the QWC is patchable\r\n\t{\r\n\t\t((uint16 *)pTag)[0] = (pLoc - pTag - 8) >> 4;\r\n\t}\r\n}\r\n\r\n\r\ninline void\t dma::ConvertXYZToFloat(Mth::Vector &vec, sint32 *p_xyz)\r\n{\r\n\tvec[X] = ((float) *(p_xyz++)) * RECIPROCAL_SUB_INCH_PRECISION;\r\n\tvec[Y] = ((float) *(p_xyz++)) * RECIPROCAL_SUB_INCH_PRECISION;\r\n\tvec[Z] = ((float) *(p_xyz)  ) * RECIPROCAL_SUB_INCH_PRECISION;\r\n\tvec[W] = 1.0f;\r\n}\r\n\r\ninline void\t dma::ConvertXYZToFloat(Mth::Vector &vec, sint32 *p_xyz, const Mth::Vector &center)\r\n{\r\n\tvec[X] = (((float) *(p_xyz++)) * RECIPROCAL_SUB_INCH_PRECISION) + center[X];\r\n\tvec[Y] = (((float) *(p_xyz++)) * RECIPROCAL_SUB_INCH_PRECISION) + center[Y];\r\n\tvec[Z] = (((float) *(p_xyz)  ) * RECIPROCAL_SUB_INCH_PRECISION) + center[Z];\r\n\tvec[W] = 1.0f;\r\n}\r\n\r\ninline void\t dma::ConvertXYZToFloat(Mth::Vector &vec, sint32 *p_xyz, const sint32 *p_center)\r\n{\r\n\tvec[X] = ((float) (*(p_xyz++) + *(p_center++))) * RECIPROCAL_SUB_INCH_PRECISION;\r\n\tvec[Y] = ((float) (*(p_xyz++) + *(p_center++))) * RECIPROCAL_SUB_INCH_PRECISION;\r\n\tvec[Z] = ((float) (*(p_xyz)   + *(p_center)  )) * RECIPROCAL_SUB_INCH_PRECISION;\r\n\tvec[W] = 1.0f;\r\n}\r\n\r\ninline void\t dma::ConvertSTToFloat(float & s, float & t, sint32 *p_st)\r\n{\r\n\ts = ((float) *(p_st++)) * (1.0f / 4096.0f);\r\n\tt = ((float) *(p_st)  ) * (1.0f / 4096.0f);\r\n}\r\n\r\ninline void\t dma::ConvertFloatToXYZ(sint32 *p_xyz, Mth::Vector &vec)\r\n{\r\n\t*(p_xyz++) = (sint32) (vec[X] * SUB_INCH_PRECISION);\r\n\t*(p_xyz++) = (sint32) (vec[Y] * SUB_INCH_PRECISION);\r\n\t*(p_xyz)   = (sint32) (vec[Z] * SUB_INCH_PRECISION);\r\n}\r\n\r\ninline void\t dma::ConvertFloatToXYZ(sint32 *p_xyz, Mth::Vector &vec, const sint32 *p_center)\r\n{\r\n\t*(p_xyz++) = ((sint32) (vec[X] * SUB_INCH_PRECISION)) - *(p_center++);\r\n\t*(p_xyz++) = ((sint32) (vec[Y] * SUB_INCH_PRECISION)) - *(p_center++);\r\n\t*(p_xyz)   = ((sint32) (vec[Z] * SUB_INCH_PRECISION)) - *(p_center);\r\n}\r\n\r\ninline void\t dma::ConvertFloatToST(sint32 *p_st, float & s, float & t)\r\n{\r\n\t*(p_st++) = (sint32) (s * 4096.0f);\r\n\t*(p_st)   = (sint32) (t * 4096.0f);\r\n}\r\n\r\ninline void dma::SetList(void *pGroup)\r\n{\r\n\t// do nothing if we're already in the right dma context\r\n\t// (Mick) This part has been moved to an inline function \r\n\t// since the overhead of setting up the stack frame \r\n\t// is large, this is a more efficient way of taking advantage of\r\n\t// group coherency.   This represents a 25% speed improvmeent for this function\r\n\t// just 0.25% of a frame.  But every little helps.\r\n\tif (sp_group != pGroup)\r\n\t{\r\n\t\tReallySetList(pGroup);\r\n\t}\r\n}\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n#endif // __DMA_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/dmacalls.cpp",
    "content": "#include <core/defines.h>\r\n#include <math.h>\r\n#include <sifdev.h>\r\n#include <stdio.h>\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n#include \"material.h\"\r\n#include \"dmacalls.h\"\r\n#include \"vu1code.h\"\r\n#include \"switches.h\"\r\n#include \"render.h\"\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\nuint8 *pSubroutine;\r\n\r\n\r\nuint32\t*p_patch_PRMODE;\r\nuint32\t*p_patch_ALPHA;\r\nuint32\t*p_patch_ALPHA2;\r\n\r\n//-----------------------------------------------------------\r\n//\t\tH A N D L I N G   D M A   S U B R O U T I N E S\r\n//-----------------------------------------------------------\r\n\r\n\r\n// begin a subroutine\r\n\r\nuint8 *BeginDmaSubroutine(void)\r\n{\r\n\tdma::Align(0,16);\r\n\tpSubroutine = dma::pLoc;\r\n\tvu1::Loc = vu1::Buffer = 0;\r\n\treturn pSubroutine;\r\n}\r\n\r\n\r\n// end a subroutine and return its address\r\n\r\nvoid EndDmaSubroutine(void)\r\n{\r\n\t((uint16 *)pSubroutine)[1] |= vu1::Loc&0x3FF;\r\n}\r\n\r\n#if 0\r\n\r\n// call a subroutine, Path1\r\n\r\nvoid Gosub1(uint Num)\r\n{\r\n\tuint8 *pSub = Subroutines[Num];\r\n\tdma::Tag(dma::call, 0, (uint)pSub);\r\n\tvif::BASE(vu1::Loc);\r\n\tvif::OFFSET(0);\r\n\tvu1::Loc += ((uint16 *)pSub)[1];\r\n}\r\n\r\n\r\n// call a subroutine, Path2\r\n\r\nvoid Gosub2(uint Num)\r\n{\r\n\tdma::Tag(dma::call, 0, (uint)Subroutines[Num]);\r\n\tvif::NOP();\r\n\tvif::NOP();\r\n}\r\n\r\n#endif\r\n\r\n\r\n\r\n//-----------------------------------------\r\n//\t\tD M A   S U B R O U T I N E S\r\n//-----------------------------------------\r\n\r\n\r\n\r\nvoid BuildDmaSubroutines(void)\r\n{\r\n\t//-------------------------------\r\n\t//\t\tC L E A R   V R A M\r\n\t//-------------------------------\r\n\r\n\tdma::BeginSub(dma::next);\r\n\tdma::BeginTag(dma::end,0);\r\n\tvif::BeginDIRECT();\r\n\tgif::BeginTag2(gs::A_D, 1, PACKED, SPRITE, 1);\r\n\tgs::Reg2(gs::FRAME_1,\t\tPackFRAME(0,16,PSMCT32,0));\r\n\tgs::Reg2(gs::ZBUF_1,\t\tPackZBUF(0,0,1));\r\n\tgs::Reg2(gs::TEST_1,\t\tPackTEST(0,0,0,0,0,0,1,ZALWAYS));\r\n\tgs::Reg2(gs::XYOFFSET_1,\tPackXYOFFSET(0,0));\r\n\tgs::Reg2(gs::SCISSOR_1,\t\tPackSCISSOR(0,0x7FF,0,0x7FF));\r\n\tgs::Reg2(gs::PRMODECONT,\tPackPRMODECONT(1));\r\n\tgs::Reg2(gs::SCANMSK,\t\tPackSCANMSK(0));\r\n\tgs::Reg2(gs::FBA_1,\t\t\tPackFBA(0));\r\n\tgs::Reg2(gs::DTHE,\t\t\tPackDTHE(0));\r\n\tgs::Reg2(gs::TEXA,\t\t\tPackTEXA(0x00,0,0x80));\r\n\tgs::Reg2(gs::RGBAQ,\t\t\tPackRGBAQ(0,0,0,0,0));\r\n\tgs::Reg2(gs::XYZ2,\t\t\tPackXYZ(0,0,0));\r\n\tgs::Reg2(gs::XYZ2,\t\t\tPackXYZ(0x3FFF,0x3FFF,0));\r\n\tgs::Reg2(gs::TEXFLUSH,\t\t0);\r\n\tgif::EndTag2(1);\r\n\tvif::EndDIRECT();\r\n\tvif::FLUSH();\r\n\tdma::EndTag();\r\n\tdma::Gosubs[CLEAR_VRAM] = dma::EndSub();\r\n\r\n\r\n\r\n\t//---------------------------------------\r\n\t//\t\tF L I P   A N D   C L E A R\r\n\t//---------------------------------------\r\n\r\n\t#define CLEAR_COLOUR 0x00706050\r\n\t\r\n\tuint32 screen_w = HRES << 4;\r\n\tuint32 screen_h = VRES << 4;\r\n\r\n\t// begin Path2 subroutine\r\n\tdma::BeginSub(dma::ref);\r\n\r\n\t// wait in case something's still drawing from last frame\r\n\tvif::FLUSHA();\r\n\r\n\t// send everything PATH2\r\n\tvif::BeginDIRECT();\r\n\r\n\t// register setup\r\n\tgif::BeginTag2(gs::A_D, 1, PACKED, 0, 0);\r\n\tp_patch_ALPHA = (uint32*) (dma::pLoc + 4);\r\n\tgs::Reg2(gs::ALPHA_1,\t\tPackALPHA(0,1,2,1,128));\t\t// tweak this alpha for motion blur!\r\n\tgs::Reg2(gs::DIMX,\t\t\tPackDIMX(-4,0,-3,1,2,-2,3,-1,-3,1,-4,0,3,-1,2,-2));\r\n\tgs::Reg2(gs::DTHE,\t\t\tPackDTHE(1));\r\n\tgs::Reg2(gs::FBA_1,\t\t\tPackFBA(0));\r\n\tgs::Reg2(gs::FRAME_1,\t\tPackFRAME(DISPLAY_START,HRES/64,PSMCT16S,0x00000000));\r\n\tgs::Reg2(gs::PRMODECONT,\tPackPRMODECONT(1));\r\n\tgs::Reg2(gs::SCANMSK,\t\tPackSCANMSK(0));\r\n\tgs::Reg2(gs::SCISSOR_1,\t\tPackSCISSOR(0,HRES - 1,0,VRES - 1));\r\n\tgs::Reg2(gs::TEST_1,\t\tPackTEST(0,0,0,0,0,0,1,ZALWAYS));\r\n\tgs::Reg2(gs::TEX0_1,\t\tPackTEX0(0,HRES/64,PSMCT32,10,10,1,DECAL,0,0,0,0,0));\r\n\tgs::Reg2(gs::TEX1_1,\t\tPackTEX1(1,0,NEAREST,NEAREST,0,0,0));\r\n\tgs::Reg2(gs::TEXFLUSH,\t\t0);\r\n\tgs::Reg2(gs::XYOFFSET_1,\tPackXYOFFSET(0,0));\r\n\tgs::Reg2(gs::ZBUF_1,\t\tPackZBUF(ZBUFFER_START,PSMZ24,0));\r\n\tgif::EndTag2(0);\r\n\r\n\t// using a set of screen-high textured sprites, copy draw buffer to disp buffer and clear z-buffer\r\n\tgif::BeginTag2(gs::UV|gs::XYZ2<<4, 2, PACKED, SPRITE|TME|FST|ABE, 1);\r\n\tfor (uint32 x=0x0000; x<screen_w; x+=0x0200)\r\n\t{\r\n\t\tvif::StoreV4_32(x+8,      0x0008,     0, 0);\t\t// UV\r\n\t\tvif::StoreV4_32(x,        0x0000,     0, 0);\t\t// XYZ2\r\n\t\tvif::StoreV4_32(x+0x0208, screen_h+8, 0, 0);\t\t// UV\r\n\t\tvif::StoreV4_32(x+0x0200, screen_h,   0, 0);\t\t// XYZ2\r\n\t}\r\n\tgif::EndTag2(0);\r\n\r\n\t#if 1\t// switch this off if we don't need to clear the screen\r\n\t// set up state for screen clear\r\n\tgif::BeginTag2(gs::A_D, 1, PACKED, 0, 0);\r\n\tgs::Reg2(gs::DTHE,\t\t\tPackDTHE(0));\r\n\tgs::Reg2(gs::FRAME_1,\t\tPackFRAME(0,HRES/64,PSMCT32,0x00000000));\r\n\tgs::Reg2(gs::ZBUF_1,\t\tPackZBUF(FRAME_START + (FRAME_SIZE / 2),PSMZ32,0));\r\n\tgs::Reg2(gs::RGBAQ,\t\t\tCLEAR_COLOUR);\r\n\tgif::EndTag2(1);\r\n\r\n\t// an optimised screen clear that sneakily uses the z-buffer to\r\n\t// clear the lower half of the screen\r\n\tgif::BeginTag2(gs::XYZ2, 1, PACKED, SPRITE, 1);\r\n\tfor (uint32 x=0x0000; x<screen_w; x+=0x0200)\r\n\t{\r\n\t\tvif::StoreV4_32(x,        0x0000    , 0, \t\t\t0);\t\t// XYZ2\r\n\t\tvif::StoreV4_32(x+0x0200, screen_h/2, CLEAR_COLOUR, 0);\t\t// XYZ2\r\n\t}\r\n\tgif::EndTag2(1);\r\n\t#endif\r\n\r\n\tvif::EndDIRECT();\r\n\r\n\t// done\r\n\tdma::Gosubs[FLIP_N_CLEAR] = dma::EndSub();\r\n\t\r\n\r\n\r\n\r\n\t//---------------------------------------------------------\r\n\t//\t\tF L I P   A N D   C L E A R\t  L E T T E R B O X E D\r\n\t//---------------------------------------------------------\r\n\r\n\r\n\t// begin Path2 subroutine\r\n\tdma::BeginSub(dma::ref);\r\n\r\n\t// wait in case something's still drawing from last frame\r\n\tvif::FLUSH();\r\n\r\n\t// send everything PATH2\r\n\tvif::BeginDIRECT();\r\n\r\n\r\n\t// Render in letterboxed mode\r\n\t// Need to crop 0.25 of the height, so 0.125 off top and bottom\r\n\t\r\n\tfloat crop = screen_h * 0.125;\r\n//\tfloat top_x = 0;\r\n//\tfloat bot_x = 0;\r\n\tfloat top_y = crop;\r\n\tfloat bot_y = screen_h-crop;\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\t// register setup\r\n\tgif::BeginTag2(gs::A_D, 1, PACKED, 0, 0);\r\n\tp_patch_ALPHA2 = (uint32*) (dma::pLoc + 4);\r\n\tgs::Reg2(gs::ALPHA_1,\t\tPackALPHA(0,1,2,1,128));\t\t// tweak this alpha for motion blur!\r\n\tgs::Reg2(gs::DIMX,\t\t\tPackDIMX(-4,0,-3,1,2,-2,3,-1,-3,1,-4,0,3,-1,2,-2));\r\n\tgs::Reg2(gs::DTHE,\t\t\tPackDTHE(1));\r\n\tgs::Reg2(gs::FBA_1,\t\t\tPackFBA(0));\r\n\tgs::Reg2(gs::FRAME_1,\t\tPackFRAME(DISPLAY_START,HRES/64,PSMCT16S,0x00000000));\r\n\tgs::Reg2(gs::PRMODECONT,\tPackPRMODECONT(1));\r\n\tgs::Reg2(gs::RGBAQ,\t\t\tPackRGBAQ(0,0,0,0,0));\r\n\tgs::Reg2(gs::SCANMSK,\t\tPackSCANMSK(0));\r\n\tgs::Reg2(gs::SCISSOR_1,\t\tPackSCISSOR(0,HRES - 1,0,VRES - 1));\r\n\tgs::Reg2(gs::TEST_1,\t\tPackTEST(0,0,0,0,0,0,1,ZALWAYS));\r\n\tgs::Reg2(gs::TEX0_1,\t\tPackTEX0(0,HRES/64,PSMCT32,10,10,1,DECAL,0,0,0,0,0));\r\n\tgs::Reg2(gs::TEX1_1,\t\tPackTEX1(1,0,NEAREST,NEAREST,0,0,0));\r\n\tgs::Reg2(gs::TEXFLUSH,\t\t0);\r\n\tgs::Reg2(gs::XYOFFSET_1,\tPackXYOFFSET(0,0));\r\n\tgs::Reg2(gs::ZBUF_1,\t\tPackZBUF(ZBUFFER_START,PSMZ24,0));\r\n\tgif::EndTag2(0);\r\n\r\n\r\n// Clear the black bars on the screen\r\n\r\n\tgif::BeginTag2(gs::XYZ2, 1, PACKED, SPRITE, 1);\r\n\tfor (uint32 x=0x0000; x<screen_w; x+=0x0200)\r\n\t{\r\n\t\tvif::StoreV4_32(x,        0x0000    , 0, 0);\t\t// XYZ2\r\n\t\tvif::StoreV4_32(x+0x0200, top_y, 0, 0);\t\t\t\t// XYZ2\r\n\t}\r\n\tfor (uint32 x=0x0000; x<screen_w; x+=0x0200)\r\n\t{\r\n\t\tvif::StoreV4_32(x,        bot_y   , 0, 0);\t\t// XYZ2\r\n\t\tvif::StoreV4_32(x+0x0200, screen_h, 0, 0);\t\t\t// XYZ2\r\n\t}\r\n\tgif::EndTag2(1);\r\n\r\n\r\n//\tfloat step = (bot_x - top_x)/16;\r\n\t\r\n\t// screen_w will be either 640*16 = 10240 = 0x2800\r\n\t//                      or 512*16 =  8192 = 0x2000\r\n\t \r\n\r\n\t\r\n\t// using a set of screen-high textured sprites, copy draw buffer to disp buffer and clear z-buffer\r\n\tgif::BeginTag2(gs::UV|gs::XYZ2<<4, 2, PACKED, SPRITE|TME|FST|ABE, 1);\r\n\tfor (uint32 x=0x0000; x<screen_w; x+=0x0200)\r\n\t{\r\n\t\tvif::StoreV4_32(x+8,      0x0008,     0, 0);\t\t// UV\r\n\t\tvif::StoreV4_32(x,        top_y\t,     0, 0);\t\t// XYZ2\r\n\t\tvif::StoreV4_32(x+0x0208, screen_h+8, 0, 0);\t\t// UV\r\n\t\tvif::StoreV4_32(x+0x0200, bot_y,   0, 0);\t\t// XYZ2\r\n\t}\t\t\t\t\t\t\t\t\t  \r\n\tgif::EndTag2(0);\r\n\r\n\t// register setup\r\n\tgif::BeginTag2(gs::A_D, 1, PACKED, 0, 0);\r\n\tgs::Reg2(gs::DTHE,\t\t\tPackDTHE(0));\r\n\tgs::Reg2(gs::FRAME_1,\t\tPackFRAME(ZBUFFER_START,HRES/64,PSMCT32,0xFF000000));\r\n\tgs::Reg2(gs::PRMODECONT,\tPackPRMODECONT(1));\r\n\tgs::Reg2(gs::RGBAQ,\t\t\t0);\r\n\tgs::Reg2(gs::SCANMSK,\t\tPackSCANMSK(0));\r\n\tgs::Reg2(gs::SCISSOR_1,\t\tPackSCISSOR(0,HRES - 1,0,VRES - 1));\r\n\tgs::Reg2(gs::TEST_1,\t\tPackTEST(0,0,0,0,0,0,1,ZALWAYS));\r\n\tgs::Reg2(gs::XYOFFSET_1,\tPackXYOFFSET(0,0));\r\n\tgs::Reg2(gs::ZBUF_1,\t\tPackZBUF(ZBUFFER_START + (ZBUFFER_SIZE / 2),PSMZ24,0));\r\n\tgif::EndTag2(1);\r\n\r\n\t// an optimised z-buffer clear that sneakily uses the frame buffer to clear the upper half\r\n\tgif::BeginTag2(gs::XYZ2, 1, PACKED, SPRITE, 1);\r\n\tfor (uint32 x=0x0000; x<screen_w; x+=0x0200)\r\n\t{\r\n\t\tvif::StoreV4_32(x,        0x0000    , 0, 0);\t\t// XYZ2\r\n\t\tvif::StoreV4_32(x+0x0200, screen_h/2, 0, 0);\t\t// XYZ2\r\n\t}\r\n\tgif::EndTag2(1);\r\n\r\n\r\n\t#if 1\t// switch this off if we don't need to clear the screen\r\n\t// set up state for screen clear\r\n\tgif::BeginTag2(gs::A_D, 1, PACKED, 0, 0);\r\n\tgs::Reg2(gs::DTHE,\t\t\tPackDTHE(0));\r\n\tgs::Reg2(gs::FRAME_1,\t\tPackFRAME(0,HRES/64,PSMCT32,0x00000000));\r\n\tgs::Reg2(gs::ZBUF_1,\t\tPackZBUF(FRAME_START + (FRAME_SIZE / 2),PSMZ32,0));\r\n\tgs::Reg2(gs::RGBAQ,\t\t\tCLEAR_COLOUR);\r\n\tgif::EndTag2(1);\r\n\r\n\t// an optimised screen clear that sneakily uses the z-buffer to\r\n\t// clear the lower half of the screen\r\n\tgif::BeginTag2(gs::XYZ2, 1, PACKED, SPRITE, 1);\r\n\tfor (uint32 x=0x0000; x<screen_w; x+=0x0200)\r\n\t{\r\n\t\tvif::StoreV4_32(x,        0x0000    , 0, \t\t\t0);\t\t// XYZ2\r\n\t\tvif::StoreV4_32(x+0x0200, screen_h/2, CLEAR_COLOUR, 0);\t\t// XYZ2\r\n\t}\r\n\tgif::EndTag2(1);\r\n\t#endif\r\n\r\n\tvif::EndDIRECT();\r\n\r\n\t// done\r\n\tdma::Gosubs[FLIP_N_CLEAR_LETTERBOX] = dma::EndSub();\r\n\r\n\r\n\r\n\r\n\r\n\t//---------------------------------------\r\n\t//\t\tC L E A R   S C R E E N\r\n\t//---------------------------------------\r\n\r\n\t// begin Path2 subroutine\r\n\tdma::BeginSub(dma::ref);\r\n\r\n\t// send everything PATH2\r\n\tvif::BeginDIRECT();\r\n\r\n\t// register setup\r\n\tgif::BeginTag2(gs::A_D, 1, PACKED, 0, 0);\r\n\tgs::Reg2(gs::DTHE,\t\t\tPackDTHE(0));\r\n\tgs::Reg2(gs::FBA_1,\t\t\tPackFBA(0));\r\n\tgs::Reg2(gs::FRAME_1,\t\tPackFRAME(0,HRES/64,PSMCT32,0x00000000));\r\n\tgs::Reg2(gs::PRMODECONT,\tPackPRMODECONT(1));\r\n\tgs::Reg2(gs::RGBAQ,\t\t\tCLEAR_COLOUR);\r\n\tgs::Reg2(gs::SCANMSK,\t\tPackSCANMSK(0));\r\n\tgs::Reg2(gs::SCISSOR_1,\t\tPackSCISSOR(0,HRES - 1,0,VRES - 1));\r\n\tgs::Reg2(gs::TEST_1,\t\tPackTEST(0,0,0,0,0,0,1,ZALWAYS));\r\n\tgs::Reg2(gs::XYOFFSET_1,\tPackXYOFFSET(0,0));\r\n\tgs::Reg2(gs::ZBUF_1,\t\tPackZBUF(FRAME_START + (FRAME_SIZE / 2),PSMZ32,0));\r\n\tgif::EndTag2(1);\r\n\r\n\t// an optimised screen clear that sneakily uses the z-buffer to clear the lower half\r\n\tgif::BeginTag2(gs::XYZ2, 1, PACKED, SPRITE, 1);\r\n\tfor (uint32 x=0x0000; x<screen_w; x+=0x0200)\r\n\t{\r\n\t\tvif::StoreV4_32(x,        0x0000    , 0, \t\t\t0);\t\t// XYZ2\r\n\t\tvif::StoreV4_32(x+0x0200, screen_h/2, CLEAR_COLOUR, 0);\t\t// XYZ2\r\n\t}\r\n\tgif::EndTag2(1);\r\n\r\n\tvif::EndDIRECT();\r\n\r\n\t// done\r\n\tdma::Gosubs[CLEAR_SCREEN] = dma::EndSub();\r\n\r\n\r\n\r\n\t//---------------------------------------\r\n\t//\t\tC L E A R   Z - B U F F E R\r\n\t//---------------------------------------\r\n\r\n\t// begin Path2 subroutine\r\n\tdma::BeginSub(dma::ref);\r\n\r\n\t// send everything PATH2\r\n\tvif::BeginDIRECT();\r\n\r\n\t// register setup\r\n\tgif::BeginTag2(gs::A_D, 1, PACKED, 0, 0);\r\n\tgs::Reg2(gs::DTHE,\t\t\tPackDTHE(0));\r\n\tgs::Reg2(gs::FRAME_1,\t\tPackFRAME(ZBUFFER_START,HRES/64,PSMCT32,0xFF000000));\r\n\tgs::Reg2(gs::PRMODECONT,\tPackPRMODECONT(1));\r\n\tgs::Reg2(gs::RGBAQ,\t\t\t0);\r\n\tgs::Reg2(gs::SCANMSK,\t\tPackSCANMSK(0));\r\n\tgs::Reg2(gs::SCISSOR_1,\t\tPackSCISSOR(0,HRES - 1,0,VRES - 1));\r\n\tgs::Reg2(gs::TEST_1,\t\tPackTEST(0,0,0,0,0,0,1,ZALWAYS));\r\n\tgs::Reg2(gs::XYOFFSET_1,\tPackXYOFFSET(0,0));\r\n\tgs::Reg2(gs::ZBUF_1,\t\tPackZBUF(ZBUFFER_START + (ZBUFFER_SIZE / 2),PSMZ24,0));\r\n\tgif::EndTag2(1);\r\n\r\n\t// an optimised z-buffer clear that sneakily uses the frame buffer to clear the upper half\r\n\tgif::BeginTag2(gs::XYZ2, 1, PACKED, SPRITE, 1);\r\n\tfor (uint32 x=0x0000; x<screen_w; x+=0x0200)\r\n\t{\r\n\t\tvif::StoreV4_32(x,        0x0000    , 0, 0);\t\t// XYZ2\r\n\t\tvif::StoreV4_32(x+0x0200, screen_h/2, 0, 0);\t\t// XYZ2\r\n\t}\r\n\tgif::EndTag2(1);\r\n\r\n\tvif::EndDIRECT();\r\n\r\n\t// done\r\n\tdma::Gosubs[CLEAR_ZBUFFER] = dma::EndSub();\r\n\r\n\r\n\r\n\r\n\t//-----------------------------------------\r\n\t//\t\tS E T   R E N D E R S T A T E\r\n\t//-----------------------------------------\r\n\r\n\t// begin Path2 subroutine\r\n\tdma::BeginSub(dma::ref);\r\n\r\n\t// send everything PATH2\r\n\tvif::BeginDIRECT();\r\n\r\n\t// GS prim sets up all the registers\r\n\tgif::BeginTag2(gs::A_D, 1, PACKED, 0, 0);\r\n\tgs::Reg2(gs::ALPHA_1,\t\tPackALPHA(0,1,0,1,128));\r\n\tgs::Reg2(gs::CLAMP_1,\t\tPackCLAMP(REPEAT,REPEAT,0,0,0,0));\r\n\tgs::Reg2(gs::COLCLAMP,\t\tPackCOLCLAMP(1));\r\n\tgs::Reg2(gs::DTHE,\t\t\tPackDTHE(0));\r\n\tgs::Reg2(gs::FBA_1,\t\t\tPackFBA(0));\r\n\tgs::Reg2(gs::FRAME_1,\t\tPackFRAME(FRAME_START,HRES/64,PSMCT32,0x00000000));\r\n\tp_patch_PRMODE = (uint32*) dma::pLoc;\r\n\tgs::Reg2(gs::PRMODECONT,\tPackPRMODECONT(1));\r\n\tgs::Reg2(gs::PRMODE,\t\tPackPRMODE(1,0,0,1,0,0,0,0));\r\n\tgs::Reg2(gs::SCANMSK,\t\tPackSCANMSK(0));\r\n\tgs::Reg2(gs::SCISSOR_1,\t\tPackSCISSOR(0,HRES - 1,0,VRES - 1));\r\n\tgs::Reg2(gs::TEST_1,\t\tPackTEST(1,AGREATER,0,KEEP,0,0,1,ZGEQUAL));\r\n\tgs::Reg2(gs::TEXFLUSH,\t\t0);\r\n\tgs::Reg2(gs::XYOFFSET_1,\tPackXYOFFSET(XOFFSET, YOFFSET));\r\n\tgs::Reg2(gs::ZBUF_1,\t\tPackZBUF(ZBUFFER_START,PSMZ24,0));\r\n\tgif::EndTag2(1);\r\n\r\n\tvif::EndDIRECT();\r\n\tvif::FLUSHA();\r\n\r\n\t// done\r\n\tdma::Gosubs[SET_RENDERSTATE] = dma::EndSub();\r\n\t\r\n\r\n\r\n\t//-----------------------------------------\r\n\t//\t\tS E T   F O G C O L\r\n\t//-----------------------------------------\r\n\r\n\t// begin Path2 subroutine\r\n\tdma::BeginSub(dma::ref);\r\n\r\n\t// send everything PATH2\r\n\tvif::BeginDIRECT();\r\n\r\n\t// GS prim sets up all the registers\r\n\tgif::BeginTag2(gs::A_D, 1, PACKED, 0, 0);\r\n\trender::p_patch_FOGCOL = (uint32*) dma::pLoc;\r\n\tgs::Reg2(gs::FOGCOL, PackFOGCOL(0xFF,0,0));\r\n\tgif::EndTag2(1);\r\n\r\n\tvif::EndDIRECT();\r\n\r\n\t// done\r\n\tdma::Gosubs[SET_FOGCOL] = dma::EndSub();\r\n\t\r\n\r\n\r\n}\r\n\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/dmacalls.h",
    "content": "#ifndef __MODELS_H\r\n#define __MODELS_H\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nenum eDmaSubroutines\r\n{\r\n\tCLEAR_VRAM,\r\n\tFLIP_N_CLEAR,\r\n\tCLEAR_SCREEN,\r\n\tSET_RENDERSTATE,\r\n\tCLEAR_ZBUFFER,\r\n\tUPLOAD_TEXTURES,\r\n\tSET_FOGCOL,\r\n\tFLIP_N_CLEAR_LETTERBOX,\r\n\r\n\tNUM_SUBROUTINES\r\n};\r\n\r\n\r\nuint8 *BeginDmaSubroutine(void);\r\nvoid EndDmaSubroutine(void);\r\nvoid BuildDmaSubroutines(void);\r\n\r\n//-------------------------\r\n//\t\tG L O B A L S\r\n//-------------------------\r\n\r\nextern uint8 *pSubroutine;\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n#endif // __MODELS_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/fx.cpp",
    "content": "#include <core\\defines.h>\r\n#include \"math.h\"\r\n#include \"fx.h\"\r\n#include \"asmdma.h\"\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n\r\nvoid Fx::SetupFogPalette(uint32 FogRGBA, float Exponent)\r\n{\r\n\tint i,j;\r\n\tfloat t, alpha = (float)(int)(FogRGBA>>24);\r\n\r\n\tfor (i=255,t=1.0f/256.0f; i>=0; i--,t+=1.0f/256.0f)\r\n\t{\r\n\t\tj = (i&0xE7) | (i&0x10)>>1 | (i&0x08)<<1;\r\n\t\tFogPalette[j] = (FogRGBA & 0x00FFFFFF) | (uint32)(int)(alpha * powf(t,Exponent) + 0.5f)<<24;\r\n\t}\r\n}\r\n\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/fx.h",
    "content": "\r\n#ifndef __NX_NGPS_FX_H\r\n#define __NX_NGPS_FX_H\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nnamespace Fx\r\n{\r\n\r\nvoid SetupFogPalette(uint32 FogRGBA, float Exponent);\r\n\r\n} // namespace Fx\r\n\r\n} // namespace NxPs2\r\n\r\n#endif // __NX_NGPS_FX_H\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/geomnode.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tTHPS4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tgeomnode\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgeomnode.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t00/00/00\t-\tmrd\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tprocess-in-place geometry nodes for PS2\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n#include <gel/scripting/checksum.h>\r\n//#include <sys/timer.h>\r\n#include \"render.h\"\r\n#include \"group.h\"\r\n#include \"geomnode.h\"\r\n#include \"vu1context.h\"\r\n#include \"occlude.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n#include \"gs.h\"\r\n#include \"vu1code.h\"\r\n#include \"light.h\"\r\n#include \"line.h\"\r\n#include \"dmacalls.h\"\r\n#include \"scene.h\"\r\n#include \"texture.h\"\r\n#include \"switches.h\"\r\n\r\n\r\n// Mick - Defining this __GEOM_STATS__ will enable bunch of counters in CGeomNode::Render\r\n// \r\n#define\t__GEOM_STATS__\r\n\r\n#define\t__ASSERT_ON_ZERO_RADIUS__  0\r\n\r\n#define\tOCCLUSION_CACHE 0\r\n\r\n// Just in case we forgot to take it out, this does it automatically on final burns   \r\n#ifndef\t__NOPT_ASSERT__\r\n#undef\t__GEOM_STATS__\r\n#endif   \r\n   \r\n#ifdef\t__GEOM_STATS__\r\n#define\tGEOMSTATINC(x) {x++;}\r\n#else\r\n#define\tGEOMSTATINC(x) {}\r\n#endif\r\n\r\n\r\n//float\tgClipDist = 0.1f;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n\r\n\r\nint geom_stats_total=0;\r\nint geom_stats_inactive =0;\r\nint geom_stats_sky=0;\r\nint geom_stats_transformed=0;\r\nint geom_stats_skeletal=0;\r\nint geom_stats_camera_sphere=0;\r\nint geom_stats_clipcull=0;\r\nint geom_stats_culled=0;\r\nint geom_stats_leaf_culled=0;\r\nint geom_stats_boxcheck=0;\r\nint geom_stats_occludecheck=0;\r\nint geom_stats_occluded=0;\r\nint geom_stats_colored=0;\r\nint geom_stats_leaf=0;\r\nint geom_stats_wibbleUV=0;\r\nint geom_stats_wibbleVC=0;\r\nint geom_stats_sendcontext=0;\r\nint geom_stats_sorted=0;\r\nint geom_stats_shadow=0;\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#define\t__LOD_MULTIPASS__\r\n\r\n#define SHADOW_CAM_FRUSTUM_HALF_WIDTH\t64.0f\r\n#define SHADOW_CAM_FRUSTUM_HALF_HEIGHT\t64.0f\r\n\r\n#define GET_FLAG(FLAG) (m_flags & (FLAG) ? true : false)\r\n#define SET_FLAG(FLAG) m_flags = yes ? m_flags|FLAG : m_flags&~FLAG\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCGeomNode CGeomNode::sWorld;\r\nCGeomNode CGeomNode::sDatabase;\r\n\r\nCGeomNode *GpInstanceNode=NULL;\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n// Mick: patch variables for debugging toggle of multi-passes\r\nuint32\t\tgPassMask1 = 0; \t\t// 1<<6 | 1<<7  (0x40, 0x80)\r\nuint32\t\tgPassMask0 = 0; \t\t// 1<<6 | 1<<7  (0x40, 0x80)\r\n#endif \r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\n// This is only used in a couple of places, and it's 2% of CPU time in a release build\r\n// so I'm making it inline for now to improve cache coherency \r\n// TODO: would be a good candidate for VU0 optimization\r\n// assuming the ViewVolume could be stored in VU mem or regs?\r\ninline bool CGeomNode::SphereIsOutsideViewVolume(Mth::Vector& s)\r\n{\r\n\treturn\r\n\t\ts[3] < s[2] - render::Near\t\t\t\t\t\t||\r\n\t\ts[3] < render::sx * s[2] - render::cx * s[0]\t||\r\n\t\ts[3] < render::sx * s[2] + render::cx * s[0]\t||\r\n\t\ts[3] < render::sy * s[2] + render::cy * s[1] \t||\r\n\t\ts[3] < render::sy * s[2] - render::cy * s[1]\t||\r\n\t\ts[3] < render::Far - s[2];\r\n}\r\n\r\n\r\n// Same with this\r\ninline bool CGeomNode::SphereIsInsideOuterVolume(Mth::Vector& s)\r\n{\r\n\treturn\r\n\t\ts[3] < render::Near - s[2]\t\t\t\t\t\t&&\r\n\t\ts[3] < -render::Sx * s[2] + render::Cx * s[0]\t&&\r\n\t\ts[3] < -render::Sx * s[2] - render::Cx * s[0]\t&&\r\n\t\ts[3] < -render::Sy * s[2] - render::Cy * s[1]\t&&\r\n\t\ts[3] < -render::Sy * s[2] + render::Cy * s[1]\t&&\r\n\t\ts[3] < s[2] - render::Far;\r\n}\r\n\r\n\r\nbool CGeomNode::BoxIsOutsideViewVolume(Mth::Vector& b, Mth::Vector& s)\r\n{\r\n\treturn ((render::FrustumFlagsPlus[0]  && (s[0]+b[0] <= render::CameraToWorld[3][0])) ||\r\n\t\t\t(render::FrustumFlagsPlus[1]  && (s[1]+b[1] <= render::CameraToWorld[3][1])) ||\r\n\t\t\t(render::FrustumFlagsPlus[2]  && (s[2]+b[2] <= render::CameraToWorld[3][2])) ||\r\n\t\t\t(render::FrustumFlagsMinus[0] && (s[0]-b[0] >= render::CameraToWorld[3][0])) ||\r\n\t\t\t(render::FrustumFlagsMinus[1] && (s[1]-b[1] >= render::CameraToWorld[3][1])) ||\r\n\t\t\t(render::FrustumFlagsMinus[2] && (s[2]-b[2] >= render::CameraToWorld[3][2])));\r\n}\r\n\r\n\r\ninline bool CGeomNode::NeedsClipping(Mth::Vector& s)\r\n{\r\n\treturn true;\r\n}\r\n\r\n\r\nvoid CGeomNode::LinkDma(uint8 *p_newTail)\r\n{\r\n\tdma::Tag(dma::next, 0, 0);\t// will be patched up by next call to LinkDma()\r\n\tvif::NOP();\r\n\tvif::NOP();\r\n\t((uint *)u3.mp_group->pListEnd[render::Field])[1] = (uint)p_newTail;\r\n\tu3.mp_group->pListEnd[render::Field] = dma::pLoc - 16;\r\n}\r\n\r\n// returns the number of leaf nodes\r\nint CGeomNode::ProcessNodeInPlace(uint8 *p_baseAddress)\r\n{\r\n\tint leaves = 0;\r\n\t\r\n\tif (!(m_flags & NODEFLAG_LEAF))\r\n\t{\r\n\t\tleaves++;\r\n\t\t// convert transform offset to pointer\r\n\t\tif ((int)u2.mp_transform != -1)\r\n\t\t{\r\n\t\t\tu2.mp_transform = (Mth::Matrix *)( (int)u2.mp_transform + p_baseAddress );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tu2.mp_transform = (Mth::Matrix *)0;\r\n\t\t}\r\n\t}\r\n\r\n\tuint32\ttex = GetTextureChecksum();\r\n\tSetTextureChecksum(0);  \t\t\t// clear it in case we don't find it\r\n\r\n\t// convert group checksum to pointer\r\n\tif ((m_flags & NODEFLAG_LEAF) && u1.mp_dma)\r\n\t{\r\n\t\tsGroup *pGroup;\r\n\t\tfor (pGroup=sGroup::pHead; pGroup; pGroup=pGroup->pNext)\r\n\t\t\tif (pGroup->Checksum == (uint)u3.mp_group)\r\n\t\t\t\tbreak;\r\n\t\tDbg_MsgAssert(pGroup, (\"Couldn't group checksum #%d\\n\", (uint)u3.mp_group));\r\n\t\tu3.mp_group = pGroup;\r\n\t\t\r\n\t\t// Resolve the group+texture checksum into a texture pointer\t\t\r\n//\t\tprintf (\"%x\\n\",GetTextureChecksum());\r\n\t\tif (tex)\r\n\t\t{\r\n\t\t\tsGroup * p_group = GetGroup();\r\n\t\t\tsScene * p_scene = p_group->pScene;\r\n\t\t\tsTexture *p_textures = p_scene->pTextures;\r\n\t\t\tint num_textures = p_scene->NumTextures;\r\n\t\t\tfor (int i=0;i<num_textures;i++)\r\n\t\t\t{\r\n\t\t\t\t// We are seraching through all the textures in the scene\r\n\t\t\t\t// so we will find multiple instances with the same texture checksum\r\n\t\t\t\t// so we need to check the group checksum as well\r\n\t\t\t\tif (p_textures[i].Checksum == tex && p_textures[i].GroupChecksum == GetGroup()->Checksum)\r\n\t\t\t\t{\r\n\t\t\t\t\t//printf (\"Found %dx%dx%d %x mips at 0x%x (%d)\\n\",p_textures[i].GetWidth(),p_textures[i].GetHeight(),p_textures[i].GetClutBitdepth(),p_textures[i].GetNumMipmaps(),*(p_textures+i),i);\r\n\t\t\t\t\tSetTextureChecksum((uint32)(p_textures+i));\r\n\t\t\t\t\tbreak;  \r\n\t\t\t\t}\r\n\t\t\t}\r\n//\t\t\tprintf (\"-> 0x%x\\n\",GetTextureChecksum());\r\n\t\t}\r\n\t\t\r\n\t}\r\n\r\n\tif (m_flags & NODEFLAG_LEAF)\r\n\t{\r\n\t\t// convert dma offset to pointer\r\n\t\tif ((int)u1.mp_dma != -1)\r\n\t\t{\r\n\t\t\tu1.mp_dma = (uint)u1.mp_dma + p_baseAddress;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tu1.mp_dma = (uint8 *)0;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// convert child offset to pointer\r\n\t\tif ((int)u1.mp_child != -1)\r\n\t\t{\r\n\t\t\tu1.mp_child = (CGeomNode *)( (int)u1.mp_child + p_baseAddress );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tu1.mp_child = (CGeomNode *)0;\r\n\t\t}\r\n\t}\r\n\r\n\t// convert sibling offset to pointer\r\n\tif ((int)mp_sibling != -1)\r\n\t{\r\n\t\tmp_sibling = (CGeomNode *)( (int)mp_sibling + p_baseAddress );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_sibling = (CGeomNode *)0;\r\n\t}\r\n\r\n\t// convert LOD offset to pointer\r\n\tif ((int)mp_next_LOD != -1)\r\n\t{\r\n\t\tmp_next_LOD = (CGeomNode *)( (int)mp_next_LOD + p_baseAddress );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_next_LOD = (CGeomNode *)0;\r\n\t}\r\n\r\n\t// convert uv wibble offset to pointer\r\n\tif (m_flags & NODEFLAG_UVWIBBLE)\r\n\t{\r\n\t\tif (!(m_flags & NODEFLAG_ENVMAPPED) || !(m_flags & NODEFLAG_LEAF))\r\n\t\t{\r\n\t\t\tDbg_MsgAssert ((int)mp_uv_wibble!=-1, (\"Null uv wibble pointer on a uv wibbled node\"));\r\n\t\t\tmp_uv_wibble = (float *)( (int)mp_uv_wibble + p_baseAddress );\r\n\t\t\tDbg_MsgAssert (!(((uint32)mp_uv_wibble) & 0xf0000003),(\"Corrupt UV wibble offset (0x%x) in node %s\\n\",((int)mp_uv_wibble - (int)p_baseAddress), Script::FindChecksumName(m_checksum)));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_uv_wibble = (float *)0;\r\n\t\t\tm_flags &= ~NODEFLAG_UVWIBBLE;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// convert vc wibble offset to pointer\r\n\tif ((int)mp_vc_wibble != -1)\r\n\t{\r\n\t\t// first convert the wibble offset itself\r\n\t\tmp_vc_wibble = (uint32 *)( (int)mp_vc_wibble + p_baseAddress );\r\n\r\n\t\t// now the mesh info\r\n\t\tuint32 *p_meshdata = mp_vc_wibble;\r\n\t\tint seq, num_seqs, vert, num_verts;\r\n\r\n\t\tnum_seqs = *p_meshdata++;\r\n\t\tfor (seq=0; seq<num_seqs; seq++)\r\n\t\t{\r\n\t\t\t// convert sequence pointer\r\n\t\t\t*(uint32 **)p_meshdata = (uint32 *) ( (int)*p_meshdata + p_baseAddress );\r\n\t\t\tp_meshdata++;\r\n\r\n\t\t\t// convert rgba pointers\r\n\t\t\tnum_verts = *p_meshdata++;\r\n\t\t\tfor (vert=0; vert<num_verts; vert++)\r\n\t\t\t{\r\n\t\t\t\t*(uint32 **)p_meshdata = (uint32 *) ( (uint)*p_meshdata + p_baseAddress );\r\n\t\t\t\tp_meshdata++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_vc_wibble = (uint32 *)0;\r\n\t}\r\n\r\n\t// recursively process any children\r\n\tif (!(m_flags & NODEFLAG_LEAF))\r\n\t{\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tleaves += p_child->ProcessNodeInPlace(p_baseAddress);\r\n\t\t}\r\n\t}\r\n\r\n\t// recursively process any LODs\r\n\tif (mp_next_LOD)\r\n\t{\r\n\t\t(void) mp_next_LOD->ProcessNodeInPlace(p_baseAddress);\r\n\t}\r\n\t\r\n\treturn leaves;\r\n}\r\n\r\n\r\n\r\nvoid CGeomNode::BecomesChildOf(CGeomNode *p_parent)\r\n{\r\n\tif (m_flags & NODEFLAG_LEAF)\r\n\t{\r\n\t\tmp_sibling = NULL;\r\n\t\tm_flags &= ~NODEFLAG_LEAF;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_sibling = p_parent->u1.mp_child;\r\n\t}\r\n\tp_parent->u1.mp_child = this;\r\n}\r\n\r\n\r\nbool CGeomNode::RemoveFrom(CGeomNode *p_parent)\r\n{\r\n\tif ((m_flags & NODEFLAG_LEAF) || !p_parent->u1.mp_child)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\tif (p_parent->u1.mp_child == this)\r\n\t{\r\n\t\tp_parent->u1.mp_child = mp_sibling;\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor (CGeomNode *p_node=p_parent->u1.mp_child; p_node->mp_sibling; p_node=p_node->mp_sibling)\r\n\t\t{\r\n\t\t\tif (p_node->mp_sibling == this)\r\n\t\t\t{\r\n\t\t\t\tp_node->mp_sibling = mp_sibling;\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\nbool CGeomNode::RemoveFromChildrenOf(CGeomNode *p_parent)\r\n{\r\n\tif ((m_flags & NODEFLAG_LEAF) || !p_parent->u1.mp_child)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfor (CGeomNode *p_node=p_parent->u1.mp_child; p_node; p_node=p_node->mp_sibling)\r\n\t{\r\n\t\tif (RemoveFrom(p_node))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\n#endif // #ifdef __PLAT_NGPS__\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#if OCCLUSION_CACHE\r\nstatic bool set_valid_flag = false;\r\n#endif\r\n\r\n\r\nCGeomNode::CGeomNode()\r\n{\r\n\tm_flags = ALL_VISIBILITY_BITS;\r\n\r\n\t\r\n#if OCCLUSION_CACHE\r\n\tif( set_valid_flag )\r\n\t{\r\n\t\tset_valid_flag = false;\r\n\t\tm_flags |= NODEFLAG_LAST_OCCLUSION_VALID;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tset_valid_flag = true;\r\n\t}\r\n#endif\r\n\tm_bounding_sphere[0] = 0.0f;\r\n\tm_bounding_sphere[1] = 0.0f;\r\n\tm_bounding_sphere[2] = 0.0f;\r\n\tm_bounding_sphere[3] = 1.0e+30f;\r\n\r\n\tm_bounding_box[0] = 1.0e+30f;\r\n\tm_bounding_box[1] = 1.0e+30f;\r\n\tm_bounding_box[2] = 1.0e+30f;\r\n\r\n\tm_LOD_far_dist\t= MAX_LOD_DIST;\r\n\r\n\tu2.mp_transform\t= NULL;\r\n\tu1.mp_child\t\t= NULL;\r\n\tmp_sibling\t\t= NULL;\r\n\tmp_next_LOD\t\t= NULL;\r\n\t//u1.mp_dma\t\t\t= NULL;\r\n\tu3.mp_group\t\t= NULL;\r\n\tmp_uv_wibble\t= NULL;\r\n\tmp_vc_wibble\t= NULL;\r\n\r\n\tm_num_bones\t\t   = 0;\r\n\tm_bone_index\t   = -1;\r\n\tu4.mp_bone_transforms = NULL;\r\n\r\n\tm_colour = 0x80808080;\r\n}\r\n\r\n\r\nvoid CGeomNode::Init()\r\n{\r\n\tm_flags = ALL_VISIBILITY_BITS;\r\n\r\n\tm_bounding_sphere[0] = 0.0f;\r\n\tm_bounding_sphere[1] = 0.0f;\r\n\tm_bounding_sphere[2] = 0.0f;\r\n\tm_bounding_sphere[3] = 1.0e+30f;\r\n\r\n\tm_bounding_box[0] = 1.0e+30f;\r\n\tm_bounding_box[1] = 1.0e+30f;\r\n\tm_bounding_box[2] = 1.0e+30f;\r\n\r\n\tm_LOD_far_dist\t= MAX_LOD_DIST;\r\n\r\n\tu2.mp_transform\t= NULL;\r\n\tu1.mp_child\t\t= NULL;\r\n\tmp_sibling\t\t= NULL;\r\n\tmp_next_LOD\t\t= NULL;\r\n\t//u1.mp_dma\t\t\t= NULL;\r\n\tu3.mp_group\t\t= NULL;\r\n\tmp_uv_wibble\t= NULL;\r\n\tmp_vc_wibble\t= NULL;\r\n\r\n\tm_num_bones\t\t   = 0;\r\n\tm_bone_index\t   = -1;\r\n\tu4.mp_bone_transforms = NULL;\r\n\r\n\tm_colour = 0x80808080;\r\n}\r\n\r\n\r\nCGeomNode::CGeomNode(const CGeomNode &node)\r\n{\r\n\t#if 1\r\n\tmemcpy(this,&node,sizeof(CGeomNode));\r\n\t#else\r\n\tm_flags\t\t\t\t= node.m_flags;\r\n\tm_bounding_sphere\t= node.m_bounding_sphere;\r\n\tu2.mp_transform\t\t= node.u2.mp_transform;\r\n\tu1.mp_child\t\t\t= node.u1.mp_child;\r\n\tmp_sibling\t\t\t= node.mp_sibling;\r\n\tmp_next_LOD\t\t\t= node.mp_next_LOD;\r\n\tm_LOD_far_dist\t\t= node.m_LOD_far_dist;\r\n\t//u1.mp_dma\t\t\t\t= node.u1.mp_dma;\r\n\tu3.mp_group\t\t\t= node.u3.mp_group;\r\n\tmp_uv_wibble\t\t= node.mp_uv_wibble;\r\n\tmp_vc_wibble\t\t= node.mp_vc_wibble;\r\n\tm_num_bones\t\t\t= node.m_num_bones;\r\n\tm_bone_index\t\t= node.m_bone_index;\r\n\tu4.mp_bone_transforms\t= node.u4.mp_bone_transforms;\r\n\tm_colour\t\t\t= node.m_colour;\r\n\t#endif\r\n}\r\n\r\n\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\n\r\n\r\n//#define\tDUMP_NODE_STRUCTURE\r\n\r\n\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\nstatic int node_level = 0;\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeomNode::RenderWorld(CVu1Context& ctxt, uint32 renderFlags)\r\n{\r\n\tGEOMSTATINC(geom_stats_total);\r\n\r\n\t\r\n// Don't render anything if it's not going to be displayed\t\r\n\tif (!FlipCopyEnabled())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// render children\r\n\tCGeomNode *p_child;\r\n\tfor (p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t{\r\n\t\tp_child->RenderScene(ctxt, renderFlags);\r\n\t}\r\n\t\r\n#ifdef\t__NOPT_ASSERT__\r\n\tm_flags |= NODEFLAG_WAS_RENDERED;\t\t// Set flag saying it was rendered\r\n#endif\r\n\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeomNode::RenderScene(CVu1Context& ctxt, uint32 renderFlags)\r\n{\r\n\tCVu1Context *p_ctxt;\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\tm_flags &= ~NODEFLAG_WAS_RENDERED;\t\t// Clear flag saying it was rendered\r\n#endif\r\n\r\n\tGEOMSTATINC(geom_stats_total);\r\n\r\n\r\n\t// cull the node if not active\r\n\tif (!((m_flags & NODEFLAG_ACTIVE) && (m_flags & render::ViewportMask)))\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_inactive);\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n\t\treturn;\r\n\t}\r\n\r\n\t// is it the root node of a sky?\r\n\tif (m_flags & NODEFLAG_SKY)\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_sky);\r\n\t\t// reserve space from dma list for new trans context\r\n\t\tp_ctxt = ctxt.Localise();\r\n\r\n\t\tp_ctxt->SetupAsSky();\r\n\t\tRenderAsSky(*p_ctxt, renderFlags);\r\n\t\tdma::SetList(NULL);\t\t\t// not quite sure why we need this, but we do\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n\t\treturn;\r\n\t}\r\n\r\n\t// is it really an object node in disguise?\r\n\tif (m_flags & NODEFLAG_OBJECT)\r\n\t{\r\n\t\tRenderObject(ctxt, renderFlags);\r\n\t\treturn;\r\n\t}\r\n\r\n\t// get this node's transform context\r\n\tif (m_flags & NODEFLAG_TRANSFORMED)\r\n\t{\r\n\t\t// copy the parent vu1 context\r\n\t\tp_ctxt = ctxt.LocaliseExtend();\r\n\r\n\t\t// set up the parts of the context that will depend on the new matrix\r\n\t\tp_ctxt->StandardSetup(*u2.mp_transform);   \r\n\r\n\t\t// Propogate the 'transformed' flag when recursing.\r\n\t\trenderFlags |= RENDERFLAG_TRANSFORMED;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_ctxt = &ctxt;\r\n\t}\r\n\r\n\t// make a note of the root node for a skeletal model\r\n\tif (m_flags & NODEFLAG_SKELETAL)\r\n\t{\r\n\t\tGpInstanceNode = this;\r\n\t\trenderFlags |= RENDERFLAG_SKELETAL;\r\n\t}\r\n\r\n\r\n\t// applying a colour to a node\r\n\tif (m_flags & NODEFLAG_COLOURED)\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_colored);\r\n\t\t// if there's no local context, copy the parent's\r\n\t\tif (p_ctxt == &ctxt)\r\n\t\t{\r\n\t\t\tp_ctxt = ctxt.Localise();\r\n\t\t}\r\n\t\r\n\t\t// copy node's colour to vu1 context\r\n\t\tp_ctxt->SetColour(this);\r\n\t\trenderFlags |= RENDERFLAG_COLOURED;\r\n\t}\r\n\r\n\t// Check for light group\r\n\tif (u3.mp_light_group && u3.mp_light_group != ctxt.GetLights())\r\n\t{\r\n\t\t// if there's no local context, copy the global one\r\n\t\tif (p_ctxt == &ctxt || !p_ctxt->IsExtended())\r\n\t\t{\r\n\t\t\tp_ctxt = ctxt.LocaliseExtend();\r\n\t\t}\r\n\r\n\t\tp_ctxt->SetLights(u3.mp_light_group);\r\n\t}\r\n\r\n\r\n// If we got here, then it's been rendered, so set the flag\r\n#ifdef\t__NOPT_ASSERT__\r\n\tm_flags |= NODEFLAG_WAS_RENDERED;\t\t// Set flag saying it was rendered\r\n#endif\r\n\r\n\t// render any children\r\n\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t{\r\n\t\tp_child->RenderObject(*p_ctxt, renderFlags);\r\n\t}\r\n\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeomNode::RenderObject(CVu1Context& ctxt, uint32 renderFlags)\r\n{\r\n\tCVu1Context *p_ctxt;\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\tm_flags &= ~NODEFLAG_WAS_RENDERED;\t\t// Clear flag saying it was rendered\r\n#endif\r\n\r\n\tGEOMSTATINC(geom_stats_total);\r\n\r\n\r\n\r\n\r\n\t#if\t__ASSERT_ON_ZERO_RADIUS__\r\n\tDbg_MsgAssert( m_bounding_sphere[W] != 0.0f, ( \"Wasn't expecting a radius of 0 for geomnode %s or a sub-mesh of it. \\n perhaps it has isolated verts that need removing?\",Script::FindChecksumName(GetChecksum()) ) );\r\n\t#endif\r\n\r\n\t// cull the node if not active\r\n\tif (!((m_flags & NODEFLAG_ACTIVE) && (m_flags & render::ViewportMask)))\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_inactive);\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n\t    return;\r\n\t}\r\n\r\n#if OCCLUSION_CACHE\r\n\tbool last_occlusion_check_valid = ( m_flags & NODEFLAG_LAST_OCCLUSION_VALID );\r\n\tif( last_occlusion_check_valid )\r\n\t{\r\n\t\t// Clear the valid flag.\r\n\t\tm_flags &= ~NODEFLAG_LAST_OCCLUSION_VALID;\r\n\r\n\t\t// Was this object occluded last frame? If so, occlude this frame also.\r\n\t\tif( m_flags & NODEFLAG_LAST_OCCLUSION_TRUE )\r\n\t\t{\r\n\t\t\tm_flags &= ~NODEFLAG_LAST_OCCLUSION_TRUE;\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n\t\treturn;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\t// get this node's transform context\r\n\tif (m_flags & NODEFLAG_TRANSFORMED)\r\n\t{\r\n\t\t// copy the parent vu1 context\r\n\t\tp_ctxt = ctxt.LocaliseExtend();\r\n\r\n\t\t// set up the parts of the context that will depend on the new matrix\r\n\t\tp_ctxt->StandardSetup(*u2.mp_transform);   \r\n\r\n\t\t// Propogate the 'transformed' flag when recursing.\r\n\t\trenderFlags |= RENDERFLAG_TRANSFORMED;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_ctxt = &ctxt;\r\n\t}\r\n\r\n\t// check for skeletal mesh\r\n\tif ((renderFlags & RENDERFLAG_SKELETAL) && (m_bone_index >= 0))\r\n\t{\r\n\t\tDbg_MsgAssert(GpInstanceNode, (\"GpInstanceNode is NULL\"));\r\n\r\n\t\tGEOMSTATINC(geom_stats_skeletal);\r\n\t\tif (p_ctxt == &ctxt)\r\n\t\t{\r\n\t\t\tp_ctxt = ctxt.Localise();\r\n\t\t}\r\n\t\r\n\t\tp_ctxt->HierarchicalSetup(GpInstanceNode->u4.mp_bone_transforms[m_bone_index]);\r\n\t}\r\n\r\n\tMth::Vector camera_sphere;\r\n\tGEOMSTATINC(geom_stats_camera_sphere);\r\n\tcamera_sphere = m_bounding_sphere;\r\n\tcamera_sphere[W] = 1.0f;\r\n\tcamera_sphere *= *p_ctxt->GetMatrix();\r\n\tcamera_sphere[W] = m_bounding_sphere[W];\r\n\r\n\r\n\t// view-volume bounding sphere tests, based on parent render flags\r\n\t// MickNote:  I experimented with only clipping the leaf nodes, but this was slightly\r\n\t// slower, as the higher level culling must cull enough to justify the overhead)\r\n\tif ( renderFlags & (RENDERFLAG_CLIP | RENDERFLAG_CULL))\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_clipcull);\r\n\t\tif (SphereIsOutsideViewVolume(camera_sphere))\r\n\t\t{\r\n\t\t\tGEOMSTATINC(geom_stats_culled);\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (SphereIsInsideOuterVolume(camera_sphere))\r\n\t\t{\r\n\t\t\trenderFlags &= ~(RENDERFLAG_CLIP|RENDERFLAG_CULL);\r\n\t\t}\r\n\t}\r\n\r\n\t// view-volume bounding box test\r\n\tif ((renderFlags & (RENDERFLAG_CLIP | RENDERFLAG_CULL)) &&\r\n\t\t!((renderFlags & RENDERFLAG_TRANSFORMED) || m_flags & NODEFLAG_TRANSFORMED))\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_boxcheck);\r\n\t\tif (BoxIsOutsideViewVolume(*(Mth::Vector *)&m_bounding_box, m_bounding_sphere))\r\n\t\t{\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Occlusion test.\r\n\tif (m_bounding_sphere[W] > 1.0e20f)\r\n\t{\r\n\t\t// Don't bother if sphere is stupidly large.\r\n\t}\r\n#if OCCLUSION_CACHE\r\n\telse if( !last_occlusion_check_valid )\r\n#else\r\n\telse\r\n#endif\t\r\n\t{\r\n\t\t\r\n#if OCCLUSION_CACHE\r\n\t\tm_flags |= NODEFLAG_LAST_OCCLUSION_VALID;\r\n#endif\r\n\t\tif (m_flags & NODEFLAG_TRANSFORMED)\t\t\t\t\t// root of a transformed branch\r\n\t\t{\r\n\t\t\tGEOMSTATINC(geom_stats_occludecheck);\r\n\t\t\tMth::Vector world_sphere(m_bounding_sphere);\r\n\t\t\tworld_sphere[W] = 1.0f;\r\n\t\t\tworld_sphere *= *u2.mp_transform;\t\t\t\t\t\t\t// => use u2.mp_transform\r\n\t\t\tif (TestSphereAgainstOccluders( &world_sphere, m_bounding_sphere[W] ))\r\n\t\t\t{\r\n\t\t\t\tGEOMSTATINC(geom_stats_occluded);\r\n#if OCCLUSION_CACHE\r\n\t\t\t\tm_flags |= NODEFLAG_LAST_OCCLUSION_TRUE;\r\n#endif\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if (renderFlags & RENDERFLAG_TRANSFORMED)\t\t\t\t// deeper within a transformed branch\r\n\t\t{\r\n\t\t}\r\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t// not transformed => use world position as-is\r\n\t\t{\r\n\t\t\tGEOMSTATINC(geom_stats_occludecheck);\r\n\t\t\tif (TestSphereAgainstOccluders( &m_bounding_sphere, m_bounding_sphere[W] ))\r\n\t\t\t{\r\n\t\t\t\tGEOMSTATINC(geom_stats_occluded);\r\n#if OCCLUSION_CACHE\r\n\t\t\t\tm_flags |= NODEFLAG_LAST_OCCLUSION_TRUE;\r\n#endif\t\t\t\t\r\n\t\t\t\t#ifdef\tDUMP_NODE_STRUCTURE\r\n\t\t\t\t\tnode_level--;\r\n\t\t\t\t#endif\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t#if !STENCIL_SHADOW\r\n\t// shadow test\r\n\tif (renderFlags & RENDERFLAG_SHADOW)\r\n\t{\r\n\t\tif (m_flags & (NODEFLAG_TRANSFORMED))\r\n\t\t{\r\n\t\t\trenderFlags &= ~RENDERFLAG_SHADOW;\r\n\t\t}\r\n\t\telse if (( m_bounding_sphere[X] + m_bounding_box[X] ) < ( render::ShadowCameraPosition[X] - SHADOW_CAM_FRUSTUM_HALF_WIDTH  )\t||\r\n\t\t\t\t ( m_bounding_sphere[X] - m_bounding_box[X] ) > ( render::ShadowCameraPosition[X] + SHADOW_CAM_FRUSTUM_HALF_WIDTH  )\t||\r\n\t\t\t\t ( m_bounding_sphere[Z] + m_bounding_box[Z] ) < ( render::ShadowCameraPosition[Z] - SHADOW_CAM_FRUSTUM_HALF_HEIGHT )\t||\r\n\t\t\t\t ( m_bounding_sphere[Z] - m_bounding_box[Z] ) > ( render::ShadowCameraPosition[Z] + SHADOW_CAM_FRUSTUM_HALF_HEIGHT ))\r\n\t\t{\r\n\t\t\trenderFlags &= ~RENDERFLAG_SHADOW;\r\n\t\t}\r\n\t}\r\n\t#endif\r\n\r\n\t// applying a colour to a node\r\n\tif (m_flags & NODEFLAG_COLOURED)\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_colored);\r\n\t\t// if there's no local context, copy the parent's\r\n\t\tif (p_ctxt == &ctxt)\r\n\t\t{\r\n\t\t\tp_ctxt = ctxt.Localise();\r\n\t\t}\r\n\r\n\t\t// copy node's colour to vu1 context\r\n\t\tp_ctxt->SetColour(this);\r\n\t\trenderFlags |= RENDERFLAG_COLOURED;\r\n\t}\r\n\r\n\t// Check for light group\r\n\tif (u3.mp_light_group && u3.mp_light_group != ctxt.GetLights())\r\n\t{\r\n\t\t// if there's no local context, copy the global one\r\n\t\tif (p_ctxt == &ctxt || !p_ctxt->IsExtended())\r\n\t\t{\r\n\t\t\tp_ctxt = ctxt.LocaliseExtend();\r\n\t\t}\r\n\r\n\t\tp_ctxt->SetLights(u3.mp_light_group);\r\n\t}\r\n\r\n\r\n\t// Check if we should use another LOD (Garrett: Logically, this should be right, but I still want to streamline it)\r\n\tfloat camera_dist = -camera_sphere[Z];\r\n\tCGeomNode *p_child = NULL;\r\n\tCGeomNode *p_lod;\r\n\tfor (p_lod=this; p_lod; p_lod = p_lod->mp_next_LOD)\r\n\t{\r\n\t\tif (p_lod->m_LOD_far_dist > camera_dist)\r\n\t\t{\r\n\t\t\tp_child = p_lod->u1.mp_child;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n// If we got here, then it's been rendered, so set the flag\r\n#ifdef\t__NOPT_ASSERT__\r\n\tm_flags |= NODEFLAG_WAS_RENDERED;\t\t// Set flag saying it was rendered\r\n#endif\r\n\r\n\t// render any children\r\n\tif (renderFlags & RENDERFLAG_TRANSFORMED)\r\n\t{\r\n\t\tfor (; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_child->RenderTransformedLeaf(*p_ctxt, renderFlags);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor (; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_child->RenderNonTransformedLeaf(*p_ctxt, renderFlags);\r\n\t\t}\r\n\t}\r\n\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeomNode::RenderTransformedLeaf(CVu1Context& ctxt, uint32 renderFlags)\r\n{\r\n\tCVu1Context *p_ctxt;\r\n\r\n\t#if\t__ASSERT_ON_ZERO_RADIUS__\r\n\tDbg_MsgAssert( m_bounding_sphere[W] != 0.0f, ( \"Wasn't expecting a radius of 0 for geomnode %s or a sub-mesh of it. \\n perhaps it has isolated verts that need removing?\",Script::FindChecksumName(GetChecksum()) ) );\r\n\t#endif\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\tm_flags &= ~NODEFLAG_WAS_RENDERED;\t\t// Clear flag saying it was rendered\r\n#endif\r\n\r\n\tGEOMSTATINC(geom_stats_total);\r\n\r\n\r\n#if OCCLUSION_CACHE\r\n\tbool last_occlusion_check_valid = ( m_flags & NODEFLAG_LAST_OCCLUSION_VALID );\r\n\tif( last_occlusion_check_valid )\r\n\t{\r\n\t\t// Clear the valid flag.\r\n\t\tm_flags &= ~NODEFLAG_LAST_OCCLUSION_VALID;\r\n\r\n\t\t// Was this object occluded last frame? If so, occlude this frame also.\r\n\t\tif( m_flags & NODEFLAG_LAST_OCCLUSION_TRUE )\r\n\t\t{\r\n\t\t\tm_flags &= ~NODEFLAG_LAST_OCCLUSION_TRUE;\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n\t\treturn;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tMth::Vector camera_sphere;\r\n\tGEOMSTATINC(geom_stats_camera_sphere);\r\n\tcamera_sphere = m_bounding_sphere;\r\n\tcamera_sphere[W] = 1.0f;\r\n\tcamera_sphere *= *ctxt.GetMatrix();\r\n\tcamera_sphere[W] = m_bounding_sphere[W];\r\n\r\n\r\n\t// view-volume bounding sphere tests, based on parent render flags\r\n\t// MickNote:  I experimented with only clipping the leaf nodes, but this was slightly\r\n\t// slower, as the higher level culling must cull enough to justify the overhead)\r\n\tif ( renderFlags & (RENDERFLAG_CLIP | RENDERFLAG_CULL))\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_clipcull);\r\n\t\tif (SphereIsOutsideViewVolume(camera_sphere))\r\n\t\t{\r\n\t\t\tGEOMSTATINC(geom_stats_culled);\r\n\t\t\tGEOMSTATINC(geom_stats_leaf_culled);\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (SphereIsInsideOuterVolume(camera_sphere))\r\n\t\t{\r\n\t\t\trenderFlags &= ~(RENDERFLAG_CLIP|RENDERFLAG_CULL);\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t// Occlusion test.\r\n#if OCCLUSION_CACHE\r\n\tif( !last_occlusion_check_valid )\r\n#endif\t\r\n\t{\r\n#if OCCLUSION_CACHE\r\n\t\tm_flags |= NODEFLAG_LAST_OCCLUSION_VALID;\r\n#endif\r\n\t}\r\n\r\n\r\n\t#if !STENCIL_SHADOW\r\n\t// shadow test\r\n\tif (renderFlags & RENDERFLAG_SHADOW)\r\n\t{\r\n\t\tif (m_flags & (NODEFLAG_BILLBOARD | NODEFLAG_ENVMAPPED))\r\n\t\t{\r\n\t\t\trenderFlags &= ~RENDERFLAG_SHADOW;\r\n\t\t}\r\n\t\telse if (( m_bounding_sphere[X] + m_bounding_box[X] ) < ( render::ShadowCameraPosition[X] - SHADOW_CAM_FRUSTUM_HALF_WIDTH  )\t||\r\n\t\t\t\t ( m_bounding_sphere[X] - m_bounding_box[X] ) > ( render::ShadowCameraPosition[X] + SHADOW_CAM_FRUSTUM_HALF_WIDTH  )\t||\r\n\t\t\t\t ( m_bounding_sphere[Z] + m_bounding_box[Z] ) < ( render::ShadowCameraPosition[Z] - SHADOW_CAM_FRUSTUM_HALF_HEIGHT )\t||\r\n\t\t\t\t ( m_bounding_sphere[Z] - m_bounding_box[Z] ) > ( render::ShadowCameraPosition[Z] + SHADOW_CAM_FRUSTUM_HALF_HEIGHT ))\r\n\t\t{\r\n\t\t\trenderFlags &= ~RENDERFLAG_SHADOW;\r\n\t\t}\r\n\t}\r\n\t#endif\r\n\r\n\t// get this node's transform context\r\n\tp_ctxt = &ctxt;\r\n\r\n\t// applying a colour to a node\r\n\tif (m_flags & NODEFLAG_COLOURED)\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_colored);\r\n\t\tp_ctxt = ctxt.Localise();\r\n\r\n\t\t// copy node's colour to vu1 context\r\n\t\tp_ctxt->SetColour(this);\r\n\t\trenderFlags |= RENDERFLAG_COLOURED;\r\n\t}\r\n\r\n\tGEOMSTATINC(geom_stats_leaf);\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t// Mick: check patch variables for debugging toggle of multi-passes\r\n\tif ((m_flags & gPassMask1) != gPassMask0)\r\n\t{\t\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\nnode_level--;\r\n#endif\r\n\t\treturn;\r\n\t}\r\n\t#endif\r\n\r\n\t#ifdef\t__LOD_MULTIPASS__\r\n\t// if 2nd+ pass, check to see if distance from camera is greater than allowed for multipass\r\n\tif ((m_flags & NODEFLAG_ZPUSH) && (-camera_sphere[Z] > render::sMultipassMaxDist))\r\n\t{\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\nnode_level--;\r\n#endif\r\n\t\treturn;\r\n\t}\r\n\t#endif\r\n\r\n\tif (m_flags & (NODEFLAG_UVWIBBLE | NODEFLAG_ENVMAPPED | NODEFLAG_VCWIBBLE))\r\n\t{\r\n\t\tif (m_flags & (NODEFLAG_UVWIBBLE | NODEFLAG_ENVMAPPED))\r\n\t\t{\r\n\t\t\t// if there's no local context, copy the global one\r\n\t\t\tif (p_ctxt == &ctxt)\r\n\t\t\t{\r\n\t\t\t\tp_ctxt = ctxt.LocaliseExtend();\r\n\t\t\t}\r\n\r\n\t\t\t// uv wibble\r\n\t\t\tif (m_flags & NODEFLAG_UVWIBBLE)\r\n\t\t\t{\r\n\t\t\t\tGEOMSTATINC(geom_stats_wibbleUV);\r\n\t\t\t\tp_ctxt->WibbleUVs(mp_uv_wibble, m_flags&NODEFLAG_EXPLICIT_UVWIBBLE);\r\n\t\t\t}\r\n\r\n\t\t\t// environment mapping\r\n\t\t\tif (m_flags & NODEFLAG_ENVMAPPED)\r\n\t\t\t{\r\n\t\t\t\t// reflection map vectors\r\n\t\t\t\tp_ctxt->SetReflectionVecs((sint16)(uint)mp_uv_wibble, (sint16)(((uint)mp_uv_wibble)>>16));\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// vc wibble\r\n\t\tif (m_flags & NODEFLAG_VCWIBBLE)\r\n\t\t{\r\n\t\t\tGEOMSTATINC(geom_stats_wibbleVC);\r\n\t\t\tWibbleVCs();\r\n\t\t}\r\n\t}\r\n\r\n\t// set the dma context\r\n\tdma::SetList(u3.mp_group);\r\n\tu3.mp_group->Used[render::Field] = true;\r\n\r\n\t// flag the texture as used\r\n\tif (u4.mp_texture)\r\n\t{\r\n\t\tu4.mp_texture->m_render_count++;\r\n\t}\r\n\r\n\r\n\tMth::Vector *p_trans = p_ctxt->GetTranslation();\r\n\r\n\t// initial cnt tag, for sending row reg and z-sort key\r\n\tdma::Tag(dma::cnt, 1, *(uint32 *)&camera_sphere[Z]);\r\n\tvif::NOP();\r\n\tvif::STROW((int)(*p_trans)[0] + (int)(m_bounding_sphere[0]*SUB_INCH_PRECISION),\r\n\t\t\t   (int)(*p_trans)[1] + (int)(m_bounding_sphere[1]*SUB_INCH_PRECISION),\r\n\t\t\t   (int)(*p_trans)[2] + (int)(m_bounding_sphere[2]*SUB_INCH_PRECISION), 0);\r\n\r\n\r\n\t// special case for billboards\r\n\tif (m_flags & NODEFLAG_BILLBOARD)\r\n\t{\r\n\t\t// compute billboard basis vecs\r\n\t\tMth::Vector udir,vdir;\r\n\t\tvdir = (*p_ctxt->GetMatrix())[1];\r\n\t\tvdir[2] =  0.0f;\r\n\t\tvdir[3] =  0.0f;\r\n\t\tvdir.Normalize();\r\n\t\tudir[0] =  vdir[1];\r\n\t\tudir[1] = -vdir[0];\r\n\t\tudir[2] =  0.0f;\r\n\t\tudir[3] =  0.0f;\r\n\r\n\t\tudir *= render::CameraToFrustum;\r\n\t\tvdir *= render::CameraToFrustum;\r\n\t\tudir[2] =  0.0f;\r\n\t\tudir[3] =  0.0f;\r\n\t\tvdir[2] =  0.0f;\r\n\t\tvdir[3] =  0.0f;\r\n\r\n\t\t// send vu1 context\r\n\t\tdma::Tag(dma::next, 16, (uint)dma::pLoc+272);\r\n\t\tvif::BASE(vu1::Loc);\r\n\t\tvif::OFFSET(0);\r\n\t\tuint vu1_loc = vu1::Loc;\r\n\t\tvu1::Loc = 0;   \t\t\t\t\t\t\t// must do this as a relative prim for a sortable list...\r\n\t\tvu1::BeginPrim(REL, VU1_ADDR(L_VF20));\r\n\t\tvu1::StoreVec(*(Vec *)&udir);\r\n\t\tvu1::StoreVec(*(Vec *)&vdir);\r\n\t\tvu1::StoreVec(*(Vec *)&render::IntViewportScale);\r\n\t\tvif::StoreV4_32(0,0,0,0);\r\n\t\tvif::StoreV4_32(0,0,0,0);\r\n\t\tvu1::StoreVec(*(Vec *)&render::CameraToWorld[3]);\r\n\t\tvu1::StoreVec(*(Vec *)ctxt.GetColour());\r\n\t\tvu1::StoreVec(*(Vec *)&render::IntViewportOffset);\r\n\t\tMth::Matrix LocalToFrustum = (*p_ctxt->GetMatrix()) * render::CameraToFrustum;\r\n\t\tvu1::CopyMat((float*)&LocalToFrustum);\r\n\t\tvu1::EndPrim(0);\r\n\r\n\t\t// gs context data, specifically the fog coefficient\r\n\t\tfloat w,f;\r\n\t\tif (renderFlags & RENDERFLAG_TRANSFORMED)\r\n\t\t{\r\n\t\t\tw = -(*p_ctxt->GetMatrix())[3][2];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Context only contains WorldToCamera matrix, so convert world position to camera relative position\r\n\t\t\tMth::Vector camera_rel_pos = render::WorldToCamera.TransformAsPos(m_bounding_sphere);\r\n\t\t\tw = -camera_rel_pos[2];\r\n\t\t}\r\n\t\tif ((w > render::FogNear) && render::EnableFog)\t// Garrett: We have to check for EnableFog here because the VU1 code isn't\r\n\t\t{\r\n\t\t\tf = 1.0 + render::EffectiveFogAlpha * (render::FogNear/w - 1.0f);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tf = 1.0f;\r\n\t\t}\r\n\t\tgs::BeginPrim(REL,0,0);\r\n\t\tgs::Reg1(gs::FOG, PackFOG((int)(f*255.99f)));\r\n\t\tgs::EndPrim(0);\r\n\r\n\t\tdma::EndTag();\r\n\t\t((uint16 *)dma::pTag)[1] |= vu1::Loc & 0x3FF;\t// must write some code for doing this automatically\r\n\t\tvu1::Loc += vu1_loc;\r\n\r\n\t\tu3.mp_group->pVu1Context = NULL;\r\n\t}\r\n\r\n\t// send transform context if necessary\r\n\telse if ((p_ctxt != u3.mp_group->pVu1Context) || (u3.mp_group->flags & GROUPFLAG_SORT))\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_sendcontext);\r\n\t\tint qwc = p_ctxt->IsExtended() ? EXT_CTXT_SIZE+2 : STD_CTXT_SIZE+2;\r\n\t\tdma::Tag(dma::ref, qwc|(qwc-1)<<16, p_ctxt->GetDma());\r\n\t\tvif::BASE(vu1::Loc);\r\n\t\tvif::OFFSET(0);\r\n\t\tvu1::Loc += qwc-1;\r\n\t\tu3.mp_group->pVu1Context = p_ctxt;\r\n\t}\r\n\r\n\t// render this node by adding to the chosen dma list\r\n\tuint vu1_flags = (renderFlags & RENDERFLAG_CLIP) ? CLIP :\r\n\t\t\t\t\t (renderFlags & RENDERFLAG_CULL) ? CULL : PROJ;\r\n\tif (renderFlags & RENDERFLAG_COLOURED)\r\n\t\tvu1_flags |= COLR;\r\n\tif (render::EnableFog && (camera_sphere[3]-camera_sphere[2] > render::FogNear))\r\n\t\tvu1_flags |= FOGE;\r\n\tdma::pTag = dma::pLoc;\t\t// must set this manually if we bypass the dma tag functions\r\n\tdma::Store32(u2.m_dma_tag_lo32,(uint32)u1.mp_dma);\r\n\tvif::BASE(vu1::Loc);\r\n\tvif::ITOP(vu1_flags);\r\n\tvu1::Loc += u2.m_dma_tag_lo32>>16;\r\n\r\n\tif (m_flags & NODEFLAG_BLACKFOG)\r\n\t{\r\n\t\tdma::Gosub(SET_FOGCOL,2);\r\n\t\tdma::pLoc -= 8;\r\n\t\tvif::FLUSHA();\r\n\t\tvif::NOP();\r\n\t}\r\n\r\n\t// must add a 'next' tag for sorted groups\r\n\tif (u3.mp_group->flags & GROUPFLAG_SORT)\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_sorted);\r\n\t\tdma::SetList(NULL);\r\n\t}\r\n\r\n\t#if !STENCIL_SHADOW\r\n\t// render shadow\r\n\tif ((renderFlags & RENDERFLAG_SHADOW) && !(m_flags & NODEFLAG_NOSHADOW))\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_shadow);\r\n\t\t// set the dma context\r\n\t\tdma::SetList(sGroup::pShadow);\r\n\r\n\t\t// set row reg\r\n\t\tdma::Tag(dma::cnt, 1, *(uint32 *)&camera_sphere[Z]);\r\n\t\tvif::NOP();\r\n\t\tvif::STROW((int)(*p_trans)[0] + (int)(m_bounding_sphere[0]*SUB_INCH_PRECISION),\r\n\t\t\t\t   (int)(*p_trans)[1] + (int)(m_bounding_sphere[1]*SUB_INCH_PRECISION),\r\n\t\t\t\t   (int)(*p_trans)[2] + (int)(m_bounding_sphere[2]*SUB_INCH_PRECISION), 0);\r\n\r\n\t\t// send transform context\r\n\t\tdma::Tag(dma::ref, 18|17<<16, sGroup::pShadow->pVu1Context->GetDma());\r\n\t\tvif::BASE(vu1::Loc);\r\n\t\tvif::OFFSET(0);\r\n\t\tvu1::Loc += 17;\r\n\r\n\t\t// render this node\r\n\t\tvu1_flags = (renderFlags & RENDERFLAG_CLIP) ? CLIP|SHDW :\r\n\t\t\t\t\t(renderFlags & RENDERFLAG_CULL) ? CULL|SHDW : PROJ|SHDW;\r\n\t\tif (render::EnableFog && (camera_sphere[3]-camera_sphere[2] > render::FogNear))\r\n\t\t\tvu1_flags |= FOGE;\r\n\t\tdma::pTag = dma::pLoc;\t\t// must set this manually if we bypass the dma tag functions\r\n\t\tdma::Store32(u2.m_dma_tag_lo32,(uint32)u1.mp_dma);\r\n\t\tvif::BASE(vu1::Loc);\r\n\t\tvif::ITOP(vu1_flags);\r\n\t\tvu1::Loc += u2.m_dma_tag_lo32>>16;\r\n\r\n\t\tif (m_flags & NODEFLAG_BLACKFOG)\r\n\t\t{\r\n\t\t\tdma::Gosub(SET_FOGCOL,2);\r\n\t\t\tdma::pLoc -= 8;\r\n\t\t\tvif::FLUSHA();\r\n\t\t\tvif::NOP();\r\n\t\t}\r\n\t}\r\n\t#endif\r\n\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeomNode::RenderNonTransformedLeaf(CVu1Context& ctxt, uint32 renderFlags)\r\n{\r\n\tfloat camera_sphere_z;\r\n\r\n\t#if\t__ASSERT_ON_ZERO_RADIUS__\r\n\tDbg_MsgAssert( m_bounding_sphere[W] != 0.0f, ( \"Wasn't expecting a radius of 0 for geomnode %s or a sub-mesh of it. \\n perhaps it has isolated verts that need removing?\",Script::FindChecksumName(GetChecksum()) ) );\r\n\t#endif\t\r\n\r\n\t// kick off the frustum culling tests in VU0\r\n\tasm __volatile__(\"\r\n\r\n\t\tlqc2\t\tvf08,(%0)\t\t\t\t\t# sphere (x,y,z,R)\r\n\t\tlqc2\t\tvf09,(%1)\t\t\t\t\t# box (bx,by,bz,?)\r\n\t\tvcallms\t\tBothCullTests\t\t\t\t# call microsubroutine\r\n\r\n\t\": : \"r\" (&m_bounding_sphere), \"r\" (&m_bounding_box) );\r\n\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\tm_flags &= ~NODEFLAG_WAS_RENDERED;\t\t// Clear flag saying it was rendered\r\n#endif\r\n\r\n\tGEOMSTATINC(geom_stats_total);\r\n\r\n\r\n//Mick:  Minimal leaf rendering makes no real difference \r\n// so I've removed this call while refactoring\t\r\n\r\n\t// check for minimal leaf node for a quicker render\r\n\tif (!(m_flags & (NODEFLAG_COLOURED\t\t|\r\n\t\t\t\t\t NODEFLAG_BILLBOARD\t\t|\r\n\t\t\t\t\t NODEFLAG_UVWIBBLE\t\t|\r\n\t\t\t\t\t NODEFLAG_VCWIBBLE\t\t|\r\n\t\t\t\t\t NODEFLAG_ENVMAPPED))\r\n\r\n\t\t&& !(renderFlags & (RENDERFLAG_COLOURED\t\t|\r\n\t\t\t\t\t\t\t#if !STENCIL_SHADOW\r\n\t\t\t\t\t\t\tRENDERFLAG_SHADOW\t\t|\r\n\t\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t\tRENDERFLAG_CLIP\t\t\t|\r\n\t\t\t\t\t\t\tRENDERFLAG_CULL)))\r\n\t{\r\n\t\tRenderMinimalLeaf(ctxt);\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n\t\treturn;\r\n\t}\r\n\r\n\r\n#if OCCLUSION_CACHE\r\n\tbool last_occlusion_check_valid = ( m_flags & NODEFLAG_LAST_OCCLUSION_VALID );\r\n\tif( last_occlusion_check_valid )\r\n\t{\r\n\t\t// Clear the valid flag.\r\n\t\tm_flags &= ~NODEFLAG_LAST_OCCLUSION_VALID;\r\n\r\n\t\t// Was this object occluded last frame? If so, occlude this frame also.\r\n\t\tif( m_flags & NODEFLAG_LAST_OCCLUSION_TRUE )\r\n\t\t{\r\n\t\t\tm_flags &= ~NODEFLAG_LAST_OCCLUSION_TRUE;\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n\t\treturn;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\r\n\t// view-volume bounding sphere tests, based on parent render flags\r\n\t// MickNote:  I experimented with only clipping the leaf nodes, but this was slightly\r\n\t// slower, as the higher level culling must cull enough to justify the overhead)\r\n\tif ( renderFlags & (RENDERFLAG_CLIP | RENDERFLAG_CULL))\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_clipcull);\r\n\r\n\t\tif (CullAgainstViewFrustum())\r\n\t\t{\r\n\t\t\tGEOMSTATINC(geom_stats_culled);\r\n\t\t\tGEOMSTATINC(geom_stats_leaf_culled);\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!CullAgainstOuterFrustum())\r\n\t\t{\r\n\t\t\trenderFlags &= ~(RENDERFLAG_CLIP|RENDERFLAG_CULL);\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t// Occlusion test.\r\n#if OCCLUSION_CACHE\r\n\tif( !last_occlusion_check_valid )\r\n#endif\t\r\n\t{\r\n\t\t\r\n#if OCCLUSION_CACHE\r\n\t\tm_flags |= NODEFLAG_LAST_OCCLUSION_VALID;\r\n#endif\r\n\t\tGEOMSTATINC(geom_stats_occludecheck);\r\n\t\tif (TestSphereAgainstOccluders( &m_bounding_sphere, m_bounding_sphere[W] ))\r\n\t\t{\r\n\t\t\tGEOMSTATINC(geom_stats_occluded);\r\n#if OCCLUSION_CACHE\r\n\t\t\tm_flags |= NODEFLAG_LAST_OCCLUSION_TRUE;\r\n#endif\t\t\t\t\r\n\t\t\t#ifdef\tDUMP_NODE_STRUCTURE\r\n\t\t\t\tnode_level--;\r\n\t\t\t#endif\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t#if !STENCIL_SHADOW\r\n\t// shadow test\r\n\tif (renderFlags & RENDERFLAG_SHADOW)\r\n\t{\r\n\t\tif (m_flags & (NODEFLAG_BILLBOARD | NODEFLAG_ENVMAPPED))\r\n\t\t{\r\n\t\t\trenderFlags &= ~RENDERFLAG_SHADOW;\r\n\t\t}\r\n\t\telse if (( m_bounding_sphere[X] + m_bounding_box[X] ) < ( render::ShadowCameraPosition[X] - SHADOW_CAM_FRUSTUM_HALF_WIDTH  )\t||\r\n\t\t\t\t ( m_bounding_sphere[X] - m_bounding_box[X] ) > ( render::ShadowCameraPosition[X] + SHADOW_CAM_FRUSTUM_HALF_WIDTH  )\t||\r\n\t\t\t\t ( m_bounding_sphere[Z] + m_bounding_box[Z] ) < ( render::ShadowCameraPosition[Z] - SHADOW_CAM_FRUSTUM_HALF_HEIGHT )\t||\r\n\t\t\t\t ( m_bounding_sphere[Z] - m_bounding_box[Z] ) > ( render::ShadowCameraPosition[Z] + SHADOW_CAM_FRUSTUM_HALF_HEIGHT ))\r\n\t\t{\r\n\t\t\trenderFlags &= ~RENDERFLAG_SHADOW;\r\n\t\t}\r\n\t}\r\n\t#endif\r\n\r\n\t// get this node's transform context\r\n\tCVu1Context *p_ctxt = &ctxt;\r\n\r\n\t// applying a colour to a node\r\n\tif (m_flags & NODEFLAG_COLOURED)\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_colored);\r\n\t\tp_ctxt = ctxt.Localise();\r\n\r\n\t\t// copy node's colour to vu1 context\r\n\t\tp_ctxt->SetColour(this);\r\n\t\trenderFlags |= RENDERFLAG_COLOURED;\r\n\t}\r\n\r\n\tGEOMSTATINC(geom_stats_leaf);\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t// Mick: check patch variables for debugging toggle of multi-passes\r\n\tif ((m_flags & gPassMask1) != gPassMask0)\r\n\t{\t\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\nnode_level--;\r\n#endif\r\n\t\treturn;\r\n\t}\r\n\t#endif\r\n\r\n\r\n\tasm __volatile__(\"\r\n\t\tqmfc2\t\t$8,$vf05\r\n\t\tsw\t\t\t$8,(%0)\r\n\t\": : \"r\" (&camera_sphere_z) : \"$8\" );\r\n\r\n\t#ifdef\t__LOD_MULTIPASS__\r\n\t// if 2nd+ pass, check to see if distance from camera is greater than allowed for multipass\r\n\tif ((m_flags & NODEFLAG_ZPUSH) && (-camera_sphere_z > render::sMultipassMaxDist))\r\n\t{\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\nnode_level--;\r\n#endif\r\n\t\treturn;\r\n\t}\r\n\t#endif\r\n\r\n\tif (m_flags & (NODEFLAG_UVWIBBLE | NODEFLAG_ENVMAPPED | NODEFLAG_VCWIBBLE))\r\n\t{\r\n\t\tif (m_flags & (NODEFLAG_UVWIBBLE | NODEFLAG_ENVMAPPED))\r\n\t\t{\r\n\t\t\t// if there's no local context, copy the global one\r\n\t\t\tif (p_ctxt == &ctxt)\r\n\t\t\t{\r\n\t\t\t\tp_ctxt = ctxt.LocaliseExtend();\r\n\t\t\t}\r\n\r\n\t\t\t// uv wibble\r\n\t\t\tif (m_flags & NODEFLAG_UVWIBBLE)\r\n\t\t\t{\r\n\t\t\t\tGEOMSTATINC(geom_stats_wibbleUV);\r\n\t\t\t\tp_ctxt->WibbleUVs(mp_uv_wibble, m_flags&NODEFLAG_EXPLICIT_UVWIBBLE);\r\n\t\t\t}\r\n\r\n\t\t\t// environment mapping\r\n\t\t\tif (m_flags & NODEFLAG_ENVMAPPED)\r\n\t\t\t{\r\n\t\t\t\t// reflection map vectors\r\n\t\t\t\tp_ctxt->SetReflectionVecs((sint16)(uint)mp_uv_wibble, (sint16)(((uint)mp_uv_wibble)>>16));\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// vc wibble\r\n\t\tif (m_flags & NODEFLAG_VCWIBBLE)\r\n\t\t{\r\n\t\t\tGEOMSTATINC(geom_stats_wibbleVC);\r\n\t\t\tWibbleVCs();\r\n\t\t}\r\n\t}\r\n\r\n\t// set the dma context\r\n\tdma::SetList(u3.mp_group);\r\n\tu3.mp_group->Used[render::Field] = true;\r\n\r\n\t// flag the texture as used\r\n\tif (u4.mp_texture)\r\n\t{\r\n\t\tu4.mp_texture->m_render_count++;\r\n\t}\r\n\r\n\r\n\tMth::Vector *p_trans = p_ctxt->GetTranslation();\r\n\r\n\t// initial cnt tag, for sending row reg and z-sort key\r\n\tdma::Tag(dma::cnt, 1, *(uint32 *)&camera_sphere_z);\r\n\tvif::NOP();\r\n\tvif::STROW((int)(*p_trans)[0] + (int)(m_bounding_sphere[0]*SUB_INCH_PRECISION),\r\n\t\t\t   (int)(*p_trans)[1] + (int)(m_bounding_sphere[1]*SUB_INCH_PRECISION),\r\n\t\t\t   (int)(*p_trans)[2] + (int)(m_bounding_sphere[2]*SUB_INCH_PRECISION), 0);\r\n\r\n\r\n\t// special case for billboards\r\n\tif (m_flags & NODEFLAG_BILLBOARD)\r\n\t{\r\n\t\t// compute billboard basis vecs\r\n\t\tMth::Vector udir,vdir;\r\n\t\tvdir = (*p_ctxt->GetMatrix())[1];\r\n\t\tvdir[2] =  0.0f;\r\n\t\tvdir[3] =  0.0f;\r\n\t\tvdir.Normalize();\r\n\t\tudir[0] =  vdir[1];\r\n\t\tudir[1] = -vdir[0];\r\n\t\tudir[2] =  0.0f;\r\n\t\tudir[3] =  0.0f;\r\n\r\n\t\tudir *= render::CameraToFrustum;\r\n\t\tvdir *= render::CameraToFrustum;\r\n\t\tudir[2] =  0.0f;\r\n\t\tudir[3] =  0.0f;\r\n\t\tvdir[2] =  0.0f;\r\n\t\tvdir[3] =  0.0f;\r\n\r\n\t\t// send vu1 context\r\n\t\tdma::Tag(dma::next, 16, (uint)dma::pLoc+272);\r\n\t\tvif::BASE(vu1::Loc);\r\n\t\tvif::OFFSET(0);\r\n\t\tuint vu1_loc = vu1::Loc;\r\n\t\tvu1::Loc = 0;   \t\t\t\t\t\t\t// must do this as a relative prim for a sortable list...\r\n\t\tvu1::BeginPrim(REL, VU1_ADDR(L_VF20));\r\n\t\tvu1::StoreVec(*(Vec *)&udir);\r\n\t\tvu1::StoreVec(*(Vec *)&vdir);\r\n\t\tvu1::StoreVec(*(Vec *)&render::IntViewportScale);\r\n\t\tvif::StoreV4_32(0,0,0,0);\r\n\t\tvif::StoreV4_32(0,0,0,0);\r\n\t\tvu1::StoreVec(*(Vec *)&render::CameraToWorld[3]);\r\n\t\tvu1::StoreVec(*(Vec *)ctxt.GetColour());\r\n\t\tvu1::StoreVec(*(Vec *)&render::IntViewportOffset);\r\n\t\tMth::Matrix LocalToFrustum = (*p_ctxt->GetMatrix()) * render::CameraToFrustum;\r\n\t\tvu1::CopyMat((float*)&LocalToFrustum);\r\n\t\tvu1::EndPrim(0);\r\n\r\n\t\t// gs context data, specifically the fog coefficient\r\n\t\tfloat w,f;\r\n\t\tif (renderFlags & RENDERFLAG_TRANSFORMED)\r\n\t\t{\r\n\t\t\tw = -(*p_ctxt->GetMatrix())[3][2];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Context only contains WorldToCamera matrix, so convert world position to camera relative position\r\n\t\t\tMth::Vector camera_rel_pos = render::WorldToCamera.TransformAsPos(m_bounding_sphere);\r\n\t\t\tw = -camera_rel_pos[2];\r\n\t\t}\r\n\t\tif ((w > render::FogNear) && render::EnableFog)\t// Garrett: We have to check for EnableFog here because the VU1 code isn't\r\n\t\t{\r\n\t\t\tf = 1.0 + render::EffectiveFogAlpha * (render::FogNear/w - 1.0f);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tf = 1.0f;\r\n\t\t}\r\n\t\tgs::BeginPrim(REL,0,0);\r\n\t\tgs::Reg1(gs::FOG, PackFOG((int)(f*255.99f)));\r\n\t\tgs::EndPrim(0);\r\n\r\n\t\tdma::EndTag();\r\n\t\t((uint16 *)dma::pTag)[1] |= vu1::Loc & 0x3FF;\t// must write some code for doing this automatically\r\n\t\tvu1::Loc += vu1_loc;\r\n\r\n\t\tu3.mp_group->pVu1Context = NULL;\r\n\t}\r\n\r\n\t// send transform context if necessary\r\n\telse if ((p_ctxt != u3.mp_group->pVu1Context) || (u3.mp_group->flags & GROUPFLAG_SORT))\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_sendcontext);\r\n\t\tint qwc = p_ctxt->IsExtended() ? EXT_CTXT_SIZE+2 : STD_CTXT_SIZE+2;\r\n\t\tdma::Tag(dma::ref, qwc|(qwc-1)<<16, p_ctxt->GetDma());\r\n\t\tvif::BASE(vu1::Loc);\r\n\t\tvif::OFFSET(0);\r\n\t\tvu1::Loc += qwc-1;\r\n\t\tu3.mp_group->pVu1Context = p_ctxt;\r\n\t}\r\n\r\n\t// render this node by adding to the chosen dma list\r\n\tuint vu1_flags = (renderFlags & RENDERFLAG_CLIP) ? CLIP :\r\n\t\t\t\t\t (renderFlags & RENDERFLAG_CULL) ? CULL : PROJ;\r\n\tif (renderFlags & RENDERFLAG_COLOURED)\r\n\t\tvu1_flags |= COLR;\r\n\tif (render::EnableFog && (m_bounding_sphere[W]-camera_sphere_z > render::FogNear))\r\n\t\tvu1_flags |= FOGE;\r\n\tdma::pTag = dma::pLoc;\t\t// must set this manually if we bypass the dma tag functions\r\n\tdma::Store32(u2.m_dma_tag_lo32,(uint32)u1.mp_dma);\r\n\tvif::BASE(vu1::Loc);\r\n\tvif::ITOP(vu1_flags);\r\n\tvu1::Loc += u2.m_dma_tag_lo32>>16;\r\n\r\n\tif (m_flags & NODEFLAG_BLACKFOG)\r\n\t{\r\n\t\tdma::Gosub(SET_FOGCOL,2);\r\n\t\tdma::pLoc -= 8;\r\n\t\tvif::FLUSHA();\r\n\t\tvif::NOP();\r\n\t}\r\n\r\n\t// must add a 'next' tag for sorted groups\r\n\tif (u3.mp_group->flags & GROUPFLAG_SORT)\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_sorted);\r\n\t\tdma::SetList(NULL);\r\n\t}\r\n\r\n\t#if !STENCIL_SHADOW\r\n\t// render shadow\r\n\tif ((renderFlags & RENDERFLAG_SHADOW) && !(m_flags & NODEFLAG_NOSHADOW))\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_shadow);\r\n\t\t// set the dma context\r\n\t\tdma::SetList(sGroup::pShadow);\r\n\r\n\t\t// set row reg\r\n\t\tdma::Tag(dma::cnt, 1, *(uint32 *)&camera_sphere_z);\r\n\t\tvif::NOP();\r\n\t\tvif::STROW((int)(*p_trans)[0] + (int)(m_bounding_sphere[0]*SUB_INCH_PRECISION),\r\n\t\t\t\t   (int)(*p_trans)[1] + (int)(m_bounding_sphere[1]*SUB_INCH_PRECISION),\r\n\t\t\t\t   (int)(*p_trans)[2] + (int)(m_bounding_sphere[2]*SUB_INCH_PRECISION), 0);\r\n\r\n\t\t// send transform context\r\n\t\tdma::Tag(dma::ref, 18|17<<16, sGroup::pShadow->pVu1Context->GetDma());\r\n\t\tvif::BASE(vu1::Loc);\r\n\t\tvif::OFFSET(0);\r\n\t\tvu1::Loc += 17;\r\n\r\n\t\t// render this node\r\n\t\tvu1_flags = (renderFlags & RENDERFLAG_CLIP) ? CLIP|SHDW :\r\n\t\t\t\t\t(renderFlags & RENDERFLAG_CULL) ? CULL|SHDW : PROJ|SHDW;\r\n\t\tif (render::EnableFog && (m_bounding_sphere[W]-camera_sphere_z > render::FogNear))\r\n\t\t\tvu1_flags |= FOGE;\r\n\t\tdma::pTag = dma::pLoc;\t\t// must set this manually if we bypass the dma tag functions\r\n\t\tdma::Store32(u2.m_dma_tag_lo32,(uint32)u1.mp_dma);\r\n\t\tvif::BASE(vu1::Loc);\r\n\t\tvif::ITOP(vu1_flags);\r\n\t\tvu1::Loc += u2.m_dma_tag_lo32>>16;\r\n\r\n\t\tif (m_flags & NODEFLAG_BLACKFOG)\r\n\t\t{\r\n\t\t\tdma::Gosub(SET_FOGCOL,2);\r\n\t\t\tdma::pLoc -= 8;\r\n\t\t\tvif::FLUSHA();\r\n\t\t\tvif::NOP();\r\n\t\t}\r\n\t}\r\n\t#endif\r\n\r\n#ifdef\tDUMP_NODE_STRUCTURE\r\n\tnode_level--;\r\n#endif\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Mick:  I've moved this function here to improved I-Cache usage while rendering\r\n\r\nbool TestSphereAgainstOccluders( Mth::Vector *p_center, float radius, uint32 meshes )\r\n{\r\n//\treturn false;\r\n\t// GJ:  This will catch bugs where a model's bounding sphere\r\n\t// is uninitialized, return inconsistent values depending on\r\n\t// the level you were in (this came up with the create-a-trick\r\n\t// skater, which uses \"ref models\", which don't have valid bounding\r\n\t// spheres)\r\n\t#if\t__ASSERT_ON_ZERO_RADIUS__\r\n\tDbg_MsgAssert( radius != 0.0f, ( \"Wasn't expecting a radius of 0\" ) );\r\n\t#endif\r\n\r\n#if defined(OCCLUDER_USES_VU0_MACROMODE) || defined(OCCLUDER_USES_VU0_MICROMODE)\r\n\r\n\tif (sOccluder::sUseVU0)\r\n\t{\r\n#ifdef\tOCCLUDER_USES_VU0_MACROMODE\r\n\t\tbool result;\r\n\r\n\t\tasm __volatile__(\r\n\t\t\"\r\n\t\t.set noreorder\r\n\t\tmfc1      $8, %3\t\t\t # radius\r\n\t\tqmtc2     $8, vf9\r\n\r\n\t\tvilwr.x   vi01, (vi00)\t\t # load number of occluders\r\n\r\n\t\tlqc2      vf10, 0x0(%1)\t\t # p_center\r\n\t\tctc2      %2, $vi15\t\t\t # meshes\r\n\r\n\t\tvaddw.x   vf31, vf00, vf00w  # Load 1.0f to VF31x\r\n\r\n\t\t# Init loop\r\n\t\tcfc2      $10,  $vi01\t\t # move number of occluders to $10\r\n\t\tbeq       $10,  $0, no_occlusions\r\n\t\tviaddi    vi02, vi00, 1\t\t # load address of first occluder\r\n\r\nocc_loop:\r\n\t\tviaddi    vi03, vi02, 0\t\t # and put here, too\r\n\t\tvlqi.xyzw vf01, (vi03++)\t # load planes\r\n\t\tli        $9, 5\t\t\t\t # number of planes\r\n\r\nplane_loop:\r\n\t\t# dot product\r\n\t\tvmul.xyz  vf11,vf01,vf10     # result = plane * center + plane_w [start]\r\n\t\tvmulax.x  ACC, vf01,vf10x\r\n\t\tvmaddaw.x ACC, vf31,vf01w\t # plane_w\r\n\t\tvmaddax.x ACC, vf31,vf09x    # also add radius in\r\n\t\tvmadday.x ACC, vf31,vf11y\r\n\t\tvmaddz.x  vf11,vf31,vf11z    # result = plane * center + plane_w + radius [ready]\r\n\r\n\t\taddi      $9, $9, -1         # decrement plane counter\r\n\t\tviaddi    vi04, vi02, 5\t\t # calc score address (since we are waiting anyway)\r\n\t\tvilwr.x   vi14, (vi04)\t\t # load score\r\n\t\tvlqi.xyzw vf01, (vi03++)\t # load next planes\r\n\t\tvnop\r\n\r\n\t\tcfc2      $8, $vi17\t\t\t # transfer if result (MAC register)\r\n\t\tandi\t  $8, $8, 0x80\t\t # check result (v >= 0) not_occluded\r\n\t\tbeq\t\t  $8, $0, done_occluder\r\n\t\tnop\r\n\r\n\t\tbne       $9, $0, plane_loop\r\n\t\tnop\r\n\r\n\t\t# got through all planes - found occluder\r\nfound_occluder:\r\n\t\tli\t\t  %0, 1\t\t\t\t # store true for return value\r\n\t\tviadd     vi14, vi14, vi15   # add meshes\r\n\t\tb         done\r\n\t\tviswr.x   vi14, (vi04)\r\n\r\ndone_occluder:\r\n\t\taddi      $10, $10, -1       # decrement occluder counter\r\n\t\tbne       $10, $0, occ_loop\r\n\t\tviaddi    vi02, vi02, 6\t\t # increment occluder address\r\n\r\nno_occlusions:\r\n\t\tli\t\t  %0, 0\t\t\t\t # store false for return value\r\n\r\ndone:\r\n\t\t.set reorder\r\n\t\t\": \"=r\" (result) : \"r\" (p_center), \"r\" (meshes), \"f\" (radius) : \"$8\", \"$9\", \"$10\");\r\n\r\n\t\treturn result;\r\n\r\n#endif\t// OCCLUDER_USES_VU0_MACROMODE\r\n\t\r\n#ifdef OCCLUDER_USES_VU0_MICROMODE\r\n\r\n\t\tuint32 result, index;\r\n\t\tMth::Vector sphere(*p_center);\r\n\t\tsphere[W] = radius;\r\n\r\n\t\t// call vu0 microsubroutine\r\n\t\tasm __volatile__(\"\r\n\r\n\t\t\tlqc2\t\tvf07,(%0)\t\t\t\t\t# load sphere (x,y,z,R) into vf07 of vu0\r\n\t\t\tvcallms\t\tTestSphereAgainstOccluders\t# call microsubroutine\r\n\t\t\tvnop\t\t\t\t\t\t\t\t\t# interlocking instruction, waits for vu0 completion\r\n\t\t\tcfc2\t\t$8,$vi01\t\t\t\t\t# get boolean result from vu0\r\n\t\t\tcfc2\t\t$9,$vi06\t\t\t\t\t# get index of first successful occluder\r\n\t\t\tsw\t\t\t$8,(%1)\t\t\t\t\t\t# store boolean result\r\n\t\t\tsw\t\t\t$9,(%2)\t\t\t\t\t\t# store index\r\n\t\t\r\n\t\t\": : \"r\" (&sphere), \"r\" (&result), \"r\" (&index) : \"$8\",\"$9\");\r\n\r\n\t\t// keeping score\r\n\t\tif (result)\r\n\t\t{\r\n\t\t\tsOccluder::Occluders[index].score += meshes;\r\n\t\t}\r\n\r\n\t\treturn (bool)result;\r\n\r\n#endif\t// OCCLUDER_USES_VU0_MICROMODE\r\n\t}\r\n\telse\r\n#endif // defined(OCCLUDER_USES_VU0_MACROMODE) || defined(OCCLUDER_USES_VU0_MICROMODE)\r\n\r\n\t{\r\n\t\tfloat center_x = p_center->GetX();\r\n\t\tfloat center_y = p_center->GetY();\r\n\t\tfloat center_z = p_center->GetZ();\r\n\r\n\t\tsOccluder * p_occluder;\r\n\t\tif (sOccluder::sUseScratchPad)\r\n\t\t{\r\n\t\t\tp_occluder = (sOccluder*)0x70000000;\r\n\t\t} else {\r\n\t\t\tp_occluder = &sOccluder::Occluders[0];\r\n\t\t}\r\n\r\n\t\t// Test against each occluder.\r\n\t\tfor( uint32 o = sOccluder::NumOccluders; o > 0 ; --o )\r\n\t\t{\r\n\t\t\tMth::Vector * p_plane = &(p_occluder->planes[0]);\r\n\t\t\t// Test against each plane in the occluder.\r\n\t\t\tfor( uint32 p = 5; p > 0; --p )\r\n\t\t\t{\r\n\r\n\t\t\t\tfloat result =\t( p_plane->GetX() * center_x ) +\r\n\t\t\t\t\t\t\t\t( p_plane->GetY() * center_y ) +\r\n\t\t\t\t\t\t\t\t( p_plane->GetZ() * center_z ) +\r\n\t\t\t\t\t\t\t\t( p_plane->GetW() );\r\n\r\n\t\t\t\tif( result >= -radius )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Outside of this plane, therefore not occluded by this occluder.\r\n\t\t\t\t\tgoto\tNOT_OCCLUDED;\r\n\t\t\t\t}\r\n\t\t\t\tp_plane++;\r\n\t\t\t}\r\n\r\n\t\t\t// Inside all five planes, therefore occluded. Increase score for this occluder.\r\n\t\t\tp_occluder->score += meshes;\r\n\t\t\treturn true;\r\n\r\n\tNOT_OCCLUDED:\t\t\r\n\t\t\tp_occluder++;\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CGeomNode::CullAgainstViewFrustum()\r\n{\r\n\r\n\tuint32 result;\r\n\r\n\t#if 0\r\n\r\n\t// test version... perform test and get results\r\n\tasm __volatile__(\"\r\n\r\n\t\tlqc2\t\tvf08,(%0)\t\t\t\t\t# sphere (x,y,z,R)\r\n\t\tlqc2\t\tvf09,(%1)\t\t\t\t\t# box (bx,by,bz,?)\r\n\t\tvcallms\t\tViewCullTest\t\t\t\t# call microsubroutine\r\n\t\tvnop\t\t\t\t\t\t\t\t\t# interlocking instruction, waits for vu0 completion\r\n\t\tcfc2\t\t$8,$vi01\t\t\t\t\t# get result\r\n\t\tsw\t\t\t$8,(%2)\t\t\t\t\t\t# store result\r\n\r\n\t\": : \"r\" (&m_bounding_sphere), \"r\" (&m_bounding_box), \"r\" (&result) : \"$8\");\r\n\r\n\r\n\t#else\r\n\t\r\n\t// faster version... pick up results from test which kicked off earlier\r\n\tasm __volatile__(\"\r\n\r\n\t\tvnop\t\t\t\t\t\t\t\t\t# interlocking instruction, waits for vu0 completion\r\n\t\tcfc2\t\t$8,$vi01\t\t\t\t\t# get result\r\n\t\tsw\t\t\t$8,(%0)\t\t\t\t\t\t# store result\r\n\r\n\t\": : \"r\" (&result) : \"$8\");\r\n\r\n\t#endif\r\n\r\n\treturn (bool)result;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CGeomNode::CullAgainstOuterFrustum()\r\n{\r\n\r\n\tuint32 result;\r\n\r\n\t#if 0\r\n\t\r\n\t// test version... perform test and get results\r\n\tasm __volatile__(\"\r\n\r\n\t\tlqc2\t\tvf08,(%0)\t\t\t\t\t# sphere (x,y,z,R)\r\n\t\tlqc2\t\tvf09,(%1)\t\t\t\t\t# box (bx,by,bz,?)\r\n\t\tvcallms\t\tOuterCullTest\t\t\t\t# call microsubroutine\r\n\t\tvnop\t\t\t\t\t\t\t\t\t# interlocking instruction, waits for vu0 completion\r\n\t\tcfc2\t\t$8,$vi01\t\t\t\t\t# get result\r\n\t\tsw\t\t\t$8,(%2)\t\t\t\t\t\t# store result\r\n\r\n\t\": : \"r\" (&m_bounding_sphere), \"r\" (&m_bounding_box), \"r\" (&result) : \"$8\");\r\n\r\n\t#else\r\n\t\r\n\t// faster version... pick up results from test which kicked off earlier\r\n\tasm __volatile__(\"\r\n\r\n\t\tcfc2\t\t$8,$vi11\t\t\t\t\t# get result\r\n\t\tsw\t\t\t$8,(%0)\t\t\t\t\t\t# store result\r\n\r\n\t\": : \"r\" (&result) : \"$8\");\r\n\r\n\t#endif\r\n\r\n\treturn (bool)result;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeomNode::RenderMinimalLeaf(CVu1Context& ctxt)\r\n{\r\n\tfloat camera_sphere_z;\r\n\r\n\t#if\t__ASSERT_ON_ZERO_RADIUS__\r\n\tDbg_MsgAssert( m_bounding_sphere[W] != 0.0f, ( \"Wasn't expecting a radius of 0 for geomnode %s or a sub-mesh of it. \\n perhaps it has isolated verts that need removing?\",Script::FindChecksumName(GetChecksum()) ) );\r\n\t#endif\r\n\t\r\n\tGEOMSTATINC(geom_stats_total);\r\n\r\n\tGEOMSTATINC(geom_stats_occludecheck);\r\n\tif (TestSphereAgainstOccluders( &m_bounding_sphere, m_bounding_sphere[W] ))\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_occluded);\r\n\t\treturn;\r\n\t}\r\n\r\n\tGEOMSTATINC(geom_stats_leaf);\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t// Mick: check patch variables for debugging toggle of multi-passes\r\n\tif ((m_flags & gPassMask1) != gPassMask0)\r\n\t{\t\r\n\t\treturn;\r\n\t}\r\n\t#endif\r\n\r\n\r\n\t// set the dma context\r\n\tdma::SetList(u3.mp_group);\r\n\tu3.mp_group->Used[render::Field] = true;\r\n\r\n\t// flag the texture as used\r\n\tif (u4.mp_texture)\r\n\t{\r\n\t\tu4.mp_texture->m_render_count++;\r\n\t}\r\n\r\n\r\n\tMth::Vector *p_trans = ctxt.GetTranslation();\r\n\t\r\n\r\n\tasm __volatile__(\"\r\n\t\tqmfc2\t\t$8,$vf05\r\n\t\tsw\t\t\t$8,(%0)\r\n\t\": : \"r\" (&camera_sphere_z) : \"$8\" );\r\n\r\n\r\n\t#ifdef\t__LOD_MULTIPASS__\r\n\t// if 2nd+ pass, check to see if distance from camera is greater than allowed for multipass\r\n//\t\tif ((m_flags & NODEFLAG_ZPUSH) && (-camera_sphere[Z] > render::sMultipassMaxDist))\r\n\tif ((m_flags & NODEFLAG_ZPUSH) && (-camera_sphere_z > render::sMultipassMaxDist))\r\n\t\treturn;\r\n\t#endif\r\n\r\n\t// initial cnt tag, for sending row reg and z-sort key\r\n\tdma::Tag(dma::cnt, 1, *(uint32 *)&camera_sphere_z);\r\n\tvif::NOP();\r\n\tvif::STROW((int)(*p_trans)[0] + (int)(m_bounding_sphere[0]*SUB_INCH_PRECISION),\r\n\t\t\t   (int)(*p_trans)[1] + (int)(m_bounding_sphere[1]*SUB_INCH_PRECISION),\r\n\t\t\t   (int)(*p_trans)[2] + (int)(m_bounding_sphere[2]*SUB_INCH_PRECISION), 0);\r\n\r\n\t// send transform context if necessary\r\n\tif ((&ctxt != u3.mp_group->pVu1Context) || (u3.mp_group->flags & GROUPFLAG_SORT))\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_sendcontext);\r\n\t\t//Dbg_MsgAssert(!ctxt.IsExtended(), (\"oh bugger\"));\r\n\t\tint qwc = ctxt.IsExtended() ? EXT_CTXT_SIZE+2 : STD_CTXT_SIZE+2;\r\n\t\tdma::Tag(dma::ref, qwc|(qwc-1)<<16, ctxt.GetDma());\r\n\t\tvif::BASE(vu1::Loc);\r\n\t\tvif::OFFSET(0);\r\n\t\tvu1::Loc += qwc-1;\r\n\t\tu3.mp_group->pVu1Context = &ctxt;\r\n\t}\r\n\r\n\t// render this node by adding to the chosen dma list\r\n\tdma::pTag = dma::pLoc;\t\t// must set this manually if we bypass the dma tag functions\r\n\tdma::Store32(u2.m_dma_tag_lo32,(uint32)u1.mp_dma);\r\n\tvif::BASE(vu1::Loc);\r\n\tif (render::EnableFog && (m_bounding_sphere[W]-camera_sphere_z > render::FogNear))\r\n\t\tvif::ITOP(PROJ|FOGE);\r\n\telse\r\n\t\tvif::ITOP(PROJ);\r\n\tvu1::Loc += u2.m_dma_tag_lo32>>16;\r\n\r\n\tif (m_flags & NODEFLAG_BLACKFOG)\r\n\t{\r\n\t\tdma::Gosub(SET_FOGCOL,2);\r\n\t\tdma::pLoc -= 8;\r\n\t\tvif::FLUSHA();\r\n\t\tvif::NOP();\r\n\t}\r\n\r\n\t// must add a 'next' tag for sorted groups\r\n\tif (u3.mp_group->flags & GROUPFLAG_SORT)\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_sorted);\r\n\t\tdma::SetList(NULL);\r\n\t}\r\n\t\r\n\t\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeomNode::RenderAsSky(CVu1Context& ctxt, uint32 renderFlags)\r\n{\r\n\tCVu1Context *p_ctxt;\r\n\r\n\t// cull the node if not active\r\n\tif (!(m_flags & NODEFLAG_ACTIVE))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// no support for transformed nodes yet...\r\n\tp_ctxt = &ctxt;\r\n\r\n\tMth::Vector sphere;\r\n\r\n\t// bounding sphere tests, based on parent render flags\r\n\tif (renderFlags & (RENDERFLAG_CLIP | RENDERFLAG_CULL))\r\n\t{\r\n\t\t// get and transform centre of bounding sphere\r\n\t\tsphere = m_bounding_sphere;\r\n\t\tsphere[W] = 1.0f;\r\n\t\tsphere *= *p_ctxt->GetMatrix();\r\n\t\tsphere[W] = m_bounding_sphere[W];\r\n\t\t\t\t\t  \r\n\t\tif (SphereIsOutsideViewVolume(sphere))\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (SphereIsInsideOuterVolume(sphere))\r\n\t\t{\r\n\t\t\trenderFlags &= ~(RENDERFLAG_CLIP|RENDERFLAG_CULL);\r\n\t\t}\r\n\r\n\t\telse if ((renderFlags & RENDERFLAG_CLIP) && !NeedsClipping(sphere))\r\n\t\t{\r\n\t\t\trenderFlags = renderFlags & ~RENDERFLAG_CLIP | RENDERFLAG_CULL;\r\n\t\t}\r\n    }\r\n\t\r\n\t// applying a colour to a node (copied from Geomnode::Render)\r\n\tif (m_flags & NODEFLAG_COLOURED)\r\n\t{\r\n\t\tGEOMSTATINC(geom_stats_colored);\r\n\t\t// if there's no local context, copy the parent's\r\n\t\tif (p_ctxt == &ctxt)\r\n\t\t{\r\n\t\t\tp_ctxt = ctxt.Localise();\r\n\t\t}\r\n\r\n\t\t// copy node's colour to vu1 context\r\n\t\tp_ctxt->SetColour(this);\r\n\t\trenderFlags |= RENDERFLAG_COLOURED;\r\n\t}\r\n\r\n\r\n\t// is it a leaf node?\r\n\tif (m_flags & NODEFLAG_LEAF)\r\n\t{\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t// Mick: check patch variables for debugging toggle of multi-passes\r\n\t\tif ((m_flags & gPassMask1) != gPassMask0)\r\n\t\t{\t\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t#endif\r\n\t\t\r\n\t\t// uv wibble\r\n\t\tif (m_flags & NODEFLAG_UVWIBBLE)\r\n\t\t{\r\n\t\t\t// if there's no local context, copy the global one\r\n\t\t\tif (p_ctxt == &ctxt)\r\n\t\t\t{\r\n\t\t\t\tp_ctxt = ctxt.LocaliseExtend();\r\n\t\t\t}\r\n\r\n\t\t\tGEOMSTATINC(geom_stats_wibbleUV);\r\n\t\t\tp_ctxt->WibbleUVs(mp_uv_wibble, m_flags&NODEFLAG_EXPLICIT_UVWIBBLE);\r\n\t\t}\r\n\r\n\t\t// set the dma context\r\n\t\tdma::SetList(u3.mp_group);\r\n\t\tu3.mp_group->Used[render::Field] = true;\r\n\r\n\t\t// initial cnt tag, for sending row reg and z-sort key\r\n\t\tdma::Tag(dma::cnt, 1, 0);\r\n\t\tvif::NOP();\r\n\t\tvif::STROW((int)(m_bounding_sphere[0]*SUB_INCH_PRECISION),\r\n\t\t\t\t   (int)(m_bounding_sphere[1]*SUB_INCH_PRECISION),\r\n\t\t\t\t   (int)(m_bounding_sphere[2]*SUB_INCH_PRECISION), 0);\r\n\r\n\t\t// send transform context if necessary\r\n\t\tif (p_ctxt != u3.mp_group->pVu1Context)\r\n\t\t{\r\n\t\t\tint qwc = p_ctxt->IsExtended() ? EXT_CTXT_SIZE+2 : STD_CTXT_SIZE+2;\r\n\t\t\tdma::Tag(dma::ref, qwc|(qwc-1)<<16, p_ctxt->GetDma());\r\n\t\t\tvif::BASE(vu1::Loc);\r\n\t\t\tvif::OFFSET(0);\r\n\t\t\tvu1::Loc += qwc-1;\r\n\t\t\tu3.mp_group->pVu1Context = p_ctxt;\r\n\t\t}\r\n\r\n\t\t// render this node by adding to the chosen dma list\r\n\t\tuint vu1_flags = (renderFlags & RENDERFLAG_CLIP) ? CLIP :\r\n\t\t\t\t\t\t (renderFlags & RENDERFLAG_CULL) ? CULL : PROJ;\r\n\t\tif (renderFlags & RENDERFLAG_COLOURED)\r\n\t\t\tvu1_flags |= COLR;\r\n\t\tif (render::EnableFog)\r\n\t\t\tvu1_flags |= FOGE;\r\n\t\tdma::pTag = dma::pLoc;\t\t// must set this manually if we bypass the dma tag functions\r\n\t\tdma::Store32(u2.m_dma_tag_lo32, (uint32)u1.mp_dma);\r\n\t\tvif::BASE(vu1::Loc);\r\n\t\tvif::ITOP(vu1_flags);\r\n\t\tvu1::Loc += u2.m_dma_tag_lo32>>16;\r\n\r\n\t\tif (m_flags & NODEFLAG_BLACKFOG)\r\n\t\t{\r\n\t\t\tdma::Gosub(SET_FOGCOL,2);\r\n\t\t\tdma::pLoc -= 8;\r\n\t\t\tvif::FLUSHA();\r\n\t\t\tvif::NOP();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// render any children\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_child->RenderAsSky(*p_ctxt, renderFlags);\r\n\t\t}\r\n\t}\r\n\r\n}\r\n\r\n\r\n\r\nvoid CGeomNode::SetBoneTransforms(Mth::Matrix *pMat)\r\n{\r\n\r\n\t#if 0\t// single-buffered\r\n\t\r\n\t// copy the given matrices into the matrix buffer\r\n\tfor (int i = 0; i < m_num_bones; i++)\r\n\t{\r\n\t\tu4.mp_bone_transforms[i] = pMat[i];\r\n\t}\r\n\r\n\t#else\t// double-buffered\r\n\t\r\n\tint startIndex = m_field ? m_num_bones : 0;\r\n\r\n\t// copy the given matrices into the correct half of the matrix buffer\r\n\tfor (int i = 0; i < m_num_bones; i++)\r\n\t{\r\n\t\tu4.mp_bone_transforms[startIndex+i] = pMat[i];\r\n\t}\r\n\r\n\t// toggle field\r\n\tm_field = !m_field;\r\n\r\n\t#endif\r\n\t\r\n}\r\n\r\n\r\n\r\n#endif\r\n\r\n\r\nbool CGeomNode::IsLeaf()\r\n{\r\n\treturn GET_FLAG(NODEFLAG_LEAF);\r\n}\r\n\r\n\r\nbool CGeomNode::IsObject()\r\n{\r\n\treturn GET_FLAG(NODEFLAG_OBJECT);\r\n}\r\n\r\n\r\nbool CGeomNode::IsActive()\r\n{\r\n\treturn GET_FLAG(NODEFLAG_ACTIVE);\r\n}\r\n\r\n\r\nbool CGeomNode::IsTransformed()\r\n{\r\n\treturn GET_FLAG(NODEFLAG_TRANSFORMED);\r\n}\r\n\r\n\r\nbool CGeomNode::IsSky()\r\n{\r\n\treturn GET_FLAG(NODEFLAG_SKY);\r\n}\r\n\r\n\r\nbool CGeomNode::IsColored()\r\n{\r\n\treturn GET_FLAG(NODEFLAG_COLOURED);\r\n}\r\n\r\n\r\nbool CGeomNode::IsSkeletal()\r\n{\r\n\treturn GET_FLAG(NODEFLAG_SKELETAL);\r\n}\r\n\r\n\r\nbool CGeomNode::IsEnvMapped()\r\n{\r\n\treturn GET_FLAG(NODEFLAG_ENVMAPPED);\r\n}\r\n\r\n\r\nbool CGeomNode::IsUVWibbled()\r\n{\r\n\treturn GET_FLAG(NODEFLAG_UVWIBBLE);\r\n}\r\n\r\nbool CGeomNode::IsBillboard()\r\n{\r\n\treturn GET_FLAG(NODEFLAG_BILLBOARD);\r\n}\r\n\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\nbool CGeomNode::WasRendered()\r\n{\r\n\treturn GET_FLAG(NODEFLAG_WAS_RENDERED);\r\n}\r\n#endif\r\n\r\nvoid CGeomNode::SetLeaf(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_LEAF);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetObject(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_OBJECT);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetActive(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_ACTIVE);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetTransformed(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_TRANSFORMED);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetSky(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_SKY);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetZPush0(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_ZPUSH0);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetZPush1(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_ZPUSH1);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetZPush2(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_ZPUSH2);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetZPush3(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_ZPUSH3);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetNoShadow(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_NOSHADOW);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetUVWibbled(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_UVWIBBLE);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetVCWibbled(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_VCWIBBLE);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetColored(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_COLOURED);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetSkinned(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_SKINNED);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetBillboard(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_BILLBOARD);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetSkeletal(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_SKELETAL);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetEnvMapped(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_ENVMAPPED);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetBlackFog(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_BLACKFOG);\r\n}\r\n\r\n\r\nuint32 CGeomNode::GetChecksum()\r\n{\r\n\treturn m_checksum;\r\n}\r\n\r\n\r\nvoid CGeomNode::SetChecksum(uint32 checksum)\r\n{\r\n\tm_checksum = checksum;\r\n}\r\n\r\n\r\nvoid CGeomNode::SetBoundingSphere(float x, float y, float z, float R)\r\n{\r\n\tm_bounding_sphere[0] = x;\r\n\tm_bounding_sphere[1] = y;\r\n\tm_bounding_sphere[2] = z;\r\n\tm_bounding_sphere[3] = R;\r\n}\r\n\r\n\r\nvoid CGeomNode::SetBoundingBox(float x, float y, float z)\r\n{\r\n\tm_bounding_box[0] = x;\r\n\tm_bounding_box[1] = y;\r\n\tm_bounding_box[2] = z;\r\n}\r\n\r\n\r\nuint8 *CGeomNode::GetDma()\r\n{\r\n\treturn (m_flags & NODEFLAG_LEAF) ? u1.mp_dma : NULL;\r\n}\r\n\r\n\r\nvoid CGeomNode::SetDma(uint8 *pDma)\r\n{\r\n\tm_flags |= NODEFLAG_LEAF;\r\n\tu1.mp_dma = pDma;\r\n}\r\n\r\n\r\nvoid CGeomNode::SetDmaTag(uint8 *pDma)\r\n{\r\n\tm_flags |= NODEFLAG_LEAF;\r\n\tu2.m_dma_tag_lo32 = dma::call<<28 | (((uint16 *)pDma)[1]&0x3FF)<<16 | 0;\r\n\tu1.mp_dma = pDma;\r\n}\r\n\r\n\r\nCGeomNode *CGeomNode::GetChild()\r\n{\r\n\treturn (m_flags & NODEFLAG_LEAF) ? NULL : u1.mp_child;\r\n}\r\n\r\n\r\nvoid CGeomNode::SetChild(CGeomNode *pChild)\r\n{\r\n\tm_flags &= ~NODEFLAG_LEAF;\r\n\tu1.mp_child = pChild;\r\n}\r\n\r\nvoid CGeomNode::AddChild(CGeomNode *pChild)\r\n{\r\n\tif (!(m_flags & NODEFLAG_LEAF) && u1.mp_child)\r\n\t{\r\n\t\tDbg_Assert(!pChild->mp_sibling);\r\n\r\n\t\tCGeomNode *p_last_child = u1.mp_child;\r\n\t\twhile (p_last_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_last_child = p_last_child->mp_sibling;\r\n\t\t}\r\n\r\n\t\tp_last_child->mp_sibling = pChild;\r\n\t} else {\r\n\t\tu1.mp_child = pChild;\r\n\t}\r\n\r\n\tm_flags &= ~NODEFLAG_LEAF;\r\n}\r\n\r\n\r\nCGeomNode *CGeomNode::GetSibling()\r\n{\r\n\treturn mp_sibling;\r\n}\r\n\r\n\r\nvoid CGeomNode::SetSibling(CGeomNode *pSibling)\r\n{\r\n\tmp_sibling = pSibling;\r\n}\r\n\r\nvoid CGeomNode::SetSlaveLOD(CGeomNode *pLOD)\r\n{\r\n    CGeomNode *pLOD_list = this;\r\n\r\n\twhile (pLOD_list->mp_next_LOD) {\r\n\t\tif (pLOD_list->mp_next_LOD->m_LOD_far_dist > pLOD->m_LOD_far_dist) {\r\n\t\t\tpLOD->mp_next_LOD = pLOD_list->mp_next_LOD;\r\n\t\t\tpLOD_list->mp_next_LOD = pLOD;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tpLOD_list = pLOD_list->mp_next_LOD;\r\n\t}\r\n\r\n\t// If we get here, then we are at the end of the list\r\n\tpLOD_list->mp_next_LOD = pLOD; \r\n}\r\n\t\r\nvoid CGeomNode::SetLODFarDist(float LOD_far_dist)\r\n{\r\n\tm_LOD_far_dist = LOD_far_dist;\r\n}\r\n\r\nfloat CGeomNode::GetLODFarDist()\r\n{\r\n\treturn m_LOD_far_dist;\r\n}\r\n\r\nsGroup *CGeomNode::GetGroup()\r\n{\r\n\treturn u3.mp_group;\r\n}\r\n\r\n\r\nvoid CGeomNode::SetGroup(sGroup *pGroup)\r\n{\r\n\tu3.mp_group = pGroup;\r\n}\r\n\r\n\r\nMth::Matrix& CGeomNode::GetMatrix()\r\n{\r\n\tDbg_MsgAssert(IsTransformed(), (\"trying to access matrix of a non-transformed CGeomNode\"));\r\n\tDbg_MsgAssert(u2.mp_transform, (\"null matrix pointer\"));\r\n\tDbg_MsgAssert(!(m_flags&NODEFLAG_LEAF), (\"Transformed leaf node\\n\"));\r\n\treturn *u2.mp_transform;\r\n}\r\n\r\n\r\nvoid CGeomNode::SetMatrix(Mth::Matrix *p_mat)\r\n{\r\n\tDbg_MsgAssert(!(m_flags&NODEFLAG_LEAF), (\"Transformed leaf node\\n\"));\r\n\tu2.mp_transform = (Mth::Matrix *)p_mat;\r\n\tSetTransformed(p_mat ? true : false);\r\n}\r\n\r\n\r\nvoid CGeomNode::SetUVWibblePointer(float *pData)\r\n{\r\n\tmp_uv_wibble = pData;\r\n}\r\n\r\n\r\nvoid CGeomNode::SetVCWibblePointer(uint32 *pData)\r\n{\r\n\tmp_vc_wibble = pData;\r\n}\r\n\r\n\r\nvoid CGeomNode::SetColor(uint32 rgba)\r\n{\r\n\tif (rgba == 0x80808080)\r\n\t{\r\n\t\t// clear the colored falg if set to the neutral color\r\n\t\t// as things render a lot quicker that way\r\n\t\t// also, applying the color gives a slightly different\r\n\t\t// value from not applying any color\r\n\t\tSetColored(false);\r\n\t}\r\n\t\r\n\tm_colour = rgba;\r\n}\r\n\r\n\r\nuint32 CGeomNode::GetColor()\r\n{\r\n\tif (IsColored())\r\n\t{\r\n\t\treturn m_colour;\r\n\t} else {\r\n\t\treturn 0x80808080;\r\n\t}\r\n}\r\n\r\n\r\nvoid CGeomNode::SetLightGroup(CLightGroup *p_light_group)\r\n{\r\n\tif (!IsLeaf())\r\n\t{\r\n\t\tu3.mp_light_group = p_light_group;\r\n\t}\r\n}\r\n\r\n\r\nCLightGroup * CGeomNode::GetLightGroup()\r\n{\r\n\tif (!IsLeaf())\r\n\t{\r\n\t\treturn u3.mp_light_group;\r\n\t} else {\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\n\r\nvoid CGeomNode::SetVisibility(uint8 mask)\r\n{\r\n\tm_flags &= ~ALL_VISIBILITY_BITS;\t\t// Take out old visibility bits\r\n\tm_flags |= (mask << VISIBILITY_FLAG_BIT);\r\n}\r\n\r\n\r\nuint8 CGeomNode::GetVisibility()\r\n{\r\n\treturn (m_flags & ALL_VISIBILITY_BITS) >> VISIBILITY_FLAG_BIT;\r\n}\r\n\r\n\r\nvoid CGeomNode::SetBoneIndex(sint8 index)\r\n{\r\n\tm_bone_index = index;\r\n}\r\n\r\n\r\nsint8 CGeomNode::GetBoneIndex()\r\n{\r\n\treturn m_bone_index;\r\n}\r\n\r\nvoid\tCGeomNode::CountMetrics(CGeomMetrics *p_metrics)\r\n{\r\n\tp_metrics->m_total++;\r\n\tif (IsObject()) \r\n\t{\r\n\t\tp_metrics->m_object++;\t\t\t\t\r\n\t}\r\n\tif (IsLeaf())\r\n\t{\r\n\t\tp_metrics->m_leaf++;\r\n\t\tp_metrics->m_verts += dma::GetNumVertices(u1.mp_dma);\r\n\t\tp_metrics->m_polys += dma::GetNumTris(u1.mp_dma);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_child->CountMetrics(p_metrics);\r\n\t\t}\r\n\t}\r\n\t\r\n}\r\n\r\n\r\nstatic Mth::Vector\t*p_verts = NULL; \r\n\r\nvoid\tCGeomNode::RenderWireframe(int mode)\r\n{\r\n#ifdef\t__PLAT_NGPS__\r\n\tint lines = 0;\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\tp_verts = new Mth::Vector[100000];\r\n\tMem::Manager::sHandle().PopContext();\r\n\tRenderWireframeRecurse(mode, lines);\r\n\tdelete p_verts;\r\n\tp_verts = NULL;\r\n#endif\r\n}\r\n\r\nvoid\tCGeomNode::RenderWireframeRecurse(int mode, int &lines)\r\n{\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n\tint sectors = 0;\r\n\tint vert_count=0;\r\n\r\n\tif (IsLeaf())\r\n\t{\r\n\t\tif (lines < 95000)  // clmap number of lines, otherwise we crash\r\n\t\t{\r\n\t\t\tsectors++;\r\n\t\t\r\n\t\t\t//\r\n\t\t\t// Do renderable geometry\r\n\t\t\tint verts = GetNumVerts();\r\n\t\t\tif (verts>2)\r\n\t\t\t{\r\n\t\t\t\tvert_count += verts;  \r\n\t\t\t\t  \r\n\t\t\t\t#define\tpeak 500\r\n\t\t\t\tint n=GetNumPolys();\r\n\t\t\t\tint r,g,b;\r\n\t\t\t\tr=g=b=0;\r\n\t\t\t\tif (n <= peak )\r\n\t\t\t\t{\r\n\t\t\t\t\tr = (255 * (n)) / peak;  \t// r ramps up (black to red)\t\r\n\t\t\t\t}\r\n\t\t\t\telse if (n <= peak * 2)\r\n\t\t\t\t{\r\n\t\t\t\t\tr = 255;\r\n\t\t\t\t\tb = (255 * (n - peak) / (peak));\t// b&g ramps up (to white)\r\n\t\t\t\t\tg = b;\r\n\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tr = g = b = 255;\r\n\t\t\t\t}\r\n\t\t\t\tuint32 rgb = (b<<16)|(g<<8)|r;\t\r\n\t\r\n\t\t\t\t\r\n\t\t\t\tif (mode == 4)\r\n\t\t\t\t{\r\n\t\t\t\t\t// generate a random looking number that's basically a hash of some\r\n\t\t\t\t\t// values in the node, so it stays the same\r\n\t\t\t\t\tuint32 xxx = ((uint32)(this) * verts  * n);\r\n\t\t\t\t\tNxPs2::BeginLines3D(0x80000000 + (0x00ffffff & xxx));\t\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tNxPs2::BeginLines3D(0x80000000 + (0x00ffffff & rgb));\t\t\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tGetVerts(p_verts);\r\n\t\t\t\tMth::Vector *p_vert = p_verts+1;\r\n\t\t\t\tfor (int i = 1; i < verts; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tNxPs2::DrawLine3D((*p_vert)[X],(*p_vert)[Y],(*p_vert)[Z],p_vert[-1][X],p_vert[-1][Y],p_vert[-1][Z]);\t\t\t\t\t\t\t\t\r\n\t\t\t\t\tp_vert++;\r\n\t\t\t\t\tlines++;\r\n\t\t\t\t} // end for\r\n\t\t\r\n\t\t\t\tNxPs2::EndLines3D();\r\n\t\t\t} // end if\r\n\t\t}\t\t\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (WasRendered())\r\n\t\t{\r\n\t\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t\t{\r\n\t\t\t\tp_child->RenderWireframeRecurse(mode, lines);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\n\r\nint\tCGeomNode::GetNumVerts()\r\n{\r\n\tint num_verts = 0;\r\n\r\n\tif (IsLeaf())\r\n\t{\r\n\t\tnum_verts = dma::GetNumVertices(u1.mp_dma);\r\n\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Check if we have LODs\r\n\t\tif (IsObject())\r\n\t\t{\r\n\t\t\tif (mp_next_LOD)\r\n\t\t\t{\r\n\t\t\t\tnum_verts += mp_next_LOD->GetNumVerts();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tnum_verts += p_child->GetNumVerts();\r\n\t\t}\r\n\t}\r\n\r\n\treturn num_verts;\r\n}\r\n\r\n\r\nint\tCGeomNode::GetNumPolys()\r\n{\r\n\tint num_polys = 0;\r\n\r\n\tif (IsLeaf())\r\n\t{\r\n\t\tnum_polys = dma::GetNumTris(u1.mp_dma);\r\n\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Check if we have LODs\r\n\t\tif (IsObject())\r\n\t\t{\r\n\t\t\tif (mp_next_LOD)\r\n\t\t\t{\r\n\t\t\t\tnum_polys += mp_next_LOD->GetNumPolys();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tnum_polys += p_child->GetNumPolys();\r\n\t\t}\r\n\t}\r\n\r\n\treturn num_polys;\r\n}\r\n\r\n\r\nint\tCGeomNode::GetNumBasePolys()\r\n{\r\n\tint num_base_polys = 0;\r\n\r\n\tif (IsLeaf())\r\n\t{\r\n\t\tif ((m_flags & NODEFLAG_ZPUSH) == 0)\t\t// check it's the base layer\r\n\t\t{\r\n\t\t\tnum_base_polys = dma::GetNumTris(u1.mp_dma);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Check if we have LODs\r\n\t\tif (IsObject())\r\n\t\t{\r\n\t\t\tif (mp_next_LOD)\r\n\t\t\t{\r\n\t\t\t\tnum_base_polys += mp_next_LOD->GetNumBasePolys();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tnum_base_polys += p_child->GetNumBasePolys();\r\n\t\t}\r\n\t}\r\n\r\n\treturn num_base_polys;\r\n}\r\n\r\n\r\nint\tCGeomNode::GetNumObjects()\r\n{\r\n\tint num_objects = 0;\r\n\r\n\t// Check self\r\n\tif (IsObject())\r\n\t{\r\n\t\tnum_objects++;\r\n\t}\r\n\r\n\t// Recursively check children\r\n\tif (!IsLeaf())\r\n\t{\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tnum_objects += p_child->GetNumObjects();\r\n\t\t}\r\n\t}\r\n\r\n\treturn num_objects;\r\n}\r\n\r\n\r\nCGeomNode*\tCGeomNode::GetObject(int num, bool root)\r\n{\r\n\tstatic int found_so_far;\r\n\r\n\tif (root)\r\n\t{\r\n\t\tfound_so_far = -1;\r\n\t\t//Dbg_Message(\"Start looking for #%d\", num);\r\n\t}\r\n\r\n\t// Check self\r\n\tif (IsObject())\r\n\t{\r\n\t\tif (++found_so_far == num)\r\n\t\t{\r\n\t\t\t//Dbg_Message(\"Found object #%d\", num);\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\t//Dbg_Message(\"Found object #%d; looking for #%d\", found_so_far, num);\r\n\t}\r\n\r\n\tCGeomNode *p_found = NULL;\r\n\r\n\t// Recursively check children\r\n\tif (!IsLeaf())\r\n\t{\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_found = p_child->GetObject(num, false);\r\n\t\t\tif (p_found)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tif (root)\r\n\t{\r\n\t\tDbg_Assert(p_found);\r\n\t}\r\n\r\n\treturn p_found;\r\n}\r\n\r\n\r\n#ifdef __PLAT_WN32__\r\n\r\nvoid CGeomNode::Preprocess(uint8 *p_baseAddress)\r\n{\r\n\t// recursively process any children\r\n\tCGeomNode *p_child, *p_sibling;\r\n\tif (!(m_flags & NODEFLAG_LEAF))\r\n\t{\r\n\t\tfor (p_child=u1.mp_child; p_child; p_child=p_sibling)\r\n\t\t{\r\n\t\t\tp_sibling = p_child->mp_sibling;\r\n\t\t\tp_child->Preprocess(p_baseAddress);\r\n\t\t}\r\n\t}\r\n\r\n\t// recursively process any LODs\r\n\tif (mp_next_LOD)\r\n\t{\r\n\t\tmp_next_LOD->Preprocess(p_baseAddress);\r\n\t}\r\n\r\n\tif (!(m_flags & NODEFLAG_LEAF))\r\n\t{\r\n\t\t// convert transform pointer to offset\r\n\t\tif (u2.mp_transform)\r\n\t\t{\r\n\t\t\tu2.mp_transform = (Mth::Matrix *) ( (uint8 *)u2.mp_transform - p_baseAddress );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tu2.mp_transform = (Mth::Matrix *)(-1);\r\n\t\t}\r\n\t}\r\n\r\n\tif (m_flags & NODEFLAG_LEAF)\r\n\t{\r\n\t\t// convert dma pointer to offset\r\n\t\tif (u1.mp_dma)\r\n\t\t{\r\n\t\t\tu1.mp_dma = (uint8 *)( u1.mp_dma - p_baseAddress );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tu1.mp_dma = (uint8 *)(-1);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// convert child pointer to offset\r\n\t\tif (u1.mp_child)\r\n\t\t{\r\n\t\t\tu1.mp_child = (CGeomNode *) ( (uint8 *)u1.mp_child - p_baseAddress );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tu1.mp_child = (CGeomNode *)(-1);\r\n\t\t}\r\n\t}\r\n\r\n\t// leave group checksum alone\r\n\r\n\t// convert sibling pointer to offset\r\n\tif (mp_sibling)\r\n\t{\r\n\t\tmp_sibling = (CGeomNode *) ( (uint8 *)mp_sibling - p_baseAddress );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_sibling = (CGeomNode *)(-1);\r\n\t}\r\n\r\n\t// convert LOD pointer to offset\r\n\tif (mp_next_LOD)\r\n\t{\r\n\t\tmp_next_LOD = (CGeomNode *) ( (uint8 *)mp_next_LOD - p_baseAddress );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_next_LOD = (CGeomNode *)(-1);\r\n\t}\r\n\r\n\t// convert uv wibble pointer to offset\r\n\tif (m_flags & NODEFLAG_UVWIBBLE)\r\n\t{\r\n\t\tif (!(m_flags & NODEFLAG_ENVMAPPED) || !(m_flags & NODEFLAG_LEAF))\t\t// can't wibble environment-mapped leaves\r\n\t\t{\r\n\t\t\tmp_uv_wibble = (float *) ( (uint8 *)mp_uv_wibble - p_baseAddress );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_uv_wibble = (float *)(-1);\r\n\t\t}\r\n\t}\r\n\r\n\t// convert vc wibble pointer to offset\r\n\tif (m_flags & NODEFLAG_VCWIBBLE)\r\n\t{\r\n\t\t// first convert mesh info\r\n\t\tuint32 *p_meshdata = mp_vc_wibble;\r\n\t\tint seq, num_seqs, vert, num_verts;\r\n\r\n\t\tnum_seqs = *p_meshdata++;\r\n\t\tfor (seq=0; seq<num_seqs; seq++)\r\n\t\t{\r\n\t\t\t// convert sequence pointer\r\n\t\t\t*(uint32 **)p_meshdata = (uint32 *) ( (uint8 *)*p_meshdata - p_baseAddress );\r\n\t\t\tp_meshdata++;\r\n\r\n\t\t\t// convert rgba pointers\r\n\t\t\tnum_verts = *p_meshdata++;\r\n\t\t\tfor (vert=0; vert<num_verts; vert++)\r\n\t\t\t{\r\n\t\t\t\t*(uint32 **)p_meshdata = (uint32 *) ( (uint8 *)*p_meshdata - p_baseAddress );\r\n\t\t\t\tp_meshdata++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// now the wibble pointer\r\n\t\tmp_vc_wibble = (uint32 *) ( (uint8 *)mp_vc_wibble - p_baseAddress );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_vc_wibble = (uint32 *)(-1);\r\n\t}\r\n\r\n}\r\n\r\n#endif\r\n\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\nstatic int SNL_Depth = 0;\r\n\t\t\t\t\t\t\t\t\t\t\t\t  \r\nvoid\t\tStripNiceLeaves(CGeomNode *p_parent)\r\n{\r\n\tSNL_Depth++;\r\n\tCGeomNode *p_child = p_parent->GetChild();\r\n\t// iterate over siblings without recursion\r\n\twhile (p_child)\t\r\n\t{\r\n\t\t\r\n\t\tprintf (\"%2d:\",SNL_Depth);\r\n\t\tfor (int i=i;i<SNL_Depth;i++)\r\n\t\t\tprintf (\"    \");\r\n\t\tprintf (\"0x%08x\\n\",p_child->GetFlags());\r\n\t\t\r\n\t\tCGeomNode *p_next_child = p_child->GetSibling();\r\n\t\t\r\n\t\t// if child not a leaf, then just recurse down\r\n\t\tif (! (p_child->GetFlags() & NODEFLAG_LEAF))\r\n\t\t{\r\n\t\t\tStripNiceLeaves(p_child);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\r\n\t\t\t// it's a leaf node, so maybe strip it, and then carry on to the siblings\r\n\t\t\tif (((p_child->GetFlags() & (NODEFLAG_ACTIVE\t\t|\r\n\t\t\t\t NODEFLAG_SKY\t\t\t|\r\n\t\t\t\t NODEFLAG_TRANSFORMED\t|\r\n\t\t\t\t NODEFLAG_LEAF\t\t\t|\r\n\t\t\t\t NODEFLAG_OBJECT\t\t|\r\n\t\t\t\t NODEFLAG_COLOURED\t\t|\r\n\t\t\t\t NODEFLAG_SKELETAL\t\t|\r\n\t\t\t\t NODEFLAG_BILLBOARD\t\t|\r\n\t\t\t\t NODEFLAG_UVWIBBLE\t\t|\r\n\t\t\t\t NODEFLAG_VCWIBBLE\t\t|\r\n\t\t\t\t NODEFLAG_ENVMAPPED))\r\n\r\n\t\t\t==  (NODEFLAG_ACTIVE\t\t|\r\n\t\t\t\t NODEFLAG_LEAF)))\r\n\t\t\t\r\n\t\t\t{\r\n\t\t\t\t// strip it out (eventually add it to a quick-render list)\r\n\t\t\t\tif (p_parent->GetChild() == p_child)\r\n\t\t\t\t{\r\n\t\t\t\t\t// just need to fix up the parent\r\n\t\t\t\t\tp_parent->SetChild(p_next_child);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// find the elder sibling and fix up his sibling\r\n\t\t\t\t\tCGeomNode *p_elder_sibling = p_parent->GetChild();\r\n\t\t\t\t\twhile (p_elder_sibling->GetSibling() != p_child)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_elder_sibling = p_elder_sibling->GetSibling();\r\n\t\t\t\t\t\tDbg_Assert(p_elder_sibling);\t// catch infinite loop\r\n\t\t\t\t\t}\r\n\t\t\t\t\tp_elder_sibling->SetSibling(p_next_child);\t\t\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\t// p_child is now an orphan\r\n\t\t\t\t// TODO - add to quick render list ...\r\n\t\t\t}\r\n\t\t}\r\n\t\tp_child = p_next_child;\r\n\t}\t\r\n\tSNL_Depth--;\r\n}\r\n\r\n\r\n\r\nCGeomNode* CGeomNode::sProcessInPlace(uint8* pPipData, uint32 loadFlags)\r\n{\r\n\tDbg_MsgAssert(((int)(pPipData) & 0xf) == 0,(\"pPipData (0x%x) not multiple of 16 \\n\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t,(int)pPipData));\r\n\r\n\t// Jump to beginning of CGeomNode data\r\n\tpPipData += *(uint32 *)pPipData;\r\n\t\r\n\t// from header, get address of root node\r\n\tCGeomNode *p_root_node = (CGeomNode *) (pPipData + *(uint32 *)pPipData);\r\n\r\n\tDbg_MsgAssert(((int)(p_root_node) & 0xf) == 0,(\"p_root_node (0x%x) not multiple of 16, .SCN.PS2 file corrupt... \\n\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t,(int)p_root_node));\r\n\r\n\r\n\r\n\t// recursively process the tree\r\n\t#ifdef\t__NOPT_ASSERT__\r\n//\tint leaves = \r\n\t#endif\r\n\tp_root_node->ProcessNodeInPlace(pPipData);\r\n\t#ifdef\t__NOPT_ASSERT__\r\n//\tprintf (\">>>>> Number of leaves in geom PIP file = %d\\n\",leaves);\r\n\t#endif\r\n\r\n\r\n\t//StripNiceLeaves(p_root_node);\t\r\n\r\n\t// add the root node to the world or to the database\r\n\tp_root_node->BecomesChildOf((loadFlags & LOADFLAG_RENDERNOW) ? &sWorld : &sDatabase);\r\n\r\n\t// set the root node's sky flag if loaded as a sky\r\n\tif (loadFlags & LOADFLAG_SKY)\r\n\t{\r\n\t\tp_root_node->SetSky(true);\r\n\t}\r\n\r\n\t// return the root node pointer\r\n\treturn p_root_node;\r\n}\r\n\r\nvoid * CGeomNode::sGetHierarchyArray(uint8 *pPipData, int& size)\r\n{\r\n\tDbg_MsgAssert(((int)(pPipData) & 0xf) == 0,(\"pPipData (0x%x) not multiple of 16 \\n\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t,(int)pPipData));\r\n\r\n\tuint32 *pPip32Data = (uint32 *) pPipData;\r\n\r\n\tpPip32Data++;\t\t// skip CGeomNode offset\r\n\r\n\t// Get array pointer and size\r\n\tvoid *p_array = (pPipData + *(pPip32Data++));\r\n\tsize = *pPip32Data;\r\n\r\n\tif (size)\r\n\t{\r\n\t\treturn p_array;\r\n\t} else {\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\nvoid CGeomNode::AddToTree(uint32 loadFlags)\r\n{\r\n\tBecomesChildOf((loadFlags & LOADFLAG_RENDERNOW) ? &sWorld : &sDatabase);\r\n\r\n\t// set the root node's sky flag if loaded as a sky\r\n\tif (loadFlags & LOADFLAG_SKY)\r\n\t{\r\n\t\tSetSky(true);\r\n\t}\r\n}\r\n\r\nvoid CGeomNode::Cleanup()\r\n{\r\n\t// remove from any node it belongs to\r\n\tRemoveFrom(&sWorld);\r\n\tRemoveFrom(&sDatabase);\r\n}\r\n\r\n\r\nCGeomNode* CGeomNode::CreateInstance(Mth::Matrix *pMat, CGeomNode *p_parent)\r\n{\r\n\t// copy node\r\n\tCGeomNode *p_node = new CGeomNode(*this);\r\n\r\n\t// flag as an instance\r\n\tp_node->m_flags |= NODEFLAG_INSTANCE;\r\n\r\n\t// set matrix\r\n\tp_node->SetMatrix(pMat);\r\n\r\n\t// add to world\r\n\tif (p_parent)\r\n\t{\r\n\t\tp_node->BecomesChildOf(p_parent);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_node->BecomesChildOf(&sWorld);\r\n\t}\r\n\r\n\t// activate!\r\n\tp_node->SetActive(true);\r\n\r\n\t// return new node\r\n\treturn p_node;\r\n}\r\n\r\n\r\n// skeletal version\r\nCGeomNode* CGeomNode::CreateInstance(Mth::Matrix *pMat, int numBones, Mth::Matrix *pBoneTransforms, CGeomNode *p_parent)\r\n{\r\n\t// copy node\r\n\tCGeomNode *p_node = new CGeomNode(*this);\r\n\r\n\t// flag as a skeletal instance\r\n\tp_node->m_flags |= NODEFLAG_SKELETAL|NODEFLAG_INSTANCE;\r\n\r\n\t// set matrix and bone data\r\n\tp_node->SetMatrix(pMat);\r\n\tp_node->m_num_bones = numBones;\r\n\tp_node->u4.mp_bone_transforms = pBoneTransforms;\r\n\tp_node->m_field = 0;\r\n\r\n\t// add to world\r\n\tif (p_parent)\r\n\t{\r\n\t\tp_node->BecomesChildOf(p_parent);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_node->BecomesChildOf(&sWorld);\r\n\t}\r\n\r\n\t// activate!\r\n\tp_node->SetActive(true);\r\n\r\n\t// return new node\r\n\treturn p_node;\r\n}\r\n\r\n\r\nvoid CGeomNode::DeleteInstance()\r\n{\r\n\tDbg_MsgAssert(m_flags&NODEFLAG_INSTANCE, (\"attempt to delete a non-instance\"));\r\n\r\n\tbool removed;\r\n\tremoved = RemoveFrom(&sWorld);\r\n\tremoved = removed || RemoveFromChildrenOf(&sWorld);\t\t// Check all cloned scenes, too\r\n\r\n\tDbg_MsgAssert(removed, (\"Couldn't remove instanced CGeomNode from CGeomNode tree\"));\r\n\r\n\tdelete this;\r\n}\r\n\r\nCGeomNode* CGeomNode::CreateCopy(CGeomNode *p_parent, bool root)\r\n{\r\n\t// copy node\r\n\tCGeomNode *p_node = new CGeomNode(*this);\r\n\r\n\t// clear some pointers\r\n\tp_node->mp_sibling = NULL;\r\n\r\n\t// add to world if this is the top node\r\n\tif (root)\r\n\t{\r\n\t\tif (p_parent)\r\n\t\t{\r\n\t\t\tp_node->BecomesChildOf(p_parent);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_node->BecomesChildOf(&sWorld);\r\n\t\t}\r\n\t}\r\n\r\n\t// activate!\r\n\tp_node->SetActive(true);\r\n\r\n\t// Also copy data and tree underneath\r\n\tif (IsLeaf())\r\n\t{\r\n\t\t// Copy the dma data\r\n\t\tDbg_Assert(u1.mp_dma);\r\n\t\tp_node->u1.mp_dma = new uint8[dma::GetDmaSize(u1.mp_dma)];\r\n\t\tDbg_Assert(!((uint32) p_node->u1.mp_dma & 0xf))\r\n\t\tdma::Copy(u1.mp_dma, p_node->u1.mp_dma);\r\n\t} else {\r\n\t\t// Check if we have LODs\r\n\t\tif (IsObject())\r\n\t\t{\r\n\t\t\tif (mp_next_LOD)\r\n\t\t\t{\r\n\t\t\t\tp_node->mp_next_LOD = mp_next_LOD->CreateCopy(NULL, false);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Recursively copy children\r\n\t\tp_node->u1.mp_child = NULL;\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_node->AddChild(p_child->CreateCopy(NULL, false));\r\n\t\t}\r\n\t}\r\n\r\n\t// return new node\r\n\treturn p_node;\r\n}\r\n\r\nvoid WaitForRendering();\r\n\r\n// Recursivly deletes an object and all its children\r\nvoid CGeomNode::DeleteCopy(bool root)\r\n{\r\n\t// Garrett: Kinda hacky, but gets the job done.  Make sure we aren't rendering before\r\n\t// we release DMA buffers\r\n\tWaitForRendering();  \r\n\r\n\tDbg_MsgAssert(!(m_flags & NODEFLAG_INSTANCE), (\"attempt to delete an instance\"));\r\n\r\n\tif (root)\r\n\t{\r\n\t\tbool removed;\r\n\t\tremoved = RemoveFrom(&sWorld);\r\n\t\tremoved = removed || RemoveFromChildrenOf(&sWorld);\t\t// Check all cloned scenes, too\r\n\r\n\t\tDbg_MsgAssert(removed, (\"Couldn't remove copied CGeomNode from CGeomNode tree\"));\r\n\t}\r\n\r\n\t// Also delete data and tree underneath\r\n\tif (IsLeaf())\r\n\t{\r\n\t\t// Delete the dma data\r\n\t\tDbg_Assert(u1.mp_dma);\r\n\t\tdelete [] u1.mp_dma;\r\n\t} else {\r\n\t\t// Check if we have LODs\r\n\t\tif (IsObject())\r\n\t\t{\r\n\t\t\tif (mp_next_LOD)\r\n\t\t\t{\r\n\t\t\t\tmp_next_LOD->DeleteCopy(false);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Recursively delete children\r\n\t\t// (Mick) restructured this because DeleteCopy will delete the object it is run on\r\n\t\tCGeomNode *p_child=u1.mp_child;\r\n\t\twhile ( p_child)\r\n\t\t{\r\n\t\t\tCGeomNode *p_next=p_child->mp_sibling;\r\n\t\t\tp_child->DeleteCopy(false);\r\n\t\t\tp_child = p_next;\r\n\t\t}\r\n\t}\r\n\r\n\tdelete this;\t   // <<<< Warning:  deletes 'this'\r\n}\r\n\r\nvoid CGeomNode::Translate(const Mth::Vector & delta_pos)\r\n{\r\n\tDbg_MsgAssert(!(m_flags & NODEFLAG_INSTANCE), (\"attempt to translate an instance\"));\r\n\r\n\t// Update bounding sphere\r\n\tm_bounding_sphere[X] += delta_pos[X];\r\n\tm_bounding_sphere[Y] += delta_pos[Y];\r\n\tm_bounding_sphere[Z] += delta_pos[Z];\r\n\r\n#if 0\r\n\t// Test for Park Editor\r\n\tDbg_Message(\"Translating by (%.8f, %.8f, %.8f)\", delta_pos[X], delta_pos[Y], delta_pos[Z]);\r\n\tint delta_x = (int) (delta_pos[X] * SUB_INCH_PRECISION);\r\n\tint delta_y = (int) (delta_pos[Y] * SUB_INCH_PRECISION);\r\n\tint delta_z = (int) (delta_pos[Z] * SUB_INCH_PRECISION);\r\n\tDbg_MsgAssert(!(delta_x & 0xF), (\"Fraction in X: (%x, %x, %x)\", delta_x, delta_y, delta_z));\r\n\tDbg_MsgAssert(!(delta_y & 0xF), (\"Fraction in Y: (%x, %x, %x)\", delta_x, delta_y, delta_z));\r\n\tDbg_MsgAssert(!(delta_z & 0xF), (\"Fraction in Z: (%x, %x, %x)\", delta_x, delta_y, delta_z));\r\n#endif\r\n\r\n\t// Update whole tree\r\n\tif (IsLeaf())\r\n\t{\r\n\t\t// Get the dma data\r\n\t\tDbg_Assert(u1.mp_dma);\r\n\r\n\t\tif (dma::GetBitLengthXYZ(u1.mp_dma) == 32)\r\n\t\t{\r\n\t\t\t// Calculate int versions\r\n\t\t\tint delta_x = (int) (delta_pos[X] * SUB_INCH_PRECISION);\r\n\t\t\tint delta_y = (int) (delta_pos[Y] * SUB_INCH_PRECISION);\r\n\t\t\tint delta_z = (int) (delta_pos[Z] * SUB_INCH_PRECISION);\r\n\r\n\t\t\tint num_verts = dma::GetNumVertices(u1.mp_dma);\r\n\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\tint32 *p_verts = new int32[num_verts * 4];\r\n\t\t\tdma::ExtractXYZs(u1.mp_dma, (uint8 *) p_verts);\t\t\r\n\r\n\t\t\tfor (int i = 0; i < num_verts; i++) {\r\n\t\t\t\tp_verts[(i * 4) + 0] += delta_x;\r\n\t\t\t\tp_verts[(i * 4) + 1] += delta_y;\r\n\t\t\t\tp_verts[(i * 4) + 2] += delta_z;\r\n\t\t\t}\r\n\r\n\t\t\tdma::ReplaceXYZs(u1.mp_dma, (uint8 *) p_verts);\t\t\r\n\r\n\t\t\tdelete [] p_verts;\r\n\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(dma::GetBitLengthXYZ(u1.mp_dma)==16, (\"oh dear, should've been either 16 or 32...\"));\r\n\t\t}\r\n\t} else {\r\n\t\t// Check if we have LODs\r\n\t\tif (IsObject())\r\n\t\t{\r\n\t\t\tif (mp_next_LOD)\r\n\t\t\t{\r\n\t\t\t\tmp_next_LOD->Translate(delta_pos);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Recursively update children\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_child->Translate(delta_pos);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CGeomNode::RotateY(const Mth::Vector & world_origin, Mth::ERot90 rot_y, bool root)\r\n{\r\n\tDbg_MsgAssert(!(m_flags & NODEFLAG_INSTANCE), (\"attempt to translate an instance\"));\r\n\r\n\tif (root)\r\n\t{\r\n\t\tTranslate(-world_origin);\r\n\t}\r\n\r\n\t// Update bounding box\r\n\t// Since they are relative to width and height, we just need to possibly swap X and Z\r\n\tif ((int) rot_y & 1)\r\n\t{\r\n\t\tfloat temp = m_bounding_box[X];\r\n\t\tm_bounding_box[X] = m_bounding_box[Z];\r\n\t\tm_bounding_box[Z] = temp;\r\n\t}\r\n\r\n\t// Also rotate bounding sphere position\r\n\tm_bounding_sphere.RotateY90(rot_y);\r\n\r\n\t// Update whole tree\r\n\tif (IsLeaf())\r\n\t{\r\n\t\t// Delete the dma data\r\n\t\tDbg_Assert(u1.mp_dma);\r\n\r\n\t\tint num_verts = dma::GetNumVertices(u1.mp_dma);\r\n\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\tint32 *p_verts = new int32[num_verts * 4];\r\n\t\tdma::ExtractXYZs(u1.mp_dma, (uint8 *) p_verts);\t\t\r\n\r\n\t\tfor (int i = 0; i < num_verts; i++) {\r\n\t\t\tMth::RotateY90(rot_y,\r\n\t\t\t\t\t\t   p_verts[(i * 4) + 0],\r\n\t\t\t\t\t\t   p_verts[(i * 4) + 1],\r\n\t\t\t\t\t\t   p_verts[(i * 4) + 2]);\r\n\t\t}\r\n\r\n\t\tdma::ReplaceXYZs(u1.mp_dma, (uint8 *) p_verts);\t\t\r\n\r\n\t\tdelete [] p_verts;\r\n\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t} else {\r\n\t\t// Check if we have LODs\r\n\t\tif (IsObject())\r\n\t\t{\r\n\t\t\tif (mp_next_LOD)\r\n\t\t\t{\r\n\t\t\t\tmp_next_LOD->RotateY(world_origin, rot_y, false);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Recursively update children\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_child->RotateY(world_origin, rot_y, false);\r\n\t\t}\r\n\t}\r\n\r\n\tif (root)\r\n\t{\r\n\t\tTranslate(world_origin);\r\n\t}\r\n}\r\n\r\nvoid CGeomNode::Scale(const Mth::Vector & world_origin, const Mth::Vector & scale, bool root)\r\n{\r\n\tDbg_MsgAssert(!(m_flags & NODEFLAG_INSTANCE), (\"attempt to scale an instance\"));\r\n\r\n\tif (root)\r\n\t{\r\n\t\tTranslate(-world_origin);\r\n\t}\r\n\r\n\t// Update bounding box\r\n\tm_bounding_box[X] *= scale[X];\r\n\tm_bounding_box[Y] *= scale[Y];\r\n\tm_bounding_box[Z] *= scale[Z];\r\n\r\n#if 0\t// Don't do this since it is a local scale\r\n\t// Also scale bounding sphere position\r\n\t// Update bounding sphere\r\n\tm_bounding_sphere[X] *= scale[X];\r\n\tm_bounding_sphere[Y] *= scale[Y];\r\n\tm_bounding_sphere[Z] *= scale[Z];\r\n#endif\r\n\r\n\t// Garrett: The radius calculation is not accurate, but so far, it works.  It will always round up.\r\n\t// We have to assume the largest radius\r\n\tfloat radius_scale = sqrtf((scale[X] * scale[X]) + (scale[Y] * scale[Y]) + (scale[Z] + scale[Z]));\r\n\tm_bounding_sphere[W] *= radius_scale;\r\n\t// But see if the bounding box radius is smaller\r\n\tfloat box_radius = sqrtf((m_bounding_box[X] * m_bounding_box[X]) + (m_bounding_box[Y] * m_bounding_box[Y]) + (m_bounding_box[Z] * m_bounding_box[Z]));\r\n\t//Dbg_Message(\"Calculated sphere radius %f; Bounding box radius %f\", m_bounding_sphere[W] , box_radius);\r\n\tm_bounding_sphere[W] = Mth::Min(box_radius, m_bounding_sphere[W]);\r\n\r\n\t// Update whole tree\r\n\tif (IsLeaf())\r\n\t{\r\n\t\t// Get the dma data\r\n\t\tDbg_Assert(u1.mp_dma);\r\n\r\n\t\t// Calculate int versions\r\n\t\tint scale_x = (int) (scale[X] * SUB_INCH_PRECISION);\r\n\t\tint scale_y = (int) (scale[Y] * SUB_INCH_PRECISION);\r\n\t\tint scale_z = (int) (scale[Z] * SUB_INCH_PRECISION);\r\n\r\n\t\t// Check to see that we didn't go to zero\r\n\t\tDbg_MsgAssert(scale_x, (\"CGeomNode::Scale(): X scale went to 0 in integer conversion. Original value %f\", scale[X]));\r\n\t\tDbg_MsgAssert(scale_y, (\"CGeomNode::Scale(): Y scale went to 0 in integer conversion. Original value %f\", scale[Y]));\r\n\t\tDbg_MsgAssert(scale_z, (\"CGeomNode::Scale(): Z scale went to 0 in integer conversion. Original value %f\", scale[Z]));\r\n\r\n\t\tint num_verts = dma::GetNumVertices(u1.mp_dma);\r\n\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\tint32 *p_verts = new int32[num_verts * 4];\r\n\t\tdma::ExtractXYZs(u1.mp_dma, (uint8 *) p_verts);\t\t\r\n\r\n\t\t// SUB_INCH_PRECISION must be a whole number\r\n\t\tDbg_Assert( ((int) (SUB_INCH_PRECISION * 1000.0f)) == (((int) SUB_INCH_PRECISION) * 1000) );\r\n\r\n\t\tfor (int i = 0; i < num_verts; i++) {\r\n\t\t\tp_verts[(i * 4) + 0] = (p_verts[(i * 4) + 0] * scale_x) / ((int) SUB_INCH_PRECISION);\r\n\t\t\tp_verts[(i * 4) + 1] = (p_verts[(i * 4) + 1] * scale_y) / ((int) SUB_INCH_PRECISION);\r\n\t\t\tp_verts[(i * 4) + 2] = (p_verts[(i * 4) + 2] * scale_z) / ((int) SUB_INCH_PRECISION);\r\n\t\t}\r\n\r\n\t\tdma::ReplaceXYZs(u1.mp_dma, (uint8 *) p_verts);\t\t\r\n\r\n\t\tdelete [] p_verts;\r\n\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t} else {\r\n\t\t// Check if we have LODs\r\n\t\tif (IsObject())\r\n\t\t{\r\n\t\t\tif (mp_next_LOD)\r\n\t\t\t{\r\n\t\t\t\tmp_next_LOD->Scale(world_origin, scale, false);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Recursively update children\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_child->Scale(world_origin, scale, false);\r\n\t\t}\r\n\t}\r\n\r\n\tif (root)\r\n\t{\r\n\t\tTranslate(world_origin);\r\n\t}\r\n}\r\n\r\nvoid \t\tCGeomNode::GetVerts(Mth::Vector *p_verts, bool root)\r\n{\r\n\t// Not thread safe\r\n\tstatic int vert_index;\r\n\tif (root)\r\n\t{\r\n\t\tvert_index = 0;\r\n\t}\r\n\r\n\tif (IsLeaf())\r\n\t{\r\n\t\t// Get the dma data\r\n\t\tDbg_Assert(u1.mp_dma);\r\n\t\tint num_verts = dma::GetNumVertices(u1.mp_dma);\r\n\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n\t\tint32 *p_raw_verts = (int32 *) &p_verts[vert_index];\r\n\t\t//int32 *p_raw_verts = new int32[num_verts * 4];\r\n\t\tdma::ExtractXYZs(u1.mp_dma, (uint8 *) p_raw_verts);\t\t\r\n\r\n\t\t// Convert center to integer\r\n\t\t// (Mick:  Changed to always have a center offset, as even 32 bit coordinates have one\r\n\t\t// previous, the code assumed that 32 bit coordinate were absolute world coords, and so\r\n\t\t// did not add in the \"center\" offset\r\n\t\tint32 center[4];\r\n\t\tdma::ConvertFloatToXYZ(center,  m_bounding_sphere);\r\n\r\n\t\tfor (int i = 0; i < num_verts; i++, vert_index++) \r\n\t\t{\r\n\t\t\tdma::ConvertXYZToFloat(p_verts[vert_index], &(p_raw_verts[i * 4]), center);\r\n\t\t}\r\n\r\n//\t\tdelete [] p_raw_verts;\r\n\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t} else {\r\n\t\t// Check if we have LODs\r\n\t\tif (IsObject())\r\n\t\t{\r\n\t\t\tif (mp_next_LOD)\r\n\t\t\t{\r\n\t\t\t\tmp_next_LOD->GetVerts(p_verts, false);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Get children verts\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_child->GetVerts(p_verts, false);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid \t\tCGeomNode::SetVerts(Mth::Vector *p_verts, bool root)\r\n{\r\n\t// Not thread safe\r\n\tstatic int vert_index;\r\n\tif (root)\r\n\t{\r\n\t\tvert_index = 0;\r\n\t}\r\n\r\n\tif (IsLeaf())\r\n\t{\r\n\t\t// Get the dma data\r\n\t\tDbg_Assert(u1.mp_dma);\r\n\t\tint num_verts = dma::GetNumVertices(u1.mp_dma);\r\n\r\n\t\t// Recalculate the bounding data BEFORE setting the DMA data, since it will change the\r\n\t\t// center of the bounding sphere.\r\n\t\trecalculate_bounding_data(&p_verts[vert_index], num_verts);\r\n\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n\t\tint32 *p_raw_verts = new int32[num_verts * 4];\r\n\r\n\t\t// Convert center to integer\r\n\t\tint32 center[4];\r\n\t\tif (dma::GetBitLengthXYZ(u1.mp_dma) < 32)\r\n\t\t{\r\n\t\t\tdma::ConvertFloatToXYZ(center,  m_bounding_sphere);\r\n\t\t}\r\n\t\t\r\n\r\n\t\tfor (int i = 0; i < num_verts; i++, vert_index++) {\r\n\t\t\tif (dma::GetBitLengthXYZ(u1.mp_dma) == 32)\r\n\t\t\t{\r\n\t\t\t\tdma::ConvertFloatToXYZ(&(p_raw_verts[i * 4]), p_verts[vert_index]);\r\n\t\t\t} else {\r\n\t\t\t\tdma::ConvertFloatToXYZ(&(p_raw_verts[i * 4]), p_verts[vert_index], center);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Replaces only XYZs (not W)\r\n\t\tdma::ReplaceXYZs(u1.mp_dma, (uint8 *) p_raw_verts, true);\t\t\r\n\r\n\t\tdelete [] p_raw_verts;\r\n\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t} else {\r\n\t\t// Check if we have LODs\r\n\t\tif (IsObject())\r\n\t\t{\r\n\t\t\tif (mp_next_LOD)\r\n\t\t\t{\r\n\t\t\t\tmp_next_LOD->SetVerts(p_verts, false);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Set children verts\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_child->SetVerts(p_verts, false);\r\n\t\t}\r\n\r\n\t\t// Recalculate the bounding data at this level using all the verts (assuming this is\r\n\t\t// going to be the object node).\r\n\t\tDbg_MsgAssert(IsObject(), (\"Don't know how to recalculate the bounding data for this node: Not an object\"));\r\n\t\tint num_verts = GetNumVerts();\r\n\t\trecalculate_bounding_data(p_verts, num_verts);\r\n\t}\r\n}\r\n\r\nvoid \t\tCGeomNode::recalculate_bounding_data(Mth::Vector *p_verts, int num_verts)\r\n{\r\n\tMth::Vector min, max, center, half_vec;\r\n\tfloat radius;\r\n\tint i;\r\n\r\n\t// calculate bounding box for the mesh\r\n\tmin[0] = min[1] = min[2] = 1e30f;\r\n\tmax[0] = max[1] = max[2] = -1e30f;\r\n\r\n\tfor (i=0; i<num_verts; i++)\r\n\t{\r\n\t\tif (p_verts[i][X] < min[X])\r\n\t\t\tmin[X] = p_verts[i][X];\r\n\t\tif (p_verts[i][Y] < min[Y])\r\n\t\t\tmin[Y] = p_verts[i][Y];\r\n\t\tif (p_verts[i][Z] < min[Z])\r\n\t\t\tmin[Z] = p_verts[i][Z];\r\n\r\n\t\tif (p_verts[i][X] > max[X])\r\n\t\t\tmax[X] = p_verts[i][X];\r\n\t\tif (p_verts[i][Y] > max[Y])\r\n\t\t\tmax[Y] = p_verts[i][Y];\r\n\t\tif (p_verts[i][Z] > max[Z])\r\n\t\t\tmax[Z] = p_verts[i][Z];\r\n\t}\r\n\r\n\t// calculate bounding sphere for the mesh\r\n\tcenter = (max+min)*0.5f;\r\n\tradius = 0.0f;\r\n\tfor (i=0; i<num_verts; i++)\r\n\t{\r\n\t\tfloat len = (p_verts[i] - center).Length();\r\n\t\tif (len > radius)\r\n\t\t\tradius = len;\r\n\t}\r\n\r\n\t// Update bounding box data\r\n\thalf_vec = 0.5f * (max - min);\r\n\tm_bounding_box[X] = half_vec[X];\r\n\tm_bounding_box[Y] = half_vec[Y];\r\n\tm_bounding_box[Z] = half_vec[Z];\r\n\r\n\t// Update bounding sphere data\r\n\tm_bounding_sphere = center;\r\n\tm_bounding_sphere[W] = radius;\r\n}\r\n\r\nvoid \t\tCGeomNode::GetColors(uint32 *p_colors, bool root)\r\n{\r\n\t// Not thread safe\r\n\tstatic int vert_index;\r\n\tif (root)\r\n\t{\r\n\t\tvert_index = 0;\r\n\t}\r\n\r\n\tif (IsLeaf())\r\n\t{\r\n\t\t// Get the dma data\r\n\t\tDbg_Assert(u1.mp_dma);\r\n\t\tint num_verts = dma::GetNumVertices(u1.mp_dma);\r\n\r\n\t\tdma::ExtractRGBAs(u1.mp_dma, (uint8 *) &(p_colors[vert_index]));\t\t\r\n\t\tvert_index += num_verts;\r\n\t} else {\r\n\t\t// Check if we have LODs\r\n\t\tif (IsObject())\r\n\t\t{\r\n\t\t\tif (mp_next_LOD)\r\n\t\t\t{\r\n\t\t\t\tmp_next_LOD->GetColors(p_colors, false);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Get children colors\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_child->GetColors(p_colors, false);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid \t\tCGeomNode::SetColors(uint32 *p_colors, bool root)\r\n{\r\n\t// Not thread safe\r\n\tstatic int vert_index;\r\n\tif (root)\r\n\t{\r\n\t\tvert_index = 0;\r\n\t}\r\n\r\n\tif (IsLeaf())\r\n\t{\r\n\t\t// Set the dma data\r\n\t\tDbg_Assert(u1.mp_dma);\r\n\t\tint num_verts = dma::GetNumVertices(u1.mp_dma);\r\n\r\n\t\tdma::ReplaceRGBAs(u1.mp_dma, (uint8 *) &(p_colors[vert_index]));\t\t\r\n\t\tvert_index += num_verts;\r\n\t} else {\r\n\t\t// Check if we have LODs\r\n\t\tif (IsObject())\r\n\t\t{\r\n\t\t\tif (mp_next_LOD)\r\n\t\t\t{\r\n\t\t\t\tmp_next_LOD->SetColors(p_colors, false);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Set children colors\r\n\t\tfor (CGeomNode *p_child=u1.mp_child; p_child; p_child=p_child->mp_sibling)\r\n\t\t{\r\n\t\t\tp_child->SetColors(p_colors, false);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/*\r\n\tvc wibble material data block format\r\n\t------------------------------------\r\n\r\n\tint num_seqs;\r\n\tfor (seq=0; seq<num_seqs; seq++)\r\n\t{\r\n\t\tint num_keys;\r\n\t\tint phase_shift;\r\n\t\tfor (key=0; key<num_keys; key++)\r\n\t\t{\r\n\t\t\tint start_time;\r\n\t\t\tfloat colour[4];\r\n\t\t}\r\n\t}\r\n\r\n\r\n\tvc wibble mesh data block format\r\n\t--------------------------------\r\n\r\n\tint num_seqs;\r\n\tfor (seq=0; seq<num_seqs; seq++)\r\n\t{\r\n\t\tuint32 *p_sequence;\r\n\t\tint num_wibbled_verts;\r\n\t\tfor (vert=0; vert<num_wibbled_verts; vert++)\r\n\t\t{\r\n\t\t\tuint32 *p_rgba;\r\n\t\t}\r\n\t}\r\n\r\n*/\r\n\r\nvoid CGeomNode::WibbleVCs()\r\n{\r\n\tint seq, num_seqs, key, num_keys, time, start_time, end_time, period, vert, num_verts, phase_shift;\r\n\tuint32 rgba, *p_rgba;\r\n\tfloat *p_key;\r\n\tfloat t,r,g,b,a;\r\n\tuint32 *p_meshdata, *p_matdata;\r\n\r\n\tp_meshdata = mp_vc_wibble;\r\n\r\n\t// get # animation sequences\r\n\tnum_seqs = *p_meshdata++;\r\n\r\n\tfor (seq=0; seq<num_seqs; seq++)\r\n\t{\r\n\t\tp_matdata = *(uint32 **)p_meshdata;\r\n\t\tp_meshdata++;\r\n\r\n\t\t// get # keyframes for this sequence\r\n\t\tnum_keys = *p_matdata++;\r\n\r\n\t\t// get phase-shift\r\n\t\tphase_shift = *p_matdata++;\r\n\r\n\t\t// time parameters\r\n\t\tstart_time\t= p_matdata[0];\r\n\t\tend_time\t= p_matdata[num_keys*5-5];\r\n\t\tperiod\t\t= end_time - start_time;\r\n\t\ttime\t\t= start_time + (render::sTime /*(int)Tmr::GetTime()*/ + phase_shift) % period;\r\n\r\n\t\t// keep time in range\r\n\t\tif (time < start_time) time = start_time;\r\n\t\tif (time > end_time) time = end_time;\r\n\r\n\t\t// locate the keyframe\r\n\t\tfor (key=num_keys-1,p_key=(float *)p_matdata+5*num_keys-5; key>=0; key--,p_key-=5)\r\n\t\t{\r\n\t\t\tif (time >= *(int *)p_key)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// parameter expressing how far we are between between this keyframe and the next\r\n\t\tt = (float)(time - ((int *)p_key)[0]) / (float)(((int *)p_key)[5] - ((int *)p_key)[0]);\r\n\r\n\t\t#if 0\r\n\t\t// for debugging a TT bug...\r\n\t\tfor (int i=1; i<=9; i++)\r\n\t\t\tDbg_MsgAssert(p_key[i]>=0 && p_key[i]<=255, (\"sTime=%d, num_keys=%d, key=%d, p_key[1]=%g, p_key[2]=%g, p_key[3]=%g, p_key[4]=%g, p_key[5]=%g, p_key[6]=%g, p_key[7]=%g, p_key[8]=%g, p_key[9]=%g, time=%d, start_time=%d, end_time=%d, period=%d, t=%g\", \\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  render::sTime,\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  num_keys,\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  key,\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  p_key[1],\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  p_key[2],\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  p_key[3],\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  p_key[4],\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  p_key[5],\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  p_key[6],\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  p_key[7],\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  p_key[8],\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  p_key[9],\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  time,\t\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  start_time,\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  end_time,\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  period,\t\t\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  t));\r\n\t\t#endif\r\n\r\n\t\t// interpolate between colours\r\n\t\tr = (1.0f-t) * p_key[1] + t * p_key[6];\r\n\t\tg = (1.0f-t) * p_key[2] + t * p_key[7];\r\n\t\tb = (1.0f-t) * p_key[3] + t * p_key[8];\r\n\t\ta = (1.0f-t) * p_key[4] + t * p_key[9];\r\n\r\n\t\tDbg_MsgAssert(r>=0 && r<=255 && g>=0 && g<=255 && b>=0 && b<=255 && a>=0 && a<=255,\r\n\t\t\t\t\t  (\"wibbled colour r=%g, g=%g, b=%g, a=%g\", r,g,b,a));\r\n\r\n\t\trgba  =\t(uint32)(sint32)r     & 0x000000FF |\r\n\t\t\t\t(uint32)(sint32)g<<8  & 0x0000FF00 |\r\n\t\t\t\t(uint32)(sint32)b<<16 & 0x00FF0000 |\r\n\t\t\t\t(uint32)(sint32)a<<24;\r\n\r\n\t\t// get # vertices wibbled by this sequence\r\n\t\tnum_verts = *p_meshdata++;\r\n\r\n\t\t// loop over wibbled vertices, overwriting colour in dma data\r\n\t\tfor (vert=0; vert<num_verts; vert++)\r\n\t\t{\r\n\t\t\tp_rgba = *(uint32 **)p_meshdata;\r\n\t\t\tp_meshdata++;\r\n\t\t\t*p_rgba = rgba;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\nMth::Vector CGeomNode::GetBoundingSphere()\r\n{\r\n\tMth::Vector sphere;\r\n\tCGeomNode *p_node = this;\r\n\r\n\t// recurse till we find a sensible sphere\r\n\twhile (!(p_node->m_flags & NODEFLAG_LEAF) && p_node->m_bounding_sphere[3] >= 1.0e+10f)\r\n\t{\r\n\t\tp_node = p_node->u1.mp_child;\r\n\t}\r\n\r\n\tsphere = p_node->m_bounding_sphere;\r\n\r\n\t// then account for any siblings\r\n\twhile (p_node->mp_sibling)\r\n\t{\r\n\t\tp_node = p_node->mp_sibling;\r\n\r\n\t\tMth::Vector x0, x1;\r\n\t\tif (p_node->m_bounding_sphere[3] > sphere[3])\r\n\t\t{\r\n\t\t\tx0 = p_node->m_bounding_sphere; \r\n\t\t\tx1 = sphere;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tx0 = sphere;\r\n\t\t\tx1 = p_node->m_bounding_sphere;\r\n\t\t}\r\n\t\tfloat r0=x0[3], r1=x1[3];\r\n\r\n\t\t// (x0,r0) is the larger sphere, (x1,r1) the smaller\r\n\t\t// d is the vector between centres\r\n\t\tMth::Vector d = x1 - x0;\r\n\r\n\t\t// square of distance between centres\r\n\t\tfloat D2 = DotProduct(d,d);\r\n\r\n\t\t// (r0-r1)^2\r\n\t\tfloat R2 = (r0-r1)*(r0-r1);\r\n\r\n\t\t// m = max { (r1-r0+|d|)/2, 0 }\r\n\t\tfloat m = 0.0f;\r\n\t\tfloat D = sqrtf(D2);\r\n\t\tif (R2-D2 < 0)\r\n\t\t{\r\n\t\t\tm = (r1-r0 + sqrtf(D2)) * 0.5f;\r\n\t\t}\r\n\r\n\t\t// normalise d\r\n\t\tif (D>0)\r\n\t\t\td *= 1.0f/D;\r\n\r\n\t\tsphere    = x0 + m * d;\r\n\t\tsphere[3] = r0 + m;\r\n\t}\r\n\r\n\treturn sphere;\r\n}\r\n\r\nMth::CBBox CGeomNode::GetBoundingBox()\r\n{\r\n\tCGeomNode *p_node = this;\r\n\r\n\twhile (!(p_node->m_flags & NODEFLAG_LEAF) && p_node->m_bounding_sphere[3] >= 1.0e+10f)\r\n\t{\r\n\t\tp_node = p_node->u1.mp_child;\r\n\t}\r\n\r\n\tMth::Vector min_p(p_node->m_bounding_sphere);\r\n\tMth::Vector max_p(p_node->m_bounding_sphere);\r\n\r\n\t//Dbg_Message(\"Bounding sphere (%.8f, %.8f, %.8f, %.8f)\", p_node->m_bounding_sphere[X], p_node->m_bounding_sphere[Y], p_node->m_bounding_sphere[Z], p_node->m_bounding_sphere[W]);\r\n\t//Dbg_Message(\"Bounding box (%.8f, %.8f, %.8f)\", p_node->m_bounding_box[X], p_node->m_bounding_box[Y], p_node->m_bounding_box[Z]);\r\n\r\n\tmin_p[X] -= p_node->m_bounding_box[0];\r\n\tmin_p[Y] -= p_node->m_bounding_box[1];\r\n\tmin_p[Z] -= p_node->m_bounding_box[2];\r\n\tmin_p[W] = 1.0f;\r\n\r\n\tmax_p[X] += p_node->m_bounding_box[0];\r\n\tmax_p[Y] += p_node->m_bounding_box[1];\r\n\tmax_p[Z] += p_node->m_bounding_box[2];\r\n\tmin_p[W] = 1.0f;\r\n\r\n\treturn Mth::CBBox(min_p, max_p);\r\n}\r\n\r\n\r\n\r\n// interface to uv wibble control\r\n\r\n\r\nvoid CGeomNode::SetUVWibbleParams(float u_vel, float u_amp, float u_freq, float u_phase,\r\n\t\t\t\t\t\t\t\t  float v_vel, float v_amp, float v_freq, float v_phase)\r\n{\r\n\tDbg_Assert(mp_uv_wibble);\r\n\r\n\tmp_uv_wibble[0] = u_vel;\r\n\tmp_uv_wibble[1] = v_vel;\r\n\tmp_uv_wibble[2] = u_freq;\r\n\tmp_uv_wibble[3] = v_freq;\r\n\tmp_uv_wibble[4] = u_amp;\r\n\tmp_uv_wibble[5] = v_amp;\r\n\tmp_uv_wibble[6] = u_phase;\r\n\tmp_uv_wibble[7] = v_phase;\r\n}\r\n\r\n\r\n\r\nvoid CGeomNode::UseExplicitUVWibble(bool yes)\r\n{\r\n\tSET_FLAG(NODEFLAG_EXPLICIT_UVWIBBLE);\r\n}\r\n\r\n\r\n\r\nvoid CGeomNode::SetUVWibbleOffsets(float u_offset, float v_offset)\r\n{\r\n\tDbg_Assert(mp_uv_wibble);\r\n\r\n\tmp_uv_wibble[8] = u_offset;\r\n\tmp_uv_wibble[9] = v_offset;\r\n}\r\n\r\n\r\n\r\nvoid CGeomNode::SetUVOffset(uint32 material_name, int pass, float u_offset, float v_offset)\r\n{\r\n\tDbg_MsgAssert(0, (\"SetUVOffset not supported for CGeomNodes\"));\r\n}\r\n\r\n\r\nvoid CGeomNode::SetUVMatrix(uint32 material_name, int pass, Mth::Matrix &mat)\r\n{\r\n\tDbg_MsgAssert(0, (\"SetUVOffset not supported for CGeomNodes\"));\r\n}\r\n\r\n\r\n\r\n\r\n#endif\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/geomnode.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tTHPS4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNxPs2\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgeometry.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/08/02\t-\tmrd\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tclasses for PS2 geometry\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_NGPS_NX_GEOMETRY_H\r\n#define __GFX_NGPS_NX_GEOMETRY_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#include \"vu1context.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define MAX_LOD_DIST\t\t\t(10000000.0f)\r\n\r\nnamespace Mth\r\n{\r\n\tclass CBBox;\r\n}\r\n\r\nnamespace NxPs2\r\n{\r\n\t// Forward declarations\r\n\tstruct\tsGroup;\r\n\tstruct  sTexture;\r\n\tclass\tCLightGroup;\r\n\tclass\tCVu1Context;\r\n\r\n// For the flags, note the visibility bits that are reserved below\r\n#define VISIBILITY_FLAG_BIT\t\t(24)\r\n#define NUM_VISIBILITY_BITS\t\t(8)\r\n//#define ALL_VISIBILITY_BITS\t\t(((1 << NUM_VISIBILITY_BITS) - 1) << VISIBILITY_FLAG_BIT)\r\n#define ALL_VISIBILITY_BITS\t\t((0xFFFFFFFF >> (32 - NUM_VISIBILITY_BITS)) << VISIBILITY_FLAG_BIT)\r\n\r\n#define NODEFLAG_ACTIVE\t\t\t(1<<0)\r\n#define NODEFLAG_LEAF\t\t\t(1<<1)\r\n#define NODEFLAG_OBJECT\t\t\t(1<<2)\r\n#define NODEFLAG_TRANSFORMED\t(1<<3)\r\n#define NODEFLAG_COLOURED\t\t(1<<4)\r\n#define NODEFLAG_SKY\t\t\t(1<<5)\r\n#define NODEFLAG_ZPUSH0\t\t\t(1<<6)\r\n#define NODEFLAG_ZPUSH1\t\t\t(1<<7)\r\n#define NODEFLAG_NOSHADOW\t\t(1<<8)\r\n#define NODEFLAG_UVWIBBLE\t\t(1<<9)\r\n#define NODEFLAG_VCWIBBLE\t\t(1<<10)\r\n#define NODEFLAG_SKINNED\t\t(1<<11)\r\n#define NODEFLAG_SKELETAL\t\t(1<<11)\r\n#define NODEFLAG_INSTANCE\t\t(1<<12)\r\n#define NODEFLAG_OBJECT_LIGHTS\t(1<<13)\r\n#define NODEFLAG_ENVMAPPED\t\t(1<<14)\r\n#define NODEFLAG_BILLBOARD\t\t(1<<15)\r\n#define NODEFLAG_EXPLICIT_UVWIBBLE\t\t(1<<16)\r\n#define NODEFLAG_ZPUSH2\t\t\t(1<<17)\r\n#define NODEFLAG_ZPUSH3\t\t\t(1<<18)\r\n#define NODEFLAG_BLACKFOG\t\t(1<<19)\r\n\r\n#define NODEFLAG_LAST_OCCLUSION_VALID\t(1 << 20)\r\n#define NODEFLAG_LAST_OCCLUSION_TRUE\t(1 << 21)\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n#define NODEFLAG_WAS_RENDERED\t(1 << 22) // True if rendered last frame.  Not always valid for leaf nodes\r\n#endif\r\n\r\n#if 0\r\n#define NODEFLAG_VISIBILITY_TEST_PERFORMED\t\t( 1 << 22 )\r\n#define NODEFLAG_VISIBILITY_TEST_NOT_VISIBLE\t( 1 << 23 )\r\n#endif\r\n\r\n#define NODEFLAG_VISIBILITY_0\t(1<<(VISIBILITY_FLAG_BIT + 0))\r\n#define NODEFLAG_VISIBILITY_1\t(1<<(VISIBILITY_FLAG_BIT + 1))\r\n#define NODEFLAG_VISIBILITY_2\t(1<<(VISIBILITY_FLAG_BIT + 2))\r\n#define NODEFLAG_VISIBILITY_3\t(1<<(VISIBILITY_FLAG_BIT + 3))\r\n#define NODEFLAG_VISIBILITY_4\t(1<<(VISIBILITY_FLAG_BIT + 4))\r\n#define NODEFLAG_VISIBILITY_5\t(1<<(VISIBILITY_FLAG_BIT + 5))\r\n#define NODEFLAG_VISIBILITY_6\t(1<<(VISIBILITY_FLAG_BIT + 6))\r\n#define NODEFLAG_VISIBILITY_7\t(1<<(VISIBILITY_FLAG_BIT + 7))\r\n\r\n#define NODEFLAG_ZPUSH\t\t\t(NODEFLAG_ZPUSH0 | NODEFLAG_ZPUSH1 | NODEFLAG_ZPUSH2 | NODEFLAG_ZPUSH3)\r\n\r\n#define LOADFLAG_RENDERNOW\t\t(1<<0)\r\n#define LOADFLAG_SKY\t\t\t(1<<1)\r\n\r\n// put these here temporarily\r\n#define RENDERFLAG_CULL\t\t\t(1<<0)\r\n#define RENDERFLAG_CLIP\t\t\t(1<<1)\r\n#define RENDERFLAG_SHADOW\t\t(1<<2)\r\n#define RENDERFLAG_COLOURED\t\t(1<<3)\r\n#define RENDERFLAG_TRANSFORMED\t(1<<4)\r\n#define RENDERFLAG_SKELETAL\t\t(1<<5)\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// from CClass, so they get zeroed automatically \r\nclass CGeomMetrics : public Spt::Class\r\n{\r\npublic:\r\n\tint \tm_total;\r\n\tint\t\tm_leaf;\r\n\tint\t\tm_object;\r\n\tint\t\tm_verts;\r\n\tint\t\tm_polys;\r\n};\r\n\r\n\r\nclass CGeomNode\r\n{\r\npublic:\r\n\r\n\t#ifdef __PLAT_NGPS__\r\n#\tif 0\r\n\tvoid\t\t\t\tRecursiveVisibilityTest( CVu1Context& ctxt, uint32 renderFlags );\r\n#\tendif\r\n\tvoid\t\t\t\tRenderWorld(CVu1Context& ctxt, uint32 renderFlags);\r\n\tvoid\t\t\t\tRenderScene(CVu1Context& ctxt, uint32 renderFlags);\r\n\tvoid\t\t\t\tRenderObject(CVu1Context& ctxt, uint32 renderFlags);\r\n\tvoid\t\t\t\tRenderTransformedLeaf(CVu1Context& ctxt, uint32 renderFlags);\r\n\tvoid\t\t\t\tRenderNonTransformedLeaf(CVu1Context& ctxt, uint32 renderFlags);\r\n\tvoid\t\t\t\tRenderMinimalLeaf(CVu1Context& ctxt);\r\n\tvoid\t\t\t\tRenderAsSky(CVu1Context& ctxt, uint32 renderFlags);\r\n\tvoid \t\t\t\tSetBoneTransforms(Mth::Matrix *pMat);\r\n\r\n\t// These modify the actual DMA data\r\n\tvoid\t\t\t\tTranslate(const Mth::Vector & delta_trans);\t\t// delta since we don't store the original pos\r\n\tvoid\t\t\t\tRotateY(const Mth::Vector & world_origin, Mth::ERot90 rot_y, bool root = true);\t// don't set root\r\n\tvoid\t\t\t\tScale(const Mth::Vector & world_origin, const Mth::Vector & delta_scale, bool root = true); // delta since we don't store the original scale\r\n\r\n\tvoid \t\t\t\tGetVerts(Mth::Vector *p_verts, bool root = true);\t\t// don't set root on any of these\r\n\tvoid \t\t\t\tGetColors(uint32 *p_colors, bool root = true);\r\n\tvoid \t\t\t\tSetVerts(Mth::Vector *p_verts, bool root = true);\r\n\tvoid \t\t\t\tSetColors(uint32 *p_colors, bool root = true);\r\n\t#endif\r\n\r\n\tbool\t\t\t\tIsLeaf();\r\n\tbool\t\t\t\tIsActive();\r\n\tbool\t\t\t\tIsObject();\r\n\tbool\t\t\t\tIsTransformed();\r\n\tbool\t\t\t\tIsSky();\r\n\tbool\t\t\t\tIsColored();\r\n\tbool\t\t\t\tIsSkeletal();\r\n\tbool\t\t\t\tIsEnvMapped();\r\n\tbool\t\t\t\tIsUVWibbled();\r\n\tbool\t\t\t\tIsBillboard();\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\tbool\t\t\t\tWasRendered();\r\n#else\r\n\tbool\t\t\t\tWasRendered() {return false;};\t\r\n#endif\r\n\t\r\n\r\n\tvoid\t\t\t\tSetLeaf(bool yes);\r\n\tvoid\t\t\t\tSetActive(bool yes);\r\n\tvoid\t\t\t\tSetObject(bool yes);\r\n\tvoid\t\t\t\tSetTransformed(bool yes);\r\n\tvoid\t\t\t\tSetSky(bool yes);\r\n\tvoid\t\t\t\tSetZPush0(bool yes);\r\n\tvoid\t\t\t\tSetZPush1(bool yes);\r\n\tvoid\t\t\t\tSetZPush2(bool yes);\r\n\tvoid\t\t\t\tSetZPush3(bool yes);\r\n\tvoid\t\t\t\tSetNoShadow(bool yes);\r\n\tvoid\t\t\t\tSetUVWibbled(bool yes);\r\n\tvoid\t\t\t\tSetVCWibbled(bool yes);\r\n\tvoid\t\t\t\tSetColored(bool yes);\r\n\tvoid\t\t\t\tSetSkinned(bool yes);\r\n\tvoid\t\t\t\tSetBillboard(bool yes);\r\n\tvoid\t\t\t\tSetSkeletal(bool yes);\r\n\tvoid\t\t\t\tSetEnvMapped(bool yes);\r\n\tvoid\t\t\t\tSetBlackFog(bool yes);\r\n\r\n\tvoid\t\t\t\tSetChecksum(uint32 checksum);\r\n\tvoid\t\t\t\tSetBoundingSphere(float x, float y, float z, float R);\t// change args to const Mth::Vector sphere\r\n\tvoid\t\t\t\tSetBoundingBox(float x, float y, float z);\t\t\t\t// change args to const Mth::Vector box\r\n\tvoid\t\t\t\tSetDma(uint8 *pDma);\r\n\tvoid\t\t\t\tSetDmaTag(uint8 *pDma);\r\n\tvoid\t\t\t\tSetChild(CGeomNode *pChild);\r\n\tvoid\t\t\t\tAddChild(CGeomNode *pChild);\r\n\tvoid\t\t\t\tSetSibling(CGeomNode *pSibling);\r\n\tvoid\t\t\t\tSetSlaveLOD(CGeomNode *pLOD);\r\n\tvoid\t\t\t\tSetLODFarDist(float LOD_far_dist);\r\n\tvoid\t\t\t\tSetGroup(sGroup *pGroup);\r\n\tvoid\t\t\t\tSetMatrix(Mth::Matrix *p_mat);\r\n\tvoid\t\t\t\tSetUVWibblePointer(float *pData);\r\n\tvoid\t\t\t\tSetVCWibblePointer(uint32 *pData);\r\n\tvoid\t\t\t\tSetColor(uint32 rgba);\r\n\tvoid\t\t\t\tSetLightGroup(CLightGroup *p_light_group);\r\n\tvoid\t\t\t\tSetVisibility(uint8 mask);\r\n\tvoid\t\t\t\tSetBoneIndex(sint8 index);\r\n\r\n\t// Texture pointer starts off as a texture checksum in SceneConv\r\n\tvoid\t\t\t\tSetTextureChecksum(uint32 checksum) {u4.mp_texture = (sTexture*)checksum;}\r\n\tuint32\t\t\t\tGetTextureChecksum() {return (uint32)u4.mp_texture;}\r\n\t#ifdef __PLAT_NGPS__\r\n\tvoid\t\t\t\tSetTexture(sTexture *p_texture) {u4.mp_texture = p_texture;}\r\n\tsTexture *\t\t\tGetTexture() {return u4.mp_texture;}\r\n\t#endif\r\n\r\n\tvoid\t\t\t\tSetUVWibbleParams(float u_vel, float u_amp, float u_freq, float u_phase,\r\n\t\t\t\t\t\t\t\t\t\t  float v_vel, float v_amp, float v_freq, float v_phase);\r\n\tvoid\t\t\t\tUseExplicitUVWibble(bool yes);\r\n\tvoid\t\t\t\tSetUVWibbleOffsets(float u_offset, float v_offset);\r\n\r\n\tvoid\t\t\t\tSetUVOffset(uint32 material_name, int pass, float u_offset, float v_offset);\r\n\tvoid \t\t\t\tSetUVMatrix(uint32 material_name, int pass, Mth::Matrix &mat);\r\n\t\r\n\tuint32\t\t\t\tGetChecksum();\r\n\tMth::Matrix&\t\tGetMatrix();\r\n\tCGeomNode*\t\t\tGetChild();\r\n\tCGeomNode*\t\t\tGetSibling();\r\n\tuint8*\t\t\t\tGetDma();\r\n\tsGroup*\t\t\t\tGetGroup();\r\n\tuint32\t\t\t\tGetColor();\r\n\tfloat\t\t\t\tGetLODFarDist();\r\n\tCLightGroup *\t\tGetLightGroup();\r\n\tuint8\t\t\t\tGetVisibility();\r\n\tMth::Vector\t\t\tGetBoundingSphere();\r\n\tMth::CBBox\t\t\tGetBoundingBox();\r\n\tsint8\t\t\t\tGetBoneIndex();\r\n\r\n\tuint32\t\t\t\tGetFlags(){return m_flags;}\r\n\r\n\tvoid\t\t\t\tCountMetrics(CGeomMetrics *p_metrics);\r\n\tvoid\t\t\t\tRenderWireframe(int mode);\r\n\tvoid\t\t\t\tRenderWireframeRecurse(int mode, int &lines);\r\n\t\r\n\t\t\t\t\t\t\t\t   \r\n\tint\t\t\t\t\tGetNumBones() { return m_num_bones; }\r\n\tint\t\t\t\t\tGetNumVerts();\r\n\tint\t\t\t\t\tGetNumPolys();\r\n\tint\t\t\t\t\tGetNumBasePolys();\r\n\r\n\t// To get at the different objects in a heirarchy\r\n\tint\t\t\t\t\tGetNumObjects();\r\n\tCGeomNode*\t\t\tGetObject(int num, bool root = true);\t\t// Don't set root\r\n\r\n\r\n\t#ifdef __PLAT_WN32__\r\n\tvoid \t\t\t\tPreprocess(uint8 *p_baseAddress);\r\n\t#endif\r\n\r\n\t#ifdef __PLAT_NGPS__\r\n\tstatic CGeomNode*\tsProcessInPlace(uint8 *pPipData, uint32 loadFlags);\r\n\tstatic void *\t\tsGetHierarchyArray(uint8 *pPipData, int& size);\r\n\tvoid\t\t\t\tAddToTree(uint32 loadFlags);\r\n\tvoid\t\t\t\tCleanup();\r\n\t\r\n\tCGeomNode*\t\t\tCreateInstance(Mth::Matrix *pMat, CGeomNode *p_parent = NULL);\r\n\tCGeomNode*\t\t\tCreateInstance(Mth::Matrix *pMat, int numBones, Mth::Matrix *pBoneTransforms, CGeomNode *p_parent = NULL);\r\n\tvoid\t\t\t\tDeleteInstance();\r\n\tCGeomNode*\t\t\tCreateCopy(CGeomNode *p_parent = NULL, bool root = true);\t\t\t\t// Don't set root\r\n\tvoid\t\t\t\tDeleteCopy(bool root = true);\t\t\t\t\t\t\t\t\t\t\t// Don't set root\r\n\t#endif\r\n\t\r\n\tbool\t\t\t\tCullAgainstViewFrustum();\r\n\tbool\t\t\t\tCullAgainstOuterFrustum();\r\n\r\n\r\n\tvoid\t\t\t\tInit();\r\n\r\n\t\t\t\t\t\tCGeomNode();\r\n\t\t\t\t\t\tCGeomNode(const CGeomNode &node);\r\n\t\t\t\t\t\t~CGeomNode() {}\r\n\r\n\r\n\t\t\t\t\t\tstatic CGeomNode\tsWorld;\r\n\t\t\t\t\t\tstatic CGeomNode\tsDatabase;\r\n\r\n\r\nprivate:\r\n\r\n\t#ifdef __PLAT_NGPS__\r\n\tbool\t\t\t\tSphereIsOutsideViewVolume(Mth::Vector &s);\r\n\tbool\t\t\t\tSphereIsInsideOuterVolume(Mth::Vector &s);\r\n\tbool\t\t\t\tBoxIsOutsideViewVolume(Mth::Vector& b, Mth::Vector& s);\r\n\tbool\t\t\t\tNeedsClipping(Mth::Vector &s);\r\n\tvoid\t\t\t\tLinkDma(uint8 *p_newTail);\r\n\tint\t \t\t\t\tProcessNodeInPlace(uint8 *p_baseAddress);\r\n\tvoid \t\t\t\tBecomesChildOf(CGeomNode *p_parent);\r\n\tbool\t\t\t\tRemoveFrom(CGeomNode *p_parent);\r\n\tbool\t\t\t\tRemoveFromChildrenOf(CGeomNode *p_parent);\r\n\tvoid \t\t\t\tWibbleVCs();\r\n\r\n\tvoid \t\t\t\trecalculate_bounding_data(Mth::Vector *p_verts, int num_verts);\r\n\t#endif\r\n\r\n\tMth::Vector\t\t\tm_bounding_sphere;\r\n\tfloat\t\t\t\tm_bounding_box[3];\r\n\tuint32\t\t\t\tm_flags;\r\n\tunion\r\n\t{\r\n\t\tCGeomNode *\t\tmp_child;\t\t\t// internal\r\n\t\tuint8 *\t\t\tmp_dma;\t\t\t\t// leaf\r\n\t} u1;\r\n\tunion\r\n\t{\r\n\t\tMth::Matrix *\tmp_transform;\t\t// internal\r\n\t\tuint32\t\t\tm_dma_tag_lo32;\t\t// leaf\r\n\t} u2;\r\n\tCGeomNode *\t\t\tmp_sibling;\r\n\tunion\r\n\t{\r\n\t\tsGroup *\t\tmp_group;\t\t\t// leaf\r\n\t\tCLightGroup *\tmp_light_group;\t\t// optional group of lights\r\n\t} u3;\r\n\tuint32\t\t\t\tm_checksum;\r\n\tfloat *\t\t\t\tmp_uv_wibble;\t\t// leaf\r\n\tuint32 *\t\t\tmp_vc_wibble;\t\t// leaf\r\n\tuint32\t\t\t\tm_colour;\r\n\t// used for skeletal models...\r\n\tsint8\t\t\t\tm_num_bones;\t\t// skeletal, internal, instance\r\n\tsint8\t\t\t\tm_bone_index;\t\t// skeletal, internal, source\r\n\tuint16\t\t\t\tm_field;\t\t\t// skeletal, internal, instance\r\n\tunion \r\n\t{\r\n\t\tMth::Matrix *\t\tmp_bone_transforms;\t// skeletal, internal, instance\r\n\t\tsTexture\t*\t\tmp_texture;\t\t\t// Level Geometry leaf- pointer to the texture we use\r\n\t} u4;\r\n\tfloat\t\t\t\tm_LOD_far_dist;\r\n\tCGeomNode *\t\t\tmp_next_LOD;\r\n\t\t\t\t\t\t\t\t\t\t\t// stay quadword-aligned with padding if necessary\r\n};\r\n\r\n\r\n// Hierarchy information available to game.  It is found at the beginning of a geom.ps2 file,\r\n// although it is not used by the CGeomNodes.\r\nclass CHierarchyObject\r\n{\r\npublic:\r\n\t\t\t\t\t\tCHierarchyObject();\r\n\t\t\t\t\t\t~CHierarchyObject();\r\n\r\n\tvoid\t\t\t\tSetChecksum(uint32 checksum);\r\n\tuint32\t\t\t\tGetChecksum() const;\r\n\tvoid\t\t\t\tSetParentChecksum(uint32 checksum);\r\n\tuint32\t\t\t\tGetParentChecksum() const;\r\n\tvoid\t\t\t\tSetParentIndex(int16 index);\r\n\tint16\t\t\t\tGetParentIndex() const;\r\n\tvoid\t\t\t\tSetBoneIndex(sint8 index);\r\n\tsint8\t\t\t\tGetBoneIndex() const;\r\n\r\n\tvoid\t\t\t\tSetSetupMatrix(const Mth::Matrix& mat);\r\n\tconst Mth::Matrix &\tGetSetupMatrix() const;\r\n\r\n\t\r\nprotected:\r\n\tuint32\t\t\t\tm_checksum;\t\t\t// Object checksum\r\n\tuint32\t\t\t\tm_parent_checksum;\t// Checksum of parent, or 0 if root object\r\n\tint16\t\t\t\tm_parent_index;\t\t// Index of parent in the hierarchy array (or -1 if root object)\r\n\tsint8\t\t\t\tm_bone_index;\t\t// The index of the bone matrix used on this object\r\n\tuint8\t\t\t\tm_pad_8;\r\n\tuint32\t\t\t\tm_pad_32;\r\n\tMth::Matrix\t\t\tm_setup_matrix;\t\t// Initial local to parent matrix\r\n};\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n//extern CGeomNode\t*pShadowList[SHADOW_LIST_SIZE];\r\nextern uint\t\t\tNumShadowListEntries;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace NxPs2\r\n\r\n#endif\t// __GFX_NGPS_NX_GEOMETRY_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/gif.cpp",
    "content": "#include <core/defines.h>\r\n#include <math.h>\r\n#include \"dma.h\"\r\n#include \"gif.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n\r\n/*\tͻ\r\n\t GIFtag format \r\n\tͼ\r\n\r\n\r\n\t 31                                           16 15 14                                         0\r\n\tĿ\r\n\t                                               EOP                   NLOOP                    \r\n\t\r\n\r\n\r\n\t 63       60 59 58 57                            47 46 45                                     32\r\n\tĿ\r\n\t   NREG     FLG               PRIM              PRE                                         \r\n\t\r\n\r\n\r\n\t 95                                                       76 75       72 71       68 67       64\r\n\tĿ\r\n\t                                                     ...     [REG2]     [REG1]      REG0    \r\n\t\r\n\r\n\r\n\t 127                                                                                          96\r\n\tĿ\r\n\t                                                                                               \r\n\t\r\n\r\n\r\n\r\n\tͻ\r\n\t PATH1 GIFtag format \r\n\tͼ\r\n\r\n\r\n\t 31 30                   23 22                16 15 14                                         0\r\n\tĿ\r\n\t0      NREG exponent      << NREG            EOP                   NLOOP                    \r\n\t\r\n\r\n\r\n\t 63       60 59 58 57                            47 46 45    43 42                            32\r\n\tĿ\r\n\t   NREG     FLG               PRIM              PRE                      ADDR              \r\n\t\r\n\r\n\r\n\t 95                                                       76 75       72 71       68 67       64\r\n\tĿ\r\n\t                                                     ...     [REG2]     [REG1]      REG0    \r\n\t\r\n\r\n\r\n\t 127                                         112 111           106 105                        96\r\n\tĿ\r\n\t                                                     flags                  SIZE             \r\n\t\r\n\r\n\r\n\tflags:\r\n\t106 -\r\n\t107 -\r\n\t108 -\r\n\t109 -\r\n\t110 - no ITOP\t}\r\n\t111 - no ITOP\t} uses 2 flags because the parsing loop is quicker\r\n\t\r\n\r\n\r\n*/\r\n\r\n\r\n\r\n//-------------------------------------------------\r\n//\t\tG I F T A G   C O N S T R U C T I O N\r\n//-------------------------------------------------\r\n\r\n\r\n// PATH1\r\n\r\n\r\nvoid gif::Tag1(uint32 Regs, uint NReg, uint Flg, uint Prim, uint Pre, uint Eop, uint NLoop, uint Addr)\r\n{\r\n\tuint32 size = NReg * NLoop;\r\n\tfloat NRegFloat  = (float)NReg * 1.1920928955e-07f;\t// 2^-23\r\n\tdma::Store32(*(uint32 *)&NRegFloat | Eop<<15 | NLoop,\r\n\t\t\t\t\t\t\tNReg<<28 | Flg<<26 | Prim<<15 | Pre<<14 | Addr,\r\n\t\t\t\t\t\t\tRegs,\r\n\t\t\t\t\t\t\tsize);\r\n}\r\n\r\n\r\nvoid gif::BeginTag1(uint32 Regs, uint NReg, uint Flg, uint Prim, uint Pre, uint Addr)\r\n{\r\n\tfloat NRegFloat = (float)NReg * 1.1920928955e-07f;\t// 2^-23\r\n\tpTag = dma::pLoc;\r\n\tdma::Store32(*(uint32 *)&NRegFloat,\r\n\t\t\t\t\t\t\tNReg<<28 | Flg<<26 | Prim<<15 | Pre<<14 | Addr,\r\n\t\t\t\t\t\t\tRegs,\r\n\t\t\t\t\t\t\t0);\r\n}\r\n\r\n\r\nvoid gif::BeginTag1_extended(uint32 Regs, uint NReg, uint Flg, uint Prim, uint Pre, uint Addr, uint Step)\r\n{\r\n\tfloat StepFloat = (float)Step * 1.1920928955e-07f;\t// 2^-23\r\n\tpTag = dma::pLoc;\r\n\tdma::Store32(*(uint32 *)&StepFloat,\r\n\t\t\t\t\tNReg<<28 | Flg<<26 | Prim<<15 | Pre<<14 | Addr,\r\n\t\t\t\t\tRegs,\r\n\t\t\t\t\t0);\r\n}\r\n\r\n\r\nvoid gif::EndTag1(uint Eop)\r\n{\r\n\tuint32 size = vif::UnpackSize * vif::CycleLength;\r\n\t((uint32 *)pTag)[0] |= Eop<<15 | vif::UnpackSize;\r\n\t((uint32 *)pTag)[3] = size;\r\n\tvu1::Loc += vif::UnpackSize * vif::CycleLength + 1;\r\n}\r\n\r\n\r\nvoid gif::BeginTagImmediate(uint32 Regs, uint NReg, uint Flg, uint Prim, uint Pre, uint Addr)\r\n{\r\n\tfloat NRegFloat = (float)NReg * 1.1920928955e-07f;\t// 2^-23\r\n\tpTag = dma::pLoc;\r\n\tdma::Store32(*(uint32 *)&NRegFloat,\r\n\t\t\t\t\t\t\tNReg<<28 | Flg<<26 | Prim<<15 | Pre<<14 | Addr,\r\n\t\t\t\t\t\t\tRegs,\r\n\t\t\t\t\t\t\t0);\r\n}\r\n\r\n\r\nvoid gif::EndTagImmediate(uint Eop)\r\n{\r\n\tuint32 size = vif::UnpackSize;\r\n\tuint NREG = pTag[7]>>4;\r\n\t((uint32 *)pTag)[0] |= Eop<<15 | (vif::UnpackSize/NREG);\r\n\t((uint32 *)pTag)[3] = size;\r\n\tvu1::Loc += vif::UnpackSize+1;\r\n}\r\n\r\n\r\n\r\n\r\n// PATH2 or 3\r\n\r\nvoid gif::Tag2(uint32 Regs, uint NReg, uint Flg, uint Prim, uint Pre, uint Eop, uint NLoop)\r\n{\r\n\tdma::Store32(\tEop<<15 | NLoop,\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\tNReg<<28 | Flg<<26 | Prim<<15 | Pre<<14,\r\n\t\t\t\t\tRegs,\r\n\t\t\t\t\t0);\r\n}\r\n\r\n\r\nvoid gif::BeginTag2(uint32 Regs, uint NReg, uint Flg, uint Prim, uint Pre)\r\n{\r\n\tpTag = dma::pLoc;\r\n\tdma::Store32(\t0,\r\n\t\t\t\t\tNReg<<28 | Flg<<26 | Prim<<15 | Pre<<14,\r\n\t\t\t\t\tRegs,\r\n\t\t\t\t\t0);\r\n}\r\n\r\n\r\nvoid gif::EndTag2(uint Eop)\r\n{\r\n\tuint FLG  = pTag[7]>>2 & 3;\r\n\tuint NREG = pTag[7]>>4;\r\n\tuint NLOOP;\r\n\tif (FLG==IMAGE)\r\n\t\tNLOOP = (dma::pLoc - pTag - 16) / 16;\r\n\telse\r\n\t\tNLOOP = (dma::pLoc - pTag - 16) / (16*NREG);\r\n\t*(uint32 *)pTag |= Eop<<15 | NLOOP;\r\n}\r\n\r\n\r\n//--------------------------------\r\n//\t\tS T A T I C   D A T A\r\n//--------------------------------\r\n\r\nuint8 *gif::pTag;\r\n\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/gif.h",
    "content": "#ifndef __GIF_H\r\n#define __GIF_H\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n// GIFtag FLG definitions\r\n#define PACKED\t0\r\n#define REGLIST\t1\r\n#define IMAGE\t2\r\n\r\nclass gif\r\n{\r\n\r\npublic:\r\n\r\n\t//------------------------------------------\r\n\t//\t\tS T A T I C   F U N C T I O N S\r\n\t//------------------------------------------\r\n\r\n\tstatic void Tag1(uint32 Regs, uint NReg, uint Flg, uint Prim, uint Pre, uint Eop, uint NLoop, uint Addr);\r\n\tstatic void EndTag1(uint Eop);\r\n\tstatic void BeginTag1(uint32 Regs, uint NReg, uint Flg, uint Prim, uint Pre, uint Addr);\r\n\tstatic void BeginTag1_extended(uint32 Regs, uint NReg, uint Flg, uint Prim, uint Pre, uint Addr, uint Step);\r\n\tstatic void EndTagImmediate(uint Eop);\r\n\tstatic void BeginTagImmediate(uint32 Regs, uint NReg, uint Flg, uint Prim, uint Pre, uint Addr);\r\n\tstatic void Tag2(uint32 Regs, uint NReg, uint Flg, uint Prim, uint Pre, uint Eop, uint NLoop);\r\n\tstatic void EndTag2(uint Eop);\r\n\tstatic void BeginTag2(uint32 Regs, uint NReg, uint Flg, uint Prim, uint Pre);\r\n\r\n\t//--------------------------------\r\n\t//\t\tS T A T I C   D A T A\r\n\t//--------------------------------\r\n\r\n\tstatic uint8 *pTag;\r\n\r\n}; // class gif\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n#endif // __GIF_H\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/group.cpp",
    "content": "#include <core/defines.h>\r\n#include \"group.h\"\r\n\t\r\n/*\r\n\r\n (Notes by Mick)\r\n \r\n A Group is a set of textures, and a set of meshes or primitives that use those textures.\r\n \r\n Rendering is performed one group at a time. \r\n \r\n The textures for a group are uploaded, and then it is rendered.\r\n \r\n Whilst a group is being rendered, the uploading of the next group's textures\r\n can start to be uploaded.\r\n \r\n This all happens asyncronously, whilst the CPU is doing the calculations for the next frame.\r\n \r\n The uploading/rendering cycle is syncronized by interrupts.\r\n \r\n The groups are rendered in this order:\r\n \r\n 1) PrologueGroup - set up in render.cpp - flips the display buffers and initializes VU1 microcode \r\n 2) The groups linked by PrologueGroup->pNext, which represent groups of textures and polygons\r\n 3) pEpilogue, (the last in this list) - uploads fonts and sprites, allowing them to be rendered next\r\n\r\n after the groups are rendered, we can render the 2D elements, namely the sprites and fonts (see render.cpp)\r\n\r\n*/\r\n\t\t\t\t\r\n\t\t\t\t\r\nnamespace NxPs2\r\n{\r\n\r\nsGroup *sGroup::pHead;\r\nsGroup *sGroup::pTail;\r\nsGroup *sGroup::pShadow;\r\nsGroup *sGroup::pFog;\r\nsGroup *sGroup::pParticles;\r\nsGroup *sGroup::pEpilogue;\r\nvolatile sGroup *sGroup::pUploadGroup;    // Group that is currently uploading\r\nvolatile sGroup *sGroup::pRenderGroup;\t  // Group that is currently rendering\r\nuint32 sGroup::VramBufferBase;\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/group.h",
    "content": "#ifndef __GROUP_H\r\n#define __GROUP_H\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n#define GROUPFLAG_TRANSPARENT\t(1<<0)\r\n#define GROUPFLAG_SKY\t\t\t(1<<1)\r\n#define GROUPFLAG_SORT\t\t\t(1<<2)\r\n\r\n\r\nclass CVu1Context;\r\nstruct STransformContext;\r\n\r\n\r\nstruct sGroup\r\n{\r\npublic:\r\n\tsGroup *pNext;\r\n\r\n\tfloat  Priority;\r\n\tuint32 Checksum;\r\n\tuint32 flags;\r\n\tuint8  *pUpload[2];\r\n\tuint8  *pRender[2];\r\n\tuint8  *pListEnd[2];\r\n\tbool\tUsed[2];\t\t\t// flag saying if this group is actually used this frame (has something in the pRender data)\r\n\tstruct sMesh  *pMeshes;\r\n\tint    NumMeshes;\r\n\tuint   vu1_loc;\r\n\tuint8  *p_tag;\r\n\r\n\tuint32 VramStart;\r\n\tuint32 VramEnd;\r\n\r\n\tstruct sScene *pScene;\r\n\r\n\tsGroup *pPrev;\r\n\r\n\tstatic sGroup *pHead;\r\n\tstatic sGroup *pTail;\r\n\tstatic sGroup *pShadow;\r\n\tstatic sGroup *pFog;\r\n\tstatic sGroup *pParticles;\r\n\tstatic sGroup *pEpilogue;\r\n\tvolatile static sGroup *pUploadGroup;\r\n\tvolatile static sGroup *pRenderGroup;\r\n\tstatic uint32 VramBufferBase;\r\n\t//STransformContext *pTransformContext;\r\n\tCVu1Context *pVu1Context;\r\n\tuint32\tprofile_color;\t\t\t\t\t// color we display it as in the profiler\r\n};\r\n\r\n} // namespace NxPs2\r\n\r\n#endif // __GROUP_H\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/gs.cpp",
    "content": "#include <core/defines.h>\r\n#include \"vu1code.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n//--------------------------------------------------\r\n//\t\tG S   P R I M   C O N S T R U C T I O N\r\n//--------------------------------------------------\r\n\r\n\r\n// begin\r\nvoid gs::BeginPrim(uint FLG, uint Prim, uint Pre)\r\n{\r\n\tvif::STCYCL(1,1);\r\n\tvif::UNPACK(0, V4_32, 1, FLG, UNSIGNED, 0);\r\n\tgif::BeginTag1(gs::A_D, 1, PACKED, Prim, Pre, VU1_ADDR(GSPrim));\r\n\tvif::BeginUNPACK(0, V3_32, FLG, UNSIGNED, 1);\r\n}\r\n\r\n\r\n// end\r\nvoid gs::EndPrim(uint Eop)\r\n{\r\n\tvif::EndUNPACK();\r\n\tgif::EndTag1(Eop);\r\n}\r\n\r\n\r\n\r\n\r\n// output 1 GS register DIRECT via PATH2, V4_32 format\r\nvoid gs::Reg2(eReg Reg, uint64 Data)\r\n{\r\n\tdma::Store64(Data);\r\n\tdma::Store64((uint64)Reg);\r\n}\r\n\r\n\r\n// version returning address of data\r\nuint32 *gs::Reg2_pData(eReg Reg, uint64 Data)\r\n{\r\n\tuint32 *p_ret = (uint32 *) dma::pLoc;\r\n\r\n\tdma::Store64(Data);\r\n\tdma::Store64((uint64)Reg);\r\n\r\n\treturn p_ret;\r\n}\r\n\r\n\r\n// Modify the TBPs of GS registers\r\nvoid gs::ModifyTBP(eReg Reg, uint32 *p_reg_ptr, sint16 tbp1, sint16 tbp2, sint16 tbp3)\r\n{\r\n\tswitch (Reg)\r\n\t{\r\n\tcase BITBLTBUF:\t\t// only modifies DBP\r\n\t\t*(++p_reg_ptr) &= ~(M14);\t\t\t\t// DBP\r\n\t\t*(  p_reg_ptr) |= (tbp1 & M14);\r\n\t\tbreak;\r\n\r\n\tcase TEX0_1:\r\n\tcase TEX0_2:\r\n\t\t*(  p_reg_ptr) &= ~(M14);\t\t\t\t// TBP\r\n\t\t*(  p_reg_ptr) |= (tbp1 & M14);\r\n\t\tif (tbp2 >= 0)\r\n\t\t{\r\n\t\t\t*(++p_reg_ptr) &= ~(M14 << 5);\t\t// CBP\r\n\t\t\t*(  p_reg_ptr) |= (tbp2 & M14) << 5;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\tcase TEX2_1:\r\n\tcase TEX2_2:\r\n\t\t*(++p_reg_ptr) &= ~(M14 << 5);\t\t\t// CBP\r\n\t\t*(  p_reg_ptr) |= (tbp1 & M14) << 5;\r\n\t\tbreak;\r\n\r\n\tcase MIPTBP1_1:\r\n\tcase MIPTBP1_2:\r\n\tcase MIPTBP2_1:\r\n\tcase MIPTBP2_2:\r\n\tdefault:\r\n\t\t#ifdef __PLAT_NGPS__\r\n\t\tDbg_MsgAssert(0, (\"gs::ModifyTBP(): Can't modify register %x\", Reg));\r\n\t\t#endif\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/gs.h",
    "content": "#ifndef __GS_H\r\n#define __GS_H\r\n\r\n#include \"dma.h\"\r\n\r\n//---------------------------------------------------\r\n//\t\tR E G I S T E R   D E F I N I T I O N S\r\n//---------------------------------------------------\r\n\r\n\r\n\r\n// mask definitions for packing macros\r\n#define M01\t0x0000000000000001\r\n#define M02\t0x0000000000000003\r\n#define M03\t0x0000000000000007\r\n#define M04\t0x000000000000000F\r\n#define M05\t0x000000000000001F\r\n#define M06\t0x000000000000003F\r\n#define M08\t0x00000000000000FF\r\n#define M09\t0x00000000000001FF\r\n#define M10\t0x00000000000003FF\r\n#define M11\t0x00000000000007FF\r\n#define M12\t0x0000000000000FFF\r\n#define M14\t0x0000000000003FFF\r\n#define M16\t0x000000000000FFFF\r\n#define M24\t0x0000000000FFFFFF\r\n#define M32\t0x00000000FFFFFFFF\r\n#define M64\t0xFFFFFFFFFFFFFFFF\r\n\r\n\r\n//----------------------------------------------------------------------------------------\r\n//\t\tG E N E R A L   P U R P O S E   R E G I S T E R   P A C K I N G   M A C R O S\r\n//----------------------------------------------------------------------------------------\r\n\r\n#define PackALPHA(A,B,C,D,FIX)\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (A)\t\t& M02 )\t<< 0\t|\t\\\r\n\t( (uint64) (B)\t\t& M02 )\t<< 2\t|\t\\\r\n\t( (uint64) (C)\t\t& M02 )\t<< 4\t|\t\\\r\n\t( (uint64) (D)\t\t& M02 )\t<< 6\t|\t\\\r\n\t( (uint64) (FIX)\t& M08 )\t<< 32\t\t\\\r\n)\r\n\r\n#define PackBITBLTBUF(SBP,SBW,SPSM,DBP,DBW,DPSM)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (SBP)\t& M14 )\t<< 0\t|\t\\\r\n\t( (uint64) (SBW)\t& M06 )\t<< 16\t|\t\\\r\n\t( (uint64) (SPSM)\t& M06 )\t<< 24\t|\t\\\r\n\t( (uint64) (DBP)\t& M14 )\t<< 32\t|\t\\\r\n\t( (uint64) (DBW)\t& M06 )\t<< 48\t|\t\\\r\n\t( (uint64) (DPSM)\t& M06 )\t<< 56\t\t\\\r\n)\r\n\r\n#define PackCLAMP(WMS,WMT,MINU,MAXU,MINV,MAXV)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (WMS)\t& M02 )\t<< 0\t|\t\\\r\n\t( (uint64) (WMT)\t& M02 )\t<< 2\t|\t\\\r\n\t( (uint64) (MINU)\t& M10 )\t<< 4\t|\t\\\r\n\t( (uint64) (MAXU)\t& M10 )\t<< 14\t|\t\\\r\n\t( (uint64) (MINV)\t& M10 )\t<< 24\t|\t\\\r\n\t( (uint64) (MAXV)\t& M10 )\t<< 34\t\t\\\r\n)\r\n\r\n#define PackCOLCLAMP(CLAMP)\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (CLAMP)\t& M01 )\t<< 0\t\t\\\r\n)\r\n\r\n#define PackDIMX(DM00,DM01,DM02,DM03,DM10,DM11,DM12,DM13,DM20,DM21,DM22,DM23,DM30,DM31,DM32,DM33)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (DM00)\t& M03 )\t<< 0\t|\t\\\r\n\t( (uint64) (DM01)\t& M03 )\t<< 4\t|\t\\\r\n\t( (uint64) (DM02)\t& M03 )\t<< 8\t|\t\\\r\n\t( (uint64) (DM03)\t& M03 )\t<< 12\t|\t\\\r\n\t( (uint64) (DM10)\t& M03 )\t<< 16\t|\t\\\r\n\t( (uint64) (DM11)\t& M03 )\t<< 20\t|\t\\\r\n\t( (uint64) (DM12)\t& M03 )\t<< 24\t|\t\\\r\n\t( (uint64) (DM13)\t& M03 )\t<< 28\t|\t\\\r\n\t( (uint64) (DM20)\t& M03 )\t<< 32\t|\t\\\r\n\t( (uint64) (DM21)\t& M03 )\t<< 36\t|\t\\\r\n\t( (uint64) (DM22)\t& M03 )\t<< 40\t|\t\\\r\n\t( (uint64) (DM23)\t& M03 )\t<< 44\t|\t\\\r\n\t( (uint64) (DM30)\t& M03 )\t<< 48\t|\t\\\r\n\t( (uint64) (DM31)\t& M03 )\t<< 52\t|\t\\\r\n\t( (uint64) (DM32)\t& M03 )\t<< 56\t|\t\\\r\n\t( (uint64) (DM33)\t& M03 )\t<< 60\t\t\\\r\n)\r\n\r\n#define PackDTHE(DTHE)\t\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (DTHE)\t& M01 )\t<< 0\t\t\\\r\n)\r\n\r\n#define PackFBA(FBA)\t\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (FBA)\t& M01 )\t<< 0\t\t\\\r\n)\r\n\r\n#define PackFOG(F)\t\t\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (F)\t\t& M08 )\t<< 56\t\t\\\r\n)\r\n\r\n#define PackFOGCOL(FCR,FCG,FCB)\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (FCR)\t& M08 )\t<< 0\t|\t\\\r\n\t( (uint64) (FCG)\t& M08 )\t<< 8\t|\t\\\r\n\t( (uint64) (FCB)\t& M08 )\t<< 16\t\t\\\r\n)\r\n\r\n#define PackFRAME(FBP,FBW,PSM,FBMSK)\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (FBP)\t& M09 )\t<< 0\t|\t\\\r\n\t( (uint64) (FBW)\t& M06 )\t<< 16\t|\t\\\r\n\t( (uint64) (PSM)\t& M06 )\t<< 24\t|\t\\\r\n\t( (uint64) (FBMSK)\t& M32 )\t<< 32\t\t\\\r\n)\r\n\r\n#define PackHWREG(DATA)\t\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (DATA)\t& M64 )\t<< 0\t\t\\\r\n)\r\n\r\n#define PackLABEL(ID,IDMSK)\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (ID)\t\t& M32 )\t<< 0\t|\t\\\r\n\t( (uint64) (IDMSK)\t& M32 )\t<< 32\t\t\\\r\n)\r\n\r\n#define PackMIPTBP1(TBP1,TBW1,TBP2,TBW2,TBP3,TBW3)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (TBP1)\t& M14 )\t<< 0\t|\t\\\r\n\t( (uint64) (TBW1)\t& M06 )\t<< 14\t|\t\\\r\n\t( (uint64) (TBP2)\t& M14 )\t<< 20\t|\t\\\r\n\t( (uint64) (TBW2)\t& M06 )\t<< 34\t|\t\\\r\n\t( (uint64) (TBP3)\t& M14 )\t<< 40\t|\t\\\r\n\t( (uint64) (TBW3)\t& M06 )\t<< 54\t\t\\\r\n)\r\n\r\n#define PackMIPTBP2(TBP4,TBW4,TBP5,TBW5,TBP6,TBW6)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (TBP4)\t& M14 )\t<< 0\t|\t\\\r\n\t( (uint64) (TBW4)\t& M06 )\t<< 14\t|\t\\\r\n\t( (uint64) (TBP5)\t& M14 )\t<< 20\t|\t\\\r\n\t( (uint64) (TBW5)\t& M06 )\t<< 34\t|\t\\\r\n\t( (uint64) (TBP6)\t& M14 )\t<< 40\t|\t\\\r\n\t( (uint64) (TBW6)\t& M06 )\t<< 54\t\t\\\r\n)\r\n\r\n#define PackPABE(PABE)\t\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (PABE)\t& M01 )\t<< 0\t\t\\\r\n)\r\n\r\n#define PackPRIM(PRIM,IIP,TME,FGE,ABE,AA1,FST,CTXT,FIX)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (PRIM)\t& M03 )\t<< 0\t|\t\\\r\n\t( (uint64) (IIP)\t& M01 )\t<< 3\t|\t\\\r\n\t( (uint64) (TME)\t& M01 )\t<< 4\t|\t\\\r\n\t( (uint64) (FGE)\t& M01 )\t<< 5\t|\t\\\r\n\t( (uint64) (ABE)\t& M01 )\t<< 6\t|\t\\\r\n\t( (uint64) (AA1)\t& M01 )\t<< 7\t|\t\\\r\n\t( (uint64) (FST)\t& M01 )\t<< 8\t|\t\\\r\n\t( (uint64) (CTXT)\t& M01 )\t<< 9\t|\t\\\r\n\t( (uint64) (FIX)\t& M01 )\t<< 10\t\t\\\r\n)\r\n\r\n#define PackPRMODE(IIP,TME,FGE,ABE,AA1,FST,CTXT,FIX)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (IIP)\t& M01 )\t<< 3\t|\t\\\r\n\t( (uint64) (TME)\t& M01 )\t<< 4\t|\t\\\r\n\t( (uint64) (FGE)\t& M01 )\t<< 5\t|\t\\\r\n\t( (uint64) (ABE)\t& M01 )\t<< 6\t|\t\\\r\n\t( (uint64) (AA1)\t& M01 )\t<< 7\t|\t\\\r\n\t( (uint64) (FST)\t& M01 )\t<< 8\t|\t\\\r\n\t( (uint64) (CTXT)\t& M01 )\t<< 9\t|\t\\\r\n\t( (uint64) (FIX)\t& M01 )\t<< 10\t\t\\\r\n)\r\n\r\n#define PackPRMODECONT(AC)\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (AC)\t\t& M01 )\t<< 0\t\t\\\r\n)\r\n\r\n#define PackRGBAQ(R,G,B,A,Q)\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (R)\t\t& M08 )\t<< 0\t|\t\\\r\n\t( (uint64) (G)\t\t& M08 )\t<< 8\t|\t\\\r\n\t( (uint64) (B)\t\t& M08 )\t<< 16\t|\t\\\r\n\t( (uint64) (A)\t\t& M08 )\t<< 24\t|\t\\\r\n\t( (uint64) (Q)\t\t& M32 )\t<< 32\t\t\\\r\n)\r\n\r\n#define PackSCANMSK(MSK)\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (MSK)\t& M01 )\t<< 0\t\t\\\r\n)\r\n\r\n#define PackSCISSOR(SCAX0,SCAX1,SCAY0,SCAY1)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (SCAX0)\t& M11 )\t<< 0\t|\t\\\r\n\t( (uint64) (SCAX1)\t& M11 )\t<< 16\t|\t\\\r\n\t( (uint64) (SCAY0)\t& M11 )\t<< 32\t|\t\\\r\n\t( (uint64) (SCAY1)\t& M11 )\t<< 48\t\t\\\r\n)\r\n\r\n#define PackSIGNAL(ID,IDMSK)\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (ID)\t\t& M32 )\t<< 0\t|\t\\\r\n\t( (uint64) (IDMSK)\t& M32 )\t<< 32\t\t\\\r\n)\r\n\r\n#define PackST(S,T)\t\t\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (S)\t\t& M32 )\t<< 0\t|\t\\\r\n\t( (uint64) (T)\t\t& M32 )\t<< 32\t\t\\\r\n)\r\n\r\n#define PackTEST(ATE,ATST,AREF,AFAIL,DATE,DATM,ZTE,ZTST)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (ATE)\t& M01 )\t<< 0\t|\t\\\r\n\t( (uint64) (ATST)\t& M03 )\t<< 1\t|\t\\\r\n\t( (uint64) (AREF)\t& M08 )\t<< 4\t|\t\\\r\n\t( (uint64) (AFAIL)\t& M02 )\t<< 12\t|\t\\\r\n\t( (uint64) (DATE)\t& M01 )\t<< 14\t|\t\\\r\n\t( (uint64) (DATM)\t& M01 )\t<< 15\t|\t\\\r\n\t( (uint64) (ZTE)\t& M01 )\t<< 16\t|\t\\\r\n\t( (uint64) (ZTST)\t& M02 )\t<< 17\t\t\\\r\n)\r\n\r\n#define PackTEX0(TBP0,TBW,PSM,TW,TH,TCC,TFX,CBP,CPSM,CSM,CSA,CLD)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (TBP0)\t& M14 )\t<< 0\t|\t\\\r\n\t( (uint64) (TBW)\t& M06 )\t<< 14\t|\t\\\r\n\t( (uint64) (PSM)\t& M06 )\t<< 20\t|\t\\\r\n\t( (uint64) (TW)\t\t& M04 )\t<< 26\t|\t\\\r\n\t( (uint64) (TH)\t\t& M04 )\t<< 30\t|\t\\\r\n\t( (uint64) (TCC)\t& M01 )\t<< 34\t|\t\\\r\n\t( (uint64) (TFX)\t& M02 )\t<< 35\t|\t\\\r\n\t( (uint64) (CBP)\t& M14 )\t<< 37\t|\t\\\r\n\t( (uint64) (CPSM)\t& M04 )\t<< 51\t|\t\\\r\n\t( (uint64) (CSM)\t& M01 )\t<< 55\t|\t\\\r\n\t( (uint64) (CSA)\t& M05 )\t<< 56\t|\t\\\r\n\t( (uint64) (CLD)\t& M03 )\t<< 61\t\t\\\r\n)\r\n\r\n#define PackTEX1(LCM,MXL,MMAG,MMIN,MTBA,L,K)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (LCM)\t& M01 )\t<< 0\t|\t\\\r\n\t( (uint64) (MXL)\t& M03 )\t<< 2\t|\t\\\r\n\t( (uint64) (MMAG)\t& M01 )\t<< 5\t|\t\\\r\n\t( (uint64) (MMIN)\t& M03 )\t<< 6\t|\t\\\r\n\t( (uint64) (MTBA)\t& M01 )\t<< 9\t|\t\\\r\n\t( (uint64) (L)\t\t& M02 )\t<< 19\t|\t\\\r\n\t( (uint64) (K)\t\t& M12 )\t<< 32\t\t\\\r\n)\r\n\r\n#define PackTEX2(PSM,CBP,CPSM,CSM,CSA,CLD)\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (PSM)\t& M06 )\t<< 20\t|\t\\\r\n\t( (uint64) (CBP)\t& M14 )\t<< 37\t|\t\\\r\n\t( (uint64) (CPSM)\t& M04 )\t<< 51\t|\t\\\r\n\t( (uint64) (CSM)\t& M01 )\t<< 55\t|\t\\\r\n\t( (uint64) (CSA)\t& M05 )\t<< 56\t|\t\\\r\n\t( (uint64) (CLD)\t& M03 )\t<< 61\t\t\\\r\n)\r\n\r\n#define PackTEXFLUSH(VAL)\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (VAL)\t& M64 )\t<< 0\t\t\\\r\n)\r\n\r\n#define PackTEXA(TA0,AEM,TA1)\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (TA0)\t& M08 )\t<< 0\t|\t\\\r\n\t( (uint64) (AEM)\t& M01 )\t<< 15\t|\t\\\r\n\t( (uint64) (TA1)\t& M08 )\t<< 32\t\t\\\r\n)\r\n\r\n#define PackTEXCLUT(CBW,COU,COV)\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (CBW)\t& M06 )\t<< 0\t|\t\\\r\n\t( (uint64) (COU)\t& M06 )\t<< 6\t|\t\\\r\n\t( (uint64) (COV)\t& M10 )\t<< 12\t\t\\\r\n)\r\n\r\n#define PackTRXDIR(XDIR)\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (XDIR)\t& M02 )\t<< 0\t\t\\\r\n)\r\n\r\n#define PackTRXPOS(SSAX,SSAY,DSAX,DSAY,DIR)\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (SSAX)\t& M11 )\t<< 0\t|\t\\\r\n\t( (uint64) (SSAY)\t& M11 )\t<< 16\t|\t\\\r\n\t( (uint64) (DSAX)\t& M11 )\t<< 32\t|\t\\\r\n\t( (uint64) (DSAY)\t& M11 )\t<< 48\t|\t\\\r\n\t( (uint64) (DIR)\t& M02 )\t<< 59\t\t\\\r\n)\r\n\r\n#define PackTRXREG(RRW,RRH)\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (RRW)\t& M12 )\t<< 0\t|\t\\\r\n\t( (uint64) (RRH)\t& M12 )\t<< 32\t\t\\\r\n)\r\n\r\n#define PackUV(U,V)\t\t\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (U)\t\t& M14 )\t<< 0\t|\t\\\r\n\t( (uint64) (V)\t\t& M14 )\t<< 16\t\t\\\r\n)\r\n\r\n#define PackXYOFFSET(OFX,OFY)\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (OFX)\t& M16 )\t<< 0\t|\t\\\r\n\t( (uint64) (OFY)\t& M16 )\t<< 32\t\t\\\r\n)\r\n\r\n#define PackXYZ(X,Y,Z)\t\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (X)\t\t& M16 )\t<< 0\t|\t\\\r\n\t( (uint64) (Y)\t\t& M16 )\t<< 16\t|\t\\\r\n\t( (uint64) (Z)\t\t& M32 )\t<< 32\t\t\\\r\n)\r\n\r\n#define PackXYZF(X,Y,Z,F)\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (X)\t\t& M16 )\t<< 0\t|\t\\\r\n\t( (uint64) (Y)\t\t& M16 )\t<< 16\t|\t\\\r\n\t( (uint64) (Z)\t\t& M24 )\t<< 32\t|\t\\\r\n\t( (uint64) (F)\t\t& M08 )\t<< 56\t\t\\\r\n)\r\n\r\n#define PackZBUF(ZBP,PSM,ZMSK)\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (ZBP)\t& M09 )\t<< 0\t|\t\\\r\n\t( (uint64) (PSM)\t& M04 )\t<< 24\t|\t\\\r\n\t( (uint64) (ZMSK)\t& M01 )\t<< 32\t\t\\\r\n)\r\n\r\n\r\n//----------------------------------------------------------------------------------------\r\n//\t\tP R I V I L E G E D   R E G I S T E R   P A C K I N G   M A C R O S\r\n//----------------------------------------------------------------------------------------\r\n\r\n\r\n#define PackBGCOLOR(R,G,B)\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (R)\t\t& M08 )\t<< 0\t|\t\\\r\n\t( (uint64) (G)\t\t& M08 )\t<< 8\t|\t\\\r\n\t( (uint64) (B)\t\t& M08 )\t<< 16\t\t\\\r\n)\r\n\r\n#define PackBUSDIR(DIR)\t\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (DIR)\t& M01 )\t<< 0\t\t\\\r\n)\r\n\r\n#define PackCSR(SIGNAL,FINISH,HSINT,VSINT,FLUSH,RESET,NFIELD,FIELD,FIFO,REV,ID)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (SIGNAL)\t& M01 )\t<< 0\t|\t\\\r\n\t( (uint64) (FINISH)\t& M01 )\t<< 1\t|\t\\\r\n\t( (uint64) (HSINT)\t& M01 )\t<< 2\t|\t\\\r\n\t( (uint64) (VSINT)\t& M01 )\t<< 3\t|\t\\\r\n\t( (uint64) (FLUSH)\t& M01 )\t<< 8\t|\t\\\r\n\t( (uint64) (RESET)\t& M01 )\t<< 9\t|\t\\\r\n\t( (uint64) (NFIELD)\t& M01 )\t<< 12\t|\t\\\r\n\t( (uint64) (FIELD)\t& M01 )\t<< 13\t|\t\\\r\n\t( (uint64) (FIFO)\t& M02 )\t<< 14\t|\t\\\r\n\t( (uint64) (REV)\t& M08 )\t<< 16\t|\t\\\r\n\t( (uint64) (ID)\t\t& M08 )\t<< 24\t\t\\\r\n)\r\n\r\n#define PackDISPFB(FBP,FBW,PSM,DBX,DBY)\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (FBP)\t& M09 )\t<< 0\t|\t\\\r\n\t( (uint64) (FBW)\t& M06 )\t<< 9\t|\t\\\r\n\t( (uint64) (PSM)\t& M05 )\t<< 15\t|\t\\\r\n\t( (uint64) (DBX)\t& M11 )\t<< 32\t|\t\\\r\n\t( (uint64) (DBY)\t& M11 )\t<< 43\t\t\\\r\n)\r\n\r\n#define PackDISPLAY(DX,DY,MAGH,MAGV,DW,DH)\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (DX)\t\t& M12 )\t<< 0\t|\t\\\r\n\t( (uint64) (DY)\t\t& M11 )\t<< 12\t|\t\\\r\n\t( (uint64) (MAGH)\t& M04 )\t<< 23\t|\t\\\r\n\t( (uint64) (MAGV)\t& M02 )\t<< 27\t|\t\\\r\n\t( (uint64) (DW)\t\t& M12 )\t<< 32\t|\t\\\r\n\t( (uint64) (DH)\t\t& M11 )\t<< 44\t\t\\\r\n)\r\n\r\n#define PackEXTBUF(EXBP,EXBW,FBIN,WFFMD,EMODA,EMODC,WDX,WDY)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (EXBP)\t& M14 )\t<< 0\t|\t\\\r\n\t( (uint64) (EXBW)\t& M06 )\t<< 14\t|\t\\\r\n\t( (uint64) (FBIN)\t& M02 )\t<< 20\t|\t\\\r\n\t( (uint64) (WFFMD)\t& M01 )\t<< 22\t|\t\\\r\n\t( (uint64) (EMODA)\t& M02 )\t<< 23\t|\t\\\r\n\t( (uint64) (EMODC)\t& M02 )\t<< 25\t|\t\\\r\n\t( (uint64) (WDX)\t& M11 )\t<< 32\t|\t\\\r\n\t( (uint64) (WDY)\t& M11 )\t<< 43\t\t\\\r\n)\r\n\r\n#define PackEXTDATA(SX,SY,SMPH,SMPV,WW,WH)\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (SX)\t\t& M12 )\t<< 0\t|\t\\\r\n\t( (uint64) (SY)\t\t& M11 )\t<< 12\t|\t\\\r\n\t( (uint64) (SMPH)\t& M04 )\t<< 23\t|\t\\\r\n\t( (uint64) (SMPV)\t& M02 )\t<< 27\t|\t\\\r\n\t( (uint64) (WW)\t\t& M12 )\t<< 32\t|\t\\\r\n\t( (uint64) (WH)\t\t& M11 )\t<< 44\t\t\\\r\n)\r\n\r\n#define PackEXTWRITE(WRITE)\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (WRITE)\t& M01 )\t<< 0\t\t\\\r\n)\r\n\r\n#define PackIMR(SIGMSK,FINISHMSK,HSMSK,VSMSK)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (SIGMSK)\t& M01 )\t<< 8\t|\t\\\r\n\t( (uint64) (FINISHMSK)& M01)<< 9\t|\t\\\r\n\t( (uint64) (HSMSK)\t& M01 )\t<< 10\t|\t\\\r\n\t( (uint64) (VSMSK)\t& M01 )\t<< 11\t|\t\\\r\n\t( (uint64)            M04 ) << 12\t\t\\\r\n)\r\n\r\n#define PackPMODE(EN1,EN2,CRTMD,MMOD,AMOD,SLBG,ALP)\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (EN1)\t& M01 )\t<< 0\t|\t\\\r\n\t( (uint64) (EN2)\t& M01 )\t<< 1\t|\t\\\r\n\t( (uint64) (CRTMOD)\t& M03 )\t<< 2\t|\t\\\r\n\t( (uint64) (MMOD)\t& M01 )\t<< 5\t|\t\\\r\n\t( (uint64) (AMOD)\t& M01 )\t<< 6\t|\t\\\r\n\t( (uint64) (SLBG)\t& M01 )\t<< 7\t|\t\\\r\n\t( (uint64) (ALP)\t& M08 )\t<< 8\t\t\\\r\n)\r\n\r\n#define PackSIGLBLID(SIGID,LBLID)\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (SIGID)\t& M32 )\t<< 0\t|\t\\\r\n\t( (uint64) (LBLID)\t& M32 )\t<< 32\t\t\\\r\n)\r\n\r\n#define PackSMODE2(INT,FFMD,DPMS)\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t( (uint64) (INT)\t& M01 )\t<< 0\t|\t\\\r\n\t( (uint64) (FFMD)\t& M01 )\t<< 1\t|\t\\\r\n\t( (uint64) (DPMS)\t& M02 )\t<< 2\t\t\\\r\n)\r\n\r\n\r\n\r\n\r\n//------------------------------------------------------\r\n//\t\tR E G I S T E R   F I E L D   V A L U E S\r\n//------------------------------------------------------\r\n\r\n\r\n// drawing primitives\r\n#define\tPOINT\t\t0\r\n#define\tLINE\t\t1\r\n#define\tLINESTRIP\t2\r\n#define\tTRIANGLE\t3\r\n#define\tTRISTRIP\t4\r\n#define\tTRIFAN\t\t5\r\n#define\tSPRITE\t\t6\r\n\r\n// PRIM bit masks   (GS Manual p. 116)\r\n#define\tIIP\t\t\t(1<<3)\t\t// Gouraud Shading\r\n#define\tTME\t\t\t(1<<4)\t\t// Texture Mapping\r\n#define\tFGE\t\t\t(1<<5)\t\t// Fogging\r\n#define\tABE\t\t\t(1<<6)\t\t// Alpha Blending\r\n#define\tAA1\t\t\t(1<<7)\t\t// Pass 1 Antialiasing\r\n#define\tFST\t\t\t(1<<8)\t\t// UV values used (UV Register)\r\n#define\tCTXT\t\t(1<<9)\t\t// Context 2 used\r\n#define\tFIX\t\t\t(1<<10)\t\t// Fixed Fragment Value Control\r\n\r\n// pixel storage modes\r\n#define PSMCT32\t\t0x00\r\n#define PSMCT24\t\t0x01\r\n#define PSMCT16\t\t0x02\r\n#define PSMCT16S\t0x0A\r\n#define PS_GPU24\t0x12\r\n#define PSMT8\t\t0x13\r\n#define PSMT4\t\t0x14\r\n#define PSMT8H\t\t0x1B\r\n#define PSMT4HL\t\t0x24\r\n#define PSMT4HH\t\t0x2C\r\n#define PSMZ32\t\t0x30\r\n#define PSMZ24\t\t0x31\r\n#define PSMZ16\t\t0x32\r\n#define PSMZ16S\t\t0x3A\r\n\r\n// depth test methods\r\n#define ZNEVER\t\t0\r\n#define ZALWAYS\t\t1\r\n#define ZGEQUAL\t\t2\r\n#define ZGREATER\t3\r\n\r\n// alpha test methods\r\n#define\tANEVER\t\t0\r\n#define\tAALWAYS\t\t1\r\n#define ALESS\t\t2\r\n#define ALEQUAL\t\t3\r\n#define\tAEQUAL\t\t4\r\n#define\tAGEQUAL\t\t5\r\n#define\tAGREATER\t6\r\n#define\tANOTEQUAL\t7\r\n\r\n// alpha fail processing\r\n#define\tKEEP\t\t0\r\n#define\tFB_ONLY\t\t1\r\n#define\tZB_ONLY\t\t2\r\n#define\tRGB_ONLY\t3\r\n\r\n// texture functions\r\n#define MODULATE\t0\r\n#define DECAL\t\t1\r\n#define HIGHLIGHT\t2\r\n#define HIGHLIGHT2\t3\r\n\r\n// texture filters\r\n#define NEAREST\t\t\t\t\t0\r\n#define LINEAR\t\t\t\t\t1\r\n#define NEAREST_MIPMAP_NEAREST\t2\r\n#define NEAREST_MIPMAP_LINEAR\t3\r\n#define LINEAR_MIPMAP_NEAREST\t4\r\n#define LINEAR_MIPMAP_LINEAR\t5\r\n\r\n// texture wrap modes\r\n#define REPEAT\t\t\t0\r\n#define CLAMP\t\t\t1\r\n#define REGION_CLAMP\t2\r\n#define REGION_REPEAT\t3\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nclass gs\r\n{\r\n\r\npublic:\r\n\r\n\tenum eReg\r\n\t{\r\n\t\tPRIM\t\t= 0x00,\t\t// GS p. 116  Drawing Primitive Setting (AC == 1)\r\n\t\tRGBAQ\t\t= 0x01,\t\t// GS p. 119  Vertex Color Setting\r\n\t\tST\t\t\t= 0x02,\t\t// GS p. 123  Specification of Vertex Texture Coordinates (sets S and T)  FST == 0\r\n\t\tUV\t\t\t= 0x03,\t\t// GS p. 135  Specification of Vertex Texture Coordinates (sets U and V)  FST == 1\r\n\t\tXYZF2\t\t= 0x04,\t\t// GS p. 139  Setting for Vertex Coordinate Values (Fog coefficient)\r\n\t\tXYZ2\t\t= 0x05,\t\t// GS p. 137  Setting for Vertex Coordinate Values\r\n\t\tTEX0_1\t\t= 0x06,\t\t// GS p. 125  Texture Information Setting (type of textures to be used)\r\n\t\tTEX0_2\t\t= 0x07,\t\t//            (mode, dimensions, blendfunc, CLUT)\r\n\t\tCLAMP_1\t\t= 0x08,\t\t// GS p. 102  Texture wrap mode\r\n\t\tCLAMP_2\t\t= 0x09,\r\n\t\tFOG\t\t\t= 0x0A,\t\t// GS p. 108  Vertex Fog Value Setting (per vert)\r\n\t\tXYZF3\t\t= 0x0C,\t\t// GS p. 140  Setting for Vertex Coordinate Values (without Drawing Kick) (Fog coefficient)\r\n\t\tXYZ3\t\t= 0x0D,\t\t// GS p. 138  Setting for Vertex Coordinate Values (without Drawing Kick)\r\n\t\tA_D\t\t\t= 0x0E,\t\t// Undocumented???\r\n\t\tNOP\t\t\t= 0x0F,\r\n\t\tTEX1_1\t\t= 0x14,\t\t// GS p. 127  Texture Information Setting (LOD info)\r\n\t\tTEX1_2\t\t= 0x15,\r\n\t\tTEX2_1\t\t= 0x16,\t\t// GS p. 128  Texture Information Setting (Format/CLUT)\r\n\t\tTEX2_2\t\t= 0x17,\r\n\t\tXYOFFSET_1\t= 0x18,\t\t// GS p. 136  Offset Value setting (prim to window coords)\r\n\t\tXYOFFSET_2\t= 0x19,\r\n\t\tPRMODECONT\t= 0x1A,\t\t// GS p. 118  Specification of Primitive Attribute Setting Method\r\n\t\tPRMODE\t\t= 0x1B,\t\t// GS p. 117  Setting for Attributes of Drawing Primitives (AC == 0)\r\n\t\tTEXCLUT\t\t= 0x1C,\t\t// GS p. 130  CLUT Position Specification (CLUT offset in buffer)\r\n\t\tSCANMSK\t\t= 0x22,\t\t// GS p. 120  Raster Address Mask Setting\r\n\t\tMIPTBP1_1\t= 0x34,\t\t// GS p. 113  MIPMAP Information Setting (Level 1 to 3)\r\n\t\tMIPTBP1_2\t= 0x35,\r\n\t\tMIPTBP2_1\t= 0x36,\t\t// GS p. 114  MIPMAP Information Setting (Level 4 to 6)\r\n\t\tMIPTBP2_2\t= 0x37,\r\n\t\tTEXA\t\t= 0x3B,\t\t// GS p. 129  Texture Alpha Value Setting (sets alpha when alpha not 8-bit)\r\n\t\tFOGCOL\t\t= 0x3D,\t\t// GS p. 109  Distant Fog Color Setting\r\n\t\tTEXFLUSH\t= 0x3F,\t\t// GS p. 131  Texture Page Buffer Disabling (wait for drawing to complete)\r\n\t\tSCISSOR_1\t= 0x40,\t\t// GS p. 121  Setting for Scissoring Area\r\n\t\tSCISSOR_2\t= 0x41,\r\n\t\tALPHA_1\t\t= 0x42,\t\t// GS p. 100  Alpha Blending Setting (Context 1)\r\n\t\tALPHA_2\t\t= 0x43,\r\n\t\tDIMX\t\t= 0x44,\t\t// GS p. 104  Dither Matrix Setting\r\n\t\tDTHE\t\t= 0x45,\t\t// GS p. 105  Dither Control (0 off / 1 on)\r\n\t\tCOLCLAMP\t= 0x46,\t\t// GS p. 103  Color Clamp Control  (0 mask / 1 clamp)\r\n\t\tTEST_1\t\t= 0x47,\t\t// GS p. 124  Pixel Test Control (Alpha test/Depth Test method and enable/disable, etc.)\r\n\t\tTEST_2\t\t= 0x48,\r\n\t\tPABE\t\t= 0x49,\t\t// GS p. 115  Alpha Blending Control in Units of Pixels\r\n\t\tFBA_1\t\t= 0x4A,\t\t// GS p. 106  Alpha Correction Value  (Sets fixed alpha value)\r\n\t\tFBA_2\t\t= 0x4B,\r\n\t\tFRAME_1\t\t= 0x4C,\t\t// GS p. 110  Frame Buffer Setting\r\n\t\tFRAME_2\t\t= 0x4D,\r\n\t\tZBUF_1\t\t= 0x4E,\t\t// GS p. 141  Z Buffer Setting\r\n\t\tZBUF_2\t\t= 0x4F,\r\n\t\tBITBLTBUF\t= 0x50,\t\t// GS p. 101  Setting for transmission between buffers\r\n\t\tTRXPOS\t\t= 0x51,\t\t// GS p. 133  Specification of Transmission Areas in Buffers (direction)\r\n\t\tTRXREG\t\t= 0x52,\t\t// GS p. 134  Specification of Transmission Areas in Buffers\r\n\t\tTRXDIR\t\t= 0x53,\t\t// GS p. 132  Activation of Transmission between Buffers\r\n\t\tHWREG\t\t= 0x54,\t\t// GS p. 111  Data Port for Transmission between Buffers\r\n\t\tSIGNAL\t\t= 0x60,\t\t// GS p. 122  SIGNAL Event Occurrence Request\r\n\t\tFINISH\t\t= 0x61,\t\t// GS p. 107  Finish Event Occurance Request\r\n\t\tLABEL\t\t= 0x62,\t\t// GS p. 112  LABEL Event Occurrence Request\r\n\t\tA_D_NOP\t\t= 0x7F\t\t// Undocumented???\r\n\t};\r\n\r\n\tstatic void BeginPrim(uint FLG, uint Prim, uint Pre);\r\n\tstatic void EndPrim(uint Eop);\r\n\tstatic void Reg1(eReg Reg, uint64 Data);\r\n\tstatic void Reg2(eReg Reg, uint64 Data);\r\n\tstatic uint32 *gs::Reg2_pData(eReg Reg, uint64 Data);\r\n\tstatic void ModifyTBP(eReg Reg, uint32 *p_reg_ptr, sint16 tbp1, sint16 tbp2 = -1, sint16 tbp3 = -1);\r\n\r\n}; // class gs\r\n\r\n\r\n\r\n// output 1 GS register via PATH1, V3_32 format\r\ninline void gs::Reg1(eReg Reg, uint64 Data)\r\n{\r\n//\tdma::Store64(Data);\r\n//\tdma::Store32((uint64)Reg);\r\n\tuint32 *p_loc = (uint32*)dma::pLoc;\r\n\tp_loc[0] = (uint32)Data;\r\n\tp_loc[1] = Data>>32;\r\n\tp_loc[2] = Reg;\r\n\tdma::pLoc = (uint8*) (p_loc + 3);\r\n\r\n}\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n\r\n\r\n\r\n#endif // __GS_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/immediate.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       immediate.cpp\r\n//* OWNER:          Garrett Jost\r\n//* CREATION DATE:  7/19/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n#include \"gfx/ngps/nx/sprite.h\"\r\n#include \"gfx/ngps/nx/switches.h\"\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nuint64 CImmediateMode::sGetTextureBlend( uint32 blend_checksum, int fix )\r\n{\r\n\tuint64 rv = PackALPHA(0,0,0,0,0);\r\n\tswitch ( blend_checksum )\r\n\t{\r\n\t\tcase 0x54628ed7:\t\t// Blend\r\n\t\t\trv = PackALPHA(0,1,0,1,0);\r\n\t\t\tbreak;\r\n\t\tcase 0x02e58c18:\t\t// Add\r\n\t\t\trv = PackALPHA(0,2,0,1,0);\r\n\t\t\tbreak;\r\n\t\tcase 0xa7fd7d23:\t\t// Sub\r\n\t\tcase 0xdea7e576:\t\t// Subtract\r\n\t\t\trv = PackALPHA(2,0,0,1,0);\r\n\t\t\tbreak;\r\n\t\tcase 0x40f44b8a:\t\t// Modulate\r\n\t\t\trv = PackALPHA(1,2,0,2,0);\r\n\t\t\tbreak;\r\n\t\tcase 0x68e77f40:\t\t// Brighten\r\n\t\t\trv = PackALPHA(1,2,0,1,0);\r\n\t\t\tbreak;\r\n\t\tcase 0x18b98905:\t\t// FixBlend\r\n\t\t\trv = PackALPHA(0,1,2,1,fix);\r\n\t\t\tbreak;\r\n\t\tcase 0xa86285a1:\t\t// FixAdd\r\n\t\t\trv = PackALPHA(0,2,2,1,fix);\r\n\t\t\tbreak;\r\n\t\tcase 0x0d7a749a:\t\t// FixSub\r\n\t\tcase 0x0eea99ff:\t\t// FixSubtract\r\n\t\t\trv = PackALPHA(2,0,2,1,fix);\r\n\t\t\tbreak;\r\n\t\tcase 0x90b93703:\t\t// FixModulate\r\n\t\t\trv = PackALPHA(1,2,2,2,fix);\r\n\t\t\tbreak;\r\n\t\tcase 0xb8aa03c9:\t\t// FixBrighten\r\n\t\t\trv = PackALPHA(1,2,2,1,fix);\r\n\t\t\tbreak;\r\n\t\tcase 0x515e298e:\t\t// Diffuse\r\n\t\tcase 0x806fff30:\t\t// None\r\n\t\t\trv = PackALPHA(0,0,0,0,0);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Illegal blend mode specified. Please use (fix)blend/add/sub/modulate/brighten or diffuse/none.\"));\r\n\t\t\tbreak;\r\n\t}\r\n\treturn rv;\r\n}\r\n\r\nvoid CImmediateMode::sViewportInit()\r\n{\r\n\t// start a cnt tag\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tvif::STROW((int)render::RowRegI[0], (int)render::RowRegI[1], (int)render::RowRegI[2], (int)render::RowRegI[3]);\r\n\r\n\t// VU context, uploading the view transform data\r\n\tvu1::BeginPrim(ABS, VU1_ADDR(L_VF09));\t  \t\t\t\t// Begin packed register upload to VF10 \r\n\tvu1::StoreVec(*(Vec *)&render::AltFrustum);\t\t\t\t// VF09\r\n\tvu1::StoreVec(*(Vec *)&render::InverseViewportScale);\t// VF10\r\n\tvu1::StoreVec(*(Vec *)&render::InverseViewportOffset);\t// VF11\r\n//\tvu1::StoreMat(*(Mat *)&render::AdjustedWorldToFrustum);\t// VF12-15\r\n\tvu1::StoreMat(*(Mat *)&render::AdjustedWorldToViewport);// VF12-15\r\n\tvu1::EndPrim(0);\t\t\t\t\t\t\t\t\t\t// End upload\r\n\r\n\t// GS context\r\n\tgs::BeginPrim(ABS,0,0);\r\n\tgs::Reg1(gs::CLAMP_1,\t\tPackCLAMP(CLAMP,CLAMP,0,0,0,0));\t\t// may want to make REPEAT an option\r\n\tgs::Reg1(gs::FRAME_1,\t\tPackFRAME(FRAME_START,HRES/64,PSMCT32,0xFF000000));\r\n\tgs::Reg1(gs::SCISSOR_1,\t\trender::reg_SCISSOR);\r\n\tgs::Reg1(gs::XYOFFSET_1,\trender::reg_XYOFFSET);\r\n\tgs::Reg1(gs::TEST_1, \t\tPackTEST(0,0,0,0,0,0,1,ZGEQUAL));\r\n\tgs::Reg1(gs::COLCLAMP,\t\tPackCOLCLAMP(1));\r\n\tgs::Reg1(gs::ZBUF_1,\t\tPackZBUF(ZBUFFER_START,PSMZ24,1));\r\n\tgs::EndPrim(0);\r\n\r\n\t// end the dma tag\r\n\tdma::EndTag();\r\n}\r\n\r\nvoid CImmediateMode::sTextureGroupInit(uint unpackFLG)\r\n{\r\n\tvif::STROW((int)render::RowRegI[0], (int)render::RowRegI[1], (int)render::RowRegI[2], (int)render::RowRegI[3]);\r\n\r\n\t// VU context, uploading the view transform data\r\n\tvu1::BeginPrim(unpackFLG, VU1_ADDR(L_VF10));\t  \t\t\t\t// Begin packed register upload to VF10 \r\n\tvu1::StoreVec(*(Vec *)&render::InverseViewportScale);\t// VF10\r\n\tvu1::StoreVec(*(Vec *)&render::InverseViewportOffset);\t// VF11\r\n//\tvu1::StoreMat(*(Mat *)&render::AdjustedWorldToFrustum);\t// VF12-15\r\n\tvu1::StoreMat(*(Mat *)&render::AdjustedWorldToViewport);// VF12-15\r\n\tvu1::EndPrim(0);\t\t\t\t\t\t\t\t\t\t// End upload\r\n}\r\n\r\nvoid CImmediateMode::sSetZPush(float zpush)\r\n{\r\n\tMth::Matrix localToViewport(render::AdjustedWorldToViewport);\r\n\tlocalToViewport[0][2] += localToViewport[0][3] * zpush * 64.0f;\r\n\tlocalToViewport[1][2] += localToViewport[1][3] * zpush * 64.0f;\r\n\tlocalToViewport[2][2] += localToViewport[2][3] * zpush * 64.0f;\r\n\tlocalToViewport[3][2] += localToViewport[3][3] * zpush * 64.0f;\r\n\r\n\t// VU context, uploading the view transform data\r\n\tvu1::BeginPrim(ABS, VU1_ADDR(L_VF12));\t  \t\t\t\t// Begin packed register upload to VF12 \r\n\tvu1::StoreMat(*(Mat *)&localToViewport);\t\t\t\t// VF12-15\r\n\tvu1::EndPrim(0);\t\t\t\t\t\t\t\t\t\t// End upload\r\n}\r\n\r\nvoid CImmediateMode::sClearZPush()\r\n{\r\n\t// VU context, uploading the view transform data\r\n\tvu1::BeginPrim(ABS, VU1_ADDR(L_VF12));\t  \t\t\t\t// Begin packed register upload to VF12 \r\n\tvu1::StoreMat(*(Mat *)&render::AdjustedWorldToViewport);// VF12-15\r\n\tvu1::EndPrim(0);\t\t\t\t\t\t\t\t\t\t// End upload\r\n}\r\n\r\nvoid CImmediateMode::sStartPolyDraw( SSingleTexture * p_engine_texture, uint64 blend, uint unpackFLG, bool clip )\r\n{\r\n\t// GS context\r\n\tgs::BeginPrim(unpackFLG,0,0);\r\n\tgs::Reg1(gs::ALPHA_1,\t\tblend);\r\n\r\n\tif ( p_engine_texture )\r\n\t{\r\n\t\tgs::Reg1(gs::TEX0_1,\tp_engine_texture->m_RegTEX0);\r\n\t\tgs::Reg1(gs::TEX1_1,\tp_engine_texture->m_RegTEX1);\r\n\t}\r\n\tgs::EndPrim(0);\r\n\r\n\t// Set render flags.\r\n\tvif::ITOP(clip ? CLIP : CULL);\r\n}\r\n\r\n//\r\n// Starts a poly draw with pre-packed texture registers (probably stolen from some other dma list)\r\n//\r\nvoid CImmediateMode::sStartPolyDraw( uint32 * p_packed_texture_regs, int num_texture_regs, uint unpackFLG, bool clip )\r\n{\r\n\t// GS context\r\n\tif (p_packed_texture_regs)\r\n\t{\r\n\t\tgs::BeginPrim(unpackFLG,0,0);\r\n\t\tfor (int i = 0; i < num_texture_regs; i++)\r\n\t\t{\r\n\t\t\tNxPs2::dma::Store32(*(p_packed_texture_regs++));\r\n\t\t\tNxPs2::dma::Store32(*(p_packed_texture_regs++));\r\n\t\t\tNxPs2::dma::Store32(*(p_packed_texture_regs++));\r\n\t\t}\r\n\t\tgs::EndPrim(0);\r\n\t}\r\n\r\n\t// Set render flags.\r\n\tvif::ITOP(clip ? CLIP : CULL);\r\n}\r\n\r\nvoid CImmediateMode::sDrawQuadTexture( SSingleTexture * p_engine_texture, const Mth::Vector& vert0, const Mth::Vector& vert1,\r\n\t\t\t\t\t\t\t\t\t   const Mth::Vector& vert2, const Mth::Vector& vert3,\r\n\t\t\t\t\t\t\t\t\t   uint32 col0, uint32 col1, uint32 col2, uint32 col3 )\r\n{\r\n\t// begin a batch of vertices\r\n\t// Note: UV must always be 1st, Pos must always be last.\r\n\tif ( p_engine_texture )\r\n\t{\r\n\t\t//BeginModelPrim(gs::XYZ2<<8|gs::RGBAQ<<4|gs::UV, 3, TRISTRIP|IIP|ABE|TME|FST, 1, VU1_ADDR(Proj));\r\n\t\tvif::STCYCL(1,3);\r\n\t\tvif::UNPACK(0,V4_32,1,ABS,UNSIGNED,0);\r\n\t\tgif::BeginTag1(gs::XYZF2<<8|gs::RGBAQ<<4|gs::UV, 3, PACKED, TRISTRIP|IIP|ABE|TME|FST, 1, VU1_ADDR(Proj));\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//BeginModelPrim(gs::XYZ2<<4|gs::RGBAQ, 2, TRISTRIP|IIP|ABE, 1, VU1_ADDR(Proj));\r\n\t\tvif::STCYCL(1,2);\r\n\t\tvif::UNPACK(0,V4_32,1,ABS,UNSIGNED,0);\r\n\t\tgif::BeginTag1(gs::XYZF2<<4|gs::RGBAQ, 2, PACKED, TRISTRIP|IIP|ABE, 1, VU1_ADDR(Proj));\r\n\t}\r\n\r\n\tint loc = 1;\r\n\r\n\tif ( p_engine_texture )\r\n\t{\r\n\t\tint u = p_engine_texture->GetWidth() << 4;\r\n\t\tint v = p_engine_texture->GetHeight() << 4;\r\n\r\n\t\tvif::BeginUNPACK(0, V2_16, ABS, UNSIGNED, loc);\r\n\t\tvif::StoreV2_16(0,0);\r\n\t\tvif::StoreV2_16(u,0);\r\n\t\tvif::StoreV2_16(0,v);\r\n\t\tvif::StoreV2_16(u,v);\r\n\t\tvif::EndUNPACK();\r\n\t\tloc++;\r\n\t}\r\n\r\n\tvif::BeginUNPACK(0, V4_8, ABS, UNSIGNED, loc);\r\n\tvif::StoreS_32(col0);\r\n\tvif::StoreS_32(col1);\r\n\tvif::StoreS_32(col3);\r\n\tvif::StoreS_32(col2);\r\n\tvif::EndUNPACK();\r\n\tloc++;\r\n\r\n\tvif::STMOD(OFFSET_MODE);\r\n\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, loc);\r\n\tvif::StoreV4_32((sint32)(vert0[X]*SUB_INCH_PRECISION), (sint32)(vert0[Y]*SUB_INCH_PRECISION), (sint32)(vert0[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert1[X]*SUB_INCH_PRECISION), (sint32)(vert1[Y]*SUB_INCH_PRECISION), (sint32)(vert1[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert3[X]*SUB_INCH_PRECISION), (sint32)(vert3[Y]*SUB_INCH_PRECISION), (sint32)(vert3[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert2[X]*SUB_INCH_PRECISION), (sint32)(vert2[Y]*SUB_INCH_PRECISION), (sint32)(vert2[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::EndUNPACK();\r\n\tloc++;\r\n\tvif::STMOD(NORMAL_MODE);\r\n\r\n\t// finish batch of vertices\r\n\t//EndModelMultiPrim();\r\n\tgif::EndTag1(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n}\r\n\r\nvoid CImmediateMode::sDrawTri( const Mth::Vector& vert0, const Mth::Vector& vert1, const Mth::Vector& vert2,\r\n\t\t\t\t\t\t\t   uint32 col0, uint32 col1, uint32 col2, uint unpackFLG )\r\n{\r\n\t// begin a batch of vertices\r\n\t// Note: ST must always be 1st, Pos must always be last.\r\n\t//BeginModelPrim(gs::XYZ2<<4|gs::RGBAQ, 2, TRISTRIP|IIP|ABE, 1, VU1_ADDR(Proj));\r\n\tvif::STCYCL(1,2);\r\n\tvif::UNPACK(0,V4_32,1,unpackFLG,UNSIGNED,0);\r\n\tgif::BeginTag1(gs::XYZF2<<4|gs::RGBAQ, 2, PACKED, TRISTRIP|IIP|ABE, 1, VU1_ADDR(Proj));\r\n\r\n\tint loc = 1;\r\n\r\n\tvif::BeginUNPACK(0, V4_8, unpackFLG, UNSIGNED, loc);\r\n\tvif::StoreS_32(col0);\r\n\tvif::StoreS_32(col1);\r\n\tvif::StoreS_32(col2);\r\n\tvif::EndUNPACK();\r\n\tloc++;\r\n\r\n\tvif::STMOD(OFFSET_MODE);\r\n\tvif::BeginUNPACK(0, V4_32, unpackFLG, SIGNED, loc);\r\n\tvif::StoreV4_32((sint32)(vert0[X]*SUB_INCH_PRECISION), (sint32)(vert0[Y]*SUB_INCH_PRECISION), (sint32)(vert0[Z]*SUB_INCH_PRECISION), 0xC000);\r\n\tvif::StoreV4_32((sint32)(vert1[X]*SUB_INCH_PRECISION), (sint32)(vert1[Y]*SUB_INCH_PRECISION), (sint32)(vert1[Z]*SUB_INCH_PRECISION), 0xC000);\r\n\tvif::StoreV4_32((sint32)(vert2[X]*SUB_INCH_PRECISION), (sint32)(vert2[Y]*SUB_INCH_PRECISION), (sint32)(vert2[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::EndUNPACK();\r\n\tvif::STMOD(NORMAL_MODE);\r\n\tloc++;\r\n\r\n\t// finish batch of vertices\r\n\t//EndModelMultiPrim();\r\n\t//EndModelPrim(1);\r\n\tgif::EndTag1(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n}\r\n\r\nvoid CImmediateMode::sDrawTriUV( const Mth::Vector& vert0, const Mth::Vector& vert1, const Mth::Vector& vert2,\r\n\t\t\t\t\t\t\t\t float u0, float v0, float u1, float v1, float u2, float v2,\r\n\t\t\t\t\t\t\t\t uint32 col0, uint32 col1, uint32 col2, uint unpackFLG )\r\n{\r\n\t// dummy gs context\r\n\tgs::BeginPrim(unpackFLG,0,0);\r\n\tgs::Reg1(gs::A_D_NOP, 0);\r\n\tgs::EndPrim(0);\r\n\r\n\t// gif tag\r\n\tvif::UNPACK(0,V4_32,1,unpackFLG,UNSIGNED,0);\r\n\tgif::BeginTag1(gs::XYZF2<<8|gs::RGBAQ<<4|gs::ST, 3, PACKED, TRISTRIP|IIP|ABE|TME, 1, VU1_ADDR(PTex) | (0x6 << 11) /* turns off UV correction */);\r\n\r\n\t// each vertex has 3 elements\r\n\tvif::STCYCL(1,3);\r\n\r\n\t// ST\r\n\tvif::UNPACK(0, V2_32, 3, unpackFLG, UNSIGNED, 1);\r\n\tvif::StoreV2_32((sint32) (u0 * 4096.0f), (sint32) (v0 * 4096.0f));\r\n\tvif::StoreV2_32((sint32) (u1 * 4096.0f), (sint32) (v1 * 4096.0f));\r\n\tvif::StoreV2_32((sint32) (u2 * 4096.0f), (sint32) (v2 * 4096.0f));\r\n\r\n\t// RGBA\r\n\tvif::UNPACK(0, V4_8, 3, unpackFLG, UNSIGNED, 2);\r\n\tvif::StoreS_32(col0);\r\n\tvif::StoreS_32(col1);\r\n\tvif::StoreS_32(col2);\r\n\r\n\t// XYZ\r\n\tvif::STMOD(OFFSET_MODE);\r\n\tvif::UNPACK(0, V4_32, 3, unpackFLG, SIGNED, 3);\r\n\tvif::StoreV4_32((sint32)(vert0[X]*SUB_INCH_PRECISION), (sint32)(vert0[Y]*SUB_INCH_PRECISION), (sint32)(vert0[Z]*SUB_INCH_PRECISION), 0xC000);\r\n\tvif::StoreV4_32((sint32)(vert1[X]*SUB_INCH_PRECISION), (sint32)(vert1[Y]*SUB_INCH_PRECISION), (sint32)(vert1[Z]*SUB_INCH_PRECISION), 0xC000);\r\n\tvif::StoreV4_32((sint32)(vert2[X]*SUB_INCH_PRECISION), (sint32)(vert2[Y]*SUB_INCH_PRECISION), (sint32)(vert2[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::STMOD(NORMAL_MODE);\r\n\r\n\t// finish batch of vertices\r\n\tgif::EndTag1(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n}\r\n\r\nvoid CImmediateMode::sDraw5QuadTexture( SSingleTexture * p_engine_texture, const Mth::Vector& vert0, const Mth::Vector& vert1,\r\n\t\t\t\t\t\t\t\t\t    const Mth::Vector& vert2, const Mth::Vector& vert3, const Mth::Vector& vert4,\r\n\t\t\t\t\t\t\t\t\t    uint32 col0, uint32 col1 )\r\n{\r\n\t// begin a batch of vertices\r\n\t// Note: UV must always be 1st, Pos must always be last.\r\n\tif ( p_engine_texture )\r\n\t{\r\n\t\t//BeginModelPrim(gs::XYZ2<<8|gs::RGBAQ<<4|gs::UV, 3, TRISTRIP|IIP|ABE|TME|FST, 1, VU1_ADDR(Proj));\r\n\t\tvif::STCYCL(1,3);\r\n\t\tvif::UNPACK(0,V4_32,1,ABS,UNSIGNED,0);\r\n\t\tgif::BeginTag1(gs::XYZF2<<8|gs::RGBAQ<<4|gs::ST, 3, PACKED, TRISTRIP|IIP|ABE|TME|FST, 1, VU1_ADDR(Proj));\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//BeginModelPrim(gs::XYZ2<<4|gs::RGBAQ, 2, TRIFAN|IIP|ABE, 1, VU1_ADDR(Proj));\r\n\t\tvif::STCYCL(1,2);\r\n\t\tvif::UNPACK(0,V4_32,1,ABS,UNSIGNED,0);\r\n\t\tgif::BeginTag1(gs::XYZF2<<4|gs::RGBAQ, 2, PACKED, TRIFAN|IIP|ABE, 1, VU1_ADDR(Proj));\r\n\t}\r\n\r\n\tint loc = 1;\r\n\r\n\tif ( p_engine_texture )\r\n\t{\r\n\t\tint u = p_engine_texture->GetWidth() << 4;\r\n\t\tint v = p_engine_texture->GetHeight() << 4;\r\n\r\n\t\tvif::BeginUNPACK(0, V2_16, ABS, UNSIGNED, loc);\r\n\t\tvif::StoreV2_16(u>>1,v>>1);\r\n\t\tvif::StoreV2_16(0,0);\r\n\t\tvif::StoreV2_16(u,0);\r\n\t\tvif::StoreV2_16(0,v);\r\n\t\tvif::StoreV2_16(u,v);\r\n\t\tvif::StoreV2_16(0,0);\r\n\t\tvif::EndUNPACK();\r\n\t\tloc++;\r\n\t}\r\n\r\n\tvif::BeginUNPACK(0, V4_8, ABS, UNSIGNED, loc);\r\n\tvif::StoreS_32(col0);\r\n\tvif::StoreS_32(col1);\r\n\tvif::StoreS_32(col1);\r\n\tvif::StoreS_32(col1);\r\n\tvif::StoreS_32(col1);\r\n\tvif::StoreS_32(col1);\r\n\tvif::EndUNPACK();\r\n\tloc++;\r\n\r\n\tvif::STMOD(OFFSET_MODE);\r\n\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, loc);\r\n\tvif::StoreV4_32((sint32)(vert0[X]*SUB_INCH_PRECISION), (sint32)(vert0[Y]*SUB_INCH_PRECISION), (sint32)(vert0[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert1[X]*SUB_INCH_PRECISION), (sint32)(vert1[Y]*SUB_INCH_PRECISION), (sint32)(vert1[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert2[X]*SUB_INCH_PRECISION), (sint32)(vert2[Y]*SUB_INCH_PRECISION), (sint32)(vert2[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert3[X]*SUB_INCH_PRECISION), (sint32)(vert3[Y]*SUB_INCH_PRECISION), (sint32)(vert3[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert4[X]*SUB_INCH_PRECISION), (sint32)(vert4[Y]*SUB_INCH_PRECISION), (sint32)(vert4[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert1[X]*SUB_INCH_PRECISION), (sint32)(vert1[Y]*SUB_INCH_PRECISION), (sint32)(vert1[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::EndUNPACK();\r\n\tloc++;\r\n\tvif::STMOD(NORMAL_MODE);\r\n\r\n\t// finish batch of vertices\r\n\t//EndModelMultiPrim();\r\n\tgif::EndTag1(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n}\r\n\r\nvoid CImmediateMode::sDrawGlowSegment( const Mth::Vector& vert0, const Mth::Vector& vert1,\r\n\t\t\t\t\t\t\t\t\t   const Mth::Vector& vert2, const Mth::Vector& vert3, const Mth::Vector& vert4,\r\n\t\t\t\t\t\t\t\t\t   uint32 col0, uint32 col1, uint32 col2 )\r\n{\r\n\t// begin a batch of vertices\r\n\t// Note: UV must always be 1st, Pos must always be last.\r\n\t//BeginModelPrim(gs::XYZ2<<4|gs::RGBAQ, 2, TRISTRIP|IIP|ABE, 1, VU1_ADDR(Proj));\r\n\tvif::STCYCL(1,2);\r\n\tvif::UNPACK(0,V4_32,1,ABS,UNSIGNED,0);\r\n\tgif::BeginTag1(gs::XYZF2<<4|gs::RGBAQ, 2, PACKED, TRISTRIP|IIP|ABE, 1, VU1_ADDR(Proj));\r\n\r\n\tint loc = 1;\r\n\r\n\tvif::BeginUNPACK(0, V4_8, ABS, UNSIGNED, loc);\r\n\tvif::StoreS_32(col0);\r\n\tvif::StoreS_32(col1);\r\n\tvif::StoreS_32(col1);\r\n\tvif::StoreS_32(col2);\r\n\tvif::StoreS_32(col2);\r\n\tvif::EndUNPACK();\r\n\tloc++;\r\n\r\n\tvif::STMOD(OFFSET_MODE);\r\n\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, loc);\r\n\tvif::StoreV4_32((sint32)(vert0[X]*SUB_INCH_PRECISION), (sint32)(vert0[Y]*SUB_INCH_PRECISION), (sint32)(vert0[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert1[X]*SUB_INCH_PRECISION), (sint32)(vert1[Y]*SUB_INCH_PRECISION), (sint32)(vert1[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert2[X]*SUB_INCH_PRECISION), (sint32)(vert2[Y]*SUB_INCH_PRECISION), (sint32)(vert2[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert3[X]*SUB_INCH_PRECISION), (sint32)(vert3[Y]*SUB_INCH_PRECISION), (sint32)(vert3[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert4[X]*SUB_INCH_PRECISION), (sint32)(vert4[Y]*SUB_INCH_PRECISION), (sint32)(vert4[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::EndUNPACK();\r\n\tloc++;\r\n\tvif::STMOD(NORMAL_MODE);\r\n\r\n\t// finish batch of vertices\r\n\t//EndModelMultiPrim();\r\n\tgif::EndTag1(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n}\r\n\r\nvoid CImmediateMode::sDrawStarSegment( const Mth::Vector& vert0, const Mth::Vector& vert1,\r\n\t\t\t\t\t\t\t\t\t   const Mth::Vector& vert2, const Mth::Vector& vert3,\r\n\t\t\t\t\t\t\t\t\t   uint32 col0, uint32 col1, uint32 col2 )\r\n{\r\n\t// begin a batch of vertices\r\n\t// Note: UV must always be 1st, Pos must always be last.\r\n\t//BeginModelPrim(gs::XYZ2<<4|gs::RGBAQ, 2, TRISTRIP|IIP|ABE, 1, VU1_ADDR(Proj));\r\n\tvif::STCYCL(1,2);\r\n\tvif::UNPACK(0,V4_32,1,ABS,UNSIGNED,0);\r\n\tgif::BeginTag1(gs::XYZF2<<4|gs::RGBAQ, 2, PACKED, TRISTRIP|IIP|ABE, 1, VU1_ADDR(Proj));\r\n\r\n\tint loc = 1;\r\n\r\n\tvif::BeginUNPACK(0, V4_8, ABS, UNSIGNED, loc);\r\n\tvif::StoreS_32(col0);\r\n\tvif::StoreS_32(col1);\r\n\tvif::StoreS_32(col1);\r\n\tvif::StoreS_32(col2);\r\n\tvif::EndUNPACK();\r\n\tloc++;\r\n\r\n\tvif::STMOD(OFFSET_MODE);\r\n\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, loc);\r\n\tvif::StoreV4_32((sint32)(vert0[X]*SUB_INCH_PRECISION), (sint32)(vert0[Y]*SUB_INCH_PRECISION), (sint32)(vert0[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert1[X]*SUB_INCH_PRECISION), (sint32)(vert1[Y]*SUB_INCH_PRECISION), (sint32)(vert1[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert2[X]*SUB_INCH_PRECISION), (sint32)(vert2[Y]*SUB_INCH_PRECISION), (sint32)(vert2[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert3[X]*SUB_INCH_PRECISION), (sint32)(vert3[Y]*SUB_INCH_PRECISION), (sint32)(vert3[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::EndUNPACK();\r\n\tloc++;\r\n\tvif::STMOD(NORMAL_MODE);\r\n\r\n\t// finish batch of vertices\r\n\t//EndModelMultiPrim();\r\n\tgif::EndTag1(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n}\r\n\r\nvoid CImmediateMode::sDrawSmoothStarSegment( const Mth::Vector& vert0, const Mth::Vector& vert1,\r\n\t\t\t\t\t\t\t\t\t\t\t const Mth::Vector& vert2, const Mth::Vector& vert3, const Mth::Vector& vert4,\r\n\t\t\t\t\t\t\t\t\t\t\t uint32 col0, uint32 col1, uint32 col2 )\r\n{\r\n\t// begin a batch of vertices\r\n\t// Note: UV must always be 1st, Pos must always be last.\r\n\t//BeginModelPrim(gs::XYZ2<<4|gs::RGBAQ, 2, TRIFAN|IIP|ABE, 1, VU1_ADDR(Proj));\r\n\tvif::STCYCL(1,2);\r\n\tvif::UNPACK(0,V4_32,1,ABS,UNSIGNED,0);\r\n\tgif::BeginTag1(gs::XYZF2<<4|gs::RGBAQ, 2, PACKED, TRIFAN|IIP|ABE, 1, VU1_ADDR(Proj));\r\n\r\n\tint loc = 1;\r\n\r\n\tvif::BeginUNPACK(0, V4_8, ABS, UNSIGNED, loc);\r\n\tvif::StoreS_32(col1);\r\n\tvif::StoreS_32(col0);\r\n\tvif::StoreS_32(col2);\r\n\tvif::StoreS_32(col2);\r\n\tvif::StoreS_32(col2);\r\n\tvif::StoreS_32(col0);\r\n\tvif::EndUNPACK();\r\n\tloc++;\r\n\r\n\tvif::STMOD(OFFSET_MODE);\r\n\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, loc);\r\n\tvif::StoreV4_32((sint32)(vert0[X]*SUB_INCH_PRECISION), (sint32)(vert0[Y]*SUB_INCH_PRECISION), (sint32)(vert0[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert1[X]*SUB_INCH_PRECISION), (sint32)(vert1[Y]*SUB_INCH_PRECISION), (sint32)(vert1[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert2[X]*SUB_INCH_PRECISION), (sint32)(vert2[Y]*SUB_INCH_PRECISION), (sint32)(vert2[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert3[X]*SUB_INCH_PRECISION), (sint32)(vert3[Y]*SUB_INCH_PRECISION), (sint32)(vert3[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert4[X]*SUB_INCH_PRECISION), (sint32)(vert4[Y]*SUB_INCH_PRECISION), (sint32)(vert4[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert1[X]*SUB_INCH_PRECISION), (sint32)(vert1[Y]*SUB_INCH_PRECISION), (sint32)(vert1[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::EndUNPACK();\r\n\tloc++;\r\n\tvif::STMOD(NORMAL_MODE);\r\n\r\n\t// finish batch of vertices\r\n\t//EndModelMultiPrim();\r\n\tgif::EndTag1(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n}\r\n\r\nvoid CImmediateMode::sDrawLine( const Mth::Vector& vert0, const Mth::Vector& vert1, uint32 col0, uint32 col1 )\r\n{\r\n\t// begin a batch of vertices\r\n\t// Note: UV must always be 1st, Pos must always be last.\r\n\t//BeginModelPrim(gs::XYZ2<<4|gs::RGBAQ, 2, LINE|IIP|ABE, 1, VU1_ADDR(Proj));\r\n\tvif::STCYCL(1,2);\r\n\tvif::UNPACK(0,V4_32,1,ABS,UNSIGNED,0);\r\n\tgif::BeginTag1(gs::XYZ2<<4|gs::RGBAQ, 2, PACKED, LINE|IIP|ABE, 1, VU1_ADDR(Line));\r\n\r\n\tint loc = 1;\r\n\r\n\tvif::BeginUNPACK(0, V4_8, ABS, UNSIGNED, loc);\r\n\tvif::StoreS_32(col0);\r\n\tvif::StoreS_32(col1);\r\n\tvif::EndUNPACK();\r\n\tloc++;\r\n\r\n\tvif::STMOD(OFFSET_MODE);\r\n\tvif::BeginUNPACK(1, V4_32, ABS, SIGNED, loc);\r\n\tvif::StoreV4_32((sint32)(vert0[X]*SUB_INCH_PRECISION), (sint32)(vert0[Y]*SUB_INCH_PRECISION), (sint32)(vert0[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(vert1[X]*SUB_INCH_PRECISION), (sint32)(vert1[Y]*SUB_INCH_PRECISION), (sint32)(vert1[Z]*SUB_INCH_PRECISION), 0);\r\n\tvif::EndUNPACK();\r\n\tloc++;\r\n\tvif::STMOD(NORMAL_MODE);\r\n\r\n\t// finish batch of vertices\r\n\t//EndModelMultiPrim();\r\n\tgif::EndTag1(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n}\r\n\r\n}\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/immediate.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       immediate.h\r\n//* OWNER:          Garrett Jost\r\n//* CREATION DATE:  7/19/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__IMMEDIATE_H__\r\n#define\t__IMMEDIATE_H__\r\n    \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nnamespace NxPs2\r\n{\r\n// Forward declarations\r\nstruct SSingleTexture;\r\n\r\nclass CImmediateMode\r\n{\r\npublic:\r\n\t// Init functions\r\n\tstatic void sViewportInit();\r\n\tstatic void sTextureGroupInit(uint unpackFLG);\r\n\r\n\tstatic void sSetZPush(float zpush = 1.0e-33f);\r\n\tstatic void sClearZPush();\r\n\r\n\t// Draw start functions\r\n\tstatic void sStartPolyDraw( SSingleTexture * p_engine_texture, uint64 blend, uint unpackFLG, bool clip = false );\r\n\tstatic void sStartPolyDraw( uint32 * p_packed_texture_regs, int num_texture_regs, uint unpackFLG, bool clip = false );\r\n\r\n\t// Draw functions\r\n\tstatic void sDrawQuadTexture( SSingleTexture * p_engine_texture, const Mth::Vector& vert0, const Mth::Vector& vert1,\r\n\t\t\t\t\t\t\t\t  const Mth::Vector& vert2, const Mth::Vector& vert3,\r\n\t\t\t\t\t\t\t\t  uint32 col0, uint32 col1, uint32 col2, uint32 col3 );\r\n\tstatic void sDrawTri( const Mth::Vector& vert0, const Mth::Vector& vert1, const Mth::Vector& vert2,\r\n\t\t\t\t\t\t  uint32 col0, uint32 col1, uint32 col2, uint unpackFLG );\r\n\tstatic void sDrawTriUV( const Mth::Vector& vert0, const Mth::Vector& vert1, const Mth::Vector& vert2,\r\n\t\t\t\t\t\t\tfloat u0, float v0, float u1, float v1, float u2, float v2,\r\n\t\t\t\t\t\t\tuint32 col0, uint32 col1, uint32 col2, uint unpackFLG );\r\n\tstatic void sDraw5QuadTexture( SSingleTexture * p_engine_texture, const Mth::Vector& vert0, const Mth::Vector& vert1,\r\n\t\t\t\t\t\t\t\t   const Mth::Vector& vert2, const Mth::Vector& vert3, const Mth::Vector& vert4,\r\n\t\t\t\t\t\t\t\t   uint32 col0, uint32 col1 );\r\n\tstatic void sDrawGlowSegment( const Mth::Vector& vert0, const Mth::Vector& vert1,\r\n\t\t\t\t\t\t\t\t  const Mth::Vector& vert2, const Mth::Vector& vert3, const Mth::Vector& vert4,\r\n\t\t\t\t\t\t\t\t  uint32 col0, uint32 col1, uint32 col2 );\r\n\tstatic void sDrawStarSegment( const Mth::Vector& vert0, const Mth::Vector& vert1,\r\n\t\t\t\t\t\t\t\t  const Mth::Vector& vert2, const Mth::Vector& vert3,\r\n\t\t\t\t\t\t\t\t  uint32 col0, uint32 col1, uint32 col2 );\r\n\tstatic void sDrawSmoothStarSegment( const Mth::Vector& vert0, const Mth::Vector& vert1,\r\n\t\t\t\t\t\t\t\t\t\tconst Mth::Vector& vert2, const Mth::Vector& vert3, const Mth::Vector& vert4,\r\n\t\t\t\t\t\t\t\t\t\tuint32 col0, uint32 col1, uint32 col2 );\r\n\tstatic void sDrawLine( const Mth::Vector& vert0, const Mth::Vector& vert1, uint32 col0, uint32 col1 );\r\n\r\n\tstatic uint64 sGetTextureBlend( uint32 blend_checksum, int fix );\r\n\r\nprotected:\r\n};\r\n\r\n}\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/instance.cpp",
    "content": "#include \"instance.h\"\r\n#include \"scene.h\"\r\n#include \"dma.h\"\r\n#include \"mesh.h\"\r\n#include <core/math.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\nCInstance::CInstance(sScene *pScene, Mth::Matrix transform, bool color_per_material)\r\n{\r\n\tSetTransform(transform);\r\n\tmp_bone_transforms = NULL;\r\n\tm_num_bones = 0;\r\n\tm_flags = INSTANCEFLAG_ACTIVE;\r\n\tmp_next = pScene->pInstances;\r\n\tpScene->pInstances = this;\r\n\tm_lastFrame = 0;\r\n\tm_field = 0;\r\n\tmp_scene = pScene;\r\n\tmp_light_group = NULL;\r\n\tif (color_per_material)\r\n\t{\r\n\t\tm_flags |= INSTANCEFLAG_COLORPERMATERIAL;\r\n\t\tmp_color_array = new uint32[mp_scene->NumMeshes];\r\n\t\tfor (int i = 0; i < mp_scene->NumMeshes; i++)\r\n\t\t{\r\n\t\t\tmp_color_array[i] = 0x80808080;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_colour = 0x80808080;\r\n\t}\r\n}\r\n\r\n\r\nCInstance::CInstance(sScene *pScene, Mth::Matrix transform, bool color_per_material, int numBones, Mth::Matrix *pBoneTransforms)\r\n{\r\n\tSetTransform(transform);\r\n\tmp_bone_transforms = pBoneTransforms;\r\n\tm_num_bones = numBones;\r\n\tm_flags = INSTANCEFLAG_ACTIVE;\r\n\tmp_next = pScene->pInstances;\r\n\tpScene->pInstances = this;\r\n\tm_lastFrame = 0;\r\n\tm_field = 0;\r\n\tmp_scene = pScene;\r\n\tmp_light_group = NULL;\r\n\tif (color_per_material)\r\n\t{\r\n\t\tm_flags |= INSTANCEFLAG_COLORPERMATERIAL;\r\n\t\tmp_color_array = new uint32[mp_scene->NumMeshes];\r\n\t\tfor (int i = 0; i < mp_scene->NumMeshes; i++)\r\n\t\t{\r\n\t\t\tmp_color_array[i] = 0x80808080;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_colour = 0x80808080;\r\n\t}\r\n}\r\n\r\n\r\nCInstance::~CInstance()\r\n{\r\n\tif (HasColorPerMaterial())\r\n\t{\r\n\t\tdelete [] mp_color_array;\r\n\t}\r\n\r\n\t// remove from list structure...\r\n\t// head of instance list\r\n\tif (mp_scene->pInstances == this)\r\n\t{\r\n\t\tmp_scene->pInstances = mp_next;\r\n\t}\r\n\t// body of instance list\r\n\telse\r\n\t{\r\n\t\tCInstance *pInstance;\r\n\t\tfor (pInstance=mp_scene->pInstances; pInstance; pInstance=pInstance->mp_next)\r\n\t\t\tif (pInstance->mp_next == this)\r\n\t\t\t\tbreak;\r\n\t\tDbg_MsgAssert(pInstance, (\"couldn't locate CInstance for deletion\"));\r\n\t\tpInstance->mp_next = mp_next;\r\n\t}\r\n}\r\n\r\n\r\nvoid CInstance::SetActive(bool Active)\r\n{\r\n\tif (Active)\r\n\t{\r\n\t\tm_flags |= INSTANCEFLAG_ACTIVE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_flags &= ~INSTANCEFLAG_ACTIVE;\r\n\t}\r\n}\r\n\r\nvoid CInstance::EnableShadow(bool Enabled)\r\n{\r\n\tif (Enabled)\r\n\t{\r\n\t\tm_flags |= INSTANCEFLAG_CASTSSHADOW;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_flags &= ~INSTANCEFLAG_CASTSSHADOW;\r\n\t}\r\n}\r\n\r\nvoid CInstance::SetWireframe(bool Wireframe)\r\n{\r\n\tif (Wireframe)\r\n\t{\r\n\t\tm_flags |= INSTANCEFLAG_WIREFRAME;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_flags &= ~INSTANCEFLAG_WIREFRAME;\r\n\t}\r\n}\r\n\r\nMth::Matrix* CInstance::GetBoneTransforms(void)\r\n{\r\n\treturn m_field ? mp_bone_transforms : ( mp_bone_transforms + m_num_bones );\r\n}\r\n\r\nvoid CInstance::SetBoneTransforms(Mth::Matrix* pMat)\r\n{\r\n\t// GJ:  toggle field, but only the first time\r\n\t// (otherwise, the double-buffer gets messed\r\n\t// up if SetBoneTransforms() is called more\r\n\t// than once per frame...)\r\n\tuint8 thisFrame = ( render::Frame & 0xff );\r\n\tif ( m_lastFrame != thisFrame )\r\n\t{\r\n\t\tm_field = !m_field;\r\n\t\tm_lastFrame = thisFrame;\r\n\t}\r\n\r\n\tint startIndex = m_field ? 0 : m_num_bones;\r\n\r\n\tMth::Matrix* pSrc = pMat;\r\n\tMth::Matrix* pDst = mp_bone_transforms + startIndex;\r\n\r\n\t// copy the given matrices into the correct half of the matrix double-buffer\r\n\tfor ( int i = 0; i < m_num_bones; i++ )\r\n\t{\r\n\t\t*pDst++ = *pSrc++;\r\n\t}\r\n}\r\n\r\n\r\nvoid CInstance::SetColor(uint32 rgba)\r\n{\r\n\tDbg_Assert(!HasColorPerMaterial());\r\n\r\n\tm_colour = rgba;\r\n}\r\n\r\nuint32 CInstance::GetColor()\r\n{\r\n\tDbg_Assert(!HasColorPerMaterial());\r\n\r\n\treturn m_colour;\r\n}\r\n\r\nvoid CInstance::SetMaterialColor(uint32 material_name, int pass, uint32 rgba)\r\n{\r\n\tDbg_Assert(HasColorPerMaterial());\r\n\r\n\tint i;\r\n\tsMesh *pMesh;\r\n\r\n\t// Array is in mesh order\r\n\tfor (pMesh = mp_scene->pMeshes, i = 0; i < mp_scene->NumMeshes; pMesh++, i++)\r\n\t{\r\n\t\tif ((pMesh->MaterialName==material_name) && (pMesh->Pass == pass))\r\n\t\t{\r\n\t\t\tmp_color_array[i] = rgba;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CInstance::SetMaterialColorByIndex(int mesh_idx, uint32 rgba)\r\n{\r\n\tDbg_Assert(HasColorPerMaterial());\r\n\tDbg_MsgAssert(mesh_idx < mp_scene->NumMeshes, (\"Mesh index %d is out of range\", mesh_idx));\r\n\r\n\tmp_color_array[mesh_idx] = rgba;\r\n}\r\n\r\nuint32 CInstance::GetMaterialColor(uint32 material_name, int pass)\r\n{\r\n\tDbg_Assert(HasColorPerMaterial());\r\n\r\n\tint i;\r\n\tsMesh *pMesh;\r\n\r\n\t// Array is in mesh order\r\n\tfor (pMesh = mp_scene->pMeshes, i = 0; i < mp_scene->NumMeshes; pMesh++, i++)\r\n\t{\r\n\t\tif ((pMesh->MaterialName==material_name) && (pMesh->Pass == pass))\r\n\t\t{\r\n\t\t\treturn mp_color_array[i];\r\n\t\t}\r\n\t}\r\n\r\n\treturn 0x80808080;\r\n}\r\n\r\nuint32 CInstance::GetMaterialColorByIndex(int mesh_idx)\r\n{\r\n\tDbg_Assert(HasColorPerMaterial());\r\n\r\n\treturn mp_color_array[mesh_idx];\r\n}\r\n\r\nMth::Vector CInstance::GetBoundingSphere()\r\n{\r\n\r\n\tif (m_flags & INSTANCEFLAG_EXPLICITSPHERE)\r\n\t{\r\n\t\treturn m_bounding_sphere;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMth::Vector sphere(mp_scene->Sphere);\r\n\t\tsphere[3] += 24.0f;\r\n\t\treturn sphere;\r\n\t}\r\n}\r\n\r\nvoid CInstance::SetBoundingSphere(float x, float y, float z, float r)\r\n{\r\n\t//printf( \"Stub:  SetBoundingSphere %f %f %f %f\\n\", x, y, z, r );\r\n\tm_bounding_sphere.Set(x,y,z,r);\r\n\tm_flags |= INSTANCEFLAG_EXPLICITSPHERE;\r\n}\r\n\r\n\r\nvoid CInstance::SqueezeADC()\r\n{\r\n\tint i, num_meshes = mp_scene->NumMeshes;\r\n\tsMesh *p_mesh = mp_scene->pMeshes;\r\n\r\n\tfor (i=0; i<num_meshes; i++,p_mesh++)\r\n\t{\r\n\t\tdma::SqueezeADC(p_mesh->pSubroutine);\r\n\t\tdma::SqueezeNOP(p_mesh->pSubroutine);\r\n\t}\r\n}\r\n\r\n\r\n\r\n// uv manipulation for skins\r\n\r\nvoid CInstance::SetUVOffset(uint32 material_name, int pass, float u_offset, float v_offset)\r\n{\r\n\tmp_scene->SetUVOffset(material_name, pass, u_offset, v_offset);\r\n}\r\n\r\n\r\nvoid CInstance::SetUVMatrix(uint32 material_name, int pass, const Mth::Matrix &mat)\r\n{\r\n\tmp_scene->SetUVMatrix(material_name, pass, mat);\r\n}\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/instance.h",
    "content": "#ifndef __INSTANCE_H\r\n#define __INSTANCE_H\r\n\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include \"scene.h\"\r\n#include <core\\math.h>\r\n\r\n\r\nnamespace Script\r\n{\r\n\textern int GetInt(uint32, bool);\r\n}\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n// Forward declarations\r\nclass\tCLightGroup;\r\n\r\n#define INSTANCEFLAG_ACTIVE\t\t\t\t(1<<0)\r\n#define INSTANCEFLAG_CASTSSHADOW\t\t(1<<1)\r\n#define INSTANCEFLAG_EXPLICITSPHERE\t\t(1<<2)\r\n#define INSTANCEFLAG_WIREFRAME\t\t\t(1<<3)\r\n#define INSTANCEFLAG_COLORPERMATERIAL\t(1<<4)\r\n\r\nclass CInstance\r\n{\r\npublic:\r\n\tvoid SetTransform(Mth::Matrix transform) { m_transform = transform; }\r\n\tMth::Matrix *GetTransform(void) { return &m_transform; }\r\n\tint GetNumBones(void) { return m_num_bones; }\r\n\tMth::Matrix *GetBoneTransforms(void);\r\n\tvoid SetBoneTransforms(Mth::Matrix *pMat);\r\n\tCInstance *GetNext() { return mp_next; }\r\n\tsScene *GetScene() { return mp_scene; }\r\n\tvoid SetActive(bool Active);\r\n\tvoid EnableShadow(bool Enabled);\r\n\tvoid SetWireframe(bool Wireframe);\r\n\tbool IsActive(void) const; \r\n\tbool CastsShadow(void) const; \r\n\tbool IsWireframe(void) const; \r\n\tbool HasColorPerMaterial(void) const; \r\n\tvoid SetColor(uint32 rgba);\r\n\tvoid SetMaterialColor(uint32 material_name, int pass, uint32 rgba);\r\n\tvoid SetMaterialColorByIndex(int mesh_idx, uint32 rgba);\r\n\tuint32 GetColor();\r\n\tuint32 GetMaterialColor(uint32 material_name, int pass);\r\n\tuint32 GetMaterialColorByIndex(int mesh_idx);\r\n\tvoid SetLightGroup(CLightGroup *p_light_group);\r\n\tCLightGroup *GetLightGroup();\r\n\tMth::Vector GetBoundingSphere();\r\n\tvoid SetBoundingSphere(float x, float y, float z, float r);\r\n\tvoid SqueezeADC();\r\n\tvoid SetUVOffset(uint32 material_name, int pass, float u_offset, float v_offset);\r\n\tvoid SetUVMatrix(uint32 material_name, int pass, const Mth::Matrix &mat);\r\n\tCInstance(sScene *pScene, Mth::Matrix transform, bool color_per_material);\r\n\tCInstance(sScene *pScene, Mth::Matrix transform, bool color_per_material, int numBones, Mth::Matrix *pBoneTransforms);\r\n\t~CInstance();\r\n\r\nprivate:\r\n\tMth::Matrix m_transform;\r\n\tMth::Matrix *mp_bone_transforms;\r\n\tMth::Vector m_bounding_sphere;\r\n\tuint32 m_flags;\r\n\tunion\r\n\t{\r\n\t\tuint32 m_colour;\r\n\t\tuint32 *mp_color_array;\t\t\t// Use this only when INSTANCEFLAG_COLORPERMATERIAL is set; in Mesh order\r\n\t};\r\n\tint m_num_bones;\r\n\tCInstance *mp_next;\r\n\tsScene *mp_scene;\r\n\tCLightGroup *mp_light_group;\t\t// optional group of lights\r\n\tuint8 m_lastFrame;\r\n\tchar m_field;\r\n};\r\n\r\n\r\n//  IsActive needs to be inline, otherwise it takes 1% of rendering cpu time\r\ninline bool CInstance::IsActive(void) const\r\n{\r\n\treturn (m_flags & INSTANCEFLAG_ACTIVE) ? true : false;\r\n}\r\n\r\ninline bool CInstance::CastsShadow(void) const\r\n{\r\n\treturn (m_flags & INSTANCEFLAG_CASTSSHADOW) ? true : false;\r\n}\r\n\r\ninline bool CInstance::IsWireframe(void) const\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tif (Script::GetInt(CRCD(0xb4ff073e,\"wireframe_skins\"),false))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t#endif\r\n\treturn (m_flags & INSTANCEFLAG_WIREFRAME) ? true : false;\r\n}\r\n\r\ninline bool CInstance::HasColorPerMaterial(void) const\r\n{\r\n\treturn m_flags & INSTANCEFLAG_COLORPERMATERIAL;\r\n}\r\n\r\ninline void CInstance::SetLightGroup(CLightGroup *p_light_group)\r\n{\r\n\tmp_light_group = p_light_group;\r\n}\r\n\r\ninline CLightGroup * CInstance::GetLightGroup()\r\n{\r\n\treturn mp_light_group;\r\n}\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n#endif // __INSTANCE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/interrupts.cpp",
    "content": "#include <core/defines.h>\r\n#include <eekernel.h>\r\n#include <eeregs.h>\r\n#include \"texture.h\"\r\n#include \"group.h\"\r\n#include \"render.h\"\r\n#include \"gs.h\"\r\n#include \"switches.h\"\r\n#include <sys\\profiler.h>\r\n\r\n//#undef\t__USE_PROFILER__\r\n\r\n\r\n/*\r\n\r\n Mick Notes:\r\n\r\n All interrupts are set up in the \"InitialiseEngine\" function of nx_init.cpp\r\n \r\n There are three types of interrupt covered here\r\n \r\n 1) GIF Interrupt - Used to signal the completion of texture upload\tto VRAM\r\n 2) GS  Interrupt - Used to signal the completion of GS rendering (drawing polygons)\r\n 3) VIF Interrupt - NOT USED, could be used like the GS interrupt, but unreliable.\r\n\r\n There are two types of activity going on in parallel: Upload and Render\r\n \r\n Whenever one of these finishes, it causes an interrupt. \r\n \r\n There is no way of knowing in advance what order the tasks will finish in\r\n so we must handle all possible cases. \r\n\r\n At any time, either upload or render might be \"Stalled\".  In this case we are waiting\r\n for something before we can start rendering or uploading a new group.  Stalls are not\r\n good, as the relevent processor is sat idle.  We want to minimize stalls as much as\r\n possible.  \r\n \r\n Stalls happen when:\r\n \r\n  - The initial render group is waiting for its textures to upload.  \r\n    (?) The renderer is always stalled on the first group \r\n  - An upload group want to use some VRAM that is used by a group \r\n    that is currently rendering. \r\n  - A render group is waiting for it's textures to upload. This could\r\n    happen if a group renders quicker than the next groups uploads.\r\n\r\n*/\r\n   \r\n   \r\n   \r\nnamespace NxPs2\r\n{\r\n\r\n\r\n#define START_UPLOAD()\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t*D2_QWC = 0;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t*D2_TADR = (uint)sGroup::pUploadGroup->pUpload[!render::Field];\t\t\t\t\t\t\t\\\r\n\t*D2_CHCR = 0x105;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tUploadStalled = 0;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n}\r\n\r\n#if GS_INTERRUPT\r\n#define START_RENDER()\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t*D1_QWC = 0;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t*D1_TADR = (uint)sGroup::pRenderGroup->pRender[!render::Field];\t\t\t\t\t\t\t\\\r\n\t*D1_CHCR = 0x145;\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\t\\\r\n\tRenderStalled = 0;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n}\r\n#endif\r\n\r\n#if VIF1_INTERRUPT\r\n#define START_RENDER()\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\nif (sGroup::pRenderGroup != sGroup::pHead)\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\t*VIF1_FBRST = 1<<3;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\t*D1_QWC = 0;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\t*D1_TADR = (uint)sGroup::pRenderGroup->pRender[!render::Field];\t\t\t\t\t\t\\\r\n\t\t*D1_CHCR = 0x145;\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\\\r\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n}\r\n#endif\r\n\r\n#define NO_VRAM_CONFLICT()\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n(\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tsGroup::pRenderGroup->VramStart >= sGroup::pUploadGroup->VramEnd ||\t\t\t\t\\\r\n\tsGroup::pUploadGroup->VramStart >= sGroup::pRenderGroup->VramEnd\t\t\t\t\\\r\n)\r\n\r\n\r\nvolatile uint32 UploadStalled, RenderStalled;\r\n\r\n\r\n\r\n// handler called when an upload finishes\r\n\r\nint GifHandler(int Cause)\r\n{\r\n\tif (!sGroup::pUploadGroup)\t\t// Mick:  Might not actually be anything to upload, if p_memview was uploading\r\n\t\tgoto EXIT;\r\n\t\r\n\t// we've finished uploading a group\r\n\tsGroup::pUploadGroup = sGroup::pUploadGroup->pNext;\r\n\twhile (sGroup::pUploadGroup && !sGroup::pUploadGroup->Used[!render::Field])\t\t// if exists, but not used\r\n\t{\r\n\t\tsGroup::pUploadGroup = sGroup::pUploadGroup->pNext;\t// then skip groups until reach end, or find one that is used\r\n\t}\r\n\r\n\r\n#\tifdef __USE_PROFILER__\r\n\tSys::DMAProfiler->PopContext();\t \r\n#\tendif // __USE_PROFILER__\r\n\r\n\t// is there another group to upload?\r\n\tif (sGroup::pUploadGroup)\r\n\t{\r\n\r\n\t\t\r\n\t\t// was there a stalled render?\r\n\t\tif (RenderStalled)\r\n\t\t{\r\n\t\t\t// kick off the stalled render\r\n#\tifdef __USE_PROFILER__\r\n\t\t\t\tSys::VUProfiler->PushContext( sGroup::pRenderGroup->profile_color );\t   \t\t\t\t\t\t\t\t\t\r\n#\tendif // __USE_PROFILER__\r\n\t\t\tSTART_RENDER();\r\n\r\n\t\t\t// is the next upload safe?\r\n\t\t\tif (NO_VRAM_CONFLICT())\r\n\t\t\t{\r\n\t\t\t\t// kick off the next upload\r\n#\tifdef __USE_PROFILER__\r\n\t\t\t\tSys::DMAProfiler->PushContext( sGroup::pUploadGroup->profile_color );\t   \t\t\t\t\t\t\t\t\t\r\n#\tendif // __USE_PROFILER__\r\n\t\t\t\tSTART_UPLOAD();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// stall the next upload\r\n\t\t\t\tUploadStalled = 1;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\telse// there's a render in progress\r\n\t\t{\r\n\t\t\t// since we just finished an upload, then the render in progress MUST\r\n\t\t\t// be using the previously uploaded group\r\n\t\t\t// so there is no way that we can start a new upload until that render finishes.\r\n\t\t\t// so, stall the next upload\r\n\t\t\tUploadStalled = 1;\r\n\t\t}\r\n\t}\r\n\r\n\telse// no more groups to upload\r\n\t{\r\n\t\t// was the final render stalled?\r\n\t\tif (RenderStalled)\r\n\t\t{\r\n\t\t\t// kick it off\r\n#\tifdef __USE_PROFILER__\r\n\t\t\t\tSys::VUProfiler->PushContext(  sGroup::pRenderGroup->profile_color );\t   \t\t\t\t\t\t\t\t\t\r\n#\tendif // __USE_PROFILER__\r\n\t\t\tSTART_RENDER();\r\n\t\t}\r\n\t}\r\n\r\nEXIT:\r\n\tExitHandler();\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n\r\n// handler called when a render finishes (gs version)\r\n\r\nint GsHandler(int Cause)\r\n{\r\n\t// mask GS interrupts\r\n\t*GS_IMR = PackIMR(1,1,1,1);\r\n\r\n\t// reset SIGNAL event bit\r\n\t*GS_CSR = *GS_CSR & ~(uint64)0x30F | 1;\r\n\r\n\t// reset signal bit\r\n\t*GS_SIGLBLID &= ~(uint64)1;\r\n\r\n\t// maybe it was a false alarm...\r\n\tif (!sGroup::pRenderGroup)\t// if nothing currently rendering, then we've finished!!\r\n\t\tgoto EXIT;\r\n\t\r\n\t// we've finished rendering a group, so find the next group to render\r\n\tsGroup::pRenderGroup = sGroup::pRenderGroup->pNext;\r\n\twhile (sGroup::pRenderGroup && !sGroup::pRenderGroup->Used[!render::Field])\t\t// if exists, but not used\r\n\t{\r\n\t\tsGroup::pRenderGroup = sGroup::pRenderGroup->pNext;\t// then skip groups until reach end, or find one that is used\r\n\t}\r\n\r\n\t#\tifdef __USE_PROFILER__\r\n\tSys::VUProfiler->PopContext();\t \r\n\t#\tendif // __USE_PROFILER__\r\n\r\n\t\r\n\t// is there another group to render?\r\n\tif (sGroup::pRenderGroup)\r\n\t{\r\n\t\t// was there a stalled upload?\r\n\t\tif (UploadStalled)\r\n\t\t{\r\n\t\t\t// is the next render waiting for the stalled upload?\r\n\t\t\t// (i.e., they both are the same group)\r\n\t\t\tif (sGroup::pRenderGroup == sGroup::pUploadGroup)\r\n\t\t\t{\r\n\t\t\t\t// kick off the stalled upload\r\n#\tifdef __USE_PROFILER__\r\n\t\t\t\tSys::DMAProfiler->PushContext(  sGroup::pUploadGroup->profile_color );\t   \t\t\t\t\t\t\t\t\t\r\n#\tendif // __USE_PROFILER__\r\n\t\t\t\tSTART_UPLOAD();\r\n\r\n\t\t\t\t// but stall the next render\r\n\t\t\t\t// as this upload group is needed for this render \r\n\t\t\t\tRenderStalled = 2;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// kick off the next render, as it's from a previous group\r\n#\tifdef __USE_PROFILER__\r\n\t\t\t\tSys::VUProfiler->PushContext(  sGroup::pRenderGroup->profile_color );\t   \t\t\t\t\t\t\t\t\t\r\n#\tendif // __USE_PROFILER__\r\n\t\t\t\tSTART_RENDER();\r\n\r\n\t\t\t\t// is the next upload safe?\r\n\t\t\t\tif (NO_VRAM_CONFLICT())\r\n\t\t\t\t{\r\n\t\t\t\t\t// kick off the next upload\r\n#\tifdef __USE_PROFILER__\r\n\t\t\t\t\tSys::DMAProfiler->PushContext(  sGroup::pUploadGroup->profile_color );\t   \t\t\t\t\t\t\t\t\t\r\n#\tendif // __USE_PROFILER__\r\n\t\t\t\t\tSTART_UPLOAD();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// is there an upload in progress?\r\n\t\t// (Mick: Does it make sense to also check to see if the upload group is the same as the render group?\r\n\t\t// or is that always the case, and that's why Mike is not checking it?)\r\n\t\telse if (sGroup::pUploadGroup)\r\n\t\t{\r\n\t\t\t// stall the next render\r\n\t\t\tRenderStalled = 1;\r\n\t\t}\r\n\r\n\t\t// no uploads left\r\n\t\telse\r\n\t\t{\r\n\t\t\t// kick off the final render\r\n#\tifdef __USE_PROFILER__\r\n\t\t\t\tSys::VUProfiler->PushContext(  sGroup::pRenderGroup->profile_color );\t   \t\t\t\t\t\t\t\t\t\r\n#\tendif // __USE_PROFILER__\r\n\t\t\tSTART_RENDER();\r\n\t\t}\r\n\t}\r\n\r\nEXIT:\r\n\t// re-enable GS interrupts\r\n\t*GS_IMR = PackIMR(0,1,1,1);\r\n\r\n\tExitHandler();\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n// handler called when a render finishes (vif version)\r\n// (Mick:  not currently used, ignore for now)\r\nint Vif1Handler(int Cause)\r\n{\r\n\t// make sure the mark register gives the go-ahead\r\n\tif (*VIF1_MARK != 1)\r\n\t\tgoto EXIT;\r\n\r\n\t// maybe it was a false alarm...\r\n\tif (!sGroup::pRenderGroup)\r\n\t\tgoto EXIT;\r\n\t\r\n\t// we've finished rendering a group\r\n\tsGroup::pRenderGroup = sGroup::pRenderGroup->pNext;\t\t// get next group\r\n\t\r\n\t// is there another group to render?\r\n\tif (sGroup::pRenderGroup)\r\n\t{\r\n\t\t// was there a stalled upload?\r\n\t\tif (UploadStalled)\r\n\t\t{\r\n\t\t\t// is the next render waiting for the stalled upload?\r\n\t\t\tif (sGroup::pRenderGroup == sGroup::pUploadGroup)\r\n\t\t\t{\r\n\t\t\t\t// kick off the stalled upload\r\n#\tifdef __USE_PROFILER__\r\n\t\t\t\tSys::DMAProfiler->PushContext(  sGroup::pUploadGroup->profile_color );\t   \t\t\t\t\t\t\t\t\t\r\n#\tendif // __USE_PROFILER__\r\n\t\t\t\tSTART_UPLOAD();\r\n\t\t\t\tUploadStalled = 0;\r\n\r\n\t\t\t\t// but stall the next render\r\n\t\t\t\tRenderStalled = 2;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// kick off the next render\r\n#\tifdef __USE_PROFILER__\r\n\t\t\t\tSys::VUProfiler->PushContext(  sGroup::pRenderGroup->profile_color );\t   \t\t\t\t\t\t\t\t\t\r\n#\tendif // __USE_PROFILER__\r\n\t\t\t\tSTART_RENDER();\r\n\r\n\t\t\t\t// is the next upload safe?\r\n\t\t\t\tif (NO_VRAM_CONFLICT())\r\n\t\t\t\t{\r\n\t\t\t\t\t// kick off the next upload\r\n#\tifdef __USE_PROFILER__\r\n\t\t\t\t\tSys::DMAProfiler->PushContext(  sGroup::pUploadGroup->profile_color );\t   \t\t\t\t\t\t\t\t\t\r\n#\tendif // __USE_PROFILER__\r\n\t\t\t\t\tSTART_UPLOAD();\r\n\t\t\t\t\tUploadStalled = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// is there an upload in progress?\r\n\t\telse if (sGroup::pUploadGroup)\r\n\t\t{\r\n\t\t\t// stall the next render\r\n\t\t\tRenderStalled = 1;\r\n\t\t}\r\n\r\n\t\t// no uploads left\r\n\t\telse\r\n\t\t{\r\n\t\t\t// kick off the final render\r\n#\tifdef __USE_PROFILER__\r\n\t\t\t\tSys::VUProfiler->PushContext(  sGroup::pRenderGroup->profile_color );\t   \t\t\t\t\t\t\t\t\t\r\n#\tendif // __USE_PROFILER__\r\n\t\t\tSTART_RENDER();\r\n\t\t}\r\n\t}\r\n\r\nEXIT:\r\n\tExitHandler();\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/interrupts.h",
    "content": "#ifndef __INTERRUPTS_H\r\n#define __INTERRUPTS_H\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nint TextureSyncHandler(int Cause);\r\nint DMATextureSyncHandler(int Cause);\r\nint GifHandler(int Cause);\r\nint GsHandler(int Cause);\r\nint Vif1Handler(int Cause);\r\n\r\nextern volatile uint32 UploadStalled, RenderStalled;\r\n\r\n// Inlines\r\n\r\n// If you need to use floating point in an interrupt, you MUST use the functions saveFloatRegs()\r\n// and restoreFloatRegs() or some equivalent.\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\ninline void saveFloatRegs(unsigned int *buffer)\r\n{\r\n    asm volatile (\"\r\n      swc1    $f00,0x00(%0)\r\n      swc1    $f01,0x04(%0)\r\n      swc1    $f02,0x08(%0)\r\n      swc1    $f03,0x0c(%0)\r\n      swc1    $f04,0x10(%0)\r\n      swc1    $f05,0x14(%0)\r\n      swc1    $f06,0x18(%0)\r\n      swc1    $f07,0x1c(%0)\r\n\r\n      swc1    $f08,0x20(%0)\r\n      swc1    $f09,0x24(%0)\r\n      swc1    $f10,0x28(%0)\r\n      swc1    $f11,0x2c(%0)\r\n      swc1    $f12,0x30(%0)\r\n      swc1    $f13,0x34(%0)\r\n      swc1    $f14,0x38(%0)\r\n      swc1    $f15,0x3c(%0)\r\n\r\n      swc1    $f16,0x40(%0)\r\n      swc1    $f17,0x44(%0)\r\n      swc1    $f18,0x48(%0)\r\n      swc1    $f19,0x4c(%0)\r\n      swc1    $f20,0x50(%0)\r\n      swc1    $f21,0x54(%0)\r\n      swc1    $f22,0x58(%0)\r\n      swc1    $f23,0x5c(%0)\r\n\r\n      swc1    $f24,0x60(%0)\r\n      swc1    $f25,0x64(%0)\r\n      swc1    $f26,0x68(%0)\r\n      swc1    $f27,0x6c(%0)\r\n      swc1    $f28,0x70(%0)\r\n      swc1    $f29,0x74(%0)\r\n      swc1    $f30,0x78(%0)\r\n      swc1    $f31,0x7c(%0)\r\n\r\n    \": : \"r\" (buffer));\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\ninline void restoreFloatRegs(unsigned int *buffer)\r\n{\r\n    asm volatile (\"\r\n      lwc1    $f00,0x00(%0)\r\n      lwc1    $f01,0x04(%0)\r\n      lwc1    $f02,0x08(%0)\r\n      lwc1    $f03,0x0c(%0)\r\n      lwc1    $f04,0x10(%0)\r\n      lwc1    $f05,0x14(%0)\r\n      lwc1    $f06,0x18(%0)\r\n      lwc1    $f07,0x1c(%0)\r\n\r\n      lwc1    $f08,0x20(%0)\r\n      lwc1    $f09,0x24(%0)\r\n      lwc1    $f10,0x28(%0)\r\n      lwc1    $f11,0x2c(%0)\r\n      lwc1    $f12,0x30(%0)\r\n      lwc1    $f13,0x34(%0)\r\n      lwc1    $f14,0x38(%0)\r\n      lwc1    $f15,0x3c(%0)\r\n\r\n      lwc1    $f16,0x40(%0)\r\n      lwc1    $f17,0x44(%0)\r\n      lwc1    $f18,0x48(%0)\r\n      lwc1    $f19,0x4c(%0)\r\n      lwc1    $f20,0x50(%0)\r\n      lwc1    $f21,0x54(%0)\r\n      lwc1    $f22,0x58(%0)\r\n      lwc1    $f23,0x5c(%0)\r\n\r\n      lwc1    $f24,0x60(%0)\r\n      lwc1    $f25,0x64(%0)\r\n      lwc1    $f26,0x68(%0)\r\n      lwc1    $f27,0x6c(%0)\r\n      lwc1    $f28,0x70(%0)\r\n      lwc1    $f29,0x74(%0)\r\n      lwc1    $f30,0x78(%0)\r\n      lwc1    $f31,0x7c(%0)\r\n\r\n    \": : \"r\" (buffer));\r\n}\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n#endif // __INTERRUPTS_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/light.cpp",
    "content": "#include <core/defines.h>\r\n#include \"light.h\"\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n// Statics\r\nCLightGroup\t\tCLightGroup::s_default_lights;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCLightGroup::CLightGroup()\r\n{\r\n\tif (this != &s_default_lights)\t   // can't initialize from itself\r\n\t{\r\n\t\t// Don't use new lights unless someone sets them\r\n\t\tm_flags = 0;\r\n\t\r\n\t\t// Init to default lights\r\n\t\tm_light_vector = s_default_lights.m_light_vector;\r\n\t\r\n\t\tm_diffuse_base_color = s_default_lights.m_diffuse_base_color;\r\n\t\tm_diffuse_mod_color = s_default_lights.m_diffuse_base_color;\r\n\t\r\n\t\tm_ambient_base_color = s_default_lights.m_ambient_base_color;\r\n\t\tm_ambient_mod_color = s_default_lights.m_ambient_base_color;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_light_vector[0].Set(0,-1,0);\r\n\t\tm_light_vector[1].Set(0,-1,0);\r\n\t\tm_light_vector[2].Set(0,-1,0);\r\n\t\tm_diffuse_base_color[0].Set() ;\r\n\t\tm_diffuse_base_color[1].Set() ;\r\n\t\tm_diffuse_base_color[2].Set() ;\r\n\t\tm_diffuse_mod_color[0].Set()  ;\r\n\t\tm_diffuse_mod_color[1].Set()  ;\r\n\t\tm_diffuse_mod_color[2].Set()  ;\r\n\t\tm_ambient_base_color.Set() ;\r\n\t\tm_ambient_mod_color.Set()  ;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCLightGroup::~CLightGroup()\r\n{\r\n}\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/light.h",
    "content": "#ifndef __LIGHT_H\r\n#define __LIGHT_H\r\n\r\n#include\t<core/defines.h>\r\n#include\t<core/math.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n// Forward declarations\r\nclass CLightGroup;\r\n\r\n#if 0\r\nclass CBaseLightGroup\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCBaseLightGroup();\r\n\tvirtual\t\t\t\t\t\t~CBaseLightGroup();\r\n\r\n\tvirtual const Mth::Vector &\tGetDirection(int idx) const;\r\n\r\n\tvirtual const Mth::Vector &\tGetAmbientColor() const;\r\n\tvirtual const Mth::Vector &\tGetDiffuseColor(int idx) const;\r\n\r\nprotected:\r\n\t// Directional light vectors\r\n\tMth::Vector\t\t\t\t\tm_light_vector[MAX_DIFFUSE_LIGHTS];\r\n\r\n\t// Light base colors\r\n\tMth::Vector \t\t\t\tm_diffuse_base_color[MAX_DIFFUSE_LIGHTS];\r\n\tMth::Vector \t\t\t\tm_ambient_base_color;\r\n\r\n\tfriend CLightGroup;\r\n};\r\n#endif\r\n\r\nclass CLightGroup/* : public CBaseLightGroup*/\r\n{\r\n\r\n\tfriend class CVu1Context;\r\npublic:\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tMAX_DIFFUSE_LIGHTS = 3,\r\n\t};\r\n\r\n\t\t\t\t\t\t\t\tCLightGroup();\r\n\t\t\t\t\t\t\t\t~CLightGroup();\r\n\t//virtual\t\t\t\t\t\t~CLightGroup();\r\n\r\n\tconst Mth::Vector &\t\t\tGetDirection(int idx) const;\r\n\t//virtual const Mth::Vector &\tGetDirection(int idx) const;\r\n\r\n\tconst Mth::Vector &\t\t\tGetBaseAmbientColor() const;\r\n\tconst Mth::Vector &\t\t\tGetBaseDiffuseColor(int idx) const;\r\n\r\n\tconst Mth::Vector &\t\t\tGetAmbientColor() const;\r\n\tconst Mth::Vector &\t\t\tGetDiffuseColor(int idx) const;\r\n\t//virtual const Mth::Vector &\tGetAmbientColor() const;\r\n\t//virtual const Mth::Vector &\tGetDiffuseColor(int idx) const;\r\n\r\n\tvoid\t\t\t\t\t\tSetDirection(int idx, const Mth::Vector & direction);\r\n\tvoid\t\t\t\t\t\tSetBaseAmbientColor(const Mth::Vector & color);\r\n\tvoid\t\t\t\t\t\tSetBaseDiffuseColor(int idx, const Mth::Vector & color);\r\n\r\n\t// Enable lights\r\n\tvoid\t\t\t\t\t\tEnableAmbientLight(bool enable);\r\n\tvoid\t\t\t\t\t\tEnableDiffuseLight(int idx, bool enable);\r\n\tbool\t\t\t\t\t\tIsAmbientLightEnabled() const;\r\n\tbool\t\t\t\t\t\tIsDiffuseLightEnabled(int idx) const;\r\n\r\n\t// Set brightness of lights\r\n\tbool\t\t\t\t\t\tSetAmbientBrightness(float brightness);\r\n\tbool\t\t\t\t\t\tSetDiffuseBrightness(int idx, float brightness);\r\n\r\n\t// Default lights\r\n\tstatic const Mth::Vector &\tsGetDefaultDirection(int idx);\r\n\tstatic const Mth::Vector &\tsGetDefaultAmbientColor();\r\n\tstatic const Mth::Vector &\tsGetDefaultDiffuseColor(int idx);\r\n\r\n\tstatic void\t\t\t\t\tsSetDefaultDirection(int idx, const Mth::Vector & direction);\r\n\tstatic void\t\t\t\t\tsSetDefaultAmbientColor(const Mth::Vector & color);\r\n\tstatic void\t\t\t\t\tsSetDefaultDiffuseColor(int idx, const Mth::Vector & color);\r\n\r\nprotected:\r\n\t// Internal flags.\r\n\tenum {\r\n\t\tmUSE_AMBIENT\t\t\t\t= 0x0001,\t\t\t\t\t// Use ambient light\r\n\t\tmUSE_DIFFUSE_0\t\t\t\t= 0x0002,\t\t\t\t\t// Use diffuse light 0\r\n\t\tmUSE_DIFFUSE_1\t\t\t\t= 0x0004,\t\t\t\t\t// rest of diffuse must follow 0\r\n\t\tmUSE_DIFFUSE_2\t\t\t\t= 0x0008,\t\t\t\t\t// rest of diffuse must follow 0\r\n\t\tmMODULATING_AMBIENT\t\t\t= 0x0010,\t\t\t\t\t// setting ambient brightness\r\n\t\tmMODULATING_DIFFUSE_0\t\t= 0x0020,\t\t\t\t\t// setting diffuse brightness 0\r\n\t\tmMODULATING_DIFFUSE_1\t\t= 0x0040,\t\t\t\t\t// rest of diffuse must follow 0\r\n\t\tmMODULATING_DIFFUSE_2\t\t= 0x0040,\t\t\t\t\t// rest of diffuse must follow 0\r\n\t};\r\n\r\n\tuint32\t\t\t\t\tm_flags;\r\n\r\n\t// Directional light vectors\r\n\tMth::Vector\t\t\t\tm_light_vector[MAX_DIFFUSE_LIGHTS];\r\n\r\n\t// Light base colors\r\n\tMth::Vector \t\t\tm_diffuse_base_color[MAX_DIFFUSE_LIGHTS];\r\n\tMth::Vector \t\t\tm_ambient_base_color;\r\n\r\n\t// Light modulated colors (modified base colors)\r\n\tMth::Vector \t\t\tm_diffuse_mod_color[MAX_DIFFUSE_LIGHTS];\r\n\tMth::Vector \t\t\tm_ambient_mod_color;\r\n\r\n\t// Default lights\r\n//\tstatic Mth::Vector\t\ts_default_directions[MAX_DIFFUSE_LIGHTS];\r\n//\tstatic CBaseLightGroup\ts_default_colors;\r\n\tstatic CLightGroup\t\ts_default_lights;\r\n\r\n}; // class CLightGroup\r\n\r\n// Inline functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Vector &\t\tCLightGroup::GetDirection(int idx) const\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\tif (m_flags & (mUSE_DIFFUSE_0 << idx))\r\n\t{\r\n\t\treturn m_light_vector[idx];\r\n\t} else {\r\n\t\treturn s_default_lights.m_light_vector[idx];\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Vector &\t\tCLightGroup::GetBaseAmbientColor() const\r\n{\r\n\tif (m_flags & mUSE_AMBIENT)\r\n\t{\r\n\t\treturn m_ambient_base_color;\r\n\t} else {\r\n\t\treturn s_default_lights.m_ambient_base_color;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Vector &\t\tCLightGroup::GetBaseDiffuseColor(int idx) const\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\tif (m_flags & (mUSE_DIFFUSE_0 << idx))\r\n\t{\r\n\t\treturn m_diffuse_base_color[idx];\r\n\t} else {\r\n\t\treturn s_default_lights.m_diffuse_base_color[idx];\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Vector &\t\tCLightGroup::GetAmbientColor() const\r\n{\r\n\tif (m_flags & (mUSE_AMBIENT | mMODULATING_AMBIENT))\r\n\t{\r\n\t\treturn m_ambient_mod_color;\r\n\t} else {\r\n\t\treturn s_default_lights.m_ambient_base_color;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Vector &\t\tCLightGroup::GetDiffuseColor(int idx) const\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\tif (m_flags & ((mUSE_DIFFUSE_0 | mMODULATING_DIFFUSE_0) << idx))\r\n\t{\r\n\t\treturn m_diffuse_mod_color[idx];\r\n\t} else {\r\n\t\treturn s_default_lights.m_diffuse_base_color[idx];\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCLightGroup::SetDirection(int idx, const Mth::Vector & direction)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\t//Dbg_Assert(m_flags & (mUSE_DIFFUSE_0 << idx));\r\n\tm_flags |= (mUSE_DIFFUSE_0 << idx);  // turn on light if it isn't already on\r\n\r\n\tm_light_vector[idx] = direction;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCLightGroup::SetBaseAmbientColor(const Mth::Vector & color)\r\n{\r\n\t//Dbg_Assert(m_flags & mUSE_AMBIENT);\r\n// Mick:  turning on and off lights should be done ABOVE the p_line\r\n// Mick:\tm_flags |= mUSE_AMBIENT;\t\t// turn on light if it isn't already on\r\n\r\n\tm_ambient_base_color = color;\r\n\r\n\tif (!(m_flags & mMODULATING_AMBIENT))\r\n\t{\r\n\t\tm_ambient_mod_color = color;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCLightGroup::SetBaseDiffuseColor(int idx, const Mth::Vector & color)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\t//Dbg_Assert(m_flags & (mUSE_DIFFUSE_0 << idx));\r\n// Mick:  turning on and off lights should be done ABOVE the p_line\r\n// Mick:\tm_flags |= (mUSE_DIFFUSE_0 << idx);  // turn on light if it isn't already on\r\n\r\n\tm_diffuse_base_color[idx] = color;\r\n\r\n\tif (!(m_flags & (mMODULATING_DIFFUSE_0 << idx)))\r\n\t{\r\n\t\tm_diffuse_mod_color[idx] = color;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCLightGroup::EnableAmbientLight(bool enable)\r\n{\r\n\tif (enable)\r\n\t{\r\n\t\tm_flags |= mUSE_AMBIENT;\r\n\t} else {\r\n\t\tm_flags &= ~mUSE_AMBIENT;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCLightGroup::EnableDiffuseLight(int idx, bool enable)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\tif (enable)\r\n\t{\r\n\t\tm_flags |= (mUSE_DIFFUSE_0 << idx);\r\n\t} else {\r\n\t\tm_flags &= ~(mUSE_DIFFUSE_0 << idx);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\t\tCLightGroup::IsAmbientLightEnabled() const\r\n{\r\n\treturn (m_flags & mUSE_AMBIENT);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\t\tCLightGroup::IsDiffuseLightEnabled(int idx) const\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\treturn (m_flags & (mUSE_DIFFUSE_0 << idx));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\t\tCLightGroup::SetAmbientBrightness(float brightness)\r\n{\r\n\tm_ambient_mod_color = GetBaseAmbientColor() * brightness;\r\n\r\n\tm_flags |= mMODULATING_AMBIENT;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\t\tCLightGroup::SetDiffuseBrightness(int idx, float brightness)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\tm_diffuse_mod_color[idx] = GetBaseDiffuseColor(idx) * brightness;\r\n\r\n\tm_flags |= (mMODULATING_DIFFUSE_0 << idx);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Vector &\t\tCLightGroup::sGetDefaultDirection(int idx)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\treturn s_default_lights.m_light_vector[idx];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Vector &\t\tCLightGroup::sGetDefaultAmbientColor()\r\n{\r\n\treturn s_default_lights.m_ambient_base_color;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Vector &\t\tCLightGroup::sGetDefaultDiffuseColor(int idx)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\treturn s_default_lights.m_diffuse_base_color[idx];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCLightGroup::sSetDefaultDirection(int idx, const Mth::Vector & direction)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\ts_default_lights.m_light_vector[idx] = direction;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCLightGroup::sSetDefaultAmbientColor(const Mth::Vector & color)\r\n{\r\n\ts_default_lights.m_ambient_base_color = color;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCLightGroup::sSetDefaultDiffuseColor(int idx, const Mth::Vector & color)\r\n{\r\n\tDbg_Assert(idx < MAX_DIFFUSE_LIGHTS);\r\n\r\n\ts_default_lights.m_diffuse_base_color[idx] = color;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n\r\n#endif // __LIGHT_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/line.cpp",
    "content": "#include <core/defines.h>\r\n#include \"line.h\"\r\n#include \"render.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n#include \"sprite.h\"\r\n#include \"switches.h\"\r\n#include \"vu1code.h\"\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\nvoid BeginLines2D(uint32 rgba)\r\n{\r\n\t// dma tag\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\r\n\tvu1::Buffer = vu1::Loc;\r\n\r\n\t// GS context\r\n\tgs::BeginPrim(ABS,0,0);\r\n\tgs::Reg1(gs::ALPHA_1, PackALPHA(0,1,0,1,0));\r\n\tgs::Reg1(gs::RGBAQ,   (uint64)rgba);\r\n\tgs::EndPrim(0);\r\n\r\n\t// unpack giftag\r\n\tvif::UNPACK(0, V4_32, 1, ABS, UNSIGNED, 0);\r\n\tgif::BeginTagImmediate(gs::XYZ2, 1, PACKED, LINE|ABE, 1, VU1_ADDR(GSPrim));\r\n\r\n\t// begin unpack for coordinates\r\n\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, 1);\r\n}\r\n\r\n\r\n\r\nvoid DrawLine2D(float x0, float y0, float z0, float x1, float y1, float z1)\r\n{\r\n\tvif::StoreV4_32(XOFFSET+(sint32)((x0 * SDraw2D::GetScreenScaleX() * 16.0f)),\r\n\t\t\t\t\tYOFFSET+(sint32)((y0 * SDraw2D::GetScreenScaleY() * 16.0f)),0xFFFFFF,0);\r\n\tvif::StoreV4_32(XOFFSET+(sint32)((x1 * SDraw2D::GetScreenScaleX() * 16.0f)),\r\n\t\t\t\t\tYOFFSET+(sint32)((y1 * SDraw2D::GetScreenScaleY() * 16.0f)),0xFFFFFF,0);\r\n\r\n\tif (((dma::pLoc - gif::pTag)>>4) >= 250)\r\n\t{\r\n\t\tvif::EndUNPACK();\r\n\t\tgif::EndTagImmediate(1);\r\n\t\tvif::MSCAL(VU1_ADDR(Parser));\r\n\t\tvif::UNPACK(0, V4_32, 1, ABS, UNSIGNED, 0);\r\n\t\tgif::BeginTagImmediate(gs::XYZ2, 1, PACKED, LINE|ABE, 1, VU1_ADDR(GSPrim));\r\n\t\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, 1);\r\n\t}\r\n\r\n}\r\n\r\n\r\nvoid EndLines2D(void)\r\n{\r\n\tvif::EndUNPACK();\r\n\tgif::EndTagImmediate(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n\tdma::EndTag();\r\n}\r\n\r\n\r\n\r\nvoid BeginLines3D(uint32 rgba)\r\n{\r\n\t\r\n\t// dma tag  - this will encompass ALL the lines up to the next EndLines3D\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\r\n\tvu1::Buffer = vu1::Loc;\r\n\r\n\t// VU context, uploading the view transform data\r\n\tvu1::BeginPrim(ABS, VU1_ADDR(L_VF10));\t  \t// Begin packed register upload to VF10 \r\n\t//vu1::StoreVec(*(Vec *)&render::ViewportScale);\t\t\t// VF10\r\n\tvu1::StoreVec(*(Vec *)&render::InverseIntViewportScale);\t\t\t// VF10\r\n\r\n//\tvu1::StoreVec(ViewportOffset);\t\t\t\t\t\t\t// VF11\r\n\r\n//\tfloat z_push = 2.40741243e-34;\t\t\t\t\t\t\t// was e-35\r\n//\tvif::StoreV4_32F(render::ViewportOffset[0],\r\n//\t\t\t\t\t render::ViewportOffset[1],\r\n//\t\t\t\t\t render::ViewportOffset[2]+z_push,\r\n//\t\t\t\t\t render::ViewportOffset[3]);\t\t\t// VF11\r\n\t\r\n\tMth::Vector temp_inv_viewport_offset;\r\n\ttemp_inv_viewport_offset[0] = -render::InverseIntViewportScale[0] * render::IntViewportOffset[0] * render::InverseIntViewportScale[3];\r\n\ttemp_inv_viewport_offset[1] = -render::InverseIntViewportScale[1] * render::IntViewportOffset[1] * render::InverseIntViewportScale[3];\r\n\ttemp_inv_viewport_offset[2] = -render::InverseIntViewportScale[2] * (render::IntViewportOffset[2]+1.0e-34f) * render::InverseIntViewportScale[3];\r\n\ttemp_inv_viewport_offset[3] = 0.0f;\r\n\tvu1::StoreVec(*(Vec *)&temp_inv_viewport_offset);\r\n\r\n\tvu1::StoreMat(*(Mat *)&render::AdjustedWorldToIntViewport);\t// VF12-15\r\n\tvu1::EndPrim(0);\t\t\t\t\t\t\t\t\t\t// End upload\r\n\r\n\t// GS context, setting color\r\n\tgs::BeginPrim(ABS,0,0);\r\n\tgs::Reg1(gs::ALPHA_1, PackALPHA(0,1,0,1,0));\r\n\tgs::Reg1(gs::RGBAQ,   (uint64)rgba);\r\n\tgs::EndPrim(0);\r\n\r\n\t// all lines will be rendered with simple culling\r\n\tvif::ITOP(CULL);\r\n\r\n\t// unpack giftag\r\n\tvif::UNPACK(0, V4_32, 1, ABS, UNSIGNED, 0);\r\n\tgif::BeginTagImmediate(gs::XYZ2, 1, PACKED, LINE|ABE, 1, VU1_ADDR(Line));\r\n\r\n\t// offset mode\r\n\tvif::STMOD(1);\r\n\r\n\t// begin unpack for coordinates\r\n\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, 1);\r\n}\r\n\r\n\r\nvoid\tChangeLineColor(uint32 rgba)\r\n{\r\n\r\n// End the previous batch of lines\r\n\t\tEndLines3D();\r\n\t\t\r\n// Like starting a new batch, but witout the VU context\t\t\r\n\t\tdma::BeginTag(dma::cnt, 0);\r\n\r\n\t\t// GS context\r\n\t\t// Sets up the GS registers for color and alpha\r\n\t\tgs::BeginPrim(ABS,0,0);\r\n\t\tgs::Reg1(gs::ALPHA_1, PackALPHA(0,1,0,1,0));\r\n\t\tgs::Reg1(gs::RGBAQ,   (uint64)rgba);\r\n\t\tgs::EndPrim(0);\r\n\t\t\r\n\t\tvif::UNPACK(0, V4_32, 1, ABS, UNSIGNED, 0);\r\n\t\tgif::BeginTagImmediate(gs::XYZ2, 1, PACKED, LINE|ABE, 1, VU1_ADDR(Line));\r\n\t\tvif::STMOD(1);\r\n\t\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, 1);\r\n\t\r\n}\r\n\r\n\r\nvoid DrawLine3D(float x0, float y0, float z0, float x1, float y1, float z1)\r\n{\r\n\tvif::StoreV4_32((sint32)(x0*SUB_INCH_PRECISION), (sint32)(y0*SUB_INCH_PRECISION), (sint32)(z0*SUB_INCH_PRECISION), 0);\r\n\tvif::StoreV4_32((sint32)(x1*SUB_INCH_PRECISION), (sint32)(y1*SUB_INCH_PRECISION), (sint32)(z1*SUB_INCH_PRECISION), 0);\r\n\r\n\tif (((dma::pLoc - gif::pTag)>>4) >= 250)\r\n\t{\r\n\t\tvif::EndUNPACK();\r\n\t\tgif::EndTagImmediate(1);\r\n\t\tvif::STMOD(0);\r\n\t\tvif::MSCAL(VU1_ADDR(Parser));\r\n\t\tvif::UNPACK(0, V4_32, 1, ABS, UNSIGNED, 0);\r\n\t\tgif::BeginTagImmediate(gs::XYZ2, 1, PACKED, LINE|ABE, 1, VU1_ADDR(Line));\r\n\t\tvif::STMOD(1);\r\n\t\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, 1);\r\n\t}\r\n\r\n}\r\n\r\n\r\nvoid EndLines3D(void)\r\n{\r\n\tvif::EndUNPACK();\r\n\r\n\tif (vif::UnpackSize)\r\n\t{\r\n\t\tgif::EndTagImmediate(1);\r\n\t\tvif::STMOD(0);\r\n\t\tvif::MSCAL(VU1_ADDR(Parser));\r\n\t}\r\n\telse\r\n\t\tdma::pLoc -= 24;\r\n\r\n\tdma::EndTag();\r\n}\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/line.h",
    "content": "#ifndef __LINE_H\r\n#define __LINE_H\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\nvoid BeginLines2D(uint32 rgba);\r\nvoid DrawLine2D(float x0, float y0, float z0, float x1, float y1, float z1);\r\nvoid EndLines2D(void);\r\nvoid BeginLines3D(uint32 rgba);\r\nvoid ChangeLineColor(uint32 rgba);\r\nvoid DrawLine3D(float x0, float y0, float z0, float x1, float y1, float z1);\r\nvoid EndLines3D(void);\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n#endif // __LINE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/loadscreen.cpp",
    "content": "#include <libgraph.h>\r\n#include <libdma.h>\r\n#include <core\\math.h>\r\n#include <core\\defines.h>\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n#include \"dmacalls.h\"\r\n#include \"group.h\"\r\n#include \"nx_init.h\"\r\n#include \"render.h\"\r\n#include \"interrupts.h\"\r\n#include \"switches.h\"\r\n#include \"sprite.h\"\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n// Callback handler for loading bar\r\nstatic int s_loading_bar_handler_id = -1;\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// Loading bar\r\n\r\nstatic uint128 p_VifData[64];\r\n\r\nint\t\t\tgLoadBarTotalFrames;\t\t// Number of frames it takes for loading bar to go to 100%\r\nint\t\t\tgLoadBarNumFrames;\t\t\t// Number of frames so far\r\nfloat\t\tgLoadBarX = 150.0f;\t\t\t// Bar position\r\nfloat\t\tgLoadBarY = 400.0f;\r\nfloat\t\tgLoadBarWidth = 340.0f;\t\t// Bar size\r\nfloat\t\tgLoadBarHeight = 20.0f;\r\nint\t\t\tgLoadBarStartColor[4] = {  255,    0,   0,  128 };\r\nint\t\t\tgLoadBarDeltaColor[4] = { -255,  255,   0,  128 };\r\nfloat\t\tgLoadBarBorderWidth = 5.0f;\t// Border width\r\nfloat\t\tgLoadBarBorderHeight = 5.0f;\t// Border height\r\nint\t\t\tgLoadBarBorderColor[4] = {  40, 40, 40, 128 };\r\n\r\n\r\nstatic int s_loading_bar_handler(int ca)\r\n{\r\n\t// If writing to a variable, make sure it is volatile (or game will crash)\r\n\t\r\n\t// inc frame count    \r\n\tgLoadBarNumFrames++;\r\n\r\n\t//-----------------------------------------\r\n\t//\t\tDRAW BAR\r\n\t//-----------------------------------------\r\n\tsceGsSyncPath(0, 0);\r\n\tif (sGroup::pRenderGroup)\t// Can't handle this condition\r\n\t{\r\n\t\tExitHandler();\r\n\t\treturn 0;\r\n\t}\r\n\r\n\t// Save floats\r\n    unsigned int floatBuffer[32];\r\n    saveFloatRegs(floatBuffer);\r\n\r\n\t// Save all these because we could already be in the middle of building packets\r\n\tuint8*\told_dma_loc = dma::pLoc;\t\t  \r\n\tuint8*\told_dma_tag = dma::pTag;\r\n\tuint8*\told_gif_tag = gif::pTag;\r\n\tuint8*\told_vif_code = vif::pVifCode;\r\n\r\n\tdma::pLoc = (uint8 *) p_VifData;\r\n\r\n\t// begin Path3 subroutine\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\r\n\t// send everything PATH3\r\n\t//vif::BeginDIRECT();\r\n\tvif::NOP();\r\n\tvif::NOP();\r\n\r\n\t// GS prim sets up all the registers\r\n\tgif::BeginTag2(gs::A_D, 1, PACKED, 0, 0);\r\n\tgs::Reg2(gs::ALPHA_1,\t\tPackALPHA(0,1,0,1,128));\r\n\tgs::Reg2(gs::CLAMP_1,\t\tPackCLAMP(REPEAT,REPEAT,0,0,0,0));\r\n\tgs::Reg2(gs::COLCLAMP,\t\tPackCOLCLAMP(1));\r\n\t//gs::Reg2(gs::DTHE,\t\t\tPackDTHE(0));\r\n\tgs::Reg2(gs::DIMX,\t\t\tPackDIMX(-4,0,-3,1,2,-2,3,-1,-3,1,-4,0,3,-1,2,-2));\r\n\tgs::Reg2(gs::DTHE,\t\t\tPackDTHE(1));\r\n\t//gs::Reg2(gs::FBA_1,\t\t\tPackFBA(0));\r\n\tgs::Reg2(gs::FRAME_1,\t\tPackFRAME(DISPLAY_START,HRES/64,PSMCT16S,0xFF000000));\t// draw directly to display buffer\r\n\tgs::Reg2(gs::PRMODECONT,\tPackPRMODECONT(1));\r\n\tgs::Reg2(gs::SCANMSK,\t\tPackSCANMSK(0));\r\n\tgs::Reg2(gs::SCISSOR_1,\t \tPackSCISSOR(0,HRES - 1,0,VRES - 1));\r\n\tgs::Reg2(gs::TEST_1,\t\tPackTEST(0,0,0,0,0,0,1,ZALWAYS));\r\n\tgs::Reg2(gs::XYOFFSET_1,\tPackXYOFFSET(0x0, 0x0));\r\n\tgs::Reg2(gs::ZBUF_1,\t\tPackZBUF(ZBUFFER_START,PSMZ24,1));\r\n\tgif::EndTag2(1);\r\n\r\n\t// Find scaled values (mainly for PAL)\r\n\tNxPs2::SDraw2D::CalcScreenScale();\t\t// May not have been calculated yet\r\n\tfloat scaledBarX = gLoadBarX * NxPs2::SDraw2D::GetScreenScaleX();\r\n\tfloat scaledBarY = gLoadBarY * NxPs2::SDraw2D::GetScreenScaleY();\r\n\tfloat scaledBarWidth = gLoadBarWidth * NxPs2::SDraw2D::GetScreenScaleX();\r\n\tfloat scaledBarHeight = gLoadBarHeight * NxPs2::SDraw2D::GetScreenScaleY();\r\n\tfloat scaledBarBorderWidth = gLoadBarBorderWidth * NxPs2::SDraw2D::GetScreenScaleX();\r\n\tfloat scaledBarBorderHeight = gLoadBarBorderHeight * NxPs2::SDraw2D::GetScreenScaleY();\r\n\r\n\tint cur_width = (int) ((scaledBarWidth - 1.0f) * 16.0f);\r\n\tif (gLoadBarNumFrames < gLoadBarTotalFrames)\r\n\t{\r\n\t\tcur_width = (cur_width * gLoadBarNumFrames) / gLoadBarTotalFrames;\r\n\t}\r\n\r\n\tint x1 = (int) (scaledBarX * 16.0f);\r\n\tint y1 = (int) (scaledBarY * 16.0f);\r\n\tint x2 = x1 + cur_width;\r\n\tint y2 = y1 + (int) ((scaledBarHeight - 1.0f) * 16.0f);\r\n\r\n\tint end_color[4];\r\n\tif (gLoadBarNumFrames < gLoadBarTotalFrames)\r\n\t{\r\n\t\tend_color[0] = gLoadBarStartColor[0] + ((gLoadBarDeltaColor[0] * gLoadBarNumFrames) / gLoadBarTotalFrames);\r\n\t\tend_color[1] = gLoadBarStartColor[1] + ((gLoadBarDeltaColor[1] * gLoadBarNumFrames) / gLoadBarTotalFrames);\r\n\t\tend_color[2] = gLoadBarStartColor[2] + ((gLoadBarDeltaColor[2] * gLoadBarNumFrames) / gLoadBarTotalFrames);\r\n\t\tend_color[3] = gLoadBarStartColor[3] + ((gLoadBarDeltaColor[3] * gLoadBarNumFrames) / gLoadBarTotalFrames);\r\n\t} else {\r\n\t\tend_color[0] = gLoadBarStartColor[0] + gLoadBarDeltaColor[0];\r\n\t\tend_color[1] = gLoadBarStartColor[1] + gLoadBarDeltaColor[1];\r\n\t\tend_color[2] = gLoadBarStartColor[2] + gLoadBarDeltaColor[2];\r\n\t\tend_color[3] = gLoadBarStartColor[3] + gLoadBarDeltaColor[3];\r\n\t}\r\n\r\n\tint border_x1 = x1 - (int) (scaledBarBorderWidth * 16.0f);\r\n\tint border_y1 = y1 - (int) (scaledBarBorderHeight * 16.0f);\r\n\tint border_x2 = x1 + (int) (((scaledBarWidth - 1) * 16.0f) + (scaledBarBorderWidth * 16.0f));\r\n\tint border_y2 = y2 + (int) (scaledBarBorderHeight * 16.0f);\r\n\r\n\tgif::BeginTag2(gs::XYZ2<<4|gs::RGBAQ, 2, PACKED, TRISTRIP|IIP|FST|AA1/*|ABE*/, 1);\r\n\r\n\t// Border\r\n\tvif::StoreV4_32(gLoadBarBorderColor[0], gLoadBarBorderColor[1],\r\n\t\t\t\t\tgLoadBarBorderColor[2], gLoadBarBorderColor[3]);\t// RGBAQ\r\n\tvif::StoreV4_32(border_x1, border_y1, 0, 0x8000);\t\t\t\t\t// XYZ2\r\n\tvif::StoreV4_32(gLoadBarBorderColor[0], gLoadBarBorderColor[1],\r\n\t\t\t\t\tgLoadBarBorderColor[2], gLoadBarBorderColor[3]);\t// RGBAQ\r\n\tvif::StoreV4_32(border_x1, border_y2, 0, 0x8000);\t\t\t\t\t// XYZ2\r\n\tvif::StoreV4_32(gLoadBarBorderColor[0], gLoadBarBorderColor[1],\r\n\t\t\t\t\tgLoadBarBorderColor[2], gLoadBarBorderColor[3]);\t// RGBAQ\r\n\tvif::StoreV4_32(border_x2, border_y1, 0, 0);\t\t\t\t\t\t// XYZ2\r\n\tvif::StoreV4_32(gLoadBarBorderColor[0], gLoadBarBorderColor[1],\r\n\t\t\t\t\tgLoadBarBorderColor[2], gLoadBarBorderColor[3]);\t// RGBAQ\r\n\tvif::StoreV4_32(border_x2, border_y2, 0, 0);\t\t\t\t\t\t// XYZ2\r\n\r\n\t// Bar\r\n\tvif::StoreV4_32(gLoadBarStartColor[0], gLoadBarStartColor[1],\r\n\t\t\t\t\tgLoadBarStartColor[2], gLoadBarStartColor[3]);\t\t\t// RGBAQ\r\n\tvif::StoreV4_32( x1,  y1, 0, 0x8000);\t\t\t\t\t\t\t\t\t// XYZ2\r\n\tvif::StoreV4_32(gLoadBarStartColor[0], gLoadBarStartColor[1],\r\n\t\t\t\t\tgLoadBarStartColor[2], gLoadBarStartColor[3]);\t\t\t// RGBAQ\r\n\tvif::StoreV4_32( x1,  y2, 0, 0x8000);\t\t\t\t\t\t\t\t\t// XYZ2\r\n\tvif::StoreV4_32(end_color[0], end_color[1], end_color[2], end_color[3]);// RGBAQ\r\n\tvif::StoreV4_32( x2,  y1, 0, 0);\t\t\t\t\t\t\t\t\t\t// XYZ2\r\n\tvif::StoreV4_32(end_color[0], end_color[1], end_color[2], end_color[3]);// RGBAQ\r\n\tvif::StoreV4_32( x2,  y2, 0, 0);\t\t\t\t\t\t\t\t\t\t// XYZ2\r\n\r\n\tgif::EndTag2(1);\r\n\r\n\t//vif::EndDIRECT();\r\n\r\n\tdma::EndTag();\r\n\r\n\t// done\r\n\tiFlushCache(WRITEBACK_DCACHE);\r\n\r\n\t// kick dma to upload textures from this group\r\n\t*D2_QWC = 0;\t\t\t\t\t\t// must zero QWC because the first action will be to use current MADR & QWC\r\n\t*D2_TADR = (uint)p_VifData;\t\t\t// address of 1st tag\r\n\t*D2_CHCR = 0x145;\t\t\t\t\t// start transfer, tte=1, chain mode, from memory\r\n\tsceGsSyncPath(0, 0);\r\n\r\n\t// Restore used variables\r\n\tdma::pLoc = old_dma_loc;\t\t  \r\n\tdma::pTag = old_dma_tag;\r\n\tgif::pTag = old_gif_tag;\r\n\tvif::pVifCode = old_vif_code;\r\n\r\n    // restore floats\r\n    restoreFloatRegs(floatBuffer);\r\n\r\n\tExitHandler();\t\t\t// Mick: Sony requires interrupts to end with an ExitHandler() call\r\n\t\t\t\t\t\t\t// this enables interrupts\t\r\n\treturn 0;\r\n}\r\n\r\nvoid StartLoadingBar(int frames)\r\n{\r\n\t//Dbg_Assert(s_loading_bar_handler_id < 0);\r\n\r\n\tif (s_loading_bar_handler_id < 0)\r\n\t{\r\n\t\tgLoadBarTotalFrames = frames;\r\n\t\tgLoadBarNumFrames = 0;\r\n\r\n\t\ts_loading_bar_handler_id = AddIntcHandler(INTC_VBLANK_S, s_loading_bar_handler, -1);\r\n\t\tDbg_MsgAssert (( s_loading_bar_handler_id >= 0 ),( \"Failed to add loading bar handler\" )); \r\n\t}\r\n}\r\n\r\nvoid RemoveLoadingBar()\r\n{\r\n\tif (s_loading_bar_handler_id >= 0)\r\n\t{\r\n\t\tRemoveIntcHandler(INTC_VBLANK_S, s_loading_bar_handler_id);\r\n\t\ts_loading_bar_handler_id = -1;\r\n\t}\r\n}\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/loadscreen.h",
    "content": "#ifndef __NXPS2_LOADSCREEN_H\r\n#define __NXPS2_LOADSCREEN_H\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n// Enable and disable loading bar interrupt\r\nvoid StartLoadingBar(int frames);\r\nvoid RemoveLoadingBar();\r\n\r\n\r\n// Loading bar data\r\nextern int\t\tgLoadBarTotalFrames;\t// Number of frames it takes for loading bar to go to 100%\r\nextern int\t\tgLoadBarNumFrames;\t\t// Number of frames so far\r\nextern float\tgLoadBarX;\t\t\t\t// Bar position\r\nextern float\tgLoadBarY;\r\nextern float\tgLoadBarWidth;\t\t\t// Bar size\r\nextern float\tgLoadBarHeight;\r\nextern int\t\tgLoadBarStartColor[4];\t// 0 = red; 1 = green; 2 = blue; 3 = alpha\r\nextern int\t\tgLoadBarDeltaColor[4];\t// 0 = delta red; 1 = delta green; 2 = delta blue; 3 = delta alpha\r\nextern float\tgLoadBarBorderWidth;\t// Border width\r\nextern float\tgLoadBarBorderHeight;\t// Border height\r\nextern int\t\tgLoadBarBorderColor[4];\t// 0 = red; 1 = green; 2 = blue; 3 = alpha\r\n\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n#endif // __NXPS2_LOADSCREEN_H\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/maintest.cpp",
    "content": "#include <stdio.h>\r\n#include <eekernel.h>\r\n#include <sifrpc.h>\r\n#include <sifdev.h>\r\n#include <libpad.h>\r\n#include <libgraph.h>\r\n#include <core/defines.h>\r\n#include <sys/profiler.h>\r\n#include \"render.h\"\r\n#include \"line.h\"\r\n#include \"nx_init.h\"\r\n#include \"chars.h\"\r\n#include \"group.h\"\r\n#include \"sprite.h\"\r\n#include \"switches.h\"\r\n#include\t\"gfx/nx.h\"\r\n#include\t\"gfx/NxParticleMgr.h\"\r\n#include\t\"gfx/NxTextured3dPoly.h\"\r\n#include\t\"gfx/ngps/p_NxLightMan.h\"\r\n\r\n\r\nnamespace Sys\r\n{\r\n\textern void Render_Profiler();\t\t\r\n}\r\n\r\n\r\nnamespace Gfx\r\n{\r\n\tvoid DebugGfx_Draw( void );\r\n}\r\n\r\nnamespace Tmr\r\n{\r\n\tvoid VSync();\t\r\n}\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n/*\r\nvoid LineTest(void);\r\nvoid CharTest(void);\r\n*/\r\n\r\nSFont *pMyFont1, *pMyFont2;\r\n\r\n\r\n\r\nint maintest(int argc, char *argv[])\r\n{\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n\r\nvoid test_init()\r\n{\r\n\tInitialiseEngine();\r\n}\r\n\r\n// I'm forward declaring this, so the compiler does not try to inline it\r\nvolatile sGroup *get_render_group();\r\nvoid\tWaitForRendering();\r\nvoid patch_texture_dma();\r\n\r\n\r\nvoid\ttest_render_start_frame()\r\n{\r\n\r\n//------------------------------------------------------------\r\n\r\n#if 0\r\n// MICK: Note, this is done in the main loop now, for profiling reasons\r\n\t// wait for rendering completion\r\n\tNxPs2::WaitForRendering();\r\n\t// wait for vsync\r\n\tTmr::VSync();\r\n#endif\r\n  \r\n\t// now the dma list has finished, we can swap dma buffers\r\n\trender::Field ^= 1;\r\n\r\n\t// kick off dma from previous frame (if there was one)\r\n\tif (render::Frame > 0)\r\n\t\tSendDisplayList();\r\n\r\n}\r\n\r\n\r\n\r\n// wait for pRenderGroup to be null\r\n// note curius use of a seperate function to read pRenderGroup\r\n// due to compler getting confused if we just read it directly\r\n// even though it is volatile, it does not re-read it\t\t\t   \r\nvoid\tWaitForRendering()\r\n{\r\n\twhile (get_render_group())\r\n\t\t;\r\n\r\n\t// Update the 2D DMA lists\r\n\tUpdate2DDMA();\r\n\t\r\n}\r\n\r\nvoid StuffAfterGSFinished()\r\n{\r\n\r\n\tNx::CPs2LightManager::sUpdateEngine();\r\n\r\n\t// particle systems effectively have their transform double-buffered for dma purposes\r\n\t// so now is the time to do the buffer flip by updating the transforms\r\n\tNx::CEngine::sGetParticleManager()->UpdateParticles();\r\n\r\n\t// patch up texture DMA\r\n\tpatch_texture_dma();\t\r\n\r\n\r\n}\r\n\r\n\t\t\t\t\t\r\nvolatile sGroup *get_render_group()\r\n{\r\n\treturn sGroup::pRenderGroup;\r\n}\r\n\r\n\r\n\r\nvoid\ttest_render(Mth::Matrix* camera_orient, Mth::Vector* camera_pos, float view_angle, float screen_aspect)\r\n{\r\n\t//RenderPrologue();\t \t// should this be in test_render_start_frame? (Garrett: Answer is no, it won't work)\r\n\r\n\t// render everything\r\n\tRenderWorld(camera_orient, camera_pos, view_angle, screen_aspect);\r\n\t//LineTest();\r\n\t//CharTest();\r\n}\r\n\r\nvoid\ttest_render_end_frame()\r\n{\r\n\tSetTextWindow(0,HRES-1,0,VRES-1);\t\t\t\t\t\t// a full-screen clipping window\r\n\tGfx::DebugGfx_Draw( );\r\n\r\n\t// Make sure 2D VRAM is up-to-date\r\n// Mick: Moved to CEngine::s_plat_render_world, which is earlier in the frame\r\n// so it happens before we draw the texture splats.\r\n//\tReallocate2DVRAM();\r\n\r\n\tSDraw2D::DrawAll();\r\n\t#ifdef\t\t__USE_PROFILER__\r\n\tSys::Render_Profiler();\t\t\r\n\t#endif\r\n\tRenderEpilogue();\r\n\t\r\n\t// set frame for next render\r\n\trender::Frame++;\r\n}\r\n\r\n\r\n\r\nvoid LineTest(void)\r\n{\r\n/*\t\r\n\tint xo,yo,zo;\r\n\r\n\t// do some 3D lines with r=0xFF, g=0x00, b=0x00, a=0x80\r\n\tBeginLines3D(0x800000FF);\r\n\r\n\tfor (xo=-130; xo<=110; xo+=80)\r\n\t\tfor (yo=-90; yo<=70; yo+=80)\r\n\t\t\tfor (zo=-130; zo<=110; zo+=80)\r\n\t\t\t{\r\n\t\t\t\tDrawLine3D(-10+xo, 10+yo, 10+zo, 10+xo, 10+yo, 10+zo);\r\n\t\t\t\tDrawLine3D(-10+xo,-10+yo, 10+zo, 10+xo,-10+yo, 10+zo);\r\n\t\t\t\tDrawLine3D(-10+xo, 10+yo,-10+zo, 10+xo, 10+yo,-10+zo);\r\n\t\t\t\tDrawLine3D(-10+xo,-10+yo,-10+zo, 10+xo,-10+yo,-10+zo);\r\n\t\t\t\t\r\n\t\t\t\tDrawLine3D(-10+xo, 10+yo, 10+zo,-10+xo,-10+yo, 10+zo);\r\n\t\t\t\tDrawLine3D( 10+xo, 10+yo, 10+zo, 10+xo,-10+yo, 10+zo);\r\n\t\t\t\tDrawLine3D(-10+xo, 10+yo,-10+zo,-10+xo,-10+yo,-10+zo);\r\n\t\t\t\tDrawLine3D( 10+xo, 10+yo,-10+zo, 10+xo,-10+yo,-10+zo);\r\n\t\t\t\t\r\n\t\t\t\tDrawLine3D(-10+xo, 10+yo, 10+zo,-10+xo, 10+yo,-10+zo);\r\n\t\t\t\tDrawLine3D( 10+xo, 10+yo, 10+zo, 10+xo, 10+yo,-10+zo);\r\n\t\t\t\tDrawLine3D(-10+xo,-10+yo, 10+zo,-10+xo,-10+yo,-10+zo);\r\n\t\t\t\tDrawLine3D( 10+xo,-10+yo, 10+zo, 10+xo,-10+yo,-10+zo);\r\n\t\t\t}\r\n\r\n\tEndLines3D();\r\n\r\n\t// do some 2D lines with r=0xFF, g=0xFF, b=0xFF, a=0x80\r\n\tBeginLines2D(0x80FFFFFF);\r\n\r\n\t// \"LINE\"\r\n\tDrawLine2D(100,100,0, 100,150,0);\r\n\tDrawLine2D(100,150,0, 150,150,0);\r\n\tDrawLine2D(160,100,0, 160,150,0);\r\n\tDrawLine2D(170,100,0, 170,150,0);\r\n\tDrawLine2D(170,100,0, 220,150,0);\r\n\tDrawLine2D(220,100,0, 220,150,0);\r\n\tDrawLine2D(230,100,0, 230,150,0);\r\n\tDrawLine2D(230,100,0, 280,100,0);\r\n\tDrawLine2D(230,125,0, 260,125,0);\r\n\tDrawLine2D(230,150,0, 280,150,0);\r\n\r\n\t// \"TEST\"\r\n\tDrawLine2D(320,100,0, 370,100,0);\r\n\tDrawLine2D(345,100,0, 345,150,0);\r\n\tDrawLine2D(380,100,0, 380,150,0);\r\n\tDrawLine2D(380,100,0, 430,100,0);\r\n\tDrawLine2D(380,125,0, 410,125,0);\r\n\tDrawLine2D(380,150,0, 430,150,0);\r\n\tDrawLine2D(440,100,0, 490,100,0);\r\n\tDrawLine2D(440,125,0, 490,125,0);\r\n\tDrawLine2D(440,150,0, 490,150,0);\r\n\tDrawLine2D(440,100,0, 440,125,0);\r\n\tDrawLine2D(490,125,0, 490,150,0);\r\n\tDrawLine2D(500,100,0, 550,100,0);\r\n\tDrawLine2D(525,100,0, 525,150,0);\r\n\r\n\tEndLines2D();\r\n*/\r\n}\r\n\r\n\r\n\r\n\r\nvoid CharTest(void)\r\n{\r\n#if 0\r\n\tfloat Width,Height;\r\n\r\n\tSetFont(\"small\");\r\n\tQueryString(\"Hello World\", &Width, &Height);\t// width and height in pixels\r\n\r\n\tSetTextWindow(0,639,0,447);\t\t\t\t\t\t// a full-screen clipping window\r\n\r\n\tBeginText(0x403070A0, 1.5);\t\t\t\t\t\t// r=0xA0, g=0x70, b=0x30, a=0x40, scale=1.5\r\n\tDrawString(\"Score\",  30, 30);\r\n\tDrawString(\"000000\", 100, 30);\r\n\tEndText();\r\n\r\n\tBeginText(0x40A06080, 1.5);\r\n\tDrawString(\"Skate4\", 520, 400);\r\n\tEndText();\r\n#endif\r\n}\r\n\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/material.cpp",
    "content": "#include <string.h>\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/memfile.h>\r\n#include \"texture.h\"\r\n#include \"material.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"gs.h\"\r\n#include \"scene.h\"\r\n#include \"switches.h\"\r\n\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n//----------------------------------------------------------------------------------------\r\n//\t\tL O A D   M A T E R I A L S\r\n//----------------------------------------------------------------------------------------\r\n\r\nvoid * LoadMaterials(void *pFile, sScene *pScene, uint32 texDictOffset)\r\n{\r\n\tsMaterial *pMat;\r\n\tsTexture *pTex;\r\n\tuint32 TextureChecksum, GroupChecksum;\r\n\tuint32 MXL, MMAG, MMIN, K, L, NumSeqs, seq, NumKeys;\r\n\tint i;\r\n\r\n\t// get number of materials\r\n\tMEM_Read(&pScene->NumMaterials, sizeof(uint32), 1, pFile);\r\n\r\n\t// allocate storage for materials\r\n\tpScene->pMaterials = (sMaterial *)Mem::Malloc(pScene->NumMaterials*sizeof(sMaterial));\r\n\tDbg_MsgAssert(pScene->pMaterials, (\"couldn't allocate memory for materials\"));\r\n\r\n\t// loop over materials\r\n\tfor (i=0,pMat=pScene->pMaterials; i<pScene->NumMaterials; i++,pMat++)\r\n\t{\r\n\t\t// get material checksum\r\n\t\tMEM_Read(&pMat->Checksum, sizeof(uint32), 1, pFile);\r\n\r\n\t\tif (sMaterial::Version >= 5)\r\n\t\t{\r\n\t\t\t// get material flags (moved up here in version 5)\r\n\t\t\tMEM_Read(&pMat->Flags, 1, sizeof(uint32), pFile);\r\n\t\t}\r\n\r\n\t\t// get Aref\r\n\t\tif (sMaterial::Version >= 2)\r\n\t\t{\r\n\t\t\tif (sMaterial::Version >= 3)\r\n\t\t\t{\r\n\t\t\t\tMEM_Read(&pMat->Aref, 1, 4, pFile);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMEM_Read(&pMat->Aref, 1, 1, pFile);\r\n\t\t\t}\r\n\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpMat->Aref = 1;\r\n\t\t}\r\n\r\n\t\tif (sMaterial::Version >= 5)\r\n\t\t{\r\n\t\t\tif (pMat->Flags & MATFLAG_ANIMATED_TEX)\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t/*\r\n\t\t\t\tNxAnimatedTexture* anim_tex;\r\n\t\r\n\t\t\t\tanim_tex = &material->m_Passes[0].m_AnimatedTexture;\r\n\t\t\t\tpOutFile->Write((const char*) &anim_tex->m_NumKeyframes, sizeof( int ), false);\r\n\t\t\t\tpOutFile->Write((const char*) &anim_tex->m_Period, sizeof( int ), false);\r\n\t\t\t\tpOutFile->Write((const char*) &anim_tex->m_Iterations, sizeof( int ), false);\r\n\t\t\t\tpOutFile->Write((const char*) &anim_tex->m_Phase, sizeof( int ), false);\r\n\t\t\t\tfor( j = 0; j < anim_tex->m_NumKeyframes; j++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tNxAnimatedTextureKeyframe* frame;\r\n\t\r\n\t\t\t\t\tframe = &anim_tex->m_Keyframes[j];\r\n\t\t\t\t\tpOutFile->Write((const char*) &frame->m_Time, sizeof( unsigned int ), false);\r\n\t\r\n\t\t\t\t\ttex_checksum = material->m_Passes[0].GetTextureChecksum( j, Utils::vPLATFORM_PS2 );\r\n\t\t\t\t\tpOutFile->Write((const char*) &tex_checksum, sizeof( unsigned long ), false);\r\n\t\t\t\t}*/\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// get texture checksum\r\n\t\t\t\tMEM_Read(&TextureChecksum, 1, sizeof(uint32), pFile);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// get texture checksum\r\n\t\t\tMEM_Read(&TextureChecksum, 1, sizeof(uint32), pFile);\r\n\t\t}\r\n\t\t\r\n\r\n\t\tif (sMaterial::Version >= 3)\r\n\t\t{\r\n\t\t\t// get group checksum\r\n\t\t\tMEM_Read(&GroupChecksum, 1, sizeof(uint32), pFile);\r\n\r\n\t\t\tGroupChecksum += texDictOffset;\r\n\t\t}\r\n\r\n\t\tif (sMaterial::Version < 5)\r\n\t\t{\r\n\t\t\t// get material flags (moved above in version 5 because the parser needs the flags\r\n\t\t\t// to correctly parse subsequent data\r\n\t\t\tMEM_Read(&pMat->Flags, 1, sizeof(uint32), pFile);\r\n\t\t}\r\n\r\n\t\t// get ALPHA register value\r\n\t\tMEM_Read(&pMat->RegALPHA, 1, sizeof(uint64), pFile);\r\n\r\n\t\t// get CLAMP register value\r\n\t\tif (sMaterial::Version >= 2)\r\n\t\t{\r\n\t\t\tuint32 ClampU,ClampV;\r\n\t\t\tMEM_Read(&ClampU, 1, sizeof(uint32), pFile);\r\n\t\t\tMEM_Read(&ClampV, 1, sizeof(uint32), pFile);\r\n\t\t\tpMat->RegCLAMP = PackCLAMP(ClampU,ClampV,0,0,0,0);\r\n\t\t}\r\n\t\telse\r\n\t\t\tpMat->RegCLAMP = PackCLAMP(REPEAT,REPEAT,0,0,0,0);\r\n\r\n\t\t// step past material colours, currently unsupported\r\n\t\tMEM_Seek(pFile, 36, SEEK_CUR);\r\n\r\n\t\t// step past uv wibble data, currently unsupported\r\n\t\tif (pMat->Flags & MATFLAG_UV_WIBBLE)\r\n\t\t{\r\n\t\t\tMEM_Seek(pFile, 40, SEEK_CUR);\r\n\t\t}\r\n\r\n\t\t// step past vc wibble data, currently unsupported\r\n\t\tif (pMat->Flags & MATFLAG_VC_WIBBLE)\r\n\t\t{\r\n\t\t\tMEM_Read(&NumSeqs, sizeof(uint32), 1, pFile);\r\n\t\t\tfor (seq=0; seq<NumSeqs; seq++)\r\n\t\t\t{ \r\n\t\t\t\tMEM_Read(&NumKeys, sizeof(uint32), 1, pFile);\r\n\t\t\t\tMEM_Seek(pFile, 20 * NumKeys, SEEK_CUR);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// if textured...\r\n\t\tif (TextureChecksum)\r\n\t\t{\r\n\t\t\t// resolve texture checksum\r\n\t\t\tif (sMaterial::Version >= 3)\r\n\t\t\t{\r\n\t\t\t\tpTex = ResolveTextureChecksum(TextureChecksum, GroupChecksum);\r\n\t\t\t\tDbg_MsgAssert(pTex, (\"error: couldn't find texture checksum %08X with group checksum %08X\\n\",\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tTextureChecksum, GroupChecksum));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpTex = ResolveTextureChecksum(TextureChecksum);\r\n\t\t\t\tDbg_MsgAssert(pTex, (\"error: couldn't find texture checksum %08X\\n\", TextureChecksum));\r\n\t\t\t}\r\n\r\n\t\t\t// set texture pointer\r\n\t\t\tpMat->pTex = pTex;\r\n\r\n\t\t\t// get mipmap info\r\n\t\t\tMXL  = pTex->MXL;\r\n\t\t\tMEM_Read(&MMAG, sizeof(uint32), 1, pFile);\r\n\t\t\tMEM_Read(&MMIN, sizeof(uint32), 1, pFile);\r\n\t\t\tMEM_Read(&K, sizeof(uint32), 1, pFile);\r\n\t\t\tK = (int) ((*(float *)&K) * 16.0f) & 0xFFF;\r\n\t\t\tif (sMaterial::Version > 1)\r\n\t\t\t\tpMat->RegTEX1 = PackTEX1(0,MXL,MMAG,MMIN,0,0,K);\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMEM_Read(&L, sizeof(uint32), 1, pFile);\r\n\t\t\t\tpMat->RegTEX1 = PackTEX1(0,MXL,MMAG,MMIN,0,L,K);\r\n\t\t\t}\r\n\t\t}\r\n\t\t// otherwise just step past mipmap info\r\n\t\telse\r\n\t\t{\r\n\t\t\tpMat->pTex = 0;\r\n\t\t\tMEM_Seek(pFile, 12+4*(sMaterial::Version==1), SEEK_CUR);\r\n\t\t}\r\n\r\n\t\t// get reflection map scale values\r\n\t\tif (sMaterial::Version >= 4)\r\n\t\t{\r\n\t\t\tfloat temp;\r\n\t\t\tMEM_Read(&temp, sizeof(float), 1, pFile);\r\n\t\t\tpMat->RefMapScaleU = (sint16)(int)(temp * 256.0f);\r\n\t\t\tMEM_Read(&temp, sizeof(float), 1, pFile);\r\n\t\t\tpMat->RefMapScaleV = (sint16)(int)(temp * 256.0f);\r\n\t\t}\r\n\r\n\t}\r\n\treturn pFile;\r\n}\r\n\r\n\r\nuint32 sMaterial::Version;\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/material.h",
    "content": "#ifndef __MATERIAL_H\r\n#define __MATERIAL_H\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n// Material Flags\r\n#define MATFLAG_UV_WIBBLE   \t(1<<0)\r\n#define MATFLAG_VC_WIBBLE   \t(1<<1)\r\n#define MATFLAG_TEXTURED    \t(1<<2)\r\n#define MATFLAG_ENVIRONMENT \t(1<<3)\r\n#define MATFLAG_DECAL       \t(1<<4)\r\n#define MATFLAG_SMOOTH      \t(1<<5)\r\n#define MATFLAG_TRANSPARENT\t\t(1<<6)\r\n#define MATFLAG_ONE_SIDED \t\t(1<<7)\r\n#define MATFLAG_INVISIBLE \t\t(1<<8)\r\n#define MATFLAG_TWO_SIDED \t\t(1<<9)\r\n#define MATFLAG_SPECULAR \t\t(1<<10)\r\n#define MATFLAG_ANIMATED_TEX\t(1<<11)\r\n#define MATFLAG_FORCE_ALPHA\t\t(1<<13)\r\n\r\n\r\nstruct sMaterial\r\n{\r\n\tuint32\tFlags;\r\n\tuint32\tChecksum;\r\n\tstruct\tsTexture *pTex;\r\n\tuint64\tRegALPHA, RegTEX1, RegCLAMP;\r\n\tuint8\tAref;\r\n\tfloat*\tpUVWibbleInfo;\r\n\tuint32*\tpVCWibbleInfo;\r\n\tsint16\tRefMapScaleU, RefMapScaleV;\r\n\r\n\tstatic uint32 Version;\r\n};\r\n\r\n\r\nvoid * LoadMaterials(void *pFile, struct sScene *pScene, uint32 texDictOffset);\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n#endif // __MATERIAL_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/mesh.cpp",
    "content": "#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include \"group.h\"\r\n#include \"scene.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n#include \"texture.h\"\r\n#include \"material.h\"\r\n#include \"mesh.h\"\r\n#include \"vu1code.h\"\r\n#include \"dmacalls.h\"\r\n#include \"render.h\"\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/memfile.h>\r\n#include <sys/mem/memman.h>\r\n#include <gfx/nx.h>\r\n\t\t\t\t\t\t\t\t\t\t  \r\nnamespace NxPs2\r\n{\r\n\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\nextern uint32\t\tgPassMask1; \t\t// 1<<6 | 1<<7  (0x40, 0x80)\r\nextern uint32\t\tgPassMask0; \t\t// 1<<6 | 1<<7  (0x40, 0x80)\r\n#endif \r\n\r\n\r\n#if 0\r\n\r\n//----------------------------------------------------------------------------------------\r\n//\t\tMesh Group Functions\r\n//----------------------------------------------------------------------------------------\r\n\r\nsMesh *sGroup::GetMeshArray()\r\n{\r\n\treturn &(Meshes[FirstMeshIndex]);\r\n}\r\n\r\n\r\nsGroup* NewMeshGroup(uint32 group_ID, uint32 num_meshes)\r\n{\r\n\tuint32 i;\r\n\tint Group = -1;\r\n\r\n\t// resolve ID\r\n\tfor (i=0; i<NumTextureGroups; i++)\r\n\t{\r\n\t\tif (Groups[i].ID == group_ID)\r\n\t\t{\r\n\t\t\tGroup = i;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tDbg_MsgAssert(Groups[i].ID==group_ID, (\"Couldn't find group ID #%d\\n\", group_ID));\r\n\r\n\t// get number of meshes\r\n\t// set group info\r\n\tGroups[Group].NumMeshes = num_meshes;\r\n\tGroups[Group].FirstMeshIndex = NumMeshes;\r\n\r\n\tNumMeshes += num_meshes;\r\n\r\n\treturn &(Groups[Group]);\r\n}\r\n\r\n#endif\r\n\r\n\r\n//----------------------------------------------------------------------------------------\r\n//\t\tMesh scaling parameters\r\n//\t\tGJ:  Used for vertex scaling at load-time (needed for cutscene head scaling)\r\n//\t\tI decided to make global functions to set these from the cutscene code,\r\n//\t\tso that I wouldn't have to pass extra parameters through the various loading\r\n//\t\tfunctions\r\n//----------------------------------------------------------------------------------------\r\n\r\nbool\t\t\ts_meshScalingEnabled = false;\r\nchar*\t\t\ts_pWeightIndices = NULL;\r\nfloat*\t\t\ts_pWeights = NULL;\r\nMth::Vector*\ts_pBonePositions = NULL;\r\nMth::Vector*\ts_pBoneScales = NULL;\r\nint\t\t\t\ts_currentVertIndex = 0;\r\n\r\nvoid SetMeshScalingParameters( Nx::SMeshScalingParameters* pParams )\r\n{\r\n\tDbg_Assert( pParams );\r\n\r\n\ts_meshScalingEnabled = true;\r\n\ts_pWeights = pParams->pWeights;\r\n\ts_pWeightIndices = pParams->pWeightIndices;\r\n\ts_pBoneScales = pParams->pBoneScales;\r\n\ts_pBonePositions = pParams->pBonePositions;\r\n\ts_currentVertIndex = 0;\r\n}\r\n\r\nvoid DisableMeshScaling()\r\n{\r\n\ts_meshScalingEnabled = false;\r\n\ts_pWeights = NULL;\r\n\ts_pWeightIndices = NULL;\r\n\ts_pBoneScales = NULL;\r\n\ts_pBonePositions = NULL;\r\n\ts_currentVertIndex = 0;\r\n}\r\n\r\n//----------------------------------------------------------------------------------------\r\n//\t\tL O A D   M E S H E S\r\n//----------------------------------------------------------------------------------------\r\n\r\nvoid * LoadMeshes(void *pFile, sScene *pScene, bool IsSkin, bool IsInstanceable, uint32 texDictOffset)\r\n{\r\n\tint i;\r\n\r\n\t// initialise sScene bounding sphere to avoid rewriting it multiple times\r\n\tpScene->Sphere[3] = -1.0f;\r\n\r\n\tint skinnedVertexCount=0;\r\n\r\n\t// iterate over mesh groups\r\n\tfor (i=0; i<pScene->NumGroups; i++)\r\n\t{\r\n\t\tpFile = LoadMeshGroup(pFile, pScene, IsSkin, IsInstanceable, texDictOffset, skinnedVertexCount);\r\n\t}\r\n\t// Check hierarchy data\r\n\tint num_hier = -1;\r\n\tMEM_Read(&num_hier, sizeof(int), 1, pFile);\r\n\tDbg_MsgAssert(num_hier == 0, (\"num_hier = %d\", num_hier));\r\n\t\r\n\t// clear it out for future use\r\n\tDisableMeshScaling();\r\n\t\r\n\treturn pFile;\r\n}\r\n\r\n\r\n\r\n\r\nvoid *LoadMeshGroup(void *pFile, sScene *pScene, bool IsSkin, bool IsInstanceable, uint32 texDictOffset, int& skinnedVertexCount)\r\n{\r\n\tsMesh *pMesh;\r\n\tsMaterial *pMat;\r\n\tsGroup *pGroup;\r\n\tuint32 MaterialChecksum, GroupChecksum;\r\n\tint NumMeshesThisGroup,i,j;\r\n\tMth::Vector sphere;\r\n\r\n\t// get group checksum and number of meshes\r\n\tMEM_Read(&GroupChecksum, sizeof(uint32), 1, pFile);\r\n\tMEM_Read(&NumMeshesThisGroup, sizeof(uint32), 1, pFile);\r\n\r\n\tGroupChecksum += texDictOffset;\r\n\r\n\t// resolve checksum\r\n\tfor (pGroup=sGroup::pHead; pGroup; pGroup=pGroup->pNext)\r\n\t\tif (pGroup->Checksum == GroupChecksum)\r\n\t\t\tbreak;\r\n\tDbg_MsgAssert(pGroup, (\"Couldn't find group checksum #%0X\\n\", GroupChecksum));\r\n\r\n\t// set mesh info in the group\r\n\tpGroup->pMeshes = pScene->pMeshes+pScene->NumMeshes;\r\n\tpGroup->NumMeshes = NumMeshesThisGroup;\r\n\r\n\t// loop over meshes\r\n\tfor (i=0,pMesh=pGroup->pMeshes; i<NumMeshesThisGroup; i++,pMesh++)\r\n\t{\r\n\t\t// start a subroutine for this mesh\r\n\t\tdma::BeginSub3D();\r\n\r\n\t\t// start a ret tag\r\n\t\tdma::BeginTag(dma::ret, 0);\r\n\r\n\t\t// get object checksum\r\n\t\tMEM_Read(&pMesh->Checksum, sizeof(uint32), 1, pFile);\r\n\r\n\t\t// get object sphere for mesh version 2 onwards\r\n\t\tif (sMesh::Version >= 2)\r\n\t\t{\r\n\t\t\tunsigned int lod_stuff_not_used_here;\r\n\t\t\tMEM_Read(&lod_stuff_not_used_here, sizeof(unsigned int), 1, pFile);\r\n\t\t\tMEM_Read(&lod_stuff_not_used_here, sizeof(unsigned int), 1, pFile);\r\n\r\n\t\t\t// Just process parent/child stuff\r\n\t\t\tint num_child, hier_data;\r\n\t\t\tMEM_Read(&hier_data, sizeof(unsigned int), 1, pFile);\r\n\t\t\tMEM_Read(&num_child, sizeof(unsigned int), 1, pFile);\r\n\t\t\tfor (int j = 0; j < num_child; j++)\r\n\t\t\t{\r\n\t\t\t\tMEM_Read(&hier_data, sizeof(unsigned int), 1, pFile);\r\n\t\t\t}\r\n\r\n\t\t\tMEM_Read(&sphere, sizeof(Mth::Vector), 1, pFile);\r\n\r\n\t\t\t// write sphere into sScene\r\n\t\t\tif (pScene->Sphere[3] < 0.0f)\r\n\t\t\t\tpScene->Sphere = sphere;\r\n\r\n\t\t\t#if 0\r\n\t\t\t// GJ:  the following assertion is no longer valid...\r\n\t\t\t// there are occasionally multiple NxObjects inside a\r\n\t\t\t// single MDL file, and each mesh will have a different\r\n\t\t\t// bounding sphere depending on which NxObject is belongs\r\n\t\t\t// to...  Mike agreed to rewrite the bounding sphere\r\n\t\t\t// calculation code so that all meshes will have a\r\n\t\t\t// new bounding sphere that encompasses all the individual\r\n\t\t\t// meshes' bounding spheres...\r\n\r\n\t\t\t// check object spheres from different meshes match ok\r\n\t\t\tDbg_MsgAssert((pScene->Sphere[0]==sphere[0] && pScene->Sphere[1]==sphere[1] &&\r\n\t\t\t\t\t\t   pScene->Sphere[2]==sphere[2] && pScene->Sphere[3]==sphere[3]),\r\n\t\t\t\t\t\t  (\"object bounding sphere differs between meshes\"));\r\n\t\t\t#else\r\n\t\t\t// ...so, if the object spheres differ, just combine them...\r\n\t\t\tif (pScene->Sphere[0]!=sphere[0] || pScene->Sphere[1]!=sphere[1] ||\r\n\t\t\t\tpScene->Sphere[2]!=sphere[2] || pScene->Sphere[3]!=sphere[3])\r\n\t\t\t{\r\n\t\t\t\t//printf(\"\\n\\n\");\r\n\t\t\t\t//printf(\"**********************************************\\n\");\r\n\t\t\t\t//printf(\"*                                            *\\n\");\r\n\t\t\t\t//printf(\"*  Tell Mike if you see this line printing!  *\\n\");\r\n\t\t\t\t//printf(\"*                                            *\\n\");\r\n\t\t\t\t//printf(\"**********************************************\\n\");\r\n\t\t\t\t//printf(\"\\n\\n\");\r\n\t\t\t\t//printf(\"combining spheres (%g,%g,%g,%g) and (%g,%g,%g,%g)\\n\",\r\n\t\t\t\t//\t   pScene->Sphere[0], pScene->Sphere[1], pScene->Sphere[2], pScene->Sphere[3],\r\n\t\t\t\t//\t   sphere[0], sphere[1], sphere[2], sphere[3]);\r\n\r\n\t\t\t\tMth::Vector x0, x1, d;\r\n\t\t\t\tif (pScene->Sphere[3] > sphere[3])\r\n\t\t\t\t{\r\n\t\t\t\t\tx0 = pScene->Sphere; \r\n\t\t\t\t\tx1 = sphere;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tx0 = sphere;\r\n\t\t\t\t\tx1 = pScene->Sphere;\r\n\t\t\t\t}\r\n\t\t\t\tfloat r0=x0[3], r1=x1[3];\r\n\r\n\t\t\t\t// (x0,r0) is the larger sphere, (x1,r1) the smaller\r\n\t\t\t\t// d is the vector between centres\r\n\t\t\t\td = x1 - x0;\r\n\r\n\t\t\t\t// square of distance between centres\r\n\t\t\t\tfloat D2 = DotProduct(d,d);\r\n\r\n\t\t\t\t// (r0-r1)^2\r\n\t\t\t\tfloat R2 = (r0-r1)*(r0-r1);\r\n\r\n\t\t\t\t// m = max { (r1-r0+|d|)/2, 0 }\r\n\t\t\t\tfloat m = 0.0f;\r\n\t\t\t\tif (R2-D2 < 0)\r\n\t\t\t\t{\r\n\t\t\t\t\tm = (r1-r0 + sqrtf(D2)) * 0.5f;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tpScene->Sphere    = x0 + m * d;\r\n\t\t\t\tpScene->Sphere[3] = r0 + m;\r\n\r\n\t\t\t\t//printf(\"result is (%g,%g,%g,%g)\\n\",\r\n\t\t\t\t//\t   pScene->Sphere[0], pScene->Sphere[1], pScene->Sphere[2], pScene->Sphere[3]);\r\n\t\t\t\r\n\t\t\t\t//Dbg_MsgAssert( 0, ( \"Please tell Mike if you see this assert firing off!\" ) );\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t}\r\n\r\n\t\t// get material checksum and look it up\r\n\t\tMEM_Read(&MaterialChecksum, sizeof(uint32), 1, pFile);\r\n\t\tfor (j=0,pMat=pScene->pMaterials; j<pScene->NumMaterials; j++,pMat++)\r\n\t\t\tif (pMat->Checksum == MaterialChecksum)\r\n\t\t\t\tbreak;\r\n\t\tDbg_MsgAssert(pMat->Checksum==MaterialChecksum, (\"couldn't find material with checksum %08X\\n\", MaterialChecksum));\r\n\t\tpMesh->pMaterial = pMat;\r\n\r\n\t\t// get mesh flags\r\n\t\tMEM_Read(&pMesh->Flags, sizeof(uint32), 1, pFile);\r\n\r\n\t\t// make it active\r\n\t\tpMesh->SetActive(true);\r\n\r\n\t\t// get bounding volume data\r\n\t\tMEM_Read(&pMesh->ObjBox, sizeof(float) * 3, 1, pFile);\r\n\t\tMEM_Read(&pMesh->Box,    sizeof(float) * 3, 1, pFile);\r\n\t\tMEM_Read(&pMesh->Sphere, sizeof(float) * 4, 1, pFile);\r\n\r\n\t\t// pass number\r\n\t\tif (sMesh::Version >= 5)\r\n\t\t{\r\n\t\t\tMEM_Read(&pMesh->Pass, sizeof(int), 1, pFile);\r\n\t\t}\r\n\r\n\t\t// material name\r\n\t\tif (sMesh::Version >= 6)\r\n\t\t{\r\n\t\t\tMEM_Read(&pMesh->MaterialName, sizeof(int), 1, pFile);\r\n\t\t}\r\n\t\t\r\n\t\t// import vertices of this mesh\r\n\t\tpFile = LoadVertices(pFile, pMesh, pMat, pGroup, skinnedVertexCount);\r\n\r\n\t\t// end the dma tag\r\n\t\tdma::EndTag();\r\n\r\n\t\t// end the model subroutine\r\n\t\tpMesh->pSubroutine = dma::EndSub3D();\r\n\t}\r\n\r\n\t// add to total number for scene\r\n\tpScene->NumMeshes += NumMeshesThisGroup;\r\n\treturn pFile;\r\n}\r\n\r\n\r\n\r\n//----------------------------------------------------------------------------------------\r\n//\t\tL O A D   V E R T I C E S\r\n//----------------------------------------------------------------------------------------\r\n\r\nint UnpackOffset;\r\n\r\nvoid * LoadVertices(void *pFile, sMesh *pMesh, sMaterial *pMat, sGroup *pGroup, int& skinnedIndexCount)\r\n{\r\n\tuint32 NumVertices;\r\n\tuint REGS, NREG, PRIM, ADDR;\r\n\tsTexture *pTex;\r\n\tuint32 i;\r\n\tuint8  VertexData[64];\r\n\tint    STOffset, ColourOffset, NormalOffset, SkinOffset, XYZOffset, VertexSize;\r\n\tint    texture_width=0, texture_height=0;\r\n\r\n\t// get number of vertices for this mesh\r\n\tMEM_Read(&NumVertices, sizeof(uint32), 1, pFile);\r\n\r\n\t// skip mesh if it has no vertices\r\n\tif (NumVertices==0)\r\n\t\treturn pFile;\r\n\r\n\t// work out giftag fields\r\n\tREGS = gs::XYZF2;\r\n\tNREG = 1;\r\n\tPRIM = TRISTRIP|ABE|FGE;\r\n\tADDR = VU1_ADDR(Proj);\r\n\tif (pMesh->Flags & MESHFLAG_COLOURS)\r\n\t{\r\n\t\tREGS = REGS<<4 | gs::RGBAQ;\r\n\t\tNREG++;\r\n\t}\r\n\tif (pMesh->Flags & MESHFLAG_NORMALS)\r\n\t{\r\n\t\tif (pMat->Flags & MATFLAG_ENVIRONMENT)\r\n\t\t{\r\n\t\t\tADDR = VU1_ADDR(Refl);\r\n\t\t\tREGS = REGS<<4 | gs::ST;\r\n\t\t\tPRIM |= TME;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tREGS = REGS<<4 | gs::NOP;\r\n\t\t}\r\n\t\tNREG++;\r\n\t}\r\n\tif ((pMesh->Flags & MESHFLAG_TEXTURE) && !(pMat->Flags & MATFLAG_ENVIRONMENT))\r\n\t{\r\n\t\tREGS = REGS<<4 | gs::ST;\r\n\t\tNREG++;\r\n\t\tPRIM |= TME;\r\n\t\tADDR = VU1_ADDR(PTex);\r\n\t}\r\n\tif (pMat->Flags & MATFLAG_SMOOTH)\r\n\t\tPRIM |= IIP;\r\n\r\n\t// override everything for skinned models!\r\n\tif (pMesh->Flags & MESHFLAG_SKINNED)\r\n\t{\r\n\t\tif (pMat->RegCLAMP & PackCLAMP(3,3,0,0,0,0))\r\n\t\t{\r\n\t\t\t// clamped case, send texture coords as 32 bits floating point STs\r\n\t\t\tREGS = gs::XYZ2<<16 | gs::RGBAQ<<12 | gs::NOP<<8 | gs::NOP<<4 | gs::ST;\r\n\t\t\tNREG = 5;\r\n\t\t\tPRIM |= TME;\r\n\t\t\tADDR = VU1_ADDR(Skin);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// standard case, non-clamped, compress texture coords to 16 bit fixed point UVs\r\n\t\t\tREGS = gs::XYZ2<<16 | gs::RGBAQ<<12 | gs::NOP<<8 | gs::NOP<<4 | gs::UV;\r\n\t\t\tNREG = 5;\r\n\t\t\tPRIM |= TME|FST;\r\n\t\t\tADDR = VU1_ADDR(Skin);\r\n\t\t}\r\n\t}\r\n\r\n\t// output GS context for material\r\n\tgs::BeginPrim(REL,0,0);\r\n\tgs::Reg1(gs::ALPHA_1,\tpMat->RegALPHA);\r\n\tgs::Reg1(gs::TEST_1, PackTEST(1,AGEQUAL,pMat->Aref,KEEP,0,0,1,ZGEQUAL));\r\n\r\n\t// texture registers if necessary\r\n\tif (pMat->Flags & MATFLAG_TEXTURED)\r\n\t{\r\n\t\tpTex = pMat->pTex;\r\n\t\tgs::Reg1(gs::TEX0_1,\tpTex->RegTEX0);\r\n\t\tgs::Reg1(gs::TEX1_1,\tpMat->RegTEX1);\r\n\t\tgs::Reg1(gs::CLAMP_1,\tpMat->RegCLAMP);\r\n\t\tif (pTex->MXL > 0)\r\n\t\t{\r\n\t\t\tgs::Reg1(gs::MIPTBP1_1,pTex->RegMIPTBP1);\r\n\t\t\tif (pTex->MXL > 3)\r\n\t\t\t{\r\n\t\t\t\tgs::Reg1(gs::MIPTBP2_1,pTex->RegMIPTBP2);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// extract texture dimensions\r\n\t\ttexture_width  = 1 << ((pTex->RegTEX0 >> 26) & 0xF);\r\n\t\ttexture_height = 1 << ((pTex->RegTEX0 >> 30) & 0xF);\r\n\t}\r\n\tgs::EndPrim(0);\r\n\r\n\t// set maximum vu buffer size\r\n\tvu1::MaxBuffer = pMesh->Flags&MESHFLAG_SKINNED ? 240 : 240;\r\n\r\n\t// begin a batch of vertices\r\n\tBeginModelMultiPrim(REGS, NREG, PRIM, NumVertices, ADDR);\r\n\r\n\t// work out vertex size and data offsets\r\n\tVertexSize = (pMesh->Flags & MESHFLAG_SKINNED) ? 8 : 16;\r\n\tXYZOffset = SkinOffset = NormalOffset = ColourOffset = STOffset = 0;\r\n\tif (pMesh->Flags & MESHFLAG_SKINNED)\r\n\t{\r\n\t\tVertexSize   += 8;\r\n\t\tXYZOffset    += 8;\r\n\t}\r\n\tif (pMesh->Flags & MESHFLAG_NORMALS)\r\n\t{\r\n\t\tVertexSize   += 4;\r\n\t\tXYZOffset    += 4;\r\n\t\tSkinOffset   += 4;\r\n\t}\r\n\tif (pMesh->Flags & MESHFLAG_COLOURS)\r\n\t{\r\n\t\tVertexSize   += 4;\r\n\t\tXYZOffset    += 4;\r\n\t\tSkinOffset   += 4;\r\n\t\tNormalOffset += 4;\r\n\t}\r\n\tif (pMesh->Flags & MESHFLAG_TEXTURE)\r\n\t{\r\n\t\tint size = (pMesh->Flags & MESHFLAG_SKINNED) ? 4 : 8;\r\n\t\tVertexSize   += size;\r\n\t\tXYZOffset    += size;\r\n\t\tSkinOffset   += size;\r\n\t\tNormalOffset += size;\r\n\t\tColourOffset += size;\r\n\t}\r\n\t// loop over vertices\r\n\tfor (i=0; i<NumVertices; i++)\r\n\t{\r\n\t\tUnpackOffset=1;\r\n\r\n\t\tMEM_Read(VertexData, 1, VertexSize, pFile);\r\n\r\n\t\tBeginVertex(pMesh, pMat);\r\n\r\n\t\t// special case for skinned models\r\n\t\tif (pMesh->Flags & MESHFLAG_SKINNED)\r\n\t\t{\r\n\t\t\t// texture coords\r\n\t\t\tUnpackOffset = 1;\r\n\t\t\tif ((pMesh->Flags & MESHFLAG_TEXTURE) && !(pMat->Flags & MATFLAG_ENVIRONMENT))\r\n\t\t\t{\r\n\t\t\t\tif (pMat->RegCLAMP & PackCLAMP(3,3,0,0,0,0))\r\n\t\t\t\t{\r\n\t\t\t\t\tVertexSTFloat(VertexData+STOffset);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tVertexUV(VertexData+STOffset, texture_width<<4, texture_height<<4);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// weights\r\n\t\t\tUnpackOffset = 2;\r\n\t\t\tVertexWeights(VertexData+SkinOffset);\r\n\t\t\t\r\n\t\t\t// normal and transform offsets\r\n\t\t\tUnpackOffset = 3;\r\n\t\t\tVertexSkinNormal(VertexData+NormalOffset, VertexData+SkinOffset+4);\r\n\r\n\t\t\t// colour\r\n\t\t\tUnpackOffset = 4;\r\n\t\t\tif (pMesh->Flags & MESHFLAG_COLOURS)\r\n\t\t\t{\r\n\t\t\t\tVertexRGBA(VertexData+ColourOffset);\r\n\t\t\t}\r\n\r\n\t\t\t// position\r\n\t\t\tUnpackOffset = 5;\r\n\t\t\tVertexXYZ(VertexData+XYZOffset, true, skinnedIndexCount);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// texture coords\r\n\t\t\tif ((pMesh->Flags & MESHFLAG_TEXTURE) && !(pMat->Flags & MATFLAG_ENVIRONMENT))\r\n\t\t\t{\r\n\t\t\t\tVertexST16(VertexData+STOffset);\r\n\t\t\t}\r\n\r\n\t\t\t// normal normals\r\n\t\t\tif (pMesh->Flags & MESHFLAG_NORMALS)\r\n\t\t\t{\r\n\t\t\t\tVertexNormal(VertexData+NormalOffset);\r\n\t\t\t}\r\n\r\n\t\t\t// colour\r\n\t\t\tif (pMesh->Flags & MESHFLAG_COLOURS)\r\n\t\t\t{\r\n\t\t\t\tVertexRGBA(VertexData+ColourOffset);\r\n\t\t\t}\r\n\r\n\t\t\t// position\r\n\t\t\tVertexXYZ(VertexData+XYZOffset, false, skinnedIndexCount);\r\n\t\t}\r\n\r\n\t\tEndVertex();\r\n\t\t\r\n\t\t// current vert being processed\r\n\t\ts_currentVertIndex++;\r\n\t}\r\n\r\n\t// accumulate number of vertices\r\n\tsMesh::TotalNumVertices += NumVertices;\r\n\r\n\t// finish batch of vertices\r\n\tEndModelMultiPrim();\r\n\treturn pFile;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n//---------------------------------------------------------\r\n//\t\tM O D E L   P R I M   C O N S T R U C T I O N\r\n//---------------------------------------------------------\r\n\r\n\r\nuint   MeshRegs, MeshNReg, MeshPrim, MeshNLoop, MeshAddr;\r\nuint   NumVerticesThisBuffer, NumOutputVertices;\r\nuint32 *pColour;\r\nsint32 *pST32;\r\nsint16 *pST16, *pVertex, *pNormal, *pSkinData;\r\nuint8  *pWeights;\r\nuint16 *pUV;\r\n\r\n\r\n\r\n// begin model prim (i.e. begin a vertex packet)\r\nvoid BeginModelPrim(uint32 Regs, uint NReg, uint Prim, uint Pre, uint Addr)\r\n{\r\n\tvif::STCYCL(1,NReg);\r\n\tvif::UNPACK(0,V4_32,1,REL,UNSIGNED,0);\r\n\tgif::BeginTag1(Regs, NReg, PACKED, Prim, Pre, Addr);\r\n}\r\n\r\n\r\n// end model prim (i.e. end a vertex packet)\r\nvoid EndModelPrim(uint Eop)\r\n{\r\n\tgif::EndTag1(Eop);\r\n}\r\n\r\n\r\n// begin model prim (i.e. begin a vertex packet)\r\nvoid BeginModelPrimImmediate(uint32 Regs, uint NReg, uint Prim, uint Pre, uint Addr)\r\n{\r\n\tvif::STCYCL(1,NReg);\r\n\tvif::UNPACK(0,V4_32,1,ABS,UNSIGNED,0);\r\n\tgif::BeginTag1(Regs, NReg, PACKED, Prim, Pre, Addr);\r\n}\r\n\r\n\r\n// end model prim (i.e. end a vertex packet)\r\nvoid EndModelPrimImmediate(uint Eop)\r\n{\r\n\tgif::EndTag1(Eop);\r\n}\r\n\r\n\r\n// begin a model prim which may span multiple VU1 buffers\r\nvoid BeginModelMultiPrim(uint32 Regs, uint NReg, uint Prim, uint NLoop, uint Addr)\r\n{\r\n\t// record tag info\r\n\tMeshRegs  = Regs;\r\n\tMeshNReg  = NReg;\r\n\tMeshPrim  = Prim;\r\n\tMeshNLoop = NLoop;\r\n\tMeshAddr  = Addr;\r\n\r\n\t// work out number of vertices to unpack first\r\n\t// (and go ahead with it for now, even if there's only room for 1 vertex)\r\n\tNumVerticesThisBuffer = (vu1::MaxBuffer - ((vu1::Loc-vu1::Buffer)&0x3FF) - 1) / NReg;\r\n\tif (NumVerticesThisBuffer > MeshNLoop)\r\n\t\tNumVerticesThisBuffer = MeshNLoop;\r\n\r\n\tBeginModelPrim(Regs, NReg, Prim, 1, Addr);\r\n\tNumOutputVertices = 0;\r\n}\r\n\r\n\r\nvoid EndModelMultiPrim(void)\r\n{\r\n\tEndModelPrim(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n\tvif::FLUSH();\r\n}\r\n\r\n\r\nint RestartTristrip=0;\r\n\r\nvoid BeginVertex(sMesh *pMesh, sMaterial *pMat)\r\n{\r\n\tif (NumOutputVertices == NumVerticesThisBuffer)\r\n\t{\r\n\t\t// end the model prim\r\n\t\tif ((pMesh->Flags & MESHFLAG_SKINNED) && (768-((vu1::Buffer+vif::UnpackSize*vif::CycleLength+1)&1023) < vu1::MaxBuffer))\r\n\t\t{\r\n\t\t\tEndModelPrim(0);\r\n\t\t\tvif::UNPACK(0, V4_32, 1, REL, UNSIGNED, 0);\r\n\t\t\tgif::Tag1(0, 0, PACKED, 0, 0, 1, 0, VU1_ADDR(Jump));\t\t// reset address to 0\r\n\t\t\tvu1::Loc = 0;\r\n\r\n\t\t\t// start VU1 execution\r\n\t\t\tvif::MSCAL(VU1_ADDR(Parser));\r\n\t\t\tvif::FLUSH();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tEndModelPrim(1);\r\n\r\n\t\t\t// start VU1 execution\r\n\t\t\tvif::MSCAL(VU1_ADDR(Parser));\r\n\t\t\tvif::FLUSH();\r\n\t\t}\r\n\r\n\t\t// reduce number still to go\r\n\t\tMeshNLoop -= NumOutputVertices;\r\n\r\n\t\t// work out number of vertices to unpack next\r\n\t\tNumVerticesThisBuffer = vu1::MaxBuffer / MeshNReg;\r\n\t\tif (NumVerticesThisBuffer > MeshNLoop)\r\n\t\t\tNumVerticesThisBuffer = MeshNLoop;\r\n\r\n\t\t// start a new buffalo'd\r\n\r\n\t\t// add a dummy gs context\r\n\t\tgs::BeginPrim(REL,0,0);\r\n\t\tgs::Reg1(gs::A_D_NOP,0);\r\n\t\tgs::EndPrim(0);\r\n\r\n\t\tBeginModelPrim(MeshRegs, MeshNReg, MeshPrim, 1, MeshAddr);\r\n\t\tNumOutputVertices = 0;\r\n\r\n\t\t// signal tristrip restart\r\n\t\tRestartTristrip=1;\r\n\t}\r\n}\r\n\r\n\r\nvoid VertexST16(uint8 *pData)\r\n{\r\n\tstatic sint16 s0,t0,s1,t1;\r\n\r\n\tif (NumOutputVertices==0)\r\n\t{\r\n\t\tvif::BeginUNPACK(0, V2_16, REL, SIGNED, UnpackOffset);\r\n\t\tpST16 = (sint16 *)dma::pLoc;\r\n\t\tif (RestartTristrip)\r\n\t\t{\r\n\t\t\t*pST16++ = s0;\r\n\t\t\t*pST16++ = t0;\r\n\t\t\t*pST16++ = s1;\r\n\t\t\t*pST16++ = t1;\r\n\t\t}\r\n\t\tdma::pLoc = (uint8 *)pST16 + NumVerticesThisBuffer * 4;\r\n\t\tvif::EndUNPACK();\r\n\t}\r\n\t*pST16++ = (sint16) (int) (((float *)pData)[0] * 4096.0f);\r\n\t*pST16++ = (sint16) (int) (((float *)pData)[1] * 4096.0f);\r\n\ts0=s1, s1=pST16[-2];\r\n\tt0=t1, t1=pST16[-1];\r\n\r\n\tUnpackOffset++;\r\n}\r\n\r\n\r\nvoid VertexSTFloat(uint8 *pData)\r\n{\r\n\tstatic sint32 s0,t0,s1,t1;\r\n\r\n\tif (NumOutputVertices==0)\r\n\t{\r\n\t\tvif::STMASK(0xE0);\r\n\t\tvif::BeginUNPACK(1, V2_32, REL, SIGNED, UnpackOffset);\r\n\t\tpST32 = (sint32 *)dma::pLoc;\r\n\t\tif (RestartTristrip)\r\n\t\t{\r\n\t\t\t*pST32++ = s0;\r\n\t\t\t*pST32++ = t0;\r\n\t\t\t*pST32++ = s1;\r\n\t\t\t*pST32++ = t1;\r\n\t\t}\r\n\t\tdma::pLoc = (uint8 *)pST32 + NumVerticesThisBuffer * 8;\r\n\t\tvif::EndUNPACK();\r\n\t}\r\n\t*(float *)pST32++ = (float)((sint16 *)pData)[0] * 0.000244140625f;\r\n\t*(float *)pST32++ = (float)((sint16 *)pData)[1] * 0.000244140625f;\r\n\ts0=s1, s1=pST32[-2];\r\n\tt0=t1, t1=pST32[-1];\r\n\r\n\tUnpackOffset++;\r\n}\r\n\r\n\r\nvoid VertexUV(uint8 *pData, int textureWidth16, int textureHeight16)\r\n{\r\n\tstatic uint16 u0,v0,u1,v1;\r\n\r\n\tif (NumOutputVertices==0)\r\n\t{\r\n\t\tvif::BeginUNPACK(0, V2_16, REL, UNSIGNED, UnpackOffset);\r\n\t\tpUV = (uint16 *)dma::pLoc;\r\n\t\tif (RestartTristrip)\r\n\t\t{\r\n\t\t\t*pUV++ = u0;\r\n\t\t\t*pUV++ = v0;\r\n\t\t\t*pUV++ = u1;\r\n\t\t\t*pUV++ = v1;\r\n\t\t}\r\n\t\tdma::pLoc = (uint8 *)pUV + NumVerticesThisBuffer * 4;\r\n\t\tvif::EndUNPACK();\r\n\t}\r\n\t*pUV++ = (uint16)((int)((float)((sint16 *)pData)[0] * (float)textureWidth16  * 0.000244140625f) + 0x00002000);\r\n\t*pUV++ = (uint16)((int)((float)((sint16 *)pData)[1] * (float)textureHeight16 * 0.000244140625f) + 0x00002000);\r\n\tu0=u1, u1=pUV[-2];\r\n\tv0=v1, v1=pUV[-1];\r\n\r\n\tUnpackOffset++;\r\n}\r\n\r\n\r\nvoid VertexNormal(uint8 *pData)\r\n{\r\n\tstatic sint16 nx0,ny0,nz0,nx1,ny1,nz1;\r\n\r\n\tif (NumOutputVertices==0)\r\n\t{\r\n\t\tvif::BeginUNPACK(0, V3_16, REL, SIGNED, UnpackOffset);\r\n\t\tpNormal = (sint16 *)dma::pLoc;\r\n\t\tif (RestartTristrip)\r\n\t\t{\r\n\t\t\t*pNormal++ = nx0;\r\n\t\t\t*pNormal++ = ny0;\r\n\t\t\t*pNormal++ = nz0;\r\n\t\t\t*pNormal++ = nx1;\r\n\t\t\t*pNormal++ = ny1;\r\n\t\t\t*pNormal++ = nz1;\r\n\t\t}\r\n\t\tdma::pLoc = (uint8 *)pNormal + NumVerticesThisBuffer * 6;\r\n\t\tvif::EndUNPACK();\r\n\t}\r\n\t*pNormal++ = ((sint16 *)pData)[0];\r\n\t*pNormal++ = ((sint16 *)pData)[1];\r\n\t//*pNormal++ = ((sint16 *)pData)[2];\r\n\tsint16 coord = (sint16)sqrtf(32767.0f*32767.0f - (float)((sint16 *)pData)[0] * (float)((sint16 *)pData)[0]\r\n\t\t\t\t\t\t\t\t\t\t\t\t   - (float)((sint16 *)pData)[1] * (float)((sint16 *)pData)[1]);\r\n\tif (((sint16 *)pData)[0] & 0x0001)\r\n\t{\r\n\t\tcoord = -coord;\r\n\t}\r\n\t*pNormal++ = coord;\r\n\tnx0=nx1, nx1=pNormal[-3];\r\n\tny0=ny1, ny1=pNormal[-2];\r\n\tnz0=nz1, nz1=pNormal[-1];\r\n\r\n\tUnpackOffset++;\r\n}\r\n\r\n\r\n#if 0\r\n\r\nvoid VertexWeights(uint8 *pData)\r\n{\r\n\tstatic sint16 wa0,wb0,wc0,wa1,wb1,wc1;\r\n\r\n\tif (NumOutputVertices==0)\r\n\t{\r\n\t\tvif::BeginUNPACK(0, V3_16, REL, SIGNED, UnpackOffset);\r\n\t\tpWeights = (sint16 *)dma::pLoc;\r\n\t\tif (RestartTristrip)\r\n\t\t{\r\n\t\t\t*pWeights++ = wa0;\r\n\t\t\t*pWeights++ = wb0;\r\n\t\t\t*pWeights++ = wc0;\r\n\t\t\t*pWeights++ = wa1;\r\n\t\t\t*pWeights++ = wb1;\r\n\t\t\t*pWeights++ = wc1;\r\n\t\t}\r\n\t\tdma::pLoc = (uint8 *)pWeights + NumVerticesThisBuffer * 6;\r\n\t\tvif::EndUNPACK();\r\n\t}\r\n\t*pWeights++ = ((sint16 *)pData)[0];\r\n\t*pWeights++ = ((sint16 *)pData)[1];\r\n\t*pWeights++ = 0x7FFF - pWeights[-1] - pWeights[-2];\r\n\twa0=wa1, wa1=pWeights[-3];\r\n\twb0=wb1, wb1=pWeights[-2];\r\n\twc0=wc1, wc1=pWeights[-1];\r\n\r\n\tUnpackOffset++;\r\n}\r\n\r\n#else\r\n\r\nvoid VertexWeights(uint8 *pData)\r\n{\r\n\tstatic uint8 wa0,wb0,wc0,wa1,wb1,wc1;\r\n\r\n\tif (NumOutputVertices==0)\r\n\t{\r\n\t\tvif::BeginUNPACK(0, V3_8, REL, UNSIGNED, UnpackOffset);\r\n\t\tpWeights = dma::pLoc;\r\n\t\tif (RestartTristrip)\r\n\t\t{\r\n\t\t\t*pWeights++ = wa0;\r\n\t\t\t*pWeights++ = wb0;\r\n\t\t\t*pWeights++ = wc0;\r\n\t\t\t*pWeights++ = wa1;\r\n\t\t\t*pWeights++ = wb1;\r\n\t\t\t*pWeights++ = wc1;\r\n\t\t}\r\n\t\tdma::pLoc = pWeights + NumVerticesThisBuffer * 3;\r\n\t\tvif::EndUNPACK();\r\n\t}\r\n\twa0=wa1;\r\n\twb0=wb1;\r\n\twc0=wc1;\r\n\twa1 = (uint8)(sint8)(((float)((sint16 *)pData)[0] + 0.5f) * 0.007818608f);\r\n\twb1 = (uint8)(sint8)(((float)((sint16 *)pData)[1] + 0.5f) * 0.007818608f);\r\n\tif (wb1==0)\r\n\t{\r\n\t\twa1=255, wb1=1;\r\n\t}\r\n\twc1 = 256 - wa1 - wb1;\r\n\t*pWeights++ = wa1;\r\n\t*pWeights++ = wb1;\r\n\t*pWeights++ = wc1;\r\n\r\n\tUnpackOffset++;\r\n}\r\n\r\n#endif\r\n\r\n\r\n\r\nvoid VertexSkinNormal(uint8 *pNormData, uint8 *pTOData)\r\n{\r\n\tstatic sint16 nx0,ny0,nz0,nx1,ny1,nz1;\r\n\r\n\tif (NumOutputVertices==0)\r\n\t{\r\n\t\tvif::BeginUNPACK(0, V3_16, REL, SIGNED, UnpackOffset);\r\n\t\tpSkinData = (sint16 *)dma::pLoc;\r\n\t\tif (RestartTristrip)\r\n\t\t{\r\n\t\t\t*pSkinData++ = nx0;\r\n\t\t\t*pSkinData++ = ny0;\r\n\t\t\t*pSkinData++ = nz0;\r\n\t\t\t*pSkinData++ = nx1;\r\n\t\t\t*pSkinData++ = ny1;\r\n\t\t\t*pSkinData++ = nz1;\r\n\t\t}\r\n\t\tdma::pLoc = (uint8 *)pSkinData + NumVerticesThisBuffer * 6;\r\n\t\tvif::EndUNPACK();\r\n\t}\r\n\r\n\t*pSkinData++ = (sint16) (((sint32) ((sint16 *)pNormData)[0]) & 0xFFFFFC00 | (((uint32)((uint8 *)pTOData)[0]) << 2));\r\n\t*pSkinData++ = (sint16) (((sint32) ((sint16 *)pNormData)[1]) & 0xFFFFFC00 | (((uint32)((uint8 *)pTOData)[1]) << 2));\r\n\t//*pSkinData++ = (sint16) (((sint32) ((sint16 *)pNormData)[2]) & 0xFFFFFC00 | (((uint32)((uint8 *)pTOData)[2]) << 2));\r\n\tsint16 coord = (sint16)sqrtf(32767.0f*32767.0f - (float)((sint16 *)pNormData)[0] * (float)((sint16 *)pNormData)[0]\r\n\t\t\t\t\t\t\t\t\t\t\t\t   - (float)((sint16 *)pNormData)[1] * (float)((sint16 *)pNormData)[1]);\r\n\tif (((sint16 *)pNormData)[0] & 0x0001)\r\n\t{\r\n\t\tcoord = -coord;\r\n\t}\r\n\t*pSkinData++ = (sint16) ((sint32)coord & 0xFFFFFC00) | (((uint8 *)pTOData)[2] << 2);\r\n\r\n\tnx0=nx1, nx1=pSkinData[-3];\r\n\tny0=ny1, ny1=pSkinData[-2];\r\n\tnz0=nz1, nz1=pSkinData[-1];\r\n\r\n\tUnpackOffset++;\r\n}\r\n\r\n\r\n\r\nvoid VertexRGBA(uint8 *pData)\r\n{\r\n\tstatic uint32 rgba0,rgba1;\r\n\r\n\tif (NumOutputVertices==0)\r\n\t{\r\n\t\tvif::BeginUNPACK(0, V4_8, REL, UNSIGNED, UnpackOffset);\r\n\t\tpColour = (uint32 *)dma::pLoc;\r\n\t\tif (RestartTristrip)\r\n\t\t{\r\n\t\t\t*pColour++ = rgba0;\r\n\t\t\t*pColour++ = rgba1;\r\n\t\t}\r\n\t\tdma::pLoc = (uint8 *)pColour + NumVerticesThisBuffer * 4;\r\n\t\tvif::EndUNPACK();\r\n\t}\r\n\t*pColour++ = ((uint32 *)pData)[0];\r\n\trgba0=rgba1, rgba1=pColour[-1];\r\n\r\n\tUnpackOffset++;\r\n}\r\n\r\nMth::Vector get_bone_scale( int bone_index )\r\n{\r\n\tMth::Vector returnVec( 1.0f, 1.0f, 1.0f, 1.0f );\r\n\r\n\tif ( bone_index >= 29 && bone_index <= 33 )\r\n\t{\r\n\t\t// this only works with the thps5 skeleton, whose\r\n\t\t// head bones are between 29 and 33...\r\n\t\t// (eventually, we can remove the subtract 29\r\n\t\t// once the exporter is massaging the data correctly)\r\n\t\treturnVec = s_pBoneScales[ bone_index - 29 ];\r\n\t\t\r\n\t\t// Y & Z are reversed...  odd!\r\n\t\tMth::Vector tempVec = returnVec;\r\n\t\treturnVec[Y] = tempVec[Z];\r\n\t\treturnVec[Z] = tempVec[Y];\r\n\t}\r\n\telse if ( bone_index == -1 )\r\n\t{\r\n\t\t// implies that it's not weighted to a bone\r\n\t\treturn returnVec;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// implies that it's weighted to the wrong bone\r\n\t\treturn returnVec;\r\n\t}\r\n\r\n\treturn returnVec;\r\n}\r\n\r\nMth::Vector get_bone_pos( int bone_index )\r\n{\r\n\tMth::Vector returnVec( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\t\r\n\tif ( bone_index >= 29 && bone_index <= 33 )\r\n\t{\r\n\t\t// this only works with the thps5 skeleton, whose\r\n\t\t// head bones are between 29 and 33...\r\n\t\t// (eventually, we can remove the subtract 29\r\n\t\t// once the exporter is massaging the data correctly)\r\n\t\treturnVec = s_pBonePositions[ bone_index - 29 ];\r\n\t}\r\n\telse if ( bone_index == -1 )\r\n\t{\r\n\t\t// implies that it's not weighted to a bone\r\n\t\treturn returnVec;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// implies that it's weighted to the wrong bone\r\n\t\treturn returnVec;\r\n\t}\r\n\r\n\t// need to get into fixed point\r\n\treturnVec.Scale( 16.0f );\r\n\treturnVec[W] = 1.0f;\r\n\r\n\treturn returnVec;\r\n}\r\n\r\nvoid VertexXYZ(uint8 *pData, bool IsSkin, int& skinnedVertexCount)\r\n{\r\n\tstatic sint64 x0,y0,z0,x1,y1,z1,x2,y2,z2;\r\n\tsint64 det0,det1,det2;\r\n\r\n\tif (NumOutputVertices==0)\r\n\t{\r\n\t\tvif::STMOD(1);\r\n\t\tvif::BeginUNPACK(0, V4_16, REL, SIGNED, UnpackOffset);\r\n\t\tpVertex = (sint16 *)dma::pLoc;\r\n\t\tif (RestartTristrip)\r\n\t\t{\r\n\t\t\t*pVertex++ = x1;\r\n\t\t\t*pVertex++ = y1;\r\n\t\t\t*pVertex++ = z1;\r\n\t\t\t*pVertex++ = 0x8000;\r\n\t\t\t*pVertex++ = x2;\r\n\t\t\t*pVertex++ = y2;\r\n\t\t\t*pVertex++ = z2;\r\n\t\t\t*pVertex++ = 0x8000;\r\n\t\t}\r\n\t\tdma::pLoc = (uint8 *)pVertex + NumVerticesThisBuffer * 8;\r\n\t\tvif::EndUNPACK();\r\n\t\tvif::STMOD(0);\r\n\t}\r\n\t\r\n\tif (IsSkin)\r\n\t{\r\n\t\tif ( s_meshScalingEnabled )\r\n\t\t{\r\n\t\t\tfloat x = (float)((sint16 *)pData)[0];\r\n\t\t\tfloat y = (float)((sint16 *)pData)[1];\r\n\t\t\tfloat z = (float)((sint16 *)pData)[2];\r\n\r\n    \t\tMth::Vector origPos( x, y, z, 1.0f );\r\n\r\n\t\t\tMth::Vector bonePos0 = get_bone_pos( s_pWeightIndices[s_currentVertIndex * 3] );\r\n\t\t\tMth::Vector bonePos1 = get_bone_pos( s_pWeightIndices[s_currentVertIndex * 3 + 1] );\r\n\t\t\tMth::Vector bonePos2 = get_bone_pos( s_pWeightIndices[s_currentVertIndex * 3 + 2] );\r\n\r\n\t\t\t// need to scale each vert relative to its parent bone\r\n\t\t\tMth::Vector localPos0 = origPos - bonePos0;\r\n\t\t\tMth::Vector localPos1 = origPos - bonePos1;\r\n\t\t\tMth::Vector localPos2 = origPos - bonePos2;\r\n\t\t\tlocalPos0.Scale( get_bone_scale( s_pWeightIndices[s_currentVertIndex * 3] ) );\r\n\t\t\tlocalPos1.Scale( get_bone_scale( s_pWeightIndices[s_currentVertIndex * 3 + 1] ) );\r\n\t\t\tlocalPos2.Scale( get_bone_scale( s_pWeightIndices[s_currentVertIndex * 3 + 2] ) );\r\n\t\t\tlocalPos0 += bonePos0;\r\n\t\t\tlocalPos1 += bonePos1;\r\n\t\t\tlocalPos2 += bonePos2;\r\n\t\t\t\r\n\t\t\tMth::Vector scaledPos = ( localPos0 * s_pWeights[s_currentVertIndex * 3] )\r\n\t\t\t\t+ ( localPos1 * s_pWeights[s_currentVertIndex * 3 + 1] )\r\n\t\t\t\t+ ( localPos2 * s_pWeights[s_currentVertIndex * 3 + 2] );\r\n\r\n\t\t\tx = scaledPos[X];\r\n\t\t\ty = scaledPos[Y];\r\n\t\t\tz = scaledPos[Z];\r\n\r\n\t\t\t*pVertex++ = (sint16)x;\r\n\t\t\t*pVertex++ = (sint16)y;\r\n\t\t\t*pVertex++ = (sint16)z;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t*pVertex++ = (((sint16 *)pData)[0] * 1);\r\n\t\t\t*pVertex++ = (((sint16 *)pData)[1] * 1);\r\n\t\t\t*pVertex++ = (((sint16 *)pData)[2] * 1);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t*pVertex++ = (sint16) (((float *)pData)[0] * SUB_INCH_PRECISION);\r\n\t\t*pVertex++ = (sint16) (((float *)pData)[1] * SUB_INCH_PRECISION);\r\n\t\t*pVertex++ = (sint16) (((float *)pData)[2] * SUB_INCH_PRECISION);\r\n\t}\r\n\t\r\n\tif (IsSkin)\r\n\t{\r\n\t\t// GJ:  if it's a skinned model, then check to see\r\n\t\t// if the skinnedVertexCount matches one of the ones\r\n\t\t// that requires a pointer to the ADC bit\r\n\t\tAddCASFlag( skinnedVertexCount, (uint16*)pVertex );\r\n\t}\r\n\t\r\n\tskinnedVertexCount++;\r\n\r\n\tif (IsSkin)\r\n\t{\r\n\t\t*pVertex++ = ((uint16 *)pData)[3] ? 0x8000 : 0x0000;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t*pVertex++ = ((uint32 *)pData)[3] ? 0x8000 : 0x0000;\r\n\t}\r\n\t\r\n\t// advance vertex queue and cull triangle if zero area\r\n\tx0=x1, y0=y1, z0=z1;\r\n\tx1=x2, y1=y2, z1=z2;\r\n\tx2=pVertex[-4], y2=pVertex[-3], z2=pVertex[-2];\r\n\tdet0 = y1*z2+y2*z0+y0*z1-y2*z1-y0*z2-y1*z0;\r\n\tdet1 = z1*x2+z2*x0+z0*x1-z2*x1-z0*x2-z1*x0;\r\n\tdet2 = x1*y2+x2*y0+x0*y1-x2*y1-x0*y2-x1*y0;\r\n\tif (det0*det0 + det1*det1 + det2*det2 == 0)\r\n\t\tpVertex[-1] = 0x8000;\r\n\r\n\tUnpackOffset++;\r\n}\r\n\r\n\r\nvoid EndVertex(void)\r\n{\r\n\tif (NumOutputVertices==0 && RestartTristrip)\r\n\t{\r\n\t\tRestartTristrip = 0;\r\n\t}\r\n\r\n\tNumOutputVertices++;\r\n}\r\n\r\n\r\n\r\n\r\nvoid sMesh::SetActive(bool active)\r\n{\r\n\tif (active)\r\n\t{\r\n\t\tFlags |= MESHFLAG_ACTIVE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tFlags &= ~MESHFLAG_ACTIVE;\r\n\t}\r\n}\r\n\r\n\r\n// Note, Meshflags and passmasks are off by 2 bits\r\n//#define MESHFLAG_PASS_BIT_0\t(1<<8)\r\n//#define MESHFLAG_PASS_BIT_1\t(1<<9)\r\n\r\n//uint32\t\tgPassMask1 = 0; \t\t// 1<<6 | 1<<7  (0x40, 0x80)\r\n//uint32\t\tgPassMask0 = 0; \t\t// 1<<6 | 1<<7  (0x40, 0x80)\r\n\r\nbool sMesh::IsActive()\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t// Mick: debug check for global pass on/off\r\n\t// Note, shifting flags by 2, so mesh flags match geomnode flags\r\n\t// Eventually, meshes will be replaced by leaf nodes in CGeomNode tree\r\n//\tif (((Flags>>2) & gPassMask1) != gPassMask0)\r\n//\t{\t\r\n//\t\treturn false;\r\n//\t}\r\n\t#endif\r\n\t\r\n\r\n\t\r\n\treturn (Flags&MESHFLAG_ACTIVE) ? true : false;\r\n}\r\n\r\nconst int MAX_CAS_DATA_LOOKUP = 10000;\r\n\r\n// array of pointers to sCASData*\r\nsCASData** sCASDataLookupTable = NULL;\r\n\r\nvoid CreateCASDataLookupTable()\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n\tDbg_MsgAssert( sCASDataLookupTable == NULL, ( \"CAS data lookup table already exists\" ) );\r\n\r\n\tsCASDataLookupTable = (sCASData**)Mem::Malloc( MAX_CAS_DATA_LOOKUP * sizeof(sCASData*) );\r\n\r\n\tfor ( int i = 0; i < MAX_CAS_DATA_LOOKUP; i++ )\r\n\t{\r\n\t\tsCASDataLookupTable[i] = NULL;\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\nvoid DestroyCASDataLookupTable()\r\n{\r\n\tif ( sCASDataLookupTable )\r\n\t{\r\n\t\tMem::Free( sCASDataLookupTable );\r\n\t\tsCASDataLookupTable = NULL;\r\n\t}\r\n}\r\n\r\nvoid SetCASDataLookupData( int index, sCASData* pData )\r\n{\r\n\tDbg_MsgAssert( sCASDataLookupTable != NULL, ( \"CAS data lookup table doesn't exist\" ) );\r\n\r\n\tDbg_MsgAssert( index >= 0 && index < MAX_CAS_DATA_LOOKUP, ( \"Out of range lookup index %d (must be between 0 and %d)\", index, MAX_CAS_DATA_LOOKUP ) );\r\n\r\n\tDbg_MsgAssert( sCASDataLookupTable[index] == NULL, ( \"Lookup index %d already used\", index, MAX_CAS_DATA_LOOKUP ) );\r\n\r\n\tsCASDataLookupTable[index] = pData;\r\n}\r\n\r\nvoid AddCASFlag( int skinnedVertexIndex, uint16* pADCBit )\r\n{\r\n\tif ( !sCASDataLookupTable )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tDbg_MsgAssert( skinnedVertexIndex >= 0 && skinnedVertexIndex < MAX_CAS_DATA_LOOKUP, ( \"Out of range lookup index %d (must be between 0 and %d\", skinnedVertexIndex, MAX_CAS_DATA_LOOKUP ) );\r\n\r\n\tif ( sCASDataLookupTable[skinnedVertexIndex] != NULL )\r\n\t{\r\n\t\tsCASDataLookupTable[skinnedVertexIndex]->pADCBit = pADCBit;\r\n\t}\r\n}\r\n\r\nint sMesh::TotalNumVertices;\r\nuint32 sMesh::Version;\r\n\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/mesh.h",
    "content": "#ifndef __MESH_H\r\n#define __MESH_H\r\n\r\n\r\n#include <core/math.h>\r\n\r\nnamespace Nx\r\n{\r\n\tstruct SMeshScalingParameters;\r\n}\r\n\t\t\t\t\t  \r\nnamespace NxPs2\r\n{\r\n\r\n\r\n#define MESHFLAG_TEXTURE\t\t(1<<0)\r\n#define MESHFLAG_COLOURS\t\t(1<<1)\r\n#define MESHFLAG_NORMALS\t\t(1<<2)\r\n#define MESHFLAG_ST16\t\t\t(1<<3)\r\n#define MESHFLAG_SKINNED\t\t(1<<4)\r\n#define MESHFLAG_AXIAL\t\t\t(1<<6)\r\n#define MESHFLAG_SHORTAXIS\t\t(1<<7)\r\n#define MESHFLAG_PASS_BIT_0\t\t(1<<8)\r\n#define MESHFLAG_PASS_BIT_1\t\t(1<<9)\r\n#define MESHFLAG_NO_SHADOW\t\t(1<<10)\r\n#define MESHFLAG_ACTIVE\t\t\t(1<<16)\r\n#define MESHFLAG_UNLIT\t\t\t(1<<17)\r\n#define MESHFLAG_COLOR_LOCKED\t(1<<18)\r\n#define MESHFLAG_BILLBOARD\t\t(1<<23)\r\n#define MESHFLAG_SINGLESIDED\t(1<<24)\r\n#define MESHFLAG_PASS_BIT_2\t\t(1<<25)\r\n#define MESHFLAG_PASS_BIT_3\t\t(1<<26)\r\n\r\n#define MESHFLAG_PASS_BITS\t\t(MESHFLAG_PASS_BIT_0 | MESHFLAG_PASS_BIT_1 | MESHFLAG_PASS_BIT_2 | MESHFLAG_PASS_BIT_3)\r\n\r\n\r\n#define OBJFLAG_TEXTURE\t\t\t(1<<0)\r\n#define OBJFLAG_COLOURS\t\t\t(1<<1)\r\n#define OBJFLAG_NORMALS\t\t\t(1<<2)\r\n#define OBJFLAG_TRANSPARENT\t\t(1<<3)\r\n\r\n\r\nstruct sGroup;\r\nstruct sMaterial;\r\n\r\nstruct sCASData\r\n{\r\n\tuint32\tmask;\r\n//\tint\t\tvertIndex;\t\r\n\tuint16* pADCBit;\r\n};\r\n\r\nvoid CreateCASDataLookupTable();\r\nvoid DestroyCASDataLookupTable();\r\nvoid SetCASDataLookupData( int index, sCASData* pData );\r\n\r\nvoid AddCASFlag(int skinnedVertexIndex, uint16* pADCBit);\r\n\r\nstruct sMesh\r\n{\r\npublic:\r\n\tuint32\t\t\tGetChecksum() const { return Checksum; }\r\n\tuint32\t\t\tGetFlags() const { return Flags; }\r\n\tvoid\t\t\tSetActive(bool active);\r\n\tbool\t\t\tIsActive(void);\r\n\r\n\tuint32 Checksum, Flags;\r\n\tsMaterial *pMaterial;\r\n\tuint8 *pSubroutine;\r\n\tMth::Vector ObjBox,Box,Sphere;\r\n\tuint32*\tpVCWibbleInfo;\r\n\tint Pass;\r\n\tuint32 MaterialName;\r\n\r\n\tstatic int TotalNumVertices;\r\n\tstatic uint32 Version;\r\n};\r\n\r\n// GJ:  for doing cutscene head scaling\r\nvoid SetMeshScalingParameters( Nx::SMeshScalingParameters* pParams );\r\n\r\nvoid * LoadMeshes(void *pFile, struct sScene *pScene, bool IsSkin, bool IsInstanceable, uint32 texDictOffset);\r\nvoid * LoadMeshGroup(void *pFile, struct sScene *pScene, bool IsSkin, bool IsInstanceable, uint32 texDictOffset, int& skinnedVertexIndex );\r\nvoid * LoadVertices(void *pFile, sMesh *pMesh, struct sMaterial *pMat, sGroup *pGroup, int& skinnedVertexIndex);\r\nvoid BeginModelPrim(uint32 Regs, uint NReg, uint Prim, uint Pre, uint Addr);\r\nvoid EndModelPrim(uint Eop);\r\nvoid BeginModelPrimImmediate(uint32 Regs, uint NReg, uint Prim, uint Pre, uint Addr);\r\nvoid EndModelPrimImmediate(uint Eop);\r\nvoid BeginModelMultiPrim(uint32 Regs, uint NReg, uint Prim, uint NLoop, uint Addr);\r\nvoid EndModelMultiPrim(void);\r\nvoid BeginVertex(sMesh *pMesh, struct sMaterial *pMat);\r\nvoid VertexST16(uint8 *pData);\r\nvoid VertexSTFloat(uint8 *pData);\r\nvoid VertexUV(uint8 *pData, int textureWidth16, int textureHeight16);\r\nvoid VertexNormal(uint8 *pData);\r\nvoid VertexWeights(uint8 *pData);\r\nvoid VertexSkinNormal(uint8 *pNormData, uint8 *pTOData);\r\nvoid VertexRGBA(uint8 *pData);\r\nvoid VertexXYZ(uint8 *pData, bool IsSkin, int& skinnedVertexIndex);\r\nvoid EndVertex(void);\r\n\r\n\r\nextern uint NumMeshesInGroup[32];\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n#endif // __MESH_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/mikemath.cpp",
    "content": "\r\n\r\n//--------------------------------------------------------------\r\n//\t\tV E C T O R   A N D   M A T R I X   R O U T I N E S\r\n//--------------------------------------------------------------\r\n\r\n\t\t\t\t\t \r\n#include <core/math.h>\r\n#include <core/defines.h>\r\n#include \"mikemath.h\"\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n// copy a vector\r\n// vd = vs\r\nvoid VecCopy(Vec vd, Vec vs)\r\n{\r\n\tvd[0]=vs[0], vd[1]=vs[1], vd[2]=vs[2], vd[3]=vs[3];\r\n}\r\n\r\n\r\n// set a vector\r\n// v = (x,y,z,w)\r\nvoid VecSet(Vec v, float x, float y, float z, float w)\r\n{\r\n\tv[0]=x, v[1]=y, v[2]=z, v[3]=w;\r\n}\r\n\r\n\r\n// add two vectors to make another\r\n// vd = v0+v1\r\nvoid VecSum(Vec vd, Vec v0, Vec v1)\r\n{\r\n\tint i;\r\n\tfor (i=0; i<4; i++)\r\n\t\tvd[i] = v0[i]+v1[i];\r\n}\r\n\r\n\r\n// add one vector onto another\r\n// vd += vs\r\nvoid VecAdd(Vec vd, Vec vs)\r\n{\r\n\tint i;\r\n\tfor (i=0; i<4; i++)\r\n\t\tvd[i] += vs[i];\r\n}\r\n\r\n\r\n// subtract two vectors to make another\r\n// vd = v0-v1\r\nvoid VecDifference(Vec vd, Vec v0, Vec v1)\r\n{\r\n\tint i;\r\n\tfor (i=0; i<4; i++)\r\n\t\tvd[i] = v0[i]-v1[i];\r\n}\r\n\r\n\r\n// subtract one vector from another\r\n// vd -= vs\r\nvoid VecSubtract(Vec vd, Vec vs)\r\n{\r\n\tint i;\r\n\tfor (i=0; i<4; i++)\r\n\t\tvd[i] -= vs[i];\r\n}\r\n\r\n\r\n// negate a vector\r\n// v = -v\r\nvoid VecNegate(Vec v)\r\n{\r\n\tint i;\r\n\tfor (i=0; i<4; i++)\r\n\t\tv[i] = -v[i];\r\n}\r\n\r\n\r\n// multiply a vector by a matrix\r\n// v = v * M\r\nvoid VecTransform(Vec v, Mat M)\r\n{\r\n\tint i,j;\r\n\tfloat sum;\r\n\tVec TempVec;\r\n\tfor (i=0; i<4; i++)\r\n\t{\r\n\t\tsum = 0.0;\r\n\t\tfor (j=0; j<4; j++)\r\n\t\t\tsum += v[j]*M[j][i];\r\n\t\tTempVec[i] = sum;\r\n\t}\r\n\tVecCopy(v,TempVec);\r\n}\r\n\r\n\r\n// product of a vector by a matrix\r\n// vd = vs * M\r\nvoid VecTransformed(Vec vd, Vec vs, Mat M)\r\n{\r\n\tint i,j;\r\n\tfloat sum;\r\n\tfor (i=0; i<4; i++)\r\n\t{\r\n\t\tsum = 0.0;\r\n\t\tfor (j=0; j<4; j++)\r\n\t\t\tsum += vs[j]*M[j][i];\r\n\t\tvd[i] = sum;\r\n\t}\r\n}\r\n\r\n\r\n// rotate a vector through an angle about an axis\r\nvoid VecRotate(Vec v, float Angle, char Axis)\r\n{\r\n\tMat M;\r\n\tMatRotation(M, Angle, Axis);\r\n\tVecTransform(v, M);\r\n}\r\n\r\n\r\n// normalise a vector\r\n// v = v / |v|\r\nvoid VecNormalise(Vec v)\r\n{\r\n\tint i;\r\n\tfloat RecipLength = 1.0 / sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2] + v[3]*v[3]);\r\n\tfor (i=0; i<4; i++)\r\n\t\tv[i] *= RecipLength;\r\n}\r\n\r\n\r\n// scale a vector\r\n// v *= k\r\nvoid VecScale(Vec v, float k)\r\n{\r\n\tint i;\r\n\tfor (i=0; i<4; i++)\r\n\t\tv[i] *= k;\r\n}\r\n\r\n\r\n// scaled vector\r\n// vd = k*vs\r\nvoid VecScaled(Vec vd, float k, Vec vs)\r\n{\r\n\tint i;\r\n\tfor (i=0; i<4; i++)\r\n\t\tvd[i] = k*vs[i];\r\n}\r\n\r\n\r\n// add scaled vector\r\n// vd += k*vs\r\nvoid VecAddScaled(Vec vd, float k, Vec vs)\r\n{\r\n\tint i;\r\n\tfor (i=0; i<4; i++)\r\n\t\tvd[i] += k*vs[i];\r\n}\r\n\r\n\r\n// weighted mean of 2 vectors\r\n// v = (k0*v0 + k1*v1)/(k0+k1)\r\nvoid VecWeightedMean2(Vec v, float k0, Vec v0, float k1, Vec v1)\r\n{\r\n\tVec Temp;\r\n\tVecScaled(v,k0,v0);\r\n\tVecScaled(Temp,k1,v1);\r\n\tVecAdd(v,Temp);\r\n\tVecScale(v,1.0f/(k0+k1));\r\n}\r\n\r\n\r\n// weighted mean of 3 vectors\r\n// v = (k0*v0 + k1*v1 + k2*v2)/(k0+k1+k2)\r\nvoid VecWeightedMean3(Vec v, float k0, Vec v0, float k1, Vec v1, float k2, Vec v2)\r\n{\r\n\tVec Temp;\r\n\tVecScaled(v,k0,v0);\r\n\tVecScaled(Temp,k1,v1);\r\n\tVecAdd(v,Temp);\r\n\tVecScaled(Temp,k2,v2);\r\n\tVecAdd(v,Temp);\r\n\tVecScale(v,1.0f/(k0+k1+k2));\r\n}\r\n\r\n\r\n// cross product\r\nvoid CrossProduct(Vec vd, Vec v0, Vec v1)\r\n{\r\n\tvd[0] = v0[1]*v1[2] - v0[2]*v1[1];\r\n\tvd[1] = v0[2]*v1[0] - v0[0]*v1[2];\r\n\tvd[2] = v0[0]*v1[1] - v0[1]*v1[0];\r\n}\r\n\r\n\r\n// dot product (3 components)\r\nfloat DotProduct3(Vec v0, Vec v1)\r\n{\r\n\treturn v0[0]*v1[0] + v0[1]*v1[1] + v0[2]*v1[2];\r\n}\r\n\r\n\r\n// dot product (4 components)\r\nfloat DotProduct4(Vec v0, Vec v1)\r\n{\r\n\treturn v0[0]*v1[0] + v0[1]*v1[1] + v0[2]*v1[2] + v0[3]*v1[3];\r\n}\r\n\r\n\r\n// length of a vector (3 components)\r\nfloat VecLength3(Vec v)\r\n{\r\n\treturn sqrtf(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);\r\n}\r\n\r\n\r\n// copy a matrix\r\n// Md = Ms\r\n//void MatCopy(Mat Md, Mat Ms)\r\n//{\r\n//    int i,j;\r\n//    for (i=0; i<4; i++)\r\n//        for (j=0; j<4; j++)\r\n//            Md[i][j] = Ms[i][j];\r\n//\t*(Mth::Matrix*)Md = *(Mth::Matrix*)Ms;\r\n//}\r\n\r\n\r\n// set a matrix\r\n// M = ((m00,m01,m02,m03), (m10,m11,m12,m13), (m20,m21,m22,m23), (m30,m31,m32,m33))\r\nvoid MatSet(Mat M, float m00, float m01, float m02, float m03,\r\n\t\t\t\t   float m10, float m11, float m12, float m13,\r\n\t\t\t\t   float m20, float m21, float m22, float m23,\r\n\t\t\t\t   float m30, float m31, float m32, float m33)\r\n{\r\n\tM[0][0]=m00, M[0][1]=m01, M[0][2]=m02, M[0][3]=m03;\r\n\tM[1][0]=m10, M[1][1]=m11, M[1][2]=m12, M[1][3]=m13;\r\n\tM[2][0]=m20, M[2][1]=m21, M[2][2]=m22, M[2][3]=m23;\r\n\tM[3][0]=m30, M[3][1]=m31, M[3][2]=m32, M[3][3]=m33;\r\n}\r\n\r\n\r\n\r\n\r\n// zero a matrix\r\n// set M to 4x4 zero matrix\r\nvoid MatZero(Mat M)\r\n{\r\n    int i,j;\r\n    for (i=0; i<4; i++)\r\n        for (j=0; j<4; j++)\r\n            M[i][j] = 0.0;\r\n}\r\n\r\n\r\n// set identity matrix\r\n// set M to 4x4 identity\r\nvoid MatIdentity(Mat M)\r\n{\r\n    int i,j;\r\n    for (i=0; i<4; i++)\r\n        for (j=0; j<4; j++)\r\n            M[i][j] = (i==j) ? 1.0 : 0.0;\r\n}\r\n\r\n\r\n// transpose a matrix\r\n// M = MT\r\nvoid MatTranspose(Mat M)\r\n{\r\n\tfloat temp;\r\n\tint i,j;\r\n\tfor (i=0; i<4; i++)\r\n\t\tfor (j=i+1; j<4; j++)\r\n\t\t\ttemp=M[i][j], M[i][j]=M[j][i], M[j][i]=temp;\r\n}\r\n\r\n\r\n// transpose a matrix\r\n// Md = MsT\r\nvoid MatTransposed(Mat Md, Mat Ms)\r\n{\r\n\tint i,j;\r\n\tfor (i=0; i<4; i++)\r\n\t\tfor (j=0; j<4; j++)\r\n\t\t\tMd[i][j]=Ms[j][i];\r\n}\r\n\r\n\r\n// make a diagonal matrix from the elements of v\r\nvoid MatDiagonal(Mat M, Vec v)\r\n{\r\n\tint i;\r\n\tMatZero(M);\r\n\tfor (i=0; i<4; i++)\r\n\t\tM[i][i] = v[i];\r\n}\r\n\r\n\r\n// scale all elements of a matrix\r\nvoid MatScale(Mat M, float k)\r\n{\r\n\tint i,j;\r\n\tfor (i=0; i<4; i++)\r\n\t\tfor (j=0; j<4; j++)\r\n\t\t\tM[i][j] *= k;\r\n}\r\n\r\n\r\n// set M to matrix for rotation through Angle (radians) about Axis ('x','y' or 'z')\r\nvoid MatRotation(Mat M, float Angle, char Axis)\r\n{\r\n    float s,c;\r\n    int i0=(int)((Axis+1-'x'))%3, i1=(int)((Axis+2-'x'))%3;\r\n    s=sinf(Angle), c=cosf(Angle);\r\n    MatIdentity(M);\r\n    M[i0][i0] = M[i1][i1] = c;\r\n    M[i1][i0] = -(M[i0][i1] = s);\r\n}\r\n\r\n\r\n// set M to matrix for translation by v\r\nvoid MatTranslation(Mat M, Vec v)\r\n{\r\n    MatIdentity(M);\r\n    VecCopy(M[3],v);\r\n}\r\n\r\n\r\n// multiply two matrices to make another\r\n// set AB = A * B\r\nvoid MatProduct(Mat AB, Mat A, Mat B)\r\n{\r\n\t\r\n\t#if 1\t\r\n\tsceVu0MulMatrix((sceVu0FVECTOR*)AB,(sceVu0FVECTOR*)B,(sceVu0FVECTOR*)A);   \r\n\treturn;\r\n\t#else \r\n\t\r\n\tfloat sum;\r\n    int i,j,k;\r\n    for (i=0; i<4; i++)\r\n        for (j=0; j<4; j++)\r\n        {\r\n            sum=0.0;\r\n            for (k=0; k<4; k++)\r\n                sum += A[i][k]*B[k][j];\r\n            AB[i][j] = sum;\r\n        }\r\n\t#endif\t\t\r\n}\r\n\r\n\r\n// premulitplication of one matrix by another\r\n// A = B * A\r\nvoid MatPremultiply(Mat A, Mat B)\r\n{\r\n    Mat TempMat;\r\n    MatProduct(TempMat,B,A);\r\n    MatCopy(A,TempMat);\r\n}\r\n\r\n\r\n// postmultiplication of one matrix by another\r\n// A = A * B\r\nvoid MatPostmultiply(Mat A, Mat B)\r\n{\r\n    Mat TempMat;\r\n    MatProduct(TempMat,A,B);\r\n    MatCopy(A,TempMat);\r\n}\r\n\r\n\r\n// invert a 4x4 matrix\r\n// Md = inv(Ms)\r\n// Note: this is not a general matrix invert: it only works for matrices which incorporate rotation and translation.\r\nvoid MatInverse(Mat Md, Mat Ms)\r\n{\r\n\tint i,j;\r\n\tMat InvT, InvR;\r\n\t// set up negative of original translation\r\n\tMatIdentity(InvT);\r\n\tInvT[3][0] = -Ms[3][0];\r\n\tInvT[3][1] = -Ms[3][1];\r\n\tInvT[3][2] = -Ms[3][2];\r\n\t// set up transpose of original rotation\r\n\tMatIdentity(InvR);\r\n\tfor (i=0; i<3; i++)\r\n\t\tfor (j=0; j<3; j++)\r\n\t\t\tInvR[i][j] = Ms[j][i];\r\n\t// take product\r\n\tMatProduct(Md,InvT,InvR);\r\n}\r\n\r\n\r\n// build a matrix from 3 Euler angles\r\n// M = Rz(Angles[2]) * Rx(Angles[0]) * Ry(Angles[1])\r\nvoid MatEuler(Mat M, Vec Angles)\r\n{\r\n\tMat Temp;\r\n\tMatRotation(M, Angles[2], 'z');\r\n\tMatRotation(Temp, Angles[0], 'x');\r\n\tMatPostmultiply(M, Temp);\r\n\tMatRotation(Temp, Angles[1], 'y');\r\n\tMatPostmultiply(M, Temp);\r\n}\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/mikemath.h",
    "content": "#ifndef __MIKEMATH_H\r\n#define __MIKEMATH_H\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n// typedefs\r\ntypedef float Vec[4] nAlign(128);\t\t// Structurally equivalent to Mth::Vector\r\ntypedef float Mat[4][4] nAlign(128);\t// Structurally equivalent to Mth::Matrix\r\n\r\n// function prototypes\r\nvoid VecCopy(Vec vd, Vec vs);\r\nvoid VecSet(Vec v, float x, float y, float z, float w);\r\nvoid VecSum(Vec vd, Vec v0, Vec v1);\r\nvoid VecAdd(Vec vd, Vec vs);\r\nvoid VecDifference(Vec vd, Vec v0, Vec v1);\r\nvoid VecSubtract(Vec vd, Vec vs);\r\nvoid VecNegate(Vec v);\r\nvoid VecTransform(Vec v, Mat M);\r\nvoid VecTransformed(Vec vd, Vec vs, Mat M);\r\nvoid VecRotate(Vec v, float Angle, char Axis);\r\nvoid VecNormalise(Vec v);\r\nvoid VecScale(Vec v, float k);\r\nvoid VecScaled(Vec vd, float k, Vec vs);\r\nvoid VecAddScaled(Vec vd, float k, Vec vs);\r\nvoid VecWeightedMean2(Vec v, float k0, Vec v0, float k1, Vec v1);\r\nvoid VecWeightedMean3(Vec v, float k0, Vec v0, float k1, Vec v1, float k2, Vec v2);\r\nvoid CrossProduct(Vec vd, Vec v0, Vec v1);\r\nfloat DotProduct3(Vec v0, Vec v1);\r\nfloat DotProduct4(Vec v0, Vec v1);\r\nfloat VecLength3(Vec v);\r\nvoid MatCopy(Mat Md, Mat Ms);\r\nvoid MatSet(Mat M, float m00, float m01, float m02, float m03,\r\n\t\t\t\t   float m10, float m11, float m12, float m13,\r\n\t\t\t\t   float m20, float m21, float m22, float m23,\r\n\t\t\t\t   float m30, float m31, float m32, float m33);\r\nvoid MatZero(Mat M);\r\nvoid MatIdentity(Mat M);\r\nvoid MatTranspose(Mat M);\r\nvoid MatTransposed(Mat Md, Mat Ms);\r\nvoid MatDiagonal(Mat M, Vec v);\r\nvoid MatScale(Mat M, float k);\r\nvoid MatRotation(Mat M, float Angle, char Axis);\r\nvoid MatTranslation(Mat M, Vec v);\r\nvoid MatProduct(Mat AB, Mat A, Mat B);\r\nvoid MatPremultiply(Mat A, Mat B);\r\nvoid MatPostmultiply(Mat A, Mat B);\r\nvoid MatInverse(Mat Md, Mat Ms);\r\nvoid MatEuler(Mat M, Vec Angles);\r\n\r\n\r\ninline void MatCopy(Mat Md, Mat Ms)\r\n{\r\n\t*(Mth::Matrix*)Md = *(Mth::Matrix*)Ms;\r\n}\r\n\r\n\r\n} // namespace NxPs2\r\n\t\t\t\t\t  \r\n\t\t\t\t\t  \r\n#endif // __MIKEMATH_H\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/nx_init.cpp",
    "content": "#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <libgraph.h>\r\n#include <libdma.h>\r\n#include <devvu0.h>\r\n#include <devvu1.h>\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <libsn.h>\r\n#include <sys/file/pip.h>\r\n#include <sys/config/config.h>\r\n#include \"nx_init.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n#include \"vu1code.h\"\r\n#include \"vu0code.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n#include \"dmacalls.h\"\r\n#include \"pcrtc.h\"\r\n#include \"render.h\"\r\n#include \"chars.h\"\r\n#include \"scene.h\"\r\n#include \"group.h\"\r\n#include \"interrupts.h\"\r\n#include \"switches.h\"\r\n#include \"instance.h\"\r\n#include \"geomnode.h\"\r\n#include \"texture.h\"\r\n#include \"resource.h\"\r\n#include \"fx.h\"\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nextern\tvoid\tWaitForRendering();\r\n\r\n// Interrupts\r\nstatic\tvoid\tStartInterrupts();\r\nstatic\tvoid\tStopInterrupts();\r\n\r\nMth::Matrix GmyMat[4];\r\n\r\n// Interrupt Handler IDs\r\n#if USE_INTERRUPTS\r\n\t\r\n#if GIF_INTERRUPT\r\nstatic int sGifHandlerId = -1;\r\n#endif\r\n\r\n#if GS_INTERRUPT\r\nstatic int sGsHandlerId = -1;\r\n#endif\r\n\r\n#if VIF1_INTERRUPT\r\nstatic int sVif1HandlerId = -1;\r\n#endif\r\n\r\n#endif\r\n\r\n//////////////////////////////////////////////////////////////////\r\n// void InitialiseEngine(void)\r\n//\r\n// Sets up the PS2 engine, down to the hardware level\r\n//  - Resets the hardware, using sce library calls, setting video mode\r\n//  - sets up the PCRTC registers (display buffer conficuration, and read circuit anti-aliasing)\r\n//  - Initilizes memory for DMA buffers\r\n//  - Builds the standard DMA subroutines (clear VRAM, page flip, etc)\r\n//  - adds GS, VIF1 and GIF interrupts\r\n//  - creates an empty \"scene\" and an empty group as the default things to render\r\n\r\n\r\nvoid InitialiseEngine(void)\r\n{\r\n    // Mick:  Make it safe to call more than once\r\n    // Needed for a last minute loading screen hack TT#12480\r\n\tstatic bool done = false;\r\n\tif (done)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tdone = true;\r\n\t\r\n\t// Initialize devices\r\n\tsceDmaReset(1);\r\n\tsceGsResetPath();\r\n    sceDevVu1PutDBit(1);\t// sceGsResetPath will clear the D-bit, so need to switch it on\r\n    //sceDevVu0PutTBit(1);\r\n\r\n\t// setup PCRTC registers - switch off display until vram has been cleared\r\n\tSetupPCRTC(0, SCE_GS_FIELD);\r\n\r\n\t// Clear resoruces\r\n\tCSystemResources::sInitResources();\r\n\r\n\t// allocate dma list memory (prebuilt & run-time) and subroutine table\r\n\tdma::pPrebuiltBuffer = (uint8 *)Mem::Calloc(PREBUILT_DMA_BUFFER_SIZE/16,16);\r\n\tDbg_MsgAssert(dma::pPrebuiltBuffer, (\"couldn't malloc memory for prebuilt dma buffer\"));\r\n\t\r\n\tif (Config::GotExtraMemory())\r\n\t{\r\n\t\t// Allocate a dummy buffer so that the current heap's usage is the same\r\n\t\t// as for when there is not extra memory.\r\n\t\tdma::pDummyBuffer = (uint8 *)Mem::Calloc(NON_DEBUG_DMA_BUFFER_SIZE/16,16);\r\n\t\t\r\n\t\t// But for the actual runtime buffer allocate a massive buffer off the debug heap.\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t\tdma::pRuntimeBuffer = (uint8 *)Mem::Calloc(DEBUG_DMA_BUFFER_SIZE/16,16);\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\tDbg_MsgAssert(dma::pRuntimeBuffer, (\"couldn't malloc memory for runtime dma buffer\"));\r\n\t\t// set runtime dma list pointers (they are double buffered, using half the buffer each)\r\n\t\tdma::pList[0] = dma::pRuntimeBuffer;\r\n\t\tdma::pList[1] = dma::pRuntimeBuffer + DEBUG_DMA_BUFFER_SIZE/2;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tdma::pRuntimeBuffer = (uint8 *)Mem::Calloc(NON_DEBUG_DMA_BUFFER_SIZE/16,16);\r\n\t\tDbg_MsgAssert(dma::pRuntimeBuffer, (\"couldn't malloc memory for runtime dma buffer\"));\r\n\t\t// set runtime dma list pointers (they are double buffered, using half the buffer each)\r\n\t\tdma::pList[0] = dma::pRuntimeBuffer;\r\n\t\tdma::pList[1] = dma::pRuntimeBuffer + NON_DEBUG_DMA_BUFFER_SIZE/2;\r\n\t}\r\n\tdma::size = NON_DEBUG_DMA_BUFFER_SIZE/2;  // normal sized (half the buffer)\r\n\t\r\n\t\t\r\n\tdma::Gosubs = (uint64 *)Mem::Calloc(NUM_SUBROUTINES, sizeof(uint64));\r\n\tDbg_MsgAssert(dma::Gosubs, (\"couldn't malloc memory for dma gosub table\"));\r\n\t//Subroutines = (uint8 **)Mem::Calloc(256, sizeof(uint8 *));\r\n\t//Dbg_MsgAssert(Subroutines, (\"couldn't malloc memory for dma gosub table\"));\r\n\r\n\t// initialise dma pointer for use by BuildDmaSubroutines\r\n\tdma::pLoc = dma::pPrebuiltBuffer;\r\n\r\n\t// prebuild dma subroutines (into dma::pPrebuiltBuffer)\r\n\tBuildDmaSubroutines();\r\n\r\n\t// Enable interrupts\r\n\tStartInterrupts();\r\n\r\n\t// wait for v-sync\r\n\tsceGsSyncV(0);\r\n\r\n\t// clear vram\r\n\tFlushCache(WRITEBACK_DCACHE);\r\n\t*D1_QWC  = 0;\t\t\t\t\t\t// must zero QWC because the first action will be to use current MADR & QWC\r\n\t*D1_TADR = dma::Gosubs[CLEAR_VRAM] >> 32;\r\n\t*D1_CHCR = 0x145;\t\t\t\t\t// start transfer, tte=1, chain mode, from memory\r\n\tsceGsSyncPath(0, 0);\r\n\r\n\t// setup PCRTC registers - vram is cleared so switch on display\r\n\tSetupPCRTC(1, SCE_GS_FIELD);\r\n\r\n\t// upload vu0 code\r\n\t*D0_QWC  = ((uint8 *)MPGEnd0-(uint8 *)MPGStart0+15)/16;\r\n\t*D0_MADR = (uint)MPGStart0;\r\n\t*D0_CHCR = 0x100;\t\t\t\t\t// start transfer, normal mode\r\n\tsceGsSyncPath(0, 0);\r\n\r\n\t// empty scene list\r\n\tsScene::pHead = NULL;\r\n\r\n\t// create the shadow group\r\n\tsGroup::pShadow = (sGroup *)Mem::Malloc(sizeof(sGroup));\r\n\tmemset(sGroup::pShadow,0,sizeof(sGroup));\r\n\tDbg_MsgAssert(sGroup::pShadow, (\"couldn't allocate shadow group\\n\"));\r\n\tsGroup::pShadow->Priority = 1500.001f;\r\n\tsGroup::pShadow->pMeshes = NULL;\r\n\tsGroup::pShadow->NumMeshes = 0;\r\n\t#if STENCIL_SHADOW\r\n\tsGroup::pShadow->VramStart = 0x3740;\r\n\t#else\r\n\tsGroup::pShadow->VramStart = 0x3E00;\r\n\t#endif\r\n\tsGroup::pShadow->VramEnd   = 0x4000;\r\n\tsGroup::pShadow->flags = 0;\r\n\tsGroup::pShadow->profile_color = 0xFFFFFF;\t\t// bright white = shadow group\r\n\r\n\t// create the fog group\r\n\tsGroup::pFog = (sGroup *)Mem::Malloc(sizeof(sGroup));\r\n\tmemset(sGroup::pFog,0,sizeof(sGroup));\r\n\tDbg_MsgAssert(sGroup::pFog, (\"couldn't allocate fog group\\n\"));\r\n\tsGroup::pFog->Priority = 9999.0f;\r\n\tsGroup::pFog->pMeshes = NULL;\r\n\tsGroup::pFog->NumMeshes = 0;\r\n\tsGroup::pFog->VramStart = 0x3000;\r\n\tsGroup::pFog->VramEnd   = 0x4000;\r\n\tsGroup::pFog->flags = 0;\r\n\tsGroup::pFog->pScene = NULL;\r\n\tsGroup::pFog->profile_color = 0x303030;\t\t\t// dark grey = fog group\r\n\t\r\n\t// create the particle group\r\n\tsGroup::pParticles = (sGroup *)Mem::Malloc(sizeof(sGroup));\r\n\tmemset(sGroup::pParticles,0,sizeof(sGroup));\r\n\tDbg_MsgAssert(sGroup::pParticles, (\"couldn't allocate particle group\\n\"));\r\n\tsGroup::pParticles->Priority = 10000.0f;\r\n\tsGroup::pParticles->pMeshes = NULL;\r\n\tsGroup::pParticles->NumMeshes = 0;\r\n\tsGroup::pParticles->VramStart = 0x3000;\r\n\tsGroup::pParticles->VramEnd   = 0x4000;\r\n\tsGroup::pParticles->flags = 0;\r\n\tsGroup::pParticles->pScene = NULL;\r\n\tsGroup::pParticles->profile_color = 0x0;\t\t// black = particle group\r\n\r\n\t// create epilogue group\r\n\tsGroup::pEpilogue = (sGroup *)Mem::Malloc(sizeof(sGroup));\r\n\tmemset(sGroup::pEpilogue,0,sizeof(sGroup));\r\n\tDbg_MsgAssert(sGroup::pEpilogue, (\"couldn't allocate epilogue group\\n\"));\r\n\tsGroup::pEpilogue->Priority = 1000000;\r\n\tsGroup::pEpilogue->pMeshes = NULL;\r\n\tsGroup::pEpilogue->NumMeshes = 0;\r\n\tsGroup::pEpilogue->VramStart = 0x0000;\t// pretend it uses all of vram\r\n\tsGroup::pEpilogue->VramEnd   = 0x4000;\t// so there's no buffer address worries\r\n\tsGroup::pEpilogue->profile_color = 0x800000;\t\t// blue = epilogue group\r\n\r\n\t// link predefined groups together\r\n\tsGroup::pShadow->pNext = sGroup::pFog;\r\n\tsGroup::pFog->pNext = sGroup::pParticles;\r\n\tsGroup::pParticles->pNext = sGroup::pEpilogue;\r\n\tsGroup::pEpilogue->pNext = NULL;\r\n\tsGroup::pShadow->pPrev = NULL;\r\n\tsGroup::pFog->pPrev = sGroup::pShadow;\r\n\tsGroup::pParticles->pPrev = sGroup::pFog;\r\n\tsGroup::pEpilogue->pPrev = sGroup::pParticles;\r\n\tsGroup::pHead = sGroup::pShadow;\r\n\tsGroup::pTail = sGroup::pEpilogue;\r\n\r\n\t// initialise vram group buffering scheme\r\n\tsGroup::VramBufferBase = 0x2BC0;\r\n\r\n\t// initialise font vram base pointer\r\n\tFontVramStart = FontVramBase = 0x2BC0;\t// a cheat\r\n\r\n\t// initialise empty font list\r\n\tpFontList = NULL;\r\n\r\n\r\n\r\n\t// activate the world!\r\n\tCGeomNode::sWorld.SetActive(true);\r\n\r\n\t// set up fog palette\r\n//\tFx::SetupFogPalette(0x40806060, 10.0f);\r\n}\r\n\r\nvoid \tAllocateExtraDMA(bool allocate)\r\n{\r\n\tstatic void * s_extra = NULL;\r\n\tstatic void * old_pList1;\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\r\n\tif (allocate)\r\n\t{\r\n\t\tDbg_MsgAssert(!s_extra,(\"Tried to allocate extra DMA when already allocated\"));\r\n\t\told_pList1 = dma::pList[1];\r\n\t\ts_extra = (uint8 *)Mem::Calloc(NON_DEBUG_DMA_BUFFER_SIZE/16,16);\t  // same size as the entire double buffer\r\n\t\tdma::pList[1] = (uint8 *)s_extra;\r\n\t\tdma::size = NON_DEBUG_DMA_BUFFER_SIZE;  // double sized\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (s_extra)\r\n\t\t{\r\n\t\t\tdma::pList[1] = (uint8 *)old_pList1;\r\n\t\t\tMem::Free(s_extra);\r\n\t\t\ts_extra = NULL;\r\n\t\t\tdma::size = NON_DEBUG_DMA_BUFFER_SIZE/2;  // normal sized\r\n\t\t}\r\n\t}\r\n\t\r\n\tdma::pLoc = 0 ;  \t// reset pLoc as it might not be valid.  This will catch this function being called in the wrong place\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\t\r\n}\r\n\r\n\r\n//////////////////////////////////////////////////////////////////\r\n// void ResetEngine(void)\r\n//\r\n// Sets up the PS2 engine, down to the hardware level\r\n//  - Resets the hardware, using sce library calls, setting video mode\r\n//  - sets up the PCRTC registers (display buffer conficuration, and read circuit anti-aliasing)\r\n//  - clears VRAM, which also sets the TEXA register\r\n//  - resets GS, VIF1 and GIF interrupts\r\n\r\nvoid ResetEngine(void)\r\n{\r\n\t// initialize devices\r\n\tsceDmaReset(1);\r\n\tsceGsResetPath();\r\n    sceDevVu1PutDBit(1);\t// sceGsResetPath will clear the D-bit, so need to switch it on\r\n    //sceDevVu0PutTBit(1);\r\n\r\n\t// Don't call sceGsResetGraph() anymore.  It interferes with SetupPCRTC().\r\n\t//// re-initialize the GS\r\n\t//if (Config::NTSC())\r\n\t//{\r\n\t//\tsceGsResetGraph(0, SCE_GS_INTERLACE, SCE_GS_NTSC, SCE_GS_FIELD);\r\n\t//} else {\r\n\t//\tsceGsResetGraph(0, SCE_GS_INTERLACE, SCE_GS_PAL, SCE_GS_FIELD);\r\n\t//}\r\n\r\n\t// setup PCRTC registers (don't need this call anymore; the last call is all that is necessary)\r\n\t//SetupPCRTC(0, SCE_GS_FIELD);\r\n\r\n\t// restart interrupts\r\n\tStartInterrupts();\r\n\r\n\t// wait for v-sync\r\n\tsceGsSyncV(0);\r\n\r\n\t// clear vram (Garrett: This is the ONLY place that TEXA is ever set!  Caused many weird bugs if not called.)\r\n\tFlushCache(WRITEBACK_DCACHE);\r\n\t*D1_QWC  = 0;\t\t\t\t\t\t// must zero QWC because the first action will be to use current MADR & QWC\r\n\t*D1_TADR = dma::Gosubs[CLEAR_VRAM] >> 32;\r\n\t*D1_CHCR = 0x145;\t\t\t\t\t// start transfer, tte=1, chain mode, from memory\r\n\tsceGsSyncPath(0, 0);\r\n\r\n\t// setup PCRTC registers - vram is cleared so switch on display\r\n\tSetupPCRTC(1, SCE_GS_FIELD);\r\n\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////\r\n// void SuspendEngine(void)\r\n//\r\n// Suspends the PS2 engine by waiting for any rendering to finish\r\n// and then shuts down the interrupts.\r\n\r\nvoid SuspendEngine(void)\r\n{\r\n\t// Let the engine finish what it was doing first\r\n\tWaitForRendering();\r\n\r\n\t// stop interrupts\r\n\tStopInterrupts();\r\n}\r\n\r\n\r\n//////////////////////////////////////////////////////////////////\r\n// void StartInterrupts(void)\r\n//\r\n// Starts all the interrupts for the PS2 engine.\r\n\r\nstatic void StartInterrupts(void)\r\n{\r\n\t#if USE_INTERRUPTS\r\n\t\r\n\t#if GIF_INTERRUPT\r\n    // install interrupt handler for texture upload completion\r\n\tif ((sGifHandlerId = AddDmacHandler(DMAC_GIF, GifHandler, 0)) == -1)\r\n\t{\r\n\t\tprintf(\"Couldn't register dmac handler\\n\");\r\n\t\texit(1);\r\n\t}\r\n\t*D_STAT = 1 << DMAC_GIF;\r\n\tEnableDmac(DMAC_GIF);\r\n\t#endif\r\n\r\n\t#if GS_INTERRUPT\r\n    // install interrupt handler for render completion\r\n\tif ((sGsHandlerId = AddIntcHandler(INTC_GS, GsHandler, 0)) == -1)\r\n\t{\r\n\t\tprintf(\"Couldn't register GS handler\\n\");\r\n\t\texit(1);\r\n\t}\r\n\t*GS_IMR = PackIMR(0,1,1,1);\t\t// SIGNAL, FINISH, HSync, VSync\r\n\tEnableIntc(INTC_GS);\r\n\t#endif\r\n\t\r\n\t#if VIF1_INTERRUPT\r\n    // install interrupt handler for render completion\r\n\tif ((sVif1HandlerId = AddIntcHandler(INTC_VIF1, Vif1Handler, 0)) == -1)\r\n\t{\r\n\t\tprintf(\"Couldn't register vif1 handler\\n\");\r\n\t\texit(1);\r\n\t}\r\n\t*VIF1_ERR = 0;\r\n\tEnableIntc(INTC_VIF1);\r\n\t#endif\r\n\r\n\t// set intermittent mode transfer\r\n\t*GIF_MODE = 0x0;\r\n\t#endif\r\n\r\n}\r\n\r\n\r\n\r\n//////////////////////////////////////////////////////////////////\r\n// void StopInterrupts(void)\r\n//\r\n// Stops all the interrupts for the PS2 engine.\r\n\r\nstatic void StopInterrupts(void)\r\n{\r\n\t#if USE_INTERRUPTS\r\n\t\r\n\t#if GIF_INTERRUPT\r\n    // remove interrupt handler for texture upload completion\r\n\tDisableDmac(DMAC_GIF);\r\n\tif (sGifHandlerId >= 0)\r\n\t{\r\n\t\tRemoveDmacHandler(DMAC_GIF, sGifHandlerId);\r\n\t\tsGifHandlerId = -1;\r\n\t}\r\n\t#endif\r\n\r\n\t#if GS_INTERRUPT\r\n    // remove interrupt handler for render completion\r\n\tDisableIntc(INTC_GS);\r\n\tif (sGsHandlerId >= 0)\r\n\t{\r\n\t\tRemoveIntcHandler(INTC_GS, sGsHandlerId);\r\n\t\tsGsHandlerId = -1;\r\n\t}\r\n\t#endif\r\n\t\r\n\t#if VIF1_INTERRUPT\r\n    // remove interrupt handler for render completion\r\n\tDisableIntc(INTC_VIF1);\r\n\tif (sVif1HandlerId >= 0)\r\n\t{\r\n\t\tRemoveIntcHandler(INTC_VIF1, sVif1HandlerId);\r\n\t\tsVif1HandlerId = -1;\r\n\t}\r\n\t#endif\r\n\r\n\t#endif\r\n}\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/nx_init.h",
    "content": "#ifndef __NX_INIT_H\r\n#define __NX_INIT_H\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nvoid InitialiseEngine(void);\r\nvoid ResetEngine(void);\r\nvoid SuspendEngine(void);\r\nvoid AllocateExtraDMA(bool allocate);\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n#endif // __NX_INIT_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/occlude.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics (GFX)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tocclude.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t04/02/02\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tOcclusion testing code\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\r\n#include <core/math.h>\r\n#include <gfx/debuggfx.h>\r\n//#include <libdma.h>\r\n#include \"occlude.h\"\r\n#include \"resource.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//extern D3DXMATRIX *p_bbox_transform;\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic bool sCopiedOccludersOffline = false;\t\t// tells that occluders have been copied to a fast ram and the\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nuint32\t\t\tNumOcclusionPolys\t\t\t= 0;\r\nuint32\t\t\tNextOcclusionPolyToCheck\t= 0;\r\nsOcclusionPoly\tOcclusionPolys[MAX_OCCLUSION_POLYS];\r\n\r\nuint32\t\tsOccluder::NumOccluders\t\t\t\t= 0;\r\nsOccluder\tsOccluder::Occluders[MAX_OCCLUDERS];\r\nbool\t\tsOccluder::sUseVU0 = false;\r\nbool\t\tsOccluder::sUseScratchPad = false;\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sOccluder::add_to_stack( sOcclusionPoly *p_poly )\r\n{\r\n\tif( NumOccluders < MAX_OCCLUDERS )\r\n\t{\r\n\t\tOccluders[NumOccluders].p_poly\t= p_poly;\r\n\t\tp_poly->in_use\t\t\t\t\t= true;\r\n\t\t++NumOccluders;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int cmp( const void *p1, const void *p2 )\r\n{\r\n\t// Zero the score for any occlusion poly that is no longer available. This will force it out of the stack.\r\n\tif(((sOccluder*)p1)->p_poly->available == false )\r\n\t\t((sOccluder*)p1)->score = 0;\r\n\r\n\tif(((sOccluder*)p2)->p_poly->available == false )\r\n\t\t((sOccluder*)p2)->score = 0;\r\n\r\n\treturn((sOccluder*)p1)->score < ((sOccluder*)p2)->score ? 1 : ((sOccluder*)p1)->score > ((sOccluder*)p2)->score ? -1 : 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sOccluder::sort_stack( void )\r\n{\r\n\tqsort( Occluders, NumOccluders, sizeof( sOccluder ), cmp );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sOccluder::tidy_stack( void )\r\n{\r\n\tif( NumOccluders > 0 )\r\n\t{\r\n\t\t// Sort in descending score order.\r\n\t\tsort_stack();\r\n\t\t\r\n\r\n\t\tint total = 0;\r\n\t\tint demoted = 0;\r\n\t\t// Count backwards so we know we get all the bad occluders.\r\n\t\tfor( int i = NumOccluders - 1; i >= 0; --i )\r\n\t\t{\r\n\t\t\t// If we have hit an occluder with zero meshes culled, cut off the stack at this point.\r\n\t\t\t// also, if the stack is full, then demote the lowest scoring 4\r\n\t\t\tif( Occluders[i].score == 0  || i > (int)(MAX_OCCLUDERS-MIN_NEW_OCCLUSION_POLYS_TO_CHECK_PER_FRAME))\r\n\t\t\t{\r\n\t\t\t\t// No longer using this poly.\r\n\t\t\t\tOccluders[i].p_poly->in_use = false;\r\n\r\n\t\t\t\t// One less occluder to worry about.\r\n\t\t\t\t--NumOccluders;\r\n\t\t\t\tdemoted++;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ttotal += Occluders[i].score;\r\n\t\t\t\t// Reset the good occluders.\r\n\t\t\t\tOccluders[i].score = 0;\r\n\t\t\t}\r\n\t\t}\r\n//\t\tprintf (\"\\nOccluded %d objects with %d Occluders (demoted %d)\\n\",total,NumOccluders,demoted);\r\n\t}\r\n\t\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Used to add an occlusion poly to the list. Likely to be called */\r\n/* as geometry is spooled in.                                     */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid AddOcclusionPoly( Mth::Vector &v0, Mth::Vector &v1, Mth::Vector &v2, Mth::Vector &v3, uint32 checksum )\r\n{\r\n//\tprintf (\" Adding occlusion polygons, currently %d\\n\",NumOcclusionPolys);\r\n\tDbg_MsgAssert( NumOcclusionPolys < MAX_OCCLUSION_POLYS,(\"Too many (%d) occlusion polygons\",NumOcclusionPolys) );\t\r\n\t\r\n\tOcclusionPolys[NumOcclusionPolys].in_use\t= false;\r\n\tOcclusionPolys[NumOcclusionPolys].available\t= true;\r\n\tOcclusionPolys[NumOcclusionPolys].checksum\t= checksum;\r\n\tOcclusionPolys[NumOcclusionPolys].verts[0]\t= v0;\r\n\tOcclusionPolys[NumOcclusionPolys].verts[1]\t= v1;\r\n\tOcclusionPolys[NumOcclusionPolys].verts[2]\t= v2;\r\n\tOcclusionPolys[NumOcclusionPolys].verts[3]\t= v3;\r\n\tOcclusionPolys[NumOcclusionPolys].normal\t= Mth::CrossProduct( v1 - v0, v3 - v0 );\r\n\tOcclusionPolys[NumOcclusionPolys].normal.Normalize();\r\n\t\r\n\t++NumOcclusionPolys;\r\n\r\n    sCopiedOccludersOffline = false;\t\t// current scores now invalid\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Used to toggle whether an occlusion poly can be used or not\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid EnableOcclusionPoly( uint32 checksum, bool available )\r\n{\r\n\tfor( uint32 i = 0; i < NumOcclusionPolys; ++i )\r\n\t{\r\n\t\tif( OcclusionPolys[i].checksum == checksum )\r\n\t\t{\r\n\t\t\tOcclusionPolys[i].available\t= available;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Used to clear all occlusion polys (when a level is unloaded)   */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid RemoveAllOcclusionPolys( void )\r\n{\r\n\tDbg_Assert( NumOcclusionPolys < MAX_OCCLUSION_POLYS );\t\r\n\t\r\n \tsOccluder::NumOccluders\t\t= 0;\r\n\tNumOcclusionPolys\t\t\t= 0;\r\n\tNextOcclusionPolyToCheck\t= 0;\r\n\r\n    sCopiedOccludersOffline = false;\t\t// current scores now invalid\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CheckForOptimalOccluders( Mth::Vector &cam_pos, Mth::Vector &view_direction )\r\n{\r\n\tif( NumOcclusionPolys > 0 )\r\n\t{\r\n\t\tuint32 added\t= 0;\r\n\t\tuint32 checked\t= 0;\r\n\r\n\t\twhile( added < MAX_NEW_OCCLUSION_POLYS_TO_CHECK_PER_FRAME )\r\n\t\t{\r\n\t\t\t// Given the current position of the camera, check through the unused occlusion polys to see if one scores higher\r\n\t\t\t// than the lowest scoring occlusion poly in use.\r\n\t\t\tsOcclusionPoly *poly_to_check = &OcclusionPolys[NextOcclusionPolyToCheck++];\r\n\t\t\tif(( !poly_to_check->in_use ) && ( poly_to_check->available ))\r\n\t\t\t{\r\n\t\t\t\tsOccluder::add_to_stack( poly_to_check );\r\n\t\t\t\t++added;\r\n\t\t\t}\r\n\t\t\t++checked;\r\n\r\n\t\t\t// Ensure we are always checking within bounds.\r\n\t\t\tif( NextOcclusionPolyToCheck >= NumOcclusionPolys )\r\n\t\t\t{\r\n\t\t\t\tNextOcclusionPolyToCheck = 0;\r\n\t\t\t}\r\n\r\n\t\t\t// Quit out if we have less available occluders than spaces to fill.\r\n\t\t\tif( checked >= NumOcclusionPolys )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n//char scratch[16384];\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid BuildOccluders( Mth::Vector *p_cam_pos )\r\n{\r\n#ifdef\tOCCLUDER_USES_VU0_MACROMODE\r\n\tif (sCopiedOccludersOffline)\r\n\t{\r\n\t\tsOccluder * p_occluder = &sOccluder::Occluders[0];\r\n\t\tuint128 * p_vu0_mem = (uint128*)0x11004060;     // Start of first score\r\n\r\n\t\tfor( uint32 o = sOccluder::NumOccluders; o > 0 ; --o )\r\n\t\t{\r\n\t\t\tp_occluder->score = *((uint32*) (p_vu0_mem));\r\n\t\t\tp_occluder++;\r\n\t\t\tp_vu0_mem += 6;\r\n\t\t}\r\n\r\n\t\tsCopiedOccludersOffline = false;\t// we are now up-to-date\r\n\t}\r\n#endif\r\n\tfor( uint32 i = 0; i < NumOcclusionPolys; ++i )\r\n\t{\r\n//\t\tGfx::AddDebugLine( OcclusionPolys[i].verts[0], OcclusionPolys[i].verts[1], 0xFFFFFFFFUL, 0, 1 );\r\n//\t\tGfx::AddDebugLine( OcclusionPolys[i].verts[1], OcclusionPolys[i].verts[2], 0xFFFFFFFFUL, 0, 1 );\r\n//\t\tGfx::AddDebugLine( OcclusionPolys[i].verts[2], OcclusionPolys[i].verts[3], 0xFFFFFFFFUL, 0, 1 );\r\n//\t\tGfx::AddDebugLine( OcclusionPolys[i].verts[3], OcclusionPolys[i].verts[0], 0xFFFFFFFFUL, 0, 1 );\r\n\t}\r\n\t\r\n\t// Tidy up from last frame.\r\n\tsOccluder::tidy_stack();\r\n\t\r\n\t// Cyclically add more occluders for checking.\r\n\tCheckForOptimalOccluders( *p_cam_pos, *p_cam_pos );\r\n\t\r\n\t// Build all 5 planes for each occluder.\r\n\tMth::Vector u0, u1, p;\r\n\r\n\t// The order in which the verts are used to build tha planes depends upon where the camera is in relation to the occlusion\r\n\t// poly. We use the default order when the viewpoint is on the side of the poly on which the default poly normal faces.\r\n\tfor( uint32 i = 0; i < sOccluder::NumOccluders; ++i )\r\n\t{\r\n\t\tsOcclusionPoly *p_poly = sOccluder::Occluders[i].p_poly;\r\n\t\tif( Mth::DotProduct( *p_cam_pos - p_poly->verts[0], p_poly->normal ) >= 0.0f )\r\n\t\t{\r\n\t\t\t// Start with left (0->1->2)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[0] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[1] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= -Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[0]\t= p;\r\n\r\n\t\t\t// ...then right (0->3->4)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[2] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[3] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= -Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[1]\t= p;\r\n\r\n\t\t\t// ...then top (0->2->3)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[1] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[2] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= -Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[2]\t= p;\r\n\r\n\t\t\t// ...then bottom (0->4->1)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[3] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[0] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= -Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[3]\t= p;\r\n\r\n\t\t\t// ...then front. We want to reverse the order of the front plane to ensure that objects *behind* the plane\r\n\t\t\t// are considered occluded. (1->3->4)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[2] - p_poly->verts[0];\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[3] - p_poly->verts[0];\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= -Mth::DotProduct( p, p_poly->verts[0] );\r\n\t\t\tsOccluder::Occluders[i].planes[4]\t= p;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Start with left (0->2->1)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[1] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[0] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= -Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[0]\t= p;\r\n\r\n\t\t\t// ...then right (0->4->3)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[3] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[2] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= -Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[1]\t= p;\r\n\r\n\t\t\t// ...then top (0->3->2)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[2] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[1] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= -Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[2]\t= p;\r\n\r\n\t\t\t// ...then bottom (0->1->4)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[0] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[3] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= -Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[3]\t= p;\r\n\r\n\t\t\t// ...then front. We want to reverse the order of the front plane to ensure that objects *behind* the plane\r\n\t\t\t// are considered occluded. (1->4->3)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[3] - p_poly->verts[0];\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[2] - p_poly->verts[0];\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= -Mth::DotProduct( p, p_poly->verts[0] );\r\n\t\t\tsOccluder::Occluders[i].planes[4]\t= p;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\tif (sOccluder::sUseScratchPad)\r\n\t{\r\n\t\t// Copy the occlusion polygons to the scratchpad\r\n\t\t// as we will read them a zillion times during rendering\r\n\t\tsOccluder * p_occluder = &sOccluder::Occluders[0];\r\n\t\tsOccluder * p_scratch = (sOccluder*)0x70000000;\r\n\t//\tsOccluder * p_scratch = (sOccluder*)scratch;\r\n\t\tfor( uint32 o = sOccluder::NumOccluders; o > 0 ; --o )\r\n\t\t{\r\n\t\t\t*p_scratch = *p_occluder;\r\n\t\t\tp_occluder++;\r\n\t\t\tp_scratch++;\r\n\t\t}\r\n\t\tDbg_MsgAssert((void*)p_scratch < (void*)0x70004000,(\"Scratchpad overflow\"));  // 16k scratchpad.  Nice.\r\n\t}\r\n\r\n#ifdef\tOCCLUDER_USES_VU0_MACROMODE\r\n\tsOccluder * p_occluder = &sOccluder::Occluders[0];\r\n\tuint128 * p_vu0_mem = (uint128*)0x11004000;\t\t// VU0 data memory\r\n\r\n\t// Copies the number of occulders into X\r\n\t*((uint32*) (p_vu0_mem++)) = sOccluder::NumOccluders;\r\n\r\n\tfor( uint32 o = sOccluder::NumOccluders; o > 0 ; --o )\r\n\t{\r\n\t\t*(p_vu0_mem++) = *((uint128*) &(p_occluder->planes[0]));\r\n\t\t*(p_vu0_mem++) = *((uint128*) &(p_occluder->planes[1]));\r\n\t\t*(p_vu0_mem++) = *((uint128*) &(p_occluder->planes[2]));\r\n\t\t*(p_vu0_mem++) = *((uint128*) &(p_occluder->planes[3]));\r\n\t\t*(p_vu0_mem++) = *((uint128*) &(p_occluder->planes[4]));\r\n\t\t*((uint32*) (p_vu0_mem++)) = p_occluder->score;\r\n\t\tp_occluder++;\r\n\t}\r\n\r\n\tFlushCache(WRITEBACK_DCACHE);\r\n\r\n\tDbg_MsgAssert((void*)p_vu0_mem < (void*)0x11005000,(\"VU0 memory overflow\"));  // 4k vu0 mem.  Nice.\r\n\r\n    sCopiedOccludersOffline = true;\t\t\t// so we know to copy the scores back (technically, this should be in\r\n\t\t\t\t\t\t\t\t\t\t\t// TestSphereAgainstOccluders(), but we only want to write this var once\r\n#endif\r\n\r\n\r\n\r\n\r\n#ifdef\tOCCLUDER_USES_VU0_MICROMODE\r\n\r\n\t// copy occlusion planes to VUMem0\r\n\tsOccluder * p_occluder = &sOccluder::Occluders[0];\r\n// Mick: removed this to fix a warning in final build.\r\n//\tfloat * p_vumem0 = (float *)0x11004000;\t\t// VUMem0\r\n\tMth::Vector * p_plane;\r\n\tasm (\"viaddi vi01,vi00,0\": : : \"$8\");\r\n\tfor( uint32 o = sOccluder::NumOccluders; o > 0 ; --o )\r\n\t{\r\n\t\tp_plane = &(p_occluder->planes[0]);\r\n\t\tfor( uint32 p = 5; p > 0; --p )\r\n\t\t{\r\n\t\t\t#if 0\r\n\t\t\t*p_vumem0++ = p_plane->GetX();\r\n\t\t\t*p_vumem0++ = p_plane->GetY();\r\n\t\t\t*p_vumem0++ = p_plane->GetZ();\r\n\t\t\t*p_vumem0++ = p_plane->GetW();\r\n\t\t\t#else\r\n\t\t\t// this way we don't need the FlushCache()\r\n\t\t\tasm __volatile__(\"\r\n\r\n\t\t\t\tlq\t\t$8,0(%0)\r\n\t\t\t\tqmtc2\t$8,vf01\r\n\t\t\t\tvsqi\tvf01,(vi01++)\r\n\r\n\t\t\t\": : \"r\" (p_plane) : \"$8\");\r\n\t\t\t#endif\r\n\t\t\tp_plane++;\r\n\t\t}\r\n\t\tp_occluder++;\r\n\t}\r\n// Mick - removed this assertions as it is no longer valid\r\n//\tDbg_MsgAssert((void*)p_vumem0 < (void*)0x11004FA0,(\"VUMem0 overflow\"));\t\t// 50 occluders max\r\n\r\n\t// flush the cache so VU0 can work on the data now.... not needed anymore\r\n\t//FlushCache(WRITEBACK_DCACHE);\r\n\r\n\t// call vu0 microsubroutine to rearrange data into a special format\r\n\tasm __volatile__(\"\r\n\r\n\t\t#sync\t\t\t\t\t\t\t\t\t# wait for write-back of the mem we just wrote to\r\n\t\tlw\t\t\t$8,(%0)\t\t\t\t\t\t# t0 = num occluders\r\n\t\tctc2\t\t$8,$vi01\t\t\t\t\t# move it to vi01 in vu0\r\n\t\tvcallms\t\tInitialiseOccluders\t\t\t# call microsubroutine to rearrange vu0 memory\r\n\t\tvnop\t\t\t\t\t\t\t\t\t# interlocking instruction, waits for vu0 completion\r\n\t\r\n\t\": : \"r\" (&sOccluder::NumOccluders) : \"$8\");\r\n\r\n\r\n#endif\r\n\r\n\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool OccludeUseVU0()\r\n{\r\n\treturn sOccluder::sUseVU0 = CSystemResources::sRequestResource(CSystemResources::vVU0_MEMORY);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid OccludeDisableVU0()\r\n{\r\n\tif (sOccluder::sUseVU0)\r\n\t{\r\n\t\tCSystemResources::sFreeResource(CSystemResources::vVU0_MEMORY);\r\n\t\tsOccluder::sUseVU0 = false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool OccludeUseScratchPad()\r\n{\r\n\treturn sOccluder::sUseScratchPad = CSystemResources::sRequestResource(CSystemResources::vSCRATCHPAD_MEMORY);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid OccludeDisableScratchPad()\r\n{\r\n\tif (sOccluder::sUseScratchPad)\r\n\t{\r\n\t\tCSystemResources::sFreeResource(CSystemResources::vSCRATCHPAD_MEMORY);\r\n\t\tsOccluder::sUseScratchPad = false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n} // namespace NxXbox\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/occlude.h",
    "content": "#ifndef\t__OCCLUDE_H__\r\n#define\t__OCCLUDE_H__\r\n\r\n//#define\tOCCLUDER_USES_VU0_MACROMODE\r\n#define\tOCCLUDER_USES_VU0_MICROMODE\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\tvoid AddOcclusionPoly( Mth::Vector &v0, Mth::Vector &v1, Mth::Vector &v2, Mth::Vector &v3, uint32 checksum = 0 );\r\n\tvoid EnableOcclusionPoly( uint32 checksum, bool available );\r\n\tvoid RemoveAllOcclusionPolys( void );\r\n\tvoid BuildOccluders( Mth::Vector *p_cam_pos );\r\n\tbool TestSphereAgainstOccluders( Mth::Vector *p_center, float radius, uint32 meshes = 1 );\r\n\r\n\tbool OccludeUseVU0();\r\n\tvoid OccludeDisableVU0();\r\n\r\n\tbool OccludeUseScratchPad();\r\n\tvoid OccludeDisableScratchPad();\r\n\r\n\r\nconst uint32 MAX_NEW_OCCLUSION_POLYS_TO_CHECK_PER_FRAME = 4;\r\nconst uint32 MIN_NEW_OCCLUSION_POLYS_TO_CHECK_PER_FRAME = 4;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Structure used to store details of a single poly. A list of these will be built at geometry load time.\r\nstruct sOcclusionPoly\r\n{\r\n\tbool\t\tin_use;\r\n\tbool\t\tavailable;\t// Whether the poly is available for selection for occlusion.\r\n\tuint32\t\tchecksum;\t// Name checksum of the occlusion poly.\r\n\tMth::Vector\tverts[4];\r\n\tMth::Vector\tnormal;\r\n};\r\n\t\r\nconst uint32\tMAX_OCCLUDERS\t\t\t\t= 12;\r\n\r\nstruct sOccluder\r\n{\r\n\tstatic uint32\t\tNumOccluders;\r\n\tstatic sOccluder\tOccluders[MAX_OCCLUDERS];\r\n\tstatic bool\t\t\tsUseVU0;\r\n\tstatic bool\t\t\tsUseScratchPad;\r\n\r\n\tstatic void\t\t\tadd_to_stack( sOcclusionPoly *p_poly );\r\n\tstatic void\t\t\tsort_stack( void );\r\n\tstatic void\t\t\ttidy_stack( void );\r\n\r\n\tsOcclusionPoly\t*p_poly;\r\n\tMth::Vector\t\tplanes[5];\r\n\tint\t\t\t\tscore;\t\t\t// Current rating on quality of occlusion - based on number of meshes occluded last frame.\r\n};\r\n\r\nconst uint32\tMAX_OCCLUSION_POLYS\t\t\t= 128; \t\t// not currently useing that many\r\nextern uint32\t\t\tNumOcclusionPolys;\r\nextern uint32\t\t\tNextOcclusionPolyToCheck;\r\nextern sOcclusionPoly\tOcclusionPolys[];\r\n\r\n\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/pcrtc.cpp",
    "content": "#include <eeregs.h>\r\n#include <libgraph.h>\r\n#include <core/defines.h>\r\n#include \"pcrtc.h\"\r\n#include \"gs.h\"\r\n#include \"switches.h\"\r\n#include \"render.h\"\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// void SetupPCRTC(void)\r\n//\r\n// Sets up the read circuit blending that provides anti-aliasing\r\n// also sets the background color (to 0,0,0)\r\n//\r\n// Note, this is dependent on HRES and VRES for horizontal and vertical resolution\r\n\r\nvoid SetupPCRTC(int Enable, int FFMode, int HRes, int VRes)\t\t// HRes and VRes default to 0\r\n{\r\n\t// initialize the GS once with sceGsResetGraph().  It is the only way to set NTSC or PAL mode.\r\n\tstatic bool inited = false;\r\n\tif (!inited)\r\n\t{\r\n\t\tsceGsSyncV(0);\r\n\t\tif (Config::NTSC())\r\n\t\t{\r\n\t\t\tsceGsResetGraph(0, SCE_GS_INTERLACE, SCE_GS_NTSC, SCE_GS_FIELD);\r\n\t\t} else {\r\n\t\t\tsceGsResetGraph(0, SCE_GS_INTERLACE, SCE_GS_PAL, SCE_GS_FIELD);\r\n\t\t}\r\n\r\n\t\tinited = true;\r\n\t}\r\n\r\n\t// zero resolution => use default res\r\n\tif (!HRes)\r\n\t\tHRes = HRES;\r\n\tif (!VRes)\r\n\t\tVRes = VRES;\r\n\r\n\ttGS_SMODE2   smode2;\r\n\ttGS_PMODE    pmode;\r\n\ttGS_DISPFB1  dispfb1;\r\n\ttGS_DISPLAY1 display1;\r\n\ttGS_DISPFB2  dispfb2;\r\n\ttGS_DISPLAY2 display2;\r\n\ttGS_BGCOLOR  bgcolor;\r\n\r\n\t// sync mode (SMODE2 register)\r\n\tsmode2.INT  = SCE_GS_INTERLACE;\r\n\tsmode2.FFMD = FFMode;\r\n\tsmode2.DPMS = 0;\r\n\r\n\tpmode.EN1   = 1;\t\t\t\t// enable Read Circuit 1\r\n\tpmode.EN2   = 1;\t\t\t\t// enable Read Circuit 2\r\n\tpmode.CRTMD = 1;\t\t\t\t// always 1\r\n\tpmode.MMOD  = 1;\t\t\t\t// use value in ALP for blending\r\n\tpmode.AMOD  = 0;\t\t\t\t// OUT1 alpha output selection (irrelevant for now)\r\n\tpmode.SLBG  = Enable?0:1;\t\t// blend with the output of Read Circuit 2 if Enable=1, or with BGCOLOR if Enable=0\r\n\tpmode.ALP \t= Enable?128:0;\t\t// alpha=0.5 if Enable=1, or 0.0 if Enable=0\r\n\tpmode.p0\t= 0;\t\t\t\t// GS manual states that unused bits of PMODE should be set to zero\r\n\tpmode.p1\t= 0;\r\n\r\n\t// Read Circuit 2 (DISPFB2 and DISPLAY2 registers)\r\n\tdispfb2.FBP = (HRes*VRes/2048);\r\n\tdispfb2.FBW = HRes/64;    //   *2 this to also display 1/2 of next frame\r\n \tdispfb2.PSM = PSMCT16S;\r\n\tdispfb2.DBX = 240-240/1;\t\t// 1 is the scale\r\n\tdispfb2.DBY = 224-224/1;\t\t// 1 is the scale\r\n\r\n\tif (Config::NTSC())\r\n\t{\r\n\t\tdisplay2.DX   = 0x27C;\t\t// horizontal offset }\r\n\t\tdisplay2.DY   = 0x32;\t\t// vertical offset   }\r\n\t} else {\t\t\t\t\t\t//\t\t\t\t\t } see SCE_GS_SET_DISPLAY_<blah> macros in eestruct.h\r\n\t\tdisplay2.DX   = 0x290;\t\t// horizontal offset }\r\n\t\tdisplay2.DY   = 0x48;\t\t// vertical offset\t }\r\n\t}\r\n\tdisplay2.MAGH = 2560/HRes-1;\t// see GS manual V5.0, p86\r\n\tdisplay2.MAGV = 0;\t\t\t\t// *1 vertical magnification (reg value plus 1)\r\n\tdisplay2.DW   = 2560-1;\r\n\tdisplay2.DH\t  = VRes-1;\r\n\t\r\n\t// Read Circuit 1 (DISPFB1 and DISPLAY1 registers)\r\n\t//... copy Read Circuit 2 and then shift by 1 row to blend the fields\r\n\tdispfb1  = *(tGS_DISPFB1 *)&dispfb2;\r\n\tdisplay1 = *(tGS_DISPLAY1 *)&display2;\r\n\tdisplay1.DY -= 1;\t\t\t\t// offset by 1 scanline, to blend the fields together\r\n\r\n\t// background colour (Sony says should always be black, unfortunately)\r\n\tbgcolor.R = 0;\r\n\tbgcolor.G = 0;\r\n\tbgcolor.B = 0;\r\n\r\n\t// write values to GS\r\n\tsceGsSyncV(0);\r\n\t*GS_SMODE2\t = *(volatile u_long *)&smode2;\r\n\t*GS_DISPFB1\t = *(volatile u_long *)&dispfb1;\r\n\t*GS_DISPLAY1 = *(volatile u_long *)&display1;\r\n\t*GS_DISPFB2\t = *(volatile u_long *)&dispfb2;\r\n\t*GS_DISPLAY2 = *(volatile u_long *)&display2;\r\n\t*GS_BGCOLOR  = *(volatile u_long *)&bgcolor;\r\n\t*GS_PMODE\t = *(volatile u_long *)&pmode;\r\n}\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/pcrtc.h",
    "content": "#ifndef __PCRTC_H\r\n#define __PCRTC_H\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nvoid SetupPCRTC(int Enable, int FFMode, int HRes=0, int VRes=0);\r\n\r\n} // namespace NxPs2\r\n\r\n#endif // __PCRTC_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/render.cpp",
    "content": "#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <libgraph.h>\r\n#include <libdma.h>\r\n#include <libsn.h>\r\n#include <devvu1.h>\r\n#include <math.h>\r\n#include <sifrpc.h>\r\n#include <sifdev.h>\r\n#include <libpad.h>\r\n#include <core\\math.h>\r\n#include <core\\defines.h>\r\n#include <core\\debug.h>\r\n#include <gfx\\nxviewman.h>\r\n#include <sys\\profiler.h>\r\n#include <sys\\timer.h>\r\n#include \"mikemath.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n#include \"vu1code.h\"\r\n#include \"dmacalls.h\"\r\n#include \"line.h\"\r\n#include \"chars.h\"\r\n#include \"texture.h\"\r\n#include \"material.h\"\r\n#include \"group.h\"\r\n#include \"scene.h\"\r\n#include \"mesh.h\"\r\n#include \"nx_init.h\"\r\n#include \"render.h\"\r\n#include \"interrupts.h\"\r\n#include \"switches.h\"\r\n#include \"sprite.h\"\r\n#include \"instance.h\"\r\n#include \"geomnode.h\"\r\n#include \"occlude.h\"\r\n#include \"resource.h\"\r\n#include \"vu1context.h\"\r\n#include \"light.h\"\r\n#include \"fx.h\"\r\n#include \"asmdma.h\"\r\n#include \"vu1\\newvu1code.h\"\r\n\r\n#include \"gfx\\nx.h\"\r\n#include \"gfx\\ngps\\p_nxscene.h\"\r\n#include \"gfx\\ngps\\p_nxtexture.h\"\r\n\r\n\r\n//#undef\t__USE_PROFILER__\r\n\r\n\r\nnamespace Inp\r\n{\r\n\textern uint32\tgDebugButtons[];\r\n\textern uint32\tgDebugMakes[];\r\n\r\n}\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nextern uint32\t*p_patch_PRMODE;\r\nextern uint32 gPassMask1;\r\n\r\n\r\nextern int geom_stats_total;\r\nextern int geom_stats_inactive ;\r\nextern int geom_stats_sky;\r\nextern int geom_stats_transformed;\r\nextern int geom_stats_skeletal;\r\nextern int geom_stats_camera_sphere;\r\nextern int geom_stats_clipcull;\r\nextern int geom_stats_culled;\r\nextern int geom_stats_leaf_culled;\r\nextern int geom_stats_boxcheck;\r\nextern int geom_stats_occludecheck;\r\nextern int geom_stats_occluded;\r\nextern int geom_stats_occludecheck;\r\nextern int geom_stats_occluded;\r\nextern int geom_stats_occludecheck;\r\nextern int geom_stats_occluded;\r\nextern int geom_stats_colored;\r\nextern int geom_stats_leaf;\r\nextern int geom_stats_wibbleUV;\r\nextern int geom_stats_wibbleVC;\r\nextern int geom_stats_sendcontext;\r\nextern int geom_stats_sorted;\r\nextern int geom_stats_shadow;\r\n\r\n// Mick:  Letterboxing on the ps2 is a post-processing\r\n// step one frame ahead in the rendering pipeline (as\r\n// compared to things like setting the FOV), so \r\n// it must be delayed by 1 frame to synchronize it\r\n// with such events.\r\nbool ActualDoLetterbox = false;\r\nbool DoLetterbox = false;\r\n\r\nint\tDMAOverflowOK  = false;\r\n\r\nbool DoFlipCopy = true;\r\nsGroup PrologueGroup;\r\nfloat SkaterY;\r\n\r\nint\tSingleRender = 0;\r\n\r\n// skinning globals\r\nMat SkaterTransform;\r\nMat BoneTransforms[64];\r\nint NumBones=0;\r\n\r\n\r\n#if STENCIL_SHADOW\r\nvoid CastStencilShadow(CInstance *pInstance, sGroup *p_group, Mth::Vector &ShadowVec, Mth::Vector &TweakVec);\r\n#else\r\nvoid CastShadow(CInstance *pInstance, sGroup *p_group);\r\n#endif\r\n\r\nvoid EnableFlipCopy(bool flip)\r\n{\r\n\tDoFlipCopy = flip;\r\n}\r\n\r\nbool FlipCopyEnabled()\r\n{\r\n\treturn DoFlipCopy;\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////\r\n// void RenderPrologue(void)\r\n//\r\n// called at the start of a frame\r\n// sets up the initial DMA list\r\n// by setting up a prologue \"group\"\r\n// consisting of an empty upload portion, and \r\n// a render portion that flips the visible buffers,\r\n// and sets up various vif settings\r\n// finally we initilize \tvu1::Loc = vu1::Buffer=0;\r\n//\r\n// Note, Field will be 0 or 1, depending on which buffer we are drawing into\r\n\r\nvoid RenderPrologue(void)\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t// a nasty patch by Mick to allow us to see the extra passes in flat shaded mode\r\n\tif (gPassMask1)\r\n\t{\r\n\t\tif (Inp::gDebugMakes[0] & (1<<5))\t\t\t  // check for Circle pressed\r\n\t\t{\r\n\t\t\t*p_patch_PRMODE ^= 1;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t*p_patch_PRMODE = 1;\r\n\t}\r\n\t#endif\r\n\t\r\n\t\r\n\t\r\n\t// record the time\r\n\trender::sTime = (int)Tmr::GetTime();\r\n\t\t\t\t\t \r\n\t// set dma pointer to the start of the dma buffer\r\n\tdma::pLoc = dma::pList[render::Field];\r\n\tdma::pBase = dma::pLoc;\r\n\r\n\tPrologueGroup.profile_color = 0x008080;\t\t// yellow = prologue group\r\n\r\n\t// prologue render begins here\r\n\tPrologueGroup.pRender[render::Field] = dma::pLoc;\r\n\tPrologueGroup.Used[render::Field] = true; \t\t\t// prologue always used\r\n\r\n\t// call the DMA routine to flip frame buffers and clear the draw buffer\r\n\t// currently the flip is accomplished by rendering a full screen sprite from the\r\n\t// draw buffer to the display buffer.  This converts it from 32-bit to 16-bit (dithered)\r\n\t// and means there is no actual buffer switching going on\r\n\t// the draw buffer is always at the same address.\r\n\t// When the game is running at 60fps, this copying takes place during the vblank.\r\n\t\r\n\t//static bool last_flip_copy = true;\r\n\tif (DoFlipCopy /*&& last_flip_copy*/)\t  // DoFlipCopy is set/cleared by the loading screen code (p_NxLoadScreen.cpp)\r\n\t{\r\n\t\tif (ActualDoLetterbox)\r\n\t\t\tdma::Gosub(FLIP_N_CLEAR_LETTERBOX,2);\r\n\t\telse\r\n\t\t\tdma::Gosub(FLIP_N_CLEAR,2);\r\n\t\tActualDoLetterbox=DoLetterbox;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tdma::Gosub(CLEAR_ZBUFFER,2);\r\n\t}\r\n\t//last_flip_copy = DoFlipCopy;\r\n\r\n\t// set the GS to the default rendering state\r\n\tdma::Gosub(SET_RENDERSTATE,2);\r\n\tdma::Gosub(SET_FOGCOL,2);\r\n\r\n\t// upload VU1 microcode\t(the code in microcode.dsm)\r\n\t// This is done every frame, at the start of the frame\r\n\t// it actually only needs doing once, but it does not really take\r\n\t// any time, and doing it every frame gives us the flexibility to uploaded new\r\n\t// microcode at a later stage in rendering.\r\n\t// for now, all the microcode fits in the 16K code area of VU1\r\n\tdma::Tag(dma::ref, ((uint8 *)&MPGEnd-(uint8 *)&MPGStart+15)/16, (uint)&MPGStart);\r\n\tvif::NOP();\r\n\tvif::NOP();\r\n\t\r\n\t// VIF1 and VU1 setup\r\n\tdma::BeginTag(dma::end, 0);\r\n\tvif::FLUSH();\r\n\tvif::STMASK(0);\r\n\tvif::STMOD(0);\r\n\tvif::STCYCL(1,1);\r\n\tvif::BASE(0);\r\n\tvif::OFFSET(0);\r\n\tvif::MSCAL(VU1_ADDR(Setup));\r\n\tdma::EndTag();\r\n\t\r\n\t// prepare all groups for rendering\r\n\tfor (sGroup *p_group=sGroup::pHead; p_group; p_group=p_group->pNext)\r\n\t{\r\n\t\t// initialise the dma list\r\n\t\tdma::BeginList(p_group);\r\n\r\n\t\t// assume textures aren't used until something actually gets rendered\r\n\t\tp_group->Used[render::Field] = false;\r\n\t}\r\n\tdma::sp_group = NULL;\r\n\r\n\r\n\t// while the dma context is null, set up an empty upload for the particles group and fog group\r\n\tsGroup::pParticles->pUpload[render::Field] = dma::pLoc;\r\n\tsGroup::pFog->pUpload[render::Field] = dma::pLoc;\r\n\tdma::Tag(dma::end, 0, 0);\r\n\tvif::NOP();\r\n\tvif::NOP();\r\n\t\r\n\t// signal that the particle group is used\r\n\tsGroup::pParticles->Used[render::Field] = true;\r\n\r\n\t// reset current marker number\r\n\trender::sMarkerIndex = 0;\r\n\r\n\t// count particles\r\n\trender::sTotalNewParticles = 0;\r\n}\r\n\r\n\r\n\r\nvoid RenderWorld(Mth::Matrix* camera_orient, Mth::Vector* camera_pos, float view_angle, float screen_aspect)\r\n{\r\n\tMth::Matrix transform(*camera_orient);\r\n\ttransform[3] = *camera_pos;\r\n\r\n\t// need the transform to be well-formed as a 4x4 matrix\r\n\ttransform[0][3] = 0.0f;\r\n\ttransform[1][3] = 0.0f;\r\n\ttransform[2][3] = 0.0f;\r\n\ttransform[3][3] = 1.0f;\r\n\r\n\tMth::Rect viewport1(0.0f, 0.0f, 1.0f, 1.0f);\r\n\tRenderViewport(0, transform, viewport1, view_angle, screen_aspect, -1.0f, -100000.0f);\r\n}\r\n\r\nvoid RenderInitImmediateMode()\r\n{\r\n\tdma::SetList(sGroup::pEpilogue);\r\n\r\n\t// epilogue render (a terrible hack to put this here!)\r\n\t//sGroup::pEpilogue->pRender[render::Field] = dma::pLoc;\r\n\tsGroup::pEpilogue->Used[render::Field] = true;\t\t\t// epilogue always rendered\r\n\r\n\t// VIF1 and VU1 setup\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tvif::FLUSH();\r\n\tvif::STROW((int)render::RowRegI[0], (int)render::RowRegI[1], (int)render::RowRegI[2], (int)render::RowRegI[3]);\r\n\tvif::STMASK(0);\r\n\tvif::STMOD(0);\r\n\tvif::STCYCL(1,1);\r\n\tvif::BASE(0);\r\n\tvif::OFFSET(0);\r\n\tvif::MSCAL(VU1_ADDR(Setup));\r\n\tvu1::Loc = vu1::Buffer=0;\r\n\t//vu1::BeginPrim(ABS, VU1_ADDR(L_VF10));\r\n\t//vu1::StoreVec(*(Vec *)&render::ViewportScale);\t\t\t\t// VF10\r\n\t//vu1::StoreVec(*(Vec *)&render::ViewportOffset);\t\t\t\t// VF11\r\n\t//vu1::StoreMat(*(Mat *)&render::AdjustedWorldToFrustum);\t\t// VF12-15\r\n\t//vu1::StoreMat(*(Mat *)&render::AdjustedWorldToViewport);\t// VF16-19\r\n\t//vu1::EndPrim(0);\r\n\tgs::BeginPrim(ABS,0,0);\r\n\tgs::Reg1(gs::XYOFFSET_1, PackXYOFFSET(XOFFSET, YOFFSET));\r\n\tgs::Reg1(gs::SCISSOR_1,\t PackSCISSOR(0,HRES - 1,0,VRES - 1));\r\n\tgs::Reg1(gs::TEST_1, PackTEST(0,0,0,0,0,0,1,ZGEQUAL));\r\n\tgs::Reg1(gs::CLAMP_1,PackCLAMP(CLAMP,CLAMP,0,0,0,0));\r\n\tgs::Reg1(gs::PRMODECONT,\tPackPRMODECONT(1));\r\n\tgs::EndPrim(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n\tdma::EndTag();\r\n}\r\n\r\nvoid RenderSwitchImmediateMode()\r\n{\r\n\tdma::SetList(sGroup::pEpilogue);\r\n}\r\n\r\n\r\n// camera_transform must be a well-formed 4x4 matrix\r\nvoid RenderViewport(uint viewport_num, const Mth::Matrix& camera_transform, const Mth::Rect& viewport_rec, float view_angle,\r\n\t\t\t\t\tfloat viewport_aspect, float near, float far, bool just_setup)\r\n{\r\n\t// set up a load of persistent data for current viewport\r\n\trender::SetupVars(viewport_num, camera_transform, viewport_rec, view_angle, viewport_aspect, near, far);\r\n\r\n\t// Perform the DMA seperately, as the actual VARS might be re-set by update_render_vars called from plat_transform_to_screen\r\n\trender::SetupVarsDMA(viewport_num, near, far);\r\n\r\n\t\t// old and new style renders\r\n\t\t#\tifdef __USE_PROFILER__\r\n\t\t\tSys::CPUProfiler->PushContext( 255, 0, 0 );\t \t// Red (Under Yellow) = OldStyle Rendering\t(Skins and stuff)\r\n\t\t#\tendif // __USE_PROFILER__\r\n\t\t\trender::OldStyle();\r\n\t\t#\tifdef __USE_PROFILER__\r\n\t\t\tSys::CPUProfiler->PopContext( );\r\n\t\t#\tendif // __USE_PROFILER__\r\n\t\t\r\n\t\t\r\n\t\t#\tifdef __USE_PROFILER__\r\n\t\t\tSys::CPUProfiler->PushContext( 0, 255, 0 );\t\t// Green (Under Yellow) = NewStyle rendering (Environment)\r\n\t\t#\tendif // __USE_PROFILER__\r\n\t\t\t\r\n\t\t\trender::NewStyle(just_setup);\r\n\t\t#\tifdef __USE_PROFILER__\r\n\t\t\tSys::CPUProfiler->PopContext(  );\r\n\t\t#\tendif // __USE_PROFILER__\r\n}\r\n\r\n// Uncomment the next line to use the color-per-mesh feature\r\n#define USE_COLOR_PER_MESH\r\n\r\nvoid render::OldStyle()\r\n{\r\n\t// Don't render anything if it's not going to be displayed\t\r\n\tif (!FlipCopyEnabled())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tfloat x,y,z,R;\r\n\tsMesh *pMesh;\r\n\tsGroup *p_group;\r\n\tint j;\r\n\tuint32 vu1_flags;\r\n\tuint32 colour;\r\n\tfloat colourComponent;\r\n\r\n\tMth::Matrix LocalToWorld;\r\n\tMth::Matrix LocalToCamera;\r\n\tMth::Matrix LocalToFrustum;\r\n\tMth::Matrix LocalToViewport;\r\n\tMth::Matrix RootToWorld;\r\n\tMth::Matrix RootToCamera;\r\n\tMth::Matrix RootToFrustum;\r\n\tMth::Matrix RootToViewport;\r\n\tMth::Matrix LightMatrix;\r\n\tMth::Matrix ColourMatrix;\r\n\r\n\tMth::Vector ambientColour;\r\n\tMth::Vector diffuseColour0;\r\n\tMth::Vector diffuseColour1;\r\n\tMth::Vector diffuseColour2;\r\n\tMth::Vector colouredAmbientColour;\r\n\tMth::Vector colouredDiffuseColour0;\r\n\tMth::Vector colouredDiffuseColour1;\r\n\tMth::Vector colouredDiffuseColour2;\r\n\tMth::Vector v;\r\n\r\n// Mick: Initialize these local matricies to known values....\r\n\tLocalToWorld.Zero();\r\n\tLocalToCamera.Zero();\r\n\tLocalToFrustum.Zero();\r\n\tLocalToViewport.Zero();\r\n\tRootToWorld.Zero();\r\n\tRootToCamera.Zero();\r\n\tRootToFrustum.Zero();\r\n\tRootToViewport.Zero();\r\n\tLightMatrix.Zero();\r\n// And the vectors...\t\r\n\tambientColour.Set(0.0f,0.0f,0.0f,1.0f);\r\n\tdiffuseColour0.Set(0.0f,0.0f,0.0f,1.0f);\r\n\tdiffuseColour1.Set(0.0f,0.0f,0.0f,1.0f);\r\n\tdiffuseColour2.Set(0.0f,0.0f,0.0f,1.0f);\r\n\tcolouredAmbientColour.Set(0.0f,0.0f,0.0f,1.0f);\r\n\tcolouredDiffuseColour0.Set(0.0f,0.0f,0.0f,1.0f);\r\n\tcolouredDiffuseColour1.Set(0.0f,0.0f,0.0f,1.0f);\r\n\tcolouredDiffuseColour2.Set(0.0f,0.0f,0.0f,1.0f);\r\n\tv.Set(0.0f,0.0f,0.0f,1.0f);\r\n\t\r\n\r\n\t\r\n\t#if STENCIL_SHADOW\r\n\t// prepare stencil shadow dma list for generating the stencil buffer\r\n\tdma::SetList(sGroup::pShadow);\r\n\r\n\t// send the GS setup\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tgs::BeginPrim(ABS,0,0);\r\n\tgs::Reg1(gs::XYOFFSET_2,\tPackXYOFFSET(XOFFSET, YOFFSET));\r\n\tgs::Reg1(gs::ZBUF_2,\t\tPackZBUF(ZBUFFER_START,PSMZ24,1));\r\n\tgs::Reg1(gs::SCISSOR_2,\t\tPackSCISSOR(0,HRES - 1,0,VRES - 1));\r\n\tgs::Reg1(gs::FRAME_2,\t\tPackFRAME(0x1BA,HRES/64,PSMCT16S,0x00000000));\r\n\t//gs::Reg1(gs::FRAME_2,\t\tPackFRAME(FRAME_START,HRES/64,PSMCT32,0x00000000));\r\n\tgs::Reg1(gs::ALPHA_2,\t\tPackALPHA(0,2,2,1,128));\r\n\tgs::Reg1(gs::FBA_2,\t\t\tPackFBA(0));\r\n\tgs::Reg1(gs::PABE,\t\t\tPackPABE(0));\r\n\tgs::Reg1(gs::COLCLAMP,\t\tPackCOLCLAMP(0));\r\n\tgs::Reg1(gs::PRMODECONT,\tPackPRMODECONT(1));\r\n\tgs::Reg1(gs::DTHE,\t\t\tPackDTHE(0));\r\n\tgs::Reg1(gs::TEST_2,\t\tPackTEST(0,0,0,0,0,0,1,ZALWAYS));\r\n\tgs::Reg1(gs::PRIM,\t\t\tPackPRIM(SPRITE,0,0,0,0,0,0,1,0));\t\t\t// clear the stencil buffer\r\n\tgs::Reg1(gs::RGBAQ,\t\t\tPackRGBAQ(0,0,0,0,0));\r\n\tgs::Reg1(gs::XYZ2,\t\t\tPackXYZ(XOFFSET,YOFFSET,0));\r\n\tgs::Reg1(gs::XYZ2,\t\t\tPackXYZ(0x10000-XOFFSET,0x10000-YOFFSET,0));\r\n\tgs::Reg1(gs::TEST_2,\t\tPackTEST(0,0,0,0,0,0,1,ZGREATER));\r\n\tgs::Reg1(gs::FRAME_2,\t\tPackFRAME(0x1BA,HRES/64,PSMCT16S,0xFF000000));\r\n\tgs::EndPrim(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n\tdma::EndTag();\r\n\t#else\r\n\t// prepare shadow dma list for generating the shadow texture\r\n\tdma::SetList(sGroup::pShadow);\r\n\r\n\t// send the GS setup\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tgs::BeginPrim(ABS,0,0);\r\n\tgs::Reg1(gs::XYOFFSET_2,\tPackXYOFFSET(0x7800,0x7800));\r\n\tgs::Reg1(gs::ZBUF_2,\t\tPackZBUF(0,PSMZ16,1));\r\n\tgs::Reg1(gs::TEST_2,\t\tPackTEST(0,0,0,0,0,0,1,ZALWAYS));\r\n\tgs::Reg1(gs::SCISSOR_2,\t\tPackSCISSOR(0,255,0,255));\r\n\tgs::Reg1(gs::FRAME_2,\t\tPackFRAME(0x1F0,4,PSMCT16,0x00000000));\r\n\t//gs::Reg1(gs::FRAME_2,\t\tPackFRAME(0x000,HRES/64,PSMCT32,0x00000000));\r\n\tgs::Reg1(gs::FBA_2,\t\t\tPackFBA(0));\r\n\tgs::Reg1(gs::PRIM,\t\t\tPackPRIM(SPRITE,0,0,0,0,0,0,1,0));\t\t\t// clear the texture\r\n\tgs::Reg1(gs::RGBAQ,\t\t\tPackRGBAQ(0,0,0,0,0));\r\n\tgs::Reg1(gs::XYZ2,\t\t\tPackXYZ(0x7800,0x7800,0));\r\n\tgs::Reg1(gs::XYZ2,\t\t\tPackXYZ(0x8800,0x8800,0));\r\n\tgs::Reg1(gs::FBA_2,\t\t\tPackFBA(1));\t\t\t\t\t\t\t\t// set A on all pixels we touch\r\n\tgs::Reg1(gs::SCISSOR_2,\t\tPackSCISSOR(1,254,1,254));\t\t\t\t\t// don't touch edge of texture to avoid streaks\r\n\tgs::Reg1(gs::PRMODECONT,\tPackPRMODECONT(0));\r\n\tgs::Reg1(gs::PRMODE,\t\tPackPRMODE(0,0,0,0,0,0,1,0));\r\n\tgs::EndPrim(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n\tdma::EndTag();\r\n\t#endif\r\n\r\n\r\n\t// assume no dma context\r\n\tdma::SetList(NULL);\r\n\r\n\t// render old-style groups\r\n\tfor (p_group=sGroup::pHead; p_group!=sGroup::pEpilogue; p_group=p_group->pNext)\r\n\t{\r\n\t\t// skip the old render mechanism if the group belongs to a pip-style scene\r\n\t\tif (p_group==sGroup::pShadow || !p_group->pScene || p_group->pScene->Flags & SCENEFLAG_USESPIP)\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tdma::SetList(p_group);\r\n\r\n\t\tdma::BeginTag(dma::cnt, 0);\r\n\r\n\t\t\t// VIF1 and VU1 setup\r\n\t\t\tvif::FLUSH();\r\n\t\t\tvif::STMASK(0);\r\n\t\t\tvif::STMOD(0);\r\n\t\t\tvif::STCYCL(1,1);\r\n\t\t\tvif::STCOL(0x3F800000,0,0,0);\r\n\t\t\tvif::BASE(0);\r\n\t\t\tvif::OFFSET(0);\r\n\t\t\tvif::MSCAL(VU1_ADDR(Setup));\r\n\t\t\tvu1::Loc = vu1::Buffer=0;\r\n\r\n\t\t\t// constant part of vu1 context data\r\n\t\t\tvu1::BeginPrim(ABS, VU1_ADDR(L_VF09));\r\n//\t\t\tvu1::StoreVec(*(Vec *)&render::AltFrustum);\t\t\t\t// VF09\r\n//\t\t\tvu1::StoreVec(*(Vec *)&render::InverseViewportScale);\t// VF10\r\n//\t\t\tvu1::StoreVec(*(Vec *)&render::InverseViewportOffset);\t// VF11\r\n\t\t\tvu1::CopyQuads((uint32*)&render::AltFrustum, \r\n\t\t\t\t\t\t\t(uint32*)&render::InverseViewportScale,\r\n\t\t\t\t\t\t\t(uint32*)&render::InverseViewportOffset\r\n\t\t\t\t\t\t\t);\r\n\t\t\tvu1::EndPrim(0);\r\n\r\n\t\t\t// send the GS viewport context\r\n\t\t\tgs::BeginPrim(ABS, 0, 0);\r\n\t\t\tgs::Reg1(gs::XYOFFSET_1, render::reg_XYOFFSET);\r\n\t\t\tgs::Reg1(gs::SCISSOR_1,  render::reg_SCISSOR);\r\n\t\t\tgs::EndPrim(1);\r\n\t\t\tvif::MSCAL(VU1_ADDR(Parser));\r\n\r\n\t\tdma::EndTag();\r\n\r\n\r\n\t\tMth::Matrix refl_temp;\r\n\t\tMth::Matrix  \tReflVecs;\r\n\t\trefl_temp[0] = Mth::Vector(1.0f, 0.0f, 0.0f, 0.0f);\r\n\t\trefl_temp[1] = Mth::Vector(0.0f, 1.0f, 0.0f, 0.0f);\r\n\t\trefl_temp[2] = Mth::Vector(0.0f, 0.0f, 1.4f, 0.0f);\r\n\t\trefl_temp[3] = Mth::Vector(0.0f, 0.0f, 0.0f, 0.0f);\r\n\r\n\t\t// this part handles the instanced non-skinned models\r\n\t\tif (p_group->pScene && (p_group->pScene->Flags & SCENEFLAG_INSTANCEABLE) &&\r\n\t\t\tp_group->pMeshes && !(p_group->pMeshes->Flags & MESHFLAG_SKINNED))\r\n\t\t{\r\n\t\t\tfor (CInstance *pInstance=p_group->pScene->pInstances; pInstance; pInstance=pInstance->GetNext())\r\n\t\t\t{\r\n\t\t\t\t// make sure the instance is active\r\n\t\t\t\tif (!pInstance->IsActive())\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tLocalToWorld = *(Mth::Matrix *)pInstance->GetTransform();\r\n\t\t\t\tLocalToCamera = LocalToWorld * render::WorldToCamera;\r\n\t\t\t\tLocalToFrustum = LocalToWorld * render::WorldToFrustum;\r\n\t\t\t\tLocalToViewport = LocalToFrustum * render::FrustumToViewport;\r\n\r\n\t\t\t\t// set up reflection map transform\r\n\t\t\t\tsceVu0MulMatrix((sceVu0FVECTOR*)&ReflVecs,\r\n\t\t\t\t\t\t\t\t(sceVu0FVECTOR*)&refl_temp,\r\n\t\t\t\t\t\t\t\t(sceVu0FVECTOR*)&LocalToCamera);\r\n\r\n\t\t\t\t// send VIF/VU context\r\n\t\t\t\tdma::BeginTag(dma::cnt, 0);\r\n\t\t\t\tvif::STROW(0,0,0,0);\r\n\t\t\t\tvu1::BeginPrim(ABS, VU1_ADDR(L_VF12));\r\n\t\t\t\tvu1::StoreMat(*(Mat *)&LocalToViewport);\t// VF12-15\r\n\t\t\t\tvu1::StoreMat(*(Mat *)&ReflVecs);\t\t\t// VF16-19\r\n\t\t\t\tvu1::EndPrim(0);\r\n\r\n\t\t\t\t//gs::BeginPrim(ABS,0,0);\r\n\t\t\t\t//gs::Reg1(gs::FOGCOL, PackFOGCOL(0x60,0x40,0xC0));\r\n\t\t\t\t//gs::EndPrim(0);\r\n\r\n\t\t\t\tdma::EndTag();\r\n\r\n\t\t\t\t// traverse array of meshes in this group\r\n\t\t\t\tfor (j=0,pMesh=p_group->pMeshes; j<p_group->NumMeshes; j++,pMesh++)\r\n\t\t\t\t{\r\n\t\t\t\t\t// skip if invisible\r\n\t\t\t\t\tif (!pMesh->IsActive())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// do nothing if mesh doesn't have a dma subroutine\r\n\t\t\t\t\tif (!pMesh->pSubroutine)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tv = pMesh->Sphere;\r\n\t\t\t\t\tv[3] = 1.0f;\r\n\t\t\t\t\tv *= LocalToCamera;\r\n\t\t\t\t\tx = v[0];\r\n\t\t\t\t\ty = v[1];\r\n\t\t\t\t\tz = v[2];\r\n\t\t\t\t\tR = pMesh->Sphere[3];\r\n\r\n\t\t\t\t\t// if all outside view volume then cull\r\n\t\t\t\t\tif (R<z-render::Near || R<render::Far-z\t\t\t\t\t\t\t||\r\n\t\t\t\t\t\tR<render::sy*z+render::cy*y || R<render::sy*z-render::cy*y\t||\r\n\t\t\t\t\t\tR<render::sx*z-render::cx*x || R<render::sx*z+render::cx*x)\r\n\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\t// else if all inside outer volume then render normally\r\n\t\t\t\t\telse if (R<render::Near-z && R<z-render::Far\t\t\t\t\t\t\t&&\r\n\t\t\t\t\t\t\t R<-render::Sy*z-render::Cy*y && R<-render::Sy*z+render::Cy*y\t&&\r\n\t\t\t\t\t\t\t R<-render::Sx*z+render::Cx*x && R<-render::Sx*z-render::Cx*x)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdma::Gosub3D(pMesh->pSubroutine, PROJ);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// otherwise cull at the vertex level\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdma::Gosub3D(pMesh->pSubroutine, CLIP);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_group->Used[render::Field] = true;\t  \t// Note, should have culling before here\r\n\t\t\t\t\t\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\r\n\t\t// this part handles the instanced skinned models\r\n\t\tif (p_group->pScene && (p_group->pScene->Flags & SCENEFLAG_INSTANCEABLE) &&\r\n\t\t\tp_group->pMeshes && (p_group->pMeshes->Flags & MESHFLAG_SKINNED))\r\n\t\t{\r\n\t\t\tfor (CInstance *pInstance=p_group->pScene->pInstances; pInstance; pInstance=pInstance->GetNext())\r\n\t\t\t{\r\n\t\t\t\t// make sure the instance is active\r\n\t\t\t\tif (!pInstance->IsActive())\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// shadow\r\n\t\t\t\tif (pInstance->CastsShadow())\r\n\t\t\t\t{\r\n\t\t\t\t\t#if STENCIL_SHADOW\r\n\t\t\t\t\tMth::Vector shadow_vec(20.0f, -100.0f, 0.0f, 0.0f);\r\n\t\t\t\t\tMth::Vector tweak_vec(0.4f, -2.0f, 0.0f, 0.0f);\r\n\t\t\t\t\tCastStencilShadow(pInstance, p_group, shadow_vec, tweak_vec);\r\n\t\t\t\t\t#else\r\n\t\t\t\t\tCastShadow(pInstance, p_group);\r\n\t\t\t\t\t#endif\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// mat for bounding sphere test\r\n\t\t\t\tRootToWorld = *(Mth::Matrix *)pInstance->GetTransform();\r\n\t\t\t\tRootToCamera = RootToWorld * render::WorldToCamera;\r\n\r\n\t\t\t\t// get bounding sphere\r\n\t\t\t\tv = pInstance->GetBoundingSphere();\r\n\t\t\t\tR = v[3];\r\n\t\t\t\tv[3] = 1.0f;\r\n\t\t\t\tv *= RootToCamera;\r\n\t\t\t\tx = v[0];\r\n\t\t\t\ty = v[1];\r\n\t\t\t\tz = v[2];\r\n\r\n\t\t\t\t// if all outside view volume then cull\r\n\t\t\t\tif (R<z-render::Near || R<render::Far-z\t\t\t\t\t\t\t||\r\n\t\t\t\t\tR<render::sy*z+render::cy*y || R<render::sy*z-render::cy*y\t||\r\n\t\t\t\t\tR<render::sx*z-render::cx*x || R<render::sx*z+render::cx*x)\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t// else if all inside outer volume then render normally\r\n\t\t\t\telse if (R<render::Near-z && R<z-render::Far\t\t\t\t\t\t\t&&\r\n\t\t\t\t\t\t R<-render::Sy*z-render::Cy*y && R<-render::Sy*z+render::Cy*y\t&&\r\n\t\t\t\t\t\t R<-render::Sx*z+render::Cx*x && R<-render::Sx*z-render::Cx*x)\r\n\t\t\t\t{\r\n\t\t\t\t\tvu1_flags = PROJ;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// otherwise cull at the vertex level\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tvu1_flags = CULL;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// wireframe mode\r\n\t\t\t\tif (pInstance->IsWireframe())\r\n\t\t\t\t{\r\n\t\t\t\t\tvu1_flags |= WIRE;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tp_group->Used[render::Field] = true;\t  \t// Note, should have culling before here\t\t\t\t\t\r\n\r\n\t\t\t\tdma::BeginTag(dma::cnt, 0);\r\n\r\n\r\n\t\t\t\t// adjust matrix for 0:8 fixed point weights format (used to be 1:15)\r\n\t\t\t\tRootToCamera[0] *= 128.0f;\r\n\t\t\t\tRootToCamera[1] *= 128.0f;\r\n\t\t\t\tRootToCamera[2] *= 128.0f;\r\n\r\n\t\t\t\t// send vu1 context\r\n\t\t\t\tRootToFrustum = RootToCamera * render::CameraToFrustum;\r\n\t\t\t\tRootToViewport = RootToFrustum * render::FrustumToIntViewport;\r\n\r\n\t\t\t\tCLightGroup *pLightGroup = pInstance->GetLightGroup();\r\n\r\n\t\t\t\tif (pLightGroup)\r\n\t\t\t\t{\r\n\t\t\t\t\tconst Mth::Vector &light_dir0 = pLightGroup->GetDirection(0);\r\n\t\t\t\t\tconst Mth::Vector &light_dir1 = pLightGroup->GetDirection(1);\r\n\t\t\t\t\tconst Mth::Vector &light_dir2 = pLightGroup->GetDirection(2);\r\n\r\n\t\t\t\t\tLightMatrix[0][0] = light_dir0[0];\r\n\t\t\t\t\tLightMatrix[1][0] = light_dir0[1];\r\n\t\t\t\t\tLightMatrix[2][0] = light_dir0[2];\r\n\t\t\t\t\tLightMatrix[0][1] = light_dir1[0];\r\n\t\t\t\t\tLightMatrix[1][1] = light_dir1[1];\r\n\t\t\t\t\tLightMatrix[2][1] = light_dir1[2];\r\n\t\t\t\t\tLightMatrix[0][2] = light_dir2[0];\r\n\t\t\t\t\tLightMatrix[1][2] = light_dir2[1];\r\n\t\t\t\t\tLightMatrix[2][2] = light_dir2[2];\r\n\t\t\t\t} else {\r\n\t\t\t\t\tconst Mth::Vector &light_dir0 = CLightGroup::sGetDefaultDirection(0);\r\n\t\t\t\t\tconst Mth::Vector &light_dir1 = CLightGroup::sGetDefaultDirection(1);\r\n\t\t\t\t\tconst Mth::Vector &light_dir2 = CLightGroup::sGetDefaultDirection(2);\r\n\r\n\t\t\t\t\tLightMatrix[0][0] = light_dir0[0];\r\n\t\t\t\t\tLightMatrix[1][0] = light_dir0[1];\r\n\t\t\t\t\tLightMatrix[2][0] = light_dir0[2];\r\n\t\t\t\t\tLightMatrix[0][1] = light_dir1[0];\r\n\t\t\t\t\tLightMatrix[1][1] = light_dir1[1];\r\n\t\t\t\t\tLightMatrix[2][1] = light_dir1[2];\r\n\t\t\t\t\tLightMatrix[0][2] = light_dir2[0];\r\n\t\t\t\t\tLightMatrix[1][2] = light_dir2[1];\r\n\t\t\t\t\tLightMatrix[2][2] = light_dir2[2];\r\n\t\t\t\t}\r\n\r\n\t\t\t\tMth::Matrix temp = *(Mth::Matrix *)pInstance->GetTransform();\r\n\t\t\t\ttemp[0].Normalize();\t\t\t\t\t\t\t// do something sensible with a scaled matrix\r\n\t\t\t\ttemp[1].Normalize();\r\n\t\t\t\ttemp[2].Normalize();\r\n\t\t\t\tLightMatrix = temp * LightMatrix;\r\n\r\n\t\t\t\tif (pLightGroup)\r\n\t\t\t\t{\r\n\t\t\t\t\tambientColour  = pLightGroup->GetAmbientColor();\r\n\t\t\t\t\tdiffuseColour0 = pLightGroup->GetDiffuseColor(0);\r\n\t\t\t\t\tdiffuseColour1 = pLightGroup->GetDiffuseColor(1);\r\n\t\t\t\t\tdiffuseColour2 = pLightGroup->GetDiffuseColor(2);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tambientColour  = CLightGroup::sGetDefaultAmbientColor();\r\n\t\t\t\t\tdiffuseColour0 = CLightGroup::sGetDefaultDiffuseColor(0);\r\n\t\t\t\t\tdiffuseColour1 = CLightGroup::sGetDefaultDiffuseColor(1);\r\n\t\t\t\t\tdiffuseColour2 = CLightGroup::sGetDefaultDiffuseColor(2);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// apply instance colour\r\n\r\n#ifdef USE_COLOR_PER_MESH\r\n\t\t\t\tif (pInstance->HasColorPerMaterial())\r\n\t\t\t\t{\r\n\t\t\t\t\t// Get first color for now\r\n\t\t\t\t\tcolour = pInstance->GetMaterialColorByIndex(0);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tcolour = pInstance->GetColor();\r\n\t\t\t\t}\r\n#else\r\n\t\t\t\tcolour = pInstance->GetColor();\r\n#endif\r\n\t\t\t\tcolourComponent = (float)(colour & 0xFF) * 0.0078125f;\r\n\t\t\t\tcolouredAmbientColour[0]  = ambientColour[0]  * colourComponent;\r\n\t\t\t\tcolouredDiffuseColour0[0] = diffuseColour0[0] * colourComponent;\r\n\t\t\t\tcolouredDiffuseColour1[0] = diffuseColour1[0] * colourComponent;\r\n\t\t\t\tcolouredDiffuseColour2[0] = diffuseColour2[0] * colourComponent;\r\n\t\t\t\tcolourComponent = (float)(colour>>8 & 0xFF) * 0.0078125f;\r\n\t\t\t\tcolouredAmbientColour[1]  = ambientColour[1]  * colourComponent;\r\n\t\t\t\tcolouredDiffuseColour0[1] = diffuseColour0[1] * colourComponent;\r\n\t\t\t\tcolouredDiffuseColour1[1] = diffuseColour1[1] * colourComponent;\r\n\t\t\t\tcolouredDiffuseColour2[1] = diffuseColour2[1] * colourComponent;\r\n\t\t\t\tcolourComponent = (float)(colour>>16 & 0xFF) * 0.0078125f;\r\n\t\t\t\tcolouredAmbientColour[2]  = ambientColour[2]  * colourComponent;\r\n\t\t\t\tcolouredDiffuseColour0[2] = diffuseColour0[2] * colourComponent;\r\n\t\t\t\tcolouredDiffuseColour1[2] = diffuseColour1[2] * colourComponent;\r\n\t\t\t\tcolouredDiffuseColour2[2] = diffuseColour2[2] * colourComponent;\r\n\r\n\t\t\t\tLightMatrix[3]  = colouredAmbientColour  * 1.0f/(128.0f*8388608.0f);\r\n\t\t\t\tColourMatrix[0] = colouredDiffuseColour0 * 1.0f/(128.0f*8388608.0f);\r\n\t\t\t\tColourMatrix[1] = colouredDiffuseColour1 * 1.0f/(128.0f*8388608.0f);\r\n\t\t\t\tColourMatrix[2] = colouredDiffuseColour2 * 1.0f/(128.0f*8388608.0f);\r\n\r\n\t\t\t\t// vu context data\r\n\t\t\t\tvu1::BeginPrim(ABS, VU1_ADDR(L_VF10));\r\n\t\t\t\t\r\n//\t\t\t\tvu1::StoreVec(*(Vec *)&render::InverseIntViewportScale);\t// VF10\r\n//\t\t\t\tvu1::StoreVec(*(Vec *)&render::InverseIntViewportOffset);\t// VF11\r\n\t\t\t\tvu1::CopyQuads((uint32*)&render::InverseIntViewportScale,\r\n\t\t\t\t\t\t\t   (uint32*)&render::InverseIntViewportOffset);\r\n\t\t\t\t\t\r\n\t\t\t\tvu1::StoreMat(*(Mat *)&RootToFrustum);\t\t\t// VF12-15\r\n\t\t\t\tvu1::StoreMat(*(Mat *)&RootToViewport);\t\t\t// VF16-19\r\n\t\t\t\tvu1::StoreMat(*(Mat *)&LightMatrix);\t\t\t// VF20-23\r\n\t\t\t\tvu1::StoreMat(*(Mat *)&ColourMatrix);\t\t\t// VF24-27\r\n\t\t\t\tvu1::EndPrim(0);\r\n\r\n\t\t\t\t// gs context data, specifically the fog coefficient\r\n\t\t\t\tfloat w,f;\r\n\t\t\t\tw = -RootToCamera[3][2];\r\n\t\t\t\tif ((w > FogNear) && EnableFog)\t// Garrett: We have to check for EnableFog here because the VU1 code isn't\r\n\t\t\t\t{\r\n\t\t\t\t\tf = 1.0 + EffectiveFogAlpha * (FogNear/w - 1.0f);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tf = 1.0f;\r\n\t\t\t\t}\r\n\t\t\t\tgs::BeginPrim(ABS,0,0);\r\n\t\t\t\tgs::Reg1(gs::FOG, PackFOG((int)(f*255.99f)));\r\n\t\t\t\t//gs::Reg1(gs::FOGCOL, PackFOGCOL(0x60,0x40,0xC0));\r\n\t\t\t\tgs::EndPrim(1);\r\n\r\n\t\t\t\tvif::MSCAL(VU1_ADDR(Parser));\r\n\r\n\t\t\t\t// get free run of the VUMem\r\n\t\t\t\tvif::FLUSHA();\r\n\r\n\t\t\t\tdma::EndTag();\r\n\r\n\t\t\t\t// send transforms\r\n\t\t\t\tvu1::Loc = 0;\r\n\t\t\t\tdma::Tag(dma::ref, pInstance->GetNumBones()<<2, (uint)pInstance->GetBoneTransforms());\r\n\t\t\t\tvif::NOP();\r\n\t\t\t\tvif::UNPACK(0,V4_32,pInstance->GetNumBones()<<2,ABS,SIGNED,0);\r\n\r\n\t\t\t\tdma::BeginTag(dma::cnt, 0);\r\n\r\n\t\t\t\tvif::ITOP(pInstance->GetNumBones()<<2);\r\n\t\t\t\tvif::MSCAL(VU1_ADDR(ReformatXforms));\r\n\r\n\t\t\t\t// not using pre-translate\r\n\t\t\t\t// don't forget to switch off the offset mode on xyz unpack if using the row reg for something else\r\n\t\t\t\tvif::STROW(0,0,0,0);\r\n\r\n\t\t\t\tdma::EndTag();\r\n\r\n\t\t\t\t// traverse colour-unlocked meshes\r\n\t\t\t\tfor (j=0,pMesh=p_group->pMeshes; j<p_group->NumMeshes; j++,pMesh++)\r\n\t\t\t\t{\r\n\t\t\t\t\t// skip if invisible, no subroutine, or not affected by dynamic colouring\r\n\t\t\t\t\tif (!pMesh->IsActive() || !pMesh->pSubroutine || (pMesh->Flags & MESHFLAG_COLOR_LOCKED))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n#ifdef USE_COLOR_PER_MESH\r\n\t\t\t\t\tuint32 mesh_color;\r\n\t\t\t\t\t// Garrett: Thought I had the material color array in the right order, but the render order\r\n\t\t\t\t\t// is different.  Right now I'm just searching out each color, but I'll need to go back\r\n\t\t\t\t\t// and see if it is possible to put the color array in render order (i.e. is the render order\r\n\t\t\t\t\t// static).\r\n\t\t\t\t\tif (pInstance->HasColorPerMaterial() && (colour != (mesh_color = pInstance->GetMaterialColor(pMesh->MaterialName, pMesh->Pass))))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcolour = mesh_color;\r\n\t\t\t\t\t\tcolourComponent = (float)(colour & 0xFF) * 0.0078125f;\r\n\t\t\t\t\t\tcolouredAmbientColour[0]  = ambientColour[0]  * colourComponent;\r\n\t\t\t\t\t\tcolouredDiffuseColour0[0] = diffuseColour0[0] * colourComponent;\r\n\t\t\t\t\t\tcolouredDiffuseColour1[0] = diffuseColour1[0] * colourComponent;\r\n\t\t\t\t\t\tcolouredDiffuseColour2[0] = diffuseColour2[0] * colourComponent;\r\n\t\t\t\t\t\tcolourComponent = (float)(colour>>8 & 0xFF) * 0.0078125f;\r\n\t\t\t\t\t\tcolouredAmbientColour[1]  = ambientColour[1]  * colourComponent;\r\n\t\t\t\t\t\tcolouredDiffuseColour0[1] = diffuseColour0[1] * colourComponent;\r\n\t\t\t\t\t\tcolouredDiffuseColour1[1] = diffuseColour1[1] * colourComponent;\r\n\t\t\t\t\t\tcolouredDiffuseColour2[1] = diffuseColour2[1] * colourComponent;\r\n\t\t\t\t\t\tcolourComponent = (float)(colour>>16 & 0xFF) * 0.0078125f;\r\n\t\t\t\t\t\tcolouredAmbientColour[2]  = ambientColour[2]  * colourComponent;\r\n\t\t\t\t\t\tcolouredDiffuseColour0[2] = diffuseColour0[2] * colourComponent;\r\n\t\t\t\t\t\tcolouredDiffuseColour1[2] = diffuseColour1[2] * colourComponent;\r\n\t\t\t\t\t\tcolouredDiffuseColour2[2] = diffuseColour2[2] * colourComponent;\r\n\r\n\t\t\t\t\t\tLightMatrix[3]  = colouredAmbientColour  * 1.0f/(128.0f*8388608.0f);\r\n\t\t\t\t\t\tColourMatrix[0] = colouredDiffuseColour0 * 1.0f/(128.0f*8388608.0f);\r\n\t\t\t\t\t\tColourMatrix[1] = colouredDiffuseColour1 * 1.0f/(128.0f*8388608.0f);\r\n\t\t\t\t\t\tColourMatrix[2] = colouredDiffuseColour2 * 1.0f/(128.0f*8388608.0f);\r\n\r\n\t\t\t\t\t\t// change lighting context\r\n\t\t\t\t\t\tdma::BeginTag(dma::cnt, 0);\r\n\t\t\t\t\t\tvif::BASE(256);\r\n\t\t\t\t\t\tvif::OFFSET(0);\r\n\t\t\t\t\t\tvu1::Loc = 256;\r\n\t\t\t\t\t\tvu1::BeginPrim(ABS, VU1_ADDR(L_VF20));\r\n\t\t\t\t\t\tvu1::StoreMat(*(Mat *)&LightMatrix);\t\t\t// VF20-23\r\n\t\t\t\t\t\tvu1::StoreMat(*(Mat *)&ColourMatrix);\t\t\t// VF24-27\r\n\t\t\t\t\t\tvu1::EndPrim(1);\r\n\t\t\t\t\t\tvif::MSCAL(VU1_ADDR(ParseInit));\r\n\t\t\t\t\t\tvif::FLUSH();\r\n\t\t\t\t\t\tdma::EndTag();\r\n\t\t\t\t\t}\r\n#endif // USE_COLOR_PER_MESH\r\n\r\n\t\t\t\t\t// render the mesh\r\n\t\t\t\t\tvu1::Loc = vu1::Buffer = 256;\r\n\t\t\t\t\tdma::BeginTag(dma::call,(uint)pMesh->pSubroutine);\r\n\t\t\t\t\tvif::BASE(256);\r\n\t\t\t\t\tvif::OFFSET(0);\r\n\t\t\t\t\tvif::MSCAL(VU1_ADDR(Setup));\r\n\t\t\t\t\tvif::ITOP(vu1_flags);\r\n\t\t\t\t\tvif::FLUSH();\r\n\t\t\t\t\tdma::EndTag();\r\n\t\t\t\t\tvu1::Loc += ((uint16 *)pMesh->pSubroutine)[1];\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t\t// change lighting context\r\n\t\t\t\tdma::BeginTag(dma::cnt, 0);\r\n\t\t\t\tvif::BASE(256);\r\n\t\t\t\tvif::OFFSET(0);\r\n\t\t\t\tvu1::Loc = 256;\r\n\t\t\t\tLightMatrix[3]  = ambientColour  * 1.0f/(128.0f*8388608.0f);\r\n\t\t\t\tColourMatrix[0] = diffuseColour0 * 1.0f/(128.0f*8388608.0f);\r\n\t\t\t\tColourMatrix[1] = diffuseColour1 * 1.0f/(128.0f*8388608.0f);\r\n\t\t\t\tColourMatrix[2] = diffuseColour2 * 1.0f/(128.0f*8388608.0f);\r\n\t\t\t\tvu1::BeginPrim(ABS, VU1_ADDR(L_VF20));\r\n\t\t\t\tvu1::StoreMat(*(Mat *)&LightMatrix);\t\t\t// VF20-23\r\n\t\t\t\tvu1::StoreMat(*(Mat *)&ColourMatrix);\t\t\t// VF24-27\r\n\t\t\t\tvu1::EndPrim(1);\r\n\t\t\t\tvif::MSCAL(VU1_ADDR(ParseInit));\r\n\t\t\t\tvif::FLUSH();\r\n\t\t\t\tdma::EndTag();\r\n\r\n\t\t\t\t// traverse colour-locked meshes\r\n\t\t\t\tfor (j=0,pMesh=p_group->pMeshes; j<p_group->NumMeshes; j++,pMesh++)\r\n\t\t\t\t{\r\n\t\t\t\t\t// skip if invisible, no subroutine, or affected by dynamic colouring\r\n\t\t\t\t\tif (!pMesh->IsActive() || !pMesh->pSubroutine || !(pMesh->Flags & MESHFLAG_COLOR_LOCKED))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// render the mesh\r\n\t\t\t\t\tvu1::Loc = vu1::Buffer = 256;\r\n\t\t\t\t\tdma::BeginTag(dma::call,(uint)pMesh->pSubroutine);\r\n\t\t\t\t\tvif::BASE(256);\r\n\t\t\t\t\tvif::OFFSET(0);\r\n\t\t\t\t\tvif::MSCAL(VU1_ADDR(Setup));\r\n\t\t\t\t\tvif::ITOP(vu1_flags);\r\n\t\t\t\t\tvif::FLUSH();\r\n\t\t\t\t\tdma::EndTag();\r\n\t\t\t\t\tvu1::Loc += ((uint16 *)pMesh->pSubroutine)[1];\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\r\n\t#if STENCIL_SHADOW\r\n\t// postprocess stencil buffer\r\n\tdma::SetList(sGroup::pShadow);\r\n\r\n\t// send the GS setup\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tgs::BeginPrim(ABS,0,0);\r\n\r\n\tgs::Reg1(gs::TEXFLUSH,\t0);\r\n\r\n\tgs::Reg1(gs::COLCLAMP,\tPackCOLCLAMP(1));\r\n\tgs::Reg1(gs::TEST_1,\tPackTEST(0,0,0,0,0,0,1,ZALWAYS));\r\n\tgs::Reg1(gs::TEX0_1,\tPackTEX0(0x3740,HRES/64,PSMCT16S,10,10,1,DECAL,0,0,0,0,0));\r\n\tgs::Reg1(gs::TEX1_1,\tPackTEX1(1,0,0,0,0,0,0));\r\n\tgs::Reg1(gs::ALPHA_1,\tPackALPHA(2,1,0,1,0));\r\n\tgs::Reg1(gs::TEXA,\t\tPackTEXA(ShadowDensity, 1, ShadowDensity));\r\n\tgs::Reg1(gs::ZBUF_1,\tPackZBUF(ZBUFFER_START,PSMZ24,1));\r\n\r\n\tgs::Reg1(gs::PRIM,\t\tPackPRIM(SPRITE,0,1,0,1,0,1,0,0));\r\n\tgs::Reg1(gs::UV,\t\tPackUV(0x0008,0x0008));\r\n\tgs::Reg1(gs::XYZ2,\t\tPackXYZ(XOFFSET,YOFFSET,0));\r\n\tgs::Reg1(gs::UV,\t\tPackUV((HRES<<4)+8, (VRES<<4)+8));\r\n\tgs::Reg1(gs::XYZ2,\t\tPackXYZ(XOFFSET+(HRES<<4), YOFFSET+(VRES<<4), 0));//0x10000-XOFFSET,0x10000-YOFFSET,0));\r\n\r\n\tgs::Reg1(gs::TEXA,\t\tPackTEXA(0x00,0,0x80));\r\n\tgs::Reg1(gs::ZBUF_1,\tPackZBUF(ZBUFFER_START,PSMZ24,0));\r\n\r\n\tgs::EndPrim(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n\tdma::EndTag();\r\n\t#endif\r\n\r\n\r\n\r\n\t// assume no dma context\r\n\tdma::SetList(NULL);\r\n\r\n}\r\n\r\nvoid patch_texture_dma()\r\n{\r\n\tNx::CScene *p_nxscene =  Nx::CEngine::sGetMainScene();\r\n\tif (p_nxscene)\r\n\t{\r\n\t\tNx::CPs2TexDict *p_tex_dict = (Nx::CPs2TexDict *)p_nxscene->GetTexDict();\r\n\t\tif (p_tex_dict)\r\n\t\t{\r\n\t\t\tsScene *p_scene = p_tex_dict->GetEngineTextureDictionary();\r\n\t\t\r\n\t\t\r\n\t\t\tsTexture *p_textures = p_scene->pTextures;\r\n\t\t\tint num_textures = p_scene->NumTextures;\r\n\t\t\r\n\t\t\t\r\n\t\t//\tint total_referenced = 0;\r\n\t\t//\tint num_unique = 0;\r\n\t\t\tint i;\r\n\t\t\tfor (i=0;i<num_textures;i++)\r\n\t\t\t{\r\n\t\t\t\t\r\n\t\t\t\tuint32* p_dma = (uint32*)p_textures[i].mp_dma;\r\n\t\t\t\t\r\n\t\t//\t\t\tgif::Tag2(0, 0, IMAGE, 0, 0, 0, NumTexQWords[j]);  \t\t\t// 0..3 words, NumTexQWords is in the lower 15 bits of the first word [0]\r\n\t\t//\t\t\tdma::EndTag();\t\t\t\t\t\t\t\t\t   \t\t\t// Just Aligns upo to QW boundry\r\n\t\t//\t\t\tdma::Tag(dma::ref, NumTexQWords[j], (uint)pTextureSource);  // 0..1 (after alignment) NumTexQWords goes in the lower 28 bits of word 0\r\n\t\t\r\n\t\t\t\tif (p_textures[i].m_render_count)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Reset it for next time around\t\r\n\t\t\t\t\tp_textures[i].m_render_count = 0;\r\n\t\t\t\t\t// fix it, so it gets uploaded\r\n\t\t\t\t\t// This test does speed up the routine by about 20%\r\n\t\t\t\t\t// Generally the visibility does not change\r\n\t\t\t\t\tuint32\tcurrent_value = (p_dma[0]);\r\n\t\t\t\t\tif (current_value == 0)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_dma[0] = p_textures[i].m_quad_words;; \r\n\t\t\t\t\t\tuint32* p_dma2 = (uint32*)((((int)(p_dma+4)) + 3)&0xfffffff0);\r\n\t\t\t\t\t\tp_dma2[0] = (dma::ref << 28) | p_textures[i].m_quad_words; \r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// patch it, so nothing gets uploaded\r\n\t\t\t\t\tuint32\tcurrent_value = (p_dma[0]);\r\n\t\t\t\t\tif (current_value != 0)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_dma[0] =  0;\r\n\t\t\t\t\t\tuint32* p_dma2 = (uint32*)((((int)(p_dma+4)) + 3)&0xfffffff0);\r\n\t\t\t\t\t\tp_dma2[0] = (dma::ref << 28);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\nvoid render::NewStyle(bool just_setup)\r\n{\r\n\r\n\tsGroup *p_group;\r\n\r\n\t// add viewport-specific GS registers to each new-style group\r\n\tfor (p_group=sGroup::pHead; p_group!=sGroup::pEpilogue; p_group=p_group->pNext)\r\n\t{\r\n\t\tif ((p_group!=sGroup::pShadow) && p_group->pScene && (p_group->pScene->Flags & SCENEFLAG_USESPIP))\r\n\t\t{\r\n\t\t\t// send the GS viewport context\r\n\t\t\tdma::SetList(p_group);\r\n\r\n\t\t\t// mark our place if it's a (the?) sorted group\r\n\t\t\t// remember to assert there's no overflow\r\n\t\t\tif (p_group->flags & GROUPFLAG_SORT)\r\n\t\t\t{\r\n\t\t\t\t//printf(\"Marking location %08X, p_group==%08X, flags=%08X\\n\", (int)dma::pLoc, (int)p_group, p_group->flags);\r\n\t\t\t\tDbg_MsgAssert(sMarkerIndex < MAX_SORTED_LIST_MARKERS, (\"too many sorted list markers - tell Mike\"));\r\n\t\t\t\trender::sSortedListMarker[render::sMarkerIndex++] = (int)dma::pLoc;\r\n\t\t\t}\r\n\r\n\t\t\tdma::BeginTag(dma::cnt, 0xFE000000);\r\n\t\t\tvif::BASE(vu1::Loc);\r\n\t\t\tvif::OFFSET(0);\r\n\t\t\tuint vu1_loc = vu1::Loc;\r\n\t\t\tvu1::Loc = 0;   \t\t\t\t\t\t\t// must do this as a relative prim for a sortable list...\r\n\r\n\t\t\t// constant part of vu1 context data\r\n\t\t\tvu1::BeginPrim(REL, VU1_ADDR(L_VF09));\r\n\t\t\tvu1::StoreVec(*(Vec *)&render::AltFrustum);\t\t\t\t// VF09\r\n\t\t\tif (p_group->flags & GROUPFLAG_SKY)\r\n\t\t\t{\r\n\t\t\t\tvu1::StoreVec(*(Vec *)&render::SkyInverseViewportScale);\t// VF10\r\n\t\t\t\tvu1::StoreVec(*(Vec *)&render::SkyInverseViewportOffset);\t// VF11\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tvu1::StoreVec(*(Vec *)&render::InverseViewportScale);\t// VF10\r\n\t\t\t\tvu1::StoreVec(*(Vec *)&render::InverseViewportOffset);\t// VF11\r\n\t\t\t}\r\n\t\t\tvu1::EndPrim(0);\r\n\r\n\t\t\tgs::BeginPrim(REL, 0, 0);\r\n\t\t\tgs::Reg1(gs::XYOFFSET_1, render::reg_XYOFFSET);\r\n\t\t\tgs::Reg1(gs::SCISSOR_1,  render::reg_SCISSOR);\r\n\t\t\tgs::EndPrim(1);\r\n\t\t\tvif::MSCAL(VU1_ADDR(Parser));\r\n\t\t\tdma::EndTag();\r\n\t\t\t((uint16 *)dma::pTag)[1] |= vu1::Loc & 0x3FF;\t// must write some code for doing this automatically\r\n\t\t\tvu1::Loc += vu1_loc;\r\n\r\n\t\t\tif (p_group->flags & GROUPFLAG_SORT)\r\n\t\t\t{\r\n\t\t\t\tdma::Tag(dma::cnt,0,0);\r\n\t\t\t\tvif::NOP();\r\n\t\t\t\tvif::NOP();\r\n\t\t\t}\r\n\r\n\t\t\t// assume no vu1 context for each group\r\n\t\t\tp_group->pVu1Context = NULL;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// reserve space from dma list for new trans context\r\n\tdma::SetList(NULL);\r\n\t//CVu1Context *p_ctxt = new(dma::pLoc) CVu1Context;\r\n\tCVu1Context *p_ctxt = (CVu1Context *)dma::pLoc;\r\n\t//dma::pLoc += sizeof(CVu1Context);\r\n\tdma::pLoc += (STD_CTXT_SIZE+7)*16;\r\n\tp_ctxt->Init();\r\n\tMth::Matrix I;\r\n\tI.Ident();\r\n\tp_ctxt->StandardSetup(I);\r\n\r\n\t// shadow stuff\r\n\tsGroup::pShadow->Used[render::Field] = true;\r\n\r\n\t#if !STENCIL_SHADOW\r\n\r\n\t// while the dma context is null, set up an empty upload for the shadow group\r\n\tsGroup::pShadow->pUpload[render::Field] = dma::pLoc;\r\n\tdma::Tag(dma::end, 0, 0);\r\n\tvif::NOP();\r\n\tvif::NOP();\r\n\t\r\n\t// ...and also a vu1 context for the shadow group\r\n\tCVu1Context *p_shdw_ctxt = new(dma::pLoc) CVu1Context(*p_ctxt);\r\n\tdma::pLoc += sizeof(CVu1Context);\r\n\tp_shdw_ctxt->InitExtended();\r\n\tp_shdw_ctxt->SetShadowVecs(SkaterY);\r\n\r\n\t// add a z-push\r\n\tp_shdw_ctxt->AddZPush(16.0f);\r\n\r\n\r\n\tdma::SetList(sGroup::pShadow);\r\n\r\n\t// initial cnt tag, for sending row reg and z-sort key\r\n\tMth::Vector *p_trans = p_shdw_ctxt->GetTranslation();\r\n\tdma::Tag(dma::cnt, 1, 0);\r\n\tvif::NOP();\r\n\tvif::STROW((int)(*p_trans)[0], (int)(*p_trans)[1], (int)(*p_trans)[2], 0);\r\n\r\n\t// send transform context\r\n\tdma::Tag(dma::ref, (EXT_CTXT_SIZE+2)|(EXT_CTXT_SIZE+1)<<16, p_shdw_ctxt->GetDma());\r\n\tvif::BASE(vu1::Loc);\r\n\tvif::OFFSET(0);\r\n\tvu1::Loc += EXT_CTXT_SIZE+1;\r\n\tsGroup::pShadow->pVu1Context = p_shdw_ctxt;\r\n\r\n\t// send the GS context for the shadow list\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\r\n\tvu1::BeginPrim(ABS, VU1_ADDR(L_VF10));\r\n\tvu1::StoreVec(*(Vec *)&render::InverseViewportScale);\t// VF10\r\n\tvu1::StoreVec(*(Vec *)&render::InverseViewportOffset);\t// VF11\r\n\tvu1::EndPrim(0);\r\n\r\n\tgs::BeginPrim(ABS,0,0);\r\n\tgs::Reg1(gs::TEXFLUSH,\t\tPackTEXFLUSH(0));\r\n\tgs::Reg1(gs::FBA_2,\t\t\tPackFBA(0));\r\n\tgs::Reg1(gs::TEX0_2,\t\tPackTEX0(0x3E00,4,PSMCT16,8,8,1,DECAL,0,0,0,0,0));\r\n\tgs::Reg1(gs::TEX1_2,\t\tPackTEX1(1,0,NEAREST,NEAREST,0,0,0));\r\n\tgs::Reg1(gs::CLAMP_2,\t\tPackCLAMP(CLAMP,CLAMP,0,0,0,0));\r\n\tgs::Reg1(gs::FRAME_2,\t\tPackFRAME(FRAME_START,HRES/64,PSMCT32,0xFF000000));\r\n\tgs::Reg1(gs::ZBUF_2,\t\tPackZBUF(ZBUFFER_START,PSMZ24,1));\r\n\tgs::Reg1(gs::XYOFFSET_2,\treg_XYOFFSET);\r\n\tgs::Reg1(gs::SCISSOR_2,\t\treg_SCISSOR);\r\n\tgs::Reg1(gs::ALPHA_2,\t\tPackALPHA(2,1,2,1,ShadowDensity));\r\n\tgs::Reg1(gs::TEST_2,\t\tPackTEST(1,AGEQUAL,0x80,KEEP,0,0,1,ZGEQUAL));\r\n\tgs::Reg1(gs::PRMODECONT,\tPackPRMODECONT(0));\r\n\tgs::Reg1(gs::PRMODE,\t\tPackPRMODE(0,1,0,1,0,0,1,0));\r\n\tgs::EndPrim(0);\r\n\tdma::EndTag();\r\n\t#endif\r\n\r\n\r\n\tgeom_stats_total=0;\r\n\tgeom_stats_inactive =0;\r\n\tgeom_stats_sky=0;\r\n\tgeom_stats_transformed=0;\r\n\tgeom_stats_skeletal=0;\r\n\tgeom_stats_camera_sphere=0;\r\n\tgeom_stats_clipcull=0;\r\n\tgeom_stats_culled=0;\r\n\tgeom_stats_leaf_culled=0;\r\n\tgeom_stats_clipcull=0;\r\n\tgeom_stats_boxcheck=0;\r\n\tgeom_stats_occludecheck=0;\r\n\tgeom_stats_occluded=0;\r\n\tgeom_stats_colored=0;\r\n\tgeom_stats_leaf=0;\r\n\tgeom_stats_wibbleUV=0;\r\n\tgeom_stats_wibbleVC=0;\r\n\tgeom_stats_sendcontext=0;\r\n\tgeom_stats_sorted=0;\r\n\tgeom_stats_shadow=0;\r\n\r\n\t// render the world\r\n\tif (!just_setup)\r\n\t{\r\n\t\t\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tconst int span = 60;\r\n\t\tstatic int avg[span];\r\n\t\tstatic int slot = 0;\r\n\t\tTmr::CPUCycles\tstart = Tmr::GetTimeInCPUCycles();\r\n\t\t#endif\r\n\r\n\t\t#if STENCIL_SHADOW\r\n\t\tCGeomNode::sWorld.RenderWorld(*p_ctxt, RENDERFLAG_CLIP);\r\n\t\t#else\r\n\t\tCGeomNode::sWorld.RenderWorld(*p_ctxt, RENDERFLAG_CLIP | RENDERFLAG_SHADOW);\r\n\t\t#endif\r\n\t\t\r\n\t\t\r\n\t\t#ifdef __NOPT_ASSERT__\t\t\r\n\t\tTmr::CPUCycles len = Tmr::GetTimeInCPUCycles() - start;\r\n\t\tint ticks = len;\r\n\t\tavg[slot++] = ticks;\r\n\t\tif (slot == span) slot = 0;\r\n\t\tint tot = 0;\r\n\t\tfor (int a=0;a<span;a++)\r\n\t\t{\r\n\t\t\ttot += avg[a];\r\n\t\t}\r\n\t\ttot/=span;\r\n//\t\tprintf (\"%9d %9d\\n\",tot,ticks);\t// printf average, and the last frame\r\n\t\t#endif\r\n\t}\r\n\r\n#if 0\r\n\t\tprintf (\"\\ngeom_stats_total = %d\\n\",          geom_stats_total);         \r\n\t\tprintf (\"geom_stats_inactive  = %d\\n\",      geom_stats_inactive );     \r\n\t\tprintf (\"geom_stats_sky = %d\\n\",            geom_stats_sky);           \r\n\t\tprintf (\"geom_stats_transformed = %d\\n\",    geom_stats_transformed);   \r\n\t\tprintf (\"geom_stats_skeletal = %d\\n\",       geom_stats_skeletal);      \r\n\t\tprintf (\"geom_stats_camera_sphere = %d\\n\",  geom_stats_camera_sphere); \r\n\t\tprintf (\"geom_stats_clipcull = %d\\n\",       geom_stats_clipcull);      \r\n\t\tprintf (\"geom_stats_boxcheck = %d\\n\",       geom_stats_boxcheck);      \r\n\t\tprintf (\"geom_stats_occludecheck = %d\\n\",   geom_stats_occludecheck);  \r\n\t\tprintf (\"geom_stats_occluded = %d\\n\",       geom_stats_occluded);      \r\n\t\tprintf (\"geom_stats_colored = %d\\n\",        geom_stats_colored);       \r\n\t\tprintf (\"geom_stats_leaf = %d\\n\",           geom_stats_leaf);          \r\n\t\tprintf (\"geom_stats_wibbleUV = %d\\n\",       geom_stats_wibbleUV);      \r\n\t\tprintf (\"geom_stats_wibbleVC = %d\\n\",       geom_stats_wibbleVC);      \r\n\t\tprintf (\"geom_stats_sendcontext = %d\\n\",    geom_stats_sendcontext);   \r\n\t\tprintf (\"geom_stats_sorted = %d\\n\",         geom_stats_sorted);        \r\n\t\tprintf (\"geom_stats_shadow = %d\\n\",         geom_stats_shadow);        \r\n#endif\t\r\n\r\n\r\n\t#if !STENCIL_SHADOW\r\n\t// undo the havoc caused by the shadow group\r\n\tdma::SetList(sGroup::pShadow);\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tgs::BeginPrim(ABS,0,0);\r\n\tgs::Reg1(gs::PRMODECONT,\tPackPRMODECONT(1));\r\n\tgs::EndPrim(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n\tdma::EndTag();\r\n\t#endif\r\n}\r\n\r\n\r\n\r\n\r\n\r\n#if !STENCIL_SHADOW\r\nvoid SetTextureProjectionCamera( Mth::Vector *p_pos, Mth::Vector *p_at )\r\n{\r\n//\tsTextureProjectionDetails *p_details = pTextureProjectionDetailsTable->GetItem((uint32)p_texture );\r\n//\tif( p_details )\r\n\t{\r\n\t\trender::ShadowCameraPosition[0] = p_pos->GetX();\r\n\t\trender::ShadowCameraPosition[1] = p_pos->GetY();\r\n\t\trender::ShadowCameraPosition[2] = p_pos->GetZ();\r\n\t}\r\n}\r\n#endif\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n// Added by Mick\r\n// quick determination of if something is visible or not\r\n// uses the previously calculated s and c vectors\r\n// and the WorldToCamera transform\r\n// (note, no attempt is made to ensure this is the same camera that the object\r\n// will eventually be rendered with)\r\nbool\tIsVisible(Mth::Vector &center, float radius)\r\n{\r\n\r\n\r\n\tfloat x,y,z;\r\n\tMth::Vector v(center);\r\n\r\n\tv[3] = 1.0f;\t\t// needed?\r\n\tv *= render::WorldToCamera;\r\n\tx = v[0];\r\n\ty = v[1];\r\n\tz = v[2];\r\n\r\n\t// if all outside view volume then cull\r\n\tif (radius<z-render::Near || radius<render::Far-z\t\t\t\t\t\t\t||\r\n\t\tradius<render::sy*z+render::cy*y || radius<render::sy*z-render::cy*y\t||\r\n\t\tradius<render::sx*z-render::cx*x || radius<render::sx*z+render::cx*x)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n//\t\treturn true;\r\n\t\r\n\t\tif( TestSphereAgainstOccluders( &center, radius ))\r\n\t\t{\r\n\t\t\t// Occluded.\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\r\n}\r\n\r\n\r\n// The same function, but without occlusion\r\nbool\tIsInFrame(Mth::Vector &center, float radius)\r\n{\r\n\r\n\tfloat x,y,z;\r\n\tMth::Vector v(center);\r\n\r\n\tv[3] = 1.0f;\t\t\t// needed?\r\n\tv *= render::WorldToCamera;\r\n\tx = v[0];\r\n\ty = v[1];\r\n\tz = v[2];\r\n\r\n\t// if all outside view volume then cull\r\n\tif (radius<z-render::Near || radius<render::Far-z\t\t\t\t\t\t\t||\r\n\t\tradius<render::sy*z+render::cy*y || radius<render::sy*z-render::cy*y\t||\r\n\t\tradius<render::sx*z-render::cx*x || radius<render::sx*z+render::cx*x)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid RenderMesh(sMesh *pMesh, uint RenderFlags)\r\n{\r\n\tdma::BeginTag(dma::call,(uint)pMesh->pSubroutine);\r\n\tvif::BASE(vu1::Loc);\r\n\tvif::OFFSET(0);\r\n\tvif::ITOP(RenderFlags);\r\n\tdma::EndTag();\r\n\tvu1::Loc += ((uint16 *)(pMesh->pSubroutine))[1];\r\n}\r\n\r\n\r\nvoid RenderEpilogue(void)\r\n{\r\n\tsGroup *p_group;\r\n\r\n\t// ---------------------------------------------\r\n\t// tag onto end of particle group\r\n\tdma::SetList(sGroup::pParticles);\r\n\r\n\t// restore vu1 code (and buffering scheme) at end of particles group\r\n\tdma::Tag(dma::ref, ((uint8 *)&MPGEnd-(uint8 *)&MPGStart+15)/16, (uint)&MPGStart);\r\n\tvif::NOP();\r\n\tvif::NOP();\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tvif::FLUSH();\r\n\tvif::STMASK(0);\r\n\tvif::STMOD(0);\r\n\tvif::STCYCL(1,1);\r\n\tvif::BASE(0);\r\n\tvif::OFFSET(0);\r\n\tvif::MSCAL(VU1_ADDR(Setup));\r\n\tvu1::Loc = vu1::Buffer = 0;\r\n\tdma::EndTag();\r\n\r\n\tdma::SetList(NULL);\r\n\t// ---------------------------------------------\r\n\t\r\n\t// add a GS SIGNAL primitive to each group\r\n\tfor (p_group=sGroup::pHead; p_group; p_group=p_group->pNext)\r\n\t{\r\n\t\t// end the dma list\r\n\t\tdma::EndList(p_group);\r\n\t}\r\n\r\n\tdma::SetList(NULL);\r\n\r\n\t// epilogue VRAM upload (fonts and sprites)\r\n\r\n\t// Upload the fonts, so we can draw 2D text on screen\t\r\n\tsGroup::pEpilogue->pUpload[render::Field] = dma::pLoc;\r\n\tuint32 *p = (uint32*)(dma::pLoc);\r\n\tfor (SFont *pFont=pFontList; pFont; pFont=pFont->pNext)\r\n\t{\r\n\t   \t// Mick: we build this upload list directly, to cut down on the number of writes\r\n\t\t*p++ = (dma::ref << 28) + ((pFont->VifSize+15)>>4); //\t\tdma::Tag(dma::ref, (pFont->VifSize+15)>>4, (uint)pFont->pVifData);\r\n\t\t*p++ = (uint32) pFont->pVifData;\r\n\t\t*p++ = 0;    //\t\tvif::NOP();\r\n\t\t*p++ = 0;    //\t\tvif::NOP();\r\n\t}\r\n\r\n\t// Upload the \"Single Textures\", the 2D screen elements (sprites)\r\n\tfor (SSingleTexture *pTexture=SSingleTexture::sp_stexture_list; pTexture; pTexture=pTexture->mp_next)\r\n\t{\r\n\t\tif (pTexture->IsInVRAM())\r\n\t\t{\r\n\t\t\t*p++ = (dma::call << 28) + (0); //\tdma::Tag(dma::call, 0, (uint)pTexture->mp_VifData);\r\n\t\t\t*p++ = (uint32) pTexture->mp_VifData;\r\n\t\t\t*p++ = 0;    //\t\tvif::NOP();\r\n\t\t\t*p++ = 0;    //\t\tvif::NOP();\r\n\t\t}\r\n\t}\r\n\tdma::pLoc = (uint8*)p;\r\n\r\n\t\r\n\t// (?) writing to TEXFLUSH will stall the gs until all the fonts and sprites\r\n\t// have been uploaded.\r\n\t// since we are not double buffering anything now, we have to wait until\r\n\t// everything is in VRAM before we can start rendering any 2D\r\n\t// this is a potential GS hiccup, but removing it would be tricky\r\n\t// and possibly not worth the effort\r\n\t// Garrett: Now the 2D uses both buffers at once.\r\n\t\t\r\n\tdma::BeginTag(dma::end, 0);\r\n\tvif::NOP();\r\n\tvif::NOP();\r\n\tgif::Tag2(gs::A_D,1,PACKED,0,0,1,1);\r\n\tgs::Reg2(gs::TEXFLUSH,\t0);\r\n\tdma::EndTag();\r\n\r\n\r\n\t// We need the scratchpad in SortGroup()\r\n\tbool got_scratch = CSystemResources::sRequestResource(CSystemResources::vSCRATCHPAD_MEMORY);\r\n\tDbg_Assert(got_scratch);\r\n\r\n\t// sort the dma lists of transparent groups\r\n\tfor (p_group=sGroup::pHead; p_group!=sGroup::pEpilogue; p_group=p_group->pNext)\r\n\t{\r\n\t\tif ((p_group->flags & GROUPFLAG_SORT) \t   // Mick, most groups are not SORT, so this test first is the fastest\r\n\t\t\t&& p_group!=sGroup::pShadow\r\n\t\t\t&& p_group->pScene \r\n\t\t\t&& (p_group->pScene->Flags & SCENEFLAG_USESPIP)\r\n\t\t\t)\r\n\t\t{\r\n\t\t\tp_group->pRender[render::Field] = dma::SortGroup(p_group->pRender[render::Field]);\r\n\t\t}\r\n\t}\r\n\r\n\tif (got_scratch)\r\n\t{\r\n\t\tCSystemResources::sFreeResource(CSystemResources::vSCRATCHPAD_MEMORY);\r\n\t}\r\n\r\n\t// swap epilogue and particle texture upload pointers (a cheat!)\r\n\tuint8 *temp_ptr = sGroup::pParticles->pUpload[render::Field];\r\n\tsGroup::pParticles->pUpload[render::Field] = sGroup::pEpilogue->pUpload[render::Field];\r\n\tsGroup::pEpilogue->pUpload[render::Field] = temp_ptr;\r\n\t\r\n\tint size = (int)dma::pLoc - (int)dma::pBase;\r\n\tstatic int max = 0;\r\n\tstatic int max2 = 0;\r\n\tif (size > max) max = size;\r\n\tif (size > max2) max2 = size;\r\n\tstatic int tick = 0;\r\n\ttick++; \r\n\ttick &= 0x1f;\r\n\tif (!tick)\r\n\t{\r\n\t  //  printf (\"%6d, %6d, %6d (of %6d)\\n\",size,max2,max, dma::size);\r\n\t\tmax2 -= 50000;\r\n\t}\r\n\r\n\tDbg_MsgAssert(DMAOverflowOK || size < (dma::size*98/100), (\"DMA Buffer Overflow used %d\\nShow screenshot to Mick (see .bmp saved, above)\",size)); \r\n\t\r\n\tif (DMAOverflowOK)\r\n\t{\r\n\t\tDMAOverflowOK--;\r\n\t}\r\n\t\r\n}\r\n\r\n\r\nvoid SendDisplayList(void)\r\n{\r\n\r\n// Mick:  Mike added this just before he left, but did not check it in\r\n//\tsceGsSyncPath(0, 0);\r\n\r\n\t// patch up the DMA list\r\n// Moved to StuffAfterGSFinished\r\n//\tpatch_texture_dma();\t\r\n\t\r\n\t// Writeback data from D-Cache to Memory\r\n\tFlushCache(WRITEBACK_DCACHE);\r\n\r\n#\tifdef __USE_PROFILER__\r\n// Initial render group does not cause an interrupt\r\n// so don't push context\r\n//\t\t\tSys::VUProfiler->PushContext( 80,80, 228 );\t   \t\t\t\t\t\t\t\t\t\r\n#\tendif // __USE_PROFILER__\r\n\t// kick prologue render\r\n\t*D1_QWC  = 0;\t\t\t\t\t\t// must zero QWC because the first action will be to use current MADR & QWC\r\n\t*D1_TADR = (uint)PrologueGroup.pRender[!render::Field];\t// address of 1st tag\r\n\t*D1_CHCR = 0x145;\t\t\t\t\t// start transfer, tte=1, chain mode, from memory\r\n\tsceGsSyncPath(0, 0);\r\n\r\n\t#if USE_INTERRUPTS\r\n\t\r\n\t// use interrupts\r\n\tsGroup::pUploadGroup = sGroup::pHead;\r\n\tsGroup::pRenderGroup = sGroup::pUploadGroup;\r\n\t\r\n\r\n//\tSingleRender = 0;\r\n\r\n\t#if 0  // debugging code to force all gorups to be executed, even if empty\r\n\tsGroup * p_group = (sGroup*)sGroup::pUploadGroup; // Skip prologue and sky\r\n\twhile (p_group->pNext)\t\t// all except the last one\r\n\t{\r\n\t\tp_group->Used[!render::Field] = 1;\r\n\t\tp_group = p_group->pNext;\r\n\t}\r\n\t#endif\r\n\r\n\r\n\t// Some debugging code to only render/upload a single selectable group\r\n\t// so we can see what is taking all the time\r\n\tif (SingleRender)\r\n\t{\r\n\t\tsGroup * p_group = (sGroup*)sGroup::pUploadGroup; // Skip prologue and sky\r\n\t\tint g = 0;\r\n\t\twhile (p_group->pNext)\t\t// all except the last one\r\n\t\t{\r\n\t\t\tg++;\r\n\t\t\tif (g > 2 && g != SingleRender)\r\n\t\t\t{\r\n\t\t\t\t\tp_group->Used[!render::Field] = 0;\t\t\t\r\n\t\t\t}\r\n\t\t\tp_group = p_group->pNext;\r\n\t\t}\r\n\t}\r\n\t\r\n\tUploadStalled  = 0;\r\n\tRenderStalled  = 1;\r\n\tFlushCache(WRITEBACK_DCACHE);\r\n\r\n#\tifdef __USE_PROFILER__\r\n\tSys::DMAProfiler->PushContext(  sGroup::pUploadGroup->profile_color );\t   \t\t\t\t\t\t\t\t\t\r\n#\tendif // __USE_PROFILER__\r\n\r\n\r\n\t// kick off first upload, should trigger all the rest by interrupt\r\n\t*D2_QWC = 0;\t\t\t\t\t\t// must zero QWC because the first action will be to use current MADR & QWC\r\n\t*D2_TADR = (uint)sGroup::pUploadGroup->pUpload[!render::Field];\t// address of 1st tag\r\n\t*D2_CHCR = 0x105;\t\t\t\t\t// start transfer, tte=0, chain mode, from memory\r\n\r\n\r\n\r\n\t#else\r\n\t\r\n\t// iterate over groups, uploading textures then rendering meshes in each\r\n\t// last group will be epilogue group\r\n\tfor (sGroup *p_group=sGroup::pHead; p_group!=sGroup::pEpilogue; p_group=p_group->pNext)\r\n\t{\r\n\t\tif (p_group->Used[!render::Field])\r\n\t\t{\r\n\t\t\t// kick dma to upload textures from this group\r\n\t\t\t*D2_QWC = 0;\t\t\t\t\t\t// must zero QWC because the first action will be to use current MADR & QWC\r\n\t\t\t*D2_TADR = (uint)p_group->pUpload[!render::Field];\t// address of 1st tag\r\n\t\t\t*D2_CHCR = 0x105;\t\t\t\t\t// start transfer, tte=0, chain mode, from memory\r\n\t\t\tsceGsSyncPath(0, 0);\r\n\r\n\t\t\t// kick dma to render scene\r\n\t\t\t*D1_QWC = 0;\t\t\t\t\t\t// must zero QWC because the first action will be to use current MADR & QWC\r\n\t\t\t*D1_TADR = (uint)p_group->pRender[!render::Field];\t// address of 1st tag\r\n\t\t\t*D1_CHCR = 0x145;\t\t\t\t\t// start transfer, tte=1, chain mode, from memory\r\n\t\t\tsceGsSyncPath(0, 0);\r\n\t\t}\r\n\t}\r\n\r\n\t// kick dma to upload textures from this group\r\n\t*D2_QWC = 0;\t\t\t\t\t\t// must zero QWC because the first action will be to use current MADR & QWC\r\n\t*D2_TADR = (uint)sGroup::pEpilogue->pUpload[!render::Field];\t// address of 1st tag\r\n\t*D2_CHCR = 0x105;\t\t\t\t\t// start transfer, tte=0, chain mode, from memory\r\n\tsceGsSyncPath(0, 0);\r\n\r\n\t// kick dma to render scene\r\n\t*D1_QWC = 0;\t\t\t\t\t\t// must zero QWC because the first action will be to use current MADR & QWC\r\n\t*D1_TADR = (uint)sGroup::pEpilogue->pRender[!render::Field];\t// address of 1st tag\r\n\t*D1_CHCR = 0x145;\t\t\t\t\t// start transfer, tte=1, chain mode, from memory\r\n\tsceGsSyncPath(0, 0);\r\n\t#endif\r\n}\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\nstatic bool sUpdate2DDma = false;\r\nstatic bool\tsVRAMNeedsUpdating = false;\r\n\r\n\r\nvoid\tClear2DVRAM()\r\n{\r\n\t// Reset VRAM pointer\r\n\tFontVramBase = FontVramStart;\r\n\r\n\t// And set flag\r\n\tsUpdate2DDma = true;\r\n}\r\n\r\nvoid\tVRAMNeedsUpdating()\r\n{\r\n\tsVRAMNeedsUpdating = true;\r\n}\r\n\r\nvoid\tReallocate2DVRAM()\r\n{\r\n\tif (!sVRAMNeedsUpdating)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Reset VRAM pointer\r\n\tClear2DVRAM();\r\n\r\n\tfor (SFont *pFont=pFontList; pFont; pFont=pFont->pNext)\r\n\t{\r\n\t\tpFont->ReallocateVRAM();\r\n\t}\r\n\r\n\tfor (SSingleTexture *pTexture=SSingleTexture::sp_stexture_list; pTexture; pTexture=pTexture->mp_next)\r\n\t{\r\n\t\tpTexture->ReallocateVRAM();\r\n\t}\r\n\r\n\t// And set flags\r\n\tsUpdate2DDma = true;\r\n\tsVRAMNeedsUpdating = false;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid\tUpdate2DDMA()\r\n{\r\n\t// Only go through the lists if it was requested\r\n\tif (!sUpdate2DDma)\r\n\t\treturn;\r\n\r\n\t// Go through each item\r\n\tfor (SFont *pFont=pFontList; pFont; pFont=pFont->pNext)\r\n\t{\r\n\t\tpFont->UpdateDMA();\r\n\t}\r\n\r\n\tfor (SSingleTexture *pTexture=SSingleTexture::sp_stexture_list; pTexture; pTexture=pTexture->mp_next)\r\n\t{\r\n\t\tpTexture->UpdateDMA();\r\n\t}\r\n\r\n\t// Clear flag\r\n\tsUpdate2DDma = false;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n#if STENCIL_SHADOW\r\n\r\nvoid CastStencilShadow(CInstance *pInstance, sGroup *p_group, Mth::Vector &ShadowVec, Mth::Vector &TweakVec)\r\n{\r\n\tsShadowVolumeHeader * p_shadow = pInstance->GetScene()->mp_shadow_volume_header;\r\n\tif (!p_shadow)\r\n\t\treturn;\r\n\r\n\tMth::Matrix RootToFrustum,RootToViewport, WorldToRoot;\r\n\r\n\tRootToFrustum = *(Mth::Matrix *)pInstance->GetTransform() * render::WorldToFrustum;\r\n\tRootToViewport = RootToFrustum * render::FrustumToIntViewport;\r\n\r\n\tWorldToRoot = *(Mth::Matrix *)pInstance->GetTransform();\r\n\tWorldToRoot.Transpose();\r\n\tShadowVec *= WorldToRoot;\r\n\tTweakVec *= WorldToRoot;\r\n\r\n\tdma::SetList(sGroup::pShadow);\r\n\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tvu1::BeginPrim(ABS, VU1_ADDR(L_VF14));\r\n\tvu1::StoreVec(*(Vec *)&ShadowVec);\t\t\t// VF14, shadow vec\r\n\tvu1::StoreVec(*(Vec *)&TweakVec);\t\t\t// VF15, tweak vec\r\n\tvu1::StoreMat(*(Mat *)&RootToViewport);\t\t// VF16-19\r\n\tvu1::EndPrim(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n\tvif::FLUSH();\r\n\tdma::EndTag();\r\n\r\n\t// send transforms\r\n\tvu1::Loc = 0;\r\n\tdma::Tag(dma::ref, pInstance->GetNumBones()<<2, (uint)pInstance->GetBoneTransforms());\r\n\tvif::STCYCL(1,1);\r\n\tvif::UNPACK(0,V4_32,pInstance->GetNumBones()<<2,ABS,SIGNED,0);\r\n\r\n\t// send data\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tvif::STCYCL(7,21);\r\n\r\n\tsShadowVertex * p_vertex = p_shadow->p_vertex;\r\n\tsShadowConnect * p_connect = p_shadow->p_connect;\r\n\tsShadowNeighbor * p_neighbor = p_shadow->p_neighbor;\r\n\r\n\tint vert, num_faces;\r\n\tfor (uint32 i=0; i<p_shadow->num_faces; i++)\r\n\t{\r\n\t\tif (i%36==0)\r\n\t\t{\r\n\t\t\tvu1::Loc = 256;\r\n\t\t\tvif::BASE(256);\r\n\t\t\tvif::OFFSET(0);\r\n\t\t\tvif::MSCAL(VU1_ADDR(Setup));\r\n\t\t}\r\n\r\n\t\tif (i%12==0)\r\n\t\t{\r\n\t\t\tnum_faces = p_shadow->num_faces-i;\r\n\t\t\tif (num_faces>12)\r\n\t\t\t\tnum_faces=12;\r\n\r\n\r\n\t\t\tvif::UNPACK(0, V4_32, 7*num_faces, ABS, UNSIGNED, 0);\r\n\t\t}\r\n\r\n\t\tif ((i%12==11) || (i==p_shadow->num_faces-1))\r\n\t\t{\r\n\t\t\tvif::StoreV4_32(0x3480800A, 0x21224000, 0x00000051, 0x8000);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tvif::StoreV4_32(0x3480800A, 0x21224000, 0x00000051, 0x0000);\r\n\t\t}\r\n\r\n\t\tuint32 * p32 = (uint32 *)dma::pLoc;\r\n\r\n\t\tvert = p_connect[i].corner[0];\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].x));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].y));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].z));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].idx));\r\n\r\n\t\tvert = p_connect[i].corner[1];\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].x));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].y));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].z));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].idx));\r\n\r\n\t\tvert = p_connect[i].corner[2];\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].x));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].y));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].z));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].idx));\r\n\r\n\t\tvert = p_neighbor[i].edge[0];\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].x));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].y));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].z));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].idx));\r\n\r\n\t\tvert = p_neighbor[i].edge[1];\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].x));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].y));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].z));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].idx));\r\n\r\n\t\tvert = p_neighbor[i].edge[2];\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].x));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].y));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].z));\r\n\t\t*p32++ = *((uint32 *)(&p_vertex[vert].idx));\r\n\r\n\t\tdma::pLoc = (uint8 *)p32;\r\n\r\n\t\tvu1::Loc += 21;\r\n\r\n\t\tif ((i%12 == 11) || (i==p_shadow->num_faces-1))\r\n\t\t{\r\n\t\t\tvif::MSCAL(VU1_ADDR(ShadowVolumeSkin));\r\n\t\t}\r\n\t}\r\n\r\n\tdma::EndTag();\r\n\r\n\tdma::SetList(p_group);\r\n}\r\n\r\n#else\r\n\r\nvoid CastShadow(CInstance *pInstance, sGroup *p_group)\r\n{\r\n\tint j;\r\n\tsMesh *pMesh;\r\n\tMth::Matrix ProjMat, temp;\r\n\r\n\t// set up projection matrix\r\n\tProjMat = *pInstance->GetTransform();\r\n\tSkaterY = ProjMat[3][1];\r\n\tProjMat[3].Set(-36.0f/**SUB_INCH_PRECISION*/*ProjMat[1][0],\r\n\t\t\t\t   -36.0f/**SUB_INCH_PRECISION*/*ProjMat[1][1],\r\n\t\t\t\t   -36.0f/**SUB_INCH_PRECISION*/*ProjMat[1][2], 1.0f);\r\n\ttemp[0].Set(32.0f/**RECIPROCAL_SUB_INCH_PRECISION*/, 0.0f, 0.0f, 0.0f);\r\n\ttemp[1].Set(0.0f, 0.0f, 0.0f, 0.0f);\r\n\ttemp[2].Set(0.0f, 32.0f/**RECIPROCAL_SUB_INCH_PRECISION*/, 0.0f, 0.0f);\r\n\ttemp[3].Set(8421376.0f, 8421376.0f, 0.0f, 1.0f);\r\n\tProjMat *= temp;\r\n\r\n\tdma::SetList(sGroup::pShadow);\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tvu1::BeginPrim(ABS, VU1_ADDR(L_VF12));\r\n\tvu1::StoreMat(*(Mat *)&ProjMat);\t\t// VF16-19\r\n\tvu1::EndPrim(1);\r\n\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n\r\n\t// not using pre-translate\r\n\t// don't forget to switch off the offset mode on xyz unpack if using the row reg for somthing else\r\n\tvif::STROW(0,0,0,0);\r\n\r\n\t// get free run of the VUMem\r\n\tvif::FLUSH();\r\n\r\n\tdma::EndTag();\r\n\r\n\t// send transforms\r\n\tvu1::Loc = 0;\r\n\tdma::Tag(dma::ref, pInstance->GetNumBones()<<2, (uint)pInstance->GetBoneTransforms());\r\n\tvif::NOP();\r\n\tvif::UNPACK(0,V4_32,pInstance->GetNumBones()<<2,ABS,SIGNED,0);\r\n\r\n\tdma::Tag(dma::cnt, 0, 0);\r\n\tvif::ITOP(pInstance->GetNumBones()<<2);\r\n\tvif::MSCAL(VU1_ADDR(ReformatXforms));\r\n\r\n\t// traverse array of meshes in the model\r\n\tfor (j=0,pMesh=p_group->pMeshes; j<p_group->NumMeshes; j++,pMesh++)\r\n\t{\r\n\t\t// skip if invisible\r\n\t\tif (!pMesh->IsActive())\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// do nothing if mesh doesn't have a dma subroutine\r\n\t\tif (!pMesh->pSubroutine)\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// render the mesh\r\n\t\tvu1::Loc = vu1::Buffer = 256;\r\n\t\tdma::BeginTag(dma::call,(uint)pMesh->pSubroutine);\r\n\t\tvif::BASE(256);\r\n\t\tvif::OFFSET(0);\r\n\t\tvif::MSCAL(VU1_ADDR(Setup));\r\n\t\tvif::ITOP(SHDW);\r\n\t\tvif::FLUSH();\r\n\t\tdma::EndTag();\r\n\t\tvu1::Loc += ((uint16 *)pMesh->pSubroutine)[1];\r\n\t}\r\n\r\n\tdma::Tag(dma::cnt, 0, 0);\r\n\tvif::FLUSH();\r\n\tvif::NOP();\r\n\r\n\tdma::SetList(p_group);\r\n}\r\n\r\n#endif\r\n\r\n\r\n\r\n\r\nnamespace render\r\n{\r\n\tMth::Matrix WorldToCamera;\r\n\tMth::Matrix WorldToCameraRotation;\t\t// shouldn't need this\r\n\tMth::Matrix WorldToFrustum;\r\n\tMth::Matrix WorldToViewport;\r\n\tMth::Matrix WorldToIntViewport;\r\n\tMth::Matrix CameraToWorld;\r\n\tMth::Matrix CameraToWorldRotation;\r\n\tMth::Matrix CameraToFrustum;\r\n\tMth::Matrix CameraToViewport;\r\n\tMth::Matrix FrustumToViewport;\r\n\tMth::Matrix FrustumToIntViewport;\r\n\tMth::Matrix AdjustedWorldToCamera;\r\n\tMth::Matrix AdjustedWorldToFrustum;\r\n\tMth::Matrix AdjustedWorldToViewport;\r\n\tMth::Matrix AdjustedWorldToIntViewport;\r\n\tMth::Matrix SkyWorldToCamera;\r\n\tMth::Matrix SkyWorldToFrustum;\r\n\tMth::Matrix SkyWorldToViewport;\r\n\tMth::Matrix SkyFrustumToViewport;\r\n\r\n\tMth::Vector ViewportScale;\r\n\tMth::Vector ViewportOffset;\r\n\tMth::Vector IntViewportScale;\r\n\tMth::Vector IntViewportOffset;\r\n\tMth::Vector InverseViewportScale;\r\n\tMth::Vector InverseViewportOffset;\r\n\tMth::Vector InverseIntViewportScale;\r\n\tMth::Vector InverseIntViewportOffset;\r\n\tMth::Vector SkyViewportScale;\r\n\tMth::Vector SkyViewportOffset;\r\n\tMth::Vector SkyInverseViewportScale;\r\n\tMth::Vector SkyInverseViewportOffset;\r\n\tMth::Vector RowReg;\r\n\tMth::Vector RowRegI;\r\n\tMth::Vector RowRegF;\r\n\t#if !STENCIL_SHADOW\r\n\tMth::Vector ShadowCameraPosition;\r\n\t#endif\r\n\tMth::Vector AltFrustum;\r\n\tMth::Vector CameraPosition;\r\n\r\n\tuint64 reg_XYOFFSET;\r\n\tuint64 reg_SCISSOR;\r\n\r\n\tfloat sx,sy,cx,cy,tx,ty,Sx,Sy,Cx,Cy,Tx,Ty,Near,Far;\r\n\t//float sMultipassMaxDist = 1000000000.0f;\r\n\tfloat sMultipassMaxDist = 4000.0f;\r\n\r\n\tuint Frame, Field;\r\n\tuint ViewportMask;\r\n\r\n\tuint RenderVarFrame = 0xFFFFFFFF; \r\n\tuint RenderVarViewport = 0xFFFFFFFF;\r\n\r\n\tbool FrustumFlagsPlus[3], FrustumFlagsMinus[3];\r\n\r\n\tint sSortedListMarker[MAX_SORTED_LIST_MARKERS];\r\n\tint sMarkerIndex;\r\n\tint sTime;\r\n\tint sTotalNewParticles;\r\n\r\n\tfloat FogNear=3000.0f, FogAlpha=0.80f;\r\n\tuint32 FogCol=0xFF4070;\r\n\tbool EnableFog=false;\r\n\tfloat EffectiveFogAlpha;\r\n\r\n\tuint32 *p_patch_FOGCOL;\r\n\r\n\tuint8 ShadowDensity = 48;\r\n}\r\n\r\n\r\n\r\nvoid render::SetupVars(uint viewport_num, const Mth::Matrix& camera_transform, const Mth::Rect& viewport_rec, float view_angle,\r\n\t\t\t\t\t   float viewport_aspect, float near, float far)\r\n{\r\n\r\n\t// fog variables\r\n\tEffectiveFogAlpha = FogAlpha;\r\n\tif (FogAlpha < 0.003f)\r\n\t{\r\n\t\tEffectiveFogAlpha = 0.003f;\r\n\t}\r\n\tif (FogAlpha > 0.997f)\r\n\t{\r\n\t\tEffectiveFogAlpha = 0.997f;\r\n\t}\r\n\tif (!EnableFog)\t\t// TT5158: ZPush is affected by FogAlpha, so having a very low number causes z-fighting.  Garrett\r\n\t{\r\n\t\tEffectiveFogAlpha = 0.75f;\r\n\t}\r\n\t*p_patch_FOGCOL = FogCol;\r\n\r\n\r\n\t// Check if we already set up the current variables\r\n\tif (VarsUpToDate(viewport_num))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// camera transform\r\n\tCameraToWorld = camera_transform;\r\n\r\n\tDbg_MsgAssert(CameraToWorld[0][3] == 0.0f, (\"CameraToWorld[0][3] is %f, not 0.0\", CameraToWorld[0][3]));\r\n\tDbg_MsgAssert(CameraToWorld[1][3] == 0.0f, (\"CameraToWorld[1][3] is %f, not 0.0\", CameraToWorld[1][3]));\r\n\tDbg_MsgAssert(CameraToWorld[2][3] == 0.0f, (\"CameraToWorld[2][3] is %f, not 0.0\", CameraToWorld[2][3]));\r\n\tDbg_MsgAssert(CameraToWorld[3][3] == 1.0f, (\"CameraToWorld[3][3] is %f, not 1.0\", CameraToWorld[3][3]));\r\n\r\n\t// need the transform to be well-formed as a 4x4 matrix\r\n\t//CameraToWorld[0][3] = 0.0f;\r\n\t//CameraToWorld[1][3] = 0.0f;\r\n\t//CameraToWorld[2][3] = 0.0f;\r\n\t//CameraToWorld[3][3] = 1.0f;\r\n\r\n\tCameraToWorldRotation = CameraToWorld;\r\n\tCameraToWorldRotation[3].Set(0.0f, 0.0f, 0.0f, 1.0f);\r\n\r\n\t// world view transform\r\n\tWorldToCameraRotation.Transpose(CameraToWorldRotation);\r\n\tWorldToCamera = CameraToWorld;\r\n\tWorldToCamera.InvertUniform();\r\n\r\n\t// massage to get ROW register value\r\n\tRowReg = SUB_INCH_PRECISION * WorldToCamera[3] * CameraToWorldRotation;\r\n\tRowRegI[0] = (float)(int)RowReg[0];\r\n\tRowRegI[1] = (float)(int)RowReg[1];\r\n\tRowRegI[2] = (float)(int)RowReg[2];\r\n\tRowRegI[3] = 0.0f;\r\n\tRowRegF = RowReg - RowRegI;\r\n\tRowRegF[3] = 0.0f;\r\n\r\n\t// massage to get modified matrix\r\n\tAdjustedWorldToCamera = WorldToCamera;\r\n\tAdjustedWorldToCamera[3] = RowRegF * WorldToCameraRotation;\r\n\tAdjustedWorldToCamera[3] *= RECIPROCAL_SUB_INCH_PRECISION;\r\n\tAdjustedWorldToCamera[3][3] = 1.0f;\r\n\r\n\t// view frustum\r\n\ttx = tanf(view_angle*8.72664626e-03f);\t\t// tan of half (angle in radians)\r\n\tty = -(tx / viewport_aspect);\r\n\tsx\t= 1.0f/sqrtf(1.0f+1.0f/(tx*tx));\r\n\tsy\t= 1.0f/sqrtf(1.0f+1.0f/(ty*ty));\r\n\tcx\t= 1.0f/sqrtf(1.0f+tx*tx);\r\n\tcy\t= 1.0f/sqrtf(1.0f+ty*ty);\r\n\tNear = near;\r\n\tFar  = far;\r\n\r\n\t// outer frustum\r\n\tTx = tx * (620.0f/(((float) HRES) * 0.5f * viewport_rec.GetWidth()));\r\n\tTy = ty * (524.0f/(((float) VRES) * 0.5f * viewport_rec.GetHeight()));\r\n\tSx\t= 1.0f/sqrtf(1.0f+1.0f/(Tx*Tx));\r\n\tSy\t= 1.0f/sqrtf(1.0f+1.0f/(Ty*Ty));\r\n\tCx\t= 1.0f/sqrtf(1.0f+Tx*Tx);\r\n\tCy\t= 1.0f/sqrtf(1.0f+Ty*Ty);\r\n\r\n\t// frustum transform\r\n\tCameraToFrustum.Zero();\r\n\tCameraToFrustum[0][0] = 1.0f/Tx;\r\n\tCameraToFrustum[1][1] = 1.0f/Ty;\r\n\tCameraToFrustum[2][2] = (near+far) / (far-near);\r\n\tCameraToFrustum[3][2] = 2.0f * near * far / (near-far);\r\n\tCameraToFrustum[2][3] = -1.0f;\r\n\tAdjustedWorldToFrustum = AdjustedWorldToCamera * CameraToFrustum;\r\n\tWorldToFrustum = WorldToCamera * CameraToFrustum;\r\n\r\n\t// viewport (scale and offset from outer frustum)\r\n\tViewportScale.Set( 620.0f, 524.0f, 0.999f*powf(2,22), EffectiveFogAlpha);\r\n\tViewportOffset.Set(2048.0f, 2048.0f, 1.5f*powf(2,23), 0);\r\n\tIntViewportScale.Set(620.0f, 524.0f, 0.999f*powf(2,-95), powf(2,32));\r\n\tIntViewportOffset.Set(2048.0f+powf(2,19), 2048.0f+powf(2,19), 1.5f*powf(2,-94), powf(2,-32));\r\n\r\n\t// viewport transform\r\n\tFrustumToViewport.Zero();\r\n\tFrustumToViewport[0][0] = ViewportScale[0];\r\n\tFrustumToViewport[1][1] = ViewportScale[1];\r\n\tFrustumToViewport[2][2] = ViewportScale[2];\r\n\tFrustumToViewport[3][3] = ViewportScale[3];\r\n\tFrustumToViewport[3][0] = ViewportOffset[0];\r\n\tFrustumToViewport[3][1] = ViewportOffset[1];\r\n\tFrustumToViewport[3][2] = ViewportOffset[2];\r\n\tAdjustedWorldToViewport = AdjustedWorldToFrustum * FrustumToViewport;\r\n\tWorldToViewport = WorldToFrustum * FrustumToViewport;\r\n\tCameraToViewport = CameraToFrustum * FrustumToViewport;\r\n\r\n\tFrustumToIntViewport.Zero();\r\n\tFrustumToIntViewport[0][0] = IntViewportScale[0];\r\n\tFrustumToIntViewport[1][1] = IntViewportScale[1];\r\n\tFrustumToIntViewport[2][2] = IntViewportScale[2];\r\n\tFrustumToIntViewport[3][3] = IntViewportScale[3];\r\n\tFrustumToIntViewport[3][0] = IntViewportOffset[0];\r\n\tFrustumToIntViewport[3][1] = IntViewportOffset[1];\r\n\tFrustumToIntViewport[3][2] = IntViewportOffset[2];\r\n\tAdjustedWorldToIntViewport = AdjustedWorldToFrustum * FrustumToIntViewport;\r\n\tWorldToIntViewport = WorldToFrustum * FrustumToIntViewport;\r\n\r\n\r\n\t// sky transforms\r\n\t//SkyViewportScale.Set(1900.0f, 1900.0f, powf(2,-102), powf(2,32));\t\t// convert these to constants\r\n\t//SkyViewportOffset.Set(2048.0f+powf(2,19), 2048.0f+powf(2,19), 1.5f*powf(2,-101), powf(2,-32));\t// convert these to constants\r\n\tSkyViewportScale.Set( 620.0f, 524.0f, 0.01f, EffectiveFogAlpha);\r\n\tSkyViewportOffset.Set(2048.0f, 2048.0f, 1.0f, 0);\r\n\r\n\tSkyWorldToCamera = AdjustedWorldToCamera;\r\n\tSkyWorldToCamera[3][0] = 0;\r\n\tSkyWorldToCamera[3][1] = 0;\r\n\tSkyWorldToCamera[3][2] = 0;\r\n\tSkyWorldToFrustum = SkyWorldToCamera * CameraToFrustum;\r\n\tSkyFrustumToViewport = FrustumToViewport;\r\n\tSkyFrustumToViewport[2][2] = SkyViewportScale[2];\r\n\tSkyFrustumToViewport[3][2] = SkyViewportOffset[2];\r\n\tSkyWorldToViewport = SkyWorldToFrustum * SkyFrustumToViewport;\r\n\r\n\t// used in 3D clipping\r\n\tAltFrustum[0] = Near;\r\n\tAltFrustum[1] = Far;\r\n\tAltFrustum[2] = 620.0f/(((float) HRES) * 0.5f * viewport_rec.GetWidth());\r\n\tAltFrustum[3] = 524.0f/(((float) VRES) * 0.5f * viewport_rec.GetHeight());\r\n\r\n\t// invert the viewport scale and offset\r\n\tInverseViewportScale[0]  = 1.0f / ViewportScale[0];\r\n\tInverseViewportScale[1]  = 1.0f / ViewportScale[1];\r\n\tInverseViewportScale[2]  = 1.0f / ViewportScale[2];\r\n\tInverseViewportScale[3]  = 1.0f / ViewportScale[3];\r\n\r\n\tInverseViewportOffset[0] = -InverseViewportScale[0] * ViewportOffset[0] * InverseViewportScale[3];\r\n\tInverseViewportOffset[1] = -InverseViewportScale[1] * ViewportOffset[1] * InverseViewportScale[3];\r\n\tInverseViewportOffset[2] = -InverseViewportScale[2] * ViewportOffset[2] * InverseViewportScale[3];\r\n\tInverseViewportOffset[3] = -InverseViewportScale[3] * ViewportOffset[3] * InverseViewportScale[3];\r\n\tInverseViewportOffset[3] = FogNear;\r\n\t\r\n\tInverseIntViewportScale[0]  = 1.0f / IntViewportScale[0];\r\n\tInverseIntViewportScale[1]  = 1.0f / IntViewportScale[1];\r\n\tInverseIntViewportScale[2]  = 1.0f / IntViewportScale[2];\r\n\tInverseIntViewportScale[3]  = 1.0f / IntViewportScale[3];\r\n\r\n\tInverseIntViewportOffset[0] = -InverseIntViewportScale[0] * IntViewportOffset[0] * InverseIntViewportScale[3];\r\n\tInverseIntViewportOffset[1] = -InverseIntViewportScale[1] * IntViewportOffset[1] * InverseIntViewportScale[3];\r\n\tInverseIntViewportOffset[2] = -InverseIntViewportScale[2] * IntViewportOffset[2] * InverseIntViewportScale[3];\r\n\tInverseIntViewportOffset[3] = 0.0f;\r\n\t\r\n\tSkyInverseViewportScale[0]  = 1.0f / SkyViewportScale[0];\r\n\tSkyInverseViewportScale[1]  = 1.0f / SkyViewportScale[1];\r\n\tSkyInverseViewportScale[2]  = 1.0f / SkyViewportScale[2];\r\n\tSkyInverseViewportScale[3]  = 1.0f / SkyViewportScale[3];\r\n\r\n\tSkyInverseViewportOffset[0] = -SkyInverseViewportScale[0] * SkyViewportOffset[0] * SkyInverseViewportScale[3];\r\n\tSkyInverseViewportOffset[1] = -SkyInverseViewportScale[1] * SkyViewportOffset[1] * SkyInverseViewportScale[3];\r\n\tSkyInverseViewportOffset[2] = -SkyInverseViewportScale[2] * SkyViewportOffset[2] * SkyInverseViewportScale[3];\r\n\tSkyInverseViewportOffset[3] = 0.0f;\r\n\t\r\n\r\n\r\n\t// generate the GS register values we'll need for the viewport\r\n\treg_XYOFFSET = PackXYOFFSET((int)(16.0f * (2048.0f - ((float) HRES) * (viewport_rec.GetOriginX() + 0.5f * viewport_rec.GetWidth()))),\r\n\t\t\t\t\t\t\t\t(int)(16.0f * (2048.0f - ((float) VRES) * (viewport_rec.GetOriginY() + 0.5f * viewport_rec.GetHeight()))));\r\n\treg_SCISSOR  = PackSCISSOR( (int)(((float) HRES) * viewport_rec.GetOriginX()),\r\n\t\t\t\t\t\t\t\t(int)(((float) HRES) * (viewport_rec.GetOriginX() + viewport_rec.GetWidth())) - 1,\r\n\t\t\t\t\t\t\t\t(int)(((float) VRES) * viewport_rec.GetOriginY()),\r\n\t\t\t\t\t\t\t\t(int)(((float) VRES) * (viewport_rec.GetOriginY() + viewport_rec.GetHeight())) - 1);\r\n\r\n\r\n\t// inverse frustum transform\r\n\t//ViewFrustumToCamera.Zero();\r\n\t//ViewFrustumToCamera[0][0] = tx;\r\n\t//ViewFrustumToCamera[1][1] = ty;\r\n\t//ViewFrustumToCamera[2][3] = (near - far) / (2.0f * near * far);\r\n\t//ViewFrustumToCamera[3][2] = -1.0f;\r\n\t//ViewFrustumToCamera[3][3] = -(near + far) / (2.0f * near * far);\r\n\r\n\t// get world coords of the far frustum vertices\r\n\tMth::Vector vFTL, vFTR, vFBL, vFBR;\r\n\tvFTL.Set( tx*far, ty*far, far, 1.0f);\r\n\tvFTL *= CameraToWorld;\r\n\tvFTR.Set(-tx*far, ty*far, far, 1.0f);\r\n\tvFTR *= CameraToWorld;\r\n\tvFBL.Set( tx*far,-ty*far, far, 1.0f);\r\n\tvFBL *= CameraToWorld;\r\n\tvFBR.Set(-tx*far,-ty*far, far, 1.0f);\r\n\tvFBR *= CameraToWorld;\r\n\r\n\tMth::Vector pos(WorldToCamera[3]);\r\n\tfor (int i=0; i<3; i++)\r\n\t{\r\n\t\tFrustumFlagsPlus[i]  = (vFTL[i]>=pos[i] && vFTR[i]>=pos[i] && vFBL[i]>=pos[i] && vFBR[i]>=pos[i]);\r\n\t\tFrustumFlagsMinus[i] = (vFTL[i]<=pos[i] && vFTR[i]<=pos[i] && vFBL[i]<=pos[i] && vFBR[i]<=pos[i]);\r\n\t}\r\n\r\n\r\n    // Set ViewportMask.  Will only draw CGeomNodes that have a non-zero result with (ViewportMask & Visibility)\r\n\tViewportMask = (1 << (VISIBILITY_FLAG_BIT + viewport_num));\r\n\r\n\t// Mark current viewport and frame\r\n\tRenderVarFrame = Frame;\r\n\tRenderVarViewport = viewport_num;\r\n\r\n}\r\n\r\nvoid\trender::SetupVarsDMA(uint viewport_num, float near, float far)\r\n{\r\n\r\n\r\n\t// initialisation for new bounding volume tests\r\n\tMth::Matrix Normals;\r\n\r\n\tasm (\"vmaxw vf31,vf00,vf00w\": :);\r\n\r\n\t// view frustum\t R,  L,  B,  T\r\n\tNormals[0].Set(-cx, cx,  0,  0);\r\n\tNormals[1].Set(  0,  0, cy,-cy);\r\n\tNormals[2].Set(-sx,-sx,-sy,-sy);\r\n\tNormals[3].Set(  0,  0,  0,  0);\r\n\r\n\tNormals = WorldToCamera * Normals;\r\n\r\n\tasm __volatile__(\"\r\n\r\n\t\tlqc2\t\tvf10,(%0)\r\n\t\tlqc2\t\tvf11,(%1)\r\n\t\tlqc2\t\tvf12,(%2)\r\n\t\tlqc2\t\tvf16,(%3)\r\n\t\tvabs\t\tvf13,vf10\r\n\t\tvabs\t\tvf14,vf11\r\n\t\tvabs\t\tvf15,vf12\r\n\r\n\t\": : \"r\" (&Normals[0]), \"r\" (&Normals[1]), \"r\" (&Normals[2]), \"r\" (&Normals[3]));\r\n\r\n\t// both frusta    ?,   ?    N,   F,\r\n\tNormals[0].Set(   0,   0,   0,   0);\r\n\tNormals[1].Set(   0,   0,   0,   0);\r\n\tNormals[2].Set(   0,   0,  -1,   1);\r\n\tNormals[3].Set(   0,   0,near,-far);\r\n\r\n\tNormals = WorldToCamera * Normals;\r\n\r\n\tasm __volatile__(\"\r\n\r\n\t\tlqc2\t\tvf17,(%0)\r\n\t\tlqc2\t\tvf18,(%1)\r\n\t\tlqc2\t\tvf19,(%2)\r\n\t\tlqc2\t\tvf23,(%3)\r\n\t\tvabs\t\tvf20,vf17\r\n\t\tvabs\t\tvf21,vf18\r\n\t\tvabs\t\tvf22,vf19\r\n\r\n\t\": : \"r\" (&Normals[0]), \"r\" (&Normals[1]), \"r\" (&Normals[2]), \"r\" (&Normals[3]));\r\n\r\n\r\n\t// outer frustum R,  L,  B,  T\r\n\tNormals[0].Set(-Cx, Cx,  0,  0);\r\n\tNormals[1].Set(  0,  0, Cy,-Cy);\r\n\tNormals[2].Set(-Sx,-Sx,-Sy,-Sy);\r\n\tNormals[3].Set(  0,  0,  0,  0);\r\n\r\n\tNormals = WorldToCamera * Normals;\r\n\r\n\tasm __volatile__(\"\r\n\r\n\t\tlqc2\t\tvf24,(%0)\r\n\t\tlqc2\t\tvf25,(%1)\r\n\t\tlqc2\t\tvf26,(%2)\r\n\t\tlqc2\t\tvf30,(%3)\r\n\t\tvabs\t\tvf27,vf24\r\n\t\tvabs\t\tvf28,vf25\r\n\t\tvabs\t\tvf29,vf26\r\n\r\n\t\": : \"r\" (&Normals[0]), \"r\" (&Normals[1]), \"r\" (&Normals[2]), \"r\" (&Normals[3]));\r\n\r\n\r\n\r\n\r\n\t#if OLD_FOG\r\n\t// link in the dma list that does fogging postprocessing\r\n\tdma::SetList(sGroup::pFog);\r\n\tdma::Tag(dma::call, 0, (uint)&FogDma);\r\n\tvif::NOP();\r\n\tvif::NOP();\r\n\tsGroup::pFog->Used[render::Field] = true;\r\n\r\n\tdma::Gosub(SET_RENDERSTATE,2);\r\n\tdma::Gosub(SET_FOGCOL,2);\r\n\t#endif\r\n\r\n\r\n\t// upload new vu1 code and set up double-buffering\r\n\tdma::SetList(sGroup::pParticles);\r\n\tdma::Tag(dma::ref, ((uint8 *)&NewMPGEnd-(uint8 *)&NewMPGStart+15)/16, (uint)&NewMPGStart);\r\n\tvif::BASE(0);\r\n\tvif::OFFSET(32);\r\n\t\r\n\t// send vu1 data for particle setup\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tvif::FLUSH();\r\n\tvif::BeginDIRECT();\r\n\tgif::Tag2(gs::A_D,1,PACKED,0,0,1,3);\r\n\tgs::Reg2(gs::SCISSOR_1, render::reg_SCISSOR);\r\n\tgs::Reg2(gs::XYOFFSET_1, render::reg_XYOFFSET);\r\n\tgs::Reg2(gs::ZBUF_1, PackZBUF(ZBUFFER_START,PSMZ24,1));\r\n\tvif::EndDIRECT();\r\n\tvif::UNPACK(0, V4_32, 7, REL, SIGNED, 0);\r\n\tvu1::StoreMat(*(Mat *)&render::WorldToIntViewport);\t\t\t// view transform\r\n\tvif::StoreV4_32F(320.0f, 320.0f, 0.0f, 0.0f);\t\t\t\t// kvec\r\n\tvif::StoreV4_32(0x39005000, 0x39006000, 0, 0x3F800000);\t\t// NTL cull test vec - w-component limits tan of apparent radius\r\n\tvif::StoreV4_32(0x3900B000, 0x3900A000, 0, 0);\t\t\t\t// BR cull test vec\r\n\tvif::MSCAL(8);\t\t// init sprites\r\n\tdma::EndTag();\r\n\tdma::SetList(NULL);\r\n}\r\n\r\n\r\n\r\n// Checks to see if the render variables are current\r\nbool render::VarsUpToDate(uint viewport_num)\r\n{\r\n\treturn (RenderVarFrame == Frame) && (RenderVarViewport == viewport_num);\r\n}\r\n\r\n// Invalidates the render variables\r\nvoid render::InvalidateVars()\r\n{\r\n\tRenderVarFrame = 0xFFFFFFFF; \r\n\tRenderVarViewport = 0xFFFFFFFF;\r\n}\r\n\r\n// a quick hack for Dave...\r\nvoid DrawRectangle(int x0, int y0, int x1, int y1, uint32 rgba)\r\n{\r\n\tdma::SetList(sGroup::pEpilogue);\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tvif::FLUSH();\r\n\tvif::BeginDIRECT();\r\n\tgif::BeginTag2(gs::A_D, 1, PACKED, SPRITE|ABE, 1);\r\n\tgs::Reg2(gs::ALPHA_1,\tPackALPHA(0,1,0,1,0));\r\n\tgs::Reg2(gs::RGBAQ,\t\t(uint64)rgba);\r\n\tgs::Reg2(gs::XYZ2,\t\tPackXYZ(x0,y0,0xFFFFFF));\r\n\tgs::Reg2(gs::XYZ2,\t\tPackXYZ(x1,y1,0xFFFFFF));\r\n\tgif::EndTag2(1);\r\n\tvif::EndDIRECT();\r\n\tdma::EndTag();\r\n}\r\n\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/render.h",
    "content": "#ifndef __RENDER_H\r\n#define __RENDER_H\r\n\r\n\r\n#include \"mikemath.h\"\r\n#include <core/math.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n#define SUB_INCH_PRECISION 16.0f\r\n#define RECIPROCAL_SUB_INCH_PRECISION 0.0625f\r\n\r\n\r\ntypedef struct\r\n{\r\n\tfloat tx,ty;\r\n\tfloat n,f;\r\n}\r\nsFrustum;\r\n\r\n\r\nvoid RenderPrologue(void);\r\nvoid RenderInitImmediateMode();\r\n\r\nvoid RenderWorld(Mth::Matrix* camera_orient, Mth::Vector* camera_pos, float view_angle, float screen_aspect);\r\nvoid RenderEpilogue(void);\r\n\r\nvoid RenderSwitchImmediateMode();\r\n\r\nvoid RenderViewport(uint viewport_num, const Mth::Matrix& camera_transform, const Mth::Rect & viewport_rec, float view_angle,\r\n\t\t\t\t\tfloat viewport_aspect, float nearz, float farz, bool just_setup=false);\r\n\r\nbool IsVisible(Mth::Vector &center, float radius);\r\nvoid UpdateCamera(Mat *camera_orient, Vec *camera_pos);\r\nvoid SendDisplayList(void);\r\nvoid RenderMesh(struct sMesh *pMesh, uint RenderFlags);\r\nvoid SkinTest(void);\r\nvoid SetTextureProjectionCamera( Mth::Vector *p_pos, Mth::Vector *p_at );\r\nvoid DrawRectangle(int x0, int y0, int x1, int y1, uint32 rgba);\r\n\r\nvoid Clear2DVRAM();\r\nvoid VRAMNeedsUpdating();\r\nvoid Reallocate2DVRAM();\r\nvoid Update2DDMA();\r\n\r\nvoid EnableFlipCopy(bool flip);\r\nbool FlipCopyEnabled();\r\n\r\n\r\nextern uint  Frame, Field;\r\nextern Mat SkaterTransform;\r\nextern Mat BoneTransforms[64];\r\nextern int NumBones;\r\n\r\nextern int\tSingleRender;\r\nextern bool DoLetterbox;\r\nextern int\tDMAOverflowOK;\r\n\r\n\r\n\r\n\r\nnamespace render\r\n{\r\n\tvoid SetupVars(uint viewport_num, const Mth::Matrix& camera_transform, const Mth::Rect& viewport_rec, float view_angle,\r\n\t\t\t\t   float viewport_aspect, float near_z, float far_z);\r\n#ifndef __PLAT_WN32__\r\n\tvoid SetupVarsDMA(uint viewport_num, float near, float far);\t\r\n#endif\t\t// __PLAT_WN32__\r\n\tbool VarsUpToDate(uint viewport_num);\r\n\tvoid InvalidateVars();\r\n\r\n\tvoid OldStyle();\r\n\tvoid NewStyle(bool just_setup = false);\r\n\r\n\textern Mth::Matrix WorldToCamera;\r\n\textern Mth::Matrix WorldToCameraRotation;\r\n\textern Mth::Matrix WorldToFrustum;\r\n\textern Mth::Matrix WorldToViewport;\r\n\textern Mth::Matrix WorldToIntViewport;\r\n\textern Mth::Matrix CameraToWorld;\r\n\textern Mth::Matrix CameraToWorldRotation;\r\n\textern Mth::Matrix CameraToFrustum;\r\n\textern Mth::Matrix CameraToViewport;\r\n\textern Mth::Matrix FrustumToViewport;\r\n\textern Mth::Matrix FrustumToIntViewport;\r\n\textern Mth::Matrix AdjustedWorldToCamera;\r\n\textern Mth::Matrix AdjustedWorldToFrustum;\r\n\textern Mth::Matrix AdjustedWorldToViewport;\r\n\textern Mth::Matrix AdjustedWorldToIntViewport;\r\n\textern Mth::Matrix SkyWorldToCamera;\r\n\textern Mth::Matrix SkyWorldToFrustum;\r\n\textern Mth::Matrix SkyWorldToViewport;\r\n\textern Mth::Matrix SkyFrustumToViewport;\r\n\r\n\textern Mth::Vector ViewportScale;\r\n\textern Mth::Vector ViewportOffset;\r\n\textern Mth::Vector IntViewportScale;\r\n\textern Mth::Vector IntViewportOffset;\r\n\textern Mth::Vector InverseViewportScale;\r\n\textern Mth::Vector InverseViewportOffset;\r\n\textern Mth::Vector InverseIntViewportScale;\r\n\textern Mth::Vector InverseIntViewportOffset;\r\n\textern Mth::Vector SkyViewportScale;\r\n\textern Mth::Vector SkyViewportOffset;\r\n\textern Mth::Vector SkyInverseViewportScale;\r\n\textern Mth::Vector SkyInverseViewportOffset;\r\n\textern Mth::Vector RowReg;\r\n\textern Mth::Vector RowRegI;\r\n\textern Mth::Vector RowRegF;\r\n\textern Mth::Vector ShadowCameraPosition;\r\n\textern Mth::Vector AltFrustum;\r\n\textern Mth::Vector CameraPosition;\r\n\r\n\textern uint64 reg_XYOFFSET;\r\n\textern uint64 reg_SCISSOR;\r\n\r\n\textern float sx,sy,cx,cy,tx,ty,Sx,Sy,Cx,Cy,Tx,Ty,Near,Far;\r\n\textern float sMultipassMaxDist;\r\n\r\n\textern uint Frame, Field;\r\n\textern uint ViewportMask;\r\n\r\n\textern bool FrustumFlagsPlus[3], FrustumFlagsMinus[3];\r\n\r\n\t#define MAX_SORTED_LIST_MARKERS 32\r\n\textern int sSortedListMarker[MAX_SORTED_LIST_MARKERS];\r\n\textern int sMarkerIndex;\r\n\textern int sTime;\r\n\textern int sTotalNewParticles;\r\n\r\n\textern float FogNear, FogAlpha;\r\n\textern uint32 FogCol;\r\n\textern uint32 *p_patch_FOGCOL;\r\n\textern bool EnableFog;\r\n\textern float EffectiveFogAlpha;\r\n\textern uint8 ShadowDensity;\r\n}\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n#endif // __RENDER_H\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/resource.cpp",
    "content": "#include <core/defines.h>\r\n#include <eekernel.h>\r\n#include \"resource.h\"\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\nbool\t\t\tCSystemResources::s_resource_used[vNUM_RESOURCES];\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \t\t\tCSystemResources::sInitResources()\r\n{\r\n\tfor (int i = 0; i < vNUM_RESOURCES; i++)\r\n\t{\r\n\t\ts_resource_used[i] = false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool \t\t\tCSystemResources::sRequestResource(EResourceType resource)\r\n{\r\n\tDbg_Assert(resource < vNUM_RESOURCES);\r\n\t\r\n\tbool old_result;\r\n\r\n\t// We need to do this with interrupts off, just in case\r\n\tDI();\r\n\told_result = s_resource_used[resource];\r\n\ts_resource_used[resource] = true;\t\t\t// We know it is reserved now\r\n\tEI();\r\n\r\n\treturn !old_result;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \t\t\tCSystemResources::sFreeResource(EResourceType resource)\r\n{\r\n\tDbg_Assert(resource < vNUM_RESOURCES);\r\n\tDbg_Assert(s_resource_used[resource]);\r\n\r\n\t// We need to do this with interrupts off, just in case\r\n\tDI();\r\n\ts_resource_used[resource] = false;\r\n\tEI();\r\n}\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/resource.h",
    "content": "#ifndef __RESOURCE_H\r\n#define __RESOURCE_H\r\n\r\n#include\t<core/defines.h>\r\n#include\t<core/math.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n// This static class locks certain system resources (like scratchpad and VU0 memory)\r\n// for code to use exclusively.  Right now, there is no mechanism to lock out just\r\n// parts of memory, but it may be added in the future if needed.\r\nclass CSystemResources\r\n{\r\n\r\npublic:\r\n\t// Resource types\r\n\tenum EResourceType {\r\n\t\tvVU0_MEMORY = 0,\r\n\t\tvSCRATCHPAD_MEMORY,\r\n\t\tvNUM_RESOURCES\r\n\t};\r\n\r\n\t//-------------------------------------------\r\n\r\n\tstatic void sInitResources();\t\t\t\t\t\t\t\t// Call only at the beginning!\r\n\r\n\tstatic bool sRequestResource(EResourceType resource); \t\t// Returns true if it was able to lock it\r\n\tstatic void sFreeResource(EResourceType resource);\r\n\r\nprivate:\r\n\tstatic bool s_resource_used[vNUM_RESOURCES];\r\n\r\n};\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n\r\n#endif // __RESOURCE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/scene.cpp",
    "content": "#include <sifdev.h>\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <libdma.h>\r\n#include <libgraph.h>\r\n#include <errno.h>\r\n#include <string.h>\r\n#include <core/defines.h>\r\n#include \"texture.h\"\r\n#include \"material.h\"\r\n#include \"mesh.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n#include \"scene.h\"\r\n#include \"mikemath.h\"\r\n#include \"vu1code.h\"\r\n#include \"switches.h\"\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/memfile.h>\r\n\r\n#include <core/debug.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nbool load_scene(uint8* pData, int dataSize, sScene *pScene, bool IsSkin, bool IsInstanceable, uint32 texDictOffset, bool doShadowVolume)\r\n{\r\n\tpScene->mp_shadow_volume_header = NULL;\r\n\r\n\t// make sure there's no dma list running\r\n\tsceGsSyncPath(0,0);\r\n\r\n\t// Load the scene file onto the dma buffer so we can use it as a memory mapped file\r\n\tvoid *pMemory = pData;\r\n\tvoid *pFile = pMemory;\r\n\t\r\n\tint\tmesh_size = dataSize * 10/100 + 2000;\t\t// adding the 2000 to cope with very small files\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t// version numbers\r\n\tuint32 vert_version;\r\n\tMEM_Read(&sMaterial::Version, sizeof(uint32), 1, pFile);\r\n\tMEM_Read(&sMesh::Version, sizeof(uint32), 1, pFile);\r\n\tMEM_Read(&vert_version, sizeof(uint32), 1, pFile);\r\n\r\n\t// allocate and import materials\r\n\tpFile = LoadMaterials(pFile, pScene, texDictOffset);\r\n\r\n\t// get number of mesh groups\r\n\tint NumGroups;\r\n\tMEM_Read(&NumGroups, sizeof(uint32), 1, pFile);\r\n\tif ( NumGroups != pScene->NumGroups )\r\n\t{\r\n\t\tDbg_Message( \"Scene mismatch in number of groups\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tint total_num_meshes = 0;\r\n\t// get number of meshes and allocate storage for meshes\r\n\tif (sMesh::Version >= 4)\r\n\t{\r\n\t\tMEM_Read(&total_num_meshes, sizeof(uint32), 1, pFile);\r\n\t\tmesh_size = total_num_meshes * sizeof(sMesh);\r\n\t}\r\n\t\r\n\tif ( pScene->NumMeshes != 0 )\r\n\t{\r\n\t\tDbg_Message( \"pScene->NumMeshes is %d when loading scene, texDictOffset = %d\", pScene->NumMeshes, texDictOffset );\r\n\t\treturn false;\r\n\t}\r\n\t\t\t\t\t\t\t\t\t\t  \r\n\tpScene->pMeshes = (sMesh *)Mem::Malloc(mesh_size);\r\n\r\n\tif ( pScene->pMeshes == NULL )\r\n\t{\r\n\t\tDbg_Message( \"couldn't allocate memory for meshes\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// allocate prebuilt dma buffer\r\n//\tint\tdma_size = Mem::Available()-128;\r\n\r\n\tint\tdma_size = dataSize;  // Really should be around 80%, based on observations, but we know it's no bigger\r\n\t\r\n\tif (dma_size < 300000)\r\n\t{\r\n\t\tdma_size = dma_size *110/100;\t \t// Patch for ironman problem\r\n\t}\r\n\t\t\t \r\n\tpScene->pMeshDma = (uint8 *)Mem::Malloc(dma_size);\r\n\tif ( pScene->pMeshDma == NULL )\r\n\t{\r\n\t\tDbg_Message( \"couldn't allocate memory for mesh dma\" );\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// set dma buffer\r\n\tdma::pLoc = pScene->pMeshDma;\r\n\r\n\t// allocate and import meshes\r\n\tsMesh::TotalNumVertices=0;\r\n\tpFile = LoadMeshes(pFile, pScene, IsSkin, IsInstanceable, texDictOffset);\r\n\r\n//\tprintf (\"DMA Mesh (used %d,  file size = %d, NumMeshes = %d, total_num_meshes = %d, available %d)\\n\",\r\n//\t(int)(dma::pLoc-pScene->pMeshDma), dataSize, pScene->NumMeshes, total_num_meshes, dma_size);\r\n\t\r\n\tDbg_MsgAssert( (int)(dma::pLoc-pScene->pMeshDma) < dma_size,(\"DMA overflow all available memory (used %d, available %d)\\n\",(int)(dma::pLoc-pScene->pMeshDma),dma_size));\r\n\t\r\n\t\r\n\tif ( (int)(pScene->NumMeshes*sizeof(sMesh)) > mesh_size )\r\n\t{\r\n\t\tDbg_Message( \"Mesh overflow file = %s, file size = %d, guessed = %d, actually %d\", dataSize, mesh_size, pScene->NumMeshes * sizeof(sMesh) );\r\n\t\treturn false;\r\n\t}\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t// reduce dma memory to fit\r\n\tMem::Manager::sHandle().ReallocateShrink( dma::pLoc-pScene->pMeshDma, pScene->pMeshDma);\r\n\t\r\n\t// reduce mesh memory to fit\r\n\tif (sMesh::Version < 4)\r\n\t{\r\n\t\tMem::Manager::sHandle().ReallocateShrink( pScene->NumMeshes*sizeof(sMesh), pScene->pMeshes);\r\n\t}\r\n\t\r\n\t// Hook up shadow volume data.\r\n\tpScene->mp_shadow_volume_header = (sShadowVolumeHeader *)pFile;\r\n\r\n\t#if STENCIL_SHADOW\r\n\tif ( pScene->mp_shadow_volume_header && pScene->mp_shadow_volume_header->byte_size )\r\n\t{\r\n\t\tint size = pScene->mp_shadow_volume_header->byte_size + sizeof ( sShadowVolumeHeader );\r\n\t\tchar * p8 = new char[size];\r\n\t\tmemcpy( p8, pScene->mp_shadow_volume_header, size );\r\n\t\tpScene->mp_shadow_volume_header = (sShadowVolumeHeader *)p8;\r\n\t\tpScene->mp_shadow_volume_header->p_vertex = (sShadowVertex *)&pScene->mp_shadow_volume_header[1];\r\n\t\tpScene->mp_shadow_volume_header->p_connect = (sShadowConnect *)&pScene->mp_shadow_volume_header->p_vertex[pScene->mp_shadow_volume_header->num_verts];\r\n\t\tpScene->mp_shadow_volume_header->p_neighbor = (sShadowNeighbor *)&pScene->mp_shadow_volume_header->p_connect[pScene->mp_shadow_volume_header->num_faces];\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpScene->mp_shadow_volume_header = NULL;\r\n\t}\r\n\t#else\r\n\tpScene->mp_shadow_volume_header = NULL;\r\n\t#endif\r\n\r\n\t// deal with instances\r\n\tpScene->pInstances = NULL;\r\n\tif (IsInstanceable)\r\n\t{\r\n\t\tpScene->Flags |= SCENEFLAG_INSTANCEABLE;\r\n\t}\r\n\r\n\t// success\r\n\treturn true;\r\n}\r\n\r\n// load scene from a file\r\nsScene* LoadScene(const char* Filename, sScene *pScene, bool IsSkin, bool IsInstanceable, uint32 texDictOffset, bool doShadowVolume)\r\n{\r\n\tint data_size;\r\n\tuint8* pData = (uint8*)File::LoadAlloc(Filename,&data_size,dma::pRuntimeBuffer,NON_DEBUG_DMA_BUFFER_SIZE);\t\r\n\t\r\n\t// theoretically, the data pointer returned is\r\n\t// exactly the same as the dma::pRuntimeBuffer\r\n\tDbg_MsgAssert( pData == dma::pRuntimeBuffer, ( \"Unexpected data pointer was found\" ) );\r\n\r\n\tbool success = load_scene(pData, data_size, pScene, IsSkin, IsInstanceable, texDictOffset, doShadowVolume);\r\n\tif ( !success )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Load scene from file %s failed\", Filename ) );\r\n\t}\r\n\r\n\treturn pScene;\r\n}\r\n\r\n// load scene from a data buffer, rather than opening a file\r\nsScene* LoadScene(uint32* pData, int dataSize, sScene *pScene, bool IsSkin, bool IsInstanceable, uint32 texDictOffset, bool doShadowVolume)\r\n{\r\n\tDbg_MsgAssert( dataSize <= NON_DEBUG_DMA_BUFFER_SIZE, ( \"Data to copy is too large to fit in buffer\" ) ); \r\n\r\n\t// copy over the data\r\n\tmemcpy( dma::pRuntimeBuffer, pData, dataSize );\r\n\t\r\n\tbool success = load_scene((uint8*)pData, dataSize, pScene, IsSkin, IsInstanceable, texDictOffset, doShadowVolume);\r\n\tif ( !success )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Load scene from data buffer failed\" ) );\r\n\t}\r\n\r\n\treturn pScene;\r\n}\r\n\r\nvoid DeleteScene(sScene *pScene)\r\n{\r\n\t// deallocate assets\r\n\tMem::Free(pScene->pMeshDma);\r\n\tMem::Free(pScene->pMaterials);\r\n\tMem::Free(pScene->pMeshes);\r\n\tMem::Free(pScene->mp_shadow_volume_header);\r\n\t// and what of groups?\r\n\r\n\t// don't unlink or free, because the textures still exist\r\n\r\n\t// GJ:  a little pre-emptive debugging, since scenes\r\n\t// and textures aren't necessarily destroyed at the same time\r\n\tpScene->pMeshDma = NULL;\r\n\tpScene->pMaterials = NULL;\r\n\tpScene->pMeshes = NULL;\r\n\r\n\tDbg_MsgAssert(!pScene->pInstances, (\"Trying to delete sScene that still has CInstances attached to it.  Must delete CInstances first.\"));\r\n}\r\n\r\n\r\n\r\nvoid sScene::SetUVOffset(uint32 material_name, int pass, float u_offset, float v_offset)\r\n{\r\n\t#if 1\r\n\tsMesh *pMesh;\r\n\tMth::Matrix mat;\r\n\tint i;\r\n\r\n\tmat.Identity();\r\n\tmat[3][0] = u_offset;\r\n\tmat[3][1] = v_offset;\r\n\r\n\tfor (pMesh=this->pMeshes, i=0; i<this->NumMeshes; pMesh++, i++)\r\n\t{\r\n\t\tif (pMesh->MaterialName==material_name && pMesh->Pass==pass)\r\n\t\t{\r\n\t\t\tdma::TransformSTs(pMesh->pSubroutine, mat);\r\n\t\t}\r\n\t}\r\n\t#else\r\n\t\r\n\t// just some test code for me to play around with...\r\n\r\n\tsMesh *pMesh;\r\n\tMth::Matrix mat;\r\n\tint i;\r\n\r\n\tmat.Identity();\r\n\r\n\t//mat[0][0] = cosf(2.0f * 3.14159265f * u_offset);\r\n\t//mat[0][1] = sinf(2.0f * 3.14159265f * u_offset);\r\n\t//mat[1][0] = -mat[0][1];\r\n\t//mat[1][1] = mat[0][0];\r\n\r\n\tif (u_offset>0.0f)\r\n\t\tmat[0][0] = 1.01f;\r\n\telse if (u_offset<0.0f)\r\n\t\tmat[0][0] = 1.0f/1.01f;\r\n\tif (v_offset>0.0f)\r\n\t\tmat[1][1] = 1.01f;\r\n\telse if (v_offset<0.0f)\r\n\t\tmat[1][1] = 1.0f/1.01f;\r\n\r\n\tfor (pMesh=this->pMeshes, i=0; i<this->NumMeshes; pMesh++, i++)\r\n\t{\r\n\t\tif (pMesh->MaterialName==material_name && pMesh->Pass==pass)\r\n\t\t{\r\n\t\t\tdma::TransformSTs(pMesh->pSubroutine, mat);\r\n\t\t}\r\n\t}\r\n\t#endif\r\n}\r\n\r\n\r\n\r\n\r\nvoid sScene::SetUVMatrix(uint32 material_name, int pass, const Mth::Matrix &mat)\r\n{\r\n\tsMesh *pMesh;\r\n\tint i;\r\n\r\n\tfor (pMesh=this->pMeshes, i=0; i<this->NumMeshes; pMesh++, i++)\r\n\t{\r\n\t\tif (pMesh->MaterialName==material_name && pMesh->Pass==pass)\r\n\t\t{\r\n\t\t\tdma::TransformSTs(pMesh->pSubroutine, mat);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nsScene *sScene::pHead;\r\nuint8  *sScene::pData;\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/scene.h",
    "content": "#ifndef __SCENE_H\r\n#define __SCENE_H\r\n\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/math.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n#define SCENEFLAG_INSTANCEABLE (1<<0)\r\n#define SCENEFLAG_USESPIP      (1<<1)\r\n\r\n\r\nstruct sShadowVertex\r\n{\r\n\tfloat\tx;\r\n\tfloat\ty;\r\n\tfloat\tz;\r\n\tint\t\tidx;\r\n};\r\n\r\nstruct sShadowConnect\r\n{\r\n\tuint16\tcorner[3];\r\n};\r\n\r\nstruct sShadowNeighbor\r\n{\r\n\tsint16\tedge[3];\r\n};\r\n\r\nstruct sShadowVolumeHeader\r\n{\r\n\tuint32\t\t\t\tversion;\r\n\tuint32\t\t\t\tnum_faces;\r\n\tuint32\t\t\t\tnum_verts;\r\n\tuint32\t\t\t\tbyte_size;\r\n\tsShadowVertex *\t\tp_vertex;\r\n\tsShadowConnect *\tp_connect;\r\n\tsShadowNeighbor *\tp_neighbor;\r\n\tuint32\t\t\t\tpad;\r\n};\r\n\r\nstruct sScene\r\n{\r\n\tMth::Vector\t\t\tSphere;\r\n\r\n\tuint32\t\t\t\tFlags;\r\n\tint\t\t\t\t\tNumGroups;\r\n\r\n\tint\t\t\t\t\tNumTextures;\r\n\tuint8\t\t\t\t*pTexBuffer;\r\n\tuint8\t\t\t\t*pTexDma;\r\n\tstruct sTexture\t\t*pTextures;\r\n\r\n\tint\t\t\t\t\tNumMaterials;\r\n\tstruct sMaterial\t*pMaterials;\r\n\r\n\tint \t\t\t\tNumMeshes;\r\n\tuint8 \t\t\t\t*pMeshDma;\r\n\tstruct sMesh\t\t*pMeshes;\r\n\tclass  CInstance\t*pInstances;\r\n\r\n\tsScene\t\t\t\t*pNext;\r\n\r\n\tstatic sScene\t\t*pHead;\r\n\tstatic uint8\t\t*pData;\r\n\r\n\tsShadowVolumeHeader\t*mp_shadow_volume_header;\r\npublic:\r\n\tvoid SetUVOffset(uint32 material_name, int pass, float u_offset, float v_offset);\r\n\tvoid SetUVMatrix(uint32 material_name, int pass, const Mth::Matrix &mat);\r\n};\r\n\r\nstruct sCASData;\r\n\r\nsScene *LoadScene(uint32 *pData, int dataSize, sScene *pScene, bool IsSkin, bool Instanced, uint32 texDictOffset, bool doShadowVolume);\r\nsScene *LoadScene(const char *Filename, sScene *pScene, bool IsSkin, bool Instanced, uint32 texDictOffset, bool doShadowVolume);\r\nvoid DeleteScene(sScene *pScene);\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n#endif // __SCENE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/sprite.cpp",
    "content": "#include <string.h>\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <sys/file/filesys.h>\r\n#include <core/math.h>\r\n#include <core/math/vector.h>\r\n#include <eestruct.h>\r\n#include <sifdev.h>\r\n#include <stdlib.h>\r\n#include \"sprite.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n#include \"vu1code.h\"\r\n#include \"texturemem.h\"\r\n#include \"render.h\"\r\n#include \"switches.h\"\r\n#include <gel/scripting/symboltable.h>\r\n\r\n/*\r\n\r\n\r\n\t\r\n.img file format\r\n--------------------------\r\n\t\r\nOffset\t\tSize (Bytes)\tField\r\n---------------------------------------------------------------\r\n0x00\t\t\t4\t\t\tVersion (currently 1)\r\n0x04\t\t\t4\t\t\tBasename of file in CRC format\r\n0x08\t\t\t4\t\t\tPS2 TW (log2 Width)\r\n0x0c\t\t\t4\t\t\tPS2 TH (log2 Height)\r\n0x10\t\t\t4\t\t\tPS2 PSM (Bit depth)\r\n0x14\t\t\t4\t\t\tPS2 CPSM (CLUT bit depth)\r\n0x18\t\t\t4\t\t\tPS2 MXL (Number of mipmaps)\r\n0x1c\t\t\t2\t\t\tOriginal image width\r\n0x1e\t\t\t2\t\t\tOriginal image height\r\n0x20\t\t\tUpto 1K\t\tCLUT data\r\n0x20+CLUT_size\tW*H*depth\t\tTexture mipmaps\r\n\r\n\t\r\n\t\r\n\t\r\nfont->vram upload format\r\n------------------------\r\n\r\n\r\n\tGIFtag PACKED 4\r\n\tBITBLTBUF ?\r\n\tTRXPOS 0\r\n\tTRXREG w,h\r\n\tTRXDIR 0\r\n\t\r\n\tGIFtag IMAGE (w*h+15)/16\r\n\t... (tex data)\r\n\t\r\n\tGIFtag PACKED 4\r\n\tBITBLTBUF ?\r\n\tTRXPOS 0\r\n\tTRXREG w,h\r\n\tTRXDIR 0\r\n\t\r\n\tGIFtag IMAGE 64\r\n\t... (clut data)\r\n\t\r\n\t\r\n\t\r\n\ttotal size in bytes = 12*16+((w*h+15)/16)*16+1024 = 1216+((w*h+15)/16)*16\r\n\t\r\n\tthis will be referenced as follows:\r\n\t\r\n\tdma ref\r\n\tNOP\r\n\tDIRECT 76+(w*h+15)/16\r\n\t\r\n\t\r\n*/\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* SSingleTexture\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSSingleTexture *\tSSingleTexture::sp_stexture_list = NULL;\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nSSingleTexture::SSingleTexture()\r\n{\r\n\tDbg_Error(\"Must supply a filename when creating a SSingleTexture\");\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// .img.ps2 buffer\r\n\r\nSSingleTexture::SSingleTexture(uint8* p_buffer, int buffer_size, bool sprite, bool alloc_vram, bool load_screen) :\r\n\tm_flags(0),\r\n\tm_usage_count(0)\r\n{\r\n\t#ifdef\t\t\t__NOPT_ASSERT__\r\n\tstrcpy(m_name,\"texture from buffer\");\r\n\t#endif\r\n\r\n\tmp_TexBitBltBuf = mp_ClutBitBltBuf = NULL;\r\n\r\n\t// Set flags\r\n\tif (load_screen)\r\n\t{\r\n\t\tm_flags |= mLOAD_SCREEN;\r\n\t}\r\n\tif (sprite)\r\n\t{\r\n\t\tm_flags |= mSPRITE;\r\n\t}\r\n\tif ((sprite && alloc_vram) && !load_screen)\r\n\t{\r\n\t\tm_flags |= mALLOC_VRAM;\r\n\t}\r\n\r\n\t// open the font file\r\n\tif (!sprite)\r\n\t{\r\n\t\tDbg_Assert(!alloc_vram);\r\n\t}\r\n\t\r\n\tmp_PixelData = mp_ClutData = NULL;\r\n\tm_PixelDataSize = m_ClutDataSize = 0;\r\n\t\r\n\tmp_TexBuffer = (uint8*)Mem::Malloc( buffer_size );\r\n\tDbg_Assert( mp_TexBuffer );\r\n\tmemcpy( mp_TexBuffer, p_buffer, buffer_size );\r\n\tm_TexBufferSize = buffer_size;\r\n\t\r\n\t// Initialize all the data\r\n\tInitTexture(false);\r\n\r\n\t// add texture to texture list\r\n\tif (sprite && !load_screen)\r\n\t{\r\n\t\tmp_next = sp_stexture_list;\r\n\t\tsp_stexture_list = this;\r\n\t}\r\n\r\n\tif (load_screen) {\r\n\t\tFlipTextureVertical();\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// .img.ps2 file\r\n\r\nSSingleTexture::SSingleTexture(const char *Filename, bool sprite, bool alloc_vram, bool load_screen) :\r\n\tm_flags(0),\r\n\tm_usage_count(0)\r\n{\r\n\tchar ExtendedFilename[128];\r\n\t\t  \r\n\t#ifdef\t\t\t__NOPT_ASSERT__\r\n\tstrcpy(m_name,Filename);\r\n\t#endif\r\n\r\n\tmp_TexBitBltBuf = mp_ClutBitBltBuf = NULL;\r\n\r\n\t// Set flags\r\n\tif (load_screen)\r\n\t{\r\n\t\tm_flags |= mLOAD_SCREEN;\r\n\t}\r\n\tif (sprite)\r\n\t{\r\n\t\tm_flags |= mSPRITE;\r\n\t}\r\n\tif ((sprite && alloc_vram) && !load_screen)\r\n\t{\r\n\t\tm_flags |= mALLOC_VRAM;\r\n\t}\r\n\r\n\t// open the font file\r\n\tif (sprite)\r\n\t{\r\n//\t\tstrcpy(ExtendedFilename, \"images/\");\r\n//\t\tstrcat(ExtendedFilename, Filename);\r\n\t\tstrcpy(ExtendedFilename, Filename);\r\n\t} else {\r\n\t\tDbg_Assert(!alloc_vram);\r\n\r\n\t\tstrcpy(ExtendedFilename, Filename);\r\n\t}\r\n\tstrcat(ExtendedFilename, \".img.ps2\");\r\n\t\r\n\tmp_PixelData = mp_ClutData = NULL;\r\n\tm_PixelDataSize = m_ClutDataSize = 0;\r\n\t\r\n\t#if 0\r\n\tvoid *pFile = File::Open(ExtendedFilename, \"rb\");\r\n\t// get file size and allocate texture buffer\r\n\tm_TexBufferSize = File::GetFileSize(pFile);\r\n\tmp_TexBuffer = (uint8 *)Mem::Malloc(m_TexBufferSize);\r\n\tFile::Read(mp_TexBuffer, 1, m_TexBufferSize, pFile);\r\n\tFile::Close(pFile);\r\n\t#else\r\n\tmp_TexBuffer = (uint8*)File::LoadAlloc(ExtendedFilename, &m_TexBufferSize);\r\n\t#endif\r\n\t\r\n\t// Initialize all the data\r\n\tInitTexture(false);\r\n\r\n\t// add texture to texture list\r\n\tif (sprite && !load_screen)\r\n\t{\r\n\t\tmp_next = sp_stexture_list;\r\n\t\tsp_stexture_list = this;\r\n\t}\r\n\r\n\tif (load_screen) {\r\n\t\tFlipTextureVertical();\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// raw buffer\r\n\r\nSSingleTexture::SSingleTexture(uint8* p_buffer, int width, int height, int bitdepth, int clut_bitdepth, int mipmaps,\r\n\t\t\t\t\t\t\t   bool sprite, bool alloc_vram, bool load_screen):\r\n\tm_flags(0),\r\n\tm_usage_count(0)\r\n{\r\n\t#ifdef\t\t\t__NOPT_ASSERT__\r\n\tstrcpy(m_name,\"texture from raw data\");\r\n\t#endif\r\n\r\n\tmp_TexBitBltBuf = mp_ClutBitBltBuf = NULL;\r\n\r\n\t// Set flags\r\n\tif (load_screen)\r\n\t{\r\n\t\tm_flags |= mLOAD_SCREEN;\r\n\t}\r\n\tif (sprite)\r\n\t{\r\n\t\tm_flags |= mSPRITE;\r\n\t}\r\n\tif ((sprite && alloc_vram) && !load_screen)\r\n\t{\r\n\t\tm_flags |= mALLOC_VRAM;\r\n\t}\r\n\r\n\t// open the font file\r\n\tif (!sprite)\r\n\t{\r\n\t\tDbg_Assert(!alloc_vram);\r\n\t}\r\n\t\r\n\tmp_PixelData = mp_ClutData = NULL;\r\n\tm_PixelDataSize = m_ClutDataSize = 0;\r\n\tmp_TexBuffer = NULL;\t\t// Since we aren't allocating any memory\r\n\tm_TexBufferSize = 0;\r\n\t\r\n\tm_checksum = 0;\r\n\tm_orig_width = width;\r\n\tm_orig_height = height;\r\n\r\n\t// Initialize all the data\r\n\t//InitTexture(false);\r\n\tuint32 TW, TH, PSM, CPSM, MXL;\r\n\r\n\tTW = TextureMemoryLayout::numBits(width - 1);\t\t// Rounds up to the nearest 2^N\r\n\tTH = TextureMemoryLayout::numBits(height - 1);\r\n\r\n\tPSM = bitdepth_to_psm(bitdepth);\r\n\tCPSM = bitdepth_to_psm(clut_bitdepth);\r\n\r\n\tMXL = mipmaps - 1;\r\n\r\n\t// Raw data is inverted vertically from the way we expect textures.\r\n\tm_flags |= mINVERTED;\r\n\r\n\tsetup_reg_and_dma(p_buffer, TW, TH, PSM, CPSM, MXL, false);\r\n\r\n\t// add texture to texture list\r\n\tif (sprite && !load_screen)\r\n\t{\r\n\t\tmp_next = sp_stexture_list;\r\n\t\tsp_stexture_list = this;\r\n\t}\r\n\r\n\tif (load_screen) {\r\n\t\tFlipTextureVertical();\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// copy constructor\r\n\r\nSSingleTexture::SSingleTexture(const SSingleTexture & src_texture)\r\n{\r\n\t// Copy checksum and flags\r\n\tm_checksum = src_texture.m_checksum;\r\n\tm_flags = src_texture.m_flags;\r\n\r\n\t#ifdef\t\t\t__NOPT_ASSERT__\r\n\tstrcpy(m_name,src_texture.m_name);\r\n\t#endif\r\n\r\n\t// Init some of the data before we call InitTexture()\r\n\tm_usage_count = 0;\r\n\tmp_TexBitBltBuf = mp_ClutBitBltBuf = NULL;\r\n\tmp_PixelData = mp_ClutData = NULL;\r\n\tm_PixelDataSize = m_ClutDataSize = 0;\r\n\r\n\t// Copy file buffer\r\n\tm_TexBufferSize = src_texture.m_TexBufferSize;\r\n\tif (m_TexBufferSize && src_texture.mp_TexBuffer)\r\n\t{\r\n\t\tmp_TexBuffer = (uint8 *)Mem::Malloc(m_TexBufferSize);\r\n\t\tmemcpy(mp_TexBuffer, src_texture.mp_TexBuffer, m_TexBufferSize);\r\n\r\n\t\t// This routine will initialize and allocate the rest\r\n\t\tInitTexture(true);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't copy SSingleTexture that was created with a raw buffer\"));\r\n\t\t//InitTexture(true);\r\n\t}\r\n\r\n\t// add texture to texture list\r\n\tif ((m_flags & mSPRITE) && !(m_flags & mLOAD_SCREEN))\r\n\t{\r\n\t\tmp_next = sp_stexture_list;\r\n\t\tsp_stexture_list = this;\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nSSingleTexture::~SSingleTexture()\r\n{\r\n\t// find texture and unchain from list\r\n\tif (sp_stexture_list == this)\r\n\t{\r\n\t\tsp_stexture_list = mp_next;\r\n\t} else if (sp_stexture_list) {\r\n\t\tSSingleTexture *p_texture = sp_stexture_list;\r\n\r\n\t\twhile(p_texture->mp_next)\r\n\t\t{\r\n\t\t\tif (p_texture->mp_next == this)\r\n\t\t\t{\r\n\t\t\t\tp_texture->mp_next = mp_next;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tp_texture = p_texture->mp_next;\r\n\t\t}\r\n\t}\r\n\r\n\t// free memory\r\n\tif (mp_VifData) Mem::Free(mp_VifData);\r\n\tif (mp_TexBuffer) Mem::Free(mp_TexBuffer);\r\n\r\n\tDbg_MsgAssert(m_usage_count == 0, (\"Trying to remove SSingleTexture %x that is still being used\", m_checksum));\r\n\r\n\t// and re-do VRAM allocation\r\n\tVRAMNeedsUpdating();\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n#define STEX_USE_CALL 1\r\n\r\nconst static uint32 TEXTURE_VERSION = 1;\r\n\r\nTextureMemoryLayout TexMemLayout;\r\n\r\nbool SSingleTexture::InitTexture(bool copy)\r\n{\r\n\tuint32 TW, TH, PSM, CPSM, MXL = 0;\r\n\r\n\tuint8 *pData = mp_TexBuffer;\r\n\r\n\tuint32 version;\r\n\tversion = *(uint32 *)pData, pData+=4;\r\n\tDbg_MsgAssert(version >= TEXTURE_VERSION, (\"Wrong version in .img file: %d. Game uses: %d\", version, TEXTURE_VERSION));\r\n\tm_checksum = *(uint32 *)pData, pData+=4;\r\n\r\n\t// get dimensions\r\n\tTW = *(uint32 *)pData, pData+=4;\r\n\tTH = *(uint32 *)pData, pData+=4;\r\n\r\n\t// get pixel storage modes\r\n\tPSM  = *(uint32 *)pData, pData+=4;\t// for texels\r\n\tCPSM = *(uint32 *)pData, pData+=4;\t// for clut\r\n\r\n\t// get maximum mipmap level\r\n\tif (version >= 2)\r\n\t{\r\n\t\tMXL  = *(uint32 *)pData, pData+=4;\r\n\t}\r\n\tDbg_Assert(MXL == 0);\r\n\tm_orig_width = *(uint16 *)pData, pData+=2;\r\n\tm_orig_height = *(uint16 *)pData, pData+=2;\r\n\r\n\t// bail if it's a non-texture\r\n\tDbg_MsgAssert((TW != 0xFFFFFFFF), (\"No texture in .img file\\n\"));\r\n\r\n\t// quadword-align\r\n\tpData = (uint8 *)(((uint)(pData+15)) & 0xFFFFFFF0);\r\n\r\n\treturn setup_reg_and_dma(pData, TW, TH, PSM, CPSM, MXL, copy);\r\n}\r\n\r\nbool SSingleTexture::setup_reg_and_dma(uint8 *pData, uint32 TW, uint32 TH, uint32 PSM, uint32 CPSM, uint32 MXL, bool copy)\r\n{\r\n\tuint TBW;\r\n\tuint Width, Height, NumTexBytes, NumTexQWords, NumClutBytes, NumClutQWords, NumVramBytes;\r\n\tuint BitsPerTexel, BitsPerClutEntry, PaletteSize;\r\n\tuint NextTBP;\r\n\tint j,k;\r\n\r\n\tuint8 *old_dma_loc = dma::pLoc;\t\t  \r\n\r\n\t// initialise base pointers\r\n\tif (IsInVRAM())\r\n\t{\r\n\t\tNextTBP = FontVramBase;\r\n\t} else {\r\n\t\tNextTBP = FontVramStart;\r\n\t}\r\n\r\n\t// bits per texel and palette size\r\n\tswitch (PSM)\r\n\t{\r\n\tcase PSMCT32:\r\n\t\tBitsPerTexel = 32;\r\n\t\tPaletteSize  = 0;\r\n\t\tbreak;\r\n\tcase PSMCT24:\r\n\t\tBitsPerTexel = 24;\r\n\t\tPaletteSize  = 0;\r\n\t\tbreak;\r\n\tcase PSMCT16:\r\n\t\tBitsPerTexel = 16;\r\n\t\tPaletteSize  = 0;\r\n\t\tbreak;\r\n\tcase PSMT8:\r\n\t\tBitsPerTexel = 8;\r\n\t\tPaletteSize  = 256;\r\n\t\tbreak;\r\n\tcase PSMT4:\r\n\t\tBitsPerTexel = 4;\r\n\t\tPaletteSize  = 16;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tprintf(\"Unknown PSM %d in texture file\\n\", PSM);\r\n\t\texit(1);\r\n\t}\r\n\r\n\t// bits per clut entry\r\n\tif (BitsPerTexel < 16)\r\n\t\tswitch (CPSM)\r\n\t\t{\r\n\t\tcase PSMCT32:\r\n\t\t\tBitsPerClutEntry = 32;\r\n\t\t\tbreak;\r\n\t\tcase PSMCT16:\r\n\t\t\tBitsPerClutEntry = 16;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tprintf(\"Unknown CPSM %d in texture file\\n\", PSM);\r\n\t\t\texit(1);\r\n\t\t}\r\n\telse\r\n\t\tBitsPerClutEntry = 0;\r\n\r\n\t// rearrange 256-colour cluts according to requirements of CSM1\r\n\tif (!copy && PSM==PSMT8)\r\n\t{\r\n\t\tuint32 temp32;\r\n\t\tuint16 temp16;\r\n\t\tfor (j=0; j<256; j+=32)\r\n\t\t\tfor (k=0; k<8; k++)\r\n\t\t\t\tif (CPSM==PSMCT32)\r\n\t\t\t\t{\r\n\t\t\t\t\ttemp32 = ((uint32 *)pData)[j+k+8];\r\n\t\t\t\t\t((uint32 *)pData)[j+k+8] = ((uint32 *)pData)[j+k+16];\r\n\t\t\t\t\t((uint32 *)pData)[j+k+16] = temp32;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\ttemp16 = ((uint16 *)pData)[j+k+8];\r\n\t\t\t\t\t((uint16 *)pData)[j+k+8] = ((uint16 *)pData)[j+k+16];\r\n\t\t\t\t\t((uint16 *)pData)[j+k+16] = temp16;\r\n\t\t\t\t}\r\n\t}\r\n\r\n\t// calculate texture dimensions\r\n\tWidth = (TW>=0 ? 1<<TW : 0);\r\n\tHeight = (TH>=0 ? 1<<TH : 0);\r\n\tTBW = (Width+63) >> 6;\r\n\tif (BitsPerTexel<16 && TBW<2)\r\n\t\tTBW = 2;\r\n\r\n\t// Calculate memory needed\r\n\tint min_width = Width, min_height = Height;\r\n\tTexMemLayout.getMinSize(min_width, min_height, PSM);\r\n\tm_NumTexVramBlocks = TexMemLayout.getImageSize(min_width, min_height, PSM);\r\n\tNumVramBytes = m_NumTexVramBlocks * 256;\r\n\t//NumVramBytes = (TBW << 6) * Height * BitsPerTexel >> 3;\r\n\r\n\t// calculate sizes within file\r\n\tNumClutBytes  = PaletteSize * BitsPerClutEntry >> 3;\r\n\tNumClutQWords = NumClutBytes >> 4;\r\n\tNumTexBytes  = Width * Height * BitsPerTexel >> 3;\r\n\tNumTexQWords = NumTexBytes >> 4;\r\n\r\n\t//Dbg_Message(\"Texture size (%d, %d) of bitdepth %d and BufferWidth %d\", Width, Height, BitsPerTexel, TBW);\r\n\t//Dbg_MsgAssert(calcVramBytes <= NumVramBytes, (\"Need more memory: %d vs. needed %d\", NumVramBytes, calcVramBytes));\r\n\r\n\t// allocate memory for vif stream\r\n#if STEX_USE_CALL\r\n\tm_VifSize = 272;\r\n#else\r\n\tm_VifSize = 1024 + NumClutBytes + NumTexBytes; //256; //1216 + (((Width*Height+15)>>4)<<4);\r\n#endif // STEX_USE_CALL\r\n\tmp_VifData = (uint8 *)Mem::Malloc(m_VifSize);\r\n\tDbg_MsgAssert(mp_VifData, (\"couldn't malloc memory for vif data\"));\r\n\tDbg_MsgAssert(((uint32)mp_VifData & 15) == 0, (\"vif data not qword aligned\"));\r\n\r\n\t// build dma data in this buffer\r\n\tdma::pLoc = mp_VifData;\r\n\r\n\t// calculate TBP\r\n\tm_TBP = NextTBP;\r\n\r\n\t// calculate next TBP\r\n\t//NextTBP = (((TBP<<8)+NumVramBytes+0x1FFF) & 0xFFFFE000) >> 8;\r\n\tNextTBP = m_TBP + m_NumTexVramBlocks;\r\n\r\n\t// calculate CBP\r\n\tm_CBP = NextTBP;\r\n\tif (BitsPerTexel >= 16)\r\n\t\tm_NumClutVramBlocks = 0;\r\n\telse if (BitsPerTexel == 4)\r\n\t\tm_NumClutVramBlocks = 4;\r\n\telse\r\n\t\tm_NumClutVramBlocks = (CPSM==PSMCT32 ? 4 : 4);\r\n\r\n\tNextTBP += m_NumClutVramBlocks;\r\n\r\n\tif (IsInVRAM() && Script::GetInt( \"vram_debug\", false ))\r\n\t{\r\n\t\tDbg_Message(\"VRAM Used = %d blocks, texture Size = %d blocks, blocks left = %d out of %d\", \r\n\t\t\t\tNextTBP - FontVramStart, m_NumTexVramBlocks + m_NumClutVramBlocks, FontVramSize - (NextTBP - FontVramStart),FontVramSize);  \t\t\t\t\t\t\t\t\t\t\r\n\t}\r\n\t\t\t\t\t\t\t  \r\n\t// bail if VRAM would become over-packed\r\n\tif (IsInVRAM() && (NextTBP > (FontVramStart + FontVramSize)))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"SingleTexture: 2D VRAM Buffer Full: %x.\", NextTBP));\r\n\t\t//pData += NumClutBytes;\r\n\t\t//pData = (uint8 *)(((uint)(pData+NumTexBytes+15)) & 0xFFFFFFF0);\r\n\t\t// And restore the CurrentDMALoc, which we were just using temporarily.\r\n\t\tdma::pLoc = old_dma_loc;\t\t  \r\n\t\treturn false;\r\n\t}\r\n\r\n\t// add clut upload to dma list if necessary\r\n\tif (BitsPerTexel < 16)\r\n\t{\r\n#if STEX_USE_CALL\r\n\t\tdma::BeginTag(dma::cnt,0);\r\n\t\tvif::NOP();\r\n\t\tvif::DIRECT(6);\r\n\t\tgif::Tag2(gs::A_D,1,PACKED,0,0,0,4);\r\n\t\tmp_ClutBitBltBuf = gs::Reg2_pData(gs::BITBLTBUF,PackBITBLTBUF(0,0,0,m_CBP,1,CPSM));\r\n\t\tgs::Reg2(gs::TRXPOS,\tPackTRXPOS(0,0,0,0,0));\r\n\t\tif (PSM==PSMT4)\r\n\t\t\tgs::Reg2(gs::TRXREG,PackTRXREG(8,2));\r\n\t\telse\r\n\t\t\tgs::Reg2(gs::TRXREG,PackTRXREG(16,16));\r\n\t\tgs::Reg2(gs::TRXDIR,\t0);\r\n\t\tgif::Tag2(0,0,IMAGE,0,0,0,NumClutQWords);\r\n\t\tdma::EndTag();\r\n\t\tdma::Tag(dma::ref, NumClutQWords, (uint)pData);\r\n\t\tvif::NOP();\r\n\t\tvif::DIRECT(NumClutQWords);\r\n#else\r\n\t\t// clut upload header\r\n\t\tgif::Tag2(gs::A_D,1,PACKED,0,0,0,4);\r\n\t\tmp_ClutBitBltBuf = gs::Reg2_pData(gs::BITBLTBUF,PackBITBLTBUF(0,0,0,m_CBP,1,CPSM));\r\n\t\tgs::Reg2(gs::TRXPOS,\tPackTRXPOS(0,0,0,0,0));\r\n\t\tif (PSM==PSMT4)\r\n\t\t\tgs::Reg2(gs::TRXREG,PackTRXREG(8,2));\r\n\t\telse\r\n\t\t\tgs::Reg2(gs::TRXREG,PackTRXREG(16,16));\r\n\t\tgs::Reg2(gs::TRXDIR,\t0);\r\n\t\tgif::Tag2(0,0,IMAGE,0,0,0,NumClutQWords);\r\n\r\n\t\t// read clut bitmap data\r\n\t\tmemcpy(dma::pLoc, pData, NumClutBytes);\r\n\r\n\t\t// step dma location\r\n\t\tdma::pLoc += NumClutBytes;\r\n#endif // STEX_USE_CALL\r\n\r\n\t\t// Save pointer\r\n\t\tmp_ClutData = pData;\r\n\t\tm_ClutDataSize = NumClutBytes;\r\n\r\n\t\t// step past clut data, and quadword-align\r\n\t\tpData = (uint8 *)(((uint)(pData+NumClutBytes+15)) & 0xFFFFFFF0);\r\n\t}\r\n\r\n#if STEX_USE_CALL\r\n\t// add texture upload to dma list\r\n\tdma::BeginTag(dma::cnt,0);\r\n\tvif::NOP();\r\n\tvif::DIRECT(6);\r\n\tgif::Tag2(gs::A_D,1,PACKED,0,0,0,4);\r\n\tmp_TexBitBltBuf = gs::Reg2_pData(gs::BITBLTBUF,PackBITBLTBUF(0,0,0,m_TBP,TBW,PSM));\r\n\tgs::Reg2(gs::TRXPOS,\tPackTRXPOS(0,0,0,0,0));\r\n\tgs::Reg2(gs::TRXREG,\tPackTRXREG(Width,Height));\r\n\tgs::Reg2(gs::TRXDIR,\t0);\r\n\tgif::Tag2(0, 0, IMAGE, 0, 0, 0, NumTexQWords);\r\n\tdma::EndTag();\r\n\tdma::Tag(dma::ref, NumTexQWords, (uint)pData);\r\n\tvif::NOP();\r\n\tvif::DIRECT(NumTexQWords);\r\n#else\r\n\t// texture upload header\r\n\tgif::Tag2(gs::A_D,1,PACKED,0,0,0,4);\r\n\tmp_TexBitBltBuf = gs::Reg2_pData(gs::BITBLTBUF,PackBITBLTBUF(0,0,0,m_TBP,TBW,PSM));\r\n\tgs::Reg2(gs::TRXPOS,\tPackTRXPOS(0,0,0,0,0));\r\n\tgs::Reg2(gs::TRXREG,\tPackTRXREG(Width,Height));\r\n\tgs::Reg2(gs::TRXDIR,\t0);\r\n\tgif::Tag2(0, 0, IMAGE, 0, 0, 0, NumTexQWords);\r\n\r\n\t// read texture bitmap data\r\n\tmemcpy(dma::pLoc, pData, NumTexBytes);\r\n\tdma::pLoc += NumTexQWords<<4;\r\n#endif // STEX_USE_CALL\r\n\r\n\t// Handle mipmaps, if any (but don't make any DMA packets for them)\r\n\tif (!(m_flags & mSPRITE) && (MXL > 0))\r\n\t{\r\n\t\tfor (j = 1; j < (int) MXL; j++)\r\n\t\t{\r\n\t\t\tint mip_width = (TW>=0 ? 1<<TW : 0) >> j;\r\n\t\t\tint mip_height = (TH>=0 ? 1<<TH : 0) >> j;\r\n\r\n\t\t\t// Add in mip sizes\r\n\t\t\tNumTexBytes += mip_width * mip_height * BitsPerTexel >> 3;\r\n\t\t}\r\n\t}\r\n\r\n\t// Save pointer\r\n\tmp_PixelData = pData;\r\n\tm_PixelDataSize = NumTexBytes;\r\n\r\n\t// make entry in texture table\r\n\tm_RegTEX0    = PackTEX0(m_TBP,TBW,PSM,TW,TH,1,MODULATE,m_CBP,CPSM,0,0,1);\r\n\tm_RegTEX1\t = PackTEX1(1,0,LINEAR,LINEAR,0,0,0);\r\n\r\n\t// update vram base pointer\r\n\tif (IsInVRAM())\r\n\t{\r\n\t\tFontVramBase = NextTBP;\r\n\t}\r\n\r\n#if STEX_USE_CALL\r\n\t// Since this data is called, do a return\r\n\tdma::Tag(dma::ret, 0, 0);\r\n\tvif::NOP();\r\n\tvif::NOP();\r\n#endif // STEX_USE_CALL\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tuint ActualSize = (uint) dma::pLoc - (uint) mp_VifData;\r\n\tDbg_MsgAssert(ActualSize <= m_VifSize, (\"Did not allocate enough DMA space for textures: allocated=%d actual=%d\", m_VifSize, ActualSize));\r\n\t//Dbg_Message(\"Texture packet size = %d\", (int) dma::pLoc - (int) pVifData);\r\n\t#endif\r\n\r\n\t// And restore the CurrentDMALoc, which we were just using temporarily.\r\n\tdma::pLoc = old_dma_loc;\t\t  \r\n\r\n\treturn true;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// Need to do this to textures that are copied directly into the frame buffer\r\n//\r\n\r\nvoid\tSSingleTexture::FlipTextureVertical()\r\n{\r\n\tint startrow = 0;\r\n\tint endrow = m_orig_height - 1;\r\n\tint rowsize = (m_orig_width * GetBitdepth()) / 8;\r\n\r\n\tuint8 *p_temp_buffer = new uint8[rowsize];\r\n\twhile (startrow < endrow)\r\n\t{\r\n\t\t// Swap rows\r\n\t\tmemcpy(p_temp_buffer,\t\t\t\t\t\t&(mp_PixelData[startrow * rowsize]),rowsize);\r\n\t\tmemcpy(&(mp_PixelData[startrow * rowsize]),\t&(mp_PixelData[endrow * rowsize]),\trowsize);\r\n\t\tmemcpy(&(mp_PixelData[endrow * rowsize]),\tp_temp_buffer,\t\t\t\t\t\trowsize);\r\n\r\n\t\tstartrow++;\r\n\t\tendrow--;\r\n\t}\r\n\r\n\tdelete p_temp_buffer;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\nbool SSingleTexture::AddToVRAM()\r\n{\r\n\tDbg_MsgAssert(!(m_flags & mAUTO_ALLOC), (\"Can't use AddToVRAM() on a auto allocated texture\"));\r\n\r\n\t#ifdef\t\t\t__NOPT_ASSERT__\r\n//\tprintf (\"++++ Adding %s ++++\\n\",m_name);\r\n\t#endif \r\n\tm_flags |= mALLOC_VRAM;\r\n\r\n\tVRAMNeedsUpdating();\r\n\r\n\treturn true;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\nbool SSingleTexture::RemoveFromVRAM()\r\n{\r\n\tDbg_MsgAssert(!(m_flags & mAUTO_ALLOC), (\"Can't use RemoveFromVRAM() on a auto allocated texture\"));\r\n\r\n\t#ifdef\t\t\t__NOPT_ASSERT__\r\n//\tprintf (\"---- removing %s ----\\n\",m_name);\r\n\t#endif \r\n\tm_flags &= ~mALLOC_VRAM;\r\n\r\n\tVRAMNeedsUpdating();\r\n\r\n\treturn true;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SSingleTexture::SetAutoAllocate()\r\n{\r\n\tm_flags |= mAUTO_ALLOC;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SSingleTexture::inc_usage_count()\r\n{\r\n\tm_usage_count++;\r\n\tm_flags |= mALLOC_VRAM;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SSingleTexture::dec_usage_count()\r\n{\r\n\tif (--m_usage_count == 0)\r\n\t{\r\n\t\tm_flags &= ~mALLOC_VRAM;\r\n\t}\r\n\r\n\tDbg_MsgAssert(m_usage_count >= 0, (\"Usage Count negative on  SSingleTexture %x\", m_checksum));\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SSingleTexture::UseTexture(bool use)\r\n{\r\n\tDbg_MsgAssert(m_flags & mAUTO_ALLOC, (\"Can't use UseTexture() on a non-auto allocated texture\"));\r\n\r\n\tbool old_alloc = IsInVRAM();\r\n\r\n\t// Update usage\r\n\tif (use)\r\n\t{\r\n\t\tinc_usage_count();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tdec_usage_count();\r\n\t}\r\n\r\n\t// See if we need to update DMA\r\n\tif (old_alloc != use)\r\n\t{\r\n\t\tVRAMNeedsUpdating();\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nuint16\tSSingleTexture::GetOrigWidth() const\r\n{\r\n\treturn m_orig_width;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nuint16\tSSingleTexture::GetOrigHeight() const\r\n{\r\n\treturn m_orig_height;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid\tSSingleTexture::ReallocateVRAM()\r\n{\r\n\t// Don't realloc load screens\r\n\tif (!IsInVRAM()) return;\r\n\r\n\t// calculate TBP\r\n\tm_TBP = FontVramBase;\r\n\tFontVramBase += m_NumTexVramBlocks;\r\n\r\n\t// calculate CBP\r\n\tm_CBP = FontVramBase;\r\n\tFontVramBase += m_NumClutVramBlocks;\r\n\r\n\t// bail if VRAM would become over-packed\r\n\tif (FontVramBase > (FontVramStart + FontVramSize))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"SingleTexture Realloc: 2D VRAM Buffer Full: %x.\", FontVramBase));\r\n\t}\r\n\r\n\t// Modify the data\r\n\tgs::ModifyTBP(gs::TEX0_1, (uint32 *) &m_RegTEX0, m_TBP, m_CBP);\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid\tSSingleTexture::UpdateDMA()\r\n{\r\n\t// Modify the packets\r\n\tgs::ModifyTBP(gs::BITBLTBUF, mp_TexBitBltBuf, m_TBP);\r\n\tif (mp_ClutBitBltBuf)\r\n\t{\r\n\t\tgs::ModifyTBP(gs::BITBLTBUF, mp_ClutBitBltBuf, m_CBP);\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// The following Get() calls are very inefficient.  They should only be\r\n// used when necessary (i.e. initialization).\r\n//\r\nuint16\tSSingleTexture::GetWidth() const\r\n{\r\n\tsceGsTex0 tex0 = *((sceGsTex0 *) &m_RegTEX0);\r\n\tuint16 TW = tex0.TW;\r\n\t//uint16 TW = (uint16) ((RegTEX0 >> 26) & M04);\r\n\r\n\treturn 1 << TW;\r\n}\r\n\r\nuint16\tSSingleTexture::GetHeight() const\r\n{\r\n\tsceGsTex0 tex0 = *((sceGsTex0 *) &m_RegTEX0);\r\n\tuint16 TH = tex0.TH;\r\n\t//uint16 TH = (uint16) ((RegTEX0 >> 30) & M04);\r\n\r\n\treturn 1 << TH;\r\n}\r\n\r\nuint8\tSSingleTexture::GetBitdepth() const\r\n{\r\n\tsceGsTex0 tex0 = *((sceGsTex0 *) &m_RegTEX0);\r\n\tuint PSM = tex0.PSM;\r\n\r\n\tswitch (PSM)\r\n\t{\r\n\tcase PSMCT32:\r\n\t\treturn 32;\r\n\t\tbreak;\r\n\tcase PSMCT24:\r\n\t\treturn 24;\r\n\t\tbreak;\r\n\tcase PSMCT16:\r\n\t\treturn 16;\r\n\t\tbreak;\r\n\tcase PSMT8:\r\n\t\treturn 8;\r\n\t\tbreak;\r\n\tcase PSMT4:\r\n\t\treturn 4;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\nuint8\tSSingleTexture::GetClutBitdepth() const\r\n{\r\n\tsceGsTex0 tex0 = *((sceGsTex0 *) &m_RegTEX0);\r\n\tuint CPSM = tex0.CPSM;\r\n\r\n\tswitch (CPSM)\r\n\t{\r\n\tcase PSMCT32:\r\n\t\treturn 32;\r\n\t\tbreak;\r\n\tcase PSMCT24:\r\n\t\treturn 24;\r\n\t\tbreak;\r\n\tcase PSMCT16:\r\n\t\treturn 16;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\nuint8\tSSingleTexture::GetNumMipmaps() const\r\n{\r\n\treturn 1;\t\t// By definition for this class\r\n}\r\n\r\nbool\tSSingleTexture::IsTransparent() const\r\n{\r\n\t//Dbg_Error(\"Not working yet\");\r\n\treturn false;\r\n}\r\n\r\nuint32\tSSingleTexture::bitdepth_to_psm(int bitdepth)\r\n{\r\n\tswitch (bitdepth)\r\n\t{\r\n\tcase 32:\r\n\t\treturn PSMCT32;\r\n\t\tbreak;\r\n\tcase 24:\r\n\t\treturn PSMCT24;\r\n\t\tbreak;\r\n\tcase 16:\r\n\t\treturn PSMCT16;\r\n\t\tbreak;\r\n\tcase 8:\r\n\t\treturn PSMT8;\r\n\t\tbreak;\r\n\tcase 4:\r\n\t\treturn PSMT4;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0, (\"Bitdepth %d is not supported on PS2\", bitdepth));\r\n\t\treturn PSMCT32;\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n#ifdef\t\t\t__NOPT_ASSERT__\r\nvoid\tSSingleTexture::sPrintAllTextureInfo()\r\n{\r\n\tfor (SSingleTexture *pTexture=SSingleTexture::sp_stexture_list; pTexture; pTexture=pTexture->mp_next)\r\n\t{\r\n\t\tDbg_Message(\"Texture name %s: using vram: %d, blocks %d\", pTexture->m_name, pTexture->IsInVRAM(),\r\n\t\t\t\t\tpTexture->m_NumTexVramBlocks + pTexture->m_NumClutVramBlocks);\r\n\t}\r\n}\r\n\r\nvoid\tSSingleTexture::sPrintAllocatedTextureInfo()\r\n{\r\n\tfor (SSingleTexture *pTexture=SSingleTexture::sp_stexture_list; pTexture; pTexture=pTexture->mp_next)\r\n\t{\r\n\t\tif (!pTexture->IsInVRAM())\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tDbg_Message(\"Texture name %s: using vram: <true>, blocks %d\", pTexture->m_name,\r\n\t\t\t\t\tpTexture->m_NumTexVramBlocks + pTexture->m_NumClutVramBlocks);\r\n\t}\r\n}\r\n\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* SScissorWindow\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSScissorWindow DefaultScissorWindow;\r\n\r\nvoid SetTextWindow(uint16 x0, uint16 x1, uint16 y0, uint16 y1)\r\n{\r\n\tDefaultScissorWindow.SetScissor(x0, y0, x1, y1);\r\n}\r\n\r\nvoid SScissorWindow::SetScissor(uint16 x0, uint16 y0, uint16 x1, uint16 y1)\r\n{\r\n\tm_RegSCISSOR = (uint64)x0 | (uint64)x1<<16 | (uint64)y0<<32 | (uint64)y1<<48;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* SDraw2D\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\tSDraw2D::s_screen_scale_x = 1.0f;\r\nfloat\t\tSDraw2D::s_screen_scale_y = 1.0f;\r\n\r\nbool\t\tSDraw2D::s_constant_z_enabled = false;\r\nuint32\t\tSDraw2D::s_constant_z = 0x7FFFFF;\r\n\r\nSDraw2D *\tSDraw2D::sp_2D_sorted_draw_list = NULL;\r\nSDraw2D *\tSDraw2D::sp_2D_zbuffer_draw_list = NULL;\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nSDraw2D::SDraw2D(float pri, bool hide) :\r\n\tm_hidden(hide),\r\n\tm_use_zbuffer(false),\r\n\tm_pri(pri),\r\n\tm_z(0xFFFFFF),\r\n\tmp_scissor_window(&DefaultScissorWindow)\r\n{\r\n\tmp_next = NULL;\r\n\r\n\t// add to sorted draw list\r\n\tif (!m_hidden)\r\n\t{\r\n\t\tInsertSortedDrawList(&sp_2D_sorted_draw_list);\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nSDraw2D::~SDraw2D()\r\n{\r\n\t// Try removing from draw list\r\n\tif (m_use_zbuffer)\r\n\t{\r\n\t\tRemoveDrawList(&sp_2D_zbuffer_draw_list);\r\n\t} else {\r\n\t\tRemoveDrawList(&sp_2D_sorted_draw_list);\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SDraw2D::SetPriority(float pri)\r\n{\r\n\tif (m_pri != pri)\r\n\t{\r\n\t\tm_pri = pri;\r\n\r\n\t\t// By removing and re-inserting, we re-sort the list\r\n\t\tif (!m_hidden)\r\n\t\t{\r\n\t\t\tif (m_use_zbuffer)\r\n\t\t\t{\r\n\t\t\t\tRemoveDrawList(&sp_2D_zbuffer_draw_list);\r\n\t\t\t} else {\r\n\t\t\t\tRemoveDrawList(&sp_2D_sorted_draw_list);\r\n\t\t\t}\r\n\t\t\tInsertSortedDrawList(&sp_2D_sorted_draw_list);\r\n\t\t}\r\n\r\n\t\tm_use_zbuffer = false;\r\n\t\tm_z = 0xFFFFFF;\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SDraw2D::SetZValue(uint32 z)\r\n{\r\n\tif (m_z != z)\r\n\t{\r\n\t\tm_z = z;\r\n\r\n\t\t// Switch lists, if necessary\r\n\t\tif (!m_use_zbuffer && !m_hidden)\r\n\t\t{\r\n\t\t\tRemoveDrawList(&sp_2D_sorted_draw_list);\r\n\t\t\tInsertDrawList(&sp_2D_zbuffer_draw_list);\r\n\t\t}\r\n\r\n\t\tm_use_zbuffer = true;\r\n\t\tm_pri = 0.0f;\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SDraw2D::SetHidden(bool hide)\r\n{\r\n\tif (m_hidden != hide)\r\n\t{\r\n\t\tm_hidden = hide;\r\n\t\tif (m_use_zbuffer)\r\n\t\t{\r\n\t\t\tif (hide)\r\n\t\t\t{\r\n\t\t\t\tRemoveDrawList(&sp_2D_zbuffer_draw_list);\r\n\t\t\t} else {\r\n\t\t\t\tInsertDrawList(&sp_2D_zbuffer_draw_list);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (hide)\r\n\t\t\t{\r\n\t\t\t\tRemoveDrawList(&sp_2D_sorted_draw_list);\r\n\t\t\t} else {\r\n\t\t\t\tInsertSortedDrawList(&sp_2D_sorted_draw_list);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SDraw2D::SetScissorWindow(SScissorWindow *p_scissor)\r\n{\r\n\tif (p_scissor)\r\n\t{\r\n\t\tmp_scissor_window = p_scissor;\r\n\t} else {\r\n\t\tmp_scissor_window = &DefaultScissorWindow;\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SDraw2D::DrawAll()\r\n{\r\n\t// Figure out screen scale (for PAL mode)\r\n\tCalcScreenScale();\r\n\r\n\t// Init certain GS registers for 2D drawing\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tgs::BeginPrim(ABS,0,0);\r\n\tgs::Reg1(gs::CLAMP_1,PackCLAMP(CLAMP,CLAMP,0,0,0,0));\t\t// Man, I hope this is the last time I fix the CLAMP bug\r\n\tgs::Reg1(gs::XYOFFSET_1, PackXYOFFSET(XOFFSET, YOFFSET));\r\n\tgs::Reg1(gs::TEST_1, PackTEST(1,AGREATER,0,KEEP,0,0,1,ZGEQUAL));\r\n\tgs::EndPrim(0);\r\n\tdma::EndTag();\r\n\r\n\t// Draw items needing ZBuffer first\r\n\tDrawList(sp_2D_zbuffer_draw_list);\r\n\tif (s_constant_z_enabled)\r\n\t{\r\n\t\tDrawList(sp_2D_sorted_draw_list);\r\n\t}\r\n\r\n\t// Turn off ZBuffer\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\tgs::BeginPrim(ABS,0,0);\r\n\tgs::Reg1(gs::TEST_1, PackTEST(0,0,0,0,0,0,1,ZGEQUAL));\r\n\tgs::EndPrim(0);\r\n\tdma::EndTag();\r\n\r\n\t// Draw the sorted list now if we aren't using constant Z\r\n\tif (!s_constant_z_enabled)\r\n\t{\r\n\t\tDrawList(sp_2D_sorted_draw_list);\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SDraw2D::DrawList(SDraw2D *pDraw)\r\n{\r\n\twhile (pDraw)\r\n\t{\r\n\t\tif (!pDraw->m_hidden)\r\n\t\t{\r\n\t\t\tpDraw->BeginDraw();\r\n\t\t\tpDraw->Draw();\r\n\t\t\tpDraw->EndDraw();\r\n\t\t}\r\n\t\tpDraw = pDraw->mp_next;\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SDraw2D::EnableConstantZValue(bool enable)\r\n{\r\n\ts_constant_z_enabled = enable;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SDraw2D::SetConstantZValue(uint32 z)\r\n{\r\n\ts_constant_z = z;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nuint32 SDraw2D::GetConstantZValue()\r\n{\r\n\treturn s_constant_z;\r\n}\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// Figure out screen scale (mainly for PAL mode)\r\n//\r\n\r\nvoid SDraw2D::CalcScreenScale()\r\n{\r\n\tif (Config::NTSC())\r\n\t{\r\n\t\ts_screen_scale_x = 1.0f;\r\n\t\ts_screen_scale_y = 1.0f;\r\n\t} else {\r\n\t\ts_screen_scale_x = ((float) HRES_PAL) / ((float) HRES_NTSC);\r\n\t\ts_screen_scale_y = ((float) VRES_PAL) / ((float) VRES_NTSC);\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SDraw2D::InsertSortedDrawList(SDraw2D **p_list)\r\n{\r\n\tDbg_Assert(!m_use_zbuffer);\r\n\r\n\tif (!*p_list ||\t\t\t\t\t\t\t// Empty List\r\n\t\t(m_pri <= (*p_list)->m_pri))\t\t// Start List\r\n\t{\r\n\t\tmp_next = *p_list;\r\n\t\t*p_list = this;\r\n\t} else {\t\t\t\t// Insert\r\n\t\tSDraw2D *p_cur = *p_list;\r\n\t\r\n\t\t// Find where to insert\r\n\t\twhile(p_cur->mp_next)\r\n\t\t{\r\n\t\t\tif (m_pri <= p_cur->mp_next->m_pri)\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tp_cur = p_cur->mp_next;\r\n\t\t}\r\n\r\n\t\t// Insert at this point\r\n\t\tmp_next = p_cur->mp_next;\r\n\t\tp_cur->mp_next = this;\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SDraw2D::InsertDrawList(SDraw2D **p_list)\r\n{\r\n\tif (!*p_list)\t\t\t\t\t\t\t// Empty List\r\n\t{\r\n\t\tmp_next = *p_list;\r\n\t\t*p_list = this;\r\n\t} else {\t\t\t\t\t\t\t\t// Insert at end of list\r\n\t\tSDraw2D *p_cur = *p_list;\r\n\r\n\t\twhile(p_cur->mp_next)\r\n\t\t{\r\n\t\t\tp_cur = p_cur->mp_next;\r\n\t\t}\r\n\r\n\t\tmp_next = p_cur->mp_next;\r\n\t\tp_cur->mp_next = this;\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SDraw2D::RemoveDrawList(SDraw2D **p_list)\r\n{\r\n\t// Take out from draw list\r\n\tif (*p_list == this)\r\n\t{\r\n\t\t*p_list = mp_next;\r\n\t} \r\n\telse if (*p_list) \r\n\t{\r\n\t\tSDraw2D *p_cur = *p_list;\r\n\r\n\t\twhile(p_cur->mp_next)\r\n\t\t{\r\n\t\t\tif (p_cur->mp_next == this)\r\n\t\t\t{\r\n\t\t\t\tp_cur->mp_next = mp_next;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tp_cur = p_cur->mp_next;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* SSprite\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nSSprite::SSprite(float pri) : SDraw2D(pri, true)\r\n{\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nSSprite::~SSprite()\r\n{\r\n\t// Deallocates the underlying texture, if there was one\r\n\tSetHidden(true);\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SSprite::SetHidden(bool hide)\r\n{\r\n\tbool old_hide = IsHidden();\r\n\r\n\t// Do the actual hide call\r\n\tSDraw2D::SetHidden(hide);\r\n\r\n\t// Make sure vram status is correct if we changed hidden states\r\n\tif (mp_texture && (old_hide != hide))\r\n\t{\r\n\t\tmp_texture->UseTexture(!hide);\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SSprite::SetTexture(SSingleTexture *p_texture)\r\n{\r\n\t// Set auto VRAM allocate\r\n\tif (p_texture && (mp_texture != p_texture))\r\n\t{\r\n\t\tp_texture->SetAutoAllocate();\r\n\r\n\t\t// Change usage counts if we aren't hidden\r\n\t\tif (!IsHidden())\r\n\t\t{\r\n\t\t\tp_texture->UseTexture(true);\r\n\t\t\tif (mp_texture)\r\n\t\t\t{\r\n\t\t\t\tmp_texture->UseTexture(false);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tmp_texture = p_texture;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SSprite::BeginDraw()\r\n{\r\n\r\n\t// dma tag\r\n\tdma::BeginTag(dma::cnt, 0);\r\n\r\n\tvu1::Buffer = vu1::Loc;\r\n\r\n\tint tme_flag = (mp_texture) ? TME : 0;\r\n\r\n\tDbg_Assert(GetScissorWindow());\r\n\r\n\t// GS context\r\n\tgs::BeginPrim(ABS,0,0);\r\n\tgs::Reg1(gs::SCISSOR_1, GetScissorWindow()->GetScissorReg());\r\n\tif (mp_texture)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_texture->IsInVRAM(), (\"Can't draw sprite when its texture 0x%x, (%s) is not in VRAM.\",mp_texture->m_checksum,mp_texture->m_name));\r\n\r\n\t\tgs::Reg1(gs::TEX0_1,\t mp_texture->m_RegTEX0);\r\n\t\tgs::Reg1(gs::TEX1_1,\t mp_texture->m_RegTEX1);\r\n\t}\r\n\tgs::Reg1(gs::ALPHA_1,\t PackALPHA(0,1,0,1,0));\r\n\tgs::Reg1(gs::COLCLAMP,\t PackCOLCLAMP(1));\r\n\tgs::Reg1(gs::RGBAQ,\t (uint64)m_rgba);\r\n\tgs::EndPrim(0);\r\n\r\n\t// unpack giftag\r\n\tvif::UNPACK(0, V4_32, 1, ABS, UNSIGNED, 0);\r\n\tif (m_rot == 0.0f)\r\n\t{\r\n\t\tgif::BeginTagImmediate(gs::UV|gs::XYZ2<<4, 2, PACKED, SPRITE|tme_flag|FST|ABE, 1, VU1_ADDR(GSPrim));\r\n\t} else {\r\n\t\tgif::BeginTagImmediate(gs::UV|gs::XYZ2<<4, 2, PACKED, TRISTRIP|tme_flag|FST|ABE, 1, VU1_ADDR(GSPrim));\r\n\t}\r\n\r\n\t// begin unpack for uv/xyz's\r\n\tvif::BeginUNPACK(0, V4_32, ABS, SIGNED, 1);\r\n}\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SSprite::Draw()\r\n{\r\n\tDbg_Assert(GetScissorWindow());\r\n\r\n\tconst int start_screen_x = XOFFSET + ((GetScissorWindow()->GetScissorReg() & 0x7FF) << 4) + ((int) (m_xpos * s_screen_scale_x * 16.0f));\r\n\tconst int start_screen_y = YOFFSET + ((GetScissorWindow()->GetScissorReg() >> 32 & 0x7FF) << 4) + ((int) (m_ypos * s_screen_scale_y * 16.0f));\r\n\r\n\tuint16 u0,v0,u1,v1;\r\n\tfloat x0,y0,x1,y1;\r\n\tuint32 z;\r\n\r\n\tuint16 tex_height = (mp_texture) ? mp_texture->GetHeight() : m_height;\r\n\r\n\tu0 = /* 8 +*/ (0);\r\n\tv0 = /*-8 +*/ (tex_height << 4);\r\n\tu1 = /* 8 +*/ (m_width << 4);\r\n\tv1 = /*-8 +*/ ((tex_height - m_height) << 4);\r\n\r\n\t// Check for flip\r\n\tfloat abs_scale_x = m_scale_x;// * s_screen_scale_x;\r\n\tfloat abs_scale_y = m_scale_y;// * s_screen_scale_y;\r\n\tif (abs_scale_x < 0.0f)\r\n\t{\r\n\t\tuint16 temp = u0;\r\n\t\tu0 = u1;\r\n\t\tu1 = temp;\r\n\t\tabs_scale_x = -abs_scale_x;\r\n\t}\r\n\tif (abs_scale_y < 0.0f)\r\n\t{\r\n\t\tuint16 temp = v0;\r\n\t\tv0 = v1;\r\n\t\tv1 = temp;\r\n\t\tabs_scale_y = -abs_scale_y;\r\n\t}\r\n\r\n\tx0 = -m_xhot * 16.0f * abs_scale_x;\r\n\ty0 = -m_yhot * 16.0f * abs_scale_y;\r\n\r\n\tx1 = x0 + ((float) (u1 - u0) * abs_scale_x);\r\n\ty1 = y0 + ((float) (v0 - v1) * abs_scale_y);\r\n\r\n\tz = s_constant_z_enabled ? s_constant_z : GetZValue();\r\n\r\n\t// Flip V if texture is inverted in VRAM\r\n\tif (mp_texture && mp_texture->IsInverted())\r\n\t{\r\n\t\tuint16 temp = v0;\r\n\t\tv0 = v1;\r\n\t\tv1 = temp;\r\n\t}\r\n\r\n\t// Check for rotation\r\n\tif (m_rot != 0.0f)\r\n\t{\r\n\t\tMth::Vector p0(x0, y0, 0.0f, 0.0f);\r\n\t\tMth::Vector p1(x1, y0, 0.0f, 0.0f);\r\n\t\tMth::Vector p2(x0, y1, 0.0f, 0.0f);\r\n\t\tMth::Vector p3(x1, y1, 0.0f, 0.0f);\r\n\r\n\t\tp0.RotateZ(m_rot);\r\n\t\tp1.RotateZ(m_rot);\r\n\t\tp2.RotateZ(m_rot);\r\n\t\tp3.RotateZ(m_rot);\r\n\r\n//printf(\"Before (%d, %d) - (%d, %d)\\n\", x0, y0, x1, y1);\r\n//printf(\"After (%d, %d) - (%d, %d)\\n\", (int) p0.GetX(), (int) p0.GetY(), (int) p3.GetX(), (int) p3.GetY());\r\n\r\n\t\tint xi0 = ((int) (p0.GetX() * s_screen_scale_x)) + start_screen_x;\r\n\t\tint xi1 = ((int) (p1.GetX() * s_screen_scale_x)) + start_screen_x;\r\n\t\tint xi2 = ((int) (p2.GetX() * s_screen_scale_x)) + start_screen_x;\r\n\t\tint xi3 = ((int) (p3.GetX() * s_screen_scale_x)) + start_screen_x;\r\n\t\tint yi0 = ((int) (p0.GetY() * s_screen_scale_y)) + start_screen_y;\r\n\t\tint yi1 = ((int) (p1.GetY() * s_screen_scale_y)) + start_screen_y;\r\n\t\tint yi2 = ((int) (p2.GetY() * s_screen_scale_y)) + start_screen_y;\r\n\t\tint yi3 = ((int) (p3.GetY() * s_screen_scale_y)) + start_screen_y;\r\n\r\n\t\t// Cull, if necessary\r\n\t\tif (NeedsCulling() && ((xi0 | xi1 | xi2 | xi3 | yi0 | yi1 | yi2 | yi3) & 0xFFFF0000))\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Do a TRISTRIP\r\n\t\tvif::StoreV4_32(u0,v0,0,0);\r\n\t\tvif::StoreV4_32(xi0, yi0, z, 0);\r\n\t\tvif::StoreV4_32(u1,v0,0,0);\r\n\t\tvif::StoreV4_32(xi1, yi1, z, 0);\r\n\t\tvif::StoreV4_32(u0,v1,0,0);\r\n\t\tvif::StoreV4_32(xi2, yi2, z, 0);\r\n\t\tvif::StoreV4_32(u1,v1,0,0);\r\n\t\tvif::StoreV4_32(xi3, yi3, z, 0);\r\n\t} else {\r\n\t\t// Just outputting two points for a SPRITE\r\n\t\tint xi0 = ((int) (x0 * s_screen_scale_x)) + start_screen_x;\r\n\t\tint xi1 = ((int) (x1 * s_screen_scale_x)) + start_screen_x;\r\n\t\tint yi0 = ((int) (y0 * s_screen_scale_y)) + start_screen_y;\r\n\t\tint yi1 = ((int) (y1 * s_screen_scale_y)) + start_screen_y;\r\n\r\n\t\t// Cull, if necessary\r\n\t\tif (NeedsCulling() && ((xi0 | xi1 | yi0 | yi1) & 0xFFFF0000))\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvif::StoreV4_32(u0,v0,0,0);\r\n\t\tvif::StoreV4_32(xi0,yi0,z,0);\r\n\t\tvif::StoreV4_32(u1,v1,0,0);\r\n\t\tvif::StoreV4_32(xi1,yi1,z,0);\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n\r\nvoid SSprite::EndDraw(void)\r\n{\r\n\tvif::EndUNPACK();\r\n\tgif::EndTagImmediate(1);\r\n\tvif::MSCAL(VU1_ADDR(Parser));\r\n\tdma::EndTag();\r\n}\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/sprite.h",
    "content": "#ifndef __SPRITE_H\r\n#define __SPRITE_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n// This is a temporary structure until we can merge the 2D textures\r\n// with texture groups\r\nstruct SSingleTexture\r\n{\r\npublic:\r\n\t// Flags\r\n\tenum\r\n\t{\r\n\t\tmLOAD_SCREEN\t\t= 0x0001,\r\n\t\tmALLOC_VRAM\t\t\t= 0x0002,\r\n\t\tmAUTO_ALLOC\t\t\t= 0x0004,\r\n\t\tmSPRITE\t\t\t\t= 0x0008,\r\n\t\tmINVERTED\t\t\t= 0x0010,\r\n\t};\r\n\t\t\t\t\tSSingleTexture();\r\n\t\t\t\t\tSSingleTexture(uint8* p_buffer, int buffer_size, bool sprite, bool alloc_vram, bool load_screen = false);\t// .img.ps2 buffer\r\n\t\t\t\t\tSSingleTexture(const char *Filename, bool sprite, bool alloc_vram, bool load_screen = false);\t\t\t\t// .img.ps2 file\r\n\t\t\t\t\tSSingleTexture(uint8* p_buffer, int width, int height, int bitdepth, int clut_bitdepth, int mipmaps,\r\n\t\t\t\t\t\t\t\t   bool sprite, bool alloc_vram, bool load_screen = false);\t\t// raw buffer\r\n\t\t\t\t\tSSingleTexture(const SSingleTexture & src_texture);\t\t// Copy constructor\r\n\t\t\t\t\t~SSingleTexture();\r\n\r\n\tbool\t\t\tInitTexture(bool copy);\r\n\tvoid\t\t\tFlipTextureVertical();\r\n\r\n\tbool\t\t\tIsInVRAM() const;\r\n\r\n\t// Manual allocate\r\n\tbool\t\t\tAddToVRAM();\r\n\tbool\t\t\tRemoveFromVRAM();\r\n\r\n\t// Auto allocate\r\n\tvoid\t\t\tSetAutoAllocate();\r\n\tvoid\t\t\tUseTexture(bool use);\r\n\r\n\tuint16\t\t\tGetOrigWidth() const;\r\n\tuint16\t\t\tGetOrigHeight() const;\r\n\r\n\tuint16\t\t\tGetWidth() const;\r\n\tuint16\t\t\tGetHeight() const;\r\n\tuint8\t\t\tGetBitdepth() const;\r\n\tuint8\t\t\tGetClutBitdepth() const;\r\n\tuint8\t\t\tGetNumMipmaps() const;\r\n\tbool\t\t\tIsTransparent() const;\r\n\tbool\t\t\tIsInverted() const;\r\n\r\n\tuint8 *\t\t\tGetTextureBuffer() const { return mp_PixelData; }\r\n\tuint32\t\t\tGetTextureBufferSize() const { return m_PixelDataSize; }\r\n\tuint8 *\t\t\tGetClutBuffer() const { return mp_ClutData; }\r\n\tuint32\t\t\tGetClutBufferSize() const { return m_ClutDataSize; }\r\n\r\n\tvoid\t\t\tReallocateVRAM();\r\n\tvoid\t\t\tUpdateDMA();\r\n\r\n\tuint32\t\t\tm_checksum;\r\n\tuint32\t\t\tm_flags;\r\n\tuint8 *\t\t\tmp_VifData;\r\n\tuint8 *\t\t\tmp_TexBuffer;\r\n\tuint8 *\t\t\tmp_PixelData;\r\n\tuint8 *\t\t\tmp_ClutData;\r\n\tuint32\t\t\tm_PixelDataSize;\r\n\tuint32\t\t\tm_ClutDataSize;\r\n\tuint32\t\t\tm_VifSize;\r\n\tint\t\t\t\tm_TexBufferSize;\r\n\tuint64\t\t\tm_RegTEX0, m_RegTEX1;\r\n\tuint32 *\t\tmp_TexBitBltBuf;\t\t// Note these register pointers point to data in the DMA buffer,\r\n\tuint32 *\t\tmp_ClutBitBltBuf;\t\t// so they should only be used for writing, and only after drawing is done.\r\n\r\n\tuint16\t\t\tm_orig_width, m_orig_height;\r\n\tuint16\t\t\tm_NumTexVramBlocks;\r\n\tuint16\t\t\tm_NumClutVramBlocks;\r\n\tuint16\t\t\tm_TBP;\r\n\tuint16\t\t\tm_CBP;\r\n\r\n\tSSingleTexture\t*mp_next;\r\n\r\n\t#ifdef\t\t\t__NOPT_ASSERT__\r\n\tchar\t\t\tm_name[128];\r\n\t#endif\r\n\r\n\t#ifdef\t\t\t__NOPT_ASSERT__\r\n\tstatic void\t\tsPrintAllTextureInfo();\r\n\tstatic void\t\tsPrintAllocatedTextureInfo();\r\n\t#endif\r\n\r\n\tstatic SSingleTexture\t*sp_stexture_list;\r\n\r\nprotected:\r\n\r\n\tbool\t\t\tsetup_reg_and_dma(uint8 *pData, uint32 TW, uint32 TH, uint32 PSM, uint32 CPSM, uint32 MXL, bool copy);\r\n\r\n\t// Update usage for auto VRAM allocate\r\n\tvoid\t\t\tinc_usage_count();\r\n\tvoid\t\t\tdec_usage_count();\r\n\r\n\tstatic uint32\tbitdepth_to_psm(int bitdepth);\r\n\r\n\tint\t\t\t\tm_usage_count;\r\n};\r\n\r\nstruct SScissorWindow\r\n{\r\n\tvoid\t\t\tSetScissorReg(uint64 reg);\r\n\tvoid\t\t\tSetScissor(uint16 x0, uint16 y0, uint16 x1, uint16 y1);\r\n\tuint64\t\t\tGetScissorReg() const { return m_RegSCISSOR; }\r\n\r\nprivate:\r\n\tuint64\t\t\tm_RegSCISSOR;\r\n};\r\n\r\nstruct SDraw2D\r\n{\r\n\t\t\t\t\tSDraw2D(float pri = 0.0f, bool hide = true);\r\n\tvirtual\t\t\t~SDraw2D();\r\n\r\n\tvoid\t\t\tSetPriority(float pri);\r\n\tfloat\t\t\tGetPriority(void) const;\r\n\r\n\tvoid\t\t\tSetZValue(uint32 z);\r\n\tuint32\t\t\tGetZValue(void) const;\r\n\r\n\tvirtual void\tSetHidden(bool hide);\t\t// Virtual because we need to check any vram issues\r\n\tbool\t\t\tIsHidden(void) const;\r\n\r\n\tbool\t\t\tNeedsCulling() const;\r\n\r\n\tvoid\t\t\tSetScissorWindow(SScissorWindow *p_scissor);\r\n\tSScissorWindow *GetScissorWindow() const { return mp_scissor_window; }\r\n\r\n\t// Statics\r\n\tstatic void\t\tDrawAll(void);\r\n\r\n\tstatic void\t\tEnableConstantZValue(bool enable);\r\n\tstatic void\t\tSetConstantZValue(uint32 z);\r\n\tstatic uint32\tGetConstantZValue();\r\n\r\n\tstatic void\t\tCalcScreenScale();\r\n\tstatic float\tGetScreenScaleX();\r\n\tstatic float\tGetScreenScaleY();\r\n\r\nprotected:\r\n\t// Scale for PAL conversion\r\n\tstatic float\ts_screen_scale_x;\r\n\tstatic float\ts_screen_scale_y;\r\n\r\n\t// Constant Z\r\n\tstatic bool\t\ts_constant_z_enabled;\r\n\tstatic uint32\ts_constant_z;\r\n\r\nprivate:\r\n\tvoid\t\t\tInsertSortedDrawList(SDraw2D **p_list);\r\n\tvoid\t\t\tInsertDrawList(SDraw2D **p_list);\r\n\tvoid\t\t\tRemoveDrawList(SDraw2D **p_list);\r\n\r\n\tstatic void\t\tDrawList(SDraw2D *p_list);\r\n\r\n\tvirtual void\tBeginDraw(void) = 0;\r\n\tvirtual void\tDraw(void) = 0;\r\n\tvirtual void\tEndDraw(void) = 0;\r\n\r\n\t// Not even the derived classes should have direct access\r\n\tbool\t\t\tm_hidden;\r\n\tbool\t\t\tm_use_zbuffer;\r\n\tfloat\t\t\tm_pri;\r\n\tuint32\t\t\tm_z;\r\n\tSScissorWindow *mp_scissor_window;\r\n\r\n\t// members\r\n\tSDraw2D\t\t\t*mp_next;\r\n\r\n\t// 2D draw list (sorted by priority)\r\n\tstatic SDraw2D\t*sp_2D_sorted_draw_list;\r\n\t// 2D zbuffer draw list\r\n\tstatic SDraw2D\t*sp_2D_zbuffer_draw_list;\r\n};\r\n\r\n\r\nstruct SSprite : public SDraw2D\r\n{\r\npublic:\r\n\t\t\t\t\tSSprite(float pri = 0.0f);\r\n\tvirtual\t\t\t~SSprite();\r\n\r\n\tvirtual void\tSetHidden(bool hide);\t\t// Virtual because we need to check any vram issues\r\n\r\n\tvoid\t\t\tSetTexture(SSingleTexture *p_texture);\r\n\r\n\tfloat\t\t\tm_xpos;\r\n\tfloat\t\t\tm_ypos;\r\n\tuint16\t\t\tm_width;\r\n\tuint16\t\t\tm_height;\r\n\tfloat\t\t\tm_scale_x;\r\n\tfloat\t\t\tm_scale_y;\r\n\tfloat\t\t\tm_xhot;\r\n\tfloat\t\t\tm_yhot;\r\n\tfloat\t\t\tm_rot;\r\n\tuint32\t\t\tm_rgba;\r\n\r\nprotected:\r\n\r\n\tSSingleTexture\t*mp_texture;\r\n\r\nprivate:\r\n\tvoid\t\t\tBeginDraw(void);\r\n\tvoid\t\t\tDraw(void);\r\n\tvoid\t\t\tEndDraw(void);\r\n};\r\n\r\n\r\n//\r\n// Inlines\r\n//\r\n\r\ninline bool\t\tSSingleTexture::IsInVRAM() const\r\n{\r\n\treturn m_flags & mALLOC_VRAM;\r\n}\r\n\r\ninline bool\t\tSSingleTexture::IsInverted() const\r\n{\r\n\treturn m_flags & mINVERTED;\r\n}\r\n\r\ninline float\tSDraw2D::GetScreenScaleX()\r\n{\r\n\treturn s_screen_scale_x;\r\n}\r\n\r\ninline float\tSDraw2D::GetScreenScaleY()\r\n{\r\n\treturn s_screen_scale_y;\r\n}\r\n\r\ninline uint32\tSDraw2D::GetZValue() const\r\n{\r\n\treturn m_z;\r\n}\r\n\r\ninline bool\t\tSDraw2D::IsHidden(void) const\r\n{\r\n\treturn m_hidden;\r\n}\r\n\r\ninline bool\t\tSDraw2D::NeedsCulling() const\r\n{\r\n\treturn m_use_zbuffer;\t\t// Assuming that only items using the ZBuffer need it\r\n}\r\n\r\nextern uint32\t\tFontVramStart;\r\nextern uint32\t\tFontVramBase;\r\nextern const uint32\tFontVramSize;\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n#endif // __CHARS_H\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/switches.h",
    "content": "#ifndef __SWITCHES_H\r\n#define __SWITCHES_H\r\n\r\n#ifdef __PLAT_NGPS__\r\n#include <sys/config/config.h>\r\n#endif // __PLAT_NGPS__\r\n\r\n#define\tmalloc(x) error Old Memory Function\r\n#define\tcalloc(x) error Old Memory Function\r\n#define\trealloc(x) error Old Memory Function\r\n#define\tfree(x) error Old Memory Function\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n#define USE_INTERRUPTS 1\r\n#define\tGIF_INTERRUPT  1\r\n#define VIF1_INTERRUPT 0\r\n#define GS_INTERRUPT   1\r\n\r\n#define TIMING_BARS 0\r\n\r\n#define C32 1\r\n#define C16 0\r\n#define Z24 1\r\n#define Z16 0\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\n#define HRES_NTSC\t(640)\r\n#define VRES_NTSC\t(448)\r\n#define HRES_PAL\t(512)\r\n#define VRES_PAL\t(512)\r\n\r\n#define HRES (Config::NTSC() ? HRES_NTSC : HRES_PAL)\r\n#define VRES (Config::NTSC() ? VRES_NTSC : VRES_PAL)\r\n\r\n#define XOFFSET ((2048 - (HRES >> 1)) << 4)\r\n#define YOFFSET ((2048 - (VRES >> 1)) << 4)\r\n\r\n// Start and size of buffers in 2K Word size blocks\r\n#define FRAME_START\t\t(0)\r\n#define FRAME_SIZE\t\t(((HRES * VRES) * 4) / (2048 * 4))\t\t// 32-bit frame buffer\r\n#define DISPLAY_START\t(FRAME_START + FRAME_SIZE)\r\n#define DISPLAY_SIZE\t(((HRES * VRES) * 2) / (2048 * 4))\t\t// 16-bit display buffer\r\n#define ZBUFFER_START\t(DISPLAY_START + DISPLAY_SIZE)\r\n#define ZBUFFER_SIZE\t(((HRES * VRES) * 4) / (2048 * 4))\t\t// 32-bit aligned ZBuffer\r\n\r\n#endif // __PLAT_NGPS__\r\n\r\n#define FTOI_TRICK 1\r\n\r\n#define STENCIL_SHADOW 0\r\n#define OLD_FOG 0\r\n\r\n} // namespace NxPs2\r\n\r\n#endif // __SWITCHES_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/texture.cpp",
    "content": "#include <string.h>\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <libgraph.h>\r\n#include \"texture.h\"\r\n#include \"texturemem.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n#include \"group.h\"\r\n#include \"scene.h\"\r\n#include \"switches.h\"\r\n#include <sys\\file\\filesys.h>\r\n#include <core\\crc.h>\r\n\r\n\r\n// K: I put this back to 0 for the moment because Conv4to32 is corrupting memory\r\n// by writing past the end of the temporary swizzle buffer, which causes a hang \r\n// when switching themes in the park editor.\r\n// Garrett: Should be fixed now.\r\n#define SWIZZLE_IN_LOAD 1\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n// static array of pointers to sGroup\r\n// (so that we can pre-allocate our sGroups\r\n// to avoid memory fragmentation)\r\nconst int vMAX_TEX_GROUPS = 32;\r\nstatic sGroup* sp_temp_groups[vMAX_TEX_GROUPS];\r\n\r\nextern TextureMemoryLayout TexMemLayout;\r\n\r\n//------------------------------------------------------------------------------------\r\n//\t\tL O A D   T E X T U R E S\r\n//------------------------------------------------------------------------------------\r\n//\r\n// Performs 2 tasks - it adds texture register settings to the array Textures for all\r\n// textures in the texture file buffer (increasing NumTextures accordingly), and it\r\n// creates a dma subroutine to upload all the textures in the file buffer to vram.\r\n// Currently it handles all the packing (poorly!), but this will eventually be done by\r\n// a preprocess in the tools pipeline.\r\n\r\nbool load_textures(sScene* pScene, uint8* pTexBuffer, bool IsSkin, bool IsInstanceable, bool UsesPip, uint32 texDictOffset)\r\n{\r\n\tDbg_MsgAssert( pScene, ( \"No scene pointer\" ) );\r\n\tDbg_MsgAssert( pTexBuffer, ( \"No tex buffer pointer\" ) );\r\n\r\n\tint total_num_textures=0;\r\n\r\n#if 0\r\n\t// make sure there's no dma list running\r\n\tsceGsSyncPath(0,0);\r\n#else\r\n\t// GJ:  Calling \"sceGsSyncPath()\" instead\r\n\t// of \"WaitForRendering()\" will cause the boardshop\r\n\t// to crash when going into the \"Change Deck\" menu.\r\n\t// Neither Mick nor Mike seem to know why this\r\n\t// would be the case, so it's probably worth \r\n\t// investigating at some point\r\n\tvoid WaitForRendering();\r\n\tWaitForRendering();\r\n#endif\r\n\r\n//\tDbg_Message(\"loading textures from file %s\\n\", Filename);\r\n\r\n\t// initialise members\r\n\tpScene->NumTextures\t= 0;\r\n\tpScene->NumMeshes\t= 0;\r\n\tpScene->pMeshes\t\t= NULL;\r\n\tpScene->Flags\t\t= 0;\r\n\tpScene->pInstances\t= NULL;\r\n\r\n\t// link it in\r\n\tpScene->pNext = sScene::pHead;\r\n\tsScene::pHead = pScene;\r\n\r\n\t// set flags\r\n\tif (UsesPip)\r\n\t{\r\n\t\tpScene->Flags |= SCENEFLAG_USESPIP;\r\n\t}\r\n\t\r\n\t// set the tex buffer pointer\r\n\tpScene->pTexBuffer = pTexBuffer;\r\n\r\n\t// set data pointer\r\n\tsScene::pData = pScene->pTexBuffer;\r\n\r\n\t// version number\r\n\tsTexture::sVersion = *(uint32 *)sScene::pData, sScene::pData+=4;\r\n//\tprintf(\"Texture version %d\\n\", sTexture::sVersion);\r\n\r\n\t// get number of texture groups\r\n\tpScene->NumGroups = *(uint32 *)sScene::pData, sScene::pData+=4;\r\n\r\n\t// get total number of textures, version >= 3\r\n\tif (sTexture::sVersion >= 3)\r\n\t{\r\n\t\ttotal_num_textures = *(int *)sScene::pData, sScene::pData+=4;\r\n\t}\r\n\r\n\r\n\t// allocate storage for textures\r\n\tif (sTexture::sVersion >= 3)\r\n\t{\r\n\t\t// if there are no textures, it will assert in Mem::Malloc\r\n\t\t// so catch this assert earlier here.....\r\n\t\t// really there should be some more elegant handling of scenes with no textures, but they are sufficently rare.\r\n\t\t//Dbg_MsgAssert(total_num_textures>0,(\"Need at least one texture in %s (it has none)\\n\",Filename));\r\n\t\tif( total_num_textures > 0 )\r\n\t\t{\r\n\t\t\tpScene->pTextures = (sTexture *)Mem::Malloc(total_num_textures*sizeof(sTexture));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpScene->pTextures = NULL;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpScene->pTextures = (sTexture *)Mem::Malloc(2000*sizeof(sTexture));\r\n\t}\r\n\r\n\tif ( !((total_num_textures == 0 ) || ( pScene->pTextures )) )\r\n\t{\r\n\t\tDbg_Message( \"couldn't allocate memory for textures\" );\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tDbg_MsgAssert( pScene->NumGroups < vMAX_TEX_GROUPS, ( \"Too many tex groups for static array of sGroup pointers (increase vMAX_TEX_GROUPS from %d)\", vMAX_TEX_GROUPS ) );\r\n\tfor (int i=0; i<pScene->NumGroups; i++)\r\n\t{\r\n\t\t// pre-allocate space for texture groups...\r\n\t\tsp_temp_groups[i] = (sGroup *)Mem::Malloc(sizeof(sGroup));\r\n\t\tmemset(sp_temp_groups[i],0,sizeof(sGroup));\r\n\t}\r\n\r\n\t// allocate prebuilt dma buffer for textures\r\n\t#if 0\r\n\tint\t\tavailable = Mem::Available()-128;\t\t\t  // -128 is needed otherwise it fails trying to allocate all free mem in a region\t\r\n\tif (available > 500000)\r\n\t{\r\n\t\tavailable = 500000;\t \t\t\t\t\t\t\t  // clamp to 500k if we have loads of memory.  No sure why, maybe just to speed up loading when in debug mode\r\n\t}\r\n\t#else\r\n\t// We don't want to allocate all memory as it messes with memory debugging\r\n\t// so \r\n\t// only seem to need T*256 + G*48\r\n\t// hmm, somethings seems to be T*512 for some reason....\r\n\t// but upped it a bit to be safe\r\n\t// These only get used for peds and stuff now\r\n\tint available = total_num_textures * 512 + pScene->NumGroups * 128  + 512;  // bumped up multipliers, and added 512 byte extra\r\n\t#endif\r\n\t\r\n\t\r\n\tpScene->pTexDma = (uint8 *)Mem::Malloc(available);\t  // Allocate all available memeory on current context \r\n\r\n\t// set dma pointer to new buffer\r\n\tdma::pLoc = pScene->pTexDma;\r\n\r\n\t// test\r\n\tsGroup::VramBufferBase = 0x2BC0;\r\n\r\n\t// iterate over groups\r\n\tfor (int i=0; i<pScene->NumGroups; i++)\r\n\t{\r\n\t\tLoadTextureGroup(NULL, pScene, sp_temp_groups[i], IsSkin, IsInstanceable, UsesPip, texDictOffset);\r\n\t\tsp_temp_groups[i] = NULL;\r\n\t}\r\n\r\n\t//Dbg_Message( \"Dma usage = %d Textures = %d, Groups = %d\", (int)(dma::pLoc-pScene->pTexDma), total_num_textures, pScene->NumGroups );\r\n\r\n\tif ( (int)(dma::pLoc-pScene->pTexDma) >= available )\r\n\t{\r\n\t\tDbg_Message( \"Texture dictionary used more memory (%d) than available (%d)\", (int)(dma::pLoc-pScene->pTexDma), available );\r\n\t\treturn false;\r\n\t}\r\n\r\n\r\n\r\n\r\n\t// resize dma buffer so it just fits\r\n\tpScene->pTexDma = (uint8 *)Mem::ReallocateShrink(dma::pLoc-pScene->pTexDma, pScene->pTexDma);\r\n\r\n\t// success!\r\n\treturn true;\r\n}\r\n\r\n// load textures from a file\r\nsScene *LoadTextures(const char *Filename, bool IsSkin, bool IsInstanceable, bool UsesPip, uint32 texDictOffset, uint32 *p_size)\r\n{\r\n//\tDbg_Message( \"LoadTextures: file = %s\", Filename );\r\n\t\r\n\tsScene* pScene = (sScene*)Mem::Malloc(sizeof(sScene));\r\n\tDbg_MsgAssert(pScene, (\"couldn't allocate scene\"));\r\n\r\n\tuint8* pTexBuffer = (uint8*)File::LoadAlloc( Filename, (int*) p_size );\r\n\r\n\tbool success = load_textures(pScene, pTexBuffer, IsSkin, IsInstanceable, UsesPip, texDictOffset);\r\n\tif ( !success )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Load textures from file %s failed\", Filename ) );\r\n\t}\r\n\r\n\treturn pScene;\r\n}\r\n\r\n// load textures from a data buffer, rather than opening a file\r\nsScene *LoadTextures(uint32* pData, int dataSize, bool IsSkin, bool IsInstanceable, bool UsesPip, uint32 texDictOffset)\r\n{\r\n//\tDbg_Message( \"LoadTextures: data = %p size = %d\", pData, dataSize );\r\n\t\r\n\tsScene* pScene = (sScene*)Mem::Malloc(sizeof(sScene));\r\n\tDbg_MsgAssert(pScene, (\"couldn't allocate scene\"));\r\n\r\n\tuint8* pTexBuffer = (uint8*)Mem::Malloc(dataSize);\r\n\tDbg_MsgAssert(pTexBuffer, (\"couldn't allocate tex buffer\"));\r\n\t\r\n\t// copy over the data\r\n\tmemcpy( pTexBuffer, pData, dataSize );\r\n\r\n\tbool success = load_textures(pScene, pTexBuffer, IsSkin, IsInstanceable, UsesPip, texDictOffset);\r\n\tif ( !success )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Load textures from data buffer failed\" ) );\r\n\t}\r\n\r\n\treturn pScene;\r\n}\r\n\r\nvoid LoadTextureGroup(void *pFile, sScene *pScene, sGroup *pGroup, bool IsSkin, bool IsInstanceable, bool UsesPip, uint32 texDictOffset)\r\n{\r\n\tsTexture *pTex, *pOriginalTexture=NULL;\r\n\tuint32 TW, TH, PSM, CPSM;\r\n\tuint TBP[7], TBW[7], CBP;\r\n\tuint Width[7], Height[7], NumTexBytes[7], NumTexQWords[7], NumClutBytes, NumClutQWords, NumVramBytes[7];\r\n\tuint BitsPerTexel, BitsPerClutEntry, PaletteSize, AdjustedWidth[7], AdjustedHeight[7];\r\n\tuint PageWidth, PageHeight, AdjustedBitsPerTexel, TexCount=0;\r\n\tint i,j,k,NumTexturesThisGroup,MXL;\r\n\tuint NextTBP, LastCBP;\r\n\tuint8 *pTextureSource;\r\n\tstatic int Shit=0;\r\n\r\n\tDbg_MsgAssert( pScene, ( \"No pScene\" ) );\r\n\tDbg_MsgAssert( pGroup, ( \"No pre-allocated pGroup was specified\" ) );\r\n\r\n\t// set the scene it belongs to\r\n\tpGroup->pScene = pScene;\r\n\r\n\tpGroup->profile_color = 0x00c000;\t\t// green = static group\t (world, cars)\r\n\tif (IsInstanceable)\r\n\t{\r\n\t\tpGroup->profile_color = 0x808000;\t\t// cyan = instancable static group (cars, gameobjs)\r\n\t}\r\n\tif (IsSkin)\r\n\t{\r\n\t\tpGroup->profile_color = 0x000080;\t\t// red = skin group\r\n\t\tif (IsInstanceable)\r\n\t\t{\r\n\t\t\tpGroup->profile_color = 0x800080;\t\t// magenta = instancable skinned group \r\n\t\t}\r\n\t}\r\n\r\n\r\n\t// zero the mesh pointer in case no meshes get loaded\r\n\tpGroup->pMeshes = NULL;\r\n\tpGroup->NumMeshes = 0;\r\n\r\n\t// prepare to build dma info for this group\r\n\tdma::Align(0,16);\r\n\tpGroup->pUpload[0] = pGroup->pUpload[1] = dma::pLoc;\r\n\r\n\t// get group checksum\r\n\tpGroup->Checksum = *(uint32 *)sScene::pData;\r\n\tpGroup->Checksum += texDictOffset;\r\n\tsScene::pData+=4;\r\n\r\n\t// get group flags if present\r\n\tif (sTexture::sVersion >= 2)\r\n\t{\r\n\t\tpGroup->flags = *(uint32 *)sScene::pData, sScene::pData+=4;\r\n\t}\r\n\telse if (pGroup->Checksum>=1000 & pGroup->Checksum<2000)\r\n\t{\r\n\t\tpGroup->flags = GROUPFLAG_SKY;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpGroup->flags = 0;\r\n\t}\r\n\r\n\t// get group priority if present\r\n\tif (sTexture::sVersion >= 4)\r\n\t{\r\n\t\tpGroup->Priority = *(float *)sScene::pData, sScene::pData+=4;\r\n\t}\r\n\r\n\telse\r\n\t{\r\n\t\t// set its priority manually\r\n\t\tif (UsesPip)\r\n\t\t{\r\n\t\t\tswitch (pGroup->flags & (GROUPFLAG_SKY|GROUPFLAG_TRANSPARENT))\r\n\t\t\t{\r\n\t\t\tcase 0:\r\n\t\t\t\tpGroup->Priority = 0;\r\n\t\t\t\tbreak;\r\n\t\t\tcase GROUPFLAG_SKY:\r\n\t\t\t\tpGroup->Priority = -100;\r\n\t\t\t\tbreak;\r\n\t\t\tcase GROUPFLAG_TRANSPARENT:\r\n\t\t\t\tpGroup->Priority = 7500;\r\n\t\t\t\tbreak;\r\n\t\t\tcase GROUPFLAG_TRANSPARENT|GROUPFLAG_SKY:\r\n\t\t\t\tpGroup->Priority = -99;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (IsSkin)\r\n\t\t{\r\n\t\t\tpGroup->Priority = 5000+Shit;\r\n\t\t}\r\n\t\tif (IsInstanceable)\r\n\t\t{\r\n\t\t\tpGroup->Priority = 2500+Shit;\r\n\t\t}\r\n\t}\r\n\r\n\t// if it has the lowest priority, make a new head\r\n\tif (sGroup::pHead==NULL || pGroup->Priority < sGroup::pHead->Priority)\r\n\t{\r\n\t\tpGroup->pNext = sGroup::pHead;\r\n\t\tpGroup->pPrev = NULL;\r\n\t\tsGroup::pHead = pGroup;\r\n\r\n\t\tif (pGroup->pNext)\r\n\t\t\tpGroup->pNext->pPrev = pGroup;\r\n\t\telse\r\n\t\t\tsGroup::pTail = pGroup;\r\n\t}\r\n\r\n\t// othwerwise if it has the highest priority, make a new tail\r\n\telse if (pGroup->Priority >= sGroup::pTail->Priority)\r\n\t{\r\n\t\tpGroup->pPrev = sGroup::pTail;\r\n\t\tpGroup->pNext = NULL;\r\n\t\tsGroup::pTail->pNext = pGroup;\r\n\t\tsGroup::pTail = pGroup;\r\n\t}\r\n\r\n\t// otherwise find its immediate superior, priority-wise, in the group list\r\n\telse\r\n\t{\r\n\t\tsGroup *pSup;\r\n\t\tfor (pSup=sGroup::pHead; pSup; pSup=pSup->pNext)\r\n\t\t{\r\n\t\t\tif (pGroup->Priority < pSup->Priority)\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tDbg_MsgAssert(pSup, (\"error inserting into group list\\n\"));\r\n\r\n\t\tpGroup->pNext = pSup;\r\n\t\tpGroup->pPrev = pSup->pPrev;\r\n\t\tpSup->pPrev->pNext = pGroup;\r\n\t\tpSup->pPrev = pGroup;\r\n\t}\r\n\r\n\t// get number of textures\r\n\tNumTexturesThisGroup = *(uint32 *)sScene::pData, sScene::pData+=4;\r\n\r\n\t// set vram usage for this group\r\n\tpGroup->VramStart = sGroup::VramBufferBase;\r\n\tpGroup->VramEnd   = sGroup::VramBufferBase+0x0A20;\r\n\r\n\t// advance buffer for next group\r\n\tsGroup::VramBufferBase ^= 0x1E20;\r\n\r\n\t// initialise base pointers\r\n\tNextTBP = pGroup->VramStart;\r\n\tLastCBP = pGroup->VramEnd;\r\n\r\n\t// loop over textures\r\n\tfor (i=0,pTex=pScene->pTextures+pScene->NumTextures; i<NumTexturesThisGroup; i++,pTex++)\r\n\t{\r\n\t\t// get texture flags\r\n\t\tif (sTexture::sVersion >= 5)\r\n\t\t{\r\n\t\t\tpTex->Flags = *(uint32 *)sScene::pData, sScene::pData+=4;\r\n\t\t}\r\n\r\n\t\t// get texture checksum\r\n\t\tpTex->Checksum = *(uint32 *)sScene::pData, sScene::pData+=4;\r\n\r\n\t\t// set group checksum\r\n\t\tpTex->GroupChecksum = pGroup->Checksum;\r\n\r\n\t\t// get dimensions\r\n\t\tTW = *(uint32 *)sScene::pData, sScene::pData+=4;\r\n\t\tTH = *(uint32 *)sScene::pData, sScene::pData+=4;\r\n\r\n\t\t// get pixel storage modes\r\n\t\tPSM  = *(uint32 *)sScene::pData, sScene::pData+=4;\t// for texels\r\n\t\tCPSM = *(uint32 *)sScene::pData, sScene::pData+=4;\t// for clut\r\n\r\n\t\t// get maximum mipmap level\r\n\t\tMXL  = *(uint32 *)sScene::pData, sScene::pData+=4;\r\n\r\n\t\t// clear buffer pointers\r\n\t\tpTex->mp_texture_buffer = NULL;\r\n\t\tpTex->mp_clut_buffer = NULL;\r\n\t\tpTex->m_texture_buffer_size = 0;\r\n\t\tpTex->m_clut_buffer_size = 0;\r\n\r\n\t\t// bail if it's a non-texture\r\n\t\tif (TW == 0xFFFFFFFF)\r\n\t\t{\r\n\t\t\tprintf(\"non-texture at number %d\\n\", i);\r\n\t\t\t// there won't be any more data for this texture\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// detect duplicated texture, signalled by MXL of -1\r\n\t\tif (MXL<0)\r\n\t\t{\r\n\t\t\t// find the original texture\r\n\t\t\tpOriginalTexture = ResolveTextureChecksum(pTex->Checksum);\r\n\r\n\t\t\t// adjust MXL\r\n\t\t\tMXL &= 0x7FFFFFFF;\r\n\r\n\t\t\t// signal duplicate\r\n\t\t\tpTex->Flags &= ~TEXFLAG_ORIGINAL;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// not a duplicate, must be the original\r\n\t\t\tpTex->Flags |= TEXFLAG_ORIGINAL;\r\n\t\t}\r\n\r\n\t\t// quadword-align (original only)\r\n\t\tif (pTex->Flags & TEXFLAG_ORIGINAL)\r\n\t\t{\r\n\t\t\tsScene::pData = (uint8 *)(((uint)(sScene::pData+15)) & 0xFFFFFFF0);\r\n\t\t}\r\n\r\n\t\t// bits per texel and palette size\r\n\t\tswitch (PSM)\r\n\t\t{\r\n\t\tcase PSMCT32:\r\n\t\t\tBitsPerTexel = 32;\r\n\t\t\tPaletteSize  = 0;\r\n\t\t\tbreak;\r\n\t\tcase PSMCT24:\r\n\t\t\tBitsPerTexel = 24;\r\n\t\t\tPaletteSize  = 0;\r\n\t\t\tbreak;\r\n\t\tcase PSMCT16:\r\n\t\t\tBitsPerTexel = 16;\r\n\t\t\tPaletteSize  = 0;\r\n\t\t\tbreak;\r\n\t\tcase PSMT8:\r\n\t\t\tBitsPerTexel = 8;\r\n\t\t\tPaletteSize  = 256;\r\n\t\t\tbreak;\r\n\t\tcase PSMT4:\r\n\t\t\tBitsPerTexel = 4;\r\n\t\t\tPaletteSize  = 16;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tprintf(\"Unknown PSM %d at index %d in texture file\\n\", PSM, i);\r\n\t\t\texit(1);\r\n\t\t}\r\n\r\n\t\t// adjust bits per texel for 24-bit\r\n\t\tAdjustedBitsPerTexel = BitsPerTexel;\r\n\t\tif (BitsPerTexel == 24)\r\n\t\t{\r\n\t\t\tAdjustedBitsPerTexel = 32;\r\n\t\t}\r\n\r\n\t\t// bits per clut entry\r\n\t\tif (BitsPerTexel < 16)\r\n\t\t\tswitch (CPSM)\r\n\t\t\t{\r\n\t\t\tcase PSMCT32:\r\n\t\t\t\tBitsPerClutEntry = 32;\r\n\t\t\t\tbreak;\r\n\t\t\tcase PSMCT16:\r\n\t\t\t\tBitsPerClutEntry = 16;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tprintf(\"Unknown CPSM %d in texture file\\n\", PSM);\r\n\t\t\t\texit(1);\r\n\t\t\t}\r\n\t\telse\r\n\t\t\tBitsPerClutEntry = 0;\r\n\r\n\t\t// rearrange original 256-colour cluts according to requirements of CSM1\r\n\t\tif (PSM==PSMT8 && (pTex->Flags & TEXFLAG_ORIGINAL))\r\n\t\t{\r\n\t\t\tuint32 temp32;\r\n\t\t\tuint16 temp16;\r\n\t\t\tfor (j=0; j<256; j+=32)\r\n\t\t\t\tfor (k=0; k<8; k++)\r\n\t\t\t\t\tif (CPSM==PSMCT32)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttemp32 = ((uint32 *)sScene::pData)[j+k+8];\r\n\t\t\t\t\t\t((uint32 *)sScene::pData)[j+k+8] = ((uint32 *)sScene::pData)[j+k+16];\r\n\t\t\t\t\t\t((uint32 *)sScene::pData)[j+k+16] = temp32;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttemp16 = ((uint16 *)sScene::pData)[j+k+8];\r\n\t\t\t\t\t\t((uint16 *)sScene::pData)[j+k+8] = ((uint16 *)sScene::pData)[j+k+16];\r\n\t\t\t\t\t\t((uint16 *)sScene::pData)[j+k+16] = temp16;\r\n\t\t\t\t\t}\r\n\t\t}\r\n\r\n\t\t// calculate texture dimensions\r\n\t\tfor (j=0; j<=MXL; j++)\r\n\t\t{\r\n\t\t\tWidth[j]  = (TW>=0 ? 1<<TW : 0) >> j;\r\n\t\t\tHeight[j] = (TH>=0 ? 1<<TH : 0) >> j;\r\n\t\t\tTBW[j] = (Width[j]+63) >> 6;\r\n\t\t\tif (BitsPerTexel<16 && TBW[j]<2)\r\n\t\t\t\tTBW[j] = 2;\r\n\t\t}\r\n\r\n\t\t// get page size\r\n\t\tswitch (PSM)\r\n\t\t{\r\n\t\tcase PSMCT32:\r\n\t\tcase PSMCT24:\r\n\t\t\tPageWidth  = 64;\r\n\t\t\tPageHeight = 32;\r\n\t\t\tbreak;\r\n\t\tcase PSMCT16:\r\n\t\t\tPageWidth  = 64;\r\n\t\t\tPageHeight = 64;\r\n\t\t\tbreak;\r\n\t\tcase PSMT8:\r\n\t\t\tPageWidth  = 128;\r\n\t\t\tPageHeight = 64;\r\n\t\t\tbreak;\r\n\t\tcase PSMT4:\r\n\t\t\tPageWidth  = 128;\r\n\t\t\tPageHeight = 128;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tprintf(\"Unknown PSM %d at index %d in texture file\\n\", PSM, i);\r\n\t\t\texit(1);\r\n\t\t}\r\n\r\n\t\t// calculate adjusted dimensions based on vram page size\r\n\t\tfor (j=0; j<=MXL; j++)\r\n\t\t{\r\n\t\t\tAdjustedWidth[j]  = Width[j];\r\n\t\t\tAdjustedHeight[j] = Height[j];\r\n\r\n\t\t\tif (AdjustedWidth[j] < PageWidth && AdjustedHeight[j] > PageHeight)\r\n\t\t\t{\r\n\t\t\t\tAdjustedWidth[j] = PageWidth;\r\n\t\t\t}\r\n\r\n\t\t\tif (AdjustedWidth[j] > PageWidth && AdjustedHeight[j] < PageHeight)\r\n\t\t\t{\r\n\t\t\t\tAdjustedHeight[j] = PageHeight;\r\n\t\t\t}\r\n\r\n\t\t\tif (TBW[j]<<6 > AdjustedWidth[j])\r\n\t\t\t{\r\n\t\t\t\tAdjustedWidth[j] = TBW[j]<<6;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// calculate sizes within file\r\n\t\tNumClutBytes  = PaletteSize * BitsPerClutEntry >> 3;\r\n\t\tNumClutQWords = NumClutBytes >> 4;\r\n\t\tfor (j=0; j<=MXL; j++)\r\n\t\t{\r\n\t\t\tNumTexBytes[j]  = Width[j] * Height[j] * BitsPerTexel >> 3;\r\n\t\t\tNumVramBytes[j] = AdjustedWidth[j] * AdjustedHeight[j] * AdjustedBitsPerTexel >> 3;\r\n\t\t\tNumTexQWords[j] = (NumTexBytes[j]+15) >> 4;\r\n\t\t}\r\n\r\n\t\t// calculate TBP\r\n\t\tTBP[0] = NextTBP;\r\n\t\tfor (j=1; j<=MXL; j++)\r\n\t\t\tTBP[j] = (((TBP[j-1]<<8)+NumVramBytes[j-1]+0x1FFF) & 0xFFFFE000) >> 8;\r\n\r\n\t\t// calculate CBP\r\n\t\tif (BitsPerTexel >= 16)\r\n\t\t\tCBP = LastCBP;\r\n\t\telse if (BitsPerTexel == 4)\r\n\t\t\tCBP = LastCBP - 1;\r\n\t\telse\r\n\t\t\tCBP = LastCBP - (CPSM==PSMCT32 ? 4 : 2);\r\n\r\n\t\t// calculate next TBP\r\n\t\tNextTBP = (((TBP[MXL]<<8)+NumVramBytes[MXL]+0x1FFF) & 0xFFFFE000) >> 8;\r\n\r\n\t\t// bail if VRAM would become over-packed\r\n\t\tif (NextTBP > CBP)\r\n\t\t{\r\n\t\t\tprintf(\"no room for texture %d\\n\", i);\r\n\t\t\tif (pTex->Flags & TEXFLAG_ORIGINAL)\r\n\t\t\t{\r\n\t\t\t\tsScene::pData += NumClutBytes;\r\n\t\t\t\tfor (j=0; j<=MXL; j++)\r\n\t\t\t\t{\r\n\t\t\t\t\tsScene::pData = (uint8 *)(((uint)(sScene::pData+NumTexBytes[j]+15)) & 0xFFFFFFF0);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// add clut upload to dma list if necessary\r\n\t\tif (BitsPerTexel < 16)\r\n\t\t{\r\n\t\t\t// source\r\n\t\t\tif (pTex->Flags & TEXFLAG_ORIGINAL)\r\n\t\t\t{\r\n\t\t\t\tpTextureSource = sScene::pData;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpTextureSource = pOriginalTexture->mp_clut_buffer;\r\n\t\t\t}\r\n\r\n\t\t\t// save buffer pointer\r\n\t\t\tpTex->mp_clut_buffer = pTextureSource;\r\n\t\t\tpTex->m_clut_buffer_size = NumClutBytes;\r\n\r\n\t\t\t// add dma\r\n\t\t\tdma::BeginTag(dma::cnt,0);\r\n\t\t\tvif::NOP();\r\n\t\t\tvif::NOP();\r\n\t\t\tgif::Tag2(gs::A_D,1,PACKED,0,0,0,4);\r\n\t\t\tgs::Reg2(gs::BITBLTBUF,PackBITBLTBUF(0,0,0,CBP,1,CPSM));\r\n\t\t\tgs::Reg2(gs::TRXPOS,\tPackTRXPOS(0,0,0,0,0));\r\n\t\t\tif (PSM==PSMT4)\r\n\t\t\t\tgs::Reg2(gs::TRXREG,PackTRXREG(8,2));\r\n\t\t\telse\r\n\t\t\t\tgs::Reg2(gs::TRXREG,PackTRXREG(16,16));\r\n\t\t\tgs::Reg2(gs::TRXDIR,\t0);\r\n\t\t\tgif::Tag2(0,0,IMAGE,0,0,0,NumClutQWords);\r\n\t\t\tdma::EndTag();\r\n\t\t\tdma::Tag(dma::ref, NumClutQWords, (uint)pTextureSource);\r\n\t\t\tvif::NOP();\r\n\t\t\tvif::NOP();\r\n\t\t}\r\n\r\n\t\tif (pTex->Flags & TEXFLAG_ORIGINAL)\r\n\t\t{\r\n\t\t\t// step past clut data, and quadword-align\r\n\t\t\tsScene::pData = (uint8 *)(((uint)(sScene::pData+NumClutBytes+15)) & 0xFFFFFFF0);\r\n\r\n\t\t\t// save buffer pointer\r\n\t\t\tpTex->mp_texture_buffer = sScene::pData;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpTex->mp_texture_buffer = pOriginalTexture->mp_texture_buffer;\r\n\t\t}\r\n\t\tpTextureSource = pTex->mp_texture_buffer;\r\n\r\n\r\n\t\t// offset to improve caching\r\n\t\tfor (j=0; j<=MXL; j++)\r\n\t\t{\r\n\t\t\tif (TexCount & 1)\r\n\t\t\t{\r\n\t\t\t\tif ((BitsPerTexel==32 || BitsPerTexel==8)\r\n\t\t\t\t\t\t&& (Width[j]  <= (PageWidth>>1))\r\n\t\t\t\t\t\t&& (Height[j] <= PageHeight)\r\n\t\t\t\t\t||\r\n\t\t\t\t\t(BitsPerTexel==16 || BitsPerTexel==4)\r\n\t\t\t\t\t\t&& (Width[j]  <=  PageWidth)\r\n\t\t\t\t\t\t&& (Height[j] <= (PageHeight>>1)))\r\n\t\t\t\t{\r\n\t\t\t\t\tTBP[j] += 16;\r\n\t\t\t\t\t//printf(\"better caching!\\n\");\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tTexCount++;\r\n\t\t}\r\n\r\n#if SWIZZLE_IN_LOAD\r\n\t\tbool swizzleTex = BitsPerTexel <= 8;\r\n#endif // SWIZZLE_IN_LOAD\r\n\r\n\t\t// loop over mipmaps\r\n\t\tfor (j=0; j<=MXL; j++)\r\n\t\t{\r\n#if SWIZZLE_IN_LOAD\r\n\t\t\tint swizzle_tbw = TBW[j];\r\n\t\t\tint swizzle_width = Width[j];\r\n\t\t\tint swizzle_height = Height[j];\r\n\t\t\tuint32 swizzlePSM = PSM;\r\n\t\t\tbool swizzleMip = false;\r\n\r\n\t\t\tif (swizzleTex)\r\n\t\t\t{\r\n\t\t\t\tswitch (PSM)\r\n\t\t\t\t{\r\n\t\t\t\tcase PSMT8:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (TexMemLayout.CanConv8to32(Width[j], Height[j]))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif (pTex->Flags & TEXFLAG_ORIGINAL)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\t\t\t\t\t\tuint8 *pTextureSwizzle = (uint8 *) Mem::Malloc(Width[j] * Height[j]);\r\n\t\t\t\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t\t\t\t\t\t\tTexMemLayout.Conv8to32(Width[j], Height[j], pTextureSource, pTextureSwizzle);\r\n\t\t\t\t\t\t\t\tmemcpy(pTextureSource, pTextureSwizzle, Width[j] * Height[j]);\r\n\r\n\t\t\t\t\t\t\t\tMem::Free(pTextureSwizzle);\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// Change size to 32-bit version\r\n\t\t\t\t\t\t\tswizzle_width /= 2;\r\n\t\t\t\t\t\t\tswizzle_height /= 2;\r\n\r\n\t\t\t\t\t\t\t// Recalculate Buffer Width since 8-bit version can be artificially high\r\n\t\t\t\t\t\t\tswizzle_tbw = swizzle_width / 64;\r\n\t\t\t\t\t\t\tif (swizzle_tbw == 0)\r\n\t\t\t\t\t\t\t\tswizzle_tbw = 1;\r\n\r\n\t\t\t\t\t\t\tswizzleMip = true;\r\n\t\t\t\t\t\t\tswizzlePSM=PSMCT32;\t// swizzle\r\n\t\t\t\t\t\t\tpTex->Flags |= TEXFLAG_MIP_SWIZZLE_32BIT(j);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\tcase PSMT4:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (TexMemLayout.CanConv4to32(Width[j], Height[j]))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t//Dbg_Message(\"Swizzling texture checksum %x\", pTex->Checksum);\r\n\r\n\t\t\t\t\t\t\tif (pTex->Flags & TEXFLAG_ORIGINAL)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\t\t\t\t\t\tuint8 *pTextureSwizzle = (uint8 *) Mem::Malloc(Width[j] * Height[j] / 2);\r\n\t\t\t\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t\t\t\t\t\t\tTexMemLayout.Conv4to32(Width[j], Height[j], pTextureSource, pTextureSwizzle);\r\n\t\t\t\t\t\t\t\tmemcpy(pTextureSource, pTextureSwizzle, Width[j] * Height[j] / 2);\r\n\r\n\t\t\t\t\t\t\t\tMem::Free(pTextureSwizzle);\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// Change size to 32-bit version\r\n\t\t\t\t\t\t\tswizzle_width /= 2;\r\n\t\t\t\t\t\t\tswizzle_height /= 4;\r\n\r\n\t\t\t\t\t\t\t// Recalculate Buffer Width since 4-bit version can be artificially high\r\n\t\t\t\t\t\t\tswizzle_tbw = swizzle_width / 64;\r\n\t\t\t\t\t\t\tif (swizzle_tbw == 0)\r\n\t\t\t\t\t\t\t\tswizzle_tbw = 1;\r\n\r\n\t\t\t\t\t\t\tswizzleMip = true;\r\n\t\t\t\t\t\t\tswizzlePSM=PSMCT32;\t// swizzle\r\n\t\t\t\t\t\t\tpTex->Flags |= TEXFLAG_MIP_SWIZZLE_32BIT(j);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse if (TexMemLayout.CanConv4to16(Width[j], Height[j]))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif (pTex->Flags & TEXFLAG_ORIGINAL)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\t\t\t\t\t\tuint8 *pTextureSwizzle = (uint8 *) Mem::Malloc(Width[j] * Height[j] / 2);\r\n\t\t\t\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t\t\t\t\t\t\tTexMemLayout.Conv4to16(Width[j], Height[j], pTextureSource, pTextureSwizzle);\r\n\t\t\t\t\t\t\t\tmemcpy(pTextureSource, pTextureSwizzle, Width[j] * Height[j] / 2);\r\n\r\n\t\t\t\t\t\t\t\tMem::Free(pTextureSwizzle);\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// Change size to 16-bit version\r\n\t\t\t\t\t\t\tswizzle_width /= 2;\r\n\t\t\t\t\t\t\tswizzle_height /= 2;\r\n\r\n\t\t\t\t\t\t\t// Recalculate Buffer Width since 4-bit version can be artificially high\r\n\t\t\t\t\t\t\tswizzle_tbw = swizzle_width / 64;\r\n\t\t\t\t\t\t\tif (swizzle_tbw == 0)\r\n\t\t\t\t\t\t\t\tswizzle_tbw = 1;\r\n\r\n\t\t\t\t\t\t\tswizzleMip = true;\r\n\t\t\t\t\t\t\tswizzlePSM=PSMCT16;\t// swizzle\r\n\t\t\t\t\t\t\tpTex->Flags |= TEXFLAG_MIP_SWIZZLE_16BIT(j);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n#endif // SWIZZLE_IN_LOAD\r\n\r\n\r\n\t\t\t// add texture upload to dma list for this mipmap level\r\n\t\t\tdma::BeginTag(dma::cnt,0);\r\n\t\t\tvif::NOP();\r\n\t\t\tvif::NOP();\r\n\t\t\tgif::Tag2(gs::A_D,1,PACKED,0,0,0,4);\r\n#if SWIZZLE_IN_LOAD\r\n\t\t\tgs::Reg2(gs::BITBLTBUF,PackBITBLTBUF(0,0,0,TBP[j],swizzle_tbw,swizzlePSM));\r\n\t\t\tgs::Reg2(gs::TRXPOS,\tPackTRXPOS(0,0,0,0,0));\r\n\t\t\tgs::Reg2(gs::TRXREG,\tPackTRXREG(swizzle_width,swizzle_height));\r\n#else\r\n\t\t\tgs::Reg2(gs::BITBLTBUF,PackBITBLTBUF(0,0,0,TBP[j],TBW[j],PSM));\r\n\t\t\tgs::Reg2(gs::TRXPOS,\tPackTRXPOS(0,0,0,0,0));\r\n\t\t\tgs::Reg2(gs::TRXREG,\tPackTRXREG(Width[j],Height[j]));\r\n#endif // SWIZZLE_IN_LOAD\r\n\t\t\tgs::Reg2(gs::TRXDIR,\t0);\r\n\t\t\t\r\n\t\t\tif (j==0)\r\n\t\t\t{\r\n\t\t\t\tpTex->mp_dma = dma::pLoc;\r\n\t\t\t\tpTex->m_quad_words = NumTexQWords[j];\r\n\t\t\t\tpTex->m_render_count = 0;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\r\n\t\t\tgif::Tag2(0, 0, IMAGE, 0, 0, 0, NumTexQWords[j]);  \t\t\t// 0..3 words, NumTexQWords is in the lower 15 bits of the first word [0]\r\n\t\t\tdma::EndTag();\t\t\t\t\t\t\t\t\t   \t\t\t// Just Aligns upo to QW boundry\r\n\t\t\tdma::Tag(dma::ref, NumTexQWords[j], (uint)pTextureSource);  // 0..1 (after alignment) NumTexQWords goes in word 1\r\n\t\t\tvif::NOP();\r\n\t\t\tvif::NOP();\r\n\r\n\t\t\t// step past tex data for this level\r\n\t\t\tpTextureSource += NumTexBytes[j];\r\n\t\t}\r\n\r\n\t\tpTex->m_texture_buffer_size = (uint32) pTextureSource - (uint32) pTex->mp_texture_buffer;\r\n\r\n\t\tif (pTex->Flags & TEXFLAG_ORIGINAL)\r\n\t\t{\r\n\t\t\tsScene::pData = pTextureSource;\r\n\t\t}\r\n\r\n\t\t// make entry in texture table\r\n\t\tpTex->MXL        = MXL;\r\n\t\tpTex->RegTEX0    = PackTEX0(TBP[0],TBW[0],PSM,TW,TH,(PSM!=PSMCT24),MODULATE,CBP,CPSM,0,0,1);\r\n\t\tpTex->RegMIPTBP1 = PackMIPTBP1(TBP[1],TBW[1],TBP[2],TBW[2],TBP[3],TBW[3]);\r\n\t\tpTex->RegMIPTBP2 = PackMIPTBP2(TBP[4],TBW[4],TBP[5],TBW[5],TBP[6],TBW[6]);\r\n\r\n\t\t// advance texture base pointer to 1st page after texture\r\n\t\t// and reduce clut base pointer to 1st page before clut (if there was one)\r\n\t\tTBP[0] = NextTBP;\r\n\t\tLastCBP = CBP;\r\n\r\n\t}\r\n\r\n\t// add to total for the scene\r\n\tpScene->NumTextures += NumTexturesThisGroup;\r\n\r\n\t// texflush so we can use textures\r\n\tdma::BeginTag(dma::end, 0);\r\n\tvif::NOP();\r\n\tvif::NOP();\r\n\tgif::Tag2(gs::A_D,1,PACKED,0,0,1,1);\r\n\tgs::Reg2(gs::TEXFLUSH,\t0);\r\n\tdma::EndTag();\r\n\r\n\tif (UsesPip==false)\r\n\t{\r\n\t\tShit++;\r\n\t}\r\n\r\n}\r\n\r\n\r\n\r\n\r\nvoid DeleteTextures(sScene *pScene)\r\n{\r\n\tsScene *pPrev;\r\n\tsGroup *pGroup, *pDead;\r\n\r\n\t// deallocate assets\r\n\tMem::Free(pScene->pTexBuffer);\r\n\tMem::Free(pScene->pTexDma);\r\n\tif( pScene->pTextures != NULL )\r\n\t{\r\n\t\tMem::Free(pScene->pTextures);\r\n\t}\r\n\r\n\t// deallocate groups\r\n\tpGroup = sGroup::pHead;\r\n\twhile (pGroup)\r\n\t{\r\n\t\tif (pGroup->pScene == pScene)\r\n\t\t{\r\n\t\t\tif (pGroup == sGroup::pHead)\r\n\t\t\t{\r\n\t\t\t\tpGroup->pNext->pPrev = NULL;\r\n\t\t\t\tsGroup::pHead = pGroup->pNext;\r\n\t\t\t}\r\n\t\t\telse if (pGroup == sGroup::pTail)\r\n\t\t\t{\r\n\t\t\t\tpGroup->pPrev->pNext = NULL;\r\n\t\t\t\tsGroup::pTail = pGroup->pPrev;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpGroup->pNext->pPrev = pGroup->pPrev;\r\n\t\t\t\tpGroup->pPrev->pNext = pGroup->pNext;\r\n\t\t\t}\r\n\t\t\tpDead = pGroup;\r\n\t\t\tpGroup = pGroup->pNext;\r\n\t\t\tMem::Free(pDead);\r\n\t\t}\r\n\t\telse\r\n\t\t\tpGroup = pGroup->pNext;\r\n\t}\r\n\r\n\t// unlink\r\n\tif (pScene==sScene::pHead)\r\n\t\tsScene::pHead = pScene->pNext;\r\n\telse\r\n\t{\r\n\t\tfor (pPrev=sScene::pHead; pPrev; pPrev=pPrev->pNext)\r\n\t\t\tif (pPrev->pNext == pScene)\r\n\t\t\t\tbreak;\r\n\t\tDbg_MsgAssert(pPrev, (\"couldn't find scene to delete\\n\"));\r\n\r\n\t\tpPrev->pNext = pScene->pNext;\r\n\t}\r\n\r\n\t// free\r\n\tMem::Free(pScene);\r\n}\r\n\r\n\r\n\r\n\r\n\r\nsTexture *ResolveTextureChecksum(uint32 TextureChecksum)\r\n{\r\n\tsScene *pScene;\r\n\tsTexture *pTex=NULL;\r\n\tint i;\r\n\r\n\tfor (pScene=sScene::pHead; pScene; pScene=pScene->pNext)\r\n\t{\r\n\t\tfor (i=0,pTex=pScene->pTextures; i<pScene->NumTextures; i++,pTex++)\r\n\t\t\tif ((pTex->Checksum == TextureChecksum) && (pTex->Flags & TEXFLAG_ORIGINAL))\r\n\t\t\t\treturn pTex;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\nsTexture *ResolveTextureChecksum(uint32 TextureChecksum, uint32 GroupChecksum)\r\n{\r\n\tsScene *pScene;\r\n\tsTexture *pTex=NULL;\r\n\tint i;\r\n\r\n\tfor (pScene=sScene::pHead; pScene; pScene=pScene->pNext)\r\n\t{\r\n\t\tfor (i=0,pTex=pScene->pTextures; i<pScene->NumTextures; i++,pTex++)\r\n\t\t\tif ((pTex->Checksum == TextureChecksum) && (pTex->GroupChecksum == GroupChecksum))\r\n\t\t\t\treturn pTex;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\nuint32 sTexture::sVersion;\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// The following Get() calls are very inefficient.  They should only be\r\n// used when necessary (i.e. initialization).\r\n//\r\nuint16\tsTexture::GetWidth() const\r\n{\r\n\tsceGsTex0 tex0 = *((sceGsTex0 *) &RegTEX0);\r\n\tuint16 TW = tex0.TW;\r\n\t//uint16 TW = (uint16) ((RegTEX0 >> 26) & M04);\r\n\r\n\treturn 1 << TW;\r\n}\r\n\r\nuint16\tsTexture::GetHeight() const\r\n{\r\n\tsceGsTex0 tex0 = *((sceGsTex0 *) &RegTEX0);\r\n\tuint16 TH = tex0.TH;\r\n\t//uint16 TH = (uint16) ((RegTEX0 >> 30) & M04);\r\n\r\n\treturn 1 << TH;\r\n}\r\n\r\nuint8\tsTexture::GetBitdepth() const\r\n{\r\n\tsceGsTex0 tex0 = *((sceGsTex0 *) &RegTEX0);\r\n\tuint PSM = tex0.PSM;\r\n\r\n\tswitch (PSM)\r\n\t{\r\n\tcase PSMCT32:\r\n\t\treturn 32;\r\n\t\tbreak;\r\n\tcase PSMCT24:\r\n\t\treturn 24;\r\n\t\tbreak;\r\n\tcase PSMCT16:\r\n\t\treturn 16;\r\n\t\tbreak;\r\n\tcase PSMT8:\r\n\t\treturn 8;\r\n\t\tbreak;\r\n\tcase PSMT4:\r\n\t\treturn 4;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\nuint8\tsTexture::GetClutBitdepth() const\r\n{\r\n\tsceGsTex0 tex0 = *((sceGsTex0 *) &RegTEX0);\r\n\tuint CPSM = tex0.CPSM;\r\n\r\n\tswitch (CPSM)\r\n\t{\r\n\tcase PSMCT32:\r\n\t\treturn 32;\r\n\t\tbreak;\r\n\tcase PSMCT24:\r\n\t\treturn 24;\r\n\t\tbreak;\r\n\tcase PSMCT16:\r\n\t\treturn 16;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\nuint8\tsTexture::GetNumMipmaps() const\r\n{\r\n\treturn MXL + 1;\r\n}\r\n\r\nbool\tsTexture::HasSwizzleMip() const\r\n{\r\n\tfor (uint mip_idx = 0; mip_idx <= MXL; mip_idx++)\r\n\t{\r\n\t\tif (Flags & TEXFLAG_MIP_SWIZZLE(mip_idx))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid\tsTexture::ReplaceTextureData(uint8 *p_texture_data)\r\n{\r\n\tuint mip_width, mip_height, mip_NumTexBytes;\r\n\r\n\tint bitdepth = GetBitdepth();\r\n\tint width = GetWidth();\r\n\tint height = GetHeight();\r\n\r\n\tuint8 *pTextureSource = mp_texture_buffer;\r\n\r\n\t// calculate texture dimensions\r\n\tfor (uint j=0; j<=MXL; j++)\r\n\t{\r\n\t\tmip_width  = width >> j;\r\n\t\tmip_height = height >> j;\r\n\t\tmip_NumTexBytes  = mip_width * mip_height * bitdepth >> 3;\r\n\r\n\t\t// Do the actual copies, swizzling if necessary\r\n\t\tif (Flags & TEXFLAG_MIP_SWIZZLE_16BIT(j))\r\n\t\t{\r\n\t\t\tswitch (bitdepth)\r\n\t\t\t{\r\n\t\t\tcase 4:\r\n\t\t\t\tTexMemLayout.Conv4to16(mip_width, mip_height, p_texture_data, pTextureSource);\r\n\t\t\t\tbreak;\r\n\t\t\tcase 8:\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(0, (\"Can't swizzle a texture of bitdepth %d to 16-bit\", bitdepth));\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if (Flags & TEXFLAG_MIP_SWIZZLE_32BIT(j))\r\n\t\t{\r\n\t\t\tswitch (bitdepth)\r\n\t\t\t{\r\n\t\t\tcase 8:\r\n\t\t\t\tTexMemLayout.Conv8to32(mip_width, mip_height, p_texture_data, pTextureSource);\r\n\t\t\t\tbreak;\r\n\t\t\tcase 4:\r\n\t\t\t\tTexMemLayout.Conv4to32(mip_width, mip_height, p_texture_data, pTextureSource);\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(0, (\"Can't swizzle a texture of bitdepth %d to 32-bit\", bitdepth));\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmemcpy(pTextureSource, p_texture_data, mip_NumTexBytes);\r\n\t\t}\r\n\r\n\t\t// step past tex data for this level\r\n\t\tpTextureSource += mip_NumTexBytes;\r\n\t\tp_texture_data += mip_NumTexBytes;\r\n\t}\r\n\r\n}\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/texture.h",
    "content": "#ifndef __TEXTURE_H\r\n#define __TEXTURE_H\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n#define TEXTURE_BUFFER_SIZE 4194304\r\n\r\n////////////////////////\r\n// Flags\r\n#define TEXFLAG_ORIGINAL\t\t\t(1<<0)\r\n#define TEXFLAG_ANIMATED\t\t\t(1<<1)\r\n#define TEXFLAG_MIP0_SWIZZLE_16BIT\t(1<<18)\t\t\t// The swizzle bit flags go all the way to the end of the Flag variable\r\n#define TEXFLAG_MIP1_SWIZZLE_16BIT\t(1<<19)\r\n#define TEXFLAG_MIP2_SWIZZLE_16BIT\t(1<<20)\r\n#define TEXFLAG_MIP3_SWIZZLE_16BIT\t(1<<21)\r\n#define TEXFLAG_MIP4_SWIZZLE_16BIT\t(1<<22)\r\n#define TEXFLAG_MIP5_SWIZZLE_16BIT\t(1<<23)\r\n#define TEXFLAG_MIP6_SWIZZLE_16BIT\t(1<<24)\r\n#define TEXFLAG_MIP0_SWIZZLE_32BIT\t(1<<25)\r\n#define TEXFLAG_MIP1_SWIZZLE_32BIT\t(1<<26)\r\n#define TEXFLAG_MIP2_SWIZZLE_32BIT\t(1<<27)\r\n#define TEXFLAG_MIP3_SWIZZLE_32BIT\t(1<<28)\r\n#define TEXFLAG_MIP4_SWIZZLE_32BIT\t(1<<29)\r\n#define TEXFLAG_MIP5_SWIZZLE_32BIT\t(1<<30)\r\n#define TEXFLAG_MIP6_SWIZZLE_32BIT\t(1<<31)\r\n\r\n#define TEXFLAG_MIP0_SWIZZLE\t\t(TEXFLAG_MIP0_SWIZZLE_16BIT | TEXFLAG_MIP0_SWIZZLE_32BIT)\r\n\r\n#define TEXFLAG_MIP_SWIZZLE_16BIT(m)\t(TEXFLAG_MIP0_SWIZZLE_16BIT << m)\r\n#define TEXFLAG_MIP_SWIZZLE_32BIT(m)\t(TEXFLAG_MIP0_SWIZZLE_32BIT << m)\r\n#define TEXFLAG_MIP_SWIZZLE(m)\t\t\t(TEXFLAG_MIP0_SWIZZLE << m)\r\n\r\nstruct sGroup;\r\n\r\nstruct sTexture\r\n{\r\n\tuint16\t\t\tGetWidth() const;\r\n\tuint16\t\t\tGetHeight() const;\r\n\tuint8\t\t\tGetBitdepth() const;\r\n\tuint8\t\t\tGetClutBitdepth() const;\r\n\tuint8\t\t\tGetNumMipmaps() const;\r\n\r\n\tuint8 *\t\t\tGetTextureBuffer() const { return mp_texture_buffer; }\r\n\tuint32\t\t\tGetTextureBufferSize() const { return m_texture_buffer_size; }\r\n\tuint8 *\t\t\tGetClutBuffer() const { return mp_clut_buffer; }\r\n\tuint32\t\t\tGetClutBufferSize() const { return m_clut_buffer_size; }\r\n\r\n\tbool\t\t\tHasSwizzleMip() const;\r\n\tvoid\t\t\tReplaceTextureData(uint8 *p_texture_data);\r\n\r\n\tuint32 Checksum, GroupChecksum, MXL;\r\n\tuint64 RegTEX0, RegMIPTBP1, RegMIPTBP2;\r\n\r\n\tuint8  *mp_texture_buffer;\r\n\tuint32 m_texture_buffer_size;\r\n\tuint8  *mp_clut_buffer;\r\n\tuint32 m_clut_buffer_size;\r\n\r\n\t//bool   Original;\r\n\tuint32 Flags;\r\n\r\n\tstatic uint32 sVersion;\r\n\t\r\n\t\r\n\tuint8\t\t*\tmp_dma;\t \t\t\t// pointer to DMA list if we want to patch up this texture\r\n\tuint32\t\tm_render_count;\t\t\t// count of how many times this has been rendered this frame\r\n\tuint32 \t\tm_quad_words;\t\t\t// number of quad words to upload in first pass\r\n};\r\n\r\n\r\n\r\nstruct sScene *LoadTextures(uint32* pData, int dataSize, bool IsSkin=false, bool IsInstanceable=false, bool UsesPip=false, uint32 texDictOffset=0);\r\nstruct sScene *LoadTextures(const char *Filename, bool IsSkin=false, bool IsInstanceable=false, bool UsesPip=false, uint32 texDictOffset=0, uint32 *p_size = NULL);\r\nvoid LoadTextureGroup(void *pFile, sScene *pScene, sGroup *pGroup, bool IsSkin, bool IsInstanceable, bool UsesPip, uint32 texDictOffset);\r\nvoid DeleteTextures(sScene *pScene);\r\nsTexture *ResolveTextureChecksum(uint32 TextureChecksum);\r\nsTexture *ResolveTextureChecksum(uint32 TextureChecksum, uint32 GroupChecksum);\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n#endif // __TEXTURE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/texturemem.cpp",
    "content": "#include <core/defines.h>\r\n#include \"texture.h\"\r\n#include \"texturemem.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n\r\n#include <core/math/math.h>\r\n\r\n#define min(x, y) (((x) > (y))? (y): (x))\r\n#define max(x, y) (((x) < (y))? (y): (x))\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nconst TextureMemoryLayout::PixelFormatLayout TextureMemoryLayout::pixelFormat[NUM_PIXEL_TYPES] = {\r\n    // PIXEL_32\r\n    {   { 64, 32 },     // page size\r\n        { 8, 8 },       // block size\r\n        true       },   // adjacentBlockWidth\r\n    // PIXEL_16\r\n    {   { 64, 64 },     // page size\r\n        { 16, 8 },      // block size\r\n        false      },   // adjacentBlockWidth\r\n    // PIXEL_8\r\n    {   { 128, 64 },    // page size\r\n        { 16, 16 },     // block size\r\n        true       },   // adjacentBlockWidth\r\n    // PIXEL_4\r\n    {   { 128, 128 },   // page size\r\n        { 32, 16 },     // block size\r\n        false      },   // adjacentBlockWidth\r\n};\r\n\r\nconst int TextureMemoryLayout::blockArrangement[4][8] = {\r\n    {  0,  1,  4,  5, 16, 17, 20, 21 },\r\n    {  2,  3,  6,  7, 18, 19, 22, 23 },\r\n    {  8,  9, 12, 13, 24, 25, 28, 29 },\r\n    { 10, 11, 14, 15, 26, 27, 30, 31 }\r\n};\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nTextureMemoryLayout::TextureMemoryLayout()\r\n{\r\n    for (int i = PIXEL_32; i < NUM_PIXEL_TYPES; i++)\r\n        initMinSize(minSize[i], PixelType(i));\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nvoid\r\nTextureMemoryLayout::initMinSize(MinSizeArray& mArray, PixelType pType)\r\n{\r\n    int tw, th;\r\n\r\n    for (th = 0; th < MAX_PIXEL_SIZE_BITS; th++) {\r\n        for (tw = 0; tw < MAX_PIXEL_SIZE_BITS; tw++) {\r\n            mArray[tw][th].width = 1 << tw;\r\n            mArray[tw][th].height = 1 << th;\r\n\r\n            setMinSize(mArray[tw][th].width, mArray[tw][th].height, pType);\r\n        }\r\n    }\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nvoid\r\nTextureMemoryLayout::setMinSize(int& width, int& height, PixelType pType)\r\n{\r\n    const PixelFormatLayout &pf = pixelFormat[pType];\r\n\r\n    // All widths and heights are powers of 2\r\n\r\n    // If texture dimension is bigger than a page dimension, then\r\n    // make sure whole pages are allocated and exit.\r\n    if (width > pf.pageSize.width) {\r\n        height = Mth::Max(height, pf.pageSize.height);\r\n        return;\r\n    } else if (height > pf.pageSize.height) {\r\n        width = Mth::Max(width, pf.pageSize.width);\r\n        return;\r\n    }\r\n\r\n    // Make sure width and height are at least block size\r\n    if (width < pf.blockSize.width)\r\n        width = pf.blockSize.width;\r\n    if (height < pf.blockSize.height)\r\n        height = pf.blockSize.height;\r\n\r\n#if 0\r\n    // Now we are only dealing with sub-pages.  Make sure\r\n    // sizes don't go beyond allowable aspect ratios\r\n    \r\n    TexSize twoBlock;\r\n\r\n    if (pf.adjacentBlockWidth) {    // width\r\n        twoBlock.width = pf.blockSize.width * 2;\r\n        twoBlock.height = pf.blockSize.height;\r\n    } else {                        // height\r\n        twoBlock.width = pf.blockSize.width;\r\n        twoBlock.height = pf.blockSize.height * 2;\r\n    }\r\n#endif\r\n\r\n    // It just happens that, given a sub-page,\r\n    // the height cannot be bigger than the\r\n    // width and the width cannot be more than\r\n    // double the height\r\n    if (height > width)\r\n        width = height;\r\n    if (width > (height * 2))\r\n        height = width / 2;\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nTextureMemoryLayout::PixelType\r\nTextureMemoryLayout::modeToPixelType(int pixMode)\r\n{\r\n    switch(pixMode) {\r\n    case PSMCT32:\r\n    case PSMCT24:\r\n        return PIXEL_32;\r\n\r\n    case PSMCT16:\r\n        return PIXEL_16;\r\n\r\n    case PSMT8:\r\n        return PIXEL_8;\r\n\r\n    case PSMT4:\r\n        return PIXEL_4;\r\n\r\n    default:\r\n        Dbg_MsgAssert(0, (\"TextureMemoryLayout: PixelMode %d not supported.\", pixMode));\r\n        return PIXEL_INVALID;\r\n    }\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nvoid\r\nTextureMemoryLayout::getMinSize(int& width, int& height, int pixMode)\r\n{\r\n    PixelType pType = modeToPixelType(pixMode);\r\n\r\n    // Now get the minimum size\r\n    int tw = numBits(width) - 1;\r\n    int th = numBits(height) - 1;\r\n\r\n    width = minSize[pType][tw][th].width;\r\n    height = minSize[pType][tw][th].height;\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n// Returns size in blocks.  Must calculate the minimum width and height first.\r\nint\r\nTextureMemoryLayout::getImageSize(int width, int height, int pixMode)\r\n{\r\n    PixelType pType = modeToPixelType(pixMode);\r\n    const PixelFormatLayout &pf = pixelFormat[pType];\r\n    int bw, bh;\r\n\r\n    bw = width / pf.blockSize.width;\r\n    bh = height / pf.blockSize.height;\r\n\r\n    return bw * bh;\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nint\r\nTextureMemoryLayout::getBlockNumber(int blockX, int blockY, int pixMode)\r\n{\r\n\r\n    switch (pixMode) {\r\n    case PSMCT32:\r\n    case PSMCT24:\r\n    case PSMT8:\r\n        return blockArrangement[blockY][blockX];\r\n\r\n    case PSMCT16:\r\n    case PSMT4:\r\n        return blockArrangement[blockX][blockY];\r\n\r\n    default:\r\n        Dbg_MsgAssert(0, (\"TextureMemoryLayout: getBlockNumber %d not supported.\", pixMode));\r\n        return -1;\r\n    }\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nvoid\r\nTextureMemoryLayout::getPosFromBlockNumber(int& posX, int& posY, int blockNumber, int pixMode)\r\n{\r\n    int blockRow = -1, blockCol = -1;\r\n\r\n    for (int i = 0; i < 4; i++)\r\n        for (int j = 0; j < 8; j++)\r\n            if (blockArrangement[i][j] == blockNumber) {\r\n                blockRow = i;\r\n                blockCol = j;\r\n                break;\r\n            }\r\n\r\n    if (blockRow < 0)\r\n        Dbg_MsgAssert(0, (\"TextureMemoryLayout: getPosFromBlockNumber\"));\r\n\r\n    PixelType pType = modeToPixelType(pixMode);\r\n    const PixelFormatLayout &pf = pixelFormat[pType];\r\n\r\n    switch (pixMode) {\r\n    case PSMCT32:\r\n    case PSMCT24:\r\n    case PSMT8:\r\n        posX = blockCol * pf.blockSize.width;\r\n        posY = blockRow * pf.blockSize.height;\r\n        break;\r\n\r\n    case PSMCT16:\r\n    case PSMT4:\r\n        posX = blockRow * pf.blockSize.width;\r\n        posY = blockCol * pf.blockSize.height;\r\n        break;\r\n\r\n    default:\r\n        Dbg_MsgAssert(0, (\"TextureMemoryLayout: getPosFromBlockNumber %d not supported.\", pixMode));\r\n    }\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nint\r\nTextureMemoryLayout::getBlockOffset(int bufferWidth, int posX, int posY, int pixMode)\r\n{\r\n    int horizPages, vertPages;\r\n    int numPages = 0;\r\n    int blockNumber = 0;\r\n    \r\n    PixelType pType = modeToPixelType(pixMode);\r\n    const PixelFormatLayout &pf = pixelFormat[pType];\r\n\r\n    // First figure out how many pages are above\r\n    vertPages = posY / pf.pageSize.height;\r\n    if (vertPages) {\r\n        horizPages = bufferWidth / pf.pageSize.width;\r\n        posY -= vertPages * pf.pageSize.height;\r\n        numPages += vertPages * horizPages;\r\n    }\r\n\r\n    // Now how many are to the left\r\n    horizPages = posX / pf.pageSize.width;\r\n    if (horizPages) {\r\n        posX -= horizPages * pf.pageSize.width;\r\n        numPages += horizPages;\r\n    }\r\n\r\n    // Now figure out where we are within the page\r\n    int horizBlocks, vertBlocks;\r\n    horizBlocks = posX / pf.blockSize.width;\r\n    vertBlocks = posY / pf.blockSize.height;\r\n    blockNumber = getBlockNumber(horizBlocks, vertBlocks, pixMode);\r\n\r\n    return (numPages * 32) + blockNumber;\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nvoid\r\nTextureMemoryLayout::getPosFromBlockOffset(int& posX, int& posY, int blockOffset, int bufferWidth, int pixMode)\r\n{\r\n    int horizPages, vertPages;\r\n    \r\n    PixelType pType = modeToPixelType(pixMode);\r\n    const PixelFormatLayout &pf = pixelFormat[pType];\r\n\r\n    posX = posY = 0;\r\n\r\n    // First figure out how many pages are above\r\n    int horizPageWidth = bufferWidth / pf.pageSize.width;\r\n    if (horizPageWidth) {\r\n        vertPages = blockOffset / (horizPageWidth * 32);\r\n        if (vertPages) {\r\n            posY += vertPages * pf.pageSize.height;\r\n            blockOffset -= vertPages * horizPageWidth * 32;\r\n        }\r\n    }\r\n\r\n    // Now how many are to the left\r\n    horizPages = blockOffset / 32;\r\n    if (horizPages) {\r\n        posX += horizPages * pf.pageSize.width;\r\n        blockOffset -= horizPages * 32;\r\n    }\r\n\r\n    // Now figure out where we are within the page\r\n    int blockPosX, blockPosY;\r\n    getPosFromBlockNumber(blockPosX, blockPosY, blockOffset, pixMode);\r\n    \r\n    posX += blockPosX;\r\n    posY += blockPosY;\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nbool\r\nTextureMemoryLayout::isPageSize(int width, int height, int pixMode)\r\n{\r\n    PixelType pType = modeToPixelType(pixMode);\r\n    const PixelFormatLayout &pf = pixelFormat[pType];\r\n\r\n    return !(width % pf.pageSize.width) && !(height % pf.pageSize.height);\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nbool\r\nTextureMemoryLayout::isBlockSize(int width, int height, int pixMode)\r\n{\r\n    PixelType pType = modeToPixelType(pixMode);\r\n    const PixelFormatLayout &pf = pixelFormat[pType];\r\n\r\n    return !(width % pf.blockSize.width) && !(height % pf.blockSize.height);\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nbool\r\nTextureMemoryLayout::isMinPageSize(int width, int height, int pixMode)\r\n{\r\n    PixelType pType = modeToPixelType(pixMode);\r\n    const PixelFormatLayout &pf = pixelFormat[pType];\r\n\r\n    getMinSize(width, height, pixMode);\r\n\r\n    return (width >= pf.pageSize.width) && (height >= pf.pageSize.height);\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nbool\r\nTextureMemoryLayout::isMinBlockSize(int width, int height, int pixMode)\r\n{\r\n    PixelType pType = modeToPixelType(pixMode);\r\n    const PixelFormatLayout &pf = pixelFormat[pType];\r\n\r\n    getMinSize(width, height, pixMode);\r\n\r\n    return (width >= pf.blockSize.width) && (height >= pf.blockSize.height);\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n//\r\nint\r\nTextureMemoryLayout::numBits(unsigned int size)\r\n{\r\n    int bits = 0;\r\n\r\n    while (size > 0) {\r\n        size >>= 1;\r\n        bits++;\r\n    }\r\n\r\n    return bits;\r\n}\r\n\r\n\r\n/////////////////////////////////////////////////////////////\r\n// GS Simulator code\r\n//\r\n\r\nuint32 *p_gsmem;\r\nint gsmem_size = 0;\r\n\r\nint block16[32] =\r\n{\r\n\t 0,  2,  8, 10,\r\n\t 1,  3,  9, 11,\r\n\t 4,  6, 12, 14,\r\n\t 5,  7, 13, 15,\r\n\t16, 18, 24, 26,\r\n\t17, 19, 25, 27,\r\n\t20, 22, 28, 30,\r\n\t21, 23, 29, 31\r\n};\r\n\r\nint columnWord16[32] = \r\n{\r\n\t 0,  1,  4,  5,  8,  9, 12, 13,   0,  1,  4,  5,  8,  9, 12, 13,\r\n\t 2,  3,  6,  7, 10, 11, 14, 15,   2,  3,  6,  7, 10, 11, 14, 15\r\n};\r\n\r\nint columnHalf16[32] =\r\n{\r\n\t0, 0, 0, 0, 0, 0, 0, 0,  1, 1, 1, 1, 1, 1, 1, 1,\r\n\t0, 0, 0, 0, 0, 0, 0, 0,  1, 1, 1, 1, 1, 1, 1, 1\r\n};\r\n\r\n\r\nvoid readTexPSMCT16(int dbp, int dbw, int dsax, int dsay, int rrw, int rrh, void *data)\r\n{\r\n\t//dbw >>= 1;\r\n\tunsigned short *src = (unsigned short *)data;\r\n\tint startBlockPos = dbp * 64;\r\n\r\n\tfor(int y = dsay; y < dsay + rrh; y++)\r\n\t{\r\n\t\tint pageY = y / 64;\r\n\t\tint py = y - (pageY * 64);\r\n\t\tint blockY = py / 8;\r\n\t\tint by = py - blockY * 8;\r\n\r\n\t\tint column = by / 2;\r\n\t\tint cy = by - column * 2;\r\n\r\n\t\tfor(int x = dsax; x < dsax + rrw; x++)\r\n\t\t{\r\n\t\t\tint pageX = x / 64;\r\n\t\t\tint page  = pageX + pageY * dbw;\r\n\r\n\t\t\tint px = x - (pageX * 64);\r\n\r\n\t\t\tint blockX = px / 16;\r\n\t\t\tint block  = block16[blockX + blockY * 4];\r\n\r\n\t\t\tint bx = px - blockX * 16;\r\n\r\n\t\t\tint cx = bx;\r\n\t\t\tint cw = columnWord16[cx + cy * 16];\r\n\t\t\tint ch = columnHalf16[cx + cy * 16];\r\n\r\n\t\t\tint gs_index = startBlockPos + page * 2048 + block * 64 + column * 16 + cw;\r\n\t\t\tDbg_MsgAssert(gs_index < gsmem_size, (\"GS simulator memory size: %d; addressing: %d\", gsmem_size, gs_index));\r\n\t\t\tunsigned short *dst = (unsigned short *)&p_gsmem[gs_index];\r\n\t\t\t*src = dst[ch];\r\n\t\t\tsrc++;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nint block4[32] =\r\n{\r\n\t 0,  2,  8, 10,\r\n\t 1,  3,  9, 11,\r\n\t 4,  6, 12, 14,\r\n\t 5,  7, 13, 15,\r\n\t16, 18, 24, 26,\r\n\t17, 19, 25, 27,\r\n\t20, 22, 28, 30,\r\n\t21, 23, 29, 31\r\n};\r\n\r\nint columnWord4[2][128] =\r\n{\r\n\t{\r\n\t\t 0,  1,  4,  5,  8,  9, 12, 13,   0,  1,  4,  5,  8,  9, 12, 13,   0,  1,  4,  5,  8,  9, 12, 13,   0,  1,  4,  5,  8,  9, 12, 13,\r\n\t\t 2,  3,  6,  7, 10, 11, 14, 15,   2,  3,  6,  7, 10, 11, 14, 15,   2,  3,  6,  7, 10, 11, 14, 15,   2,  3,  6,  7, 10, 11, 14, 15,\r\n\r\n\t\t 8,  9, 12, 13,  0,  1,  4,  5,   8,  9, 12, 13,  0,  1,  4,  5,   8,  9, 12, 13,  0,  1,  4,  5,   8,  9, 12, 13,  0,  1,  4,  5,\r\n\t\t10, 11, 14, 15,  2,  3,  6,  7,  10, 11, 14, 15,  2,  3,  6,  7,  10, 11, 14, 15,  2,  3,  6,  7,  10, 11, 14, 15,  2,  3,  6,  7\r\n\t},\r\n\t{\r\n\t\t 8,  9, 12, 13,  0,  1,  4,  5,   8,  9, 12, 13,  0,  1,  4,  5,   8,  9, 12, 13,  0,  1,  4,  5,   8,  9, 12, 13,  0,  1,  4,  5,\r\n\t\t10, 11, 14, 15,  2,  3,  6,  7,  10, 11, 14, 15,  2,  3,  6,  7,  10, 11, 14, 15,  2,  3,  6,  7,  10, 11, 14, 15,  2,  3,  6,  7,\r\n\r\n\t\t 0,  1,  4,  5,  8,  9, 12, 13,   0,  1,  4,  5,  8,  9, 12, 13,   0,  1,  4,  5,  8,  9, 12, 13,   0,  1,  4,  5,  8,  9, 12, 13,\r\n\t\t 2,  3,  6,  7, 10, 11, 14, 15,   2,  3,  6,  7, 10, 11, 14, 15,   2,  3,  6,  7, 10, 11, 14, 15,   2,  3,  6,  7, 10, 11, 14, 15\r\n\t}\r\n};\r\n\r\nint columnByte4[128] =\r\n{\r\n\t0, 0, 0, 0, 0, 0, 0, 0,  2, 2, 2, 2, 2, 2, 2, 2,  4, 4, 4, 4, 4, 4, 4, 4,  6, 6, 6, 6, 6, 6, 6, 6,\r\n\t0, 0, 0, 0, 0, 0, 0, 0,  2, 2, 2, 2, 2, 2, 2, 2,  4, 4, 4, 4, 4, 4, 4, 4,  6, 6, 6, 6, 6, 6, 6, 6,\r\n\r\n\t1, 1, 1, 1, 1, 1, 1, 1,  3, 3, 3, 3, 3, 3, 3, 3,  5, 5, 5, 5, 5, 5, 5, 5,  7, 7, 7, 7, 7, 7, 7, 7,\r\n\t1, 1, 1, 1, 1, 1, 1, 1,  3, 3, 3, 3, 3, 3, 3, 3,  5, 5, 5, 5, 5, 5, 5, 5,  7, 7, 7, 7, 7, 7, 7, 7\r\n};\r\n\r\nvoid writeTexPSMT4(int dbp, int dbw, int dsax, int dsay, int rrw, int rrh, void *data)\r\n{\r\n\tdbw >>= 1;\r\n\tunsigned char *src = (unsigned char *)data;\r\n\tint startBlockPos = dbp * 64;\r\n\r\n\tbool odd = false;\r\n\r\n\tfor(int y = dsay; y < dsay + rrh; y++)\r\n\t{\r\n\t\tint pageY = y / 128;\r\n\t\tint py = y - (pageY * 128);\r\n\t\tint blockY = py / 16;\r\n\t\tint by = py - blockY * 16;\r\n\r\n\t\tint column = by / 4;\r\n\t\tint cy = by - column * 4;\r\n\r\n\t\tfor(int x = dsax; x < dsax + rrw; x++)\r\n\t\t{\r\n\t\t\tint pageX = x / 128;\r\n\t\t\tint page  = pageX + pageY * dbw;\r\n\r\n\t\t\tint px = x - (pageX * 128);\r\n\r\n\t\t\tint blockX = px / 32;\r\n\t\t\tint block  = block4[blockX + blockY * 4];\r\n\r\n\t\t\tint bx = px - blockX * 32;\r\n\r\n\t\t\tint cx = bx;\r\n\t\t\tint cw = columnWord4[column & 1][cx + cy * 32];\r\n\t\t\tint cb = columnByte4[cx + cy * 32];\r\n\r\n\t\t\tint gs_index = startBlockPos + page * 2048 + block * 64 + column * 16 + cw;\r\n\t\t\tDbg_MsgAssert(gs_index < gsmem_size, (\"GS simulator memory size: %d; addressing: %d\", gsmem_size, gs_index));\r\n\t\t\tunsigned char *dst = (unsigned char *)&p_gsmem[gs_index];\r\n\r\n\t\t\tif(cb & 1)\r\n\t\t\t{\r\n\t\t\t\tif(odd)\r\n\t\t\t\t\tdst[cb >> 1] = (dst[cb >> 1] & 0x0f) | ((*src) & 0xf0);\r\n\t\t\t\telse\r\n\t\t\t\t\tdst[cb >> 1] = (dst[cb >> 1] & 0x0f) | (((*src) << 4) & 0xf0);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif(odd)\r\n\t\t\t\t\tdst[cb >> 1] = (dst[cb >> 1] & 0xf0) | (((*src) >> 4) & 0x0f);\r\n\t\t\t\telse\r\n\t\t\t\t\tdst[cb >> 1] = (dst[cb >> 1] & 0xf0) | ((*src) & 0x0f);\r\n\t\t\t}\r\n\r\n\t\t\tif(odd)\r\n\t\t\t\tsrc++;\r\n\r\n\t\t\todd = !odd;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n// -------------------------------------------------------------------------------------------\r\n//\r\n//\r\nint TextureMemoryLayout::BlockConv4to32(u_char *p_input, u_char *p_output) {\r\n\r\n\tstatic int lut[] = {\r\n\t\t// even column\r\n\t\t0, 68, 8,  76, 16, 84, 24, 92,\r\n\t\t1, 69, 9,  77, 17, 85, 25, 93,\r\n\t\t2, 70, 10, 78, 18, 86, 26, 94,\r\n\t\t3, 71, 11, 79, 19, 87, 27, 95,\r\n\t\t4, 64, 12, 72, 20, 80, 28, 88,\r\n\t\t5, 65, 13, 73, 21, 81, 29, 89,\r\n\t\t6, 66, 14, 74, 22, 82, 30, 90,\r\n\t\t7, 67, 15, 75, 23, 83, 31, 91,\r\n\r\n\t\t32, 100, 40, 108, 48, 116, 56, 124,\r\n\t\t33, 101, 41, 109, 49, 117, 57, 125,\r\n\t\t34, 102, 42, 110, 50, 118, 58, 126,\r\n\t\t35, 103, 43, 111, 51, 119, 59, 127,\r\n\t\t36, 96,  44, 104, 52, 112, 60, 120,\r\n\t\t37, 97,  45, 105, 53, 113, 61, 121,\r\n\t\t38, 98,  46, 106, 54, 114, 62, 122,\r\n\t\t39, 99,  47, 107, 55, 115, 63, 123,\r\n\r\n\r\n\t\t// odd column\r\n\t\t4, 64, 12, 72, 20, 80, 28, 88,\r\n\t\t5, 65, 13, 73, 21, 81, 29, 89,\r\n\t\t6, 66, 14, 74, 22, 82, 30, 90,\r\n\t\t7, 67, 15, 75, 23, 83, 31, 91,\r\n\t\t0, 68, 8,  76, 16, 84, 24, 92,\r\n\t\t1, 69, 9,  77, 17, 85, 25, 93,\r\n\t\t2, 70, 10, 78, 18, 86, 26, 94,\r\n\t\t3, 71, 11, 79, 19, 87, 27, 95,\r\n\r\n\t\t36, 96,  44, 104, 52, 112, 60, 120,\r\n\t\t37, 97,  45, 105, 53, 113, 61, 121,\r\n\t\t38, 98,  46, 106, 54, 114, 62, 122,\r\n\t\t39, 99,  47, 107, 55, 115, 63, 123,\r\n\t\t32, 100, 40, 108, 48, 116, 56, 124,\r\n\t\t33, 101, 41, 109, 49, 117, 57, 125,\r\n\t\t34, 102, 42, 110, 50, 118, 58, 126,\r\n\t\t35, 103, 43, 111, 51, 119, 59, 127\r\n\t};\r\n\r\n\tunsigned int i, j, k, i0, i1, i2;\r\n\tunsigned int index0, index1;\r\n\tunsigned char c_in, c_out, *pIn;\r\n\r\n\tpIn = p_input;\r\n\r\n\t// for first step, we only think for a single block. (4bits, 32x16)\r\n\tindex1 = 0;\r\n\r\n\tfor(k = 0; k < 4; k++) {\r\n\t\tindex0 = (k % 2) * 128;\r\n\r\n\t\tfor(i = 0; i < 16; i++) {\r\n\r\n\t\t\tfor(j = 0; j < 4; j++) {\r\n\r\n\t\t\t\tc_out = 0x00;\r\n\r\n\t\t\t\t// lower 4bit.\r\n\t\t\t\ti0 = lut[index0++];\r\n\t\t\t\ti1 = i0 / 2;\r\n\t\t\t\ti2 = (i0 & 0x1) * 4;\r\n\t\t\t\tc_in = (pIn[i1] & (0x0f << i2)) >> i2;\r\n\t\t\t\tc_out = c_out | c_in;\r\n\r\n\t\t\t\t// uppper 4bit\r\n\t\t\t\ti0 = lut[index0++];\r\n\t\t\t\ti1 = i0 / 2;\r\n\t\t\t\ti2 = (i0 & 0x1) * 4;\r\n\t\t\t\tc_in = (pIn[i1] & (0x0f << i2)) >> i2;\r\n\t\t\t\tc_out = c_out | ((c_in << 4) & 0xf0);\r\n\r\n\t\t\t\tp_output[index1++] = c_out;\r\n\t\t\t}\r\n\t\t}\r\n\t\tpIn += 64;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n// -------------------------------------------------------------------------------------------\r\n//\r\n//\r\nint TextureMemoryLayout::BlockConv8to32(u_char *p_input, u_char *p_output) {\r\n\r\n\tstatic int lut[] = {\r\n\t\t// even column\r\n\t\t0, 36, 8,  44,\r\n\t\t1, 37, 9,  45,\r\n\t\t2, 38, 10, 46,\r\n\t\t3, 39, 11, 47,\r\n\t\t4, 32, 12, 40,\r\n\t\t5, 33, 13, 41,\r\n\t\t6, 34, 14, 42,\r\n\t\t7, 35, 15, 43,\r\n\r\n\t\t16, 52, 24, 60,\r\n\t\t17, 53, 25, 61,\r\n\t\t18, 54, 26, 62,\r\n\t\t19, 55, 27, 63, \r\n\t\t20, 48, 28, 56,\r\n\t\t21, 49, 29, 57,\r\n\t\t22, 50, 30, 58,\r\n\t\t23, 51, 31, 59,\r\n\r\n\t\t// odd column\r\n\t\t4, 32, 12, 40,\r\n\t\t5, 33, 13, 41,\r\n\t\t6, 34, 14, 42,\r\n\t\t7, 35, 15, 43,\r\n\t\t0, 36, 8,  44,\r\n\t\t1, 37, 9,  45,\r\n\t\t2, 38, 10, 46,\r\n\t\t3, 39, 11, 47,\r\n\r\n\t\t20, 48, 28, 56,\r\n\t\t21, 49, 29, 57,\r\n\t\t22, 50, 30, 58,\r\n\t\t23, 51, 31, 59,\r\n\t\t16, 52, 24, 60,\r\n\t\t17, 53, 25, 61,\r\n\t\t18, 54, 26, 62,\r\n\t\t19, 55, 27, 63\r\n\t};\r\n\r\n\tunsigned int i, j, k, i0;\r\n\tunsigned int index0, index1;\r\n\tunsigned char *pIn;\r\n\r\n\tpIn = p_input;\r\n\r\n\t// for first step, we only think for a single block. (4bits, 32x16)\r\n\tindex1 = 0;\r\n\r\n\tfor(k = 0; k < 4; k++) {\r\n\r\n\t\tindex0 = (k % 2) * 64;\r\n\r\n\t\tfor(i = 0; i < 16; i++) {\r\n\t\t\tfor(j = 0; j < 4; j++) {\r\n\t\t\t\ti0 = lut[index0++];\r\n\t\t\t\tp_output[index1++] = pIn[i0];\r\n\t\t\t}\r\n\t\t}\r\n\t\tpIn += 64;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n// -------------------------------------------------------------------------------\r\n// send page size 4bit texture and get each block\r\n// \r\n//\r\n//\r\n#define PSMT4_BLOCK_WIDTH 32\r\n#define PSMT4_BLOCK_HEIGHT 16\r\n\r\n#define PSMCT32_BLOCK_WIDTH 8\r\n#define PSMCT32_BLOCK_HEIGHT 8\r\n\r\nint TextureMemoryLayout::PageConv4to32(int width, int height, u_char *p_input, u_char *p_output) {\r\n\r\n\tstatic u_int block_table4[] = {\r\n\t\t0,  2,  8, 10,\r\n\t\t1,  3,  9, 11,\r\n\t\t4,  6, 12, 14,\r\n\t\t5,  7, 13, 15,\r\n\t\t16, 18, 24, 26,\r\n\t\t17, 19, 25, 27,\r\n\t\t20, 22, 28, 30,\r\n\t\t21, 23, 29, 31\r\n\t};\r\n\r\n\tstatic u_int block_table32[] = {\r\n\t\t0,  1,  4,  5, 16, 17, 20, 21,\r\n\t\t2,  3,  6,  7, 18, 19, 22, 23,\r\n\t\t8,  9, 12, 13, 24, 25, 28, 29,\r\n\t\t10, 11, 14, 15, 26, 27, 30, 31\r\n\t};\r\n\r\n\tu_int *index32_h, *index32_v, in_block_nb;\r\n\r\n\tu_char input_block[16 * 16], output_block[16 * 16];\r\n\tu_char *pi0, *pi1, *po0, *po1;\r\n\tint index0, index1, i, j, k;\r\n\tint n_width, n_height, input_page_line_size;\r\n\tint output_page_line_size;\r\n\r\n\r\n\r\n\r\n\r\n\t// --- create table for output 32bit buffer ---\r\n\tindex32_h = (u_int*) malloc(8 * 4 * sizeof(u_int));\r\n\tindex32_v = (u_int*) malloc(8 * 4 * sizeof(u_int));\r\n\tindex0 = 0;\r\n\tfor(i = 0; i < 4; i++) {\r\n\t\tfor(j = 0; j < 8; j++) {\r\n\t\t\tindex1 = block_table32[index0];\r\n\t\t\tindex32_h[index1] = j;\r\n\t\t\tindex32_v[index1] = i;\r\n\t\t\tindex0++;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\r\n\r\n\tn_width = width / 32;\r\n\tn_height = height / 16;\r\n\r\n\tmemset(input_block, 0, 16 *16);\r\n\tmemset(output_block, 0, 16 * 16);\r\n\r\n\tinput_page_line_size = 128 / 2;    // PSMT4 page width (byte)\r\n\toutput_page_line_size = 256;       // PSMCT32 page width (byte)\r\n\r\n\t// now assume copying from page top. \r\n\tfor(i = 0; i < n_height; i++) {\r\n\r\n\t\tfor(j = 0; j < n_width; j++) {\r\n\r\n\t\t\tpi0 = input_block;\r\n\t\t\tpi1 = p_input + 16 * i * input_page_line_size + j * 16;\r\n\r\n\t\t\tin_block_nb = block_table4[i * n_width + j];\r\n\r\n\t\t\tfor(k = 0; k < PSMT4_BLOCK_HEIGHT; k++) {\r\n\t\t\t\tmemcpy(pi0, pi1, PSMT4_BLOCK_WIDTH / 2); // copy full 1 line of 1 block.\r\n\t\t\t\tpi0 += PSMT4_BLOCK_WIDTH / 2;\r\n\t\t\t\tpi1 += input_page_line_size;\r\n\t\t\t}\r\n\r\n\t\t\tBlockConv4to32(input_block, output_block);\r\n\r\n\t\t\tpo0 = output_block;\r\n\t\t\tpo1 = p_output + 8 * index32_v[in_block_nb] * output_page_line_size + index32_h[in_block_nb] * 32;\r\n\t\t\tfor(k = 0; k < PSMCT32_BLOCK_HEIGHT; k++) {\r\n\t\t\t\tmemcpy(po1, po0, PSMCT32_BLOCK_WIDTH * 4);\r\n\t\t\t\tpo0 += PSMCT32_BLOCK_WIDTH * 4;\r\n\t\t\t\tpo1 += output_page_line_size;   \r\n\t\t\t}\r\n\r\n\t\t}\r\n\t}\r\n\r\n\tfree(index32_h);\r\n\tfree(index32_v);\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n// -------------------------------------------------------------------------------\r\n// send page size 8bit texture and get each block\r\n// \r\n//\r\n//\r\n#define PSMT8_BLOCK_WIDTH  16\r\n#define PSMT8_BLOCK_HEIGHT 16\r\n\r\n\r\n\r\nint TextureMemoryLayout::PageConv8to32(int width, int height, u_char *p_input, u_char *p_output) {\r\n\r\n\tstatic u_int block_table8[] = {\r\n\t\t0,  1,  4,  5, 16, 17, 20, 21,\r\n\t\t2,  3,  6,  7, 18, 19, 22, 23,\r\n\t\t8,  9, 12, 13, 24, 25, 28, 29,\r\n\t\t10, 11, 14, 15, 26, 27, 30, 31\r\n\t};\r\n\r\n\tstatic u_int block_table32[] = {\r\n\t\t0,  1,  4,  5, 16, 17, 20, 21,\r\n\t\t2,  3,  6,  7, 18, 19, 22, 23,\r\n\t\t8,  9, 12, 13, 24, 25, 28, 29,\r\n\t\t10, 11, 14, 15, 26, 27, 30, 31\r\n\t};\r\n\r\n\tu_int *index32_h, *index32_v, in_block_nb;\r\n\r\n\tu_char input_block[16 * 16], output_block[16 * 16];\r\n\tu_char *pi0, *pi1, *po0, *po1;\r\n\tint index0, index1, i, j, k;\r\n\tint n_width, n_height, input_page_line_size;\r\n\tint output_page_line_size;\r\n\r\n\r\n\r\n\t// --- create table for output 32bit buffer ---\r\n\tindex32_h = (u_int*) malloc(8 * 4 * sizeof(u_int));\r\n\tindex32_v = (u_int*) malloc(8 * 4 * sizeof(u_int));\r\n\tindex0 = 0;\r\n\tfor(i = 0; i < 4; i++) {\r\n\t\tfor(j = 0; j < 8; j++) {\r\n\t\t\tindex1 = block_table32[index0];\r\n\t\t\tindex32_h[index1] = j;\r\n\t\t\tindex32_v[index1] = i;\r\n\t\t\tindex0++;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t// how many blocks we should calc (width/height)\r\n\tn_width = width / PSMT8_BLOCK_WIDTH;\r\n\tn_height = height / PSMT8_BLOCK_HEIGHT;\r\n\r\n\tmemset(input_block, 0, 16 *16);\r\n\tmemset(output_block, 0, 16 * 16);\r\n\r\n\tinput_page_line_size  = 128;    // PSMT8 page width (byte)\r\n\toutput_page_line_size = 256;    // PSMCT32 page width (byte)\r\n\r\n\t// now assume copying from page top. \r\n\tfor(i = 0; i < n_height; i++) {\r\n\r\n\t\tfor(j = 0; j < n_width; j++) {\r\n\r\n\t\t\tpi0 = input_block;\r\n\t\t\tpi1 = p_input + PSMT8_BLOCK_HEIGHT * i * input_page_line_size + j * PSMT8_BLOCK_WIDTH; // byte\r\n\r\n\t\t\tin_block_nb = block_table8[i * n_width + j];\r\n\r\n\t\t\tfor(k = 0; k < PSMT8_BLOCK_HEIGHT; k++) {\r\n\t\t\t\tmemcpy(pi0, pi1, PSMT8_BLOCK_WIDTH); // copy full 1 line of 1 block.\r\n\t\t\t\tpi0 += PSMT8_BLOCK_WIDTH;  \r\n\t\t\t\tpi1 += input_page_line_size;\r\n\t\t\t}\r\n\r\n\t\t\tBlockConv8to32(input_block, output_block);\r\n\r\n\t\t\tpo0 = output_block;\r\n\t\t\tpo1 = p_output + 8 * index32_v[in_block_nb] * output_page_line_size + index32_h[in_block_nb] * 32;\r\n\t\t\tfor(k = 0; k < PSMCT32_BLOCK_HEIGHT; k++) {\r\n\t\t\t\tmemcpy(po1, po0, PSMCT32_BLOCK_WIDTH * 4);\r\n\t\t\t\tpo0 += PSMCT32_BLOCK_WIDTH * 4;\r\n\t\t\t\tpo1 += output_page_line_size;   \r\n\t\t\t}\r\n\r\n\t\t}\r\n\t}\r\n\r\n\tfree(index32_h);\r\n\tfree(index32_v);\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n// -------------------------------------------------------------\r\n//\r\n//\r\n\r\n#define PSMT4_PAGE_WIDTH    128\r\n#define PSMT4_PAGE_HEIGHT   128\r\n#define PSMCT32_PAGE_WIDTH  64\r\n#define PSMCT32_PAGE_HEIGHT 32\r\n\r\nstatic bool sCanConvert4to32[10][10] =\r\n{\r\n#if 1\t// This one only allows for dimensions that are easy to calculate the 32-bit dimensions\r\n\t//  1      2      4      8     16     32     64     128    256    512\r\n\t{ false, false, false, false, false, false, false, false, false, false },\t// 1\r\n\t{ false, false, false, false, false, false, false, false, false, false },\t// 2\r\n\t{ false, false, false, false, false, false, false, false, false, false },\t// 4\r\n\t{ false, false, false, false, false, false , false, false, false, false },\t// 8\r\n\t{ false, false, false, false, false, false , false, false, false, false },\t// 16\r\n\t{ false, false, false, false, false, true , false, false, false, false },\t// 32\r\n\t{ false, false, false, false, false, false, true , false, false, false },\t// 64\r\n\t{ false, false, false, false, false, false, false, true , true , true  },\t// 128\r\n\t{ false, false, false, false, false, false, false, true , true , true  },\t// 256\r\n\t{ false, false, false, false, false, false, false, true , true , true  },\t// 512\r\n#else\r\n\t//  1      2      4      8     16     32     64     128    256    512\r\n\t{ false, false, false, false, false, false, false, false, false, false },\t// 1\r\n\t{ false, false, false, false, false, false, false, false, false, false },\t// 2\r\n\t{ false, false, false, false, false, false, false, false, false, false },\t// 4\r\n\t{ false, false, false, false, false, true , false, false, false, false },\t// 8\r\n\t{ false, false, false, false, false, true , false, false, false, false },\t// 16\r\n\t{ false, false, false, false, false, true , true , false, false, false },\t// 32\r\n\t{ false, false, false, false, false, true , true , true , false, false },\t// 64\r\n\t{ false, false, false, false, false, false, true , true , true , true  },\t// 128\r\n\t{ false, false, false, false, false, false, false, true , true , true  },\t// 256\r\n\t{ false, false, false, false, false, false, false, true , true , true  },\t// 512\r\n#endif\r\n};\r\n\r\nbool TextureMemoryLayout::CanConv4to32(int width, int height)\r\n{\r\n    int tw = numBits(width) - 1;\r\n    int th = numBits(height) - 1;\r\n\r\n\treturn sCanConvert4to32[th][tw];\r\n}\r\n\r\nbool TextureMemoryLayout::Conv4to32(int width, int height, u_char *p_input, u_char *p_output) {\r\n\r\n\r\n\tint i, j, k;\r\n\tint n_page_h, n_page_w, n_page4_width_byte, n_page32_width_byte;\r\n\tu_char *pi0, *pi1, *po0, *po1;\r\n\tint n_input_width_byte, n_output_width_byte, n_input_height, n_output_height;\r\n\tu_char input_page[PSMT4_PAGE_WIDTH / 2 * PSMT4_PAGE_HEIGHT];\r\n\tu_char output_page[PSMCT32_PAGE_WIDTH * 4 * PSMCT32_PAGE_HEIGHT];\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tint output_buffer_size = width * height / 2;\r\n\t#endif\r\n\r\n\t// ----- check width -----\r\n\tfor(i = 0; i < 11; i++) {\r\n\t\tif(width == (0x400 >> i)) break;\r\n\t}\r\n\tif(i == 11) {\r\n\t\tfprintf(stderr, \"Error : width is not 2^n\\n\");\r\n\t\treturn false;\r\n\t}\r\n\r\n\t//printf(\"input_page: %d\\n\", PSMT4_PAGE_WIDTH / 2 * PSMT4_PAGE_HEIGHT);\r\n\t//printf(\"output_page: %d\\n\", PSMCT32_PAGE_WIDTH * 4 * PSMCT32_PAGE_HEIGHT);\r\n\r\n\tmemset(input_page, 0, PSMT4_PAGE_WIDTH / 2 * PSMT4_PAGE_HEIGHT);\r\n\tmemset(output_page, 0, PSMCT32_PAGE_WIDTH * 4 * PSMCT32_PAGE_HEIGHT);\r\n\r\n\t// ----- check height -----\r\n\tfor(i = 0; i < 11; i++) {\r\n\t\tif(height == (0x400 >> i)) break;\r\n\t}\r\n\tif(i == 11) {\r\n\t\tfprintf(stderr, \"Error : width is not 2^n\\n\");\r\n\t\treturn false;\r\n\t}\r\n\r\n\r\n\tn_page_w = (width - 1) / PSMT4_PAGE_WIDTH + 1;\r\n\tn_page_h = (height - 1) / PSMT4_PAGE_HEIGHT + 1;\r\n\r\n\tn_page4_width_byte = PSMT4_PAGE_WIDTH / 2;\r\n\tn_page32_width_byte = PSMCT32_PAGE_WIDTH * 4;\r\n\r\n\t//printf(\"n_page_w : %d\\n\", n_page_w );\r\n\t//printf(\"n_page_h : %d\\n\", n_page_h );\r\n\r\n\t//printf(\"n_page4_width_byte : %d\\n\", n_page4_width_byte );\r\n\t//printf(\"n_page32_width_byte : %d\\n\", n_page32_width_byte );\r\n\r\n\r\n\t// --- set in/out buffer size (for image smaller than one page) ---\r\n\tif(n_page_w == 1) {\r\n\t\tn_input_width_byte = width / 2;\r\n\t\tn_output_height = width / 4;\r\n\t} else {\r\n\t\tn_input_width_byte = n_page4_width_byte;\r\n\t\tn_output_height = PSMCT32_PAGE_HEIGHT;\r\n\t}\r\n\r\n\tif(n_page_h == 1) {\r\n\t\tn_input_height = height;\r\n\t\tn_output_width_byte = height * 2;\r\n\t} else {\r\n\t\tn_input_height = PSMT4_PAGE_HEIGHT;\r\n\t\tn_output_width_byte = n_page32_width_byte;\r\n\t}\r\n\r\n\r\n\tfor(i = 0; i < n_page_h; i++) {\r\n\t\tfor(j = 0; j < n_page_w; j++) {\r\n\t\t\tpi0 = p_input + (n_input_width_byte * PSMT4_PAGE_HEIGHT) * n_page_w * i \r\n\t\t\t\t+ n_input_width_byte * j;\r\n\t\t\tpi1 = input_page;\r\n\r\n\t\t\tfor(k = 0; k < n_input_height; k++) {\r\n\t\t\t\tmemcpy(pi1, pi0, n_input_width_byte);\r\n\t\t\t\tpi0 += n_input_width_byte * n_page_w;\r\n\t\t\t\tpi1 += n_page4_width_byte;\r\n\t\t\t}\r\n\r\n\t\t\tPageConv4to32(PSMT4_PAGE_WIDTH, PSMT4_PAGE_HEIGHT, input_page, output_page);\r\n\r\n\t\t\tpo0 = p_output + (n_output_width_byte * PSMCT32_PAGE_HEIGHT) * n_page_w * i\r\n\t\t\t\t+ n_output_width_byte * j;\r\n\t\t\tpo1 = output_page;\r\n\t\t\tfor(k = 0; k < n_output_height; k++) {\r\n\t\t\t\tDbg_MsgAssert(((int) (po0 - p_output) + n_output_width_byte) <= output_buffer_size, (\"Went outside output buffer for texture of size (%d, %d)\", width, height));\r\n\t\t\t\tmemcpy(po0, po1, n_output_width_byte);\r\n\t\t\t\tpo0 += n_output_width_byte * n_page_w;\r\n\t\t\t\tpo1 += n_page32_width_byte;\r\n\t\t\t}          \r\n\t\t}\r\n\t}\r\n\r\n\treturn CanConv4to32(width, height);\r\n}\r\n\r\n\r\n// -------------------------------------------------------------\r\n//\r\n//\r\n\r\n#define PSMT8_PAGE_WIDTH    128\r\n#define PSMT8_PAGE_HEIGHT   64\r\n\r\nstatic bool sCanConvert8to32[10][10] =\r\n{\r\n\t//  1      2      4      8     16     32     64     128    256    512\r\n\t{ false, false, false, false, false, false, false, false, false, false },\t// 1\r\n\t{ false, false, false, false, false, false, false, false, false, false },\t// 2\r\n\t{ false, false, false, false, true , true , true , true , true , false },\t// 4\r\n\t{ false, false, false, false, true , true , true , true , true , false },\t// 8\r\n\t{ false, false, false, false, true , true , true , true , true , false },\t// 16\r\n\t{ false, false, false, false, true , true , true , true , true , false },\t// 32\r\n\t{ false, false, false, false, true , true , true , true , true , true  },\t// 64\r\n\t{ false, false, false, false, false, false, false, true , true , true  },\t// 128\r\n\t{ false, false, false, false, false, false, false, true , true , true  },\t// 256\r\n\t{ false, false, false, false, false, false, false, true , true , false },\t// 512\r\n};\r\n\r\nbool TextureMemoryLayout::CanConv8to32(int width, int height)\r\n{\r\n    int tw = numBits(width) - 1;\r\n    int th = numBits(height) - 1;\r\n\r\n\treturn sCanConvert8to32[th][tw];\r\n}\r\n\r\nbool TextureMemoryLayout::Conv8to32(int width, int height, u_char *p_input, u_char *p_output) {\r\n\r\n\tint i, j, k;\r\n\tint n_page_h, n_page_w, n_page8_width_byte, n_page32_width_byte;\r\n\tint n_input_width_byte, n_output_width_byte, n_input_height, n_output_height;\r\n\tu_char *pi0, *pi1, *po0, *po1;\r\n\tu_char input_page[PSMT8_PAGE_WIDTH * PSMT8_PAGE_HEIGHT];\r\n\tu_char output_page[PSMCT32_PAGE_WIDTH * 4 * PSMCT32_PAGE_HEIGHT];\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tint output_buffer_size = width * height;\r\n\t#endif\r\n\t\r\n\t// ----- check width -----\r\n\tfor(i = 0; i < 11; i++) {\r\n\t\tif(width == (0x400 >> i)) break;\r\n\t}\r\n\tif(i == 11) {\r\n\t\tfprintf(stderr, \"Error : width is not 2^n\\n\");\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// ----- check height -----\r\n\tfor(i = 0; i < 11; i++) {\r\n\t\tif(height == (0x400 >> i)) break;\r\n\t}\r\n\tif(i == 11) {\r\n\t\tfprintf(stderr, \"Error : width is not 2^n\\n\");\r\n\t\treturn false;\r\n\t}\r\n\r\n\tmemset(input_page, 0, PSMT8_PAGE_WIDTH * PSMT8_PAGE_HEIGHT);\r\n\tmemset(output_page, 0, PSMCT32_PAGE_WIDTH * 4 * PSMCT32_PAGE_HEIGHT);\r\n\r\n\tn_page_w = (width - 1) / PSMT8_PAGE_WIDTH + 1;\r\n\tn_page_h = (height - 1) / PSMT8_PAGE_HEIGHT + 1;\r\n\r\n\tn_page8_width_byte = PSMT8_PAGE_WIDTH;\r\n\tn_page32_width_byte = PSMCT32_PAGE_WIDTH * 4;\r\n\r\n\t// --- set in/out buffer size (for image smaller than one page) ---\r\n\tif(n_page_w == 1) {\r\n\t\tn_input_width_byte = width;\r\n\t\tn_output_width_byte = width * 2;\r\n\t} else {\r\n\t\tn_input_width_byte = n_page8_width_byte;\r\n\t\tn_output_width_byte = n_page32_width_byte;\r\n\t}\r\n\r\n\tif(n_page_h == 1) {\r\n\t\tn_input_height = height;\r\n\t\tn_output_height = height / 2;\r\n\t} else {\r\n\t\tn_input_height = PSMT8_PAGE_HEIGHT;\r\n\t\tn_output_height = PSMCT32_PAGE_HEIGHT;\r\n\t}\r\n\r\n\t// --- conversion ---\r\n\tfor(i = 0; i < n_page_h; i++) {\r\n\t\tfor(j = 0; j < n_page_w; j++) {\r\n\t\t\tpi0 = p_input + (n_input_width_byte * PSMT8_PAGE_HEIGHT) * n_page_w * i \r\n\t\t\t\t+ n_input_width_byte * j;\r\n\t\t\tpi1 = input_page;\r\n\r\n\t\t\tfor(k = 0; k < n_input_height; k++) {\r\n\t\t\t\tmemcpy(pi1, pi0, n_input_width_byte);\r\n\t\t\t\tpi0 += n_input_width_byte * n_page_w;\r\n\t\t\t\tpi1 += n_page8_width_byte;\r\n\t\t\t}\r\n\r\n\t\t\t// --- convert a page ---\r\n\t\t\tPageConv8to32(PSMT8_PAGE_WIDTH, PSMT8_PAGE_HEIGHT, input_page, output_page);\r\n\r\n\t\t\tpo0 = p_output + (n_output_width_byte * n_output_height) * n_page_w * i\r\n\t\t\t\t+ n_output_width_byte * j;\r\n\t\t\tpo1 = output_page;\r\n\t\t\tfor(k = 0; k < n_output_height; k++) {\r\n\t\t\t\tDbg_MsgAssert(((int) (po0 - p_output) + n_output_width_byte) <= output_buffer_size, (\"Went outside output buffer for texture of size (%d, %d)\", width, height));\r\n\t\t\t\tmemcpy(po0, po1, n_output_width_byte);\r\n\t\t\t\tpo0 += n_output_width_byte * n_page_w;\r\n\t\t\t\tpo1 += n_page32_width_byte;\r\n\t\t\t}          \r\n\t\t}\r\n\t}\r\n\r\n\treturn CanConv4to16(width, height);\r\n}\r\n\r\n// -------------------------------------------------------------\r\n//\r\n//\r\n\r\nstatic bool sCanConvert4to16[10][10] =\r\n{\r\n\t//  1      2      4      8     16     32     64     128    256    512\r\n\t{ false, false, false, false, false, false, false, false, false, false },\t// 1\r\n\t{ false, false, false, false, false, false, false, false, false, false },\t// 2\r\n\t{ false, false, false, false, false, false, false, false, false, false },\t// 4\r\n\t{ false, false, false, false, true , true , true , true , true , false },\t// 8\r\n\t{ false, false, false, false, true , true , true , true , true , false },\t// 16\r\n\t{ false, false, false, false, true , true , true , true , true , false },\t// 32\r\n\t{ false, false, false, false, true , true , true , true , true , false },\t// 64\r\n\t{ false, false, false, false, true , true , true , true , true , true  },\t// 128\r\n\t{ false, false, false, false, false, false, false, true , true , true  },\t// 256\r\n\t{ false, false, false, false, false, false, false, true , true , true  },\t// 512\r\n};\r\n\r\nbool TextureMemoryLayout::CanConv4to16(int width, int height)\r\n{\r\n    int tw = numBits(width) - 1;\r\n    int th = numBits(height) - 1;\r\n\r\n\treturn sCanConvert4to16[th][tw];\r\n}\r\n\r\nbool TextureMemoryLayout::Conv4to16(int width, int height, u_char *p_input, u_char *p_output) {\r\n\r\n\r\n\tint i;\r\n\r\n\t// ----- check width -----\r\n\tfor(i = 0; i < 11; i++) {\r\n\t\tif(width == (0x400 >> i)) break;\r\n\t}\r\n\tif(i == 11) {\r\n\t\tfprintf(stderr, \"Error : width is not 2^n\\n\");\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// ----- check height -----\r\n\tfor(i = 0; i < 11; i++) {\r\n\t\tif(height == (0x400 >> i)) break;\r\n\t}\r\n\tif(i == 11) {\r\n\t\tfprintf(stderr, \"Error : width is not 2^n\\n\");\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// Find size needed for buffers\r\n\tint min_4_width = width;\r\n\tint min_4_height = height;\r\n\tint min_16_width = width / 2;\r\n\tint min_16_height = height / 2;\r\n\tgetMinSize(min_4_width, min_4_height, PSMT4);\r\n\tgetMinSize(min_16_width, min_16_height, PSMCT16);\r\n\r\n\tint blocks_needed = max(getImageSize(min_4_width, min_4_height, PSMT4), getImageSize(min_16_width, min_16_height, PSMCT16));\r\n\tint words_needed = blocks_needed * 64;\r\n\r\n\t// Allocate memory\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tp_gsmem = new uint32[words_needed];\r\n\tgsmem_size = words_needed;\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Swizzle through GS simulator code\r\n\twriteTexPSMT4(0, max(width / 128, 1) * 2, 0, 0, width, height, p_input);\r\n\treadTexPSMCT16(0, max(width / 2 / 128, 1) * 2, 0, 0, width / 2, height / 2, p_output);\r\n\r\n\t// Free memory\r\n\tdelete [] p_gsmem;\r\n\tp_gsmem = NULL;\r\n\tgsmem_size = 0;\r\n\r\n\treturn CanConv4to16(width, height);\r\n}\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/texturemem.h",
    "content": "#ifndef __TEXTUREMEM_H\r\n#define __TEXTUREMEM_H\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nclass TextureMemoryLayout {\r\npublic:\r\n\r\n    ///\r\n    enum {\r\n        MAX_PIXEL_SIZE_BITS = 10\r\n    };\r\n\r\n    \r\n    /// PIXEL_16S won't work with the algorithms here because\r\n    /// of it's wierd layout.  Hopefully we won't need it.\r\n    \r\n    /// Pixel type.  Will add more types later when needed.\r\n    enum PixelType {\r\n        PIXEL_INVALID = -1,\r\n        PIXEL_32 = 0,       // Covers 32 and 24 bit\r\n        PIXEL_16,\r\n        PIXEL_8,\r\n        PIXEL_4,\r\n        NUM_PIXEL_TYPES\r\n    };\r\n    \r\n    ///\r\n    struct TexSize {\r\n        int width;\r\n        int height;\r\n    };\r\n\r\n    ///\r\n    struct PixelFormatLayout {\r\n        TexSize pageSize;\r\n        TexSize blockSize;\r\n        \r\n        bool adjacentBlockWidth;  // if not width, then height\r\n    };\r\n\r\n    ///\r\n    typedef TexSize MinSizeArray[MAX_PIXEL_SIZE_BITS][MAX_PIXEL_SIZE_BITS];\r\n    \r\n    ///\r\n    TextureMemoryLayout();\r\n\r\n    ///\r\n    void getMinSize(int& width, int& height, int pixMode);\r\n    ///\r\n    int getImageSize(int width, int height, int pixMode);\r\n    ///\r\n    int getBlockNumber(int blockX, int blockY, int pixMode);\r\n    ///\r\n    int getBlockOffset(int bufferWidth, int posX, int posY, int pixMode);\r\n    ///\r\n    void getPosFromBlockNumber(int& posX, int& posY, int blockNumber, int pixMode);\r\n    ///\r\n    void getPosFromBlockOffset(int& posX, int& posY, int blockOffset, int bufferWidth, int pixMode);\r\n    ///\r\n    bool isPageSize(int width, int height, int pixMode);\r\n    ///\r\n    bool isBlockSize(int width, int height, int pixMode);\r\n    ///\r\n    bool isMinPageSize(int width, int height, int pixMode);\r\n    ///\r\n    bool isMinBlockSize(int width, int height, int pixMode);\r\n\r\n\t// Converts memory layout (not format)\r\n    int BlockConv4to32(uint8 *p_input, uint8 *p_output);\r\n\tint BlockConv8to32(uint8 *p_input, uint8 *p_output);\r\n\tint PageConv4to32(int width, int height, uint8 *p_input, uint8 *p_output);\r\n\tint PageConv8to32(int width, int height, uint8 *p_input, uint8 *p_output);\r\n\tbool Conv4to32(int width, int height, uint8 *p_input, uint8 *p_output);\r\n\tbool Conv8to32(int width, int height, uint8 *p_input, uint8 *p_output);\r\n\tbool Conv4to16(int width, int height, uint8 *p_input, uint8 *p_output);\r\n\r\n\tbool CanConv4to32(int width, int height);\r\n\tbool CanConv8to32(int width, int height);\r\n\tbool CanConv4to16(int width, int height);\r\n\r\n    ///\r\n    static int numBits(unsigned int size);\r\n    ///\r\n    static PixelType modeToPixelType(int pMode);\r\n\r\nprivate:\r\n    ///\r\n    MinSizeArray minSize[NUM_PIXEL_TYPES];\r\n\r\n    ///\r\n    static const PixelFormatLayout pixelFormat[NUM_PIXEL_TYPES];\r\n    ///\r\n    static const int blockArrangement[4][8];\r\n\r\n    ///\r\n    void initMinSize(MinSizeArray& mArray, PixelType pType);\r\n    ///\r\n    void setMinSize(int& width, int& height, PixelType pType);\r\n\r\n};\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n#endif // __TEXTUREMEM_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/types.h",
    "content": "#ifndef __TYPES_H\r\n#define __TYPES_H\r\n\r\ntypedef unsigned int \tuint;\r\ntypedef unsigned long\tuint64;\r\ntypedef unsigned int\tuint32;\r\ntypedef unsigned short\tuint16;\r\ntypedef unsigned char\tuint8;\r\n\r\ntypedef signed int \t\tsint;\r\ntypedef signed long\t\tsint64;\r\ntypedef signed int\t\tsint32;\r\ntypedef signed short\tsint16;\r\ntypedef signed char\t\tsint8;\r\n\r\n#endif // __TYPES_H\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vif.cpp",
    "content": "#include <core/defines.h>\r\n#include <stdio.h>\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\nuint8 *vif::NextCode(uint8 *pVifcode)\r\n{\r\n\tif ((pVifcode[3] & 0x60) != 0x60)\r\n\t{\r\n\t\tswitch (pVifcode[3] & 0x7F)\r\n\t\t{\r\n\t\tcase 0x00:\t// NOP\r\n\t\tcase 0x02:\t// OFFSET\r\n\t\tcase 0x03:\t// BASE\r\n\t\tcase 0x04:\t// ITOP\r\n\t\tcase 0x05:\t// STMOD\r\n\t\tcase 0x06:\t// MSKPATH3\r\n\t\tcase 0x07:\t// MARK\r\n\t\tcase 0x10:\t// FLUSHE\r\n\t\tcase 0x11:\t// FLUSH\r\n\t\tcase 0x13:\t// FLUSHA\r\n\t\tcase 0x14:\t// MSCAL\r\n\t\tcase 0x15:\t// MSCALF\r\n\t\tcase 0x17:\t// MSCNT\r\n\t\t\treturn pVifcode + 4;\r\n\r\n\t\tcase 0x01:\t// STCYCL\r\n\t\t\tvif::CL = pVifcode[0];\r\n\t\t\tvif::WL = pVifcode[1];\r\n\t\t\treturn pVifcode + 4;\r\n\r\n\t\tcase 0x20:\t// STMASK\r\n\t\t\treturn pVifcode + 8;\r\n\r\n\t\tcase 0x30:\t// STROW\r\n\t\tcase 0x31:\t// STCOL\r\n\t\t\treturn pVifcode + 20;\r\n\r\n\t\tcase 0x4A:\t// MPG\r\n\t\t\treturn pVifcode + (pVifcode[2] << 3) + 4;\r\n\r\n\t\tcase 0x50:\t// DIRECT\r\n\t\tcase 0x51:\t// DIRECTHL\r\n\t\t\treturn pVifcode + (((uint16 *)pVifcode)[0] << 4) + 4;\r\n\r\n\t\tdefault:\t// undefined vifcode\r\n\t\t\treturn pVifcode;\r\n\t\t}\r\n\t}\r\n\telse\t\t\t// UNPACK\r\n\t{\r\n\t\tuint vn = (pVifcode[3] >> 2) & 3;\r\n\t\tuint vl = pVifcode[3] & 3;\r\n\t\tuint num = pVifcode[2];\r\n\t\tuint dimension = vn+1;\r\n\t\tuint bitlength = 32>>vl;\r\n\t\tif (vif::WL <= vif::CL)\r\n\t\t{\r\n\t\t\treturn pVifcode + 4 + (((bitlength * dimension * num + 31) >> 5) << 2);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tuint rem = num % vif::WL;\r\n\t\t\tuint n = vif::CL * (num/vif::WL) + (rem > vif::CL ? vif::CL : rem);\r\n\t\t\treturn pVifcode + 4 + (((bitlength * dimension * n + 31) >> 5) << 2);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n//--------------------------------\r\n//\t\tS T A T I C   D A T A\r\n//--------------------------------\r\n\r\nuint  vif::UnpackSize;\r\nuint  vif::CycleLength;\r\nuint  vif::BitLength;\r\nuint  vif::Dimension;\r\nuint8 *vif::pVifCode;\r\nuint  vif::WL;\r\nuint  vif::CL;\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vif.h",
    "content": "#ifndef __VIF_H\r\n#define __VIF_H\r\n\r\n#include \"dma.h\"\r\n#include \"vu1.h\"\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n// VIF1_MODE settings\r\n#define NORMAL_MODE\t\t0\r\n#define OFFSET_MODE\t\t1\r\n#define DIFFERENCE_MODE\t2\r\n\r\n// unpack formats\r\n#define\tS_32\t0x0\r\n#define\tS_16\t0x1\r\n#define\tS_8\t\t0x2\r\n#define\tV2_32\t0x4\r\n#define\tV2_16\t0x5\r\n#define\tV2_8\t0x6\r\n#define\tV3_32\t0x8\r\n#define\tV3_16\t0x9\r\n#define\tV3_8\t0xA\r\n#define\tV4_32\t0xC\r\n#define\tV4_16\t0xD\r\n#define\tV4_8\t0xE\r\n#define\tV4_5\t0xF\r\n\r\n// unpack FLG values\r\n#define\tABS\t0\r\n#define REL 1\r\n\r\n// unpack USN values\r\n#define SIGNED\t\t0\r\n#define UNSIGNED\t1\r\n\r\n\r\n\r\nclass vif\r\n{\r\n\r\npublic:\r\n\r\n\t//------------------------------------------\r\n\t//\t\tS T A T I C   F U N C T I O N S\r\n\t//------------------------------------------\r\n\r\n\t// vifcodes\r\n\tstatic void Code(uint8 CMD, uint8 NUM, uint16 IMMEDIATE);\r\n\tstatic void BASE(uint16 BASE);\r\n\tstatic void DIRECT(uint16 SIZE);\r\n\tstatic void DIRECTHL(uint16 SIZE);\r\n\tstatic void FLUSH(void);\r\n\tstatic void FLUSHA(void);\r\n\tstatic void FLUSHE(void);\r\n\tstatic void ITOP(uint16 ADDR);\r\n\tstatic void MARK(uint16 MARK);\r\n\tstatic void MPG(uint8 SIZE, uint16 LOADADDR);\r\n\tstatic void MSCAL(uint16 EXECADDR);\r\n\tstatic void MSCALF(uint16 EXECADDR);\r\n\tstatic void MSCNT(void);\r\n\tstatic void MSKPATH3(uint16 MASK);\r\n\tstatic void NOP(void);\r\n\tstatic void NOPi(void);\r\n\tstatic void OFFSET(uint16 OFFSET);\r\n\tstatic void STCOL(uint32 C0, uint32 C1, uint32 C2, uint32 C3);\r\n\tstatic void STCYCL(uint16 WL, uint16 CL);\r\n\tstatic void STMASK(uint32 MASK);\r\n\tstatic void STMOD(uint16 MODE);\r\n\tstatic void STROW(uint32 R0, uint32 R1, uint32 R2, uint32 R3);\r\n\tstatic void UNPACK(uint8 m, uint8 vnvl, uint8 SIZE, uint16 FLG, uint16 USN, uint16 ADDR);\r\n\r\n\t// vifcodes, begin-end style\r\n\tstatic void BeginDIRECT(void);\r\n\tstatic void EndDIRECT(void);\r\n\tstatic void BeginDIRECTHL(void);\r\n\tstatic void EndDIRECTHL(void);\r\n\tstatic void BeginMPG(uint16 LOADADDR);\r\n\tstatic void EndMPG(void);\r\n\tstatic void BeginUNPACK(uint8 m, uint8 vnvl, uint16 FLG, uint16 USN, uint16 ADDR);\r\n\tstatic void EndUNPACK(void);\r\n\r\n\t// storing data for various unpack formats\r\n\tstatic void StoreS_32(uint32 x);\r\n\tstatic void StoreS_16(uint16 x);\r\n\tstatic void StoreS_8(uint8 x);\r\n\tstatic void StoreV2_32(uint32 x, uint32 y);\r\n\tstatic void StoreV2_16(uint16 x, uint16 y);\r\n\tstatic void StoreV2_8(uint8 x, uint8 y);\r\n\tstatic void StoreV3_32(uint32 x, uint32 y, uint32 z);\r\n\tstatic void StoreV3_16(uint16 x, uint16 y, uint16 z);\r\n\tstatic void StoreV3_8(uint8 x, uint8 y, uint8 z);\r\n\tstatic void StoreV4_32F(float x, float y, float z, float w);\r\n\tstatic void StoreV4_32(sint32 x, sint32 y, sint32 z, sint32 w);\r\n\tstatic void StoreV4_16(sint16 x, sint16 y, sint16 z, sint16 w);\r\n\tstatic void StoreV4_8(sint8 x, sint8 y, sint8 z, sint8 w);\r\n\tstatic void StoreV4_5(uint8 R, uint8 G, uint8 B, uint8 A);\r\n\r\n\t// vifcode parsing\r\n\tstatic uint8 *vif::NextCode(uint8 *pVifcode);\r\n\r\n\r\n\t//--------------------------------\r\n\t//\t\tS T A T I C   D A T A\r\n\t//--------------------------------\r\n\r\n\tstatic uint  UnpackSize;\r\n\tstatic uint  CycleLength;\r\n\tstatic uint  BitLength;\r\n\tstatic uint  Dimension;\r\n\tstatic uint8 *pVifCode;\r\n\tstatic uint  WL;\r\n\tstatic uint  CL;\r\n\r\n\r\n}; // class vif\r\n\r\n\r\n\r\n//--------------------------\r\n//\t\tV I F C O D E S\r\n//--------------------------\r\n\r\n\r\n\r\n// generic vifcode\r\n//\r\n//\t 31   24 23   16 15            0\r\n//\tĿ\r\n//\t  CMD    NUM     IMMEDIATE   \r\n//\t\r\n\r\n\r\ninline void vif::Code(uint8 CMD, uint8 NUM, uint16 IMMEDIATE)\r\n{\r\n\tdma::Store32((uint32)CMD<<24 | (uint32)NUM<<16 | (uint32)IMMEDIATE);\r\n}\r\n\r\n\r\n\r\n// Sets VIF1_BASE to lower 10 bits of BASE.\r\n\r\ninline void vif::BASE(uint16 BASE)\r\n{\r\n\tvif::Code(0x03, 0, BASE);\r\n}\r\n\r\n\r\n\r\n// Transfers SIZE 128-bit data via PATH2.\r\n\r\ninline void vif::DIRECT(uint16 SIZE)\r\n{\r\n\tvif::Code(0x50, 0, SIZE);\r\n}\r\n\r\n\r\n\r\n// Transfers SIZE 128-bit data via PATH2, stalling till PATH3 IMAGE mode transfer is complete.\r\n\r\ninline void vif::DIRECTHL(uint16 SIZE)\r\n{\r\n\tvif::Code(0x51, 0, SIZE);\r\n}\r\n\r\n\r\n\r\n// Waits for PATH1/PATH2 transfers to end, after VU1 microprogram has ended.\r\n\r\ninline void vif::FLUSH(void)\r\n{\r\n\tvif::Code(0x11, 0, 0);\r\n}\r\n\r\n\r\n\r\n// Waits till no PATH3 transfer request, after the end of VU1 microprogram and PATH1/PATH2 transfer.\r\n\r\ninline void vif::FLUSHA(void)\r\n{\r\n\tvif::Code(0x13, 0, 0);\r\n}\r\n\r\n\r\n\r\n// Waits for VU0/VU1 microprogram to end.\r\n\r\ninline void vif::FLUSHE(void)\r\n{\r\n\tvif::Code(0x10, 0, 0);\r\n}\r\n\r\n\r\n\r\n// Sets VIFn_ITOPS to lower to bits of ADDR.\r\n\r\ninline void vif::ITOP(uint16 ADDR)\r\n{\r\n\tvif::Code(0x04, 0, ADDR);\r\n}\r\n\r\n\r\n\r\n// Sets VIFn_MARK to MARK.\r\n\r\ninline void vif::MARK(uint16 MARK)\r\n{\r\n\tvif::Code(0x07, 0, MARK);\r\n}\r\n\r\n\r\n\r\n// Waits for end of microprogram and transfers SIZE 64-bit data to MicroMem address LOADADDR (low 11 bits).\r\n\r\ninline void vif::MPG(uint8 SIZE, uint16 LOADADDR)\r\n{\r\n\tvif::Code(0x4A, SIZE, LOADADDR);\r\n}\r\n\r\n\r\n\r\n// Waits for end of microprogram, and activates microprogram at address EXECADDR (low 11 bits).\r\n\r\ninline void vif::MSCAL(uint16 EXECADDR)\r\n{\r\n\tvif::Code(0x14, 0, EXECADDR);\r\n\tvu1::Buffer = vu1::Loc;\r\n}\r\n\r\n\r\n\r\n// Waits for end of bot microprogram and PATH1/PATH2 transfers,\r\n// and activates microprogram at address EXECADDR (low 11 bits).\r\n\r\ninline void vif::MSCALF(uint16 EXECADDR)\r\n{\r\n\tvif::Code(0x15, 0, EXECADDR);\r\n}\r\n\r\n\r\n\r\n// Waits for end of microprogram, and activates microprogram at address held in PC.\r\n\r\ninline void vif::MSCNT(void)\r\n{\r\n\tvif::Code(0x17, 0, 0);\r\n}\r\n\r\n\r\n\r\n// MASK==1 => disables transfer via PATH3.\r\n\r\ninline void vif::MSKPATH3(uint16 MASK)\r\n{\r\n\tvif::Code(0x06, 0, MASK<<15);\r\n}\r\n\r\n\r\n\r\n// Does nothing.\r\n\r\ninline void vif::NOP(void)\r\n{\r\n\tvif::Code(0x00, 0, 0);\r\n}\r\n\r\n\r\n\r\n// Interrupt version.\r\n\r\ninline void vif::NOPi(void)\r\n{\r\n\tvif::Code(0x80, 0, 0);\r\n}\r\n\r\n\r\n\r\n// Sets VIF1_OFST to lower 10 bits of OFFSET.\r\n// DBF flag of VIF1_STAT is cleared and VIF1_BASE is copied to VIF1_TOPS.\r\n\r\ninline void vif::OFFSET(uint16 OFFSET)\r\n{\r\n\tvif::Code(0x02, 0, OFFSET);\r\n}\r\n\r\n\r\n\r\n// Sets VIFn_C0-VIFn_C3 to C0-C3.\r\n\r\ninline void vif::STCOL(uint32 C0, uint32 C1, uint32 C2, uint32 C3)\r\n{\r\n\tvif::Code(0x31, 0, 0);\r\n\tdma::Store32(C0, C1, C2, C3);\r\n}\r\n\r\n\r\n\r\n// Sets VIFn_CYCLE.\r\n// CL>=WL gives skipping write;\r\n// CL<WL gives filling write.\r\n\r\ninline void vif::STCYCL(uint16 WL, uint16 CL)\r\n{\r\n\tvif::Code(0x01, 0, WL<<8|CL);\r\n\tCycleLength = WL>CL?WL:CL;\r\n}\r\n\r\n\r\n\r\n// Sets VIFn_MASK to MASK = (m15,...,m0) with m0 at the low end of the word.\r\n//\r\n//\t\t\t\t\t W\t Z\t Y\t X\r\n//\t\t\t\t\t---------------\r\n// write cycle=1\tm0\tm1\tm2\tm3\r\n// write cycle=2\tm4\tm5\tm6\tm7\r\n// write cycle=3\tm8\tm9\tm10\tm11\r\n// write cycle>=4\tm15\tm14\tm13\tm12\r\n//\r\n// m[n]=0 => decompressed data written as-is;\r\n// m[n]=1 => row register written;\r\n// m[n]=2 => column register written;\r\n// m[n]=3 => write masked.\r\n\r\ninline void vif::STMASK(uint32 MASK)\r\n{\r\n\tvif::Code(0x20, 0, 0);\r\n\tdma::Store32(MASK);\r\n}\r\n\r\n\r\n\r\n// Sets VIFn_MODE to lower 2 bits of MODE.\r\n\r\ninline void vif::STMOD(uint16 MODE)\r\n{\r\n\tvif::Code(0x05, 0, MODE);\r\n}\r\n\r\n\r\n\r\n// Sets VIFn_R0-VIFn_R3 to R0-R3.\r\n\r\ninline void vif::STROW(uint32 R0, uint32 R1, uint32 R2, uint32 R3)\r\n{\r\n\tvif::Code(0x30, 0, 0);\r\n\tdma::Store32(R0,R1,R2,R3);\r\n}\r\n\r\n\r\n\r\n// Decompresses data to VUMem+ADDR.\r\n// SIZE is the number of decompressed data;\r\n// vnvl is the format of compressed data (S_8, V4_32, etc);\r\n// destination in VUMem is ADDR (if FLG==0 on VU1) or VIF1_TOPS+ADDR (if FLG==1 on VU1);\r\n// USN==0 => sign extension, USN==1 => padding with 0's;\r\n// m==1 => masking write using VIFn_MASK.\r\n\r\ninline void vif::UNPACK(uint8 m, uint8 vnvl, uint8 SIZE, uint16 FLG, uint16 USN, uint16 ADDR)\r\n{\r\n\tvif::Code(0x60|m<<4|vnvl, SIZE, FLG<<15 | USN<<14 | ((vu1::Loc+ADDR)&0x03FF));\r\n\tUnpackSize = SIZE;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n//--------------------------------------------------------------\r\n//\t\tV I F C O D E S   ( B E G I N - E N D   S T Y L E )\r\n//--------------------------------------------------------------\r\n\r\n\r\n// Auto-size version of DIRECT.\r\n// Alignment necessary because data must align to 128-bit boundary.\r\n\r\ninline void vif::BeginDIRECT(void)\r\n{\r\n\tdma::Align(12,16);\r\n\tpVifCode = dma::pLoc;\r\n\tvif::Code(0x50, 0, 0);\r\n}\r\n\r\n\r\n\r\n// Patch up the IMMEDIATE field of a DIRECT generated using BeginDIRECT().\r\n// Alignment necessary because vif will interpret till 16-byte boundary as data.\r\n\r\ninline void vif::EndDIRECT(void)\r\n{\r\n\tdma::Align(0,16);\r\n\t((uint16 *)pVifCode)[0] = (dma::pLoc - pVifCode - 4)/16;\r\n}\r\n\r\n\r\n\r\n// Auto-size version of DIRECTHL.\r\n// Alignment necessary because data must align to 16-byte boundary.\r\n\r\ninline void vif::BeginDIRECTHL(void)\r\n{\r\n\tdma::Align(12,16);\r\n\tpVifCode = dma::pLoc;\r\n\tvif::Code(0x51, 0, 0);\r\n}\r\n\r\n\r\n\r\n// Patch up the IMMEDIATE field of a DIRECTHL generated using BeginDIRECTHL().\r\n// Alignment necessary because vif will interpret till 16-byte boundary as data.\r\n\r\ninline void vif::EndDIRECTHL(void)\r\n{\r\n\tdma::Align(0,16);\r\n\t((uint16 *)pVifCode)[0] = (dma::pLoc - pVifCode - 4)/16;\r\n}\r\n\r\n\r\n\r\n// Auto-size version of MPG.\r\n// Alignment necessary because data must align to 8-byte boundary.\r\n\r\ninline void vif::BeginMPG(uint16 LOADADDR)\r\n{\r\n\tdma::Align(4,8);\r\n\tpVifCode = dma::pLoc;\r\n\tvif::Code(0x4A, 0, LOADADDR);\r\n}\r\n\r\n\r\n\r\n// Patch up the NUM field of an MPG generated using BeginMPG().\r\n// Alignment necessary because vif will interpret till 8-byte boundary as data.\r\n\r\ninline void vif::EndMPG(void)\r\n{\r\n\tdma::Align(0,8);\r\n\tpVifCode[2] = (dma::pLoc - pVifCode - 4)/8;\r\n}\r\n\r\n\r\n\r\n// Auto-size version of UNPACK.\r\n\r\ninline void vif::BeginUNPACK(uint8 m, uint8 vnvl, uint16 FLG, uint16 USN, uint16 ADDR)\r\n{\r\n\tpVifCode = dma::pLoc;\r\n\tBitLength = 32 >> (vnvl & 3);\r\n\tDimension = (vnvl>>2 & 3) + 1;\r\n\tvif::Code(0x60 | m<<4 | vnvl, 0, FLG<<15 | USN<<14 | ((vu1::Loc+ADDR)&0x03FF) );\r\n}\r\n\r\n\r\n\r\n// Patch up the NUM field of an UNPACK generated using BeginUNPACK().\r\n// Alignment is necessary because some data formats won't fill out to a 4-byte boundary.\r\n\r\ninline void vif::EndUNPACK(void)\r\n{\r\n\tUnpackSize = ((dma::pLoc - pVifCode - 4) << 3) / (Dimension * BitLength);\r\n\tdma::Align(0,4);\r\n\tif (UnpackSize==0)\r\n\t\tdma::pLoc -= 4;\t\t\t\t// no data, rewind over vifcode\r\n\telse if (UnpackSize < 256)\r\n\t\tpVifCode[2] = UnpackSize;\t// normal usage\r\n\telse if (UnpackSize == 256)\r\n\t\tpVifCode[2] = 0;\t\t\t\t// 0 represents 256\r\n\telse\r\n\t{\r\n\t\tprintf(\"unpack size greater than 256\\n\");\r\n\t\t#ifdef __PLAT_NGPS__\r\n\t\texit(1);\r\n\t\t#endif\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------\r\n//\t\tS T O R I N G   C O M P R E S S E D   V I F   D A T A\r\n//-----------------------------------------------------------------\r\n\r\n\r\n// scalars\r\n\r\ninline void vif::StoreS_32(uint32 x)\r\n{\r\n\t*(uint32 *)dma::pLoc = x;\r\n\tdma::pLoc += 4;\r\n}\r\n\r\n\r\ninline void vif::StoreS_16(uint16 x)\r\n{\r\n\t*(uint16 *)dma::pLoc = x;\r\n\tdma::pLoc += 2;\r\n}\r\n\r\n\r\ninline void vif::StoreS_8(uint8 x)\r\n{\r\n\t*dma::pLoc++ = x;\r\n}\r\n\r\n\r\n\r\n// 2-vectors\r\n\r\ninline void vif::StoreV2_32(uint32 x, uint32 y)\r\n{\r\n\t((uint32 *)dma::pLoc)[0] = x;\r\n\t((uint32 *)dma::pLoc)[1] = y;\r\n\tdma::pLoc += 8;\r\n}\r\n\r\n\r\ninline void vif::StoreV2_16(uint16 x, uint16 y)\r\n{\r\n\t((uint16 *)dma::pLoc)[0] = x;\r\n\t((uint16 *)dma::pLoc)[1] = y;\r\n\tdma::pLoc += 4;\r\n}\r\n\r\n\r\ninline void vif::StoreV2_8(uint8 x, uint8 y)\r\n{\r\n\t((uint8 *)dma::pLoc)[0] = x;\r\n\t((uint8 *)dma::pLoc)[1] = y;\r\n\tdma::pLoc += 2;\r\n}\r\n\r\n\r\n\r\n// 3-vectors\r\n\r\ninline void vif::StoreV3_32(uint32 x, uint32 y, uint32 z)\r\n{\r\n\t((uint32 *)dma::pLoc)[0] = x;\r\n\t((uint32 *)dma::pLoc)[1] = y;\r\n\t((uint32 *)dma::pLoc)[2] = z;\r\n\tdma::pLoc += 12;\r\n}\r\n\r\n\r\ninline void vif::StoreV3_16(uint16 x, uint16 y, uint16 z)\r\n{\r\n\t((uint16 *)dma::pLoc)[0] = x;\r\n\t((uint16 *)dma::pLoc)[1] = y;\r\n\t((uint16 *)dma::pLoc)[2] = z;\r\n\tdma::pLoc += 6;\r\n}\r\n\r\n\r\ninline void vif::StoreV3_8(uint8 x, uint8 y, uint8 z)\r\n{\r\n\t((uint8 *)dma::pLoc)[0] = x;\r\n\t((uint8 *)dma::pLoc)[1] = y;\r\n\t((uint8 *)dma::pLoc)[2] = z;\r\n\tdma::pLoc[2] = z;\r\n\tdma::pLoc += 3;\r\n}\r\n\r\n\r\n\r\n// 4-vectors\r\n\r\ninline void vif::StoreV4_32F(float x, float y, float z, float w)\r\n{\r\n\t((float *)dma::pLoc)[0] = x;\r\n\t((float *)dma::pLoc)[1] = y;\r\n\t((float *)dma::pLoc)[2] = z;\r\n\t((float *)dma::pLoc)[3] = w;\r\n\tdma::pLoc += 16;\r\n}\r\n\r\n\r\ninline void vif::StoreV4_32(sint32 x, sint32 y, sint32 z, sint32 w)\r\n{\r\n\t((sint32 *)dma::pLoc)[0] = x;\r\n\t((sint32 *)dma::pLoc)[1] = y;\r\n\t((sint32 *)dma::pLoc)[2] = z;\r\n\t((sint32 *)dma::pLoc)[3] = w;\r\n\tdma::pLoc += 16;\r\n}\r\n\r\n\r\ninline void vif::StoreV4_16(sint16 x, sint16 y, sint16 z, sint16 w)\r\n{\r\n\t((sint16 *)dma::pLoc)[0] = x;\r\n\t((sint16 *)dma::pLoc)[1] = y;\r\n\t((sint16 *)dma::pLoc)[2] = z;\r\n\t((sint16 *)dma::pLoc)[3] = w;\r\n\tdma::pLoc += 8;\r\n}\r\n\r\n\r\ninline void vif::StoreV4_8(sint8 x, sint8 y, sint8 z, sint8 w)\r\n{\r\n\t((sint8 *)dma::pLoc)[0] = x;\r\n\t((sint8 *)dma::pLoc)[1] = y;\r\n\t((sint8 *)dma::pLoc)[2] = z;\r\n\t((sint8 *)dma::pLoc)[3] = w;\r\n\tdma::pLoc += 4;\r\n}\r\n\r\n\r\ninline void vif::StoreV4_5(uint8 R, uint8 G, uint8 B, uint8 A)\r\n{\r\n\t*(uint16 *)dma::pLoc = (A&0x80)<<8 | (B&0xF8)<<7 | (G&0xF8)<<2 | (R&0xF8)>>3;\r\n\tdma::pLoc += 2;\r\n}\r\n\r\n\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n#endif // __VIF_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu0code.dsm",
    "content": "\r\n.global MPGStart0\r\n.global MPGEnd0\r\n\r\n.global\tTestFunc\r\n.global\tInitialiseOccluders\r\n.global TestSphereAgainstOccluders\r\n.global RayTriangleCollision\r\n.global BatchRayTriangleCollision\r\n.global ViewCullTest\r\n.global OuterCullTest\r\n.global BothCullTests\r\n\r\n; align to a 2^4=16 byte boundary, so it can be the target of a dma::ref\r\n.align\t4\r\n\r\nMPGStart0:\r\n\r\nMPG 0, *\r\n\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\n\r\nTestFunc:\r\n\r\n\t\t; just a little test func to make sure I understand how to communicate with a vu0 microprogram\r\n\r\n\t\t; integer register test\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI01,VI01\r\n\t\t\r\n\t\t; float register test\r\n\t\tADDw\t\tVF02,VF01,VF00w\t\tNOP\r\n\t\t\r\n\t\t; memory test\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF03,0(VI00)\r\n\t\tADDw\t\tVF03,VF03,VF00w\t\tNOP\r\n\t\t\r\n\t\t; quit\r\n\t\tNOP[E]\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\n\r\nInitialiseOccluders:\r\n\r\n\t\t; this function will be optimised later... not a priority now since only called once per frame (per camera)\r\n\r\n\t\t; assumes an initial state where the 5 planes of occluder 0 are at addresses 0,1,2,3,4\r\n\t\t; occluder 1 at 5,6,7,8,9, etc, and the number of occluders is in VI01\r\n\r\n\t\t\r\n\t\t; get address of 1st spare occluder\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI05,VI01,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI05,VI05,VI05\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI05,VI05,VI01\r\n\t\t\r\n\t\t; set up a sentinel plane that's colossally far away\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t-1.0e+35\r\n\t\tMULi\t\tVF01,VF00,I\t\t\tNOP\r\n\t\t\r\n\t\t; add 1 sentinel occluder (5 sentinel planes)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF01,(VI05++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF01,(VI05++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF01,(VI05++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF01,(VI05++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF01,(VI05++)\r\n\t\t\r\n\t\t; rearrange memory\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI02,VI00,0\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.xyzw\tVF31,VI00\r\n\t\t\r\nMemLoop:\r\n\t\t; load 4 occluders, 5 planes each\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,0(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF02,5(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF03,10(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF04,15(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF05,1(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF06,6(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF07,11(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF08,16(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF09,2(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF10,7(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF11,12(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF12,17(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF13,3(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF14,8(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF15,13(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF16,18(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF17,4(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF18,9(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF19,14(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF20,19(VI02)\r\n\t\t\r\n\t\t\r\n\t\t; transpose VF01,VF02,VF03,VF04\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF21,VF01\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF22,VF02\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF23,VF03\r\n\t\t\r\n\t\tADDx.y\t\tVF01,VF31,VF02x\t\tNOP\r\n\t\tADDx.z\t\tVF01,VF31,VF03x\t\tNOP\r\n\t\tADDx.w\t\tVF01,VF31,VF04x\t\tNOP\r\n\t\t\r\n\t\tADDy.x\t\tVF02,VF31,VF21y\t\tNOP\r\n\t\tADDy.z\t\tVF02,VF31,VF03y\t\tNOP\r\n\t\tADDy.w\t\tVF02,VF31,VF04y\t\tNOP\r\n\t\t\r\n\t\tADDz.x\t\tVF03,VF31,VF21z\t\tNOP\r\n\t\tADDz.y\t\tVF03,VF31,VF22z\t\tNOP\r\n\t\tADDz.w\t\tVF03,VF31,VF04z\t\tNOP\r\n\t\t\r\n\t\tADDw.x\t\tVF04,VF31,VF21w\t\tNOP\r\n\t\tADDw.y\t\tVF04,VF31,VF22w\t\tNOP\r\n\t\tADDw.z\t\tVF04,VF31,VF23w\t\tNOP\r\n\t\t\r\n\t\t\r\n\t\t; transpose VF05,VF06,VF07,VF08\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF21,VF05\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF22,VF06\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF23,VF07\r\n\t\t\r\n\t\tADDx.y\t\tVF05,VF31,VF06x\t\tNOP\r\n\t\tADDx.z\t\tVF05,VF31,VF07x\t\tNOP\r\n\t\tADDx.w\t\tVF05,VF31,VF08x\t\tNOP\r\n\t\t\r\n\t\tADDy.x\t\tVF06,VF31,VF21y\t\tNOP\r\n\t\tADDy.z\t\tVF06,VF31,VF07y\t\tNOP\r\n\t\tADDy.w\t\tVF06,VF31,VF08y\t\tNOP\r\n\t\t\r\n\t\tADDz.x\t\tVF07,VF31,VF21z\t\tNOP\r\n\t\tADDz.y\t\tVF07,VF31,VF22z\t\tNOP\r\n\t\tADDz.w\t\tVF07,VF31,VF08z\t\tNOP\r\n\t\t\r\n\t\tADDw.x\t\tVF08,VF31,VF21w\t\tNOP\r\n\t\tADDw.y\t\tVF08,VF31,VF22w\t\tNOP\r\n\t\tADDw.z\t\tVF08,VF31,VF23w\t\tNOP\r\n\t\t\r\n\t\t\r\n\t\t; transpose VF09,VF10,VF11,VF12\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF21,VF09\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF22,VF10\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF23,VF11\r\n\t\t\r\n\t\tADDx.y\t\tVF09,VF31,VF10x\t\tNOP\r\n\t\tADDx.z\t\tVF09,VF31,VF11x\t\tNOP\r\n\t\tADDx.w\t\tVF09,VF31,VF12x\t\tNOP\r\n\t\t\r\n\t\tADDy.x\t\tVF10,VF31,VF21y\t\tNOP\r\n\t\tADDy.z\t\tVF10,VF31,VF11y\t\tNOP\r\n\t\tADDy.w\t\tVF10,VF31,VF12y\t\tNOP\r\n\t\t\r\n\t\tADDz.x\t\tVF11,VF31,VF21z\t\tNOP\r\n\t\tADDz.y\t\tVF11,VF31,VF22z\t\tNOP\r\n\t\tADDz.w\t\tVF11,VF31,VF12z\t\tNOP\r\n\t\t\r\n\t\tADDw.x\t\tVF12,VF31,VF21w\t\tNOP\r\n\t\tADDw.y\t\tVF12,VF31,VF22w\t\tNOP\r\n\t\tADDw.z\t\tVF12,VF31,VF23w\t\tNOP\r\n\t\t\r\n\t\t\r\n\t\t; transpose VF13,VF14,VF15,VF16\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF21,VF13\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF22,VF14\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF23,VF15\r\n\t\t\r\n\t\tADDx.y\t\tVF13,VF31,VF14x\t\tNOP\r\n\t\tADDx.z\t\tVF13,VF31,VF15x\t\tNOP\r\n\t\tADDx.w\t\tVF13,VF31,VF16x\t\tNOP\r\n\t\t\r\n\t\tADDy.x\t\tVF14,VF31,VF21y\t\tNOP\r\n\t\tADDy.z\t\tVF14,VF31,VF15y\t\tNOP\r\n\t\tADDy.w\t\tVF14,VF31,VF16y\t\tNOP\r\n\t\t\r\n\t\tADDz.x\t\tVF15,VF31,VF21z\t\tNOP\r\n\t\tADDz.y\t\tVF15,VF31,VF22z\t\tNOP\r\n\t\tADDz.w\t\tVF15,VF31,VF16z\t\tNOP\r\n\t\t\r\n\t\tADDw.x\t\tVF16,VF31,VF21w\t\tNOP\r\n\t\tADDw.y\t\tVF16,VF31,VF22w\t\tNOP\r\n\t\tADDw.z\t\tVF16,VF31,VF23w\t\tNOP\r\n\t\t\r\n\t\t\r\n\t\t; transpose VF17,VF18,VF19,VF20\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF21,VF17\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF22,VF18\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF23,VF19\r\n\t\t\r\n\t\tADDx.y\t\tVF17,VF31,VF18x\t\tNOP\r\n\t\tADDx.z\t\tVF17,VF31,VF19x\t\tNOP\r\n\t\tADDx.w\t\tVF17,VF31,VF20x\t\tNOP\r\n\t\t\r\n\t\tADDy.x\t\tVF18,VF31,VF21y\t\tNOP\r\n\t\tADDy.z\t\tVF18,VF31,VF19y\t\tNOP\r\n\t\tADDy.w\t\tVF18,VF31,VF20y\t\tNOP\r\n\t\t\r\n\t\tADDz.x\t\tVF19,VF31,VF21z\t\tNOP\r\n\t\tADDz.y\t\tVF19,VF31,VF22z\t\tNOP\r\n\t\tADDz.w\t\tVF19,VF31,VF20z\t\tNOP\r\n\t\t\r\n\t\tADDw.x\t\tVF20,VF31,VF21w\t\tNOP\r\n\t\tADDw.y\t\tVF20,VF31,VF22w\t\tNOP\r\n\t\tADDw.z\t\tVF20,VF31,VF23w\t\tNOP\r\n\t\t\r\n\t\t\r\n\t\t; store the rearranged occluders\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF04,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF01,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF02,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF03,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF08,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF05,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF06,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF07,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF12,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF09,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF10,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF11,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF16,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF13,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF14,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF15,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF20,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF17,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF18,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF19,(VI02++)\r\n\t\t\r\n\t\t\r\n\t\t; loop if we haven't just processed the sentinel planes\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI02,VI05\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBLTZ\t\tVI01,MemLoop\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; quit\r\n\t\tNOP[E]\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\n\r\nTestSphereAgainstOccluders:\t\t\r\n\r\n\t\t; sphere is in VF07 as (x,y,z,R)\r\n\t\t; for each plane p, we must compute px*x + py*w + pz*z + pw + R\r\n\t\t; uses a sentinel occluder to terminate\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI02,VI00,0\t\t\t; initialise pointer\r\n\r\n\t\t; loop prologue\r\n\t\tADD.y\t\tVF05,VF00,VF00\t\tLQI\t\t\tVF04,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF02,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF03,(VI02++)\r\n\t\tADDAw\t\tACC,VF04,VF07w\t\tLQI\t\t\tVF04,(VI02++)\r\n\t\tMADDAx\t\tACC,VF01,VF07x\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\tMADDAy\t\tACC,VF02,VF07y\t\tLQI\t\t\tVF02,(VI02++)\r\n\t\tMADDz\t\tVF00,VF03,VF07z\t\tIADDIU\t\tVI10,VI00,0xF0\t\t; VI10 = mask for Sxyzw FMAC flags\r\n\t\t\r\n\t\t; main loop, tests 4 occluders (20 planes) per pass\r\nLoop:\tADDw.y\t\tVF05,VF05,VF00w\t\tLQI\t\t\tVF03,(VI02++)\r\n\t\tADDAw\t\tACC,VF04,VF07w\t\tLQI\t\t\tVF04,(VI02++)\r\n\t\tMADDAx\t\tACC,VF01,VF07x\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\tMADDAy\t\tACC,VF02,VF07y\t\tFMAND\t\tVI01,VI10\r\n\t\tMADDz\t\tVF00,VF03,VF07z\t\tLQI\t\t\tVF02,(VI02++)\r\n\t\tADDw.y\t\tVF05,VF05,VF00w\t\tLQI\t\t\tVF03,(VI02++)\r\n\t\tADDAw\t\tACC,VF04,VF07w\t\tLQI\t\t\tVF04,(VI02++)\r\n\t\tMADDAx\t\tACC,VF01,VF07x\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\tMADDAy\t\tACC,VF02,VF07y\t\tFMAND\t\tVI01,VI01\r\n\t\tMADDz\t\tVF00,VF03,VF07z\t\tLQI\t\t\tVF02,(VI02++)\r\n\t\tADDw.y\t\tVF05,VF05,VF00w\t\tLQI\t\t\tVF03,(VI02++)\r\n\t\tADDAw\t\tACC,VF04,VF07w\t\tLQI\t\t\tVF04,(VI02++)\r\n\t\tMADDAx\t\tACC,VF01,VF07x\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\tMADDAy\t\tACC,VF02,VF07y\t\tFMAND\t\tVI01,VI01\r\n\t\tMADDz\t\tVF00,VF03,VF07z\t\tLQI\t\t\tVF02,(VI02++)\r\n\t\tADDw.y\t\tVF05,VF05,VF00w\t\tLQI\t\t\tVF03,(VI02++)\r\n\t\tADDAw\t\tACC,VF04,VF07w\t\tLQI\t\t\tVF04,(VI02++)\r\n\t\tMADDAx\t\tACC,VF01,VF07x\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\tMADDAy\t\tACC,VF02,VF07y\t\tFMAND\t\tVI01,VI01\r\n\t\tMADDz\t\tVF00,VF03,VF07z\t\tLQI\t\t\tVF02,(VI02++)\r\n\t\tFTOI0.y\t\tVF06,VF05\t\t\tLQI\t\t\tVF03,(VI02++)\r\n\t\tADDAw\t\tACC,VF04,VF07w\t\tLQI\t\t\tVF04,(VI02++)\r\n\t\tMADDAx\t\tACC,VF01,VF07x\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\tMADDAy\t\tACC,VF02,VF07y\t\tFMAND\t\tVI01,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI01,VI00,Loop\r\n\t\tMADDz\t\tVF00,VF03,VF07z\t\tLQI\t\t\tVF02,(VI02++)\r\n\t\t\r\n\t\t; (macflags & 0x80) => possible occluder in 1st slot of group of 4\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI10,VI01,0x80\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI06,VF06y\r\n\t\tNOP\t\t\t\t\t\t\t\tIBGEZ\t\tVI10,TestForSentinel\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI03,VI02,22\r\n\t\t\r\n\t\t; (macflags & 0x40) => possible occluder in 2nd slot of group of 4\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI10,VI01,0x40\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI06,VI06,1\r\n\t\tNOP\t\t\t\t\t\t\t\tIBGEZ\t\tVI10,TestForSentinel\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI03,VI02,17\r\n\t\t\r\n\t\t; (macflags & 0x20) => possible occluder in 3rd slot of group of 4\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI10,VI01,0x20\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI06,VI06,1\r\n\t\tNOP\t\t\t\t\t\t\t\tIBGEZ\t\tVI10,TestForSentinel\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI03,VI02,12\r\n\t\t\r\n\t\t; (macflags & 0x10) => possible occluder in 4th slot of group of 4\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI06,VI06,1\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI03,VI02,7\r\n\t\t\r\nTestForSentinel:\r\n\t\t; sentinel if VI03==VI05, else occluded\r\n\t\tNOP[E]\t\t\t\t\t\t\tISUB\t\tVI01,VI03,VI05\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI06,VI06,4\r\n\t\t\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\nBatchRayTriangleCollision:\r\n\t\tNOP\t\t\t\t\t\t\t\tILW.y\t\tVI04, 0(VI00)\t\t; total number of collision tests\r\n\t\tNOP\t\t\t\t\t\t\t\tILW.x\t\tVI05, 0(VI00)\t\t; starting index\r\n\r\n\t\tNOP                 \t\t\tIADDIU \t\tVI01, VI00, 0\t\t; init number of found collisions\r\n\t\tNOP                 \t\t\tIADDIU \t\tVI03, VI00, 1\t\t; init address\r\n\t\tNOP                 \t\t\tIADD \t\tVI06, VI00, VI03\t; init output address (writes over input)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI04, VI04, VI05\t; decrement the start index from the array size\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF06, 2(VI03)\t\t; v0\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF08, 4(VI03)\t\t; v2\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF07, 3(VI03)\t\t; v1\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF04, 0(VI03)\t\t; rayStart\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF05, 1(VI03)\t\t; rayDir\r\n   \r\nNextCollision:\r\n\t\tSUB.xyz     VF10, VF08, VF06\tNOP\t\t\t\t\t\t\t   \t; edge2 = v2 - v0\r\n\t\tSUB.xyz     VF09, VF07, VF06\tMFIR.w\t\tVF17w, VI05   \t\t; edge1 = v1 - v0  ; store index in VF17w (output)\r\n\t\tSUB.xyz     VF13, VF04, VF06\tFSSET 0\t\t\t\t\t\t\t; tvec = rayStart - v0\r\n\t\tADDW.x      VF02, VF00, VF00w\tLOI 1.00001\t\t\t\t\t\t; Load 1.0f to VF02x ; load 1 + EPSILON into I\r\n\r\n\t\tOPMULA.xyz  ACC, VF05, VF10\t\tNOP\t\t\t\t\t\t\t\t; Cross product of ray normal and edge2 (pvec)\r\n\t\tOPMSUB.xyz  VF12,VF10, VF05\t\tNOP\t\t\t\t\t\t\t\t; Second part of cross product\r\n\t\tOPMULA.xyz  ACC, VF13, VF09     IADDIU      VI14, VI00, 0x80    ; qvec = crossProd(tvec, edge1) ; Set the mask X sign flag\r\n\t\tOPMSUB.xyz  VF14,VF09, VF13     IADDIU      VI13, VI00, 0x10\t; Set the mask W sign flag\r\n\t\tSUBi.x\t\tVF03,VF00, I\t\tNOP\t\t\t\t\t\t\t\t; put -(1 + EPSILON) in VF03x\r\n\r\n\t\tMUL.xyz     VF11,VF09, VF12\t\tNOP\t\t\t\t\t\t\t\t; det = edge1 * pvec [start]\r\n\t\tMUL.xyz     VF15,VF13, VF12\t\tNOP\t\t\t\t\t\t\t\t; u = tvec * pvec [start]\r\n\t\tMULAx.x     ACC, VF09, VF12x\tIADDI\t\tVI04, VI04, -1\t\t; decrement number of collision tests\r\n\t\tMADDAy.x    ACC, VF02, VF11y\tIADDIU \t\tVI03, VI03, 5\t\t; increment address\r\n\t\tMADDz.x     VF11,VF02, VF11z\tNOP\t\t\t\t\t\t\t\t; det = edge1 * pvec [ready]\r\n\t\tMULAx.x     ACC, VF02, VF15x\tLOI 0.00001\t\t\t\t\t\t; load 1 + EPSILON into I\r\n\t\tMADDAy.x    ACC, VF02, VF15y\tLQ\t\t\tVF04, 0(VI03)\t\t; next rayStart\r\n\t\tMUL.xyz\t\tVF17,VF10, VF14\t\tNOP\t\t\t\t\t\t\t\t; t = edge2 * qvec [start]\r\n\t\tSUBi.x      VF01,VF11, I  \t\tDIV \t    Q,   VF00w,VF11x\t; If det < EPSILON ; Q = 1.0f / det\r\n\r\n\t\tMADDz.x     VF15,VF02, VF15z\tLQ\t\t\tVF06, 2(VI03)\t\t; u = tvec * pvec [ready] ; next v0\r\n\t\tMULAx.x\t\tACC, VF10, VF14x\tLQ\t\t\tVF08, 4(VI03)\t\t; next v2\r\n\t\tMADDAy.x\tACC, VF02, VF17\t\tLQ\t\t\tVF07, 3(VI03)\t\t; next v1\r\n        MUL.xyz\t\tVF16,VF05, VF14     FMAND \t\tVI15,VI14 \t\t\t; v = rayDir * qvec [start] ; check if det result (MAC register)\r\n        MADDz.x\t\tVF17,VF02, VF17z \tIBNE \t\tVI15,VI00,BatchRayTriDone\t; t = edge2 * qvec [ready]\r\n\t\tMULAx.x\t\tACC, VF05, VF14x\tLQ\t\t\tVF05, 1(VI03)\t\t; next rayDir\r\n\t\tMULQ.x\t\tVF15,VF15, Q        NOP\t\t\t\t\t\t\t\t; u = (tvec * pvec) / det\r\n\t\tMADDAy.x\tACC, VF02, VF16\t\tNOP\r\n\t\tMADDz.x\t\tVF16,VF02, VF16z    NOP\t\t\t\t\t\t\t\t; v = rayDir * qvec [ready]\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t\t\t\t\t\t\r\n\r\n\t\tADDx.x\t\tVF00,VF15, VF03x\tFMAND \t\tVI15,VI14\t\t\t; if u > 1 + EPSILON ; check if u result (MAC register)  \r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI15,VI00,BatchRayTriDone\r\n\t\tMULQ.x\t\tVF16,VF16, Q\t\tNOP\t\t\t\t\t\t\t\t; v = (rayDir * qvec) / det;\r\n\t\tMULQ.x\t\tVF17,VF17, Q        NOP\t\t\t\t\t\t\t\t; t = (edge2 * qvec) / det\r\n        NOP\t\t\t\t\t\t\t\tFMAND \t\tVI15,VI14      \t\t; check if u > 1 + EPSILON result (MAC register)\r\n        NOP\t\t\t\t\t\t\t    IBEQ\t\tVI15,VI00,BatchRayTriDone\r\n\r\n        ADDA.x\t\tACC ,VF15, VF16   \tFMAND \t\tVI15,VI14      \t\t; check if v < 0 result (MAC register)\r\n        MADDw.x     VF31,VF03, VF00w    IBNE \t\tVI15,VI00,BatchRayTriDone ; if (u+v) > 1 + EPSILON [start]\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tSUB.x\t\tVF00,VF17, VF00\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n        SUBx.w\t\tVF00,VF00, VF17 \tFMAND \t\tVI15,VI14     \t\t; if t > 1 [start] ; check if u+v > 1 + EPSILON result (MAC register)\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ \t\tVI15,VI00,BatchRayTriDone\t\r\n\r\n\t\tNOP\t\t\t\t\t\t\t    FMAND \t\tVI15,VI14\t\t\t; check if t < 0 result (MAC register) \t  \t\r\n        NOP                             IBNE \t\tVI15,VI00,BatchRayTriDone\r\n\r\n        NOP\t\t\t\t\t\t\t\tFMAND \t\tVI15,VI13          \t; check if t > 1 result (MAC register)\r\n        NOP                             IBNE \t\tVI15,VI00,BatchRayTriDone\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI.xw\t\tVF17, (VI06++)\t\t; store distance (x) and index (w)\r\n\t\tNOP                 \t\t\tIADDIU \t\tVI01, VI01, 1\t\t; inc number of found collisions\r\n\r\nBatchRayTriDone:\r\n        NOP                             IBNE \t\tVI04, VI00,NextCollision\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI05, VI05, 1\t\t; increment index for output\r\n\r\n\t\tNOP[T]\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\nRayTriangleCollision:\r\n\r\n\t\tSUB.xyz     VF10, VF08, VF06\tNOP\t\t\t\t\t\t\t\t; edge2 = v2 - v0\r\n\t\tSUB.xyz     VF09, VF07, VF06\tFSSET 0\t\t\t\t\t\t\t; edge1 = v1 - v0 \r\n\t\tSUB.xyz     VF13, VF04, VF06\tNOP\t\t\t\t\t\t\t\t; tvec = rayStart - v0\r\n\t\tADDW.x      VF02, VF00, VF00w\tLOI 1.00001\t\t\t\t\t\t; Load 1.0f to VF02x ; load 1 + EPSILON into I\r\n\r\n\t\tOPMULA.xyz  ACC, VF05, VF10\t\tNOP\t\t\t\t\t\t\t\t; Cross product of ray normal and edge2 (pvec)\r\n\t\tOPMSUB.xyz  VF12,VF10, VF05\t\tNOP\t\t\t\t\t\t\t\t; Second part of cross product\r\n\t\tOPMULA.xyz  ACC, VF13, VF09     IADDIU      VI14, VI00, 0x80    ; qvec = crossProd(tvec, edge1) ; Set the mask X sign flag\r\n\t\tOPMSUB.xyz  VF14,VF09, VF13     IADDIU      VI13, VI00, 0x10\t; Set the mask W sign flag\r\n\t\tSUBi.x\t\tVF03,VF00, I\t\tIADDIU \t\tVI02, VI00, 0\t\t; put -(1 + EPSILON) in VF03x ; store 0 for return value\r\n\r\n\t\tMUL.xyz     VF11,VF09, VF12\t\tNOP\t\t\t\t\t\t\t\t; det = edge1 * pvec [start]\r\n\t\tMUL.xyz     VF15,VF13, VF12\t\tNOP\t\t\t\t\t\t\t\t; u = tvec * pvec [start]\r\n\t\tMULAx.x     ACC, VF09, VF12x\tNOP\r\n\t\tMADDAy.x    ACC, VF02, VF11y\tNOP\r\n\t\tMADDz.x     VF11,VF02, VF11z\tNOP\t\t\t\t\t\t\t\t; det = edge1 * pvec [ready]\r\n\t\tMULAx.x     ACC, VF02, VF15x\tLOI 0.00001\t\t\t\t\t\t; load 1 + EPSILON into I\r\n\t\tMADDAy.x    ACC, VF02, VF15y\tNOP\r\n\t\tMUL.xyz\t\tVF17,VF10, VF14\t\tNOP\t\t\t\t\t\t\t\t; t = edge2 * qvec [start]\r\n\t\tSUBi.x      VF01,VF11, I  \t\tDIV \t    Q,   VF00w,VF11x\t; If det < EPSILON ; Q = 1.0f / det\r\n\r\n\t\tMADDz.x     VF15,VF02, VF15z\tNOP\t\t\t\t\t\t\t\t; u = tvec * pvec [ready]\r\n\t\tMULAx.x\t\tACC, VF10, VF14x\tNOP\r\n\t\tMADDAy.x\tACC, VF02, VF17\t\tNOP\r\n        MUL.xyz\t\tVF16,VF05, VF14     FMAND \t\tVI15,VI14 \t\t\t; v = rayDir * qvec [start] ; check if det result (MAC register)\r\n        MADDz.x\t\tVF17,VF02, VF17z \tIBNE \t\tVI15,VI00,vu0RayTriDone\t; t = edge2 * qvec [ready]\r\n\t\tMULAx.x\t\tACC, VF05, VF14x\tNOP\r\n\t\tMULQ.x\t\tVF15,VF15, Q        NOP\t\t\t\t\t\t\t\t; u = (tvec * pvec) / det\r\n\t\tMADDAy.x\tACC, VF02, VF16\t\tNOP\r\n\t\tMADDz.x\t\tVF16,VF02, VF16z    NOP\t\t\t\t\t\t\t\t; v = rayDir * qvec [ready]\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t\t\t\t\t\t\r\n\r\n\t\tADDx.x\t\tVF00,VF15, VF03x\tFMAND \t\tVI15,VI14\t\t\t; if u > 1 + EPSILON ; check if u result (MAC register)  \r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI15,VI00,vu0RayTriDone\r\n\t\tMULQ.x\t\tVF16,VF16, Q\t\tNOP\t\t\t\t\t\t\t\t; v = (rayDir * qvec) / det;\r\n\t\tMULQ.x\t\tVF17,VF17, Q        NOP\t\t\t\t\t\t\t\t; t = (edge2 * qvec) / det\r\n        NOP\t\t\t\t\t\t\t\tFMAND \t\tVI15,VI14      \t\t; check if u > 1 + EPSILON result (MAC register)\r\n        NOP\t\t\t\t\t\t\t    IBEQ\t\tVI15,VI00,vu0RayTriDone\r\n\r\n        ADDA.x\t\tACC ,VF15, VF16   \tFMAND \t\tVI15,VI14      \t\t; check if v < 0 result (MAC register)\r\n        MADDw.x     VF31,VF03, VF00w    IBNE \t\tVI15,VI00,vu0RayTriDone ; if (u+v) > 1 + EPSILON [start]\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tSUB.x\t\tVF00,VF17, VF00\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n        SUBx.w\t\tVF00,VF00, VF17 \tFMAND \t\tVI15,VI14     \t\t; if t > 1 [start] ; check if u+v > 1 + EPSILON result (MAC register)\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ \t\tVI15,VI00,vu0RayTriDone\t\r\n\r\n\t\tNOP\t\t\t\t\t\t\t    FMAND \t\tVI15,VI14\t\t\t; check if t < 0 result (MAC register) \t  \t\r\n        NOP                             IBNE \t\tVI15,VI00,vu0RayTriDone\r\n\r\n        NOP\t\t\t\t\t\t\t\tFMAND \t\tVI15,VI13          \t; check if t > 1 result (MAC register)\r\n        NOP                             IBNE \t\tVI15,VI00,vu0RayTriDone\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t;qmfc2\t$9, $vf17\t\t\t # move t to $9\r\n\t;sw\t\t$9, 0(%1)\t\t\t # and write out\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU \t\tVI02, VI00, 1\t\t; store 1 for return value\r\n\r\nvu0RayTriDone:\r\n\r\n\t\tNOP[E]\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; new bounding volume / frustum intersection tests\r\n\r\n\r\n\t\t; VF08 = (x0,y0,z0,r)\r\n\t\t; VF09 = (bx,by,bz,?)\r\n\t\t\r\n\t\t; VF10 = (nx)\r\n\t\t; VF11 = (ny)\r\n\t\t; VF12 = (nz)\r\n\t\t; VF13 = (|nx|)\r\n\t\t; VF14 = (|ny|)\r\n\t\t; VF15 = (|nz|)\r\n\t\t; VF16 = (nw)\r\n\t\t\r\n\t\t; VF17 = (nx)\r\n\t\t; VF18 = (ny)\r\n\t\t; VF19 = (nz)\r\n\t\t; VF20 = (|nx|)\r\n\t\t; VF21 = (|ny|)\r\n\t\t; VF22 = (|nz|)\r\n\t\t; VF23 = (nw)\r\n\t\t\r\n\t\t; VF24 = (nx)\r\n\t\t; VF25 = (ny)\r\n\t\t; VF26 = (nz)\r\n\t\t; VF27 = (|nx|)\r\n\t\t; VF28 = (|ny|)\r\n\t\t; VF29 = (|nz|)\r\n\t\t; VF30 = (nw)\r\n\t\t\r\n\t\t; VF31 = (1)\r\n\r\n\t\t\r\nViewCullTest:\r\n\t\t\r\n\t\tADDAx\t\tACC,VF16,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF10,VF08x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF11,VF08y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF12,VF08z\t\tNOP\r\n\t\tMADDw\t\tVF00,VF31,VF08w\t\tNOP\r\n\t\tMADDAx\t\tACC,VF13,VF09x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF14,VF09y\t\tNOP\r\n\t\tMADDz\t\tVF00,VF15,VF09z\t\tNOP\r\n\t\t\r\n\t\tADDAx.xy\tACC,VF23,VF00x\t\tFMOR\t\tVI01,VI00\r\n\t\tMADDAx.xy\tACC,VF17,VF08x\t\tNOP\r\n\t\tMADDAy.xy\tACC,VF18,VF08y\t\tNOP\r\n\t\tMADDAz.xy\tACC,VF19,VF08z\t\tFMOR\t\tVI01,VI01\r\n\t\tMADDw.xy\tVF00,VF31,VF08w\t\tNOP\r\n\t\tMADDAx.xy\tACC,VF20,VF09x\t\tNOP\r\n\t\tMADDAy.xy\tACC,VF21,VF09y\t\tNOP\r\n\t\tMADDz.xy\tVF00,VF22,VF09z\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tFMOR\t\tVI01,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP[E]\t\t\t\t\t\t\tFMOR\t\tVI01,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\r\nOuterCullTest:\r\n\r\n\t\tADDAx.zw\tACC,VF23,VF00x\t\tNOP\r\n\t\tMADDAx.zw\tACC,VF17,VF08x\t\tNOP\r\n\t\tMADDAy.zw\tACC,VF18,VF08y\t\tNOP\r\n\t\tMADDAz.zw\tACC,VF19,VF08z\t\tNOP\r\n\t\tMSUBw.zw\tVF00,VF31,VF08w\t\tNOP\r\n\t\tMSUBAx.zw\tACC,VF20,VF09x\t\tNOP\r\n\t\tMSUBAy.zw\tACC,VF21,VF09y\t\tNOP\r\n\t\tMSUBz.zw\tVF00,VF22,VF09z\t\tNOP\r\n\t\t\r\n\t\tADDAx\t\tACC,VF30,VF00x\t\tFMOR\t\tVI01,VI00\r\n\t\tMADDAx\t\tACC,VF24,VF08x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF25,VF08y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF26,VF08z\t\tFMOR\t\tVI01,VI01\r\n\t\tMSUBw\t\tVF00,VF31,VF08w\t\tNOP\r\n\t\tMSUBAx\t\tACC,VF27,VF09x\t\tNOP\r\n\t\tMSUBAy\t\tACC,VF28,VF09y\t\tNOP\r\n\t\tMSUBz\t\tVF00,VF29,VF09z\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tFMOR\t\tVI01,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP[E]\t\t\t\t\t\t\tFMOR\t\tVI01,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\nBothCullTests:\r\n\t\t\r\n\t\tMULAx.zw\tACC,VF20,VF09x\t\tNOP\r\n\t\tMADDAy.zw\tACC,VF21,VF09y\t\tNOP\r\n\t\tMADDz.zw\tVF01,VF22,VF09z\t\tNOP\r\n\t\t\r\n\t\tADDAx\t\tACC,VF16,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF10,VF08x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF11,VF08y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF12,VF08z\t\tNOP\r\n\t\tMADDw\t\tVF00,VF31,VF08w\t\tNOP\r\n\t\tMADDAx\t\tACC,VF13,VF09x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF14,VF09y\t\tNOP\r\n\t\tMADDz\t\tVF00,VF15,VF09z\t\tNOP\r\n\t\t\r\n\t\tADDAx.zw\tACC,VF23,VF00x\t\tFMOR\t\tVI01,VI00\r\n\t\tMADDAx.zw\tACC,VF17,VF08x\t\tNOP\r\n\t\tMADDAy.zw\tACC,VF18,VF08y\t\tNOP\r\n\t\tMADDAz.zw\tACC,VF19,VF08z\t\tFMOR\t\tVI01,VI01\r\n\t\tMADDx.z\t\tVF05,VF00,VF00x\t\tNOP\r\n\t\tMADDw.zw\tVF00,VF31,VF08w\t\tNOP\r\n\t\tMADDw.zw\tVF00,VF01,VF00w\t\tNOP\r\n\t\tMSUBw.zw\tVF00,VF31,VF08w\t\tNOP\r\n\t\tMSUBw.zw\tVF00,VF01,VF00w\t\tNOP\r\n\t\t\r\n\t\tADDAx\t\tACC,VF30,VF00x\t\tFMOR\t\tVI01,VI01\r\n\t\tMADDAx\t\tACC,VF24,VF08x\t\tFMOR\t\tVI01,VI01\r\n\t\tMADDAy\t\tACC,VF25,VF08y\t\tFMOR\t\tVI11,VI00\r\n\t\tMADDAz\t\tACC,VF26,VF08z\t\tFMOR\t\tVI11,VI11\r\n\t\tMSUBw\t\tVF00,VF31,VF08w\t\tNOP\r\n\t\tMSUBAx\t\tACC,VF27,VF09x\t\tNOP\r\n\t\tMSUBAy\t\tACC,VF28,VF09y\t\tNOP\r\n\t\tMSUBz\t\tVF00,VF29,VF09z\t\tNOP\r\n\t\t\r\n\t\tSUBz.x\t\tVF05,VF00,VF05z\t\tFMOR\t\tVI11,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFMOR\t\tVI11,VI11\r\n\t\t\r\n\t\tNOP[E]\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\n\r\n.EndMPG\r\n\r\nMPGEnd0:\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu0code.h",
    "content": "#ifndef __VU0CODE_H\r\n#define __VU0CODE_H\r\n\r\nextern uint MPGStart0[8]; \t\t// Mick:  The [8] is a patch to make the compiler not assume it is in ldata\r\nextern uint MPGEnd0[8];\r\n\r\nextern uint TestFunc;\r\nextern uint InitialiseOccluders;\r\nextern uint TestSphereAgainstOccluders;\r\nextern uint RayTriangleCollision;\r\nextern uint BatchRayTriangleCollision;\r\nextern uint ViewCullTest;\r\nextern uint OuterCullTest;\r\nextern uint BothCullTests;\r\n\r\n#endif //__VU0CODE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu1/defs.vsm",
    "content": "\r\n\t\t.equr\tzero,\tVF00x\r\n\t\t.equr\tone,\tVF00w\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu1/jumptab.vsm",
    "content": "\r\nJumpTable:\r\n; load at micromem address 0\r\n\r\n\t\t; initially the branch addresses will be static\r\n\t\t; but they can later be written dynamically by a vu code caching system\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tInit\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tProcessPacket\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tVU1Context\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tGSContext\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tSpritesInit\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tSprites\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tB\t\t\tScreenAlignedBillboards\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tB\t\t\tAxialBillboards\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu1/main.vsm",
    "content": "\r\n;\tͻ\r\n;\t tag format \r\n;\tͼ\r\n;\r\n;\tThis follows GIFtag format (EE User's Manual section 7.2.2), but with some added fields.\r\n;\r\n;\r\n;\r\n;\t 31 30                   23 22                16 15 14                                         0\r\n;\tĿ\r\n;\t0      STEP exponent      STEP mantissa      EOP                   NLOOP                    \r\n;\t\r\n;\r\n;\r\n;\t 63       60 59 58 57                            47 46 45    43 42                            32\r\n;\tĿ\r\n;\t   NREG     FLG               PRIM              PRE                      ADDR              \r\n;\t\r\n;\r\n;\r\n;\t 95                                                       76 75       72 71       68 67       64\r\n;\tĿ\r\n;\t                                                     ...     [REG2]     [REG1]      REG0    \r\n;\t\r\n;\r\n;\r\n;\t 127                                         112 111                                          96\r\n;\tĿ\r\n;\t                                                                     SIZE                     \r\n;\t\r\n;\r\n;\r\n;\r\n\r\n\r\nInit:\tNOP[E]\t\t\t\t\t\t\tIADDIU\t\tVI02,VI00,0\t\t\t; initialise VI02\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\nProcessPacket:\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; get 1st tag\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI13,VI02,1\t\t\t; VI13 = start address of current packet\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI15,VI00,0\t\t\t; set EOP=0\r\n\t\tNOP\t\t\t\t\t\t\t\tXITOP\t\tVI14\t\t\t\t; get run-time render flags from VIF1_ITOP\r\n\r\nMainLoop:\r\n\t\tNOP\t\t\t\t\t\t\t\tIBLTZ\t\tVI15,KickPacket\t\t; kick if EOP==1\r\n\t\tADDw\t\tVF02,VF01,VF00w\t\tMTIR\t\tVI01,VF01y\t\t\t; VI01 = ADDR, jumptable address. 'ADDw' is for extracting STEP\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI15,VF01x\t\t\t; VI15 = EOP:NLOOP\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI06,VF01w\t\t\t; VI06 = SIZE = NREG*NLOOP, size of prim (excl. tag)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI05,VI02,VI06\t\t; VI05 = end pointer for prim\r\n\t\tNOP\t\t\t\t\t\t\t\tJR\t\t\tVI01\t\t\t\t; jump via jumptable\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI04,VF02x\t\t\t; VI04 = STEP (branch delay slot)\r\n\r\n\r\nKickPacket:\r\n\t\t; kick and stop\r\n\t\tNOP[E]\t\t\t\t\t\t\tXGKICK\t\tVI13\t\t\t\t; kick the processed packet to the GS\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI02,VI02,1\t\t\t; undo last postincrement (so VI02 points to next packet)\r\n\r\n\r\nNextPrim:\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; get next tag\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tMainLoop\t\t\t; loop\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\n\r\n\r\n; SIZE field must be NREG*NLOOP - 1\r\n; STEP mantissa must generate the value n*3-27 where VFn is the first reg in the context\r\n\r\n\r\nVU1Context:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI04,VU1Context; eventually optimise this away and just do...\r\n\t\tNOP\t\t\t\t\t\t\t\tJR\t\t\tVI01\t\t\t\t; JR VI04\r\n\t\tSUBA.w\t\tACC,VF00,VF00\t\tLOI\t\t\t0x44800000\t\t\t; 2^10\r\n\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF10,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x45000000\t\t\t; 2^11\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF11,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x45800000\t\t\t; 2^12\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF12,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x46000000\t\t\t; 2^13\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF13,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x46800000\t\t\t; 2^14\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF14,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x47000000\t\t\t; 2^15\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF15,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x47800000\t\t\t; 2^16\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF16,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x48000000\t\t\t; 2^17\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF17,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x48800000\t\t\t; 2^18\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF18,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x49000000\t\t\t; 2^19\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF19,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x49800000\t\t\t; 2^20\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF20,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x4A000000\t\t\t; 2^21\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF21,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x4A800000\t\t\t; 2^22\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF22,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x4B000000\t\t\t; 2^23\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF23,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x4B800000\t\t\t; 2^24\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF24,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x4C000000\t\t\t; 2^25\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF25,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x4C800000\t\t\t; 2^26\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF26,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x4D000000\t\t\t; 2^27\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF27,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x4D800000\t\t\t; 2^28\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF28,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x4E000000\t\t\t; 2^29\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF29,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x4E800000\t\t\t; 2^30\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,NextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF30,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x4F000000\t\t\t; 2^31\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tMADDAi.w\tACC,VF00,I\t\t\tLQI\t\t\tVF31,(VI02++)\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\nGSContext:\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,0(VI05)\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tMainLoop\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI02,VI05,1\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu1/newvu1code.dsm",
    "content": "\r\n.global NewMPGStart\r\n.global NewMPGEnd\r\n\r\n.include \"defs.vsm\"\r\n\r\n; align to a 2^7=128 byte boundary for faster dma transfer\r\n.align\t7\r\n\r\nNewMPGStart:\r\n\r\n.DmaData ParticleVU1CodeStart\r\n\r\n\tMPG 0, *\r\n\t\r\n\t\t.include \"jumptab.vsm\"\r\n\t\t.include \"main.vsm\"\r\n\t\t.include \"particle.vsm\"\r\n\t\t;.include \"billboard.vsm\"\r\n\r\n\t.EndMPG\r\n\t\r\n.EndDmaData\r\nNewMPGEnd:\r\n\r\n; force rebuild\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu1/newvu1code.h",
    "content": "#ifndef __NEWVU1CODE_H\r\n#define __NEWVU1CODE_H\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\nextern uint NewMPGStart       __attribute__((section(\".vudata\")));\r\nextern uint NewMPGEnd         __attribute__((section(\".vudata\")));\r\n\r\n#endif\r\n\r\n#endif //__NEWVU1CODE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu1/particle.vsm",
    "content": "\r\n; -----------------\r\n; VU1 PARTICLE CODE\r\n; -----------------\r\n\r\n\r\n; to do:\r\n; - lift restriction on number of particles per system (ie allow one system to span multiple VU1 'buffers')\r\n; - cyclic paths?\r\n\r\n\r\n; notes:\r\n; the arrangement of VU1 memory accesses should be done in consideration of the low amount of VIF1 activity per system\r\n\r\n\r\n; VU1's (crap) random number generator uses this algorithm:\r\n;\r\n; R = 0x3F800000\t\t|\r\n;     R<<1 & 0x007FFFFF\t|\r\n;     (R>>4 ^ R>>22) & 1\r\n;\r\n; This is augmented by a few xor's and a history of 4 seeds (which we sort of need anyway, to do random vectors),\r\n; to give fairly decent random numbers. If VF13 holds the 4-vector of seeds, the following code steps to the next\r\n; set of 4 values:\r\n;\r\n;\t\tRNEXT.x\t\tVF13,R\r\n;\t\tRXOR\t\tR,VF13y\r\n;\t\tRGET.y\t\tVF13,R\r\n;\t\tRXOR\t\tR,VF13z\r\n;\t\tRGET.z\t\tVF13,R\r\n;\t\tRXOR\t\tR,VF13w\r\n;\t\tRGET.w\t\tVF13,R\r\n;\r\n; But this code is also efficiently emulated on the cpu, which is crucial.\r\n\r\n\r\n\r\nGS_BUF0 = 512\r\nGS_BUF1 = 768\r\nOUT_MAXNUM = 42\r\n\r\n\r\n\r\n\r\n; output sprite format is (STQ,RGBA,XYZ2,UV,XYZ2)\r\n\r\n\r\n\t\t; per stream\r\n\t\t.equr\tt,\t\tVF09\t\t\t; (t,dt,num_particles,?,)\r\n\t\t.equr\tseed,\tVF10\t\t\t; (Rx,Ry,Rz,Rw)\r\n\t\t\r\n\t\t; per system\r\n\t\t.equr\tuv1,\tVF11\t\t\t; (u1,v1,?,?)\r\n\t\t.equr\tuv0,\tVF12\t\t\t; (u0,v0,?,?)\r\n\t\t.equr\tp0,\t\tVF13\t\t\t; t^0 position coefficient\r\n\t\t.equr\tp1,\t\tVF14\t\t\t; t^1 position coefficient\r\n\t\t.equr\tp2,\t\tVF15\t\t\t; t^2 position coefficient\r\n\t\t.equr\ts0,\t\tVF17\t\t\t; t^0 spread coefficient\r\n\t\t.equr\ts1,\t\tVF18\t\t\t; t^1 spread coefficient\r\n\t\t.equr\ts2,\t\tVF19\t\t\t; t^2 spread coefficient\r\n\t\t.equr\tc0,\t\tVF21\t\t\t; t^0 colour coefficient\r\n\t\t.equr\tc1,\t\tVF22\t\t\t; t^1 colour coefficient\r\n\t\t.equr\tc2,\t\tVF23\t\t\t; t^1 colour coefficient\r\n\t\t.equr\ttag,\tVF24\t\t\t; GIFtag for particle GS packets\r\n\r\n\t\t; constant\r\n\t\t.equr\tkvec,\tVF25\t\t\t; scale vec (kx,ky,0,0)\r\n\t\t.equr\tNTLvec,\tVF26\t\t\t; near-top-left cull testing vec\r\n\t\t.equr\tBRvec,\tVF27\t\t\t; far-bottom-right cull testing vec\r\n\t\t.equr\tmat0,\tVF28\t\t\t; view matrix row 0\r\n\t\t.equr\tmat1,\tVF29\t\t\t; view matrix row 1\r\n\t\t.equr\tmat2,\tVF30\t\t\t; view matrix row 2\r\n\t\t.equr\tmat3,\tVF31\t\t\t; view matrix row 3\r\n\r\n\t\t; integer regs\r\n\t\t.equr\tInput,\tVI02\r\n\t\t.equr\tOutput,\tVI03\r\n\t\t.equr\tFlip,\tVI12\r\n\t\t.equr\tPacket,\tVI13\r\n\t\t\r\n\r\n\r\n\t\t.scope\r\n\r\n\r\nSpritesInit:\r\n\r\n\t\t; get input buffer address\r\n\t\tNOP\t\t\t\t\t\t\t\tXTOP\t\tInput\r\n\t\t\r\n\t\t; load constant data\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tmat0,  (Input++)\t; view matrix row 0\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tmat1,  (Input++)\t; view matrix row 1\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tmat2,  (Input++)\t; view matrix row 2\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tmat3,  (Input++)\t; view matrix row 3\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tkvec,  (Input++)\t; scale vec (kx,ky,0,0)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tNTLvec,(Input++)\t; near-top-left cull testing vec\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tBRvec,(Input++)\t\t; bottom-right cull testing vec\r\n\r\n\t\tNOP[E]\t\t\t\t\t\t\tIADDIU\t\tPacket,VI00,GS_BUF0\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tFlip,Packet,GS_BUF1\r\n\r\n\r\n\r\nSprites:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\t; get input buffer address\r\n\t\tNOP\t\t\t\t\t\t\t\tXTOP\t\tInput\r\n\t\t\r\n\t\t; kick GS context and step over it\r\n\t\tNOP\t\t\t\t\t\t\t\tILW.x\t\tVI01,0(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tXGKICK\t\tInput\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tInput,Input,0x7FFF\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tInput,Input,VI01\r\n\r\n\t\t; load the context data for the system\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tuv0,(Input++)\t\t; (u0,v0,u1,v1)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tp0, (Input++)\t\t; t^0 position coefficient\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tp1, (Input++)\t\t; t^1 position coefficient\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tp2, (Input++)\t\t; t^2 position coefficient\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\ts0, (Input++)\t\t; t^0 spread coefficient\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\ts1, (Input++)\t\t; t^1 spread coefficient\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\ts2, (Input++)\t\t; t^2 spread coefficient\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tc0, (Input++)\t\t; \r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tc1, (Input++)\t\t; \r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tc2, (Input++)\t\t; \r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\ttag,(Input++)\t\t; GIFtag for particle GS packets\r\n\r\n\r\n\t\t; a little bit of reformatting\r\n\t\tNOP\t\t\t\t\t\t\t\tMR32\t\tuv1,uv0\r\n\t\tNOP\t\t\t\t\t\t\t\tMR32\t\tuv1,uv1\r\n\r\n\t\t; copy tag to packet buffers\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\ttag,GS_BUF0(VI00)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\ttag,GS_BUF1(VI00)\r\n\r\n@StreamLoop:\r\n\r\n\t\t; load stream data\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tt,(Input++)\t\t\t; t_oldest, dt, num_particles, terminator\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tseed,(Input++)\r\n\r\n\t\t; seed initialisation\r\n\t\tNOP\t\t\t\t\t\t\t\tRINIT\t\tR,seed.w\r\n\r\n\t\t; To start with, just pack each buffer full until we run out. This will usually end with a half-full buffer.\r\n\t\t; Later we can work out the ideal packet size to even out the cost.\r\n\t\t\r\n\t\t; get num particles\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI06,t.z\r\n\r\n@PacketLoop:\r\n\r\n\t\t; set output pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tOutput,Packet,1\r\n\t\t\r\n\t\t; see if they'll all fit\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI01,VI06,OUT_MAXNUM\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBGTZ\t\tVI01,@WontFit\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n@WillFit:\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\t@Reduce\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI05,VI06,0\r\n\r\n@WontFit:\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI05,VI00,OUT_MAXNUM\r\n\r\n@Reduce:\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI06,VI06,VI05\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI05,VI00,@NextStream\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI05,0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.x\t\tVI01,0(Packet)\r\n\r\n@ParticleLoop:\r\n\r\n\t\t; generate new seed vector\r\n\t\tNOP\t\t\t\t\t\t\t\tRNEXT.x\t\tseed,R\r\n\t\tNOP\t\t\t\t\t\t\t\tRXOR\t\tR,seed.y\r\n\t\tNOP\t\t\t\t\t\t\t\tRGET.y\t\tseed,R\r\n\t\tNOP\t\t\t\t\t\t\t\tRXOR\t\tR,seed.z\r\n\t\tNOP\t\t\t\t\t\t\t\tRGET.z\t\tseed,R\r\n\t\tNOP\t\t\t\t\t\t\t\tRXOR\t\tR,seed.w\r\n\t\tNOP\t\t\t\t\t\t\t\tRGET.w\t\tseed,R\r\n\r\n\t\t; compute p0+s0*seed + t(p1+s1*seed) + t^2(p2+s2*seed) + t^3(p3+s3*seed)\r\n\t\t; = (((p3+s3*seed)t + p2+s2*seed)t + p1+s1*seed)t + p0+s0*seed\r\n\r\n\t\tADDAx\t\tACC,p2,zero\t\t\tNOP\r\n\t\tMADD\t\tVF02,s2,seed\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,p1,zero\t\t\tNOP\r\n\t\tMADDA\t\tACC,s1,seed\t\t\tNOP\r\n\t\tMADDx\t\tVF02,VF02,t.x\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,p0,zero\t\t\tNOP\r\n\t\tMADDA\t\tACC,s0,seed\t\t\tNOP\r\n\t\tMADDx\t\tVF02,VF02,t.x\t\tNOP\r\n\t\t\r\n\t\t; VF02 = (x,y,z,r)\r\n\t\t\r\n\t\t; transform and add corner offsets\r\n\t\tADDAx\t\tACC,mat3,zero\t\tNOP\r\n\t\tMADDAx\t\tACC,mat0,VF02x\t\tNOP\r\n\t\tMADDAy\t\tACC,mat1,VF02y\t\tNOP\r\n\t\tMADDAz\t\tACC,mat2,VF02z\t\tNOP\r\n\t\tMSUBw\t\tVF01,kvec,VF02w\t\tNOP\r\n\t\tMADDw.xyz\tVF02,kvec,VF02w\t\tNOP\r\n\t\t\r\n\t\t; VF01 = (x'-kx*r, y'-ky*r, z', w)\r\n\t\t; VF02 = (x'+kx*r, y'+ky*r, z', r)\r\n\t\t\r\n\t\t; calc 1/w\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,one,VF01w\r\n\t\tNOP\t\t\t\t\t\t\t\tWAITQ\r\n\t\t\r\n\t\t; prepare for cull tests, move r to NTL vec\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE.w\t\tNTLvec,VF02\r\n\t\t\r\n\t\t; generate screen coords of corners\r\n\t\tMULq.xyz\tVF01,VF01,Q\t\t\tNOP\r\n\t\tMULq\t\tVF02,VF02,Q\t\t\tNOP\r\n\r\n\t\t; VF01 = (X0,Y0,Z0,w)\r\n\t\t; VF02 = (X1,Y1,Z1,r/w) - r/w is only used for mipmapping\r\n\r\n\t\t; get (GS) Q\r\n\t\tNOP\t\t\t\t\t\t\t\tMR32.z\t\tVF03,VF02\r\n\r\n\t\t; compute colour\r\n\t\tSUB.x\t\tVF06,t,tag\t\t\tNOP\t\t\t; subtract mid time\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFMOR\t\tVI01,VI00\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI01,VI00,tPos\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\ntNeg:\tADDAx\t\tACC,c1,zero\t\t\tNOP\r\n\t\tMADDx\t\tVF06,c0,VF06x\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\ttDone\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\ntPos:\tADDAx\t\tACC,c1,zero\t\t\tNOP\r\n\t\tMADDx\t\tVF06,c2,VF06x\t\tNOP\r\n\r\ntDone:\tFTOI0\t\tVF06,VF06\t\t\tNOP\r\n\r\n\t\t; decrement t (remember we started with the oldest particle!)\r\n\t\tSUBy.x\t\tt,t,t.y\t\t\t\tNOP\r\n\t\t\r\n\t\t; cull tests\r\n\t\tSUB.xyw\t\tVF00,VF01,NTLvec\tNOP\r\n\t\tSUB.xy\t\tVF00,BRvec,VF02\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFMOR\t\tVI01,VI00\r\n\t\tNOP\t\t\t\t\t\t\t\tFMOR\t\tVI01,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,0x7FFF\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF02,VI01\r\n\t\t\r\n\t\t; store stuff\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI.z\t\tVF03,(Output++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF06,(Output++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI.xy\t\tuv0, (Output++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI.xyz\t\tVF01,(Output++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tuv1, (Output++)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQI\t\t\tVF02,(Output++)\r\n\t\t\r\n\t\t; dec counter and loop inner\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI05,VI05,1\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI05,VI00,@ParticleLoop\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\t; kick and flip\r\n\t\tNOP\t\t\t\t\t\t\t\tXGKICK\t\tPacket\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tPacket,Flip,Packet\r\n\r\n\t\t; loop outer\r\n\t\tNOP\t\t\t\t\t\t\t\tIBGTZ\t\tVI06,@PacketLoop\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n@NextStream:\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,t.w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBGEZ\t\tVI01,@StreamLoop\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n@Done:\tNOP[E]\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\t.endscope\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu1.cpp",
    "content": "#include <core/defines.h>\r\n#include <stdio.h>\r\n#include \"mikemath.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"vu1.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n#include \"vu1code.h\"\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n//---------------------------------------------------\r\n//\t\tV U   P R I M   C O N S T R U C T I O N\r\n//---------------------------------------------------\r\n\r\n\r\n// begin\r\n\r\n#if 0\r\n// original version\r\nvoid vu1::BeginPrim(uint FLG, uint Addr)\r\n{\r\n\tvif::STCYCL(1,1);\r\n\tvif::BeginUNPACK(0, V4_32, FLG, SIGNED, 0);\r\n\tgif::BeginTag1(gs::NOP, 1, PACKED, 0, 0, Addr);\r\n}\r\n#else\r\n// a quicker version\r\nvoid vu1::BeginPrim(uint FLG, uint Addr)\r\n{\r\n\tregister uint32 *p_dest = (uint32 *)dma::pLoc;\r\n\t*p_dest++ = 0x01000101;\r\n\tvif::pVifCode = (uint8 *)p_dest;\r\n\t*p_dest++ = 0x6C000000 | FLG<<15 | vu1::Loc&0x03FF;\r\n\tgif::pTag = (uint8 *)p_dest;\r\n\t*p_dest++ = 0x34000000;\r\n\t*p_dest++ = 0x10000000 | Addr;\r\n\t*p_dest   = 0x0000000F;\r\n\tdma::pLoc = (uint8 *)(p_dest+2);\r\n}\r\n#endif\r\n\r\n// end\r\n\r\n#if 0\r\n// original version\r\nvoid vu1::EndPrim(uint Eop)\r\n{\r\n\tvif::EndUNPACK();\r\n\tvif::UnpackSize--;\t\t\t// a fudge to ignore the giftag which was inside the unpack\r\n\tgif::EndTag1(Eop);\r\n}\r\n#else\r\n// a quicker version\r\nvoid vu1::EndPrim(uint Eop)\r\n{\r\n\tregister uint unpack_size = (dma::pLoc - vif::pVifCode - 4) >> 4;\r\n\tDbg_MsgAssert(unpack_size>0, (\"Error: unpack size 0 not supported for vu prims\\n\"));\r\n\tDbg_MsgAssert(unpack_size<=256, (\"Error: unpack size greater than 256\\n\"));\r\n\tvif::pVifCode[2] = unpack_size;\r\n\t((uint32 *)gif::pTag)[0] |= Eop<<15 | (unpack_size-1);\r\n\t((uint32 *)gif::pTag)[3] = unpack_size - 1;\r\n\tvu1::Loc += unpack_size;\r\n}\r\n#endif\r\n\r\n\r\n// output vector\r\n\r\nvoid vu1::StoreVec(Vec v)\r\n{\r\n\tvif::StoreV4_32F(v[0], v[1], v[2], v[3]);\r\n}\r\n\r\n\r\n// output matrix\r\n\r\nvoid vu1::StoreMat(Mat m)\r\n{\r\n\t#if 1\r\n\t// we basically need to copy 16 32 bit words\r\n\tregister uint32 * source = (uint32*)&m[0][0];\r\n\tregister uint32 * dest = (uint32*)dma::pLoc;\r\n\t// 16 copies\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t*dest++ = *source++;\r\n\t\r\n\tdma::pLoc = (uint8*) dest;\r\n\t\r\n\t#else\r\n\tvif::StoreV4_32F(m[0][0], m[0][1], m[0][2], m[0][3]);\r\n\tvif::StoreV4_32F(m[1][0], m[1][1], m[1][2], m[1][3]);\r\n\tvif::StoreV4_32F(m[2][0], m[2][1], m[2][2], m[2][3]);\r\n\tvif::StoreV4_32F(m[3][0], m[3][1], m[3][2], m[3][3]);\r\n\t#endif\r\n}\r\n\r\n\r\n// routine has a breakpoint for debugging\r\n\r\nvoid vu1::BreakpointPrim(uint FLG, uint Eop)\r\n{\r\n\tvif::UNPACK(0, V4_32, 1, FLG, SIGNED, 0);\r\n\tgif::Tag1(0, 0, 0, 0, 0, Eop, 0, VU1_ADDR(Breakpoint));\r\n\tLoc += 1;\r\n}\r\n\r\n\r\n//---------------------------------\r\n//\t\tS T A T I C   D A T A\r\n//---------------------------------\r\n\r\nuint vu1::Loc;\r\nuint vu1::Buffer;\r\nuint vu1::MaxBuffer;\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu1.h",
    "content": "#ifndef __VU_H\r\n#define __VU_H\r\n\r\n#include\t<core/defines.h>\r\n#include\t<core/math.h>\r\n\r\n// simplify VU1 call addresses\r\n#ifdef __PLAT_NGPS__\r\n#define VU1_ADDR(Label) ((uint)&(Label)/8)\r\n#endif\r\n#ifdef __PLAT_WN32__\r\n#define VU1_ADDR(Label) (Label)\r\n#endif\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nclass vu1\r\n{\r\n\r\npublic:\r\n\r\n\t//-------------------------------------------\r\n\t//\t\tS T A T I C   F U N C T I O N S\r\n\t//-------------------------------------------\r\n\r\n\tstatic void BeginPrim(uint FLG, uint Addr);\r\n\tstatic void EndPrim(uint Eop);\r\n\tstatic void BreakpointPrim(uint FLG, uint Eop);\r\n\tstatic void StoreVec(float v[4]);\r\n\tstatic void CopyQuads(uint32 *p0);\r\n\tstatic void CopyQuads(uint32 *p0,uint32 *p1);\r\n\tstatic void CopyQuads(uint32 *p0,uint32 *p1,uint32 *p2);\r\n\tstatic void CopyQuads(uint32 *p0,uint32 *p1,uint32 *p2, uint32 *p3);\r\n\tstatic void StoreVecAligned(float v[4]);\r\n\tstatic void CopyMat(float *p_mat);\r\n\tstatic void CopyMatAligned(float *p_mat);\r\n\tstatic void StoreMat(float m[4][4]);\r\n\tstatic void StoreMatAligned(float m[4][4]);\r\n\r\n\t//---------------------------------\r\n\t//\t\tS T A T I C   D A T A\r\n\t//---------------------------------\r\n\r\n\tstatic uint Loc;\r\n\tstatic uint Buffer;\r\n\tstatic uint MaxBuffer;\r\n\r\n}; // class vu1\r\n\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\ninline void asm_copy_vec(void* m0, void* m1)\r\n{\r\n\tasm __volatile__(\"\r\n\tlq    $6,0x0(%1)\r\n\tsq    $6,0x0(%0)\r\n\t\": : \"r\" (m0) , \"r\" (m1):\"$6\");\r\n}\r\n\r\ninline void vu1::StoreVecAligned(float v[4])\r\n{\r\n\tasm_copy_vec(dma::pLoc,v);\r\n\tdma::pLoc += 16;\r\n}\r\n\r\ninline void vu1::StoreMatAligned(float m[4][4])\r\n{\r\n\t*(Mth::Matrix*)dma::pLoc = *(Mth::Matrix*)(&m[0][0]);\r\n\tdma::pLoc += 64;\r\n}\r\n\r\ninline void vu1::CopyMatAligned(float *p_mat)\r\n{\r\n\t*(Mth::Matrix*)dma::pLoc = *((Mth::Matrix*)(p_mat));\r\n\tdma::pLoc += 64;\r\n}\r\n\r\ninline void vu1::CopyMat(float *p_mat)\r\n{\r\n\tuint32 *p = (uint32*)dma::pLoc;\r\n\tuint32 *p2 = (uint32*)p_mat;\r\n\tfor (int i=0;i<16;i++)\r\n\t\t*p++ = *p2++;\r\n\tdma::pLoc = (uint8*)p;\r\n}\r\n\r\n\r\n\r\ninline void vu1::CopyQuads(uint32 *p0)\r\n{\r\n\tuint32\t* p = (uint32*)dma::pLoc;\r\n\tp[0] = p0[0];\r\n\tp[1] = p0[1];\r\n\tp[2] = p0[2];\r\n\tp[3] = p0[3];\r\n\tdma::pLoc = (uint8*)(p+4);\r\n}\r\n\r\ninline void vu1::CopyQuads(uint32 *p0, uint32 *p1)\r\n{\r\n\tuint32\t* p = (uint32*)dma::pLoc;\r\n\tp[0] = p0[0];\r\n\tp[1] = p0[1];\r\n\tp[2] = p0[2];\r\n\tp[3] = p0[3];\r\n\tp[4] = p1[0];\r\n\tp[5] = p1[1];\r\n\tp[6] = p1[2];\r\n\tp[7] = p1[3];\r\n\tdma::pLoc = (uint8*)(p+8);\r\n}\r\n\r\ninline void vu1::CopyQuads(uint32 *p0, uint32 *p1, uint32*p2)\r\n{\r\n\tuint32\t* p = (uint32*)dma::pLoc;\r\n\tp[0] = p0[0];\r\n\tp[1] = p0[1];\r\n\tp[2] = p0[2];\r\n\tp[3] = p0[3];\r\n\tp[4] = p1[0];\r\n\tp[5] = p1[1];\r\n\tp[6] = p1[2];\r\n\tp[7] = p1[3];\r\n\tp[8] = p2[0];\r\n\tp[9] = p2[1];\r\n\tp[10] = p2[2];\r\n\tp[11] = p2[3];\r\n\tdma::pLoc = (uint8*)(p+12);\r\n}\r\n\r\ninline void vu1::CopyQuads(uint32 *p0, uint32 *p1, uint32 *p2, uint32 *p3)\r\n{\r\n\tuint32\t* p = (uint32*)dma::pLoc;\r\n\tp[0] = p0[0];\r\n\tp[1] = p0[1];\r\n\tp[2] = p0[2];\r\n\tp[3] = p0[3];\r\n\tp[4] = p1[0];\r\n\tp[5] = p1[1];\r\n\tp[6] = p1[2];\r\n\tp[7] = p1[3];\r\n\tp[8] = p2[0];\r\n\tp[9] = p2[1];\r\n\tp[10] = p2[2];\r\n\tp[11] = p2[3];\r\n\tp[12] = p3[0];\r\n\tp[13] = p3[1];\r\n\tp[14] = p3[2];\r\n\tp[15] = p3[3];\r\n\tdma::pLoc = (uint8*)(p+16);\r\n}\r\n\r\n\t\r\n//\tstatic void StoreQuads(uint32 *p0,uint32 *p1);\r\n//\tstatic void StoreQuads(uint32 *p0,uint32 *p1,uint32 *p2);\r\n//\tstatic void StoreQuads(uint32 *p0,uint32 *p1,uint32 *p2, uint32 *p0);\r\n\r\n\r\n\r\n#endif\r\n\r\n\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n\r\n#endif // __VU_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu1code.dsm",
    "content": ";\r\n; set tab stops to 4 to read this file\r\n;\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; The result of assembling this file is a set of vif packets with vifcode MPG, used to upload\r\n; microcode to MicroMem1, the 16K program memory of VU1. There is only one MPG assembler\r\n; directive, but this is clever enough to split the assembled code into multiple packets when\r\n; the maximum MPG packet size (256 64-bit instruction slots, 2K of program) is exceeded.\r\n; There will be the need to manage multiple sets of microcode, once there's more than 16K\r\n; total.\r\n;\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n;\r\n; Very brief overview of rendering scheme\r\n; ---------------------------------------\r\n;\r\n; I decided where possible to take a 'process-in-place' approach to basic triangle rendering.\r\n; e.g. a pair of texture coordinates loaded to address 100 in VU memory will end up being\r\n; output as a pair of texture coordinates from the same address, on its way to the GS. This\r\n; is efficient because it reduces the amount of data copying, as sometimes the VU doesn't\r\n; need to touch the data - e.g. vertex colours can sometimes pass straight through without\r\n; further processing.\r\n;\r\n; This means the data should be at least triple-buffered for maximum efficiency, since there\r\n; are 3 processes that can run in parallel - sending data into memory via VIF1, processing\r\n; the data using VU1, and sending data out through the GIF to the GS. For maximum flexibility,\r\n; I have chosen to use VUMem1 (the VU1 data memory) as a cyclic buffer, letting the data\r\n; packets themselves ensure that the triple-buffering rule is not violated. (This is an\r\n; original approach - generally people use fixed buffers.)\r\n;\r\n; The result of processing renderable data in VU1 will be a GS packet (see EE User's Manual,\r\n; section 7.2, \"Data Format\"). Each GS packet is composed of GS primitives which begin with\r\n; a GIFtag. Following through to the max on the 'process-in-place' philosophy, I consider the\r\n; incoming geometry data to also consist of packets made up of primitives, each with a tag.\r\n; The tag is a superset of the GIFtag, appearing to the GIF as a valid GIFtag but making use\r\n; of the many unused bits of the GIFtag to signal additional info to VU1, eg the size of the\r\n; packet, the address of the microcode that should be used to process the packet, etc.\r\n; (This is also a pretty nifty idea, although using the spare bits is common practice.)\r\n;\r\n; There are 3 varieties of primitive - a VU prim, containing contextual VU data that will be\r\n; loaded into floating point VU1 registers (which doesn't need kicking to the GS), a GS prim,\r\n; containing contextual GS data that won't be touched by the VU but will be kicked directly\r\n; to the GS where it will set some of the GS registers, and finally a geometry prim which\r\n; contains renderable geometry and will be processed by the rendering code into a GS prim\r\n; that outputs something on the screen. But all varieties of prim use a common tag format so\r\n; they can be freely mixed in the data and parsed by a common piece of code.\r\n;\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; Registers used in the main parsing loop and in the renderers (all except for the clipping code)\r\n;\r\n; Integer registers:\r\n; VI00 - the constant zero register, always zero (doesn't change if you write something else to it)\r\n; VI01 - mainly temporary values, also hardwired as the result of the FCAND, FCEQ, FCOR instructions\r\n; VI02 - the data pointer as the prims are parsed\r\n; VI03 - an auxilliary data pointer, so that data can be read from one vertex while writing to another\r\n; VI04 - number of quadwords in each vertex of the current prim\r\n; VI05 - end address for the current prim\r\n; VI06 - size of the current prim\r\n; VI07 - \\\r\n; VI08 - \\\\\r\n; VI09 - -- temporaries\r\n; VI10 - //\r\n; VI11 - /\r\n; VI12 - address of current tag\r\n; VI13 - address of packet start\r\n; VI14 - render flags\r\n; VI15 - EOP:NLOOP from current tag\r\n\r\n; VF00 - the constant register (0,0,0,1) (doesn't change if you write something else to it)\r\n; VF01 - temporary value\r\n; VF02 - temporary value\r\n; VF03 - temporary value\r\n; VF04 - temporary value\r\n; VF05 - temporary value\r\n; VF06 - temporary value\r\n; VF07 - temporary value\r\n; VF08 - temporary value\r\n; VF09 - (Near, Far, k/(xRes/2), k/(yRes/2)) where k=viewport_scale_x, should be 2048 but is 1900 because of clipper problem\r\n; VF10 - inverse viewport scale vector\r\n; VF11 - inverse viewport offset vector\r\n; VF12 - row 0, local to viewport transform\r\n; VF13 - row 1, local to viewport transform\r\n; VF14 - row 2, local to viewport transform\r\n; VF15 - row 3, local to viewport transform\r\n; VF26 - lightsource 2 colour (r,g,b,?)\r\n; VF17 - row 0, reflection map transform\r\n; VF18 - row 1, reflection map transform\r\n; VF19 - row 2, reflection map transform\r\n; VF20 - light vectors, x components\r\n; VF21 - light vectors, y components\r\n; VF22 - light vectors, z components\r\n; VF23 - ambient colour (r,g,b,?)\r\n; VF24 - lightsource 0 colour (r,g,b,?)\r\n; VF25 - lightsource 1 colour (r,g,b,?)\r\n; VF16 - texture projection scale vector\r\n; VF27 - texture projection offset vector\r\n; VF28 - saves the z-components of the view matrix during a z-push\r\n; VF29 - \\\r\n; VF30 - - temporaries used in skinning code\r\n; VF31 - /\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\nCULL=0x01\t; per-triangle view culling\r\nCLIP=0x02\t; full 3D clipping of triangles\r\nSHDW=0x04\t; skinned=>cast shadow into texture; non-skinned=>render mesh with projected shadow texture on it\r\nCOLR=0x08\t; apply colour at vertices\r\nFOGE=0x10\t; calculate per-vertex fog coefficient\r\nWIRE=0x20\t; render skinned as wireframe (but doesn't render all edges)\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\n; Make the very start and end of the file available to the linker, so the dma packet that\r\n; sends the code (using a dma ref tag) can be constructed.\r\n.global MPGStart\r\n.global MPGEnd\r\n\r\n; here's a list of all the entry points into the microcode so they're available to the engine\r\n.global\tSetup\r\n.global\tJump\r\n.global Breakpoint\r\n.global\tParseInit\r\n.global\tParser\r\n.global\tL_VF09\r\n.global\tL_VF10\r\n.global\tL_VF11\r\n.global\tL_VF12\r\n.global\tL_VF13\r\n.global\tL_VF14\r\n.global\tL_VF15\r\n.global\tL_VF16\r\n.global\tL_VF17\r\n.global\tL_VF18\r\n.global\tL_VF19\r\n.global\tL_VF20\r\n.global\tL_VF21\r\n.global\tL_VF22\r\n.global\tL_VF23\r\n.global\tL_VF24\r\n.global\tL_VF25\r\n.global\tL_VF26\r\n.global\tL_VF27\r\n.global\tL_VF28\r\n.global\tL_VF29\r\n.global\tL_VF30\r\n.global\tL_VF31\r\n.global\tGSPrim\r\n.global Sprites\r\n.global SpriteCull\r\n.global ReformatXforms\r\n.global ShadowVolumeSkin\r\n\r\n; These entry points are currently not used, because the entry points are being generated in\r\n; the scene converter which doesn't have the linker information available for the microcode.\r\n; Instead there is a temporary jump table at the top of program memory, branching to each\r\n; routine via fixed known locations.\r\n.global Proj\r\n.global PTex\r\n.global Refl\r\n.global Line\r\n.global Skin\r\n\r\n; align to a 2^4=16 byte boundary, so it can be the target of a dma::ref\r\n.align\t4\r\n\r\n; label so the engine knows where to start dma'ing the microcode from\r\nMPGStart:\r\n\r\n; The MPG directive (ended by .EndMPG at the bottom of the file) is the assembler mechanism\r\n; for constructing a vif packet using the MPG vifcode, which tells the vif to upload the\r\n; subsequent data as vu microcode. But it's cleverer than that, because (a) it will split\r\n; the data into multiple MPG vif packets if the maximum size for MPG is exceeded (2K), and\r\n; (b) all labels between the MPG and the .EndMPG will be reduced so that not only are they\r\n; relative to the start of the MPG block, but also act as if any extra MPG vifcodes inserted\r\n; into the data didn't really exist... as if the assembler output really contained just the\r\n; microcode and not the extra vifcodes, just like it will be when it reaches MicroMem1 (the\r\n; program memory of VU1).\r\n\r\nMPG 0, *\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; Jump table. (This can later be eliminated with a mechanism for supplying vu1 label\r\n; addresses to the scene converter.)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tBreakpoint\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tParseInit\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tParser\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF09\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF10\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF11\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF12\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF13\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF14\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF15\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF16\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF17\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF18\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF19\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF20\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF21\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF22\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF23\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF24\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF25\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF26\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF27\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF28\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF29\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF30\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tL_VF31\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tGSPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\nProj:\tNOP\t\t\t\t\t\t\t\tB\t\t\tProj1\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\nPTex:\tNOP\t\t\t\t\t\t\t\tB\t\t\tPTex1\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\nRefl:\tNOP\t\t\t\t\t\t\t\tB\t\t\tRefl1\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\nLine:\tNOP\t\t\t\t\t\t\t\tB\t\t\tLine1\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\nSkin:\tNOP\t\t\t\t\t\t\t\tB\t\t\tSkin1\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\nLight:\tNOP\t\t\t\t\t\t\t\tB\t\t\tLight1\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI00,0\r\nLightT:\tNOP\t\t\t\t\t\t\t\tB\t\t\tLight1\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI00,1\r\nWibbleT:NOP\t\t\t\t\t\t\t\tB\t\t\tWibbleT1\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\nLWibT:\tNOP\t\t\t\t\t\t\t\tB\t\t\tLWibT1\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI00,1\r\nAddZPush:NOP\t\t\t\t\t\t\tB\t\t\tZPush\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t16\r\nSubZPush:NOP\t\t\t\t\t\t\tB\t\t\tRestoreZPush\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\nSetup:\tNOP[E]\t\t\t\t\t\t\tXTOP\t\tVI02\t\t\t\t; initialise input pointer and halt\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\nJump:\tNOP\t\t\t\t\t\t\t\tB\t\t\tJumpToIt\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\nSCAB:\tNOP\t\t\t\t\t\t\t\tB\t\t\tScreenAlignedBillboards\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\nLAB:\tNOP\t\t\t\t\t\t\t\tB\t\t\tLongAxisBillboards\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\nSHAB:\tNOP\t\t\t\t\t\t\t\tB\t\t\tShortAxisBillboards\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\nJumpToIt:\t; set new value for data pointer\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI02,VF01z\r\n\t\tNOP\t\t\t\t\t\t\t\tXTOP\t\tVI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\nBreakpoint:\t; for debugging purposes\r\n\r\n\t\tNOP[D]\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n;\r\n;\r\n;\r\n;\tͻ\r\n;\t tag format \r\n;\tͼ\r\n;\r\n;\tThis follows GIFtag format (EE User's Manual section 7.2.2), but with some added fields.\r\n;\r\n;\r\n;\r\n;\t 31 30                   23 22                16 15 14                                         0\r\n;\tĿ\r\n;\t0      NREG exponent      NREG mantissa      EOP                   NLOOP                    \r\n;\t\r\n;\r\n;\r\n;\t 63       60 59 58 57                            47 46 45    43 42                            32\r\n;\tĿ\r\n;\t   NREG     FLG               PRIM              PRE  FLAGS               ADDR              \r\n;\t\r\n;\r\n;\r\n;\t 95                                                       76 75       72 71       68 67       64\r\n;\tĿ\r\n;\t                                                     ...     [REG2]     [REG1]      REG0    \r\n;\t\r\n;\r\n;\r\n;\t 127                                         112 111                                          96\r\n;\tĿ\r\n;\t                                                                     SIZE                     \r\n;\t\r\n;\r\n;\r\n;\r\n; Added fields:\r\n;\r\n; bits 22-16:\tthe mantissa of ((float)NREG*powf(2,-23))\r\n; bits 23-30:\tthe exponent of ((float)NREG*powf(2,-23))\r\n; bit  31:\t\tzero, the a sign bit for treating the x-component as a float\r\n;\r\n; bits 32-42:\tADDR, the vu1 code address for processing the current primitive\r\n; bits 43-45:\tFLAGS, 43=unused, 44=u-clamp, 45=v-clamp\r\n;\r\n; bits 96-111:\tSIZE=NREG*NLOOP\r\n;\r\n; bits 112-127:\tunused\r\n;\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; This is the main loop that parses the incoming packet data. Each iteration of PrimLoop will do this:\r\n; - set VI04 to NREG, the vertex step size\r\n; - set VI05 to the end address for the current prim\r\n; - set VI06 to NREG*NLOOP, the size of the current prim\r\n; - set VI15 to hold EOP in its sign bit\r\n; - jump the the address of the renderer that will process the prim\r\n; The two entry points are Parser, which maintains the previous value of the data pointer VI02,\r\n; and ParseInit, which first initialises VI02 to the value in VIF1_TOP.\r\n\r\n\r\nParseInit:\r\n\t\tNOP\t\t\t\t\t\t\t\tXTOP\t\tVI02\t\t\t\t; initialise VI02\r\n\r\nParser: NOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; get 1st tag\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI13,VI02,1\t\t\t; VI13 = start address of current packet\r\n\t\tNOP\t\t\t\t\t\t\t\tXITOP\t\tVI14\t\t\t\t; get run-time render flags from VIF1_ITOP\r\n\r\nPrimLoop:\r\n\t\tADDw.x\t\tVF02,VF01,VF00w\t\tMTIR\t\tVI15,VF01x\t\t\t; VI15=EOP:NLOOP, 'ADDw' is for extracting NREG\r\n\t\tFTOI0.y\t\tVF02,VF01\t\t\tMTIR\t\tVI01,VF01y\t\t\t; VI01 = ADDR, renderer address\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI06,VF01w\t\t\t; VI06 = SIZE = NREG*NLOOP, size of prim (excl. tag)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI05,VI02,VI06\t\t; VI05 = end pointer for prim\r\n\t\tNOP\t\t\t\t\t\t\t\tJR\t\t\tVI01\t\t\t\t; jump to renderer\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI04,VF02x\t\t\t; VI04 = NREG (branch delay slot)\r\n\r\nNextPrim:\r\n\t\tNOP\t\t\t\t\t\t\t\tIBGEZ\t\tVI15,PrimLoop\t\t; loop if EOP==0\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\nKickPacket:\r\n\r\n\t\t; kick and stop\r\n\t\tNOP[E]\t\t\t\t\t\t\tXGKICK\t\tVI13\t\t\t\t; kick the processed packet to the GS\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI02,VI02,1\t\t\t; undo last postincrement (VI02 points to next packet)\r\n\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; Process a VU1 prim\r\n; ------------------\r\n; by loading the designated floating point registers.\r\n; It loads registers consecutively, starting from any register (VF09 or higher) and ending on\r\n; any of VF11, VF15, VF19, VF23, VF27 or VF31. The decision to load in batches of 4 was because\r\n; one often wants to load matrices as contextual data, and also to save having to put a test\r\n; (plus the necessary delay slots) after each individual register load... it just means having\r\n; to sometimes pad out the VU1 context to a 4-register boundary.\r\n\r\nL_VF09:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF09,(VI02++)\t\t; entry point for loading VF09, etc\r\nL_VF10:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF10,(VI02++)\r\nL_VF11:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF11,(VI02++)\r\n\r\n\t\tMULw.w\t\tVF24,VF11,VF00w\t\tDIV\t\t\tQ,VF00w,VF10w\r\n\t\tSUB.w\t\tVF11,VF00,VF00\t\tIBEQ\t\tVI02,VI05,VUPrimEnd\r\n\t\tMULq.w\t\tVF23,VF00,Q\t\t\tWAITQ\t\t\t\t\t\t\t; VF23w = f0\r\n\t\t\r\nL_VF12:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF12,(VI02++)\r\nL_VF13:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF13,(VI02++)\r\nL_VF14:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF14,(VI02++)\r\nL_VF15:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF15,(VI02++)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI02,1\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,VUPrimEnd\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI01,VI05,VUPrimEnd\r\nL_VF16:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF16,(VI02++)\r\nL_VF17:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF17,(VI02++)\r\nL_VF18:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF18,(VI02++)\r\nL_VF19:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF19,(VI02++)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,VUPrimEnd\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\nL_VF20:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF20,(VI02++)\r\nL_VF21:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF21,(VI02++)\r\nL_VF22:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF22,(VI02++)\r\nL_VF23:\tNOP\t\t\t\t\t\t\t\tLQI.xyz\t\tVF23,(VI02++)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,VUPrimEnd\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\nL_VF24:\tNOP\t\t\t\t\t\t\t\tLQI.xyz\t\tVF24,(VI02++)\r\nL_VF25:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF25,(VI02++)\r\nL_VF26:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF26,(VI02++)\r\nL_VF27:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF27,(VI02++)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,VUPrimEnd\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\nL_VF28:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF28,(VI02++)\r\nL_VF29:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF29,(VI02++)\r\nL_VF30:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF30,(VI02++)\r\nL_VF31:\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF31,(VI02++)\r\n\r\nVUPrimEnd:\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; process a GS prim\r\n; -----------------\r\n; by simply stepping the data pointer over it.\r\n\r\nGSPrim:\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,0(VI05)\t\t; prefetch next tag\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI12,VI02,1\t\t\t; save the current tag address (see clipping code)\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI02,VI05,1\t\t\t; step data pointer past next tag\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\nCullPrim:\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI01,VI00,1\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.z\t\tVF01,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.z\t\tVF01,-1(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI06\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; zpush\r\n; -----\r\n; m_localToViewport[0][2] += m_localToViewport[0][3] * zPush * I / FogAlpha;\r\n; m_localToViewport[1][2] += m_localToViewport[1][3] * zPush * I / FogAlpha;\r\n; m_localToViewport[2][2] += m_localToViewport[2][3] * zPush * I / FogAlpha;\r\n; m_localToViewport[3][2] += m_localToViewport[3][3] * zPush * I / FogAlpha;\r\n; on entry, zPush is held in VF01w (from the tag)\r\n\r\n\t\t; new version, frees up VF12-15\r\n\t\t; still needs optimising\r\n\r\nZPush:\r\n\t\tMULi.w\t\tVF02,VF10,I\t\t\tNOP\r\n\r\n\t\tSUB.w\t\tVF28,VF00,VF00\t\tNOP\r\n\t\tADDz.x\t\tVF28,VF00,VF12z\t\tNOP\r\n\t\tADDz.y\t\tVF28,VF00,VF13z\t\tNOP\r\n\t\tADDz.z\t\tVF28,VF00,VF14z\t\tNOP\r\n\t\tADDz.w\t\tVF28,VF28,VF15z\t\tNOP\r\n\t\t\r\n\t\tMULw.w\t\tVF04,VF12,VF02w\t\tMR32.z\t\tVF02,VF01\r\n\t\tMULw.w\t\tVF05,VF13,VF02w\t\tNOP\r\n\t\tMULw.w\t\tVF06,VF14,VF02w\t\tNOP\r\n\t\tMULw.w\t\tVF07,VF15,VF02w\t\tNOP\r\n\t\tADDA.z\t\tACC,VF00,VF12\t\tNOP\r\n\t\tMADDw.z\t\tVF12,VF02,VF04\t\tNOP\r\n\t\tADDA.z\t\tACC,VF00,VF13\t\tNOP\r\n\t\tMADDw.z\t\tVF13,VF02,VF05\t\tNOP\r\n\t\tADDA.z\t\tACC,VF00,VF14\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\tMADDw.z\t\tVF14,VF02,VF06\t\tNOP\r\n\t\tADDA.z\t\tACC,VF00,VF15\t\tB\t\t\tNextPrim\r\n\t\tMADDw.z\t\tVF15,VF02,VF07\t\tNOP\r\n\r\nRestoreZPush:\r\n\r\n\t\tADDx.z\t\tVF12,VF00,VF28x\t\tNOP\r\n\t\tADDy.z\t\tVF13,VF00,VF28y\t\tNOP\r\n\t\tADDz.z\t\tVF14,VF00,VF28z\t\tNOP\r\n\t\tADDw.z\t\tVF15,VF00,VF28w\t\tNOP\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; vertex projection\r\n; -----------------\r\n; just transforms and projects the vertex coords, used for non-textured meshes\r\n\r\nProj1:\r\n\t\t; first some hackery added in as a bit of an afterthought, to support single-sided and colouring of meshes\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI11,VI00,0x0800\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI10,VI00,FOGE+1\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI14,VI14,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,SingleSided\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,Label00\r\n\r\nLabel00:NOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,COLR\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI14,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI14,VI14,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,ApplyColour\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,Label0\r\n\t\t\r\n\t\t; now branch to the appropriate rendering code\r\n\r\nLabel0:\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI14,VI00,Proj2\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,CULL\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI11,VI00,CLIP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI14,VI01,Cull\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,Cull\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI14,VI11,Clip\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.w\t\tVI01,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tCullPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\r\n\r\nProj2:\r\n\r\n\t\t.if 1\r\n\t\t\r\n\t\t; fog version\r\n\t\t\r\n\t\t; f = min(f0+k/w,1) = f0+(1/w)(1-f0)min(w0,w)\r\n\t\t; where k=w0(1-f0)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x45000FFF\r\n\t\tMULi.w\t\tVF25,VF00,I\t\t\tNOP\t\t\t\t\t\t\t\t; VF25w = 2^11 + 1 - 2^-12\r\n\t\tSUBw.w\t\tVF25,VF25,VF23w\t\tNOP\t\t\t\t\t\t\t\t; VF25w = 2^11 + 1-f0 - 2^-12\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t8\r\n\t\tADDi.w\t\tVF26,VF25,I\t\t\tNOP\t\t\t\t\t\t\t\t; VF26w = VF25w + ADC\r\n\t\t\r\n\r\n\r\n\r\n\t\t.if 0\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\t\r\nLoopP:\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyzw\t\tVF01,-1(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tMTIR\t\tVI07,VF01w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF23w,VF03w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMINI.w\t\tVF03,VF03,VF24w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBLTZ\t\tVI07,CullP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULAw\t\tACC,VF00,VF25w\t\tNOP\r\n\t\tMADDq.xyzw\tVF04,VF03,Q\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI4.xyz\tVF04,VF04\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyzw\t\tVF04,-1(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\nCullP:\tMULAw\t\tACC,VF00,VF26w\t\tNOP\r\n\t\tMADDq.xyzw\tVF04,VF03,Q\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI4.xyz\tVF04,VF04\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyzw\t\tVF04,-1(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\n\t\t\r\n\t\t.else\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ.xyzw\t\tVF01,-1(VI03)\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tMTIR\t\tVI07,VF01w\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tLQ.xyzw\t\tVF01,-1(VI03)\r\n\t\tMADDz\t\tVF04,VF14,VF02z\t\tNOP\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tDIV\t\t\tQ,VF23w,VF04w\r\n\t\tMINI.w\t\tVF04,VF04,VF24w\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tIBLTZ\t\tVI07,CullP0\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tMTIR\t\tVI07,VF01w\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tLQ.xyzw\t\tVF01,-1(VI03)\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tNOP\r\n\t\tMULAw\t\tACC,VF00,VF25w\t\tNOP\r\n\t\t\r\nLoopP:\tMADDq.xyzw\tVF05,VF04,Q\t\t\tMOVE.xyz\tVF04,VF03\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tMINI.w\t\tVF04,VF03,VF24w\t\tDIV\t\t\tQ,VF23w,VF03w\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tFTOI4.xyz\tVF05,VF05\t\t\tIBLTZ\t\tVI07,CullP\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tMTIR\t\tVI07,VF01w\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tLQ.xyzw\t\tVF01,-1(VI03)\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tIBNE\t\tVI02,VI05,LoopP\r\n\t\tMULAw\t\tACC,VF00,VF25w\t\tSQ.xyzw\t\tVF05,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\nCullP0:\tMADDAy\t\tACC,VF13,VF02y\t\tLQ.xyzw\t\tVF01,-1(VI03)\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tB\t\t\tLoopP\r\n\t\tMULAw\t\tACC,VF00,VF26w\t\tNOP\r\n\r\nCullP:\tMADDAy\t\tACC,VF13,VF02y\t\tLQ.xyzw\t\tVF01,-1(VI03)\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tIBNE\t\tVI02,VI05,LoopP\r\n\t\tMULAw\t\tACC,VF00,VF26w\t\tSQ.xyzw\t\tVF05,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n\r\n\t\t.endif\r\n\r\n\r\n\r\n\r\n\t\t.if 0\r\n\t\t\r\n\t\t; unoptimised version\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\t\t\t; source ptr = dest ptr\r\n\r\nLoopP:\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\t\t; step source ptr\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t; get vertex coords\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tNOP\t\t\t\t\t\t\t\t; vertex coords to float\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\t\t\t\t\t\t\t\t; row 3 view transform\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tNOP\t\t\t\t\t\t\t\t; row 1 view transform\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tNOP\t\t\t\t\t\t\t\t; row 2 view transform\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF02w\t\t; calc 1/w\r\n\t\tNOP\t\t\t\t\t\t\t\tWAITQ\r\n\t\tMULq.xyz\tVF03,VF02,Q\t\t\tNOP\t\t\t\t\t\t\t\t; homogeneous divide\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\t\t; step dest ptr\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF03,-1(VI02)\t\t; store screen coords\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopP\t\t; loop\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; prefetch next tag\r\n\r\n\t\t.endif\r\n\t\t.else\r\n\t\t.if 1\r\n\t\t\r\n\t\t; fairly optimised version\r\n\t\t; 7 cycles per vertex\r\n\t\t\r\n\t\t; loop prologue\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI02,VI04\t\t\t\t\t\t\t\t\t; init/step source ptr\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t; row 3 view transform\t\t; get 1st vertex\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tIADD\t\tVI03,VI03,VI04\t\t; 1st vertex to float\t\t; step source ptr\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t; row 0 view transform\t\t; get 2nd vertex\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tIADD\t\tVI03,VI03,VI04\t\t; row 1 view transform\t\t; step source ptr\r\n\t\tMADDz\t\tVF04,VF14,VF02z\t\tNOP\t\t\t\t\t\t\t\t; row 2 view transform\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t; 2nd vertex to float\t\t; get 3rd vertex\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tDIV\t\t\tQ,VF00w,VF04w\t\t; row 3 view transform\t\t; calc 1/w\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tNOP                             ; row 1 view transform\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tNOP                             ; row 2 view transform\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tNOP\t\t\t\t\t\t\t\t; 3rd vertex to float\r\n\r\n\t\t; projection loop\t\t\r\nLoopP:\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\t\t\t\t\t\t\t\t\t; step source ptr\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t; row 3 view transform\t\t; get vertex coords\r\n\t\tMULq.xyz\tVF05,VF04,Q\t\t\tDIV\t\t\tQ,VF00w,VF03w\t\t; homogeneous div (xyz)/w\t; calc 1/w\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tIADD\t\tVI02,VI02,VI04\t\t; row 0 view transform\t\t; step destination ptr\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tMOVE.xyz\tVF04,VF03\t\t\t; row 1 view transform\t\t; advance vertex queue\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tIBNE\t\tVI02,VI05,LoopP\t\t; row 2 view transform\t\t; loop\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tSQ.xyz\t\tVF05,-1(VI02)\t\t; vertex coord to float\t\t; store screen coords\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t\t\t\t\t\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t\t\t\t\t\t\t\t; prefetch next tag\r\n\r\n\t\t.else\r\n\t\t\r\n\t\t; very optimised version\r\n\t\t; 6 cycles per vertex, but uses a lot of code space\r\n\t\t\r\n\t\t; loop prologue\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI01,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI01,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t\t\t\t\t\t\t\t; get vertex 1\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF05,-1(VI01)\t\t\t\t\t\t\t\t\t; get vertex 0\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tIADD\t\tVI01,VI03,VI04\t\t; vertex 1 to float\r\n\t\tITOF4.xyz\tVF06,VF05\t\t\tIADD\t\tVI03,VI01,VI04\t\t; vertex 0 to float\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t\t\t\t\t\t\t\t; get vertex 3\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tLQ.xyz\t\tVF05,-1(VI01)\t\t\t\t\t\t\t\t\t; get vertex 2\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDz\t\tVF02,VF14,VF02z\t\tIADDIU\t\tVI01,VI00,1\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tIAND\t\tVI07,VI15,VI01\t\t; test for NLOOP odd\r\n\t\tMADDAx\t\tACC,VF12,VF06x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF06y\t\tNOP\r\n\t\tMADDz\t\tVF07,VF14,VF06z\t\tERCPR\t\tP,VF02w\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tNOP\t\t\t\t\t\t\t\t; vertex 3 to float\r\n\t\tITOF4.xyz\tVF06,VF05\t\t\tLQ.xyz\t\tVF05,-1(VI03)\t\t; vertex 2 to float\t\t\t; get vertex 4\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tDIV\t\t\tQ,VF00w,VF07w\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDz\t\tVF03,VF14,VF01z\t\tIBEQ\t\tVI07,VI00,LoopP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI05,VI05,VI04\t\t; finish 1 vertex early if NLOOP odd\r\n\t\r\nLoopP:\tMADDAx\t\tACC,VF12,VF06x\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t; row 0 vertex transform B\t; get vertex A\r\n\t\tMADDAy\t\tACC,VF13,VF06y\t\tIADD\t\tVI03,VI03,VI04\t\t; row 1 vertex transform B\t; step source ptr\r\n\t\tMULq.xyz\tVF04,VF07,Q\t\t\tERCPR\t\tP,VF03w\t\t\t\t; homogeneous div (xyz)/wB'\t; calculate 1/wA'\r\n\t\tMADDz\t\tVF07,VF14,VF06z\t\tMFP.w\t\tVF02,P\t\t\t\t; row 2 vertex transform B\t; get 1/wA\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tIADD\t\tVI02,VI02,VI04\t\t; vertex A to float\t\t\t; step destination ptr\r\n\t\tITOF4.xyz\tVF06,VF05\t\t\tLQ.xyz\t\tVF05,-1(VI03)\t\t; vertex B' to float\t\t; get vertex B\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tSQ.xyz\t\tVF04,-1(VI02)\t\t; row 3 vertex transform A\t; store screen coords B'\r\n\r\n\t\tMULw.xyz\tVF04,VF02,VF02w\t\tDIV\t\t\tQ,VF00w,VF07w\t\t; homogeneous div (xyz)/wA\t; calc 1/wB\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tIADD\t\tVI02,VI02,VI04\t\t; row 0 vertex transform A\t; step destination ptr\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIADD\t\tVI03,VI03,VI04\t\t; row 1 vertex transform A\t; step source ptr\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tIBEQ\t\tVI02,VI05,QuitP\t\t; row 2 vertex transform A\t; continue or quit\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tSQ.xyz\t\tVF04,-1(VI02)\t\t; row 3 vertex transform B'\t; store screen coords A\r\n\r\n\t\tMADDAx\t\tACC,VF12,VF06x\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t; row 0 vertex transform B'\t; get vertex A'\r\n\t\tMADDAy\t\tACC,VF13,VF06y\t\tIADD\t\tVI03,VI03,VI04\t\t; row 1 vertex transform B' ; step source ptr\r\n\t\tMULq.xyz\tVF04,VF07,Q\t\t\tERCPR\t\tP,VF02w\t\t\t\t; homogeneous div (xyz)/wB\t; calc 1/wA\r\n\t\tMADDz\t\tVF07,VF14,VF06z\t\tMFP.w\t\tVF03,P\t\t\t\t; row 2 vertex transform B'\t; get 1/wA'\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tIADD\t\tVI02,VI02,VI04\t\t; vertex A' to float\t\t; step destination ptr\r\n\t\tITOF4.xyz\tVF06,VF05\t\t\tLQ.xyz\t\tVF05,-1(VI03)\t\t; vertex B to float\t\t\t; get vertex B'\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tSQ.xyz\t\tVF04,-1(VI02)\t\t; row 3 vertex transform A'\t; store screen coords B\r\n\r\n\t\tMULw.xyz\tVF04,VF03,VF03w\t\tDIV\t\t\tQ,VF00w,VF07w\t\t; homogeneous div (xyz)/wA'\t; calc 1/wB'\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tIADD\t\tVI02,VI02,VI04\t\t; row 0 vertex transform A'\t; step destination ptr\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIADD\t\tVI03,VI03,VI04\t\t; row 1 vertex transform A'\t; step source ptr\r\n\t\tMADDz\t\tVF03,VF14,VF01z\t\tIBNE\t\tVI02,VI05,LoopP\t\t; row 2 vertex transform A'\t; loop or quit\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tSQ.xyz\t\tVF04,-1(VI02)\t\t; row 3 vertex transform B\t; store screen coords A'\r\n\r\nQuitP:\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI07,VI00,EndP\t\t\t\t\t\t\t\t\t; finish if NLOOP was even\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULq.xyz\tVF04,VF07,Q\t\t\tIADD\t\tVI02,VI02,VI04\t\t; homogeneous div (xyz)/wB\t; step source ptr\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF04,-1(VI02)\t\t\t\t\t\t\t\t\t; store screen coords B\r\n\r\nEndP:\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t\t\t\t\t\t\t\t; back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t\t\t\t\t\t\t\t; prefetch next tag\r\n\r\n\t\t.endif\r\n\t\t.endif\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; triangle culling\r\n; ----------------\r\n; the per-triangle culling version of Proj\r\n\r\nCull:\r\n\r\n\r\n\t\t.if 1\r\n\t\t\r\n\t\t; fog version\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x45000FFF\r\n\t\tMULi.w\t\tVF25,VF00,I\t\t\tNOP\t\t\t\t\t\t\t\t; VF25w = 2^11 + 1 - 2^-12\r\n\t\tSUBw.w\t\tVF25,VF25,VF23w\t\tNOP\t\t\t\t\t\t\t\t; VF25w = 2^11 + 1-f0 - 2^-12\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI00,0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI10,0x4000\r\n\r\n\r\n\t\t.if 0\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\r\nLoopK:\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyzw\t\tVF01,-1(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tMTIR\t\tVI07,VF01w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF03\t\tDIV\t\t\tQ,VF23w,VF03w\r\n\t\tMADDw\t\tVF04,VF11,VF03w\t\tNOP\r\n\t\tMINI.w\t\tVF03,VF03,VF24\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF04xyz,VF04w\t\tNOP\r\n\t\tMULAw\t\tACC,VF00,VF25w\t\tNOP\r\n\t\tMADDq.xyzw\tVF05,VF03,Q\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullK\r\n\t\tFTOI4.xyz\tVF06,VF05\t\t\tMTIR\t\tVI01,VF05w\r\n\t\tNOP\t\t\t\t\t\t\t\tIOR\t\t\tVI01,VI01,VI07\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF06,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopK\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyzw\t\tVF06,-1(VI02)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\nCullK:\tNOP\t\t\t\t\t\t\t\tIOR\t\t\tVI01,VI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF06,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopK\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyzw\t\tVF06,-1(VI02)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n\r\n\t\t.else\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\t\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tMTIR\t\tVI06,VF01w\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tADDx.xyz\tVF04,VF02,VF00x\t\tDIV\t\t\tQ,VF23w,VF02w\r\n\t\tMULA\t\tACC,VF10,VF02\t\tNOP\r\n\t\tMADDw\t\tVF03,VF11,VF02w\t\tNOP\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tIADDIU\t\tVI07,VI06,0\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tMTIR\t\tVI06,VF01w\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tNOP\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tNOP\r\n\t\t\r\nLoopK:\tMULAw\t\tACC,VF00,VF25w\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDq\t\tVF05,VF04,Q\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tADDx.xyz\tVF04,VF02,VF00x\t\tDIV\t\t\tQ,VF23w,VF02w\r\n\t\tMULA\t\tACC,VF10,VF02\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tMADDw\t\tVF03,VF11,VF02w\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tIBNE\t\tVI01,VI00,CullK\r\n\t\tMINIw.w\t\tVF04,VF02,VF24w\t\tMTIR\t\tVI01,VF05w\r\n\t\tFTOI4.xyz\tVF06,VF05\t\t\tIOR\t\t\tVI01,VI01,VI07\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tMFIR.w\t\tVF06,VI01\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tIADDIU\t\tVI07,VI06,0\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tMTIR\t\tVI06,VF01w\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tIBNE\t\tVI02,VI05,LoopK\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tSQ\t\t\tVF06,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\nCullK:\tFTOI4.xyz\tVF06,VF05\t\t\tIOR\t\t\tVI01,VI01,VI10\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tMFIR.w\t\tVF06,VI01\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tIADDIU\t\tVI07,VI06,0\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tMTIR\t\tVI06,VF01w\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tIBNE\t\tVI02,VI05,LoopK\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tSQ\t\t\tVF06,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t.endif\r\n\r\n\r\n\t\t.else\r\n\r\n\t\t.if 0\r\n\t\t; unoptimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\t\t\t; source ptr = dest ptr\r\n\t\tFTOI15.w\tVF05,VF00\t\t\tNOP\t\t\t\t\t\t\t\t; set VF05w=0x8000 (for ADC bit)\r\n\r\nLoopK:\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\t\t; step source ptr\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t; get vertex coords\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tNOP\t\t\t\t\t\t\t\t; vertex coords to float\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\t\t\t\t\t\t\t\t; row 3 view transform\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tNOP\t\t\t\t\t\t\t\t; row 1 view transform\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tNOP\t\t\t\t\t\t\t\t; row 2 view transform\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF03\t\tDIV\t\t\tQ,VF00w,VF03w\t\t; inv viewport scale\t; calc 1/w\r\n\t\tMADDw\t\tVF06,VF11,VF03w\t\tNOP\t\t\t\t\t\t\t\t; inv viewport offset\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF06xyz,VF06w\t\tNOP\t\t\t\t\t\t\t\t; generate outcodes\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULq.xyz\tVF05,VF03,Q\t\t\tNOP\t\t\t\t\t\t\t\t; homogeneous divide\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\t\t; step dest ptr\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x03FFFF\t\t; test last 3 outcodes\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullK\t\t; cull if all out\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopK\t\t; loop\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF05,-1(VI02)\t\t; store screen coords\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; prefetch next tag\r\n\r\nCullK:\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopK\t\t; loop\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF05,-1(VI02)\t\t; store screen coords\r\n\t\t\r\n\t\t.else\r\n\t\t; optimised\r\n\t\t\r\n\t\tFTOI15.w\tVF05,VF00\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDz\t\tVF04,VF14,VF02z\t\tNOP\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tMULA\t\tACC,VF10,VF04\t\tDIV\t\t\tQ,VF00w,VF04w\r\n\t\tMADDw\t\tVF06,VF11,VF04w\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tNOP\r\n\t\t\r\nLoopK:\tCLIPw.xyz\tVF06xyz,VF06w\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMULq.xyz\tVF05,VF04,Q\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tMULA\t\tACC,VF10,VF03\t\tDIV\t\t\tQ,VF00w,VF03w\r\n\t\tMADDw\t\tVF06,VF11,VF03w\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tIBNE\t\tVI01,VI00,CullK\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tMOVE.xyz\tVF04,VF03\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tIBNE\t\tVI02,VI05,LoopK\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tSQ.xyz\t\tVF05,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; prefetch next tag\r\n\r\nCullK:\tMADDAy\t\tACC,VF13,VF02y\t\tIBNE\t\tVI02,VI05,LoopK\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tSQ\t\t\tVF05,-1(VI02)\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; prefetch next tag\r\n\r\n\t\t\r\n\t\t.endif\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; vertex projection with perspective texturing\r\n; --------------------------------------------\r\n; transforms and projects vertex coords, and applies perspective to texture coords\r\n\r\n\r\n\r\n\t\t\r\nPTex1:\r\n\r\n\t\t; first some hackery added in as a bit of an afterthought, to support single-sided and colouring of meshes\r\n\t\t; and switch between VU1-fogging and standard version of rendering code\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI00,0x0800\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI10,VI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI11,VI00,0x3000\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI11,VI01,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI10,VI00,SingleSided\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,Label1\r\nLabel1:\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,COLR\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI14,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI14,VI14,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,ApplyColour\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,Label2\r\nLabel2:\r\n\r\n\t\t; test for fog enable\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.y\t\tVF02,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,FOGE\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI14,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI14,VI14,VI01\t\t; clear FOGE flag\r\n\t\tITOF12.y\tVF02,VF02\t\t\tIBNE\t\tVI01,VI00,PTexFog\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,3\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x302E4000\r\n\t\tADDAi.y\t\tACC,VF00,I\t\t\tLOI\t\t\t0x2A800000\r\n\t\tMADDi.y\t\tVF01,VF02,I\t\t\tIBEQ\t\tVI04,VI01,FGE0\t\t; keep uv-clamp flags\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x4F800000\r\n\t\tMULi.y\t\tVF01,VF01,I\t\t\tNOP\r\nFGE0:\tNOP\t\t\t\t\t\t\t\tSQ.y\t\tVF01,-1(VI02)\t\t; clear FGE bit\r\n\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI14,VI00,PTex2\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,CULL\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI11,VI00,CLIP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI14,VI01,CullPTex\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,CullPTex\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI14,VI11,Clip\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.w\t\tVI01,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tShadow\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\nPTexFog:\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI14,VI00,PTex2F\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,CULL\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI11,VI00,CLIP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI14,VI01,CullPTexF\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,CullPTexF\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI14,VI11,Clip\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.w\t\tVI01,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tShadow\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\r\n\r\n\t\t\r\nPTex2F:\r\n\t\t; fog version\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x45000FFF\r\n\t\tMULi.w\t\tVF25,VF00,I\t\t\tNOP\t\t\t\t\t\t\t\t; VF25w = 2^11 + 1 - 2^-12\r\n\t\tSUBw.w\t\tVF25,VF25,VF23w\t\tNOP\t\t\t\t\t\t\t\t; VF25w = 2^11 + 1-f0 - 2^-12\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t8\r\n\t\tADDi.w\t\tVF26,VF25,I\t\t\tNOP\t\t\t\t\t\t\t\t; VF26w = VF25w + ADC\r\n\r\n\r\n\r\n\t\t.if 0\r\n\t\t\r\n\t\t; unoptimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\tNOP\t\t\t\t\t\t\t\tMR32.z\t\tVF07,VF00\r\n\r\n\t\t\r\nLoopPTF:NOP\t\t\t\t\t\t\t\tLQ.xy\t\tVF06,0(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyzw\t\tVF01,-1(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF12.xy\tVF07,VF06\t\t\tNOP\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tMTIR\t\tVI07,VF01w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF23w,VF03w\r\n\t\tMINI.w\t\tVF03,VF03,VF24\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBLTZ\t\tVI07,PTCullF\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULAw\t\tACC,VF00,VF25w\t\tNOP\r\n\t\tMULq.xyz\tVF08,VF07,Q\t\t\tNOP\r\n\t\tMADDq\t\tVF04,VF03,Q\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF08,0(VI02)\r\n\t\tFTOI4.xyz\tVF04,VF04\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopPTF\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyzw\t\tVF04,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\nPTCullF:MULAw\t\tACC,VF00,VF26w\t\tNOP\r\n\t\tMULq.xyz\tVF08,VF07,Q\t\t\tNOP\r\n\t\tMADDq\t\tVF04,VF03,Q\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF08,0(VI02)\r\n\t\tFTOI4.xyz\tVF04,VF04\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopPTF\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyzw\t\tVF04,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\n\t\t\r\n\t\t.else\r\n\t\t\r\n\t\t; optimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tLQ.xy\t\tVF07,0(VI02)\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tLQ.xy\t\tVF05,0(VI03)\r\n\t\tMADDz\t\tVF03,VF14,VF01z\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMINI.w\t\tVF03,VF03,VF24\t\tDIV\t\t\tQ,VF23w,VF03w\r\n\t\tITOF12.xy\tVF07,VF07\t\t\tMTIR\t\tVI07,VF01w\r\n\t\tITOF12.xy\tVF06,VF05\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tMR32.z\t\tVF07,VF00\r\n\t\t\r\nLoopPTF:MADDAx\t\tACC,VF12,VF01x\t\tLQ.xy\t\tVF05,0(VI03)\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMULq\t\tVF04,VF03,Q\t\t\tIBLTZ\t\tVI07,PTCullF\r\n\t\tMADDz\t\tVF03,VF14,VF01z\t\tMTIR\t\tVI07,VF01w\r\n\t\tMULq.xyz\tVF08,VF07,Q\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tADDx.xy\t\tVF07,VF06,VF00x\t\tIADDIU\t\tVI01,VI02,0\r\n\t\tFTOI4.xyz\tVF04,VF04\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tADD.w\t\tVF04,VF04,VF25\t\tDIV\t\t\tQ,VF23w,VF03w\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tSQ.xyz\t\tVF08,0(VI01)\r\n\t\tMINI.w\t\tVF03,VF03,VF24\t\tNOP\r\n\t\tITOF12.xy\tVF06,VF05\t\t\tIBNE\t\tVI02,VI05,LoopPTF\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tSQ\t\t\tVF04,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\nPTCullF:MULq.xyz\tVF08,VF07,Q\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tADDx.xy\t\tVF07,VF06,VF00x\t\tIADDIU\t\tVI01,VI02,0\r\n\t\tFTOI4.xyz\tVF04,VF04\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tADD.w\t\tVF04,VF04,VF26\t\tDIV\t\t\tQ,VF23w,VF03w\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tSQ.xyz\t\tVF08,0(VI01)\r\n\t\tMINI.w\t\tVF03,VF03,VF24\t\tNOP\r\n\t\tITOF12.xy\tVF06,VF05\t\t\tIBNE\t\tVI02,VI05,LoopPTF\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tSQ\t\t\tVF04,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t; non-fogged version\r\n\t\t\r\nPTex2:\r\n\r\n\r\n\t\t.if 0\r\n\t\t; unoptimised version\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\t\t\t; source ptr = dest ptr\r\n\t\tNOP\t\t\t\t\t\t\t\tMR32.z\t\tVF04,VF00\t\t\t; set 1 in (s,t,1)\r\n\r\nLoopPT:\tNOP\t\t\t\t\t\t\t\tLQ.xy\t\tVF04,0(VI03)\t\t; get texture coords\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\t\t; step source ptr\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t; get vertex coords\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF12.xy\tVF04,VF04\t\t\tNOP\t\t\t\t\t\t\t\t; texture coords to float\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tNOP\t\t\t\t\t\t\t\t; vertex coords to float\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\t\t\t\t\t\t\t\t; row 3 view transform\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tNOP\t\t\t\t\t\t\t\t; row 1 view transform\t\t\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tNOP\t\t\t\t\t\t\t\t; row 2 view transform\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF23w,VF02w\t\t; calc 1/w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULq.xyz\tVF05,VF04,Q\t\t\tNOP\t\t\t\t\t\t\t\t; homogeneous div (st1)/w\r\n\t\tMULq.xyz\tVF03,VF02,Q\t\t\tNOP\t\t\t\t\t\t\t\t; homogeneous div (xyz)/w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI4.xyz\tVF03,VF03\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF05,0(VI02)\t\t; store texture coords\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\t\t; step dest ptr\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF03,-1(VI02)\t\t; store screen coords\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopPT\t; loop\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; prefetch next tag\r\n\t\t\r\n\t\t.else\r\n\t\t\r\n\t\t; optimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tLQ.xy\t\tVF05,0(VI02)\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tLQ.xy\t\tVF06,0(VI03)\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDz\t\tVF03,VF14,VF01z\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tITOF12.xy\tVF07,VF05\t\t\tNOP\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tMR32.z\t\tVF07,VF00\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tDIV\t\t\tQ,VF23w,VF03w\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tLQ.xy\t\tVF05,0(VI03)\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tMULq.xyz\tVF08,VF07,Q\t\t\tWAITQ\r\n\t\tMULq.xyz\tVF04,VF03,Q\t\t\tNOP\r\n\t\t\r\nLoopPT:\tITOF12.xy\tVF07,VF06\t\t\tMOVE.xy\t\tVF06,VF05\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tDIV\t\t\tQ,VF23w,VF02w\r\n\t\tADDx.xyz\tVF03,VF02,VF00x\t\tSQ.xyz\t\tVF08,0(VI02)\r\n\t\tFTOI4.xyz\tVF04,VF04\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tLQ.xy\t\tVF05,0(VI03)\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tMULq.xyz\tVF08,VF07,Q\t\t\tIBNE\t\tVI02,VI05,LoopPT\r\n\t\tMULq.xyz\tVF04,VF03,Q\t\t\tSQ.xyz\t\tVF04,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; triangle culling and perspective texturing\r\n\r\n\r\nCullPTexF:\r\n\r\n\t\t; fog version\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x45000FFF\r\n\t\tMULi.w\t\tVF25,VF00,I\t\t\tNOP\t\t\t\t\t\t\t\t; VF25w = 2^11 + 1 - 2^-12\r\n\t\tSUBw.w\t\tVF25,VF25,VF23w\t\tNOP\t\t\t\t\t\t\t\t; VF25w = 2^11 + 1-f0 - 2^-12\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI00,0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI10,0x4000\r\n\t\t\r\n\t\t\r\n\t\t.if 0\r\n\t\t; unoptimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\tNOP\t\t\t\t\t\t\t\tMR32.z\t\tVF07,VF00\r\n\r\n\t\t\r\nLoopKPTF:\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xy\t\tVF07,0(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyzw\t\tVF01,-1(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF12.xy\tVF07,VF07\t\t\tNOP\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tMTIR\t\tVI07,VF01w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF03\t\tDIV\t\t\tQ,VF23w,VF03w\r\n\t\tMADDw\t\tVF04,VF11,VF03w\t\tNOP\r\n\t\tMINI.w\t\tVF03,VF03,VF24\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF04xyz,VF04w\t\tNOP\r\n\t\tMULAw\t\tACC,VF00,VF25w\t\tNOP\r\n\t\tMULq.xyz\tVF08,VF07,Q\t\t\tNOP\r\n\t\tMADDq\t\tVF05,VF03,Q\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullKPTF\r\n\t\tFTOI4.xyz\tVF06,VF05\t\t\tSQ.xyz\t\tVF08,0(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI11,VF05w\r\n\t\tNOP\t\t\t\t\t\t\t\tIOR\t\t\tVI11,VI11,VI07\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF06,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopKPTF\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyzw\t\tVF06,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\nCullKPTF:\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI11,VF05w\r\n\t\tNOP\t\t\t\t\t\t\t\tIOR\t\t\tVI11,VI11,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF06,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopKPTF\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyzw\t\tVF06,-1(VI02)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n\r\n\t\t.else\r\n\t\t; optimised\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ\t\t\tVF04,-1(VI03)\r\n\t\tITOF4.xyz\tVF04,VF04\t\t\tLQ.xy\t\tVF07,0(VI02)\r\n\t\tMADDAx\t\tACC,VF12,VF04x\t\tMTIR\t\tVI07,VF04w\r\n\t\tMADDAy\t\tACC,VF13,VF04y\t\tLQ.xy\t\tVF06,0(VI03)\r\n\t\tMADDz\t\tVF04,VF14,VF04z\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tITOF12.xy\tVF07,VF07\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tMULA\t\tACC,VF10,VF04\t\tDIV\t\t\tQ,VF23w,VF04w\r\n\t\tMADDw\t\tVF03,VF11,VF04w\t\tMR32.z\t\tVF07,VF00\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tNOP\r\n\t\tMINI.w\t\tVF04,VF04,VF24\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tNOP\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tNOP\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tNOP\r\n\t\t\r\nLoopKPTF:\r\n\t\tMULq.xyz\tVF08,VF07,Q\t\t\tMTIR\t\tVI06,VF01w\r\n\t\tITOF12.xy\tVF07,VF06\t\t\tLQ.xy\t\tVF06,0(VI03)\r\n\t\tMULAw\t\tACC,VF00,VF25w\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDq\t\tVF05,VF04,Q\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tADDx.xyz\tVF04,VF02,VF00x\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tMULA\t\tACC,VF10,VF02\t\tDIV\t\t\tQ,VF23w,VF02w\r\n\t\tMADDw\t\tVF03,VF11,VF02w\t\tSQ.xyz\t\tVF08,0(VI02)\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tIBNE\t\tVI01,VI00,CullKPTF\r\n\t\tMINI.w\t\tVF04,VF02,VF24\t\tMTIR\t\tVI11,VF05w\r\n\t\tFTOI4.xyz\tVF05,VF05\t\t\tIOR\t\t\tVI11,VI11,VI07\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tMFIR.w\t\tVF05,VI11\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIADDIU\t\tVI07,VI06,0\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tIBNE\t\tVI02,VI05,LoopKPTF\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tSQ.xyzw\t\tVF05,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\nCullKPTF:\r\n\t\tFTOI4.xyz\tVF05,VF05\t\t\tIOR\t\t\tVI11,VI11,VI10\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tMFIR.w\t\tVF05,VI11\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIADDIU\t\tVI07,VI06,0\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tIBNE\t\tVI02,VI05,LoopKPTF\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tSQ.xyzw\t\tVF05,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\n\t\t\r\n\r\n\r\n\t\t\r\n\t\t; non-fogged version\r\n\r\nCullPTex:\r\n\r\n\t\t.if 0\r\n\t\t; unoptimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\t\t\t; source ptr = dest ptr\r\n\t\tFTOI15.w\tVF05,VF00\t\t\tNOP\t\t\t\t\t\t\t\t; set VF05w=0x8000 (for ADC bit)\r\n\t\tNOP\t\t\t\t\t\t\t\tMR32.z\t\tVF07,VF00\t\t\t; set 1 in (s,t,1)\r\n\r\nLoopKPT:NOP\t\t\t\t\t\t\t\tLQ.xy\t\tVF07,0(VI03)\t\t; get tex coords\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\t\t; step source ptr\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t; get vertex coords\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF12.xy\tVF07,VF07\t\t\tNOP\t\t\t\t\t\t\t\t; tex coords to float\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tNOP\t\t\t\t\t\t\t\t; vertex coords to float\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\t\t\t\t\t\t\t\t; row 3 view transform\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tNOP\t\t\t\t\t\t\t\t; row 1 view transform\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tNOP\t\t\t\t\t\t\t\t; row 2 view transform\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF03\t\tDIV\t\t\tQ,VF23w,VF03w\t\t; inv viewport scale\t; calc 1/w\r\n\t\tMADDw\t\tVF06,VF11,VF03w\t\tNOP\t\t\t\t\t\t\t\t; inv viewport offset\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF06xyz,VF06w\t\tNOP\t\t\t\t\t\t\t\t; generate outcodes\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULq.xyz\tVF08,VF07,Q\t\t\tNOP\t\t\t\t\t\t\t\t; homogeneous divide (st1)/w\r\n\t\tMULq.xyz\tVF05,VF03,Q\t\t\tNOP\t\t\t\t\t\t\t\t; homogeneous divide (xyz)/w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x03FFFF\t\t; test last 3 outcodes\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF08,0(VI02)\r\n\t\tFTOI4.xyz\tVF05,VF05\t\t\tIADD\t\tVI02,VI02,VI04\t\t; step dest ptr\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullKPT\t; cull if all out\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopKPT\t; loop\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF05,-1(VI02)\t\t; store screen coords\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; prefetch next tag\r\n\r\nCullKPT:NOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopKPT\t; loop\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF05,-1(VI02)\t\t; store screen coords\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\n\t\t.else\r\n\t\t\r\n\t\t; optimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tLQ.xy\t\tVF05,0(VI02)\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tLQ.xy\t\tVF06,0(VI03)\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDz\t\tVF03,VF14,VF01z\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tITOF12.xy\tVF07,VF05\t\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF03\t\tNOP\r\n\t\tMADDw\t\tVF02,VF11,VF03w\t\tDIV\t\t\tQ,VF23w,VF03w\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tMR32.z\t\tVF07,VF00\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tISUBIU\t\tVI01,VI00,1\r\n\t\tCLIPw.xyz\tVF02xyz,VF02w\t\tMFIR.w\t\tVF04,VI01\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tNOP\r\n\t\t\r\nLoopKPT:MADDz\t\tVF02,VF14,VF01z\t\tLQ.xy\t\tVF05,0(VI03)\r\n\t\tMULq.xyz\tVF08,VF07,Q\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMULq.xyz\tVF04,VF03,Q\t\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tITOF12.xy\tVF07,VF06\t\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tMULA\t\tACC,VF10,VF02\t\tDIV\t\t\tQ,VF23w,VF02w\r\n\t\tMADDw\t\tVF03,VF11,VF02w\t\tMOVE.xy\t\tVF06,VF05\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tSQ.xyz\t\tVF08,0(VI02)\r\n\t\tFTOI4.xyz\tVF04,VF04\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tIBNE\t\tVI01,VI00,CullKPT\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tMOVE.xyz\tVF03,VF02\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tIBNE\t\tVI02,VI05,LoopKPT\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tSQ.xyz\t\tVF04,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\nCullKPT:MADDAx\t\tACC,VF12,VF01x\t\tIBNE\t\tVI02,VI05,LoopKPT\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tSQ\t\t\tVF04,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\nWibbleT1:\r\n\r\n\t\t.if 0\r\n\t\t; unoptimised version\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\t\r\nLoopW:\tNOP\t\t\t\t\t\t\t\tLQ.xy\t\tVF01,0(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF12.xy\tVF02,VF01\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADD.xy\t\tVF03,VF02,VF27\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI12.xy\tVF04,VF03\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xy\t\tVF04,0(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopW\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t.else\r\n\t\t; optimised version\r\n\t\t\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xy\t\tVF04,0(VI02)\r\n\t\tITOF12.xy\tVF04,VF04\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tADD.xy\t\tVF04,VF04,VF27\t\tLQ.xy\t\tVF03,0(VI03)\r\n\t\tITOF12.xy\tVF03,VF03\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tFTOI12.xy\tVF04,VF04\t\t\tLQ.xy\t\tVF02,0(VI03)\r\n\t\tADD.xy\t\tVF03,VF03,VF27\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tITOF12.xy\tVF02,VF02\t\t\tISUB\t\tVI05,VI05,VI04\r\n\t\t\r\nLoopW:\tNOP\t\t\t\t\t\t\t\tLQ.xy\t\tVF01,0(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xy\t\tVF04,0(VI02)\r\n\t\tFTOI12.xy\tVF04,VF03\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tADD.xy\t\tVF03,VF02,VF27      IBNE\t\tVI02,VI05,LoopW\r\n\t\tITOF12.xy\tVF02,VF01\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI05,VI05,VI04\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tPTex1\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\nLWibT1:\r\n\r\n\t\t; optimised version\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xy\t\tVF04,0(VI02)\r\n\t\tITOF12.xy\tVF04,VF04\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tADD.xy\t\tVF04,VF04,VF27\t\tLQ.xy\t\tVF03,0(VI03)\r\n\t\tITOF12.xy\tVF03,VF03\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tFTOI12.xy\tVF04,VF04\t\t\tLQ.xy\t\tVF02,0(VI03)\r\n\t\tADD.xy\t\tVF03,VF03,VF27\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tITOF12.xy\tVF02,VF02\t\t\tISUB\t\tVI05,VI05,VI04\r\n\t\t\r\nLoopLW:\tNOP\t\t\t\t\t\t\t\tLQ.xy\t\tVF01,0(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xy\t\tVF04,0(VI02)\r\n\t\tFTOI12.xy\tVF04,VF03\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tADD.xy\t\tVF03,VF02,VF27      IBNE\t\tVI02,VI05,LoopLW\r\n\t\tITOF12.xy\tVF02,VF01\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI05,VI05,VI04\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tLight1\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; reflection mapping\r\n\r\nRefl1:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI11,VI00,0x0800\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,SingleSided\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,LabelR0\r\n\r\nLabelR0:\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,COLR\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI14,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI14,VI14,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,ApplyColour\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,LabelR1\r\n\r\nLabelR1:\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,CLIP\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI14,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,ReflClip\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\n\t\t.if 0\r\n\t\t; unoptimised\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\tNOP\t\t\t\t\t\t\t\tMR32.z\t\tVF04,VF00\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0.5\r\n\r\nLoopR: \tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF05,0(VI03)\t\t; get normal\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\t\t; step source pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t; get vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF15.xyz\tVF05,VF05\t\t\tNOP\t\t\t\t\t\t\t\t; VF05 = n (unit, in model space)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tNOP\r\n\t\t\r\n\t\t; compute 0.5*(nx+vx/vz+1, ny+vy/vz+1)\r\n\t\tMULAx.xyz\tACC,VF17,VF02x\t\tNOP\t\t\t\t\t\t\t\t; transform v\r\n\t\tMADDAy.xyz\tACC,VF18,VF02y\t\tNOP\r\n\t\tMADDz.xyz\tVF02,VF19,VF02z\t\tNOP\r\n\t\tMULAx.xy\tACC,VF17,VF05x\t\tNOP\t\t\t\t\t\t\t\t; transform n\r\n\t\tMADDAy.xy\tACC,VF18,VF05y\t\tNOP\r\n\t\tMADDz.xy\tVF03,VF19,VF05z\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF02z\t\t; calc 1/vz'\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAi.xy\tACC,VF03,I\t\t\tNOP\r\n\t\tMSUBq.xy\tVF04,VF02,Q\t\t\tNOP\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF04,0(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopR\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tProj1\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\r\n\t\t.else\r\n\t\t; optimised\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF02,2(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF04,0(VI02)\r\n\t\tITOF4.xyz\tVF02,VF02\t\t\tMR32.z\t\tVF03,VF00\r\n\t\tITOF15.xyz\tVF05,VF04\t\t\tLOI\t\t\t0.5\r\n\t\tMULAx.xyz\tACC,VF17,VF02x\t\tLQ.xyz\t\tVF01,5(VI02)\r\n\t\tMADDAy.xyz\tACC,VF18,VF02y\t\tLQ.xyz\t\tVF04,3(VI02)\r\n\t\tMADDz.xyz\tVF02,VF19,VF02z\t\tNOP\r\n\t\tMULAx.xy\tACC,VF17,VF05x\t\tNOP\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tDIV\t\t\tQ,VF00w,VF02z\r\n\t\tMADDAy.xy\tACC,VF18,VF05y\t\tNOP\r\n\t\tMADDz.xy    VF27,VF19,VF05z\t\tNOP\r\n\t\tITOF15.xyz\tVF05,VF04\t\t\tNOP\r\n\t\t\r\nLoopR:\tMULAx.xyz\tACC,VF17,VF01x\t\tMOVE.xy\t\tVF03,VF02\r\n\t\tMADDAy.xyz\tACC,VF18,VF01y\t\tNOP\r\n\t\tMADDz.xyz\tVF02,VF19,VF01z\t\tLQ.xyz\t\tVF01,8(VI02)\r\n\t\tADDAi.xy\tACC,VF27,I\t\t\tLQ.xyz\t\tVF04,6(VI02)\r\n\t\tMSUBq.xy\tVF03,VF03,Q\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tMULAx.xy\tACC,VF17,VF05x\t\tNOP\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tDIV\t\t\tQ,VF00w,VF02z\r\n\t\tMADDAy.xy\tACC,VF18,VF05y\t\tNOP\r\n\t\tMADDz.xy    VF27,VF19,VF05z\t\tIBNE\t\tVI02,VI05,LoopR\r\n\t\tITOF15.xyz\tVF05,VF04\t\t\tSQ.xyz\t\tVF03,-3(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tProj2\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\r\n\t\t.endif\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\nReflClip:\r\n\r\n\t\t.if 0\r\n\t\t; unoptimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0.5\r\n\r\n\r\nLoopRC:\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF04,0(VI03)\t\t; get normal\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\t\t; step source pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t; get vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF15.xyz\tVF04,VF04\t\t\tNOP\t\t\t\t\t\t\t\t; VF01 = n (unit, in model space)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tNOP\r\n\t\t\r\n\t\t; compute ((nx'+0.5)*vz'-vx', (ny'+0.5)*vz'-vy', vz', 1/vz')\r\n\t\tMULAx.xyz\tACC,VF17,VF01x\t\tNOP\t\t\t\t\t\t\t\t; transform v\r\n\t\tMADDAy.xyz\tACC,VF18,VF01y\t\tNOP\r\n\t\tMADDz.xyz\tVF02,VF19,VF01z\t\tNOP\r\n\t\tADDAi.xy\tACC,VF00,I\t\t\tNOP\r\n\t\tMADDAx.xy\tACC,VF17,VF04x\t\tNOP\t\t\t\t\t\t\t\t; transform n\r\n\t\tMADDAy.xy\tACC,VF18,VF04y\t\tNOP\r\n\t\tMADDz.xy\tVF03,VF19,VF04z\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF02z\r\n\t\tSUBA.xy\t\tACC,VF00,VF02\t\tMOVE.z\t\tVF04,VF02\r\n\t\tMADDz.xy\tVF04,VF03,VF02z\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULq.w\t\tVF04,VF00,Q\t\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF04,0(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopRC\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,ReflPostClip\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tClip\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.w\t\tVI01,-1(VI02)\r\n\t\t\r\n\t\t.else\r\n\t\t; optimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF02,2(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF03,0(VI02)\r\n\t\tITOF4.xyz\tVF02,VF02\t\t\tLOI\t\t\t0.5\r\n\t\tITOF15.xyz\tVF04,VF03\t\t\tNOP\r\n\t\tMULAx.xyz\tACC,VF17,VF02x\t\tLQ.xyz\t\tVF03,3(VI02)\r\n\t\tMADDAy.xyz\tACC,VF18,VF02y\t\tLQ.xyz\t\tVF01,5(VI02)\r\n\t\tMADDz.xyz\tVF02,VF19,VF02z\t\tNOP\r\n\t\tADDAi.xy\tACC,VF00,I\t\t\tNOP\r\n\t\tMADDAx.xy\tACC,VF17,VF04x\t\tNOP\r\n\t\tMADDAy.xy\tACC,VF18,VF04y\t\tNOP\r\n\t\t\r\nLoopRC:\tMADDz.xy\tVF05,VF19,VF04z\t\tDIV\t\t\tQ,VF00w,VF02z\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tITOF15.xyz\tVF04,VF03\t\t\tNOP\r\n\t\tSUBA.xy\t\tACC,VF00,VF02\t\tMOVE.z\t\tVF05,VF02\r\n\t\tMADDz.xy\tVF05,VF05,VF02z\t\tNOP\r\n\t\tMULAx.xyz\tACC,VF17,VF01x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF18,VF01y\t\tNOP\r\n\t\tMULq.w\t\tVF05,VF00,Q\t\t\tLQ.xyz\t\tVF03,3(VI02)\r\n\t\tMADDz.xyz\tVF02,VF19,VF01z\t\tLQ.xyz\t\tVF01,5(VI02)\r\n\t\tADDAi.xy\tACC,VF00,I\t\t\tNOP\r\n\t\tMADDAx.xy\tACC,VF17,VF04x\t\tIBNE\t\tVI02,VI05,LoopRC\r\n\t\tMADDAy.xy\tACC,VF18,VF04y\t\tSQ\t\t\tVF05,-3(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,ReflPostClip\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tClip\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.w\t\tVI01,-1(VI02)\r\n\t\t\r\n\t\t\r\n\t\t.endif\r\n\r\n\r\n\r\n\r\nReflPostClip:\r\n\r\n\t\t.if 1\r\n\t\t\r\n\t\t; fog version\r\n\r\n\t\t\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x45000FFF\r\n\t\tMULi.w\t\tVF25,VF00,I\t\t\tNOP\t\t\t\t\t\t\t\t; VF25w = 2^11 + 1 - 2^-12\r\n\t\tSUBw.w\t\tVF25,VF25,VF23w\t\tNOP\t\t\t\t\t\t\t\t; VF25w = 2^11 + 1-f0 - 2^-12\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI00,0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI10,0x4000\r\n\t\t\r\n\t\t\r\n\t\t.if 0\r\n\t\t; unoptimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\r\n\t\t\r\nLoopRPC:NOP\t\t\t\t\t\t\t\tLQ\t\t\tVF07,0(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULw.xyz\tVF08,VF07,VF07w\t\tNOP\t\t\t\t\t\t\t\t; homogeneous divide (str)/r\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tMTIR\t\tVI07,VF01w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF03\t\tDIV\t\t\tQ,VF23w,VF03w\r\n\t\tMADDw\t\tVF04,VF11,VF03w\t\tNOP\r\n\t\tMINI.w\t\tVF03,VF03,VF24\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF04xyz,VF04w\t\tNOP\r\n\t\tMULAw\t\tACC,VF00,VF25w\t\tNOP\r\n\t\tMADDq\t\tVF05,VF03,Q\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullRPC\r\n\t\tFTOI4.xyz\tVF06,VF05\t\t\tSQ.xyz\t\tVF08,0(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI11,VF05w\r\n\t\tNOP\t\t\t\t\t\t\t\tIOR\t\t\tVI11,VI11,VI07\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF06,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopRPC\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyzw\t\tVF06,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\nCullRPC:NOP\t\t\t\t\t\t\t\tMTIR\t\tVI11,VF05w\r\n\t\tNOP\t\t\t\t\t\t\t\tIOR\t\t\tVI11,VI11,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF06,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopRPC\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyzw\t\tVF06,-1(VI02)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n\t\t.else\r\n\t\t; optimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ\t\t\tVF04,-1(VI03)\r\n\t\tITOF4.xyz\tVF04,VF04\t\t\tLQ\t\t\tVF07,0(VI02)\r\n\t\tMADDAx\t\tACC,VF12,VF04x\t\tMTIR\t\tVI07,VF04w\r\n\t\tMADDAy\t\tACC,VF13,VF04y\t\tLQ\t\t\tVF06,0(VI03)\r\n\t\tMADDz\t\tVF04,VF14,VF04z\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tADDx\t\tVF07,VF07,VF00x\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tMULA\t\tACC,VF10,VF04\t\tDIV\t\t\tQ,VF23w,VF04w\r\n\t\tMADDw\t\tVF03,VF11,VF04w\t\tNOP\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tNOP\r\n\t\tMINI.w\t\tVF04,VF04,VF24\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tNOP\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tNOP\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tNOP\r\n\t\t\r\nLoopRPC:MULw.xyz\tVF08,VF07,VF07w\t\tMTIR\t\tVI06,VF01w\r\n\t\tADDx\t\tVF07,VF06,VF00x\t\tLQ\t\t\tVF06,0(VI03)\r\n\t\tMULAw\t\tACC,VF00,VF25w\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDq\t\tVF05,VF04,Q\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tADDx.xyz\tVF04,VF02,VF00x\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tMULA\t\tACC,VF10,VF02\t\tDIV\t\t\tQ,VF23w,VF02w\r\n\t\tMADDw\t\tVF03,VF11,VF02w\t\tSQ.xyz\t\tVF08,0(VI02)\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tIBNE\t\tVI01,VI00,CullRPC\r\n\t\tMINI.w\t\tVF04,VF02,VF24\t\tMTIR\t\tVI11,VF05w\r\n\t\tFTOI4.xyz\tVF05,VF05\t\t\tIOR\t\t\tVI11,VI11,VI07\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tMFIR.w\t\tVF05,VI11\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIADDIU\t\tVI07,VI06,0\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tIBNE\t\tVI02,VI05,LoopRPC\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tSQ.xyzw\t\tVF05,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\nCullRPC:FTOI4.xyz\tVF05,VF05\t\t\tIOR\t\t\tVI11,VI11,VI10\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tMFIR.w\t\tVF05,VI11\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIADDIU\t\tVI07,VI06,0\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tIBNE\t\tVI02,VI05,LoopRPC\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tSQ.xyzw\t\tVF05,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n\t\t\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t.else\r\n\t\t\r\n\t\t; original version\r\n\r\n\r\n\t\t.if 1\r\n\t\t; unoptimised\r\n\r\n\t\tFTOI15.w\tVF05,VF00\t\t\tNOP\t\t\t\t\t\t\t\t; set VF05w=0x8000 (for ADC bit)\r\n\r\nLoopRPC:NOP\t\t\t\t\t\t\t\tLQ\t\t\tVF07,0(VI02)\t\t; get tex coords\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,2(VI02)\t\t; get vertex coords\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULw.xyz\tVF08,VF07,VF07w\t\tNOP\t\t\t\t\t\t\t\t; homogeneous divide (str)/r\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tNOP\t\t\t\t\t\t\t\t; vertex coords to float\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\t\t\t\t\t\t\t\t; row 3 view transform\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tNOP\t\t\t\t\t\t\t\t; row 1 view transform\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tNOP\t\t\t\t\t\t\t\t; row 2 view transform\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF08,0(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\t\t; step dest ptr\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF03\t\tDIV\t\t\tQ,VF00w,VF03w\t\t; inv viewport scale\t; calc 1/w\r\n\t\tMADDw\t\tVF06,VF11,VF03w\t\tNOP\t\t\t\t\t\t\t\t; inv viewport offset\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF06xyz,VF06w\t\tNOP\t\t\t\t\t\t\t\t; generate outcodes\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULq.xyz\tVF05,VF03,Q\t\t\tNOP\t\t\t\t\t\t\t\t; homogeneous divide (xyz)/w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x03FFFF\t\t; test last 3 outcodes\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullRPC\t; cull if one was out\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopRPC\t; loop\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF05,-1(VI02)\t\t; store screen coords\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; prefetch next tag\r\n\r\nCullRPC:NOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopRPC\t; loop\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF05,-1(VI02)\t\t; store screen coords\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\n\t\t.else\r\n\t\t; optimised\r\n\t\t\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ.xyz\t\tVF01,2(VI02)\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tLQ.xyz\t\tVF01,5(VI02)\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tLQ\t\t\tVF07,0(VI02)\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tIADDIU\t\tVI01,VI00,0x4000\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tIADDIU\t\tVI01,VI01,0x4000\r\n\t\tMULw.xyz\tVF08,VF07,VF07w\t\tMFIR.w\t\tVF05,VI01\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tLQ\t\t\tVF07,3(VI02)\r\n\t\tMULA\t\tACC,VF10,VF03\t\tNOP\r\n\t\tMADDw\t\tVF06,VF11,VF03w\t\tDIV\t\t\tQ,VF00w,VF03w\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tNOP\r\n\t\t\r\nLoopRPC:MADDAy\t\tACC,VF13,VF02y\t\tMOVE.xyz\tVF04,VF03\r\n\t\tCLIPw.xyz\tVF06xyz,VF06w\t\tLQ.xyz\t\tVF01,8(VI02)\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tMULw.xyz\tVF08,VF07,VF07w\t\tSQ.xyz\t\tVF08,-3(VI02)\r\n\t\tMULq.xyz\tVF05,VF04,Q\t\t\tLQ\t\t\tVF07,3(VI02)\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tMULA\t\tACC,VF10,VF03\t\tIBNE\t\tVI01,VI00,CullRPC\r\n\t\tMADDw\t\tVF06,VF11,VF03w\t\tDIV\t\t\tQ,VF00w,VF03w\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tIBNE\t\tVI02,VI05,LoopRPC\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tSQ.xyz\t\tVF05,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\nCullRPC:ADDAx\t\tACC,VF15,VF00x\t\tIBNE\t\tVI02,VI05,LoopRPC\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tSQ\t\t\tVF05,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\n\t\t.endif\r\n\r\n\r\n\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; lighting (2 diffuse + ambient)\r\n\r\nLight1:\r\n\t\t.if 0\r\n\t\t; unoptimised version\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\t\r\nLoopL:\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,-3(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF08,-2(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF15.xyz\tVF02,VF01\t\t\tNOP\r\n\t\tITOF0.xyz\tVF08,VF08\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULAx.xyz\tACC,VF20,VF02x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF21,VF02y\t\tNOP\r\n\t\tMADDz.xyz\tVF03,VF22,VF02z\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMAXx.xyz\tVF04,VF03,VF00x\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx.xyz\tACC,VF23,VF00x\t\tNOP\r\n\t\tMADDAx.xyz\tACC,VF24,VF04x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF25,VF04y\t\tNOP\r\n\t\tMADDz.xyz\tVF05,VF26,VF04z\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMUL.xyz\t\tVF05,VF05,VF08\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t255\r\n\t\tMINIi.xyz\tVF06,VF05,I\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI0.xyz\tVF07,VF06\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopL\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF07,-2(VI02)\r\n\t\t\r\n\r\n\t\t.else\r\n\t\t; optimised version\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF02,-3(VI03)\r\n\t\tITOF15.xyz\tVF02,VF02\t\t\tLQ.xyz\t\tVF06,-2(VI03)\r\n\t\tMULAx.xyz\tACC,VF20,VF02x\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDAy.xyz\tACC,VF21,VF02y\t\tLQ.xyz\t\tVF01,-3(VI03)\r\n\t\tMADDz.xyz\tVF02,VF22,VF02z\t\tLQ.xyz\t\tVF05,-2(VI03)\r\n\t\tITOF0.xyz\tVF06,VF06\t\t\tNOP\r\n\t\tMAXx.xyz\tVF02,VF02,VF00x\t\tNOP\r\n\t\tADDAx.xyz\tACC,VF23,VF00x\t\tNOP\r\n\t\tITOF15.xyz\tVF01,VF01\t\t\tNOP\r\n\t\tMADDAx.xyz\tACC,VF24,VF02x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF25,VF02y\t\tNOP\r\n\t\tMADDz.xyz\tVF03,VF26,VF02z\t\tNOP\r\n\t\tMULAx.xyz\tACC,VF20,VF01x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF21,VF01y\t\tNOP\r\n\t\tMADDz.xyz\tVF02,VF22,VF01z\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMUL.xyz\t\tVF03,VF03,VF06\t\tLQ.xyz\t\tVF01,-3(VI03)\r\n\t\tITOF0.xyz\tVF06,VF05\t\t\tLQ.xyz\t\tVF05,-2(VI03)\r\n\t\tMAXx.xyz\tVF02,VF02,VF00x\t\tNOP\r\n\t\tADDAx.xyz\tACC,VF23,VF00x      LOI\t\t\t255\r\n\t\t\r\nLoopL:\tITOF15.xyz\tVF01,VF01\t\t\tNOP\r\n\t\tMINIi.xyz\tVF04,VF03,I\t\t\tNOP\r\n\t\tMADDAx.xyz\tACC,VF24,VF02x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF25,VF02y\t\tNOP\r\n\t\tMADDz.xyz\tVF03,VF26,VF02z\t\tNOP\r\n\t\tMULAx.xyz\tACC,VF20,VF01x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF21,VF01y\t\tNOP\r\n\t\tMADDz.xyz\tVF02,VF22,VF01z\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tFTOI0.xyz\tVF04,VF04\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tMUL.xyz\t\tVF03,VF03,VF06\t\tLQ.xyz\t\tVF01,-3(VI03)\r\n\t\tITOF0.xyz\tVF06,VF05\t\t\tLQ.xyz\t\tVF05,-2(VI03)\r\n\t\tMAXx.xyz\tVF02,VF02,VF00x\t\tIBNE\t\tVI02,VI05,LoopL\r\n\t\tADDAx.xyz\tACC,VF23,VF00x\t\tSQ.xyz\t\tVF04,-2(VI02)\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI11,VI00,0x3000\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI11,VI01,VI11\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI08,VI00,COLR+1\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI14,VI14,VI08\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI10,VI00,Label2\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI05,VI06\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tLabel0\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; applying material colour\r\n\r\nApplyColour:\r\n\r\n\t\t.if 0\r\n\t\t; unoptimised version\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\t\r\nLoopAC:\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,-2(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF0.xyz\tVF02,VF01\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMUL.xyz\t\tVF03,VF02,VF16\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t255\r\n\t\tMINIi.xyz\tVF04,VF03,I\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI0.xyz\tVF05,VF04\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopAC\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF05,-2(VI02)\r\n\t\t\r\n\t\t.else\r\n\t\t; optimised version\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,-2(VI03)\r\n\t\tITOF0.xyz\tVF02,VF01\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMUL.xyz\t\tVF03,VF02,VF16\t\tLQ.xyz\t\tVF01,-2(VI03)\r\n\t\tITOF0.xyz\tVF02,VF01\t\t\tLOI\t\t\t255\r\n\t\tMINIi.xyz\tVF04,VF03,I\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMUL.xyz\t\tVF03,VF02,VF16\t\tLQ.xyz\t\tVF01,-2(VI03)\r\n\t\tITOF0.xyz\tVF02,VF01\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tFTOI0.xyz\tVF05,VF04\t\t\tLQ.xyz\t\tVF01,-2(VI03)\r\n\t\t\r\nLoopAC:\tMINIi.xyz\tVF04,VF03,I\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMUL.xyz\t\tVF03,VF02,VF16\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tITOF0.xyz\tVF02,VF01\t\t\tLQ.xyz\t\tVF01,-2(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopAC\r\n\t\tFTOI0.xyz\tVF05,VF04\t\t\tSQ.xyz\t\tVF05,-2(VI02)\r\n\t\t\r\n\t\t.endif\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tJR\t\t\tVI01\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\t\t\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\n\t\t\r\nSingleSided:\r\n\r\n\t\t.if 0\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\tADDw.x\t\tVF08,VF00,VF00w\t\tNOP\r\n\t\tFTOI15.w\tVF08,VF00\t\t\tNOP\r\n\t\t\r\nLoop_SS:OPMULA.xyz\tACC,VF02,VF03\t\tNOP\r\n\t\tOPMSUB.xyz\tVF04,VF03,VF02\t\tNOP\r\n\t\tADDx\t\tVF02,VF03,VF00x\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF4.xyz\tVF03,VF01\t\t\tMTIR\t\tVI10,VF01w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMUL.xyz\t\tVF05,VF04,VF03\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAy.x\t\tACC,VF05,VF05y\t\tNOP\r\n\t\tMADDz.x\t\tVF00,VF08,VF05z\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tFMEQ\t\tVI10,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI10,VI00,Cull_SS\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,Loop_SS\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tJR\t\t\tVI01\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\t\t\r\nCull_SS:NOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,Loop_SS\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.w\t\tVF08,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tJR\t\t\tVI01\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\t\t\r\n\t\t.else\r\n\t\t\r\n\t\tADDw.x\t\tVF08,VF00,VF00w\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tFTOI15.w\tVF08,VF00\t\t\tLQ\t\t\tVF02,-1(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tITOF4.xyz\tVF02,VF02\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tITOF4\t\tVF03,VF01\t\t\tMTIR\t\tVI10,VF02w\r\n\t\t\r\nLoop_SS:FTOI4.w\t\tVF03,VF03\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMUL.xyz\t\tVF05,VF04,VF03\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tOPMULA.xyz\tACC,VF02,VF03\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tOPMSUB.xyz\tVF04,VF03,VF02\t\tFMEQ\t\tVI10,VI10\r\n\t\tADDx\t\tVF02,VF03,VF00x\t\tIBEQ\t\tVI10,VI00,Cull_SS\r\n\t\tITOF4\t\tVF03,VF01\t\t\tMTIR\t\tVI10,VF03w\r\n\t\tADDAy.x\t\tACC,VF05,VF05y\t\tIBNE\t\tVI02,VI05,Loop_SS\r\n\t\tMADDz.x\t\tVF00,VF08,VF05z\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tJR\t\t\tVI01\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\t\t\r\nCull_SS:ADDAy.x\t\tACC,VF05,VF05y\t\tIBNE\t\tVI02,VI05,Loop_SS\r\n\t\tMADDz.x\t\tVF00,VF08,VF05z\t\tSQ.w\t\tVF08,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tJR\t\t\tVI01\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; lines\r\n\r\nLine1:\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI03,VI00,Proj1+16\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; line culling\r\n\r\nCullLine:\r\n\r\n\t\t.if 0\r\n\t\t; unoptimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\t\t\t; source ptr = dest ptr\r\n\t\tFTOI15.w\tVF05,VF00\t\t\tNOP\t\t\t\t\t\t\t\t; set VF05w=0x8000 (for ADC bit)\r\n\r\nLoopKL:\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\t\t; step source ptr\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,-1(VI03)\t\t; get vertex coords\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tNOP\t\t\t\t\t\t\t\t; vertex coords to float\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\t\t\t\t\t\t\t\t; row 3 view transform\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tNOP\t\t\t\t\t\t\t\t; row 1 view transform\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tNOP\t\t\t\t\t\t\t\t; row 2 view transform\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF03\t\tDIV\t\t\tQ,VF00w,VF03w\t\t; inv viewport scale\t; calc 1/w\r\n\t\tMADDw\t\tVF06,VF11,VF03w\t\tNOP\t\t\t\t\t\t\t\t; inv viewport offset\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF06xyz,VF06w\t\tNOP\t\t\t\t\t\t\t\t; generate outcodes\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULq.xyz\tVF05,VF03,Q\t\t\tNOP\t\t\t\t\t\t\t\t; homogeneous divide\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\t\t; step dest ptr\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x000FFF\t\t; test last 3 outcodes\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullKL\t\t; cull if all out\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopKL\t; loop\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF05,-1(VI02)\t\t; store screen coords\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; prefetch next tag\r\n\r\nCullKL:\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopKL\t; loop\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF05,-1(VI02)\t\t; store screen coords\r\n\t\t\r\n\t\t.else\r\n\t\t; optimised\r\n\t\t\r\n\t\tFTOI15.w\tVF05,VF00\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDz\t\tVF04,VF14,VF02z\t\tNOP\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tMULA\t\tACC,VF10,VF04\t\tDIV\t\t\tQ,VF00w,VF04w\r\n\t\tMADDw\t\tVF06,VF11,VF04w\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tNOP\r\n\t\t\r\nLoopKL:\tCLIPw.xyz\tVF06xyz,VF06w\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMULq.xyz\tVF05,VF04,Q\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tMULA\t\tACC,VF10,VF03\t\tDIV\t\t\tQ,VF00w,VF03w\r\n\t\tMADDw\t\tVF06,VF11,VF03w\t\tFCAND\t\tVI01,0x000FFF\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tIBNE\t\tVI01,VI00,CullKL\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tMOVE.xyz\tVF04,VF03\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tIBNE\t\tVI02,VI05,LoopKL\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tSQ.xyz\t\tVF05,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; prefetch next tag\r\n\r\nCullKL:\tMADDAy\t\tACC,VF13,VF02y\t\tIBNE\t\tVI02,VI05,LoopKL\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tSQ\t\t\tVF05,-1(VI02)\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\nShadow:\r\n\t\t.if 0\r\n\t\t; unoptimised version\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0.5\r\n\t\tMULi.w\t\tVF04,VF00,I\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE.z\t\tVF04,VF00\r\n\t\tFTOI15.w\tVF01,VF00\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI09,VI00,0x1F\r\n\r\nLoopSH:\tNOP                             IADD\t\tVI03,VI03,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI08,VI07,VI09\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx.xy\tACC,VF27,VF00x\t\tNOP\r\n\t\tMADDx.x\t\tVF03,VF16,VF02x\t\tNOP\r\n\t\tMADDz.y\t\tVF03,VF16,VF02z\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDy.z\t\tVF04,VF27,VF02y\t\tNOP\r\n\t\tSUBw.xy\t\tVF04,VF03,VF04w\t\tNOP\r\n\t\tFTOI12.xy\tVF03,VF03\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF04xyz,VF04w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xy\t\tVF03,0(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tFCGET\t\tVI07\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI07\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullSH\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI07,VI08\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopSH\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tEndSH\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\nCullSH:\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopSH\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.w\t\tVF01,-1(VI02)\r\n\t\t\r\n\t\t.else\r\n\t\t; optimised version\r\n\t\t\r\n\t\tFTOI15.w\tVF01,VF00\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tADDAx.xy\tACC,VF27,VF00x\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDx.x\t\tVF03,VF16,VF02x\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tMADDz.y\t\tVF03,VF16,VF02z\t\tLOI\t\t\t0.5\r\n\t\tMULi.w\t\tVF04,VF00,I\t\t\tIADDIU\t\tVI09,VI00,0x1F\r\n\t\tADDy.z\t\tVF04,VF27,VF02y\t\tNOP\r\n\t\tSUBw.xy\t\tVF04,VF03,VF04w\t\tNOP\r\n\t\tFTOI12.xy\tVF03,VF03\t\t\tNOP\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF04xyz,VF04w       MOVE.z\t\tVF04,VF00\r\n\t\t\r\nLoopSH:\tADDAx.xy\tACC,VF27,VF00x\t\tSQ.xy\t\tVF03,0(VI02)\r\n\t\tMADDx.x\t\tVF03,VF16,VF02x\t\tIAND\t\tVI08,VI07,VI09\r\n\t\tMADDz.y\t\tVF03,VF16,VF02z\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tFCGET\t\tVI07\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,-1(VI03)\r\n\t\tADDy.z\t\tVF04,VF27,VF02y\t\tIAND\t\tVI01,VI01,VI07\r\n\t\tSUBw.xy\t\tVF04,VF03,VF04w\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tFTOI12.xy\tVF03,VF03\t\t\tIBEQ\t\tVI01,VI00,KeepSH\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tIAND\t\tVI01,VI07,VI08\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopSH\r\n\t\tCLIPw.xyz\tVF04xyz,VF04w\t\tSQ.w\t\tVF01,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tEndSH\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\nKeepSH:\tCLIPw.xyz\tVF00xyz,VF00w\t\tIBNE\t\tVI02,VI05,LoopSH\r\n\t\tCLIPw.xyz\tVF04xyz,VF04w\t\tNOP\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\nEndSH:\tNOP                             ISUBIU\t\tVI14,VI14,SHDW\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tPTex1\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\t\t\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\nReformatXforms:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,3(VI00)\r\n\t\tMULx.w\t\tVF02,VF00,VF01x\t\tXITOP\t\tVI06\r\n\t\tMULy.w\t\tVF03,VF00,VF01y\t\tIADDIU\t\tVI01,VI00,0\r\n\t\t\r\nLoopRT:\tMULz.w\t\tVF04,VF00,VF01z\t\tLQ.xyz\t\tVF01,7(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,4\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.w\t\tVF02,-4(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.w\t\tVF03,-3(VI01)\r\n\t\tMULx.w\t\tVF02,VF00,VF01x\t\tIBNE\t\tVI01,VI06,LoopRT\r\n\t\tMULy.w\t\tVF03,VF00,VF01y\t\tSQ.w\t\tVF04,-2(VI01)\r\n\t\t\r\n\t\tNOP[E]\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\n; vertex format\r\n; -------------\r\n; (s,t,1,?)\r\n; (w0,w1,w2,?)\r\n; (nx:to0, ny:to1, nz:to2, ?)\r\n; (r,g,b,a)\r\n; (x,y,z,adc)\r\n\r\n\r\n\r\nSkin1:\r\n\t\t;---------------------------------------------------------------\r\n\t\t; wireframe\r\n\t\t\r\n\t\t; 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 58 47\r\n\t\t; s  x  x  x  x  x  x  x  x  m  m  m  m  m  m  m  m\r\n\t\t;                   <-------------PRIM------------->\r\n\t\t;                         1  0  0  0  0  0  0  1  0\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,WIRE\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI14,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI01,VI00,SkipWireframe\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI14,VI14,WIRE\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.y\t\tVF01,-1(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tRINIT\t\tR,VF01y\r\n\t\tNOP\t\t\t\t\t\t\t\tRGET.y\t\tVF02,R\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF02y\r\n\t\tMULq.y\t\tVF03,VF01,Q\t\t\tWAITQ\r\n\t\tADDAx.y\t\tACC,VF01,VF00x\t\tLOI\t\t\t0.0078125\r\n\t\tMSUBAi.y\tACC,VF03,I\t\t\tLOI\t\t\t0.0625\r\n\t\tMSUBi.y\t\tVF04,VF03,I\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.y\t\tVF04,-1(VI02)\r\n\r\nSkipWireframe:\r\n\t\t;---------------------------------------------------------------\r\n\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI14,VI00,CullSkin\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,SHDW\r\n\t\t\r\n\t\t\r\n\t\t.if 0\r\n\t\t; unoptimised\r\n\r\nLoopS:\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF02,2(VI02)\t\t; get normal & offsets\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF03,1(VI02)\t\t; get weights\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI08,VF02x\t\t\t\t\t\t\t\t\t\t; offset of M0\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI09,VF02y\t\t\t\t\t\t\t\t\t\t; offset of M1\r\n\t\tITOF15.xyz\tVF02,VF02\t\t\tMTIR\t\tVI10,VF02z\t\t\t; normal to float\t\t\t; offset of M2\r\n\t\tITOF15.xyz\tVF03,VF03\t\t\tLQ\t\t\tVF05,0(VI08)\t\t; weights to float\t\t\t; get M0 row 0\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF06,1(VI08)\t\t\t\t\t\t\t\t\t; get M0 row 1\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF07,2(VI08)\t\t\t\t\t\t\t\t\t; get M0 row 2\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULAx.xyz\tACC,VF05,VF02x\t\tLQ\t\t\tVF08,0(VI09)\t\t; nx*(M0 row 0)\t\t\t\t; get M1 row 0\r\n\t\tMADDAy.xyz\tACC,VF06,VF02y\t\tLQ\t\t\tVF30,0(VI10)\t\t; ny*(M0 row 1)\t\t\t\t; get M2 row 0\r\n\t\tMADDz.xyz\tVF02,VF07,VF02z\t\tNOP\t\t\t\t\t\t\t\t; nz*(M0 row 2)\r\n\t\tMULAx\t\tACC,VF05,VF03x\t\tNOP\t\t\t\t\t\t\t\t; row 0 w0*M0\r\n\t\tMADDAy\t\tACC,VF08,VF03y\t\tNOP\t\t\t\t\t\t\t\t; add row 0 w1*M1\r\n\t\tMADDz\t\tVF05,VF30,VF03z\t\tNOP\t\t\t\t\t\t\t\t; add row 0 w2*M2\r\n\t\tMULAx.xyz\tACC,VF20,VF02x\t\tLQ\t\t\tVF08,1(VI09)\t\t; lighting dot prods x part\t; get M1 row 1\r\n\t\tMADDAy.xyz\tACC,VF21,VF02y\t\tLQ\t\t\tVF30,1(VI10)\t\t; lighting dot prods y part\t; get M2 row 1\r\n\t\tMADDz.xyz\tVF02,VF22,VF02z\t\tNOP\t\t\t\t\t\t\t\t; lighting dot prods z part\r\n\t\tMULAx\t\tACC,VF06,VF03x\t\tMR32.z\t\tVF31,VF05\t\t\t; row 1 w0*M0\r\n\t\tMADDAy\t\tACC,VF08,VF03y\t\tLQ.xyz\t\tVF01,4(VI02)\t\t; add row 1 w1*M1\t\t\t; get xyz\r\n\t\tMADDz\t\tVF06,VF30,VF03z\t\tLQ.xyz\t\tVF29,3(VI02)\t\t; add row 1 w2*M2\t\t\t; get rgb\r\n\t\tMAXx.xyz\tVF02,VF02,VF00x\t\tLQ\t\t\tVF08,2(VI09)\t\t; clamp dot prods at 0\t\t; get M1 row 2\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF30,2(VI10)\t\t\t\t\t\t\t\t\t; get M2 row 2\r\n\t\tNOP\t\t\t\t\t\t\t\tMR32.y\t\tVF31,VF31\r\n\t\tMULAx\t\tACC,VF07,VF03x\t\tMR32.z\t\tVF31,VF06\t\t\t; row 2 w0*M0\r\n\t\tMADDAy\t\tACC,VF08,VF03y\t\tNOP\t\t\t\t\t\t\t\t; add row 2 w1*M1\r\n\t\tMADDz\t\tVF07,VF30,VF03z\t\tNOP\t\t\t\t\t\t\t\t; add row 2 w2*M2\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tNOP\r\n\t\tITOF0.xyz\tVF29,VF29\t\t\tNOP\r\n\t\tADDAx.xyz\tACC,VF23,VF00x\t\tNOP\t\t\t\t\t\t\t\t; ambient colour\r\n\t\tMADDAx.xyz\tACC,VF24,VF02x\t\tMR32.xy\t\tVF31,VF31\t\t\t; add diffuse 0\r\n\t\tMADDAy.xyz\tACC,VF25,VF02y\t\tMR32.z\t\tVF31,VF07\t\t\t; add diffuse 1\r\n\t\tMADDz.xyz\tVF02,VF26,VF02z\t\tNOP\t\t\t\t\t\t\t\t; add diffuse 2\r\n\t\tMULAx.xyz\tACC,VF05,VF01x\t\tNOP\t\t\t\t\t\t\t\t; add x*(M row 0)\r\n\t\tMADDAy.xyz\tACC,VF06,VF01y\t\tNOP\t\t\t\t\t\t\t\t; add y*(M row 1)\r\n\t\tMADDAz.xyz\tACC,VF07,VF01z\t\tNOP\t\t\t\t\t\t\t\t; add z*(M row 2)\r\n\t\tMADDw.xyz\tVF01,VF31,VF00w\t\tNOP\t\t\t\t\t\t\t\t; M row 3\r\n\t\tADDAw.xyz\tACC,VF00,VF00w\t\tNOP\r\n\t\tMADD.xyz\tVF02,VF02,VF29\t\tNOP\r\n\t\tADDAx\t\tACC,VF19,VF00x\t\tNOP\t\t\t\t\t\t\t\t; row 3 view transform\r\n\t\tMADDAx\t\tACC,VF16,VF01x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF17,VF01y\t\tNOP\t\t\t\t\t\t\t\t; row 1 view transform\r\n\t\tMADDz\t\tVF01,VF18,VF01z\t\tLOI\t\t\t1.00003039837\t\t; row 2 view transform\r\n\t\tMINIi.xyz\tVF02,VF02,I\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF01w\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF02,3(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULq.xyz\tVF01,VF01,Q\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopS\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF01,-1(VI02)\r\n\t\t\r\n\t\t.else\r\n\t\t; optimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,2(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF03,1(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI08,VF01x\r\n\t\tITOF15.xyz\tVF02,VF01\t\t\tLQ\t\t\tVF05,0(VI08)\r\n\t\tITOF15.xyz\tVF03,VF03\t\t\tLQ\t\t\tVF06,1(VI08)\r\n\t\tMULAx.xyz\tACC,VF05,VF02x\t\tLQ\t\t\tVF07,2(VI08)\r\n\t\tMADDAy.xyz\tACC,VF06,VF02y\t\tMTIR\t\tVI09,VF01y\r\n\t\tMADDz.xyz\tVF02,VF07,VF02z\t\tLQ\t\t\tVF08,0(VI09)\r\n\t\tMULAx\t\tACC,VF05,VF03x\t\tMTIR\t\tVI10,VF01z\r\n\t\tMADDAy\t\tACC,VF08,VF03y\t\tLQ\t\t\tVF30,0(VI10)\r\n\t\tMADDz\t\tVF05,VF30,VF03z\t\tLQ\t\t\tVF08,1(VI09)\r\n\t\tMULAx.xyz\tACC,VF20,VF02x\t\tLQ\t\t\tVF30,1(VI10)\r\n\t\tMADDAy.xyz\tACC,VF21,VF02y\t\tNOP\r\n\t\tMADDz.xyz\tVF02,VF22,VF02z\t\tMR32.z\t\tVF31,VF05\r\n\t\tMULAx\t\tACC,VF06,VF03x\t\tLQ\t\t\tVF04,2(VI09)\r\n\t\tMADDAy\t\tACC,VF08,VF03y\t\tLQ\t\t\tVF29,2(VI10)\r\n\t\tMADDz\t\tVF06,VF30,VF03z\t\tLOI\t\t\t0x3F8000FF\t\t\t\t\t\t\t\t\t\t; I = 1+255/(2^23)\r\n\r\n\r\nLoopS:\tMAXx.xyz\tVF02,VF02,VF00x\t\tLQ.xyz\t\tVF01,4(VI02)\t\t; clamp dot prods at 0\t\t; get vertex\r\n\t\tMULAx\t\tACC,VF07,VF03x\t\tNOP\t\t\t\t\t\t\t\t;  row 2 M0*w0\r\n\t\tMADDAy\t\tACC,VF04,VF03y\t\tMR32.y\t\tVF31,VF31\t\t\t; +row 2 M1*w1\t\t\t\t; VF31 = (?,(M)30,?)\r\n\t\tMADDz\t\tVF07,VF29,VF03z\t\tMR32.z\t\tVF31,VF06\t\t\t; +row 2 M2*w2\t\t\t\t; VF31 = (?,(M)30,(M)31)\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tLQ.xyz\t\tVF29,3(VI02)\t\t; vertex to float\t\t\t; get rgb\r\n\t\tADDAx.xyz\tACC,VF23,VF00x\t\tNOP\t\t\t\t\t\t\t\t;  ambient\r\n\t\tMADDAx.xyz\tACC,VF24,VF02x\t\tNOP\t\t\t\t\t\t\t\t; +diffuse 0\r\n\t\tMADDAy.xyz\tACC,VF25,VF02y\t\tMR32.xy\t\tVF31,VF31\t\t\t; +diffuse 1\t\t\t\t; VF31 = ((M)30,(M)31,?)\r\n\t\tMADDz.xyz\tVF04,VF26,VF02z\t\tNOP\t\t\t\t\t\t\t\t; +diffuse 2\r\n\t\tITOF0.xyz\tVF29,VF29\t\t\tMR32.z\t\tVF31,VF07\t\t\t; rgb to float\t\t\t\t; VF31 = M row 3\r\n\t\tMULAx.xyz\tACC,VF05,VF01x\t\tLQ.xyz\t\tVF02,7(VI02)\t\t;  x * (M row 0)\t\t\t; get normal and offsets\r\n\t\tMADDAy.xyz\tACC,VF06,VF01y\t\tLQ.xyz\t\tVF03,6(VI02)\t\t; +y * (M row 1)\t\t\t; get weights\r\n\t\tMADDAz.xyz\tACC,VF07,VF01z\t\tNOP\t\t\t\t\t\t\t\t; +z * (M row 2)\r\n\t\tMADDw.xyz\tVF01,VF31,VF00w\t\tNOP\t\t\t\t\t\t\t\t; +1 * (M row 3)\r\n\t\tADDAw.xyz\tACC,VF00,VF00w\t\tMTIR\t\tVI08,VF02x\t\t\t;  (1,1,1)\t\t\t\t\t; offset of M0\r\n\t\tMADD.xyz\tVF04,VF04,VF29\t\tLQ\t\t\tVF05,0(VI08)\t\t; +illum * rgb\t\t\t\t; get M0 row 0\r\n\t\tADDAx\t\tACC,VF19,VF00x\t\tLQ\t\t\tVF06,1(VI08)\t\t; row 3 view transform\t\t; get M0 row 1\r\n\t\tMADDAx\t\tACC,VF16,VF01x\t\tMTIR\t\tVI09,VF02y\t\t\t; row 0 view transform\t\t; offset of M1\r\n\t\tITOF15.xyz\tVF02,VF02\t\t\tMTIR\t\tVI10,VF02z\t\t\t; normal to float\t\t\t; offset of M2\r\n\t\tMADDAy\t\tACC,VF17,VF01y\t\tLQ\t\t\tVF07,2(VI08)\t\t; row 1 view transform\t\t; get M0 row 2\r\n\t\tMADDz\t\tVF01,VF18,VF01z\t\tLQ\t\t\tVF08,0(VI09)\t\t; row 2 view transform\t\t; get M1 row 0\r\n\t\tMINIi.xyz\tVF04,VF04,I\t\t\tNOP\t\t\t\t\t\t\t\t; clamp rgb at 255\r\n\t\tITOF15.xyz\tVF03,VF03\t\t\tNOP\t\t\t\t\t\t\t\t; weights to float\r\n\t\tMULAx.xyz\tACC,VF05,VF02x\t\tLQ\t\t\tVF30,0(VI10)\t\t;  nx * (M0 row 0)\t\t\t; get M2 row 0\r\n\t\tMADDAy.xyz\tACC,VF06,VF02y\t\tDIV\t\t\tQ,VF00w,VF01w\t\t; +ny * (M0 row 1)\t\t\t; calc 1/w\r\n\t\tMADDz.xyz\tVF02,VF07,VF02z\t\tSQ.xyz\t\tVF04,3(VI02)\t\t; +nz * (M0 row 2)\t\t\t; store colour\r\n\t\tMULAx\t\tACC,VF05,VF03x\t\tNOP\t\t\t\t\t\t\t\t;  row 0 M0*w0\r\n\t\tMADDAy\t\tACC,VF08,VF03y\t\tLQ\t\t\tVF08,1(VI09)\t\t; +row 0 M1*w1\t\t\t\t; get M1 row 1\r\n\t\tMADDz\t\tVF05,VF30,VF03z\t\tLQ\t\t\tVF30,1(VI10)\t\t; +row 0 M2*w2\t\t\t\t; get M2 row 1\r\n\t\tMULAx.xyz\tACC,VF20,VF02x\t\tNOP\t\t\t\t\t\t\t\t; lighting dot prods x part\r\n\t\tMADDAy.xyz\tACC,VF21,VF02y\t\tIADD\t\tVI02,VI02,VI04\t\t; lighting dot prods y part\t; step pointer\r\n\t\tMULq.xyz\tVF01,VF01,Q\t\t\tLQ\t\t\tVF04,2(VI09)\t\t; homogeneous div (xyz)/w\t; get M1 row 2\r\n\t\tMADDz.xyz\tVF02,VF22,VF02z\t\tLQ\t\t\tVF29,2(VI10)\t\t; lighting dot prods z part\t; get M2 row 2\r\n\t\tMULAx\t\tACC,VF06,VF03x\t\tMR32.z\t\tVF31,VF05\t\t\t;  row 1 M0*w0\t\t\t\t; VF31 = (?,?,(M)30)\r\n\t\tMADDAy\t\tACC,VF08,VF03y\t\tIBNE\t\tVI02,VI05,LoopS\t\t; +row 1 M1*w1\t\t\t\t; loop\r\n\t\tMADDz\t\tVF06,VF30,VF03z\t\tSQ.xyz\t\tVF01,-1(VI02)\t\t; +row 1 M2*w2\t\t\t\t; store screen coords\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\t\t\r\n\t\t\r\n\t\t\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\nCullSkin:\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t\t\t\t\t\t; need this cycle here\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI14,VI01,ShadowSkin\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; new version\r\n\t\t\r\n\t\t.if 0\r\n\t\t; unoptimised\r\n\t\t\r\n\t\tFTOI15.w\tVF03,VF00\t\t\tNOP\r\n\t\t\r\n\t\t\r\nLoopKS:\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF02,2(VI02)\t\t; get normal & offsets\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF03,1(VI02)\t\t; get weights\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI08,VF02x\t\t\t\t\t\t\t\t\t\t; offset of M0\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI09,VF02y\t\t\t\t\t\t\t\t\t\t; offset of M1\r\n\t\tITOF15.xyz\tVF02,VF02\t\t\tMTIR\t\tVI10,VF02z\t\t\t; normal to float\t\t\t; offset of M2\r\n\t\tITOF15.xyz\tVF03,VF03\t\t\tLQ\t\t\tVF05,0(VI08)\t\t; weights to float\t\t\t; get M0 row 0\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF06,1(VI08)\t\t\t\t\t\t\t\t\t; get M0 row 1\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF07,2(VI08)\t\t\t\t\t\t\t\t\t; get M0 row 2\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULAx.xyz\tACC,VF05,VF02x\t\tLQ\t\t\tVF08,0(VI09)\t\t; nx*(M0 row 0)\t\t\t\t; get M1 row 0\r\n\t\tMADDAy.xyz\tACC,VF06,VF02y\t\tLQ\t\t\tVF30,0(VI10)\t\t; ny*(M0 row 1)\t\t\t\t; get M2 row 0\r\n\t\tMADDz.xyz\tVF02,VF07,VF02z\t\tNOP\t\t\t\t\t\t\t\t; nz*(M0 row 2)\r\n\t\tMULAx\t\tACC,VF05,VF03x\t\tNOP\t\t\t\t\t\t\t\t; row 0 w0*M0\r\n\t\tMADDAy\t\tACC,VF08,VF03y\t\tNOP\t\t\t\t\t\t\t\t; add row 0 w1*M1\r\n\t\tMADDz\t\tVF05,VF30,VF03z\t\tNOP\t\t\t\t\t\t\t\t; add row 0 w2*M2\r\n\t\tMULAx.xyz\tACC,VF20,VF02x\t\tLQ\t\t\tVF08,1(VI09)\t\t; lighting dot prods x part\t; get M1 row 1\r\n\t\tMADDAy.xyz\tACC,VF21,VF02y\t\tLQ\t\t\tVF30,1(VI10)\t\t; lighting dot prods y part\t; get M2 row 1\r\n\t\tMADDz.xyz\tVF02,VF22,VF02z\t\tNOP\t\t\t\t\t\t\t\t; lighting dot prods z part\r\n\t\tMULAx\t\tACC,VF06,VF03x\t\tMR32.z\t\tVF31,VF05\t\t\t; row 1 w0*M0\r\n\t\tMADDAy\t\tACC,VF08,VF03y\t\tLQ.xyz\t\tVF01,4(VI02)\t\t\t\t\t\t\t\t\t; add row 1 w1*M1\r\n\t\tMADDz\t\tVF06,VF30,VF03z\t\tLQ.xyz\t\tVF29,3(VI02)\t\t\t\t\t\t\t\t\t; add row 1 w2*M2\r\n\t\tMAXx.xyz\tVF02,VF02,VF00x\t\tLQ\t\t\tVF08,2(VI09)\t\t; clamp dot prods at 0\t\t; get M1 row 2\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF30,2(VI10)\t\t\t\t\t\t\t\t\t; get M2 row 2\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULAx\t\tACC,VF07,VF03x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF08,VF03y\t\tMR32.y\t\tVF31,VF31\r\n\t\tMADDz\t\tVF07,VF30,VF03z\t\tMR32.z\t\tVF31,VF06\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tNOP\r\n\t\tITOF0.xyz\tVF29,VF29\t\t\tNOP\r\n\t\tADDAx.xyz\tACC,VF23,VF00x\t\tNOP\t\t\t\t\t\t\t\t; ambient colour\r\n\t\tMADDAx.xyz\tACC,VF24,VF02x\t\tMR32.xy\t\tVF31,VF31\t\t\t; add diffuse 0\r\n\t\tMADDAy.xyz\tACC,VF25,VF02y\t\tMR32.z\t\tVF31,VF07\t\t\t; add diffuse 1\r\n\t\tMADDz.xyz\tVF02,VF26,VF02z\t\tNOP\t\t\t\t\t\t\t\t; add diffuse 2\r\n\t\tMULAx.xyz\tACC,VF05,VF01x\t\tNOP\t\t\t\t\t\t\t\t; add x*(M row 0)\r\n\t\tMADDAy.xyz\tACC,VF06,VF01y\t\tNOP\t\t\t\t\t\t\t\t; add y*(M row 1)\r\n\t\tMADDAz.xyz\tACC,VF07,VF01z\t\tNOP\t\t\t\t\t\t\t\t; add z*(M row 2)\r\n\t\tMADDw.xyz\tVF01,VF31,VF00w\t\tNOP\t\t\t\t\t\t\t\t; M row 3\r\n\t\tADDAw.xyz\tACC,VF00,VF00w\t\tNOP\r\n\t\tMADD.xyz\tVF02,VF02,VF29\t\tNOP\r\n\t\tADDAx\t\tACC,VF19,VF00x\t\tNOP\t\t\t\t\t\t\t\t; row 3 view transform\r\n\t\tMADDAx\t\tACC,VF16,VF01x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF17,VF01y\t\tNOP\t\t\t\t\t\t\t\t; row 1 view transform\r\n\t\tMADDz\t\tVF01,VF18,VF01z\t\tLOI\t\t\t1.00003039837\t\t; row 2 view transform\r\n\t\tMINIi.xyz\tVF02,VF02,I\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF01\t\tDIV\t\t\tQ,VF00w,VF01w\r\n\t\tMADDw\t\tVF05,VF11,VF01w\t\tSQ.xyz\t\tVF02,3(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF05xyz,VF05w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULq.xyz\tVF03,VF01,Q\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullKS\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopKS\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF03,-1(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\nCullKS:\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopKS\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF03,-1(VI02)\r\n\t\t\r\n\t\t.else\r\n\t\t; optimised\r\n\r\n\t\tFTOI15.w\tVF04,VF00\t\t\tLQ.xyz\t\tVF01,2(VI02)\t\t; set ADC bit\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF03,1(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI08,VF01x\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF05,0(VI08)\r\n\t\tITOF15.xyz\tVF02,VF01\t\t\tLQ\t\t\tVF06,1(VI08)\r\n\t\tITOF15.xyz\tVF03,VF03\t\t\tLQ\t\t\tVF07,2(VI08)\r\n\t\tMULAx.xyz\tACC,VF05,VF02x\t\tMTIR\t\tVI09,VF01y\r\n\t\tMADDAy.xyz\tACC,VF06,VF02y\t\tMTIR\t\tVI10,VF01z\r\n\t\tMADDz.xyz\tVF02,VF07,VF02z\t\tLQ\t\t\tVF08,0(VI09)\r\n\t\tMULAx\t\tACC,VF05,VF03x\t\tLQ\t\t\tVF30,0(VI10)\r\n\t\tMADDAy\t\tACC,VF08,VF03y\t\tNOP\r\n\t\tMADDz\t\tVF05,VF30,VF03z\t\tLQ\t\t\tVF31,1(VI09)\r\n\t\tMULAx.xyz\tACC,VF20,VF02x\t\tLQ\t\t\tVF29,1(VI10)\r\n\t\tMADDAy.xyz\tACC,VF21,VF02y\t\tLOI\t\t\t0x3F8000FF\t\t\t\t\t\t\t\t\t\t; I = 1+255/(2^23)\r\n\t\tMADDz.xyz\tVF02,VF22,VF02z\t\tLQ\t\t\tVF08,2(VI09)\r\n\t\tMULAx\t\tACC,VF06,VF03x\t\tLQ\t\t\tVF30,2(VI10)\r\n\t\t\r\n\t\t\r\nLoopKS:\tMADDAy\t\tACC,VF31,VF03y\t\tMR32.z\t\tVF31,VF05\t\t\t; +row 1 M1*w1\t\t\t\t; VF31 = (?,?,(M)30)\r\n\t\tMADDz\t\tVF06,VF29,VF03z\t\tNOP\t\t\t\t\t\t\t\t; +row 1 M2*w2\r\n\t\tMAXx.xyz\tVF02,VF02,VF00x\t\tLQ.xyz\t\tVF01,4(VI02)\t\t; clamp dot prods at 0\t\t; get vertex\r\n\t\tMULAx\t\tACC,VF07,VF03x\t\tLQ.xyz\t\tVF29,3(VI02)\t\t;  row 2 M0*w0\t\t\t\t; get rgb\r\n\t\tMADDAy\t\tACC,VF08,VF03y\t\tMR32.y\t\tVF31,VF31\t\t\t; +row 2 M1*w1\t\t\t\t; VF31 = (?,(M)30,?)\r\n\t\tMADDz\t\tVF07,VF30,VF03z\t\tMR32.z\t\tVF31,VF06\t\t\t; +row 2 M2*w2\t\t\t\t; VF31 = (?,(M)30,(M)31)\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tNOP\t\t\t\t\t\t\t\t; vertex to float\r\n\t\tITOF0.xyz\tVF29,VF29\t\t\tNOP\t\t\t\t\t\t\t\t; rgb to float\r\n\t\tADDAx.xyz\tACC,VF23,VF00x\t\tNOP\t\t\t\t\t\t\t\t; ambient\r\n\t\tMADDAx.xyz\tACC,VF24,VF02x\t\tMR32.xy\t\tVF31,VF31\t\t\t; +diffuse 0\t\t\t\t; VF31 = ((M)30,(M)31,?)\r\n\t\tMADDAy.xyz\tACC,VF25,VF02y\t\tMR32.z\t\tVF31,VF07\t\t\t; +diffuse 1\t\t\t\t; VF31 = M row 3\r\n\t\tMADDz.xyz\tVF04,VF26,VF02z\t\tNOP\t\t\t\t\t\t\t\t; +diffuse 2\r\n\t\tMULAx.xyz\tACC,VF05,VF01x\t\tLQ.xyz\t\tVF02,7(VI02)\t\t;  x * (M row 0)\t\t\t; get normal and offsets\r\n\t\tMADDAy.xyz\tACC,VF06,VF01y\t\tNOP\t\t\t\t\t\t\t\t; +y * (M row 1)\r\n\t\tMADDAz.xyz\tACC,VF07,VF01z\t\tNOP\t\t\t\t\t\t\t\t; +z * (M row 2)\r\n\t\tMADDw.xyz\tVF01,VF31,VF00w\t\tLQ.xyz\t\tVF03,6(VI02)\t\t; +1 * (M row 3)\t\t\t; get weights\r\n\t\tADDAw.xyz\tACC,VF00,VF00w\t\tNOP\t\t\t\t\t\t\t\t;  (1,1,1)\r\n\t\tMADD.xyz\tVF04,VF04,VF29\t\tMTIR\t\tVI08,VF02x\t\t\t; +illum * rgb\t\t\t\t; offset of M0\r\n\t\tADDAx\t\tACC,VF19,VF00x\t\tLQ\t\t\tVF05,0(VI08)\t\t; row 3 view transform\t\t; get M0 row 0\r\n\t\tMADDAx\t\tACC,VF16,VF01x\t\tLQ\t\t\tVF06,1(VI08)\t\t; row 0 view transform\t\t; get M0 row 1\r\n\t\tMADDAy\t\tACC,VF17,VF01y\t\tMTIR\t\tVI09,VF02y\t\t\t; row 1 view transform\t\t; offset of M1\r\n\t\tMADDz\t\tVF01,VF18,VF01z\t\tMTIR\t\tVI10,VF02z\t\t\t; row 2 view transform\t\t; offset of M2\r\n\t\tMINIi.xyz\tVF04,VF04,I\t\t\tLQ\t\t\tVF07,2(VI08)\t\t; clamp rgb at 255\t\t\t; get M0 row 2\r\n\t\tITOF15.xyz\tVF02,VF02\t\t\tLQ\t\t\tVF08,0(VI09)\t\t; normal to float\t\t\t; get M1 row 0\r\n\t\tITOF15.xyz\tVF03,VF03\t\t\tNOP\t\t\t\t\t\t\t\t; weights to float\r\n\t\tMULA\t\tACC,VF10,VF01\t\tDIV\t\t\tQ,VF00w,VF01w\t\t; inverse viewport scale\t; calc 1/w\r\n\t\tMADDw\t\tVF31,VF11,VF01w\t\tSQ.xyz\t\tVF04,3(VI02)\t\t; inverse viewport offset\t; store colour\r\n\t\tMULAx.xyz\tACC,VF05,VF02x\t\tLQ\t\t\tVF30,0(VI10)\t\t;  nx * (M0 row 0)\t\t\t; get M2 row 0\r\n\t\tMADDAy.xyz\tACC,VF06,VF02y\t\tNOP\t\t\t\t\t\t\t\t; +ny * (M0 row 1)\r\n\t\tMADDz.xyz\tVF02,VF07,VF02z\t\tNOP\t\t\t\t\t\t\t\t; +nz * (M0 row 2)\r\n\t\tCLIPw.xyz\tVF31xyz,VF31w\t\tLQ\t\t\tVF31,1(VI09)\t\t; generate clip codes\t\t; get M1 row 1\r\n\t\tMULAx\t\tACC,VF05,VF03x\t\tLQ\t\t\tVF29,1(VI10)\t\t;  row 0 M0*w0\t\t\t\t; get M2 row 1\r\n\t\tMADDAy\t\tACC,VF08,VF03y\t\tIADD\t\tVI02,VI02,VI04\t\t; +row 0 M1*w1\t\t\t\t; step pointer\r\n\t\tMADDz\t\tVF05,VF30,VF03z\t\tLQ\t\t\tVF08,2(VI09)\t\t; +row 0 M2*w2\t\t\t\t; get M1 row 2\r\n\t\tMULq.xyz\tVF04,VF01,Q\t\t\tFCAND\t\tVI01,0x03FFFF\t\t; homogeneous div (xyz)/w\t; last 3 clip codes\r\n\t\tMULAx.xyz\tACC,VF20,VF02x\t\tIBNE\t\tVI01,VI00,CullKS\t; lighting dot prods x part\t; cull if any non-zero\r\n\t\tMADDAy.xyz\tACC,VF21,VF02y\t\tLQ\t\t\tVF30,2(VI10)\t\t; lighting dot prods y part\t; get M2 row 2\r\n\t\tMADDz.xyz\tVF02,VF22,VF02z\t\tIBNE\t\tVI02,VI05,LoopKS\t; lighting dot prods z part\t; loop\r\n\t\tMULAx\t\tACC,VF06,VF03x\t\tSQ.xyz\t\tVF04,-1(VI02)\t\t;  row 1 M0*w0\t\t\t\t; store screen coords\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\nCullKS:\tMADDz.xyz\tVF02,VF22,VF02z\t\tIBNE\t\tVI02,VI05,LoopKS\t; lighting dot prods z part ; loop\r\n\t\tMULAx\t\tACC,VF06,VF03x\t\tSQ\t\t\tVF04,-1(VI02)       ;  row 1 M0*w0\t\t\t\t; store screen coords\r\n\t\t\r\n\t\t.endif\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; shadow version\r\n\r\nShadowSkin:\r\n\r\n\t\t.if 0\r\n\t\t; unoptimised\r\n\t\t\r\nLoopSS:\r\n\t\tNOP\t\t\t\t\t\t\t\tILW.x\t\tVI08,2(VI02)\t\t; get primary transform offset\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,4(VI02)\t\t; get vertex coords\r\n\t\tITOF4.xyz\tVF01,VF01\t\t\tNOP\t\t\t\t\t\t\t\t; vertex coords to float\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF04,0(VI08)\t\t; get M0 row 0\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF05,1(VI08)        ; get M0 row 1\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF06,2(VI08)\t\t; get M0 row 2\r\n\t\tADDAw.x\t\tACC,VF00,VF04w\t\tNOP\t\t\t\t\t\t\t\t; ACCx = (M0)30\r\n\t\tADDAw.y\t\tACC,VF00,VF05w\t\tNOP\t\t\t\t\t\t\t\t; ACCy = (M0)31\r\n\t\tADDAw.z\t\tACC,VF00,VF06w\t\tNOP\t\t\t\t\t\t\t\t; ACCz = (M0)32\r\n\t\tMADDAx.xyz\tACC,VF04,VF01x\t\tNOP\t\t\t\t\t\t\t\t; +x * M0 row 0\r\n\t\tMADDAy.xyz\tACC,VF05,VF01y\t\tNOP\t\t\t\t\t\t\t\t; +y * M0 row 1\r\n\t\tMADDz.xyz\tVF01,VF06,VF01z\t\tNOP\t\t\t\t\t\t\t\t; +z * M0 row 2\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\t\t; step pointer\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\t\t\t\t\t\t\t\t; row 3 view transform\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tNOP\t\t\t\t\t\t\t\t; row 1 view transform\r\n\t\tMADDz\t\tVF01,VF14,VF01z\t\tNOP\t\t\t\t\t\t\t\t; row 2 view transform\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF01w\t\t; calc 1/w\r\n\t\tMULq.xyz\tVF01,VF01,Q\t\t\tWAITQ\t\t\t\t\t\t\t; homogeneous div (xyz)/w\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopSS\t; loop\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF01,-1(VI02)\t\t; store screen coords\r\n\t\t\r\n\t\t.else\r\n\t\t; optimised\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tILW.x\t\tVI08,2(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,4(VI02)\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tLQ\t\t\tVF08,3(VI08)\r\n\t\tADDAx.xyz\tACC,VF08,VF00\t\tLQ\t\t\tVF05,0(VI08)\r\n\t\tMADDAx.xyz\tACC,VF05,VF02x\t\tLQ\t\t\tVF06,1(VI08)\r\n\t\tMADDAy.xyz\tACC,VF06,VF02y\t\tLQ\t\t\tVF07,2(VI08)\r\n\t\tMADDz.xyz\tVF02,VF07,VF02z\t\tILW.x\t\tVI08,7(VI02)\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ\t\t\tVF01,9(VI02)\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tLQ\t\t\tVF05,0(VI08)\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tLQ\t\t\tVF06,1(VI08)\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tLQ\t\t\tVF07,2(VI08)\r\n\t\t\r\nLoopSS:\tITOF4.xyz\tVF02,VF01\t\t\tILW.x\t\tVI08,12(VI02)\r\n\t\tADDAw.x\t\tACC,VF00,VF05w\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tADDAw.y\t\tACC,VF00,VF06w\t\tDIV\t\t\tQ,VF00w,VF03w\r\n\t\tADDAw.z\t\tACC,VF00,VF07w\t\tNOP\r\n\t\tMADDAx.xyz\tACC,VF05,VF02x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF06,VF02y\t\tLQ\t\t\tVF01,9(VI02)\r\n\t\tMADDz.xyz\tVF02,VF07,VF02z\t\tLQ\t\t\tVF05,0(VI08)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMULq.xyz\tVF04,VF03,Q\t\t\tLQ\t\t\tVF06,1(VI08)\r\n\t\tMADDAx\t\tACC,VF12,VF02x\t\tLQ\t\t\tVF07,2(VI08)\r\n\t\tMADDAy\t\tACC,VF13,VF02y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF14,VF02z\t\tIBNE\t\tVI02,VI05,LoopSS\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF04,-1(VI02)\r\n\t\t\r\n\t\t.endif\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\n\r\n\t\t; context data:\r\n\t\t\r\n\t\t; VF14 = shadow vec (magnitude defines length of shadow polys), in body coords\r\n\t\t; VF15 = tweak vec (small, parallel to shadow vec), in body coords\r\n\t\t; VF16-19 = body to frustum transform\r\n\r\n\r\n\t\t\r\n\t\t;      3-----0-----5\r\n\t\t;\t\t\\   / \\   /\r\n\t\t;        \\ /   \\ /\r\n\t\t;         1-----2\r\n\t\t;          \\   /\r\n\t\t;\t\t\t\\ /\r\n\t\t;            4\r\n\r\n\r\nShadowVolumeSkin:\r\n\r\n\t\t; set up VF07 = VF14x*VF16 + VF14y*VF17 + VF14z*VF18 + VF19\r\n\t\tMULAx\t\tACC,VF16,VF14x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF17,VF14y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF18,VF14z\t\tNOP\r\n\t\tMADDw\t\tVF07,VF19,VF00w\t\tNOP\r\n\t\t\r\n\t\t; set up VF08 = VF15x*VF16 + VF15y*VF17 + VF15z*VF18 + VF19\r\n\t\tMULAx\t\tACC,VF16,VF15x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF17,VF15y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF18,VF15z\t\tNOP\r\n\t\tMADDw\t\tVF08,VF19,VF00w\t\tIADDIU\t\tVI09,VI00,0x10\t\t; mask for Sw FMAC flag\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI08, VI00, 0\r\n\r\nLoopSVS:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF20,1(VI02)\t\t; | Load vector 0\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF21,2(VI02)        ; | Load vector 1 \r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF22,3(VI02)        ; | Load vector 2 \r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF23,4(VI02)        ; | Load vector 3 \r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF24,5(VI02)        ; | Load vector 4 \r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF20w\t\t\t; | Load up matrix 0 index\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF04,3(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,0(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF02,1(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF03,2(VI01)\r\n\r\n\t\t; v0\r\n\t\tADDAx.xyz\tACC,VF04,VF00x\t\tMTIR\t\tVI01,VF21w          ; | Load up matrix 1 index \r\n\t\tMADDAx.xyz\tACC,VF01,VF20x\t\tLQ\t\t\tVF04,3(VI01)\r\n\t\tMADDAy.xyz\tACC,VF02,VF20y\t\tLQ\t\t\tVF01,0(VI01)\r\n\t\tMADDz.xyz\tVF20,VF03,VF20z\t\tLQ\t\t\tVF02,1(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF03,2(VI01)\r\n\r\n\t\t; v1\r\n\t\tADDAx.xyz\tACC,VF04,VF00x\t\tMTIR\t\tVI01,VF22w          ; | Load up matrix 2 index \r\n\t\tMADDAx.xyz\tACC,VF01,VF21x\t\tLQ\t\t\tVF04,3(VI01)\r\n\t\tMADDAy.xyz\tACC,VF02,VF21y\t\tLQ\t\t\tVF01,0(VI01)\r\n\t\tMADDz.xyz\tVF21,VF03,VF21z\t\tLQ\t\t\tVF02,1(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF03,2(VI01)\r\n\r\n\t\t; v2\r\n\t\tADDAx.xyz\tACC,VF04,VF00x\t\tMTIR\t\tVI01,VF23w          ; | Load up matrix 3 index \r\n\t\tMADDAx.xyz\tACC,VF01,VF22x\t\tLQ\t\t\tVF04,3(VI01)\r\n\t\tMADDAy.xyz\tACC,VF02,VF22y\t\tLQ\t\t\tVF01,0(VI01)\r\n\t\tMADDz.xyz\tVF22,VF03,VF22z\t\tLQ\t\t\tVF02,1(VI01)\r\n\t\tSUB.xyz\t\tVF26,VF21,VF20      LQ\t\t\tVF03,2(VI01)\r\n\r\n\t\t; v3\r\n\t\tADDAx.xyz\tACC,VF04,VF00x\t\tLQ\t\t\tVF25,6(VI02)        ; | Load vector 5\r\n\t\tMADDAx.xyz\tACC,VF01,VF23x\t\tMTIR\t\tVI01,VF24w          ; | Load up matrix 4 index \r\n\t\tSUB.xyz\t\tVF27,VF22,VF20\t\tLQ\t\t\tVF04,3(VI01)\r\n\t\tMADDAy.xyz\tACC,VF02,VF23y\t\tLQ\t\t\tVF01,0(VI01)\r\n\t\tMADDz.xyz\tVF23,VF03,VF23z\t\tLQ\t\t\tVF02,1(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF03,2(VI01)\r\n\r\n\t\t; v4\r\n\t\tOPMULA.xyz\tACC,VF26,VF27\t\tNOP\r\n\t\tOPMSUB.xyz\tVF05,VF27,VF26\t\tNOP\r\n\t\tADDAx.xyz\tACC,VF04,VF00x\t\tMTIR\t\tVI01,VF25w          ; | Load up matrix 5 index \r\n\t\tMADDAx.xyz\tACC,VF01,VF24x\t\tLQ\t\t\tVF04,3(VI01)\r\n\t\tMADDAy.xyz\tACC,VF02,VF24y\t\tLQ\t\t\tVF01,0(VI01)\r\n\t\tMUL.xyz\t\tVF05,VF05,VF15\t\tLQ\t\t\tVF02,1(VI01)\r\n\t\tMADDz.xyz\tVF24,VF03,VF24z\t\tLQ\t\t\tVF03,2(VI01)\r\n\t\t\r\n\t\t; v5\r\n\t\tADDAx.xyz\tACC,VF04,VF00x\t\tNOP\r\n\t\tMADDAx.xyz\tACC,VF01,VF25x\t\tNOP\r\n\t\tADDy.x\t\tVF05,VF05,VF05y\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF02,VF25y\t\tNOP\r\n\t\tMADDz.xyz\tVF25,VF03,VF25z\t\tNOP\r\n\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t   \r\n\t\tSUB.xyz\t\tVF02,VF21,VF23\t\tNOP\r\n\t\tADDz.x\t\tVF00,VF05,VF05z\t\tNOP\r\n\t\tSUB.xyz\t\tVF06,VF22,VF24\t\tNOP\r\n\t\tSUB.xyz\t\tVF05,VF21,VF24\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF02,VF26\t\tILW.w\t\tVI15,0(VI02)\r\n\t\tSUB.xyz\t\tVF04,VF25,VF20\t\tFSAND\t\tVI01,2\r\n\t\tOPMSUB.xyz\tVF02,VF26,VF02\t\tIBEQ\t\tVI01,VI00,CullPrism\r\n\t\tOPMULA.xyz\tACC,VF05,VF06\t\tNOP\r\n\t\tOPMSUB.xyz\tVF03,VF06,VF05\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF04,VF27\t\tNOP\r\n\t\tOPMSUB.xyz\tVF04,VF27,VF04\t\tNOP\r\n\r\n\t\t; compute and project v0,v1,v2 and their translates\r\n\t\tMULAx\t\tACC,VF16,VF22x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF17,VF22y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF18,VF22z\t\tNOP\r\n\t\tMADDw\t\tVF22,VF08,VF00w\t\tNOP\r\n\t\tMADDw\t\tVF25,VF07,VF00w\t\tNOP\r\n\t\t\r\n\t\t\r\n\t\tMULA\t\tACC,VF10,VF22\t\tNOP\r\n\t\tMADDw\t\tVF12,VF11,VF22w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t; needs to be 3 nops\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF12xyz,VF12w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t; needs to be 3 nops\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x00003F\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullPrism\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t\r\n\t\tMULAx\t\tACC,VF16,VF21x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF17,VF21y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF18,VF21z\t\tERCPR\t\tP,VF22w\r\n\t\tMADDw\t\tVF21,VF08,VF00w\t\tDIV\t\t\tQ,VF00w,VF25w\r\n\t\tMADDw\t\tVF24,VF07,VF00w\t\tNOP\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\tMULAx\t\tACC,VF16,VF20x\t\tMFIR.w      VF22,VI00\r\n\t\tMADDAy\t\tACC,VF17,VF20y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF18,VF20z\t\tNOP\r\n\t\tMADDw\t\tVF20,VF08,VF00w\t\tNOP\r\n\t\tMADDw\t\tVF23,VF07,VF00w\t\tNOP\r\n\r\n\t\tMULA\t\tACC,VF10,VF24\t\tNOP\r\n\t\tMADDw\t\tVF01,VF11,VF24w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t; needs to be 3 nops\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF01xyz,VF01w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t; needs to be 3 nops\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x00003F\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullPrism\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\t\r\n\t\tMULA\t\tACC,VF10,VF25\t\tNOP\r\n\t\tMADDw\t\tVF12,VF11,VF25w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t; needs to be 3 nops\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF12xyz,VF12w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t; needs to be 3 nops\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x00003F\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullPrism\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\n\t\tMULA\t\tACC,VF10,VF21\t\tNOP\r\n\t\tMADDw\t\tVF12,VF11,VF21w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t; needs to be 3 nops\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF12xyz,VF12w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t; needs to be 3 nops\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x00003F\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullPrism\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t\r\n\t\tMULq.xyz\tVF25,VF25,Q\t\t\tDIV\t\t\tQ,VF00w,VF21w\r\n\t\tMUL.xyz\t\tVF02,VF02,VF15\t\tNOP\r\n\t\tMUL.xyz\t\tVF03,VF03,VF15\t\tNOP\r\n\t\tMUL.xyz\t\tVF04,VF04,VF15\t\tNOP\r\n\t\tFTOI15.w\tVF21,VF00\t\t\tMFP.w\t\tVF01,P\r\n\t\tADDy.x\t\tVF02,VF02,VF02y\t\tERCPR\t\tP,VF24w\r\n\t\tADDx.y\t\tVF03,VF03,VF03x\t\tSQ.xyz\t\tVF25,6(VI02)\r\n\t\t\r\n\t\tMULA\t\tACC,VF10,VF23\t\tNOP\r\n\t\tMADDw\t\tVF12,VF11,VF23w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t; needs to be 3 nops\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF12xyz,VF12w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t; needs to be 3 nops\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x00003F\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullPrism\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t; vf20-25 = verts.\t \r\n\t\t\r\n\t\tMULA\t\tACC,VF10,VF20\t\tNOP\r\n\t\tMADDw\t\tVF12,VF11,VF20w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t; needs to be 3 nops\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF12xyz,VF12w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\t\t\t; needs to be 3 nops\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x00003F\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,CullPrism\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\r\n\t\t\r\n\t\tMULq.xyz\tVF21,VF21,Q\t\t\tDIV\t\t\tQ,VF00w,VF20w\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\tMULw.xyz\tVF22,VF22,VF01w\t\tSQ.w\t\tVF21,2(VI02)\r\n\t\tADDx.z\t\tVF04,VF04,VF04x\t\tNOP\r\n\t\tMULx.w\t\tVF05,VF00,VF25x\t\tNOP\r\n\t\tADDz.x\t\tVF02,VF02,VF02z\t\tSQ\t\t\tVF21,4(VI02)\r\n\t\tADDz.y\t\tVF03,VF03,VF03z\t\tSQ\t\t\tVF22,16(VI02)\r\n\t\tADDy.z\t\tVF04,VF04,VF04y\t\tSQ.xyz\t\tVF22,2(VI02)\r\n\t\tMULq.xyz\tVF20,VF20,Q\t\t\tDIV\t\t\tQ,VF00w,VF23w\r\n\t\tSUB.w\t\tVF23,VF00,VF00\t\tIADDIU      VI10, VI00, 0\t;FSAND\t\tVI10,2\t\t\t; get adc results (4 cycles after mac)\r\n\t\tADDy.x\t\tVF05,VF00,VF25y\t\tIADDIU      VI11, VI00, 0  ;FSAND\t\tVI11,2\r\n\t\tMULx.w\t\tVF22,VF00,VF22x\t\tIADDIU      VI12, VI00, 0  ;FSAND\t\tVI12,2\r\n\t\tADDy.x\t\tVF22,VF00,VF22y\t\tMFP.w\t\tVF01,P\r\n\t\tMULx.w\t\tVF26,VF00,VF21x\t\tNOP\t;ISUBIU\t\tVI10,VI10,1\r\n\t\tADDy.x\t\tVF26,VF00,VF21y\t\tNOP ;ISUBIU\t\tVI11,VI11,1\r\n\r\n\t\tMULq.xyz\tVF23,VF23,Q\t\t\tNOP ;ISUBIU\t\tVI12,VI12,1\r\n\t\t\r\n;\t\tSUB.w\t\tVF23,VF00,VF00\t\tFSAND\t\tVI10,2\t\t\t; get adc results (4 cycles after mac)\r\n;\t\tADDy.x\t\tVF05,VF00,VF25y\t\tFSAND\t\tVI11,2\r\n;\t\tMULx.w\t\tVF22,VF00,VF22x\t\tFSAND\t\tVI12,2\r\n;\t\tADDy.x\t\tVF22,VF00,VF22y\t\tMFP.w\t\tVF01,P\r\n;\t\tMULx.w\t\tVF26,VF00,VF21x\t\tISUBIU\t\tVI10,VI10,1\r\n;\t\tADDy.x\t\tVF26,VF00,VF21y\t\tISUBIU\t\tVI11,VI11,1\r\n;\t\t\r\n;\t\tMULq.xyz\tVF23,VF23,Q\t\t\tISUBIU\t\tVI12,VI12,1\r\n\t\tMULw.xyz\tVF24,VF24,VF01w\t\tSQ.xyz\t\tVF21,12(VI02)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF23,10(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF23,VI12\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.w\t\tVI10,12(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.w\t\tVI11,6(VI02)\r\n\r\n\t\t; backface testing and colours (8 tests)\r\n\t\tSUB.xw\t\tVF01,VF22,VF26\t\tMR32.xw\t\tVF04,VF24\r\n\t\tSUB.xw\t\tVF02,VF05,VF26\t\tMFIR.w\t\tVF20,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF24,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tMR32.xw\t\tVF06,VF23\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\tSUB.xw\t\tVF03,VF05,VF04\t\tMFIR.w\t\tVF25,VI12\r\n\t\tMULAx.w\t\tACC,VF01,VF02x\t\tSQ\t\t\tVF23,18(VI02)\r\n\t\tMSUBx.w\t\tVF00,VF02,VF01x\t\tSQ\t\t\tVF20,14(VI02)\r\n\r\n\t\tSUB.xw\t\tVF01,VF06,VF04\t\tMR32.xw\t\tVF20,VF20\r\n\t\tMULAx.w\t\tACC,VF03,VF02x\t\tSQ\t\t\tVF24,8(VI02)\r\n\t\tMSUBx.w\t\tVF00,VF02,VF03x\t\tSQ\t\t\tVF25,20(VI02)\r\n\r\n\t\tSUB.xw\t\tVF02,VF06,VF26\t\tFMAND\t\tVI01,VI09\r\n\t\tMULAx.w\t\tACC,VF03,VF01x\t\tISUBIU\t\tVI01,VI01,8\r\n\t\tMSUBx.w\t\tVF00,VF01,VF03x\t\tISW.xyz\t\tVI01,5(VI02)\r\n\r\n\t\tSUB.xw\t\tVF03,VF20,VF26\t\tFMAND\t\tVI01,VI09\r\n\t\tMULAx.w\t\tACC,VF02,VF01x\t\tISUBIU\t\tVI01,VI01,8\r\n\t\tMSUBx.w\t\tVF00,VF01,VF02x\t\tISW.xyz\t\tVI01,7(VI02)\r\n\r\n\t\tSUB.xw\t\tVF01,VF20,VF22\t\tFMAND\t\tVI01,VI09\r\n\t\tMULAx.w\t\tACC,VF02,VF03x\t\tISUBIU\t\tVI01,VI01,8\r\n\t\tMSUBx.w\t\tVF00,VF03,VF02x\t\tISW.xyz\t\tVI01,9(VI02)\r\n\r\n\t\tSUB.xw\t\tVF02,VF06,VF22\t\tFMAND\t\tVI01,VI09\r\n\t\tMULAx.w\t\tACC,VF01,VF03x\t\tISUBIU\t\tVI01,VI01,8\r\n\t\tMSUBx.w\t\tVF00,VF03,VF01x\t\tISW.xyz\t\tVI01,11(VI02)\r\n\r\n\t\tSUB.xw\t\tVF03,VF06,VF05\t\tFMAND\t\tVI01,VI09\r\n\t\tMULAx.w\t\tACC,VF01,VF02x\t\tISUBIU\t\tVI01,VI01,8\r\n\t\tMSUBx.w\t\tVF00,VF02,VF01x\t\tISW.xyz\t\tVI01,13(VI02)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND\t\tVI01,VI09\r\n\t\tMULAx.w\t\tACC,VF03,VF02x\t\tISUBIU\t\tVI01,VI01,8\r\n\t\tMSUBx.w\t\tVF00,VF02,VF03x\t\tISW.xyz\t\tVI01,15(VI02)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND\t\tVI01,VI09\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI01,VI01,8\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.xyz\t\tVI01,17(VI02)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND\t\tVI01,VI09\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI01,VI01,8\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.xyz\t\tVI01,19(VI02)\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI08, VI00, 1\r\n\t\tNOP\t\t\t\t\t\t\t\tXGKICK\t\tVI02\r\n\t\t\r\nCullPrism:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIBGEZ\t\tVI15,LoopSVS\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI02,VI02,21\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI08, VI00, DummyKick\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tNOP[E]\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\nDummyKick:\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI01, VI02, 1\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI08, VI00, 0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU      VI08, VI08, 0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.x\t\tVI08, 0(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tXGKICK\t\tVI01\r\n\r\n\t\tNOP[E]\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t.if 0\r\n\t\t; original unoptimised version\r\n \r\nLoopSVS:\r\n\t\t; v0\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF20,0(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF20w\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF04,3(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,0(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF02,1(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF03,2(VI01)\r\n\r\n\t\tADDAx.xyz\tACC,VF04,VF00x\t\tNOP\r\n\t\tMADDAx.xyz\tACC,VF01,VF20x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF02,VF20y\t\tNOP\r\n\t\tMADDz.xyz\tVF20,VF03,VF20z\t\tNOP\r\n\r\n\t\t; v1\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF21,1(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF21w\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF04,3(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,0(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF02,1(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF03,2(VI01)\r\n\r\n\t\tADDAx.xyz\tACC,VF04,VF00x\t\tNOP\r\n\t\tMADDAx.xyz\tACC,VF01,VF21x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF02,VF21y\t\tNOP\r\n\t\tMADDz.xyz\tVF21,VF03,VF21z\t\tNOP\r\n\r\n\t\t; v2\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF22,2(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF22w\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF04,3(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,0(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF02,1(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF03,2(VI01)\r\n\r\n\t\tADDAx.xyz\tACC,VF04,VF00x\t\tNOP\r\n\t\tMADDAx.xyz\tACC,VF01,VF22x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF02,VF22y\t\tNOP\r\n\t\tMADDz.xyz\tVF22,VF03,VF22z\t\tNOP\r\n\r\n\r\n\t\t; generate n021\r\n\t\tSUB.xyz\t\tVF05,VF20,VF22\t\tNOP\r\n\t\tSUB.xyz\t\tVF06,VF21,VF22\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF05,VF06\t\tNOP\r\n\t\tOPMSUB.xyz\tVF01,VF06,VF05\t\tNOP\r\n\r\n\t\t; dot with light vector\r\n\t\tMUL.xyz\t\tVF01,VF01,VF15\t\tNOP\r\n\t\tADDy.x\t\tVF01,VF01,VF01y\t\tNOP\r\n\t\tADDz.x\t\tVF01,VF01,VF01z\t\tMOVE\t\tVF02,VF01\r\n\t\t\r\n\t\t; cull if dot product negative\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI0\t\tVF02,VF02\t\t\tFSAND\t\tVI01,2\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI01,VI00,CullPrism\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\n\t\t; v3\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF23,3(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF23w\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF04,3(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,0(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF02,1(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF03,2(VI01)\r\n\r\n\t\tADDAx.xyz\tACC,VF04,VF00x\t\tNOP\r\n\t\tMADDAx.xyz\tACC,VF01,VF23x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF02,VF23y\t\tNOP\r\n\t\tMADDz.xyz\tVF23,VF03,VF23z\t\tNOP\r\n\r\n\t\t; v4\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF24,4(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF24w\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF04,3(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,0(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF02,1(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF03,2(VI01)\r\n\r\n\t\tADDAx.xyz\tACC,VF04,VF00x\t\tNOP\r\n\t\tMADDAx.xyz\tACC,VF01,VF24x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF02,VF24y\t\tNOP\r\n\t\tMADDz.xyz\tVF24,VF03,VF24z\t\tNOP\r\n\r\n\t\t; v5\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF25,5(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF25w\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF04,3(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,0(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF02,1(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF03,2(VI01)\r\n\r\n\t\tADDAx.xyz\tACC,VF04,VF00x\t\tNOP\r\n\t\tMADDAx.xyz\tACC,VF01,VF25x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF02,VF25y\t\tNOP\r\n\t\tMADDz.xyz\tVF25,VF03,VF25z\t\tNOP\r\n\t\t\r\n\t\t\r\n\t\t\r\n\r\n\t\t; generate n013\r\n\t\tSUB.xyz\t\tVF06,VF20,VF21\t\tNOP\r\n\t\tSUB.xyz\t\tVF05,VF23,VF21\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF05,VF06\t\tNOP\r\n\t\tOPMSUB.xyz\tVF02,VF06,VF05\t\tNOP\r\n\r\n\t\t; generate n241\r\n\t\tSUB.xyz\t\tVF06,VF22,VF24\t\tNOP\r\n\t\tSUB.xyz\t\tVF05,VF21,VF24\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF05,VF06\t\tNOP\r\n\t\tOPMSUB.xyz\tVF03,VF06,VF05\t\tNOP\r\n\r\n\t\t; generate n052\r\n\t\tSUB.xyz\t\tVF06,VF20,VF25\t\tNOP\r\n\t\tSUB.xyz\t\tVF05,VF22,VF25\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF05,VF06\t\tNOP\r\n\t\tOPMSUB.xyz\tVF04,VF06,VF05\t\tNOP\r\n\r\n\r\n\t\t; take dot products with light vec\r\n\t\tMUL.xyz\t\tVF02,VF02,VF15\t\tNOP\r\n\t\tMUL.xyz\t\tVF03,VF03,VF15\t\tNOP\r\n\t\tMUL.xyz\t\tVF04,VF04,VF15\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDy.x\t\tVF02,VF02,VF02y\t\tNOP\r\n\t\tADDx.y\t\tVF03,VF03,VF03x\t\tNOP\r\n\t\tADDx.z\t\tVF04,VF04,VF04x\t\tNOP\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDz.x\t\tVF02,VF02,VF02z\t\tIADDIU\t\tVI10,VI00,0x80\r\n\t\tADDz.y\t\tVF03,VF03,VF03z\t\tIADDIU\t\tVI11,VI00,0x40\r\n\t\tADDy.z\t\tVF04,VF04,VF04y\t\tIADDIU\t\tVI12,VI00,0x20\r\n\t\t\r\n\t\t; get ADC results\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND\t\tVI10,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND\t\tVI11,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND\t\tVI12,VI12\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI10,VI10,1\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI11,VI11,1\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI12,VI12,1\r\n\r\n\r\n\t\t; compute and project v0,v1,v2 and their translates\r\n\t\tMULAx\t\tACC,VF16,VF20x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF17,VF20y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF18,VF20z\t\tNOP\r\n\t\tMADDw\t\tVF20,VF08,VF00w\t\tNOP\r\n\t\tMADDw\t\tVF23,VF07,VF00w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF20w\r\n\t\tMULq.xyz\tVF20,VF20,Q\t\t\tWAITQ\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF23w\r\n\t\tMULq.xyz\tVF23,VF23,Q\t\t\tWAITQ\r\n\r\n\t\tMULAx\t\tACC,VF16,VF21x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF17,VF21y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF18,VF21z\t\tNOP\r\n\t\tMADDw\t\tVF21,VF08,VF00w\t\tNOP\r\n\t\tMADDw\t\tVF24,VF07,VF00w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF21w\r\n\t\tMULq.xyz\tVF21,VF21,Q\t\t\tWAITQ\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF24w\r\n\t\tMULq.xyz\tVF24,VF24,Q\t\t\tWAITQ\r\n\r\n\t\tMULAx\t\tACC,VF16,VF22x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF17,VF22y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF18,VF22z\t\tNOP\r\n\t\tMADDw\t\tVF22,VF08,VF00w\t\tNOP\r\n\t\tMADDw\t\tVF25,VF07,VF00w\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF22w\r\n\t\tMULq.xyz\tVF22,VF22,Q\t\t\tWAITQ\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF25w\r\n\t\tMULq.xyz\tVF25,VF25,Q\t\t\tWAITQ\r\n\r\n\r\n\t\t;   0\r\n\t\t;  /|\\\r\n\t\t; 2---1\r\n\t\t; | | |\r\n\t\t; | 3 |\r\n\t\t; |/ \\|\r\n\t\t; 5---4\r\n\t\t;\r\n\t\t; adc's a(01), b(12), c(20)\r\n\t\t;\r\n\t\t; 2, 1, 5, 4, 3, 1, 0, 2, 3, 5\r\n\t\t; 1, 1, b, b, 0, a, a, 0, c, c\r\n\r\n\t\t; store positions and adc's\r\n\t\tFTOI15.w\tVF22,VF00\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF22,1(VI02)\r\n\t\tFTOI15.w\tVF21,VF00\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF21,3(VI02)\r\n\t\t\r\n\t\tFTOI15.w\tVF25,VF00\t\t\tNOP\r\n;\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF25,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF25,5(VI02)\r\n\t\tFTOI15.w\tVF24,VF00\t\t\tNOP\r\n;\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF24,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF24,7(VI02)\r\n\t\t\r\n\t\t;FTOI15.w\tVF23,VF00\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF23,VI00\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF23,9(VI02)\r\n\t\t\r\n;\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF21,VI10\r\n\t\tFTOI15.w\tVF21,VF00\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF21,11(VI02)\r\n\t\tFTOI15.w\tVF20,VF00\t\t\tNOP\r\n;\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF20,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF20,13(VI02)\r\n\t\t\r\n\t\t;FTOI15.w\tVF22,VF00\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF22,VI00\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF22,15(VI02)\r\n\t\t\r\n;\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF23,VI12\r\n\t\tFTOI15.w\tVF23,VF00\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF23,17(VI02)\r\n;\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF25,VI12\r\n\t\tFTOI15.w\tVF25,VF00\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF25,19(VI02)\r\n\r\n\r\n\t\t\r\n\t\t; backface testing and colours (8 tests)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI00,0x10\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI11,VI00,0x08\r\n\t\t\r\n\t\t; 215\r\n\t\tSUB.xyz\t\tVF01,VF22,VF21\t\tNOP\r\n\t\tSUB.xyz\t\tVF02,VF25,VF21\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF01,VF02\t\tNOP\r\n\t\tOPMSUB.xyz\tVF03,VF02,VF01\t\tMOVE\t\tVF01,VF02\r\n\t\tMULz.w\t\tVF00,VF00,VF03z\t\tMOVE\t\tVF01,VF02\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI0\t\tVF02,VF01\t\t\tFMAND\t\tVI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI01,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.xyzw\tVI01,4(VI02)\r\n\t\t\r\n\t\t; 145\r\n\t\tSUB.xyz\t\tVF01,VF21,VF24\t\tNOP\r\n\t\tSUB.xyz\t\tVF02,VF25,VF24\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF01,VF02\t\tNOP\r\n\t\tOPMSUB.xyz\tVF03,VF02,VF01\t\tMOVE\t\tVF01,VF02\r\n\t\tMULz.w\t\tVF00,VF00,VF03z\t\tMOVE\t\tVF01,VF02\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI0\t\tVF02,VF01\t\t\tFMAND\t\tVI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI01,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.xyzw\tVI01,6(VI02)\r\n\t\t\r\n\t\t; 543\r\n\t\tSUB.xyz\t\tVF01,VF25,VF24\t\tNOP\r\n\t\tSUB.xyz\t\tVF02,VF23,VF24\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF01,VF02\t\tNOP\r\n\t\tOPMSUB.xyz\tVF03,VF02,VF01\t\tMOVE\t\tVF01,VF02\r\n\t\tMULz.w\t\tVF00,VF00,VF03z\t\tMOVE\t\tVF01,VF02\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI0\t\tVF02,VF01\t\t\tFMAND\t\tVI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI01,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.xyzw\tVI01,8(VI02)\r\n\t\t\r\n\t\t; 134\r\n\t\tSUB.xyz\t\tVF01,VF21,VF23\t\tNOP\r\n\t\tSUB.xyz\t\tVF02,VF24,VF23\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF01,VF02\t\tNOP\r\n\t\tOPMSUB.xyz\tVF03,VF02,VF01\t\tMOVE\t\tVF01,VF02\r\n\t\tMULz.w\t\tVF00,VF00,VF03z\t\tMOVE\t\tVF01,VF02\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI0\t\tVF02,VF01\t\t\tFMAND\t\tVI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI01,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.xyzw\tVI01,10(VI02)\r\n\t\t\r\n\t\t; 103\r\n\t\tSUB.xyz\t\tVF01,VF21,VF20\t\tNOP\r\n\t\tSUB.xyz\t\tVF02,VF23,VF20\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF01,VF02\t\tNOP\r\n\t\tOPMSUB.xyz\tVF03,VF02,VF01\t\tMOVE\t\tVF01,VF02\r\n\t\tMULz.w\t\tVF00,VF00,VF03z\t\tMOVE\t\tVF01,VF02\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI0\t\tVF02,VF01\t\t\tFMAND\t\tVI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI01,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.xyzw\tVI01,12(VI02)\r\n\t\t\r\n\t\t; 012\r\n\t\tSUB.xyz\t\tVF01,VF20,VF21\t\tNOP\r\n\t\tSUB.xyz\t\tVF02,VF22,VF21\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF01,VF02\t\tNOP\r\n\t\tOPMSUB.xyz\tVF03,VF02,VF01\t\tMOVE\t\tVF01,VF02\r\n\t\tMULz.w\t\tVF00,VF00,VF03z\t\tMOVE\t\tVF01,VF02\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI0\t\tVF02,VF01\t\t\tFMAND\t\tVI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI01,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.xyzw\tVI01,14(VI02)\r\n\t\t\r\n\t\t; 023\r\n\t\tSUB.xyz\t\tVF01,VF20,VF22\t\tNOP\r\n\t\tSUB.xyz\t\tVF02,VF23,VF22\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF01,VF02\t\tNOP\r\n\t\tOPMSUB.xyz\tVF03,VF02,VF01\t\tMOVE\t\tVF01,VF02\r\n\t\tMULz.w\t\tVF00,VF00,VF03z\t\tMOVE\t\tVF01,VF02\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI0\t\tVF02,VF01\t\t\tFMAND\t\tVI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI01,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.xyzw\tVI01,16(VI02)\r\n\r\n\t\t; 253\r\n\t\tSUB.xyz\t\tVF01,VF22,VF25\t\tNOP\r\n\t\tSUB.xyz\t\tVF02,VF23,VF25\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF01,VF02\t\tNOP\r\n\t\tOPMSUB.xyz\tVF03,VF02,VF01\t\tMOVE\t\tVF01,VF02\r\n\t\tMULz.w\t\tVF00,VF00,VF03z\t\tMOVE\t\tVF01,VF02\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\tFTOI0\t\tVF02,VF01\t\t\tFMAND\t\tVI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI01,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.xyz\t\tVI01,18(VI02)\r\n\r\nNextPrism:\t\t\r\n\t\t; loop control\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI02,VI02,20\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\n\t\t.endif\r\n\r\n\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n; clip triangle if not already culled and if part of it may be in the view frustum and another part in the outer frustum\r\n; i.e. if clip if (ADC==0 && viewAND==0 && outerOR!=0)\r\n\r\n; ADC bit should be set for any of the following:\r\n;  - ADC set already\r\n;  - outerOR!=0 (i.e. if culling renderer would cull it)\r\n;  - viewAND!=0 (trivial rejection)\r\n\r\nClip:\r\n\r\n\t\t; reconstruct world-to-frustum transform\r\n\t\tMULA\t\tACC,VF10,VF12\t\tNOP\r\n\t\tMADDw\t\tVF04,VF11,VF12w\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF13\t\tNOP\r\n\t\tMADDw\t\tVF05,VF11,VF13w\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF14\t\tNOP\r\n\t\tMADDw\t\tVF06,VF11,VF14w\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF15\t\tNOP\r\n\t\tMADDw\t\tVF07,VF11,VF15w\t\tNOP\r\n\t\t\r\n\t\t.if 0\r\n\t\t;---------------------------------------------------------\r\n\t\t.if 0\r\n\t\t; optimised version\r\n\t\t\r\n\t\t; loop prologue\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tADDAx\t\tACC,VF07,VF00x\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tNOP\r\n\t\tMADDAx\t\tACC,VF04,VF02x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF05,VF02y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF06,VF02z\t\tNOP\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tIADDIU\t\tVI10,VI00,0\r\n\t\t\r\n\t\t; main clip-testing loop\r\nLoopC:\tADDAw.xyz\tACC,VF00,VF03w\t\tMTIR\t\tVI07,VF01w\r\n\t\tMULAw.w\t\tACC,VF03,VF00w\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDAz.x\tACC,VF03,VF09z\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tMADDAw.y\tACC,VF03,VF09w\t\tFCOR\t\tVI01,0xFEFBEF\r\n\t\tMSUBAx.z\tACC,VF09,VF03x\t\tISUB\t\tVI07,VI07,VI01\r\n\t\tMSUBAy.w\tACC,VF09,VF03y\t\tFCOR\t\tVI01,0xFDF7DF\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tISUB\t\tVI07,VI07,VI01\r\n\t\tMADDx\t\tVF00,VF00,VF00x\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI07,VI07,VI01\r\n\t\tADDAx\t\tACC,VF07,VF00x\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tMADDAx\t\tACC,VF04,VF02x\t\tIAND\t\tVI08,VI10,VI11\r\n\t\tMADDAy\t\tACC,VF05,VF02y\t\tIADDIU\t\tVI11,VI10,0\r\n\t\tMADDz\t\tVF03,VF06,VF02z\t\tFMOR\t\tVI10,VI00\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI08,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI07,VI07,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopC\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tISW.w\t\tVI07,-1(VI02)\r\n\t\t\r\n\t\t;---------------------------------------------------------\r\n\t\t.else\r\n\t\t; unoptimised version\r\n\r\n\t\t; initialise source pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\t\r\nLoopC:\r\n\t\t; step source pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\t\r\n\t\t; load vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; convert to float\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tNOP\r\n\t\t\r\n\t\t; get ADC field\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI07,VF01w\r\n\t\t\r\n\t\t; transform to outer volume\r\n\t\tADDAx\t\tACC,VF07,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF04,VF02x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF05,VF02y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF06,VF02z\t\tNOP\r\n\t\t\r\n\t\t; step destination pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; generate clip codes\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tNOP\r\n\r\n\t\t; generate pre-AND and advance outcode queue\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI08,VI10,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI11,VI10,0\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; generate view-AND.z, combine with ADC\r\n\t\tNOP\t\t\t\t\t\t\t\tFCOR\t\tVI01,0xFEFBEF\t\t; near\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI07,VI07,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tFCOR\t\tVI01,0xFDF7DF\t\t; far\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI07,VI07,VI01\r\n\t\t\r\n\t\t; get outer-OR.xyz, combine with ADC\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI07,VI07,VI01\r\n\r\n\t\t; generate flags for view-AND.xy\r\n\t\tADDAw.xyz\tACC,VF00,VF03w\t\tNOP\r\n\t\tMULAw.w\t\tACC,VF03,VF00w\t\tNOP\r\n\t\tMADDAz.x\tACC,VF03,VF09z\t\tNOP\r\n\t\tMADDAw.y\tACC,VF03,VF09w\t\tNOP\r\n\t\tMSUBAx.z\tACC,VF09,VF03x\t\tNOP\r\n\t\tMSUBAy.w\tACC,VF09,VF03y\t\tNOP\r\n\t\tMADDx\t\tVF00,VF00,VF00x\t\tNOP\t\t\t; result is (w+Sx*x,w+Sy*y,w-Sx*x,w-Sy*y)\r\n\t\t\r\n\t\t; get flags for view-AND.xy\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFMOR\t\tVI10,VI00\r\n\t\t\r\n\t\t; generate view-AND.xy, combine with ADC\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI08,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI07,VI07,VI01\r\n\t\t\r\n\t\t; store computed w component\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.w\t\tVI07,-1(VI02)\r\n\t\t\r\n\t\t; loop control\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopC\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t.endif\r\n\t\t;---------------------------------------------------------\r\n\t\t.else\r\n\t\t; backface cull version\r\n\t\t\r\n\t\t.if 0\r\n\t\t; unoptimised version\r\n\t\t\r\n\t\t; initialise source pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\t\r\n\t\t; set ADC mask\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI09,VI00,0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI09,VI09,0x4000\r\n\t\t\r\nLoopC:\r\n\t\t; step source pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\r\n\t\t\r\n\t\t; load vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; convert to float\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tNOP\r\n\t\t\r\n\t\t; get ADC field\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI14,VF01w\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI07,VI14,VI09\r\n\t\t\r\n\t\t; transform to outer volume\r\n\t\tADDAx\t\tACC,VF07,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF04,VF02x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF05,VF02y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF06,VF02z\t\tNOP\r\n\t\t\r\n\t\t; step destination pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; generate clip codes\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tNOP\r\n\r\n\t\t; generate pre-AND and advance outcode queue\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI08,VI10,VI11\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI11,VI10,0\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; generate view-AND.z, combine with ADC\r\n\t\tNOP\t\t\t\t\t\t\t\tFCOR\t\tVI01,0xFEFBEF\t\t; near\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI07,VI07,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tFCOR\t\tVI01,0xFDF7DF\t\t; far\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI07,VI07,VI01\r\n\t\t\r\n\t\t; get outer-OR.xyz, combine with ADC\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI07,VI07,VI01\r\n\r\n\t\t; generate flags for view-AND.xy\r\n\t\tADDAw.xyz\tACC,VF00,VF03w\t\tNOP\r\n\t\tMULAw.w\t\tACC,VF03,VF00w\t\tNOP\r\n\t\tMADDAz.x\tACC,VF03,VF09z\t\tNOP\r\n\t\tMADDAw.y\tACC,VF03,VF09w\t\tNOP\r\n\t\tMSUBAx.z\tACC,VF09,VF03x\t\tNOP\r\n\t\tMSUBAy.w\tACC,VF09,VF03y\t\tNOP\r\n\t\tMADDx\t\tVF00,VF00,VF00x\t\tNOP\t\t\t; result is (w+Sx*x,w+Sy*y,w-Sx*x,w-Sy*y)\r\n\t\t\r\n\t\t; get flags for view-AND.xy\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tFMOR\t\tVI10,VI00\r\n\t\t\r\n\t\t; inc by 1\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI07,VI07,1\r\n\t\t\r\n\t\t; generate view-AND.xy, combine with ADC\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI08,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI07,VI07,VI01\r\n\t\t\r\n\t\t; will it be clipped?\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI07,VI00,WontBeClipped\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; set both adc and clip-bit (0x4000)\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI01,VI14,0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.w\t\tVI01,-1(VI02)\r\nWontBeClipped:\r\n\t\t\r\n\t\t; loop control\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopC\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t.else\r\n\t\t; optimised version\r\n\t\t;\r\n\t\t\r\n\t\t; loop prologue\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI02,VI04\r\n\t\tADDAx\t\tACC,VF07,VF00x\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tIADDIU\t\tVI09,VI00,0x4000\r\n\t\tMADDAx\t\tACC,VF04,VF02x\t\tIADDIU\t\tVI09,VI09,0x4000\r\n\t\tMADDAy\t\tACC,VF05,VF02y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF06,VF02z\t\tNOP\r\n\t\t\r\n\t\t; main clip-testing loop\r\nLoopC:\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,AllClipped\r\n\t\tCLIPw.xyz\tVF03xyz,VF03w\t\tMTIR\t\tVI14,VF01w\r\n\t\tADDAw.xyz\tACC,VF00,VF03w\t\tIAND\t\tVI07,VI14,VI09\r\n\t\tMULAw.w\t\tACC,VF03,VF00w\t\tIADD\t\tVI03,VI03,VI04\r\n\t\tMADDAz.x\tACC,VF03,VF09z\t\tLQ\t\t\tVF01,-1(VI03)\r\n\t\tMADDAw.y\tACC,VF03,VF09w\t\tFCOR\t\tVI01,0xFEFBEF\r\n\t\tMSUBAx.z\tACC,VF09,VF03x\t\tISUB\t\tVI07,VI07,VI01\r\n\t\tMSUBAy.w\tACC,VF09,VF03y\t\tFCOR\t\tVI01,0xFDF7DF\r\n\t\tITOF4.xyz\tVF02,VF01\t\t\tISUB\t\tVI07,VI07,VI01\r\n\t\tMADDx\t\tVF00,VF00,VF00x\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI07,VI07,VI01\r\n\t\tADDAx\t\tACC,VF07,VF00x\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tMADDAx\t\tACC,VF04,VF02x\t\tIAND\t\tVI08,VI10,VI11\r\n\t\tMADDAy\t\tACC,VF05,VF02y\t\tIADDIU\t\tVI11,VI10,0\r\n\t\tMADDz\t\tVF03,VF06,VF02z\t\tFMOR\t\tVI10,VI00\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI08,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI07,VI07,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI07,VI07,1\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI07,VI00,LoopC\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI01,VI14,0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopC\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.w\t\tVI01,-1(VI02)\r\n\t\t\r\n\t\t.endif\r\n\t\t.endif\r\n\t\t;---------------------------------------------------------\r\n\t\t\r\nAllClipped:\r\n\t\t; reset pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\t\t\r\n\t\t; set the EOP bit of the previous tag\r\n\t\tNOP\t\t\t\t\t\t\t\tILW.x\t\tVI01,0(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.x\t\tVI01,0(VI12)\r\n\t\t\r\n\t\t; set fan buffer base\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI12,VI13,288\t\t; MAX_VU1_BUFFER - # regs to save\r\n\t\t\r\n\t\t; kick the context (which might be just a dummy giftag)\r\n\t\t; this stalls until the GS has finished with the memory we want to use as the fan buffer\r\n\t\tNOP\t\t\t\t\t\t\t\tXGKICK\t\tVI13\r\n\t\t\r\n\t\t; the fan buffer is now guaranteed not to be in use by the GS or DMAC\r\n\t\t\r\n\t\t; save some registers\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF20,-12(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF21,-11(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF22,-10(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF23,-9(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF24,-8(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF25,-7(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF26,-6(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF27,-5(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF28,-4(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF29,-3(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF30,-2(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF31,-1(VI12)\r\n\t\t\r\n\t\t; set new giftag pointer (the preclipped tristrip)\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI13,VI02,1\r\n\t\t\r\n\t\t; output pointer = fan buffer base\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI12,0\r\n\t\t\r\n\r\n\t\t; frustum planes:\r\n\t\t;\r\n\t\t; 0x0020 far\r\n\t\t; 0x0010 near\r\n\t\t; 0x0008 top\r\n\t\t; 0x0004 bottom\r\n\t\t; 0x0002 left\r\n\t\t; 0x0001 right\r\n\t\t;\r\n\t\t;   1---------0\r\n\t\t;   |\\   3   /|\r\n\t\t;   | *-----* |\r\n\t\t;   | | (5) | |\r\n\t\t;   |1|  4  |0|\r\n\t\t;   | |     | |\r\n\t\t;   | *-----* |\r\n\t\t;   |/   2   \\|\r\n\t\t;   *---------*\r\n\r\n\r\n\t\t; registers used:\r\n\t\t;\r\n\t\t; VF20: p[j0], m[j0]\r\n\t\t; VF21: p[j1], m[j1]\r\n\t\t; VF22: p[j2], m[j2]\r\n\t\t; VF23: p[j3], m[j3]\r\n\t\t; VF24: p[j4], m[j4]\r\n\t\t; VF25: p[j5], m[j5]\r\n\t\t;\r\n\t\t; VF26: x[i0], o[i0]\r\n\t\t; VF27: x[i1], o[i1]\r\n\t\t; VF28: x[i2], o[i2]\r\n\t\t;\r\n\t\t; VF30: e0, flags(e0), just the w-component\r\n\t\t; VF31: e1, flags(e1)\r\n\t\t;\r\n\t\t;\r\n\t\t; VI12: fan buffer base\r\n\r\n\r\n\t\t; skip the 1st 2 vertices\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI02,VI05\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI08,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tIBGEZ\t\tVI01,PostClip\r\n\t\tNOP\t\t\t\t\t\t\t\tILW.w\t\tVI01,-1(VI08)\r\n\r\n\t\t; loop over strip, clipping the triangles that are marked with clip bit 0x4000\r\nClipLoop:\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,KickFans\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI08,VI00,0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI08,VI01,VI08\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI01,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI08,VI00,ClipLoop\r\n\t\tNOP\t\t\t\t\t\t\t\tILW.w\t\tVI01,-1(VI01)\r\n\r\n\r\n\t\t; go ahead with clipping...\r\n\t\t\r\n\r\n\t\t;-------------------------------\r\n\t\t; load vertex coords from memory\r\n\t\t;-------------------------------\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF07,-1(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF06,-1(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI01,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF05,-1(VI01)\r\n\t\t\r\n\t\t\r\n\t\t;-----------------\r\n\t\t; convert to float\r\n\t\t;-----------------\r\n\t\t\r\n\t\tITOF4.xyz\tVF07,VF07\t\t\tNOP\r\n\t\tITOF4.xyz\tVF06,VF06\t\t\tNOP\r\n\t\tITOF4.xyz\tVF05,VF05\t\t\tNOP\r\n\r\n\t\t;------------------------\r\n\t\t; apply frustum transform\r\n\t\t;------------------------\r\n\r\n\t\t; reconstruct world-to-frustum transform\r\n\t\tMULA\t\tACC,VF10,VF15\t\tNOP\r\n\t\tMADDw\t\tVF04,VF11,VF15w\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF12\t\tNOP\r\n\t\tMADDw\t\tVF01,VF11,VF12w\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF13\t\tNOP\r\n\t\tMADDw\t\tVF02,VF11,VF13w\t\tNOP\r\n\t\tMULA\t\tACC,VF10,VF14\t\tNOP\r\n\t\tMADDw\t\tVF03,VF11,VF14w\t\tNOP\r\n\t\t\r\n\t\tADDAx\t\tACC,VF04,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF01,VF05x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF02,VF05y\t\tNOP\r\n\t\tMADDz\t\tVF26,VF03,VF05z\t\tNOP\r\n\r\n\t\tADDAx\t\tACC,VF04,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF01,VF06x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF02,VF06y\t\tNOP\r\n\t\tMADDz\t\tVF27,VF03,VF06z\t\tNOP\r\n\r\n\t\tADDAx\t\tACC,VF04,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF01,VF07x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF02,VF07y\t\tNOP\r\n\t\tMADDz\t\tVF28,VF03,VF07z\t\tNOP\r\n\r\n\r\n\t\t; reorder the vertices\r\n\t\t;\r\n\t\t.if 0\r\n\t\t\r\n\t\t; zero the swap flags\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI00,0\r\n\t\t\r\n\t\t; set up mask 0x0E\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI07,VI00,0x0E\r\n\t\t\r\n\t\t; compare VF05 to VF06\r\n\t\tMAX.xyz\t\tVF01,VF05,VF06\t\tNOP\r\n\t\tSUB.xyz\t\tVF00,VF05,VF06\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tSUB.xyz\t\tVF00,VF01,VF06\t\tNOP\r\n\t\t\r\n\t\t; Z\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND \t\tVI01,VI07\r\n\t\t\r\n\t\t; ~Z\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI07,VI01\r\n\t\t\r\n\t\t; ~Z & -(~Z)\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI08,VI00,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI08\r\n\t\t\r\n\t\t; (~Z & -(~Z)) & S\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND\t\tVI01,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,NoSwap0\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tADDx.xyz\tVF05,VF06,VF00x\t\tMOVE.xyz\tVF06,VF05\r\n\t\tADDx\t\tVF26,VF27,VF00x\t\tMOVE\t\tVF27,VF26\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI10,1\r\nNoSwap0:\r\n\t\t\r\n\t\t; compare VF05 to VF07\r\n\t\tMAX.xyz\t\tVF02,VF05,VF07\t\tNOP\r\n\t\tSUB.xyz\t\tVF00,VF05,VF07\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tSUB.xyz\t\tVF00,VF02,VF07\t\tNOP\r\n\t\t\r\n\t\t; Z\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND \t\tVI01,VI07\r\n\t\t\r\n\t\t; ~Z\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI07,VI01\r\n\t\t\r\n\t\t; ~Z & -(~Z)\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI08,VI00,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI08\r\n\t\t\r\n\t\t; (~Z & -(~Z)) & S\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND\t\tVI01,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,NoSwap1\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tADDx.xyz\tVF05,VF07,VF00x\t\tMOVE.xyz\tVF07,VF05\r\n\t\tADDx\t\tVF26,VF28,VF00x\t\tMOVE\t\tVF28,VF26\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI10,2\r\nNoSwap1:\r\n\t\t\r\n\t\t; compare VF06 to VF07\r\n\t\tMAX.xyz\t\tVF03,VF06,VF07\t\tNOP\r\n\t\tSUB.xyz\t\tVF00,VF06,VF07\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tSUB.xyz\t\tVF00,VF03,VF07\t\tNOP\r\n\t\t\r\n\t\t; Z\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND \t\tVI01,VI07\r\n\t\t\r\n\t\t; ~Z\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI07,VI01\r\n\t\t\r\n\t\t; ~Z & -(~Z)\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI08,VI00,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI08\r\n\t\t\r\n\t\t; (~Z & -(~Z)) & S\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND\t\tVI01,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,NoSwap2\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tADDx.xyz\tVF06,VF07,VF00x\t\tMOVE.xyz\tVF07,VF06\r\n\t\tADDx\t\tVF27,VF28,VF00x\t\tMOVE\t\tVF28,VF27\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI10,4\r\nNoSwap2:\r\n\r\n\t\t; save the swap flags\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.x\t\tVF30,VI10\r\n\t\t\r\n\t\t.else\r\n\t\t\r\n\t\tMAX.xyz\t\tVF01,VF05,VF06\t\tIADDIU\t\tVI09,VI00,0x0E\t\t; set up mask 0x0E\r\n\t\tSUB.xyz\t\tVF00,VF05,VF06\t\tNOP\r\n\t\tMAX.xyz\t\tVF02,VF05,VF07\t\tNOP\r\n\t\tMAX.xyz\t\tVF03,VF06,VF07\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tSUB.xyz\t\tVF00,VF01,VF06\t\tFMAND \t\tVI01,VI09\t\t\t; Z\r\n\t\tSUB.xyz\t\tVF00,VF05,VF07\t\tISUB\t\tVI07,VI09,VI01\t\t; ~Z\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI00,VI07\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI07,VI07,VI01\t\t; ~Z & -(~Z)\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND\t\tVI07,VI07\t\t\t; (~Z & -(~Z)) & S\r\n\t\tSUB.xyz\t\tVF00,VF02,VF07\t\tFMAND \t\tVI01,VI09\t\t\t; Z\r\n\t\tSUB.xyz\t\tVF00,VF06,VF07\t\tISUB\t\tVI08,VI09,VI01\t\t; ~Z\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI00,VI08\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI08,VI08,VI01\t\t; ~Z & -(~Z)\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND\t\tVI08,VI08\t\t\t; (~Z & -(~Z)) & S\r\n\t\tSUB.xyz\t\tVF00,VF03,VF07\t\tFMAND \t\tVI01,VI09\t\t\t; Z\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI09,VI09,VI01\t\t; ~Z\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI00,VI09\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI09,VI09,VI01\t\t; ~Z & -(~Z)\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND\t\tVI09,VI09\t\t\t; (~Z & -(~Z)) & S\r\n\r\n\t\tADDx.xyz\tVF01,VF05,VF00x\t\tIBEQ\t\tVI07,VI00,NoSwap0\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,0\r\n\t\t\r\n\t\tADDx.xyz\tVF05,VF06,VF00x\t\tISUB\t\tVI08,VI08,VI09\t\t; swap VF05 with VF06\r\n\t\tADDx\t\tVF26,VF27,VF00x\t\tMOVE\t\tVF27,VF26\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI09,VI08,VI09\t\t; and swap flags VI08 with VI09\r\n\t\tADDx.xyz\tVF06,VF01,VF00x\t\tISUB\t\tVI08,VI09,VI08\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,1\t\t\t; set swap flag 0\r\nNoSwap0:\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI08,VI00,NoSwap1\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tADDx.xyz\tVF05,VF07,VF00x\t\tMOVE.xyz\tVF07,VF05\t\t\t; swap VF05 with VF07\r\n\t\tADDx\t\tVF26,VF28,VF00x\t\tMOVE\t\tVF28,VF26\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,2\t\t\t; set swap flag 1\r\nNoSwap1:\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI09,VI00,NoSwap2\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tADDx.xyz\tVF06,VF07,VF00x\t\tMOVE.xyz\tVF07,VF06\t\t\t; swap VF06 with VF07\r\n\t\tADDx\t\tVF27,VF28,VF00x\t\tMOVE\t\tVF28,VF27\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,4\t\t\t; set swap flag 2\r\nNoSwap2:\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.x\t\tVF30,VI01\t\t\t; save the swap flags\r\n\t\t\r\n\t\t.endif\r\n\t\t;------------------------------------------------------------------------\r\n\t\t\r\n\t\t\r\n\t\t;--------------------------\r\n\t\t; apply full view transform\r\n\t\t;--------------------------\r\n\t\t\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF05x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF05y\t\tNOP\r\n\t\tMADDz\t\tVF05,VF14,VF05z\t\tNOP\r\n\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF06x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF06y\t\tNOP\r\n\t\tMADDz\t\tVF06,VF14,VF06z\t\tNOP\r\n\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF07x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF07y\t\tNOP\r\n\t\tMADDz\t\tVF07,VF14,VF07z\t\tNOP\r\n\r\n\r\n\r\n\t\t;---------------------------\r\n\t\t; classify triangle vertices\r\n\t\t;---------------------------\r\n\r\n\t\tADDx\t\tVF01,VF26,VF00x\t\tBAL\t\t\tVI14,ClassifyTriangleVertex\r\n\t\tSUB.xyz\t\tVF02,VF00,VF26\t\tMR32.z\t\tVF26,VF26\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF26,VI01\r\n\t\t\r\n\t\tADDx\t\tVF01,VF27,VF00x\t\tBAL\t\t\tVI14,ClassifyTriangleVertex\r\n\t\tSUB.xyz     VF02,VF00,VF27\t\tMR32.z\t\tVF27,VF27\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF27,VI01\r\n\t\t\r\n\t\tADDx\t\tVF01,VF28,VF00x\t\tBAL\t\t\tVI14,ClassifyTriangleVertex\r\n\t\tSUB.xyz     VF02,VF00,VF28\t\tMR32.z\t\tVF28,VF28\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF28,VI01\r\n\r\n\r\n\t\t;--------------------------\r\n\t\t; classify frustum vertices\r\n\t\t;--------------------------\r\n\t\t\r\n\t\t; in frustum coords, the 8 vertices of the frustum are\r\n\t\t; FTL\t( f, f, f,-f)  ->  (-1,-1,-1)\t0x8000\r\n\t\t; FTR\t(-f, f, f,-f)  ->  ( 1,-1,-1)\t0x4000\r\n\t\t; FBL\t( f,-f, f,-f)  ->  (-1, 1,-1)\t0x2000\r\n\t\t; FBR\t(-f,-f, f,-f)  ->  ( 1, 1,-1)\t0x1000\r\n\t\t; NTL\t( n, n,-n,-n)  ->  (-1,-1, 1)\t0x0800\r\n\t\t; NTR\t(-n, n,-n,-n)  ->  ( 1,-1, 1)\t0x0400\r\n\t\t; NBL\t( n,-n,-n,-n)  ->  (-1, 1, 1)\t0x0200\r\n\t\t; NBR\t(-n,-n,-n,-n)  ->  ( 1, 1, 1)\t0x0100\r\n\t\t\r\n\t\t; for point classification we can work entirely in frustum coords,\r\n\t\t; using just the x,y and w of each point (which form a right-handed set)\r\n\t\t\r\n\t\t; calculate normal to plane of triangle\t(in frustum xyw-space)\r\n\t\tSUB.xyz\t\tVF01,VF27,VF26\t\tNOP\r\n\t\tSUB.xyz\t\tVF02,VF28,VF26\t\tNOP\r\n\t\t\r\n\t\t;ADDw.xyz\tVF04,VF00,VF00w\t\tNOP\t\t\t\t\t\t\t\t; set VF04 = (1,1,1,1)...\r\n\t\t;NOP\t\t\t\t\t\t\t\tMOVE.w\t\tVF04,VF00\r\n\t\tMAXw\t\tVF04,VF00,VF00w\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tOPMULA.xyz\tACC,VF02,VF01\t\tNOP\r\n\t\tOPMSUB.xyz\tVF01,VF01,VF02\t\tNOP\r\n\t\t\r\n\t\tSUBA\t\tACC,VF00,VF00\t\tNOP\r\n\t\t\r\n\t\t; set VF03 = (nx*x0, ny*y0, nz*w0, ?)\r\n\t\tMUL.xyz\t\tVF03,VF01,VF26\t\tNOP\r\n\t\t\r\n\t\t; set VF01 = (nx+ny-nz, -nx+ny-nz, nx-ny-nz, -nx-ny-nz)\r\n\t\tMADDAx.xz\tACC,VF04,VF01x\t\tNOP\r\n\t\tMSUBAx.yw\tACC,VF04,VF01x\t\tNOP\r\n\t\tMADDAy.xy\tACC,VF04,VF01y\t\tNOP\r\n\t\tMSUBAy.zw\tACC,VF04,VF01y\t\tNOP\r\n\t\tMSUBz\t\tVF01,VF04,VF01z\t\tNOP\r\n\t\t\r\n\t\t; set ACC = (n.x0, n.x0, n.x0, n.x0)\r\n\t\tMULAx\t\tACC,VF04,VF03x\t\tNOP\r\n\t\tMADDAy\t\tACC,VF04,VF03y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF04,VF03z\t\tNOP\r\n\t\t\r\n\t\t; calculate (n.x0) - far * VF01\r\n\t\tMSUBy\t\tVF00,VF01,VF09y\t\tNOP\r\n\t\t\r\n\t\t; calculate (n.x0) - near * VF01\r\n\t\tMSUBx\t\tVF00,VF01,VF09x\t\tNOP\r\n\t\t\r\n\t\t; classify 8 vertices of frustum wrt plane of triangle\r\n\t\tADDx.x\t\tVF01,VF00,VF28x\t\tIADDIU\t\tVI08,VI00,0x0F10\r\n\t\tADDx.y\t\tVF01,VF00,VF26x\t\tIADDIU\t\tVI01,VI00,0x00F0\t; Sxyzw MAC flags\r\n\t\tADDx.z\t\tVF01,VF00,VF27x\t\tFMAND\t\tVI10,VI01\r\n\t\tADDz.x\t\tVF03,VF00,VF28z\t\tFMAND\t\tVI01,VI01\r\n\t\tADDz.y\t\tVF03,VF00,VF26z\t\tIADD\t\tVI10,VI10,VI10\r\n\t\tADDz.z\t\tVF03,VF00,VF27z\t\tIADD\t\tVI10,VI10,VI10\r\n        ADDy.x\t\tVF02,VF00,VF28y\t\tIADD\t\tVI10,VI10,VI10\r\n\t\tADDy.y\t\tVF02,VF00,VF26y\t\tIADD\t\tVI10,VI10,VI10\r\n\t\tADDy.z\t\tVF02,VF00,VF27y\t\tIOR\t\t\tVI10,VI10,VI01\r\n\r\n\r\n\t\t; frustum outcodes now in VI10\r\n\r\n\r\n\t\t;------------------------------------\r\n\t\t; trivial rejection of triangle plane\r\n\t\t;------------------------------------\r\n\t\t\r\n\t\tSUB.w\t\tVF01,VF00,VF00\t\tIADDIU\t\tVI01,VI00,0x0FF0\r\n\t\tSUB.xyz\t\tVF20,VF03,VF01\t\tIBEQ\t\tVI10,VI00,ClipNext\t; reject if whole frustum is on '0' side of trianlge plane\r\n\t\tADD.xyz\t\tVF21,VF03,VF01\t\tIADDIU\t\tVI06,VI00,0\t\t\t; zero output vertex count\t\t\r\n\t\tSUB.xyz\t\tVF22,VF03,VF02\t\tIBEQ\t\tVI10,VI01,ClipNext\t; reject if whole frustum is on '1' side of triangle plane\r\n\t\tADD.xyz\t\tVF23,VF03,VF02\t\tIADD\t\tVI10,VI10,VI10\t\t; shift another 4 bits left\r\n\t\tADDx.xyz\tVF24,VF03,VF09x\t\tIADD\t\tVI10,VI10,VI10\r\n\t\tSUBAy.xyz\tACC,VF00,VF09y\t\tIADD\t\tVI10,VI10,VI10\r\n\t\tMSUBw.xyz\tVF25,VF03,VF00w\t\tIADD\t\tVI10,VI10,VI10\r\n\t\t\r\n\t\t;-------------------------------------------\r\n\t\t; initialise frustum in standard orientation\r\n\t\t;-------------------------------------------\r\n\t\t\r\n\t\t; VecSet(p[0],  w0-x0,  w1-x1,  w2-x2, 0),\tm[0] = 0x5501;\t; right\r\n\t\t; VecSet(p[1],  w0+x0,  w1+x1,  w2+x2, 0),\tm[1] = 0xAA02;\t; left\r\n\t\t; VecSet(p[2],  w0-y0,  w1-y1,  w2-y2, 0),\tm[2] = 0x3304;\t; bottom\r\n\t\t; VecSet(p[3],  w0+y0,  w1+y1,  w2+y2, 0),\tm[3] = 0xCC08;\t; top\r\n\t\t; VecSet(p[4],  w0+n ,  w1+n ,  w2+n , 0),\tm[4] = 0x0F10;\t; near\r\n\t\t; VecSet(p[5], -w0-f , -w1-f , -w2-f , 0),\tm[5] = 0xF020;\t; far\r\n\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x3F805501\r\n\t\tADDi.w\t\tVF20,VF01,I\t\t\tLOI\t\t\t0x3F80AA02\r\n\t\tADDi.w\t\tVF21,VF01,I\t\t\tLOI\t\t\t0x3F803304\r\n\t\tADDi.w\t\tVF22,VF01,I\t\t\tLOI\t\t\t0x3F80CC08\r\n\t\tADDi.w\t\tVF23,VF01,I\t\t\tLOI\t\t\t0x3F800F10\r\n\t\tADDi.w\t\tVF24,VF01,I\t\t\tLOI\t\t\t0x3F80F020\r\n\t\tADDi.w\t\tVF25,VF01,I\t\t\tISUBIU\t\tVI11,VI00,0x0100 \t; 0xFF00\r\n\t\t\r\n\r\n\r\n\t\t;------------------------------------------\r\n\t\t; put a straddling edge in the primary face\r\n\t\t;------------------------------------------\r\n\r\n\t\t; while (((c & m[j4])==0) || ((c & m[j4])==(0xFF00 & m[j4])))\r\n\t\t; {\r\n\t\t;\tjt=j2, j2=j5, j5=j3, j3=j4, j4=jt;\r\n\t\t; }\r\n\t\t\r\nWhileA:\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI07,VI10,VI08\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI11,VI08\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI07,VI00,RotateA\r\n\t\tADDx\t\tVF01,VF22,VF00x\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI07,EndWhileA\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\nRotateA:ADDx\t\tVF22,VF25,VF00x\t\tMTIR\t\tVI08,VF22w\r\n\t\tADDx\t\tVF25,VF23,VF00x\t\tB\t\t\tWhileA\r\n\t\tADDx\t\tVF23,VF24,VF00x\t\tMOVE\t\tVF24,VF01\r\nEndWhileA:\r\n\t\t\r\n\r\n\t\t;-------------------------------------------\r\n\t\t; rotate straddling edge into secondary face\r\n\t\t;-------------------------------------------\r\n\r\n\t\t; while ((c & m[j3] & m[j4]) != (m[j1] & m[j3] & m[j4]))\r\n\t\t; {\r\n\t\t;\tjt=j2, j2=j0, j0=j3, j3=j1, j1=jt;\r\n\t\t; }\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI07,VF23w\t\t\t; m[j3]\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI07,VI07,VI08\t\t; m[j3] & m[j4]\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI11,VF21w\t\t\t; m[j1]\r\n\r\nWhileB:\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI11,VI07\t\t; m[j1] & m[j3] & m[j4]\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI07,VI07,VI10\t\t; c & m[j3] & m[j4]\r\n\t\tADDx\t\tVF01,VF22,VF00x\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI07,VI01,EndWhileB\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI07,VI11,VI08\r\n\t\tADDx\t\tVF22,VF20,VF00x\t\tMTIR\t\tVI11,VF22w\r\n\t\tADDx\t\tVF20,VF23,VF00x\t\tB\t\t\tWhileB\r\n\t\tADDx\t\tVF23,VF21,VF00x\t\tMOVE\t\tVF21,VF01\r\nEndWhileB:\r\n\r\n\r\n\r\n\t\t;------------------------------------------------\r\n\t\t; roll the frustum classifier bits into the masks\r\n\t\t;------------------------------------------------\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI10,0xFF\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x4B400000\t\t\t; 2^23+2^22\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF20w\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF20,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF21w\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF21,VI01\r\n\t\tITOF0.w\t\tVF20,VF20\t\t\tMTIR\t\tVI01,VF22w\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF22,VI01\r\n\t\tITOF0.w\t\tVF21,VF21\t\t\tMTIR\t\tVI01,VF23w\r\n\t\tADDi.w\t\tVF20,VF20,I\t\t\tIAND\t\tVI01,VI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF23,VI01\r\n\t\tITOF0.w\t\tVF22,VF22\t\t\tMTIR\t\tVI01,VF24w\r\n\t\tADDi.w\t\tVF21,VF21,I\t\t\tIAND\t\tVI01,VI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF24,VI01\r\n\t\tITOF0.w\t\tVF23,VF23\t\t\tMTIR\t\tVI01,VF25w\r\n\t\tADDi.w\t\tVF22,VF22,I\t\t\tIAND\t\tVI01,VI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF25,VI01\r\n\t\tITOF0.w\t\tVF24,VF24\t\t\tNOP\r\n\t\tADDi.w\t\tVF23,VF23,I\t\t\tNOP\r\n\t\tITOF0.w\t\tVF25,VF25\t\t\tNOP\r\n\t\tADDi.w\t\tVF24,VF24,I\t\t\tNOP\r\n\t\tADDi.w\t\tVF25,VF25,I\t\t\tNOP\r\n\t\t\r\n\t\t\r\n\r\n\t\t;----------------------------------------------\r\n\t\t; classify initial straddling edge wrt triangle\r\n\t\t;----------------------------------------------\r\n\t\t\r\n\t\tOPMULA.xyz\tACC,VF23,VF24\t\tNOP\r\n\t\tOPMSUB.xyz\tVF31,VF24,VF23\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,0x00E0\t; Sxyz MAC flags\r\n\t\tNOP\t\t\t\t\t\t\t\tFMAND\t\tVI01,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF31,VI01\r\n\r\n\t\t; advance one face to fill the classification queue\r\n\t\tNOP\t\t\t\t\t\t\t\tBAL\t\t\tVI14,NextFrustumFace\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\n; ; GENERAL ALGORITHM\r\n;\r\n; ; mark our place in the triangle\r\n; vT0 = vT;\r\n;\r\n; ; are we starting at a triangle vertex inside the frustum?\r\n; if (vT inside F)\r\n;\tgoto vTinsideF;\r\n;\r\n; ; find the first edge of the frustum poly with respect to which which the triangle vertex is out\r\n; while (vT outside edge(vF,vF->next))\r\n;\tvF = vF->next;\r\n; while (vT inside edge(vF,vF->next))\r\n;\tvF = vF->next;\r\n;\r\n; ; mark our place in the frustum poly\r\n; vF0 = vF;\r\n;\r\n; ; find an intersection, or determine there isn't one and quit\r\n; while (1)\r\n; {\r\n;\twhile (vT->next outside edge(vF,vF->next))\r\n;\t\tvT = vT->next;\r\n;\r\n;\tdo\r\n;\t{\r\n;\t\tif ( vF        inside edge(vT,vT->next) &&\r\n;\t\t     vF->next outside edge(vT,vT->next) &&\r\n;\t\t     vT       outside edge(vF,vF->next))\r\n;\t\t    goto Intersection;\r\n;\t\tvF = vF->next;\r\n;\t\tif (vF == vF0)\r\n;\t\t\tgoto Reject;\r\n;\t}\r\n;\twhile (vT->next inside edge(vF,vF->next));\r\n; }\r\n;\r\n; Intersection:\r\n;\r\n; while (1)\r\n; {\r\n;\r\n;\tOutput(Intersection(edge(vF,vF->next), edge(vT,vT->next));\r\n;\r\n;\twhile (vT->next inside F)\r\n;\t{\r\n;\t\tvT = vT->next;\r\n;\t\tif (vT==vT0)\r\n;\t\t\tgoto Finish;\r\n; vTinsideF:\r\n;\t\tOutput(vT);\r\n;\t}\r\n;\r\n;\tdo {\r\n;\t\tvF = vF->next;\r\n;\t} while ((vF inside edge(vT,vT->next)) || (vF->next outside edge(vT,vT->next)));\r\n;\r\n;\tOutput(Intersection(edge(vT,vT->next), edge(vF,vF->next));\r\n;\r\n;\twhile (vF->next inside T)\r\n;\t{\r\n;\t\tvF = vF->next;\r\n;\t\tOutput(vF);\r\n;\t}\r\n;\r\n;\tdo {\r\n;\t\tvT = vT->next;\r\n;\t\tif (vT==vT0)\r\n;\t\t\tgoto Finish;\r\n;\t} while ((vT inside edge(vF,vF->next)) || (vT->next outside edge(vF,vF->next)));\r\n;\r\n; }\r\n;\r\n; Finish:\r\n\r\n\t\t; are we starting at an in-vertex?\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI07,VF26w\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI10,VI00,0x80\t\t; mark our place in the triangle\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI07,VI00,StartIn\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\t; find the first edge of the frustum poly with respect to which which the triangle vertex is out\r\nFindEdge1:\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF23w\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI07\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,NextFrustumFace\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI14,VI00,FindEdge1\r\n\r\nFindEdge2:\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF23w\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI07\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI01,VI00,NextFrustumFace\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI14,VI00,FindEdge2\r\n\r\n\t\t; mark our place in the frustum poly\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI11,VF23w\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI07,VF23w\r\n\r\n\t\t; find an intersection, or determine there isn't one and quit\r\nFindIntersection:\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI08,VF27w\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI08,VI07\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,NextTriangleVertex\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI14,VI00,FindIntersection\r\n\r\nWhile3:\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF26w\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI07\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI07,VF31w\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI01,VI00,NoIntersectionYet\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF30w\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI07,VI07,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI01,VI07\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBLTZ\t\tVI01,While4\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\nNoIntersectionYet:\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tBAL\t\t\tVI14,NextFrustumFace\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI07,VF23w\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI08,VI07\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI07,VI11,ClipNext\t; reject\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,FindIntersection\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tWhile3\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nWhile4:\t; output entering intersection\r\n\t\tNOP\t\t\t\t\t\t\t\tBAL\t\t\tVI14,OutputType2\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\t; output any vertices of triangle inside frustum\r\nOutputTriVerts:\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF27w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,EndOutputTriVerts\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tBAL\t\t\tVI14,NextTriangleVertex\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\nStartIn:NOP\t\t\t\t\t\t\t\tB\t\t\tOutputType1\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI14,VI00,OutputTriVerts\r\nEndOutputTriVerts:\r\n\r\n\t\t; traverse frustum poly to find leaving intersection\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF31w\r\n\t\t\r\nFindLeavingIntersection:\r\n\t\tNOP\t\t\t\t\t\t\t\tBAL\t\t\tVI14,NextFrustumFace\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI07,VI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI09,VI07,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBLEZ\t\tVI09,FindLeavingIntersection\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; output leaving intersection\r\n\t\tNOP\t\t\t\t\t\t\t\tBAL\t\t\tVI14,OutputType2\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF31w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; output any vertices of frustum poly inside triangle\r\nOutputFrustumVerts:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,EndOutputFrustumVerts\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tBAL\t\t\tVI14,OutputType3\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextFrustumFace\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI14,VI00,OutputFrustumVerts\r\nEndOutputFrustumVerts:\r\n\r\n\t\t; traverse triangle to find entering intersection\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI09,VF23w\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI07,VF27w\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI07,VI07,VI09\r\n\r\nFindEnteringIntersection:\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI07,0\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI07,VF28w\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI07,VI07,VI09\r\n\t\tNOP\t\t\t\t\t\t\t\tBAL\t\t\tVI14,NextTriangleVertex\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI01,VI07\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIBLEZ\t\tVI01,FindEnteringIntersection\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tWhile4\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\n\r\n\t\t;------------------------------------\r\n\t\t; classify triangle vertex subroutine\r\n\t\t;------------------------------------\r\n\t\t\r\n\t\t\r\n\t\t; classify a triangle vertex with respect to the 6 planes of the frustum\r\n\t\t; this info could possibly be retained from pass 1\r\n\t\t\r\nClassifyTriangleVertex:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,0x0010\t; Sw MAC flag\r\n\t\tCLIPw.xyz\tVF01,VF01w\t\t\tFMAND\t\tVI01,VI01\r\n\t\tCLIPw.xyz\tVF02,VF01w\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI07,VI00,0x003F\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI01,VI00,wPos\r\n\t\tNOP\t\t\t\t\t\t\t\tFCGET\t\tVI01\r\n\t\tNOP\t\t\t\t\t\t\t\tFCGET\t\tVI01\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI07,VI01\r\nwPos:\tNOP\t\t\t\t\t\t\t\tJR\t\t\tVI14\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI07\r\n\t\t\r\n\r\n\t\t;--------------------------------\r\n\t\t; next triangle vertex subroutine\r\n\t\t;--------------------------------\r\n\r\n;NextTriangleVertex()\r\n;{\r\n;\tit=i0, i0=i1, i1=i2, i2=it;\r\n;}\r\n\r\nNextTriangleVertex:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI10,VI10,0x30\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF01,VF26\r\n\t\tNOP\t\t\t\t\t\t\t\tIBLTZ\t\tVI10,ProcessFan\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF26,VF27\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF27,VF28\r\n\t\tNOP\t\t\t\t\t\t\t\tJR\t\t\tVI14\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE\t\tVF28,VF01\r\n\t\t\r\n\r\n\t\t;-----------------------------\r\n\t\t; next frustum face subroutine\r\n\t\t;-----------------------------\r\n\t\t\r\n\r\n;   1---------0\r\n;   |\\   3   /|\r\n;   | *-----* |\r\n;   | | (5) | |\r\n;   |1|  4  |0|\r\n;   | |     | |\r\n;   | *-----* |\r\n;   |/   2   \\|\r\n;   *---------*\r\n;\r\n;NextFrustumFace()\r\n;{\r\n;\t; advance edge classification queue\r\n;\te0 = e1;\r\n;\r\n;\t; rotate frustum in 1 of 3 ways\r\n;\tjt=j3, j3=j4;\r\n;\tif (m[j4] & m[j0])\r\n;\t\tj4=j0, j0=jt, jt=j1, j1=j2;\r\n;\telse if (m[j4] & m[j2])\r\n;\t\tj4=j2;\r\n;\telse\r\n;\t\tj4=j1, j1=jt, jt=j0, j0=j2;\r\n;\tj2=j5, j5=jt;\r\n;\r\n;\t; classify new straddling edge wrt triangle\r\n;\tCrossProduct(e1, p[j2], p[j4]);\r\n;}\r\n\r\n\r\nNextFrustumFace:\r\n\r\n\t\tADDx\t\tVF01,VF23,VF00x\t\tMTIR\t\tVI09,VF24w\r\n\t\tADDx\t\tVF23,VF24,VF00x\t\tMTIR\t\tVI01,VF20w\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI09,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE.w\t\tVF30,VF31\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI01,VI00,NFF1\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI01,VF22w\r\n\t\t\r\n\t\tOPMULA.xyz\tACC,VF23,VF20\t\tMOVE\t\tVF24,VF20\r\n\t\tOPMSUB.xyz\tVF31,VF20,VF23\t\tMOVE\t\tVF20,VF01\r\n\t\tADDx\t\tVF01,VF21,VF00x\t\tB\t\t\tNFF3\r\n\t\tADDx\t\tVF21,VF22,VF00x\t\tIADDIU\t\tVI01,VI00,0x00E0\t; Sxyz MAC flags\r\n\r\nNFF1:\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI09,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,NFF2\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,0x00E0\t; Sxyz MAC flags\r\n\r\n\t\tOPMULA.xyz\tACC,VF23,VF21\t\tMOVE\t\tVF24,VF21\r\n\t\tOPMSUB.xyz\tVF31,VF21,VF23\t\tMOVE\t\tVF21,VF01\r\n\t\tADDx\t\tVF01,VF20,VF00x\t\tB\t\t\tNFF3\r\n\t\tADDx\t\tVF20,VF22,VF00x\t\tNOP\r\n\r\nNFF2:\tOPMULA.xyz\tACC,VF23,VF22\t\tMOVE\t\tVF24,VF22\r\n\t\tOPMSUB.xyz\tVF31,VF22,VF23\t\tNOP\r\n\r\nNFF3:\tADDx\t\tVF00,VF31,VF00x\t\tFMAND\t\tVI01,VI01\r\n\t\tADDx\t\tVF22,VF25,VF00x\t\tJR\t\t\tVI14\r\n\t\tADDx\t\tVF25,VF01,VF00x\t\tMFIR.w\t\tVF31,VI01\r\n\r\n\r\n\t\t;--------------------------\r\n\t\t; vertex output subroutines\r\n\t\t;--------------------------\r\n\r\n\r\nOutputWeightsFromAcc:\r\n\r\n\t\tMADDx\t\tVF01,VF00,VF00x\t\tNOP\r\n\r\nOutputWeights:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI06,VI06,1\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI03,3\r\n\t\tNOP\t\t\t\t\t\t\t\tJR\t\t\tVI14\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF01,-2(VI03)\r\n\t\t\r\n\r\n\r\n\r\nOutputType1:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI01,VI10,0x50\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDw.y\t\tVF01,VF00,VF00w\t\tIBEQ\t\tVI01,VI00,OutputWeights\r\n\t\tADDx.xzw\tVF01,VF00,VF00x\t\tNOP\t\t\t\t\t\t\t\t; case i0=1 : VF01 = (0,1,0,1)\r\n\t\tADDw.z\t\tVF01,VF00,VF00w\t\tIBLTZ\t\tVI01,OutputWeights\r\n\t\tADDx.xyw\tVF01,VF00,VF00x\t\tNOP\t\t\t\t\t\t\t\t; case i0=2 : VF01 = (0,0,1,1)\r\n\t\tADDw.x\t\tVF01,VF00,VF00w\t\tB\t\t\tOutputWeights\r\n\t\tADDx.yzw\tVF01,VF00,VF00x\t\tNOP\t\t\t\t\t\t\t\t; case i0=0 : VF01 = (1,0,0,1)\r\n\r\n\r\n\r\n\r\n;OutputIntersectionType2(Vec x[3])\r\n;{\r\n;\t; x = ((a0.p)x1-(a1.p)x0)/(x0-x1).p\r\n;\tVec Result;\r\n;\tVecWeightedMean2(Result, -p[j4][i1], x[i0], p[j4][i0], x[i1]);\r\n;\tOutput(Result,&pClippedPoly);\r\n;}\r\n\r\nOutputType2:\r\n\r\n\t\tADDw.xyz\tVF01,VF00,VF00w\t\tISUBIU\t\tVI01,VI10,0x50\t\t; VF01 = (1,1,1,?)\r\n\t\tNOP\t\t\t\t\t\t\t\tMOVE.w\t\tVF01,VF00\t\t\t; VF01 = (1,1,1,1)\r\n\t\tSUBA\t\tACC,VF00,VF00\t\tIBEQ\t\tVI01,VI00,Type2B\t; ACC  = (0,0,0,0)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBLTZ\t\tVI01,Type2C\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\nType2A:\tMADDAy.yw\tACC,VF01,VF23y\t\tB\t\t\tOutputWeightsFromAcc; ACC  = (0,VF23y,0,VF23y)\r\n\t\tMSUBAz.xw\tACC,VF01,VF23z\t\tNOP\t\t\t\t\t\t\t\t; ACC  = (-VF23z,VF23y,0,VF23y-VF23z)\r\n\t\t\r\nType2B:\tMADDAz.zw\tACC,VF01,VF23z\t\tB\t\t\tOutputWeightsFromAcc; ACC  = (0,0,VF23z,VF23z)\r\n\t\tMSUBAx.yw\tACC,VF01,VF23x\t\tNOP\t\t\t\t\t\t\t\t; ACC  = (0,-VF23x,VF23z,VF23z-VF23x)\r\n\t\t\r\nType2C:\tMADDAx.xw\tACC,VF01,VF23x\t\tB\t\t\tOutputWeightsFromAcc; ACC  = (VF23x,0,0,VF23x)\r\n\t\tMSUBAy.zw\tACC,VF01,VF23y\t\tNOP\t\t\t\t\t\t\t\t; ACC  = (VF23x,0,-VF23y,VF23x-VF23y)\r\n\r\n\r\n\r\nOutputType3:\r\n\t\t\r\n\t\tMULAx.w\t\tACC,VF00,VF31x\t\tMR32.xy\t\tVF01,VF31\r\n\t\tMADDAy.w\tACC,VF00,VF31y\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\tMADDz.w\t\tVF01,VF00,VF31z\t\tB\t\t\tOutputWeights\r\n\t\tADDx.z\t\tVF01,VF00,VF31x\t\tNOP\t\t\t\t\t\t\t\t; VF01 = (VF31y, VF31z, VF31x, VF31x+VF31y+VF31z)\r\n\t\t\r\n\r\n\r\n\r\n\r\nProcessFan:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI06,VI00,ClipNext\t; if nothing was output, just forget it\r\n\t\tNOP\t\t\t\t\t\t\t\tILW.y\t\tVI08,0(VI13)\r\n\r\n\t\t; get colours and texcoords from the source triangle\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI10,VI01,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI11,VI10,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF23,-2(VI10)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF24,-2(VI01)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF25,-2(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF20,0(VI11)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF21,0(VI10)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF22,0(VI01)\r\n\t\t\r\n\t\t; convert rgba to float and test for reflection mapping\r\n\t\tITOF0\t\tVF23,VF23\t\t\tISUBIU\t\tVI10,VI08,Refl\r\n\t\tITOF0\t\tVF24,VF24\t\t\tIADDIU\t\tVI01,VI00,0x0FF\r\n\t\tITOF0\t\tVF25,VF25\t\t\tIAND\t\tVI01,VI10,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tXITOP\t\tVI11\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI01,VI00,NoConvST\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,SHDW\r\n\t\t\r\n\t\t; convert st to float and supplement with 1, and check whether it's a shadow projection\r\n\t\tITOF12.xy\tVF20,VF20\t\t\tIAND\t\tVI01,VI01,VI11\r\n\t\tITOF12.xy\tVF21,VF21\t\t\tMR32.z\t\tVF20,VF00\r\n\t\tITOF12.xy\tVF22,VF22\t\t\tIBNE\t\tVI01,VI00,ClampedInUV\r\n\t\tADDw.z\t\tVF21,VF00,VF00w\t\tMR32.z\t\tVF22,VF00\r\n\t\t\r\n\r\n\t\t; reduce texture coordinates...\r\n\t\t\r\n\t\t; get u-clamp flag and start floating point calculation on both coords\r\n\t\tADDw.xy\t\tVF01,VF00,VF00w\t\tLOI\t\t\t-0.33333333\r\n\t\tMULAi.xy\tACC,VF20,I\t\t\tIADDIU\t\tVI01,VI00,0x1000\r\n\t\tMADDAi.xy\tACC,VF21,I\t\t\tIAND\t\tVI01,VI08,VI01\r\n\t\tMADDAi.xy\tACC,VF22,I\t\t\tLOI\t\t\t0xCB400000\t; -2^23-2^22\r\n\t\tMADDAi.xy\tACC,VF01,I\t\t\tIBNE\t\tVI01,VI00,ClampedInU\r\n\t\tMSUBAi.xy\tACC,VF01,I          IADDIU\t\tVI01,VI00,0x2000\r\n\t\t\r\n\t\t; reduce texture coords in s\r\n\t\tMADDw.x\t\tVF20,VF20,VF00w\t\tNOP\r\n\t\tMADDw.x\t\tVF21,VF21,VF00w\t\tNOP\r\n\t\tMADDw.x\t\tVF22,VF22,VF00w\t\tNOP\r\n\t\t\r\nClampedInU:\r\n\r\n\t\t; get v-clamp flag\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI08,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,ClampedInV\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; reduce texture coords in t\r\n\t\tMADDw.y\t\tVF20,VF20,VF00w\t\tNOP\r\n\t\tMADDw.y\t\tVF21,VF21,VF00w\t\tNOP\r\n\t\tMADDw.y\t\tVF22,VF22,VF00w\t\tNOP\r\n\t\t\r\nClampedInV:\r\nClampedInUV:\r\nNoConvST:\r\n\r\n\r\n\t\t; get giftag and replace NLOOP, NREG and PRIM fields\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.y\t\tVF01,0(VI13)\t\t\t\t\t\t\t\t\t\t\t; VF01y = NREG:FLG:PRIM:PRE:000\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x53400000\t\t\t\t\t\t\t\t\t\t\t\t; 2^39+2^38\r\n\t\tADDi.y\t\tVF03,VF00,I\t\t\tLOI\t\t\t196616\t\t\t\t\t\t\t\t\t\t\t\t\t; 3*2^16+8\r\n\t\tADDi.y\t\tVF04,VF00,I\t\t\tLOI\t\t\t0x3F800412\t\t\t; XYZ2:RGBA:STQ\r\n\t\tITOF12.y\tVF01,VF01\t\t\tIADDIU\t\tVI11,VI08,0\t\t\t; VF01y = float(NREG:FLG:PRIM:PRE)\t; save GIFTAGy\r\n\t\tSUBA.y\t\tACC,VF03,VF01\t\tIADDIU\t\tVI08,VI03,0\t\t\t; ACCy = 2^39+2^38-float(NREG)\t\t; end pointer\r\n\t\tMSUBAw.y\tACC,VF03,VF00w\t\tIADD\t\tVI01,VI06,VI06\t\t; ACCy = -float(NREG)\t\t\t\t; 2 * vertex count\r\n\t\tMADDAw.y\tACC,VF01,VF00w\t\tIADD\t\tVI01,VI01,VI06\t\t; ACCy = float(FLG:PRIM:PRE)\t\t; 3 * vertex count\r\n\t\tMADDw.y\t\tVF01,VF04,VF00w\t\tISUB\t\tVI03,VI03,VI01\t\t; VF01y = float(3:FLG:fanPRIM:PRE)\t; address of giftag\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.x\t\tVF01,VI06\t\t\t; EOP:NLOOP\r\n\t\tADDi.z\t\tVF01,VF00,I\t\t\tNOP\r\n\t\tFTOI12.y\tVF01,VF01\t\t\tNOP\t\t\t\t\t\t\t\t; VF01y = 3:FLG:fanPRIM:PRE:000\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF01,0(VI03)\r\n\t\t\r\n\t\t\r\n\t\t;------------------------------------------------------------------------\r\n\t\t; reorder the colours and texcoords\r\n\t\t.if 1\r\n\t\t\r\n\t\t; retrieve the swap flags\r\n\t\tNOP\t\t\t\t\t\t\t\tMTIR\t\tVI10,VF30x\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,1\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI10\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI07,VI00,2\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI01,VI00,NoSwap3\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI07,VI07,VI10\r\n\t\t\r\n\t\tADDx\t\tVF23,VF24,VF00x\t\tMOVE\t\tVF24,VF23\r\n\t\tADDx\t\tVF20,VF21,VF00x\t\tMOVE\t\tVF21,VF20\r\nNoSwap3:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,4\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI07,VI00,NoSwap4\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI01,VI10\r\n\t\t\r\n\t\tADDx\t\tVF23,VF25,VF00x\t\tMOVE\t\tVF25,VF23\r\n\t\tADDx\t\tVF20,VF22,VF00x\t\tMOVE\t\tVF22,VF20\r\nNoSwap4:\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI01,VI00,NoSwap5\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\tADDx\t\tVF24,VF25,VF00x\t\tMOVE\t\tVF25,VF24\r\n\t\tADDx\t\tVF21,VF22,VF00x\t\tMOVE\t\tVF22,VF21\r\nNoSwap5:\r\n\t\t\r\n\t\t.endif\r\n\t\t;------------------------------------------------------------------------\r\n\t\t\r\n\t\t; prepare reflection-map test\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI11,VI10,Refl\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,0x0FF\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI11,VI11,VI01\r\n\t\t\r\n\t\t; fog setup\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF10w\r\n\t\tADDq.x\t\tVF08,VF00,Q\t\t\tWAITQ\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t0x45000FFF\r\n\t\tADDi.y\t\tVF08,VF00,I\t\t\tNOP\t\t\t\t\t\t\t\t; VF08y = 2^11 + 1 - 2^-12\r\n\t\tSUBq.y\t\tVF08,VF08,Q\t\t\tNOP\t\t\t\t\t\t\t\t; VF08y = 2^11 + 1-f0 - 2^-12\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.w\t\tVF01,-8(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tMR32.z\t\tVF08,VF01\t\t\t; VF08 = FogNear\r\n\t\t\r\nFanLoop:\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF04,1(VI03)\r\n\t\t\r\n\t\tMULz.w\t\tVF08,VF04,VF08z\t\tNOP\r\n\t\t\r\n\t\tMULAx\t\tACC,VF05,VF04x\t\tERCPR\t\tP,VF04w\r\n\t\tMADDAy\t\tACC,VF06,VF04y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF07,VF04z\t\tIADDIU\t\tVI01,VI00,0x0010\t; Sw FMAC flag\r\n\t\t\r\n\t\tMULAx\t\tACC,VF23,VF04x\t\tFMAND\t\tVI01,VI01\r\n\t\tMADDAy\t\tACC,VF24,VF04y\t\tNOP\r\n\t\tMADDz\t\tVF02,VF25,VF04z\t\tDIV\t\t\tQ,VF08x,VF03w\r\n\t\t\r\n\t\tMULAx.xyz\tACC,VF20,VF04x\t\tNOP\r\n\t\tMADDAy.xyz\tACC,VF21,VF04y\t\tNOP\r\n\t\tMADDz.xyz\tVF01,VF22,VF04z\t\tLOI\t\t\t1.0039\t\t\t\t; fudgefactor to compensate for RGBA rounding error\r\n\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,NonStandard\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\tMINI.w\t\tVF03,VF03,VF08\t\tNOP\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tStandard\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\nNonStandard:\r\n\r\n\t\tMAX.w\t\tVF03,VF03,VF08\t\tNOP\r\n\r\n\r\nStandard:\r\n\r\n\t\tMULi\t\tVF02,VF02,I\t\t\tNOP\r\n\t\tMULAy\t\tACC,VF00,VF08y\t\tNOP\r\n\t\tMADDq.xyzw\tVF03,VF03,Q\t\t\tWAITQ\r\n\r\n\t\t\r\n\t\t\r\n\t\t; test for reflection mapping\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI11,VI00,StandardDivST\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t8388608\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF01z\r\n\t\tNOP\t\t\t\t\t\t\t\tWAITQ\r\n\t\t\r\nStandardDivST:\r\n\t\tMULq.xyz\tVF01,VF01,Q\t\t\tNOP\r\n\t\tFTOI4.xyz\tVF03,VF03\t\t\tWAITP\r\n\t\tADDAi.xyz\tACC,VF00,I\t\t\tMFP.w\t\tVF04,P\r\n\t\tMULAi.w\t\tACC,VF00,I\t\t\tIADDIU\t\tVI03,VI03,3\r\n\t\tMADDw\t\tVF02,VF02,VF04w\t\tSQ.xyz\t\tVF01,-2(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF03,0(VI03)\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI03,VI08,FanLoop\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF02,-1(VI03)\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI03,1\t\t\t; add 1 for giftag\r\n\r\n\r\n\t\t; temporary overflow check\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI01,VI03,VI12\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI01,VI01,263\t\t; MAX_VU1_BUFFER - # saved regs - 25\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBGEZ\t\tVI01,KickFans\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\t\t\r\n\t\t; go back for next triangle\r\nClipNext:\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI01,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,ClipLoop\r\n\t\tNOP\t\t\t\t\t\t\t\tILW.w\t\tVI01,-1(VI01)\r\n\t\t\r\n\r\nKickFans:\r\n\t\t; add a terminal giftag\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI03,VI12,PostClip\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,0x4000\r\n\t\tNOP\t\t\t\t\t\t\t\tISW.x\t\tVI01,0(VI03)\r\n\t\t\r\n\t\t; kick the fan buffer\r\n\t\tNOP\t\t\t\t\t\t\t\tXGKICK\t\tVI12\r\n\t\t\r\n\t\t; are there any more source triangles?\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,PostClip\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; stall VU till fan buffer is free\r\n\t\tNOP\t\t\t\t\t\t\t\tXGKICK\t\tVI03\r\n\t\t\r\n\t\t; reset output pointer and go back for more\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI12,0\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tClipNext\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\nPostClip:\r\n\t\t; restore some registers\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF20,-12(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF21,-11(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF22,-10(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF23,-9(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF24,-8(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF25,-7(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF26,-6(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF27,-5(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF28,-4(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF29,-3(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF30,-2(VI12)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF31,-1(VI12)\r\n\t\t\r\n\t\t; get renderer address\r\n\t\tNOP\t\t\t\t\t\t\t\tILW.w\t\tVI01,0(VI13)\r\n\t\t\r\n\t\t; reset pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI02,VI13,1\r\n\t\t\r\n\t\t; restore render flags\r\n\t\tNOP\t\t\t\t\t\t\t\tXITOP\t\tVI14\r\n\t\t\r\n\t\t; jump to postclip pass\r\n\t\tNOP\t\t\t\t\t\t\t\tJR\t\t\tVI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\r\n\r\n\r\n\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\n\r\n; -------------\r\n; PARTICLE CODE\r\n; -------------\r\n\r\n\r\nSprites:\r\n\r\n\t\t.if 0\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI03,VI02,0\r\n\t\tNOP\t\t\t\t\t\t\t\tMR32.xyz\tVF08,VF00\t\t\t; upper left texcoords (0,0,1)\r\n\t\tADDw.xyz\tVF29,VF00,VF00w\t\tNOP\t\t\t\t\t\t\t\t; lower right texcoords (1,1,1)\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF05,VI00\t\t\t; clear adc bit\r\n\t\t\r\nSpriteLoop:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\t\t; step source pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,-1(VI03)\t\t; get vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\t\t\t\t\t\t\t\t; row 3 view transform\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tNOP\t\t\t\t\t\t\t\t; row 1 view transform\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tNOP\t\t\t\t\t\t\t\t; row 2 view transform\r\n\t\tMULw.xyz\tVF03,VF30,VF01w\t\tNOP\t\t\t\t\t\t\t\t; viewport scale time size parameter\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF02w\t\t; calc 1/w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULAq.xyz\tACC,VF02,Q\t\t\tNOP\t\t\t\t\t\t\t\t; homogeneous div\r\n\t\tMSUBq.xyz\tVF04,VF03,Q\t\t\tNOP\t\t\t\t\t\t\t\t; calc upper left vertex\r\n\t\tMADDq.xyz\tVF05,VF03,Q\t\t\tNOP\t\t\t\t\t\t\t\t; calc lower right vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF29,1(VI02)\t\t; store lower right texcoords\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF04,0(VI02)\t\t; store upper left vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\t\t; step destination pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF05,-1(VI02)\t\t; store lower right vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,SpriteDone; break\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI03,VI03,VI04\t\t; step source pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,-1(VI03)\t\t; get vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\t\t\t\t\t\t\t\t; row 3 view transform\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tNOP\t\t\t\t\t\t\t\t; row 1 view transform\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tNOP\t\t\t\t\t\t\t\t; row 2 view transform\r\n\t\tMULw.xyz\tVF03,VF30,VF01w\t\tNOP\t\t\t\t\t\t\t\t; viewport scale time size parameter\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,VF00w,VF02w\t\t; calc 1/w\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULAq.xyz\tACC,VF02,Q\t\t\tNOP\t\t\t\t\t\t\t\t; homogeneous div\r\n\t\tMADDq.xyz\tVF04,VF03,Q\t\t\tNOP\t\t\t\t\t\t\t\t; calc lower right vertex\r\n\t\tMSUBq.xyz\tVF05,VF03,Q\t\t\tNOP\t\t\t\t\t\t\t\t; calc upper left vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF08,1(VI02)\t\t; store upper left texcoords\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF04,0(VI02)\t\t; store lower right vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\t\t; step destination pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF05,-1(VI02)\t\t; store upper left vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,SpriteLoop; loop\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t\r\nSpriteDone:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; prefetch next tag\r\n\r\n\r\n\t\t.else\r\n\t\t\r\n\t\t; optimised version\r\n\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ\t\t\tVF03,3(VI02)\r\n\t\tMADDAx\t\tACC,VF12,VF03x\t\tLQ\t\t\tVF01,7(VI02)\r\n\t\tMADDAy\t\tACC,VF13,VF03y\t\tNOP\r\n\t\tMADDz\t\tVF02,VF14,VF03z\t\tNOP\r\n\t\tMULw.xyz\tVF04,VF30,VF03w\t\tDIV\t\t\tQ,VF00w,VF02w\r\n\t\tADDw.xyz\tVF29,VF00,VF00w\t\tMR32.xyz\tVF08,VF00\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tMFIR.w\t\tVF04,VI00\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tMFIR.w\t\tVF05,VI00\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tNOP\r\n\t\tMADDz\t\tVF03,VF14,VF01z\t\tNOP\r\n\t\t\r\nSpriteLoop:\r\n\t\t\r\n\t\tMULw.xyz\tVF05,VF30,VF01w\t\tNOP\r\n\t\tMULAq.xyz\tACC,VF02,Q\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tMADDq.xyz\tVF02,VF04,Q\t\t\tLQ\t\t\tVF01,7(VI02)\r\n\t\tMSUBq.xyz\tVF04,VF04,Q\t\t\tDIV\t\t\tQ,VF00w,VF03w\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF29,-3(VI02)\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tSQ\t\t\tVF02,-4(VI02)\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIBEQ\t\tVI02,VI05,SpriteDone\r\n\t\tMADDz\t\tVF02,VF14,VF01z\t\tSQ\t\t\tVF04,-1(VI02)\r\n\r\n\r\n\t\tMULw.xyz\tVF04,VF30,VF01w\t\tNOP\r\n\t\tMULAq.xyz\tACC,VF03,Q\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tMSUBq.xyz\tVF03,VF05,Q\t\t\tLQ\t\t\tVF01,-1(VI02)\r\n\t\tMADDq.xyz\tVF05,VF05,Q\t\t\tDIV\t\t\tQ,VF00w,VF02w\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF08,-3(VI02)\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tSQ\t\t\tVF03,-4(VI02)\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tIBNE\t\tVI02,VI05,SpriteLoop\r\n\t\tMADDz\t\tVF03,VF14,VF01z\t\tSQ\t\t\tVF05,-1(VI02)\r\n\t\t\r\nSpriteDone:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; prefetch next tag\r\n\r\n\r\n\t\t.endif\r\n\r\n\r\n\r\n\r\n\r\nSpriteCull:\r\n\r\n\t\t.if 0\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tMR32.xyz\tVF08,VF00\t\t\t; upper left texcoords (0,0,1)\r\n\t\tADDw.xyz\tVF29,VF00,VF00w\t\tNOP\t\t\t\t\t\t\t\t; lower right texcoords (1,1,1)\r\n\t\t\r\nSpriteCullLoop:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,-1(VI02)\t\t; get xyzr\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\t\t\t\t\t\t\t\t; row 3 view transform\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tNOP\t\t\t\t\t\t\t\t; row 1 view transform\r\n\t\tMADDAz\t\tACC,VF14,VF01z\t\tNOP\t\t\t\t\t\t\t\t; row 2 view transform\r\n\t\tMSUBw\t\tVF02,VF31,VF01w\t\tNOP\t\t\t\t\t\t\t\t; 1st vertex frustum coords\r\n\t\tMADDw\t\tVF03,VF31,VF01w\t\tNOP\t\t\t\t\t\t\t\t; 2nd vertex frustum coords\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULAw\t\tACC,VF11,VF02w\t\tDIV\t\t\tQ,VF00w,VF02w\r\n\t\tMADD\t\tVF04,VF10,VF02\t\tNOP\t\t\t\t\t\t\t\t; apply viewport scale to 1st vertex\r\n\t\tMADD\t\tVF05,VF10,VF03\t\tNOP\t\t\t\t\t\t\t\t; apply viewport scale to 2nd vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF04xyz,VF04w\t\tNOP\r\n\t\tCLIPw.xyz\tVF05xyz,VF05w\t\tNOP\r\n\t\tMULq.xyz\tVF02,VF02,Q\t\t\tNOP\r\n\t\tMULq.xyz\tVF03,VF03,Q\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF29,-3(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x000FFF\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,0x7FFF\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF03,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF02,-4(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBEQ\t\tVI02,VI05,SpriteCullDone\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF03,-1(VI02)\r\n\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tVF01,-1(VI02)\t\t; get xyzr\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tNOP\t\t\t\t\t\t\t\t; row 3 view transform\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\t\t\t\t\t\t\t\t; row 0 view transform\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tNOP\t\t\t\t\t\t\t\t; row 1 view transform\r\n\t\tMADDAz\t\tACC,VF14,VF01z\t\tNOP\t\t\t\t\t\t\t\t; row 2 view transform\r\n\t\tMADDw\t\tVF02,VF31,VF01w\t\tNOP\t\t\t\t\t\t\t\t; 1st vertex frustum coords\r\n\t\tMSUBw\t\tVF03,VF31,VF01w\t\tNOP\t\t\t\t\t\t\t\t; 2nd vertex frustum coords\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMULAw\t\tACC,VF11,VF02w\t\tDIV\t\t\tQ,VF00w,VF02w\r\n\t\tMADD\t\tVF04,VF10,VF02\t\tNOP\t\t\t\t\t\t\t\t; apply viewport scale to 1st vertex\r\n\t\tMADD\t\tVF05,VF10,VF03\t\tNOP\t\t\t\t\t\t\t\t; apply viewport scale to 2nd vertex\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tCLIPw.xyz\tVF04xyz,VF04w\t\tNOP\r\n\t\tCLIPw.xyz\tVF05xyz,VF05w\t\tNOP\r\n\t\tMULq.xyz\tVF02,VF02,Q\t\t\tNOP\r\n\t\tMULq.xyz\tVF03,VF03,Q\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF08,-3(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x000FFF\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,0x7FFF\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\tVF03,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF02,-4(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,SpriteCullLoop\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\tVF03,-1(VI02)\r\n\r\nSpriteCullDone:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; prefetch next tag\r\n\r\n\r\n\t\t.else\r\n\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tLQ\t\t\tVF01,3(VI02)\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tMR32.z\t\tVF29,VF00\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tMR32.xyz\tVF08,VF00\r\n\t\tMADDAz\t\tACC,VF14,VF01z\t\tNOP\r\n\t\tMADDw\t\tVF02,VF31,VF01w\t\tNOP\r\n\t\tMSUBw\t\tVF03,VF31,VF01w\t\tMR32.y\t\tVF29,VF29\r\n\t\tMULAw\t\tACC,VF11,VF02w\t\tLQ\t\t\tVF01,7(VI02)\r\n\t\tMADD\t\tVF06,VF10,VF02\t\tDIV\t\t\tQ,VF00w,VF02w\r\n\t\tMADD\t\tVF07,VF10,VF03\t\tNOP\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tMR32.x\t\tVF29,VF29\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tNOP\r\n\r\nSpriteCullLoop:\r\n\r\n\t\tCLIPw.xyz\tVF06xyz,VF06w\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tCLIPw.xyz\tVF07xyz,VF07w\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF14,VF01z\t\tSQ.xyz\t\tVF29,-3(VI02)\r\n\t\tMSUBw\t\tVF04,VF31,VF01w\t\tNOP\r\n\t\tMADDw\t\tVF05,VF31,VF01w\t\tFCAND\t\tVI01,0x000FFF\r\n\t\tMULq.xyz\tVF02,VF02,Q\t\t\tIADDIU\t\tVI01,VI01,0x7FFF\r\n\t\tMULq.xyz\tVF03,VF03,Q\t\t\tLQ\t\t\tVF01,7(VI02)\r\n\t\tMULAw\t\tACC,VF11,VF04w\t\tMFIR.w\t\tVF03,VI01\r\n\t\tMADD\t\tVF06,VF10,VF04\t\tDIV\t\t\tQ,VF00w,VF04w\r\n\t\tMADD\t\tVF07,VF10,VF05\t\tSQ\t\t\tVF02,-4(VI02)\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tIBEQ\t\tVI02,VI05,SpriteCullDone\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tSQ\t\t\tVF03,-1(VI02)\r\n\r\n\r\n\t\tCLIPw.xyz\tVF06xyz,VF06w\t\tIADD\t\tVI02,VI02,VI04\r\n\t\tCLIPw.xyz\tVF07xyz,VF07w\t\tNOP\r\n\t\tMADDAy\t\tACC,VF13,VF01y\t\tNOP\r\n\t\tMADDAz\t\tACC,VF14,VF01z\t\tSQ.xyz\t\tVF08,-3(VI02)\r\n\t\tMADDw\t\tVF02,VF31,VF01w\t\tNOP\r\n\t\tMSUBw\t\tVF03,VF31,VF01w\t\tFCAND\t\tVI01,0x000FFF\r\n\t\tMULq.xyz\tVF04,VF04,Q\t\t\tIADDIU\t\tVI01,VI01,0x7FFF\r\n\t\tMULq.xyz\tVF05,VF05,Q\t\t\tLQ\t\t\tVF01,7(VI02)\r\n\t\tMULAw\t\tACC,VF11,VF02w\t\tMFIR.w\t\tVF05,VI01\r\n\t\tMADD\t\tVF06,VF10,VF02\t\tDIV\t\t\tQ,VF00w,VF02w\r\n\t\tMADD\t\tVF07,VF10,VF03\t\tSQ\t\t\tVF04,-4(VI02)\r\n\t\tADDAx\t\tACC,VF15,VF00x\t\tIBNE\t\tVI02,VI05,SpriteCullLoop\r\n\t\tMADDAx\t\tACC,VF12,VF01x\t\tSQ\t\t\tVF05,-1(VI02)\r\n\r\nSpriteCullDone:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\t\t\t; go back for next prim\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tVF01,(VI02++)\t\t; prefetch next tag\r\n\r\n\t\t.endif\r\n\t\t\r\n\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\n; ------------------\r\n; VU1 BILLBOARD CODE\r\n; ------------------\r\n\r\n; The most general data format for billboards:\r\n\r\n; input              output       \r\n; (s0,t0)            (s0,t0,1,0)   \r\n; (r0,g0,b0,a0)      (r0,g0,b0,a0) \r\n; (x,y,z)            (X0,Y0,Z0,0)  \r\n; (s1,t1)            (s1,t1,1,0)   \r\n; (r1,g1,b1,a1)      (r1,g1,b1,a1) \r\n; (w,h)              (X1,Y1,Z1,0)  \r\n; (s2,t2)            (s2,t2,1,0)   \r\n; (r2,g2,b2,a2)      (r2,g2,b2,a2) \r\n; (tx,ty,ty)         (X2,Y2,Z2,0)  \r\n; (s3,t3)            (s3,t3,1,0)   \r\n; (r3,g3,b3,a3)      (r3,g3,b3,a3) \r\n; (ax,ay,az)         (X3,Y3,Z3,0)  \r\n\r\n; screen aligned billboards omit the axis vector (ax,ay,az)\r\n; and various optimised types can omit much of the rest of the data.\r\n\r\n\r\n\t\t.include \"vu1/defs.vsm\"\r\n\r\n\r\n\r\n\r\n\r\n\t\t; float regs\r\n\t\t.equr\tTag,\tVF01\r\n\t\t\r\n\t\t.equr\tpvw,\tVF01\r\n\t\t.equr\txyz0,\tVF02\r\n\t\t.equr\txyz1,\tVF03\r\n\t\t.equr\txyz2,\tVF04\r\n\t\t.equr\txyz3,\tVF05\r\n\t\t.equr\tdim,\tVF06\r\n\t\t.equr\tpvl,\tVF07\r\n\t\t.equr\taxis,\tVF08\r\n\t\t.equr\twdir,\tVF13\r\n\t\t.equr\tvdir2,\tVF13\r\n\t\t.equr\tviewvec,VF14\r\n\t\t.equr\ttrans,\tVF15\r\n\t\t.equr\tstq0,\tVF16\r\n\t\t.equr\tstq1,\tVF17\r\n\t\t.equr\tstq2,\tVF18\r\n\t\t.equr\tstq3,\tVF19\r\n\t\t\r\n\t\t.equr\tudir,\tVF20\r\n\t\t.equr\tvdir,\tVF21\r\n\t\t.equr\tvscale,\tVF22\r\n\t\t.equr\tcam,\tVF25\r\n\t\t.equr\tcol,\tVF26\r\n\t\t.equr\tvoff,\tVF27\r\n\t\t.equr\tmatWF0,\tVF28\r\n\t\t.equr\tmatWF1,\tVF29\r\n\t\t.equr\tmatWF2,\tVF30\r\n\t\t.equr\tmatWF3,\tVF31\r\n\r\n\t\t; integer regs\r\n\t\t.equr\tInput,\tVI02\r\n\t\t.equr\tOutput,\tVI03\r\n\t\t.equr\tStep,\tVI04\r\n\t\t.equr\tEnd,\tVI05\r\n\t\t\r\n\r\n\r\n\t\t.scope\r\n\r\nScreenAlignedBillboards:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,COLR\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI14,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,ApplyColourBillboard\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,Label3\r\nLabel3:\r\n\r\n\r\n\t\t; double v basis vec\r\n\t\tADD\t\t\tvdir2,vdir,vdir\t\tNOP\r\n\t\t\r\n\t\t; init output pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tOutput,Input,0\r\n\t\t\r\n@Loop:\r\n\r\n\t\t; load geometric values\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tpvw,2(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tdim,5(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tpvl,8(Input)\r\n\t\t\r\n\t\t; transform world position of pivot by matWF:\r\n\t\tADDAx\t\tACC,matWF3,zero\t\tNOP\r\n\t\tMADDAx\t\tACC,matWF0,pvw.x\tNOP\r\n\t\tMADDAy\t\tACC,matWF1,pvw.y\tNOP\r\n\t\tMADDAz\t\tACC,matWF2,pvw.z\tNOP\r\n\t\t\r\n\t\t; offset by pivot's local coords\r\n\t\tMSUBAx\t\tACC,udir,pvl.x\t\tNOP\r\n\t\tMSUBAy\t\tACC,vdir,pvl.y\t\tNOP\r\n\t\t\r\n\t\t; generate the 4 corners in frustum coords\r\n\t\tMSUBAy\t\tACC,vdir,dim.y\t\tNOP\r\n\t\tMSUBx\t\txyz0,udir,dim.x\t\tNOP\r\n\t\tMADDx\t\txyz1,udir,dim.x\t\tNOP\r\n\t\tMADDAy\t\tACC,vdir2,dim.y\t\tNOP\r\n\t\tMSUBx\t\txyz2,udir,dim.x\t\tNOP\r\n\t\tMADDx\t\txyz3,udir,dim.x\t\tNOP\r\n\t\t\r\n\t\t; culling tests\r\n\t\tCLIPw.xyz\txyz0.xyz,xyz0.w\t\tNOP\r\n\t\tCLIPw.xyz\txyz1.xyz,xyz1.w\t\tNOP\r\n\t\tCLIPw.xyz\txyz2.xyz,xyz2.w\t\tNOP\r\n\t\tCLIPw.xyz\txyz3.xyz,xyz3.w\t\tNOP\r\n\t\t\r\n\t\t; calc 1/w\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,voff.w,xyz0.w\r\n\t\tNOP\t\t\t\t\t\t\t\tWAITQ\r\n\t\t\r\n\t\t; transform to homogeneous viewport coords\r\n\t\tMULAw.xyz\tACC,voff,xyz0.w\t\tNOP\r\n\t\tMADD.xyz\txyz0,vscale,xyz0\tNOP\r\n\t\tMADD.xyz\txyz1,vscale,xyz1\tNOP\r\n\t\tMADD.xyz\txyz2,vscale,xyz2\tNOP\r\n\t\tMADD.xyz\txyz3,vscale,xyz3\tNOP\r\n\t\t\r\n\t\t; projection\r\n\t\tMULq.xyz\txyz0,xyz0,Q\t\t\tNOP\r\n\t\tMULq.xyz\txyz1,xyz1,Q\t\t\tNOP\r\n\t\tMULq.xyz\txyz2,xyz2,Q\t\t\tNOP\r\n\t\tMULq.xyz\txyz3,xyz3,Q\t\t\tNOP\r\n\t\t\r\n\t\t; culling results\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI01,VI00,1\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\txyz0,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\txyz1,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0xFFFFC0\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,0x7FFF\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\txyz2,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,0x7FFF\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\txyz3,VI01\r\n\t\t\r\n\t\t; store corners\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\txyz0, 2(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\txyz1, 5(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\txyz2, 8(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\txyz3,11(Output)\r\n\r\n\t\t; step pointers and loop\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tInput,Input,Step\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tOutput,Output,Step\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tOutput,End,@Loop\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; go back for more\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tTag,(Output++)\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tInput,Output,0\r\n\r\n\t\t.endscope\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t.scope\r\n\t\t\r\nLongAxisBillboards:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,COLR\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI14,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,ApplyColourBillboard\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,Label4\r\nLabel4:\r\n\r\n\t\t; init output pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tOutput,Input,0\r\n\r\n@Loop:\r\n\r\n\t\t; load geometric values\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tpvw,  2(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tdim,  5(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tpvl,  8(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\taxis,11(Input)\r\n\t\t\r\n\t\t; get view vector in world space\r\n\t\tSUB.xyz\t\tviewvec,pvw,cam\t\tNOP\r\n\t\t\r\n\t\t; generate transverse axis in world space\r\n\t\tOPMULA.xyz\tACC,viewvec,axis\tNOP\r\n\t\tOPMSUB.xyz\ttrans,axis,viewvec\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tERLENG\t\tP,trans\r\n\t\tNOP\t\t\t\t\t\t\t\tWAITP\r\n\t\tNOP\t\t\t\t\t\t\t\tMFP.w\t\ttrans,P\r\n\t\tMULw.xyz\ttrans,trans,trans.w\tNOP\r\n\t\t\r\n\t\t; generate wdir\r\n\t\tOPMULA.xyz\tACC,trans,axis\t\tNOP\r\n\t\tOPMSUB.xyz\twdir,axis,trans\t\tNOP\r\n\t\t\r\n\t\t; transform to frustum coords\r\n\t\tMULAx\t\tACC,matWF0,trans.x\tNOP\r\n\t\tMADDAy\t\tACC,matWF1,trans.y\tNOP\r\n\t\tMADDz\t\ttrans,matWF2,trans.z\tNOP\r\n\t\t\r\n\t\tMULAx\t\tACC,matWF0,axis.x\tNOP\r\n\t\tMADDAy\t\tACC,matWF1,axis.y\tNOP\r\n\t\tMADDz\t\taxis,matWF2,axis.z\tNOP\r\n\t\t\r\n\t\tMULAx\t\tACC,matWF0,wdir.x\tNOP\r\n\t\tMADDAy\t\tACC,matWF1,wdir.y\tNOP\r\n\t\tMADDz\t\twdir,matWF2,wdir.z\tNOP\r\n\t\t\r\n\t\t; transform world position of pivot by matWF:\r\n\t\tADDAx\t\tACC,matWF3,zero\t\tNOP\r\n\t\tMADDAx\t\tACC,matWF0,pvw.x\tNOP\r\n\t\tMADDAy\t\tACC,matWF1,pvw.y\tNOP\r\n\t\tMADDAz\t\tACC,matWF2,pvw.z\tNOP\r\n\t\t\r\n\t\t; offset by pivot's local coords\r\n\t\tMSUBAx\t\tACC,trans,pvl.x\t\tNOP\r\n\t\tMSUBAy\t\tACC,axis,pvl.y\t\tNOP\r\n\t\tMSUBAz\t\tACC,wdir,pvl.z\t\tNOP\r\n\t\t\r\n\t\t; generate the 2 'left' corners in frustum coords\r\n\t\tMSUBAx.xy\tACC,trans,dim.x\t\tNOP\r\n\t\tMSUBy\t\txyz0,axis,dim.y\t\tNOP\r\n\t\tMADDy\t\txyz2,axis,dim.y\t\tNOP\r\n\t\t\r\n\t\t; generate the 2 'right' corners in frustum coords\r\n\t\tMADDAx.xy\tACC,trans,dim.x\t\tNOP\r\n\t\tMADDAx.xy\tACC,trans,dim.x\t\tNOP\r\n\t\tMSUBy\t\txyz1,axis,dim.y\t\tNOP\r\n\t\tMADDy\t\txyz3,axis,dim.y\t\tNOP\r\n\t\t\r\n\t\t; culling tests\r\n\t\tCLIPw.xyz\txyz0.xyz,xyz0.w\t\tNOP\r\n\t\tCLIPw.xyz\txyz1.xyz,xyz1.w\t\tNOP\r\n\t\tCLIPw.xyz\txyz2.xyz,xyz2.w\t\tNOP\r\n\t\tCLIPw.xyz\txyz3.xyz,xyz3.w\t\tNOP\r\n\t\t\r\n\t\t; transform to homogeneous viewport coords\r\n\t\tMULAw.xyz\tACC,voff,xyz0.w\t\tNOP\r\n\t\tMADD.xyz\txyz0,vscale,xyz0\tNOP\r\n\t\tMADD.xyz\txyz1,vscale,xyz1\tNOP\r\n\t\tMULAw.xyz\tACC,voff,xyz2.w\t\tNOP\r\n\t\tMADD.xyz\txyz2,vscale,xyz2\tNOP\r\n\t\tMADD.xyz\txyz3,vscale,xyz3\tNOP\r\n\t\t\r\n\t\t; load texcoords\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tstq0,0(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tstq1,3(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tstq2,6(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tstq3,9(Input)\r\n\t\t\r\n\t\t; homogeneous divs for 'top' corners\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,voff.w,xyz0.w\r\n\t\tNOP\t\t\t\t\t\t\t\tWAITQ\r\n\t\tMULq.xyz\txyz0,xyz0,Q\t\t\tNOP\r\n\t\tMULq.xyz\txyz1,xyz1,Q\t\t\tNOP\r\n\t\tMULq.xyz\tstq0,stq0,Q\t\t\tNOP\r\n\t\tMULq.xyz\tstq1,stq1,Q\t\t\tNOP\r\n\t\t\r\n\t\t; homogeneous divs for 'bottom' corners\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,voff.w,xyz2.w\r\n\t\tNOP\t\t\t\t\t\t\t\tWAITQ\r\n\t\tMULq.xyz\txyz2,xyz2,Q\t\t\tNOP\r\n\t\tMULq.xyz\txyz3,xyz3,Q\t\t\tNOP\r\n\t\tMULq.xyz\tstq2,stq2,Q\t\t\tNOP\r\n\t\tMULq.xyz\tstq3,stq3,Q\t\t\tNOP\r\n\t\t\r\n\t\t; culling results\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI01,VI00,1\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\txyz0,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\txyz1,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0xFFFFC0\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,0x7FFF\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\txyz2,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,0x7FFF\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\txyz3,VI01\r\n\t\t\r\n\t\t; store corners\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\txyz0, 2(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\txyz1, 5(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\txyz2, 8(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\txyz3,11(Output)\r\n\r\n\t\t; store texcoords\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tstq0,0(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tstq1,3(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tstq2,6(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tstq3,9(Output)\r\n\r\n\t\t; step pointers and loop\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tInput,Input,Step\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tOutput,Output,Step\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tOutput,End,@Loop\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; go back for more\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tTag,(Output++)\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tInput,Output,0\r\n\r\n\t\t.endscope\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t.scope\r\n\t\t\r\nShortAxisBillboards:\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,COLR\r\n\t\tNOP\t\t\t\t\t\t\t\tIAND\t\tVI01,VI14,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI01,VI00,ApplyColourBillboard\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI00,Label5\r\nLabel5:\r\n\r\n\t\t; init output pointer\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tOutput,Input,0\r\n\r\n@Loop:\r\n\r\n\t\t; load geometric values\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tpvw,  2(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tdim,  5(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\tpvl,  8(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ\t\t\taxis,11(Input)\r\n\t\t\r\n\t\t; get view vector in world space\r\n\t\tSUB.xyz\t\tviewvec,pvw,cam\t\tNOP\r\n\t\t\r\n\t\t; generate transverse axis in world space\r\n\t\tOPMULA.xyz\tACC,axis,viewvec\tNOP\r\n\t\tOPMSUB.xyz\ttrans,viewvec,axis\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tERLENG\t\tP,trans\r\n\t\tNOP\t\t\t\t\t\t\t\tWAITP\r\n\t\tNOP\t\t\t\t\t\t\t\tMFP.w\t\ttrans,P\r\n\t\tMULw.xyz\ttrans,trans,trans.w\tNOP\r\n\t\t\r\n\t\t; generate wdir\r\n\t\tOPMULA.xyz\tACC,trans,axis\t\tNOP\r\n\t\tOPMSUB.xyz\twdir,axis,trans\t\tNOP\r\n\t\t\r\n\t\t; transform to frustum coords\r\n\t\tMULAx\t\tACC,matWF0,trans.x\tNOP\r\n\t\tMADDAy\t\tACC,matWF1,trans.y\tNOP\r\n\t\tMADDz\t\ttrans,matWF2,trans.z\tNOP\r\n\t\t\r\n\t\tMULAx\t\tACC,matWF0,axis.x\tNOP\r\n\t\tMADDAy\t\tACC,matWF1,axis.y\tNOP\r\n\t\tMADDz\t\taxis,matWF2,axis.z\tNOP\r\n\t\t\r\n\t\tMULAx\t\tACC,matWF0,wdir.x\tNOP\r\n\t\tMADDAy\t\tACC,matWF1,wdir.y\tNOP\r\n\t\tMADDz\t\twdir,matWF2,wdir.z\tNOP\r\n\t\t\r\n\t\t; transform world position of pivot by matWF:\r\n\t\tADDAx\t\tACC,matWF3,zero\t\tNOP\r\n\t\tMADDAx\t\tACC,matWF0,pvw.x\tNOP\r\n\t\tMADDAy\t\tACC,matWF1,pvw.y\tNOP\r\n\t\tMADDAz\t\tACC,matWF2,pvw.z\tNOP\r\n\t\t\r\n\t\t; offset by pivot's local coords\r\n\t\tMSUBAy\t\tACC,trans,pvl.y\t\tNOP\r\n\t\tMSUBAx\t\tACC,axis,pvl.x\t\tNOP\r\n\t\tMSUBAz\t\tACC,wdir,pvl.z\t\tNOP\r\n\t\t\r\n\t\t; generate the 2 'left' corners in frustum coords\r\n\t\tMSUBAy.xy\tACC,trans,dim.y\t\tNOP\r\n\t\tMSUBx\t\txyz0,axis,dim.x\t\tNOP\r\n\t\tMADDx\t\txyz2,axis,dim.x\t\tNOP\r\n\t\t\r\n\t\t; generate the 2 'right' corners in frustum coords\r\n\t\tMADDAy.xy\tACC,trans,dim.y\t\tNOP\r\n\t\tMADDAy.xy\tACC,trans,dim.y\t\tNOP\r\n\t\tMSUBx\t\txyz1,axis,dim.x\t\tNOP\r\n\t\tMADDx\t\txyz3,axis,dim.x\t\tNOP\r\n\t\t\r\n\t\t; culling tests\r\n\t\tCLIPw.xyz\txyz0.xyz,xyz0.w\t\tNOP\r\n\t\tCLIPw.xyz\txyz1.xyz,xyz1.w\t\tNOP\r\n\t\tCLIPw.xyz\txyz2.xyz,xyz2.w\t\tNOP\r\n\t\tCLIPw.xyz\txyz3.xyz,xyz3.w\t\tNOP\r\n\t\t\r\n\t\t; transform to homogeneous viewport coords\r\n\t\tMULAw.xyz\tACC,voff,xyz0.w\t\tNOP\r\n\t\tMADD.xyz\txyz0,vscale,xyz0\tNOP\r\n\t\tMADD.xyz\txyz1,vscale,xyz1\tNOP\r\n\t\tMULAw.xyz\tACC,voff,xyz2.w\t\tNOP\r\n\t\tMADD.xyz\txyz2,vscale,xyz2\tNOP\r\n\t\tMADD.xyz\txyz3,vscale,xyz3\tNOP\r\n\t\t\r\n\t\t; load texcoords\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tstq0,0(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tstq1,3(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tstq2,6(Input)\r\n\t\tNOP\t\t\t\t\t\t\t\tLQ.xyz\t\tstq3,9(Input)\r\n\t\t\r\n\t\t; homogeneous divs for 'top' corners\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,voff.w,xyz0.w\r\n\t\tNOP\t\t\t\t\t\t\t\tWAITQ\r\n\t\tMULq.xyz\txyz0,xyz0,Q\t\t\tNOP\r\n\t\tMULq.xyz\txyz1,xyz1,Q\t\t\tNOP\r\n\t\tMULq.xyz\tstq0,stq0,Q\t\t\tNOP\r\n\t\tMULq.xyz\tstq1,stq1,Q\t\t\tNOP\r\n\t\t\r\n\t\t; homogeneous divs for 'bottom' corners\r\n\t\tNOP\t\t\t\t\t\t\t\tDIV\t\t\tQ,voff.w,xyz2.w\r\n\t\tNOP\t\t\t\t\t\t\t\tWAITQ\r\n\t\tMULq.xyz\txyz2,xyz2,Q\t\t\tNOP\r\n\t\tMULq.xyz\txyz3,xyz3,Q\t\t\tNOP\r\n\t\tMULq.xyz\tstq2,stq2,Q\t\t\tNOP\r\n\t\tMULq.xyz\tstq3,stq3,Q\t\t\tNOP\r\n\t\t\r\n\t\t; culling results\r\n\t\tNOP\t\t\t\t\t\t\t\tISUBIU\t\tVI01,VI00,1\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\txyz0,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\txyz1,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0xFFFFC0\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,0x7FFF\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\txyz2,VI01\r\n\t\tNOP\t\t\t\t\t\t\t\tFCAND\t\tVI01,0x03FFFF\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI01,VI01,0x7FFF\r\n\t\tNOP\t\t\t\t\t\t\t\tMFIR.w\t\txyz3,VI01\r\n\t\t\r\n\t\t; store corners\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\txyz0, 2(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\txyz1, 5(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\txyz2, 8(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ\t\t\txyz3,11(Output)\r\n\r\n\t\t; store texcoords\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tstq0,0(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tstq1,3(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tstq2,6(Output)\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tstq3,9(Output)\r\n\r\n\t\t; step pointers and loop\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tInput,Input,Step\r\n\t\tNOP\t\t\t\t\t\t\t\tIADD\t\tOutput,Output,Step\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tOutput,End,@Loop\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\t\r\n\t\t; go back for more\r\n\t\tNOP\t\t\t\t\t\t\t\tLQI\t\t\tTag,(Output++)\r\n\t\tNOP\t\t\t\t\t\t\t\tB\t\t\tNextPrim\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tInput,Output,0\r\n\r\n\t\t.endscope\r\n\t\t\r\n\t\t\r\n; applying material colour to a billboard\r\nApplyColourBillboard:\r\n\r\n\t\t.if 0\r\n\t\t; unoptimised version\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t8388608\r\n\t\tADDAi\t\tACC,VF00,I\t\t\tLOI\t\t\t8388863\r\n\t\t\r\nLoopACB:NOP\t\t\t\t\t\t\t\tLQ.xyz\t\tVF01,1(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tIADDIU\t\tVI02,VI02,3\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tITOF0.xyz\tVF02,VF01\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMADD.xyz\tVF03,VF02,col\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tMINIi.xyz\tVF04,VF03,I\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tNOP\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopACB\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF04,-2(VI02)\r\n\t\t\r\n\t\t.else\r\n\t\t; optimised version\r\n\t\t\r\n\t\tNOP\t\t\t\t\t\t\t\tLOI\t\t\t8388608\r\n\t\tADDAi\t\tACC,VF00,I\t\t\tLQ.xyz\t\tVF03,1(VI02)\r\n\t\tITOF0.xyz\tVF03,VF03\t\t\tLQ.xyz\t\tVF02,4(VI02)\r\n\t\tMADD.xyz\tVF03,VF03,col\t\tLOI\t\t\t8388863\r\n\t\tITOF0.xyz\tVF02,VF02\t\t\tLQ.xyz\t\tVF01,7(VI02)\r\n\t\t\r\nLoopACB:MINIi.xyz\tVF04,VF03,I\t\t\tIADDIU\t\tVI02,VI02,3\r\n\t\tMADD.xyz\tVF03,VF02,col\t\tNOP\r\n\t\tITOF0.xyz\tVF02,VF01\t\t\tLQ.xyz\t\tVF01,7(VI02)\r\n\t\tNOP\t\t\t\t\t\t\t\tIBNE\t\tVI02,VI05,LoopACB\r\n\t\tNOP\t\t\t\t\t\t\t\tSQ.xyz\t\tVF04,-2(VI02)\r\n\t\t\r\n\t\t.endif\r\n\r\n\t\tNOP\t\t\t\t\t\t\t\tJR\t\t\tVI01\r\n\t\tNOP\t\t\t\t\t\t\t\tISUB\t\tVI02,VI02,VI06\r\n\t\t\r\n;-----------------------------------------------------------------------------------------------------------------------------\r\n\r\n\t\t; Can use this to see how much micromem is left. (The assembler warns if the code overflows.)\r\n\t\t;.rept 93\r\n\t\t;NOP\t\t\t\t\t\t\t\tNOP\r\n\t\t;.endr\r\n\r\n\r\n.EndMPG\r\n\r\nMPGEnd:\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu1code.h",
    "content": "#ifndef __MICROCODE_H\r\n#define __MICROCODE_H\r\n\r\n// the __attribute__ things are there so the code can compile using GP relative\r\n// otherwise, the compiler assumes these go in the .lit4 section, and we get a link error, as they don't\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\nextern uint MPGStart       __attribute__((section(\".vudata\")));\r\nextern uint MPGEnd         __attribute__((section(\".vudata\")));\r\nextern uint Setup          __attribute__((section(\".vudata\")));\r\nextern uint Jump           __attribute__((section(\".vudata\")));\r\nextern uint Breakpoint     __attribute__((section(\".vudata\")));\r\nextern uint ParseInit      __attribute__((section(\".vudata\")));\r\nextern uint Parser         __attribute__((section(\".vudata\")));\r\nextern uint L_VF09         __attribute__((section(\".vudata\")));\r\nextern uint L_VF10         __attribute__((section(\".vudata\")));\r\nextern uint L_VF11         __attribute__((section(\".vudata\")));\r\nextern uint L_VF12         __attribute__((section(\".vudata\")));\r\nextern uint L_VF13         __attribute__((section(\".vudata\")));\r\nextern uint L_VF14         __attribute__((section(\".vudata\")));\r\nextern uint L_VF15         __attribute__((section(\".vudata\")));\r\nextern uint L_VF16         __attribute__((section(\".vudata\")));\r\nextern uint L_VF17         __attribute__((section(\".vudata\")));\r\nextern uint L_VF18         __attribute__((section(\".vudata\")));\r\nextern uint L_VF19         __attribute__((section(\".vudata\")));\r\nextern uint L_VF20         __attribute__((section(\".vudata\")));\r\nextern uint L_VF21         __attribute__((section(\".vudata\")));\r\nextern uint L_VF22         __attribute__((section(\".vudata\")));\r\nextern uint L_VF23         __attribute__((section(\".vudata\")));\r\nextern uint L_VF24         __attribute__((section(\".vudata\")));\r\nextern uint L_VF25         __attribute__((section(\".vudata\")));\r\nextern uint L_VF26         __attribute__((section(\".vudata\")));\r\nextern uint L_VF27         __attribute__((section(\".vudata\")));\r\nextern uint L_VF28         __attribute__((section(\".vudata\")));\r\nextern uint L_VF39         __attribute__((section(\".vudata\")));\r\nextern uint L_VF30         __attribute__((section(\".vudata\")));\r\nextern uint L_VF31         __attribute__((section(\".vudata\")));\r\nextern uint GSPrim         __attribute__((section(\".vudata\")));\r\nextern uint Proj           __attribute__((section(\".vudata\")));\r\nextern uint PTex           __attribute__((section(\".vudata\")));\r\nextern uint Refl           __attribute__((section(\".vudata\")));\r\nextern uint Line           __attribute__((section(\".vudata\")));\r\nextern uint Skin           __attribute__((section(\".vudata\")));\r\nextern uint Sprites        __attribute__((section(\".vudata\")));\r\nextern uint SpriteCull     __attribute__((section(\".vudata\")));\r\nextern uint ReformatXforms __attribute__((section(\".vudata\")));\r\nextern uint ShadowVolumeSkin __attribute__((section(\".vudata\")));\r\n\r\n#endif\r\n\r\n#ifdef __PLAT_WN32__\r\n\r\n//#define Setup\t\t 0\r\n//#define Jump\t\t 2\r\n#define Breakpoint\t 4\r\n#define ParseInit\t 6\r\n#define Parser\t\t 8\r\n#define L_VF09\t\t10\t// (Near, Far, k/(xRes/2), k/(yRes/2)) where k=viewport_scale_x, should be 2048 but is 1900 because of clipper problem\r\n#define L_VF10\t\t12\t// inverse viewport scale vector\r\n#define L_VF11\t\t14\t// inverse viewport offset vector\r\n#define L_VF12\t\t16\t// row 0, local to viewport transform\r\n#define L_VF13\t\t18\t// row 1, local to viewport transform\r\n#define L_VF14\t\t20\t// row 2, local to viewport transform\r\n#define L_VF15\t\t22\t// row 3, local to viewport transform\r\n#define L_VF16\t\t24\t// lightsource 2 colour (r,g,b,?)\r\n#define L_VF17\t\t26\t// row 0, reflection map transform\r\n#define L_VF18\t\t28\t// row 1, reflection map transform\r\n#define L_VF19\t\t30\t// row 2, reflection map transform\r\n#define L_VF20\t\t32\t// light vectors, x components\r\n#define L_VF21\t\t34\t// light vectors, y components\r\n#define L_VF22\t\t36\t// light vectors, z components\r\n#define L_VF23\t\t38\t// ambient colour (r,g,b,?)\r\n#define L_VF24\t\t40\t// lightsource 0 colour (r,g,b,?)\r\n#define L_VF25\t\t42\t// lightsource 1 colour (r,g,b,?)\r\n#define L_VF26\t\t44\t// texture projection scale vector\r\n#define L_VF27\t\t46\t// texture projection offset vector\r\n#define L_VF28\t\t48\t// saves the z-components of the view matrix during a z-push\r\n#define L_VF29\t\t50\t// temp skinning\r\n#define L_VF30\t\t52\t// temp skinning\r\n#define L_VF31\t\t54\t// temp skinning\r\n#define GSPrim\t\t56\r\n#define Proj\t\t58\r\n#define PTex\t\t60\r\n#define Refl\t\t62\r\n#define Line\t\t64\r\n#define Skin\t\t66\r\n#define Light\t\t68\r\n#define LightT\t\t70\r\n#define WibbleT\t\t72\r\n#define LWibT\t\t74\r\n#define AddZPush\t76\r\n#define SubZPush\t78\r\n#define Setup\t\t80\r\n#define Jump\t\t82\r\n#define SCAB\t\t84\r\n#define LAB\t\t\t86\r\n#define SHAB\t\t88\r\n\r\n#endif\r\n\r\n#define PROJ 0x00\r\n#define CULL 0x01\t\t// per-triangle view culling\r\n#define CLIP 0x02\t\t// full 3D clipping of triangles\r\n#define SHDW 0x04\t\t// skinned=>cast shadow into texture; non-skinned=>render mesh with projected shadow texture on it\r\n#define COLR 0x08\t\t// apply colour at vertices\r\n#define FOGE 0x10\t\t// calculate per-vertex fog coefficient\r\n#define WIRE 0x20\t\t// render skinned as wireframe (but doesn't render all edges)\r\n\r\n#endif //__MICROCODE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu1context.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tTHPS4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tvu1context\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tvu1context.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t00/00/00\t-\tmrd\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tsends contextual setup data to vu1 float registers\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <sys/timer.h>\r\n#include \"geomnode.h\"\r\n#include \"vu1context.h\"\r\n#include \"vu1code.h\"\r\n#include \"render.h\"\r\n#include \"dma.h\"\r\n#include \"vif.h\"\r\n#include \"gif.h\"\r\n#include \"gs.h\"\r\n#include \"light.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCVu1Context::CVu1Context()\r\n{\r\n\tDbg_Assert(\"Don't use this constructor!\");\r\n}\r\n\r\n\r\nvoid CVu1Context::Init()\r\n{\r\n\tuint8 *dma_ploc = dma::pLoc;\r\n\r\n\t//dma::pLoc = (uint8 *)&m_stmask;\r\n\tdma::pLoc = (uint8 *)&m_stmask;\r\n\tvu1::Loc = 0;\r\n\r\n\t// set vifcodes\r\n\tvif::STMASK(0);\t\t\t\t// mp_light_group = NULL; in a very cheeky way\r\n\tvif::STCYCL(1,1);\r\n\tvif::UNPACK(0,V4_32,STD_CTXT_SIZE+1,REL,UNSIGNED,0);\r\n\r\n\t// set m_giftag\r\n\tgif::Tag1(gs::NOP, 1, PACKED, 0, 0, 0, STD_CTXT_SIZE, VU1_ADDR(L_VF12));\r\n\r\n\t//SetExtended(false);\r\n\r\n\tdma::pLoc = dma_ploc;\r\n}\r\n\r\n\r\nvoid CVu1Context::InitExtended()\r\n{\r\n\tuint8 *dma_ploc = dma::pLoc;\r\n\r\n\t//dma::pLoc = (uint8 *)&m_stmask;\r\n\tdma::pLoc = (uint8 *)&m_stmask;\r\n\tvu1::Loc = 0;\r\n\r\n\t// set vifcodes\r\n\tvif::STMASK(0);\t\t\t\t// mp_light_group = NULL; in a very cheeky way\r\n\tvif::STCYCL(1,1);\r\n\tvif::UNPACK(0,V4_32,EXT_CTXT_SIZE+1,REL,UNSIGNED,0);\r\n\r\n\t// set m_giftag\r\n\tgif::Tag1(gs::NOP, 1, PACKED, 0, 0, 0, EXT_CTXT_SIZE, VU1_ADDR(L_VF12));\r\n\r\n\tSetExtended(true);\r\n\r\n\tupdate_lights();\r\n\r\n\tdma::pLoc = dma_ploc;\r\n}\r\n\r\n\r\nCVu1Context::CVu1Context(const CVu1Context &ctxt)\r\n{\r\n\t// Mick: Since this does not contain any pointers, it's safe to just copy it\r\n\t// this cuts down on unwarrented initialization of the various vectors and stuff\r\n\t// and should be fast as we are quad word aligned.\r\n\t// Garrett: Even though we have a pointer to a light group, it is still OK to\r\n\t// use memcpy() since this class doesn't manage the instance it points to.\r\n\r\n\tif (ctxt.IsExtended())\r\n\t{\r\n\t\tmemcpy(this, &ctxt, (EXT_CTXT_SIZE+7)*16);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// reduced version\r\n\t\tmemcpy(this, &ctxt, (STD_CTXT_SIZE+7)*16);\r\n\t}\r\n\r\n}\r\n\r\n\r\nvoid CVu1Context::StandardSetup(Mth::Matrix &localToWorld)\r\n{\r\n\t// get the local to camera matrix\r\n\tm_matrix = localToWorld * render::WorldToCamera;\r\n\r\n\t// get the massaged matrix values\r\n\tMth::Matrix inv = m_matrix;\r\n\tinv.InvertUniform();\r\n\tm_translation = -inv[3] * SUB_INCH_PRECISION;\r\n\tm_translation[0] = float(int(m_translation[0]));\r\n\tm_translation[1] = float(int(m_translation[1]));\r\n\tm_translation[2] = float(int(m_translation[2]));\r\n\r\n\tMth::Matrix adjusted_matrix = m_matrix;\r\n\t//m_adjustedMatrix = m_matrix;\r\n\tadjusted_matrix[3] = -m_translation * m_matrix * RECIPROCAL_SUB_INCH_PRECISION;\r\n\r\n\t// generate the vu1 context data\r\n\t//m_localToFrustum  = m_adjustedMatrix * render::CameraToFrustum;\r\n\tMth::Matrix temp;\r\n\tsceVu0MulMatrix((sceVu0FVECTOR*)&temp,\r\n\t\t\t\t\t(sceVu0FVECTOR*)&render::CameraToFrustum,\r\n\t\t\t\t\t(sceVu0FVECTOR*)&adjusted_matrix);   \t\r\n\t//m_localToFrustum = temp;\r\n\t\r\n//\tm_localToViewport = m_localToFrustum * render::FrustumToViewport;\r\n\tsceVu0MulMatrix((sceVu0FVECTOR*)&m_localToViewport,\r\n\t\t\t\t\t(sceVu0FVECTOR*)&render::FrustumToViewport,\r\n\t\t\t\t\t(sceVu0FVECTOR*)&temp);\r\n\r\n\t// Update light directions\r\n\tif (IsExtended())\r\n\t{\r\n\t\tupdate_lights();\r\n\t}\r\n}\r\n\r\n\r\n\r\nCVu1Context *CVu1Context::Localise()\r\n{\r\n\tdma::SetList(NULL);\r\n\tCVu1Context *p_new_context = (CVu1Context*)dma::pLoc;\r\n\r\n\tif (IsExtended())\r\n\t{\r\n\t\tmemcpy(dma::pLoc, this, sizeof(CVu1Context));\r\n\t\tdma::pLoc += sizeof(CVu1Context);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// reduced version\r\n\t\tmemcpy(dma::pLoc, this, (STD_CTXT_SIZE+7)*16);\r\n\t\tdma::pLoc += (STD_CTXT_SIZE+7)*16;\r\n\t}\r\n\r\n\treturn p_new_context;\r\n}\r\n\r\n\r\n\r\n\r\nCVu1Context *CVu1Context::LocaliseExtend()\r\n{\r\n\tdma::SetList(NULL);\r\n\tCVu1Context *p_new_context = (CVu1Context*)dma::pLoc;\r\n\r\n\tif (IsExtended())\r\n\t{\r\n\t\tmemcpy(dma::pLoc, this, sizeof(CVu1Context));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmemcpy(dma::pLoc, this, (STD_CTXT_SIZE+7)*16);\r\n\t\tp_new_context->InitExtended();\r\n\t}\r\n\tdma::pLoc += sizeof(CVu1Context);\r\n\r\n\treturn p_new_context;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CVu1Context::HierarchicalSetup(Mth::Matrix &localToParent)\r\n{\r\n\t// get the local to camera matrix\r\n\tm_matrix = localToParent * m_matrix;\r\n\r\n\t// get the massaged matrix values\r\n\tMth::Matrix temp = m_matrix;\r\n\tm_translation = -(temp.InvertUniform())[3] * SUB_INCH_PRECISION;\r\n\tm_translation[0] = float(int(m_translation[0]));\r\n\tm_translation[1] = float(int(m_translation[1]));\r\n\tm_translation[2] = float(int(m_translation[2]));\r\n\r\n\tMth::Matrix adjusted_matrix = m_matrix;\r\n\t//m_adjustedMatrix = m_matrix;\r\n\tadjusted_matrix[3] = -m_translation * m_matrix * RECIPROCAL_SUB_INCH_PRECISION;\r\n\r\n\t// generate the vu1 context data\r\n//\tm_localToFrustum  = m_adjustedMatrix * render::CameraToFrustum;\r\n\tsceVu0MulMatrix((sceVu0FVECTOR*)&temp,\r\n\t\t\t\t\t(sceVu0FVECTOR*)&render::CameraToFrustum,\r\n\t\t\t\t\t(sceVu0FVECTOR*)&adjusted_matrix);   \t\r\n\t//m_localToFrustum = temp;\r\n\t\r\n//\tm_localToViewport = m_localToFrustum * render::FrustumToViewport;\r\n\tsceVu0MulMatrix((sceVu0FVECTOR*)&m_localToViewport,\r\n\t\t\t\t\t(sceVu0FVECTOR*)&render::FrustumToViewport,\r\n\t\t\t\t\t(sceVu0FVECTOR*)&temp);\r\n\r\n\t// Update light directions\r\n\tif (IsExtended())\r\n\t{\r\n\t\tupdate_lights();\r\n\t}\r\n}\r\n\r\n// Mick: This is taking 1.5% of our precious CPU time\r\nvoid CVu1Context::update_lights()\r\n{\r\n\tMth::Matrix temp;\r\n\ttemp[W].Set(0.0f,0.0f,0.0f,1.0f);\r\n\r\n\t// light vectors\r\n\tif (mp_light_group)\r\n\t{\r\n\t\ttemp[0] = mp_light_group->GetDirection(0);\r\n\t\ttemp[1] = mp_light_group->GetDirection(1);\r\n\t\ttemp[2] = mp_light_group->GetDirection(2);\r\n\t\r\n\t\ttemp *= render::WorldToCamera;\r\n\t\ttemp.Transpose();\r\n\t\t\r\n\t\tsceVu0MulMatrix((sceVu0FVECTOR*)&m_lightVecsX,\r\n\t\t\t\t\t\t(sceVu0FVECTOR*)&temp,\r\n\t\t\t\t\t\t(sceVu0FVECTOR*)&m_matrix);   \t\r\n\t\r\n\t\tm_ambientColour = mp_light_group->GetAmbientColor() * 1.0f/128.0f;\r\n\t\tm_lightColour0  = mp_light_group->GetDiffuseColor(0) * 1.0f/128.0f;\r\n\t\tm_lightColour1  = mp_light_group->GetDiffuseColor(1) * 1.0f/128.0f;\r\n\t\tm_lightColour2  = mp_light_group->GetDiffuseColor(2) * 1.0f/128.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttemp[0] = CLightGroup::sGetDefaultDirection(0);\r\n\t\ttemp[1] = CLightGroup::sGetDefaultDirection(1);\r\n\t\ttemp[2] = CLightGroup::sGetDefaultDirection(2);\r\n\r\n\t\ttemp *= render::WorldToCamera;\r\n\t\ttemp.Transpose();\r\n\t\t\r\n\t\tsceVu0MulMatrix((sceVu0FVECTOR*)&m_lightVecsX,\r\n\t\t\t\t\t\t(sceVu0FVECTOR*)&temp,\r\n\t\t\t\t\t\t(sceVu0FVECTOR*)&m_matrix);   \t\r\n\t\r\n\t\tm_ambientColour = CLightGroup::sGetDefaultAmbientColor() * 1.0f/128.0f;\r\n\t\tm_lightColour0  = CLightGroup::sGetDefaultDiffuseColor(0) * 1.0f/128.0f;\r\n\t\tm_lightColour1  = CLightGroup::sGetDefaultDiffuseColor(1) * 1.0f/128.0f;\r\n\t\tm_lightColour2  = CLightGroup::sGetDefaultDiffuseColor(2) * 1.0f/128.0f;\r\n\t}\r\n\r\n\t\r\n}\r\n\r\n\r\nvoid CVu1Context::SetupAsSky()\r\n{\r\n\t// get the local to camera matrix\r\n\tm_matrix = render::WorldToCamera;\r\n\r\n\t// get the massaged matrix values\r\n\tm_matrix[3].Set(0,0,0,1);\r\n\tm_translation.Set(0,0,0,1);\r\n\r\n\tMth::Matrix adjusted_matrix = m_matrix;\r\n\t//m_adjustedMatrix = m_matrix;\r\n\tadjusted_matrix.ScaleLocal(Mth::Vector(RECIPROCAL_SUB_INCH_PRECISION, RECIPROCAL_SUB_INCH_PRECISION, RECIPROCAL_SUB_INCH_PRECISION, 1.0f));\r\n\r\n\t// generate the vu1 context data\r\n\t//m_viewportScale   = render::SkyViewportScale;\r\n\t//m_viewportOffset  = render::SkyViewportOffset;\r\n\t//m_localToFrustum  = adjusted_matrix * render::CameraToFrustum;\r\n\tm_localToViewport = adjusted_matrix * render::CameraToFrustum * render::SkyFrustumToViewport;\r\n}\r\n\r\n\r\nvoid CVu1Context::AddZPush(float zPush)\r\n{\r\n\tm_localToViewport[0][2] += m_localToViewport[0][3] * zPush * 16.0f * render::InverseViewportScale[3];\r\n\tm_localToViewport[1][2] += m_localToViewport[1][3] * zPush * 16.0f * render::InverseViewportScale[3];\r\n\tm_localToViewport[2][2] += m_localToViewport[2][3] * zPush * 16.0f * render::InverseViewportScale[3];\r\n\tm_localToViewport[3][2] += m_localToViewport[3][3] * zPush * 16.0f * render::InverseViewportScale[3];\r\n}\r\n\r\n\r\nvoid CVu1Context::WibbleUVs(float *pData, uint Explicit)\r\n{\r\n\tif (Explicit)\r\n\t{\r\n\t\tm_texOffset[0] = pData[8];\r\n\t\tm_texOffset[1] = pData[9];\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Get number of vblanks, but reduce it to 24 bits so we don't lose accuracy in the float conversion.\r\n\t\t// This will introduce a glitch every 6 days, but that's preferrable to the loss of accuracy.\r\n\t\tint vblanks = Tmr::GetVblanks() & 0x00FFFFFF;\r\n\r\n\t\t// convert to seconds as float\r\n\t\tfloat t = (float)vblanks * (1.0f/60.0f);\r\n\t\tfloat angle;\r\n\r\n\t\t// u offset\r\n\t\tangle = pData[2] * t + pData[6];\r\n\t\tangle -= (2.0f*Mth::PI) * (float)(int)(angle * (0.5f/Mth::PI));\t\t// reduce angle mod 2pi\r\n\t\tm_texOffset[0] = pData[0] * t + pData[4] * sinf(angle);\r\n\t\tm_texOffset[0] += 8.0f;\r\n\t\tm_texOffset[0] -= (float)(((int)m_texOffset[0] >> 4) << 4);\t\t\t// reduce offset mod 16\r\n\t\tif (m_texOffset[0] < 0.0f)\t\t\t\t\t\t\t\t\t\t\t// and put it in the range -8 to +8\r\n\t\t\tm_texOffset[0] += 8.0f;\r\n\t\telse\r\n\t\t\tm_texOffset[0] -= 8.0f;\r\n\r\n\t\t// v offset\r\n\t\tangle = pData[3] * t + pData[7];\r\n\t\tangle -= (2.0f*Mth::PI) * (float)(int)(angle * (0.5f/Mth::PI));\t\t// reduce angle mod 2pi\r\n\t\tm_texOffset[1] = pData[1] * t + pData[5] * sinf(angle);\r\n\t\tm_texOffset[1] += 8.0f;\r\n\t\tm_texOffset[1] -= (float)(((int)m_texOffset[1] >> 4) << 4);\t\t\t// reduce offset mod 16\r\n\t\tif (m_texOffset[1] < 0.0f)\t\t\t\t\t\t\t\t\t\t\t// and put it in the range -8 to +8\r\n\t\t\tm_texOffset[1] += 8.0f;\r\n\t\telse\r\n\t\t\tm_texOffset[1] -= 8.0f;\r\n\r\n\t}\r\n}\r\n\r\n\r\nvoid CVu1Context::SetShadowVecs(float y)\r\n{\r\n\tm_texScale  = Mth::Vector(0.0078125f, 0.0078125f, 0.0f, 0.0f);\r\n\tm_texOffset = Mth::Vector(0.5f-0.0078125f*(render::ShadowCameraPosition[X]+RECIPROCAL_SUB_INCH_PRECISION*m_translation[X]),\r\n\t\t\t\t\t\t\t  0.5f-0.0078125f*(render::ShadowCameraPosition[Z]+RECIPROCAL_SUB_INCH_PRECISION*m_translation[Z]),\r\n\t\t\t\t\t\t\t  -((y+36.0f)+RECIPROCAL_SUB_INCH_PRECISION*m_translation[Y]),\r\n\t\t\t\t\t\t\t  0.0f);\r\n}\r\n\r\n\r\nvoid CVu1Context::SetColour(CGeomNode *pNode)\r\n{\r\n\tuint32 rgba = pNode->GetColor();\r\n   \tm_texScale[X] = (float)(rgba     & 0xFF) * 0.0078125f;\r\n\tm_texScale[Y] = (float)(rgba>> 8 & 0xFF) * 0.0078125f;\r\n\tm_texScale[Z] = (float)(rgba>>16 & 0xFF) * 0.0078125f;\r\n\tm_texScale[W] = (float)(rgba>>24       ) * 0.0078125f;\r\n}\r\n\r\n\r\nMth::Vector *CVu1Context::GetColour()\r\n{\r\n\treturn &m_texScale;\r\n}\r\n\r\n\r\nvoid CVu1Context::SetLights(CLightGroup *pLightGroup)\r\n{\r\n\tmp_light_group = pLightGroup;\r\n\tupdate_lights();\r\n}\r\n\r\n\r\nvoid CVu1Context::SetReflectionVecs(sint16 uScale, sint16 vScale)\r\n{\r\n\tMth::Matrix temp;\r\n\tfloat uf,vf;\r\n\tuf = float(uScale)*(0.5f/256.0f);\r\n\tvf = float(vScale)*(0.5f/256.0f);\r\n\r\n\ttemp[0] = Mth::Vector(uf, 0,  0,  0);\r\n\ttemp[1] = Mth::Vector(0,  vf, 0,  0);\r\n\ttemp[2] = Mth::Vector(0,  0,  1.4,0);\r\n\ttemp.Transpose();\r\n\r\n\tsceVu0MulMatrix((sceVu0FVECTOR*)&m_reflVecsX,\r\n\t\t\t\t\t(sceVu0FVECTOR*)&temp,\r\n\t\t\t\t\t(sceVu0FVECTOR*)&m_matrix);   \t\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace NxPs2\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/NX/vu1context.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tTHPS4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tvu1context\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tvu1context.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t00/00/00\t-\tmrd\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tsends contextual setup data to vu1 float registers\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __NGPS_NX_VU1CONTEXT_H\r\n#define __NGPS_NX_VU1CONTEXT_H\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n\r\n#define STD_CTXT_SIZE 5\r\n#define EXT_CTXT_SIZE 16\r\n\r\n\r\n\r\nclass CVu1Context\r\n{\r\npublic:\r\n\r\n\tCVu1Context();\r\n\tvoid Init();\r\n\tvoid InitExtended();\r\n\tCVu1Context(const CVu1Context &node);\r\n\t~CVu1Context() {}\r\n\r\n\tvoid\t\t\tStandardSetup(Mth::Matrix &localToWorld);\r\n\tvoid\t\t\tHierarchicalSetup(Mth::Matrix &localToParent);\r\n\tvoid\t\t\tSetupAsSky();\r\n\tvoid\t\t\tAddZPush(float zPush);\r\n\tvoid\t\t\tWibbleUVs(float *pData, uint Explicit);\r\n\tvoid\t\t\tSetShadowVecs(float y);\r\n\tvoid\t\t\tSetColour(CGeomNode *pNode);\r\n\tvoid\t\t\tSetAmbient(uint32 rgba);\r\n\tvoid\t\t\tSetLights(CLightGroup *pLightGroup);\r\n\tvoid\t\t\tSetReflectionVecs(sint16 uScale, sint16 vScale);\r\n\tvoid\t\t\tSetExtended(bool yes);\r\n\r\n\tCVu1Context\t\t*Localise();\r\n\tCVu1Context\t\t*LocaliseExtend();\r\n\r\n\r\n\tMth::Matrix \t*GetMatrix();\r\n\tMth::Vector\t\t*GetTranslation();\r\n\tint\t\t\t\tGetDma();\r\n\tMth::Vector\t\t*GetColour();\r\n\tCLightGroup\t\t*GetLights();\r\n\tbool\t\t\tIsExtended() const;\r\n\r\nprivate:\r\n\tvoid\t\t\tupdate_lights();\r\n\r\n\t// non-dma data\r\n\tMth::Matrix\t\tm_matrix;\r\n\tMth::Vector\t\tm_translation;\r\n\r\n\t// dma data... don't rearrange this part!\r\n\tuint32\t\t\tm_stmask;\r\n\tCLightGroup *\tmp_light_group;\r\n\tuint32\t\t\tm_stcycl;\r\n\tuint32\t\t\tm_unpack;\r\n\tuint128\t\t\tm_giftag;\r\n\tMth::Matrix\t\tm_localToViewport;\r\n\tMth::Vector\t\tm_texScale;\r\n\tMth::Vector\t\tm_reflVecsX;\r\n\tMth::Vector\t\tm_reflVecsY;\r\n\tMth::Vector\t\tm_reflVecsZ;\r\n\tMth::Vector\t\tm_lightVecsX;\r\n\tMth::Vector\t\tm_lightVecsY;\r\n\tMth::Vector\t\tm_lightVecsZ;\r\n\tMth::Vector\t\tm_ambientColour;\r\n\tMth::Vector\t\tm_lightColour0;\r\n\tMth::Vector\t\tm_lightColour1;\r\n\tMth::Vector\t\tm_lightColour2;\r\n\tMth::Vector\t\tm_texOffset;\r\n\r\n\t// keep the size a whole number of a quadwords\r\n};\r\n\r\n\r\ninline Mth::Matrix *CVu1Context::GetMatrix()\r\n{\r\n\treturn &m_matrix;\r\n}\r\n\r\n\r\ninline Mth::Vector *CVu1Context::GetTranslation()\r\n{\r\n\treturn &m_translation;\r\n}\r\n\r\ninline int CVu1Context::GetDma()\r\n{\r\n\treturn (int)&m_stmask;\r\n}\r\n\r\ninline CLightGroup *CVu1Context::GetLights()\r\n{\r\n\treturn mp_light_group;\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline void CVu1Context::SetExtended(bool yes)\r\n{\r\n\tif (yes)\r\n\t{\r\n\t\tm_stmask |= 1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_stmask &= ~1;\r\n\t}\r\n}\r\n\r\n\r\ninline bool CVu1Context::IsExtended() const\r\n{\r\n\treturn (m_stmask & 1) ? true : false;\r\n}\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace NxPs2\r\n\r\n#endif\t// __PLAT_NGPS__\r\n\r\n#endif\t// __NGPS_NX_VU1CONTEXT_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/PaletteGen.cpp",
    "content": "\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <gfx/ngps/PaletteGen.h>\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n#define\tRED\t1\r\n#define\tGREEN\t2\r\n#define BLUE\t3\r\n#define ALPHA\t4\r\n\r\n#define MAXDEPTH 5\r\n#define MAXCOLOR 256\r\n\r\n#define ColorRealLengthSq(a)\t((a)->red*(a)->red + (a)->green*(a)->green + (a)->blue*(a)->blue + (a)->alpha*(a)->alpha)\r\n#define\tColorRealFromColorInt(o,i)\t\t\t\t\t\t\t\t\t\t\\\r\n{                                                                        \\\r\n    (o)->red   =                                                         \\\r\n        (((float)(((i)->r))) * (   (float)((1.0/255.0))));           \\\r\n    (o)->green =                                                         \\\r\n        (((float)(((i)->g))) * ( (float)((1.0/255.0))));           \\\r\n    (o)->blue  =                                                         \\\r\n        (((float)(((i)->b))) * (  (float)((1.0/255.0))));           \\\r\n    (o)->alpha =                                                         \\\r\n        (((float)(((i)->a))) * ( (float)((1.0/255.0))));           \\\r\n}                                                                        \\\r\n\r\n#define ColorRealScale(o,a,scale)\t\t\t\t\t\t\t\t\t\t\\\r\n{                                                                        \\\r\n    (o)->red   = (((a)->red) * (   scale));                              \\\r\n    (o)->green = (((a)->green) * ( scale));                              \\\r\n    (o)->blue  = (((a)->blue) * (  scale));                              \\\r\n    (o)->alpha = (((a)->alpha) * ( scale));                              \\\r\n}                                                                        \\\r\n\r\n#define ColorRealAdd(o,a,b)                                        \\\r\n{                                                                        \\\r\n    (o)->red   = (((a)->red) + (   (b)->red));                           \\\r\n    (o)->green = (((a)->green) + ( (b)->green));                         \\\r\n    (o)->blue  = (((a)->blue) + (  (b)->blue));                          \\\r\n    (o)->alpha = (((a)->alpha) + ( (b)->alpha));                         \\\r\n}                                                                        \\\r\n\r\n#define ColorRealSub(o,a,b)                                        \\\r\n{                                                                        \\\r\n    (o)->red   = (((a)->red) - (   (b)->red));                           \\\r\n    (o)->green = (((a)->green) - ( (b)->green));                         \\\r\n    (o)->blue  = (((a)->blue) - (  (b)->blue));                          \\\r\n    (o)->alpha = (((a)->alpha) - ( (b)->alpha));                         \\\r\n}                                                                        \\\r\n\r\ntypedef uint32 OctantMap;\r\n\r\n/* local */\r\nstatic OctantMap    *p_splice = NULL;\r\n\r\n/*************************************************************************/\r\nstatic LeafNode    *\r\nInitLeaf(LeafNode * Leaf)\r\n{\r\n    Dbg_Assert( Leaf );\r\n\r\n    Leaf->palIndex = 0;\r\n    Leaf->weight = 0.0f;\r\n    Leaf->ac.red = 0.0f;\r\n    Leaf->ac.green = 0.0f;\r\n    Leaf->ac.blue = 0.0f;\r\n    Leaf->ac.alpha = 0.0f;\r\n    Leaf->m2 = 0.0f;\r\n    \r\n\treturn Leaf;\r\n}\r\n\r\n/*************************************************************************/\r\nstatic BranchNode  *\r\nInitBranch(BranchNode * Branch)\r\n{\r\n    int                 i;\r\n\r\n    Dbg_Assert( Branch );\r\n\r\n    for (i = 0; i < 16; i++)\r\n    {\r\n        Branch->dir[i] = (OctNode *)NULL;\r\n    }\r\n\r\n    return Branch;\r\n}\r\n\r\n/*************************************************************************/\r\nstatic OctNode     *\r\nCreateCube( void )\r\n{\r\n    OctNode            *cube;\r\n\r\n\tcube = (OctNode*) Mem::Calloc( 1, sizeof( OctNode ));\r\n    return(cube);\r\n}\r\n\r\n/*************************************************************************/\r\nstatic              OctantMap\r\nGetOctAdr(Image::RGBA * c)\r\n{\r\n    int                 cs = 8 - MAXDEPTH;\r\n\r\n    Dbg_Assert(c);\r\n\r\n    return((p_splice[c->r >> cs] << 3) | (p_splice[c->g >> cs] << 2) |\r\n             (p_splice[c->b >> cs] << 1) | (p_splice[c->a >> cs] << 0));\r\n}\r\n\r\n/*************************************************************************/\r\nstatic OctNode     *\r\nAllocateToLeaf(PalQuant * pq, OctNode * root, OctantMap Octs, int depth)\r\n{\r\n\r\n    Dbg_Assert(pq);\r\n    Dbg_Assert(root);\r\n\r\n    /* return leaf */\r\n    if (depth == 0)\r\n    {\r\n        return(root);\r\n    }\r\n\r\n    /* populate branch */\r\n    if (!root->Branch.dir[Octs & 15])\r\n    {\r\n        OctNode            *node;\r\n\r\n        node = CreateCube();//(pq->cubefreelist);\r\n        root->Branch.dir[Octs & 15] = node;\r\n        if (depth == 1)\r\n        {\r\n            InitLeaf(&node->Leaf);\r\n        }\r\n        else\r\n        {\r\n            InitBranch(&node->Branch);\r\n        }\r\n    }\r\n\r\n    return(AllocateToLeaf\r\n             (pq, root->Branch.dir[Octs & 15], Octs >> 4, depth - 1));\r\n}\r\n\r\n/*************************************************************************/\r\nvoid\r\nPalQuantAddImage(PalQuant *pq, uint8 *img, int width, int height, int image_bpp, float weight)\r\n{\r\n    int     i, size;//, stride;\r\n    //unsigned char\t\t*pixels;    \r\n\r\n    Dbg_Assert(pq);\r\n    Dbg_Assert(img);\r\n\r\n    //pixels = (unsigned char*) texture->buf;//GetTexelData( 0 );    \r\n\tsize = width * height;\r\n\r\n    switch (image_bpp / 8)\r\n    {\r\n\t\tcase 3:\r\n\t\t{\t\t\t\r\n#if 0\r\n\t\t\tImage::RGBA         color;\r\n            ColorReal         rColor;\r\n            OctNode            *leaf;\r\n            OctantMap           Octs;\r\n\r\n\t\t\tcolor24* colors= (color24*)img;\r\n\t\t\tfor( i = 0; i < size; i++ )\r\n\t\t\t{\r\n\t\t\t\tcolor.red = colors[i].r;\r\n\t\t\t\tcolor.green = colors[i].g;\r\n\t\t\t\tcolor.blue = colors[i].b;\r\n\t\t\t\tcolor.alpha = 255;\t\t\t\r\n\t\t\t\r\n\t\t\t\t/* build down to leaf */\r\n\t\t\t\tOcts = GetOctAdr(&color);\r\n\t\t\t\tleaf = AllocateToLeaf(pq, pq->root, Octs, MAXDEPTH);\r\n\r\n\t\t\t\tColorRealFromColorInt(&rColor, &color);\r\n\t\t\t\tleaf->Leaf.weight += weight;\r\n\t\t\t\tColorRealScale(&rColor, &rColor, weight);\r\n\t\t\t\tColorRealAdd(&leaf->Leaf.ac, &leaf->Leaf.ac,\r\n\t\t\t\t\t\t\t  &rColor);\r\n\t\t\t\tleaf->Leaf.m2 += weight*ColorRealLengthSq(&rColor);\r\n\t\t\t}\r\n#endif\r\n\t\t\tDbg_Assert(0);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 4:\r\n\t\t{\r\n\t\t\tImage::RGBA         color;\r\n            ColorReal         rColor;\r\n            OctNode            *leaf;\r\n            OctantMap           Octs;\r\n\r\n\t\t\tuint32* p_colors= (uint32*)img;\r\n\t\t\tfor( i = 0; i < size; i++ )\r\n\t\t\t{\r\n\t\t\t\tcolor = *((Image::RGBA *) &p_colors[i]);\r\n\t\t\t\r\n\t\t\t\t/* build down to leaf */\r\n\t\t\t\tOcts = GetOctAdr(&color);\r\n\t\t\t\tleaf = AllocateToLeaf(pq, pq->root, Octs, MAXDEPTH);\r\n\r\n\t\t\t\tColorRealFromColorInt(&rColor, &color);\r\n\t\t\t\tleaf->Leaf.weight += weight;\r\n\t\t\t\tColorRealScale(&rColor, &rColor, weight);\r\n\t\t\t\tColorRealAdd(&leaf->Leaf.ac, &leaf->Leaf.ac,\r\n\t\t\t\t\t\t\t  &rColor);\r\n\t\t\t\tleaf->Leaf.m2 += weight*ColorRealLengthSq(&rColor);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        default:\r\n\t\t\tbreak;\r\n    }    \r\n}\r\n\r\n/*************************************************************************/\r\n\r\n/*************************************************************************/\r\nstatic void\r\nassignindex(OctNode * root, Image::RGBA * origin, int depth, box * region,\r\n            int palIndex)\r\n{\r\n    int                 width, dr, dg, db, da, dR, dG, dB, dA;\r\n    int                 i;\r\n\r\n    Dbg_Assert(origin);\r\n    Dbg_Assert(region);\r\n\r\n    if (!root)\r\n        return;\r\n\r\n    width = 1 << depth;\r\n\r\n    dr = origin->r - region->col1.r;\r\n    dg = origin->g - region->col1.g;\r\n    db = origin->b - region->col1.b;\r\n    da = origin->a - region->col1.a;\r\n    if (dr >= 0 || dg >= 0 || db >= 0 || da >= 0)\r\n    {\r\n        return;\r\n    }\r\n\r\n    dR = region->col0.r - origin->r;\r\n    dG = region->col0.g - origin->g;\r\n    dB = region->col0.b - origin->b;\r\n    dA = region->col0.a - origin->a;\r\n    if (dR >= width || dG >= width || dB >= width || dA >= width)\r\n    {\r\n        return;\r\n    }\r\n\r\n    /* wholly inside region and a leaf? */\r\n    if (dr <= -width && dg <= -width && db <= -width && da <= -width)\r\n        if (dR <= 0 && dG <= 0 && dB <= 0 && dA <= 0)\r\n            if (depth == 0)\r\n            {\r\n                root->Leaf.palIndex = (unsigned char) palIndex;\r\n                return;\r\n            }\r\n\r\n    /* try children */\r\n    depth--;\r\n    for (i = 0; i < 16; i++)\r\n    {\r\n        Image::RGBA              suborigin;\r\n\r\n        suborigin.r = origin->r + (((i >> 3) & 1) << depth);\r\n        suborigin.g = origin->g + (((i >> 2) & 1) << depth);\r\n        suborigin.b = origin->b + (((i >> 1) & 1) << depth);\r\n        suborigin.a = origin->a + (((i >> 0) & 1) << depth);\r\n\r\n        assignindex(root->Branch.dir[i], &suborigin, depth, region, palIndex);\r\n    }    \r\n}\r\n\r\n/*************************************************************************/\r\n\r\n/* Assign palIndex to leaves */\r\nstatic void\r\nnAssign(int palIndex, OctNode * root, box * cube)\r\n{\r\n    Image::RGBA              origin;\r\n\r\n    Dbg_Assert(root);\r\n    Dbg_Assert(cube);\r\n\r\n    origin.r = 0;\r\n    origin.g = 0;\r\n    origin.b = 0;\r\n    origin.a = 0;\r\n    assignindex(root, &origin, MAXDEPTH, cube, palIndex);    \r\n}\r\n\r\n/*************************************************************************/\r\nstatic void\r\naddvolume(OctNode * root, Image::RGBA * origin, int depth, box * region,\r\n          LeafNode * volume)\r\n{\r\n    int                 width, dr, dg, db, da, dR, dG, dB, dA;\r\n    int                 i;\r\n\r\n    Dbg_Assert(origin);\r\n    Dbg_Assert(region);\r\n\r\n    if (!root)\r\n        return;\r\n\r\n    width = 1 << depth;\r\n\r\n    dr = origin->r - region->col1.r;\r\n    dg = origin->g - region->col1.g;\r\n    db = origin->b - region->col1.b;\r\n    da = origin->a - region->col1.a;\r\n    if (dr >= 0 || dg >= 0 || db >= 0 || da >= 0)\r\n    {\r\n        return;\r\n    }\r\n\r\n    dR = region->col0.r - origin->r;\r\n    dG = region->col0.g - origin->g;\r\n    dB = region->col0.b - origin->b;\r\n    dA = region->col0.a - origin->a;\r\n    if (dR >= width || dG >= width || dB >= width || dA >= width)\r\n    {\r\n        return;\r\n    }\r\n\r\n    /* wholly inside region? */\r\n    if (dr <= -width && dg <= -width && db <= -width && da <= -width)\r\n        if (dR <= 0 && dG <= 0 && dB <= 0 && dA <= 0)\r\n#ifndef CACHEWEIGHTS\r\n            if (depth == 0)    /* we need to visit each leaf */\r\n#endif\r\n            {\r\n                volume->weight += root->Leaf.weight;\r\n                ColorRealAdd(&volume->ac, &volume->ac, &root->Leaf.ac);\r\n                volume->m2 += root->Leaf.m2;\r\n                return;\r\n            }\r\n\r\n    /* try children */\r\n    depth--;\r\n    for (i = 0; i < 16; i++)\r\n    {\r\n        Image::RGBA              suborigin;\r\n\r\n        suborigin.r = origin->r + (((i >> 3) & 1) << depth);\r\n        suborigin.g = origin->g + (((i >> 2) & 1) << depth);\r\n        suborigin.b = origin->b + (((i >> 1) & 1) << depth);\r\n        suborigin.a = origin->a + (((i >> 0) & 1) << depth);\r\n\r\n        addvolume(root->Branch.dir[i], &suborigin, depth, region, volume);\r\n    }    \r\n}\r\n\r\n/*************************************************************************/\r\n\r\n/* Compute sum over a box of any given statistic */\r\nstatic LeafNode    *\r\nnVol(LeafNode * Vol, OctNode * root, box * cube)\r\n{\r\n    Image::RGBA              origin;\r\n\r\n    Dbg_Assert(root);\r\n    Dbg_Assert(cube);\r\n\r\n    origin.r = 0;\r\n    origin.g = 0;\r\n    origin.b = 0;\r\n    origin.a = 0;\r\n    InitLeaf(Vol);\r\n    addvolume(root, &origin, MAXDEPTH, cube, Vol);\r\n\r\n    return(Vol);\r\n}\r\n\r\n/*************************************************************************/\r\n\r\n/* Compute the weighted variance of a box */\r\n\r\n/* NB: as with the raw statistics, this is really the variance * size */\r\nstatic              float\r\nnVar(OctNode * root, box * cube)\r\n{\r\n    LeafNode            Node;\r\n\r\n    Dbg_Assert(root);\r\n    Dbg_Assert(cube);\r\n\r\n    nVol(&Node, root, cube);\r\n\r\n    return(Node.m2 - (ColorRealLengthSq(&Node.ac) / Node.weight));\r\n}\r\n\r\n/*************************************************************************/\r\n\r\n/* We want to minimize the sum of the variances of two subboxes.\r\n * The sum(c^2) terms can be ignored since their sum over both subboxes\r\n * is the same (the sum for the whole box) no matter where we split.\r\n * The remaining terms have a minus sign in the variance formula,\r\n * so we drop the minus sign and MAXIMIZE the sum of the two terms.\r\n */\r\nstatic              float\r\nnMaximize(OctNode * root, box * cube, int dir, int * cut,\r\n          LeafNode * whole)\r\n{\r\n    box                 infcube;\r\n    LeafNode            left, right;\r\n    float              maxsum, val, lastval;\r\n    int             i;\r\n\r\n    Dbg_Assert(root);\r\n    Dbg_Assert(cube);\r\n    Dbg_Assert(cut);\r\n    Dbg_Assert(whole);\r\n\r\n    lastval = maxsum = 0.0f;\r\n    *cut = -1;\r\n    infcube = *cube;\r\n    switch (dir)\r\n    {\r\n        case RED:\r\n            for (i = cube->col0.r; i < cube->col1.r; i++)\r\n            {\r\n                infcube.col1.r = (unsigned char) i;\r\n\r\n                nVol(&left, root, &infcube);\r\n                ColorRealSub(&right.ac, &whole->ac, &left.ac);\r\n                right.weight = whole->weight - left.weight;\r\n                if ((left.weight > 0.0f) && (right.weight > 0.0f))\r\n                {\r\n                    val = ColorRealLengthSq(&left.ac) / left.weight;\r\n                    val += ColorRealLengthSq(&right.ac) / right.weight;\r\n\r\n                    if (val > maxsum)\r\n                    {\r\n                        maxsum = val;\r\n                        *cut = i;\r\n                    }\r\n                    else if (val < lastval)\r\n                    {\r\n                        /* we've past the peak */\r\n                        break;\r\n                    }\r\n\r\n                    lastval = val;\r\n                }\r\n            }\r\n            break;\r\n\r\n        case GREEN:\r\n            for (i = cube->col0.g; i < cube->col1.g; i++)\r\n            {\r\n                infcube.col1.g = (unsigned char) i;\r\n\r\n                nVol(&left, root, &infcube);\r\n                ColorRealSub(&right.ac, &whole->ac, &left.ac);\r\n                right.weight = whole->weight - left.weight;\r\n                if ((left.weight > 0.0f) && (right.weight > 0.0f))\r\n                {\r\n                    val = ColorRealLengthSq(&left.ac) / left.weight;\r\n                    val += ColorRealLengthSq(&right.ac) / right.weight;\r\n\r\n                    if (val > maxsum)\r\n                    {\r\n                        maxsum = val;\r\n                        *cut = i;\r\n                    }\r\n                    else if (val < lastval)\r\n                    {\r\n                        /* we've past the peak */\r\n                        break;\r\n                    }\r\n\r\n                    lastval = val;\r\n                }\r\n            }\r\n            break;\r\n\r\n        case BLUE:\r\n            for (i = cube->col0.b; i < cube->col1.b; i++)\r\n            {\r\n                infcube.col1.b = (unsigned char) i;\r\n\r\n                nVol(&left, root, &infcube);\r\n                ColorRealSub(&right.ac, &whole->ac, &left.ac);\r\n                right.weight = whole->weight - left.weight;\r\n                if ((left.weight > 0.0f) && (right.weight > 0.0f))\r\n                {\r\n                    val = ColorRealLengthSq(&left.ac) / left.weight;\r\n                    val += ColorRealLengthSq(&right.ac) / right.weight;\r\n\r\n                    if (val > maxsum)\r\n                    {\r\n                        maxsum = val;\r\n                        *cut = i;\r\n                    }\r\n                    else if (val < lastval)\r\n                    {\r\n                        /* we've past the peak */\r\n                        break;\r\n                    }\r\n\r\n                    lastval = val;\r\n                }\r\n            }\r\n            break;\r\n\r\n        case ALPHA:\r\n            for (i = cube->col0.a; i < cube->col1.a; i++)\r\n            {\r\n                infcube.col1.a = (unsigned char) i;\r\n\r\n                nVol(&left, root, &infcube);\r\n                ColorRealSub(&right.ac, &whole->ac, &left.ac);\r\n                right.weight = whole->weight - left.weight;\r\n                if ((left.weight > 0.0f) && (right.weight > 0.0f))\r\n                {\r\n                    val = ColorRealLengthSq(&left.ac) / left.weight;\r\n                    val += ColorRealLengthSq(&right.ac) / right.weight;\r\n\r\n                    if (val > maxsum)\r\n                    {\r\n                        maxsum = val;\r\n                        *cut = i;\r\n                    }\r\n                    else if (val < lastval)\r\n                    {\r\n                        /* we've past the peak */\r\n                        break;\r\n                    }\r\n\r\n                    lastval = val;\r\n                }\r\n            }\r\n            break;\r\n    }\r\n\r\n    return(maxsum);\r\n}\r\n\r\n/*************************************************************************/\r\nstatic              bool\r\nnCut(OctNode * root, box * set1, box * set2)\r\n{\r\n    int             cutr, cutg, cutb, cuta;\r\n    float              maxr, maxg, maxb, maxa;\r\n    LeafNode            whole;\r\n\r\n    Dbg_Assert(root);\r\n    Dbg_Assert(set1);\r\n    Dbg_Assert(set2);\r\n\r\n    nVol(&whole, root, set1);\r\n    maxr = nMaximize(root, set1, RED, &cutr, &whole);\r\n    maxg = nMaximize(root, set1, GREEN, &cutg, &whole);\r\n    maxb = nMaximize(root, set1, BLUE, &cutb, &whole);\r\n    maxa = nMaximize(root, set1, ALPHA, &cuta, &whole);\r\n\r\n    /* did we find any splits? */\r\n    if ( (maxr == 0.0f) &&\r\n         (maxg == 0.0f) &&\r\n         (maxb == 0.0f) &&\r\n         (maxa == 0.0f) )\r\n    {\r\n        return false;\r\n    }\r\n\r\n    *set2 = *set1;\r\n\r\n    /* NEED TO CHECK FOR ALPHA TOO */\r\n\r\n    if (maxr >= maxg)\r\n    {\r\n        if (maxr >= maxb)\r\n        {\r\n            if (maxr >= maxa)\r\n            {\r\n                set1->col1.r = set2->col0.r = (unsigned char) cutr;\r\n            }\r\n            else\r\n            {\r\n                set1->col1.a = set2->col0.a = (unsigned char) cuta;\r\n            }\r\n        }\r\n        else\r\n        {\r\n            if (maxb >= maxa)\r\n            {\r\n                set1->col1.b = set2->col0.b = (unsigned char) cutb;\r\n            }\r\n            else\r\n            {\r\n                set1->col1.a = set2->col0.a = (unsigned char) cuta;\r\n            }\r\n        }\r\n    }\r\n    else if (maxg >= maxb)\r\n    {\r\n        if (maxg >= maxa)\r\n        {\r\n            set1->col1.g = set2->col0.g = (unsigned char) cutg;\r\n        }\r\n        else\r\n        {\r\n            set1->col1.a = set2->col0.a = (unsigned char) cuta;\r\n        }\r\n    }\r\n    else if (maxb >= maxa)\r\n    {\r\n        set1->col1.b = set2->col0.b = (unsigned char) cutb;\r\n    }\r\n    else\r\n    {\r\n        set1->col1.a = set2->col0.a = (unsigned char) cuta;\r\n    }\r\n\r\n\r\n    return true;\r\n}\r\n\r\n/*************************************************************************/\r\n#ifdef CACHEWEIGHTS\r\nstatic LeafNode    *\r\nCalcNodeWeights(OctNode * root, int depth)\r\n{\r\n    LeafNode           *Leaf;\r\n    int                 i;\r\n\r\n    Leaf = NULL;\r\n    if (root)\r\n    {\r\n        Leaf = &root->Leaf;\r\n\r\n        /* is it a branch? */\r\n        if (depth > 0)\r\n        {\r\n            InitLeaf(Leaf);\r\n            for (i = 0; i < 16; i++)\r\n            {\r\n                LeafNode           *SubNode =\r\n                    CalcNodeWeights(root->Branch.dir[i], depth - 1);\r\n\r\n                if (SubNode)\r\n                {\r\n                    Leaf->weight += SubNode->weight;\r\n                    ColorRealAdd(&Leaf->ac, &Leaf->ac, &SubNode->ac);\r\n                    Leaf->m2 += SubNode->m2;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    return(Leaf);\r\n}\r\n#endif\r\n\r\n/*************************************************************************/\r\nstatic int\r\nCountLeafs(OctNode * root, int depth)\r\n{\r\n    int                 i, n;\r\n\r\n    n = 0;\r\n    if (root)\r\n    {\r\n        /* is it a branch? */\r\n        if (depth > 0)\r\n        {\r\n            for (i = 0; i < 16; i++)\r\n            {\r\n                n += CountLeafs(root->Branch.dir[i], depth - 1);\r\n            }\r\n        }\r\n        else\r\n        {\r\n            n = 1;\r\n        }\r\n    }\r\n\r\n    return(n);\r\n}\r\n\r\n/*************************************************************************/\r\nstatic int\r\nCountNodes(OctNode * root, int depth)\r\n{\r\n    int                 i, n;\r\n\r\n    n = 0;\r\n    if (root)\r\n    {\r\n        n = 1;\r\n\r\n        /* is it a branch? */\r\n        if (depth > 0)\r\n        {\r\n            for (i = 0; i < 16; i++)\r\n            {\r\n                n += CountNodes(root->Branch.dir[i], depth - 1);\r\n            }\r\n        }\r\n    }\r\n\r\n    return(n);\r\n}\r\n\r\n/*************************************************************************/\r\n\r\n/* \r\n * Note the use of 255.9999f value when generating the scale variable.\r\n * This is used instead of 255.0f to prevent rounding errors.\r\n */\r\n\r\n#define node2pal(rgb, node)                                              \\\r\n{                                                                        \\\r\n    int             quantize;                                        \\\r\n    float              scale = ( ((node)->weight > 0) ?                 \\\r\n                                  (255.9999f / (node)->weight) :         \\\r\n                                  (float) 0 );                          \\\r\n                                                                         \\\r\n    quantize = (int) ((node)->ac.red * scale);                       \\\r\n    (rgb)->r = (unsigned char) quantize;                                     \\\r\n    quantize = (int) ((node)->ac.green * scale);                     \\\r\n    (rgb)->g = (unsigned char) quantize;                                   \\\r\n    quantize = (int) ((node)->ac.blue * scale);                      \\\r\n    (rgb)->b = (unsigned char) quantize;                                    \\\r\n    quantize = (int) ((node)->ac.alpha * scale);                     \\\r\n    (rgb)->a = (unsigned char) quantize;                                   \\\r\n}                                                                        \\\r\n\r\n/*************************************************************************/\r\nint\r\nPalQuantResolvePalette(Image::RGBA * palette, int maxcols, PalQuant * pq)\r\n{\r\n    int             numcols, uniquecols, i, k, next;\r\n    \r\n#if (defined(RWDEBUG))\r\n    if (256 < maxcols)\r\n    {\r\n        RWMESSAGE((\"256 < %d == maxcols\", (int) maxcols));\r\n    }\r\n#endif /* (defined(RWDEBUG)) */\r\n\r\n\r\n    Dbg_Assert(palette);\r\n    Dbg_Assert(maxcols <= 256);\r\n    Dbg_Assert(pq);\r\n\r\n    numcols = maxcols;\r\n    uniquecols = CountLeafs(pq->root, MAXDEPTH);\r\n    if (numcols > uniquecols)\r\n    {\r\n        numcols = uniquecols;\r\n    }\r\n\r\n#ifdef CACHEWEIGHTS\r\n    /* cache weightings at every node */\r\n    CalcNodeWeights(pq->root, MAXDEPTH);\r\n#endif\r\n\r\n    /* divide and conquer */\r\n    pq->Mcube[0].col0.r = 0;\r\n    pq->Mcube[0].col0.g = 0;\r\n    pq->Mcube[0].col0.b = 0;\r\n    pq->Mcube[0].col0.a = 0;\r\n    pq->Mcube[0].col1.r = 1 << MAXDEPTH;\r\n    pq->Mcube[0].col1.g = 1 << MAXDEPTH;\r\n    pq->Mcube[0].col1.b = 1 << MAXDEPTH;\r\n    pq->Mcube[0].col1.a = 1 << MAXDEPTH;\r\n    pq->Mvv[0] = nVar(pq->root, &pq->Mcube[0]);\r\n    for (i = 1; i < numcols; i++)\r\n    {\r\n        float               maxvar;\r\n\r\n        /* find best box to split */\r\n        next = -1;\r\n        maxvar = 0.0f;\r\n        for (k = 0; k < i; k++)\r\n        {\r\n            if (pq->Mvv[k] > maxvar)\r\n            {\r\n                maxvar = pq->Mvv[k];\r\n                next = k;\r\n            }\r\n        }\r\n\r\n        /* stop if we couldn't find a box to split */\r\n        if (next == -1)\r\n        {\r\n            break;\r\n        }\r\n\r\n        /* split box */\r\n        if (nCut(pq->root, &pq->Mcube[next], &pq->Mcube[i]))\r\n        {\r\n            /* volume test ensures we won't try to cut one-cell box */\r\n            pq->Mvv[next] = nVar(pq->root, &pq->Mcube[next]);\r\n            pq->Mvv[i] = nVar(pq->root, &pq->Mcube[i]);\r\n        }\r\n        else\r\n        {\r\n            /* don't try to split this box again */\r\n            pq->Mvv[next] = 0.0f;\r\n            i--;\r\n        }\r\n    }\r\n\r\n    /* extract the new palette */\r\n    for (k = 0; k < maxcols; k++)\r\n    {\r\n        if (k < numcols)\r\n        {\r\n            LeafNode            Node;\r\n\r\n            nAssign(k, pq->root, &pq->Mcube[k]);\r\n            nVol(&Node, pq->root, &pq->Mcube[k]);\r\n            node2pal(&palette[k], &Node);\r\n        }\r\n        else\r\n        {\r\n            palette[k].r = 0;\r\n            palette[k].g = 0;\r\n            palette[k].b = 0;\r\n            palette[k].a = 0;\r\n        }\r\n    }\r\n\r\n    return(numcols);\r\n}\r\n\r\n#if 0\r\n/*************************************************************************/\r\nstatic              unsigned char\r\nGetIndex(OctNode * root, OctantMap Octs, int depth)\r\n{\r\n    unsigned char             result;\r\n\r\n    Dbg_Assert(root);\r\n\r\n    if (depth == 0)\r\n    {\r\n        result = root->Leaf.palIndex;\r\n    }\r\n    else\r\n    {\r\n        result = GetIndex(root->Branch.dir[Octs & 15], Octs >> 4, depth - 1);\r\n    }\r\n\r\n    return(result);\r\n}\r\n#endif\r\n\r\n/*************************************************************************/\r\nbool\r\nPalQuantInit(PalQuant * pq)\r\n{\r\n    int                 i, j, maxval;\r\n\r\n    Dbg_Assert(pq);\r\n    Dbg_Assert(!p_splice);\r\n\r\n\tp_splice = (OctantMap *) Mem::Malloc(sizeof(OctantMap) * MAXCOLOR);\r\n\r\n    /* lookup mapping (8) bit-patterns to every 4th bit b31->b00 (least to most) */\r\n    maxval = 1 << MAXDEPTH;\r\n    for (i = 0; i < maxval; i++)\r\n    {\r\n        OctantMap           mask = 0;\r\n\r\n        for (j = 0; j < MAXDEPTH; j++)\r\n        {\r\n            mask |= (i & (1 << j)) ? (1 << ((MAXDEPTH - 1 - j) * 4)) : 0;\r\n        }\r\n        p_splice[i] = mask;\r\n    }\r\n\r\n    pq->Mcube = (box *) Mem::Calloc(sizeof(box), MAXCOLOR);\r\n    pq->Mvv = (float *) Mem::Calloc(sizeof(float), MAXCOLOR);\r\n\r\n    pq->root = CreateCube();\r\n    InitBranch(&pq->root->Branch);\r\n\r\n    return true;\r\n}\r\n\r\n/*************************************************************************/\r\nstatic void\r\nDeleteOctTree(PalQuant * pq, OctNode * root, int depth)\r\n{\r\n    int                 i;\r\n\r\n    Dbg_Assert(pq);\r\n\r\n    if (root)\r\n    {\r\n        /* is it a branch? */\r\n        if (depth > 0)\r\n        {\r\n            for (i = 0; i < 16; i++)\r\n            {\r\n                DeleteOctTree(pq, root->Branch.dir[i], depth - 1);\r\n            }\r\n        }\r\n\r\n\t\tMem::Free(root);\r\n    }\r\n}\r\n\r\n/*************************************************************************/\r\nvoid\r\nPalQuantTerm(PalQuant * pq)\r\n{\r\n\r\n    Dbg_Assert(pq);\r\n    Dbg_Assert(p_splice);\r\n\r\n\r\n    DeleteOctTree(pq, pq->root, MAXDEPTH);\r\n    pq->root = (OctNode *)NULL;\r\n\r\n    Mem::Free( pq->Mvv );\r\n    Mem::Free( pq->Mcube );\r\n\tMem::Free( p_splice );\r\n\tp_splice = NULL;\r\n}\r\n\r\n/*************************************************************************/\r\nvoid GeneratePalette( Image::RGBA *p_palette, uint8* src_image, int width, int height, int image_bpp, int max_colors )\r\n{\r\n\tint num_colors;\r\n\tPalQuant pal_quant;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n\tif( !PalQuantInit( &pal_quant ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tPalQuantAddImage( &pal_quant, src_image, width, height, image_bpp, 1 );\t\r\n\t\r\n\t// Create a palette for all of the mips\r\n\tnum_colors = PalQuantResolvePalette( p_palette, max_colors, &pal_quant );\r\n\r\n\t// And swizzle for the PS2\r\n\tImage::RGBA temp_rgba;\r\n\tfor (int j=0; j<256; j+=32)\r\n\t{\r\n\t\tfor (int k=0; k<8; k++)\r\n\t\t{\r\n\t\t\ttemp_rgba = p_palette[j+k+8];\r\n\t\t\tp_palette[j+k+8] = p_palette[j+k+16];\r\n\t\t\tp_palette[j+k+16] = temp_rgba;\r\n\t\t}\r\n\t}\r\n\r\n\t\r\n\tPalQuantTerm( &pal_quant );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/PaletteGen.h",
    "content": "#ifndef __NX_NGPS_PALETTEGEN_H__\r\n#define __NX_NGPS_PALETTEGEN_H__\r\n\r\n#include <gfx/image/imagebasic.h>\r\n\r\n/* caching weights at every node improves performance at expense of memory */\r\n#define CACHEWEIGHTSx\r\n\r\nnamespace Nx\r\n{\r\n\r\n/****************************************************************************\r\n Global Types\r\n */\r\n\r\ntypedef struct\r\n{\r\n\tfloat\tred;\r\n\tfloat\tgreen;\r\n\tfloat\tblue;\r\n\tfloat\talpha;\r\n} ColorReal;\r\n\r\ntypedef struct\r\n{\r\n\tImage::RGBA col0;\t/* min value, inclusive */\r\n\tImage::RGBA col1;\t/* max value, exclusive */\r\n} box;\r\n\r\n\r\n\r\n#ifdef CACHEWEIGHTS\r\ntypedef struct OctNode OctNode;\r\n#else\r\ntypedef union OctNode OctNode;\r\n#endif\r\n\r\ntypedef struct LeafNode LeafNode;\r\nstruct LeafNode\r\n{\r\n\tfloat weight;\r\n\tColorReal ac;\r\n\tfloat m2;\r\n\tunsigned char palIndex;\r\n};\r\n\r\ntypedef struct BranchNode BranchNode;\r\nstruct BranchNode\r\n{\r\n\tOctNode *dir[16];\r\n};\r\n\r\n#ifdef CACHEWEIGHTS\r\nstruct OctNode\r\n#else\r\nunion OctNode\r\n#endif\r\n{\r\n\tLeafNode   Leaf;\r\n\tBranchNode Branch;\r\n};\r\n\r\n/* working data */\r\ntypedef struct\r\n{\r\n\tbox *Mcube;\r\n\tfloat *Mvv;\r\n\tOctNode *root;\t\r\n}  PalQuant;\r\n\r\n/****************************************************************************\r\n Function prototypes\r\n */\r\n\r\nbool PalQuantInit(PalQuant *pq);\r\nvoid PalQuantTerm(PalQuant *pq);\r\n\r\nvoid PalQuantAddImage(PalQuant *pq, uint8 *img, int width, int height, int image_bpp, float weight);\r\nint PalQuantResolvePalette(unsigned char *palette, int maxcols, PalQuant *pq, int pbpp);\r\nvoid GeneratePalette( Image::RGBA *p_palette, uint8* src_image, int width, int height, int image_bpp, int max_colors );\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\t// __NX_NGPS_PALETTEGEN_H__\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxAnimCache.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_NxAnimCache.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  5/06/2002\r\n//****************************************************************************\r\n\r\n#include <gfx/ngps/p_nxanimcache.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2AnimCache::CPs2AnimCache( int lookupTableSize ) : CAnimCache( lookupTableSize )\r\n{\r\n\t// Machine specific code here ............\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2AnimCache::~CPs2AnimCache()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxAnimCache.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_NxAnimCache.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  5/06/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NXANIMCACHE_H__\r\n#define\t__GFX_P_NXANIMCACHE_H__\r\n    \r\n#include <gfx/nxanimcache.h>\r\n\r\nnamespace Nx\r\n{\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CGeom\r\n    \r\nclass CPs2AnimCache : public CAnimCache\r\n{\r\n                                      \r\npublic:\r\n\t\t\t\t\t\tCPs2AnimCache( int lookupTableSize );\r\n\tvirtual \t\t\t~CPs2AnimCache();\r\n\r\nprivate:\t\t\t\t// It's all private, as it is machine specific\r\n};\r\n\r\n} // Nx\r\n\r\n#endif \r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxFont.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxFont.cpp\r\n\r\n#include \t\"Gfx/NGPS/p_NxFont.h\"\r\n#include \t\"Gfx/NGPS/p_NxWin2D.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CFont\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Font::CPs2Font() : mp_plat_font(NULL)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Font::~CPs2Font()\r\n{\r\n\tif (mp_plat_font)\r\n\t{\r\n\t\tplat_unload();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCPs2Font::plat_load(const char *filename)\r\n{\r\n\tmp_plat_font = NxPs2::LoadFont(filename);\r\n\r\n\treturn (mp_plat_font != NULL);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Font::plat_set_spacings(int charSpacing, int spaceSpacing)\r\n{\r\n\tmp_plat_font->mCharSpacing = charSpacing;\r\n\tif (spaceSpacing > 0)\r\n\t\tmp_plat_font->mSpaceSpacing = spaceSpacing;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Font::plat_set_rgba_table(Image::RGBA *pTab)\r\n{\r\n\tfor (int i = 0; i < 16; i++)\r\n\t\tmp_plat_font->mRGBATab[i] = *((uint32 *) &pTab[i]);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Font::plat_mark_as_button_font(bool isButton)\r\n{\r\n\tNxPs2::pButtonsFont = (isButton) ? mp_plat_font : NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCPs2Font::plat_unload()\r\n{\r\n\tNxPs2::UnloadFont(mp_plat_font);\r\n\tmp_plat_font = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\t\tCPs2Font::plat_get_default_height() const\r\n{\r\n\tDbg_Assert(mp_plat_font);\r\n\r\n\treturn mp_plat_font->GetDefaultHeight();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\t\tCPs2Font::plat_get_default_base() const\r\n{\r\n\tDbg_Assert(mp_plat_font);\r\n\r\n\treturn mp_plat_font->GetDefaultBase();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCPs2Font::plat_query_string(char *String, float &width, float &height) const\r\n{\r\n\tDbg_Assert(mp_plat_font);\r\n\r\n\tmp_plat_font->QueryString(String, width, height);\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of the CText\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Text::CPs2Text(CWindow2D *p_window) : CText(p_window)\r\n{\r\n\tmp_plat_text = new NxPs2::SText();\r\n\r\n\tplat_initialize();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Text::~CPs2Text()\r\n{\r\n\tif (mp_plat_text)\r\n\t{\r\n\t\tdelete mp_plat_text;\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCPs2Text::plat_initialize()\r\n{\r\n\tplat_update_engine();\r\n\tplat_update_priority();\r\n\tplat_update_hidden();\r\n\tplat_update_window();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCPs2Text::plat_update_hidden()\r\n{\r\n\tmp_plat_text->SetHidden(m_hidden);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCPs2Text::plat_update_engine()\r\n{\r\n\tCPs2Font *p_ps2_font = static_cast<CPs2Font *>(mp_font);\r\n\r\n\tmp_plat_text->mp_string\t= m_string;\r\n\tif (p_ps2_font) {\r\n\t\tmp_plat_text->mp_font\t= p_ps2_font->GetEngineFont();\r\n\t}\r\n\r\n\tmp_plat_text->m_xpos\t= m_xpos;\r\n\tmp_plat_text->m_ypos\t= m_ypos;\r\n\tmp_plat_text->m_xscale\t= m_xscale;\r\n\tmp_plat_text->m_yscale\t= m_yscale;\r\n\tmp_plat_text->m_rgba\t= *((uint32 *) &m_rgba);\r\n\tmp_plat_text->m_color_override = m_color_override;\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCPs2Text::plat_update_priority()\r\n{\r\n\t// Update draw list\r\n\tif (m_use_zbuffer)\r\n\t{\r\n\t\tmp_plat_text->SetZValue((uint32) m_zvalue);\r\n\t} else {\r\n\t\tmp_plat_text->SetPriority(m_priority);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCPs2Text::plat_update_window()\r\n{\r\n\tCPs2Window2D *p_ps2_window = static_cast<CPs2Window2D *>(mp_window);\r\n\r\n\tif (p_ps2_window)\r\n\t{\r\n\t\tmp_plat_text->SetScissorWindow(p_ps2_window->GetEngineWindow());\r\n\t} else {\r\n\t\tmp_plat_text->SetScissorWindow(NULL);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCTextMan::s_plat_alloc_text_pool()\r\n{\r\n   \tCPs2Text *p_text_array = new CPs2Text[vMAX_TEXT_INSTANCES];\r\n\r\n\tfor (int i = 0; i < vMAX_TEXT_INSTANCES; i++)\r\n\t{\r\n//\t   \tCPs2Text *p_text = new CPs2Text(NULL);\r\n\t   \tCPs2Text *p_text = &p_text_array[i];\r\n\t\tp_text->mp_next = sp_dynamic_text_list;\r\n\t\tsp_dynamic_text_list = p_text;\r\n\t}\r\n}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxFont.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxFont.h\r\n\r\n#ifndef\t__GFX_P_NX_FONT_H__\r\n#define\t__GFX_P_NX_FONT_H__\r\n\r\n#include \t\"Gfx/NxFont.h\"\r\n#include \t\"Gfx/NGPS/NX/chars.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CFont\r\nclass\tCPs2Font : public CFont\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCPs2Font();\r\n\tvirtual\t\t\t\t\t\t~CPs2Font();\r\n\r\n\tNxPs2::SFont *\t\t\t\tGetEngineFont() const;\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\tvirtual\tbool\t\t\t\tplat_load(const char *filename);\r\n\tvirtual void\t\t\t\tplat_set_spacings(int charSpacing, int spaceSpacing);\r\n\tvirtual void\t\t\t\tplat_set_rgba_table(Image::RGBA *pTab);\r\n\tvirtual void \t\t\t\tplat_mark_as_button_font(bool isButton);\r\n\tvirtual void\t\t\t\tplat_unload();\r\n\r\n\tvirtual\tuint32\t\t\t\tplat_get_default_height() const;\r\n\tvirtual\tuint32\t\t\t\tplat_get_default_base() const;\r\n\tvirtual void\t\t\t\tplat_query_string(char *String, float &width, float &height) const;\r\n\r\n\t// Machine specific members\r\n\tNxPs2::SFont *\t\t\t\tmp_plat_font;\t\t// Pointer to engine font\r\n};\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of the CText\r\nclass\tCPs2Text : public CText\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCPs2Text(CWindow2D *p_window = NULL);\r\n\tvirtual\t\t\t\t\t\t~CPs2Text();\r\n\r\nprivate:\r\n\t//\r\n\tvirtual void\t\t\t\tplat_initialize();\r\n\r\n\tvirtual void\t\t\t\tplat_update_hidden();\t\t// Tell engine of update\r\n\tvirtual void\t\t\t\tplat_update_engine();\t\t// Update engine primitives\r\n\tvirtual void\t\t\t\tplat_update_priority();\r\n\tvirtual void\t\t\t\tplat_update_window();\r\n\r\n\t// Machine specific members\r\n\tNxPs2::SText *\t\t\t\tmp_plat_text;\t\t// Pointer to engine text\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline NxPs2::SFont *\t\tCPs2Font::GetEngineFont() const\r\n{\r\n\treturn mp_plat_font;\r\n}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxFontMan.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxFontMan.cpp - PS2 platform specific interface to the Font Manager\r\n//\r\n// This is PS2 SPECIFIC!!!!!!  So might get a bit messy\r\n//\r\n\r\n#include\t\"gfx\\nx.h\"\r\n#include\t\"gfx\\NxFontMan.h\"\r\n#include\t\"gfx\\NGPS\\p_NxFont.h\"\r\n\r\n#include \t\"gfx\\ngps\\nx\\chars.h\"\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCFont\t*\tCFontManager::s_plat_load_font(const char *pName)\r\n{\r\n\tCPs2Font *p_new_font;\r\n\r\n\tp_new_font = new CPs2Font;\r\n\tp_new_font->Load(pName);\r\n\r\n\treturn p_new_font;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCFontManager::s_plat_unload_font(CFont *pFont)\r\n{\r\n\tpFont->Unload();\r\n}\r\n\r\n} \r\n \r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxGeom.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxGeom.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  3/4/2002\r\n//****************************************************************************\r\n\r\n#include <gfx/ngps/p_nxgeom.h>\r\n\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/symboltable.h>\r\n\t\t\t\t\t\t\t\t\r\n#include <gfx/skeleton.h>\r\n#include <gfx/ngps/p_nxlight.h>\r\n#include <gfx/ngps/p_nxmesh.h>\r\n#include <gfx/ngps/p_nxmodel.h>\r\n#include <gfx/ngps/p_nxscene.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n#include <gfx/ngps/nx/geomnode.h>\r\n#include <gfx/ngps/nx/instance.h>\r\n#include <gfx/ngps/nx/group.h>\r\n#include <gfx/ngps/nx/geomnode.h>\r\n\r\n#include <gel/collision/collision.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Geom::CPs2Geom()\r\n{\r\n\t// Machine specific code here ............\r\n\tmp_oldInstance = NULL;\r\n\tmp_instance = NULL;\r\n\tmp_matrices = NULL;\r\n\tm_rootMatrix.Ident();\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Geom::~CPs2Geom()\r\n{\r\n\tif ( mp_oldInstance != NULL )\r\n\t{\r\n\t\tdelete mp_oldInstance;\r\n\t\tmp_oldInstance = NULL;\r\n\t}\r\n\r\n\tif ( mp_instance != NULL )\r\n\t{\r\n\t\tif ( m_cloned == vINSTANCE )\r\n\t\t{\r\n\t\t\tmp_instance->DeleteInstance();\r\n\t\t}\r\n\t\telse if ( m_cloned == vCOPY )\r\n\t\t{\r\n\t\t\tmp_instance->DeleteCopy();\r\n\t\t}\r\n\t\tmp_instance = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPs2Geom::plat_load_geom_data(CMesh* pMesh, CModel* pModel, bool color_per_material)\r\n{\r\n\tint numBones;\r\n\tnumBones = pModel->GetNumBones();\r\n\r\n\tMth::Matrix temp;\r\n\ttemp.Identity();\r\n\tDbg_Assert( mp_oldInstance == NULL );\r\n\r\n\t// attempting to move skins over to .geom.ps2\r\n\tmp_matrices = ((CPs2Model*)pModel)->GetMatrices();\r\n    if ( ((CPs2Mesh*)pMesh)->GetGeomNode() )\r\n\t{\r\n\t\tif ( numBones )\r\n\t\t{\r\n\t\t\tmp_instance = ((CPs2Mesh*)pMesh)->GetGeomNode()->CreateInstance( &m_rootMatrix, numBones, (Mth::Matrix *)mp_matrices );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_instance = ((CPs2Mesh*)pMesh)->GetGeomNode()->CreateInstance( &m_rootMatrix );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Assert( pMesh );\r\n\t\tDbg_Assert( pMesh->GetTextureDictionary() );\r\n\t\tNxPs2::sScene* pScene = ((Nx::CPs2TexDict*)pMesh->GetTextureDictionary())->GetEngineTextureDictionary();\r\n\t\tDbg_Assert( pScene );\r\n\r\n\t\tif ( numBones )\r\n\t\t{\r\n\t\t\tmp_oldInstance = new NxPs2::CInstance(pScene, temp, color_per_material, numBones, mp_matrices );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_oldInstance = new NxPs2::CInstance(pScene, temp, color_per_material);\r\n\t\t}\r\n\t}\r\n\r\n\t// remember the source mesh, so that we can do poly-hiding on it\r\n\tmp_sourceMesh = (CPs2Mesh*)pMesh;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_finalize()\r\n{\r\n\tif (mp_oldInstance)\r\n\t{\r\n\t\t// only supported on old-style instances\r\n\t\tmp_oldInstance->SqueezeADC();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom *\tCPs2Geom::plat_clone(bool instance, CScene* pDestScene)\r\n{\r\n\tDbg_MsgAssert(mp_oldInstance == NULL, (\"Wrong version of CPs2Geom::plat_clone() for CInstances\"));\r\n\tDbg_MsgAssert(mp_matrices == NULL, (\"Wrong version of CPs2Geom::plat_clone() for matrix arrays\"));\r\n\r\n\tCPs2Scene *p_ps2_dest_scene = static_cast<CPs2Scene *>(pDestScene);\r\n\tNxPs2::CGeomNode *p_scene_geom = (p_ps2_dest_scene) ? p_ps2_dest_scene->GetEngineCloneScene() : NULL;\r\n\r\n\t// Copy into new sector\r\n\tCPs2Geom *p_new_geom = new CPs2Geom(*this);\r\n\r\n\t// Copy engine data\r\n\tif (p_new_geom && mp_instance)\r\n\t{\r\n\t\tif (instance)\r\n\t\t{\r\n\t\t\tp_new_geom->mp_instance = mp_instance->CreateInstance(&p_new_geom->m_rootMatrix, p_scene_geom);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_new_geom->mp_instance = mp_instance->CreateCopy(p_scene_geom);\r\n\t\t\t//p_new_geom->mp_instance->SetMatrix(&p_new_geom->m_rootMatrix);\r\n\t\t}\r\n\t}\r\n\r\n\treturn p_new_geom;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom *\tCPs2Geom::plat_clone(bool instance, CModel* pDestModel)\r\n{\r\n\tDbg_MsgAssert(mp_instance == NULL, (\"Wrong version of CPs2Geom::plat_clone() for CGeomNodes\"));\r\n\tDbg_Assert(mp_oldInstance);\r\n\r\n\t// Copy into new geom\r\n\tCPs2Geom *p_new_geom = new CPs2Geom(*this);\r\n\r\n\tDbg_Assert(p_new_geom);\r\n\r\n\tint numBones;\r\n\tnumBones = pDestModel->GetNumBones();\r\n\r\n\tMth::Matrix temp;\r\n\ttemp.Identity();\r\n\r\n\tp_new_geom->mp_matrices = ((CPs2Model*)pDestModel)->GetMatrices();\r\n\r\n\tNxPs2::sScene* pScene = mp_oldInstance->GetScene();\r\n\tDbg_Assert( pScene );\r\n\r\n\tif ( numBones )\r\n\t{\r\n\t\tp_new_geom->mp_oldInstance = new NxPs2::CInstance(pScene, temp, mp_oldInstance->HasColorPerMaterial(), numBones, p_new_geom->mp_matrices );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_new_geom->mp_oldInstance = new NxPs2::CInstance(pScene, temp, mp_oldInstance->HasColorPerMaterial());\r\n\t}\r\n\r\n\tDbg_Assert(p_new_geom->mp_oldInstance);\r\n\r\n\t// Copy the colors from instance\r\n\tif (mp_oldInstance->HasColorPerMaterial())\r\n\t{\r\n\t\tint num_colors = mp_oldInstance->GetScene()->NumMeshes;\r\n\t\tfor (int i = 0; i < num_colors; i++)\r\n\t\t{\r\n\t\t\tp_new_geom->mp_oldInstance->SetMaterialColorByIndex(i, mp_oldInstance->GetMaterialColorByIndex(i));\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_new_geom->mp_oldInstance->SetColor(mp_oldInstance->GetColor());\r\n\t}\r\n\r\n\treturn p_new_geom;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CPs2Geom::plat_get_checksum()\r\n{\r\n\tDbg_Assert(mp_instance);\r\n\r\n\treturn mp_instance->GetChecksum();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_set_color(Image::RGBA rgba)\r\n{\r\n\t// Engine call here\r\n\tif ( mp_instance )\r\n\t{\r\n\t\tmp_instance->SetColored(true);\r\n//\t\tprintf( \"Color 0x%x\\n\", *((uint32 *) &rgba ));\r\n\t\tmp_instance->SetColor(*((uint32 *) &rgba));\r\n\t}\r\n\telse if (mp_oldInstance)\r\n\t{\r\n\t\tif (mp_oldInstance->HasColorPerMaterial())\r\n\t\t{\r\n\t\t\tfor (int i = 0; i < mp_oldInstance->GetScene()->NumMeshes; i++)\r\n\t\t\t{\r\n\t\t\t\tmp_oldInstance->SetMaterialColorByIndex(i, *((uint32 *) &rgba));\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_oldInstance->SetColor(*((uint32 *) &rgba));\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA CPs2Geom::plat_get_color() const\r\n{\r\n\t// Engine call here\r\n\tif ( mp_instance && mp_instance->IsColored() )\r\n\t{\r\n\t\tuint32 raw_data = mp_instance->GetColor();\r\n\t\treturn *((Image::RGBA *) &raw_data);\r\n\t}\r\n\telse if (mp_oldInstance)\r\n\t{\r\n\t\tuint32 raw_data = mp_oldInstance->GetColor();\r\n\t\treturn *((Image::RGBA *) &raw_data);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn Image::RGBA(128, 128, 128, 128);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_clear_color()\r\n{\r\n\t// Engine call here\r\n\tif ( mp_instance )\r\n\t{\r\n\t\tmp_instance->SetColored(false);\r\n\t} else {\r\n\t\t// Set to white\r\n\t\tplat_set_color(Image::RGBA(128, 128, 128, 128));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCPs2Geom::plat_set_material_color(uint32 mat_checksum, int pass, Image::RGBA rgba)\r\n{\r\n\tif (mp_oldInstance)\r\n\t{\r\n\t\tif (mp_oldInstance->HasColorPerMaterial())\r\n\t\t{\r\n\t\t\tmp_oldInstance->SetMaterialColor(mat_checksum, pass, *((uint32 *) &rgba));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n//\t\t\tDbg_Message( \"%s %d doesn't have multicolor set\", Script::FindChecksumName(mat_checksum), pass );\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Trying to set the material color on a Geom that doesn't support it\"));\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\tCPs2Geom::plat_get_material_color(uint32 mat_checksum, int pass)\r\n{\r\n\tif (mp_oldInstance && mp_oldInstance->HasColorPerMaterial())\r\n\t{\r\n\t\tuint32 raw_data = mp_oldInstance->GetMaterialColor(mat_checksum, pass);\r\n\t\treturn *((Image::RGBA *) &raw_data);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Trying to get the material color on a Geom that doesn't support it\"));\r\n\t\treturn Image::RGBA(128, 128, 128, 128);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_set_visibility(uint32 mask)\r\n{\r\n\t// Engine call here\r\n\tif (mp_instance)\r\n\t{\r\n\t\tmp_instance->SetVisibility(mask & 0xFF);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CPs2Geom::plat_get_visibility() const\r\n{\r\n\t// Engine call here\r\n\tif ( mp_instance )\r\n\t{\r\n\t\treturn mp_instance->GetVisibility() | 0xFFFFFF00;\t\t// To keep format compatible\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_set_active( bool active )\r\n{\r\n\tif ( mp_oldInstance )\r\n\t{\r\n\t\tif ( active != mp_oldInstance->IsActive() )\r\n\t\t{\r\n\t\t\tmp_oldInstance->SetActive( active );\r\n\t\t}\r\n\t}\r\n\r\n\t// New engine\r\n\tif ( mp_instance )\r\n\t{\r\n\t\tif ( active != mp_instance->IsActive() )\r\n\t\t{\r\n\t\t\tmp_instance->SetActive( active );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPs2Geom::plat_is_active() const\r\n{\r\n\tif ( mp_instance )\r\n\t{\r\n\t\treturn mp_instance->IsActive();\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::CBBox & CPs2Geom::plat_get_bounding_box() const\r\n{\r\n#if 0\t// Enable this after THPS4 and do something about needing a static\r\n\tif ( mp_instance )\r\n\t{\r\n\t\tstatic Mth::CBBox bbox;\r\n\t\tbbox = mp_instance->GetBoundingBox();\r\n\t\treturn bbox;\r\n\t} \r\n\telse\r\n#endif\r\n\t{\r\n\t\t// Garrett: TODO: change to renderable bounding box\r\n\t\tDbg_Assert(mp_coll_tri_data);\r\n\t\treturn mp_coll_tri_data->GetBBox();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector CPs2Geom::plat_get_bounding_sphere() const\r\n{\r\n\tif ( mp_instance )\r\n\t{\r\n\t\t// CGeomNode-style\r\n\t\treturn mp_instance->GetBoundingSphere();\r\n\t}\r\n\telse if ( mp_oldInstance )\r\n\t{\r\n\t\t// CInstance-style\r\n\t\treturn mp_oldInstance->GetBoundingSphere();\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn Mth::Vector(0.0f, 0.0f, 0.0f, 1.0e+10f);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_set_bounding_sphere( const Mth::Vector& boundingSphere )\r\n{\r\n\tif ( mp_instance )\r\n\t{\r\n\t\t// CGeomNode-style\r\n\t\tmp_instance->SetBoundingSphere( boundingSphere[X], boundingSphere[Y], boundingSphere[Z], boundingSphere[W] );\r\n\t}\r\n\telse if ( mp_oldInstance )\r\n\t{\r\n\t\t// CInstance-style\r\n\t\tmp_oldInstance->SetBoundingSphere( boundingSphere[X], boundingSphere[Y], boundingSphere[Z], boundingSphere[W] );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Shouldn't get here\" ) );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_set_world_position(const Mth::Vector& pos)\r\n{\r\n\t// Garrett: we may need to do this in integer format instead to make it lossless\r\n\tMth::Vector delta_pos(pos - m_rootMatrix[W]);\r\n\r\n\t// Set values\r\n\tm_rootMatrix[W][X] = pos[X];\r\n\tm_rootMatrix[W][Y] = pos[Y];\r\n\tm_rootMatrix[W][Z] = pos[Z];\t\r\n\t//m_rootMatrix[W][W] = 1.0f;\r\n\r\n\t// Engine call here\r\n\tif (m_cloned != vCOPY)\r\n\t{\r\n\t\tupdate_engine_matrix();\r\n\t} else {\r\n\t\tmp_instance->Translate(delta_pos);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\tCPs2Geom::plat_get_world_position() const\r\n{\r\n\treturn m_rootMatrix[W];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_set_orientation(const Mth::Matrix& orient)\r\n{\r\n\t// Set values\r\n\tm_rootMatrix[X] = orient[X];\r\n\tm_rootMatrix[Y] = orient[Y];\r\n\tm_rootMatrix[Z] = orient[Z];\r\n\r\n\t// Engine call here\r\n\tif (m_cloned != vCOPY)\r\n\t{\r\n\t\tupdate_engine_matrix();\r\n\t} else {\r\n\t\tDbg_MsgAssert(0, (\"Don't call SetOrientation() on a CGeom copy\"));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Matrix &\tCPs2Geom::plat_get_orientation() const\r\n{\r\n\tDbg_MsgAssert(0, (\"CPs2Geom::plat_get_orientation() not implemented yet\"));\r\n\treturn m_rootMatrix;\t\t\t// This is not correct\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_rotate_y(Mth::ERot90 rot)\r\n{\r\n\t// Engine call here\r\n\t// Garrett: TEMP just set the world matrix\r\n\tMth::Matrix orig_rot_mat(m_rootMatrix), rot_mat;\r\n\tfloat rad = (float) ((int) rot) * (Mth::PI * 0.5f);\r\n\tCreateRotateYMatrix(rot_mat, rad);\r\n\r\n\torig_rot_mat[W] = Mth::Vector(0.0f, 0.0f, 0.0f, 1.0f);\r\n\r\n\trot_mat = orig_rot_mat * rot_mat;\r\n\t//Dbg_Message(\"[X] (%f, %f, %f, %f)\", rot_mat[X][X], rot_mat[X][Y],  rot_mat[X][Z],  rot_mat[X][W]);\r\n\t//Dbg_Message(\"[Y] (%f, %f, %f, %f)\", rot_mat[Y][X], rot_mat[Y][Y],  rot_mat[Y][Z],  rot_mat[Y][W]);\r\n\t//Dbg_Message(\"[Z] (%f, %f, %f, %f)\", rot_mat[Z][X], rot_mat[Z][Y],  rot_mat[Z][Z],  rot_mat[Z][W]);\r\n\t//Dbg_Message(\"[W] (%f, %f, %f, %f)\", rot_mat[W][X], rot_mat[W][Y],  rot_mat[W][Z],  rot_mat[W][W]);\r\n\t\r\n\tm_rootMatrix[X] = rot_mat[X];\r\n\tm_rootMatrix[Y] = rot_mat[Y];\r\n\tm_rootMatrix[Z] = rot_mat[Z];\r\n\r\n\tif (m_cloned != vCOPY)\r\n\t{\r\n\t\tupdate_engine_matrix();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Garrett: We may need to change the world pos to integer to avoid float losses\r\n\t\tmp_instance->RotateY(m_rootMatrix[W], rot);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_set_transform(const Mth::Matrix& transform)\r\n{\r\n\t// Set values\r\n\tm_rootMatrix = transform;\r\n\r\n\t// Engine call here\r\n\tif (m_cloned != vCOPY)\r\n\t{\r\n\t\tupdate_engine_matrix();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Don't call SetTransform() on a CGeom copy\"));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Matrix &\tCPs2Geom::plat_get_transform() const\r\n{\r\n\treturn m_rootMatrix;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_set_scale(const Mth::Vector & scale)\r\n{\r\n\t// Engine call here\r\n\tMth::Matrix orig_rot_mat(m_rootMatrix);\r\n\r\n\t// orientation\r\n\tm_rootMatrix[X] *= scale[X];\r\n\tm_rootMatrix[Y] *= scale[Y];\r\n\tm_rootMatrix[Z] *= scale[Z];\r\n\r\n#if 0\t\t// Don't do this now since it is a local space scale\r\n\t// position (since this is what will happen in the copy geometry)\r\n\tm_rootMatrix[Mth::POS][X] *= scale[X];\r\n\tm_rootMatrix[Mth::POS][Y] *= scale[Y];\r\n\tm_rootMatrix[Mth::POS][Z] *= scale[Z];\r\n#endif\r\n\r\n\tif (m_cloned != vCOPY)\r\n\t{\r\n\t\tupdate_engine_matrix();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMth::Vector delta_scale;\r\n\r\n\t\tdelta_scale[X] = scale[X] /  orig_rot_mat[X].Length();\r\n\t\tdelta_scale[Y] = scale[Y] /  orig_rot_mat[Y].Length();\r\n\t\tdelta_scale[Z] = scale[Z] /  orig_rot_mat[Z].Length();\r\n\r\n\t\tmp_instance->Scale(m_rootMatrix[W], delta_scale);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nMth::Vector CPs2Geom::plat_get_scale() const\r\n{\r\n\tMth::Vector scale;\r\n\r\n\tscale[X] = m_rootMatrix[X].Length();\r\n\tscale[Y] = m_rootMatrix[Y].Length();\r\n\tscale[Z] = m_rootMatrix[Z].Length();\r\n\r\n\treturn scale;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::update_engine_matrix()\r\n{\r\n\tif (m_cloned != vCOPY)\r\n\t{\r\n\t\tmp_instance->SetMatrix(&m_rootMatrix);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// not needed anymore\r\n#if 0\r\nvoid ConvertMatrix(Mth::Matrix* pMatrix, Mth::Matrix* pMat)\r\n{\r\n\t/*\r\n\t// right\r\n\t(*pMat)[0][0] = (*pMatrix)[0][0];\r\n\t(*pMat)[0][1] = (*pMatrix)[0][1];\r\n\t(*pMat)[0][2] = (*pMatrix)[0][2];\r\n\t(*pMat)[0][3] = (*pMatrix)[0][3];\r\n\r\n\t// up\r\n\t(*pMat)[1][0] = (*pMatrix)[1][0];\r\n\t(*pMat)[1][1] = (*pMatrix)[1][1];\r\n\t(*pMat)[1][2] = (*pMatrix)[1][2];\r\n\t(*pMat)[1][3] = (*pMatrix)[1][3];\r\n\r\n\t// at\r\n\t(*pMat)[2][0] = (*pMatrix)[2][0];\r\n\t(*pMat)[2][1] = (*pMatrix)[2][1];\r\n\t(*pMat)[2][2] = (*pMatrix)[2][2];\r\n\t(*pMat)[2][3] = (*pMatrix)[2][3];\r\n\r\n\t// position\r\n\t(*pMat)[3][0] = (*pMatrix)[3][0];\r\n\t(*pMat)[3][1] = (*pMatrix)[3][1];\r\n\t(*pMat)[3][2] = (*pMatrix)[3][2];\r\n\t(*pMat)[3][3] = (*pMatrix)[3][3];\r\n\r\n\t*/\r\n\t\r\n\t// the copy operator is more efficient\r\n\t// (on PS2, does 4 quad copies.  Other platform does the same as above\r\n\t*pMat  = *pMatrix;\t\t\t\t \r\n\r\n\t// clear out the final column\r\n\t(*pMat)[0][3] = 0.0f;//(*pMatrix)[3][0];\r\n\t(*pMat)[1][3] = 0.0f;//(*pMatrix)[3][0];\r\n\t(*pMat)[2][3] = 0.0f;//(*pMatrix)[3][0];\r\n\t(*pMat)[3][3] = 1.0f;//(*pMatrix)[3][0];\r\n\t\t\r\n\t#if 0\r\n\t// right\r\n\t(*pMat)[0][0] = 1.0f;//(*pMatrix)[0][0];\r\n\t(*pMat)[0][1] = 0.0f;//(*pMatrix)[1][0];\r\n\t(*pMat)[0][2] = 0.0f;//(*pMatrix)[2][0];\r\n\t(*pMat)[0][3] = 0.0f;//(*pMatrix)[3][0];\r\n\r\n\t// up\r\n\t(*pMat)[1][0] = 0.0f;//(*pMatrix)[0][1];\r\n\t(*pMat)[1][1] = 1.0f;//(*pMatrix)[1][1];\r\n\t(*pMat)[1][2] = 0.0f;//(*pMatrix)[2][1];\r\n\t(*pMat)[1][3] = 0.0f;//(*pMatrix)[3][1];\r\n\r\n\t// at\r\n\t(*pMat)[2][0] = 0.0f;//(*pMatrix)[0][2];\r\n\t(*pMat)[2][1] = 0.0f;//(*pMatrix)[1][2];\r\n\t(*pMat)[2][2] = 1.0f;//(*pMatrix)[2][2];\r\n\t(*pMat)[2][3] = 0.0f;//(*pMatrix)[3][2];\r\n\r\n\t// position\r\n//\t(*pMat)[3][0] = (*pMatrix)[3][0];\r\n//\t(*pMat)[3][1] = (*pMatrix)[3][1];\r\n//\t(*pMat)[3][2] = (*pMatrix)[3][2];\r\n//\t(*pMat)[3][3] = 1.0f;//(*pMatrix)[3][3];\r\n\t#endif\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPs2Geom::plat_render(Mth::Matrix* pRootMatrix, Mth::Matrix* pBoneMatrices, int numBones)\r\n{\r\n\t// implies it's got a skin\r\n\tif ( mp_oldInstance )\r\n\t{\r\n\t\tDbg_Assert( mp_oldInstance );\r\n\t\t\r\n\t\tif ( numBones > 0 )\r\n\t\t{\r\n\t\t\tmp_oldInstance->SetBoneTransforms( pBoneMatrices ); \r\n\t\t}\r\n\r\n\t\tmp_oldInstance->SetTransform(*pRootMatrix);\r\n\t\r\n\t\tDbg_MsgAssert( numBones <= mp_oldInstance->GetNumBones(), ( \"Bone mismatch Trying to render %d bones, but model was initialized with %d bones\", \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnumBones, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmp_oldInstance->GetNumBones() ) );\r\n\t}\r\n\r\n\tif ( mp_instance )\r\n\t{\r\n\t\tm_rootMatrix = *pRootMatrix;\r\n\r\n\t\tif ( numBones )\r\n\t\t{\r\n\t\t\tmp_instance->SetBoneTransforms( pBoneMatrices );\r\n\t\t}\r\n\t\t\r\n\t\tDbg_MsgAssert( numBones <= mp_instance->GetNumBones(), ( \"Bone mismatch Trying to render %d bones, but model was initialized with %d bones\", \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnumBones, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmp_instance->GetNumBones() ) );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPs2Geom::plat_hide_polys( uint32 mask )\r\n{\r\n\tif ( mp_instance )\r\n\t{\r\n\t// Only supporting old style geom for now\r\n\t//\tmp_instance->HidePolys( mask );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Assert( mp_sourceMesh );\r\n\t\tNxPs2::CGeomNode* pGeomNode = mp_sourceMesh->GetGeomNode();\r\n\t\tif ( pGeomNode )\r\n\t\t{\r\n\t\t// Only supporting old style geom for now\r\n\t\t//\tpGeomNode->HidePolys( mask );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_sourceMesh->HidePolys( mask );\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPs2Geom::plat_enable_shadow( bool enabled )\r\n{\r\n\tif ( mp_instance )\r\n\t{\r\n\t\t// only supporting old style geom for now\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_oldInstance->EnableShadow( enabled );\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_set_model_lights(CModelLights *p_model_lights)\r\n{\r\n\tNxPs2::CLightGroup *p_light_group;\r\n\tif (p_model_lights)\r\n\t{\r\n\t\tCPs2ModelLights *p_ps2_model_lights;\r\n\t\tp_ps2_model_lights = static_cast<CPs2ModelLights *>(p_model_lights);\r\n\t\tp_light_group = p_ps2_model_lights->GetEngineLightGroup();\r\n\t} else {\r\n\t\tp_light_group = NULL;\r\n\t}\r\n\r\n\r\n\t// Model lights only work on CGeomNodes\r\n\tif (mp_instance)\r\n\t{\r\n\t\tDbg_Assert(!mp_instance->IsLeaf());\r\n\t\tmp_instance->SetLightGroup(p_light_group);\r\n\t}\r\n\telse if (mp_oldInstance)\r\n\t{\r\n\t\tmp_oldInstance->SetLightGroup(p_light_group);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CPs2Geom::plat_get_num_render_verts()\r\n{\r\n\tDbg_Assert(mp_instance);\r\n\r\n\treturn mp_instance->GetNumVerts();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_get_render_verts(Mth::Vector *p_verts)\r\n{\r\n\tDbg_Assert(mp_instance);\r\n\r\n\tmp_instance->GetVerts(p_verts);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CPs2Geom::plat_get_num_render_polys()\t\t\t\t\t\t\t\t\r\n{\r\n\treturn mp_instance->GetNumPolys();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CPs2Geom::plat_get_num_render_base_polys()\t\t\t\t\t\t\t\t\r\n{\r\n\treturn mp_instance->GetNumBasePolys();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_get_render_colors(Image::RGBA *p_colors)\r\n{\r\n\tDbg_Assert(mp_instance);\r\n\r\n\tmp_instance->GetColors((uint32 *) p_colors);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_set_render_verts(Mth::Vector *p_verts)\r\n{\r\n\tDbg_Assert(mp_instance);\r\n\r\n\tmp_instance->SetVerts(p_verts);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_set_render_colors(Image::RGBA *p_colors)\r\n{\r\n\tDbg_Assert(mp_instance);\r\n\r\n\tmp_instance->SetColors((uint32 *) p_colors);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_set_uv_wibble_params(float u_vel, float u_amp, float u_freq, float u_phase,\r\n\t\t\t\t\t\t\t\t\t\t float v_vel, float v_amp, float v_freq, float v_phase)\r\n{\r\n\tDbg_Assert(mp_instance);\r\n\r\n\tNxPs2::CGeomNode *p_node = mp_instance;\r\n\r\n\t// Get leaf\r\n\twhile (!p_node->IsLeaf())\r\n\t{\r\n\t\tp_node = p_node->GetChild();\r\n\t}\r\n\r\n\t// Do on all siblings\r\n\twhile (p_node)\r\n\t{\r\n\t\tif (p_node->IsUVWibbled())\r\n\t\t{\r\n\t\t\tp_node->SetUVWibbleParams(u_vel, u_amp, u_freq, u_phase, v_vel, v_amp, v_freq, v_phase);\r\n\t\t}\r\n\r\n\t\tp_node = p_node->GetSibling();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_use_explicit_uv_wibble(bool yes)\r\n{\r\n\tDbg_Assert(mp_instance);\r\n\r\n\tNxPs2::CGeomNode *p_node = mp_instance;\r\n\r\n\t// Get leaf\r\n\twhile (!p_node->IsLeaf())\r\n\t{\r\n\t\tp_node = p_node->GetChild();\r\n\t}\r\n\r\n\t// Do on all siblings\r\n\twhile (p_node)\r\n\t{\r\n\t\tif (p_node->IsUVWibbled())\r\n\t\t{\r\n\t\t\tp_node->UseExplicitUVWibble(yes);\r\n\t\t}\r\n\r\n\t\tp_node = p_node->GetSibling();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Geom::plat_set_uv_wibble_offsets(float u_offset, float v_offset)\r\n{\r\n\tDbg_Assert(mp_instance);\r\n\r\n\tNxPs2::CGeomNode *p_node = mp_instance;\r\n\r\n\t// Get leaf\r\n\twhile (!p_node->IsLeaf())\r\n\t{\r\n\t\tp_node = p_node->GetChild();\r\n\t}\r\n\r\n\t// Do on all siblings\r\n\twhile (p_node)\r\n\t{\r\n\t\tif (p_node->IsUVWibbled())\r\n\t\t{\r\n\t\t\tp_node->SetUVWibbleOffsets(u_offset, v_offset);\r\n\t\t\t// If we are setting the offsets, then we should want to use the explicit mode\r\n\t\t\tp_node->UseExplicitUVWibble(true);\r\n\t\t}\r\n\r\n\t\tp_node = p_node->GetSibling();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPs2Geom::plat_set_uv_wibble_offsets(uint32 mat_checksum, int pass, float u_offset, float v_offset)\r\n{\r\n\tif (mp_oldInstance)\r\n\t{\r\n\t\tmp_oldInstance->SetUVOffset(mat_checksum, pass, u_offset, v_offset);\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't set the UV offset with material checksum on CGeomNode\"));\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPs2Geom::plat_set_uv_matrix(uint32 mat_checksum, int pass, const Mth::Matrix &mat)\r\n{\r\n\tif (mp_oldInstance)\r\n\t{\r\n\t\tmp_oldInstance->SetUVMatrix(mat_checksum, pass, mat);\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't set the UV matrix with material checksum on CGeomNode\"));\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxGeom.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxGeom.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  3/5/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_GEOM_H__\r\n#define\t__GFX_P_NX_GEOM_H__\r\n    \r\n#include \"core/math.h\"\r\n\r\n#include \"gfx/nxgeom.h\"\r\n\r\nnamespace NxPs2\r\n{\r\n\tclass CInstance;\r\n\tclass CGeomNode;\r\n}\r\n\t\t\t\t\t\t   \r\nnamespace Nx\r\n{\r\n\tclass CPs2Mesh;\r\n\tclass CModelLights;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CGeom\r\n    \r\nclass CPs2Geom : public CGeom\r\n{\r\n                                      \r\npublic:\r\n\t\t\t\t\t\tCPs2Geom();\r\n\tvirtual \t\t\t~CPs2Geom();\r\n\r\n\tvoid\t\t\t\tSetEngineObject(NxPs2::CGeomNode *p_object);\r\n\tNxPs2::CGeomNode *\tGetEngineObject() const;\r\n\r\n\tMth::Vector\t\t\tGetBoundingSphere();\r\n\r\n\r\nprivate:\t\t\t\t// It's all private, as it is machine specific\r\n\tvirtual CGeom *\t\tplat_clone(bool instance, CScene* pDestScene=NULL);\r\n\tvirtual CGeom *\t\tplat_clone(bool instance, CModel* pDestModel);\r\n\r\n\tvirtual\tbool\t\tplat_load_geom_data(CMesh* pMesh, CModel* pModel, bool color_per_material);\r\n\tvirtual void\t\tplat_finalize();\r\n\r\n\tvirtual uint32\t\tplat_get_checksum();\r\n\r\n\tvirtual\tvoid\t\tplat_set_color(Image::RGBA rgba);\r\n\tvirtual\tImage::RGBA\tplat_get_color() const;\r\n\tvirtual\tvoid\t\tplat_clear_color();\r\n\r\n\tvirtual bool\t\tplat_set_material_color(uint32 mat_checksum, int pass, Image::RGBA rgba);\r\n\tvirtual Image::RGBA\tplat_get_material_color(uint32 mat_checksum, int pass);\r\n\r\n\tvirtual\tvoid\t\tplat_set_visibility(uint32 mask);\r\n\tvirtual\tuint32\t\tplat_get_visibility() const;\r\n\r\n\tvirtual\tvoid\t\tplat_set_active(bool active);\r\n\tvirtual\tbool\t\tplat_is_active() const;\r\n\r\n\tvirtual const Mth::CBBox &\tplat_get_bounding_box() const;\r\n\r\n\tvirtual void\tplat_set_bounding_sphere( const Mth::Vector& boundingSphere );\r\n\tvirtual const Mth::Vector\tplat_get_bounding_sphere() const;\r\n\r\n\tvirtual void\t\tplat_set_world_position(const Mth::Vector& pos);\r\n\tvirtual const Mth::Vector &\tplat_get_world_position() const;\r\n\r\n\tvirtual void\t\tplat_set_orientation(const Mth::Matrix& orient);\r\n\tvirtual const Mth::Matrix &\tplat_get_orientation() const;\r\n\r\n\tvirtual void \t\tplat_rotate_y(Mth::ERot90 rot);\r\n\r\n\tvirtual void\t\tplat_set_transform(const Mth::Matrix& transform);\r\n\tvirtual const Mth::Matrix &\tplat_get_transform() const;\r\n\r\n\tvirtual void\t\tplat_set_scale(const Mth::Vector& scale);\r\n\tvirtual Mth::Vector plat_get_scale() const;\r\n\r\n\tvirtual void\t\tplat_set_model_lights(CModelLights *);\r\n\r\n\tvirtual bool\t\tplat_render(Mth::Matrix* pRootMatrix, Mth::Matrix* ppBoneMatrices, int numBones);\r\n\tvirtual bool\t\tplat_hide_polys( uint32 mask );\r\n\tvirtual bool\t\tplat_enable_shadow( bool enabled );\r\n\r\n\tvirtual\tint \t\tplat_get_num_render_verts();\t\t\t\t\t\t\t\t// - returns number of renderable verts\r\n\tvirtual\tint \t\tplat_get_num_render_polys();\r\n\tvirtual\tint \t\tplat_get_num_render_base_polys();\r\n\tvirtual\tvoid \t\tplat_get_render_verts(Mth::Vector *p_verts);\t\t\t\t// - gets a single array of the verts\r\n\tvirtual\tvoid \t\tplat_get_render_colors(Image::RGBA *p_colors);\t\t\t\t// - gets an array of vertex colors\r\n\tvirtual void \t\tplat_set_render_verts(Mth::Vector *p_verts);\t\t\t\t// - sets the verts after modification\r\n\tvirtual\tvoid \t\tplat_set_render_colors(Image::RGBA *p_colors);\t\t\t\t// - sets the colors after modification\r\n\r\n\t// Wibble functions\r\n\tvirtual void\t\tplat_set_uv_wibble_params(float u_vel, float u_amp, float u_freq, float u_phase,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  float v_vel, float v_amp, float v_freq, float v_phase);\r\n\tvirtual void\t\tplat_use_explicit_uv_wibble(bool yes);\r\n\tvirtual void\t\tplat_set_uv_wibble_offsets(float u_offset, float v_offset);\r\n\tvirtual bool\t\tplat_set_uv_wibble_offsets(uint32 mat_checksum, int pass, float u_offset, float v_offset);\r\n\tvirtual bool\t\tplat_set_uv_matrix(uint32 mat_checksum, int pass, const Mth::Matrix &mat);\r\n\r\n\t// local functions\r\n\tvoid \t\t\t\tupdate_engine_matrix();\r\n\r\nprivate:\r\n\t// old format\r\n\tNxPs2::CInstance*\tmp_oldInstance;\r\n\t\r\n\t// access to the scene means access to the polys for hiding purposes\r\n\t// this code will all be thrown away once we convert to the new geomnode\r\n\t// stuff anyway\r\n\tCPs2Mesh*\t\t\tmp_sourceMesh;\t\t\t\r\n\r\n\t// new format\r\n\tNxPs2::CGeomNode*\tmp_instance;\r\n\tMth::Matrix\t\t\tm_rootMatrix;\r\n\r\n\tMth::Matrix *\t\tmp_matrices;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCPs2Geom::SetEngineObject(NxPs2::CGeomNode *p_object)\r\n{\r\n\tmp_instance = p_object;\r\n\tDbg_MsgAssert(((int)(mp_instance) & 0xf) == 0,(\"mp_instance (0x%x) not multiple of 16 (Maybe .SCN corrupted on export?)\\n\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t,(int)mp_instance));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline NxPs2::CGeomNode *\tCPs2Geom::GetEngineObject() const\r\n{\r\n\treturn mp_instance;\r\n}\r\n\r\n} // Nx\r\n\r\n#endif \r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxImposter.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxImposter.cpp\r\n\r\n#include \t\"gfx/ngps/p_NxGeom.h\"\r\n#include \t\"gfx/ngps/p_NxImposter.h\"\r\n\r\nnamespace Nx\r\n{\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCImposterGroup* CImposterManager::plat_create_imposter_group( void )\r\n{\r\n\treturn new CPs2ImposterGroup;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterManager::plat_pre_render_imposters( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterManager::plat_post_render_imposters( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CImposterGroup\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCPs2ImposterGroup::CPs2ImposterGroup()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCPs2ImposterGroup::~CPs2ImposterGroup()\r\n{\r\n}\r\n\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxImposter.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxFont.h\r\n\r\n#ifndef\t__GFX_P_NX_IMPOSTER_H__\r\n#define\t__GFX_P_NX_IMPOSTER_H__\r\n\r\n#include \t\"gfx/NxImposter.h\"\r\n\r\nnamespace Nx\r\n{\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CImposterGroup\r\nclass CPs2ImposterGroup : public CImposterGroup\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\t\tCPs2ImposterGroup();\r\n\tvirtual\t\t\t\t\t\t~CPs2ImposterGroup();\r\n\r\n\r\n\tprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\r\n\t// Machine specific members\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxLight.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxLight.cpp - PS2 platform specific interface to CModelLights\r\n//\r\n// This is PS2 SPECIFIC!!!!!!  So might get a bit messy\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gfx/ngps/p_NxLight.h>\r\n#include <gfx/ngps/nx/light.h>\r\n\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2ModelLights::CPs2ModelLights()\r\n{\r\n\tmp_light_group = new NxPs2::CLightGroup;\r\n\r\n\tplat_enable_ambient_light(false);\r\n\tfor (int i = 0; i < CLightManager::MAX_LIGHTS; i++)\r\n\t{\r\n\t\tplat_enable_diffuse_light(i, false);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2ModelLights::~CPs2ModelLights()\r\n{\r\n\tif (mp_light_group)\r\n\t{\r\n\t\tdelete mp_light_group;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2ModelLights::plat_update_engine( Mth::Vector & pos, bool add_scene_light )\r\n{\r\n\t// Figure Scene Lighting if required.\r\n\tif( add_scene_light )\r\n\t{\r\n\t\t// Copy the object position into our position.  If this pointer is set to NULL,\r\n\t\t// we probably won't find any Scene Lights.\r\n\t\tif (mp_pos)\r\n\t\t{\r\n\t\t\tpos = *mp_pos;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"No object position pointer for scene lights\"));\r\n\t\t}\r\n\r\n\t\t// We should check if any calcs are necessary first by seeing if this position is\r\n\t\t// \"visible\", but for now, we'll do them all.\r\n\t\tNx::CSceneLight *p_scene_light = CLightManager::sGetOptimumSceneLight( pos );\r\n\t\tif( p_scene_light )\r\n\t\t{\r\n\t\t\tDbg_Assert(mp_light_group);\r\n\r\n\t\t\tMth::Vector light_pos = p_scene_light->GetLightPosition();\r\n\r\n\t\t\tfloat dist\t= Mth::Distance( pos, light_pos );\r\n\t\t\tfloat ratio\t= dist * p_scene_light->GetLightReciprocalRadius();\r\n\r\n\t\t\tlight_pos = - ( pos - light_pos ).Normalize();\r\n\r\n\t\t\t// Figure the direction...\r\n\t\t\tmp_light_group->SetDirection(SCENE_LIGHT_INDEX, light_pos);\r\n\r\n\t\t\t// ...and the color.\r\n\t\t\tratio = sqrtf( 1.0f - ratio ) * p_scene_light->GetLightIntensity();\r\n\t\t\tMth::Vector color(ratio * p_scene_light->GetLightColor().r,\r\n\t\t\t\t\t\t\t  ratio * p_scene_light->GetLightColor().g,\r\n\t\t\t\t\t\t\t  ratio * p_scene_light->GetLightColor().b,\r\n\t\t\t\t\t\t\t  0);\r\n\r\n\t\t\tmp_light_group->SetBaseDiffuseColor(SCENE_LIGHT_INDEX, color);\r\n\r\n\t\t\tplat_enable_diffuse_light(SCENE_LIGHT_INDEX, true);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n#if 0\r\n\t\t\t// Disable this light by setting zero color.\r\n\t\t\tMth::Vector color(0, 0, 0, 0);\r\n\r\n\t\t\tmp_light_group->SetBaseDiffuseColor(SCENE_LIGHT_INDEX, color);\r\n#endif\r\n\t\t\tplat_enable_diffuse_light(SCENE_LIGHT_INDEX, false);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2ModelLights::plat_update_brightness()\r\n{\r\n\tmp_light_group->SetAmbientBrightness(m_ambient_brightness);\r\n\r\n\tfor (int i = 0; i < CLightManager::MAX_LIGHTS; i++)\r\n\t{\r\n\t\tmp_light_group->SetDiffuseBrightness(i, m_diffuse_brightness[i]);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2ModelLights::plat_set_light_ambient_color(const Image::RGBA &rgba)\r\n{\r\n\tMth::Vector color(((float) rgba.r),\r\n\t\t\t\t\t  ((float) rgba.g),\r\n\t\t\t\t\t  ((float) rgba.b),\r\n\t\t\t\t\t  0);\r\n\r\n\tmp_light_group->SetBaseAmbientColor(color);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\t\tCPs2ModelLights::plat_get_light_ambient_color() const\r\n{\r\n\tMth::Vector color = mp_light_group->GetBaseAmbientColor();\r\n\r\n\tImage::RGBA rgba(color[0], color[1], color[2], 0);\r\n\t\r\n\treturn rgba;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2ModelLights::plat_set_light_direction(int light_index, const Mth::Vector &direction)\r\n{\r\n\tmp_light_group->SetDirection(light_index, direction);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\tCPs2ModelLights::plat_get_light_direction(int light_index) const\r\n{\r\n\treturn mp_light_group->GetDirection(light_index);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2ModelLights::plat_set_light_diffuse_color(int light_index, const Image::RGBA &rgba)\r\n{\r\n\tMth::Vector color(((float) rgba.r),\r\n\t\t\t\t\t  ((float) rgba.g),\r\n\t\t\t\t\t  ((float) rgba.b),\r\n\t\t\t\t\t  0);\r\n\r\n\tmp_light_group->SetBaseDiffuseColor(light_index, color);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\t\tCPs2ModelLights::plat_get_light_diffuse_color(int light_index) const\r\n{\r\n\tMth::Vector color = mp_light_group->GetBaseDiffuseColor(light_index);\r\n\r\n\tImage::RGBA rgba(color[0], color[1], color[2], 0);\r\n\t\r\n\treturn rgba;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2ModelLights::plat_enable_ambient_light(bool enable)\r\n{\r\n\tmp_light_group->EnableAmbientLight(enable);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2ModelLights::plat_enable_diffuse_light(int light_index, bool enable)\r\n{\r\n\tmp_light_group->EnableDiffuseLight(light_index, enable);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2ModelLights::plat_is_ambient_light_enabled() const\r\n{\r\n\treturn mp_light_group->IsAmbientLightEnabled();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2ModelLights::plat_is_diffuse_light_enabled(int light_index) const\r\n{\r\n\treturn mp_light_group->IsDiffuseLightEnabled(light_index);\r\n}\r\n\r\n} \r\n \r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxLight.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// p_NxLight.H - Neversoft Engine, Rendering portion, Platform dependent interface\r\n\r\n#ifndef\t__GFX_P_NX_LIGHT_H__\r\n#define\t__GFX_P_NX_LIGHT_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/math.h>\r\n#include <gfx/image/imagebasic.h>\r\n#include <gfx/nxlight.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\tclass CLightGroup;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// Nx::CPs2ModelLights\r\nclass\tCPs2ModelLights : public CModelLights\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCPs2ModelLights();\r\n\tvirtual\t\t\t\t\t\t~CPs2ModelLights();\r\n\r\n\tNxPs2::CLightGroup *\t\tGetEngineLightGroup() const;\r\n\r\nprivate:\t\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tSCENE_LIGHT_INDEX = 2,\r\n\t};\r\n\r\n\t// The engine light group\r\n\tNxPs2::CLightGroup *\t\tmp_light_group;\r\n\r\n\t// Platform-specific calls\r\n\t//virtual void\t\t\t\tplat_update_lights();\r\n\tvirtual bool\t\t\t\tplat_set_light_ambient_color(const Image::RGBA &rgba);\r\n\tvirtual bool\t\t\t\tplat_set_light_direction(int light_index, const Mth::Vector &direction);\r\n\tvirtual bool\t\t\t\tplat_set_light_diffuse_color(int light_index, const Image::RGBA &rgba);\r\n\tvirtual Image::RGBA\t\t\tplat_get_light_ambient_color() const;\r\n\tvirtual const Mth::Vector &\tplat_get_light_direction(int light_index) const;\r\n\tvirtual Image::RGBA\t\t\tplat_get_light_diffuse_color(int light_index) const;\r\n\r\n\tvirtual void\t\t\t\tplat_update_engine( Mth::Vector & pos, bool add_scene_light );\r\n\r\n\tvirtual void\t\t\t\tplat_update_brightness();\r\n\r\n\tvirtual void\t\t\t\tplat_enable_ambient_light(bool enable);\r\n\tvirtual void\t\t\t\tplat_enable_diffuse_light(int light_index, bool enable);\r\n\tvirtual bool\t\t\t\tplat_is_ambient_light_enabled() const;\r\n\tvirtual bool\t\t\t\tplat_is_diffuse_light_enabled(int light_index) const;\r\n};\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline NxPs2::CLightGroup *\tCPs2ModelLights::GetEngineLightGroup() const\r\n{\r\n\treturn mp_light_group;\r\n}\r\n\r\n}\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxLightMan.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxLightMan.cpp - PS2 platform specific interface to CLightManager\r\n//\r\n// This is PS2 SPECIFIC!!!!!!  So might get a bit messy\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gfx/ngps/p_NxLight.h>\r\n#include <gfx/ngps/p_NxLightMan.h>\r\n#include <gfx/ngps/nx/light.h>\r\n\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid\t\t\tCLightManager::s_plat_update_engine( void )\r\n{\r\n\tCPs2LightManager::sUpdateEngine();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCLightManager::s_plat_update_lights()\r\n{\r\n\ts_plat_set_light_ambient_color();\r\n\tfor (int i = 0; i < MAX_LIGHTS; i++)\r\n\t{\r\n\t\ts_plat_set_light_direction(i);\r\n\t\ts_plat_set_light_diffuse_color(i);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCLightManager::s_plat_update_colors()\r\n{\r\n\ts_plat_set_light_ambient_color();\r\n\tfor (int i = 0; i < MAX_LIGHTS; i++)\r\n\t{\r\n\t\ts_plat_set_light_diffuse_color(i);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCLightManager::s_plat_set_light_ambient_color()\r\n{\r\n\tMth::Vector color(((float) s_world_lights.m_light_ambient_rgba.r),\r\n\t\t\t\t\t  ((float) s_world_lights.m_light_ambient_rgba.g),\r\n\t\t\t\t\t  ((float) s_world_lights.m_light_ambient_rgba.b),\r\n\t\t\t\t\t  0);\r\n\r\n\tNxPs2::CLightGroup::sSetDefaultAmbientColor(color);\r\n\r\n\t//color *= s_ambient_brightness;\r\n\t//NxPs2::CLightGroup::sSetDefaultModAmbientColor(color);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\t\tCLightManager::s_plat_get_light_ambient_color()\r\n{\r\n\tMth::Vector color(NxPs2::CLightGroup::sGetDefaultAmbientColor());\r\n\r\n\tImage::RGBA rgb;\r\n\r\n\trgb.r = (uint8) color[X];\r\n\trgb.g = (uint8) color[Y];\r\n\trgb.b = (uint8) color[Z];\r\n\trgb.a = 0x80;\r\n\r\n\treturn rgb;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCLightManager::s_plat_set_light_direction(int light_index)\r\n{\r\n\tNxPs2::CLightGroup::sSetDefaultDirection(light_index, s_world_lights.m_light_direction[light_index]);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector & CLightManager::s_plat_get_light_direction(int light_index)\r\n{\r\n\treturn NxPs2::CLightGroup::sGetDefaultDirection(light_index);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCLightManager::s_plat_set_light_diffuse_color(int light_index)\r\n{\r\n\tMth::Vector color(((float) s_world_lights.m_light_diffuse_rgba[light_index].r),\r\n\t\t\t\t\t  ((float) s_world_lights.m_light_diffuse_rgba[light_index].g),\r\n\t\t\t\t\t  ((float) s_world_lights.m_light_diffuse_rgba[light_index].b),\r\n\t\t\t\t\t  0);\r\n\r\n\tNxPs2::CLightGroup::sSetDefaultDiffuseColor(light_index, color);\r\n\t\r\n\t//color *= s_diffuse_brightness[light_index];\r\n\t//NxPs2::CLightGroup::sSetDefaultModDiffuseColor(light_index, color);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\t\tCLightManager::s_plat_get_light_diffuse_color(int light_index)\r\n{\r\n\tMth::Vector color(NxPs2::CLightGroup::sGetDefaultDiffuseColor(light_index));\r\n\r\n\tImage::RGBA rgb;\r\n\r\n\trgb.r = (uint8) color[X];\r\n\trgb.g = (uint8) color[Y];\r\n\trgb.b = (uint8) color[Z];\r\n\trgb.a = 0x80;\r\n\r\n\treturn rgb;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModelLights *\tCLightManager::s_plat_create_model_lights()\r\n{\r\n\tCModelLights *p_model_lights = new CPs2ModelLights;\r\n\r\n\tif (p_model_lights)\r\n\t{\r\n\t\tCPs2LightManager::sAddToModelLightsList(p_model_lights);\r\n\t}\r\n\r\n\treturn p_model_lights;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCLightManager::s_plat_free_model_lights(CModelLights *p_model_lights)\r\n{\r\n\tDbg_Assert(p_model_lights);\r\n\r\n\tCPs2LightManager::sRemoveFromModelLightsList(p_model_lights);\r\n\r\n\tdelete p_model_lights;\r\n\r\n\treturn true;\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// Nx::CPs2LightManager\r\n\r\n// Model light list\r\nLst::Head< CModelLights > CPs2LightManager::s_model_lights_list;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2LightManager::sUpdateEngine( void )\r\n{\r\n\ts_update_model_lights();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2LightManager::sAddToModelLightsList(CModelLights *p_model_lights)\r\n{\r\n\tDbg_Assert(p_model_lights);\r\n\r\n\tLst::Node< CModelLights > *node = new Lst::Node< CModelLights > (p_model_lights);\r\n\tif (node)\r\n\t{\r\n\t\ts_model_lights_list.AddToTail(node);\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2LightManager::sRemoveFromModelLightsList(CModelLights *p_model_lights)\r\n{\r\n\tDbg_Assert(p_model_lights);\r\n\r\n\tLst::Node< CModelLights > *obj_node;\r\n\r\n\tfor(obj_node = s_model_lights_list.GetNext(); obj_node; obj_node = obj_node->GetNext())\r\n\t{\r\n\t\tif (obj_node->GetData() == p_model_lights)\r\n\t\t{\r\n\t\t\tdelete obj_node;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2LightManager::s_update_model_lights()\r\n{\r\n\tMth::Vector dummy_pos(0, 0, 0, 1);\t\t// Function requires this to be passed in, even though not used\r\n\tLst::Node< CModelLights > *obj_node;\r\n\r\n\tfor(obj_node = s_model_lights_list.GetNext(); obj_node; obj_node = obj_node->GetNext())\r\n\t{\r\n\t\tCModelLights *p_model_lights = obj_node->GetData();\r\n\t\t\r\n\t\tDbg_Assert(p_model_lights);\r\n\r\n\t\tp_model_lights->UpdateEngine(dummy_pos, true);\r\n\t}\r\n}\r\n\r\n} \r\n \r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxLightMan.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// p_NxLightMan.H - Neversoft Engine, Rendering portion, Platform dependent interface\r\n\r\n#ifndef\t__GFX_P_NX_LIGHT_MAN_H__\r\n#define\t__GFX_P_NX_LIGHT_MAN_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/hashtable.h>\r\n\r\n#include <gfx/NxLightMan.h>\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// Nx::CPs2LightManager\r\nclass\tCPs2LightManager : public CLightManager\r\n{\r\npublic:\r\n\r\n\t// Does any once-per-frame light update\r\n\tstatic void\t\t\t\t\tsUpdateEngine( void );\r\n\r\n\t// Model Lights List functions\r\n\tstatic bool\t\t\t\t\tsAddToModelLightsList(CModelLights *p_model_lights);\r\n\tstatic bool\t\t\t\t\tsRemoveFromModelLightsList(CModelLights *p_model_lights);\r\n\r\nprivate:\t\r\n\r\n\t// once-per-frame update functions called from sUpdateEngine()\r\n\tstatic void\t\t\t\t\ts_update_model_lights();\r\n\r\n\t// Model light list\r\n\tstatic Lst::Head< CModelLights > s_model_lights_list;\r\n};\r\n\r\n}\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxLoadScreen.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxLoadScreen.cpp - PS2 platform specific interface for the load screen\r\n//\r\n// This is PS2 SPECIFIC!!!!!!  So might get a bit messy\r\n//\r\n\r\n#include\t\"gfx\\Nx.h\"\r\n#include\t\"gfx\\NxLoadScreen.h\"\r\n#include\t\"gfx\\NGPS\\p_NxTexture.h\"\r\n#include\t\"gfx\\NGPS\\p_NxSprite.h\"\r\n#include\t\"gfx\\NGPS\\NX\\sprite.h\"\r\n#include\t\"gfx\\NGPS\\NX\\render.h\"\r\n#include\t\"gfx\\NGPS\\NX\\loadscreen.h\"\r\n#include\t\"gfx\\NGPS\\NX\\dma.h\"\r\n#include\t\"gfx\\NGPS\\NX\\dmacalls.h\"\r\n#include\t\"gfx\\NGPS\\NX\\nx_init.h\"\r\n\r\n#include\t\"gel\\movies\\NGPS\\disp.h\"  // for clear screen\r\n\r\n#include\t\"core\\macros.h\"\r\n#include <sys/config/config.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/timer.h>\r\n\r\n#include <libgraph.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\tvoid\tWaitForRendering();\r\n}\r\n\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\nNx::CPs2Texture\t*sp_load_screen_texture;\r\nNx::CPs2Sprite\t*sp_load_screen_sprite;\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n#define USE_SPRITES 0\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::s_plat_display(const char* filename, bool just_freeze, bool blank)\r\n{\r\n\t// Engine stuff\r\n\tDbg_Assert(!sp_load_screen_texture);\r\n\tDbg_Assert(!sp_load_screen_sprite);\r\n\r\n\tchar adjustedFilename[144];\r\n\r\n\tif (!just_freeze && !blank)\r\n\t{\r\n\t\tsp_load_screen_texture = new CPs2Texture(true);\r\n\r\n\t\tif (Config::NTSC())\r\n\t\t{\r\n\t\t\tstrcpy(adjustedFilename, filename);\r\n\t\t} else {\r\n\t\t\t// Find correct directory to use based on language\r\n\t\t\tswitch (Config::GetLanguage())\r\n\t\t\t{\r\n\t\t\tcase Config::LANGUAGE_FRENCH:\r\n\t\t\t\tsprintf(adjustedFilename, \"PALimages/FRImages/%s\", filename);\r\n\t\t\t\tbreak;\r\n\t\t\tcase Config::LANGUAGE_SPANISH:\r\n\t\t\t\tsprintf(adjustedFilename, \"PALimages/SPImages/%s\", filename);\r\n\t\t\t\tbreak;\r\n\t\t\tcase Config::LANGUAGE_GERMAN:\r\n\t\t\t\tsprintf(adjustedFilename, \"PALimages/GRImages/%s\", filename);\r\n\t\t\t\tbreak;\r\n\t\t\tcase Config::LANGUAGE_ITALIAN:\r\n\t\t\t\tsprintf(adjustedFilename, \"PALimages/ITImages/%s\", filename);\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tsprintf(adjustedFilename, \"PALimages/%s\", filename);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// Since LoadTexture() will assert if the file doesn't exist, we need to test ahead of time\r\n\t\t\tchar ExtendedFilename[160];\r\n\t\t\tsprintf(ExtendedFilename, \"images/%s.img.ps2\", adjustedFilename);\r\n\r\n\t\t\tif (!File::Exist(ExtendedFilename))\r\n\t\t\t{\r\n\t\t\t\t// Can't find it, so lets try the base directory before giving up\r\n\t\t\t\tsprintf(adjustedFilename, \"PALimages/%s\", filename);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!sp_load_screen_texture->LoadTexture(adjustedFilename, true))\r\n\t\t{\r\n\t\t\tDbg_Error(\"Can't load texture %s\", adjustedFilename);\r\n\t\t}\r\n\t\r\n\t#if USE_SPRITES\r\n\t\tsp_load_screen_sprite = static_cast<Nx::CPs2Sprite *>(CEngine::sCreateSprite());\r\n\t\tsp_load_screen_sprite->SetTexture(sp_load_screen_texture);\r\n\t\tsp_load_screen_sprite->SetPos(0, 0);\r\n\t\tsp_load_screen_sprite->SetScale(1, 1);\r\n\t\tsp_load_screen_sprite->SetRGBA(Image::RGBA(128, 128, 128, 128));\r\n\t\tsp_load_screen_sprite->SetHidden(false);\r\n\t#else\r\n\t\t// Copy directly into display buffer\r\n\t\tsceGsLoadImage gs_image;\r\n\t\tNxPs2::SSingleTexture *p_engine_texture = sp_load_screen_texture->GetSingleTexture();\r\n\t\r\n\t\tFlushCache( 0 );\r\n\t\tsceGsSyncPath( 0, 0 );\r\n\t\t\r\n\t\tint display_addr = (SCREEN_CONV_X( 640 ) * SCREEN_CONV_Y( 448 ) * 4) / (64 * 4);\r\n\t\r\n\t\tconst int download_parts = 2;\r\n\t\tint partial_height = sp_load_screen_texture->GetHeight() / download_parts;\r\n\t\tint partial_size = sp_load_screen_texture->GetWidth() * partial_height * 2;\r\n\t\tfor (int i = 0; i < download_parts; i++)\r\n\t\t{\r\n\t\t\tsceGsSetDefLoadImage( &gs_image, display_addr, SCREEN_CONV_X( 640 )/64, SCE_GS_PSMCT16S,\r\n\t\t\t\t\t\t\t   0, partial_height * i, sp_load_screen_texture->GetWidth(), partial_height );\r\n\t\t\t\t\t\r\n\t\t\tFlushCache( 0 );\t\t\r\n\t\t\tsceGsExecLoadImage( &gs_image, ( u_long128 * )(p_engine_texture->mp_PixelData + (partial_size * i)) );\r\n\t\t\tsceGsSyncPath( 0, 0 );\r\n\t\t}\r\n\t\r\n\t\t// Done with texture\r\n\t\tdelete sp_load_screen_texture;\r\n\t\tsp_load_screen_texture = NULL;\r\n\t}\r\n\t\r\n\tif (blank)\r\n\t{\r\n\t\t// This is esentially the same as playing a movie, without playing a movie\r\n\t\t// the ResetEngine handles clearing the screen \r\n\t\tNxPs2::SuspendEngine();\r\n\t\tNxPs2::ResetEngine();\t\t\r\n\t}\r\n\t\r\n\t\r\n\t\r\n\tNxPs2::EnableFlipCopy(false);\r\n#endif // USE_SPRITES\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::s_plat_start_loading_bar(float seconds)\r\n{\r\n\tNxPs2::StartLoadingBar((int) (seconds * Config::FPS()));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::s_plat_hide()\r\n{\r\n\tNxPs2::RemoveLoadingBar();\r\n\t//Tmr::VSync();\r\n#if !USE_SPRITES\r\n\tNxPs2::EnableFlipCopy(true);\r\n#endif // USE_SPRITES\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::s_plat_update_bar_properties()\r\n{\r\n\t// Bar size and position\r\n\tNxPs2::gLoadBarX = s_bar_x;\r\n\tNxPs2::gLoadBarY = s_bar_y;\r\n\tNxPs2::gLoadBarWidth = s_bar_width;\r\n\tNxPs2::gLoadBarHeight = s_bar_height;\r\n\r\n\t// Bar colors\r\n\tNxPs2::gLoadBarStartColor[0] = s_bar_start_color.r;\r\n\tNxPs2::gLoadBarStartColor[1] = s_bar_start_color.g;\r\n\tNxPs2::gLoadBarStartColor[2] = s_bar_start_color.b;\r\n\tNxPs2::gLoadBarStartColor[3] = s_bar_start_color.a;\r\n\tNxPs2::gLoadBarDeltaColor[0] = (int) s_bar_end_color.r - NxPs2::gLoadBarStartColor[0];\r\n\tNxPs2::gLoadBarDeltaColor[1] = (int) s_bar_end_color.g - NxPs2::gLoadBarStartColor[1];\r\n\tNxPs2::gLoadBarDeltaColor[2] = (int) s_bar_end_color.b - NxPs2::gLoadBarStartColor[2];\r\n\tNxPs2::gLoadBarDeltaColor[3] = (int) s_bar_end_color.a - NxPs2::gLoadBarStartColor[3];\r\n\r\n\t// Border size\r\n\tNxPs2::gLoadBarBorderWidth = s_bar_border_width;\r\n\tNxPs2::gLoadBarBorderHeight = s_bar_border_height;\r\n\r\n\t// Border color\r\n\tNxPs2::gLoadBarBorderColor[0] = s_bar_border_color.r;\r\n\tNxPs2::gLoadBarBorderColor[1] = s_bar_border_color.g;\r\n\tNxPs2::gLoadBarBorderColor[2] = s_bar_border_color.b;\r\n\tNxPs2::gLoadBarBorderColor[3] = s_bar_border_color.a;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::s_plat_clear()\r\n{\r\n\tif (sp_load_screen_sprite)\r\n\t{\r\n\t\tCEngine::sDestroySprite(sp_load_screen_sprite);\r\n\t\tsp_load_screen_sprite = NULL;\r\n\t}\r\n\r\n\tif (sp_load_screen_texture)\r\n\t{\r\n\t\tdelete sp_load_screen_texture;\r\n\t\tsp_load_screen_texture = NULL;\r\n\t}\r\n\r\n\tNxPs2::RemoveLoadingBar();\r\n}\r\n\r\n} \r\n \r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxMesh.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxMesh.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/15/2002\r\n//****************************************************************************\r\n\r\n#include <gfx/ngps/p_nxmesh.h>\r\n\r\n#include <core/string/stringutils.h>\r\n\t\t\t\t\t\t\t\t  \r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n#include <gfx/ngps/nx/geomnode.h>\r\n#include <gfx/ngps/nx/mesh.h>\r\n#include <gfx/ngps/nx/scene.h>\r\n#include <gfx/ngps/nx/texture.h>\r\n\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/pip.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPs2Mesh::build_casdata_table(uint8* p_casData)\r\n{\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint32 version = *((uint32*)p_casData);\r\n\t#endif\r\n\tp_casData += sizeof(uint32);\r\n\r\n\tDbg_MsgAssert( version >= 2, ( \"Obsolete version of CAS file.  Please re-export.\" ) )\r\n\t\t\r\n\tm_CASRemovalMask = *((uint32*)p_casData);\r\n\tp_casData += sizeof(uint32);\r\n\r\n\tm_numCASData = *((int*)p_casData);\r\n\tp_casData += sizeof(int);\r\n\r\n\t// temporary lookup table, for the duration of the scene loading\r\n\tNxPs2::CreateCASDataLookupTable();\r\n\r\n\tif ( m_numCASData > 0 )\r\n\t{\r\n\t\t// create-a-skater flags\r\n\t\tmp_CASData = new NxPs2::sCASData[m_numCASData];\r\n\t\t\r\n\t\tfor ( int i = 0; i < m_numCASData; i++ )\r\n\t\t{\r\n\t\t\tmp_CASData[i].mask = *((uint32*)p_casData);\r\n\t\t\tp_casData += sizeof(uint32);\r\n\r\n\t\t\t// this will get converted into a pointer to the DMA data\r\n\t\t\tint vertIndex = *((int*)p_casData);\r\n\t\t\tp_casData += sizeof(int);\r\n\t\t\t\r\n\t\t\tNxPs2::SetCASDataLookupData( vertIndex, &mp_CASData[i] );\r\n\t\t}\t\t\r\n\t}\r\n\r\n\treturn ( m_numCASData > 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPs2Mesh::build_casdata_table(const char* pFileName)\r\n{\r\n\tvoid *pFile = File::Open(pFileName, \"rb\");\r\n\tDbg_MsgAssert(pFile, (\"Couldn't open CAS data file %s\\n\", pFileName));\r\n\r\n\tint file_size = File::GetFileSize(pFile);\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tuint8* p_fileBuffer = (uint8*)Mem::Malloc( file_size );\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tFile::Read(p_fileBuffer, file_size, 1, pFile);\r\n\tFile::Close( pFile );\r\n\r\n\tbool success = build_casdata_table( p_fileBuffer );\r\n\r\n\tMem::Free(p_fileBuffer);\r\n\t\r\n\t// some debugging information for the artists\r\n\tif ( Script::GetInteger( \"DebugCAS\", Script::NO_ASSERT ) )\r\n\t{\r\n\t\tprintf( \"%s removes %08x: [\", pFileName, m_CASRemovalMask );\r\n\t\tfor ( int i = 0; i < 32; i++ )\r\n\t\t{\r\n\t\t\tuint32 mask = ( 1 << i );\r\n\t\t\tif ( m_CASRemovalMask & mask )\r\n\t\t\t{\r\n\t\t\t\tprintf( \" %d\", i );\r\n\t\t\t}\r\n\t\t}\r\n\t\tprintf( \"]\\n\" );\r\n\t}\r\n\r\n\treturn success;\r\n}\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool use_new_geom_format( const char* pMeshFileName )\r\n{\r\n\t// \"reetest\" is a quick kludge to get the skeletal trees\r\n\t// up and running...  eventually, pass this in as a parameter\r\n\t// from the nx.cpp level...\r\n\tif ( strstr( pMeshFileName, \"eh_\" ) || strstr( pMeshFileName, \"reetest\" ) )\r\n\t{\r\n\t\t// if it's a vehicle, then use the new geomnode format\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false; \r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Mesh::CPs2Mesh(uint32* pModelData, int modelDataSize, uint8* pCASData, Nx::CTexDict* pTexDict, uint32 texDictOffset, bool isSkin, bool doShadowVolume)\r\n{\r\n\tDbg_Assert( pTexDict );\r\n\r\n\tmp_texDict = pTexDict;\r\n\t\r\n\t// polys should only be hidden once\r\n\tm_polysAlreadyHidden = false;\r\n\r\n\tm_isPipped = false;\r\n\tm_numCASData = 0;\r\n\r\n\t// don't do this for models\r\n\tif ( isSkin && pCASData )\r\n\t{\r\n\t\tbuild_casdata_table( pCASData );\r\n\t}\r\n\t\r\n\t// GJ:  The geomnodes blow off the texDictOffset, \r\n\t// which means it won't work with skater models, \r\n\t// or the 10 board gameobjs in the boardshop.\r\n\tif ( !isSkin && texDictOffset == 0 )\r\n\t{\t\t \r\n\t\t// since we're not actually opening a PIP file\r\n\t\t// we don't need to keep track of it\r\n\t\tm_isPipped = false;\r\n\r\n\t\t// this should already be in GEOM format,\r\n\t\t// by the time the data arrives here...\r\n\t\t// (we're not loading up the Pip through the\r\n\t\t// normal Pip::Load process, so we need\r\n\t\t// to remember the pointer to the pip data\r\n\t\t// so that we can delete it later)\r\n\t\tmp_pipData = (uint8*)Mem::Malloc( modelDataSize );\r\n\t\tDbg_Assert( mp_pipData );\r\n\t\t\r\n\t\tmemcpy( mp_pipData, pModelData, modelDataSize );\r\n\r\n\t\t// process data in place\r\n\t\t// final arg (0) says to hold it in a database to be rendered later\r\n\t\t// (as opposed to rendering it unconditionally, LOADFLAG_RENDERNOW)\r\n\t\tmp_geomNode = NxPs2::CGeomNode::sProcessInPlace( mp_pipData, 0 );\r\n\r\n\t\t// Get hierarchy array\r\n\t\tmp_hierarchyObjects = (CHierarchyObject*) NxPs2::CGeomNode::sGetHierarchyArray(mp_pipData, m_numHierarchyObjects);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNxPs2::sScene* pTextureDictionary = ((Nx::CPs2TexDict*)mp_texDict)->GetEngineTextureDictionary();\r\n\t\r\n\t\tNxPs2::LoadScene( pModelData, modelDataSize, pTextureDictionary, true, true, texDictOffset, doShadowVolume );\r\n\r\n\t\tmp_geomNode = NULL;\r\n\t}\r\n\r\n\t// temporary lookup table is no longer needed\r\n\tNxPs2::DestroyCASDataLookupTable();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Mesh::CPs2Mesh(const char* pMeshFileName, Nx::CTexDict* pTexDict, uint32 texDictOffset, bool isSkin, bool doShadowVolume)\r\n{\r\n\tDbg_Assert( pTexDict );\r\n\r\n\tm_isPipped = false;\r\n\tmp_texDict = pTexDict;\r\n\t\r\n\tm_numCASData = 0;\r\n\r\n\t// don't do this for models\r\n\tif ( isSkin )\r\n\t{\r\n\t\tchar CASFileName[256];\r\n\t\tstrcpy(CASFileName, pMeshFileName);\r\n\t\tStr::LowerCase( CASFileName );\r\n\t\tchar* pExt = strstr( CASFileName, \"skin.ps2\" );\r\n\t\tif ( pExt )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( pExt, (\"Couldn't find skin.ps2 extension in %s\", CASFileName));\r\n\t\t\tstrcpy(pExt, \"cas.ps2\");\r\n\t\t\tbuild_casdata_table( CASFileName );\r\n\t\t}\r\n\t}\r\n\t\r\n\t// GJ:  The geomnodes blow off the texDictOffset, \r\n\t// which means it won't work with skater models, \r\n\t// or the 10 board gameobjs in the boardshop.\r\n\tif ( !isSkin && texDictOffset == 0 )\r\n\t{\t\t \r\n\t\t// change the file name so that it's using the new Geom\r\n\t\t// file format rather than Mdl.\r\n\t\tchar msg[512];\r\n\t\tstrcpy( msg, pMeshFileName );\r\n\t\tchar* pDot = strstr( msg, \".\" );\r\n\t\tDbg_Assert( pDot );\r\n\t\t*pDot = NULL;\r\n\t\tsprintf( pDot, \".geom.%s\", Nx::CEngine::sGetPlatformExtension() );\r\n\t\tm_pipFileName = msg;\r\n\t\tm_isPipped = true;\r\n\r\n//\t\tprintf( \"about to load pip file %s %d\\n\", m_pipFileName.getString(), texDictOffset );\r\n\r\n\t\t// Pip::Load the new file\r\n\t\tuint8* pPipData = (uint8*)Pip::Load( m_pipFileName.getString() );\r\n\r\n\t\tDbg_Assert( pPipData );\r\n\r\n\t\t// process data in place\r\n\t\t// final arg (0) says to hold it in a database to be rendered later\r\n\t\t// (as opposed to rendering it unconditionally, LOADFLAG_RENDERNOW)\r\n\t\tmp_geomNode = NxPs2::CGeomNode::sProcessInPlace( pPipData, 0 );\r\n\r\n\t\t// Find CGeomNodeObjects\r\n//\t\tif ( use_new_geom_format(pMeshFileName) )\r\n\t\t{\r\n\t\t\t// Get hierarchy array\r\n\t\t\tmp_hierarchyObjects = (CHierarchyObject *) NxPs2::CGeomNode::sGetHierarchyArray(pPipData, m_numHierarchyObjects);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNxPs2::sScene* pTextureDictionary = ((Nx::CPs2TexDict*)mp_texDict)->GetEngineTextureDictionary();\r\n\t\r\n\t\tNxPs2::LoadScene( pMeshFileName, pTextureDictionary, true, true, texDictOffset, doShadowVolume );\r\n\r\n\t\tmp_geomNode = NULL;\r\n\t}\r\n\r\n\t// temporary lookup table is no longer needed\r\n\tNxPs2::DestroyCASDataLookupTable();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Mesh::~CPs2Mesh()\r\n{\r\n\t//if (mp_geomNodeObjects)\r\n\t//{\r\n\t//\tdelete[] mp_geomNodeObjects;\r\n\t//}\r\n\r\n\tif ( mp_geomNode )\r\n\t{\r\n\t\t// clean up the node we created\r\n\t\tDbg_Assert( mp_geomNode );\r\n\t\tmp_geomNode->Cleanup();\r\n\r\n\t\t// Pip::Unload the file\r\n\t\tif ( m_isPipped )\r\n\t\t{\r\n\t\t\tPip::Unload( m_pipFileName.getString() );\r\n\t\t}\r\n\r\n\t\t// the file was not loaded using Pip::Load()\r\n\t\tif ( mp_pipData )\r\n\t\t{\r\n\t\t\tMem::Free( mp_pipData );\r\n\t\t\tmp_pipData = NULL;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNxPs2::sScene* pScene = ((Nx::CPs2TexDict*)mp_texDict)->GetEngineTextureDictionary();\r\n\t\r\n\t\t// unload scene\r\n\t\tNxPs2::DeleteScene( pScene );\r\n\t}\r\n\r\n\tif ( mp_CASData )\r\n\t{\r\n\t\tdelete[] mp_CASData;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Mesh::HidePolys( uint32 mask )\r\n{\r\n\tint count = 0;\r\n\r\n\t// this function should only be called once per mesh\r\n\t// because after the ADC bits are squeezed,\r\n\t// the pointers are no longer valid...\r\n\t// (was causing a crash in the secret level\r\n\t// with random peds that were doing poly removal)\r\n\tif ( m_polysAlreadyHidden )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n//\tprintf( \"Hiding polys with mask 0x%08x\\n\", mask);\r\n\r\n\tfor ( int j = 0; j < m_numCASData; j++ )\r\n\t{\r\n\t\tDbg_Assert( mp_CASData );\r\n\r\n\t\tif ( mp_CASData[j].mask & mask )\r\n\t\t{\r\n\t\t\tif ( mp_CASData[j].pADCBit )\r\n\t\t\t{\r\n\t\t\t\t*mp_CASData[j].pADCBit = 0xC000;\r\n\t\t\t}\r\n\t\t\tcount++;\r\n\t\t}\r\n\t}\r\n\r\n//\tprintf( \"Hiding %d polys\\n\", count );\r\n\r\n\tm_polysAlreadyHidden = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxMesh.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxMesh.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/15/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_MESH_H__\r\n#define\t__GFX_P_NX_MESH_H__\r\n    \r\n#include \"gfx/nxmesh.h\"\r\n\r\n#include <core/string/cstring.h>\r\n\t\t\t\r\nnamespace NxPs2\r\n{\r\n\tclass\tCGeomNode;\r\n\tstruct\tsCASData;\r\n}\r\n\t\t\t \r\nnamespace Nx\r\n{\r\n\r\n\tclass\tCHierarchyObject;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CMesh\r\n    \r\nclass CPs2Mesh : public CMesh\r\n{\r\n                                      \r\npublic:\r\n\tCPs2Mesh( uint32* pModelData, int modelDataSize, uint8* pCASData, Nx::CTexDict* pTexDict, uint32 texDictOffset, bool isSkin, bool doShadowVolume );\r\n\tCPs2Mesh( const char* pMeshFileName, Nx::CTexDict* pTexDict, uint32 texDictOffset, bool isSkin, bool doShadowVolume );\r\n\tvirtual \t\t\t~CPs2Mesh();\r\n\r\n\t// temporary?\r\n\tNxPs2::CGeomNode*\tGetGeomNode() { return mp_geomNode; }\r\n\tvoid\t\t\t\tHidePolys( uint32 mask );\r\n\r\nprotected:\r\n\tNxPs2::CGeomNode*\tmp_geomNode;\r\n\tbool\t\t\t\tm_polysAlreadyHidden:1;\r\n\tbool\t\t\t\tm_isPipped:1;\r\n\tuint8*\t\t\t\tmp_pipData;\t// for pip-style geoms that are loaded from a data buffer\r\n\tStr::String\t\t\tm_pipFileName;\r\n\r\n\tbool\t\t\t\tbuild_casdata_table(uint8* pCASData);\r\n\tbool\t\t\t\tbuild_casdata_table(const char* pFileName);\r\n\t\r\n\tNxPs2::sCASData*\tmp_CASData;\r\n\tint\t\t\t\t\tm_numCASData;\r\n};\r\n\r\n\r\n} // Nx\r\n\r\n#endif \r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxModel.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxModel.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/21/2001\r\n//****************************************************************************\r\n\r\n#include <gfx/ngps/p_nxmodel.h>\r\n\r\n#include <gfx/skeleton.h>\r\n#include \"gfx/nxgeom.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CPs2Model::plat_init_skeleton( int numBones )\r\n{\r\n\tDbg_Assert( mp_matrices == NULL );\r\n\r\n\t// matrix buffer is double-buffered\r\n\tmp_matrices = new Mth::Matrix[numBones * 2];\r\n\tfor ( int i = 0; i < numBones * 2; i++ )\r\n\t{\r\n\t\tmp_matrices[i].Identity();\r\n\t}\r\n    \r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CPs2Model::plat_get_bounding_sphere()\r\n{\r\n\tMth::Vector sphere, sphere1, sum, diff;\r\n\tfloat dist;\r\n\r\n\t// this should probably never happen\r\n\tif (m_numGeoms == 0)\r\n\t\treturn Mth::Vector(0.0f, 0.0f, 0.0f, 0.0f);\r\n\r\n\t// combine the spheres of all geoms\r\n\t// (this should really be done once at load time)\r\n\r\n\t// start with first sphere\r\n\tsphere = mp_geom[0]->GetBoundingSphere();\r\n\r\n\t// loop over remaining spheres, expanding as necessary\r\n\tfor (int i=1; i<m_numGeoms; i++)\r\n\t{\r\n\t\t// get next sphere\r\n\t\tsphere1 = mp_geom[i]->GetBoundingSphere();\r\n\r\n\t\t// centre-to-centre vector, and distance\r\n\t\tdiff = sphere1-sphere;\r\n\t\tdist = diff.Length();\r\n\r\n\t\t// test for sphere1 inside sphere\r\n\t\tif (dist+sphere1[3] <= sphere[3])\r\n\t\t\tcontinue;\t\t\t// keep sphere\r\n\r\n\t\t// test for sphere inside sphere1\r\n\t\tif (dist+sphere[3] <= sphere1[3])\r\n\t\t{\r\n\t\t\tsphere = sphere1;\t// replace sphere\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// otherwise make a larger sphere that contains both\r\n\t\tsum       = sphere+sphere1;\r\n\t\tsphere    = 0.5f * (sum + (diff[3]/dist) * diff);\r\n\t\tsphere[3] = 0.5f * (dist + sum[3]);\r\n\t}\r\n\r\n\treturn sphere;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Model::plat_set_bounding_sphere( const Mth::Vector& boundingSphere )\r\n{\r\n\t// loop over all spheres\r\n\tfor ( int i = 0; i < m_numGeoms; i++ )\r\n\t{\r\n\t\tmp_geom[i]->SetBoundingSphere( boundingSphere );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2Model::CPs2Model()\r\n{\r\n\tmp_matrices = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2Model::~CPs2Model()\r\n{\t\r\n\tif ( mp_matrices != NULL )\r\n\t{\r\n\t\tdelete[] mp_matrices;\r\n\t\tmp_matrices = NULL;\r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Matrix* CPs2Model::GetMatrices()\r\n{\r\n\treturn mp_matrices;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxModel.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxModel.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  1/8/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_MODEL_H__\r\n#define\t__GFX_P_NX_MODEL_H__\r\n    \r\n#include \"gfx/nxmodel.h\"\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\tclass CInstance;             \r\n\tstruct sScene;\r\n}\r\n\t\t\t\t\t\t\t   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CModel\r\n    \r\nclass CPs2Model : public CModel\r\n{\r\n                                      \r\npublic:\r\n\tCPs2Model();\r\n\tvirtual\t\t\t\t~CPs2Model();\r\n\tMth::Matrix*\t\tGetMatrices();\r\n\r\nprivate:\t\t\t\t// It's all private, as it is machine specific\r\n\tbool\t\t\t\tplat_init_skeleton( int numBones );\r\n\tMth::Vector \t\tplat_get_bounding_sphere();\r\n\tvoid\t\t\t\tplat_set_bounding_sphere( const Mth::Vector& boundingSphere );\r\n\r\nprivate:\r\n\tMth::Matrix*\t\tmp_matrices;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n#endif \r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxScene.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxScene.cpp\r\n\r\n#include \t\"Gfx/nx.h\"\r\n#include \t\"Gfx/NGPS/p_NxGeom.h\"\r\n#include \t\"Gfx/NGPS/p_NxScene.h\"\r\n#include \t\"Gfx/NGPS/p_NxSector.h\"\r\n#include \t\"Gfx/NGPS/NX/geomnode.h\"\r\n\r\n#include <libgraph.h>\r\n\r\n#include <sys/file/pip.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Scene::CPs2Scene()\r\n{\r\n\tmp_plat_scene = NULL;\r\n\tmp_plat_clone_scene = NULL;\r\n\tmp_plat_add_scene = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Scene::~CPs2Scene()\r\n{\r\n\tif (mp_plat_clone_scene)\r\n\t{\r\n\t\t// Have to delete the sectors here first\r\n\t\tmp_sector_table->IterateStart();\r\n\t\tCSector *p_sector;\r\n\t\twhile ((p_sector = mp_sector_table->IterateNext()))\r\n\t\t{\r\n\t\t\tp_sector->clear_flags(CSector::mIN_SUPER_SECTORS);\t// Tells cloned sectors it is OK to go away (and SuperSectors will be dead, anyway)\r\n\t\t\tdelete p_sector;\r\n\t\t}\r\n\t\tdelete mp_sector_table;\r\n\t\tmp_sector_table = NULL;\r\n\r\n\t\tmp_plat_clone_scene->Cleanup();\r\n\t\tdelete mp_plat_clone_scene;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNxPs2::CGeomNode *\tCPs2Scene::GetEngineScene() const\r\n{\r\n\treturn mp_plat_scene;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2Scene::SetEngineScene(NxPs2::CGeomNode *p_scene)\r\n{\r\n\tmp_plat_scene = p_scene;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNxPs2::CGeomNode *\tCPs2Scene::GetEngineCloneScene() const\r\n{\r\n\treturn mp_plat_clone_scene;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2Scene::SetEngineCloneScene(NxPs2::CGeomNode *p_scene)\r\n{\r\n\tmp_plat_clone_scene = p_scene;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNxPs2::CGeomNode *\tCPs2Scene::GetEngineAddScene() const\r\n{\r\n\treturn mp_plat_add_scene;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2Scene::SetEngineAddScene(NxPs2::CGeomNode *p_scene)\r\n{\r\n\tmp_plat_add_scene = p_scene;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CScene\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2Scene::create_sectors(NxPs2::CGeomNode *p_node)\r\n{\r\n\tif (!p_node)\r\n\t\treturn;\r\n\r\n\twhile (p_node)\r\n\t{\r\n\t\t// Recursively traverse tree, treating the object-level nodes as leaves.\r\n\t\t// From each object, create a sector.\r\n\t\t// (Mick: optimized tail recursion, after suggestion from John Brandwood)\r\n\t\tif (p_node->IsObject())\t\t\t// Create CSector from object\r\n\t\t{\r\n\t\t\tCSector *pSector;\r\n\t\t\tCPs2Sector *pPs2Sector;\t\t// platform dependent class\r\n\t\t\tCPs2Geom *pGeom;\r\n\t\r\n\t\t\t// Find Sector\r\n\t\t\tpSector = GetSector(p_node->GetChecksum());\r\n\t\t\tDbg_MsgAssert(!pSector, (\"We already have a sector with checksum %x\", p_node->GetChecksum()));\r\n\t\r\n\t\t\t// If it doesn't exist yet, create it\r\n\t\t\tif (!pSector)\r\n\t\t\t{\r\n\t\t\t\tpSector = new CPs2Sector;\t\t// Create platform specific data\r\n\t\t\t\tpSector->SetChecksum(p_node->GetChecksum());\r\n\t\r\n\t\t\t\tpGeom = new CPs2Geom;\r\n\t\t\t\tpGeom->SetEngineObject(p_node);\r\n\t\r\n\t\t\t\tpSector->SetGeom(pGeom);\r\n\t\r\n\t\t\t\tAddSector(pSector);\r\n\t\r\n\t\t\t\t//Dbg_Message(\"Creating new sector %x\", p_node->GetChecksum());\r\n\t\t\t}\r\n\t\r\n\t\t\t// Access platform dependent data\r\n\t\t\tpPs2Sector = static_cast<CPs2Sector *>(pSector);\r\n\t\r\n\t\t\t// Add node to sector\r\n\t\t\t//pPs2Sector->SetEngineObject(p_node);\r\n\t\t\tpPs2Sector->SetEngineObject(NULL);\r\n\t\t} else {\t// Traverse children and siblings\r\n\t\t\tcreate_sectors(p_node->GetChild());\r\n\t\t}\r\n\t\r\n\t\tp_node = p_node->GetSibling();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2Scene::add_sectors(NxPs2::CGeomNode *p_node)\r\n{\r\n\tif (!p_node)\r\n\t\treturn;\r\n\r\n\t// Recursively traverse tree, treating the object-level nodes as leaves.\r\n\t// From each object, create a sector.\r\n\tif (p_node->IsObject())\t\t\t// Create CSector from object\r\n\t{\r\n\t\tCSector *pSector, *p_found_sector;\r\n\t\tCPs2Sector *pPs2Sector;\t\t// platform dependent class\r\n\t\tCPs2Geom *pGeom;\r\n\r\n\t\t// Find Sector\r\n\t\tp_found_sector = GetSector(p_node->GetChecksum());\r\n\t\t//Dbg_MsgAssert(!pSector, (\"We already have a sector with checksum %x\", p_node->GetChecksum()));\r\n\r\n\t\t// Even if it does exist, create it\r\n\t\tpSector = new CPs2Sector;\t\t// Create platform specific data\r\n\t\tpSector->SetChecksum(p_node->GetChecksum());\r\n\r\n\t\tpGeom = new CPs2Geom;\r\n\t\tpGeom->SetEngineObject(p_node);\r\n\r\n\t\tpSector->SetGeom(pGeom);\r\n\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tCSector *p_old_sector =\r\n\t\t#endif\r\n\t\tReplaceSector(pSector);\r\n\r\n\t\tDbg_Assert(p_old_sector == p_found_sector);\r\n\t\t//Dbg_Message(\"Creating new sector %x\", p_node->GetChecksum());\r\n\r\n\t\t// Access platform dependent data\r\n\t\tpPs2Sector = static_cast<CPs2Sector *>(pSector);\r\n\r\n\t\t// Add node to sector\r\n\t\tpPs2Sector->SetEngineObject(NULL);\r\n\t} else {\t// Traverse children and siblings\r\n\t\tadd_sectors(p_node->GetChild());\r\n\t}\r\n\r\n\tadd_sectors(p_node->GetSibling());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2Scene::delete_sectors(NxPs2::CGeomNode *p_node)\r\n{\r\n\tif (!p_node)\r\n\t\treturn;\r\n\r\n\t// Recursively traverse tree, treating the object-level nodes as leaves.\r\n\t// From each object, delete the sector.\r\n\tif (p_node->IsObject())\t\t\t// Create CSector from object\r\n\t{\r\n\t\t// Find Sector\r\n\t\tCSector *pSector = GetSector(p_node->GetChecksum());\r\n\t\tDbg_MsgAssert(pSector, (\"Cant find a sector with checksum %x to delete\", p_node->GetChecksum()));\r\n\r\n\t\tDeleteSector(pSector);\r\n\t} else {\t// Traverse children and siblings\r\n\t\tdelete_sectors(p_node->GetChild());\r\n\t}\r\n\r\n\tdelete_sectors(p_node->GetSibling());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2Scene::plat_post_load()\r\n{\r\n\t// Generate CSectors first\r\n\t// Garrett: TEMP HACK: We don't want to traverse siblings, so we send down the child.\r\n\t//          This works because we know there won't be any data in the root node.\r\n\t//          THIS WILL GO AWAY VERY SOON.  DON'T COPY THIS HACK WITHOUT THIS MESSAGE.\r\n\tcreate_sectors(mp_plat_scene->GetChild());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2Scene::plat_post_add()\r\n{\r\n\t// Generate CSectors first\r\n\t// Garrett: TEMP HACK: We don't want to traverse siblings, so we send down the child.\r\n\t//          This works because we know there won't be any data in the root node.\r\n\t//          THIS WILL GO AWAY VERY SOON.  DON'T COPY THIS HACK WITHOUT THIS MESSAGE.\r\n\tadd_sectors(mp_plat_add_scene->GetChild());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2Scene::plat_load_textures(const char *p_name)\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2Scene::plat_load_collision(const char *p_name)\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2Scene::plat_add_collision(const char *p_name)\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2Scene::plat_unload_add_scene()\r\n{\r\n\tif (mp_plat_add_scene)\r\n\t{\r\n\t\tsceGsSyncPath(0, 0);\r\n\r\n\t\t// Delete CSectors first\r\n\t\t// Garrett: TEMP HACK: We don't want to traverse siblings, so we send down the child.\r\n\t\t//          This works because we know there won't be any data in the root node.\r\n\t\t//          THIS WILL GO AWAY VERY SOON.  DON'T COPY THIS HACK WITHOUT THIS MESSAGE.\r\n\t\t//delete_sectors(mp_plat_add_scene->GetChild());\r\n\r\n\t\t// clean up the node we created\r\n\t\tmp_plat_add_scene->Cleanup();\r\n\r\n\t\t// Pip::Unload the file\r\n\t\tPip::Unload(m_add_scene_filename);\r\n\t\tm_add_scene_filename[0] = '\\0';\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Create an empty sector\r\nCSector\t*\t\t\tCPs2Scene::plat_create_sector()\r\n{\r\n\tCPs2Sector * p_sector = new CPs2Sector(); \r\n\r\n\treturn p_sector;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid\t\t\t\tCPs2Scene::plat_set_majority_color(Image::RGBA rgba)\r\n{\r\n\tif (mp_plat_scene)\r\n\t{\r\n\t\t// Set the color of the root node\r\n\t\tmp_plat_scene->SetColored(true);\r\n\t\tmp_plat_scene->SetColor(*((uint32 *) &rgba));\r\n\t}\r\n\tif (mp_plat_clone_scene)\r\n\t{\r\n\t\t// Set the color of the root clone node\r\n\t\tmp_plat_clone_scene->SetColored(true);\r\n\t\tmp_plat_clone_scene->SetColor(*((uint32 *) &rgba));\r\n\t}\r\n}\r\n\t\t \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nImage::RGBA\t\t\tCPs2Scene::plat_get_majority_color() const\r\n{\r\n\tuint32 color = mp_plat_scene->GetColor();\r\n\treturn *((Image::RGBA *) &color);\r\n}\r\n\t\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxScene.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxScene.h\r\n\r\n#ifndef\t__GFX_P_NX_SCENE_H__\r\n#define\t__GFX_P_NX_SCENE_H__\r\n\r\n#include \t\"Gfx/nxscene.h\"\r\n\r\nnamespace NxPs2\r\n{\r\n\tclass CGeomNode;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CScene\r\nclass\tCPs2Scene : public CScene\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCPs2Scene();\r\n\tvirtual\t\t\t\t\t\t~CPs2Scene();\r\n\r\n\tNxPs2::CGeomNode *\t\t\tGetEngineScene() const;\r\n\tvoid\t\t\t\t\t\tSetEngineScene(NxPs2::CGeomNode *p_scene);\r\n\r\n\tNxPs2::CGeomNode *\t\t\tGetEngineAddScene() const;\r\n\tvoid\t\t\t\t\t\tSetEngineAddScene(NxPs2::CGeomNode *p_scene);\r\n\r\n\tNxPs2::CGeomNode *\t\t\tGetEngineCloneScene() const;\r\n\tvoid\t\t\t\t\t\tSetEngineCloneScene(NxPs2::CGeomNode *p_scene);\r\n\r\nprivate:\t\t\r\n\tvirtual void\t\t\t\tplat_post_load();\t\r\n\tvirtual void\t\t\t\tplat_post_add();\t\r\n\tvirtual bool\t\t\t\tplat_load_textures(const char *p_name);\t\t// load textures \r\n\tvirtual bool\t\t\t\tplat_load_collision(const char *p_name);\t// load collision data\r\n\tvirtual bool\t\t\t\tplat_add_collision(const char *p_name);\t\t// add collision data\r\n\tvirtual bool\t\t\t\tplat_unload_add_scene();\t\t\t\t\t// unloads previous add scene\r\n\tvirtual\tCSector\t*\t\t\tplat_create_sector();\t \t\t\t\t\t// empty sector\r\n\tvirtual void\t\t\t\tplat_set_majority_color(Image::RGBA rgba);\t// set the most common sector color\r\n\tvirtual Image::RGBA\t\t\tplat_get_majority_color() const;\t\t\t// get the most common sector color\r\n\t\r\n\r\n\tvoid\t\t\t\t\t\tcreate_sectors(NxPs2::CGeomNode *p_node);\r\n\tvoid\t\t\t\t\t\tadd_sectors(NxPs2::CGeomNode *p_node);\r\n\tvoid\t\t\t\t\t\tdelete_sectors(NxPs2::CGeomNode *p_node);\r\n\r\n\tNxPs2::CGeomNode *\t\t\tmp_plat_scene;\t\t// Platform-dependent data\r\n\tNxPs2::CGeomNode *\t\t\tmp_plat_clone_scene;\r\n\tNxPs2::CGeomNode *\t\t\tmp_plat_add_scene;\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxSector.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxSector.cpp\r\n\r\n#include \t\"Gfx/nx.h\"\r\n#include \t\"Gfx/NGPS/p_NxGeom.h\"\r\n#include \t\"Gfx/NGPS/p_NxSector.h\"\r\n#include \t\"Gfx/NxMiscFX.h\"\r\n#include \t<gfx/image/imagebasic.h>\r\n#include \t\"gfx\\ngps\\nx\\geomnode.h\"\r\n\r\n#include \t\"gel/collision/collision.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Sector::CPs2Sector() :\r\n\tmp_plat_object(NULL), \r\n\tm_rgba(Image::RGBA(128, 128, 128, 128)),\r\n\tm_shatter(false)\r\n{\r\n\tm_world_matrix.Ident();\r\n\tm_active = true;\t\t\t\t\t\t// default to be active....\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Sector::~CPs2Sector()\r\n{\r\n\tif (mp_geom)\r\n\t{\r\n\t\t//CPs2Geom *p_ps2_geom = static_cast<CPs2Geom *>(mp_geom);\r\n\t\t//p_ps2_geom->SetEngineObject(NULL);\t\t// Hack so that CGeom doesn't try to free the CGeomNode\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CSector\r\n// and we will also have a CXboxSector, CNgcSector, even a CPcSector\r\n// maybe in the future we will have a CPS3Sector?\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Sector::plat_set_color(Image::RGBA rgba)\r\n{\r\n\t// Set values\r\n\tm_rgba = rgba;\r\n\r\n\t// Engine call here\r\n\tif (mp_plat_object)\r\n\t{\r\n\t\tmp_plat_object->SetColored(true);\r\n\t\tmp_plat_object->SetColor(*((uint32 *) &rgba));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA CPs2Sector::plat_get_color() const\r\n{\r\n\treturn m_rgba;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Sector::plat_clear_color()\r\n{\r\n#if 0\r\n\t// Set to white\r\n\tplat_set_color(Image::RGBA(128, 128, 128, 128));\r\n#endif\r\n\t// Engine call here\r\n\tif (mp_plat_object)\r\n\t{\r\n\t\tmp_plat_object->SetColored(false);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Sector::plat_set_visibility(uint32 mask)\r\n{\r\n\t// Engine call here\r\n\tif (mp_plat_object)\r\n\t{\r\n\t\tmp_plat_object->SetVisibility(mask & 0xFF);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CPs2Sector::plat_get_visibility() const\r\n{\r\n\tif ( mp_plat_object )\r\n\t{\r\n\t\treturn mp_plat_object->GetVisibility() | 0xFFFFFF00;\t\t// To keep format compatible\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Sector::plat_set_active(bool on)\t\r\n{\r\n\t// Set values\r\n\tif (m_active != on)\r\n\t{\r\n\t\tm_active = on;\r\n\r\n\t\tif (mp_plat_object)\r\n\t\t{\r\n\t\t\t// Engine call here\r\n\t\t\tmp_plat_object->SetActive(on);\r\n\t\t}\r\n\t}\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPs2Sector::plat_is_active() const\r\n{\r\n\treturn m_active;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::CBBox & CPs2Sector::plat_get_bounding_box() const\r\n{\r\n\t// Garrett: TODO: change to renderable bounding box\r\n\tDbg_Assert(mp_coll_sector);\r\n\tDbg_Assert(mp_coll_sector->GetGeometry());\r\n\treturn mp_coll_sector->GetGeometry()->GetBBox();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Sector::plat_set_world_position(const Mth::Vector& pos)\r\n{\r\n\t // Set values\r\n\t m_world_matrix[W] = pos;\r\n\r\n\t // Engine call here\r\n\t // TEMP, just update matrix of CGeomNode\r\n\t update_engine_matrix();\r\n }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\tCPs2Sector::plat_get_world_position() const\r\n{\r\n\treturn m_world_matrix[W];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Sector::plat_set_y_rotation(Mth::ERot90 rot)\r\n{\r\n\t// Engine call here\r\n\t// Garrett: TEMP just set the world matrix\r\n\tMth::Matrix orig_rot_mat(m_world_matrix), rot_mat;\r\n\tfloat rad = (float) ((int) rot) * (Mth::PI * 0.5f);\r\n\tCreateRotateYMatrix(rot_mat, rad);\r\n\r\n\torig_rot_mat[W] = Mth::Vector(0.0f, 0.0f, 0.0f, 1.0f);\r\n\r\n\trot_mat = orig_rot_mat * rot_mat;\r\n\t//Dbg_Message(\"[X] (%f, %f, %f, %f)\", rot_mat[X][X], rot_mat[X][Y],  rot_mat[X][Z],  rot_mat[X][W]);\r\n\t//Dbg_Message(\"[Y] (%f, %f, %f, %f)\", rot_mat[Y][X], rot_mat[Y][Y],  rot_mat[Y][Z],  rot_mat[Y][W]);\r\n\t//Dbg_Message(\"[Z] (%f, %f, %f, %f)\", rot_mat[Z][X], rot_mat[Z][Y],  rot_mat[Z][Z],  rot_mat[Z][W]);\r\n\t//Dbg_Message(\"[W] (%f, %f, %f, %f)\", rot_mat[W][X], rot_mat[W][Y],  rot_mat[W][Z],  rot_mat[W][W]);\r\n\t\r\n\tm_world_matrix[X] = rot_mat[X];\r\n\tm_world_matrix[Y] = rot_mat[Y];\r\n\tm_world_matrix[Z] = rot_mat[Z];\r\n\r\n\tupdate_engine_matrix();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Sector::update_engine_matrix()\r\n{\r\n\tif ( mp_plat_object )\r\n\t{\r\n\t\tmp_plat_object->SetMatrix(&m_world_matrix);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2Sector::plat_set_shatter(bool on)\t\r\n{\r\n\t// Set values\r\n\tm_shatter = on;\r\n\r\n\t// Engine call here\r\n\tif( on && mp_geom )\r\n\t{\r\n\t\tShatter( mp_geom );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPs2Sector::plat_get_shatter() const\r\n{\r\n\treturn m_shatter;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSector * CPs2Sector::plat_clone(bool instance, CScene *p_dest_scene)\r\n{\r\n\t// Copy into new sector\r\n\tCPs2Sector *p_new_sector = new CPs2Sector(*this);\r\n\r\n\t// Copy engine data\r\n\tif (p_new_sector && mp_plat_object)\r\n\t{\r\n\t\tif (instance)\r\n\t\t{\r\n\t\t\tp_new_sector->mp_plat_object = mp_plat_object->CreateInstance(&p_new_sector->m_world_matrix);\r\n\t\t} else {\r\n\t\t\tp_new_sector->mp_plat_object = mp_plat_object->CreateInstance(&p_new_sector->m_world_matrix);\r\n\t\t\tDbg_Message(\"CPs2Sector: Can't create copy of CGeomNode yet\");\r\n\t\t\t//p_new_sector->mp_plat_object = mp_plat_object->CreateCopy();\r\n\t\t}\r\n\t}\r\n\r\n\treturn p_new_sector;\r\n}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxSector.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxSector.h\r\n\r\n#ifndef\t__GFX_P_NX_SECTOR_H__\r\n#define\t__GFX_P_NX_SECTOR_H__\r\n\r\n#include \t<core/math.h>\r\n\r\n#include \t<gfx/nxsector.h>\r\n#include \t<gfx/image/imagebasic.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\tclass CGeomNode;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CSector\r\n// and we will also have a CXboxSector, CNgcSector, even a CPcSector\r\n// maybe in the future we will have a CPS3Sector?\r\nclass\tCPs2Sector : public CSector\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCPs2Sector();\r\n\tvirtual\t\t\t\t\t\t~CPs2Sector();\r\n\r\n\tvoid\t\t\t\t\t\tSetEngineObject(NxPs2::CGeomNode *p_object);\r\n\tNxPs2::CGeomNode *\t\t\tGetEngineObject() const;\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\tvirtual void\t\t\t\tplat_set_color(Image::RGBA rgba);\r\n\tvirtual\tImage::RGBA\t\t\tplat_get_color() const;\r\n\tvirtual void\t\t\t\tplat_clear_color();\r\n\r\n\tvirtual void\t\t\t\tplat_set_visibility(uint32 mask);\r\n\tvirtual\tuint32\t\t\t\tplat_get_visibility() const;\r\n\r\n\tvirtual void\t\t\t\tplat_set_active(bool on);\t\r\n\tvirtual\tbool\t\t\t\tplat_is_active() const;\r\n\r\n\tvirtual const Mth::CBBox &\tplat_get_bounding_box() const;\r\n\r\n\tvirtual void\t\t\t\tplat_set_world_position(const Mth::Vector& pos);\r\n\tvirtual const Mth::Vector &\tplat_get_world_position() const;\r\n\r\n\tvirtual void\t\t\t\tplat_set_y_rotation(Mth::ERot90 rot);\r\n\r\n\tvirtual\tvoid\t\t\t\tplat_set_shatter(bool on);\r\n\tvirtual\tbool\t\t\t\tplat_get_shatter() const;\r\n\t\r\n\tvirtual CSector *\t\t\tplat_clone(bool instance, CScene *p_dest_scene = NULL);\r\n\r\n\t// local functions\r\n\tvoid \t\t\t\t\t\tupdate_engine_matrix();\r\n\r\n\tNxPs2::CGeomNode *\t\t\tmp_plat_object;\r\n\r\n\tMth::Matrix\t\t\t\t\tm_world_matrix;\r\n\r\n\tImage::RGBA\t\t\t\t\tm_rgba;\r\n\tbool\t\t\t\t\t\tm_active;\r\n\tbool\t\t\t\t\t\tm_shatter;\r\n};\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Inlines\r\n//\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCPs2Sector::SetEngineObject(NxPs2::CGeomNode *p_object)\r\n{\r\n\tmp_plat_object = p_object;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline NxPs2::CGeomNode *\tCPs2Sector::GetEngineObject() const\r\n{\r\n\treturn mp_plat_object;\r\n}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxSprite.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxSprite.cpp\r\n\r\n#include \t\"Gfx/NGPS/p_NxSprite.h\"\r\n#include \t\"Gfx/NGPS/p_NxTexture.h\"\r\n#include \t\"Gfx/NGPS/p_NxWin2D.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CSprite\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Sprite::CPs2Sprite(CWindow2D *p_window) : CSprite(p_window)\r\n{\r\n\tmp_plat_sprite = new NxPs2::SSprite();\r\n\r\n\tplat_initialize();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Sprite::~CPs2Sprite()\r\n{\r\n\tdelete mp_plat_sprite;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCPs2Sprite::plat_initialize()\r\n{\r\n\tplat_update_engine();\r\n\tplat_update_priority();\r\n\tplat_update_hidden();\r\n\tplat_update_window();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCPs2Sprite::plat_update_hidden()\r\n{\r\n\t// Take sprite on or off draw list\r\n\tmp_plat_sprite->SetHidden(m_hidden);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCPs2Sprite::plat_update_engine()\r\n{\r\n\tCPs2Texture *p_ps2_texture = static_cast<CPs2Texture *>(mp_texture);\r\n\r\n\t// Rebuild sprite primitives\r\n\tif (p_ps2_texture)\r\n\t{\r\n\t\tmp_plat_sprite->SetTexture(p_ps2_texture->GetSingleTexture());\r\n\t} else {\r\n\t\tmp_plat_sprite->SetTexture(NULL);\r\n\t}\r\n\r\n\tmp_plat_sprite->m_xpos\t\t= m_pos_x;\r\n\tmp_plat_sprite->m_ypos\t\t= m_pos_y;\r\n\tmp_plat_sprite->m_width\t\t= m_width;\r\n\tmp_plat_sprite->m_height\t= m_height;\r\n\tmp_plat_sprite->m_scale_x\t= m_scale_x;\r\n\tmp_plat_sprite->m_scale_y\t= m_scale_y;\r\n\r\n\tmp_plat_sprite->m_xhot\t\t= ((m_anchor_x + 1.0f) * 0.5f) * (m_width);\r\n\tmp_plat_sprite->m_yhot\t\t= ((m_anchor_y + 1.0f) * 0.5f) * (m_height);\r\n\r\n\tmp_plat_sprite->m_rot\t\t= m_rotation;\r\n\tmp_plat_sprite->m_rgba\t\t= *((uint32 *) &m_rgba);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCPs2Sprite::plat_update_priority()\r\n{\r\n\t// Update draw list\r\n\tif (m_use_zbuffer)\r\n\t{\r\n\t\tmp_plat_sprite->SetZValue((uint32) m_zvalue);\r\n\t} else {\r\n\t\tmp_plat_sprite->SetPriority(m_priority);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCPs2Sprite::plat_update_window()\r\n{\r\n\tCPs2Window2D *p_ps2_window = static_cast<CPs2Window2D *>(mp_window);\r\n\r\n\tif (p_ps2_window)\r\n\t{\r\n\t\tmp_plat_sprite->SetScissorWindow(p_ps2_window->GetEngineWindow());\r\n\t} else {\r\n\t\tmp_plat_sprite->SetScissorWindow(NULL);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCSprite::plat_enable_constant_z_value(bool enable)\r\n{\r\n\tNxPs2::SSprite::EnableConstantZValue(enable);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCSprite::plat_set_constant_z_value(Nx::ZBufferValue z)\r\n{\r\n\tNxPs2::SSprite::SetConstantZValue(z);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::ZBufferValue\tCSprite::plat_get_constant_z_value()\r\n{\r\n\treturn NxPs2::SSprite::GetConstantZValue();\r\n}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxSprite.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxScene.h\r\n\r\n#ifndef\t__GFX_P_NX_SPRITE_H__\r\n#define\t__GFX_P_NX_SPRITE_H__\r\n\r\n#include \t\"Gfx/NxSprite.h\"\r\n#include \t\"Gfx/NGPS/NX/texture.h\"\r\n#include \t\"Gfx/NGPS/NX/sprite.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Machine specific implementation of the CSprite\r\nclass\tCPs2Sprite : public CSprite\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCPs2Sprite(CWindow2D *p_window = NULL);\r\n\tvirtual\t\t\t\t\t\t~CPs2Sprite();\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\tvirtual void\t\t\t\tplat_initialize();\r\n\r\n\tvirtual void\t\t\t\tplat_update_hidden();\t\t// Tell engine of update\r\n\tvirtual void\t\t\t\tplat_update_engine();\t\t// Update engine primitives\r\n\tvirtual void\t\t\t\tplat_update_priority();\r\n\tvirtual void\t\t\t\tplat_update_window();\r\n\r\n\tNxPs2::SSprite *\t\t\tmp_plat_sprite;\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxTexMan.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxTexMan.cpp - PS2 platform specific interface to CTexMan\r\n//\r\n// This is PS2 SPECIFIC!!!!!!  So might get a bit messy\r\n\r\n#include <core/defines.h>\r\n\r\n#include \"gfx/NxTexMan.h\"\r\n#include \"gfx/NGPS/p_NxTexture.h\"\r\n\r\n#include <libgraph.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\tvoid WaitForRendering();\r\n}\r\n\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexDict *\t\tCTexDictManager::s_plat_load_texture_dictionary(const char *p_tex_dict_name, bool is_level_data, uint32 texDictOffset, bool isSkin, bool forceTexDictLookup)\r\n{\r\n\treturn new CPs2TexDict(p_tex_dict_name, is_level_data, texDictOffset, isSkin, forceTexDictLookup);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexDict *\t\tCTexDictManager::s_plat_load_texture_dictionary(uint32 checksum, uint32* pData, int dataSize, bool is_level_data, uint32 texDictOffset, bool isSkin, bool forceTexDictLookup)\r\n{\r\n\tCPs2TexDict* pTexDict = new CPs2TexDict( checksum );\r\n\tpTexDict->LoadTextureDictionary(NULL, pData, dataSize, is_level_data, texDictOffset, isSkin, forceTexDictLookup);\r\n\treturn pTexDict;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexDict *\t\tCTexDictManager::s_plat_create_texture_dictionary(uint32 checksum)\r\n{\r\n\treturn new CPs2TexDict(checksum);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCTexDictManager::s_plat_unload_texture_dictionary(CTexDict *p_tex_dict)\r\n{\r\n\t#if 0\r\n\tsceGsSyncPath(0, 0);\t\t// To make sure it isn't being used\r\n\t#else\r\n\tNxPs2::WaitForRendering();\r\n\t#endif\r\n\t\r\n\tdelete p_tex_dict;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n} \r\n \r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxTexture.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxTexture.cpp\r\n\r\n#include \t\"Gfx/gfxutils.h\"\r\n#include \t\"Gfx/Nx.h\"\r\n#include \t\"Gfx/NGPS/p_NxTexture.h\"\r\n#include \t\"Gfx/NGPS/PaletteGen.h\"\r\n#include\t\"Gfx/NGPS/nx/scene.h\"\r\n#include\t\"Gfx/NGPS/nx/sprite.h\"\r\n#include\t<gel/scripting/checksum.h>\r\n#include\t<gel/scripting/script.h>\r\n#include\t<gel/scripting/symboltable.h>\r\n\r\n#define min(x, y) (((x) > (y))? (y): (x))\r\n#define max(x, y) (((x) < (y))? (y): (x))\r\n\r\n#define USE_FAST_COLOR_FIND 1\r\n#define PRINT_TIMES 0\r\n#define PRINT_FAST_TIMES 0\r\n\r\nnamespace Nx\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CTexture\r\n\r\nbool\t\t\t\tCPs2Texture::s_tables_initialized = false;\r\nuint8\t\t\t\tCPs2Texture::s_clut8_index_to_offset_table[256];\r\nuint8\t\t\t\tCPs2Texture::s_clut8_offset_to_index_table[256];\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Texture::CPs2Texture(bool loading_screen) :\r\n\tm_transparent(false),\r\n\tm_loading_screen(loading_screen),\r\n\tmp_single_texture(NULL),\r\n\tmp_group_texture(NULL),\r\n\tmp_orig_temp_32bit_image(NULL),\r\n\tmp_cur_temp_32bit_image(NULL),\r\n\tmp_temp_32bit_single_texture(NULL)\r\n{\r\n\tm_width = m_height = m_bitdepth = m_clut_bitdepth = m_num_mipmaps = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Texture::CPs2Texture(const CPs2Texture & src_texture) :\r\n\tCTexture(src_texture)\r\n{\r\n\tDbg_MsgAssert(src_texture.mp_group_texture == NULL, (\"Can't copy a CPs2Texture that is in a texture group\"));\r\n\r\n\tm_width = src_texture.m_width;\r\n\tm_height = src_texture.m_height;\r\n\tm_bitdepth = src_texture.m_bitdepth;\r\n\tm_clut_bitdepth = src_texture.m_clut_bitdepth;\r\n\tm_num_mipmaps = src_texture.m_num_mipmaps;\r\n\r\n\tm_transparent = src_texture.m_transparent;\r\n\tm_loading_screen = src_texture.m_loading_screen;\r\n\r\n\tmp_group_texture = NULL;\r\n\r\n\tif (src_texture.mp_orig_temp_32bit_image)\r\n\t{\r\n\t\tmp_orig_temp_32bit_image = new uint32[m_width * m_height];\r\n\t\tmemcpy(mp_orig_temp_32bit_image, src_texture.mp_orig_temp_32bit_image, m_width * m_height * sizeof(uint32));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_orig_temp_32bit_image = NULL;\r\n\t}\r\n\r\n\tif (src_texture.mp_cur_temp_32bit_image)\r\n\t{\r\n\t\tmp_cur_temp_32bit_image = new uint32[m_width * m_height];\r\n\t\tmemcpy(mp_cur_temp_32bit_image, src_texture.mp_cur_temp_32bit_image, m_width * m_height * sizeof(uint32));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_cur_temp_32bit_image = NULL;\r\n\t}\r\n\r\n\tif (src_texture.mp_single_texture)\r\n\t{\r\n\t\tmp_single_texture = new NxPs2::SSingleTexture(*src_texture.mp_single_texture);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_single_texture = NULL;\r\n\t}\r\n\r\n\tif (src_texture.mp_temp_32bit_single_texture)\r\n\t{\r\n\t\tmp_temp_32bit_single_texture = new NxPs2::SSingleTexture(*src_texture.mp_temp_32bit_single_texture);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_temp_32bit_single_texture = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Texture::~CPs2Texture()\r\n{\r\n\t// delete the actual single texture, if any\r\n\tif (mp_single_texture)\r\n\t{\r\n\t\tdelete mp_single_texture;\r\n\t}\r\n\r\n\tif (mp_orig_temp_32bit_image)\r\n\t{\r\n\t\tdelete mp_orig_temp_32bit_image;\r\n\t}\r\n\r\n\tif (mp_cur_temp_32bit_image)\r\n\t{\r\n\t\tdelete mp_cur_temp_32bit_image;\r\n\t}\r\n\r\n\tif (mp_temp_32bit_single_texture)\r\n\t{\r\n\t\tdelete mp_temp_32bit_single_texture;\r\n\t}\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \tCPs2Texture::sInitTables()\r\n{\r\n    if (!s_tables_initialized)\r\n\t{\r\n\t\tuint i, j, idx;\r\n\r\n\t\tidx = 0;\r\n        for(i = 0; i < 256; i+=32)\r\n\t\t{\r\n            for(j = i; j < i+8; j++)\r\n                s_clut8_index_to_offset_table[j] = (uint8) idx++;\r\n            for(j = i+16; j < i+16+8; j++)\r\n                s_clut8_index_to_offset_table[j] = (uint8) idx++;\r\n            for(j = i+8;  j < i+8+8;  j++)\r\n                s_clut8_index_to_offset_table[j] = (uint8) idx++;\r\n            for(j = i+24; j < i+24+8; j++)\r\n                s_clut8_index_to_offset_table[j] = (uint8) idx++;\r\n        }\r\n\r\n\t\tidx = 0;\r\n\t\tfor(i = 0; i < 256; i+=32)\r\n\t\t{\r\n\t\t\tfor(j = i; j < i+8; j++)\r\n\t\t\t\ts_clut8_offset_to_index_table[idx++] = (uint8) j;\r\n\t\t\tfor(j = i+16; j < i+16+8; j++)\r\n\t\t\t\ts_clut8_offset_to_index_table[idx++] = (uint8) j;\r\n\t\t\tfor(j = i+8;  j < i+8+8;  j++)\r\n\t\t\t\ts_clut8_offset_to_index_table[idx++] = (uint8) j;\r\n\t\t\tfor(j = i+24; j < i+24+8; j++)\r\n\t\t\t\ts_clut8_offset_to_index_table[idx++] = (uint8) j;\r\n\t\t}\r\n\t\r\n        s_tables_initialized = true;\r\n\t}\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_load_texture(const char *p_texture_name, bool sprite, bool alloc_vram)\r\n{\r\n\tDbg_Assert(mp_group_texture == NULL);\r\n\r\n\t// call engine\r\n\tmp_single_texture = new NxPs2::SSingleTexture(p_texture_name, sprite, alloc_vram, m_loading_screen);\r\n\tif (mp_single_texture)\r\n\t{\r\n\t\tm_width\t\t\t= mp_single_texture->GetOrigWidth();\t// Garrett: This is probably not what we want, but CSprite\r\n\t\tm_height\t\t= mp_single_texture->GetOrigHeight();  // needs this.  Probably will need to change CTexture.\r\n\t\tm_bitdepth\t\t= mp_single_texture->GetBitdepth();\r\n\t\tm_clut_bitdepth\t= mp_single_texture->GetClutBitdepth();\r\n\t\tm_num_mipmaps\t= mp_single_texture->GetNumMipmaps();\r\n\t\tm_transparent\t= mp_single_texture->IsTransparent();\r\n\t}\r\n\r\n\treturn mp_single_texture != NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_load_texture_from_buffer(uint8* p_buffer, int buffer_size, bool sprite, bool alloc_vram)\r\n{\r\n\tDbg_Assert(mp_group_texture == NULL);\r\n\r\n\t// call engine\r\n\tmp_single_texture = new NxPs2::SSingleTexture(p_buffer, buffer_size, sprite, alloc_vram, m_loading_screen);\r\n\tif (mp_single_texture)\r\n\t{\r\n\t\tm_width\t\t\t= mp_single_texture->GetOrigWidth();\t// Garrett: This is probably not what we want, but CSprite\r\n\t\tm_height\t\t= mp_single_texture->GetOrigHeight();  // needs this.  Probably will need to change CTexture.\r\n\t\tm_bitdepth\t\t= mp_single_texture->GetBitdepth();\r\n\t\tm_clut_bitdepth\t= mp_single_texture->GetClutBitdepth();\r\n\t\tm_num_mipmaps\t= mp_single_texture->GetNumMipmaps();\r\n\t\tm_transparent\t= mp_single_texture->IsTransparent();\r\n\t}\r\n\r\n\treturn mp_single_texture != NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_replace_texture(CTexture *p_texture)\r\n{\t\t\t\t\t\t\t\t \t\r\n\tDbg_Assert(p_texture);\r\n\tDbg_Assert(mp_group_texture);\r\n\r\n\tCPs2Texture *p_ps2_texture = static_cast<CPs2Texture *>(p_texture);\r\n\tDbg_Assert(p_ps2_texture->mp_single_texture);\r\n\r\n\tif ((m_width != p_ps2_texture->m_width) ||\r\n\t\t(m_height != p_ps2_texture->m_height) ||\r\n\t\t(m_bitdepth != p_ps2_texture->m_bitdepth) ||\r\n\t\t(m_num_mipmaps != p_ps2_texture->m_num_mipmaps))\r\n\t{\r\n\t\tDbg_Message(\"Original size (%d, %d); Replacement size (%d, %d)\", m_width, m_height, p_ps2_texture->m_width, p_ps2_texture->m_height);\r\n\t\tDbg_Message(\"Original bitdepth %d; Replacement bitdepth %d\", m_bitdepth, p_ps2_texture->m_bitdepth);\r\n\t\tDbg_Message(\"Original num mipmaps %d; Replacement num mipmaps %d\", m_num_mipmaps, p_ps2_texture->m_num_mipmaps);\r\n\t\treturn false;\r\n\t}\r\n\r\n#if 0\r\n\tif ((m_bitdepth <= 8) && (m_clut_bitdepth < p_ps2_texture->m_clut_bitdepth))\r\n\t{\r\n\t\tDbg_Message(\"Original clut bitdepth %d; Replacement clut bitdepth %d\", m_clut_bitdepth, p_ps2_texture->m_clut_bitdepth);\r\n\t\treturn false;\r\n\t}\r\n#endif\r\n\r\n\t// Copy texture\r\n\tuint8 *p_orig_tex_buffer = mp_group_texture->GetTextureBuffer();\r\n\tuint8 *p_new_tex_buffer = p_ps2_texture->mp_single_texture->GetTextureBuffer();\r\n\tif (mp_group_texture->HasSwizzleMip())\r\n\t{\r\n\t\tmp_group_texture->ReplaceTextureData(p_new_tex_buffer);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmemcpy(p_orig_tex_buffer, p_new_tex_buffer, p_ps2_texture->mp_single_texture->GetTextureBufferSize());\r\n\t}\r\n\r\n\t// And clut (if any)\r\n\tuint32 *p_orig_clut_buffer = (uint32 *) mp_group_texture->GetClutBuffer();\r\n\tif (p_orig_clut_buffer)\r\n\t{\r\n\t\tuint32 *p_new_clut_buffer = (uint32 *) p_ps2_texture->mp_single_texture->GetClutBuffer();\r\n\t\tDbg_Assert(p_new_clut_buffer);\r\n\r\n\t\tif (m_clut_bitdepth == p_ps2_texture->m_clut_bitdepth)\r\n\t\t{\r\n\t\t\tmemcpy(p_orig_clut_buffer, p_new_clut_buffer, p_ps2_texture->mp_single_texture->GetClutBufferSize());\r\n\t\t} else if ((m_clut_bitdepth == 32) && (p_ps2_texture->m_clut_bitdepth == 16))\r\n\t\t{\r\n\t\t\tuint16 *p_clut_16_buffer = (uint16 *) p_new_clut_buffer;\r\n\t\t\tImage::RGBA new_color;\r\n\t\t\tnew_color.a = 0x80;\r\n\r\n\t\t\tint num_colors = p_ps2_texture->mp_single_texture->GetClutBufferSize() / 2;\r\n\t\t\tfor (int i = 0; i < num_colors; i++)\r\n\t\t\t{\r\n\t\t\t\t// Convert from 16 to 32 bit\r\n\t\t\t\tnew_color.r = ((*(p_clut_16_buffer)   >>  0) & 0x1f) << 3;\r\n\t\t\t\tnew_color.g = ((*(p_clut_16_buffer)   >>  5) & 0x1f) << 3;\r\n\t\t\t\tnew_color.b = ((*(p_clut_16_buffer++) >> 10) & 0x1f) << 3;\r\n\r\n\t\t\t\t//Dbg_Message(\"Replacing color #%d %x with %x\", i, *p_orig_clut_buffer, *((uint32 *) &new_color));\r\n\t\t\t\t*(p_orig_clut_buffer++) = *((uint32 *) &new_color);\r\n\t\t\t}\r\n\t\t} else if ((m_clut_bitdepth == 16) && (p_ps2_texture->m_clut_bitdepth == 32))\r\n\t\t{\r\n\t\t\tuint16 *p_clut_16_buffer = (uint16 *) p_orig_clut_buffer;\r\n\t\t\tuint16 new_color;\r\n\t\t\tImage::RGBA *p_full_color;\r\n\r\n\t\t\tint num_colors = p_ps2_texture->mp_single_texture->GetClutBufferSize() / 4;\r\n\t\t\tfor (int i = 0; i < num_colors; i++)\r\n\t\t\t{\r\n\t\t\t\tp_full_color = (Image::RGBA *) p_new_clut_buffer++;\r\n\t\t\t\tnew_color = 0x8000 | (p_full_color->r >> 3) | ( (p_full_color->g >> 3) << 5 ) | ( (p_full_color->b >> 3) << 10 );\r\n\t\t\t\t*(p_clut_16_buffer++) = new_color;\t\t\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tDbg_Message(\"Can't handle this combination: clut bitdepth %d; Replacement clut bitdepth %d\", m_clut_bitdepth, p_ps2_texture->m_clut_bitdepth);\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t//Dbg_Message(\"Original clut size %d; Replacement clut size %d\", mp_group_texture->GetClutBufferSize(), p_ps2_texture->mp_single_texture->GetClutBufferSize());\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_generate_32bit_image(bool renderable, bool store_original)\r\n{\r\n\tDbg_MsgAssert(!mp_cur_temp_32bit_image, (\"Can't generate temp 32-bit image: one already exists\"));\r\n\r\n\t// For now, just coded up the 8-bit image with 32-bit clut\r\n\tDbg_Assert(m_bitdepth == 8);\r\n\tDbg_MsgAssert(m_clut_bitdepth == 32, (\"Clut bitdepth is only %d, not 32\", m_clut_bitdepth));\r\n\tDbg_Assert(mp_single_texture);\r\n\tDbg_Assert(s_tables_initialized);\r\n\r\n\t// Allocate buffer\r\n\tmp_cur_temp_32bit_image = new uint32[m_width * m_height];\r\n\tuint32 *p_pixel_buffer = mp_cur_temp_32bit_image;\r\n\r\n\t// Get source buffers\r\n\tuint8 *p_orig_tex_buffer = mp_single_texture->GetTextureBuffer();\r\n\t// And clut (if any)\r\n\tuint32 *p_orig_clut_buffer = (uint32 *) mp_single_texture->GetClutBuffer();\r\n\r\n\t// Move texture buffer to start (and flip y)\r\n\tp_orig_tex_buffer += (m_height - 1) * m_width;\r\n\r\n\tfor (uint h = 0; h < m_height; h++)\r\n\t{\r\n\t\tfor (uint w = 0; w < m_width; w++)\r\n\t\t{\r\n\t\t\t// Copies from 8-bit to 32-bit\r\n\t\t\t*p_pixel_buffer++ = p_orig_clut_buffer[ s_clut8_index_to_offset(p_orig_tex_buffer[w]) ];\r\n\t\t}\r\n\t\tp_orig_tex_buffer -= m_width;\t// Negative because were flipping the lines\r\n\t}\r\n\r\n\t// Copy to original buffer\r\n\tif (store_original)\r\n\t{\r\n\t\tmp_orig_temp_32bit_image = new uint32[m_width * m_height];\r\n\t\tmemcpy(mp_orig_temp_32bit_image, mp_cur_temp_32bit_image, m_width * m_height * sizeof(uint32));\r\n\t}\r\n\r\n\t// Allocate a SSingleTexture\r\n\tif (renderable)\r\n\t{\r\n\t\tmp_temp_32bit_single_texture = new NxPs2::SSingleTexture((uint8 *) mp_cur_temp_32bit_image, m_width, m_height, 32,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t m_clut_bitdepth, m_num_mipmaps, true, true, m_loading_screen);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_put_32bit_image_into_texture(bool new_palette)\r\n{\r\n\tDbg_MsgAssert(mp_cur_temp_32bit_image, (\"No temp 32-bit image\"));\r\n\r\n\t// For now, just coded up the 8-bit image with 32-bit clut\r\n\tDbg_Assert(m_bitdepth == 8);\r\n\tDbg_Assert(m_clut_bitdepth == 32);\r\n\tDbg_Assert(mp_single_texture);\r\n\tDbg_Assert(s_tables_initialized);\r\n\r\n\t// Generate a new palette\r\n\tif (new_palette)\r\n\t{\r\n\t\tGeneratePalette((Image::RGBA *) mp_single_texture->GetClutBuffer(), (uint8 *) mp_cur_temp_32bit_image, m_width, m_height, 32, 1 << m_bitdepth);\r\n\t}\r\n\r\n\t// Get buffers\r\n\tuint8 *p_tex_buffer = mp_single_texture->GetTextureBuffer();\r\n\tuint32 *p_pixel_buffer = mp_cur_temp_32bit_image;\r\n\r\n\t// Move texture buffer to start (and flip y)\r\n\tp_tex_buffer += (m_height - 1) * m_width;\r\n\r\n#if USE_FAST_COLOR_FIND\r\n#if PRINT_FAST_TIMES\r\n\tuint32 start_time = Tmr::GetTimeInUSeconds();\r\n#endif // PRINT_FAST_TIMES\r\n\r\n\tsetup_fast_clut_color_find(false);\r\n\r\n#if PRINT_FAST_TIMES\r\n\tuint32 end_time = Tmr::GetTimeInUSeconds();\r\n\tDbg_Message(\"plat_put_32bit_image_into_texture fast setup time %d us\", end_time - start_time);\r\n#endif // PRINT_FAST_TIMES\r\n#endif // USE_FAST_COLOR_FIND\r\n\r\n\tfor (uint h = 0; h < m_height; h++)\r\n\t{\r\n\t\tfor (uint w = 0; w < m_width; w++)\r\n\t\t{\r\n\t\t\t// Copies from 32-bit to 8-bit\r\n#if USE_FAST_COLOR_FIND\r\n\t\t\tp_tex_buffer[w] = s_clut8_offset_to_index( fast_find_closest_clut_color( *((Image::RGBA *) p_pixel_buffer++) ) );\r\n#else\r\n\t\t\tp_tex_buffer[w] = s_clut8_offset_to_index( find_closest_clut_color( *((Image::RGBA *) p_pixel_buffer++) ) );\r\n#endif // USE_FAST_COLOR_FIND\r\n\t\t}\r\n\t\tp_tex_buffer -= m_width;\t\t// Negative because were flipping the lines\r\n\t}\r\n\r\n#if USE_FAST_COLOR_FIND\r\n\tcleanup_fast_clut_color_find();\r\n\r\n#if PRINT_FAST_TIMES\r\n\tend_time = Tmr::GetTimeInUSeconds();\r\n\tDbg_Message(\"plat_put_32bit_image_into_texture fast total time %d us\", end_time - start_time);\r\n#endif // PRINT_FAST_TIMES\r\n#endif // USE_FAST_COLOR_FIND\r\n\r\n\t// Delete buffers\r\n\tdelete [] mp_cur_temp_32bit_image;\r\n\tmp_cur_temp_32bit_image = NULL;\r\n\r\n\tif (mp_orig_temp_32bit_image)\r\n\t{\r\n\t\tdelete [] mp_orig_temp_32bit_image;\r\n\t\tmp_orig_temp_32bit_image = NULL;\r\n\t}\r\n\r\n\tif (mp_temp_32bit_single_texture)\r\n\t{\r\n\t\tdelete mp_temp_32bit_single_texture;\r\n\t\tmp_temp_32bit_single_texture = NULL;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCPs2Texture::s_get_nearest_pixels_from_32bit_texture(Image::RGBA p_nearest[][2], uint32 *p_buffer,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t uint16 x_pos, uint16 y_pos, uint16 width, uint16 height)\r\n{\r\n\tint next_x = (x_pos >= (width - 1)) ? 0 : 1;\t\t// Clamp x if at end\r\n\tbool clamp_y = (y_pos >= (height - 1));\t\t\t\t// And same for y\r\n\r\n\tp_buffer += (y_pos * width) + x_pos;\r\n\r\n\t// First row\r\n\tp_nearest[0][0] = *((Image::RGBA *) p_buffer);\r\n\tp_nearest[0][1] = *((Image::RGBA *) &p_buffer[next_x]);\r\n\r\n\tif (!clamp_y)\r\n\t{\r\n\t\tp_buffer += width;\r\n\t}\r\n\r\n\t// Second row\r\n\tp_nearest[1][0] = *((Image::RGBA *) p_buffer);\r\n\tp_nearest[1][1] = *((Image::RGBA *) &p_buffer[next_x]);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCPs2Texture::s_get_region(uint8 *p_buffer, uint16 x_pos, uint16 y_pos, uint16 tex_width, uint16 tex_height,\r\n\t\t\t\t\t\t\t\t  uint8 *p_region, uint16 region_width, uint16 region_height, uint16 bitdepth)\r\n{\r\n\tint bytes_per_pixel = bitdepth / 8;\r\n\tint copy_bytes;\r\n\tint width_in_bytes;\r\n\tint stride_in_bytes;\r\n\r\n\t// Clamp region values\r\n\tint clamp_region_width = min(region_width, tex_width - x_pos);\r\n\tint clamp_region_height = min(region_height, tex_height - y_pos);\r\n\tDbg_Assert(clamp_region_width >= 0);\r\n\tDbg_Assert(clamp_region_height >= 0);\r\n\r\n\t// Move texture buffer to start\r\n\tif (bytes_per_pixel)\r\n\t{\r\n\t\tp_buffer += ((y_pos * tex_width) + x_pos) * bytes_per_pixel;\r\n\t\tcopy_bytes = clamp_region_width * bytes_per_pixel;\r\n\t\twidth_in_bytes = region_width * bytes_per_pixel;\r\n\t\tstride_in_bytes = tex_width * bytes_per_pixel;\r\n\t}\r\n\telse // 4-bit\r\n\t{\r\n\t\tp_buffer += ((y_pos * tex_width) + x_pos) / 2;\r\n\t\tcopy_bytes = clamp_region_width / 2;\r\n\t\twidth_in_bytes = region_width / 2;\r\n\t\tstride_in_bytes = tex_width / 2;\r\n\t}\r\n\r\n\t//Dbg_Message(\"s_get_region(): xpos %d, ypos %d, tex_width %d, tex_height %d, region_width %d, region_height %d, width_in_bytes %d, stride_in_bytes %d, bitdepth %d\",\r\n\t//\t\t\tx_pos, y_pos, tex_width, tex_height, region_width, region_height, width_in_bytes, stride_in_bytes, bitdepth);\r\n\tfor (int h = 0; h < clamp_region_height; h++)\r\n\t{\r\n\t\t// Copy each line\r\n\t\tmemcpy(p_region, p_buffer, copy_bytes);\r\n\t\tp_region += width_in_bytes;\r\n\t\tp_buffer += stride_in_bytes;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCPs2Texture::s_put_region(uint8 *p_buffer, uint16 x_pos, uint16 y_pos, uint16 tex_width, uint16 tex_height,\r\n\t\t\t\t\t\t\t\t  uint8 *p_region, uint16 region_width, uint16 region_height, uint16 bitdepth)\r\n{\r\n\tint bytes_per_pixel = bitdepth / 8;\r\n\tint copy_bytes;\r\n\tint width_in_bytes;\r\n\tint stride_in_bytes;\r\n\r\n\t// Clamp region values\r\n\tint clamp_region_width = min(region_width, tex_width - x_pos);\r\n\tint clamp_region_height = min(region_height, tex_height - y_pos);\r\n\tDbg_Assert(clamp_region_width >= 0);\r\n\tDbg_Assert(clamp_region_height >= 0);\r\n\r\n\t// Move texture buffer to start\r\n\tif (bytes_per_pixel)\r\n\t{\r\n\t\tp_buffer += ((y_pos * tex_width) + x_pos) * bytes_per_pixel;\r\n\t\tcopy_bytes = clamp_region_width * bytes_per_pixel;\r\n\t\twidth_in_bytes = region_width * bytes_per_pixel;\r\n\t\tstride_in_bytes = tex_width * bytes_per_pixel;\r\n\t}\r\n\telse // 4-bit\r\n\t{\r\n\t\tp_buffer += ((y_pos * tex_width) + x_pos) / 2;\r\n\t\tcopy_bytes = clamp_region_width / 2;\r\n\t\twidth_in_bytes = region_width / 2;\r\n\t\tstride_in_bytes = tex_width / 2;\r\n\t}\r\n\r\n\t//Dbg_Message(\"s_put_region(): xpos %d, ypos %d, tex_width %d, tex_height %d, region_width %d, region_height %d, width_in_bytes %d, stride_in_bytes %d, bitdepth %d\",\r\n\t//\t\t\tx_pos, y_pos, tex_width, tex_height, region_width, region_height, width_in_bytes, stride_in_bytes, bitdepth);\r\n\tfor (int h = 0; h < clamp_region_height; h++)\r\n\t{\r\n\t\t// Copy each line\r\n\t\tmemcpy(p_buffer, p_region, copy_bytes);\r\n\t\tp_region += width_in_bytes;\r\n\t\tp_buffer += stride_in_bytes;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCPs2Texture::s_scale_texture(uint8 *p_buffer, uint16 width, uint16 height,\r\n\t\t\t\t\t\t\t\t\t uint8 *p_result_buffer, uint16 new_width, uint16 new_height, uint16 bitdepth)\r\n{\r\n\tDbg_MsgAssert(bitdepth > 8, (\"Can't scale a paletted texture.  Convert to unpaletted first.\"));\r\n\tDbg_Assert(bitdepth == 32);\t\t// We'll worry about 16 and 24 bit later.\r\n\r\n#if PRINT_TIMES\r\n\tstatic uint32 total_time = 0;\r\n\tuint32 start_time = Tmr::GetTimeInUSeconds();\r\n#endif\r\n\r\n\tfloat orig_coord[2] = { 0.0f, 0.0f };\r\n\tfloat delta_dim[2];\r\n\tfloat delta_coord[2] = { 0.0f, 0.0f };\r\n\tuint16 orig_index[2] = { 0, 0 };\r\n\r\n\tImage::RGBA closest_pixels[2][2];\r\n\tfloat pixel_portion[2][2];\r\n\tImage::RGBA combined_pixel;\r\n\r\n\tdelta_dim[X] = (float) width / (float) new_width;\r\n\tdelta_dim[Y] = (float) height / (float) new_height;\r\n\r\n\tfor (int h = 0; h < new_height; h++)\r\n\t{\r\n\t\torig_index[Y] = (uint16) orig_coord[Y];\t\t\t// Get integer version\r\n\t\tdelta_coord[Y] = orig_coord[Y] - orig_index[Y];\t// And now get fractional part\r\n\r\n\t\tfor (int w = 0; w < new_width; w++)\r\n\t\t{\r\n\t\t\torig_index[X] = (uint16) orig_coord[X];\t\t\t// Get integer version\r\n\t\t\tdelta_coord[X] = orig_coord[X] - orig_index[X];\t// And now get fractional part\r\n\r\n\t\t\t// Calculate the pixel portions\r\n\t\t\tpixel_portion[0][0] = (1.0f - delta_coord[X]) * (1.0f - delta_coord[Y]);\r\n\t\t\tpixel_portion[0][1] =        (delta_coord[X]) * (1.0f - delta_coord[Y]);\r\n\t\t\tpixel_portion[1][0] = (1.0f - delta_coord[X]) *        (delta_coord[Y]);\r\n\t\t\tpixel_portion[1][1] =        (delta_coord[X]) *        (delta_coord[Y]);\r\n\t\t\t\t\r\n\t\t\tDbg_MsgAssert((orig_index[X] + 0) < width, (\"X coord out of range: %d\", orig_index[X]));\r\n\t\t\tDbg_MsgAssert((orig_index[Y] + 0) < height, (\"Y coord out of range: %d\", orig_index[Y]));\r\n\r\n\t\t\t// Get the 4 nearest pixels\r\n\t\t\ts_get_nearest_pixels_from_32bit_texture(closest_pixels, (uint32 *) p_buffer, orig_index[X], orig_index[Y], width, height);\r\n\r\n\t\t\t// Calculate each color\r\n\t\t\tcombined_pixel.r = (uint8) ((pixel_portion[0][0] * (float) closest_pixels[0][0].r) +\r\n\t\t\t\t\t\t\t\t\t    (pixel_portion[0][1] * (float) closest_pixels[0][1].r) +\r\n\t\t\t\t\t\t\t\t\t    (pixel_portion[1][0] * (float) closest_pixels[1][0].r) +\r\n\t\t\t\t\t\t\t\t\t    (pixel_portion[1][1] * (float) closest_pixels[1][1].r));\r\n\t\t\tcombined_pixel.g = (uint8) ((pixel_portion[0][0] * (float) closest_pixels[0][0].g) +\r\n\t\t\t\t\t\t\t\t\t    (pixel_portion[0][1] * (float) closest_pixels[0][1].g) +\r\n\t\t\t\t\t\t\t\t\t    (pixel_portion[1][0] * (float) closest_pixels[1][0].g) +\r\n\t\t\t\t\t\t\t\t\t    (pixel_portion[1][1] * (float) closest_pixels[1][1].g));\r\n\t\t\tcombined_pixel.b = (uint8) ((pixel_portion[0][0] * (float) closest_pixels[0][0].b) +\r\n\t\t\t\t\t\t\t\t\t    (pixel_portion[0][1] * (float) closest_pixels[0][1].b) +\r\n\t\t\t\t\t\t\t\t\t    (pixel_portion[1][0] * (float) closest_pixels[1][0].b) +\r\n\t\t\t\t\t\t\t\t\t    (pixel_portion[1][1] * (float) closest_pixels[1][1].b));\r\n\t\t\tcombined_pixel.a = (uint8) ((pixel_portion[0][0] * (float) closest_pixels[0][0].a) +\r\n\t\t\t\t\t\t\t\t\t    (pixel_portion[0][1] * (float) closest_pixels[0][1].a) +\r\n\t\t\t\t\t\t\t\t\t    (pixel_portion[1][0] * (float) closest_pixels[1][0].a) +\r\n\t\t\t\t\t\t\t\t\t    (pixel_portion[1][1] * (float) closest_pixels[1][1].a));\r\n\r\n\t\t\t// And copy\r\n\t\t\t*((uint32 *) p_result_buffer)++ = *((uint32 *) &(combined_pixel));\r\n\r\n\t\t\t// Advance to next coord\r\n\t\t\torig_coord[X] += delta_dim[X];\r\n\t\t}\r\n\r\n\t\torig_coord[X] = 0.0f;\r\n\t\torig_coord[Y] += delta_dim[Y];\r\n\t}\r\n\r\n#if PRINT_TIMES\r\n\tuint32 end_time = Tmr::GetTimeInUSeconds();\r\n\ttotal_time += end_time - start_time;\r\n\tDbg_Message(\"scale_texture Update time %d us; Total Time %d\", end_time - start_time, total_time);\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCPs2Texture::s_combine_adjacent_borders(uint8 *p_first_rect, uint8 *p_second_rect, uint16 first_width,\r\n\t\t\t\t\t\t\t\t\t\t\t\tuint16 first_height, uint16 second_stride, float first_portion,\r\n\t\t\t\t\t\t\t\t\t\t\t\tint split_axis, uint16 bitdepth)\r\n{\r\n\tDbg_MsgAssert(bitdepth > 8, (\"Can't adjust the border of a paletted texture.  Convert to unpaletted first.\"));\r\n\tDbg_Assert(bitdepth == 32);\t\t// We'll worry about 16 and 24 bit later.\r\n\r\n\tImage::RGBA *p_rect_pixel[2] = { (Image::RGBA *) p_first_rect, (Image::RGBA *) p_second_rect };\r\n\tfloat second_portion = 1.0f - first_portion;\r\n\r\n\tint num_pixels, inc_pixels;\r\n\r\n\t// Init\r\n\tif (split_axis == X)\r\n\t{\r\n\t\tnum_pixels = first_width;\r\n\t\tinc_pixels = 1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Assert(first_width == second_stride);\r\n\r\n\t\tnum_pixels = first_height;\r\n\t\tinc_pixels = second_stride;\r\n\t}\r\n\r\n\t// Combine the pixels\r\n\tfor (int pidx = 0; pidx < num_pixels; pidx++)\r\n\t{\r\n\t\tp_rect_pixel[1]->r = (uint8) ( (first_portion * (float) p_rect_pixel[0]->r) + (second_portion * (float) p_rect_pixel[1]->r) );\r\n\t\tp_rect_pixel[1]->g = (uint8) ( (first_portion * (float) p_rect_pixel[0]->g) + (second_portion * (float) p_rect_pixel[1]->g) );\r\n\t\tp_rect_pixel[1]->b = (uint8) ( (first_portion * (float) p_rect_pixel[0]->b) + (second_portion * (float) p_rect_pixel[1]->b) );\r\n\t\tp_rect_pixel[1]->a = (uint8) ( (first_portion * (float) p_rect_pixel[0]->a) + (second_portion * (float) p_rect_pixel[1]->a) );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic const int ALPHA_WEIGHT = 2;    // how much more weight to give to alpha\r\nuint8 \tCPs2Texture::find_closest_clut_color(Image::RGBA rgba)\r\n{\r\n\t// For now, just coded up the 8-bit image with 32-bit clut\r\n\tDbg_Assert(m_bitdepth == 8);\r\n\tDbg_Assert(m_clut_bitdepth == 32);\r\n\tDbg_Assert(mp_single_texture);\r\n\r\n\tint clutsize = 1 << m_bitdepth;\r\n\r\n\tImage::RGBA *p_clut_buffer = (Image::RGBA *) mp_single_texture->GetClutBuffer();\r\n\r\n\tDbg_Assert(p_clut_buffer);\r\n\r\n    int delR, delG, delB, delA;\r\n    int bestDist, curDist;\r\n    uint8 bestIdx = 0;\r\n\r\n    bestDist = 0x7FFFFFFF;\r\n\r\n    for (int i = 0; i < clutsize; i++)\r\n\t{\r\n        delR = (int) (p_clut_buffer)->r   - (int) rgba.r;\r\n        delG = (int) (p_clut_buffer)->g   - (int) rgba.g;\r\n        delB = (int) (p_clut_buffer)->b   - (int) rgba.b;\r\n        delA = (int) (p_clut_buffer++)->a - (int) rgba.a;\r\n\r\n        // Calculate 4-dimensional distance between color components\r\n        curDist = (delR * delR) + (delG * delG) + (delB * delB) +\r\n                  (delA * delA * ALPHA_WEIGHT);\r\n\r\n        // Choose the index with the smallest distance from src color\r\n        if (curDist < bestDist)\r\n\t\t{\r\n            bestDist = curDist;\r\n            bestIdx = i;\r\n        }\r\n    }\r\n\r\n    return bestIdx;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Holds clut index array start and size\r\nstruct SClutEntries\r\n{\r\n\tuint16\tm_clut_buffer_index;\r\n\tuint8\tm_num_clut_entries;\r\n};\r\n\r\nstatic const int s_axis_level_bits = 3;\t\t\t// Significant bits used to break down each color into the tree\r\nstatic const int s_axis_levels = 1 << s_axis_level_bits;\r\nstatic bool s_use_alpha_axis;\r\nstatic uint8 *sp_clut_index_buffer = NULL;\r\n\r\n//static int s_num_color_searches;\r\n//static int s_num_color_compares;\r\n\r\n// Array is of form [R][G][B][A]\r\nstatic SClutEntries s_palette_octree[s_axis_levels][s_axis_levels][s_axis_levels][s_axis_levels];\r\n\r\nvoid \tCPs2Texture::setup_fast_clut_color_find(bool use_alpha)\r\n{\r\n\t// For now, just coded up the 8-bit image with 32-bit clut\r\n\tDbg_Assert(m_bitdepth == 8);\r\n\tDbg_Assert(m_clut_bitdepth == 32);\r\n\tDbg_Assert(mp_single_texture);\r\n\tDbg_Assert(!sp_clut_index_buffer);\r\n\r\n\ts_use_alpha_axis = use_alpha;\r\n\r\n\tint clutsize = 1 << m_bitdepth;\r\n\tint range = clutsize >> s_axis_level_bits;\r\n\tint alpha_axis_levels = (s_use_alpha_axis) ? s_axis_levels : 1;\r\n\tint index_buffer_size = s_axis_levels * s_axis_levels * s_axis_levels * alpha_axis_levels * (clutsize / 2);\t// Could be made smaller\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tsp_clut_index_buffer = new uint8[index_buffer_size];\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tint min_level[4];\r\n\tint max_level[4];\r\n\r\n\tconst int overlap = (range >> 1);\r\n\tconst int min_start = -overlap;\r\n\tconst int max_start = range + overlap;\r\n\tconst int max_alpha_start = (s_use_alpha_axis) ? max_start : clutsize;\r\n\r\n\tint buffer_index = 0;\r\n\r\n\tmin_level[0] = min_start;\r\n\tmax_level[0] = max_start;\r\n\r\n\tfor (int r = 0; r < s_axis_levels; r++)\r\n\t{\r\n\t\tmin_level[1] = min_start;\r\n\t\tmax_level[1] = max_start;\r\n\r\n\t\tfor (int g = 0; g < s_axis_levels; g++)\r\n\t\t{\r\n\t\t\tmin_level[2] = min_start;\r\n\t\t\tmax_level[2] = max_start;\r\n\r\n\t\t\tfor (int b = 0; b < s_axis_levels; b++)\r\n\t\t\t{\r\n\t\t\t\tmin_level[3] = min_start;\r\n\t\t\t\tmax_level[3] = max_alpha_start;\r\n\r\n\t\t\t\tfor (int a = 0; a < alpha_axis_levels; a++)\r\n\t\t\t\t{\r\n\t\t\t\t\tSClutEntries *p_palette_node = &s_palette_octree[r][g][b][a];\r\n\t\t\t\t\tp_palette_node->m_clut_buffer_index = buffer_index;\r\n\t\t\t\t\tp_palette_node->m_num_clut_entries = 0;\r\n\t\t\t\t\tImage::RGBA *p_clut_buffer = (Image::RGBA *) mp_single_texture->GetClutBuffer();\r\n\r\n\t\t\t\t\tDbg_MsgAssert(buffer_index < (index_buffer_size - clutsize), (\"Running out of index buffer space\"));\r\n\r\n\t\t\t\t\tfor (int index = 0; index < clutsize; index++, p_clut_buffer++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ((p_clut_buffer->r >= min_level[0]) && (p_clut_buffer->r <= max_level[0]) &&\r\n\t\t\t\t\t\t\t(p_clut_buffer->g >= min_level[1]) && (p_clut_buffer->g <= max_level[1]) &&\r\n\t\t\t\t\t\t\t(p_clut_buffer->b >= min_level[2]) && (p_clut_buffer->b <= max_level[2]) &&\r\n\t\t\t\t\t\t\t(p_clut_buffer->a >= min_level[3]) && (p_clut_buffer->a <= max_level[3]))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_palette_node->m_num_clut_entries++;\r\n\t\t\t\t\t\t\tsp_clut_index_buffer[buffer_index++] = index;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} // for index\r\n\r\n\t\t\t\t\tmin_level[3] += range;\r\n\t\t\t\t\tmax_level[3] += range;\r\n\r\n\t\t\t\t} // for a\r\n\r\n\t\t\t\tmin_level[2] += range;\r\n\t\t\t\tmax_level[2] += range;\r\n\r\n\t\t\t} // for b\r\n\r\n\t\t\tmin_level[1] += range;\r\n\t\t\tmax_level[1] += range;\r\n\r\n\t\t} // for g\r\n\r\n\t\tmin_level[0] += range;\r\n\t\tmax_level[0] += range;\r\n\r\n\t} // for r\r\n\r\n\t//s_num_color_searches = 0;\r\n\t//s_num_color_compares = 0;\r\n}\r\n\r\n\r\nuint8 \tCPs2Texture::fast_find_closest_clut_color(Image::RGBA rgba)\r\n{\r\n\t// For now, just coded up the 8-bit image with 32-bit clut\r\n\tDbg_Assert(m_bitdepth == 8);\r\n\tDbg_Assert(m_clut_bitdepth == 32);\r\n\tDbg_Assert(mp_single_texture);\r\n\tDbg_Assert(sp_clut_index_buffer);\r\n\r\n\tint range_bits = m_bitdepth - s_axis_level_bits;\r\n\r\n\tint r_index = rgba.r >> range_bits;\r\n\tint g_index = rgba.g >> range_bits;\r\n\tint b_index = rgba.b >> range_bits;\r\n\tint a_index = (s_use_alpha_axis) ? rgba.a >> range_bits : 0;\r\n\r\n\tSClutEntries *p_palette_node = &s_palette_octree[r_index][g_index][b_index][a_index];\r\n\r\n\t//s_num_color_searches++;\r\n\tif (p_palette_node->m_num_clut_entries == 0)\r\n\t{\r\n\t\t//s_num_color_compares += 256;\r\n\t\treturn find_closest_clut_color(rgba);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tuint8 *p_palette_index = &sp_clut_index_buffer[p_palette_node->m_clut_buffer_index];\r\n\t\tImage::RGBA *p_clut_buffer = (Image::RGBA *) mp_single_texture->GetClutBuffer();\r\n\t\tDbg_Assert(p_clut_buffer);\r\n\r\n\t\tint delR, delG, delB, delA;\r\n\t\tint bestDist, curDist;\r\n\t\tuint8 bestIdx = 0;\r\n\r\n\t\tbestDist = 0x7FFFFFFF;\r\n\r\n\t\tfor (int entry_index = 0; entry_index < p_palette_node->m_num_clut_entries; entry_index++, p_palette_index++)\r\n\t\t{\r\n\t\t\tImage::RGBA *p_clut_color = &p_clut_buffer[*p_palette_index];\r\n\r\n\t\t\tdelR = (int) p_clut_color->r - (int) rgba.r;\r\n\t\t\tdelG = (int) p_clut_color->g - (int) rgba.g;\r\n\t\t\tdelB = (int) p_clut_color->b - (int) rgba.b;\r\n\t\t\tdelA = (int) p_clut_color->a - (int) rgba.a;\r\n\r\n\t\t\t// Calculate 4-dimensional distance between color components\r\n\t\t\tcurDist = (delR * delR) + (delG * delG) + (delB * delB) +\r\n\t\t\t\t\t  (delA * delA * ALPHA_WEIGHT);\r\n\r\n\t\t\t// Choose the index with the smallest distance from src color\r\n\t\t\tif (curDist < bestDist)\r\n\t\t\t{\r\n\t\t\t\tbestDist = curDist;\r\n\t\t\t\tbestIdx = *p_palette_index;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t//s_num_color_compares += p_palette_node->m_num_clut_entries;\r\n\r\n\t\treturn bestIdx;\r\n\t}\r\n}\r\n\r\nvoid \tCPs2Texture::cleanup_fast_clut_color_find()\r\n{\r\n\tDbg_Assert(sp_clut_index_buffer);\r\n\r\n\t//Dbg_Message(\"Average color compares per search: %f\", (float) s_num_color_compares / (float) s_num_color_searches);\r\n\r\n\tdelete [] sp_clut_index_buffer;\r\n\tsp_clut_index_buffer = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCPs2Texture::copy_region_to_32bit_buffer(uint32 *p_pixel_buffer, uint16 x_pos, uint16 y_pos,\r\n\t\t\t\t\t\t\t\t\t\t\t\t uint16 width, uint16 height)\r\n{\r\n\t// For now, just coded up the 8-bit image with 32-bit clut\r\n\tDbg_Assert(m_bitdepth == 8);\r\n\tDbg_MsgAssert(m_clut_bitdepth == 32, (\"Clut bitdepth is only %d, not 32\", m_clut_bitdepth));\r\n\tDbg_Assert(mp_single_texture);\r\n\tDbg_Assert(s_tables_initialized);\r\n\r\n#if PRINT_TIMES\r\n\tstatic uint32 total_time = 0;\r\n\tuint32 start_time = Tmr::GetTimeInUSeconds();\r\n#endif\r\n\r\n\tif (mp_cur_temp_32bit_image)\r\n\t{\r\n\t\t// Get source buffer\r\n\t\tuint32 *p_orig_tex_buffer = mp_cur_temp_32bit_image;\r\n\r\n\t\t// Move texture buffer to start\r\n\t\tp_orig_tex_buffer += (y_pos * m_width) + x_pos;\r\n\r\n\t\tfor (uint h = 0; h < height; h++)\r\n\t\t{\r\n\t\t\tmemcpy(p_pixel_buffer, p_orig_tex_buffer, width * sizeof(uint32));\r\n\t\t\tp_pixel_buffer += width;\r\n\t\t\tp_orig_tex_buffer += m_width;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Get source buffers\r\n\t\tuint8 *p_orig_tex_buffer = mp_single_texture->GetTextureBuffer();\r\n\t\t// And clut (if any)\r\n\t\tuint32 *p_orig_clut_buffer = (uint32 *) mp_single_texture->GetClutBuffer();\r\n\r\n\t\t// Move texture buffer to start (and flip y)\r\n\t\tp_orig_tex_buffer += ((m_height - 1 - y_pos) * m_width) + x_pos;\r\n\r\n\t\tfor (uint h = 0; h < height; h++)\r\n\t\t{\r\n\t\t\tfor (uint w = 0; w < width; w++)\r\n\t\t\t{\r\n\t\t\t\t// Copies from 8-bit to 32-bit\r\n\t\t\t\t*p_pixel_buffer++ = p_orig_clut_buffer[ s_clut8_index_to_offset(p_orig_tex_buffer[w]) ];\r\n\t\t\t}\r\n\t\t\tp_orig_tex_buffer -= m_width;\t// Negative because were flipping the lines\r\n\t\t}\r\n\t}\r\n\r\n#if PRINT_TIMES\r\n\tuint32 end_time = Tmr::GetTimeInUSeconds();\r\n\ttotal_time += end_time - start_time;\r\n\tDbg_Message(\"copy_region_to_32bit_buffer Update time %d us; Total Time %d\", end_time - start_time, total_time);\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCPs2Texture::blit_32bit_buffer_to_texture(uint32 *p_pixel_buffer, uint16 x_pos, uint16 y_pos,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  uint16 width, uint16 height)\r\n{\r\n\t// For now, just coded up the 8-bit image with 32-bit clut\r\n\tDbg_Assert(m_bitdepth == 8);\r\n\tDbg_Assert(m_clut_bitdepth == 32);\r\n\tDbg_Assert(mp_single_texture);\r\n\tDbg_Assert(s_tables_initialized);\r\n\r\n#if PRINT_TIMES\r\n\tstatic uint32 total_time = 0;\r\n\tuint32 start_time = Tmr::GetTimeInUSeconds();\r\n#endif\r\n\r\n\tif (mp_cur_temp_32bit_image)\r\n\t{\r\n\t\t// Get source buffer\r\n\t\tuint32 *p_tex_buffer = mp_cur_temp_32bit_image;\r\n\r\n\t\t// Move texture buffer to start\r\n\t\tp_tex_buffer += (y_pos * m_width) + x_pos;\r\n\r\n\t\tfor (uint h = 0; h < height; h++)\r\n\t\t{\r\n\t\t\tmemcpy(p_tex_buffer, p_pixel_buffer, width * sizeof(uint32));\r\n\t\t\tp_pixel_buffer += width;\r\n\t\t\tp_tex_buffer += m_width;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Get source buffers\r\n\t\tuint8 *p_tex_buffer = mp_single_texture->GetTextureBuffer();\r\n\r\n\t\t// Move texture buffer to start (and flip y)\r\n\t\tp_tex_buffer += ((m_height - 1 - y_pos) * m_width) + x_pos;\r\n\r\n\t\tfor (uint h = 0; h < height; h++)\r\n\t\t{\r\n\t\t\tfor (uint w = 0; w < width; w++)\r\n\t\t\t{\r\n\t\t\t\t// Copies from 32-bit to 8-bit\r\n\t\t\t\tp_tex_buffer[w] = s_clut8_offset_to_index( find_closest_clut_color( *((Image::RGBA *) p_pixel_buffer++) ) );\r\n\t\t\t}\r\n\t\t\tp_tex_buffer -= m_width;\t\t// Negative because were flipping the lines\r\n\t\t}\r\n\t}\r\n\r\n#if PRINT_TIMES\r\n\tuint32 end_time = Tmr::GetTimeInUSeconds();\r\n\ttotal_time += end_time - start_time;\r\n\tDbg_Message(\"blit_32bit_buffer_to_texture Update time %d us; Total Time %d\", end_time - start_time, total_time);\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCPs2Texture::set_32bit_pixel_to_texture(uint32 pixel, uint16 x_pos, uint16 y_pos)\r\n{\r\n\t// For now, just coded up the 8-bit image with 32-bit clut\r\n\tDbg_Assert(m_bitdepth == 8);\r\n\tDbg_Assert(m_clut_bitdepth == 32);\r\n\tDbg_Assert(mp_single_texture);\r\n\tDbg_Assert(s_tables_initialized);\r\n\r\n\tif (mp_cur_temp_32bit_image)\r\n\t{\r\n\t\t// Set pixel in buffer\r\n\t\tmp_cur_temp_32bit_image[(y_pos * m_width) + x_pos] = pixel;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Get source buffers\r\n\t\tuint8 *p_tex_buffer = mp_single_texture->GetTextureBuffer();\r\n\r\n\t\t// Move texture buffer to start (and flip y)\r\n\t\tp_tex_buffer[((m_height - 1 - y_pos) * m_width) + x_pos] = s_clut8_offset_to_index( find_closest_clut_color( *((Image::RGBA *) &pixel) ) );\r\n\t}\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_offset(int x_pixels, int y_pixels, bool use_fill_color, Image::RGBA fill_color)\r\n{\r\n\tint region_start_pos[2];\r\n\tint region_end_pos[2];\r\n\tint region_width;\r\n\tint region_height;\r\n\r\n\t// Figure out X info\r\n\tif (x_pixels >= 0)\r\n\t{\r\n\t\tregion_start_pos[X] = 0;\r\n\t\tregion_end_pos[X] = x_pixels;\r\n\t\tregion_width = m_width - x_pixels;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tregion_start_pos[X] = -x_pixels;\r\n\t\tregion_end_pos[X] = 0;\r\n\t\tregion_width = m_width - (-x_pixels);\r\n\t}\r\n\r\n\t// Figure out Y info\r\n\tif (y_pixels >= 0)\r\n\t{\r\n\t\tregion_start_pos[Y] = 0;\r\n\t\tregion_end_pos[Y] = y_pixels;\r\n\t\tregion_height = m_height - y_pixels;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tregion_start_pos[Y] = -y_pixels;\r\n\t\tregion_end_pos[Y] = 0;\r\n\t\tregion_height = m_height - (-y_pixels);\r\n\t}\r\n\r\n\t// Copy texture region into temp buffers in 32-bit format\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tuint32 *p_texture_buffer = new uint32[region_width * region_height];\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Get section that will be in offset texture\r\n\tcopy_region_to_32bit_buffer(p_texture_buffer, region_start_pos[X], region_start_pos[Y], region_width, region_height);\r\n\r\n\t// And put that region back into texture\r\n\tblit_32bit_buffer_to_texture(p_texture_buffer, region_end_pos[X], region_end_pos[Y], region_width, region_height);\r\n\r\n\t//static uint32 total_time = 0;\r\n\t//uint32 start_time = Tmr::GetTimeInUSeconds();\r\n\r\n\t// Check if we have a fill color\r\n\tif (use_fill_color)\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Fill color not implemented yet\"));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor (int h = 0, y_pos = -region_end_pos[Y]; h < m_height; h++, y_pos++)\r\n\t\t{\r\n\t\t\tint y_clamp_pos = max(y_pos, 0);\r\n\t\t\ty_clamp_pos = min(y_clamp_pos, region_height - 1);\r\n\t\t\tint y_buffer_index = y_clamp_pos * region_width;\r\n\r\n\t\t\tfor (int w = 0, x_pos = -region_end_pos[X]; w < m_width; w++, x_pos++)\r\n\t\t\t{\r\n\t\t\t\t// Check if we are within the new region\r\n\t\t\t\tif ((x_pos >= 0) && (x_pos < region_width) &&\r\n\t\t\t\t\t(y_pos >= 0) && (y_pos < region_height))\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tint x_clamp_pos = max(x_pos, 0);\r\n\t\t\t\tx_clamp_pos = min(x_clamp_pos, region_width - 1);\r\n\r\n\t\t\t\tset_32bit_pixel_to_texture(p_texture_buffer[y_buffer_index + x_clamp_pos], w, h);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t//uint32 end_time = Tmr::GetTimeInUSeconds();\r\n\t//total_time += end_time - start_time;\r\n\t//Dbg_Message(\"offset_texture fill Update time %d us; Total Time %d\", end_time - start_time, total_time);\r\n\r\n\tdelete [] p_texture_buffer;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_adjust_region(uint16 x_pos, uint16 y_pos, uint16 width, uint16 height,\r\n\t\t\t\t\t\t\t\t\t\tint split_axis, uint16 start_point, uint16 end_point)\r\n{\t\t\t\t\t\t\t\t \t\r\n\t// Copy original rectangle in a temp buffer in 32-bit format (needed for interpolation)\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tuint32 *p_orig_region_pixels = new uint32[width * height];\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tcopy_region_to_32bit_buffer(p_orig_region_pixels, x_pos, y_pos, width, height);\r\n\r\n\tfloat first_rect_portion;\r\n\tuint16 rect_pos[2][2];\r\n\tuint16 rect_new_pos[2];\r\n\tuint16 rect_orig_width[2];\r\n\tuint16 rect_orig_height[2];\r\n\tuint16 rect_new_width[2];\r\n\tuint16 rect_new_height[2];\r\n\r\n\t// Figure out first rectangle\r\n\trect_pos[0][X] = 0;\r\n\trect_pos[0][Y] = 0;\r\n\r\n\tif (split_axis == X)\r\n\t{\r\n\t\tDbg_Assert(start_point >= x_pos);\r\n\t\tDbg_Assert(start_point <= x_pos + width);\r\n\t\tDbg_Assert(end_point >= x_pos);\r\n\t\tDbg_Assert(end_point <= x_pos + width);\r\n\r\n\t\t// Dimensions of first rectangle\r\n\t\trect_orig_width[0] = start_point - x_pos + 1;\r\n\t\trect_orig_height[0] = height;\r\n\t\trect_new_width[0] = end_point - x_pos + 1;\r\n\t\trect_new_height[0] = height;\r\n\t\t\r\n\t\t// Second rectangle\r\n\t\trect_pos[1][X] = start_point - x_pos;\r\n\t\trect_pos[1][Y] = 0;\r\n\t\trect_new_pos[X] = end_point - x_pos;\r\n\t\trect_new_pos[Y] = 0;\r\n\r\n\t\trect_orig_width[1] = width - (start_point - x_pos);\r\n\t\trect_orig_height[1] = height;\r\n\t\trect_new_width[1] = width - (end_point - x_pos);\r\n\t\trect_new_height[1] = height;\r\n\r\n\t\t// Figure out portion of first rectangle to whole region\r\n\t\tfirst_rect_portion = (float) rect_new_width[0] / (float) width;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Assert(start_point >= y_pos);\r\n\t\tDbg_Assert(start_point <= y_pos + height);\r\n\t\tDbg_Assert(end_point >= y_pos);\r\n\t\tDbg_Assert(end_point <= y_pos + height);\r\n\r\n\t\t// Dimensions of first rectangle\r\n\t\trect_orig_width[0] = width;\r\n\t\trect_orig_height[0] = start_point - y_pos + 1;\r\n\t\trect_new_width[0] = width;\r\n\t\trect_new_height[0] = end_point - y_pos + 1;\r\n\t\t\r\n\t\t// Second rectangle\r\n\t\trect_pos[1][X] = 0;\r\n\t\trect_pos[1][Y] = start_point - y_pos;\r\n\t\trect_new_pos[X] = 0;\r\n\t\trect_new_pos[Y] = end_point - y_pos;\r\n\r\n\t\trect_orig_width[1] = width;\r\n\t\trect_orig_height[1] = height - (start_point - y_pos);\r\n\t\trect_new_width[1] = width;\r\n\t\trect_new_height[1] = height - (end_point - y_pos);\r\n\r\n\t\t// Figure out portion of first rectangle to whole region\r\n\t\tfirst_rect_portion = (float) rect_new_height[0] / (float) height;\r\n\t}\r\n\r\n\t// Make room for the original and new rectangles\r\n\tuint32 *p_orig_rect_pixels[2];\r\n\tuint32 *p_new_rect_pixels[2];\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tp_orig_rect_pixels[0] = new uint32[rect_orig_width[0] * rect_orig_height[0]];\r\n\tp_orig_rect_pixels[1] = new uint32[rect_orig_width[1] * rect_orig_height[1]];\r\n\r\n\tp_new_rect_pixels[0] = new uint32[rect_new_width[0] * rect_new_height[0]];\r\n\tp_new_rect_pixels[1] = new uint32[rect_new_width[1] * rect_new_height[1]];\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Get the original rectangles\r\n\ts_get_region((uint8 *) p_orig_region_pixels, rect_pos[0][X], rect_pos[0][Y], width, height,\r\n\t\t\t\t (uint8 *) p_orig_rect_pixels[0], rect_orig_width[0], rect_orig_height[0], 32);\r\n\ts_get_region((uint8 *) p_orig_region_pixels, rect_pos[1][X], rect_pos[1][Y], width, height,\r\n\t\t\t\t (uint8 *) p_orig_rect_pixels[1], rect_orig_width[1], rect_orig_height[1], 32);\r\n\r\n\t// Scale each rectangle\r\n\ts_scale_texture((uint8 *) p_orig_rect_pixels[0], rect_orig_width[0], rect_orig_height[0],\r\n\t\t\t\t\t(uint8 *) p_new_rect_pixels[0], rect_new_width[0], rect_new_height[0], 32);\r\n\ts_scale_texture((uint8 *) p_orig_rect_pixels[1], rect_orig_width[1], rect_orig_height[1],\r\n\t\t\t\t\t(uint8 *) p_new_rect_pixels[1], rect_new_width[1], rect_new_height[1], 32);\r\n\r\n\t// Combine two adjacent side lines into 1 (and put into the second rectangle since it will overwrite the first)\r\n\ts_combine_adjacent_borders((uint8 *) p_new_rect_pixels[0], (uint8 *) p_new_rect_pixels[1],\r\n\t\t\t\t\t\t\t\t\t\t rect_new_width[0], rect_new_height[0], rect_new_width[1], first_rect_portion, split_axis, 32);\r\n\r\n\t// Put new rectangles back into region\r\n\ts_put_region((uint8 *) p_orig_region_pixels, rect_pos[0][X], rect_pos[0][Y], width, height,\r\n\t\t\t\t (uint8 *) p_new_rect_pixels[0], rect_new_width[0], rect_new_height[0], 32);\r\n\ts_put_region((uint8 *) p_orig_region_pixels, rect_new_pos[X], rect_new_pos[Y], width, height,\r\n\t\t\t\t (uint8 *) p_new_rect_pixels[1], rect_new_width[1], rect_new_height[1], 32);\r\n\r\n\t// And put region back into texture\r\n\tblit_32bit_buffer_to_texture(p_orig_region_pixels, x_pos, y_pos, width, height);\r\n\r\n\t// Free all the buffers\r\n\tdelete [] p_orig_rect_pixels[0];\r\n\tdelete [] p_orig_rect_pixels[1];\r\n\r\n\tdelete [] p_new_rect_pixels[0];\r\n\tdelete [] p_new_rect_pixels[1];\r\n\r\n\tdelete [] p_orig_region_pixels;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_pull_to_edge(uint16 point, int axis, int num_pixels)\r\n{\r\n#if PRINT_TIMES\r\n\tstatic uint32 total_time = 0;\r\n\tuint32 start_time = Tmr::GetTimeInUSeconds();\r\n#endif\r\n\r\n\tuint32 *p_texture_buffer = NULL;\r\n\tuint32 *p_scaled_texture_buffer = NULL;\r\n\r\n\tuint16 rect_pos[2];\r\n\tuint16 rect_orig_width;\r\n\tuint16 rect_orig_height;\r\n\tuint16 rect_new_width;\r\n\tuint16 rect_new_height;\r\n\tuint16 scaled_offset;\r\n\r\n\tif (num_pixels == 0)\r\n\t{\r\n\t\t// Nothing to do\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Cap num_pixels on low end\r\n\tif ((point + num_pixels) <= 0)\r\n\t{\r\n\t\tnum_pixels = -point + 1;\r\n\t}\r\n\r\n\tDbg_Assert((point + num_pixels) >= 0);\r\n\r\n\tif (axis == X)\r\n\t{\r\n\t\tDbg_Assert(point < m_width);\r\n\r\n\t\t// Cap num_pixels on high end\r\n\t\tif ((point + num_pixels) >= m_width)\r\n\t\t{\r\n\t\t\tnum_pixels = m_width - point - 1;\r\n\t\t}\r\n\r\n\t\tDbg_Assert((point + num_pixels) < m_width);\r\n\r\n\t\tbool left = (num_pixels < 0);\r\n\r\n\t\tif (left)\r\n\t\t{\r\n\t\t\t// Figure out orig rectangle\r\n\t\t\trect_pos[X] = 0;\r\n\t\t\trect_pos[Y] = 0;\r\n\t\t\trect_orig_width = point + 1;\r\n\t\t\trect_orig_height = m_height;\r\n\r\n\t\t\t// Figure out new rectangle\r\n\t\t\trect_new_width = point + (-num_pixels) + 1;\r\n\t\t\trect_new_height = m_height;\r\n\r\n\t\t\tscaled_offset = -num_pixels;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Figure out orig rectangle\r\n\t\t\trect_pos[X] = point;\r\n\t\t\trect_pos[Y] = 0;\r\n\t\t\trect_orig_width = (m_width - point);\r\n\t\t\trect_orig_height = m_height;\r\n\r\n\t\t\t// Figure out new rectangle\r\n\t\t\trect_new_width = (m_width - point) + num_pixels;\r\n\t\t\trect_new_height = m_height;\r\n\r\n\t\t\tscaled_offset = 0;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Assert(point < m_height);\r\n\r\n\t\t// Cap num_pixels on high end\r\n\t\tif ((point + num_pixels) >= m_height)\r\n\t\t{\r\n\t\t\tnum_pixels = m_height - point - 1;\r\n\t\t}\r\n\r\n\t\tDbg_Assert((point + num_pixels) < m_height);\r\n\r\n\t\tbool top = (num_pixels < 0);\r\n\r\n\t\tif (top)\r\n\t\t{\r\n\t\t\t// Figure out orig rectangle\r\n\t\t\trect_pos[X] = 0;\r\n\t\t\trect_pos[Y] = 0;\r\n\t\t\trect_orig_width = m_width;\r\n\t\t\trect_orig_height = point + 1;\r\n\r\n\t\t\t// Figure out new rectangle\r\n\t\t\trect_new_width = m_width;\r\n\t\t\trect_new_height = point + (-num_pixels) + 1;\r\n\r\n\t\t\tscaled_offset = -num_pixels * m_width;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Figure out orig rectangle\r\n\t\t\trect_pos[X] = 0;\r\n\t\t\trect_pos[Y] = point;\r\n\t\t\trect_orig_width = m_width;\r\n\t\t\trect_orig_height = (m_height - point);\r\n\r\n\t\t\t// Figure out new rectangle\r\n\t\t\trect_new_width = m_width;\r\n\t\t\trect_new_height = (m_height - point) + num_pixels;\r\n\r\n\t\t\tscaled_offset = 0;\r\n\t\t}\r\n\t}\r\n\r\n\t// Copy texture region into temp buffers in 32-bit format\r\n\tif (Mem::Manager::sHandle().CutsceneTopDownHeap())\r\n\t{\r\n\t\t// GJ FIX 9/9/03 FOR SK5:TT13114 - \"Failing to allocate \r\n\t\t// face texture memory in cutscenes\"\r\n\t\t// if the cutscene top down heap exists, we want to use\r\n\t\t// that first, because there won't be much on the\r\n\t\t// top down heap during cutscenes...\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().CutsceneTopDownHeap());\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t}\r\n\tp_texture_buffer = new uint32[rect_orig_width * rect_orig_height];\r\n\tp_scaled_texture_buffer = new uint32[rect_new_width * rect_new_height];\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t//Dbg_Message(\"Copying region from (%d, %d) of size (%d, %d)\", rect_pos[X], rect_pos[Y], rect_orig_width, rect_orig_height);\r\n\tcopy_region_to_32bit_buffer(p_texture_buffer, rect_pos[X], rect_pos[Y], rect_orig_width, rect_orig_height);\r\n\r\n\t// Scale the rectangle\r\n\ts_scale_texture((uint8 *) p_texture_buffer, rect_orig_width, rect_orig_height,\r\n\t\t\t\t\t(uint8 *) p_scaled_texture_buffer, rect_new_width, rect_new_height, 32);\r\n\r\n\t//Dbg_Message(\"Pull: Original size (%d, %d), new size (%d, %d)\", rect_orig_width, rect_orig_height, rect_new_width, rect_new_height);\r\n\t// Crop the rectangle and put back into original buffer\r\n\ts_put_region((uint8 *) p_texture_buffer, 0, 0, rect_orig_width, rect_orig_height,\r\n\t\t\t\t (uint8 *) (p_scaled_texture_buffer + scaled_offset), rect_new_width, rect_new_height, 32);\r\n\r\n\t// And put region back into texture\r\n\tblit_32bit_buffer_to_texture(p_texture_buffer, rect_pos[X], rect_pos[Y], rect_orig_width, rect_orig_height);\r\n\r\n\t// Free buffers\r\n\tif (p_texture_buffer)\r\n\t{\r\n\t\tdelete [] p_texture_buffer;\r\n\t}\r\n\tif (p_scaled_texture_buffer)\r\n\t{\r\n\t\tdelete [] p_scaled_texture_buffer;\r\n\t}\r\n\r\n#if PRINT_TIMES\r\n\tuint32 end_time = Tmr::GetTimeInUSeconds();\r\n\ttotal_time += end_time - start_time;\r\n\tDbg_Message(\"pull_to_edge Update time %d us; Total Time %d\", end_time - start_time, total_time);\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_push_to_point(uint16 point, int axis, int num_pixels, bool use_fill_color, Image::RGBA fill_color)\r\n{\r\n#if PRINT_TIMES\r\n\tstatic uint32 total_time = 0;\r\n\tuint32 start_time = Tmr::GetTimeInUSeconds();\r\n#endif\r\n\r\n\tuint32 *p_texture_buffer = NULL;\r\n\tuint32 *p_scaled_texture_buffer = NULL;\r\n\r\n\tuint16 rect_pos[2];\r\n\tuint16 rect_new_offset[2];\r\n\tuint16 rect_orig_width;\r\n\tuint16 rect_orig_height;\r\n\tuint16 rect_new_width;\r\n\tuint16 rect_new_height;\r\n\r\n\tif (num_pixels == 0)\r\n\t{\r\n\t\t// Nothing to do\r\n\t\treturn true;\r\n\t}\r\n\t//Dbg_Message(\"Moving %d pixels along %d axis starting at %d\", num_pixels, axis, point);\r\n\r\n\t// Cap num_pixels on low end\r\n\tif ((point + num_pixels) <= 0)\r\n\t{\r\n\t\tnum_pixels = -point + 1;\r\n\t}\r\n\r\n\tDbg_Assert((point + num_pixels) >= 0);\r\n\r\n\tif (axis == X)\r\n\t{\r\n\t\tDbg_Assert(point < m_width);\r\n\r\n\t\t// Cap num_pixels on high end\r\n\t\tif ((point + num_pixels) >= m_width)\r\n\t\t{\r\n\t\t\tnum_pixels = m_width - point - 1;\r\n\t\t}\r\n\r\n\t\tDbg_Assert((point + num_pixels) < m_width);\r\n\r\n\t\tbool left = (num_pixels < 0);\r\n\r\n\t\tif (left)\r\n\t\t{\r\n\t\t\t// Figure out orig rectangle\r\n\t\t\trect_pos[X] = point;\r\n\t\t\trect_pos[Y] = 0;\r\n\t\t\trect_orig_width = (m_width - point);\r\n\t\t\trect_orig_height = m_height;\r\n\r\n\t\t\t// Figure out new rectangle\r\n\t\t\trect_new_offset[X] = 0;\r\n\t\t\trect_new_offset[Y] = 0;\r\n\t\t\trect_new_width = (m_width - point) - (-num_pixels);\r\n\t\t\trect_new_height = m_height;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Figure out orig rectangle\r\n\t\t\trect_pos[X] = 0;\r\n\t\t\trect_pos[Y] = 0;\r\n\t\t\trect_orig_width = point + 1;\r\n\t\t\trect_orig_height = m_height;\r\n\r\n\t\t\t// Figure out new rectangle\r\n\t\t\trect_new_offset[X] = num_pixels;\r\n\t\t\trect_new_offset[Y] = 0;\r\n\t\t\trect_new_width = point - num_pixels + 1;\r\n\t\t\trect_new_height = m_height;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Assert(point < m_height);\r\n\r\n\t\t// Cap num_pixels on high end\r\n\t\tif ((point + num_pixels) >= m_height)\r\n\t\t{\r\n\t\t\tnum_pixels = m_height - point - 1;\r\n\t\t}\r\n\r\n\t\tDbg_Assert((point + num_pixels) < m_height);\r\n\r\n\t\tbool top = (num_pixels < 0);\r\n\r\n\t\tif (top)\r\n\t\t{\r\n\t\t\t// Figure out orig rectangle\r\n\t\t\trect_pos[X] = 0;\r\n\t\t\trect_pos[Y] = point;\r\n\t\t\trect_orig_width = m_width;\r\n\t\t\trect_orig_height = (m_height - point);\r\n\r\n\t\t\t// Figure out new rectangle\r\n\t\t\trect_new_offset[X] = 0;\r\n\t\t\trect_new_offset[Y] = 0;\r\n\t\t\trect_new_width = m_width;\r\n\t\t\trect_new_height = (m_height - point) - (-num_pixels);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Figure out orig rectangle\r\n\t\t\trect_pos[X] = 0;\r\n\t\t\trect_pos[Y] = 0;\r\n\t\t\trect_orig_width = m_width;\r\n\t\t\trect_orig_height = point + 1;\r\n\r\n\t\t\t// Figure out new rectangle\r\n\t\t\trect_new_offset[X] = 0;\r\n\t\t\trect_new_offset[Y] = num_pixels;\r\n\t\t\trect_new_width = m_width;\r\n\t\t\trect_new_height = point - num_pixels + 1;\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_Assert(rect_new_width);\r\n\tDbg_Assert(rect_new_height);\r\n\r\n\t// Copy texture region into temp buffers in 32-bit format\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tp_texture_buffer = new uint32[rect_orig_width * rect_orig_height];\r\n\tp_scaled_texture_buffer = new uint32[rect_new_width * rect_new_height];\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t//Dbg_Message(\"Copying region from (%d, %d) of size (%d, %d)\", rect_pos[X], rect_pos[Y], rect_orig_width, rect_orig_height);\r\n\tcopy_region_to_32bit_buffer(p_texture_buffer, rect_pos[X], rect_pos[Y], rect_orig_width, rect_orig_height);\r\n\r\n\t// Scale the rectangle\r\n\ts_scale_texture((uint8 *) p_texture_buffer, rect_orig_width, rect_orig_height,\r\n\t\t\t\t\t(uint8 *) p_scaled_texture_buffer, rect_new_width, rect_new_height, 32);\r\n\r\n\t// Check if we have a fill color\r\n\tif (use_fill_color)\r\n\t{\r\n\t\tint num_pixels = rect_orig_width * rect_orig_height;\r\n\r\n\t\t// Just brute force it for now\r\n\t\t// Garrett: This doesn't work since p_texture_buffer is only a subset of the texture\r\n\t\tDbg_MsgAssert(0, (\"Fill color not implemented properly yet\"));\r\n\t\tfor (int i = 0; i < num_pixels; i++)\r\n\t\t{\r\n\t\t\tp_texture_buffer[i] = *((uint32 *) &fill_color);\r\n\t\t}\r\n\t}\r\n\r\n\t// Put smaller rectangle back into original buffer\r\n\ts_put_region((uint8 *) p_texture_buffer, rect_new_offset[X], rect_new_offset[Y], rect_orig_width, rect_orig_height,\r\n\t\t\t\t (uint8 *) p_scaled_texture_buffer, rect_new_width, rect_new_height, 32);\r\n\r\n\t// And put region back into texture\r\n\tblit_32bit_buffer_to_texture(p_texture_buffer, rect_pos[X], rect_pos[Y], rect_orig_width, rect_orig_height);\r\n\r\n\t// Cover up old pixels\r\n\tif (!use_fill_color)\r\n\t{\r\n\t\tif (axis == X)\r\n\t\t{\r\n\t\t\tbool use_left = (num_pixels > 0);\r\n\t\t\tint scaled_coord = (use_left) ? 0 : rect_new_width - 1; \r\n\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\tuint32 *p_strip_buffer = new uint32[m_height];\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\tfor (int pidx = 0; pidx < m_height; pidx++)\r\n\t\t\t{\r\n\t\t\t\tp_strip_buffer[pidx] = p_scaled_texture_buffer[(pidx * rect_new_width) + scaled_coord];\r\n\t\t\t}\r\n\r\n\t\t\tint start = (use_left) ? 0 : m_width - (-num_pixels);\r\n\t\t\tint end = (use_left) ? num_pixels - 1 : m_width - 1;\r\n\r\n\t\t\tfor (int line = start; line <= end; line++)\r\n\t\t\t{\r\n\t\t\t\tblit_32bit_buffer_to_texture(p_strip_buffer, line, 0, 1, m_height);\r\n\t\t\t}\r\n\r\n\t\t\tdelete [] p_strip_buffer;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbool use_top = (num_pixels > 0);\r\n\t\t\tint scaled_coord = (use_top) ? 0 : rect_new_height - 1; \r\n\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\tuint32 *p_strip_buffer = new uint32[m_width];\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\tmemcpy(p_strip_buffer, &(p_scaled_texture_buffer[scaled_coord * rect_new_width]), m_width * sizeof(uint32));\r\n\r\n\t\t\tint start = (use_top) ? 0 : m_height - (-num_pixels);\r\n\t\t\tint end = (use_top) ? num_pixels - 1 : m_height - 1;\r\n\r\n\t\t\tfor (int line = start; line <= end; line++)\r\n\t\t\t{\r\n\t\t\t\tblit_32bit_buffer_to_texture(p_strip_buffer, 0, line, m_width, 1);\r\n\t\t\t}\r\n\r\n\t\t\tdelete [] p_strip_buffer;\r\n\t\t}\r\n\t}\r\n\r\n\t// Free buffers\r\n\tif (p_texture_buffer)\r\n\t{\r\n\t\tdelete [] p_texture_buffer;\r\n\t}\r\n\tif (p_scaled_texture_buffer)\r\n\t{\r\n\t\tdelete [] p_scaled_texture_buffer;\r\n\t}\r\n\r\n#if PRINT_TIMES\r\n\tuint32 end_time = Tmr::GetTimeInUSeconds();\r\n\ttotal_time += end_time - start_time;\r\n\tDbg_Message(\"push_to_point Update time %d us; Total Time %d\", end_time - start_time, total_time);\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_adjust_brightness(float brightness_scale, bool force_adjust_current)\r\n{\r\n#if PRINT_TIMES\r\n\tstatic uint32 total_time = 0;\r\n\tuint32 start_time = Tmr::GetTimeInUSeconds();\r\n#endif\r\n\r\n\tDbg_Assert(mp_single_texture);\r\n\tDbg_MsgAssert(mp_cur_temp_32bit_image, (\"For now, AdjustBrightness() only supports 32-bit mode\"));\r\n\r\n\tImage::RGBA *p_src_pixels;\r\n\tImage::RGBA *p_dst_pixels = (Image::RGBA *) mp_cur_temp_32bit_image;\r\n\r\n\t// Figure out the source\r\n\tif (mp_orig_temp_32bit_image && !force_adjust_current)\r\n\t{\r\n\t\tp_src_pixels = (Image::RGBA *) mp_orig_temp_32bit_image;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_src_pixels = (Image::RGBA *) mp_cur_temp_32bit_image;\r\n\t}\r\n\r\n\t// Adjust each pixel\r\n\tint num_pixels = m_width * m_height;\r\n\tfor (int i = 0; i < num_pixels; i++, p_src_pixels++, p_dst_pixels++)\r\n\t{\r\n\t\tp_dst_pixels->r = (uint8) min(p_src_pixels->r * brightness_scale, 255);\r\n\t\tp_dst_pixels->g = (uint8) min(p_src_pixels->g * brightness_scale, 255);\r\n\t\tp_dst_pixels->b = (uint8) min(p_src_pixels->b * brightness_scale, 255);\r\n\t}\r\n\r\n#if PRINT_TIMES\r\n\tuint32 end_time = Tmr::GetTimeInUSeconds();\r\n\ttotal_time += end_time - start_time;\r\n\tDbg_Message(\"adjust_brightness(%f) Update time %d us; Total Time %d\", brightness_scale, end_time - start_time, total_time);\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_adjust_hsv(float h, float s, float v, bool force_adjust_current)\r\n{\r\n#if PRINT_TIMES\r\n\tstatic uint32 total_time = 0;\r\n\tuint32 start_time = Tmr::GetTimeInUSeconds();\r\n#endif\r\n\r\n\tDbg_Assert(mp_single_texture);\r\n\tDbg_MsgAssert(mp_cur_temp_32bit_image, (\"For now, AdjustHSV() only supports 32-bit mode\"));\r\n\r\n\tDbg_MsgAssert((h >= 0.0f) && (h <= 360.0f), (\"h is out of range: %f\", h));\r\n\tDbg_MsgAssert(s >= 0.0f, (\"s is negative: %f\", s));\r\n\tDbg_MsgAssert(v >= 0.0f, (\"v is negative: %f\", v));\r\n\r\n\tImage::RGBA *p_src_pixels;\r\n\tImage::RGBA *p_dst_pixels = (Image::RGBA *) mp_cur_temp_32bit_image;\r\n\r\n\t// Figure out the source\r\n\tif (mp_orig_temp_32bit_image && !force_adjust_current)\r\n\t{\r\n\t\tp_src_pixels = (Image::RGBA *) mp_orig_temp_32bit_image;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_src_pixels = (Image::RGBA *) mp_cur_temp_32bit_image;\r\n\t}\r\n\r\n\t// Adjust each pixel\r\n\tfloat pixel_h, pixel_s, pixel_v;\r\n\tfloat pixel_r, pixel_g, pixel_b;\r\n\tint num_pixels = m_width * m_height;\r\n\tfor (int i = 0; i < num_pixels; i++, p_src_pixels++, p_dst_pixels++)\r\n\t{\r\n\t\t// Convert\r\n\t\tGfx::inlineRGBtoHSV(p_src_pixels->r / 255.0f, p_src_pixels->g / 255.0f, p_src_pixels->b / 255.0f, pixel_h, pixel_s, pixel_v);\r\n\r\n\t\t// Adjust\r\n\t\tpixel_h += h;\r\n\t\tif (pixel_h > 360.0f)\r\n\t\t{\r\n\t\t\tpixel_h -= 360.0f;\r\n\t\t}\r\n\t\tpixel_s = Mth::Min(pixel_s * s, 1.0f);\r\n\t\tpixel_v = Mth::Min(pixel_v * v, 1.0f);\r\n\r\n\t\t// Convert back\r\n\t\tGfx::inlineHSVtoRGB(pixel_r, pixel_g, pixel_b, pixel_h, pixel_s, pixel_v);\r\n\t\tp_dst_pixels->r = (unsigned char)( pixel_r * 255.0f + 0.5f );\r\n\t\tp_dst_pixels->g = (unsigned char)( pixel_g * 255.0f + 0.5f );\r\n\t\tp_dst_pixels->b = (unsigned char)( pixel_b * 255.0f + 0.5f );\r\n\t}\r\n\r\n#if PRINT_TIMES\r\n\tuint32 end_time = Tmr::GetTimeInUSeconds();\r\n\ttotal_time += end_time - start_time;\r\n\tDbg_Message(\"adjust_hsv(%f) Update time %d us; Total Time %d\", s, end_time - start_time, total_time);\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_add_to_vram()\r\n{\t\t\t\t\t\t\t\t \t\r\n\tDbg_MsgAssert(mp_single_texture, (\"CPs2Texture::plat_add_to_vram() only works for sSingleTexture types\"));\r\n\r\n\treturn mp_single_texture->AddToVRAM();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_remove_from_vram()\r\n{\t\t\t\t\t\t\t\t \t\r\n\tDbg_MsgAssert(mp_single_texture, (\"CPs2Texture::plat_remove_from_vram() only works for sSingleTexture types\"));\r\n\r\n\treturn mp_single_texture->RemoveFromVRAM();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint16\tCPs2Texture::plat_get_width() const\r\n{\r\n\treturn m_width;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint16\tCPs2Texture::plat_get_height() const\r\n{\r\n\treturn m_height;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\tCPs2Texture::plat_get_bitdepth() const\r\n{\r\n\treturn m_bitdepth;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\tCPs2Texture::plat_get_palette_bitdepth() const\r\n{\r\n\treturn m_clut_bitdepth;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\tCPs2Texture::plat_get_num_mipmaps() const\r\n{\r\n\treturn m_num_mipmaps;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_is_transparent() const\r\n{\r\n\treturn m_transparent;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCPs2Texture::plat_combine_textures(CTexture *p_texture, bool palette_gen)\r\n{\r\n\tCPs2Texture *p_ps2_texture = static_cast<CPs2Texture *>(p_texture);\r\n\r\n\t// Make sure both textures have same attributes\r\n\tDbg_Assert(m_width == p_ps2_texture->m_width);\r\n\tDbg_Assert(m_height == p_ps2_texture->m_height);\r\n\tDbg_Assert(m_bitdepth == p_ps2_texture->m_bitdepth);\r\n\tDbg_Assert(m_clut_bitdepth == p_ps2_texture->m_clut_bitdepth);\r\n\r\n\tDbg_Assert((m_bitdepth == 8) || (m_bitdepth == 32));\t\t// Maybe support more later\r\n\tDbg_Assert(mp_single_texture);\r\n\tDbg_Assert(p_ps2_texture->mp_single_texture);\r\n\r\n\tbool paletted = (m_bitdepth <= 8);\r\n\tuint32 *p_texture1_buffer = NULL;\r\n\tuint32 *p_texture2_buffer = NULL;\r\n\tImage::RGBA *p_src;\r\n\tImage::RGBA *p_dst;\r\n\r\n\tif (paletted)\r\n\t{\r\n\t\t// Try temp 32-bit images first\r\n\t\tp_dst = (Image::RGBA *) mp_cur_temp_32bit_image;\r\n\t\tp_src = (Image::RGBA *) p_ps2_texture->mp_cur_temp_32bit_image;\r\n\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n\t\t// Copy original textures iton temp buffers in 32-bit format\r\n\t\tif (!p_dst)\r\n\t\t{\r\n\t\t\tp_texture1_buffer = new uint32[m_width * m_height];\r\n\t\t\tcopy_region_to_32bit_buffer(p_texture1_buffer, 0, 0, m_width, m_height);\r\n\t\t\tp_dst = (Image::RGBA *) p_texture1_buffer;\r\n\t\t}\r\n\r\n\t\tif (!p_src)\r\n\t\t{\r\n\t\t\tp_texture2_buffer = new uint32[p_ps2_texture->m_width * p_ps2_texture->m_height];\r\n\t\t\tp_ps2_texture->copy_region_to_32bit_buffer(p_texture2_buffer, 0, 0, p_ps2_texture->m_width, p_ps2_texture->m_height);\r\n\t\t\tp_src = (Image::RGBA *) p_texture2_buffer;\r\n\t\t}\r\n\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_src = (Image::RGBA *) p_ps2_texture->mp_single_texture->GetTextureBuffer();\r\n\t\tp_dst = (Image::RGBA *) mp_single_texture->GetTextureBuffer();\r\n\t}\r\n\r\n\t// Do the actual alpha blend\r\n\tuint8 om_src_alpha;\r\n\tint size = m_width * m_height;\r\n\r\n\tfor (int i = 0; i < size; i++, p_src++, p_dst++)\r\n\t{\r\n\t\tom_src_alpha = 0x80 - p_src->a;\r\n\r\n\t\tp_dst->r = (uint8) ( ( ((int) p_src->r * p_src->a) + ((int) p_dst->r * om_src_alpha) ) >> 7 /* divide by 0x80 */);\r\n\t\tp_dst->g = (uint8) ( ( ((int) p_src->g * p_src->a) + ((int) p_dst->g * om_src_alpha) ) >> 7 /* divide by 0x80 */);\r\n\t\tp_dst->b = (uint8) ( ( ((int) p_src->b * p_src->a) + ((int) p_dst->b * om_src_alpha) ) >> 7 /* divide by 0x80 */);\r\n\t\tp_dst->a = max(p_src->a, p_dst->a);\t// Choose the highest alpha (since we don't want solid pixels to become transparent)\r\n\t}\r\n\r\n\t// Go back to original bitdepth if necessary\r\n\tif (paletted && !mp_cur_temp_32bit_image)\r\n\t{\r\n\t\tDbg_Assert(m_clut_bitdepth == 32);\r\n\r\n\t\t// Generate a new palette\r\n\t\tif (palette_gen)\r\n\t\t{\r\n\t\t\tGeneratePalette((Image::RGBA *) mp_single_texture->GetClutBuffer(), (uint8 *) p_texture1_buffer, m_width, m_height, 32, 1 << m_bitdepth);\r\n\t\t}\r\n\r\n\t\t// And repalettize and put back into texture\r\n\t\tblit_32bit_buffer_to_texture(p_texture1_buffer, 0, 0, m_width, m_height);\r\n\r\n\t}\r\n\r\n\t// Free buffers\r\n\tif (p_texture1_buffer)\r\n\t{\r\n\t\tdelete [] p_texture1_buffer;\r\n\t}\r\n\tif (p_texture2_buffer)\r\n\t{\r\n\t\tdelete [] p_texture2_buffer;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CTexDict\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2TexDict::CPs2TexDict(uint32 checksum) : CTexDict(checksum)\r\n{\r\n\t// Load nothing\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2TexDict::CPs2TexDict(const char *p_tex_dict_name, bool is_level_data, uint32 texDictOffset, bool isSkin, bool forceTexDictLookup) : CTexDict(p_tex_dict_name, !is_level_data)\r\n{\t\t\t\t\t\t\t\t  \r\n\tLoadTextureDictionary(p_tex_dict_name, NULL, 0, is_level_data, texDictOffset, isSkin, forceTexDictLookup);\t// the derived class will does this\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2TexDict::~CPs2TexDict()\r\n{\r\n\tUnloadTextureDictionary();\t\t\t\t// the derived class does this\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNxPs2::sScene *\tCPs2TexDict::GetEngineTextureDictionary() const\r\n{\r\n\t//printf( \"Returning scene from GetEngineTextureDictionary %08x\\n\", (uint32)mp_tex_dict );\r\n\r\n\treturn mp_tex_dict;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPs2TexDict::add_textures_to_hash_table()\r\n{\r\n\tfor (int i = 0; i < mp_tex_dict->NumTextures; i++)\r\n\t{\r\n\t\t// Make sure we don't add duplicate textures.  We can have the same texture in two\r\n\t\t// different texture groups (for sorting purposes).  This will break texture\r\n\t\t// replacement, though.\r\n\t\tif (!GetTexture(mp_tex_dict->pTextures[i].Checksum))\r\n\t\t{\r\n\t\t\tCPs2Texture *p_texture = new CPs2Texture;\r\n\r\n\t\t\tp_texture->m_checksum\t\t= mp_tex_dict->pTextures[i].Checksum;\r\n\t\t\tp_texture->m_width\t\t\t= mp_tex_dict->pTextures[i].GetWidth();\r\n\t\t\tp_texture->m_height\t\t\t= mp_tex_dict->pTextures[i].GetHeight();\r\n\t\t\tp_texture->m_bitdepth\t\t= mp_tex_dict->pTextures[i].GetBitdepth();\r\n\t\t\tp_texture->m_clut_bitdepth\t= mp_tex_dict->pTextures[i].GetClutBitdepth();\r\n\t\t\tp_texture->m_num_mipmaps\t= mp_tex_dict->pTextures[i].GetNumMipmaps();\r\n\r\n\t\t\tp_texture->mp_group_texture = &(mp_tex_dict->pTextures[i]);\r\n\r\n\t\t\tAddTexture(p_texture);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPs2TexDict::LoadTextureDictionary(const char *p_tex_dict_name, uint32* pData, int dataSize, bool is_level_data, uint32 texDictOffset, bool isSkin, bool forceTexDictLookup)\r\n{\r\n\t// set up the texture dictionary's main parameters\r\n\r\n\tbool IsSkin;\r\n\tbool IsInstanceable;\r\n\tbool UsesPip;\r\n\r\n\tif ( is_level_data )\r\n\t{\r\n\t\t// for level data\r\n\t\tIsSkin = false;\r\n\t\tIsInstanceable = false;\r\n\t\tUsesPip = true;\r\n\t}\r\n\telse if ( !isSkin && texDictOffset==0 )\r\n\t{\r\n\t\t// for non-skinned models (unless they \r\n\t\t// do texture replacement, such as the\r\n\t\t// boards in the skateshop do)\r\n\t\tIsSkin = false;\r\n\t\tIsInstanceable = false;\r\n\t\tUsesPip = true;\r\n\t}   \r\n\telse\r\n\t{\r\n\t\t// for all skinned models, and for\r\n\t\t// non-skinned models that do\r\n\t\t// texture replacement)\r\n\t\tIsSkin = true;\r\n\t\tIsInstanceable = true;\r\n\t\tUsesPip = false;\r\n\t}\r\n\r\n\tif ( !is_level_data && isSkin )\r\n\t{\r\n\t\t// add all skinned model textures\r\n\t\t// to the hash table\r\n\t\tforceTexDictLookup = true;\r\n\t}\r\n\r\n\tif ( p_tex_dict_name )\r\n\t{\r\n\t\t// either the filename OR the data pointer should have been specified, but not both\r\n\t\tDbg_MsgAssert( !pData, ( \"You can't specify both a filename %s AND a data pointer\", p_tex_dict_name ) )\r\n\t\t\r\n\t\t// p_tex_dict_name is assumed to be the full path name of the texture dictionary\r\n\t\tmp_tex_dict = NxPs2::LoadTextures(p_tex_dict_name, IsSkin, IsInstanceable, UsesPip, texDictOffset, &m_file_size );\r\n\t\tDbg_Assert( mp_tex_dict );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert( pData, ( \"No data pointer specified\" ) );\r\n\t\t\r\n\t\tm_file_size = dataSize;\r\n\t\tmp_tex_dict = NxPs2::LoadTextures(pData, dataSize, IsSkin, IsInstanceable, UsesPip, texDictOffset );\r\n\t\tDbg_Assert( mp_tex_dict );\r\n\t}\r\n\r\n\t// Add textures to hash table (just do it for non-level dictionaries now)\r\n\t// should this go on bottom up heap?\r\n\tif ( forceTexDictLookup )\r\n\t{\r\n\t\tadd_textures_to_hash_table();\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2TexDict::UnloadTextureDictionary()\r\n{\r\n\tNxPs2::DeleteTextures(mp_tex_dict);\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\tCPs2TexDict::plat_load_texture(const char *p_texture_name, bool sprite, bool alloc_vram)\r\n{\r\n\tCPs2Texture *p_texture = new CPs2Texture;\r\n\tif (!p_texture->LoadTexture(p_texture_name, sprite, alloc_vram))\r\n\t{\r\n\t\tDbg_Error(\"Can't load texture %s\", p_texture_name);\r\n\t}\r\n\r\n\treturn p_texture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\tCPs2TexDict::plat_load_texture_from_buffer(uint8* p_buffer, int buffer_size, uint32 texture_checksum, bool sprite, bool alloc_vram)\r\n{\r\n\tCPs2Texture *p_texture = new CPs2Texture;\r\n\tif (!p_texture->LoadTextureFromBuffer(p_buffer, buffer_size, texture_checksum, sprite, alloc_vram))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't load texture from buffer %s\", Script::FindChecksumName(texture_checksum)));\r\n\t}\r\n\r\n\treturn p_texture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\tCPs2TexDict::plat_reload_texture(const char *p_texture_name)\r\n{\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2TexDict::plat_unload_texture(CTexture *p_texture)\r\n{\r\n\tdelete p_texture;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2TexDict::plat_add_texture(CTexture *p_texture)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCPs2TexDict::plat_remove_texture(CTexture *p_texture)\r\n{\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\tCPs2TexDict::plat_copy_texture(uint32 new_texture_checksum, CTexture *p_texture)\r\n{\r\n\tCPs2Texture *p_ps2_texture = static_cast<CPs2Texture *>(p_texture);\r\n\r\n\treturn new CPs2Texture(*p_ps2_texture);\r\n}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxTexture.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxScene.h\r\n\r\n#ifndef\t__GFX_P_NX_TEXTURE_H__\r\n#define\t__GFX_P_NX_TEXTURE_H__\r\n\r\n#include \t<gfx/nxtexture.h>\r\n#include \t\"gfx/NGPS/NX/texture.h\"\r\n#include \t\"gfx/NGPS/NX/material.h\"\r\n#include \t\"gfx/NGPS/NX/scene.h\"\r\n#include \t\"gfx/NGPS/NX/sprite.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n// Forward declarations\r\nclass CPs2TexDict;\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Machine specific implementation of the CTexture\r\nclass\tCPs2Texture : public CTexture\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCPs2Texture(bool loading_screen = false);\r\n\t\t\t\t\t\t\t\tCPs2Texture(const CPs2Texture & src_texture);\t\t// Copy constructor\r\n\tvirtual\t\t\t\t\t\t~CPs2Texture();\r\n\r\n\tNxPs2::SSingleTexture *\t\tGetSingleTexture() const;\r\n\tNxPs2::sTexture *\t\t\tGetGroupTexture() const;\r\n\r\n\tstatic void\t\t\t\t\tsInitTables();\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\r\n\tuint8 \t\t\t\t\t\tfind_closest_clut_color(Image::RGBA rgba);\r\n\r\n\tvoid\t\t\t\t\t\tsetup_fast_clut_color_find(bool use_alpha = true);\r\n\tuint8 \t\t\t\t\t\tfast_find_closest_clut_color(Image::RGBA rgba);\r\n\tvoid \t\t\t\t\t\tcleanup_fast_clut_color_find();\r\n\r\n\tvoid\t\t\t\t\t\tcopy_region_to_32bit_buffer(uint32 *p_pixel_buffer, uint16 x_pos, uint16 y_pos,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuint16 width, uint16 height);\r\n\tvoid\t\t\t\t\t\tblit_32bit_buffer_to_texture(uint32 *p_pixel_buffer, uint16 x_pos, uint16 y_pos,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t uint16 width, uint16 height);\r\n\tvoid\t\t\t\t\t\tset_32bit_pixel_to_texture(uint32 pixel, uint16 x_pos, uint16 y_pos);\r\n\r\n\t// Plat functions\r\n\tvirtual bool\t\t\t\tplat_load_texture(const char *p_texture_name, bool sprite, bool alloc_vram);\r\n\tvirtual bool\t\t\t\tplat_load_texture_from_buffer(uint8* p_buffer, int buffer_size, bool sprite, bool alloc_vram);\r\n\tvirtual bool\t\t\t\tplat_replace_texture(CTexture *p_texture);\r\n\r\n\tvirtual bool\t\t\t\tplat_generate_32bit_image(bool renderble = false, bool store_original = false);\r\n\tvirtual bool\t\t\t\tplat_put_32bit_image_into_texture(bool new_palette = false);\r\n\r\n\tvirtual bool\t\t\t\tplat_offset(int x_pixels, int y_pixels, bool use_fill_color, Image::RGBA fill_color);\r\n\r\n\tvirtual bool\t\t\t\tplat_adjust_region(uint16 x_pos, uint16 y_pos, uint16 width, uint16 height,\r\n\t\t\t\t\t\t\t\t\t\t\t\t   int split_axis, uint16 start_point, uint16 end_point);\r\n\r\n\tvirtual bool\t\t\t\tplat_pull_to_edge(uint16 point, int axis, int num_pixels);\r\n\tvirtual bool\t\t\t\tplat_push_to_point(uint16 point, int axis, int num_pixels, bool use_fill_color,\r\n\t\t\t\t\t\t\t\t\t\t\t\t   Image::RGBA fill_color);\r\n\r\n\tvirtual bool\t\t\t\tplat_adjust_brightness(float brightness_scale, bool force_adjust_current = false);\r\n\tvirtual bool\t\t\t\tplat_adjust_hsv(float h, float s, float v, bool force_adjust_current = false);\r\n\r\n\tvirtual bool\t\t\t\tplat_add_to_vram();\r\n\tvirtual bool\t\t\t\tplat_remove_from_vram();\r\n\r\n\tvirtual uint16\t\t\t\tplat_get_width() const;\r\n\tvirtual uint16\t\t\t\tplat_get_height() const;\r\n\tvirtual uint8\t\t\t\tplat_get_bitdepth() const;\r\n\tvirtual uint8\t\t\t\tplat_get_palette_bitdepth() const;\r\n\tvirtual uint8\t\t\t\tplat_get_num_mipmaps() const;\r\n\tvirtual bool\t\t\t\tplat_is_transparent() const;\r\n\r\n\tvirtual bool\t\t\t\tplat_combine_textures(CTexture *p_texture, bool palette_gen);\r\n\r\n\t// Static functions\r\n\tstatic uint8 \t\t\t\ts_clut8_index_to_offset(uint8 PS2idx);\r\n\tstatic uint8 \t\t\t\ts_clut8_offset_to_index(uint8 offset);\r\n\r\n\tstatic inline uint32\t\ts_get_pixel_from_32bit_texture(uint32 *p_buffer, uint16 x_pos, uint16 y_pos, uint16 stride);\r\n\tstatic void\t\t\t\t\ts_get_nearest_pixels_from_32bit_texture(Image::RGBA p_nearest[][2], uint32 *p_buffer,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuint16 x_pos, uint16 y_pos, uint16 width, uint16 height);\r\n\t\r\n\tstatic void\t\t\t\t\ts_get_region(uint8 *p_buffer, uint16 x_pos, uint16 y_pos, uint16 tex_width, uint16 tex_height,\r\n\t\t\t\t\t\t\t\t\t\t\t uint8 *p_region, uint16 region_width, uint16 region_height, uint16 bitdepth);\r\n\tstatic void\t\t\t\t\ts_put_region(uint8 *p_buffer, uint16 x_pos, uint16 y_pos, uint16 tex_width, uint16 tex_height,\r\n\t\t\t\t\t\t\t\t\t\t\t uint8 *p_region, uint16 region_width, uint16 region_height, uint16 bitdepth);\r\n\r\n\tstatic void\t\t\t\t\ts_scale_texture(uint8 *p_buffer, uint16 width, uint16 height,\r\n\t\t\t\t\t\t\t\t\t\t\t\tuint8 *p_result_buffer, uint16 new_width, uint16 new_height, uint16 bitdepth);\r\n\r\n\tstatic void\t\t\t\t\ts_combine_adjacent_borders(uint8 *p_first_rect, uint8 *p_second_rect, uint16 first_width,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   uint16 first_height, uint16 second_stride, float first_portion,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   int split_axis, uint16 bitdepth);\r\n\r\n\tuint16\t\t\t\t\t\tm_width;\r\n\tuint16\t\t\t\t\t\tm_height;\r\n\tuint8\t\t\t\t\t\tm_bitdepth;\r\n\tuint8\t\t\t\t\t\tm_clut_bitdepth;\r\n\tuint8\t\t\t\t\t\tm_num_mipmaps;\r\n\tbool\t\t\t\t\t\tm_transparent;\r\n\r\n\t// Tells is this texture is used as loading screen (so it isn't allocated VRAM, etc)\r\n\tbool\t\t\t\t\t\tm_loading_screen;\r\n\r\n\t// The actual data in the engine (can only be one or the other\r\n\tNxPs2::SSingleTexture *\t\tmp_single_texture;\t// Uses SSingleTexture\r\n\tNxPs2::sTexture *\t\t\tmp_group_texture;\t// Uses sTexture (part of texture group\r\n\r\n\t// Temp 32-bit texture images for texture manipulations (so we don't need to palettize every operation)\r\n\tuint32 *\t\t\t\t\tmp_orig_temp_32bit_image;\t\t// Original\r\n\tuint32 *\t\t\t\t\tmp_cur_temp_32bit_image;\t\t// Current\r\n\tNxPs2::SSingleTexture *\t\tmp_temp_32bit_single_texture;\t// So we can draw it\r\n\r\n\t// PS2 clut index conversions\r\n\tstatic bool\t\t\t\t\ts_tables_initialized;\r\n    static uint8\t\t\t\ts_clut8_index_to_offset_table[256];\r\n    static uint8\t\t\t\ts_clut8_offset_to_index_table[256];\r\n\t\r\n\t// Friends\r\n\tfriend CPs2TexDict;\r\n};\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline NxPs2::SSingleTexture *\tCPs2Texture::GetSingleTexture() const\r\n{\r\n\tif (mp_temp_32bit_single_texture)\r\n\t{\r\n\t\treturn mp_temp_32bit_single_texture;\t\t// This can be a problem if plat_put_32bit_image_into_texture()\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t// is called before the corresponding CSprite is deleted.\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn mp_single_texture;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline NxPs2::sTexture *\t\tCPs2Texture::GetGroupTexture() const\r\n{\r\n\treturn mp_group_texture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint32\t\t\t\t\tCPs2Texture::s_get_pixel_from_32bit_texture(uint32 *p_buffer, uint16 x_pos, uint16 y_pos,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuint16 stride)\r\n{\r\n\treturn p_buffer[(y_pos * stride) + x_pos];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint8 \t\t\t\t\tCPs2Texture::s_clut8_index_to_offset(uint8 PS2idx)\r\n{\r\n    return s_clut8_index_to_offset_table[PS2idx];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint8 \t\t\t\t\tCPs2Texture::s_clut8_offset_to_index(uint8 offset)\r\n{\r\n    return s_clut8_offset_to_index_table[offset];\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////////////\r\n// Machine specific implementation of the CMaterial\r\nclass\tCPs2Material : public CMaterial\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCPs2Material();\r\n\tvirtual\t\t\t\t\t\t~CPs2Material();\r\n\r\nprivate:\r\n\tvirtual Image::RGBA\t\t\tplat_get_rgba() const;\r\n\tvirtual void\t\t\t\tplat_set_rgba(Image::RGBA rgba);\r\n\tvirtual void\t\t\t\tplat_set_texture();\r\n\r\n\tImage::RGBA\t\t\t\t\tm_rgba;\r\n\r\n\t// The actual data in the engine\r\n\tNxPs2::sMaterial *\t\t\tmp_material;\r\n};\r\n\r\n//////////////////////////////////////////////////////////////////////////////////\r\n// Machine specific implementation of the CTexDict\r\nclass\tCPs2TexDict : public CTexDict\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCPs2TexDict(uint32 checksum);\t\t// loads nothing\r\n\t\t\t\t\t\t\t\tCPs2TexDict(uint32* pData, int dataSize, bool is_level_data, uint32 texDictOffset, bool isSkin, bool forceTexDictLookup = false);\r\n\t\t\t\t\t\t\t\tCPs2TexDict(const char *p_tex_dict_name, bool is_level_data, uint32 texDictOffset, bool isSkin, bool forceTexDictLookup = false);\r\n\tvirtual\t\t\t\t\t\t~CPs2TexDict();\r\n\r\n\tNxPs2::sScene *\t\t\t\tGetEngineTextureDictionary() const;\r\n\r\npublic:\r\n\t// made this public so that the tex dict manager needs to be able to \r\n\t// create a texture dictionary and load up its textures in two separate steps...\r\n\tbool\t\t\t\t\t\tLoadTextureDictionary(const char *p_tex_dict_name, uint32* pData, int dataSize, bool is_level_data, uint32 texDictOffset, bool isSkin, bool forceTexDictLookup = false);\r\n\r\nprivate:\r\n\tvoid\t\t\t\t\t\tadd_textures_to_hash_table();\r\n\tbool\t\t\t\t\t\tUnloadTextureDictionary();\r\n\r\n\t// Platform-specific calls\r\n\tvirtual CTexture *\t\t\tplat_load_texture(const char *p_texture_name, bool sprite, bool alloc_vram);\r\n\tvirtual CTexture *\t\t\tplat_load_texture_from_buffer(uint8* p_buffer, int buffer_size, uint32 texture_checksum, bool sprite, bool alloc_vram);\r\n\tvirtual CTexture *\t\t\tplat_reload_texture(const char *p_texture_name);\r\n\tvirtual bool\t\t\t\tplat_unload_texture(CTexture *p_texture);\r\n\tvirtual void\t\t\t\tplat_add_texture(CTexture *p_texture);\r\n\tvirtual bool\t\t\t\tplat_remove_texture(CTexture *p_texture);\r\n\tvirtual CTexture *\t\t\tplat_copy_texture(uint32 new_texture_checksum, CTexture *p_texture);\r\n\t//virtual CTexture *\t\t\tplat_combine_textures(uint32 new_texture_checksum, CTexture *p_texture1, CTexture *p_texture2);\r\n\r\n\tNxPs2::sScene *\t\t\t\tmp_tex_dict;\t\t// Platform-dependent data\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxTextured3dPoly.cpp",
    "content": "#include <Gfx/NGPS/p_NxTextured3dPoly.h>\r\n#include <Gfx/NGPS/p_nxtexture.h>\r\n#include <Gfx/NGPS/nx/immediate.h>\r\n#include <Gfx/NGPS/nx/gs.h>\r\n#include <Gfx/NGPS/nx/vif.h>\r\n#include <gfx/nxtexman.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\r\nCPs2Textured3dPoly::CPs2Textured3dPoly()\r\n{\r\n}\r\n\r\nCPs2Textured3dPoly::~CPs2Textured3dPoly()\r\n{\r\n}\r\n\r\nvoid CPs2Textured3dPoly::plat_set_texture(uint32 texture_checksum)\r\n{\r\n\tNx::CTexture *p_texture = Nx::CTexDictManager::sp_sprite_tex_dict->GetTexture(texture_checksum);\r\n\tDbg_MsgAssert(p_texture, (\"no texture found for sprite\"));\r\n\tNx::CPs2Texture *p_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tDbg_MsgAssert(p_ps2_texture,(\"NULL p_ps2_texture\"));\r\n\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\tDbg_MsgAssert(mp_engine_texture,(\"NULL mp_engine_texture\"));\r\n}\t\r\n\r\nvoid CPs2Textured3dPoly::plat_render()\r\n{\r\n\tCImmediateMode::sStartPolyDraw( mp_engine_texture, PackALPHA(0,0,0,0,0), ABS );\r\n\t\r\n\tCImmediateMode::sDrawQuadTexture(mp_engine_texture, mp_pos[0], mp_pos[1], mp_pos[2], mp_pos[3], 0x80808080,0x80808080,0x80808080,0x80808080);\r\n}\r\n\r\n\r\n} // Namespace NxPs2\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxTextured3dPoly.h",
    "content": "#ifndef\t__GFX_P_NX_TEXTURED_3D_POLY_H__\r\n#define\t__GFX_P_NX_TEXTURED_3D_POLY_H__\r\n\r\n#include <gfx/nxtextured3dpoly.h>\r\n#include <gfx/ngps/nx/sprite.h>\r\n\r\nnamespace NxPs2\r\n{\r\n\r\n// Machine specific implementation of CTextured3dPoly\r\nclass\tCPs2Textured3dPoly : public Nx::CTextured3dPoly\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2Textured3dPoly();\r\n\tvirtual\t\t\t\t\t~CPs2Textured3dPoly();\r\nprivate:\r\n\tvoid\t\t\t\t\tplat_render();\r\n\tvoid\t\t\t\t\tplat_set_texture(uint32 texture_checksum);\r\n\t\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n};\r\n\r\n}\t// namespace NxPs2\r\n\r\n#endif\r\n\t\t\t\t   \r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxViewMan.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxViewMan.cpp - PS2 platform specific interface to CViewportManager\r\n//\r\n// This is PS2 SPECIFIC!!!!!!  So might get a bit messy\r\n\r\n#include <core/defines.h>\r\n\r\n#include \"gfx/NxViewMan.h\"\r\n#include \"gfx/NGPS/p_NxViewport.h\"\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCViewport *\t\tCViewportManager::s_plat_create_viewport(const Mth::Rect* rect, Gfx::Camera* cam)\r\n{\r\n\treturn new CPs2Viewport(rect, cam);\r\n}\r\n\r\n} \r\n \r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxViewport.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxViewport.cpp\r\n\r\n#include \t\"Gfx/NxViewMan.h\"\r\n#include \t\"Gfx/NGPS/p_NxViewport.h\"\r\n\r\n#include \t\"Gfx/NGPS/NX/render.h\"\r\n#include \t\"Gfx/NGPS/NX/sprite.h\"\r\n#include \t\"Gfx/NGPS/NX/switches.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CViewport\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Viewport::CPs2Viewport()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Viewport::CPs2Viewport( const Mth::Rect* rect, Gfx::Camera* cam) :\r\n\tCViewport(rect, cam)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Viewport::~CPs2Viewport()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCPs2Viewport::update_render_vars()\r\n{\r\n\tint view_idx = CViewportManager::sGetActiveViewportNumber(this);\r\n\tDbg_MsgAssert(view_idx >= 0, (\"Can't find viewport in active viewport list\"));\r\n\r\n\tif (!NxPs2::render::VarsUpToDate(view_idx) && mp_camera)\r\n\t{\r\n\t\tMth::Matrix cam_matrix(mp_camera->GetMatrix());\r\n\t\tcam_matrix[W] = mp_camera->GetPos();\r\n\r\n\t\tNxPs2::render::SetupVars(view_idx, cam_matrix, GetRect(), mp_camera->GetAdjustedHFOV(), GetAspectRatio(),\r\n\t\t\t\t\t\t\t  /*-mp_camera->GetNearClipPlane(), -mp_camera->GetFarClipPlane()*/ -1.0f, -100000.0f);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\t\tCPs2Viewport::plat_transform_to_screen_coord(const Mth::Vector & world_pos, float & screen_pos_x, float & screen_pos_y, ZBufferValue & screen_pos_z)\r\n{\r\n\tfloat zdistance;\r\n\tfloat scale;\r\n\r\n\tupdate_render_vars();\r\n\r\n\t// First check frustum\r\n\tMth::Vector screen_pos(NxPs2::render::WorldToFrustum.Transform(world_pos));\r\n\r\n\t//if ((Tmr::GetVblanks() % 200) == 0)\r\n\t//{\r\n\t//\tDbg_Message(\"Homogenious (%g, %g, %g, %g)\", screen_pos[X], screen_pos[Y], screen_pos[Z], screen_pos[W]);\r\n\t//}\r\n\r\n\tif ((screen_pos[X] > screen_pos[W]) || (screen_pos[X] < -screen_pos[W]) ||\r\n\t\t(screen_pos[Y] > screen_pos[W]) || (screen_pos[Y] < -screen_pos[W]) ||\r\n\t\t(screen_pos[Z] > screen_pos[W]) || (screen_pos[Z] < -screen_pos[W]))\r\n\t{\r\n\t\treturn -1.0f;\r\n\t} else {\r\n\t\tzdistance = -screen_pos[Z]; //(screen_pos[Z] - screen_pos[W]) / (2.0f * screen_pos[W]);\r\n\t}\r\n\r\n\t// Now find screen coordinates\r\n\tscreen_pos = NxPs2::render::WorldToIntViewport.Transform(world_pos);\r\n\r\n\t//if ((Tmr::GetVblanks() % 200) == 0)\r\n\t//{\r\n\t//\tDbg_Message(\"Converted (%f, %f, %f, %f) to (%g, %g, %g, %g)\", world_pos[X], world_pos[Y], world_pos[Z], world_pos[W],\r\n\t//\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  screen_pos[X], screen_pos[Y], screen_pos[Z], screen_pos[W]);\r\n\t//}\r\n\r\n\t// Get into homogenious space\r\n\tfloat oow = 1.0f / screen_pos[W];\r\n\tscreen_pos *= oow;\r\n\r\n\t// Convert the int back to float\r\n\tscreen_pos_x = (((float) ( *((int *) &(screen_pos[X])) & 0xFFFF )) - XOFFSET) / 16.0f;\r\n\tscreen_pos_y = (((float) ( *((int *) &(screen_pos[Y])) & 0xFFFF )) - YOFFSET) / 16.0f;\r\n\tscreen_pos_z = (ZBufferValue) ( *((int *) &(screen_pos[Z])) & 0xFFFFFF );\r\n\r\n\t// Convert back to NTSC, if necessary\r\n\tscreen_pos_x /= NxPs2::SDraw2D::GetScreenScaleX();\r\n\tscreen_pos_y /= NxPs2::SDraw2D::GetScreenScaleY();\r\n\r\n\t//if ((Tmr::GetVblanks() % 200) == 0)\r\n\t//{\r\n\t//\tDbg_Message(\"Divide by W (%g, %g, %x, %g) Z distance: %g\", screen_pos_x, screen_pos_y, screen_pos_z, screen_pos[W], zdistance);\r\n\t//}\r\n\r\n\t// Calculate scale\r\n\tscale = CViewportManager::sGet2DIn3DSpaceNoscaleDistance() / zdistance;\r\n\tscale = Mth::Min(scale, CViewportManager::sGet2DIn3DSpaceMaxScale());\r\n\tscale = Mth::Max(scale, CViewportManager::sGet2DIn3DSpaceMinScale());\r\n\r\n#if 0\t\t// This scales 1 sprite or text pixel to an inch!\r\n\tfloat hfov;\r\n\tif (mp_camera)\r\n\t{\r\n\t\thfov = mp_camera->GetAdjustedHFOV();\r\n\t} else {\r\n\t\thfov = CViewportManager::sGetScreenAngle();\r\n\t}\r\n\r\n\t// Calculate scale\r\n\tfloat h = ((float) HRES) / (tanf(Mth::DegToRad(hfov / 2.0f)));\r\n\tscale = h / zdistance;\r\n\r\n\tif ((Tmr::GetVblanks() % 300) == 0)\r\n\t{\r\n\t\tDbg_Message(\"H %f, ZDistance %f, Scale %f, HFOC %f\", h, zdistance, scale, hfov);\r\n\t}\r\n#endif\r\n\r\n\treturn scale;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxViewport.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxViewport.h\r\n\r\n#ifndef\t__GFX_P_NX_VIEWPORT_H__\r\n#define\t__GFX_P_NX_VIEWPORT_H__\r\n\r\n#include \t\"Gfx/NxViewport.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Machine specific implementation of the CViewport\r\nclass\tCPs2Viewport : public CViewport\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCPs2Viewport();\r\n\t\t\t\t\t\t\t\tCPs2Viewport(const Mth::Rect* rect, Gfx::Camera* cam = NULL);\r\n\tvirtual\t\t\t\t\t\t~CPs2Viewport();\r\n\r\nprotected:\r\n\tvoid\t\t\t\t\t\tupdate_render_vars();\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\tvirtual float\t\t\t\tplat_transform_to_screen_coord(const Mth::Vector & world_pos, float & screen_pos_x, float & screen_pos_y, ZBufferValue & screen_pos_z);\r\n\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxWin2D.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxWin2D.cpp\r\n\r\n#include \t\"Gfx/NGPS/p_NxWin2D.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of the CText\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Window2D::CPs2Window2D(int x, int y, int width, int height) : CWindow2D(x, y, width, height)\r\n{\r\n\tmp_plat_window = new NxPs2::SScissorWindow();\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2Window2D::~CPs2Window2D()\r\n{\r\n\tif (mp_plat_window)\r\n\t{\r\n\t\tdelete mp_plat_window;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCPs2Window2D::plat_update_engine()\r\n{\r\n\tint x0 = (int) (((float) m_xpos) * NxPs2::SDraw2D::GetScreenScaleX());\r\n\tint y0 = (int) (((float) m_ypos) * NxPs2::SDraw2D::GetScreenScaleY());\r\n\r\n\tDbg_Assert(x0 >= 0);\r\n\tDbg_Assert(y0 >= 0);\r\n\r\n\tint x1 = x0 + (int) (((float) m_width ) * NxPs2::SDraw2D::GetScreenScaleX()) - 1;\r\n\tint y1 = y0 + (int) (((float) m_height) * NxPs2::SDraw2D::GetScreenScaleY()) - 1;\r\n\r\n\tDbg_Assert(x1 >= 0);\r\n\tDbg_Assert(y1 >= 0);\r\n\r\n\tmp_plat_window->SetScissor(x0, y0, x1, y1);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCWindow2DManager::s_plat_alloc_window2d_pool()\r\n{\r\n\tfor (int i = 0; i < vMAX_WINDOW_INSTANCES; i++)\r\n\t{\r\n\t   \tCPs2Window2D *p_window = new CPs2Window2D;\r\n\t\tp_window->mp_next = sp_window_list;\r\n\t\tsp_window_list = p_window;\r\n\t}\r\n}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_NxWin2D.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxWin2D.h\r\n\r\n#ifndef\t__GFX_P_NX_WIN2D_H__\r\n#define\t__GFX_P_NX_WIN2D_H__\r\n\r\n#include \t\"Gfx/NxWin2D.h\"\r\n#include \t\"Gfx/NGPS/NX/sprite.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of the CWindow2D\r\nclass\tCPs2Window2D : public CWindow2D\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCPs2Window2D(int x = 0, int y = 0, int width = 640, int height = 448);\r\n\t\t\t\t\t\t\t\tCPs2Window2D(const Mth::Rect & win_rect);\r\n\tvirtual\t\t\t\t\t\t~CPs2Window2D();\r\n\r\n\tNxPs2::SScissorWindow *\t\tGetEngineWindow() const;\r\n\r\nprivate:\r\n\t//\r\n\tvirtual void\t\t\t\tplat_update_engine();\t\t// Update engine primitives\r\n\r\n\t// Machine specific members\r\n\tNxPs2::SScissorWindow *\t\tmp_plat_window;\t\t\t\t// Pointer to engine window\r\n};\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline NxPs2::SScissorWindow *\tCPs2Window2D::GetEngineWindow() const\r\n{\r\n\treturn mp_plat_window;\r\n}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_gfxman.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics (GFX)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_gfxman.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t07/26/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGraphics device manager\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\r\nextern \"C\"\t\t\t\t \r\n{\r\n\r\n#include <sifdev.h>\r\n#include <libgraph.h>\r\n#include <libpkt.h>\r\n}\r\n\r\n#include <gfx/gfxman.h>\r\n#include <gfx/nxviewport.h>\r\n#include <sys/file/filesys.h>\r\n\r\n#include <gel/scripting/symboltable.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define NUMPIXELS ( width * height )\r\n\r\n#define HEADSIZE 54\r\n#define IMAGESIZE ( NUMPIXELS * 3 )\r\n#define BITMAPSIZE ( IMAGESIZE + HEADSIZE )\r\n\r\n// Macro to store 32-bit data to unaligned address.\r\n#define SET_UINT32( addr, x ) ( \\\r\n\t*(( uint16 * )( addr )) = ( x ), \\\r\n\t*(( uint16 * )(( addr ) + 2 )) = (( x ) >> 16 ) \\\r\n)\r\n\r\nvoid SetupBMPHeader(uint8 *bmp, int width, int height)\r\n{\r\n\t// Initialize the BMP header structure.\r\n\t// Bitmapfileheader\r\n\t*bmp\t\t\t\t\t\t= 'B';              // Type\r\n\t*( bmp + 1 )\t\t\t\t= 'M';\r\n\tSET_UINT32( bmp + 2, BITMAPSIZE );\t\t\t\t// Size\r\n\t*( uint16 * )( bmp + 6 )\t= 0;                // Reserved\r\n\tSET_UINT32( bmp + 10, HEADSIZE );\t\t\t\t// Offset\r\n\r\n\t// Bitmapinfoheader\r\n\tSET_UINT32( bmp + 14, 40 );\t\t\t\t\t\t// Bitmapinfoheader size\r\n\tSET_UINT32( bmp + 18, width );\t\t\t\t\t// Width\r\n\tSET_UINT32( bmp + 22, height );\t\t\t\t\t// Height\r\n\t*( uint16 * )( bmp + 26 )\t= 1;      \t\t\t// Planes\r\n\t*( uint16 * )( bmp + 28 )\t= 24;     \t\t\t// Bitcount\r\n\tSET_UINT32( bmp + 30, 0 );\t\t\t\t\t\t// Compression\r\n\tSET_UINT32( bmp + 34, IMAGESIZE );\t\t\t\t// Image size in bytes\r\n\tSET_UINT32( bmp + 38, 4740 );\t\t\t\t\t// X Pels per metre\r\n\tSET_UINT32( bmp + 42, 4740 );\t\t\t\t\t// Y Pels per metre\r\n\tSET_UINT32( bmp + 46, 0 );\t\t\t\t\t\t// ClrUsed\r\n\tSET_UINT32( bmp + 50, 0 );\t\t\t\t\t\t// ClrImportant\r\n\r\n}\r\n\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// File: main.c\r\n// Date: August 19, 2000\r\n// Author: George Bain @ Sony Computer Entertainment Europe\r\n// Description: Store GS local memory -> Main/SPR memory \r\n// Notes: - read StoreTextureVIF1() and DumpImage() for more information\r\n//        - pause screen using \"square + cross buttons\" to avoid blur\r\n//\r\n//--------------------------------------------------------------------------------------------\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// I N C L U D E S\r\n//--------------------------------------------------------------------------------------------\r\n\r\n#include <eekernel.h>\r\n#include <stdlib.h>\r\n#include <stdio.h>\r\n#include <math.h>\r\n#include <libdev.h>\r\n#include <eeregs.h>\r\n#include <libgraph.h>\r\n#include <libdma.h>\r\n#include <libvu0.h>\r\n#include <sifdev.h>\r\n#include <libpkt.h>\r\n#include <sifdev.h>\r\n#include <sifrpc.h>\r\n#include <libpad.h>\r\n\r\n#include\t<gfx\\ngps\\nx\\dma.h>\r\n\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// D E F I N E S\r\n//--------------------------------------------------------------------------------------------\r\n\r\n#define SCRN_W (640)\r\n#define SCRN_H (224)\r\n#define SCRN_CENTER_X (2048.0f)\r\n#define SCRN_CENTER_Y (2048.0f)\r\n#define SCRN_Z (512.0f)\r\n#define ZBUF_MAX (16777000.0f)\r\n#define ZBUF_MIN (1.0f)\r\n#define ZCLIP_MAX (16777216.0f)\r\n#define ZCLIP_MIN (1.0f)\r\n#define ASPECT_X (1.0f)\r\n#define ASPECT_Y (((float)SCRN_H*4.0f)/((float)SCRN_W*3.0f))\r\n#define STRING_SIZE   (64)\r\n#define OFFX (((4096-SCRN_W)/2)<<4)\r\n#define OFFY (((4096-SCRN_H)/2)<<4)\r\n#define PI (3.141592f)\r\n\r\n#define RAD_TO_DEG(x) (x * 180.0f / PI)\r\n#define DEG_TO_RAD(x) (x * PI / 180.0f)\r\n\r\n#define ROT_SPEED (1.0f)\r\n#define SET_VECTOR(_p,_x,_y,_z,_w)  ((_p)[0] = _x, (_p)[1] = _y, (_p)[2] = _z, (_p)[3] = _w)\r\n#define TRANS (10.0f)\r\n#define SPR_MEM (0x70000000)\r\n#define UNCACHED_MEM (0x20000000)\r\n#define DMA_SPR (0x80000000)\r\n#define DMA_MEM (0x0FFFFFFF)\r\n#define CUBE_VERT (36)\r\n\r\n#define GIFTAG_NLOOP (CUBE_VERT)\r\n#define GS_PRIM_SHADED (1)\r\n#define GS_PRIM_ALPHA (1)\r\n#define GIFTAG_EOP (1)\r\n#define GIFTAG_PRE (1)\r\n#define GS_PRIM_TEX (1)\r\n\r\n#define RGB_FRAME (1)\r\n\r\n#define GIFTAG_MAX_NLOOP (32767)\r\n#define IMAGE_W (256)\r\n#define IMAGE_H (256)\r\n#define STORE_IMAGE_W (SCRN_W)\r\n#define STORE_IMAGE_H (SCRN_H)\r\n#define IMAGE_ADDR ( ((SCRN_W*SCRN_H*4)*3) / 256 )\r\n#define CLUT_CSM1_MODE (0)\r\n#define CLUT_CSM2_MODE (1)\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// S T R U C T U R E S\r\n//--------------------------------------------------------------------------------------------\r\n\r\ntypedef struct rect_tag\r\n{\r\n\r\n  short x, y;\r\n  short w, h;\r\n\r\n}\r\nRECT;\r\n\r\ntypedef struct timimage_tag\r\n{\r\n\r\n  u_int mode;\r\n  u_int id;\r\n  u_int flag;\r\n  u_int cbnum;\r\n  RECT crect;\r\n  u_int *caddr;\r\n  u_int pbnum;\r\n  RECT prect;\r\n  u_int *paddr;\r\n\r\n}\r\nTIM_IMAGE;\r\n\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// G L O B A L S\r\n//--------------------------------------------------------------------------------------------\r\n\r\nsceVu0FVECTOR camera_p = { 0.0f, 0.0f, -300.0f, 0.0f };\r\nsceVu0FVECTOR camera_zd = { 0.0f, 0.0f, 1.0f, 1.0f };\r\nsceVu0FVECTOR camera_yd = { 0.0f, 1.0f, 0.0f, 1.0f };\r\nsceVu0FVECTOR light0 = { 1.0f, 0.0f, 0.3f, 0.0f };\r\nsceVu0FVECTOR light1 = { 0.0f, 1.0f, 0.3f, 0.0f };\r\nsceVu0FVECTOR light2 = { 0.0f, 0.0f, 1.0f, 0.0f };\r\nsceVu0FVECTOR color0 = { 0.3f, 0.3f, 0.3f, 1.0f };\r\nsceVu0FVECTOR color1 = { 0.3f, 0.3f, 0.3f, 1.0f };\r\nsceVu0FVECTOR color2 = { 0.4f, 0.4f, 0.4f, 1.0f };\r\nsceVu0FVECTOR ambient = { 0.2f, 0.2f, 0.2f, 0.0f };\r\nsceVu0FVECTOR obj_trans = { 0.0f, 0.0f, 0.0f, 0.0f };\r\nsceVu0FVECTOR obj_rot = { 0.0f, 0.0f, 0.0f, 0.0f };\r\nsceVu0FMATRIX local_world;\r\nsceVu0FMATRIX world_view;\r\nsceVu0FMATRIX view_screen;\r\nsceVu0FMATRIX local_screen;\r\nsceVu0FMATRIX normal_light;\r\nsceVu0FMATRIX light_color;\r\nsceVu0FMATRIX local_light;\r\nsceVu0FMATRIX work;\r\nsceGsDBuff db;\r\nsceDmaChan *dmaGIF = NULL;\r\nsceDmaChan *dmaVIF1 = NULL;\r\nfloat delta = ROT_SPEED;\r\nu_int paddata;\r\nu_char rdata[32];\r\nu_long128 pad_dma_buf[scePadDmaBufferMax] __attribute__ ( ( aligned( 64 ) ) );\r\nTIM_IMAGE texture;\r\n\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// P R O T O T Y P E S\r\n//--------------------------------------------------------------------------------------------\r\n\r\nvoid InitPad( void );\r\nvoid InitSystem( void );\r\nvoid InitGraphics( void );\r\nvoid ControlInput( void );\r\nvoid SetAlphaBlend( void );\r\nvoid SetTexFilter( void );\r\nvoid SetTextureInfo( void );\r\nvoid LoadTexture( u_long128 * base_addr, short pixel_mode, short addr, short w, short h,\r\n\t\t  short dest_x, short dest_y );\r\nvoid ClearVRAM( u_char r, u_char g, u_char b, u_char a );\r\nvoid CubePacket( sceVu0FVECTOR * vertex, sceVu0FVECTOR * normal, sceVu0FVECTOR * color,\r\n\t\t sceVu0FVECTOR * st );\r\nvoid sceVu0NormalColorVector( sceVu0IVECTOR c0, sceVu0FMATRIX local_light,\r\n\t\t\t      sceVu0FMATRIX light_color, sceVu0FVECTOR v0, sceVu0FVECTOR c1 );\r\nvoid ReadTIM( u_char * file, TIM_IMAGE * tim, short clut_store_mode );\r\nvoid StoreTextureVIF1( u_long128 * base_addr, short start_addr, short pixel_mode, short x,\r\n\t\t       short y, short w, short h, short frame_width );\r\nvoid DumpImage( int frame_cnt, int oddeven );\r\n\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// Function: DumpImage()\r\n// Description: Uses StoreTextureVIF1() to grab both the odd and even frame buffers in GS local\r\n//              memory.  A 24-bit TIM image is written to a file called \"image.tim\".\r\n// Paramaters:  int frame_cnt: odd or even frame\r\n//              int oddeven: odd or even frame (Vsync)\r\n// Returns: none\r\n// Notes: N/A\r\n//--------------------------------------------------------------------------------------------\r\n\r\n/*\r\nvoid DumpImage( int frame_cnt, int oddeven )\r\n{\r\n\r\n  u_long128 *dst1 = NULL, *dst2 = NULL;\r\n  int fd;\r\n  int cnt = 0;\r\n  int index = 0;\r\n  u_int bnum __attribute__ ( ( aligned( 16 ) ) );\r\n  u_short pixel_head[4] __attribute__ ( ( aligned( 16 ) ) );\r\n  u_int header[3] __attribute__ ( ( aligned( 16 ) ) );\r\n\r\n  // create image file\r\n  fd = sceOpen( \"host:image.tim\", SCE_WRONLY | SCE_TRUNC | SCE_CREAT );\r\n\r\n  header[0] = 0x10;\t\t// id\r\n  header[1] = 0x03;\t\t// flag 2= 16bit 3 = 24bit\r\n\r\n  // write header\r\n  sceWrite( fd, &header[0], 4 );\r\n  sceWrite( fd, &header[1], 4 );\r\n\r\n  bnum = ( ( STORE_IMAGE_W * STORE_IMAGE_H * 3 ) * 2 ) + 12;\t// BNUM\r\n  pixel_head[0] = 0;\t\t//x\r\n  pixel_head[1] = 0;\t\t//y\r\n  pixel_head[2] = 960;\t\t//w\r\n  pixel_head[3] = 448;\t\t//h\r\n\r\n  // write pixel header information\r\n  sceWrite( fd, &bnum, 4 );\r\n  sceWrite( fd, &pixel_head[0], 2 );\r\n  sceWrite( fd, &pixel_head[1], 2 );\r\n  sceWrite( fd, &pixel_head[2], 2 );\r\n  sceWrite( fd, &pixel_head[3], 2 );\r\n\r\n  // allocate some memory\r\n  dst1 = ( u_long128 * ) memalign( 64, STORE_IMAGE_W * STORE_IMAGE_H * 3 );\r\n  dst2 = ( u_long128 * ) memalign( 64, STORE_IMAGE_W * STORE_IMAGE_H * 3 );\r\n\r\n  StoreTextureVIF1( dst1, 0, SCE_GS_PSMCT24, 0, 0, STORE_IMAGE_W, STORE_IMAGE_H, SCRN_W );\r\n  StoreTextureVIF1( dst2, 2240, SCE_GS_PSMCT24, 0, 0, STORE_IMAGE_W, STORE_IMAGE_H, SCRN_W );\r\n\r\n  index = 0;\r\n\r\n  for ( cnt = 0; cnt < STORE_IMAGE_H; cnt++ )\r\n    {\r\n\r\n      if ( ( ( frame_cnt == NULL ) && ( oddeven == NULL ) )\r\n\t   || ( ( frame_cnt ) && ( oddeven ) ) )\r\n\t{\r\n\t  sceWrite( fd, dst1 + index, STORE_IMAGE_W * 3 );\r\n\t  sceWrite( fd, dst2 + index, STORE_IMAGE_W * 3 );\r\n\t}\r\n      else\r\n\t{\r\n\t  sceWrite( fd, dst2 + index, STORE_IMAGE_W * 3 );\r\n\t  sceWrite( fd, dst1 + index, STORE_IMAGE_W * 3 );\r\n\t}\r\n\r\n\r\n      index += 120;\t\t// (STORE_IMAGE_W * 3)/16;\r\n      printf( \"written line:%d\\n\", cnt );\r\n\r\n    }\r\n\r\n  free( dst1 );\r\n  free( dst2 );\r\n\r\n  sceClose( fd );\r\n\r\n\r\n}\t\t\t\t// end DumpImage\r\n\r\n*/\r\n\r\n\r\n\r\n//--------------------------------------------------------------------------------------------\r\n// Function:    StoreTextureVIF1()\r\n// Description: Stores texture data from GS to main memory or scratchpad memory.  See notes on\r\n//              data flow\r\n// Paramaters:  u_long128* base_addr: base address of stored texture data in MAIN/SPR memory\r\n//              short start_addr: start address in GS memory to transfer from\r\n//              short pixel_mode: pixel mode of stored data\r\n//              short x: x location in GS memory\r\n//              short y: y location in GS memory\r\n//              short w: width of stored image\r\n//              short h: height of stored image\r\n//\t\t\t\t\t\t\tshort frame_width: width of frame buffer\r\n// Returns:     N/A\r\n// Notes: -     data flow of store image\r\n//              \t- wait for all 3 PATHS to GIF to be complete (FLUSHA vif code)\r\n//              \t- disable PATH3 transfer using MSKPATH3 vifcode (mask)\r\n//              \t- set BITBLTBUF register (source parameters)\r\n//              \t- set TRXPOS register (x,y postion)\r\n//              \t- set TRXREG register (width and height)\r\n//              \t- set FINISH register (set event)\r\n//              \t- set TRXDIR register (LOCAL->HOST)\r\n//              \t- get previous Interrupt Mask Control (IMR)\r\n//              \t- enable the FINISH event\r\n//              \t- send GIF packet to GS\r\n//              \t- wait for DMA to be complete\r\n//              \t- wait for FINISH event to be generated  (all drawing is complete)\r\n//              \t- change direction of the GS bus\r\n//              \t- change direction of VIF1-FIFO (VIF1_STAT.FDR)\r\n//              \t- DMA GS data to main/spr memory\r\n//              \t- wait for DMA to be complete\r\n//              \t- restore direction of the GS bus\r\n//              \t- restore direction of VIF1-FIFO \r\n//              \t- restore previous Interrupt Mask Control (IMR)\r\n//              \t- enable the FINISH event\r\n//              \t- enable PATH3 transfer using MSKPATH3 vifcode\r\n//--------------------------------------------------------------------------------------------\r\n\r\nvoid StoreTextureVIF1( u_long128 * base_addr, short start_addr, short pixel_mode, short x,\r\n\t\t       short y, short w, short h, short frame_width )\r\n{\r\n\r\n  int texture_qwc;\r\n  sceVif1Packet vif1_pkt;\r\n  u_long128 settup_base[10];\r\n  int buff_width;\r\n  static u_int enable_path3[4] __attribute__ ( ( aligned( 16 ) ) ) = {\r\n    0x06000000,\r\n    0x00000000,\r\n    0x00000000,\r\n    0x00000000,\r\n  };\r\n\r\n  // get quad word count for image\r\n  if ( pixel_mode == SCE_GS_PSMCT32 )\r\n    texture_qwc = ( w * h * 32 ) >> 7;\r\n  else if ( pixel_mode == SCE_GS_PSMCT24 )\r\n    texture_qwc = ( w * h * 24 ) >> 7;\r\n  else if ( pixel_mode == SCE_GS_PSMCT16 )\r\n    texture_qwc = ( w * h * 16 ) >> 7;\r\n  else if ( pixel_mode == SCE_GS_PSMT8 )\r\n    texture_qwc = ( w * h * 8 ) >> 7;\r\n  else\r\n    texture_qwc = ( w * h * 4 ) >> 7;\r\n\r\n  if ( texture_qwc > GIFTAG_MAX_NLOOP )\r\n    {\r\n      printf( \"ERROR: Texture QWC is greater then GIFTAG_NLOOP! line:(%d), file:(%s)\\n\", __LINE__,\r\n\t       __FILE__ ); \r\n\t\t\texit( 0 );\r\n    }\r\n\r\n  buff_width = frame_width >> 6;\r\n\r\n  if ( buff_width <= 0 )\r\n    buff_width = 1;\r\n\r\n  // set base address of GIF packet\r\n  sceVif1PkInit( &vif1_pkt, &settup_base[0] );\r\n  sceVif1PkReset( &vif1_pkt );\r\n\r\n  // will start transfer with VIF code and GS data will follow\r\n  sceVif1PkAddCode( &vif1_pkt, SCE_VIF1_SET_NOP( 0 ) );\r\n  // disable PATH 3 transfer\r\n  sceVif1PkAddCode( &vif1_pkt, SCE_VIF1_SET_MSKPATH3( 0x8000, 0 ) );\r\n  // wait for all 3 PATHS to GS to be complete\r\n  sceVif1PkAddCode( &vif1_pkt, SCE_VIF1_SET_FLUSHA( 0 ) );\r\n  // transfer 6 QW's to GS\r\n  sceVif1PkAddCode( &vif1_pkt, SCE_VIF1_SET_DIRECT( 6, 0 ) );\r\n\r\n  // GIF tag for texture settings         \r\n  sceVif1PkAddGsData( &vif1_pkt, SCE_GIF_SET_TAG( 5, GIFTAG_EOP, NULL, NULL, SCE_GIF_PACKED, 1 ) );\r\n  sceVif1PkAddGsData( &vif1_pkt, 0xEL );\r\n\r\n  // set transmission between buffers\r\n  sceVif1PkAddGsData( &vif1_pkt, SCE_GS_SET_BITBLTBUF( start_addr, buff_width, pixel_mode,\t// SRC\r\n\t\t\t\t\t\t       NULL, NULL, NULL ) );\t// DEST\r\n  sceVif1PkAddGsData( &vif1_pkt, SCE_GS_BITBLTBUF );\r\n\r\n  // set transmission area between buffers        ( source x,y  dest x,y  and direction )\r\n  sceVif1PkAddGsData( &vif1_pkt, SCE_GS_SET_TRXPOS( x, y, 0, 0, 0 ) );\r\n  sceVif1PkAddGsData( &vif1_pkt, SCE_GS_TRXPOS );\r\n\r\n  // set size of transmission area \r\n  sceVif1PkAddGsData( &vif1_pkt, SCE_GS_SET_TRXREG( w, h ) );\r\n  sceVif1PkAddGsData( &vif1_pkt, SCE_GS_TRXREG );\r\n\r\n  // set FINISH event occurrence request\r\n  sceVif1PkAddGsData( &vif1_pkt, ( u_long ) ( 0x0 ) );\r\n  sceVif1PkAddGsData( &vif1_pkt, SCE_GS_FINISH );\r\n\r\n  // set transmission direction  ( LOCAL -> HOST Transmission )\r\n  sceVif1PkAddGsData( &vif1_pkt, SCE_GS_SET_TRXDIR( 1 ) );\r\n  sceVif1PkAddGsData( &vif1_pkt, SCE_GS_TRXDIR );\r\n\r\n  // get packet size in quad words        \r\n  sceVif1PkTerminate( &vif1_pkt );\r\n\r\n\r\n\r\n\r\n  // get current IMR status\r\n//  u_long prev_imr = 0;\r\n//  prev_imr = sceGsPutIMR( sceGsGetIMR(  ) | 0x0200 );    // <<<<<  Mick, removed.\r\n\r\n\r\n  // set the FINISH event\r\n  DPUT_GS_CSR( GS_CSR_FINISH_M );\r\n\r\n\r\n\r\n  // DMA from memory and start DMA transfer\r\n  FlushCache( WRITEBACK_DCACHE );\r\n  \r\n\tDPUT_D1_QWC( 0x7 );\r\n  \r\n\tDPUT_D1_MADR( ( u_int ) vif1_pkt.pBase & DMA_MEM );\r\n\r\n  \r\n\tDPUT_D1_CHCR( 1 | ( 1 << 8 ) );\r\n\r\n  asm __volatile__( \" sync.l \" );\r\n\r\n\r\n  // check if DMA is complete (STR=0)\r\n  while ( DGET_D1_CHCR(  ) & 0x0100 );\r\n//  printf( \" 5 GS registers set\\n\" );\r\n\r\n  // check if FINISH event occured\r\n  while ( ( DGET_GS_CSR(  ) & GS_CSR_FINISH_M ) == 0 );\r\n//  printf( \" Finish event complete\\n\" );\r\n\r\n\r\n\r\n  // change VIF1-FIFO transfer direction (VIF1 -> MAIN MEM or SPR)\r\n  *VIF1_STAT = 0x00800000;\r\n\r\n\r\n  // change GS bus direction (LOCAL->HOST)\r\n  DPUT_GS_BUSDIR( ( u_long ) 0x00000001 );\r\n\r\n\r\n//  printf( \" Changed VIF1 and GS direction complete\\n\" );\r\n\r\n  // DMA to memory and start DMA transfer\r\n  FlushCache( WRITEBACK_DCACHE );\r\n  \r\n\tDPUT_D1_QWC( texture_qwc );\r\n  \r\n\tDPUT_D1_MADR( ( u_int ) base_addr & DMA_MEM );\r\n\r\n  \r\n\tDPUT_D1_CHCR( 0 | ( 1 << 8 ) );\r\n  \r\n\tasm __volatile__( \" sync.l \" );\r\n\r\n  // check if DMA is complete (STR=0)\r\n  while ( DGET_D1_CHCR(  ) & 0x0100 );\r\n//  printf( \" Transferred:(%d) QW from GS -> MEM complete\\n\", texture_qwc );\r\n\r\n\r\n\r\n  // change VIF1-FIFO transfer direction (MAIN MEM or SPR -> VIF1)\r\n  *VIF1_STAT = 0;\r\n\r\n  // change GS bus direction (HOST->LOCAL)\r\n  DPUT_GS_BUSDIR( ( u_long ) 0 );\r\n\r\n\r\n  // restore previous IMR status\r\n//  sceGsPutIMR( prev_imr );\t // <<<<<  Mick, removed.\r\n\r\n  \r\n  \r\n  // set the FINISH event\r\n  DPUT_GS_CSR( GS_CSR_FINISH_M );\r\n//  printf( \" Restore VIF1 and GS direction complete\\n\" );\r\n\r\n  // MSKPATH3 is now enabled to allow transfer via PATH3\r\n  DPUT_VIF1_FIFO( *( u_long128 * ) enable_path3 );\r\n\r\n//  printf( \" Restore PATH3 direction complete\\n\" );\r\n\r\n\r\n}\t\t\t\t// end StoreTextureVIF1\r\n\r\n\r\n\r\n//----------------------------------------------EOF-------------------------------------------\r\n\r\n\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace NxPs2\r\n{\r\n\tvoid\tWaitForRendering();\r\n}\r\n\r\nnamespace Gfx\r\n{\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tManager::DumpVRAMUsage( void )\r\n{\r\n\tprintf (\"ERROR: DumpVRAMUsage is no longer supported, due to dynamic textures\\n\");\t\r\n}\r\n\r\n\r\nvoid \tsave_to_pc(const char *fileroot,uint8* pixelBuffer)\r\n{\r\n\t\t// Try to find a good filename of the format filebasexxx.bmp.  \"Good\" is\r\n\t\t// defined here as one that isn't already used.\r\n\t\tchar fileName[ 132 ];\r\n\t\tint i = 0;\r\n\t\twhile ( TRUE ) {\r\n\t\t\tsprintf( fileName, \"Screens\\\\%s%03d.bmp\", fileroot, i );\r\n\t\r\n\t\t\t// Found an unused one!  Yay!\r\n\t\t\tif ( FALSE == File::Exist( fileName ))\r\n\t\t\t\tbreak;\r\n\t\r\n\t\t\ti++;\r\n\t\t}\r\n\t\tprintf (\"Saving Screenshot %s\\n\",fileName);\r\n\t\t// Write out the file.\t\r\n\t\tvoid *rwfd;\r\n\t\trwfd = File::Open( fileName, \"wb\" );\r\n\t\tDbg_MsgAssert(rwfd, (\"Couldn't open %s for writing on the PC.\", fileName));\r\n\t\tFile::Write(pixelBuffer,1,640*448*3+HEADSIZE,rwfd);\r\n\t\tFile::Close( rwfd );\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::ScreenShot( const char *fileroot )\r\n{\r\n\r\n\r\n\t#if 1\r\n\r\n\tbool\tcompact = true;\r\n\r\n\tFlushCache( 0 );\r\n\tsceGsSyncPath( 0, 0 );\r\n\r\n\tNxPs2::WaitForRendering(); \t\t// This will also ensure the DMA buffers are free\r\n\tsceGsSyncPath( 0, 0 );\r\n\r\n\r\n\r\n\tuint8 *pixelBuffer;\r\n\t// Get a huge chunk of memory and dump the video buffer into it.\r\n\tpixelBuffer = NxPs2::dma::pRuntimeBuffer + HEADSIZE + 10;\r\n\r\n\t// for compact mode, we need 640*448*31/32*3 + 640*448/32*4  + 54 bytes = 833280 + 35840 + 54 = 869174 bytes\r\n\r\n\tint lines=32;\t\t\t// lines per StoreImage (we need to do it in at last two)\r\n\tfor (int i=0;i<448/lines;i++)\r\n\t{\r\n\t\t// not got that much memory, so we convert the buffer in place\r\n\t\tuint32 *p_pixel4 =  (uint32*)( pixelBuffer +i*640*3*lines );\r\n\t\t\r\n\t\tStoreTextureVIF1(\r\n\t\t(u_long128*)( p_pixel4 ),\r\n\t\t0,  // offset....\r\n\t\tSCE_GS_PSMCT32,\r\n\t\t0,\r\n\t\ti*lines,\r\n\t\t640,\r\n\t\tlines,\r\n\t\t640 );\r\n\r\n\t\tuint8 *p_pixel3 =  (uint8*) p_pixel4;\r\n\t\tuint8 r, g, b;\r\n\t\tfor (int x = 0;x < 640*lines;x++)\r\n\t\t{\r\n\t\t\t// \r\n\t\t\tr = ((( *p_pixel4 ) >> 16 ) & 0xff ) ;\r\n\t\t\tg = ((( *p_pixel4 ) >> 8 ) & 0xff ) ;\r\n\t\t\tb = ((( *p_pixel4++ )  ) & 0xff ) ;\r\n\t\t\t\r\n\t\t\t*p_pixel3++ = r;\r\n\t\t\t*p_pixel3++ = g;\r\n\t\t\t*p_pixel3++ = b;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// flip the buffer upside down in place\r\n\tuint8*\t\ttop_line = pixelBuffer;\r\n\tuint8*\t\tbot_line = pixelBuffer + 640*3*447;\r\n\tfor (int line = 0;line <224; line++)\r\n\t{\r\n\t\tfor (int b = 0;b<640*3;b++)\r\n\t\t{\r\n\t\t\tuint8 t = top_line[b];\r\n\t\t\ttop_line[b] = bot_line[b];\r\n\t\t\tbot_line[b] = t;\r\n\t\t}\r\n\t\ttop_line += 640*3;\r\n\t\tbot_line -= 640*3;\r\n\t}\r\n\r\n\t// and insert the header\r\n\tSetupBMPHeader((uint8*)NxPs2::dma::pRuntimeBuffer+10,640,448);\r\n\r\n\t// Finally, I'm going to copy the whole pile of crap down 10 bytes\r\n\t// in case anything that saves it relies on it being 16 byte aligned\r\n\tuint8 *p1 = (uint8*)NxPs2::dma::pRuntimeBuffer+10;\r\n\tuint8 *p2 = (uint8*)NxPs2::dma::pRuntimeBuffer;\r\n\tfor (int i=0;i<640*448*3+HEADSIZE;i++)\r\n\t{\r\n\t\t*p2++ = *p1++;\r\n\t}  \r\n\tpixelBuffer = (uint8*)NxPs2::dma::pRuntimeBuffer; \r\n\r\n\tif (Script::GetInt(\"memcard_screenshots\"))\r\n\t{\r\n\t\tprintf (\"STUBBED!!! Saving Screenshot to TH4MC???\\n\");\r\n//\t\tCFuncs::SaveDataFile(\"TH4MC\", NxPs2::dma::pRuntimeBuffer, 640*448*3+HEADSIZE);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsave_to_pc(fileroot,pixelBuffer);\t\r\n\t}\r\n\t\r\n\tif (!compact)\r\n\t{\r\n\t\t// Release the memory for the video buffer.\r\n\t\tdelete( pixelBuffer );\r\n\t}\t\r\n\t\r\n\t#else\r\n\t\tprintf (\"Screenshot functionality stubbed out\\n\");\r\n\t\r\n\t#endif\r\n\r\n\t\r\n    FlushCache(0);\r\n\r\n\r\n}\r\n\r\n// Called byte dumpshots\r\nvoid Manager::DumpMemcardScreeenshots()\r\n{\r\n/*\r\n\tchar name[100];\r\n\tfor (int i=0;i<12;i++)\r\n\t{\r\n\t\tsprintf(name,\"TH4MC%03d\",i);\r\n\t\tprintf (\"Checking for %s \\n\",name);\r\n\t\tif (CFuncs::LoadDataFile(name, NxPs2::dma::pRuntimeBuffer, 640*448*3+HEADSIZE))\r\n\t\t{\r\n\t\t\tsave_to_pc(\"MemCard\", NxPs2::dma::pRuntimeBuffer);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tprintf (\"not there\\n\");\r\n\t\t}\r\n\t}\r\n*/\t\r\n\tprintf (\"DumpMemcardScreeenshots STUBBED\\n\");\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Gfx\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_memview.cpp",
    "content": "//////////////////////////////////////////////////////\r\n// p_memview.cpp\r\n//\r\n// code for tracking memory usage, and displaying it in a graphical manner\r\n// keeps extra info about allocated blocks\r\n// including the call stack, so we can print out information\r\n// about specific allocated blocks\r\n// which we will select using the graphical memory browser\r\n//\r\n//\r\n// tried to use a little of the task system as possible\r\n// so we can run the inspector\r\n// without it messing with the heap it inspects\r\n//\r\n//\r\n\r\n\r\nextern char _mem_dump_start[];\r\nextern char _map_file_start[];\r\nextern char _symbols_start[];\r\nextern char _callstack_start[];\r\nextern char _code_end[];\r\nextern char\t_std_mem_end[];\r\nextern char\t_stack_size[];\r\n\r\nextern char __text_org[];\r\nextern char __data_org[];\r\nextern char __rodata_org[];\r\nextern char __bss_org[];\r\n\r\nextern char __rodata_orgend[];\r\nextern char __bss_objend[];\r\nextern char __text_objend[];\r\n\r\nextern char _debug_heap_start[];\r\nextern char _script_heap_start[];\r\n\r\n\r\n//extern char _rwheapdebug_start[];\r\n\r\n\t\t\t \r\n#define\tSTACKDEPTH  30\t\t\t \r\n\r\nint \tmem_strings;\r\n\r\n\r\nnamespace Nx\r\n{\r\n\textern void\t_debug_change_2d_scale(float x);\r\n\r\n}\r\n\t\t\t \r\nextern \"C\"\t\t\t\t \r\n{\r\nextern char ENTRYPOINT[];\t\t\r\n\r\n\r\n#include <sifdev.h>\r\n#include <libgraph.h>\r\n#include <libpkt.h>\r\n}\r\n\r\n#include <gfx/gfxman.h>\r\n#include <gfx/nxviewport.h>\r\n#include <gel/inpman.h>\t\t\t\t\t// needed for buttons\r\n#include <gfx/ngps/p_memview.h>\r\n#include <sys/file/filesys.h> \t\t\t// needed for loading map file\r\n#include <sys/config/config.h>\r\n#include <gel/scripting/script.h>\r\n\r\n#include <stdio.h>\r\n#include <string.h>\r\n#include <sifdev.h>\r\n#include <sifrpc.h>\r\n#include <libcdvd.h>\r\n\r\n\r\n#include <sys\\mem\\memman.h>\r\n#include <sys\\mem\\heap.h>\r\n#include <sys\\mem\\region.h>\r\n\r\n// needed for some VerticalMenu specific debugging\t\t\t\t\t\t\t\r\n#include <core/support.h>\r\n#include <core/list.h>\r\n#include <core/string/cstring.h>\r\n\r\n\r\nextern volatile int\ttest_vblanks;\r\n\r\n\r\nclass CCallStack\r\n{\r\npublic:\r\n\tvoid Append(CCallStack *p);\r\n\tvoid Remove();\r\n\tvoid InitHead();\r\n\tint\tused;\r\n\tint\tsize;\r\n\tCCallStack *pNext;\r\n\tCCallStack *pPrev;\r\n\tint\taddr[STACKDEPTH];\r\n\tuint32\tflags;\r\n\tMem::Allocator::BlockHeader * pBlock;\t// pointer to block that has this callstack\r\n\r\n};\r\n\r\nCCallStack\t\tfree_list;\t// list of created objects\r\nCCallStack\t\tused_list;\t// list of created objects\r\n\r\n// init a node, so it can act as the head\t\t\t \r\ninline void CCallStack::InitHead()\r\n{\r\n\tpPrev = this;\r\n\tpNext = this;\r\n}\r\n\t\r\n// append node p to this node (after it)\t\t\t\t\t\t\t\t\t \r\ninline void CCallStack::Append(CCallStack *p)\r\n{\r\n\r\n\tp->pNext = this->pNext;\r\n\tp->pPrev = this;\r\n\tthis->pNext = p;\r\n\tp->pNext->pPrev = p;\r\n}\r\n\r\n// simply unlink it from the list\t\t\t   \r\ninline void CCallStack::Remove()\r\n{\r\n\tpPrev->pNext = pNext;\r\n\tpNext->pPrev = pPrev;\r\n}\r\n\r\n\r\n\t\t\t\t\t\t\r\n//CCallStack * CallStack_FirstFree;\r\n//CCallStack * CallStack_FirstUsed; \r\n\r\nstatic int MemView_Active = 0;\r\n\r\n\r\n\r\n#define\tMAX_CALLSTACK (8192 * 8)\t\t// we got 8 mb, woo woo.\r\n\r\n\r\nstatic float step = 128.0f;\r\n\r\n\r\nstatic char HexByte(char a)\r\n{\r\n\tif (a >= '0' && a <='9')\r\n\t{\r\n\t\treturn a-'0';\r\n\t}\r\n\tif (a >= 'A' && a <='F')\r\n\t{\r\n\t\treturn 10 + a-'A';\r\n\t}\r\n\tif (a >= 'a' && a <='f')\r\n\t{\r\n\t\treturn 10 + a-'a';\r\n\t}\r\n\r\n\t// should really be an error, but just ignore it and return 0\r\n\t// as this is only used for parsing the map file\t\r\n\treturn 0;\r\n\t\r\n\t\r\n}\r\n\r\n\r\nstatic int doneonce = 0;\r\n\r\n\r\nchar *MemView_GetFunctionName(int pc, int *p_size)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn \"NULL\";\r\n\t}\r\n\t\t\r\n\tif (!pc)\r\n\t{\r\n\t\treturn \"NULL\";\r\n\t}\r\n\t\t\t\t   \r\n\t// given an address, return the name of the function\r\n\t// does this by intially loading and buuilding a list of\r\n\t// all the start points, and names, of all the functions\r\n\t// by loading the skate3.map\r\n\r\n\t\r\n\tstatic int symbols = 0;\r\n\t\r\n\tif (!doneonce)\r\n\t{\r\n\t\r\n//\t\tmdl.m_fd = sceOpen( \"host:ctrl_out.dat\", SCE_RDWR );\r\n///\t\tsceRead( mdl.m_fd, mdl.m_recorded_data, 72000 * sizeof( Inp::RecordedData ));\r\n//\t\tsceClose( mdl.m_fd );\r\n\r\n\r\n\t\tchar map_name[256];\r\n\t\tsprintf (map_name,\"host0:..\\\\build\\\\ngpsgnu\\\\%s.map\", Config::GetElfName());\r\n\t\tprintf (\"Map name = %s\\n\",map_name);\r\n\r\n\t\tint map_file_handle;\r\n\t\tmap_file_handle= sceOpen(map_name, SCE_RDONLY);\t\t\r\n\r\n\t\tif (map_file_handle < 0)\r\n\t\t{\r\n\t\t\treturn \"(map file not loaded yet)\";\r\n\t\t}\r\n\r\n\r\n\t\tdoneonce = 1;\r\n\t\r\n\t\tchar *pQB= _map_file_start ;\r\n\t\t\r\n\t\t//sceRead(map_file_handle,pQB,4000000);\r\n\t\tlong HedSize=sceLseek(map_file_handle, 0, SCE_SEEK_END);\r\n\t\tsceLseek(map_file_handle, 0, SCE_SEEK_SET);\r\n\t\tsceRead(map_file_handle,pQB,HedSize);\r\n\t\tsceClose(map_file_handle);\r\n\t\t// Now the file is loaded, we need to extract all the functions\r\n\t\t// so, search for the text \r\n\t\t\r\n\t\tchar *p = strstr(pQB,\"0\");\t// Find the first address\r\n\t\tint\t *d = (int*)_symbols_start; \r\n\t\twhile (*p)\r\n\t\t{\r\n\t\t\t// the next 8 characters are the address in lower case hex\r\n\t\t\tint addr = 0;\r\n\t\t\tfor (int i=0;i<8;i++)\r\n\t\t\t{\r\n\t\t\t\taddr <<= 4;\r\n\t\t\t\taddr += HexByte(*p++);\r\n\t\t\t}\r\n\t\t\tp+= 1;\t\t\t// skip the space\r\n\t\t\t\r\n\t\t\t// the next 8 characters are the size in lower case hex\r\n\t\t\tint size = 0;\r\n\t\t\tfor (int i=0;i<8;i++)\r\n\t\t\t{\r\n\t\t\t\tsize <<= 4;\r\n\t\t\t\tsize += HexByte(*p++);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// skip white spaces\r\n\t\t\twhile( *p == ' ' )\r\n\t\t\t{\r\n\t\t\t\tp++;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tint alignment = 0;\r\n\t\t\tdo\r\n\t\t\t{\r\n\t\t\t\talignment <<= 4;\r\n\t\t\t\talignment += HexByte(*p++);\r\n\t\t\t} while( *p != ' ' );\r\n\r\n\t\t\t// skip white spaces\r\n\t\t\twhile( *p == ' ' )\r\n\t\t\t{\r\n\t\t\t\tp++;\r\n\t\t\t}\r\n\r\n\t\t\t// only store symbols of non-zero size\r\n\t\t\t// otherwise, we get confused by having things like _bss_size in there\r\n\t\t\t// as they are not addresses, they just look like them, being so big...\r\n\t\t\tif (size || (addr >(int) __text_objend))\r\n\t\t\t{\r\n\t\t\t\tif( alignment == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t*d++ = addr;\t\t// store the address of the symbol\r\n\t\t\t\t\t*d++ = (int)p;\t\t\t// store the start of the symbol name\r\n\t\t\t\t\tsymbols++;\t\t \t// one more symbol\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// search for first space, or CF, and replace with a 0\r\n\t\t\t// that way we ignore the \"unmangled\" version of the function\r\n\t\t\twhile (*p && /**p!=' ' &&*/ *p!=0x0a && *p!='(' && *p != 0x0d) p++;\t\r\n\t\t\t*p++ = 0;\r\n\t\t\t\r\n\r\n\t\t\t// skip to LF, and replace the \t\t\t\r\n\t\t\twhile (*p && *p!=0x0a) p++;\t\t// skip to start of next line\r\n\t\t\tp++;\t\t\t\t\t\t// skip over 0a, will now be at the space on next line\r\n\t\t}\r\n\r\n\t\tuint32 *p_top  =  (uint32*)_symbols_start;\r\n\t\tfor\t(int i = 0;i<symbols-1;i++)\r\n\t\t{\r\n\t\t\tuint32 top = *p_top;\r\n\t\t\tuint32 *p_scan  =  p_top+2;\t  \r\n\t\t\tuint32 *p_best = p_top;  \t\t\t\r\n\t\t\tfor (int j = i;j<symbols-1;j++)\r\n\t\t\t{\r\n\t\t\t\tuint32 scan = *p_scan;\r\n\t\t\t\tif (scan < top)\r\n\t\t\t\t{\r\n\t\t\t\t\ttop = scan;\r\n\t\t\t\t\tp_best = p_scan;\r\n\t\t\t\t}\r\n\t\t\t\tp_scan+=2;\r\n\t\t\t}\r\n\t\t\tuint64 t = *(uint64*)p_top;\r\n\t\t\t*(uint64*)p_top = *(uint64*)p_best;\r\n\t\t\t*(uint64*)p_best = t;\t\t\r\n\t\t\tp_top +=2;\r\n\t\t}\r\n\t}\r\n\r\n\t\r\n\tint\t *s = (int*)_symbols_start; \r\n\r\n// just serach the table\r\n// (might want a binary search, but no real need for speed)\r\n\tfor (int i=0;i<symbols;i++)\r\n\t{\r\n\t\r\n\t\tint addr = *s;\r\n\t\tif (addr > pc)\t \t\t// if this one is above the pc\r\n\t\t{\r\n\t\t\t*p_size = addr-s[-2];\t\t// calculate the size of the function\r\n\t\t\treturn (char*) (s[-1]);\t\t// then the previous one is the function\r\n\t\t}\r\n\t\ts += 2;\t\r\n\t}\r\n\t\t \r\n\treturn \"UNKNOWN\";\r\n\t\r\n}\r\n\r\n// Track the call stack by looking the instructions to\r\n// see where the ra was stored on the stack\r\n// iMadDepth is the number of address to trace back\r\n// pDest is the location to put the results, whcih are stored as\r\n//\tdw\tra,0\r\n// (not sure why the zero is there...)\r\nint DumpUnwindStack( int iMaxDepth, int *pDest )\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\t\r\n\tuint32* ra;\r\n\tuint64* sp;\t\t\t\t\t\t\t\t\t\t\t// frame pointer\r\n\tra = ((uint32*)DumpUnwindStack)+64;\t\t\t\t// fake point in function to unwind from (\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// after the sd ra,0(sp), but before getting it back\r\n\tasm ( \"daddu %0, $29, $0\" : \"=r\" (sp) );\t\t\t// get current sp\r\n\r\n\tif (!pDest)\t\t\t\t\t\t   \t\r\n\t{\r\n\t\tprintf(\"\\n\");\r\n\t}\r\n\t\t\r\n\tint icd = iMaxDepth;\t   \t\t\t\t\t\t\t// depth counter\r\n\tuint32* last_ra = NULL;\r\n\twhile ( icd-- )\r\n\t{\r\n\t\t\t/* scan instruction*/\r\n\t\tuint32* pc = ra;\t\t\t\t\t\t\t\t// current pc, somewehre in middle of function\r\n\t\tuint32 count = 4096;\t\t\t\t\t\t\t// enought to cover large functions\t(16k)\r\n\t\twhile ( count-- )\r\n\t\t{\r\n\t\t\tuint32 ins = *pc;\t\t \t\t\t\t\t// get 32 bit instruction\r\n\t\t\tif (((ins >> 16) & 0x7fff) == 0x7fbf)\t\t// sd ra,offset(sp)  (or sq, for .C files)\r\n\t\t\t{\r\n\t\t\t\tuint32 offset = *(short*)pc;\t\t\t// get offset (bottom 16 bits)\r\n\t\t\t\tra = (uint32*)(sp[offset>>3]);\t\t\t\t\t// >>3 as it's at 64 bit word pointer\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tpc--;\r\n\t\t}\r\n\t\twhile ( count--)\r\n\t\t{\r\n\t\t\tuint32 ins = *pc;\t\t \t\t\t\t\t// get 32 bit instruction\r\n\t\t\tif ((ins >> 16) == 0x27bd)\t\t\t\t\t// addiu sp,sp,offset\r\n\t\t\t{\r\n\t\t\t\tint offset = *(short*)pc;\t\t\t\t// get offset (bottom 16 bits)\r\n\t\t\t\tif (offset & 0x8000)\r\n\t\t\t\t{\r\n\t\t\t\t\toffset |= 0xffff0000;\r\n\t\t\t\t}\r\n\t\t\t\tsp = (uint64*)( (int)(sp) - (offset));\t   \r\n\t\t\t\tbreak; \t\r\n\t\t\t}\t\t\t\r\n\t\t\tpc--;\r\n\t\t}\r\n\r\n//\t\tif (last_ra == ra)\r\n//\t\t{\r\n//\t\t\ticd++;\t\t\t// one more please....\r\n//\t\t}\r\n//\t\telse\r\n\t\t{\r\n\t\t\tlast_ra = ra;\r\n\t\t\tif (pDest)\r\n\t\t\t{\r\n\t\t\t\t*pDest++ = (int)ra;\r\n\t\t\t\t*pDest = 0;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tint size;\r\n\t//\t\t\tprintf (\"sp = %p, ra = %p %s\\n\",sp,ra,MemView_GetFunctionName((int)ra));\r\n\t\t\t\tprintf (\"%p: %s\\n\",ra,MemView_GetFunctionName((int)ra,&size));\r\n\t\t\t}\r\n\t\t}\r\n\t    \r\n\t\t// test to see if we have recursed up all the way...\r\n\t\tif (abs(int((int)ra - (int)&ENTRYPOINT)) < 1024\r\n\t\t   || (int)ra &3 \r\n\t\t   || (int)ra < 0x100000\r\n\t\t   || (int)ra > (int)_code_end\t\t// and check it's not totally crazy....\r\n\t\t   )\r\n\t\t{\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\r\n\t}\r\n\treturn iMaxDepth - icd;\r\n}\r\n\t\t\t\t   \r\n\t\t\t\t   \r\n//        mD_L2           = nBit( vD_L2 ),\r\n//        mD_R2           = nBit( vD_R2 ),\r\n//        mD_L1           = nBit( vD_L1 ),\r\n//        mD_R1           = nBit( vD_R1 ),\r\n//        mD_TRIANGLE     = nBit( vD_TRIANGLE ),\r\n//\t      mD_CIRCLE       = nBit( vD_CIRCLE ),\r\n//        mD_X            = nBit( vD_X ),\r\n//        mD_SQUARE       = nBit( vD_SQUARE ),\r\n//        mD_SELECT       = nBit( vD_SELECT ),\r\n//        mD_L3           = nBit( vD_L3 ),\r\n//        mD_R3           = nBit( vD_R3 ),\r\n//        mD_START        = nBit( vD_START ),\r\n//        mD_UP           = nBit( vD_UP ),\r\n//        mD_RIGHT        = nBit( vD_RIGHT ),\r\n//        mD_DOWN         = nBit( vD_DOWN ),\r\n//        mD_LEFT         = nBit( vD_LEFT ),\r\n\r\n\r\nvoid MemViewToggle()\r\n{\r\n\tMemView_Active ^=1;\r\n}\r\n\r\n\r\n\t \r\n\r\nvoid MemView_Alloc( void *v)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\r\n\tMem::Allocator::BlockHeader *p = (Mem::Allocator::BlockHeader *)v;\t\r\n\t\r\n\tstatic int cleared = 0;\r\n\tif (!cleared)\r\n\t{\r\n\t\tcleared = 1;\r\n\t\tfree_list.InitHead();\r\n\t\tused_list.InitHead();\r\n\t\tCCallStack *p = (CCallStack *)_callstack_start;\t\t\r\n\t\tfor (int i=0;i<MAX_CALLSTACK;i++)\r\n\t\t{\r\n\t\t\tfree_list.Append(p);\r\n\t\t\tp++;\r\n\t\t}\r\n\t}\r\n\r\n\t// Right, just find one that is not used\r\n\t// remove it from the free list, and add to the full list\r\n\tCCallStack *c = (CCallStack*)free_list.pNext;\t  \t\t// head of free list\r\n\tc->Remove();\r\n\tused_list.Append(c);\r\n\r\n\tDumpUnwindStack(STACKDEPTH-1,c->addr);\t   \t\t\t\t// stick the call stack in there\r\n\tc->size = p->mSize;\r\n\r\n\tc->flags = 0;\r\n \r\n\tp->mp_debug_data = (void*)c;\t\t \t\t\t\t\t// and store it in the block header\r\n\tc->pBlock = p;\t\t\t\t\t\t\t\t\t\t\t// store pointer back\r\n\t\r\n#endif\r\n}\r\n\r\nvoid MemView_Free( void *v)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\t// Need to remove it from the used list\r\n\t// and add it back to the full list\r\n\t\r\n\tMem::Allocator::BlockHeader *p = (Mem::Allocator::BlockHeader *)v;\t\t\t\t\t\t  \r\n\t\t\t\t\t\t  \r\n\tCCallStack *c = (CCallStack*)p->mp_debug_data;\t\r\n\t\r\n\tif (!c)\r\n\t{\r\n\t\t// no debug data, so probably a re-alloc\r\n\t\t// should probably handle those later\r\n\t\treturn;\r\n\t}\r\n\r\n\t// we clear it, in case this header is re-used later \r\n\t// I'm not entirely sure how well this will work\r\n\tp->mp_debug_data = NULL;\t\r\n\tc->Remove();\r\n\tfree_list.Append(c);\r\n\t\r\n#endif\t\r\n}\r\n\r\n\r\nMem::Allocator::BlockHeader *MemView_FindBlock( int addr)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\r\n\t\r\n\tMem::Allocator::BlockHeader *pSmallestBlock\t= NULL;\r\n\tuint32 smallest_block_size = 100000000;\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\tfor (Mem::Heap* heap = mem_man.FirstHeap(); heap != NULL; heap = mem_man.NextHeap(heap))\r\n\t{\r\n\t\tMem::Allocator::BlockHeader *pBlock = (Mem::Allocator::BlockHeader *) heap->find_block((void*)addr);\t\r\n\t\tif (pBlock)\r\n\t\t{\r\n\t\t\tif (pBlock->mSize < smallest_block_size)\r\n\t\t\t{\r\n\t\t\t\tsmallest_block_size = pBlock->mSize;\r\n\t\t\t\tpSmallestBlock = pBlock;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn pSmallestBlock;\r\n#else\r\n\treturn NULL;\r\n#endif\r\n}\r\n\r\nchar * MemView_GetClassName(CCallStack *c)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\tint *ra = (int*)(c->addr[4]);\r\n\tif (!ra) return NULL;\r\n\tint count = STACKDEPTH-4;\r\n\twhile (count--)\r\n\t{\r\n\t\tint instruction = *ra++;\r\n\t\tif (instruction >> 24 == 0x0c)\r\n\t\t{\r\n\t\t\tint code = (instruction & 0xffffff)<<2;\r\n\t\t\tint size;\r\n\t\t\tchar *p = MemView_GetFunctionName(code,&size); \r\n\t\t\t// to tell if this is class or not\r\n\t\t\t// we see if the text is of the form  \r\n\t\t\t//    classname::classname (teminated by a 0)\r\n\t\t\t// as that indicates that it is a constructor\r\n\t\t\t// dude... this is where we need a regular expression....\r\n\t\t\tchar *end = p;\r\n\t\t\twhile (*end) end++;\t   \t\t\t\t\t\t// scan to end\r\n\t\t\twhile (end[-1] != ':' && end > p)\tend--;\t// skip to char after the last :\r\n\t\t\tchar *other = strstr(p,end);\t\t\t\t// find fist occurance of end of string\r\n\t\t\tif (other != end)\t\t\t\t\t\t\t// if different, then this is it!!\r\n\t\t\t{\r\n\t\t\t\treturn MemView_GetFunctionName(code,&size);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\r\n\treturn NULL;\r\n}\r\n\r\n\r\nvoid MemView_DumpBlockInfo(int cursor)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\t\r\n\tMem::Allocator::BlockHeader *pBlock = MemView_FindBlock(cursor);\r\n\tif (!pBlock)\r\n\t{\r\n\t\t// should search free blocks here???\r\n\t}\r\n\t// find this in the allocators used list\r\n\t// and say if it is free, or not\t\r\n\tif (pBlock == NULL)\r\n\t{\r\n\t\tif (cursor > (int)__text_org && cursor < (int)__bss_objend)\t\t// check to see if in code/data\r\n\t\t{\r\n\t\t\t\r\n\t\t\tif (cursor < (int)__data_org)\r\n\t\t\t\tprintf(\"Code: \");\r\n\t\t\telse if (cursor < (int)__rodata_org)\r\n\t\t\t\tprintf(\"Data: \");\r\n\t\t\telse if (cursor < (int)__bss_org)\r\n\t\t\t\tprintf(\"RO-Data: \");\r\n\t\t\telse \r\n\t\t\t\tprintf(\"BSS: \");\r\n\t\t\t\r\n\t\t\r\n\t\t\tint size;\r\n\t\t\tchar *p_name = MemView_GetFunctionName(cursor,&size);\r\n\t\t\tprintf ( \"%s, size %d\\n\",p_name,size);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tprintf (\"Block Not Found\\n\");\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tvoid * p_start = (void*)((uint)pBlock + Mem::Allocator::BlockHeader::sSize);\r\n\t\tprintf (\"Block found, addr = %p, size = %d (Header = %d)\\n\",p_start,pBlock->mSize,Mem::Allocator::BlockHeader::sSize);\r\n\t\tCCallStack *c = (CCallStack*)pBlock->mp_debug_data;\r\n\t\tif (!c)\r\n\t\t{\r\n\t\t\tprintf (\"Block with No Debug Info!!\\n\");\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// assume this is a \"new\", then the fourth callstack ra will point to the \r\n\t\t\t// jal xxxxxx  instruction, where xxxxx is the constructor for the \r\n\t\t\t// or it might be sortly thereafter, so check 16 instructions\r\n\t\t\t\r\n\t\t\tchar * classname = MemView_GetClassName(c);\r\n\t\t\t\t\t\t\r\n\t\t\tif (classname)\r\n\t\t\t{\r\n\t\t\t\tprintf (\"CLASS: %s\\n\",classname);\t\t\r\n\t\t\t}\r\n\r\n\t\t\t// then list out the call stack (skipping the MemView_Alloc, as that's a given, and irrelevant);\t\t\t\r\n\t\t\r\n\t\t\tint *p = c->addr + 1;\r\n\t\t\twhile (p[1])\t\t\t// also skip the ENTRYPOINT, just go back to main()\r\n\t\t\t{\r\n\t\t\t\tint size;\r\n\t\t\t\tprintf (\"%p: %s\\n\",(void*)*p,MemView_GetFunctionName(*p,&size));\r\n\t\t\t\tp++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\nstatic\tint\tblockstart;\r\n\r\nstatic float cursor;\r\n\r\nvoid \t\tMemView_Display()\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\r\n\r\n\tif (!MemView_Active)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tFlushCache( 0 );\r\n\tsceGsSyncPath( 0, 0 );\r\n\t\r\n\t//perfrom the copying\r\n\t// there are 512x256 words in the rectangle\r\n\t// and 32768*1024 bytes in memory\r\n\t// giving us a step of 256 (i.e, sample every 256th bytes)\r\n\t\r\n\t\r\n\t// The start of the middle line will be at \r\n\t//       start + 512 * 2 * 128 * step;\r\n\t// then  start1 + 512 * 2 * 128 * step1\r\n\t// for them to be the same, start + 512 * 2 * 128 * step = start1 + 512 * 2 * 128 * step1\r\n\t// so start1 =  start + 512 * 2 * 128 * (step - step1)\r\n\t\r\n\t\r\n\r\n\tblockstart = 0;\r\n\tint blockend = 0;\r\n\t\r\n\tstatic float last_start;\t\t\t\t \r\n\t\r\n\tfloat start = cursor - (512.0f * 2.0f * 128.0f * step);\r\n\t\r\n\tint i_cursor = (int)cursor;\r\n\t\r\n\tMem::Allocator::BlockHeader *pBlock = MemView_FindBlock(i_cursor);\r\n\r\n\tif (pBlock)\r\n\t{\r\n\t\tblockstart = (int)((uint)pBlock + Mem::Allocator::BlockHeader::sSize);\r\n\t\tint size = pBlock->mSize;\r\n\t\tblockend = (int)((int)blockstart + size);\r\n\t}\r\n\t\r\n\tif (start != last_start)\r\n\t{\r\n\t\tlast_start = start;\r\n\t\tprintf (\"\\nCursor Addr = %p\\n\",(void*)i_cursor);   \t\r\n\t\tMemView_DumpBlockInfo(i_cursor);\r\n\t}\r\n\t\r\n\t\r\n\tstatic int color = 10 + (10<<5) ;\r\n//\tcolor ^= 5 << 10;\r\n\t\r\n\tfloat f_source = start;\r\n\tfloat f_off = 0.0f;\r\n//\tuint16 *source = (uint16*)(intstart&~1);   \t\t// converting from a float to a pointer... yowza!!!\r\n\tuint16 *dest  =  (uint16*)_mem_dump_start;\r\n\tfor (int i=0;i<512*256-4096;i++)\r\n\t{\r\n\t\tuint16 *source = (uint16*)((int)(f_source + f_off) &~1);\t\t\r\n\t\r\n\t\tuint32 word;\r\n\t\tif (source < (uint16*)0x00100000 || source >= (uint16*)(0x08000000))\r\n\t\t{\r\n\t\t\tword = (3<<10)+(3<<5)+(3);\t\t\t// grey for outside of memory\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tword = *source;\r\n\t\t\t\r\n//\t\t\t#if 0 \t\t// only display the unused memor\r\n//\t\t\tif (word !=0 && word !=0x5555)\r\n//\t\t\t{\r\n//\t\t\t\tword = 0x8;\t\t// a used word, set to some dark color\r\n//\t\t\t}\r\n//\t\t\t#endif\r\n\t\t\t\r\n\t\t\tif (blockstart && (int)(source)>=blockstart && (int)(source) <blockend)\r\n\t\t\t   \tword |= color;\r\n\t\t}\r\n\r\n\t\t\t\r\n\t\t*dest++ = word;\r\n\t\t*dest++ = word;\r\n//\t\tsource += intstep;\t\t\t// 128 words = 256 bytes\r\n\t\tf_off += step*2.0f;\t\t\t// 128 words = 256 bytes\t\t\r\n\t}\r\n\r\n\t// need a flush cache, as the data probably has not been written yet...\r\n\tFlushCache( 0 );\r\n\r\n\t//for (int i=0;i<1000000;i++);\t\t\t// bit more of a delay, to stop flickering\r\n\r\n\tsceGsLoadImage gs_simage;\r\n\tsceGsLoadImage gs_pointer;\r\n\t\r\n\t\r\n\tfor (int i=0;i<2;i++)\r\n\t{\r\n\t\tsceGsSetDefLoadImage( &gs_simage , 0 , 640 / 64, SCE_GS_PSMCT32,  \t\t// was SCE_GS_PSMCT16S\r\n\t\t\t\t\t\t\t   64, 64 + 128*i, 512, 128 );\r\n\t\tsceGsSetDefLoadImage( &gs_pointer, 0 , 640 / 64, SCE_GS_PSMCT32,\r\n\t\t\t\t\t\t\t   32, 64 + 127, 32, 3 );\r\n\t\t\r\n\t\tFlushCache( 0 );\t\t\r\n\t\tsceGsExecLoadImage( &gs_simage, ( u_long128 * )(_mem_dump_start + (512*128*4*i))\t\t );\r\n\t\tsceGsExecLoadImage( &gs_pointer, ( u_long128 * )MemView_Display );\r\n\t\tsceGsSyncPath( 0, 0 );\r\n\t}\r\n\r\n\r\n\t\r\n\treturn;\r\n#endif\r\n}\r\n\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\r\nstatic int num_used;\r\n\r\nstatic void ScanRegion(uint32 *p_start, uint32 *p_end)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tprintf (\"scanning from %p to %p\\n\",p_start,p_end);\r\n\t// scan the whole range of memeory\r\n\twhile (p_start<p_end)\r\n\t{\r\n\t\t// get value that might be a pointer\r\n\t\tuint32 x = *p_start++;\r\n\t\t// check to see if it's not odd, and it lays in the heap area\r\n\t\tif (!(x&3) && x > (uint32)_code_end /*&& x < (uint32)_std_mem_end*/) // don't check for end now, as we have some debug heaps up there we want to include\r\n\t\t{\r\n\t\t\t// check to see if it points to one of the heap members\r\n\t\t\t\r\n\t\t\tuint32 *p_refs = (uint32*)_mem_dump_start;\r\n\t\t\t\r\n\t\t#if 0\r\n\t\t\tfor (int i=0;i<num_used;i++)\r\n\t\t\t{\r\n\t\t\t\tif (*p_refs == x)\t  \t\r\n\t\t\t\t{\r\n\t\t\t\t\t// got it, increment the reference counter\r\n\t\t\t\t\tp_refs[1]++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tp_refs+=2;\r\n\t\t\t} \r\n\t\t\t\r\n\t\t#else\r\n\t\t\r\n\t\t\t// we want to do it twice, once for x, and once for x+16\r\n\t\t\t// the reason being, a class this is allocated with\r\n\t\t\t// the [] operator will actually start 16 bytes before the ref\r\n\t\t\t// so we need to go back 16 bytes when looking for the block\r\n\r\n\t\t\tint oldx = x;\r\n\t\t\tfor (int i=0;i<2;i++)\r\n\t\t\t{\r\n\t\t\t\r\n\t\t\t\t// binary search folks.....\r\n\t\t\t\tint low = 0;\r\n\t\t\t\tint high = num_used-1;\r\n\t\t\t\twhile (1)\r\n\t\t\t\t{\r\n\t\t\t\t\tint mid = (low + high) /2;\r\n\t\t\t\t\tif (p_refs[mid<<1] == x)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_refs[(mid<<1)+1] ++;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (high == low)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (p_refs[mid<<1] > x)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\thigh = mid;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// if the low point is already the same as the mid point\r\n\t\t\t\t\t\t// then the only way to go is up!\r\n\t\t\t\t\t\t// as this will only occur when low + 1 == high\r\n\t\t\t\t\t\tif (low == mid)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tlow = high;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tlow = mid;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tx -= 16;\r\n\t\t\t}\r\n\t\t\tx = oldx;\r\n\t\t#endif\t\t\t\t\t\t  \t\t\r\n\t\t}\r\n\t}\r\n\t\r\n\t\r\n}\r\n#endif\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__\r\nstatic uint32 *p_used;\t\t\r\n#endif\r\n\r\nint MemView_CountBlocks(Mem::Allocator::BlockHeader *p_header)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\tint num_used = 0;\r\n\twhile ( p_header )\r\n\t{\r\n\t\tvoid * p_start = (void*)((uint)p_header + Mem::Allocator::BlockHeader::sSize);\r\n\t\t\r\n\t\t*p_used++ = (uint32)p_start;\t \t\t// store the start of the block\r\n\t\t*p_used++ = 0;\t\t\t\t\t\t\t// store a count\r\n\t\tp_header = p_header->mp_next_used;\r\n\t\tnum_used++;\r\n\t}\r\n\treturn num_used;\r\n#else\r\n\treturn 0;\r\n#endif\r\n}\r\n\r\n\r\nint blockCompFunc( const void *arg1, const void *arg2 )\r\n{\r\n\tuint32 addr1 = (*(uint32*)arg1);\r\n\tuint32 addr2 = (*(uint32*)arg2);\r\n\r\n\tif ( addr1 == addr2 )\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\telse if ( addr1 < addr2 )\r\n\t{\r\n\t\treturn 1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn -1;\r\n\t}\r\n\r\n}\r\n\r\n\r\n// Find memory leaks\r\n// the algorithm is quite simple:\r\n// 1) Make a list of all \"used\" memory blocks, and set their usage count to 0\r\n// 2) Scan all of the heap, and the stack, for each word that looks like a pointer, \r\n//    check to see if it is in the list of \"used\", and increment the usage count if so\r\n// 3) Scan the list of used pointers, and check for any with usage == 0\r\n\r\nvoid MemView_FindLeaks()\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\t\tp_used  =  (uint32*)_mem_dump_start;\t\t\r\n\t\tnum_used = 0;\r\n\t\tprintf (\"Counting blocks....\");\t\t\r\n  \t\tMem::Heap * p_heap = Mem::Manager::sHandle().FirstHeap();\r\n\t\twhile (p_heap)\r\n\t\t{\r\n\t\t\tnum_used += MemView_CountBlocks(p_heap->first_block()); \r\n\t\t\tp_heap = Mem::Manager::sHandle().NextHeap(p_heap);\r\n\t\t}\r\n\r\n\t\tprintf (\" %d\\n\",num_used);\r\n\t\tprintf (\"Sorting .....\\n\");\t\t\t\r\n\t\t// Now we've done that, let's sort the list, so we can use a binary search later\r\n\t\t\r\n\t\t\r\n\t\t#if 1\r\n\t\tuint32 *p_top  =  (uint32*)_mem_dump_start;\t\t\r\n\t\tfor\t(int i = 0;i<num_used-1;i++)\r\n\t\t{\r\n\t\t\tuint32 top = *p_top;\r\n\t\t\tuint32 *p_scan  =  p_top+2;\t  \r\n\t\t\tuint32 *p_best = p_top;  \t\t\t\r\n\t\t\tfor (int j = i;j<num_used-1;j++)\r\n\t\t\t{\r\n\t\t\t\tuint32 scan = *p_scan;\r\n\t\t\t\tif (scan < top)\r\n\t\t\t\t{\r\n\t\t\t\t\ttop = scan;\r\n\t\t\t\t\tp_best = p_scan;\r\n\t\t\t\t}\r\n\t\t\t\tp_scan+=2;\r\n\t\t\t}\r\n\t\t\tuint64 t = *(uint64*)p_top;\r\n\t\t\t*(uint64*)p_top = *(uint64*)p_best;\r\n\t\t\t*(uint64*)p_best = t;\t\t\r\n\t\t\tp_top +=2;\r\n\t\t}\r\n\t\t#else\r\n\r\n\t\t// Use a quicksort\r\n\t\t// (NOT WORKING)\r\n\t\tqsort( (uint32*)_mem_dump_start, num_used, 8, blockCompFunc );\r\n\t\t\r\n\t\t#endif\r\n\r\n\r\n\r\n\t\t// now scan all appropiate regions of memory\r\n\t\t\r\n\t\t// First scan the code, data and regular heap\r\n\t\tScanRegion((uint32*)_code_end,(uint32*)_std_mem_end);\r\n\t\t\r\n\t\t// now scan the debug heap, as that is where the internet heap goes\r\n\t\tScanRegion((uint32*)(_debug_heap_start)  , (uint32*)(_debug_heap_start+DEBUG_HEAP_SIZE));\r\n\r\n\t\t// Next scan the alternate area or memory, where the script heap goes\r\n\t\t//ScanRegion((uint32*)(_rwheapdebug_start),(uint32*)(_rwheapdebug_start + 0x04970000 - 0x04500000));\r\n\t\tScanRegion((uint32*)(_script_heap_start),(uint32*)(_script_heap_start + 4500000)); // note, 4500K is bigger than actual script region\r\n\t\t// then scan the stack\r\n\t\tuint64* sp;\t\t\t\t\t\t\t\t\t\t\t// frame pointer\r\n\t\tasm ( \"daddu %0, $29, $0\" : \"=r\" (sp) );\t\t\t// get current sp\r\n\t\tuint32 *stack_start = (uint32*)sp;\r\n\t\t// stack end is stack start rounded up by the stack size\r\n\t\t// assumes that things are nice powers of 2\r\n\t\tuint32 *stack_end = (uint32*)(((int)(stack_start) + (int)_stack_size-4) & ~(int)(_stack_size-1));\r\n\t\tScanRegion(stack_start,stack_end);\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\t\tbool\tLeaksFound = false;\r\n\r\n\t\t// then check for any with zero reference\r\n\t\tuint32 *p_refs = (uint32*)_mem_dump_start;\r\n\t\tfor (int i=0;i<num_used;i++)\r\n\t\t{\r\n\t\t\tif (!p_refs[1])\t  \t\r\n\t\t\t{\r\n\t\t\t\tuint32 addr = *p_refs;\r\n\t\t\t\tif (!LeaksFound)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf (\"-----------------------------------------------------------------------\\n\");\r\n\t\t\t\t\tprintf (\"-----------  LEAKS FOUND !!!!!!!!!!!!!!           ---------------------\\n\");\r\n\t\t\t\t\tprintf (\"-----------------------------------------------------------------------\\n\");\r\n\t\t\t\t\tLeaksFound = true;\r\n\t\t\t\t}\r\n\t\t\t\tprintf (\"\\nPossible leak, addr %p\\n\",(void*)addr);\t\t\t\t\r\n\t\t\t\tMemView_DumpBlockInfo(addr);\r\n\t\t\t}\r\n\t\t\tp_refs+=2;\r\n\t\t}\t\t\t\r\n\t\t\r\n\t\tif (LeaksFound)\r\n\t\t{\r\n\t\t\tprintf (\"-----------------------------------------------------------------------\\n\");\r\n\t\t\tprintf (\"-----------  END OF LEAKS                         ---------------------\\n\");\r\n\t\t\tprintf (\"-----------------------------------------------------------------------\\n\");\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tprintf (\"-----------  NO LEAKS DETECTED!!!  ---------------------\\n\");\r\n\t\t}\r\n#endif\r\n}\r\n\r\n\r\n// Given a block addr, then search all the other blocks to see \r\n// which block contains a reference to this block\r\n// and recursivly step back through the blocks until\r\n// we can't find another reference, or the address is not in a block\r\nvoid MemView_DumpRefs(int addr)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\tprintf (\"\\n\\nDumping references for %p\\n\",(void*)addr);\r\n\tMemView_DumpBlockInfo(addr);\r\n\tuint32 *p_first = NULL;\t\r\n\tint last_addr = 0;\r\n\tint count = 0 ;\r\n\twhile (1)\r\n\t{\r\n\t\t// now just do a simple search through the heap reagion\r\n\t\t// to find another reference\r\n\t\tuint32 *p_start = (uint32*)_code_end;\r\n\t\tuint32 *p_end = (uint32*)_std_mem_end;\r\n\t\twhile (p_start<p_end && count < 10)\r\n\t\t{\r\n\t\t\tif (*p_start == (uint32)addr && p_start != (uint32*)&blockstart)\r\n\t\t\t{\r\n\t\t\t\tcount++;\r\n\t\t\t\tprintf (\"\\nReference level %d in %p\\n\",count,(void*)p_start);\r\n\t\t\t\tMemView_DumpBlockInfo((int)p_start);\r\n\t\t\t\taddr = (int)p_start;\r\n\r\n\r\n\t\t\t\tMem::Allocator::BlockHeader *pBlock = MemView_FindBlock(addr);\t\t\t\t\r\n\t\t\t\taddr = (int)((uint)pBlock + Mem::Allocator::BlockHeader::sSize);\r\n\t\t\t\tif (addr == (int) p_first || addr == last_addr)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf (\"LOOPING .....\\n\");\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tlast_addr = addr;\r\n\t\t\t\tif (!p_first)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_first = (uint32*)addr;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\tp_start++;\r\n\t\t}\r\n\t\tif (count >= 10)\r\n\t\t{\r\n\t\t\tprintf (\"Stopping after %d refs\\n\",count);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (p_start >= p_end)\r\n\t\t{\r\n\t\t\tprintf (\"No more References Found in heap \\n\");\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\n// Find the first block in the free list\r\n// if no free blocks, then return\r\n// scan all used blocks, and print out the info for all the blocks\r\n// that have an address above the first free block\r\nvoid MemView_DumpFragments(Mem::Heap *pHeap)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t#ifdef\t__LINKED_LIST_HEAP__    \r\n\r\n\tif (!pHeap->mFreeBlocks.m_count)\r\n\t{\r\n\t\tprintf (\"NO Fragmentation\\n\");\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif (!pHeap->mp_context->mp_free_list)\r\n\t{\r\n\t\tprintf (\"!!!!!! No free list, but there are %d free blocks???\\n\",pHeap->mFreeBlocks.m_count);\r\n\t\treturn;\r\n\t}\r\n\r\n\tMem::Allocator::BlockHeader *p_free = pHeap->mp_context->mp_free_list;\r\n\t\r\n\twhile (p_free->mSize < 10000)\r\n\t{\r\n\t\tMem::Allocator::BlockHeader *p_next = p_free->mpNext;\r\n\t\tif (!p_next)\r\n\t\t{\r\n\t\t\tprintf (\"Did not find a free block >10K ?????\\n\");\r\n\t\t\treturn;\r\n\t\t}\t\t\r\n\t\tp_free = p_next;\r\n\t}\r\n\t\r\n\tMem::Allocator::BlockHeader *p_full = pHeap->mp_context->mp_used_list;\r\n\t\r\n\tprintf (\"!!!!!! Free list starts at %p\\n\",p_free);\r\n\t\r\n\r\n\t// The first p_free will be the start of fragmentations\r\n\twhile (p_full)\r\n\t{\r\n\t\tif (p_full > p_free)\r\n\t\t{\r\n\t\t\tprintf (\"\\nFramgented Block\\n\\n\");\r\n\t\t\tvoid * p_start = (void*)((uint)p_full + Mem::Allocator::BlockHeader::sSize);\r\n\t\t\tMemView_DumpBlockInfo((int)p_start);\r\n\t\t\tfor (int xx=0;xx<1000000;xx++);\t\t// little delay, to allow printfs to work\r\n\t\t}\r\n\t\tp_full = p_full->mp_next_used;\r\n\t}\r\n\t#endif\r\n}\r\n\r\nvoid MemView_DumpHeap(Mem::Heap *pHeap, uint32 mask)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t#ifdef\t__LINKED_LIST_HEAP__    \r\n\r\n//\tMem::Allocator::BlockHeader *p_free = pHeap->mp_context->mp_free_list;\r\n\tMem::Allocator::BlockHeader *p_full = pHeap->mp_context->mp_used_list;\r\n\t\r\n\t// The first p_free will be the start of fragmentations\r\n\twhile (p_full)\r\n\t{\r\n//\t\tif (p_full > p_free)\r\n//\t\tCCallStack *c = (CCallStack*)p_full->mp_debug_data;\t\r\n//\t\tif (!mask || !c || !(c->flags && mask))\r\n\t\t{\r\n\t\t\tprintf (\"\\n\");\r\n\t\t\tvoid * p_start = (void*)((uint)p_full + Mem::Allocator::BlockHeader::sSize);\r\n\t\t\tMemView_DumpBlockInfo((int)p_start);\r\n\t\t}\r\n\t\tp_full = p_full->mp_next_used;\r\n\t}\r\n\t#endif\r\n}\r\n\r\n\r\n\r\nvoid MemView_DumpBottomFragments()\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tMemView_DumpFragments(Mem::Manager::sHandle().BottomUpHeap());\r\n}\r\n\r\nvoid MemView_DumpTopFragments()\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tMemView_DumpFragments(Mem::Manager::sHandle().TopDownHeap());\r\n}\r\n\r\n\r\n\r\n/*\r\nclass CCallStack\r\n{\r\npublic:\r\n\tvoid Append(CCallStack *p);\r\n\tvoid Remove();\r\n\tvoid InitHead();\r\n\tint\tused;\r\n\tint\tsize;\r\n\tCCallStack *pNext;\r\n\tCCallStack *pPrev;\r\n\tint\taddr[STACKDEPTH];\r\n\r\n};\r\n*/\r\n\r\nstruct SBlockType\r\n{\r\n\tint\treturn_addr; \t\t\t// first meaningful return addr \r\n\t\r\n\tint\tsize;\t\t\t\t\t// size of block (if we want to sort by it\r\n\tint\ttotal;\t\t\t\t\t// total size of this type\r\n\tint\tactual;\t\t\t\t\t// actual total size, including headers\r\n\tchar *p_class;\t\t\t\t// points to class node \r\n\t\r\n\tint\tcount;\r\n};\r\n\r\n// scan throught the list of \"used\" blocks\r\n// and sort them into a list, organized by \"type\"\r\n// the \"type\" is determined by the first return address after\r\n// a callstack entry that is either \"Malloc\" or \"Spt::Class::operator new\"\r\n// the \"type\" is furthur sorted by either \"size\" or \"Class\"\r\n// where \"size\" is the size of the block (for a Malloc)\r\n// and \"Class\" is the type of class that constructed this block \r\n\r\n#define\tMAX_TYPES 10000\r\n\r\n\r\nvoid MemView_DumpAnalysis( SBlockType* blocks, int numBlocksToPrint )\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\t// Sorts the types, and print out totals\r\n\r\n\tint temp;\r\n\r\n\tfor (int i = 0; i < numBlocksToPrint; i++)\r\n\t{\r\n\t\tfor (int j = i+1;j<numBlocksToPrint;j++)\r\n\t\t{\r\n\t\t\tbool swap = false;\r\n\t\t\tif (blocks[i].actual < blocks[j].actual)\r\n\t\t\t{\r\n\t\t\t\tswap = true;\r\n\t\t\t}\r\n\r\n\t\t\tif (swap)\r\n\t\t\t{\r\n\t\t\t\tSBlockType t = blocks[i];\r\n\t\t\t\tblocks[i] = blocks[j];\r\n\t\t\t\tblocks[j] = t;\t\t\t\t\r\n\t\t\t}\t\t\t\r\n\t\t}\r\n\r\n\t\t// i is sorted, so print it out\r\n\t\tprintf (\"%7d bytes, (%6d hdrs) %4d blks, avg %6d bytes, class %s, function %s\\n\", \t\t\r\n\t\t\t\tblocks[i].actual,\r\n\t\t\t\tblocks[i].actual-blocks[i].total,\r\n\t\t\t\tblocks[i].count,\t\t\t\t \r\n\t\t\t\tblocks[i].total/blocks[i].count,\r\n\t\t\t\tblocks[i].p_class,\r\n\t\t\t\tMemView_GetFunctionName(blocks[i].return_addr,&temp)\r\n\t\t\t   );\t   \r\n\t\tfor (int xx=0;xx<2000000;xx++);\t\t// little delay, to allow printfs to work\r\n\t}\r\n#endif\r\n}\r\n\r\nvoid MemView_AnalyzeCallStack( CCallStack* pCallStack, SBlockType* pBlocks, int& num )\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// for each block we find the three things:\r\n\t//  return_addr after Malloc or Spt::Class::operator new\r\n\t//  size\r\n\t//  class\r\n\r\n\tint\tsize = pCallStack->size;\t  \t// size is the only thing we know for sure\r\n\tint\treturn_addr = 0;\t\t\t\t// default unknown return address\r\n\tchar *p_class = \"not a class\";\r\n\tint latest = 1;\r\n\tint i = 0;\r\n\t\r\n\tfor ( i = 1; i < 8; i++ )\r\n\t{\r\n\t\tint xsize;\r\n\r\n\t\t/*\r\n\t\t// the types of call stack we may encounter:\r\n\t\t// need to \r\n\t\t\t0x10be48: Mem::Heap::allocate                                                   \r\n\t\t\t0x109914: Mem::Manager::New                                                     \r\n\t\t\t0x1035b0: Spt::Class::operator new                                              \r\n\t\t\t0x161094: Front::KeyboardControl::sCreateInstance   \r\n\r\n\t\t*/\r\n\r\n\t\tchar *p_name = MemView_GetFunctionName(pCallStack->addr[i],&xsize);\r\n\t\tif (!strcmp(\"Malloc\",p_name) \r\n\t\t\t|| !strcmp(\"Spt::Class::operator new\",p_name)\r\n\t\t\t|| !strcmp(\"Mem::Manager::New\",p_name)\r\n\t\t\t|| !strcmp(\"Mem::AllocRegion::AllocRegion\",p_name)\r\n\t\t\t|| !strcmp(\"ReallocateShrink\",p_name)\r\n\t\t\t|| !strcmp(\"Mem::Manager::ReallocateShrink\",p_name)\r\n\t\t\t|| !strcmp(\"ReallocateDown\",p_name)\r\n\t\t\t|| !strcmp(\"Pip::Load\",p_name)\r\n\t\t\t|| !strcmp(\"Pip::LoadPre\",p_name)\r\n\t\t\t|| !strcmp(\"Calloc\",p_name)\r\n\t\t\t\r\n\t\t\t)\r\n\t\t{\r\n\t\t\tlatest = i;\r\n\t\t}\r\n\t}\r\n\r\n\tif (latest != 1)\r\n\t{\r\n\t\treturn_addr = pCallStack->addr[latest+1];\r\n\t}\r\n\r\n\tp_class = MemView_GetClassName(pCallStack);\t\t\t\t// get class\r\n\t// right, now we have all the info on this block\r\n\t// let's see if we've got one just like it\r\n\r\n\t//\t\tif (!p_class && !MemView_GetFunctionName(return_addr,&temp))\r\n\t/*\t\t\r\n\t\t\tif (!return_addr)\r\n\t\t\t{\r\n\t\t\t\tfor (int i = 0;i<STACKDEPTH;i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf (\"%2d: >>%s<<\\n\",i,MemView_GetFunctionName(p->addr[i],&temp));\r\n\r\n\t\t\t\t}\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\t*/\r\n\t\r\n\t\t\t\t\t\t\t\t\t  \r\n\t// check if it is a string, and print it out, if so\t\t\t\t\t\r\n\r\n\t\r\n\tint temp;\t\t\t\t  \r\n\tif (!strcmp(\"Str::String::copy\",MemView_GetFunctionName(return_addr,&temp)))\r\n\t{\r\n\t\tprintf (\"Str::String   <%s>\\n\",(char*)((char*)(pCallStack->pBlock)+32)); \r\n\t\tmem_strings++;\r\n\t}\t\r\n\telse if (!strcmp(\"Script::CreateString\",MemView_GetFunctionName(return_addr,&temp)))\r\n\t{\r\n\t\tprintf (\"Script String <%s>\\n\",(char*)((char*)(pCallStack->pBlock)+32)); \r\n\t\tmem_strings++;\r\n\t}\r\n\r\n\t\r\n\t\r\n\r\n\t// Analyze the contents of the block\r\n\t// counting zero, and unused (0x555555) words\r\n//\tuint32 *p\r\n\r\n\r\n\tint dummy;\r\n\t// check to see if this block is already included\r\n\tfor ( i = 0; i < num; i++ )\r\n\t{\r\n\t\t//int diff = pBlocks[i].return_addr - \r\n\t\tif ( /* pBlocks[i].p_class == p_class*/\r\n\t\t\t /*&& pBlocks[i].size == size */\r\n\t\t\t /*&& pBlocks[i].return_addr == return_addr*/\r\n\t\t\t // just check if allocated by the same function\r\n\t\t\t \r\n\t\t\t MemView_GetFunctionName(pBlocks[i].return_addr,&dummy) == MemView_GetFunctionName(return_addr,&dummy)\r\n\t\t\t  \r\n\t\t\t  )\r\n\t\t{\r\n\t\t\tpBlocks[i].count++;\r\n\t\t\tpBlocks[i].total += size;\r\n\t\t\tpBlocks[i].actual += size + Mem::Allocator::BlockHeader::sSize;\r\n\t\t\tbreak;\t\t\t\t\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (return_addr == NULL)\r\n\t{\r\n\t\t\r\n\t\tprintf (\"\\nUntraceable Block\");   \t\r\n\t\tMemView_DumpBlockInfo(((int)(pCallStack->pBlock)+32));\t\r\n\t}\r\n\t\r\n\r\n\t// if not, then add the block\r\n\tif ( i == num )\r\n\t{\r\n\t\tpBlocks[i].p_class = p_class;\r\n\t\tpBlocks[i].size = size;\r\n\t\tpBlocks[i].total = size;\r\n\t\tpBlocks[i].actual = size + Mem::Allocator::BlockHeader::sSize;\r\n\t\tpBlocks[i].return_addr = return_addr;\r\n\t\tpBlocks[i].count = 1;\r\n\t\tnum++;\r\n\t}\r\n}\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__\r\nstatic int bbb = 0;\t   \t// compiler patch var, see below\r\n#endif\r\n\r\nvoid MemView_AnalyzeBlocks(uint32 mask)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\tSBlockType  *pBlocks = (SBlockType  *)_mem_dump_start;\t// temp memory\r\n\tint\tnum_blocks = 0;\r\n\tint num = 0;\r\n\r\n\tprintf (\"\\nAnalyzing blocks....\\n\");\r\n\t\r\n\tmem_strings = 0;\r\n\t\t\t\t\t\r\n\tCCallStack *p = used_list.pNext;  \r\n\twhile (p != &used_list)\r\n\t{\r\n\t\t// Get the actualy block we referred to\r\n//\t\tMem::Allocator::BlockHeader * pBlock = p->pBlock;\r\n//\t\tvoid * p_start = (void*)((uint)pBlock + Mem::Allocator::BlockHeader::sSize);\r\n\t\t// Otionally check to see if it on the front end heap\r\n//\t\tif (Mem::SameContext(p_start,Mem::Manager::sHandle().FrontEndHeap()))\r\n\t\t{\r\n\t\t\tif (!mask || !(p->flags & mask))\r\n\t\t\t{\r\n\t\t\t\tMemView_AnalyzeCallStack( p, pBlocks, num );\t\t\t\r\n\t\t\t\tnum_blocks++;\r\n\t\t\t}\r\n\t\t}\r\n\t\tp = p->pNext; \r\n\t}\r\n\tprintf(\"\\n  THERE ARE %d STRINGS (above) \\n\\n\",mem_strings);\r\n\t\r\n\t\r\n\tprintf (\"%d types, in %d total blocks\\n\", num, num_blocks); \r\n\r\n\tMemView_DumpAnalysis( pBlocks, num );\r\n\tif (bbb)\r\n\t{\r\n\t\tMemView_DumpBottomFragments();\t\t\t// just to get it compiling \r\n\t\tMemView_DumpTopFragments();\t\t\t// just to get it compiling \r\n\t}\t\t\r\n#endif\r\n}\r\n\r\n\r\nvoid MemView_MarkBlocks(uint32 mask)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\r\n\tCCallStack *p = used_list.pNext;  \r\n\twhile (p != &used_list)\r\n\t{\r\n\t\tp->flags |= mask;\r\n\t\t\r\n\t\tp = p->pNext;\r\n\t}\r\n#endif\r\n}\r\n\r\n\r\n\r\nvoid MemView_Input(uint buttons, uint makes, uint breaks)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\r\n//\tif (makes & Inp::Data::mD_TRIANGLE)\r\n//\t{\r\n//\t\tMemView_Active = !MemView_Active;\r\n//\t}\r\n\r\n\r\n\tif (!MemView_Active)\r\n\t{\r\n\t\t// Stupid hook up of scaling buttons for overhead view\r\n\r\n\t\t#ifdef\t__DEBUG_CODE__  \t\r\n\t\tif (buttons & Inp::Data::mD_CIRCLE)\r\n\t\t\tNx::_debug_change_2d_scale(1.11);\r\n\t\tif (buttons & Inp::Data::mD_SQUARE)\r\n\t\t\tNx::_debug_change_2d_scale(0.9);\r\n\t\t#endif\t\t\r\n\t\r\n\t\r\n\t\r\n\t\treturn;\r\n\t}\r\n\r\n\t\t\t\t\t  \r\n\tfloat step1 = step;\r\n\t\r\n\tfloat zoom = 1.1f;\r\n\t\r\n\tfloat scroll = 4.0f;\r\n\r\n\t\r\n\r\n\r\n\r\n\tif (buttons & Inp::Data::mD_LEFT)\r\n\t{\r\n\t\tstep1 = step * zoom;\r\n\t}\r\n\tif (buttons & Inp::Data::mD_RIGHT)\r\n\t{\r\n\t\tstep1 = step / zoom;\r\n\t}\r\n\t\r\n\tif (buttons & Inp::Data::mD_UP)\r\n\t{\r\n//\t\tstart = start - scroll * 512.0f * 2.0f * step;\r\n\t\tcursor = cursor - scroll * 512.0f * 2.0f * step;\r\n\t}\r\n\tif (buttons & Inp::Data::mD_DOWN)\r\n\t{\r\n//\t\tstart = start + scroll * 512.0f * 2.0f * step;\r\n\t\tcursor = cursor + scroll * 512.0f * 2.0f * step;\r\n\t}\r\n\r\n\tif (buttons & Inp::Data::mD_L1)\r\n\t{\r\n//\t\tstart = start - scroll * 512.0f * 2.0f * step / 256.0f;\r\n\t\tcursor = cursor - scroll * 2.0f * 2.0f * step;\r\n\t}\r\n\tif (buttons & Inp::Data::mD_L2)\r\n\t{\r\n//\t\tstart = start + scroll * 512.0f * 2.0f * step / 256.0f;\r\n\t\tcursor = cursor + scroll * 2.0f * 2.0f * step;\r\n\t}\r\n\r\n#define \tMMMIN \t(0.0078125f)\r\n\t \t\t\t\t\r\n\tif (step1 <MMMIN)\r\n\t{\r\n\t\tstep1 = MMMIN;\r\n\t}\r\n\t\r\n\tif (step1>1024.0f)\r\n\t{\r\n\t\tstep1 = 1024.0f;\r\n\t}\r\n\r\n//\tstart = start + (512.0f * 2.0f * 128.0f * (step - step1));\r\n\r\n\tstep = step1;\r\n\r\n\tif (makes & Inp::Data::mD_CIRCLE)\r\n\t{\r\n\t\tif (blockstart)\r\n\t\t{\r\n\t\t\tMemView_DumpRefs(blockstart);\r\n\t\t}\r\n//\t\tMemView_MarkBlocks(1);\r\n\t}\r\n\r\n\t// We don't look for leaks automatically now, so I'v put it on \"SQUARE\"\t\r\n\tif (makes & Inp::Data::mD_SQUARE)\r\n\t{\r\n\t\tMemView_FindLeaks();\r\n//\tMem::Manager& mem_man = Mem::Manager::sHandle();\t\tMemView_DumpHeap(1);\r\n//\theap\t= mem_man.TopDownHeap();\r\n//\tMemView_DumpFragments(heap);\r\n//\tMemView_DumpHeap(heap,1);\r\n\r\n\t}\r\n\r\n\tif (makes & Inp::Data::mD_X)\r\n\t{\r\n//\t\tMemView_AnalyzeBlocks();\r\n\t}\r\n\r\n\t// Triangle = Dump Fragmentation\r\n/*\tif (makes & Inp::Data::mD_TRIANGLE)\r\n\t{\r\n\t\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\t\tMem::Heap* heap = mem_man.BottomUpHeap();\r\n\t\tMem::Region* region = heap->ParentRegion();\r\n\t\tprintf (\"BottomUp Frag %dK, %d Blocks\\n\",heap->mFreeMem.m_count / 1024, heap->mFreeBlocks.m_count);\r\n\t\tprintf (\"Region %d/%d K\", region->MemAvailable() / 1024, region->TotalSize() / 1024 );\r\n\t\tMemView_DumpFragments(heap);\r\n\t}\r\n*/\t\r\n\r\n}\r\n\r\nvoid MemView_AnalyzeHeap(Mem::Heap *pHeap)\r\n{\r\n\tif (!Config::GotExtraMemory())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif ( !pHeap )\r\n\t\treturn;\r\n\t\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\tSBlockType  *pBlocks = (SBlockType  *)_mem_dump_start;\t// temp memory\r\n\tint\tnum_blocks = 0;\r\n\tint num = 0;\r\n\r\n\tMem::Allocator::BlockHeader *p_full = pHeap->mp_context->mp_used_list;\r\n\r\n\twhile (p_full)\r\n\t{\r\n\t\tCCallStack* pCallStack = (CCallStack*)p_full->mp_debug_data;\r\n\t\t\r\n\t\tif ( pCallStack )\r\n\t\t{\r\n\t\t\tMemView_AnalyzeCallStack( pCallStack, pBlocks, num );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tprintf (\"Block with No Debug Info!!\\n\");\r\n\t\t}\r\n\r\n\t\tp_full = p_full->mp_next_used;\r\n\t}\r\n\tprintf(\"\\n  THERE ARE %d STRINGS (above) \\n\\n\",mem_strings);\r\n\r\n\tprintf (\"%d types, in %d total blocks\\n\", num, num_blocks); \r\n\t\r\n\tMemView_DumpAnalysis( pBlocks, num );\r\n#endif\r\n}\r\n  \r\n  \r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_memview.h",
    "content": "////\r\n\r\n#ifndef\t__P_MEMVIEW_H__\r\n#define\t__P_MEMVIEW_H__\r\n\r\nvoid MemView_Display();\r\nvoid MemView_Input(uint buttons, uint makes, uint breaks);\r\nvoid MemView_Alloc( void *v);\r\nvoid MemView_Free( void *v);\r\nvoid MemViewToggle();\r\nvoid MemView_FindLeaks();\r\nint DumpUnwindStack( int iMaxDepth, int *pDest );\r\nchar *MemView_GetFunctionName(int pc, int *p_size);\r\nvoid MemView_DumpFragments(Mem::Heap *pHeap);\r\nvoid MemView_AnalyzeBlocks(uint32 mask = 0);\r\nvoid MemView_MarkBlocks(uint32 flags = 1 );\r\nvoid MemView_DumpHeap(Mem::Heap *pHeap, uint32 mask =0);\r\nvoid MemView_AnalyzeHeap(Mem::Heap *pHeap);\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nx.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_nx.cpp - PS2 platform specific interface to the engine\r\n//\r\n// This is PS2 SPECIFIC!!!!!!  So might get a bit messy\r\n//\r\n// If there is anything in here that is not PS2 specific, then it needs to \r\n// be in nx.cpp\r\n\r\n#include\t\"gfx\\nx.h\"\r\n#include\t\"gfx\\NxViewMan.h\"\r\n#include\t\"gfx\\NxMiscFX.h\"\r\n#include\t\"gfx\\NxParticleMgr.h\"\r\n#include\t\"gfx\\NxQuickAnim.h\"\r\n#include\t\"gfx\\NGPS\\p_NxGeom.h\"\r\n#include\t\"gfx\\NGPS\\p_NxLightMan.h\"\r\n#include\t\"gfx\\NGPS\\p_NxMesh.h\"\r\n#include\t\"gfx\\NGPS\\p_NxModel.h\"\r\n#include\t\"gfx\\NGPS\\p_NxSector.h\"\r\n#include\t\"gfx\\NGPS\\p_NxScene.h\"\r\n#include\t\"gfx\\NGPS\\p_NxSprite.h\"\r\n#include\t\"gfx\\NGPS\\p_NxTexture.h\"\r\n#include\t\"gfx\\NGPS\\p_NxTextured3dPoly.h\"\r\n#include\t\"gfx\\NGPS\\p_NxNewParticleMgr.h\"\r\n#include\t\"core\\math.h\"\r\n#include    \"gel\\collision\\collision.h\"\r\n\r\n#include \t\"gfx\\ngps\\nx\\nx_init.h\"\r\n#include \t\"gfx\\ngps\\nx\\material.h\"\r\n#include \t\"gfx\\ngps\\nx\\mesh.h\"\r\n#include \t\"gfx\\ngps\\nx\\occlude.h\"\r\n#include \t\"gfx\\ngps\\nx\\scene.h\"\r\n#include \t\"gfx\\ngps\\nx\\chars.h\"\r\n#include \t\"gfx\\ngps\\nx\\render.h\"\r\n#include \t\"gfx\\ngps\\nx\\geomnode.h\"\r\n#include \t\"gfx\\ngps\\nx\\immediate.h\"\r\n#include \t\"gfx\\ngps\\p_nxweather.h\"\r\n#include \t\"gfx\\ngps\\nx\\switches.h\"\r\n\r\n#include <gfx/camera.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/pip.h>\r\n#include <gel/components/collisioncomponent.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/object/compositeobject.h>\r\n\r\nnamespace NxPs2\r\n{\r\nextern void\ttest_render_start_frame();\r\nextern void\ttest_render(Mth::Matrix* camera_orient, Mth::Vector* camera_pos,  float view_angle, float screen_aspect);\r\nextern void\ttest_render_end_frame();\r\nextern void\ttest_init();\t\t\t\r\nextern bool IsVisible(Mth::Vector &center, float radius);\r\nextern void\tWaitForRendering();\r\nextern uint32\t*p_patch_ALPHA;\r\nextern uint32\t*p_patch_ALPHA2;\r\n} // namespace NxPs2\r\n\r\n\r\nnamespace\tNx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCEngine::s_plat_start_engine()\r\n{\r\n\tNxPs2::InitialiseEngine();\r\n\tmp_particle_manager = new CPs2NewParticleManager;\r\n\tNx::CPs2Texture::sInitTables();\r\n\tmp_weather = new CPs2Weather;\r\n}\r\n\r\n\r\nvoid \t\tCEngine::s_plat_pre_render()\r\n{\r\n// Moved to StuffAfterGSFinished\r\n//\tCPs2LightManager::sUpdateEngine();\r\n//\r\n//\t// particle systems effectively have their transform double-buffered for dma purposes\r\n//\t// so now is the time to do the buffer flip by updating the transforms\r\n//\tmp_particle_manager->UpdateParticles();\r\n\r\n\tNxPs2::test_render_start_frame();\r\n}\r\n\r\nvoid \t\tCEngine::s_plat_post_render()\r\n{\r\n\t// bit of a hack, see below\r\n//\tGfx::Camera *cur_camera = CViewportManager::sGetCamera( 0 );\r\n//\tif (cur_camera)\r\n\t{\r\n\r\n\t\t\r\n\t\t\r\n\t\tNxPs2::test_render_end_frame();\r\n\t}\r\n}\r\n\r\n//void shadow_test( float * p_sn, uint16 * p_index_list, int count, float * dir )\r\n//{\r\n//\t// Test...\r\n//\r\n//\tasm __volatile__(\r\n//\t\t\"\r\n//\t\t.set noreorder\r\n//\r\n//\t\tlqc2\tvf09, 0x0(%1)\t\t# light dir\r\n//\r\n//\t\tlqc2\tvf10, 0x0(%0)\t\t# surface normal\r\n//\t\taddi\t%2, %2, -1\r\n//\r\n//dot_loop:\r\n//\t\tvmul.xyz\tvf13,\tvf09,\tvf10\t# result = plane * center + plane_w [start]\r\n//\t\taddiu\t\t%0,\t\t%0,\t\t12\r\n//\t\tlqc2\t\tvf10,\t0x4(%0)\t\t\t# surface normal\r\n//\t\tvaddy.x\t\tvf13,\tvf13,\tvf13y\r\n//\t\tvaddz.x\t\tvf13,\tvf13,\tvf13z\r\n//\r\n//\t\tqmfc2\t\t$8,\t\tvf13\r\n//\t\tsw\t\t\t$8,\t\t0x0(%0)\r\n//\t\taddiu\t\t%0,\t\t%0,\t\t4\r\n//\r\n//\t\tbne\t\t\t%2,\t\t$0,\t\tdot_loop\r\n//\t\taddi\t\t%2,\t\t%2,\t\t-1\r\n//done:\r\n//\r\n//\t\t.set reorder\r\n//\t\t\": : \"r\" (p_sn), \"r\" (dir), \"r\" (count) : \"$8\" ); \r\n////\r\n////\t\t\": \"=r\" (p_dot) : \"r\" (p_sn) : \"$8\", \"$9\", \"$10\");\r\n//\t\r\n//\r\n////#\t\tlhu\t\t$8, 0(%2)\r\n////#\t\tlhu\t\t$9, 2(%2)\r\n////#\t\tlhu\t\t$10, 4(%2)\r\n////#\t\taddiu\t%2, %2, 6\r\n////#\r\n////#\t\tadd\t\t$8, $8, %1\r\n////#\t\tadd\t\t$9, $9, %1\r\n////#\t\tadd\t\t$10, $10, %1\r\n////#\t\tlqc2\tvf10, 0x0($8)\t\t# p0\r\n////#\t\tlqc2\tvf11, 0x0($8)\t\t# p1\r\n////#\t\tlqc2\tvf12, 0x0($8)\t\t# p2\r\n//\r\n//}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCEngine::s_plat_render_world()\r\n{\r\n\tNxPs2::RenderPrologue();\t \t// should this be in test_render_start_frame? (Garrett: Answer is no, it won't work)\r\n\tNxPs2::RenderInitImmediateMode();\r\n\r\n\r\n//#define NUM_TRIS 1851\r\n////\tfloat\txyz[(NUM_TRIS+2)*3];\r\n//\tfloat\tsn[NUM_TRIS*4];\r\n//\tuint16\tlist[NUM_TRIS*3];\r\n//\tfloat\tvec[3] = { 1.0f, 1.5f, 2.0f };\r\n//\r\n//\tfor ( int lp = 0; lp < NUM_TRIS; lp++ )\r\n//\t{\r\n//\t\tsn[(lp*4)+0] = 6.0f;\r\n//\t\tsn[(lp*4)+1] = 7.0f;\r\n//\t\tsn[(lp*4)+2] = 8.0f;\r\n//\r\n////\t\txyz[(lp*3)+0] = ((float)(lp/2));\r\n////\t\txyz[(lp*3)+1] = ((float)(lp&1));\r\n////\t\txyz[(lp*3)+2] = 0.0f;\r\n//\r\n//\t\tlist[(lp*3)+0] = ( lp + 0 ) * 12;\r\n//\t\tlist[(lp*3)+1] = ( lp + 1 ) * 12;\r\n//\t\tlist[(lp*3)+2] = ( lp + 2 ) * 12;\r\n//\t}\r\n//\r\n//\tTmr::CPUCycles cycles = Tmr::GetTimeInCPUCycles();\r\n//\tshadow_test( sn, list, NUM_TRIS, vec );\r\n//\tcycles = Tmr::GetTimeInCPUCycles() - cycles;\r\n//\tprintf( \"CPU Cycles for shadow test: %d\\n\", cycles );\r\n\r\n\t#if 0\r\n\t// (Mike) see if there are any viewports to render, and return if there aren't\r\n\t// (Mike) ...perhaps make this trivial by having a CViewportManager::sGetNumActiveCameras() ?\r\n\tbool no_viewports = true;\r\n\tfor (int view_idx = 0; view_idx < CViewportManager::sGetNumActiveViewports(); view_idx++)\r\n\t{\r\n\t\tif (CViewportManager::sGetActiveViewport(view_idx)->GetCamera())\r\n\t\t{\r\n\t\t\tno_viewports = false;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif (no_viewports)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t// (Mike) now we know there's something to render...\r\n\t#endif\r\n\r\n\r\n/*\r\n\t#if 1\r\n\t// normal 4:3 TV\t\r\n\tfloat view_angle = 72.0f;   \t\t\t// The angle prepended by the width of the screen\r\n\tfloat screen_aspect = 4.0f/3.0f;\t\t// physical ration of width to height on the screen\t(4:3 or 16:9)\r\n\t#else \r\n\t// anamorphic widescreen\r\n\tfloat view_angle = 80.0f;   \t\t\t// The angle prepended by the width of the screen\r\n\tfloat screen_aspect = 16.0f/9.0f;\t// physical ratio of width to height on the screen\t(4:3 or 16:9)\r\n\t#endif\r\n*/\r\n//\tCViewportManager::sSetScreenMode(vSPLIT_V);\r\n\t\r\n\t\r\n\r\n\tbool got_vu0 = NxPs2::OccludeUseVU0();\r\n\tDbg_Assert(got_vu0);\r\n\t\r\n\t// Note: this method of setting up the camera must change\r\n\t// so that the p_nx module does not reference things higher up the hierarchy\r\n\tfor (int view_idx = 0; view_idx < CViewportManager::sGetNumActiveViewports(); view_idx++)\r\n\t{\r\n\t\tGfx::Camera *cur_camera;\r\n\t\tCViewport *p_cur_viewport = CViewportManager::sGetActiveViewport(view_idx);\r\n\t\t\r\n\t\tDbg_MsgAssert(p_cur_viewport,(\"Unable to get viewport %d\",view_idx));\r\n\t\tcur_camera = p_cur_viewport->GetCamera();\r\n\t\t\r\n\t\tif (cur_camera)\r\n\t\t{\r\n\t\t\t\r\n\t\t\t// Build the occluders first now that we know where the camera is for this frame.\r\n\t\t\tNxPs2::BuildOccluders( &( cur_camera->GetPos()));\r\n\r\n\t\t\t// Make camera matrix\r\n\t\t\tMth::Matrix cam_matrix(cur_camera->GetMatrix());\r\n\t\t\tcam_matrix[W] = cur_camera->GetPos();\r\n\r\n\t\t\t// Garrett: For some reason, only these clipping values work\r\n\t\t\tNxPs2::RenderViewport(view_idx, cam_matrix, p_cur_viewport->GetRect(), cur_camera->GetAdjustedHFOV(), p_cur_viewport->GetAspectRatio(),\r\n\t\t\t\t\t\t\t\t  /*-cur_camera->GetNearClipPlane(), -cur_camera->GetFarClipPlane()*/ -1.0f, -100000.0f, s_render_mode > 1);\r\n#\tifdef __USE_PROFILER__\r\n\t\t\tSys::CPUProfiler->PushContext( 0, 0, 255 );\t \t// Blue (Under Yellow) = Immediate mode rnedering\r\n#\tendif // __USE_PROFILER__\r\n\r\n\t\t\t// Draw the immediate mode stuff\r\n\t\t\tNxPs2::RenderSwitchImmediateMode();\r\n\t\t\tNxPs2::CImmediateMode::sViewportInit();\r\n\r\n// Mick: Moved this here from test_render_end_frame\r\n\t\t\tNxPs2::Reallocate2DVRAM();\r\n\r\n\t\t\tif (NxPs2::FlipCopyEnabled()) // TT 13470, 13471, 11061 Particle systems displayed when screen is blank\r\n\t\t\t{\r\n\t\t\t\r\n\t\t\t\tNx::render_particles();\r\n\t\t\t\tmp_particle_manager->RenderParticles();\r\n\t\r\n\t\t\t\t// Render Weather effects.\r\n\t\t\t\tmp_weather->Process( Tmr::FrameLength() );\r\n\t\t\t\tmp_weather->Render();\r\n\t\r\n\t\t\t\t//Nx::CTextured3dPoly::sRenderAll();\r\n\t\t\t\tTextureSplatRender();\r\n\t\t\t\tShatterRender();\t\t\t// Make sure this is always the last immediate draw since it switches DMA lists\r\n\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\tNxPs2::RenderSwitchImmediateMode();\r\n\r\n#\tifdef __USE_PROFILER__\r\n\t\t\tSys::CPUProfiler->PopContext(  );\t \r\n#\tendif // __USE_PROFILER__\r\n\r\n\t\t\tif (s_render_mode)\r\n\t\t\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\t\t\tfor (int i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (sp_loaded_scenes[i])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsp_loaded_scenes[i]->DebugRenderCollision(s_debug_ignore_1, s_debug_ignore_0);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n#endif\r\n\r\n\t\t\t\tconst Lst::Head<Obj::CObject>& composite_obj_list = Nx::CEngine::sGetMovableObjects();\r\n\t\t\t\tLst::Node<Obj::CObject>* p_composite_node = composite_obj_list.GetNext();\r\n\t\t\t\twhile( p_composite_node )\r\n\t\t\t\t{\r\n\t\t\t\t\tObj::CCompositeObject* p_composite_object = static_cast<Obj::CCompositeObject*>(p_composite_node->GetData());\r\n\t\t\t\t\tDbg_MsgAssert(p_composite_object, (\"Node in CObject list wasn't a CCompositeObject\"));\r\n\r\n\t\t\t\t\tObj::CCollisionComponent* p_collision_component = GetCollisionComponentFromObject( p_composite_object );\r\n\t\t\t\t\tif ( p_collision_component )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tCCollObj* p_coll_obj = p_collision_component->GetCollision();\r\n\t\t\t\t\t\tif (p_coll_obj)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_coll_obj->DebugRender( s_debug_ignore_1, s_debug_ignore_0 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tp_composite_node = p_composite_node->GetNext();\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t//printf (\"RENDERING FRAME WITH NO CAMERA (Nothing rendered)\\n\");\r\n\t\t}\r\n\t\t\r\n\t\t// Screen flash rendering.\r\n\t\tNx::ScreenFlashRender( view_idx, 0 );\r\n\t}\r\n\r\n\t//NxPs2::RenderEpilogueStart();\r\n\t\r\n\tif (got_vu0)\r\n\t{\r\n\t\tNxPs2::OccludeDisableVU0();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCScene\t*\tCEngine::s_plat_create_scene(const char *p_name, CTexDict *p_tex_dict, bool add_super_sectors)\r\n{\r\n\t// Create scene class instance\r\n\tCPs2Scene *p_ps2_scene = new CPs2Scene;\r\n\r\n\tNxPs2::CGeomNode *p_geomnode = new NxPs2::CGeomNode;\r\n\tp_geomnode->AddToTree(LOADFLAG_RENDERNOW);\r\n\tp_geomnode->SetActive(true);\r\n\tp_ps2_scene->SetEngineCloneScene(p_geomnode);\r\n\r\n\tCScene *new_scene = p_ps2_scene;\r\n\tnew_scene->SetInSuperSectors(add_super_sectors);\r\n\tnew_scene->SetIsSky(false);\r\n\r\n\treturn new_scene;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCScene *CEngine::s_plat_load_scene_from_memory( void *p_mem, CTexDict *p_tex_dict, bool add_super_sectors, bool is_sky, bool is_dictionary )\r\n{\r\n\t// GJ:  This is a stub function that should never be called by the PS2.\r\n\t// Currently, it's only needed by the X-box and the NGC\r\n\t// because all models are treated as \"scenes\" on those platforms.\r\n\t// On the PS2, models are treated as CPS2Mesh-es...\r\n\r\n\tDbg_MsgAssert( 0, ( \"This function is not supported on the PS2 right now\" ) );\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCScene\t*\tCEngine::s_plat_load_scene(const char *p_name, CTexDict *p_tex_dict,\r\n\t\t\t\t\t\t\t\t\t   bool add_super_sectors, bool is_sky, bool is_dictionary)\r\n{\r\n\t// Create scene class instance\r\n\tCPs2Scene *p_ps2_scene = new CPs2Scene;\r\n\tCScene *new_scene = p_ps2_scene;\r\n\tnew_scene->SetInSuperSectors(add_super_sectors);\r\n\tnew_scene->SetIsSky(is_sky);\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tCPs2TexDict *p_ps2_tex_dict = static_cast<CPs2TexDict *>(p_tex_dict);\r\n\tDbg_MsgAssert(p_ps2_tex_dict,(\"Invalid texture dictionsary for %s\",p_name));\r\n\t#endif\r\n\t\r\n\t// load scene\r\n\t// Pip::Load the new file\r\n\tuint8 *p_pipData = (uint8*)Pip::Load(p_name);\r\n\r\n\t// 1st section is shadow volume data.\r\n//\tp_ps2_scene->mp_shadow_volume_header = (Nx::sShadowVolumeHeader*)p_pipData;\r\n//\tp_ps2_scene->mp_shadow_volume_header->p_vertex = (Nx::sShadowVertex *)&p_ps2_scene->mp_shadow_volume_header[1];\r\n//\t\tp_ps2_scene->mp_shadow_volume_header->p_connect = (Nx::sShadowConnect *)&p_ps2_scene->mp_shadow_volume_header->p_vertex[p_ps2_scene->mp_shadow_volume_header->num_verts];\r\n//\tp_ps2_scene->mp_shadow_volume_header->p_neighbor = (Nx::sShadowNeighbor *)&p_ps2_scene->mp_shadow_volume_header->p_connect[p_ps2_scene->mp_shadow_volume_header->num_faces];\r\n//\r\n//\tuint8 * p_geom_data = (uint8*)p_ps2_scene->mp_shadow_volume_header->p_vertex;\r\n//\tp_geom_data = &p_geom_data[p_ps2_scene->mp_shadow_volume_header->byte_size];\r\n\t// PJR\r\n\t// Process my data here.\r\n\r\n\t// set up load flags\r\n\tuint32 load_flags = 0;\r\n\tif (!is_dictionary)\r\n\t{\r\n\t\t// render it unconditionally as opposed to holding in a database to be instanced later)\r\n\t\tload_flags |= LOADFLAG_RENDERNOW;\r\n\t} else {\r\n\t\tDbg_MsgAssert(!add_super_sectors, (\"Why would you need collision SuperSectors for a scene dictionary?\"));\r\n\t}\r\n\tif (is_sky)\r\n\t{\r\n\t\tload_flags |= LOADFLAG_SKY;\r\n\t}\r\n\r\n\t// process data in place\r\n\tNxPs2::CGeomNode *p_geomnode = NxPs2::CGeomNode::sProcessInPlace(p_pipData, load_flags);\r\n//\tNxPs2::CGeomNode *p_geomnode = NxPs2::CGeomNode::sProcessInPlace(p_geom_data, load_flags);\r\n\t\r\n\tDbg_MsgAssert(((int)(p_geomnode) & 0xf) == 0,(\"p_geomnode (0x%x) not multiple of 16 after sProcessInPlace\\n\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t,(int)p_geomnode));\r\n\r\n\t\r\n\tp_ps2_scene->SetEngineScene(p_geomnode);\r\n\r\n\treturn new_scene;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCEngine::s_plat_add_scene(CScene *p_scene, const char *p_filename)\r\n{\r\n\tDbg_MsgAssert(/*!p_scene->is_dictionary &&*/ !p_scene->IsSky(), (\"Can't add to sky or dictionary scene.\"));\r\n\r\n\t// load scene\r\n\t// Pip::Load the new file\r\n\tuint8 *p_pipData = (uint8*)Pip::Load(p_filename);\r\n\r\n\tDbg_MsgAssert(p_pipData, (\"s_plat_add_scene(): Can't open file %s\", p_filename));\r\n\r\n\t// process data in place\r\n\tNxPs2::CGeomNode *p_geomnode = NxPs2::CGeomNode::sProcessInPlace(p_pipData, LOADFLAG_RENDERNOW);\r\n\r\n\tCPs2Scene *p_ps2_scene = static_cast<CPs2Scene *>(p_scene);\r\n\tp_ps2_scene->SetEngineAddScene(p_geomnode);\r\n\r\n\treturn p_geomnode != NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCEngine::s_plat_unload_scene(CScene *p_scene)\r\n{\r\n\r\n\tDbg_MsgAssert(p_scene,(\"Trying to delete a NULL scene\"));\r\n\r\n\tCPs2Scene * p_ps2_scene = (CPs2Scene*)p_scene;\r\n\r\n\tNxPs2::CGeomNode *p_geomnode = p_ps2_scene->GetEngineScene();\r\n\r\n\tif (p_geomnode)\r\n\t{\r\n\t\t// clean up the node we created\r\n\t\tp_geomnode->Cleanup();\r\n\r\n\t\t// Pip::Unload the file\r\n\t\tPip::Unload(p_scene->GetSceneFilename());\r\n\t}\r\n\t\r\n\t// Clone scene node\r\n#if 0\t\t// Moved this into ~CPs2Scene so that this CGeomNode isn't destroyed before the cloned sectors\r\n\tNxPs2::CGeomNode *p_clone_geomnode = p_ps2_scene->GetEngineCloneScene();\r\n\tif (p_clone_geomnode)\r\n\t{\r\n\t\tp_clone_geomnode->Cleanup();\r\n\t\tdelete p_clone_geomnode;\r\n\t}\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModel*\t\tCEngine::s_plat_init_model(void)\r\n{\r\n\tCPs2Model* pModel = new CPs2Model;\r\n\r\n\treturn pModel;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCEngine::s_plat_uninit_model(CModel* pModel)\r\n{\r\n\tDbg_Assert( pModel );\r\n\r\n\tdelete pModel;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom*\tCEngine::s_plat_init_geom(void)\r\n{\r\n\tCPs2Geom* pGeom = new CPs2Geom;\r\n\r\n\treturn pGeom;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCEngine::s_plat_uninit_geom(CGeom* pGeom)\r\n{\r\n\tDbg_Assert( pGeom );\r\n\r\n\tdelete pGeom;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCQuickAnim* CEngine::s_plat_init_quick_anim()\r\n{\r\n\tCQuickAnim* pQuickAnim = new CQuickAnim;\r\n\r\n\treturn pQuickAnim;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CEngine::s_plat_uninit_quick_anim(CQuickAnim* pQuickAnim)\r\n{\r\n\tDbg_Assert( pQuickAnim );\r\n\r\n\tdelete pQuickAnim;\r\n\r\n\treturn;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMesh*\tCEngine::s_plat_load_mesh(uint32 id, uint32* pModelData, int modelDataSize, uint8* pCASData, Nx::CTexDict* pTexDict, uint32 texDictOffset, bool isSkin, bool doShadowVolume)\r\n{\r\n\tCPs2Mesh* pMesh = new CPs2Mesh(pModelData, modelDataSize, pCASData, pTexDict, texDictOffset, isSkin, doShadowVolume);\r\n\r\n\treturn pMesh;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMesh*\tCEngine::s_plat_load_mesh(const char* pMeshFileName, Nx::CTexDict* pTexDict, uint32 texDictOffset, bool isSkin, bool doShadowVolume)\r\n{\r\n\tCPs2Mesh* pMesh = new CPs2Mesh(pMeshFileName, pTexDict, texDictOffset, isSkin, doShadowVolume);\r\n\r\n\treturn pMesh;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCEngine::s_plat_unload_mesh(CMesh* pMesh)\r\n{\r\n\tDbg_Assert( pMesh );\r\n\r\n\tdelete pMesh;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCEngine::s_plat_set_mesh_scaling_parameters( SMeshScalingParameters* pParams )\r\n{\r\n\tNxPs2::SetMeshScalingParameters( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSprite *\tCEngine::s_plat_create_sprite(CWindow2D *p_window)\r\n{\r\n\treturn new CPs2Sprite(p_window);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCEngine::s_plat_destroy_sprite(CSprite *p_sprite)\r\n{\r\n\tdelete p_sprite;\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTextured3dPoly *\tCEngine::s_plat_create_textured_3d_poly()\r\n{\r\n\treturn new NxPs2::CPs2Textured3dPoly;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCEngine::s_plat_destroy_textured_3d_poly(CTextured3dPoly *p_poly)\r\n{\r\n\tdelete p_poly;\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::CTexture *CEngine::s_plat_create_render_target_texture( int width, int height, int depth, int z_depth )\r\n{\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CEngine::s_plat_project_texture_into_scene( Nx::CTexture *p_texture, Nx::CModel *p_model, Nx::CScene *p_scene )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CEngine::s_plat_set_projection_texture_camera( Nx::CTexture *p_texture, Gfx::Camera *p_camera )\r\n{\r\n\t#if !STENCIL_SHADOW\r\n\t// Currently assumes a top down view. So all we need to store is the position of the camera.\r\n\t// The width and height of the view frustum (this is an orthographic camera) are constant.\r\n\tMth::Vector pos = p_camera->GetPos();\r\n\tNxPs2::SetTextureProjectionCamera( &pos, &pos );\r\n\t#endif\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_stop_projection_texture( Nx::CTexture *p_texture )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_add_occlusion_poly( uint32 num_verts, Mth::Vector *p_vert_array, uint32 checksum )\r\n{\r\n\tif( num_verts == 4 )\r\n\t{\r\n\t\tNxPs2::AddOcclusionPoly( p_vert_array[0], p_vert_array[1], p_vert_array[2], p_vert_array[3], checksum );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_enable_occlusion_poly( uint32 checksum, bool enable )\r\n{\r\n\tNxPs2::EnableOcclusionPoly( checksum, enable );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_remove_all_occlusion_polys( void )\r\n{\r\n\tNxPs2::RemoveAllOcclusionPolys();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// returns true if the sphere at \"center\", with the \"radius\"\r\n// is visible to the current camera\r\n// (note, currently this is the last frame's camera on PS2)\r\nbool CEngine::s_plat_is_visible( Mth::Vector&\tcenter, float radius  )\r\n{\r\n\treturn NxPs2::IsVisible(center,radius);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_set_max_multipass_distance(float dist)\r\n{\r\n\tNxPs2::render::sMultipassMaxDist = dist;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char *\t\tCEngine::s_plat_get_platform_extension()\r\n{\r\n\treturn \"PS2\";\t// String literals are statically allocated so can be returned safely, (Bjarne, p90)\r\n}\r\n\r\n\r\n/******************************************************************/\r\n// Wait for any pending asyncronous rendering to finish, so rendering\r\n// data can be unloaded\r\n/******************************************************************/\r\n\r\nvoid CEngine::s_plat_finish_rendering()\r\n{\r\n\t\tNxPs2::WaitForRendering();\t\t// PS2 Specific, wait for prior frame's DMA to finish\t\r\n} \r\n\r\n/******************************************************************/\r\n// Set the amount that the previous frame is blended with this frame\r\n// 0 = none\t  \t(just see current frame) \t\r\n// 128 = 50/50\r\n// 255 = 100% \t(so you only see the previous frame)\t\t\t\t\t\t\t\t\t\t\t\t  \r\n/******************************************************************/\r\n\r\nvoid CEngine::s_plat_set_screen_blur(uint32 amount )\r\n{\r\n\tamount = (255-amount)/2;\r\n\tuint32 alpha = *NxPs2::p_patch_ALPHA;\r\n\talpha &= 0xffffff00;\r\n\talpha |= amount; \r\n\t*NxPs2::p_patch_ALPHA = alpha;\t\r\n\t*NxPs2::p_patch_ALPHA2 = alpha;\t\r\n} \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tCEngine::s_plat_get_num_soundtracks()\r\n{\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char* CEngine::s_plat_get_soundtrack_name( int soundtrack_number )\r\n{\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n// Add some PS2 specific debug info to the metrics script structure\r\nvoid\tCEngine::s_plat_get_metrics(Script::CStruct * p_info)\r\n{\r\n\r\n\t// get the scene, and get the root \r\n\r\n\tScript::CStruct *p_ps2 = new Script::CStruct();\r\n\t\r\n\tNxPs2::CGeomMetrics * p_metrics = new NxPs2::CGeomMetrics;\r\n\r\n\tCPs2Scene * p_ps2_scene = (CPs2Scene *) sGetMainScene();\r\n\tif (p_ps2_scene->GetEngineScene())\r\n\t{\r\n\t\tp_ps2_scene->GetEngineScene()->CountMetrics(p_metrics);\r\n\t\tp_ps2->AddInteger(CRCD(0xd55cd658,\"NULLEngineScene\"),0);\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\t// K: Added this so that the script refresh_poly_count in lighttool.q\r\n\t\t// can display \"N/A\" for the values.\r\n\t\tp_ps2->AddInteger(CRCD(0xd55cd658,\"NULLEngineScene\"),1);\r\n\t}\r\n\r\n\tp_ps2->AddInteger(CRCD(0x3dd01ea1,\"total\"), p_metrics->m_total);        \r\n\tp_ps2->AddInteger(CRCD(0x3960ff18,\"leaf\"),  p_metrics->m_leaf);  \r\n\tp_ps2->AddInteger(CRCD(0x4de5330c,\"objects\"),  p_metrics->m_object);  \r\n\tp_ps2->AddInteger(CRCD(0x94927839,\"vert\"),  p_metrics->m_verts);  \r\n\tp_ps2->AddInteger(CRCD(0x169ee151,\"poly\"),  p_metrics->m_polys);  \r\n\tp_ps2->AddFloat(CRCD(0x58785e10,\"verts_per_poly\"),  (float)p_metrics->m_verts/(float)p_metrics->m_polys);  \r\n\tp_ps2->AddFloat(CRCD(0x3b75d7cc,\"polys_per_object\"),  (float)p_metrics->m_polys/(float)p_metrics->m_object);  \r\n\tp_ps2->AddFloat(CRCD(0xbc56249d,\"polys_per_mesh\"),  (float)p_metrics->m_polys/(float)p_metrics->m_leaf);  \r\n\t\t   \r\n\tp_info->AddStructurePointer(CRCD(0x26861025,\"scene\"),p_ps2);\r\n\t\r\n\tdelete\tp_metrics;\r\n\r\n\r\n}\r\n\r\n\r\nvoid CEngine::s_plat_set_letterbox( bool letterbox )\r\n{\r\n\tNxPs2::DoLetterbox = letterbox;\r\n} \r\n \r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_set_color_buffer_clear( bool clear )\r\n{\r\n}\r\n\r\n\r\n\r\n}"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxmiscfx.cpp",
    "content": "#include <core/defines.h>\r\n\r\n#include <gel/collision/collision.h>\r\n#include <gel/collision/colltridata.h>\r\n#include <gel/collision/movcollman.h>\r\n#include <gel/collision/batchtricoll.h>\r\n#include <engine/SuperSector.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/nxtexman.h>\r\n#include <gfx/debuggfx.h>\r\n#include <gfx/NxViewMan.h>\r\n#include <gfx/NxMiscFX.h>\r\n\r\n#include <gfx/ngps/p_nxgeom.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n#include <gfx/ngps/nx/dma.h>\r\n#include <gfx/ngps/nx/fx.h>\r\n#include <gfx/ngps/nx/immediate.h>\r\n#include <gfx/ngps/nx/geomnode.h>\r\n#include <gfx/ngps/nx/group.h>\r\n#include <gfx/ngps/nx/gs.h>\r\n#include <gfx/ngps/nx/vif.h>\r\n#include <gfx/ngps/nx/render.h>\r\n#include <gfx/ngps/nx/switches.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n#define\tDRAW_DEBUG_LINES\t\t0\r\n#define PRINT_SHATTER_MEMORY\t0\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sNGPSVert\r\n{\r\n\tMth::Vector\t\tpos;\r\n\tImage::RGBA\t\tcol;\r\n\tfloat\t\t\tu, v;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sNGPSSplatInstanceDetails : public sSplatInstanceDetails\r\n{\r\n\t// Platform specific part.\r\n\tNxPs2::SSingleTexture\t*mp_texture;\r\n\tsNGPSVert\t\t\t\tm_verts[SPLAT_POLYS_PER_MESH * 3];\r\n};\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sNGPSShatterInstanceDetails : public sShatterInstanceDetails\r\n{\r\n\t// Platform specific part.\r\n\t\t\t\t\t\t\tsNGPSShatterInstanceDetails( int num_tris, NxPs2::CGeomNode *p_geom_node );\r\n\t\t\t\t\t\t\t~sNGPSShatterInstanceDetails( void );\r\n\r\n\tstatic int\t\t\t\tsQueryMemoryNeeded(int num_tris);\r\n\r\n\tNxPs2::CGeomNode *\t\tmp_geom_node;\t\t// Corresponding source mesh\r\n\tsNGPSVert *\t\t\t\tmp_vert_array;\t\t// Array of vertices\r\n\r\n\tuint32 *\t\t\t\tmp_tex_regs;\t\t// packed texture registers\r\n\tint\t\t\t\t\t\tm_num_tex_regs;\t\t// number of texture registers\r\n};\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsNGPSShatterInstanceDetails::sNGPSShatterInstanceDetails( int num_tris, NxPs2::CGeomNode *p_geom_node ) : sShatterInstanceDetails( num_tris )\r\n{\r\n\tmp_geom_node = p_geom_node;\r\n\r\n#if PRINT_SHATTER_MEMORY\r\n\tDbg_Message(\"Allocating %d bytes for vert array of %d tris\", sizeof(sNGPSVert) * 3 * num_tris, num_tris);\r\n#endif\r\n\tmp_vert_array = new sNGPSVert[num_tris * 3];\r\n\r\n\t// Get texture info\r\n\tif (p_geom_node->GetGroup())\t\t// Garrett: Need to find the real way to figure out if a mesh\r\n\t{\t\t\t\t\t\t\t\t\t// is textures or not (can always look at the GIFtag)\r\n\t\tuint32 *p_dma = (uint32 *) p_geom_node->GetDma();\r\n\r\n\t\tp_dma += 9;\t\t\t// Go to vif::UNPACK() for texture regs\r\n\r\n\t\tm_num_tex_regs = (*p_dma >> 16) & 0xf;\r\n\t\tmp_tex_regs = p_dma + 1;\r\n#if 0\r\n\t\tDbg_Message(\"Found %d texture registers for type %x\", m_num_tex_regs, (*p_dma >> 24));\r\n\t\tfor (int i = 0; i < m_num_tex_regs; i++)\r\n\t\t{\r\n\t\t\tDbg_Message(\" - Register %x\", mp_tex_regs[(i * 3) + 2]);\r\n\t\t}\r\n#endif\r\n\t} else {\r\n\t\tmp_tex_regs = NULL;\r\n\t\tm_num_tex_regs = 0;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsNGPSShatterInstanceDetails::~sNGPSShatterInstanceDetails( void )\r\n{\r\n\tdelete [] mp_vert_array;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\tsNGPSShatterInstanceDetails::sQueryMemoryNeeded(int num_tris)\r\n{\r\n\tint size = sShatterInstanceDetails::s_query_memory_needed(num_tris);\r\n\r\n\tsize += (sizeof(sNGPSShatterInstanceDetails) - sizeof(sShatterInstanceDetails));\r\n\tsize += sizeof(sNGPSVert) * num_tris * 3;\r\n\r\n\treturn size;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsNGPSSplatInstanceDetails * getDetailsForTextureSplat( NxPs2::SSingleTexture *p_texture )\r\n{\r\n\tsNGPSSplatInstanceDetails *p_ngps_details;\r\n\r\n\tDbg_Assert( p_splat_details_table );\r\n\t\r\n\t// Check to see whether we have a scene already created for this type of texture splat.\r\n\tp_splat_details_table->IterateStart();\r\n\tsSplatInstanceDetails *p_details = p_splat_details_table->IterateNext();\r\n\twhile( p_details )\r\n\t{\r\n\t\tp_ngps_details\t\t\t\t\t= static_cast<sNGPSSplatInstanceDetails*>( p_details );\r\n\r\n\t\t// If this one matches, return it...\r\n\t\tif (p_ngps_details->mp_texture == p_texture)\r\n\t\t{\r\n\t\t\treturn p_ngps_details;\r\n\t\t}\r\n\t\tp_details = p_splat_details_table->IterateNext();\r\n\t}\r\n\r\n\t// Check to see that we have memory first\r\n\tif (Mem::Available() < (int) ((sizeof(sNGPSSplatInstanceDetails) * 3) / 2))\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tp_ngps_details = new sNGPSSplatInstanceDetails;\r\n\tp_ngps_details->m_highest_active_splat\t= 0;\r\n\tp_ngps_details->mp_texture = p_texture;\r\n\tmemset( p_ngps_details->m_lifetimes, 0, sizeof( int ) * SPLAT_POLYS_PER_MESH );\r\n\t\r\n\tfor( int v = 0; v < SPLAT_POLYS_PER_MESH * 3; ++v )\r\n\t{\r\n\t\tp_ngps_details->m_verts[v].pos = Mth::Vector(0.0f, 0.0f, 0.0f, 1.0f);\r\n\t\tp_ngps_details->m_verts[v].col = Image::RGBA( 0x80, 0x80, 0x80, 0x80 );\r\n\t}\r\n\r\n\tp_splat_details_table->PutItem((uint32)p_ngps_details, p_ngps_details );\r\n\r\n\treturn p_ngps_details;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool subdivide_tri_stack( float shatterArea, sNGPSVert **p_write, NxPs2::CGeomNode *p_node )\r\n{\r\n\t// If there are elements on the stack, pop off the top three vertices and subdivide if necessary.\r\n\tif( triSubdivideStack.IsEmpty())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Three temporary buffers.\r\n\tsNGPSVert v0;\r\n\tsNGPSVert v1;\r\n\tsNGPSVert v2;\r\n\t\r\n\t// Stack is LIFO, so Pop() off in reverse order.\r\n\ttriSubdivideStack.Pop( &v2 );\r\n\ttriSubdivideStack.Pop( &v1 );\r\n\ttriSubdivideStack.Pop( &v0 );\r\n\t\r\n\t// Calculate the area of this tri.\r\n\tMth::Vector p(\tv1.pos[X] - v0.pos[X], v1.pos[Y] - v0.pos[Y], v1.pos[Z] - v0.pos[Z] );\r\n\tMth::Vector q(\tv2.pos[X] - v0.pos[X], v2.pos[Y] - v0.pos[Y], v2.pos[Z] - v0.pos[Z] );\r\n\tMth::Vector r(( p[Y] * q[Z] ) - ( q[Y] * p[Z] ), ( p[Z] * q[X] ) - ( q[Z] * p[X] ), ( p[X] * q[Y] ) - ( q[X] * p[Y] ));\r\n\tfloat area_squared = r.LengthSqr();\r\n\r\n\tif( area_squared > shatterArea )\r\n\t{\r\n\t\t// We need to subdivide this tri. Calculate the three intermediate points.\r\n\t\tint block_size = triSubdivideStack.GetBlockSize();\r\n\r\n\t\t// Three temporary buffers.\r\n\t\tsNGPSVert i01;\r\n\t\tsNGPSVert i12;\r\n\t\tsNGPSVert i20;\r\n\r\n\t\tmemcpy( &i01, &v0, block_size );\r\n\t\tmemcpy( &i12, &v1, block_size );\r\n\t\tmemcpy( &i20, &v2, block_size );\r\n\r\n\t\t// Deal with positions (always present).\r\n\t\ti01.pos[X] = v0.pos[X] + (( v1.pos[X] - v0.pos[X] ) * 0.5f );\r\n\t\ti01.pos[Y] = v0.pos[Y] + (( v1.pos[Y] - v0.pos[Y] ) * 0.5f );\r\n\t\ti01.pos[Z] = v0.pos[Z] + (( v1.pos[Z] - v0.pos[Z] ) * 0.5f );\r\n\r\n\t\ti12.pos[X] = v1.pos[X] + (( v2.pos[X] - v1.pos[X] ) * 0.5f );\r\n\t\ti12.pos[Y] = v1.pos[Y] + (( v2.pos[Y] - v1.pos[Y] ) * 0.5f );\r\n\t\ti12.pos[Z] = v1.pos[Z] + (( v2.pos[Z] - v1.pos[Z] ) * 0.5f );\r\n\r\n\t\ti20.pos[X] = v2.pos[X] + (( v0.pos[X] - v2.pos[X] ) * 0.5f );\r\n\t\ti20.pos[Y] = v2.pos[Y] + (( v0.pos[Y] - v2.pos[Y] ) * 0.5f );\r\n\t\ti20.pos[Z] = v2.pos[Z] + (( v0.pos[Z] - v2.pos[Z] ) * 0.5f );\r\n\r\n\t\t// Deal with colors (not always present).\r\n\t\t//if( p_node->m_diffuse_offset > 0 )\r\n\t\t{\r\n\t\t\tuint8\t*p_v0col\t= (uint8*)( &(v0.col));\r\n\t\t\tuint8\t*p_v1col\t= (uint8*)( &(v1.col));\r\n\t\t\tuint8\t*p_v2col\t= (uint8*)( &(v2.col));\r\n\t\t\tuint8\t*p_i01col\t= (uint8*)( &(i01.col));\r\n\t\t\tuint8\t*p_i12col\t= (uint8*)( &(i12.col));\r\n\t\t\tuint8\t*p_i20col\t= (uint8*)( &(i20.col));\r\n\t\t\r\n\t\t\tfor( int i = 0; i < 4; ++i )\r\n\t\t\t{\r\n\t\t\t\tp_i01col[i]\t\t= p_v0col[i] + (char)(( p_v1col[i] - p_v0col[i] ) * 0.5f );\r\n\t\t\t\tp_i12col[i]\t\t= p_v1col[i] + (char)(( p_v2col[i] - p_v1col[i] ) * 0.5f );\r\n\t\t\t\tp_i20col[i]\t\t= p_v2col[i] + (char)(( p_v0col[i] - p_v2col[i] ) * 0.5f );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Deal with uv0 (not always present).\r\n\t\t//if( p_node->m_uv0_offset > 0 )\r\n\t\t{\r\n\t\t\tfloat\t*p_v0uv\t\t= (float*)( &v0.u );\r\n\t\t\tfloat\t*p_v1uv\t\t= (float*)( &v1.u );\r\n\t\t\tfloat\t*p_v2uv\t\t= (float*)( &v2.u );\r\n\t\t\tfloat\t*p_i01uv\t= (float*)( &i01.u );\r\n\t\t\tfloat\t*p_i12uv\t= (float*)( &i12.u );\r\n\t\t\tfloat\t*p_i20uv\t= (float*)( &i20.u );\r\n\t\t\r\n\t\t\t// We know that v is contiguous to u\r\n\t\t\tfor( int i = 0; i < 2; ++i )\r\n\t\t\t{\r\n\t\t\t\tp_i01uv[i]\t\t= p_v0uv[i] + (( p_v1uv[i] - p_v0uv[i] ) * 0.5f );\r\n\t\t\t\tp_i12uv[i]\t\t= p_v1uv[i] + (( p_v2uv[i] - p_v1uv[i] ) * 0.5f );\r\n\t\t\t\tp_i20uv[i]\t\t= p_v2uv[i] + (( p_v0uv[i] - p_v2uv[i] ) * 0.5f );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Push the four new tris onto the stack.\r\n\t\ttriSubdivideStack.Push( &v0 );\r\n\t\ttriSubdivideStack.Push( &i01 );\r\n\t\ttriSubdivideStack.Push( &i20 );\r\n\r\n\t\ttriSubdivideStack.Push( &i01 );\r\n\t\ttriSubdivideStack.Push( &v1 );\r\n\t\ttriSubdivideStack.Push( &i12 );\r\n\r\n\t\ttriSubdivideStack.Push( &i01 );\r\n\t\ttriSubdivideStack.Push( &i12 );\r\n\t\ttriSubdivideStack.Push( &i20 );\r\n\r\n\t\ttriSubdivideStack.Push( &i20 );\r\n\t\ttriSubdivideStack.Push( &i12 );\r\n\t\ttriSubdivideStack.Push( &v2 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Don't need to subdivide this tri.\r\n\t\tint block_size = triSubdivideStack.GetBlockSize();\r\n\r\n\t\t// Just copy the tri into the next available slot.\r\n\t\tmemcpy( *p_write, &v0, block_size );\r\n\t\t(*p_write)++;\r\n\t\tmemcpy( *p_write, &v1, block_size );\r\n\t\t(*p_write)++;\r\n\t\tmemcpy( *p_write, &v2, block_size );\r\n\t\t(*p_write)++;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic bool same_side( Mth::Vector &p1, Mth::Vector &p2, Mth::Vector &a, Mth::Vector &b )\r\n{\r\n\tMth::Vector cp1 = Mth::CrossProduct( b - a, p1 - a );\r\n\tMth::Vector cp2 = Mth::CrossProduct( b - a, p2 - a );\r\n\tif( Mth::DotProduct( cp1, cp2 ) >= 0.0f )\r\n\t\treturn true;\r\n    else\r\n\t\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic bool point_in_triangle( Mth::Vector &p, Mth::Vector &a, Mth::Vector &b, Mth::Vector &c )\r\n{\r\n\tif( same_side( p, a, b, c ) && same_side( p, b, a, c ) && same_side( p, c, a, b ))\r\n\t\treturn true;\r\n    else\r\n\t\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline bool line_segment_intersection( float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4 )\r\n{\r\n\tfloat den = (( y4 - y3 ) * ( x2 - x1 )) - (( x4 - x3 ) * ( y2 - y1 ));\r\n\r\n\tif( den == 0.0f )\r\n\t{\r\n\t\t// Parallel lines.\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tfloat num_a = (( x4 - x3 ) * ( y1 - y3 )) - (( y4 - y3 ) * ( x1 - x3 ));\r\n\tfloat num_b = (( x2 - x1 ) * ( y1 - y3 )) - (( y2 - y1 ) * ( x1 - x3 ));\r\n\r\n\tnum_a /= den;\r\n\tnum_b /= den;\r\n\r\n\tif(( num_a <= 1.0f ) && ( num_b <= 1.0f ))\r\n\t\treturn true;\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline bool tri_texture_intersect( float u0, float v0, float u1, float v1, float u2, float v2 )\r\n{\r\n\t// Trivial check to see if all three points are outside range of texture.\r\n\tif(( u0 < -1.0f ) && ( u1 < -1.0f ) && ( u2 < -1.0f ))\r\n\t\treturn false;\r\n\tif(( u0 > 1.0f ) && ( u1 > 1.0f ) && ( u2 > 1.0f ))\r\n\t\treturn false;\r\n\tif(( v0 < -1.0f ) && ( v1 < -1.0f ) && ( v2 < -1.0f ))\r\n\t\treturn false;\r\n\tif(( v0 > 1.0f ) && ( v1 > 1.0f ) && ( v2 > 1.0f ))\r\n\t\treturn false;\r\n\t\r\n\t// Check that at least one corner of the texture falls within the tri.\r\n\tMth::Vector texture_square[4] = {\tMth::Vector( -1.0f, -1.0f, 0.0f, 0.0f ),\r\n\t\t\t\t\t\t\t\t\t\tMth::Vector(  1.0f, -1.0f, 0.0f, 0.0f ),\r\n\t\t\t\t\t\t\t\t\t\tMth::Vector(  1.0f,  1.0f, 0.0f, 0.0f ),\r\n\t\t\t\t\t\t\t\t\t\tMth::Vector( -1.0f,  1.0f, 0.0f, 0.0f )};\r\n\r\n\tMth::Vector a( u0, v0, 0.0f );\r\n\tMth::Vector b( u1, v1, 0.0f );\r\n\tMth::Vector c( u2, v2, 0.0f );\r\n\r\n\tfor( int p = 0; p < 4; ++p )\r\n\t{\r\n\t\tif( point_in_triangle( texture_square[p], a, b, c ))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// No corners of the texture fall within the tri. There are 3 possible explanations:\r\n\t// 1) The tri intersects the texture, but does not contain a texture corner.\r\n\t// 2) The texture lies entirely outside of the tri.\r\n\t// 3) The tri falls entirely within the texture.\r\n\t// Given the relatively small size of the textures, case (3) is extremely unlikely.\r\n\r\n\t// Perform a trivial check to see whether a corner of the tri lies within the texture. This will catch (3) and sometimes (1).\r\n\tif(( u0 >= -1.0f ) && ( u0 <= 1.0f ) && ( v0 >= -1.0f ) && ( v0 <= 1.0f ))\r\n\t\treturn true;\r\n\tif(( u1 >= -1.0f ) && ( u1 <= 1.0f ) && ( v1 >= -1.0f ) && ( v1 <= 1.0f ))\r\n\t\treturn true;\r\n\tif(( u2 >= -1.0f ) && ( u2 <= 1.0f ) && ( v2 >= -1.0f ) && ( v2 <= 1.0f ))\r\n\t\treturn true;\r\n\r\n\t// Perform the complete check to see if any line segment forming the tri intersects any line segment forming the texture.\r\n\tfor( int p = 0; p < 4; ++p )\r\n\t{\r\n\t\tint q = ( p + 1 ) % 4;\r\n\t\tif( line_segment_intersection( u0, v0, u1, v1, texture_square[p][X], texture_square[p][Y], texture_square[q][X], texture_square[q][Y] ))\r\n\t\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_screen_flash_render( sScreenFlashDetails *p_details )\r\n{\r\n\t// Get viewport details.\r\n\tCViewport *p_vp = CViewportManager::sGetActiveViewport( p_details->m_viewport );\r\n\t\r\n\t// Centre of screen is (0x8000, 0x8000), unit is 1/16 pixel.\r\n\t\r\n\tint x0 = XOFFSET + (int)( p_vp->GetOriginX() * (HRES << 4) );\r\n\tint y0 = YOFFSET + (int)( p_vp->GetOriginY() * (VRES << 4) );\r\n\tint x1 = x0 + (int)( p_vp->GetWidth() * (HRES << 4) );\r\n\tint y1 = y0 + (int)( p_vp->GetHeight() * (VRES << 4) );\r\n\r\n\tuint32 rgba = p_details->m_current.r | ((uint32)p_details->m_current.g << 8 ) | ((uint32)p_details->m_current.b << 16 ) | ((uint32)p_details->m_current.a << 24 );\r\n\t\r\n\tNxPs2::DrawRectangle( x0, y0, x1, y1, rgba );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_texture_splat_initialize( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_texture_splat_cleanup( void )\r\n{\r\n\tsNGPSSplatInstanceDetails *p_ngps_details;\r\n\r\n\tDbg_Assert( p_splat_details_table );\r\n\t\r\n\tp_splat_details_table->IterateStart();\r\n\tsSplatInstanceDetails *p_details = p_splat_details_table->IterateNext();\r\n\twhile( p_details )\r\n\t{\r\n\t\tp_ngps_details = static_cast<sNGPSSplatInstanceDetails*>( p_details );\r\n\t\t\r\n\t\tp_details = p_splat_details_table->IterateNext();\r\n\r\n\t\tp_splat_details_table->FlushItem((uint32)p_ngps_details );\r\n\t\tdelete p_ngps_details;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_texture_splat_reset_poly( sSplatInstanceDetails *p_details, int index )\r\n{\r\n\t// Cast the details to NGPS details.\r\n\tsNGPSSplatInstanceDetails *p_ngps_details = static_cast<sNGPSSplatInstanceDetails *>( p_details );\r\n\t\r\n\t// Force this poly to be degenerate.\r\n\tp_ngps_details->m_verts[index * 3 + 1]\t= p_ngps_details->m_verts[index * 3];\r\n\tp_ngps_details->m_verts[index * 3 + 2]\t= p_ngps_details->m_verts[index * 3];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool plat_texture_splat( Nx::CSector **pp_sectors, Nx::CCollStatic **pp_collision, Mth::Vector& start, Mth::Vector& end,\r\n\t\t\t\t\t\t float size, float lifetime, Nx::CTexture *p_texture, Nx::sSplatTrailInstanceDetails *p_trail_details )\r\n{\r\n\tMth::Matrix view_matrix, ortho_matrix, projection_matrix;\r\n\r\n#\tif DRAW_DEBUG_LINES\r\n\tGfx::AddDebugLine( start, end, MAKE_RGB( 200, 200, 0 ), MAKE_RGB( 200, 200, 0 ), 1 );\r\n#\tendif // DRAW_DEBUG_LINES\r\n\t\r\n\t// The length of the start->end line defines the view depth of the frustum.\r\n\tMth::Vector\tsplat_vector\t= end - start;\r\n\tfloat\t\tview_depth\t\t= splat_vector.Length();\r\n\tsplat_vector.Normalize();\r\n\t\r\n\t// Calculate the parallel projection matrix. Generally the projection vector will tend to point downwards, so we use a\r\n\t// random vector in the x-z plane to define the up vector for the projection. However if this splat is part of a trail,\r\n\t// use the previous point to generate the up vector.\r\n\tif( p_trail_details )\r\n\t{\r\n\t\tMth::Vector up( start[X] - p_trail_details->m_last_pos[X], start[Y] - p_trail_details->m_last_pos[Y], start[Z] - p_trail_details->m_last_pos[Z], 0.0f );\r\n\t\tDbg_MsgAssert((up[X] != 0.0f) || (up[Z] != 0.0f), (\"Up vector has no length\"));\r\n\t\t//Dbg_Message(\"Splat up vector (%.8f, %.8f, %.8f)\", up[X], up[Y], up[Z]);\r\n\r\n\t\t// The height of the viewport is defined by the distance between the two points.\r\n\t\tfloat height = up.Length() * 0.5f;\r\n\r\n\t\tstart\t-= up * 0.5f;\r\n\t\tend\t\t-= up * 0.5f;\r\n\r\n\t\tup.Normalize();\r\n\r\n\t\tMth::CreateMatrixLookAt( view_matrix, start, end, up );\r\n\t\tMth::CreateMatrixOrtho( ortho_matrix, size, height, 0.1f, view_depth );\r\n\t}\r\n\telse if( fabsf( splat_vector[Y] ) > 0.5f )\r\n\t{\r\n\t\tfloat angle = ((float)rand() * 2.0f * Mth::PI ) / (float)RAND_MAX;\r\n\t\tMth::CreateMatrixLookAt( view_matrix, start, end, Mth::Vector( sinf( angle ), 0.0f, cosf( angle ), 0.0f ));\r\n\t\tMth::CreateMatrixOrtho( ortho_matrix , size, size, 0.1f, view_depth );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMth::CreateMatrixLookAt( view_matrix, start, end, Mth::Vector( 0.0f, 1.0f, 0.0f, 0.0f ));\r\n\t\tMth::CreateMatrixOrtho( ortho_matrix , size, size, 0.1f, view_depth );\r\n\t}\r\n\r\n\tprojection_matrix = view_matrix * ortho_matrix;\r\n\r\n\t// Find texture info\r\n\tDbg_Assert(p_texture);\r\n\tCPs2Texture *p_ps2_texture = static_cast<CPs2Texture *>(p_texture);\r\n\tNxPs2::SSingleTexture *p_single_texture = p_ps2_texture->GetSingleTexture();\r\n\tDbg_Assert(p_single_texture);\r\n\r\n\t// Pointer to the mesh we will be modifying. (Don't want to set the pointer up until we know for\r\n\t// sure that we will be adding some polys).\r\n\tsNGPSSplatInstanceDetails\t*p_details\t\t= NULL;\r\n\tsNGPSVert\t\t\t\t\t*p_target_verts\t= NULL;\r\n\r\n#if DRAW_DEBUG_LINES\r\n\tNx::CSector *p_sector;\r\n\twhile(( p_sector = *pp_sectors ))\r\n\t{\r\n\t\tNx::CPs2Geom *p_ngps_geom = static_cast<Nx::CPs2Geom*>( p_sector->GetGeom());\r\n\r\n\t\tif( p_ngps_geom )\r\n\t\t{\r\n\t\t\tMth::Vector min = p_ngps_geom->GetBoundingBox().GetMin();\r\n\t\t\tMth::Vector max = p_ngps_geom->GetBoundingBox().GetMax();\r\n\r\n\t\t\tMth::Vector box[8];\r\n\t\t\tbox[0] = box[1] = box[2] = box[3] = max;\r\n\t\t\tbox[1][X] = min[X];\r\n\t\t\tbox[2][Y] = min[Y];\r\n\t\t\tbox[3][Z] = min[Z];\r\n\t\t\tbox[5] = box[6] = box[7] = box[4] = min;;\r\n\t\t\tbox[5][X] = max[X];\r\n\t\t\tbox[6][Y] = max[Y];\r\n\t\t\tbox[7][Z] = max[Z];\r\n\r\n\t\t\tfor ( int i = 1; i < 4; i++ )\r\n\t\t\t{\r\n\t\t\t\tGfx::AddDebugLine( box[0], box[i], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\t}\r\n\t\t\tfor ( int i = 5; i < 8; i++ )\r\n\t\t\t{\r\n\t\t\t\tGfx::AddDebugLine( box[4], box[i], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\t}\r\n\t\t\tGfx::AddDebugLine( box[1], box[6], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\tGfx::AddDebugLine( box[1], box[7], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\tGfx::AddDebugLine( box[2], box[5], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\tGfx::AddDebugLine( box[2], box[7], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\tGfx::AddDebugLine( box[3], box[5], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\tGfx::AddDebugLine( box[3], box[6], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t}\r\n\r\n\t\t++pp_sectors;\r\n\t}\r\n#endif // DRAW_DEBUG_LINES\r\n\r\n\t// Make initial line bounding box.  (Possibly pass previous one in if this takes too long)\r\n\tMth::CBBox line_bbox( start );\r\n\tline_bbox.AddPoint( end );\r\n\r\n\t//Dbg_Message(\"Using line (%f, %f, %f) - (%f, %f, %f)\", start[X], start[Y], start[Z], end[X], end[Y], end[Z]);\r\n\r\n\tNx::CCollStatic *p_collision;\r\n\twhile(( p_collision = *(pp_collision++) ))\r\n\t{\r\n\t\t// Since the collision is static, we can assume the collision geometry data is in world space\r\n\t\tNx::CCollObjTriData *p_coll_geom = p_collision->GetGeometry();\r\n\t\t\r\n\t\t// narrow down list of possible faces\r\n\t\tuint num_faces;\r\n\t\tFaceIndex *p_face_indexes;\r\n\t\tp_face_indexes = p_coll_geom->FindIntersectingFaces(line_bbox, num_faces);\r\n\t\tDbg_Assert(p_face_indexes);\r\n\r\n\t\tMth::Vector uvprojections[3];\r\n\r\n\t\tfor (uint fidx = 0; fidx < num_faces; fidx++, p_face_indexes++)\r\n\t\t{\r\n\t\t\t// Make sure it is collidable and visible\r\n\t\t\tif (p_coll_geom->GetFaceFlags(*p_face_indexes) & (mFD_NON_COLLIDABLE | mFD_INVISIBLE))\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tMth::Vector v0(p_coll_geom->GetRawVertexPos(p_coll_geom->GetFaceVertIndex(*p_face_indexes, 0)));\r\n\t\t\tMth::Vector v1(p_coll_geom->GetRawVertexPos(p_coll_geom->GetFaceVertIndex(*p_face_indexes, 1)));\r\n\t\t\tMth::Vector v2(p_coll_geom->GetRawVertexPos(p_coll_geom->GetFaceVertIndex(*p_face_indexes, 2)));\r\n\t\t\tv0[W] = v1[W] = v2[W] = 1.0f;\t\t// Make sure they are points, not vectors\r\n\r\n#if 1\r\n\t\t\tuvprojections[0] = v0 * projection_matrix;\r\n\t\t\tuvprojections[1] = v1 * projection_matrix;\r\n\t\t\tuvprojections[2] = v2 * projection_matrix;\r\n#else\r\n\t\t\t// Test each component\r\n\t\t\tuvprojections[0] = v0 * view_matrix;\r\n\t\t\tuvprojections[1] = v1 * view_matrix;\r\n\t\t\tuvprojections[2] = v2 * view_matrix;\r\n\r\n\t\t\tDbg_Message(\"Looking at possible splat poly vert 0 (%f, %f, %f, %f)\", v0[X], v0[Y], v0[Z], v0[W]);\r\n\t\t\tDbg_Message(\"Looking at possible splat poly vert 1 (%f, %f, %f, %f)\", v1[X], v1[Y], v1[Z], v1[W]);\r\n\t\t\tDbg_Message(\"Looking at possible splat poly vert 2 (%f, %f, %f, %f)\", v2[X], v2[Y], v2[Z], v2[W]);\r\n\r\n\t\t\tDbg_Message(\"Converted vert 0 to (%f, %f, %f)\", uvprojections[0][X], uvprojections[0][Y], uvprojections[0][Z]);\r\n\t\t\tDbg_Message(\"Converted vert 1 to (%f, %f, %f)\", uvprojections[1][X], uvprojections[1][Y], uvprojections[1][Z]);\r\n\t\t\tDbg_Message(\"Converted vert 2 to (%f, %f, %f)\", uvprojections[2][X], uvprojections[2][Y], uvprojections[2][Z]);\r\n\r\n\t\t\tuvprojections[0] = uvprojections[0] * ortho_matrix;\r\n\t\t\tuvprojections[1] = uvprojections[1] * ortho_matrix;\r\n\t\t\tuvprojections[2] = uvprojections[2] * ortho_matrix;\r\n\r\n\t\t\tDbg_Message(\"Converted vert 0 again to (%f, %f, %f)\", uvprojections[0][X], uvprojections[0][Y], uvprojections[0][Z]);\r\n\t\t\tDbg_Message(\"Converted vert 1 again to (%f, %f, %f)\", uvprojections[1][X], uvprojections[1][Y], uvprojections[1][Z]);\r\n\t\t\tDbg_Message(\"Converted vert 2 again to (%f, %f, %f)\", uvprojections[2][X], uvprojections[2][Y], uvprojections[2][Z]);\r\n#endif\r\n\r\n\t\t\t// Check that they are in the frustum\r\n//\t\t\tif(( uvprojections[0][X] < -1.0f ) && ( uvprojections[1][X] < -1.0f ) && ( uvprojections[2][X] < -1.0f ))\r\n//\t\t\t\tcontinue;\r\n//\t\t\tif(( uvprojections[0][Y] < -1.0f ) && ( uvprojections[1][Y] < -1.0f ) && ( uvprojections[2][Y] < -1.0f ))\r\n//\t\t\t\tcontinue;\r\n//\t\t\tif(( uvprojections[0][X] > 1.0f ) && ( uvprojections[1][X] > 1.0f ) && ( uvprojections[2][X] > 1.0f ))\r\n//\t\t\t\tcontinue;\r\n//\t\t\tif(( uvprojections[0][Y] > 1.0f ) && ( uvprojections[1][Y] > 1.0f ) && ( uvprojections[2][Y] > 1.0f ))\r\n//\t\t\t\tcontinue;\r\n\t\t\tif(( uvprojections[0][Z] < -1.0f ) && ( uvprojections[1][Z] < -1.0f ) && ( uvprojections[2][Z] < -1.0f ))\r\n\t\t\t\tcontinue;\r\n\t\t\tif(( uvprojections[0][Z] > 1.0f ) && ( uvprojections[1][Z] > 1.0f ) && ( uvprojections[2][Z] > 1.0f ))\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\t// Okay, this tri lies within the projection frustum. Now check that it intersects the texture\r\n\t\t\tif( !tri_texture_intersect( uvprojections[0][X], uvprojections[0][Y],\r\n\t\t\t\t\t\t\t\t\t\tuvprojections[1][X], uvprojections[1][Y],\r\n\t\t\t\t\t\t\t\t\t\tuvprojections[2][X], uvprojections[2][Y] ))\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t//Dbg_Message(\"Found splat poly vert 0 (%f, %f, %f) uv (%f, %f)\", v0[X], v0[Y], v0[Z], uvprojections[0][X], uvprojections[0][Y]);\r\n\t\t\t//Dbg_Message(\"Found splat poly vert 1 (%f, %f, %f) uv (%f, %f)\", v1[X], v1[Y], v1[Z], uvprojections[1][X], uvprojections[1][Y]);\r\n\t\t\t//Dbg_Message(\"Found splat poly vert 2 (%f, %f, %f) uv (%f, %f)\", v2[X], v2[Y], v2[Z], uvprojections[2][X], uvprojections[2][Y]);\r\n\r\n\t\t\t// Check if we have a line or point.  For some reason, the rendering code will crash\r\n\t\t\t// with this (I think it is the clipping).  Since we really don't want it anyways,\r\n\t\t\t// just skip them.\r\n\t\t\tint equal_axis = 0;\r\n\t\t\tif ((v0[X] == v1[X]) && (v1[X] == v2[X]))\tequal_axis++;\r\n\t\t\tif ((v0[Y] == v1[Y]) && (v1[Y] == v2[Y]))\tequal_axis++;\r\n\t\t\tif ((v0[Z] == v1[Z]) && (v1[Z] == v2[Z]))\tequal_axis++;\r\n\t\t\tif (equal_axis > 1)\r\n\t\t\t{\r\n\t\t\t\t//Dbg_Message(\"Skipping line poly...\");\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// Okay, this tri lies within the projection frustum. Get a pointer to the mesh used for rendering texture splats\r\n\t\t\t// with the given texture. (Note this will create a new instance to handle texture splats of this texture if one\r\n\t\t\t// does not already exist).\r\n\t\t\tif( p_target_verts == NULL )\r\n\t\t\t{\r\n\t\t\t\tp_details\t\t\t\t\t\t= getDetailsForTextureSplat(p_single_texture);\r\n\t\t\t\tif ( p_details == NULL )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tp_target_verts\t\t\t\t\t= p_details->m_verts;\r\n\t\t\t\tDbg_Assert( p_target_verts );\r\n\t\t\t}\r\n\r\n\t\t\t// If we have trails, scale up the mapping by one pixel in all directions.\r\n\t\t\t// (effectively 2 pixels in u and 2 pixels in v ).\r\n\t\t\tfloat up_one_u_pixel;\r\n\t\t\tfloat up_one_v_pixel;\r\n\t\t\tif( p_trail_details )\r\n\t\t\t{\r\n\t\t\t\tup_one_u_pixel = 1.0f - ( 1.0f / ( p_texture->GetWidth() / 2.0f ) );\r\n\t\t\t\tup_one_v_pixel = 1.0f - ( 1.0f / ( p_texture->GetHeight() / 2.0f ) );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tup_one_u_pixel = 1.0f;\r\n\t\t\t\tup_one_v_pixel = 1.0f;\r\n\t\t\t}\r\n\r\n\t\t\t// Scan through the lifetimes, finding a 'dead' poly (lifetime == 0), or the oldest.\r\n\t\t\tuint32 idx\t\t\t\t\t\t= p_details->GetOldestSplat();\r\n\r\n\t\t\t// Convert lifetime from seconds to milliseconds.\r\n\t\t\tp_details->m_lifetimes[idx]\t\t= (int)( lifetime * 1000.0f );\r\n\r\n\t\t\t// Set up the corresponding vertices. First write the positions.\r\n\t\t\tuint32 index\t\t\t\t\t= idx * 3;\r\n\t\t\tDbg_Assert((index + 2) < (SPLAT_POLYS_PER_MESH * 3));\r\n\t\t\tp_target_verts[index + 0].pos\t= v0;\r\n\t\t\tp_target_verts[index + 1].pos\t= v1;\r\n\t\t\tp_target_verts[index + 2].pos\t= v2;\r\n\t\t\t//p_target_verts[index + 0].pos[Y] += ( 12.0f * (float)rand() / RAND_MAX );\r\n\t\t\t//p_target_verts[index + 1].pos[Y] += ( 12.0f * (float)rand() / RAND_MAX );\r\n\t\t\t//p_target_verts[index + 2].pos[Y] += ( 12.0f * (float)rand() / RAND_MAX );\r\n\r\n\t\t\t// Then the uv's.\r\n\t\t\tp_target_verts[index + 0].u\t\t= ( (uvprojections[0][X] * 0.5f) + 0.5f ) * up_one_u_pixel;\r\n\t\t\tp_target_verts[index + 0].v\t\t= ( (uvprojections[0][Y] * 0.5f) + 0.5f ) * up_one_v_pixel;\r\n\t\t\tp_target_verts[index + 1].u\t\t= ( (uvprojections[1][X] * 0.5f) + 0.5f ) * up_one_u_pixel;\r\n\t\t\tp_target_verts[index + 1].v\t\t= ( (uvprojections[1][Y] * 0.5f) + 0.5f ) * up_one_v_pixel;\r\n\t\t\tp_target_verts[index + 2].u\t\t= ( (uvprojections[2][X] * 0.5f) + 0.5f ) * up_one_u_pixel;\r\n\t\t\tp_target_verts[index + 2].v\t\t= ( (uvprojections[2][Y] * 0.5f) + 0.5f ) * up_one_v_pixel;\r\n\r\n\t\t\t// Now the colors\r\n\t\t\tuint8 intensity0 = p_coll_geom->GetVertexIntensity(p_coll_geom->GetFaceVertIndex(*p_face_indexes, 0));\r\n\t\t\tuint8 intensity1 = p_coll_geom->GetVertexIntensity(p_coll_geom->GetFaceVertIndex(*p_face_indexes, 1));\r\n\t\t\tuint8 intensity2 = p_coll_geom->GetVertexIntensity(p_coll_geom->GetFaceVertIndex(*p_face_indexes, 2));\r\n\t\t\tp_target_verts[index + 0].col = Image::RGBA(intensity0, intensity0, intensity0, 0x80);\r\n\t\t\tp_target_verts[index + 1].col = Image::RGBA(intensity1, intensity1, intensity1, 0x80);\r\n\t\t\tp_target_verts[index + 2].col = Image::RGBA(intensity2, intensity2, intensity2, 0x80);\r\n\r\n\t\t\tMth::Vector\t*p_v0 = &( p_target_verts[index + 0].pos );\r\n\t\t\tMth::Vector\t*p_v1 = &( p_target_verts[index + 1].pos );\r\n\t\t\tMth::Vector\t*p_v2 = &( p_target_verts[index + 2].pos );\r\n\t\t\tMth::Vector pv(\tp_v1->GetX() - p_v0->GetX(), p_v1->GetY() - p_v0->GetY(), p_v1->GetZ() - p_v0->GetZ() );\r\n\t\t\tMth::Vector qv(\tp_v2->GetX() - p_v0->GetX(), p_v2->GetY() - p_v0->GetY(), p_v2->GetZ() - p_v0->GetZ() );\r\n\t\t\tMth::Vector r(( pv[Y] * qv[Z] ) - ( qv[Y] * pv[Z] ), ( pv[Z] * qv[X] ) - ( qv[Z] * pv[X] ), ( pv[X] * qv[Y] ) - ( qv[X] * pv[Y] ));\r\n\t\t\tfloat area_squared = r.LengthSqr();\r\n\r\n\t\t\t// Set the shatter test to ensure that we don't subdivide too far. Note that each successive subdivision will quarter\r\n\t\t\t// the area of each triangle, which means the area *squared* of each triangle will become 1/16th of the previous value.\r\n\t\t\tfloat shatterArea = area_squared / 128.0f;\r\n\r\n\t\t\ttriSubdivideStack.Clear();\r\n\t\t\ttriSubdivideStack.SetBlockSize( sizeof(sNGPSVert) );\r\n\t\t\ttriSubdivideStack.Push( &p_target_verts[index + 0] );\r\n\t\t\ttriSubdivideStack.Push( &p_target_verts[index + 1] );\r\n\t\t\ttriSubdivideStack.Push( &p_target_verts[index + 2] );\r\n\r\n\t\t\t// Allocate a block of memory into which the subdivision stack will write the results.\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\tsNGPSVert\t\t*p_array\t\t= new sNGPSVert[100];\r\n\t\t\tsNGPSVert\t\t*p_array_start\t= p_array;\r\n\t\t\tsNGPSVert\t\t*p_array_loop\t= p_array;\r\n\t\t\t//memset( p_array, 0, sizeof(sNGPSVert) * 100 );\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t\twhile( subdivide_tri_stack( shatterArea, &p_array, NULL ));\r\n\r\n\t\t\t// Ensure we haven't overrun the buffer.\r\n\t\t\tDbg_Assert((uint32)p_array - (uint32)p_array_loop < ( sizeof(sNGPSVert) * 100 ));\r\n\r\n\t\t\tfloat oo_up_one_u_pixel = 1.0f / up_one_u_pixel;\r\n\t\t\tfloat oo_up_one_v_pixel = 1.0f / up_one_v_pixel;\r\n\r\n//\t\t\tint vert_idx = 0;\r\n\t\t\tbool no_polys = true;\r\n\r\n\t\t\twhile( p_array_loop != p_array )\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert(((uint32) p_array_loop) < ((uint32) p_array));\r\n//\t\t\t\tDbg_Message(\"Looking at vert %d\", vert_idx);\r\n\t\t\t\t// Add this triangle, *if* it is valid.\r\n\t\t\t\tif( tri_texture_intersect(((p_array_loop[0].u * oo_up_one_u_pixel) - 0.5f) * 2.0f,\r\n\t\t\t\t\t\t\t\t\t\t  ((p_array_loop[0].v * oo_up_one_v_pixel) - 0.5f) * 2.0f,\r\n\t\t\t\t\t\t\t\t\t\t  ((p_array_loop[1].u * oo_up_one_u_pixel) - 0.5f) * 2.0f,\r\n\t\t\t\t\t\t\t\t\t\t  ((p_array_loop[1].v * oo_up_one_v_pixel) - 0.5f) * 2.0f,\r\n\t\t\t\t\t\t\t\t\t\t  ((p_array_loop[2].u * oo_up_one_u_pixel) - 0.5f) * 2.0f,\r\n\t\t\t\t\t\t\t\t\t\t  ((p_array_loop[2].v * oo_up_one_v_pixel) - 0.5f) * 2.0f ))\r\n//\t\t\t\tif( tri_texture_intersect((p_array_loop[0].u * 2.0f * oo_up_one_u_pixel) - 1.0f,\r\n//\t\t\t\t\t\t\t\t\t\t  (p_array_loop[0].v * 2.0f * oo_up_one_v_pixel) - 1.0f,\r\n//\t\t\t\t\t\t\t\t\t\t  (p_array_loop[1].u * 2.0f * oo_up_one_u_pixel) - 1.0f,\r\n//\t\t\t\t\t\t\t\t\t\t  (p_array_loop[1].v * 2.0f * oo_up_one_v_pixel) - 1.0f,\r\n//\t\t\t\t\t\t\t\t\t\t  (p_array_loop[2].u * 2.0f * oo_up_one_u_pixel) - 1.0f,\r\n//\t\t\t\t\t\t\t\t\t\t  (p_array_loop[2].v * 2.0f * oo_up_one_v_pixel) - 1.0f ))\r\n\t\t\t\t{\r\n//\t\t\t\t\tDbg_Message(\"Accepted vert %d\", vert_idx);\r\n\t\t\t\t\t// Convert lifetime from seconds to milliseconds.\r\n\t\t\t\t\tp_details->m_lifetimes[idx]\t\t= (int)( lifetime * 1000.0f );\r\n\r\n\t\t\t\t\tp_target_verts[index + 0].pos\t= p_array_loop[0].pos;\r\n\t\t\t\t\tp_target_verts[index + 1].pos\t= p_array_loop[1].pos;\r\n\t\t\t\t\tp_target_verts[index + 2].pos\t= p_array_loop[2].pos;\r\n\r\n\t\t\t\t\tp_target_verts[index + 0].u\t\t= p_array_loop[0].u;\r\n\t\t\t\t\tp_target_verts[index + 0].v\t\t= p_array_loop[0].v;\r\n\t\t\t\t\tp_target_verts[index + 1].u\t\t= p_array_loop[1].u;\r\n\t\t\t\t\tp_target_verts[index + 1].v\t\t= p_array_loop[1].v;\r\n\t\t\t\t\tp_target_verts[index + 2].u\t\t= p_array_loop[2].u;\r\n\t\t\t\t\tp_target_verts[index + 2].v\t\t= p_array_loop[2].v;\r\n\r\n\t\t\t\t\tp_target_verts[index + 0].col\t= p_array_loop[0].col;\r\n\t\t\t\t\tp_target_verts[index + 1].col\t= p_array_loop[1].col;\r\n\t\t\t\t\tp_target_verts[index + 2].col\t= p_array_loop[2].col;\r\n\r\n\t\t\t\t\tidx\t\t\t\t\t\t\t\t= p_details->GetOldestSplat();\r\n\t\t\t\t\tindex\t\t\t\t\t\t\t= idx * 3;\r\n\t\t\t\t\tDbg_Assert((index + 2) < (SPLAT_POLYS_PER_MESH * 3));\r\n\t\t\t\t\tno_polys \t\t\t\t\t\t= false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tp_array_loop\t\t\t\t\t+= 3;\r\n//\t\t\t\tvert_idx++;\r\n\t\t\t}\r\n\r\n\t\t\tdelete [] p_array_start;\r\n\r\n\t\t\t// Check if all the new polys were rejected.  Don't know why this happens, but we want\r\n\t\t\t// to get rid of the original texture.\r\n\t\t\tif (no_polys)\r\n\t\t\t{\r\n\t\t\t\tplat_texture_splat_reset_poly( p_details, idx );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_texture_splat_render( void )\r\n{\r\n\tsNGPSSplatInstanceDetails *p_ngps_details;\r\n\r\n\tDbg_Assert( p_splat_details_table );\r\n\r\n\tp_splat_details_table->IterateStart();\r\n\tsSplatInstanceDetails *p_details = p_splat_details_table->IterateNext();\r\n\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\r\n\tbool set_zpush = (p_details != NULL);\r\n\tif (set_zpush)\r\n\t{\r\n\t\tNxPs2::CImmediateMode::sSetZPush(24.0f);\r\n\t}\r\n\r\n\twhile( p_details )\r\n\t{\r\n\r\n\t\t// See if we have anything to draw first\r\n\t\tif (p_details->m_highest_active_splat >= 0)\r\n\t\t{\r\n\t\t\tp_ngps_details = static_cast<sNGPSSplatInstanceDetails*>( p_details );\r\n\r\n\t\t\t// Init drawing, since we know we have to draw\r\n#if 1\r\n\t\t\tNxPs2::CImmediateMode::sStartPolyDraw(p_ngps_details->mp_texture, PackALPHA(0,1,0,1,0), ABS, true);\r\n#else\r\n\t\t\tif ((Tmr::GetVblanks() % 600) < 300)\r\n\t\t\t{\r\n\t\t\t\tNxPs2::CImmediateMode::sStartPolyDraw(p_ngps_details->mp_texture, PackALPHA(0,0,0,0,0), ABS, true);\r\n\t\t\t} else {\r\n\t\t\t\tNxPs2::CImmediateMode::sStartPolyDraw(p_ngps_details->mp_texture, PackALPHA(0,0,0,0,0), ABS, false);\r\n\t\t\t}\r\n#endif\r\n\r\n\t\t\t// Render the triangles\r\n\t\t\tsNGPSVert *p_vert_array = p_ngps_details->m_verts;\r\n\t\t\tfor (int i = 0; i <= p_details->m_highest_active_splat; i++, p_vert_array += 3)\r\n\t\t\t{\r\n\t\t\t\tNxPs2::CImmediateMode::sDrawTriUV(p_vert_array[0].pos, p_vert_array[1].pos, p_vert_array[2].pos,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  p_vert_array[0].u, p_vert_array[0].v,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  p_vert_array[1].u, p_vert_array[1].v,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  p_vert_array[2].u, p_vert_array[2].v,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  *((uint32 *) &p_vert_array[0].col),\r\n\t\t\t\t\t\t\t\t\t\t\t\t  *((uint32 *) &p_vert_array[1].col),\r\n\t\t\t\t\t\t\t\t\t\t\t\t  *((uint32 *) &p_vert_array[2].col),\r\n\t\t\t\t\t\t\t\t\t\t\t\t  ABS);\r\n\r\n#if DRAW_DEBUG_LINES\r\n\t\t\t\tGfx::AddDebugLine( p_vert_array[0].pos, p_vert_array[1].pos, MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\t\tGfx::AddDebugLine( p_vert_array[1].pos, p_vert_array[2].pos, MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\t\tGfx::AddDebugLine( p_vert_array[2].pos, p_vert_array[0].pos, MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n#endif\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tp_details = p_splat_details_table->IterateNext();\r\n\t}\r\n\r\n\tif (set_zpush)\r\n\t{\r\n\t\tNxPs2::CImmediateMode::sClearZPush();\r\n\t}\r\n\r\n\tNxPs2::dma::EndTag();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_shatter_initialize( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_shatter_cleanup( void )\r\n{\r\n\tsNGPSShatterInstanceDetails *p_ngps_details;\r\n\r\n\tDbg_Assert( p_shatter_details_table );\r\n\t\r\n\tp_shatter_details_table->IterateStart();\r\n\tsShatterInstanceDetails *p_details = p_shatter_details_table->IterateNext();\r\n\twhile( p_details )\r\n\t{\r\n\t\tp_ngps_details = static_cast<sNGPSShatterInstanceDetails*>( p_details );\r\n\t\t\r\n\t\tp_details = p_shatter_details_table->IterateNext();\r\n\r\n\t\tp_shatter_details_table->FlushItem((uint32)p_ngps_details );\r\n\t\tdelete p_ngps_details;\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst int MAX_GEOM_NODES = 10;\r\n\r\nvoid find_geom_leaves( NxPs2::CGeomNode *p_node, NxPs2::CGeomNode **leaf_array, int & num_nodes)\r\n{\r\n\tif (p_node->IsLeaf())\r\n\t{\r\n\t\tDbg_Assert(num_nodes < MAX_GEOM_NODES);\r\n\r\n\t\tleaf_array[num_nodes++] = p_node;\r\n\t\treturn;\r\n\t} else {\r\n\t\tNxPs2::CGeomNode *p_child;\r\n\t\tfor (p_child = p_node->GetChild(); p_child; p_child = p_child->GetSibling())\r\n\t\t{\r\n\t\t\tfind_geom_leaves(p_child, leaf_array, num_nodes);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint get_num_extra_shatter_tris(float shatterArea, const Mth::Vector & pos0, const Mth::Vector & pos1, const Mth::Vector & pos2)\r\n{\r\n\tint num_extra_tris = 0;\r\n\r\n\t// Figure the area of this tri.\r\n\tMth::Vector p( pos1[X] - pos0[X], pos1[Y] - pos0[Y], pos1[Z] - pos0[Z], 0.0f );\r\n\tMth::Vector q( pos2[X] - pos0[X], pos2[Y] - pos0[Y], pos2[Z] - pos0[Z], 0.0f );\r\n\tMth::Vector r(( p[Y] * q[Z] ) - ( q[Y] * p[Z] ), ( p[Z] * q[X] ) - ( q[Z] * p[X] ), ( p[X] * q[Y] ) - ( q[X] * p[Y] ), 0.0f);\r\n\tfloat area_squared = r.LengthSqr();\r\n\r\n\tif( area_squared > shatterArea )\r\n\t{\r\n\t\t//Dbg_Message(\"Area of triangle: %f\", sqrtf(area_squared));\r\n\r\n\t\t// We will need to subdivide - each subdivision will result in an area one quarter the previous area\r\n\t\t// (and thusly the square of the area will be one sixteenth the previous area).\r\n\t\tnum_extra_tris = 1;\r\n\t\twhile( area_squared > shatterArea )\r\n\t\t{\r\n\t\t\tnum_extra_tris *= 4;\r\n\t\t\tarea_squared *= ( 1.0f / 16.0f );\r\n\t\t}\r\n\r\n\t\t// This original tri will not be added...\r\n\t\t// ...however, the subdivided versions will.\r\n\t\tnum_extra_tris--;\r\n\t\t//Dbg_Message(\"Adding %d triangles\", num_extra_tris);\r\n\t}\r\n\r\n\treturn num_extra_tris;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid plat_shatter( CGeom *p_geom )\r\n{\r\n\tCPs2Geom *p_ps2_geom = static_cast<CPs2Geom*>( p_geom );\r\n\tNxPs2::CGeomNode *p_root_node = p_ps2_geom->GetEngineObject();\r\n\tDbg_Assert(p_root_node);\r\n\r\n\t// Get Time of Day color\r\n\tImage::RGBA geom_rgba = Nx::CEngine::sGetMainScene()->GetMajorityColor();\r\n\r\n\t// Put all the meshes in an array\r\n\tint num_meshes = 0;\r\n\tNxPs2::CGeomNode *mesh_array[MAX_GEOM_NODES];\r\n\tfind_geom_leaves(p_root_node, mesh_array, num_meshes);\r\n\r\n\t// For each mesh in the geom...\r\n\tfor( int m = 0; m < num_meshes; ++m )\r\n\t{\r\n\t\tNxPs2::CGeomNode *p_node = mesh_array[m];\r\n\r\n\t\t// Since these are extra passes 99% of the time, Environment Mapped CGeomNodes are rejected\r\n\t\tif (p_node->IsEnvMapped())\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tuint8 *p_dma = p_node->GetDma();\r\n\r\n\t\tint num_verts = NxPs2::dma::GetNumVertices(p_dma);\r\n\t\tif( num_verts >= 3 )\r\n\t\t{\r\n\t\t\tbool short_xyz = (NxPs2::dma::GetBitLengthXYZ(p_dma) == 16);\r\n\t\t\tMth::Vector mesh_center = p_node->GetBoundingSphere();\r\n\r\n\t\t\t// Set the block size for this mesh.\r\n\t\t\ttriSubdivideStack.SetBlockSize( sizeof(sNGPSVert) );\r\n\r\n\t\t\t// Get DMA arrays\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\tsint32 *p_vert_array = new sint32[4 * num_verts];\r\n\t\t\tsint32 *p_uv_array = new sint32[2 * num_verts];\r\n\t\t\tuint32 *p_rgb_array = new uint32[num_verts];\r\n#if PRINT_SHATTER_MEMORY\r\n\t\t\tDbg_Message(\"Mesh #%d; Verts %d; CGeomNode pointer %x checksum %x\", m, num_verts, p_node, p_node->GetChecksum());\r\n\t\t\tDbg_Message(\"Allocating %d bytes temporarily for DMA\", 7 * num_verts * sizeof(uint32));\r\n#endif\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t\t// Copy DMA data\r\n\t\t\tNxPs2::dma::ExtractXYZs(p_dma, (uint8 *) p_vert_array);\r\n\t\t\tNxPs2::dma::ExtractSTs(p_dma, (uint8 *) p_uv_array);\r\n\t\t\tNxPs2::dma::ExtractRGBAs(p_dma, (uint8 *) p_rgb_array);\r\n\r\n\t\t\tDbg_Assert(p_vert_array[(0 * 4) + 3] & 0x8000);\r\n\t\t\tDbg_Assert(p_vert_array[(1 * 4) + 3] & 0x8000);\r\n\r\n\t\t\tsNGPSVert v0, v1, v2;\r\n\r\n\t\t\tif (short_xyz)\r\n\t\t\t{\r\n\t\t\t\tNxPs2::dma::ConvertXYZToFloat(v0.pos, &(p_vert_array[0 * 4]), mesh_center);\r\n\t\t\t\tNxPs2::dma::ConvertXYZToFloat(v1.pos, &(p_vert_array[1 * 4]), mesh_center);\r\n\t\t\t} else {\r\n\t\t\t\tNxPs2::dma::ConvertXYZToFloat(v0.pos, &(p_vert_array[0 * 4]));\r\n\t\t\t\tNxPs2::dma::ConvertXYZToFloat(v1.pos, &(p_vert_array[1 * 4]));\r\n\t\t\t}\r\n\t\t\tNxPs2::dma::ConvertSTToFloat(v0.u, v0.v, &(p_uv_array[0 * 2]));\r\n\t\t\tNxPs2::dma::ConvertSTToFloat(v1.u, v1.v, &(p_uv_array[1 * 2]));\r\n\r\n\t\t\tv0.col = *((Image::RGBA *) &(p_rgb_array[0]));\r\n\t\t\tv0.col.Blend128(geom_rgba);\r\n\t\t\tv1.col = *((Image::RGBA *) &(p_rgb_array[1]));\r\n\t\t\tv1.col.Blend128(geom_rgba);\r\n\r\n\t\t\tint orig_tris = 0;\r\n\t\t\tint valid_tris = 0;\r\n\r\n\t\t\t//Dbg_Message(\"Number of verts: %d\", num_verts);\r\n\r\n\t\t\tfor (int idx = 2; idx < num_verts; idx++)\r\n\t\t\t{\r\n\t\t\t\tif (short_xyz)\r\n\t\t\t\t{\r\n\t\t\t\t\tNxPs2::dma::ConvertXYZToFloat(v2.pos, &(p_vert_array[idx * 4]), mesh_center);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tNxPs2::dma::ConvertXYZToFloat(v2.pos, &(p_vert_array[idx * 4]));\r\n\t\t\t\t}\r\n\t\t\t\tNxPs2::dma::ConvertSTToFloat(v2.u, v2.v, &(p_uv_array[idx * 2]));\r\n\t\t\t\tv2.col = *((Image::RGBA *) &(p_rgb_array[idx]));\r\n\t\t\t\tv2.col.Blend128(geom_rgba);\r\n\r\n\t\t\t\t// Dont make triangle if vert has ADC bit set\r\n\t\t\t\tif (!(p_vert_array[(idx * 4) + 3] & 0x8000))\t\t// if adc bit not set\r\n\t\t\t\t{\r\n\t\t\t\t\torig_tris++;\r\n\t\t\t\t\tvalid_tris++;\r\n\r\n\t\t\t\t\t// Push this tri onto the stack.\r\n\t\t\t\t\ttriSubdivideStack.Push( &v0 );\r\n\t\t\t\t\ttriSubdivideStack.Push( &v1 );\r\n\t\t\t\t\ttriSubdivideStack.Push( &v2 );\r\n\r\n\t\t\t\t\t//Dbg_Message(\"Triangle (%f, %f, %f, %f) - (%f, %f, %f, %f) - (%f, %f, %f, %f)\", v0.pos[X], v0.pos[Y], v0.pos[Z], v0.pos[W],\r\n\t\t\t\t\t//\t\t\t v1.pos[X], v1.pos[Y], v1.pos[Z], v1.pos[W], v2.pos[X], v2.pos[Y], v2.pos[Z], v2.pos[W]);\r\n\t\t\t\t\t//Dbg_Message(\"UVs (%f, %f) - (%f, %f) - (%f, %f)\", v0.u, v0.v, v1.u, v1.v, v2.u, v2.v);\r\n\t\t\t\t\t//Dbg_Message(\"Colors (%d, %d, %d, %d) - (%d, %d, %d, %d) - (%d, %d, %d, %d)\", v0.col.r, v0.col.g, v0.col.b, v0.col.a,\r\n\t\t\t\t\t//\t\t\t v1.col.r, v1.col.g, v1.col.b, v1.col.a, v2.col.r, v2.col.g, v2.col.b, v2.col.a);\r\n\r\n\t\t\t\t\t// Add extra triangles that we need\r\n\t\t\t\t\tvalid_tris += get_num_extra_shatter_tris(shatterAreaTest, v0.pos, v1.pos, v2.pos);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tv0 = v1;\r\n\t\t\t\tv1 = v2;\r\n\t\t\t}\r\n\r\n\t\t\t// Free DMA buffers\r\n\t\t\tdelete [] p_vert_array;\r\n\t\t\tdelete [] p_uv_array;\r\n\t\t\tdelete [] p_rgb_array;\r\n\r\n\t\t\tif( valid_tris == 0 )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tfloat newShatterArea = shatterAreaTest;\r\n\r\n\t\t\t// Make sure there is memory available and that we don't take it all\r\n\t\t\tint free_mem = Mem::Available();\r\n\t\t\tint needed_mem = (sNGPSShatterInstanceDetails::sQueryMemoryNeeded(valid_tris) * 3) / 2; \r\n\t\t\tif (free_mem < needed_mem)\r\n\t\t\t{\r\n\t\t\t\t// Calculate how much bigger we need to make the area\r\n\t\t\t\tDbg_Message(\"Old needed memory %d free memory %d for %d tris\", needed_mem, free_mem, valid_tris);\r\n\t\t\t\tfloat mem_ratio = ((float) needed_mem) / ((float) free_mem);\r\n\t\t\t\tint iratio = (int) (mem_ratio + 0.99f);\t\t// Round up\r\n\t\t\t\tiratio = (iratio + 3) & ~3;\t\t\t\t\t// Round up to the nearest divisible by 4\r\n\t\t\t\tnewShatterArea = newShatterArea * (iratio * iratio);\t// And square the ratio\r\n\r\n\t\t\t\tDbg_Message(\"mem ratio %f iratio %d\", mem_ratio, iratio);\r\n\r\n\t\t\t\tconst Mth::Vector *pos0, *pos1, *pos2;\r\n\t\t\t\tvalid_tris = orig_tris;\r\n\t\t\t\tfor (int idx = 0; idx < orig_tris; idx++)\r\n\t\t\t\t{\r\n\t\t\t\t\tpos0 = &(((const sNGPSVert *) triSubdivideStack.Peek((idx * 3) + 0))->pos);\r\n\t\t\t\t\tpos1 = &(((const sNGPSVert *) triSubdivideStack.Peek((idx * 3) + 1))->pos);\r\n\t\t\t\t\tpos2 = &(((const sNGPSVert *) triSubdivideStack.Peek((idx * 3) + 2))->pos);\r\n\t\t\t\t   \r\n\t\t\t\t\t// Add extra triangles that we need\r\n\t\t\t\t\tvalid_tris += get_num_extra_shatter_tris(newShatterArea, *pos0, *pos1, *pos2);\r\n\t\t\t\t}\r\n\t\t\t\tneeded_mem = (sNGPSShatterInstanceDetails::sQueryMemoryNeeded(valid_tris) * 3) / 2; \r\n\t\t\t\tDbg_Message(\"New needed memory %d free memory %d for %d tris\", needed_mem, free_mem, valid_tris);\r\n\r\n\t\t\t\t// See if this one is smaller, otherwise, give up\r\n\t\t\t\tif (free_mem < needed_mem)\r\n\t\t\t\t{\r\n\t\t\t\t\ttriSubdivideStack.Clear();\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tDbg_Message(\"Increased shatter area from %f to %f\", shatterAreaTest, newShatterArea);\r\n\t\t\t}\r\n\r\n\t\t\t//Dbg_Message(\"Making %d triangles\", valid_tris);\r\n\r\n\t\t\t// Create a tracking structure for this mesh.\r\n\t\t\tsNGPSShatterInstanceDetails *p_details\t\t= new sNGPSShatterInstanceDetails( valid_tris, p_node );\r\n\t\t\tsNGPSVert\t \t\t\t\t*p_write_vertex\t= p_details->mp_vert_array;\r\n\t\t\tuint32\t\t\t\t\t\tdetails_index\t= 0;\r\n\r\n#if PRINT_SHATTER_MEMORY\r\n\t\t\tDbg_Message(\"Allocated %d bytes for shatter of %d tris\", sNGPSShatterInstanceDetails::sQueryMemoryNeeded(valid_tris), valid_tris);\r\n#endif\r\n\r\n\t\t\tMth::Vector\t\t\t\t\tspread_center\t= shatterVelocity * -shatterSpreadFactor;\r\n\t\t\tfloat\t\t\t\t\t\tbase_speed\t\t= shatterVelocity.Length();\r\n\r\n\t\t\tspread_center[X] += mesh_center[X];\r\n\t\t\tspread_center[Y] += mesh_center[Y];\r\n\t\t\tspread_center[Z] += mesh_center[Z];\r\n\t\t\tspread_center[W] = 1.0f;\r\n\t\t\t\r\n\t\t\t// Add the tracking structure to the table.\r\n\t\t\tp_shatter_details_table->PutItem((uint32)p_details, p_details );\r\n\t\t\t\r\n\t\t\t// Process-subdivide the entire stack.\r\n\t\t\tsNGPSVert *p_copy_vertex = p_write_vertex;\r\n\t\t\twhile( subdivide_tri_stack( newShatterArea, &p_write_vertex, p_node ));\r\n\r\n\t\t\t// Copy the (possibly subdivided) vertex data over.\r\n\t\t\twhile( p_copy_vertex < p_write_vertex )\r\n\t\t\t{\r\n\t\t\t\tMth::Vector *p_vert0 = &((p_copy_vertex + 0)->pos);\r\n\t\t\t\tMth::Vector *p_vert1 = &((p_copy_vertex + 1)->pos);\r\n\t\t\t\tMth::Vector *p_vert2 = &((p_copy_vertex + 2)->pos);\r\n\t\t\t\t\r\n\t\t\t\t// Calculate position as the midpoint of the three vertices per poly.\r\n\t\t\t\tp_details->mp_positions[details_index][X] = ( p_vert0->GetX() + p_vert1->GetX() + p_vert2->GetX() ) * ( 1.0f / 3.0f );\r\n\t\t\t\tp_details->mp_positions[details_index][Y] = ( p_vert0->GetY() + p_vert1->GetY() + p_vert2->GetY() ) * ( 1.0f / 3.0f );\r\n\t\t\t\tp_details->mp_positions[details_index][Z] = ( p_vert0->GetZ() + p_vert1->GetZ() + p_vert2->GetZ() ) * ( 1.0f / 3.0f );\r\n\t\t\t\tp_details->mp_positions[details_index][W] = 1.0f;\r\n\r\n\t\t\t\t// Calculate the vector <velocity> back from the bounding box of the object. Then use this to figure the 'spread' of the\r\n\t\t\t\t// shards by calculating the vector from this position to the center of each shard.\r\n\t\t\t\tfloat speed = base_speed + ( base_speed * (( shatterVelocityVariance * rand() ) / RAND_MAX ));\r\n\t\t\t\tp_details->mp_velocities[details_index] = ( p_details->mp_positions[details_index] - spread_center ).Normalize( speed );\r\n\r\n\t\t\t\tMth::Vector axis( -1.0f + ( 2.0f * (float)rand() / RAND_MAX ), -1.0f + ( 2.0f * (float)rand() / RAND_MAX ), -1.0f + ( 2.0f * (float)rand() / RAND_MAX ), 0.0f);\r\n\t\t\t\taxis.Normalize();\r\n\t\t\t\tp_details->mp_matrices[details_index].Ident();\r\n\t\t\t\tp_details->mp_matrices[details_index].Rotate( axis, 0.1f * ((float)rand() / RAND_MAX ));\r\n\r\n\t\t\t\tp_copy_vertex += 3;\r\n\t\t\t\t//p_copy_u += 3;\r\n\t\t\t\t//p_copy_v += 3;\r\n\t\t\t\t\t\t\r\n\t\t\t\t++details_index;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n}\r\n\r\n\r\n\r\n/******************************************************************************\r\n *\r\n * \r\n *****************************************************************************/\r\nvoid plat_shatter_update( sShatterInstanceDetails *p_details, float framelength )\r\n{\r\n\tsNGPSShatterInstanceDetails *p_ps2_details = static_cast<sNGPSShatterInstanceDetails*>( p_details );\r\n\t\r\n\t// Load up initial three vertex pointers.\r\n\tsNGPSVert *p_v0\t= p_ps2_details->mp_vert_array;\r\n\tsNGPSVert *p_v1\t= p_ps2_details->mp_vert_array + 1;\r\n\tsNGPSVert *p_v2\t= p_ps2_details->mp_vert_array + 2;\r\n\t\r\n\tfor( int i = 0; i < p_details->m_num_triangles; ++i )\r\n\t{\r\n\t\t// To move the shatter pieces:\r\n\t\t// 1) subtract position from each vertex\r\n\t\t// 2) rotate\r\n\t\t// 3) update position with velocity\r\n\t\t// 4) add new position to each vertex\r\n\r\n\t\t// The matrix holds 3 vectors at once.\r\n\t\tMth::Matrix m;\r\n\t\tm[X].Set( p_v0->pos[X] - p_details->mp_positions[i][X], p_v0->pos[Y] - p_details->mp_positions[i][Y], p_v0->pos[Z] - p_details->mp_positions[i][Z] );\r\n\t\tm[Y].Set( p_v1->pos[X] - p_details->mp_positions[i][X], p_v1->pos[Y] - p_details->mp_positions[i][Y], p_v1->pos[Z] - p_details->mp_positions[i][Z] );\r\n\t\tm[Z].Set( p_v2->pos[X] - p_details->mp_positions[i][X], p_v2->pos[Y] - p_details->mp_positions[i][Y], p_v2->pos[Z] - p_details->mp_positions[i][Z] );\r\n         \r\n\t\tm[X].Rotate( p_details->mp_matrices[i] );\r\n\t\tm[Y].Rotate( p_details->mp_matrices[i] );\r\n\t\tm[Z].Rotate( p_details->mp_matrices[i] );\r\n\r\n\t\t// Update the position and velocity of the shatter piece, dealing with bouncing if necessary.\r\n\t\tp_details->UpdateParameters( i, framelength );\r\n      \r\n\t\tm[X] += p_details->mp_positions[i]; \r\n\t\tm[Y] += p_details->mp_positions[i]; \r\n\t\tm[Z] += p_details->mp_positions[i];\r\n\r\n\t\tp_v0->pos[X] = m[X][X]; p_v0->pos[Y] = m[X][Y]; p_v0->pos[Z] = m[X][Z];\r\n\t\tp_v1->pos[X] = m[Y][X]; p_v1->pos[Y] = m[Y][Y]; p_v1->pos[Z] = m[Y][Z];\r\n\t\tp_v2->pos[X] = m[Z][X]; p_v2->pos[Y] = m[Z][Y]; p_v2->pos[Z] = m[Z][Z];\r\n\r\n\t\tp_v0 = p_v0 + 3;\r\n\t\tp_v1 = p_v1 + 3;\r\n\t\tp_v2 = p_v2 + 3;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************************\r\n *\r\n * \r\n *****************************************************************************/\r\nvoid plat_shatter_render( sShatterInstanceDetails *p_details )\r\n{\r\n\t//Dbg_Message(\"In plat_shatter_render()\");\r\n\tsNGPSShatterInstanceDetails *p_ps2_details = static_cast<sNGPSShatterInstanceDetails*>( p_details );\r\n\r\n\tDbg_Assert( p_ps2_details );\r\n\r\n\tif (p_ps2_details->m_num_triangles == 0)\r\n\t\treturn;\r\n\r\n\tbool textured = (p_ps2_details->mp_tex_regs != NULL);\r\n\tif (textured)\r\n\t{\r\n\t\tNxPs2::sGroup *p_group = p_ps2_details->mp_geom_node->GetGroup();\r\n\t\tNxPs2::dma::SetList(p_group);\r\n\t\tp_group->Used[NxPs2::render::Field] = true;\r\n\t\tp_ps2_details->mp_geom_node->GetTexture()->m_render_count++;\r\n\t}\r\n\r\n\tMth::Vector sort_pos = p_ps2_details->mp_vert_array[0].pos;\t\t\t// just use 1st vert of 1st tri\r\n\tsort_pos *= NxPs2::render::WorldToCamera;\r\n\tsort_pos[2] = -1000.0f;\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, *(uint32 *)&sort_pos[2]);\t\t// z-sort key\r\n\tNxPs2::vif::BASE(NxPs2::vu1::Loc);\r\n\tNxPs2::vif::OFFSET(0);\r\n\tuint vu1_loc = NxPs2::vu1::Loc;\r\n\tNxPs2::vu1::Loc = 0;\t\t\t\t\t\t// must do this as a relative prim for a sortable list...\r\n\r\n\tif (textured)\r\n\t{\r\n\t\tNxPs2::CImmediateMode::sTextureGroupInit(REL);\r\n\t\tNxPs2::CImmediateMode::sStartPolyDraw(p_ps2_details->mp_tex_regs, p_ps2_details->m_num_tex_regs, REL, false);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNxPs2::CImmediateMode::sStartPolyDraw(NULL, PackALPHA(0,1,0,1,0), REL, false);\r\n\t}\r\n\r\n\t// Render the triangles\r\n\tsNGPSVert *p_vert_array = p_ps2_details->mp_vert_array;\r\n\tfor (int i = 0; i < p_ps2_details->m_num_triangles; i++, p_vert_array += 3)\r\n\t{\r\n\t\tif (textured)\r\n\t\t{\r\n\t\t\tNxPs2::CImmediateMode::sDrawTriUV(p_vert_array[0].pos, p_vert_array[1].pos, p_vert_array[2].pos,\r\n\t\t\t\t\t\t\t\t\t\t\t  p_vert_array[0].u, p_vert_array[0].v,\r\n\t\t\t\t\t\t\t\t\t\t\t  p_vert_array[1].u, p_vert_array[1].v,\r\n\t\t\t\t\t\t\t\t\t\t\t  p_vert_array[2].u, p_vert_array[2].v,\r\n\t\t\t\t\t\t\t\t\t\t\t  *((uint32 *) &p_vert_array[0].col),\r\n\t\t\t\t\t\t\t\t\t\t\t  *((uint32 *) &p_vert_array[1].col),\r\n\t\t\t\t\t\t\t\t\t\t\t  *((uint32 *) &p_vert_array[2].col),\r\n\t\t\t\t\t\t\t\t\t\t\t  REL);\r\n\t\t} else {\r\n\t\t\tNxPs2::CImmediateMode::sDrawTri(p_vert_array[0].pos, p_vert_array[1].pos, p_vert_array[2].pos,\r\n\t\t\t\t\t\t\t\t\t\t\t*((uint32 *) &p_vert_array[0].col),\r\n\t\t\t\t\t\t\t\t\t\t\t*((uint32 *) &p_vert_array[1].col),\r\n\t\t\t\t\t\t\t\t\t\t\t*((uint32 *) &p_vert_array[2].col),\r\n\t\t\t\t\t\t\t\t\t\t\tREL);\r\n\t\t}\r\n\r\n// this may break if put back in...\r\n//#if DRAW_DEBUG_LINES\r\n//\t\tGfx::AddDebugLine( p_vert_array[0].pos, p_vert_array[1].pos, MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n//\t\tGfx::AddDebugLine( p_vert_array[1].pos, p_vert_array[2].pos, MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n//\t\tGfx::AddDebugLine( p_vert_array[2].pos, p_vert_array[0].pos, MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n//#endif\r\n\t}\r\n\r\n\tNxPs2::dma::EndTag();\r\n\t((uint16 *)NxPs2::dma::pTag)[1] |= NxPs2::vu1::Loc & 0x3FF;\t// must write some code for doing this automatically\r\n\tNxPs2::vu1::Loc += vu1_loc;\r\n\r\n\tif (p_ps2_details->mp_geom_node->GetGroup()->flags & GROUPFLAG_SORT)\r\n\t{\r\n\t\tNxPs2::dma::Tag(NxPs2::dma::cnt,0,0);\r\n\t\tNxPs2::vif::NOP();\r\n\t\tNxPs2::vif::NOP();\r\n\t\tNxPs2::dma::SetList(NULL);\r\n\t}\r\n\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////\r\n//\r\n// FOG\r\n//\r\n///////////////////////////////////////////////////////////////////\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCFog::s_plat_enable_fog(bool enable)\r\n{\r\n\tNxPs2::render::EnableFog = enable;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCFog::s_plat_set_fog_near_distance(float distance)\r\n{\r\n\tNxPs2::render::FogNear = distance;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCFog::s_plat_set_fog_exponent(float exponent)\r\n{\r\n\tDbg_Message(\"Stub: CFog::SetFogExponent()\");\r\n\t//NxPs2::Fx::SetupFogPalette(*((unsigned int *) &m_rgba), exponent);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCFog::s_plat_set_fog_rgba(Image::RGBA rgba)\r\n{\r\n\t//NxPs2::Fx::SetupFogPalette(*((unsigned int *) &rgba), m_exponent);\r\n\r\n\t// Set alpha (and clamp between 0.0 and 1.0)\r\n\tfloat f_alpha = (float) rgba.a / 128.0f;\r\n\tf_alpha = Mth::Min(f_alpha, 1.0f);\r\n\tf_alpha = Mth::Max(f_alpha, 0.0f);\r\n\tNxPs2::render::FogAlpha = f_alpha;\r\n\r\n\t// Set color\r\n\tNxPs2::render::FogCol = *((uint32 *) &rgba) & 0xFFFFFF;\t// mask out alpha\r\n}\r\n\r\nvoid\t\tCFog::s_plat_set_fog_color( void )\r\n{\r\n\t// Doesn't need to do anything on PS2.\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CFog::s_plat_fog_update( void )\r\n{\r\n}\r\n\t\r\n\r\n\r\n} // Nx\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxnewparticle.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_NxNewParticle.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/25/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPS2 new parametric particle system\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <gfx/ngps/p_NxNewParticle.h>\r\n#include <gfx/ngps/nx/group.h>\r\n#include <gfx/ngps/nx/texture.h>\r\n#include <gfx/ngps/nx/dma.h>\r\n#include <gfx/ngps/nx/vif.h>\r\n#include <gfx/ngps/nx/gs.h>\r\n#include <gfx/nx.h>\r\n\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tCPs2NewParticle::plat_render( void )\r\n{\r\n\tCParticleStream *p_stream;\r\n\tint i;\r\n\r\n\t//--------------------------------------------------------------------------------------------------------------------\r\n\t// process the streams\r\n\tif (m_params.m_EmitRate && (!m_emitting || (m_params.m_EmitRate != mp_newest_stream->m_rate)))\r\n\t{\t\r\n\t\tif (m_num_streams < m_max_streams)\r\n\t\t{\r\n\t\t\t// add new stream to cyclic buffer\r\n\t\t\tm_num_streams++;\r\n\t\t\tmp_newest_stream++;\r\n\t\t\tif (mp_newest_stream == mp_stream + m_max_streams)\r\n\t\t\t{\r\n\t\t\t\tmp_newest_stream = mp_stream;\r\n\t\t\t}\r\n\r\n\t\t\t// initialise new stream\r\n\t\t\tmp_newest_stream->m_rate\t\t\t= m_params.m_EmitRate;\r\n\t\t\tmp_newest_stream->m_interval\t\t= 1.0f/m_params.m_EmitRate;\r\n\t\t\tmp_newest_stream->m_oldest_age\t\t= 0.0f;\r\n\t\t\tmp_newest_stream->m_num_particles\t= 0;\r\n\t\t\tmp_newest_stream->m_seed[0]\t\t\t= rand();\r\n\t\t\tmp_newest_stream->m_seed[1]\t\t\t= rand();\r\n\t\t\tmp_newest_stream->m_seed[2]\t\t\t= rand();\r\n\t\t\tmp_newest_stream->m_seed[3]\t\t\t= rand();\r\n\t\t\tm_emitting = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_emitting = false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_emitting = m_params.m_EmitRate;\r\n\t}\r\n\r\n\tif (!m_num_streams)\r\n\t\treturn;\r\n\r\n\t// age all streams\r\n\tfor (i=0, p_stream=mp_oldest_stream; i<m_num_streams; i++)\r\n\t{\r\n\t\t// increase age of oldest particle\r\n\t\tp_stream->m_oldest_age += 1.0f/60.0f;\r\n\r\n\t\t// step pointer within cyclic buffer\r\n\t\tp_stream++;\r\n\t\tif (p_stream == mp_stream + m_max_streams)\r\n\t\t{\r\n\t\t\tp_stream = mp_stream;\r\n\t\t}\r\n\t}\r\n\r\n\t// births into newest stream\r\n\tif (m_emitting)\r\n\t{\r\n\t\t// how many particles so far emitted?\r\n\t\tmp_newest_stream->m_num_particles = (int)(mp_newest_stream->m_oldest_age * mp_newest_stream->m_rate + 1.0f);\r\n\t}\r\n\r\n\t// deaths from oldest stream\r\n\tif (mp_oldest_stream->m_oldest_age > m_params.m_Lifetime)\r\n\t{\r\n\t\t// work out number dead\r\n\t\tint particles_dead = (int)((mp_oldest_stream->m_oldest_age - m_params.m_Lifetime) * mp_oldest_stream->m_rate + 1.0f);\r\n\r\n\t\t// remove dead particles\r\n\t\tmp_oldest_stream->m_num_particles -= particles_dead;\r\n\r\n\t\t// should we keep processing the oldest stream?\r\n\t\tif (mp_oldest_stream->m_num_particles>0 || (m_num_streams==1 && m_emitting))\r\n\t\t{\r\n\t\t\t// adjust age of oldest particle\r\n\t\t\tmp_oldest_stream->m_oldest_age -= (float)particles_dead * mp_oldest_stream->m_interval;\r\n\r\n\t\t\t// advance seed\r\n\t\t\tmp_oldest_stream->AdvanceSeed(particles_dead);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// remove oldest stream and wrap in cyclic buffer if necessary\r\n\t\t\tm_num_streams--;\r\n\t\t\tmp_oldest_stream++;\r\n\t\t\tif (mp_oldest_stream == mp_stream + m_max_streams)\r\n\t\t\t{\r\n\t\t\t\tmp_oldest_stream = mp_stream;\r\n\t\t\t}\r\n\t\t\tif (!m_num_streams)\r\n\t\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t//--------------------------------------------------------------------------------------------------------------------\r\n\t// now render the streams\r\n\r\n\tif (mp_engine_texture)\r\n\t{\r\n\t\t// Mick:  If this is textured, we reset the TEX0, TEX1 regs as the texture might move\r\n\t\t// Since 2D textures are dynamically packed every frame\r\n\t\t*(uint64 *)&m_systemDmaData.m_GScontext[8] = mp_engine_texture->m_RegTEX0;\r\n\t\t*(uint64 *)&m_systemDmaData.m_GScontext[12] = mp_engine_texture->m_RegTEX1;\r\n\t}\r\n\r\n\t// FOG\r\n\tMth::Vector x = 0.5f * (m_params.m_BoxPos[0] + m_params.m_BoxPos[2]);\r\n\tx[3] = 1.0f;\r\n\tx *= NxPs2::render::WorldToFrustum;\r\n\tfloat f;\r\n\tif ((x[3] > NxPs2::render::FogNear) && NxPs2::render::EnableFog)\t// Garrett: We have to check for EnableFog here because the VU1 code isn't\r\n\t{\r\n\t\tf = 1.0 + NxPs2::render::EffectiveFogAlpha * (NxPs2::render::FogNear/x[3] - 1.0f);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tf = 1.0f;\r\n\t}\r\n\tm_systemDmaData.m_GScontext[21] = ((uint32)(int)(f*255.99f)) << 24;\r\n\r\n\t// set the group\r\n\tNxPs2::dma::SetList(NxPs2::sGroup::pParticles);\r\n\r\n\t// the system and streams will be loaded to a double-buffered input area of VUMem1\r\n\t// ref the system data, and include an unpack for the system and streams:\r\n\tNxPs2::dma::Tag(NxPs2::dma::ref, (sizeof(CSystemDmaData)>>4), (uint)&m_systemDmaData);\r\n\tNxPs2::vif::STCYCL(1,1);\r\n\tNxPs2::vif::UNPACK(0, V4_32, (sizeof(CSystemDmaData)>>4)+m_num_streams*2, REL, SIGNED, 0);\r\n\r\n\t// construct a packet with data for each stream\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tfor (i=0,p_stream=mp_oldest_stream; i<m_num_streams; i++,p_stream++)\r\n\t{\r\n\t\tDbg_MsgAssert(p_stream->m_num_particles<65536, (\"particle limit reached (65536)\"));\r\n\r\n\t\t// wrap at end of cyclic buffer\r\n\t\tif (p_stream == mp_stream + m_max_streams)\r\n\t\t{\r\n\t\t\tp_stream = mp_stream;\r\n\t\t}\r\n\r\n\t\t((float  *)NxPs2::dma::pLoc)[0] = p_stream->m_oldest_age;\r\n\t\t((float  *)NxPs2::dma::pLoc)[1] = p_stream->m_interval;\r\n\t\t((uint32 *)NxPs2::dma::pLoc)[2] = p_stream->m_num_particles;\r\n\t\t((uint32 *)NxPs2::dma::pLoc)[3] = (p_stream==mp_newest_stream) ? 0x8000 : 0;\r\n\t\t((uint32 *)NxPs2::dma::pLoc)[4] = p_stream->m_seed[0];\r\n\t\t((uint32 *)NxPs2::dma::pLoc)[5] = p_stream->m_seed[1];\r\n\t\t((uint32 *)NxPs2::dma::pLoc)[6] = p_stream->m_seed[2];\r\n\t\t((uint32 *)NxPs2::dma::pLoc)[7] = p_stream->m_seed[3];\r\n\r\n\t\t//printf(\"stream %d, num particles=%d, oldest age=%f\\n\", s, p_stream->m_num_particles, p_stream->m_oldest_age);\r\n\r\n\t\t// step dma pointer\r\n\t\tNxPs2::dma::pLoc += 8*4;\r\n\r\n\t\t// count particles\r\n\t\tNxPs2::render::sTotalNewParticles += p_stream->m_num_particles;\r\n\t}\r\n\r\n\tNxPs2::vif::MSCAL(10);\t// sprites\r\n\tNxPs2::dma::EndTag();\r\n\tNxPs2::dma::SetList(NxPs2::sGroup::pEpilogue);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCPs2NewParticle::update_position( void )\r\n{\r\n\t// convert 3-point -> PVA format\r\n\tfloat t1 = m_params.m_Lifetime * m_params.m_MidpointPct * 0.01f;\r\n\tfloat t2 = m_params.m_Lifetime;\r\n\tMth::Vector x0,x1,x2,u,a_;\r\n\r\n\tx0    = m_params.m_BoxPos[0];\r\n\tx0[3] = m_params.m_Radius[0];\r\n\tx1    = m_params.m_BoxPos[1];\r\n\tx1[3] = m_params.m_Radius[1];\r\n\tx2    = m_params.m_BoxPos[2];\r\n\tx2[3] = m_params.m_Radius[2];\r\n\r\n\tif (m_params.m_UseMidpoint)\r\n\t{\r\n\t\tu  =  ( t2*t2*(x1 - x0) - t1*t1*(x2 - x0) ) / ( t1*t2*(t2 - t1) );\r\n\t\ta_ =  ( t1*(x2 - x0) - t2*(x1 - x0) ) / ( t1*t2*(t2 - t1) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tu  = ( x2 - x0 ) / t2;\r\n\t\ta_.Set(0,0,0,0);\r\n\t}\r\n\r\n\tm_systemDmaData.m_p0 = x0 - 1.5f * m_systemDmaData.m_s0;\r\n\tm_systemDmaData.m_p1 = u  - 1.5f * m_systemDmaData.m_s1;\r\n\tm_systemDmaData.m_p2 = a_ - 1.5f * m_systemDmaData.m_s2;\r\n\tm_systemDmaData.m_p0[3] = x0[3] - 1.5f * m_systemDmaData.m_s0[3];\r\n\tm_systemDmaData.m_p1[3] = u[3]  - 1.5f * m_systemDmaData.m_s1[3];\r\n\tm_systemDmaData.m_p2[3] = a_[3] - 1.5f * m_systemDmaData.m_s2[3];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCPs2NewParticle::plat_update( void )\r\n{\r\n\tif (m_params.m_LocalCoord)\r\n\t{\r\n\t\tupdate_position();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCPs2NewParticle::plat_build( void )\r\n{\r\n\r\n\t// initialise streams\r\n\tm_max_streams = 5;\r\n\tm_num_streams = 0;\r\n\tmp_stream = new CParticleStream[m_max_streams]; \r\n\tmp_newest_stream = mp_stream + m_max_streams - 1;\r\n\tmp_oldest_stream = mp_stream;\r\n\tm_emitting = false;\r\n\r\n\r\n\t// giftag for gs context\r\n\tm_systemDmaData.m_GScontext[0] = 0x00008005;\r\n\tm_systemDmaData.m_GScontext[1] = 0x10000000;\r\n\tm_systemDmaData.m_GScontext[2] = 0x0000000E;\r\n\tm_systemDmaData.m_GScontext[3] = 0x00000000;\r\n\r\n\t// ALPHA_1 register\r\n\tuint64 AlphaReg = 0;\r\n\tuint8 fix=64;\r\n\tswitch (m_params.m_BlendMode)\r\n\t{\r\n\t\tcase 0x54628ed7:\t\t// Blend\r\n\t\t\tAlphaReg = PackALPHA(0,1,0,1,0);\r\n\t\t\tbreak;\r\n\t\tcase 0x02e58c18:\t\t// Add\r\n\t\t\tAlphaReg = PackALPHA(0,2,0,1,0);\r\n\t\t\tbreak;\r\n\t\tcase 0xa7fd7d23:\t\t// Sub\r\n\t\tcase 0xdea7e576:\t\t// Subtract\r\n\t\t\tAlphaReg = PackALPHA(2,0,0,1,0);\r\n\t\t\tbreak;\r\n\t\tcase 0x40f44b8a:\t\t// Modulate\r\n\t\t\tAlphaReg = PackALPHA(1,2,0,2,0);\r\n\t\t\tbreak;\r\n\t\tcase 0x68e77f40:\t\t// Brighten\r\n\t\t\tAlphaReg = PackALPHA(1,2,0,1,0);\r\n\t\t\tbreak;\r\n\t\tcase 0x18b98905:\t\t// FixBlend\r\n\t\t\tAlphaReg = PackALPHA(0,1,2,1,fix);\r\n\t\t\tbreak;\r\n\t\tcase 0xa86285a1:\t\t// FixAdd\r\n\t\t\tAlphaReg = PackALPHA(0,2,2,1,fix);\r\n\t\t\tbreak;\r\n\t\tcase 0x0d7a749a:\t\t// FixSub\r\n\t\tcase 0x0eea99ff:\t\t// FixSubtract\r\n\t\t\tAlphaReg = PackALPHA(2,0,2,1,fix);\r\n\t\t\tbreak;\r\n\t\tcase 0x90b93703:\t\t// FixModulate\r\n\t\t\tAlphaReg = PackALPHA(1,2,2,2,fix);\r\n\t\t\tbreak;\r\n\t\tcase 0xb8aa03c9:\t\t// FixBrighten\r\n\t\t\tAlphaReg = PackALPHA(1,2,2,1,fix);\r\n\t\t\tbreak;\r\n\t\tcase 0x515e298e:\t\t// Diffuse\r\n\t\tcase 0x806fff30:\t\t// None\r\n\t\t\tAlphaReg = PackALPHA(0,0,0,0,0);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Illegal blend mode specified. Please use (fix)blend/add/sub/modulate/brighten or diffuse/none.\"));\r\n\t\t\tbreak;\r\n\t}\r\n\tm_systemDmaData.m_GScontext[6] = 0x00000042;\r\n\t*(uint64 *)&m_systemDmaData.m_GScontext[4] = AlphaReg;\r\n\r\n\t// TEX0_1 and TEX1_1 registers\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_engine_texture = NULL;\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( m_params.m_Texture );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\t//printf(\"m_Texture = %08X\\n\", m_params.m_Texture);\r\n\t//printf(\"p_texture = %08X\\n\", p_texture);\r\n\t//printf(\"p_ps2_texture = %08X\\n\", p_ps2_texture);\r\n\t//printf(\"mp_engine_texture = %08X\\n\", mp_engine_texture);\r\n\r\n\tm_systemDmaData.m_GScontext[10] = 0x00000006;\r\n\r\n\tm_systemDmaData.m_GScontext[14] = 0x00000014;\r\n\r\n\tif (mp_engine_texture)\r\n\t{\r\n\t\t//printf(\"\\n\\nTEX0_1 = %08X%08X\\n\\n\\n\",\r\n\t\t//\t\t\t\t\t(uint32)(mp_engine_texture->m_RegTEX0>>32),\r\n\t\t//\t\t\t\t\t(uint32)(mp_engine_texture->m_RegTEX0));\r\n\r\n\t\t// texture coords\r\n\t\tm_systemDmaData.m_u0 = 8;\r\n\t\tm_systemDmaData.m_v0 = (mp_engine_texture->GetHeight()<<4) - 8;\r\n\t\tm_systemDmaData.m_u1 = (mp_engine_texture->GetWidth() <<4) - 8;\r\n\t\tm_systemDmaData.m_v1 = 8;\r\n\t}\r\n\r\n\t// TEST_1\r\n\tm_systemDmaData.m_GScontext[18] = 0x00000047;\r\n\tm_systemDmaData.m_GScontext[16] = 0x0005000B | m_params.m_AlphaCutoff<<4;\r\n\r\n\t// FOG\r\n\tm_systemDmaData.m_GScontext[22] = 0x0000000A;\r\n\r\n\t// giftag for particles\r\n\tm_systemDmaData.m_tagy = 0x60BB4000;\r\n\tm_systemDmaData.m_tagz = 0x00535312;\r\n\r\n\r\n\r\n\t// have already set m_Lifetime, which is called m_life in newflat\r\n\r\n\t// x-component will be overwritten by vu1 code, so can store midtime there\r\n\t*(float *)&m_systemDmaData.m_tagx = m_params.m_UseMidcolor ?\r\n\t\t\t\t\t\t\t\t\t\tm_params.m_Lifetime * m_params.m_ColorMidpointPct * 0.01f :\r\n\t\t\t\t\t\t\t\t\t\t0.0f;\r\n\r\n\t// and now a load of redundant duplication of data, which should later be removed...\r\n\r\n\t// convert 3-point -> PVA format\r\n\tfloat t1 = m_params.m_Lifetime * m_params.m_MidpointPct * 0.01f;\r\n\tfloat t2 = m_params.m_Lifetime;\r\n\tMth::Vector x0,x1,x2,u,a_;\r\n\r\n\t//printf(\"\\n\\n\\n\\n\\n%g,%g,%g\\n%g,%g,%g\\n\\n\\n\\n\\n\",\r\n\t//\t   m_params.m_BoxDims[0][3], m_params.m_BoxDims[1][3], m_params.m_BoxDims[2][3],\r\n\t//\t   m_params.m_BoxPos[0][3], m_params.m_BoxPos[1][3], m_params.m_BoxPos[2][3]);\r\n\r\n\tx0    = m_params.m_BoxDims[0];\r\n\tx0[3] = m_params.m_RadiusSpread[0];\r\n\tx1    = m_params.m_BoxDims[1];\r\n\tx1[3] = m_params.m_RadiusSpread[1];\r\n\tx2    = m_params.m_BoxDims[2];\r\n\tx2[3] = m_params.m_RadiusSpread[2];\r\n\r\n\tif (m_params.m_UseMidpoint)\r\n\t{\r\n\t\tu  = ( t2*t2*(x1 - x0) - t1*t1*(x2 - x0) ) / ( t1*t2*(t2 - t1) );\r\n\t\ta_ = ( t1*(x2 - x0) - t2*(x1 - x0) ) / ( t1*t2*(t2 - t1) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tu  = ( x2 - x0 ) / t2;\r\n\t\ta_.Set(0,0,0,0);\r\n\t}\r\n\r\n\tm_systemDmaData.m_s0 = x0;\r\n\tm_systemDmaData.m_s1 = u;\r\n\tm_systemDmaData.m_s2 = a_;\r\n\r\n\tupdate_position();\r\n\r\n\r\n\t// colour\r\n\tif (m_params.m_UseMidcolor)\r\n\t{\r\n\t\tfloat q0 = 100.0f / (m_params.m_Lifetime * m_params.m_ColorMidpointPct);\r\n\t\tfloat q1 = 100.0f / (m_params.m_Lifetime * (100.0f - m_params.m_ColorMidpointPct));\r\n\r\n\t\tm_systemDmaData.m_c0[0] = ((float)m_params.m_Color[1].r - (float)m_params.m_Color[0].r) * q0;\r\n\t\tm_systemDmaData.m_c0[1] = ((float)m_params.m_Color[1].g - (float)m_params.m_Color[0].g) * q0;\r\n\t\tm_systemDmaData.m_c0[2] = ((float)m_params.m_Color[1].b - (float)m_params.m_Color[0].b) * q0;\r\n\t\tm_systemDmaData.m_c0[3] = ((float)m_params.m_Color[1].a - (float)m_params.m_Color[0].a) * q0;\r\n\r\n\t\tm_systemDmaData.m_c1[0] = (float)m_params.m_Color[1].r;\r\n\t\tm_systemDmaData.m_c1[1] = (float)m_params.m_Color[1].g;\r\n\t\tm_systemDmaData.m_c1[2] = (float)m_params.m_Color[1].b;\r\n\t\tm_systemDmaData.m_c1[3] = (float)m_params.m_Color[1].a;\r\n\r\n\t\tm_systemDmaData.m_c2[0] = ((float)m_params.m_Color[2].r - (float)m_params.m_Color[1].r) * q1;\r\n\t\tm_systemDmaData.m_c2[1] = ((float)m_params.m_Color[2].g - (float)m_params.m_Color[1].g) * q1;\r\n\t\tm_systemDmaData.m_c2[2] = ((float)m_params.m_Color[2].b - (float)m_params.m_Color[1].b) * q1;\r\n\t\tm_systemDmaData.m_c2[3] = ((float)m_params.m_Color[2].a - (float)m_params.m_Color[1].a) * q1;\r\n\r\n\t}\r\n\telse // else suppress mid-colour\r\n\t{\r\n\t\tfloat q = 1.0f / m_params.m_Lifetime;\r\n\r\n\t\tm_systemDmaData.m_c1[0] = (float)m_params.m_Color[0].r;\r\n\t\tm_systemDmaData.m_c1[1] = (float)m_params.m_Color[0].g;\r\n\t\tm_systemDmaData.m_c1[2] = (float)m_params.m_Color[0].b;\r\n\t\tm_systemDmaData.m_c1[3] = (float)m_params.m_Color[0].a;\r\n\r\n\t\tm_systemDmaData.m_c2[0] = ((float)m_params.m_Color[2].r - (float)m_params.m_Color[0].r) * q;\r\n\t\tm_systemDmaData.m_c2[1] = ((float)m_params.m_Color[2].g - (float)m_params.m_Color[0].g) * q;\r\n\t\tm_systemDmaData.m_c2[2] = ((float)m_params.m_Color[2].b - (float)m_params.m_Color[0].b) * q;\r\n\t\tm_systemDmaData.m_c2[3] = ((float)m_params.m_Color[2].a - (float)m_params.m_Color[0].a) * q;\r\n\t}\r\n\r\n\r\n\r\n\t// rotation matrix\r\n\t//m_rotation = m_params.m_RotMatrix;\r\n\tm_rotation.Identity();\r\n\r\n\t#if 0\r\n\t// invert rotation and apply to spatial params\r\n\t// leaving this code a bit shoddy and slow until full transition to new-style params\r\n\tMth::Matrix mat;\r\n\tmat=m_rotation;\r\n\tmat.Transpose();\r\n\tMth::Vector vec;\r\n\r\n\tvec = m_systemDmaData.m_p0 + 1.5f * m_systemDmaData.m_s0;\r\n\tvec *= mat;\r\n\tm_systemDmaData.m_p0 = vec - 1.5f * m_systemDmaData.m_s0;\r\n\r\n\tvec = m_systemDmaData.m_p1 + 1.5f * m_systemDmaData.m_s1;\r\n\tvec *= mat;\r\n\tm_systemDmaData.m_p1 = vec - 1.5f * m_systemDmaData.m_s1;\r\n\r\n\tvec = m_systemDmaData.m_p2 + 1.5f * m_systemDmaData.m_s2;\r\n\tvec *= mat;\r\n\tm_systemDmaData.m_p2 = vec - 1.5f * m_systemDmaData.m_s2;\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCPs2NewParticle::plat_destroy( void )\r\n{\r\n\t\r\n\t// Bit of a patch, but need to wait until particle system DMA packet has\r\n\t// been used before we can delete it, otherwise memory might get corrupted\r\n\t// in normal gameplay particle systems are rarely created\r\n\t// but in \"FireFight\" it shows up a lot more.\r\n\t// This really should be handled at a lower level\r\n\tNx::CEngine::sFinishRendering();\r\n\t\r\n\t\r\n\tif( mp_stream )\r\n\t{\r\n\t\tdelete [] mp_stream;\r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxnewparticle.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_NxNewParticle.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/24/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPS2 implementation of new parametric particle system\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_NGPS_P_NXNEWPARTICLE_H__\r\n#define __GFX_NGPS_P_NXNEWPARTICLE_H__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/nxnewparticle.h>\r\n#include <gfx/ngps/nx/sprite.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n                        \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nclass CParticleStream\r\n{\r\npublic:\r\n\tint\t\t\t\t\t\tm_num_particles;\r\n\tfloat\t\t\t\t\tm_rate;\r\n\tfloat\t\t\t\t\tm_interval;\r\n\tfloat\t\t\t\t\tm_oldest_age;\r\n\tuint32\t\t\t\t\tm_seed[4];\r\n\tvoid\t\t\t\t\tAdvanceSeed(int num_places);\r\n};\r\n\r\nclass CSystemDmaData\r\n{\r\npublic:\r\n\tuint32\t\tm_GScontext[24];\r\n\tuint32\t\tm_u0,  m_v0,  m_u1,  m_v1;\r\n\tMth::Vector\tm_p0;\r\n\tMth::Vector\tm_p1;\r\n\tMth::Vector\tm_p2;\r\n\tMth::Vector\tm_s0;\r\n\tMth::Vector\tm_s1;\r\n\tMth::Vector\tm_s2;\r\n\tMth::Vector\tm_c0;\r\n\tMth::Vector\tm_c1;\r\n\tMth::Vector\tm_c2;\r\n\tuint32\t\tm_tagx,m_tagy,m_tagz,m_tagw;\r\n} nAlign(128);\r\n\r\n\r\nclass CPs2NewParticle : public CNewParticle\r\n{\r\nprivate:\r\n\tvoid\t\t\t\tupdate_position();\r\n\r\n\tbool\t\t\t\tm_emitting;\r\n\tint\t\t\t\t\tm_max_streams;\r\n\tint\t\t\t\t\tm_num_streams;\r\n\tCParticleStream*\tmp_stream;\r\n\tCParticleStream*\tmp_newest_stream;\r\n\tCParticleStream*\tmp_oldest_stream;\r\n\tMth::Matrix \t\tm_rotation;\r\n\tCSystemDmaData\t\tm_systemDmaData;\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n\r\n\r\nprotected:\r\n\tvoid\tplat_render( void );\r\n\tvoid\tplat_update( void );\r\n\tvoid\tplat_build( void );\r\n\tvoid\tplat_destroy( void );\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n#endif\t// __GFX_NGPS_P_NXNEWPARTICLE_H__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxnewparticlemgr.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_NxNewParticleMgr.cpp\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/25/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPs2-specific parametric particle system manager\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gfx/ngps/p_nxnewparticle.h>\r\n#include <gfx/ngps/p_nxnewparticlemgr.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCNewParticle*\tCPs2NewParticleManager::plat_create_particle( void )\r\n{\r\n\treturn new CPs2NewParticle;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxnewparticlemgr.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5 \t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_nxnewparticlemgr.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/24/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPS2-specific new parametric particle system manager\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_NGPS__P_NXNEWPARTICLEMGR_H__\r\n#define __GFX_NGPS__P_NXNEWPARTICLEMGR_H__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/nxnewparticlemgr.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CPs2NewParticleManager : public CNewParticleManager\r\n{\r\nprotected:\r\n\tvirtual\tCNewParticle*\tplat_create_particle( void );\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n#endif\t// __GFX_NGPS__P_NXNEWPARTICLEMGR_H__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticle.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n#include \"gfx/ngps/p_nxparticleflat.h\"\r\n#include \"gfx/ngps/p_nxparticleshaded.h\"\r\n#include \"gfx/ngps/p_nxparticlesmooth.h\"\r\n#include \"gfx/ngps/p_nxparticleglow.h\"\r\n#include \"gfx/ngps/p_nxparticlestar.h\"\r\n#include \"gfx/ngps/p_nxparticlesmoothstar.h\"\r\n#include \"gfx/ngps/p_nxparticleline.h\"\r\n#include \"gfx/ngps/p_nxparticleribbon.h\"\r\n#include \"gfx/ngps/p_nxparticleribbontrail.h\"\r\n#include \"gfx/ngps/p_nxparticlesmoothribbon.h\"\r\n#include \"gfx/ngps/p_nxparticleglowribbontrail.h\"\r\n#include \"gfx/ngps/p_nxparticlenewflat.h\"\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\nCParticle* plat_create_particle( uint32 checksum, uint32 type_checksum, int max_particles, int max_streams, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\t// Types to add:\r\n\t// 1. x Flat color quad\r\n\t// 2. x Gouraud quad\r\n\t// 3. x Quad with center point & outer color\r\n\t// 4. x n sided glow (center color + outer color)\r\n\t// 5. x n sided 2 layer glow ( center color + mid color + outer color)\r\n\t// 6. x n spiked star (center color + mid color + spike color)\r\n\t// 7. Lines (current color + previous color)\r\n\t// 8. Ribbons - volumetric lines made from quads (current color + previous color)\r\n\r\n\tswitch ( type_checksum )\r\n\t{\r\n\t\tcase 0xf4d8d486:\t\t// Shaded\r\n\t\t\t{\r\n\t\t\t\tCPs2ParticleShaded* p_particle = new CPs2ParticleShaded( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x8addac1f:\t\t// Smooth\r\n\t\t\t{\r\n\t\t\t\tCPs2ParticleSmooth* p_particle = new CPs2ParticleSmooth( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x15834eea:\t\t// Glow\r\n\t\t\t{\r\n\t\t\t\tCPs2ParticleGlow* p_particle = new CPs2ParticleGlow( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x3624a5eb:\t\t// Star\r\n\t\t\t{\r\n\t\t\t\tCPs2ParticleStar* p_particle = new CPs2ParticleStar( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x97cb7a9:\t\t// SmoothStar\r\n\t\t\t{\r\n\t\t\t\tCPs2ParticleSmoothStar* p_particle = new CPs2ParticleSmoothStar( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x2eeb4b09:\t\t// Line\r\n\t\t\t{\r\n\t\t\t\tCPs2ParticleLine* p_particle = new CPs2ParticleLine( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0xee6fc5b:\t\t// Ribbon\r\n\t\t\t{\r\n\t\t\t\tCPs2ParticleRibbon* p_particle = new CPs2ParticleRibbon( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0xc4d5a4cb:\t\t// RibbonTrail\r\n\t\t\t{\r\n\t\t\t\tCPs2ParticleRibbonTrail* p_particle = new CPs2ParticleRibbonTrail( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x3f109fcc:\t\t// SmoothRibbon\r\n\t\t\t{\r\n\t\t\t\tCPs2ParticleSmoothRibbon* p_particle = new CPs2ParticleSmoothRibbon( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x7ec7252d:\t\t// GlowRibbonTrail\r\n\t\t\t{\r\n\t\t\t\tCPs2ParticleGlowRibbonTrail* p_particle = new CPs2ParticleGlowRibbonTrail( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0xdedfc057:\t\t// NewFlat\r\n\t\t\t{\r\n\t\t\t\tCPs2ParticleNewFlat* p_particle = new CPs2ParticleNewFlat( checksum, max_streams, texture_checksum, blendmode_checksum, fix );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\tcase 0xaab555bb:\t\t// Flat\r\n\t\tdefault:\r\n\t\t\t{\r\n\t\t\t\tCPs2ParticleFlat* p_particle = new CPs2ParticleFlat( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\t\t\t\t\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticle.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLE_H__\r\n#define\t__GFX_P_NX_PARTICLE_H__\r\n    \r\n#include \"gfx/nxparticle.h\"\r\n                   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleflat.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n\r\n#include \"gfx/ngps/p_nxparticleflat.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleFlat::CPs2ParticleFlat()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleFlat::CPs2ParticleFlat( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxPs2::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tm_start_color.r = 128;\r\n\tm_start_color.g = 128;\r\n\tm_start_color.b = 128;\r\n\tm_start_color.a = 128;\r\n\tm_mid_color.r = 128;\r\n\tm_mid_color.g = 128;\r\n\tm_mid_color.b = 128;\r\n\tm_mid_color.a = 128;\r\n\tm_end_color.r = 128;\r\n\tm_end_color.g = 128;\r\n\tm_end_color.b = 128;\r\n\tm_end_color.a = 128;\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleFlat::~CPs2ParticleFlat()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleFlat::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleFlat::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleFlat::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CPs2ParticleFlat::plat_get_num_particle_colors( void ) { return 1; }\r\nint CPs2ParticleFlat::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CPs2ParticleFlat::plat_set_sr( int entry, uint8 value ) { m_start_color.r = value; }\r\nvoid CPs2ParticleFlat::plat_set_sg( int entry, uint8 value ) { m_start_color.g = value; }\r\nvoid CPs2ParticleFlat::plat_set_sb( int entry, uint8 value ) { m_start_color.b = value; }\r\nvoid CPs2ParticleFlat::plat_set_sa( int entry, uint8 value ) { m_start_color.a = value >> 1; }\r\nvoid CPs2ParticleFlat::plat_set_mr( int entry, uint8 value ) { m_mid_color.r = value; }\r\nvoid CPs2ParticleFlat::plat_set_mg( int entry, uint8 value ) { m_mid_color.g = value; }\r\nvoid CPs2ParticleFlat::plat_set_mb( int entry, uint8 value ) { m_mid_color.b = value; }\r\nvoid CPs2ParticleFlat::plat_set_ma( int entry, uint8 value ) { m_mid_color.a = value >> 1; }\r\nvoid CPs2ParticleFlat::plat_set_er( int entry, uint8 value ) { m_end_color.r = value; }\r\nvoid CPs2ParticleFlat::plat_set_eg( int entry, uint8 value ) { m_end_color.g = value; }\r\nvoid CPs2ParticleFlat::plat_set_eb( int entry, uint8 value ) { m_end_color.b = value; }\r\nvoid CPs2ParticleFlat::plat_set_ea( int entry, uint8 value ) { m_end_color.a = value >> 1; }\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n#if 0\r\n\r\nvoid CPs2ParticleFlat::plat_render( void )\r\n{\r\n\tif (m_num_particles == 0)\r\n\t\treturn;\r\n\r\n\t// Draw the particles.\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t//Mth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraOrientation;\r\n\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\tscreen_right.Normalize();\r\n\tscreen_up.Normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tNxPs2::CImmediateMode::sStartPolyDraw( mp_engine_texture, m_blend );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v = mp_vertices; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\t\t\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[4];\r\n\t\r\n\t\tss_right\t= screen_right * w;\r\n\t\tss_up\t\t= screen_up * h;\r\n\t\r\n\t\ttmp[0]\t\t= pos - ss_right + ss_up;\r\n\t\ttmp[1]\t\t= pos + ss_right + ss_up;\t\t\r\n\t\ttmp[2]\t\t= pos + ss_right - ss_up;\t\t\r\n\t\ttmp[3]\t\t= pos - ss_right - ss_up;\t\t\r\n\t\r\n\t\tImage::RGBA color;\r\n\t\tImage::RGBA *p_col0;\r\n\t\tImage::RGBA *p_col1;\r\n\t\t\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = &m_start_color;\r\n\t\t\t\tp_col1 = &m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = &m_mid_color;\r\n\t\t\t\tp_col1 = &m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = &m_start_color;\r\n\t\t\tp_col1 = &m_end_color;\r\n\t\t}\r\n\r\n\t\tImage::RGBA start = *p_col0;\r\n\t\tImage::RGBA end = *p_col1;\r\n\r\n\t\tcolor.r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\tcolor.g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\tcolor.b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\tcolor.a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\r\n\t\tNxPs2::CImmediateMode::sDrawQuadTexture( mp_engine_texture, tmp[0], tmp[1], tmp[2], tmp[3],\r\n\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color),\r\n\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color),\r\n\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color),\r\n\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color));\r\n\t}\r\n\r\n\tNxPs2::dma::EndTag();\r\n}\r\n\r\n#else\r\n\r\nvoid CPs2ParticleFlat::plat_render( void )\r\n{\r\n\tif (m_num_particles <= 0)\r\n\t\treturn;\r\n\r\n\tDbg_MsgAssert(mp_engine_texture, (\"no support for non-textured sprites yet...\"));\r\n\r\n\tint i,j=0;\r\n\tCParticleEntry *p_particle;\r\n\tfloat *p_v;\r\n\tfloat *p_xyzr=NULL;\r\n\tuint32 *p_rgba=NULL;\r\n\r\n\t// add a dma packet\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\r\n\t// VU context\r\n\tNxPs2::vu1::BeginPrim(ABS, VU1_ADDR(L_VF10));\r\n\tNxPs2::vu1::StoreVec(*(NxPs2::Vec *)&NxPs2::render::InverseIntViewportScale);\r\n\tNxPs2::vu1::StoreVec(*(NxPs2::Vec *)&NxPs2::render::InverseIntViewportOffset);\r\n\tNxPs2::vu1::StoreMat(*(NxPs2::Mat *)&NxPs2::render::WorldToIntViewport);\t// VF12-15\r\n\tNxPs2::vu1::EndPrim(0);\r\n\tNxPs2::vu1::BeginPrim(ABS, VU1_ADDR(L_VF30));\r\n\tNxPs2::vif::StoreV4_32F(640.0f, 480.0f, 0.0f, 0.0f);\t\t\t\t\t\t// VF30\r\n\tNxPs2::vif::StoreV4_32F(NxPs2::render::IntViewportScale[0]/NxPs2::render::Tx,\t// VF31\r\n\t\t\t\t\t\t\tNxPs2::render::IntViewportScale[1]/NxPs2::render::Ty,\r\n\t\t\t\t\t\t\t0.0f, 0.0f);\r\n\tNxPs2::vu1::EndPrim(0);\r\n\r\n\t// GS context\r\n\tNxPs2::gs::BeginPrim(ABS, 0, 0);\r\n\tNxPs2::gs::Reg1(NxPs2::gs::ALPHA_1,\tm_blend);\r\n\tNxPs2::gs::Reg1(NxPs2::gs::TEX0_1,\tmp_engine_texture->m_RegTEX0);\r\n\tNxPs2::gs::Reg1(NxPs2::gs::TEX1_1,\tmp_engine_texture->m_RegTEX1);\r\n\tNxPs2::gs::Reg1(NxPs2::gs::ST,\t\tPackST(0x3F800000,0x3F800000));\r\n\tNxPs2::gs::Reg1(NxPs2::gs::RGBAQ,\tPackRGBAQ(0,0,0,0,0x3F800000));\r\n\tNxPs2::gs::EndPrim(0);\r\n\r\n\tfor (i=0, p_particle=mp_particle_array, p_v=mp_vertices; i<m_num_particles; i++, j--, p_particle++, p_v+=3)\r\n\t{\r\n\t\tif (i==0 || j==0)\r\n\t\t{\r\n\t\t\tj = m_num_particles - i;\r\n\t\t\tif (j > 80)\r\n\t\t\t\tj = 80;\r\n\t\t\t\t\r\n\t\t\tNxPs2::BeginModelPrimImmediate(NxPs2::gs::XYZ2\t\t|\r\n\t\t\t\t\t\t\t\t\t\t   NxPs2::gs::ST<<4\t\t|\r\n\t\t\t\t\t\t\t\t\t\t   NxPs2::gs::RGBAQ<<8\t|\r\n\t\t\t\t\t\t\t\t\t\t   NxPs2::gs::XYZ2<<12,\r\n\t\t\t\t\t\t\t\t\t\t   4, SPRITE|ABE|TME, 1, VU1_ADDR(SpriteCull));\r\n\r\n\t\t\t// create an unpack for the colours\r\n\t\t\tNxPs2::vif::BeginUNPACK(0, V4_8, ABS, UNSIGNED, 3);\r\n\t\t\tp_rgba = (uint32 *)NxPs2::dma::pLoc;\r\n\t\t\tNxPs2::dma::pLoc += j * 4;\r\n\t\t\tNxPs2::vif::EndUNPACK();\r\n\r\n\t\t\t// and one for the positions (& sizes)\r\n\t\t\tNxPs2::vif::BeginUNPACK(0, V4_32, ABS, SIGNED, 4);\r\n\t\t\tp_xyzr = (float *)NxPs2::dma::pLoc;\r\n\t\t\tNxPs2::dma::pLoc += j * 16;\r\n\t\t\tNxPs2::vif::EndUNPACK();\r\n\r\n\t\t\tNxPs2::EndModelPrimImmediate(1);\r\n\r\n\t\t\tNxPs2::vif::MSCAL(VU1_ADDR(Parser));\r\n\t\t}\r\n\r\n\t\tfloat t = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\t// just use the width for now...\r\n\t\tfloat width = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * t );\r\n\t\t\r\n\t\t// store position\r\n\t\t*p_xyzr++ = p_v[0]+m_pos[0];\r\n\t\t*p_xyzr++ = p_v[1]+m_pos[1];\r\n\t\t*p_xyzr++ = p_v[2]+m_pos[2];\r\n\t\t*p_xyzr++ = width;\r\n\r\n\t\tImage::RGBA start, end, colour;\r\n\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( t < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tstart = m_start_color;\r\n\t\t\t\tend   = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tt /= m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tstart = m_mid_color;\r\n\t\t\t\tend   = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tt = ( t - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tstart = m_start_color;\r\n\t\t\tend   = m_end_color;\r\n\t\t}\r\n\r\n\t\t// compute interpolated colour\r\n\t\tcolour.r = start.r + (uint8) (int) ( ((float)( end.r - start.r )) * t );\r\n\t\tcolour.g = start.g + (uint8) (int) ( ((float)( end.g - start.g )) * t );\r\n\t\tcolour.b = start.b + (uint8) (int) ( ((float)( end.b - start.b )) * t );\r\n\t\tcolour.a = start.a + (uint8) (int) ( ((float)( end.a - start.a )) * t );\r\n\r\n\t\t// store colour\r\n\t\t*p_rgba++ = *(uint32 *)&colour;\r\n\t}\r\n\r\n\t// restore transform\r\n\tNxPs2::vu1::BeginPrim(ABS, VU1_ADDR(L_VF12));\t\t// was L_VF16\r\n\tNxPs2::vu1::StoreMat(*(NxPs2::Mat *)&NxPs2::render::AdjustedWorldToViewport);\t\t// VF16-19\r\n\tNxPs2::vu1::EndPrim(1);\r\n\tNxPs2::vif::MSCAL(VU1_ADDR(Parser));\r\n\r\n\t// end the dma tag\r\n\tNxPs2::dma::EndTag();\r\n\r\n}\r\n\r\n#endif\r\n\r\n} // Nx\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleflat.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLEFLAT_H__\r\n#define\t__GFX_P_NX_PARTICLEFLAT_H__\r\n    \r\n#include \"gfx/ngps/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CPs2ParticleFlat : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2ParticleFlat();\r\n\t\t\t\t\t\t\tCPs2ParticleFlat( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CPs2ParticleFlat();\r\n\r\n//\tNxPs2::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\t//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n//\tNxPs2::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tImage::RGBA\t\t\t\tm_start_color;\t\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color;\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color;\t\t\t\t// End color for each corner.\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleglow.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n\r\n#include \"gfx/ngps/p_nxparticleGlow.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleGlow::CPs2ParticleGlow()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleGlow::CPs2ParticleGlow( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxPs2::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 3; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n\r\n\tm_num_segments = num_segments;\r\n\tm_split = split;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleGlow::~CPs2ParticleGlow()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleGlow::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleGlow::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleGlow::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CPs2ParticleGlow::plat_get_num_particle_colors( void ) { return 3; }\r\nint CPs2ParticleGlow::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CPs2ParticleGlow::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CPs2ParticleGlow::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CPs2ParticleGlow::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CPs2ParticleGlow::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleGlow::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CPs2ParticleGlow::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CPs2ParticleGlow::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CPs2ParticleGlow::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleGlow::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CPs2ParticleGlow::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CPs2ParticleGlow::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CPs2ParticleGlow::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value >> 1; }\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleGlow::plat_render( void )\r\n{\r\n\tif (m_num_particles == 0)\r\n\t\treturn;\r\n\r\n\t// Draw the particles.\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t//Mth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraOrientation;\r\n\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\tscreen_right.Normalize();\r\n\tscreen_up.Normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tNxPs2::CImmediateMode::sStartPolyDraw( mp_engine_texture, m_blend, ABS );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v = mp_vertices; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[4];\r\n\t\r\n\t\tss_right\t= screen_right * w;\r\n\t\tss_up\t\t= screen_up * h;\r\n\t\r\n\t\tImage::RGBA color[3];\r\n\t\tImage::RGBA *p_col0;\r\n\t\tImage::RGBA *p_col1;\r\n\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 3; c++ )\r\n\t\t{\r\n\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\r\n\t\ttmp[0]  = pos;\r\n\t\ttmp[0] += ss_right * sinf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\t\ttmp[0] += ss_up    * cosf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\r\n\t\ttmp[2]  = pos;\r\n\t\ttmp[2] += ss_right * sinf( Mth::DegToRad( 0.0f ) );\r\n\t\ttmp[2] += ss_up    * cosf( Mth::DegToRad( 0.0f ) );\r\n\r\n\t\tfor ( int lp2 = 0; lp2 < m_num_segments; lp2++ )\r\n\t\t{\r\n\t\t\ttmp[1]  = pos;\r\n\t\t\ttmp[1] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\t\t\ttmp[1] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\r\n\t\t\ttmp[3]  = pos;\r\n\t\t\ttmp[3] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) );\r\n\t\t\ttmp[3] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) );\r\n\r\n\t\t\tNxPs2::CImmediateMode::sDrawGlowSegment( pos, tmp[0], tmp[1], tmp[2], tmp[3],\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color[0]),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color[1]),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color[2]));\r\n\t\t\ttmp[0] = tmp[1];\r\n\t\t\ttmp[2] = tmp[3];\r\n\t\t}\r\n\t}\r\n\r\n\tNxPs2::dma::EndTag();\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleglow.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLEGlow_H__\r\n#define\t__GFX_P_NX_PARTICLEGlow_H__\r\n    \r\n#include \"gfx/ngps/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CPs2ParticleGlow : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2ParticleGlow();\r\n\t\t\t\t\t\t\tCPs2ParticleGlow( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CPs2ParticleGlow();\r\n\r\n//\tNxPs2::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n\r\n//\tNxPs2::sParticleSystem*\tmp_engine_particle;\r\n\tint\t\t\t\t\t\tm_num_segments;\r\n\tfloat\t\t\t\t\tm_split;\r\n\tImage::RGBA\t\t\t\tm_start_color[3];\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color[3];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color[3];\t\t\t\t// End color for each corner.\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleglowribbontrail.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n\r\n#include \"gfx/ngps/p_nxparticleGlowRibbonTrail.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleGlowRibbonTrail::CPs2ParticleGlowRibbonTrail()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleGlowRibbonTrail::CPs2ParticleGlowRibbonTrail( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float*[( history + 1)];\r\n\tfor ( int lp = 0; lp < ( history + 1); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxPs2::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tm_start_color = new Image::RGBA[m_num_vertex_buffers+3];\r\n\tm_mid_color = new Image::RGBA[m_num_vertex_buffers+3];\r\n\tm_end_color = new Image::RGBA[m_num_vertex_buffers+3];\r\n\tfor ( int lp = 0; lp < (m_num_vertex_buffers+3); lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n\r\n\tm_num_segments = num_segments;\r\n\tm_split = split;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleGlowRibbonTrail::~CPs2ParticleGlowRibbonTrail()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\r\n\tdelete [] m_start_color;\r\n\tdelete [] m_mid_color;\r\n\tdelete [] m_end_color;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleGlowRibbonTrail::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleGlowRibbonTrail::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleGlowRibbonTrail::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CPs2ParticleGlowRibbonTrail::plat_get_num_particle_colors( void ) { return m_num_vertex_buffers + 3; }\r\nint CPs2ParticleGlowRibbonTrail::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CPs2ParticleGlowRibbonTrail::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CPs2ParticleGlowRibbonTrail::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CPs2ParticleGlowRibbonTrail::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CPs2ParticleGlowRibbonTrail::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleGlowRibbonTrail::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CPs2ParticleGlowRibbonTrail::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CPs2ParticleGlowRibbonTrail::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CPs2ParticleGlowRibbonTrail::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleGlowRibbonTrail::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CPs2ParticleGlowRibbonTrail::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CPs2ParticleGlowRibbonTrail::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CPs2ParticleGlowRibbonTrail::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value >> 1; }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleGlowRibbonTrail::plat_render( void )\r\n{\r\n\tif (m_num_particles == 0)\r\n\t\treturn;\r\n\r\n\t// Draw the ribbontrail.\r\n\t\r\n//\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n//\t//Mth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraOrientation;\r\n//\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n//\r\n//\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n//\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n//\r\n//\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n//\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n//\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n//\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n//\r\n//\tscreen_right.Normalize();\r\n//\tscreen_up.Normalize();\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\tscreen_right.Normalize();\r\n\tscreen_up.Normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tNxPs2::CImmediateMode::sStartPolyDraw( mp_engine_texture, m_blend, ABS );\r\n\r\n\tImage::RGBA color[3];\r\n\tImage::RGBA *p_col0;\r\n\tImage::RGBA *p_col1;\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array; lp < m_num_particles; lp++, p_particle++ )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tMth::Vector\tpos[2];\r\n\t\tp_v = &mp_vertices[0][lp*3];\r\n\t\tpos[0].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tp_v = &mp_vertices[1][lp*3];\r\n\t\tpos[1].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\r\n\t\tMth::Vector\tpart_vec = pos[1] - pos[0];\r\n\t\tMth::Vector perp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\tperp_vec.Normalize();\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\t\t\r\n\t\tMth::Vector tmp[4];\r\n\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = &m_start_color[3];\r\n\t\t\t\tp_col1 = &m_mid_color[3];\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = &m_mid_color[3];\r\n\t\t\t\tp_col1 = &m_end_color[3];\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = &m_start_color[3];\r\n\t\t\tp_col1 = &m_end_color[3];\r\n\t\t}\r\n\r\n\t\tImage::RGBA start = *p_col0++;\r\n\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\tcolor[0].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\tcolor[0].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\tcolor[0].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\tcolor[0].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\r\n\t\ttmp[0]\t\t= pos[0] + ( perp_vec * w * m_split );\r\n\t\ttmp[1]\t\t= pos[0] - ( perp_vec * w * m_split );\r\n\r\n\t\tfor ( int c = 1; c < m_num_vertex_buffers; c++ )\r\n\t\t{\r\n\t\t\tstart = *p_col0++;\r\n\t\t\tend = *p_col1++;\r\n\r\n\t\t\tcolor[1].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[1].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[1].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[1].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\r\n\t\t\tif ( c > 1 )\r\n\t\t\t{\r\n\t\t\t\tp_v = &mp_vertices[c][lp*3];\r\n\t\t\t\tpos[1].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\t\t\tpart_vec = pos[1] - pos[0];\r\n\t\t\t\tperp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\t\t\tperp_vec.Normalize();\r\n\t\t\t}\r\n\r\n\t\t\ttmp[2]\t\t= pos[1] - ( perp_vec * w * m_split );\r\n\t\t\ttmp[3]\t\t= pos[1] + ( perp_vec * w * m_split );\r\n\r\n\t\t\tNxPs2::CImmediateMode::sDrawQuadTexture( mp_engine_texture, tmp[0], tmp[1], tmp[2], tmp[3], *((uint32 *) &color[0]), *((uint32 *) &color[0]), *((uint32 *) &color[1]), *((uint32 *) &color[1]) );\r\n\r\n\t\t\tcolor[0] = color[1];\r\n\t\t\tpos[0] = pos[1];\r\n\t\t\ttmp[0] = tmp[3];\r\n\t\t\ttmp[1] = tmp[2];\r\n\t\t}\r\n\r\n\t\t// Draw the glow.\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tp_v = &mp_vertices[0][lp*3];\r\n\t\tpos[0].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\r\n\t\tss_right\t= screen_right * w;\r\n\t\tss_up\t\t= screen_up * h;\r\n\t\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 3; c++ )\r\n\t\t{\r\n\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\r\n\t\ttmp[0]  = pos[0];\r\n\t\ttmp[0] += ss_right * sinf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\t\ttmp[0] += ss_up    * cosf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\r\n\t\ttmp[2]  = pos[0];\r\n\t\ttmp[2] += ss_right * sinf( Mth::DegToRad( 0.0f ) );\r\n\t\ttmp[2] += ss_up    * cosf( Mth::DegToRad( 0.0f ) );\r\n\r\n\t\tfor ( int lp2 = 0; lp2 < m_num_segments; lp2++ )\r\n\t\t{\r\n\t\t\ttmp[1]  = pos[0];\r\n\t\t\ttmp[1] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\t\t\ttmp[1] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\r\n\t\t\ttmp[3]  = pos[0];\r\n\t\t\ttmp[3] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) );\r\n\t\t\ttmp[3] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) );\r\n\r\n\t\t\tNxPs2::CImmediateMode::sDrawGlowSegment( pos[0], tmp[0], tmp[1], tmp[2], tmp[3],\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color[0]),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color[1]),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color[2]));\r\n\t\t\ttmp[0] = tmp[1];\r\n\t\t\ttmp[2] = tmp[3];\r\n\t\t}\r\n\t}\r\n\r\n\tNxPs2::dma::EndTag();\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleglowribbontrail.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLEGlowRibbonTrail_H__\r\n#define\t__GFX_P_NX_PARTICLEGlowRibbonTrail_H__\r\n    \r\n#include \"gfx/ngps/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CPs2ParticleGlowRibbonTrail : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2ParticleGlowRibbonTrail();\r\n\t\t\t\t\t\t\tCPs2ParticleGlowRibbonTrail( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CPs2ParticleGlowRibbonTrail();\r\n\r\n//\tNxPs2::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\t//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tint\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tfloat**\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n//\tNxPs2::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tint\t\t\t\t\t\tm_num_segments;\r\n\tfloat\t\t\t\t\tm_split;\r\n\tImage::RGBA*\t\t\tm_start_color;\t\t\t\t// Start color for each corner.\r\n\tImage::RGBA*\t\t\tm_mid_color;\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA*\t\t\tm_end_color;\t\t\t\t// End color for each corner.\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleline.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n\r\n#include \"gfx/ngps/p_nxparticleLine.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleLine::CPs2ParticleLine()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleLine::CPs2ParticleLine( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffers.\r\n\tmp_vertices = new float*[( history + 1)];\r\n\tfor ( int lp = 0; lp < ( history + 1 ); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxPs2::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tm_start_color = new Image::RGBA[m_num_vertex_buffers];\r\n\tm_mid_color = new Image::RGBA[m_num_vertex_buffers];\r\n\tm_end_color = new Image::RGBA[m_num_vertex_buffers];\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleLine::~CPs2ParticleLine()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleLine::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleLine::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleLine::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CPs2ParticleLine::plat_get_num_particle_colors( void ) { return 2; }\r\nint CPs2ParticleLine::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CPs2ParticleLine::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CPs2ParticleLine::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CPs2ParticleLine::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CPs2ParticleLine::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleLine::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CPs2ParticleLine::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CPs2ParticleLine::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CPs2ParticleLine::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleLine::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CPs2ParticleLine::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CPs2ParticleLine::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CPs2ParticleLine::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value >> 1; }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleLine::plat_render( void )\r\n{\r\n\tif (m_num_particles == 0)\r\n\t\treturn;\r\n\r\n\t// Draw the particles.\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v0;\r\n\tfloat\t\t\t*p_v1;\r\n\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tNxPs2::CImmediateMode::sStartPolyDraw( mp_engine_texture, m_blend, ABS );\r\n\r\n\tImage::RGBA color[2];\r\n\tImage::RGBA *p_col0;\r\n\tImage::RGBA *p_col1;\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v0 = mp_vertices[0], p_v1 = mp_vertices[(m_num_vertex_buffers-1)]; lp < m_num_particles; lp++, p_particle++, p_v0 += 3, p_v1 += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 2; c++ )\r\n\t\t{\r\n\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos0( p_v0[0] + m_pos[X], p_v0[1] + m_pos[Y], p_v0[2] + m_pos[Z] );\r\n\t\tMth::Vector\tpos1( p_v1[0] + m_pos[X], p_v1[1] + m_pos[Y], p_v1[2] + m_pos[Z] );\r\n\t\r\n\t\tNxPs2::CImmediateMode::sDrawLine( pos0, pos1, *((uint32 *) &color[0]), *((uint32 *) &color[1]) );\r\n\t}\r\n\r\n\tNxPs2::dma::EndTag();\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleline.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLELine_H__\r\n#define\t__GFX_P_NX_PARTICLELine_H__\r\n    \r\n#include \"gfx/ngps/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CPs2ParticleLine : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2ParticleLine();\r\n\t\t\t\t\t\t\tCPs2ParticleLine( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CPs2ParticleLine();\r\n\r\n//\tNxPs2::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\t//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tint\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tfloat**\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n//\tNxPs2::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tImage::RGBA*\t\t\tm_start_color;\t\t\t\t// Start color for each corner.\r\n\tImage::RGBA*\t\t\tm_mid_color;\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA*\t\t\tm_end_color;\t\t\t\t// End color for each corner.\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticlenewflat.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n#include \"gfx/ngps/nx/group.h\"\r\n\r\n#include \"gfx/ngps/p_nxparticlenewflat.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleNewFlat::CPs2ParticleNewFlat()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleNewFlat::CPs2ParticleNewFlat( uint32 checksum, int max_streams, uint32 texture_checksum, uint32 blendmode_checksum, int fix )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_streams = max_streams;\r\n\tm_num_streams = 0;\r\n\r\n\t// Get the texture.\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n\r\n\t// Allocate space for span information & streams. \r\n\tm_num_spans = 1;\t\t// Currently defaulting to 1 span.\r\n\tmp_span = new CParticleSpan[m_num_spans];\r\n\tmp_stream = new CParticleStream[m_max_streams]; \r\n\r\n\tmp_newest_stream = mp_stream + m_max_streams - 1;\r\n\tmp_oldest_stream = mp_stream;\r\n\tm_life = 0.5f * (m_life_min + m_life_max);\r\n\tm_emitting = false;\r\n\r\n\r\n\t// set up system dma data, apart from new coefficients, which are calculated in plat_build_path()\r\n\tm_systemDmaData.m_GScontext[0] = 0x00008004;\r\n\tm_systemDmaData.m_GScontext[1] = 0x10000000;\r\n\tm_systemDmaData.m_GScontext[2] = 0x0000000E;\r\n\tm_systemDmaData.m_GScontext[3] = 0x00000000;\r\n\r\n\t*(uint64 *)&m_systemDmaData.m_GScontext[4] = m_blend;\r\n\tm_systemDmaData.m_GScontext[6] = 0x00000042;\r\n\r\n\tif (mp_engine_texture)\r\n\t{\r\n\t\tm_systemDmaData.m_u0 = 8;\r\n\t\tm_systemDmaData.m_v0 = (mp_engine_texture->GetHeight()<<4) - 8;\r\n\t\tm_systemDmaData.m_u1 = (mp_engine_texture->GetWidth() <<4) - 8;\r\n\t\tm_systemDmaData.m_v1 = 8;\r\n\t\t//m_systemDmaData.m_GScontext[16] = ((mp_engine_texture->GetHeight()<<4) - 8) << 16 | 8;\r\n\r\n\t\t*(uint64 *)&m_systemDmaData.m_GScontext[8] = mp_engine_texture->m_RegTEX0;\r\n\t\t*(uint64 *)&m_systemDmaData.m_GScontext[12] = mp_engine_texture->m_RegTEX1;\r\n\t}\r\n\tm_systemDmaData.m_GScontext[10] = 0x00000006;\r\n\tm_systemDmaData.m_GScontext[14] = 0x00000014;\r\n\r\n\tm_systemDmaData.m_GScontext[16] = 0x0005000B /* | m_alphaCutoff<<4 */;\t//101 0000 xxxx xxxx 1011\r\n\tm_systemDmaData.m_GScontext[18] = 0x00000047;\r\n\r\n\tm_systemDmaData.m_tagy = 0x60AB4000;\r\n\tm_systemDmaData.m_tagz = 0x00434312;\r\n\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleNewFlat::~CPs2ParticleNewFlat()\r\n{\r\n\tdelete [] mp_span;\r\n\tdelete [] mp_stream;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleNewFlat::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleNewFlat::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleNewFlat::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CPs2ParticleNewFlat::plat_get_num_particle_colors( void ) { return 1; };\r\nint CPs2ParticleNewFlat::plat_get_num_vertex_lists( void ) { return 0; };\r\nvoid CPs2ParticleNewFlat::plat_set_sr( int entry, uint8 value ) { m_start_color.r = value; }\r\nvoid CPs2ParticleNewFlat::plat_set_sg( int entry, uint8 value ) { m_start_color.g = value; }\r\nvoid CPs2ParticleNewFlat::plat_set_sb( int entry, uint8 value ) { m_start_color.b = value; }\r\nvoid CPs2ParticleNewFlat::plat_set_sa( int entry, uint8 value ) { m_start_color.a = value >> 1; }\r\nvoid CPs2ParticleNewFlat::plat_set_mr( int entry, uint8 value ) { m_mid_color.r = value; }\r\nvoid CPs2ParticleNewFlat::plat_set_mg( int entry, uint8 value ) { m_mid_color.g = value; }\r\nvoid CPs2ParticleNewFlat::plat_set_mb( int entry, uint8 value ) { m_mid_color.b = value; }\r\nvoid CPs2ParticleNewFlat::plat_set_ma( int entry, uint8 value ) { m_mid_color.a = value >> 1; }\r\nvoid CPs2ParticleNewFlat::plat_set_er( int entry, uint8 value ) { m_end_color.r = value; }\r\nvoid CPs2ParticleNewFlat::plat_set_eg( int entry, uint8 value ) { m_end_color.g = value; }\r\nvoid CPs2ParticleNewFlat::plat_set_eb( int entry, uint8 value ) { m_end_color.b = value; }\r\nvoid CPs2ParticleNewFlat::plat_set_ea( int entry, uint8 value ) { m_end_color.a = value >> 1; }\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n\r\nvoid CPs2ParticleNewFlat::plat_render( void )\r\n{\r\n\tCParticleStream *p_stream;\r\n\tint i;\r\n\r\n\r\n\t//--------------------------------------------------------------------------------------------------------------------\r\n\t// process the streams\r\n\tif (m_emit_rate && (!m_emitting || (m_emit_rate != mp_newest_stream->m_rate)))\r\n\t{\t\r\n\t\tif (m_num_streams < m_max_streams)\r\n\t\t{\r\n\t\t\t// add new stream to cyclic buffer\r\n\t\t\tm_num_streams++;\r\n\t\t\tmp_newest_stream++;\r\n\t\t\tif (mp_newest_stream == mp_stream + m_max_streams)\r\n\t\t\t{\r\n\t\t\t\tmp_newest_stream = mp_stream;\r\n\t\t\t}\r\n\r\n\t\t\t// initialise new stream\r\n\t\t\tmp_newest_stream->m_rate\t\t\t= m_emit_rate;\r\n\t\t\tmp_newest_stream->m_interval\t\t= 1.0f/m_emit_rate;\r\n\t\t\tmp_newest_stream->m_oldest_age\t\t= 0.0f;\r\n\t\t\tmp_newest_stream->m_num_particles\t= 0;\r\n\t\t\tmp_newest_stream->m_seed[0]\t\t\t= rand();\r\n\t\t\tmp_newest_stream->m_seed[1]\t\t\t= rand();\r\n\t\t\tmp_newest_stream->m_seed[2]\t\t\t= rand();\r\n\t\t\tmp_newest_stream->m_seed[3]\t\t\t= rand();\r\n\t\t\tm_emitting = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_emitting = false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_emitting = m_emit_rate;\r\n\t}\r\n\r\n\tif (!m_num_streams)\r\n\t\treturn;\r\n\r\n\t// age all streams\r\n\tfor (i=0, p_stream=mp_oldest_stream; i<m_num_streams; i++)\r\n\t{\r\n\t\t// increase age of oldest particle\r\n\t\tp_stream->m_oldest_age += 1.0f/60.0f;\r\n\r\n\t\t// step pointer within cyclic buffer\r\n\t\tp_stream++;\r\n\t\tif (p_stream == mp_stream + m_max_streams)\r\n\t\t{\r\n\t\t\tp_stream = mp_stream;\r\n\t\t}\r\n\t}\r\n\r\n\t// births into newest stream\r\n\tif (m_emitting)\r\n\t{\r\n\t\t// how many particles so far emitted?\r\n\t\tmp_newest_stream->m_num_particles = (int)(mp_newest_stream->m_oldest_age * mp_newest_stream->m_rate + 1.0f);\r\n\t}\r\n\r\n\t// deaths from oldest stream\r\n\tif (mp_oldest_stream->m_oldest_age > m_life)\r\n\t{\r\n\t\t// work out number dead\r\n\t\tint particles_dead = (int)((mp_oldest_stream->m_oldest_age - m_life) * mp_oldest_stream->m_rate + 1.0f);\r\n\r\n\t\t// remove dead particles\r\n\t\tmp_oldest_stream->m_num_particles -= particles_dead;\r\n\r\n\t\t// should we keep processing the oldest stream?\r\n\t\tif (mp_oldest_stream->m_num_particles>0 || (m_num_streams==1 && m_emitting))\r\n\t\t{\r\n\t\t\t// adjust age of oldest particle\r\n\t\t\tmp_oldest_stream->m_oldest_age -= (float)particles_dead * mp_oldest_stream->m_interval;\r\n\r\n\t\t\t// advance seed\r\n\t\t\tmp_oldest_stream->AdvanceSeed(particles_dead);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// remove oldest stream and wrap in cyclic buffer if necessary\r\n\t\t\tm_num_streams--;\r\n\t\t\tmp_oldest_stream++;\r\n\t\t\tif (mp_oldest_stream == mp_stream + m_max_streams)\r\n\t\t\t{\r\n\t\t\t\tmp_oldest_stream = mp_stream;\r\n\t\t\t}\r\n\t\t\tif (!m_num_streams)\r\n\t\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t//--------------------------------------------------------------------------------------------------------------------\r\n\t// now render the streams\r\n\r\n\tif (mp_engine_texture)\r\n\t{\r\n\t\t// Mick:  If this is textured, we reset the TEX0, TEX1 regs as the texture might move\r\n\t\t// Since 2D textures are dynamically packed every frame\r\n\t\t*(uint64 *)&m_systemDmaData.m_GScontext[8] = mp_engine_texture->m_RegTEX0;\r\n\t\t*(uint64 *)&m_systemDmaData.m_GScontext[12] = mp_engine_texture->m_RegTEX1;\r\n\t}\r\n\r\n\t// matrix is system rotation times view transform\r\n\tm_systemDmaData.m_matrix = m_rotation * NxPs2::render::WorldToIntViewport;\r\n\r\n\t// in the per-frame setup dma we must have:\r\n\t// dma tag\r\n\t// base\r\n\t// offset\r\n\r\n\t// set the group\r\n\tNxPs2::dma::SetList(NxPs2::sGroup::pParticles);\r\n\r\n\t// the system and streams will be loaded to a double-buffered input area of VUMem1\r\n\t// ref the system data, and include an unpack for the system and streams:\r\n\tNxPs2::dma::Tag(NxPs2::dma::ref, (sizeof(CSystemDmaDataFlat)>>4), (uint)&m_systemDmaData);\r\n\tNxPs2::vif::STCYCL(1,1);\r\n\tNxPs2::vif::UNPACK(0, V4_32, (sizeof(CSystemDmaDataFlat)>>4)+m_num_streams*2, REL, SIGNED, 0);\r\n\r\n\t// construct a packet with data for each stream\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tfor (i=0,p_stream=mp_oldest_stream; i<m_num_streams; i++,p_stream++)\r\n\t{\r\n\t\tDbg_MsgAssert(m_num_particles<65536, (\"particle limit reached (65536)\"));\r\n\r\n\t\t// wrap at end of cyclic buffer\r\n\t\tif (p_stream == mp_stream + m_max_streams)\r\n\t\t{\r\n\t\t\tp_stream = mp_stream;\r\n\t\t}\r\n\r\n\t\t((float  *)NxPs2::dma::pLoc)[0] = p_stream->m_oldest_age;\r\n\t\t((float  *)NxPs2::dma::pLoc)[1] = p_stream->m_interval;\r\n\t\t((uint32 *)NxPs2::dma::pLoc)[2] = p_stream->m_num_particles;\r\n\t\t((uint32 *)NxPs2::dma::pLoc)[3] = (p_stream==mp_newest_stream) ? 0x8000 : 0;\r\n\t\t((uint32 *)NxPs2::dma::pLoc)[4] = p_stream->m_seed[0];\r\n\t\t((uint32 *)NxPs2::dma::pLoc)[5] = p_stream->m_seed[1];\r\n\t\t((uint32 *)NxPs2::dma::pLoc)[6] = p_stream->m_seed[2];\r\n\t\t((uint32 *)NxPs2::dma::pLoc)[7] = p_stream->m_seed[3];\r\n\r\n\t\t//printf(\"stream %d, num particles=%d, oldest age=%f\\n\", s, p_stream->m_num_particles, p_stream->m_oldest_age);\r\n\r\n\t\t// step dma pointer\r\n\t\tNxPs2::dma::pLoc += 8*4;\r\n\r\n\t\t// count particles\r\n\t\tNxPs2::render::sTotalNewParticles += p_stream->m_num_particles;\r\n\t}\r\n\r\n\tNxPs2::vif::MSCAL(10);\t// sprites\r\n\tNxPs2::dma::EndTag();\r\n\tNxPs2::dma::SetList(NxPs2::sGroup::pEpilogue);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleNewFlat::plat_build_path( void )\r\n{\r\n\tfloat midTime;\r\n\r\n\t// set m_life\r\n\tm_life = 0.5f * (m_life_min + m_life_max);\r\n\r\n\t// set clamped local midtime variable\r\n\tif (m_mid_time <= 0.0f)\r\n\t{\r\n\t\tmidTime = 0.0f;\r\n\t}\r\n\telse if (m_mid_time >= 100.0f)\r\n\t{\r\n\t\tmidTime = m_life;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmidTime = m_mid_time * 0.01f * m_life;\r\n\t}\r\n\r\n\t// x-component will be overwritten by vu1 code, so can store midtime there\r\n\t*(float *)&m_systemDmaData.m_tagx = midTime;\r\n\r\n\r\n\t// constant part\r\n\tm_systemDmaData.m_s0x = m_emit_w;\r\n\tm_systemDmaData.m_s0y = 0.0f;\r\n\tm_systemDmaData.m_s0z = m_emit_h;\r\n\tm_systemDmaData.m_s0w = 0.0f;\r\n\r\n\tm_systemDmaData.m_c0x = m_pos[0] - 1.5f * m_systemDmaData.m_s0x;\r\n\tm_systemDmaData.m_c0y = m_pos[1] - 1.5f * m_systemDmaData.m_s0y;\r\n\tm_systemDmaData.m_c0z = m_pos[2] - 1.5f * m_systemDmaData.m_s0z;\r\n\tm_systemDmaData.m_c0w = m_sw     - 1.5f * m_systemDmaData.m_s0w;\r\n\r\n\r\n\t// linear part\r\n\tMth::Vector vel(m_tx,m_ty,m_tz,0.0f);\r\n\tfloat speed = 60.0f * 0.5 * (m_speed_min + m_speed_max);\r\n\tvel.Normalize();\r\n\tvel *= speed;\r\n\tm_systemDmaData.m_s1x = speed * Mth::PI/2.0f * m_emit_angle_spread;\r\n\tm_systemDmaData.m_s1y = 60.0f * (m_speed_max - m_speed_min);\r\n\tm_systemDmaData.m_s1z = speed * Mth::PI/2.0f * m_emit_angle_spread;\r\n\tm_systemDmaData.m_s1w = 0.0f;\r\n\r\n\tm_systemDmaData.m_c1x = vel[0]               - 1.5f * m_systemDmaData.m_s1x;\r\n\tm_systemDmaData.m_c1y = vel[1]               - 1.5f * m_systemDmaData.m_s1y;\r\n\tm_systemDmaData.m_c1z = vel[2]               - 1.5f * m_systemDmaData.m_s1z;\r\n\tm_systemDmaData.m_c1w = (m_ew-m_sw) / m_life - 1.5f * m_systemDmaData.m_s1w;\r\n\r\n\r\n\t// quadratic part\r\n\tm_systemDmaData.m_s2x = 0.0f;\r\n\tm_systemDmaData.m_s2y = 0.0f;\r\n\tm_systemDmaData.m_s2z = 0.0f;\r\n\tm_systemDmaData.m_s2w = 0.0f;\r\n\r\n\tm_systemDmaData.m_c2x = m_fx*0.5f*(60.0f*60.0f) - 1.5f * m_systemDmaData.m_s2x;\r\n\tm_systemDmaData.m_c2y = m_fy*0.5f*(60.0f*60.0f) - 1.5f * m_systemDmaData.m_s2y;\r\n\tm_systemDmaData.m_c2z = m_fz*0.5f*(60.0f*60.0f) - 1.5f * m_systemDmaData.m_s2z;\r\n\tm_systemDmaData.m_c2w = 0.0f                    - 1.5f * m_systemDmaData.m_s2w;\r\n\r\n\r\n\t// cubic part\r\n\t//m_systemDmaData.m_s3x = 0.0f;\r\n\t//m_systemDmaData.m_s3y = 0.0f;\r\n\t//m_systemDmaData.m_s3z = 0.0f;\r\n\t//m_systemDmaData.m_s3w = 0.0f;\r\n\r\n\t//m_systemDmaData.m_c3x = 0.0f - 1.5f * m_systemDmaData.m_s3x;\r\n\t//m_systemDmaData.m_c3y = 0.0f - 1.5f * m_systemDmaData.m_s3y;\r\n\t//m_systemDmaData.m_c3z = 0.0f - 1.5f * m_systemDmaData.m_s3z;\r\n\t//m_systemDmaData.m_c3w = 0.0f - 1.5f * m_systemDmaData.m_s3w;\r\n\t\r\n\r\n\t// colour\r\n\tif (m_mid_time >= 0.0f)\t\t// if using mid-colour\r\n\t{\r\n\t\tfloat q0 = 1.0f / midTime;\r\n\t\tfloat q1 = 1.0f / (m_life - midTime);\r\n\r\n\t\tm_systemDmaData.m_c0r = ((float)m_mid_color.r - (float)m_start_color.r) * q0;\r\n\t\tm_systemDmaData.m_c0g = ((float)m_mid_color.g - (float)m_start_color.g) * q0;\r\n\t\tm_systemDmaData.m_c0b = ((float)m_mid_color.b - (float)m_start_color.b) * q0;\r\n\t\tm_systemDmaData.m_c0a = ((float)m_mid_color.a - (float)m_start_color.a) * q0;\r\n\r\n\t\tm_systemDmaData.m_c1r = (float)m_mid_color.r;\r\n\t\tm_systemDmaData.m_c1g = (float)m_mid_color.g;\r\n\t\tm_systemDmaData.m_c1b = (float)m_mid_color.b;\r\n\t\tm_systemDmaData.m_c1a = (float)m_mid_color.a;\r\n\r\n\t\tm_systemDmaData.m_c2r = ((float)m_end_color.r - (float)m_mid_color.r) * q1;\r\n\t\tm_systemDmaData.m_c2g = ((float)m_end_color.g - (float)m_mid_color.g) * q1;\r\n\t\tm_systemDmaData.m_c2b = ((float)m_end_color.b - (float)m_mid_color.b) * q1;\r\n\t\tm_systemDmaData.m_c2a = ((float)m_end_color.a - (float)m_mid_color.a) * q1;\r\n\t}\r\n\telse\t\t\t\t\t\t// else suppress mid-colour\r\n\t{\r\n\t\tfloat q = 1.0f / m_life;\r\n\r\n\t\tm_systemDmaData.m_c1r = (float)m_start_color.r;\r\n\t\tm_systemDmaData.m_c1g = (float)m_start_color.g;\r\n\t\tm_systemDmaData.m_c1b = (float)m_start_color.b;\r\n\t\tm_systemDmaData.m_c1a = (float)m_start_color.a;\r\n\r\n\t\tm_systemDmaData.m_c2r = ((float)m_end_color.r - (float)m_start_color.r) * q;\r\n\t\tm_systemDmaData.m_c2g = ((float)m_end_color.g - (float)m_start_color.g) * q;\r\n\t\tm_systemDmaData.m_c2b = ((float)m_end_color.b - (float)m_start_color.b) * q;\r\n\t\tm_systemDmaData.m_c2a = ((float)m_end_color.a - (float)m_start_color.a) * q;\r\n\t}\r\n\r\n\r\n\t// rotation matrix, hardwired to the identity for now\r\n\tm_rotation.Identity();\r\n\r\n\t// temp test\r\n\t//m_rotation[0][0] =  0.8;\r\n\t//m_rotation[0][1] =  0.6;\r\n\t//m_rotation[1][0] = -0.6;\r\n\t//m_rotation[1][1] =  0.8;\r\n\r\n\t// invert rotation and apply to spatial params\r\n\t// leaving this code a bit shoddy and slow until full transition to new-style params\r\n\tMth::Matrix mat;\r\n\tmat=m_rotation;\r\n\tmat.Transpose();\r\n\tMth::Vector vec;\r\n\r\n\tvec[0] = m_systemDmaData.m_c0x + 1.5f * m_systemDmaData.m_s0x;\r\n\tvec[1] = m_systemDmaData.m_c0y + 1.5f * m_systemDmaData.m_s0y;\r\n\tvec[2] = m_systemDmaData.m_c0z + 1.5f * m_systemDmaData.m_s0z;\r\n\tvec[3] = 0;\r\n\tvec *= mat;\r\n\tm_systemDmaData.m_c0x = vec[0] - 1.5f * m_systemDmaData.m_s0x;\r\n\tm_systemDmaData.m_c0y = vec[1] - 1.5f * m_systemDmaData.m_s0y;\r\n\tm_systemDmaData.m_c0z = vec[2] - 1.5f * m_systemDmaData.m_s0z;\r\n\r\n\tvec[0] = m_systemDmaData.m_c1x + 1.5f * m_systemDmaData.m_s1x;\r\n\tvec[1] = m_systemDmaData.m_c1y + 1.5f * m_systemDmaData.m_s1y;\r\n\tvec[2] = m_systemDmaData.m_c1z + 1.5f * m_systemDmaData.m_s1z;\r\n\tvec[3] = 0;\r\n\tvec *= mat;\r\n\tm_systemDmaData.m_c1x = vec[0] - 1.5f * m_systemDmaData.m_s1x;\r\n\tm_systemDmaData.m_c1y = vec[1] - 1.5f * m_systemDmaData.m_s1y;\r\n\tm_systemDmaData.m_c1z = vec[2] - 1.5f * m_systemDmaData.m_s1z;\r\n\t\r\n\tvec[0] = m_systemDmaData.m_c2x + 1.5f * m_systemDmaData.m_s2x;\r\n\tvec[1] = m_systemDmaData.m_c2y + 1.5f * m_systemDmaData.m_s2y;\r\n\tvec[2] = m_systemDmaData.m_c2z + 1.5f * m_systemDmaData.m_s2z;\r\n\tvec[3] = 0;\r\n\tvec *= mat;\r\n\tm_systemDmaData.m_c2x = vec[0] - 1.5f * m_systemDmaData.m_s2x;\r\n\tm_systemDmaData.m_c2y = vec[1] - 1.5f * m_systemDmaData.m_s2y;\r\n\tm_systemDmaData.m_c2z = vec[2] - 1.5f * m_systemDmaData.m_s2z;\r\n\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CParticleStream::AdvanceSeed(int num_places)\r\n{\r\n\tfor (int i=0; i<num_places; i++)\r\n\t{\r\n\t\tm_seed[0]  = m_seed[3]<<1 | ((m_seed[3]>>4 ^ m_seed[3]>>22) & 1);\r\n\t\tm_seed[1] ^= m_seed[0];\r\n\t\tm_seed[2] ^= m_seed[1];\r\n\t\tm_seed[3] ^= m_seed[2];\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CPs2ParticleNewFlat::GetNumParticles()\r\n{\r\n\tint i, total=0;\r\n\tCParticleStream *p_stream;\r\n\r\n\tfor (i=0, p_stream=mp_oldest_stream; i<m_num_streams; i++)\r\n\t{\r\n\t\t// add this stream to tally\r\n\t\ttotal += p_stream->m_num_particles;\r\n\r\n\t\t// step pointer within cyclic buffer\r\n\t\tp_stream++;\r\n\t\tif (p_stream == mp_stream + m_max_streams)\r\n\t\t{\r\n\t\t\tp_stream = mp_stream;\r\n\t\t}\r\n\t}\r\n\r\n\treturn total;\r\n}\r\n\r\n\r\n} // Nx\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticlenewflat.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLENEWFLAT_H__\r\n#define\t__GFX_P_NX_PARTICLENEWFLAT_H__\r\n    \r\n#include \"gfx/ngps/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\nclass CParticleSpan\r\n{\r\npublic:\r\n\tfloat\t\t\t\t\tm_sx,m_sy,m_sz;\t\t\t// Start, mid & end points of span path.\r\n\tfloat\t\t\t\t\tm_mx,m_my,m_mz;\t\t\t// This should really be the coefficients you need to\r\n\tfloat\t\t\t\t\tm_ex,m_ey,m_ez;\t\t\t// describe the path, not the raw position data.\r\n\tunsigned char\t\t\tm_sr,m_sg,m_sb,m_sa;\t// Start color\r\n\tunsigned char\t\t\tm_er,m_eg,m_eb,m_ea;\t// End color\r\n};\r\n\r\nclass CParticleStream\r\n{\r\npublic:\r\n\tint\t\t\t\t\t\tm_num_particles;\r\n\tfloat\t\t\t\t\tm_rate;\r\n\tfloat\t\t\t\t\tm_interval;\r\n\tfloat\t\t\t\t\tm_oldest_age;\r\n\tuint32\t\t\t\t\tm_seed[4];\r\n\tvoid\t\t\t\t\tAdvanceSeed(int num_places);\r\n};\r\n\r\nclass CSystemDmaDataFlat\r\n{\r\npublic:\r\n\tuint32\t\t\t\t\tm_GScontext[20];\r\n\tuint32\t\t\t\t\tm_u0,  m_v0,  m_u1,  m_v1;\r\n\tfloat\t\t\t\t\tm_c0x, m_c0y, m_c0z, m_c0w;\r\n\tfloat\t\t\t\t\tm_c1x, m_c1y, m_c1z, m_c1w;\r\n\tfloat\t\t\t\t\tm_c2x, m_c2y, m_c2z, m_c2w;\r\n\tfloat\t\t\t\t\tm_s0x, m_s0y, m_s0z, m_s0w;\r\n\tfloat\t\t\t\t\tm_s1x, m_s1y, m_s1z, m_s1w;\r\n\tfloat\t\t\t\t\tm_s2x, m_s2y, m_s2z, m_s2w;\r\n\tfloat\t\t\t\t\tm_c0r, m_c0g, m_c0b, m_c0a;\r\n\tfloat\t\t\t\t\tm_c1r, m_c1g, m_c1b, m_c1a;\r\n\tfloat\t\t\t\t\tm_c2r, m_c2g, m_c2b, m_c2a;\r\n\tuint32\t\t\t\t\tm_tagx,m_tagy,m_tagz,m_tagw;\r\n\tMth::Matrix\t\t\t\tm_matrix;\r\n} nAlign(128);\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CPs2ParticleNewFlat : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2ParticleNewFlat();\r\n\t\t\t\t\t\t\tCPs2ParticleNewFlat( uint32 checksum, int max_streams, uint32 texture_checksum, uint32 blendmode_checksum, int fix );\r\n\tvirtual \t\t\t\t~CPs2ParticleNewFlat();\r\n\r\n\tint\t\t\t\t\t\tGetNumParticles();\r\n\r\n//\tNxPs2::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_build_path( void );\r\n\t\t\r\n\tImage::RGBA\t\t\t\tm_start_color;\t\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color;\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color;\t\t\t\t// End color for each corner.\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n\r\n\tuint64\t\t\t\t\tm_blend;\r\n\r\n\tint\t\t\t\t\t\tm_max_streams;\t\t\t// Maximum number of particle streams.\r\n\tint\t\t\t\t\t\tm_num_streams;\t\t\t// Number of active streams.\r\n\tint\t\t\t\t\t\tm_num_spans;\t\t\t// Number of span segments.\r\n\r\n\tCParticleSpan*\t\t\tmp_span;\r\n\tCParticleStream*\t\tmp_stream;\r\n\tCParticleStream*\t\tmp_newest_stream;\r\n\tCParticleStream*\t\tmp_oldest_stream;\r\n\tfloat\t\t\t\t\tm_life;\r\n\tbool\t\t\t\t\tm_emitting;\r\n\r\n\r\n\tMth::Matrix\t\t\t\tm_rotation;\r\n\r\n\t// dma data\r\n\tCSystemDmaDataFlat\t\t\tm_systemDmaData;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleribbon.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n\r\n#include \"gfx/ngps/p_nxparticleRibbon.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleRibbon::CPs2ParticleRibbon()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleRibbon::CPs2ParticleRibbon( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float*[( history + 1)];\r\n\tfor ( int lp = 0; lp < ( history + 1 ); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxPs2::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 2; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleRibbon::~CPs2ParticleRibbon()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\t\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleRibbon::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleRibbon::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleRibbon::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CPs2ParticleRibbon::plat_get_num_particle_colors( void ) { return 2; }\r\nint CPs2ParticleRibbon::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CPs2ParticleRibbon::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CPs2ParticleRibbon::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CPs2ParticleRibbon::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CPs2ParticleRibbon::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleRibbon::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CPs2ParticleRibbon::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CPs2ParticleRibbon::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CPs2ParticleRibbon::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleRibbon::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CPs2ParticleRibbon::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CPs2ParticleRibbon::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CPs2ParticleRibbon::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value >> 1; }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleRibbon::plat_render( void )\r\n{\r\n\tif (m_num_particles == 0)\r\n\t\treturn;\r\n\r\n\t// Draw the particles.\r\n\t\r\n//\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n//\t//Mth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraOrientation;\r\n//\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n//\r\n//\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n//\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n//\r\n//\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n//\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n//\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n//\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n//\r\n//\tscreen_right.Normalize();\r\n//\tscreen_up.Normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v0;\r\n\tfloat\t\t\t*p_v1;\r\n\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tNxPs2::CImmediateMode::sStartPolyDraw( mp_engine_texture, m_blend, ABS );\r\n\r\n\tImage::RGBA color[2];\r\n\tImage::RGBA *p_col0;\r\n\tImage::RGBA *p_col1;\r\n\r\n\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v0 = mp_vertices[0], p_v1 = mp_vertices[(m_num_vertex_buffers-1)]; lp < m_num_particles; lp++, p_particle++, p_v0 += 3, p_v1 += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tMth::Vector\tpos0( p_v0[0] + m_pos[X], p_v0[1] + m_pos[Y], p_v0[2] + m_pos[Z] );\r\n\t\tMth::Vector\tpos1( p_v1[0] + m_pos[X], p_v1[1] + m_pos[Y], p_v1[2] + m_pos[Z] );\r\n\r\n\t\tMth::Vector\tpart_vec = pos1 - pos0;\r\n\t\tMth::Vector perp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\tperp_vec.Normalize();\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n//\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\t\t\r\n//\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n//\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[4];\r\n//\t\r\n\t\ttmp[0]\t\t= pos0 + ( perp_vec * w );\r\n\t\ttmp[1]\t\t= pos0 - ( perp_vec * w );\r\n\t\ttmp[2]\t\t= pos1 - ( perp_vec * w );\r\n\t\ttmp[3]\t\t= pos1 + ( perp_vec * w );\r\n\t\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 2; c++ )\r\n\t\t{\r\n\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\r\n\t\tNxPs2::CImmediateMode::sDrawQuadTexture( mp_engine_texture, tmp[0], tmp[1], tmp[2], tmp[3], *((uint32 *) &color[0]), *((uint32 *) &color[0]), *((uint32 *) &color[1]), *((uint32 *) &color[1]) );\r\n\t}\r\n\r\n\tNxPs2::dma::EndTag();\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleribbon.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLERibbon_H__\r\n#define\t__GFX_P_NX_PARTICLERibbon_H__\r\n    \r\n#include \"gfx/ngps/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CPs2ParticleRibbon : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2ParticleRibbon();\r\n\t\t\t\t\t\t\tCPs2ParticleRibbon( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CPs2ParticleRibbon();\r\n\r\n//\tNxPs2::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\t//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tint\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tfloat**\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n//\tNxPs2::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tImage::RGBA\t\t\t\tm_start_color[2];\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color[2];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color[2];\t\t\t\t// End color for each corner.\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleribbontrail.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n\r\n#include \"gfx/ngps/p_nxparticleRibbonTrail.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleRibbonTrail::CPs2ParticleRibbonTrail()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleRibbonTrail::CPs2ParticleRibbonTrail( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float*[( history + 1)];\r\n\tfor ( int lp = 0; lp < ( history + 1 ); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxPs2::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tm_start_color = new Image::RGBA[m_num_vertex_buffers];\r\n\tm_mid_color = new Image::RGBA[m_num_vertex_buffers];\r\n\tm_end_color = new Image::RGBA[m_num_vertex_buffers];\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleRibbonTrail::~CPs2ParticleRibbonTrail()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\t\r\n\tdelete [] m_start_color;\r\n\tdelete [] m_mid_color;\r\n\tdelete [] m_end_color;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleRibbonTrail::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleRibbonTrail::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleRibbonTrail::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CPs2ParticleRibbonTrail::plat_get_num_particle_colors( void ) { return m_num_vertex_buffers; }\r\nint CPs2ParticleRibbonTrail::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CPs2ParticleRibbonTrail::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CPs2ParticleRibbonTrail::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CPs2ParticleRibbonTrail::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CPs2ParticleRibbonTrail::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleRibbonTrail::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CPs2ParticleRibbonTrail::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CPs2ParticleRibbonTrail::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CPs2ParticleRibbonTrail::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleRibbonTrail::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CPs2ParticleRibbonTrail::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CPs2ParticleRibbonTrail::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CPs2ParticleRibbonTrail::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value >> 1; }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleRibbonTrail::plat_render( void )\r\n{\r\n\tif (m_num_particles == 0)\r\n\t\treturn;\r\n\r\n\t// Draw the particles.\r\n\t\r\n//\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n//\t//Mth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraOrientation;\r\n//\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n//\r\n//\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n//\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n//\r\n//\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n//\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n//\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n//\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n//\r\n//\tscreen_right.Normalize();\r\n//\tscreen_up.Normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tNxPs2::CImmediateMode::sStartPolyDraw( mp_engine_texture, m_blend, ABS );\r\n\r\n\tImage::RGBA color[2];\r\n\tImage::RGBA *p_col0;\r\n\tImage::RGBA *p_col1;\r\n\r\n\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array; lp < m_num_particles; lp++, p_particle++ )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tMth::Vector\tpos[2];\r\n\t\tp_v = &mp_vertices[0][lp*3];\r\n\t\tpos[0].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tp_v = &mp_vertices[1][lp*3];\r\n\t\tpos[1].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\r\n\t\tMth::Vector\tpart_vec = pos[1] - pos[0];\r\n\t\tMth::Vector perp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\tperp_vec.Normalize();\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\t\r\n\t\tMth::Vector tmp[4];\r\n\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tImage::RGBA start = *p_col0++;\r\n\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\tcolor[0].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\tcolor[0].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\tcolor[0].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\tcolor[0].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\r\n\t\ttmp[0]\t\t= pos[0] + ( perp_vec * w );\r\n\t\ttmp[1]\t\t= pos[0] - ( perp_vec * w );\r\n\r\n\t\tfor ( int c = 1; c < m_num_vertex_buffers; c++ )\r\n\t\t{\r\n\t\t\tstart = *p_col0++;\r\n\t\t\tend = *p_col1++;\r\n\r\n\t\t\tcolor[1].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[1].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[1].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[1].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\r\n\t\t\tif ( c > 1 )\r\n\t\t\t{\r\n\t\t\t\tp_v = &mp_vertices[c][lp*3];\r\n\t\t\t\tpos[1].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\t\t\tpart_vec = pos[1] - pos[0];\r\n\t\t\t\tperp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\t\t\tperp_vec.Normalize();\r\n\t\t\t}\r\n\r\n\t\t\ttmp[2]\t\t= pos[1] - ( perp_vec * w );\r\n\t\t\ttmp[3]\t\t= pos[1] + ( perp_vec * w );\r\n\r\n\t\t\tNxPs2::CImmediateMode::sDrawQuadTexture( mp_engine_texture, tmp[0], tmp[1], tmp[2], tmp[3], *((uint32 *) &color[0]), *((uint32 *) &color[0]), *((uint32 *) &color[1]), *((uint32 *) &color[1]) );\r\n\r\n\t\t\tcolor[0] = color[1];\r\n\t\t\tpos[0] = pos[1];\r\n\t\t\ttmp[0] = tmp[3];\r\n\t\t\ttmp[1] = tmp[2];\r\n\t\t}\r\n\t}\r\n\r\n\tNxPs2::dma::EndTag();\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleribbontrail.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLERibbonTrail_H__\r\n#define\t__GFX_P_NX_PARTICLERibbonTrail_H__\r\n    \r\n#include \"gfx/ngps/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CPs2ParticleRibbonTrail : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2ParticleRibbonTrail();\r\n\t\t\t\t\t\t\tCPs2ParticleRibbonTrail( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CPs2ParticleRibbonTrail();\r\n\r\n//\tNxPs2::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\t//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tint\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tfloat**\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n//\tNxPs2::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tImage::RGBA*\t\t\tm_start_color;\t\t\t\t// Start color for each corner.\r\n\tImage::RGBA*\t\t\tm_mid_color;\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA*\t\t\tm_end_color;\t\t\t\t// End color for each corner.\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleshaded.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n\r\n#include \"gfx/ngps/p_nxparticleShaded.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleShaded::CPs2ParticleShaded()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleShaded::CPs2ParticleShaded( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxPs2::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 4; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleShaded::~CPs2ParticleShaded()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleShaded::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleShaded::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleShaded::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CPs2ParticleShaded::plat_get_num_particle_colors( void ) { return 4; }\r\nint CPs2ParticleShaded::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CPs2ParticleShaded::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CPs2ParticleShaded::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CPs2ParticleShaded::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CPs2ParticleShaded::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleShaded::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CPs2ParticleShaded::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CPs2ParticleShaded::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CPs2ParticleShaded::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleShaded::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CPs2ParticleShaded::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CPs2ParticleShaded::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CPs2ParticleShaded::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value >> 1; }\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleShaded::plat_render( void )\r\n{\r\n\tif (m_num_particles == 0)\r\n\t\treturn;\r\n\r\n\t// Draw the particles.\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t//Mth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraOrientation;\r\n\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\tscreen_right.Normalize();\r\n\tscreen_up.Normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tNxPs2::CImmediateMode::sStartPolyDraw( mp_engine_texture, m_blend, ABS );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v = mp_vertices; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[4];\r\n\t\r\n\t\tss_right\t= screen_right * w;\r\n\t\tss_up\t\t= screen_up * h;\r\n\t\r\n\t\ttmp[0]\t\t= pos - ss_right + ss_up;\r\n\t\ttmp[1]\t\t= pos + ss_right + ss_up;\t\t\r\n\t\ttmp[2]\t\t= pos + ss_right - ss_up;\t\t\r\n\t\ttmp[3]\t\t= pos - ss_right - ss_up;\t\t\r\n\t\r\n\t\tImage::RGBA color[4];\r\n\t\tImage::RGBA *p_col0;\r\n\t\tImage::RGBA *p_col1;\r\n\t\t\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 4; c++ )\r\n\t\t{\r\n\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\t\tNxPs2::CImmediateMode::sDrawQuadTexture( mp_engine_texture, tmp[0], tmp[1], tmp[2], tmp[3],\r\n\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color[0]),\r\n\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color[1]),\r\n\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color[2]),\r\n\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color[3]));\r\n\t}\r\n\r\n\tNxPs2::dma::EndTag();\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticleshaded.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLEShaded_H__\r\n#define\t__GFX_P_NX_PARTICLEShaded_H__\r\n    \r\n#include \"gfx/ngps/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CPs2ParticleShaded : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2ParticleShaded();\r\n\t\t\t\t\t\t\tCPs2ParticleShaded( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CPs2ParticleShaded();\r\n\r\n//\tNxPs2::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n//\tNxPs2::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tImage::RGBA\t\t\t\tm_start_color[4];\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color[4];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color[4];\t\t\t\t// End color for each corner.\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticlesmooth.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n\r\n#include \"gfx/ngps/p_nxparticleSmooth.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleSmooth::CPs2ParticleSmooth()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleSmooth::CPs2ParticleSmooth( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxPs2::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 2; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleSmooth::~CPs2ParticleSmooth()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleSmooth::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleSmooth::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleSmooth::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CPs2ParticleSmooth::plat_get_num_particle_colors( void ) { return 2; }\r\nint CPs2ParticleSmooth::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CPs2ParticleSmooth::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CPs2ParticleSmooth::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CPs2ParticleSmooth::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CPs2ParticleSmooth::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleSmooth::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CPs2ParticleSmooth::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CPs2ParticleSmooth::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CPs2ParticleSmooth::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleSmooth::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CPs2ParticleSmooth::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CPs2ParticleSmooth::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CPs2ParticleSmooth::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value >> 1; }\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleSmooth::plat_render( void )\r\n{\r\n\tif (m_num_particles == 0)\r\n\t\treturn;\r\n\r\n\t// Draw the particles.\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t//Mth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraOrientation;\r\n\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\tscreen_right.Normalize();\r\n\tscreen_up.Normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tNxPs2::CImmediateMode::sStartPolyDraw( mp_engine_texture, m_blend, ABS );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v = mp_vertices; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[4];\r\n\t\r\n\t\tss_right\t= screen_right * w;\r\n\t\tss_up\t\t= screen_up * h;\r\n\t\r\n\t\ttmp[0]\t\t= pos - ss_right + ss_up;\r\n\t\ttmp[1]\t\t= pos + ss_right + ss_up;\t\t\r\n\t\ttmp[2]\t\t= pos + ss_right - ss_up;\t\t\r\n\t\ttmp[3]\t\t= pos - ss_right - ss_up;\t\t\r\n\t\r\n\t\tImage::RGBA color[2];\r\n\t\tImage::RGBA *p_col0;\r\n\t\tImage::RGBA *p_col1;\r\n\t\t\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 2; c++ )\r\n\t\t{\r\n\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\t\tNxPs2::CImmediateMode::sDraw5QuadTexture( mp_engine_texture, pos, tmp[0], tmp[1], tmp[2], tmp[3],\r\n\t\t\t\t\t\t\t\t\t\t\t\t  *((uint32 *) &color[0]),\r\n\t\t\t\t\t\t\t\t\t\t\t\t  *((uint32 *) &color[1]));\r\n\t}\r\n\r\n\tNxPs2::dma::EndTag();\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticlesmooth.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLESmooth_H__\r\n#define\t__GFX_P_NX_PARTICLESmooth_H__\r\n    \r\n#include \"gfx/ngps/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CPs2ParticleSmooth : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2ParticleSmooth();\r\n\t\t\t\t\t\t\tCPs2ParticleSmooth( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CPs2ParticleSmooth();\r\n\r\n//\tNxPs2::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n//\tNxPs2::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tImage::RGBA\t\t\t\tm_start_color[2];\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color[2];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color[2];\t\t\t\t// End color for each corner.\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticlesmoothribbon.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n\r\n#include \"gfx/ngps/p_nxparticleSmoothRibbon.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleSmoothRibbon::CPs2ParticleSmoothRibbon()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleSmoothRibbon::CPs2ParticleSmoothRibbon( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float*[( history + 1)];\r\n\tfor ( int lp = 0; lp < ( history + 1 ); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxPs2::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 4; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleSmoothRibbon::~CPs2ParticleSmoothRibbon()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\t\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleSmoothRibbon::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleSmoothRibbon::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleSmoothRibbon::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CPs2ParticleSmoothRibbon::plat_get_num_particle_colors( void ) { return 4; }\r\nint CPs2ParticleSmoothRibbon::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CPs2ParticleSmoothRibbon::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CPs2ParticleSmoothRibbon::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CPs2ParticleSmoothRibbon::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CPs2ParticleSmoothRibbon::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleSmoothRibbon::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CPs2ParticleSmoothRibbon::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CPs2ParticleSmoothRibbon::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CPs2ParticleSmoothRibbon::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleSmoothRibbon::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CPs2ParticleSmoothRibbon::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CPs2ParticleSmoothRibbon::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CPs2ParticleSmoothRibbon::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value >> 1; }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleSmoothRibbon::plat_render( void )\r\n{\r\n\tif (m_num_particles == 0)\r\n\t\treturn;\r\n\r\n\t// Draw the particles.\r\n\t\r\n//\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n//\t//Mth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraOrientation;\r\n//\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n//\r\n//\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n//\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n//\r\n//\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n//\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n//\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n//\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n//\r\n//\tscreen_right.Normalize();\r\n//\tscreen_up.Normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v0;\r\n\tfloat\t\t\t*p_v1;\r\n\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tNxPs2::CImmediateMode::sStartPolyDraw( mp_engine_texture, m_blend, ABS );\r\n\r\n\tImage::RGBA color[4];\r\n\tImage::RGBA *p_col0;\r\n\tImage::RGBA *p_col1;\r\n\r\n\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v0 = mp_vertices[0], p_v1 = mp_vertices[(m_num_vertex_buffers-1)]; lp < m_num_particles; lp++, p_particle++, p_v0 += 3, p_v1 += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tMth::Vector\tpos0( p_v0[0] + m_pos[X], p_v0[1] + m_pos[Y], p_v0[2] + m_pos[Z] );\r\n\t\tMth::Vector\tpos1( p_v1[0] + m_pos[X], p_v1[1] + m_pos[Y], p_v1[2] + m_pos[Z] );\r\n\r\n\t\tMth::Vector\tpart_vec = pos1 - pos0;\r\n\t\tMth::Vector perp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\tperp_vec.Normalize();\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n//\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\t\t\r\n//\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n//\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[4];\r\n//\t\r\n\t\ttmp[0]\t\t= pos0 + ( perp_vec * w );\r\n\t\ttmp[1]\t\t= pos0 - ( perp_vec * w );\r\n\t\ttmp[2]\t\t= pos1 - ( perp_vec * w );\r\n\t\ttmp[3]\t\t= pos1 + ( perp_vec * w );\r\n\t\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 4; c++ )\r\n\t\t{\r\n\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\r\n\t\tNxPs2::CImmediateMode::sDrawQuadTexture( mp_engine_texture, pos0, tmp[0], tmp[3], pos1, *((uint32 *) &color[0]), *((uint32 *) &color[1]), *((uint32 *) &color[2]), *((uint32 *) &color[3]) );\r\n\t\tNxPs2::CImmediateMode::sDrawQuadTexture( mp_engine_texture, pos0, tmp[1], tmp[2], pos1, *((uint32 *) &color[0]), *((uint32 *) &color[1]), *((uint32 *) &color[2]), *((uint32 *) &color[3]) );\r\n\t}\r\n\t\r\n\tNxPs2::dma::EndTag();\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticlesmoothribbon.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLESmoothRibbon_H__\r\n#define\t__GFX_P_NX_PARTICLESmoothRibbon_H__\r\n    \r\n#include \"gfx/ngps/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CPs2ParticleSmoothRibbon : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2ParticleSmoothRibbon();\r\n\t\t\t\t\t\t\tCPs2ParticleSmoothRibbon( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CPs2ParticleSmoothRibbon();\r\n\r\n//\tNxPs2::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\t//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tint\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tfloat**\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n//\tNxPs2::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tImage::RGBA\t\t\t\tm_start_color[4];\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color[4];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color[4];\t\t\t\t// End color for each corner.\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticlesmoothstar.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n\r\n#include \"gfx/ngps/p_nxparticleSmoothStar.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleSmoothStar::CPs2ParticleSmoothStar()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleSmoothStar::CPs2ParticleSmoothStar( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\t\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxPs2::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 3; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n\r\n\tm_num_segments = num_segments;\r\n\tm_split = split;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleSmoothStar::~CPs2ParticleSmoothStar()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleSmoothStar::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleSmoothStar::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleSmoothStar::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CPs2ParticleSmoothStar::plat_get_num_particle_colors( void ) { return 3; }\r\nint CPs2ParticleSmoothStar::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CPs2ParticleSmoothStar::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CPs2ParticleSmoothStar::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CPs2ParticleSmoothStar::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CPs2ParticleSmoothStar::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleSmoothStar::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CPs2ParticleSmoothStar::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CPs2ParticleSmoothStar::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CPs2ParticleSmoothStar::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleSmoothStar::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CPs2ParticleSmoothStar::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CPs2ParticleSmoothStar::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CPs2ParticleSmoothStar::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value >> 1; }\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleSmoothStar::plat_render( void )\r\n{\r\n\tif (m_num_particles == 0)\r\n\t\treturn;\r\n\r\n\t// Draw the particles.\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t//Mth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraOrientation;\r\n\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\tscreen_right.Normalize();\r\n\tscreen_up.Normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tNxPs2::CImmediateMode::sStartPolyDraw( mp_engine_texture, m_blend, ABS );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v = mp_vertices; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[4];\r\n\t\r\n\t\tss_right\t= screen_right * w;\r\n\t\tss_up\t\t= screen_up * h;\r\n\t\r\n\t\tImage::RGBA color[3];\r\n\t\tImage::RGBA *p_col0;\r\n\t\tImage::RGBA *p_col1;\r\n\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 3; c++ )\r\n\t\t{\r\n\t\t\tImage::RGBA SmoothStart = *p_col0++;\r\n\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = SmoothStart.r + (uint8)(( ((float)( end.r - SmoothStart.r )) * terp ));\r\n\t\t\tcolor[c].g = SmoothStart.g + (uint8)(( ((float)( end.g - SmoothStart.g )) * terp ));\r\n\t\t\tcolor[c].b = SmoothStart.b + (uint8)(( ((float)( end.b - SmoothStart.b )) * terp ));\r\n\t\t\tcolor[c].a = SmoothStart.a + (uint8)(( ((float)( end.a - SmoothStart.a )) * terp ));\r\n\t\t}\r\n\r\n\t\ttmp[1]  = pos;\r\n\t\ttmp[1] += ss_right * sinf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\t\ttmp[1] += ss_up    * cosf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\r\n\t\tfor ( int lp2 = 0; lp2 < m_num_segments; lp2++ )\r\n\t\t{\r\n\t\t\ttmp[0]  = pos;\r\n\t\t\ttmp[0] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) ) * m_split;\r\n\t\t\ttmp[0] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) ) * m_split;\r\n\t\t\t\r\n\t\t\ttmp[3]  = pos;\r\n\t\t\ttmp[3] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 2 ) ) ) ) * m_split;\r\n\t\t\ttmp[3] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 2 ) ) ) ) * m_split;\r\n\t\t\t\r\n\t\t\ttmp[2]  = pos;\r\n\t\t\ttmp[2] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) );\r\n\t\t\ttmp[2] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) );\r\n\r\n\t\t\tNxPs2::CImmediateMode::sDrawSmoothStarSegment( tmp[0], pos, tmp[1], tmp[2], tmp[3],\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *((uint32 *) &color[0]),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *((uint32 *) &color[1]),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *((uint32 *) &color[2]));\r\n\t\t\ttmp[1] = tmp[3];\r\n\t\t}\r\n\t}\r\n\t\r\n\tNxPs2::dma::EndTag();\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticlesmoothstar.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLESmoothStar_H__\r\n#define\t__GFX_P_NX_PARTICLESmoothStar_H__\r\n    \r\n#include \"gfx/ngps/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CPs2ParticleSmoothStar : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2ParticleSmoothStar();\r\n\t\t\t\t\t\t\tCPs2ParticleSmoothStar( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CPs2ParticleSmoothStar();\r\n\r\n//\tNxPs2::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n\r\n//\tNxPs2::sParticleSystem*\tmp_engine_particle;\r\n\tint\t\t\t\t\t\tm_num_segments;\r\n\tfloat\t\t\t\t\tm_split;\r\n\tImage::RGBA\t\t\t\tm_start_color[3];\t\t\t// SmoothStart color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color[3];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color[3];\t\t\t\t// End color for each corner.\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticlestar.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n\r\n#include \"gfx/ngps/p_nxparticleStar.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleStar::CPs2ParticleStar()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleStar::CPs2ParticleStar( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum = checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n//\t// Create the engine representation.\r\n//\tmp_engine_particle = new NxPs2::sParticleSystem( max_particles, texture_checksum, blendmode_checksum, fix );\r\n//\r\n\r\n\t// Get the texture.\r\n\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_engine_texture = NULL;\r\n\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_engine_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\t// Set blendmode.\r\n\tm_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 3; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n\r\n\tm_num_segments = num_segments;\r\n\tm_split = split;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2ParticleStar::~CPs2ParticleStar()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n//\tdelete mp_engine_particle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleStar::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleStar::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleStar::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CPs2ParticleStar::plat_get_num_particle_colors( void ) { return 3; }\r\nint CPs2ParticleStar::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CPs2ParticleStar::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CPs2ParticleStar::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CPs2ParticleStar::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CPs2ParticleStar::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleStar::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CPs2ParticleStar::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CPs2ParticleStar::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CPs2ParticleStar::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value >> 1; }\r\nvoid CPs2ParticleStar::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CPs2ParticleStar::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CPs2ParticleStar::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CPs2ParticleStar::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value >> 1; }\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2ParticleStar::plat_render( void )\r\n{\r\n\tif (m_num_particles == 0)\r\n\t\treturn;\r\n\r\n\t// Draw the particles.\r\n\t\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t//Mth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraOrientation;\r\n\tMth::Matrix* p_matrix = (Mth::Matrix*)&NxPs2::render::CameraToWorldRotation;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tMth::Vector at( p_matrix->GetAt()[X], p_matrix->GetAt()[Y], p_matrix->GetAt()[Z], 0.0f );\r\n\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\tscreen_right.Normalize();\r\n\tscreen_up.Normalize();\r\n\t\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry\t*p_particle;\r\n\tfloat\t\t\t*p_v;\r\n\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tNxPs2::CImmediateMode::sStartPolyDraw( mp_engine_texture, m_blend, ABS );\r\n\r\n\tfor ( lp = 0, p_particle = mp_particle_array, p_v = mp_vertices; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t{\r\n\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\tfloat h = p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\tMth::Vector tmp[3];\r\n\t\r\n\t\tss_right\t= screen_right * w;\r\n\t\tss_up\t\t= screen_up * h;\r\n\t\r\n\t\tImage::RGBA color[3];\r\n\t\tImage::RGBA *p_col0;\r\n\t\tImage::RGBA *p_col1;\r\n\r\n\t\tif ( m_mid_time >= 0.0f )\r\n\t\t{\r\n\t\t\tif ( terp < m_mid_time )\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\tp_col1 = m_mid_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No mid color specified.\r\n\t\t\tp_col0 = m_start_color;\r\n\t\t\tp_col1 = m_end_color;\r\n\t\t}\r\n\r\n\t\tfor ( int c = 0; c < 3; c++ )\r\n\t\t{\r\n\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t}\r\n\r\n\t\ttmp[0]  = pos;\r\n\t\ttmp[0] += ss_right * sinf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\t\ttmp[0] += ss_up    * cosf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\r\n\t\tfor ( int lp2 = 0; lp2 < m_num_segments; lp2++ )\r\n\t\t{\r\n\t\t\ttmp[1]  = pos;\r\n\t\t\ttmp[1] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\t\t\ttmp[1] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\r\n\t\t\ttmp[2]  = pos;\r\n\t\t\ttmp[2] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) );\r\n\t\t\ttmp[2] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) );\r\n\r\n\t\t\tNxPs2::CImmediateMode::sDrawStarSegment( pos, tmp[0], tmp[1], tmp[2],\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color[0]),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color[1]),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t *((uint32 *) &color[2]));\r\n\t\t\ttmp[0] = tmp[1];\r\n\t\t}\r\n\t}\r\n\r\n\tNxPs2::dma::EndTag();\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxparticlestar.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLEStar_H__\r\n#define\t__GFX_P_NX_PARTICLEStar_H__\r\n    \r\n#include \"gfx/ngps/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CPs2ParticleStar : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2ParticleStar();\r\n\t\t\t\t\t\t\tCPs2ParticleStar( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CPs2ParticleStar();\r\n\r\n//\tNxPs2::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n//\tvoid*\t\t\t\t\tmp_display_list;\r\n//\tint\t\t\t\t\t\tm_display_list_size;\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n\r\n//\tNxPs2::sParticleSystem*\tmp_engine_particle;\r\n\tint\t\t\t\t\t\tm_num_segments;\r\n\tfloat\t\t\t\t\tm_split;\r\n\tImage::RGBA\t\t\t\tm_start_color[3];\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color[3];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color[3];\t\t\t\t// End color for each corner.\r\n\tNxPs2::SSingleTexture*\tmp_engine_texture;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxweather.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxWeather.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  6/2/2003\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n\r\n#include \"gfx/ngps/nx/line.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/ngps/p_nxtexture.h>\r\n\r\n#include \"gfx/ngps/nx/immediate.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#include \"gfx/ngps/nx/mesh.h\"\r\n\r\n#include \"gfx/ngps/p_nxweather.h\"\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/skater.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <engine/SuperSector.h>\r\n#include \"gfx/nx.h\"\r\n\r\n#include \"gfx/ngps/nx/render.h\"\r\n#include \"gfx/ngps/nx/dma.h\"\r\n#include \"gfx/ngps/nx/vif.h\"\r\n#include \"gfx/ngps/nx/vu1.h\"\r\n#include \"gfx/ngps/nx/gif.h\"\r\n#include \"gfx/ngps/nx/gs.h\"\r\n#include \"gfx/ngps/nx/sprite.h\"\r\n#include \"gfx/ngps/nx/switches.h\"\r\n#include \"gfx/ngps/nx/vu1code.h\"\r\n\r\n#define FEELER_START 50000.0f\r\n\r\n#define _STCYCL(a,b) ((uint32)0x01<<24 | (uint32)0<<16 | (uint32)((a)<<8|(b)))\r\n#define _UNPACK(m,v,s,f,u,a) (((0x60|(m)<<4|(v))<<24) | ((s)<<16) | ((f)<<15 | (u)<<14 | ((NxPs2::vu1::Loc+(a))&0x03FF)))\r\n\r\n#define _NREG(n) ((float)(n) * 1.1920928955e-07f)\r\n#define _PRIM(n,f,p,r,a) (n)<<28 | (f)<<26 | (p)<<15 | (r)<<14 | (a)\r\n\r\n#define _BEGINUNPACK(m,v,f,u,a,nbytes)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t((uint32)(0x60 | (m)<<4 | (v))<<24 |\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\t\t\t\t\t(uint32)(( ((nbytes) << 3) / ( (((v)>>2 & 3) + 1) * (32 >> ((v) & 3)) ) ))<<16 |\t\t\t\\\r\n\t\t\t\t\t(uint32)((f)<<15 | (u)<<14 | ((NxPs2::vu1::Loc+(a))&0x03FF)))\r\n\r\n\r\n#define _STMOD(o) ((uint32)0x05<<24 | (uint32)0<<16 | (uint32)(o)) \r\n\r\n\r\n#define _SIZE(v,nbytes) ((uint32)(( ((nbytes) << 3) / ( (((v)>>2 & 3) + 1) * (32 >> ((v) & 3)) ) )))\r\n\r\n#define _PARSER ((uint32)0x14<<24 | (uint32)0<<16 | (uint32)VU1_ADDR(Parser)) \r\n\r\n#define NUM_LINES_PER_BATCH 80\r\n#define NUM_SPRITES_PER_BATCH 80\r\n\r\n#define PRECISION_SHIFT 4\r\n\r\nunsigned char grid_bytes[70*1024];\r\n\r\n#define RENDER_DIST 16\r\n//#define RAIN_HEIGHT 2000\r\n//#define RAIN_FRAMES 40\r\n//#define RAIN_LENGTH 100.0f\r\n#define SEQ_START 411\t\t// Between 1 and 4095.\r\n#define SEQ_MASK 0x0240\r\n//#define SEQ_MASK 0x0ca0\r\n//#define NUM_DROPS_PER_FRAME 25\r\n\r\n//1-3: 0x03\r\n//1-7: 0x06\r\n//1-15: 0x0C\r\n//1-31: 0x14\r\n//1-63: 0x30\r\n//1-127: 0x60\r\n//1-255: 0xB8\r\n//1-511: 0x0110\r\n//1-1023: 0x0240\r\n//1-2047: 0x0500\r\n//1-4095: 0x0CA0\r\n//1-8191: 0x1B00\r\n//1-16383: 0x3500\r\n//1-32767: 0x6000\r\n//1-65535: 0xB400\r\n//0x00012000\r\n//0x00020400\r\n//0x00072000\r\n//0x00090000\r\n//0x00140000\r\n//0x00300000\r\n//0x00400000\r\n//0x00D80000\r\n//0x01200000\r\n//0x03880000\r\n//0x07200000\r\n//0x09000000\r\n//0x14000000\r\n//0x32800000\r\n//0x48000000\r\n//0xA3000000\r\n\r\n\r\n//#define DEBUG_LINES\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2Weather::CPs2Weather()\r\n{\r\n\tmp_roof_height_index = NULL;\r\n\tmp_rain_texture = NULL;\r\n\r\n\tm_rain_blend = NxPs2::CImmediateMode::sGetTextureBlend( CRCD(0xa86285a1,\"fixadd\"), 64 );\t\t// FixAdd / 64\r\n\tm_splash_blend = NxPs2::CImmediateMode::sGetTextureBlend( CRCD(0xa86285a1,\"fixadd\"), 64 );\t\t// FixAdd / 64\r\n\tm_snow_blend = NxPs2::CImmediateMode::sGetTextureBlend( CRCD(0xa86285a1,\"fixadd\"), 64 );\t\t// FixAdd / 64\r\n\r\n\tm_rain_rate = 0.0f;\r\n\tm_splash_rate = 0.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCPs2Weather::~CPs2Weather()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2Weather::plat_update_grid( void )\r\n{\r\n\tm_system_active = false;\r\n\t// Get super sector manager.\r\n\tSSec::Manager *ss_man;\r\n\tMth::Line line;\r\n\tss_man = Nx::CEngine::sGetNearestSuperSectorManager( line );\t\t// Line is ignored, 1st manager is returned.\r\n\tif ( !ss_man ) return;\r\n\r\n\t// Calculate the size of the world in cels.\r\n\tint min_x = ( ((int)ss_man->GetWorldBBox()->GetMin()[X]) / WEATHER_CEL_SIZE ) - 1;\r\n\tint max_x = ( ((int)ss_man->GetWorldBBox()->GetMax()[X]) / WEATHER_CEL_SIZE ) + 1;\r\n\tint min_z = ( ((int)ss_man->GetWorldBBox()->GetMin()[Z]) / WEATHER_CEL_SIZE ) - 1;\r\n\tint max_z = ( ((int)ss_man->GetWorldBBox()->GetMax()[Z]) / WEATHER_CEL_SIZE ) + 1;\r\n\r\n\t// Define a maximum...\r\n\tif ( ( max_x - min_x ) > 350 )\r\n\t{\r\n\t\tint wid = ( max_x - min_x );\r\n\t\tint excess = ( wid - 350 );\r\n\t\tmin_x += ( excess / 2 );\r\n\t\tmax_x -= ( excess / 2 );\r\n\t}\r\n\r\n\tif ( ( max_z - min_z ) > 300 )\r\n\t{\r\n\t\tint wid = ( max_z - min_z );\r\n\t\tint excess = ( wid - 300 );\r\n\t\tmin_z += ( excess / 2 );\r\n\t\tmax_z -= ( excess / 2 );\r\n\t}\r\n\r\n\t// This is the actual width;\r\n\tm_width = ( max_x - min_x ) + 1;\r\n\tm_height = ( max_z - min_z ) + 1;\r\n\r\n\t// Allocate a new piece of memory for the grid.\r\n//\tif ( mp_roof_height_index ) delete mp_roof_height_index;\r\n//\tmp_roof_height_index = new unsigned char[m_width * m_height];\r\n\r\n//\tmp_roof_height_index = grid_bytes;\r\n\r\n\tm_min_x = ( min_x * WEATHER_CEL_SIZE );\r\n\tm_min_z = ( min_z * WEATHER_CEL_SIZE );\r\n\r\n\t// Temporary buffer for the raw array.\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tunsigned char * p8 = new unsigned char[m_width*m_height];\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Go through and get the height for each cel corner.\r\n\tCFeeler feeler;\r\n\tint num_heights = 0;\r\n\tint xx, zz;\r\n\tfor ( zz = min_z; zz <= max_z; zz++ )\r\n\t{\r\n\t\tfor ( xx = min_x; xx <= max_x; xx++ )\r\n\t\t{\r\n\t\t\t// The cel to fill.\r\n\t\t\tint cel = ( ( zz - min_z ) * m_width ) + ( xx - min_x );\r\n\r\n\t\t\t// The position to check.\r\n\t\t\tMth::Vector pos;\r\n\t\t\tpos[X] = (float)( xx * WEATHER_CEL_SIZE );\r\n\t\t\tpos[Y] = FEELER_START;\r\n\t\t\tpos[Z] = (float)( zz * WEATHER_CEL_SIZE );\r\n\t\t\tpos[W] = 1.0f;\r\n\r\n\t\t\tfeeler.SetStart( pos );\r\n\t\t\tpos[Y] = -FEELER_START;\r\n\t\t\tfeeler.SetEnd( pos );\r\n\r\n\t\t\t// Get the y position.\r\n\t\t\tsint32 y;\r\n\t\t\tif ( feeler.GetCollision( false, false ) )\t\t// No movables, nearest collision.\r\n\t\t\t{\r\n\t\t\t\ty = (sint32)( feeler.GetPoint()[Y] * SUB_INCH_PRECISION );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ty = (sint32)( FEELER_START * SUB_INCH_PRECISION );\r\n\t\t\t}\r\n\r\n\t\t\t// See if a close enough y pos already exists.\r\n\t\t\tint found = -1;\r\n\t\t\tfor ( int lp = 0; lp < num_heights; lp++ )\r\n\t\t\t{\r\n\t\t\t\tif ( abs( ( m_roof_height[lp] - y ) ) < HEIGHT_TOLERANCE )\r\n\t\t\t\t{\r\n\t\t\t\t\tfound = lp;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Fill in the cel.\r\n\t\t\tif ( found != -1 )\r\n\t\t\t{\r\n\t\t\t\t// Existing height.\r\n\t\t\t\tp8[cel] = found;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// New height.\r\n\t\t\t\tp8[cel] = num_heights;\r\n\t\t\t\tm_roof_height[num_heights] = y;\r\n\t\t\t\tnum_heights++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Work out highest height for each cel.\r\n\tfor ( zz = min_z; zz <= max_z; zz++ )\r\n\t{\r\n\t\tfor ( xx = min_x; xx <= max_x; xx++ )\r\n\t\t{\r\n\t\t\t// The cel to fill.\r\n\t\t\tint cel = ( ( zz - min_z ) * m_width ) + ( xx - min_x );\r\n\t\t\tint celx = ( ( zz - min_z ) * m_width ) + ( ( xx + 1 ) - min_x );\r\n\t\t\tint celz = ( ( ( zz + 1 ) - min_z ) * m_width ) + ( xx - min_x );\r\n\t\t\tint celxz = ( ( ( zz + 1 ) - min_z ) * m_width ) + ( ( xx + 1 ) - min_x );\r\n\r\n\t\t\tif ( m_roof_height[p8[celx]] > m_roof_height[p8[cel]] ) p8[cel] = p8[celx];\r\n\t\t\tif ( m_roof_height[p8[celz]] > m_roof_height[p8[cel]] ) p8[cel] = p8[celz];\r\n\t\t\tif ( m_roof_height[p8[celxz]] > m_roof_height[p8[cel]] ) p8[cel] = p8[celxz];\r\n\t\t}\r\n\t}\r\n\r\n\t// Create a sparse array.\r\n\tmp_roof_row = (sRowEntry *)grid_bytes;\r\n\tmp_roof_height_index = (unsigned char *)&mp_roof_row[m_height];\r\n\r\n\t// 0 = offset\r\n\t// 1 = width\r\n\t// 2 = index\r\n\r\n\tunsigned short index = 0;\r\n\tfor ( zz = 0; zz <= m_height; zz++ )\r\n\t{\r\n\t\tunsigned short start = 0;\r\n\t\tunsigned short end = m_width - 1;\r\n\r\n\t\t// Scan to find the start.\r\n\t\tbool start_set = false;\r\n\t\tfor ( xx = 0; xx < m_width; xx++ )\r\n\t\t{\r\n\t\t\tint cel = ( zz * m_width ) + xx;\r\n\r\n\t\t\tif ( m_roof_height[p8[cel]] != (sint32)( FEELER_START * SUB_INCH_PRECISION ) )\r\n\t\t\t{\r\n\t\t\t\tif ( !start_set )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Set start value.\r\n\t\t\t\t\tstart = xx;\r\n\t\t\t\t\tstart_set = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Set end value.\r\n\t\t\t\t\tend = xx;\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Copy data & set row entry.\r\n\t\tif ( start < end )\r\n\t\t{\r\n\t\t\tmp_roof_row[zz].start = start;\r\n\t\t\tmp_roof_row[zz].end = end;\r\n\t\t\tmp_roof_row[zz].index = index;\r\n\t\t\tfor ( xx = start; xx <= end ; xx++ )\r\n\t\t\t{\r\n\t\t\t\tint cel = ( zz * m_width ) + xx;\r\n\r\n\t\t\t\tmp_roof_height_index[index] = p8[cel];\r\n\t\t\t\tindex++;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Row doesn't exist.\r\n\t\t\tmp_roof_row[zz].start = 16384;\r\n\t\t\tmp_roof_row[zz].end = 0;\r\n\t\t\tmp_roof_row[zz].index = 0;\r\n\t\t}\r\n\t}\r\n\r\n\tdelete p8;\r\n\r\n\tint new_size = ( m_height * 6 ) + index;\r\n\r\n\tprintf( \"Grid Size: Old: %d New: %d Num Heights: %d\\n\", ( m_width * m_height ), new_size, num_heights );\r\n//\tprintf( \"Num Weather Grid Heights: %d (%d x %d)\\n\", num_heights, m_width, m_height );\r\n\r\n\t// Set all drip time counters to 255.\r\n\t// 255 means the drop won't be rendered.\r\n\t// Setting to anything other than 255 will mean that it will increment to 255 and stop.\r\n\tfor ( int lp = 0; lp < ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ); lp++ )\r\n\t{\r\n\t\tm_drop_time[lp] = 255;\r\n\t\tm_x_offset[lp] = Mth::Rnd( 255 );\r\n\t\tm_z_offset[lp] = Mth::Rnd( 255 );\r\n\t}\r\n\tm_active_drops = 0;\r\n\r\n\tm_seq = SEQ_START;\r\n\r\n\t// Get the texture.\r\n\tNx::CTexture *p_texture;\r\n\tNx::CPs2Texture *p_ps2_texture;\r\n\tmp_rain_texture = NULL;\r\n\r\n\t// Set Rain Texture.\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( CRCD(0x45c7eb0f,\"splash\") );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_rain_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\t// Set Snow Texture.\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( CRCD(0xc97c5a4c,\"snow\") );\r\n\tp_ps2_texture = static_cast<Nx::CPs2Texture*>( p_texture );\r\n\tif ( p_ps2_texture )\r\n\t{\r\n\t\tmp_snow_texture = p_ps2_texture->GetSingleTexture(); \r\n\t}\r\n\r\n\tm_system_active = true;\r\n\r\n\t// Zero out the splashes.\r\n\tfor ( int sp = 0; sp < NUM_SPLASH_ACTIVE; sp++ )\r\n\t{\r\n\t\tm_splash_current_life[sp] = 0;\r\n\t}\r\n\tm_current_splash = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2Weather::plat_process( float delta_time )\r\n{\r\n\tif ( !m_system_active ) return;\r\n\r\n\tif ( m_raining )\r\n\t{\r\n\t\t// It's raining.\r\n\t\tfloat rate = m_rain_drops_per_frame;\r\n\t\tif ( rate > (float)( ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ) / m_rain_frames ) ) rate = (float)( ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ) / m_rain_frames );\r\n\r\n\t\tfloat last = m_rain_rate;\r\n\t\tm_rain_rate += rate;\r\n\t\tint new_drops = (int)m_rain_rate - (int)last;\r\n\r\n\t\tfor ( int lp = 0; lp < new_drops; lp++ )\r\n\t\t{\r\n\t\t\t// If this cel is not inactive, we caught up with ourselves.\r\n\t\t\tif ( m_drop_time[m_seq] != 255 ) break;\r\n\r\n\t\t\t// Setup the drop.\r\n\t\t\tm_drop_time[m_seq] = ( 254 - m_rain_frames );\r\n\t\t\tm_x_offset[m_seq] = Mth::Rnd( 255 );\r\n\t\t\tm_z_offset[m_seq] = Mth::Rnd( 255 );\r\n\t\t\tm_active_drops++;\r\n\r\n\t\t\t// Calculate next sequence value. Notice hack to get entry 0 into the sequence.\r\n\t\t\tswitch ( m_seq )\r\n\t\t\t{\r\n\t\t\t\tcase SEQ_START:\r\n\t\t\t\t\tm_seq = 0;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tm_seq = SEQ_START;\r\n\t\t\t\t\t// Fall through to default case...\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tif ( m_seq & 1 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_seq = ( m_seq >> 1 ) ^ SEQ_MASK;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_seq = ( m_seq >> 1 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// It's snowing.\r\n\t\tfloat rate = m_snow_flakes_per_frame;\r\n\t\tif ( rate > (float)( ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ) / m_snow_frames ) ) rate = (float)( ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ) / m_snow_frames );\r\n\r\n\t\tfloat last = m_snow_rate;\r\n\t\tm_snow_rate += rate;\r\n\t\tint new_drops = (int)m_snow_rate - (int)last;\r\n\r\n\t\tfor ( int lp = 0; lp < new_drops; lp++ )\r\n\t\t{\r\n\t\t\t// If this cel is not inactive, we caught up with ourselves.\r\n\t\t\tif ( m_drop_time[m_seq] != 255 ) break;\r\n\r\n\t\t\t// Setup the drop.\r\n\t\t\tm_drop_time[m_seq] = ( 254 - m_snow_frames );\r\n\t\t\tm_x_offset[m_seq] = Mth::Rnd( 255 );\r\n\t\t\tm_z_offset[m_seq] = Mth::Rnd( 255 );\r\n\t\t\tm_active_drops++;\r\n\r\n\t\t\t// Calculate next sequence value. Notice hack to get entry 0 into the sequence.\r\n\t\t\tswitch ( m_seq )\r\n\t\t\t{\r\n\t\t\t\tcase SEQ_START:\r\n\t\t\t\t\tm_seq = 0;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tm_seq = SEQ_START;\r\n\t\t\t\t\t// Fall through to default case...\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tif ( m_seq & 1 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_seq = ( m_seq >> 1 ) ^ SEQ_MASK;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_seq = ( m_seq >> 1 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2Weather::plat_render_snow( float skx, float skz )\r\n{\r\n\t// Early out if no drops to draw.\r\n\tif ( !m_active_drops ) return;\r\n\r\n\t// Get skater position.\r\n\tint x = (int)( ( skx - m_min_x ) / WEATHER_CEL_SIZE );\r\n\tint z = (int)( ( skz - m_min_z ) / WEATHER_CEL_SIZE );\r\n\r\n\t// Calculate area to render.\r\n\tint sx = x - RENDER_DIST;\r\n\tint ex = x + DROP_SIZE;\t//RENDER_DIST;\r\n\tint sz = z - RENDER_DIST;\r\n\tint ez = z + DROP_SIZE;\t//RENDER_DIST;\r\n\r\n\t// Clip z values.\r\n\tif ( ez < 0 ) return;\r\n\tif ( sz > ( m_height - 1 ) ) return;\r\n\r\n//\tif ( sz < 0 ) sz = 0;\r\n//\tif ( ez > ( m_height - 1 ) ) ez = ( m_height - 1 );\r\n\r\n#ifdef DEBUG_LINES\r\n\tNxPs2::BeginLines3D( 0xffffffff );\r\n#else\r\n\t// add a dma packet\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\r\n\t// VU context\r\n\tNxPs2::vu1::BeginPrim(ABS, VU1_ADDR(L_VF10));\r\n\tNxPs2::vu1::StoreVec(*(NxPs2::Vec *)&NxPs2::render::InverseIntViewportScale);\r\n\tNxPs2::vu1::StoreVec(*(NxPs2::Vec *)&NxPs2::render::InverseIntViewportOffset);\r\n\tNxPs2::vu1::StoreMat(*(NxPs2::Mat *)&NxPs2::render::WorldToIntViewport);\t// VF12-15\r\n\tNxPs2::vu1::EndPrim(0);\r\n\tNxPs2::vu1::BeginPrim(ABS, VU1_ADDR(L_VF30));\r\n\tNxPs2::vif::StoreV4_32F(640.0f, 480.0f, 0.0f, 0.0f);\t\t\t\t\t\t// VF30\r\n\tNxPs2::vif::StoreV4_32F(NxPs2::render::IntViewportScale[0]/NxPs2::render::Tx,\t// VF31\r\n\t\t\t\t\t\t\tNxPs2::render::IntViewportScale[1]/NxPs2::render::Ty,\r\n\t\t\t\t\t\t\t0.0f, 0.0f);\r\n\tNxPs2::vu1::EndPrim(0);\r\n\r\n\t// GS context\r\n\tNxPs2::gs::BeginPrim(ABS, 0, 0);\r\n\tNxPs2::gs::Reg1(NxPs2::gs::ALPHA_1,\tm_snow_blend);\r\n\tNxPs2::gs::Reg1(NxPs2::gs::TEX0_1,\tmp_snow_texture->m_RegTEX0);\r\n\tNxPs2::gs::Reg1(NxPs2::gs::TEX1_1,\tmp_snow_texture->m_RegTEX1);\r\n\tNxPs2::gs::Reg1(NxPs2::gs::ST,\t\tPackST(0x3F800000,0x3F800000));\r\n\tNxPs2::gs::Reg1(NxPs2::gs::RGBAQ,\tPackRGBAQ(0,0,0,0,0x3F800000));\r\n\tNxPs2::gs::EndPrim(0);\r\n\r\n#endif\t\t// DEBUG_LINES\r\n\r\n\tfloat minx = m_min_x;\r\n\tfloat minz = m_min_z;\r\n//\tsint32 rlength = (sint32)( m_rain_length * SUB_INCH_PRECISION );\r\n\t\r\n\t// Calculate drop height list.\r\n\tint lp;\r\n\tfloat y_off[256];\r\n\r\n\tfor ( lp = ( 254 - m_snow_frames ); lp < 256; lp++ )\r\n\t{\r\n\t\ty_off[lp] = m_snow_height - ( ( (float)( ( lp - 254 ) + m_snow_frames ) / (float)m_snow_frames ) * m_snow_height );\r\n\t}\r\n\r\n\t// Calculate xz offset list.\r\n\tfloat xz_off[256];\r\n\r\n\tfor ( lp = 0; lp < 256; lp++ )\r\n\t{\r\n\t\txz_off[lp] = ( (float)lp * (float)( WEATHER_CEL_SIZE / 2 ) ) / 255.0f;\r\n\t}\r\n\r\n\t// Calculate sine wave.\r\n\tfloat sin_off[256];\r\n\r\n\tfor ( lp = 0; lp < 256; lp++ )\r\n\t{\r\n\t\tsin_off[lp] = sinf( Mth::PI * 2.0f * ( (float)lp / 256.0f ) ) * ( WEATHER_CEL_SIZE / 2 );\r\n//\t\tsin_off[lp] = sinf( Mth::PI * 2.0f * (float)lp ) * 128.0f;\r\n\t}\r\n\r\n\tint flakes = 0;\r\n\tuint32 * p_col = NULL;\r\n\tfloat * p_xyz = NULL;\r\n//\tuint32 * p_last_loc = NULL;\r\n//\tuint32 * p_tag = NULL;\r\n\r\n\tfor ( int lzz = sz; lzz <= ez; lzz++ )\r\n\t{\r\n\t\tint zz = ( lzz < 0 ) ? 0 : ( lzz > ( m_height - 1 ) ) ? ( m_height - 1 ) : lzz;\r\n\r\n\t\tif ( mp_roof_row[zz].start == 16384 ) continue;\r\n\r\n//\t\t// Calculate actual span to scan.\r\n//\t\tint rsx = sx > mp_roof_row[zz].start ? sx : mp_roof_row[zz].start;\r\n//\t\tint rex = ex < mp_roof_row[zz].end ? ex : mp_roof_row[zz].end;\r\n//\r\n//\t\t// Start position.\r\n//\t\tsint32 vx = ( (sint32)rsx * WEATHER_CEL_SIZE * (sint32)SUB_INCH_PRECISION ) + minx;\r\n//\t\tsint32 vz = ( (sint32)zz * WEATHER_CEL_SIZE * (sint32)SUB_INCH_PRECISION ) + minz;\r\n\r\n\t\tfloat vx = ( (float)sx * (float)WEATHER_CEL_SIZE ) + minx;\r\n\t\tfloat vz = ( (float)zz * (float)WEATHER_CEL_SIZE ) + minz;\r\n\r\n\t\tint cel = mp_roof_row[zz].index + ( sx - mp_roof_row[zz].start );\r\n\r\n\t\tint drop_cel_z = ( ( zz & ( DROP_SIZE - 1 ) ) << DROP_SIZE_SHIFT );\r\n\r\n//\t\tfor ( int xx = rsx; xx <= rex; xx++, cel++ )\r\n\t\tfor ( int lxx = sx; lxx <= ex; lxx++, cel++ )\r\n\t\t{\r\n\t\t\tint xx = ( lxx > mp_roof_row[zz].start ) ? ( ( lxx < mp_roof_row[zz].end ) ? lxx : mp_roof_row[zz].end ) : mp_roof_row[zz].start;\r\n\r\n\t\t\t// Get the current drop value. Skip this one if it's inactive.\r\n\t\t\tint drop_cel = drop_cel_z + ( xx & ( DROP_SIZE - 1 ) );\r\n\r\n//\t\t\tvx += ( WEATHER_CEL_SIZE << PRECISION_SHIFT );\r\n\t\t\tvx += (float)WEATHER_CEL_SIZE;\r\n\t\t\tfloat vy = (float)( m_roof_height[mp_roof_height_index[cel]] >> PRECISION_SHIFT );\r\n\r\n\t\t\tfor ( int d = 0; d < DROP_LAYERS; d++, drop_cel += ( DROP_SIZE * DROP_SIZE ) )\r\n\t\t\t{\r\n\t\t\t\tif ( m_drop_time[drop_cel] == 255 ) continue;\r\n\r\n\t\t\t\t// Create the position for rendering.\r\n\t\t\t\tfloat v0x = vx + xz_off[m_x_offset[drop_cel]] + sin_off[(m_z_offset[drop_cel]+m_drop_time[drop_cel])&255];\r\n\t\t\t\tfloat v0y = vy + y_off[m_drop_time[drop_cel]] + m_snow_size;\r\n\t\t\t\tfloat v0z = vz + xz_off[m_z_offset[drop_cel]] + sin_off[(m_x_offset[drop_cel]+m_drop_time[drop_cel])&255];\r\n\r\n//\t\t\t\tsint32 v1y = v0y + rlength;\r\n\r\n#ifdef DEBUG_LINES\r\n\t\t\t\tNxPs2::DrawLine3D( v0[X], v0[Y], v0[Z], v1[X], v1[Y], v1[Z] );\r\n#else\r\n\t\t\t\tif ( flakes == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tNxPs2::BeginModelPrimImmediate(NxPs2::gs::XYZ2\t\t|\r\n\t\t\t\t\t\t\t\t\t\t\t\t   NxPs2::gs::ST<<4\t\t|\r\n\t\t\t\t\t\t\t\t\t\t\t\t   NxPs2::gs::RGBAQ<<8\t|\r\n\t\t\t\t\t\t\t\t\t\t\t\t   NxPs2::gs::XYZ2<<12,\r\n\t\t\t\t\t\t\t\t\t\t\t\t   4, SPRITE|ABE|TME, 1, VU1_ADDR(SpriteCull));\r\n\r\n\t\t\t\t\t// create an unpack for the colours\r\n\t\t\t\t\tNxPs2::vif::BeginUNPACK(0, V4_8, ABS, UNSIGNED, 3);\r\n\t\t\t\t\tp_col = (uint32 *)NxPs2::dma::pLoc;\r\n\t\t\t\t\tNxPs2::dma::pLoc += NUM_SPRITES_PER_BATCH * 4;\r\n\t\t\t\t\tNxPs2::vif::EndUNPACK();\r\n\r\n\t\t\t\t\t// and one for the positions (& sizes)\r\n\t\t\t\t\tNxPs2::vif::BeginUNPACK(0, V4_32, ABS, SIGNED, 4);\r\n\t\t\t\t\tp_xyz = (float *)NxPs2::dma::pLoc;\r\n\t\t\t\t\tNxPs2::dma::pLoc += NUM_SPRITES_PER_BATCH * 16;\r\n\t\t\t\t\tNxPs2::vif::EndUNPACK();\r\n\r\n\t\t\t\t\tNxPs2::EndModelPrimImmediate(1);\r\n\r\n\t\t\t\t\tNxPs2::vif::MSCAL(VU1_ADDR(Parser));\r\n\t\t\t\t\r\n\t\t\t\t\tflakes = NUM_SPRITES_PER_BATCH;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t*p_col++ = *((uint32 *)&m_snow_color);\r\n\r\n\t\t\t\tp_xyz[0] = v0x;\r\n\t\t\t\tp_xyz[1] = v0y;\r\n\t\t\t\tp_xyz[2] = v0z;\r\n\t\t\t\tp_xyz[3] = m_snow_size;\r\n\t\t\t\tp_xyz += 4;\r\n\r\n\t\t\t\tflakes--;\r\n\r\n#endif\t\t// DEBUG_LINES\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n//\tprintf( \"Drop comparison: Counted: %d Calculated: %d\\n\", drops, m_active_drops );\r\n\r\n\t// Fix the last packet.\r\n//\tif ( flakes == NUM_SPRITES_PER_BATCH )\r\n//\t{\r\n//\t\tNxPs2::vu1::Loc -= _SIZE(V4_32,16*NUM_SPRITES_PER_BATCH) * 2 + 1;\r\n//\t\tp_loc = p_last_loc;\r\n//\t}\r\n//\telse if ( lines )\r\n//\t{\r\n\tif ( flakes )\r\n\t{\r\n\t\t// Fill in with degenerate lines.\r\n\t\tfor ( int l = 0; l < flakes; l++ )\r\n\t\t{\r\n\t\t\tp_xyz[0] = 0;\r\n\t\t\tp_xyz[1] = 0;\r\n\t\t\tp_xyz[2] = 0;\r\n\t\t\tp_xyz[3] = 0;\r\n\r\n\t\t\tp_xyz += 4;\r\n\t\t}\r\n\t}\r\n\r\n#ifdef DEBUG_LINES\r\n\tNxPs2::EndLines3D();\r\n#else\r\n\t// restore transform\r\n\tNxPs2::vu1::BeginPrim(ABS, VU1_ADDR(L_VF12));\t\t// was L_VF16\r\n\tNxPs2::vu1::StoreMat(*(NxPs2::Mat *)&NxPs2::render::AdjustedWorldToViewport);\t\t// VF16-19\r\n\tNxPs2::vu1::EndPrim(1);\r\n\tNxPs2::vif::MSCAL(VU1_ADDR(Parser));\r\n\r\n\t// end the dma tag\r\n\tNxPs2::dma::EndTag();\r\n#endif\t\t// DEBUG_LINES\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2Weather::plat_render_rain( float skx, float skz )\r\n{\r\n\t// Early out if no drops to draw.\r\n\tif ( !m_active_drops ) return;\r\n\r\n\t// Get skater position.\r\n\tint x = (int)( ( skx - m_min_x ) / WEATHER_CEL_SIZE );\r\n\tint z = (int)( ( skz - m_min_z ) / WEATHER_CEL_SIZE );\r\n\r\n\t// Calculate area to render.\r\n\tint sx = x - RENDER_DIST;\r\n\tint ex = x + DROP_SIZE;\t//RENDER_DIST;\r\n\tint sz = z - RENDER_DIST;\r\n\tint ez = z + DROP_SIZE;\t//RENDER_DIST;\r\n\r\n\t// Clip z values.\r\n\tif ( ez < 0 ) return;\r\n\tif ( sz > ( m_height - 1 ) ) return;\r\n\r\n//\tif ( sz < 0 ) sz = 0;\r\n//\tif ( ez > ( m_height - 1 ) ) ez = ( m_height - 1 );\r\n\r\n#ifdef DEBUG_LINES\r\n\tNxPs2::BeginLines3D( 0xffffffff );\r\n#else\r\n\tNxPs2::BeginLines3D( 0xffffffff );\r\n\tNxPs2::EndLines3D();\r\n\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\tNxPs2::CImmediateMode::sStartPolyDraw( NULL, m_rain_blend, ABS );\r\n\tregister uint32 *p_loc = (uint32*)NxPs2::dma::pLoc;\r\n#endif\t\t// DEBUG_LINES\r\n\r\n\tsint32 minx = (sint32)( m_min_x * SUB_INCH_PRECISION );\r\n\tsint32 minz = (sint32)( m_min_z * SUB_INCH_PRECISION );\r\n\tsint32 rlength = (sint32)( m_rain_length * SUB_INCH_PRECISION );\r\n\t\r\n\t// Calculate drop height list.\r\n\tint lp;\r\n\tsint32 y_off[256];\r\n\r\n\tfor ( lp = ( 254 - m_rain_frames ); lp < 256; lp++ )\r\n\t{\r\n\t\ty_off[lp] = (sint32)( ( m_rain_height - ( ( (float)( ( lp - 254 ) + m_rain_frames ) / (float)m_rain_frames ) * m_rain_height ) ) * SUB_INCH_PRECISION );\r\n\t}\r\n\r\n\t// Calculate xz offset list.\r\n\tsint32 xz_off[256];\r\n\r\n\tfor ( lp = 0; lp < 256; lp++ )\r\n\t{\r\n\t\txz_off[lp] = (sint32)( ( ( (float)lp * (float)WEATHER_CEL_SIZE * SUB_INCH_PRECISION ) / 255.0f ) );\r\n\t}\r\n\r\n\tint lines = 0;\r\n\tuint32 * p_col = NULL;\r\n\tsint32 * p_xyz = NULL;\r\n\tuint32 * p_last_loc = NULL;\r\n//\tuint32 * p_tag = NULL;\r\n\r\n\tfor ( int lzz = sz; lzz <= ez; lzz++ )\r\n\t{\r\n\t\tint zz = ( lzz < 0 ) ? 0 : ( lzz > ( m_height - 1 ) ) ? ( m_height - 1 ) : lzz;\r\n\r\n\t\tif ( mp_roof_row[zz].start == 16384 ) continue;\r\n\r\n//\t\t// Calculate actual span to scan.\r\n//\t\tint rsx = sx > mp_roof_row[zz].start ? sx : mp_roof_row[zz].start;\r\n//\t\tint rex = ex < mp_roof_row[zz].end ? ex : mp_roof_row[zz].end;\r\n//\r\n//\t\t// Start position.\r\n//\t\tsint32 vx = ( (sint32)rsx * WEATHER_CEL_SIZE * (sint32)SUB_INCH_PRECISION ) + minx;\r\n//\t\tsint32 vz = ( (sint32)zz * WEATHER_CEL_SIZE * (sint32)SUB_INCH_PRECISION ) + minz;\r\n\r\n\t\tsint32 vx = ( (sint32)sx << ( WEATHER_CEL_SIZE_SHIFT + PRECISION_SHIFT ) ) + minx;\r\n\t\tsint32 vz = ( (sint32)zz << ( WEATHER_CEL_SIZE_SHIFT + PRECISION_SHIFT ) ) + minz;\r\n\r\n\t\tint cel = mp_roof_row[zz].index + ( sx - mp_roof_row[zz].start );\r\n\r\n\t\tint drop_cel_z = ( ( zz & ( DROP_SIZE - 1 ) ) << DROP_SIZE_SHIFT );\r\n\r\n//\t\tfor ( int xx = rsx; xx <= rex; xx++, cel++ )\r\n\t\tfor ( int lxx = sx; lxx <= ex; lxx++, cel++ )\r\n\t\t{\r\n\t\t\tint xx = ( lxx > mp_roof_row[zz].start ) ? ( ( lxx < mp_roof_row[zz].end ) ? lxx : mp_roof_row[zz].end ) : mp_roof_row[zz].start;\r\n\r\n\t\t\t// Get the current drop value. Skip this one if it's inactive.\r\n\t\t\tint drop_cel = drop_cel_z + ( xx & ( DROP_SIZE - 1 ) );\r\n\r\n\t\t\tvx += ( WEATHER_CEL_SIZE << PRECISION_SHIFT );\r\n\t\t\tsint32 vy = m_roof_height[mp_roof_height_index[cel]];\r\n\r\n\t\t\tfor ( int d = 0; d < DROP_LAYERS; d++, drop_cel += ( DROP_SIZE * DROP_SIZE ) )\r\n\t\t\t{\r\n\t\t\t\tif ( m_drop_time[drop_cel] == 255 ) continue;\r\n\r\n\t\t\t\t// Create the position for rendering.\r\n\t\t\t\tsint32 v0x = vx + xz_off[m_x_offset[drop_cel]];\r\n\t\t\t\tsint32 v0y = vy + y_off[m_drop_time[drop_cel]]; \r\n\t\t\t\tsint32 v0z = vz + xz_off[m_z_offset[drop_cel]];\r\n\r\n\t\t\t\tsint32 v1y = v0y + rlength;\r\n\r\n#ifdef DEBUG_LINES\r\n\t\t\t\tNxPs2::DrawLine3D( v0[X], v0[Y], v0[Z], v1[X], v1[Y], v1[Z] );\r\n#else\r\n\t\t\t\tif ( lines == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_last_loc = p_loc;\r\n\r\n\t\t\t\t\tp_loc[0] = _STCYCL(1,2);\r\n\t\t\t\t\tp_loc[1] = _UNPACK(0,V4_32,1,ABS,UNSIGNED,0);\r\n//\t\t\t\t\tp_tag = &p_loc[2];\r\n\t\t\t\t\t*(float*)&p_loc[2] = _NREG(2);\r\n\t\t\t\t\tp_loc[2] |= (1<<15) | _SIZE(V4_32,16*2*NUM_LINES_PER_BATCH);\r\n\r\n\t\t\t\t\tp_loc[3] = _PRIM(2, PACKED, LINE|IIP|ABE, 1, VU1_ADDR(Line));\r\n\t\t\t\t\tp_loc[4] = NxPs2::gs::XYZ2<<4|NxPs2::gs::RGBAQ;\r\n\t\t\t\t\tp_loc[5] = ( _SIZE(V4_32,16*2*NUM_LINES_PER_BATCH) * 2 ); \r\n\t\t\t\t\tp_loc[6] = _BEGINUNPACK(0, V4_8, ABS, UNSIGNED, 1, 4*2*NUM_LINES_PER_BATCH); \r\n\r\n\t\t\t\t\tlines = NUM_LINES_PER_BATCH;\r\n\r\n\t\t\t\t\tp_col = &p_loc[7];\r\n\t\t\t\t\tp_loc = &p_loc[7+(2*NUM_LINES_PER_BATCH)];\r\n\r\n\t\t\t\t\tp_loc[0] = _STMOD(OFFSET_MODE); \r\n\t\t\t\t\tp_loc[1] = _BEGINUNPACK(1, V4_32, ABS, SIGNED, 2, 16*2*NUM_LINES_PER_BATCH);\r\n\r\n\t\t\t\t\tp_xyz = (sint32 *)&p_loc[2];\r\n\t\t\t\t\tp_loc = &p_loc[2+(8*NUM_LINES_PER_BATCH)];\r\n\t\t\t\t\r\n\t\t\t\t\tp_loc[0] = _STMOD(NORMAL_MODE); \r\n\t\r\n\t\t\t\t\t// finish batch of vertices\r\n//\t\t\t\t\tp_tag[0] |= (1<<15) | SIZE(V4_32,16*2*NUM_LINES_PER_BATCH);\r\n\t\t\t\t\tNxPs2::vu1::Loc += _SIZE(V4_32,16*2*NUM_LINES_PER_BATCH) * 2 + 1;\r\n\t\r\n\t\t\t\t\tp_loc[1] = _PARSER;\r\n\t\t\t\t\tNxPs2::vu1::Buffer = NxPs2::vu1::Loc;\r\n\t\r\n\t\t\t\t\tp_loc = &p_loc[2];\r\n\r\n\t\t\t\t\t// Fill color regardless.\r\n\t\t\t\t\tuint32 col0 = *((uint32 *)&m_rain_bottom_color); \r\n\t\t\t\t\tuint32 col1 = *((uint32 *)&m_rain_top_color);    \r\n//\t\t\t\t\tfor ( int lp = 0; lp < ( NUM_LINES_PER_BATCH / 4 ); lp++ )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tp_col[0] = col0;\r\n//\t\t\t\t\t\tp_col[1] = col1;\r\n//\r\n//\t\t\t\t\t\tp_col[2] = col0;\r\n//\t\t\t\t\t\tp_col[3] = col1;\r\n//\t\t\t\t\t\r\n//\t\t\t\t\t\tp_col[4] = col0;\r\n//\t\t\t\t\t\tp_col[5] = col1;\r\n//\t\t\t\t\t\r\n//\t\t\t\t\t\tp_col[6] = col0;\r\n//\t\t\t\t\t\tp_col[7] = col1;\r\n//\r\n//\t\t\t\t\t\tp_col += 8;\r\n//\t\t\t\t\t}\r\n\r\n\t\t\t\t\tfor ( int lp = 0; lp < NUM_LINES_PER_BATCH; lp++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col[0] = col0;\r\n\t\t\t\t\t\tp_col[1] = col1;\r\n\r\n\t\t\t\t\t\tp_col += 2;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n//\t\t\t\tp_col[0] = col0;\r\n//\t\t\t\tp_col[1] = col1;\r\n\r\n\t\t\t\tp_xyz[0] = v0x;\r\n\t\t\t\tp_xyz[1] = v0y;\r\n\t\t\t\tp_xyz[2] = v0z;\r\n\t\t\t\tp_xyz[3] = 0;\r\n\t\t\t\tp_xyz[4] = v0x;\r\n\t\t\t\tp_xyz[5] = v1y;\r\n\t\t\t\tp_xyz[6] = v0z;\r\n\t\t\t\tp_xyz[7] = 0;\r\n\r\n//\t\t\t\tp_col += 2;\r\n\t\t\t\tp_xyz += 8;\r\n\r\n\t\t\t\tlines --;\r\n#endif\t\t// DEBUG_LINES\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n//\tprintf( \"Drop comparison: Counted: %d Calculated: %d\\n\", drops, m_active_drops );\r\n\r\n\t// Fix the last packet.\r\n\tif ( lines == NUM_LINES_PER_BATCH )\r\n\t{\r\n\t\tNxPs2::vu1::Loc -= _SIZE(V4_32,16*2*NUM_LINES_PER_BATCH) * 2 + 1;\r\n\t\tp_loc = p_last_loc;\r\n\t}\r\n\telse if ( lines )\r\n\t{\r\n\t\t// Fill in with degenerate lines.\r\n\t\tfor ( int l = 0; l < lines; l++ )\r\n\t\t{\r\n\t\t\tp_xyz[0] = 0;\r\n\t\t\tp_xyz[1] = 0;\r\n\t\t\tp_xyz[2] = 0;\r\n\t\t\tp_xyz[3] = 0;\r\n\t\t\tp_xyz[4] = 0;\r\n\t\t\tp_xyz[5] = 0;\r\n\t\t\tp_xyz[6] = 0;\r\n\t\t\tp_xyz[7] = 0;\r\n\r\n\t\t\tp_xyz += 8;\r\n\t\t}\r\n\t}\r\n\r\n#ifdef DEBUG_LINES\r\n\tNxPs2::EndLines3D();\r\n#else\r\n\tNxPs2::dma::pLoc = (uint8*)p_loc;\r\n\tNxPs2::dma::EndTag();\r\n\r\n\r\n\r\n\r\n\r\n#endif\t\t// DEBUG_LINES\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2Weather::plat_render_splashes( float skx, float skz )\r\n{\r\n\t// Create a new splash if required.\r\n\tfloat last = m_splash_rate;\r\n\tm_splash_rate += m_splash_per_frame;\r\n\tint new_splashes = (int)m_splash_rate - (int)last;\r\n\r\n\tif ( new_splashes )\r\n\t{\r\n\t\tCFeeler feeler;\r\n\t\tMth::Vector pos;\r\n\r\n\t\tpos[X] = NxPs2::render::CameraToWorld.GetPos()[X];\t// + ( Mth::Rnd( ( WEATHER_CEL_SIZE * RENDER_DIST * 2 ) ) ) - ( WEATHER_CEL_SIZE * RENDER_DIST );\r\n\t\tpos[Y] = FEELER_START;\r\n\t\tpos[Z] = NxPs2::render::CameraToWorld.GetPos()[Z];\t// + ( Mth::Rnd( ( WEATHER_CEL_SIZE * RENDER_DIST * 2 ) ) ) - ( WEATHER_CEL_SIZE * RENDER_DIST ); \r\n\t\tpos[W] = 1.0f;\r\n\r\n\t\tMth::Vector dir;\r\n\t\tdir[X] = skx - NxPs2::render::CameraToWorld.GetPos()[X];\r\n\t\tdir[Y] = 0.0f;\r\n\t\tdir[Z] = skz - NxPs2::render::CameraToWorld.GetPos()[Z];\r\n\t\tdir[W] = 1.0f;\r\n\t\tdir.Normalize();\r\n\r\n\t\t// Add distance.\r\n\t\tfloat r1 = (float)Mth::Rnd( 32768 ) / 32768.0f;\r\n\t\tpos += ( dir * ( (float)WEATHER_CEL_SIZE * RENDER_DIST * r1 ) );\r\n\r\n\t\t// Add lateral.\r\n\t\tMth::Vector lat;\r\n\t\tlat[X] = dir[Z];\r\n\t\tlat[Y] = 0.0f;\r\n\t\tlat[Z] = -dir[X];\r\n\t\tlat[W] = 1.0f;\r\n\r\n\t\tfloat r2 = 1.0f - ( (float)Mth::Rnd( 32768 ) / 32768.0f );\r\n\t\tif ( m_current_splash & 1 )\r\n\t\t{\r\n\t\t\tpos += ( lat * ( (float)WEATHER_CEL_SIZE * RENDER_DIST * r1 * r2 ) );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpos += ( lat * ( (float)WEATHER_CEL_SIZE * RENDER_DIST * r1 * -r2 ) );\r\n\t\t}\r\n\r\n\t\tfeeler.SetStart( pos );\r\n\t\tpos[Y] = -FEELER_START;\r\n\t\tfeeler.SetEnd( pos );\r\n\r\n\t\t// Get the y position.\r\n\t\tfloat y;\r\n\t\tif ( feeler.GetCollision( false, false ) )\t\t// No movables, nearest collision.\r\n\t\t{\r\n\t\t\ty = feeler.GetPoint()[Y];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ty = FEELER_START;\r\n\t\t}\r\n\r\n\t\tm_splash_x[m_current_splash] = pos[X];\r\n\t\tm_splash_y[m_current_splash] = y + m_splash_size;\r\n\t\tm_splash_z[m_current_splash] = pos[Z];\r\n\t\tm_splash_current_life[m_current_splash] = m_splash_life;\r\n\r\n\t\tm_current_splash++;\r\n\t\tm_current_splash %= NUM_SPLASH_ACTIVE;\r\n\t}\r\n\t\r\n\t// Count active splashes.\r\n\tint splashes = 0;\r\n\tfor ( int spl = 0; spl < NUM_SPLASH_ACTIVE; spl++ )\r\n\t{\r\n\t\tif ( m_splash_current_life[spl] != 0 ) splashes++;\r\n\t}\r\n\r\n\tif ( splashes )\r\n\t{\r\n\t\t// add a dma packet\r\n\t\tNxPs2::dma::BeginTag(NxPs2::dma::cnt, 0);\r\n\r\n\t\t// VU context\r\n\t\tNxPs2::vu1::BeginPrim(ABS, VU1_ADDR(L_VF10));\r\n\t\tNxPs2::vu1::StoreVec(*(NxPs2::Vec *)&NxPs2::render::InverseIntViewportScale);\r\n\t\tNxPs2::vu1::StoreVec(*(NxPs2::Vec *)&NxPs2::render::InverseIntViewportOffset);\r\n\t\tNxPs2::vu1::StoreMat(*(NxPs2::Mat *)&NxPs2::render::WorldToIntViewport);\t// VF12-15\r\n\t\tNxPs2::vu1::EndPrim(0);\r\n\t\tNxPs2::vu1::BeginPrim(ABS, VU1_ADDR(L_VF30));\r\n\t\tNxPs2::vif::StoreV4_32F(640.0f, 480.0f, 0.0f, 0.0f);\t\t\t\t\t\t// VF30\r\n\t\tNxPs2::vif::StoreV4_32F(NxPs2::render::IntViewportScale[0]/NxPs2::render::Tx,\t// VF31\r\n\t\t\t\t\t\t\t\tNxPs2::render::IntViewportScale[1]/NxPs2::render::Ty,\r\n\t\t\t\t\t\t\t\t0.0f, 0.0f);\r\n\t\tNxPs2::vu1::EndPrim(0);\r\n\r\n\t\t// GS context\r\n\t\tNxPs2::gs::BeginPrim(ABS, 0, 0);\r\n\t\tNxPs2::gs::Reg1(NxPs2::gs::ALPHA_1,\tm_splash_blend);\r\n\t\tNxPs2::gs::Reg1(NxPs2::gs::TEX0_1,\tmp_rain_texture->m_RegTEX0);\r\n\t\tNxPs2::gs::Reg1(NxPs2::gs::TEX1_1,\tmp_rain_texture->m_RegTEX1);\r\n\t\tNxPs2::gs::Reg1(NxPs2::gs::ST,\t\tPackST(0x3F800000,0x3F800000));\r\n\t\tNxPs2::gs::Reg1(NxPs2::gs::RGBAQ,\tPackRGBAQ(0,0,0,0,0x3F800000));\r\n\t\tNxPs2::gs::EndPrim(0);\r\n\r\n\t\t// Render the splashes.\r\n\t//\tint u = mp_rain_texture->GetWidth() << 4;\r\n\t//\tint v = mp_rain_texture->GetHeight() << 4;\r\n\t//\tuint32 col = *((uint32 *)&m_splash_color); \r\n\r\n\t\tNxPs2::BeginModelPrimImmediate(NxPs2::gs::XYZ2\t\t|\r\n\t\t\t\t\t\t\t\t\t   NxPs2::gs::ST<<4\t\t|\r\n\t\t\t\t\t\t\t\t\t   NxPs2::gs::RGBAQ<<8\t|\r\n\t\t\t\t\t\t\t\t\t   NxPs2::gs::XYZ2<<12,\r\n\t\t\t\t\t\t\t\t\t   4, SPRITE|ABE|TME, 1, VU1_ADDR(SpriteCull));\r\n\r\n\t\t// create an unpack for the colours\r\n\t\tNxPs2::vif::BeginUNPACK(0, V4_8, ABS, UNSIGNED, 3);\r\n\t\tuint32 * p_col = (uint32 *)NxPs2::dma::pLoc;\r\n\t\tNxPs2::dma::pLoc += splashes * 4;\r\n\t\tNxPs2::vif::EndUNPACK();\r\n\r\n\t\t// and one for the positions (& sizes)\r\n\t\tNxPs2::vif::BeginUNPACK(0, V4_32, ABS, SIGNED, 4);\r\n\t\tfloat * p_xyz = (float *)NxPs2::dma::pLoc;\r\n\t\tNxPs2::dma::pLoc += splashes * 16;\r\n\t\tNxPs2::vif::EndUNPACK();\r\n\r\n\t\tNxPs2::EndModelPrimImmediate(1);\r\n\r\n\t\tNxPs2::vif::MSCAL(VU1_ADDR(Parser));\r\n\r\n\t\tfor ( int spl = 0; spl < NUM_SPLASH_ACTIVE; spl++ )\r\n\t\t{\r\n\t\t\tif ( m_splash_current_life[spl] == 0 ) continue;\r\n\r\n\t\t\t// Interpolate color.\r\n\t\t\tImage::RGBA\ticol;\r\n\t\t\ticol.r = (uint8)( ( (int)m_splash_color.r * m_splash_current_life[spl] ) / m_splash_life );\r\n\t\t\ticol.g = (uint8)( ( (int)m_splash_color.g * m_splash_current_life[spl] ) / m_splash_life );\r\n\t\t\ticol.b = (uint8)( ( (int)m_splash_color.b * m_splash_current_life[spl] ) / m_splash_life );\r\n\t\t\ticol.a = (uint8)( ( (int)m_splash_color.a * m_splash_current_life[spl] ) / m_splash_life );\r\n\r\n\t\t\t// Draw splashes...\r\n\t\t\t*p_col++ = *((uint32 *)&icol);\r\n\r\n\t\t\tp_xyz[0] = m_splash_x[spl];\r\n\t\t\tp_xyz[1] = m_splash_y[spl];\r\n\t\t\tp_xyz[2] = m_splash_z[spl];\r\n\t\t\tp_xyz[3] = m_splash_size;\r\n\t\t\tp_xyz += 4;\r\n\r\n\t\t\tm_splash_current_life[spl]--;\r\n\t\t}\r\n\r\n\t\t// restore transform\r\n\t\tNxPs2::vu1::BeginPrim(ABS, VU1_ADDR(L_VF12));\t\t// was L_VF16\r\n\t\tNxPs2::vu1::StoreMat(*(NxPs2::Mat *)&NxPs2::render::AdjustedWorldToViewport);\t\t// VF16-19\r\n\t\tNxPs2::vu1::EndPrim(1);\r\n\t\tNxPs2::vif::MSCAL(VU1_ADDR(Parser));\r\n\r\n\t\t// end the dma tag\r\n\t\tNxPs2::dma::EndTag();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CPs2Weather::plat_render( void )\r\n{\r\n\tif ( !m_system_active ) return;\r\n\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = pSkate->GetSkater(0);\r\n\tif (!pSkater) return;\r\n\t\r\n\tfloat skx = pSkater->m_pos[X];\r\n\tfloat skz = pSkater->m_pos[Z];\r\n\r\n\tif ( m_raining )\r\n\t{\r\n\t\tplat_render_splashes( skx, skz );\r\n\t\tplat_render_rain( skx, skz );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tplat_render_snow( skx, skz );\r\n\t}\r\n\r\n\t// Increment rain drop/snow flake positions.\r\n\tif ( m_active_drops )\r\n\t{\r\n\t\tfor ( int lp = 0; lp < ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ); lp++ )\r\n\t\t{\r\n\t\t\tswitch ( m_drop_time[lp] )\r\n\t\t\t{\r\n\t\t\t\tcase 255:\r\n\t\t\t\t\t// Inactive.\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 254:\r\n\t\t\t\t\t// About to become inactive, so decrement active drops.\r\n\t\t\t\t\tm_active_drops--;\r\n\t\t\t\t\t// Deliberately falls through...\r\n\t\t\t\tdefault:\r\n\t\t\t\t\t// Increment time.\r\n\t\t\t\t\tm_drop_time[lp]++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CPs2Weather::plat_set_rain_blend_mode( uint32 blendmode_checksum, int fix )\r\n{\r\n\tm_rain_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CPs2Weather::plat_set_splash_blend_mode( uint32 blendmode_checksum, int fix )\r\n{\r\n\tm_splash_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CPs2Weather::plat_set_snow_blend_mode( uint32 blendmode_checksum, int fix )\r\n{\r\n\tm_snow_blend = NxPs2::CImmediateMode::sGetTextureBlend( blendmode_checksum, fix );\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NGPS/p_nxweather.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_WEATHER_H__\r\n#define\t__GFX_P_NX_WEATHER_H__\r\n    \r\n#include \"gfx/nxweather.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n//#define WEATHER_GRID_W 65\r\n//#define WEATHER_GRID_H 65\r\n//\r\n//#define WEATHER_CEL_W 32\r\n//#define WEATHER_CEL_H 32\r\n\r\n#define WEATHER_CEL_SIZE 128\r\n#define WEATHER_CEL_SIZE_SHIFT 7\r\n#define HEIGHT_TOLERANCE (sint32)( 30.0f * SUB_INCH_PRECISION )\r\n#define DROP_SIZE 16\r\n#define DROP_SIZE_SHIFT 4\r\n#define DROP_LAYERS 4\r\n\r\n#define NUM_SPLASH_ACTIVE 32\r\n\r\ntypedef struct\r\n{\r\n\tunsigned short start;\r\n\tunsigned short end;\r\n\tunsigned short index;\r\n} sRowEntry;\r\n\r\nclass CPs2Weather : public CWeather\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCPs2Weather();\r\n\tvirtual \t\t\t\t~CPs2Weather();\r\n\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_update_grid( void );\r\n\tvoid\t\t\t\t\tplat_process( float delta_time );\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_set_rain_blend_mode( uint32 blendmode_checksum, int fix );\r\n\tvoid\t\t\t\t\tplat_set_splash_blend_mode( uint32 blendmode_checksum, int fix );\r\n\tvoid\t\t\t\t\tplat_set_snow_blend_mode( uint32 blendmode_checksum, int fix );\r\n\r\n\tvoid\t\t\t\t\tplat_render_splashes( float skx, float skz );\r\n\tvoid\t\t\t\t\tplat_render_rain( float skx, float skz );\r\n\tvoid\t\t\t\t\tplat_render_snow( float skx, float skz );\r\n\r\n\tNxPs2::SSingleTexture*\tmp_rain_texture;\r\n\tNxPs2::SSingleTexture*\tmp_snow_texture;\r\n\r\n\tunsigned char *\t\t\tmp_roof_height_index;\r\n\tsRowEntry *\t\t\t\tmp_roof_row;\r\n\tsint32\t\t\t\t\tm_roof_height[256];\r\n\tint\t\t\t\t\t\tm_width;\r\n\tint\t\t\t\t\t\tm_height;\r\n\r\n\tfloat\t\t\t\t\tm_min_x;\r\n\tfloat\t\t\t\t\tm_min_z;\r\n\r\n\tfloat\t\t\t\t\tm_rain_rate;\r\n\tfloat\t\t\t\t\tm_splash_rate;\r\n\tfloat\t\t\t\t\tm_snow_rate;\r\n\r\n\tMth::Vector\t\t\t\tm_grid_base;\r\n\r\n\tunsigned char\t\t\tm_drop_time[DROP_SIZE*DROP_SIZE*DROP_LAYERS];\r\n\tunsigned char\t\t\tm_x_offset[DROP_SIZE*DROP_SIZE*DROP_LAYERS];\r\n\tunsigned char\t\t\tm_z_offset[DROP_SIZE*DROP_SIZE*DROP_LAYERS];\r\n\r\n\tuint32\t\t\t\t\tm_seq;\r\n\r\n\tuint64\t\t\t\t\tm_rain_blend;\r\n\tuint64\t\t\t\t\tm_splash_blend;\r\n\tuint64\t\t\t\t\tm_snow_blend;\r\n\r\n\tfloat\t\t\t\t\tm_splash_x[NUM_SPLASH_ACTIVE];\r\n\tfloat\t\t\t\t\tm_splash_y[NUM_SPLASH_ACTIVE];\r\n\tfloat\t\t\t\t\tm_splash_z[NUM_SPLASH_ACTIVE];\r\n\tint\t\t\t\t\t\tm_splash_current_life[NUM_SPLASH_ACTIVE]; \r\n\tint\t\t\t\t\t\tm_current_splash;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxAnimCache.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       NxAnimCache.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  5/06/2002\r\n//****************************************************************************\r\n\r\n#include <gfx/nxanimcache.h>\r\n\r\n#include <gel/assman/assman.h>\r\n\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n\r\n#include <gfx/bonedanim.h>\r\n#include <gfx/nx.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stub versions of all platform specific functions are provided here:\r\n// so engine implementors can leave certain functionality until later\r\n// (Mick Perforce: added line) \r\n\t\t\t\t\t\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// These functions are the platform independent part of the interface to \r\n// the platform specific code\r\n// parameter checking can go here....\r\n// although we might just want to have these functions inline, or not have them at all?\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGfx::CBonedAnimFrameData* GetCachedAnim( uint32 animChecksum, bool assertOnFail )\r\n{\r\n\tif ( animChecksum == 0 )\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tAss::CAssMan* ass_man = Ass::CAssMan::Instance();\r\n\treturn (Gfx::CBonedAnimFrameData*)ass_man->GetAsset( animChecksum, assertOnFail );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n"
  },
  {
    "path": "Code/Gfx/NxAnimCache.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       NxAnimCache.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  5/06/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_NXANIMCACHE_H__\r\n#define\t__GFX_NXANIMCACHE_H__\r\n                   \r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\nnamespace Gfx\r\n{\r\n\tclass CBonedAnimFrameData;\r\n};\r\n\r\nnamespace Nx\r\n{\r\n\r\nGfx::CBonedAnimFrameData* GetCachedAnim( uint32 animChecksum, bool assertOnFail = true );\r\n\r\n}\r\n\r\n#endif // __GFX_NXANIMCACHE_H__\r\n"
  },
  {
    "path": "Code/Gfx/NxFont.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxFont.cpp\r\n\r\n#include \"gfx/NxFont.h\"\r\n\r\nnamespace\tNx\r\n{\r\n// These functions are the platform independent part of the interface to \r\n// the platform specific code\r\n// parameter checking can go here....\r\n// although we might just want to have these functions inline, or not have them at all?\r\n\t\t\t\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCFont::CFont()\r\n{\r\n\tm_checksum = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCFont::~CFont()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCFont::Load(const char *filename)\r\n{\r\n\treturn plat_load(filename);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFont::SetSpacings(int charSpacing, int spaceSpacing)\r\n{\r\n\tplat_set_spacings(charSpacing, spaceSpacing);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFont::SetRGBATable(Image::RGBA *pTab)\r\n{\r\n\tDbg_Assert(pTab);\r\n\tplat_set_rgba_table(pTab);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFont::MarkAsButtonFont(bool isButton)\r\n{\r\n\tplat_mark_as_button_font(isButton);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCFont::Unload()\r\n{\r\n\tplat_unload();\r\n\r\n\tm_checksum = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tCFont::GetChecksum() const\r\n{\r\n\treturn m_checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tCFont::GetDefaultHeight() const\r\n{\r\n\treturn plat_get_default_height();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tCFont::GetDefaultBase() const\r\n{\r\n\treturn plat_get_default_base();\r\n}\r\n\r\n#if 0\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCFont::BeginText(uint32 rgba, float Scale)\r\n{\r\n\tplat_begin_text(rgba, Scale);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCFont::DrawString(char *String, float x0, float y0)\r\n{\r\n\tplat_draw_string(String, x0, y0);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCFont::EndText(void)\r\n{\r\n\tplat_end_text();\r\n}\r\n#endif // 0\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCFont::QueryString(char *String, float &width, float &height) const\r\n{\r\n\tplat_query_string(String, width, height);\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stub versions of all platform specific functions are provided here:\r\n// so engine implementors can leave certain functionality until later\r\n\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCFont::plat_load(const char *filename)\r\n{\r\n\tprintf (\"STUB: PlatLoad\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFont::plat_set_spacings(int charSpacing, int spaceSpacing)\r\n{\r\n\tprintf(\"STUB A DUB DUB\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFont::plat_set_rgba_table(Image::RGBA *pTab)\r\n{\r\n\tprintf(\"STUB A DUB DUB\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFont::plat_mark_as_button_font(bool isButton)\r\n{\r\n\tprintf(\"STUB A DUB DUB\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCFont::plat_unload()\r\n{\r\n\tprintf (\"STUB: PlatUnload\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tCFont::plat_get_default_height() const\r\n{\r\n\tprintf (\"STUB: PlatGetDefaultHeight\\n\");\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tCFont::plat_get_default_base() const\r\n{\r\n\tprintf (\"STUB: PlatGetDefaultBase\\n\");\r\n\treturn 0;\r\n}\r\n\r\n#if 0\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCFont::plat_begin_text(uint32 rgba, float Scale)\r\n{\r\n\tDbg_Assert(0);\t// Don't call anymore\r\n\tprintf (\"STUB: PlatBeginText\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCFont::plat_draw_string(char *String, float x0, float y0)\r\n{\r\n\tDbg_Assert(0);\t// Don't call anymore\r\n\tprintf (\"STUB: PlatDrawString\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCFont::plat_end_text(void)\r\n{\r\n\tDbg_Assert(0);\t// Don't call anymore\r\n\tprintf (\"STUB: PlatEndText\\n\");\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCFont::plat_query_string(char *String, float &width, float &height) const\r\n{\r\n\tprintf (\"STUB: PlatQueryString\\n\");\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// CText\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCText::CText(CWindow2D *p_window) : \r\n\tmp_font(NULL),\r\n\tm_xpos(0.0f),\r\n\tm_ypos(0.0f),\r\n\tm_xscale(1.0f),\r\n\tm_yscale(1.0f),\r\n\tm_priority(0.0f),\r\n\tm_rgba(128, 128, 128, 128),\r\n\tm_color_override(false),\r\n\tm_hidden(true),\r\n\tm_use_zbuffer(false),\r\n\tmp_window(p_window),\r\n\tmp_next(NULL)\r\n{\r\n\t#if\t\t\t\t\t\t__STATIC_FONT_STRINGS__\r\n\tm_string[0] = '\\0';\r\n\t#else\r\n\tm_string = NULL;\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCText::~CText() \r\n{\r\n\t#if\t\t\t\t\t\t__STATIC_FONT_STRINGS__\r\n\t#else\r\n\tif (m_string)\r\n\t{\r\n\t\tdelete [] m_string;\r\n\t}\r\n\t#endif\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::SetHidden(bool hide)\r\n{\r\n\tm_hidden = hide;\r\n\r\n\tplat_update_hidden();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::SetFont(CFont *p_font)\r\n{\r\n\tmp_font = p_font;\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::SetString(const char *p_string)\r\n{\r\n\tDbg_MsgAssert(strlen(p_string) < vMAX_TEXT_CHARS, (\"CText: string too long %d\", strlen(p_string)));\r\n\r\n\t#if\t\t\t\t\t\t__STATIC_FONT_STRINGS__\r\n\tstrcpy(m_string, p_string);\r\n\t#else\r\n\tif (!m_string)\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\tm_string = new char[vMAX_TEXT_CHARS];\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\tstrcpy(m_string, p_string);\r\n\t#endif\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::ClearString()\r\n{\r\n\t#if\t\t\t\t\t\t__STATIC_FONT_STRINGS__\r\n\t#else\r\n\tif (m_string)\r\n\t{\r\n\t\tdelete m_string;\r\n\t\tm_string = NULL;\r\n\t}\r\n\t#endif\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::SetPos(float x, float y)\r\n{\r\n\tm_xpos = x;\r\n\tm_ypos = y;\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::SetScale(float scale_x, float scale_y)\r\n{\r\n\tm_xscale = scale_x;\r\n\tm_yscale = scale_y;\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::SetPriority(float pri)\r\n{\r\n\tm_priority = pri;\r\n\tm_use_zbuffer = false;\r\n\r\n\tplat_update_priority();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::SetZValue(ZBufferValue z)\r\n{\r\n\tm_zvalue = z;\r\n\tm_use_zbuffer = true;\r\n\r\n\tplat_update_priority();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::SetRGBA(Image::RGBA rgba, bool colorOverride)\r\n{\r\n\tm_rgba = rgba;\r\n\tm_color_override = colorOverride;\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::SetWindow(CWindow2D *p_window)\r\n{\r\n\tmp_window = p_window;\r\n\r\n\tplat_update_window();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::plat_initialize()\r\n{\r\n\tprintf (\"STUB: PlatInitialize\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::plat_update_hidden()\r\n{\r\n\tprintf (\"STUB: PlatUpdateHidden\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::plat_update_engine()\r\n{\r\n\tprintf (\"STUB: PlatUpdateEngine\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::plat_update_priority()\r\n{\r\n\tprintf (\"STUB: PlatUpdatePriority\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCText::plat_update_window()\r\n{\r\n\tprintf (\"STUB: PlatUpdateWindow\\n\");\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// CTextMan\r\n\r\nCText *\t\t\tCTextMan::sp_dynamic_text_list = NULL;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCTextMan::sAllocTextPool()\r\n{\r\n\ts_plat_alloc_text_pool();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCText *\t\t\tCTextMan::sGetTextInstance()\r\n{\r\n\tCText *p_text = sp_dynamic_text_list;\r\n\r\n\tif (p_text)\r\n\t{\r\n\t\tsp_dynamic_text_list = p_text->mp_next;\r\n\t\t//p_text->AddToDrawList();\r\n\t} else {\r\n\t\tDbg_MsgAssert(0, (\"Out of CText Instances\"));\r\n\t}\r\n\r\n\treturn p_text;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCTextMan::sFreeTextInstance(CText *p_text)\r\n{\r\n\t//p_text->RemoveFromDrawList();\r\n\tp_text->SetHidden(true);\r\n\r\n\t// Clear text, otherwise it hangs around\r\n\t// it would get re-used, but it's fragmenting memory\t\r\n\tp_text->ClearString();\r\n\r\n\tp_text->mp_next = sp_dynamic_text_list;\r\n\tsp_dynamic_text_list = p_text;\r\n}\r\n\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxFont.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxFont.h\r\n\r\n\r\n\r\n#ifndef\t__GFX_NXFONT_H__\r\n#define\t__GFX_NXFONT_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <gfx/NxViewport.h>\r\n#include <gfx/image/imagebasic.h>\r\n\r\n#define\t\t__STATIC_FONT_STRINGS__ 0\t\t\t// set to 1 to have the old statically allocated strings\r\n\r\nnamespace Nx\r\n{\r\n\r\n// Forward declarations\r\nclass CTextMan;\r\nclass CWindow2D;\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n// The CFont class is the platform independent abstract base class\r\n// of the platform specific CFont classes\r\nclass\tCFont\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCFont();\r\n\tvirtual\t\t\t\t\t~CFont();\r\n\r\n\tbool\t\t\t\t\tLoad(const char *filename);\r\n\tvoid\t\t\t\t\tSetSpacings(int charSpacing, int spaceSpacing);\r\n\tvoid\t\t\t\t\tSetRGBATable(Image::RGBA *pTab);\r\n\tvoid\t\t\t\t\tMarkAsButtonFont(bool isButton);\r\n\tvoid\t\t\t\t\tUnload();\r\n\r\n\tuint32\t\t\t\t\tGetChecksum() const;\r\n\tuint32\t\t\t\t\tGetDefaultHeight() const;\r\n\tuint32\t\t\t\t\tGetDefaultBase() const;\r\n\tvoid\t\t\t\t\tQueryString(char *String, float &width, float &height) const;\r\n\r\n\t// Member variables (protected so the p-classes can access them)\r\nprotected:\r\n\tuint32\t\t\t\t\tm_checksum;\r\n\r\n\t// The virtual functions have a stub implementation.\r\nprivate:\r\n\tvirtual\tbool\t\t\tplat_load(const char *filename);\r\n\tvirtual void\t\t\tplat_set_spacings(int charSpacing, int spaceSpacing);\r\n\tvirtual void\t\t\tplat_set_rgba_table(Image::RGBA *pTab);\r\n\tvirtual void \t\t\tplat_mark_as_button_font(bool isButton);\r\n\tvirtual\tvoid\t\t\tplat_unload();\r\n\r\n\tvirtual\tuint32\t\t\tplat_get_default_height() const;\r\n\tvirtual\tuint32\t\t\tplat_get_default_base() const;\r\n\tvirtual void\t\t\tplat_query_string(char *String, float &width, float &height) const;\r\n};\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n// Holds a string of text that needs to be displayed this frame\r\nclass CText\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCText(CWindow2D *p_window = NULL);\r\n\tvirtual\t\t\t\t\t~CText();\r\n\r\n\t// If hidden, it won't be drawn that frame\r\n\tvoid\t\t\t\t\tSetHidden(bool hide);\r\n\tbool\t\t\t\t\tIsHidden() const;\r\n\r\n\t// Font used for the text.\r\n\tCFont *\t\t\t\t\tGetFont() const;\r\n\tvoid\t\t\t\t\tSetFont(CFont *p_font);\r\n\r\n\t// Actual text\r\n\tconst char *\t\t\tGetString() const;\r\n\tvoid\t\t\t\t\tSetString(const char *p_string);\r\n\tvoid\t\t\t\t\tClearString();\r\n\r\n\t// Position on screen.  Assumes screen size of 640x448.\r\n\tfloat\t\t\t\t\tGetXPos() const;\r\n\tfloat\t\t\t\t\tGetYPos() const;\r\n\tvoid\t\t\t\t\tSetPos(float x, float y);\r\n\r\n\t// Scale of text.\r\n\tfloat\t\t\t\t\tGetXScale() const;\r\n\tfloat\t\t\t\t\tGetYScale() const;\r\n\tvoid\t\t\t\t\tSetScale(float scale_x, float scale_y);\r\n\r\n\t// Priority of text.  Higher priority text are\r\n\t// drawn on top of lower priority text.\r\n\tfloat\t\t\t\t\tGetPriority() const;\r\n\tvoid\t\t\t\t\tSetPriority(float pri);\r\n\tNx::ZBufferValue\t\tGetZValue() const;\r\n\tvoid\t\t\t\t\tSetZValue(Nx::ZBufferValue z);\r\n\r\n\t// Color of text.\r\n\tImage::RGBA\t\t\t\tGetRGBA() const;\r\n\tvoid\t\t\t\t\tSetRGBA(Image::RGBA rgba, bool colorOverride);\r\n\r\n\t// Clipping window\r\n\tCWindow2D *\t\t\t\tGetWindow() const;\r\n\tvoid\t\t\t\t\tSetWindow(CWindow2D *p_window);\r\n\r\nprotected:\r\n\t// Constants\r\n\tenum {\r\n\t\tvMAX_TEXT_CHARS = 96\r\n\t};\r\n\r\n\tCFont *\t\t\t\t\tmp_font;\r\n\t#if\t\t\t\t\t\t__STATIC_FONT_STRINGS__\r\n\tchar\t\t\t\t\tm_string[vMAX_TEXT_CHARS];\r\n\t#else\r\n\tchar *\t\t\t\t\tm_string;\r\n\t#endif\r\n\tfloat\t\t\t\t\tm_xpos;\r\n\tfloat\t\t\t\t\tm_ypos;\r\n\tfloat\t\t\t\t\tm_xscale;\r\n\tfloat\t\t\t\t\tm_yscale;\r\n\tfloat\t\t\t\t\tm_priority;\r\n\tZBufferValue\t\t\tm_zvalue;\t\t  // for zbuffer sort\r\n\tImage::RGBA\t\t\t\tm_rgba;\r\n\tbool\t\t\t\t\tm_color_override; // colors encoded in text will be overridden if true\r\n\r\n\tbool\t\t\t\t\tm_hidden;\r\n\tbool\t\t\t\t\tm_use_zbuffer;\r\n\r\n\tCWindow2D *\t\t\t\tmp_window;\r\n\r\n\t// For free list in CTextMan\r\n\tCText *\t\t\t\t\tmp_next;\r\n\r\nprivate:\r\n\t//\r\n\tvirtual void\t\t\tplat_initialize();\r\n\r\n\tvirtual void\t\t\tplat_update_hidden();\t\t// Tell engine of update\r\n\tvirtual void\t\t\tplat_update_engine();\t\t// Update engine primitives\r\n\tvirtual void\t\t\tplat_update_priority();\r\n\tvirtual void\t\t\tplat_update_window();\r\n\r\n\tfriend CTextMan;\r\n\r\n};\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n// Static class for memory management of CTexts\r\nclass CTextMan\r\n{\r\npublic:\r\n\t//\r\n\tstatic void\t\t\t\tsAllocTextPool();\r\n\tstatic CText *\t\t\tsGetTextInstance();\r\n\tstatic void\t\t\t\tsFreeTextInstance(CText *p_text);\r\n\r\nprivate:\r\n\t// Constants\r\n\tenum {\r\n\t\tvMAX_TEXT_INSTANCES = 512\r\n\t};\r\n\r\n\t// Because it is static, it is declared here, but defined in p_NxFont.cpp\r\n\tstatic void\t\t\t\ts_plat_alloc_text_pool();\r\n\tstatic CText *\t\t\ts_plat_get_text_instance();\r\n\tstatic void\t\t\t\ts_plat_free_text_instance(CText *p_text);\r\n\r\n\t// Array of Text requests\r\n\tstatic CText *\t\t\tsp_dynamic_text_list;\r\n};\r\n\r\n/////////////////////////////////////////////////////////\r\n// CText inline function\r\ninline bool\t\t\t\t\tCText::IsHidden() const\r\n{\r\n\treturn m_hidden;\r\n}\r\n\r\ninline CFont *\t\t\t\tCText::GetFont() const\r\n{\r\n\treturn mp_font;\r\n}\r\n\r\ninline float\t\t\t\tCText::GetXPos() const\r\n{\r\n\treturn m_xpos;\r\n}\r\n\r\ninline float\t\t\t\tCText::GetYPos() const\r\n{\r\n\treturn m_ypos;\r\n}\r\n\r\ninline float\t\t\t\tCText::GetXScale() const\r\n{\r\n\treturn m_xscale;\r\n}\r\n\r\ninline float\t\t\t\tCText::GetYScale() const\r\n{\r\n\treturn m_yscale;\r\n}\r\n\r\ninline float\t\t\t\tCText::GetPriority() const\r\n{\r\n\treturn m_priority;\r\n}\r\n\r\ninline ZBufferValue\t\t\tCText::GetZValue() const\r\n{\r\n\treturn m_zvalue;\r\n}\r\n\r\ninline Image::RGBA\t\t\tCText::GetRGBA() const\r\n{\r\n\treturn m_rgba;\r\n}\r\n\r\ninline CWindow2D *\t\t\tCText::GetWindow() const\r\n{\r\n\treturn mp_window;\r\n}\r\n\r\n}\r\n\r\n#endif // \r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxFontMan.cpp",
    "content": "#include <core/defines.h>\r\n#include <core/String/stringutils.h>\r\n#include <gfx/NxFontMan.h>\r\n#include <gel/Scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\nCFontManager::FontEntry \t\t\t\tCFontManager::s_font_tab[vMAX_FONT_ENTRIES];\r\nLst::HashTable<CFontManager::FontEntry>\tCFontManager::s_font_lookup(4);\r\nchar\t\t\t\t\t\t\t\t\tCFontManager::s_meta_button_map[NUM_META_BUTTON_ENTRIES];\r\nbool\t\t\t\t\t\t\t\t\tCFontManager::s_meta_button_map_initialized = false;\r\n\r\n\r\nvoid CFontManager::sLoadFont(const char *pName, int charSpacing, int spaceSpacing, Image::RGBA *pColorTab, bool isButtonFont)\r\n{\r\n\tDbg_Assert(strlen(pName) < FontEntry::vMAX_NAME_SIZE);\r\n\r\n\t// See if this font is already loaded.\r\n\tif ( sGetFont( pName ) )\r\n\t{\r\n\t\tsGetFont( pName )->SetSpacings(charSpacing, spaceSpacing); \r\n\t\tif (pColorTab) sGetFont( pName )->SetRGBATable(pColorTab); \r\n\t\tsGetFont( pName )->MarkAsButtonFont(isButtonFont); \r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (int i = 0; i < vMAX_FONT_ENTRIES; i++)\r\n\t{\r\n\t\tif (!s_font_tab[i].mp_font)\r\n\t\t{\r\n\t\t\ts_font_tab[i].mp_font = s_plat_load_font(pName);\r\n\t\t\ts_font_tab[i].mp_font->SetSpacings(charSpacing, spaceSpacing);\r\n\t\t\tif (pColorTab)\r\n\t\t\t\ts_font_tab[i].mp_font->SetRGBATable(pColorTab);\r\n\t\t\ts_font_tab[i].mp_font->MarkAsButtonFont(isButtonFont);\r\n\t\t\t\t\t\t\r\n\t\t\tstrcpy(s_font_tab[i].mName, pName);\r\n\t\t\ts_font_lookup.PutItem(Script::GenerateCRC(pName), &s_font_tab[i]);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (!s_meta_button_map_initialized)\r\n\t{\r\n\t\t#ifdef __PLAT_XBOX__\r\n\t\tScript::CArray *p_array = Script::GetArray(\"meta_button_map_xbox\", Script::ASSERT);\r\n\t\t#else\r\n\t\t#ifdef __PLAT_NGC__\r\n\t\tScript::CArray *p_array = Script::GetArray(\"meta_button_map_gamecube\");\r\n\t\t#else\r\n\t\tScript::CArray *p_array = Script::GetArray(\"meta_button_map_ps2\", Script::ASSERT);\r\n\t\t#endif\r\n\t\t#endif\r\n\t\t\r\n\t\tif ( p_array )\r\n\t\t{\r\n\t\t\tfor (uint i = 0; i < NUM_META_BUTTON_ENTRIES; i++)\r\n\t\t\t{\r\n\t\t\t\tint index = (i < p_array->GetSize()) ? p_array->GetInteger(i) : 0;\r\n\r\n\t\t\t\tif (index <= 9)\r\n\t\t\t\t\ts_meta_button_map[i] = '0' + index;\r\n\t\t\t\telse\r\n\t\t\t\t\ts_meta_button_map[i] = 'a' + index - 10;\r\n\t\t\t}\r\n\r\n\t\t\ts_meta_button_map_initialized = true;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CFontManager::sUnloadFont(const char *pName)\r\n{\r\n\tfor (int i = 0; i < vMAX_FONT_ENTRIES; i++)\r\n\t{\r\n\t\tif (strcmp(s_font_tab[i].mName, pName) == 0)\r\n\t\t{\r\n\t\t\ts_font_lookup.FlushItem(Script::GenerateCRC(pName));\r\n\t\t\t\r\n\t\t\ts_plat_unload_font(s_font_tab[i].mp_font);\r\n\t\t\ts_font_tab[i].mp_font = NULL;\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n// returns pointer to font if loaded, NULL if not\r\nNx::CFont *CFontManager::sGetFont(uint32 checksum)\r\n{\r\n\tFontEntry *p_entry = s_font_lookup.GetItem(checksum);\r\n\tif (p_entry)\r\n\t\treturn p_entry->mp_font;\r\n\telse\r\n\t\treturn NULL;\r\n}\r\n\r\n// returns pointer to font if loaded, NULL if not\r\nNx::CFont *CFontManager::sGetFont(const char *pName)\r\n{\r\n\treturn sGetFont(Script::GenerateCRC(pName));\r\n}\r\n\r\n// returns pointer to name if loaded, NULL if not\r\nconst char *CFontManager::sTestFontLoaded(uint32 checksum)\r\n{\r\n\tFontEntry *p_entry = s_font_lookup.GetItem(checksum);\r\n\tif (p_entry)\r\n\t\treturn p_entry->mName;\r\n\telse\r\n\t\treturn NULL;\r\n}\r\n\r\n\r\n\r\n\r\nchar CFontManager::sMapMetaCharacterToButton(const char *pMetaChar)\r\n{\r\n\tDbg_MsgAssert(s_meta_button_map_initialized, (\"meta button character table not initialized\"));\r\n\treturn s_meta_button_map[Str::DehexifyDigit(pMetaChar)];\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptLoadFont(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tbool is_buttons_font = pParams->ContainsFlag(\"buttons_font\");\r\n\t\r\n\tconst char *p_name;\r\n\t\r\n\t\r\n\tif (!pParams->GetText(NONAME, &p_name) && !is_buttons_font)\r\n\t\tDbg_MsgAssert(0, (\"no font specified\"));\r\n\t\r\n\t\r\n\tif (is_buttons_font)\r\n\t{\r\n\t\t#ifdef __PLAT_XBOX__\r\n\t\tp_name = \"ButtonsXbox\";\r\n\t\t#else\r\n\t\t\t#ifdef __PLAT_NGC__\r\n\t\t\tp_name = \"ButtonsNgc\";\r\n\t\t\t#else\r\n\t\t\tp_name = \"ButtonsPs2\";\r\n\t\t\t#endif\r\n\t\t#endif\r\n\t}\r\n\r\n\tMem::PushMemProfile((char*)p_name);\r\n\t\r\n\tfloat char_spacing = 0;\r\n\tpParams->GetFloat(\"char_spacing\", &char_spacing);\r\n\t\r\n\tfloat space_spacing = 0;\r\n\tpParams->GetFloat(\"space_spacing\", &space_spacing);\r\n\t\r\n\tScript::CArray *p_script_col_tab;\r\n\r\n   \t// 15Jan02 JCB - Make this local to avoid fragmentation when allocating from the heap.\r\n\tImage::RGBA rgba_tab[16];\r\n\tImage::RGBA* p_rgba_tab = &rgba_tab[0];\r\n\r\n\tif (pParams->GetArray(\"color_tab\", &p_script_col_tab))\r\n\t{\r\n\t\tfor (int i = 0; i < (int) p_script_col_tab->GetSize() && i < 16; i++)\r\n\t\t{\r\n\t\t\tScript::CArray *p_entry = p_script_col_tab->GetArray(i);\r\n\t\t\tuint32 rgba = 0;\r\n\t\t\tint size = p_entry->GetSize();\r\n\t\t\tDbg_MsgAssert(size >= 3 && size <= 4, (\"wrong size %d for color array\", size));\r\n\t\t\tfor (int j = 0; j < size; j++) \r\n\t\t\t{\r\n\t\t\t\trgba |= (p_entry->GetInteger(j) & 255) << (j*8);\r\n\t\t\t}\r\n\t\t\tp_rgba_tab[i] = *((Image::RGBA *) &rgba);\r\n\t\t}\r\n\t}\r\n\t\r\n\tNx::CFontManager::sLoadFont(p_name, (int) char_spacing, (int) space_spacing, p_rgba_tab, is_buttons_font);\r\n\r\n\tMem::PopMemProfile();\t\t\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptUnloadFont(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_name;\r\n\tif (!pParams->GetText(NONAME, &p_name))\r\n\t\tDbg_MsgAssert(0, (\"no font specified\"));\r\n\t\r\n\tNx::CFontManager::sUnloadFont(p_name);\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxFontMan.h",
    "content": "#ifndef __GFX_2D_FONTMAN_H__\r\n#define __GFX_2D_FONTMAN_H__\r\n\r\n#include <core/hashtable.h>\r\n\r\n#include <gfx/NxFont.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CScriptStructure;\r\n\tclass CScript;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\nclass CFontManager\r\n{\r\npublic:\r\n\tstatic void\t\t\t\t\tsLoadFont(const char *pName, int charSpacing = 0, \r\n\t\t\t\t\t\t\t\t\t\t  int spaceSpacing = 0, Image::RGBA *pColorTab = NULL,\r\n\t\t\t\t\t\t\t\t\t\t  bool isButtonFont = false);\r\n\tstatic void\t\t\t\t\tsUnloadFont(const char *pName);\r\n\tstatic Nx::CFont *\t\t\tsGetFont(const char *pName);\r\n\tstatic Nx::CFont *\t\t\tsGetFont(uint32 checksum);\r\n\r\n\tstatic const char *\t\t\tsTestFontLoaded(uint32 checksum);\r\n\t\r\n\tstatic char\t\t\t\t\tsMapMetaCharacterToButton(const char *pMetaChar);\r\n\r\nprivate:\r\n\t// Constants\r\n\tenum {\r\n\t\tvMAX_FONT_ENTRIES \t\t= 16,\r\n\t\tNUM_META_BUTTON_ENTRIES = 32,\r\n\t};\r\n\r\n\r\n\tstruct FontEntry\r\n\t{\r\n\t\tenum {\r\n\t\t\tvMAX_NAME_SIZE = 24\r\n\t\t};\r\n\r\n\t\t\t\t\t\t\t\tFontEntry() : mp_font(NULL) { }\r\n\r\n\t\tchar\t\t\t\t\tmName[vMAX_NAME_SIZE];\r\n\t\tNx::CFont *\t\t\t\tmp_font;\r\n\t};\r\n\t\r\n\tstatic FontEntry \t\t\t\t\ts_font_tab[vMAX_FONT_ENTRIES];\r\n\tstatic Lst::HashTable<FontEntry>\ts_font_lookup;\r\n\r\n\tstatic char\t\t\t\t\ts_meta_button_map[NUM_META_BUTTON_ENTRIES];\r\n\tstatic bool\t\t\t\t\ts_meta_button_map_initialized;\r\n\t\r\n\t// The platform dependent calls\r\n\tstatic Nx::CFont *\t\t\ts_plat_load_font(const char *pName);\r\n\tstatic void\t\t\t\t\ts_plat_unload_font(Nx::CFont *pFont);\r\n};\r\n\r\n\r\n\r\nbool ScriptLoadFont(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptUnloadFont(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\n}\r\n\r\n#endif // FONTMAN\r\n"
  },
  {
    "path": "Code/Gfx/NxGeom.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       NxGeom.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/math.h>\r\n\r\n#include <gfx/nxgeom.h>\r\n#include <gfx/image/imagebasic.h>\r\n\r\n#include <gel/collision/colltridata.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stub versions of all platform specific functions are provided here:\r\n// so engine implementors can leave certain functionality until later\r\n\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom* \t\t\tCGeom::plat_clone(bool instance, CScene* pDestScene)\r\n{\r\n\tprintf (\"STUB: PlatClone\\n\");\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom* \t\t\tCGeom::plat_clone(bool instance, CModel* pDestModel)\r\n{\r\n\tprintf (\"STUB: PlatClone\\n\");\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCGeom::plat_load_geom_data(CMesh* pMesh, CModel* pModel, bool color_per_material)\r\n{\r\n\tprintf (\"STUB: PlatLoadGeomData\\n\");\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCGeom::plat_finalize()\r\n{\r\n\t// do nothing...  this is only needed for the PS2 right now\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\t\t\tCGeom::plat_get_checksum()\r\n{\r\n\tprintf (\"STUB: PlatGetChecksum\\n\");\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCGeom::plat_set_color(Image::RGBA rgba)\r\n{\r\n\tprintf (\"STUB: PlatSetColor\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\t\tCGeom::plat_get_color() const\r\n{\r\n\tprintf (\"STUB: PlatGetColor\\n\");\r\n\treturn Image::RGBA(0, 0, 0, 0);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCGeom::plat_clear_color()\r\n{\r\n\tprintf (\"STUB: PlatClearColor\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCGeom::plat_set_material_color(uint32 mat_checksum, int pass, Image::RGBA rgba)\r\n{\r\n\tprintf (\"STUB: PlatSetMaterialColor\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\t\tCGeom::plat_get_material_color(uint32 mat_checksum, int pass)\r\n{\r\n\tprintf (\"STUB: PlatGetMaterialColor\\n\");\r\n\treturn Image::RGBA(0, 0, 0, 0);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCGeom::plat_set_visibility(uint32 mask)\r\n{\r\n\tprintf (\"STUB: PlatSetVisibility\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\t\t\tCGeom::plat_get_visibility() const\r\n{\r\n\tprintf (\"STUB: PlatGetVisibility\\n\");\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCGeom::plat_set_active(bool active)\r\n{\r\n\tprintf (\"STUB: PlatSetActive\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCGeom::plat_is_active() const\r\n{\r\n\tprintf (\"STUB: PlatIsActive\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::CBBox &\tCGeom::plat_get_bounding_box() const\r\n{\r\n\tstatic Mth::CBBox stub_bbox;\r\n\tprintf (\"STUB: PlatGetBoundingBox\\n\");\r\n\treturn stub_bbox;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::Vector CGeom::plat_get_bounding_sphere() const\r\n{\r\n\tprintf (\"STUB: PlatGetBoundingSphere\\n\");\r\n\treturn Mth::Vector( 0.0f, 0.0f, 0.0f, 10000.0f );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCGeom::plat_set_world_position(const Mth::Vector& pos)\r\n{\r\n\tprintf (\"STUB: PlatSetWorldPosition\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\tCGeom::plat_get_world_position() const\r\n{\r\n\tstatic Mth::Vector stub_vec;\r\n\tprintf (\"STUB: PlatGetWorldPosition\\n\");\r\n\treturn stub_vec;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCGeom::plat_set_orientation(const Mth::Matrix& orient)\r\n{\r\n\tprintf (\"STUB: PlatSetOrientation\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Matrix & CGeom::plat_get_orientation() const\r\n{\r\n\tstatic Mth::Matrix stub_mat;\r\n\tprintf (\"STUB: PlatGetOrientation\\n\");\r\n\treturn stub_mat;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \t\t\tCGeom::plat_rotate_y(Mth::ERot90 rot)\r\n{\r\n\tprintf (\"STUB: PlatRotateY\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCGeom::plat_set_transform(const Mth::Matrix& transform)\r\n{\r\n\tprintf (\"STUB: PlatSetTransform\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Matrix &\tCGeom::plat_get_transform() const\r\n{\r\n\tstatic Mth::Matrix stub_mat;\r\n\tprintf (\"STUB: PlatGetTransform\\n\");\r\n\treturn stub_mat;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCGeom::plat_set_scale(const Mth::Vector& scale)\r\n{\r\n\tprintf (\"STUB: PlatSetScale\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector\t\tCGeom::plat_get_scale() const\r\n{\r\n\tprintf (\"STUB: PlatGetScale\\n\");\r\n\treturn Mth::Vector(0, 0, 0, 0);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCGeom::plat_set_model_lights(CModelLights *p_model_lights)\r\n{\r\n\tprintf (\"STUB: PlatSetModelLights\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCGeom::plat_render(Mth::Matrix* pRootMatrix, Mth::Matrix* ppBoneMatrices, int numBones)\r\n{\r\n\tprintf (\"STUB: PlatRender\\n\");\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCGeom::plat_set_bounding_sphere( const Mth::Vector& boundingSphere )\r\n{\r\n\tprintf (\"STUB: PlatSetBoundingSphere\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCGeom::plat_hide_polys( uint32 mask )\r\n{\r\n\tprintf (\"STUB: PlatHidePolys\\n\");\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCGeom::plat_enable_shadow( bool enabled )\r\n{\r\n//\tprintf (\"STUB: PlatEnableShadow\\n\");\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// - returns number of renderable verts in a C...Geom\r\n// this should be the same number of verts as is returned/expected by the following functions \r\nint \t\tCGeom::plat_get_num_render_verts()\t\t\t\t\t\t\t\t\r\n{\r\n\tprintf (\"STUB: CGeom::plat_get_num_render_verts\\n\");\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// - gets a single array of the verts positions as regular floating point Mth::Vectors\r\n// p_verts points to memory supplied by the caller\r\nvoid \t\tCGeom::plat_get_render_verts(Mth::Vector *p_verts)\t\t\t\r\n{\r\n\tprintf (\"STUB: CGeom::plat_get_render_verts\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint \t\tCGeom::plat_get_num_render_polys()\t\t\t\t\t\t\t\t\r\n{\r\n\tprintf (\"STUB: CGeom::plat_get_num_render_polys\\n\");\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint \t\tCGeom::plat_get_num_render_base_polys()\t\t\t\t\t\t\t\t\r\n{\r\n\tprintf (\"STUB: CGeom::plat_get_num_render_base_polys\\n\");\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// - gets a single array of the verts colors as RGBA\r\n// p_colors points to memory supplied by the caller\r\nvoid \t\tCGeom::plat_get_render_colors(Image::RGBA *p_colors)\t\t// - gets an array of vertex colors\r\n{\r\n\tprintf (\"STUB: CGeom::plat_get_render_colors\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// - sets the verts after modification\r\nvoid \t\tCGeom::plat_set_render_verts(Mth::Vector *p_verts)\t\t\t  \r\n{\r\n\tprintf (\"STUB: CGeom::plat_set_render_verts\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// - sets the colors after modification\r\nvoid \t\tCGeom::plat_set_render_colors(Image::RGBA *p_colors)\t\t\t\t\r\n{\r\n\tprintf (\"STUB: CGeom::plat_set_render_colors\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid\t\tCGeom::plat_set_bone_matrix_data( Mth::Matrix* pBoneMatrices, int numBones )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCGeom::plat_set_uv_wibble_params(float u_vel, float u_amp, float u_freq, float u_phase,\r\n\t\t\t\t\t\t\t\t\t\t\t float v_vel, float v_amp, float v_freq, float v_phase)\r\n{\r\n\tprintf (\"STUB: CGeom::plat_set_uv_wibble_params\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCGeom::plat_use_explicit_uv_wibble(bool yes)\r\n{\r\n\tprintf (\"STUB: CGeom::plat_use_explicit_uv_wibble\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCGeom::plat_set_uv_wibble_offsets(float u_offset, float v_offset)\r\n{\r\n\tprintf (\"STUB: CGeom::plat_set_uv_wibble_offsets\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCGeom::plat_set_uv_wibble_offsets(uint32 mat_checksum, int pass, float u_offset, float v_offset)\r\n{\r\n\tprintf (\"STUB: CGeom::plat_set_uv_wibble_offsets\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCGeom::plat_set_uv_matrix(uint32 mat_checksum, int pass, const Mth::Matrix &mat)\r\n{\r\n\tprintf (\"STUB: CGeom::plat_set_uv_matrix\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCGeom::plat_allocate_uv_matrix_params(uint32 mat_checksum, int pass)\r\n{\r\n\t// only needed by the xbox right now...\r\n\r\n\treturn true;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// These functions are the platform independent part of the interface to \r\n// the platform specific code\r\n// parameter checking can go here....\r\n// although we might just want to have these functions inline, or not have them at all?\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom::CGeom()\r\n{\r\n\tm_cloned = vORIGINAL;\r\n\tmp_coll_tri_data = NULL;\r\n\tmp_orig_render_colors = NULL;\r\n\tm_multipleColorsEnabled = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom::~CGeom()\r\n{\r\n\tif (m_cloned != vORIGINAL)\t\t\t// delete cloned data\r\n\t{\r\n\t\tif (mp_coll_tri_data)\r\n\t\t{\r\n\t\t\t// Right now, cloning of collision isn't handled at the CGeom level\r\n\t\t\t//delete mp_coll_tri_data;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (mp_orig_render_colors)\r\n\t{\r\n\t\tdelete mp_orig_render_colors;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom*  CGeom::Clone(bool instance, CScene* pDestScene)\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\t// Garrett: Want to be able to disable copy just in case it opens up crashes on the Park Editor\r\n\tif (Script::GetInt( \"disable_clone_copy\", false ))\r\n\t{\r\n\t\tinstance = true;\r\n\t}\r\n#endif\r\n\r\n\t// Create new instance and clone stuff below p-line\r\n\tCGeom* p_new_geom = plat_clone(instance, pDestScene);\r\n\r\n\tif (p_new_geom)\r\n\t{\r\n\t\tp_new_geom->m_cloned = (instance) ? vINSTANCE : vCOPY;\r\n\r\n\t\tif (mp_coll_tri_data)\r\n\t\t{\r\n#if 1\r\n\t\t\t// Garrett: Just copying the pointer now, since the CGeom version is just used for reference\r\n\t\t\tp_new_geom->mp_coll_tri_data = mp_coll_tri_data;\r\n#else\r\n\t\t\t// Make NULL for now until we can figure out a better way of cloning collision with CSector\r\n\t\t\tp_new_geom->mp_coll_tri_data = NULL;\r\n\t\t\t//p_new_geom->mp_coll_tri_data = mp_coll_tri_data->Clone(instance);\r\n\t\t\t//Dbg_Assert(p_new_geom->mp_coll_tri_data);\r\n#endif\r\n\t\t}\r\n\t\t// Mick:  bit of a patch - attempt to fix crash from deleting thigns twice\r\n\t\tp_new_geom->mp_orig_render_colors = NULL;\r\n\t}\r\n\r\n\treturn p_new_geom;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom* CGeom::Clone(bool instance, CModel* pDestModel)\r\n{\r\n\t// Create new instance and clone stuff below p-line\r\n\tCGeom* p_new_geom = plat_clone(instance, pDestModel);\r\n\r\n\tif (p_new_geom)\r\n\t{\r\n\t\tp_new_geom->m_cloned = (instance) ? vINSTANCE : vCOPY;\r\n\r\n\t\tDbg_MsgAssert(!mp_coll_tri_data, (\"Cloning of model geometry doesn't support collision now\"));\r\n\r\n\t\t// Mick:  bit of a patch - attempt to fix crash from deleting thigns twice\r\n\t\tp_new_geom->mp_orig_render_colors = NULL;\r\n\t}\r\n\r\n\treturn p_new_geom;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGeom::LoadGeomData( CMesh* pMesh, CModel* pModel, bool color_per_material )\r\n{\r\n\t// All data created here is an instance of something else\r\n\tm_cloned = vINSTANCE;\r\n\tm_multipleColorsEnabled = color_per_material;\r\n\r\n\treturn plat_load_geom_data( pMesh, pModel, color_per_material );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::Finalize()\r\n{\r\n\tplat_finalize();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CGeom::GetChecksum()\r\n{\t\t\r\n\treturn plat_get_checksum();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::SetColor(Image::RGBA rgba)\r\n{\t\t\r\n\tplat_set_color(rgba);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::ClearColor()\r\n{\t\t\r\n\tplat_clear_color();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\tCGeom::GetColor() const\r\n{\t\t\r\n\treturn plat_get_color();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGeom::SetMaterialColor(uint32 mat_checksum, int pass, Image::RGBA rgba)\r\n{\r\n\treturn plat_set_material_color(mat_checksum, pass, rgba);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\tCGeom::GetMaterialColor(uint32 mat_checksum, int pass)\r\n{\r\n\treturn plat_get_material_color(mat_checksum, pass);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::SetVisibility(uint32 mask)\r\n{\r\n\tplat_set_visibility(mask);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CGeom::GetVisibility() const\r\n{\r\n\treturn plat_get_visibility();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::SetActive( bool active )\r\n{\r\n\tplat_set_active( active );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGeom::IsActive() const\r\n{\r\n\treturn plat_is_active();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::CBBox & CGeom::GetBoundingBox() const\r\n{\r\n\treturn plat_get_bounding_box();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector CGeom::GetBoundingSphere() const\r\n{\r\n\treturn plat_get_bounding_sphere();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::SetBoundingSphere( const Mth::Vector& boundingSphere )\r\n{\r\n\tplat_set_bounding_sphere( boundingSphere );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::SetWorldPosition(const Mth::Vector& pos)\r\n{\r\n\tplat_set_world_position(pos);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector & CGeom::GetWorldPosition() const\r\n{\r\n\treturn plat_get_world_position();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::SetOrientation(const Mth::Matrix& orient)\r\n{\r\n\tplat_set_orientation(orient);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Matrix & CGeom::GetOrientation() const\r\n{\r\n\treturn plat_get_orientation();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::RotateY(Mth::ERot90 rot)\r\n{\r\n\tplat_rotate_y(rot);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::SetScale(const Mth::Vector& scale)\r\n{\r\n\tplat_set_scale(scale);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CGeom::GetScale() const\r\n{\r\n\treturn plat_get_scale();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::SetCollTriData(CCollObjTriData *p_coll_data)\r\n{\r\n\tmp_coll_tri_data = p_coll_data;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCollObjTriData* CGeom::GetCollTriData() const\r\n{\r\n\treturn mp_coll_tri_data;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::SetModelLights(CModelLights *p_model_lights)\r\n{\r\n\tplat_set_model_lights(p_model_lights);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGeom::Render( Mth::Matrix* pMatrix, Mth::Matrix* ppBoneMatrices, int numBones )\r\n{\r\n\treturn plat_render( pMatrix, ppBoneMatrices, numBones );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CGeom::SetBoneMatrixData( Mth::Matrix* pBoneMatrices, int numBones )\r\n{\r\n\tplat_set_bone_matrix_data( pBoneMatrices, numBones );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGeom::HidePolys( uint32 mask )\r\n{\r\n\treturn plat_hide_polys( mask );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGeom::EnableShadow( bool enabled )\r\n{\r\n\treturn plat_enable_shadow( enabled );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGeom::GetNumRenderVerts()\t\t\t\t\t\t\t\t// - returns number of renderable verts\r\n{\r\n\t\treturn plat_get_num_render_verts();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::GetRenderVerts(Mth::Vector *p_verts)\t\t\t\t// - gets a single array of the verts\r\n{\r\n\t\treturn plat_get_render_verts(p_verts);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::GetRenderColors(Image::RGBA *p_colors)\t\t\t\t// - gets an array of vertex colors\r\n{\r\n\t\treturn plat_get_render_colors(p_colors);\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Return the total number of renerable polygons \r\nint\tCGeom::GetNumRenderPolys()\r\n{\r\n \treturn\t\tplat_get_num_render_polys();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Return the total number of base polygons (excludes those generated for multipass)\r\nint\tCGeom::GetNumRenderBasePolys()\r\n{\r\n \treturn\t\tplat_get_num_render_base_polys();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Get the original render colors\r\n// if this is the first time this function was called\r\n// then we will allocate memory and store the colors\r\nvoid CGeom::GetOrigRenderColors(Image::RGBA *p_colors)\t\t\t\t// - gets an array of vertex colors\r\n{\r\n\tint verts = GetNumRenderVerts();\r\n\tif (!mp_orig_render_colors)\r\n\t{\r\n\t\t// GJ:  this check was previously used to make sure the malloc caused no bottomup\r\n\t\t// fragmentation during cutscenes.\thowever, it's no longer needed because of\r\n\t\t// the new cutscene heap.  i'm going to leave the code here commented out, just in case\r\n//\t\t#ifdef\t__NOPT_ASSERT__\r\n//\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n//\t\tDbg_MsgAssert( !skate_mod->GetMovieManager()->IsRolling(), ( \"Can't create lights during cutscenes\" ) );\r\n//\t\t#endif\r\n\r\n\t\t// Mick: Game specific optimization here\r\n\t\t// because the \"fake lights\" are only used in non-net games\r\n\t\t// we use the frontend/net heap to store the original colors\r\n\t\t// as it is under utilized in a a single player game\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\t\t\r\n\t\tmp_orig_render_colors = (Image::RGBA*) Mem::Malloc(verts * sizeof(Image::RGBA));\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\tGetRenderColors(mp_orig_render_colors);\r\n\t}\r\n\tmemcpy(p_colors,mp_orig_render_colors,verts * sizeof(Image::RGBA));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::SetRenderVerts(Mth::Vector *p_verts)\t\t\t\t// - sets the verts after modification\r\n{\r\n\t\treturn plat_set_render_verts(p_verts);\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::SetRenderColors(Image::RGBA *p_colors)\t\t\t\t// - sets the colors after modification\r\n{\r\n\r\n\t\treturn plat_set_render_colors(p_colors);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::SetUVWibbleParams(float u_vel, float u_amp, float u_freq, float u_phase,\r\n\t\t\t\t\t\t\t  float v_vel, float v_amp, float v_freq, float v_phase)\r\n{\r\n\tplat_set_uv_wibble_params(u_vel, u_amp, u_freq, u_phase, v_vel, v_amp, v_freq, v_phase);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::UseExplicitUVWibble(bool yes)\r\n{\r\n\tplat_use_explicit_uv_wibble(yes);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGeom::SetUVWibbleOffsets(float u_offset, float v_offset)\r\n{\r\n\tplat_set_uv_wibble_offsets(u_offset, v_offset);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGeom::SetUVWibbleOffsets(uint32 mat_checksum, int pass, float u_offset, float v_offset)\r\n{\r\n\treturn plat_set_uv_wibble_offsets(mat_checksum, pass, u_offset, v_offset);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGeom::SetUVMatrix(uint32 mat_checksum, int pass, const Mth::Matrix &mat)\r\n{\r\n\treturn plat_set_uv_matrix(mat_checksum, pass, mat);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGeom::AllocateUVMatrixParams(uint32 mat_checksum, int pass)\r\n{\r\n\treturn plat_allocate_uv_matrix_params(mat_checksum, pass);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGeom::MultipleColorsEnabled()\r\n{\r\n\treturn m_multipleColorsEnabled;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n"
  },
  {
    "path": "Code/Gfx/NxGeom.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       NxGeom.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_NXGEOM_H__\r\n#define\t__GFX_NXGEOM_H__\r\n                   \r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#ifndef\t__CORE_ROT90_H\r\n    #include <core/math/rot90.h>\r\n#endif\r\n\r\n#ifdef __PLAT_NGC__\r\n#include \"sys/ngc/p_gx.h\"\r\n#endif\t\t// __PLAT_NGC__\r\n\r\nnamespace Mth\r\n{\r\n\tclass Matrix;\r\n\tclass Vector;\r\n\tclass CBBox;\r\n}\r\n\t\t\t\r\nnamespace Image\r\n{\r\n\tstruct RGBA;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\tclass CScene;\r\n\tclass CMesh;\r\n\tclass CModel;\r\n\tclass CModelLights;\r\n\tclass CCollObjTriData;\r\n\r\nclass CGeom : public Spt::Class\r\n{\r\n\r\npublic:\r\n\r\n    // The basic interface to the geom object\r\n    // this is the machine independent part\t\r\n    // machine independent range checking, etc can go here\t\r\n\t\t\t\t\t\tCGeom();\r\n    virtual\t\t\t\t~CGeom();\r\n\r\n\tCGeom *\t\t\t\tClone(bool instance, CScene* pDestScene=NULL);\r\n\tCGeom *\t\t\t\tClone(bool instance, CModel* pDestModel);\t\t// Clones a Geom from one model into a new model\r\n\r\n\tbool\t\t\t\tLoadGeomData(CMesh* pMesh, CModel* pModel, bool color_per_material);\r\n\tvoid\t\t\t\tFinalize();\r\n\r\n\tuint32\t\t\t\tGetChecksum();\r\n\r\n\tvoid\t\t\t\tSetColor(Image::RGBA rgba);\r\n\tImage::RGBA\t\t\tGetColor() const;\r\n\tvoid\t\t\t\tClearColor();\r\n\r\n\t// Can only be used on geometries that were created with color_per_material\r\n\tbool\t\t\t\tSetMaterialColor(uint32 mat_checksum, int pass, Image::RGBA rgba);\r\n\tImage::RGBA\t\t\tGetMaterialColor(uint32 mat_checksum, int pass);\r\n\r\n\tvoid\t\t\t\tSetVisibility(uint32 mask);\r\n\tuint32\t\t\t\tGetVisibility() const;\r\n\r\n\tvoid\t\t\t\tSetActive(bool active);\r\n\tbool\t\t\t\tIsActive() const;\r\n\r\n\tconst Mth::CBBox &\tGetBoundingBox() const;\r\n\r\n\tvoid\t\t\t\tSetBoundingSphere(const Mth::Vector& boundingSphere);\r\n\tconst Mth::Vector\tGetBoundingSphere() const;\r\n\r\n\tvoid\t\t\t\tSetWorldPosition(const Mth::Vector& pos);\r\n\tconst Mth::Vector &\tGetWorldPosition() const;\r\n\r\n\tvoid\t\t\t\tSetOrientation(const Mth::Matrix& orient);\r\n\tconst Mth::Matrix &\tGetOrientation() const;\r\n\r\n\tvoid \t\t\t\tRotateY(Mth::ERot90 rot);\r\n\r\n\tvoid\t\t\t\tSetTransform(const Mth::Matrix& transform);\t\t// Overrides both world pos and orientation\r\n\tconst Mth::Matrix &\tGetTransform() const;\r\n\r\n\tvoid\t\t\t\tSetScale(const Mth::Vector& scale);\r\n\tMth::Vector\t\t\tGetScale() const;\r\n\r\n\tvoid\t\t\t\tSetCollTriData(CCollObjTriData *);\r\n\tCCollObjTriData *\tGetCollTriData() const;\r\n\r\n\tvoid\t\t\t\tSetModelLights(CModelLights *);\r\n\r\n\tbool                Render( Mth::Matrix* pMatrix, Mth::Matrix* ppBoneMatrices, int numBones );\r\n\tvoid\t\t\t\tSetBoneMatrixData( Mth::Matrix* pBoneMatrices, int numBones );\r\n\tbool\t\t\t\tHidePolys(uint32 mask);\r\n\tbool\t\t\t\tEnableShadow(bool enabled);\r\n\r\n\t// used by CModelBuilder to figure out which color modulation function to use\r\n\tbool\t\t\t\tMultipleColorsEnabled();\r\n\r\n// Functions for getting and modifying the raw vertex information in a CGeom\t\r\n\tint \t\t\t\tGetNumRenderPolys();\t\t\t\t\t\t\t\t\t// - returns number of renderable polys\r\n\tint \t\t\t\tGetNumRenderBasePolys();\t\t\t\t\t\t\t// - returns number of first pass polys\r\n\tint \t\t\t\tGetNumRenderVerts();\t\t\t\t\t\t\t\t// - returns number of renderable verts\r\n\tvoid \t\t\t\tGetRenderVerts(Mth::Vector *p_verts);\t\t\t\t// - gets a single array of the verts\r\n\tvoid \t\t\t\tGetOrigRenderColors(Image::RGBA *p_colors);\t\t\t// - gets original render colors, storing them if this si the first time\r\n\tvoid \t\t\t\tGetRenderColors(Image::RGBA *p_colors);\t\t\t\t// - gets an array of vertex colors\r\n\tvoid \t\t\t\tSetRenderVerts(Mth::Vector *p_verts);\t\t\t\t// - sets the verts after modification\r\n\tvoid \t\t\t\tSetRenderColors(Image::RGBA *p_colors);\t\t\t\t// - sets the colors after modification\r\n\r\n\t// Wibble functions\r\n\tvoid\t\t\t\tSetUVWibbleParams(float u_vel, float u_amp, float u_freq, float u_phase,\r\n\t\t\t\t\t\t\t\t\t\t  float v_vel, float v_amp, float v_freq, float v_phase);\r\n\tvoid\t\t\t\tUseExplicitUVWibble(bool yes);\r\n\tvoid\t\t\t\tSetUVWibbleOffsets(float u_offset, float v_offset);\r\n\tbool\t\t\t\tSetUVWibbleOffsets(uint32 mat_checksum, int pass, float u_offset, float v_offset);\r\n\tbool\t\t\t\tSetUVMatrix(uint32 mat_checksum, int pass, const Mth::Matrix &mat);\r\n\tbool\t\t\t\tAllocateUVMatrixParams(uint32 mat_checksum, int pass);\r\n\r\nprotected:\r\n\t// Declares if and what type of clone it is\r\n\tenum CloneType\r\n\t{\r\n\t\tvORIGINAL = 0,\t\t\t// not cloned\r\n\t\tvINSTANCE,\r\n\t\tvCOPY,\r\n\t};\r\n\r\n\tCloneType\t\t\tm_cloned;\t\t\t\t\t\t\t\t\t\t// marks if cloned object\r\n\tCCollObjTriData *\tmp_coll_tri_data;\t\t\t\t\t\t\t\t// Collision geom data\r\n\r\n\tImage::RGBA\t\t*\tmp_orig_render_colors;\r\n\tbool\t\t\t\tm_multipleColorsEnabled;\r\n\r\nprivate:\r\n    // The virtual functions will have a stub implementation\r\n    // in p_nxgeom.cpp\r\n\tvirtual CGeom *\t\tplat_clone(bool instance, CScene* pDestScene=NULL);\r\n\tvirtual CGeom *\t\tplat_clone(bool instance, CModel* pDestModel);\r\n\r\n\tvirtual\tbool\t\tplat_load_geom_data(CMesh* pMesh, CModel* pModel, bool color_per_material);\r\n\r\n\tvirtual void\t\tplat_finalize();\r\n\r\n\tvirtual uint32\t\tplat_get_checksum();\r\n\r\n\tvirtual\tvoid\t\tplat_set_color(Image::RGBA rgba);\r\n\tvirtual\tImage::RGBA\tplat_get_color() const;\r\n\tvirtual\tvoid\t\tplat_clear_color();\r\n\r\n\tvirtual bool\t\tplat_set_material_color(uint32 mat_checksum, int pass, Image::RGBA rgba);\r\n\tvirtual Image::RGBA\tplat_get_material_color(uint32 mat_checksum, int pass);\r\n\r\n\tvirtual\tvoid\t\tplat_set_visibility(uint32 mask);\r\n\tvirtual\tuint32\t\tplat_get_visibility() const;\r\n\r\n\tvirtual\tvoid\t\tplat_set_active(bool active);\r\n\tvirtual\tbool\t\tplat_is_active() const;\r\n\r\n\tvirtual const Mth::CBBox &\tplat_get_bounding_box() const;\r\n\t\r\n\tvirtual void\t\tplat_set_bounding_sphere(const Mth::Vector& boundingSphere);\r\n\tvirtual const Mth::Vector\tplat_get_bounding_sphere() const;\r\n\r\n\tvirtual void\t\tplat_set_world_position(const Mth::Vector& pos);\r\n\tvirtual const Mth::Vector &\tplat_get_world_position() const;\r\n\r\n\tvirtual void\t\tplat_set_orientation(const Mth::Matrix& orient);\r\n\tvirtual const Mth::Matrix &\tplat_get_orientation() const;\r\n\r\n\tvirtual void \t\tplat_rotate_y(Mth::ERot90 rot);\r\n\r\n\tvirtual void\t\tplat_set_transform(const Mth::Matrix& transform);\r\n\tvirtual const Mth::Matrix &\tplat_get_transform() const;\r\n\r\n\tvirtual void\t\tplat_set_scale(const Mth::Vector& scale);\r\n\tvirtual Mth::Vector plat_get_scale() const;\r\n\r\n\tvirtual void\t\tplat_set_model_lights(CModelLights *);\r\n\r\n\tvirtual bool\t\tplat_render(Mth::Matrix* pRootMatrix, Mth::Matrix* ppBoneMatrices, int numBones);\r\n\tvirtual void\t\tplat_set_bone_matrix_data( Mth::Matrix* pBoneMatrices, int numBones );\r\n\tvirtual bool\t\tplat_hide_polys(uint32 mask);\r\n\tvirtual bool\t\tplat_enable_shadow( bool enabled );\r\n\r\n\tvirtual\tint \t\tplat_get_num_render_polys();\r\n\tvirtual\tint \t\tplat_get_num_render_base_polys();\r\n\tvirtual\tint \t\tplat_get_num_render_verts();\t\t\t\t\t\t\t\t// - returns number of renderable verts\r\n\tvirtual\tvoid \t\tplat_get_render_verts(Mth::Vector *p_verts);\t\t\t\t// - gets a single array of the verts\r\n\tvirtual\tvoid \t\tplat_get_render_colors(Image::RGBA *p_colors);\t\t\t\t// - gets an array of vertex colors\r\n\tvirtual void \t\tplat_set_render_verts(Mth::Vector *p_verts);\t\t\t\t// - sets the verts after modification\r\n\tvirtual\tvoid \t\tplat_set_render_colors(Image::RGBA *p_colors);\t\t\t\t// - sets the colors after modification\r\n\r\n\tvirtual void\t\tplat_set_uv_wibble_params(float u_vel, float u_amp, float u_freq, float u_phase,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  float v_vel, float v_amp, float v_freq, float v_phase);\r\n\tvirtual void\t\tplat_use_explicit_uv_wibble(bool yes);\r\n\tvirtual void\t\tplat_set_uv_wibble_offsets(float u_offset, float v_offset);\r\n\tvirtual bool\t\tplat_set_uv_wibble_offsets(uint32 mat_checksum, int pass, float u_offset, float v_offset);\r\n\tvirtual bool\t\tplat_set_uv_matrix(uint32 mat_checksum, int pass, const Mth::Matrix &mat);\r\n\tvirtual bool\t\tplat_allocate_uv_matrix_params(uint32 mat_checksum, int pass);\r\n};\r\n\r\n}\r\n\r\n#endif // __GFX_NXGEOM_H__\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxHierarchy.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       NxHierarchy.h\r\n//* OWNER:          Garrett Jost\r\n//* CREATION DATE:  7/26/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_NXHIERARCHY_H__\r\n#define\t__GFX_NXHIERARCHY_H__\r\n\r\n                           \r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <core/math.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n// Hierarchy information available to game.  It is found at the beginning of a geom.<plat> file\r\n// although it is not used by the geometry directly.\r\nclass CHierarchyObject\r\n{\r\npublic:\r\n\t\t\t\t\t\tCHierarchyObject();\r\n\t\t\t\t\t\t~CHierarchyObject();\r\n\r\n\tvoid\t\t\t\tSetChecksum(uint32 checksum);\r\n\tuint32\t\t\t\tGetChecksum() const;\r\n\tvoid\t\t\t\tSetParentChecksum(uint32 checksum);\r\n\tuint32\t\t\t\tGetParentChecksum() const;\r\n\tvoid\t\t\t\tSetParentIndex(int16 index);\r\n\tint16\t\t\t\tGetParentIndex() const;\r\n\tvoid\t\t\t\tSetBoneIndex(sint8 index);\r\n\tsint8\t\t\t\tGetBoneIndex() const;\r\n\r\n\tvoid\t\t\t\tSetSetupMatrix(const Mth::Matrix& mat);\r\n\tconst Mth::Matrix &\tGetSetupMatrix() const;\r\n\r\n\t//static CHierarchyObject*\tsGetHierarchyArray(uint8 *pPipData, int& size);\r\n\t\r\nprotected:\r\n\tuint32\t\t\t\tm_checksum;\t\t\t// Object checksum\r\n\tuint32\t\t\t\tm_parent_checksum;\t// Checksum of parent, or 0 if root object\r\n\tint16\t\t\t\tm_parent_index;\t\t// Index of parent in the hierarchy array (or -1 if root object)\r\n\tsint8\t\t\t\tm_bone_index;\t\t// The index of the bone matrix used on this object\r\n\tuint8\t\t\t\tm_pad_8;\r\n\tuint32\t\t\t\tm_pad_32;\r\n\tMth::Matrix\t\t\tm_setup_matrix;\t\t// Initial local to parent matrix\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline CHierarchyObject::CHierarchyObject()\r\n{\r\n\tm_checksum = 0;\r\n\tm_parent_checksum = 0;\r\n\r\n\tm_parent_index = -1;\r\n\tm_bone_index = 0;\r\n\r\n\tm_setup_matrix.Ident();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline CHierarchyObject::~CHierarchyObject()\r\n{\r\n}\r\n\r\ninline void\t\t\t\t\tCHierarchyObject::SetChecksum(uint32 checksum)\r\n{\r\n\tm_checksum = checksum;\r\n}\r\n\r\ninline uint32\t\t\t\tCHierarchyObject::GetChecksum() const\r\n{\r\n\treturn m_checksum;\r\n}\r\n\r\ninline void\t\t\t\t\tCHierarchyObject::SetParentChecksum(uint32 checksum)\r\n{\r\n\tm_parent_checksum = checksum;\r\n}\r\n\r\ninline uint32\t\t\t\tCHierarchyObject::GetParentChecksum() const\r\n{\r\n\treturn m_parent_checksum;\r\n}\r\n\r\ninline void\t\t\t\t\tCHierarchyObject::SetParentIndex(int16 index)\r\n{\r\n\tm_parent_index = index;\r\n}\r\n\r\ninline int16\t\t\t\tCHierarchyObject::GetParentIndex() const\r\n{\r\n\treturn m_parent_index;\r\n}\r\n\r\ninline void\t\t\t\t\tCHierarchyObject::SetBoneIndex(sint8 index)\r\n{\r\n\tm_bone_index = index;\r\n}\r\n\r\ninline sint8\t\t\t\tCHierarchyObject::GetBoneIndex() const\r\n{\r\n\treturn m_bone_index;\r\n}\r\n\r\ninline void\t\t\t\t\tCHierarchyObject::SetSetupMatrix(const Mth::Matrix& mat)\r\n{\r\n\tm_setup_matrix = mat;\r\n}\r\n\r\ninline const Mth::Matrix &\tCHierarchyObject::GetSetupMatrix() const\r\n{\r\n\treturn m_setup_matrix;\r\n}\r\n\r\n}\r\n\r\n#endif // __GFX_NXMESH_H__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxImposter.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNx Imposter\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgfx/NxImposter.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/13/03\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tImposter and Imposter Management code\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// start autoduck documentation\r\n// @DOC nximposter\r\n// @module nximposter | None\r\n// @subindex Scripting Database\r\n// @index script | nximposter\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <gfx/NxImposter.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCImposterManager::CImposterManager( void )\r\n{\r\n\tmp_group_table\t\t\t\t\t\t= new Lst::HashTable< CImposterGroup >( 8 );\r\n\tm_max_imposters_to_redraw_per_frame\t= 1;\r\n}\r\n\r\n\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCImposterManager::~CImposterManager( void )\r\n{\r\n\tdelete mp_group_table;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterManager::Cleanup( void )\r\n{\r\n\t// Goes through and removes all imposter groups.\r\n\tmp_group_table->IterateStart();\r\n\tCImposterGroup *p_imposter_group = mp_group_table->IterateNext();\r\n\twhile( p_imposter_group )\r\n\t{\r\n\t\tCImposterGroup *p_next\t= mp_group_table->IterateNext();\r\n\t\tdelete p_imposter_group;\r\n\t\tp_imposter_group\t\t= p_next;\r\n\t}\r\n\tmp_group_table->FlushAllItems();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterManager::AddGeomToImposter( uint32 group_checksum, Nx::CGeom *p_geom )\r\n{\r\n\t// See if this imposter group exists already, create it if not.\r\n\tCImposterGroup *p_group = mp_group_table->GetItem( group_checksum );\r\n\tif( p_group == NULL )\r\n\t{\r\n\t\tp_group = plat_create_imposter_group();\r\n\t\tmp_group_table->PutItem( group_checksum, p_group );\r\n\r\n\t\t// Set the bounding box to be that of the 'founding' CGeom.\r\n\t\tp_group->SetCompositeBoundingBox( p_geom->GetBoundingBox());\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Add the bounding box details of this CGeom.\r\n\t\tp_group->AddBoundingBox( p_geom->GetBoundingBox());\r\n\t}\r\n\r\n\t// Add the specified CGeom to the CImposterGroup's list.\r\n\tp_group->AddGeom( p_geom );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterManager::RemoveGeomFromImposter( uint32 group_checksum, Nx::CGeom *p_geom )\r\n{\r\n\tCImposterGroup *p_group = mp_group_table->GetItem( group_checksum );\r\n\tif( p_group )\r\n\t{\r\n\t\tp_group->RemoveGeom( p_geom );\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterManager::ProcessImposters( void )\r\n{\r\n\tint imposters_drawn = 0;\r\n\r\n\tmp_group_table->IterateStart();\r\n\tCImposterGroup *p_imposter_group = mp_group_table->IterateNext();\r\n\twhile( p_imposter_group )\r\n\t{\r\n\t\t// Once per frame process function, for platform-specific tasks.\r\n\t\tp_imposter_group->Process();\r\n\r\n\t\t// Determine whether this imposter is no longer visible, or is outside the switch distance.\r\n\t\tfloat d = p_imposter_group->CheckDistance();\r\n\r\n\t\tif( d <= p_imposter_group->GetSwitchDistance())\r\n\t\t{\r\n\t\t\t// This imposter is no longer outside the switch distance, or is not visible. Remove the imposter polygon if it exists.\r\n\t\t\tp_imposter_group->RemoveImposterPolygon();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// This imposter is outside the switch distance. Create the imposter polygon if it doesn't exist...\r\n\t\t\tif( p_imposter_group->ImposterPolygonExists() == false )\r\n\t\t\t{\r\n\t\t\t\tif( imposters_drawn < m_max_imposters_to_redraw_per_frame )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_imposter_group->CreateImposterPolygon();\r\n\t\t\t\t\t++imposters_drawn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// ...Otherwise determine whether the imposter polygon requires updating.\r\n\t\t\t\tif( imposters_drawn < m_max_imposters_to_redraw_per_frame )\r\n\t\t\t\t{\r\n\t\t\t\t\tbool drawn = p_imposter_group->UpdateImposterPolygon();\r\n\t\t\t\t\tif( drawn )\r\n\t\t\t\t\t\t++imposters_drawn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tp_imposter_group = mp_group_table->IterateNext();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterManager::DrawImposters( void )\r\n{\r\n\tplat_pre_render_imposters();\r\n\r\n\tmp_group_table->IterateStart();\r\n\tCImposterGroup *p_imposter_group = mp_group_table->IterateNext();\r\n\twhile( p_imposter_group )\r\n\t{\r\n\t\tif( p_imposter_group->ImposterPolygonExists())\r\n\t\t{\r\n\t\t\tp_imposter_group->DrawImposterPolygon();\r\n\t\t}\r\n\t\tp_imposter_group = mp_group_table->IterateNext();\r\n\t}\r\n\r\n\tplat_post_render_imposters();\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCImposterGroup::CImposterGroup( void )\r\n{\r\n\tm_switch_distance\t\t\t= 960.0f;\r\n\tmp_geom_list\t\t\t\t= new Lst::Head < Nx::CGeom >;\r\n\tm_imposter_polygon_exists\t= false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCImposterGroup::~CImposterGroup( void )\r\n{\r\n\t// Remove all nodes from the table.\r\n\tLst::Node<Nx::CGeom> *p_node, *p_next;\r\n\tfor( p_node = mp_geom_list->GetNext(); p_node; p_node = p_next )\r\n\t{\r\n\t\tp_next = p_node->GetNext();\r\n\t\tdelete p_node;\r\n\t}\r\n\r\n\t// Remove the table itself.\r\n\tdelete mp_geom_list;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterGroup::AddGeom( CGeom *p_geom )\r\n{\r\n\t// Create a new node.\r\n\tLst::Node<Nx::CGeom> *p_new_node = new Lst::Node<Nx::CGeom>( p_geom );\r\n\r\n\t// Link in the new node.\r\n\tmp_geom_list->AddToTail( p_new_node );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterGroup::RemoveGeom( CGeom *p_geom )\r\n{\r\n\tLst::Node<Nx::CGeom> *p_node, *p_next;\r\n\tfor( p_node = mp_geom_list->GetNext(); p_node; p_node = p_next )\r\n\t{\r\n\t\tp_next = p_node->GetNext();\r\n\r\n\t\tif( p_node->GetData() == p_geom )\r\n\t\t{\r\n\t\t\tdelete p_node;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterGroup::SetCompositeBoundingBox( const Mth::CBBox & bbox )\r\n{\r\n\tm_composite_bbox\t\t\t= bbox;\r\n\tm_composite_bbox_mid\t\t= m_composite_bbox.GetMin() + ( 0.5f * ( m_composite_bbox.GetMax() - m_composite_bbox.GetMin()));\r\n\tm_composite_bsphere_radius\t= ( m_composite_bbox.GetMax() - m_composite_bbox_mid ).Length();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterGroup::AddBoundingBox( const Mth::CBBox & bbox )\r\n{\r\n\tm_composite_bbox.AddPoint( bbox.GetMin());\r\n\tm_composite_bbox.AddPoint( bbox.GetMax());\r\n\r\n\tm_composite_bbox_mid\t\t= m_composite_bbox.GetMin() + ( 0.5f * ( m_composite_bbox.GetMax() - m_composite_bbox.GetMin()));\r\n\tm_composite_bsphere_radius\t= ( m_composite_bbox.GetMax() - m_composite_bbox_mid ).Length();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterGroup::Process( void )\r\n{\r\n\treturn plat_process();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nfloat CImposterGroup::CheckDistance( void )\r\n{\r\n\treturn plat_check_distance();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterGroup::CreateImposterPolygon( void )\r\n{\r\n\tplat_create_imposter_polygon();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterGroup::RemoveImposterPolygon( void )\r\n{\r\n\tplat_remove_imposter_polygon();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CImposterGroup::UpdateImposterPolygon( void )\r\n{\r\n\t++m_update_count;\r\n\treturn plat_update_imposter_polygon();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterGroup::DrawImposterPolygon( void )\r\n{\r\n\tplat_draw_imposter_polygon();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterGroup::plat_create_imposter_polygon( void )\r\n{\r\n\tprintf( \"STUB: plat_create_imposter_polygon\\n\");\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterGroup::plat_remove_imposter_polygon( void )\r\n{\r\n\tprintf( \"STUB: plat_remove_imposter_polygon\\n\");\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CImposterGroup::plat_update_imposter_polygon( void )\r\n{\r\n\tprintf( \"STUB: plat_update_imposter_polygon\\n\");\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterGroup::plat_draw_imposter_polygon( void )\r\n{\r\n\tprintf( \"STUB: plat_draw_imposter_polygon\\n\");\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nfloat CImposterGroup::plat_check_distance( void )\r\n{\r\n\tprintf( \"STUB: plat_check_distance\\n\");\r\n\treturn 0.0f;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterGroup::plat_process( void )\r\n{\r\n\tprintf( \"STUB: plat_process\\n\");\r\n}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxImposter.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// NxImposter.H - Neversoft Engine, Rendering portion, Platform independent interface\r\n\r\n#ifndef\t__GFX_NX_IMPOSTER_H__\r\n#define\t__GFX_NX_IMPOSTER_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/hashtable.h>\r\n#include <core/math/geometry.h>\r\n#include <gfx/NxGeom.h>\r\n\r\nnamespace Nx\r\n{\r\n/////////////////////////////////////////////////////////////////////////\r\n// Forward declarations\r\n\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CImposterGroup\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\t\tCImposterGroup( void );\r\n\tvirtual\t\t\t\t\t\t~CImposterGroup();\r\n\r\n\tvoid\t\t\t\t\t\tAddGeom( CGeom *p_geom );\r\n\tvoid\t\t\t\t\t\tRemoveGeom( CGeom *p_geom );\r\n\t\t\t\t\t\t\t\t\r\n\tMth::CBBox &\t\t\t\tGetCompositeBoundingBox( void )\t\t\t\t\t{ return m_composite_bbox; }\r\n\tvoid\t\t\t\t\t\tSetCompositeBoundingBox( const Mth::CBBox & bbox );\r\n\tvoid\t\t\t\t\t\tAddBoundingBox( const Mth::CBBox & bbox );\r\n\tfloat\t\t\t\t\t\tGetSwitchDistance( void )\t\t\t\t\t\t{ return m_switch_distance; }\r\n\tfloat\t\t\t\t\t\tCheckDistance( void );\r\n\tvoid\t\t\t\t\t\tProcess( void );\t\t\t// Called once per frame for platform specific processing.\r\n\r\n\tvoid\t\t\t\t\t\tCreateImposterPolygon( void );\r\n\tvoid\t\t\t\t\t\tRemoveImposterPolygon( void );\r\n\tbool\t\t\t\t\t\tUpdateImposterPolygon( void );\r\n\tvoid\t\t\t\t\t\tDrawImposterPolygon( void );\r\n\r\n\tbool\t\t\t\t\t\tImposterPolygonExists( void )\t\t\t\t\t{ return m_imposter_polygon_exists; }\r\n\r\n\tprotected:\r\n\r\n\tfloat\t\t\t\t\t\tm_switch_distance;\t\t\t// Distance at which the imposter switches in/out.\r\n\tMth::CBBox\t\t\t\t\tm_composite_bbox;\t\t\t// Composite bounding box from all geometey added to the group.\r\n\tMth::Vector\t\t\t\t\tm_composite_bbox_mid;\t\t// Mid point of composite bounding box (for speed).\r\n\tfloat\t\t\t\t\t\tm_composite_bsphere_radius;\t// Composite bounding sphere radius (mid point is same as box).\r\n\tLst::Head <Nx::CGeom> *\t\tmp_geom_list;\t\t\t\t// List of geometry for this imposter group.\r\n\tMth::Vector\t\t\t\t\tm_cam_pos;\t\t\t\t\t// The camera position at the time of creation.\r\n\tint\t\t\t\t\t\t\tm_tex_width, m_tex_height;\t// Current imposter texture width and height.\r\n\tint\t\t\t\t\t\t\tm_update_count;\t\t\t\t// Incremented each update, used to allow intermittent checks.\r\n\tbool\t\t\t\t\t\tm_imposter_polygon_exists;\r\n\r\n\tprivate:\r\n\r\n\t// The virtual functions have a stub implementation.\r\n\tvirtual void\t\t\t\tplat_create_imposter_polygon( void );\r\n\tvirtual void\t\t\t\tplat_remove_imposter_polygon( void );\r\n\tvirtual bool\t\t\t\tplat_update_imposter_polygon( void );\r\n\tvirtual void\t\t\t\tplat_draw_imposter_polygon( void );\r\n\tvirtual float\t\t\t\tplat_check_distance( void );\r\n\tvirtual void\t\t\t\tplat_process( void );\r\n};\r\n\t\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CImposterManager\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\t\t\tCImposterManager( void );\r\n\t\t\t\t\t\t\t\t\t\t~CImposterManager();\r\n\r\n\tvoid\t\t\t\t\t\t\t\tCleanup( void );\r\n\tvoid\t\t\t\t\t\t\t\tAddGeomToImposter( uint32 group_checksum, Nx::CGeom *p_geom );\r\n\tvoid\t\t\t\t\t\t\t\tRemoveGeomFromImposter( uint32 group_checksum, Nx::CGeom *p_geom );\r\n\tvoid\t\t\t\t\t\t\t\tProcessImposters( void );\r\n\tvoid\t\t\t\t\t\t\t\tDrawImposters( void );\r\n\r\n\tCImposterGroup*\t\t\t\t\t\tplat_create_imposter_group( void );\r\n\tvoid\t\t\t\t\t\t\t\tplat_pre_render_imposters( void );\r\n\tvoid\t\t\t\t\t\t\t\tplat_post_render_imposters( void );\r\n\r\nprotected:\r\n\r\nprivate:\r\n\r\n\tLst::HashTable< CImposterGroup >\t*mp_group_table;\r\n\tint\t\t\t\t\t\t\t\t\tm_max_imposters_to_redraw_per_frame;\r\n\r\n\r\n};\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////\r\n//\r\n// Inline functions\r\n//\r\n}\r\n#endif"
  },
  {
    "path": "Code/Gfx/NxLight.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxLight.cpp\r\n\r\n\r\n#include <core/defines.h>\r\n\r\n#include \"gfx/NxLight.h\"\r\n\r\nnamespace\tNx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// CModelLights\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// These functions are the platform independent part of the interface.\r\n\t\t\t\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModelLights::CModelLights()\r\n{\r\n\tm_brightness = m_brightness_target = 0.0f;\r\n\r\n\tm_ambient_brightness = 1.0f;\r\n\r\n\tfor (int i = 0; i < CLightManager::MAX_LIGHTS; i++)\r\n\t{\r\n\t\tm_diffuse_brightness[i] = 1.0f;\r\n\t}\r\n\r\n\tmp_pos = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModelLights::~CModelLights()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCModelLights::SetLightAmbientColor(const Image::RGBA &rgba)\r\n{\r\n\t//m_light_ambient_rgba = rgba;\r\n\r\n\tbool success = plat_set_light_ambient_color(rgba);\r\n\r\n\t// need to call this whenever the color/brightness changes\r\n\tplat_update_brightness();\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\t\t\tCModelLights::GetLightAmbientColor()\r\n{\r\n\treturn plat_get_light_ambient_color();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCModelLights::SetLightDirection(int light_index, const Mth::Vector &direction)\r\n{\r\n\tDbg_Assert(light_index < CLightManager::MAX_LIGHTS);\r\n\r\n\t//m_light_direction[light_index] = direction;\r\n\r\n\treturn plat_set_light_direction(light_index, direction);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\tCModelLights::GetLightDirection(int light_index)\r\n{\r\n\tDbg_Assert(light_index < CLightManager::MAX_LIGHTS);\r\n\r\n\treturn plat_get_light_direction(light_index);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCModelLights::SetLightDiffuseColor(int light_index, const Image::RGBA &rgba)\r\n{\r\n\tDbg_Assert(light_index < CLightManager::MAX_LIGHTS);\r\n\r\n\t//m_light_diffuse_rgba[light_index] = rgba;\r\n\r\n\tbool success = plat_set_light_diffuse_color(light_index, rgba);\r\n\r\n\t// need to call this whenever the color/brightness changes\r\n\tplat_update_brightness();\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\t\t\tCModelLights::GetLightDiffuseColor(int light_index)\r\n{\r\n\tDbg_Assert(light_index < CLightManager::MAX_LIGHTS);\r\n\r\n\treturn plat_get_light_diffuse_color(light_index);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* The 'add_scene_light' parameter is used optionally to\t\t  */\r\n/* determine whether a nearby Scene Light should be added to the  */\r\n/* lighting calc (based on the 'pos' position).\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid\t\t\t\tCModelLights::UpdateEngine( Mth::Vector & pos, bool add_scene_light )\r\n{\r\n\tplat_update_engine( pos, add_scene_light );\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCModelLights::EnableAmbientLight(bool enable)\r\n{\r\n\tplat_enable_ambient_light(enable);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCModelLights::EnableDiffuseLight(int light_index, bool enable)\r\n{\r\n\tplat_enable_diffuse_light(light_index, enable);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCModelLights::IsAmbientLightEnabled() const\r\n{\r\n\treturn plat_is_ambient_light_enabled();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCModelLights::IsDiffuseLightEnabled(int light_index) const\r\n{\r\n\treturn plat_is_diffuse_light_enabled(light_index);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCModelLights::SetBrightness(float brightness)\r\n{\r\n\tm_brightness_target = brightness;\r\n\r\n\t// We've found the target brightness, so move actual brightness towards this to avoid sudden unnatural transitions.\r\n\tconst float BRIGHTNESS_SPEED = 0.02f;\r\n\tif( m_brightness < m_brightness_target )\r\n\t{\r\n\t\tm_brightness += BRIGHTNESS_SPEED;\r\n\t\tif( m_brightness > m_brightness_target )\r\n\t\t{\r\n\t\t\tm_brightness = m_brightness_target;\r\n\t\t}\r\n\t}\r\n\telse if( m_brightness > m_brightness_target )\r\n\t{\r\n\t\tm_brightness -= BRIGHTNESS_SPEED;\r\n\t\tif( m_brightness < m_brightness_target )\r\n\t\t{\r\n\t\t\tm_brightness = m_brightness_target;\r\n\t\t}\r\n\t}\r\n\r\n\tm_ambient_brightness = 1.0f + ((2.0f * m_brightness) - 1.0f) * CLightManager::s_world_lights.m_ambient_light_modulation_factor;\r\n\tif (m_ambient_brightness < 0.0f)\r\n\t{\r\n\t\tm_ambient_brightness = 0.0f;\r\n\t}\r\n\r\n\tfor (int i = 0; i < CLightManager::MAX_LIGHTS; i++)\r\n\t{\r\n\t\tm_diffuse_brightness[i] = 1.0f + ((2.0f * m_brightness) - 1.0f) * CLightManager::s_world_lights.m_diffuse_light_modulation_factor[i];\r\n\t\tif (m_diffuse_brightness[i] < 0.0f)\r\n\t\t{\r\n\t\t\tm_diffuse_brightness[i] = 0.0f;\r\n\t\t}\r\n\t}\r\n\r\n\t// need to call this whenever the color/brightness changes\r\n\tplat_update_brightness();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCModelLights::UpdateBrightness()\r\n{\r\n\tm_ambient_brightness = 1.0f + ((2.0f * m_brightness) - 1.0f) * CLightManager::s_world_lights.m_ambient_light_modulation_factor;\r\n\tif (m_ambient_brightness < 0.0f)\r\n\t{\r\n\t\tm_ambient_brightness = 0.0f;\r\n\t}\r\n\r\n\tfor (int i = 0; i < CLightManager::MAX_LIGHTS; i++)\r\n\t{\r\n\t\tm_diffuse_brightness[i] = 1.0f + ((2.0f * m_brightness) - 1.0f) * CLightManager::s_world_lights.m_diffuse_light_modulation_factor[i];\r\n\t\tif (m_diffuse_brightness[i] < 0.0f)\r\n\t\t{\r\n\t\t\tm_diffuse_brightness[i] = 0.0f;\r\n\t\t}\r\n\t}\r\n\r\n\t// GJ: the normal PS2 lighting code assumes that the collision \r\n\t// code will be run once a frame to copy over the m_ambient_base_color \r\n\t// into the m_ambient_mod_color.  unfortunately, the cutscene objects' \r\n\t// ref objects don't go through this code, so I had to add this function\r\n\t// to explicitly copy over the data...  there's probably a cleaner way\r\n\t// to do it, but I didn't want to break the existing code.\r\n\t\r\n\t// need to call this whenever the color/brightness changes\r\n    plat_update_brightness();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCModelLights::SetPositionPointer(Mth::Vector *p_pos)\r\n{\r\n\tmp_pos = p_pos;\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector *\t\tCModelLights::GetPositionPointer()\r\n{\r\n\treturn mp_pos;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// These functions are the stubs of the platform dependent part of the interface.\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCModelLights::plat_set_light_ambient_color(const Image::RGBA &rgba)\r\n{\r\n\tprintf (\"STUB: CModelLights::SetLightAmbientColor\\n\");\r\n\r\n\treturn false;\r\n}\r\n\r\nbool\t\t\t\tCModelLights::plat_set_light_direction(int light_index, const Mth::Vector &direction)\r\n{\r\n\tprintf (\"STUB: CModelLights::SetLightDirection\\n\");\r\n\r\n\treturn false;\r\n}\r\n\r\nbool\t\t\t\tCModelLights::plat_set_light_diffuse_color(int light_index, const Image::RGBA &rgba)\r\n{\r\n\tprintf (\"STUB: CModelLights::SetLightDiffuseColor\\n\");\r\n\r\n\treturn false;\r\n}\r\n\r\nImage::RGBA\t\t\tCModelLights::plat_get_light_ambient_color() const\r\n{\r\n\tprintf (\"STUB: CModelLights::GetLightAmbientColor\\n\");\r\n\r\n\treturn Image::RGBA(0, 0, 0, 0);\r\n}\r\n\r\nconst Mth::Vector &\tCModelLights::plat_get_light_direction(int light_index) const\r\n{\r\n\tprintf (\"STUB: CModelLights::GetLightDirection\\n\");\r\n\r\n\tstatic Mth::Vector stub(0, 0, 0, 0);\r\n\r\n\treturn stub;\r\n}\r\n\r\nImage::RGBA\t\t\tCModelLights::plat_get_light_diffuse_color(int light_index) const\r\n{\r\n\tprintf (\"STUB: CModelLights::GetLightDiffuseColor\\n\");\r\n\r\n\treturn Image::RGBA(0, 0, 0, 0);\r\n}\r\n\r\nvoid\t\t\t\tCModelLights::plat_update_brightness()\r\n{\r\n\tprintf (\"STUB: CModelLights::UpdateBrightness\\n\");\r\n}\r\n\r\nvoid\t\t\t\tCModelLights::plat_enable_ambient_light(bool enable)\r\n{\r\n\tprintf (\"STUB: CModelLights::EnableAmbientLight\\n\");\r\n}\r\n\r\nvoid\t\t\t\tCModelLights::plat_enable_diffuse_light(int light_index, bool enable)\r\n{\r\n\tprintf (\"STUB: CModelLights::EnableDiffuseLight\\n\");\r\n}\r\n\r\nbool\t\t\t\tCModelLights::plat_is_ambient_light_enabled() const\r\n{\r\n\tprintf (\"STUB: CModelLights::IsAmbientLightEnabled\\n\");\r\n\r\n\treturn false;\r\n}\r\n\r\nbool\t\t\t\tCModelLights::plat_is_diffuse_light_enabled(int light_index) const\r\n{\r\n\tprintf (\"STUB: CModelLights::IsDiffuseLightEnabled\\n\");\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid CModelLights::plat_update_engine( Mth::Vector & pos, bool add_scene_light )\r\n{\r\n\tprintf (\"STUB: CModelLights::plat_update_engine\\n\");\r\n}\r\n\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxLight.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// NxLight.H - Neversoft Engine, Rendering portion, Platform independent interface\r\n\r\n#ifndef\t__GFX_NX_LIGHT_H__\r\n#define\t__GFX_NX_LIGHT_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/math.h>\r\n#include <gfx/image/imagebasic.h>\r\n#include <gfx/nxlightman.h>\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// Nx::CModelLights\r\nclass\tCModelLights\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCModelLights();\r\n\tvirtual\t\t\t\t\t\t~CModelLights();\r\n\r\n\t// lights\r\n\tbool\t\t\t\t\t\tSetLightAmbientColor(const Image::RGBA &rgba);\r\n\tImage::RGBA\t\t\t\t\tGetLightAmbientColor();\r\n\r\n\tbool\t\t\t\t\t\tSetLightDirection(int light_index, const Mth::Vector &direction);\r\n\tconst Mth::Vector &\t\t\tGetLightDirection(int light_index);\r\n\r\n\tbool\t\t\t\t\t\tSetLightDiffuseColor(int light_index, const Image::RGBA &rgba);\r\n\tImage::RGBA\t\t\t\t\tGetLightDiffuseColor(int light_index);\r\n\r\n\t// Upload values to engine (where applicable)\r\n\tvoid\t\t\t\t\t\tUpdateEngine( Mth::Vector & pos, bool add_scene_light = false );\r\n\t\r\n\t// Enable lights\r\n\tvoid\t\t\t\t\t\tEnableAmbientLight(bool enable);\r\n\tvoid\t\t\t\t\t\tEnableDiffuseLight(int light_index, bool enable);\r\n\tbool\t\t\t\t\t\tIsAmbientLightEnabled() const;\r\n\tbool\t\t\t\t\t\tIsDiffuseLightEnabled(int light_index) const;\r\n\r\n\t// Sets the modulation brightness\r\n\tbool\t\t\t\t\t\tSetBrightness(float brightness);\r\n\tfloat\t\t\t\t\t\tGetBrightness() const;\r\n\tvoid\t\t\t\t\t\tUpdateBrightness();\r\n\r\n\t// Position pointer\r\n\tbool\t\t\t\t\t\tSetPositionPointer(Mth::Vector *p_pos);\r\n\tMth::Vector *\t\t\t\tGetPositionPointer();\r\n\r\nprotected:\t\r\n\t// Internal flags.\r\n\tenum {\r\n\t\tmUSE_MODEL_AMBIENT\t\t= 0x0001,\t\t\t\t\t// Use ambient light\r\n\t\tmUSE_MODEL_DIFFUSE_0\t= 0x0002,\t\t\t\t\t// Use diffuse light 0\r\n\t\tmUSE_MODEL_DIFFUSE_1\t= 0x0004,\t\t\t\t\t// rest of diffuse must follow 0\r\n\t};\r\n\r\n\t//Image::RGBA\t\t\t\t\tm_light_ambient_rgba;\r\n\t//Mth::Vector\t\t\t\t\tm_light_direction[CLightManager::MAX_LIGHTS];\r\n\t//Image::RGBA\t\t\t\t\tm_light_diffuse_rgba[CLightManager::MAX_LIGHTS];\r\n\r\n\t// Modulation brightness\r\n\tfloat\t\t\t\t\t\tm_brightness;\r\n\tfloat\t\t\t\t\t\tm_brightness_target;\r\n\tfloat\t\t\t\t\t\tm_ambient_brightness;\r\n\tfloat\t\t\t\t\t\tm_diffuse_brightness[CLightManager::MAX_LIGHTS];\r\n\r\n\t// Position pointer (for scene lights)\r\n\tMth::Vector *\t\t\t\tmp_pos;\r\n\r\nprivate:\r\n\t// Platform-specific calls\r\n\tvirtual bool\t\t\t\tplat_set_light_ambient_color(const Image::RGBA &rgba);\r\n\tvirtual bool\t\t\t\tplat_set_light_direction(int light_index, const Mth::Vector &direction);\r\n\tvirtual bool\t\t\t\tplat_set_light_diffuse_color(int light_index, const Image::RGBA &rgba);\r\n\tvirtual Image::RGBA\t\t\tplat_get_light_ambient_color() const;\r\n\tvirtual const Mth::Vector &\tplat_get_light_direction(int light_index) const;\r\n\tvirtual Image::RGBA\t\t\tplat_get_light_diffuse_color(int light_index) const;\r\n\r\n\tvirtual void\t\t\t\tplat_update_engine( Mth::Vector & pos, bool add_scene_light );\r\n\r\n\tvirtual void\t\t\t\tplat_update_brightness();\r\n\r\n\tvirtual void\t\t\t\tplat_enable_ambient_light(bool enable);\r\n\tvirtual void\t\t\t\tplat_enable_diffuse_light(int light_index, bool enable);\r\n\tvirtual bool\t\t\t\tplat_is_ambient_light_enabled() const;\r\n\tvirtual bool\t\t\t\tplat_is_diffuse_light_enabled(int light_index) const;\r\n};\r\n\r\n\r\n}\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxLightMan.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxLightMan.cpp\r\n\r\n// start autoduck documentation\r\n// @DOC NxLightMan\r\n// @module NxLightMan | None\r\n// @subindex Scripting Database\r\n// @index script | NxLightMan\r\n\r\n#include <core/defines.h>\r\n#include <gel/Scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <gfx/debuggfx.h> // for AddDebugLine( )\r\n#include <sk/objects/skater.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <core/math/math.h>\r\n\r\n// This should eventually be removed, only needed for a call to GamePaused, which should not be\r\n// called from here anyway.\r\n#include <sk/modules/frontend/frontend.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/NxGeom.h>\r\n\r\n#include \"gfx/NxLightMan.h\"\r\n\r\nnamespace\tNx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// CLightManager\r\n\r\n// World lights\r\nCLightManager::SLightSet CLightManager::s_world_lights =\r\n{\r\n\t\t\t\t\tImage::RGBA(72, 72, 72, 0x80),\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Ambient RGBA\r\n\t\t\t\t\t{ Mth::Vector(0.5f, 0.8660254f, 0.0f, 0.0f), Mth::Vector(0.0f, 1.0f, 0.0f, 0.0f) },\t\t// Light direction\r\n\t\t\t\t\t{ Image::RGBA(75, 75, 75, 0x80), Image::RGBA(0, 0, 0, 0x80) },\t\t\t\t\t\t\t// Diffuse RGBA\r\n\t\t\t\t\t0.5f,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Ambient modulation\r\n\t\t\t\t\t{ 0.7f, 1.0f }\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Diffuse modulation\r\n};\r\nCLightManager::SLightSet CLightManager::s_world_lights_stack[WORLD_LIGHTS_STACK_SIZE];\r\nint\t\t\t\t\t\t CLightManager::s_world_lights_stack_index = -1;\r\n\r\n// The following are temp variables.  These should be done per model\r\nfloat\t\t\t\tCLightManager::s_brightness = 1.0f;\r\nfloat\t\t\t\tCLightManager::s_brightness_target = 1.0f;\r\n\r\nfloat\t\t\t\tCLightManager::s_min_brightness = 0.0f;\r\nfloat\t\t\t\tCLightManager::s_ambient_brightness = 1.0f;\r\nfloat\t\t\t\tCLightManager::s_diffuse_brightness[MAX_LIGHTS] = { 1.0f, 1.0f };\r\n\r\nCSceneLight\t\t\tCLightManager::s_scene_lights[MAX_SCENE_LIGHTS];\r\nint\t\t\t\t\tCLightManager::s_num_scene_lights\t= 0;\r\n\r\nSVCLight\t\t\tCLightManager::sp_vc_lights[MAX_VC_LIGHTS];\r\nint\t\t\t\t\tCLightManager::s_num_vc_lights = 0;\r\nuint16 *\t\t\tCLightManager::sp_fake_lights_nodes=NULL;\r\nint\t\t\t\t\tCLightManager::s_num_fake_lights_nodes=0;\r\nint\t\t\t\t\tCLightManager::s_next_fake_light_node_to_process=0;\r\nint\t\t\t\t\tCLightManager::s_fake_lights_period=0;\r\nint\t\t\t\t\tCLightManager::s_fake_lights_current_time=0;\r\nScript::CStruct *\tCLightManager::sp_fake_lights_params=NULL;\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// These functions are the platform independent part of the interface.\r\n\t\t\t\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid\t\t\t\tCLightManager::sUpdateEngine( void )\r\n{\r\n\ts_plat_update_engine();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCLightManager::sClearLights()\r\n{\r\n\ts_ambient_brightness = 1.0f;\r\n\r\n\ts_world_lights.m_light_ambient_rgba = Image::RGBA(0, 0, 0, 0x80);\r\n\tfor (int i = 0; i < MAX_LIGHTS; i++)\r\n\t{\r\n\t\ts_world_lights.m_light_direction[i] = Mth::Vector(0.0f, 1.0f, 0.0f, 0.0f);\r\n\t\ts_world_lights.m_light_diffuse_rgba[i] = Image::RGBA(0, 0, 0, 0x80);\r\n\r\n\t\ts_diffuse_brightness[i] = 1.0f;\r\n\t}\r\n\r\n\ts_plat_update_lights();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCLightManager::sSetLightAmbientColor(const Image::RGBA rgba)\r\n{\r\n\ts_world_lights.m_light_ambient_rgba = rgba;\r\n\r\n\treturn s_plat_set_light_ambient_color();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\t\t\tCLightManager::sGetLightAmbientColor()\r\n{\r\n\t//return s_light_ambient_rgba;\r\n\treturn s_plat_get_light_ambient_color();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCLightManager::sSetLightDirection(int light_index, const Mth::Vector &direction)\r\n{\r\n\tDbg_Assert(light_index < MAX_LIGHTS);\r\n\r\n\ts_world_lights.m_light_direction[light_index] = direction;\r\n\r\n\treturn s_plat_set_light_direction(light_index);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\tCLightManager::sGetLightDirection(int light_index)\r\n{\r\n\tDbg_Assert(light_index < MAX_LIGHTS);\r\n\r\n\t//return s_light_direction[light_index];\r\n\treturn s_plat_get_light_direction(light_index);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCLightManager::sSetLightDiffuseColor(int light_index, const Image::RGBA rgba)\r\n{\r\n\ts_world_lights.m_light_diffuse_rgba[light_index] = rgba;\r\n\r\n\treturn s_plat_set_light_diffuse_color(light_index);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\t\t\tCLightManager::sGetLightDiffuseColor(int light_index)\r\n{\r\n\tDbg_Assert(light_index < MAX_LIGHTS);\r\n\r\n\t//return s_light_diffuse_rgba[light_index];\r\n\treturn s_plat_get_light_diffuse_color(light_index);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCLightManager::sSetAmbientLightModulationFactor(float factor)\r\n{\r\n\ts_world_lights.m_ambient_light_modulation_factor = factor;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCLightManager::sSetDiffuseLightModulationFactor(int light_index, float factor)\r\n{\r\n\tDbg_Assert(light_index < MAX_LIGHTS);\r\n\r\n\ts_world_lights.m_diffuse_light_modulation_factor[light_index] = factor;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\t\t\tCLightManager::sGetAmbientLightModulationFactor()\r\n{\r\n\treturn s_world_lights.m_ambient_light_modulation_factor;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\t\t\tCLightManager::sGetDiffuseLightModulationFactor(int light_index)\r\n{\r\n\tDbg_Assert(light_index < MAX_LIGHTS);\r\n\r\n\treturn s_world_lights.m_diffuse_light_modulation_factor[light_index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCLightManager::sPushWorldLights()\r\n{\r\n\tif (++s_world_lights_stack_index < WORLD_LIGHTS_STACK_SIZE)\r\n\t{\r\n\t\t// Put on top of stack\r\n\t\ts_world_lights_stack[s_world_lights_stack_index] = s_world_lights;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t--s_world_lights_stack_index;\r\n\t\tDbg_MsgAssert(0, (\"World light stack full\"));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCLightManager::sPopWorldLights()\r\n{\r\n\tif (s_world_lights_stack_index >= 0)\r\n\t{\r\n\t\t// Get from top of stack and update the engine\r\n\t\ts_world_lights = s_world_lights_stack[s_world_lights_stack_index--];\r\n\t\ts_plat_update_lights();\r\n\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"World light stack empty\"));\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModelLights *\t\tCLightManager::sCreateModelLights()\r\n{\r\n\treturn s_plat_create_model_lights();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCLightManager::sFreeModelLights(CModelLights *p_model_lights)\r\n{\r\n\treturn s_plat_free_model_lights(p_model_lights);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*   This will eventually be done through CModel                  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCLightManager::sSetBrightness(float brightness)\r\n{\r\n#if 0\r\n\t// Don't do anything now\r\n\treturn true;\r\n#endif\r\n\r\n\ts_brightness_target = brightness;\r\n\r\n\t// We've found the target brightness, so move actual brightness towards this to avoid sudden unnatural transitions.\r\n\tconst float BRIGHTNESS_SPEED = 0.02f;\r\n\tif( s_brightness < s_brightness_target )\r\n\t{\r\n\t\ts_brightness += BRIGHTNESS_SPEED;\r\n\t\tif( s_brightness > s_brightness_target )\r\n\t\t{\r\n\t\t\ts_brightness = s_brightness_target;\r\n\t\t}\r\n\t}\r\n\telse if( s_brightness > s_brightness_target )\r\n\t{\r\n\t\ts_brightness -= BRIGHTNESS_SPEED;\r\n\t\tif( s_brightness < s_brightness_target )\r\n\t\t{\r\n\t\t\ts_brightness = s_brightness_target;\r\n\t\t}\r\n\t}\r\n\r\n\ts_ambient_brightness = 1.0f + ((2.0f * s_brightness) - 1.0f) * s_world_lights.m_ambient_light_modulation_factor;\r\n\tif (s_ambient_brightness < s_min_brightness)\r\n\t{\r\n\t\ts_ambient_brightness = s_min_brightness;\r\n\t}\r\n\r\n\tfor (int i = 0; i < MAX_LIGHTS; i++)\r\n\t{\r\n\t\ts_diffuse_brightness[i] = 1.0f + ((2.0f * s_brightness) - 1.0f) * s_world_lights.m_diffuse_light_modulation_factor[i];\r\n\t\tif (s_diffuse_brightness[i] < s_min_brightness)\r\n\t\t{\r\n\t\t\ts_diffuse_brightness[i] = s_min_brightness;\r\n\t\t}\r\n\t}\r\n\r\n\ts_plat_update_colors();\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCSceneLight * CLightManager::sAddSceneLight( void )\r\n{\r\n\tif( s_num_scene_lights < MAX_SCENE_LIGHTS )\r\n\t{\r\n\t\t++s_num_scene_lights;\r\n\t\treturn &s_scene_lights[s_num_scene_lights - 1];\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLightManager::sClearSceneLights( void )\r\n{\r\n\ts_num_scene_lights = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLightManager::sClearVCLights()\r\n{\r\n\r\n// Need to flush the entries from each sector list before we \"ignore\" the light\r\n// otherwise the hash items from one level hang around for another level, confusing us.\r\n\t\r\n\tfor( int i = 0; i < s_num_vc_lights; ++i )\r\n\t{\r\n\t\tsp_vc_lights[i].ResetSectorList();\r\n\t}\r\n\t\r\n\ts_num_vc_lights=0;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CLightManager::sAddVCLight(uint32 name, Mth::Vector &pos, float intensity,\r\n\t\t\t\t\t\t\t\tImage::RGBA col, float outer_radius)\r\n{\r\n\tDbg_MsgAssert(s_num_vc_lights < MAX_VC_LIGHTS, (\"Too many level lights that affect geometry (%d max)\",MAX_VC_LIGHTS));\r\n\tif (s_num_vc_lights < MAX_VC_LIGHTS)\r\n\t{\r\n\t\tSVCLight *p_new_light = &sp_vc_lights[s_num_vc_lights++];\r\n\t\r\n\t\tp_new_light->SetNameChecksum( name );\r\n\t\tp_new_light->SetPosition( pos );\r\n\t\r\n\t\tp_new_light->SetIntensity( intensity * 0.01f );\r\n\t\tp_new_light->SetColor( col );\r\n\t\r\n\t\t// Setting the radius will implicitly calculate the sector list for this light.\r\n\t\tp_new_light->SetRadius( outer_radius );\r\n\t\r\n\t\t// Calculate which sectors will be affected.\r\n\t\tp_new_light->CalculateSectorList();\r\n\t\r\n\t\tif( intensity > 0.0f )\r\n\t\t{\r\n\t\t\ts_apply_lighting( Nx::CEngine::sGetMainScene(), name );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLightManager::sClearCurrentFakeLightsCommand()\r\n{\r\n\tif (sp_fake_lights_nodes)\r\n\t{\r\n\t\tMem::Free(sp_fake_lights_nodes);\r\n\t\tsp_fake_lights_nodes=NULL;\r\n\t}\t\r\n\ts_num_fake_lights_nodes=0;\r\n\ts_next_fake_light_node_to_process=0;\r\n\t\r\n\ts_fake_lights_period=0;\r\n\ts_fake_lights_current_time=0;\r\n\t\r\n\tif (sp_fake_lights_params)\r\n\t{\r\n\t\tdelete sp_fake_lights_params;\r\n\t\tsp_fake_lights_params=NULL;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Gets called from ScriptFakeLights in cfuncs.cpp\r\nvoid CLightManager::sFakeLights(const uint16 *p_nodes, int numNodes, int period, Script::CStruct *pParams)\r\n{\r\n\tsClearCurrentFakeLightsCommand();\r\n\r\n\tsp_fake_lights_params=new Script::CStruct;\r\n\tsp_fake_lights_params->AppendStructure(pParams);\r\n\t\r\n\tif (numNodes)\r\n\t{\r\n\t\tsp_fake_lights_nodes=(uint16*)Mem::Malloc(numNodes*sizeof(uint16));\r\n\t\tfor (int i=0; i<numNodes; ++i)\r\n\t\t{\r\n\t\t\tsp_fake_lights_nodes[i]=p_nodes[i];\r\n\t\t}\t\r\n\t}\t\r\n\ts_num_fake_lights_nodes=numNodes;\r\n\t\r\n\ts_fake_lights_period=period;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// This gets called every frame from CEngine::sRenderWorld()\r\n// It calls sFakeLight for each of the nodes in the array sp_fake_lights_nodes, but\r\n// staggers the calls across frames so that they don't cause a CPU time glitch.\r\n// Once sFakeLight ahs been called for all of them it calls sClearCurrentFakeLightsCommand()\r\nvoid CLightManager::sUpdateVCLights()\r\n{\r\n\tif (!sp_fake_lights_nodes)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// TODO: At some point all the calls to GamePaused need to be removed from\r\n\t// the logic functions that are currently called from CEngine::sRenderWorld()\r\n\tif (Mdl::FrontEnd::Instance()->GamePaused())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// If finished, clean up & stop.\t\r\n\tif (s_fake_lights_current_time > s_fake_lights_period)\r\n\t{\r\n\t\tsClearCurrentFakeLightsCommand();\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\t// Calculate how many nodes ought to have been processed by now, based on the ratio of s_fake_lights_current_time\r\n\t// to s_fake_lights_period\r\n\tint required_num_nodes_processed;\r\n\tif (s_fake_lights_period)\r\n\t{\r\n\t\trequired_num_nodes_processed = (s_num_fake_lights_nodes * s_fake_lights_current_time) / s_fake_lights_period;\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\trequired_num_nodes_processed = s_num_fake_lights_nodes;\r\n\t}\r\n\t\r\n\t// Call sFakeLight for each node starting from where it got to last time, until the required number have\r\n\t// been processed.\r\n\tfor (; s_next_fake_light_node_to_process<required_num_nodes_processed; ++s_next_fake_light_node_to_process)\r\n\t{\r\n\t\tScript::CStruct *p_node=SkateScript::GetNode(sp_fake_lights_nodes[s_next_fake_light_node_to_process]);\r\n\t\tuint32 id=0;\r\n\t\tp_node->GetChecksum(CRCD(0xa1dc81f9,\"Name\"),&id);\r\n\t\tsFakeLight(id,sp_fake_lights_params);\r\n\t}\r\n\t\r\n\t++s_fake_lights_current_time;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCSceneLight *CLightManager::sGetSceneLight( uint32 checksum )\r\n{\r\n\tfor( int l = 0; l < s_num_scene_lights; ++l )\r\n\t{\r\n\t\tif( s_scene_lights[l].GetNameChecksum() == checksum )\r\n\t\t{\r\n\t\t\treturn &s_scene_lights[l];\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCSceneLight * CLightManager::sGetOptimumSceneLight( Mth::Vector & pos )\r\n{\r\n\tif( s_num_scene_lights > 0 )\r\n\t{\r\n\t\tfloat\tbest_ratio\t\t= 1.0f;\r\n\t\tint\t\tbest_index\t\t= -1;\r\n\r\n\t\tfor( int l = 0; l < s_num_scene_lights; ++l )\r\n\t\t{\r\n\t\t\t// Only interested in lights that are active.\r\n\t\t\tif( s_scene_lights[l].GetLightIntensity() > 0.0f )\r\n\t\t\t{\r\n\t\t\t\tfloat dist = Mth::Distance( pos, s_scene_lights[l].GetLightPosition());\r\n\t\t\t\tif( dist < s_scene_lights[l].GetLightRadius())\r\n\t\t\t\t{\r\n\t\t\t\t\t// Potentially a usable light.\r\n\t\t\t\t\tfloat ratio = dist * s_scene_lights[l].GetLightReciprocalRadius();\r\n\t\t\t\t\tif( ratio < best_ratio )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// I wonder whether we should also consider intensity here? A further light, with a higher\r\n\t\t\t\t\t\t// intensity may have more effect than a nearer light with smaller intensity.\r\n\t\t\t\t\t\tbest_ratio = ratio;\r\n\t\t\t\t\t\tbest_index = l;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( best_index >= 0 )\r\n\t\t{\r\n\t\t\treturn &s_scene_lights[best_index];\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// The script functions\r\n\r\n// @script | SetLightAmbientColor | Sets the global light ambient color\r\n// @parm int | r | Red\r\n// @parm int | g | Green\r\n// @parm int | b | Blue\r\nbool ScriptSetLightAmbientColor(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tint r, g, b;\r\n\tif (!pParams->GetInteger(\"r\", &r))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'r' color\"));\r\n\t}\r\n\tif (!pParams->GetInteger(\"g\", &g))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'g' color\"));\r\n\t}\r\n\tif (!pParams->GetInteger(\"b\", &b))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'b' color\"));\r\n\t}\r\n\t\r\n\tImage::RGBA rgb(r, g, b, 0x80);\r\n\r\n\treturn CLightManager::sSetLightAmbientColor(rgb);\r\n}\r\n\r\n\r\n// @script | SetLightDirection | Sets the unit direction vector of a global light\r\n// @parm int | index | Light number\r\n// @parm vector | direction | Unit direction vector (overrides heading and pitch)\r\n// @parm float | heading | Heading angle (in degrees)\r\n// @parm float | pitch | Pitch angle (in degrees)\r\nbool ScriptSetLightDirection(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tint index;\r\n\tif (!pParams->GetInteger(CRCD(0x7f8c98fe,\"index\"), &index))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'index' of light\"));\r\n\t}\r\n\r\n\tfloat heading, pitch;\r\n\tMth::Vector direction(0, 0, 1, 0);\r\n\tif (pParams->GetVector(CRCD(0xc1b52e4c,\"direction\"), &direction))\r\n\t{\r\n\t\tdirection[W] = 0.0f;\t\t// This is the only way to force this to be a vector (as opposed to a point)\r\n\t\t//Dbg_Message(\"************ direction (%f, %f, %f)\", direction[X], direction[Y], direction[Z]);\r\n\t} else if (pParams->GetFloat(CRCD(0xfd4bc03e,\"heading\"), &heading) && pParams->GetFloat(CRCD(0xd8604126,\"pitch\"), &pitch)) {\r\n\t\tdirection.RotateX(Mth::DegToRad(pitch));\r\n\t\tdirection.RotateY(Mth::DegToRad(heading));\r\n\t\t//Dbg_Message(\"************ heading and pitch direction (%f, %f, %f)\", direction[X], direction[Y], direction[Z]);\r\n\t} else {\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'direction' or 'heading' and 'pitch' of light\"));\r\n\t}\r\n\r\n\treturn CLightManager::sSetLightDirection(index, direction);\r\n}\r\n\r\n\r\n// @script | SetLightDiffuseColor | Sets the diffuse color of a global light\r\n// @parm int | index | Light number\r\n// @parm int | r | Red\r\n// @parm int | g | Green\r\n// @parm int | b | Blue\r\nbool ScriptSetLightDiffuseColor(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tint index;\r\n\tif (!pParams->GetInteger(CRCD(0x7f8c98fe,\"index\"), &index))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'index' of light\"));\r\n\t}\r\n\r\n\tint r, g, b;\r\n\tif (!pParams->GetInteger(CRCD(0x93f60062,\"r\"), &r))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'r' color\"));\r\n\t}\r\n\tif (!pParams->GetInteger(CRCD(0xfe2be489,\"g\"), &g))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'g' color\"));\r\n\t}\r\n\tif (!pParams->GetInteger(CRCD(0x8e411006,\"b\"), &b))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'b' color\"));\r\n\t}\r\n\t\r\n\tImage::RGBA rgb(r, g, b, 0x80);\r\n\r\n\treturn CLightManager::sSetLightDiffuseColor(index, rgb);\r\n}\r\n\r\n\r\n// @script | GetLightCurrentColor | Gets the rgb values for ambient and directional lights\r\nbool ScriptGetLightCurrentColor(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tint r=0, g=0, b=0;\r\n    Image::RGBA rgb(r, g, b, 0x80);\r\n    \r\n    rgb = CLightManager::sGetLightAmbientColor();\r\n\r\n    pScript->GetParams()->AddInteger(CRCD(0xed664897,\"ambient_red\"), rgb.r);\r\n    pScript->GetParams()->AddInteger(CRCD(0x908bf647,\"ambient_green\"), rgb.g);\r\n    pScript->GetParams()->AddInteger(CRCD(0x5f4fba78,\"ambient_blue\"), rgb.b);\r\n\r\n    rgb = CLightManager::sGetLightDiffuseColor(0);\r\n\r\n    pScript->GetParams()->AddInteger(CRCD(0xe213aeb7,\"red_0\"), rgb.r);\r\n    pScript->GetParams()->AddInteger(CRCD(0x6ef19631,\"green_0\"), rgb.g);\r\n    pScript->GetParams()->AddInteger(CRCD(0x5ec44213,\"blue_0\"), rgb.b);\r\n\r\n    rgb = CLightManager::sGetLightDiffuseColor(1);\r\n\r\n    pScript->GetParams()->AddInteger(CRCD(0x95149e21,\"red_1\"), rgb.r);\r\n    pScript->GetParams()->AddInteger(CRCD(0x19f6a6a7,\"green_1\"), rgb.g);\r\n    pScript->GetParams()->AddInteger(CRCD(0x29c37285,\"blue_1\"), rgb.b);\r\n    \r\n    /*float heading=0, pitch=0;\r\n    Mth::Vector direction(0, 0, 1, 0);\r\n\r\n    direction = CLightManager::sGetLightDirection(0);\r\n\r\n    //printf(\"x=%i y=%i z=%i\", direction[0], direction[1], direction[2]);\r\n\r\n    //Do the opposite of these two lines\r\n    //direction.RotateX(Mth::DegToRad(pitch));\r\n    //direction.RotateY(Mth::DegToRad(heading));\r\n        \r\n    pScript->GetParams()->AddInteger(\"pitch_0\", pitch);\r\n    pScript->GetParams()->AddInteger(\"heading_0\", heading);\r\n    \r\n    */\r\n\r\n    return true;\r\n}\r\n\r\n// @script | PushWorldLights | Pushes current world lights onto stack, so they can be restored later.\r\nbool ScriptPushWorldLights(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCLightManager::sPushWorldLights();\r\n\treturn true;\r\n}\r\n\r\n// @script | PopWorldLights | Restores last pushed world lights to the current world lights.\r\nbool ScriptPopWorldLights(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\treturn CLightManager::sPopWorldLights();\r\n}\r\n\r\n// @script | DrawDirectionalLightLines | Draws two lines to represent the directional lights\r\nbool ScriptDrawDirectionalLightLines(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tfloat heading;\r\n\tpParams->GetFloat( CRCD(0xfd4bc03e,\"heading\"), &heading, Script::ASSERT );\r\n\r\n    float pitch;\r\n\tpParams->GetFloat( CRCD(0xd8604126,\"pitch\"), &pitch, Script::ASSERT );\r\n\r\n    pitch = -pitch * Mth::PI / 180.0f;\r\n    heading = ((-heading+90) * Mth::PI / 180.0f);\r\n    \r\n    int r, g, b;\r\n    pParams->GetInteger( CRCD(0x93f60062,\"r\"), &r, Script::ASSERT );\r\n    pParams->GetInteger( CRCD(0xfe2be489,\"g\"), &g, Script::ASSERT );\r\n    pParams->GetInteger( CRCD(0x8e411006,\"b\"), &b, Script::ASSERT );\r\n    Image::RGBA rgb(r, g, b, 0x80);\r\n    //rgb = CLightManager::sGetLightDiffuseColor(0);\r\n\r\n    Obj::CSkater *pSkater = Mdl::Skate::Instance()->GetLocalSkater();\r\n\t\r\n\tMth::Vector pos = pSkater->GetPos();\r\n\tfloat x = pos.GetX();\r\n\tfloat y = ( pos.GetY() + 75 );\r\n\tfloat z = pos.GetZ();\r\n\r\n    float hypyh = 50;\r\n    \r\n    float y0 = ( (sin(pitch) * hypyh) + y );\r\n    float hypxz = (cos(pitch) * hypyh);\r\n    float x0 = ( (cos(heading) * hypxz) + x );\r\n    float z0 = ( (sin(heading) * hypxz) + z );\r\n    \r\n    Mth::Vector skaterpos(x, y, z, 0);\r\n    Mth::Vector direction0(x0, y0, z0, 0);\r\n    \r\n    //printf(\"x=%i y=%i z=%i\\n\", direction0[0], direction0[1], direction0[2]);\r\n    \r\n    Gfx::AddDebugLine( skaterpos, direction0, MAKE_RGB( rgb.r, rgb.g, rgb.b ), MAKE_RGB( rgb.r, rgb.g, rgb.b ), 1 );\r\n    \r\n    return true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nSVCLight *CLightManager::s_get_vclight_from_checksum( uint32 cs )\r\n{\r\n\tfor( int i = 0; i < s_num_vc_lights; ++i )\r\n\t{\r\n\t\tif( sp_vc_lights[i].m_checksum == cs )\r\n\t\t{\r\n\t\t\treturn &sp_vc_lights[i];\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nSVCLight::SVCLight( void )\r\n{\r\n\tmp_sector_list = new Lst::HashTable< Nx::CSector >( 4 );\r\n\r\n\tm_radius\t= 0.0f;\r\n\tm_intensity = 0.0f;\r\n\r\n\t// Default the color to pure white.\r\n\tm_color.r\t= 0x80;\r\n\tm_color.g\t= 0x80;\r\n\tm_color.b\t= 0x80;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nSVCLight::~SVCLight( void )\r\n{\r\n\tResetSectorList();\r\n\tdelete mp_sector_list;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SVCLight::SetRadius( float radius )\r\n{\r\n\tDbg_Assert( radius >= 0.0f );\r\n\r\n\tif( radius != m_radius )\r\n\t{\r\n\t\tm_radius = radius;\r\n\r\n\t\t// Deal with the SceneLight that may have been created from this node.\r\n\t\tNx::CSceneLight *p_light = Nx::CLightManager::sGetSceneLight( m_checksum );\r\n\t\tif( p_light )\r\n\t\t{\r\n\t\t\tp_light->SetLightRadius( radius );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SVCLight::SetIntensity( float i )\r\n{\r\n\tDbg_Assert(( i >= 0.0f ) && ( i <= 1.0f ));\r\n\r\n\tif( i != m_intensity )\r\n\t{\r\n\t\tm_intensity = i;\r\n\r\n\t\t// Deal with the SceneLight that may have been created from this node.\r\n\t\tNx::CSceneLight *p_light = Nx::CLightManager::sGetSceneLight( m_checksum );\r\n\t\tif( p_light )\r\n\t\t{\r\n\t\t\tp_light->SetLightIntensity( i );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SVCLight::SetColor( Image::RGBA col )\r\n{\r\n\tm_color = col;\r\n\r\n\t// Deal with the SceneLight that may have been created from this node.\r\n\tNx::CSceneLight *p_light = Nx::CLightManager::sGetSceneLight( m_checksum );\r\n\tif( p_light )\r\n\t{\r\n\t\tp_light->SetLightColor( col );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nLst::HashTable< Nx::CSector > *SVCLight::GetSectorList( void )\r\n{\r\n\treturn mp_sector_list;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SVCLight::ResetSectorList( void )\r\n{\r\n\tmp_sector_list->FlushAllItems();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool SVCLight::AffectsSector( Nx::CSector *p_sector )\r\n{\r\n\tNx::CSector *p_match = mp_sector_list->GetItem((uint32)p_sector );\r\n    return ( p_match != NULL );\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SVCLight::CalculateSectorList( void )\r\n{\r\n\t// First reset the sector list.\r\n\tResetSectorList();\r\n\t\r\n\tNx::CScene *p_scene = Nx::CEngine::sGetMainScene();\r\n\tif( p_scene )\r\n\t{\r\n\t\tLst::HashTable< Nx::CSector > *p_sector_list = p_scene->GetSectorList();\r\n\t\tif( p_sector_list )\r\n\t\t{\r\n\t\t\tp_sector_list->IterateStart();\t\r\n\t\t\tNx::CSector *p_sector = p_sector_list->IterateNext();\r\n\t\t\twhile( p_sector )\r\n\t\t\t{\r\n\t\t\t\t// Only consider this sector if it is not in the \"NoLevelLights\" lightgroup.\r\n\t\t\t\t// and not in the Indoor group\r\n\t\t\t\tif( p_sector->GetLightGroup() != CRCD( 0xed82767b, \"NoLevelLights\" )\r\n\t\t\t\t\t&& p_sector->GetLightGroup() != CRCD(0xec6542d3,\"indoor\"))\r\n\t\t\t\t{\r\n\t\t\t\t\tNx::CGeom *p_geom = p_sector->GetGeom();\r\n\t\t\t\t\tif( p_geom )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// See of the radius of the light will intersect the radius of the bounding box of the geometry.\r\n\t\t\t\t\t\tMth::CBBox\tbbox\t= p_sector->GetBoundingBox();\r\n\t\t\t\t\t\tMth::Vector\tmid\t\t= ( bbox.GetMax() + bbox.GetMin()) / 2.0f;\r\n\t\t\t\t\t\tfloat\t\tr\t\t= ( bbox.GetMax() - mid ).Length();\r\n\t\t\t\t\t\tfloat\t\tdist\t= ( mid - m_pos ).Length();\r\n\t\t\t\t\t\tif( dist < ( r + m_radius ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmp_sector_list->PutItem((uint32)p_sector, p_sector );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tp_sector = p_sector_list->IterateNext();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLightManager::s_recalculate_sector_lighting( Nx::CSector *p_sector )\r\n{\r\n\tNx::CGeom *p_geom = p_sector->GetGeom();\r\n\tif( p_geom == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst int MAX_LIGHTS_AFFECTING_SECTOR = 8;\r\n\r\n\tint\t\t\tcurrent_lights_affecting_sector = 0;\r\n\tint\t\t\tlight_index[MAX_LIGHTS_AFFECTING_SECTOR];\r\n\r\n\t// Build a list of lights that affect this sector, to the maximum of MAX_LIGHTS_AFFECTING_SECTOR.\r\n\tfor( int l = 0; l < s_num_vc_lights; ++l )\r\n\t{\r\n\t\tif(( sp_vc_lights[l].m_intensity > 0.0f ) && sp_vc_lights[l].AffectsSector( p_sector ))\r\n\t\t{\r\n\t\t\tlight_index[current_lights_affecting_sector] = l;\r\n\t\t\tif( ++current_lights_affecting_sector >= MAX_LIGHTS_AFFECTING_SECTOR )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif( current_lights_affecting_sector == 0 )\r\n\t{\r\n\t\t// No lights are affecting this sector, which can happen in the situation where the last remaining\r\n\t\t// light affecting a sector is turned off. In this case we just want to restore the original\r\n\t\t// vertex colors.\r\n\t\tint verts = p_geom->GetNumRenderVerts();\r\n\t\tif( verts > 0 )\r\n\t\t{\r\n\t\t\tImage::RGBA\t*p_colors\t= new Image::RGBA[verts];\r\n\t\t\tp_geom->GetOrigRenderColors( p_colors );\r\n\t\t\tp_geom->SetRenderColors( p_colors );\r\n\t\t\tdelete [] p_colors;\r\n\t\t}\r\n\t}\r\n\telse if( current_lights_affecting_sector > 0 )\r\n\t{\r\n\t\tint verts = p_geom->GetNumRenderVerts();\r\n\t\tif( verts > 0 )\r\n\t\t{\r\n\t\t\tMth::Vector\t*p_verts\t= new Mth::Vector[verts];\r\n\t\t\tImage::RGBA\t*p_colors\t= new Image::RGBA[verts];\r\n\r\n\t\t\tp_geom->GetRenderVerts( p_verts );\r\n\t\t\tp_geom->GetOrigRenderColors( p_colors );\r\n\t\t\t\t\t\r\n\t\t\tImage::RGBA *p_color = p_colors;\r\n\t\t\tMth::Vector *p_vert = p_verts;\r\n\t\t\tfor( int i = 0; i < verts; ++i )\r\n\t\t\t{\r\n\t\t\t\tfloat ir = 0.0f;\r\n\t\t\t\tfloat ig = 0.0f;\r\n\t\t\t\tfloat ib = 0.0f;\r\n\t\t\t\r\n\t\t\t\tfor( int l = 0; l < current_lights_affecting_sector; ++l )\r\n\t\t\t\t{\r\n\t\t\t\t\tSVCLight *p_current_light = &sp_vc_lights[light_index[l]];\r\n\r\n\t\t\t\t\tfloat dist_sqr\t= ( *p_vert - p_current_light->m_pos ).LengthSqr();\r\n\t\t\t\t\tif( dist_sqr < ( p_current_light->m_radius * p_current_light->m_radius ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfloat dist\t\t= sqrtf( dist_sqr );\r\n\t\t\t\t\t\tfloat intensity\t= p_current_light->m_intensity * (( p_current_light->m_radius - dist ) / p_current_light->m_radius );\r\n\r\n\t\t\t\t\t\tir += intensity * (float)p_current_light->m_color.r;\r\n\t\t\t\t\t\tig += intensity * (float)p_current_light->m_color.g;\r\n\t\t\t\t\t\tib += intensity * (float)p_current_light->m_color.b;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Apply to each r,g,b idividually, so we don't loose original color.\r\n\t\t\t\tImage::RGBA rgb = *p_color;\r\n\t\t\t\tfloat v = (float)rgb.r + ir;\r\n\t\t\t\trgb.r = (uint8)(( v > 255.0f ) ? 255.0f : v );\r\n\t\t\t\t\t\t\t\r\n\t\t\t\tv = (float)rgb.g + ig;\r\n\t\t\t\trgb.g = (uint8)(( v > 255.0f ) ? 255.0f : v );\r\n\r\n\t\t\t\tv = (float)rgb.b + ib;\r\n\t\t\t\trgb.b = (uint8)(( v > 255.0f ) ? 255.0f : v );\r\n\r\n\t\t\t\t*p_color = rgb;\r\n\r\n\t\t\t\t++p_color;\r\n\t\t\t\t++p_vert;\r\n\t\t\t}\r\n\r\n\t\t\tp_geom->SetRenderColors( p_colors );\r\n\t\t\t\t\t\t\r\n\t\t\tdelete [] p_verts;\r\n\t\t\tdelete [] p_colors;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLightManager::s_apply_lighting( Nx::CScene * p_scene, uint32 checksum )\r\n{\r\n\t// Now requires a checksum.\r\n\tif( checksum == 0 )\r\n\t\treturn;\r\n\r\n\t// Now deal with geometry.\r\n\tSVCLight *p_scene_light = s_get_vclight_from_checksum( checksum );\r\n\tif( p_scene_light == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tLst::HashTable< Nx::CSector > * p_sector_list = p_scene_light->GetSectorList();\r\n\tif( p_sector_list )\r\n\t{\r\n\t\tp_sector_list->IterateStart();\t\r\n\t\tNx::CSector *p_sector = p_sector_list->IterateNext();\t\t\r\n\t\twhile( p_sector )\r\n\t\t{\r\n\t\t\tNx::CGeom *p_geom = p_sector->GetGeom();\r\n\t\t\tif( p_geom )\r\n\t\t\t{\r\n\t\t\t\ts_recalculate_sector_lighting( p_sector );\r\n\t\t\t}\r\n\t\t\tp_sector = p_sector_list->IterateNext();\r\n\t\t}\r\n\t}\r\n\r\n#\tif 0\r\n\t// Set up an array of lights, (eventually) culled from the node array.\r\n\ts_num_vc_lights = 0;\r\n\r\n\tScript::CArray *p_nodearray=Script::GetArray(\"NodeArray\");\r\n\tfor (uint32 i=0; i<p_nodearray->GetSize(); ++i)\r\n\t{\r\n\t\tScript::CStruct *p_node_struct=p_nodearray->GetStructure(i);\r\n\t\tDbg_MsgAssert(p_node_struct,(\"Error getting node from node array for rail generation\"));\r\n\r\n\t\tuint32 class_checksum = 0;\t\t\r\n\t\tp_node_struct->GetChecksum( CRCD(0x12b4e660, \"Class\"), &class_checksum );\r\n\t\tif (class_checksum == CRCD(0xa0e52802,\"LevelLight\"))\r\n\t\t{\r\n\t\t\tSkateScript::GetPosition(p_node_struct,&sp_vc_lights[s_num_vc_lights].m_pos);\r\n\t\t\t\r\n\t\t\tsp_vc_lights[s_num_vc_lights].m_value = 100.0f;  \t\t// default values\r\n\t\t\tsp_vc_lights[s_num_vc_lights].m_radius = 300.0f;\r\n\t\t\t\r\n\t\t\tp_node_struct->GetFloat(CRCD(0x2689291c,\"Brightness\"),&sp_vc_lights[s_num_vc_lights].m_value);\t\r\n\t\t\tp_node_struct->GetFloat(CRCD(0xc48391a5,\"Radius\"),&sp_vc_lights[s_num_vc_lights].m_radius);\t\r\n\t\t\t\r\n\t\t\ts_num_vc_lights++;\r\n\t\t}\r\n\t}\r\n\tDbg_Message( \"Found %d LevelLights\\n\", s_num_vc_lights );\r\n\r\n\tif( s_num_vc_lights == 0 )\r\n\t{\r\n\t\tDbg_Message( \"Did not find any LevelLight nodes, so using Pedestrian nodes....\\n\" );\r\n\r\n\t\t// Scan through the node array creating all things that need to be created.\r\n\t\tScript::CArray *p_nodearray=Script::GetArray(\"NodeArray\");\r\n\t\tfor (uint32 i=0; i<p_nodearray->GetSize(); ++i)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_node_struct=p_nodearray->GetStructure(i);\r\n\t\t\tDbg_MsgAssert(p_node_struct,(\"Error getting node from node array for rail generation\"));\r\n\t\r\n\t\t\tuint32 class_checksum = 0;\t\t\r\n\t\t\tp_node_struct->GetChecksum( CRCD(0x12b4e660, \"Class\"), &class_checksum );\r\n\t\t\tif (class_checksum == CRCD(0xa0dfac98,\"Pedestrian\"))\r\n\t\t\t{\r\n\t\t\t\tSkateScript::GetPosition(p_node_struct,&sp_vc_lights[s_num_vc_lights].m_pos);\r\n\t\t\t\tsp_vc_lights[s_num_vc_lights].m_value = 100.0f;\r\n\t\t\t\tsp_vc_lights[s_num_vc_lights].m_radius = 300.0f;\r\n\t\t\t\ts_num_vc_lights++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Go through each object, find the nearest light that intersects the object\r\n\t// and the  apply lighting from that\r\n\tLst::HashTable< Nx::CSector > * p_sector_list = p_scene->GetSectorList();\r\n\t\r\n\tImage::RGBA rgb;\r\n\t\r\n\tif (p_sector_list)\r\n\t{\r\n\t\tp_sector_list->IterateStart();\t\r\n\t\tNx::CSector *p_sector = p_sector_list->IterateNext();\t\t\r\n\t\twhile(p_sector)\r\n\t\t{\r\n\r\n\t\t\tNx::CGeom \t*p_geom = p_sector->GetGeom();\r\n\t\t\t\r\n\t\t\tif (p_geom)\r\n\t\t\t{\r\n\t\t\t\t// Need to find a light (if any) such that the radius of the light\r\n\t\t\t\t// will intersect the radius of the bounding box of the geometry\r\n\t\t\t\tMth::CBBox bbox = p_sector->GetBoundingBox();\r\n\t\t\t\tMth::Vector\tmid = (bbox.GetMax() + bbox.GetMin())/2.0f;\r\n\t\t\t\tfloat\tradius = (bbox.GetMax() - bbox.GetMin()).Length();\r\n\r\n\t\t\t\tint best_light = -1;\r\n\t\t\t\tfloat best_dist = 100000000000.0f;\t\t\t\t\r\n\t\t\t\tfor (int light = 0; light < s_num_vc_lights; light++)\r\n\t\t\t\t{\r\n\t\t\t\t\tfloat dist = (mid - sp_vc_lights[light].m_pos).Length();\t\t\t\t\t\r\n\t\t\t\t\tif (dist < best_dist && dist < (radius+sp_vc_lights[light].m_radius))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbest_dist = dist;\r\n\t\t\t\t\t\tbest_light = light;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (best_light != -1)\r\n\t\t\t\t{\r\n\t\t\t\t\t\r\n\t\t\t\t\tMth::Vector\tlight_pos = sp_vc_lights[best_light].m_pos;\r\n\t\t\t\t\tfloat\tlight_radius = sp_vc_lights[best_light].m_radius;\r\n\t\t\t\t\tfloat\tlight_radius_squared = light_radius * light_radius;\r\n\t\t\t\t\tfloat\tlight_value = sp_vc_lights[best_light].m_value * amount;\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t//\r\n\t\t\t\t\t// Do renderable geometry\r\n\t\t\t\t\tint verts = p_geom->GetNumRenderVerts();\r\n\t\t\t\t\r\n\t\t\t\t\tif (verts)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMth::Vector\t*p_verts = new Mth::Vector[verts];\r\n\t\t\t\t\t\tImage::RGBA\t*p_colors = new Image::RGBA[verts];\r\n\t\t\t\t\t\tp_geom->GetRenderVerts(p_verts);\r\n\t\t\t\t\t\t// Note: getting the original render colors will allocate lots of memory\r\n\t\t\t\t\t\t// to store all the origianl colors the firs tiem it is called\r\n\t\t\t\t\t\t//p_geom->GetOrigRenderColors(p_colors);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// For lighting, we get the current colors, so needs to be applied in conjunction with a compressVC\r\n\t\t\t\t\t\tp_geom->GetRenderColors(p_colors);\r\n\t\t\t\t\t\r\n\t\t\t\t\t\tImage::RGBA *p_color = p_colors;\r\n\t\t\t\t\t\tMth::Vector *p_vert = p_verts;\r\n\t\t\t\t\t\tfor (int i = 0; i < verts; i++)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t//\t\t\tCalculateVertexLighting(*p_vert, *p_color);\r\n\r\n\t\t\t\t\t\t\tfloat dist_sqr = (*p_vert - light_pos).LengthSqr();\r\n\t\t\t\t\t\t\tfloat intensity = (light_radius_squared-dist_sqr)/light_radius_squared * light_value;\r\n\t\t\t\t\t\t\tif (intensity<0.0f)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tintensity = 0.0f;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\trgb = *p_color;\r\n\t\t\t\t\t\t\tfloat v;\r\n\r\n\t\t\t\t\t\t\t// Apply to each r,g,b idividually, so we don't loose original color\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tv = (float) rgb.r + intensity;\r\n\t\t\t\t\t\t\tif (v > 255.0f) v = 255.0f;\r\n\t\t\t\t\t\t\trgb.r = (uint8) v; \r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tv = (float) rgb.g + intensity;\r\n\t\t\t\t\t\t\tif (v > 255.0f) v = 255.0f;\r\n\t\t\t\t\t\t\trgb.g = (uint8) v; \r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tv = (float) rgb.b + intensity;\r\n\t\t\t\t\t\t\tif (v > 255.0f) v = 255.0f;\r\n\t\t\t\t\t\t\trgb.b = (uint8) v; \r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t\t*p_color = rgb;\t\t//(*p_color & 0xff000000) | color;\r\n\t\t\t\t\t\t\t//*(uint32*)p_color = Mth::Rnd(32767);\t\t//(*p_color & 0xff000000) | color;\r\n\t\t\t\t\r\n\t\t\t\t\t\t\tp_color++;\r\n\t\t\t\t\t\t\tp_vert++;\r\n\t\t\t\t\t\t} // end for\r\n\t\t\t\t\r\n\t\t\t\t\t\tp_geom->SetRenderColors(p_colors);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tdelete [] p_verts;\r\n\t\t\t\t\t\tdelete [] p_colors;\r\n\t\t\t\t\t} // end if\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// debuggery\r\n\t\t\t\t\t\t//p_geom->SetColor(Image::RGBA(0,0,100,0));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tp_sector = p_sector_list->IterateNext();\r\n\t\t}\r\n\t}\r\n#\tendif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// K: Factored this out so that the FakeLights command could also adjust a set of prefixed nodes.\r\nvoid CLightManager::sFakeLight(uint32 id, Script::CStruct *pParams)\r\n{\r\n\tNx::CScene *p_scene = Nx::CEngine::sGetMainScene();\r\n\t\r\n\tfloat\tamount, radius;\r\n\tint\t\tred, grn, blu;\r\n\r\n\t// Get the SVCLight created from this node.\r\n\tSVCLight *p_light = s_get_vclight_from_checksum( id );\r\n\tif( p_light )\r\n\t{\r\n\t\t// Determine the intensity required.\r\n\t\tif( pParams->GetFloat( CRCD(0x9e497fc6,\"percent\"), &amount ))\r\n\t\t{\r\n\t\t\t// Want to adjust the intensity. Convert from percentage to [0.0, 1.0].\r\n\t\t\tamount = amount * 0.01f;\r\n\r\n\t\t\t// Adjust the light intensity for this amount.\r\n\t\t\tp_light->SetIntensity( amount );\r\n\t\t}\r\n\r\n\t\tif( pParams->GetFloat( CRCD(0x999151b,\"outer_radius\"), &radius ))\r\n\t\t{\r\n\t\t\tp_light->SetRadius( radius );\r\n\r\n\t\t\t// Changing the radius requires that the sector list be rebuilt.\r\n\t\t\tp_light->CalculateSectorList();\r\n\t\t}\r\n\r\n\t\tif( pParams->GetInteger( CRCD(0x59ea070,\"red\"), &red ))\r\n\t\t{\r\n\t\t\t// We must have a green and blue value too.\r\n\t\t\tpParams->GetInteger( CRCD(0x2f6511de,\"green\"), &grn, true );\r\n\t\t\tpParams->GetInteger( CRCD(0x61c9354b,\"blue\"), &blu, true );\r\n\r\n\t\t\tImage::RGBA col( red, grn, blu, 0xFF );\r\n\r\n\t\t\t// Adjust the light color.\r\n\t\t\tp_light->SetColor( col );\r\n\t\t}\r\n\r\n\t\ts_apply_lighting( p_scene, id );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Perhaps there is just a light for objects?\r\n\t\tNx::CSceneLight *p_obj_light = Nx::CLightManager::sGetSceneLight( id );\r\n\t\tif( p_obj_light )\r\n\t\t{\r\n\t\t\t// Determine the intensity required.\r\n\t\t\tif( pParams->GetFloat( CRCD(0x9e497fc6,\"percent\"), &amount ))\r\n\t\t\t{\r\n\t\t\t\t// Want to adjust the intensity. Convert from percentage to [0.0, 1.0].\r\n\t\t\t\tamount = amount * 0.01f;\r\n\r\n\t\t\t\t// Adjust the light intensity for this amount.\r\n\t\t\t\tp_obj_light->SetLightIntensity( amount );\r\n\t\t\t}\r\n\r\n\t\t\tif( pParams->GetFloat( CRCD(0x999151b,\"outer_radius\"), &radius ))\r\n\t\t\t{\r\n\t\t\t\tp_obj_light->SetLightRadius( radius );\r\n\t\t\t}\r\n\r\n\t\t\tif( pParams->GetInteger( CRCD(0x59ea070,\"red\"), &red ))\r\n\t\t\t{\r\n\t\t\t\t// We must have a green and blue value too.\r\n\t\t\t\tpParams->GetInteger( CRCD(0x2f6511de,\"green\"), &grn, true );\r\n\t\t\t\tpParams->GetInteger( CRCD(0x61c9354b,\"blue\"), &blu, true );\r\n\r\n\t\t\t\tImage::RGBA col( red, grn, blu, 0xFF );\r\n\r\n\t\t\t\t// Adjust the light color.\r\n\t\t\t\tp_obj_light->SetLightColor( col );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxLightMan.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// NxLightMan.H - Neversoft Engine, Rendering portion, Platform independent interface\r\n\r\n#ifndef\t__GFX_NX_LIGHT_MAN_H__\r\n#define\t__GFX_NX_LIGHT_MAN_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/math.h>\r\n#include <gfx/image/imagebasic.h>\r\n\r\n#ifndef __CORE_LIST_HASHTABLE_H\r\n#include <core/hashtable.h>\r\n#endif\r\n\r\n#ifndef\t__GFX_NXSECTOR_H__\r\n#include <gfx/NxSector.h>\r\n#endif\r\n\r\n\r\nnamespace Script\r\n{\r\n\tclass CScriptStructure;\r\n\tclass CScript;\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\n// Forward declarations\r\nclass CModelLights;\r\nclass CSector;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CSceneLight\r\n{\r\npublic:\r\n\r\n\tinline void\t\t\t\t\t\tSetLightPosition( Mth::Vector &pos )\t{ m_pos = pos; }\r\n\tinline Mth::Vector &\t\t\tGetLightPosition( void )\t\t\t\t{ return m_pos; }\r\n\r\n\tinline void\t\t\t\t\t\tSetNameChecksum( uint32 cs )\t\t\t{ m_name_checksum = cs; }\r\n\tinline uint32\t\t\t\t\tGetNameChecksum( void )\t\t\t\t\t{ return m_name_checksum; }\r\n\r\n\tinline void\t\t\t\t\t\tSetLightColor( Image::RGBA col )\t\t{ m_color = col; }\r\n\tinline Image::RGBA &\t\t\tGetLightColor( void )\t\t\t\t\t{ return m_color; }\r\n\r\n\tinline void\t\t\t\t\t\tSetLightIntensity( float i )\t\t\t{ m_intensity = i; }\r\n\tinline float\t\t\t\t\tGetLightIntensity( void )\t\t\t\t{ return m_intensity; }\r\n\r\n\tinline void\t\t\t\t\t\tSetLightRadius( float r )\t\t\t\t{ m_radius = r; m_reciprocal_radius = 1.0f / r; }\r\n\tinline float\t\t\t\t\tGetLightRadius( void )\t\t\t\t\t{ return m_radius; }\r\n\tinline float\t\t\t\t\tGetLightReciprocalRadius( void )\t\t{ return m_reciprocal_radius; }\r\n\r\nprotected:\r\n\r\n\tMth::Vector\t\t\t\t\t\tm_pos;\r\n\tfloat\t\t\t\t\t\t\tm_radius;\r\n\tfloat\t\t\t\t\t\t\tm_reciprocal_radius;\r\n\tfloat\t\t\t\t\t\t\tm_intensity;\t\t\t\t// Intensity in range [0.0, 1.0].\r\n\tImage::RGBA\t\t\t\t\t\tm_color;\r\n\tuint32\t\t\t\t\t\t\tm_name_checksum;\t\t\t// Provides a link between the light and the node that created it.\r\n};\r\n\r\n\r\nstruct SVCLight\r\n{\r\n\tMth::Vector\t\t\t\t\t\tm_pos;\r\n\tfloat\t\t\t\t\t\t\tm_intensity;\t\t// [0.0, 1.0].\r\n\tfloat\t\t\t\t\t\t\tm_radius;\r\n\tuint32\t\t\t\t\t\t\tm_checksum;\t\t\t// Checksum of the name of the node that corresponds to this light.\r\n\tImage::RGBA\t\t\t\t\t\tm_color;\r\n\tLst::HashTable< Nx::CSector >\t*mp_sector_list;\t// List of all the sectors that this light can affect.\r\n\r\n\t\t\t\t\t\t\t\t\tSVCLight();\r\n\t\t\t\t\t\t\t\t\t~SVCLight();\r\n\r\n\r\n\tvoid\t\t\t\t\t\t\tSetPosition( Mth::Vector & pos )\t\t\t{ m_pos = pos; }\r\n\tvoid\t\t\t\t\t\t\tSetNameChecksum( uint32 cs )\t\t\t\t{ m_checksum = cs; }\r\n\tvoid\t\t\t\t\t\t\tSetIntensity( float i );\r\n\tvoid\t\t\t\t\t\t\tSetColor( Image::RGBA col );\r\n\tvoid\t\t\t\t\t\t\tSetRadius( float radius );\r\n\tvoid\t\t\t\t\t\t\tResetSectorList( void );\r\n\tvoid\t\t\t\t\t\t\tCalculateSectorList( void );\r\n\tbool\t\t\t\t\t\t\tAffectsSector( Nx::CSector *p_sector );\r\n\tLst::HashTable< Nx::CSector >\t*GetSectorList( void );\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// Nx::CLightManager\r\nclass\tCLightManager\r\n{\r\npublic:\r\n\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tMAX_LIGHTS\t\t\t\t= 2,\r\n\t\tMAX_SCENE_LIGHTS\t\t= 256,\t// These are static, designer placed lights in the level.\r\n\t\tMAX_VC_LIGHTS\t\t\t= 150,\r\n\t\tWORLD_LIGHTS_STACK_SIZE\t= 4,\r\n\t};\r\n\r\n\t// Upload lights to the engine (if applicable)\r\n\tstatic void\t\t\t\t\tsUpdateEngine( void );\r\n\r\n\t// Create and destroy Lights\r\n\tstatic void\t\t\t\t\tsClearLights();\r\n\r\n\t// World lights\r\n\tstatic bool\t\t\t\t\tsSetLightAmbientColor(const Image::RGBA rgba);\r\n\tstatic Image::RGBA\t\t\tsGetLightAmbientColor();\r\n\r\n\tstatic bool\t\t\t\t\tsSetLightDirection(int light_index, const Mth::Vector &direction);\r\n\tstatic const Mth::Vector &\tsGetLightDirection(int light_index);\r\n\r\n\tstatic bool\t\t\t\t\tsSetLightDiffuseColor(int light_index, const Image::RGBA rgba);\r\n\tstatic Image::RGBA\t\t\tsGetLightDiffuseColor(int light_index);\r\n\r\n\tstatic void\t\t\t\t\tsSetAmbientLightModulationFactor(float factor);\r\n\tstatic float\t\t\t\tsGetAmbientLightModulationFactor();\r\n\tstatic void\t\t\t\t\tsSetDiffuseLightModulationFactor(int light_index, float factor);\r\n\tstatic float\t\t\t\tsGetDiffuseLightModulationFactor(int light_index);\r\n\r\n\t// Push and pop world lights on stack\r\n\tstatic void\t\t\t\t\tsPushWorldLights();\r\n\tstatic bool\t\t\t\t\tsPopWorldLights();\r\n\r\n\t// Model Lights\r\n\tstatic CModelLights *\t\tsCreateModelLights();\r\n\tstatic bool\t\t\t\t\tsFreeModelLights(CModelLights *p_model_lights);\r\n\r\n\t// This is here temporarily\r\n\tstatic bool\t\t\t\t\tsSetBrightness(float brightness);\r\n\r\n\t// Static scene lights.\r\n\tstatic CSceneLight *\t\tsAddSceneLight( void );\r\n\tstatic CSceneLight *\t\tsGetSceneLight( uint32 checksum );\r\n\tstatic CSceneLight *\t\tsGetOptimumSceneLight( Mth::Vector & pos );\r\n\tstatic void\t\t\t\t\tsClearSceneLights( void );\r\n\r\n\tstatic void\t\t\t\t\tsClearVCLights();\r\n\tstatic void\t\t\t\t\tsAddVCLight(uint32 name, Mth::Vector &pos, float intensity,\r\n\t\t\t\t\t\t\t\t\t\t\tImage::RGBA col, float outer_radius);\r\n\r\n\tstatic void\t\t\t\t\tsClearCurrentFakeLightsCommand();\t\r\n\tstatic void\t\t\t\t\tsUpdateVCLights();\r\n\tstatic void\t\t\t\t\tsFakeLight(uint32 id, Script::CStruct *pParams);\r\n\tstatic void\t\t\t\t\tsFakeLights(const uint16 *p_nodes, int numNodes, int period, Script::CStruct *pParams);\r\n\t\r\nprotected:\t\r\n\r\n\t// Set of lights\r\n\tstruct SLightSet\r\n\t{\r\n\t\t// Ambient and diffuse lights\r\n\t\tImage::RGBA\t\t\t\tm_light_ambient_rgba;\r\n\t\tMth::Vector\t\t\t\tm_light_direction[MAX_LIGHTS];\r\n\t\tImage::RGBA\t\t\t\tm_light_diffuse_rgba[MAX_LIGHTS];\r\n\r\n\t\t// Modulation info\r\n\t\tfloat\t\t\t\t\tm_ambient_light_modulation_factor;\r\n\t\tfloat\t\t\t\t\tm_diffuse_light_modulation_factor[MAX_LIGHTS];\r\n\t};\r\n\r\n\t// World lights\r\n\tstatic SLightSet\t\t\ts_world_lights;\t\t\t\t\t\t// Current world lights\r\n\tstatic SLightSet\t\t\ts_world_lights_stack[WORLD_LIGHTS_STACK_SIZE];\r\n\tstatic int\t\t\t\t\ts_world_lights_stack_index;\t\t\t// index to top of stack (-1 if empty)\r\n\r\n\tstatic CSceneLight\t\t\ts_scene_lights[MAX_SCENE_LIGHTS];\r\n\tstatic int\t\t\t\t\ts_num_scene_lights;\r\n\r\n\tstatic SVCLight\t\t\t\tsp_vc_lights[MAX_VC_LIGHTS];\r\n\tstatic int\t\t\t\t\ts_num_vc_lights;\r\n\r\n\tstatic uint16 *\t\t\t\tsp_fake_lights_nodes;\r\n\tstatic int\t\t\t\t\ts_num_fake_lights_nodes;\r\n\tstatic int\t\t\t\t\ts_next_fake_light_node_to_process;\r\n\tstatic int\t\t\t\t\ts_fake_lights_period;\r\n\tstatic int\t\t\t\t\ts_fake_lights_current_time;\r\n\tstatic Script::CStruct *\tsp_fake_lights_params;\r\n\t\r\n\t// These are here temporarily\r\n\tstatic float\t\t\t\ts_brightness;\r\n\tstatic float\t\t\t\ts_brightness_target;\r\n\tstatic float\t\t\t\ts_min_brightness;\r\n\tstatic float\t\t\t\ts_ambient_brightness;\r\n\tstatic float\t\t\t\ts_diffuse_brightness[MAX_LIGHTS];\r\n\r\n\tstatic SVCLight *\t\t\ts_get_vclight_from_checksum( uint32 cs );\r\n\tstatic void\t\t\t\t\ts_recalculate_sector_lighting( Nx::CSector *p_sector );\r\n\tstatic void\t\t\t\t\ts_apply_lighting( Nx::CScene * p_scene, uint32 checksum = 0 );\r\n\r\n\t// Platform-specific calls\r\n\tstatic void\t\t\t\t\ts_plat_update_engine();\r\n\tstatic void\t\t\t\t\ts_plat_update_lights();\r\n\tstatic void\t\t\t\t\ts_plat_update_colors();\r\n\tstatic bool\t\t\t\t\ts_plat_set_light_ambient_color();\r\n\tstatic bool\t\t\t\t\ts_plat_set_light_direction(int light_index);\r\n\tstatic bool\t\t\t\t\ts_plat_set_light_diffuse_color(int light_index);\r\n\tstatic Image::RGBA\t\t\ts_plat_get_light_ambient_color();\r\n\tstatic const Mth::Vector &\ts_plat_get_light_direction(int light_index);\r\n\tstatic Image::RGBA\t\t\ts_plat_get_light_diffuse_color(int light_index);\r\n\r\n\tstatic CModelLights *\t\ts_plat_create_model_lights();\r\n\tstatic bool\t\t\t\t\ts_plat_free_model_lights(CModelLights *p_model_lights);\r\n\r\n\t// Friends\r\n\tfriend CModelLights;\r\n\tfriend CSceneLight;\r\n};\r\n\r\nbool ScriptSetLightAmbientColor(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptSetLightDirection(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptSetLightDiffuseColor(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptGetLightCurrentColor(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptPushWorldLights(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptPopWorldLights(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptDrawDirectionalLightLines(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\n}\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxLoadScreen.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxLoadScreen.cpp\r\n\r\n// start autoduck documentation\r\n// @DOC NxLoadScreen\r\n// @module NxLoadScreen | None\r\n// @subindex Scripting Database\r\n// @index script | NxLoadScreen\r\n\r\n#include <core/defines.h>\r\n#include <gfx/NxLoadScreen.h>\r\n\r\n#include <gel/Scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\nbool\t\t\tCLoadScreen::s_active = false;\t\t// Set to true when loading screen is enabled\r\nfloat\t\t\tCLoadScreen::s_load_time;\t\t\t// Amount of time it takes for loading bar to go to 100%\r\nint\t\t\t\tCLoadScreen::s_bar_x = 258;\t\t\t// Bar position\r\nint\t\t\t\tCLoadScreen::s_bar_y = 400;\r\nint\t\t\t\tCLoadScreen::s_bar_width = 140;\t\t// Bar size\r\nint\t\t\t\tCLoadScreen::s_bar_height = 8;\r\nImage::RGBA\t\tCLoadScreen::s_bar_start_color = Image::RGBA(0, 76, 129, 128);\r\nImage::RGBA\t\tCLoadScreen::s_bar_end_color = Image::RGBA(172, 211, 115, 128);\r\nint\t\t\t\tCLoadScreen::s_bar_border_width = 5;// Border width\r\nint\t\t\t\tCLoadScreen::s_bar_border_height = 5;// Border height\r\nImage::RGBA\t\tCLoadScreen::s_bar_border_color = Image::RGBA(40, 40, 40, 128);\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::sDisplay(const char* filename, bool just_freeze, bool blank)\r\n{\r\n\t// Get rid of old stuff, if any\r\n\ts_clear();\r\n\r\n\ts_plat_display(filename, just_freeze, blank);\r\n\r\n\t//sStartLoadingBar(38.0f);\r\n\r\n\ts_active = true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::sStartLoadingBar(float seconds)\r\n{\r\n\tif (seconds <= 0.0f)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\ts_load_time = seconds;\r\n\r\n\ts_plat_update_bar_properties();\t\t\t// Just in case\r\n\ts_plat_start_loading_bar(seconds);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nvoid CLoadScreen::sHide()\r\n{\r\n\t// Turn off drawing\r\n\ts_plat_hide();\r\n\r\n\t// Get rid of old stuff\r\n\ts_clear();\r\n\r\n\ts_active = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::sSetLoadingBarPos(int x, int y)\r\n{\r\n\ts_bar_x = x;\r\n\ts_bar_y = y;\r\n\r\n\ts_plat_update_bar_properties();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::sSetLoadingBarSize(int width, int height)\r\n{\r\n\ts_bar_width = width;\r\n\ts_bar_height = height;\r\n\r\n\ts_plat_update_bar_properties();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::sSetLoadingBarStartColor(Image::RGBA color)\r\n{\r\n\ts_bar_start_color = color;\r\n\r\n\ts_plat_update_bar_properties();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::sSetLoadingBarEndColor(Image::RGBA color)\r\n{\r\n\ts_bar_end_color = color;\r\n\r\n\ts_plat_update_bar_properties();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::sSetLoadingBarBorder(int width, int height)\r\n{\r\n\ts_bar_border_width = width;\r\n\ts_bar_border_height = height;\r\n\r\n\ts_plat_update_bar_properties();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::sSetLoadingBarBorderColor(Image::RGBA color)\r\n{\r\n\ts_bar_border_color = color;\r\n\r\n\ts_plat_update_bar_properties();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::s_clear()\r\n{\r\n\ts_plat_clear();\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// The script functions\r\n\r\n// @script | SetLoadingBarPos | Sets the position of the loading bar\r\n// @parm int | x | X position of bar\r\n// @parm int | y | Y position of bar\r\nbool ScriptSetLoadingBarPos(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tint x, y;\r\n\tif (!pParams->GetInteger(\"x\", &x))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'x' position of bar\"));\r\n\t}\r\n\tif (!pParams->GetInteger(\"y\", &y))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'y' position of bar\"));\r\n\t}\r\n\r\n\tCLoadScreen::sSetLoadingBarPos(x, y);\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | SetLoadingBarSize | Sets the size of the loading bar\r\n// @parm int | width | Width of bar\r\n// @parm int | height | Heigh of bar\r\nbool ScriptSetLoadingBarSize(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tint width, height;\r\n\tif (!pParams->GetInteger(\"width\", &width))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'width' of bar\"));\r\n\t}\r\n\tif (!pParams->GetInteger(\"height\", &height))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'height' of bar\"));\r\n\t}\r\n\r\n\tCLoadScreen::sSetLoadingBarSize(width, height);\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | SetLoadingBarStartColor | Sets the color of the left side of the loading bar\r\n// @parm int | r | Red\r\n// @parm int | g | Green\r\n// @parm int | b | Blue\r\nbool ScriptSetLoadingBarStartColor(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tint r, g, b;\r\n\tif (!pParams->GetInteger(\"r\", &r))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'r' color\"));\r\n\t}\r\n\tif (!pParams->GetInteger(\"g\", &g))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'g' color\"));\r\n\t}\r\n\tif (!pParams->GetInteger(\"b\", &b))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'b' color\"));\r\n\t}\r\n\t\r\n\tImage::RGBA rgb(r, g, b, 0x80);\r\n\r\n\tCLoadScreen::sSetLoadingBarStartColor(rgb);\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | SetLoadingBarEndColor | Sets the color of the right side of the loading bar\r\n// @parm int | r | Red\r\n// @parm int | g | Green\r\n// @parm int | b | Blue\r\nbool ScriptSetLoadingBarEndColor(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tint r, g, b;\r\n\tif (!pParams->GetInteger(\"r\", &r))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'r' color\"));\r\n\t}\r\n\tif (!pParams->GetInteger(\"g\", &g))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'g' color\"));\r\n\t}\r\n\tif (!pParams->GetInteger(\"b\", &b))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'b' color\"));\r\n\t}\r\n\t\r\n\tImage::RGBA rgb(r, g, b, 0x80);\r\n\r\n\tCLoadScreen::sSetLoadingBarEndColor(rgb);\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | SetLoadingBarBorder | Sets the size of the loading bar border\r\n// @parm int | width | Width of bar border\r\n// @parm int | height | Heigh of bar border\r\nbool ScriptSetLoadingBarBorder(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tint width, height;\r\n\tif (!pParams->GetInteger(\"width\", &width))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'width' of bar border\"));\r\n\t}\r\n\tif (!pParams->GetInteger(\"height\", &height))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'height' of bar border\"));\r\n\t}\r\n\r\n\tCLoadScreen::sSetLoadingBarBorder(width, height);\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | SetLoadingBarBorderColor | Sets the color of the loading bar border\r\n// @parm int | r | Red\r\n// @parm int | g | Green\r\n// @parm int | b | Blue\r\nbool ScriptSetLoadingBarBorderColor(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tint r, g, b;\r\n\tif (!pParams->GetInteger(\"r\", &r))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'r' color\"));\r\n\t}\r\n\tif (!pParams->GetInteger(\"g\", &g))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'g' color\"));\r\n\t}\r\n\tif (!pParams->GetInteger(\"b\", &b))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find 'b' color\"));\r\n\t}\r\n\t\r\n\tImage::RGBA rgb(r, g, b, 0x80);\r\n\r\n\tCLoadScreen::sSetLoadingBarBorderColor(rgb);\r\n\r\n\treturn true;\r\n}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxLoadScreen.h",
    "content": "#ifndef __GFX_NX_LOAD_SCREEN_H__\r\n#define __GFX_NX_LOAD_SCREEN_H__\r\n\r\n#include <gfx/image/imagebasic.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CScriptStructure;\r\n\tclass CScript;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\nclass CLoadScreen\r\n{\r\npublic:\r\n\tstatic void\t\t\t\t\tsDisplay(const char* filename, bool just_freeze, bool blank);\r\n\tstatic void\t\t\t\t\tsStartLoadingBar(float seconds);\r\n\tstatic void\t\t\t\t\tsHide();\r\n\tstatic bool\t\t\t\t\tsIsActive() { return s_active; }\r\n\r\n\tstatic void\t\t\t\t\tsSetLoadingBarPos(int x, int y);\r\n\tstatic void\t\t\t\t\tsSetLoadingBarSize(int width, int height);\r\n\tstatic void\t\t\t\t\tsSetLoadingBarStartColor(Image::RGBA color);\r\n\tstatic void\t\t\t\t\tsSetLoadingBarEndColor(Image::RGBA color);\r\n\tstatic void\t\t\t\t\tsSetLoadingBarBorder(int width, int height);\r\n\tstatic void\t\t\t\t\tsSetLoadingBarBorderColor(Image::RGBA color);\r\n\r\nprivate:\r\n\tstatic void\t\t\t\t\ts_clear();\t\t// Clears out old memory (called by both Display and Hide)\r\n\r\n\t// The platform dependent calls\r\n\tstatic void\t\t\t\t\ts_plat_display(const char *filename, bool just_freeze, bool blank);\r\n\tstatic void\t\t\t\t\ts_plat_start_loading_bar(float seconds);\r\n\tstatic void\t\t\t\t\ts_plat_hide();\r\n\r\n\tstatic void\t\t\t\t\ts_plat_update_bar_properties();\r\n\r\n\tstatic void\t\t\t\t\ts_plat_clear();\r\n\r\n\tstatic bool\t\t\t\t\ts_active;\t\t\t// Set to true when loading screen is enabled\r\n\tstatic float\t\t\t\ts_load_time;\t\t// Amount of time it takes for loading bar to go to 100%\r\n\tstatic int\t\t\t\t\ts_bar_x;\t\t\t// Bar position\r\n\tstatic int\t\t\t\t\ts_bar_y;\r\n\tstatic int\t\t\t\t\ts_bar_width;\t\t// Bar size\r\n\tstatic int\t\t\t\t\ts_bar_height;\r\n\tstatic Image::RGBA\t\t\ts_bar_start_color;\r\n\tstatic Image::RGBA\t\t\ts_bar_end_color;\r\n\tstatic int\t\t\t\t\ts_bar_border_width;\t// Border width\r\n\tstatic int\t\t\t\t\ts_bar_border_height;// Border height\r\n\tstatic Image::RGBA\t\t\ts_bar_border_color;\r\n};\r\n\r\nbool ScriptSetLoadingBarPos(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptSetLoadingBarSize(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptSetLoadingBarStartColor(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptSetLoadingBarEndColor(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptSetLoadingBarBorder(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptSetLoadingBarBorderColor(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\n}\r\n\r\n#endif //__GFX_NX_LOAD_SCREEN_H__\r\n"
  },
  {
    "path": "Code/Gfx/NxMesh.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       NxMesh.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/15/2002\r\n//****************************************************************************\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/nxmesh.h>\r\n#include <gfx/nxhierarchy.h>\r\n\r\n#include <gel/collision/collision.h>\r\n#include <gel/collision/colltridata.h>\r\n\r\n#include <sys/file/pip.h>\r\n\r\n#ifdef __PLAT_NGC__\r\n#include <gfx/ngc/p_nxmesh.h>\r\n#endif\t\t// __PLAT_NGC__\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stub versions of all platform specific functions are provided here:\r\n// so engine implementors can leave certain functionality until later\r\n\t\t\t\t\t\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// These functions are the platform independent part of the interface to \r\n// the platform specific code\r\n// parameter checking can go here....\r\n// although we might just want to have these functions inline, or not have them at all?\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMesh::CMesh()\r\n{\r\n\tm_CASRemovalMask = 0;\r\n\r\n\t// In case it isn't loaded below the p-line\r\n\tmp_hierarchyObjects = NULL;\r\n\tm_numHierarchyObjects = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMesh::~CMesh()\r\n{\r\n\t// Remove Collision\r\n\tif (mp_coll_objects)\r\n\t{\r\n\t\tPip::Unload(m_coll_filename);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCMesh::LoadCollision(const char *p_name)\r\n{\r\n\t\r\n\t// for now collision is kind of assumed to be platform independent \r\n\tstrcpy(m_coll_filename, p_name);\r\n\tchar *p_ext = strstr(m_coll_filename, \".\");\r\n\tif (p_ext)\r\n\t{\r\n\t\tstrcpy(p_ext, \".col.\");\r\n\t} else {\r\n\t\tstrcat(m_coll_filename, \".col.\");\r\n\t}\r\n\tstrcat(m_coll_filename, CEngine::sGetPlatformExtension());\r\n\r\n//\tDbg_Message ( \"Loading collision %s....\", m_coll_filename );\r\n\r\n\tMem::PushMemProfile((char*)m_coll_filename);\r\n\r\n\tuint8 *p_base_addr = (uint8 *) Pip::Load(m_coll_filename);\r\n\tif (p_base_addr)\r\n\t{\r\n\t\tNx::CCollObjTriData::SReadHeader *p_header = (Nx::CCollObjTriData::SReadHeader *) p_base_addr;\r\n\t\tp_base_addr += sizeof(Nx::CCollObjTriData::SReadHeader);\r\n\r\n//\t\tDbg_Message ( \"Version # %d header sizeof %d\", p_header->m_version, sizeof(Nx::CCollObjTriData));\r\n#ifdef __PLAT_NGC__\r\n\t\tDbg_Message ( \"Number of objects: %d verts: %d faces: %d\", p_header->m_num_objects, p_header->m_total_num_verts, p_header->m_total_num_faces );\r\n#else\r\n//\t\tDbg_Message ( \"Number of objects: %d verts: %d faces: %d\", p_header->m_num_objects, p_header->m_total_num_verts, p_header->m_total_num_faces_large + p_header->m_total_num_faces_small);\r\n//\t\tDbg_Message ( \"Small (%d) verts: %d Large (%d) verts: %d\", Nx::CCollObjTriData::GetVertSmallElemSize(), p_header->m_total_num_verts_small, Nx::CCollObjTriData::GetVertElemSize(), p_header->m_total_num_verts_large);\r\n#endif\t\t// __PLAT_NGC__\r\n\t\tDbg_MsgAssert(p_header->m_version >= 9, (\"Collision version must be at least 9.\"));\r\n\r\n\t\t// reserve space for objects\r\n\t\tm_num_coll_objects = p_header->m_num_objects;\r\n\t\tmp_coll_objects = (Nx::CCollObjTriData *) p_base_addr;\r\n\r\n\t\t// Calculate base addresses for vert and face arrays\r\n\t\tuint8 *p_base_vert_addr = (uint8 *) (mp_coll_objects + m_num_coll_objects);\r\n#ifndef __PLAT_NGC__\r\n\t\tp_base_vert_addr = (uint8 *)(((uint)(p_base_vert_addr+15)) & 0xFFFFFFF0);\t// Align to 128 bit boundary\r\n#ifdef FIXED_POINT_VERTICES\r\n\t\tuint8 *p_base_intensity_addr = p_base_vert_addr + (p_header->m_total_num_verts_large * Nx::CCollObjTriData::GetVertElemSize() +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   p_header->m_total_num_verts_small * Nx::CCollObjTriData::GetVertSmallElemSize());\r\n\t\tuint8 *p_base_face_addr = p_base_intensity_addr + p_header->m_total_num_verts;\r\n\t\tp_base_face_addr = (uint8 *)(((uint)(p_base_face_addr+3)) & 0xFFFFFFFC);\t// Align to 32 bit boundary\r\n#else\r\n\t\tuint8 *p_base_intensity_addr = NULL;\r\n\t\tuint8 *p_base_face_addr = p_base_vert_addr + (p_header->m_total_num_verts * Nx::CCollObjTriData::GetVertElemSize());\r\n\t\tp_base_face_addr = (uint8 *)(((uint)(p_base_face_addr+15)) & 0xFFFFFFF0);\t// Align to 128 bit boundary\r\n#endif // FIXED_POINT_VERTICES\r\n#else\r\n\t\tuint8 *p_base_face_addr = p_base_vert_addr + (p_header->m_total_num_faces * Nx::CCollObjTriData::GetVertElemSize());\r\n\t\tp_base_face_addr = (uint8 *)(((uint)(p_base_face_addr+3)) & 0xFFFFFFFC);\t// Align to 32 bit boundary\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\t\t// Calculate addresses for BSP arrays\r\n#ifndef __PLAT_NGC__\r\n\t\tuint8 *p_node_array_size = p_base_face_addr + (p_header->m_total_num_faces_large * Nx::CCollObjTriData::GetFaceElemSize() +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t   p_header->m_total_num_faces_small * Nx::CCollObjTriData::GetFaceSmallElemSize());\r\n\t\tp_node_array_size += ( p_header->m_total_num_faces_large & 1 ) ? 2 : 0;\r\n#else\r\n\t\tuint8 *p_node_array_size = p_base_face_addr + ( p_header->m_total_num_faces * Nx::CCollObjTriData::GetFaceElemSize() );\r\n\t\tp_node_array_size += ( p_header->m_total_num_faces & 1 ) ? 2 : 0;\r\n#endif\t\t// __PLAT_NGC__\r\n\t\tuint8 *p_base_node_addr = p_node_array_size + 4;\r\n\t\tuint8 *p_base_face_idx_addr = p_base_node_addr + *((int *) p_node_array_size);\r\n\r\n\t\t// Read objects\r\n\t\tfor (int oidx = 0; oidx < p_header->m_num_objects; oidx++)\r\n\t\t{\r\n#ifdef __PLAT_NGC__\r\n\t\t\tCScene * p_scene = static_cast<CScene*>( (static_cast<CNgcMesh*>( this ))->GetScene() );\r\n\t\t\tmp_coll_objects[oidx].InitCollObjTriData(p_scene, p_base_vert_addr, NULL, p_base_face_addr, p_base_node_addr, p_base_face_idx_addr);\r\n#else\r\n\t\t\tmp_coll_objects[oidx].InitCollObjTriData(NULL, p_base_vert_addr, p_base_intensity_addr, p_base_face_addr,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t p_base_node_addr, p_base_face_idx_addr);\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\tmp_coll_objects[oidx].InitBSPTree();\r\n\r\n\t\t\t// Add to mesh bbox\r\n\t\t\tm_collision_bbox.AddPoint(mp_coll_objects[oidx].GetBBox().GetMin());\r\n\t\t\tm_collision_bbox.AddPoint(mp_coll_objects[oidx].GetBBox().GetMax());\r\n\t\t}\r\n\r\n//\t\tDbg_Message(\"Mesh bounding box: min (%f, %f, %f) max (%f, %f, %f)\", \r\n//\t\t\t\t\tm_collision_bbox.GetMin()[X], m_collision_bbox.GetMin()[Y], m_collision_bbox.GetMin()[Z], \r\n//\t\t\t\t\tm_collision_bbox.GetMax()[X], m_collision_bbox.GetMax()[Y], m_collision_bbox.GetMax()[Z]);\r\n\r\n\t} else {\r\n\t\tDbg_Error ( \"Could not open collision file\\n\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n//\tDbg_Message ( \"successfully loaded collision\" );\r\n\r\n\tif (m_num_coll_objects > 0)\r\n\t{\r\n#if 0\r\n\t\t// Add to CSectors\r\n\t\tfor (int i = 0; i < m_num_coll_objects; i++)\r\n\t\t{\r\n\t\t\tCSector *p_sector = GetSector(mp_coll_objects[i].GetChecksum());\r\n\t\t\tif (p_sector)\t// Don't assert now since there may not be renderable data\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(p_sector, (\"LoadCollision: Can't find CSector with checksum %x\", mp_coll_objects[i].GetChecksum()));\r\n\t\t\t\tp_sector->AddCollSector(&(mp_coll_objects[i]));\r\n\t\t\t}\r\n\t\t}\r\n#endif\r\n\t}\r\n\r\n\tMem::PopMemProfile(/*(char*)m_coll_filename*/);\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::CHierarchyObject* CMesh::GetHierarchy()\r\n{\r\n\treturn mp_hierarchyObjects;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CMesh::GetNumObjectsInHierarchy()\r\n{\r\n\treturn m_numHierarchyObjects;\r\n}\r\n\r\n\r\n} // Nx\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxMesh.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       NxMesh.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/15/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_NXMESH_H__\r\n#define\t__GFX_NXMESH_H__\r\n\r\n                           \r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n\r\nnamespace Nx\r\n{\r\n\tclass CTexDict;\r\n\tclass CCollObjTriData;\r\n\tclass CHierarchyObject;\r\n\r\nclass CMesh : public Spt::Class\r\n{\r\n\r\npublic:\r\n    // The basic interface to the model\r\n    // this is the machine independent part\t\r\n    // machine independent range checking, etc can go here\t\r\n\tCMesh();\r\n    virtual\t\t\t\t~CMesh();\r\n\r\n\tbool\t\t\t\tLoadCollision(const char *p_name);\t\t\t// load mesh collision data\r\n\t\r\n\tNx::CHierarchyObject*\t\tGetHierarchy();\r\n\tint\t\t\t\t\t\t\tGetNumObjectsInHierarchy();\r\n\tNx::CCollObjTriData*\t\tGetCollisionTriDataArray() const { return mp_coll_objects; }\r\n\tint\t\t\t\t\t\t\tGetCollisionTriDataArraySize() const { return m_num_coll_objects; }\r\n\tconst Mth::CBBox &\t\t\tGetCollisionBBox() const { return m_collision_bbox; }\r\n\r\npublic:\r\n\tNx::CTexDict*\t\tGetTextureDictionary()\r\n\t{\r\n\t\treturn mp_texDict;\r\n\t}\r\n\tuint32\t\t\t\tGetRemovalMask()\r\n\t{\r\n\t\treturn m_CASRemovalMask;\r\n\t}\r\n\r\nprotected:\r\n\tNx::CTexDict*\t\tmp_texDict;\r\n\r\n\tchar\t\t\t\t\t\tm_coll_filename[128];\t\t\t\t\t\t// collision filename (kept around for unload)\r\n\tint\t\t\t\t\t\t\tm_num_coll_objects;\t\t\t\t\t\t\t// non-cloned collision\r\n\tNx::CCollObjTriData *\t\tmp_coll_objects;\r\n\tMth::CBBox\t\t\t\t\tm_collision_bbox;\t\t\t\t\t\t\t// Bounding box of whole mesh\r\n\r\n\tuint32\t\t\t\t\t\tm_CASRemovalMask;\r\n\r\n\t// For mesh heirarchies\r\n\tCHierarchyObject*\t\t\tmp_hierarchyObjects;\t\t\t\t\t\t// array of hierarchy objects\r\n\tint\t\t\t\t\t\t\tm_numHierarchyObjects;\t\t\t\t\t\t// number of hierarchy objects\r\n};\r\n\r\n}\r\n\r\n#endif // __GFX_NXMESH_H__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxMiscFX.cpp",
    "content": "#include <core/defines.h>\r\n\r\n#include <gel/collision/collision.h>\r\n#include <gel/collision/colltridata.h>\r\n#include <gel/collision/movcollman.h>\r\n#include <gel/collision/batchtricoll.h>\r\n#include <sys/timer.h>\r\n#include <sk/modules/frontend/frontend.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/NxViewMan.h>\r\n#include <gfx/debuggfx.h>\r\n#include <sys/replay/replay.h>\r\n\r\n#include \"NxMiscFX.h\"\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\nLst::HashTable< sScreenFlashDetails >\t\t*p_screen_flash_details_table\t= NULL;\r\nLst::HashTable< sSplatInstanceDetails >\t\t*p_splat_details_table\t\t\t= NULL;\r\nLst::HashTable< sSplatTrailInstanceDetails >*p_splat_trail_details_table\t= NULL;\r\nLst::HashTable< sShatterInstanceDetails >\t*p_shatter_details_table\t\t= NULL;\r\n\r\nstatic const float\tDEFAULT_AREA_TEST\t\t\t= 288.0f;\r\nstatic const float\tDEFAULT_VELOCITY_VARIANCE\t= 0.0f;\r\nstatic const float\tDEFAULT_SPREAD_FACTOR\t\t= 1.0f;\r\nstatic const float\tDEFAULT_LIFETIME\t\t\t= 4.0f;\r\nstatic const float\tDEFAULT_BOUNCE\t\t\t\t= -10000.0f;\r\nstatic const float\tDEFAULT_BOUNCE_AMPLITUDE\t= 0.8f;\r\n\r\nMth::Vector\t\t\tshatterVelocity;\r\nfloat\t\t\t\tshatterAreaTest\t\t\t= DEFAULT_AREA_TEST * DEFAULT_AREA_TEST;\r\nfloat\t\t\t\tshatterVelocityVariance\t= DEFAULT_VELOCITY_VARIANCE;\r\nfloat\t\t\t\tshatterSpreadFactor\t\t= DEFAULT_SPREAD_FACTOR;\r\nfloat\t\t\t\tshatterLifetime\t\t\t= DEFAULT_LIFETIME;\r\nfloat\t\t\t\tshatterBounce\t\t\t= DEFAULT_BOUNCE;\r\nfloat\t\t\t\tshatterBounceAmplitude\t= DEFAULT_BOUNCE_AMPLITUDE;\r\nsTriSubdivideStack\ttriSubdivideStack;\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint sSplatInstanceDetails::GetOldestSplat( void )\r\n{\r\n\tint oldest\t\t= m_lifetimes[0];\r\n\tint oldest_idx\t= 0;\r\n\t\r\n\tfor( uint32 idx = 0; idx < SPLAT_POLYS_PER_MESH; ++idx )\r\n\t{\r\n\t\tif( m_lifetimes[idx] == 0 )\r\n\t\t{\r\n\t\t\treturn idx;\r\n\t\t}\r\n\t\telse if( m_lifetimes[idx] < oldest )\r\n\t\t{\r\n\t\t\toldest\t\t= m_lifetimes[idx];\r\n\t\t\toldest_idx\t= idx;\r\n\t\t}\r\n\t}\r\n\r\n\t// If we get here there wasn't a 'dead' splat, so return the oldest.\r\n\treturn oldest_idx;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sTriSubdivideStack::Reset( void )\r\n{\r\n\tm_offset\t\t= 0;\r\n\tm_block_size\t= 0;\r\n\r\n\tmemset( m_data, 0x03, TRI_SUBDIVIDE_STACK_SIZE );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sTriSubdivideStack::Clear( void )\r\n{\r\n\tm_offset\t\t= 0;\r\n\tm_block_size\t= 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sTriSubdivideStack::Push( void *p_data )\r\n{\r\n\tDbg_Assert( m_offset + m_block_size < TRI_SUBDIVIDE_STACK_SIZE );\r\n\t\r\n\tmemcpy( m_data + m_offset, p_data, m_block_size );\r\n\tm_offset += m_block_size;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sTriSubdivideStack::Pop( void* p_data )\r\n{\r\n\tDbg_Assert( m_offset >= m_block_size );\r\n\t\r\n\tm_offset -= m_block_size;\r\n\tmemcpy( p_data, m_data + m_offset, m_block_size );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst void * sTriSubdivideStack::Peek( uint index )\r\n{\r\n\tint offset = index * m_block_size;\r\n\tDbg_MsgAssert( offset < m_offset, (\"Index %d is beyond end offset %d\", index, m_offset) );\r\n\t\r\n\treturn m_data + offset;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsShatterInstanceDetails::sShatterInstanceDetails( int num_tris )\r\n{\r\n\t//Dbg_Message(\"Allocating %d bytes for position arrays of %d tris\", (sizeof(Mth::Vector) * 2 + sizeof(Mth::Matrix)) * num_tris, num_tris);\r\n\r\n\tmp_positions\t\t= new Mth::Vector[num_tris];\r\n\tmp_velocities\t\t= new Mth::Vector[num_tris];\r\n\tmp_matrices\t\t\t= new Mth::Matrix[num_tris];\r\n\tm_num_triangles\t\t= num_tris;\r\n\r\n\tm_gravity\t\t\t= 128.0f;\r\n\tm_lifetime\t\t\t= shatterLifetime;\r\n\tm_bounce_level\t\t= shatterBounce;\r\n\tm_bounce_amplitude\t= shatterBounceAmplitude;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsShatterInstanceDetails::~sShatterInstanceDetails( void )\r\n{\r\n\tdelete [] mp_positions;\r\n\tdelete [] mp_velocities;\r\n\tdelete [] mp_matrices;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sShatterInstanceDetails::UpdateParameters( int index, float timestep )\r\n{\r\n\tDbg_Assert( index < m_num_triangles );\r\n\t\r\n\tmp_positions[index]\t+= mp_velocities[index] * timestep;\r\n\r\n\tif(( mp_positions[index][Y] < m_bounce_level ) && ( mp_velocities[index][Y] < 0.0f ))\r\n\t{\r\n\t\t// Hit the floor. Bounce back up.\r\n\t\tmp_positions[index][Y]\t= m_bounce_level + ( m_bounce_level - mp_positions[index][Y] );\r\n\t\tmp_velocities[index][Y]\t= mp_velocities[index][Y] * -m_bounce_amplitude;\r\n\r\n\t\t// And figure a new rotation matrix.\r\n\t\tMth::Vector axis( -1.0f + ( 2.0f * (float)rand() / RAND_MAX ), -1.0f + ( 2.0f * (float)rand() / RAND_MAX ), -1.0f + ( 2.0f * (float)rand() / RAND_MAX ));\r\n\t\taxis.Normalize();\r\n\t\tmp_matrices[index].Ident();\r\n\t\tmp_matrices[index].Rotate( axis, 0.1f * ((float)rand() / RAND_MAX ));\r\n\t}\r\n\r\n\tmp_velocities[index][Y]\t-= m_gravity * timestep;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint\tsShatterInstanceDetails::s_query_memory_needed(int num_tris)\r\n{\r\n\tint size = sizeof(sShatterInstanceDetails);\r\n\tsize += (2 * sizeof(Mth::Vector) + sizeof(Mth::Matrix)) * num_tris;\r\n\r\n\treturn size;\r\n}\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid MiscFXInitialize( void )\r\n{\r\n\tif( p_screen_flash_details_table == NULL )\r\n\t{\r\n\t\tp_screen_flash_details_table = new Lst::HashTable< sScreenFlashDetails >( 4 );\r\n\t}\r\n\r\n\tif( p_splat_details_table == NULL )\r\n\t{\r\n\t\tp_splat_details_table = new Lst::HashTable< sSplatInstanceDetails >( 4 );\r\n\t}\r\n\r\n\tif( p_splat_trail_details_table == NULL )\r\n\t{\r\n\t\tp_splat_trail_details_table = new Lst::HashTable< sSplatTrailInstanceDetails >( 4 );\r\n\t}\r\n\t\r\n\tif( p_shatter_details_table == NULL )\r\n\t{\r\n\t\tp_shatter_details_table = new Lst::HashTable< sShatterInstanceDetails >( 4 );\r\n\t}\r\n\t\r\n\tplat_texture_splat_initialize();\r\n\tplat_shatter_initialize();\r\n\r\n\ttriSubdivideStack.Reset();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid MiscFXCleanup( void )\r\n{\r\n\t// Can cleanup the screen flash details here, since they are not platform specific.\r\n\tp_screen_flash_details_table->IterateStart();\r\n\tsScreenFlashDetails *p_details = p_screen_flash_details_table->IterateNext();\r\n\twhile( p_details )\r\n\t{\r\n\t\tsScreenFlashDetails *p_delete\t= p_details;\r\n\t\tp_details\t\t\t\t\t\t= p_screen_flash_details_table->IterateNext();\r\n\r\n\t\tp_screen_flash_details_table->FlushItem((uint32)p_delete );\r\n\t\tdelete p_delete;\r\n\t}\r\n\t\r\n\t// Ditto for the tetxure splat trail details.\r\n\tKillAllTextureSplats();\r\n\r\n\t// Clean up the shatter details.\r\n\tplat_shatter_cleanup();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid KillAllTextureSplats( void )\r\n{\r\n\t// This was split into a separate function because it can also be used after turning geometry off,\r\n\t// to ensure no splats are 'floating'.\r\n\tp_splat_trail_details_table->IterateStart();\r\n\tsSplatTrailInstanceDetails *p_trail_details = p_splat_trail_details_table->IterateNext();\r\n\twhile( p_trail_details )\r\n\t{\r\n\t\tsSplatTrailInstanceDetails *p_delete\t= p_trail_details;\r\n\t\tp_trail_details\t\t\t\t\t\t\t= p_splat_trail_details_table->IterateNext();\r\n\r\n\t\tp_splat_trail_details_table->FlushItem((uint32)p_delete );\r\n\t\tdelete p_delete;\r\n\t}\r\n\t\r\n\t// Call the platform specific cleanup function.\r\n\tplat_texture_splat_cleanup();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid AddScreenFlash( int viewport, Image::RGBA from, Image::RGBA to, float duration, float z, uint32 flags, const char *p_texture_name )\r\n{\r\n\tReplay::WriteScreenFlash(viewport, from, to, duration, z, flags);\r\n\t\r\n\t// Ensure the supplied viewport is within bounds.\r\n#ifdef __NOPT_ASSERT__\r\n\tint num_viewports = CViewportManager::sGetNumActiveViewports();\r\n\tDbg_Assert( viewport < num_viewports );\r\n#endif\t\t// __NOPT_ASSERT__\r\n\r\n\t// Resolve the texture name if present.\r\n\tCTexture *p_texture = NULL;\r\n\tif( p_texture_name )\r\n\t{\r\n\t}\r\n\r\n\t// Store these details.\r\n\tsScreenFlashDetails *p_flash = new sScreenFlashDetails;\r\n\tp_flash->m_from\t\t= from;\r\n\tp_flash->m_to\t\t= to;\r\n\tp_flash->m_duration\t= duration;\r\n\tp_flash->m_lifetime\t= duration;\r\n\tp_flash->m_z\t\t= z;\r\n\tp_flash->m_flags\t= flags;\r\n\tp_flash->mp_texture\t= p_texture;\r\n\tp_flash->m_viewport\t= viewport;\r\n\r\n\tp_screen_flash_details_table->PutItem((uint32)p_flash, p_flash );\r\n\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid ScreenFlashUpdate( void )\r\n{\r\n\tfloat framelength = Tmr::FrameLength();\r\n\r\n\tif( p_screen_flash_details_table )\r\n\t{\r\n\t\tp_screen_flash_details_table->IterateStart();\r\n\t\tsScreenFlashDetails *p_details = p_screen_flash_details_table->IterateNext();\r\n\t\twhile( p_details )\r\n\t\t{\r\n\t\t\tsScreenFlashDetails *p_delete = NULL;\r\n\r\n\t\t\t// Don't process if paused.\r\n\t\t\tif( !Mdl::FrontEnd::Instance()->GamePaused() || ( p_details->m_flags & Nx::SCREEN_FLASH_FLAG_IGNORE_PAUSE ))\r\n\t\t\t{\r\n\t\t\t\tp_details->m_lifetime -= framelength;\r\n\t\t\t\tif( p_details->m_lifetime > 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Calculate the current color.\r\n\t\t\t\t\tfloat mult\t\t\t\t= p_details->m_lifetime / p_details->m_duration;\r\n\t\t\t\t\tp_details->m_current.r\t= p_details->m_to.r + (int)(((float)p_details->m_from.r - (float)p_details->m_to.r ) * mult );\r\n\t\t\t\t\tp_details->m_current.g\t= p_details->m_to.g + (int)(((float)p_details->m_from.g - (float)p_details->m_to.g ) * mult );\r\n\t\t\t\t\tp_details->m_current.b\t= p_details->m_to.b + (int)(((float)p_details->m_from.b - (float)p_details->m_to.b ) * mult );\r\n\t\t\t\t\tp_details->m_current.a\t= p_details->m_to.a + (int)(((float)p_details->m_from.a - (float)p_details->m_to.a ) * mult );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_delete = p_details;\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\r\n\t\t\tp_details = p_screen_flash_details_table->IterateNext();\r\n\r\n\t\t\tif( p_delete )\r\n\t\t\t{\r\n\t\t\t\tp_screen_flash_details_table->FlushItem((uint32)p_delete );\r\n\t\t\t\tdelete p_delete;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid ScreenFlashRender( int viewport, uint32 flags )\r\n{\r\n\tp_screen_flash_details_table->IterateStart();\r\n\tsScreenFlashDetails *p_details = p_screen_flash_details_table->IterateNext();\r\n\twhile( p_details )\r\n\t{\r\n\t\tif( viewport == p_details->m_viewport )\r\n\t\t{\r\n\t\t\tif(( flags & Nx::SCREEN_FLASH_FLAG_BEHIND_PANEL ) == ( p_details->m_flags & Nx::SCREEN_FLASH_FLAG_BEHIND_PANEL ))\r\n\t\t\t{\r\n\t\t\t\tplat_screen_flash_render( p_details );\r\n\t\t\t}\r\n\t\t}\r\n\t\tp_details = p_screen_flash_details_table->IterateNext();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid TextureSplatUpdate( void )\r\n{\r\n\t// Don't process if paused.\r\n\tif( Mdl::FrontEnd::Instance()->GamePaused() && !Replay::RunningReplay())\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\r\n\tif( p_splat_details_table )\r\n\t{\r\n\t\tint framelength_in_ms = (int)( Tmr::FrameLength() * 1000.0f );\r\n\t\t\r\n\t\tp_splat_details_table->IterateStart();\r\n\t\tsSplatInstanceDetails *p_details = p_splat_details_table->IterateNext();\r\n\t\twhile( p_details )\r\n\t\t{\r\n\t\t\t// Initialize to -1 to indicate no active splats so far.\r\n\t\t\tp_details->m_highest_active_splat = -1;\r\n\t\t\t\r\n\t\t\tfor( int i = 0; i < SPLAT_POLYS_PER_MESH; ++i )\r\n\t\t\t{\r\n\t\t\t\tif( p_details->m_lifetimes[i] > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_details->m_lifetimes[i] -= framelength_in_ms;\r\n\t\t\t\t\tif( p_details->m_lifetimes[i] <= 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Make sure to set lifetime back to exactly zero to indicate ready for re-use.\r\n\t\t\t\t\t\tp_details->m_lifetimes[i] = 0;\r\n\r\n\t\t\t\t\t\t// This splat has just 'expired'. Reset this poly.\r\n\t\t\t\t\t\tplat_texture_splat_reset_poly( p_details, i );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_details->m_highest_active_splat = i;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tp_details = p_splat_details_table->IterateNext();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool TextureSplat( Mth::Vector& splat_start, Mth::Vector& splat_end, float size, float lifetime, const char *p_texture_name, uint32 trail )\r\n{\r\n\tReplay::WriteTextureSplat(splat_start,splat_end,size,lifetime,p_texture_name,trail);\r\n\t\r\n\t// If this is a flagged as a trail splat, see if we have a trail instance already that matches.\r\n\tsSplatTrailInstanceDetails *p_trail_details = NULL;\r\n\tif( trail > 0 )\r\n\t{\r\n\t\tuint32 time = Tmr::GetTime();\r\n\r\n\t\tp_splat_trail_details_table->IterateStart();\r\n\t\tp_trail_details = p_splat_trail_details_table->IterateNext();\r\n\t\twhile( p_trail_details )\r\n\t\t{\r\n\t\t\tsSplatTrailInstanceDetails *p_delete = NULL;\r\n\r\n\t\t\tif(( time < p_trail_details->m_last_pos_added_time ) || (( time - p_trail_details->m_last_pos_added_time ) > 500 ))\r\n\t\t\t{\r\n\t\t\t\t// This trail is over half a second old - remove it.\r\n\t\t\t\tp_delete = p_trail_details;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// This trail had a point added within the last half second, so check it for bone ID.\r\n\t\t\t\tif( p_trail_details->m_trail_id == trail )\r\n\t\t\t\t{\r\n\t\t\t\t\t// ID's match, so check it for proximity. Seems like fast moving reverts can cause successive calls to be up to 5.5 feet away.\r\n\t\t\t\t\tfloat sq_dist = ( splat_start - p_trail_details->m_last_pos ).LengthSqr();\r\n\t\t\t\t\tif( sq_dist < ( 66.0f * 66.0f ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// This trail had a point added within the last half second that is within 3 feet of this point. Select this trail.\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tp_trail_details = p_splat_trail_details_table->IterateNext();\r\n\r\n\t\t\tif( p_delete )\r\n\t\t\t{\r\n\t\t\t\tp_splat_trail_details_table->FlushItem((uint32)p_delete );\r\n\t\t\t\tdelete p_delete;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If there were no trail details, create a new instance and just return.\r\n\t\tif( p_trail_details == NULL )\r\n\t\t{\r\n\t\t\tp_trail_details = new sSplatTrailInstanceDetails;\r\n\t\t\tp_trail_details->m_trail_id\t\t\t\t= trail;\r\n\t\t\tp_trail_details->m_last_pos\t\t\t\t= splat_start;\r\n\t\t\tp_trail_details->m_last_pos_added_time\t= time;\r\n\t\t\tp_splat_trail_details_table->PutItem((uint32)p_trail_details, p_trail_details );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Convert the name string to a checksum.\r\n\tuint32 texture_checksum = Crc::GenerateCRCFromString( p_texture_name );\r\n\t\r\n\t// Obtain a pointer to the texture.\r\n\tNx::CTexture *p_texture\t= Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tDbg_MsgAssert( p_texture, (\"Couldn't find texture %s in particle texture dictionary\", p_texture_name) );\r\n\r\n\tMth::Line is( splat_start, splat_end );\r\n\r\n\t// Make initial line bounding box.\r\n\tMth::CBBox line_bbox( is.m_start );\r\n\tline_bbox.AddPoint( is.m_end );\r\n\t\r\n\t// Get a list of all collision sectors within all super sectors that the line intersects.\r\n\t// This is a very fast call, but likely to provide many collision sectors that are not actually within the\r\n\t// bounding box of the line.\r\n\tSSec::Manager\t*ss_man\t\t\t\t= Nx::CEngine::sGetNearestSuperSectorManager( is );\r\n\tNx::CCollStatic\t**pp_coll_obj_list\t= ss_man->GetIntersectingCollSectors( is );\r\n\r\n\t// Can't create blood splat if no objects found.\r\n\tif( !pp_coll_obj_list )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// The sector table is used to pass a platform independent set of CSector pointers to the below p-line code.\r\n\t// Garrett: Also added static collision table, just in case CSector points to a CCollMulti\r\n\t#define SECTOR_TABLE_SIZE\t\t127\r\n\tstatic CSector* sector_table[SECTOR_TABLE_SIZE + 1];\r\n\tstatic Nx::CCollStatic* collision_table[SECTOR_TABLE_SIZE + 1];\r\n\r\n\tint\t\t\t\tsector_table_index = 0;\r\n\tNx::CCollStatic *p_coll_obj;\r\n\twhile(( p_coll_obj = *pp_coll_obj_list ))\r\n\t{\r\n\t\tif( p_coll_obj->GetGeometry())\r\n\t\t{\r\n\t\t\t// Determine whether this collision sector actually falls within the bounding box of our line.\r\n\t\t\tif( p_coll_obj->GetGeometry()->GetBBox().Intersect( line_bbox ))\r\n\t\t\t{\r\n\t\t\t\tuint32 checksum = p_coll_obj->GetChecksum();\r\n\r\n\t\t\t\t// From the checksum we can get the CSector (the renderable version) from the hash table of the scene.\r\n\t\t\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector( checksum );\r\n\r\n\t\t\t\t// Store the pointer in the table.\r\n\t\t\t\tDbg_Assert( sector_table_index < SECTOR_TABLE_SIZE );\r\n\t\t\t\tcollision_table[sector_table_index] = p_coll_obj;\r\n\t\t\t\tsector_table[sector_table_index++] = p_sector;\r\n\t\t\t}\r\n\t\t\t++pp_coll_obj_list;\r\n\t\t}\r\n\t}\r\n\r\n\t// Mark the end of the sector table with a NULL pointer.\r\n\tif( sector_table_index > 0 )\r\n\t{\r\n\t\tsector_table[sector_table_index] = NULL;\r\n\t\tcollision_table[sector_table_index] = NULL;\r\n\r\n\t\t// Make sure we can can calculate an up vector.  If not, just move on.\r\n\t\tbool rv;\r\n\t\tif ((trail == 0) || (splat_start[X] != p_trail_details->m_last_pos[X]) || (splat_start[Z] != p_trail_details->m_last_pos[Z]))\r\n\t\t{\r\n\t\t\trv = plat_texture_splat( sector_table, collision_table, splat_start, splat_end, size, lifetime, p_texture, p_trail_details );\r\n\t\t} else {\r\n\t\t\trv = false;\r\n\t\t}\r\n\r\n\t\t// Update the trail details if present.\r\n\t\tif( p_trail_details )\r\n\t\t{\r\n\t\t\tp_trail_details->m_last_pos\t= splat_start;\r\n\t\t\tp_trail_details->m_last_pos_added_time\t= Tmr::GetTime();\r\n\t\t}\r\n\r\n\t\treturn rv;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid TextureSplatRender( void )\r\n{\r\n\r\n\t\r\n\tplat_texture_splat_render();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid ShatterSetParams( Mth::Vector& velocity, float area_test, float velocity_variance, float spread_factor, float lifetime, float bounce, float bounce_amplitude )\r\n{\r\n\tReplay::WriteShatterParams(velocity, area_test, velocity_variance, spread_factor, lifetime, bounce, bounce_amplitude);\r\n\r\n\tshatterVelocity\t\t\t= velocity;\r\n\tshatterAreaTest\t\t\t= ( area_test == 0.0f ) ? ( DEFAULT_AREA_TEST * DEFAULT_AREA_TEST ) : ( area_test * area_test );\r\n\tshatterVelocityVariance\t= ( velocity_variance == 0.0f ) ? DEFAULT_VELOCITY_VARIANCE : velocity_variance;\r\n\tshatterSpreadFactor\t\t= ( spread_factor == 0.0f ) ? DEFAULT_SPREAD_FACTOR : spread_factor;\r\n\tshatterLifetime\t\t\t= ( lifetime == 0.0f ) ? DEFAULT_LIFETIME : lifetime;\r\n\tshatterBounce\t\t\t= ( bounce == 0.0f ) ? DEFAULT_BOUNCE : bounce;\r\n\tshatterBounceAmplitude\t= ( bounce_amplitude == 0.0f ) ? DEFAULT_BOUNCE_AMPLITUDE : bounce_amplitude;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Shatter( CGeom *p_geom )\r\n{\r\n\tplat_shatter( p_geom );\r\n\r\n\t// After shattering the subdivision stack should be empty.\r\n\tDbg_Assert( triSubdivideStack.IsEmpty());\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid ShatterUpdate( void )\r\n{\r\n\t// Don't process if paused.\r\n\tif( Mdl::FrontEnd::Instance()->GamePaused() && !Replay::RunningReplay())\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tif (Replay::Paused())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tif( p_shatter_details_table )\r\n\t{\r\n\t\tfloat framelength = Tmr::FrameLength();\r\n\t\t\r\n\t\tp_shatter_details_table->IterateStart();\r\n\t\tsShatterInstanceDetails *p_details = p_shatter_details_table->IterateNext();\r\n\t\twhile( p_details )\r\n\t\t{\r\n\t\t\tsShatterInstanceDetails *p_delete = NULL;\r\n\t\t\t\r\n\t\t\tp_details->m_lifetime -= framelength;\r\n\t\t\tif( p_details->m_lifetime <= 0.0f )\r\n\t\t\t{\r\n\t\t\t\t// Remove this entry from the table and destroy at the bottom of the loop.\r\n\t\t\t\tp_delete = p_details;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tplat_shatter_update( p_details, framelength );\r\n\t\t\t}\r\n\t\t\tp_details = p_shatter_details_table->IterateNext();\r\n\r\n\t\t\tif( p_delete )\r\n\t\t\t{\r\n\t\t\t\tp_shatter_details_table->FlushItem((uint32)p_delete );\r\n\t\t\t\tdelete p_delete;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid ShatterRender( void )\r\n{\r\n\tif( p_shatter_details_table )\r\n\t{\r\n\t\tp_shatter_details_table->IterateStart();\r\n\t\tsShatterInstanceDetails *p_details = p_shatter_details_table->IterateNext();\r\n\t\twhile( p_details )\r\n\t\t{\r\n\t\t\tplat_shatter_render( p_details );\r\n\t\t\tp_details = p_shatter_details_table->IterateNext();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n///////////////////////////////////////////////////////////////////\r\n//\r\n// FOG\r\n//\r\n///////////////////////////////////////////////////////////////////\r\n\r\nbool\t\tCFog::s_enabled = false;\r\nfloat\t\tCFog::s_near_distance = 3000.0f;\r\nfloat\t\tCFog::s_exponent = 10.0f;\r\nImage::RGBA\tCFog::s_rgba(0x60, 0x60, 0x80, 0x66);\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCFog::sEnableFog(bool enable)\r\n{\r\n\ts_enabled = enable;\r\n\ts_plat_enable_fog(enable);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCFog::sSetFogNearDistance(float distance)\r\n{\r\n\ts_near_distance = distance;\r\n\ts_plat_set_fog_near_distance(distance);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCFog::sSetFogExponent(float exponent)\r\n{\r\n\ts_exponent = exponent;\r\n\ts_plat_set_fog_exponent(exponent);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCFog::sSetFogRGBA(Image::RGBA rgba)\r\n{\r\n\ts_rgba = rgba;\r\n\ts_plat_set_fog_rgba(rgba);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCFog::sSetFogColor( void )\r\n{\r\n\ts_plat_set_fog_color();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCFog::sFogUpdate( void )\r\n{\r\n\ts_plat_fog_update();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCFog::sIsFogEnabled()\r\n{\r\n\treturn s_enabled;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\tCFog::sGetFogNearDistance()\r\n{\r\n\treturn s_near_distance;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\tCFog::sGetFogExponent()\r\n{\r\n\treturn s_exponent;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\tCFog::sGetFogRGBA()\r\n{\r\n\treturn s_rgba;\r\n}\r\n\r\n} // Nx\r\n"
  },
  {
    "path": "Code/Gfx/NxMiscFX.h",
    "content": "#ifndef\t__GFX_NXMISCFX_H__\r\n#define\t__GFX_NXMISCFX_H__\r\n\r\n#include <gfx/nx.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nenum eScreenFlashFlags\r\n{\r\n\tSCREEN_FLASH_FLAG_BEHIND_PANEL\t= 0x01,\r\n\tSCREEN_FLASH_FLAG_ADDITIVE\t\t= 0x02,\r\n\tSCREEN_FLASH_FLAG_SUBTRACTIVE\t= 0x04,\r\n\tSCREEN_FLASH_FLAG_IGNORE_PAUSE\t= 0x08\r\n};\r\n\t\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sScreenFlashDetails\r\n{\r\n\tint\t\t\tm_viewport;\r\n\tImage::RGBA\tm_from;\r\n\tImage::RGBA\tm_to;\r\n\tImage::RGBA\tm_current;\r\n\tuint32\t\tm_flags;\r\n\tfloat\t\tm_duration;\r\n\tfloat\t\tm_lifetime;\r\n\tfloat\t\tm_z;\r\n\tCTexture*\tmp_texture;\r\n};\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CFog\r\n{\r\npublic:\r\n\tstatic void\t\t\tsEnableFog(bool enable);\r\n\tstatic void\t\t\tsSetFogExponent(float exponent);\r\n\tstatic void\t\t\tsSetFogNearDistance(float distance);\r\n\tstatic void\t\t\tsSetFogRGBA(Image::RGBA rgba);\r\n\tstatic void\t\t\tsSetFogColor( void );\r\n\tstatic void\t\t\tsFogUpdate( void );\r\n\r\n\tstatic bool\t\t\tsIsFogEnabled();\r\n\tstatic float\t\tsGetFogNearDistance();\r\n\tstatic float\t\tsGetFogExponent();\r\n\tstatic Image::RGBA\tsGetFogRGBA();\r\n\r\nprivate:\r\n\tstatic void\t\t\ts_plat_enable_fog(bool enable);\r\n\tstatic void\t\t\ts_plat_set_fog_near_distance(float distance);\r\n\tstatic void\t\t\ts_plat_set_fog_exponent(float exponent);\r\n\tstatic void\t\t\ts_plat_set_fog_rgba(Image::RGBA rgba);\r\n\tstatic void\t\t\ts_plat_set_fog_color( void );\r\n\tstatic void\t\t\ts_plat_fog_update( void );\r\n\r\n\t// Keep the numbers here, just in case they need to be mangled below the p-line\r\n\tstatic bool\t\t\ts_enabled;\r\n\tstatic float\t\ts_near_distance;\r\n\tstatic float\t\ts_exponent;\r\n\tstatic Image::RGBA\ts_rgba;\r\n};\r\n\r\n\r\n#define SPLAT_POLYS_PER_MESH\t256\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Platform independent structure for holding details on a set    */\r\n/* of texture splats. The platform-specific code will most likely */\r\n/* derive a structure from this to maintain additional details.   */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sSplatInstanceDetails\r\n{\r\n\tint\t\t\t\t\tm_lifetimes[SPLAT_POLYS_PER_MESH];\r\n\tint\t\t\t\t\tm_highest_active_splat;\t\t\t\t// Can be used to dynamically optimise rendering lists.\r\n\tint\t\t\t\t\tGetOldestSplat( void );\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Platform independent structure for holding details on a single */\r\n/* trail texture splats.\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sSplatTrailInstanceDetails\r\n{\r\n\tMth::Vector\t\t\tm_last_pos;\r\n\tuint32\t\t\t\tm_trail_id;\t\t\t\t// Keyed from the bone checksum.\r\n\tuint32\t\t\t\tm_last_pos_added_time;\t// In milliseconds.\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sShatterInstanceDetails\r\n{\r\n\t\t\t\t\t\tsShatterInstanceDetails( int num_tris );\r\n\tvirtual\t\t\t\t~sShatterInstanceDetails( void );\r\n\tvoid\t\t\t\tUpdateParameters( int index, float timestep );\r\n\t\r\n\tMth::Vector*\t\tmp_positions;\r\n\tMth::Vector*\t\tmp_velocities;\r\n\tMth::Vector*\t\tmp_normals;    // For 'fake' lighting.\r\n\tMth::Matrix*\t\tmp_matrices;\r\n\tfloat\t\t\t\tm_lifetime;\t\r\n\tfloat\t\t\t\tm_gravity;\t\r\n\tfloat\t\t\t\tm_bounce_level;\r\n\tfloat\t\t\t\tm_bounce_amplitude;\r\n\tint\t\t\t\t\tm_num_triangles;\r\n\r\nprotected:\r\n\tstatic int\t\t\ts_query_memory_needed(int num_tris);\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sTriSubdivideStack\r\n{\r\n\tstatic const int\tTRI_SUBDIVIDE_STACK_SIZE\t= 16 * 1024;\r\n\r\n\tvoid\t\t\t\tReset( void );\r\n\tvoid\t\t\t\tClear( void );\r\n\tbool\t\t\t\tIsEmpty( void )\t\t\t\t{ return m_offset == 0; }\r\n\tvoid\t\t\t\tSetBlockSize( int size )\t{ m_block_size = size; }\r\n\tint\t\t\t\t\tGetBlockSize( void )\t\t{ return m_block_size; }\r\n\tvoid\t\t\t\tPop( void *p_data );\r\n\tvoid\t\t\t\tPush( void *p_data );\r\n\tconst void *\t\tPeek( uint index );\r\n\r\n\tprivate:\t\r\n\tint\t\t\t\t\tm_offset;\r\n\tint\t\t\t\t\tm_block_size;\r\n\tchar\t\t\t\tm_data[TRI_SUBDIVIDE_STACK_SIZE];\r\n};\r\n\r\n\r\n\r\nextern Lst::HashTable< sSplatInstanceDetails >\t\t\t*p_splat_details_table;\r\nextern Lst::HashTable< sSplatTrailInstanceDetails >\t\t*p_splat_trail_details_table;\r\nextern Lst::HashTable< sShatterInstanceDetails >\t\t*p_shatter_details_table;\r\nextern Mth::Vector\t\t\t\t\t\t\t\t\t\tshatterVelocity;\r\nextern float\t\t\t\t\t\t\t\t\t\t\tshatterAreaTest;\r\nextern float\t\t\t\t\t\t\t\t\t\t\tshatterVelocityVariance;\r\nextern float\t\t\t\t\t\t\t\t\t\t\tshatterSpreadFactor;\r\nextern float\t\t\t\t\t\t\t\t\t\t\tshatterLifetime;\r\nextern float\t\t\t\t\t\t\t\t\t\t\tshatterBounce;\r\n\r\nextern sTriSubdivideStack\t\t\t\t\t\t\t\ttriSubdivideStack;\r\n\r\nvoid MiscFXInitialize( void );\r\nvoid MiscFXCleanup( void );\r\n\r\nvoid AddScreenFlash( int viewport, Image::RGBA from, Image::RGBA to, float duration, float z, uint32 flags, const char *p_texture_name );\r\nvoid ScreenFlashUpdate( void );\r\nvoid ScreenFlashRender( int viewport, uint32 flags );\r\n\r\nvoid TextureSplatRender( void );\r\nvoid TextureSplatUpdate( void );\r\nbool TextureSplat( Mth::Vector& splat_start, Mth::Vector& splat_end, float size, float lifetime, const char *p_texture_name, uint32 trail = 0 );\r\nvoid KillAllTextureSplats( void );\r\n\r\nvoid ShatterSetParams( Mth::Vector& velocity, float area_test, float velocity_variance, float spread_factor, float lifetime, float bounce, float bounce_amplitude );\r\nvoid Shatter( CGeom *p_geom );\r\nvoid ShatterUpdate( void );\r\nvoid ShatterRender( void );\r\n\r\nvoid plat_screen_flash_render( sScreenFlashDetails *p_details );\r\n\r\nvoid plat_texture_splat_initialize( void );\r\nvoid plat_texture_splat_cleanup( void );\r\nvoid plat_texture_splat_render( void );\r\nvoid plat_texture_splat_reset_poly( sSplatInstanceDetails *p_details, int index );\r\nbool plat_texture_splat( Nx::CSector **pp_sectors, Nx::CCollStatic **pp_collision, Mth::Vector& start, Mth::Vector& end, float size, float lifetime, Nx::CTexture *p_texture, Nx::sSplatTrailInstanceDetails *p_trail_details = NULL );\r\n\r\nvoid plat_shatter_initialize( void );\r\nvoid plat_shatter_cleanup( void );\r\nvoid plat_shatter( CGeom *p_geom );\r\nvoid plat_shatter_update( sShatterInstanceDetails *p_details, float framelength );\r\nvoid plat_shatter_render( sShatterInstanceDetails *p_details );\r\n\r\n} // Nx\r\n\r\n#endif // __GFX_NXMISCFX_H__\r\n"
  },
  {
    "path": "Code/Gfx/NxModel.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       NxModel.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/21/2001\r\n//****************************************************************************\r\n\r\n#include <gfx/nxmodel.h>\r\n\r\n#include <core/string/stringutils.h>\r\n\r\n#include <gel/assman/assman.h>\r\n#include <gel/assman/skinasset.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/debuggfx.h>\r\n#include <gfx/facetexture.h>\r\n#include <gfx/gfxutils.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxgeom.h>\r\n#include <gfx/nxmesh.h>\r\n#include <gfx/nxlight.h>\r\n#include <gfx/nxtexman.h>\r\n#include <gfx/skeleton.h>\r\n\r\n#include <sys/file/filesys.h>\r\n\r\nnamespace Nx\r\n{\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stub versions of all platform specific functions are provided here:\r\n// so engine implementors can leave certain functionality until later\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CModel::plat_init_skeleton( int numBones )\r\n{\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CModel::plat_set_render_mode(ERenderMode mode)\r\n{\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CModel::plat_set_color(uint8 r, uint8 g, uint8 b, uint8 a)\r\n{\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CModel::plat_set_visibility(uint32 mask)\r\n{\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CModel::plat_set_active(bool active)\r\n{\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CModel::plat_set_scale(float scaleFactor)\r\n{\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CModel::plat_render(Mth::Matrix* pRootMatrix, Mth::Matrix* ppBoneMatrices, int numBones)\r\n{\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CModel::plat_replace_texture(char* p_srcFileName, char* p_dstFileName)\r\n{\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CModel::plat_prepare_materials( void )\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CModel::plat_refresh_materials( void )\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CModel::plat_get_bounding_sphere()\r\n{\r\n\tif ( m_numBones > 0 )\r\n\t{\r\n\t\t// the original hack for skinned models\r\n\t\treturn Mth::Vector(0.0f, 36.0f, 0.0f, 48.0f);\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// the original hack for non-skinned models\r\n\t\treturn Mth::Vector(0.0f, 36.0f, 0.0f, 1200.0f);\t\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModel::plat_set_bounding_sphere( const Mth::Vector& boundingSphere )\r\n{\r\n\t// Do nothing by default... \r\n\t// (this is only needed by the PS2 version...)\r\n\r\n\t// TODO:  Set the appropriate bounding sphere that will be returned\r\n\t// by plat_get_bounding_sphere...\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// These functions are the platform independent part of the interface to \r\n// the platform specific code\r\n// parameter checking can go here....\r\n// although we might just want to have these functions inline, or not have them at all?\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModel::CModel()\r\n{\r\n    m_numBones = 0;\r\n    mp_skeletonMatrices = NULL;\r\n\r\n    SetRenderMode( vNONE );\r\n\r\n\tm_numGeoms = 0;\r\n\r\n\tm_primaryMeshName = CRCD(0x6607dd3e,\"Uninitialized\");\r\n\r\n\tm_active = true;\r\n\tm_hidden = false;\r\n\tm_scale = Mth::Vector( 1.0f, 1.0f, 1.0f );\r\n\tm_scalingEnabled = false;\r\n\tm_shadowEnabled = false;\r\n\tm_doShadowVolume = false;\r\n\r\n\tmp_model_lights = NULL;\r\n\r\n\tm_boundingSphereCached = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModel::~CModel()\r\n{\r\n\tif (mp_model_lights)\r\n\t{\r\n\t\tCLightManager::sFreeModelLights(mp_model_lights);\r\n\t}\r\n\r\n\tClearGeoms();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\n\r\n// GJ 10/23/02:  This function didn't seem to be used, \r\n// so I commented it out for now\r\n\r\nvoid CModel::ResetScale()\r\n{\r\n\tSetScale( Mth::Vector( 1.0f, 1.0f, 1.0f ) );\r\n\r\n\tif ( mp_skeleton )\r\n\t{\r\n\t\tmp_skeleton->ResetScale();\r\n\t}\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::SetSkeleton( Gfx::CSkeleton* pSkeleton )\r\n{\r\n\r\n\tif (!mp_skeletonMatrices)\r\n\t{\r\n\t\tm_numBones = pSkeleton->GetNumBones();\r\n\t\r\n\t\tplat_init_skeleton( pSkeleton->GetNumBones() );\r\n\t\r\n\t\tmp_skeletonMatrices = pSkeleton->GetMatrices();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(m_numBones == pSkeleton->GetNumBones(),(\"Mismatch in number of bones\"));\r\n\t\t\r\n\t}\r\n\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::Render( Mth::Matrix* pMatrix, bool no_anim, Gfx::CSkeleton* pSkeleton )\r\n{\r\n\t// don't display the skin, unless we're\r\n\t// in the standard \"textured\" mode\r\n\tbool is_textured = m_renderMode == vTEXTURED; \r\n\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( int i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tDbg_Assert( GetGeomByIndex(i) );\r\n\t\tGetGeomByIndex(i)->SetActive( is_textured && m_active && (m_geomActiveMask&(1<<i)) );\r\n\t}\r\n\r\n\t// scale up the matrix by the appropriate amount...\r\n\tif ( m_scalingEnabled )\r\n\t{\r\n\t\tpMatrix->ScaleLocal(m_scale);\r\n\t}\r\n       \r\n\t// make sure the skeleton matches up...\r\n\tif ( pSkeleton )\t\t\t\t\t    \r\n\t{\r\n\t\tDbg_MsgAssert( m_numBones != 0, ( \"Trying to update a model with incorrect number of bones (expected %d, found %d)\", m_numBones, pSkeleton->GetNumBones() ) );\r\n\t\tDbg_Assert( mp_skeletonMatrices );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert( m_numBones == 0, ( \"Trying to update a model with incorrect number of bones (expected %d, found %d)\", 0, m_numBones ) );\r\n\t\tDbg_Assert( mp_skeletonMatrices == NULL );\r\n\t}\r\n\r\n    switch ( m_renderMode )\r\n    {\r\n        case vTEXTURED:\r\n        {\r\n\t\t\tif ( pSkeleton )\r\n            {\r\n\t\t\t\t(*pMatrix)[Mth::RIGHT][W] = 0.0f;\r\n\t\t\t\t(*pMatrix)[Mth::UP][W] = 0.0f;\r\n\t\t\t\t(*pMatrix)[Mth::AT][W] = 0.0f;\r\n\t\t\t\t(*pMatrix)[Mth::POS][W] = 1.0f;\r\n\r\n\t\t\t\tint numGeoms = GetNumGeoms();\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\tif ( no_anim )\r\n\t\t\t\t{\r\n\t\t\t\t\t// update root position without updating bones\r\n\t\t\t\t\tfor ( int i = 0; i < numGeoms; i++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_Assert( GetGeomByIndex(i) );\r\n\t\t\t\t\t\tGetGeomByIndex(i)->Render( pMatrix, NULL, 0 );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n \t\t\t\t\t// update both root position AND bones\r\n\t\t\t\t\tfor ( int i = 0; i < numGeoms; i++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_Assert( GetGeomByIndex(i) );\r\n\t\t\t\t\t\tGetGeomByIndex(i)->Render( pMatrix, pSkeleton->GetMatrices(), pSkeleton->GetNumBones() );\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// the following should NOT be necessary,\r\n\t\t\t\t// but it is.\r\n\t\t\t\t(*pMatrix)[Mth::RIGHT][W] = 0.0f;\r\n\t\t\t\t(*pMatrix)[Mth::UP][W] = 0.0f;\r\n\t\t\t\t(*pMatrix)[Mth::AT][W] = 0.0f;\r\n\t\t\t\t(*pMatrix)[Mth::POS][W] = 1.0f;\r\n\t\t\t\t\r\n\t\t\t\tint numGeoms = GetNumGeoms();\r\n\t\t\t\tfor ( int i = 0; i < numGeoms; i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( GetGeomByIndex(i) );\r\n\t\t\t\t\tGetGeomByIndex(i)->Render( pMatrix, NULL, 0 );\r\n\t\t\t\t}\r\n\t\t\t}\r\n        }\r\n        break;\r\n        \r\n\t\tcase vSKELETON:\r\n\t\t{\r\n            if ( pSkeleton )\r\n            {\r\n\t\t\t\tpSkeleton->Display( pMatrix, 0.5f, 0.5f, 1.0f );\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n        case vBBOX:\r\n        default:\r\n        {\r\n            Mth::Matrix matrix = *pMatrix;\r\n\r\n            // really, the AddDebugBox function should be\r\n            // able to draw with only one matrix, rather\r\n            // than matrix+pos.\r\n            matrix[Mth::POS] = Mth::Vector( 0, 0, 0 );\r\n\r\n            Mth::Vector pos = pMatrix->GetPos();\r\n\r\n            // set up bounding box\r\n            SBBox theBox;\r\n            theBox.m_max.Set(10.0f, 10.0f, 10.0f);\r\n            theBox.m_min.Set(-10.0f, -10.0f, -10.0f);    \r\n\r\n            // For now, draw a bounding box\r\n            Gfx::AddDebugBox( matrix, pos, &theBox, NULL, 1, NULL ); \r\n\t\t}\r\n        break;\r\n        \r\n\t\tcase vGOURAUD:\r\n        case vFLAT:\r\n        case vWIREFRAME:\r\n            Dbg_Assert( 0 );\r\n        break;\r\n\r\n        case vNONE:\r\n            // draw nothing...\r\n            break;\r\n        \r\n    }\r\n\r\n    return true;\r\n}\r\n                            \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::SetBoneMatrixData( Gfx::CSkeleton* pSkeleton )\r\n{\r\n\t// GJ:  X-box doesn't copy over bone matrix data once per frame\r\n\t// like the PS2 does...  so the following allows me to hijack the\r\n\t// skater's model matrices and copy over the matrices\r\n\t// from a different model... (for skater substitution in cutscenes,\r\n\t// and perhaps for the bail board)\r\n\r\n\tDbg_Assert( pSkeleton );\r\n\t\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( int i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tDbg_Assert( GetGeomByIndex(i) );\r\n\t\tGetGeomByIndex(i)->SetBoneMatrixData( pSkeleton->GetMatrices(), pSkeleton->GetNumBones() );\r\n\t}  \r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::AddGeom(uint32 assetName, uint32 geomName, bool supportMultipleMaterialColors)\r\n{\r\n\t// now that a new geom has been added to the model,\r\n\t// consider the bounding sphere \"dirty\"\r\n\tm_boundingSphereCached = false;\r\n\r\n\t// for now, assume that if we're using this method of creating assets,\r\n\t// then we'll be using the asset manager and a texDictOffset of 0\r\n    \r\n\tbool success = false;\r\n\r\n\tDbg_MsgAssert( m_numGeoms < MAX_GEOMS, ( \"Too many geoms for this model (max=%d)\", MAX_GEOMS ) );\r\n\r\n\t// the asset must already exist in the assman by this point!\r\n\t// note that we're not loading the asset, only getting it\r\n\tAss::CAssMan * ass_man = Ass::CAssMan::Instance();\r\n\r\n\tNx::CMesh* pMesh = NULL;\r\n\tpMesh = (Nx::CMesh*)ass_man->GetAsset( assetName, false );\r\n\tif( !pMesh )\r\n\t{\r\n\t\tDbg_MsgAssert( false,( \"Could not get asset %08x\", assetName ));\r\n\t}\t   \t\t   \r\n\r\n\tm_preloadedMeshNames[m_numPreloadedMeshes] = assetName;\r\n\tm_numPreloadedMeshes++;\r\n\r\n\tmp_geom[m_numGeoms] = Nx::CEngine::sInitGeom();\r\n\r\n\tif ( mp_geom[m_numGeoms] )\r\n\t{\r\n\t\tmp_geom[m_numGeoms]->LoadGeomData(pMesh, this, supportMultipleMaterialColors);\r\n\t\tmp_geomTexDict[m_numGeoms] = pMesh->GetTextureDictionary();\r\n\t\tmp_geom[m_numGeoms]->EnableShadow(m_shadowEnabled);\r\n\t\tm_geomName[m_numGeoms] = geomName;\r\n\t\tm_geomActiveMask |= (1<<m_numGeoms);\r\n\r\n\t\t// Set the model lights, if any\r\n\t\tif (mp_model_lights)\r\n\t\t{\r\n\t\t\tmp_geom[m_numGeoms]->SetModelLights(mp_model_lights);\r\n\t\t}\r\n\r\n\t\tm_numGeoms++;\r\n\t\t\r\n\t\tSetRenderMode( vTEXTURED );\r\n\t}\r\n\r\n\t// TODO:  The mesh file name represents\r\n\t// mesh #0, but the mesh file name is\r\n\t// already kind of kludge that will be\r\n\t// cleaned up when CGeoms are properly\r\n\t// implemented.\r\n\tif ( m_numGeoms == 1 )\r\n\t{\r\n\t\t// doesn't have a filename because it came from a stream...\r\n\t\tm_primaryMeshName = Script::GenerateCRC(\"data_from_stream\");\r\n\t}\r\n    \r\n\treturn success;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::AddGeom(const char* pMeshFileName, uint32 geomName, bool useAssetManager, uint32 texDictOffset, bool forceTexDictLookup, bool supportMultipleMaterialColors)\r\n{\r\n\t// now that a new geom has been added to the model,\r\n\t// consider the bounding sphere \"dirty\"\r\n\tm_boundingSphereCached = false;\r\n\r\n    bool success = false;\r\n\r\n\tDbg_MsgAssert( m_numGeoms < MAX_GEOMS, ( \"Too many geoms for this model (max=%d)\", MAX_GEOMS ) );\r\n\r\n\t// grabs the data from the asset manager if it's not already loaded\r\n\tAss::CAssMan * ass_man = Ass::CAssMan::Instance();\r\n\r\n\tNx::CMesh* pMesh = NULL;\r\n\tif ( useAssetManager )\r\n\t{\r\n\t\tAss::SSkinAssetLoadContext theContext;\r\n\t\ttheContext.forceTexDictLookup = forceTexDictLookup;\r\n\t\ttheContext.doShadowVolume = m_doShadowVolume;\r\n\t\ttheContext.texDictOffset = texDictOffset;\r\n\r\n\t\tpMesh = (Nx::CMesh*)ass_man->LoadOrGetAsset( pMeshFileName, false, false, ass_man->GetDefaultPermanent(), 0, &theContext );\r\n\t\tif( !pMesh )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( false,( \"Could not load asset %s\", pMeshFileName ));\r\n\t\t}\t   \t\t   \r\n\r\n\t\tm_preloadedMeshNames[m_numPreloadedMeshes] = Script::GenerateCRC(pMeshFileName);\r\n\t\tm_numPreloadedMeshes++;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMem::PushMemProfile((char*)pMeshFileName);\r\n\t\tpMesh = Nx::CEngine::sLoadMesh( pMeshFileName, texDictOffset, forceTexDictLookup, m_doShadowVolume );\r\n\t\tMem::PopMemProfile(/*(char*)pMeshFileName*/);\r\n\t\tDbg_MsgAssert( m_numMeshes < MAX_MESHES, ( \"Too many meshes for this model (max=%d)\", MAX_MESHES ) );\r\n\t\tmp_mesh[m_numMeshes] = pMesh;\r\n\t\tm_numMeshes++;\r\n\t}\r\n\r\n\tmp_geom[m_numGeoms] = Nx::CEngine::sInitGeom();\r\n\r\n\tif ( mp_geom[m_numGeoms] )\r\n\t{\r\n\t\tmp_geom[m_numGeoms]->LoadGeomData(pMesh, this, supportMultipleMaterialColors);\r\n\t\tmp_geomTexDict[m_numGeoms] = pMesh->GetTextureDictionary();\r\n\t\tmp_geom[m_numGeoms]->EnableShadow(m_shadowEnabled);\r\n\t\tm_geomName[m_numGeoms] = geomName;\r\n\t\tm_geomActiveMask |= (1<<m_numGeoms);\r\n\r\n\t\t// Set the model lights, if any\r\n\t\tif (mp_model_lights)\r\n\t\t{\r\n\t\t\tmp_geom[m_numGeoms]->SetModelLights(mp_model_lights);\r\n\t\t}\r\n\r\n\t\tm_numGeoms++;\r\n\t\t\r\n\t\tSetRenderMode( vTEXTURED );\r\n\t}\r\n\r\n\t// TODO:  The mesh file name represents\r\n\t// mesh #0, but the mesh file name is\r\n\t// already kind of kludge that will be\r\n\t// cleaned up when CGeoms are properly\r\n\t// implemented.\r\n\tif ( m_numGeoms == 1 )\r\n\t{\r\n\t\tm_primaryMeshName = Script::GenerateCRC(pMeshFileName);\r\n\t}\r\n    \r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::AddGeom(CGeom* pGeom, uint32 geomName)\r\n{\r\n\t// now that a new geom has been added to the model,\r\n\t// consider the bounding sphere \"dirty\"\r\n\tm_boundingSphereCached = false;\r\n\r\n    bool success = false;\r\n\r\n\tDbg_MsgAssert( m_numGeoms < MAX_GEOMS, ( \"Too many geoms for this model (max=%d)\", MAX_GEOMS ) );\r\n\r\n\tmp_geom[m_numGeoms] = pGeom;\r\n\tmp_geom[m_numGeoms]->EnableShadow(m_shadowEnabled);\r\n\tm_geomName[m_numGeoms] = geomName;\r\n\tm_geomActiveMask |= (1<<m_numGeoms);\r\n\r\n\t// Set the model lights, if any\r\n\tif (mp_model_lights)\r\n\t{\r\n\t\tmp_geom[m_numGeoms]->SetModelLights(mp_model_lights);\r\n\t}\r\n\r\n\tm_numGeoms++;\r\n\t\t\r\n\tSetRenderMode( vTEXTURED );\r\n\r\n\t// TODO:  The mesh file name represents\r\n\t// mesh #0, but the mesh file name is\r\n\t// already kind of kludge that will be\r\n\t// cleaned up when CGeoms are properly\r\n\t// implemented.\r\n\tif ( m_numGeoms == 1 )\r\n\t{\r\n\t\tm_primaryMeshName = CRCD(0x9facc1a5,\"TempMeshName\");\r\n\t}\r\n    \r\n\t// Maybe need to pass in the collision volume instead?\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::RemovePolys(void)\r\n{\r\n\tuint32 polyRemovalMask = GetPolyRemovalMask();\r\n\r\n\tHidePolys( polyRemovalMask );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CModel::GetPolyRemovalMask()\r\n{\r\n\tuint32 polyRemovalMask = 0;\r\n\t\r\n\t// loop through the meshes to collect the poly removal masks\r\n\tfor ( short i = 0; i < m_numMeshes; i++ )\r\n\t{\r\n\t\tpolyRemovalMask |= ( mp_mesh[i]->GetRemovalMask() );\r\n\t}\r\n\r\n\t// also account for cutscene objects, which are loaded\r\n\t// through the asset manager\r\n\tfor ( short i = 0; i < m_numPreloadedMeshes; i++ )\r\n\t{\r\n\t\tAss::CAssMan * ass_man = Ass::CAssMan::Instance();\r\n\t\tNx::CMesh* pMesh = (Nx::CMesh*)ass_man->GetAsset( m_preloadedMeshNames[i], true );\r\n\t\tif( pMesh )\r\n\t\t{\r\n\t\t\tpolyRemovalMask |= pMesh->GetRemovalMask();\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn polyRemovalMask;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModel::HidePolys( uint32 polyRemovalMask )\r\n{\r\n\t// loop through the existing models, and remove existing polys\r\n\tfor ( short i = 0; i < m_numGeoms; i++ )\r\n\t{\r\n\t\tmp_geom[i]->HidePolys( polyRemovalMask );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::CreateModelLights()\r\n{\r\n\tDbg_MsgAssert( !mp_model_lights, (\"Model lights already exist\") );\r\n\r\n\tmp_model_lights = Nx::CLightManager::sCreateModelLights();\r\n\r\n\tfor ( short i = 0; i < m_numGeoms; i++ )\r\n\t{\r\n\t\tmp_geom[i]->SetModelLights( mp_model_lights );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::DestroyModelLights()\r\n{\r\n\tDbg_MsgAssert( mp_model_lights, (\"No Model lights to destroy\") );\r\n\r\n\tNx::CLightManager::sFreeModelLights( mp_model_lights );\r\n\r\n\tmp_model_lights = NULL;\r\n\tfor ( short i = 0; i < m_numGeoms; i++ )\r\n\t{\r\n\t\tmp_geom[i]->SetModelLights( NULL );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModelLights * CModel::GetModelLights() const\r\n{\r\n\treturn mp_model_lights;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::SetRenderMode(ERenderMode mode)\r\n{\r\n    bool success = false;\r\n\r\n    if (mode != m_renderMode)\r\n    {\r\n        success = plat_set_render_mode(mode);\r\n        \r\n        if (success)\r\n        {\r\n            m_renderMode = mode;\r\n        }\r\n    }\r\n\r\n    return success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nERenderMode CModel::GetRenderMode()\r\n{\r\n\treturn m_renderMode;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModel::Hide( bool should_hide )\r\n{   \r\n\tm_hidden = should_hide;\r\n\t\r\n\tSetActive( !should_hide );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::SetActive( bool active )\r\n{\r\n\tif( m_hidden && active )\r\n\t{\r\n\t\treturn false;\t\t\t\t\t\t\t\t\t\r\n\t}\r\n\r\n\t// (Mick) if the active state is already set correctly, then just return\r\n\t// (this assumes that the geoms are correctly set already)\t\r\n\tif (m_active == active)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tDbg_Assert( GetGeomByIndex(i) );\r\n\t\tGetGeomByIndex(i)->SetActive( active );\r\n\t}\r\n\t\r\n\tm_active = active;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom* CModel::GetGeom(uint32 geomName)\r\n{\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\t// TODO:  there might be multiple geoms with\r\n\t\t// the same checksum...\r\n\t\tif ( geomName == m_geomName[i] )\r\n\t\t{\r\n\t\t\tDbg_Assert( GetGeomByIndex( i ) );\r\n\t\t\treturn GetGeomByIndex( i );\r\n\t\t}\r\n\t}\r\n\r\n    return NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::ReplaceTexture( uint32 geomName, const char* p_SrcTextureName, const char* p_DstTextureName )\r\n{\r\n\tbool success = false;\r\n\t\r\n\tbool applyToAll = (geomName == vREPLACE_GLOBALLY);\r\n\t\r\n\tplat_prepare_materials();\r\n\r\n\t// The lower level code is expecting the .PNG extension\r\n\t// for the source texture name, so add it if's not there\r\n\tchar src_texture_name[512];\r\n\tstrcpy( src_texture_name, p_SrcTextureName );\r\n\tStr::LowerCase( src_texture_name );\r\n\tchar* pSrcExt = strstr( src_texture_name, \".png\" );\r\n\tif ( !pSrcExt )\r\n\t{\r\n\t\tstrcat( src_texture_name, \".png\" );\r\n\t}\r\n\r\n\t// The lower level code is NOT expecting the .PNG extension\r\n\t// for the destination texture name, so strip it out if it's \r\n\t// there (the artists sometimes accidentally leave the .PNG in there)...\r\n\tchar dest_texture_name[512];\r\n\tstrcpy( dest_texture_name, p_DstTextureName );\r\n\tStr::LowerCase( dest_texture_name );\r\n\tchar* pDstExt = strstr( dest_texture_name, \".png\" );\r\n\tif ( pDstExt )\r\n\t{\r\n\t\t*pDstExt = NULL;\r\n\t}\r\n\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\t// m_geomName[i] = 0 will handle cutscene objects,\r\n\t\t// for texture replacement on the hi-res heads\r\n\r\n\t\tif ( geomName == m_geomName[i] || applyToAll || m_geomName[i] == 0 )\r\n\t\t{\r\n\t\t\tif ( mp_geomTexDict[i] && mp_geomTexDict[i]->ReplaceTexture( src_texture_name, dest_texture_name) )\r\n\t\t\t{\r\n\t\t\t\tsuccess = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif ( !success && Script::GetInteger( CRCD(0x2a648514,\"cas_artist\") ) )\r\n\t{\r\n\t\tDbg_Message( \"Texture replacement of %s by %s failed!\", p_SrcTextureName, dest_texture_name );\r\n\t}\r\n\r\n\tplat_refresh_materials();\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::ReplaceTexture( uint32 geomName, const char* p_SrcFileName, uint32 DstChecksum )\r\n{\r\n\tbool success = false;\r\n\t\r\n\tbool applyToAll = (geomName == vREPLACE_GLOBALLY);\r\n\t\r\n\tplat_prepare_materials();\r\n\r\n\t// The lower level code is expecting the .PNG extension\r\n\t// for the source texture name, so add it if's not there\r\n\tchar src_texture_name[512];\r\n\tstrcpy( src_texture_name, p_SrcFileName );\r\n\tStr::LowerCase( src_texture_name );\r\n\tchar* pSrcExt = strstr( src_texture_name, \".png\" );\r\n\tif ( !pSrcExt )\r\n\t{\r\n\t\tstrcat( src_texture_name, \".png\" );\r\n\t}\r\n\r\n\tCTexture *p_dest_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(DstChecksum);\r\n\tif (!p_dest_texture)\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find destination texture %s\", Script::FindChecksumName(DstChecksum)));\r\n\t}\r\n\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tif ( geomName == m_geomName[i] || applyToAll )\r\n\t\t{\r\n\t\t\tif ( mp_geomTexDict[i] && mp_geomTexDict[i]->ReplaceTexture( src_texture_name, p_dest_texture) )\r\n\t\t\t{\r\n\t\t\t\tsuccess = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif ( !success && Script::GetInteger( CRCD(0x2a648514,\"cas_artist\") ) )\r\n\t{\r\n\t\tDbg_Message( \"Texture replacement of %s by %s failed!\", p_SrcFileName, Script::FindChecksumName(DstChecksum) );\r\n\t}\r\n\r\n\tplat_refresh_materials();\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::ClearColor( uint32 geomName )\r\n{\r\n\tbool success = false;\r\n\t\r\n\tbool applyToAll = (geomName == vREPLACE_GLOBALLY);\r\n\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tif ( geomName == m_geomName[i] || applyToAll )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( !mp_geom[i]->MultipleColorsEnabled(), ( \"Wasn't expecting multiple material colors\" ) );\r\n\r\n\t\t\tmp_geom[i]->ClearColor();\r\n\t\t\tsuccess = true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::ModulateColor( uint32 geomName, float h, float s, float v )\r\n{\r\n\t// hue = [0.0, 360.0f)\r\n\t// satuation = [0.0, 1.0]\r\n\t// value = [0.0, 1.0]\r\n\r\n\tbool success = false;\r\n\t\r\n\tbool applyToAll = (geomName == vREPLACE_GLOBALLY);\r\n\t\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tif ( geomName == m_geomName[i] || applyToAll )\r\n\t\t{\r\n\t\t\tif ( mp_geom[i]->MultipleColorsEnabled() )\r\n\t\t\t{\r\n\t\t\t\t// ignore geoms with the \"multiple colors\" flag\r\n\t\t\t\t// (you're supposed to use SetColorWithParams() for that)\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfloat r, g, b;\r\n\t\t\t\tGfx::HSVtoRGB( &r, &g, &b, h, s, v );\r\n\r\n\t\t\t\tImage::RGBA theColor;\r\n\t\t\t\ttheColor.r = (unsigned char)( r * 255.0f + 0.5f );\r\n\t\t\t\ttheColor.g = (unsigned char)( g * 255.0f + 0.5f );\r\n\t\t\t\ttheColor.b = (unsigned char)( b * 255.0f + 0.5f );\r\n\t\t\t\ttheColor.a = 255;\r\n\r\n\t\t\t\tDbg_MsgAssert( !mp_geom[i]->MultipleColorsEnabled(), ( \"Wasn't expecting multiple material colors\" ) );\r\n\r\n\t\t\t\tmp_geom[i]->SetColor( theColor );\r\n\t\t\t\tsuccess = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::SetUVOffset(uint32 mat_checksum, int pass, float u_offset, float v_offset)\r\n{\r\n\tbool success = false;\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tsuccess |= mp_geom[i]->SetUVWibbleOffsets(mat_checksum, pass, u_offset, v_offset);\r\n\t}\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::SetUVMatrix(uint32 mat_checksum, int pass, const Mth::Matrix &mat)\r\n{\r\n\tbool success = false;\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tsuccess |= mp_geom[i]->SetUVMatrix(mat_checksum, pass, mat);\r\n\t}\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::AllocateUVMatrixParams(uint32 mat_checksum, int pass)\r\n{\r\n\tbool success = false;\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tsuccess |= mp_geom[i]->AllocateUVMatrixParams(mat_checksum, pass);\r\n\t}\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::SetColor( Script::CStruct* pParams, float h, float s, float v )\r\n{\r\n\t// GJ:  This is a generic way of changing the colors in a model,\r\n\t// without having to know whether it has a separate color per material\r\n\t\r\n\t// GJ TODO:  Ideally, this function would not reference CStruct,\r\n\t// but would rather be passed the appropriate material/pass\r\n\t// parameters from a higher level...\r\n\r\n\tbool success = false;\r\n\r\n\tuint32 geomName;\r\n\tpParams->GetChecksum( CRCD(0xb6f08f39,\"part\"), &geomName, Script::ASSERT );\r\n\r\n\tfloat r, g, b;\r\n\tGfx::HSVtoRGB( &r, &g, &b, h, s, v );\r\n\r\n\tImage::RGBA theColor;\r\n\ttheColor.r = (unsigned char)( r * 255.0f + 0.5f );\r\n\ttheColor.g = (unsigned char)( g * 255.0f + 0.5f );\r\n\ttheColor.b = (unsigned char)( b * 255.0f + 0.5f );\r\n\ttheColor.a = 255;\r\n\r\n\tbool applyToAll = (geomName == vREPLACE_GLOBALLY);\r\n\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( int i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tuint32 mat_checksum;\r\n\t\tint pass = 0;\r\n\t\tScript::CArray* pMaterialArray;\r\n\t\t\r\n\t\tif ( !mp_geom[i]->MultipleColorsEnabled() )\r\n\t\t{\r\n\t\t\tif ( geomName == m_geomName[i] || applyToAll )\r\n\t\t\t{\r\n\t\t\t\tmp_geom[i]->SetColor( theColor );\r\n\t\t\t\tsuccess = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( pParams->GetArray( CRCD(0x64e8e94a,\"materials\"), &pMaterialArray, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tfor ( uint32 j = 0; j < pMaterialArray->GetSize(); j++ )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pMaterialStruct = pMaterialArray->GetStructure( j );\r\n\t\t\t\tpMaterialStruct->GetChecksum( NONAME, &mat_checksum, Script::ASSERT );\r\n\t\t\t\tpMaterialStruct->GetInteger( NONAME, &pass, Script::ASSERT ); \r\n\r\n\t\t\t\tsuccess |= mp_geom[i]->SetMaterialColor(mat_checksum, pass, theColor);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( pParams->GetChecksum( CRCD(0x83418a6a,\"material\"), &mat_checksum, Script::NO_ASSERT )\t)\r\n\t\t{\r\n\t\t\tScript::CArray* pPassArray;\r\n\t\t\tif ( pParams->GetArray( CRCD(0x318f2bdb,\"pass\"), &pPassArray, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tfor ( uint32 j = 0; j < pPassArray->GetSize(); j++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tsuccess |= mp_geom[i]->SetMaterialColor(mat_checksum, pPassArray->GetInteger(j), theColor);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( pParams->GetInteger( CRCD(0x318f2bdb,\"pass\"), &pass, Script::ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tsuccess |= mp_geom[i]->SetMaterialColor(mat_checksum, pass, theColor);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// kludge for changing skin color\r\n\t\t// (ideally this would be in script, but we would have to uglify the\r\n\t\t// code to get around some of the model-building operations that\r\n\t\t// currently overwrite the body substructure, such as when\r\n\t\t// the head forces the body to a specific skin tone)\r\n\t\tif ( ( geomName == CRCD(0x650fab6d,\"skater_m_head\") \r\n\t\t\t   || geomName == CRCD(0x0fc85bae,\"skater_f_head\") )\r\n\t\t\t && m_geomName[i] == CRCD(0x2457f44d,\"body\") )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( !mp_geom[i]->MultipleColorsEnabled(), ( \"Wasn't expecting color per material on body geom\" ) );\r\n\t\t\tthis->ModulateColor( CRCD(0x2457f44d,\"body\"), h, s, v );\r\n\t\t}\r\n\t}\t\r\n\t\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::ClearColor( Script::CStruct* pParams )\r\n{\r\n\t// GJ:  This is a generic way of changing the colors in a model,\r\n\t// without having to know whether it has a separate color per material\r\n\t\r\n\tbool success = false;\r\n\r\n\tuint32 geomName;\r\n\tpParams->GetChecksum( CRCD(0xb6f08f39,\"part\"), &geomName, Script::ASSERT );\r\n\r\n\tbool applyToAll = (geomName == vREPLACE_GLOBALLY);\r\n\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( int i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tuint32 mat_checksum;\r\n\t\tint pass = 0;\r\n\t\tScript::CArray* pMaterialArray;\r\n\t\t\r\n\t\tif ( !mp_geom[i]->MultipleColorsEnabled() )\r\n\t\t{\r\n\t\t\tif ( geomName == m_geomName[i] || applyToAll )\r\n\t\t\t{\r\n\t\t\t\tmp_geom[i]->ClearColor();\r\n\t\t\t\tsuccess = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( pParams->GetArray( CRCD(0x64e8e94a,\"materials\"), &pMaterialArray, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tImage::RGBA theColor;\r\n\t\t\ttheColor.r = 128;\r\n\t\t\ttheColor.g = 128;\r\n\t\t\ttheColor.b = 128;\r\n\t\t\ttheColor.a = 128;\r\n\r\n\t\t\tfor ( uint32 j = 0; j < pMaterialArray->GetSize(); j++ )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pMaterialStruct = pMaterialArray->GetStructure( j );\r\n\t\t\t\tpMaterialStruct->GetChecksum( NONAME, &mat_checksum, Script::ASSERT );\r\n\t\t\t\tpMaterialStruct->GetInteger( NONAME, &pass, Script::ASSERT ); \r\n\r\n\t\t\t\tsuccess |= mp_geom[i]->SetMaterialColor(mat_checksum, pass, theColor);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( pParams->GetChecksum( CRCD(0x83418a6a,\"material\"), &mat_checksum, Script::NO_ASSERT )\t)\r\n\t\t{\r\n\t\t\tImage::RGBA theColor;\r\n\t\t\ttheColor.r = 128;\r\n\t\t\ttheColor.g = 128;\r\n\t\t\ttheColor.b = 128;\r\n\t\t\ttheColor.a = 128;\r\n\t\t\t\r\n\t\t\tScript::CArray* pPassArray;\r\n\t\t\tif ( pParams->GetArray( CRCD(0x318f2bdb,\"pass\"), &pPassArray, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tfor ( uint32 j = 0; j < pPassArray->GetSize(); j++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tsuccess |= mp_geom[i]->SetMaterialColor(mat_checksum, pPassArray->GetInteger(j), theColor);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( pParams->GetInteger( CRCD(0x318f2bdb,\"pass\"), &pass, Script::ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tsuccess |= mp_geom[i]->SetMaterialColor(mat_checksum, pass, theColor);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// kludge for changing skin color\r\n\t\tif ( ( geomName == CRCD(0x650fab6d,\"skater_m_head\") \r\n\t\t\t   || geomName == CRCD(0x0fc85bae,\"skater_f_head\") )\r\n\t\t\t && m_geomName[i] == CRCD(0x2457f44d,\"body\") )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( !mp_geom[i]->MultipleColorsEnabled(), ( \"Wasn't expecting color per material on body geom\" ) );\r\n\t\t\tmp_geom[i]->ClearColor();\r\n\t\t\tsuccess = true;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom* CModel::GetGeomByIndex(int index)\r\n{\r\n\tDbg_Assert( index >= 0 && index < m_numGeoms );\r\n\r\n    return mp_geom[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CModel::GetGeomNameByIndex(int index)\r\n{\r\n\tDbg_Assert( index >= 0 && index < m_numGeoms );\r\n\r\n    return m_geomName[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexDict* CModel::GetTexDictByIndex(int index)\r\n{\r\n\tDbg_Assert( index >= 0 && index < m_numGeoms );\r\n\r\n    return mp_geomTexDict[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CModel::GetNumGeoms() const\r\n{\r\n    return m_numGeoms;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CModel::GetGeomActiveMask() const\r\n{\r\n\t// K: Used by replay code.\r\n\treturn m_geomActiveMask;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModel::SetGeomActiveMask(uint32 mask)\r\n{\r\n\t// K: Used by replay code.\r\n\tm_geomActiveMask=mask;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModel::Finalize()\r\n{\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tDbg_Assert( GetGeomByIndex(i) );\r\n\t\tGetGeomByIndex(i)->Finalize();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModel::ClearGeoms()\r\n{\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tDbg_Assert( GetGeomByIndex(i) );\r\n\t\tNx::CEngine::sUninitGeom( GetGeomByIndex(i) );\r\n\t}\r\n\r\n\tm_numGeoms = 0;\r\n\r\n\t// eliminate all the meshes\r\n\tfor ( short i = 0; i < m_numMeshes; i++ )\r\n\t{\r\n\t\tNx::CEngine::sUnloadMesh( mp_mesh[i] );\r\n\t}\r\n\r\n\tm_numMeshes = 0;\r\n\r\n\tm_numPreloadedMeshes = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::HideGeom( uint32 geomName, bool hidden )\r\n{\r\n\tbool success = false;\r\n\r\n\tbool applyToAll = (geomName == vREPLACE_GLOBALLY);\r\n\t\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tif ( (geomName == m_geomName[i]) || applyToAll )\r\n\t\t{\r\n\t\t\tif ( hidden )\r\n\t\t\t{\r\n\t\t\t\tm_geomActiveMask &= ~(1<<i);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_geomActiveMask |= (1<<i);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tsuccess = true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::GeomHidden( uint32 geomName )\r\n{\r\n    bool success = true;\r\n    \r\n    int numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tif ( (geomName == m_geomName[i]) )\r\n\t\t{\r\n\t\t\tif ( m_geomActiveMask & (1<<i) )\r\n            {\r\n                success = false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Matrix* CModel::GetBoneTransforms()\r\n{\r\n    // GJ:  eventually, i'd like to get rid of this ptr,\r\n    // but for now, don't break the NGC and XBOX versions\r\n\r\n    return mp_skeletonMatrices;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::SetColor(uint8 r, uint8 g, uint8 b, uint8 a)\r\n{\r\n\tImage::RGBA rgba(r, g, b, a);\r\n\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tDbg_Assert( GetGeomByIndex(i) );\r\n\t\tGetGeomByIndex(i)->SetColor(rgba);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::SetVisibility(uint32 mask)\r\n{\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tDbg_Assert( GetGeomByIndex(i) );\r\n\t\tGetGeomByIndex(i)->SetVisibility(mask);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::SetScale( const Mth::Vector& scale )\r\n{\r\n\tm_scale = scale;\r\n\t\r\n\tm_scalingEnabled = ( scale[X] != 1.0f || scale[Y] != 1.0f || scale[Z] != 1.0f );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModel::EnableScaling( bool enabled )\r\n{\r\n\tm_scalingEnabled = enabled;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModel::EnableShadow( bool enabled )\r\n{\r\n\tm_shadowEnabled = enabled;\r\n\r\n\tint numGeoms = GetNumGeoms();\r\n\tfor ( short i = 0; i < numGeoms; i++ )\r\n\t{\r\n\t\tDbg_Assert( GetGeomByIndex(i) );\r\n\t\tGetGeomByIndex(i)->EnableShadow(enabled);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CModel::GetNumObjectsInHierarchy()\r\n{\r\n\t// This function only works with single-CMesh items\r\n\tif ( m_numPreloadedMeshes == 1 )\r\n\t{\r\n\t\tAss::CAssMan * ass_man = Ass::CAssMan::Instance();\r\n\t\tNx::CMesh* pMesh = (Nx::CMesh*)ass_man->GetAsset( m_preloadedMeshNames[0] );\r\n\t\tDbg_MsgAssert( pMesh, ( \"Couldn't find preloaded mesh[0] to get hierarchy from\" ) );\r\n\t\treturn pMesh->GetNumObjectsInHierarchy();\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::CHierarchyObject* CModel::GetHierarchy()\r\n{\r\n\t// This function only works with single-CMesh items\r\n\tif ( m_numPreloadedMeshes == 1 )\r\n\t{\r\n\t\tAss::CAssMan * ass_man = Ass::CAssMan::Instance();\r\n\t\tNx::CMesh* pMesh = (Nx::CMesh*)ass_man->GetAsset( m_preloadedMeshNames[0] );\r\n\t\tDbg_MsgAssert( pMesh, ( \"Couldn't find preloaded mesh[0] to get hierarchy from\" ) );\r\n\t\treturn pMesh->GetHierarchy();\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CModel::GetBoundingSphere()\r\n{\r\n\t// unless the dirty flag has been set\r\n\tif ( m_boundingSphereCached )\r\n\t{\r\n\t\treturn m_boundingSphere;\r\n\t}\r\n\r\n\t// recalculate the bounding sphere\r\n\tm_boundingSphere = plat_get_bounding_sphere();\r\n\tm_boundingSphereCached = true;\r\n\r\n\treturn m_boundingSphere;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModel::SetBoundingSphere( const Mth::Vector& boundingSphere )\r\n{\r\n\tm_boundingSphereCached = false;\r\n\r\n\tplat_set_bounding_sphere( boundingSphere );\r\n}\t\t\t\t\t  \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CModel::ApplyFaceTexture( Gfx::CFaceTexture* pFaceTexture, const char* pSrcTexture, uint32 partChecksumToReplace )\r\n{\r\n\tbool success = false;\r\n\r\n\tDbg_Assert( pFaceTexture );\r\n\tDbg_Assert( pFaceTexture->IsValid() );\r\n\r\n\t//-------------------------------------------------------------\r\n\t// step 1:  load up the temporary texture from the appearance's CFaceTexture\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n\tbool alloc_vram = true;\r\n\tuint32 temp_checksum = CRCD(0xb00b0dc0,\"dummy\");\r\n\tNx::CTexture* p_temp_texture = Nx::CTexDictManager::sp_sprite_tex_dict->LoadTextureFromBuffer(pFaceTexture->GetTextureData(), pFaceTexture->GetTextureSize(), temp_checksum, true, alloc_vram, false);\r\n\tDbg_Assert( p_temp_texture );\r\n\r\n\tNx::CTexture* p_temp_overlay = Nx::CTexDictManager::sp_sprite_tex_dict->LoadTexture(pFaceTexture->GetOverlayTextureName(), alloc_vram);\r\n\tDbg_Assert( p_temp_overlay );\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\t//-------------------------------------------------------------\r\n\r\n\t//-------------------------------------------------------------\r\n\t// step 2:  massage the temporary texture here, based on the appearance's CFaceTexture\r\n\tNx::SFacePoints originalModelFacePoints;\r\n\tScript::CStruct* pModelFacePoints = Script::GetStructure( CRCD(0xa435752c,\"original_model_face_points\"), Script::ASSERT );\r\n\tGetFacePointsStruct( originalModelFacePoints, pModelFacePoints );\r\n\tNx::CFaceTexMassager::sSetModelFacePoints( originalModelFacePoints );\r\n\r\n\tNx::CFaceTexMassager::sSetFaceTextureOverlay( p_temp_overlay );\r\n\r\n\t// this speeds things up a little because the palette doesn't get rebuilt\r\n\t// (the image is not accurate, but it does end up matching the skintone more)\r\n\t//bool do_palette_gen = false;\r\n\tbool do_palette_gen = pFaceTexture->GetFacePoints().m_adjust_hsv;\t\t// Rebuild the palette if HSV is modified\r\n\r\n\t// this is a test for Nolan to see if the colors match better\r\n\t// when the palette is generated\r\n//\tdo_palette_gen = Script::GetInt( CRCD(0x8b32fff0,\"do_palette_gen\"), Script::NO_ASSERT );\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tbool massage_success = \r\n\t#endif\r\n\tNx::CFaceTexMassager::sMassageTexture( p_temp_texture,\r\n\t\t\t\t\t\t\t\t\t\t   pFaceTexture->GetFacePoints(),\r\n\t\t\t\t\t\t\t\t\t\t   do_palette_gen );\r\n\r\n\tDbg_Assert( massage_success );\r\n\t//-------------------------------------------------------------\r\n\r\n\t//-------------------------------------------------------------\r\n\t// step 3:  do texture replacement on the actual model\r\n\tDbg_Assert( pSrcTexture );\r\n\tsuccess = this->ReplaceTexture( partChecksumToReplace, pSrcTexture, p_temp_texture->GetChecksum() );\r\n\t//-------------------------------------------------------------\r\n\r\n\t//-------------------------------------------------------------\r\n\t// step 4:  get rid of the temporary texture\r\n\tNx::CTexDictManager::sp_sprite_tex_dict->UnloadTexture( p_temp_texture );\r\n\tNx::CTexDictManager::sp_sprite_tex_dict->UnloadTexture( p_temp_overlay );\r\n\t//-------------------------------------------------------------\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CModel::EnableShadowVolume( bool enabled )\r\n{\r\n\t// if true, any future geoms added to the \r\n\t// model will use shadow volumes\r\n\tm_doShadowVolume = enabled;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxModel.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       NxModel.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/21/2001\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_NXMODEL_H__\r\n#define\t__GFX_NXMODEL_H__\r\n\r\n                           \r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <core/math.h>\r\n\r\n// Forward declarations\r\nnamespace Gfx\r\n{\r\n\tclass\tCFaceTexture;\r\n    class   CSkeleton;\r\n};\r\n\r\nnamespace Script\r\n{\r\n\tclass\tCStruct;\r\n};\r\n                  \r\nnamespace Nx\r\n{\r\n\r\n// Forward declarations\r\nclass\tCGeom;\r\nclass\tCHierarchyObject;\r\nclass\tCMesh;\r\nclass\tCTexDict;\r\nclass\tCModelLights;\r\n\r\n// TODO:  Insert class description here...\r\n// This is the machine-independent representation of a model,\r\n// which is the graphical representation of some object\r\n\r\nenum ERenderMode\r\n{\r\n    vTEXTURED,\r\n\tvSKELETON,\r\n    vGOURAUD,\r\n    vFLAT,\r\n    vWIREFRAME,\r\n    vBBOX,\r\n    vNONE\r\n};\r\n\r\nclass CModel : public Spt::Class\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\t// special flag for global texture replacement\r\n\t\tvREPLACE_GLOBALLY = 0xc4e78e22\t\t\t// all\r\n\t};\r\n\r\npublic:\r\n    // The basic interface to the model\r\n    // this is the machine independent part\t\r\n    // machine independent range checking, etc can go here\t\r\n\tCModel();\r\n    virtual\t\t\t\t~CModel();\r\n\r\npublic:\r\n\tbool\t\t\t\tSetBoneMatrixData( Gfx::CSkeleton* pSkeleton );\r\n    bool                Render( Mth::Matrix* pMatrix, bool no_anim, Gfx::CSkeleton* pSkeleton );\r\n    uint32\t\t\t\tGetFileName() { return m_primaryMeshName; }\r\n\r\n    // Grabs a specific geom object so that you can do part-specific operations\r\n    CGeom*     \t\t\tGetGeom(uint32 geomName);\r\n\tCGeom*\t\t\t\tGetGeomByIndex(int index);\r\n\tuint32\t\t\t\tGetGeomNameByIndex(int index);\r\n\tCTexDict*\t\t\tGetTexDictByIndex(int index);\r\n\tint\t\t\t\t\tGetNumGeoms() const;\r\n\tvoid\t\t\t\tClearGeoms();\r\n\tvoid\t\t\t\tFinalize();\r\n\tuint32\t\t\t\tGetGeomActiveMask() const;\r\n\tvoid\t\t\t\tSetGeomActiveMask(uint32 mask);\r\n\t\r\n\tbool\t\t\t\tAddGeom(uint32 assetName, uint32 geomName, bool supportMultipleMaterialColors=false);\r\n\tbool\t\t\t\tAddGeom(const char* pMeshName, uint32 geomName, bool useAssetManager, uint32 texDictOffset=0, bool forceTexDictLookup=false, bool supportMultipleMaterialColors=false);\r\n\tbool\t\t\t\tHideGeom( uint32 geomName, bool hidden );\r\n    bool\t\t\t\tGeomHidden( uint32 geomName );\r\n\r\n\t// probably need to pass the collision as well\r\n\tbool\t\t\t\tAddGeom(Nx::CGeom* pGeom, uint32 geomName);\r\n\r\n\t// model lights\r\n\tbool\t\t\t\tCreateModelLights();\r\n\tbool\t\t\t\tDestroyModelLights();\r\n\tCModelLights *\t\tGetModelLights() const;\r\n\r\npublic:\r\n    bool                SetRenderMode(ERenderMode mode);\r\n\tERenderMode\t\t\tGetRenderMode();\r\n\tbool\t\t\t\tSetColor(uint8 r, uint8 g, uint8 b, uint8 a);\r\n\tbool\t\t\t\tSetVisibility(uint32 mask);\r\n\tvoid\t\t\t\tResetScale();\r\n\tbool\t\t\t\tSetScale(const Mth::Vector& scale);\r\n\tMth::Vector\t\t\tGetScale() {return m_scale;}\r\n\tvoid\t\t\t\tEnableScaling( bool enabled );\r\n\tbool\t\t\t\tIsScalingEnabled() { return m_scalingEnabled; }\r\n\tvoid\t\t\t\tHide( bool should_hide = true );\r\n\tbool\t\t\t\tIsHidden() { return m_hidden; }\r\n\tbool\t\t\t\tSetActive(bool active);\r\n\tbool\t\t\t\tGetActive() {return m_active && !m_hidden;}    \r\n\tbool                ReplaceTexture( uint32 geomName, const char* p_SrcFileName, const char* p_DstFileName );\r\n\tbool                ReplaceTexture( uint32 geomName, const char* p_SrcFileName, uint32 DstChecksum );\r\n\tbool\t\t\t\tSetUVOffset(uint32 mat_checksum, int pass, float u_offset, float v_offset);\r\n\tbool\t\t\t\tSetUVMatrix(uint32 mat_checksum, int pass, const Mth::Matrix &mat);\r\n\tbool\t\t\t\tAllocateUVMatrixParams(uint32 mat_checksum, int pass);\r\n    bool                SetSkeleton( Gfx::CSkeleton* pSkeleton );\r\n    Mth::Matrix*\t\tGetBoneTransforms();\r\n    void\t\t\t\tEnableShadow(bool enabled);\r\n    bool\t\t\t\tRemovePolys();\r\n\tuint32 \t\t\t\tGetPolyRemovalMask();\r\n\tvoid \t\t\t\tHidePolys( uint32 polyRemovalMask );\r\n\r\n\t// way of changing object color (for general objects)\r\n\tbool\t\t\t\tModulateColor( uint32 geomName, float h, float s, float v );\r\n\tbool\t\t\t\tClearColor( uint32 geomName );\r\n\t\r\n\t// generic way of changing colors, without having to know whether\r\n\t// you've got material colors or object colors...  (used from\r\n\t// model builder)\r\n\tbool\t\t\t\tSetColor( Script::CStruct* pParams, float h, float s, float v );\r\n\tbool\t\t\t\tClearColor( Script::CStruct* pParams );\r\n\t\r\n\t// apply face texture (kind of like a texture replacement)\r\n\tbool\t\t\t\tApplyFaceTexture( Gfx::CFaceTexture* pFaceTexture, const char* pSrcTexture, uint32 geomName );\r\n\r\n    // phase this out, eventually...\r\n    int                 GetNumBones() {return m_numBones;}      // not really happy about this\r\n\r\nprotected:\r\n    ERenderMode         m_renderMode;\r\n    \r\nprotected:\r\n\t// GJ:  skeleton related stuff...  I'm not sure\r\n\t// if this is the appropriate place to store this\r\n\t// data...  maybe model should be able to query the \r\n\t// composite object for this data?\r\n\tint                 m_numBones;\r\n    Mth::Matrix*        mp_skeletonMatrices;\r\n\r\npublic:\r\n\tMth::Vector\t\t\tGetBoundingSphere();\r\n\tvoid\t\t\t\tSetBoundingSphere( const Mth::Vector& boundingSphere );\r\n\r\n\t// for skeletal models, such as cars\r\n\tNx::CHierarchyObject* GetHierarchy();\r\n\tint\t\t\t\t\tGetNumObjectsInHierarchy();\r\n\r\n\tvoid\t\t\t\tEnableShadowVolume(bool enabled);\r\n\r\nprotected:\r\n\t// TODO:  replace this with a linked list\r\n\tenum\r\n\t{\r\n\t\tMAX_GEOMS = 18\r\n\t};\r\n\tCGeom*\t\t\t\tmp_geom[MAX_GEOMS];\r\n\tNx::CTexDict*\t\tmp_geomTexDict[MAX_GEOMS];\r\n\tuint32\t\t\t\tm_geomName[MAX_GEOMS];\r\n\tuint32\t\t\t\tm_geomActiveMask;\r\n\tMth::Vector\t\t\tm_scale;\r\n\r\n\tCModelLights*\t\tmp_model_lights;\r\n\r\n\tenum\r\n\t{\r\n\t\tMAX_MESHES = 18\r\n\t};\r\n\r\n\tCMesh*\t\t\t\tmp_mesh[MAX_MESHES];\r\n\tuint32\t\t\t\tm_preloadedMeshNames[MAX_MESHES];\r\n\tuint32\t\t\t\tm_primaryMeshName;\r\n\r\n\t// remember the bounding sphere\r\n\tMth::Vector\t\t\tm_boundingSphere;\r\n\t\r\n\tbool\t\t\t\tm_boundingSphereCached:1;\r\n\tbool\t\t\t\tm_active:1;\r\n\tbool\t\t\t\tm_hidden:1;\r\n\tbool\t\t\t\tm_scalingEnabled:1;\r\n\tbool\t\t\t\tm_shadowEnabled:1;\r\n\tbool\t\t\t\tm_doShadowVolume:1;\r\n\r\n\tshort\t\t\t\tm_numGeoms;\r\n\tshort\t\t\t\tm_numMeshes;\r\n\tshort\t\t\t\tm_numPreloadedMeshes;\r\n\t\r\nprivate:\r\n    // The virtual functions will have a stub implementation\r\n    // in p_nxmodel.cpp\r\n\tvirtual\tbool\t\tplat_init_skeleton( int numBones );\r\n\tvirtual\tbool\t\tplat_set_render_mode(ERenderMode mode);\r\n\tvirtual\tbool\t\tplat_set_color(uint8 r, uint8 g, uint8 b, uint8 a);\r\n\tvirtual\tbool\t\tplat_set_visibility(uint32 mask);\r\n\tvirtual\tbool\t\tplat_set_active(bool active);\r\n    virtual bool        plat_set_scale(float scaleFactor);\r\n    virtual bool        plat_replace_texture(char* p_srcFileName, char* p_dstFileName);\r\n\tvirtual bool\t\tplat_render(Mth::Matrix* pRootMatrix, Mth::Matrix* ppBoneMatrices, int numBones);\r\n\tvirtual bool\t\tplat_prepare_materials( void );\r\n\tvirtual bool\t\tplat_refresh_materials( void );\r\n\tvirtual Mth::Vector\tplat_get_bounding_sphere();\r\n\tvirtual void\t\tplat_set_bounding_sphere( const Mth::Vector& boundingSphere );\r\n};\r\n\r\n}\r\n\r\n#endif // __GFX_NXMODEL_H__\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxNewParticle.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tskate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tNxNewParticle.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/24/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNew parametric particle system\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gfx/NxNewParticle.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic Mth::Vector extrema( Mth::Vector p0, Mth::Vector p1, Mth::Vector p2, float t1, float t2 )\r\n{\r\n\tMth::Vector e1, e2, u, a, p;\r\n\tfloat\t\tq;\r\n\r\n    e1\t= t1 * ( p2 - p0 );\r\n    e2\t= t2 * ( p1 - p0 );\r\n\tq\t= 1.0f / ( t1 * t2 * ( t2 - t1 )); \r\n\tu\t= ( t2 * e2 - t1 * e1 ) * q;\t\t\t// Intitial velocity.\r\n\ta\t= ( e1 - e2 ) * q;\t\t\t\t\t\t// Twice initial acceleration.\r\n\r\n\tfor( int i = 0; i < 3; i++ )\r\n    {\r\n\t\tfloat t\t= -0.5f * u[i] / a[i];\t\t\t\t// Time of extremum for given coordinate.\r\n\t\tp[i]\t= p0[i]  + u[i] * t + a[i] * t * t;\t// Value of coordinate at time t.\r\n    }\r\n\tp[3] = 0.0f;\r\n\r\n\treturn p;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic Mth::Vector componentwise_min( Mth::Vector& p0, Mth::Vector& p1 )\r\n{\r\n\tMth::Vector r = p0;\r\n\r\n\tif( p1[X] < p0[X] )\r\n\t\tr[X] = p1[X];\r\n\tif( p1[Y] < p0[Y] )\r\n\t\tr[Y] = p1[Y];\r\n\tif( p1[Z] < p0[Z] )\r\n\t\tr[Z] = p1[Z];\r\n\tif( p1[W] < p0[W] )\r\n\t\tr[W] = p1[W];\r\n\r\n\treturn r;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic Mth::Vector componentwise_max( Mth::Vector& p0, Mth::Vector& p1 )\r\n{\r\n\tMth::Vector r = p0;\r\n\r\n\tif( p1[X] > p0[X] )\r\n\t\tr[X] = p1[X];\r\n\tif( p1[Y] > p0[Y] )\r\n\t\tr[Y] = p1[Y];\r\n\tif( p1[Z] > p0[Z] )\r\n\t\tr[Z] = p1[Z];\r\n\tif( p1[W] > p0[W] )\r\n\t\tr[W] = p1[W];\r\n\r\n\treturn r;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCParticleParams::CParticleParams( void )\r\n{\r\n\tint i;\r\n\r\n\tm_Type = CRCD(0xdedfc057,\"NEWFLAT\");\r\n\tm_UseMidpoint = true;\r\n\tm_LocalCoord = false;\r\n\tfor( i = 0; i < vNUM_BOXES; i++ )\r\n\t{\r\n\t\tm_Radius[i] = 1.0f;\r\n\t\tm_RadiusSpread[i] = 0.0f;\r\n\r\n\t\tm_BoxPos[i][X] = 0.0f;\r\n\t\tm_BoxPos[i][Y] = 0.0f;\r\n\t\tm_BoxPos[i][Z] = 0.0f;\r\n\t\tm_BoxPos[i][W] = 0.0f;\r\n\r\n\t\tm_BoxDims[i][X] = 20.0f;\r\n\t\tm_BoxDims[i][Y] = 20.0f;\r\n\t\tm_BoxDims[i][Z] = 20.0f;\r\n\t\tm_BoxDims[i][W] = 0.0f;\r\n\r\n\t\tm_LocalBoxPos[i][X] = 0.0f;\r\n\t\tm_LocalBoxPos[i][Y] = 0.0f;\r\n\t\tm_LocalBoxPos[i][Z] = 0.0f;\r\n\t\tm_LocalBoxPos[i][W] = 0.0f;\r\n\r\n\t\tm_Color[i].r = 128;\r\n\t\tm_Color[i].g = 128;\r\n\t\tm_Color[i].b = 128;\r\n\t\tm_Color[i].a = 128;\r\n\t}\r\n\r\n\tm_MaxStreams = 2;\r\n\tm_EmitRate = 300.0f;\r\n\tm_Lifetime = 4.0f;\r\n\tm_MidpointPct = 50.0f;\r\n\t\r\n    m_UseMidcolor = false;\r\n\tm_ColorMidpointPct = 50.0f;\r\n\tm_BlendMode = CRCD(0xa86285a1,\"FixAdd\");\r\n\tm_AlphaCutoff = 1;\r\n\tm_Texture = 0;\r\n\tm_FixedAlpha = 0;\r\n\r\n\tm_LODDistance1 = 400;\r\n\tm_LODDistance2 = 401;\r\n\tm_SuspendDistance = 0;\r\n\r\n\tm_Hidden = false;\r\n\tm_Suspended = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNewParticle::CNewParticle( void )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNewParticle::~CNewParticle( void )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::CalculateBoundingVolumes( void )\r\n{\r\n\t// Calculate the bounding box.\r\n\tMth::Vector p0, p1, p2;\t\t\t\t// box centres\r\n\tMth::Vector s0, s1, s2;\t\t\t\t// box dimensions\r\n\tMth::Vector p0_lo, p1_lo, p2_lo;\t// corresponding minimum possible coords\r\n\tMth::Vector p0_hi, p1_hi, p2_hi;\t// corresponding maximum possible coords\r\n\tMth::Vector AABB_min, AABB_max;\t\t// AABB corners\r\n\tMth::Vector one( 1.0f, 1.0f, 1.0f, 1.0f );\r\n\r\n\tp0 = m_params.m_BoxPos[0];\r\n\tp1 = m_params.m_BoxPos[1];\r\n\tp2 = m_params.m_BoxPos[2];\r\n\r\n\tp0[W] = m_params.m_Radius[0];\r\n\tp1[W] = m_params.m_Radius[1];\r\n\tp2[W] = m_params.m_Radius[2];\r\n\r\n\ts0 = 0.5f * m_params.m_BoxDims[0];\r\n\ts1 = 0.5f * m_params.m_BoxDims[1];\r\n\ts2 = 0.5f * m_params.m_BoxDims[2];\r\n\r\n\ts0[W] = 0.5f * m_params.m_RadiusSpread[0];\r\n\ts1[W] = 0.5f * m_params.m_RadiusSpread[1];\r\n\ts2[W] = 0.5f * m_params.m_RadiusSpread[2];\r\n\r\n\tp0_lo = p0 - s0 - p0[W]*one - s0[W]*one;\r\n\tp1_lo = p1 - s1 - p1[W]*one - s1[W]*one; \r\n\tp2_lo = p2 - s2 - p2[W]*one - s2[W]*one;\r\n\r\n\tp0_hi = p0 + s0 + p0[W]*one + s0[W]*one;\r\n\tp1_hi = p1 + s1 + p1[W]*one + s1[W]*one;\r\n\tp2_hi = p2 + s2 + p2[W]*one + s2[W]*one;\r\n\r\n\tAABB_min = componentwise_min( p0_lo, p2_lo );\r\n\tAABB_max = componentwise_max( p0_hi, p2_hi );\r\n\r\n\tif( m_params.m_UseMidpoint )\r\n\t{ \r\n\t\tMth::Vector p;\r\n\r\n\t\tp = extrema( p0_lo, p1_lo, p2_lo,\r\n\t\t\t\t\tm_params.m_Lifetime * m_params.m_MidpointPct * 0.01f,\r\n\t\t\t\t\tm_params.m_Lifetime );\r\n\r\n\t\tAABB_min = componentwise_min( AABB_min, p ); \r\n\t \r\n\t\tp = extrema( p0_hi, p1_hi, p2_hi,\r\n\t\t\t\t\tm_params.m_Lifetime * m_params.m_MidpointPct * 0.01f,\r\n\t\t\t\t\tm_params.m_Lifetime );\r\n\r\n\t\tAABB_max = componentwise_max( AABB_max, p ); \r\n\t}\r\n\r\n\t// Set the bounding box.\r\n\tm_bbox.Set( AABB_min, AABB_max );\r\n\r\n\t// Now calculate the bounding sphere.\r\n\tMth::Vector diag\t\t= ( AABB_max - AABB_min ) * 0.5f;\r\n\tdiag[W]\t\t\t\t\t= 0.0f;\r\n\tm_bsphere\t\t\t\t= AABB_min + diag;\r\n\tm_bsphere[W]\t\t\t= diag.Length();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::Initialize( CParticleParams* params )\r\n{\r\n\tm_params = *params;\r\n\tCalculateBoundingVolumes();\r\n\tplat_build();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCParticleParams*\tCNewParticle::GetParameters( void )\r\n{\r\n\treturn &m_params;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::Render( void )\r\n{\r\n\tif (!m_params.m_Hidden && !m_params.m_Suspended  )\r\n\t{\r\n\t\tplat_render();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::Update( void )\r\n{\r\n\tif (!m_params.m_Hidden && !m_params.m_Suspended)\r\n\t{\r\n\t\tplat_update();\r\n\t}\r\n\t\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::Destroy( void )\r\n{\r\n\tplat_destroy();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::Hide( bool  should_hide )\r\n{\r\n\tif (m_params.m_Hidden != should_hide)\r\n\t{\r\n\t\tm_params.m_Hidden = should_hide;\r\n\t\tplat_hide(should_hide);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n\r\nvoid\tCNewParticle::Suspend( bool\tshould_suspend )\r\n{\r\n\tif (m_params.m_Suspended != should_suspend)\r\n\t{\r\n\t\t// if we were not hidden, then hide/unhide based on the value of the suspend flag\r\n\t\tif (!m_params.m_Hidden)\r\n\t\t{\r\n\t\t\tplat_hide(should_suspend);\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::SetEmitRate( float emit_rate )\r\n{\r\n\tm_params.m_EmitRate = emit_rate;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::SetLifetime( float lifetime )\r\n{\r\n\tm_params.m_Lifetime = lifetime;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::SetMidpointPct( float midpoint_pct )\r\n{\r\n\tm_params.m_MidpointPct = midpoint_pct;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::SetRadius( int which, float radius )\r\n{\r\n\tDbg_Assert( which < vNUM_BOXES );\r\n\r\n\tm_params.m_Radius[which] = radius;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::SetBoxPos( int which, Mth::Vector* pos )\r\n{\r\n\tDbg_Assert( pos );\r\n\tDbg_Assert( which < vNUM_BOXES );\r\n\r\n\tm_params.m_BoxPos[which] = *pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::SetBoxDims( int which, Mth::Vector* dims )\r\n{\r\n\tDbg_Assert( dims );\r\n\tDbg_Assert( which < vNUM_BOXES );\r\n\r\n\tm_params.m_BoxDims[which] = *dims;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::SetColor( int which, Image::RGBA* color )\r\n{\r\n\tDbg_Assert( which < vNUM_BOXES );\r\n\tDbg_Assert( color );\r\n\r\n\tm_params.m_Color[which] = *color;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::SetMidpointColorPct( float midpoint_pct )\r\n{\r\n\tm_params.m_ColorMidpointPct = midpoint_pct;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::plat_render( void )\r\n{\r\n\tDbg_Printf( \"STUB: plat_render\\n\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::plat_update( void )\r\n{\r\n\tDbg_Printf( \"STUB: plat_update\\n\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::plat_build( void )\r\n{\r\n\tDbg_Printf( \"STUB: plat_build\\n\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::plat_destroy( void )\r\n{\r\n\tDbg_Printf( \"STUB: plat_destroy\\n\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCNewParticle::plat_hide( bool should_hide )\r\n{\r\n\tDbg_Printf( \"STUB: plat_destroy\\n\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxNewParticle.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tNxNewParticle.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/24/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNew parametric particle system  \t \t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_NXNEWPARTICLE_H__\r\n#define __GFX_NXNEWPARTICLE_H__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n\r\n#include <gfx/image/imagebasic.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n\t\t\t\t\t\t\r\nenum\r\n{\r\n\tvBOX_START,\r\n\tvBOX_MID,\r\n\tvBOX_END,\r\n\tvNUM_BOXES\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CParticleParams\r\n{\r\npublic:\r\n\tCParticleParams( void );\r\n\r\n\t// Particle Params\r\n\tuint32\t\t\tm_Name;\r\n\tuint32\t\t\tm_Type;\t// NEWFLAT is the only one for now\r\n\tbool\t\t\tm_UseMidpoint;\r\n\tfloat\t\t\tm_Radius[vNUM_BOXES];\r\n\tfloat\t\t\tm_RadiusSpread[vNUM_BOXES];\r\n\tint\t\t\t\tm_MaxStreams;\r\n\tfloat\t\t\tm_EmitRate;\r\n\tfloat\t\t\tm_Lifetime;\t\t// in seconds\r\n\tfloat\t\t\tm_MidpointPct;\t// percent of lifetime at which midpoint occurs\r\n\r\n\t// Spatial params\r\n\tMth::Matrix\t\tm_RotMatrix;\r\n\tMth::Vector\t\tm_BoxPos[vNUM_BOXES];\r\n\tMth::Vector\t\tm_BoxDims[vNUM_BOXES];\r\n\r\n\t// Local data (CParticleComponent is the only class that supports this)\r\n\tbool\t\t\tm_LocalCoord;\r\n\tMth::Vector\t\tm_LocalBoxPos[vNUM_BOXES];\r\n\r\n\t// Color params\r\n\tbool\t\t\tm_UseMidcolor;\r\n\tfloat\t\t\tm_ColorMidpointPct;\t// percent of lifetime at which midcolor occurs\r\n\tImage::RGBA\t\tm_Color[vNUM_BOXES];\r\n\r\n\t// Material params\r\n\tuint32\t\t\tm_BlendMode;\r\n\tint\t\t\t\tm_FixedAlpha;\r\n\tint\t\t\t\tm_AlphaCutoff;\r\n\tuint32\t\t\tm_Texture;\r\n\r\n\t// LOD params\r\n\tint\t\t\t\tm_LODDistance1;\r\n\tint\t\t\t\tm_LODDistance2;\r\n\tint\t\t\t\tm_SuspendDistance;\r\n\r\n\t// Hidden flag\r\n\tbool\t\t\tm_Hidden;\r\n\tbool\t\t\tm_Suspended;\r\n\r\n};\r\n\r\nclass CNewParticle\r\n{\r\npublic:\r\n\tCNewParticle( void );\r\n\tvirtual\t~CNewParticle( void );\r\n\r\n\tvoid\tInitialize( CParticleParams* params );\r\n\tCParticleParams*\tGetParameters( void );\r\n\r\n\tvoid\tSetEmitRate( float emit_rate );\r\n\tvoid\tSetLifetime( float lifetime );\r\n\tvoid\tSetMidpointPct( float midpoint_pct );\r\n\tvoid\tSetMidpointColorPct( float midpoint_pct );\r\n\r\n\tvoid\tSetRadius( int which, float radius );\r\n\tvoid\tSetBoxPos( int which, Mth::Vector* pos );\r\n\tvoid\tSetBoxDims( int which, Mth::Vector* dims );\r\n\tvoid\tSetColor( int which, Image::RGBA* color );\r\n\t\r\n\tvoid\tCalculateBoundingVolumes( void );\r\n\r\n\tvoid\tRender( void );\r\n\tvoid\tUpdate( void );\r\n\tvoid\tDestroy( void );\r\n\tvoid\tHide(bool should_hide);\r\n\tvoid\tSuspend( bool\tshould_suspend );\r\n\t\r\n\tuint32\tGetName() {return m_params.m_Name;}\r\n\t\r\nprotected:\r\n\t\r\n\tCParticleParams\tm_params;\r\n\r\n\tMth::CBBox\t\tm_bbox;\r\n\tMth::Vector\t\tm_bsphere;\r\n\r\n\tvirtual void\tplat_build( void );\r\n\tvirtual void\tplat_destroy( void );\r\n\tvirtual void\tplat_hide( bool should_hide );\r\n\tvirtual\tvoid\tplat_render( void );\r\n\tvirtual\tvoid\tplat_update( void );\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n#endif\t// __GFX_NXNEWPARTICLE_H__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxNewParticleMgr.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tNxNewParticleMgr.cpp\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/24/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNew parametric particle system manager\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gfx/NxNewParticleMgr.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCNewParticle*\tCNewParticleManager::plat_create_particle( void )\r\n{\r\n\tDbg_Assert( 0 );\r\n\tDbg_Printf( \"Stub plat_create_particle\\n\" );\r\n\treturn NULL;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCNewParticleManager::CNewParticleManager( void )\r\n{\r\n\tmp_particle_table = new Lst::HashTable< CNewParticle >( 8 );\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNewParticleManager::~CNewParticleManager( void )\r\n{\r\n\tdelete mp_particle_table;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNewParticle*\tCNewParticleManager::CreateParticle( CParticleParams* params, bool generate_name )\r\n{\r\n\tCNewParticle* particle;\r\n\t \r\n\tparticle = plat_create_particle();\r\n\tif( particle )\r\n\t{\r\n\t\tif( generate_name )\r\n\t\t{\r\n\t\t\tuint32 name;\r\n\r\n\t\t\tname = params->m_Name;\r\n\t\t\t// Ensure a unique name for this system\r\n\t\t\twhile(( mp_particle_table->GetItem( name, false ) != NULL ))\r\n\t\t\t{\r\n\t\t\t\tname++;\r\n\t\t\t}\r\n\r\n\t\t\tparams->m_Name = name;\r\n\t\t}\r\n\r\n\t\tparticle->Initialize( params );\r\n\t\tmp_particle_table->PutItem( params->m_Name, particle );\r\n\t}\r\n\r\n\treturn particle;\r\n}\r\n\r\n// Given an actual particle system\r\n// remove it from the Particle\r\nvoid\tCNewParticleManager::KillParticle( CNewParticle* p_particle)\r\n{\r\n\tDbg_MsgAssert(p_particle,(\"NULL p_particle passed to KillParticle\"));\r\n\tDbg_MsgAssert(mp_particle_table->GetItem(p_particle->GetName()) == p_particle,(\"entry in particle table for %s does not match where it came from\",Script::FindChecksumName(p_particle->GetName())));\t\r\n\tmp_particle_table->FlushItem(p_particle->GetName());\t\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCNewParticleManager::RenderParticles( void )\r\n{\r\n\tmp_particle_table->IterateStart();\r\n\tCNewParticle *p_particle = mp_particle_table->IterateNext();\r\n\twhile( p_particle )\r\n\t{\r\n\t\tp_particle->Render();\r\n\t\tp_particle = mp_particle_table->IterateNext();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCNewParticleManager::UpdateParticles( void )\r\n{\r\n\tmp_particle_table->IterateStart();\r\n\tCNewParticle *p_particle = mp_particle_table->IterateNext();\r\n\twhile( p_particle )\r\n\t{\r\n\t\tp_particle->Update();\r\n\t\tp_particle = mp_particle_table->IterateNext();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \t\t\tCNewParticleManager::Cleanup( void )\r\n{\r\n\t// Goes through and removes all particle systems.\r\n\tmp_particle_table->IterateStart();\r\n\tCNewParticle *p_particle = mp_particle_table->IterateNext();\r\n\twhile( p_particle )\r\n\t{\r\n\t\tCNewParticle *p_next\t= mp_particle_table->IterateNext();\r\n\t\tp_particle->Destroy();\r\n\t\tdelete p_particle;\r\n\t\tp_particle\t\t= p_next;\r\n\t}\r\n\tmp_particle_table->FlushAllItems();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxNewParticleMgr.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tNxNewParticleMgr.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/24/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNew parametric particle system manager\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_NXNEWPARTICKEMGR_H__\r\n#define __GFX_NXNEWPARTICKEMGR_H__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/hashtable.h>\r\n#include <gfx/nxnewparticle.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CNewParticleManager\r\n{\r\npublic:\r\n\tCNewParticleManager( void );\r\n\tvirtual\t~CNewParticleManager( void );\r\n\r\n\tCNewParticle*\tCreateParticle( CParticleParams* params, bool generate_name = false );\r\n\tvoid\t\t\tKillParticle( CNewParticle* p_particle );\r\n\tvoid\t\t\tRenderParticles( void );\r\n\tvoid\t\t\tUpdateParticles( void );\r\n\tvoid\t\t\tCleanup( void );\r\n\r\nprotected:\r\n\r\n\tLst::HashTable< CNewParticle >\t*mp_particle_table;\r\n\r\nprivate:\r\n\tvirtual\tCNewParticle*\tplat_create_particle( void );\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n#endif\t// __GFX_NXNEWPARTICKEMGR_H__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxQuickAnim.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       quickanim.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/4/2003\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/nxquickanim.h>\r\n\r\n#include <gfx/bonedanim.h>\r\n#include <gfx/nxanimcache.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float quatDown(short theSource)\r\n{\r\n    return (float)(theSource / 16384.0f);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float transDown(short theSource, float scaleFactor)\r\n{\r\n    return (float)(theSource / scaleFactor);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void get_rotation_from_key( Gfx::CAnimQKey* p_in, Mth::Quat* pQuat, bool isHiRes )\r\n{\r\n\tif ( isHiRes )\r\n\t{\r\n\t\t(*pQuat)[X] = ((Gfx::CHiResAnimQKey*)p_in)->qx;\r\n\t\t(*pQuat)[Y] = ((Gfx::CHiResAnimQKey*)p_in)->qy;\r\n\t\t(*pQuat)[Z] = ((Gfx::CHiResAnimQKey*)p_in)->qz;\r\n//  \t(*pQuat)[W] = ((Gfx::CHiResAnimQKey*)p_in)->qw;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t(*pQuat)[X] = quatDown( ((Gfx::CStandardAnimQKey*)p_in)->qx );\r\n\t\t(*pQuat)[Y] = quatDown( ((Gfx::CStandardAnimQKey*)p_in)->qy );\r\n\t\t(*pQuat)[Z] = quatDown( ((Gfx::CStandardAnimQKey*)p_in)->qz );\r\n//\t\t(*pQuat)[W] = quatDown( ((Gfx::CStandardAnimQKey*)p_in)->qw );\r\n\t}\r\n\t\r\n\tfloat qx = (*pQuat)[X];\r\n\tfloat qy = (*pQuat)[Y];\r\n\tfloat qz = (*pQuat)[Z];\r\n\r\n\t// Dave note: added 09/12/02 - a simple check to ensure we don't try to take the square root of a negative\r\n\t// number, which will hose Nan-sensitive platforms later on...\r\n\tfloat sum\t= 1.0f - qx * qx - qy * qy - qz * qz;\r\n\t(*pQuat)[W] = sqrtf (( sum < 0.0f ) ? 0.0f : sum );\r\n\t\r\n\tif ( p_in->signBit )\r\n\t{\r\n\t\t(*pQuat)[W] = -(*pQuat)[W];\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void get_translation_from_key( Gfx::CAnimTKey* p_in, Mth::Vector* pVector, bool isHiRes )\r\n{\r\n\tif ( isHiRes )\r\n\t{\r\n\t\t(*pVector)[X] = ((Gfx::CHiResAnimTKey*)p_in)->tx;\r\n\t\t(*pVector)[Y] = ((Gfx::CHiResAnimTKey*)p_in)->ty;\r\n\t\t(*pVector)[Z] = ((Gfx::CHiResAnimTKey*)p_in)->tz;\r\n\t\t(*pVector)[W] = 1.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t(*pVector)[X] = transDown( ((Gfx::CStandardAnimTKey*)p_in)->tx, 32.0f );\r\n\t\t(*pVector)[Y] = transDown( ((Gfx::CStandardAnimTKey*)p_in)->ty, 32.0f );\r\n\t\t(*pVector)[Z] = transDown( ((Gfx::CStandardAnimTKey*)p_in)->tz, 32.0f );\r\n\t\t(*pVector)[W] = 1.0f;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float get_alpha( float timeStamp1, float timeStamp2, float time )\r\n{\r\n\tDbg_MsgAssert(timeStamp1 <= time && timeStamp2 >= time, ( \"%f should be within [%f %f]\", time, timeStamp1, timeStamp2 ));\r\n    \r\n\treturn (( time - timeStamp1 ) / ( timeStamp2 - timeStamp1 ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t\t  \r\ninline void interpolate_q_frame(Mth::Quat* p_out, Gfx::CAnimQKey* p_in1, Gfx::CAnimQKey* p_in2, float alpha, bool isHiRes)\r\n{\r\n\tDbg_Assert(p_out);\r\n\tDbg_Assert(p_in1);\r\n\tDbg_Assert(p_in2);\r\n\r\n\tMth::Quat\tqIn1;\r\n\tget_rotation_from_key( p_in1, &qIn1, isHiRes );\r\n\r\n\tif ( alpha == 0.0f )\r\n\t{\r\n\t\t// don't need to slerp, because it's the start time\r\n\t\t*p_out = qIn1; \r\n\t\treturn;\r\n\t}\r\n\r\n\tMth::Quat   qIn2;\r\n\tget_rotation_from_key( p_in2, &qIn2, isHiRes );\r\n    \r\n\tif ( alpha == 1.0f )\r\n\t{\r\n\t\t// don't need to slerp, because it's the end time\r\n\t\t*p_out = qIn2; \r\n\t\treturn;\r\n\t}\r\n\r\n\t// fast slerp, stolen from game developer magazine\r\n\t*p_out = Mth::FastSlerp( qIn1, qIn2, alpha );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void interpolate_t_frame(Mth::Vector* p_out, Gfx::CAnimTKey* p_in1, Gfx::CAnimTKey* p_in2, float alpha, bool isHiRes)\r\n{\r\n\tDbg_Assert(p_out);\r\n\tDbg_Assert(p_in1);\r\n\tDbg_Assert(p_in2);\r\n    \r\n\t// INTERPOLATE T-COMPONENT\r\n    Mth::Vector   tIn1;\t\t\t\t\t  \r\n\tget_translation_from_key( p_in1, &tIn1, isHiRes );\r\n\r\n\tif ( alpha == 0.0f )\r\n\t{\r\n\t\t// don't need to lerp, because it's the start time\r\n\t\t*p_out = tIn1; \r\n\t\treturn;\r\n\t}\r\n\r\n\tMth::Vector   tIn2;\r\n\tget_translation_from_key( p_in2, &tIn2, isHiRes );\r\n\r\n\tif ( alpha == 1.0f )\r\n\t{\r\n\t\t// don't need to slerp, because it's the end time\r\n\t\t*p_out = tIn2; \r\n\t\treturn;\r\n\t}\r\n\r\n    /* Linearly interpolate positions */\r\n    *p_out = Mth::Lerp( tIn1, tIn2, alpha );\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stub versions of all platform specific functions are provided here:\r\n// so engine implementors can leave certain functionality until later\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CQuickAnim::plat_get_interpolated_frames( Mth::Quat* pRotations, Mth::Vector* pTranslations, uint32* pSkipList, uint32 skipIndex, float time )\r\n{\r\n\tDbg_MsgAssert( mp_frameData, ( \"No pointer to frame data\" ) );\r\n\r\n/*\r\n\t// this optimization doesn't really speed things up at all,\r\n\t// since the time-consuming part is walking through the compressed\r\n\t// key lists in CBonedAnimFrameData::GetCompressedInterpolatedFrames.\r\n\t// i've commented this out for now until I have more time\r\n\t// to figure out a better alternative...\r\n\t\r\n\tif ( m_quickAnimPointers.valid )\r\n\t{\r\n\t\tfloat timeStamp = time * 60.0f;\r\n\t\tint numBones = mp_frameData->GetNumBones();\r\n\t\tMth::Quat* pCurrRotations = pRotations;\r\n\t\tMth::Vector* pCurrTranslations = pTranslations;\r\n\r\n\t\tfor ( int i = 0; i < numBones; i++ )\r\n\t\t{\r\n\t\t\tm_quickAnimPointers.qSkip[i] = false;\r\n\r\n\t\t\tGfx::CAnimQKey* pStartQKey = &m_quickAnimPointers.theStartQKey[i];\r\n\t\t\tGfx::CAnimQKey* pEndQKey = &m_quickAnimPointers.theEndQKey[i];\r\n\r\n\t\t\t// if the two adjacent keys haven't changed,\r\n\t\t\t// then we can use the optimization\r\n\t\t\tif ( timeStamp >= (int)pStartQKey->timestamp && timeStamp <= (int)pEndQKey->timestamp )\r\n\t\t\t{\r\n\t\t\t\tfloat qAlpha = get_alpha( (float)pStartQKey->timestamp, (float)pEndQKey->timestamp, timeStamp );\r\n\r\n\t\t\t\tinterpolate_q_frame( pCurrRotations, \r\n\t\t\t\t\t\t\t\t pStartQKey, \r\n\t\t\t\t\t\t\t\t pEndQKey,\r\n\t\t\t\t\t\t\t\t qAlpha,\r\n\t\t\t\t\t\t\t\t false );\r\n\r\n\t\t\t\tm_quickAnimPointers.qSkip[i] = true;\r\n\t\t\t}\r\n\r\n\t\t\tpCurrRotations++;\r\n\r\n\t\t\tm_quickAnimPointers.tSkip[i] = false;\r\n\r\n\t\t\tGfx::CAnimTKey* pStartTKey = &m_quickAnimPointers.theStartTKey[i];\r\n\t\t\tGfx::CAnimTKey* pEndTKey = &m_quickAnimPointers.theEndTKey[i];\r\n\r\n\t\t\t// if the two adjacent keys haven't changed,\r\n\t\t\t// then we can use the optimization\r\n\t\t\tif ( timeStamp >= (int)pStartTKey->timestamp && timeStamp <= (int)pEndTKey->timestamp )\r\n\t\t\t{\r\n\t\t\t\tfloat tAlpha = get_alpha( (float)pStartTKey->timestamp, (float)pEndTKey->timestamp, timeStamp );\r\n\r\n\t\t\t\tinterpolate_t_frame( pCurrTranslations, \r\n\t\t\t\t\t\t\t\t pStartTKey, \r\n\t\t\t\t\t\t\t\t pEndTKey,\r\n\t\t\t\t\t\t\t\t tAlpha,\r\n\t\t\t\t\t\t\t\t false );\r\n\r\n\t\t\t\tm_quickAnimPointers.tSkip[i] = true;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tpCurrTranslations++;\r\n\t\t}\r\n\t}\r\n*/\r\n\r\n\r\n\r\n\tm_quickAnimPointers.pSkipList\t= pSkipList;\r\n\tm_quickAnimPointers.skipIndex\t= skipIndex;\r\n\t\r\n\tDbg_MsgAssert( mp_frameData, ( \"No frame data\" ) );\r\n\tmp_frameData->GetInterpolatedFrames(pRotations, pTranslations, time, this);\r\n\t\r\n\tm_quickAnimPointers.valid = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCQuickAnim::CQuickAnim()\r\n{\r\n\tmp_frameData = NULL;\r\n\tm_quickAnimPointers.valid = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCQuickAnim::~CQuickAnim()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CQuickAnim::Enable( bool enabled )\r\n{\r\n\tm_quickAnimPointers.valid = enabled;\r\n\r\n\t// if the cache is invalid, then regrab the pointer to the anim\r\n\tif ( !enabled )\r\n\t{\r\n\t\tmp_frameData = Nx::GetCachedAnim( m_animAssetName, true );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CQuickAnim::SetAnimAssetName( uint32 animAssetName )\r\n{\r\n\tm_animAssetName = animAssetName;\r\n\t\r\n\t// set the pointer to the animation\r\n\tmp_frameData = Nx::GetCachedAnim( m_animAssetName, true );\r\n\t\r\n\t// invalidate the cache\r\n\tEnable(false);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// These functions are the platform independent part of the interface to \r\n// the platform specific code\r\n// parameter checking can go here....\r\n// although we might just want to have these functions inline, or not have them at all?\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CQuickAnim::GetInterpolatedFrames( Mth::Quat* pRotations, Mth::Vector* pTranslations, uint32* pSkipList, uint32 skipIndex, float time )\r\n{\r\n\tplat_get_interpolated_frames( pRotations, pTranslations, pSkipList, skipIndex, time );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CQuickAnim::GetInterpolatedHiResFrames( Mth::Quat* pRotations, Mth::Vector* pTranslations, float time )\r\n{\r\n\tDbg_MsgAssert( mp_frameData, ( \"No pointer to frame data\" ) );\r\n\r\n\tmp_frameData->GetInterpolatedCameraFrames(pRotations, pTranslations, time, this);\r\n\t\r\n\tm_quickAnimPointers.valid = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CQuickAnim::GetNumBones()\r\n{\r\n\tDbg_MsgAssert( mp_frameData, ( \"No pointer to frame data\" ) );\r\n\r\n\treturn mp_frameData->GetNumBones();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CQuickAnim::ResetCustomKeys()\r\n{\r\n\tDbg_MsgAssert( mp_frameData, ( \"No pointer to frame data\" ) );\r\n\r\n\tmp_frameData->ResetCustomKeys();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CQuickAnim::GetDuration()\r\n{\r\n\tDbg_MsgAssert( mp_frameData, ( \"No pointer to frame data\" ) );\r\n\r\n\treturn mp_frameData->GetDuration();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nuint32 CQuickAnim::GetBoneName( int i )\r\n{\r\n\tDbg_MsgAssert( mp_frameData, ( \"No pointer to frame data\" ) );\r\n\r\n\treturn mp_frameData->GetBoneName( i );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CQuickAnim::ProcessCustomKeys( float startTimeInclusive, float endTimeInclusive, Obj::CObject* pObject )\r\n{\r\n\tDbg_MsgAssert( mp_frameData, ( \"No pointer to frame data\" ) );\r\n\r\n\tbool inclusive = true;\r\n\treturn mp_frameData->ProcessCustomKeys( startTimeInclusive, endTimeInclusive, pObject, inclusive );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxQuickAnim.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       NxQuickAnim.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/4/2003\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_NXQUICKANIM_H__\r\n#define\t__GFX_NXQUICKANIM_H__\r\n\r\n// The CQuickAnim is a per-object interface to the CBonedAnimFrameData\r\n// (which is raw animation data).  Because multiple objects can be playing \r\n// the same animation at the same time, we can't do anything fancy like \r\n// caching pointers inside the CBonedAnimFrameData;  however, since each \r\n// object has its own CQuickAnim, we can store pointers or decompress data\r\n// or whatever here.  I've decided to give this class a p-line interface\r\n// so that different platforms can implement different optimizations\r\n// based on whether speed or memory is the bottleneck.  \t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gfx/bonedanimtypes.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\tclass CBonedAnimFrameData;\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\tclass CObject;\r\n}\r\n\r\nnamespace Mth\r\n{\r\n\tclass Quat;\r\n\tclass Vector;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CQuickAnim : public Spt::Class\r\n{\r\npublic:\r\n\tCQuickAnim();\r\n\tvirtual ~CQuickAnim();\r\n\r\npublic:\r\n\tvoid\t\t\t\t\t\tSetAnimAssetName( uint32 animAssetName );\r\n\tvoid\t\t\t\t\t\tGetInterpolatedFrames( Mth::Quat* pRotations, Mth::Vector* pTranslations, uint32* pSkipList, uint32 skipIndex, float time );\r\n\tvoid\t\t\t\t\t\tGetInterpolatedHiResFrames( Mth::Quat* pRotations, Mth::Vector* pTranslations, float time );\r\n\tvoid\t\t\t\t\t\tEnable(bool enabled);\r\n\tint\t\t\t\t\t\t\tGetNumBones();\r\n\tvoid\t\t\t\t\t\tResetCustomKeys();\r\n\tfloat\t\t\t\t\t\tGetDuration();\r\n\tuint32\t\t\t\t\t\tGetBoneName( int i );\r\n\tbool\t\t\t\t\t\tProcessCustomKeys( float startTimeInclusive, float endTimeExclusive, Obj::CObject* pObject );\r\n\r\nprivate:\r\n    // The virtual functions will have a stub implementation in p_nxquickanim.cpp\r\n\tvirtual\tvoid\t\t\t\tplat_get_interpolated_frames( Mth::Quat* pRotations, Mth::Vector* pTranslations, uint32* pSkipList, uint32 skipIndex, float time );\r\n\r\nprotected:\r\n\tGfx::CBonedAnimFrameData*\tmp_frameData;\r\n\tuint32\t\t\t\t\t\tm_animAssetName;\r\n\r\npublic:\r\n\tGfx::SQuickAnimPointers\t\tm_quickAnimPointers;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // namespace Gfx\r\n\r\n#endif\t// __GFX_NXQUICKANIM_H__\r\n"
  },
  {
    "path": "Code/Gfx/NxScene.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// NX.CPP - Platform independent interface to the platfrom specific engine code \r\n\r\n#include \"gfx/nx.h\"\r\n#include \"gfx/NxSector.h\"\r\n#include \"gfx/NxTexMan.h\"\r\n\r\n#include \"core/debug.h\"\r\n\r\n#include <gel/collision/collision.h>\r\n#include <gel/collision/colltridata.h>\r\n\r\n\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/pip.h>\r\n\r\n#include <gel/scripting/script.h>\t   \r\n#include <gel/scripting/struct.h>\t   \r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\n#include <gfx\\nxgeom.h>\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n// For wireframe debuging mode\r\n#include <gfx\\ngps\\nx\\line.h>\r\n#include <gfx\\ngps\\nx\\geomnode.h>\r\n#include <gfx\\ngps\\p_nxgeom.h>\r\n#include <gfx\\ngps\\p_nxscene.h>\r\n#endif\r\n\r\n#include <gfx\\nxweather.h>\r\n\r\nnamespace\tNx\r\n{\r\n\r\n///////////////////////////////////////////////////////////////////\r\n// CScene definitions\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCScene::CScene( int sector_table_size ) : mp_sector_man(NULL)\r\n{\r\n\tmp_sector_table = new Lst::HashTable< CSector >( sector_table_size );\r\n\r\n//\tDbg_MsgAssert(0,(\"secotr-tabel_size = %d\\n\",sector_table_size))\r\n\r\n\tm_scene_filename[0] = '\\0';\r\n\t\r\n\t// Initilizing supersector and collision crap to NULL, as \r\n\t// we might not have any (like for skys and background stuff)\r\n\tmp_sector_man = NULL;\r\n\tmp_coll_sectors = NULL;\r\n\tmp_coll_sector_data = NULL;\r\n\tm_num_coll_sectors = 0;\r\n\r\n\t// Incremental update\r\n\tm_add_scene_filename[0] = '\\0';\r\n\tmp_add_tex_dict = NULL; \r\n\tmp_add_coll_sectors = NULL;\r\n\tmp_add_coll_sector_data = NULL;\r\n\tm_num_add_coll_sectors = 0;\r\n\r\n\tm_using_add_sectors = false;\r\n\tmp_orig_sectors = new Lst::Head < CSector >;\r\n\tmp_add_sectors = new Lst::Head < CSector >;\r\n\r\n\tm_in_super_sectors = false;\r\n\tm_sky = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCScene::~CScene()\r\n{\r\n\r\n\t// Mick: iterate over all the sectors, and delete them\r\n\t// (deleting the mp_sector_table just deletes the references to them)\r\n\tif (mp_sector_table)\r\n\t{\r\n\t\tmp_sector_table->IterateStart();\r\n\t\tCSector *p_sector;\r\n\t\twhile ((p_sector = mp_sector_table->IterateNext()))\r\n\t\t{\r\n\t\t\tp_sector->clear_flags(CSector::mIN_SUPER_SECTORS);\t// Tells cloned sectors it is OK to go away (and SuperSectors will be dead, anyway)\r\n\t\t\tdelete p_sector;\r\n\t\t}\r\n\t\tdelete mp_sector_table;\r\n\t}\r\n\t\r\n\t// Remove SuperSectors\r\n\tif (mp_sector_man)\r\n\t{\r\n\t\tdelete mp_sector_man;\r\n\t}\r\n\t\r\n\t// Remove Collision\r\n\tif (mp_coll_sectors)\r\n\t{\r\n\t\tdelete[] mp_coll_sectors;\r\n\t}\r\n\r\n\tif (mp_coll_sector_data)\r\n\t{\r\n\t\tPip::Unload(m_coll_filename);\r\n\t}\r\n\r\n\t// And the toggle list heads\r\n\tif (mp_orig_sectors)\r\n\t{\r\n\t\tdelete mp_orig_sectors;\r\n\t}\r\n\r\n\tif (mp_add_sectors)\r\n\t{\r\n\t\tdelete mp_add_sectors;\r\n\t}\r\n\r\n\t// Check if additional texture dictionary was loaded\r\n\tif (mp_add_tex_dict) \r\n\t{\r\n\t\tNx::CTexDictManager::sUnloadTextureDictionary(mp_add_tex_dict);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCScene::UnloadAddScene()\r\n{\r\n\tif (m_using_add_sectors)\r\n\t{\r\n\t   \tToggleAddScene();\r\n\t}\r\n\r\n\tif (!plat_unload_add_scene())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (mp_add_coll_sectors)\r\n\t{\r\n\t\tdelete[] mp_add_coll_sectors;\r\n\t}\r\n\r\n\tif (mp_add_coll_sector_data)\r\n\t{\r\n\t\tPip::Unload(m_add_coll_filename);\r\n\t}\r\n\r\n\tif (mp_orig_sectors)\r\n\t{\r\n\t\tLst::Node< CSector > *obj_node, *next;\r\n\r\n\t\tfor(obj_node = mp_orig_sectors->GetNext(); obj_node; obj_node = next)\r\n\t\t{\r\n\t\t\tnext = obj_node->GetNext();\r\n\r\n\t\t\tdelete obj_node;\r\n\t\t}\r\n\t}\r\n\r\n\tif\t(mp_add_sectors)\r\n\t{\r\n\t\tLst::Node< CSector > *obj_node, *next;\r\n\r\n\t\tfor(obj_node = mp_add_sectors->GetNext(); obj_node; obj_node = next)\r\n\t\t{\r\n\t\t\tnext = obj_node->GetNext();\r\n\r\n\t\t\tDeleteSector(obj_node->GetData());\t\t// And delete the sector itself\r\n\t\t\tdelete obj_node;\r\n\t\t}\r\n\t}\r\n\r\n\tm_using_add_sectors = false;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSector * \t\tCScene::GetSector(uint32 sector_checksum)\r\n{\r\n\treturn mp_sector_table->GetItem(sector_checksum);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \t\t\tCScene::AddSector(CSector *pSector)\r\n{\r\n\tmp_sector_table->PutItem(pSector->GetChecksum(), pSector);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSector *\t\tCScene::ReplaceSector(CSector *pSector)\r\n{\r\n\tCSector *p_old_sector = mp_sector_table->GetItem(pSector->GetChecksum());\r\n\r\n\t// Possibly delete old sector\r\n\tif (p_old_sector)\r\n\t{\r\n\t\t//if (p_old_sector->get_flags() & CSector::mCLONE)\r\n\t\t//{\r\n\t\t//\tDeleteSector(p_old_sector);\r\n\t\t//} else {\r\n\t\t\tremove_sector_from_table(p_old_sector->GetChecksum());\t// can't delete something that is PIP'ed in\r\n\t\t\tp_old_sector->SetActive(false);\r\n\t\t//}\r\n\r\n\t\t// We also want this out of the SuperSectors\r\n\t\tp_old_sector->set_flags(CSector::mREMOVE_FROM_SUPER_SECTORS);\r\n\r\n\t\t// Also add to orig list\r\n\t\tLst::Node<CSector> *node = new Lst::Node<CSector>(p_old_sector);\r\n\t\tmp_orig_sectors->AddToTail(node);\r\n\r\n\t\tDbg_Message(\"Replacing sector %x\", pSector->GetChecksum());\r\n\t} else {\r\n\t\tDbg_Message(\"Adding sector %x\", pSector->GetChecksum());\r\n\t}\r\n\r\n\t// And add new one\r\n\t// Garrett TODO: Should I check to see if there is a CCollObj here?  Or UpdateSuperSectors()?  Or does it matter?\r\n\tpSector->set_flags(CSector::mADD_TO_SUPER_SECTORS);\t\t\t// And do an UpdateSuperSectors() after all the calls\r\n\tAddSector(pSector);\r\n\r\n\tLst::Node<CSector> *node = new Lst::Node<CSector>(pSector);\r\n\tmp_add_sectors->AddToTail(node);\r\n\r\n\treturn p_old_sector;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCScene::ToggleAddScene()\r\n{\r\n\tif (mp_add_sectors->CountItems() == 0)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tLst::Head < CSector > *p_on_sectors, *p_off_sectors;\r\n\tLst::Node< CSector > *obj_node, *next;\r\n\tCSector *p_sector;\r\n\r\n\t// Do actual toggle\r\n\tm_using_add_sectors = !m_using_add_sectors;\r\n\r\n\t// Figure out which to turn on and off\r\n\tif (m_using_add_sectors)\r\n\t{\r\n\t\tp_on_sectors = mp_add_sectors;\r\n\t\tp_off_sectors = mp_orig_sectors;\r\n\t} else {\r\n\t\tp_on_sectors = mp_orig_sectors;\r\n\t\tp_off_sectors = mp_add_sectors;\r\n\t}\r\n\r\n\t// Do off list first\r\n\tfor(obj_node = p_off_sectors->GetNext(); obj_node; obj_node = next)\r\n\t{\r\n\t\tnext = obj_node->GetNext();\r\n\t\tp_sector = obj_node->GetData();\r\n\r\n\t\tp_sector->set_flags(CSector::mREMOVE_FROM_SUPER_SECTORS);\r\n\t\tremove_sector_from_table(p_sector->GetChecksum());\r\n\t\tp_sector->SetActive(false);\r\n\t\t//Dbg_Message(\"Removed sector %x in toggle\", p_sector->GetChecksum());\r\n\t}\r\n\r\n\t// Do on list\r\n\tfor(obj_node = p_on_sectors->GetNext(); obj_node; obj_node = next)\r\n\t{\r\n\t\tnext = obj_node->GetNext();\r\n\t\tp_sector = obj_node->GetData();\r\n\r\n\t\tp_sector->set_flags(CSector::mADD_TO_SUPER_SECTORS);\r\n\t\tAddSector(p_sector);\r\n\t\tp_sector->SetActive(true);\r\n\t\t//Dbg_Message(\"Added sector %x in toggle\", p_sector->GetChecksum());\r\n\t}\r\n\r\n\t// And update the SuperSectors\r\n\tUpdateSuperSectors(p_off_sectors);\r\n\r\n\treturn m_using_add_sectors;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 \t\t\tCScene::CloneSector(uint32 orig_sector_checksum, CScene *p_dest_scene, bool instance, bool add_to_super_sectors)\r\n{\r\n\tCSector *p_orig_sector = GetSector(orig_sector_checksum);\r\n\r\n\tif (p_orig_sector)\r\n\t{\r\n\t\treturn CloneSector(p_orig_sector, p_dest_scene, instance, add_to_super_sectors);\r\n\t} else {\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 \t\t\tCScene::CloneSector(CSector *p_orig_sector, CScene *p_dest_scene, bool instance, bool add_to_super_sectors)\r\n{\r\n\t// Use current scene if dest is NULL\r\n\tif (!p_dest_scene)\r\n\t{\r\n\t\tp_dest_scene = this;\r\n\t}\r\n\r\n\tCSector *p_new_sector = p_orig_sector->clone(instance, add_to_super_sectors, p_dest_scene);\r\n\r\n\tif (p_new_sector)\r\n\t{\r\n\t\tp_dest_scene->AddSector(p_new_sector);\r\n\r\n\t\treturn p_new_sector->GetChecksum();\r\n\t} else {\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool \t\t\tCScene::DeleteSector(uint32 sector_checksum)\r\n{\r\n\tCSector *p_sector = GetSector(sector_checksum);\r\n\r\n\tif (p_sector)\r\n\t{\r\n\t\treturn DeleteSector(p_sector);\r\n\t} else {\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool \t\t\tCScene::DeleteSector(CSector *p_sector)\r\n{\r\n\tif (p_sector->get_flags() & CSector::mIN_SUPER_SECTORS)\r\n\t{\r\n\t\tp_sector->set_flags(CSector::mMARKED_FOR_DELETION);\t\t// Can't delete, yet\r\n\r\n\t\treturn false;\r\n\t} else {\r\n\t\tif (GetSector(p_sector->GetChecksum()) == p_sector)\t\t// Just in case we're doing this with AddSectors\r\n\t\t{\r\n\t\t\tmp_sector_table->FlushItem(p_sector->GetChecksum());\r\n\t\t}\r\n\r\n\t\tdelete p_sector;\r\n\r\n\t\treturn true;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCScene::PostLoad(const char *p_name)\r\n{\r\n\tstrcpy(m_scene_filename, p_name);\t// needs name for Pip::Unload()\r\n\r\n\tplat_post_load();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCScene::PostAdd(const char *p_name, Nx::CTexDict * p_tex_dict)\r\n{\r\n\tstrcpy(m_add_scene_filename, p_name);\t// needs to store name somewhere for Pip::Unload(), if we use Pip\r\n\tmp_add_tex_dict = p_tex_dict; \r\n\tm_using_add_sectors = true;\r\n\r\n\tplat_post_add();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCScene::read_collision(const char *p_name, char *p_pip_name, int &num_coll_sectors,\r\n\t\t\t\t\t\t\t\t\t   CCollStaticTri * &p_coll_sectors, CCollObjTriData * &p_coll_sector_data, Mth::CBBox &bbox, bool is_net)\r\n{\r\n\t// for now collision is kind of assumed to be platform independent \r\n\tsprintf(p_pip_name,\"levels\\\\%s\\\\%s%s.col.%s\",p_name,p_name,is_net?\"_net\":\"\",CEngine::sGetPlatformExtension());\r\n\r\n\tDbg_Message ( \"Loading collision %s....\", p_pip_name );\r\n\t\r\n\tbool\tfound_point = false;\r\n\r\n\tuint8 *p_base_addr = (uint8 *) Pip::Load(p_pip_name);\r\n\tif (p_base_addr)\r\n\t{\r\n\t\tNx::CCollObjTriData::SReadHeader *p_header = (Nx::CCollObjTriData::SReadHeader *) p_base_addr;\r\n\t\tp_base_addr += sizeof(Nx::CCollObjTriData::SReadHeader);\r\n\r\n#ifndef __PLAT_NGC__\r\n\t\tDbg_Message ( \"Version # %d header sizeof %d\", p_header->m_version, sizeof(Nx::CCollObjTriData));\r\n\t\tDbg_Message ( \"Number of objects: %d verts: %d faces: %d\", p_header->m_num_objects, p_header->m_total_num_verts, p_header->m_total_num_faces_large + p_header->m_total_num_faces_small);\r\n\t\tDbg_Message ( \"Small verts: %d Large verts: %d\", p_header->m_total_num_verts_small, p_header->m_total_num_verts_large);\r\n#endif\t\t// __PLAT_NGC__\r\n\t\tDbg_MsgAssert(p_header->m_version >= 9, (\"Collision version must be at least 9.\"));\r\n\r\n\t\t// reserve space for objects\r\n\t\tnum_coll_sectors = p_header->m_num_objects;\r\n\t\tp_coll_sector_data = (Nx::CCollObjTriData *) p_base_addr; //new Cld::CCollSector [m_num_coll_sectors];\r\n\r\n\t\t// Calculate base addresses for vert and face arrays\r\n\t\tuint8 *p_base_vert_addr = (uint8 *) (p_coll_sector_data + num_coll_sectors);\r\n#ifndef __PLAT_NGC__\r\n\t\tp_base_vert_addr = (uint8 *)(((uint)(p_base_vert_addr+15)) & 0xFFFFFFF0);\t// Align to 128 bit boundary\r\n#ifdef FIXED_POINT_VERTICES\r\n\t\tuint8 *p_base_intensity_addr = p_base_vert_addr + (p_header->m_total_num_verts_large * Nx::CCollObjTriData::GetVertElemSize() +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   p_header->m_total_num_verts_small * Nx::CCollObjTriData::GetVertSmallElemSize());\r\n\t\tuint8 *p_base_face_addr = p_base_intensity_addr + p_header->m_total_num_verts;\r\n\t\tp_base_face_addr = (uint8 *)(((uint)(p_base_face_addr+3)) & 0xFFFFFFFC);\t// Align to 32 bit boundary\r\n#else\r\n\t\tuint8 *p_base_intensity_addr = NULL;\r\n\t\tuint8 *p_base_face_addr = p_base_vert_addr + (p_header->m_total_num_verts * Nx::CCollObjTriData::GetVertElemSize());\r\n\t\tp_base_face_addr = (uint8 *)(((uint)(p_base_face_addr+15)) & 0xFFFFFFF0);\t// Align to 128 bit boundary\r\n#endif // FIXED_POINT_VERTICES\r\n#else\r\n\t\tuint8 *p_base_intensity_addr = NULL;\r\n\t\tuint8 *p_base_face_addr = p_base_vert_addr + (p_header->m_total_num_faces * Nx::CCollObjTriData::GetVertElemSize());\r\n\t\tp_base_face_addr = (uint8 *)(((uint)(p_base_face_addr+3)) & 0xFFFFFFFC);\t// Align to 32 bit boundary\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\t\t// Calculate addresses for BSP arrays\r\n#ifndef __PLAT_NGC__\r\n\t\tuint8 *p_node_array_size = p_base_face_addr + (p_header->m_total_num_faces_large * Nx::CCollObjTriData::GetFaceElemSize() +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t   p_header->m_total_num_faces_small * Nx::CCollObjTriData::GetFaceSmallElemSize());\r\n\t\tp_node_array_size += ( p_header->m_total_num_faces_large & 1 ) ? 2 : 0;\r\n#else\r\n\t\tuint8 *p_node_array_size = p_base_face_addr + ( p_header->m_total_num_faces * Nx::CCollObjTriData::GetFaceElemSize() );\r\n\t\tp_node_array_size += ( p_header->m_total_num_faces & 1 ) ? 2 : 0;\r\n#endif\t\t// __PLAT_NGC__\r\n\t\tuint8 *p_base_node_addr = p_node_array_size + 4;\r\n\t\tuint8 *p_base_face_idx_addr = p_base_node_addr + *((int *) p_node_array_size);\r\n\r\n\t\t// Reserve space for collsion objects\r\n\t\tp_coll_sectors = new CCollStaticTri[p_header->m_num_objects];\r\n\r\n\t\t// Read objects\r\n\t\tfor (int oidx = 0; oidx < p_header->m_num_objects; oidx++)\r\n\t\t{\r\n\t\t\tp_coll_sector_data[oidx].InitCollObjTriData(this, p_base_vert_addr, p_base_intensity_addr, p_base_face_addr,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tp_base_node_addr, p_base_face_idx_addr);\r\n\t\t\tp_coll_sector_data[oidx].InitBSPTree();\r\n\r\n\t\t\tp_coll_sectors[oidx].SetGeometry(&(p_coll_sector_data[oidx]));\r\n\r\n\t\t\tif (p_coll_sector_data[oidx].GetNumFaces() > 0)\t // only add bbox if there are some faces in the object.....\r\n\t\t\t{\r\n\t\t\t\t// Add to scene bbox\r\n\t\t\t\tbbox.AddPoint(p_coll_sector_data[oidx].GetBBox().GetMin());\r\n\t\t\t\tbbox.AddPoint(p_coll_sector_data[oidx].GetBBox().GetMax());\r\n\t\t\t\tfound_point = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!found_point)\r\n\t\t{\r\n\t\t\t// if there was no collision, then set up a dummy 200 inch bounding box at the origin\r\n\t\t\tbbox.AddPoint(Mth::Vector (-100,-100,-100));\r\n\t\t\tbbox.AddPoint(Mth::Vector (100,100,100));\r\n\t\t}\r\n\t} \r\n\telse \r\n\t{\r\n\t\tDbg_Error ( \"Could not open collision file\\n\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tDbg_Message ( \"successfully read collision\" );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCScene::LoadCollision(const char *p_name, bool is_net)\r\n{\r\n\tread_collision(p_name, m_coll_filename, m_num_coll_sectors, mp_coll_sectors, mp_coll_sector_data, m_collision_bbox, is_net);\r\n\r\n\tDbg_Message(\"Scene bounding box: min (%f, %f, %f) max (%f, %f, %f)\", \r\n\t\t\t\tm_collision_bbox.GetMin()[X], m_collision_bbox.GetMin()[Y], m_collision_bbox.GetMin()[Z], \r\n\t\t\t\tm_collision_bbox.GetMax()[X], m_collision_bbox.GetMax()[Y], m_collision_bbox.GetMax()[Z]);\r\n\r\n\tif (m_num_coll_sectors > 0)\r\n\t{\r\n\t\t// Create super sectors\r\n\t\tif (m_in_super_sectors)\r\n\t\t{\r\n\t\t\tmp_sector_man = new SSec::Manager;\r\n\t\t\tmp_sector_man->GenerateSuperSectors(m_collision_bbox);\r\n\r\n\t\t\tmp_sector_man->AddCollisionToSuperSectors(mp_coll_sectors, m_num_coll_sectors);\r\n\t\t}\r\n\r\n\t\t// Add to CSectors\r\n\t\tfor (int i = 0; i < m_num_coll_sectors; i++)\r\n\t\t{\r\n\t\t\tCSector *p_sector = GetSector(mp_coll_sectors[i].GetChecksum());\r\n\t\t\tif (!p_sector)\t// Don't assert now since there may not be renderable data\r\n\t\t\t{\r\n\t\t\t\t// Collision info, but not renderable\r\n\t\t\t\t// so, we still need to create a Sector, but with no renderable component\r\n\t\t\t\tp_sector = CreateSector(); \t\t\t// create empty secotr\r\n\t\t\t\tp_sector->SetChecksum(mp_coll_sectors[i].GetChecksum());\r\n\t\t\t\tp_sector->SetActive(true);\r\n\t\t\t\tAddSector(p_sector);\r\n\t\t\t}\r\n\t\t\tp_sector->AddCollSector(&(mp_coll_sectors[i]));\r\n\t\t\tp_sector->set_flags(CSector::mIN_SUPER_SECTORS);\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tCEngine::sGetWeather()->UpdateGrid();\r\n\r\n\treturn plat_load_collision(p_name);\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCScene::AddCollision(const char *p_name)\r\n{\r\n\tMth::CBBox\t\t\tadd_collision_bbox;\r\n\r\n\tif (mp_coll_sectors == NULL)\r\n\t{\r\n\t\treturn false;\t\t\t// collision not needed\r\n\t}\r\n\r\n\tread_collision(p_name, m_add_coll_filename, m_num_add_coll_sectors, mp_add_coll_sectors, mp_add_coll_sector_data, add_collision_bbox);\r\n\r\n\tif ((add_collision_bbox.GetMin()[X] < m_collision_bbox.GetMin()[X]) ||\r\n\t\t(add_collision_bbox.GetMax()[X] > m_collision_bbox.GetMax()[X]) ||\r\n\t\t(add_collision_bbox.GetMin()[Z] < m_collision_bbox.GetMin()[Z]) ||\r\n\t\t(add_collision_bbox.GetMax()[Z] > m_collision_bbox.GetMax()[Z]))\r\n\t{\r\n\t\tDbg_Message(\"Add Scene bounding box: min (%f, %f, %f) max (%f, %f, %f)\", \r\n\t\t\t\t\tadd_collision_bbox.GetMin()[X], add_collision_bbox.GetMin()[Y], add_collision_bbox.GetMin()[Z], \r\n\t\t\t\t\tadd_collision_bbox.GetMax()[X], add_collision_bbox.GetMax()[Y], add_collision_bbox.GetMax()[Z]);\r\n\t\tDbg_Message(\"Scene bounding box: min (%f, %f, %f) max (%f, %f, %f)\", \r\n\t\t\t\t\tm_collision_bbox.GetMin()[X], m_collision_bbox.GetMin()[Y], m_collision_bbox.GetMin()[Z], \r\n\t\t\t\t\tm_collision_bbox.GetMax()[X], m_collision_bbox.GetMax()[Y], m_collision_bbox.GetMax()[Z]);\r\n\t\tDbg_MsgAssert(add_collision_bbox.Within(m_collision_bbox), (\"Can't add collision outside of original scene\"));\r\n\t}\r\n\r\n\tif (m_num_add_coll_sectors > 0)\r\n\t{\r\n\t\t// Add to CSectors\r\n\t\tfor (int i = 0; i < m_num_add_coll_sectors; i++)\r\n\t\t{\r\n\t\t\tCSector *p_sector = GetSector(mp_add_coll_sectors[i].GetChecksum());\r\n\t\t\tif (!p_sector)\t// Don't assert now since there may not be renderable data\r\n\t\t\t{\r\n\t\t\t\tDbg_Message(\"We don't necessarily want to be creating invisible sectors on an incremental update\");\r\n\r\n\t\t\t\t// Collision info, but not renderable\r\n\t\t\t\t// so, we still need to create a Sector, but with no renderable component\r\n\t\t\t\tp_sector = CreateSector(); \t\t\t// create empty secotr\r\n\t\t\t\tp_sector->SetChecksum(mp_add_coll_sectors[i].GetChecksum());\r\n\t\t\t\tp_sector->SetActive(true);\r\n\t\t\t\tp_sector->set_flags(CSector::mADD_TO_SUPER_SECTORS);\r\n\t\t\t\tAddSector(p_sector);\r\n\r\n\t\t\t\tLst::Node<CSector> *node = new Lst::Node<CSector>(p_sector);\r\n\t\t\t\tmp_add_sectors->AddToTail(node);\r\n\t\t\t}\r\n\t\t\tp_sector->AddCollSector(&(mp_add_coll_sectors[i]));\r\n\t\t\tDbg_Assert(p_sector->get_flags() & CSector::mADD_TO_SUPER_SECTORS);\r\n\t\t}\r\n\r\n\t\t// Now add to SuperSectors\r\n\t\tUpdateSuperSectors(mp_orig_sectors);\r\n\t}\r\n\r\n\treturn plat_add_collision(p_name);\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCScene::CreateCollision(const Mth::CBBox & scene_bbox)\r\n{\r\n\t// Make sure we asked for it at scene creation\r\n\tif (!m_in_super_sectors)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tm_collision_bbox = scene_bbox;\r\n\tmp_sector_man = new SSec::Manager;\r\n\tmp_sector_man->GenerateSuperSectors(m_collision_bbox);\r\n\r\n\treturn true;\r\n}\r\n\r\n#ifdef __NOPT_ASSERT__\r\nvoid\t\t\tCScene::DebugRenderCollision(uint32 ignore_1, uint32 ignore_0)\r\n{\r\n\tif (Nx::CEngine::GetWireframeMode() == 4 || Nx::CEngine::GetWireframeMode() == 5)\r\n\t{\r\n\t\r\n\t\t#ifdef\t__PLAT_NGPS__\r\n\t\t#if 1\r\n\t\t\r\n\t\t// Traverse the tree at the mesh level\r\n\t\t// so we can see the actual meshes\r\n\t\t\r\n\t\tCPs2Scene * p_ps2_scene = (CPs2Scene *) Nx::CEngine::sGetMainScene();\r\n\t\tp_ps2_scene->GetEngineScene()->RenderWireframe(Nx::CEngine::GetWireframeMode());\r\n\r\n\t\t\r\n\t\t\t \r\n\t\t#else\t \r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t\tMth::Vector\t*p_verts = new Mth::Vector[100000];\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\t\r\n\t\tNx::CScene\t*p_scene = Nx::CEngine::sGetMainScene();\r\n\t\t// crappy wireframe rendering of renderable, so we can see if there is any invislbe junk there\r\n\t\tLst::HashTable< Nx::CSector > * p_sector_list = p_scene->GetSectorList();\r\n\t\t\r\n\t\tint sectors = 0;\r\n\t\tint vert_count=0;\r\n\t\tint lines = 0;\r\n\t\tif (p_sector_list)\r\n\t\t{\r\n\t\t\tp_sector_list->IterateStart();\t\r\n\t\t\tNx::CSector *p_sector = p_sector_list->IterateNext();\t\t\r\n\t\t\twhile(p_sector && lines <100000)   // Can't draw too many lines in this mode for some reason\r\n\t\t\t{\r\n\t\r\n\t\t\t\tif (p_sector->IsActive())\r\n\t\t\t\t{\r\n\t\t\t\r\n\t\t\t\t\t\t\t \r\n\t\t\t\t\tNx::CGeom \t*p_geom = p_sector->GetGeom();\r\n\t\t\t\t\tif (p_geom)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\r\n\t\t\t\t\t\tNxPs2::CGeomNode *p_node = (((CPs2Geom*)p_geom)->GetEngineObject());\r\n\t\t\t\t\t\tif (p_node->WasRendered())\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tsectors++;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t//\r\n\t\t\t\t\t\t\t// Do renderable geometry\r\n\t\t\t\t\t\t\tint verts = p_geom->GetNumRenderVerts();\r\n\t\t\t\t\t\t\tif ( verts > 3000)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t//\tprintf (\"Strange no of verts %d on %s\\n\",verts, Script::FindChecksumName(p_sector->GetChecksum()));\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (verts < 30000)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t//NxPs2::BeginLines3D(0x80000000 + (0x00ff00ff));\t\t// Magenta \r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tvert_count += verts;  \r\n\t\t\t\t\t\t\t\t  \r\n\t\t\t\t\t\t\t\t#define\tpeak 500\r\n\t\t\t\t\t\t\t\tint n=p_geom->GetNumRenderPolys();\r\n\t\t\t\t\t\t\t\tint r,g,b;\r\n\t\t\t\t\t\t\t\tr=g=b=0;\r\n\t\t\t\t\t\t\t\tif (n <= peak )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tr = (255 * (n)) / peak;  \t// r ramps up (black to red)\t\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\telse if (n <= peak * 2)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tr = 255;\r\n\t\t\t\t\t\t\t\t\tb = (255 * (n - peak) / (peak));\t// b&g ramps up (to white)\r\n\t\t\t\t\t\t\t\t\tg = b;\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tr = g = b = 255;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\tuint32 rgb = (b<<16)|(g<<8)|r;\t\r\n\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tif (Nx::CEngine::GetWireframeMode() == 4)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tNxPs2::BeginLines3D(0x80000000 + (0x00ffffff & p_sector->GetChecksum()));\t\t\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tNxPs2::BeginLines3D(0x80000000 + (0x00ffffff & rgb));\t\t\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tp_geom->GetRenderVerts(p_verts);\r\n\t\t\t\t\t\t\t\tMth::Vector *p_vert = p_verts+1;\r\n\t\t\t\t\t\t\t\tfor (int i = 1; i < verts; i++)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tNxPs2::DrawLine3D((*p_vert)[X],(*p_vert)[Y],(*p_vert)[Z],p_vert[-1][X],p_vert[-1][Y],p_vert[-1][Z]);\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\tp_vert++;\r\n\t\t\t\t\t\t\t\t\tlines++;\r\n\t\t\t\t\t\t\t\t} // end for\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tNxPs2::EndLines3D();\r\n\t\t\t\t\t\t\t} // end if\r\n\t\t\t\t\t\t}\t\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tp_sector = p_sector_list->IterateNext();\r\n\t\t\t}\r\n\t\t}\r\n//\t\tprintf (\"Renderable wireframe %d sectors, %d verts, %d lines\\n\",sectors, vert_count, lines);\r\n\t\tdelete [] p_verts;\r\n\t\t#endif\r\n\t\t#endif\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tif (!m_in_super_sectors)\r\n\t\t{\r\n\t\t\t// if collision data is not being used, then just return\r\n\t\t\treturn;\r\n\t\t}\r\n\t\r\n\t\tif (mp_coll_sectors)\r\n\t\t{\r\n\t\t\tfor (int i = 0; i < m_num_coll_sectors; i++)\r\n\t\t\t{\r\n\t\t\t\tmp_coll_sectors[i].DebugRender(ignore_1,ignore_0);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\t// Try finding the collision through the sectors\r\n\t\t\tmp_sector_table->IterateStart();\r\n\t\t\tCSector *p_sector;\r\n\t\t\twhile ((p_sector = mp_sector_table->IterateNext()))\r\n\t\t\t{\r\n\t\t\t\tif (p_sector->GetCollSector())\t  // Might not have it yet in park editor\r\n\t\t\t\t{\r\n\t\t\t\t\tp_sector->GetCollSector()->DebugRender(ignore_1, ignore_0);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n#endif\r\n\r\nvoid\t\t\tCScene::DebugCheckForHoles()\r\n{\r\n\r\n\tfor (int i = 0; i < m_num_coll_sectors; i++)\r\n\t{\r\n\t\tprintf (\"%4d/%d \",i,m_num_coll_sectors);\r\n\t\tCCollStaticTri *p_static_tri = static_cast<CCollStaticTri *>(&(mp_coll_sectors[i]));\r\n\t\tDbg_Assert(p_static_tri);\r\n\t\tp_static_tri->CheckForHoles();\r\n\t}\r\n\r\n}\r\n\r\n\r\n// Return the number of collision sectors in the scene\r\nint\t\tCScene::GetNumCollSectors()\r\n{\r\n\treturn m_num_coll_sectors;\r\n}\r\n\r\n// return a pointer to static collision data\r\n// for a collision sector\r\n// used\r\nCCollStaticTri * CScene::GetCollStatic(int n)\r\n{\r\n\treturn &(mp_coll_sectors[n]);\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCScene::UpdateSuperSectors(Lst::Head<CSector> *p_additional_remove_list)\r\n{\r\n\t// Check if we even have SuperSectors\r\n\tif (!mp_sector_man)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tLst::Head< Nx::CCollStatic > coll_add_list;\r\n\tLst::Head< Nx::CCollStatic > coll_remove_list;\r\n\tLst::Head< Nx::CCollStatic > coll_update_list;\r\n\tLst::Head< CSector > \t  sector_delete_list;\r\n\r\n\t/*\r\n\tMem::Heap *p_top_heap = Mem::Manager::sHandle().TopDownHeap();\r\n\tMem::Region *p_top_region = p_top_heap->mp_region;\r\n\tRyan(\"UpdateSuperSectors()\\n\");\r\n\tRyan(\"  free %d\\n\", p_top_heap->mFreeMem.m_count + p_top_region->MemAvailable());\r\n\tRyan(\"  used %d\\n\", p_top_heap->mUsedMem.m_count);\r\n\tRyan(\"  largest %d\\n\", p_top_heap->LargestFreeBlock());\r\n\t*/\r\n\r\n\t// Allocate temp list on high heap\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n\tmp_sector_table->IterateStart();\r\n\r\n\tLst::Node< Nx::CCollStatic > *node;\r\n\tCSector *p_sector;\r\n\r\n\t// Make Add and remove list\r\n\twhile ((p_sector = mp_sector_table->IterateNext()))\r\n\t{\r\n\t\t// Add List\r\n\t\tif (p_sector->get_flags() & CSector::mADD_TO_SUPER_SECTORS)\r\n\t\t{\r\n\t\t\tnode = new Lst::Node< Nx::CCollStatic > ( p_sector->GetCollSector() );\r\n\t\t\tcoll_add_list.AddToTail(node);\r\n\t\t\tp_sector->clear_flags(CSector::mADD_TO_SUPER_SECTORS);\r\n\t\t\tp_sector->set_flags(CSector::mIN_SUPER_SECTORS);\r\n\r\n\t\t\t//Dbg_Message(\"Adding sector %x and collision %x of checksum %x\", p_sector, p_sector->GetCollSector(), p_sector->GetChecksum());\r\n\t\t\t//Mth::CBBox b_box = p_sector->GetCollSector()->GetGeometry()->GetBBox();\r\n\t\t\t//Dbg_Message(\"Adding sector %x and collision %x and bounding box [%f,%f,%f]-[%f,%f,%f]\", p_sector->GetChecksum(), p_sector->GetCollSector()->GetChecksum(),\r\n\t\t\t//\t\t\t   b_box.GetMin()[X], b_box.GetMin()[Y], b_box.GetMin()[Z],\r\n\t\t\t//\t\t\t   b_box.GetMax()[X], b_box.GetMax()[Y], b_box.GetMax()[Z]);\r\n\r\n\t\t\tDbg_MsgAssert(!(p_sector->get_flags() & CSector::mINVALID_SUPER_SECTORS),\r\n\t\t\t\t\t\t  (\"Trying to add collision that needed updating\"));\r\n\t\t}\r\n\r\n\t\t// Remove List\r\n\t\tif (p_sector->get_flags() & (CSector::mMARKED_FOR_DELETION | CSector::mREMOVE_FROM_SUPER_SECTORS))\r\n\t\t{\r\n\t\t\tnode = new Lst::Node< Nx::CCollStatic > ( p_sector->GetCollSector() );\r\n\t\t\tcoll_remove_list.AddToTail(node);\r\n\r\n\t\t\t// Also make a sector delete list\r\n\t\t\tif (p_sector->get_flags() & CSector::mMARKED_FOR_DELETION)\r\n\t\t\t{\r\n\t\t\t\tLst::Node< CSector > *sec_node = new Lst::Node< CSector > (p_sector);\r\n\t\t\t\tsector_delete_list.AddToTail(sec_node);\r\n\t\t\t} else {\r\n\t\t\t\tp_sector->clear_flags(CSector::mREMOVE_FROM_SUPER_SECTORS);\r\n\t\t\t}\r\n\r\n\t\t\t//Dbg_Message(\"Deleting sector %x and collision %x of checksum %x\", p_sector, p_sector->GetCollSector(), p_sector->GetChecksum());\r\n\t\t\t//Mth::CBBox b_box = p_sector->GetCollSector()->GetGeometry()->GetBBox();\r\n\t\t\t//Dbg_Message(\"Deleting sector %x and collision %x and bounding box [%f,%f,%f]-[%f,%f,%f]\", p_sector->GetChecksum(), p_sector->GetCollSector()->GetChecksum(),\r\n\t\t\t//\t\t\t\tb_box.GetMin()[X], b_box.GetMin()[Y], b_box.GetMin()[Z],\r\n\t\t\t//\t\t\t\tb_box.GetMax()[X], b_box.GetMax()[Y], b_box.GetMax()[Z]);\r\n\t\t\tDbg_MsgAssert(!(p_sector->get_flags() & CSector::mADD_TO_SUPER_SECTORS),\r\n\t\t\t\t\t\t  (\"Collision being both added and deleted from SuperSectors\"));\r\n\t\t\tDbg_MsgAssert(p_sector->get_flags() & CSector::mIN_SUPER_SECTORS,\r\n\t\t\t\t\t\t  (\"Trying to remove sector from SuperSector that isn't in any SuperSector\"));\r\n\r\n\t\t\tDbg_MsgAssert(!(p_sector->get_flags() & CSector::mINVALID_SUPER_SECTORS),\r\n\t\t\t\t\t\t  (\"Trying to remove collision that hasn't been updated\"));\r\n\t\t}\r\n\r\n\t\t// Update List\r\n\t\tif (p_sector->get_flags() & CSector::mINVALID_SUPER_SECTORS)\r\n\t\t{\r\n\t\t\tnode = new Lst::Node< Nx::CCollStatic > ( p_sector->GetCollSector() );\r\n\t\t\tcoll_update_list.AddToTail(node);\r\n\t\t\tp_sector->clear_flags(CSector::mINVALID_SUPER_SECTORS);\r\n\r\n\t\t\t//Mth::CBBox b_box = p_sector->GetCollSector()->GetGeometry()->GetBBox();\r\n\t\t\t//Dbg_Message(\"Updating sector %x and collision %x and bounding box [%f,%f,%f]-[%f,%f,%f]\", p_sector->GetChecksum(), p_sector->GetCollSector()->GetChecksum(),\r\n\t\t\t//\t\t\t   b_box.GetMin()[X], b_box.GetMin()[Y], b_box.GetMin()[Z],\r\n\t\t\t//\t\t\t   b_box.GetMax()[X], b_box.GetMax()[Y], b_box.GetMax()[Z]);\r\n\r\n\t\t\tDbg_MsgAssert(p_sector->get_flags() & CSector::mIN_SUPER_SECTORS,\r\n\t\t\t\t\t\t  (\"Collision being updated that isn't in SuperSectors\"));\r\n\t\t}\r\n\t}\r\n\r\n\t// Check additional remove list\r\n\tif (p_additional_remove_list)\r\n\t{\r\n\t\tLst::Node< CSector > *obj_node, *next;\r\n\r\n\t\tfor(obj_node = p_additional_remove_list->GetNext(); obj_node; obj_node = next)\r\n\t\t{\r\n\t\t\tnext = obj_node->GetNext();\r\n\t\t\tp_sector = obj_node->GetData();\r\n\r\n\t\t\tDbg_Assert(!(p_sector->get_flags() & CSector::mMARKED_FOR_DELETION));\t\t// Make sure it shouldn't be deleted\r\n\r\n\t\t\t// Make sure it isn't already on the list\r\n\t\t\tbool new_node = true;\r\n\t\t\tif(coll_remove_list.CountItems() > 0)\r\n\t\t\t{\r\n\t\t\t\tLst::Node<Nx::CCollStatic> *node_coll, *node_next;\r\n\t\t\t\tfor(node_coll = coll_remove_list.GetNext(); node_coll; node_coll = node_next)\r\n\t\t\t\t{\r\n\t\t\t\t\tnode_next = node_coll->GetNext();\r\n\t\t\t\t\tif (node_coll->GetData() == p_sector->GetCollSector())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnew_node = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (new_node)\r\n\t\t\t{\r\n\t\t\t\tnode = new Lst::Node< Nx::CCollStatic > ( p_sector->GetCollSector() );\r\n\t\t\t\tcoll_remove_list.AddToTail(node);\r\n\t\t\t\tp_sector->clear_flags(CSector::mREMOVE_FROM_SUPER_SECTORS);\r\n\t\t\t\t//Dbg_Message(\"Deleting additional sector %x and collision %x of checksum %x\", p_sector, p_sector->GetCollSector(), p_sector->GetChecksum());\r\n\t\t\t\t//Dbg_Message(\"Deleting additional sector %x and collision %x\", p_sector->GetChecksum(), p_sector->GetCollSector()->GetChecksum());\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Do the actual update\r\n\tmp_sector_man->UpdateCollisionSuperSectors(coll_add_list, coll_remove_list, coll_update_list);\r\n\r\n\tLst::Node<Nx::CCollStatic> *node_coll, *node_next;\r\n\r\n\t//\r\n\t// Free lists\r\n\t//\r\n\tif(coll_add_list.CountItems() > 0)\r\n\t{\r\n\t\tfor(node_coll = coll_add_list.GetNext(); node_coll; node_coll = node_next)\r\n\t\t{\r\n\t\t\tnode_next = node_coll->GetNext();\r\n\r\n\t\t\tdelete node_coll;\r\n\t\t}\r\n\t}\r\n\r\n\tif(coll_remove_list.CountItems() > 0)\r\n\t{\r\n\t\tfor(node_coll = coll_remove_list.GetNext(); node_coll; node_coll = node_next)\r\n\t\t{\r\n\t\t\tnode_next = node_coll->GetNext();\r\n\r\n\t\t\tdelete node_coll;\r\n\t\t}\r\n\t}\r\n\r\n\tif(coll_update_list.CountItems() > 0)\r\n\t{\r\n\t\tfor(node_coll = coll_update_list.GetNext(); node_coll; node_coll = node_next)\r\n\t\t{\r\n\t\t\tnode_next = node_coll->GetNext();\r\n\r\n\t\t\tdelete node_coll;\r\n\t\t}\r\n\t}\r\n\r\n\t// And finally delete the marked sectors\r\n\tif(sector_delete_list.CountItems() > 0)\r\n\t{\r\n\t\tLst::Node<CSector> *node_sector, *node_sec_next;\r\n\t\tfor(node_sector = sector_delete_list.GetNext(); node_sector; node_sector = node_sec_next)\r\n\t\t{\r\n\t\t\tnode_sec_next = node_sector->GetNext();\r\n\r\n\t\t\tp_sector = node_sector->GetData();\r\n\r\n\t\t\tmp_sector_table->FlushItem(p_sector->GetChecksum());\r\n\r\n\t\t\tp_sector->clear_flags(CSector::mIN_SUPER_SECTORS);\r\n\t\t\tdelete p_sector;\r\n\r\n\t\t\tdelete node_sector;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCScene::ClearSuperSectors()\r\n{\r\n\t// Check if we even have SuperSectors\r\n\tif (!mp_sector_man)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tmp_sector_table->IterateStart();\r\n\r\n\tCSector *p_sector;\r\n\r\n\t// Check all sectors to make sure they need deleting\r\n\twhile ((p_sector = mp_sector_table->IterateNext()))\r\n\t{\r\n\t\t// Remove List\r\n\t\tif (p_sector->get_flags() & CSector::mMARKED_FOR_DELETION)\r\n\t\t{\r\n\t\t\t//Dbg_Message(\"Deleting sector %x and collision %x of checksum %x\", p_sector, p_sector->GetCollSector(), p_sector->GetChecksum());\r\n\t\t\tDbg_MsgAssert(!(p_sector->get_flags() & CSector::mADD_TO_SUPER_SECTORS),\r\n\t\t\t\t\t\t  (\"Collision being both added and deleted from SuperSectors\"));\r\n\t\t\tDbg_MsgAssert(p_sector->get_flags() & CSector::mIN_SUPER_SECTORS,\r\n\t\t\t\t\t\t  (\"Trying to remove sector from SuperSector that isn't in any SuperSector\"));\r\n\r\n\t\t\tDbg_MsgAssert(!(p_sector->get_flags() & CSector::mINVALID_SUPER_SECTORS),\r\n\t\t\t\t\t\t  (\"Trying to remove collision that hasn't been updated\"));\r\n\r\n\t\t\tp_sector->clear_flags(CSector::mIN_SUPER_SECTORS);\r\n\t\t\tdelete p_sector;\r\n\t\t} else {\r\n\t\t\tDbg_MsgAssert(0, (\"Trying to clear SuperSectors even though sector %x hasn't been marked for deletion\", p_sector->GetChecksum()));\r\n\t\t}\r\n\t}\r\n\r\n\t// Do the actual clear\r\n\tmp_sector_man->ClearCollisionSuperSectors();\r\n\r\n\t// And clear the hash table\r\n\tmp_sector_table->FlushAllItems();\r\n}\r\n\r\n// Given a bounding box, then set the active flag of those \r\n// sectors that intersect this box by at least a certain abount \r\nvoid CScene::SetActiveInBox(Mth::CBBox &box, bool active, float min_intersect)\r\n{\r\n\t\r\n\tMth::CBBox smaller_box = box;\r\n\t\r\n\t// later..\r\n//\tsmaller_box.Shrink(min_intersect);   \r\n\t\r\n\tmp_sector_table->IterateStart();\r\n\tCSector *p_sector;\r\n\twhile ((p_sector = mp_sector_table->IterateNext()))\r\n\t{\r\n//\t\tprintf (\"Checking sector\\n\");\r\n\t\tif (smaller_box.Intersect(p_sector->GetBoundingBox()))\r\n\t\t{\r\n//\t\t\tprintf(\"Setting active = %d\\n\",active);\r\n\t\t\tp_sector->SetActive(active);\r\n\t\t}\r\n\t}\r\n\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Create an empty sector\r\nCSector\t*\t\t\tCScene::CreateSector()\r\n{\r\n\tCSector\t*p_sector = plat_create_sector();\r\n\tp_sector->mp_geom = NULL;\r\n\tp_sector->mp_coll_sector = NULL;\r\n\treturn p_sector;\r\n}\r\n\r\n\r\nvoid\tCScene::GetMetrics(Script::CStruct * p_info)\r\n{\r\n\tp_info->AddString(CRCD(0xc3f4169a,\"FileName\"),GetSceneFilename());\r\n\r\n\tint total_sectors = 0;\r\n\tint render_sectors = 0;\t\r\n\tint render_verts = 0;\t\r\n\tint render_polys = 0;\t\r\n\tint render_base_polys = 0;\t\r\n\t// Iterate over the sectors, counting verious things\t\r\n\tLst::HashTable< Nx::CSector > * p_sector_list = GetSectorList();\r\n\tif (p_sector_list)\r\n\t{\r\n\t\tp_sector_list->IterateStart();\t\r\n\t\tNx::CSector *p_sector = p_sector_list->IterateNext();\t\t\r\n\t\twhile(p_sector)\r\n\t\t{\r\n\t\t\ttotal_sectors++;\r\n\t\t\tNx::CGeom \t*p_geom = p_sector->GetGeom();\r\n\t\t\tif (p_geom)\r\n\t\t\t{\r\n\t\t\t\t// Do renderable geometry\r\n\t\t\t\trender_sectors++;\r\n\t\t\t\trender_verts += p_geom->GetNumRenderVerts();\r\n\t\t\t\trender_polys += p_geom->GetNumRenderPolys();\r\n\t\t\t\trender_base_polys += p_geom->GetNumRenderBasePolys();\r\n\t\t\t}\r\n\t\t\tp_sector = p_sector_list->IterateNext();\r\n\t\t}\r\n\t}\r\n\t\r\n\tp_info->AddInteger(CRCD(0x4a6bf967,\"Sectors\"),total_sectors);\r\n\tp_info->AddInteger(CRCD(0xac30a9d,\"ColSectors\"),GetNumCollSectors());\r\n\tp_info->AddInteger(CRCD(0x969d3af6,\"Verts\"),render_verts);\r\n\tp_info->AddInteger(CRCD(0xd576df05,\"Polys\"),render_polys);\r\n\tp_info->AddInteger(CRCD(0x1e3061ee,\"BasePolys\"),render_base_polys);\r\n\r\n\tp_info->AddInteger(CRCD(0x5714c480,\"TextureMemory\"),GetTexDict()->GetFileSize());\r\n\t\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCScene::SetMajorityColor(Image::RGBA rgba)\r\n{\r\n\tplat_set_majority_color(rgba);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\tCScene::GetMajorityColor() const\r\n{\r\n\treturn plat_get_majority_color();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCScene::plat_post_load()\r\n{\r\n\tprintf (\"STUB: PostLoad\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCScene::plat_post_add()\r\n{\r\n\tprintf (\"STUB: PostAdd\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCScene::plat_load_textures(const char *p_name)\r\n{\r\n\tprintf (\"STUB: LoadTextures\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCScene::plat_load_collision(const char *p_name)\r\n{\r\n\tprintf (\"STUB: LoadCollision\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCScene::plat_add_collision(const char *p_name)\r\n{\r\n\tprintf (\"STUB: AddCollision\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCScene::plat_unload_add_scene()\r\n{\r\n\tprintf (\"STUB: UnloadAddScene\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSector*\t\t\tCScene::plat_create_sector()\r\n{\r\n\tprintf (\"STUB: plat_create_sector\\n\");\r\n\treturn NULL;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCScene::plat_set_majority_color(Image::RGBA rgba)\r\n{\r\n\t// STUB: only really needed on PS2, so ignorable on other platforms\r\n}\r\n\t\t \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\t\t\tCScene::plat_get_majority_color() const\r\n{\r\n\t// STUB: only really needed on PS2, so ignorable on other platforms\r\n\treturn Image::RGBA(0x80, 0x80, 0x80, 0x80);\r\n}\r\n\r\n\r\n\r\n\r\n} // namespace Nx\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxScene.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// NXSCENE.H - Neversoft Engine, Rendering portion, Platform independent interface\r\n\r\n#ifndef\t__GFX_NX_SCENE_H__\r\n#define\t__GFX_NX_SCENE_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/hashtable.h>\r\n\r\n#include <sk/engine/supersector.h>\r\n#include \t<gfx/image/imagebasic.h>\r\n\r\n\r\nnamespace Script\r\n{\r\n\tclass\tCStruct;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n/////////////////////////////////////////////////////////////////////////\r\n// Forward declarations\r\nclass\tCSector;\r\nclass\tCTexDict;\r\nclass\tCCollStaticTri;\r\nclass\tCCollObjTriData;\r\n\r\n////////////////////////////////////////////////////////////////////////\r\n// CScene:\r\n//\r\n// Holds all the CSectors for a scene.\r\n//\r\n\r\nclass\t\tCScene\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCScene( int sector_table_size = 10 );\r\n\tvirtual\t\t\t\t\t\t~CScene();\r\n\r\n\tvoid\t\t\t\t\t\tPostLoad(const char *p_name);\r\n\tvoid\t\t\t\t\t\tPostAdd(const char *p_name, Nx::CTexDict * p_tex_dict);\r\n\tbool\t\t\t\t\t\tLoadTextures(const char *p_name);\t\t\t// load scene textures\r\n\tbool\t\t\t\t\t\tLoadCollision(const char *p_name, bool is_net=false);\t\t\t// load scene collision data\r\n\tbool\t\t\t\t\t\tAddCollision(const char *p_name);\t\t\t// add scene collision data\r\n\tbool\t\t\t\t\t\tCreateCollision(const Mth::CBBox & scene_bbox); // load scene collision data\r\n\r\n\tbool\t\t\t\t\t\tToggleAddScene();\t\t\t\t\t\t\t// Toggle the orig and add sectors\r\n\tbool\t\t\t\t\t\tUnloadAddScene();\t\t\t\t\t\t\t// unloads previous add scene\r\n\r\n\tbool\t\t\t\t\t\tInSuperSectors() const;\r\n\tvoid\t\t\t\t\t\tSetInSuperSectors(bool);\r\n\tbool\t\t\t\t\t\tIsSky() const;\r\n\tvoid\t\t\t\t\t\tSetIsSky(bool);\r\n\r\n\tCSector\t*\t\t\t\t\tGetSector(uint32 sector_checksum);\t\t\t// get a sector pointer, based on the checksum of the name\r\n\tvoid\t\t\t\t\t\tAddSector(CSector *pSector);\t\t\t\t// Add a sector to the list\r\n\tLst::HashTable<CSector> *\tGetSectorList() const;\t\t\t  \t\t\t// get the whole list\r\n\r\n\t// Replacing a sector is for in-house testing.  Since PIP'ed CSectors can't be deleted individually,\r\n\t// the replace will hide the old one.\r\n\tCSector *\t\t\t\t\tReplaceSector(CSector *pSector);\t\t\t// returns old sector, if any\r\n\r\n\t// Cloning copies a sector, puts it in hash table, and returns its checksum (p_dest_scene of NULL uses current scene)\r\n\tuint32\t\t\t\t\t\tCloneSector(uint32 orig_sector_checksum, CScene *p_dest_scene = NULL,\r\n\t\t\t\t\t\t\t\t\t\t\tbool instance = false, bool add_to_super_sectors = true);\r\n\tuint32\t\t\t\t\t\tCloneSector(CSector *p_orig_sector, CScene *p_dest_scene = NULL,\r\n\t\t\t\t\t\t\t\t\t\t\tbool instance = false, bool add_to_super_sectors = true);\r\n\r\n\t// creates an empty sector\r\n\tCSector\t*\t\t\t\t\tCreateSector();\r\n\t\r\n\t\r\n\t// Deletes a sector and takes it off the list\r\n\tbool\t\t\t\t\t\tDeleteSector(uint32 sector_checksum);\r\n\tbool\t\t\t\t\t\tDeleteSector(CSector *p_sector);\r\n\r\n\t// Updates the SuperSectors with any clone or quickupdate changes\r\n\tvoid\t\t\t\t\t\tUpdateSuperSectors(Lst::Head<CSector> *p_additional_remove_list = NULL);\r\n\tvoid\t\t\t\t\t\tClearSuperSectors();\t\t\t\t\t\t// note ALL sectors must already be marked for deletion\r\n\r\n\t// allow access to the collision sectors\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\tint\t\t\t\t\t\t\tGetNumCollSectors();\r\n\tCCollStaticTri * \t\t\tGetCollStatic(int n);\r\n\r\n\r\n\t// Sets sectors active or inactive if they are inside a particular bounding box\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\tvoid \t\t\t\t\t\tSetActiveInBox(Mth::CBBox &box, bool active, float min_intersect);\r\n\t\r\n\tconst Mth::CBBox &\t\t\tGetRenderBoundingBox() const;\t\t\t\t// get bounding box of scene renderables\r\n\tconst Mth::CBBox &\t\t\tGetCollisionBoundingBox() const;\t\t\t// get bounding box of scene collision\r\n\tSSec::Manager *\t\t\t\tGetSuperSectorManager() const;\t\t\t\t// get the super sectors, if any\r\n\r\n\tvoid\t\t\t\t\t\tSetTexDict(CTexDict * p_tex_dict);\t\t\t// set texture dictionary\r\n\tCTexDict *\t\t\t\t\tGetTexDict() const;\t\t\t\t\t\t\t// set texture dictionary\r\n\r\n\tvoid\t\t\t\t\t\tSetID(uint32 id);\t\t\t\t\t\t\t// Set name checksum ID\r\n\tuint32\t\t\t\t\t\tGetID() const;\r\n\tconst char *\t\t\t\tGetSceneFilename() const;\r\n\tconst char *\t\t\t\tGetAddSceneFilename() const;\r\n\r\n\tvoid\t\t\t\t\t\tDebugRenderCollision(uint32 ignore_1, uint32 ignore_0);\t\t\t\t\t\t// render in wireframe\r\n\tvoid\t\t\t\t\t\tDebugCheckForHoles();\r\n\r\n\tvoid\t\t\t\t\t\tGetMetrics(Script::CStruct * p_info);\r\n\r\n\tvoid\t\t\t\t\t\tSetMajorityColor(Image::RGBA rgba);\r\n\tImage::RGBA\t\t\t\t\tGetMajorityColor() const;\r\n\r\nprotected:\r\n\t// read scene collision file\r\n\tbool\t\t\t\t\t\tread_collision(const char *p_name, char *p_pip_name, int &num_coll_sectors,\r\n\t\t\t\t\t\t\t\t\t\t\t   CCollStaticTri * &p_coll_sectors, CCollObjTriData * &p_coll_sector_data,\r\n\t\t\t\t\t\t\t\t\t\t\t   Mth::CBBox &bbox, bool is_net=false);\r\n\r\n\tvoid\t\t\t\t\t\tremove_sector_from_table(uint32 sector_checksum);\r\n\r\n\tchar\t\t\t\t\t\tm_scene_filename[128];\t\t\t\t\t\t// scene filename (kept around for unload)\r\n\tuint32\t\t\t\t\t\tm_id;\t\t\t\t\t\t\t\t\t\t// checksum of name\r\n\t\r\n\tCTexDict *\t\t\t\t\tmp_tex_dict;\t\t\t\t\t\t\t\t// texture dictionary that this scene uses\t\r\n\t\r\n\tbool\t\t\t\t\t\tm_in_super_sectors;\t\t\t\t\t\t\t// Is this scene in the super sectors\r\n\tbool\t\t\t\t\t\tm_sky;\t\t\t\t\t\t\t\t\t\t// Tells if scene is a sky type\r\n\r\n\tMth::CBBox\t\t\t\t\tm_render_bbox;\t\t\t\t\t\t\t\t// scene renderable bounding box\r\n\tMth::CBBox\t\t\t\t\tm_collision_bbox;\t\t\t\t\t\t\t// scene collision bounding box\r\n\tLst::HashTable< CSector > *\tmp_sector_table;\t\t\t\t\t\t\t// All the CSector pointers\r\n\tSSec::Manager *\t\t\t\tmp_sector_man;\t\t\t\t\t\t\t\t// SuperSector manager\r\n\r\n\tchar\t\t\t\t\t\tm_coll_filename[128];\t\t\t\t\t\t// collision filename (kept around for unload)\r\n\tint\t\t\t\t\t\t\tm_num_coll_sectors;\t\t\t\t\t\t\t// non-cloned collision\r\n\tCCollStaticTri *\t\t\tmp_coll_sectors;\t\t\t\t\t\t\t// Static collision objects\r\n\tCCollObjTriData *\t\t\tmp_coll_sector_data;\t\t\t\t\t\t// Static collision object data\r\n\r\n\t// For the incremental update code\r\n\tchar\t\t\t\t\t\tm_add_scene_filename[128];\r\n\tCTexDict *\t\t\t\t\tmp_add_tex_dict; \r\n\tchar\t\t\t\t\t\tm_add_coll_filename[128];\r\n\tint\t\t\t\t\t\t\tm_num_add_coll_sectors;\r\n\tCCollStaticTri *\t\t\tmp_add_coll_sectors;\r\n\tCCollObjTriData *\t\t\tmp_add_coll_sector_data;\r\n\r\n\tbool\t\t\t\t\t\tm_using_add_sectors;\r\n\tLst::Head < CSector > *\t\tmp_orig_sectors;\r\n\tLst::Head < CSector > *\t\tmp_add_sectors;\r\n\r\nprivate:\r\n\t////////////////////////////////////////////////////////////\r\n\t// Platform specific function calls\t\r\n\t//\r\n\tvirtual void\t\t\t\tplat_post_load();\r\n\tvirtual void\t\t\t\tplat_post_add();\r\n\tvirtual bool\t\t\t\tplat_load_textures(const char *p_name);\t\t// load textures \r\n\tvirtual bool\t\t\t\tplat_load_collision(const char *p_name);\t// load collision data\r\n\tvirtual bool\t\t\t\tplat_add_collision(const char *p_name);\t\t// add collision data\r\n\tvirtual bool\t\t\t\tplat_unload_add_scene();\t\t\t\t\t// unloads previous add scene\r\n\tvirtual CSector\t*\t\t\tplat_create_sector();  \t\t\t\t\t\t// create empty sector\r\n\tvirtual void\t\t\t\tplat_set_majority_color(Image::RGBA rgba);\t// set the most common sector color\r\n\tvirtual Image::RGBA\t\t\tplat_get_majority_color() const;\t\t\t// get the most common sector color\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////\r\n//\r\n// Inline functions\r\n//\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Lst::HashTable< CSector > * CScene::GetSectorList() const\r\n{\r\n\treturn mp_sector_table;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\t\tCScene::InSuperSectors() const\r\n{\r\n\treturn m_in_super_sectors;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCScene::SetInSuperSectors(bool s)\r\n{\r\n\tm_in_super_sectors = s;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool\t\t\t\t\tCScene::IsSky() const\r\n{\r\n\treturn m_sky;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\t\t\tCScene::SetIsSky(bool s)\r\n{\r\n\tm_sky = s;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::CBBox &\tCScene::GetRenderBoundingBox() const\r\n{\r\n\treturn m_render_bbox;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::CBBox &\tCScene::GetCollisionBoundingBox() const\r\n{\r\n\treturn m_collision_bbox;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline SSec::Manager *\t\tCScene::GetSuperSectorManager() const\r\n{\r\n\treturn mp_sector_man;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline \tvoid\t\t\t\tCScene::SetTexDict(CTexDict * p_tex_dict)\r\n{\r\n\tmp_tex_dict = p_tex_dict;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tCTexDict *\t\t\tCScene::GetTexDict() const\r\n{\r\n\treturn mp_tex_dict;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline \tvoid\t\t\t\tCScene::SetID(uint32 id)\r\n{\r\n\tm_id = id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tuint32\t\t\t\tCScene::GetID() const\r\n{\r\n\treturn m_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tconst char *\t\tCScene::GetSceneFilename() const\r\n{\r\n\treturn m_scene_filename;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tconst char *\t\tCScene::GetAddSceneFilename() const\r\n{\r\n\treturn m_add_scene_filename;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ninline void\t\t\t\t\tCScene::remove_sector_from_table(uint32 sector_checksum)\r\n{\r\n\tmp_sector_table->FlushItem(sector_checksum);\r\n}\r\n\r\n}\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxSector.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxSector.cpp\r\n\r\n#include \"gfx/nx.h\"\r\n#include \"gfx/nxgeom.h\"\r\n#include \"gfx/nxsector.h\"\r\n#include \"gfx/nxflags.h\"\r\n#include \"gel/collision/collision.h\"\r\n#include <sys/replay/replay.h>\r\n\r\nnamespace\tNx\r\n{\r\n///////////////////////////////////////////////////////////////////\r\n// CSector definitions\r\n\r\n// These functions are the platform independent part of the interface to \r\n// the platform specific code\r\n// parameter checking can go here....\r\n// although we might just want to have these functions inline, or not have them at all?\r\n\t\t\t\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSector::CSector()\r\n{\r\n\tm_flags = mCOLLIDE;\r\n\tmp_geom = NULL;\r\n\tmp_coll_sector = NULL;\r\n\tm_rot_y = Mth::ROT_0;\r\n\tuint32\tlight_group = CRCD(0xe3714dc1,\"outdoor\");\t\t\t // default to OutDoors\r\n\tSetLightGroup(light_group);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSector::~CSector()\r\n{\r\n\tif (mp_coll_sector && (m_flags & mCLONE))\t// cloned collision isn't in scene array\r\n\t{\r\n\t\t// Check if in SuperSectors\r\n\t\tif (m_flags & mIN_SUPER_SECTORS)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"Can't free CSector when it is still on the SuperSector lists\"));\r\n\t\t}\r\n\r\n\t\tdelete mp_coll_sector;\r\n\t}\r\n\r\n\tif (mp_geom /*&& (m_flags & mCLONE)*/)\t\t\t// cloned geometry isn't in scene array\r\n\t{\r\n\t\tdelete mp_geom;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tCSector::GetChecksum() const\r\n{\r\n\treturn m_checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::SetChecksum(uint32 c)\r\n{\r\n\tm_checksum = c;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom *\tCSector::GetGeom() const\r\n{\r\n\treturn mp_geom;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::SetGeom(CGeom *p_geom)\r\n{\r\n\tmp_geom = p_geom;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::SetColor(Image::RGBA rgba)\r\n{\t\t\r\n\tif (mp_geom)\r\n\t{\r\n\t\tmp_geom->SetColor(rgba);\r\n\t//} else {\r\n\t//\tplat_set_color(rgba);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::ClearColor()\r\n{\t\t\r\n\tif (mp_geom)\r\n\t{\r\n\t\tmp_geom->ClearColor();\r\n\t//} else {\r\n\t//\tplat_clear_color();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\tCSector::GetColor() const\r\n{\t\t\r\n\tif (mp_geom)\r\n\t{\r\n\t\treturn mp_geom->GetColor();\r\n\t} else {\r\n\t\treturn Image::RGBA(0, 0, 0, 0);\r\n\t//\treturn plat_get_color();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::SetVisibility(uint32 mask)\r\n{\r\n\tif (mp_geom)\r\n\t{\r\n\t\tuint32 vis=mp_geom->GetVisibility();\r\n\t\tif ( (vis^mask) & 0x01 )\r\n\t\t{\r\n\t\t\tReplay::WriteSectorVisibleStatus(m_checksum,mask&0x01);\r\n\t\t}\t\r\n\t\tmp_geom->SetVisibility(mask);\r\n\t//} else {\r\n\t//\tplat_set_visibility(mask);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tCSector::GetVisibility() const\r\n{\r\n\tif (mp_geom)\r\n\t{\r\n\t\treturn mp_geom->GetVisibility();\r\n\t} else {\r\n\t\treturn 0;\r\n\t//\treturn plat_get_visibility();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::SetActive(bool on)\r\n{\r\n\t// Do collision also\r\n\tif (mp_coll_sector)\r\n\t{\r\n\t\tif (on) {\r\n\t\t\tmp_coll_sector->ClearObjectFlags(mSD_KILLED);\r\n\t\t} else {\r\n\t\t\tmp_coll_sector->SetObjectFlags(mSD_KILLED);\r\n\t\t}\r\n\t}\r\n\r\n\tif (mp_geom)\r\n\t{\r\n\t\tif (mp_geom->IsActive() != on)\r\n\t\t{\r\n\t\t\tReplay::WriteSectorActiveStatus(m_checksum,on);\r\n\t\t}\r\n\t\tmp_geom->SetActive(on);\r\n\t//} else {\r\n\t//\tplat_set_active(on);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCSector::IsActive() const\r\n{\r\n\tif (mp_geom)\r\n\t{\r\n\t\treturn mp_geom->IsActive();\r\n\t} else {\r\n\t\tDbg_Assert(mp_coll_sector);\r\n\r\n\t\treturn !(mp_coll_sector->GetObjectFlags() & mSD_KILLED);\r\n\t//\treturn plat_is_active();\r\n\t}\r\n}\r\n\r\nvoid CSector::SetActiveAtReplayStart(bool on)\r\n{\r\n\tif (on)\r\n\t{\r\n\t\tm_flags|=mACTIVE_AT_REPLAY_START;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_flags&=~mACTIVE_AT_REPLAY_START;\r\n\t}\r\n}\r\n\r\nbool CSector::GetActiveAtReplayStart() const\r\n{\r\n\treturn m_flags&mACTIVE_AT_REPLAY_START;\r\n}\r\n\r\nvoid CSector::SetVisibleAtReplayStart(bool on)\r\n{\r\n\tif (on)\r\n\t{\r\n\t\tm_flags|=mVISIBLE_AT_REPLAY_START;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_flags&=~mVISIBLE_AT_REPLAY_START;\r\n\t}\r\n}\r\n\r\nbool CSector::GetVisibleAtReplayStart() const\r\n{\r\n\treturn m_flags&mVISIBLE_AT_REPLAY_START;\r\n}\r\n\r\nvoid CSector::SetStoredActive(bool on)\r\n{\r\n\tif (on)\r\n\t{\r\n\t\tm_flags|=mSTORED_ACTIVE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_flags&=~mSTORED_ACTIVE;\r\n\t}\r\n}\r\n\r\nbool CSector::GetStoredActive() const\r\n{\r\n\treturn m_flags&mSTORED_ACTIVE;\r\n}\r\n\r\nvoid CSector::SetStoredVisible(bool on)\r\n{\r\n\tif (on)\r\n\t{\r\n\t\tm_flags|=mSTORED_VISIBLE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_flags&=~mSTORED_VISIBLE;\r\n\t}\r\n}\r\n\r\nbool CSector::GetStoredVisible() const\r\n{\r\n\treturn m_flags&mSTORED_VISIBLE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::CBBox & CSector::GetBoundingBox() const\r\n{\r\n\tif (mp_geom)\r\n\t{\r\n\t\treturn mp_geom->GetBoundingBox();\r\n\t} else {\r\n\t\tDbg_Assert(mp_coll_sector);\r\n\r\n\t\tCCollObjTriData *p_coll_data = mp_coll_sector->GetGeometry();\r\n\r\n\t\tDbg_Assert(p_coll_data);\r\n\r\n\t\treturn p_coll_data->GetBBox();\r\n\t//\treturn plat_get_bounding_box();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::SetWorldPosition(const Mth::Vector& pos)\r\n{\r\n\t// Do collision first\r\n\tif (mp_coll_sector)\r\n\t{\r\n\t\tmp_coll_sector->SetWorldPosition(pos);\r\n\t\tif (m_flags & mIN_SUPER_SECTORS)\r\n\t\t{\r\n\t\t\tm_flags |= mINVALID_SUPER_SECTORS;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Then Geometry\r\n\tif (mp_geom)\r\n\t{\r\n\t\tmp_geom->SetWorldPosition(pos);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\tCSector::GetWorldPosition() const\r\n{\r\n\tif (mp_geom)\r\n\t{\r\n\t\treturn mp_geom->GetWorldPosition();\r\n\t} else {\r\n\t\tDbg_Assert(mp_coll_sector);\r\n\r\n\t\treturn mp_coll_sector->GetWorldPosition();\r\n\t//\treturn plat_get_world_position();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::SetYRotation(Mth::ERot90 rot)\r\n{\r\n\tMth::ERot90 delta_rot = (Mth::ERot90) (((rot + Mth::NUM_ROTS) - m_rot_y) % Mth::NUM_ROTS);\r\n\t//Dbg_Message(\"SetYRotation: new rot %d sector rot %d delta rot %d\", rot, m_rot_y, delta_rot);\r\n\r\n\t// Do collision first\r\n\tif (mp_coll_sector)\r\n\t{\r\n\t\tmp_coll_sector->RotateY(GetWorldPosition(), delta_rot);\r\n\t}\r\n\r\n\tif (mp_geom)\r\n\t{\r\n\t\tmp_geom->RotateY(delta_rot);\r\n\t//} else {\r\n\t//\tplat_set_y_rotation(delta_rot);\r\n\t}\r\n\r\n\t// Now change value\r\n\tm_rot_y = rot;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::ERot90\tCSector::GetYRotation() const\r\n{\r\n\treturn m_rot_y;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::SetScale(const Mth::Vector & scale)\r\n{\r\n\t// Do collision first\r\n\tif (mp_coll_sector)\r\n\t{\r\n\t\tmp_coll_sector->Scale(GetWorldPosition(), scale);\r\n\t\tif (m_flags & mIN_SUPER_SECTORS)\r\n\t\t{\r\n\t\t\tm_flags |= mINVALID_SUPER_SECTORS;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tif (mp_geom)\r\n\t{\r\n\t\tmp_geom->SetScale(scale);\r\n\t}\r\n\r\n\t// Now change value\r\n\tm_scale = scale;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CSector::GetScale() const\r\n{\r\n\treturn m_scale;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tCSector::GetNumCollVertices() const\r\n{\r\n\tif (mp_coll_sector && mp_coll_sector->GetGeometry())\r\n\t{\r\n\t\treturn mp_coll_sector->GetGeometry()->GetNumVerts();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"SetRawCollVertices(): Can't find collision geometry\"));\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::GetRawCollVertices(Mth::Vector *p_vert_array) const\r\n{\r\n\tif (mp_coll_sector && mp_coll_sector->GetGeometry())\r\n\t{\r\n\t\tmp_coll_sector->GetGeometry()->GetRawVertices(p_vert_array);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"SetRawCollVertices(): Can't find collision geometry\"));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::SetRawCollVertices(const Mth::Vector *p_vert_array)\r\n{\r\n\tif (mp_coll_sector && mp_coll_sector->GetGeometry())\r\n\t{\r\n\t\tmp_coll_sector->GetGeometry()->SetRawVertices(p_vert_array);\r\n\r\n\t\t// Invalidate sector in SuperSectors\r\n\t\tif (m_flags & mIN_SUPER_SECTORS)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(!(m_flags & mREMOVE_FROM_SUPER_SECTORS), (\"Can't change collision verts of a sector being removed\"));\r\n\t\t\tm_flags |= mINVALID_SUPER_SECTORS;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"SetRawCollVertices(): Can't find collision geometry\"));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::SetCollidable(bool on)\r\n{\r\n\tif (on) {\r\n\t\tm_flags |= mCOLLIDE;\r\n\t} else {\r\n\t\tm_flags &= ~mCOLLIDE;\r\n\t}\r\n\r\n\tif (mp_coll_sector)\r\n\t{\r\n\t\tif (on) {\r\n\t\t\tmp_coll_sector->ClearObjectFlags(mSD_NON_COLLIDABLE);\r\n\t\t} else {\r\n\t\t\tmp_coll_sector->SetObjectFlags(mSD_NON_COLLIDABLE);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCSector::IsCollidable() const\r\n{\r\n\treturn (m_flags & mCOLLIDE) || IsActive();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::SetOccluder(bool on)\r\n{\r\n\tDbg_MsgAssert(mp_coll_sector,(\"Flagging a sector as occluder that has no collision info\"));\r\n\tif (mp_coll_sector)\r\n\t{\r\n\t\tif (!on)\r\n\t\t{\r\n\t\t\tmp_coll_sector->ClearObjectFlags(mSD_OCCLUDER);\r\n\t\t}\r\n\t\telse \r\n\t\t{\r\n\t\t\tif (! (mp_coll_sector->GetObjectFlags() & mSD_OCCLUDER))\r\n\t\t\t{\r\n\t\t\t\tmp_coll_sector->SetObjectFlags(mSD_OCCLUDER);\r\n\t\t\t\t\r\n\t\t\t\t// we've just set some collision as an occluder for the first time\r\n\t\t\t\t// so now would be a good time to tell the engine about these new occlusion polygons\r\n\t\t\t\t\r\n\t\t\t\tCCollStaticTri * p_coll_static = static_cast<CCollStaticTri*>(mp_coll_sector);\r\n\t\t\t\tDbg_MsgAssert(p_coll_static,(\"World sector has non-static collision???\"));\r\n\t\t\t\t\r\n\t\t\t\tp_coll_static->ProcessOcclusion();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::SetShatter(bool on)\r\n{\r\n\tReplay::WriteShatter(m_checksum,on);\r\n\tplat_set_shatter(on);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCSector::GetShatter() const\r\n{\r\n\treturn plat_get_shatter();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCSector::AddCollSector(Nx::CCollStatic *p_coll_sector)\r\n{\r\n\tDbg_Assert(m_checksum == p_coll_sector->GetChecksum());\r\n\r\n\tif (!mp_coll_sector)\r\n\t{\r\n\t\tmp_coll_sector = p_coll_sector;\r\n\t\tif (mp_geom)\r\n\t\t{\r\n\t\t\tmp_geom->SetCollTriData(p_coll_sector->GetGeometry());\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t} else {\r\n\t\tDbg_MsgAssert(0, (\"CSector::AddCollSector(): adding second collision sector to %x\\n\", m_checksum));\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::CCollStatic *\tCSector::GetCollSector() const\r\n{\r\n\treturn mp_coll_sector;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\t\tCSector::get_flags() const\r\n{\r\n\treturn m_flags;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCSector::SetUVWibbleParams(float u_vel, float u_amp, float u_freq, float u_phase,\r\n\t\t\t\t\t\t\t\t\t\t\t   float v_vel, float v_amp, float v_freq, float v_phase)\r\n{\r\n\tif (mp_geom)\r\n\t{\r\n\t\tmp_geom->SetUVWibbleParams(u_vel, u_amp, u_freq, u_phase, v_vel, v_amp, v_freq, v_phase);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCSector::UseExplicitUVWibble(bool yes)\r\n{\r\n\tif (mp_geom)\r\n\t{\r\n\t\tmp_geom->UseExplicitUVWibble(yes);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCSector::SetUVWibbleOffsets(float u_offset, float v_offset)\r\n{\r\n\tif (mp_geom)\r\n\t{\r\n\t\tmp_geom->SetUVWibbleOffsets(u_offset, v_offset);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSector::set_flags(uint32 flags)\r\n{\r\n\tm_flags |= flags;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSector::clear_flags(uint32 flags)\r\n{\r\n\tm_flags &= ~flags;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSector *\tCSector::clone(bool instance, bool add_to_super_sectors, CScene *p_dest_scene)\r\n{\r\n\t// Create new instance and clone stuff below p-line\r\n\tCSector *p_new_sector = plat_clone(instance, p_dest_scene);\r\n\r\n\tif (p_new_sector)\r\n\t{\r\n\t\t// Get new checksum\r\n\t\tp_new_sector->m_checksum = CEngine::sGetUnusedSectorChecksum();\r\n\r\n\t\t// Now clone stuff above p-line\r\n\t\tp_new_sector->m_flags\t= m_flags | mCLONE;\t\t// mark as clone\r\n\t\tp_new_sector->m_rot_y \t= m_rot_y;\r\n\r\n\t\tif (mp_geom)\r\n\t\t{\r\n\t\t\tp_new_sector->mp_geom = mp_geom->Clone(instance, p_dest_scene);\r\n\t\t\tDbg_Assert(p_new_sector->mp_geom);\r\n\t\t}\r\n\r\n\t\tif (mp_coll_sector)\r\n\t\t{\r\n\t\t\t\r\n\t\t\t// Note, static_cast seems to be essentially a macro\r\n\t\t\t// so you must pass it a pointer, and not the result of an expression\r\n\t\t\t// otherwise it will continually re-evaluate that expression\r\n\t\t\t// which here would casue memory leaks.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\t\tCCollObj *p_coll_obj = mp_coll_sector->Clone(false /*instance*/);\t// Garrett: We're not even going to try to instamce it\r\n\t\t\tif (p_coll_obj)\r\n\t\t\t{\r\n\t\t\t\tp_new_sector->mp_coll_sector = static_cast<CCollStatic *>(p_coll_obj);\r\n\r\n\t\t\t\tp_new_sector->mp_coll_sector->SetChecksum(p_new_sector->m_checksum);\r\n\r\n\t\t\t\tp_new_sector->m_flags &= ~mIN_SUPER_SECTORS;\t\t// Not in there yet\r\n\r\n\t\t\t\tif (add_to_super_sectors)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_new_sector->m_flags |= mADD_TO_SUPER_SECTORS;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tDbg_Assert(p_new_sector->mp_coll_sector);\r\n\r\n\t\t\t\t// For now, just copy the CCollObjTriData pointer over\r\n\t\t\t\tif (p_new_sector->mp_geom)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Garrett: Commented assert out because the pointer is now copied in CGeom\r\n\t\t\t\t\t//Dbg_Assert(p_new_sector->mp_geom->GetCollTriData() == NULL);\r\n\t\t\t\t\tp_new_sector->mp_geom->SetCollTriData(p_coll_obj->GetGeometry());\r\n\t\t\t\t}\r\n\r\n\t\t\t\tDbg_Assert(p_coll_obj->GetGeometry() != mp_coll_sector->GetGeometry());\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_new_sector->mp_coll_sector = NULL;\r\n\t\t\t\tp_new_sector->m_flags &= ~mIN_SUPER_SECTORS;\t\t// Not in there at all\r\n\t\t\t\tif (p_new_sector->mp_geom)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_new_sector->mp_geom->SetCollTriData(NULL);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\treturn p_new_sector;\r\n\t} else {\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stub versions of all platform specific functions are provided here:\r\n// so engine implementors can leave certain functionality until later\r\n\t\t\t\t\t\t\r\n#if 0\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::plat_set_color(Image::RGBA rgba)\r\n{\r\n\tprintf (\"STUB: PlatSetColor\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA CSector::plat_get_color() const\r\n{\r\n\tprintf (\"STUB: PlatGetColor\\n\");\r\n\treturn Image::RGBA(0, 0, 0, 0);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::plat_clear_color()\r\n{\r\n\tprintf (\"STUB: PlatClearColor\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::plat_set_visibility(uint32 mask)\r\n{\r\n\tprintf (\"STUB: PlatSetVisibility\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tCSector::plat_get_visibility() const\r\n{\r\n\tprintf (\"STUB: PlatGetVisibility\\n\");\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::plat_set_active(bool on)\r\n{\r\n\tprintf (\"STUB: PlatSetActive\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCSector::plat_is_active() const\r\n{\r\n\tprintf (\"STUB: PlatIsActive\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n void\tCSector::plat_set_world_position(const Mth::Vector& pos)\r\n {\r\n\t printf (\"STUB: PlatSetWorldPosition\\n\");\r\n }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::CBBox &\tCSector::plat_get_bounding_box() const\r\n{\r\n\tstatic Mth::CBBox stub_bbox;\r\n\tprintf (\"STUB: PlatGetBoundingBox\\n\");\r\n\treturn stub_bbox;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst Mth::Vector &\tCSector::plat_get_world_position() const\r\n{\r\n\tstatic Mth::Vector stub_vec;\r\n\tprintf (\"STUB: PlatGetWorldPosition\\n\");\r\n\treturn stub_vec;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::plat_set_y_rotation(Mth::ERot90 rot)\r\n{\r\n\tprintf (\"STUB: PlatSetYRotation\\n\");\r\n}\r\n#endif // 0\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSector::plat_set_shatter(bool on)\r\n{\r\n\tprintf (\"STUB: PlatSetShatter\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCSector::plat_get_shatter() const\r\n{\r\n\tprintf (\"STUB: PlatGetShatter\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSector *\tCSector::plat_clone(bool instance, CScene *p_dest_scene)\r\n{\r\n\tprintf (\"STUB: PlatClone\\n\");\r\n\treturn NULL;\r\n}\r\n\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxSector.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxSector.h\r\n\r\n\r\n\r\n#ifndef\t__GFX_NXSECTOR_H__\r\n#define\t__GFX_NXSECTOR_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include \t<gfx/image/imagebasic.h>\r\n\r\nnamespace Mth {\r\n\tclass Vector;\r\n\tclass CBBox;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\n////////////////////////////////////////////////////////////////\r\n// The Sector Story:\r\n//\r\n// To the designer, A \"Sector\" (previously a \"world sector\" is an\r\n// object in 3D Studio Max.  Typically this might be a tree, a wall\r\n// a section of a building, a parked car or any other static part of the world\r\n//\r\n// The designer wants to be able to:\r\n// -  load the sector as part of the scene, see it and collide with it\r\n// -  reference the sector by name\r\n// -  Turn it on and off (both collision and display)\r\n// -  make it visible and invisible in particular viewports for LOD reasons\r\n// -  change its color\r\n// -  change various attributes, like UV wibble speed.  \r\n//\r\n// To the engine programmer, the sector will be split into various bits of data\r\n// for optimization and platform specific reasons.  The geometry might be in different chunks\r\n// and the collision data might be seperate from the rendering data.  \r\n// The act of \"turning off\" a sector will be very different from platform to platform\r\n//\r\n// To get round this problem, we have a CSector class which acts as a facade\r\n// to the actual machine specific sector data.\r\n//\r\n// When the engine loads a scene, it will create a list of CSectors, one for each\r\n// sector in the scene.  \r\n// Each CSector will actually be a platfrom specific class derived from CSector,\r\n// like: CPs2Sector, CXboxSector or CNGC Sector\r\n// The derived class (like, CPs2Sector), contains the platform specific data that\r\n// identifies the sector in the engine.  On the PS2, this might have a list of the \r\n// meshes that make up the sector, maybe a list of the materials, probably a pointer to the \r\n// collision data, and maybe a pointer to a structure containing sector flags.\r\n// CSector provides functions like SetVisibility(), which call a platform specific\r\n// function (PlatSetVisibility()), which calls the actual engine specific\r\n// function, which performs whatever is necessary at a low level to make the \r\n// sector visible/invisible (on the PS2, this might involve relinking a DMA chain,\r\n// on other platforms, it might just involve flipping a bit.)\r\n//\r\n// The \"engine programmers\" have to implement and maintain the platform\r\n// specific CPs2Sector (and CXBox.., etc) implementation.\r\n//\r\n// The \"game programmers\" simply use the CSector class, and will never need to know \r\n// anything about the derived class, and their code will work across all three platforms.  \r\n//\r\n// The End\r\n/////////////////////////////////////////////////////////////////////////////////\r\n\r\n// Forward declaration\r\nclass CGeom;\r\nclass CScene;\r\nclass CCollStatic;\r\n#ifdef\t__PLAT_NGPS__\t\t\r\nclass CPs2Scene;\r\n#endif //\t__PLAT_NGPS__\t\t\r\n\r\n// The CSector class is the platform independent abstract base class\r\n// of the platform specific CSector classes\r\nclass\tCSector\r\n{\r\npublic:\r\n// The basic interface to the sector\r\n// this is the machine independent part\t\r\n// machine independ range checking, etc can go here\t\r\n\t\t\t\t\t\t\tCSector();\r\n\tvirtual\t\t\t\t\t~CSector();\r\n\r\n\tuint32\t\t\t\t\tGetChecksum() const;\r\n\tvoid\t\t\t\t\tSetChecksum(uint32 c);\r\n\r\n\tCGeom *\t\t\t\t\tGetGeom() const;\r\n\tvoid\t\t\t\t\tSetGeom(CGeom *p_geom);\r\n\r\n\tvoid\t\t\t\t\tSetColor(Image::RGBA rgba);\r\n\tImage::RGBA\t\t\t\tGetColor() const;\r\n\tvoid\t\t\t\t\tClearColor();\r\n\t\r\n\tvoid \t\t\t\t\tSetLightGroup(uint32 light_group) {m_light_group = light_group;}\r\n\tuint32 \t\t\t\t\tGetLightGroup() {return m_light_group;}\r\n\r\n\tvoid\t\t\t\t\tSetVisibility(uint32 mask);\r\n\tuint32\t\t\t\t\tGetVisibility() const;\r\n\r\n\tvoid\t\t\t\t\tSetActive(bool on);\r\n\tbool\t\t\t\t\tIsActive() const;\r\n\r\n\tvoid\t\t\t\t\tSetActiveAtReplayStart(bool on);\r\n\tbool\t\t\t\t\tGetActiveAtReplayStart() const;\r\n\tvoid\t\t\t\t\tSetVisibleAtReplayStart(bool on);\r\n\tbool\t\t\t\t\tGetVisibleAtReplayStart() const;\r\n\tvoid\t\t\t\t\tSetStoredActive(bool on);\r\n\tbool\t\t\t\t\tGetStoredActive() const;\r\n\tvoid\t\t\t\t\tSetStoredVisible(bool on);\r\n\tbool\t\t\t\t\tGetStoredVisible() const;\r\n\t\r\n\tconst Mth::CBBox &\t\tGetBoundingBox() const;\r\n\r\n\tvoid\t\t\t\t\tSetWorldPosition(const Mth::Vector& pos);\r\n\tconst Mth::Vector &\t\tGetWorldPosition() const;\r\n\r\n\t// Rotation is applied to meshes permanently\r\n\tvoid\t\t\t\t\tSetYRotation(Mth::ERot90 rot);\r\n\tMth::ERot90\t\t\t\tGetYRotation() const;\t\t\t// Gets applied rotation\r\n\r\n\t// Scale is applied to meshes permanently\r\n\tvoid\t\t\t\t\tSetScale(const Mth::Vector& scale);\r\n\tMth::Vector\t\t\t\tGetScale() const;\t\t\t\t// Gets scale\r\n\r\n\t// Change collision data of a sector\r\n\tint\t\t\t\t\t\tGetNumCollVertices() const;\r\n\tvoid\t\t\t\t\tGetRawCollVertices(Mth::Vector *p_vert_array) const;\r\n\tvoid\t\t\t\t\tSetRawCollVertices(const Mth::Vector *p_vert_array);\r\n\r\n\tvoid\t\t\t\t\tSetCollidable(bool on);\r\n\tbool\t\t\t\t\tIsCollidable() const;\r\n\r\n\tvoid\t\t\t\t\tSetShatter(bool on);\r\n\tbool\t\t\t\t\tGetShatter() const;\r\n\r\n\tbool\t\t\t\t\tAddCollSector(Nx::CCollStatic *p_coll_sector);\r\n\tCCollStatic *\t\t\tGetCollSector() const;\r\n\r\n\tvoid\t\t\t\t\tSetOccluder(bool on);\r\n\t\r\n\t// Wibble functions\r\n\tvoid\t\t\t\t\tSetUVWibbleParams(float u_vel, float u_amp, float u_freq, float u_phase,\r\n\t\t\t\t\t\t\t\t\t\t\t  float v_vel, float v_amp, float v_freq, float v_phase);\r\n\tvoid\t\t\t\t\tUseExplicitUVWibble(bool yes);\r\n\tvoid\t\t\t\t\tSetUVWibbleOffsets(float u_offset, float v_offset);\r\n\t\r\nprotected:\r\n\t// Internal sector flags.\r\n\tenum {\r\n\t\tmCOLLIDE\t\t\t\t\t= 0x0001,\r\n\t\tmCLONE\t\t\t\t\t\t= 0x0002,\r\n\t\tmADD_TO_SUPER_SECTORS\t\t= 0x0004,\t\t\t\t\t// Cloned sector needs adding to Super Sectors\r\n\t\tmMARKED_FOR_DELETION\t\t= 0x0008,\t\t\t\t\t// Cloned object no longer used but not deleted yet\r\n\t\tmREMOVE_FROM_SUPER_SECTORS\t= 0x0010,\t\t\t\t\t// Take out of Super Sectors w/o deleting\r\n\t\tmINVALID_SUPER_SECTORS\t\t= 0x0020,\t\t\t\t\t// Tells if SuperSectors needs updating\r\n\t\tmIN_SUPER_SECTORS\t\t\t= 0x0040,\t\t\t\t\t// Tells if in SuperSectors\r\n\t\t// These 4 used by replay code\r\n\t\tmACTIVE_AT_REPLAY_START\t\t= 0x0080,\t\t\t\t\t// Whether the sector is active at the start of the replay\r\n\t\tmVISIBLE_AT_REPLAY_START\t= 0x0100,\t\t\t\t\t// Whether the sector is visible at the start of the replay\r\n\t\tmSTORED_ACTIVE\t\t\t\t= 0x0200,\t\t\t\t\t// Stored active status, so that it can be restored at the end of the replay\r\n\t\tmSTORED_VISIBLE\t\t\t\t= 0x0400,\t\t\t\t\t// Stored visible status, so that it can be restored at the end of the replay\r\n\t};\r\n\r\n\tuint32\t\t\t\t\tget_flags() const;\t\t\t\t// Get internal flags\r\n\tvoid\t\t\t\t\tset_flags(uint32 flags);\t\t// Set internal flags\r\n\tvoid\t\t\t\t\tclear_flags(uint32 flags);\t\t// Clear internal flags\r\n\r\n\tuint32\t\t\t\t\tm_checksum;\r\n\tuint32\t\t\t\t\tm_flags;\r\n\tuint32\t\t\t\t\tm_light_group;\t\t// checksum of light group as specified in node array\r\n\r\n\tMth::ERot90\t\t\t\tm_rot_y;\t\t// since rotation already applied below p-line, we keep the value above\r\n\tMth::Vector\t\t\t\tm_scale;\t\t// since scale already applied below p-line, we keep the value above\r\n\r\n\tCGeom *\t\t\t\t\tmp_geom;\t\t// The geometry of the sector\r\n\tCCollStatic *\t\t\tmp_coll_sector;\t// Collision object for the sector\r\n\r\nprivate:\r\n\tCSector *\t\t\t\tclone(bool instance, bool add_to_super_sectors, CScene *p_dest_scene = NULL);\t// must only be called through CScene\r\n\r\n\t// The virtual functions will have a stub implementation\r\n\t// in nxsector.cpp\r\n\t//virtual\tvoid\t\t\tplat_set_color(Image::RGBA rgba);\r\n\t//virtual\tImage::RGBA\t\tplat_get_color() const;\r\n\t//virtual\tvoid\t\t\tplat_clear_color();\r\n\r\n\t//virtual\tvoid\t\t\tplat_set_visibility(uint32 mask);\r\n\t//virtual\tuint32\t\t\tplat_get_visibility() const;\r\n\r\n\t//virtual\tvoid\t\t\tplat_set_active(bool on);\r\n\t//virtual\tbool\t\t\tplat_is_active() const;\r\n\r\n\t//virtual const Mth::CBBox &\tplat_get_bounding_box() const;\r\n\r\n\t//virtual void\t\t\tplat_set_world_position(const Mth::Vector& pos);\r\n\t//virtual const Mth::Vector &\tplat_get_world_position() const;\r\n\r\n\t//virtual void\t\t\tplat_set_y_rotation(Mth::ERot90 rot);\r\n\r\n\tvirtual\tvoid\t\t\tplat_set_shatter(bool on);\r\n\tvirtual\tbool\t\t\tplat_get_shatter() const;\r\n\r\n\tvirtual CSector *\t\tplat_clone(bool instance, CScene *p_dest_scene);\r\n\r\n\t// CScene needs access to clone() and internal flags\r\n\tfriend CScene;\r\n#ifdef\t__PLAT_NGPS__\t\t\r\n\tfriend CPs2Scene;\r\n#endif //\t__PLAT_NGPS__\t\t\r\n};\r\n\r\n}\r\n\r\n#endif // \r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxSkinComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       NxSkinComponent.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/21/2001\r\n//****************************************************************************\r\n\r\n#include \"gfx/nxskincomponent.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stub versions of all platform specific functions are provided here:\r\n// so engine implementors can leave certain functionality until later\r\n\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkinComponent::plat_set_color(uint8 r, uint8 g, uint8 b, uint8 a)\r\n{\r\n    // STUB\r\n    printf(\"STUB FUNCTION called:  CSkinComponent::set_color %d %d %d %d\", r, g, b, a);\r\n}\r\n         \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkinComponent::plat_set_visibility(uint32 mask)\r\n{\r\n    // STUB\r\n    printf(\"STUB FUNCTION called:  CSkinComponent::set_visibility %08x\", mask);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkinComponent::plat_set_scale(float scaleFactor)\r\n{\r\n    // STUB\r\n    printf(\"STUB FUNCTION called:  CSkinComponent::set_scale %f\", scaleFactor);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkinComponent::plat_replace_texture(char* p_srcFileName, char* p_dstFileName)\r\n{\r\n    Dbg_Assert(p_srcFileName);\r\n    Dbg_Assert(p_dstFileName);\r\n    \r\n    // STUB\r\n    printf(\"STUB FUNCTION called:  CSkinComponent::replace_texture %s %s\", p_srcFileName, p_dstFileName);\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// These functions are the platform independent part of the interface to \r\n// the platform specific code\r\n// parameter checking can go here....\r\n// although we might just want to have these functions inline, or not have them at all?\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkinComponent::CSkinComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkinComponent::~CSkinComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkinComponent::SetColor(uint8 r, uint8 g, uint8 b, uint8 a)\r\n{\r\n    plat_set_color(r,g,b,a);\r\n}\r\n         \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkinComponent::SetVisibility(uint32 mask)\r\n{\r\n    plat_set_visibility(mask);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkinComponent::SetScale(float scaleFactor)\r\n{\r\n    plat_set_scale(scaleFactor);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkinComponent::ReplaceTexture(char* p_srcFileName, char* p_dstFileName)\r\n{\r\n    plat_replace_texture(p_srcFileName, p_dstFileName);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxSkinComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       NxSkinComponent.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/21/2001\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_NXSKINCOMPONENT_H__\r\n#define\t__GFX_NXSKINCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\nclass CSkinComponent\r\n{\r\n\r\npublic:\r\n    // The basic interface to the skin component\r\n    // this is the machine independent part\t\r\n    // machine independent range checking, etc can go here\r\n    CSkinComponent();\r\n\tvirtual\t\t\t\t\t~CSkinComponent();\r\n\r\npublic:\r\n\tvoid\t\t\t\t\tSetColor(uint8 r, uint8 g, uint8 b, uint8 a);\r\n\tvoid\t\t\t\t\tSetVisibility(uint32 mask);\r\n\tvoid\t\t\t\t\tSetScale(float scaleFactor);\r\n    void                    ReplaceTexture(char* p_srcFileName, char* p_dstFileName);\r\n\r\nprotected:\r\n    uint32                  m_componentName;\r\n\r\nprivate:\r\n    // The virtual functions will have a stub implementation\r\n    // in p_nxskincomponent.cpp\r\n\tvirtual\tvoid\t\t\tplat_set_color(uint8 r, uint8 g, uint8 b, uint8 a);\r\n\tvirtual\tvoid\t\t\tplat_set_visibility(uint32 mask);\r\n    virtual void            plat_set_scale(float scaleFactor);\r\n    virtual void            plat_replace_texture(char* p_srcFileName, char* p_dstFileName);\r\n};\r\n\r\n}\r\n\r\n#endif // __GFX_NXSKINCOMPONENT_H__\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxSprite.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxSprite.cpp\r\n\r\n#include <core/defines.h>\r\n\r\n#include \"gfx/NxSprite.h\"\r\n\r\nnamespace\tNx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// CSprite\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// These functions are the platform independent part of the interface.\r\n\t\t\t\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSprite::CSprite(CWindow2D *p_window) :\r\n\tmp_texture(NULL),\r\n\tm_pos_x(-1.0f),\r\n\tm_pos_y(-1.0f),\r\n\tm_scale_x(1.0f),\r\n\tm_scale_y(1.0f),\r\n\tm_anchor_x(-1.0f),\r\n\tm_anchor_y(-1.0f),\r\n\tm_rotation(0.0f),\r\n\tm_priority(0.0f),\r\n\tm_width(0),\r\n\tm_height(0),\r\n\tm_rgba(0x80, 0x80, 0x80, 0x80),\r\n\tmp_window(p_window)\r\n{\r\n\tm_hidden = true;\t// until we get more information\r\n\tm_use_zbuffer = false;\r\n}\r\n\r\nCSprite::CSprite(CTexture *p_tex, float xpos, float ypos,\r\n\t\t\t\tuint16 width, uint16 height, CWindow2D *p_window, Image::RGBA rgba,\r\n\t\t\t\tfloat xscale, float yscale, float xanchor,\r\n\t\t\t\tfloat yanchor, float rot, float pri, bool hide)\r\n{\r\n\tInitialize(p_tex, xpos, ypos, width, height, p_window, rgba, xscale, yscale,\r\n\t\t\t   xanchor, yanchor, rot, pri, hide);\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSprite::~CSprite()\r\n{\r\n\t// TODO: Possibly free texture\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::Initialize(CTexture *p_tex, float xpos, float ypos,\r\n\t\t\t\t\t\t\t\tuint16 width, uint16 height, CWindow2D *p_window,\r\n\t\t\t\t\t\t\t\tImage::RGBA rgba, float xscale, float yscale, float xanchor,\r\n\t\t\t\t\t\t\t\tfloat yanchor, float rot, float pri, bool hide)\r\n{\r\n\tmp_texture = p_tex;\r\n\tm_pos_x = xpos;\r\n\tm_pos_y = ypos;\r\n\tm_width = width;\r\n\tm_height = height;\r\n\tm_rgba = rgba;\r\n\tm_scale_x = xscale;\r\n\tm_scale_y = yscale;\r\n\tm_anchor_x = xanchor;\r\n\tm_anchor_y = yanchor;\r\n\tm_rotation = rot;\r\n\tm_priority = pri;\r\n\r\n\tm_hidden = hide;\r\n\tm_use_zbuffer = false;\r\n\tmp_window = p_window;\r\n\r\n\tplat_initialize();\t\t\t// This calls nothing when called from the constructor\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::SetHidden(bool hide)\r\n{\r\n\tm_hidden = hide;\r\n\r\n\tplat_update_hidden();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::SetTexture(CTexture *p_texture)\r\n{\r\n\tmp_texture = p_texture;\r\n\tif (p_texture)\r\n\t{\r\n\t\tm_width = p_texture->GetWidth();\r\n\t\tm_height = p_texture->GetHeight();\r\n\t}\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::SetPos(float x, float y)\r\n{\r\n\tm_pos_x = x;\r\n\tm_pos_y = y;\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::SetSize(uint16 width, uint16 height)\r\n{\r\n\tm_width = width;\r\n\tm_height = height;\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::SetScale(float x, float y)\r\n{\r\n\tm_scale_x = x;\r\n\tm_scale_y = y;\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::SetAnchor(float x, float y)\r\n{\r\n\tm_anchor_x = x;\r\n\tm_anchor_y = y;\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::SetRotation(float rot)\r\n{\r\n\tm_rotation = rot;\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::SetPriority(float pri)\r\n{\r\n\tm_priority = pri;\r\n\tm_use_zbuffer = false;\r\n\r\n\tplat_update_priority();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t CSprite::SetZValue(ZBufferValue z)\r\n{\r\n\tm_zvalue = z;\r\n\tm_use_zbuffer = true;\r\n\r\n\tplat_update_priority();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::SetRGBA(Image::RGBA rgba)\r\n{\r\n\tm_rgba = rgba;\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::SetWindow(CWindow2D *p_window)\r\n{\r\n\tmp_window = p_window;\r\n\r\n\tplat_update_window();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCSprite::EnableConstantZValue(bool enable)\r\n{\r\n\tplat_enable_constant_z_value(enable);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCSprite::SetConstantZValue(Nx::ZBufferValue z)\r\n{\r\n\tplat_set_constant_z_value(z);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::ZBufferValue\tCSprite::GetConstantZValue()\r\n{\r\n\treturn plat_get_constant_z_value();\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stub versions of all platform specific functions are provided here:\r\n// so engine implementors can leave certain functionality until later\r\n\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::plat_initialize()\r\n{\r\n\tprintf (\"STUB: PlatInitialize\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::plat_update_hidden()\r\n{\r\n\tprintf (\"STUB: PlatUpdateHidden\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::plat_update_engine()\r\n{\r\n\tprintf (\"STUB: PlatUpdateEngine\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::plat_update_priority()\r\n{\r\n\tprintf (\"STUB: PlatUpdatePriority\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCSprite::plat_update_window()\r\n{\r\n\tprintf (\"STUB: PlatUpdateWindow\\n\");\r\n}\r\n\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxSprite.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// NxSprite.H - Neversoft Engine, Rendering portion, Platform independent interface\r\n\r\n#ifndef\t__GFX_NX_SPRITE_H__\r\n#define\t__GFX_NX_SPRITE_H__\r\n\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/hashtable.h>\r\n\r\n#include <gfx/nxtexture.h>\r\n#include <gfx/nxviewport.h>\r\n#include <gfx/image/imagebasic.h>\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n// Forward declarations\r\nclass CWindow2D;\r\n\r\n//////////////////////////////////////////////////////////////////////////////////\r\n// Nx::CSprite: Class for 2D sprites\r\nclass\tCSprite\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCSprite(CWindow2D *p_window = NULL);\r\n\t\t\t\t\t\t\tCSprite(CTexture *p_tex, float xpos, float ypos,\r\n\t\t\t\t\t\t\t\t\tuint16 width, uint16 height, CWindow2D *p_window = NULL,\r\n\t\t\t\t\t\t\t\t\tImage::RGBA rgba = Image::RGBA(0x80, 0x80, 0x80, 0x80),\r\n\t\t\t\t\t\t\t\t\tfloat xscale = 1.0f, float yscale = 1.0f,\r\n\t\t\t\t\t\t\t\t\tfloat xanchor = -1.0f, float yanchor = -1.0f,\r\n\t\t\t\t\t\t\t\t\tfloat rot = 0.0f, float pri = 0.0f, bool hide = false);\r\n\tvirtual\t\t\t\t\t~CSprite();\r\n\r\n\t// Initialization\r\n\tvoid\t\t\t\t\tInitialize(CTexture *p_tex, float xpos, float ypos,\r\n\t\t\t\t\t\t\t\t\t   uint16 width, uint16 height, CWindow2D *p_window = NULL,\r\n\t\t\t\t\t\t\t\t\t   Image::RGBA rgba = Image::RGBA(0x80, 0x80, 0x80, 0x80),\r\n\t\t\t\t\t\t\t\t\t   float xscale = 1.0f, float yscale = 1.0f,\r\n\t\t\t\t\t\t\t\t\t   float xanchor = -1.0f, float yanchor = -1.0f,\r\n\t\t\t\t\t\t\t\t\t   float rot = 0.0f, float pri = 0.0f, bool hide = false);\r\n\r\n\t// If hidden, it won't be drawn that frame\r\n\tvoid\t\t\t\t\tSetHidden(bool hide);\r\n\tbool\t\t\t\t\tIsHidden() const;\r\n\r\n\t// Texture used for the sprite.  But it is optional.\r\n\tCTexture *\t\t\t\tGetTexture() const;\r\n\tvoid\t\t\t\t\tSetTexture(CTexture *p_texture);\r\n\r\n\t// Position on screen.  Assumes screen size of 640x448.\r\n\tfloat\t\t\t\t\tGetXPos() const;\r\n\tfloat\t\t\t\t\tGetYPos() const;\r\n\tvoid\t\t\t\t\tSetPos(float x, float y);\r\n\r\n\t// Actual width and height of sprite.  If textured, it will also\r\n\t// use this for the texture width and height.\r\n\tuint16\t\t\t\t\tGetWidth() const;\r\n\tuint16\t\t\t\t\tGetHeight() const;\r\n\tvoid\t\t\t\t\tSetSize(uint16 w, uint16 h);\r\n\r\n\t// Scale of sprite.  A negative scale will flip the axis.\r\n\tfloat\t\t\t\t\tGetXScale() const;\r\n\tfloat\t\t\t\t\tGetYScale() const;\r\n\tvoid\t\t\t\t\tSetScale(float x, float y);\r\n\r\n\t// The anchor position of the sprite.  Basically, the origin within\r\n\t// the sprite.  This point is going to be at the screen position.  It\r\n\t// is also the point of rotation.  The range is [-1.0, 1.0], where\r\n\t// (-1.0, -1.0) is the top left corner and (1.0, 1.0) is the bottom\r\n\t// right corner.\r\n\tfloat\t\t\t\t\tGetXAnchor() const;\r\n\tfloat\t\t\t\t\tGetYAnchor() const;\r\n\tvoid\t\t\t\t\tSetAnchor(float x, float y);\r\n\r\n\t// Rotation of sprite in radians\r\n\tfloat\t\t\t\t\tGetRotation() const;\r\n\tvoid\t\t\t\t\tSetRotation(float rot);\r\n\r\n\t// Priority of sprite from 0.0 to 1.0.  Higher priority sprites are\r\n\t// drawn on top of lower priority sprites.\r\n\tfloat\t\t\t\t\tGetPriority() const;\r\n\tvoid\t\t\t\t\tSetPriority(float pri);\r\n\tNx::ZBufferValue\t\tGetZValue() const;\r\n\tvoid\t\t\t\t\tSetZValue(Nx::ZBufferValue z);\r\n\r\n\t// Color of sprite.  All 4 corners are the same.\r\n\tImage::RGBA\t\t\t\tGetRGBA() const;\r\n\tvoid\t\t\t\t\tSetRGBA(Image::RGBA rgba);\r\n\r\n\t// Clipping window\r\n\tCWindow2D *\t\t\t\tGetWindow() const;\r\n\tvoid\t\t\t\t\tSetWindow(CWindow2D *p_window);\r\n\r\n\t// Constant z-buffer value (only affect sprites using a priority)\r\n\tstatic void\t\t\t\tEnableConstantZValue(bool enable);\r\n\tstatic void\t\t\t\tSetConstantZValue(Nx::ZBufferValue z);\r\n\tstatic Nx::ZBufferValue\tGetConstantZValue();\r\n\r\nprotected:\r\n\tCTexture *\t\t\t\tmp_texture;\t\t\t\t// Texture\r\n\r\n\tfloat\t\t\t\t\tm_pos_x;\t\t\t\t// Position\r\n\tfloat\t\t\t\t\tm_pos_y;\r\n\tfloat\t\t\t\t\tm_scale_x;\t\t\t\t// Scale\r\n\tfloat\t\t\t\t\tm_scale_y;\r\n\tfloat\t\t\t\t\tm_anchor_x;\t\t\t\t// Anchor Position\r\n\tfloat\t\t\t\t\tm_anchor_y;\r\n\r\n\tfloat\t\t\t\t\tm_rotation;\t\t\t\t// Rotation\r\n\tfloat\t\t\t\t\tm_priority;\t\t\t\t// Priority\r\n\tZBufferValue\t\t\tm_zvalue;\t\t\t\t// for zbuffer sort\r\n\r\n\tuint16\t\t\t\t\tm_width;\t\t\t\t// Size\r\n\tuint16\t\t\t\t\tm_height;\r\n\r\n\tbool\t\t\t\t\tm_hidden;\t\t\t\t// Hidden\r\n\tbool\t\t\t\t\tm_use_zbuffer;\r\n\tImage::RGBA\t\t\t\tm_rgba;\t\t\t\t\t// Color\r\n\r\n\tCWindow2D *\t\t\t\tmp_window;\r\n\r\nprivate:\r\n\tvirtual void\t\t\tplat_initialize();\r\n\r\n\tvirtual void\t\t\tplat_update_hidden();\t\t// Tell engine of update\r\n\tvirtual void\t\t\tplat_update_engine();\t\t// Update engine primitives\r\n\tvirtual void\t\t\tplat_update_priority();\r\n\tvirtual void\t\t\tplat_update_window();\r\n\r\n\tstatic void\t\t\t\tplat_enable_constant_z_value(bool enable);\r\n\tstatic void\t\t\t\tplat_set_constant_z_value(Nx::ZBufferValue z);\r\n\tstatic Nx::ZBufferValue\tplat_get_constant_z_value();\r\n};\r\n\r\n/////////////////////////////////////////////////////////\r\n// CSprite inline function\r\ninline bool\t\t\t\t\tCSprite::IsHidden() const\r\n{\r\n\treturn m_hidden;\r\n}\r\n\r\ninline CTexture *\t\t\tCSprite::GetTexture() const\r\n{\r\n\treturn mp_texture;\r\n}\r\n\r\ninline float\t\t\t\tCSprite::GetXPos() const\r\n{\r\n\treturn m_pos_x;\r\n}\r\n\r\ninline float\t\t\t\tCSprite::GetYPos() const\r\n{\r\n\treturn m_pos_y;\r\n}\r\n\r\ninline uint16\t\t\t\tCSprite::GetWidth() const\r\n{\r\n\treturn m_width;\r\n}\r\n\r\ninline uint16\t\t\t\tCSprite::GetHeight() const\r\n{\r\n\treturn m_height;\r\n}\r\n\r\ninline float\t\t\t\tCSprite::GetXScale() const\r\n{\r\n\treturn m_scale_x;\r\n}\r\n\r\ninline float\t\t\t\tCSprite::GetYScale() const\r\n{\r\n\treturn m_scale_y;\r\n}\r\n\r\ninline float\t\t\t\tCSprite::GetXAnchor() const\r\n{\r\n\treturn m_anchor_x;\r\n}\r\n\r\ninline float\t\t\t\tCSprite::GetYAnchor() const\r\n{\r\n\treturn m_anchor_y;\r\n}\r\n\r\ninline float\t\t\t\tCSprite::GetRotation() const\r\n{\r\n\treturn m_rotation;\r\n}\r\n\r\ninline float\t\t\t\tCSprite::GetPriority() const\r\n{\r\n\treturn m_priority;\r\n}\r\n\r\ninline ZBufferValue\t\t\tCSprite::GetZValue() const\r\n{\r\n\treturn m_zvalue;\r\n}\r\n\r\ninline Image::RGBA\t\t\tCSprite::GetRGBA() const\r\n{\r\n\treturn m_rgba;\r\n}\r\n\r\ninline CWindow2D *\t\t\tCSprite::GetWindow() const\r\n{\r\n\treturn mp_window;\r\n}\r\n\r\n}\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxTexMan.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxTexMan.cpp\r\n\r\n// start autoduck documentation\r\n// @DOC nxtexman\r\n// @module nxtexman | None\r\n// @subindex Scripting Database\r\n// @index script | nxtexman\r\n\r\n#include <core/defines.h>\r\n#include <core/crc.h>\r\n#include <gel/Scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\n#include \"gfx/NxTexMan.h\"\r\n#include \"gfx/NxSprite.h\"\r\n#include \"gfx/Nx.h\"\r\n\r\n#include <sys/config/config.h>\r\n\r\n// for downloading faces\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/skaterprofile.h>\r\n#include <gfx/facetexture.h>\r\n#include <gfx/modelappearance.h>\r\n\r\nnamespace\tNx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// CTexMan\r\n\r\nLst::HashTable<CTexDict>\tCTexDictManager::s_tex_dict_lookup(4);\r\n\r\n// temporary sprite texture dictionary\r\nCTexDict *\t\t\t\t\tCTexDictManager::sp_sprite_tex_dict = sCreateTextureDictionary(\"sprite\");\r\nCTexDict *\t\t\t\t\tCTexDictManager::sp_particle_tex_dict = sCreateTextureDictionary(\"particle\");\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// These functions are the platform independent part of the interface.\r\n\t\t\t\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexDict *\t\t\tCTexDictManager::sCreateTextureDictionary(const char *p_tex_dict_name)\r\n{\r\n\tCTexDict *p_dict;\r\n\tuint32 checksum = Crc::GenerateCRCFromString(p_tex_dict_name);\r\n\r\n\tp_dict = sGetTextureDictionary(checksum);\r\n\r\n\t// Assert for now unless we can think of a reason to use with ref counts\r\n\tDbg_MsgAssert((p_dict == NULL), (\"Texture dictionary %s already exists\", p_tex_dict_name));\r\n\r\n\tif (p_dict)\t\r\n\t{\r\n\t\t// If already loaded, then just link up with it\r\n\t\tp_dict->IncRefCount();\r\n\t} else {\r\n\t\tp_dict = s_plat_create_texture_dictionary(checksum);\r\n\t\ts_tex_dict_lookup.PutItem(checksum, p_dict);\r\n\t}\r\n\treturn p_dict;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexDict *\t\t\tCTexDictManager::sLoadTextureDictionary(uint32 fileNameChecksum, uint32* pData, int dataSize, bool isLevelData, uint32 texDictOffset, bool isSkin, bool forceTexDictLookup )\r\n{\r\n\tMem::PushMemProfile((char*)\"TEX_data_buffer\");\r\n\r\n\tuint32 checksum = fileNameChecksum + texDictOffset;\r\n\r\n\tCTexDict *p_dict;\r\n\tp_dict = sGetTextureDictionary(checksum);\r\n\r\n\tif (p_dict)\t\r\n\t{\r\n\t\t// Mick: temporary assertion to track down annoyingly persisten phantom texture dcitionaries\r\n\t\t// you can probably remove this\r\n\t\t//Dbg_MsgAssert(0,(\"Not supposed to be multiply using tex dicts yet! (%s/%x)\",texture_dict_name,texDictOffset));\r\n\r\n\t\t// If already loaded, then just link up with it\r\n\t\tp_dict->IncRefCount();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_dict = s_plat_load_texture_dictionary(checksum, pData, dataSize, isLevelData, texDictOffset, isSkin, forceTexDictLookup);\r\n\t\tp_dict->set_checksum(checksum);\t\t\t// Since it just uses the base name\r\n\t\ts_tex_dict_lookup.PutItem(checksum, p_dict);\r\n\t}\r\n\r\n\tMem::PopMemProfile(/*(char*)\"TEX_data_buffer\"*/);\r\n\r\n\treturn p_dict;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexDict *\t\t\tCTexDictManager::sLoadTextureDictionary(const char *p_tex_dict_name, bool isLevelData, uint32 texDictOffset, bool isSkin, bool forceTexDictLookup )\r\n{\r\n\t// append the extension\r\n\tchar\ttexture_dict_name[128];\r\n\tsprintf(texture_dict_name,\"%s.%s\",p_tex_dict_name,CEngine::sGetPlatformExtension());\r\n\r\n\tMem::PushMemProfile((char*)p_tex_dict_name);\r\n\t\r\n\t// the texDictOffset prevents clashes when we need multiple\r\n\t// separate versions of the same texture dictionary, such as\r\n\t// for multiplayer create-a-skater parts (note:  peds should not\r\n\t// use this system because they should share actual texture\r\n\t// dictionaries)\r\n\tuint32 checksum = Crc::GenerateCRCFromString(p_tex_dict_name) + texDictOffset;\r\n\r\n\tCTexDict *p_dict;\r\n\tp_dict = sGetTextureDictionary(checksum);\r\n\r\n\tif (p_dict)\t\r\n\t{\r\n\t\t// Mick: temporary assertion to track down annoyingly persisten phantom texture dcitionaries\r\n\t\t// you can probably remove this\r\n\t\t//Dbg_MsgAssert(0,(\"Not supposed to be multiply using tex dicts yet! (%s/%x)\",texture_dict_name,texDictOffset));\r\n\r\n\t\t// If already loaded, then just link up with it\r\n\t\tp_dict->IncRefCount();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_dict = s_plat_load_texture_dictionary(texture_dict_name, isLevelData, texDictOffset, isSkin, forceTexDictLookup);\r\n\t\tp_dict->set_checksum(checksum);\t\t\t// Since it just uses the base name\r\n\t\ts_tex_dict_lookup.PutItem(checksum, p_dict);\r\n\t}\r\n\r\n\tMem::PopMemProfile(/*(char*)p_tex_dict_name*/);\r\n\r\n\treturn p_dict;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCTexDictManager::sUnloadTextureDictionary(CTexDict *p_tex_dict)\r\n{\r\n\tif (p_tex_dict->DecRefCount() == 0)\r\n\t{\r\n\t\ts_tex_dict_lookup.FlushItem(p_tex_dict->GetChecksum());  // Remove the reference to it before we delete it\r\n\t\ts_plat_unload_texture_dictionary(p_tex_dict);\t\t\t // as deleting it can kill the checksum with memory trashing\r\n\t\treturn TRUE;\r\n\t}\r\n\r\n\treturn FALSE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexDict *\t\t  \tCTexDictManager::sGetTextureDictionary(uint32 checksum)\r\n{\r\n\treturn s_tex_dict_lookup.GetItem(checksum);\r\n}\r\n\r\n\r\n// @script | LoadTexture | Loads a 2D sprite texture\r\n// @parm string |  | path and name of texture\r\n// @flag no_vram_alloc | won't allocate in vram\r\nbool ScriptLoadTexture(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_name;\r\n\tif (!pParams->GetText(NONAME, &p_name))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\r\n\tbool alloc_vram = true;\r\n\tif (pParams->ContainsFlag(CRCD(0x3955ff2e,\"no_vram_alloc\")))\r\n\t{\r\n\t\talloc_vram = false;\r\n\t}\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->LoadTexture(p_name, true, alloc_vram);\r\n\r\n\treturn p_texture != NULL;\r\n}\r\n\r\n\r\n\r\n// @script | UnloadTexture | Unloads a 2D sprite texture\r\n// @parm string |  | name of texture\r\nbool ScriptUnloadTexture(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tCTexture *p_texture = NULL;\r\n\tconst char *p_name;\r\n\tuint32 checksum;\r\n\r\n\tif (pParams->GetText(NONAME, &p_name))\r\n\t{\r\n\t\t// get texture based on string\r\n\t\tp_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(p_name);\r\n\t}\r\n\telse if (pParams->GetChecksum(NONAME, &checksum))\r\n\t{\t\t\t\t\t\t\t \r\n\t\t// get texture based on checksum\r\n\t\tp_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"no texture specified in %s\", pScript->GetScriptInfo()));\r\n\t}\r\n\r\n\tif (p_texture)\r\n\t{\r\n\t\tCTexDictManager::sp_sprite_tex_dict->UnloadTexture(p_texture);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( !pParams->ContainsFlag( CRCD(0x3d92465e,\"dont_assert\") ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"Can't find texture %s to unload\", p_name));\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n// @script | AddTextureToVram | Puts 2D sprite texture into VRAM (so it is drawable)\r\n// @parm string |  | name of texture\r\nbool ScriptAddTextureToVram(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n#if 0\r\n\tconst char *p_name;\r\n\tif (!pParams->GetText(NONAME, &p_name))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(p_name);\r\n\tif (p_texture)\r\n\t{\r\n\t\tp_texture->AddToVram();\r\n\t} else {\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to add to vram\", p_name));\r\n\t}\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | RemoveTextureFromVram | Removes 2D sprite texture from VRAM\r\n// @parm string |  | name of texture\r\n// @flag no_assert | won't assert on failure\r\nbool ScriptRemoveTextureFromVram(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n#if 0\r\n\tconst char *p_name;\r\n\tif (!pParams->GetText(NONAME, &p_name))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(p_name);\r\n\tif (p_texture)\r\n\t{\r\n\t\tp_texture->RemoveFromVram();\r\n\t} else if (!pParams->ContainsFlag(CRCD(0x512c7426,\"no_assert\"))) {\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to remove from vram\", p_name));\r\n\t}\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | LoadFaceTextureFromProfile | Loads a 2D sprite texture\r\nbool ScriptLoadFaceTextureFromProfile(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    bool alloc_vram = true;\r\n\tuint32 checksum;\r\n    pParams->GetChecksum( \"checksum\", &checksum, Script::ASSERT );\r\n\t\r\n    // Copy the downloaded face for use as a sprite\r\n    Mdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n    Obj::CSkaterProfile* pSkaterProfile = skate_mod->GetCurrentProfile();\r\n    Dbg_Assert( pSkaterProfile );\r\n    Dbg_MsgAssert( !pSkaterProfile->IsPro(), ( \"Can only map face onto a custom skater.  UI must make the custom skater active before this point\" ) );\r\n    Gfx::CModelAppearance* pAppearance = pSkaterProfile->GetAppearance();\r\n    Dbg_Assert( pAppearance );\r\n    Gfx::CFaceTexture* pFaceTexture = pAppearance->GetFaceTexture();\r\n\r\n\tDbg_MsgAssert(pFaceTexture,(\"NULL pFaceTexture\"));\r\n\tDbg_MsgAssert(pFaceTexture->IsValid(),(\"Invalid pFaceTexture\"));\r\n\r\n    Nx::CTexture* p_texture = Nx::CTexDictManager::sp_sprite_tex_dict->LoadTextureFromBuffer(pFaceTexture->GetTextureData(), pFaceTexture->GetTextureSize(), checksum, true, alloc_vram);\r\n    Dbg_MsgAssert( p_texture, ( \"Appearance has no face texture\" ) );\r\n\r\n\r\n\treturn p_texture != NULL;\r\n}\r\n\r\n// @script | Generate32BitImage | Generates 32bit image data for texture\r\n// @parm name |  | name of texture\r\n// @parmopt int | renderable | 0 | If set to 1, make 32-bit image renderable in a sprite\r\n// @parmopt int | store_original | 0 | If set to 1, keeps original 32-bit image around that can be used with some functions\r\nbool ScriptGenerate32BitImage(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(NONAME, &checksum))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\tif (p_texture)\r\n\t{\r\n\t\tint value;\r\n\t\tbool renderable = false;\r\n\t\tbool store_original = false;\r\n\r\n\t\tif (pParams->GetInteger(CRCD(0xa5d7cfaa,\"renderable\"), &value) && (value == 1))\r\n\t\t{\r\n\t\t\trenderable = true;\r\n\t\t}\r\n\t\tif (pParams->GetInteger(CRCD(0xeefaf080,\"store_original\"), &value) && (value == 1))\r\n\t\t{\r\n\t\t\tstore_original = true;\r\n\t\t}\r\n\r\n\t\tp_texture->Generate32BitImage(renderable, store_original);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to generate 32-bit image\", Script::FindChecksumName(checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | OffsetTexture | Move texture (cropping the part that moves off and filling in the new parts with\r\n// either the old edge or a supplied fill color)\r\n// @parm name |  | name of texture\r\n// @parm int | x_offset | x offset in pixels\r\n// @parm int | y_offset | y offset in pixels\r\n// @parmopt int | fill_r | 128 | fill color red component\r\n// @parmopt int | fill_g | 128 | fill color green component\r\n// @parmopt int | fill_b | 128 | fill color blue component\r\n// @parmopt int | fill_a | 128 | fill color alpha component\r\nbool ScriptOffsetTexture(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(NONAME, &checksum))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\tif (p_texture)\r\n\t{\r\n\t\tint x_offset = 0;\r\n\t\tint y_offset = 0;\r\n\t\tbool use_fill_color = false;\r\n\t\tint r = 128, g = 128, b = 128, a = 128;\r\n\r\n\t\tpParams->GetInteger(CRCD(0xd83d589e,\"x_offset\"), &x_offset);\r\n\t\tpParams->GetInteger(CRCD(0x14975800,\"y_offset\"), &y_offset);\r\n\r\n\t\tuse_fill_color |= pParams->GetInteger(CRCD(0xb7a78c53,\"fill_r\"), &r);\r\n\t\tuse_fill_color |= pParams->GetInteger(CRCD(0xda7a68b8,\"fill_g\"), &g);\r\n\t\tuse_fill_color |= pParams->GetInteger(CRCD(0xaa109c37,\"fill_b\"), &b);\r\n\t\tuse_fill_color |= pParams->GetInteger(CRCD(0x3319cd8d,\"fill_a\"), &a);\r\n\r\n\t\tImage::RGBA fill_color(r, g, b, a);\r\n\r\n\t\tp_texture->Offset(x_offset, y_offset, use_fill_color, fill_color);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to offset\", Script::FindChecksumName(checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | AdjustTextureRegion | Stretches and shrinks a texture region from the start point to the end point\r\n// @parm name |  | name of texture\r\n// @parm int | xpos | X position of regiom\r\n// @parm int | ypos | Y position of regiom\r\n// @parm int | width | width of regiom\r\n// @parm int | height | height of regiom\r\n// @parm int | split_axis | axis where the split line crosses (0 = X, 1 = Y)\r\n// @parm int | start_point | split line start point on axis\r\n// @parm int | end_point | split line end point on axis\r\nbool ScriptAdjustTextureRegion(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(NONAME, &checksum))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\tif (p_texture)\r\n\t{\r\n\t\tint x_pos = 0;\r\n\t\tint y_pos = 0;\r\n\t\tint width = p_texture->GetWidth();\r\n\t\tint height = p_texture->GetHeight();\r\n\t\tint split_axis = X;\r\n\t\tint start_point = 0;\r\n\t\tint end_point = 0;\r\n\r\n\t\tpParams->GetInteger(CRCD(0xfa8972e,\"xpos\"), &x_pos);\r\n\t\tpParams->GetInteger(CRCD(0xb714f04b,\"ypos\"), &y_pos);\r\n\t\tpParams->GetInteger(CRCD(0x73e5bad0,\"width\"), &width);\r\n\t\tpParams->GetInteger(CRCD(0xab21af0,\"height\"), &height);\r\n\t\tpParams->GetInteger(CRCD(0xe679982e,\"split_axis\"), &split_axis);\r\n\t\tpParams->GetInteger(CRCD(0x3d0f162a,\"start_point\"), &start_point);\r\n\t\tpParams->GetInteger(CRCD(0x39c54bde,\"end_point\"), &end_point);\r\n\r\n\t\tp_texture->AdjustRegion(x_pos, y_pos, width, height, split_axis, start_point, end_point);\r\n\t} else {\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to adjust\", Script::FindChecksumName(checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | PullTextureToEdge | Pull texture from point along the axis by num_pixels (+ or - determines the direction)\r\n// and crop anything going outside the texture border.\r\n// @parm name |  | name of texture\r\n// @parm int | point | pull point on axis\r\n// @parm int | axis | axis to pull along (0 = X, 1 = Y)\r\n// @parm int | num_pixels | number of pixels (+ or - determines the direction)\r\nbool ScriptPullTextureToEdge(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(NONAME, &checksum))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\tif (p_texture)\r\n\t{\r\n\t\tint point = 0;\r\n\t\tint axis = X;\r\n\t\tint num_pixels = 0;\r\n\r\n\t\tpParams->GetInteger(CRCD(0x485a0cdb,\"point\"), &point);\r\n\t\tpParams->GetInteger(CRCD(0x7af07905,\"axis\"), &axis);\r\n\t\tpParams->GetInteger(CRCD(0x88cf948c,\"num_pixels\"), &num_pixels);\r\n\r\n\t\tp_texture->PullToEdge(point, axis, num_pixels);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to pull\", Script::FindChecksumName(checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n// @script | PushTextureToPoint | Push texture to point along the axis by num_pixels (+ or - determines the direction)\r\n// and either stretch the edge line or fill it in with a fill color.\r\n// @parm name |  | name of texture\r\n// @parm int | point | pull point on axis\r\n// @parm int | axis | axis to pull along (0 = X, 1 = Y)\r\n// @parm int | num_pixels | number of pixels (+ or - determines the direction)\r\n// @parmopt int | fill_r | 128 | fill color red component\r\n// @parmopt int | fill_g | 128 | fill color green component\r\n// @parmopt int | fill_b | 128 | fill color blue component\r\n// @parmopt int | fill_a | 128 | fill color alpha component\r\nbool ScriptPushTextureToPoint(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(NONAME, &checksum))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\tif (p_texture)\r\n\t{\r\n\t\tint point = 0;\r\n\t\tint axis = X;\r\n\t\tint num_pixels = 0;\r\n\t\tbool use_fill_color = false;\r\n\t\tint r = 128, g = 128, b = 128, a = 128;\r\n\r\n\t\tpParams->GetInteger(CRCD(0x485a0cdb,\"point\"), &point);\r\n\t\tpParams->GetInteger(CRCD(0x7af07905,\"axis\"), &axis);\r\n\t\tpParams->GetInteger(CRCD(0x88cf948c,\"num_pixels\"), &num_pixels);\r\n\r\n\t\tuse_fill_color |= pParams->GetInteger(CRCD(0xb7a78c53,\"fill_r\"), &r);\r\n\t\tuse_fill_color |= pParams->GetInteger(CRCD(0xda7a68b8,\"fill_g\"), &g);\r\n\t\tuse_fill_color |= pParams->GetInteger(CRCD(0xaa109c37,\"fill_b\"), &b);\r\n\t\tuse_fill_color |= pParams->GetInteger(CRCD(0x3319cd8d,\"fill_a\"), &a);\r\n\r\n\t\tImage::RGBA fill_color(r, g, b, a);\r\n\r\n\t\tp_texture->PushToPoint(point, axis, num_pixels, use_fill_color, fill_color);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to push\", Script::FindChecksumName(checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | AdjustTextureBrightness | Scales the texture brightness by the supplied value\r\n// @parm name |  | name of texture\r\n// @parm float | brightness | Brightness value (1.0 = no change)\r\n// @parmopt int | adjust_current | 0 | If set to 1, adjusts the current image, even if the original image exists\r\nbool ScriptAdjustTextureBrightness(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(NONAME, &checksum))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\tif (p_texture)\r\n\t{\r\n\t\tfloat brightness = 1.0f;\r\n\t\tint adjust_current = 0;\r\n\t\tbool force_adjust_current = false;\r\n\r\n\t\tpParams->GetFloat(CRCD(0x2689291c,\"brightness\"), &brightness, true);\r\n\t\tpParams->GetInteger(CRCD(0xc164842a,\"adjust_current\"), &adjust_current);\r\n\t\tif (adjust_current == 1)\r\n\t\t{\r\n\t\t\tforce_adjust_current = true;\r\n\t\t}\r\n\r\n\t\tp_texture->AdjustBrightness(brightness, force_adjust_current);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s\", Script::FindChecksumName(checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | AdjustTextureHSV | Scales the texture HSV by the supplied values\r\n// @parm name |  | name of texture\r\n// @parm float | h | Hue offset (0 - 360)\r\n// @parm float | s | Saturation scale (1.0 = no change)\r\n// @parm float | v | Brightness scale (1.0 = no change)\r\n// @parmopt int | adjust_current | 0 | If set to 1, adjusts the current image, even if the original image exists\r\nbool ScriptAdjustTextureHSV(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(NONAME, &checksum))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\tif (p_texture)\r\n\t{\r\n\t\tfloat h = 0.0f;\r\n\t\tfloat s = 1.0f;\r\n\t\tfloat v = 1.0f;\r\n\t\tint adjust_current = 0;\r\n\t\tbool force_adjust_current = false;\r\n\r\n\t\tbool got_params;\r\n\t\tgot_params = pParams->GetFloat(CRCD(0x6e94f918,\"h\"), &h);\r\n\t\tgot_params = pParams->GetFloat(CRCD(0xe4f130f4,\"s\"), &s) && got_params;\r\n\t\tgot_params = pParams->GetFloat(CRCD(0x949bc47b,\"v\"), &v) && got_params;\r\n\r\n\t\tDbg_MsgAssert(got_params, (\"Need to supply values for h, s, and v\"));\r\n\t\tDbg_MsgAssert((h >= 0.0f) && (h <= 360.0f), (\"h must be in the range of 0-360\"));\r\n\t\tDbg_MsgAssert(s >= 0.0f, (\"s cannot be negative\"));\r\n\r\n\t\tpParams->GetInteger(CRCD(0xc164842a,\"adjust_current\"), &adjust_current);\r\n\t\tif (adjust_current == 1)\r\n\t\t{\r\n\t\t\tforce_adjust_current = true;\r\n\t\t}\r\n\r\n\t\tp_texture->AdjustHSV(h, s, v, force_adjust_current);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s\", Script::FindChecksumName(checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n// @script | CopyTexture | Copy 2D sprite texture into a new texture\r\n// @parm name | src | name of texture\r\n// @parm name | new | name of new texture\r\nbool ScriptCopyTexture(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(CRCD(0x9fbbdb72,\"src\"), &checksum))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_sprite_tex_dict->GetTexture(checksum);\r\n\tif (p_texture)\r\n\t{\r\n\t\tuint32 new_checksum;\r\n\t\tif (pParams->GetChecksum(CRCD(0x941cbbba,\"new\"), &new_checksum))\r\n\t\t{\r\n\t\t\tCTexDictManager::sp_sprite_tex_dict->CopyTexture(new_checksum, p_texture);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"no new texture specified\"));\r\n\t\t}\r\n\t} else {\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to copy\", Script::FindChecksumName(checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | CombineTextures | Combine two textures\r\n// @parm name | src | name of orig texture (and final texture if no new texture is supplied)\r\n// @parm name | top | name of top additional texture\r\n// @parmopt name | new | | name of new destination texture\r\n// @parmopt flag | no_palette_gen | | use original palette (faster)\r\nbool ScriptCombineTextures(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 new_checksum = 0;\r\n\tuint32 tex1_checksum;\r\n\tuint32 tex2_checksum;\r\n\tbool gen_palette = true;\r\n\r\n\tif (!pParams->GetChecksum(CRCD(0x9fbbdb72,\"src\"), &tex1_checksum))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"no original source texture specified\"));\r\n\t}\r\n\tif (!pParams->GetChecksum(CRCD(0xe126e035,\"top\"), &tex2_checksum))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"no top source texture specified\"));\r\n\t}\r\n\tpParams->GetChecksum(CRCD(0x941cbbba,\"new\"), &new_checksum);\r\n\tif (pParams->ContainsFlag(CRCD(0x5905256b,\"no_palette_gen\")))\r\n\t{\r\n\t\tgen_palette = false;\r\n\t}\r\n\r\n\tCTexture *p_texture1 = CTexDictManager::sp_sprite_tex_dict->GetTexture(tex1_checksum);\r\n\tif (p_texture1)\r\n\t{\r\n\t\tCTexture *p_texture2 = CTexDictManager::sp_sprite_tex_dict->GetTexture(tex2_checksum);\r\n\t\tif (p_texture2)\r\n\t\t{\r\n\t\t\tif (new_checksum)\r\n\t\t\t{\r\n\t\t\t\t// Make new texture\r\n\t\t\t\tCTexDictManager::sp_sprite_tex_dict->CombineTextures(new_checksum, p_texture1, p_texture2, gen_palette);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Just overwrite original texture\r\n\t\t\t\tp_texture1->CombineTextures(p_texture2, gen_palette);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"Can't find texture %s to combine\", Script::FindChecksumName(tex2_checksum)));\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to combine\", Script::FindChecksumName(tex1_checksum)));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool ScriptLoadParticleTexture(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_name;\r\n\tif (!pParams->GetText(NONAME, &p_name))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\r\n//\tDbg_MsgAssert(*p_name,(\"%s\\n Empty name string for Particle Texture\\n\",pScript->GetScriptInfo()));\r\n\r\n\tif (! *p_name)\r\n\t{\r\n\t\tDbg_Message(\"WARNING:  empty name in LoadAllParticleTextures - proabably an old level\\n\");\r\n\t\treturn false;\r\n\t}\r\n\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_particle_tex_dict->GetTexture(p_name);\r\n\t\r\n\tbool\tperm = pParams->ContainsFlag(CRCD(0xd5928f25,\"perm\"));\r\n\t\r\n\tif (!p_texture)\r\n\t{\r\n\t\tp_texture = CTexDictManager::sp_particle_tex_dict->LoadTexture(p_name, true, true, perm);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// The testure is already there\r\n\t\t// if we are on CD, we assume that's the one we want to load\r\n\t\t// but if not, then we assume we want to re-load the texture\r\n\t\t// for quick previewing by artists\r\n\t\t// so we unload it, and load it up agian\r\n\t\t#ifdef\t__PLAT_NGPS__\t\t\r\n\t\tif (!Config::CD())\r\n\t\t{\t\r\n\t\t\tif (Config::gGotExtraMemory)\r\n\t\t\t{\r\n\t\t\t\t// If we have the extra memory, then use that\r\n\t\t\t\t// to avoid fragmentation when testing variants of perm textures\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t\t\t}\r\n\t\t\tperm = p_texture->IsPerm();\r\n\t\t\tCTexDictManager::sp_particle_tex_dict->UnloadTexture(p_texture);\r\n\t\t\tp_texture = CTexDictManager::sp_particle_tex_dict->LoadTexture(p_name, true, true, perm);\r\n\t\t\tif (Config::gGotExtraMemory)\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t}\r\n\t\t}\r\n\t\t#endif\r\n\t}\r\n\t\r\n\treturn p_texture != NULL;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptUnloadParticleTexture(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_name;\r\n\tif (!pParams->GetText(NONAME, &p_name))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_particle_tex_dict->GetTexture(p_name);\r\n\tif (p_texture)\r\n\t{\r\n\t\tp_texture->RemoveFromVram();\r\n\t\tCTexDictManager::sp_particle_tex_dict->UnloadTexture(p_texture);\r\n\t} else {\r\n\r\n\t\tprintf (\"Can't find particle texture %s to unload\", p_name);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool ScriptLoadSFPTexture(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_name;\r\n\tif (!pParams->GetText(NONAME, &p_name))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_particle_tex_dict->LoadTexture(p_name, false);\r\n\r\n\treturn p_texture != NULL;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptUnloadSFPTexture(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_name;\r\n\tif (!pParams->GetText(NONAME, &p_name))\r\n\t\tDbg_MsgAssert(0, (\"no texture specified\"));\r\n\t\r\n\tCTexture *p_texture = CTexDictManager::sp_particle_tex_dict->GetTexture(p_name);\r\n\tif (p_texture)\r\n\t{\r\n\t\tCTexDictManager::sp_particle_tex_dict->UnloadTexture(p_texture);\r\n\t} else {\r\n\t\tDbg_MsgAssert(0, (\"Can't find texture %s to unload\", p_name));\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool ScriptDumpTextures(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t// Get the hashable that has the textures in it\r\n\tLst::HashTable<CTexture> * p_textures = CTexDictManager::sp_particle_tex_dict->GetTexLookup();\r\n\tp_textures->PrintContents();\r\n\r\n\tp_textures->IterateStart();\r\n\tNx::CTexture *p_tex = p_textures->IterateNext();\t\t\r\n\twhile(p_tex)\r\n\t{\r\n\t\r\n\t\tprintf (\"0x%8x: (%d x %d) %s\\n\",\r\n\t\t\t\t\tp_tex->GetChecksum(),\r\n\t\t\t\t\t p_tex->GetWidth(),\r\n\t\t\t\t\t p_tex->GetHeight(),\r\n\t\t\t\t\t p_tex->GetName()\r\n\t\t\t\t\t);  \r\n\t\r\n\t\tp_tex = p_textures->IterateNext();\t\t\r\n\t}\r\n\t#endif\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\nvoid \tFlushParticleTextures(bool all)\r\n{\r\n   \r\n   CTexDictManager::sp_particle_tex_dict->FlushTextures(all); \r\n\t\r\n}\r\n\r\n\r\n} //end namespace Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxTexMan.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// NxTexMan.H - Neversoft Engine, Rendering portion, Platform independent interface\r\n\r\n#ifndef\t__GFX_NX_TEX_MAN_H__\r\n#define\t__GFX_NX_TEX_MAN_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/hashtable.h>\r\n\r\n#include <gfx/nxtexture.h>\r\n\r\n\r\nnamespace Script\r\n{\r\n\tclass CScriptStructure;\r\n\tclass CScript;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// Nx::CTexDictManager\r\nclass\tCTexDictManager\r\n{\r\npublic:\r\n\r\n\t// Create and destroy CTexDicts\r\n\tstatic CTexDict *\t\t\tsCreateTextureDictionary(const char *p_tex_dict_name);\t// Creates an empty dictionary\r\n\tstatic CTexDict *\t\t\tsLoadTextureDictionary(uint32 checksum, uint32* pData, int dataSize, bool isLevelData, uint32 texDictOffset=0, bool isSkin=0, bool forceTexDictLookup=false );    // Loads dictionary from file\r\n\tstatic CTexDict *\t\t\tsLoadTextureDictionary(const char *p_tex_dict_name, bool isLevelData, uint32 texDictOffset=0, bool isSkin=0, bool forceTexDictLookup=false );    // Loads dictionary from file\r\n\tstatic bool\t\t\t\t\tsUnloadTextureDictionary(CTexDict *p_tex_dict);\r\n\r\n\tstatic CTexDict *  \t\t\tsGetTextureDictionary(uint32 checksum);\t\t// Will not affect ref_count\r\n\r\n\t// temporary sprite texture dictionary\r\n\tstatic CTexDict *\t\t\tsp_sprite_tex_dict;\r\n\tstatic CTexDict *\t\t\tsp_particle_tex_dict;\r\n\r\nprivate:\t\r\n\tstatic Lst::HashTable<CTexDict>\ts_tex_dict_lookup;\r\n\r\n\t// Platform-specific calls\r\n\t// The following two will only be called if a physical load or unload is done\r\n\tstatic CTexDict *\t\t\ts_plat_load_texture_dictionary(const char *p_tex_dict_name, bool is_level_data, uint32 texDictOffset, bool isSkin, bool forceTexDictLookup = false );\r\n\tstatic CTexDict *\t\t\ts_plat_load_texture_dictionary(uint32 checksum, uint32* pData, int dataSize, bool is_level_data, uint32 texDictOffset, bool isSkin, bool forceTexDictLookup = false );\r\n\tstatic CTexDict *\t\t\ts_plat_create_texture_dictionary(uint32 checksum);\r\n\tstatic bool\t\t\t\t\ts_plat_unload_texture_dictionary(CTexDict *p_tex_dict);\r\n};\r\n\r\nbool ScriptLoadTexture(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptUnloadTexture(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptAddTextureToVram(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptRemoveTextureFromVram(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptLoadFaceTextureFromProfile(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptGenerate32BitImage(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptOffsetTexture(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptAdjustTextureRegion(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptPullTextureToEdge(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptPushTextureToPoint(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptAdjustTextureBrightness(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptAdjustTextureHSV(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptCopyTexture(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptCombineTextures(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptLoadParticleTexture(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptUnloadParticleTexture(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptLoadSFPTexture(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptUnloadSFPTexture(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptDumpTextures(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\n\r\nvoid \tFlushParticleTextures(bool all);\r\n\r\n\r\n}\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxTexture.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxTexture.cpp\r\n\r\n#include <core/defines.h>\r\n\r\n#include <core/crc.h>\r\n#include <core/math/vector.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/symboltable.h>\r\n\t\t\t\t\t\t\t\t\t \r\n#include <gfx/nx.h>\r\n#include <gfx/nxtexture.h>\r\n\r\nnamespace\tNx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic uint32 s_convert_filename_to_checksum( const char* pFileName )\r\n{\r\n\t// Find base name\r\n\tint idx\t= strlen(pFileName);\r\n\twhile ((idx > 0) && pFileName[idx - 1] != '\\\\' && pFileName[idx - 1] != '/')\r\n\t\t--idx;\r\n\r\n\tconst char *p_base_name = &(pFileName[idx]);\r\n\r\n\treturn Crc::GenerateCRCFromString(p_base_name);\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// CTexture\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// These functions are the platform independent part of the interface.\r\n\t\t\t\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture::CTexture()\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tmp_name = NULL;\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture::CTexture(const CTexture & src_texture)\r\n{\r\n\tm_checksum = src_texture.m_checksum;\r\n\tm_perm = src_texture.m_perm;\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tmp_name = new char[strlen(\"Copy of \")+strlen(src_texture.mp_name)+1];\r\n\tsprintf (mp_name,\"Copy of %s\",src_texture.mp_name);\t\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture::~CTexture()\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tif (mp_name)\r\n\t{\r\n\t\tdelete [] mp_name;\r\n\t}\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::LoadTexture(const char *p_texture_name, bool sprite, bool alloc_vram)\r\n{\t\t\t\t\t\t\t\t \t\r\n#ifdef\t__NOPT_ASSERT__\r\n\tmp_name = new char[strlen(p_texture_name)+1];\r\n\tsprintf (mp_name,\"%s\",p_texture_name);\t\r\n#endif\r\n\r\n\tchar texture_name[512];\r\n\tsprintf(texture_name,\"%s\",p_texture_name);\r\n\tif (sprite)\r\n\t{\r\n\r\n\t\tif (p_texture_name[0]=='.'\r\n\t\t\t&& p_texture_name[1]=='.'\r\n\t\t\t&& p_texture_name[2]=='/')\r\n\t\t{\r\n\t\t\t// detected a ../ at the start of the file name, so use the full file name\r\n\t\t\tsprintf(texture_name,\"%s\",p_texture_name+3);\r\n\t\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsprintf(texture_name,\"images/%s\",p_texture_name);\r\n\t\t}\r\n\t}\r\n\t\r\n\tm_checksum = s_convert_filename_to_checksum( texture_name );\r\n\t\r\n\treturn plat_load_texture(texture_name, sprite, alloc_vram);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::LoadTextureFromBuffer(uint8* p_buffer, int buffer_size, uint32 texture_checksum, bool sprite, bool alloc_vram)\r\n{\t\t\t\t\t\t\t\t \t\r\n#ifdef\t__NOPT_ASSERT__\r\n\tconst char* p_name = Script::FindChecksumName(texture_checksum);\r\n\tmp_name = new char[strlen(p_name)+1];\r\n\tsprintf (mp_name,\"%s\",p_name);\t\r\n#endif\r\n\tm_checksum = texture_checksum;\r\n\treturn plat_load_texture_from_buffer(p_buffer, buffer_size, sprite, alloc_vram);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::ReplaceTexture(CTexture *p_texture)\r\n{\t\t\t\t\t\t\t\t \t\r\n\treturn plat_replace_texture(p_texture);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::Generate32BitImage(bool renderable, bool store_original)\r\n{\r\n\treturn plat_generate_32bit_image(renderable, store_original);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::Put32BitImageIntoTexture(bool new_palette)\r\n{\r\n\treturn plat_put_32bit_image_into_texture(new_palette);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::Offset(int x_pixels, int y_pixels, bool use_fill_color, Image::RGBA fill_color)\r\n{\r\n\tDbg_MsgAssert(abs(x_pixels) < GetWidth(), (\"x_pixels is out of range: %d\", x_pixels));\r\n\tDbg_MsgAssert(abs(y_pixels) < GetHeight(), (\"y_pixels is out of range: %d\", y_pixels));\r\n\r\n\treturn plat_offset(x_pixels, y_pixels, use_fill_color, fill_color);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::AdjustRegion(uint16 x_pos, uint16 y_pos, uint16 width, uint16 height,\r\n\t\t\t\t\t\t\t   int split_axis, uint16 start_point, uint16 end_point)\r\n{\r\n\tDbg_MsgAssert((split_axis >= X) && (split_axis <= Y), (\"Split axis is out of range: %d\", split_axis));\r\n\tDbg_MsgAssert(x_pos < GetWidth(), (\"x_pos is out of range: %d\", x_pos));\r\n\tDbg_MsgAssert(y_pos < GetHeight(), (\"y_pos is out of range: %d\", y_pos));\r\n\tDbg_MsgAssert(width <= GetWidth(), (\"width is out of range: %d\", width));\r\n\tDbg_MsgAssert(height <= GetHeight(), (\"height is out of range: %d\", height));\r\n\r\n\treturn plat_adjust_region(x_pos, y_pos, width, height, split_axis, start_point, end_point);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::PullToEdge(uint16 point, int axis, int num_pixels)\r\n{\r\n\tDbg_MsgAssert((axis >= X) && (axis <= Y), (\"axis is out of range: %d\", axis));\r\n\r\n\treturn plat_pull_to_edge(point, axis, num_pixels);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::PushToPoint(uint16 point, int axis, int num_pixels, bool use_fill_color, Image::RGBA fill_color)\r\n{\r\n\tDbg_MsgAssert((axis >= X) && (axis <= Y), (\"axis is out of range: %d\", axis));\r\n\r\n\treturn plat_push_to_point(point, axis, num_pixels, use_fill_color, fill_color);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::AdjustBrightness(float brightness_scale, bool force_adjust_current)\r\n{\r\n\treturn plat_adjust_brightness(brightness_scale, force_adjust_current);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::AdjustHSV(float h, float s, float v, bool force_adjust_current)\r\n{\r\n\treturn plat_adjust_hsv(h, s, v, force_adjust_current);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::AddToVram()\r\n{\t\t\t\t\t\t\t\t \t\r\n\treturn plat_add_to_vram();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::RemoveFromVram()\r\n{\t\t\t\t\t\t\t\t \t\r\n\treturn plat_remove_from_vram();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tCTexture::GetChecksum() const\r\n{\r\n\treturn m_checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint16\tCTexture::GetWidth() const\r\n{\r\n\treturn plat_get_width();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint16\tCTexture::GetHeight() const\r\n{\r\n\treturn plat_get_height();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\tCTexture::GetBitDepth() const\r\n{\r\n\treturn plat_get_bitdepth();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\tCTexture::GetPaletteBitDepth() const\r\n{\r\n\treturn plat_get_palette_bitdepth();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\tCTexture::GetNumMipmaps() const\r\n{\r\n\treturn plat_get_num_mipmaps();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::IsTransparent() const\r\n{\r\n\treturn plat_is_transparent();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::CombineTextures(CTexture *p_texture, bool palette_gen)\r\n{\r\n\treturn plat_combine_textures(p_texture, palette_gen);\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stub versions of all platform specific functions are provided here:\r\n// so engine implementors can leave certain functionality until later\r\n\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_load_texture(const char *p_texture_name, bool sprite, bool alloc_vram)\r\n{\r\n\tprintf (\"STUB: PlatLoadTexture\\n\");\r\n\tDbg_Assert(0);\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_load_texture_from_buffer(uint8* p_buffer, int buffer_size, bool sprite, bool alloc_vram)\r\n{\r\n\tprintf (\"STUB: PlatLoadTextureFromBuffer\\n\");\r\n\tDbg_MsgAssert(0, (\"This function was only supposed to be called on the PS2\"));\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_replace_texture(CTexture *p_texture)\r\n{\t\t\t\t\t\t\t\t \t\r\n\tprintf (\"STUB: PlatReplaceTexture\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_generate_32bit_image(bool renderable, bool store_original)\r\n{\r\n\tprintf (\"STUB: PlatGenerate32BitImage\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_put_32bit_image_into_texture(bool new_palette)\r\n{\r\n\tprintf (\"STUB: PlatPut32BitImageIntoTexture\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_offset(int x_pixels, int y_pixels, bool use_fill_color, Image::RGBA fill_color)\r\n{\r\n\tprintf (\"STUB: PlatOffset\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_adjust_region(uint16 x_pos, uint16 y_pos, uint16 width, uint16 height,\r\n\t\t\t\t\t\t\t\t\t int split_axis, uint16 start_point, uint16 end_point)\r\n{\t\t\t\t\t\t\t\t \t\r\n\tprintf (\"STUB: PlatAdjustRegion\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_pull_to_edge(uint16 point, int axis, int num_pixels)\r\n{\r\n\tprintf (\"STUB: PlatPullToEdge\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_push_to_point(uint16 point, int axis, int num_pixels, bool use_fill_color, Image::RGBA fill_color)\r\n{\r\n\tprintf (\"STUB: PlatPushToPoint\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_adjust_brightness(float brightness_scale, bool force_adjust_current)\r\n{\r\n\tprintf (\"STUB: PlatAdjustBrightness\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_adjust_hsv(float h, float s, float v, bool force_adjust_current)\r\n{\r\n\tprintf (\"STUB: PlatAdjustHSV\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_add_to_vram()\r\n{\t\t\t\t\t\t\t\t \t\r\n\tprintf (\"STUB: PlatAddToVram\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_remove_from_vram()\r\n{\t\t\t\t\t\t\t\t \t\r\n\tprintf (\"STUB: PlatRemoveFromVram\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint16\tCTexture::plat_get_width() const\r\n{\r\n\tprintf (\"STUB: PlatGetWidth\\n\");\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint16\tCTexture::plat_get_height() const\r\n{\r\n\tprintf (\"STUB: PlatGetHeight\\n\");\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\tCTexture::plat_get_bitdepth() const\r\n{\r\n\tprintf (\"STUB: PlatGetBitDepth\\n\");\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\tCTexture::plat_get_palette_bitdepth() const\r\n{\r\n\tprintf (\"STUB: PlatGetPaletteBitDepth\\n\");\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\tCTexture::plat_get_num_mipmaps() const\r\n{\r\n\tprintf (\"STUB: PlatGetNumMipmaps\\n\");\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_is_transparent() const\r\n{\r\n\tprintf (\"STUB: PlatIsTransparent\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTexture::plat_combine_textures(CTexture *p_texture, bool palette_gen)\r\n{\r\n\tprintf (\"STUB: PlatCombineTextures\\n\");\r\n\treturn false;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// CMaterial\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMaterial::CMaterial() : mp_texture(NULL)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA\t\t\tCMaterial::GetRGBA() const\r\n{\r\n\treturn plat_get_rgba();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCMaterial::SetRGBA(Image::RGBA rgba)\r\n{\r\n\tplat_set_rgba(rgba);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\t\tCMaterial::GetTexture() const\r\n{\r\n\treturn mp_texture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCMaterial::SetTexture(CTexture *tex)\r\n{\r\n\tmp_texture = tex;\r\n\tplat_set_texture(tex);\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stub versions of all platform specific functions:\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nImage::RGBA \t\tCMaterial::plat_get_rgba() const\r\n{\r\n\tprintf (\"STUB: PlatGetRGBA\\n\");\r\n\treturn Image::RGBA();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCMaterial::plat_set_rgba(Image::RGBA rgba)\r\n{\r\n\tprintf (\"STUB: PlatSetRGBA\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCMaterial::plat_set_texture(CTexture *tex)\r\n{\r\n\tprintf (\"STUB: PlatSetTexture\\n\");\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// CTexDict\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexDict::CTexDict(uint32 checksum, bool create_lookup_table)\r\n{\r\n\tm_checksum = checksum;\r\n\tm_ref_count = 1;\t// Belongs to someone\r\n\t\r\n\t// Mick: for now, since most texture dictionaries don't need to reference\r\n\t// the textures by name, we only created the lookup table when it is needed\r\n\t// so we save memory\t\r\n\t// Gary: Well, actually, the create-a-skater texture dictionaries\r\n\t// do need lookup tables, just in case there's texture\r\n\t// replacement.  So, this constructor should be rewritten so\r\n\t// that it takes a parameter telling it whether it should\r\n\t// create the hashtable.\r\n\t// Garrett: OK\r\n\tif (create_lookup_table)\r\n\t{\r\n\t\tmp_texture_lookup = new Lst::HashTable<CTexture>(5);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_texture_lookup = NULL;\r\n\t}\r\n\r\n\t// Derived class loads the actual file\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexDict::CTexDict(const char* p_tex_dict_name, bool create_lookup_table)\r\n{\r\n\tm_checksum = Crc::GenerateCRCFromString(p_tex_dict_name);\r\n\tm_ref_count = 1;\t// Just belong to one scene\r\n\r\n\t// Mick: for now, since most texture dictionaries don't need to reference\r\n\t// the textures by name, we only created the lookup table when it is needed\r\n\t// so we save memory\t\r\n\t// Gary: Well, actually, the create-a-skater texture dictionaries\r\n\t// do need lookup tables, just in case there's texture\r\n\t// replacement.  So, this constructor should be rewritten so\r\n\t// that it takes a parameter telling it whether it should\r\n\t// create the hashtable.\r\n\t// Garrett: OK\r\n\tif (create_lookup_table)\r\n\t{\r\n\t\tmp_texture_lookup = new Lst::HashTable<CTexture>(5);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_texture_lookup = NULL;\r\n\t}\r\n\r\n\t// Derived class loads the actual file\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexDict::~CTexDict()\r\n{\r\n\t// Unload everything\r\n\t//plat_unload_texture_dictionary();\t\t\t\t\t// the derived class does this\r\n\r\n\tFlushTextures(true);\r\n\r\n\tif (mp_texture_lookup)\r\n\t{\r\n\t\tdelete mp_texture_lookup;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Flush all non permanent textures\r\nvoid CTexDict::FlushTextures(bool flush_all)\r\n{\r\n\tif (mp_texture_lookup)\r\n\t{\r\n\t\t// Delete textures\r\n\t\tmp_texture_lookup->IterateStart();\r\n\t\tCTexture *p_texture = mp_texture_lookup->IterateNext();\r\n\t\twhile (p_texture)\r\n\t\t{\r\n\t\t\tCTexture *p_next = mp_texture_lookup->IterateNext();\r\n\t\t\tif (flush_all || !p_texture->IsPerm())\r\n\t\t\t{\r\n\t\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\t\tif (p_texture->GetName())\r\n\t\t\t\t{\r\n//\t\t\t\t\tprintf (\"deleting particle tex %s\\n\",p_texture->GetName());\r\n\t\t\t\t}\r\n\t\t\t\t#endif\t\t\t\t\r\n\t\t\t\tuint32 checksum = p_texture->GetChecksum();\t\t\t\r\n\t\t\t\tdelete p_texture;\r\n\t\t\t\tmp_texture_lookup->FlushItem(checksum);\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\t\tif (p_texture->GetName())\r\n\t\t\t\t{\r\n//\t\t\t\t\tprintf (\"NOT deleting particle tex %s  perm = %d\\n\",p_texture->GetName(),p_texture->IsPerm());\r\n\t\t\t\t}\r\n\t\t\t\t#endif\t\t\t\t\r\n\r\n\t\t\t}\r\n\t\t\tp_texture = p_next;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\t\tCTexDict::LoadTexture(const char *p_texture_name, bool sprite, bool alloc_vram, bool perm)\r\n{\r\n\tMem::PushMemProfile((char*)p_texture_name);\r\n\t\r\n\t\r\n\tCTexture *p_texture = plat_load_texture(p_texture_name, sprite, alloc_vram);\r\n\r\n\tif (p_texture)\r\n\t{\r\n\t\tp_texture->SetPerm(perm);\r\n\t\tmp_texture_lookup->PutItem(p_texture->GetChecksum(), p_texture);\r\n\t\t\r\n\t} else {\r\n\t\tDbg_Error(\"Texture %s not found\", p_texture_name);\r\n\t}\r\n\r\n\tMem::PopMemProfile();\r\n\treturn p_texture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture * \t\t\tCTexDict::LoadTextureFromBuffer(uint8* p_buffer, int buffer_size, uint32 texture_checksum, bool sprite, bool alloc_vram, bool perm)\r\n{\r\n\tMem::PushMemProfile((char*)\"texture from buffer\");\r\n\tCTexture *p_texture = plat_load_texture_from_buffer(p_buffer, buffer_size, texture_checksum, sprite, alloc_vram);\r\n\r\n\tif (p_texture)\r\n\t{\r\n\t\tp_texture->SetPerm(perm);\r\n\t\tmp_texture_lookup->PutItem(p_texture->GetChecksum(), p_texture);\r\n\t\t\r\n\t} else {\r\n\t\tDbg_MsgAssert(0,(\"Couldn't load texture %s from buffer\",Script::FindChecksumName(texture_checksum)));\r\n\t}\r\n\r\n\tMem::PopMemProfile();\r\n\treturn p_texture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCTexDict::UnloadTexture(CTexture *p_texture)\r\n{\r\n\tuint32 checksum = p_texture->GetChecksum();\r\n\r\n\t// Because the texture might be still being used, we have to wait for the frame to \r\n\t// finish rendering\r\n\tNx::CEngine::sFinishRendering();\r\n\r\n\tif (plat_unload_texture(p_texture))\r\n\t{\r\n\t\tmp_texture_lookup->FlushItem(checksum);\r\n\t\treturn true;\r\n\t} else {\r\n\t\tDbg_Error(\"Cannot unload texture %x\", checksum);\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCTexDict::AddTexture(CTexture *p_texture)\r\n{\r\n\tDbg_Assert(mp_texture_lookup);\r\n\tDbg_Assert(p_texture);\r\n\r\n\tmp_texture_lookup->PutItem(p_texture->GetChecksum(), p_texture);\r\n\r\n\tplat_add_texture(p_texture);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture* CTexDict::get_source_texture( const char* p_src_texture_name )\r\n{\r\n\tuint32 src_checksum = Crc::GenerateCRCFromString( p_src_texture_name );\r\n\t//src_checksum *= 24;\r\n\r\n\t// look for the texture with that checksum\r\n\tstatic int modifiers[] = { 2, 3, 4, 2 * 3, 3 * 4, 2 * 4, 2 * 3 * 4, -1 };\r\n\tCTexture* pTexture = NULL;\r\n\tfor (int idx = 0; modifiers[idx] > 0; idx++)\r\n\t{\r\n\t\tuint32 calc_checksum = src_checksum * modifiers[idx];\r\n\t\tpTexture = GetTexture( calc_checksum );\r\n\r\n\t\tif (pTexture)\r\n\t\t{\r\n\t\t\tsrc_checksum *= calc_checksum;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// If we haven't found the texture at this stage, it may be because an auto-generated MIP version was used.\r\n\t// In which case, the name will have _auto32m0 appended to it. Try searching for this name instead.\r\n\tif( pTexture == NULL )\r\n\t{\r\n\t\tchar auto32_name[512];\r\n\t\tstrcpy( auto32_name, p_src_texture_name );\r\n\r\n\t\t// Remove the .png, and add the new suffix.\r\n\t\tint length = strlen( auto32_name );\r\n\t\tif( length > 4 )\r\n\t\t{\r\n\t\t\tauto32_name[strlen( auto32_name ) - 4] = 0;\r\n\r\n\t\t\t// Append the extra bit.\r\n\t\t\tstrcat( auto32_name, \"_auto32m0.png\" );\r\n\t\t}\r\n\t\t\r\n\t\tsrc_checksum = Crc::GenerateCRCFromString( auto32_name );\r\n\t\tfor( int idx = 0; modifiers[idx] > 0; idx++ )\r\n\t\t{\r\n\t\t\tuint32 calc_checksum = src_checksum * modifiers[idx];\r\n\t\t\tpTexture = GetTexture( calc_checksum );\r\n\t\t\tif( pTexture )\r\n\t\t\t{\r\n\t\t\t\tsrc_checksum *= calc_checksum;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn pTexture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTexDict::ReplaceTexture(const char* p_src_texture_name, const char* p_dst_texture_name)\r\n{\r\n\tCTexture* pTexture = get_source_texture( p_src_texture_name );\r\n\t\r\n\tif ( pTexture )\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\t\tif ( Script::GetInt( CRCD(0x2a648514,\"cas_artist\"), false ) )\r\n\t\t{\r\n\t\t\tDbg_Message( \"Replacing %s with %s here\", p_src_texture_name, p_dst_texture_name );\r\n\t\t}\r\n#endif\r\n\r\n\t\tCTexture *p_new_texture = LoadTexture(p_dst_texture_name, false, false);\r\n\t\tDbg_MsgAssert(p_new_texture, (\"Can't find replacement texture %s\", p_dst_texture_name));\r\n\r\n\t\tbool result = pTexture->ReplaceTexture( p_new_texture );\r\n\t\tDbg_MsgAssert(result, (\"Can't replace texture %s with %s\", p_src_texture_name, p_dst_texture_name));\r\n\r\n\t\t// We're done with the new texture, get rid of it\r\n\t\tUnloadTexture(p_new_texture);\r\n\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\treturn result;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// GJ:  The texture checksum lookup table is only\r\n\t\t// available for sprite tex dicts, not for CAS\r\n\t\t// parts, so I've commented out the following for now...\r\n//\t\tif ( Script::GetInt( \"cas_artist\", false ) )\r\n//\t\t{\r\n//\t\t\tDbg_Message( \"Couldn't find %s (%08x) in order to replace texture %s\", p_src_texture_name, src_checksum, p_dst_texture_name );\r\n//\t\t}\r\n\t\t\r\n\t\tDbg_Assert( mp_texture_lookup );\r\n\r\n/*\r\n\t\t// For debugging...\r\n\t\t\r\n\t\tif (mp_texture_lookup)\r\n\t\t{\r\n\t\t\tmp_texture_lookup->IterateStart();\r\n\t\t\tCTexture *p_texture;\r\n\t\t\tint count = 0;\r\n\t\t\twhile ((p_texture = mp_texture_lookup->IterateNext()))\r\n\t\t\t{\r\n\t\t\t\tDbg_Message(\"Found Checksum #%d %08x\", count, p_texture->GetChecksum());\r\n\t\t\t\tcount++;\r\n\t\t\t}\r\n\t\t\tDbg_Assert( count );\r\n\t\t}\r\n*/\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTexDict::ReplaceTexture( const char* p_src_texture_name, CTexture* p_dst_texture )\r\n{\r\n\tCTexture* pTexture = get_source_texture( p_src_texture_name );\r\n\t\r\n\tif ( pTexture )\r\n\t{\r\n\t\tbool result = pTexture->ReplaceTexture( p_dst_texture );\r\n\t\tDbg_MsgAssert(result, (\"Can't replace texture %s with CTexture %p\", p_src_texture_name, p_dst_texture));\r\n\r\n\t\treturn result;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// GJ:  The texture checksum lookup table is only\r\n\t\t// available for sprite tex dicts, not for CAS\r\n\t\t// parts, so I've commented out the following for now...\r\n//\t\tif ( Script::GetInt( \"cas_artist\", false ) )\r\n//\t\t{\r\n//\t\t\tDbg_Message( \"Couldn't find %s (%08x) in order to replace texture %s\", p_src_texture_name, src_checksum, p_dst_texture_name );\r\n//\t\t}\r\n\t\t\r\n\t\tDbg_Assert( mp_texture_lookup );\r\n\r\n/*\r\n\t\t// For debugging...\r\n\t\t\r\n\t\tif (mp_texture_lookup)\r\n\t\t{\r\n\t\t\tmp_texture_lookup->IterateStart();\r\n\t\t\tCTexture *p_texture;\r\n\t\t\tint count = 0;\r\n\t\t\twhile ((p_texture = mp_texture_lookup->IterateNext()))\r\n\t\t\t{\r\n\t\t\t\tDbg_Message(\"Found Checksum #%d %08x\", count, p_texture->GetChecksum());\r\n\t\t\t\tcount++;\r\n\t\t\t}\r\n\t\t\tDbg_Assert( count );\r\n\t\t}\r\n*/\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\t\tCTexDict::CopyTexture(uint32 new_texture_checksum, CTexture *p_texture)\r\n{\r\n\tCTexture *p_new_texture = plat_copy_texture(new_texture_checksum, p_texture);\r\n\r\n\tif (p_new_texture)\r\n\t{\r\n\t\tp_new_texture->m_checksum = new_texture_checksum;\r\n\t\tmp_texture_lookup->PutItem(new_texture_checksum, p_new_texture);\r\n\t} else {\r\n\t\tDbg_Error(\"Could not create new CTexture %x\", new_texture_checksum);\r\n\t}\r\n\r\n\treturn p_new_texture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\t\tCTexDict::CombineTextures(uint32 new_texture_checksum, CTexture *p_texture1, CTexture *p_texture2, bool palette_gen)\r\n{\r\n\tCTexture *p_new_texture = CopyTexture(new_texture_checksum, p_texture1);\r\n\r\n\tif (p_new_texture)\r\n\t{\r\n\t\tp_new_texture->CombineTextures(p_texture2, palette_gen);\r\n\t} else {\r\n\t\tDbg_Error(\"Could not create new CTexture for CombineTexture of %x\", new_texture_checksum);\r\n\t}\r\n\r\n\treturn p_new_texture;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\t\tCTexDict::GetTexture(uint32 checksum) const\r\n{\r\n\tif ( !mp_texture_lookup )\r\n\t{\r\n\t\tDbg_Error( \"No texture lookup has been created for this texdict\" );\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\treturn mp_texture_lookup->GetItem(checksum);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\t\tCTexDict::GetTexture(const char *p_texture_name) const\r\n{\r\n\treturn GetTexture(s_convert_filename_to_checksum(p_texture_name));\r\n}\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stub versions of all platform specific functions:\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\t\tCTexDict::plat_load_texture(const char *p_texture_name, bool sprite, bool alloc_vram)\r\n{\r\n\tprintf (\"STUB: PlatLoadTexture\\n\");\r\n\tDbg_Assert(0);\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\t\tCTexDict::plat_load_texture_from_buffer(uint8* p_buffer, int buffer_size, uint32 texture_checksum, bool sprite, bool alloc_vram)\r\n{\r\n\tprintf (\"STUB: PlatLoadTextureFromBuffer\\n\");\r\n\tDbg_MsgAssert(0, (\"This function was only supposed to be called on the PS2\"));\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\t\tCTexDict::plat_reload_texture(const char *p_texture_name)\r\n{\r\n\tprintf (\"STUB: PlatReloadTexture\\n\");\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCTexDict::plat_unload_texture(CTexture *p_texture)\r\n{\r\n\tprintf (\"STUB: PlatUnloadTexture\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCTexDict::plat_add_texture(CTexture *p_texture)\r\n{\r\n\tprintf (\"STUB: PlatAddTexture\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCTexDict::plat_remove_texture(CTexture *p_texture)\r\n{\r\n\tprintf (\"STUB: PlatRemoveTexture\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *\t\t\tCTexDict::plat_copy_texture(uint32 new_texture_checksum, CTexture *p_texture)\r\n{\r\n\tprintf (\"STUB: PlatCopyTexture\\n\");\r\n\treturn NULL;\r\n}\r\n\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxTexture.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// NxTexture.H - Neversoft Engine, Rendering portion, Platform independent interface\r\n\r\n#ifndef\t__GFX_NX_TEXTURE_H__\r\n#define\t__GFX_NX_TEXTURE_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/hashtable.h>\r\n\r\n#include <gfx/image/imagebasic.h>\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\nclass CTexDict;\r\nclass CTexDictManager;\r\n\r\n//////////////////////////////////////////////////////////////////////////////////\r\n// Nx::CTexture replaces RwTexture\r\nclass\tCTexture\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCTexture();\r\n\t\t\t\t\t\t\tCTexture(const CTexture & src_texture);\t\t// Copy constructor\r\n\tvirtual\t\t\t\t\t~CTexture();\r\n\r\n\tbool\t\t\t\t\tLoadTexture(const char *p_texture_name, bool sprite, bool alloc_vram = true);\r\n\tbool\t\t\t\t\tLoadTextureFromBuffer(uint8* p_buffer, int buffer_size, uint32 texture_checksum, bool sprite, bool alloc_vram = true);\r\n\tbool\t\t\t\t\tReplaceTexture(CTexture *p_texture);\r\n\r\n\t// Temp 32-bit texture image generation.  All the texture manipulation routines need to use\r\n\t// 32-bit versions of the texture.  But to palettize every operation can be slow, so keeping\r\n\t// the temp buffer around speeds things up greatly.\r\n\tbool\t\t\t\t\tGenerate32BitImage(bool renderble = false, bool store_original = false);\r\n\tbool\t\t\t\t\tPut32BitImageIntoTexture(bool new_palette = false);\r\n\r\n\t// Combines current texture with new texture (overwriting original one)\r\n\tbool\t\t\t\t\tCombineTextures(CTexture *p_texture, bool palette_gen = true);\r\n\r\n\t// Move texture (cropping the part that moves off and filling in the new parts with either the old edge or a\r\n\t// supplied fill color)\r\n\tbool\t\t\t\t\tOffset(int x_pixels, int y_pixels, bool use_fill_color = false,\r\n\t\t\t\t\t\t\t\t   Image::RGBA fill_color = Image::RGBA(128, 128, 128, 128));\r\n\r\n\t// This function will scale a rectangular section of a texture.  Each side of the texture\r\n\t// will be stretched or shrunk from the start_point to the end_point along the split axis.\r\n\tbool\t\t\t\t\tAdjustRegion(uint16 x_pos, uint16 y_pos, uint16 width, uint16 height,\r\n\t\t\t\t\t\t\t\t\t\t int split_axis, uint16 start_point, uint16 end_point);\r\n\r\n\t// Pull texture from point along the axis by num_pixels (+ or - determines the direction)\r\n\t// and crop anything going outside the texture border.\r\n\tbool\t\t\t\t\tPullToEdge(uint16 point, int axis, int num_pixels);\r\n\t// Similar to PullToEdge(), except it pushes the texture from the edge to the point.  Instead\r\n\t// of cropping, it either stretches the edge line or fills it in with a fill color\r\n\tbool\t\t\t\t\tPushToPoint(uint16 point, int axis, int num_pixels, bool use_fill_color = false,\r\n\t\t\t\t\t\t\t\t\t\tImage::RGBA fill_color = Image::RGBA(128, 128, 128, 128));\r\n\r\n\tbool\t\t\t\t\tAdjustBrightness(float brightness_scale, bool force_adjust_current = false);\r\n\tbool\t\t\t\t\tAdjustHSV(float h, float s, float v, bool force_adjust_current = false);\r\n\r\n\t// These VRAM calls won't do anything on platforms that don't have separate\r\n\t// texture memory\r\n\tbool\t\t\t\t\tAddToVram();\r\n\tbool\t\t\t\t\tRemoveFromVram();\r\n\r\n\tuint32\t\t\t\t\tGetChecksum() const;\r\n\tuint16\t\t\t\t\tGetWidth() const;\r\n\tuint16\t\t\t\t\tGetHeight() const;\r\n\tuint8\t\t\t\t\tGetBitDepth() const;\r\n\tuint8\t\t\t\t\tGetPaletteBitDepth() const;\r\n\tuint8\t\t\t\t\tGetNumMipmaps() const;\r\n\tbool\t\t\t\t\tIsTransparent() const;\r\n\r\n\tvoid\t\t\t\t\tSetPerm( bool perm) {m_perm = perm;}\r\n\tbool\t\t\t\t\tIsPerm() {return m_perm;}\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\tchar *\t\t\t\t\tGetName() {return mp_name;}\r\n#else\r\n\tchar *\t\t\t\t\tGetName() {return \"WARNING NO NAME\";}\r\n#endif\t\r\n\t\r\n\r\nprotected:\r\n\r\n\tuint32\t\t\t\t\tm_checksum;\r\n\r\n\t// So it can access set_checksum()\r\n\tfriend CTexDict;\r\n\r\nprivate:\r\n\tvirtual bool\t\t\tplat_load_texture(const char *p_texture_name, bool sprite, bool alloc_vram);\r\n\tvirtual bool\t\t\tplat_load_texture_from_buffer(uint8* p_buffer, int buffer_size, bool sprite, bool alloc_vram);\r\n\tvirtual bool\t\t\tplat_replace_texture(CTexture *p_texture);\r\n\r\n\tvirtual bool\t\t\tplat_generate_32bit_image(bool renderble = false, bool store_original = false);\r\n\tvirtual bool\t\t\tplat_put_32bit_image_into_texture(bool new_palette = false);\r\n\r\n\tvirtual bool\t\t\tplat_offset(int x_pixels, int y_pixels, bool use_fill_color, Image::RGBA fill_color);\r\n\r\n\tvirtual bool\t\t\tplat_adjust_region(uint16 x_pos, uint16 y_pos, uint16 width, uint16 height,\r\n\t\t\t\t\t\t\t\t\t\t\t   int split_axis, uint16 start_point, uint16 end_point);\r\n\r\n\tvirtual bool\t\t\tplat_pull_to_edge(uint16 point, int axis, int num_pixels);\r\n\tvirtual bool\t\t\tplat_push_to_point(uint16 point, int axis, int num_pixels, bool use_fill_color,\r\n\t\t\t\t\t\t\t\t\t\t\t   Image::RGBA fill_color);\r\n\r\n\tvirtual bool\t\t\tplat_adjust_brightness(float brightness_scale, bool force_adjust_current = false);\r\n\tvirtual bool\t\t\tplat_adjust_hsv(float h, float s, float v, bool force_adjust_current = false);\r\n\r\n\tvirtual bool\t\t\tplat_add_to_vram();\r\n\tvirtual bool\t\t\tplat_remove_from_vram();\r\n\r\n\tvirtual uint16\t\t\tplat_get_width() const;\r\n\tvirtual uint16\t\t\tplat_get_height() const;\r\n\tvirtual uint8\t\t\tplat_get_bitdepth() const;\r\n\tvirtual uint8\t\t\tplat_get_palette_bitdepth() const;\r\n\tvirtual uint8\t\t\tplat_get_num_mipmaps() const;\r\n\tvirtual bool\t\t\tplat_is_transparent() const;\r\n\r\n\tvirtual bool\t\t\tplat_combine_textures(CTexture *p_texture, bool palette_gen);\r\n\t\r\n\tbool\t\t\t\t\tm_perm;\t\t// set to true if this texture should survive a level change \r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tchar\t*\t\t\t\tmp_name;\r\n\t#endif\r\n\r\n};\r\n\r\n//////////////////////////////////////////////////////////////////////////////////\r\n// Nx::CMaterial\r\nclass\tCMaterial\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCMaterial();\r\n\tvirtual\t\t\t\t\t~CMaterial()\t{}\r\n\r\n\tImage::RGBA\t\t\t\tGetRGBA() const;\r\n\tvoid\t\t\t\t\tSetRGBA(Image::RGBA rgba);\r\n\tCTexture *\t\t\t\tGetTexture() const;\r\n\tvoid\t\t\t\t\tSetTexture(CTexture *tex);\r\n\r\nprotected:\r\n\tuint32\t\t\t\t\tm_checksum;\r\n\tCTexture *\t\t\t\tmp_texture;\r\n\r\nprivate:\r\n\tvirtual Image::RGBA\t\tplat_get_rgba() const;\r\n\tvirtual void\t\t\tplat_set_rgba(Image::RGBA rgba);\r\n\tvirtual void\t\t\tplat_set_texture(CTexture *tex);\r\n\r\n};\r\n\r\n//////////////////////////////////////////////////////////////////////////////////\r\n// Nx::CTexDict\r\nclass\tCTexDict\r\n{\r\npublic:\r\n\t// The constructor and destructor start the loading and unloading\r\n\t\t\t\t\t\t\tCTexDict(uint32 checksum, bool create_lookup_table = true);\t// loads nothing\r\n\t\t\t\t\t\t\tCTexDict(const char *p_tex_dict_name, bool create_lookup_table = false);\r\n\tvirtual\t\t\t\t\t~CTexDict();\r\n\r\n\tvoid\t\t\t\t\tIncRefCount();\r\n\tint16\t\t\t\t\tDecRefCount();\r\n\r\n\t// The load and unload functions probably will change, since\r\n\t// we will only load and unload whole texture dictionaries.\r\n\t// For now, they will only be used for the 2D textures.\r\n\tCTexture *\t\t\t\tLoadTexture(const char *p_texture_name, bool sprite, bool alloc_vram = true, bool perm = true);\r\n\tCTexture *\t\t\t\tLoadTextureFromBuffer(uint8* p_buffer, int buffer_size, uint32 texture_checksum, bool sprite, bool alloc_vram = true, bool perm = true);\r\n\tCTexture *\t\t\t\tReloadTexture(const char *p_texture_name);\r\n\tbool\t\t\t\t\tUnloadTexture(CTexture *p_texture);\r\n\tvoid\t\t\t\t\tAddTexture(CTexture *p_texture);\r\n\tbool\t\t\t\t\tRemoveTexture(CTexture *p_texture);\r\n\tbool\t\t\t\t\tReplaceTexture( const char* p_src_texture_name, const char* p_dst_texture_name );\r\n\tbool\t\t\t\t\tReplaceTexture( const char* p_src_texture_name, CTexture* p_dst_texture );\r\n\r\n\tCTexture *\t\t\t\tCopyTexture(uint32 new_texture_checksum, CTexture *p_texture);\r\n\t// Combine two textures to make a new texture\r\n\tCTexture *\t\t\t\tCombineTextures(uint32 new_texture_checksum, CTexture *p_texture1, CTexture *p_texture2, bool palette_gen = true);\r\n\r\n\tuint32\t\t\t\t\tGetChecksum() const;\r\n\tCTexture *  \t\t\tGetTexture(uint32 checksum) const;\r\n\tCTexture *  \t\t\tGetTexture(const char *p_texture_name) const;\r\n\t\r\n\tuint32\t\t\t\t\tGetFileSize() {return m_file_size;}\r\n\r\n\tLst::HashTable<CTexture> *GetTexLookup( void ) { return mp_texture_lookup; }\r\n\r\n\tvoid\t\t\t\t\tFlushTextures(bool flush_all);\t// flush textures, optionally flushing perm textures\r\n\r\nprotected:\r\n\tvoid\t\t\t\t\tset_checksum(uint32 checksum);\r\n\tCTexture*\t\t\t\tget_source_texture( const char* p_src_texture_name );\r\n\r\n\tuint32\t\t\t\t\tm_checksum;\r\n\tint16\t\t\t\t\tm_ref_count;\r\n\r\n\tLst::HashTable<CTexture> *\tmp_texture_lookup;\r\n\r\n\t// So it can access set_checksum()\r\n\tfriend CTexDictManager;\r\n\r\nprivate:\t\r\n\t// Platform-specific calls\r\n\tvirtual CTexture *\t\t\tplat_load_texture(const char *p_texture_name, bool sprite, bool alloc_vram);\r\n\tvirtual CTexture *\t\t\tplat_load_texture_from_buffer(uint8* p_buffer, int buffer_size, uint32 texture_checksum, bool sprite, bool alloc_vram);\r\n\tvirtual CTexture *\t\t\tplat_reload_texture(const char *p_texture_name);\r\n\tvirtual bool\t\t\t\tplat_unload_texture(CTexture *p_texture);\r\n\tvirtual void\t\t\t\tplat_add_texture(CTexture *p_texture);\r\n\tvirtual bool\t\t\t\tplat_remove_texture(CTexture *p_texture);\r\n\tvirtual CTexture *\t\t\tplat_copy_texture(uint32 new_texture_checksum, CTexture *p_texture);\r\n\r\nprotected:\r\n\tuint32\t\t\t\t\t\tm_file_size;\t\t// DEBUGGING USE ONLY, NOT GUARENTEED\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t\t\t \r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\tCTexDict::IncRefCount()\r\n{\r\n\tm_ref_count++;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline int16\t\tCTexDict::DecRefCount()\r\n{\r\n\treturn --m_ref_count;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint32\t\tCTexDict::GetChecksum() const\r\n{\r\n\treturn m_checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\t\t\tCTexDict::set_checksum(uint32 checksum)\r\n{\r\n\tm_checksum = checksum;\r\n}\r\n\r\n}\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxTextured3dPoly.cpp",
    "content": "#include <core/defines.h>\r\n#include <core/math.h>\r\n\r\n#include <gfx/nxtextured3dpoly.h>\r\n#include <core/crc.h>\r\n#include <core/hashtable.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\nstatic Lst::HashTable< Nx::CTextured3dPoly > s_poly_table(1);\r\n\r\nvoid CTextured3dPoly::sRenderAll()\r\n{\r\n\tCTextured3dPoly *p_poly;\r\n\ts_poly_table.IterateStart();\r\n\twhile(( p_poly = s_poly_table.IterateNext()))\r\n\t{\r\n\t\tp_poly->Render();\r\n\t}\r\n}\r\n\r\nCTextured3dPoly::CTextured3dPoly()\r\n{\r\n\ts_poly_table.PutItem((uint32)this,this);\r\n}\r\n\r\nCTextured3dPoly::~CTextured3dPoly()\r\n{\r\n\ts_poly_table.FlushItem((uint32)this);\r\n}\r\n\r\nvoid CTextured3dPoly::SetTexture(uint32 texture_checksum)\r\n{\r\n\tplat_set_texture(texture_checksum);\r\n}\r\n\r\nvoid CTextured3dPoly::SetTexture(const char *p_textureName)\r\n{\r\n\tSetTexture(Crc::GenerateCRCFromString(p_textureName));\r\n}\r\n\t\r\nvoid CTextured3dPoly::SetPos(const Mth::Vector &pos, float width, float height, const Mth::Vector &normal, float angle)\r\n{\r\n\tMth::Vector offx(1.0f,0.0f,0.0f);\r\n\tMth::Vector offz=Mth::CrossProduct(normal,offx);\r\n\t\r\n\toffx*=width/2.0f;\r\n\toffz*=height/2.0f;\r\n\t\r\n\tmp_pos[0]=pos-offx-offz;\r\n\tmp_pos[1]=pos+offx-offz;\r\n\tmp_pos[2]=pos+offx+offz;\r\n\tmp_pos[3]=pos-offx+offz;\r\n}\r\n\r\nvoid CTextured3dPoly::Render()\r\n{\r\n\tplat_render();\r\n}\t\r\n\r\n} // namespace Nx\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxTextured3dPoly.h",
    "content": "//////////////////////////////////////////////////////////////////////////////////////////////\r\n// NxTextured3dPoly.h - Neversoft Engine, Rendering portion, Platform independent interface\r\n\r\n#ifndef\t__GFX_NX_TEXTURED_3D_POLY_H__\r\n#define\t__GFX_NX_TEXTURED_3D_POLY_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __CORE_MATH_VECTOR_H\r\n#include <core/math/vector.h>\r\n#endif\r\n\r\nnamespace Nx\r\n{\r\n\r\n// Class for displaying a single textured 3d poly. Currently used by the pedestrian shadows, which\r\n// are just simple circular textures oriented to the ground.\r\nclass\tCTextured3dPoly\r\n{\r\nprotected:\r\n\tMth::Vector mp_pos[4];\r\n\t\r\npublic:\r\n\t\t\t\t\t\t\tCTextured3dPoly();\r\n\tvirtual\t\t\t\t\t~CTextured3dPoly();\r\n\r\n\tvoid\t\t\t\t\tSetTexture(const char *p_textureName);\r\n\tvoid \t\t\t\t\tSetTexture(uint32 texture_checksum);\r\n\t\r\n\tvoid\t\t\t\t\tSetPos(const Mth::Vector &pos, float width, float height, const Mth::Vector &normal, float angle=0.0f);\r\n\r\n\tvoid\t\t\t\t\tRender();\r\n\r\n\tstatic void\t\t\t\tsRenderAll();\r\n\t\t\r\nprivate:\r\n\tvirtual void\t\t\tplat_render() {}\r\n\tvirtual void\t\t\tplat_set_texture(uint32 texture_checksum) {}\r\n\t\r\n};\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxViewMan.cpp",
    "content": "\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tNx Viewport Manager\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgfx/nxviewman.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t04/30/02\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tViewport Manager\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// start autoduck documentation\r\n// @DOC nxviewman\r\n// @module nxviewman | None\r\n// @subindex Scripting Database\r\n// @index script | nxviewman\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <string.h>\r\n#include <core/defines.h>\r\n#include <gfx/NxViewMan.h>\r\n#include <gel/Scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n// This defines the width to height ratio of the camera's *view* window, and\r\n// as such does not need to be changed for different screen modes or systems.\r\nconst float vBASE_ASPECT_RATIO = 1.428566f;\r\n\r\nconst float\tCViewportManager::s_viewport_rects[vNUM_VIEWPORTS][4] =\r\n{\r\n//    x      y      w     h\r\n\t{ 0.0f,  0.0f,  1.0f, 1.0f},\t// vMAIN\r\n\t{ 0.0f,  0.0f,  1.0f, 1.0f},\t// vSECONDPLAYER (2nd player fullscreen)\r\n\t{ 0.0f,  0.0f,  0.5f, 1.0f},\t// vSPLIT_V_LEFT\r\n\t{ 0.5f,  0.0f,  0.5f, 1.0f},\t// vSPLIT_V_RIGHT\r\n\t{ 0.0f,  0.0f,  1.0f, 0.5f},\t// vSPLIT_H_TOP\r\n\t{ 0.0f,  0.5f,  1.0f, 0.5f},\t// vSPLIT_H_BOTTOM\r\n\t{ 0.0f,  0.0f,  0.5f, 0.5f},\t// vSPLIT_QUARTER_UL\r\n\t{ 0.5f,  0.0f,  0.5f, 0.5f},\t// vSPLIT_QUARTER_UR\r\n\t{ 0.0f,  0.5f,  0.5f, 0.5f},\t// vSPLIT_QUARTER_LL\r\n\t{ 0.5f,  0.5f,  0.5f, 0.5f}\t\t// vSPLIT_QUARTER_LR\r\n};\r\n\r\nconst int \tCViewportManager::s_num_active_viewports[vNUM_SCREEN_MODES]\r\n\t\t\t\t\t\t\t = { 1, 2, 2, 4, 1, 1 };\r\nconst int\tCViewportManager::s_screen_mode_viewport_indexes[vNUM_SCREEN_MODES][vMAX_NUM_ACTIVE_VIEWPORTS]\r\n\t\t\t\t\t= { { vMAIN,\t\t\t -1,\t\t\t\t-1,\t\t\t\t   -1 },\t\t\t\t// vONE_CAM\r\n\t\t\t\t\t\t{ vSPLIT_V_LEFT,\t vSPLIT_V_RIGHT,\t-1,\t\t\t\t   -1 },\t\t\t\t// vSPLIT_V\r\n\t\t\t\t\t\t{ vSPLIT_H_TOP,\t\t vSPLIT_H_BOTTOM,\t-1,\t\t\t\t   -1 },\t\t\t\t// vSPLIT_H\r\n\t\t\t\t\t\t{ vSPLIT_QUARTER_UL, vSPLIT_QUARTER_UR, vSPLIT_QUARTER_LL, vSPLIT_QUARTER_LR },\t// vSPLIT_QUARTERS\r\n\t\t\t\t\t\t{ vMAIN,\t\t\t -1,\t\t\t\t-1,\t\t\t\t   -1 },\t\t\t\t// vHORSE1\r\n\t\t\t\t\t\t{ -1,\t\t\t\t vSECONDPLAYER,\t\t-1,\t\t\t\t   -1 },\t\t\t\t// vHORSE2\r\n\t\t\t\t\t  };\r\n\r\n\r\nCViewport*\tCViewportManager::sp_viewports[vNUM_VIEWPORTS];\r\nconst int*\tCViewportManager::sp_active_viewport_indexes = s_screen_mode_viewport_indexes[0];\r\n\r\nScreenMode\tCViewportManager::s_screen_mode;\r\nint\t\t\tCViewportManager::s_num_active_viewports_cached=0;\r\n\r\nfloat\t\tCViewportManager::s_default_angle;\r\nfloat\t\tCViewportManager::s_screen_angle;\r\nfloat\t\tCViewportManager::s_screen_angle_factor = 1.0f;\r\nfloat\t\tCViewportManager::s_screen_aspect;\r\n\r\nfloat\t\tCViewportManager::s_2D_in_3D_space_noscale_distance = 300.0f;\r\nfloat\t\tCViewportManager::s_2D_in_3D_space_max_scale = 3.0f;\r\nfloat\t\tCViewportManager::s_2D_in_3D_space_min_scale = 0.0f;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \t\tCViewportManager::sInit( void )\r\n{\r\n\t// Create viewports\r\n\tfor ( uint32 i = 0; i < vNUM_VIEWPORTS; i++ )\r\n\t{\r\n\t\tMth::Rect theRect( s_viewport_rects[i][0], s_viewport_rects[i][1], s_viewport_rects[i][2], s_viewport_rects[i][3] );\r\n\r\n\t\tsp_viewports[i] = s_create_viewport(&theRect);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCViewportManager::sCleanup( void )\r\n{\r\n\tfor ( uint32 i = 0; i < vNUM_VIEWPORTS; i++ )\r\n\t{\r\n\t\tif ( sp_viewports[i] )\r\n\t\t{\r\n\t\t\tdelete sp_viewports[i];\r\n\t\t\tsp_viewports[i] = NULL;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCViewport*\tCViewportManager::sGetActiveViewport(int view)\r\n{\r\n\tDbg_MsgAssert(view < s_num_active_viewports[s_screen_mode], (\"Active viewport number is invalid %d\", view));\r\n\r\n\tint found_views = 0;\r\n\r\n\t// Go through array, and don't count invalid viewports\r\n\tfor ( uint32 i = 0; i < vNUM_VIEWPORTS; i++ )\r\n\t{\r\n\t\tif (sp_active_viewport_indexes[i] >= 0)\r\n\t\t{\r\n\t\t\tif (found_views == view)\r\n\t\t\t{\r\n\t\t\t\treturn sp_viewports[sp_active_viewport_indexes[i]];\r\n\t\t\t}\r\n\t\t\tfound_views++;\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert(0, (\"Cant find active viewport # %d\", view));\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\tCViewportManager::sGetActiveViewportNumber(CViewport *p_viewport)\r\n{\r\n\tint found_views = 0;\r\n\r\n\t// Go through array, and don't count invalid viewports\r\n\tfor ( uint32 i = 0; i < vNUM_VIEWPORTS; i++ )\r\n\t{\r\n\t\tif (sp_active_viewport_indexes[i] >= 0)\r\n\t\t{\r\n\t\t\tif (sp_viewports[sp_active_viewport_indexes[i]] == p_viewport)\r\n\t\t\t{\r\n\t\t\t\treturn found_views;\r\n\t\t\t}\r\n\t\t\tfound_views++;\r\n\t\t}\r\n\t}\r\n\r\n\t// Not found\r\n\treturn -1;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGfx::Camera* CViewportManager::sGetCamera(int index)\r\n{\r\n\t//Dbg_MsgAssert(sp_active_viewport_indexes[index] >= 0, (\"Viewport index invalid %d from camera %d, screen mode %d \", sp_active_viewport_indexes[index], index, s_screen_mode));\r\n\r\n\tif (sp_active_viewport_indexes[index] == -1)\r\n\t{\r\n\t\treturn NULL;\r\n\t\t//printf (\"CAMERA WARNING: - Getting invalid camera %d when in screen mode %d (Returning default camera 0)\\n\",index,s_screen_mode);  \r\n\t\t//index = 0;\r\n\t}\r\n\r\n\treturn sp_viewports[sp_active_viewport_indexes[index]]->GetCamera();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCViewportManager::sSetCamera(int index, Gfx::Camera* pCamera)\r\n{\r\n\tDbg_Assert( index >= 0 && index < vMAX_NUM_ACTIVE_VIEWPORTS );\r\n\tif (sp_active_viewport_indexes[index] == -1)\r\n\t{\r\n\t\t//printf (\"CAMERA WARNING: - Setting invalid camera %d when in screen mode %d (Ignoring)\\n\",index,s_screen_mode);  \r\n\t\treturn;\r\n\t}\r\n\tsp_viewports[sp_active_viewport_indexes[index]]->SetCamera(pCamera);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCViewportManager::sSetCameraAllScreenModes(int index, Gfx::Camera* pCamera)\r\n{\r\n\tfor (int mode = 0; mode < vNUM_SCREEN_MODES; mode++)\r\n\t{\r\n\t\tif (s_screen_mode_viewport_indexes[mode][index] >= 0)\r\n\t\t{\r\n\t\t\t//Dbg_Message(\"******************* SetCameraAllScreenMode: Setting viewport mode %d camera #%d to Camera (%x)\", mode, index, pCamera);\r\n\t\t\tsp_viewports[s_screen_mode_viewport_indexes[mode][index]]->SetCamera(pCamera);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScreenMode\tCViewportManager::sGetScreenMode()\r\n{\r\n\treturn s_screen_mode;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGfx::Camera* CViewportManager::sGetActiveCamera(int cam)\r\n{\r\n\tCViewport *p_viewport = sGetActiveViewport(cam);\r\n\tDbg_MsgAssert(p_viewport, (\"sGetActiveCamera(): Active viewport index %d invalid for screen mode %d \", cam, s_screen_mode));\r\n\r\n\treturn p_viewport->GetCamera();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGfx::Camera* CViewportManager::sGetClosestCamera(const Mth::Vector &pos, float *distParam)\r\n{\r\n\tint i;\r\n\tint numCams = sGetNumActiveCameras( );\r\n\tGfx::Camera *p_camera;\r\n\tGfx::Camera *p_closestCamera = NULL;\r\n\tfloat closestDist = -1.0f;\r\n\tfloat tempDist;\r\n\r\n\tfor ( i = 0; i < numCams; i++ )\r\n\t{\r\n\t\tp_camera = sGetActiveCamera( i );\r\n\t\tif ( p_camera )\r\n\t\t{\r\n\t\t\ttempDist = Mth::DistanceSqr( pos, p_camera->GetPos() );\r\n\t\t\tif ( ( closestDist < 0 ) || ( tempDist < closestDist ) )\r\n\t\t\t{\r\n\t\t\t\tclosestDist = tempDist;\r\n\t\t\t\tp_closestCamera = p_camera;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t//Dbg_MsgAssert( p_closestCamera,( \"No cameras or what?\" ));\r\n\tif ( p_closestCamera == NULL )\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tif ( distParam )\r\n\t{\r\n\t\t*distParam = sqrtf(closestDist);\r\n\t}\r\n\treturn p_closestCamera;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\tCViewportManager::sGetNumActiveCameras(void)\r\n{\r\n\r\n\treturn s_num_active_viewports[s_screen_mode];\t\t// Same number of cams as there are viewports\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCViewportManager::sMarkCameraForDeletion(Gfx::Camera *pCamera)\r\n{\r\n\t// Check all viewports in case the screen mode is changed after this\r\n\tfor ( uint32 i = 0; i < vNUM_VIEWPORTS; i++ )\r\n\t{\r\n\t\tif ( sp_viewports[i] )\r\n\t\t{\r\n\t\t\tif (sp_viewports[i]->MarkCameraForDeletion(pCamera))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCViewportManager::sDeleteMarkedCameras()\r\n{\r\n\t// Check all viewports in case the screen mode was changed\r\n\tfor ( uint32 i = 0; i < vNUM_VIEWPORTS; i++ )\r\n\t{\r\n\t\tif ( sp_viewports[i] )\r\n\t\t{\r\n\t\t\tsp_viewports[i]->DeleteMarkedCamera();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid    \tCViewportManager::sSetScreenMode( ScreenMode mode )\r\n{\r\n\t// Update active viewport indexes\r\n\tsp_active_viewport_indexes = s_screen_mode_viewport_indexes[mode];\r\n\r\n\ts_screen_mode = mode;\r\n\t\r\n\ts_num_active_viewports_cached = s_num_active_viewports[s_screen_mode];\r\n\t\r\n\t \r\n\t// Now update cameras\r\n\tfor ( int i = 0; i < s_num_active_viewports[mode]; i++ )\r\n\t{\r\n\t\tCViewport *p_viewport = sGetActiveViewport(i);\r\n\t\tDbg_MsgAssert(p_viewport, (\"SetScreenMode: Couldn't find active viewport # %d for mode %d\", i, mode));\r\n\r\n\t\t// no camera has been bound\r\n\t\tGfx::Camera *p_camera = p_viewport->GetCamera();\r\n\t\tif ( !p_camera )\r\n\t\t{\r\n\t\t\t//return;\r\n\t\t\tcontinue;\t   \t\t\t// just continue, even if there is no camera set up yet.....\r\n\t\t}\r\n\r\n\t\t//Dbg_Message(\"******************* SetScreenMode: Setting Camera %d (%x) of mode %d\", i, p_camera, mode);\r\n\r\n\t\t// set up proper aspect ratio for camera\r\n\t\tswitch (mode)\r\n\t\t{\r\n\t\t\tcase vSPLIT_V:\r\n\t\t\t\t// camera \"window\" at same height, half width as full screen camera\r\n\t\t\t\t//p_camera->SetFocalLength ( Script::GetFloat(\"Skater_Cam_Focal_Length\"), vBASE_ASPECT_RATIO / 2.0f);\r\n\t\t\t\tp_camera->SetHFOV(Script::GetFloat(\"Skater_Cam_Horiz_FOV\") / 2.0f);\r\n\t\t\t\tbreak;\r\n\t\t\tcase vSPLIT_H:\r\n\t\t\t\t// camera \"window\" at same width, half height as full screen camera\r\n\t\t\t\t//p_camera->SetFocalLength ( Script::GetFloat(\"Skater_Cam_Focal_Length\") * 2.0f, vBASE_ASPECT_RATIO * 2.0f);\r\n\t\t\t\tp_camera->SetHFOV(Script::GetFloat(\"Skater_Cam_Horiz_FOV\"));\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\t// camera \"window\" at same width, height as full screen camera\r\n\t\t\t\t//p_camera->SetFocalLength ( Script::GetFloat(\"Skater_Cam_Focal_Length\"), vBASE_ASPECT_RATIO);\r\n\t\t\t\tp_camera->SetHFOV(Script::GetFloat(\"Skater_Cam_Horiz_FOV\"));\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCViewport *\tCViewportManager::s_create_viewport(const Mth::Rect* rect, Gfx::Camera* cam)\r\n{\r\n\treturn s_plat_create_viewport(rect, cam);\r\n}\r\n\r\n\r\n// some fundamental things about the TV\r\n//\r\n// s_screen_aspect is the aspect ratio of the TV\r\n// this is the physical aspect ratio, and not the pixel ratio\r\n// thus it will be either 4:3 (4.0f/3.0f) or 16:9 (16.0f/9.0f) \r\n//\r\n// s_screen_angle is the default view angle for a full screen viewport\r\n// currently (2/8/02) it is set at 72 degrees when screen_aspect is 4:3\r\n// when we have a wider aspect ratio, we want a wider screen angle\r\n// however, we don't want to go too wide, or we will render too much\r\n// 80 degrees is okay, providing us with reduced vertical coverage, but increased\r\n// horizontal coverage (so skater seems bigger on screen, and you can see more of the level)\r\n\r\n\r\nvoid\t\t\t\tCViewportManager::sSetScreenAspect(float aspect)\r\n{\r\n\tDbg_MsgAssert(aspect > 0.1f && aspect <5.0f,(\"Unlikely value (%f) for screen aspect\",aspect));\r\n\ts_screen_aspect = aspect;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\t\t\tCViewportManager::sGetScreenAspect()\r\n{\r\n\treturn s_screen_aspect;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nvoid\t\t\t\tCViewportManager::sSetDefaultAngle(float angle)\r\n{\r\n\tDbg_MsgAssert(angle > 0.01f && angle < 180.0f,(\"Unlikely value (%f) for screen default angle\",angle));\r\n\ts_default_angle = angle;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\t\t\tCViewportManager::sGetDefaultAngle()\r\n{\r\n\treturn s_default_angle;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCViewportManager::sSetScreenAngle(float angle)\r\n{\r\n\tif (angle == 0.0f)\r\n\t{\r\n\t\tangle = s_default_angle;\r\n\t}\r\n\r\n\tDbg_MsgAssert(angle > 0.01f && angle < 180.0f,(\"Unlikely value (%f) for screen angle\",angle));\r\n\ts_screen_angle = angle;\r\n\r\n\ts_screen_angle_factor = tanf(Mth::DegToRad(angle / 2.0f)) / tanf(Mth::DegToRad(s_default_angle / 2.0f));\r\n\r\n\t//Dbg_Message(\"Screen angle %f; Screen angle factor %f\", s_screen_angle, s_screen_angle_factor);\r\n\r\n\t// Update cameras\r\n\t// Garrett: This isn't the right way to do it since it won't touch all the possible cameras.\r\n\t// It would be better to go through a list of all the cameras.\r\n\tfor (int view_idx = 0; view_idx < sGetNumActiveViewports(); view_idx++)\r\n\t{\r\n\t\tCViewport *p_cur_viewport = CViewportManager::sGetActiveViewport(view_idx);\r\n\t\tif (p_cur_viewport)\r\n\t\t{\r\n\t\t\tGfx::Camera *p_cur_camera = p_cur_viewport->GetCamera();\r\n\r\n\t\t\tif (p_cur_camera)\r\n\t\t\t{\r\n\t\t\t\tp_cur_camera->UpdateAdjustedHFOV();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\t\t\tCViewportManager::sGetScreenAngle()\r\n{\r\n\treturn s_screen_angle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\t\t\tCViewportManager::sGetScreenAngleFactor()\r\n{\r\n\treturn s_screen_angle_factor;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCViewportManager::sSet2DIn3DSpaceNoscaleDistance(float distance)\r\n{\r\n\ts_2D_in_3D_space_noscale_distance = distance;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCViewportManager::sSet2DIn3DSpaceMaxScale(float scale)\r\n{\r\n\ts_2D_in_3D_space_max_scale = scale;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCViewportManager::sSet2DIn3DSpaceMinScale(float scale)\r\n{\r\n\ts_2D_in_3D_space_min_scale = scale;\r\n}\r\n\r\n// @script | SetScreenMode | Sets the way the screen will be split up into separate\r\n// viewports in the game. If there is more than one viewport, and multiple skaters\r\n// are active, then each skater will get his own viewport\r\n// @uparm One_Camera | the mode to use - one of the following: <nl>\r\n// One_Camera <nl>\r\n// Split_Vertical <nl>\r\n// Split_Horizontal <nl>\r\n// Split_Quarters\r\nbool ScriptSetScreenMode(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\r\n\tuint32 mode;\r\n\tpParams->GetChecksum(NONAME, &mode, true);\r\n\r\n\tswitch (mode)\r\n\t{\r\n\t\tcase 0x6f70ea65: // \"one_camera\"\r\n\t\t\tCViewportManager::sSetScreenMode(vONE_CAM);\r\n\t\t\tbreak;\r\n\t\tcase 0x9b62e5a6: // \"split_vertical\"\r\n\t\t\tCViewportManager::sSetScreenMode(vSPLIT_V);\r\n\t\t\tbreak;\r\n\t\tcase 0xb07b580e: // \"split_horizontal\"\r\n\t\t\tCViewportManager::sSetScreenMode(vSPLIT_H);\r\n\t\t\tbreak;\r\n\t\tcase 0xb6624a73: // \"split_quarters\"\r\n\t\t\tCViewportManager::sSetScreenMode(vSPLIT_QUARTERS);\r\n\t\t\tbreak;\r\n\t\tcase 0x6f2d1231: // \"horse1\"\r\n\t\t\tCViewportManager::sSetScreenMode(vHORSE1);\r\n\t\t\tbreak;\r\n\t\tcase 0xf624438b: // \"horse2\"\r\n\t\t\tCViewportManager::sSetScreenMode(vHORSE2);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,( \"invalid screen mode\"));\r\n\t\t\tbreak;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool ScriptGetScreenMode(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\tScript::CStruct* p_return_params;\r\n\r\n\tp_return_params = pScript->GetParams();\r\n\tswitch( CViewportManager::sGetScreenMode())\r\n\t{\r\n\t\tcase vSPLIT_V:\r\n\t\t\tp_return_params->AddChecksum( \"screen_mode\", Script::GenerateCRC( \"split_vertical\" ));\r\n\t\t\tbreak;\r\n\t\tcase vSPLIT_H:\r\n\t\t\tp_return_params->AddChecksum( \"screen_mode\", Script::GenerateCRC( \"split_horizontal\" ));\r\n\t\t\tbreak;\r\n\t\tcase vSPLIT_QUARTERS:\r\n\t\t\tp_return_params->AddChecksum( \"screen_mode\", Script::GenerateCRC( \"split_quarters\" ));\r\n\t\t\tbreak;\r\n\t\tcase vONE_CAM:\r\n\t\t\tp_return_params->AddChecksum( \"screen_mode\", Script::GenerateCRC( \"one_camera\" ));\r\n\t\t\tbreak;\r\n\t\tcase vHORSE1:\r\n\t\t\tp_return_params->AddChecksum( \"screen_mode\", Script::GenerateCRC( \"horse1\" ));\r\n\t\t\tbreak;\r\n\t\tcase vHORSE2:\r\n\t\t\tp_return_params->AddChecksum( \"screen_mode\", Script::GenerateCRC( \"horse2\" ));\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,( \"invalid screen mode\"));\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | Set2DIn3DSpaceParams | Sets the parameters for the 2D Screen Elements in 3D space\r\n// @parmopt float | noscale_distance | 100.0 | Distance at which the 3D scale is equal to 1.0 (in inches)\r\n// @parmopt float | max_scale | 3.0 | Maximum 3D scale\r\n// @parmopt float | min_scale | 0.0 | Minimum 3D scale\r\nbool ScriptSet2DIn3DSpaceParams(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tfloat distance, scale;\r\n\r\n\tif (pParams->GetFloat(CRCD(0x33aa4915,\"noscale_distance\"), &distance))\r\n\t{\r\n\t\tCViewportManager::sSet2DIn3DSpaceNoscaleDistance(distance);\r\n\t}\r\n\r\n\tif (pParams->GetFloat(CRCD(0xa0a0db70,\"max_scale\"), &scale))\r\n\t{\r\n\t\tCViewportManager::sSet2DIn3DSpaceMaxScale(scale);\r\n\t}\r\n\r\n\tif (pParams->GetFloat(CRCD(0x774b6931,\"min_scale\"), &scale))\r\n\t{\r\n\t\tCViewportManager::sSet2DIn3DSpaceMinScale(scale);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxViewMan.h",
    "content": "#ifndef __GFX_NX_VIEWMAN_H__\r\n#define __GFX_NX_VIEWMAN_H__\r\n\r\n#include <gfx/camera.h>\r\n#include <gfx/nxviewport.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CScriptStructure;\r\n\tclass CScript;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\nextern const float vBASE_ASPECT_RATIO;\r\n\r\nenum ScreenMode\r\n{\r\n\tvONE_CAM = 0,\r\n\tvSPLIT_V,\r\n\tvSPLIT_H,\r\n\tvSPLIT_QUARTERS,\r\n\tvHORSE1,\r\n\tvHORSE2,\r\n\tvNUM_SCREEN_MODES\r\n};\r\n\r\nenum ViewportType\r\n{\r\n\tvMAIN = 0,\r\n\tvSECONDPLAYER,\t\t// 2nd player fullscreen, for horse\r\n\tvSPLIT_V_LEFT,\r\n\tvSPLIT_V_RIGHT,\r\n\tvSPLIT_H_TOP,\r\n\tvSPLIT_H_BOTTOM,\r\n\tvSPLIT_QUARTER_UL,\r\n\tvSPLIT_QUARTER_UR,\r\n\tvSPLIT_QUARTER_LL,\r\n\tvSPLIT_QUARTER_LR,\r\n\tvNUM_VIEWPORTS\r\n};\r\n\t\r\nclass CViewportManager\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvMAX_NUM_ACTIVE_VIEWPORTS\t= 4,\r\n\t};\r\n\r\n\tstatic void\t\t\t\t\tsInit(void);\r\n    static void                 sCleanup(void);\r\n\r\n\tstatic CViewport*\t\t\tsGetActiveViewport(int view = 0);\r\n\tstatic int\t\t\t\t\tsGetActiveViewportNumber(CViewport *p_viewport);\r\n\tstatic int\t\t\t\t\tsGetNumActiveViewports();\r\n\r\n\tstatic Gfx::Camera*\t\t\tsGetCamera(int index = 0);\r\n\tstatic void\t\t\t\t\tsSetCamera(int index, Gfx::Camera* pCamera);\r\n\tstatic void\t\t\t\t\tsSetCameraAllScreenModes(int index, Gfx::Camera* pCamera);\r\n\r\n\tstatic Gfx::Camera*\t\t\tsGetActiveCamera(int cam = 0);\r\n\tstatic Gfx::Camera*\t\t\tsGetClosestCamera(const Mth::Vector &pos, float *distParam = NULL);\r\n\tstatic int\t\t\t\t\tsGetNumActiveCameras();\r\n\r\n\tstatic bool\t\t\t\t\tsMarkCameraForDeletion(Gfx::Camera *pCamera);\r\n\tstatic void\t\t\t\t\tsDeleteMarkedCameras();\r\n\r\n\t// it would be nice to have descriptions of what these 'modes' are...\r\n\t// for now, i'm assuming screen mode 0 is where the camera is free from the skater.\r\n\tstatic ScreenMode\t\t\tsGetScreenMode();\r\n\tstatic void\t\t\t\t\tsSetScreenMode(ScreenMode mode);\r\n\r\n\t// some fundamental things about the TV\r\n\tstatic\tvoid\t\t\t\tsSetScreenAspect(float aspect);\r\n\tstatic\tfloat\t\t\t\tsGetScreenAspect();\r\n\tstatic\tvoid\t\t\t\tsSetDefaultAngle(float angle);\r\n\tstatic\tfloat\t\t\t\tsGetDefaultAngle();\r\n\tstatic\tvoid\t\t\t\tsSetScreenAngle(float angle);\r\n\tstatic\tfloat\t\t\t\tsGetScreenAngle();\r\n\tstatic\tfloat\t\t\t\tsGetScreenAngleFactor();\r\n\r\n\t// some parameters for 2D objects in 3D space\r\n\tstatic\tvoid\t\t\t\tsSet2DIn3DSpaceNoscaleDistance(float distance);\r\n\tstatic\tfloat\t\t\t\tsGet2DIn3DSpaceNoscaleDistance();\r\n\tstatic\tvoid\t\t\t\tsSet2DIn3DSpaceMaxScale(float scale);\r\n\tstatic\tfloat\t\t\t\tsGet2DIn3DSpaceMaxScale();\r\n\tstatic\tvoid\t\t\t\tsSet2DIn3DSpaceMinScale(float scale);\r\n\tstatic\tfloat\t\t\t\tsGet2DIn3DSpaceMinScale();\r\n\r\nprotected:\r\n\tstatic CViewport *\t\t\ts_create_viewport(const Mth::Rect* rect, Gfx::Camera* cam = NULL);\r\n\r\nprivate:\r\n\t// The platform dependent calls\r\n\tstatic CViewport *\t\t\ts_plat_create_viewport(const Mth::Rect* rect, Gfx::Camera* cam);\r\n\r\n\tstatic CViewport*\t\t\tsp_viewports[vNUM_VIEWPORTS];\r\n\tstatic const int*\t\t\tsp_active_viewport_indexes;\r\n\tstatic int\t\t\t\t\ts_num_active_viewports_cached;\r\n\r\n\tstatic const float\t\t\ts_viewport_rects[vNUM_VIEWPORTS][4];\r\n\tstatic const int \t\t\ts_num_active_viewports[vNUM_SCREEN_MODES];\r\n\tstatic const int\t\t\ts_screen_mode_viewport_indexes[vNUM_SCREEN_MODES][vMAX_NUM_ACTIVE_VIEWPORTS];\r\n\r\n\tstatic ScreenMode\t\t\ts_screen_mode;\r\n\r\n\tstatic\tfloat\t\t\t\ts_screen_aspect;\t\t\t\t // aspect ratio, usually 4/3 (1.3333333) or 16/9 (1.7777777)\r\n\tstatic\tfloat\t\t\t\ts_screen_angle;\t\t\t\t\t // angle subtended by the width of the screen usually 72 degrees\r\n\tstatic\tfloat\t\t\t\ts_default_angle;\t\t\t\t // the default value for s_screen_angle\r\n\tstatic\tfloat\t\t\t\ts_screen_angle_factor;\t\t\t // factor to multiply all the tan(cam_angle/2) camera values by\r\n\r\n\tstatic\tfloat\t\t\t\ts_2D_in_3D_space_noscale_distance;\t// z distance at which 3D scale would be 1.0\r\n\tstatic\tfloat\t\t\t\ts_2D_in_3D_space_max_scale;\t\t\t// maximum 3D scale\r\n\tstatic\tfloat\t\t\t\ts_2D_in_3D_space_min_scale;\t\t\t// minimum 3D scale\r\n};\r\n\r\n\r\n\r\nbool ScriptSetScreenMode(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetScreenMode(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSet2DIn3DSpaceParams(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\n///////////\r\n// Inlines\r\n///////////\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float\t\tCViewportManager::sGet2DIn3DSpaceNoscaleDistance()\r\n{\r\n\treturn s_2D_in_3D_space_noscale_distance;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float\t\tCViewportManager::sGet2DIn3DSpaceMaxScale()\r\n{\r\n\treturn s_2D_in_3D_space_max_scale;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float\t\tCViewportManager::sGet2DIn3DSpaceMinScale()\r\n{\r\n\treturn s_2D_in_3D_space_min_scale;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline int\t\t\tCViewportManager::sGetNumActiveViewports()\r\n{\r\n//\treturn s_num_active_viewports[s_screen_mode];\r\n\treturn s_num_active_viewports_cached;\r\n}\r\n\r\n\r\n}\r\n\r\n#endif // VIEWMAN\r\n"
  },
  {
    "path": "Code/Gfx/NxViewport.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics (GFX)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tviewport.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/29/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGraphics viewports\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#include <core/defines.h>\r\n#include <gfx/nxviewport.h>\r\n#include <gfx/nxviewman.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCViewport::CViewport( ) \r\n: m_Rect(0,0,1,1), m_flags(0), mp_camera(NULL)\r\n{\r\n\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCViewport::CViewport(const Mth::Rect* rect, Gfx::Camera* cam)\r\n: m_Rect(0,0,1,1), m_flags(0)\r\n{\r\n\t\r\n\r\n\tif (rect)\r\n\t{\t\r\n\t\tm_Rect.SetOriginX(rect->GetOriginX());\r\n\t\tm_Rect.SetOriginY(rect->GetOriginY());\r\n\t\tm_Rect.SetWidth(rect->GetWidth());\r\n\t\tm_Rect.SetHeight(rect->GetHeight());\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_Rect.SetOriginX(0);\r\n\t\tm_Rect.SetOriginY(0);\r\n\t\tm_Rect.SetWidth(1);\r\n\t\tm_Rect.SetHeight(1);\r\n\t}\r\n\r\n\t//m_pixel_ratio = parent->GetPixelRatio();\r\n\r\n\tmp_camera = cam;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCViewport::~CViewport ( void )\r\n{\t\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst float\t\tCViewport::GetAspectRatio() const\r\n{\r\n\treturn CViewportManager::sGetScreenAspect() * m_Rect.GetWidth() / m_Rect.GetHeight();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCViewport::MarkCameraForDeletion(Gfx::Camera *pCamera)\r\n{\r\n\tif (mp_camera == pCamera)\r\n\t{\r\n\t\tm_flags |= mCAMERA_MARKED_FOR_DELETION;\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCViewport::DeleteMarkedCamera()\r\n{\r\n\tif (m_flags & mCAMERA_MARKED_FOR_DELETION)\r\n\t{\r\n\t\tDbg_Assert(mp_camera);\r\n\t\tdelete mp_camera;\r\n\t\tmp_camera = NULL;\r\n\r\n\t\tm_flags &= ~mCAMERA_MARKED_FOR_DELETION;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\t\tCViewport::TransformToScreenCoord(const Mth::Vector & world_pos, float & screen_pos_x, float & screen_pos_y, ZBufferValue & screen_pos_z)\r\n{\r\n\treturn plat_transform_to_screen_coord(world_pos, screen_pos_x, screen_pos_y, screen_pos_z);\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stub versions of all platform specific functions:\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat\t\t\tCViewport::plat_transform_to_screen_coord(const Mth::Vector & world_pos, float & screen_pos_x, float & screen_pos_y, ZBufferValue & screen_pos_z)\r\n{\r\n\tprintf (\"STUB: PlatTransformToScreenCoord\\n\");\r\n\treturn -1.0f;\r\n}\r\n\r\n} // namespace Gfx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxViewport.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics  (GFX)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgfx/viewport.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t01/29/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_VIEWPORT_H\r\n#define __GFX_VIEWPORT_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/support.h>\r\n#include <core/math.h>\r\n#include <gfx/camera.h>\r\n#include <gel/objptr.h>\r\n\t\t\t  \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\n// Since a ZBuffer value is a platform-specific type, we need \"void\" type for it.\r\n// Since we do have to give it a size, the type has been assigned to a uint32.\r\n// It should not be treated as a uint32 above the p-line, though.\r\ntypedef uint32 ZBufferValue;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  CViewport\r\n{\r\n\t\r\n\tpublic :\r\n\t\t\t\t\t\tCViewport();\r\n\t\t\t\t\t\tCViewport(const Mth::Rect* Rect, Gfx::Camera* cam = NULL);\r\n\tvirtual\t\t\t\t~CViewport();\r\n\r\n\tGfx::Camera *\t\tGetCamera();\r\n\tvoid\t\t\t\tSetCamera(Gfx::Camera* cam);\r\n\r\n\tconst Mth::Rect &\tGetRect() const;\r\n\r\n\tconst\t\tfloat\tGetOriginX() const;\r\n\tconst\t\tfloat\tGetOriginY() const;\r\n\tconst\t\tfloat\tGetWidth() const;\r\n\tconst\t\tfloat\tGetHeight() const;\r\n\r\n\tconst\t\tfloat\tGetAspectRatio() const;\r\n\r\n\t// These functions are used to prevent the camera from being deleted prematurely\r\n\t\t\t\tbool\tMarkCameraForDeletion(Gfx::Camera *pCamera);\r\n\t\t\t\tvoid\tDeleteMarkedCamera();\r\n\r\n\t\t\t\tfloat\tTransformToScreenCoord(const Mth::Vector & world_pos, float & screen_pos_x, float & screen_pos_y, ZBufferValue & screen_pos_z);\r\n\r\nprotected:\t\r\n\t// Internal flags\r\n\tenum\r\n\t{\r\n\t\tmCAMERA_MARKED_FOR_DELETION\t\t= 0x00000001,\r\n\t};\r\n\r\n\t\r\n\tMth::Rect\t\t\tm_Rect;\r\n\tuint32\t\t\t\tm_flags;\r\n\r\n\tObj::CSmtPtr<Gfx::Camera> mp_camera;\t\t\t// Smart pointer to camera   \r\n//\tGfx::Camera *\t\tmp_camera;\r\n\r\nprivate :\t\r\n\tvirtual float\t\tplat_transform_to_screen_coord(const Mth::Vector & world_pos, float & screen_pos_x, float & screen_pos_y, ZBufferValue & screen_pos_z);\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Mth::Rect & CViewport::GetRect() const\r\n{\r\n\treturn m_Rect;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const float\tCViewport::GetOriginX ( void ) const\r\n{\r\n   \t\r\n\r\n\treturn m_Rect.GetOriginX();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const float\tCViewport::GetOriginY ( void ) const\r\n{\r\n   \t\r\n\r\n\treturn m_Rect.GetOriginY();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const float\tCViewport::GetWidth ( void ) const\r\n{\r\n   \t\r\n\r\n\treturn m_Rect.GetWidth();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const float\tCViewport::GetHeight ( void ) const\r\n{\r\n   \t\r\n\r\n\treturn m_Rect.GetHeight();\r\n}\r\n\t\r\n#if 0\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\r\ninline const float\t\tCViewport::GetPixelRatio ( void ) const\r\n{\r\n   \t\r\n\r\n\treturn \tm_pixel_ratio;\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Returns a pointer to the viewport's camera\r\n// since this uses a smart pointer, it will be NULL\r\n// if the camera has been deleted\r\n\t\t\t\r\ninline Gfx::Camera *\tCViewport::GetCamera ( void )\r\n{\r\n\treturn \tmp_camera.Convert();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\r\ninline void \t\t\tCViewport::SetCamera ( Gfx::Camera* cam )\r\n{\r\n\tDeleteMarkedCamera();\t\t\t// In case there is an old camera\r\n\tmp_camera = cam;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\r\n} // namespace Nx\r\n\r\n#endif\t// __GFX_VIEWPORT_H\r\n"
  },
  {
    "path": "Code/Gfx/NxWin2D.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxWin2D.cpp\r\n\r\n#include \"gfx/NxWin2D.h\"\r\n\r\nnamespace\tNx\r\n{\r\n// These functions are the platform independent part of the interface to \r\n// the platform specific code\r\n// parameter checking can go here....\r\n// although we might just want to have these functions inline, or not have them at all?\r\n\t\t\t\t\t \r\n///////////////////////////////////////////////////////////////////////////////\r\n// CWindow2D\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCWindow2D::CWindow2D(int x, int y, int width, int height) : \r\n\tm_xpos(x),\r\n\tm_ypos(y),\r\n\tm_width(width),\r\n\tm_height(height),\r\n\tmp_next(NULL)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCWindow2D::~CWindow2D() \r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCWindow2D::SetPos(int x, int y)\r\n{\r\n\tm_xpos = x;\r\n\tm_ypos = y;\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCWindow2D::SetSize(int width, int height)\r\n{\r\n\tm_width = width;\r\n\tm_height = height;\r\n\r\n\tplat_update_engine();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCWindow2D::plat_update_engine()\r\n{\r\n\tprintf (\"STUB: PlatUpdateEngine\\n\");\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// CWindow2DManager\r\n\r\nCWindow2D *\t\t\tCWindow2DManager::sp_window_list = NULL;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCWindow2DManager::sAllocWindow2DPool()\r\n{\r\n\ts_plat_alloc_window2d_pool();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCWindow2D *\t\tCWindow2DManager::sGetWindowInstance(int x, int y, int width, int height)\r\n{\r\n\tCWindow2D *p_window = sp_window_list;\r\n\r\n\tif (p_window)\r\n\t{\r\n\t\tsp_window_list = p_window->mp_next;\r\n\t} else {\r\n\t\tDbg_MsgAssert(0, (\"Out of CWindow2D Instances\"));\r\n\t}\r\n\r\n\t// Initialize\r\n\tp_window->SetPos(x, y);\r\n\tp_window->SetSize(width, height);\r\n\r\n\treturn p_window;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCWindow2DManager::sFreeWindowInstance(CWindow2D *p_window)\r\n{\r\n\tp_window->mp_next = sp_window_list;\r\n\tsp_window_list = p_window;\r\n}\r\n\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/NxWin2D.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxWin2D.h\r\n\r\n\r\n\r\n#ifndef\t__GFX_NXWIN2D_H__\r\n#define\t__GFX_NXWIN2D_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __CORE_MATH_RECT_H\r\n#include <core/math/rect.h>\r\n#endif\r\n\r\nnamespace Nx\r\n{\r\n\r\n// Forward declarations\r\nclass CWindow2DManager;\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n// Holds a string of text that needs to be displayed this frame\r\nclass CWindow2D\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCWindow2D(int x = 0, int y = 0, int width = 640, int height = 448);\r\n\t\t\t\t\t\t\tCWindow2D(const Mth::Rect & win_rect);\r\n\tvirtual\t\t\t\t\t~CWindow2D();\r\n\r\n\t// Position of screen.\r\n\tint\t\t\t\t\t\tGetXPos() const;\r\n\tint\t\t\t\t\t\tGetYPos() const;\r\n\tvoid\t\t\t\t\tSetPos(int x, int y);\r\n\r\n\t// Size of screen.\r\n\tint\t\t\t\t\t\tGetWidth() const;\r\n\tint\t\t\t\t\t\tGetHeight() const;\r\n\tvoid\t\t\t\t\tSetSize(int width, int height);\r\n\r\nprotected:\r\n\tint\t\t\t\t\t\tm_xpos;\r\n\tint\t\t\t\t\t\tm_ypos;\r\n\tint\t\t\t\t\t\tm_width;\r\n\tint\t\t\t\t\t\tm_height;\r\n\r\n\t// For free list in CWindow2DManager\r\n\tCWindow2D *\t\t\t\tmp_next;\r\n\r\nprivate:\r\n\t//\r\n\tvirtual void\t\t\tplat_update_engine();\r\n\r\n\tfriend CWindow2DManager;\r\n\r\n};\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n// Static class for memory management of CWindow2Ds\r\nclass CWindow2DManager\r\n{\r\npublic:\r\n\t//\r\n\tstatic void\t\t\t\tsAllocWindow2DPool();\r\n\tstatic CWindow2D *\t\tsGetWindowInstance(int x = 0, int y = 0, int width = 640, int height = 448);\r\n\tstatic void\t\t\t\tsFreeWindowInstance(CWindow2D *p_window);\r\n\r\nprivate:\r\n\t// Constants\r\n\tenum {\r\n\t\tvMAX_WINDOW_INSTANCES = 10\r\n\t};\r\n\r\n\t// Because it is static, it is declared here, but defined in p_NxWin2D.cpp\r\n\tstatic void\t\t\t\ts_plat_alloc_window2d_pool();\r\n\r\n\t// Array of Text requests\r\n\tstatic CWindow2D *\t   \tsp_window_list;\r\n};\r\n\r\n/////////////////////////////////////////////////////////\r\n// CText inline function\r\ninline int\t\t\t\t\tCWindow2D::GetXPos() const\r\n{\r\n\treturn m_xpos;\r\n}\r\n\r\ninline int\t\t\t\t\tCWindow2D::GetYPos() const\r\n{\r\n\treturn m_ypos;\r\n}\r\n\r\ninline int\t\t\t\t\tCWindow2D::GetWidth() const\r\n{\r\n\treturn m_width;\r\n}\r\n\r\ninline int\t\t\t\t\tCWindow2D::GetHeight() const\r\n{\r\n\treturn m_height;\r\n}\r\n\r\n}\r\n\r\n#endif // \r\n\r\n"
  },
  {
    "path": "Code/Gfx/Pose.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       Pose.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/13/2002\r\n//****************************************************************************\r\n\r\n#ifndef __GFX_POSE_H\r\n#define __GFX_POSE_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <core/math.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n    \r\n\tconst int vMAX_BONES = 64;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass CPose\r\n{\r\npublic:\r\n\tMth::Quat\t\tm_rotations[vMAX_BONES];\r\n\tMth::Vector\t\tm_translations[vMAX_BONES];\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n#endif\t// __GFX_POSE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/Skeleton.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       skeleton.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  11/15/2001\r\n//****************************************************************************\r\n\r\n// TODO:\r\n// Assert that the anim sequence contains the same number of bones as the skeleton?\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/skeleton.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/debuggfx.h>\r\n\r\n#include <sys/file/filesys.h>\r\n#include <core/crc.h>\r\n\r\n#ifdef __PLAT_NGC__\r\n#include \"dolphin.h\"\r\nextern bool g_in_cutscene;\r\n#endif\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define nxBONEFLAGS_ROTATE\t\t\t(1<<31)\r\n#define nxBONEFLAGS_NOANIM\t\t\t(1<<30)\r\n#define nxBONEFLAGS_SCALELOCAL\t\t(1<<29)\r\n#define nxBONEFLAGS_SCALENONLOCAL\t(1<<28)\r\n\r\n#define MAX_LOD_DISTANCE\t\t\t3.4e+38f;\r\n\r\nclass CBone\r\n{\r\npublic:\r\n\tCBone();\r\n\r\npublic:\r\n\tuint32\t\t\t\t\tm_name;\r\n\tMth::Matrix*\t\t\tmp_parentMatrix;\r\n\tMth::Matrix*\t\t\tmp_flippedMatrix;\r\n\r\n// GJ:  The neutral pose has been moved to the skeleton data,\r\n// since it can be shared by all the instances of this skeleton\r\n//\tMth::Matrix\t\t\t\tm_invertedNeutralMatrix;\r\n//\tMth::Matrix*\t\t\tmp_invertedNeutralParentMatrix;\r\n\t\r\n\tuint32\t\t\t\t\tm_flags;\r\n// GJ:  The parent name doesn't seem to be needed, and\r\n// can be accessed from the skeleton data if necessary...\r\n//\tuint32\t\t\t\t\tm_parentName;\r\n\tint\t\t\t\t\t\tm_flipIndex;\r\n\tMth::Vector\t\t\t\tm_scale;\r\n};\r\n\r\n// GJ:  Removed reference to skateboard, because\r\n// there shouldn't be anything skate-specific in here!\r\n//#define nxSKELETONFLAGS_ROTATESKATEBOARD\t(1<<30)\r\n\r\n// This flag has been moved to CAnimationComponent,\r\n// and will eventually be removed...\r\n#define nxSKELETONFLAGS_FLIPPED\t\t\t\t(1<<29)\r\n\r\n// This flag was used as a kludge on THPS4 to get\r\n// female models to scale properly (because supposedly-\r\n// equivalent vertices in the female model were weighted\r\n// to different bones in the male model)\r\n#define nxSKELETONFLAGS_FEMALESKELETON\t\t(1<<28)\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBone* CSkeleton::get_bone_by_id( uint32 boneId )\r\n{\r\n\tfor ( int i = 0; i < m_numBones; i++ )\r\n\t{\r\n\t\tif ( boneId == mp_bones[i].m_name )\r\n\t\t\treturn &mp_bones[i];\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBone::CBone()\r\n{\r\n\tm_name = 0;\r\n\tmp_parentMatrix = NULL;\r\n// GJ:  Parent name has been moved to skeleton data\r\n//\tm_parentName = 0;\r\n\tmp_flippedMatrix = NULL;\r\n// GJ:  Neutral pose has been moved to skeleton data\r\n//\tm_invertedNeutralMatrix.Ident();\r\n//\tmp_invertedNeutralParentMatrix = NULL;\r\n\tm_flipIndex = -1;\r\n\tm_flags = 0;\r\n\tm_scale = Mth::Vector( 1.0f, 1.0f, 1.0f );\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkeleton::CSkeleton( CSkeletonData* pSkeletonData )\r\n{\r\n    Dbg_Assert( pSkeletonData );\r\n\r\n\t// clear out flags completely\r\n\tm_flags = 0;\r\n\t\r\n\tif ( pSkeletonData->m_flags & 0x1 )\r\n\t{\r\n\t\tm_flags |= nxSKELETONFLAGS_FEMALESKELETON;\r\n\t}\r\n\r\n#ifdef __PLAT_NGC__\r\n\tint size = sizeof( CBone ) * pSkeletonData->GetNumBones();\r\n\tint mem_available;\r\n\tbool need_to_pop = false;\r\n\tif ( g_in_cutscene )\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().FrontEndHeap() );\r\n\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\tif ( size < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t{\r\n\t\t\tneed_to_pop = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ThemeHeap() );\r\n\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\tif ( size < ( mem_available - ( 5 * 1024 ) ) )\r\n\t\t\t{\r\n\t\t\t\tneed_to_pop = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ScriptHeap() );\r\n\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\tif ( size < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\t// __PLAT_NGC__\r\n\r\n\tmp_bones = new CBone[pSkeletonData->GetNumBones()];\r\n\r\n#ifdef __PLAT_NGC__\r\n\tif ( need_to_pop )\r\n\t{\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n#endif\t// __PLAT_NGC__\r\n\r\n#ifdef __PLAT_NGC__\r\n\tsize = sizeof( Mth::Matrix ) * pSkeletonData->GetNumBones();\r\n\tneed_to_pop = false;\r\n\tif ( g_in_cutscene )\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().FrontEndHeap() );\r\n\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\tif ( size < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t{\r\n\t\t\tneed_to_pop = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ThemeHeap() );\r\n\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\tif ( size < ( mem_available - ( 5 * 1024 ) ) )\r\n\t\t\t{\r\n\t\t\t\tneed_to_pop = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ScriptHeap() );\r\n\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\tif ( size < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\t// __PLAT_NGC__\r\n\r\n\tmp_matrices = new Mth::Matrix[pSkeletonData->GetNumBones()];\r\n\t\r\n#ifdef __PLAT_NGC__\r\n\tif ( need_to_pop )\r\n\t{\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n#endif\t// __PLAT_NGC__\r\n\r\n\t// clear out all the matrices to the identity\r\n\tMth::Matrix* p_currentMatrix = mp_matrices;\r\n\tfor ( int i = 0; i < pSkeletonData->GetNumBones(); i++ )\r\n\t{\r\n\t\tp_currentMatrix->Ident();\r\n\t\tp_currentMatrix++;\r\n\t}\r\n\r\n\tm_numBones = pSkeletonData->GetNumBones();\r\n\t\r\n    initialize_bone_names( pSkeletonData );\r\n    initialize_hierarchy( pSkeletonData );\r\n    initialize_flip_matrices( pSkeletonData );\r\n\r\n\tmp_skeletonData\t\t= pSkeletonData;\r\n\r\n\t// Set the maxmimum possible bone skip LOD level.\r\n\tSetMaxBoneSkipLOD( CSkeletonData::BONE_SKIP_LOD_BITS - 1 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkeleton::~CSkeleton()\r\n{\r\n\tdelete[] mp_bones;\r\n\tdelete[] mp_matrices;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CSkeleton::GetBoneIndexById( uint32 boneId )\r\n{\r\n\tfor ( int i = 0; i < m_numBones; i++ )\r\n\t{\r\n\t\tif ( boneId == mp_bones[i].m_name )\r\n\t\t\treturn i;\r\n\t}\r\n\r\n\treturn -1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CSkeleton::GetFlipIndex( int i )\r\n{\r\n\tCBone* pBone = &mp_bones[i];\r\n\treturn pBone->m_flipIndex;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSkeleton::initialize_flip_matrices( CSkeletonData* pSkeletonData )\r\n{\r\n    Dbg_Assert( pSkeletonData );\r\n    Dbg_Assert( pSkeletonData->GetNumBones() == m_numBones );\r\n\t\r\n\tfor ( int i = 0; i < pSkeletonData->GetNumBones(); i++ )\r\n\t{\r\n        // if it's got a flip\r\n        if ( pSkeletonData->GetFlipName(i) )\r\n        {\r\n            int index = pSkeletonData->GetIndex( pSkeletonData->GetFlipName(i) );\r\n            mp_bones[i].mp_flippedMatrix = mp_matrices + index;\r\n\t\t\tmp_bones[i].m_flipIndex = index;\r\n\r\n\t\t\t// and vice versa...\r\n\t\t\tmp_bones[index].m_flipIndex = i;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSkeleton::initialize_hierarchy( CSkeletonData* pSkeletonData )\r\n{\r\n\t// the parent of the root is itself.\r\n    \r\n    Dbg_Assert( pSkeletonData );\r\n    Dbg_Assert( pSkeletonData->GetNumBones() == m_numBones );\r\n\r\n    for ( int i = 0; i < pSkeletonData->GetNumBones(); i++ )\r\n    {\r\n        int parentIndex;\r\n         \r\n        if ( pSkeletonData->GetParentName(i) == 0 )\r\n        {\r\n            parentIndex = 0;\r\n        }\r\n        else\r\n        {\r\n            parentIndex = pSkeletonData->GetParentIndex( i );\r\n        }\r\n\r\n\t\tCBone* p_currentBone = &mp_bones[i];\r\n\r\n//\t\tDbg_Message( \"Parent of %d is %d\\n\", i, parentIndex );\r\n\r\n// GJ:  Parent name has been moved to skeleton data\r\n//\t\tp_currentBone->m_parentName = pSkeletonData->GetParentName(i);\r\n\r\n\t\t// Assign parentage here...\r\n\t\tp_currentBone->mp_parentMatrix = mp_matrices + parentIndex;\r\n\r\n// GJ:  Neutral pose has been moved to skeleton data\r\n//\t\tCBone* p_parentBone = &mp_bones[parentIndex];\r\n//\t\tp_currentBone->mp_invertedNeutralParentMatrix = &p_parentBone->m_invertedNeutralMatrix;\r\n\r\n\t\tp_currentBone->m_flags = 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSkeleton::initialize_bone_names( CSkeletonData* pSkeletonData )\r\n{\r\n    Dbg_Assert( pSkeletonData );\r\n    Dbg_Assert( pSkeletonData->GetNumBones() == m_numBones );\r\n\r\n    for ( int i = 0; i < pSkeletonData->GetNumBones(); i++ )\r\n    {\r\n\t\tmp_bones[i].m_name = pSkeletonData->GetBoneName( i );\r\n   \t}\r\n}\r\n\r\n#if 0\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nMth::Matrix CSkeleton::GetNeutralMatrix( int boneIndex )\r\n{\r\n\tDbg_MsgAssert( 0, ( \"This function has been deprecated.\" ) );\r\n\r\n\tDbg_Assert( boneIndex >= 0 && boneIndex < m_numBones );\r\n\r\n\tMth::Matrix theReturnMatrix;\r\n\r\n\ttheReturnMatrix = mp_bones[boneIndex].m_invertedNeutralMatrix;\r\n\ttheReturnMatrix.InvertUniform();\r\n\r\n\treturn theReturnMatrix;\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nMth::Matrix* CSkeleton::GetMatrices()\r\n{\r\n\treturn mp_matrices;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CSkeleton::GetNumBones() const\r\n{\r\n\treturn m_numBones;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkeleton::Display( Mth::Matrix* pRootMatrix, float r, float g, float b )\r\n{\r\n\tMth::Matrix* p_inverseNeutralPoseMatrices = mp_skeletonData->GetInverseNeutralPoseMatrices();\r\n\r\n\tfor ( int i = 0; i < m_numBones; i++ )\r\n\t{\r\n\t\tCBone* p_currentBone = &mp_bones[i];\r\n    \r\n\t\tMth::Matrix tempMatrix0, tempMatrix1;\r\n\t\t\t\t\t\r\n\t\tMth::Matrix boneMatrix;\r\n\t\tboneMatrix = *( mp_matrices + i );\r\n\t\ttempMatrix0 = *( p_inverseNeutralPoseMatrices + i );\r\n\t\ttempMatrix0.InvertUniform();\r\n\t\ttempMatrix0 = tempMatrix0 * boneMatrix;\r\n\t\ttempMatrix0 *= (*pRootMatrix);\r\n\t\t\r\n\t\tboneMatrix = *p_currentBone->mp_parentMatrix;\r\n\t\tif ( i == 0 )\r\n\t\t{\r\n\t\t\t// the root has no parent\r\n\t\t\ttempMatrix1.Ident();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttempMatrix1 = *( p_inverseNeutralPoseMatrices + mp_skeletonData->GetParentIndex(i) );\r\n\t\t}\r\n\t\ttempMatrix1.InvertUniform();\r\n\t\ttempMatrix1 = tempMatrix1 * boneMatrix; \r\n\t\ttempMatrix1 *= (*pRootMatrix);\r\n\t\t\r\n\t\tAddDebugBone( tempMatrix0.GetPos(), tempMatrix1.GetPos(), r, g, b );\r\n   }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkeleton::SetBoneActive( uint32 boneId, bool active )\r\n{\r\n\tCBone* pBone = get_bone_by_id( boneId );\r\n\r\n\tif ( pBone )\r\n\t{\r\n\t\tpBone->m_flags &= ~nxBONEFLAGS_NOANIM;\r\n\t\tpBone->m_flags |= ( active ? 0 : nxBONEFLAGS_NOANIM );\r\n\t}\r\n\r\n\treturn pBone;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkeleton::ApplyBoneScale( Script::CStruct* pBodyShapeStructure )\r\n{\r\n\t// TODO:  CSkeleton shouldn't know anything about\r\n\t// Script::CStruct*...  this should be moved\r\n\t// out to a higher level...\r\n\r\n\tif ( !pBodyShapeStructure ) \r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tint scaleFromOrigin = 0;\r\n\tpBodyShapeStructure->GetInteger( \"scaleFromOrigin\", &scaleFromOrigin, Script::NO_ASSERT );\r\n\tbool localScale = !scaleFromOrigin;\r\n\r\n\tMth::Vector theBoneScaleVector;\r\n\t\r\n\tfor ( int i = 0; i < m_numBones; i++ )\r\n\t{\r\n\t\tif ( pBodyShapeStructure->GetVector(mp_bones[i].m_name,&theBoneScaleVector,Script::NO_ASSERT) )\r\n\t\t{\r\n\t\t\tuint32 name = mp_bones[i].m_name;\r\n\r\n\t\t\tif ( m_flags & nxSKELETONFLAGS_FEMALESKELETON )\r\n\t\t\t{\r\n\t\t\t\tif ( name == CRCD(0x580c0963, \"head\") )\r\n\t\t\t\t{\r\n\t\t\t\t\tname = CRCD(0xdfee29ac,\"neck\");\r\n\t\t\t\t}\t\t   \r\n\t\t\t}\r\n\r\n\t\t\t// GJ PATCH:  test for Nolan\r\n\t\t\tScript::CArray* pNolanScalingTest = Script::GetArray( \"nonlocal_bones\", Script::NO_ASSERT );\r\n\t\t\tif ( pNolanScalingTest )\r\n\t\t\t{\r\n\t\t\t\tfor ( uint32 i = 0; i < pNolanScalingTest->GetSize(); i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( pNolanScalingTest->GetChecksum(i) == name )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tlocalScale = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tMth::Vector vec = Mth::Vector( 1.0f, 1.0f, 1.0f, 1.0f );\r\n\t\t\tif ( GetBoneScale( name, &vec ) )\r\n\t\t\t{\r\n\t\t\t\tvec[X] *= theBoneScaleVector[X];\r\n\t\t\t\tvec[Y] *= theBoneScaleVector[Y];\r\n\t\t\t\tvec[Z] *= theBoneScaleVector[Z];\r\n\t\t\t\tvec[W] = 1.0f;\r\n\r\n\t\t\t\tbool success = SetBoneScale(name, vec, localScale);\r\n\t\t\t\tif ( !success )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( 0, ( \"Couldn't apply bone scale %s\", Script::FindChecksumName(mp_bones[i].m_name) ) );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkeleton::ResetScale( void )\r\n{\r\n\tfor ( int i = 0; i < m_numBones; i++ )\r\n\t{\r\n\t\tCBone* pBone = &mp_bones[i];\r\n\t\tpBone->m_flags &= ~(nxBONEFLAGS_SCALELOCAL | nxBONEFLAGS_SCALENONLOCAL);\r\n\t\tpBone->m_scale = Mth::Vector( 1.0f, 1.0f, 1.0f, 1.0f );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkeleton::GetBoneScale( uint32 boneId, Mth::Vector* pBoneScaleVector )\r\n{\r\n\tCBone* pBone = get_bone_by_id( boneId );\r\n\r\n\tif ( pBone )\r\n\t{\r\n\t\tDbg_Assert( pBoneScaleVector );\r\n\t\t*pBoneScaleVector = pBone->m_scale;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Message( \"Couldn't find bone to scale %s\", Script::FindChecksumName(boneId) );\r\n\t}\r\n\r\n\treturn pBone;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkeleton::SetBoneScale( uint32 boneId, const Mth::Vector& theBoneScale, bool isLocalScale )\r\n{\r\n\tCBone* pBone = get_bone_by_id( boneId );\r\n\r\n\tif ( pBone )\r\n\t{\r\n\t\tpBone->m_scale = theBoneScale;\r\n\r\n\t\tbool isIdentityScale = ( theBoneScale[X] == 1.0f && theBoneScale[Y] == 1.0f && theBoneScale[Z] == 1.0f );\r\n\t\tpBone->m_flags &= ~(nxBONEFLAGS_SCALELOCAL | nxBONEFLAGS_SCALENONLOCAL);\r\n\t\tif ( !isIdentityScale )\r\n\t\t{\r\n\t\t\tpBone->m_flags |= ( isLocalScale ? nxBONEFLAGS_SCALELOCAL : nxBONEFLAGS_SCALENONLOCAL );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Message( \"Couldn't find bone to scale %s\", Script::FindChecksumName(boneId) );\r\n\t}\r\n\r\n\treturn pBone;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkeleton::CopyBoneScale( Gfx::CSkeleton* pSourceSkeleton )\r\n{\r\n\tCSkeletonData* pSkeletonData = pSourceSkeleton->GetSkeletonData();\r\n\tfor ( int i = 0; i < pSkeletonData->GetNumBones(); i++ )\r\n\t{\r\n\t\tuint32 boneName = pSkeletonData->GetBoneName( i );\r\n\r\n\t\tMth::Vector sourceScale;\r\n\r\n\t\t// if the bone exists in the destination skeleton,\r\n\t\t// and the source skeleton, then copy the scale\r\n\t\tif ( get_bone_by_id( boneName )\r\n\t\t\t && pSourceSkeleton->GetBoneScale( boneName, &sourceScale ) )\r\n\t\t{\r\n\t\t\tbool isLocalScale = true;\r\n\r\n\t\t\t#if 0\r\n\t\t\t// GJ:  This code handles the shoulder bones differently\r\n\t\t\t// so that the female skaters aren't so broad-shouldered.\r\n\t\t\t// However, it ends up screwing stuff up during cutscenes,\r\n\t\t\t// because the female's hands will not be aligned to the\r\n\t\t\t// items that she might be holding.  The only way I can\r\n\t\t\t// think of around this (right now) is to create female-\r\n\t\t\t// specific versions of the cutscenes, but it's too late \r\n\t\t\t// for that now.\r\n\t\t\tScript::CArray* pShoulderScalingArray = Script::GetArray( CRCD(0x20d9ac2f,\"nonlocal_bones\"), Script::NO_ASSERT );\r\n\t\t\tif ( pShoulderScalingArray )\r\n\t\t\t{\r\n\t\t\t\tfor ( uint32 i = 0; i < pShoulderScalingArray->GetSize(); i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( pShoulderScalingArray->GetChecksum(i) == boneName )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tisLocalScale = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t#endif\r\n\r\n\t\t\tSetBoneScale( boneName, sourceScale, isLocalScale );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void sQuatVecToMatrix( Mth::Quat* pQ, Mth::Vector* pT, Mth::Matrix* pMatrix, bool rotate, bool flip )\r\n{\r\n\tDbg_Assert( pQ );\r\n   \tDbg_Assert( pT );\r\n\tDbg_Assert( pMatrix );\r\n\t\r\n#ifdef __PLAT_NGPS__\r\n\tDbg_MsgAssert( ( (uint32)&(pQ->GetVector()) - (uint32)pQ )==0, (\"Quat::quat is no longer offset 0 bytes from the start of the Quat, need to modify the VU code in sQuatVecToMatrix\"));\r\n\t\r\n\tasm __volatile__(\"\r\n\t\r\n\tlw\t$8,(%3)\t# Put 'rotate' flag in t0\r\n\tlw\t$9,(%4)\t# Put 'flip' flag in t1\r\n\t\r\n\tlqc2    vf4,0x00(%0)\t\t\t# Load pQ into vf4\r\n\tlqc2    vf7,0x00(%1)\t\t\t# Load pT into vf7\r\n\t\r\n\t#\tsquare[X] = (*pQ)[X] * (*pQ)[X];\r\n\t#\tsquare[Y] = (*pQ)[Y] * (*pQ)[Y];\r\n\t#\tsquare[Z] = (*pQ)[Z] * (*pQ)[Z];\r\n\tvmul.xyz vf5,vf4,vf4\t\t\t# vf5=square\r\n\t\t\t\t\t\t\t\t\t\r\n\t#\tcross[X] = (*pQ)[Y] * (*pQ)[Z];\r\n\t#\tcross[Y] = (*pQ)[Z] * (*pQ)[X];\r\n\t#\tcross[Z] = (*pQ)[X] * (*pQ)[Y];\r\n\tvopmula.xyz     ACC,vf4,vf4\t\t# ACC=cross\r\n\r\n\t#\twimag[X] = -(*pQ)[W] * (*pQ)[X];\r\n\t#\twimag[Y] = -(*pQ)[W] * (*pQ)[Y];\r\n\t#\twimag[Z] = -(*pQ)[W] * (*pQ)[Z];\r\n\tvmsubw.xyzw vf8,vf4,vf4w\t# vf8=cross+wimag\r\n\tvmaddw.xyzw vf9,vf4,vf4w\t# vf9=cross-wimag\r\n\r\n\t\r\n\tvmulax.w\tACC,vf0,vf5x\t# ACCw=pQx squared\r\n\tvmadday.w\tACC,vf0,vf5y\t# ACCw=pQx squared + pQy squared\r\n\tvmaddz.w\tvf1,vf0,vf5z\t# vf1w=pQx squared + pQy squared + pQz squared\r\n\t\r\n\t# 3 vnops here ... use 2 of them with the following.\r\n\tvadd.xyz\tvf8,vf8,vf8\t\t# vf8=2*(cross+wimag)\r\n\tvadd.xyz\tvf9,vf9,vf9\t\t# vf9=2*(cross-wimag)\r\n\t\r\n\tvsubw.xyz\tvf1,vf5,vf1w\t# vf1=(-y2-z2,-x2-z2,-x2-y2)\r\n\t# 3 vnops here that could be used for something\r\n\tvaddaw.xyz\tACC,vf1,vf0w\t# ACC=(1-y2-z2,1-x2-z2,1-x2-y2)\r\n\tvmaddw.xyz\tvf1,vf1,vf0w\t# vf1=(1-2(y2+z2),1-2(x2+z2),1-2(x2+y2))\r\n\r\n\r\n\tbeqz\t$8,norotate\t\t# if (rotate)\r\n\tnop\r\n\r\n\tbeqz\t$9,noflip\t\t# if (flip)\r\n\tnop\r\n\r\n\t# (*pMatrix)[Mth::RIGHT][X] = -(1 - 2 * (square[Y] + square[Z]));\r\n\t# (*pMatrix)[Mth::RIGHT][Y] = 2 * (cross[Z] + wimag[Z]);\r\n\t# (*pMatrix)[Mth::RIGHT][Z] = 2 * (cross[Y] - wimag[Y]);\r\n\t# (*pMatrix)[Mth::RIGHT][W] = 0.0f;\r\n\tvsubax.x\tACC,vf0,vf1x\r\n\tvaddaz.y\tACC,vf0,vf8z\r\n\tvadday.z \tACC,vf0,vf9y\r\n\tvsubaw.w\tACC,vf0,vf0w\r\n\t# Save out (*pMatrix)[Mth::RIGHT]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x00(%2)\r\n\r\n\t# (*pMatrix)[Mth::UP][X] = 2 * (cross[Z] - wimag[Z]);\r\n\t# (*pMatrix)[Mth::UP][Y] = -(1 - 2 * (square[X] + square[Z]));\r\n\t# (*pMatrix)[Mth::UP][Z] = -(2 * (cross[X] + wimag[X]));\r\n\t# (*pMatrix)[Mth::UP][W] = 0.0f;\r\n\tvaddaz.x\tACC,vf0,vf9z\r\n\tvsubay.y\tACC,vf0,vf1y\r\n\tvsubax.z\tACC,vf0,vf8x\r\n\tvsubaw.w\tACC,vf0,vf0w\r\n\t# Save out (*pMatrix)[Mth::UP]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x10(%2)\r\n\r\n\t# (*pMatrix)[Mth::AT][X] = -(2 * (cross[Y] + wimag[Y]));\r\n\t# (*pMatrix)[Mth::AT][Y] = 2 * (cross[X] - wimag[X]);\r\n\t# (*pMatrix)[Mth::AT][Z] = 1 - 2 * (square[X] + square[Y]);\r\n\t# (*pMatrix)[Mth::AT][W] = 0.0f;\r\n\tvsubay.x\tACC,vf0,vf8y\r\n\tvaddax.y\tACC,vf0,vf9x\r\n\tvaddaz.z\tACC,vf0,vf1z\r\n\tvsubaw.w\tACC,vf0,vf0w\r\n\t# Save out (*pMatrix)[Mth::AT]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x20(%2)\r\n\r\n\t# (*pMatrix)[Mth::POS][X] = -pT->GetX();\r\n\t# (*pMatrix)[Mth::POS][Y] = pT->GetY();\r\n\t# (*pMatrix)[Mth::POS][Z] = pT->GetZ();\r\n\t# (*pMatrix)[Mth::POS][W] = 1.0f;\r\n\tvsubax.x\tACC,vf0,vf7x\r\n\tvadday.y\tACC,vf0,vf7y\r\n\tvaddaz.z\tACC,vf0,vf7z\r\n\tvaddax.w\tACC,vf0,vf0x\r\n\t# Save out (*pMatrix)[Mth::POS]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x30(%2)\r\n\t\r\n\tj\tovernorotate\t\t\r\n\tnop\r\nnoflip:\t\t\t\t\t\t\t# else  (if (flip))\r\n\r\n\t# (*pMatrix)[Mth::RIGHT][X] = -(1 - 2 * (square[Y] + square[Z]));\r\n\t# (*pMatrix)[Mth::RIGHT][Y] = -(2 * (cross[Z] + wimag[Z]));\r\n\t# (*pMatrix)[Mth::RIGHT][Z] = -(2 * (cross[Y] - wimag[Y]));\r\n\t# (*pMatrix)[Mth::RIGHT][W] = 0.0f;\r\n\tvsubax.x\tACC,vf0,vf1x\r\n\tvsubaz.y\tACC,vf0,vf8z\r\n\tvsubay.z \tACC,vf0,vf9y\r\n\tvsubaw.w\tACC,vf0,vf0w\r\n\t# Save out (*pMatrix)[Mth::RIGHT]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x00(%2)\r\n\r\n\t# (*pMatrix)[Mth::UP][X] = -(2 * (cross[Z] - wimag[Z]));\r\n\t# (*pMatrix)[Mth::UP][Y] = -(1 - 2 * (square[X] + square[Z]));\r\n\t# (*pMatrix)[Mth::UP][Z] = -(2 * (cross[X] + wimag[X]));\r\n\t# (*pMatrix)[Mth::UP][W] = 0.0f;\r\n\tvsubaz.x\tACC,vf0,vf9z\r\n\tvsubay.y\tACC,vf0,vf1y\r\n\tvsubax.z\tACC,vf0,vf8x\r\n\tvsubaw.w\tACC,vf0,vf0w\r\n\t# Save out (*pMatrix)[Mth::UP]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x10(%2)\r\n\r\n\t# (*pMatrix)[Mth::AT][X] = 2 * (cross[Y] + wimag[Y]);\r\n\t# (*pMatrix)[Mth::AT][Y] = 2 * (cross[X] - wimag[X]);\r\n\t# (*pMatrix)[Mth::AT][Z] = 1 - 2 * (square[X] + square[Y]);\r\n\t# (*pMatrix)[Mth::AT][W] = 0.0f;\r\n\tvadday.x\tACC,vf0,vf8y\r\n\tvaddax.y\tACC,vf0,vf9x\r\n\tvaddaz.z\tACC,vf0,vf1z\r\n\tvsubaw.w\tACC,vf0,vf0w\r\n\t# Save out (*pMatrix)[Mth::AT]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x20(%2)\r\n\r\n\t# (*pMatrix)[Mth::POS][X] = pT->GetX();\r\n\t# (*pMatrix)[Mth::POS][Y] = pT->GetY();\r\n\t# (*pMatrix)[Mth::POS][Z] = pT->GetZ();\r\n\t# (*pMatrix)[Mth::POS][W] = 1.0f;\r\n\tvaddax.x\tACC,vf0,vf7x\r\n\tvadday.y\tACC,vf0,vf7y\r\n\tvaddaz.z\tACC,vf0,vf7z\r\n\tvaddax.w\tACC,vf0,vf0x\r\n\t# Save out (*pMatrix)[Mth::POS]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x30(%2)\r\n\r\n\tj\tovernorotate\t\t\r\n\tnop\t\t\t\t\t\t# else (if (rotate))\r\nnorotate:\r\n\r\n\tbeqz\t$9,noflip2\t\t# if (flip)\r\n\tnop\r\n\r\n\t# (*pMatrix)[Mth::RIGHT][X] = 1 - 2 * (square[Y] + square[Z]);\r\n\t# (*pMatrix)[Mth::RIGHT][Y] = -(2 * (cross[Z] + wimag[Z]));\r\n\t# (*pMatrix)[Mth::RIGHT][Z] = -(2 * (cross[Y] - wimag[Y]));\r\n\t# (*pMatrix)[Mth::RIGHT][W] = 0.0f;\r\n\tvaddax.x\tACC,vf0,vf1x\r\n\tvsubaz.y\tACC,vf0,vf8z\r\n\tvsubay.z \tACC,vf0,vf9y\r\n\tvsubaw.w\tACC,vf0,vf0w\r\n\t# Save out (*pMatrix)[Mth::RIGHT]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x00(%2)\r\n\r\n\t# (*pMatrix)[Mth::UP][X] = -(2 * (cross[Z] - wimag[Z]));\r\n\t# (*pMatrix)[Mth::UP][Y] = 1 - 2 * (square[X] + square[Z]);\r\n\t# (*pMatrix)[Mth::UP][Z] = 2 * (cross[X] + wimag[X]);\r\n\t# (*pMatrix)[Mth::UP][W] = 0.0f;\r\n\tvsubaz.x\tACC,vf0,vf9z\r\n\tvadday.y\tACC,vf0,vf1y\r\n\tvaddax.z\tACC,vf0,vf8x\r\n\tvsubaw.w\tACC,vf0,vf0w\r\n\t# Save out (*pMatrix)[Mth::UP]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x10(%2)\r\n\r\n\t# (*pMatrix)[Mth::AT][X] = -(2 * (cross[Y] + wimag[Y]));\r\n\t# (*pMatrix)[Mth::AT][Y] = 2 * (cross[X] - wimag[X]);\r\n\t# (*pMatrix)[Mth::AT][Z] = 1 - 2 * (square[X] + square[Y]);\r\n\t# (*pMatrix)[Mth::AT][W] = 0.0f;\r\n\tvsubay.x\tACC,vf0,vf8y\r\n\tvaddax.y\tACC,vf0,vf9x\r\n\tvaddaz.z\tACC,vf0,vf1z\r\n\tvsubaw.w\tACC,vf0,vf0w\r\n\t# Save out (*pMatrix)[Mth::AT]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x20(%2)\r\n\r\n\t# (*pMatrix)[Mth::POS][X] = -pT->GetX();\r\n\t# (*pMatrix)[Mth::POS][Y] = pT->GetY();\r\n\t# (*pMatrix)[Mth::POS][Z] = pT->GetZ();\r\n\t# (*pMatrix)[Mth::POS][W] = 1.0f;\r\n\tvsubax.x\tACC,vf0,vf7x\r\n\tvadday.y\tACC,vf0,vf7y\r\n\tvaddaz.z\tACC,vf0,vf7z\r\n\tvaddax.w\tACC,vf0,vf0x\r\n\t# Save out (*pMatrix)[Mth::POS]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x30(%2)\r\n\r\n\tj\tovernoflip2\t\t\t# else  (if (flip))\r\n\tnop\r\nnoflip2:\r\n\r\n\t# (*pMatrix)[Mth::RIGHT][X] = 1 - 2 * (square[Y] + square[Z]);\r\n\t# (*pMatrix)[Mth::RIGHT][Y] = 2 * (cross[Z] + wimag[Z]);\r\n\t# (*pMatrix)[Mth::RIGHT][Z] = 2 * (cross[Y] - wimag[Y]);\r\n\t# (*pMatrix)[Mth::RIGHT][W] = 0.0f;\r\n\tvaddax.x\tACC,vf0,vf1x\r\n\tvaddaz.y\tACC,vf0,vf8z\r\n\tvadday.z \tACC,vf0,vf9y\r\n\tvsubaw.w\tACC,vf0,vf0w\r\n\t# Save out (*pMatrix)[Mth::RIGHT]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x00(%2)\r\n\r\n\t# (*pMatrix)[Mth::UP][X] = 2 * (cross[Z] - wimag[Z]);\r\n\t# (*pMatrix)[Mth::UP][Y] = 1 - 2 * (square[X] + square[Z]);\r\n\t# (*pMatrix)[Mth::UP][Z] = 2 * (cross[X] + wimag[X]);\r\n\t# (*pMatrix)[Mth::UP][W] = 0.0f;\r\n\tvaddaz.x\tACC,vf0,vf9z\r\n\tvadday.y\tACC,vf0,vf1y\r\n\tvaddax.z\tACC,vf0,vf8x\r\n\tvsubaw.w\tACC,vf0,vf0w\r\n\t# Save out (*pMatrix)[Mth::UP]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x10(%2)\r\n\r\n\t# (*pMatrix)[Mth::AT][X] = 2 * (cross[Y] + wimag[Y]);\r\n\t# (*pMatrix)[Mth::AT][Y] = 2 * (cross[X] - wimag[X]);\r\n\t# (*pMatrix)[Mth::AT][Z] = 1 - 2 * (square[X] + square[Y]);\r\n\t# (*pMatrix)[Mth::AT][W] = 0.0f;\r\n\tvadday.x\tACC,vf0,vf8y\r\n\tvaddax.y\tACC,vf0,vf9x\r\n\tvaddaz.z\tACC,vf0,vf1z\r\n\tvsubaw.w\tACC,vf0,vf0w\r\n\t# Save out (*pMatrix)[Mth::AT]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x20(%2)\r\n\r\n\t# (*pMatrix)[Mth::POS][X] = pT->GetX();\r\n\t# (*pMatrix)[Mth::POS][Y] = pT->GetY();\r\n\t# (*pMatrix)[Mth::POS][Z] = pT->GetZ();\r\n\t# (*pMatrix)[Mth::POS][W] = 1.0f;\r\n\tvaddax.x\tACC,vf0,vf7x\r\n\tvadday.y\tACC,vf0,vf7y\r\n\tvaddaz.z\tACC,vf0,vf7z\r\n\tvaddax.w\tACC,vf0,vf0x\r\n\t# Save out (*pMatrix)[Mth::POS]\r\n\tvmaddx.xyzw\tvf11,vf0,vf0x\r\n\tsqc2\t\tvf11,0x30(%2)\r\n\r\novernoflip2:\r\n\t\r\novernorotate:\r\n\r\n\t\": : \"r\" (pQ), \"r\" (pT), \"r\" (pMatrix), \"r\" (&rotate), \"r\" (&flip) : \"$8\",\"$9\");\r\n\r\n#else\r\n#ifdef __PLAT_NGC__\r\n\tMTXQuat( (Mtx)pMatrix, (QuaternionPtr)pQ );\r\n\r\n\t(*pMatrix)[Mth::POS][X] = pT->GetX();\r\n\t(*pMatrix)[Mth::POS][Y] = pT->GetY();\r\n\t(*pMatrix)[Mth::POS][Z] = pT->GetZ();\r\n\t(*pMatrix)[Mth::POS][W] = 1.0f;\r\n#else\r\n\t// Ye olde slowe code\r\n\tMth::Vector\t\tsquare;\r\n\tMth::Vector\t\tcross;\r\n\tMth::Vector\t\twimag;\r\n\r\n\tsquare[X] = (*pQ)[X] * (*pQ)[X];\r\n\tsquare[Y] = (*pQ)[Y] * (*pQ)[Y];\r\n\tsquare[Z] = (*pQ)[Z] * (*pQ)[Z];\r\n\r\n\tcross[X] = (*pQ)[Y] * (*pQ)[Z];\r\n\tcross[Y] = (*pQ)[Z] * (*pQ)[X];\r\n\tcross[Z] = (*pQ)[X] * (*pQ)[Y];\r\n\r\n\twimag[X] = -(*pQ)[W] * (*pQ)[X];\r\n\twimag[Y] = -(*pQ)[W] * (*pQ)[Y];\r\n\twimag[Z] = -(*pQ)[W] * (*pQ)[Z];\r\n\r\n\t(*pMatrix)[Mth::RIGHT][X] = 1 - 2 * (square[Y] + square[Z]);\r\n\t(*pMatrix)[Mth::RIGHT][Y] = 2 * (cross[Z] + wimag[Z]);\r\n\t(*pMatrix)[Mth::RIGHT][Z] = 2 * (cross[Y] - wimag[Y]);\r\n\t(*pMatrix)[Mth::RIGHT][W] = 0.0f;\r\n\t\r\n\t(*pMatrix)[Mth::UP][X] = 2 * (cross[Z] - wimag[Z]);\r\n\t(*pMatrix)[Mth::UP][Y] = 1 - 2 * (square[X] + square[Z]);\r\n\t(*pMatrix)[Mth::UP][Z] = 2 * (cross[X] + wimag[X]);\r\n\t(*pMatrix)[Mth::UP][W] = 0.0f;\r\n\r\n\t(*pMatrix)[Mth::AT][X] = 2 * (cross[Y] + wimag[Y]);\r\n\t(*pMatrix)[Mth::AT][Y] = 2 * (cross[X] - wimag[X]);\r\n\t(*pMatrix)[Mth::AT][Z] = 1 - 2 * (square[X] + square[Y]);\r\n\t(*pMatrix)[Mth::AT][W] = 0.0f;\r\n\r\n\t(*pMatrix)[Mth::POS][X] = pT->GetX();\r\n\t(*pMatrix)[Mth::POS][Y] = pT->GetY();\r\n\t(*pMatrix)[Mth::POS][Z] = pT->GetZ();\r\n\t(*pMatrix)[Mth::POS][W] = 1.0f;\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\tif (rotate)\r\n\t{\r\n\t\t// compensate for bone rotation (like for the skateboards)\r\n\r\n\t\tif (flip)\r\n\t\t{\r\n\t\t\t// Right: -x,y,z\r\n\t\t\t(*pMatrix)[Mth::RIGHT][X] = -(*pMatrix)[Mth::RIGHT][X];\r\n\t\t\t// Up: x,-y,-z\r\n\t\t\t(*pMatrix)[Mth::UP][Y]=-(*pMatrix)[Mth::UP][Y];\r\n\t\t\t(*pMatrix)[Mth::UP][Z]=-(*pMatrix)[Mth::UP][Z];\r\n\t\t\t// At: -x,y,z\r\n\t\t\t(*pMatrix)[Mth::AT][X]=-(*pMatrix)[Mth::AT][X];\r\n\t\t\t// Pos: -x,y,z\r\n\t\t\t(*pMatrix)[Mth::POS][X]=-(*pMatrix)[Mth::POS][X];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Right: -x,-y,-z\r\n\t\t\t(*pMatrix)[Mth::RIGHT][X] = -(*pMatrix)[Mth::RIGHT][X];\r\n\t\t\t(*pMatrix)[Mth::RIGHT][Y] = -(*pMatrix)[Mth::RIGHT][Y];\r\n\t\t\t(*pMatrix)[Mth::RIGHT][Z] = -(*pMatrix)[Mth::RIGHT][Z];\r\n\t\t\t// Up: -x,-y,-z\r\n\t\t\t(*pMatrix)[Mth::UP][X]=-(*pMatrix)[Mth::UP][X];\r\n\t\t\t(*pMatrix)[Mth::UP][Y]=-(*pMatrix)[Mth::UP][Y];\r\n\t\t\t(*pMatrix)[Mth::UP][Z]=-(*pMatrix)[Mth::UP][Z];\r\n\t\t\t// At: x,y,z\r\n\t\t\t// Pos: x,y,z\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (flip)\r\n\t\t{\r\n\t\t\t// Right: x,-y,-z\r\n\t\t\t(*pMatrix)[Mth::RIGHT][Y] = -(*pMatrix)[Mth::RIGHT][Y];\r\n\t\t\t(*pMatrix)[Mth::RIGHT][Z] = -(*pMatrix)[Mth::RIGHT][Z];\r\n\t\t\t// Up: -x,y,z\r\n\t\t\t(*pMatrix)[Mth::UP][X]=-(*pMatrix)[Mth::UP][X];\r\n\t\t\t// At: -x,y,z\r\n\t\t\t(*pMatrix)[Mth::AT][X]=-(*pMatrix)[Mth::AT][X];\r\n\t\t\t// Pos: -x,y,z\r\n\t\t\t(*pMatrix)[Mth::POS][X]=-(*pMatrix)[Mth::POS][X];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Right: x,y,z\r\n\t\t\t// Up: x,y,z\r\n\t\t\t// At: x,y,z\r\n\t\t\t// Pos: x,y,z\r\n\t\t}\t\r\n\t}\t\r\n#endif\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSkeleton::Update( CPose* pPose )\r\n{\r\n\tthis->Update( &pPose->m_rotations[0], &pPose->m_translations[0] );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkeleton::Update( Mth::Quat* pQuat, Mth::Vector* pTrans )\r\n{\r\n\tCBone* p_currentBone = mp_bones;\r\n\tMth::Matrix* p_currentMatrix=mp_matrices;\r\n\tMth::Quat* p_current_quat=pQuat;\r\n\tMth::Vector* p_current_trans=pTrans;\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tbool flipped = m_flags & nxSKELETONFLAGS_FLIPPED;\r\n\tif ( flipped )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Flipping has been moved to CAnimationComponent\" ) );\r\n\t}\r\n#endif\r\n\r\n\t// Calculate the mask for testing the bone skip data.\r\n\tuint32 skip_index_mask\t= 1 << GetBoneSkipIndex();\r\n\tuint32*\tp_skip_list\t\t= mp_skeletonData->GetBoneSkipList();\r\n\r\n\tfor ( int i = 0; i < m_numBones; i++ )\r\n\t{\r\n\t\tif( !( p_currentBone->m_flags & nxBONEFLAGS_NOANIM ))\r\n\t\t{\r\n\t\t\t// Decide whether we can skip this bone. Skipping bones where a child bone is not skipped will cause\r\n\t\t\t// problems.\r\n\t\t\tbool skip_this_bone = (( p_skip_list[i] & skip_index_mask ) != 0 );\r\n\t\t\tif( !skip_this_bone )\r\n\t\t\t{\r\n\t\t\t\t// Skateboard rotation has been moved to CAnimationComponent.\r\n\t\t\t\tDbg_MsgAssert( !( p_currentBone->m_flags & nxBONEFLAGS_ROTATE ), ( \"Skateboard rotation has been moved to CAnimationComponent\" ) );\r\n\r\n\t\t\t\tsQuatVecToMatrix( p_current_quat, p_current_trans, p_currentMatrix, false, false );\r\n\t\t\r\n\t\t\t\tif ( p_currentBone->m_flags & nxBONEFLAGS_SCALENONLOCAL )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_currentMatrix->Scale( p_currentBone->m_scale );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( i != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// if it's not the root, then apply the parent's xform\r\n\t\t\t\t\t(*p_currentMatrix) *= *(p_currentBone->mp_parentMatrix);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Use the parent bone's matrix for now.\r\n\t\t\t\t(*p_currentMatrix) = *(p_currentBone->mp_parentMatrix);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tp_currentMatrix++;\r\n\t\tp_currentBone++;\r\n\t\tp_current_quat++;\r\n\t\tp_current_trans++;\r\n\t}\r\n\r\n\tMth::Matrix* p_currentInverseNeutralPoseMatrix = mp_skeletonData->GetInverseNeutralPoseMatrices();\r\n\tDbg_MsgAssert( p_currentInverseNeutralPoseMatrix, ( \"Was expecting neutral pose matrices to be initialized.  SKE files not in version 2 format?\" ) );\r\n\r\n\t// Loop through each bone and update its matrices\r\n\tp_currentBone=mp_bones;\r\n\tp_currentMatrix=mp_matrices;\r\n\tfor ( int i = 0; i < m_numBones; i++ )\r\n\t{\r\n\t\tif ( !(p_currentBone->m_flags & nxBONEFLAGS_NOANIM) )\r\n\t\t{\r\n\t\t\tif ( p_currentBone->m_flags & nxBONEFLAGS_SCALELOCAL )\r\n\t\t\t{\r\n\t\t\t\tp_currentMatrix->ScaleLocal( p_currentBone->m_scale );\r\n\t\t\t}\r\n\r\n\t\t\t// switching over to the new system of having the neutral pose\r\n//\t\t\tDbg_MsgAssert( p_currentInverseNeutralPoseMatrix, ( \"default anims have been deprecated\" ) );\r\n//\t\t\t(*p_currentMatrix) = p_currentBone->m_invertedNeutralMatrix * (*p_currentMatrix);\t\t\r\n\r\n\t\t\t// data inside the SKE file, rather than the skeleton instance\r\n\t\t\t(*p_currentMatrix) = (*p_currentInverseNeutralPoseMatrix) * (*p_currentMatrix);\t\t\r\n\t\t\t\t\r\n\t\t\t// clear out final component, just in case...\r\n\t\t\t// it's probably be worth investigating whether we need to do this...\r\n\t\t\t(*p_currentMatrix)[Mth::RIGHT][W] = 0.0f;\r\n\t\t\t(*p_currentMatrix)[Mth::UP][W] = 0.0f;\r\n\t\t\t(*p_currentMatrix)[Mth::AT][W] = 0.0f;\r\n//\t\t\t(*p_currentMatrix)[Mth::POS][W] = 1.0f;\r\n\t\t}\r\n\r\n\t\tp_currentInverseNeutralPoseMatrix++;\r\n\t\tp_currentMatrix++;\r\n\t\tp_currentBone++;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkeleton::GetBoneMatrix( uint32 boneId, Mth::Matrix* pBoneMatrix )\r\n{\r\n\tDbg_Assert( pBoneMatrix );\r\n\r\n\tCBone* pBone = get_bone_by_id( boneId );\r\n\tint i = GetBoneIndexById( boneId );\r\n\r\n\tif ( !pBone )\r\n\t{\r\n\t\t// for now, since we're changing our bone names around,\r\n\t\t// don't assert if we can't find the bone...\r\n\t\treturn false;\r\n\t}\r\n\r\n\tDbg_MsgAssert( pBone, ( \"Couldn't find bone with id %s\", Script::FindChecksumName(boneId) ) );\r\n\r\n\t// m_matrix represents the transform needed to go from the default (neutral)\r\n\t// pose to the actual pose with animation applied to it.  So, we need to\r\n\t// transform this value by the root-to-neutral matrix (m_neutralMatrix)\r\n\t// in order to get the actual animated-bone's position for this frame (relative\r\n\t// to the root of the object).\r\n\r\n\tMth::Matrix boneMatrix;\r\n\tboneMatrix = *(mp_matrices + i);\r\n\t\r\n\t// GJ 2/21/03:  i'm not sure why we needed to deal with the\r\n\t// neutral matrix at all...   should look into this at some\r\n\t// point...\r\n\tMth::Matrix theMat = *( mp_skeletonData->GetInverseNeutralPoseMatrices() + i );\r\n//\tMth::Matrix theMat = pBone->m_invertedNeutralMatrix;\r\n\ttheMat.InvertUniform();\r\n\ttheMat = theMat * boneMatrix;\r\n    \r\n\t// GJ kludge:  the root bone contains a 90 degree rotation\r\n\t// to compensate for the MAX->Game coordinate change\r\n\t// but we don't want that to affect the bone matrix, \r\n\t// so transform it by the inverse of the root matrix\r\n//\tCBone* pDummyBone = get_bone_by_id( CRCD(0x9f173eeb,\"dummy_scale_zz\") );\r\n//\tif ( pDummyBone )\r\n\t\r\n\tint dummyIndex = GetBoneIndexById( CRCD(0x9f173eeb,\"dummy_scale_zz\") );\r\n\tif ( dummyIndex != -1 )\r\n\t{\r\n\t\tMth::Vector temp = theMat[Mth::POS];\r\n\t\ttheMat[Mth::POS] = Mth::Vector(0.0f,0.0f,0.0f,1.0f);\r\n\t\tMth::Matrix dummyMatrix = *( mp_skeletonData->GetInverseNeutralPoseMatrices() + dummyIndex );\r\n//\t\tMth::Matrix dummyMatrix = pDummyBone->m_invertedNeutralMatrix;\r\n\t\ttheMat = dummyMatrix * theMat;\r\n\t\ttheMat[Mth::POS] = temp;\r\n\t}\r\n\r\n\t(*pBoneMatrix) = theMat;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32* CSkeleton::GetBoneSkipList( void )\r\n{\r\n\tif( mp_skeletonData )\r\n\t{\r\n\t\treturn mp_skeletonData->GetBoneSkipList();\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkeleton::SetBoneSkipDistance( float dist )\r\n{\r\n\tif( mp_skeletonData )\r\n\t{\r\n\t\tfor( uint32 lod = 0; lod <= m_maxBoneSkipLOD; ++lod )\r\n\t\t{\r\n\t\t\tif( dist < mp_skeletonData->GetBoneSkipDistance( lod ))\r\n\t\t\t{\r\n\t\t\t\tm_skipIndex = lod;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tm_skipIndex = m_maxBoneSkipLOD;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkeleton::GetBonePosition( uint32 boneId, Mth::Vector* pBonePos )\r\n{\r\n\tDbg_Assert( pBonePos );\r\n\r\n\tCBone* pBone = get_bone_by_id( boneId );\r\n\tint i = GetBoneIndexById( boneId );\r\n\r\n\tif ( !pBone )\r\n\t{\r\n\t\t// for now, since we're changing our bone names around,\r\n\t\t// don't assert if we can't find the bone...\r\n\t\treturn false;\r\n\t}\r\n\r\n\tDbg_MsgAssert( pBone, ( \"Couldn't find bone with id %s\", Script::FindChecksumName(boneId) ) );\r\n\r\n\t// m_matrix represents the transform needed to go from the default (neutral)\r\n\t// pose to the actual pose with animation applied to it.  So, we need to\r\n\t// transform this value by the root-to-neutral matrix (m_neutralMatrix)\r\n\t// in order to get the actual animated-bone's position for this frame (relative\r\n\t// to the root of the object).\r\n\r\n\t// GJ 2/21/03:  i'm not sure why we needed to deal with the\r\n\t// neutral matrix at all...   should look into this at some\r\n\t// point...\r\n\r\n\tMth::Matrix boneMatrix;\r\n\tboneMatrix = *(mp_matrices + i);\r\n\tMth::Matrix theMat = *( mp_skeletonData->GetInverseNeutralPoseMatrices() + i );\r\n//\tMth::Matrix theMat = pBone->m_invertedNeutralMatrix;\r\n\ttheMat.InvertUniform();\r\n\ttheMat = theMat * boneMatrix;\r\n    \r\n    (*pBonePos) = theMat[Mth::POS];\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkeletonData::CSkeletonData()\r\n{\r\n    m_numBones = 0;\r\n\tm_flags = 0;\r\n    m_animScriptName = 0;\r\n\tmp_inverseNeutralPoseMatrices = NULL;\r\n\r\n\t// Default the Level0 LOD distance to a large number.\r\n\tm_skipLODDistances[0] = MAX_LOD_DISTANCE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkeletonData::~CSkeletonData()\r\n{\r\n\tif ( mp_inverseNeutralPoseMatrices )\r\n\t{\r\n\t\tdelete[] mp_inverseNeutralPoseMatrices;\r\n\t\tmp_inverseNeutralPoseMatrices = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkeletonData::Load( uint32* p_data32, int data_size, bool assertOnFail )\r\n{\r\n\tuint8* p_data = (uint8*)p_data32;\r\n\r\n\t// new load of platform-specific SKE files...\r\n\tbool success = false;\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tint versionNumber = *((int*)p_data);\r\n\tDbg_MsgAssert( versionNumber >= 2, ( \"No longer supporting old SKE format\" ) );\r\n#endif\r\n\tp_data += sizeof(int);\r\n\t\t\r\n\tm_flags = *((uint32*)p_data);\r\n\tp_data += sizeof(uint32);\r\n\r\n\tm_numBones = *((int*)p_data);\r\n\tp_data += sizeof(int);\r\n    \r\n    Dbg_MsgAssert( m_numBones < vMAX_BONES, ( \"Too many bones in skeleton (raise vMAX_BONES from %d to %d)\", vMAX_BONES, m_numBones ) );\r\n\r\n\tmemcpy( m_boneNameTable, p_data, m_numBones * sizeof(uint32) );\r\n\tp_data += ( m_numBones * sizeof(uint32) );\r\n\r\n\tmemcpy( m_parentNameTable, p_data, m_numBones * sizeof(uint32) );\r\n\tp_data += ( m_numBones * sizeof(uint32) );\r\n\r\n\tmemcpy( m_flipNameTable, p_data, m_numBones * sizeof(uint32) );\r\n\tp_data += ( m_numBones * sizeof(uint32) );\r\n\t\r\n\tDbg_MsgAssert( mp_inverseNeutralPoseMatrices == NULL, ( \"Inverse neutral pose matrices not NULL?!?\" ) );\r\n\tmp_inverseNeutralPoseMatrices = new Mth::Matrix[m_numBones];\r\n\r\n\tfor ( int i = 0; i < m_numBones; i++ )\r\n\t{\r\n// Mick: read a word at a time, as it's not aligned and I'm trying to ensure\r\n// that all vector operations work on aligned boundries\r\n// so we can optimize with that assumption\t\r\n//\t\tMth::Quat theQuat = *((Mth::Quat*)p_data);\r\n\t\tMth::Quat theQuat;\r\n\t\ttheQuat[X] = *((float*)p_data);\r\n\t\ttheQuat[Y] = *((float*)(p_data+4));\r\n\t\ttheQuat[Z] = *((float*)(p_data+8));\r\n\t\ttheQuat[W] = *((float*)(p_data+12));\r\n\t\tp_data += sizeof(Mth::Quat);\r\n\t\t\r\n//\t\tMth::Vector theVector = *((Mth::Vector*)p_data);\r\n\t\tMth::Vector theVector;\r\n\t\ttheVector[X] = *((float*)(p_data));\r\n\t\ttheVector[Y] = *((float*)(p_data+4));\r\n\t\ttheVector[Z] = *((float*)(p_data+8));\r\n\t\ttheVector[W] = *((float*)(p_data+12));\r\n\t\tp_data += sizeof(Mth::Vector);\r\n\r\n\t\tMth::Matrix theNeutralPoseMatrix;\r\n\r\n\t\t// gets the skeleton into the model's space\r\n\t\tMth::QuatVecToMatrix( &theQuat, &theVector, &theNeutralPoseMatrix );\r\n\r\n\t\tif ( i != 0 )\r\n\t\t{\r\n\t\t\tMth::Matrix neutral_parent_matrix = *(mp_inverseNeutralPoseMatrices + GetIndex(GetParentName(i)));\r\n\r\n\t\t\t// GJ:  shouldn't this already be inverted from\r\n\t\t\t// previous iterations of the for-loop?\r\n\t\t\tneutral_parent_matrix.InvertUniform();\r\n\r\n\t\t\ttheNeutralPoseMatrix *= neutral_parent_matrix;\r\n\r\n\t\t\ttheNeutralPoseMatrix[X][W] = 0.0f;\r\n\t\t\ttheNeutralPoseMatrix[Y][W] = 0.0f;\r\n\t\t\ttheNeutralPoseMatrix[Z][W] = 0.0f;\r\n\t\t\ttheNeutralPoseMatrix[W][W] = 1.0f;\r\n\t\t}\r\n\r\n\t\ttheNeutralPoseMatrix.InvertUniform();\r\n\t\t*(mp_inverseNeutralPoseMatrices + i) = theNeutralPoseMatrix;\r\n\t}\r\n\r\n\t// if we get here, then it's successful\r\n\tsuccess = true;\r\n\r\n//ERROR:\r\n    return success;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkeletonData::InitialiseBoneSkipList( const char* p_fileName )\r\n{\r\n\t// Stip leading path information and trailing extensions to obtain the name of the skeleton.\r\n\tchar skeleton_name[128];\r\n\r\n\tchar *p_copy = strrchr( p_fileName, '/' );\r\n\tif( p_copy == NULL )\r\n\t\tp_copy = strrchr( p_fileName, '\\\\' );\r\n\r\n\tif( p_copy )\r\n\t{\r\n\t\t++p_copy;\r\n\t\tstrcpy( skeleton_name, p_copy );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tstrcpy( skeleton_name, p_fileName );\r\n\t}\r\n\r\n\tp_copy = strchr( skeleton_name, '.' );\r\n\tif( p_copy )\r\n\t{\r\n\t\t*p_copy = '\\0';\r\n\t}\r\n\r\n\t// First, get a pointer to the script global SkipBoneLODInfo.\r\n\tScript::CStruct *p_all_lod_info = Script::GetStructure( CRCD( 0x7da53781, \"BoneSkipLODInfo\" ));\r\n\tif( p_all_lod_info )\r\n\t{\r\n\t\tScript::CArray *p_skeleton_lod_info = NULL;\r\n\t\tp_all_lod_info->GetArray( skeleton_name, &p_skeleton_lod_info );\r\n\r\n\t\t// No requirement that there *must* be SkipBoneLODInfo for a given skeleton.\r\n\t\tif( p_skeleton_lod_info )\r\n\t\t{\r\n\t\t\t// Now run through each element of the array. Each element is a structure.\r\n\t\t\tuint32 array_size = p_skeleton_lod_info->GetSize();\r\n\t\t\tfor( uint32 lod_level = 0; lod_level < array_size; ++lod_level )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct *p_element = p_skeleton_lod_info->GetStructure( lod_level );\r\n\t\r\n\t\t\t\t// Obtain the distance, required, below which this LOD is active.\r\n\t\t\t\tfloat lod_distance = 0.0f;\r\n\t\t\t\tif( p_element->GetFloat( \"LODDistance\", &lod_distance ))\r\n\t\t\t\t{\r\n\t\t\t\t\t// Convert to inches.\r\n\t\t\t\t\tlod_distance = FEET_TO_INCHES( lod_distance );\r\n\r\n\t\t\t\t\t// Store the square of the distance (in inches).\r\n\t\t\t\t\t// Special case - if this is the last lod level, set the distance such that it will always be active.\r\n\t\t\t\t\tif( lod_level == ( array_size - 1 ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_skipLODDistances[lod_level] = MAX_LOD_DISTANCE;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_skipLODDistances[lod_level] = lod_distance * lod_distance;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( 0, ( \"Missing LODDistance field for LOD level %d in skeleton %s\\n\", lod_level, skeleton_name ));\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tScript::CArray *p_skip_bones_array = NULL;\r\n\t\t\t\tif( p_element->GetArray( \"SkipBones\", &p_skip_bones_array ))\r\n\t\t\t\t{\r\n\t\t\t\t\t// There are bones to be skipped for this entry.\r\n\t\t\t\t\tuint32 size = p_skip_bones_array->GetSize();\r\n\t\t\t\t\tfor( uint32 bone = 0; bone < size; ++bone )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Get the checksum of the bone name.\r\n\t\t\t\t\t\tuint32 bone_checksum = p_skip_bones_array->GetChecksum( bone );\r\n\r\n\t\t\t\t\t\t// Obtain the bone index from this bone checksum.\r\n\t\t\t\t\t\tuint32 bone_index\t\t\t= GetIndex( bone_checksum );\r\n\r\n\t\t\t\t\t\t// Set the bitfield flag for this bone.\r\n\t\t\t\t\t\tm_skipLODTable[bone_index]\t= 0xFFFFFFFF & ~(( 1 << lod_level ) - 1 );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkeletonData::Load(const char* p_fileName, bool assertOnFail)\r\n{\r\n\t// new load of platform-specific SKE files...\r\n\tbool success = false;\r\n\tint file_size;\r\n\tuint32* p_fileBuffer = NULL;\r\n\r\n\t// open the file as a stream\r\n\tvoid* pStream = File::Open( p_fileName, \"rb\" );\r\n\t\r\n    // make sure the file is valid\r\n\tif ( !pStream )\r\n\t{\r\n\t\tDbg_MsgAssert( assertOnFail, (\"Load of %s failed - file not found?\", p_fileName) );\r\n\t\tgoto ERROR;\r\n\t}\r\n\r\n\tfile_size = File::GetFileSize(pStream);\r\n\tDbg_MsgAssert( file_size, (\"Skeleton file %s size is 0\", p_fileName) );\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tp_fileBuffer = (uint32*)Mem::Malloc( file_size );\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\tif ( !File::Read( p_fileBuffer, file_size, 1, pStream ) )\r\n\t{\r\n\t\tDbg_MsgAssert( assertOnFail, (\"Load of %s failed - read failed?\", p_fileName) );\r\n\t\tgoto ERROR;\r\n\t}\r\n\r\n\tif ( !Load( p_fileBuffer, file_size, assertOnFail ) )\r\n\t{\r\n\t\tDbg_MsgAssert( assertOnFail, (\"Load of %s failed - parse failed?\", p_fileName) );\r\n\t\tgoto ERROR;\r\n\t}\r\n\r\n\t// GJ:  THPS4 patch for weird head scaling on female peds...\r\n\tif ( strstr( p_fileName, \"ped_f\" ) )\r\n\t{\r\n\t\tm_flags |= 0x1;\r\n\t}\r\n\r\n\t// if we get here, then it's successful\r\n\tsuccess = true;\r\n\r\nERROR:\r\n\tif ( p_fileBuffer )\r\n\t{\r\n\t\tMem::Free( p_fileBuffer );\r\n\t}\r\n\tFile::Close(pStream);    \r\n\r\n\tInitialiseBoneSkipList( p_fileName );\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CSkeletonData::GetNumBones() const\r\n{\r\n    return m_numBones;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CSkeletonData::GetBoneName( int index )\r\n{\r\n    Dbg_Assert( index >= 0 && index < m_numBones );\r\n    \r\n    return m_boneNameTable[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CSkeletonData::GetParentName( int index )\r\n{\r\n    Dbg_Assert( index >= 0 && index < m_numBones );\r\n    \r\n    return m_parentNameTable[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CSkeletonData::GetParentIndex( int index )\r\n{\r\n    Dbg_Assert( index >= 0 && index < m_numBones );\r\n    \r\n    return GetIndex( m_parentNameTable[index] );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CSkeletonData::GetFlipName( int index )\r\n{\r\n    Dbg_Assert( index >= 0 && index < m_numBones );\r\n    \r\n    return m_flipNameTable[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CSkeletonData::GetIndex( uint32 boneName )\r\n{\r\n    for ( int i = 0; i < m_numBones; i++ )\r\n    {\r\n        if ( boneName == m_boneNameTable[i] )\r\n            return i;\r\n    }\r\n\r\n    // not found\r\n    Dbg_Assert( 0 );\r\n    return 0;\r\n}\r\n\r\n\r\n\r\n#if 0\r\n// The following functions have been deprecated...\r\n// they were formerly used to find the correct\r\n// default SKA file in order to build the neutral\r\n// pose matrices.  Now, however, the neutral pose\r\n// is stored inside the SKE file\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkeletonData::SetAnimScriptName( uint32 anim_script_name )\r\n{\r\n\tm_animScriptName = anim_script_name;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CSkeletonData::GetAnimScriptName() const\r\n{\r\n\treturn m_animScriptName;\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Matrix* CSkeletonData::GetInverseNeutralPoseMatrices()\r\n{\r\n\treturn mp_inverseNeutralPoseMatrices;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n\r\n// DEBUG FUNCTIONS\r\n\r\n#if 0\r\n\r\n\t#if 0\r\n\t\t// draw the bone between the origin of that bone, and its parent\r\n\t\ttempMatrix0 = (*p_currentBone->mp_parentMatrix) * (*pRootMatrix);\r\n\t\ttempMatrix1 = ( ( mp_matrices + i ) ) * (*pRootMatrix); \r\n\t\tAddDebugBone( tempMatrix0.GetPos(), tempMatrix1.GetPos(), r, g, b );\t\r\n\t#endif\r\n\r\n\t#if 0\r\n\t\t// * test neutral-in-skater-space pose *\r\n\t\ttempMatrix0 = *p_currentBone->mp_invertedNeutralParentMatrix;\r\n\t\ttempMatrix0.InvertUniform();\r\n\t\ttempMatrix0\t= tempMatrix0 * (*pRootMatrix); \r\n\t\t\t\r\n\t\ttempMatrix1 = p_currentBone->m_invertedNeutralMatrix;\r\n\t\ttempMatrix1.InvertUniform();\r\n\t\ttempMatrix1 = tempMatrix1 * (*pRootMatrix);\r\n\t\t\t\r\n\t\tAddDebugBone( tempMatrix0.GetPos(), tempMatrix1.GetPos(), r, g, b );\t\r\n\t#endif\r\n\t\r\n\t#if 0\r\n\t\t// * test inverted-to-neutral *\r\n\t\tMth::Matrix boneMatrix;\r\n\t\tboneMatrix = *( ( mp_matrices + i ) );\r\n\t\ttempMatrix0 = tempMatrix1;\r\n\t\ttempMatrix1 = p_currentBone->m_neutralMatrix * boneMatrix;\r\n\t\ttempMatrix1 *= (*pRootMatrix);\r\n\t\tAddDebugBone( tempMatrix0.GetPos(), tempMatrix1.GetPos(), r, g, b );\r\n\t#endif\r\n\r\n#endif\r\n\r\n\r\n#if 0\r\n\t// Programmatic jaw test\r\n\tif ( p_currentBone->m_name == Script::GenerateCRC(\"jaw\") )\r\n\t{\r\n\t\tstatic int jaw_rotation = 0;\r\n\t\tjaw_rotation++;\r\n\t\tp_currentMatrix->RotateLocal(Mth::Vector( Mth::DegToRad((float)(jaw_rotation)/10.0f), 0.0f, 0.0f));\r\n\t\tif (jaw_rotation>60)\r\n\t\t{\r\n\t\t\tjaw_rotation=0;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n#if 0\r\n\t// This scales the item, with respect to the model's\r\n\t// origin.  There are some neat looking effects\r\n\t// that can be done with this, such as a gorilla man\r\n\t// with a over-sized upper body, but makes the lip\r\n\t// tricks look incorrect.\r\n\tif ( Script::GetInt( \"ScalingTest\", false ) )\r\n\t{\r\n\t\t// override the scale if the GorillaMode is set...\r\n\t\tScript::CArray* pArray = Script::GetArray( \"master_scaling_table\" );\r\n\t\tif ( pArray && i < (int)pArray->GetSize() )\r\n\t\t{\r\n\t\t\tScript::CVector* pVector = pArray->GetVector(i);\r\n\t\t\tMth::Vector theVector;\r\n\t\t\tconst float weight_scale=Script::GetFloat(\"weight_scale\");\r\n\t\t\ttheVector[X] = 1.0f + (pVector->mX-1.0f) * weight_scale;\r\n\t\t\ttheVector[Y] = 1.0f + (pVector->mY-1.0f) * weight_scale;\r\n\t\t\ttheVector[Z] = 1.0f + (pVector->mZ-1.0f) * weight_scale;\r\n\t\t\tp_currentMatrix->Scale(theVector);\r\n\t\t}\r\n\t}\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/Skeleton.h",
    "content": "//****************************************************************************\r\n//* MODULE:\t\t\tGfx\r\n//* FILENAME:\t\tSkeleton.h\r\n//* OWNER:\t\t\tGary Jesdanun\r\n//* CREATION DATE:\t11/15/2001\r\n//****************************************************************************\r\n\r\n#ifndef __GFX_SKELETON_H\r\n#define __GFX_SKELETON_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tIncludes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gfx/pose.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDefines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mth\r\n{\r\n\tclass Matrix;\r\n\tclass Quat;\r\n\tclass Vector;\r\n}\r\n\t\t\t\t\t\t\t\t\t\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n};\r\n\r\nnamespace Gfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\tclass CBone;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n    \r\nclass CSkeletonData\t: public Spt::Class\r\n{\r\npublic:\r\n\r\n\tstatic const int\tBONE_SKIP_LOD_BITS = 32;\r\n\r\n\t\t\t\t\tCSkeletonData();\r\n\tvirtual\t\t\t~CSkeletonData();\r\n\tbool\t\t\tLoad( const char* p_fileName, bool assertOnFail );\r\n\tbool\t\t\tLoad( uint32* p_data, int data_size, bool assertOnFail );\r\n\tvoid\t\t\tInitialiseBoneSkipList( const char* p_fileName );\r\n//\tvoid\t\t\tSetAnimScriptName( uint32 animScriptName );\r\n\r\npublic:\r\n\tint\t\t\t\tGetNumBones() const;\r\n\tuint32\t\t\tGetBoneName( int index );\r\n\tuint32\t\t\tGetParentName( int index );\r\n\tuint32\t\t\tGetParentIndex( int index );\r\n\tuint32\t\t\tGetFlipName( int index );\r\n\tuint32\t\t\tGetIndex( uint32 boneName );\r\n//\tuint32\t\t\tGetAnimScriptName() const;\r\n\tuint32*\t\t\tGetBoneSkipList( void )\t\t\t\t{ return m_skipLODTable; }\r\n\tfloat\t\t\tGetBoneSkipDistance( uint32 lod )\t{ return m_skipLODDistances[lod]; }\r\n\r\n\tMth::Matrix*\tGetInverseNeutralPoseMatrices();\r\n\r\nprotected:\r\n\tint\t\t\t\tm_numBones;\r\n\tuint32\t\t\tm_boneNameTable[vMAX_BONES];\r\n\tuint32\t\t\tm_parentNameTable[vMAX_BONES];\r\n\tuint32\t\t\tm_flipNameTable[vMAX_BONES];\r\n\tuint32\t\t\tm_skipLODTable[vMAX_BONES];\t\t\t\t// Each uint32 for a specific bone provides 32 levels of skip information.\r\n\tfloat\t\t\tm_skipLODDistances[BONE_SKIP_LOD_BITS];\r\n\tuint32\t\t\tm_animScriptName;\r\n\tMth::Matrix* \tmp_inverseNeutralPoseMatrices;\r\n\t\r\npublic:\r\n\tint\t\t\t\tm_flags;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass CSkeleton\r\n{\r\npublic:\r\n\tCSkeleton( CSkeletonData* pSkeletonData );\r\n\t~CSkeleton();\r\n\r\npublic:\r\n\tint\t\t\t\t\t\tGetNumBones( void ) const;\r\n\tbool\t\t\t\t\tApplyBoneScale( Script::CStruct* pBodyShapeStructure );\r\n\tvoid\t\t\t\t\tResetScale( void );\r\n\t\r\npublic:\r\n\tvoid \t\t\t\t\tUpdate( CPose* pPose );\r\n\tvoid\t\t\t\t\tUpdate( Mth::Quat* pQuat, Mth::Vector* pTrans );\r\n\tvoid\t\t\t\t\tDisplay( Mth::Matrix* pMatrix, float r, float g, float b );\r\n\t\r\npublic:\r\n\tMth::Matrix*\t\t\tGetMatrices();\r\n\tMth::Matrix\t\t\t\tGetNeutralMatrix( int boneIndex );\r\n\tbool\t\t\t\t\tGetBoneMatrix( uint32 boneId, Mth::Matrix* pMatrix );\r\n\tbool\t\t\t\t\tGetBonePosition( uint32 boneId, Mth::Vector* pVector );\r\n\tint\t\t\t\t\t\tGetBoneIndexById( uint32 boneId );\r\n\tint\t\t\t\t\t\tGetFlipIndex( int boneIndex );\r\n//\tvoid\t\t\t\t\tGetSkipList( int* pSkipList );\r\n\tuint32*\t\t\t\t\tGetBoneSkipList( void );\r\n\tuint32\t\t\t\t\tGetBoneSkipIndex( void )\t\t{ return m_skipIndex; }\r\n\tvoid\t\t\t\t\tSetBoneSkipDistance( float dist );\r\n\tvoid\t\t\t\t\tSetMaxBoneSkipLOD( uint32 max )\t{ m_maxBoneSkipLOD = max; }\r\n\r\npublic:\r\n\t// The following should be moved to the CAnimationComponent class\t\r\n//\tbool\t\t\t\t\tGetBoneRotationByIndex( int boneIndex );\r\n\r\npublic:\r\n\tbool\t\t\t\t\tSetBoneActive( uint32 boneId, bool active );\r\n\tbool\t\t\t\t\tSetBoneScale( uint32 boneId, const Mth::Vector& theBoneScale, bool isLocalScale );\r\n\tbool\t\t\t\t\tGetBoneScale( uint32 boneId, Mth::Vector* pBoneScaleVector );\r\n\tvoid\t\t\t\t\tCopyBoneScale( Gfx::CSkeleton* pSourceSkeleton );\r\n\tvoid\t\t\t\t\tSetNeutralPose( Mth::Quat* pQuat, Mth::Vector* pTrans );\r\n\tCSkeletonData*\t\t\tGetSkeletonData() { return mp_skeletonData; }\r\n\r\nprotected:\r\n\tCBone*\t\t\t\t\tget_bone_by_id( uint32 boneId );\r\n\tvoid\t\t\t\t\tupdate_matrices();\r\n\r\nprotected:\r\n\tuint32\t\t\t\t\tm_flags;\r\n\tMth::Matrix*\t\t\tmp_matrices;\r\n    CSkeletonData*\t\t\tmp_skeletonData;\r\n\tuint32\t\t\t\t\tm_skipIndex;\r\n\tuint32\t\t\t\t\tm_maxBoneSkipLOD;\r\n\r\n\t// for non-procedural bone anims\r\n\tint\t\t\t\t\t\tm_numBones;\r\n\tCBone*\t\t\t\t\tmp_bones;\r\n\t\r\nprotected:\r\n\tvoid\t\t\t\t\tinitialize_hierarchy( CSkeletonData* pSkeletonData );\r\n\tvoid\t\t\t\t\tinitialize_flip_matrices( CSkeletonData* pSkeletonData );\r\n\tvoid\t\t\t\t\tinitialize_bone_names( CSkeletonData* pSkeletonData );\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n#endif\t// __GFX_SKELETON_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/BillboardScreenAlignedVS.vsh",
    "content": "xvs.1.1\r\n\r\n; Constants:\r\n;  c0 - c3\t\tWVP Matrix (WORLD*VIEW*PROJECTION)\r\n;  c4\t\t\tScreen right vector\r\n;  c5\t\t\tScreen up vector\r\n;  c6\t\t\tScreen at vector\r\n\r\n; In:\r\n;   v0 - Position\t\t(actually the position of the pivot point)\r\n;\tv1 - Normal\t\t\t(actually the position of the point relative to the pivot)\r\n;   v2 - Vertex color\r\n;   v3 - TexCoord0\r\n;   v4 - TexCoord1\r\n;   v5 - TexCoord2\r\n;   v6 - TexCoord3\r\n\r\n; Out:\r\n;   oPos - Position\r\n;   oTn - TextureCoords\r\n\r\n;------------------------------------------------------------------------------\r\n; Pivot relative position -> world relative position, plus copy texture coordinates\r\n; (interleaving these helps prevent stalls)\r\n;------------------------------------------------------------------------------\r\nmul\tr0.xyz,\tv1.x, c4\r\nmov oT0,\tv3\r\nmad r0.xyz, v1.y, c5, r0\r\nmov oT1,\tv4\r\nmad r0.xyz,\tv1.z, c6, r0\r\nmov oT2,\tv5\r\nadd r0.xyz,\tv0, r0\r\nmov oT3,\tv6\r\nsge r0.w,\tc0.x, c0.x\t\t; Set r0.w = 1.0\r\n\r\n;------------------------------------------------------------------------------\r\n; Vertex color\r\n;------------------------------------------------------------------------------\r\nmov oD0, v2\r\n\r\n;------------------------------------------------------------------------------\r\n; Vertex->screen transform\r\n;------------------------------------------------------------------------------\r\ndp4 oPos.x, r0, c0\r\ndp4 oPos.y, r0, c1\r\ndp4 oPos.z, r0, c2\r\ndp4 oPos.w, r0, c3\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\nmov\toFog.x, -r12.w\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/ParticleFlatVS.vsh",
    "content": "xvs.1.1\r\n\r\n; Constants:\r\n;  c0 - c3\t\tWVP Matrix (WORLD*VIEW*PROJECTION)\r\n;  c4\t\t\tScreen right vector\r\n;  c5\t\t\tScreen up vector\r\n;  c8-c11\t\tVertex texture coordinates (for index0 through index3)\r\n;  c12-c15\t\tVertex width and height multipliers (for index0 through index3)\r\n\r\n;  c16\t\t\tParticle position (xyz) (set in the data stream per particle)\r\n;  c17\t\t\tParticle start width and height (xy) and end width and height (zw) (set in the data stream per particle)\r\n;  c18\t\t\tSize interpolator (x) and color interpolator (y) (set in the data stream per particle)\r\n\r\n\r\n; In:\r\n;   v0 - Vertex start color\r\n;   v1 - Vertex end color\r\n;   v2 - Index\r\n\r\n; Out:\r\n;   oPos\t- Position\r\n;   oD0\t\t- Vertex color\r\n;   oT0\t\t- TextureCoords\r\n\r\n; Get the index of this vert\r\nmov\ta0.x, v2.x\r\n\r\n; Move the width and height multipliers into a general register.\r\nmov r1, c[12 + a0.x]\r\n\r\n; Calculate the interpolated width and height of the particle.\r\nmov r2, c17.zw\t\t// r2 = ( c17.z, c17.w, c17.w, c17.w )\r\nsub r2, r2, c17.xy\t// r2 = ( c17.z - c17.x, c17.w - c17.y, ...)\r\nmul r2, r2, c18.x\r\nadd r2, r2, c17.xy\r\n\r\n; Multiply by the width and height of this particle.\r\nmul r1, r1, r2\r\n\r\n; Add width and height multiples of the screen right and up vectors\r\nmul r0.xyz, r1.x, c4\r\nmad r0.xyz, r1.y, c5, r0\r\n\r\n; Add particle position\r\nadd r0.xyz, c16, r0\r\nsge r0.w,\tr1.x, r1.x\t\t; r0.w = 1.0\r\n\r\n; Vertex->screen transform\r\ndp4 oPos.x, r0, c0\r\ndp4 oPos.y, r0, c1\r\ndp4 oPos.z, r0, c2\r\ndp4 oPos.w, r0, c3\r\n\r\n; Calculate the interpolated vertex color\r\nmov r2, v1\r\nsub r2, r2, v0\r\nmad r2, r2, c18.y, v0\r\n\r\n; Vertex color\r\nmov oD0, r2\r\n\r\n; Deal with fog value (r12 shadows oPos)...\r\nmov\toFog.x, -r12.w\r\n\r\n; Move texture coordinate in based on index\r\nmov oT0, c[8 + a0.x]\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/ParticleNewFlatPointSpriteVS.vsh",
    "content": "xvs.1.1\r\n\r\n; Constants:\r\n;  c0 - c3\t\tWVP Matrix (WORLD*VIEW*PROJECTION)\r\n;  c18-c20\t\tParticle s0, s1 and s2 vectors\r\n;  c21-c23\t\tParticle p0, p1 and p2 vectors\r\n;  c24\t\t\tEye position (x,y,z) and viewport height (w)\r\n\r\n; In:\r\n;   v0 - 4-element random vector\r\n;   v1 - Time (x) and color interpolator (y)\r\n;   v2 - Vertex start color\r\n;   v3 - Vertex end color\r\n\r\n; Out:\r\n;   oPos\t- Position\r\n;\toPts\t- Point sprite size\r\n;   oD0\t\t- Vertex color\r\n\r\n\r\n; Calculate the square of the time interpolator.\r\nmul r2.x, v1.x, v1.x\r\n\r\n; Calculate the position of the particle, from pos = ( m_p0 + ( t * m_p1 ) + (( t * t ) * m_p2 )) + ( m_s0 + ( t * m_s1 ) + (( t * t ) * m_s2 )).Scale( r );\r\nmov r0, c21\t\t\t\t\t; pos = m_p0\r\nmad r0, c22, v1.x, r0\t\t; pos = m_p0 + ( t * m_p1 )\r\nmad r0, c23, r2.x, r0\t\t; pos = m_p0 + ( t * m_p1 ) + (( t * t ) * m_p2 )\r\n\r\nmov r1, c18\t\t\t\t\t; tmp = ( m_s0 )\r\nmad r1, c19, v1.x, r1\t\t; tmp = ( m_s0 + ( t * m_s1 ))\r\nmad r1, c20, r2.x, r1\t\t; tmp = ( m_s0 + ( t * m_s1 ) + (( t * t ) * m_s2 ))\r\n\r\nmad r0, r1, v0, r0\t\t\t; pos = ( m_p0 + ( t * m_p1 ) + (( t * t ) * m_p2 )) + ( m_s0 + ( t * m_s1 ) + (( t * t ) * m_s2 )).Scale( r );\r\n\r\n; Calculate the distance from the camera to the particle.\r\nsub r4, c24, r0\r\ndp3\tr4.x, r4, r4\r\nrsq r4.x, r4.x\r\nmul r4.x, r4.x, r0.w\r\n\r\n; Now set position w to 1.0\r\nsge r0.w, r0.x, r0.x\r\n\r\n; Vertex->screen transform\r\ndp4 oPos.x, r0, c0\r\ndp4 oPos.y, r0, c1\r\ndp4 oPos.z, r0, c2\r\ndp4 oPos.w, r0, c3\r\n\r\n; Save off the size of the particle\r\nmul oPts.x, r4.x, c24.w\r\n\r\n; Calculate the interpolated vertex color\r\nmov r2, v2\t\t\t\t\t; r2 = start_col\r\nsub r3, v3, r2\t\t\t\t; r3 = end_col - start_col\r\nmad oD0, r3, v1.y, r2\t\t; r3 = start_col + (( end col - start_col ) * color_interpolator )\r\n\r\n; Deal with fog value (r12 shadows oPos)...\r\nmov\toFog.x, -r12.w\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/ParticleNewFlatVS.vsh",
    "content": "xvs.1.1\r\n\r\n; Constants:\r\n;  c0 - c3\t\tWVP Matrix (WORLD*VIEW*PROJECTION)\r\n;  c4\t\t\tScreen right vector\r\n;  c5\t\t\tScreen up vector\r\n;  c8-c11\t\tVertex texture coordinates (for index0 through index3)\r\n;  c12-c15\t\tVertex width and height multipliers (for index0 through index3)\r\n\r\n;  c16\t\t\tParticle random seed vector\r\n;  c17\t\t\tParticle time interpolator (c17.x), color interpolator (c17.y)\r\n\r\n;  c18-c20\t\tParticle s0, s1 and s2 vectors\r\n;  c21-c23\t\tParticle p0, p1 and p2 vectors\r\n\r\n; In:\r\n;   v0 - Vertex start color\r\n;   v1 - Vertex end color\r\n;   v2 - Index\r\n\r\n; Out:\r\n;   oPos\t- Position\r\n;   oD0\t\t- Vertex color\r\n;   oT0\t\t- TextureCoords\r\n\r\n; Get the index of this vert\r\nmov\ta0.x, v2.x\r\n\r\n; Move the time interpolator into a general register, and calculate the square.\r\nmov r4, c17\r\nmul r4.y, r4.x, r4.x\r\n\r\n; Move the width and height multipliers into a general register.\r\nmov r3, c[12 + a0.x]\r\n\r\n; Calculate the position of the particle, from pos = ( m_p0 + ( t * m_p1 ) + (( t * t ) * m_p2 )) + ( m_s0 + ( t * m_s1 ) + (( t * t ) * m_s2 )).Scale( r );\r\nmov r0, c21\t\t\t\t\t; pos = m_p0\r\nmad r0, c22, r4.x, r0\t\t; pos = m_p0 + ( t * m_p1 )\r\nmad r0, c23, r4.y, r0\t\t; pos = m_p0 + ( t * m_p1 ) + (( t * t ) * m_p2 )\r\n\r\nmov r1, c18\t\t\t\t\t; tmp = ( m_s0 )\r\nmad r1, c19, r4.x, r1\t\t; tmp = ( m_s0 + ( t * m_s1 ))\r\nmad r1, c20, r4.y, r1\t\t; tmp = ( m_s0 + ( t * m_s1 ) + (( t * t ) * m_s2 ))\r\n\r\nmad r0, r1, c16, r0\t\t\t; pos = ( m_p0 + ( t * m_p1 ) + (( t * t ) * m_p2 )) + ( m_s0 + ( t * m_s1 ) + (( t * t ) * m_s2 )).Scale( r );\r\n\r\n; Calculate the interpolated width and height of the particle.\r\nmov r2, r0.w\r\n\r\n; Now set position w to 1.0\r\nsge r0.w, r0.x, r0.x\r\n\r\n; Multiply width and height by the width and height multipliers of this vertex index\r\nmul r2.xy, r2.xy, r3.xy\r\n\r\n; Add width and height multiples of the screen right and up vectors to the position.\r\nmad r0.xyz, r2.x, c4, r0\r\nmad r0.xyz, r2.y, c5, r0\r\n\r\n; Vertex->screen transform\r\ndp4 oPos.x, r0, c0\r\ndp4 oPos.y, r0, c1\r\ndp4 oPos.z, r0, c2\r\ndp4 oPos.w, r0, c3\r\n\r\n; Calculate the interpolated vertex color\r\nmov r2, v1\r\nsub r2, r2, v0\r\nmad oD0, r2, c17.y, v0\r\n\r\n; Deal with fog value (r12 shadows oPos)...\r\nmov\toFog.x, -r12.w\r\n\r\n; Move texture coordinate in based on index\r\nmov oT0, c[8 + a0.x]\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShader0.psh",
    "content": "xps.1.1\r\n\r\ntex t0\r\nmul\t\tt0.rgb,t0.rgb,c0.rgb\t; Modulate texture color0 with material color0\r\nmul_x4\tr0.rgb,v0.rgb,t0.rgb\t; Modulate (x4) resultant color with vertex color\r\n+mul_x2\tr0.a,v0.a,t0.a\t\t\t; Modulate (x2) result alpha with vertex alpha\r\n\r\nxfc prod, fog.rgb, sum, zero, 1 - fog.a, c4, r0.a\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShader0IVA.psh",
    "content": "xps.1.1\r\n\r\ntex t0\r\nmul\t\tt0.rgb,t0.rgb,c0.rgb\t; Modulate texture color0 with material color0\r\nmul_x4\tr0.rgb,v0.rgb,t0.rgb\t; Modulate (x4) resultant color with vertex color\r\n+mul_x2\tr0.a,c4.a,t0.a\t\t\t; Modulate (x2) result alpha with constant alpha\r\n\r\nxfc prod, fog.rgb, sum, zero, 1 - fog.a, c4, r0.a\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShader1.psh",
    "content": "xps.1.1\r\nmul_x2\tv0.rgb,v0.rgb,c0.rgb\t\t\t\t\t\t; Modulate vertex color0 with material color0\r\nmov\t\tr0,v0\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShader2.psh",
    "content": "xps.1.1\r\ntex t0\r\nmov r0,t0\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShader3.psh",
    "content": "xps.1.1\r\nmov r0,c0\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShader4.psh",
    "content": "xps.1.1\r\ntex t0\r\nmul_x2\tr0,v0,t0\t\t\t\t; Modulate (x2) texture color with vertex color.\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShader5.psh",
    "content": "xps.1.1\r\nmov\tr0,v0\t\t; Just use vertex color.\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShaderBrighten.psh",
    "content": "xps.1.1\r\n\r\ntex t0\r\n;mul\tt0.rgb,t0.rgb,c0.rgb\t; Modulate texture color0 with material color0\r\n;mul_x4\tr0.rgb,v0.rgb,t0.rgb\t; Modulate (x4) resultant color with vertex color\r\n;mul_x2\tr0.a,v0.a,t0.a\t\t\t; Modulate (x2) result alpha with vertex alpha\r\n\r\nmul_x2\tr0,v0.a,t0.a\t\t\t; Modulate (x2) result alpha with vertex alpha and copy into all 4 channels\r\n\r\nxfc prod, fog.rgb, sum, zero, 1 - fog.a, c4, r0.a\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShaderBrightenIVA.psh",
    "content": "xps.1.1\r\n\r\ntex t0\r\n;mul\t\tt0.rgb,t0.rgb,c0.rgb\t; Modulate texture color0 with material color0\r\n;mul_x4\t\tr0.rgb,v0.rgb,t0.rgb\t; Modulate (x4) resultant color with vertex color\r\n;+mul_x2\tr0.a,c4.a,t0.a\t\t\t; Modulate (x2) result alpha with constant alpha\r\n\r\nmul_x2\t\tr0,c4.a,t0.a\t\t\t; Modulate (x2) result alpha with constant alpha and copy into all 4 channels\r\n\r\nxfc prod, fog.rgb, sum, zero, 1 - fog.a, c4, r0.a\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShaderBumpWater.psh",
    "content": "xps.1.1\r\n\r\ntex\t\tt0\r\ntexbem\tt1, t0\r\nmul\t\tt1.rgb,t1.rgb,c0.rgb\t; Modulate texture1 color with material color0\r\nmul_x4\tr0.rgb,v0.rgb,t1.rgb\t; Modulate (x4) resultant color with vertex color\r\n+mul_x2\tr0.a,v0.a,t1.a\t\t\t; Modulate (x2) result alpha with vertex alpha\r\n\r\nxfc prod, fog.rgb, sum, zero, 1 - fog.a, c4, r0.a\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShaderFocusBlur.psh",
    "content": ";------------------------------------------------------------------------------\r\n; 4-tap filtering\r\n; Copyright (C) 2001 Microsoft Corporation\r\n; All rights reserved.\r\n;------------------------------------------------------------------------------\r\nxps.1.1\r\n\r\n; default filter is box filter, but this is easily overwritten using SetPixelShaderConstant\r\n\r\n; When setting a pixel shader constant, we must check to see if the\r\n; filter coefficient is negative, in which case we set the constant as a positive\r\n; number and negate the constant in the expression below.\r\ndef c0, 0.25f, 0.25f, 0.25f, 0.25f\r\ndef c1, 0.25f, 0.25f, 0.25f, 0.25f \r\ndef c2, 0.25f, 0.25f, 0.25f, 0.25f \r\ndef c3, 0.25f, 0.25f, 0.25f, 0.25f \r\n\r\n; source textures\r\ntex t0\r\ntex t1\r\ntex t2\r\ntex t3\r\n\r\n; simple way\r\n; mul r0, c0, t0\r\n; mad r0, c1, t1, r0\r\n; mad r0, c2, t2, r0\r\n; mad r0, c3, t3, r0\r\n\r\n; This has better precision (assuming the xmma_x2 intermediates don't overflow):\r\nxmma_x2 discard, discard, r0, c0, t0, c1, t1\t; 2 * (c0 * t0 + c1 * t1)\r\nxmma_x2 discard, discard, r1, c2, t2, c3, t3\t; 2 * (c2 * t2 + c3 * t3)\r\nadd_d2 r0, r0, r1\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShaderFocusIntegrate.psh",
    "content": ";------------------------------------------------------------------------------\r\n; Depth of field by choosing a range of z values and using that to select\r\n; a blurred version of the original image.\r\n; \r\n; Copyright (C) 2001 Microsoft Corporation\r\n; All rights reserved.\r\n;------------------------------------------------------------------------------\r\nxps.1.1\r\n\r\n; override with SetPixelShaderConstant\r\ndef c0, 0.f, 0.f, 0.f, 0.f      ; offset\r\ndef c1, 0.f, 0.f, 1.f, 0.f      ; slope x1\r\ndef c2, 0.f, 0.f, 0.f, 0.f      ; slope x4\r\ndef c3, 0.f, 0.f, 0.f, 1.f      ; slope x16\r\ndef c4, 1.f, 1.f, 1.f, 0.498039215      ; 0x7f\r\n\r\n; source textures\r\ntex t0                  ; z-buffer texture\r\ntex t1                  ; pre-blurred texture\r\n\r\n; get the range of active z values\r\nsub    r0, t0, c0               ; offset\r\nmul_x4 r1, c3, r0               ; scale x16\r\nmad_x4 r1, c2, r0, r1           ; scale x4\r\nmad    r1, c1, r0, r1           ; scale x1\r\nsub r0.a, r1.a, c4.a            ; subtract 0x7f from r1.a\r\ncnd r0.a, r0.a, zero.a, r1.b    ; keep blue only if r1.a is not 0xff\r\nadd r1.a, r1.a, r0.a            ; add alpha + blue, the desired range is now mapped to [0,1]\r\nmul r1.a, r1_bx2.a, r1_bx2.a    ; convert to -1,1 range and square to get parabola\r\n\r\n; modulate pre-blurred texture by depth range\r\nxfc r1.a, t1, zero, zero, zero, zero, r1.a\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShaderFocusLookupIntegrate.psh",
    "content": ";------------------------------------------------------------------------------\r\n; FocusBlur by choosing a range of z values and using that to select\r\n; a blurred version of the original image.\r\n; \r\n; Copyright (C) 2001 Microsoft Corporation\r\n; All rights reserved.\r\n;------------------------------------------------------------------------------\r\nxps.1.1\r\n\r\ndef c0, 0.5f, 0.5f, 0.5f, 0.5f\t\t; blur value\r\n\r\n; source textures\r\ntex t0\t\t\t\t; z-buffer texture\r\ntexreg2ar t1, t0\t; lookup-table texture to choose what range of depth to use\r\ntex t2\t\t\t\t; pre-blurred texture, first offset\r\ntex t3\t\t\t\t; pre-blurred texture, second offset\r\n\r\n; blur pre-blurred texture even more\r\nlrp r0, c0, t2, t3\r\n\r\n; modulate by depth range\r\nxfc r0_sat, 1-t1.a, zero, zero, zero, zero, 1-t1.a\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShaderNULL.psh",
    "content": "xps.1.1\r\ndef c7, 1.0f, 1.0f, 1.0f, 1.0f\r\nmov r0, c7\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShaderPointSprite.psh",
    "content": "xps.1.1\r\ntex t3\r\nmul_x2\tr0,v0,t3\t\t\t\t; Modulate (x2) texture color with vertex color.\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/PixelShader_ShadowBuffer.psh",
    "content": "; Shadow buffer pixel shader.\r\n; On entry:\r\n; c0 contains the base percentage of color (even in shadow),\r\n; c1 contains the percentage of color that shadow affects.\r\n\r\nxps.1.1\r\n\r\ntex t3\t\t\t; get shadow from light\r\n\r\nmul r1, c1, t3\t; Use the shadow buffer to affect the shadow portion of the color change\r\nadd r0, c0, r1\t; Add to the base color to get final color\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/ShadowBufferStaticGeomPS.psh",
    "content": ";Shadowbuffer pixel shader.\r\n\r\nxps.1.1\r\n\r\ndef c7, 0.6f, 0.6f, 0.6f, 0.0f\r\n\r\ntex t0\t\t\t\t\t\t\t; Base geometry texture (for alpha modulation).\r\ntex t1\t\t\t\t\t\t\t; Shadow depth buffer texture.\r\n\r\n; White texture (outside of skater) we don't want to draw - so negate blue component into alpha.\r\n; This way the white part of the texture will have zero alpha, the black part will have full alpha.\r\n\r\nmul\t\tr0.a, 1-t1.b, t0.a\t\t; Modulate shadow alpha with base texture alpha (to neatly deal with holes in texture).\r\n+add\tr0.rgb, t1.rgb, c7.rgb\t; Add in the ambient component to brighten up the shadow a bit.\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/ShadowBufferStaticGeomVS.vsh",
    "content": "xvs.1.1\r\n\r\n; Constants:\r\n;  c0  - c3  - WVP Matrix (WORLD*VIEW*PROJECTION)\r\n;  c4  - c7  - WT Matrix (WORLD*TEXTURETRANSFORM)\r\n;  c8  - local space light position.\r\n\r\n; In:\r\n;   v0 - Position\r\n;   v1 - Vertex color\r\n;   v2 - TexCoord0\r\n\r\n; Out:\r\n;   oPos - Position\r\n;   oTn - TextureCoords\r\n\r\n;vertex->screen\r\ndp4 oPos.x, v0, c0\r\ndp4 oPos.y, v0, c1\r\ndp4 oPos.z, v0, c2\r\ndp4 oPos.w, v0, c3\r\n\r\n;diffuse lighting (not necessary for our purposes)\r\n;add\tr0,c8,-v0\r\n;dp3 r0.w,r0,r0\r\n;rsq r1.x,r0.w\r\n;mul r0,r0,r1.x\r\n;dp3 oD0,v1,r0\r\n\r\n;decal texture\r\nmov oT0, v2\r\n\r\n;vertex->shadowbuffer texcoords\r\ndp4 oT1.x, v0, c4\r\ndp4 oT1.y, v0, c5\r\ndp4 oT1.z, v0, c6\r\ndp4 r0.w, v0, c7\r\n\r\n;clamp w (q) to 0\r\nslt r1, c0, c0\r\nmax r0.w, r0.w, r1.w\r\nmov oT1.w, r0.w\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_1Weight.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n    ; Transform position\r\n    dp4\t\tVSTMP_REG_POS_TMP.x, VSIN_REG_POS, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.y, VSIN_REG_POS, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.z, VSIN_REG_POS, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed point by weight\r\n    mul     VSTMP_REG_POS_ACCUM.xyz, VSTMP_REG_POS_TMP.xyz, VSIN_REG_WEIGHTS.x\r\n\r\n    ; Transform normal\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed normal by weight\r\n    mul     VSTMP_REG_NORMAL_ACCUM.xyz, VSTMP_REG_NORMAL_TMP.xyz, VSIN_REG_WEIGHTS.x\r\n\r\n    ; Copy w\r\n    mov\t\tVSTMP_REG_POS_ACCUM.w, VSIN_REG_POS.w\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dp4\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dp4\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dp4\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dp4     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; Transform normal by combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_X\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_Y\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_Z\r\n\r\n;------------------------------------------------------------------------------\r\n; Single directional light + Ambient\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Normalize\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSTMP_REG_NORMAL_TMP\r\n    rsq     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP.w\r\n    mul     VSTMP_REG_NORMAL_TMP.xyz, VSTMP_REG_NORMAL_TMP.xyz, VSTMP_REG_NORMAL_TMP.w\r\n\r\n    ; DP normal & light0 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_TMP.w\r\n\r\n\t; This is where the ambient gets added in.\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\r\n\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light1 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_TMP.w\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light2 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_TMP.w\r\n;    mad     oD0, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_TMP.w, r11\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n\t; Material color attenuation\r\n\tmul\t\toD0, r11, VSCONST_REG_MATERIAL_COLOR\r\n\r\n;------------------------------------------------------------------------------\r\n; Copy texture coordinates\r\n;------------------------------------------------------------------------------\r\n\r\n    mov     oT0, VSIN_REG_TEXCOORDS0\r\n    mov     oT1, VSIN_REG_TEXCOORDS1\r\n    mov     oT2, VSIN_REG_TEXCOORDS2\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_2Weight.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n\t; Transform normal by weighted matrix\r\n    dp3     VSTMP_REG_NORMAL_ACCUM.x, VSIN_REG_NORMAL, VSTMP_REG_MAT0\r\n\tdp3\t\tVSTMP_REG_NORMAL_ACCUM.y, VSIN_REG_NORMAL, VSTMP_REG_MAT1\r\n\tdp3\t\tVSTMP_REG_NORMAL_ACCUM.z, VSIN_REG_NORMAL, VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; Transform normal by combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_X\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_Y\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_Z\r\n\r\n;------------------------------------------------------------------------------\r\n; Single directional light + Ambient\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Normalize\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSTMP_REG_NORMAL_TMP\r\n    rsq     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP.w\r\n    mul     VSTMP_REG_NORMAL_TMP.xyz, VSTMP_REG_NORMAL_TMP.xyz, VSTMP_REG_NORMAL_TMP.w\r\n\r\n    ; DP normal & light0 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_TMP.w\r\n\r\n\t; This is where the ambient gets added in.\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\r\n\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light1 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_TMP.w\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light2 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_TMP.w\r\n;    mad     oD0, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_TMP.w, r11\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n\t; Material color attenuation\r\n\tmul\t\toD0, r11, VSCONST_REG_MATERIAL_COLOR\r\n\r\n;------------------------------------------------------------------------------\r\n; Copy texture coordinates\r\n;------------------------------------------------------------------------------\r\n\r\n    mov     oT0, VSIN_REG_TEXCOORDS0\r\n    mov     oT1, VSIN_REG_TEXCOORDS1\r\n    mov     oT2, VSIN_REG_TEXCOORDS2\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_3Weight.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 3\r\n    mov     a0.x, VSIN_REG_INDICES.z\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.z, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.z, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.z, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n\t; Transform normal by weighted matrix\r\n    dp3     VSTMP_REG_NORMAL_ACCUM.x, VSIN_REG_NORMAL, VSTMP_REG_MAT0\r\n\tdp3\t\tVSTMP_REG_NORMAL_ACCUM.y, VSIN_REG_NORMAL, VSTMP_REG_MAT1\r\n\tdp3\t\tVSTMP_REG_NORMAL_ACCUM.z, VSIN_REG_NORMAL, VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; Transform normal by combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_X\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_Y\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_Z\r\n\r\n;------------------------------------------------------------------------------\r\n; Single directional light + Ambient\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Normalize\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSTMP_REG_NORMAL_TMP\r\n    rsq     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP.w\r\n    mul     VSTMP_REG_NORMAL_TMP.xyz, VSTMP_REG_NORMAL_TMP.xyz, VSTMP_REG_NORMAL_TMP.w\r\n\r\n    ; DP normal & light0 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_TMP.w\r\n\r\n\t; This is where the ambient gets added in.\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\r\n\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light1 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_TMP.w\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light2 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_TMP.w\r\n;    mad     oD0, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_TMP.w, r11\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n\t; Material color attenuation\r\n\tmul\t\toD0, r11, VSCONST_REG_MATERIAL_COLOR\r\n\r\n;------------------------------------------------------------------------------\r\n; Copy texture coordinates\r\n;------------------------------------------------------------------------------\r\n\r\n    mov     oT0, VSIN_REG_TEXCOORDS0\r\n    mov     oT1, VSIN_REG_TEXCOORDS1\r\n    mov     oT2, VSIN_REG_TEXCOORDS2\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_1Weight.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n    ; Transform position\r\n    dp4\t\tVSTMP_REG_POS_TMP.x, VSIN_REG_POS, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.y, VSIN_REG_POS, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.z, VSIN_REG_POS, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    mov\t\tVSTMP_REG_POS_TMP.w, VSIN_REG_POS.w\r\n\r\n    ; Transform normal\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n\t; No need to scale by results by vertex weights, since this is a one-weight shader so the weight\r\n\t; is assumed to be 1.0\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dp4\t\toPos.x, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_X\r\n    dp4\t\toPos.y, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_Y\r\n    dp4\t\toPos.z, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_Z\r\n    dp4     oPos.w, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Multiple directional lights plus ambient, plus copy texture coordinates\r\n; (interleaving these helps prevent stalls)\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.x, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\t\t\t; Light0 dir.normal\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.y, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\t\t\t; Light1 dir.normal\r\n\tdp3     VSTMP_REG_NORMAL_ACCUM.z, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\t\t\t; Light2 dir.normal\r\n\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.x, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_ACCUM.x\t; Light0 result clamp\r\n    max     VSTMP_REG_NORMAL_ACCUM.y, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_ACCUM.y\t; Light1 result clamp\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.z, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_ACCUM.z\t; Light2 result clamp\r\n\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\t\t\t\t\t\t\t\t\t\t\t\t; Accumulate start with ambient\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_ACCUM.x, r11\t\t\t\t\t; Accumulate Light0 result modulated with Light0 color\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_ACCUM.y, r11\t\t\t\t\t; Accumulate Light1 result modulated with Light1 color\r\n\tmad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_ACCUM.z, r11\t\t\t\t\t; Accumulate Light2 result modulated with Light2 color\r\n\r\n\tmov     oT0, VSIN_REG_TEXCOORDS0\r\n\tmov     oT1, VSIN_REG_TEXCOORDS1\r\n\tmov     oT2, VSIN_REG_TEXCOORDS2\r\n\tmov     oT3, VSIN_REG_TEXCOORDS3\r\n\r\n\tmul\t\toD0, r11, VSIN_REG_COLOR\t\t\t\t\t\t\t\t\t\t\t\t\t\t; Vertex color attenuation\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, -r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_1Weight_SBPassThru.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n    ; Transform position\r\n    dp4\t\tVSTMP_REG_POS_TMP.x, VSIN_REG_POS, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.y, VSIN_REG_POS, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.z, VSIN_REG_POS, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    mov\t\tVSTMP_REG_POS_TMP.w, VSIN_REG_POS.w\r\n\r\n\t; No need to scale by results by vertex weights, since this is a one-weight shader so the weight\r\n\t; is assumed to be 1.0\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dp4\t\toPos.x, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_X\r\n    dp4\t\toPos.y, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_Y\r\n    dp4\t\toPos.z, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_Z\r\n    dp4     oPos.w, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Calculate second set of texture coordinates (into 4th slot) by transforming the world space\r\n; position into the shadowbuffer space\r\n;------------------------------------------------------------------------------\r\n\r\n\tdp4\t\toT3.x, VSTMP_REG_POS_TMP, VSCONST_REG_SHADOWBUFFER_TRANSFORM_X\r\n\tdp4\t\toT3.y, VSTMP_REG_POS_TMP, VSCONST_REG_SHADOWBUFFER_TRANSFORM_Y\r\n\tdp4\t\toT3.z, VSTMP_REG_POS_TMP, VSCONST_REG_SHADOWBUFFER_TRANSFORM_Z\r\n\tdp4\t\tr0.w,  VSTMP_REG_POS_TMP, VSCONST_REG_SHADOWBUFFER_TRANSFORM_W\r\n\r\n\t;clamp w (q) to 0\r\n\tslt\t\tr1, c0, c0\r\n\tmax\t\tr0.w, r0.w, r1.w\r\n\tmov\t\toT3.w, r0.w\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_1Weight_UVTransform.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n    ; Transform position\r\n    dp4\t\tVSTMP_REG_POS_TMP.x, VSIN_REG_POS, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.y, VSIN_REG_POS, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.z, VSIN_REG_POS, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    mov\t\tVSTMP_REG_POS_TMP.w, VSIN_REG_POS.w\r\n\r\n    ; Transform normal\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n\t; No need to scale by results by vertex weights, since this is a one-weight shader so the weight\r\n\t; is assumed to be 1.0\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dp4\t\toPos.x, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_X\r\n    dp4\t\toPos.y, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_Y\r\n    dp4\t\toPos.z, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_Z\r\n    dp4     oPos.w, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Multiple directional lights plus ambient, plus transform texture coordinates\r\n; (interleaving these helps prevent stalls)\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.x, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\t\t\t; Light0 dir.normal\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.y, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\t\t\t; Light1 dir.normal\r\n\tdp3     VSTMP_REG_NORMAL_ACCUM.z, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\t\t\t; Light2 dir.normal\r\n\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.x, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_ACCUM.x\t; Light0 result clamp\r\n    max     VSTMP_REG_NORMAL_ACCUM.y, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_ACCUM.y\t; Light1 result clamp\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.z, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_ACCUM.z\t; Light2 result clamp\r\n\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\t\t\t\t\t\t\t\t\t\t\t\t; Accumulate start with ambient\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_ACCUM.x, r11\t\t\t\t\t; Accumulate Light0 result modulated with Light0 color\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_ACCUM.y, r11\t\t\t\t\t; Accumulate Light1 result modulated with Light1 color\r\n\tmad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_ACCUM.z, r11\t\t\t\t\t; Accumulate Light2 result modulated with Light2 color\r\n\r\n\tdp4     oT0.x, VSIN_REG_TEXCOORDS0, VSCONST_REG_UV_MAT00\t\t\t\t\t\t\t\t; u' = ( s * mat00.x ) + ( t * mat00.y ) + ( 1.0 * mat00.w )\r\n\tdp4     oT0.y, VSIN_REG_TEXCOORDS0, VSCONST_REG_UV_MAT01\t\t\t\t\t\t\t\t; v' = ( s * mat01.x ) + ( t * mat01.y ) + ( 1.0 * mat01.w )\r\n\tdp4     oT1.x, VSIN_REG_TEXCOORDS1, VSCONST_REG_UV_MAT10\t\t\t\t\t\t\t\t; u' = ( s * mat10.x ) + ( t * mat10.y ) + ( 1.0 * mat10.w )\r\n\tdp4     oT1.y, VSIN_REG_TEXCOORDS1, VSCONST_REG_UV_MAT11\t\t\t\t\t\t\t\t; v' = ( s * mat11.x ) + ( t * mat11.y ) + ( 1.0 * mat11.w )\r\n\tdp4     oT2.x, VSIN_REG_TEXCOORDS2, VSCONST_REG_UV_MAT20\t\t\t\t\t\t\t\t; u' = ( s * mat20.x ) + ( t * mat20.y ) + ( 1.0 * mat20.w )\r\n\tdp4     oT2.y, VSIN_REG_TEXCOORDS2, VSCONST_REG_UV_MAT21\t\t\t\t\t\t\t\t; v' = ( s * mat21.x ) + ( t * mat21.y ) + ( 1.0 * mat21.w )\r\n\tdp4     oT3.x, VSIN_REG_TEXCOORDS3, VSCONST_REG_UV_MAT30\t\t\t\t\t\t\t\t; u' = ( s * mat30.x ) + ( t * mat30.y ) + ( 1.0 * mat30.w )\r\n\tdp4     oT3.y, VSIN_REG_TEXCOORDS3, VSCONST_REG_UV_MAT31\t\t\t\t\t\t\t\t; v' = ( s * mat31.x ) + ( t * mat31.y ) + ( 1.0 * mat31.w )\r\n\r\n\tmul\t\toD0, r11, VSIN_REG_COLOR\t\t\t\t\t\t\t\t\t\t\t\t\t\t; Vertex color attenuation\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, -r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_2Weight.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n\t; Transform normal by weighted matrix\r\n\tdp3     VSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, VSTMP_REG_MAT0\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, VSTMP_REG_MAT1\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Multiple directional lights plus ambient, plus copy texture coordinates\r\n; (interleaving these helps prevent stalls)\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.x, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\t\t\t; Light0 dir.normal\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.y, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\t\t\t; Light1 dir.normal\r\n\tdp3     VSTMP_REG_NORMAL_ACCUM.z, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\t\t\t; Light2 dir.normal\r\n\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.x, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_ACCUM.x\t; Light0 result clamp\r\n    max     VSTMP_REG_NORMAL_ACCUM.y, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_ACCUM.y\t; Light1 result clamp\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.z, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_ACCUM.z\t; Light2 result clamp\r\n\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\t\t\t\t\t\t\t\t\t\t\t\t; Accumulate start with ambient\r\n    mov     oT0, VSIN_REG_TEXCOORDS0\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_ACCUM.x, r11\t\t\t\t\t; Accumulate Light0 result modulated with Light0 color\r\n    mov     oT1, VSIN_REG_TEXCOORDS1\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_ACCUM.y, r11\t\t\t\t\t; Accumulate Light1 result modulated with Light1 color\r\n    mov     oT2, VSIN_REG_TEXCOORDS2\r\n\tmad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_ACCUM.z, r11\t\t\t\t\t; Accumulate Light2 result modulated with Light2 color\r\n    mov     oT3, VSIN_REG_TEXCOORDS3\r\n\r\n\tmul\t\toD0, r11, VSIN_REG_COLOR\t\t\t\t\t\t\t\t\t\t\t\t\t\t; Vertex color attenuation\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, -r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_2Weight_SBPassThru.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n    ; Copy w\r\n    mov\t\tVSTMP_REG_POS_ACCUM.w, VSIN_REG_POS.w\r\n    \r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Calculate second set of texture coordinates (into 4th slot) by transforming the world space\r\n; position into the shadowbuffer space\r\n;------------------------------------------------------------------------------\r\n\r\n\tdp4\t\toT3.x, VSTMP_REG_POS_ACCUM,\tVSCONST_REG_SHADOWBUFFER_TRANSFORM_X\r\n\tdp4\t\toT3.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_SHADOWBUFFER_TRANSFORM_Y\r\n\tdp4\t\toT3.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_SHADOWBUFFER_TRANSFORM_Z\r\n\tdp4\t\tr0.w,  VSTMP_REG_POS_ACCUM, VSCONST_REG_SHADOWBUFFER_TRANSFORM_W\r\n\r\n\t;clamp w (q) to 0\r\n\tslt\t\tr1, c0, c0\r\n\tmax\t\tr0.w, r0.w, r1.w\r\n\tmov\t\toT3.w, r0.w\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_2Weight_UVTransform.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n\t; Transform normal by weighted matrix\r\n\tdp3     VSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, VSTMP_REG_MAT0\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, VSTMP_REG_MAT1\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Multiple directional lights plus ambient, plus transform texture coordinates\r\n; (interleaving these helps prevent stalls)\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.x, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\t\t\t; Light0 dir.normal\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.y, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\t\t\t; Light1 dir.normal\r\n\tdp3     VSTMP_REG_NORMAL_ACCUM.z, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\t\t\t; Light2 dir.normal\r\n\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.x, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_ACCUM.x\t; Light0 result clamp\r\n    max     VSTMP_REG_NORMAL_ACCUM.y, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_ACCUM.y\t; Light1 result clamp\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.z, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_ACCUM.z\t; Light2 result clamp\r\n\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\t\t\t\t\t\t\t\t\t\t\t\t; Accumulate start with ambient\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_ACCUM.x, r11\t\t\t\t\t; Accumulate Light0 result modulated with Light0 color\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_ACCUM.y, r11\t\t\t\t\t; Accumulate Light1 result modulated with Light1 color\r\n\tmad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_ACCUM.z, r11\t\t\t\t\t; Accumulate Light2 result modulated with Light2 color\r\n\r\n\tdp4     oT0.x, VSIN_REG_TEXCOORDS0, VSCONST_REG_UV_MAT00\t\t\t\t\t\t\t\t; u' = ( s * mat00.x ) + ( t * mat00.y ) + ( 1.0 * mat00.w )\r\n\tdp4     oT0.y, VSIN_REG_TEXCOORDS0, VSCONST_REG_UV_MAT01\t\t\t\t\t\t\t\t; v' = ( s * mat01.x ) + ( t * mat01.y ) + ( 1.0 * mat01.w )\r\n\tdp4     oT1.x, VSIN_REG_TEXCOORDS1, VSCONST_REG_UV_MAT10\t\t\t\t\t\t\t\t; u' = ( s * mat10.x ) + ( t * mat10.y ) + ( 1.0 * mat10.w )\r\n\tdp4     oT1.y, VSIN_REG_TEXCOORDS1, VSCONST_REG_UV_MAT11\t\t\t\t\t\t\t\t; v' = ( s * mat11.x ) + ( t * mat11.y ) + ( 1.0 * mat11.w )\r\n\tdp4     oT2.x, VSIN_REG_TEXCOORDS2, VSCONST_REG_UV_MAT20\t\t\t\t\t\t\t\t; u' = ( s * mat20.x ) + ( t * mat20.y ) + ( 1.0 * mat20.w )\r\n\tdp4     oT2.y, VSIN_REG_TEXCOORDS2, VSCONST_REG_UV_MAT21\t\t\t\t\t\t\t\t; v' = ( s * mat21.x ) + ( t * mat21.y ) + ( 1.0 * mat21.w )\r\n\tdp4     oT3.x, VSIN_REG_TEXCOORDS3, VSCONST_REG_UV_MAT30\t\t\t\t\t\t\t\t; u' = ( s * mat30.x ) + ( t * mat30.y ) + ( 1.0 * mat30.w )\r\n\tdp4     oT3.y, VSIN_REG_TEXCOORDS3, VSCONST_REG_UV_MAT31\t\t\t\t\t\t\t\t; v' = ( s * mat31.x ) + ( t * mat31.y ) + ( 1.0 * mat31.w )\r\n\r\n\tmul\t\toD0, r11, VSIN_REG_COLOR\t\t\t\t\t\t\t\t\t\t\t\t\t\t; Vertex color attenuation\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, -r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_3Weight.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 3\r\n    mov     a0.x, VSIN_REG_INDICES.z\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.z, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.z, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.z, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n\t; Transform normal by weighted matrix\r\n\tdp3     VSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, VSTMP_REG_MAT0\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, VSTMP_REG_MAT1\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Multiple directional lights plus ambient, plus copy texture coordinates\r\n; (interleaving these helps prevent stalls)\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.x, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\t\t\t; Light0 dir.normal\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.y, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\t\t\t; Light1 dir.normal\r\n\tdp3     VSTMP_REG_NORMAL_ACCUM.z, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\t\t\t; Light2 dir.normal\r\n\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.x, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_ACCUM.x\t; Light0 result clamp\r\n    max     VSTMP_REG_NORMAL_ACCUM.y, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_ACCUM.y\t; Light1 result clamp\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.z, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_ACCUM.z\t; Light2 result clamp\r\n\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\t\t\t\t\t\t\t\t\t\t\t\t; Accumulate start with ambient\r\n    mov     oT0, VSIN_REG_TEXCOORDS0\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_ACCUM.x, r11\t\t\t\t\t; Accumulate Light0 result modulated with Light0 color\r\n    mov     oT1, VSIN_REG_TEXCOORDS1\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_ACCUM.y, r11\t\t\t\t\t; Accumulate Light1 result modulated with Light1 color\r\n    mov     oT2, VSIN_REG_TEXCOORDS2\r\n\tmad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_ACCUM.z, r11\t\t\t\t\t; Accumulate Light2 result modulated with Light2 color\r\n    mov     oT3, VSIN_REG_TEXCOORDS3\r\n\r\n\tmul\t\toD0, r11, VSIN_REG_COLOR\t\t\t\t\t\t\t\t\t\t\t\t\t\t; Vertex color attenuation\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, -r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_3Weight_SBPassThru.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 3\r\n    mov     a0.x, VSIN_REG_INDICES.z\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.z, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.z, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.z, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n    ; Copy w\r\n    mov\t\tVSTMP_REG_POS_ACCUM.w, VSIN_REG_POS.w\r\n    \r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Calculate second set of texture coordinates (into 4th slot) by transforming the world space\r\n; position into the shadowbuffer space\r\n;------------------------------------------------------------------------------\r\n\r\n\tdp4\t\toT3.x, VSTMP_REG_POS_ACCUM,\tVSCONST_REG_SHADOWBUFFER_TRANSFORM_X\r\n\tdp4\t\toT3.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_SHADOWBUFFER_TRANSFORM_Y\r\n\tdp4\t\toT3.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_SHADOWBUFFER_TRANSFORM_Z\r\n\tdp4\t\tr0.w,  VSTMP_REG_POS_ACCUM, VSCONST_REG_SHADOWBUFFER_TRANSFORM_W\r\n\r\n\t;clamp w (q) to 0\r\n\tslt\t\tr1, c0, c0\r\n\tmax\t\tr0.w, r0.w, r1.w\r\n\tmov\t\toT3.w, r0.w\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_3Weight_UVTransform.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 3\r\n    mov     a0.x, VSIN_REG_INDICES.z\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.z, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.z, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.z, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n\t; Transform normal by weighted matrix\r\n\tdp3     VSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, VSTMP_REG_MAT0\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, VSTMP_REG_MAT1\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Multiple directional lights plus ambient, plus copy texture coordinates\r\n; (interleaving these helps prevent stalls)\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.x, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\t\t\t; Light0 dir.normal\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.y, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\t\t\t; Light1 dir.normal\r\n\tdp3     VSTMP_REG_NORMAL_ACCUM.z, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\t\t\t; Light2 dir.normal\r\n\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.x, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_ACCUM.x\t; Light0 result clamp\r\n    max     VSTMP_REG_NORMAL_ACCUM.y, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_ACCUM.y\t; Light1 result clamp\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.z, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_ACCUM.z\t; Light2 result clamp\r\n\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\t\t\t\t\t\t\t\t\t\t\t\t; Accumulate start with ambient\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_ACCUM.x, r11\t\t\t\t\t; Accumulate Light0 result modulated with Light0 color\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_ACCUM.y, r11\t\t\t\t\t; Accumulate Light1 result modulated with Light1 color\r\n\tmad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_ACCUM.z, r11\t\t\t\t\t; Accumulate Light2 result modulated with Light2 color\r\n\r\n\tdp4     oT0.x, VSIN_REG_TEXCOORDS0, VSCONST_REG_UV_MAT00\t\t\t\t\t\t\t\t; u' = ( s * mat00.x ) + ( t * mat00.y ) + ( 1.0 * mat00.w )\r\n\tdp4     oT0.y, VSIN_REG_TEXCOORDS0, VSCONST_REG_UV_MAT01\t\t\t\t\t\t\t\t; v' = ( s * mat01.x ) + ( t * mat01.y ) + ( 1.0 * mat01.w )\r\n\tdp4     oT1.x, VSIN_REG_TEXCOORDS1, VSCONST_REG_UV_MAT10\t\t\t\t\t\t\t\t; u' = ( s * mat10.x ) + ( t * mat10.y ) + ( 1.0 * mat10.w )\r\n\tdp4     oT1.y, VSIN_REG_TEXCOORDS1, VSCONST_REG_UV_MAT11\t\t\t\t\t\t\t\t; v' = ( s * mat11.x ) + ( t * mat11.y ) + ( 1.0 * mat11.w )\r\n\tdp4     oT2.x, VSIN_REG_TEXCOORDS2, VSCONST_REG_UV_MAT20\t\t\t\t\t\t\t\t; u' = ( s * mat20.x ) + ( t * mat20.y ) + ( 1.0 * mat20.w )\r\n\tdp4     oT2.y, VSIN_REG_TEXCOORDS2, VSCONST_REG_UV_MAT21\t\t\t\t\t\t\t\t; v' = ( s * mat21.x ) + ( t * mat21.y ) + ( 1.0 * mat21.w )\r\n\tdp4     oT3.x, VSIN_REG_TEXCOORDS3, VSCONST_REG_UV_MAT30\t\t\t\t\t\t\t\t; u' = ( s * mat30.x ) + ( t * mat30.y ) + ( 1.0 * mat30.w )\r\n\tdp4     oT3.y, VSIN_REG_TEXCOORDS3, VSCONST_REG_UV_MAT31\t\t\t\t\t\t\t\t; v' = ( s * mat31.x ) + ( t * mat31.y ) + ( 1.0 * mat31.w )\r\n\r\n\tmul\t\toD0, r11, VSIN_REG_COLOR\t\t\t\t\t\t\t\t\t\t\t\t\t\t; Vertex color attenuation\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, -r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_4Weight.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 3\r\n    mov     a0.x, VSIN_REG_INDICES.z\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.z, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.z, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.z, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 4\r\n    mov     a0.x, VSIN_REG_INDICES.w\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.w, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.w, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.w, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n\t; Transform normal by weighted matrix\r\n\tdp3     VSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, VSTMP_REG_MAT0\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, VSTMP_REG_MAT1\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, -r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; Multiple directional lights plus ambient\r\n;------------------------------------------------------------------------------\r\n\r\n    ; DP normal & light0 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_TMP.w\r\n\r\n\t; This is where the ambient gets added in.\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\r\n\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light1 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_TMP.w\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light2 dir clamp then scale by light color\r\n\tdp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\r\n\tmax     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_TMP.w\r\n\tmad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n\t; Vertex color attenuation\r\n\tmul\t\toD0, r11, VSIN_REG_COLOR\r\n\r\n;------------------------------------------------------------------------------\r\n; Copy texture coordinates\r\n;------------------------------------------------------------------------------\r\n\r\n    mov     oT0, VSIN_REG_TEXCOORDS0\r\n    mov     oT1, VSIN_REG_TEXCOORDS1\r\n    mov     oT2, VSIN_REG_TEXCOORDS2\r\n    mov     oT3, VSIN_REG_TEXCOORDS3\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_4Weight_SBPassThru.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 3\r\n    mov     a0.x, VSIN_REG_INDICES.z\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.z, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.z, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.z, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 4\r\n    mov     a0.x, VSIN_REG_INDICES.w\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.w, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.w, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.w, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n    ; Copy w\r\n    mov\t\tVSTMP_REG_POS_ACCUM.w, VSIN_REG_POS.w\r\n    \r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Calculate second set of texture coordinates (into 4th slot) by transforming the world space\r\n; position into the shadowbuffer space\r\n;------------------------------------------------------------------------------\r\n\r\n\tdp4\t\toT3.x, VSTMP_REG_POS_ACCUM,\tVSCONST_REG_SHADOWBUFFER_TRANSFORM_X\r\n\tdp4\t\toT3.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_SHADOWBUFFER_TRANSFORM_Y\r\n\tdp4\t\toT3.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_SHADOWBUFFER_TRANSFORM_Z\r\n\tdp4\t\tr0.w,  VSTMP_REG_POS_ACCUM, VSCONST_REG_SHADOWBUFFER_TRANSFORM_W\r\n\r\n\t;clamp w (q) to 0\r\n\tslt\t\tr1, c0, c0\r\n\tmax\t\tr0.w, r0.w, r1.w\r\n\tmov\t\toT3.w, r0.w\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_Specular_1Weight.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n    ; Transform position\r\n    dp4\t\tVSTMP_REG_POS_TMP.x, VSIN_REG_POS, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.y, VSIN_REG_POS, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.z, VSIN_REG_POS, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    mov\t\tVSTMP_REG_POS_TMP.w, VSIN_REG_POS.w\r\n\r\n    ; Transform normal\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n\t; No need to scale by results by vertex weights, since this is a one-weight shader so the weight\r\n\t; is assumed to be 1.0\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dp4\t\toPos.x, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_X\r\n    dp4\t\toPos.y, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_Y\r\n    dp4\t\toPos.z, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_Z\r\n    dp4     oPos.w, VSTMP_REG_POS_TMP, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Multiple directional lights plus ambient, plus copy texture coordinates\r\n; (interleaving these helps prevent stalls)\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.x, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\t\t\t; Light0 dir.normal\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.y, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\t\t\t; Light1 dir.normal\r\n\tdp3     VSTMP_REG_NORMAL_ACCUM.z, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\t\t\t; Light2 dir.normal\r\n\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.x, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_ACCUM.x\t; Light0 result clamp\r\n    max     VSTMP_REG_NORMAL_ACCUM.y, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_ACCUM.y\t; Light1 result clamp\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.z, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_ACCUM.z\t; Light2 result clamp\r\n\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\t\t\t\t\t\t\t\t\t\t\t\t; Accumulate start with ambient\r\n    mov     oT0, VSIN_REG_TEXCOORDS0\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_ACCUM.x, r11\t\t\t\t\t; Accumulate Light0 result modulated with Light0 color\r\n    mov     oT1, VSIN_REG_TEXCOORDS1\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_ACCUM.y, r11\t\t\t\t\t; Accumulate Light1 result modulated with Light1 color\r\n    mov     oT2, VSIN_REG_TEXCOORDS2\r\n\tmad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_ACCUM.z, r11\t\t\t\t\t; Accumulate Light2 result modulated with Light2 color\r\n    mov     oT3, VSIN_REG_TEXCOORDS3\r\n\r\n\tmul\t\toD0, r11, VSIN_REG_COLOR\t\t\t\t\t\t\t\t\t\t\t\t\t\t; Vertex color attenuation\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, -r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; Specular calculation\r\n;------------------------------------------------------------------------------\r\n\r\n\t; Calculate vector to eye (V)\r\n\tsub\t\tr7.xyz, VSCONST_REG_CAM_POS, VSTMP_REG_POS_TMP\r\n\t\r\n\t; Store Light0 dir.normal off into r0\r\n\tmov\t\tr0.x, VSTMP_REG_NORMAL_ACCUM.x\r\n\r\n\t; Normalize V\r\n\tdp3\t\tr7.w, r7.xyz, r7.xyz\r\n\trsq\t\tr1.x, r7.w\r\n\tmul\t\tr7, r7, r1.x\r\n\r\n\t; Calculate H = L + V\r\n\tadd\t\tr7, -VSCONST_REG_LIGHT_DIR0, r7\r\n\r\n\t; Normalize H\r\n\tdp3\t\tr7.w, r7.xyz, r7.xyz\r\n\trsq\t\tr1.x, r7.w\r\n\tmul\t\tr7, r7, r1.x\r\n\r\n\t; Calculate N.H (don't worry about clamping to zero, since the lit instruction below does this)\r\n\tdp3\t\tr0.y, VSTMP_REG_NORMAL_TMP, r7\r\n\r\n\t; Move the power term over into r0\r\n\tmov\t\tr0.w, VSCONST_REG_SPECULAR_COLOR.w\r\n\t\r\n\t; Specular lighting calc - (N.H)^pow\r\n\tlit\t\tr1.z, r0\r\n\r\n\t; Modulate specular color by specular result.\r\n\tmul\t\toD1.xyz, r1.z, VSCONST_REG_SPECULAR_COLOR.xyz\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_Specular_2Weight.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n\t; Transform normal by weighted matrix\r\n\tdp3     VSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, VSTMP_REG_MAT0\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, VSTMP_REG_MAT1\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Multiple directional lights plus ambient, plus copy texture coordinates\r\n; (interleaving these helps prevent stalls)\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.x, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\t\t\t; Light0 dir.normal\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.y, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\t\t\t; Light1 dir.normal\r\n\tdp3     VSTMP_REG_NORMAL_ACCUM.z, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\t\t\t; Light2 dir.normal\r\n\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.x, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_ACCUM.x\t; Light0 result clamp\r\n    max     VSTMP_REG_NORMAL_ACCUM.y, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_ACCUM.y\t; Light1 result clamp\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.z, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_ACCUM.z\t; Light2 result clamp\r\n\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\t\t\t\t\t\t\t\t\t\t\t\t; Accumulate start with ambient\r\n    mov     oT0, VSIN_REG_TEXCOORDS0\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_ACCUM.x, r11\t\t\t\t\t; Accumulate Light0 result modulated with Light0 color\r\n    mov     oT1, VSIN_REG_TEXCOORDS1\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_ACCUM.y, r11\t\t\t\t\t; Accumulate Light1 result modulated with Light1 color\r\n    mov     oT2, VSIN_REG_TEXCOORDS2\r\n\tmad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_ACCUM.z, r11\t\t\t\t\t; Accumulate Light2 result modulated with Light2 color\r\n    mov     oT3, VSIN_REG_TEXCOORDS3\r\n\r\n\tmul\t\toD0, r11, VSIN_REG_COLOR\t\t\t\t\t\t\t\t\t\t\t\t\t\t; Vertex color attenuation\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, -r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; Specular calculation\r\n;------------------------------------------------------------------------------\r\n\r\n\t; Calculate vector to eye (V)\r\n\tsub\t\tr7.xyz, VSCONST_REG_CAM_POS, VSTMP_REG_POS_ACCUM\r\n\t\r\n\t; Store Light0 dir.normal off into r0\r\n\tmov\t\tr0.x, VSTMP_REG_NORMAL_ACCUM.x\r\n\r\n\t; Normalize V\r\n\tdp3\t\tr7.w, r7.xyz, r7.xyz\r\n\trsq\t\tr1.x, r7.w\r\n\tmul\t\tr7, r7, r1.x\r\n\r\n\t; Calculate H = L + V\r\n\tadd\t\tr7, -VSCONST_REG_LIGHT_DIR0, r7\r\n\r\n\t; Normalize H\r\n\tdp3\t\tr7.w, r7.xyz, r7.xyz\r\n\trsq\t\tr1.x, r7.w\r\n\tmul\t\tr7, r7, r1.x\r\n\r\n\t; Calculate N.H (don't worry about clamping to zero, since the lit instruction below does this)\r\n\tdp3\t\tr0.y, VSTMP_REG_NORMAL_TMP, r7\r\n\r\n\t; Move the power term over into r0\r\n\tmov\t\tr0.w, VSCONST_REG_SPECULAR_COLOR.w\r\n\t\r\n\t; Specular lighting calc - (N.H)^pow\r\n\tlit\t\tr1.z, r0\r\n\r\n\t; Modulate specular color by specular result.\r\n\tmul\t\toD1.xyz, r1.z, VSCONST_REG_SPECULAR_COLOR.xyz\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_Specular_3Weight.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 3\r\n    mov     a0.x, VSIN_REG_INDICES.z\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.z, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.z, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.z, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n\t; Transform normal by weighted matrix\r\n\tdp3     VSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, VSTMP_REG_MAT0\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, VSTMP_REG_MAT1\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Multiple directional lights plus ambient, plus copy texture coordinates\r\n; (interleaving these helps prevent stalls)\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.x, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\t\t\t; Light0 dir.normal\r\n    dp3\t\tVSTMP_REG_NORMAL_ACCUM.y, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\t\t\t; Light1 dir.normal\r\n\tdp3     VSTMP_REG_NORMAL_ACCUM.z, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\t\t\t; Light2 dir.normal\r\n\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.x, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_ACCUM.x\t; Light0 result clamp\r\n    max     VSTMP_REG_NORMAL_ACCUM.y, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_ACCUM.y\t; Light1 result clamp\r\n\tmax     VSTMP_REG_NORMAL_ACCUM.z, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_ACCUM.z\t; Light2 result clamp\r\n\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\t\t\t\t\t\t\t\t\t\t\t\t; Accumulate start with ambient\r\n    mov     oT0, VSIN_REG_TEXCOORDS0\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_ACCUM.x, r11\t\t\t\t\t; Accumulate Light0 result modulated with Light0 color\r\n    mov     oT1, VSIN_REG_TEXCOORDS1\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_ACCUM.y, r11\t\t\t\t\t; Accumulate Light1 result modulated with Light1 color\r\n    mov     oT2, VSIN_REG_TEXCOORDS2\r\n\tmad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_ACCUM.z, r11\t\t\t\t\t; Accumulate Light2 result modulated with Light2 color\r\n    mov     oT3, VSIN_REG_TEXCOORDS3\r\n\r\n\tmul\t\toD0, r11, VSIN_REG_COLOR\t\t\t\t\t\t\t\t\t\t\t\t\t\t; Vertex color attenuation\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, -r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; Specular calculation\r\n;------------------------------------------------------------------------------\r\n\r\n\t; Calculate vector to eye (V)\r\n\tsub\t\tr7.xyz, VSCONST_REG_CAM_POS, VSTMP_REG_POS_ACCUM\r\n\t\r\n\t; Store Light0 dir.normal off into r0\r\n\tmov\t\tr0.x, VSTMP_REG_NORMAL_ACCUM.x\r\n\r\n\t; Normalize V\r\n\tdp3\t\tr7.w, r7.xyz, r7.xyz\r\n\trsq\t\tr1.x, r7.w\r\n\tmul\t\tr7, r7, r1.x\r\n\r\n\t; Calculate H = L + V\r\n\tadd\t\tr7, -VSCONST_REG_LIGHT_DIR0, r7\r\n\r\n\t; Normalize H\r\n\tdp3\t\tr7.w, r7.xyz, r7.xyz\r\n\trsq\t\tr1.x, r7.w\r\n\tmul\t\tr7, r7, r1.x\r\n\r\n\t; Calculate N.H (don't worry about clamping to zero, since the lit instruction below does this)\r\n\tdp3\t\tr0.y, VSTMP_REG_NORMAL_TMP, r7\r\n\r\n\t; Move the power term over into r0\r\n\tmov\t\tr0.w, VSCONST_REG_SPECULAR_COLOR.w\r\n\t\r\n\t; Specular lighting calc - (N.H)^pow\r\n\tlit\t\tr1.z, r0\r\n\r\n\t; Modulate specular color by specular result.\r\n\tmul\t\toD1.xyz, r1.z, VSCONST_REG_SPECULAR_COLOR.xyz\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVS_VXC_Specular_4Weight.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 3\r\n    mov     a0.x, VSIN_REG_INDICES.z\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.z, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.z, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.z, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 4\r\n    mov     a0.x, VSIN_REG_INDICES.w\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.w, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.w, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.w, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n\t; Transform normal by weighted matrix\r\n\tdp3     VSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, VSTMP_REG_MAT0\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, VSTMP_REG_MAT1\r\n\tdp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, -r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; Multiple directional lights plus ambient\r\n;------------------------------------------------------------------------------\r\n\r\n    ; DP normal & light0 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_TMP.w\r\n\r\n\t; For specular calculations further down, save this result off into r0.x\r\n\tmov\t\tr0.x, VSTMP_REG_NORMAL_TMP.w\r\n\r\n\t; This is where the ambient gets added in.\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\r\n\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light1 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_TMP.w\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light2 dir clamp then scale by light color (third light currently deactivated).\r\n;\tdp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\r\n;\tmax     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_TMP.w\r\n;\tmad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n\t; Vertex color attenuation\r\n\tmul\t\toD0, r11, VSIN_REG_COLOR\r\n\r\n;------------------------------------------------------------------------------\r\n; Specular calculation\r\n;------------------------------------------------------------------------------\r\n\r\n\t; Calculate vector to eye (V)\r\n\tsub\t\tr7.xyz, VSCONST_REG_CAM_POS, VSTMP_REG_POS_ACCUM\r\n\t\r\n\t; Normalize V\r\n\tdp3\t\tr7.w, r7.xyz, r7.xyz\r\n\trsq\t\tr1.x, r7.w\r\n\tmul\t\tr7, r7, r1.x\r\n\r\n\t; Calculate H = L + V\r\n\tadd\t\tr7, -VSCONST_REG_LIGHT_DIR0, r7\r\n\r\n\t; Normalize H\r\n\tdp3\t\tr7.w, r7.xyz, r7.xyz\r\n\trsq\t\tr1.x, r7.w\r\n\tmul\t\tr7, r7, r1.x\r\n\r\n\t; Calculate N.H (don't worry about clamping to zero, since the lit instruction below does this)\r\n\tdp3\t\tr0.y, VSTMP_REG_NORMAL_TMP, r7\r\n\r\n\t; Move the power term over into r0\r\n\tmov\t\tr0.w, VSCONST_REG_SPECULAR_COLOR.w\r\n\t\r\n\t; Specular lighting calc - (N.H)^pow\r\n\tlit\t\tr1.z, r0\r\n\r\n\t; Modulate specular color by specular result.\r\n;\tmov\t\toD1.xyz, r1.z\r\n\tmul\t\toD1.xyz, r1.z, VSCONST_REG_SPECULAR_COLOR.xyz\r\n\r\n;------------------------------------------------------------------------------\r\n; Copy texture coordinates\r\n;------------------------------------------------------------------------------\r\n\r\n    mov     oT0, VSIN_REG_TEXCOORDS0\r\n    mov     oT1, VSIN_REG_TEXCOORDS1\r\n    mov     oT2, VSIN_REG_TEXCOORDS2\r\n    mov     oT3, VSIN_REG_TEXCOORDS3\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVertexShader0.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n    ; Transform position\r\n    dp4\t\tVSTMP_REG_POS_TMP.x, VSIN_REG_POS, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.y, VSIN_REG_POS, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.z, VSIN_REG_POS, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed point by weight\r\n    mul     VSTMP_REG_POS_ACCUM.xyz, VSTMP_REG_POS_TMP.xyz, VSIN_REG_WEIGHTS.x\r\n\r\n    ; Transform normal\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed normal by weight\r\n    mul     VSTMP_REG_NORMAL_ACCUM.xyz, VSTMP_REG_NORMAL_TMP.xyz, VSIN_REG_WEIGHTS.x\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n    ; Transform position\r\n    dp4\t\tVSTMP_REG_POS_TMP.x, VSIN_REG_POS, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.y, VSIN_REG_POS, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.z, VSIN_REG_POS, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed point by weight and add to previous\r\n    mad     VSTMP_REG_POS_ACCUM.xyz, VSTMP_REG_POS_TMP.xyz, VSIN_REG_WEIGHTS.y, VSTMP_REG_POS_ACCUM.xyz\r\n\r\n    ; Transform normal\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed point by weight\r\n    mad     VSTMP_REG_NORMAL_ACCUM.xyz, VSTMP_REG_NORMAL_TMP.xyz, VSIN_REG_WEIGHTS.y, VSTMP_REG_NORMAL_ACCUM.xyz\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 3\r\n    mov     a0.x, VSIN_REG_INDICES.z\r\n\r\n    ; Transform position\r\n    dp4\t\tVSTMP_REG_POS_TMP.x, VSIN_REG_POS, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.y, VSIN_REG_POS, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.z, VSIN_REG_POS, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed point by weight and add to previous\r\n    mad     VSTMP_REG_POS_ACCUM.xyz, VSTMP_REG_POS_TMP.xyz, VSIN_REG_WEIGHTS.z, VSTMP_REG_POS_ACCUM.xyz\r\n\r\n    ; Transform normal\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed point by weight\r\n    mad     VSTMP_REG_NORMAL_ACCUM.xyz, VSTMP_REG_NORMAL_TMP.xyz, VSIN_REG_WEIGHTS.z, VSTMP_REG_NORMAL_ACCUM.xyz\r\n\r\n    ; Copy w\r\n    mov\t\tVSTMP_REG_POS_ACCUM.w, VSIN_REG_POS.w\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dp4\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dp4\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dp4\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dp4     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; Transform normal by combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_X\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_Y\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_Z\r\n\r\n;------------------------------------------------------------------------------\r\n; Single directional light + Ambient\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Normalize\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSTMP_REG_NORMAL_TMP\r\n    rsq     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP.w\r\n    mul     VSTMP_REG_NORMAL_TMP.xyz, VSTMP_REG_NORMAL_TMP.xyz, VSTMP_REG_NORMAL_TMP.w\r\n\r\n    ; DP normal & light0 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_TMP.w\r\n\r\n\t; This is where the ambient gets added in.\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\r\n\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light1 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_TMP.w\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light2 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_TMP.w\r\n;    mad     oD0, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_TMP.w, r11\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n\t; Material color attenuation\r\n\tmul\t\toD0, r11, VSCONST_REG_MATERIAL_COLOR\r\n\r\n;------------------------------------------------------------------------------\r\n; Copy texture coordinates\r\n;------------------------------------------------------------------------------\r\n\r\n    mov     oT0, VSIN_REG_TEXCOORDS0\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVertexShader1.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n    ; Transform position\r\n    dp4\t\tVSTMP_REG_POS_TMP.x, VSIN_REG_POS, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.y, VSIN_REG_POS, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.z, VSIN_REG_POS, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed point by weight\r\n    mul     VSTMP_REG_POS_ACCUM.xyz, VSTMP_REG_POS_TMP.xyz, VSIN_REG_WEIGHTS.x\r\n\r\n    ; Transform normal\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed normal by weight\r\n    mul     VSTMP_REG_NORMAL_ACCUM.xyz, VSTMP_REG_NORMAL_TMP.xyz, VSIN_REG_WEIGHTS.x\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n    ; Transform position\r\n    dp4\t\tVSTMP_REG_POS_TMP.x, VSIN_REG_POS, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.y, VSIN_REG_POS, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.z, VSIN_REG_POS, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed point by weight and add to previous\r\n    mad     VSTMP_REG_POS_ACCUM.xyz, VSTMP_REG_POS_TMP.xyz, VSIN_REG_WEIGHTS.y, VSTMP_REG_POS_ACCUM.xyz\r\n\r\n    ; Transform normal\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed point by weight\r\n    mad     VSTMP_REG_NORMAL_ACCUM.xyz, VSTMP_REG_NORMAL_TMP.xyz, VSIN_REG_WEIGHTS.y, VSTMP_REG_NORMAL_ACCUM.xyz\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 3\r\n    mov     a0.x, VSIN_REG_INDICES.z\r\n\r\n    ; Transform position\r\n    dp4\t\tVSTMP_REG_POS_TMP.x, VSIN_REG_POS, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.y, VSIN_REG_POS, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp4\t\tVSTMP_REG_POS_TMP.z, VSIN_REG_POS, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed point by weight and add to previous\r\n    mad     VSTMP_REG_POS_ACCUM.xyz, VSTMP_REG_POS_TMP.xyz, VSIN_REG_WEIGHTS.z, VSTMP_REG_POS_ACCUM.xyz\r\n\r\n    ; Transform normal\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSIN_REG_NORMAL, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSIN_REG_NORMAL, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSIN_REG_NORMAL, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n    ; Scale transformed point by weight\r\n    mad     VSTMP_REG_NORMAL_ACCUM.xyz, VSTMP_REG_NORMAL_TMP.xyz, VSIN_REG_WEIGHTS.z, VSTMP_REG_NORMAL_ACCUM.xyz\r\n\r\n    ; Copy w\r\n    mov\t\tVSTMP_REG_POS_ACCUM.w, VSIN_REG_POS.w\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dp4\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dp4\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dp4\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dp4     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n;------------------------------------------------------------------------------\r\n; Deal with fog value (r12 shadows oPos)...\r\n;------------------------------------------------------------------------------\r\n\r\n\tmov\t\toFog.x, r12.w\r\n\r\n;------------------------------------------------------------------------------\r\n; Transform normal by combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.x, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_X\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.y, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_Y\r\n    dp3\t\tVSTMP_REG_NORMAL_TMP.z, VSTMP_REG_NORMAL_ACCUM, VSCONST_REG_WORLD_TRANSFORM_Z\r\n\r\n;------------------------------------------------------------------------------\r\n; Single directional light + Ambient\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Normalize\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSTMP_REG_NORMAL_TMP\r\n    rsq     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP.w\r\n    mul     VSTMP_REG_NORMAL_TMP.xyz, VSTMP_REG_NORMAL_TMP.xyz, VSTMP_REG_NORMAL_TMP.w\r\n\r\n    ; DP normal & light0 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR0\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR0.w, -VSTMP_REG_NORMAL_TMP.w\r\n\r\n\t; This is where the ambient gets added in.\r\n    mov     r11, VSCONST_REG_AMB_LIGHT_COLOR\r\n\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR0, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light1 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR1\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR1.w, -VSTMP_REG_NORMAL_TMP.w\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR1, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n    ; DP normal & light2 dir clamp then scale by light color\r\n    dp3     VSTMP_REG_NORMAL_TMP.w, VSTMP_REG_NORMAL_TMP, VSCONST_REG_LIGHT_DIR2\r\n    max     VSTMP_REG_NORMAL_TMP.w, VSCONST_REG_LIGHT_DIR2.w, -VSTMP_REG_NORMAL_TMP.w\r\n;    mad     oD0, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_TMP.w, r11\r\n    mad     r11, VSCONST_REG_LIGHT_COLOR2, VSTMP_REG_NORMAL_TMP.w, r11\r\n\r\n\t; Vertex color attenuation\r\n\tmul\t\toD0, r11, VSIN_REG_COLOR\r\n\r\n;------------------------------------------------------------------------------\r\n; Copy texture coordinates\r\n;------------------------------------------------------------------------------\r\n\r\n    mov     oT0, VSIN_REG_TEXCOORDS0\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/WeightedMeshVertexShader_SBWrite.vsh",
    "content": "xvs.1.1\r\n\r\n#include \"anim_vertdefs.h\"\r\n\r\n#pragma screenspace\r\n\r\n;------------------------------------------------------------------------------\r\n; Bone space transforms\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 1\r\n    mov     a0.x, VSIN_REG_INDICES.x\r\n\r\n\t; Weight matrix\r\n\tmul\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.x, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.x, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\tmul\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.x, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET]\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 2\r\n    mov     a0.x, VSIN_REG_INDICES.y\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.y, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.y, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.y, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n\r\n    ; Get matrix index 3\r\n    mov     a0.x, VSIN_REG_INDICES.z\r\n\r\n\t; Weight matrix\r\n\tmad\t\tVSTMP_REG_MAT0, VSIN_REG_WEIGHTS.z, c[0 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT0\r\n\tmad\t\tVSTMP_REG_MAT1, VSIN_REG_WEIGHTS.z, c[1 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT1\r\n\tmad\t\tVSTMP_REG_MAT2, VSIN_REG_WEIGHTS.z, c[2 + a0.x VSCONST_REG_MATRIX_OFFSET], VSTMP_REG_MAT2\r\n\r\n\t; Transform position by weighted matrix\r\n    dp4     VSTMP_REG_POS_ACCUM.x, VSIN_REG_POS, VSTMP_REG_MAT0\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.y, VSIN_REG_POS, VSTMP_REG_MAT1\r\n\tdp4\t\tVSTMP_REG_POS_ACCUM.z, VSIN_REG_POS, VSTMP_REG_MAT2\r\n\r\n;------------------------------------------------------------------------------\r\n; Combined camera & projection matrix\r\n;------------------------------------------------------------------------------\r\n\r\n    dph\t\toPos.x, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_X\r\n    dph\t\toPos.y, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Y\r\n    dph\t\toPos.z, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_Z\r\n    dph     oPos.w, VSTMP_REG_POS_ACCUM, VSCONST_REG_TRANSFORM_W\r\n\r\n\r\n;------------------------------------------------------------------------------\r\n; oPos to screenspace transformation\r\n;------------------------------------------------------------------------------\r\n\r\n\tmul\t\toPos.xyz, r12, c94\t\t\t; scale\r\n\t+ rcc\tr1.x, r12.w\t\t\t\t\t; compute 1/w\r\n\tmad\t\toPos.xyz, r12, r1.x, c95\t; scale by 1/w, add offset\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/anim.cpp",
    "content": "#include <xtl.h>\r\n\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <core/HashTable.h>\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/timer.h>\r\n\r\n#include \"nx_init.h\"\r\n#include \"mesh.h\"\r\n#include \"scene.h\"\r\n#include \"anim.h\"\r\n#include \"anim_vertdefs.h\"\r\n\r\n#include \"WeightedMeshVS_VXC_1Weight.h\"\r\n#include \"WeightedMeshVS_VXC_2Weight.h\"\r\n#include \"WeightedMeshVS_VXC_3Weight.h\"\r\n\r\n#include \"WeightedMeshVS_VXC_Specular_1Weight.h\"\r\n#include \"WeightedMeshVS_VXC_Specular_2Weight.h\"\r\n#include \"WeightedMeshVS_VXC_Specular_3Weight.h\"\r\n\r\n#include \"WeightedMeshVS_VXC_1Weight_UVTransform.h\"\r\n#include \"WeightedMeshVS_VXC_2Weight_UVTransform.h\"\r\n#include \"WeightedMeshVS_VXC_3Weight_UVTransform.h\"\r\n\r\n#include \"WeightedMeshVS_VXC_1Weight_SBPassThru.h\"\r\n#include \"WeightedMeshVS_VXC_2Weight_SBPassThru.h\"\r\n#include \"WeightedMeshVS_VXC_3Weight_SBPassThru.h\"\r\n\r\n#include \"WeightedMeshVertexShader_SBWrite.h\"\r\n#include \"ShadowBufferStaticGeomVS.h\"\r\n#include \"BillboardScreenAlignedVS.h\"\r\n#include \"ParticleFlatVS.h\"\r\n#include \"ParticleNewFlatVS.h\"\r\n#include \"ParticleNewFlatPointSpriteVS.h\"\r\n\r\nDWORD WeightedMeshVS_VXC_1Weight;\r\nDWORD WeightedMeshVS_VXC_2Weight;\r\nDWORD WeightedMeshVS_VXC_3Weight;\r\nDWORD WeightedMeshVS_VXC_Specular_1Weight;\r\nDWORD WeightedMeshVS_VXC_Specular_2Weight;\r\nDWORD WeightedMeshVS_VXC_Specular_3Weight;\r\nDWORD WeightedMeshVS_VXC_1Weight_UVTransform;\r\nDWORD WeightedMeshVS_VXC_2Weight_UVTransform;\r\nDWORD WeightedMeshVS_VXC_3Weight_UVTransform;\r\nDWORD WeightedMeshVertexShader_SBWrite;\r\nDWORD WeightedMeshVS_VXC_1Weight_SBPassThru;\r\nDWORD WeightedMeshVS_VXC_2Weight_SBPassThru;\r\nDWORD WeightedMeshVS_VXC_3Weight_SBPassThru;\r\nDWORD WeightedMeshVertexShader_VXC_SBPassThru;\r\nDWORD BillboardScreenAlignedVS;\r\nDWORD ParticleFlatVS;\r\nDWORD ParticleNewFlatVS;\r\nDWORD ParticleNewFlatPointSpriteVS;\r\nDWORD ShadowBufferStaticGeomVS;\r\n\r\nnamespace NxXbox\r\n{\r\n\t// Vertex color attenuation, 4 sets of tex coords.\r\n\tstatic DWORD WeightedMeshVertexShaderVertColUV4Decl[] = {\r\n\tD3DVSD_STREAM( 0 ),\r\n\tD3DVSD_REG( VSD_REG_POS,\t\tD3DVSDT_FLOAT3 ),\t\t// Position.\r\n\tD3DVSD_REG( VSD_REG_WEIGHTS,\tD3DVSDT_NORMPACKED3 ),\t// Weights.\r\n\tD3DVSD_REG( VSD_REG_INDICES,\tD3DVSDT_SHORT4 ),\t\t// Indices.\r\n\tD3DVSD_REG( VSD_REG_NORMAL,\t\tD3DVSDT_NORMPACKED3 ),\t// Normals.\r\n\tD3DVSD_REG( VSD_REG_COLOR,\t\tD3DVSDT_D3DCOLOR ),\t\t// Diffuse color.\r\n\tD3DVSD_REG( VSD_REG_TEXCOORDS0,\tD3DVSDT_FLOAT2 ),\t\t// Texture coordinates 0.\r\n\tD3DVSD_REG( VSD_REG_TEXCOORDS1,\tD3DVSDT_FLOAT2 ),\t\t// Texture coordinates 1.\r\n\tD3DVSD_REG( VSD_REG_TEXCOORDS2,\tD3DVSDT_FLOAT2 ),\t\t// Texture coordinates 2.\r\n\tD3DVSD_REG( VSD_REG_TEXCOORDS3,\tD3DVSDT_FLOAT2 ),\t\t// Texture coordinates 3.\r\n\tD3DVSD_END() };\r\n\t\r\n\t// Billboards.\r\n\tstatic DWORD BillboardVSDecl[] = {\r\n\tD3DVSD_STREAM( 0 ),\r\n\tD3DVSD_REG( 0,\tD3DVSDT_FLOAT3 ),\t\t// Position (actually pivot position).\r\n\tD3DVSD_REG( 1,\tD3DVSDT_FLOAT3 ),\t\t// Normal (actually position of point relative to pivot).\r\n\tD3DVSD_REG( 2,\tD3DVSDT_D3DCOLOR ),\t\t// Diffuse color.\r\n\tD3DVSD_REG( 3,\tD3DVSDT_FLOAT2 ),\t\t// Texture coordinates 0.\r\n\tD3DVSD_REG( 4,\tD3DVSDT_FLOAT2 ),\t\t// Texture coordinates 1.\r\n\tD3DVSD_REG( 5,\tD3DVSDT_FLOAT2 ),\t\t// Texture coordinates 2.\r\n\tD3DVSD_REG( 6,\tD3DVSDT_FLOAT2 ),\t\t// Texture coordinates 3.\r\n\tD3DVSD_END() };\r\n\r\n\t// Particles.\r\n\tstatic DWORD ParticleFlatVSDecl[] = {\r\n\tD3DVSD_STREAM( 0 ),\r\n\tD3DVSD_REG( 0,\tD3DVSDT_D3DCOLOR ),\t\t// Diffuse color (start)\r\n\tD3DVSD_REG( 1,\tD3DVSDT_D3DCOLOR ),\t\t// Diffuse color (end)\r\n\tD3DVSD_REG( 2,\tD3DVSDT_SHORT2 ),\t\t// Indices.\r\n\tD3DVSD_END() };\r\n\r\n\t// New, Ps2 style particles using PointSprites.\r\n\tstatic DWORD NewParticleFlatVSDecl[] = {\r\n\tD3DVSD_STREAM( 0 ),\r\n\tD3DVSD_REG( 0,\tD3DVSDT_FLOAT4 ),\t\t// Random 4-element 'R' vector.\r\n\tD3DVSD_REG( 1,\tD3DVSDT_FLOAT2 ),\t\t// Time and color interpolator.\r\n\tD3DVSD_REG( 2,\tD3DVSDT_D3DCOLOR ),\t\t// Diffuse color (start)\r\n\tD3DVSD_REG( 3,\tD3DVSDT_D3DCOLOR ),\t\t// Diffuse color (end)\r\n\tD3DVSD_END() };\r\n\r\n\t// Shadow buffer, static geom.\r\n\tstatic DWORD ShadowBufferStaticGeomVSDecl[] = {\r\n\tD3DVSD_STREAM( 0 ),\r\n\tD3DVSD_REG( 0,\tD3DVSDT_FLOAT3 ),\t\t// Position.\r\n\tD3DVSD_REG( 1,\tD3DVSDT_D3DCOLOR ),\t\t// Diffuse color.\r\n\tD3DVSD_REG( 2,\tD3DVSDT_FLOAT2 ),\t\t// Texture coordinates 0.\r\n\tD3DVSD_REG( 3,\tD3DVSDT_FLOAT2 ),\t\t// Texture coordinates 1.\r\n\tD3DVSD_REG( 4,\tD3DVSDT_FLOAT2 ),\t\t// Texture coordinates 2.\r\n\tD3DVSD_END() };\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nDWORD GetVertexShader( bool vertex_colors, bool specular, uint32 max_weights_used )\r\n{\r\n\tDbg_Assert( max_weights_used > 0 );\r\n\t\r\n\tif( vertex_colors )\r\n\t{\r\n\t\tif( max_weights_used == 1 )\r\n\t\t{\r\n\t\t\treturn ( specular ) ? WeightedMeshVS_VXC_Specular_1Weight : WeightedMeshVS_VXC_1Weight;\r\n\t\t}\r\n\t\telse if( max_weights_used == 2 )\r\n\t\t{\r\n\t\t\treturn ( specular ) ? WeightedMeshVS_VXC_Specular_2Weight : WeightedMeshVS_VXC_2Weight;\r\n\t\t}\r\n\t\telse if( max_weights_used == 3 )\r\n\t\t{\r\n\t\t\treturn ( specular ) ? WeightedMeshVS_VXC_Specular_3Weight : WeightedMeshVS_VXC_3Weight;\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_Assert( 0 );\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CreateWeightedMeshVertexShaders( void )\r\n{\r\n\tstatic bool created_shaders = false;\r\n\r\n\tif( !created_shaders )\r\n\t{\r\n\t\tcreated_shaders = true;\r\n\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShaderVertColUV4Decl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedMeshVS_VXC_1WeightVertexShader,\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVS_VXC_1Weight,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShaderVertColUV4Decl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedMeshVS_VXC_2WeightVertexShader,\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVS_VXC_2Weight,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShaderVertColUV4Decl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedMeshVS_VXC_3WeightVertexShader,\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVS_VXC_3Weight,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShaderVertColUV4Decl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedMeshVS_VXC_Specular_1WeightVertexShader,\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVS_VXC_Specular_1Weight,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShaderVertColUV4Decl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedMeshVS_VXC_Specular_2WeightVertexShader,\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVS_VXC_Specular_2Weight,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShaderVertColUV4Decl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedMeshVS_VXC_Specular_3WeightVertexShader,\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVS_VXC_Specular_3Weight,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShaderVertColUV4Decl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedMeshVS_VXC_1Weight_UVTransformVertexShader,\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVS_VXC_1Weight_UVTransform,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShaderVertColUV4Decl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedMeshVS_VXC_2Weight_UVTransformVertexShader,\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVS_VXC_2Weight_UVTransform,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShaderVertColUV4Decl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedMeshVS_VXC_3Weight_UVTransformVertexShader,\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVS_VXC_3Weight_UVTransform,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShaderVertColUV4Decl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedMeshVertexShader_SBWriteVertexShader,\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVertexShader_SBWrite,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShaderVertColUV4Decl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedMeshVS_VXC_1Weight_SBPassThruVertexShader,\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVS_VXC_1Weight_SBPassThru,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShaderVertColUV4Decl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedMeshVS_VXC_2Weight_SBPassThruVertexShader,\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVS_VXC_2Weight_SBPassThru,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tWeightedMeshVertexShaderVertColUV4Decl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwWeightedMeshVS_VXC_3Weight_SBPassThruVertexShader,\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&WeightedMeshVS_VXC_3Weight_SBPassThru,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tBillboardVSDecl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwBillboardScreenAlignedVSVertexShader,\t\t\t\t\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&BillboardScreenAlignedVS,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\r\n\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tParticleFlatVSDecl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwParticleFlatVSVertexShader,\t\t\t\t\t\t\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&ParticleFlatVS,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tParticleFlatVSDecl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwParticleNewFlatVSVertexShader,\t\t\t\t\t\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&ParticleNewFlatVS,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tNewParticleFlatVSDecl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwParticleNewFlatPointSpriteVSVertexShader,\t\t\t\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&ParticleNewFlatPointSpriteVS,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\t\tif( D3D_OK != D3DDevice_CreateVertexShader(\tShadowBufferStaticGeomVSDecl,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tdwShadowBufferStaticGeomVSVertexShader,\t\t\t\t\t// Defined in the header file from xsasm.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t&ShadowBufferStaticGeomVS,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid setup_weighted_mesh_vertex_shader( void *p_root_matrix, void *p_bone_matrices, int num_bone_matrices )\r\n{\r\n\tXGMATRIX\tdest_matrix;\r\n\tXGMATRIX\tinverse_view_matrix;\r\n\tXGMATRIX\ttemp_matrix;\r\n\tXGMATRIX\tprojMatrix;\r\n\tXGMATRIX\tviewMatrix;\r\n\tXGMATRIX\tworldMatrix;\r\n\r\n\t// Projection matrix.\r\n\tXGMatrixTranspose( &projMatrix, &EngineGlobals.projection_matrix );\r\n\t\r\n\t// View matrix.\r\n\tXGMatrixTranspose( &viewMatrix, &EngineGlobals.view_matrix );\r\n    viewMatrix.m[3][0] = 0.0f;\r\n    viewMatrix.m[3][1] = 0.0f;\r\n    viewMatrix.m[3][2] = 0.0f;\r\n    viewMatrix.m[3][3] = 1.0f;\r\n\t\r\n\t// World space transformation matrix. (3x3 rotation plus 3 element translation component).\r\n\tworldMatrix.m[0][0] = ((float*)p_root_matrix )[0];\r\n\tworldMatrix.m[0][1] = ((float*)p_root_matrix )[1];\r\n\tworldMatrix.m[0][2] = ((float*)p_root_matrix )[2];\r\n\tworldMatrix.m[0][3] = ((float*)p_root_matrix )[3];\r\n\tworldMatrix.m[1][0] = ((float*)p_root_matrix )[4];\r\n\tworldMatrix.m[1][1] = ((float*)p_root_matrix )[5];\r\n\tworldMatrix.m[1][2] = ((float*)p_root_matrix )[6];\r\n\tworldMatrix.m[1][3] = ((float*)p_root_matrix )[7];\r\n\tworldMatrix.m[2][0] = ((float*)p_root_matrix )[8];\r\n\tworldMatrix.m[2][1] = ((float*)p_root_matrix )[9];\r\n\tworldMatrix.m[2][2] = ((float*)p_root_matrix )[10];\r\n\tworldMatrix.m[2][3] = ((float*)p_root_matrix )[11];\r\n\tworldMatrix.m[3][0] = 0.0f;\r\n\tworldMatrix.m[3][1] = 0.0f;\r\n\tworldMatrix.m[3][2] = 0.0f;\r\n\tworldMatrix.m[3][3] = 1.0f;\r\n\r\n\t// Calculate composite world->view->projection matrix.\r\n\tXGMatrixMultiply( &temp_matrix, &viewMatrix, &worldMatrix );\r\n\tXGMatrixMultiply( &dest_matrix, &projMatrix, &temp_matrix );\r\n\r\n\t// Switch to 192 constant mode, removing the lock on the reserved constants c-38 and c-37.\r\n//\tD3DDevice_SetShaderConstantMode( D3DSCM_192CONSTANTS | D3DSCM_NORESERVEDCONSTANTS );\r\n\r\n\t// Load up the combined world, camera & projection matrix.\r\n\tD3DDevice_SetVertexShaderConstantFast( VSCONST_REG_TRANSFORM_OFFSET, (void*)&dest_matrix, VSCONST_REG_TRANSFORM_SIZE );\r\n\tD3DDevice_SetVertexShaderConstantFast( VSCONST_REG_WORLD_TRANSFORM_OFFSET,\t(void*)&worldMatrix, VSCONST_REG_WORLD_TRANSFORM_SIZE );\r\n\r\n\t// We want to transform the light directions by the inverse of the world transform - this means we don't have to transform\r\n\t// the normal by the world transform for every vertex in the vertex shader. However, the function D3DXVec3TransformNormal\r\n\t// (used below) does the inverse transform for us, so need to actually figure the inverse...\r\n//\tXGMATRIX inverse_world_transform = worldMatrix;\r\n//\tD3DXMatrixInverse( &inverse_world_transform, NULL, &worldMatrix );\r\n\r\n\tfloat directional_light_color[24];\r\n\tCopyMemory( directional_light_color, EngineGlobals.directional_light_color, sizeof( float ) * 24 );\r\n\t\r\n\tXGVec3TransformNormal((XGVECTOR3*)&directional_light_color[0],\t(XGVECTOR3*)&EngineGlobals.directional_light_color[0], &worldMatrix );\r\n\tXGVec3TransformNormal((XGVECTOR3*)&directional_light_color[8],\t(XGVECTOR3*)&EngineGlobals.directional_light_color[8], &worldMatrix );\r\n\tXGVec3TransformNormal((XGVECTOR3*)&directional_light_color[16],\t(XGVECTOR3*)&EngineGlobals.directional_light_color[16], &worldMatrix );\r\n\t\r\n\tXGVec3Normalize((XGVECTOR3*)&directional_light_color[0], (XGVECTOR3*)&directional_light_color[0] ); \r\n\tXGVec3Normalize((XGVECTOR3*)&directional_light_color[8], (XGVECTOR3*)&directional_light_color[8] ); \r\n\tXGVec3Normalize((XGVECTOR3*)&directional_light_color[16], (XGVECTOR3*)&directional_light_color[16] ); \r\n\r\n\t// Load up the directional light data.\r\n\tD3DDevice_SetVertexShaderConstantFast( VSCONST_REG_DIR_LIGHT_OFFSET, (void*)directional_light_color, 6 );\r\n\r\n\t// Load up the ambient light color.\r\n\tD3DDevice_SetVertexShaderConstantFast( VSCONST_REG_AMB_LIGHT_OFFSET, (void*)EngineGlobals.ambient_light_color, 1 );\r\n\t\r\n\t// Calculate and load up the model-relative camera position.\r\n\tEngineGlobals.model_relative_cam_position = XGVECTOR3( EngineGlobals.cam_position.x - worldMatrix.m[0][3],\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   EngineGlobals.cam_position.y - worldMatrix.m[1][3],\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   EngineGlobals.cam_position.z - worldMatrix.m[2][3] );\r\n\tXGVec3TransformNormal( &EngineGlobals.model_relative_cam_position, &EngineGlobals.model_relative_cam_position, &worldMatrix );\r\n\r\n\tfloat specular_attribs[4] = { EngineGlobals.model_relative_cam_position.x,\r\n\t\t\t\t\t\t\t\t  EngineGlobals.model_relative_cam_position.y,\r\n\t\t\t\t\t\t\t\t  EngineGlobals.model_relative_cam_position.z,\r\n\t\t\t\t\t\t\t\t  0.0f };\r\n\tD3DDevice_SetVertexShaderConstantFast( VSCONST_REG_CAM_POS_OFFSET, (void*)&specular_attribs, 1 );\r\n\r\n\t// Safety check here to limit number of bones to that available.\r\n\tif( num_bone_matrices > 55 )\r\n\t{\r\n\t\tnum_bone_matrices = 55;\r\n\t}\r\n\r\n\tDWORD*\tp_bone_element\t= (DWORD*)p_bone_matrices;\r\n\r\n\t// Begin state block to set vertex shader constants for bone transforms.\r\n\tDWORD *p_push;\r\n\tEngineGlobals.p_Device->BeginState(( num_bone_matrices * ( 12 + 1 )) + 3, &p_push );\r\n\r\n\t// 1 here isn't the parameter for SET_TRANSFORM_CONSTANT_LOAD; rather, it's the number of dwords written to that register.\r\n\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_TRANSFORM_CONSTANT_LOAD, 1 ); \r\n\r\n\t// Here is the actual parameter for SET_TRANSFORM_CONSTANT_LOAD. Always add 96 to the constant register.\r\n\tp_push[1] = VSCONST_REG_MATRIX_OFFSET + 96;\r\n\r\n\tp_push += 2;\r\n\r\n\twhile( num_bone_matrices > 0 )\r\n\t{\r\n\t\t// A 3x4 matrix is 12 dwords. You can encode a maximum of 32 dwords to D3DPUSH_SET_TRANSFORM_CONSTANT before needing another D3DPUSH_ENCODE.\r\n\t\tp_push[0]\t\t= D3DPUSH_ENCODE( D3DPUSH_SET_TRANSFORM_CONSTANT, 12 );\r\n\r\n\t\tp_push[1]\t\t= p_bone_element[0];\r\n\t\tp_push[2]\t\t= p_bone_element[4];\r\n\t\tp_push[3]\t\t= p_bone_element[8];\r\n\t\tp_push[4]\t\t= p_bone_element[12];\r\n\r\n\t\tp_push[5]\t\t= p_bone_element[1];\r\n\t\tp_push[6]\t\t= p_bone_element[5];\r\n\t\tp_push[7]\t\t= p_bone_element[9];\r\n\t\tp_push[8]\t\t= p_bone_element[13];\r\n\r\n\t\tp_push[9]\t\t= p_bone_element[2];\r\n\t\tp_push[10]\t\t= p_bone_element[6];\r\n\t\tp_push[11]\t\t= p_bone_element[10];\r\n\t\tp_push[12]\t\t= p_bone_element[14];\r\n\r\n\t\t--num_bone_matrices;\r\n\r\n\t\tp_bone_element\t+= 16;\r\n\t\tp_push\t\t\t+= 13;\r\n\t}\r\n\r\n\tEngineGlobals.p_Device->EndState( p_push );\r\n\r\n\t// Load up the replacement registers for c-38 and c-37\r\n\t// The z value is 2^24 - to take 1.0f to the max z buffer value for a 24bit z buffer.\r\n\tstatic float homogenous_to_screen_reg[8] = { 320.0f, -240.0f, 1.6777215e7f, 0.0f, 320.53125f, 240.53125f, 0.0f, 0.0f };\r\n\t\r\n\tif( EngineGlobals.is_orthographic )\r\n\t{\r\n\t\thomogenous_to_screen_reg[0] = 128.0f;\r\n\t\thomogenous_to_screen_reg[1] = -128.0f;\r\n\r\n\t\thomogenous_to_screen_reg[2] = 1.6777215e7f;\r\n\t\t\r\n\t\thomogenous_to_screen_reg[4] = 128.53125f;\r\n\t\thomogenous_to_screen_reg[5] = 128.53125f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\thomogenous_to_screen_reg[0] = (float)EngineGlobals.viewport.Width * 0.5f;\r\n\t\thomogenous_to_screen_reg[1] = (float)EngineGlobals.viewport.Height * -0.5f;\r\n\r\n\t\thomogenous_to_screen_reg[2] = ( EngineGlobals.zstencil_depth == 16 ) ? 65535.0f : 1.6777215e7f;\r\n\r\n\t\thomogenous_to_screen_reg[4] = (float)NxXbox::EngineGlobals.viewport.X + ((float)NxXbox::EngineGlobals.viewport.Width * 0.5f ) + 0.53125f;\r\n\t\thomogenous_to_screen_reg[5] = (float)NxXbox::EngineGlobals.viewport.Y + ((float)NxXbox::EngineGlobals.viewport.Height * 0.5f ) + 0.53125f;\r\n\t}\r\n\r\n\tD3DDevice_SetVertexShaderConstantFast( 94, (void*)homogenous_to_screen_reg, 2 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid startup_weighted_mesh_vertex_shader( void )\r\n{\r\n\t// Switch to 192 constant mode, removing the lock on the reserved constants c-38 and c-37.\r\n\tD3DDevice_SetShaderConstantMode( D3DSCM_192CONSTANTS | D3DSCM_NORESERVEDCONSTANTS );\r\n\r\n\t// Flag the custom pipeline is in operation.\r\n\tEngineGlobals.custom_pipeline_enabled = true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid shutdown_weighted_mesh_vertex_shader( void )\r\n{\r\n\t// Switch back to 96 constant mode.\r\n\tD3DDevice_SetShaderConstantMode( D3DSCM_96CONSTANTS );\r\n\r\n\t// Flag the custom pipeline is no longer in operation.\r\n\tEngineGlobals.custom_pipeline_enabled = false;\r\n}\r\n\r\n\r\n} // namespace NxXbox"
  },
  {
    "path": "Code/Gfx/XBox/NX/anim.h",
    "content": "#ifndef __ANIM_H\r\n#define __ANIM_H\r\n\r\nextern DWORD WeightedMeshVS_VXC_1Weight;\r\nextern DWORD WeightedMeshVS_VXC_2Weight;\r\nextern DWORD WeightedMeshVS_VXC_3Weight;\r\nextern DWORD WeightedMeshVS_VXC_Specular_1Weight;\r\nextern DWORD WeightedMeshVS_VXC_Specular_2Weight;\r\nextern DWORD WeightedMeshVS_VXC_Specular_3Weight;\r\nextern DWORD WeightedMeshVS_VXC_1Weight_UVTransform;\r\nextern DWORD WeightedMeshVS_VXC_2Weight_UVTransform;\r\nextern DWORD WeightedMeshVS_VXC_3Weight_UVTransform;\r\nextern DWORD WeightedMeshVS_VXC_1Weight_SBPassThru;\r\nextern DWORD WeightedMeshVS_VXC_2Weight_SBPassThru;\r\nextern DWORD WeightedMeshVS_VXC_3Weight_SBPassThru;\r\nextern DWORD WeightedMeshVertexShader_SBWrite;\r\nextern DWORD BillboardScreenAlignedVS;\r\nextern DWORD ParticleFlatVS;\r\nextern DWORD ParticleNewFlatVS;\r\nextern DWORD ParticleNewFlatPointSpriteVS;\r\nextern DWORD ShadowBufferStaticGeomVS;\r\n\r\nnamespace NxXbox\r\n{\r\n\r\nDWORD\tGetVertexShader( bool vertex_colors, bool specular, uint32 max_weights_used );\r\nvoid\tCreateWeightedMeshVertexShaders( void );\r\nvoid\tstartup_weighted_mesh_vertex_shader( void );\r\nvoid\tsetup_weighted_mesh_vertex_shader( void *p_root_matrix, void *p_bone_matrices, int num_bone_matrices );\r\nvoid\tshutdown_weighted_mesh_vertex_shader( void );\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n#endif // __ANIM_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/anim_vertdefs.h",
    "content": "#ifndef ANIM_VERTDEFS_H\r\n#define ANIM_VERTDEFS_H\r\n\r\n// Used in the vertex shader descriptor.\r\n#define VSD_REG_POS                     0\r\n#define VSD_REG_WEIGHTS                 1\r\n#define VSD_REG_INDICES                 2\r\n#define VSD_REG_NORMAL                  3\r\n#define VSD_REG_COLOR                   4\r\n#define VSD_REG_TEXCOORDS0              5\r\n#define VSD_REG_TEXCOORDS1              6\r\n#define VSD_REG_TEXCOORDS2              7\r\n#define VSD_REG_TEXCOORDS3              8\r\n\r\n// Input register - used in the vertex shader code.\r\n#define VSIN_REG_POS                    v0\r\n#define VSIN_REG_WEIGHTS                v1\r\n#define VSIN_REG_INDICES                v2\r\n#define VSIN_REG_NORMAL                 v3\r\n#define VSIN_REG_COLOR                  v4\r\n#define VSIN_REG_TEXCOORDS0             v5\r\n#define VSIN_REG_TEXCOORDS1             v6\r\n#define VSIN_REG_TEXCOORDS2             v7\r\n#define VSIN_REG_TEXCOORDS3             v8\r\n\r\n// Temporary register - used in the vertex shader code.\r\n#define VSTMP_REG_POS_TMP               r0\r\n#define VSTMP_REG_POS_ACCUM             r1\r\n#define VSTMP_REG_NORMAL_TMP            r2\r\n#define VSTMP_REG_NORMAL_ACCUM          r3\r\n#define VSTMP_REG_MAT0\t\t\t\t\tr8\r\n#define VSTMP_REG_MAT1\t\t\t\t\tr9\r\n#define VSTMP_REG_MAT2\t\t\t\t\tr10\r\n\r\n// Vertex shader defines.\r\n#define VSCONST_REG_BASE\t\t\t\t\t-96\t// Don't have to worry about the constant -38 and -37, we are not using them.\r\n\r\n#define VSCONST_REG_TRANSFORM_OFFSET\t\tVSCONST_REG_BASE\r\n#define VSCONST_REG_TRANSFORM_SIZE\t\t\t4\r\n\r\n#define VSCONST_REG_WORLD_TRANSFORM_OFFSET\tVSCONST_REG_TRANSFORM_OFFSET + VSCONST_REG_TRANSFORM_SIZE\r\n#define VSCONST_REG_WORLD_TRANSFORM_SIZE\t3\r\n\r\n#define VSCONST_REG_DIR_LIGHT_OFFSET\t\tVSCONST_REG_WORLD_TRANSFORM_OFFSET + VSCONST_REG_WORLD_TRANSFORM_SIZE\r\n#define VSCONST_REG_DIR_LIGHT_SIZE\t\t\t6\t// Support for 3 directional lights.\r\n\r\n#define VSCONST_REG_AMB_LIGHT_OFFSET\t\tVSCONST_REG_DIR_LIGHT_OFFSET + VSCONST_REG_DIR_LIGHT_SIZE\r\n#define VSCONST_REG_AMB_LIGHT_SIZE\t\t\t1\r\n\r\n#define VSCONST_REG_CAM_POS_OFFSET\t\t\tVSCONST_REG_AMB_LIGHT_OFFSET + VSCONST_REG_AMB_LIGHT_SIZE\r\n#define VSCONST_REG_CAM_POS_SIZE\t\t\t1\r\n\r\n#define VSCONST_REG_SPECULAR_COLOR_OFFSET\tVSCONST_REG_CAM_POS_OFFSET + VSCONST_REG_CAM_POS_SIZE\r\n#define VSCONST_REG_SPECULAR_COLOR_SIZE\t\t1\r\n\r\n#define VSCONST_REG_UV_MAT_OFFSET\t\t\tVSCONST_REG_SPECULAR_COLOR_OFFSET + VSCONST_REG_SPECULAR_COLOR_SIZE\r\n#define VSCONST_REG_UV_MAT_SIZE\t\t\t\t8\r\n\r\n\r\n//#define VSCONST_REG_MATRIX_OFFSET\t\t\t( VSCONST_REG_UV_MAT_OFFSET + VSCONST_REG_UV_MAT_SIZE )\r\n#define VSCONST_REG_MATRIX_OFFSET\t\t\t-72\r\n\r\n// Constant registers - used in the vertex shader code.\r\n#define VSCONST_REG_TRANSFORM_X\t\t\t\t\tc[0 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_TRANSFORM_Y\t\t\t\t\tc[1 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_TRANSFORM_Z\t\t\t\t\tc[2 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_TRANSFORM_W\t\t\t\t\tc[3 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_WORLD_TRANSFORM_X\t\t\tc[4 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_WORLD_TRANSFORM_Y\t\t\tc[5 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_WORLD_TRANSFORM_Z\t\t\tc[6 + VSCONST_REG_BASE]\r\n\r\n#define VSCONST_REG_LIGHT_DIR0\t\t\t\t\tc[7 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_LIGHT_COLOR0\t\t\t\tc[8 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_LIGHT_DIR1\t\t\t\t\tc[9 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_LIGHT_COLOR1\t\t\t\tc[10 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_LIGHT_DIR2\t\t\t\t\tc[11 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_LIGHT_COLOR2\t\t\t\tc[12 + VSCONST_REG_BASE]\r\n\r\n// Shadowbuffer transform shares space with lighting params, since both not required at the same time.\r\n#define VSCONST_REG_SHADOWBUFFER_TRANSFORM_X\tc[7 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_SHADOWBUFFER_TRANSFORM_Y\tc[8 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_SHADOWBUFFER_TRANSFORM_Z\tc[9 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_SHADOWBUFFER_TRANSFORM_W\tc[10 + VSCONST_REG_BASE]\r\n\r\n#define VSCONST_REG_AMB_LIGHT_COLOR\t\t\t\tc[13 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_CAM_POS\t\t\t\t\t\tc[14 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_SPECULAR_COLOR\t\t\t\tc[15 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_UV_MAT00\t\t\t\t\tc[16 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_UV_MAT01\t\t\t\t\tc[17 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_UV_MAT10\t\t\t\t\tc[18 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_UV_MAT11\t\t\t\t\tc[19 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_UV_MAT20\t\t\t\t\tc[20 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_UV_MAT21\t\t\t\t\tc[21 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_UV_MAT30\t\t\t\t\tc[22 + VSCONST_REG_BASE]\r\n#define VSCONST_REG_UV_MAT31\t\t\t\t\tc[23 + VSCONST_REG_BASE]\r\n\r\n#endif // ANIM_VERTDEFS_H"
  },
  {
    "path": "Code/Gfx/XBox/NX/billboard.cpp",
    "content": "#include \"billboard.h\"\r\n#include \"nx_init.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\nsBillboardManager BillboardManager;\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsBillboardManager::sBillboardManager( void )\r\n{\r\n\tm_num_batches\t= 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsBillboardManager::~sBillboardManager( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int sort_batches_by_draw_order( const void *p1, const void *p2 )\r\n{\r\n\tsBillboardMaterialBatch *p_batch0 = *((sBillboardMaterialBatch**)p1 );\r\n\tsBillboardMaterialBatch *p_batch1 = *((sBillboardMaterialBatch**)p2 );\r\n\r\n\t// Deal with NULL pointers first (caused by removing batches from the list).\r\n\tif( p_batch0 == NULL )\r\n\t{\r\n\t\tif( p_batch1 == NULL )\r\n\t\t{\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t}\r\n\telse if( p_batch1 == NULL )\r\n\t{\r\n\t\treturn -1;\r\n\t}\r\n\r\n\treturn p_batch0->GetDrawOrder() < p_batch1->GetDrawOrder() ? -1 : p_batch0->GetDrawOrder() > p_batch1->GetDrawOrder() ? 1 : 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsBillboardMaterialBatch *sBillboardManager::GetBatch( sMaterial *p_material )\r\n{\r\n\tfor( int b = 0; b < m_num_batches; ++b )\r\n\t{\r\n\t\tif( mp_batches[b]->GetMaterial() == p_material )\r\n\t\t{\r\n\t\t\treturn mp_batches[b];\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sBillboardManager::AddEntry( sMesh *p_mesh )\r\n{\r\n\tif( p_mesh->mp_material )\r\n\t{\r\n\t\t// Make sure it is textured.\r\n\t\tif( p_mesh->mp_material->mp_tex[0] != NULL )\r\n\t\t{\r\n\t\t\tsBillboardMaterialBatch *p_batch = GetBatch( p_mesh->mp_material );\r\n\t\t\tif( p_batch == NULL )\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( m_num_batches < ( MAX_BILLBOARD_BATCHES - 1 ));\r\n\r\n\t\t\t\t// Need to create a new batch for this material.\r\n\t\t\t\tp_batch = new sBillboardMaterialBatch( p_mesh->mp_material );\r\n\t\t\t\tmp_batches[m_num_batches++]\t= p_batch;\r\n\r\n\t\t\t\t// Resort the list of batches.\r\n\t\t\t\tSortBatches();\r\n\t\t\t}\r\n\r\n\t\t\t// Now add the mesh to this batch.\r\n\t\t\tp_batch->AddEntry( p_mesh );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sBillboardManager::RemoveEntry( sMesh *p_mesh )\r\n{\r\n\tif( p_mesh->mp_material )\r\n\t{\r\n\t\tsBillboardMaterialBatch *p_batch = GetBatch( p_mesh->mp_material );\r\n\t\tif( p_batch )\r\n\t\t{\r\n\t\t\t// Removes the entry if it exists.\r\n\t\t\tp_batch->RemoveEntry( p_mesh );\r\n\r\n\t\t\t// If the batch is now empty, remove it.\r\n\t\t\tif( p_batch->IsEmpty())\r\n\t\t\t{\r\n\t\t\t\tfor( int i = 0; i < m_num_batches; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( mp_batches[i] == p_batch )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdelete p_batch;\r\n\t\t\t\t\t\tmp_batches[i] = NULL;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Resort the batches (will move the NULL pointer to the end).\r\n\t\t\t\tSortBatches();\r\n\r\n\t\t\t\t// Important not to decrement this until after the resort has been performed.\r\n\t\t\t\t--m_num_batches;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sBillboardManager::SortBatches( void )\r\n{\r\n\tqsort( mp_batches, m_num_batches, sizeof( sBillboardMaterialBatch* ), sort_batches_by_draw_order );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sBillboardManager::SetCameraMatrix( void )\r\n{\r\n\tMth::Vector up( 0.0f, 1.0f, 0.0f );\r\n\r\n\tm_at.Set( NxXbox::EngineGlobals.view_matrix.m[0][2], NxXbox::EngineGlobals.view_matrix.m[1][2], NxXbox::EngineGlobals.view_matrix.m[2][2] );\r\n\tm_screen_right\t\t= Mth::CrossProduct( m_at, up ).Normalize();\r\n\tm_screen_up\t\t\t= Mth::CrossProduct( m_screen_right, m_at ).Normalize();\r\n\tm_at_xz\t\t\t\t= Mth::Vector( m_at[X], 0.0f, m_at[Z] ).Normalize();\r\n\tm_screen_right_xz\t= Mth::Vector( m_screen_right[X], 0.0f, m_screen_right[Z] ).Normalize();\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sBillboardManager::Render( uint32 flags )\r\n{\r\n\t// Render the opaque billboards if requested.\r\n\tif( flags & vRENDER_OPAQUE )\r\n\t{\r\n\t\tfor( int b = 0; b < m_num_batches; ++b )\r\n\t\t{\r\n\t\t\tif( !( mp_batches[b]->mp_material->m_flags[0] & 0x40 ))\r\n\t\t\t{\r\n\t\t\t\tmp_batches[b]->Render();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Render the semitransparent billboards if requested.\r\n\tif( flags & vRENDER_SEMITRANSPARENT )\r\n\t{\r\n\t\tfor( int b = 0; b < m_num_batches; ++b )\r\n\t\t{\r\n\t\t\tif( mp_batches[b]->mp_material->m_flags[0] & 0x40 )\r\n\t\t\t{\r\n\t\t\t\tmp_batches[b]->Render();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsBillboardMaterialBatch::sBillboardMaterialBatch( sMaterial *p_material )\r\n{\r\n\tmp_material\t\t= p_material;\r\n\tmp_entries[0]\t= new Lst::Head <sBillboardEntry>;\r\n\tmp_entries[1]\t= new Lst::Head <sBillboardEntry>;\r\n\tmp_entries[2]\t= new Lst::Head <sBillboardEntry>;\r\n\r\n\t// We can calculate what the per-entry size will be based on the material properties.\r\n\tm_entry_size\t = 4 * sizeof( float ) * 3;\t\t\t\t\t\t\t// Four vertex positions.\r\n\tm_entry_size\t+= 4 * sizeof( D3DCOLOR );\t\t\t\t\t\t\t// Four vertex colors.\r\n\tm_entry_size\t+= 4 * sizeof( float ) * 2 * p_material->m_passes;\t// Four uv pairs for each pass.\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsBillboardMaterialBatch::~sBillboardMaterialBatch( void )\r\n{\r\n\tdelete mp_entries[0];\r\n\tdelete mp_entries[1];\r\n\tdelete mp_entries[2];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool sBillboardMaterialBatch::IsEmpty( void )\r\n{\r\n\treturn ( mp_entries[0]->IsEmpty() && mp_entries[1]->IsEmpty() && mp_entries[2]->IsEmpty());\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nfloat sBillboardMaterialBatch::GetDrawOrder( void )\r\n{\r\n\treturn mp_material ? mp_material->m_draw_order : 0.0f;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsMaterial *sBillboardMaterialBatch::GetMaterial( void )\r\n{\r\n\treturn mp_material;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sBillboardMaterialBatch::AddEntry( sMesh *p_mesh )\r\n{\r\n\t// Create a new billboard entry.\r\n\tsBillboardEntry *p_entry = new sBillboardEntry( p_mesh );\r\n\r\n\t// And a new node.\r\n\tLst::Node<sBillboardEntry> *node = new Lst::Node<sBillboardEntry>( p_entry );\r\n\r\n\tmp_entries[p_entry->m_type]->AddToTail( node );\r\n\r\n\t// Now process the mesh.\r\n\tProcessMesh( p_mesh );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sBillboardMaterialBatch::ProcessMesh( sMesh *p_mesh )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sBillboardMaterialBatch::RemoveEntry( sMesh *p_mesh )\r\n{\r\n\tfor( int e = 0; e < 3; ++e )\r\n\t{\r\n\t\tLst::Node<sBillboardEntry> *node, *next;\r\n\t\tnode = mp_entries[e]->GetNext();\r\n\t\twhile( node )\r\n\t\t{\r\n\t\t\tnext = node->GetNext();\r\n\t\t\tsBillboardEntry *p_entry = node->GetData();\r\n\t\t\tif( p_entry->mp_mesh == p_mesh )\r\n\t\t\t{\r\n\t\t\t\t// This is the entry. Delete the node and the entry.\r\n\t\t\t\tdelete node;\r\n\t\t\t\tdelete p_entry;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tnode = next;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sBillboardMaterialBatch::Render( void )\r\n{\r\n\tstatic float vector_upload[12] = {\t0.0f, 0.0f, 0.0f, 1.0f,\r\n\t\t\t\t\t\t\t\t\t\t0.0f, 0.0f, 0.0f, 1.0f,\r\n\t\t\t\t\t\t\t\t\t\t0.0f, 0.0f, 0.0f, 1.0f };\r\n\r\n\tif( mp_material )\r\n\t{\r\n\t\tmp_material->Submit();\r\n\r\n\t\t// Set up correct vertex shader.\r\n\t\tNxXbox::set_vertex_shader( BillboardScreenAlignedVS );\r\n\r\n\t\t// Lock out vertex shader changes.\r\n\t\tEngineGlobals.vertex_shader_override = BillboardScreenAlignedVS;\r\n\r\n\t\t// Set up correct pixel shader - this assumes that all meshes with the same material will have the same pixel shader.\r\n\t\tfor( int e = 0; e < 3; ++e )\r\n\t\t{\r\n\t\t\tif( mp_entries[e]->GetNext())\r\n\t\t\t{\r\n\t\t\t\tsBillboardEntry *p_entry = mp_entries[e]->GetNext()->GetData();\r\n\t\t\t\tset_pixel_shader( p_entry->mp_mesh->m_pixel_shader );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Load up the combined world->view_projection matrix.\r\n\t\tXGMATRIX\tdest_matrix;\r\n\t\tXGMATRIX\ttemp_matrix;\r\n\t\tXGMATRIX\tprojMatrix;\r\n\t\tXGMATRIX\tviewMatrix;\r\n\t\tXGMATRIX\tworldMatrix;\r\n\t\t\r\n\t\t// Projection matrix.\r\n\t\tXGMatrixTranspose( &projMatrix, &EngineGlobals.projection_matrix );\r\n\t\r\n\t\t// View matrix.\r\n\t\tXGMatrixTranspose( &viewMatrix, &EngineGlobals.view_matrix );\r\n\t\tviewMatrix.m[3][0] = 0.0f;\r\n\t\tviewMatrix.m[3][1] = 0.0f;\r\n\t\tviewMatrix.m[3][2] = 0.0f;\r\n\t\tviewMatrix.m[3][3] = 1.0f;\r\n\t\r\n\t\t// World space transformation matrix.\r\n\t\tXGMatrixIdentity( &worldMatrix );\r\n\r\n\t\t// Calculate composite world->view->projection matrix.\r\n\t\tXGMatrixMultiply( &temp_matrix, &viewMatrix, &worldMatrix );\r\n\t\tXGMatrixMultiply( &dest_matrix, &projMatrix, &temp_matrix );\r\n\r\n\t\t// Load up the combined world, camera & projection matrix.\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 0, (void*)&dest_matrix, 4 );\r\n\r\n\t\tLst::Node<sBillboardEntry> *node, *next;\r\n\r\n\t\t// First do the screen aligned billboards.\r\n\t\tvector_upload[0]\t= BillboardManager.m_screen_right[X];\r\n\t\tvector_upload[1]\t= BillboardManager.m_screen_right[Y];\r\n\t\tvector_upload[2]\t= BillboardManager.m_screen_right[Z];\r\n\t\tvector_upload[4]\t= BillboardManager.m_screen_up[X];\r\n\t\tvector_upload[5]\t= BillboardManager.m_screen_up[Y];\r\n\t\tvector_upload[6]\t= BillboardManager.m_screen_up[Z];\r\n\t\tvector_upload[8]\t= BillboardManager.m_at[X];\r\n\t\tvector_upload[9]\t= BillboardManager.m_at[Y];\r\n\t\tvector_upload[10]\t= BillboardManager.m_at[Z];\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 4, (void*)( &vector_upload[0] ), 3 );\r\n\r\n\t\tfor( node = mp_entries[0]->GetNext(); node; node = next )\r\n\t\t{\r\n\t\t\tnext = node->GetNext();\r\n\t\t\tsBillboardEntry *p_entry = node->GetData();\r\n\r\n\t\t\t// Only render if the mesh is active.\r\n\t\t\tif( p_entry->mp_mesh->m_flags & sMesh::MESH_FLAG_ACTIVE )\r\n\t\t\t{\r\n\t\t\t\t// Deal with material color override.\r\n\t\t\t\tif( p_entry->mp_mesh->m_flags & sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE )\r\n\t\t\t\t\tp_entry->mp_mesh->HandleColorOverride();\r\n\t\t\t\telse\r\n\t\t\t\t\tset_pixel_shader( p_entry->mp_mesh->m_pixel_shader );\r\n\r\n\t\t\t\t// Deal with vertex color wibble if present.\r\n\t\t\t\tif( p_entry->mp_mesh->mp_vc_wibble_data )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_entry->mp_mesh->wibble_vc();\r\n\t\t\t\t\tIDirect3DVertexBuffer8*\tp_submit_buffer = p_entry->mp_mesh->mp_vertex_buffer[p_entry->mp_mesh->m_current_write_vertex_buffer];\r\n\t\t\t\t\tp_entry->mp_mesh->SwapVertexBuffers();\r\n\t\t\t\t\tD3DDevice_SetStreamSource( 0, p_submit_buffer, p_entry->mp_mesh->m_vertex_stride );\r\n\t\t\t\t\tD3DDevice_DrawIndexedVertices( p_entry->mp_mesh->m_primitive_type, p_entry->mp_mesh->m_num_indices[0], p_entry->mp_mesh->mp_index_buffer[0] );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetStreamSource( 0, p_entry->mp_mesh->mp_vertex_buffer[0], p_entry->mp_mesh->m_vertex_stride );\r\n\t\t\t\t\tD3DDevice_DrawIndexedVertices( p_entry->mp_mesh->m_primitive_type, p_entry->mp_mesh->m_num_indices[0], p_entry->mp_mesh->mp_index_buffer[0] );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Next do the the y axis aligned billboards.\r\n\t\tvector_upload[0]\t= BillboardManager.m_screen_right_xz[X];\r\n\t\tvector_upload[1]\t= BillboardManager.m_screen_right_xz[Y];\r\n\t\tvector_upload[2]\t= BillboardManager.m_screen_right_xz[Z];\r\n\t\tvector_upload[4]\t= 0.0f;\r\n\t\tvector_upload[5]\t= 1.0f;\r\n\t\tvector_upload[6]\t= 0.0f;\r\n\t\tvector_upload[8]\t= BillboardManager.m_at_xz[X];\r\n\t\tvector_upload[9]\t= BillboardManager.m_at_xz[Y];\r\n\t\tvector_upload[10]\t= BillboardManager.m_at_xz[Z];\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 4, (void*)vector_upload, 3 );\r\n\r\n\t\tfor( node = mp_entries[1]->GetNext(); node; node = next )\r\n\t\t{\r\n\t\t\tnext = node->GetNext();\r\n\t\t\tsBillboardEntry *p_entry = node->GetData();\r\n\r\n\t\t\t// Only render if the mesh is active.\r\n\t\t\tif( p_entry->mp_mesh->m_flags & sMesh::MESH_FLAG_ACTIVE )\r\n\t\t\t{\r\n\t\t\t\t// Deal with material color override.\r\n\t\t\t\tif( p_entry->mp_mesh->m_flags & sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE )\r\n\t\t\t\t\tp_entry->mp_mesh->HandleColorOverride();\r\n\t\t\t\telse\r\n\t\t\t\t\tset_pixel_shader( p_entry->mp_mesh->m_pixel_shader );\r\n\r\n\t\t\t\t// Deal with vertex color wibble if present.\r\n\t\t\t\tif( p_entry->mp_mesh->mp_vc_wibble_data )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_entry->mp_mesh->wibble_vc();\r\n\t\t\t\t\tIDirect3DVertexBuffer8*\tp_submit_buffer = p_entry->mp_mesh->mp_vertex_buffer[p_entry->mp_mesh->m_current_write_vertex_buffer];\r\n\t\t\t\t\tp_entry->mp_mesh->SwapVertexBuffers();\r\n\t\t\t\t\tD3DDevice_SetStreamSource( 0, p_submit_buffer, p_entry->mp_mesh->m_vertex_stride );\r\n\t\t\t\t\tD3DDevice_DrawIndexedVertices( p_entry->mp_mesh->m_primitive_type, p_entry->mp_mesh->m_num_indices[0], p_entry->mp_mesh->mp_index_buffer[0] );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetStreamSource( 0, p_entry->mp_mesh->mp_vertex_buffer[0], p_entry->mp_mesh->m_vertex_stride );\r\n\t\t\t\t\tD3DDevice_DrawIndexedVertices( p_entry->mp_mesh->m_primitive_type, p_entry->mp_mesh->m_num_indices[0], p_entry->mp_mesh->mp_index_buffer[0] );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Now do the arbitrary axis aligned billboards.\r\n\t\tfor( node = mp_entries[2]->GetNext(); node; node = next )\r\n\t\t{\r\n\t\t\tnext = node->GetNext();\r\n\t\t\tsBillboardEntry *p_entry\t\t= node->GetData();\r\n\t\t\tsBillboardData *p_entry_data\t= p_entry->mp_mesh->mp_billboard_data;\r\n\t\t\r\n\t\t\t// Only render if the mesh is active.\r\n\t\t\tif( p_entry->mp_mesh->m_flags & sMesh::MESH_FLAG_ACTIVE )\r\n\t\t\t{\r\n\t\t\t\t// For this type we need to calculate the vector perpendicular to both the view vector and the axis of rotation.\r\n\t\t\t\tMth::Vector axis_right = Mth::CrossProduct( BillboardManager.m_at, p_entry_data->m_pivot_axis ).Normalize();\r\n\t\t\t\tMth::Vector axis_at = Mth::CrossProduct( p_entry_data->m_pivot_axis, axis_right ).Normalize();\r\n\r\n\t\t\t\t// Begin state block to set vertex shader constants for bone transforms.\r\n\t\t\t\tDWORD *p_push;\r\n\t\t\t\tEngineGlobals.p_Device->BeginState( 15, &p_push );\r\n\r\n\t\t\t\t// 1 here isn't the parameter for SET_TRANSFORM_CONSTANT_LOAD; rather, it's the number of dwords written to that register.\r\n\t\t\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_TRANSFORM_CONSTANT_LOAD, 1 ); \r\n\r\n\t\t\t\t// Here is the actual parameter for SET_TRANSFORM_CONSTANT_LOAD. Always add 96 to the constant register.\r\n\t\t\t\tp_push[1]\t= 4 + 96;\r\n\t\t\t\tp_push[2]\t= D3DPUSH_ENCODE( D3DPUSH_SET_TRANSFORM_CONSTANT, 12 );\r\n\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&axis_right[X] );\r\n\t\t\t\tp_push[4]\t= *((DWORD*)&axis_right[Y] );\r\n\t\t\t\tp_push[5]\t= *((DWORD*)&axis_right[Z] );\r\n\r\n\t\t\t\tp_push[7]\t= *((DWORD*)&p_entry_data->m_pivot_axis[X] );\r\n\t\t\t\tp_push[8]\t= *((DWORD*)&p_entry_data->m_pivot_axis[Y] );\r\n\t\t\t\tp_push[9]\t= *((DWORD*)&p_entry_data->m_pivot_axis[Z] );\r\n\r\n\t\t\t\tp_push[11]\t= *((DWORD*)&axis_at[X] );\r\n\t\t\t\tp_push[12]\t= *((DWORD*)&axis_at[Y] );\r\n\t\t\t\tp_push[13]\t= *((DWORD*)&axis_at[Z] );\r\n\r\n\t\t\t\tp_push\t\t+= 15;\r\n\t\t\t\tEngineGlobals.p_Device->EndState( p_push );\r\n\r\n\t\t\t\t// Deal with material color override.\r\n\t\t\t\tif( p_entry->mp_mesh->m_flags & sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE )\r\n\t\t\t\t\tp_entry->mp_mesh->HandleColorOverride();\r\n\t\t\t\telse\r\n\t\t\t\t\tset_pixel_shader( p_entry->mp_mesh->m_pixel_shader );\r\n\r\n\t\t\t\t// Deal with vertex color wibble if present.\r\n\t\t\t\tif( p_entry->mp_mesh->mp_vc_wibble_data )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_entry->mp_mesh->wibble_vc();\r\n\t\t\t\t\tIDirect3DVertexBuffer8*\tp_submit_buffer = p_entry->mp_mesh->mp_vertex_buffer[p_entry->mp_mesh->m_current_write_vertex_buffer];\r\n\t\t\t\t\tp_entry->mp_mesh->SwapVertexBuffers();\r\n\t\t\t\t\tD3DDevice_SetStreamSource( 0, p_submit_buffer, p_entry->mp_mesh->m_vertex_stride );\r\n\t\t\t\t\tD3DDevice_DrawIndexedVertices( p_entry->mp_mesh->m_primitive_type, p_entry->mp_mesh->m_num_indices[0], p_entry->mp_mesh->mp_index_buffer[0] );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetStreamSource( 0, p_entry->mp_mesh->mp_vertex_buffer[0], p_entry->mp_mesh->m_vertex_stride );\r\n\t\t\t\t\tD3DDevice_DrawIndexedVertices( p_entry->mp_mesh->m_primitive_type, p_entry->mp_mesh->m_num_indices[0], p_entry->mp_mesh->mp_index_buffer[0] );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Finally do the world aligned billboards.\r\n//\t\tfor( node = mp_entries[3]->GetNext(); node; node = next )\r\n//\t\t{\r\n//\t\t\tnext = node->GetNext();\r\n//\t\t\tsBillboardEntry *p_entry = node->GetData();\r\n\t\t\r\n\t\t\t// Only render if the mesh is active.\r\n//\t\t\tif( p_entry->mp_mesh->m_flags & sMesh::MESH_FLAG_ACTIVE )\r\n//\t\t\t{\r\n\t\t\t\t// For this type we need to calculate the vector perpendicular to both the view vector and the axis of rotation.\r\n//\t\t\t\tMth::Vector at( p_entry->m_pivot_axis[X] - EngineGlobals.cam_position.x,\r\n//\t\t\t\t\t\t\t\tp_entry->m_pivot_axis[Y] - EngineGlobals.cam_position.y,\r\n//\t\t\t\t\t\t\t\tp_entry->m_pivot_axis[Z] - EngineGlobals.cam_position.z );\r\n//\t\t\t\tat.Normalize();\r\n\r\n//\t\t\t\tMth::Vector axis_right = Mth::CrossProduct( at, BillboardManager.m_screen_up ).Normalize();\r\n//\t\t\t\tMth::Vector axis_at = Mth::CrossProduct( BillboardManager.m_screen_up, axis_right ).Normalize();\r\n\r\n//\t\t\t\tvector_upload[0]\t= axis_right[X];\r\n//\t\t\t\tvector_upload[1]\t= axis_right[Y];\r\n//\t\t\t\tvector_upload[2]\t= axis_right[Z];\r\n//\t\t\t\tvector_upload[4]\t= BillboardManager.m_screen_up[X];\r\n//\t\t\t\tvector_upload[5]\t= BillboardManager.m_screen_up[Y];\r\n//\t\t\t\tvector_upload[6]\t= BillboardManager.m_screen_up[Z];\r\n//\t\t\t\tvector_upload[8]\t= axis_at[X];\r\n//\t\t\t\tvector_upload[9]\t= axis_at[Y];\r\n//\t\t\t\tvector_upload[10]\t= axis_at[Z];\r\n//\t\t\t\tD3DDevice_SetVertexShaderConstant( 4, (void*)vector_upload, 3 );\r\n\r\n//\t\t\t\tD3DDevice_SetStreamSource( 0, p_entry->mp_mesh->mp_vertex_buffer[0], p_entry->mp_mesh->m_vertex_stride );\r\n//\t\t\t\tD3DDevice_DrawIndexedVertices( p_entry->mp_mesh->m_primitive_type, p_entry->mp_mesh->m_num_indices[0], p_entry->mp_mesh->mp_index_buffer[0] );\r\n//\t\t\t}\r\n//\t\t}\r\n\r\n\t\t// Undo vertex shader lock.\r\n\t\tEngineGlobals.vertex_shader_override = 0;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sBillboardMaterialBatch::Reset( void )\r\n{\r\n\tLst::Node<sBillboardEntry> *node, *next;\r\n\r\n\tfor( int e = 0; e < 3; ++e )\r\n\t{\r\n\t\tif( mp_entries[e] )\r\n\t\t{\r\n\t\t\tfor( node = mp_entries[e]->GetNext(); node; node = next )\r\n\t\t\t{\r\n\t\t\t\tnext = node->GetNext();\r\n\t\t\t\tdelete node;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tmp_material\t\t= NULL;\r\n\tm_entry_size\t= 0;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsBillboardEntry::sBillboardEntry( sMesh *p_mesh )\r\n{\r\n\tDbg_Assert( p_mesh->mp_billboard_data != NULL );\r\n\r\n\tmp_mesh\t\t\t= p_mesh;\r\n\tm_type\t\t\t= p_mesh->mp_billboard_data->m_type;\r\n\r\n\t// For now set the pivot point as the center of the bounding sphere.\r\n//\tm_pivot_pos.Set( p_mesh->m_sphere_center.x, p_mesh->m_sphere_center.y, p_mesh->m_sphere_center.z );\r\n\r\n\t// Frig the verts for now.\r\n//\tm_verts[0][0]\t= -12.0f;\r\n//\tm_verts[0][1]\t= -24.0f;\r\n//\tm_verts[0][2]\t= 0.0f;\r\n\r\n//\tm_verts[1][0]\t= -12.0f;\r\n//\tm_verts[1][1]\t= 24.0f;\r\n//\tm_verts[1][2]\t= 0.0f;\r\n\r\n//\tm_verts[2][0]\t= 12.0f;\r\n//\tm_verts[2][1]\t= 24.0f;\r\n//\tm_verts[2][2]\t= 0.0f;\r\n\r\n//\tm_verts[3][0]\t= 12.0f;\r\n//\tm_verts[3][1]\t= -24.0f;\r\n//\tm_verts[3][2]\t= 0.0f;\r\n\r\n\r\n//\tswitch( rand() & 0x03 )\r\n//\t{\r\n//\t\tcase 0:\r\n//\t\t{\r\n//\t\t\tm_type = vBILLBOARD_TYPE_SCREEN_ALIGNED;\r\n//\t\t\tbreak;\r\n//\t\t}\r\n//\t\tcase 1:\r\n//\t\t{\r\n//\t\t\tm_type = vBILLBOARD_TYPE_Y_AXIS_ALIGNED;\r\n//\t\t\tbreak;\r\n//\t\t}\r\n//\t\tcase 2:\r\n//\t\tcase 3:\r\n//\t\t{\r\n//\t\t\tm_type = vBILLBOARD_TYPE_ARBITRARY_AXIS_ALIGNED;\r\n//\t\t\tm_pivot_axis = Mth::Vector((float)( rand() - rand()), (float)( rand() - rand()), (float)( rand() - rand())).Normalize();\r\n//\t\t\tbreak;\r\n//\t\t}\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsBillboardEntry::~sBillboardEntry( void )\r\n{\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/billboard.h",
    "content": "#ifndef __BILLBOARD_H\r\n#define __BILLBOARD_H\r\n\r\n\r\n#include <core/defines.h>\r\n#include \"render.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* A single billboard entry.\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sBillboardEntry\r\n{\r\n\tsBillboardData::EBillboardType\tm_type;\r\n\tsMesh\t\t\t\t\t\t\t*mp_mesh;\r\n//\tMth::Vector\t\t\t\t\t\tm_pivot_pos;\r\n//\tMth::Vector\t\t\t\t\t\tm_pivot_axis;\t// Normalised axis of rotation, valid only for type ARBITRARY_AXIS_ALIGNED.\r\n//\tfloat\t\t\t\t\t\t\tm_verts[4][3];\t// Verts defined as an offset from the pivot point.\r\n\r\n\t\t\t\t\t\t\t\t\tsBillboardEntry( sMesh *p_mesh );\r\n\t\t\t\t\t\t\t\t\t~sBillboardEntry( void );\r\n};\r\n\t\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Stores information about a billboard batch, effectively a set  */\r\n/* of billboards with the same material.                          */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sBillboardMaterialBatch\r\n{\r\n\tint\t\t\t\t\t\t\tm_entry_size;\t\t// Push buffer size of each billboard entry (bytes).\r\n\tsMaterial\t\t\t\t\t*mp_material;\r\n\tLst::Head <sBillboardEntry>\t*mp_entries[3];\t\t// One entry each for screen aligned, y axis aligned, and arbitrary aligned.\r\n\r\n\t\t\t\t\t\t\t\tsBillboardMaterialBatch( sMaterial *p_material );\r\n\t\t\t\t\t\t\t\t~sBillboardMaterialBatch( void );\r\n\r\n\tbool\t\t\t\t\t\tIsEmpty( void );\r\n\tfloat\t\t\t\t\t\tGetDrawOrder( void );\r\n\tsMaterial\t\t\t\t\t*GetMaterial( void );\r\n\tvoid\t\t\t\t\t\tAddEntry( sMesh *p_mesh );\r\n\tvoid\t\t\t\t\t\tRemoveEntry( sMesh *p_mesh );\r\n\tvoid\t\t\t\t\t\tProcessMesh( sMesh *p_mesh );\r\n\tvoid\t\t\t\t\t\tRender( void );\r\n\tvoid\t\t\t\t\t\tReset( void );\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sBillboardManager\r\n{\r\n\tenum\r\n\t{\r\n\t\t\t\tMAX_BILLBOARD_BATCHES\t= 256\r\n\t};\r\n\r\n\tint\t\t\t\t\t\t\tm_num_batches;\r\n\tsBillboardMaterialBatch\t\t*mp_batches[MAX_BILLBOARD_BATCHES];\r\n\r\n\tMth::Vector\t\t\t\t\tm_at;\r\n\tMth::Vector\t\t\t\t\tm_screen_right;\r\n\tMth::Vector\t\t\t\t\tm_screen_up;\r\n\tMth::Vector\t\t\t\t\tm_at_xz;\r\n\tMth::Vector\t\t\t\t\tm_screen_right_xz;\r\n\r\n\t\t\t\t\t\t\t\tsBillboardManager( void );\r\n\t\t\t\t\t\t\t\t~sBillboardManager( void );\r\n\r\n\tvoid\t\t\t\t\t\tRender( uint32 flags );\r\n\tvoid\t\t\t\t\t\tSetCameraMatrix( void );\r\n\tsBillboardMaterialBatch\t\t*GetBatch( sMaterial *p_material );\r\n\tvoid\t\t\t\t\t\tAddEntry( sMesh *p_mesh );\r\n\tvoid\t\t\t\t\t\tRemoveEntry( sMesh *p_mesh );\r\n\tvoid\t\t\t\t\t\tSortBatches( void );\r\n};\r\n\r\n\r\nextern sBillboardManager BillboardManager;\r\n\r\n\r\n\t\r\n\r\n} // namespace NxXbox\r\n\r\n\r\n#endif // __BILLBOARD_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/chars.cpp",
    "content": "#include <stdlib.h>\r\n#include <string.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <core/string/stringutils.h>\r\n#include <core/macros.h>\r\n#include <gfx/nxfontman.h>\r\n#include <sys/config/config.h>\r\n#include <sys/file/filesys.h>\r\n\r\n#include \"nx_init.h\"\r\n#include \"render.h\"\r\n#include \"chars.h\"\r\n#include \"xbmemfnt.h\"\r\n\r\n\r\n/*\r\n\r\n\r\n\t\r\n.fnt file format (by Ryan)\r\n--------------------------\r\n\r\n\t4\tFile size in bytes\r\n\t4\tNumber of characters\r\n\t4\tDefault height\r\n\t4\tDefault base\r\n\t\r\n\t?\tCharacter table (see below)\r\n\t?\tTexture (see below)\r\n\r\n\tCharacter\r\n\t2\tBaseline (how many pixels down relative to top of image)\r\n\t2\tAscii value\r\n\r\n\tTexture\r\n\t4\tSize of texture\r\n\t2\tWidth\r\n\t2\tHeight\r\n\t2\tBit depth\r\n\t6\tPadding\r\n\tW*H\tRaw data\r\n\t0-3\tPadding for uint32 alignment\r\n\t1K\tPalette data\r\n\t4\tNumber of subtextures\r\n\t?\tSubtexture table (see below)\r\n\r\n\tSubtexture\r\n\t2\tX\r\n\t2\tY\r\n\t2\tW\r\n\t2\tH\r\n\t\r\n*/\r\n\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ntypedef struct\r\n{\r\n\tfloat\t\tx, y, z;\r\n\tfloat\t\trhw;\r\n\tD3DCOLOR\tcol;\r\n\tfloat\t\tu, v;\r\n}\r\nsFontVert;\r\n\r\n\r\nSFont\t\t\t*pFontList;\r\nSFont\t\t\t*pButtonsFont\t\t\t\t= NULL;\r\nSFont\t\t\t*SText::spOverrideFont\t\t= NULL;\r\n\r\nconst uint32\tCHARS_PER_BUFFER\t\t\t= 256;\r\nstatic int\t\tfont_vertex_offset\t\t\t= 0;\r\nstatic BYTE*\tp_locked_font_vertex_buffer\t= NULL;\r\nstatic BYTE\t\tfont_vertex_buffer[CHARS_PER_BUFFER * 4 * sizeof( sFontVert )];\r\n\r\nstatic uint32\tswizzle_table[4096];\r\nstatic bool\t\tswizzle_table_generated\t\t= false;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void generateSwizzleTable( void )\r\n{\r\n\tif( !swizzle_table_generated )\r\n\t{\r\n\t\tfor( uint32 i = 0, value = 0; i < 4096; i++ )\r\n\t\t{\r\n\t\t\tswizzle_table[i] = value;\r\n\t\t\tvalue += 0x2AAAAAAB;\r\n\t\t\tvalue &= 0x55555555;\r\n\t\t}\r\n\t\tswizzle_table_generated = true;\r\n\t}\r\n}\r\n\r\n\r\n\r\n#define TWIDDLE(_u, _v) ((swizzle_table[(_v)] << 1) | (swizzle_table[(_u)]))\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SwizzleTexture( void *dstBuffer, void *srcBuffer, int width, int height, int32 depth, int32 stride )\r\n{\r\n    int32 tilesX, tilesY;\r\n    int32 tilesSizeX, tilesSizeY;\r\n    int32 tileSize;\r\n\r\n\tgenerateSwizzleTable();\r\n\r\n\tif( width > height )\r\n    {\r\n        tilesX = width / height;\r\n        tilesY = 1;\r\n\r\n        tilesSizeX = width / tilesX;\r\n        tilesSizeY = height;\r\n    }\r\n    else\r\n    {\r\n        tilesX = 1;\r\n        tilesY = height / width;\r\n\r\n        tilesSizeX = width;\r\n        tilesSizeY = height / tilesY;\r\n    }\r\n\r\n    tileSize = tilesSizeX * tilesSizeY;\r\n\r\n\tswitch (depth)\r\n\t{\r\n\t\tcase 4:\r\n\t    case 8:\r\n        {\r\n            int32 j;\r\n\r\n            for (j = 0; j < tilesY; j++)\r\n            {\r\n                int32 i;\r\n\r\n                for (i = 0; i < tilesX; i++)\r\n                {\r\n            int32 y;\r\n                    uint8 *base;\r\n\r\n                    base = (uint8 *)(((uint8 *)dstBuffer) +\r\n                                       ((tileSize * tilesX) * j) +\r\n                                       (tileSize * i));\r\n\r\n                    for (y = 0; y < tilesSizeY; y++)\r\n            {\r\n                uint8    *srcPixel;\r\n                int32     x;\r\n\r\n                        srcPixel = (uint8 *)(((uint8 *)srcBuffer) +\r\n                                               (stride * (tilesSizeY * j)) +\r\n                                               (tilesSizeX * i) +\r\n                                               (stride * y));\r\n\r\n                        for (x = 0; x < tilesSizeX; x++)\r\n                {\r\n                    uint8    *dstPixel;\r\n                        dstPixel = (uint8 *)(base + TWIDDLE(x, y));\r\n\t\t                *dstPixel = *srcPixel;\r\n\r\n                    srcPixel++;\r\n                }\r\n            }\r\n        }\r\n            }\r\n        }\r\n        break;\r\n\r\n    case 16:\r\n        {\r\n            int32 j;\r\n\r\n            for (j = 0; j < tilesY; j++)\r\n            {\r\n                int32 i;\r\n\r\n                for (i = 0; i < tilesX; i++)\r\n                {\r\n            int32 y;\r\n                    uint8 *base;\r\n\r\n                    base = (uint8 *)(((uint16 *)dstBuffer) +\r\n                                       ((tileSize * tilesX) * j) +\r\n                                       (tileSize * i));\r\n\r\n                    for (y = 0; y < tilesSizeY; y++)\r\n            {\r\n                uint16    *srcPixel;\r\n                int32     x;\r\n\r\n                        srcPixel = (uint16 *)(((uint8 *)srcBuffer) +\r\n                                                (stride * (tilesSizeY * j)) +\r\n                                                (2 * tilesSizeX * i) +\r\n                                                (stride * y));\r\n\r\n                        for (x = 0; x < tilesSizeX; x++)\r\n                {\r\n                    uint16    *dstPixel;\r\n                    dstPixel = (uint16 *)(base + (TWIDDLE(x, y) << 1));\r\n                    *dstPixel = *srcPixel;\r\n\r\n                    srcPixel++;\r\n                }\r\n            }\r\n        }\r\n            }\r\n        }\r\n        break;\r\n\r\n    case 24:\r\n    case 32:\r\n        {\r\n            int32 j;\r\n\r\n            for (j = 0; j < tilesY; j++)\r\n            {\r\n                int32 i;\r\n\r\n                for (i = 0; i < tilesX; i++)\r\n                {\r\n            int32 y;\r\n                    uint8 *base;\r\n\r\n                    base = (uint8 *)(((uint32 *)dstBuffer) +\r\n                                       ((tileSize * tilesX) * j) +\r\n                                       (tileSize * i));\r\n\r\n                    for (y = 0; y < tilesSizeY; y++)\r\n            {\r\n                uint32    *srcPixel;\r\n                int32     x;\r\n\r\n                        srcPixel = (uint32 *)(((uint8 *)srcBuffer) +\r\n                                                (stride * (tilesSizeY * j)) +\r\n                                                (4 * tilesSizeX * i) +\r\n                                                (stride * y));\r\n\r\n                        for (x = 0; x < tilesSizeX; x++)\r\n                {\r\n                    uint32    *dstPixel;\r\n                    dstPixel = (uint32 *)(base + (TWIDDLE(x, y) << 2));\r\n                    *dstPixel = *srcPixel;\r\n\r\n                    srcPixel++;\r\n                }\r\n            }\r\n        }\r\n            }\r\n        }\r\n        break;\r\n\r\n    default:\r\n\t\texit( 0 );\r\n        break;\r\n    }\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nSFont* InitialiseMemoryResidentFont( void )\r\n{\r\n\treturn LoadFont((const char*)xbmemfnt, true );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nSFont* LoadFont( const char *Filename, bool memory_resident )\r\n{\r\n\tSFont*\tpFont;\r\n\tSChar*\tpChar;\r\n\tuint8*\tpData;\r\n\tvoid*\tp_FH;\r\n\tint\t\ti,Len,NumChars,Width,Height,Depth,NumBytes;\r\n\r\n\t// Build the full filename.\r\n\tchar filename[128];\r\n\r\n\tif( !memory_resident )\r\n\t{\r\n\t\tstrcpy( filename, \"fonts/\" );\r\n\t\tstrcat( filename, Filename );\r\n\t\tstrcat( filename, \".fnt.xbx\" );\r\n\t}\r\n\t\r\n\t// Open the font file.\r\n\tif( !memory_resident )\r\n\t\tp_FH = File::Open( filename, \"rb\" );\r\n\r\n\t// Allocate memory for the font structure.\r\n\tpFont = new SFont();\r\n\r\n\t// Allocate a temporary buffer.\r\n\tuint8 FontBuf[2048];\r\n\r\n\t// Load file header.\r\n\tif( !memory_resident )\r\n\t{\r\n\t\tLen = File::Read( FontBuf, 16, 1, p_FH );\r\n\t\tDbg_MsgAssert( Len == 16, ( \"couldn't read file header from font file %s\", Filename ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCopyMemory( FontBuf, Filename, 16 );\r\n\t\tFilename += 16;\r\n\t}\r\n\r\n\tNumChars\t\t\t = ((uint32 *)FontBuf)[1];\r\n\tpFont->DefaultHeight = ((uint32 *)FontBuf)[2];\r\n\tpFont->DefaultBase\t = ((uint32 *)FontBuf)[3];\r\n\r\n\t// Clear character map to zero.\r\n\tmemset( pFont->Map, 0, 256 );\r\n\tmemset( pFont->SpecialMap, 0, 32 );\r\n\r\n\t// Allocate memory for character table.\r\n\tpFont->pChars = new SChar[NumChars];\r\n\r\n\t// Load character map and character table.\r\n\tif( !memory_resident )\r\n\t{\r\n\t\tLen = File::Read( FontBuf, NumChars << 2, 1, p_FH );\r\n\t\tDbg_MsgAssert( Len == ( NumChars << 2 ), ( \"couldn't read character table in font file %s\", Filename ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCopyMemory( FontBuf, Filename, NumChars << 2 );\r\n\t\tFilename += NumChars << 2;\r\n\t}\r\n\r\n\tfor( i = 0, pChar = pFont->pChars, pData = FontBuf; i < NumChars; i++,pChar++,pData += 4 )\r\n\t{\r\n\t\tpChar->Baseline\t\t\t\t\t\t\t= ((uint16 *)pData)[0];\r\n\t\tsint16 ascii_val = ((sint16 *)pData)[1];\r\n\t\tif (ascii_val >= 0)\r\n\t\t\tpFont->Map[(uint8) ascii_val] = i;\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Assert(ascii_val >= -32)\r\n\t\t\tpFont->SpecialMap[(uint8) (-ascii_val - 1)] = i;\r\n\t\t}\r\n\t}\r\n\r\n\t// If there is a null character in the font, make characters that could not be found\r\n\t// in the font display that instead of 'A'\r\n\tif( pFont->SpecialMap[31] != 0 )\r\n\t{\r\n\t\tfor( i = 0; i < 256; ++i ) \r\n\t\t{\r\n\t\t\tif( pFont->Map[i] == 0 && i != 'A' && i != 'a')\r\n\t\t\t\tpFont->Map[i] = pFont->SpecialMap[31];\r\n\r\n\t\t\tif( i < 31 && pFont->SpecialMap[i] == 0 )\r\n\t\t\t\tpFont->SpecialMap[i] = pFont->SpecialMap[31];\r\n\t\t}\r\n\t}\t\r\n\t\r\n\t// Load texture header.\r\n\tif( !memory_resident )\r\n\t{\r\n\t\tLen = File::Read( FontBuf, 16, 1, p_FH );\r\n\t\tDbg_MsgAssert( Len == 16, ( \"couldn't read texture header from font file %s\", Filename ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCopyMemory( FontBuf, Filename, 16 );\r\n\t\tFilename += 16;\r\n\t}\r\n\r\n\tWidth\t= ((uint16 *)FontBuf)[2];\r\n\tHeight\t= ((uint16 *)FontBuf)[3];\r\n\tDepth\t= ((uint16 *)FontBuf)[4];\r\n\r\n\t// Create texture.\r\n\tDbg_Assert( Depth == 8 );\r\n\tif( D3D_OK != D3DDevice_CreateTexture(\tWidth, Height, 1, 0, D3DFMT_P8, 0, &pFont->pD3DTexture ))\r\n\t{\r\n\t\tDbg_Assert( 0 );\r\n\t\treturn NULL;\r\n\t}\r\n\t\r\n\t// Read texture bitmap data (into temp buffer so we can then swizzle it).\r\n\tNumBytes = ( Width * Height + 3 ) & 0xFFFFFFFC;\r\n\r\n\tuint8* p_temp_texel_data = new uint8[NumBytes];\r\n\tif( !memory_resident )\r\n\t{\r\n\t\tLen = File::Read( p_temp_texel_data, NumBytes, 1, p_FH );\r\n\t\tDbg_MsgAssert( Len == NumBytes, ( \"Couldn't read texture bitmap from font file %s\", Filename ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCopyMemory( p_temp_texel_data, Filename, NumBytes );\r\n\t\tFilename += NumBytes;\r\n\t}\r\n\r\n\t// Lock the texture so we can swizzle into it directly.\r\n\tD3DLOCKED_RECT locked_rect;\r\n\tif( D3D_OK != pFont->pD3DTexture->LockRect( 0, &locked_rect, NULL, 0 ))\r\n\t{\r\n\t\tDbg_Assert( 0 );\r\n\t\treturn NULL;\r\n\t}\r\n\t\r\n\t// Swizzle the texture data.\r\n\tSwizzleTexture( locked_rect.pBits, p_temp_texel_data, Width, Height, 8, Width );\r\n\r\n\t// No longer need this data.\r\n\tdelete[] p_temp_texel_data;\t\r\n\t\r\n\t// Create palette.\r\n\tif( D3D_OK != D3DDevice_CreatePalette(\tD3DPALETTE_256,\t&pFont->pD3DPalette ))\r\n\t{\r\n\t\tDbg_Assert( 0 );\r\n\t\treturn NULL;\r\n\t}\r\n\t\r\n\t// Read clut bitmap data.\r\n\tD3DCOLOR *p_clut;\r\n\tpFont->pD3DPalette->Lock( &p_clut, 0 );\r\n\r\n\tif( !memory_resident )\r\n\t{\r\n\t\tLen\t= File::Read( p_clut, 1024, 1, p_FH );\r\n\t\tDbg_MsgAssert( Len == 1024, ( \"couldn't read clut bitmap from font file %s\", Filename ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCopyMemory( p_clut, Filename, 1024 );\r\n\t\tFilename += 1024;\r\n\t}\r\n\r\n\t// Switch from RGBA to BGRA format palette.\r\n\tfor( i = 0; i < 256; ++i )\r\n\t{\r\n\t\tuint32\tred = p_clut[i] & 0xFF;\r\n\t\tuint32\tblu = ( p_clut[i] >> 16 ) & 0xFF;\r\n\r\n\t\t// Double the alpha in the clut (currently limited to 0x80).\r\n\t\tuint32 alpha = p_clut[i] >> 24;\r\n\t\talpha = ( alpha >= 0x80 ) ? 0xFF : ( alpha * 2 );\r\n\t\tp_clut[i] = ( alpha << 24 ) | ( p_clut[i] & 0x0000FF00 ) | ( red << 16 ) | ( blu );\r\n\t}\r\n\r\n\t// Skip numsubtextures, and load subtextures.\r\n\tif( !memory_resident )\r\n\t{\r\n\t\tLen = File::Read( FontBuf, ( NumChars << 3 ) + 4, 1, p_FH );\r\n\t\tDbg_MsgAssert( Len == ( NumChars << 3 ) + 4, ( \"couldn't read subtexture table from font file %s\", Filename ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCopyMemory( FontBuf, Filename, ( NumChars << 3 ) + 4 );\r\n\t\tFilename += ( NumChars << 3 ) + 4;\r\n\t}\r\n\r\n\tfor( i = 0, pChar = pFont->pChars, pData = FontBuf + 4; i < NumChars; i++, pChar++, pData += 8 )\r\n\t{\r\n\t\tuint16 x\t= ((uint16 *)pData )[0];\r\n\t\tuint16 y\t= ((uint16 *)pData )[1];\r\n\t\tuint16 w\t= ((uint16 *)pData )[2];\r\n\t\tuint16 h\t= ((uint16 *)pData )[3];\r\n\t\t\r\n\t\tpChar->w\t= w;\r\n\t\tpChar->h\t= h;\r\n\t\tpChar->u0\t= (float)x / (float)Width;\r\n\t\tpChar->v0\t= (float)y / (float)Height;\r\n\t\tpChar->u1\t= pChar->u0 + ((float)w / (float)Width );\r\n\t\tpChar->v1\t= pChar->v0 + ((float)h / (float)Height );\r\n\t}\r\n\r\n\t// Add font to font list.\r\n\tpFont->pNext\t= pFontList;\r\n\tpFontList\t\t= pFont;\r\n\r\n\t// We're done with the font file now.\r\n\tif( !memory_resident )\r\n\t\tFile::Close( p_FH );\r\n\t\r\n\t// this will serve as the default spacing\r\n\tpFont->mSpaceSpacing = pFont->pChars[pFont->Map['I']].w;\r\n\t\r\n\treturn pFont;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid UnloadFont( SFont *pFont )\r\n{\r\n\tSFont*\tpPrevFont;\r\n\tint\t\tfound = 0;\r\n\r\n\t// Find font and unchain from list.\r\n\tif( pFontList == pFont )\r\n\t{\r\n\t\tfound=1;\r\n\t\tpFontList = pFontList->pNext;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor( pPrevFont=pFontList; pPrevFont->pNext; pPrevFont=pPrevFont->pNext )\r\n\t\t{\r\n\t\t\tif( pPrevFont->pNext == pFont )\r\n\t\t\t{\r\n\t\t\t\tfound = 1;\r\n\t\t\t\tpPrevFont->pNext = pFont->pNext;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert( found, ( \"Attempt to unload font which has not been loaded\" ));\r\n\r\n\t// Free memory.\r\n\tdelete [] pFont->pChars;\r\n\tdelete pFont;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 SFont::GetDefaultHeight() const\r\n{\r\n\treturn DefaultHeight;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 SFont::GetDefaultBase() const\r\n{\r\n\treturn DefaultBase;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SFont::QueryString( char *String, float &width, float &height )\r\n{\r\n\tSChar\t*pChar;\r\n\tchar\t*pLetter;\r\n\tint\t\tx0,x1;\r\n\r\n\tx0 = 0;\r\n\r\n\tfor (pLetter=String;; pLetter++)\r\n\t{\r\n\t\tpChar = NULL;\r\n\t\t// may be overridden by the '\\b' tag\r\n\t\tSFont *p_font = this;\r\n\t\t\r\n\t\t// acount for tags (might be multiple ones in a row)\r\n\t\tbool got_char_tag = false; // tag resulting in output of character\r\n\t\twhile (*pLetter == '\\\\' && !got_char_tag)\r\n\t\t{\r\n\t\t\tpLetter++;\r\n\t\t\tif (*pLetter == '\\\\')\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tswitch(*pLetter)\r\n\t\t\t{\r\n\t\t\t\tcase '\\\\':\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 'c':\r\n\t\t\t\tcase 'C':\r\n\t\t\t\t\tpLetter += 2; // skip over \"c#\"\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 's':\r\n\t\t\t\tcase 'S':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++; // skip \"s\"\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\tpChar = pChars + SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase 'b':\r\n\t\t\t\tcase 'B':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++; // skip \"b\"\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// switch over to buttons font, the regular font will be used again on the next character\r\n\r\n\t\t\t\t\tp_font = pButtonsFont;\r\n\t\t\t\t\tDbg_Assert(p_font);\r\n\t\t\t\t\tpChar = p_font->pChars + p_font->SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase 'm':\r\n\t\t\t\tcase 'M':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++; // skip \"m\"\r\n\t\t\t\t\tchar button_char = Nx::CFontManager::sMapMetaCharacterToButton(pLetter);\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(&button_char);\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_font = pButtonsFont;\r\n\t\t\t\t\tDbg_Assert(p_font);\r\n\t\t\t\t\tpChar = p_font->pChars + p_font->SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDbg_MsgAssert(0, (\"unknown tag\"));\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t} // end while\r\n\t\t\r\n\t\tif (*pLetter == '\\0') break;\r\n\t\t\r\n\t\tif (*pLetter!=' ' || pChar)\r\n\t\t{\r\n\t\t\tif (!pChar)\r\n\t\t\t\tpChar = p_font->pChars + p_font->Map[(uint8)*pLetter];\r\n\t\t\tx1 = x0 + pChar->w;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tx1 = x0 + mSpaceSpacing;\r\n\t\t}\r\n\r\n\t\t//x0 = x1 + mCharSpacing + 1;\r\n\t\tx0 = x1 + mCharSpacing;\r\n\t}\r\n\r\n\twidth  = (float)x0;\r\n\theight = (float)DefaultHeight;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nSText::SText( float pri ) : SDraw2D( pri, true )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nSText::~SText( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SText::BeginDraw( void )\r\n{\r\n\tp_locked_font_vertex_buffer = &( font_vertex_buffer[0] );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SText::Draw( void )\r\n{\r\n\tSChar\t*pChar;\r\n\tchar\t*pLetter;\r\n\tfloat\tu0,v0,x0,y0,u1,v1,x1,y1,yt;\r\n\r\n\tx0 = SCREEN_CONV_X( m_xpos );\r\n\ty0 = SCREEN_CONV_Y( m_ypos );\r\n\r\n\tfloat char_spacing\t= (float)mp_font->mCharSpacing * m_xscale;\r\n\tfloat space_spacing = (float)mp_font->mSpaceSpacing * m_xscale;\r\n\t\r\n\tDWORD current_color\t= ( m_rgba & 0xFF00FF00 ) | (( m_rgba & 0xFF ) << 16 ) | (( m_rgba & 0xFF0000 ) >> 16 );\r\n\t\r\n\tfloat text_z = GetZValue();\r\n\t\r\n\tfor( pLetter = mp_string;; pLetter++ )\r\n\t{\r\n\t\tpChar = NULL;\r\n\t\tSFont *p_font = mp_font;\r\n\r\n\t\tsFontVert* p_vert = ((sFontVert*)p_locked_font_vertex_buffer ) + font_vertex_offset;\r\n\r\n\t\t// acount for tags (might be multiple ones in a row)\r\n\t\tbool got_char_tag = false; // tag resulting in output of character\r\n\t\twhile (*pLetter == '\\\\' && !got_char_tag)\r\n\t\t{\r\n\t\t\tpLetter++;\r\n\r\n\t\t\tswitch(*pLetter)\r\n\t\t\t{\r\n\t\t\t\tcase '\\\\':\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 'c':\r\n\t\t\t\tcase 'C':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++;\t// skip \"c\"\t\t\t\t\t\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\tpLetter++; // skip \"#\"\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Set active color from font.\r\n\t\t\t\t\tif( digit == 0 || m_color_override)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Switch from RGBA to BGRA format.\r\n\t\t\t\t\t\tcurrent_color\t= ( m_rgba & 0xFF00FF00 ) | (( m_rgba & 0xFF ) << 16 ) | (( m_rgba & 0xFF0000 ) >> 16 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Switch from RGBA to BGRA format.\r\n\t\t\t\t\t\tuint32 color\t= mp_font->mRGBATab[digit-1];\r\n\t\t\t\t\t\tcurrent_color\t= ( color & 0xFF00FF00 ) | (( color & 0xFF ) << 16 ) | (( color & 0xFF0000 ) >> 16 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase 's':\r\n\t\t\t\tcase 'S':\r\n\t\t\t\t{\r\n\t\t\t\t\tpLetter++;\t// skip \"s\"\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit(pLetter);\r\n\t\t\t\t\t\r\n\t\t\t\t\tpChar = mp_font->pChars + mp_font->SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase 'b':\r\n\t\t\t\tcase 'B':\r\n\t\t\t\t{\r\n\t\t\t\t\t// 'B' stands for button, accesses the button font\r\n\r\n\t\t\t\t\tpLetter++; // skip \"b\"\r\n\t\t\t\t\tuint digit = Str::DehexifyDigit( pLetter );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// switch to the buttons font!\r\n\t\t\t\t\tp_font = pButtonsFont;\r\n\t\t\t\t\tDbg_Assert( p_font );\r\n\t\t\t\t\t\r\n\t\t\t\t\tpChar = p_font->pChars + p_font->SpecialMap[digit];\r\n\t\t\t\t\tgot_char_tag = true;\r\n\t\t\t\t\t\r\n\t\t\t\t\tEndDraw();\r\n\t\t\t\t\tBeginDraw();\r\n\r\n\t\t\t\t\t// Reset the vertex data pointer.\r\n\t\t\t\t\tp_vert = ((sFontVert*)p_locked_font_vertex_buffer ) + font_vertex_offset;\r\n\t\t\t\t\t\r\n\t\t\t\t\tspOverrideFont = p_font;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( 0, ( \"unknown tag\" ));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} // end while\r\n\t\t\r\n\t\tif (*pLetter == '\\0') break;\r\n\t\t\r\n\t\tif( *pLetter != ' ' || pChar)\r\n\t\t{\r\n\t\t\tif (!pChar)\r\n\t\t\t\tpChar = p_font->pChars + p_font->Map[(uint8) *pLetter];\r\n\t\t\tyt = y0 + ((float)( p_font->DefaultBase - pChar->Baseline ) * m_yscale ) * EngineGlobals.screen_conv_y_multiplier;\r\n\t\t\tu0 = pChar->u0;\r\n\t\t\tv0 = pChar->v0;\r\n\t\t\tu1 = pChar->u1;\r\n\t\t\tv1 = pChar->v1;\r\n\t\t\tx1 = x0 + ( pChar->w * m_xscale * EngineGlobals.screen_conv_x_multiplier );\r\n\t\t\ty1 = yt + ( pChar->h * m_yscale * EngineGlobals.screen_conv_y_multiplier );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tx0 += ( space_spacing + char_spacing ) * EngineGlobals.screen_conv_x_multiplier;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tp_vert->x\t= x0;\r\n\t\tp_vert->y\t= yt;\r\n\t\tp_vert->z\t= text_z;\r\n\t\tp_vert->rhw\t= 0.0f;\r\n\t\tp_vert->col\t= current_color;\r\n\t\tp_vert->u\t= u0;\r\n\t\tp_vert->v\t= v0;\r\n\t\t++p_vert;\r\n\r\n\t\tp_vert->x\t= x0;\r\n\t\tp_vert->y\t= y1;\r\n\t\tp_vert->z\t= text_z;\r\n\t\tp_vert->rhw\t= 0.0f;\r\n\t\tp_vert->col\t= current_color;\r\n\t\tp_vert->u\t= u0;\r\n\t\tp_vert->v\t= v1;\r\n\t\t++p_vert;\r\n\r\n\t\tp_vert->x\t= x1;\r\n\t\tp_vert->y\t= y1;\r\n\t\tp_vert->z\t= text_z;\r\n\t\tp_vert->rhw\t= 0.0f;\r\n\t\tp_vert->col\t= current_color;\r\n\t\tp_vert->u\t= u1;\r\n\t\tp_vert->v\t= v1;\r\n\t\t++p_vert;\r\n\r\n\t\tp_vert->x\t= x1;\r\n\t\tp_vert->y\t= yt;\r\n\t\tp_vert->z\t= text_z;\r\n\t\tp_vert->rhw\t= 0.0f;\r\n\t\tp_vert->col\t= current_color;\r\n\t\tp_vert->u\t= u1;\r\n\t\tp_vert->v\t= v0;\r\n\r\n\t\tfont_vertex_offset += 4;\r\n\r\n\t\tif( font_vertex_offset >= ( CHARS_PER_BUFFER * 4 ))\r\n\t\t{\r\n\t\t\t// Draw this buffer and cycle through to the next.\r\n\t\t\tEndDraw();\r\n\t\t\tBeginDraw();\r\n\t\t}\r\n\r\n\t\tx0 = x1 + ( char_spacing * EngineGlobals.screen_conv_x_multiplier );\r\n\r\n\t\tif( p_font != mp_font )\r\n\t\t{\r\n\t\t\t// We just used the button font, so return to the regular one.\r\n\t\t\tEndDraw();\r\n\t\t\tBeginDraw();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SText::EndDraw( void )\r\n{\r\n\tif( font_vertex_offset > 0 )\r\n\t{\r\n\t\t// Subsequent processing within Draw() will use this font\r\n\t\t// Draw() may call this function to temporarily switch fonts\r\n\t\tSFont *p_font = ( spOverrideFont ) ? spOverrideFont : mp_font;\r\n\t\t\r\n\t\t// Set up the render state and submit.\r\n\t\tset_pixel_shader( PixelShader4 );\r\n\t\tset_vertex_shader( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2( 0 ));\r\n\r\n\t\tset_texture( 0, p_font->pD3DTexture, p_font->pD3DPalette );\r\n\r\n\t\tEngineGlobals.p_Device->DrawVerticesUP( D3DPT_QUADLIST, font_vertex_offset, &( font_vertex_buffer[0] ), sizeof( sFontVert ));\r\n\r\n\t\t// Reset offset.\r\n\t\tfont_vertex_offset = 0;\r\n\r\n\t\t// We can now return to using the regular font (no override).\r\n\t\tspOverrideFont = NULL;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SetTextWindow( uint16 x0, uint16 x1, uint16 y0, uint16 y1 )\r\n{\r\n}\r\n\r\n} // namespace Xbox\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/chars.h",
    "content": "#ifndef __CHARS_H\r\n#define __CHARS_H\r\n\r\n#include <gfx/xbox/nx/sprite.h>\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n\r\ntypedef struct\r\n{\r\n\tfloat\tu0, v0, u1, v1;\r\n\tuint16\tw, h;\r\n\tuint16\tBaseline;\r\n}\r\nSChar;\r\n\r\n\r\nstruct SFont\r\n{\r\npublic:\r\n\tuint32\t\tGetDefaultHeight() const;\r\n\tuint32\t\tGetDefaultBase() const;\r\n\r\n//\tvoid\t\tBeginText(uint32 rgba, float Scale);\r\n//\tvoid\t\tDrawString(char *String, float x0, float y0);\r\n//\tvoid\t\tEndText(void);\r\n\tvoid\t\tQueryString(char *String, float &width, float &height);\r\n\r\n\t//char Name[16];\r\n\tuint32\t\tDefaultHeight, DefaultBase;\r\n\tSChar\t\t*pChars;\r\n\tuint8\t\tMap[256];\r\n\tuint8\t\tSpecialMap[32];\r\n//\tuint8\t\t*pVifData;\r\n//\tuint32\t\tVifSize;\r\n//\tuint64\t\tRegTEX0, RegTEX1;\r\n\tSFont\t\t*pNext;\r\n\r\n\tsint16\t\tmCharSpacing;\r\n\tsint16\t\tmSpaceSpacing;\r\n\tuint32\t\tmRGBATab[16];\r\n\t\r\n\tIDirect3DTexture8*\tpD3DTexture;\t\t// To do - these should probably be replaced with an sTexture.\r\n\tIDirect3DPalette8*\tpD3DPalette;\r\n};\r\n\r\n\r\n\r\nSFont*\t\tInitialiseMemoryResidentFont( void );\r\nSFont*\t\tLoadFont( const char* Filename, bool memory_resident = false );\r\nvoid\t\tUnloadFont( SFont * );\r\nvoid\t\tSetTextWindow( uint16 x0, uint16 x1, uint16 y0, uint16 y1 );\r\n\r\n\r\nstruct SText : public SDraw2D\r\n{\r\n\tpublic:\r\n\t\t\t\t\tSText( float pri = 0.0f );\r\n\tvirtual\t\t\t~SText();\r\n\r\n\tSFont\t\t\t*mp_font;\r\n\r\n\tchar\t\t\t*mp_string;\r\n\tfloat\t\t\tm_xpos;\r\n\tfloat\t\t\tm_ypos;\r\n\tfloat\t\t\tm_xscale;\r\n\tfloat\t\t\tm_yscale;\r\n\tuint32\t\t\tm_rgba;\r\n\tbool\t\t\tm_color_override;\r\n\t\r\n\t// used in conjunction with BeginDraw()\r\n\t// if set, use specified font instead of mp_font\r\n\t// if not, use mp_font\r\n\tstatic SFont *\tspOverrideFont;\r\n\r\n\tvoid\t\t\tBeginDraw( void );\r\n\tvoid\t\t\tDraw( void );\r\n\tvoid\t\t\tEndDraw( void );\r\n};\r\n\r\nvoid SwizzleTexture( void *dstBuffer, void *srcBuffer, int width, int height, int32 depth, int32 stride );\r\n\r\n\r\nextern uint32 FontVramBase;\r\nextern SFont *pFontList;\r\nextern SFont *pButtonsFont;\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n\r\n#endif // __CHARS_H\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/gamma.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics (GFX)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgamma.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t02/27/02\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGamma setting code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\r\n#include <xtl.h>\r\n#include \"gamma.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Some defines for gamma settings.\r\n#define gammaDefault\t1.0f\r\n#define gammaDomain\t\t256\r\n#define gammaRange\t\t256.0f\r\n#define MIN_GAMMA\t\t0.0f\r\n#define MAX_GAMMA\t\t2.0f\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic D3DGAMMARAMP\tgammaTable;\r\nstatic float\t\tgammaValueR = gammaDefault;\t// Current red gamma value.\r\nstatic float\t\tgammaValueG = gammaDefault;\t// Current green gamma value.\r\nstatic float\t\tgammaValueB = gammaDefault;\t// Current blue gamma value.\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void gammaInitTable( void )\r\n{\r\n\t// Create the gamma intensity lookup table.\r\n\t// It works like this: given a colour value r [0,255] do r' = gammaTable.red[r] etc.\r\n\tfor( int i = 0; i < gammaDomain; ++i )\r\n\t{\r\n\t\tgammaTable.red[i]\t= (BYTE)((float)gammaRange * pow(((float)i / (float)gammaDomain ), 1.0f / gammaValueR ));\r\n\t\tgammaTable.green[i]\t= (BYTE)((float)gammaRange * pow(((float)i / (float)gammaDomain ), 1.0f / gammaValueG ));\r\n\t\tgammaTable.blue[i]\t= (BYTE)((float)gammaRange * pow(((float)i / (float)gammaDomain ), 1.0f / gammaValueB ));\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid gammaSetValue( float gr, float gg, float gb )\r\n{\r\n\tgammaValueR = gr;\r\n\tgammaValueG = gg;\r\n\tgammaValueB = gb;\r\n\r\n\t// Create the table.\r\n\tgammaInitTable();\r\n\r\n\t// Pass the table along to the hardware.\r\n\tD3DDevice_SetGammaRamp( D3DSGR_NO_CALIBRATION, &gammaTable );\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SetGammaNormalized( float fr, float fg, float fb )\r\n{\r\n\t// Cap it....\r\n\tfr = ( fr < 0.0f ) ? 0.0f : (( fr > 1.0f ) ? 1.0f : fr );\r\n\tfg = ( fg < 0.0f ) ? 0.0f : (( fg > 1.0f ) ? 1.0f : fg );\r\n\tfb = ( fb < 0.0f ) ? 0.0f : (( fb > 1.0f ) ? 1.0f : fb );\r\n\r\n\t// Scale it....\r\n\tfr *= MAX_GAMMA;\r\n\tfg *= MAX_GAMMA;\r\n\tfb *= MAX_GAMMA;\r\n\r\n\t// Offset it.\r\n\tfr += 0.5f;\r\n\tfg += 0.5f;\r\n\tfb += 0.5f;\r\n\r\n\t// f<col> now goes from 0.5 to 2.5.\r\n\tgammaSetValue( fr, fg, fb );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid GetGammaNormalized( float *fr, float *fg, float *fb )\r\n{\r\n\t// Peform the opposite operation to that done in SetGammaNormalized().\r\n\t*fr = ( gammaValueR - 0.5f ) / MAX_GAMMA;\r\n\t*fg = ( gammaValueG - 0.5f ) / MAX_GAMMA;\r\n\t*fb = ( gammaValueB - 0.5f ) / MAX_GAMMA;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n} // namespace Gfx\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/gamma.h",
    "content": "#ifndef\t__GAMMA_H__\r\n#define\t__GAMMA_H__\r\n\r\nnamespace NxXbox\r\n{\r\n\tvoid SetGammaNormalized( float fr, float fg, float fb );\r\n\tvoid GetGammaNormalized( float *fr, float *fg, float *fb );\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/grass.cpp",
    "content": "#include <xtl.h>\r\n#include <xgraphics.h>\r\n#include <core\\defines.h>\r\n#include <core\\crc.h>\r\n#include <sys\\file\\filesys.h>\r\n#include <gfx\\xbox\\p_nxtexture.h>\r\n#include \"nx_init.h\"\r\n#include \"render.h\"\r\n#include \"grass.h\"\r\n\r\nstatic bool\t\t\t\tbumpsLoaded = false;\r\nNxXbox::sMaterial\t\twaterMaterial;\r\nNxXbox::sTexture\t\twaterTextures[2];\r\n\r\nIDirect3DTexture8\t\t*pBumpTextures[17];\r\nNxXbox::sTexture\t\tbumpTextures[17];\r\n\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Unswizzles a 2D texture before it gets unlocked.\t\t\t\t  */\r\n/* Note: this operation can be very slow.\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nVOID XBUtil_UnswizzleTexture2D( D3DLOCKED_RECT* pLock, const D3DSURFACE_DESC* pDesc )\r\n{\r\n    DWORD dwPixelSize   = XGBytesPerPixelFromFormat( pDesc->Format );\r\n    DWORD dwTextureSize = pDesc->Width * pDesc->Height * dwPixelSize;\r\n\r\n    BYTE* pSrcBits = new BYTE[ dwTextureSize ];\r\n    memcpy( pSrcBits, pLock->pBits, dwTextureSize );\r\n    \r\n    XGUnswizzleRect( pSrcBits, pDesc->Width, pDesc->Height, NULL, pLock->pBits, \r\n                     0, NULL, dwPixelSize );\r\n\r\n    delete [] pSrcBits;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Swizzles a 2D texture before it gets unlocked.\t\t\t\t  */\r\n/* Note: this operation can be very slow.\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nVOID XBUtil_SwizzleTexture2D( D3DLOCKED_RECT* pLock, const D3DSURFACE_DESC* pDesc )\r\n{\r\n    DWORD dwPixelSize   = XGBytesPerPixelFromFormat( pDesc->Format );\r\n    DWORD dwTextureSize = pDesc->Width * pDesc->Height * dwPixelSize;\r\n\r\n    BYTE* pSrcBits = new BYTE[ dwTextureSize ];\r\n    memcpy( pSrcBits, pLock->pBits, dwTextureSize );\r\n    \r\n    XGSwizzleRect( pSrcBits, 0, NULL, pLock->pBits,\r\n                  pDesc->Width, pDesc->Height, \r\n                  NULL, dwPixelSize );\r\n\r\n    delete [] pSrcBits;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* There are 17 frames. Each has 3 level mipmaps\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nHRESULT LoadBumpTextures( void )\r\n{\r\n\tHRESULT hr = S_OK;\r\n\tfor( int i = 0; i < 17; ++i )\r\n    {\r\n\t\tint height = 128, width = 128;\r\n\r\n        // Find file name\r\n\t\tchar strBumpFile[128];\r\n\t\tsprintf( strBumpFile, \"c:\\\\skate5\\\\data\\\\images\\\\miscellaneous\\\\%d.bum\", i );\r\n        \r\n        // Open and read file.\r\n\t\tvoid *fp = File::Open( strBumpFile, \"rb\" );\r\n        if( !fp )\r\n            return E_FAIL;\r\n      \r\n\t\t// Create texture.\r\n\t\tif( FAILED( hr = D3DDevice_CreateTexture( width,\r\n            height,\r\n            3,\r\n            NULL,\r\n            D3DFMT_V8U8,\r\n            D3DPOOL_MANAGED,\r\n\t\t\t&pBumpTextures[i] )))\r\n            return hr;\r\n       \r\n        // Lock first level.\r\n        D3DLOCKED_RECT lr; \r\n        D3DSURFACE_DESC desc;\r\n        pBumpTextures[i]->GetLevelDesc( 0, &desc );\r\n        pBumpTextures[i]->LockRect( NULL, &lr, NULL, NULL );\r\n        XBUtil_UnswizzleTexture2D( &lr, &desc );\r\n\r\n\t\tFile::Read( lr.pBits, sizeof( WORD ), height * width, fp );\r\n\r\n\t\t// Modulate the size of the offset.\r\n\t\tuint8 *p_mod = (uint8*)lr.pBits;\r\n\t\tfor( int p = 0; p < height * width * 2; ++p )\r\n\t\t{\r\n\t\t\t// Noticed occasionally this maps to outside of the map tetxure with texbem.\r\n\t\t\t// Culprit appears to be the maximum negative value (0, given 0x80 offset of values\r\n\t\t\t// in V8U8 format).\r\n\t\t\tif( *p_mod == 0 )\r\n\t\t\t{\r\n\t\t\t\t// Max negative offset.\r\n\t\t\t\t*p_mod = 1;\r\n\t\t\t}\r\n\t\t\t++p_mod;\r\n\t\t}\r\n\t\t\r\n\t\tXBUtil_SwizzleTexture2D( &lr, &desc );\r\n        pBumpTextures[i]->UnlockRect( 0 );\r\n\r\n        // Load mipmaps\r\n\t\tint level = 0;\r\n        while( ++level < 3 )\r\n        {\r\n            width >>= 1;\r\n            height >>= 1;\r\n                        \r\n            pBumpTextures[i]->GetLevelDesc( level, &desc );\r\n            pBumpTextures[i]->LockRect( level, &lr, NULL,NULL );\r\n            XBUtil_UnswizzleTexture2D( &lr, &desc );\r\n\r\n\t\t\tFile::Read( lr.pBits, sizeof( WORD ), height * width, fp );\r\n\r\n\t\t\t// Modulate the size of the offset.\r\n\t\t\tp_mod = (uint8*)lr.pBits;\r\n\t\t\tfor( int p = 0; p < height * width * 2; ++p )\r\n\t\t\t{\r\n\t\t\t\t// Noticed occasionally this maps to outside of the map tetxure with texbem.\r\n\t\t\t\t// Culprit appears to be the maximum negative value (0, given 0x80 offset of values\r\n\t\t\t\t// in V8U8 format).\r\n\t\t\t\tif( *p_mod == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Max negative offset.\r\n\t\t\t\t\t*p_mod = 1;\r\n\t\t\t\t}\r\n\t\t\t\t++p_mod;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tXBUtil_SwizzleTexture2D( &lr, &desc );\r\n            pBumpTextures[i]->UnlockRect( level );\r\n        }\r\n\t\tFile::Close( fp );\r\n\r\n\t\tbumpTextures[i].pD3DTexture = pBumpTextures[i];\r\n\t\tbumpTextures[i].pD3DPalette\t= NULL;\r\n\t}\r\n\r\n\t// Set up the texture container for the bump textures.\r\n\tZeroMemory( &waterTextures[0],\tsizeof( NxXbox::sTexture ));\r\n\twaterTextures[0].pD3DTexture = pBumpTextures[0];\r\n\r\n\treturn hr;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CreateWaterMaterial( NxXbox::sMaterial *p_material )\r\n{\r\n\t// Set texture 0 to be the first bump texture.\r\n\tp_material->mp_tex[0]\t\t\t= &waterTextures[0];\r\n\tp_material->mp_tex[1]\t\t\t= &waterTextures[1];\r\n\tp_material->m_reg_alpha[0]\t\t= NxXbox::vBLEND_MODE_BLEND_FIXED | ( 0x40UL << 24 );\r\n\tp_material->m_color[0][3]\t\t= 0.5f;\r\n\tp_material->m_passes\t\t\t= 2;\r\n\r\n\t// Add transparent flag.\r\n\tp_material->m_flags[0]\t\t\t|= 0x40;\r\n\tp_material->m_flags[1]\t\t\t= 0x00;\r\n\r\n\t// Add bump setup flag.\r\n\tp_material->m_flags[0]\t\t\t|= MATFLAG_BUMP_SIGNED_TEXTURE;\r\n\tp_material->m_flags[1]\t\t\t|= MATFLAG_BUMP_LOAD_MATRIX;\r\n\r\n\tp_material->m_uv_wibble\t\t\t= false;\r\n\tp_material->m_flags[0]\t\t\t&= ~MATFLAG_ENVIRONMENT;\r\n\tp_material->m_flags[0]\t\t\t&= ~MATFLAG_UV_WIBBLE;\r\n\r\n\t// Adjust K.\r\n\tp_material->m_k[0]\t\t\t\t= 0.0f;\r\n\tp_material->m_k[1]\t\t\t\t= 0.0f;\r\n\r\n\t// Set texture address mode.\r\n\tp_material->m_uv_addressing[0]\t= 0x00000000UL;\r\n\tp_material->m_uv_addressing[1]\t= 0x00000000UL;\r\n\r\n\t// Set the draw order to ensure meshes are drawn from the bottom up. Default draw order for transparent\r\n\t// meshes is 1000.0, so add a little onto that.\r\n\tp_material->m_sorted\t\t\t= false;\r\n\tp_material->m_draw_order\t\t= 1501.0f;\r\n\r\n\t// Create the animating texture details.\r\n\tp_material->m_texture_wibble\t= true;\r\n\tp_material->m_flags[0]\t\t\t|= MATFLAG_PASS_TEXTURE_ANIMATES;\r\n\r\n\tp_material->mp_wibble_texture_params\t\t\t\t\t\t= new NxXbox::sTextureWibbleParams;\r\n\tp_material->mp_wibble_texture_params->m_num_keyframes[0]\t= 18;\r\n\tp_material->mp_wibble_texture_params->m_phase[0]\t\t\t= 0;\r\n\tp_material->mp_wibble_texture_params->m_num_iterations[0]\t= 0;\r\n\tp_material->mp_wibble_texture_params->mp_keyframes[0]\t\t= new NxXbox::sTextureWibbleKeyframe[18];\r\n\tp_material->mp_wibble_texture_params->mp_keyframes[1]\t\t= NULL;\r\n\tp_material->mp_wibble_texture_params->mp_keyframes[2]\t\t= NULL;\r\n\tp_material->mp_wibble_texture_params->mp_keyframes[3]\t\t= NULL;\r\n\r\n\tfor( int f = 0; f < 18; ++f )\r\n\t{\r\n\t\tp_material->mp_wibble_texture_params->mp_keyframes[0][f].m_time\t\t\t\t\t\t= (( f * 1000 ) / 30 );\r\n\t\tp_material->mp_wibble_texture_params->mp_keyframes[0][f].mp_texture\t\t\t\t\t= &bumpTextures[f % 17];\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool AddWater( Nx::CXboxGeom *p_geom, NxXbox::sMesh *p_mesh )\r\n{\r\n\t// Ensure there is at least two sets of uv's available.\r\n\tDbg_Assert( p_mesh->m_uv0_offset > 0 );\r\n\r\n\t// Check to see whether the texture we want is present.\r\n\tNx::CScene\t\t*p_sky_scene\t\t= Nx::CEngine::sGetSkyScene();\r\n\tNx::CTexDict\t*p_tex_dict\t\t\t= p_sky_scene->GetTexDict();\r\n\tNx::CTexture\t*p_texture\t\t\t= p_tex_dict->GetTexture( 0x96d0bf08UL );\r\n\r\n\tif( p_texture == NULL )\r\n\t\treturn false;\r\n\r\n\tNx::CXboxTexture\t*p_xbox_texture = static_cast<Nx::CXboxTexture*>( p_texture );\r\n\tNxXbox::sTexture\t*p_engine_texture\t= p_xbox_texture->GetEngineTexture();\r\n\tCopyMemory( &waterTextures[1], p_engine_texture, sizeof( NxXbox::sTexture ));\r\n\r\n\tint num_tc_sets = ( p_mesh->m_vertex_stride - p_mesh->m_uv0_offset ) / 8;\r\n\tif( num_tc_sets == 1 )\r\n\t{\r\n\t\t// We need to alter this mesh to create two sets of uv's.\r\n\t\tIDirect3DVertexBuffer8* p_new_buffer = p_mesh->AllocateVertexBuffer(( p_mesh->m_vertex_stride + 8 ) * p_mesh->m_num_vertices );\r\n\t\tBYTE* p_read_byte;\r\n\t\tBYTE* p_write_byte;\r\n\t\tp_mesh->mp_vertex_buffer[0]->Lock( 0, 0, &p_read_byte, D3DLOCK_READONLY | D3DLOCK_NOFLUSH );\r\n\t\tp_new_buffer->Lock( 0, 0, &p_write_byte, D3DLOCK_NOFLUSH );\r\n\r\n\t\tfor( int v = 0; v < p_mesh->m_num_vertices; ++v )\r\n\t\t{\r\n\t\t\t// Copy all existing vertex information.\r\n\t\t\tCopyMemory( p_write_byte, p_read_byte, p_mesh->m_vertex_stride );\r\n\t\t\tp_read_byte\t\t+= p_mesh->m_vertex_stride;\r\n\t\t\tp_write_byte\t+= p_mesh->m_vertex_stride + 8;\r\n\t\t}\r\n\r\n\t\tdelete p_mesh->mp_vertex_buffer[0];\r\n\t\tp_mesh->mp_vertex_buffer[0] = p_new_buffer;\r\n\r\n\t\tp_mesh->m_vertex_stride += 8;\r\n\r\n\t\t// Switch the vertex shader.\r\n\t\tp_mesh->m_vertex_shader[0]\t&= ~( D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2( 0 ));\r\n\t\tp_mesh->m_vertex_shader[0]\t|= D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE2( 0 ) | D3DFVF_TEXCOORDSIZE2( 1 );\r\n\t}\r\n\r\n\tNxXbox::sMaterial *p_water_mat = p_mesh->mp_material;\r\n\r\n\tCreateWaterMaterial( p_water_mat );\r\n\r\n\t// Disable skater shadow on the mesh.\r\n\tp_mesh->m_flags |= NxXbox::sMesh::MESH_FLAG_NO_SKATER_SHADOW;\r\n\tp_mesh->m_flags |= NxXbox::sMesh::MESH_FLAG_BUMPED_WATER;\r\n\r\n\t// Set the water pixel shader.\r\n\tp_mesh->m_pixel_shader\t= PixelShaderBumpWater;\r\n\t\t\r\n\t// Go through and calculate new texture coordinates based on the x-z space of the vertex positions.\r\n\tBYTE *p_byte_dest;\r\n\tp_mesh->mp_vertex_buffer[0]->Lock( 0, 0, &p_byte_dest, 0 );\r\n\tfor( uint32 vert = 0; vert < p_mesh->m_num_vertices; ++vert )\r\n\t{\r\n\t\tD3DXVECTOR3 *p_pos\t= (D3DXVECTOR3*)( p_byte_dest + ( vert * p_mesh->m_vertex_stride ));\r\n\r\n\t\tfloat u0\t\t\t\t= p_pos->x / 192.0f;\r\n\t\tfloat v0\t\t\t\t= p_pos->z / 192.0f;\r\n\r\n\t\tfloat u1\t\t\t\t= p_pos->x / 96.0f;\r\n\t\tfloat v1\t\t\t\t= p_pos->z / 96.0f;\r\n\r\n\r\n\t\tfloat *p_tex\t\t= (float*)( p_byte_dest + p_mesh->m_uv0_offset + ( vert * p_mesh->m_vertex_stride ));\r\n\t\tp_tex[0]\t\t\t= u0;\r\n\t\tp_tex[1]\t\t\t= v0;\r\n\t\tp_tex[2]\t\t\t= u1;\r\n\t\tp_tex[3]\t\t\t= v1;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool AddGrass( Nx::CXboxGeom *p_geom, NxXbox::sMesh *p_mesh )\r\n{\r\n\t// Need a material to proceed.\r\n\tif( p_mesh->mp_material == NULL )\r\n\t\treturn false;\r\n\r\n\tif( p_mesh->mp_material->m_flags[0] & MATFLAG_WATER_EFFECT )\r\n\t{\r\n\t\treturn AddWater( p_geom, p_mesh );\r\n\t}\r\n\r\n\tif( p_mesh->mp_material->m_grass_layers == 0 )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// At this stage we know we want to add grass.\r\n\tDbg_Assert( p_mesh->mp_material->m_grass_layers > 0 );\r\n\r\n\tint\t\tgrass_layers\t\t= ( p_mesh->mp_material->m_grass_layers > 5 ) ? 5 : p_mesh->mp_material->m_grass_layers;\r\n\tfloat\theight_per_layer\t= p_mesh->mp_material->m_grass_height / grass_layers;\r\n\t\r\n\tfor( int layer = 0; layer < grass_layers; ++layer )\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().BottomUpHeap());\r\n\t\tNxXbox::sMesh *p_grass_mesh = p_mesh->Clone( false );\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\t// Disable skater shadow on the mesh.\r\n\t\tp_grass_mesh->m_flags |= NxXbox::sMesh::MESH_FLAG_NO_SKATER_SHADOW;\r\n\t\t\r\n\t\t// Turn off anisotropic filtering and z-write on the mesh.\r\n\t\tp_grass_mesh->m_flags |= ( NxXbox::sMesh::MESH_FLAG_NO_ANISOTROPIC | NxXbox::sMesh::MESH_FLAG_NO_ZWRITE );\r\n\t\t\r\n\t\t// Now point the mesh to a different material, first build the material checksum from the name of the parent\r\n\t\t// material (Grass) and the name of the sub material (Grass_LayerX)...\r\n\t\tchar material_name[64];\r\n\t\tsprintf( material_name, \"Grass-Grass_Layer%d\", layer );\r\n\t\tuint32 material_checksum\t= Crc::GenerateCRCCaseSensitive( material_name, strlen( material_name ));\r\n\r\n\t\t// ...then use the checksum to lookup the material.\r\n\t\tp_grass_mesh->mp_material\t= p_geom->mp_scene->GetEngineScene()->GetMaterial( material_checksum );\r\n\t\tDbg_MsgAssert( p_grass_mesh->mp_material, ( \"Grass maaterial for layer %d appears to be named badly\", layer ));\r\n\t\t\r\n\t\t// We need also to override the mesh pixel shader, which may have been setup for a multipass material.\r\n\t\tNxXbox::GetPixelShader( p_grass_mesh->mp_material, &p_grass_mesh->m_pixel_shader );\r\n\t\t\r\n\t\t// Add transparent flag to the material.\r\n\t\tp_grass_mesh->mp_material->m_flags[0]\t\t|= 0x40;\r\n\r\n\t\t// Adjust K for the material.\r\n\t\tp_grass_mesh->mp_material->m_k[0]\t\t\t= -2.0f;\r\n\r\n\t\t// Set the draw order to ensure meshes are drawn from the bottom up. Default draw order for transparent\r\n\t\t// meshes is 1000.0, so add a little onto that.\r\n\t\tp_grass_mesh->mp_material->m_sorted\t\t = false;\r\n\t\tp_grass_mesh->mp_material->m_draw_order\t = 1100.0f + ( layer * 0.1f );\r\n\t\t\r\n\t\t// Go through and move all the vertices up a little, and calculate new texture coordinates based on the x-z space of the vertex positions.\r\n\t\tBYTE *p_byte_dest;\r\n\t\tp_grass_mesh->mp_vertex_buffer[0]->Lock( 0, 0, &p_byte_dest, 0 );\r\n\r\n\t\tfor( uint32 vert = 0; vert < p_grass_mesh->m_num_vertices; ++vert )\r\n\t\t{\r\n\t\t\tD3DXVECTOR3 *p_pos = (D3DXVECTOR3*)( p_byte_dest + ( vert * p_grass_mesh->m_vertex_stride ));\r\n\t\t\tp_pos->y += ( height_per_layer * ( layer + 1 ));\r\n\r\n\t\t\tfloat u\t\t\t= p_pos->x / 48.0f;\r\n\t\t\tfloat v\t\t\t= p_pos->z / 48.0f;\r\n\t\t\tfloat *p_tex\t= (float*)( p_byte_dest + p_grass_mesh->m_uv0_offset + ( vert * p_grass_mesh->m_vertex_stride ));\r\n\t\t\tp_tex[0]\t\t= u;\t\t\r\n\t\t\tp_tex[1]\t\t= v;\r\n\t\t}\r\n\r\n\t\tp_geom->AddMesh( p_grass_mesh );\r\n\t}\r\n\r\n\t// Turn off anisotropic filtering on the base mesh also.\r\n\tp_mesh->m_flags |= NxXbox::sMesh::MESH_FLAG_NO_ANISOTROPIC;\r\n\t\r\n\treturn true;\r\n}\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/grass.h",
    "content": "#pragma once\r\n//-----------------------------------------------------------------------------\r\n// File: XBFur.h\r\n//\r\n// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.\r\n//-----------------------------------------------------------------------------\r\n#include <xtl.h>\r\n//#include \"xfvf.h\"\r\n#include <gfx/xbox/p_nxgeom.h>\r\n\r\n#define XBFUR_MAXSLICE_LOG2 5\r\n#define XBFUR_MAXSLICE (1 << XBFUR_MAXSLICE_LOG2)\r\n\r\nextern float g_fOneInch;\r\n\r\n#define FVF_XYZDIFF (D3DFVF_XYZ|D3DFVF_DIFFUSE)\r\n\r\ntypedef struct sFVFT_XYZDIFF\r\n{\r\n    D3DVECTOR v;\r\n    DWORD diff;\r\n} FVFT_XYZDIFF;\r\n\r\n\r\n// patch generation\r\n\r\n// a fuzz is a single hair follicle, blade of grass, etc.\r\nstruct Fuzz\r\n{\r\n    D3DVECTOR dp;            // velocity\r\n    D3DVECTOR ddp;            // acceleration\r\n    D3DXCOLOR colorBase;\r\n    D3DXCOLOR colorTip;\r\n};\r\n\r\n// a fuzz instance is a single instance of a fuzz\r\n// located at x, z on the patch\r\n// we create only a limited number of unique fuzzes\r\n// and index the library with lidx.\r\nstruct FuzzInst\r\n{\r\n    float x, z;                // fuzz location\r\n    int lidx;                // library index\r\n};\r\n\r\n// a fur patch is a volume that holds fuzzes.\r\n// xsize and zsize are chosen by the user\r\n// ysize is calculated using the height of the \r\n// tallest fuzz\r\nclass CXBFur\r\n{\r\n    friend class CXBFurMesh;\r\npublic:\r\n    DWORD m_dwSeed;            // patch seed\r\n    \r\n    float m_fXSize;            // patch size in world coords\r\n    float m_fYSize;\r\n    float m_fZSize;\r\n\r\n    // fuzz library\r\n    DWORD m_dwNumSegments;    // # of segments in highest LOD\r\n    Fuzz m_fuzzCenter;        // fuzz constant\r\n    Fuzz m_fuzzRandom;        // random offset around center\r\n    DWORD m_dwNumFuzzLib;    // # of fuzz in the library\r\n    Fuzz *m_pFuzzLib;        // fuzz library\r\n\r\n    // fuzz instances\r\n    DWORD m_dwNumFuzz;        // # of fuzz in this patch\r\n    FuzzInst *m_pFuzz;\r\n\r\n    // patch volume\r\n    DWORD m_dwNumSlices;    // # of layers in the volume\r\n    DWORD m_dwSliceSize;        // width*height\r\n    DWORD m_dwSliceXSize;        // width of volume texture slice\r\n    DWORD m_dwSliceZSize;        // height of volume texture slice\r\n    LPDIRECT3DTEXTURE8 m_apSliceTexture[XBFUR_MAXSLICE * 2 - 1];    // slices of volume texture\r\n                    // ... followed by level-of-detail textures  N/2, N/4, N/8, ... 1\r\n\r\n    // LOD textures\r\n    DWORD m_dwNumSlicesLOD; // number of slices in current level of detail\r\n    float m_fLevelOfDetail;    // current LOD value\r\n    DWORD m_iLOD;            // current integer LOD value\r\n    float m_fLODFraction;    // fraction towards next coarser level-of-detail\r\n    DWORD m_dwLODMax;        // maximum LOD index\r\n    LPDIRECT3DTEXTURE8 *m_pSliceTextureLOD; // current level of detail pointer into m_apSliceTexture array\r\n\r\n    // hair lighting texture\r\n    D3DMATERIAL8 m_HairLightingMaterial;\r\n    LPDIRECT3DTEXTURE8 m_pHairLightingTexture;\r\n\r\n    // fin texture\r\n    DWORD m_finWidth, m_finHeight;        // size of fin texture\r\n    float m_fFinXFraction, m_fFinZFraction;    // portion of hair texture to put into fin\r\n    LPDIRECT3DTEXTURE8 m_pFinTexture;    // texture projected from the side\r\n\r\n    CXBFur();\r\n    ~CXBFur();\r\n    void InitFuzz(DWORD nfuzz, DWORD nfuzzlib);\r\n    void GenSlices(DWORD nslices, DWORD slicexsize, DWORD slicezsize);\r\n    void GenFin(DWORD finWidth, DWORD finHeight, float fFinXFraction, float fFinZFraction);\r\n    void GetLinesVertexBuffer(IDirect3DVertexBuffer8 **ppVB);\r\n    void RenderLines();\r\n    void Save(char *fname, int flags);\r\n    void Load(char *fname);\r\n    HRESULT SetHairLightingMaterial(D3DMATERIAL8 *pMaterial);\r\n    void SetPatchSize(float x, float z)\r\n    {\r\n        m_fXSize = x;\r\n        m_fZSize = z;\r\n        InitFuzz(m_dwNumFuzz, m_dwNumFuzzLib);    // re-init the fuzz. automatically sets ysize\r\n    };\r\n    void SetFVel(float cx, float cy, float cz, float rx, float ry, float rz)\r\n    {\r\n        m_fuzzCenter.dp.x = cx; m_fuzzCenter.dp.y = cy; m_fuzzCenter.dp.z = cz;\r\n        m_fuzzRandom.dp.x = rx; m_fuzzRandom.dp.y = ry; m_fuzzRandom.dp.z = rz;\r\n    };\r\n    void SetFAcc(float cx, float cy, float cz, float rx, float ry, float rz)\r\n    {\r\n        m_fuzzCenter.ddp.x = cx; m_fuzzCenter.ddp.y = cy; m_fuzzCenter.ddp.z = cz;\r\n        m_fuzzRandom.ddp.x = rx; m_fuzzRandom.ddp.y = ry; m_fuzzRandom.ddp.z = rz;\r\n    };\r\n\r\n    // fLevelOfDetail can range from 0 to log2(NumSlices)\r\n    HRESULT SetLevelOfDetail(float fLevelOfDetail);\r\n    HRESULT ComputeLevelOfDetailTextures();\r\n    inline UINT LevelOfDetailCount(UINT iLOD)\r\n    {\r\n        return m_dwNumSlices >> iLOD;\r\n    }\r\n    inline UINT LevelOfDetailIndex(UINT iLOD)\r\n    {\r\n        UINT offset = 0;\r\n        for (UINT i = 1; i <= iLOD; i++)\r\n            offset += LevelOfDetailCount(i-1);\r\n        return offset;\r\n    }\r\n    inline UINT TotalTextureCount()\r\n    {\r\n        UINT TextureCount = 0;\r\n        for (UINT iLOD = 0; m_dwNumSlices >> iLOD; iLOD++)\r\n            TextureCount += LevelOfDetailCount(iLOD);\r\n        return TextureCount;\r\n    }\r\n\r\n    // Compress textures one at a time until all are done.\r\n    // Returns S_OK when all the textures are in fmtNew format.\r\n    // Returns S_FALSE if there are textures still to be done.\r\n    HRESULT CompressNextTexture(D3DFORMAT fmtNew, UINT *pTextureIndex);\r\n};\r\n\r\nHRESULT\tFillHairLightingTexture(D3DMATERIAL8 *pMaterial, LPDIRECT3DTEXTURE8 pTexture);\r\nbool\tAddGrass( Nx::CXboxGeom *p_geom, NxXbox::sMesh *p_mesh );\r\nHRESULT\tLoadBumpTextures( void );\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/instance.cpp",
    "content": "#include <gfx\\NxLight.h>\r\n#include <gfx\\DebugGfx.h>\r\n#include <gfx\\DebugGfx.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include \"nx_init.h\"\r\n#include \"instance.h\"\r\n#include \"anim.h\"\r\n#include \"render.h\"\r\n#include \"occlude.h\"\r\n#include \"anim_vertdefs.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\nstatic Mth::Matrix\t*pLastBoneTransforms\t= NULL;\r\nCInstance\t\t\t*pFirstInstance\t\t\t= NULL;\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int sort_by_bone_transform( const void *p1, const void *p2 )\r\n{\r\n\tCInstance\t*p_mesh1\t\t= *((CInstance**)p1 );\r\n\tCInstance\t*p_mesh2\t\t= *((CInstance**)p2 );\r\n\r\n\tMth::Matrix *p_mat1\t\t\t= p_mesh1->GetBoneTransforms();\r\n\tMth::Matrix *p_mat2\t\t\t= p_mesh2->GetBoneTransforms();\r\n\t\r\n\tif(( p_mat1 == NULL ) || ( p_mesh1->GetScene()->m_numHierarchyObjects > 0 ))\r\n\t{\r\n\t\tif(( p_mat2 == NULL ) || ( p_mesh2->GetScene()->m_numHierarchyObjects > 0 ))\r\n\t\t{\r\n\t\t\tint num_st1 = p_mesh1->GetScene()->m_num_semitransparent_mesh_entries;\r\n\t\t\tint num_st2 = p_mesh2->GetScene()->m_num_semitransparent_mesh_entries;\r\n\r\n\t\t\tif( num_st1 == num_st2 )\r\n\t\t\t{\r\n\t\t\t\t// Try sorting on the material draw order of the first semitransparent mesh.\r\n\t\t\t\tif( num_st1 > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tNxXbox::sMaterial\t*p_material1 = p_mesh1->GetScene()->m_meshes[p_mesh1->GetScene()->m_first_semitransparent_entry]->mp_material;\r\n\t\t\t\t\tNxXbox::sMaterial\t*p_material2 = p_mesh2->GetScene()->m_meshes[p_mesh2->GetScene()->m_first_semitransparent_entry]->mp_material;\r\n\r\n\t\t\t\t\tif( p_material1 && p_material2 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn ( p_material1->m_draw_order > p_material2->m_draw_order ) ? 1 : (( p_material1->m_draw_order < p_material2->m_draw_order ) ? -1 : 0 );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\r\n\t\t\treturn ( num_st1 > num_st2 ) ? 1 : -1;\r\n\t\t}\r\n\t\treturn 1;\r\n\t}\r\n\telse if(( p_mat2 == NULL ) || ( p_mesh2->GetScene()->m_numHierarchyObjects > 0 ))\r\n\t{\r\n\t\treturn -1;\r\n\t}\r\n\r\n\t// At this stage we know both instances have bone transforms.\r\n\tif( p_mat1 == p_mat2 )\r\n\t{\r\n\t\tint num_st1 = p_mesh1->GetScene()->m_num_semitransparent_mesh_entries;\r\n\t\tint num_st2 = p_mesh2->GetScene()->m_num_semitransparent_mesh_entries;\r\n\t\r\n\t\tif( num_st1 == num_st2 )\r\n\t\t\treturn 0;\r\n\t\r\n\t\treturn ( num_st1 > num_st2 ) ? 1 : -1;\r\n\t}\r\n\r\n\treturn((uint32)p_mat1 > (uint32)p_mat2 ) ? 1 : -1;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid render_instance( CInstance* p_instance, uint32 flags )\r\n{\r\n\t// Seed the static pointer off to NULL, otherwise if there is only one object with bone transforms, it will never update.\r\n\tpLastBoneTransforms = NULL;\r\n\r\n\tif( p_instance->GetActive())\r\n\t{\r\n\t\tset_frustum_bbox_transform( p_instance->GetTransform());\r\n\r\n\t\tbool render = true;\r\n\t\tif( !( flags & vRENDER_NO_CULLING ))\r\n\t\t{\r\n\t\t\t// Check whether this instance is visible.\r\n\t\t\trender = false;\r\n\t\t\tif( frustum_check_sphere( &p_instance->GetScene()->m_sphere_center, p_instance->GetScene()->m_sphere_radius ))\r\n\t\t\t{\r\n\t\t\t\tif( !TestSphereAgainstOccluders( &p_instance->GetScene()->m_sphere_center, p_instance->GetScene()->m_sphere_radius ))\r\n\t\t\t\t{\r\n\t\t\t\t\trender = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( render )\r\n\t\t{\r\n\t\t\tif( p_instance->GetBoneTransforms() != NULL )\r\n\t\t\t{\r\n\t\t\t\tstartup_weighted_mesh_vertex_shader();\r\n\t\t\t\tp_instance->Render( vRENDER_OPAQUE | vRENDER_SEMITRANSPARENT );\r\n\t\t\t\tshutdown_weighted_mesh_vertex_shader();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_instance->Render( vRENDER_OPAQUE | vRENDER_SEMITRANSPARENT );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Restore world transform to identity.\r\n\t\tD3DDevice_SetTransform( D3DTS_WORLD, &EngineGlobals.world_matrix );\r\n\t\tset_frustum_bbox_transform( NULL );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid render_instances( uint32 flags )\r\n{\r\n\t#define INSTANCE_ARRAY_SIZE\t4096\r\n\tstatic CInstance *p_instances[INSTANCE_ARRAY_SIZE];\r\n\tint current_index = 0;\r\n\r\n\tMth::Matrix t;\r\n\tt.Identity();\r\n\t\r\n\t// Seed the static pointer off to NULL, otherwise if there is only one object with bone transforms, it will never update.\r\n\tpLastBoneTransforms = NULL;\r\n\t\r\n\t// First go through and build a list of the visible instances.\r\n\tCInstance *p_instance = pFirstInstance;\r\n\twhile( p_instance )\r\n\t{\r\n\t\tif( p_instance->GetActive())\r\n\t\t{\r\n\t\t\t// Check to see whether this instance is of the type we want to render - opaque or semitransparent.\r\n\t\t\tif((( flags & vRENDER_OPAQUE ) && ( p_instance->GetScene()->m_num_mesh_entries > p_instance->GetScene()->m_num_semitransparent_mesh_entries )) ||\r\n\t\t\t   (( flags & vRENDER_SEMITRANSPARENT ) && ( p_instance->GetScene()->m_num_semitransparent_mesh_entries > 0 )))\r\n\t\t\t{\r\n\t\t\t\t// Check whether this instance is visible - if so, place it in the visible array.\r\n\t\t\t\tt.SetPos( p_instance->GetTransform()->GetPos());\r\n\t\t\t\tset_frustum_bbox_transform( &t );\r\n\t\t\t\t\r\n\t\t\t\t// For skinned objects, we have no idea how the skeleton transforms will be affecting the final position of each object.\r\n\t\t\t\t// This can sometimes result in small objects getting culled incorrectly. For these objects, increase the size of\r\n\t\t\t\t// the bounding sphere slightly.\r\n\t\t\t\tfloat radius = p_instance->GetScene()->m_sphere_radius;\r\n\t\t\t\tif( p_instance->GetBoneTransforms() && ( p_instance->GetScene()->m_numHierarchyObjects == 0 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tradius = ( radius < 72.0f ) ? 72.0f : radius;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// The logic code already sets the active flag based on visibility, so there is no need to perform a second visibility check\r\n\t\t\t\t// at this point.\r\n\t\t\t\t// We do, however, want to test against occluders.\r\n\t\t\t\tif( !TestSphereAgainstOccluders( &p_instance->GetScene()->m_sphere_center, radius ))\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( current_index < INSTANCE_ARRAY_SIZE );\r\n\t\t\t\t\tp_instances[current_index++] = p_instance;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tp_instance = p_instance->GetNextInstance();\r\n\t}\r\n\r\n\t// Now sort the list based on bone transform and number of semitransparent objects in scene.\r\n\tif( current_index > 0 )\r\n\t{\r\n\t\tqsort( p_instances, current_index, sizeof( CInstance* ), sort_by_bone_transform );\r\n\r\n\t\tint i = 0;\r\n\r\n\t\t// First render the instances with bone transforms.\r\n\t\tstartup_weighted_mesh_vertex_shader();\r\n\t\tfor( ; i < current_index; ++i )\r\n\t\t{\r\n\t\t\tif(( p_instances[i]->GetBoneTransforms() == NULL ) || ( p_instances[i]->GetScene()->m_numHierarchyObjects > 0 ))\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tif(( flags & vRENDER_OPAQUE ) || (( flags & vRENDER_SEMITRANSPARENT ) && ( flags & vRENDER_INSTANCE_PRE_WORLD_SEMITRANSPARENT )))\r\n\t\t\t\tp_instances[i]->Render( flags );\r\n\t\t}\r\n\t\tshutdown_weighted_mesh_vertex_shader();\r\n\t\t\r\n\t\t// Then the instances with no bone transforms. These will require fixed function lighting.\r\n\t\tD3DDevice_SetRenderState( D3DRS_LIGHTING,\t\t\t\tTRUE );\r\n\t\tD3DDevice_SetRenderState( D3DRS_COLORVERTEX,\t\t\tTRUE );\r\n\t\tD3DDevice_LightEnable( 0, TRUE );\r\n\t\tD3DDevice_LightEnable( 1, TRUE );\r\n\r\n\t\tMth::Vector current_cam_pos( EngineGlobals.cam_position.x, EngineGlobals.cam_position.y, EngineGlobals.cam_position.z );\r\n\r\n\t\t// Get the (square of) the distance at which env mapping will be disabled, in inches.\r\n\t\tfloat env_map_disable_distance\t= Script::GetFloat( CRCD( 0x4e7dc608, \"EnvMapDisableDistance\")) * 12.0f;\r\n\t\tenv_map_disable_distance\t\t= env_map_disable_distance * env_map_disable_distance;\r\n\r\n\t\tfor( ; i < current_index; ++i )\r\n\t\t{\r\n\t\t\t// Calculate the distance from the current camera to the instance.\r\n\t\t\tfloat dist_squared = Mth::DistanceSqr( p_instances[i]->GetTransform()->GetPos(), current_cam_pos );\r\n\r\n\t\t\t// At forty feet, environment mapping is turned off.\r\n\t\t\tEngineGlobals.allow_envmapping = ( dist_squared > env_map_disable_distance ) ? false : true;\r\n\r\n\t\t\tif(( flags & vRENDER_OPAQUE ) || (( flags & vRENDER_SEMITRANSPARENT ) && ( flags & vRENDER_INSTANCE_POST_WORLD_SEMITRANSPARENT )))\r\n\t\t\t\tp_instances[i]->Render( flags );\r\n\t\t}\r\n\r\n\t\t// Restore environment mapping..\r\n\t\tEngineGlobals.allow_envmapping = true;\r\n\r\n\t\t// Shut down fixed function lighting.\r\n\t\tD3DDevice_SetRenderState( D3DRS_LIGHTING,\t\t\t\tFALSE );\r\n\t\tD3DDevice_SetRenderState( D3DRS_COLORVERTEX,\t\t\tFALSE );\r\n\t\tD3DDevice_LightEnable( 0, FALSE );\r\n\t\tD3DDevice_LightEnable( 1, FALSE );\r\n\t}\r\n\r\n\t// Restore world transform to identity.\r\n\tD3DDevice_SetTransform( D3DTS_WORLD, &EngineGlobals.world_matrix );\r\n\tset_frustum_bbox_transform( NULL );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCInstance::CInstance( sScene *pScene, Mth::Matrix &transform, int numBones, Mth::Matrix *pBoneTransforms )\r\n{\r\n\tSetTransform( transform );\r\n\tmp_bone_transforms\t= pBoneTransforms;\r\n\tm_num_bones\t\t\t= numBones;\r\n\tmp_scene\t\t\t= pScene;\r\n\tmp_model\t\t\t= NULL;\r\n\tm_active\t\t\t= true;\r\n\tm_flags\t\t\t\t= 0;\r\n\r\n\tmp_next_instance\t= pFirstInstance;\r\n\tpFirstInstance\t\t= this;\r\n\r\n\t// Check to see whether this instance is allowed to be lit or not (for non-skinned instances).\r\n\t// Currently, we assume that instances with a model containing valid normals requires lighting, except in the\r\n\t// situation where that model contains a mesh specifically flagged not to be lit.\r\n\tif(( pBoneTransforms == NULL ) || ( GetScene()->m_numHierarchyObjects > 0 ))\r\n\t{\r\n\t\tfor( int m = 0; m < pScene->m_num_mesh_entries; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = pScene->m_meshes[m];\r\n\t\t\tif(( p_mesh->m_vertex_shader[0] & D3DFVF_NORMAL ) == 0 )\r\n\t\t\t\treturn;\r\n\t\t\tif( p_mesh->m_flags & sMesh::MESH_FLAG_UNLIT )\r\n\t\t\t\treturn;\r\n\t\t}\r\n\t\tm_flags |= CInstance::INSTANCE_FLAG_LIGHTING_ALLOWED;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCInstance::~CInstance()\r\n{\r\n\tif( m_flags & INSTANCE_FLAG_DELETE_ATTACHED_SCENE )\r\n\t{\r\n\t\tif( mp_scene )\r\n\t\t{\r\n\t\t\tdelete mp_scene;\r\n\t\t\tmp_scene = NULL;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Remove this instance from the list.\r\n\tCInstance **pp_instance = &pFirstInstance;\r\n\twhile( *pp_instance )\r\n\t{\r\n\t\tif( *pp_instance == this )\r\n\t\t{\r\n\t\t\t*pp_instance = mp_next_instance;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpp_instance = &(( *pp_instance )->mp_next_instance );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CInstance::Render( uint32 flags )\r\n{\r\n\tconst int\t\t\tMAX_SUPPORTED_BONES\t= 58;\r\n\tstatic float\t\troot_matrix[12];\r\n\r\n\tstatic D3DLIGHT8 l0 =\r\n\t{\r\n\t\tD3DLIGHT_DIRECTIONAL,\r\n\t\t{ 0.0f, 0.0f, 0.0f, 1.0f },\t// Diffuse color\r\n\t\t{ 1.0f, 1.0f, 1.0f, 0.0f },\t// Specular color\r\n\t\t{ 0.0f, 0.0f, 0.0f, 0.0f },\t// Ambient color\r\n\t\t{ 0.0f, 0.0f, 0.0f },\t\t// Position\r\n\t\t{ 0.0f, 0.0f, 0.0f },\t\t// Direction\r\n\t\t0.0f, 0.0f,\t\t\t\t\t// Range, falloff\r\n\t\t0.0f, 0.0f, 0.0f,\t\t\t// Attenuation0, 1, 2\r\n\t\t0.0f, 0.0f\t\t\t\t\t// Theta, Phi\r\n\t};\r\n\tstatic D3DLIGHT8 l1 =\r\n\t{\r\n\t\tD3DLIGHT_DIRECTIONAL,\r\n\t\t{ 0.0f, 0.0f, 0.0f, 1.0f },\t// Diffuse color\r\n\t\t{ 0.0f, 0.0f, 0.0f, 0.0f },\t// Specular color\r\n\t\t{ 0.0f, 0.0f, 0.0f, 0.0f },\t// Ambient color\r\n\t\t{ 0.0f, 0.0f, 0.0f },\t\t// Position\r\n\t\t{ 0.0f, 0.0f, 0.0f },\t\t// Direction\r\n\t\t0.0f, 0.0f,\t\t\t\t\t// Range, falloff\r\n\t\t0.0f, 0.0f, 0.0f,\t\t\t// Attenuation0, 1, 2\r\n\t\t0.0f, 0.0f\t\t\t\t\t// Theta, Phi\r\n\t};\r\n\r\n\tif(( GetBoneTransforms() == NULL ) || ( GetScene()->m_numHierarchyObjects > 0 ))\r\n\t{\r\n\t\t// Is a non-skinned object.\r\n\t\tpLastBoneTransforms = NULL;\r\n\t\t\r\n\t\t// Do the lighting setup here.\r\n\t\tif((( m_flags & CInstance::INSTANCE_FLAG_LIGHTING_ALLOWED ) == 0 ) || ( GetScene()->m_flags & SCENE_FLAG_RENDERING_SHADOW ))\r\n\t\t{\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_LIGHTING, FALSE );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tNx::CModelLights *p_lights = GetModel() ? GetModel()->GetModelLights() : NULL;\r\n\t\t\tif( p_lights )\r\n\t\t\t{\r\n\t\t\t\t// Obtain position from the transform, for calculating Scene Lighting.\r\n\t\t\t\tp_lights->UpdateEngine( GetTransform()->GetPos(), true );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tNx::CLightManager::sUpdateEngine();\r\n\t\t\t}\r\n\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_LIGHTING, TRUE );\r\n\t\t\t\r\n\t\t\tl0.Diffuse.r\t= EngineGlobals.directional_light_color[4];\r\n\t\t\tl0.Diffuse.g\t= EngineGlobals.directional_light_color[5];\r\n\t\t\tl0.Diffuse.b\t= EngineGlobals.directional_light_color[6];\r\n\t\t\tl0.Direction.x\t= EngineGlobals.directional_light_color[0];\r\n\t\t\tl0.Direction.y\t= EngineGlobals.directional_light_color[1];\r\n\t\t\tl0.Direction.z\t= EngineGlobals.directional_light_color[2];\r\n\t\t\tD3DDevice_SetLight( 0, &l0 );\r\n\r\n\t\t\tl1.Diffuse.r\t= EngineGlobals.directional_light_color[12];\r\n\t\t\tl1.Diffuse.g\t= EngineGlobals.directional_light_color[13];\r\n\t\t\tl1.Diffuse.b\t= EngineGlobals.directional_light_color[14];\r\n\t\t\tl1.Direction.x\t= EngineGlobals.directional_light_color[8];\r\n\t\t\tl1.Direction.y\t= EngineGlobals.directional_light_color[9];\r\n\t\t\tl1.Direction.z\t= EngineGlobals.directional_light_color[10];\r\n\t\t\tD3DDevice_SetLight( 1, &l1 );\r\n\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_AMBIENT, D3DCOLOR_RGBA(\tFtoi_ASM( EngineGlobals.ambient_light_color[0] * 255.0f ),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tFtoi_ASM( EngineGlobals.ambient_light_color[1] * 255.0f ),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tFtoi_ASM( EngineGlobals.ambient_light_color[2] * 255.0f ),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0xFF ));\r\n\t\t}\r\n\r\n\t\t// If the object has a 'fake skeleton', like the cars with rotating wheels, then set up accordingly.\r\n\t\tif( GetScene()->m_numHierarchyObjects )\r\n\t\t{\r\n\t\t\tint num_bones = ( GetNumBones() < MAX_SUPPORTED_BONES ) ? GetNumBones() : MAX_SUPPORTED_BONES;\r\n\t\t\tfor( int lp = 0; lp < num_bones; ++lp )\r\n\t\t\t{\r\n\t\t\t\tMth::Matrix temp = *GetTransform();\r\n\t\t\t\ttemp = GetBoneTransforms()[lp] * temp;\r\n\t\t\t\tset_frustum_bbox_transform( &temp );\r\n\t\t\t\tD3DDevice_SetTransform( D3DTS_WORLD, (D3DXMATRIX*)&temp );\r\n\r\n\t\t\t\t// Scan through the meshes, setting only those with the current bone active.\r\n\t\t\t\tfor( int m = 0; m < GetScene()->m_num_mesh_entries; ++m )\r\n\t\t\t\t{\r\n\t\t\t\t\tNxXbox::sMesh *p_mesh = GetScene()->m_meshes[m];\r\n\t\t\t\t\tif( p_mesh->GetBoneIndex() == lp )\r\n\t\t\t\t\t\tp_mesh->SetActive( true );\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tp_mesh->SetActive( false );\r\n\t\t\t\t}\r\n\t\t\t\trender_scene( GetScene(), flags | vRENDER_NO_CULLING );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Has no skeleton.\r\n\t\t\tset_frustum_bbox_transform( GetTransform());\r\n\t\t\tD3DDevice_SetTransform( D3DTS_WORLD, (D3DXMATRIX*)GetTransform());\r\n\r\n\t\t\trender_scene( GetScene(), flags | vRENDER_NO_CULLING );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Has bone transforms, is therefore an animated object such as a skater, pedestrian etc.\r\n\t\tset_frustum_bbox_transform( GetTransform());\r\n\r\n\t\t// We only want to upload all the bone transforms if they have changed from the last call.\r\n\t\tbool upload_bone_transforms = false;\r\n\t\t\r\n\t\tif( pLastBoneTransforms != GetBoneTransforms())\r\n\t\t{\r\n\t\t\t// Okay, the bone transforms have changed from the last call.\r\n\t\t\tupload_bone_transforms = true;\r\n\t\t\t\r\n\t\t\t// Do the lighting setup here (if not rendering shadow, which requires no lighting).\r\n\t\t\tif(( GetScene()->m_flags & SCENE_FLAG_RENDERING_SHADOW ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tNx::CModelLights *p_lights = GetModel() ? GetModel()->GetModelLights() : NULL;\r\n\t\t\t\tif( p_lights )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_lights->UpdateEngine( GetTransform()->GetPos(), true );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tNx::CLightManager::sUpdateEngine();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tpLastBoneTransforms = GetBoneTransforms();\r\n\r\n\t\t\tint num_bones = ( GetNumBones() < MAX_SUPPORTED_BONES ) ? GetNumBones() : MAX_SUPPORTED_BONES;\r\n\t\t}\r\n\t\t\t\t\r\n\t\troot_matrix[0]\t= GetTransform()->GetRight()[X];\r\n\t\troot_matrix[1]\t= GetTransform()->GetUp()[X];\r\n\t\troot_matrix[2]\t= GetTransform()->GetAt()[X];\r\n\t\troot_matrix[3]\t= GetTransform()->GetPos()[X];\r\n\t\troot_matrix[4]\t= GetTransform()->GetRight()[Y];\r\n\t\troot_matrix[5]\t= GetTransform()->GetUp()[Y];\r\n\t\troot_matrix[6]\t= GetTransform()->GetAt()[Y];\r\n\t\troot_matrix[7]\t= GetTransform()->GetPos()[Y];\r\n\t\troot_matrix[8]\t= GetTransform()->GetRight()[Z];\r\n\t\troot_matrix[9]\t= GetTransform()->GetUp()[Z];\r\n\t\troot_matrix[10]\t= GetTransform()->GetAt()[Z];\r\n\t\troot_matrix[11]\t= GetTransform()->GetPos()[Z];\r\n\t\t\r\n\t\tsetup_weighted_mesh_vertex_shader( &root_matrix, &GetBoneTransforms()[0][Mth::RIGHT][X], upload_bone_transforms ? GetNumBones() : 0 );\r\n\r\n\t\tif( GetScene()->m_flags & SCENE_FLAG_RENDERING_SHADOW )\r\n\t\t{\r\n\t\t\t// Set the simple vertex shader that does no normal transform or lighting.\r\n\t\t\tset_vertex_shader( WeightedMeshVertexShader_SBWrite );\r\n\t\t\tEngineGlobals.vertex_shader_override = 1;\r\n\r\n\t\t\t// Set the simple pixel shader that just writes constant (1,1,1,1) out.\r\n\t\t\tset_pixel_shader( PixelShaderNULL );\r\n\t\t\tEngineGlobals.pixel_shader_override = 1;\r\n\r\n\t\t\t// No backface culling.\r\n\t\t\tset_render_state( RS_CULLMODE, D3DCULL_NONE );\r\n\r\n\t\t\t// Lock out material changes.\r\n\t\t\tEngineGlobals.material_override = 1;\r\n\r\n\t\t\trender_scene( GetScene(), flags | vRENDER_NO_CULLING );\r\n\r\n//\t\t\tRenderShadowVolume();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\trender_scene( GetScene(), flags | vRENDER_NO_CULLING );\r\n\r\n\t\t\t// Render the self-shadowing pass here, if so flagged.\r\n\t\t\tif( GetScene()->m_flags & SCENE_FLAG_SELF_SHADOWS )\r\n\t\t\t{\r\n\t\t\t\tstatic float texture_projection_matrix[16];\r\n\r\n\t\t\t\t// Calculate distance to the camera - the self shadowing fades out beyond a certain distance, (and also fades out\r\n\t\t\t\t// close up, to avoid the visible streaks). Also need to take into account the view angle since that directly affects\r\n\t\t\t\t// the relative screen space size of the object.\r\n\t\t\t\tconst float SHADOW_FADE_CLOSE_START\t\t\t= 150.0f;\r\n\t\t\t\tconst float SHADOW_FADE_CLOSE_COMPLETE\t\t= 120.0f;\r\n\t\t\t\tconst float SHADOW_FADE_FAR_START\t\t\t= 500.0f;\r\n\t\t\t\tconst float SHADOW_FADE_FAR_COMPLETE\t\t= 600.0f;\r\n\t\t\t\tconst float DEFAULT_SCREEN_ANGLE\t\t\t= 0.72654f;\t// tan( 72 / 2 )\r\n\r\n\t\t\t\tMth::Vector pos_to_cam\t= GetTransform()->GetPos() - Mth::Vector( NxXbox::EngineGlobals.cam_position.x, NxXbox::EngineGlobals.cam_position.y, NxXbox::EngineGlobals.cam_position.z );\r\n\t\t\t\tfloat\t\tdist\t\t= pos_to_cam.Length() * ( tanf( Mth::DegToRad( EngineGlobals.screen_angle * 0.5f )) / DEFAULT_SCREEN_ANGLE );\r\n\r\n\t\t\t\tif(( dist > SHADOW_FADE_CLOSE_COMPLETE ) && ( dist < SHADOW_FADE_FAR_COMPLETE ))\r\n\t\t\t\t{\r\n\t\t\t\t\t// Find which set of details relates to this instance.\r\n\t\t\t\t\tpTextureProjectionDetailsTable->IterateStart();\r\n\t\t\t\t\tsTextureProjectionDetails *p_details = pTextureProjectionDetailsTable->IterateNext();\r\n\t\t\t\t\twhile( p_details )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( p_details->p_model == mp_model )\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tp_details = pTextureProjectionDetailsTable->IterateNext();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif( p_details )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Need to incorporate the world matrix into the texture projection matrix, since we will be using the bone-transformed\r\n\t\t\t\t\t\t// vertex positions, which are in object space.\r\n\t\t\t\t\t\tXGMATRIX world_matrix;\r\n\t\t\t\t\t\tworld_matrix.m[0][0] = GetTransform()->GetRight()[X];\r\n\t\t\t\t\t\tworld_matrix.m[0][1] = GetTransform()->GetRight()[Y];\r\n\t\t\t\t\t\tworld_matrix.m[0][2] = GetTransform()->GetRight()[Z];\r\n\t\t\t\t\t\tworld_matrix.m[0][3] = 0.0f;\r\n\t\t\t\t\t\tworld_matrix.m[1][0] = GetTransform()->GetUp()[X];\r\n\t\t\t\t\t\tworld_matrix.m[1][1] = GetTransform()->GetUp()[Y];\r\n\t\t\t\t\t\tworld_matrix.m[1][2] = GetTransform()->GetUp()[Z];\r\n\t\t\t\t\t\tworld_matrix.m[1][3] = 0.0f;\r\n\t\t\t\t\t\tworld_matrix.m[2][0] = GetTransform()->GetAt()[X];\r\n\t\t\t\t\t\tworld_matrix.m[2][1] = GetTransform()->GetAt()[Y];\r\n\t\t\t\t\t\tworld_matrix.m[2][2] = GetTransform()->GetAt()[Z];\r\n\t\t\t\t\t\tworld_matrix.m[2][3] = 0.0f;\r\n\t\t\t\t\t\tworld_matrix.m[3][0] = GetTransform()->GetPos()[X];\r\n\t\t\t\t\t\tworld_matrix.m[3][1] = GetTransform()->GetPos()[Y];\r\n\t\t\t\t\t\tworld_matrix.m[3][2] = GetTransform()->GetPos()[Z];\r\n\t\t\t\t\t\tworld_matrix.m[3][3] = 1.0f;\r\n\t\t\t\t\t\tcalculate_tex_proj_matrix( &p_details->view_matrix, &p_details->projection_matrix, &p_details->texture_projection_matrix, &world_matrix );\r\n\r\n\t\t\t\t\t\t// Upload that matrix to the GPU also.\r\n\t\t\t\t\t\ttexture_projection_matrix[0]\t= p_details->texture_projection_matrix.m[0][0];\r\n\t\t\t\t\t\ttexture_projection_matrix[1]\t= p_details->texture_projection_matrix.m[1][0];\r\n\t\t\t\t\t\ttexture_projection_matrix[2]\t= p_details->texture_projection_matrix.m[2][0];\r\n\t\t\t\t\t\ttexture_projection_matrix[3]\t= p_details->texture_projection_matrix.m[3][0];\r\n\t\t\t\t\t\ttexture_projection_matrix[4]\t= p_details->texture_projection_matrix.m[0][1];\r\n\t\t\t\t\t\ttexture_projection_matrix[5]\t= p_details->texture_projection_matrix.m[1][1];\r\n\t\t\t\t\t\ttexture_projection_matrix[6]\t= p_details->texture_projection_matrix.m[2][1];\r\n\t\t\t\t\t\ttexture_projection_matrix[7]\t= p_details->texture_projection_matrix.m[3][1];\r\n\t\t\t\t\t\ttexture_projection_matrix[8]\t= p_details->texture_projection_matrix.m[0][2];\r\n\t\t\t\t\t\ttexture_projection_matrix[9]\t= p_details->texture_projection_matrix.m[1][2];\r\n\t\t\t\t\t\ttexture_projection_matrix[10]\t= p_details->texture_projection_matrix.m[2][2];\r\n\t\t\t\t\t\ttexture_projection_matrix[11]\t= p_details->texture_projection_matrix.m[3][2];\r\n\t\t\t\t\t\ttexture_projection_matrix[12]\t= p_details->texture_projection_matrix.m[0][3];\r\n\t\t\t\t\t\ttexture_projection_matrix[13]\t= p_details->texture_projection_matrix.m[1][3];\r\n\t\t\t\t\t\ttexture_projection_matrix[14]\t= p_details->texture_projection_matrix.m[2][3];\r\n\t\t\t\t\t\ttexture_projection_matrix[15]\t= p_details->texture_projection_matrix.m[3][3];\r\n\r\n\t\t\t\t\t\t// We can upload this matrix to the space taken up by the directional lighting details, since this render pass requires no lighting.\r\n\t\t\t\t\t\tD3DDevice_SetVertexShaderConstantFast( VSCONST_REG_DIR_LIGHT_OFFSET, (void*)texture_projection_matrix, 4 );\r\n\r\n\t\t\t\t\t\t// Scan through each mesh in this scene, setting the vertex shader to be the equivalent vertex shader\r\n\t\t\t\t\t\t// for shadow buffering.\r\n\t\t\t\t\t\tsScene *p_scene = GetScene();\r\n\t\t\t\t\t\tfor( int m = 0; m < p_scene->m_num_mesh_entries; ++m )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tsMesh *p_mesh = p_scene->m_meshes[m];\r\n\t\t\t\t\t\t\tif(( p_mesh->m_vertex_shader[0] == WeightedMeshVS_VXC_1Weight ) ||\r\n\t\t\t\t\t\t\t   ( p_mesh->m_vertex_shader[0] == WeightedMeshVS_VXC_Specular_1Weight ) ||\r\n\t\t\t\t\t\t\t   ( p_mesh->m_vertex_shader[0] == WeightedMeshVS_VXC_1Weight_UVTransform ))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tp_mesh->PushVertexShader( WeightedMeshVS_VXC_1Weight_SBPassThru );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse if(( p_mesh->m_vertex_shader[0] == WeightedMeshVS_VXC_2Weight ) ||\r\n\t\t\t\t\t\t\t\t\t( p_mesh->m_vertex_shader[0] == WeightedMeshVS_VXC_Specular_2Weight ) ||\r\n\t\t\t\t\t\t\t\t    ( p_mesh->m_vertex_shader[0] == WeightedMeshVS_VXC_2Weight_UVTransform ))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tp_mesh->PushVertexShader( WeightedMeshVS_VXC_2Weight_SBPassThru );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tp_mesh->PushVertexShader( WeightedMeshVS_VXC_3Weight_SBPassThru );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tfloat max = 0.25f;\r\n\t\t\t\t\t\tif( dist < SHADOW_FADE_CLOSE_START )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmax = (( dist - SHADOW_FADE_CLOSE_COMPLETE ) / ( SHADOW_FADE_CLOSE_START - SHADOW_FADE_CLOSE_COMPLETE )) * max;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse if( dist > SHADOW_FADE_FAR_START )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmax = (( SHADOW_FADE_FAR_COMPLETE - dist ) / ( SHADOW_FADE_FAR_COMPLETE - SHADOW_FADE_FAR_START )) * max;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Set ambient color multipliers in pixel shader C0 and C1.\r\n\t\t\t\t\t\tNxXbox::EngineGlobals.pixel_shader_constants[0]\t\t= 1.0f - max;\t\t// Always present\r\n\t\t\t\t\t\tNxXbox::EngineGlobals.pixel_shader_constants[1]\t\t= 1.0f - max;\r\n\t\t\t\t\t\tNxXbox::EngineGlobals.pixel_shader_constants[2]\t\t= 1.0f - max;\r\n\t\t\t\t\t\tNxXbox::EngineGlobals.pixel_shader_constants[3]\t\t= 1.0f;\r\n\t\t\t\t\t\tNxXbox::EngineGlobals.pixel_shader_constants[4]\t\t= max;\t\t// The part the shadow affects.\r\n\t\t\t\t\t\tNxXbox::EngineGlobals.pixel_shader_constants[5]\t\t= max;\r\n\t\t\t\t\t\tNxXbox::EngineGlobals.pixel_shader_constants[6]\t\t= max;\r\n\t\t\t\t\t\tNxXbox::EngineGlobals.pixel_shader_constants[7]\t\t= 1.0f;\r\n\t\t\t\t\t\tNxXbox::EngineGlobals.upload_pixel_shader_constants\t= true;\r\n\r\n\t\t\t\t\t\t// Set the pixel shader that will do the shadow attenuation.\t\t\t\r\n\t\t\t\t\t\textern DWORD PixelShader_ShadowBuffer;\r\n\t\t\t\t\t\tset_pixel_shader( PixelShader_ShadowBuffer );\r\n\t\t\t\t\t\tEngineGlobals.pixel_shader_override = 1;\r\n\r\n\t\t\t\t\t\t// Set the material properties used for shadow modulation.\r\n\t\t\t\t\t\tset_blend_mode( vBLEND_MODE_MODULATE_COLOR );\r\n\t\t\t\t\t\tset_texture( 0, NULL );\r\n\t\t\t\t\t\tset_texture( 1, NULL );\r\n\t\t\t\t\t\tset_texture( 2, NULL );\r\n\t\t\t\t\t\tEngineGlobals.material_override = 1;\r\n\r\n\t\t\t\t\t\t// Set texture stage 3 to use the shadow buffer.\r\n\t\t\t\t\t\tEngineGlobals.texture_stage_override |= ( 1 << 3 );\r\n\t\t\t\t\t\tset_texture( 3, NULL );\r\n\t\t\t\t\t\tset_texture( 3, p_details->p_texture->pD3DTexture );\r\n\t\t\t\t\t\tset_render_state( RS_UVADDRESSMODE0 + 3, 0x00020002UL );\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( 3, D3DTSS_BORDERCOLOR, 0x00000000UL );\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( 3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( 3, D3DTSS_MINFILTER, D3DTEXF_LINEAR );\r\n\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( 3, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( 3, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | 3 );\r\n\r\n\t\t\t\t\t\t// Set shadowbuffer state.\r\n\t\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_SHADOWFUNC, D3DCMP_GREATER );\r\n\r\n\t\t\t\t\t\t// Render the shadow pass with fogging disabled.\r\n\t\t\t\t\t\tif( EngineGlobals.fog_enabled )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_FOGENABLE, FALSE );\r\n\t\t\t\t\t\t\trender_scene( GetScene(), flags | vRENDER_NO_CULLING );\r\n\t\t\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_FOGENABLE, TRUE );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\trender_scene( GetScene(), flags | vRENDER_NO_CULLING );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Restore shadowbuffer state.\r\n\t\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_SHADOWFUNC, D3DCMP_NEVER );\r\n\r\n\t\t\t\t\t\t// Scan through each mesh in this scene, restoring the vertex shader to the original.\r\n\t\t\t\t\t\tfor( int m = 0; m < p_scene->m_num_mesh_entries; ++m )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tsMesh *p_mesh = p_scene->m_meshes[m];\r\n\t\t\t\t\t\t\tp_mesh->PopVertexShader();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Restore state.\r\n\t\tEngineGlobals.vertex_shader_override\t= 0;\r\n\t\tEngineGlobals.pixel_shader_override\t\t= 0;\r\n\t\tEngineGlobals.material_override\t\t\t= 0;\r\n\t\tEngineGlobals.texture_stage_override\t&= ~( 1 << 3 );\r\n\t\tset_texture( 3, NULL );\r\n\r\n//\t\tshutdown_weighted_mesh_vertex_shader();\r\n\t}\r\n}\r\n\r\n\r\n\r\n// Test code...\r\nvoid CInstance::RenderShadowVolume( void )\r\n{\r\n\tif( GetBoneTransforms())\r\n\t{\r\n\t\tXGMATRIX root_matrix = *((XGMATRIX*)GetTransform());\r\n\r\n\t\tsScene*\tp_scene = GetScene();\r\n\r\n\t\t// Process each mesh in turn.\r\n\t\tfor( int m = 0; m < p_scene->m_num_mesh_entries; ++m )\r\n\t\t{\r\n\t\t\tsMesh* p_mesh\t= p_scene->m_meshes[m];\r\n\r\n\t\t\t// Lock the vertex buffer so we can read the data.\r\n\t\t\tBYTE* p_byte;\r\n\t\t\tp_mesh->mp_vertex_buffer[0]->Lock( 0, 0, &p_byte, D3DLOCK_READONLY );\r\n\r\n\t\t\t// Grab a buffer for the transformed points.\r\n\t\t\tXGVECTOR4*\tp_t_buffer\t= new XGVECTOR4[p_mesh->m_num_vertices];\r\n\r\n\t\t\tfor( int v = 0; v < p_mesh->m_num_vertices; ++v )\r\n\t\t\t{\r\n\t\t\t\t// Get untransformed point.\r\n\t\t\t\tXGVECTOR3*\tp_source_vertex\t= (XGVECTOR3*)( p_byte + ( v * p_mesh->m_vertex_stride ));\r\n\r\n\t\t\t\t// Get and unpack weights.\r\n\t\t\t\tuint32\t\tpacked_weights\t= *((uint32*)( p_byte + ( v * p_mesh->m_vertex_stride ) + 12 ));\r\n\t\t\t\tfloat\t\tw0\t\t\t\t= (( packed_weights >> 0 ) & 0x7ff ) * ( 1.0f / 1023.0f );\r\n\t\t\t\tfloat\t\tw1\t\t\t\t= (( packed_weights >> 11 ) & 0x7ff ) * ( 1.0f / 1023.0f );\r\n\t\t\t\tfloat\t\tw2\t\t\t\t= (( packed_weights >> 22 ) & 0x3ff ) * ( 1.0f / 511.0f );\r\n\r\n\t\t\t\t// Get and unpack matrix indices.\r\n\t\t\t\tuint32\t\tpacked_indices\t= *((uint32*)( p_byte + ( v * p_mesh->m_vertex_stride ) + 16 ));\r\n\t\t\t\tuint32\t\ti0\t\t\t\t= ( packed_indices >> 0 ) & 0xff;\r\n\t\t\t\tuint32\t\ti1\t\t\t\t= ( packed_indices >> 8 ) & 0xff;\r\n\t\t\t\tuint32\t\ti2\t\t\t\t= ( packed_indices >> 16 ) & 0xff;\r\n\r\n\t\t\t\t// Get bone matrix pointers.\r\n\t\t\t\tXGMATRIX*\tp_bone_mat0\t\t= (XGMATRIX*)( GetBoneTransforms() + i0 );\r\n\t\t\t\tXGMATRIX*\tp_bone_mat1\t\t= (XGMATRIX*)( GetBoneTransforms() + i1 );\r\n\t\t\t\tXGMATRIX*\tp_bone_mat2\t\t= (XGMATRIX*)( GetBoneTransforms() + i2 );\r\n\r\n\t\t\t\tXGVECTOR4\ttp0;\r\n\t\t\t\tXGVECTOR4\ttp1;\r\n\t\t\t\tXGVECTOR4\ttp2;\r\n\r\n\t\t\t\t// Transform point by bone matrix 0, 1 and 2 and scale with weight 0, 1, 2.\r\n\t\t\t\tXGVec3Transform( &tp0, p_source_vertex, p_bone_mat0 );\r\n\t\t\t\tXGVec3Scale((XGVECTOR3*)&tp0, (XGVECTOR3*)&tp0, w0 );\r\n\r\n\t\t\t\tXGVec3Transform( &tp1, p_source_vertex, p_bone_mat1 );\r\n\t\t\t\tXGVec3Scale((XGVECTOR3*)&tp1, (XGVECTOR3*)&tp1, w1 );\r\n\r\n\t\t\t\tXGVec3Transform( &tp2, p_source_vertex, p_bone_mat2 );\r\n\t\t\t\tXGVec3Scale((XGVECTOR3*)&tp2, (XGVECTOR3*)&tp2, w2 );\r\n\r\n\t\t\t\t// Obtain cumulative result.\r\n\t\t\t\ttp0 = tp0 + tp1 + tp2;\r\n\r\n\t\t\t\t// Tranform point by object transform.\r\n\t\t\t\tXGVec3Transform( p_t_buffer + v, (XGVECTOR3*)&tp0, &root_matrix );\r\n\t\t\t}\r\n\t\t\tdelete [] p_t_buffer;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/instance.h",
    "content": "#ifndef __INSTANCE_H\r\n#define __INSTANCE_H\r\n\r\n\r\n#include <core/defines.h>\r\n#include <gfx/NxModel.h>\r\n#include \"scene.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\nvoid\trender_instance( CInstance *p_instance, uint32 flags );\r\nvoid\trender_instances( uint32 flags );\r\n\r\nclass CInstance\r\n{\r\npublic:\r\n\r\n\tenum EInstanceFlag\r\n\t{\r\n\t\tINSTANCE_FLAG_DELETE_ATTACHED_SCENE\t= 0x01,\r\n\t\tINSTANCE_FLAG_LIGHTING_ALLOWED\t\t= 0x02\r\n\t};\r\n\t\r\n\tvoid\t\t\tSetTransform( Mth::Matrix &transform )\t{ m_transform = transform; }\r\n\tMth::Matrix*\tGetTransform(void)\t\t\t\t\t\t{ return &m_transform; }\r\n\tint\t\t\t\tGetNumBones( void )\t\t\t\t\t\t{ return m_num_bones; }\r\n\tMth::Matrix*\tGetBoneTransforms( void )\t\t\t\t{ return mp_bone_transforms; }\r\n\tvoid\t\t\tSetBoneTransforms( Mth::Matrix* p_t )\t{ mp_bone_transforms = p_t; }\r\n\tsScene*\t\t\tGetScene( void )\t\t\t\t\t\t{ return mp_scene; }\r\n\tvoid\t\t\tSetActive( bool active )\t\t\t\t{ m_active = active; }\r\n\tbool\t\t\tGetActive( void )\t\t\t\t\t\t{ return m_active; }\r\n\tvoid\t\t\tSetFlag( EInstanceFlag flag )\t\t\t{ m_flags |= flag; }\r\n\tvoid\t\t\tClearFlag( EInstanceFlag flag )\t\t\t{ m_flags &= ~flag; }\r\n\tvoid\t\t\tSetModel( Nx::CModel *p_model )\t\t\t{ mp_model = p_model; }\r\n\tNx::CModel*\t\tGetModel( void )\t\t\t\t\t\t{ return mp_model; }\r\n\tCInstance*\t\tGetNextInstance( void )\t\t\t\t{ return mp_next_instance; }\r\n\r\n\t\t\t\t\tCInstance( sScene *pScene, Mth::Matrix &transform, int numBones, Mth::Matrix *pBoneTransforms );\r\n\t\t\t\t\t~CInstance();\r\n\r\n\tvoid\t\t\tRender( uint32 flags );\r\n\tvoid\t\t\tRenderShadowVolume( void );\r\n\r\nprivate:\r\n\tuint32\t\t\tm_flags;\r\n\tMth::Matrix\t\tm_transform;\r\n\tMth::Matrix*\tmp_bone_transforms;\r\n\tint\t\t\t\tm_num_bones;\r\n\tbool\t\t\tm_active;\r\n\tNx::CModel*\t\tmp_model;\t\t// Required in order to get pointer to CXboxLights structure at render time.\r\n\tsScene*\t\t\tmp_scene;\r\n\tCInstance*\t\tmp_next_instance;\r\n};\r\n\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n\r\n#endif // __INSTANCE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/material.cpp",
    "content": "#include <xtl.h>\r\n#include <string.h>\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <sys/file/filesys.h>\r\n#include <gfx/gfxman.h>\r\n#include \"gfx/xbox/p_nxtexture.h\"\r\n#include \"anim_vertdefs.h\"\r\n#include \"nx_init.h\"\r\n#include \"material.h\"\r\n#include \"scene.h\"\r\n#include \"render.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n\r\nuint32\t\t\t\t\t\tNumMaterials;\r\n\r\nstatic const float pi_over_180 = (float)Mth::PI / 180.0f;\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsUVWibbleParams::sUVWibbleParams( void )\r\n{\r\n\t// Zero out the members.\r\n\tZeroMemory( this, sizeof( sUVWibbleParams ));\r\n\r\n\t// Set the matrix correctly.\r\n\tm_UVMatrix[0] = 1.0f;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsUVWibbleParams::~sUVWibbleParams( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsMaterial::sMaterial( void )\r\n{\r\n\tm_num_wibble_vc_anims\t\t= 0;\r\n\tmp_wibble_vc_params\t\t\t= NULL;\r\n\tmp_wibble_vc_colors\t\t\t= NULL;\r\n\tmp_wibble_texture_params\t= NULL;\r\n\tm_uv_wibble\t\t\t\t\t= false;\r\n\tm_texture_wibble\t\t\t= false;\r\n\tm_grass_layers\t\t\t\t= 0;\r\n\tm_zbias\t\t\t\t\t\t= 0;\r\n\tfor( int p = 0; p < MAX_PASSES; ++p )\r\n\t{\r\n\t\tm_flags[p]\t\t\t\t= 0;\r\n\t\tmp_UVWibbleParams[p]\t= NULL;\r\n\r\n\t\tm_envmap_tiling[p][0]\t= 3.0f;\r\n\t\tm_envmap_tiling[p][1]\t= 3.0f;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsMaterial::~sMaterial( void )\r\n{\r\n\tif( mp_wibble_vc_params\t)\r\n\t{\r\n\t\tfor( uint32 i = 0; i < m_num_wibble_vc_anims; ++i )\r\n\t\t{\r\n\t\t\tdelete [] mp_wibble_vc_params[i].mp_keyframes;\r\n\t\t}\r\n\t\tdelete [] mp_wibble_vc_params;\r\n\t}\r\n\tif( mp_wibble_vc_colors\t)\r\n\t{\r\n\t\tdelete [] mp_wibble_vc_colors;\r\n\t}\r\n\r\n\tfor( int p = 0; p < MAX_PASSES; ++p )\r\n\t{\r\n\t\tif( mp_UVWibbleParams[p] )\r\n\t\t\tdelete mp_UVWibbleParams[p];\r\n\t}\r\n\r\n\tif( mp_wibble_texture_params )\r\n\t{\r\n\t\tfor( uint32 p = 0; p < MAX_PASSES; ++p )\r\n\t\t{\r\n\t\t\tdelete [] mp_wibble_texture_params->mp_keyframes[p];\r\n\t\t}\r\n\t\tdelete mp_wibble_texture_params;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMaterial::figure_wibble_uv( void )\r\n{\r\n\tif( m_uv_wibble )\r\n\t{\r\n\t\t// Get the time.\r\n\t\tfloat t = (float)Tmr::GetTime() * 0.001f;\r\n\r\n\t\tfor( uint32 p = 0; p < m_passes; ++p )\r\n\t\t{\r\n\t\t\t// Figure out UV offsets for wibbling if required.\r\n\t\t\tif( m_flags[p] & MATFLAG_UV_WIBBLE )\r\n\t\t\t{\r\n\t\t\t\tif( !( m_flags[p] & MATFLAG_EXPLICIT_UV_WIBBLE ))\r\n\t\t\t\t{\r\n\t\t\t\t\tfloat uoff, voff;\r\n\t\t\t\r\n\t\t\t\t\tuoff\t= ( t * mp_UVWibbleParams[p]->m_UVel ) + ( mp_UVWibbleParams[p]->m_UAmplitude * sinf( mp_UVWibbleParams[p]->m_UFrequency * t + mp_UVWibbleParams[p]->m_UPhase ));\r\n\t\t\t\t\tvoff\t= ( t * mp_UVWibbleParams[p]->m_VVel ) + ( mp_UVWibbleParams[p]->m_VAmplitude * sinf( mp_UVWibbleParams[p]->m_VFrequency * t + mp_UVWibbleParams[p]->m_VPhase ));\r\n\r\n\t\t\t\t\t// Reduce offset mod 16 and put it in the range -8 to +8.\r\n\t\t\t\t\tuoff\t+= 8.0f;\r\n\t\t\t\t\tuoff\t-= (float)(( Ftoi_ASM( uoff ) >> 4 ) << 4 );\r\n\t\t\t\t\tvoff\t+= 8.0f;\r\n\t\t\t\t\tvoff\t-= (float)(( Ftoi_ASM( voff ) >> 4 ) << 4 );\r\n\r\n\t\t\t\t\tmp_UVWibbleParams[p]->m_UVMatrix[2]\t= ( uoff < 0.0f ) ? ( uoff + 8.0f ) : ( uoff - 8.0f );\r\n\t\t\t\t\tmp_UVWibbleParams[p]->m_UVMatrix[3]\t= ( voff < 0.0f ) ? ( voff + 8.0f ) : ( voff - 8.0f );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMaterial::figure_wibble_vc( void )\r\n{\r\n\t// The vertex color wibble flag is placed in pass 0.\r\n\tif( m_flags[0] & MATFLAG_VC_WIBBLE )\r\n\t{\r\n\t\tfor( uint32 i = 0; i < m_num_wibble_vc_anims; ++i )\r\n\t\t{\r\n\t\t\tstruct sVCWibbleParams\t*p_sequence\t\t= mp_wibble_vc_params + i;\r\n\t\t\t\r\n\t\t\t// Get phase-shift.\r\n\t\t\tint\t\t\t\t\t\tphase_shift\t\t= p_sequence->m_phase;\r\n\r\n\t\t\t// Time parameters.\r\n\t\t\tint\t\t\t\t\t\tnum_keys\t\t= p_sequence->m_num_keyframes;\r\n\t\t\tint\t\t\t\t\t\tstart_time\t\t= p_sequence->mp_keyframes[0].m_time;\r\n\t\t\tint\t\t\t\t\t\tend_time\t\t= p_sequence->mp_keyframes[num_keys - 1].m_time;\r\n\t\t\tint\t\t\t\t\t\tperiod\t\t\t= end_time - start_time;\r\n\t\t\tint\t\t\t\t\t\ttime\t\t\t= start_time + ( NxXbox::EngineGlobals.render_start_time + phase_shift ) % period;\r\n\r\n\t\t\t// Locate the keyframe.\r\n\t\t\tint key;\r\n\t\t\tfor( key = num_keys - 1; key >= 0; --key )\r\n\t\t\t{\r\n\t\t\t\tif( time >= p_sequence->mp_keyframes[key].m_time )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tDbg_Assert( key < ( num_keys - 1 ));\r\n\r\n\t\t\t// Parameter expressing how far we are between between this keyframe and the next.\r\n\t\t\tfloat\t\t\t\t\tt\t\t\t\t= (float)( time - p_sequence->mp_keyframes[key].m_time ) * ReciprocalEstimateNR_ASM((float)( p_sequence->mp_keyframes[key + 1].m_time - p_sequence->mp_keyframes[key].m_time ));\r\n\r\n\t\t\t// Interpolate the color.\r\n\t\t\tuint32 red = (uint32)Ftoi_ASM((( 1.0f - t ) * p_sequence->mp_keyframes[key].m_color.r ) + ( t * p_sequence->mp_keyframes[key + 1].m_color.r ));\r\n\t\t\tuint32 grn = (uint32)Ftoi_ASM((( 1.0f - t ) * p_sequence->mp_keyframes[key].m_color.g ) + ( t * p_sequence->mp_keyframes[key + 1].m_color.g ));\r\n\t\t\tuint32 blu = (uint32)Ftoi_ASM((( 1.0f - t ) * p_sequence->mp_keyframes[key].m_color.b ) + ( t * p_sequence->mp_keyframes[key + 1].m_color.b ));\r\n\t\t\tuint32 alp = (uint32)Ftoi_ASM((( 1.0f - t ) * p_sequence->mp_keyframes[key].m_color.a ) + ( t * p_sequence->mp_keyframes[key + 1].m_color.a ));\r\n\r\n\t\t\t// Switch red and blue, and store.\r\n\t\t\tmp_wibble_vc_colors[i] = ( alp << 24 ) | ( red << 16 ) | ( grn << 8 ) | blu;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMaterial::figure_wibble_texture( void )\r\n{\r\n\t// The vertex color wibble flag is placed in pass 0.\r\n\tif( m_texture_wibble )\r\n\t{\r\n\t\tint current_time = (int)Tmr::GetTime();\r\n\r\n\t\tstruct sTextureWibbleParams\t*p_sequence\t\t= mp_wibble_texture_params;\r\n\t\t\t\r\n\t\tfor( int pass = 0; pass < MAX_PASSES; ++pass )\r\n\t\t{\r\n\t\t\tif( m_flags[pass] & MATFLAG_PASS_TEXTURE_ANIMATES )\r\n\t\t\t{\r\n\t\t\t\t// Get phase-shift.\r\n\t\t\t\tint\t\t\t\t\t\tphase_shift\t= p_sequence->m_phase[pass];\r\n\r\n\t\t\t\t// Time parameters.\r\n\t\t\t\tint\t\t\t\t\t\tnum_keys\t= p_sequence->m_num_keyframes[pass];\r\n\t\t\t\tint\t\t\t\t\t\tstart_time\t= p_sequence->mp_keyframes[pass][0].m_time;\r\n\t\t\t\tint\t\t\t\t\t\tend_time\t= p_sequence->mp_keyframes[pass][num_keys - 1].m_time;\r\n\t\t\t\tint\t\t\t\t\t\tperiod\t\t= end_time - start_time;\r\n\t\t\t\tint\t\t\t\t\t\ttime\t\t= start_time + (( current_time + phase_shift ) % period );\r\n\r\n\t\t\t\t// Keep track of the iterations, if iterations on this animation are required.\r\n\t\t\t\tif( p_sequence->m_num_iterations[pass] > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tint iteration = ( current_time - start_time ) / period;\r\n\t\t\t\t\tif( iteration >= p_sequence->m_num_iterations[pass] )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Set the time such that the animation no longer continues.\r\n\t\t\t\t\t\ttime = start_time + ((( period * p_sequence->m_num_iterations[pass] ) + phase_shift ) % period );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Locate the keyframe.\r\n\t\t\t\tint key;\r\n\t\t\t\tfor( key = num_keys - 1; key >= 0; --key )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( time >= p_sequence->mp_keyframes[pass][key].m_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\t// Set the texture.\r\n//\t\t\t\tDbg_Assert( p_sequence->mp_keyframes[pass][key].mp_texture );\r\n\t\t\t\tmp_tex[pass] = p_sequence->mp_keyframes[pass][key].mp_texture;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\ninline DWORD F2DW( FLOAT f )\r\n{\r\n\treturn *( ( DWORD *) & f );\r\n}\r\n\r\n\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMaterial::Submit( void )\r\n{\r\n\t// Dummy 8 element uv 'matrix' for custom pipeline.\r\n\tstatic float custom_uv_mat[8] = {\t1.0f, 0.0f, 0.0f, 0.0f,\r\n\t\t\t\t\t\t\t\t\t\t0.0f, 1.0f, 0.0f, 0.0f };\r\n\r\n\t// Matrix for UV wibbling texture transform.\r\n\tstatic D3DMATRIX uv_mat = { 1.0f, 0.0f, 0.0f, 0.0f,\r\n\t\t\t\t\t\t\t\t0.0f, 1.0f, 0.0f, 0.0f,\r\n\t\t\t\t\t\t\t\t0.0f, 0.0f, 0.0f, 0.0f,\r\n\t\t\t\t\t\t\t\t0.0f, 0.0f, 0.0f, 0.0f };\r\n\r\n\t// Matrix for env mapping texture transform. Note that the [0][0] and [1][1] elements of the matrix are set up to scale, based on the\r\n\t// material pass properties.\r\n\tstatic D3DMATRIX env_mat = { 0.5f,  0.0f, 0.0f, 0.0f,\r\n\t\t\t\t\t\t\t\t 0.0f, -0.5f, 0.0f, 0.0f,\r\n\t\t\t\t\t\t\t\t 0.0f,  0.0f, 0.0f,\t0.0f,\r\n\t\t\t\t\t\t\t\t 0.5f,  0.5f, 0.0f, 0.0f };\r\n\t\r\n\t// Check for material change lockout.\r\n\tif( EngineGlobals.material_override )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Set the alpha blend mode.\r\n\tset_blend_mode( m_reg_alpha[0] );\r\n\t\r\n\t// Set the alpha cutoff value.\r\n\tset_render_state( RS_ALPHACUTOFF, (uint32)m_alpha_cutoff );\r\n\t\r\n\t// Set the backface cull mode.\r\n\tset_render_state( RS_CULLMODE, m_no_bfc ? D3DCULL_NONE : D3DCULL_CW );\r\n\r\n\t// Set the z-bias.\r\n\tset_render_state( RS_ZBIAS, m_zbias );\r\n\t\r\n\t// Figure uv, vc and texture wibble updates if required.\r\n\tfigure_wibble_uv();\r\n\tfigure_wibble_vc();\r\n\tfigure_wibble_texture();\r\n\t\r\n\t// Set specular properties of this material.\r\n\tif( m_flags[0] & MATFLAG_SPECULAR )\r\n\t{\r\n\t\tif( EngineGlobals.specular_enabled == 0 )\r\n\t\t{\r\n\t\t\tset_render_state( RS_SPECULARENABLE, 1 );\r\n\r\n\t\t\t// Set the specular material.\r\n\t\t\tD3DMATERIAL8 test_mat;\r\n\t\t\tZeroMemory( &test_mat, sizeof( D3DMATERIAL8 ));\r\n\t\t\ttest_mat.Specular.r\t= m_specular_color[0];\r\n\t\t\ttest_mat.Specular.g\t= m_specular_color[1];\r\n\t\t\ttest_mat.Specular.b\t= m_specular_color[2];\r\n\t\t\ttest_mat.Specular.a\t= 1.0f;\r\n\t\t\ttest_mat.Power\t\t= m_specular_color[3];\r\n\t\t\tD3DDevice_SetMaterial( &test_mat );\r\n\r\n\t\t\t// If using a custom vertex shader, also need to load the specular color and power to vert shader registers here.\r\n\t\t\tif( NxXbox::EngineGlobals.custom_pipeline_enabled )\r\n\t\t\t{\r\n\t\t\t\tD3DDevice_SetVertexShaderConstantFast( VSCONST_REG_SPECULAR_COLOR_OFFSET, (void*)&m_specular_color[0], 1 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( EngineGlobals.specular_enabled > 0 )\r\n\t\t{\r\n\t\t\tset_render_state( RS_SPECULARENABLE, 0 );\r\n\r\n\t\t\t// Set the specular material (basically just to set the power to zero).\r\n\t\t\tD3DMATERIAL8 test_mat;\r\n\t\t\tZeroMemory( &test_mat, sizeof( D3DMATERIAL8 ));\r\n\t\t\tD3DDevice_SetMaterial( &test_mat );\r\n\t\t}\r\n\t}\r\n\r\n\t// Set up the textures if present. This involves setting the texture and palette pointers and addressing mode.\r\n\t// Also, for multipass textures, it may require loading of fixed alpha values into specific constant registers.\r\n\tuint32 p;\r\n\tfor( p = 0; p < m_passes; ++p )\r\n\t{\r\n\t\tif( !( EngineGlobals.texture_stage_override & ( 1 << p )))\r\n\t\t{\r\n\t\t\t// Load pass color and fixed alpha values to the pixel shader, if required.\r\n\t\t\tif( !EngineGlobals.upload_pixel_shader_constants )\r\n\t\t\t{\r\n\t\t\t\t// Do the comparison as 32bit unsigned ints.\r\n\t\t\t\tuint32 *p_test0 = (uint32*)&m_color[p][0];\r\n\t\t\t\tuint32 *p_test1 = (uint32*)&EngineGlobals.pixel_shader_constants[p * 4];\r\n\r\n\t\t\t\tif(( p_test0[0] != p_test1[0] ) || ( p_test0[1] != p_test1[1] ) || ( p_test0[2] != p_test1[2] ) || ( p_test0[3] != p_test1[3] ))\r\n\t\t\t\t{\r\n\t\t\t\t\tEngineGlobals.upload_pixel_shader_constants = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif( mp_tex[p] )\r\n\t\t\t{\r\n\t\t\t\tset_texture( p, mp_tex[p]->pD3DTexture, mp_tex[p]->pD3DPalette );\r\n\r\n\t\t\t\t// Set UV adressing mode.\r\n\t\t\t\tset_render_state( RS_UVADDRESSMODE0 + p,\tm_uv_addressing[p] );\r\n\r\n\t\t\t\t// Set filtering mode.\r\n//\t\t\t\tset_render_state( RS_MINMAGFILTER0 + p,\t\tm_filtering_mode[p] );\r\n\t\t\t\t\t\t\r\n\t\t\t\t// Set MIP lod bias.\r\n\t\t\t\tset_render_state( RS_MIPLODBIASPASS0 + p,\t*((uint32*)( &m_k[p] )));\r\n\r\n\t\t\t\t// Deal with bump mapping setup.\r\n\t\t\t\tif( m_flags[p] & MATFLAG_BUMP_SIGNED_TEXTURE )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Channel of bump texture value (v,u) MUST be signed.\r\n\t\t\t\t\tif( EngineGlobals.color_sign[p] != ( D3DTSIGN_RSIGNED | D3DTSIGN_GSIGNED | D3DTSIGN_BSIGNED ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tEngineGlobals.color_sign[p] = ( D3DTSIGN_RSIGNED | D3DTSIGN_GSIGNED | D3DTSIGN_BSIGNED );\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_COLORSIGN, D3DTSIGN_RSIGNED | D3DTSIGN_GSIGNED | D3DTSIGN_BSIGNED );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif( EngineGlobals.color_sign[p] != ( D3DTSIGN_RUNSIGNED | D3DTSIGN_GUNSIGNED | D3DTSIGN_BUNSIGNED ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tEngineGlobals.color_sign[p] = ( D3DTSIGN_RUNSIGNED | D3DTSIGN_GUNSIGNED | D3DTSIGN_BUNSIGNED );\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_COLORSIGN, D3DTSIGN_RUNSIGNED | D3DTSIGN_GUNSIGNED | D3DTSIGN_BUNSIGNED );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( m_flags[p] & MATFLAG_BUMP_LOAD_MATRIX )\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_BUMPENVMAT00, F2DW( EngineGlobals.bump_env_matrix._11 ));\r\n\t\t\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_BUMPENVMAT01, F2DW( EngineGlobals.bump_env_matrix._13 ));\r\n\t\t\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_BUMPENVMAT10, F2DW( EngineGlobals.bump_env_matrix._31 ));\r\n\t\t\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_BUMPENVMAT11, F2DW( EngineGlobals.bump_env_matrix._33 ));\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif(( m_flags[p] & MATFLAG_ENVIRONMENT ) && ( EngineGlobals.allow_envmapping ))\r\n\t\t\t\t{\r\n\t\t\t\t\t// Handle environment mapping.\r\n\t\t\t\t\tenv_mat.m[0][0] = 0.5f * m_envmap_tiling[p][0];\r\n\t\t\t\t\tenv_mat.m[1][1] = 0.5f * m_envmap_tiling[p][1];\r\n\r\n\t\t\t\t\tD3DDevice_SetTransform((D3DTRANSFORMSTATETYPE)( D3DTS_TEXTURE0 + p ), &env_mat );\r\n\t\t\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );\r\n\t\t\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR | p );\r\n\t\t\t\t}\r\n\t\t\t\telse if( m_flags[p] & MATFLAG_UV_WIBBLE )\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );\r\n\t\t\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | p );\r\n\r\n\t\t\t\t\tif( NxXbox::EngineGlobals.custom_pipeline_enabled )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// If using a custom vertex shader, need to load the uv matrix here.\r\n\t\t\t\t\t\t// If using a custom vertex shader, need to load the custom uv matrix here.\r\n\t\t\t\t\t\tcustom_uv_mat[0] =  mp_UVWibbleParams[p]->m_UVMatrix[0];\r\n\t\t\t\t\t\tcustom_uv_mat[1] = -mp_UVWibbleParams[p]->m_UVMatrix[1];\r\n\t\t\t\t\t\tcustom_uv_mat[3] =  mp_UVWibbleParams[p]->m_UVMatrix[2];\r\n\r\n\t\t\t\t\t\tcustom_uv_mat[4] =  mp_UVWibbleParams[p]->m_UVMatrix[1];\r\n\t\t\t\t\t\tcustom_uv_mat[5] =\tmp_UVWibbleParams[p]->m_UVMatrix[0];\r\n\t\t\t\t\t\tcustom_uv_mat[7] =  mp_UVWibbleParams[p]->m_UVMatrix[3];\r\n\r\n\t\t\t\t\t\tD3DDevice_SetVertexShaderConstantFast( VSCONST_REG_UV_MAT_OFFSET + ( p * 2 ), (void*)&custom_uv_mat[0], 2 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Handle fixed function UV matrix.\r\n\t\t\t\t\t\tuv_mat._31 = mp_UVWibbleParams[p]->m_UVMatrix[2];\r\n\t\t\t\t\t\tuv_mat._32 = mp_UVWibbleParams[p]->m_UVMatrix[3];\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tD3DDevice_SetTransform((D3DTRANSFORMSTATETYPE)( D3DTS_TEXTURE0 + p ), &uv_mat );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif( NxXbox::EngineGlobals.custom_pipeline_enabled )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// If using a custom vertex shader, need to load the custom uv matrix here.\r\n\t\t\t\t\t\tcustom_uv_mat[0] = 1.0f; custom_uv_mat[1] = 0.0f; custom_uv_mat[3] = 0.0f;\r\n\t\t\t\t\t\tcustom_uv_mat[4] = 0.0f; custom_uv_mat[5] = 1.0f; custom_uv_mat[7] = 0.0f;\r\n\t\t\t\t\t\tD3DDevice_SetVertexShaderConstantFast( VSCONST_REG_UV_MAT_OFFSET + ( p * 2 ), (void*)&custom_uv_mat[0], 2 );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Regular case. Check states here since it is quicker for this common case than setting blindly.\r\n\t\t\t\t\tuint32 tex_coord_index, tex_trans_flags;\r\n\r\n\t\t\t\t\tD3DDevice_GetTextureStageState( p, D3DTSS_TEXTURETRANSFORMFLAGS, &tex_trans_flags );\r\n\t\t\t\t\tD3DDevice_GetTextureStageState( p, D3DTSS_TEXCOORDINDEX, &tex_coord_index );\r\n\r\n\t\t\t\t\tif( tex_trans_flags != D3DTTFF_DISABLE )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif( tex_coord_index != ( D3DTSS_TCI_PASSTHRU | p ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( p, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | p );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tset_texture( p, NULL, NULL );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif( EngineGlobals.upload_pixel_shader_constants )\r\n\t{\r\n\t\tCopyMemory( EngineGlobals.pixel_shader_constants, &m_color[0][0], sizeof( float ) * 4 * m_passes );\r\n\t}\r\n\r\n\t// Make sure to set the textures for unused stages to NULL, to reduce texture overhead.\r\n//\tfor( ; p < 4; ++p )\r\n//\t{\r\n//\t\tif( !( EngineGlobals.texture_stage_override & ( 1 << p )))\r\n//\t\t{\r\n//\t\t\tset_texture( p, NULL, NULL );\r\n//\t\t}\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 sMaterial::GetIgnoreVertexAlphaPasses( void )\r\n{\r\n\t// Return a bitfield with a bit set for any pass that is flagged to ignore vertex alpha.\r\n\tuint32 bf = 0;\r\n\r\n\tfor( uint32 p = 0; p < m_passes; ++p )\r\n\t{\r\n\t\tif( m_flags[p] & MATFLAG_PASS_IGNORE_VERTEX_ALPHA )\r\n\t\t{\r\n\t\t\tbf |= ( 1 << p );\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn bf;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsMaterial* GetMaterial( uint32 checksum, sScene *p_scene )\r\n{\r\n\tif( p_scene->pMaterialTable )\r\n\t{\r\n\t\tp_scene->pMaterialTable->IterateStart();\r\n\t\tsMaterial *p_mat = p_scene->pMaterialTable->IterateNext();\r\n\t\twhile( p_mat )\r\n\t\t{\r\n\t\t\tif( p_mat->m_checksum == checksum )\r\n\t\t\t{\r\n\t\t\t\treturn p_mat;\r\n\t\t\t}\r\n\t\t\tp_mat = p_scene->pMaterialTable->IterateNext();\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n\r\n#define MemoryRead( dst, size, num, src )\tCopyMemory(( dst ), ( src ), (( num ) * ( size )));\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t( src ) += (( num ) * ( size ))\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nLst::HashTable< sMaterial >\t*LoadMaterialsFromMemory( void **pp_mem, Lst::HashTable< Nx::CTexture > *p_texture_table )\r\n{\r\n\tuint8\t*p_data = (uint8*)( *pp_mem );\r\n\tuint32\tMMAG, MMIN, K, L, NumSeqs, seq, NumKeys;\r\n\t\r\n\t// Get number of materials.\r\n\tuint32 new_materials;\r\n\tMemoryRead( &new_materials, sizeof( uint32 ), 1, p_data );\r\n\t\r\n\tLst::HashTable< sMaterial >* pMaterialTable;\r\n\r\n\t// Create table, dynamically sizing it based on the number of new materials.\r\n\tuint32 optimal_table_size\t= new_materials * 2;\r\n\tuint32 test\t\t\t\t\t= 4;\r\n\tuint32 size\t\t\t\t\t= 2;\r\n\r\n\tfor( ;; test <<= 1, ++size )\r\n\t{\r\n\t\t// Check if this iteration of table size is sufficient, or if we have hit the maximum size.\r\n\t\tif(( optimal_table_size < test ) || ( size >= 12 ))\r\n\t\t{\r\n\t\t\tpMaterialTable = new Lst::HashTable< sMaterial >( size );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Loop over materials.\r\n\tfor( uint32 i = 0; i < new_materials; ++i )\r\n\t{\r\n\t\t// Create new material.\r\n\t\tsMaterial *pMat = new sMaterial;\r\n\r\n\t\t// Get material checksum.\r\n\t\tMemoryRead( &pMat->m_checksum, sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t// Get material name checksum.\r\n\t\tMemoryRead( &pMat->m_name_checksum, sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t// Get number of passes.\r\n\t\tMemoryRead( &pMat->m_passes, sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t// Get alpha cutoff value.\r\n\t\tuint32 AlphaCutoff;\r\n\t\tMemoryRead( &AlphaCutoff, sizeof( uint32 ), 1, p_data );\r\n\t\tDbg_Assert( AlphaCutoff <= 0xFF );\r\n\t\tpMat->m_alpha_cutoff = (uint8)AlphaCutoff;\r\n\r\n\t\t// Get sorted flag.\r\n\t\tMemoryRead( &pMat->m_sorted, sizeof( bool ), 1, p_data );\r\n\t\t\r\n\t\t// Get draw order.\r\n\t\tMemoryRead( &pMat->m_draw_order, sizeof( float ), 1, p_data );\r\n\t\t\r\n\t\t// Get single sided flag.\r\n\t\tbool single_sided;\r\n\t\tMemoryRead( &single_sided, sizeof( bool ), 1, p_data );\r\n\r\n\t\t// Get backface cull flag.\r\n\t\tMemoryRead( &pMat->m_no_bfc, sizeof( bool ), 1, p_data );\r\n\r\n\t\t// Get z-bias value.\r\n\t\tint zbias;\r\n\t\tMemoryRead( &zbias, sizeof( int ), 1, p_data );\r\n\t\tpMat->m_zbias = (uint8)(( zbias > 16 ) ? 16 : zbias );\r\n\r\n\t\t// Get grassify flag and (optionally) grassify data.\r\n\t\tbool grassify;\r\n\t\tMemoryRead( &grassify, sizeof( bool ), 1, p_data );\r\n\t\tif( grassify )\r\n\t\t{\r\n\t\t\tMemoryRead( &pMat->m_grass_height, sizeof( float ), 1, p_data );\r\n\t\t\tMemoryRead( &pMat->m_grass_layers, sizeof( int ), 1, p_data );\r\n\t\t}\r\n\r\n\t\t// Get specular power and (optionally) specular color.\r\n\t\tMemoryRead( &pMat->m_specular_color[3], sizeof( float ), 1, p_data );\r\n\t\tif( pMat->m_specular_color[3] > 0.0f )\r\n\t\t{\r\n\t\t\tMemoryRead( &pMat->m_specular_color[0], sizeof( float ) * 3, 1, p_data );\r\n\t\t}\r\n\r\n\t\t// Neutral under proven otherwise.\r\n\t\tbool neutral_material_color = true;\r\n\t\tfor( uint32 pass = 0; pass < pMat->m_passes; ++pass )\r\n\t\t{\r\n\t\t\t// Get texture checksum.\r\n\t\t\tuint32 TextureChecksum;\r\n\t\t\tMemoryRead( &TextureChecksum, sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t\t// Get material flags.\r\n\t\t\tMemoryRead( &pMat->m_flags[pass], sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t\t// Get pass color flag.\r\n\t\t\tbool has_color;\r\n\t\t\tMemoryRead( &has_color, sizeof( bool ), 1, p_data );\r\n\r\n\t\t\t// Get pass color.\r\n\t\t\tMemoryRead( &pMat->m_color[pass][0], sizeof( float ) * 3, 1, p_data );\r\n\r\n\t\t\t// Check for color being neutral.\r\n\t\t\tif( neutral_material_color )\r\n\t\t\t{\r\n\t\t\t\tif(( pMat->m_color[pass][0] != 0.5f ) || ( pMat->m_color[pass][1] != 0.5f ) || ( pMat->m_color[pass][2] != 0.5f ))\r\n\t\t\t\t{\r\n\t\t\t\t\tneutral_material_color = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Get ALPHA register value.\r\n\t\t\tuint64 reg_alpha;\r\n\t\t\tMemoryRead( &reg_alpha, sizeof( uint64 ), 1, p_data );\r\n\r\n\t\t\tuint32\tblend_mode\t\t= (uint32)( reg_alpha & 0xFFFFFFUL );\r\n\t\t\tuint32\tfixed_alpha\t\t= (uint32)( reg_alpha >> 32 );\r\n\t\t\tpMat->m_reg_alpha[pass]\t= blend_mode | ( fixed_alpha << 24 );\r\n\r\n\t\t\t// Also calculate the floating point version of the fixed alpha.\r\n\t\t\tpMat->m_color[pass][3]\t= fixed_alpha / 128.0f;\r\n\r\n\t\t\t// Backface cull test - if this is an alpha blended material, turn off backface culling, except\r\n\t\t\t// where the material has been explicitly flagged as single sided.\r\n\t\t\tif(( pass == 0 ) && !single_sided && (( pMat->m_reg_alpha[pass] & sMaterial::BLEND_MODE_MASK ) != 0x00 ))\r\n\t\t\t{\r\n\t\t\t\tpMat->m_no_bfc = true;\r\n\t\t\t}\r\n\r\n\t\t\t// Get UV addressing types.\r\n\t\t\tuint32 u_addressing, v_addressing;\r\n\t\t\tMemoryRead( &u_addressing, sizeof( uint32 ), 1, p_data );\r\n\t\t\tMemoryRead( &v_addressing, sizeof( uint32 ), 1, p_data );\r\n\t\t\tpMat->m_uv_addressing[pass] = (( v_addressing << 16 ) | u_addressing );\r\n\t\t\t\r\n\t\t\t// Get environment map u and v tiling multiples.\r\n\t\t\tMemoryRead( &pMat->m_envmap_tiling[pass][0], sizeof( float ) * 2, 1, p_data );\r\n\r\n\t\t\t// Get minification and magnification filtering mode.\r\n\t\t\tMemoryRead( &pMat->m_filtering_mode[pass], sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t\t// Read uv wibble data if present.\r\n\t\t\tif( pMat->m_flags[pass] & MATFLAG_UV_WIBBLE )\r\n\t\t\t{\r\n\t\t\t\t// Flag that this material wibbles.\r\n\t\t\t\tpMat->m_uv_wibble = true;\r\n\t\t\t\t\r\n\t\t\t\t// Create uv wibble params structure.\r\n\t\t\t\tpMat->mp_UVWibbleParams[pass] = new sUVWibbleParams;\r\n\t\t\t\tMemoryRead( pMat->mp_UVWibbleParams[pass], sizeof( float ) * 8, 1, p_data );\r\n\t\t\t}\r\n\r\n\t\t\t// Read vertex color wibble data.\r\n\t\t\tif(( pass == 0 ) && ( pMat->m_flags[0] & MATFLAG_VC_WIBBLE ))\r\n\t\t\t{\r\n\t\t\t\tMemoryRead( &NumSeqs, sizeof( uint32 ), 1, p_data );\r\n\t\t\t\tpMat->m_num_wibble_vc_anims = NumSeqs;\r\n\r\n\t\t\t\t// Create sequence data array.\r\n\t\t\t\tpMat->mp_wibble_vc_params = new sVCWibbleParams[NumSeqs];\r\n\t\t\t\t\r\n\t\t\t\t// Create resultant color array.\r\n\t\t\t\tpMat->mp_wibble_vc_colors = new D3DCOLOR[NumSeqs];\r\n\r\n\t\t\t\tfor( seq = 0; seq < NumSeqs; ++seq )\r\n\t\t\t\t{ \r\n\t\t\t\t\tMemoryRead( &NumKeys, sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t\t\t\tint phase;\r\n\t\t\t\t\tMemoryRead( &phase, sizeof( int ), 1, p_data );\r\n\r\n\t\t\t\t\t// Create array for keyframes.\r\n\t\t\t\t\tpMat->mp_wibble_vc_params[seq].m_num_keyframes\t= NumKeys;\r\n\t\t\t\t\tpMat->mp_wibble_vc_params[seq].m_phase\t\t\t= phase;\r\n\t\t\t\t\tpMat->mp_wibble_vc_params[seq].mp_keyframes\t\t= new sVCWibbleKeyframe[NumKeys];\r\n\r\n\t\t\t\t\t// Read keyframes into array.\r\n\t\t\t\t\tMemoryRead( pMat->mp_wibble_vc_params[seq].mp_keyframes, sizeof( sVCWibbleKeyframe ), NumKeys, p_data );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Read texture wibble data.\r\n\t\t\tif( pMat->m_flags[pass] & MATFLAG_PASS_TEXTURE_ANIMATES )\r\n\t\t\t{\r\n\t\t\t\t// Create the texture wibble structure if not created yet.\r\n\t\t\t\tif( pMat->mp_wibble_texture_params == NULL )\r\n\t\t\t\t{\r\n\t\t\t\t\tpMat->mp_wibble_texture_params = new NxXbox::sTextureWibbleParams;\r\n\t\t\t\t\tZeroMemory( pMat->mp_wibble_texture_params, sizeof( NxXbox::sTextureWibbleParams ));\r\n\r\n\t\t\t\t\t// Flag the material as having texture wibble.\r\n\t\t\t\t\tpMat->m_texture_wibble = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tint num_keyframes, period, iterations, phase;\r\n\t\t\t\tMemoryRead( &num_keyframes, sizeof( int ), 1, p_data );\r\n\t\t\t\tMemoryRead( &period, sizeof( int ), 1, p_data );\t\t\t// This value is currently discarded.\r\n\t\t\t\tMemoryRead( &iterations, sizeof( int ), 1, p_data );\r\n\t\t\t\tMemoryRead( &phase, sizeof( int ), 1, p_data );\r\n\r\n\t\t\t\tDbg_Assert( num_keyframes > 0 );\r\n\r\n\t\t\t\tpMat->mp_wibble_texture_params->m_num_keyframes[pass]\t= num_keyframes;\r\n\t\t\t\tpMat->mp_wibble_texture_params->m_phase[pass]\t\t\t= phase;\r\n\t\t\t\tpMat->mp_wibble_texture_params->m_num_iterations[pass]\t= iterations;\r\n\t\t\t\tpMat->mp_wibble_texture_params->mp_keyframes[pass]\t\t= new NxXbox::sTextureWibbleKeyframe[num_keyframes];\r\n\r\n\t\t\t\tfor( int ati = 0; ati < num_keyframes; ++ati )\r\n\t\t\t\t{\r\n\t\t\t\t\tMemoryRead( &pMat->mp_wibble_texture_params->mp_keyframes[pass][ati].m_time,\t\tsizeof( uint32 ), 1, p_data );\r\n\r\n\t\t\t\t\t// Read the texture checksum.\r\n\t\t\t\t\tuint32 cs;\r\n\t\t\t\t\tMemoryRead( &cs, sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t\t\t\t// Set the TextureChecksum variable so the mp_tex member will get populated.\r\n\t\t\t\t\tif( ati == 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tTextureChecksum = cs;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Resolve the checksum to a texture pointer.\r\n\t\t\t\t\tNx::CXboxTexture *p_xbox_texture = static_cast<Nx::CXboxTexture*>( p_texture_table->GetItem( cs ));\r\n\t\t\t\t\tpMat->mp_wibble_texture_params->mp_keyframes[pass][ati].mp_texture = ( p_xbox_texture ) ? p_xbox_texture->GetEngineTexture() : NULL;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif( TextureChecksum )\r\n\t\t\t{\r\n\t\t\t\t// If textured, resolve texture checksum...\r\n\t\t\t\tNx::CXboxTexture\t*p_xbox_texture\t= static_cast<Nx::CXboxTexture*>( p_texture_table->GetItem( TextureChecksum ));\r\n\t\t\t\tsTexture\t\t\t*mp_tex\t\t\t= ( p_xbox_texture ) ? p_xbox_texture->GetEngineTexture() : NULL;\r\n\r\n\t\t\t\t// Bail if checksum not found.\r\n\t\t\t\tif( mp_tex == NULL )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Message( \"error: couldn't find texture checksum %08X\\n\", TextureChecksum );\r\n\t\t\t\t\tpMat->mp_tex[pass] = NULL;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Set texture pointer.\r\n\t\t\t\t\tpMat->mp_tex[pass] = mp_tex;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Get mipmap info.\r\n\t\t\t\tMemoryRead( &MMAG, sizeof( uint32 ), 1, p_data );\r\n\t\t\t\tMemoryRead( &MMIN, sizeof( uint32 ), 1, p_data );\r\n\t\t\t\tMemoryRead( &K, sizeof( uint32 ), 1, p_data );\r\n\t\t\t\tMemoryRead( &L, sizeof( uint32 ), 1, p_data );\r\n\t\t\t\t\r\n\t\t\t\t// Default PS2 value for K appears to be -8.0f - we are interested in deviations from this value.\r\n\t\t\t\tpMat->m_k[pass]\t= ( *(float*)&K ) + 8.0f;\r\n\t\t\t\t\r\n\t\t\t\t// Dave note 09/03/02 - having MIPs selected earlier than normal seems to cause some problems, since Xbox\r\n\t\t\t\t// MIP selection is so different to Ps2. Limit the k value such that Xbox can never select smaller MIPs\r\n\t\t\t\t// earlier than it would do by default.\r\n\t\t\t\tif( pMat->m_k[pass] > 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tpMat->m_k[pass] = 0.0f;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// ...otherwise just step past mipmap info.\r\n\t\t\t\tpMat->mp_tex[pass] = NULL;\r\n\t\t\t\tp_data += 16;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Set the no material color flag if appropriate.\r\n\t\tif( neutral_material_color )\r\n\t\t{\r\n\t\t\tpMat->m_flags[0] |= MATFLAG_NO_MAT_COL_MOD;\r\n\t\t}\r\n\t\t\r\n\t\t// Set the specular flag if appropriate.\r\n\t\tif( pMat->m_specular_color[3] > 0.0f )\r\n\t\t{\r\n\t\t\tpMat->m_flags[0] |= MATFLAG_SPECULAR;\r\n\t\t}\r\n\r\n\t\t// There is a problem adding materials with the same checksum into the table.\r\n\t\t// This could happen when materials in different scenes share the same name.\r\n\t\t// It also happens for the dummy material (checksum == 0), so for now just special-case\r\n\t\t// that one.\r\n\t\tif( pMat->m_checksum == 0 )\r\n\t\t{\r\n\t\t\tif( !pMaterialTable->GetItem( 0 ))\r\n\t\t\t{\r\n\t\t\t\tpMaterialTable->PutItem( pMat->m_checksum, pMat );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\t\t\r\n\t\t{\r\n\t\t\tif( pMaterialTable->GetItem( pMat->m_checksum ))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"NXXBOX ERROR: duplicate material: %x\\n\", pMat->m_checksum ));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpMaterialTable->PutItem( pMat->m_checksum, pMat );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Set the data pointer to the new position on return.\r\n\t*pp_mem = p_data;\r\n\r\n\treturn pMaterialTable;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nLst::HashTable< sMaterial >\t*LoadMaterials( void *p_FH, Lst::HashTable< Nx::CTexture > *p_texture_table )\r\n{\r\n\tuint32 MMAG, MMIN, K, L, NumSeqs, seq, NumKeys;\r\n\t\r\n\t// Get number of materials.\r\n\tuint32 new_materials;\r\n\tFile::Read( &new_materials, sizeof( uint32 ), 1, p_FH );\r\n\t\r\n\tLst::HashTable< sMaterial >* pMaterialTable;\r\n\r\n\t// Create table, dynamically sizing it based on the number of new materials.\r\n\tuint32 optimal_table_size\t= new_materials * 2;\r\n\tuint32 test\t\t\t\t\t= 4;\r\n\tuint32 size\t\t\t\t\t= 2;\r\n\r\n\tfor( ;; test <<= 1, ++size )\r\n\t{\r\n\t\t// Check if this iteration of table size is sufficient, or if we have hit the maximum size.\r\n\t\tif(( optimal_table_size < test ) || ( size >= 12 ))\r\n\t\t{\r\n\t\t\tpMaterialTable = new Lst::HashTable< sMaterial >( size );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Loop over materials.\r\n\tfor( uint32 i = 0; i < new_materials; ++i )\r\n\t{\r\n\t\t// Create new material.\r\n\t\tsMaterial *pMat = new sMaterial;\r\n\r\n\t\t// Get material checksum.\r\n\t\tFile::Read( &pMat->m_checksum, sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t// Get material name checksum.\r\n\t\tFile::Read( &pMat->m_name_checksum, sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t// Get number of passes.\r\n\t\tFile::Read( &pMat->m_passes, sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t// Get alpha cutoff value.\r\n\t\tuint32 AlphaCutoff;\r\n\t\tFile::Read( &AlphaCutoff, sizeof( uint32 ), 1, p_FH );\r\n\t\tpMat->m_alpha_cutoff = (uint8)AlphaCutoff;\r\n\r\n\t\t// Get sorted flag.\r\n\t\tFile::Read( &pMat->m_sorted, sizeof( bool ), 1, p_FH );\r\n\t\t\r\n\t\t// Get draw order.\r\n\t\tFile::Read( &pMat->m_draw_order, sizeof( float ), 1, p_FH );\r\n\t\t\r\n\t\t// Get single sided flag.\r\n\t\tbool single_sided;\r\n\t\tFile::Read( &single_sided, sizeof( bool ), 1, p_FH );\r\n\r\n\t\t// Get backface cull flag.\r\n\t\tFile::Read( &pMat->m_no_bfc, sizeof( bool ), 1, p_FH );\r\n\r\n\t\t// Get z-bias value.\r\n\t\tint zbias;\r\n\t\tFile::Read( &zbias, sizeof( int ), 1, p_FH );\r\n\t\tpMat->m_zbias = (uint8)(( zbias > 16 ) ? 16 : zbias );\r\n\r\n\t\t// Get grassify flag and (optionally) grassify data.\r\n\t\tbool grassify;\r\n\t\tFile::Read( &grassify, sizeof( bool ), 1, p_FH );\r\n\t\tif( grassify )\r\n\t\t{\r\n\t\t\tFile::Read( &pMat->m_grass_height, sizeof( float ), 1, p_FH );\r\n\t\t\tFile::Read( &pMat->m_grass_layers, sizeof( int ), 1, p_FH );\r\n\t\t}\r\n\r\n\t\t// Get specular power and (optionally) specular color.\r\n\t\tFile::Read( &pMat->m_specular_color[3], sizeof( float ), 1, p_FH );\r\n\t\tif( pMat->m_specular_color[3] > 0.0f )\r\n\t\t{\r\n\t\t\tFile::Read( &pMat->m_specular_color[0], sizeof( float ) * 3, 1, p_FH );\r\n\t\t}\r\n\r\n\t\t// Neutral under proven otherwise.\r\n\t\tbool neutral_material_color = true;\r\n\t\tfor( uint32 pass = 0; pass < pMat->m_passes; ++pass )\r\n\t\t{\r\n\t\t\t// Get texture checksum.\r\n\t\t\tuint32 TextureChecksum;\r\n\t\t\tFile::Read( &TextureChecksum, sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t\t// Get material flags.\r\n\t\t\tFile::Read( &pMat->m_flags[pass], sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t\t// Get pass color flag.\r\n\t\t\tbool has_color;\r\n\t\t\tFile::Read( &has_color, sizeof( bool ), 1, p_FH );\r\n\r\n\t\t\t// Get pass color.\r\n\t\t\tFile::Read( &pMat->m_color[pass][0], sizeof( float ) * 3, 1, p_FH );\r\n\r\n\t\t\t// Check for color being neutral.\r\n\t\t\tif( neutral_material_color )\r\n\t\t\t{\r\n\t\t\t\tif(( pMat->m_color[pass][0] != 0.5f ) || ( pMat->m_color[pass][1] != 0.5f ) || ( pMat->m_color[pass][2] != 0.5f ))\r\n\t\t\t\t{\r\n\t\t\t\t\tneutral_material_color = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Get ALPHA register value.\r\n\t\t\tuint64 reg_alpha;\r\n\t\t\tFile::Read( &reg_alpha, sizeof( uint64 ), 1, p_FH );\r\n\r\n\t\t\tuint32\tblend_mode\t\t= (uint32)( reg_alpha & 0xFFFFFFUL );\r\n\t\t\tuint32\tfixed_alpha\t\t= (uint32)( reg_alpha >> 32 );\r\n\t\t\tpMat->m_reg_alpha[pass]\t= blend_mode | ( fixed_alpha << 24 );\r\n\r\n\t\t\t// Also calculate the floating point version of the fixed alpha.\r\n\t\t\tpMat->m_color[pass][3]\t= fixed_alpha / 128.0f;\r\n\r\n\t\t\t// Backface cull test - if this is an alpha blended material, turn off backface culling, except\r\n\t\t\t// where the material has been explicitly flagged as single sided.\r\n\t\t\tif(( pass == 0 ) && !single_sided && (( pMat->m_reg_alpha[pass] & sMaterial::BLEND_MODE_MASK ) != 0x00 ))\r\n\t\t\t{\r\n\t\t\t\tpMat->m_no_bfc = true;\r\n\t\t\t}\r\n\r\n\t\t\t// Get UV addressing types.\r\n\t\t\tuint32 u_addressing, v_addressing;\r\n\t\t\tFile::Read( &u_addressing, sizeof( uint32 ), 1, p_FH );\r\n\t\t\tFile::Read( &v_addressing, sizeof( uint32 ), 1, p_FH );\r\n\t\t\tpMat->m_uv_addressing[pass] = (( v_addressing << 16 ) | u_addressing );\r\n\t\t\t\r\n\t\t\t// Get environment map u and v tiling multiples.\r\n\t\t\tFile::Read( &pMat->m_envmap_tiling[pass][0], sizeof( float ) * 2, 1, p_FH );\r\n\r\n\t\t\t// Get minification and magnification filtering mode.\r\n\t\t\tFile::Read( &pMat->m_filtering_mode[pass], sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t\t// Read uv wibble data if present.\r\n\t\t\tif( pMat->m_flags[pass] & MATFLAG_UV_WIBBLE )\r\n\t\t\t{\r\n\t\t\t\t// Flag that this material wibbles.\r\n\t\t\t\tpMat->m_uv_wibble = true;\r\n\t\t\t\t\r\n\t\t\t\t// Create uv wibble params structure.\r\n\t\t\t\tpMat->mp_UVWibbleParams[pass] = new sUVWibbleParams;\r\n\t\t\t\tFile::Read( pMat->mp_UVWibbleParams[pass], sizeof( float ) * 8, 1, p_FH );\r\n\t\t\t}\r\n\r\n\t\t\t// Read vertex color wibble data.\r\n\t\t\tif(( pass == 0 ) && ( pMat->m_flags[0] & MATFLAG_VC_WIBBLE ))\r\n\t\t\t{\r\n\t\t\t\tFile::Read( &NumSeqs, sizeof( uint32 ), 1, p_FH );\r\n\t\t\t\tpMat->m_num_wibble_vc_anims = NumSeqs;\r\n\r\n\t\t\t\t// Create sequence data array.\r\n\t\t\t\tpMat->mp_wibble_vc_params = new sVCWibbleParams[NumSeqs];\r\n\t\t\t\t\r\n\t\t\t\t// Create resultant color array.\r\n\t\t\t\tpMat->mp_wibble_vc_colors = new D3DCOLOR[NumSeqs];\r\n\r\n\t\t\t\tfor( seq = 0; seq < NumSeqs; ++seq )\r\n\t\t\t\t{ \r\n\t\t\t\t\tFile::Read( &NumKeys, sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t\t\t\tint phase;\r\n\t\t\t\t\tFile::Read( &phase, sizeof( int ), 1, p_FH );\r\n\r\n\t\t\t\t\t// Create array for keyframes.\r\n\t\t\t\t\tpMat->mp_wibble_vc_params[seq].m_num_keyframes\t= NumKeys;\r\n\t\t\t\t\tpMat->mp_wibble_vc_params[seq].m_phase\t\t\t= phase;\r\n\t\t\t\t\tpMat->mp_wibble_vc_params[seq].mp_keyframes\t\t= new sVCWibbleKeyframe[NumKeys];\r\n\r\n\t\t\t\t\t// Read keyframes into array.\r\n\t\t\t\t\tFile::Read( pMat->mp_wibble_vc_params[seq].mp_keyframes, sizeof( sVCWibbleKeyframe ), NumKeys, p_FH );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Read texture wibble data.\r\n\t\t\tif( pMat->m_flags[pass] & MATFLAG_PASS_TEXTURE_ANIMATES )\r\n\t\t\t{\r\n\t\t\t\t// Create the texture wibble structure if not created yet.\r\n\t\t\t\tif( pMat->mp_wibble_texture_params == NULL )\r\n\t\t\t\t{\r\n\t\t\t\t\tpMat->mp_wibble_texture_params = new NxXbox::sTextureWibbleParams;\r\n\t\t\t\t\tZeroMemory( pMat->mp_wibble_texture_params, sizeof( NxXbox::sTextureWibbleParams ));\r\n\r\n\t\t\t\t\t// Flag the material as having texture wibble.\r\n\t\t\t\t\tpMat->m_texture_wibble = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tint num_keyframes, period, iterations, phase;\r\n\t\t\t\tFile::Read( &num_keyframes, sizeof( int ), 1, p_FH );\r\n\t\t\t\tFile::Read( &period, sizeof( int ), 1, p_FH );\t\t\t// This value is currently discarded.\r\n\t\t\t\tFile::Read( &iterations, sizeof( int ), 1, p_FH );\r\n\t\t\t\tFile::Read( &phase, sizeof( int ), 1, p_FH );\r\n\r\n\t\t\t\tDbg_Assert( num_keyframes > 0 );\r\n\r\n\t\t\t\tpMat->mp_wibble_texture_params->m_num_keyframes[pass]\t= num_keyframes;\r\n\t\t\t\tpMat->mp_wibble_texture_params->m_phase[pass]\t\t\t= phase;\r\n\t\t\t\tpMat->mp_wibble_texture_params->m_num_iterations[pass]\t= iterations;\r\n\t\t\t\tpMat->mp_wibble_texture_params->mp_keyframes[pass]\t\t= new NxXbox::sTextureWibbleKeyframe[num_keyframes];\r\n\r\n\t\t\t\tfor( int ati = 0; ati < num_keyframes; ++ati )\r\n\t\t\t\t{\r\n\t\t\t\t\tFile::Read( &pMat->mp_wibble_texture_params->mp_keyframes[pass][ati].m_time,\t\tsizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t\t\t\t// Read the texture checksum.\r\n\t\t\t\t\tuint32 cs;\r\n\t\t\t\t\tFile::Read( &cs, sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t\t\t\t// Set the TextureChecksum variable so the mp_tex member will get populated.\r\n\t\t\t\t\tif( ati == 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tTextureChecksum = cs;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Resolve the checksum to a texture pointer.\r\n\t\t\t\t\tNx::CXboxTexture *p_xbox_texture = static_cast<Nx::CXboxTexture*>( p_texture_table->GetItem( cs ));\r\n\t\t\t\t\tpMat->mp_wibble_texture_params->mp_keyframes[pass][ati].mp_texture = ( p_xbox_texture ) ? p_xbox_texture->GetEngineTexture() : NULL;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif( TextureChecksum )\r\n\t\t\t{\r\n\t\t\t\t// If textured, resolve texture checksum...\r\n\t\t\t\tNx::CXboxTexture\t*p_xbox_texture\t= static_cast<Nx::CXboxTexture*>( p_texture_table->GetItem( TextureChecksum ));\r\n\t\t\t\tsTexture\t\t\t*mp_tex\t\t\t= ( p_xbox_texture ) ? p_xbox_texture->GetEngineTexture() : NULL;\r\n\r\n\t\t\t\t// Bail if checksum not found.\r\n\t\t\t\tif( mp_tex == NULL )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Message( \"error: couldn't find texture checksum %08X\\n\", TextureChecksum );\r\n\t\t\t\t\tpMat->mp_tex[pass] = NULL;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Set texture pointer.\r\n\t\t\t\t\tpMat->mp_tex[pass] = mp_tex;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Get mipmap info.\r\n\t\t\t\tFile::Read( &MMAG, sizeof( uint32 ), 1, p_FH );\r\n\t\t\t\tFile::Read( &MMIN, sizeof( uint32 ), 1, p_FH );\r\n\t\t\t\tFile::Read( &K, sizeof( uint32 ), 1, p_FH );\r\n\t\t\t\tFile::Read( &L, sizeof( uint32 ), 1, p_FH );\r\n\t\t\t\t\r\n\t\t\t\t// Default PS2 value for K appears to be -8.0f - we are interested in deviations from this value.\r\n\t\t\t\tpMat->m_k[pass]\t= ( *(float*)&K ) + 8.0f;\r\n\t\t\t\t\r\n\t\t\t\t// Dave note 09/03/02 - having MIPs selected earlier than normal seems to cause some problems, since Xbox\r\n\t\t\t\t// MIP selection is so different to Ps2. Limit the k value such that Xbox can never select smaller MIPs\r\n\t\t\t\t// earlier than it would do by default.\r\n\t\t\t\tif( pMat->m_k[pass] > 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tpMat->m_k[pass] = 0.0f;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// ...otherwise just step past mipmap info.\r\n\t\t\t\tpMat->mp_tex[pass] = NULL;\r\n\t\t\t\tFile::Seek( p_FH, 16, SEEK_CUR );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Set the no material color flag if appropriate.\r\n\t\tif( neutral_material_color )\r\n\t\t{\r\n\t\t\tpMat->m_flags[0] |= MATFLAG_NO_MAT_COL_MOD;\r\n\t\t}\r\n\t\t\r\n\t\t// Set the specular flag if appropriate.\r\n\t\tif( pMat->m_specular_color[3] > 0.0f )\r\n\t\t{\r\n\t\t\tpMat->m_flags[0] |= MATFLAG_SPECULAR;\r\n\t\t}\r\n\r\n\t\t// There is a problem adding materials with the same checksum into the table.\r\n\t\t// This could happen when materials in different scenes share the same name.\r\n\t\t// It also happens for the dummy material (checksum == 0), so for now just special-case\r\n\t\t// that one.\r\n\t\tif( pMat->m_checksum == 0 )\r\n\t\t{\r\n\t\t\tif( !pMaterialTable->GetItem( 0 ))\r\n\t\t\t{\r\n\t\t\t\tpMaterialTable->PutItem( pMat->m_checksum, pMat );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\t\t\r\n\t\t{\r\n\t\t\tif( pMaterialTable->GetItem( pMat->m_checksum ))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"NXXBOX ERROR: duplicate material: %x\\n\", pMat->m_checksum ));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpMaterialTable->PutItem( pMat->m_checksum, pMat );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn pMaterialTable;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/material.h",
    "content": "#ifndef __MATERIAL_H\r\n#define __MATERIAL_H\r\n\r\n#include <core/HashTable.h>\r\n#include <gfx/image/imagebasic.h>\r\n#include <gfx/nxtexture.h>\r\n#include \"texture.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n// Material Flags\r\n#define MATFLAG_UV_WIBBLE\t\t\t\t\t(1<<0)\r\n#define MATFLAG_VC_WIBBLE\t\t\t\t\t(1<<1)\r\n#define MATFLAG_TEXTURED\t\t\t\t\t(1<<2)\r\n#define MATFLAG_ENVIRONMENT\t\t\t\t\t(1<<3)\r\n#define MATFLAG_DECAL\t\t\t\t\t\t(1<<4)\r\n#define MATFLAG_SMOOTH\t\t\t\t\t\t(1<<5)\r\n#define MATFLAG_TRANSPARENT\t\t\t\t\t(1<<6)\r\n#define MATFLAG_PASS_COLOR_LOCKED\t\t\t(1<<7)\r\n#define MATFLAG_SPECULAR\t\t\t\t\t(1<<8)\t\t// Specular lighting is enabled on this material (Pass0).\r\n#define MATFLAG_BUMP_SIGNED_TEXTURE\t\t\t(1<<9)\t\t// This pass uses an offset texture which needs to be treated as signed data.\r\n#define MATFLAG_BUMP_LOAD_MATRIX\t\t\t(1<<10)\t\t// This pass requires the bump mapping matrix elements to be set up.\r\n#define MATFLAG_PASS_TEXTURE_ANIMATES\t\t(1<<11)\t\t// This pass has a texture which animates.\r\n#define MATFLAG_PASS_IGNORE_VERTEX_ALPHA\t(1<<12)\t\t// This pass should not have the texel alpha modulated by the vertex alpha.\r\n#define MATFLAG_EXPLICIT_UV_WIBBLE\t\t\t(1<<14)\t\t// Uses explicit uv wibble (set via script) rather than calculated.\r\n#define MATFLAG_WATER_EFFECT\t\t\t\t(1<<27)\t\t// This material should be processed to provide the water effect.\r\n#define MATFLAG_NO_MAT_COL_MOD\t\t\t\t(1<<28)\t\t// No material color modulation required (all passes have m.rgb = 0.5).\r\n\r\n\r\nconst uint32 MAX_PASSES = 4;\r\n\r\n\r\n\t\r\nstruct sUVWibbleParams\r\n{\r\n\t\t\tsUVWibbleParams( void );\r\n\t\t\t~sUVWibbleParams( void );\r\n\r\n\tfloat\tm_UVel;\r\n\tfloat\tm_VVel;\r\n\tfloat\tm_UFrequency;\r\n\tfloat\tm_VFrequency;\r\n\tfloat\tm_UAmplitude;\r\n\tfloat\tm_VAmplitude;\r\n\tfloat\tm_UPhase;\r\n\tfloat\tm_VPhase;\r\n\tfloat\tm_UVMatrix[4];\t\t// This value is written to dynamically. The first two values are rotation, the second two are translation.\r\n};\r\n\r\nstruct sVCWibbleKeyframe\r\n{\r\n\tint\t\t\tm_time;\r\n\tImage::RGBA\tm_color;\r\n};\r\n\r\nstruct sVCWibbleParams\r\n{\r\n\tuint32\t\t\t\tm_num_keyframes;\r\n\tint\t\t\t\t\tm_phase;\r\n\tsVCWibbleKeyframe\t*mp_keyframes;\r\n};\r\n\r\n\r\nstruct sTextureWibbleKeyframe\r\n{\r\n\tint\t\t\tm_time;\r\n\tsTexture\t*mp_texture;\r\n};\r\n\r\nstruct sTextureWibbleParams\r\n{\r\n\tuint32\t\t\t\t\tm_num_keyframes[MAX_PASSES];\r\n\tint\t\t\t\t\t\tm_phase[MAX_PASSES];\r\n\tint\t\t\t\t\t\tm_num_iterations[MAX_PASSES];\r\n\tsTextureWibbleKeyframe\t*mp_keyframes[MAX_PASSES];\r\n};\r\n\r\n\r\n\r\nstruct sMaterial\r\n{\r\n\tpublic:\r\n\r\n\tstatic const uint32\t\tBLEND_MODE_MASK\t= 0x00FFFFFFUL;\r\n\r\n\t\t\t\t\t\t\tsMaterial( void );\r\n\t\t\t\t\t\t\t~sMaterial( void );\r\n\t\r\n\tvoid\t\t\t\t\tSubmit( void );\r\n\tuint32\t\t\t\t\tGetIgnoreVertexAlphaPasses( void );\r\n\tvoid\t\t\t\t\tfigure_wibble_uv( void );\r\n\tvoid\t\t\t\t\tfigure_wibble_vc( void );\r\n\tvoid\t\t\t\t\tfigure_wibble_texture( void );\r\n\r\n\tuint32\t\t\t\t\tm_checksum;\r\n\tuint32\t\t\t\t\tm_name_checksum;\r\n\tuint32\t\t\t\t\tm_passes;\r\n\r\n\tbool\t\t\t\t\tm_sorted;\r\n\tbool\t\t\t\t\tm_no_bfc;\r\n\tbool\t\t\t\t\tm_uv_wibble;\r\n\tbool\t\t\t\t\tm_texture_wibble;\r\n\tuint8\t\t\t\t\tm_alpha_cutoff;\r\n\tuint8\t\t\t\t\tm_zbias;\r\n\r\n\tfloat\t\t\t\t\tm_grass_height;\r\n\tint\t\t\t\t\t\tm_grass_layers;\r\n\tfloat\t\t\t\t\tm_draw_order;\r\n\tuint32\t\t\t\t\tm_flags[MAX_PASSES];\r\n\tsTexture*\t\t\t\tmp_tex[MAX_PASSES];\r\n\tfloat\t\t\t\t\tm_color[MAX_PASSES][4];\t\t\t\t// Element [pass][3] holds the fixed alpha value where appropriate.\r\n\tuint32\t\t\t\t\tm_reg_alpha[MAX_PASSES];\t\t\t// Low 24 bits are blend mode, high 8 bits are fixed alpha value.\r\n\tuint32\t\t\t\t\tm_uv_addressing[MAX_PASSES];\r\n\tfloat\t\t\t\t\tm_envmap_tiling[MAX_PASSES][2];\t\t// Tile multiples for env mapping (NOTE: could maybe be changed to byte array?)\r\n\tuint32\t\t\t\t\tm_filtering_mode[MAX_PASSES];\r\n\tsUVWibbleParams\t\t\t*mp_UVWibbleParams[MAX_PASSES];\r\n\tfloat\t\t\t\t\tm_k[MAX_PASSES];\r\n\tuint32\t\t\t\t\tm_num_wibble_vc_anims;\r\n\tsVCWibbleParams\t\t\t*mp_wibble_vc_params;\r\n\tD3DCOLOR\t\t\t\t*mp_wibble_vc_colors;\t\t\t\t// Max of eight banks of vertex color wibble information.\r\n\tsTextureWibbleParams\t*mp_wibble_texture_params;\r\n\tfloat\t\t\t\t\tm_specular_color[4];\t\t\t\t// Specular color (0-2) plus power term (3).\r\n};\r\n\r\n\r\nLst::HashTable< sMaterial >\t*LoadMaterials( void *p_FH, Lst::HashTable< Nx::CTexture > *p_texture_table );\r\nLst::HashTable< sMaterial >\t*LoadMaterialsFromMemory( void **pp_mem, Lst::HashTable< Nx::CTexture > *p_texture_table );\r\n\r\n//extern Lst::HashTable< sMaterial > *pMaterialTable;\r\nextern uint32 NumMaterials;\r\n\r\n} // namespace NxXbox\r\n\r\n#endif // __MATERIAL_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/mesh.cpp",
    "content": "#include <xtl.h>\r\n#include <xgraphics.h>\r\n\r\n#include <sys/timer.h>\r\n#include <sys/file/filesys.h>\r\n#include <core/macros.h>\r\n\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include \"nx_init.h\"\r\n#include \"texture.h\"\r\n#include \"scene.h\"\r\n#include \"mesh.h\"\r\n#include \"anim.h\"\r\n#include \"render.h\"\r\n#include \"billboard.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\nbool\t\t\ts_meshScalingEnabled = false;\r\nchar*\t\t\ts_pWeightIndices = NULL;\r\nfloat*\t\t\ts_pWeights = NULL;\r\nMth::Vector*\ts_pBonePositions = NULL;\r\nMth::Vector*\ts_pBoneScales = NULL;\r\nint\t\t\t\ts_currentVertIndex = 0;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SetMeshScalingParameters( Nx::SMeshScalingParameters* pParams )\r\n{\r\n\tDbg_Assert( pParams );\r\n\r\n\ts_meshScalingEnabled\t= true;\r\n\ts_pWeights\t\t\t\t= pParams->pWeights;\r\n\ts_pWeightIndices\t\t= pParams->pWeightIndices;\r\n\ts_pBoneScales\t\t\t= pParams->pBoneScales;\r\n\ts_pBonePositions\t\t= pParams->pBonePositions;\r\n\ts_currentVertIndex\t\t= 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid DisableMeshScaling( void )\r\n{\r\n\ts_meshScalingEnabled\t= false;\r\n\ts_pWeights\t\t\t\t= NULL;\r\n\ts_pWeightIndices\t\t= NULL;\r\n\ts_pBoneScales\t\t\t= NULL;\r\n\ts_pBonePositions\t\t= NULL;\r\n\ts_currentVertIndex\t\t= 0;\r\n}\r\n\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline Mth::Vector get_bone_scale( int bone_index )\r\n{\r\n\tMth::Vector returnVec( 1.0f, 1.0f, 1.0f, 1.0f );\r\n\r\n\tif( bone_index >= 29 && bone_index <= 33 )\r\n\t{\r\n\t\t// this only works with the thps5 skeleton, whose\r\n\t\t// head bones are between 29 and 33...\r\n\t\t// (eventually, we can remove the subtract 29\r\n\t\t// once the exporter is massaging the data correctly)\r\n\t\treturnVec = s_pBoneScales[ bone_index - 29 ];\r\n\t\t\r\n\t\t// Y & Z are reversed...  odd!\r\n\t\tMth::Vector tempVec = returnVec;\r\n\t\treturnVec[Y] = tempVec[Z];\r\n\t\treturnVec[Z] = tempVec[Y];\r\n\t}\r\n\telse if( bone_index == -1 )\r\n\t{\r\n\t\t// implies that it's not weighted to a bone\r\n\t\treturn returnVec;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// implies that it's weighted to the wrong bone\r\n\t\treturn returnVec;\r\n\t}\r\n\treturn returnVec;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline Mth::Vector get_bone_pos( int bone_index )\r\n{\r\n\tMth::Vector returnVec( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\t\r\n\tif( bone_index >= 29 && bone_index <= 33 )\r\n\t{\r\n\t\t// this only works with the thps5 skeleton, whose\r\n\t\t// head bones are between 29 and 33...\r\n\t\t// (eventually, we can remove the subtract 29\r\n\t\t// once the exporter is massaging the data correctly)\r\n\t\treturnVec = s_pBonePositions[ bone_index - 29 ];\r\n\t}\r\n\telse if( bone_index == -1 )\r\n\t{\r\n\t\t// implies that it's not weighted to a bone\r\n\t\treturn returnVec;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// implies that it's weighted to the wrong bone\r\n\t\treturn returnVec;\r\n\t}\r\n\treturnVec[W] = 1.0f;\r\n\r\n\treturn returnVec;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid ApplyMeshScaling( float* p_vertices, int num_verts )\r\n{\r\n\tif( s_meshScalingEnabled )\r\n\t{\r\n\t\tfor( int v = 0; v < num_verts; ++v, p_vertices += 3 )\r\n\t\t{\r\n\t\t\tfloat x = p_vertices[0];\r\n\t\t\tfloat y = p_vertices[1];\r\n\t\t\tfloat z = p_vertices[2];\r\n\r\n    \t\tMth::Vector origPos( x, y, z, 1.0f );\r\n\r\n\t\t\tMth::Vector bonePos0 = get_bone_pos( s_pWeightIndices[v * 3] );\r\n\t\t\tMth::Vector bonePos1 = get_bone_pos( s_pWeightIndices[v * 3 + 1] );\r\n\t\t\tMth::Vector bonePos2 = get_bone_pos( s_pWeightIndices[v * 3 + 2] );\r\n\r\n\t\t\t// Need to scale each vert relative to its parent bone.\r\n\t\t\tMth::Vector localPos0 = origPos - bonePos0;\r\n\t\t\tMth::Vector localPos1 = origPos - bonePos1;\r\n\t\t\tMth::Vector localPos2 = origPos - bonePos2;\r\n\r\n\t\t\tlocalPos0.Scale( get_bone_scale( s_pWeightIndices[v * 3] ) );\r\n\t\t\tlocalPos1.Scale( get_bone_scale( s_pWeightIndices[v * 3 + 1] ) );\r\n\t\t\tlocalPos2.Scale( get_bone_scale( s_pWeightIndices[v * 3 + 2] ) );\r\n\r\n\t\t\tlocalPos0 += bonePos0;\r\n\t\t\tlocalPos1 += bonePos1;\r\n\t\t\tlocalPos2 += bonePos2;\r\n\t\t\t\r\n\t\t\tMth::Vector scaledPos = ( localPos0 * s_pWeights[v * 3] ) +\r\n\t\t\t\t\t\t\t\t\t( localPos1 * s_pWeights[v * 3 + 1] ) +\r\n\t\t\t\t\t\t\t\t\t( localPos2 * s_pWeights[v * 3 + 2] );\r\n\r\n\t\t\tp_vertices[0] = scaledPos[X];\r\n\t\t\tp_vertices[1] = scaledPos[Y];\r\n\t\t\tp_vertices[2] = scaledPos[Z];\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsMesh::sMesh( void )\r\n{\r\n\tm_flags\t\t\t\t\t\t\t= 0;\r\n\tm_num_vertex_buffers\t\t\t= 1;\r\n\tm_current_write_vertex_buffer\t= 0;\r\n\tfor( int vb = 0; vb < MAX_VERTEX_BUFFERS; ++vb )\r\n\t{\r\n\t\tmp_vertex_buffer[vb]\t\t= NULL;\r\n\t}\r\n\tfor( int ib = 0; ib < MAX_INDEX_BUFFERS; ++ib )\r\n\t{\r\n\t\tmp_index_buffer[ib]\t\t\t= NULL;\r\n\t\tm_num_indices[ib]\t\t\t= 0;\r\n\t}\r\n\tmp_vc_wibble_data\t\t\t\t= NULL;\r\n\tmp_index_lod_data\t\t\t\t= NULL;\r\n\tmp_billboard_data\t\t\t\t= NULL;\r\n\tm_bone_index\t\t\t\t\t= -1;\r\n\tmp_transform\t\t\t\t\t= NULL;\r\n\tm_diffuse_offset\t\t\t\t= 0;\r\n\tm_uv0_offset\t\t\t\t\t= 0;\r\n\tm_normal_offset\t\t\t\t\t= 0;\r\n\tm_vertex_stride\t\t\t\t\t= 0;\r\n\tm_vertex_shader[0]\t\t\t\t= 0;\r\n\tm_pixel_shader\t\t\t\t\t= 0;\r\n\r\n\tSetActive( true );\r\n\tSetVisibility( 0xFF );\r\n\r\n\t// Set default primitive type.\r\n\tm_primitive_type\t\t\t\t= D3DPT_TRIANGLESTRIP;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsMesh::~sMesh( void )\r\n{\r\n\t// Remove this mesh from the billboard manager if appropriate.\r\n\tif( m_flags & sMesh::MESH_FLAG_BILLBOARD )\r\n\t{\r\n\t\tBillboardManager.RemoveEntry( this );\r\n\t}\r\n\r\n\tEngineGlobals.p_Device->BlockUntilIdle();\r\n\r\n\tif( mp_transform )\r\n\t{\r\n\t\tdelete mp_transform;\r\n\t}\r\n\t\r\n\tif( !( m_flags & MESH_FLAG_IS_INSTANCE ))\r\n\t{\r\n\t\tfor( int ib = 0; ib < MAX_INDEX_BUFFERS; ++ib )\r\n\t\t{\r\n\t\t\tdelete [] mp_index_buffer[ib];\r\n\t\t\tmp_index_buffer[ib] = NULL;\r\n\t\t}\r\n\r\n\t\tif( mp_vc_wibble_data )\r\n\t\t{\r\n\t\t\tdelete mp_vc_wibble_data;\r\n\t\t\tmp_vc_wibble_data = NULL;\r\n\t\t}\r\n\r\n\t\tif( mp_index_lod_data )\r\n\t\t{\r\n\t\t\tdelete mp_index_lod_data;\r\n\t\t\tmp_index_lod_data = NULL;\r\n\t\t}\r\n\r\n\t\tif( mp_billboard_data )\r\n\t\t{\r\n\t\t\tdelete mp_billboard_data;\r\n\t\t\tmp_billboard_data = NULL;\r\n\t\t}\r\n\r\n\t\tUINT\t\t\t\t\tstride;\r\n\t\tIDirect3DVertexBuffer8\t*p_vb;\r\n\t\tD3DDevice_GetStreamSource( 0, &p_vb, &stride );\r\n\t\tif( p_vb )\r\n\t\t{\r\n\t\t\t// GetStreamSource() increments the reference count, so call Release() here.\r\n\t\t\tp_vb->Release();\r\n\t\t}\r\n\r\n\t\tfor( uint32 i = 0; i < m_num_vertex_buffers; ++i )\r\n\t\t{\r\n\t\t\tif( mp_vertex_buffer[i] )\r\n\t\t\t{\r\n\t\t\t\tif( p_vb == mp_vertex_buffer[i] )\r\n\t\t\t\t{\r\n\t\t\t\t\t// We are deleting a vertex buffer that is set as the current stream source. This can result in\r\n\t\t\t\t\t// problems with the internal D3D reference counter, so clear this up first.\r\n\t\t\t\t\tD3DDevice_SetStreamSource( 0, NULL, 0 );\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tuint8 *p_del = (uint8*)mp_vertex_buffer[i];\r\n\t\t\t\tdelete p_del;\r\n\t\t\t\tmp_vertex_buffer[i]\t= NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::PushVertexShader( uint32 shader_id )\r\n{\r\n\tfor( uint32 i = sMesh::VERTEX_SHADER_STACK_SIZE - 1; i > 0; --i )\r\n\t{\r\n\t\tm_vertex_shader[i] = m_vertex_shader[i - 1];\r\n\t}\r\n\tm_vertex_shader[0] = shader_id;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::PopVertexShader( void )\r\n{\r\n\tfor( uint32 i = 0; i < sMesh::VERTEX_SHADER_STACK_SIZE - 1; ++i )\r\n\t{\r\n\t\tm_vertex_shader[i] = m_vertex_shader[i + 1];\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::wibble_normals( void )\r\n{\r\n\tif( m_flags & 0 )\r\n\t{\r\n\t\t// Angle in the range [-PI/16, PI/16], period is 1 second.\r\n\t\tfloat time = (float)Tmr::GetTime() * 0.0005f;\r\n\r\n\t\tBYTE\t\t*p_byte;\r\n\t\tfloat\t\t*p_normal;\r\n\t\tfloat\t\t*p_pos;\r\n\t\tmp_vertex_buffer[m_current_write_vertex_buffer]->Lock( 0, 0, &p_byte, 0 );\r\n\t\tp_pos\t\t= (float*)( p_byte + 0 );\r\n\t\tp_normal\t= (float*)( p_byte + m_normal_offset );\r\n\r\n\t\tfor( uint32 i = 0; i < m_num_vertices; ++i )\r\n\t\t{\r\n\t\t\tfloat x\t\t\t\t= p_pos[0] - m_sphere_center.x;\r\n\t\t\tfloat z\t\t\t\t= p_pos[2] - m_sphere_center.z;\r\n\t\t\t\r\n\t\t\tfloat time_offset_x\t= time + (( x / m_sphere_radius ) * 0.5f );\r\n\t\t\tfloat time_offset_z\t= time + (( z / m_sphere_radius ) * 0.5f );\r\n\r\n\t\t\tfloat angle_x\t\t= ( Mth::PI * ( 1.0f / 64.0f ) * (float)fabs( sinf( time_offset_x * Mth::PI ))) - ( Mth::PI * ( 1.0f / 128.0f ));\r\n\t\t\tfloat angle_z\t\t= ( Mth::PI * ( 1.0f / 64.0f ) * (float)fabs( sinf( time_offset_z * Mth::PI ))) - ( Mth::PI * ( 1.0f / 129.0f ));\r\n\t\t\t\r\n\t\t\tMth::Vector\tn( sinf( angle_x ), cosf(( angle_x + angle_z ) * 0.5f ), sinf( angle_z ));\r\n\t\t\tn.Normalize();\r\n\t\t\t\r\n\t\t\tp_normal[0]\t\t\t= n[X];\r\n\t\t\tp_normal[1]\t\t\t= n[Y];\r\n\t\t\tp_normal[2]\t\t\t= n[Z];\r\n\t\t\t\r\n\t\t\tp_pos\t\t\t\t= (float*)((BYTE*)p_pos + m_vertex_stride );\r\n\t\t\tp_normal\t\t\t= (float*)((BYTE*)p_normal + m_vertex_stride );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::wibble_vc( void )\r\n{\r\n\tif( mp_vc_wibble_data )\r\n\t{\r\n\t\t// Grab byte pointer to current 'write' vertex buffer.\r\n\t\tBYTE\t\t*p_byte;\r\n\t\tD3DCOLOR\t*p_color;\r\n\t\tmp_vertex_buffer[m_current_write_vertex_buffer]->Lock( 0, 0, &p_byte, 0 );\r\n\t\tp_color = (D3DCOLOR*)( p_byte + m_diffuse_offset );\r\n\r\n\t\tD3DCOLOR *p_color_array\t= mp_material->mp_wibble_vc_colors;\r\n\r\n\t\t// Scan through each vertex, setting the new color.\r\n\t\tfor( uint32 i = 0; i < m_num_vertices; ++i )\r\n\t\t{\r\n\t\t\t// An index of zero means no update for this vert.\r\n\t\t\tuint32 index\t= mp_vc_wibble_data[i];\r\n\t\t\tif( index > 0 )\r\n\t\t\t{\r\n\t\t\t\t*p_color\t= p_color_array[index - 1];\r\n\t\t\t}\r\n\t\t\tp_color\t\t= (D3DCOLOR*)((BYTE*)p_color + m_vertex_stride );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::CreateDuplicateVertexBuffers( int n )\r\n{\r\n\t// Ensure this hasn't already been called.\r\n\tDbg_Assert( mp_vertex_buffer[0] != NULL );\r\n\tDbg_Assert( mp_vertex_buffer[1] == NULL );\r\n\tDbg_Assert(( n > 0 ) && ( n < MAX_VERTEX_BUFFERS ));\r\n\r\n\t// Lock the source buffer.\r\n\tBYTE *p_byte;\r\n\tif( D3D_OK != mp_vertex_buffer[0]->Lock( 0, 0, &p_byte, D3DLOCK_READONLY ))\r\n\t{\r\n\t\texit( 0 );\r\n\t}\r\n\t\r\n\tfor( int i = 0; i < n; ++i )\r\n\t{\r\n\t\tmp_vertex_buffer[i + 1] = AllocateVertexBuffer( m_vertex_stride * m_num_vertices );\r\n\r\n\t\t// Lock the destination buffer and copy the contents of the original buffer into the new buffer.\r\n\t\tBYTE *p_byte2;\r\n\t\tif( D3D_OK != mp_vertex_buffer[i + 1]->Lock( 0, 0, &p_byte2, 0 ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\t\tCopyMemory( p_byte2, p_byte, m_vertex_stride * m_num_vertices );\r\n\t}\r\n\r\n\tm_num_vertex_buffers = 1 + n;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::SetPosition( Mth::Vector &pos )\r\n{\r\n\t// Create a transform if one doesn't exist yet.\r\n\tif( mp_transform == NULL )\r\n\t{\r\n\t\tmp_transform = new Mth::Matrix();\r\n\t\tmp_transform->Ident();\r\n\t}\r\n\t\r\n\t// Figure what we need to add to each vertex, based on current position.\r\n\tMth::Vector offset(\tpos[X] - mp_transform->GetPos()[X],\r\n\t\t\t\t\t\tpos[Y] - mp_transform->GetPos()[Y],\r\n\t\t\t\t\t\tpos[Z] - mp_transform->GetPos()[Z] );\r\n\r\n\tmp_transform->SetPos( pos );\r\n\t\r\n\tfor( uint32 vb = 0; vb < m_num_vertex_buffers; ++vb )\r\n\t{\r\n\t\tBYTE *p_byte;\r\n\t\tmp_vertex_buffer[vb]->Lock( 0, 0, &p_byte, 0 );\r\n\r\n\t\tfor( uint32 v = 0; v < m_num_vertices; ++v )\r\n\t\t{\r\n\t\t\t((D3DVECTOR*)p_byte )->x += offset[X];\r\n\t\t\t((D3DVECTOR*)p_byte )->y += offset[Y];\r\n\t\t\t((D3DVECTOR*)p_byte )->z += offset[Z];\r\n\t\t\tp_byte += m_vertex_stride;\r\n\t\t}\r\n\t}\r\n\r\n\t// We also need to adjust the bounding box and sphere information for this mesh.\r\n\tm_sphere_center.x += offset[X];\r\n\tm_sphere_center.y += offset[Y];\r\n\tm_sphere_center.z += offset[Z];\r\n}\r\n\t\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::GetPosition( Mth::Vector *p_pos )\r\n{\r\n\tif( mp_transform == NULL )\r\n\t{\r\n\t\tp_pos->Set( 0.0f, 0.0f, 0.0f );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t*p_pos = mp_transform->GetPos();\r\n\t}\r\n}\r\n\t\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::SetYRotation( Mth::ERot90 rot )\r\n{\r\n\tif( rot > Mth::ROT_0 )\r\n\t{\r\n\t\t// Create a transform if one doesn't exist yet.\r\n\t\tif( mp_transform == NULL )\r\n\t\t{\r\n\t\t\tmp_transform = new Mth::Matrix();\r\n\t\t\tmp_transform->Ident();\r\n\t\t}\r\n\r\n\t\tfor( uint32 vb = 0; vb < m_num_vertex_buffers; ++vb )\r\n\t\t{\r\n\t\t\tBYTE *p_byte;\r\n\t\t\tmp_vertex_buffer[vb]->Lock( 0, 0, &p_byte, 0 );\r\n\r\n\t\t\tswitch( rot )\r\n\t\t\t{\r\n\t\t\t\tcase Mth::ROT_90:\r\n\t\t\t\t{\r\n\t\t\t\t\tfor( uint32 v = 0; v < m_num_vertices; ++v )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfloat x = ((D3DVECTOR*)p_byte )->x - mp_transform->GetPos()[X];\r\n\t\t\t\t\t\tfloat z = ((D3DVECTOR*)p_byte )->z - mp_transform->GetPos()[Z];\r\n\t\t\t\t\t\t((D3DVECTOR*)p_byte )->x = z + mp_transform->GetPos()[X];\r\n\t\t\t\t\t\t((D3DVECTOR*)p_byte )->z = -x + mp_transform->GetPos()[Z];\r\n\t\t\t\t\t\tp_byte += m_vertex_stride;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Adjust the bounding sphere information for this mesh.\r\n\t\t\t\t\tm_sphere_center.x\t-= mp_transform->GetPos()[X];\r\n\t\t\t\t\tm_sphere_center.z\t-= mp_transform->GetPos()[Z];\r\n\t\t\t\t\tfloat t\t\t\t\t= m_sphere_center.x;\r\n\t\t\t\t\tm_sphere_center.x\t= m_sphere_center.z + mp_transform->GetPos()[X];\r\n\t\t\t\t\tm_sphere_center.z\t= -t + mp_transform->GetPos()[Z];\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase Mth::ROT_180:\r\n\t\t\t\t{\r\n\t\t\t\t\tfor( uint32 v = 0; v < m_num_vertices; ++v )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfloat x = ((D3DVECTOR*)p_byte )->x - mp_transform->GetPos()[X];\r\n\t\t\t\t\t\tfloat z = ((D3DVECTOR*)p_byte )->z - mp_transform->GetPos()[Z];\r\n\t\t\t\t\t\t((D3DVECTOR*)p_byte )->x = -x + mp_transform->GetPos()[X];\r\n\t\t\t\t\t\t((D3DVECTOR*)p_byte )->z = -z + mp_transform->GetPos()[Z];\r\n\t\t\t\t\t\tp_byte += m_vertex_stride;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Adjust the bounding sphere information for this mesh.\r\n\t\t\t\t\tm_sphere_center.x\t-= mp_transform->GetPos()[X];\r\n\t\t\t\t\tm_sphere_center.z\t-= mp_transform->GetPos()[Z];\r\n\t\t\t\t\tm_sphere_center.x\t= -m_sphere_center.x + mp_transform->GetPos()[X];\r\n\t\t\t\t\tm_sphere_center.z\t= -m_sphere_center.z + mp_transform->GetPos()[Z];\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase Mth::ROT_270:\r\n\t\t\t\t{\r\n\t\t\t\t\tfor( uint32 v = 0; v < m_num_vertices; ++v )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfloat x = ((D3DVECTOR*)p_byte )->x - mp_transform->GetPos()[X];\r\n\t\t\t\t\t\tfloat z = ((D3DVECTOR*)p_byte )->z - mp_transform->GetPos()[Z];\r\n\t\t\t\t\t\t((D3DVECTOR*)p_byte )->x = -z + mp_transform->GetPos()[X];\r\n\t\t\t\t\t\t((D3DVECTOR*)p_byte )->z = x + mp_transform->GetPos()[Z];\r\n\t\t\t\t\t\tp_byte += m_vertex_stride;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Adjust the bounding sphere information for this mesh.\r\n\t\t\t\t\tm_sphere_center.x\t-= mp_transform->GetPos()[X];\r\n\t\t\t\t\tm_sphere_center.z\t-= mp_transform->GetPos()[Z];\r\n\t\t\t\t\tfloat t\t\t\t\t= m_sphere_center.x;\r\n\t\t\t\t\tm_sphere_center.x\t= -m_sphere_center.z + mp_transform->GetPos()[X];\r\n\t\t\t\t\tm_sphere_center.z\t= t + mp_transform->GetPos()[Z];\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::SwapVertexBuffers( void )\r\n{\r\n\tif( m_num_vertex_buffers > 1 )\r\n\t{\r\n\t\tm_current_write_vertex_buffer = ( m_current_write_vertex_buffer + 1 ) % m_num_vertex_buffers;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::HandleColorOverride( void )\r\n{\r\n\tstatic float constants[16];\r\n\r\n\tDbg_Assert( m_flags & sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE );\r\n\r\n\t// Re-jig the pixel shader constants for the material color override.\r\n\tCopyMemory( constants, EngineGlobals.pixel_shader_constants, sizeof( float ) * 16 );\r\n\t\t\t\r\n\tfor( uint32 p = 0; p < mp_material->m_passes; ++p )\r\n\t{\r\n\t\tif( !( mp_material->m_flags[p] & MATFLAG_PASS_COLOR_LOCKED ))\r\n\t\t{\r\n//\t\t\tEngineGlobals.pixel_shader_constants[( p * 4 ) + 0]\t*= m_material_color_override[0];\r\n//\t\t\tEngineGlobals.pixel_shader_constants[( p * 4 ) + 1]\t*= m_material_color_override[1];\r\n//\t\t\tEngineGlobals.pixel_shader_constants[( p * 4 ) + 2]\t*= m_material_color_override[2];\r\n\t\t\tEngineGlobals.pixel_shader_constants[( p * 4 ) + 0]\t= m_material_color_override[0];\r\n\t\t\tEngineGlobals.pixel_shader_constants[( p * 4 ) + 1]\t= m_material_color_override[1];\r\n\t\t\tEngineGlobals.pixel_shader_constants[( p * 4 ) + 2]\t= m_material_color_override[2];\r\n\t\t}\r\n\t}\r\n\tEngineGlobals.upload_pixel_shader_constants = true;\r\n\r\n\t// Set the pixel shader (this will upload the new constants).\r\n\tset_pixel_shader( m_pixel_shader, mp_material->m_passes );\r\n\r\n\t// Restore the pixel shader constants and flag as needing a reload.\r\n\tCopyMemory( EngineGlobals.pixel_shader_constants, constants, sizeof( float ) * 16 );\r\n\tEngineGlobals.upload_pixel_shader_constants = true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::Submit( void )\r\n{\r\n\tDWORD\tstage_zero_minfilter;\r\n\tDWORD\tzwrite;\r\n\t\r\n\t// Pointless submitting a mesh with zero indices.\r\n\tif( m_num_indices == 0 )\r\n\t\treturn;\r\n\r\n\t// Deal with vertex color wibbling.\r\n\twibble_vc();\r\n\t\r\n\t// Set vertex shader.\r\n\tset_vertex_shader( m_vertex_shader[0] );\r\n\r\n\tif( m_flags & sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE )\r\n\t{\r\n\t\tHandleColorOverride();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Just set the pixel shader.\r\n\t\tset_pixel_shader( m_pixel_shader, mp_material->m_passes );\r\n\t}\r\n\r\n\t// Deal with meshes that set no anisotropic filtering.\r\n\tif( m_flags & MESH_FLAG_NO_ANISOTROPIC )\r\n\t{\r\n\t\tD3DDevice_GetTextureStageState( 0, D3DTSS_MINFILTER, &stage_zero_minfilter );\r\n\t\tif( stage_zero_minfilter != D3DTEXF_LINEAR )\r\n\t\t{\r\n\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Deal with meshes that set no z-write.\r\n\tif( m_flags & MESH_FLAG_NO_ZWRITE )\r\n\t{\r\n\t\tD3DDevice_GetRenderState( D3DRS_ZWRITEENABLE, &zwrite );\r\n\t\tif( zwrite == TRUE )\r\n\t\t{\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_ZWRITEENABLE, FALSE );\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Get the vertex buffer to submit (which is the one we have potentially just been writing to).\r\n\tIDirect3DVertexBuffer8*\tp_submit_buffer = mp_vertex_buffer[m_current_write_vertex_buffer];\r\n\t\r\n\t// Swap multiple vertex buffers if present.\r\n\tSwapVertexBuffers();\r\n\r\n\t// Set the stream source.\r\n\tD3DDevice_SetStreamSource( 0, p_submit_buffer, m_vertex_stride );\r\n\r\n\t// See if we have index LOD data, in which case we need to figure distance and select the correct LOD.\r\n\tif( mp_index_lod_data )\r\n\t{\r\n\t\t// Figure distance from this mesh to the camera. This is *not* an efficient way to do it.\r\n\t\tfrustum_check_sphere( &m_sphere_center, m_sphere_radius );\r\n\t\tfloat dist = get_bounding_sphere_nearest_z();\r\n\t\tfor( int idx = 0; idx < MAX_INDEX_BUFFERS; ++idx )\r\n\t\t{\r\n\t\t\tif( mp_index_buffer[idx] == NULL )\r\n\t\t\t{\r\n\t\t\t\t// We have got to the end of the set without drawing anything. Just use the last valid index set.\r\n\t\t\t\tif( idx > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t--idx;\r\n\t\t\t\t\tD3DDevice_DrawIndexedVertices( m_primitive_type, m_num_indices[idx], mp_index_buffer[idx] );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tif( dist < mp_index_lod_data[idx] )\r\n\t\t\t{\r\n\t\t\t\t// This is the index set we want.\r\n\t\t\t\tD3DDevice_DrawIndexedVertices( m_primitive_type, m_num_indices[idx], mp_index_buffer[idx] );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Submit.\r\n\t\tD3DDevice_DrawIndexedVertices( m_primitive_type, m_num_indices[0], mp_index_buffer[0] );\r\n\t}\r\n\r\n\t// Deal with meshes that set no anisotropic filtering.\r\n\tif( m_flags & MESH_FLAG_NO_ANISOTROPIC )\r\n\t{\r\n\t\tif( stage_zero_minfilter != D3DTEXF_LINEAR )\r\n\t\t{\r\n\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER, stage_zero_minfilter );\r\n\t\t}\r\n\t}\r\n\r\n\t// Deal with meshes that set no z-write.\r\n\tif( m_flags & MESH_FLAG_NO_ZWRITE )\r\n\t{\r\n\t\tif( zwrite == TRUE )\r\n\t\t{\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_ZWRITEENABLE, zwrite );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsMesh *sMesh::Clone( bool instance )\r\n{\r\n\tsMesh *p_clone = new sMesh();\r\n\r\n\t// Copy over basic details.\r\n\tCopyMemory( p_clone, this, sizeof( sMesh ));\r\n\t\r\n\tif( instance )\r\n\t{\r\n\t\tp_clone->m_flags |= MESH_FLAG_IS_INSTANCE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Build new vertex and index lists.\r\n\t\tp_clone->mp_vertex_buffer[0] = AllocateVertexBuffer( p_clone->m_vertex_stride * p_clone->m_num_vertices );\r\n\r\n\t\tBYTE *p_byte_src, *p_byte_dest;\r\n\t\tif( D3D_OK != mp_vertex_buffer[0]->Lock( 0, 0, &p_byte_src, D3DLOCK_READONLY ))\r\n\t\t{\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t\tif( D3D_OK != p_clone->mp_vertex_buffer[0]->Lock( 0, 0, &p_byte_dest, 0 ))\r\n\t\t{\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\r\n\t\t// Copy over vertex information.\r\n\t\tCopyMemory( p_byte_dest, p_byte_src, p_clone->m_vertex_stride * p_clone->m_num_vertices );\r\n\r\n\t\t// Create index buffer(s) and copy over index information.\r\n\t\tfor( int ib = 0; ib < MAX_INDEX_BUFFERS; ++ib )\r\n\t\t{\r\n\t\t\tif( p_clone->m_num_indices[ib] > 0 )\r\n\t\t\t{\r\n\t\t\t\tp_clone->mp_index_buffer[ib] = new uint16[p_clone->m_num_indices[ib]];\r\n\t\t\t\tCopyMemory( p_clone->mp_index_buffer[ib], mp_index_buffer[ib], sizeof( uint16 ) * p_clone->m_num_indices[ib] );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Handle duplicate vertex buffers if they exist.\r\n\t\tif( m_num_vertex_buffers > 1 )\r\n\t\t{\r\n\t\t\tp_clone->mp_vertex_buffer[1] = NULL;\r\n\t\t\tp_clone->CreateDuplicateVertexBuffers( m_num_vertex_buffers - 1 );\r\n\t\t}\r\n\t}\r\n\treturn p_clone;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nIDirect3DVertexBuffer8 *sMesh::AllocateVertexBuffer( uint32 size )\r\n{\r\n\tuint8\t\t\t\t\t*p_vb\t\t= new uint8[sizeof( IDirect3DVertexBuffer8 ) + size];\r\n\tIDirect3DVertexBuffer8\t*p_vb_ret\t= (IDirect3DVertexBuffer8*)p_vb;\r\n\t\r\n\tXGSetVertexBufferHeader( 0, 0, 0, 0, p_vb_ret, 0 );\r\n\tp_vb_ret->Register( p_vb + sizeof( IDirect3DVertexBuffer8 ));\r\n\r\n\treturn p_vb_ret;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::Crunch( void )\r\n{\r\n\tuint16 *p_indices = mp_index_buffer[0];\r\n\r\n\tuint32 i0 = p_indices[0];\r\n\tuint32 i1 = p_indices[1];\r\n\r\n\tuint32\tinvalid\t\t\t= 0;\r\n\tuint32\ttotal_invalid\t= 0;\r\n\tbool\tcrunch\t\t\t= false;\r\n\r\n\tfor( uint32 i = 2; i < m_num_indices[0]; ++i )\r\n\t{\r\n\t\tuint32 i2 = p_indices[i];\r\n\r\n\t\tif(( i0 == i1 ) || ( i0 == i2 ) || ( i1 == i2 ))\r\n\t\t{\r\n\t\t\t++invalid;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif( invalid > 5 )\r\n\t\t\t{\r\n\t\t\t\tif(( invalid & 1 ) == 0 )\r\n\t\t\t\t{\r\n//\t\t\t\t\tprintf( \"Crunching %d indices (even)\\n\", invalid - 4 );\r\n\r\n\t\t\t\t\t// Ensure the leading and trailing degenerate indices are correct.\r\n\t\t\t\t\tp_indices[i - 3]\t\t= p_indices[i - 2];\r\n\t\t\t\t\tp_indices[i - invalid]\t= p_indices[i - invalid - 1];\r\n\r\n\t\t\t\t\t// With an even number of invalid entries, the wind order won't change during crunch.\r\n\t\t\t\t\tMoveMemory( p_indices + i - invalid + 1, p_indices + i - 3, sizeof( uint16 ) * ( m_num_indices[0] - i + 3 ));\r\n\r\n\t\t\t\t\tm_num_indices[0]\t-= (uint16)( invalid - 4 );\r\n\t\t\t\t\ti\t\t\t\t\t-= invalid - 4;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n//\t\t\t\t\tprintf( \"Crunching %d indices (odd)\\n\", invalid - 5 );\r\n\r\n\t\t\t\t\t// Ensure the leading and trailing degenerate indices are correct.\r\n\t\t\t\t\tp_indices[i - 3]\t\t\t= p_indices[i - 2];\r\n\t\t\t\t\tp_indices[i - invalid]\t\t= p_indices[i - invalid - 1];\r\n\t\t\t\t\tp_indices[i - invalid + 1]\t= p_indices[i - invalid];\r\n\r\n\t\t\t\t\t// With an odd number of invalid entries, the wind order will change during crunch, so use one extra index.\r\n\t\t\t\t\tMoveMemory( p_indices + i - invalid + 2, p_indices + i - 3, sizeof( uint16 ) * ( m_num_indices[0] - i + 3 ));\r\n\t\t\t\t\tm_num_indices[0]\t-= (uint16)( invalid - 5 );\r\n\t\t\t\t\ti\t\t\t\t\t-= invalid - 5;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tinvalid = 0;\r\n\t\t}\r\n\t\t\r\n\t\ti0 = i1;\r\n\t\ti1 = i2;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::SetBillboardData( uint32 type, Mth::Vector & pivot_pos, Mth::Vector & pivot_axis )\r\n{\r\n\tDbg_Assert( mp_billboard_data == NULL );\r\n\r\n\t// Create the billboard data.\r\n\tmp_billboard_data\t\t\t\t\t= new sBillboardData;\r\n\r\n\t// Determine the billboard type.\r\n\tif( type == 1 )\r\n\t{\r\n\t\tmp_billboard_data->m_type = sBillboardData::vBILLBOARD_TYPE_SCREEN_ALIGNED;\r\n\t}\r\n\telse if( type == 2 )\r\n\t{\r\n\t\t// Axial aligned. See if this is y axis.\r\n\t\tif( fabsf( Mth::DotProduct( pivot_axis, Mth::Vector( 0.0f, 1.0f, 0.0f ))) > 0.99f )\r\n\t\t{\r\n\t\t\tmp_billboard_data->m_type = sBillboardData::vBILLBOARD_TYPE_Y_AXIS_ALIGNED;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_billboard_data->m_type = sBillboardData::vBILLBOARD_TYPE_ARBITRARY_AXIS_ALIGNED;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n\t\r\n\tmp_billboard_data->m_pivot_pos\t\t= pivot_pos;\r\n\tif( mp_billboard_data->m_type == sBillboardData::vBILLBOARD_TYPE_ARBITRARY_AXIS_ALIGNED )\r\n\t{\r\n\t\tmp_billboard_data->m_pivot_axis\t= pivot_axis;\r\n\t}\r\n\r\n\t// We need to go through at a low level and rebuild the vertex buffer. In all cases the\r\n\t// mesh won't have been exported with normals, which we use for billboards to store the\r\n\t// pivot-relative position, so we need to recalculate the vertex stride.\r\n\tDbg_Assert( m_normal_offset == 0 );\r\n\tDbg_Assert( m_diffuse_offset > 0 );\r\n\tDbg_Assert( m_uv0_offset > 0 );\r\n\tDbg_Assert( m_num_vertices == 4 );\r\n\tDbg_Assert( m_num_indices[0] == 4 );\r\n\r\n\t// Add size of normal to vertex size.\r\n\tint old_vertex_stride = m_vertex_stride;\r\n\tint new_vertex_stride = old_vertex_stride + ( sizeof( float ) * 3 );\r\n\r\n\tIDirect3DVertexBuffer8*\tp_old_buffer = mp_vertex_buffer[0];\r\n\tIDirect3DVertexBuffer8*\tp_new_buffer = AllocateVertexBuffer( new_vertex_stride * 4 );\r\n\r\n\t// Lock old buffer (read) and new buffer (write).\r\n\tBYTE *p_old_vb_data;\r\n\tBYTE *p_new_vb_data;\r\n\tp_old_buffer->Lock( 0, 0, &p_old_vb_data, D3DLOCK_READONLY | D3DLOCK_NOFLUSH );\r\n\tp_new_buffer->Lock( 0, 0, &p_new_vb_data, 0 );\r\n\r\n\t// Calculate the normal of the billboard, using the first tri.\r\n\tfloat\t\t*p_vert;\r\n\tuint16\t\tindices[4];\r\n\tindices[0]\t\t\t= mp_index_buffer[0][0];\r\n\tindices[1]\t\t\t= mp_index_buffer[0][1];\r\n\tindices[2]\t\t\t= mp_index_buffer[0][2];\r\n\tindices[3]\t\t\t= mp_index_buffer[0][3];\r\n\r\n\tp_vert\t\t\t\t= (float*)( p_old_vb_data + ( indices[0] * old_vertex_stride ));\r\n\tMth::Vector v0( p_vert[0], p_vert[1], p_vert[2] );\r\n\tp_vert\t\t\t\t= (float*)( p_old_vb_data + ( indices[1] * old_vertex_stride ));\r\n\tMth::Vector v1( p_vert[0], p_vert[1], p_vert[2] );\r\n\tp_vert\t\t\t\t= (float*)( p_old_vb_data + ( indices[2] * old_vertex_stride ));\r\n\tMth::Vector v2( p_vert[0], p_vert[1], p_vert[2] );\r\n\tMth::Vector\tnormal\t= Mth::CrossProduct(( v1 - v0 ), ( v2 - v0 )).Normalize();\r\n\r\n\t// Given the normal, calculate the local right and up (u and v) vectors, based on the billboard type.\r\n\tMth::Vector u, v;\r\n\r\n\tswitch( mp_billboard_data->m_type )\r\n\t{\r\n\t\tcase sBillboardData::vBILLBOARD_TYPE_SCREEN_ALIGNED:\r\n\t\tcase sBillboardData::vBILLBOARD_TYPE_Y_AXIS_ALIGNED:\r\n\t\tcase sBillboardData::vBILLBOARD_TYPE_WORLD_ORIENTED:\r\n\t\t{\r\n\t\t\t// Use the world 'up' vector to generate the 'u' vector.\r\n\t\t\tu = Mth::CrossProduct( normal, Mth::Vector( 0.0f, 1.0f, 0.0f )).Normalize();\r\n\r\n\t\t\t// Use the 'u' vector and the normal vector to generate the 'v' vector.\r\n\t\t\tv = Mth::CrossProduct( u, normal ).Normalize();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase sBillboardData::vBILLBOARD_TYPE_ARBITRARY_AXIS_ALIGNED:\r\n\t\t{\r\n\t\t\t// Use the pivot axis and the normal vector to generate the 'u' vector.\r\n\t\t\tu = Mth::CrossProduct( normal, pivot_axis ).Normalize();\r\n\r\n\t\t\t// Use the 'u' vector and the normal vector to generate the 'v' vector.\r\n\t\t\tv = Mth::CrossProduct( u, normal ).Normalize();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tfor( int i = 0; i < 4; ++i )\r\n\t{\r\n\t\t// The new position is actually the position of the pivot point for the billboard.\r\n\t\tfloat *p_pos_old\t= (float*)( p_old_vb_data + ( i * old_vertex_stride ));\r\n\t\tfloat *p_pos_new\t= (float*)( p_new_vb_data + ( i * new_vertex_stride ));\r\n\t\tp_pos_new[0]\t\t= pivot_pos[X];\r\n\t\tp_pos_new[1]\t\t= pivot_pos[Y];\r\n\t\tp_pos_new[2]\t\t= pivot_pos[Z];\r\n\r\n\t\t// Introduce normal (which is actually the position of the vertex relative to the pivot).\r\n\t\tMth::Vector pos_relative_to_pivot( p_pos_old[0] - pivot_pos[X], p_pos_old[1] - pivot_pos[Y], p_pos_old[2] - pivot_pos[Z] );\r\n\r\n\t\tp_pos_new[3]\t\t= Mth::DotProduct( pos_relative_to_pivot, u );\r\n\t\tp_pos_new[4]\t\t= Mth::DotProduct( pos_relative_to_pivot, v );\r\n\t\tp_pos_new[5]\t\t= Mth::DotProduct( pos_relative_to_pivot, normal );\r\n\r\n\t\t// Copy color.\r\n\t\tD3DCOLOR *p_col_old\t= (D3DCOLOR*)( p_old_vb_data + ( i * old_vertex_stride ) + m_diffuse_offset );\r\n\t\tD3DCOLOR *p_col_new\t= (D3DCOLOR*)( p_new_vb_data + ( i * new_vertex_stride ) + m_diffuse_offset + ( sizeof( float ) * 3 ));\r\n\t\tp_col_new[0]\t\t= p_col_old[0];\r\n\r\n\t\t// Copy uv0...\r\n\t\tfloat *p_uv0_old\t= (float*)( p_old_vb_data + ( i * old_vertex_stride ) + m_uv0_offset );\r\n\t\tfloat *p_uv0_new\t= (float*)( p_new_vb_data + ( i * new_vertex_stride ) + m_uv0_offset + ( sizeof( float ) * 3 ));\r\n\t\tp_uv0_new[0]\t\t= p_uv0_old[0];\r\n\t\tp_uv0_new[1]\t\t= p_uv0_old[1];\r\n\r\n\t\t// ...and additional uv's if present.\r\n\t\tif(( m_vertex_shader[0] & D3DFVF_TEXCOUNT_MASK ) > D3DFVF_TEX1 )\r\n\t\t{\r\n\t\t\tp_uv0_new[2]\t\t= p_uv0_old[2];\r\n\t\t\tp_uv0_new[3]\t\t= p_uv0_old[3];\r\n\t\t}\r\n\t\tif(( m_vertex_shader[0] & D3DFVF_TEXCOUNT_MASK ) > D3DFVF_TEX2 )\r\n\t\t{\r\n\t\t\tp_uv0_new[4]\t\t= p_uv0_old[4];\r\n\t\t\tp_uv0_new[5]\t\t= p_uv0_old[5];\r\n\t\t}\r\n\t\tif(( m_vertex_shader[0] & D3DFVF_TEXCOUNT_MASK ) > D3DFVF_TEX3 )\r\n\t\t{\r\n\t\t\tp_uv0_new[6]\t\t= p_uv0_old[6];\r\n\t\t\tp_uv0_new[7]\t\t= p_uv0_old[7];\r\n\t\t}\r\n\t}\r\n\r\n\t// Now fix up the mesh. Flag the mesh as being a billboard (stop the mesh being rendered by the regular pathway).\r\n\tm_flags |= sMesh::MESH_FLAG_BILLBOARD;\r\n\r\n\t// Switch vertex buffers, deleting the old one.\r\n\tmp_vertex_buffer[0]\t= p_new_buffer;\r\n\tdelete p_old_buffer;\r\n\r\n\t// Set the new vertex stride, diffuse and uv0 offset (and normal offset, just to be complete).\r\n\tm_vertex_stride\t\t= new_vertex_stride;\r\n\tm_diffuse_offset\t+= sizeof( float ) * 3;\r\n\tm_uv0_offset\t\t+= sizeof( float ) * 3;\r\n\tm_normal_offset\t\t= sizeof( float ) * 3;\r\n\r\n\t// Copy the new vertex buffer into existing buffered buffers if m_num_vertex_buffers > 1.\r\n\tif( m_num_vertex_buffers > 1 )\r\n\t{\r\n\t\tBYTE *p_buffer0;\r\n\t\tBYTE *p_bufferN;\r\n\t\tmp_vertex_buffer[0]->Lock( 0, 0, &p_buffer0, D3DLOCK_READONLY | D3DLOCK_NOFLUSH );\r\n\t\tfor( int vb = 1; vb < m_num_vertex_buffers; ++vb )\r\n\t\t{\r\n\t\t\tdelete mp_vertex_buffer[vb];\r\n\t\t\tmp_vertex_buffer[vb] = AllocateVertexBuffer( new_vertex_stride * 4 );\r\n\t\t\tmp_vertex_buffer[vb]->Lock( 0, 0, &p_bufferN, 0 );\r\n\t\t\tCopyMemory( p_bufferN, p_buffer0, new_vertex_stride * 4 );\r\n\t\t}\r\n\t}\r\n\r\n\t// Set the new vertex shader.\r\n\tm_vertex_shader[0]\t= 999;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::SetBoundingData( Mth::Vector & sphere_center, float radius, Mth::Vector & bb_min, Mth::Vector & bb_max )\r\n{\r\n//\tm_bbox.Set( bb_min, bb_max );\r\n\r\n\tm_sphere_center = D3DXVECTOR3( sphere_center[X], sphere_center[Y], sphere_center[Z] );\r\n\tm_sphere_radius = radius;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::Initialize( int\t\t\t\tnum_vertices,\r\n\t\t\t\t\t\tfloat\t\t\t*p_positions,\r\n\t\t\t\t\t\tfloat\t\t\t*p_normals,\r\n\t\t\t\t\t\tfloat\t\t\t*p_tex_coords,\r\n\t\t\t\t\t\tint\t\t\t\tnum_tc_sets,\r\n\t\t\t\t\t\tDWORD\t\t\t*p_colors,\r\n\t\t\t\t\t\tint\t\t\t\tnum_index_sets,\t\t\t// How many sets of indices there are (usually 1 set)\r\n\t\t\t\t\t\tint\t\t\t\t*p_num_indices,\t\t\t// Pointer to an array of ints containing number of indices per set\r\n\t\t\t\t\t\tuint16\t\t\t**pp_indices,\t\t\t// Pointer to an array of pointers to the actual indices\r\n\t\t\t\t\t\tunsigned long\tmaterial_checksum,\r\n\t\t\t\t\t\tvoid\t\t\t*p_scene,\r\n\t\t\t\t\t\tuint16\t\t\t*p_matrix_indices,\r\n\t\t\t\t\t\tuint32\t\t\t*p_weights,\r\n\t\t\t\t\t\tchar\t\t\t*p_vc_wibble_anims )\r\n{\r\n\t// First thing to do is grab the material pointer for this mesh.\r\n\tmp_material\t= ((sScene*)p_scene )->GetMaterial( material_checksum );\r\n\tif( mp_material == NULL )\r\n\t{\r\n\t\tDbg_Assert( 0 );\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif(( num_index_sets == 0 ) || ( p_num_indices[0] == 0 ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tuint16 min_index\t= ( pp_indices[0] )[0];\r\n\tuint16 max_index\t= ( pp_indices[0] )[0];\r\n\tfor( int i = 0; i < p_num_indices[0]; ++i )\r\n\t{\r\n\t\tif(( pp_indices[0] )[i] > max_index )\r\n\t\t{\r\n\t\t\tmax_index = ( pp_indices[0] )[i];\r\n\t\t}\r\n\t\telse if(( pp_indices[0] )[i] < min_index )\r\n\t\t{\r\n\t\t\tmin_index = ( pp_indices[0] )[i];\r\n\t\t}\r\n\t}\r\n\r\n\tif( max_index >= num_vertices )\r\n\t{\r\n\t\t// Error!\r\n\t\tDbg_Assert( 0 );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Grab top-down heap memory for the mesh workspace buffer. This will need to be as big as the maximum vertex indexed.\r\n\tint16 *p_mesh_workspace_array = new (Mem::Manager::sHandle().TopDownHeap()) int16[max_index + 1];\r\n\r\n\t// Setup workspace buffer.\r\n\tmemset( p_mesh_workspace_array, 1, sizeof( int16 ) * ( max_index + 1 ));\r\n\tfor( int i = 0; i < p_num_indices[0]; ++i )\r\n\t{\r\n\t\tp_mesh_workspace_array[( pp_indices[0] )[i]] = 0;\r\n\t}\r\n\t\r\n\t// Now figure the wasted space.\r\n\tint wasted_verts = 0;\r\n\tfor( int i = min_index; i <= max_index; ++i )\r\n\t{\r\n\t\tif( p_mesh_workspace_array[i] != 0 )\r\n\t\t\t++wasted_verts;\r\n\t}\r\n\r\n\t// Now figure the total number of vertices required for this mesh, to span the min->max indices.\r\n\tuint16 vertices_for_this_mesh\t= ( max_index - min_index + 1 ) - wasted_verts;\r\n\tm_num_vertices\t\t\t\t\t= vertices_for_this_mesh;\r\n\r\n\t// Create the index buffer(s). (Should be 16byte aligned for best performance).\r\n\tfor( int ib = 0; ib < num_index_sets; ++ib )\r\n\t{\r\n\t\tmp_index_buffer[ib]\t= new uint16[p_num_indices[ib]];\r\n\t\tm_num_indices[ib]\t= p_num_indices[ib];\r\n\t}\r\n\t\r\n\t// Use the material flags to figure the vertex format.\r\n\tint vertex_size\t\t\t= 3 * sizeof( float );\r\n\r\n\t// Include weights (for weighted animation) if present.\r\n\tuint32 biggest_index_used = 0;\r\n\tif( p_weights )\r\n\t{\r\n\t\tDbg_Assert( p_matrix_indices );\r\n\r\n\t\t// Calculate the biggest weight used.\r\n\t\tuint32*\tp_weight_read\t= p_weights + min_index;\r\n\t\tfor( int v = min_index; v <= max_index; ++v )\r\n\t\t{\r\n\t\t\tif( p_mesh_workspace_array[v] == 0 )\r\n\t\t\t{\r\n\t\t\t\t// This vertex is used.\r\n\t\t\t\tuint32 w2 = (( p_weight_read[0] >> 22 ) & 0x3FF );\r\n\t\t\t\tif( w2 > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tbiggest_index_used = 2;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 w1 = (( p_weight_read[0] >> 11 ) & 0x7FF );\r\n\t\t\t\t\tif( w1 > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbiggest_index_used = 1;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t++p_weight_read;\r\n\t\t}\r\n\t\tvertex_size\t+= sizeof( uint32 );\r\n\t}\r\n\r\n\t// Include indices (for weighted animation) if present.\r\n\tif( p_matrix_indices )\r\n\t{\r\n\t\tDbg_Assert( p_weights );\r\n\t\tvertex_size\t+= sizeof( uint16 ) * 4;\r\n\t}\r\n\t\r\n\t// Texture coordinates.\r\n\tuint32\ttex_coord_pass\t= 0;\r\n\tbool\tenv_mapped\t\t= false;\r\n\tif( p_tex_coords )\r\n\t{\r\n\t\tfor( uint32 pass = 0; pass < mp_material->m_passes; ++pass )\r\n\t\t{\r\n\t\t\tif( mp_material->m_flags[pass] & MATFLAG_ENVIRONMENT )\r\n\t\t\t{\r\n\t\t\t\tenv_mapped\t\t= true;\r\n\t\t\t}\r\n\r\n\t\t\t// Only need UV's for this stage if it is *not* environment mapped.\r\n\t\t\tif(( mp_material->mp_tex[pass] ) && ( !( mp_material->m_flags[pass] & MATFLAG_ENVIRONMENT )))\r\n\t\t\t{\r\n\t\t\t\t// Will need uv for this pass and all before it.\r\n\t\t\t\ttex_coord_pass\t= pass + 1; \r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor( uint32 pass = 0; pass < mp_material->m_passes; ++pass )\r\n\t\t{\r\n\t\t\tif( mp_material->m_flags[pass] & MATFLAG_ENVIRONMENT )\r\n\t\t\t{\r\n\t\t\t\tenv_mapped\t\t= true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif( tex_coord_pass > 0 )\r\n\t{\r\n\t\tvertex_size\t\t\t+= 2 * sizeof( float ) * tex_coord_pass;\r\n\t}\r\n\r\n\t// Assume no normals for now, unless weight information indicates an animating mesh.\r\n\tbool use_normals\t\t= false;\r\n\tbool use_packed_normals\t= false;\r\n\r\n\tif( p_normals || p_weights || env_mapped )\r\n\t{\r\n\t\t// Need to include normals. They will be packed differently for weighted meshes.\r\n\t\tuse_normals\t= true;\r\n\t\tif( p_weights )\r\n\t\t{\r\n\t\t\tuse_packed_normals = true;\r\n\t\t\tvertex_size\t+= sizeof( uint32 );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tvertex_size\t+= sizeof( float ) * 3;\r\n\t\t}\r\n\t}\r\n\r\n\tbool use_colors = false;\r\n\tif( p_colors )\r\n\t{\r\n\t\t// The raw vertex data does contain vertex colors.\r\n\t\tvertex_size\t+= sizeof( D3DCOLOR );\r\n\t\tuse_colors\t= true;\r\n\t}\r\n\r\n\r\n\t// Create the vertex buffer.\r\n\tm_vertex_stride\t= vertex_size;\r\n\r\n\t// One allocation for the header and the data buffer.\t\r\n\tmp_vertex_buffer[0] = AllocateVertexBuffer( vertex_size * vertices_for_this_mesh );\r\n\r\n\t// Lock the vertex buffer.\r\n\tBYTE* p_byte;\r\n\tif( D3D_OK != mp_vertex_buffer[0]->Lock(\t0,\t\t\t\t\t// Offset to lock.\r\n\t\t\t\t\t\t\t\t\t\t\t\t0,\t\t\t\t\t// Size to lock ( 0 means all).\r\n\t\t\t\t\t\t\t\t\t\t\t\t&p_byte,\t\t\t// Pointer to data.\r\n\t\t\t\t\t\t\t\t\t\t\t\tD3DLOCK_NOFLUSH ))\t// Flags.\r\n\t{\r\n\t\tDbg_Assert( 0 );\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// Copy in vertex position data (for vertices that are used).\r\n\tuint32\t\tbyte_write_offset\t= 0;\r\n\tfloat*\t\tp_read\t\t\t\t= p_positions + ( min_index * 3 );\r\n\tfloat*\t\tp_write\t\t\t\t= (float*)p_byte;\r\n\r\n\tfor( int v = min_index; v <= max_index; ++v )\r\n\t{\r\n\t\tif( p_mesh_workspace_array[v] == 0 )\r\n\t\t{\r\n\t\t\t// This vertex is used.\r\n\t\t\tp_write[0]\t= p_read[0];\r\n\t\t\tp_write[1]\t= p_read[1];\r\n\t\t\tp_write[2]\t= p_read[2];\r\n\t\t\tp_write\t= (float*)((char*)p_write + vertex_size );\r\n\t\t}\r\n\t\tp_read += 3;\r\n\t}\r\n\r\n\tbyte_write_offset\t+= sizeof( float ) * 3;\r\n\tm_vertex_shader[0]\t|= D3DFVF_XYZ;\r\n\r\n\t// Copy in vertex weight data.\r\n\tif( p_weights )\r\n\t{\r\n\t\tuint32*\tp_weight_read\t= p_weights + min_index;\r\n\t\tuint32*\tp_weight_write\t= (uint32*)((char*)p_byte + byte_write_offset );\r\n\r\n\t\tfor( int v = min_index; v <= max_index; ++v )\r\n\t\t{\r\n\t\t\tif( p_mesh_workspace_array[v] == 0 )\r\n\t\t\t{\r\n\t\t\t\t// This vertex is used.\r\n\t\t\t\tp_weight_write[0]\t= p_weight_read[0];\r\n\t\t\t\tp_weight_write\t\t= (uint32*)((char*)p_weight_write + vertex_size );\r\n\t\t\t}\r\n\t\t\t++p_weight_read;\r\n\t\t}\r\n\t\tbyte_write_offset += sizeof( uint32 );\r\n\r\n\t\t// No fvf flag setting, since it will be determined at the end.\r\n\t}\r\n\r\n\t// Copy in vertex matrix index data.\r\n\tif( p_matrix_indices )\r\n\t{\r\n\t\tuint16*\tp_index_read\t= p_matrix_indices + ( min_index * 4 );\r\n\t\tuint16*\tp_index_write\t= (uint16*)((char*)p_byte + byte_write_offset );\r\n\t\tfor( int v = min_index; v <= max_index; ++v )\r\n\t\t{\r\n\t\t\tif( p_mesh_workspace_array[v] == 0 )\r\n\t\t\t{\r\n\t\t\t\t// Have to multiply the indices by three to get the correct register offset, since there are 3 registers\r\n\t\t\t\t// per matrix.\r\n\t\t\t\tp_index_write[0]\t= p_index_read[0] * 3;\r\n\t\t\t\tp_index_write[1]\t= p_index_read[1] * 3;\r\n\t\t\t\tp_index_write[2]\t= p_index_read[2] * 3;\r\n\t\t\t\tp_index_write[3]\t= p_index_read[3] * 3;\r\n\t\t\t\tp_index_write\t\t= (uint16*)((char*)p_index_write + vertex_size );\r\n\t\t\t}\r\n\t\t\tp_index_read += 4;\r\n\t\t}\r\n\t\tbyte_write_offset += sizeof( uint16 ) * 4;\r\n\r\n\t\t// No fvf flag setting, since it will be determined at the end.\r\n\t}\r\n\r\n\t// Copy in normals data.\r\n\tif( use_normals )\r\n\t{\r\n\t\tm_normal_offset\t\t= (uint8)byte_write_offset;\r\n\t\tif( use_packed_normals )\r\n\t\t{\r\n\t\t\tfloat *p_read\t= p_normals + ( min_index * 3 );\r\n\t\t\tuint32 *p_write\t= (uint32*)((char*)p_byte + byte_write_offset );\r\n\t\t\tfor( int v = min_index; v <= max_index; ++v )\r\n\t\t\t{\r\n\t\t\t\tif( p_mesh_workspace_array[v] == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// The packed normal format is as follows:\r\n\t\t\t\t\t// 31                                             0\r\n\t\t\t\t\t// |----- 10 -----|----- 11 ------|----- 11 ------|\r\n\t\t\t\t\t// |       z      |       y       |       x       |\r\n\t\t\t\t\tuint32 snx\t= Ftoi_ASM( p_read[0] * 1023.0f );\r\n\t\t\t\t\tuint32 sny\t= Ftoi_ASM( p_read[1] * 1023.0f );\r\n\t\t\t\t\tuint32 snz\t= Ftoi_ASM( p_read[2] * 511.0f );\r\n\t\t\t\t\tp_write[0]\t= ( snx & 0x7FF ) | (( sny & 0x7FF ) << 11 ) | (( snz & 0x3FF ) << 22 );\r\n\t\t\t\t\tp_write\t\t= (uint32*)((char*)p_write + vertex_size );\r\n\t\t\t\t}\r\n\t\t\t\tp_read += 3;\r\n\t\t\t}\r\n\t\t\tbyte_write_offset += sizeof( uint32 );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfloat*\tp_read\t= p_normals + ( min_index * 3 );\r\n\t\t\tfloat*\tp_write\t= (float*)((char*)p_byte + byte_write_offset );\r\n\t\t\tfor( int v = min_index; v <= max_index; ++v )\r\n\t\t\t{\r\n\t\t\t\tif( p_mesh_workspace_array[v] == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_write[0]\t= p_read[0];\r\n\t\t\t\t\tp_write[1]\t= p_read[1];\r\n\t\t\t\t\tp_write[2]\t= p_read[2];\r\n\t\t\t\t\tp_write\t\t= (float*)((char*)p_write + vertex_size );\r\n\t\t\t\t}\r\n\t\t\t\tp_read += 3;\r\n\t\t\t}\r\n\t\t\tbyte_write_offset += sizeof( float ) * 3;\r\n\t\t}\r\n\t\tm_vertex_shader[0]\t|= D3DFVF_NORMAL;\r\n\t}\r\n\r\n\t// Copy in vertex color data.\r\n\tif( use_colors )\r\n\t{\r\n\t\tm_diffuse_offset\t= (uint8)byte_write_offset;\r\n\t\tDWORD*\tp_col_read\t= p_colors + min_index;\r\n\t\tDWORD*\tp_col_write\t= (DWORD*)((char*)p_byte + byte_write_offset );\r\n\t\tfor( int v = min_index; v <= max_index; ++v )\r\n\t\t{\r\n\t\t\tif( p_mesh_workspace_array[v] == 0 )\r\n\t\t\t{\r\n\t\t\t\tp_col_write[0]\t= p_col_read[0];\r\n\t\t\t\tp_col_write\t\t= (DWORD*)((char*)p_col_write + vertex_size );\r\n\t\t\t}\r\n\t\t\tp_col_read++;\r\n\t\t}\r\n\t\tbyte_write_offset += sizeof( DWORD );\r\n\t\tm_vertex_shader[0] |= D3DFVF_DIFFUSE;\r\n\t}\r\n\r\n\t// Copy in vertex texture coordinate data.\r\n\tif(( tex_coord_pass > 0 ) && ( p_tex_coords != NULL ))\r\n\t{\r\n\t\tm_uv0_offset\t\t\t\t\t\t= (uint8)byte_write_offset;\r\n\t\tp_read\t\t\t\t\t\t\t\t= p_tex_coords + ( min_index * 2 * num_tc_sets );\r\n\t\tp_write\t\t\t\t\t\t\t\t= (float*)((char*)p_byte + byte_write_offset );\r\n\t\tfor( int v = min_index; v <= max_index; ++v )\r\n\t\t{\r\n\t\t\tif( p_mesh_workspace_array[v] == 0 )\r\n\t\t\t{\r\n\t\t\t\tfor( uint32 pass = 0; pass < tex_coord_pass; ++pass )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_write[( pass * 2 ) + 0]\t= p_read[( pass * 2 ) + 0];\r\n\t\t\t\t\tp_write[( pass * 2 ) + 1]\t= p_read[( pass * 2 ) + 1];\r\n\t\t\t\t}\r\n\t\t\t\tp_write\t= (float*)((char*)p_write + vertex_size );\r\n\t\t\t}\r\n\t\t\tp_read = p_read + ( num_tc_sets * 2 );\r\n\t\t}\r\n\t\tbyte_write_offset\t+= sizeof( float ) * 2 * tex_coord_pass;\r\n\r\n\t\tswitch( tex_coord_pass )\r\n\t\t{\r\n\t\t\tcase 1:\r\n\t\t\t{\r\n\t\t\t\tm_vertex_shader[0]\t|= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2( 0 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase 2:\r\n\t\t\t{\r\n\t\t\t\tm_vertex_shader[0]\t|= D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE2( 0 ) | D3DFVF_TEXCOORDSIZE2( 1 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase 3:\r\n\t\t\t{\r\n\t\t\t\tm_vertex_shader[0]\t|= D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE2( 0 ) | D3DFVF_TEXCOORDSIZE2( 1 ) | D3DFVF_TEXCOORDSIZE2( 2 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase 4:\r\n\t\t\t{\r\n\t\t\t\tm_vertex_shader[0]\t|= D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE2( 0 ) | D3DFVF_TEXCOORDSIZE2( 1 ) | D3DFVF_TEXCOORDSIZE2( 2 ) | D3DFVF_TEXCOORDSIZE2( 3 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"Bad number of passes\" ));\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Create the vertex color wibble array if data is present.\r\n\tif( p_vc_wibble_anims )\r\n\t{\r\n\t\tmp_vc_wibble_data\t\t\t= new char[m_num_vertices];\r\n\t\tint vc_wibble_data_offset\t= 0;\r\n\r\n\t\tfor( int v = min_index; v <= max_index; ++v )\r\n\t\t{\r\n\t\t\tif( p_mesh_workspace_array[v] == 0 )\r\n\t\t\t{\r\n\t\t\t\tmp_vc_wibble_data[vc_wibble_data_offset++] = p_vc_wibble_anims[v];\r\n\t\t\t}\r\n\t\t}\r\n\t\t// Double buffer the vertex buffer.\r\n\t\tCreateDuplicateVertexBuffers( 1 );\r\n\t}\r\n\r\n\t// Process the workspace array.\r\n\tint offset = 0;\r\n\tfor( int v = 0; v <= max_index; ++v )\r\n\t{\r\n\t\tif( p_mesh_workspace_array[v] == 0 )\r\n\t\t{\r\n\t\t\t// This vertex is used.\r\n\t\t\tp_mesh_workspace_array[v] = offset;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// This vertex is not used. Update the offset for the next used vertex.\r\n\t\t\t--offset;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Copy in index data, normalising the indices for this vertex buffer (i.e. so the lowest index will reference\r\n\t// vertex 0 in the buffer built specifically for this mesh).\r\n\tfor( int ib = 0; ib < num_index_sets; ++ib )\r\n\t{\r\n\t\tfor( int i = 0; i < p_num_indices[ib]; ++i )\r\n\t\t{\r\n\t\t\tuint16 idx\t\t\t\t= ( pp_indices[ib] )[i];\r\n\t\t\tmp_index_buffer[ib][i]\t= idx + p_mesh_workspace_array[idx];\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Can now remove the mesh workspace array.\r\n\tdelete [] p_mesh_workspace_array;\r\n\t\r\n\t// Set the correct vertex shader if a weighted mesh.\r\n\t// The number of indices used will be one more than the biggest index used (given 0 base).\r\n\tif( p_weights )\r\n\t{\r\n\t\tm_vertex_shader[0] = GetVertexShader( use_colors, ( mp_material->m_flags[0] & MATFLAG_SPECULAR ) ? true : false, biggest_index_used + 1 );\r\n\t}\r\n\r\n\t// Set the pixel shader regardless.\r\n\tGetPixelShader( mp_material, &m_pixel_shader );\r\n\r\n\tif( num_index_sets > 1 )\r\n\t{\r\n\t\tmp_index_lod_data = new float[num_index_sets];\r\n\t\tfor( int d = 0; d < num_index_sets; ++d )\r\n\t\t{\r\n\t\t\tfloat dist\t\t\t\t= ( 15.0f + ( d * 10.0f )) * 12.0f;\r\n\t\t\tmp_index_lod_data[d]\t= dist;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sMesh::DrawBoundingSphere( void )\r\n{\r\n#\tifdef __NOPT_ASSERT__\r\n\tconst uint32 NUM_SPHERE_POINTS\t= 64;\r\n\r\n\tstatic uint32 sphere_buffer[NUM_SPHERE_POINTS * 4];\r\n\r\n\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\tMth::Vector up( 0.0f, 1.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\tscreen_right.Normalize();\r\n\tscreen_up.Normalize();\r\n\r\n\tset_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\tset_pixel_shader( PixelShader5 );\r\n\r\n\tint\t\tindex\t\t= 0;\r\n\tfloat\tangle\t\t= 0.0f;\r\n\tfloat\tangle_step\t= ( Mth::PI * 2.0f ) / (float)NUM_SPHERE_POINTS;\r\n\r\n\t// Draw the screen aligned sphere.\r\n\tfor( uint32 i = 0; i < NUM_SPHERE_POINTS; ++i, angle += angle_step )\r\n\t{\r\n\t\tfloat x = m_sphere_center.x + ( m_sphere_radius * cosf( angle ) * screen_right[X] ) + ( m_sphere_radius * sinf( angle ) * screen_up[X] );\r\n\t\tfloat y = m_sphere_center.y + ( m_sphere_radius * cosf( angle ) * screen_right[Y] ) + ( m_sphere_radius * sinf( angle ) * screen_up[Y] );\r\n\t\tfloat z = m_sphere_center.z + ( m_sphere_radius * cosf( angle ) * screen_right[Z] ) + ( m_sphere_radius * sinf( angle ) * screen_up[Z] );\r\n\r\n\t\tsphere_buffer[index++]\t= *((uint32*)&x );\r\n\t\tsphere_buffer[index++]\t= *((uint32*)&y );\r\n\t\tsphere_buffer[index++]\t= *((uint32*)&z );\r\n\t\tsphere_buffer[index++]\t= 0x80800000;\r\n\t}\r\n\tD3DDevice_DrawVerticesUP( D3DPT_LINELOOP, NUM_SPHERE_POINTS, sphere_buffer, sizeof( uint32 ) * 4 );\r\n\r\n\t// Draw the xz plane sphere.\r\n\tindex\t\t= 0;\r\n\tangle\t\t= 0.0f;\r\n\tfor( uint32 i = 0; i < NUM_SPHERE_POINTS; ++i, angle += angle_step )\r\n\t{\r\n\t\tfloat x = m_sphere_center.x + ( m_sphere_radius * cosf( angle ));\r\n\t\tfloat y = m_sphere_center.y;\r\n\t\tfloat z = m_sphere_center.z + ( m_sphere_radius * sinf( angle ));\r\n\r\n\t\tsphere_buffer[index++]\t= *((uint32*)&x );\r\n\t\tsphere_buffer[index++]\t= *((uint32*)&y );\r\n\t\tsphere_buffer[index++]\t= *((uint32*)&z );\r\n\t\tsphere_buffer[index++]\t= 0x80800000;\r\n\t}\r\n\tD3DDevice_DrawVerticesUP( D3DPT_LINELOOP, NUM_SPHERE_POINTS, sphere_buffer, sizeof( uint32 ) * 4 );\r\n#\tendif\r\n}\r\n\r\n\r\n\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/mesh.h",
    "content": "#ifndef __MESH_H\r\n#define __MESH_H\r\n\r\n#include <core\\math.h>\r\n#include <core\\math\\geometry.h>\r\n#include <gfx\\nx.h>\r\n#include \"material.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\nstruct sCASData\r\n{\r\n\tuint32\tmask;\r\n\tuint32\tdata0;\r\n\tuint32\tdata1;\r\n\tuint32\tstart_index;\r\n};\r\n\t\r\n\r\n\r\nstruct sBillboardData\r\n{\r\n\tenum EBillboardType\r\n\t{\r\n\t\tvBILLBOARD_TYPE_SCREEN_ALIGNED\t\t\t= 0,\r\n\t\tvBILLBOARD_TYPE_Y_AXIS_ALIGNED\t\t\t= 1,\t\t// Specialised case of arbitrary axial alignment.\r\n\t\tvBILLBOARD_TYPE_ARBITRARY_AXIS_ALIGNED\t= 2,\r\n\t\tvBILLBOARD_TYPE_WORLD_ORIENTED\t\t\t= 3\r\n\t};\r\n\t\r\n\tEBillboardType\tm_type;\r\n\tMth::Vector\t\tm_pivot_pos;\r\n\tMth::Vector\t\tm_pivot_axis;\t\t\t\t\t\t\t// Normalised axis of rotation, valid only for type ARBITRARY_AXIS_ALIGNED.\r\n};\r\n\r\n\r\n\r\nstruct sMesh\r\n{\r\npublic:\r\n\r\n\tstatic const uint32\tVERTEX_SHADER_STACK_SIZE\t= 2;\r\n\tstatic const uint32\tMAX_VERTEX_BUFFERS\t\t\t= 3;\r\n\tstatic const uint32\tMAX_INDEX_BUFFERS\t\t\t= 8;\t\t// Multiple index buffers are used for triangle-decimated LOD's.\r\n\t\r\n\tenum EMeshFlags\r\n\t{\r\n\t\tMESH_FLAG_IS_INSTANCE\t\t\t\t= 0x01,\r\n\t\tMESH_FLAG_NO_SKATER_SHADOW\t\t\t= 0x02,\r\n\t\tMESH_FLAG_MATERIAL_COLOR_OVERRIDE\t= 0x04,\r\n\t\tMESH_FLAG_VERTEX_COLOR_WIBBLE\t\t= 0x08,\r\n\t\tMESH_FLAG_BILLBOARD\t\t\t\t\t= 0x10,\t\t// This mesh is a billboard.\r\n\t\tMESH_FLAG_HAS_TRANSFORM\t\t\t\t= 0x20,\r\n\t\tMESH_FLAG_ACTIVE\t\t\t\t\t= 0x40,\r\n\t\tMESH_FLAG_NO_ANISOTROPIC\t\t\t= 0x80,\t\t// No texture 0 anisotropic filtering for this mesh.\r\n\t\tMESH_FLAG_NO_ZWRITE\t\t\t\t\t= 0x100,\t// No zwrite for this mesh.\r\n\t\tMESH_FLAG_SHADOW_VOLUME\t\t\t\t= 0x200,\t// This mesh represents a single shadow volume.\r\n\t\tMESH_FLAG_BUMPED_WATER\t\t\t\t= 0x400,\r\n\t\tMESH_FLAG_UNLIT\t\t\t\t\t\t= 0x20000\t// This corresponds to the material unlit flag during the scene conversion process.\r\n\t};\r\n\r\n\t\t\t\t\tsMesh( void );\r\n\t\t\t\t\t~sMesh( void );\r\n\r\n\t// Functions\r\n\tvoid\t\t\twibble_vc( void );\r\n\tvoid\t\t\twibble_normals( void );\r\n\tuint32\t\t\tGetChecksum()\tconst\t\t\t{ return Checksum; }\r\n\tuint32\t\t\tGetFlags()\t\tconst\t\t\t{ return m_flags; }\r\n\tvoid\t\t\tSetActive( bool active )\t\t{ if( active ) m_flags |= MESH_FLAG_ACTIVE; else m_flags &= ~MESH_FLAG_ACTIVE; }\r\n\tvoid\t\t\tSetVisibility( uint8 mask )\t\t{ m_visibility_mask\t= mask; }\r\n\tvoid\t\t\tSetPosition( Mth::Vector &pos );\r\n\tvoid\t\t\tGetPosition( Mth::Vector *p_pos );\r\n\tvoid\t\t\tSetYRotation( Mth::ERot90 rot );\r\n\tsMesh\t\t\t*Clone( bool instance = false );\r\n\tvoid\t\t\tSetBoneIndex( int8 idx )\t\t{ m_bone_index = idx; }\r\n\tint8\t\t\tGetBoneIndex( void )\t\t\t{ return m_bone_index; }\r\n\tvoid\t\t\tSetBillboardData( uint32 type, Mth::Vector & pivot_pos, Mth::Vector & pivot_axis );\r\n\tvoid\t\t\tSetBoundingData( Mth::Vector & sphere_center, float radius, Mth::Vector & bb_min, Mth::Vector & bb_max );\r\n\r\n\t// Grabs memory chunk and builds vertex buffer from heap memory, rather than getting DX to do it.\r\n\tstatic IDirect3DVertexBuffer8\t*AllocateVertexBuffer( uint32 size );\r\n\r\n\t// All-purpose mesh instancing code, used for static geometry and animating weighted meshes.\r\n\tvoid\t\t\tInitialize( int\t\t\t\tnum_vertices,\r\n\t\t\t\t\t\t\t\tfloat\t\t\t*p_positions,\r\n\t\t\t\t\t\t\t\tfloat\t\t\t*p_normals,\r\n\t\t\t\t\t\t\t\tfloat\t\t\t*p_tex_coords,\r\n\t\t\t\t\t\t\t\tint\t\t\t\tnum_tc_sets,\r\n\t\t\t\t\t\t\t\tDWORD\t\t\t*p_colors,\r\n\t\t\t\t\t\t\t\tint\t\t\t\tnum_index_sets,\t\t\t// How many sets of indices there are (usually 1 set)\r\n\t\t\t\t\t\t\t\tint\t\t\t\t*p_num_indices,\t\t\t// Pointer to an array of ints containing number of indices per set\r\n\t\t\t\t\t\t\t\tuint16\t\t\t**pp_indices,\t\t\t// Pointer to an array of pointers to the actual indices\r\n\t\t\t\t\t\t\t\tunsigned long\tmaterial_checksum,\r\n\t\t\t\t\t\t\t\tvoid\t\t\t*p_scene,\r\n\t\t\t\t\t\t\t\tuint16\t\t\t*p_matrix_indices\t= NULL,\r\n\t\t\t\t\t\t\t\tuint32\t\t\t*p_weights\t\t\t= NULL,\r\n\t\t\t\t\t\t\t\tchar\t\t\t*p_vc_wibble_anims\t= NULL );\r\n\r\n\tvoid\t\t\tSubmit( void );\r\n\tvoid\t\t\tHandleColorOverride( void );\r\n\tvoid\t\t\tCreateDuplicateVertexBuffers( int n );\r\n\tvoid\t\t\tSwapVertexBuffers( void );\r\n\tvoid\t\t\tPushVertexShader( uint32 shader_id );\r\n\tvoid\t\t\tPopVertexShader( void );\r\n\tvoid\t\t\tCrunch( void );\r\n\r\n\t// Debug functions, will be empty stub for Final build.\r\n\tvoid\t\t\tDrawBoundingSphere( void );\r\n\r\n\t// Members. Order is important here since details required for fast mesh rejection need to be in top 32 bytes of structure.\r\n\tuint32\t\t\t\t\tm_flags;\r\n\tD3DXVECTOR3\t\t\t\tm_sphere_center;\r\n\tfloat\t\t\t\t\tm_sphere_radius;\r\n\tsMaterial\t\t\t\t*mp_material;\r\n\r\n\tuint8\t\t\t\t\tm_vertex_stride;\r\n\tuint8\t\t\t\t\tm_current_write_vertex_buffer;\r\n\tuint8\t\t\t\t\tm_num_vertex_buffers;\r\n\tuint8\t\t\t\t\tm_visibility_mask;\r\n\tuint8\t\t\t\t\tm_diffuse_offset;\t\t// Offset into vertex format for diffuse color component.\r\n\tuint8\t\t\t\t\tm_normal_offset;\t\t// Offset into vertex format for normal component.\r\n\tuint8\t\t\t\t\tm_uv0_offset;\t\t\t// Offset into vertex format for uv0 component.\r\n\tint8\t\t\t\t\tm_bone_index;\r\n\r\n\tuint16\t\t\t\t\tm_load_order;\r\n\tuint16\t\t\t\t\tm_num_vertices;\r\n\tuint16\t\t\t\t\tm_num_indices[MAX_INDEX_BUFFERS];\r\n\r\n\tuint32\t\t\t\t\tChecksum;\r\n\tuint32\t\t\t\t\tm_vertex_shader[VERTEX_SHADER_STACK_SIZE];\r\n\tuint32\t\t\t\t\tm_pixel_shader;\r\n\r\n\tfloat\t\t\t\t\t*mp_index_lod_data;\t\t\t\t// List of distances (squared) for which a particular index list should be used.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// NULL for meshes that only have one set of index data.\r\n\r\n\tsBillboardData\t\t\t*mp_billboard_data;\t\t\t\t// Data defining billboard properties. NULL for non-billboard meshes.\r\n\r\n\tD3DPRIMITIVETYPE\t\tm_primitive_type;\r\n\tuint16\t\t\t\t\t*mp_index_buffer[MAX_INDEX_BUFFERS];\r\n\tIDirect3DVertexBuffer8*\tmp_vertex_buffer[MAX_VERTEX_BUFFERS];\r\n\r\n\tfloat\t\t\t\t\tm_bounding_sphere_nearest_z;\t// Used for dynamic sorting during front-back block sorting.\r\n\tfloat\t\t\t\t\tm_material_color_override[3];\r\n\tchar\t\t\t\t\t*mp_vc_wibble_data;\r\n\tMth::Matrix\t\t\t\t*mp_transform;\r\n};\r\n\r\n\r\nvoid SetMeshScalingParameters( Nx::SMeshScalingParameters* pParams );\r\nvoid DisableMeshScaling( void );\r\nvoid ApplyMeshScaling( float* p_vertices, int num_verts );\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n#endif // __MESH_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/mipmap.inl",
    "content": "// Xbox Shader Assembler 1.00.4705.1\r\nD3DPIXELSHADERDEF psd;\r\nZeroMemory(&psd, sizeof(psd));\r\npsd.PSCombinerCount=PS_COMBINERCOUNT(\r\n    8,\r\n    PS_COMBINERCOUNT_MUX_MSB | PS_COMBINERCOUNT_UNIQUE_C0 | PS_COMBINERCOUNT_UNIQUE_C1);\r\npsd.PSTextureModes=PS_TEXTUREMODES(\r\n    PS_TEXTUREMODES_PROJECT2D,\r\n    PS_TEXTUREMODES_PROJECT2D,\r\n    PS_TEXTUREMODES_PROJECT2D,\r\n    PS_TEXTUREMODES_PROJECT2D);\r\npsd.PSInputTexture=PS_INPUTTEXTURE(0,0,0,0);\r\npsd.PSDotMapping=PS_DOTMAPPING(\r\n    0,\r\n    PS_DOTMAPPING_ZERO_TO_ONE,\r\n    PS_DOTMAPPING_ZERO_TO_ONE,\r\n    PS_DOTMAPPING_ZERO_TO_ONE);\r\npsd.PSCompareMode=PS_COMPAREMODE(\r\n    PS_COMPAREMODE_S_LT | PS_COMPAREMODE_T_LT | PS_COMPAREMODE_R_LT | PS_COMPAREMODE_Q_LT,\r\n    PS_COMPAREMODE_S_LT | PS_COMPAREMODE_T_LT | PS_COMPAREMODE_R_LT | PS_COMPAREMODE_Q_LT,\r\n    PS_COMPAREMODE_S_LT | PS_COMPAREMODE_T_LT | PS_COMPAREMODE_R_LT | PS_COMPAREMODE_Q_LT,\r\n    PS_COMPAREMODE_S_LT | PS_COMPAREMODE_T_LT | PS_COMPAREMODE_R_LT | PS_COMPAREMODE_Q_LT);\r\n\r\n//------------- Stage 0 -------------\r\npsd.PSRGBInputs[0]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_RGB | PS_INPUTMAPPING_UNSIGNED_IDENTITY,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_RGB | PS_INPUTMAPPING_UNSIGNED_IDENTITY);\r\npsd.PSAlphaInputs[0]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_UNSIGNED_IDENTITY,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_UNSIGNED_IDENTITY);\r\npsd.PSRGBOutputs[0]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_R0,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSAlphaOutputs[0]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_R0,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSConstant0[0] = 0x40404040;\r\npsd.PSConstant1[0] = 0x00000000;\r\n\r\n//------------- Stage 1 -------------\r\npsd.PSRGBInputs[1]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T1 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_RGB | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSAlphaInputs[1]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T1 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSRGBOutputs[1]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSAlphaOutputs[1]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSConstant0[1] = 0x40404040;\r\npsd.PSConstant1[1] = 0x00000000;\r\n\r\n//------------- Stage 2 -------------\r\npsd.PSRGBInputs[2]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T2 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_RGB | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSAlphaInputs[2]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T2 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSRGBOutputs[2]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSAlphaOutputs[2]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSConstant0[2] = 0x40404040;\r\npsd.PSConstant1[2] = 0x00000000;\r\n\r\n//------------- Stage 3 -------------\r\npsd.PSRGBInputs[3]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T3 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_RGB | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSAlphaInputs[3]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T3 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSRGBOutputs[3]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSAlphaOutputs[3]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSConstant0[3] = 0x40404040;\r\npsd.PSConstant1[3] = 0x00000000;\r\n\r\n//------------- Stage 4 -------------\r\npsd.PSRGBInputs[4]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_NEGATE,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_RGB | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSAlphaInputs[4]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_NEGATE,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSRGBOutputs[4]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSAlphaOutputs[4]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSConstant0[4] = 0x00000000;\r\npsd.PSConstant1[4] = 0x00000000;\r\n\r\n//------------- Stage 5 -------------\r\npsd.PSRGBInputs[5]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T1 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_NEGATE,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_RGB | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSAlphaInputs[5]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T1 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_NEGATE,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSRGBOutputs[5]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSAlphaOutputs[5]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSConstant0[5] = 0x00000000;\r\npsd.PSConstant1[5] = 0x00000000;\r\n\r\n//------------- Stage 6 -------------\r\npsd.PSRGBInputs[6]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T2 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_NEGATE,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_RGB | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSAlphaInputs[6]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T2 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_NEGATE,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSRGBOutputs[6]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSAlphaOutputs[6]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSConstant0[6] = 0x00000000;\r\npsd.PSConstant1[6] = 0x00000000;\r\n\r\n//------------- Stage 7 -------------\r\npsd.PSRGBInputs[7]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T3 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_NEGATE,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_RGB | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_RGB | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSAlphaInputs[7]=PS_COMBINERINPUTS(\r\n    PS_REGISTER_T3 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n    PS_REGISTER_C0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_NEGATE,\r\n    PS_REGISTER_ZERO | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_UNSIGNED_INVERT,\r\n    PS_REGISTER_R0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY);\r\npsd.PSRGBOutputs[7]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSAlphaOutputs[7]=PS_COMBINEROUTPUTS(\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_DISCARD,\r\n    PS_REGISTER_R0,\r\n    PS_COMBINEROUTPUT_IDENTITY | PS_COMBINEROUTPUT_AB_MULTIPLY | PS_COMBINEROUTPUT_CD_MULTIPLY | PS_COMBINEROUTPUT_AB_CD_SUM);\r\npsd.PSConstant0[7] = 0x00000000;\r\npsd.PSConstant1[7] = 0x00000000;\r\n\r\npsd.PSC0Mapping = 0x76543210;\r\npsd.PSC1Mapping = 0xffffffff;\r\npsd.PSFinalCombinerConstants = 0x000001ff;\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/nx_init.cpp",
    "content": "#include <xtl.h>\r\n\r\n// Include the following two files for detailed timing data collection.\r\n//#include <xbdm.h>\r\n//#include <d3d8perf.h>\r\n\r\n#include \"sys/config/config.h\"\r\n#include \"nx_init.h\"\r\n#include \"anim.h\"\r\n#include \"chars.h\"\r\n#include \"scene.h\"\r\n#include \"render.h\"\r\n#include \"instance.h\"\r\n#include \"gamma.h\"\r\n#include \"grass.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\nsEngineGlobals\tEngineGlobals;\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid InitialiseRenderstates( void )\r\n{\r\n\tD3DDevice_SetRenderState( D3DRS_LOCALVIEWER,\t\tFALSE );\r\n\r\n\tD3DDevice_SetRenderState( D3DRS_COLORVERTEX,\t\tFALSE );\r\n\r\n\tEngineGlobals.lighting_enabled\t\t= false;\r\n\tD3DDevice_SetRenderState( D3DRS_LIGHTING,\t\t\tFALSE );\r\n\r\n\tEngineGlobals.specular_enabled\t\t= 0;\r\n\tD3DDevice_SetRenderState( D3DRS_SPECULARENABLE,\t\tFALSE );\r\n\t\r\n\tEngineGlobals.cull_mode\t\t\t\t= D3DCULL_CW;\r\n\tD3DDevice_SetRenderState( D3DRS_CULLMODE,\t\t\tD3DCULL_CW );\r\n\r\n\tEngineGlobals.allow_envmapping\t\t= true;\r\n\r\n\tEngineGlobals.dither_enable\t\t\t= TRUE;\r\n\tD3DDevice_SetRenderState( D3DRS_DITHERENABLE,\t\tTRUE );\r\n\r\n\tEngineGlobals.z_test_enabled\t\t= TRUE;\r\n\tD3DDevice_SetRenderState( D3DRS_ZFUNC,\t\t\t\tD3DCMP_LESSEQUAL );\r\n\r\n\tEngineGlobals.z_write_enabled\t\t= TRUE;\r\n\tD3DDevice_SetRenderState( D3DRS_ZWRITEENABLE,\t\tTRUE );\r\n\t\r\n\tEngineGlobals.alpha_blend_enable\t= 1;\r\n\tD3DDevice_SetRenderState( D3DRS_ALPHABLENDENABLE,\tTRUE );\r\n\r\n\tEngineGlobals.alpha_test_enable\t\t= 1;\r\n\tD3DDevice_SetRenderState( D3DRS_ALPHATESTENABLE,\tTRUE );\r\n\r\n\tD3DDevice_SetRenderState( D3DRS_ALPHAFUNC,\t\t\tD3DCMP_GREATEREQUAL );\r\n\r\n\tEngineGlobals.alpha_ref\t\t\t\t= 0;\r\n\tD3DDevice_SetRenderState( D3DRS_ALPHAREF,\t\t\t0x00 );\r\n\r\n\tfor( int stage = 0; stage < 4; ++stage )\r\n\t{\r\n\t\tEngineGlobals.uv_addressing[stage]\t\t= 0x00000000UL;\r\n\t\tEngineGlobals.mip_map_lod_bias[stage]\t= 0x00000000UL;\r\n\t\tEngineGlobals.p_texture[stage]\t\t\t= NULL;\r\n\t\tEngineGlobals.min_mag_filter[stage]\t\t= 0x00010000UL;\r\n\t\tEngineGlobals.color_sign[stage]\t\t\t= 0x00000000UL;\r\n\r\n\t\tD3DDevice_SetTextureStageState( stage, D3DTSS_MAGFILTER,\t\tD3DTEXF_LINEAR );\r\n\t\tD3DDevice_SetTextureStageState( stage, D3DTSS_MIPFILTER,\t\tD3DTEXF_LINEAR );\r\n\r\n\t\tif( stage == 0 )\r\n\t\t{\r\n\t\t\t// If we are running in 720p or 1080i mode, need max pixel pushing power - avoid anisotropic filtering.\r\n\t\t\t// MSM PERFCHANGE\r\n\t\t\tif( EngineGlobals.backbuffer_height > 480 )\r\n\t\t\t{\r\n\t\t\t\tD3DDevice_SetTextureStageState( stage, D3DTSS_MINFILTER,\t\tD3DTEXF_LINEAR );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tD3DDevice_SetTextureStageState( stage, D3DTSS_MINFILTER,\t\tD3DTEXF_ANISOTROPIC );\r\n\t\t\t\tD3DDevice_SetTextureStageState( stage, D3DTSS_MAXANISOTROPY, 3 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tD3DDevice_SetTextureStageState( stage, D3DTSS_MINFILTER,\t\tD3DTEXF_LINEAR );\r\n\t\t}\r\n\t\tD3DDevice_SetTextureStageState( stage, D3DTSS_ADDRESSU,\t\t\tD3DTADDRESS_WRAP );\r\n\t\tD3DDevice_SetTextureStageState( stage, D3DTSS_ADDRESSV,\t\t\tD3DTADDRESS_WRAP );\r\n\t}\r\n\r\n\t// Set up material for specular properties for fixed function pipeline.\r\n\tD3DMATERIAL8\ttest_mat;\r\n\tZeroMemory( &test_mat, sizeof( D3DMATERIAL8 ));\r\n\tD3DDevice_SetMaterial( &test_mat );\r\n\r\n\tD3DDevice_SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE,\tD3DMCS_COLOR1 );\r\n    D3DDevice_SetRenderState( D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL );\r\n    D3DDevice_SetRenderState( D3DRS_AMBIENTMATERIALSOURCE,\tD3DMCS_COLOR1 );\r\n    D3DDevice_SetRenderState( D3DRS_EMISSIVEMATERIALSOURCE,\tD3DMCS_MATERIAL );\r\n\r\n\t// Set these up so they will get reset first time through.\r\n\tEngineGlobals.blend_mode_value\t\t\t= 0xDEADBABE;\r\n\tEngineGlobals.blend_op\t\t\t\t\t= 0xDEADBABE;\r\n\tEngineGlobals.src_blend\t\t\t\t\t= 0xDEADBABE;\r\n\tEngineGlobals.dest_blend\t\t\t\t= 0xDEADBABE;\r\n\r\n\tEngineGlobals.screenshot_name[0]\t\t= 0;\r\n\t\r\n\t// Build the required vertex shaders.\r\n\tCreateWeightedMeshVertexShaders();\r\n\r\n\t// Build required pixel shaders.\r\n\tcreate_pixel_shaders();\r\n\r\n\t// Set pixel shader constants.\r\n\tEngineGlobals.pixel_shader_constants[16]\t= 0.0f;\r\n\tEngineGlobals.pixel_shader_constants[17]\t= 0.5f;\r\n\tEngineGlobals.pixel_shader_constants[18]\t= 0.0f;\t// Fog denisty.\r\n\tEngineGlobals.pixel_shader_constants[19]\t= 0.5f;\t// Constant 0.5\r\n\r\n\tEngineGlobals.pixel_shader_override\t\t\t= 0;\r\n\tEngineGlobals.pixel_shader_id\t\t\t\t= 0;\r\n\tEngineGlobals.upload_pixel_shader_constants = false;\r\n\tEngineGlobals.is_orthographic\t\t\t\t= false;\r\n\tEngineGlobals.custom_pipeline_enabled\t\t= false;\r\n\tEngineGlobals.vertex_shader_override\t\t= 0;\r\n\tEngineGlobals.texture_stage_override\t\t= 0;\r\n\tEngineGlobals.material_override\t\t\t\t= 0;\r\n\tEngineGlobals.blend_mode_override\t\t\t= 0;\r\n\r\n\tEngineGlobals.clear_color_buffer\t\t\t= true;\r\n\tEngineGlobals.clear_color\t\t\t\t\t= 0x00506070;\r\n\tEngineGlobals.letterbox_active\t\t\t\t= false;\r\n\r\n\t// Set default directional lights\r\n\tEngineGlobals.directional_light_color[0]\t= -0.5f;\t\t// Dir0\r\n\tEngineGlobals.directional_light_color[1]\t= -0.8660254f;\r\n\tEngineGlobals.directional_light_color[2]\t= 0.0f;\r\n\tEngineGlobals.directional_light_color[3]\t= 0.0f;\r\n\tEngineGlobals.directional_light_color[4]\t= 0.586f;\t\t// Col0\r\n\tEngineGlobals.directional_light_color[5]\t= 0.586f;\r\n\tEngineGlobals.directional_light_color[6]\t= 0.586f;\r\n\tEngineGlobals.directional_light_color[7]\t= 1.0f;\r\n\t\r\n\tEngineGlobals.directional_light_color[8]\t= 1.0f;\t\t\t// Dir1\r\n\tEngineGlobals.directional_light_color[9]\t= 0.0f;\r\n\tEngineGlobals.directional_light_color[10]\t= 0.0f;\r\n\tEngineGlobals.directional_light_color[11]\t= 0.0f;\r\n\tEngineGlobals.directional_light_color[12]\t= 0.0f;\t\t\t// Col1\r\n\tEngineGlobals.directional_light_color[13]\t= 0.0f;\r\n\tEngineGlobals.directional_light_color[14]\t= 0.0f;\r\n\tEngineGlobals.directional_light_color[15]\t= 1.0f;\r\n\t\r\n\tEngineGlobals.directional_light_color[16]\t= 1.0f;\t\t\t// Dir2\r\n\tEngineGlobals.directional_light_color[17]\t= 0.0f;\r\n\tEngineGlobals.directional_light_color[18]\t= 0.0f;\r\n\tEngineGlobals.directional_light_color[19]\t= 0.0f;\r\n\tEngineGlobals.directional_light_color[20]\t= 0.0f;\t\t\t// Col2\r\n\tEngineGlobals.directional_light_color[21]\t= 0.0f;\r\n\tEngineGlobals.directional_light_color[22]\t= 0.0f;\r\n\tEngineGlobals.directional_light_color[23]\t= 1.0f;\r\n\r\n\t// Set default ambient light.\r\n\tEngineGlobals.ambient_light_color[0]\t\t= 0.5865f;\r\n\tEngineGlobals.ambient_light_color[1]\t\t= 0.5865f;\r\n\tEngineGlobals.ambient_light_color[2]\t\t= 0.5865f;\r\n\tEngineGlobals.ambient_light_color[3]\t\t= 1.0f;\r\n \r\n\tEngineGlobals.fog_enabled\t\t\t\t\t= false;\r\n\tEngineGlobals.fog_color\t\t\t\t\t\t= 0x00000000UL;\r\n\tEngineGlobals.fog_start\t\t\t\t\t\t= FEET_TO_INCHES( -20.0f );\r\n\tEngineGlobals.fog_end\t\t\t\t\t\t= FEET_TO_INCHES( -2050.0f );\r\n\t\r\n\tD3DDevice_SetRenderState( D3DRS_FOGENABLE,\t\tEngineGlobals.fog_enabled );\r\n\tD3DDevice_SetRenderState( D3DRS_FOGTABLEMODE,\tD3DFOG_LINEAR );\r\n//\tD3DDevice_SetRenderState( D3DRS_FOGTABLEMODE,\tD3DFOG_EXP );\r\n//\tD3DDevice_SetRenderState( D3DRS_FOGSTART,\t\t*((DWORD*)( &EngineGlobals.fog_start )));\r\n//\tD3DDevice_SetRenderState( D3DRS_FOGEND,\t\t\t*((DWORD*)( &EngineGlobals.fog_end )));\r\n\tD3DDevice_SetRenderState( D3DRS_FOGCOLOR,\t\tEngineGlobals.fog_color );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid InitialiseEngine( void )\r\n{\r\n\tD3DPRESENT_PARAMETERS   params;\r\n\tDWORD\t\t\t\t\tvideo_flags = XGetVideoFlags();\r\n\r\n\tEngineGlobals.loadingbar_timer_event\t= 0;\r\n\t\r\n\t// Setup default values for the screen conversion macro.\r\n\tEngineGlobals.screen_conv_x_multiplier\t= 640.0f / 640.0f;\r\n\tEngineGlobals.screen_conv_y_multiplier\t= 480.0f / 480.0f;\r\n\tEngineGlobals.screen_conv_x_offset\t\t= 0;\r\n\tEngineGlobals.screen_conv_y_offset\t\t= 16;\r\n\t\r\n\tZeroMemory( &params, sizeof( D3DPRESENT_PARAMETERS ));\r\n\r\n\t// This setting required for any multisample presentation.\r\n\tparams.SwapEffect\t\t\t\t\t\t= D3DSWAPEFFECT_DISCARD;\r\n\r\n\t// Let D3D create the depth-stencil buffer for us.\r\n\tparams.EnableAutoDepthStencil\t\t\t= TRUE;\r\n\r\n\t// Select default refresh rate and presentation interval. Note: When we switch to the December SDK\r\n\t// we can use the ONE_OR_IMMEDIATE value (if the tearing looks okay).\r\n\tif(( Config::GetDisplayType() == Config::DISPLAY_TYPE_PAL ) && ( Config::FPS() == 60 ))\r\n\t{\r\n\t\t// PAL 60Hz has been selected - need to set this refresh rate explicitly.\r\n\t\tparams.FullScreen_RefreshRateInHz\t= 60;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tparams.FullScreen_RefreshRateInHz\t= D3DPRESENT_RATE_DEFAULT;\r\n\t}\r\n//\tparams.FullScreen_PresentationInterval\t= D3DPRESENT_INTERVAL_ONE;\r\n\tparams.FullScreen_PresentationInterval\t= D3DPRESENT_INTERVAL_ONE_OR_IMMEDIATE;\r\n//\tparams.FullScreen_PresentationInterval\t= D3DPRESENT_INTERVAL_IMMEDIATE;\r\n\r\n\t// Set up the back buffer format.\r\n\tparams.BackBufferCount\t\t\t\t\t= 1;\r\n\tparams.BackBufferWidth\t\t\t\t\t= 640;\r\n\tparams.BackBufferHeight\t\t\t\t\t= 480;\r\n\tparams.BackBufferFormat\t\t\t\t\t= D3DFMT_LIN_X8R8G8B8;\r\n\r\n\t// Set up the Z-stencil buffer format and multisample format.\r\n\tparams.AutoDepthStencilFormat\t\t\t= D3DFMT_D24S8;\r\n//\tparams.MultiSampleType\t\t\t\t\t= D3DMULTISAMPLE_NONE;\r\n\tparams.MultiSampleType\t\t\t\t\t= D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_LINEAR;\r\n//\tparams.MultiSampleType\t\t\t\t\t= D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_QUINCUNX;\r\n//\tparams.MultiSampleType\t\t\t\t\t= D3DMULTISAMPLE_4_SAMPLES_SUPERSAMPLE_LINEAR;\r\n\r\n\t// Set flag for widescreen where appropriate.\r\n\tif( video_flags & XC_VIDEO_FLAGS_WIDESCREEN )\r\n\t{\r\n\t\tparams.Flags\t\t\t|= D3DPRESENTFLAG_WIDESCREEN;\r\n\r\n\t\t// Optionally set up 720480 back buffer.\r\n\t\t// Set up 16:9 projection transform.\r\n\t}\r\n\r\n\t\r\n\t// Set flag for progrssive scan where appropriate.\r\n\tif( video_flags & XC_VIDEO_FLAGS_HDTV_720p )\r\n\t{\r\n\t\tparams.Flags\t\t\t|= D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN;\r\n\t\tparams.BackBufferWidth\t= 1280;\r\n\t\tparams.BackBufferHeight\t= 720;\r\n\r\n\t\t// Turn off FSAA.\r\n\t\tparams.MultiSampleType\t= D3DMULTISAMPLE_NONE;\r\n\r\n\t\tEngineGlobals.screen_conv_x_multiplier\t= 1280.0f / 704.0f;\r\n\t\tEngineGlobals.screen_conv_y_multiplier\t= 720.0f / 480.0f;\r\n\t\tEngineGlobals.screen_conv_x_offset\t\t= 32;\r\n\t\tEngineGlobals.screen_conv_y_offset\t\t= 32;\r\n\t}\r\n\telse if( video_flags & XC_VIDEO_FLAGS_HDTV_480p )\r\n\t{\r\n\t\tparams.Flags\t\t\t|= D3DPRESENTFLAG_PROGRESSIVE;\r\n\t}\r\n//\telse if( video_flags & XC_VIDEO_FLAGS_HDTV_1080i )\r\n//\t{\r\n//\t\tparams.Flags\t\t\t\t\t\t\t|= D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_WIDESCREEN | D3DPRESENTFLAG_FIELD;\r\n//\t\tparams.BackBufferWidth\t\t\t\t\t= 1920;\r\n//\t\tparams.BackBufferHeight\t\t\t\t\t= 540;\r\n//\t\tparams.BackBufferFormat\t\t\t\t\t= D3DFMT_LIN_R5G6B5;\r\n//\t\tparams.AutoDepthStencilFormat\t\t\t= D3DFMT_D16;\r\n//\t\tparams.FullScreen_PresentationInterval\t= D3DPRESENT_INTERVAL_TWO;\r\n//\r\n//\t\t// Turn off FSAA.\r\n//\t\tparams.MultiSampleType\t= D3DMULTISAMPLE_NONE;\r\n//\r\n//\t\tEngineGlobals.screen_conv_x_multiplier\t= 1920.0f / 704.0f;\r\n//\t\tEngineGlobals.screen_conv_y_multiplier\t= 1080.0f / 480.0f;\r\n//\t\tEngineGlobals.screen_conv_x_offset\t\t= 32;\r\n//\t\tEngineGlobals.screen_conv_y_offset\t\t= 16;\r\n//\t}\r\n\telse\r\n\t{\r\n\t\tparams.Flags\t\t\t|= D3DPRESENTFLAG_INTERLACED;\r\n\t}\r\n\t\r\n\tif( params.BackBufferWidth == 640 )\r\n\t{\r\n\t\tparams.Flags\t\t\t|= D3DPRESENTFLAG_10X11PIXELASPECTRATIO;\r\n\t}\r\n\t\r\n\t// The default push buffer size is 512k. Double this to reduce stalls from filling the push buffer.\r\n\tDirect3D_SetPushBufferSize( 2 * 512 * 1024, 32 * 1024 );\r\n\t\r\n\tif( D3D_OK != Direct3D_CreateDevice(\tD3DADAPTER_DEFAULT,\r\n\t\t\t\t\t\t\t\t\t\t\tD3DDEVTYPE_HAL,\r\n\t\t\t\t\t\t\t\t\t\t\tNULL,\r\n\t\t\t\t\t\t\t\t\t\t\tD3DCREATE_HARDWARE_VERTEXPROCESSING,\t// Note: may want to consider adding the PUREDEVICE flag here also.\r\n\t\t\t\t\t\t\t\t\t\t\t&params,\r\n\t\t\t\t\t\t\t\t\t\t\t&EngineGlobals.p_Device ))\r\n\t{\r\n\t\t// Failed to start up engine. Bad!\r\n\t\texit( 0 );\r\n\t}\r\n\r\n\t// Also create the render surface we will use when doing screen blur. (Creating this at 32bit depth also, since still\r\n\t// takes up less memory than 720p buffers).\r\n\tif( params.BackBufferWidth <= 640 )\r\n\t{\r\n\t\tD3DDevice_CreateRenderTarget( 640, 480, D3DFMT_LIN_X8R8G8B8, 0, 0, &EngineGlobals.p_BlurSurface[0] );\r\n\t\tD3DDevice_CreateRenderTarget( 320, 240, D3DFMT_LIN_X8R8G8B8, 0, 0, &EngineGlobals.p_BlurSurface[1] );\r\n\t\tD3DDevice_CreateRenderTarget( 160, 120, D3DFMT_LIN_X8R8G8B8, 0, 0, &EngineGlobals.p_BlurSurface[2] );\r\n\t\tD3DDevice_CreateRenderTarget(  80,  60, D3DFMT_LIN_X8R8G8B8, 0, 0, &EngineGlobals.p_BlurSurface[3] );\r\n\t}\r\n\t\r\n\t// Obtain pointers to the render and Z-stencil surfaces. Doing this increases their reference counts, so release\r\n\t// them following the operation.\r\n\tD3DDevice_GetRenderTarget( &EngineGlobals.p_RenderSurface );\r\n\tD3DDevice_GetDepthStencilSurface( &EngineGlobals.p_ZStencilSurface );\r\n\r\n\tLPDIRECT3DSURFACE8 pBackBuffer;\r\n    D3DDevice_GetBackBuffer( 0, 0, &pBackBuffer );\r\n\t\r\n\t// Get back buffer information.\r\n\tEngineGlobals.backbuffer_width\t= params.BackBufferWidth;\r\n\tEngineGlobals.backbuffer_height\t= params.BackBufferHeight;\r\n\tEngineGlobals.backbuffer_format\t= params.BackBufferFormat;\r\n\tEngineGlobals.zstencil_depth\t= ( params.AutoDepthStencilFormat == D3DFMT_D16 ) ? 16 : 32;\r\n\t\r\n\t// Get blur buffer information.\r\n\tif( EngineGlobals.p_BlurSurface[0] )\r\n\t{\r\n\t\tD3DSURFACE_DESC blur_surface_desc;\r\n\t\tEngineGlobals.p_BlurSurface[0]->GetDesc( &blur_surface_desc );\r\n\t\tEngineGlobals.blurbuffer_format\t= blur_surface_desc.Format;\r\n\t}\r\n\t\r\n\t// Set our renderstate to a known state.\r\n\tInitialiseRenderstates();\r\n\r\n\t// Set default gamma values.\r\n\tSetGammaNormalized( 0.14f, 0.13f, 0.12f );\r\n\r\n\t// Initialise the memory resident font, used for fatal i/o error messages etc.\r\n\tEngineGlobals.p_memory_resident_font = InitialiseMemoryResidentFont();\r\n\r\n\t// Code to enable detailed timing. Need to link with d3d8i.lib.\r\n//\tDmEnableGPUCounter( TRUE );\r\n//\tD3DPERF_SetShowFrameRateInterval( 1000 );\r\n//\tD3DPERF_GetStatistics()->m_dwDumpFPSInfoMask |= D3DPERF_DUMP_FPS_PERFPROFILE;\r\n\r\n\t// Now that the D3DDevice is created, it's safe to install vsync handlers.\r\n\tTmr::InstallVSyncHandlers();\r\n\r\n\t// Load up the bump textures.\r\n//\tLoadBumpTextures();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid FatalFileError( uint32 error )\r\n{\r\n\tstatic char*\tp_error_message_english[2]\t= {\t\"There's a problem with the disc you're using.\",\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"It may be dirty or damaged.\" };\r\n\tstatic char*\tp_error_message_french[2]\t= {\t\"Le disque utilis prsente une anomalie.\",\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Il est peut-tre sale ou endommag.\" };\r\n\tstatic char*\tp_error_message_german[2]\t= {\t\"Bei der benutzten CD ist ein Problem aufgetreten.\",\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Mglicherweise ist sie verschmutzt oder beschdigt.\" };\r\n\r\n\t// Turn off the loading bar if it is active.\r\n\tif( EngineGlobals.loadingbar_timer_event != 0 )\r\n\t{\r\n\t\ttimeKillEvent( EngineGlobals.loadingbar_timer_event );\r\n\t\tEngineGlobals.loadingbar_timer_event = 0;\r\n\t}\r\n\r\n\t// Ensure the graphics device has been initialised at this point.\r\n\tif( EngineGlobals.p_Device == NULL )\r\n\t{\r\n\t\tInitialiseEngine();\r\n\t}\r\n\r\n\t// Wait for any rendering to complete.\r\n\tEngineGlobals.p_Device->BlockUntilIdle();\r\n\r\n\tchar*\tp_error_message[2];\r\n\tswitch( Config::GetLanguage())\r\n\t{\r\n\t\tcase Config::LANGUAGE_FRENCH:\r\n\t\t{\r\n\t\t\tp_error_message[0] = p_error_message_french[0];\r\n\t\t\tp_error_message[1] = p_error_message_french[1];\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase Config::LANGUAGE_GERMAN:\r\n\t\t{\r\n\t\t\tp_error_message[0] = p_error_message_german[0];\r\n\t\t\tp_error_message[1] = p_error_message_german[1];\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tp_error_message[0] = p_error_message_english[0];\r\n\t\t\tp_error_message[1] = p_error_message_english[1];\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Set up the text string used for the error message.\r\n\tSText error_text;\r\n\terror_text.mp_font\t\t= (SFont*)EngineGlobals.p_memory_resident_font;\r\n\terror_text.m_xpos\t\t= 48.0f;\r\n\terror_text.m_ypos\t\t= 128.0f;\r\n\terror_text.m_xscale\t\t= 0.8f;\r\n\terror_text.m_yscale\t\t= 1.0f;\r\n\terror_text.m_rgba\t\t= 0x80808080;\r\n\terror_text.mp_next\t\t= NULL;\r\n\r\n\tset_texture( 1, NULL );\r\n\tset_texture( 2, NULL );\r\n\tset_texture( 3, NULL );\r\n\r\n\t// Want an infinite loop here.\r\n\twhile( true )\r\n\t{\r\n\t\tD3DDevice_Swap( D3DSWAP_DEFAULT );\r\n\r\n\t\t// Now that the swap instruction has been pushed, clear the buffer for next frame.\r\n\t\tD3DDevice_Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, 0x00000000, 1.0f, 0 );\r\n\r\n\t\tset_blend_mode( vBLEND_MODE_BLEND );\r\n\t\tset_texture( 0, NULL );\r\n\r\n\t\tset_render_state( RS_UVADDRESSMODE0,\t0x00010001UL );\r\n\t\tset_render_state( RS_ZBIAS,\t\t\t\t0 );\r\n\t\tset_render_state( RS_ALPHACUTOFF,\t\t1 );\r\n\t\tset_render_state( RS_ZWRITEENABLE,\t\t0 );\r\n\r\n\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_COLORSIGN, D3DTSIGN_RUNSIGNED | D3DTSIGN_GUNSIGNED | D3DTSIGN_BUNSIGNED );\r\n\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );\r\n\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | 0 );\r\n\r\n\t\terror_text.mp_string\t= p_error_message[0];\r\n\t\terror_text.m_ypos\t\t= error_text.m_ypos - 16.0f;\r\n\t\terror_text.BeginDraw();\r\n\t\terror_text.Draw();\r\n\t\terror_text.EndDraw();\r\n\r\n\t\terror_text.mp_string\t= p_error_message[1];\r\n\t\terror_text.m_ypos\t\t= error_text.m_ypos + 16.0f;\r\n\t\terror_text.BeginDraw();\r\n\t\terror_text.Draw();\r\n\t\terror_text.EndDraw();\r\n\t}\r\n}\r\n\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/nx_init.h",
    "content": "#ifndef __NX_INIT_H\r\n#define __NX_INIT_H\r\n\r\n#include <core/defines.h>\r\n#include <xgmath.h>\r\n\r\nnamespace NxXbox\r\n{\r\n\r\nvoid InitialiseEngine( void );\r\nvoid FatalFileError( uint32 error );\r\n\r\ntypedef struct\r\n{\r\n\tXGMATRIX\t\t\tworld_matrix;\r\n\tXGMATRIX\t\t\tview_matrix;\r\n\tXGMATRIX\t\t\tprojection_matrix;\r\n\r\n\tXGMATRIX\t\t\tbump_env_matrix;\t\t\t\t\t// Used to set the D3DTSS_BUMPENVMATnn texture states where applicable.\r\n\r\n\tD3DVIEWPORT8\t\tviewport;\r\n\tfloat\t\t\t\tnear_plane;\r\n\tfloat\t\t\t\tfar_plane;\r\n\tfloat\t\t\t\tscreen_angle;\r\n\tfloat\t\t\t\tnear_plane_width;\r\n\tfloat\t\t\t\tnear_plane_height;\r\n\tbool\t\t\t\tis_orthographic;\r\n\tbool\t\t\t\tclear_color_buffer;\t\t\t\t\t// Whether the color buffer is cleared during buffer swap and clear process.\r\n\tbool\t\t\t\tletterbox_active;\t\t\t\t\t// Whether running in 4:3 letterbox mode.\r\n\tD3DCOLOR\t\t\tclear_color;\t\t\t\t\t\t// The color to which the color buffer is cleared.\r\n\tXGVECTOR3\t\t\tcam_position;\r\n\tXGVECTOR3\t\t\tmodel_relative_cam_position;\t\t// Used in specular lighting calculations.\r\n\tXGVECTOR3\t\t\tcam_at;\r\n\tXGVECTOR3\t\t\tcam_up;\r\n\tXGVECTOR3\t\t\tcam_right;\r\n\r\n\tint\t\t\t\t\trender_start_time;\t\t\t\t\t// Time (milliseconds) at which the current frame render started.\r\n\r\n\tbool\t\t\t\tloadingscreen_visible;\r\n\tMMRESULT\t\t\tloadingbar_timer_event;\r\n\t\t\r\n\tIDirect3DDevice8*\tp_Device;\r\n\tIDirect3DSurface8*\tp_RenderSurface;\r\n\tIDirect3DSurface8*\tp_ZStencilSurface;\r\n\tIDirect3DSurface8*\tp_BlurSurface[4];\r\n\r\n\tint\t\t\t\t\tbackbuffer_width;\r\n\tint\t\t\t\t\tbackbuffer_height;\r\n\tD3DFORMAT\t\t\tbackbuffer_format;\r\n\tD3DFORMAT\t\t\tblurbuffer_format;\r\n\tint\t\t\t\t\tzstencil_depth;\r\n\tfloat\t\t\t\tscreen_conv_x_multiplier;\r\n\tfloat\t\t\t\tscreen_conv_y_multiplier;\r\n\tint\t\t\t\t\tscreen_conv_x_offset;\r\n\tint\t\t\t\t\tscreen_conv_y_offset;\r\n\t\r\n\tvoid*\t\t\t\tp_memory_resident_font;\r\n\r\n\tchar\t\t\t\tscreenshot_name[128];\r\n\r\n\t// For bounding sphere culling calculations.\r\n\tfloat\t\t\t\tViewFrustumTX;\r\n\tfloat\t\t\t\tViewFrustumTY;\r\n\tfloat\t\t\t\tViewFrustumSX;\r\n\tfloat\t\t\t\tViewFrustumSY;\r\n\tfloat\t\t\t\tViewFrustumCX;\r\n\tfloat\t\t\t\tViewFrustumCY;\r\n\r\n\tuint32\t\t\t\tblend_mode_value;\r\n\tuint32\t\t\t\tblend_op;\r\n\tuint32\t\t\t\tsrc_blend;\r\n\tuint32\t\t\t\tdest_blend;\r\n\r\n\tuint32\t\t\t\talpha_blend_enable;\r\n\tuint32\t\t\t\talpha_test_enable;\r\n\tuint32\t\t\t\talpha_ref;\r\n\tuint32\t\t\t\tspecular_enabled;\r\n\tbool\t\t\t\tlighting_enabled;\r\n\tbool\t\t\t\tdither_enable;\r\n\tbool\t\t\t\tz_write_enabled;\r\n\tbool\t\t\t\tz_test_enabled;\r\n\tuint32\t\t\t\tz_bias;\r\n\tint\t\t\t\t\tcull_mode;\r\n\tbool\t\t\t\tallow_envmapping;\t\t\t\t// Set to true (default) to allow costly environment mapping\r\n\tuint32\t\t\t\tuv_addressing[4];\r\n\tuint32\t\t\t\tmip_map_lod_bias[4];\r\n\tuint32\t\t\t\tmin_mag_filter[4];\r\n\tvoid\t\t\t\t*p_texture[4];\r\n\tDWORD\t\t\t\tcolor_sign[4];\r\n\tbool\t\t\t\tcustom_pipeline_enabled;\t\t// A true value indicates that the fixed function pipeline is not being used.\r\n\tDWORD\t\t\t\tvertex_shader_id;\r\n\tDWORD\t\t\t\tpixel_shader_override;\r\n\tDWORD\t\t\t\tpixel_shader_id;\r\n\tfloat\t\t\t\tpixel_shader_constants[20];\t\t// 4 floats per constant.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// c0 - c3\t: material pass color (rgb) and fixed alpha (a) for relevant blend modes\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// c4\t\t: fog denisty (b), 0.5 (a)\r\n\tbool\t\t\t\tupload_pixel_shader_constants;\r\n\tDWORD\t\t\t\tvertex_shader_override;\r\n\tDWORD\t\t\t\ttexture_stage_override;\r\n\tDWORD\t\t\t\tmaterial_override;\r\n\tDWORD\t\t\t\tblend_mode_override;\r\n\tfloat\t\t\t\tambient_light_color[4];\t\t\t// In format ready to load to GPU.\r\n\tfloat\t\t\t\tdirectional_light_color[24];\t// In format ready to load to GPU (dir0, col0, dir 1, col1, etc).\r\n\tuint32\t\t\t\tscreen_blur;\t\t\t\t\t// [0, 255] - [no blur, max blur]\r\n\tuint32\t\t\t\tscreen_blur_duration;\t\t\t// How many frames the screen blur has been active for.\r\n\tuint32\t\t\t\tfocus_blur;\t\t\t\t\t\t// [0, 255] - [no blur, max blur]\r\n\tuint32\t\t\t\tfocus_blur_duration;\t\t\t// How many frames the focus blur has been active for.\r\n\r\n\tuint32\t\t\t\tfog_enabled;\r\n\tD3DCOLOR\t\t\tfog_color;\r\n\tfloat\t\t\t\tfog_start;\r\n\tfloat\t\t\t\tfog_end;\r\n}\r\nsEngineGlobals;\r\n\r\nextern sEngineGlobals EngineGlobals;\r\n\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n#endif // __NX_INIT_H\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/occlude.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics (GFX)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tocclude.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/18/02\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tOcclusion testing code\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\r\n#include <xtl.h>\r\n#include <xgmath.h>\r\n#include <core/math.h>\r\n#include <gfx/debuggfx.h>\r\n#include \"occlude.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//extern D3DXMATRIX *p_bbox_transform;\r\nextern XGMATRIX *p_bbox_transform;\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nconst uint32 MAX_NEW_OCCLUSION_POLYS_TO_CHECK_PER_FRAME = 4;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Structure used to store details of a single poly. A list of these will be built at geometry load time.\r\nstruct sOcclusionPoly\r\n{\r\n\tbool\t\tin_use;\t\t// Whether the poly is currently being used for occlusion.\r\n\tbool\t\tavailable;\t// Whether the poly is available for selection for occlusion.\r\n\tuint32\t\tchecksum;\t// Name checksum of the occlusion poly.\r\n\tMth::Vector\tverts[4];\r\n\tMth::Vector\tnormal;\r\n};\r\n\t\r\nconst uint32\tMAX_OCCLUDERS\t\t\t\t= 8;\r\nconst uint32\tMAX_VIEWS_PER_OCCLUDER\t\t= 2;\r\n\r\nstruct sOccluder\r\n{\r\n\tstatic uint32\t\tNumOccluders;\r\n\tstatic sOccluder\tOccluders[MAX_OCCLUDERS];\r\n\r\n\tstatic void\t\t\tadd_to_stack( sOcclusionPoly *p_poly );\r\n\tstatic void\t\t\tsort_stack( void );\r\n\tstatic void\t\t\ttidy_stack( void );\r\n\r\n\tsOcclusionPoly\t*p_poly;\r\n\tMth::Vector\t\tplanes[5];\r\n\tint\t\t\t\tscore[MAX_VIEWS_PER_OCCLUDER];\t// Current rating on quality of occlusion - based on number of meshes occluded last frame.\r\n};\r\n\r\nconst uint32\tMAX_OCCLUSION_POLYS\t\t\t= 512;\r\nuint32\t\t\tNumOcclusionPolys\t\t\t= 0;\r\nuint32\t\t\tNextOcclusionPolyToCheck\t= 0;\r\nint\t\t\t\tCurrentView\t\t\t\t\t= 0;\r\nsOcclusionPoly\tOcclusionPolys[MAX_OCCLUSION_POLYS];\r\n\r\nuint32\t\tsOccluder::NumOccluders\t\t\t\t= 0;\r\nsOccluder\tsOccluder::Occluders[MAX_OCCLUDERS];\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sOccluder::add_to_stack( sOcclusionPoly *p_poly )\r\n{\r\n\tif( NumOccluders < MAX_OCCLUDERS )\r\n\t{\r\n\t\tDbg_Assert( p_poly->available );\r\n\r\n\t\tOccluders[NumOccluders].p_poly\t= p_poly;\r\n\t\tp_poly->in_use\t\t\t\t\t= true;\r\n\r\n\t\t// Reset scores for all views.\r\n\t\tmemset( Occluders[NumOccluders].score, 0, sizeof( int ) * MAX_VIEWS_PER_OCCLUDER );\r\n\r\n\t\t++NumOccluders;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int cmp( const void *p1, const void *p2 )\r\n{\r\n\t// Sort based on the sum total of scores in all views.\r\n\tint score1 = 0;\r\n\tint score2 = 0;\r\n\tfor( int v = 0; v < MAX_VIEWS_PER_OCCLUDER; ++v )\r\n\t{\r\n\t\t// Zero the score for any occlusion poly that is no longer available. This will force it out of the stack.\r\n\t\tif(((sOccluder*)p1)->p_poly->available == false )\r\n\t\t\t((sOccluder*)p1)->score[v] = 0;\r\n\r\n\t\tif(((sOccluder*)p2)->p_poly->available == false )\r\n\t\t\t((sOccluder*)p2)->score[v] = 0;\r\n\r\n\t\tscore1 += ((sOccluder*)p1)->score[v];\r\n\t\tscore2 += ((sOccluder*)p2)->score[v];\r\n\t}\r\n\r\n\treturn score1 < score2 ? 1 : score1 > score2 ? -1 : 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sOccluder::sort_stack( void )\r\n{\r\n\tqsort( Occluders, NumOccluders, sizeof( sOccluder ), cmp );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sOccluder::tidy_stack( void )\r\n{\r\n\tif( NumOccluders > 0 )\r\n\t{\r\n\t\t// Sort in descending score order.\r\n\t\tsort_stack();\r\n\r\n\t\t// Count backwards so we know we get all the bad occluders.\r\n\t\tfor( int i = NumOccluders - 1; i >= 0; --i )\r\n\t\t{\r\n\t\t\t// If we have hit an occluder with zero meshes culled, cut off the stack at this point.\r\n\t\t\tint total_score = 0;\r\n\t\t\tfor( int v = 0; v < MAX_VIEWS_PER_OCCLUDER; ++v )\r\n\t\t\t{\r\n\t\t\t\ttotal_score += Occluders[i].score[v];\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif( total_score == 0 )\r\n\t\t\t{\r\n\t\t\t\t// No longer using this poly.\r\n\t\t\t\tOccluders[i].p_poly->in_use = false;\r\n\r\n\t\t\t\t// One less occluder to worry about.\r\n\t\t\t\t--NumOccluders;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Reset the good occluders.\r\n\t\t\t\tOccluders[i].score[CurrentView] = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Used to add an occlusion poly to the list. Likely to be called */\r\n/* as geometry is spooled in.                                     */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid AddOcclusionPoly( Mth::Vector &v0, Mth::Vector &v1, Mth::Vector &v2, Mth::Vector &v3, uint32 checksum )\r\n{\r\n\tDbg_Assert( NumOcclusionPolys < MAX_OCCLUSION_POLYS );\t\r\n\t\r\n\tOcclusionPolys[NumOcclusionPolys].in_use\t= false;\r\n\tOcclusionPolys[NumOcclusionPolys].available\t= true;\r\n\tOcclusionPolys[NumOcclusionPolys].checksum\t= checksum;\r\n\tOcclusionPolys[NumOcclusionPolys].verts[0]\t= v0;\r\n\tOcclusionPolys[NumOcclusionPolys].verts[1]\t= v1;\r\n\tOcclusionPolys[NumOcclusionPolys].verts[2]\t= v2;\r\n\tOcclusionPolys[NumOcclusionPolys].verts[3]\t= v3;\r\n\tOcclusionPolys[NumOcclusionPolys].normal\t= Mth::CrossProduct( v1 - v0, v3 - v0 );\r\n\tOcclusionPolys[NumOcclusionPolys].normal.Normalize();\r\n\t\r\n\t++NumOcclusionPolys;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Used to toggle whether an occlusion poly can be used or not\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid EnableOcclusionPoly( uint32 checksum, bool available )\r\n{\r\n\tfor( uint32 i = 0; i < NumOcclusionPolys; ++i )\r\n\t{\r\n\t\tif( OcclusionPolys[i].checksum == checksum )\r\n\t\t{\r\n\t\t\tOcclusionPolys[i].available\t= available;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Used to clear all occlusion polys (when a level is unloaded)   */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid RemoveAllOcclusionPolys( void )\r\n{\r\n\tDbg_Assert( NumOcclusionPolys < MAX_OCCLUSION_POLYS );\t\r\n\t\r\n \tsOccluder::NumOccluders\t\t= 0;\r\n\tNumOcclusionPolys\t\t\t= 0;\r\n\tNextOcclusionPolyToCheck\t= 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CheckForOptimalOccluders( Mth::Vector &cam_pos, Mth::Vector &view_direction )\r\n{\r\n\tif( NumOcclusionPolys > 0 )\r\n\t{\r\n\t\tuint32 added\t= 0;\r\n\t\tuint32 checked\t= 0;\r\n\r\n\t\twhile( added < MAX_NEW_OCCLUSION_POLYS_TO_CHECK_PER_FRAME )\r\n\t\t{\r\n\t\t\t// Given the current position of the camera, check through the unused, available occlusion polys to see if one scores higher\r\n\t\t\t// than the lowest scoring occlusion poly in use.\r\n\t\t\tsOcclusionPoly *poly_to_check = &OcclusionPolys[NextOcclusionPolyToCheck++];\r\n\t\t\tif(( !poly_to_check->in_use ) && ( poly_to_check->available ))\r\n\t\t\t{\r\n\t\t\t\tsOccluder::add_to_stack( poly_to_check );\r\n\t\t\t\t++added;\r\n\t\t\t}\r\n\t\t\t++checked;\r\n\r\n\t\t\t// Ensure we are always checking within bounds.\r\n\t\t\tif( NextOcclusionPolyToCheck >= NumOcclusionPolys )\r\n\t\t\t{\r\n\t\t\t\tNextOcclusionPolyToCheck = 0;\r\n\t\t\t}\r\n\r\n\t\t\t// Quit out if we have less available occluders than spaces to fill.\r\n\t\t\tif( checked >= NumOcclusionPolys )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid BuildOccluders( Mth::Vector *p_cam_pos, int view )\r\n{\r\n//\tfor( uint32 i = 0; i < NumOcclusionPolys; ++i )\r\n//\t{\r\n//\t\tGfx::AddDebugLine( OcclusionPolys[i].verts[0], OcclusionPolys[i].verts[1], 0, 0, 1 );\r\n//\t\tGfx::AddDebugLine( OcclusionPolys[i].verts[1], OcclusionPolys[i].verts[2], 0, 0, 1 );\r\n//\t\tGfx::AddDebugLine( OcclusionPolys[i].verts[2], OcclusionPolys[i].verts[3], 0, 0, 1 );\r\n//\t\tGfx::AddDebugLine( OcclusionPolys[i].verts[3], OcclusionPolys[i].verts[0], 0, 0, 1 );\r\n//\t}\r\n\t\r\n\t// Set the current view - this will remain active until another call to this function.\r\n\tDbg_Assert( view < MAX_VIEWS_PER_OCCLUDER );\r\n\tCurrentView\t= view;\r\n\t\r\n\t// Tidy up from last frame.\r\n\tsOccluder::tidy_stack();\r\n\t\r\n\t// Cyclically add more occluders for checking.\r\n\tCheckForOptimalOccluders( *p_cam_pos, *p_cam_pos );\r\n\t\r\n\t// Build all 5 planes for each occluder.\r\n\tMth::Vector u0, u1, p;\r\n\r\n\t// The order in which the verts are used to build tha planes depends upon where the camera is in relation to the occlusion\r\n\t// poly. We use the default order when the viewpoint is on the side of the poly on which the default poly normal faces.\r\n\tfor( uint32 i = 0; i < sOccluder::NumOccluders; ++i )\r\n\t{\r\n\t\tsOcclusionPoly *p_poly = sOccluder::Occluders[i].p_poly;\r\n\r\n//\t\tGfx::AddDebugLine( p_poly->verts[0], p_poly->verts[1], 0, 0, 1 );\r\n//\t\tGfx::AddDebugLine( p_poly->verts[1], p_poly->verts[2], 0, 0, 1 );\r\n//\t\tGfx::AddDebugLine( p_poly->verts[2], p_poly->verts[3], 0, 0, 1 );\r\n//\t\tGfx::AddDebugLine( p_poly->verts[3], p_poly->verts[0], 0, 0, 1 );\r\n\t\t\r\n\t\tif( Mth::DotProduct( *p_cam_pos - p_poly->verts[0], p_poly->normal ) >= 0.0f )\r\n\t\t{\r\n\t\t\t// Start with the front. We want to reverse the order of the front plane to ensure that objects *behind* the plane\r\n\t\t\t// are considered occluded. (1->3->4)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[2] - p_poly->verts[0];\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[3] - p_poly->verts[0];\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, p_poly->verts[0] );\r\n\t\t\tsOccluder::Occluders[i].planes[0]\t= p;\r\n\r\n\t\t\t// ...then left (0->1->2)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[0] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[1] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[1]\t= p;\r\n\r\n\t\t\t// ...then right (0->3->4)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[2] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[3] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[2]\t= p;\r\n\r\n\t\t\t// ...then top (0->2->3)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[1] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[2] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[3]\t= p;\r\n\r\n\t\t\t// ...then bottom (0->4->1)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[3] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[0] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[4]\t= p;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Start with the front. We want to reverse the order of the front plane to ensure that objects *behind* the plane\r\n\t\t\t// are considered occluded. (1->4->3)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[3] - p_poly->verts[0];\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[2] - p_poly->verts[0];\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, p_poly->verts[0] );\r\n\t\t\tsOccluder::Occluders[i].planes[0]\t= p;\r\n\r\n\t\t\t// ...then left (0->2->1)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[1] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[0] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[1]\t= p;\r\n\r\n\t\t\t// ...then right (0->4->3)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[3] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[2] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[2]\t= p;\r\n\r\n\t\t\t// ...then top (0->3->2)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[2] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[1] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[3]\t= p;\r\n\r\n\t\t\t// ...then bottom (0->1->4)...\r\n\t\t\tu0\t\t\t\t\t\t= p_poly->verts[0] - *p_cam_pos;\r\n\t\t\tu1\t\t\t\t\t\t= p_poly->verts[3] - *p_cam_pos;\r\n\t\t\tp\t\t\t\t\t\t= Mth::CrossProduct( u0, u1 );\r\n\t\t\tp.Normalize();\r\n\t\t\tp[W]\t\t\t\t\t= Mth::DotProduct( p, *p_cam_pos );\r\n\t\t\tsOccluder::Occluders[i].planes[4]\t= p;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool TestSphereAgainstOccluders( D3DXVECTOR3 *p_center, float radius, uint32 meshes )\r\n{\r\n\tXGVECTOR3 center;\r\n\r\n\t// Build the composite transform if required.\r\n\tif( p_bbox_transform )\r\n\t{\r\n\t\t// Object to world, so transform the sphere center.\r\n\t\tcenter.x = p_center->x + p_bbox_transform->_41;\r\n\t\tcenter.y = p_center->y + p_bbox_transform->_42;\r\n\t\tcenter.z = p_center->z + p_bbox_transform->_43;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcenter.x = p_center->x;\r\n\t\tcenter.y = p_center->y;\r\n\t\tcenter.z = p_center->z;\r\n\t}\r\n\r\n\t// Test against each occluder.\r\n\tfor( uint32 o = 0; o < sOccluder::NumOccluders; ++o )\r\n\t{\r\n\t\tbool occluded = true;\r\n\r\n\t\t// Test against each plane in the occluder.\r\n\t\tfor( uint32 p = 0; p < 5; ++p )\r\n\t\t{\r\n\t\t\tfloat result =\t( sOccluder::Occluders[o].planes[p][X] * center.x ) +\r\n\t\t\t\t\t\t\t( sOccluder::Occluders[o].planes[p][Y] * center.y ) +\r\n\t\t\t\t\t\t\t( sOccluder::Occluders[o].planes[p][Z] * center.z ) -\r\n\t\t\t\t\t\t\t( sOccluder::Occluders[o].planes[p][W] );\r\n\t\t\tif( result >= -radius )\r\n\t\t\t{\r\n\t\t\t\t// Outside of this plane, therefore not occluded by this occluder.\r\n\t\t\t\toccluded = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( occluded )\r\n\t\t{\r\n\t\t\t// Inside all planes, therefore occluded. Increase score for this occluder.\r\n\t\t\tsOccluder::Occluders[o].score[CurrentView] += meshes;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n} // namespace NxXbox\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/occlude.h",
    "content": "#ifndef\t__OCCLUDE_H__\r\n#define\t__OCCLUDE_H__\r\n\r\nnamespace NxXbox\r\n{\r\n\tvoid AddOcclusionPoly( Mth::Vector &v0, Mth::Vector &v1, Mth::Vector &v2, Mth::Vector &v3, uint32 checksum = 0 );\r\n\tvoid EnableOcclusionPoly( uint32 checksum, bool available );\r\n\tvoid RemoveAllOcclusionPolys( void );\r\n\tvoid BuildOccluders( Mth::Vector *p_cam_pos, int view );\r\n\tbool TestSphereAgainstOccluders( D3DXVECTOR3 *p_center, float radius, uint32 meshes = 1 );\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/particles.cpp",
    "content": "\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics (GFX)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tparticle.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/27/02\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tLow level particle rendering code\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\r\n#include <xtl.h>\r\n#include <core/math.h>\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/xbox/p_nxtexture.h>\r\n#include \"render.h\"\r\n#include \"particles.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsParticleSystem::sParticleSystem( uint32 max_particles, eParticleType type, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, int history )\r\n{\r\n\t// Obtain the texture.\r\n\tNx::CTexture\t\t* p_texture\t\t\t= Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( texture_checksum );\r\n\tNx::CXboxTexture\t*p_xbox_texture\t\t= static_cast<Nx::CXboxTexture*>( p_texture );\r\n\tNxXbox::sTexture\t*p_engine_texture\t= NULL;\r\n\tif( p_xbox_texture )\r\n\t{\r\n\t\tp_engine_texture = p_xbox_texture->GetEngineTexture(); \r\n\t}\r\n\t\r\n\t// Create a (semi-transparent) material used to render the mesh.\r\n\tsMaterial *p_material\t\t\t= new sMaterial();\r\n\tp_material->m_flags[0]\t\t\t= 0x40 | (( p_engine_texture ) ? MATFLAG_TEXTURED : 0 );\r\n\tp_material->m_checksum\t\t\t= (uint32)rand() * (uint32)rand();\r\n\tp_material->m_passes\t\t\t= 1;\r\n\tp_material->mp_tex[0]\t\t\t= p_engine_texture;\r\n\tp_material->m_reg_alpha[0]\t\t= GetBlendMode( blendmode_checksum ) | ((uint32)fix << 24 );\r\n\tp_material->m_color[0][0]\t\t= 0.5f;\r\n\tp_material->m_color[0][1]\t\t= 0.5f;\r\n\tp_material->m_color[0][2]\t\t= 0.5f;\r\n\tp_material->m_color[0][3]\t\t= fix * ( 1.0f /  128.0f );\r\n\r\n\tp_material->m_uv_addressing[0]\t= 0;\r\n\tp_material->m_k[0]\t\t\t\t= 0.0f;\r\n\tp_material->m_alpha_cutoff\t\t= 1;\r\n\tp_material->m_no_bfc\t\t\t= true;\r\n\tp_material->m_uv_wibble\t\t\t= false;\r\n\r\n\tmp_material\t\t\t\t\t\t= p_material;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsParticleSystem::~sParticleSystem( void )\r\n{\r\n\tdelete mp_material;\r\n}\r\n\r\n} // namespace NxXbox\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/particles.h",
    "content": "\r\n#ifndef\t__PARTICLE_H__\r\n#define\t__PARTICLE_H__\r\n\r\n#include \"gfx\\xbox\\nx\\scene.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\nenum eParticleType\r\n{\r\n\tPARTICLE_TYPE_LINE,\r\n\tPARTICLE_TYPE_FLAT,\r\n\tPARTICLE_TYPE_SHADED,\r\n\tPARTICLE_TYPE_SMOOTH,\r\n\tPARTICLE_TYPE_GLOW,\r\n\tPARTICLE_TYPE_STAR,\r\n\tPARTICLE_TYPE_SMOOTHSTAR,\r\n\tPARTICLE_TYPE_RIBBON,\r\n\tPARTICLE_TYPE_SMOOTHRIBBON,\r\n\tPARTICLE_TYPE_RIBBONTRAIL,\r\n\tPARTICLE_TYPE_GLOWRIBBONTRAIL,\r\n};\r\n\r\n\r\nstruct sParticleSystem\r\n{\r\npublic:\r\n\t\t\t\tsParticleSystem( uint32 max_particles, eParticleType type, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments = 0, int history = 0 );\r\n\t\t\t\t~sParticleSystem( void );\r\n\r\n\tsMaterial\t*mp_material;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/render.cpp",
    "content": "#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <core/HashTable.h>\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <xgraphics.h>\r\n#include <xgmath.h>\r\n#include <gfx\\xbox\\p_nxgeom.h>\r\n#include <sys\\timer.h>\r\n#include \"nx_init.h\"\r\n#include \"scene.h\"\r\n#include \"render.h\"\r\n#include \"instance.h\"\r\n#include \"occlude.h\"\r\n#include \"billboard.h\"\r\n\r\n#include \"PixelShader0.h\"\r\n#include \"PixelShader0IVA.h\"\r\n#include \"PixelShader1.h\"\r\n#include \"PixelShader2.h\"\r\n#include \"PixelShader3.h\"\r\n#include \"PixelShader4.h\"\r\n#include \"PixelShader5.h\"\r\n#include \"PixelShaderBrighten.h\"\r\n#include \"PixelShaderBrightenIVA.h\"\r\n#include \"PixelShaderFocusBlur.h\"\r\n#include \"PixelShaderFocusIntegrate.h\"\r\n#include \"PixelShaderFocusLookupIntegrate.h\"\r\n#include \"PixelShaderNULL.h\"\r\n#include \"PixelShaderPointSprite.h\"\r\n#include \"PixelShader_ShadowBuffer.h\"\r\n#include \"PixelShaderBumpWater.h\"\r\n#include \"ShadowBufferStaticGeomPS.h\"\r\n\r\nDWORD PixelShader0;\r\nDWORD PixelShader0IVA;\r\nDWORD PixelShader1;\r\nDWORD PixelShader2;\r\nDWORD PixelShader3;\r\nDWORD PixelShader4;\r\nDWORD PixelShader5;\r\nDWORD PixelShaderBrighten;\r\nDWORD PixelShaderBrightenIVA;\r\nDWORD PixelShaderFocusBlur;\r\nDWORD PixelShaderFocusIntegrate;\r\nDWORD PixelShaderFocusLookupIntegrate;\r\nDWORD PixelShaderNULL;\r\nDWORD PixelShaderPointSprite;\r\nDWORD PixelShader_ShadowBuffer;\r\nDWORD PixelShaderBumpWater;\r\nDWORD ShadowBufferStaticGeomPS;\r\n\r\n//D3DXMATRIX *p_bbox_transform = NULL;\r\n//D3DXMATRIX bbox_transform;\r\nXGMATRIX\t*p_bbox_transform = NULL;\r\nXGMATRIX\tbbox_transform;\r\n\r\nextern DWORD ShadowBufferStaticGeomVS;\r\n\r\nnamespace NxXbox\r\n{\r\n\r\nconst float FRONT_TO_BACK_SORT_CUTOFF\t= ( 50.0f * 12.0f );\r\n\r\nLst::HashTable< sTextureProjectionDetails >\t*pTextureProjectionDetailsTable = NULL;\r\n\r\n// For converting a FLOAT to a DWORD (useful for SetRenderState() calls)\r\ninline DWORD FtoDW( FLOAT f ) { return *((DWORD*)&f); }\r\n\r\nstatic Lst::HashTable<DWORD> sPixelShaderTable( 8 );\r\n\r\n\r\nstatic const int MAX_FREE_TESTS\t\t\t\t\t= 1024;\r\nstatic bool\t\tvisibilityTestValuesInitialised = false;\r\nstatic uint8\tvisibilityTestValues[MAX_FREE_TESTS];\r\n\r\nstruct sVisibilityTestFIFO\r\n{\r\n\tstatic const int\tMAX_FIFO_SIZE\t= 4;\r\n\r\n\tuint32\t\t\t\tm_status_fifo[MAX_FIFO_SIZE];\r\n\tuint32\t\t\t\tm_fifo_index;\r\n\r\n\t\t\t\t\t\tsVisibilityTestFIFO();\r\n\t\t\t\t\t\t~sVisibilityTestFIFO();\r\n\r\n\tstatic uint32\t\tGetFreeTestIndex( void );\r\n\tuint32\t\t\t\tAddStatus( void );\r\n\tuint32\t\t\t\tGetStatus( void );\r\n\r\n\r\n\tprivate:\r\n\r\n\tvoid\t\t\t\tSlideQueue( void );\r\n\tuint32\t\t\t\tm_last_valid_status;\r\n};\r\n\r\n\r\nstruct sLightGlowDetails\r\n{\r\n\tMth::Vector\t\t\tm_pos;\r\n\tfloat\t\t\t\tm_glow_radius;\r\n\tfloat\t\t\t\tm_current_radius;\r\n\tfloat\t\t\t\tm_test_radius;\r\n\tfloat\t\t\t\tm_radius_growth;\r\n\tsVisibilityTestFIFO\tm_visibility_test_fifo;\r\n};\r\n\r\n\r\nstatic Lst::HashTable<sLightGlowDetails> sLightGlowDetailsTable( 8 );\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nBlendModes GetBlendMode( uint32 blend_checksum )\r\n{\r\n\tBlendModes rv = NxXbox::vBLEND_MODE_DIFFUSE;\r\n\r\n\tswitch ( blend_checksum )\r\n\t{\r\n\t\tcase 0x54628ed7:\t\t// Blend\r\n\t\t\trv = NxXbox::vBLEND_MODE_BLEND;\r\n\t\t\tbreak;\r\n\t\tcase 0x02e58c18:\t\t// Add\r\n\t\t\trv = NxXbox::vBLEND_MODE_ADD;\r\n\t\t\tbreak;\r\n\t\tcase 0xa7fd7d23:\t\t// Sub\r\n\t\tcase 0xdea7e576:\t\t// Subtract\r\n\t\t\trv = NxXbox::vBLEND_MODE_SUBTRACT;\r\n\t\t\tbreak;\r\n\t\tcase 0x40f44b8a:\t\t// Modulate\r\n\t\t\trv = NxXbox::vBLEND_MODE_MODULATE;\r\n\t\t\tbreak;\r\n\t\tcase 0x68e77f40:\t\t// Brighten\r\n\t\t\trv = NxXbox::vBLEND_MODE_BRIGHTEN;\r\n\t\t\tbreak;\r\n\t\tcase 0x18b98905:\t\t// FixBlend\r\n\t\t\trv = NxXbox::vBLEND_MODE_BLEND_FIXED;\r\n\t\t\tbreak;\r\n\t\tcase 0xa86285a1:\t\t// FixAdd\r\n\t\t\trv = NxXbox::vBLEND_MODE_ADD_FIXED;\r\n\t\t\tbreak;\r\n\t\tcase 0x0d7a749a:\t\t// FixSub\r\n\t\tcase 0x0eea99ff:\t\t// FixSubtract\r\n\t\t\trv = NxXbox::vBLEND_MODE_SUB_FIXED;\r\n\t\t\tbreak;\r\n\t\tcase 0x90b93703:\t\t// FixModulate\r\n\t\t\trv = NxXbox::vBLEND_MODE_MODULATE_FIXED;\r\n\t\t\tbreak;\r\n\t\tcase 0xb8aa03c9:\t\t// FixBrighten\r\n\t\t\trv = NxXbox::vBLEND_MODE_BRIGHTEN_FIXED;\r\n\t\t\tbreak;\r\n\t\tcase 0x515e298e:\t\t// Diffuse\r\n\t\tcase 0x806fff30:\t\t// None\r\n\t\t\trv = NxXbox::vBLEND_MODE_DIFFUSE;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Illegal blend mode specified. Please use (fix)blend/add/sub/modulate/brighten or diffuse/none.\"));\r\n\t\t\tbreak;\r\n\t}\r\n\treturn rv;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsVisibilityTestFIFO::sVisibilityTestFIFO()\r\n{\r\n\tm_fifo_index\t\t= 0;\r\n\tm_last_valid_status\t= 0;\r\n\r\n\tif( !visibilityTestValuesInitialised )\r\n\t{\r\n\t\tZeroMemory( visibilityTestValues, sizeof( uint8 ) * MAX_FREE_TESTS );\r\n\r\n\t\t// The first index is always reserved.\r\n\t\tvisibilityTestValues[0] = 1;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsVisibilityTestFIFO::~sVisibilityTestFIFO()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sVisibilityTestFIFO::SlideQueue( void )\r\n{\r\n\tDbg_Assert( m_fifo_index > 0 );\r\n\r\n\tm_status_fifo[0] = m_status_fifo[1];\r\n\tm_status_fifo[1] = m_status_fifo[2];\r\n\tm_status_fifo[2] = m_status_fifo[3];\r\n\tm_status_fifo[3] = 0;\r\n\r\n\t--m_fifo_index;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 sVisibilityTestFIFO::GetFreeTestIndex( void )\r\n{\r\n\tfor( uint32 i = 0; i < MAX_FREE_TESTS; ++i )\r\n\t{\r\n\t\tif( visibilityTestValues[i] == 0 )\r\n\t\t{\r\n\t\t\tvisibilityTestValues[i] = 1;\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\tDbg_Assert( 0 );\r\n\treturn MAX_FREE_TESTS - 1;\r\n}\r\n\t\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 sVisibilityTestFIFO::AddStatus( void )\r\n{\r\n\t// If the queue is already full, do nothing.\r\n\tif( m_fifo_index >= ( MAX_FIFO_SIZE - 1 ))\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\r\n\t// Get a free index.\r\n\tuint32 index = GetFreeTestIndex();\r\n\tm_status_fifo[m_fifo_index++] = index;\r\n\r\n\treturn index;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 sVisibilityTestFIFO::GetStatus( void )\r\n{\r\n\tDbg_Assert( m_fifo_index > 0 );\r\n\r\n\tUINT result;\r\n\r\n\t// Get the result from the least recently issued test.\r\n\tHRESULT hr = D3DDevice_GetVisibilityTestResult( m_status_fifo[0], &result, NULL );\r\n\r\n\tif( hr == D3D_OK )\r\n\t{\r\n\t\t// Finished with this test. First mark this test index as no longer in use.\r\n\t\tvisibilityTestValues[m_status_fifo[0]] = 0;\r\n\r\n\t\t// Remove entry from the queue.\r\n\t\tSlideQueue();\r\n\r\n\t\tm_last_valid_status = (uint32)result;\r\n\t\treturn m_last_valid_status;\r\n\t}\r\n\telse if( hr == D3DERR_TESTINCOMPLETE )\r\n\t{\r\n\t\t// Use the last valid status.\r\n\t\treturn m_last_valid_status;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nDWORD get_pixel_shader( sMaterial *p_material )\r\n{\r\n\tconst  int\tPIXEL_SHADER_BUFFER_SIZE\t= 64 * 1024;\r\n\tstatic char pixel_shader_buffer[PIXEL_SHADER_BUFFER_SIZE];\r\n\tstatic int\tpixel_shader_buffer_offset = 0;\r\n\tuint32\t\tblend_modes[4];\r\n\r\n\tbool\t\tmcm = true;\r\n//\tbool\t\tmcm = false;\r\n\tfor( uint32 p = 0; p < p_material->m_passes; ++p )\r\n\t{\r\n\t\tif( !mcm )\r\n\t\t{\r\n\t\t\tif(( p_material->m_color[p][0] != 0.5f ) || ( p_material->m_color[p][1] != 0.5f ) || ( p_material->m_color[p][2] != 0.5f ))\r\n\t\t\t\tmcm = true;\r\n\t\t}\r\n\t\tblend_modes[p] = p_material->m_reg_alpha[p] & sMaterial::BLEND_MODE_MASK;\r\n\t}\r\n\r\n\tif( p_material->m_passes > 1 )\r\n\t{\r\n\t\t// First we build the unique key from the properties of the required shader, to see if it already exists.\r\n\t\tuint32 code = p_material->m_passes;\r\n\t\tfor( uint32 p = 0; p < p_material->m_passes; ++p )\r\n\t\t{\r\n\t\t\tcode |= ( blend_modes[p] << ( 5 * ( p + 1 )));\r\n\t\t}\r\n\r\n\t\t// Integrate the ignore vertex alpha flags.\r\n\t\tuint32 ignore_bf = p_material->GetIgnoreVertexAlphaPasses();\r\n\t\tcode |= ( ignore_bf << 25 );\r\n\r\n\t\t// Check also to see if material color modulation is required.\r\n\t\tif( mcm )\r\n\t\t{\r\n\t\t\tcode |= ( 1 << 30 );\r\n\t\t}\r\n\t\t\r\n\t\t// Check to see if the shader exists, if so just return the shader handle.\r\n\t\tDWORD *p_shader = sPixelShaderTable.GetItem( code );\r\n\t\tif( p_shader )\r\n\t\t{\r\n\t\t\treturn (DWORD)p_shader;\r\n\t\t}\r\n\r\n\t\t// We need to build the shader.\r\n\t\tchar shader_buffer[1024];\r\n\r\n\t\tsprintf( shader_buffer, \"xps.1.1\\n\" );\r\n\r\n\t\tstrcat( shader_buffer, \"tex t0\\n\" );\r\n\t\tstrcat( shader_buffer, \"tex t1\\n\" );\r\n\r\n\t\tswitch( p_material->m_passes )\r\n\t\t{\r\n\t\t\tcase 2:\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( ignore_bf <= 0x03 );\r\n\r\n\t\t\t\tif( mcm )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Modulate texture0 and texture 1 color with pass 0 and pass 1 material color, and place into t0.rgb and t1.rgb.\r\n\t\t\t\t\tstrcat( shader_buffer, \"xmma\t\tt0.rgb,t1.rgb,discard.rgb,t0.rgb,c0.rgb,t1.rgb,c1.rgb\\n\" );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Modulate result color with vertex color.\r\n\t\t\t\t\tstrcat( shader_buffer, \"xmma_x4\t\tr0.rgb,r1.rgb,discard.rgb,t0.rgb,v0.rgb,t1.rgb,v0.rgb\\n\" );\r\n\r\n\t\t\t\t\t// Modulate result alpha with vertex alpha (or constant alpha = 0.5 for those passes that ignore alpha).\r\n\t\t\t\t\tif( ignore_bf == 0x00 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with vertex alpha. Pass1 modulates with vertex alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,v0.a,t1.a,v0.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( ignore_bf == 0x01 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with constant alpha. Pass1 modulates with vertex alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,c4.a,t1.a,v0.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( ignore_bf == 0x02 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with vertex alpha. Pass1 modulates with constant alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,v0.a,t1.a,c4.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( ignore_bf == 0x03 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with constant alpha. Pass1 modulates with constant alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,c4.a,t1.a,c4.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Modulate texture0 and texture1 color with vertex color.\r\n\t\t\t\t\tstrcat( shader_buffer, \"xmma_x2\t\tr0.rgb,r1.rgb,discard.rgb,t0.rgb,v0.rgb,t1.rgb,v0.rgb\\n\" );\r\n\r\n\t\t\t\t\t// Modulate texture0 and tetxure1 alpha with vertex alpha (or constant alpha = 0.5 for those passes that ignore alpha).\r\n\t\t\t\t\tif( ignore_bf == 0x00 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with vertex alpha. Pass1 modulates with vertex alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,v0.a,t1.a,v0.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( ignore_bf == 0x01 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with constant alpha. Pass1 modulates with vertex alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,c4.a,t1.a,v0.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( ignore_bf == 0x02 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with vertex alpha. Pass1 modulates with constant alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,v0.a,t1.a,c4.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( ignore_bf == 0x03 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with constant alpha. Pass1 modulates with constant alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,c4.a,t1.a,c4.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Then deal with the second pass blend.\r\n\t\t\t\tswitch( blend_modes[1] )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase vBLEND_MODE_ADD:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r1.rgb,r1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r1.rgb,c1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r1.rgb,-r1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r1.rgb,-c1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,r1.a,r1.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,c1.a,r1.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul r0.rgb,r0.rgb,r1.a\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul r0.rgb,r0.rgb,c1.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r0.rgb,r1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r0.rgb,c1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,r0.a,r1.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,r0.a,r0.rgb,r1.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_GLOSS_MAP:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul v1.rgb,v1.rgb,t1.a\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tcase 3:\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( ignore_bf <= 0x07 );\r\n\r\n\t\t\t\tstrcat( shader_buffer, \"tex t2\\n\" );\r\n\r\n\t\t\t\tif( mcm )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Modulate texture0 and texture 1 color with pass 0 and pass 1 material color, and place into t0.rgb and t1.rgb.\r\n\t\t\t\t\tstrcat( shader_buffer, \"xmma\t\tt0.rgb,t1.rgb,discard.rgb,t0.rgb,c0.rgb,t1.rgb,c1.rgb\\n\" );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Modulate result color with vertex color.\r\n\t\t\t\t\tstrcat( shader_buffer, \"xmma_x4\t\tr0.rgb,r1.rgb,discard.rgb,t0.rgb,v0.rgb,t1.rgb,v0.rgb\\n\" );\r\n\r\n\t\t\t\t\t// Modulate result alpha with vertex alpha (or constant alpha = 0.5 for those passes that ignore alpha).\r\n\t\t\t\t\tif(( ignore_bf & 0x03 ) == 0x00 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with vertex alpha. Pass1 modulates with vertex alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,v0.a,t1.a,v0.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(( ignore_bf & 0x03 ) == 0x01 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with constant alpha. Pass1 modulates with vertex alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,c4.a,t1.a,v0.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(( ignore_bf & 0x03 ) == 0x02 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with vertex alpha. Pass1 modulates with constant alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,v0.a,t1.a,c4.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(( ignore_bf & 0x03 ) == 0x03 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with constant alpha. Pass1 modulates with constant alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,c4.a,t1.a,c4.a\\n\" );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Modulate texture2 with pass 2 material color.\r\n\t\t\t\t\tstrcat( shader_buffer, \"mul\t\t\tt2.rgb,t2.rgb,c2.rgb\\n\" );\r\n\r\n\t\t\t\t\t// Modulate result color with vertex color.\r\n\t\t\t\t\tstrcat( shader_buffer, \"mul_x4\t\tt2.rgb,t2.rgb,v0.rgb\\n\" );\r\n\r\n\t\t\t\t\t// Modulate result alpha with vertex alpha (or constant alpha = 0.5 for those passes that ignore alpha).\r\n\t\t\t\t\tif(( ignore_bf & 0x04 ) == 0x00 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass2 modulates with vertex alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+mul_x2\t\tt2.a,t2.a,v0.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(( ignore_bf & 0x04 ) == 0x04 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass2 modulates with constant alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+mul_x2\t\tt2.a,t2.a,c4.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Modulate texture0 and texture1 with vertex color.\r\n\t\t\t\t\tstrcat( shader_buffer, \"xmma_x2\tr0,r1,discard,t0,v0,t1,v0\\n\" );\r\n\r\n\t\t\t\t\t// Modulate texture2 with vertex color.\r\n\t\t\t\t\tstrcat( shader_buffer, \"mul_x2\tt2,t2,v0\\n\" );\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Then deal with the second pass blend.\r\n\t\t\t\tswitch( blend_modes[1] )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase vBLEND_MODE_ADD:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r1.rgb,r1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r1.rgb,c1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r1.rgb,-r1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r1.rgb,-c1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,r1.a,r1.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp\tr0.rgb,c1.a,r1.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul r0.rgb,r0.rgb,r1.a\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul r0.rgb,r0.rgb,c1.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r0.rgb,r1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r0.rgb,c1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,r0.a,r1.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,r0.a,r0.rgb,r1.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_GLOSS_MAP:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul v1.rgb,v1.rgb,t1.a\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// Then deal with the third pass blend.\r\n\t\t\t\tswitch( blend_modes[2] )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase vBLEND_MODE_ADD:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,t2.rgb,t2.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,t2.rgb,c2.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,t2.rgb,-t2.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,t2.rgb,-c2.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,t2.a,t2.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp\tr0.rgb,c2.a,t2.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul r0.rgb,r0.rgb,t2.a\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul r0.rgb,r0.rgb,c2.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r0.rgb,t2.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r0.rgb,c2.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,r1.a,t2.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,r1.a,r0.rgb,t2.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_GLOSS_MAP:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul v1.rgb,v1.rgb,t2.a\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\r\n\t\t\tcase 4:\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( ignore_bf <= 0x0F );\r\n\r\n\t\t\t\tstrcat( shader_buffer, \"tex t2\\n\" );\r\n\t\t\t\tstrcat( shader_buffer, \"tex t3\\n\" );\r\n\r\n\t\t\t\tif( mcm )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Modulate texture0 and texture 1 color with pass 0 and pass 1 material color, and place into t0.rgb and t1.rgb.\r\n\t\t\t\t\tstrcat( shader_buffer, \"xmma\t\tt0.rgb,t1.rgb,discard.rgb,t0.rgb,c0.rgb,t1.rgb,c1.rgb\\n\" );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Modulate result color with vertex color.\r\n\t\t\t\t\tstrcat( shader_buffer, \"xmma_x4\t\tr0.rgb,r1.rgb,discard.rgb,t0.rgb,v0.rgb,t1.rgb,v0.rgb\\n\" );\r\n\r\n\t\t\t\t\t// Modulate result alpha with vertex alpha (or constant alpha = 0.5 for those passes that ignore alpha).\r\n\t\t\t\t\tif(( ignore_bf & 0x03 ) == 0x00 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with vertex alpha. Pass1 modulates with vertex alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,v0.a,t1.a,v0.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(( ignore_bf & 0x03 ) == 0x01 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with constant alpha. Pass1 modulates with vertex alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,c4.a,t1.a,v0.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(( ignore_bf & 0x03 ) == 0x02 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with vertex alpha. Pass1 modulates with constant alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,v0.a,t1.a,c4.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(( ignore_bf & 0x03 ) == 0x03 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass0 modulates with constant alpha. Pass1 modulates with constant alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tr0.a,r1.a,discard.a,t0.a,c4.a,t1.a,c4.a\\n\" );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Modulate texture2 and texture 3 color with pass 2 and pass 3 material color, and place into t0.rgb and t1.rgb.\r\n\t\t\t\t\tstrcat( shader_buffer, \"xmma\t\tt2.rgb,t3.rgb,discard.rgb,t2.rgb,c2.rgb,t3.rgb,c3.rgb\\n\" );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Modulate result color with vertex color.\r\n\t\t\t\t\tstrcat( shader_buffer, \"xmma_x4\t\tt2.rgb,t3.rgb,discard.rgb,t2.rgb,v0.rgb,t3.rgb,v0.rgb\\n\" );\r\n\r\n\t\t\t\t\t// Modulate result alpha with vertex alpha (or constant alpha = 0.5 for those passes that ignore alpha).\r\n\t\t\t\t\tif(( ignore_bf & 0x0C ) == 0x00 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass2 modulates with vertex alpha. Pass3 modulates with vertex alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tt2.a,t3.a,discard.a,t2.a,v0.a,t3.a,v0.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(( ignore_bf & 0x0C ) == 0x04 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass2 modulates with constant alpha. Pass3 modulates with vertex alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tt2.a,t3.a,discard.a,t2.a,c4.a,t3.a,v0.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(( ignore_bf & 0x0C ) == 0x08 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass2 modulates with vertex alpha. Pass3 modulates with constant alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tt2.a,t3.a,discard.a,t2.a,v0.a,t3.a,c4.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(( ignore_bf & 0x0C ) == 0x0C )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Pass2 modulates with constant alpha. Pass3 modulates with constant alpha.\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"+xmma_x2\tt2.a,t3.a,discard.a,t2.a,c4.a,t3.a,c4.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Modulate texture0 and texture1 with vertex color.\r\n\t\t\t\t\tstrcat( shader_buffer, \"xmma_x2\t\tr0,r1,discard,t0,v0,t1,v0\\n\" );\r\n\r\n\t\t\t\t\t// Modulate texture2 and texture3 with vertex color.\r\n\t\t\t\t\tstrcat( shader_buffer, \"xmma_x2\t\tt2,t3,discard,t2,v0,t3,v0\\n\" );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// Then deal with the second pass blend.\r\n\t\t\t\tswitch( blend_modes[1] )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase vBLEND_MODE_ADD:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r1.rgb,r1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r1.rgb,c1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r1.rgb,-r1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r1.rgb,-c1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,r1.a,r1.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,c1.a,r1.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul r0.rgb,r0.rgb,r1.a\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul r0.rgb,r0.rgb,c1.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r0.rgb,r1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r0.rgb,c1.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,r0.a,r1.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,r0.a,r0.rgb,r1.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_GLOSS_MAP:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul v1.rgb,v1.rgb,t1.a\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Then deal with the third pass blend.\r\n\t\t\t\tswitch( blend_modes[2] )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase vBLEND_MODE_ADD:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,t2.rgb,t2.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,t2.rgb,c2.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,t2.rgb,-t2.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,t2.rgb,-c2.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,t2.a,t2.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp\tr0.rgb,c2.a,t2.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul r0.rgb,r0.rgb,t2.a\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul r0.rgb,r0.rgb,c2.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r0.rgb,t2.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r0.rgb,c2.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,r1.a,t2.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,r1.a,r0.rgb,t2.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_GLOSS_MAP:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul v1.rgb,v1.rgb,t2.a\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// Then deal with the fourth pass blend.\r\n\t\t\t\tswitch( blend_modes[3] )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase vBLEND_MODE_ADD:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,t3.rgb,t3.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,t3.rgb,c3.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,t3.rgb,-t3.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,t3.rgb,-c3.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,t3.a,t3.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp\tr0.rgb,c3.a,t3.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul r0.rgb,r0.rgb,t3.a\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul r0.rgb,r0.rgb,c3.a\\n\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r0.rgb,t3.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mad r0.rgb,r0.rgb,c3.a,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,t2.a,t3.rgb,r0.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"lrp r0.rgb,t2.a,r0.rgb,t3.rgb\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase vBLEND_MODE_GLOSS_MAP:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( shader_buffer, \"mul v1.rgb,v1.rgb,t3.a\\n\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Final combiner.\r\n\t\tstrcat( shader_buffer, \"xfc prod, fog.rgb, sum, zero, 1 - fog.a, c4, r0.a\\n\" );\r\n\r\n\t\tLPXGBUFFER pCompiledShader;\r\n\t\tHRESULT hr = XGAssembleShader(\t\"autogen.ps\",\t\t\t\t\t\t\t\t\t// Source file name, used in error messages.\r\n\t\t\t\t\t\t\t\t\t\tshader_buffer,\t\t\t\t\t\t\t\t\t// A pointer to the source data.\r\n\t\t\t\t\t\t\t\t\t\tstrlen( shader_buffer ),\t\t\t\t\t\t// The source data length.\r\n\t\t\t\t\t\t\t\t\t\tSASM_SKIPPREPROCESSOR | SASM_SKIPVALIDATION,\t// SASM_xxx flags. See xgraphics.h for a complete list.\r\n\t\t\t\t\t\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t\t\t\t// If constants are declared in the shader, they are written here. Pass NULL if you don't care.\r\n\t\t\t\t\t\t\t\t\t\t&pCompiledShader,\t\t\t\t\t\t\t\t// The shader microcode is written here. Pass NULL if you don't care.\r\n\t\t\t\t\t\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t\t\t\t// Errors are written here. Pass NULL if you don't care.\r\n\t\t\t\t\t\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t\t\t\t// A human-readable listing is written here. Pass NULL if you don't want it.\r\n\t\t\t\t\t\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t\t\t\t// Used by the preprocessor. Can be NULL if you don't use #include in your source file.\r\n\t\t\t\t\t\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t\t\t\t// Passed unmodified to the pResolver function.\r\n\t\t\t\t\t\t\t\t\t\tNULL );\t\t\t\t\t\t\t\t\t\t\t// Returns the type of shader that was assembled. Pass NULL if you don't care.\r\n\t\tDbg_Assert( hr == S_OK );\r\n\t\t\r\n\t\t// Copy the microcode into our buffer.\r\n\t\tDbg_Assert( pixel_shader_buffer_offset + pCompiledShader->size < PIXEL_SHADER_BUFFER_SIZE );\r\n\t\tCopyMemory( pixel_shader_buffer + pixel_shader_buffer_offset, pCompiledShader->pData, pCompiledShader->size );\r\n\t\t\r\n\t\t// Generate a handle to this shader.\r\n\t\tDWORD shader_handle;\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( pixel_shader_buffer + pixel_shader_buffer_offset ), &shader_handle );\r\n\r\n\t\t// Update the buffer offset now we have copied a new shader into the buffer.\r\n\t\tpixel_shader_buffer_offset += pCompiledShader->size;\r\n\r\n\t\t// This was allocated during XGAssembleShader().\r\n\t\tXGBuffer_Release( pCompiledShader );\r\n\r\n\t\t// Place the shader handle in the table.\r\n\t\tsPixelShaderTable.PutItem( code, (DWORD*)shader_handle );\r\n\t\t\r\n\t\t// Return the handle.\r\n\t\treturn shader_handle;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid create_pixel_shaders( void )\r\n{\r\n\tstatic bool created_shaders = false;\r\n\tif( !created_shaders )\r\n\t{\r\n\t\tcreated_shaders = true;\r\n\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShader0PixelShader[0] ),\t\t\t\t\t\t&PixelShader0 );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShader0IVAPixelShader[0] ),\t\t\t\t\t&PixelShader0IVA );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShader1PixelShader[0] ),\t\t\t\t\t\t&PixelShader1 );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShader2PixelShader[0] ),\t\t\t\t\t\t&PixelShader2 );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShader3PixelShader[0] ),\t\t\t\t\t\t&PixelShader3 );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShader4PixelShader[0] ),\t\t\t\t\t\t&PixelShader4 );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShader5PixelShader[0] ),\t\t\t\t\t\t&PixelShader5 );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShaderBrightenPixelShader[0] ),\t\t\t\t&PixelShaderBrighten );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShaderBrightenIVAPixelShader[0] ),\t\t\t&PixelShaderBrightenIVA );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShaderFocusBlurPixelShader[0] ),\t\t\t\t&PixelShaderFocusBlur );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShaderFocusIntegratePixelShader[0] ),\t\t\t&PixelShaderFocusIntegrate );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShaderFocusLookupIntegratePixelShader[0] ),\t&PixelShaderFocusLookupIntegrate );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShaderNULLPixelShader[0] ),\t\t\t\t\t&PixelShaderNULL );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShaderPointSpritePixelShader[0] ),\t\t\t&PixelShaderPointSprite );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShaderBumpWaterPixelShader[0] ),\t\t\t\t&PixelShaderBumpWater );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwPixelShader_ShadowBufferPixelShader[0] ),\t\t\t&PixelShader_ShadowBuffer );\r\n\t\tD3DDevice_CreatePixelShader((D3DPIXELSHADERDEF*)( &dwShadowBufferStaticGeomPSPixelShader[0] ),\t\t\t&ShadowBufferStaticGeomPS );\r\n\t\r\n\t\t// Shouldn't be doing this here!\r\n\t\tpTextureProjectionDetailsTable = new Lst::HashTable< sTextureProjectionDetails >( 8 );\r\n\r\n#\t\tif 0\r\n\t\t// Light glow test code.\r\n\t\tsLightGlowDetails *p_details = new sLightGlowDetails;\r\n\t\tp_details->m_pos.Set( 0.0f, 48.0f, 0.0f );\r\n\t\tp_details->m_glow_radius\t= 24.0f;\r\n\t\tp_details->m_current_radius\t= 0.0f;\r\n\t\tp_details->m_test_radius\t= 2.0f;\r\n\t\tp_details->m_radius_growth\t= 0.2f;\r\n\t\tsLightGlowDetailsTable.PutItem( (uint32)p_details, p_details );\r\n\r\n\t\tp_details = new sLightGlowDetails;\r\n\t\tp_details->m_pos.Set( 60.0f, 48.0f, 0.0f );\r\n\t\tp_details->m_glow_radius\t= 24.0f;\r\n\t\tp_details->m_current_radius\t= 0.0f;\r\n\t\tp_details->m_test_radius\t= 2.0f;\r\n\t\tp_details->m_radius_growth\t= 0.2f;\r\n\t\tsLightGlowDetailsTable.PutItem( (uint32)p_details, p_details );\r\n\r\n\t\tp_details = new sLightGlowDetails;\r\n\t\tp_details->m_pos.Set( -60.0f, 48.0f, 0.0f );\r\n\t\tp_details->m_glow_radius\t= 24.0f;\r\n\t\tp_details->m_current_radius\t= 0.0f;\r\n\t\tp_details->m_test_radius\t= 2.0f;\r\n\t\tp_details->m_radius_growth\t= 0.2f;\r\n\t\tsLightGlowDetailsTable.PutItem( (uint32)p_details, p_details );\r\n#\t\tendif\r\n\t}\r\n}\r\n\t\r\n\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid GetPixelShader( sMaterial *p_material, uint32 *p_pixel_shader_id )\r\n{\r\n\tif( p_material->m_passes == 1 )\r\n\t{\r\n\t\t// There are only 2 shader for single pass materials, depending on whether a texture is required.\r\n\t\tif( p_material->mp_tex[0] == NULL )\r\n\t\t{\r\n\t\t\t*p_pixel_shader_id = PixelShader1;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tuint32 ignore_bf = p_material->GetIgnoreVertexAlphaPasses();\r\n\r\n\t\t\tif(( p_material->m_reg_alpha[0] & sMaterial::BLEND_MODE_MASK ) == vBLEND_MODE_BRIGHTEN )\r\n\t\t\t{\r\n\t\t\t\t// The single pass mode is brighten, which requires special handling.\r\n\t\t\t\tif( ignore_bf == 0 )\r\n\t\t\t\t\t*p_pixel_shader_id = PixelShaderBrighten;\r\n\t\t\t\telse\r\n\t\t\t\t\t*p_pixel_shader_id = PixelShaderBrightenIVA;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( ignore_bf == 0 )\r\n\t\t\t\t\t*p_pixel_shader_id = PixelShader0;\r\n\t\t\t\telse\r\n\t\t\t\t\t*p_pixel_shader_id = PixelShader0IVA;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Get the pixel shader.\r\n\t\t*p_pixel_shader_id = get_pixel_shader( p_material );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid set_texture( uint32 pass, IDirect3DTexture8 *p_texture, IDirect3DPalette8 *p_palette )\r\n{\r\n\tif((IDirect3DTexture8*)( EngineGlobals.p_texture[pass] ) != p_texture )\r\n\t{\r\n\t\t// Use SwitchTexture() whenever possible. Cannot switch from or to a NULL texture. Also cannot\r\n\t\t// switch to a liner texture (in this case the calling code should perform a set_texture( NULL )\r\n\t\t// call first, to force D3DDevice_SetTexture() to be called for the linear texture.\r\n\t\tif(( p_texture != NULL ) && ( EngineGlobals.p_texture[pass] != NULL ))\r\n\t\t{\r\n\t\t\tEngineGlobals.p_Device->SwitchTexture( pass, (LPDIRECT3DBASETEXTURE8)( p_texture ));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tD3DDevice_SetTexture( pass, (LPDIRECT3DBASETEXTURE8)( p_texture ));\r\n\t\t}\r\n\r\n\t\tif( p_palette )\r\n\t\t{\r\n\t\t\tD3DDevice_SetPalette( pass, p_palette );\r\n\t\t}\r\n\r\n\t\tEngineGlobals.p_texture[pass] = p_texture;\r\n\t}\r\n}\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid set_blend_mode( uint32 mode )\r\n{\r\n\tif( NxXbox::EngineGlobals.blend_mode_override )\r\n\t{\r\n\t\tmode = NxXbox::EngineGlobals.blend_mode_override;\r\n\t}\r\n\r\n\t// Only do something if the blend mode is changing.\r\n\tif( mode != EngineGlobals.blend_mode_value )\r\n\t{\r\n\t\t// Low 24 bits contain the mode, high 8 bits contain the fixed alpha value.\r\n\t\tif(( mode & 0x00FFFFFFUL ) != ( EngineGlobals.blend_mode_value & 0x00FFFFFFUL ))\r\n\t\t{\r\n\t\t\t// For additive and subtractive, we set the fog color to black.\r\n\t\t\tif( EngineGlobals.fog_enabled )\r\n\t\t\t{\r\n\t\t\t\tif((( mode & 0x00FFFFFFUL ) >= vBLEND_MODE_ADD ) && (( mode & 0x00FFFFFFUL ) <= vBLEND_MODE_SUB_FIXED ))\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_FOGCOLOR, 0x00000000UL );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_FOGCOLOR, NxXbox::EngineGlobals.fog_color );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tint blend_op, src_blend, dest_blend;\r\n\r\n\t\t\tswitch( mode & 0x00FFFFFFUL )\r\n\t\t\t{\r\n\t\t\t\tcase vBLEND_MODE_DIFFUSE:\t\t\t// ( 0 - 0 ) * 0 + Src\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_ONE;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_ZERO;\r\n\t\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_ADD:\t\t\t\t// ( Src - 0 ) * Src + Dst\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_SRCALPHA;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_ONE;\r\n\t\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_ADD_FIXED:\t\t\t// ( Src - 0 ) * Fixed + Dst\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_CONSTANTALPHA;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_ONE;\r\n\t\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_SUBTRACT:\t\t\t// ( 0 - Src ) * Src + Dst\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_REVSUBTRACT;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_SRCALPHA;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_ONE;\r\n\t\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_SUB_FIXED:\t\t\t// ( 0 - Src ) * Fixed + Dst\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_REVSUBTRACT;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_CONSTANTALPHA;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_ONE;\r\n\t\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_BLEND:\t\t\t\t// ( Src - Dst ) * Src + Dst\t\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_SRCALPHA;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_INVSRCALPHA;\r\n\t\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_BLEND_FIXED:\t\t// ( Src - Dst ) * Fixed + Dst\t\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_CONSTANTALPHA;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_INVCONSTANTALPHA;\r\n\t\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_MODULATE:\t\t\t// ( Dst - 0 ) * Src + 0\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_ZERO;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_SRCALPHA;\r\n\t\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\t// ( Dst - 0 ) * Fixed + 0\t\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_ZERO;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_CONSTANTALPHA;\r\n\t\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_BRIGHTEN:\t\t\t// ( Dst - 0 ) * Src + Dst\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_DESTCOLOR;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_ONE;\r\n\t\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\t// ( Dst - 0 ) * Fixed + Dst\t\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_DESTCOLOR;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_CONSTANTALPHA;\r\n\t\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_GLOSS_MAP:\r\n\t\t\t\t{\r\n\t\t\t\t\t// Treat as diffuse for now.\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_ONE;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_ZERO;\r\n\t\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_MODULATE_COLOR:\t// ( Dst - 0 ) * Src(col) + 0 - specially for the shadow.\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_ZERO;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_SRCCOLOR;\r\n\t\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\t\t\t{\r\n\t\t\t\t\t// Meaningless unless destination alpha is enabled.\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_DESTALPHA;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_INVDESTALPHA;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\t\t\t{\r\n\t\t\t\t\t// Meaningless unless destination alpha is enabled.\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_INVDESTALPHA;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_DESTALPHA;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase vBLEND_MODE_ONE_INV_SRC_ALPHA:\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_op\t= D3DBLENDOP_ADD;\r\n\t\t\t\t\tsrc_blend\t= D3DBLEND_ONE;\r\n\t\t\t\t\tdest_blend\t= D3DBLEND_INVSRCALPHA;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Now set the values if they have changed.\r\n\t\t\tif( blend_op != EngineGlobals.blend_op )\r\n\t\t\t{\r\n\t\t\t\tD3DDevice_SetRenderState( D3DRS_BLENDOP, blend_op );\r\n\t\t\t\tEngineGlobals.blend_op\t= blend_op;\r\n\t\t\t}\r\n\t\t\tif( src_blend != EngineGlobals.src_blend )\r\n\t\t\t{\r\n\t\t\t\tD3DDevice_SetRenderState( D3DRS_SRCBLEND, src_blend );\r\n\t\t\t\tEngineGlobals.src_blend\t= src_blend;\r\n\t\t\t}\r\n\t\t\tif( dest_blend != EngineGlobals.dest_blend )\r\n\t\t\t{\r\n\t\t\t\tD3DDevice_SetRenderState( D3DRS_DESTBLEND, dest_blend );\r\n\t\t\t\tEngineGlobals.dest_blend = dest_blend;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Change the fixed alpha value if different.\r\n\t\tif(( mode & 0xFF000000UL ) != ( EngineGlobals.blend_mode_value & 0xFF000000UL ))\r\n\t\t{\r\n\t\t\tuint32 fixed_alpha\t= mode & 0xFF000000UL;\r\n\t\t\tfixed_alpha\t\t\t= fixed_alpha >= 0x80000000UL ? 0xFF000000UL : ( fixed_alpha << 1 );\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_BLENDCOLOR,\tfixed_alpha );\r\n\t\t}\r\n\r\n\t\t// Set the new blend mode value.\r\n\t\tEngineGlobals.blend_mode_value\t= mode;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid set_vertex_shader( DWORD shader_id )\r\n{\r\n\tif( EngineGlobals.vertex_shader_override == 0 )\r\n\t{\r\n\t\tif( EngineGlobals.vertex_shader_id != shader_id )\r\n\t\t{\r\n\t\t\t// Set vertex shader.\r\n\t\t\tD3DDevice_SetVertexShader( shader_id );\r\n\t\t\tEngineGlobals.vertex_shader_id = shader_id;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid set_pixel_shader( uint32 shader_id )\r\n{\r\n\tif( EngineGlobals.pixel_shader_override == 0 )\r\n\t{\r\n\t\tif( EngineGlobals.pixel_shader_id != shader_id )\r\n\t\t{\r\n\t\t\t// Set pixel shader.\r\n\t\t\tD3DDevice_SetPixelShader( shader_id );\r\n\t\t\tEngineGlobals.pixel_shader_id = shader_id;\r\n\r\n\t\t\t// Changing pixel shader invalidates the constants, so we need to upload.\r\n\t\t\tEngineGlobals.upload_pixel_shader_constants = true;\r\n\t\t}\r\n\t\t\t\r\n\t\t// Upload any pixel shader constants if required.\r\n\t\tif( EngineGlobals.upload_pixel_shader_constants && ( shader_id > 0 ))\r\n\t\t{\r\n\t\t\tD3DDevice_SetPixelShaderConstant( 0, EngineGlobals.pixel_shader_constants, 5 );\r\n\t\t}\r\n\t}\r\n\r\n\t// Want to clear this field even if the override is set, since otherwise it will persist and cause problems later.\r\n\tEngineGlobals.upload_pixel_shader_constants = false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid set_pixel_shader( uint32 shader_id, uint32 num_passes )\r\n{\r\n\tif( EngineGlobals.pixel_shader_override == 0 )\r\n\t{\r\n\t\tif( EngineGlobals.pixel_shader_id != shader_id )\r\n\t\t{\r\n\t\t\t// Set pixel shader.\r\n\t\t\tD3DDevice_SetPixelShader( shader_id );\r\n\t\t\tEngineGlobals.pixel_shader_id = shader_id;\r\n\r\n\t\t\t// Changing pixel shader invalidates the constants, so we need to upload.\r\n\t\t\tEngineGlobals.upload_pixel_shader_constants = true;\r\n\t\t}\r\n\t\t\t\r\n\t\t// Upload any pixel shader constants if required.\r\n\t\tif( EngineGlobals.upload_pixel_shader_constants && ( shader_id > 0 ))\r\n\t\t{\r\n\t\t\tD3DDevice_SetPixelShaderConstant( 0, &EngineGlobals.pixel_shader_constants[0], num_passes );\r\n\t\t\tD3DDevice_SetPixelShaderConstant( 4, &EngineGlobals.pixel_shader_constants[16], 1 );\r\n\t\t}\r\n\t}\r\n\r\n\t// Want to clear this field even if the override is set, since otherwise it will persist and cause problems later.\r\n\tEngineGlobals.upload_pixel_shader_constants = false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid set_render_state( uint32 type, uint32 state )\r\n{\r\n\tswitch( type )\r\n\t{\r\n\t\tcase RS_ZBIAS:\r\n\t\t{\r\n\t\t\tif( state != EngineGlobals.z_bias )\r\n\t\t\t{\r\n\t\t\t\tEngineGlobals.z_bias = state;\r\n\t\t\t\tD3DDevice_SetRenderState( D3DRS_ZBIAS, state );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase RS_CULLMODE:\r\n\t\t{\r\n\t\t\tif( state != EngineGlobals.cull_mode )\r\n\t\t\t{\r\n\t\t\t\tEngineGlobals.cull_mode = state;\r\n\t\t\t\tD3DDevice_SetRenderState( D3DRS_CULLMODE, state );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase RS_ALPHABLENDENABLE:\r\n\t\t{\r\n\t\t\tif( state != EngineGlobals.alpha_blend_enable )\r\n\t\t\t{\r\n\t\t\t\tEngineGlobals.alpha_blend_enable = state;\r\n\t\t\t\tD3DDevice_SetRenderState( D3DRS_ALPHABLENDENABLE, ( state > 0 ) ? TRUE : FALSE );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase RS_ALPHATESTENABLE:\r\n\t\t{\r\n\t\t\tif( state != EngineGlobals.alpha_test_enable )\r\n\t\t\t{\r\n\t\t\t\tEngineGlobals.alpha_test_enable = state;\r\n\t\t\t\tD3DDevice_SetRenderState( D3DRS_ALPHATESTENABLE, ( state > 0 ) ? TRUE : FALSE );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase RS_ZWRITEENABLE:\r\n\t\t{\r\n\t\t\tif( state > 0 )\r\n\t\t\t{\r\n\t\t\t\tif( EngineGlobals.z_write_enabled == FALSE )\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_ZWRITEENABLE, TRUE );\r\n\t\t\t\t\tEngineGlobals.z_write_enabled = TRUE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( EngineGlobals.z_write_enabled == TRUE )\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_ZWRITEENABLE, FALSE );\r\n\t\t\t\t\tEngineGlobals.z_write_enabled = FALSE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase RS_ZTESTENABLE:\r\n\t\t{\r\n\t\t\tif( state > 0 )\r\n\t\t\t{\r\n\t\t\t\tif( EngineGlobals.z_test_enabled == FALSE )\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );\r\n\t\t\t\t\tEngineGlobals.z_test_enabled = TRUE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( EngineGlobals.z_test_enabled == TRUE )\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_ZFUNC, D3DCMP_ALWAYS );\r\n\t\t\t\t\tEngineGlobals.z_test_enabled = FALSE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase RS_ALPHACUTOFF:\r\n\t\t{\r\n\t\t\t// Convert from state (where 1 means \"render all pixels with alpha 1 or higher\") to the D3D.\r\n\t\t\t// Also, if alpha cutoff is 1 or greater, enable alphakill, which can in some cases provide an earlier\r\n\t\t\t// rejection of the pixel.\r\n\t\t\tif( state != EngineGlobals.alpha_ref )\r\n\t\t\t{\r\n\t\t\t\tEngineGlobals.alpha_ref = state;\r\n\t\t\t\tif( state > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_ALPHAREF,\t\t\t\tstate );\r\n\r\n\t\t\t\t\t// Enable alpha testing.\r\n\t\t\t\t\tif( EngineGlobals.alpha_test_enable == 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_ALPHATESTENABLE,\tTRUE );\r\n\t\t\t\t\t\tEngineGlobals.alpha_test_enable = 1;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_ALPHAKILL,\tD3DTALPHAKILL_ENABLE );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Disable alpha testing.\r\n\t\t\t\t\tif( EngineGlobals.alpha_test_enable > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_ALPHATESTENABLE,\tFALSE );\r\n\t\t\t\t\t\tEngineGlobals.alpha_test_enable = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_ALPHAKILL,\tD3DTALPHAKILL_DISABLE );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase RS_SPECULARENABLE:\r\n\t\t{\r\n\t\t\tif( state != EngineGlobals.specular_enabled )\r\n\t\t\t{\r\n\t\t\t\tEngineGlobals.specular_enabled = state;\r\n\r\n\t\t\t\tif( state > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_SPECULARENABLE, TRUE );\r\n\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_LOCALVIEWER, TRUE );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_SPECULARENABLE, FALSE );\r\n\t\t\t\t\tD3DDevice_SetRenderState( D3DRS_LOCALVIEWER, FALSE );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase RS_FOGENABLE:\r\n\t\t{\r\n\t\t\tif( state != EngineGlobals.fog_enabled )\r\n\t\t\t{\r\n\t\t\t\tEngineGlobals.fog_enabled = state;\r\n\t\t\t\tD3DDevice_SetRenderState( D3DRS_FOGENABLE, ( state > 0 ) ? TRUE : FALSE );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase RS_UVADDRESSMODE0:\r\n\t\tcase RS_UVADDRESSMODE1:\r\n\t\tcase RS_UVADDRESSMODE2:\r\n\t\tcase RS_UVADDRESSMODE3:\r\n\t\t{\r\n\t\t\tint pass = type - RS_UVADDRESSMODE0;\r\n\t\t\tif(( state & 0xFFFFUL ) != ( EngineGlobals.uv_addressing[pass] & 0xFFFFUL ))\r\n\t\t\t{\r\n\t\t\t\tswitch( state & 0xFFFFUL )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase 0x0000U:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( pass, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase 0x0001U:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( pass, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase 0x0002U:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( pass, D3DTSS_ADDRESSU, D3DTADDRESS_BORDER );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tEngineGlobals.uv_addressing[pass] = ( EngineGlobals.uv_addressing[pass] & 0xFFFF0000UL ) | ( state & 0xFFFFUL );\r\n\t\t\t}\r\n\r\n\t\t\tif(( state & 0xFFFF0000UL ) != ( EngineGlobals.uv_addressing[pass] & 0xFFFF0000UL ))\r\n\t\t\t{\r\n\t\t\t\tswitch( state & 0xFFFF0000UL )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase 0x00000000UL:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( pass, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase 0x00010000UL:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( pass, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase 0x00020000UL:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( pass, D3DTSS_ADDRESSV, D3DTADDRESS_BORDER );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tEngineGlobals.uv_addressing[pass] = ( EngineGlobals.uv_addressing[pass] & 0x0000FFFFUL ) | ( state & 0xFFFF0000UL );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase RS_MIPLODBIASPASS0:\r\n\t\tcase RS_MIPLODBIASPASS1:\r\n\t\tcase RS_MIPLODBIASPASS2:\r\n\t\tcase RS_MIPLODBIASPASS3:\r\n\t\t{\r\n\t\t\tint pass = type - RS_MIPLODBIASPASS0;\r\n\t\t\tif( state != EngineGlobals.mip_map_lod_bias[pass] )\r\n\t\t\t{\r\n\t\t\t\tD3DDevice_SetTextureStageState( pass, D3DTSS_MIPMAPLODBIAS, state );\r\n\t\t\t\tEngineGlobals.mip_map_lod_bias[pass] = state;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase RS_MINMAGFILTER0:\r\n\t\tcase RS_MINMAGFILTER1:\r\n\t\tcase RS_MINMAGFILTER2:\r\n\t\tcase RS_MINMAGFILTER3:\r\n\t\t{\r\n\t\t\tint pass = type - RS_MINMAGFILTER0;\r\n\r\n\t\t\t// Magnification filter.\r\n\t\t\tstate = state & 0xFFFF0000UL;\r\n\t\t\tif( state != EngineGlobals.min_mag_filter[pass] )\r\n\t\t\t{\r\n\t\t\t\tif( state == 0x00000000UL )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Point.\r\n\t\t\t\t\tD3DDevice_SetTextureStageState( pass, D3DTSS_MAGFILTER, D3DTEXF_POINT );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Linear.\r\n\t\t\t\t\tD3DDevice_SetTextureStageState( pass, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );\r\n\t\t\t\t}\r\n\t\t\t\tEngineGlobals.min_mag_filter[pass] = state;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid create_texture_projection_details( sTexture *p_texture, Nx::CXboxModel *p_model, sScene *p_scene )\r\n{\r\n\tsTextureProjectionDetails *p_details = new sTextureProjectionDetails;\r\n\r\n\tp_details->p_model\t\t= p_model;\r\n\tp_details->p_scene\t\t= p_scene;\r\n\tp_details->p_texture\t= p_texture;\r\n\t\r\n\tXGMatrixIdentity( &p_details->view_matrix );\r\n\tXGMatrixIdentity( &p_details->projection_matrix );\r\n\t\r\n\tpTextureProjectionDetailsTable->PutItem((uint32)p_texture, p_details );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid destroy_texture_projection_details( sTexture *p_texture )\r\n{\r\n\tsTextureProjectionDetails *p_details = pTextureProjectionDetailsTable->GetItem((uint32)p_texture );\r\n\tif( p_details )\r\n\t{\r\n\t\tpTextureProjectionDetailsTable->FlushItem((uint32)p_texture );\r\n\t\tdelete p_details;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid set_texture_projection_camera( sTexture *p_texture, XGVECTOR3 *p_pos, XGVECTOR3 *p_at )\r\n{\r\n\tsTextureProjectionDetails *p_details = pTextureProjectionDetailsTable->GetItem((uint32)p_texture );\r\n\tif( p_details )\r\n\t{\r\n\t\t// Check for 'straight down' vector.\r\n\t\tif(( p_pos->x == p_at->x ) && ( p_pos->z == p_at->z ))\r\n\t\t{\r\n\t\t\tXGMatrixLookAtRH( &p_details->view_matrix, p_pos, p_at, &XGVECTOR3( 0.0f, 0.0f, 1.0f ));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tXGMatrixLookAtRH( &p_details->view_matrix, p_pos, p_at, &XGVECTOR3( 0.0f, 1.0f, 0.0f ));\r\n\t\t}\r\n\t\tXGMatrixOrthoRH( &p_details->projection_matrix, 96.0f, 96.0f, 1.0f, 128.0f );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// MSM PERFCHANGE - added scale.\r\nvoid set_camera( Mth::Matrix *p_matrix, Mth::Vector *p_position, float screen_angle, float aspect_ratio, bool render_at_infinity )\r\n{\r\n\tEngineGlobals.cam_position.x\t= p_position->GetX();\r\n\tEngineGlobals.cam_position.y\t= p_position->GetY();\r\n\tEngineGlobals.cam_position.z\t= p_position->GetZ();\r\n\t\r\n\tEngineGlobals.cam_at.x\t\t\t= p_matrix->GetAt().GetX();\r\n\tEngineGlobals.cam_at.y\t\t\t= p_matrix->GetAt().GetY();\r\n\tEngineGlobals.cam_at.z\t\t\t= p_matrix->GetAt().GetZ();\r\n\t\r\n\tEngineGlobals.cam_up.x\t\t\t= p_matrix->GetUp().GetX();\r\n\tEngineGlobals.cam_up.y\t\t\t= p_matrix->GetUp().GetY();\r\n\tEngineGlobals.cam_up.z\t\t\t= p_matrix->GetUp().GetZ();\r\n\t\r\n\tXGMatrixIdentity( &EngineGlobals.world_matrix );\r\n\r\n\t// XGMatrixLookAtRH() takes an 'at' position rather than a direction, so we need it relative to the camera position.\r\n\tXGVECTOR3\tat;\r\n\tat.x\t= EngineGlobals.cam_position.x - EngineGlobals.cam_at.x;\r\n\tat.y\t= EngineGlobals.cam_position.y - EngineGlobals.cam_at.y;\r\n\tat.z\t= EngineGlobals.cam_position.z - EngineGlobals.cam_at.z;\r\n\tXGMatrixLookAtRH( &EngineGlobals.view_matrix, &EngineGlobals.cam_position, &at, &EngineGlobals.cam_up );\r\n\r\n\tEngineGlobals.near_plane\t= 2.0f;\r\n\tEngineGlobals.far_plane\t\t= 32000.0f;\r\n\tEngineGlobals.screen_angle\t= screen_angle;\r\n\r\n\t// Figure width and height of viewport at near clip plane.\r\n\tfloat half_screen_angle_in_radians\t= Mth::DegToRad( screen_angle * 0.5f );\r\n\tfloat width\t\t\t\t\t\t\t= EngineGlobals.near_plane * 2.0f * tanf( half_screen_angle_in_radians );\r\n\r\n\tif( EngineGlobals.backbuffer_width == 640.0f )\r\n\t{\r\n\t\t// We need to adjust the aspect ratio for the Xbox, since it is now rendering with D3DPRESENTFLAG_10X11PIXELASPECTRATIO\r\n\t\t// set. This changes the regular aspect ratio from 4:3 to 4:3.3, so adjust the value here.\r\n\t\taspect_ratio = aspect_ratio * (( 4.0f / 3.3f ) / ( 4.0f / 3.0f ));\r\n\t}\r\n\t\r\n\tfloat height\t= width / aspect_ratio;\r\n\tXGMatrixPerspectiveRH( &EngineGlobals.projection_matrix, width, height, EngineGlobals.near_plane, EngineGlobals.far_plane );\r\n\t\r\n\tNxXbox::EngineGlobals.near_plane_width\t= width;\r\n\tNxXbox::EngineGlobals.near_plane_height\t= height;\r\n\r\n\tif( render_at_infinity )\r\n\t{\r\n\t\t// Rendering the sky, so set the projection transform up to calculate a constant z value of 1.0.\r\n\t\t// W value must remain correct however.\r\n\t\tEngineGlobals.projection_matrix.m[2][2] = -0.999999f;\t// Setting this to -1.0f causes D3D to complain about WNear calculation.\r\n\t\tEngineGlobals.projection_matrix.m[3][2] =  0.0f;\r\n\t}\r\n\t\r\n\tD3DDevice_SetTransform( D3DTS_WORLD, &EngineGlobals.world_matrix );\r\n\tD3DDevice_SetTransform( D3DTS_VIEW, &EngineGlobals.view_matrix );\r\n\tD3DDevice_SetTransform( D3DTS_PROJECTION, &EngineGlobals.projection_matrix );\r\n\r\n\t// Set up view frustum values for bounding sphere culling.\r\n\tEngineGlobals.ViewFrustumTX\t= tanf( Mth::DegToRad( screen_angle * 0.5f ));\r\n\tEngineGlobals.ViewFrustumTY\t= -( EngineGlobals.ViewFrustumTX / aspect_ratio );\r\n\tEngineGlobals.ViewFrustumSX\t= 1.0f / sqrtf( 1.0f + 1.0f / ( EngineGlobals.ViewFrustumTX * EngineGlobals.ViewFrustumTX ));\r\n\tEngineGlobals.ViewFrustumSY\t= 1.0f / sqrtf( 1.0f + 1.0f / ( EngineGlobals.ViewFrustumTY * EngineGlobals.ViewFrustumTY ));\r\n\tEngineGlobals.ViewFrustumCX\t= 1.0f / sqrtf( 1.0f + EngineGlobals.ViewFrustumTX * EngineGlobals.ViewFrustumTX );\r\n\tEngineGlobals.ViewFrustumCY\t= 1.0f / sqrtf( 1.0f + EngineGlobals.ViewFrustumTY * EngineGlobals.ViewFrustumTY );\r\n\r\n\t// Set up matrix for offset bump mapping (the matrix that will be used to set the D3DTSS_BUMPENVMATnn texture states).\r\n    float rotate_angle = atan2f( -EngineGlobals.cam_at.z, -EngineGlobals.cam_at.x );\r\n\tXGMatrixRotationY( &EngineGlobals.bump_env_matrix, rotate_angle - D3DX_PI / 2 );\r\n\r\n\t// Calculate vectors for billboard rendering.\r\n\tBillboardManager.SetCameraMatrix();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/* Quick determination of if something is visible or not, uses\t  */\r\n/* the previously calculated s and c vectors and the\t\t\t  */\r\n/* WorldToCamera transform (note, no attempt is made to ensure\t  */\r\n/* this is the same camera that the object will eventually be\t  */\r\n/* rendered with.\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nbool IsVisible( Mth::Vector &center, float radius )\r\n{\r\n\tXGVECTOR4 test_out;\r\n\r\n\tXGVec3Transform( &test_out, (XGVECTOR3*)&center[X], (XGMATRIX*)&EngineGlobals.view_matrix );\r\n\r\n\tif( -test_out.z + radius < EngineGlobals.near_plane )\r\n\t\treturn false;\r\n\r\n\tfloat sx_z\t= EngineGlobals.ViewFrustumSX * test_out.z;\r\n\tfloat cx_x\t= EngineGlobals.ViewFrustumCX * test_out.x;\r\n\tif(( radius < sx_z - cx_x ) || ( radius < sx_z + cx_x ))\r\n\t\treturn false;\r\n\r\n\tfloat sy_z\t= EngineGlobals.ViewFrustumSY * test_out.z;\r\n\tfloat cy_y\t= EngineGlobals.ViewFrustumCY * test_out.y;\r\n\tif(( radius < sy_z + cy_y ) || ( radius < sy_z - cy_y ))\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid set_frustum_bbox_transform( Mth::Matrix *p_transform )\r\n{\r\n\tif( p_transform == NULL )\r\n\t{\r\n\t\tp_bbox_transform = NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_bbox_transform\t\t= &bbox_transform;\r\n\r\n\t\tbbox_transform.m[0][0]\t= ( *p_transform ).GetRight().GetX();\r\n\t\tbbox_transform.m[0][1]\t= ( *p_transform ).GetRight().GetY();\r\n\t\tbbox_transform.m[0][2]\t= ( *p_transform ).GetRight().GetZ();\r\n\t\tbbox_transform.m[0][3]\t= 0.0f;\r\n\r\n\t\tbbox_transform.m[1][0]\t= ( *p_transform ).GetUp().GetX();\r\n\t\tbbox_transform.m[1][1]\t= ( *p_transform ).GetUp().GetY();\r\n\t\tbbox_transform.m[1][2]\t= ( *p_transform ).GetUp().GetZ();\r\n\t\tbbox_transform.m[1][3]\t= 0.0f;\r\n\r\n\t\tbbox_transform.m[2][0]\t= ( *p_transform ).GetAt().GetX();\r\n\t\tbbox_transform.m[2][1]\t= ( *p_transform ).GetAt().GetY();\r\n\t\tbbox_transform.m[2][2]\t= ( *p_transform ).GetAt().GetZ();\r\n\t\tbbox_transform.m[2][3]\t= 0.0f;\r\n\r\n\t\tbbox_transform.m[3][0]\t= p_transform->GetPos().GetX();\r\n\t\tbbox_transform.m[3][1]\t= p_transform->GetPos().GetY();\r\n\t\tbbox_transform.m[3][2]\t= p_transform->GetPos().GetZ();\r\n\t\tbbox_transform.m[3][3]\t= 1.0f;\r\n\t}\r\n}\r\n\r\n\r\n\r\nfloat boundingSphereNearestZ = 0.0f;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nfloat get_bounding_sphere_nearest_z( void )\r\n{\r\n\treturn boundingSphereNearestZ;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Checks a bounding sphere against the current view frustum\t  */\r\n/* (ignoring far clipping). Returns true if any part is visible.  */\r\n/* Timings suggest this method runs on average around ~0.25us,    */\r\n/* faster than test code doing world space culling against a set  */\r\n/* of plane equations representing the view frustum in world\t  */\r\n/* space.\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool frustum_check_sphere( D3DXVECTOR3 *p_center, float radius )\r\n{\r\n\tXGVECTOR4\ttest_out;\r\n\r\n\t// Build the composite transform if required.\r\n\tif( p_bbox_transform )\r\n\t{\r\n\t\t// Object to world.\r\n\t\ttest_out.x = p_center->x + p_bbox_transform->_41;\r\n\t\ttest_out.y = p_center->y + p_bbox_transform->_42;\r\n\t\ttest_out.z = p_center->z + p_bbox_transform->_43;\r\n//\t\tXGVec3Transform( &test_out, (XGVECTOR3*)p_center, p_bbox_transform );\r\n\r\n\t\t// World to view.\r\n\t\tXGVec3Transform( &test_out, (XGVECTOR3*)&test_out, (XGMATRIX*)&EngineGlobals.view_matrix );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// World to view.\r\n\t\tXGVec3Transform( &test_out, (XGVECTOR3*)p_center, (XGMATRIX*)&EngineGlobals.view_matrix );\r\n\t}\r\n\t\t\r\n\tboundingSphereNearestZ = -test_out.z - radius;\r\n\r\n\tif( -test_out.z + radius < EngineGlobals.near_plane )\r\n\t\treturn false;\r\n\r\n\tfloat sx_z\t= EngineGlobals.ViewFrustumSX * test_out.z;\r\n\tfloat cx_x\t= EngineGlobals.ViewFrustumCX * test_out.x;\r\n\tif(( radius < sx_z - cx_x ) || ( radius < sx_z + cx_x ))\r\n\t\treturn false;\r\n\r\n\tfloat sy_z\t= EngineGlobals.ViewFrustumSY * test_out.z;\r\n\tfloat cy_y\t= EngineGlobals.ViewFrustumCY * test_out.y;\r\n\tif(( radius < sy_z + cy_y ) || ( radius < sy_z - cy_y ))\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Checks a bounding box against the current view frustum\t\t  */\r\n/* (ignoring far clipping). Returns true if any part is visible.  */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool frustum_check_box( Mth::CBBox *p_bbox )\r\n{\r\n\tXGVECTOR3\ttest_in, test_out;\r\n\tXGVECTOR4\ttest_mid;\r\n\t\r\n\tuint32\tcumulative_projection_space_outcode\t= 0xFF;\r\n\tfloat\tmin_x = p_bbox->GetMin().GetX();\r\n\tfloat\tmin_y = p_bbox->GetMin().GetY();\r\n\tfloat\tmin_z = p_bbox->GetMin().GetZ();\r\n\tfloat\tmax_x = p_bbox->GetMax().GetX();\r\n\tfloat\tmax_y = p_bbox->GetMax().GetY();\r\n\tfloat\tmax_z = p_bbox->GetMax().GetZ();\r\n\r\n\tfor( uint32 v = 0; v < 8; ++v )\r\n\t{\r\n\t\tuint32 projection_space_outcode = 0;\r\n\r\n\t\ttest_in.x = ( v & 0x04 ) ? max_x : min_x;\r\n\t\ttest_in.y = ( v & 0x02 ) ? max_y : min_y;\r\n\t\ttest_in.z = ( v & 0x01 ) ? max_z : min_z;\r\n\r\n\t\tif( p_bbox_transform )\r\n\t\t{\r\n\t\t\tXGVec3Transform( &test_mid, &test_in, p_bbox_transform );\r\n\t\t\ttest_in.x = test_mid.x;\r\n\t\t\ttest_in.y = test_mid.y;\r\n\t\t\ttest_in.z = test_mid.z;\r\n\t\t}\r\n\t\t\r\n\t\tXGVec3Transform( &test_mid, &test_in, &EngineGlobals.view_matrix );\r\n\t\ttest_in.x = test_mid.x;\r\n\t\ttest_in.y = test_mid.y;\r\n\t\ttest_in.z = test_mid.z;\r\n\t\t\r\n\t\t// Do z-checking here.\r\n\t\tif( -test_mid.z < EngineGlobals.near_plane )\r\n\t\t{\r\n\t\t\t// Behind the camera near plane.\r\n\t\t\tprojection_space_outcode |= 0x10;\r\n\t\t}\r\n\t\telse if( -test_mid.z > EngineGlobals.far_plane )\r\n\t\t{\r\n\t\t\t// Beyond the camera far plane.\r\n\t\t\tprojection_space_outcode |= 0x20;\r\n\t\t}\r\n\t\t\r\n\t\t// At this point it's important to check to see whether the point is in postive or negative z-space, since\r\n\t\t// after the projection transform, both very large camera space z values and camera space z values where z < 0\r\n\t\t// will give results with z > 1. (Camera space values in the range [0,near] give negative projection space z values).\r\n\t\tXGVec3TransformCoord( &test_out, &test_in, &EngineGlobals.projection_matrix );\r\n\r\n\t\tif(( -test_mid.z < 0.0f ) && ( !EngineGlobals.is_orthographic ))\r\n\t\t{\r\n\t\t\ttest_out.x = -test_out.x;\r\n\t\t\ttest_out.y = -test_out.y;\r\n\t\t}\r\n\r\n\t\tif( test_out.x > 1.0f )\r\n\t\t\tprojection_space_outcode |= 0x01;\r\n\t\telse if( test_out.x < -1.0f )\r\n\t\t\tprojection_space_outcode |= 0x02;\r\n\r\n\t\tif( test_out.y > 1.0f )\r\n\t\t\tprojection_space_outcode |= 0x04;\r\n\t\telse if( test_out.y < -1.0f )\r\n\t\t\tprojection_space_outcode |= 0x08;\r\n\r\n\t\tcumulative_projection_space_outcode\t&= projection_space_outcode;\r\n\r\n\t\tif( cumulative_projection_space_outcode == 0 )\r\n\t\t{\r\n\t\t\t// Early out.\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\nstruct sSortedMeshEntry\r\n{\r\n\tsMesh\t\t\t\t*p_mesh;\r\n\tfloat\t\t\t\tsort;\r\n\tsSortedMeshEntry\t*pNext;\r\n};\r\n\r\n\r\nstatic sSortedMeshEntry\tsortedMeshArray[1000];\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid calculate_tex_proj_matrix( XGMATRIX *p_tex_view_matrix, XGMATRIX *p_tex_proj_matrix, XGMATRIX *p_tex_transform_matrix, XGMATRIX *p_world_matrix )\r\n{\r\n\t// Get the current view matrix.\r\n\tXGMATRIX matView, matInvView;\r\n\tD3DDevice_GetTransform( D3DTS_VIEW, (XGMATRIX*)&matView );\r\n\tXGMatrixInverse( &matInvView,  NULL, &matView );\r\n\r\n\tXGMATRIX matBiasScale;\r\n    XGMatrixIdentity( &matBiasScale );\r\n\r\n\tstatic float x0 = 256.0f;\r\n\tstatic float y0 = 256.0f;\r\n\t\r\n\tmatBiasScale._11 = x0 * 0.5f;\r\n\tmatBiasScale._22 = y0 * -0.5f;\r\n\tmatBiasScale._33 = D3DZ_MAX_D24S8;\r\n\r\n\tstatic float x1 = 256.0f;\r\n\tstatic float y1 = 256.0f;\r\n\t\r\n\tmatBiasScale._41 = x1 * 0.5f + 0.5f;\r\n\tmatBiasScale._42 = y1 * 0.5f + 0.5f;\r\n\r\n\tXGMATRIX m_matTexProj;\r\n\r\n\t// Don't bother with inverse view transform for Shadow Buffer, since we are picking up world-space coordinates directly.\r\n\tif( p_world_matrix )\r\n\t{\r\n\t\tm_matTexProj = *p_world_matrix;\t\t\t\t\t\t\t\t\t\t\t\t// Transform to world space.\r\n\t\tXGMatrixMultiply( &m_matTexProj, &m_matTexProj, p_tex_view_matrix );\t\t// Transform to projection camera space.\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_matTexProj = *p_tex_view_matrix;\t\t\t\t\t\t\t\t\t\t\t// Transform to projection camera space.\r\n\t}\r\n\tXGMatrixMultiply( &m_matTexProj, &m_matTexProj, p_tex_proj_matrix );\t\t\t// Situate verts relative to projector's view\r\n    XGMatrixMultiply( p_tex_transform_matrix, &m_matTexProj, &matBiasScale );\t\t// Scale and bias to map the near clipping plane to texcoords\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid render_shadow_targets( void )\r\n{\r\n\tXGMATRIX\tstored_view_matrix\t\t\t= EngineGlobals.view_matrix;\r\n\tXGMATRIX\tstored_projection_matrix\t= EngineGlobals.projection_matrix;\r\n\tuint32\t\tstored_fog_state\t\t\t= EngineGlobals.fog_enabled;\r\n\tDWORD\t\tmultisample_mode;\r\n\r\n\t// Get multisample mode.\r\n\tD3DDevice_GetRenderState( D3DRS_MULTISAMPLEMODE, &multisample_mode );\r\n\r\n\t// Disable fogging.\r\n\tset_render_state( RS_FOGENABLE, 0 );\r\n\r\n\t// Goes through the list of render target textures, rendering to each one in turn.\r\n\tpTextureProjectionDetailsTable->IterateStart();\r\n\tsTextureProjectionDetails *p_details = pTextureProjectionDetailsTable->IterateNext();\r\n\t\r\n\tD3DSurface fake_target;\r\n\r\n\twhile( p_details )\r\n\t{\r\n\t\tif( p_details->p_model )\r\n\t\t{\r\n\t\t\t// Setup dummy color buffer (bad things will happen if you write to it).\r\n\t\t\t// The XGSetSurfaceHeader() function is slow, these values are now set explicitly from the observed values\r\n\t\t\t// set by the function.\r\n//\t\t\tZeroMemory( &fake_target, sizeof( fake_target ));\r\n//\t\t\tXGSetSurfaceHeader( 256, 256, D3DFMT_LIN_R5G6B5, &fake_target, 0, 0 );\r\n\t\t\tfake_target.Common\t= 0x00050001UL;\r\n\t\t\tfake_target.Data\t= 0x00000000UL;\r\n\t\t\tfake_target.Lock\t= 0x00000000UL;\r\n\t\t\tfake_target.Format\t= 0x00011129UL;\r\n\t\t\tfake_target.Size\t= 0x070FF0FFUL;\r\n\t\t\tfake_target.Parent\t= 0x00000000UL;\r\n\t\t\t\r\n\t\t\t// Set the new render target.\r\n\t\t\tLPDIRECT3DSURFACE8 pSurface;\r\n\r\n\t\t\t// This call will increase the reference count of the IDirect3DTexture8 object.\r\n\t\t\tp_details->p_texture->pD3DTexture->GetSurfaceLevel( 0, &pSurface );\r\n\r\n\t\t\t// This call will increase the reference count of the IDirect3DSurface8 object.\r\n\t\t\tD3DDevice_SetRenderTarget( &fake_target, pSurface );\r\n\t\t\t\r\n\t\t\t// Clear the target.\r\n\t\t\tD3DDevice_Clear( 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, 0, 1.0f, 0 ); \r\n\t\t\t\r\n\t\t\t// Disable color writes.\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_COLORWRITEENABLE, 0 );\r\n\r\n\t\t\t// Turn on z-offset.\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_SOLIDOFFSETENABLE,\t\t\tTRUE );\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_POLYGONOFFSETZOFFSET,\t\tFtoDW( 4.0f ));\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_POLYGONOFFSETZSLOPESCALE,\tFtoDW( 2.0f ));\r\n\r\n\t\t\t// Performance optimiser suggested change.\r\n\t\t\t// Priority 2: Set D3DRS_MULTISAMPLEMODE to D3DMULTISAMPLEMODE_4X for faster fill rate with no quality loss when depth only rendering.\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_MULTISAMPLEMODE,\t\t\tD3DMULTISAMPLEMODE_4X );\r\n\r\n\t\t\t// Set the view and projection transforms.\r\n\t\t\tEngineGlobals.view_matrix\t\t= p_details->view_matrix;\r\n\t\t\tEngineGlobals.projection_matrix\t= p_details->projection_matrix;\r\n\t\t\tEngineGlobals.is_orthographic\t= true;\r\n\r\n\t\t\t// Render all instances for the CGeom's contained in this model.\r\n\t\t\tint num_geoms = p_details->p_model->GetNumGeoms();\r\n\t\t\tfor( int i = 0; i < num_geoms; ++i )\r\n\t\t\t{\r\n\t\t\t\tNx::CXboxGeom *p_xbox_geom\t= static_cast<Nx::CXboxGeom*>( p_details->p_model->GetGeomByIndex( i ));\r\n\t\t\t\tCInstance *p_instance\t\t= p_xbox_geom->GetInstance();\r\n\t\t\t\t\r\n\t\t\t\tif( p_instance->GetActive())\r\n\t\t\t\t{\r\n\t\t\t\t\t// Flag the scene as having the shadow version rendered.\r\n\t\t\t\t\tp_instance->GetScene()->m_flags |= SCENE_FLAG_RENDERING_SHADOW;\r\n\r\n\t\t\t\t\t// Render the model.\r\n\t\t\t\t\trender_instance( p_instance, vRENDER_NO_CULLING );\r\n\r\n\t\t\t\t\t// Clear the flag the scene as having the shadow version rendered.\r\n\t\t\t\t\tp_instance->GetScene()->m_flags &= ~SCENE_FLAG_RENDERING_SHADOW;\r\n\t\t\t\r\n\t\t\t\t\t// Flag the scene as self shadowing.\r\n\t\t\t\t\tp_instance->GetScene()->m_flags |= SCENE_FLAG_SELF_SHADOWS;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tpSurface->Release();\r\n\t\t}\r\n\t\tp_details = pTextureProjectionDetailsTable->IterateNext();\r\n\t}\r\n\r\n\t// Restore important states.\r\n\tD3DDevice_SetRenderState( D3DRS_COLORWRITEENABLE,\tD3DCOLORWRITEENABLE_ALL );\r\n\tD3DDevice_SetRenderState( D3DRS_SOLIDOFFSETENABLE,\tFALSE );\r\n\tD3DDevice_SetRenderState( D3DRS_MULTISAMPLEMODE,\tmultisample_mode );\r\n\tset_render_state( RS_FOGENABLE, stored_fog_state );\r\n\r\n\t// Pixel shader override no longer required.\r\n\tEngineGlobals.pixel_shader_override = 0;\r\n\t\r\n\t// Restore the view and projection transforms.\r\n\tEngineGlobals.view_matrix\t\t= stored_view_matrix;\r\n\tEngineGlobals.projection_matrix\t= stored_projection_matrix;\r\n\tEngineGlobals.is_orthographic\t= false;\r\n\r\n\t// It's important to set the internal reference count of the dummy color surface here, otherwise\r\n\t// the debug version of D3D will complain when it attempts to reduce the internal ref count during\r\n\t// the subsequent SetRenderTarget() call.\r\n\tfake_target.Common\t= 0x000D0001UL;\r\n\r\n\t// Restore the default render target.\r\n\tD3DDevice_SetRenderTarget( EngineGlobals.p_RenderSurface, EngineGlobals.p_ZStencilSurface );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid render_shadow_meshes( sScene *p_scene, sMesh **p_mesh_indices, int num_meshes )\r\n{\r\n\t// No anisotropic filtering for the base texture.\r\n\tDWORD stage_zero_minfilter;\r\n\tD3DDevice_GetTextureStageState( 0, D3DTSS_MINFILTER, &stage_zero_minfilter );\r\n\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );\r\n\t\r\n\t// Disable fogging.\r\n\tuint32 stored_fog_state = EngineGlobals.fog_enabled;\r\n\tset_render_state( RS_FOGENABLE, 0 );\r\n\r\n\t// Scan through each entry in the TextureProjectionDetails table, and see whether it relates to this scene.\r\n\tpTextureProjectionDetailsTable->IterateStart();\r\n\tsTextureProjectionDetails *p_details = pTextureProjectionDetailsTable->IterateNext();\r\n\twhile( p_details )\r\n\t{\r\n\t\tXGMATRIX\tstored_view_matrix\t\t\t= EngineGlobals.view_matrix;\r\n\t\tXGMATRIX\tstored_projection_matrix\t= EngineGlobals.projection_matrix;\r\n\t\t\t\r\n\t\t// Calculate the projection matrix that will project world coordinates into our shadow buffer.\r\n\t\tcalculate_tex_proj_matrix( &p_details->view_matrix, &p_details->projection_matrix, &p_details->texture_projection_matrix );\r\n\r\n\t\t// Set the vertex shader.\r\n\t\tset_vertex_shader( ShadowBufferStaticGeomVS );\r\n\r\n\t\t// Set the pixel shader that just does straight texturing.\r\n\t\tset_pixel_shader( ShadowBufferStaticGeomPS );\r\n\r\n\t\tset_render_state( RS_ALPHACUTOFF, 1 );\r\n\t\t\r\n\t\t// Set the other textures to NULL.\r\n\t\tset_texture( 0, NULL );\r\n\t\tset_texture( 2, NULL );\r\n\t\tset_texture( 3, NULL );\r\n\r\n\t\t// Need to set this texture NULL first, to flush the texture state, since the incoming texture is linear.\r\n\t\tset_texture( 1, NULL );\r\n\r\n\t\t// Set the projected texture (as the second-pass texture).\r\n\t\tif( p_details->p_texture->pD3DSurface )\r\n\t\t\tset_texture( 1, (IDirect3DTexture8*)( p_details->p_texture->pD3DSurface ));\r\n\t\telse\r\n\t\t\tset_texture( 1, p_details->p_texture->pD3DTexture );\r\n\r\n\t\t// Set shadowbuffer texture details.\r\n\t\tset_render_state( RS_UVADDRESSMODE1, 0x00020002UL );\t\t\t\t\t// Set (border,border) addressing.\r\n\t\tD3DDevice_SetTextureStageState( 1, D3DTSS_BORDERCOLOR, 0xffffffff );\r\n\t\tD3DDevice_SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );\r\n\t\tD3DDevice_SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR );\r\n\t\t\r\n\t\t// Set shadowbuffer state.\r\n\t\tD3DDevice_SetRenderState( D3DRS_SHADOWFUNC, D3DCMP_GREATEREQUAL );\r\n\t\t\t\r\n\t\t// Upload constants to the vertex shader for composite world->view->projection transform (c0 - c3) and\r\n\t\t// world->texture transform (c4 - c7).\r\n\t\tXGMATRIX\tdest_matrix;\r\n\t\tXGMATRIX\ttemp_matrix;\r\n\t\tXGMATRIX\tprojMatrix;\r\n\t\tXGMATRIX\tviewMatrix;\r\n\t\tXGMATRIX\tworldMatrix;\r\n\t\tXGMATRIX\ttexProjMatrix;\r\n\r\n\t\t// Texture projection matrix.\r\n\t\tXGMatrixTranspose( &texProjMatrix, &p_details->texture_projection_matrix );\r\n\t\t\r\n\t\t// Projection matrix.\r\n\t\tXGMatrixTranspose( &projMatrix, &EngineGlobals.projection_matrix );\r\n\t\r\n\t\t// View matrix.\r\n\t\tXGMatrixTranspose( &viewMatrix, &EngineGlobals.view_matrix );\r\n\t\tviewMatrix.m[3][0] = 0.0f;\r\n\t\tviewMatrix.m[3][1] = 0.0f;\r\n\t\tviewMatrix.m[3][2] = 0.0f;\r\n\t\tviewMatrix.m[3][3] = 1.0f;\r\n\t\r\n\t\t// World space transformation matrix.\r\n\t\tXGMatrixIdentity( &worldMatrix );\r\n\r\n\t\t// Calculate composite world->view->projection matrix.\r\n\t\tXGMatrixMultiply( &temp_matrix, &viewMatrix, &worldMatrix );\r\n\t\tXGMatrixMultiply( &dest_matrix, &projMatrix, &temp_matrix );\r\n\r\n\t\t// Load up the combined world, camera & projection matrix, and the tetxure transform matrix.\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 0, (void*)&dest_matrix, 4 );\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 4, (void*)&texProjMatrix, 4 );\r\n\r\n\t\t// Turn on z-offset.\r\n\t\tD3DDevice_SetRenderState( D3DRS_SOLIDOFFSETENABLE,\t\t\tTRUE );\r\n\t\tD3DDevice_SetRenderState( D3DRS_POLYGONOFFSETZOFFSET,\t\tFtoDW( -4.0f ));\r\n\t\tD3DDevice_SetRenderState( D3DRS_POLYGONOFFSETZSLOPESCALE,\tFtoDW( -2.0f ));\r\n\r\n\t\t// Set the blend mode to modulate, using the texture color.\r\n\t\tset_blend_mode( vBLEND_MODE_MODULATE_COLOR );\r\n\r\n\t\t// Set up the correct view and projection matrix for frustum culling.\r\n\t\tEngineGlobals.view_matrix\t\t= p_details->view_matrix;\r\n\t\tEngineGlobals.projection_matrix\t= p_details->projection_matrix;\r\n\t\tEngineGlobals.is_orthographic\t= true;\r\n\r\n\t\t// Draw the meshes.\r\n\t\tfor( int i = 0; i < num_meshes; ++i )\r\n\t\t{\r\n\t\t\tsMesh *p_mesh = p_mesh_indices[i];\r\n\t\t\t\t\r\n\t\t\t// Check this mesh is okay for shadow rendering.\r\n\t\t\tif( !( p_mesh->m_flags & sMesh::MESH_FLAG_NO_SKATER_SHADOW ))\r\n\t\t\t{\r\n\t\t\t\t// Cull this mesh against the second view frustum.\r\n\t\t\t\tif( frustum_check_sphere( &p_mesh->m_sphere_center, p_mesh->m_sphere_radius ))\r\n\t\t\t\t{\r\n//\t\t\t\t\tif( frustum_check_box( &p_mesh->m_bbox ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Here we want to set up texture 0 as per the material on the mesh. This way we can use it as an alpha\r\n\t\t\t\t\t\t// mask to avoid drawing the shadow on transparent pixels.\r\n\t\t\t\t\t\tif( p_mesh->mp_material->mp_tex[0] )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tset_texture( 0, p_mesh->mp_material->mp_tex[0]->pD3DTexture );\r\n\t\t\t\t\t\t\tset_render_state( RS_UVADDRESSMODE0, p_mesh->mp_material->m_uv_addressing[0] );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Draw the mesh.\r\n\t\t\t\t\t\tD3DDevice_SetStreamSource( 0, p_mesh->mp_vertex_buffer[0], p_mesh->m_vertex_stride );\r\n\t\t\t\t\t\tD3DDevice_DrawIndexedVertices( p_mesh->m_primitive_type, p_mesh->m_num_indices[0], p_mesh->mp_index_buffer[0] );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Restore the view and projection transforms.\r\n\t\tEngineGlobals.view_matrix\t\t= stored_view_matrix;\r\n\t\tEngineGlobals.projection_matrix\t= stored_projection_matrix;\r\n\t\tEngineGlobals.is_orthographic\t= false;\r\n\r\n\t\tp_details = pTextureProjectionDetailsTable->IterateNext();\r\n\t}\r\n\r\n\t// Turn off z-offset.\r\n\tD3DDevice_SetRenderState( D3DRS_SOLIDOFFSETENABLE, FALSE );\r\n\tD3DDevice_SetRenderState( D3DRS_SHADOWFUNC, D3DCMP_NEVER );\r\n\tset_pixel_shader( 0 );\r\n\r\n\t// Restore anisotropic filtering if present.\r\n\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER, stage_zero_minfilter );\r\n\r\n\t// Restore fogging if present.\r\n\tset_render_state( RS_FOGENABLE, stored_fog_state );\r\n\r\n\t// Reflush linear texture.\r\n\tset_texture( 1, NULL );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int cmp( const void *p1, const void *p2 )\r\n{\r\n\treturn((sSortedMeshEntry*)p1)->sort < ((sSortedMeshEntry*)p2)->sort ? -1 : ((sSortedMeshEntry*)p1)->sort > ((sSortedMeshEntry*)p2)->sort ? 1 : 0;\r\n}\r\n\r\n\r\n\r\nstatic bool debug_shadow_volumes = false;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid render_shadow_volumes( sScene *p_scene, uint32 viewport )\r\n{\r\n\t// Switch viewport from value to bitfield value.\r\n\tviewport = ( 1 << viewport );\r\n\t\r\n\tNxXbox::set_pixel_shader( PixelShader5 );\r\n\tEngineGlobals.pixel_shader_override\t= PixelShader5;\r\n\tNxXbox::set_texture( 0, NULL );\r\n\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t0 );\r\n\tNxXbox::set_render_state( RS_ZTESTENABLE,\t1 );\r\n\tNxXbox::set_render_state( RS_ALPHACUTOFF,\t0 );\r\n\r\n\tif( debug_shadow_volumes == false )\r\n\t\tD3DDevice_SetRenderState( D3DRS_ZFUNC,\t\tD3DCMP_GREATEREQUAL );\r\n\r\n\t// Render all meshes.\r\n\tfor( int e = 0; e < p_scene->m_num_mesh_entries; ++e )\r\n\t{\r\n\t\tsMesh *p_mesh = p_scene->m_meshes[e];\r\n\t\tif(( p_mesh->m_flags & sMesh::MESH_FLAG_ACTIVE ) && ( p_mesh->m_flags & sMesh::MESH_FLAG_SHADOW_VOLUME ))\r\n\t\t{\r\n\t\t\t// Frustum cull this mesh, using the associated bounding sphere.\r\n\t\t\tif( frustum_check_sphere( &p_mesh->m_sphere_center, p_mesh->m_sphere_radius ))\r\n\t\t\t{\r\n\t\t\t\tif( debug_shadow_volumes == false )\r\n\t\t\t\t{\r\n\t\t\t\t\tNxXbox::set_render_state( RS_CULLMODE, D3DCULL_CW );\r\n\t\t\t\t\tNxXbox::set_blend_mode( 0x10000000UL | NxXbox::vBLEND_MODE_ADD_FIXED );\r\n\t\t\t\t\tp_mesh->Submit();\r\n\r\n\t\t\t\t\tNxXbox::set_render_state( RS_CULLMODE, D3DCULL_CCW );\r\n\t\t\t\t\tNxXbox::set_blend_mode( 0x10000000UL | NxXbox::vBLEND_MODE_SUB_FIXED );\r\n\t\t\t\t\tp_mesh->Submit();\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tNxXbox::set_render_state( RS_CULLMODE, D3DCULL_NONE );\r\n\t\t\t\t\tNxXbox::set_blend_mode( 0x30000000UL | NxXbox::vBLEND_MODE_BLEND_FIXED );\r\n\t\t\t\t\tp_mesh->Submit();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tEngineGlobals.pixel_shader_override\t= 0;\r\n\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t1 );\r\n\tNxXbox::set_render_state( RS_CULLMODE,\t\tD3DCULL_CW );\r\n\tD3DDevice_SetRenderState( D3DRS_ZFUNC,\t\tD3DCMP_LESSEQUAL );\r\n}\r\n\r\n\r\n#define\t\t\tVISIBLE_MESH_ARRAY_SIZE\t\t4096\r\nstatic sMesh\t*visible_mesh_array[VISIBLE_MESH_ARRAY_SIZE];\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid render_scene( sScene *p_scene, uint32 flags, uint32 viewport )\r\n{\r\n\tsMaterial\t\t*p_material\t\t\t\t\t= NULL;\r\n\tbool\t\t\tno_culling\t\t\t\t\t= ( flags & vRENDER_NO_CULLING ) > 0 ;\r\n\tbool\t\t\trender;\r\n\tint\t\t\t\tvisible_mesh_array_index\t= 0;\r\n\r\n\t// Don't render dictionary scenes.\r\n\tif( p_scene->m_is_dictionary )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif( flags & vRENDER_SHADOW_VOLUMES )\r\n\t{\r\n\t\trender_shadow_volumes( p_scene, viewport );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Disallow front to back sorting if the number of opaque meshes is larger than the visible mesh array.\r\n\tif( p_scene->m_first_semitransparent_entry >= VISIBLE_MESH_ARRAY_SIZE )\r\n\t{\r\n\t\tflags &= ~vRENDER_SORT_FRONT_TO_BACK;\r\n\t}\r\n\r\n\t// Switch viewport from value to bitfield value.\r\n\tviewport = ( 1 << viewport );\r\n\t\r\n\t// Render opaque meshes.\r\n\tif( flags & vRENDER_OPAQUE )\r\n\t{\r\n\t\tfor( int e = 0; e < p_scene->m_first_semitransparent_entry; ++e )\r\n\t\t{\r\n\t\t\tsMesh *p_mesh = p_scene->m_meshes[e];\r\n\r\n\t\t\t__asm mov eax, p_mesh\t\t\t// Store mesh pointer.\r\n\t\t\t__asm prefetcht0 [eax]\t\t\t// Get first 32 bytes of sMesh structure.\r\n\t\t\t\r\n\t\t\tif(( p_mesh->m_flags & sMesh::MESH_FLAG_ACTIVE ) && (( p_mesh->m_flags & ( sMesh::MESH_FLAG_SHADOW_VOLUME | sMesh::MESH_FLAG_BILLBOARD )) == 0 ))\r\n\t\t\t{\r\n\t\t\t\tif( no_culling )\r\n\t\t\t\t{\r\n\t\t\t\t\trender = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\trender = false;\r\n\r\n\t\t\t\t\t// Check the visibility mask.\r\n\t\t\t\t\tif( p_mesh->m_visibility_mask & viewport )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Frustum cull this set of meshes, using the associated bounding sphere and bounding box.\r\n\t\t\t\t\t\tif( frustum_check_sphere( &p_mesh->m_sphere_center, p_mesh->m_sphere_radius ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Check against any occluders.\r\n\t\t\t\t\t\t\tif(( !( flags & vRENDER_OCCLUDED )) || ( !TestSphereAgainstOccluders( &p_mesh->m_sphere_center, p_mesh->m_sphere_radius )))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\trender = true;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Draw this mesh if we decided it is visible.\r\n\t\t\t\tif( render )\r\n\t\t\t\t{\r\n\t\t\t\t\tif(( flags & vRENDER_SORT_FRONT_TO_BACK ) == 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// If the material has changed, submit the new material.\r\n\t\t\t\t\t\tif( p_mesh->mp_material != p_material )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_material = p_mesh->mp_material;\r\n\t\t\t\t\t\t\tp_material->Submit();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tp_mesh->Submit();\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// If this mesh is within the 'near' section, render it now. Meshes in the far section will be\r\n\t\t\t\t\t\t// deferred for rendering later on, which should gain some benefit from the fast pixel occlusion.\r\n\t\t\t\t\t\tif( boundingSphereNearestZ <= FRONT_TO_BACK_SORT_CUTOFF )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif( p_mesh->mp_material != p_material )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tp_material = p_mesh->mp_material;\r\n\t\t\t\t\t\t\t\tp_material->Submit();\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tp_mesh->Submit();\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Set the nearest point of the bounding sphere.\r\n\t\t\t\t\t\tp_mesh->m_bounding_sphere_nearest_z = boundingSphereNearestZ;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Add this mesh to the visible list, providing it is within bounds.\r\n\t\t\t\t\tvisible_mesh_array[visible_mesh_array_index] = p_mesh;\r\n\t\t\t\t\tif( visible_mesh_array_index < ( VISIBLE_MESH_ARRAY_SIZE - 1 ))\r\n\t\t\t\t\t\t++visible_mesh_array_index;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\t\t\t\r\n\t\t\r\n\t\tif(( flags & vRENDER_SORT_FRONT_TO_BACK ) && ( visible_mesh_array_index > 0 ))\r\n\t\t{\r\n\t\t\t// At this stage we have an array of meshes, some of which may not yet have been rendered.\r\n\t\t\t// At this point simply scan through the list twice, drawing all 'far' meshes.\r\n\t\t\tfor( int vm = 0; vm < visible_mesh_array_index; ++vm )\r\n\t\t\t{\r\n\t\t\t\tsMesh *p_sorted_mesh = visible_mesh_array[vm];\r\n\r\n\t\t\t\tif( p_sorted_mesh->m_bounding_sphere_nearest_z > FRONT_TO_BACK_SORT_CUTOFF )\r\n\t\t\t\t{\t\t\t\t\r\n\t\t\t\t\t// If the material has changed, submit the new material.\r\n\t\t\t\t\tif( p_sorted_mesh->mp_material != p_material )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_material = p_sorted_mesh->mp_material;\r\n\t\t\t\t\t\tp_material->Submit();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tp_sorted_mesh->Submit();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Now draw the opaque meshes with shadow mapped on them.\r\n\t\tif( p_scene->m_flags & SCENE_FLAG_RECEIVE_SHADOWS )\r\n\t\t{\r\n\t\t\tset_render_state( RS_ZWRITEENABLE,\t0 );\r\n\t\t\tDWORD min_filter;\r\n\t\t\tD3DDevice_GetTextureStageState( 0, D3DTSS_MINFILTER, &min_filter );\r\n\t\t\tif( min_filter == D3DTEXF_ANISOTROPIC )\r\n\t\t\t{\r\n\t\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );\r\n\t\t\t}\r\n\t\t\r\n\t\t\trender_shadow_meshes( p_scene, visible_mesh_array, visible_mesh_array_index );\r\n\r\n\t\t\tif( min_filter == D3DTEXF_ANISOTROPIC )\r\n\t\t\t{\r\n\t\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_ANISOTROPIC );\r\n\t\t\t}\r\n\t\t\tset_render_state( RS_ZWRITEENABLE,\t1 );\r\n\t\t}\r\n\r\n\t\t// Reset mesh array\r\n\t\tvisible_mesh_array_index = 0;\r\n\r\n\t\tif( flags & vRENDER_BILLBOARDS )\r\n\t\t{\r\n\t\t\tBillboardManager.Render( vRENDER_OPAQUE );\r\n\t\t}\r\n\t}\r\n\t\r\n\tif( flags & vRENDER_SEMITRANSPARENT )\r\n\t{\r\n\t\tint e\t\t\t\t\t\t= p_scene->m_first_semitransparent_entry;\r\n\t\tint next_sorted_mesh_entry\t= 0;\r\n\t\t\r\n\t\t// Semitransparent rendering is done in three stages.\r\n\t\t// The first stage is meshes in the list up to the point where dynamic sorting starts.\r\n\t\t// The second stage is meshes in the list which use dynamic sorting.\r\n\t\t// The third stage is meshes in the list beyond the point where dynamic sorting ends.\r\n\t\tfor( ; e < p_scene->m_first_dynamic_sort_entry; ++e )\r\n\t\t{\r\n\t\t\tsMesh *p_mesh = p_scene->m_meshes[e];\r\n\r\n\t\t\t__asm mov eax, p_mesh\t\t\t// Store mesh pointer.\r\n\t\t\t__asm prefetcht0 [eax]\t\t\t// Get first 32 bytes of sMesh structure.\r\n\r\n\t\t\tif(( p_mesh->m_flags & sMesh::MESH_FLAG_ACTIVE ) && (( p_mesh->m_flags & ( sMesh::MESH_FLAG_SHADOW_VOLUME | sMesh::MESH_FLAG_BILLBOARD )) == 0 ))\r\n\t\t\t{\r\n\t\t\t\tif( no_culling )\r\n\t\t\t\t{\r\n\t\t\t\t\trender = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\trender = false;\r\n\r\n\t\t\t\t\t// Check the visibility mask.\r\n\t\t\t\t\tif( p_mesh->m_visibility_mask & viewport )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Frustum cull this set of meshes, using the associated bounding box.\r\n\t\t\t\t\t\tif( frustum_check_sphere( &p_mesh->m_sphere_center, p_mesh->m_sphere_radius ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Check against any occluders.\r\n\t\t\t\t\t\t\tif(( !( flags & vRENDER_OCCLUDED )) || ( !TestSphereAgainstOccluders( &p_mesh->m_sphere_center, p_mesh->m_sphere_radius )))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\trender = true;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif( render )\r\n\t\t\t\t{\r\n\t\t\t\t\t// If the material has changed, submit the new material.\r\n\t\t\t\t\tif( p_mesh->mp_material != p_material )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_material = p_mesh->mp_material;\r\n\t\t\t\t\t\tp_material->Submit();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tp_mesh->Submit();\r\n\r\n\t\t\t\t\t// Add this mesh to the visible list, providing it is within bounds.\r\n\t\t\t\t\tvisible_mesh_array[visible_mesh_array_index] = p_mesh;\r\n\t\t\t\t\tif( visible_mesh_array_index < ( VISIBLE_MESH_ARRAY_SIZE - 1 ))\r\n\t\t\t\t\t\t++visible_mesh_array_index;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( p_scene->m_num_dynamic_sort_entries > 0 )\r\n\t\t{\r\n\t\t\t// Second stage - dynamically sorted meshes.\r\n\t\t\tint last_dynamic_sort_entry = p_scene->m_first_dynamic_sort_entry + p_scene->m_num_dynamic_sort_entries;\r\n\t\t\tfor( ; e < last_dynamic_sort_entry; ++e )\r\n\t\t\t{\r\n\t\t\t\tsMesh *p_mesh = p_scene->m_meshes[e];\r\n\r\n\t\t\t\t__asm mov eax, p_mesh\t\t\t// Store mesh pointer.\r\n\t\t\t\t__asm prefetcht0 [eax]\t\t\t// Get first 32 bytes of sMesh structure.\r\n\r\n\t\t\t\tif(( p_mesh->m_flags & sMesh::MESH_FLAG_ACTIVE ) && (( p_mesh->m_flags & ( sMesh::MESH_FLAG_SHADOW_VOLUME | sMesh::MESH_FLAG_BILLBOARD )) == 0 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tif( no_culling )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\trender = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\trender = false;\r\n\r\n\t\t\t\t\t\t// Check the visibility mask.\r\n\t\t\t\t\t\tif( p_mesh->m_visibility_mask & viewport )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Frustum cull this set of meshes, using the associated bounding box.\r\n\t\t\t\t\t\t\tif( frustum_check_sphere( &p_mesh->m_sphere_center, p_mesh->m_sphere_radius ))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// Check against any occluders.\r\n\t\t\t\t\t\t\t\tif(( !( flags & vRENDER_OCCLUDED )) || ( !TestSphereAgainstOccluders( &p_mesh->m_sphere_center, p_mesh->m_sphere_radius )))\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\trender = true;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif( render )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Add this mesh to the visible list, providing it is within bounds.\r\n\t\t\t\t\t\tvisible_mesh_array[visible_mesh_array_index] = p_mesh;\r\n\t\t\t\t\t\tif( visible_mesh_array_index < ( VISIBLE_MESH_ARRAY_SIZE - 1 ))\r\n\t\t\t\t\t\t\t++visible_mesh_array_index;\r\n\r\n\t\t\t\t\t\tsortedMeshArray[next_sorted_mesh_entry].p_mesh\t= p_mesh;\r\n\t\t\t\t\t\tsortedMeshArray[next_sorted_mesh_entry].sort\t= boundingSphereNearestZ;\r\n\r\n\t\t\t\t\t\t++next_sorted_mesh_entry;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif( next_sorted_mesh_entry > 0 )\r\n\t\t\t{\r\n\t\t\t\t// Sort the array into ascending sort order.\r\n\t\t\t\tqsort( sortedMeshArray, next_sorted_mesh_entry, sizeof( sSortedMeshEntry ), cmp );\r\n\t\t\r\n\t\t\t\tfor( int m = 0; m < next_sorted_mesh_entry; ++m )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( sortedMeshArray[m].p_mesh->mp_material != p_material )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsortedMeshArray[m].p_mesh->mp_material->Submit();\r\n\t\t\t\t\t\tp_material = sortedMeshArray[m].p_mesh->mp_material;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsortedMeshArray[m].p_mesh->Submit();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\r\n\t\t\t// Third stage - meshes after the dynamically sorted set.\r\n\t\t\tfor( ; e < p_scene->m_num_mesh_entries; ++e )\r\n\t\t\t{\r\n\t\t\t\tsMesh *p_mesh = p_scene->m_meshes[e];\r\n\r\n\t\t\t\t__asm mov eax, p_mesh\t\t\t// Store mesh pointer.\r\n\t\t\t\t__asm prefetcht0 [eax]\t\t\t// Get first 32 bytes of sMesh structure.\r\n\r\n\t\t\t\tif(( p_mesh->m_flags & sMesh::MESH_FLAG_ACTIVE ) && (( p_mesh->m_flags & ( sMesh::MESH_FLAG_SHADOW_VOLUME | sMesh::MESH_FLAG_BILLBOARD )) == 0 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tif( no_culling )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\trender = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\trender = false;\r\n\r\n\t\t\t\t\t\t// Check the visibility mask.\r\n\t\t\t\t\t\tif( p_mesh->m_visibility_mask & viewport )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Frustum cull this set of meshes, using the associated bounding box.\r\n\t\t\t\t\t\t\tif( frustum_check_sphere( &p_mesh->m_sphere_center, p_mesh->m_sphere_radius ))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// Check against any occluders.\r\n\t\t\t\t\t\t\t\tif(( !( flags & vRENDER_OCCLUDED )) || ( !TestSphereAgainstOccluders( &p_mesh->m_sphere_center, p_mesh->m_sphere_radius )))\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\trender = true;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif( render )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// If the material has changed, submit the new material.\r\n\t\t\t\t\t\tif( p_mesh->mp_material != p_material )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_material = p_mesh->mp_material;\r\n\t\t\t\t\t\t\tp_material->Submit();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tp_mesh->Submit();\r\n\r\n\t\t\t\t\t\t// Add this mesh to the visible list, providing it is within bounds.\r\n\t\t\t\t\t\tvisible_mesh_array[visible_mesh_array_index] = p_mesh;\r\n\t\t\t\t\t\tif( visible_mesh_array_index < ( VISIBLE_MESH_ARRAY_SIZE - 1 ))\r\n\t\t\t\t\t\t\t++visible_mesh_array_index;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Now draw the semitransparent meshes with shadow mapped on them.\r\n\t\tif( p_scene->m_flags & SCENE_FLAG_RECEIVE_SHADOWS )\r\n\t\t{\r\n\t\t\trender_shadow_meshes( p_scene, visible_mesh_array, visible_mesh_array_index );\r\n\t\t}\r\n\r\n\t\tif( flags & vRENDER_BILLBOARDS )\r\n\t\t{\r\n\t\t\tBillboardManager.Render( vRENDER_SEMITRANSPARENT );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid render_light_glows( bool test )\r\n{\r\n\tstruct sLightGlowVert\r\n\t{\r\n\t\tD3DVECTOR\tm_pos;\r\n\t\tD3DCOLOR\tm_col;\r\n\t};\r\n\r\n\tstatic sLightGlowVert verts[4];\r\n\r\n\t// This function will be called twice per render, once to test the amount of pixels drawn,\r\n\t// the other to actually draw the pixels.\r\n\r\n\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\r\n\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t// Get the 'right' vector as the cross product of camera 'at' and world 'up'.\r\n\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\tscreen_right.Normalize();\r\n\tscreen_up.Normalize();\r\n\r\n\tsLightGlowDetailsTable.IterateStart();\r\n\tsLightGlowDetails *p_details = sLightGlowDetailsTable.IterateNext();\r\n\r\n\tif( test )\r\n\t{\r\n\t\t// Turn of z and color writes.\r\n//\t\tD3DDevice_SetRenderState( D3DRS_COLORWRITEENABLE,\t0 );\r\n\t\tD3DDevice_SetRenderState( D3DRS_ZWRITEENABLE,\t\tFALSE );\r\n\r\n\t\tset_blend_mode( vBLEND_MODE_DIFFUSE );\r\n\t\tset_texture( 0, NULL );\r\n\t\tset_pixel_shader( PixelShader5 );\r\n\t\tset_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\r\n\t\twhile( p_details )\r\n\t\t{\r\n\t\t\t// Get a new test index.\r\n\t\t\tuint32 index = p_details->m_visibility_test_fifo.AddStatus();\r\n\r\n\t\t\t// Only do the check if there is room on the queue.\r\n\t\t\tif( index > 0 )\r\n\t\t\t{\r\n\t\t\t\t// For each light glow instance, add a render check.\r\n\t\t\t\tD3DDevice_BeginVisibilityTest();\r\n\r\n\t\t\t\t// Draw the glow.\r\n\t\t\t\tverts[0].m_pos.x\t= p_details->m_pos[X] - ( screen_right[X] * p_details->m_test_radius ) - ( screen_up[X] * p_details->m_test_radius );\r\n\t\t\t\tverts[0].m_pos.y\t= p_details->m_pos[Y] - ( screen_right[Y] * p_details->m_test_radius ) - ( screen_up[Y] * p_details->m_test_radius );\r\n\t\t\t\tverts[0].m_pos.z\t= p_details->m_pos[Z] - ( screen_right[Z] * p_details->m_test_radius ) - ( screen_up[Z] * p_details->m_test_radius );\r\n\t\t\t\tverts[0].m_col\t\t= 0xFFFFFFFF;\r\n\r\n\t\t\t\tverts[1].m_pos.x\t= p_details->m_pos[X] - ( screen_right[X] * p_details->m_test_radius ) + ( screen_up[X] * p_details->m_test_radius );\r\n\t\t\t\tverts[1].m_pos.y\t= p_details->m_pos[Y] - ( screen_right[Y] * p_details->m_test_radius ) + ( screen_up[Y] * p_details->m_test_radius );\r\n\t\t\t\tverts[1].m_pos.z\t= p_details->m_pos[Z] - ( screen_right[Z] * p_details->m_test_radius ) + ( screen_up[Z] * p_details->m_test_radius );\r\n\t\t\t\tverts[1].m_col\t\t= 0xFFFFFFFF;\r\n\r\n\t\t\t\tverts[2].m_pos.x\t= p_details->m_pos[X] + ( screen_right[X] * p_details->m_test_radius ) + ( screen_up[X] * p_details->m_test_radius );\r\n\t\t\t\tverts[2].m_pos.y\t= p_details->m_pos[Y] + ( screen_right[Y] * p_details->m_test_radius ) + ( screen_up[Y] * p_details->m_test_radius );\r\n\t\t\t\tverts[2].m_pos.z\t= p_details->m_pos[Z] + ( screen_right[Z] * p_details->m_test_radius ) + ( screen_up[Z] * p_details->m_test_radius );\r\n\t\t\t\tverts[2].m_col\t\t= 0xFFFFFFFF;\r\n\r\n\t\t\t\tverts[3].m_pos.x\t= p_details->m_pos[X] + ( screen_right[X] * p_details->m_test_radius ) - ( screen_up[X] * p_details->m_test_radius );\r\n\t\t\t\tverts[3].m_pos.y\t= p_details->m_pos[Y] + ( screen_right[Y] * p_details->m_test_radius ) - ( screen_up[Y] * p_details->m_test_radius );\r\n\t\t\t\tverts[3].m_pos.z\t= p_details->m_pos[Z] + ( screen_right[Z] * p_details->m_test_radius ) - ( screen_up[Z] * p_details->m_test_radius );\r\n\t\t\t\tverts[3].m_col\t\t= 0xFFFFFFFF;\r\n\r\n\t\t\t\tD3DDevice_DrawVerticesUP( D3DPT_QUADLIST, 4, verts, sizeof( sLightGlowVert ));\r\n\r\n\t\t\t\t// Push a visibility check onto the queue.\r\n\t\t\t\tD3DDevice_EndVisibilityTest( index );\r\n\t\t\t}\r\n\r\n\t\t\tp_details = sLightGlowDetailsTable.IterateNext();\r\n\t\t}\r\n\r\n\t\t// Restore z and color writes.\r\n\t\tD3DDevice_SetRenderState( D3DRS_COLORWRITEENABLE,\tD3DCOLORWRITEENABLE_ALL );\r\n\t\tD3DDevice_SetRenderState( D3DRS_ZWRITEENABLE,\t\tTRUE );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tset_blend_mode( vBLEND_MODE_BLEND );\r\n\t\tset_pixel_shader( PixelShader5 );\r\n\t\tset_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\r\n\t\twhile( p_details )\r\n\t\t{\r\n\t\t\t// Get the visibility check result.\r\n\t\t\tuint32 result = p_details->m_visibility_test_fifo.GetStatus();\r\n\r\n\t\t\tif( result > 0 )\r\n\t\t\t{\r\n\t\t\t\t// Tend the radius towards the target.\r\n\t\t\t\tp_details->m_current_radius += ( p_details->m_glow_radius - p_details->m_current_radius ) * p_details->m_radius_growth;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Tend the radius towards zero.\r\n\t\t\t\tp_details->m_current_radius -= p_details->m_current_radius * p_details->m_radius_growth;\r\n\t\t\t}\r\n\r\n\t\t\tif( p_details->\r\n\t\t\t\tm_current_radius > 0.0f )\r\n\t\t\t{\r\n\t\t\t\t// Draw the glow.\r\n\t\t\t\tverts[0].m_pos.x\t= p_details->m_pos[X] - ( screen_right[X] * p_details->m_current_radius ) - ( screen_up[X] * p_details->m_current_radius );\r\n\t\t\t\tverts[0].m_pos.y\t= p_details->m_pos[Y] - ( screen_right[Y] * p_details->m_current_radius ) - ( screen_up[Y] * p_details->m_current_radius );\r\n\t\t\t\tverts[0].m_pos.z\t= p_details->m_pos[Z] - ( screen_right[Z] * p_details->m_current_radius ) - ( screen_up[Z] * p_details->m_current_radius );\r\n\t\t\t\tverts[0].m_col\t\t= 0x40FFFFFF;\r\n\r\n\t\t\t\tverts[1].m_pos.x\t= p_details->m_pos[X] - ( screen_right[X] * p_details->m_current_radius ) + ( screen_up[X] * p_details->m_current_radius );\r\n\t\t\t\tverts[1].m_pos.y\t= p_details->m_pos[Y] - ( screen_right[Y] * p_details->m_current_radius ) + ( screen_up[Y] * p_details->m_current_radius );\r\n\t\t\t\tverts[1].m_pos.z\t= p_details->m_pos[Z] - ( screen_right[Z] * p_details->m_current_radius ) + ( screen_up[Z] * p_details->m_current_radius );\r\n\t\t\t\tverts[1].m_col\t\t= 0x40FFFFFF;\r\n\r\n\t\t\t\tverts[2].m_pos.x\t= p_details->m_pos[X] + ( screen_right[X] * p_details->m_current_radius ) + ( screen_up[X] * p_details->m_current_radius );\r\n\t\t\t\tverts[2].m_pos.y\t= p_details->m_pos[Y] + ( screen_right[Y] * p_details->m_current_radius ) + ( screen_up[Y] * p_details->m_current_radius );\r\n\t\t\t\tverts[2].m_pos.z\t= p_details->m_pos[Z] + ( screen_right[Z] * p_details->m_current_radius ) + ( screen_up[Z] * p_details->m_current_radius );\r\n\t\t\t\tverts[2].m_col\t\t= 0x40FFFFFF;\r\n\r\n\t\t\t\tverts[3].m_pos.x\t= p_details->m_pos[X] + ( screen_right[X] * p_details->m_current_radius ) - ( screen_up[X] * p_details->m_current_radius );\r\n\t\t\t\tverts[3].m_pos.y\t= p_details->m_pos[Y] + ( screen_right[Y] * p_details->m_current_radius ) - ( screen_up[Y] * p_details->m_current_radius );\r\n\t\t\t\tverts[3].m_pos.z\t= p_details->m_pos[Z] + ( screen_right[Z] * p_details->m_current_radius ) - ( screen_up[Z] * p_details->m_current_radius );\r\n\t\t\t\tverts[3].m_col\t\t= 0x40FFFFFF;\r\n\r\n\t\t\t\tD3DDevice_DrawVerticesUP( D3DPT_QUADLIST, 4, verts, sizeof( sLightGlowVert ));\r\n\t\t\t}\r\n\r\n\t\t\tp_details = sLightGlowDetailsTable.IterateNext();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/render.h",
    "content": "#ifndef __RENDER_H\r\n#define __RENDER_H\r\n\r\n#include <xgmath.h>\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n#include <gfx/xbox/p_nxmodel.h>\r\n#include \"mesh.h\"\r\n\r\n#define\t\tRS_ZWRITEENABLE\t\t\t1\r\n#define\t\tRS_ZTESTENABLE\t\t\t2\r\n#define\t\tRS_ALPHACUTOFF\t\t\t3\r\n#define\t\tRS_UVADDRESSMODE0\t\t4\r\n#define\t\tRS_UVADDRESSMODE1\t\t5\r\n#define\t\tRS_UVADDRESSMODE2\t\t6\r\n#define\t\tRS_UVADDRESSMODE3\t\t7\r\n#define\t\tRS_MIPLODBIASPASS0\t\t8\r\n#define\t\tRS_MIPLODBIASPASS1\t\t9\r\n#define\t\tRS_MIPLODBIASPASS2\t\t10\r\n#define\t\tRS_MIPLODBIASPASS3\t\t11\r\n#define\t\tRS_CULLMODE\t\t\t\t16\r\n#define\t\tRS_ALPHABLENDENABLE\t\t17\r\n#define\t\tRS_ALPHATESTENABLE\t\t18\r\n#define\t\tRS_SPECULARENABLE\t\t19\r\n#define\t\tRS_FOGENABLE\t\t\t20\r\n#define\t\tRS_ZBIAS\t\t\t\t21\r\n#define\t\tRS_MINMAGFILTER0\t\t32\r\n#define\t\tRS_MINMAGFILTER1\t\t33\r\n#define\t\tRS_MINMAGFILTER2\t\t34\r\n#define\t\tRS_MINMAGFILTER3\t\t35\r\n\r\nextern\t\tDWORD PixelShader0;\r\nextern\t\tDWORD PixelShader0IVA;\r\nextern\t\tDWORD PixelShader1;\r\nextern\t\tDWORD PixelShader2;\r\nextern\t\tDWORD PixelShader3;\r\nextern\t\tDWORD PixelShader4;\r\nextern\t\tDWORD PixelShader5;\r\nextern\t\tDWORD PixelShaderBrighten;\r\nextern\t\tDWORD PixelShaderBrightenIVA;\r\nextern\t\tDWORD PixelShaderFocusBlur;\r\nextern\t\tDWORD PixelShaderFocusIntegrate;\r\nextern\t\tDWORD PixelShaderFocusLookupIntegrate;\r\nextern\t\tDWORD PixelShaderNULL;\r\nextern\t\tDWORD PixelShaderPointSprite;\r\nextern\t\tDWORD PixelShaderBumpWater;\r\n\r\nnamespace NxXbox\r\n{\r\n\tstruct sTextureProjectionDetails\r\n\t{\r\n\t\tsTexture\t\t*p_texture;\r\n\t\tNx::CXboxModel\t*p_model;\r\n\t\tsScene\t\t\t*p_scene;\r\n\t\tXGMATRIX\t\tview_matrix;\r\n\t\tXGMATRIX\t\tprojection_matrix;\r\n\t\tXGMATRIX\t\ttexture_projection_matrix;\r\n\t};\r\n\r\n\r\n\textern Lst::HashTable< sTextureProjectionDetails > *pTextureProjectionDetailsTable;\r\n\r\n\t\r\n\ttypedef enum\r\n\t{\r\n\t\tvBLEND_MODE_DIFFUSE,\t\t\t\t\t\t\t\t// ( 0 - 0 ) * 0 + Src\r\n\t\tvBLEND_MODE_ADD,\t\t\t\t\t\t\t\t\t// ( Src - 0 ) * Src + Dst\r\n\t\tvBLEND_MODE_ADD_FIXED,\t\t\t\t\t\t\t\t// ( Src - 0 ) * Fixed + Dst\r\n\t\tvBLEND_MODE_SUBTRACT,\t\t\t\t\t\t\t\t// ( 0 - Src ) * Src + Dst\r\n\t\tvBLEND_MODE_SUB_FIXED,\t\t\t\t\t\t\t\t// ( 0 - Src ) * Fixed + Dst\r\n\t\tvBLEND_MODE_BLEND,\t\t\t\t\t\t\t\t\t// ( Src * Dst ) * Src + Dst\t\r\n\t\tvBLEND_MODE_BLEND_FIXED,\t\t\t\t\t\t\t// ( Src * Dst ) * Fixed + Dst\t\r\n\t\tvBLEND_MODE_MODULATE,\t\t\t\t\t\t\t\t// ( Dst - 0 ) * Src + 0\r\n\t\tvBLEND_MODE_MODULATE_FIXED,\t\t\t\t\t\t\t// ( Dst - 0 ) * Fixed + 0\t\r\n\t\tvBLEND_MODE_BRIGHTEN,\t\t\t\t\t\t\t\t// ( Dst - 0 ) * Src + Dst\r\n\t\tvBLEND_MODE_BRIGHTEN_FIXED,\t\t\t\t\t\t\t// ( Dst - 0 ) * Fixed + Dst\t\r\n\t\tvBLEND_MODE_GLOSS_MAP,\t\t\t\t\t\t\t\t// Specular = Specular * Src\t- special mode for gloss mapping\r\n\t\tvBLEND_MODE_BLEND_PREVIOUS_MASK,\t\t\t\t\t// ( Src - Dst ) * Dst + Dst\r\n\t\tvBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK,\t\t\t// ( Dst - Src ) * Dst + Src\r\n\r\n\t\tvBLEND_MODE_MODULATE_COLOR\t\t\t\t\t= 15,\t// ( Dst - 0 ) * Src(col) + 0\t- special mode for the shadow.\r\n\t\tvBLEND_MODE_ONE_INV_SRC_ALPHA\t\t\t\t= 17,\t//\t\t\t\t\t\t\t\t- special mode for imposter rendering.\r\n\r\n\t\tvNUM_BLEND_MODES\r\n\t} BlendModes; \r\n\r\n\ttypedef enum\r\n\t{\r\n\t\tvRENDER_OPAQUE\t\t\t\t\t\t\t\t= 1,\t\t\t\t\t\t\r\n\t\tvRENDER_SEMITRANSPARENT\t\t\t\t\t\t= 2,\r\n\t\tvRENDER_OCCLUDED\t\t\t\t\t\t\t= 4,\r\n\t\tvRENDER_NO_CULLING\t\t\t\t\t\t\t= 8,\t\t// Used for instances which have already been culled at a higher level\r\n\t\tvRENDER_SORT_FRONT_TO_BACK\t\t\t\t\t= 16,\t\t// Used to improve pixel rejection tests for opaque rendering only\r\n\t\tvRENDER_SHADOW_VOLUMES\t\t\t\t\t\t= 32,\t\t// Used to indicate that only shadow volumes should be (special-case) rendered\r\n\t\tvRENDER_BILLBOARDS\t\t\t\t\t\t\t= 64,\t\t// Used to indicate that billboards should be rendered\r\n\t\tvRENDER_INSTANCE_PRE_WORLD_SEMITRANSPARENT\t= 128,\t\t// Used to indicate that this instance rendering is happening prior to semitransparent world rendering\r\n\t\tvRENDER_INSTANCE_POST_WORLD_SEMITRANSPARENT\t= 256,\t\t// Used to indicate that this instance rendering is happening after semitransparent world rendering\r\n\t} SceneRenderFlags; \r\n\r\n\tBlendModes\tGetBlendMode( uint32 blend_checksum );\r\n\r\n\tvoid\t\tcreate_pixel_shaders();\r\n\tvoid\t\tGetPixelShader( sMaterial *p_material, uint32 *p_pixel_shader_id );\r\n\tvoid\t\tset_pixel_shader( uint32 shader_id );\r\n\tvoid\t\tset_pixel_shader( uint32 shader_id, uint32 num_passes );\r\n\tvoid\t\tset_vertex_shader( DWORD shader_id );\r\n\r\n\tvoid\t\tset_render_state( uint32 type, uint32 state );\r\n\tvoid\t\tset_blend_mode( uint32 mode );\r\n\tvoid\t\tset_texture( uint32 pass, IDirect3DTexture8 *p_texture, IDirect3DPalette8 *p_palette = NULL );\r\n\t\r\n\tvoid\t\tcreate_texture_projection_details( sTexture *p_texture, Nx::CXboxModel *p_model, sScene *p_scene );\r\n\tvoid\t\tdestroy_texture_projection_details( sTexture *p_texture );\r\n\tvoid\t\tset_texture_projection_camera( sTexture *p_texture, XGVECTOR3 *p_pos, XGVECTOR3 *p_at );\r\n\tvoid\t\tcalculate_tex_proj_matrix( XGMATRIX *p_tex_view_matrix, XGMATRIX *p_tex_proj_matrix, XGMATRIX *p_tex_transform_matrix, XGMATRIX *p_world_matrix = NULL );\r\n\t\r\n\t// MSM PERFCHANGE - added scale.\r\n\tvoid\tset_camera( Mth::Matrix *p_matrix, Mth::Vector *p_position, float screen_angle, float aspect_ratio, bool render_at_infinity = false );\r\n\tvoid\tset_frustum_bbox_transform( Mth::Matrix *p_transform );\r\n\tbool\tfrustum_check_sphere( D3DXVECTOR3 *p_center, float radius );\r\n\tfloat\tget_bounding_sphere_nearest_z( void );\r\n\tbool\tIsVisible( Mth::Vector &center, float radius );\r\n\tvoid\trender_shadow_targets();\r\n\tvoid\trender_light_glows( bool test );\r\n\tvoid\trender_scene( sScene *p_scene, uint32 flags = ( vRENDER_OPAQUE | vRENDER_SEMITRANSPARENT ), uint32 viewport = 0 );\r\n\r\n} // namespace NxXbox\r\n\r\n#endif // __RENDER_H\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/scene.cpp",
    "content": "#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <string.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/timer.h>\r\n#include \"texture.h\"\r\n#include \"mesh.h\"\r\n#include \"scene.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint sort_by_material_draw_order( const void *p1, const void *p2 )\r\n{\r\n\tsMesh\t\t*p_mesh1\t\t= *((sMesh**)p1 );\r\n\tsMesh\t\t*p_mesh2\t\t= *((sMesh**)p2 );\r\n\tsMaterial\t*p_material1\t= p_mesh1->mp_material;\r\n\tsMaterial\t*p_material2\t= p_mesh2->mp_material;\r\n\t\r\n\tDbg_Assert( p_material1 != NULL );\r\n\tDbg_Assert( p_material2 != NULL );\r\n\r\n\tif( p_material1->m_draw_order == p_material2->m_draw_order )\r\n\t{\r\n\t\t// Have to do some special case processing for the situation where two or more meshes have the same draw order, but only some are\r\n\t\t// marked as being dynamically sorted. In such a situation the non dynamically sorted ones should come first.\r\n\t\tif( p_material1->m_sorted == p_material2->m_sorted )\r\n\t\t{\r\n\t\t\tif( p_material1 == p_material2 )\r\n\t\t\t{\r\n\t\t\t\t// Same material, no further sorting required.\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// If the pixel shaders are the same, sort by material address, otherwise sort by pixel shader value.\r\n\t\t\t\tif( p_mesh1->m_pixel_shader == p_mesh2->m_pixel_shader )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn ((uint32)p_material1 > (uint32)p_material2 ) ? 1 : -1;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\treturn ((uint32)p_mesh1->m_pixel_shader > (uint32)p_mesh2->m_pixel_shader ) ? 1 : -1;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( p_material1->m_sorted )\r\n\t\t{\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t\treturn -1;\r\n\t}\r\n\treturn ( p_material1->m_draw_order > p_material2->m_draw_order ) ? 1 : -1;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsScene::sScene( void )\r\n{\r\n\tm_flags\t\t\t\t\t\t\t\t= 0;\r\n\r\n\t// No meshes as yet.\r\n\tm_num_mesh_entries\t\t\t\t\t= 0;\r\n\tm_num_semitransparent_mesh_entries\t= 0;\r\n\tm_num_filled_mesh_entries\t\t\t= 0;\r\n\tm_first_dynamic_sort_entry\t\t\t= 0xFFFFFFFFUL;\r\n\tm_first_semitransparent_entry\t\t= 0xFFFFFFFFUL;\r\n\tm_num_dynamic_sort_entries\t\t\t= 0;\r\n\tm_is_dictionary\t\t\t\t\t\t= false;\r\n\r\n\tm_meshes\t\t\t\t\t\t\t= NULL;\r\n\tpMaterialTable\t\t\t\t\t\t= NULL;\r\n\r\n\tmp_hierarchyObjects\t\t\t\t\t= NULL;\r\n\tm_numHierarchyObjects\t\t\t\t= 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsScene::~sScene( void )\r\n{\r\n\t// Remove the material table.\r\n\tif( pMaterialTable )\r\n\t{\r\n\t\tdelete pMaterialTable;\r\n\t}\r\n\r\n\tif( m_meshes != NULL )\r\n\t{\r\n\t\tdelete [] m_meshes;\r\n\t}\r\n\r\n\tif( mp_hierarchyObjects )\r\n\t{\r\n\t\tdelete [] mp_hierarchyObjects;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sScene::FigureBoundingVolumes( void )\r\n{\r\n\t// Figure bounding sphere assuming bounding box has already been set up (during individual mesh initialisation).\r\n\tMth::Vector radial\t= ( m_bbox.GetMax() - m_bbox.GetMin() ) * 0.5f;\r\n\tMth::Vector center\t= m_bbox.GetMin() + radial;\r\n\tm_sphere_center\t\t= D3DXVECTOR3( center[X], center[Y], center[Z] );\r\n\tm_sphere_radius\t\t= sqrtf(( radial[X] * radial[X] ) +\t( radial[Y] * radial[Y] ) + ( radial[Z] * radial[Z] ));\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sScene::CountMeshes( int num_meshes, sMesh **pp_meshes )\r\n{\r\n\t// Count each mesh.\r\n\tfor( int m = 0; m < num_meshes; ++m )\r\n\t{\r\n\t\t++m_num_mesh_entries;\r\n\t\tbool transparent = (( pp_meshes[m]->mp_material ) && ( pp_meshes[m]->mp_material->m_flags[0] & 0x40 ));\r\n\t\tif( transparent )\r\n\t\t{\r\n\t\t\t++m_num_semitransparent_mesh_entries;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sScene::CreateMeshArrays( void )\r\n{\r\n\tif( m_num_mesh_entries > 0 )\r\n\t{\r\n\t\tm_meshes = new sMesh*[m_num_mesh_entries];\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sScene::AddMeshes( int num_meshes, sMesh **pp_meshes )\r\n{\r\n\t// Add each mesh.\r\n\tfor( int m = 0; m < num_meshes; ++m )\r\n\t{\r\n\t\tDbg_Assert( m_num_filled_mesh_entries < m_num_mesh_entries );\r\n\t\tm_meshes[m_num_filled_mesh_entries] = pp_meshes[m];\r\n\t\t++m_num_filled_mesh_entries;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sScene::RemoveMeshes( int num_meshes, sMesh **pp_meshes )\r\n{\r\n\tint num_mesh_entries_removed\t\t\t\t= 0;\r\n\t\r\n\tfor( int m = 0; m < num_meshes; ++m )\r\n\t{\r\n\t\tsMesh *p_mesh = pp_meshes[m];\r\n\r\n\t\tbool found = false;\r\n\t\tfor( int i = 0; i < m_num_mesh_entries; ++i )\r\n\t\t{\r\n\t\t\tif( m_meshes[i] == p_mesh )\r\n\t\t\t{\r\n\t\t\t\tfound = true;\r\n\t\t\t\tm_meshes[i] = NULL;\r\n\t\t\t\t++num_mesh_entries_removed;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tDbg_Assert( found );\t\r\n\t}\r\n\t\r\n\t// Now go through and compact the arrays.\r\n\twhile( num_mesh_entries_removed > 0 )\r\n\t{\r\n\t\tfor( int i = 0; i < m_num_mesh_entries; ++i )\r\n\t\t{\r\n\t\t\tif( m_meshes[i] == NULL )\r\n\t\t\t{\r\n\t\t\t\t// Only worth copying if there is anything beyond this mesh.\r\n\t\t\t\tif( i < ( m_num_mesh_entries - 1 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tCopyMemory( &m_meshes[i], &m_meshes[i + 1], sizeof( sMesh* ) * ( m_num_mesh_entries - ( i + 1 )));\r\n\t\t\t\t}\r\n\t\t\t\t--num_mesh_entries_removed;\r\n\t\t\t\t--m_num_mesh_entries;\r\n\t\t\t\t--m_num_filled_mesh_entries;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Finally, scan through and mark the start and end of the dynamically sorted set of meshes.\r\n\tm_num_semitransparent_mesh_entries\t= 0;\r\n\tm_num_dynamic_sort_entries\t\t\t= 0;\r\n\tm_first_semitransparent_entry\t\t= m_num_mesh_entries;\r\n\tm_first_dynamic_sort_entry\t\t\t= m_num_mesh_entries;\r\n\t\r\n\tfor( int i = 0; i < m_num_mesh_entries; ++i )\r\n\t{\r\n\t\tbool transparent = (( m_meshes[i]->mp_material ) && ( m_meshes[i]->mp_material->m_flags[0] & 0x40 ));\r\n\t\tif( transparent )\r\n\t\t{\r\n\t\t\t++m_num_semitransparent_mesh_entries;\r\n\r\n\t\t\tif( i < m_first_semitransparent_entry )\r\n\t\t\t{\r\n\t\t\t\tm_first_semitransparent_entry = i;\r\n\t\t\t}\r\n\r\n\t\t\tif( m_meshes[i]->mp_material->m_sorted )\r\n\t\t\t{\r\n\t\t\t\t++m_num_dynamic_sort_entries;\r\n\t\t\t\tif( i < m_first_dynamic_sort_entry )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_first_dynamic_sort_entry = i;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sScene::SortMeshes( void )\r\n{\r\n\t// Sort the list of meshes.\r\n\tqsort( m_meshes, m_num_mesh_entries, sizeof( sMesh* ), sort_by_material_draw_order );\r\n\r\n\t// Now scan through and mark the start and end of the dynamically sorted set of meshes.\r\n\tm_num_semitransparent_mesh_entries\t= 0;\r\n\tm_first_semitransparent_entry\t\t= m_num_mesh_entries;\r\n\tm_first_dynamic_sort_entry\t\t\t= m_num_mesh_entries;\r\n\tm_num_dynamic_sort_entries\t\t\t= 0;\r\n\tfor( int i = 0; i < m_num_mesh_entries; ++i )\r\n\t{\r\n\t\tbool transparent = (( m_meshes[i]->mp_material ) && ( m_meshes[i]->mp_material->m_flags[0] & 0x40 ));\r\n\t\tif( transparent )\r\n\t\t{\r\n\t\t\t++m_num_semitransparent_mesh_entries;\r\n\r\n\t\t\tif( i < m_first_semitransparent_entry )\r\n\t\t\t{\r\n\t\t\t\tm_first_semitransparent_entry = i;\r\n\t\t\t}\r\n\r\n\t\t\tif( m_meshes[i]->mp_material->m_sorted )\r\n\t\t\t{\r\n\t\t\t\t++m_num_dynamic_sort_entries;\r\n\t\t\t\tif( i < m_first_dynamic_sort_entry )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_first_dynamic_sort_entry = i;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsMesh *sScene::GetMeshByLoadOrder( int load_order )\r\n{\r\n\tfor( int i = 0; i < m_num_mesh_entries; ++i )\r\n\t{\r\n\t\tif( m_meshes[i]->m_load_order == load_order )\r\n\t\t{\r\n\t\t\treturn m_meshes[i];\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsMaterial *sScene::GetMaterial( uint32 checksum )\r\n{\r\n\tif( pMaterialTable )\r\n\t{\r\n\t\tpMaterialTable->IterateStart();\r\n\t\tsMaterial *p_mat = pMaterialTable->IterateNext();\r\n\t\twhile( p_mat )\r\n\t\t{\r\n\t\t\tif( p_mat->m_checksum == checksum )\r\n\t\t\t{\r\n\t\t\t\treturn p_mat;\r\n\t\t\t}\r\n\t\t\tp_mat = pMaterialTable->IterateNext();\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\nconst uint32\tINDEX_WORKBUFFER_SIZE\t= 3072;\r\nstatic uint16\tindex_workbuffer[INDEX_WORKBUFFER_SIZE];\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sScene::HidePolys( uint32 mask, sCASData *p_cas_data, uint32 num_entries )\r\n{\r\n\tif(( num_entries == 0 ) || ( mask == 0 ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n//\tTmr::Time start = Tmr::GetTimeInUSeconds();\r\n\t\r\n\tint indices_added[64];\r\n\tZeroMemory( indices_added, sizeof( int ) * 64 );\r\n\t\r\n\t// Check against every CAS entry.\r\n\tsCASData *p_cas_entry = p_cas_data;\r\n\tfor( uint32 entry = 0; entry < num_entries; ++entry, ++p_cas_entry )\r\n\t{\r\n\t\t// Check this CAS entry has the correct mask...\r\n\t\tif( p_cas_entry->mask & mask )\r\n\t\t{\r\n\t\t\t// Get the mesh this entry references.\r\n\t\t\tuint32\tload_order\t= p_cas_entry->data0 >> 16;\r\n\t\t\tsMesh\t*p_mesh\t\t= GetMeshByLoadOrder( load_order );\r\n\r\n\t\t\tDbg_Assert( load_order < 32 );\r\n\t\t\t\r\n\t\t\tif( p_mesh == NULL )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Get the indices of the poly referenced.\r\n//\t\t\tuint32 i0 = ( p_cas_entry->data0 & 0xFFFF ) - p_mesh->m_index_base;\r\n\t\t\tuint32 i0 = p_cas_entry->data0 & 0xFFFF;\r\n//\t\t\tuint32 i1 = ( p_cas_entry->data1 >> 16 ) - p_mesh->m_index_base;\r\n\t\t\tuint32 i1 = p_cas_entry->data1 >> 16;\r\n//\t\t\tuint32 i2 = ( p_cas_entry->data1 & 0xFFFF ) - p_mesh->m_index_base;\r\n\t\t\tuint32 i2 = p_cas_entry->data1 & 0xFFFF;\r\n\r\n\t\t\t// For every vertex index in this mesh...\r\n\t\t\tuint16 *p_indices\t= p_mesh->mp_index_buffer[0];\r\n\t\t\tuint32 index0\t\t= p_indices[p_cas_entry->start_index] & 0x7FFF;\r\n\t\t\tuint32 index1\t\t= p_indices[p_cas_entry->start_index + 1] & 0x7FFF;\r\n\t\t\tfor( uint32 i = p_cas_entry->start_index + 2; i < p_mesh->m_num_indices[0]; ++i )\r\n\t\t\t{\r\n\t\t\t\tuint32 index2 = p_indices[i] & 0x7FFF;\r\n\t\t\t\tif(( index0 == i0 ) && ( index1 == i1 ) && ( index2 == i2 ))\r\n\t\t\t\t{\r\n\t\t\t\t\t// Indicate this mesh will need rebuilding.\r\n\t\t\t\t\tindices_added[load_order] = indices_added[load_order] + 1;\r\n\r\n\t\t\t\t\t// Flag the second index of the poly.\r\n\t\t\t\t\tp_indices[i - 1] |= 0x8000;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tindex0\t= index1;\r\n\t\t\t\tindex1\t= index2;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Now rebuild those meshes that need it.\r\n\tfor( int m = 0; m < m_num_mesh_entries; ++m )\r\n\t{\r\n\t\tsMesh *p_mesh = m_meshes[m];\r\n\t\tif( indices_added[p_mesh->m_load_order] > 0 )\r\n\t\t{\r\n\t\t\tuint16 *p_indices\t\t\t\t\t\t= p_mesh->mp_index_buffer[0];\r\n\t\t\tuint32 new_indices_index\t\t\t\t= 0;\r\n\t\t\tfor( uint32 i = 0; i < p_mesh->m_num_indices[0]; ++i )\r\n\t\t\t{\r\n\t\t\t\tuint16 index = p_indices[i];\r\n\t\t\t\t\r\n\t\t\t\tDbg_Assert( new_indices_index < INDEX_WORKBUFFER_SIZE );\r\n\t\t\t\tindex_workbuffer[new_indices_index++]\t= index & 0x7FFF;\r\n\r\n\t\t\t\tif( index & 0x8000 )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( new_indices_index < INDEX_WORKBUFFER_SIZE );\r\n\t\t\t\t\tindex_workbuffer[new_indices_index++]\t= index & 0x7FFF;\r\n\t\t\t\t\tDbg_Assert( new_indices_index < INDEX_WORKBUFFER_SIZE );\r\n\t\t\t\t\tindex_workbuffer[new_indices_index++]\t= index & 0x7FFF;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Create new index buffer, on the same heap as the existing index buffer.\r\n\t\t\tMem::Allocator::BlockHeader*\tp_bheader\t= Mem::Allocator::BlockHeader::sRead( p_mesh->mp_index_buffer[0] );\r\n\t\t\tMem::Allocator*\t\t\t\t\tp_allocater\t= p_bheader->mpAlloc;\r\n\t\t\tMem::Manager::sHandle().PushContext( p_allocater );\r\n\r\n\t\t\tdelete [] p_mesh->mp_index_buffer[0];\r\n\t\t\tp_mesh->m_num_indices[0]\t= (uint16)new_indices_index;\r\n\t\t\tp_mesh->mp_index_buffer[0]\t= new uint16[p_mesh->m_num_indices[0]];\r\n\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t\t// And copy in the new indices from the workbuffer.\r\n\t\t\tCopyMemory( p_mesh->mp_index_buffer[0], index_workbuffer, sizeof( uint16 ) * p_mesh->m_num_indices[0] );\r\n\t\t}\r\n\t}\r\n\r\n//\tTmr::Time end = Tmr::GetTimeInUSeconds() - start;\r\n//\tprintf( \"HidePolys() took %ld u seconds\\n\", end );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsScene *LoadScene( const char *Filename, sScene *pScene )\r\n{\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid DeleteScene( sScene *pScene )\r\n{\r\n\t// Iterate through the table of materials, deleting them.\r\n\tif( pScene->pMaterialTable )\r\n\t{\r\n\t\tpScene->pMaterialTable->IterateStart();\r\n\t\tsMaterial* p_mat = pScene->pMaterialTable->IterateNext();\r\n\t\twhile( p_mat )\r\n\t\t{\r\n\t\t\tdelete p_mat;\r\n\t\t\tp_mat = pScene->pMaterialTable->IterateNext();\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Delete the scene itself.\r\n\tdelete pScene;\r\n}\r\n\r\n\r\n\r\nsScene *sScene::pHead;\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/scene.h",
    "content": "#ifndef __SCENE_H\r\n#define __SCENE_H\r\n\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n#include <gfx/NxHierarchy.h>\r\n#include \"texture.h\"\r\n#include \"mesh.h\"\r\n#include \"material.h\"\r\n#include \"anim.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n\r\nstruct sMeshEntry\r\n{\r\n\tsMesh*\t\t\t\t\tmp_mesh;\t\t\t// Pointer to mesh.\r\n\tint\t\t\t\t\t\tm_bbox;\t\t\t\t// Bounding box index.\r\n};\r\n\r\n#define SCENE_FLAG_RENDERING_SHADOW\t\t( 1 << 7 )\r\n#define SCENE_FLAG_RECEIVE_SHADOWS\t\t( 1 << 8 )\r\n#define SCENE_FLAG_SELF_SHADOWS\t\t\t( 1 << 9 )\r\n\r\nstruct sScene\r\n{\r\n\t\t\t\t\t\t\t\tsScene( void );\r\n\t\t\t\t\t\t\t\t~sScene( void );\r\n\r\n\tsMaterial *\t\t\t\t\tsScene::GetMaterial( uint32 checksum );\r\n\tvoid\t\t\t\t\t\tCountMeshes( int num_meshes, sMesh **pp_meshes );\r\n\tvoid\t\t\t\t\t\tCreateMeshArrays( void );\r\n\tvoid\t\t\t\t\t\tAddMeshes( int num_meshes, sMesh **pp_meshes );\r\n\tvoid\t\t\t\t\t\tRemoveMeshes( int num_meshes, sMesh **pp_meshes );\r\n\tvoid\t\t\t\t\t\tSortMeshes( void );\r\n\tsMesh\t\t\t\t\t\t*GetMeshByLoadOrder( int load_order );\r\n\tvoid\t\t\t\t\t\tFigureBoundingVolumes( void );\r\n\tvoid\t\t\t\t\t\tHidePolys( uint32 mask, sCASData *p_cas_data, uint32 num_entries );\r\n\t\r\n\tuint32\t\t\t\t\t\tm_flags;\r\n\tint\t\t\t\t\t\t\tNumTextures;\r\n\tuint8\t\t\t\t\t\t*pTexBuffer;\r\n\tuint8\t\t\t\t\t\t*pTexDma;\r\n\tsTexture\t\t\t\t\t*pTextures;\r\n\r\n\tint\t\t\t\t\t\t\tNumMaterials;\r\n\tLst::HashTable< sMaterial >\t*pMaterialTable;\r\n\t\r\n\tsMesh\t\t\t\t\t\t**m_meshes;\r\n\tint\t\t\t\t\t\t\tm_num_mesh_entries;\r\n\tint\t\t\t\t\t\t\tm_num_semitransparent_mesh_entries;\t\t// Used for making scene level draw order decisions.\r\n\tint\t\t\t\t\t\t\tm_num_filled_mesh_entries;\r\n\tint\t\t\t\t\t\t\tm_first_semitransparent_entry;\r\n\tint\t\t\t\t\t\t\tm_first_dynamic_sort_entry;\r\n\tint\t\t\t\t\t\t\tm_num_dynamic_sort_entries;\r\n\t\r\n\tclass CInstance\t\t\t\t*pInstances;\r\n\r\n\tsScene\t\t\t\t\t\t*pNext;\r\n\r\n\tstatic sScene\t\t\t\t*pHead;\r\n\r\n\tbool\t\t\t\t\t\tm_is_dictionary;\r\n\r\n\tMth::CBBox\t\t\t\t\tm_bbox;\t\r\n\tD3DXVECTOR3\t\t\t\t\tm_sphere_center;\r\n\tfloat\t\t\t\t\t\tm_sphere_radius;\r\n\r\n\t// For mesh heirarchies.\r\n\tNx::CHierarchyObject*\t\tmp_hierarchyObjects;\t\t\t\t\t\t// Array of hierarchy objects.\r\n\tint\t\t\t\t\t\t\tm_numHierarchyObjects;\t\t\t\t\t\t// Number of hierarchy objects.\r\n};\r\n\r\n\r\nsScene\t*LoadScene( const char *Filename, sScene *pScene );\r\nvoid\tDeleteScene( sScene *pScene );\r\nint\t\tsort_by_material_draw_order( const void *p1, const void *p2 );\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n\r\n#endif // __SCENE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/screenfx.cpp",
    "content": "#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <xgraphics.h>\r\n#include \"nx_init.h\"\r\n#include \"render.h\"\r\n#include \"screenfx.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// A filter sample holds a subpixel offset and a filter value\r\n// to be multiplied by a source texture to compute an arbitrary\r\n// filter.  See filter_copy for more details.\r\n//-----------------------------------------------------------------------------\r\nstruct FilterSample \r\n{\r\n    FLOAT fValue;               // Coefficient\r\n    FLOAT fOffsetX, fOffsetY;   // Subpixel offsets of supersamples in destination coordinates\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// The depth-mapping pixel shader attempts to do higher precision\r\n// math with eight-bit color registers.  The _x4 instruction modifier\r\n// is used twice to get a 16x range of values.\r\n//-----------------------------------------------------------------------------\r\nFLOAT g_fPixelShaderScale = 16.0f;   // to get into the right range, we scale up the value in the pixel shader\r\nFLOAT m_fDepth0\t= 0.900f;\r\nFLOAT m_fDepth1\t= 0.997f;\r\nD3DTexture* m_pTextureFocusRange = NULL;   // Lookup table for range of z values to use\r\n\r\n// Enumeration of blur filters available in this sample to compare the speed and quality of different types of blur filters for\r\n// the out-of-focus parts of the scene.\r\nenum FILTERMODE \r\n{\r\n        FM_BOX,\r\n        FM_VERT,\r\n        FM_HORIZ, \r\n        FM_BOX2,\r\n        FM_VERT2,\r\n        FM_HORIZ2,\r\n        FM_BOX2_BOX2,\r\n\t\tFM_VERT2_HORIZ2,\r\n        FM_HORIZ2_VERT2,\r\n        FM_VERT2_HORIZ,\r\n        FM_HORIZ2_VERT,\r\n        FM_VERT2_HORIZ2_BOX2,\r\n        FM_BOX2_BOX2_BOX2,\r\n        FM_VERT2_HORIZ2_VERT2,\r\n        FM_HORIZ2_VERT2_HORIZ2,\r\n        FM_VERT2_HORIZ2_VERT2_HORIZ2,\r\n        FM_HORIZ2_VERT2_HORIZ2_VERT2,\r\n        FM_BOX2_BOX2_BOX2_BOX2,\r\n        _FM_MAX\r\n    };\r\n\r\n\r\n\r\n\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n\r\nvoid draw_rain( void )\r\n{\r\n\tstatic float table_x[512];\r\n\tstatic float table_y[512];\r\n\tstatic bool table_set = false;\r\n\tstatic int table_index = 0;\r\n\tif( !table_set )\r\n\t{\r\n\t\ttable_set = true;\r\n\t\tfor( int i = 0; i < 512; ++i )\r\n\t\t{\r\n\t\t\ttable_x[i] = ((float)( rand() - ( RAND_MAX / 2 )) * 32.0f ) / (float)RAND_MAX;\r\n\t\t\ttable_y[i] = ((float)rand() * 12.0f ) / (float)RAND_MAX;\r\n\t\t}\r\n\t}\r\n\t\r\n\tstatic float radius = 24.0f;\r\n\r\n\t// Distance of the drip from the camera.\r\n\tstatic float distance = 10.0f * 12.0f;\r\n\r\n\t// Drip vector.\r\n\tstatic Mth::Vector offset( 0.0f, -1.0f * radius, 0.0f );\r\n\tstatic Mth::Vector offset_target( 0.0f, -1.0f * radius, 0.0f );\r\n\r\n\tstatic int num_drops = 1000;\r\n\r\n\tif(( rand() & 63 ) == 1 )\r\n\t{\r\n\t\toffset_target[X] = ( radius * 0.25f * ( rand() - ( RAND_MAX / 2 ))) / RAND_MAX;\r\n\t\toffset_target[Y] = ( radius * -1.0f * rand() ) / RAND_MAX;\r\n\t\toffset_target[Z] = ( radius * 0.25f * ( rand() - ( RAND_MAX / 2 ))) / RAND_MAX;\r\n\t\t\r\n\t\toffset_target.Normalize( radius );\r\n\t}\r\n\t\r\n\toffset += ( offset_target - offset ) * 0.2f;\r\n\toffset.Normalize( radius );\t\r\n\t\r\n\tD3DXVECTOR4 or( EngineGlobals.cam_position.x + ( distance * EngineGlobals.cam_at.x ),\r\n\t\t\t\t\tEngineGlobals.cam_position.y + ( distance * EngineGlobals.cam_at.y ),\r\n\t\t\t\t\tEngineGlobals.cam_position.z + ( distance * EngineGlobals.cam_at.z ),\r\n\t\t\t\t\t1.0f );\r\n\tD3DXVECTOR4 of( or.x + offset[X], or.y + offset[Y], or.z + offset[Z], 1.0f );\r\n\r\n\tD3DXVec4Transform( &or, &or, (D3DXMATRIX*)&EngineGlobals.view_matrix );\r\n\tD3DXVec4Transform( &of, &of, (D3DXMATRIX*)&EngineGlobals.view_matrix );\r\n\r\n\tD3DXVec4Transform( &or, &or, (D3DXMATRIX*)&EngineGlobals.projection_matrix );\r\n\tD3DXVec4Transform( &of, &of, (D3DXMATRIX*)&EngineGlobals.projection_matrix );\r\n\r\n\tor.x /= or.w;\r\n\tor.y /= or.w;\r\n\r\n\tof.x /= of.w;\r\n\tof.y /= of.w;\r\n\r\n\tof.y = -of.y;\r\n\t\r\n//\tprintf( \"(%.2f %.2f) (%.2f %.2f)\\n\", or.x, or.y, of.x, of.y );\r\n\r\n\t// Obtain push buffer lock.\r\n\tDWORD *p_push; \r\n\tDWORD dwords_per_particle\t= 10;\r\n\tDWORD dword_count\t\t\t= dwords_per_particle * num_drops;\r\n\r\n\t// Submit particle material.\r\n//\tmp_engine_particle->mp_material->Submit();\r\n\tNxXbox::set_blend_mode( vBLEND_MODE_BLEND );\r\n\t\t\r\n\t// Set up correct vertex and pixel shader.\r\n\tNxXbox::set_vertex_shader( D3DFVF_XYZRHW | D3DFVF_DIFFUSE );\r\n\tNxXbox::set_pixel_shader( PixelShader5 );\r\n\t\t\r\n\t// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.\r\n\tp_push = D3DDevice_BeginPush( dword_count + 32 );\r\n\r\n\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\tp_push[1]\t= D3DPT_LINELIST;\r\n\tp_push\t\t+= 2; \r\n\r\n\t// Set up loop variables here, since we be potentially entering the loop more than once.\r\n\tint lp = 0;\r\n\r\n\twhile( dword_count > 0 )\r\n\t{\r\n\t\tint dwords_written = 0;\r\n\r\n\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, ( dword_count > 2047 ) ? ((int)( 2047 / dwords_per_particle )) * dwords_per_particle: dword_count );\r\n\t\t++p_push;\r\n\t\t\r\n\t\tfor( ; lp < num_drops; lp++ )\r\n\t\t{\r\n\t\t\t// Check to see if writing another particle will take us over the edge.\r\n\t\t\tif(( dwords_written + dwords_per_particle ) > 2047 )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tfloat\tscreen_x0\t\t= (float)(( NxXbox::EngineGlobals.backbuffer_width * rand() ) / RAND_MAX );\r\n\t\t\tfloat\tscreen_y0\t\t= (float)(( NxXbox::EngineGlobals.backbuffer_height * rand() ) / RAND_MAX );\r\n\r\n\t\t\tint\t\trandom_length\t= rand();\r\n\t\t\t\r\n\t\t\tfloat\tscreen_x1\t\t= (float)( screen_x0 + (( of.x * ( EngineGlobals.backbuffer_width / 2 ) * random_length ) / RAND_MAX ));\r\n\t\t\tfloat\tscreen_y1\t\t= (float)( screen_y0 + (( of.y * ( EngineGlobals.backbuffer_height / 2 ) * random_length ) / RAND_MAX ));\r\n\r\n\t\t\tscreen_x1\t\t+= table_x[table_index];\r\n\t\t\tscreen_y1\t\t+= table_y[table_index];\r\n\t\t\ttable_index\t\t= ( table_index >= 512 ) ? 0 : ( table_index + 1 );\r\n\r\n\t\t\tp_push[0]\t= *((DWORD*)&screen_x0 );\r\n\t\t\tp_push[1]\t= *((DWORD*)&screen_y0 );\r\n\t\t\tp_push[2]\t= 0x00000000UL;\r\n\t\t\tp_push[3]\t= 0x00000000UL;\r\n\t\t\tp_push[4]\t= 0xA0808080UL;\r\n\t\t\tp_push\t\t+= 5;\r\n\r\n\t\t\tp_push[0]\t= *((DWORD*)&screen_x1 );\r\n\t\t\tp_push[1]\t= *((DWORD*)&screen_y1 );\r\n\t\t\tp_push[2]\t= 0x00000000UL;\r\n\t\t\tp_push[3]\t= 0x00000000UL;\r\n\t\t\tp_push[4]\t= 0x20808080UL;\r\n\t\t\tp_push\t\t+= 5;\r\n\r\n\t\t\tdwords_written\t+= dwords_per_particle;\r\n\t\t\tdword_count\t\t-= dwords_per_particle;\r\n\t\t}\r\n\t}\r\n\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\tp_push[1] = 0;\r\n\tp_push += 2;\r\n\tD3DDevice_EndPush( p_push );\r\n}\r\n\r\n\t\r\n\t\r\n\t\r\n//////////////////////////////////////////////////////////////////////\r\n// For mapping from the depth buffer to blend values using\r\n// a texture map lookup. See media\\shaders\\depthlookup.psh\r\n//\r\n// This is more general than computing the range as in\r\n// media\\shaders\\depth.psh, since the ramp can be filled in\r\n// arbitrarily, but may be more expensive due to the extra texture\r\n// lookup.\r\n//\r\nfloat FUnitMap(float fAlpha, float fBlue, float fAlphaOffset, float fAlphaSlope, float fBlueOffset, float fBlueSlope)\r\n{\r\n    //return g_fPixelShaderScale * fAlphaSlope * (fAlpha - fAlphaOffset) + fBlueSlope * fBlue + fBlueOffset - 0.5f;\r\n    return g_fPixelShaderScale * fAlphaSlope * (fAlpha - fAlphaOffset) + fBlueSlope * (fBlue - fBlueOffset);\r\n}\r\n\r\nfloat FQuantizedDepth(float fDepth, float *pfAlpha, float *pfBlue)\r\n{\r\n    float fDepth16 = fDepth * (float)(1 << 16);\r\n    DWORD dwDepth16 = (DWORD)(fDepth16 /*+ 0.5f*/);\r\n    *pfAlpha = (dwDepth16 >> 8) * (1.0f / 255.0f);\r\n    *pfBlue = (dwDepth16 & 0xff) * (1.0f / 255.0f);\r\n    return (float)dwDepth16 / (float)(1 << 16);\r\n}\r\n\r\n\t\r\n\t\r\n\t\r\n//-----------------------------------------------------------------------------\r\n// Name: CalculateDepthMapping()\r\n// Desc: Calculate offsets and slope to map given z range to 0,1 in\r\n//       the depth and focus pixel shaders.\r\n//-----------------------------------------------------------------------------\r\nstatic HRESULT calculate_depth_mapping( float fDepth0, float fDepth1, float* pfAlphaOffset, float* pfAlphaSlope, float* pfBlueOffset, float* pfBlueSlope )\r\n{\r\n    // Check range of args\r\n    if( fDepth0 < 0.0f ) fDepth0 = 0.0f;\r\n    if( fDepth0 > 1.0f ) fDepth0 = 1.0f;\r\n    if( fDepth1 < 0.0f ) fDepth1 = 0.0f;\r\n    if( fDepth1 > 1.0f ) fDepth1 = 1.0f;\r\n\r\n    if( fDepth1 < fDepth0 )\r\n    {\r\n        // Swap depth to make fDepth0 <= fDepth1\r\n        float t = fDepth1;\r\n        fDepth1 = fDepth0;\r\n        fDepth0 = t;\r\n    }\r\n    \r\n    // Calculate quantized values\r\n    float fAlpha0, fBlue0;\r\n    float fQuantizedDepth0 = FQuantizedDepth(fDepth0, &fAlpha0, &fBlue0);\r\n    float fAlpha1, fBlue1;\r\n    float fQuantizedDepth1 = FQuantizedDepth(fDepth1, &fAlpha1, &fBlue1);\r\n\r\n    // Calculate offset and slopes\r\n    float fScale = 1.0f / (fQuantizedDepth1 - fQuantizedDepth0);\r\n    if( fScale > g_fPixelShaderScale )\r\n    {\r\n        fScale = g_fPixelShaderScale; // This is the steepest slope we can handle\r\n        fDepth0 = 0.5f * (fDepth0 + fDepth1) - 0.5f / fScale; // Move start so that peak is in middle of fDepth0 and fDepth1\r\n        fDepth1 = fDepth0 + 1.0f / fScale;\r\n        fQuantizedDepth0 = FQuantizedDepth(fDepth0, &fAlpha0, &fBlue0);\r\n        fQuantizedDepth1 = FQuantizedDepth(fDepth1, &fAlpha1, &fBlue1);\r\n    }\r\n    \r\n    (*pfAlphaOffset) = fAlpha0;\r\n    (*pfAlphaSlope)  = fScale / g_fPixelShaderScale;\r\n    (*pfBlueSlope)   = fScale * (1.0f/255.0f); // blue ramp adds more levels to the ramp\r\n\r\n    // Align peak of map to center by calculating the quantized alpha value\r\n//    *pfBlueOffset = 0.5f;   // zero biased up by 0.5f\r\n//    float fZeroDesired = (fQuantizedDepth0 - fDepth0) / (fDepth1 - fDepth0);\r\n//    float fZero = FUnitMap(fAlpha0, fBlue0, *pfAlphaOffset, *pfAlphaSlope, *pfBlueOffset, *pfBlueSlope);\r\n//    float fOneDesired = (fQuantizedDepth1 - fDepth0) / (fDepth1 - fDepth0);\r\n//    float fOne = FUnitMap(fAlpha1, fBlue1, *pfAlphaOffset, *pfAlphaSlope, *pfBlueOffset, *pfBlueSlope);\r\n//    *pfBlueOffset = 0.5f * (fZeroDesired-fZero + fOneDesired-fOne) + 0.5f;  // biased up by 0.5f\r\n    (*pfBlueOffset) = fBlue0;\r\n    \r\n    return S_OK;\r\n}\r\n\r\n\t\r\n\r\n\t\r\n\t\r\nstatic HRESULT fill_focus_range_texture( bool bRamp )\r\n{\r\n    HRESULT hr;\r\n\r\n    static const DWORD Width\t= 256;\r\n    static const DWORD Height\t= 256;\r\n    \r\n    // Create the focus range texture\r\n    if( m_pTextureFocusRange )\r\n        m_pTextureFocusRange->Release();\r\n\tEngineGlobals.p_Device->CreateTexture( Width, Height, 1, 0, D3DFMT_A8, 0, &m_pTextureFocusRange );\r\n    \r\n    // Fill the focus range texture\r\n    D3DLOCKED_RECT lockedRect;\r\n    hr = m_pTextureFocusRange->LockRect( 0, &lockedRect, NULL, 0L );\r\n    if( FAILED(hr) )\r\n        return hr;\r\n    \r\n    DWORD dwPixelStride = 1;\r\n    Swizzler s(Width, Height, 0);\r\n    s.SetV(s.SwizzleV(0));\r\n    s.SetU(s.SwizzleU(0));\r\n    if( bRamp )\r\n    {\r\n        for( DWORD j = 0; j < Height; j++ )\r\n        {\r\n            for( DWORD i = 0; i < Width; i++ )\r\n            {\r\n                BYTE *p = (BYTE *)lockedRect.pBits + dwPixelStride * s.Get2D();\r\n                *p = (BYTE)i;\r\n                s.IncU();\r\n            }\r\n            s.IncV();\r\n        }\r\n    }\r\n    else\r\n    {\r\n//        float fAlphaOffset, fAlphaSlope, fBlueOffset, fBlueSlope;\r\n//        calculate_depth_mapping( m_fDepth0, m_fDepth1, &fAlphaOffset, &fAlphaSlope, &fBlueOffset, &fBlueSlope );\r\n        for( DWORD i = 0; i < Width; i++ )\r\n        {\r\n\t\t\tfloat z_high = (float)i / ( Width - 1 );\r\n\r\n            for( DWORD j = 0; j < Height; j++ )\r\n            {\r\n                BYTE *p = (BYTE *)lockedRect.pBits + dwPixelStride * s.Get2D();\r\n//                float fAlpha = (float)i / (Width - 1);\r\n//                float fBlue  = (float)j / (Height - 1);\r\n//                float fUnit  = 2.0f * (FUnitMap(fAlpha, fBlue, fAlphaOffset, fAlphaSlope, fBlueOffset, fBlueSlope) - 0.5f);\r\n//                float fMap   = 1.0f - fUnit * fUnit;\r\n//                if( fMap < 0.0f ) fMap = 0.0f;\r\n//                if( fMap > 1.0f ) fMap = 1.0f;\r\n//                *p = (BYTE)(255 * fMap + 0.5f);\r\n                \r\n\t\t\t\tfloat z_low\t\t\t= (float)j / ( Height - 1 );\r\n\t\t\t\tfloat quantized_z\t= ((( z_high * 256.0f ) + z_low ) * 256.0f ) / 65536.0f;\r\n\r\n\t\t\t\tif( quantized_z < m_fDepth0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t*p = 0;\r\n\t\t\t\t}\r\n\t\t\t\telse if( quantized_z > m_fDepth1 )\r\n\t\t\t\t{\r\n\t\t\t\t\t*p = 0;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t*p = 255;\r\n\t\t\t\t}\r\n\t\t\t\ts.IncV();\r\n            }\r\n            s.IncU();\r\n        }\r\n    }\r\n    \r\n\tm_pTextureFocusRange->UnlockRect( 0 );\r\n\r\n    return S_OK;\r\n}\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n//-----------------------------------------------------------------------------\r\n// Name: filter_copy()\r\n// Desc: Filter the source texture by rendering into the destination texture\r\n//       with subpixel offsets. Does 4 filter coefficients at a time, using all\r\n//       the stages of the pixel shader.\r\n//-----------------------------------------------------------------------------\r\n\r\nD3DTexture* m_pBlur;\r\n\t\r\nstatic HRESULT filter_copy( LPDIRECT3DTEXTURE8 pTextureDst,\r\n                                 LPDIRECT3DTEXTURE8 pTextureSrc,\r\n                                 DWORD dwNumSamples,\r\n                                 FilterSample rSample[],\r\n                                 DWORD dwSuperSampleX,\r\n                                 DWORD dwSuperSampleY )\r\n{\r\n    // Set destination as render target, with no-depth buffer\r\n    LPDIRECT3DSURFACE8 pSurface;\r\n    pTextureDst->GetSurfaceLevel( 0, &pSurface );\r\n    EngineGlobals.p_Device->SetRenderTarget( pSurface, NULL );\r\n    pSurface->Release();\r\n\r\n    // Get descriptions of source and destination\r\n    D3DSURFACE_DESC descSrc;\r\n    pTextureSrc->GetLevelDesc( 0, &descSrc );\r\n\r\n\tif( descSrc.MultiSampleType == D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_LINEAR )\r\n\t{\r\n\t\tdescSrc.Width *= 2;\r\n\t}\r\n\t\r\n\t// Set render state for filtering\r\n    EngineGlobals.p_Device->SetRenderState( D3DRS_LIGHTING,         FALSE );\r\n\tset_render_state( RS_ZWRITEENABLE,\t\t0 );\r\n\tset_render_state( RS_ZTESTENABLE,\t\t0 );\r\n\tset_render_state( RS_ALPHATESTENABLE,\t0 );\r\n\tset_render_state( RS_ALPHABLENDENABLE,\t0 );\r\n    EngineGlobals.p_Device->SetRenderState( D3DRS_BLENDOP,          D3DBLENDOP_ADD ); // Setup subsequent renderings to add to previous value\r\n    EngineGlobals.p_Device->SetRenderState( D3DRS_SRCBLEND,         D3DBLEND_ONE );\r\n    EngineGlobals.p_Device->SetRenderState( D3DRS_DESTBLEND,        D3DBLEND_ONE );\r\n\r\n    // Set texture state\r\n    DWORD xx;\r\n    for( xx = 0; xx < 4; xx++ )\r\n    {\r\n        set_texture( xx, pTextureSrc );  // use our source texture for all four stages\r\n\r\n        EngineGlobals.p_Device->SetTextureStageState( xx, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );  // pass texture coords without transformation\r\n        EngineGlobals.p_Device->SetTextureStageState( xx, D3DTSS_TEXCOORDINDEX, xx ); // each texture has different tex coords\r\n\t\tset_render_state( RS_UVADDRESSMODE0 + xx, 0x00010001UL );\r\n        EngineGlobals.p_Device->SetTextureStageState( xx, D3DTSS_ALPHAKILL, D3DTALPHAKILL_DISABLE );\r\n    }\r\n    \r\n\t// Use blur pixel shader.\r\n\tset_pixel_shader( PixelShaderFocusBlur );\r\n\tset_vertex_shader( D3DFVF_XYZRHW | D3DFVF_TEX4 );\r\n\r\n    // Prepare quadrilateral vertices\r\n    float x0 = -0.5f;\r\n    float y0 = -0.5f;\r\n    float x1 = (float)( descSrc.Width  / dwSuperSampleX ) - 0.5f;\r\n    float y1 = (float)( descSrc.Height / dwSuperSampleY ) - 0.5f;\r\n    struct QUAD\r\n    {\r\n        float x, y, z, w1;\r\n        struct uv \r\n        {\r\n            float u, v;\r\n        } tex[4];   // each texture has different offset\r\n    };\r\n    \r\n    QUAD aQuad[4] = \r\n    {\r\n        { x0, y0, 1.0f, 1.0f, }, // texture coords are set below\r\n        { x1, y0, 1.0f, 1.0f, },\r\n        { x0, y1, 1.0f, 1.0f, },\r\n        { x1, y1, 1.0f, 1.0f, }\r\n    };\r\n\r\n    // Draw a quad for each block of 4 filter coefficients\r\n    xx = 0; // current texture stage\r\n    FLOAT fOffsetScaleX, fOffsetScaleY; // convert destination coords to source texture coords\r\n    FLOAT u0, v0, u1, v1;   // base source rectangle.\r\n\tif( XGIsSwizzledFormat( descSrc.Format ))\r\n    {\r\n        FLOAT fWidthScale  = 1.0f / (FLOAT)descSrc.Width;\r\n        FLOAT fHeightScale = 1.0f / (FLOAT)descSrc.Height;\r\n        fOffsetScaleX = (FLOAT)dwSuperSampleX * fWidthScale;\r\n        fOffsetScaleY = (FLOAT)dwSuperSampleY * fHeightScale;\r\n        u0 = 0.0f;\r\n        v0 = 0.0f;\r\n        u1 = (FLOAT)descSrc.Width * fWidthScale;\r\n        v1 = (FLOAT)descSrc.Height * fHeightScale;\r\n    }\r\n    else\r\n    {\r\n        fOffsetScaleX = (FLOAT)dwSuperSampleX;\r\n        fOffsetScaleY = (FLOAT)dwSuperSampleY;\r\n        u0 = 0.0f;\r\n        v0 = 0.0f;\r\n        u1 = (FLOAT)descSrc.Width;\r\n        v1 = (FLOAT)descSrc.Height;\r\n\t}\r\n    D3DCOLOR rColor[4];\r\n    DWORD rPSInput[4];\r\n    for( DWORD dwSample = 0; dwSample < dwNumSamples; dwSample++ )\r\n    {\r\n        // Set filter coefficients\r\n        FLOAT fValue = rSample[dwSample].fValue;\r\n//      float rf[4] = {fValue, fValue, fValue, fValue};\r\n//      EngineGlobals.p_Device->SetPixelShaderConstant(xx, rf, 1);            // positive coeff\r\n  \r\n        if( fValue < 0.0f )\r\n        {\r\n            rColor[xx] = D3DXCOLOR(-fValue, -fValue, -fValue, -fValue);\r\n            rPSInput[xx] = PS_INPUTMAPPING_SIGNED_NEGATE | ((xx % 2) ? PS_REGISTER_C1 : PS_REGISTER_C0);\r\n        }\r\n        else\r\n        {\r\n            rColor[xx] = D3DXCOLOR(fValue, fValue, fValue, fValue);\r\n            rPSInput[xx] = PS_INPUTMAPPING_SIGNED_IDENTITY | ((xx % 2) ? PS_REGISTER_C1 : PS_REGISTER_C0);\r\n        }\r\n\r\n        // Align supersamples with center of destination pixels\r\n        FLOAT fOffsetX = rSample[dwSample].fOffsetX * fOffsetScaleX;\r\n        FLOAT fOffsetY = rSample[dwSample].fOffsetY * fOffsetScaleY;\r\n        aQuad[0].tex[xx].u = u0 + fOffsetX;\r\n        aQuad[0].tex[xx].v = v0 + fOffsetY;\r\n        aQuad[1].tex[xx].u = u1 + fOffsetX;\r\n        aQuad[1].tex[xx].v = v0 + fOffsetY;\r\n        aQuad[2].tex[xx].u = u0 + fOffsetX;\r\n        aQuad[2].tex[xx].v = v1 + fOffsetY;\r\n        aQuad[3].tex[xx].u = u1 + fOffsetX;\r\n        aQuad[3].tex[xx].v = v1 + fOffsetY;\r\n        \r\n        xx++; // Go to next stage\r\n        if( xx == 4 || dwSample == dwNumSamples - 1 )  // max texture stages or last sample\r\n        {\r\n            // zero out unused texture stage coefficients \r\n            // (only for last filter sample, when number of samples is not divisible by 4)\r\n            for( ; xx < 4; xx++ )\r\n            {\r\n\t\t\t\tset_texture( xx, NULL );\r\n                rColor[xx] = 0;\r\n                rPSInput[xx] = PS_INPUTMAPPING_UNSIGNED_IDENTITY | PS_REGISTER_ZERO;\r\n            }\r\n        \r\n            // Set coefficients\r\n            EngineGlobals.p_Device->SetRenderState( D3DRS_PSCONSTANT0_0, rColor[0] );\r\n            EngineGlobals.p_Device->SetRenderState( D3DRS_PSCONSTANT1_0, rColor[1] );\r\n            EngineGlobals.p_Device->SetRenderState( D3DRS_PSCONSTANT0_1, rColor[2] );\r\n            EngineGlobals.p_Device->SetRenderState( D3DRS_PSCONSTANT1_1, rColor[3] );\r\n\r\n            // Remap coefficients to proper sign\r\n            EngineGlobals.p_Device->SetRenderState( D3DRS_PSRGBINPUTS0,\r\n                                          PS_COMBINERINPUTS( rPSInput[0] | PS_CHANNEL_RGB,   PS_REGISTER_T0 | PS_CHANNEL_RGB   | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n                                                             rPSInput[1] | PS_CHANNEL_RGB,   PS_REGISTER_T1 | PS_CHANNEL_RGB   | PS_INPUTMAPPING_SIGNED_IDENTITY ) );\r\n            EngineGlobals.p_Device->SetRenderState( D3DRS_PSALPHAINPUTS0,\r\n                                          PS_COMBINERINPUTS( rPSInput[0] | PS_CHANNEL_ALPHA, PS_REGISTER_T0 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n                                                             rPSInput[1] | PS_CHANNEL_ALPHA, PS_REGISTER_T1 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY ) );\r\n            EngineGlobals.p_Device->SetRenderState( D3DRS_PSRGBINPUTS1,\r\n                                          PS_COMBINERINPUTS( rPSInput[2] | PS_CHANNEL_RGB,   PS_REGISTER_T2 | PS_CHANNEL_RGB   | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n                                                             rPSInput[3] | PS_CHANNEL_RGB,   PS_REGISTER_T3 | PS_CHANNEL_RGB   | PS_INPUTMAPPING_SIGNED_IDENTITY ) );\r\n            EngineGlobals.p_Device->SetRenderState( D3DRS_PSALPHAINPUTS1,\r\n                                          PS_COMBINERINPUTS( rPSInput[2] | PS_CHANNEL_ALPHA, PS_REGISTER_T2 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY,\r\n                                                             rPSInput[3] | PS_CHANNEL_ALPHA, PS_REGISTER_T3 | PS_CHANNEL_ALPHA | PS_INPUTMAPPING_SIGNED_IDENTITY ) );\r\n            \r\n            // Draw the quad to filter the coefficients so far\r\n\t\t\tEngineGlobals.p_Device->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, aQuad, sizeof( QUAD )); // one quad blends 4 textures\r\n\r\n\t\t\t// On subsequent renderings, add to what's in the render target.\r\n\t\t\tset_render_state( RS_ALPHABLENDENABLE,\t1 );\r\n\t\t\txx = 0;\r\n        }\r\n    }\r\n\r\n    // Clear texture stages\r\n    for( xx=0; xx<4; xx++ )\r\n    {\r\n\t\tset_texture( xx, NULL );\r\n    }\r\n\r\n\t// Restore render target, zbuffer, and state.\r\n    set_pixel_shader( NULL );\r\n\tEngineGlobals.p_Device->SetRenderTarget( EngineGlobals.p_RenderSurface, EngineGlobals.p_ZStencilSurface );\r\n\r\n\treturn S_OK;\r\n}\r\n\t\r\n\t\r\n\t\r\n//-----------------------------------------------------------------------------\r\n// Name: Blur()\r\n// Desc: Blur backbuffer and set m_pBlur to the current blur texture.  Calls\r\n//       filter_copy() with different filter coefficients and offsets, based on\r\n//       the current FILTERMODE setting.\r\n//-----------------------------------------------------------------------------\r\nstatic HRESULT focus_blur( void )\r\n{\r\n\tD3DTexture\tm_BackBufferTexture;\r\n\tD3DTexture\tm_BlurTexture[5];\r\n\t\r\n\tFILTERMODE filter_mode = FM_BOX2_BOX2;\r\n\t\r\n\tint\tmultisample_adjusted_width = EngineGlobals.backbuffer_width * 2;\r\n\t\r\n\tXGSetTextureHeader( multisample_adjusted_width, EngineGlobals.backbuffer_height, 1, 0,\r\n                        EngineGlobals.backbuffer_format, 0, &m_BackBufferTexture, \r\n\t\t\t\t\t\tEngineGlobals.p_RenderSurface->Data,\r\n                        multisample_adjusted_width * XGBytesPerPixelFromFormat( EngineGlobals.backbuffer_format ));\r\n\r\n\tXGSetTextureHeader( EngineGlobals.backbuffer_width, EngineGlobals.backbuffer_height, 1, 0,\r\n\t                    EngineGlobals.blurbuffer_format, 0, &m_BlurTexture[0], \r\n\t\t\t\t\t\tEngineGlobals.p_BlurSurface[0]->Data,\r\n\t\t\t\t        EngineGlobals.backbuffer_width * XGBytesPerPixelFromFormat( EngineGlobals.blurbuffer_format ));\r\n\r\n\tXGSetTextureHeader( EngineGlobals.backbuffer_width / 2, EngineGlobals.backbuffer_height / 2, 1, 0,\r\n\t                    EngineGlobals.blurbuffer_format, 0, &m_BlurTexture[1], \r\n\t\t\t\t\t\tEngineGlobals.p_BlurSurface[1]->Data,\r\n\t\t\t\t        EngineGlobals.backbuffer_width / 2 * XGBytesPerPixelFromFormat( EngineGlobals.blurbuffer_format ));\r\n\r\n\tXGSetTextureHeader( EngineGlobals.backbuffer_width / 4, EngineGlobals.backbuffer_height / 4, 1, 0,\r\n\t                    EngineGlobals.blurbuffer_format, 0, &m_BlurTexture[2], \r\n\t\t\t\t\t\tEngineGlobals.p_BlurSurface[2]->Data,\r\n\t\t\t\t        EngineGlobals.backbuffer_width / 4 * XGBytesPerPixelFromFormat( EngineGlobals.blurbuffer_format ));\r\n\r\n\tXGSetTextureHeader( EngineGlobals.backbuffer_width / 8, EngineGlobals.backbuffer_height / 8, 1, 0,\r\n\t                    EngineGlobals.blurbuffer_format, 0, &m_BlurTexture[3], \r\n\t\t\t\t\t\tEngineGlobals.p_BlurSurface[3]->Data,\r\n\t\t\t\t        EngineGlobals.backbuffer_width / 8 * XGBytesPerPixelFromFormat( EngineGlobals.blurbuffer_format ));\r\n\t\r\n\t// Filters align to blurriest point in supersamples, on the 0.5 boundaries.\r\n    // This takes advantage of the bilinear filtering in the texture map lookup.\r\n    static FilterSample BoxFilter[] =     // for 2x2 downsampling\r\n    {\r\n        { 0.25f, -0.5f, -0.5f },\r\n        { 0.25f,  0.5f, -0.5f },\r\n        { 0.25f, -0.5f,  0.5f },\r\n        { 0.25f,  0.5f,  0.5f },\r\n    };\r\n    static FilterSample YFilter[] =       // 1221 4-tap filter in Y\r\n    {\r\n        { 1.0f/6.0f, 0.0f, -1.5f },\r\n        { 2.0f/6.0f, 0.0f, -0.5f },\r\n        { 2.0f/6.0f, 0.0f,  0.5f },\r\n        { 1.0f/6.0f, 0.0f,  1.5f },\r\n    };\r\n    static FilterSample XFilter[] =       // 1221 4-tap filter in X\r\n    {\r\n        { 1.0f/6.0f, -1.5f, 0.0f },\r\n        { 2.0f/6.0f, -0.5f, 0.0f },\r\n        { 2.0f/6.0f,  0.5f, 0.0f },\r\n        { 1.0f/6.0f,  1.5f, 0.0f },\r\n    };\r\n    static FilterSample Y141Filter[] =    // 141 3-tap filter in Y\r\n    {\r\n        { 1.0f/6.0f, 0.0f, -1.0f },\r\n        { 4.0f/6.0f, 0.0f,  0.0f },\r\n        { 1.0f/6.0f, 0.0f,  1.0f },\r\n    };\r\n    static FilterSample X141Filter[] =        // 141 3-tap filter in X\r\n    {\r\n        { 1.0f/6.0f, -1.0f, 0.0f },\r\n        { 4.0f/6.0f,  0.0f, 0.0f },\r\n        { 1.0f/6.0f,  1.0f, 0.0f },\r\n    };\r\n    static FilterSample IdentityFilter[] = // No filtering\r\n    {\r\n        { 1.0f, 0.0f, 0.0f },\r\n    };\r\n\r\n    switch( filter_mode )\r\n    {\r\n        case FM_BOX:\r\n        {\r\n            // Blur from the backbuffer to the blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture* pTextureDst = &m_BlurTexture[0];\r\n\t\t\tfilter_copy( pTextureDst, pTextureSrc, 4, BoxFilter, 1, 1 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[0];\r\n            break;\r\n        }\r\n\r\n        case FM_VERT:\r\n        {\r\n            // Blur from the backbuffer to the blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture* pTextureDst = &m_BlurTexture[0];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, YFilter, 1, 1 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[0];\r\n            break;\r\n        }\r\n\r\n        case FM_HORIZ:\r\n        {\r\n            // Blur from the backbuffer to the blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture* pTextureDst = &m_BlurTexture[0];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, XFilter, 1, 1 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[0];\r\n            break;\r\n        }\r\n\r\n        case FM_BOX2:\r\n        {\r\n            // Blur from the backbuffer to the 1/2 sized blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture *pTextureDst = &m_BlurTexture[1];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, BoxFilter, 2, 2 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[1];\r\n            break;\r\n        }\r\n\r\n        case FM_VERT2:\r\n        {\r\n            // Blur from the backbuffer to the 1/2 sized blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture* pTextureDst = &m_BlurTexture[1];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, YFilter, 2, 2 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[1];\r\n            break;\r\n        }\r\n\r\n        case FM_HORIZ2:\r\n        {\r\n            // Blur from the backbuffer to the 1/2 sized blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture *pTextureDst = &m_BlurTexture[1];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, XFilter, 2, 2 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[1];\r\n            break;\r\n        }\r\n        \r\n        case FM_VERT2_HORIZ2:\r\n        {\r\n            // Blur from the backbuffer to the 1/2 sized blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture* pTextureDst = &m_BlurTexture[1];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, YFilter, 2, 2 );\r\n            \r\n            // Blur from the previous blur texture to the next blur texture\r\n            pTextureSrc = &m_BlurTexture[1];\r\n            pTextureDst = &m_BlurTexture[2];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, XFilter, 2, 2 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[2];\r\n            break;\r\n        }\r\n\r\n        case FM_HORIZ2_VERT2:\r\n        {\r\n            // Blur from the backbuffer to the 1/2 sized blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture* pTextureDst = &m_BlurTexture[1];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, XFilter, 2, 2 );\r\n            \r\n            // Blur from the previous blur texture to the next blur texture\r\n            pTextureSrc = &m_BlurTexture[1];\r\n            pTextureDst = &m_BlurTexture[2];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, YFilter, 2, 2 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[2];\r\n            break;\r\n        }\r\n\r\n        case FM_VERT2_HORIZ:\r\n        {\r\n            // Blur from the backbuffer to the 1/2 sized blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture* pTextureDst = &m_BlurTexture[1];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, YFilter, 2, 2 );\r\n            \r\n            // Blur from the previous blur texture to the next blur texture\r\n            pTextureSrc = &m_BlurTexture[1];\r\n            pTextureDst = &m_BlurTexture[2];\r\n            filter_copy( pTextureDst, pTextureSrc, 3, X141Filter, 2, 2 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[2];\r\n            break;\r\n        }\r\n\r\n        case FM_HORIZ2_VERT:\r\n        {\r\n            // Blur from the backbuffer to the 1/2 sized blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture* pTextureDst = &m_BlurTexture[1];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, XFilter, 2, 2 );\r\n\r\n            // Blur from the previous blur texture to the next blur texture\r\n            pTextureSrc = &m_BlurTexture[1];\r\n            pTextureDst = &m_BlurTexture[2];  // destination is next blur texture\r\n            filter_copy( pTextureDst, pTextureSrc, 3, Y141Filter, 2, 2 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[2];\r\n            break;\r\n        }\r\n\r\n        case FM_BOX2_BOX2:\r\n        {\r\n            // Blur from the backbuffer to the 1/2 sized blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture* pTextureDst = &m_BlurTexture[0];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, BoxFilter, 2, 1 );\r\n\r\n            // Blur from the previous blur texture to the next blur texture\r\n            pTextureSrc = &m_BlurTexture[0];\r\n            pTextureDst = &m_BlurTexture[1];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, BoxFilter, 2, 2 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[1];\r\n            break;\r\n        }\r\n\r\n\r\n        case FM_VERT2_HORIZ2_BOX2:\r\n        {\r\n            // Blur from the backbuffer to the 1/2 sized blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture* pTextureDst = &m_BlurTexture[1];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, YFilter, 2, 2 );\r\n\r\n            // Blur from the previous blur texture to the next blur texture\r\n            pTextureSrc = &m_BlurTexture[1];\r\n            pTextureDst = &m_BlurTexture[2];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, XFilter, 2, 2 );\r\n\r\n            // Blur from the previous blur texture to the next blur texture\r\n            pTextureSrc = &m_BlurTexture[2];\r\n            pTextureDst = &m_BlurTexture[3];\r\n\t\t\tfilter_copy( pTextureDst, pTextureSrc, 4, BoxFilter, 2, 2 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[3];\r\n            break;\r\n        }\r\n\r\n        case FM_BOX2_BOX2_BOX2:\r\n        {\r\n            // Blur from the backbuffer to the 1/2 sized blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture* pTextureDst = &m_BlurTexture[1];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, BoxFilter, 2, 2 );\r\n\r\n            // Blur from the previous blur texture to the next blur texture\r\n            pTextureSrc = &m_BlurTexture[1];\r\n            pTextureDst = &m_BlurTexture[2];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, BoxFilter, 2, 2 );\r\n\r\n            // Blur from the previous blur texture to the next blur texture\r\n            pTextureSrc = &m_BlurTexture[2];\r\n            pTextureDst = &m_BlurTexture[3];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, BoxFilter, 2, 2 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[3];\r\n            break;\r\n        }\r\n\r\n        case FM_VERT2_HORIZ2_VERT2:\r\n        {\r\n            // Blur from the backbuffer to the 1/2 sized blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture* pTextureDst = &m_BlurTexture[1];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, YFilter, 2, 2 );\r\n\r\n            // Blur from the previous blur texture to the next blur texture\r\n            pTextureSrc = &m_BlurTexture[1];\r\n            pTextureDst = &m_BlurTexture[2];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, XFilter, 2, 2 );\r\n\r\n            // Blur from the previous blur texture to the next blur texture\r\n            pTextureSrc = &m_BlurTexture[2];\r\n            pTextureDst = &m_BlurTexture[3];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, YFilter, 2, 2 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[3];\r\n            break;\r\n        }\r\n\r\n        case FM_HORIZ2_VERT2_HORIZ2:\r\n        {\r\n            // Blur from the backbuffer to the 1/2 sized blur texture\r\n            D3DTexture* pTextureSrc = &m_BackBufferTexture;\r\n            D3DTexture* pTextureDst = &m_BlurTexture[1];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, XFilter, 2, 2 );\r\n\r\n            // Blur from the previous blur texture to the next blur texture\r\n            pTextureSrc = &m_BlurTexture[1];\r\n            pTextureDst = &m_BlurTexture[2];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, YFilter, 2, 2 );\r\n\r\n            // Blur from the previous blur texture to the next blur texture\r\n            pTextureSrc = &m_BlurTexture[2];\r\n            pTextureDst = &m_BlurTexture[3];\r\n            filter_copy( pTextureDst, pTextureSrc, 4, XFilter, 2, 2 );\r\n            \r\n            m_pBlur = (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[3];\r\n            break;\r\n        }\r\n\r\n        default:\r\n\t\t{\r\n            m_pBlur = NULL;\r\n            break;\r\n\t\t}\r\n    }\r\n    return S_OK;\r\n}\r\n\r\n\r\n\r\n\r\nstatic HRESULT draw_focus_effect_using_planes( void )\r\n{\r\n    // Make a D3DTexture wrapper around the depth buffer surface\r\n//    D3DTexture ZBufferTexture;\r\n//    XGSetTextureHeader( EngineGlobals.backbuffer_width, EngineGlobals.backbuffer_height, 1, 0, \r\n//                        D3DFMT_LIN_A8B8G8R8, 0, &ZBufferTexture,\r\n//                        EngineGlobals.p_ZStencilSurface->Data, EngineGlobals.backbuffer_width * 4 );\r\n\r\n    // Get size of blur texture for setting texture coords of final blur\r\n    D3DSURFACE_DESC descBlur;\r\n    m_pBlur->GetLevelDesc( 0, &descBlur );\r\n    float fOffsetX = 0.0f;\r\n    float fOffsetY = 0.5f / (float)descBlur.Height; // vertical blur\r\n    struct VERTEX \r\n    {\r\n        D3DXVECTOR4 p;\r\n        FLOAT tu0, tv0;\r\n\r\n    } v[4];\r\n    v[0].p = D3DXVECTOR4( -0.5f,\t\t\t\t\t\t\t\t\t-0.5f,\t\t\t\t\t\t\t\t\t1.0f, 1.0f );\r\n    v[1].p = D3DXVECTOR4( EngineGlobals.backbuffer_width - 0.5f,\t-0.5f,\t\t\t\t\t\t\t\t\t1.0f, 1.0f );\r\n    v[2].p = D3DXVECTOR4( -0.5f,\t\t\t\t\t\t\t\t\tEngineGlobals.backbuffer_height - 0.5f,\t1.0f, 1.0f );\r\n    v[3].p = D3DXVECTOR4( EngineGlobals.backbuffer_width - 0.5f,\tEngineGlobals.backbuffer_height - 0.5f, 1.0f, 1.0f );\r\n    v[0].tu0 = fOffsetX;\t\t\t\t\t\t\tv[0].tv0 = fOffsetY;\r\n    v[1].tu0 = fOffsetX + (float)descBlur.Width;\tv[1].tv0 = fOffsetY;\r\n    v[2].tu0 = fOffsetX;\t\t\t\t\t\t\tv[2].tv0 = fOffsetY + (float)descBlur.Height;\r\n    v[3].tu0 = fOffsetX + (float)descBlur.Width;\tv[3].tv0 = fOffsetY + (float)descBlur.Height;\r\n\t\r\n\t// Set pixel shader state\r\n//    float fAlphaOffset, fAlphaSlope, fBlueOffset, fBlueSlope;\r\n//   calculate_depth_mapping( m_fDepth0, m_fDepth1, &fAlphaOffset, &fAlphaSlope, &fBlueOffset, &fBlueSlope );\r\n//    float Constants[] = \r\n//    {\r\n//        0.0f, 0.0f, fBlueOffset, fAlphaOffset,      // offset\r\n//        0.0f, 0.0f, fBlueSlope, 0.0f,               // 1x\r\n//        0.0f, 0.0f, 0.0f, 0.0f,                     // 4x\r\n//        0.0f, 0.0f, 0.0f, fAlphaSlope,              // 16x\r\n//    };\r\n\r\n\tset_pixel_shader( 0 );\r\n//    EngineGlobals.p_Device->SetPixelShaderConstant( 0, Constants, 4 );\r\n    \r\n    // Set render state\r\n\tset_render_state( RS_ZWRITEENABLE,\t\t0 );\r\n\tset_render_state( RS_ZTESTENABLE,\t\t1 );\r\n    set_render_state( RS_ALPHATESTENABLE,\t0 );\r\n\tset_render_state( RS_ALPHABLENDENABLE,\t0 );\r\n    set_render_state( RS_ALPHACUTOFF,\t\t0 );\r\n//    EngineGlobals.p_Device->SetRenderState( D3DRS_SRCBLEND,         D3DBLEND_ONE );\r\n//    EngineGlobals.p_Device->SetRenderState( D3DRS_DESTBLEND,        D3DBLEND_INVSRCALPHA );\r\n    EngineGlobals.p_Device->SetRenderState( D3DRS_SRCBLEND,         D3DBLEND_ONE );\r\n    EngineGlobals.p_Device->SetRenderState( D3DRS_DESTBLEND,        D3DBLEND_ZERO );\r\n\r\n\t// Set texture state.\r\n\tset_texture( 0, m_pBlur );\r\n\tset_texture( 1, NULL );\r\n\tset_texture( 2, NULL );\r\n    set_texture( 3, NULL );\r\n\r\n\tset_render_state( RS_UVADDRESSMODE0, 0x00010001UL );\r\n    \r\n\tset_vertex_shader( D3DFVF_XYZRHW | D3DFVF_TEX1 );\r\n\r\n\t// Render the screen-aligned quadrilateral\r\n\tfor( int vx = 0; vx < 4; ++vx )\r\n\t{\r\n\t\tv[vx].p.z = m_fDepth1;\r\n\t}\r\n\tEngineGlobals.p_Device->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );\r\n    EngineGlobals.p_Device->DrawPrimitiveUP( D3DPT_QUADSTRIP, 1, v, sizeof( VERTEX ));\r\n\r\n\t// Render the screen-aligned quadrilateral\r\n\tfor( int vx = 0; vx < 4; ++vx )\r\n\t{\r\n\t\tv[vx].p.z = m_fDepth0;\r\n\t}\r\n\tEngineGlobals.p_Device->SetRenderState( D3DRS_ZFUNC, D3DCMP_GREATEREQUAL );\r\n    EngineGlobals.p_Device->DrawPrimitiveUP( D3DPT_QUADSTRIP, 1, v, sizeof( VERTEX ));\r\n\r\n    // Reset render states\r\n\tEngineGlobals.p_Device->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );\r\n\r\n    set_render_state( RS_ALPHATESTENABLE,\t1 );\r\n\tset_render_state( RS_ALPHABLENDENABLE,\t1 );\r\n\tset_render_state( RS_ZWRITEENABLE,\t\t1 );\r\n\tset_render_state( RS_ZTESTENABLE,\t\t1 );\r\n\r\n\tset_pixel_shader( 0 );\r\n\r\n\tset_texture( 0, NULL );\r\n\tset_texture( 1, NULL );\r\n\tset_texture( 2, NULL );\r\n\tset_texture( 3, NULL );\r\n\r\n    return S_OK;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: DrawFocusRange()\r\n// Desc: Choose the focus range by mapping z to a focus value using pixel\r\n//       shader arithmetic.  See media/shaders/focus.psh for more details.\r\n//\r\n//       High focus values leave the back-buffer unchanged.\r\n//       Low focus values blend in the blurred texture computed by Blur().\r\n//-----------------------------------------------------------------------------\r\nstatic HRESULT draw_focus_effect_using_range( void )\r\n{\r\n    // Make a D3DTexture wrapper around the depth buffer surface\r\n    D3DTexture ZBufferTexture;\r\n    XGSetTextureHeader( EngineGlobals.backbuffer_width, EngineGlobals.backbuffer_height, 1, 0, \r\n                        D3DFMT_LIN_A8B8G8R8, 0, &ZBufferTexture,\r\n                        EngineGlobals.p_ZStencilSurface->Data, EngineGlobals.backbuffer_width * 4 );\r\n\r\n    // Get size of blur texture for setting texture coords of final blur\r\n    D3DSURFACE_DESC descBlur;\r\n    m_pBlur->GetLevelDesc( 0, &descBlur );\r\n    float fOffsetX = 0.0f;\r\n    float fOffsetY = 0.5f / (float)descBlur.Height; // vertical blur\r\n    struct VERTEX \r\n    {\r\n        D3DXVECTOR4 p;\r\n        FLOAT tu0, tv0;\r\n        FLOAT tu1, tv1;\r\n    } v[4];\r\n    v[0].p = D3DXVECTOR4( -0.5f,                      -0.5f,                       1.0f, 1.0f );\r\n    v[1].p = D3DXVECTOR4( EngineGlobals.backbuffer_width - 0.5f, -0.5f,                       1.0f, 1.0f );\r\n    v[2].p = D3DXVECTOR4( -0.5f,                      EngineGlobals.backbuffer_height - 0.5f, 1.0f, 1.0f );\r\n    v[3].p = D3DXVECTOR4( EngineGlobals.backbuffer_width - 0.5f, EngineGlobals.backbuffer_height - 0.5f, 1.0f, 1.0f );\r\n    v[0].tu0 = 0.0f;                       v[0].tv0 = 0.0f;\r\n    v[1].tu0 = (float)EngineGlobals.backbuffer_width; v[1].tv0 = 0.0f;\r\n    v[2].tu0 = 0.0f;                       v[2].tv0 = (float)EngineGlobals.backbuffer_height;\r\n    v[3].tu0 = (float)EngineGlobals.backbuffer_width; v[3].tv0 = (float)EngineGlobals.backbuffer_height;\r\n    v[0].tu1 = fOffsetX;                         v[0].tv1 = fOffsetY;\r\n    v[1].tu1 = fOffsetX + (float)descBlur.Width; v[1].tv1 = fOffsetY;\r\n    v[2].tu1 = fOffsetX;                         v[2].tv1 = fOffsetY + (float)descBlur.Height;\r\n    v[3].tu1 = fOffsetX + (float)descBlur.Width; v[3].tv1 = fOffsetY + (float)descBlur.Height;\r\n    \r\n    // Set pixel shader state\r\n    float fAlphaOffset, fAlphaSlope, fBlueOffset, fBlueSlope;\r\n    calculate_depth_mapping( m_fDepth0, m_fDepth1, &fAlphaOffset, &fAlphaSlope, &fBlueOffset, &fBlueSlope );\r\n    float Constants[] = \r\n    {\r\n        0.0f, 0.0f, fBlueOffset, fAlphaOffset,      // offset\r\n        0.0f, 0.0f, fBlueSlope, 0.0f,               // 1x\r\n        0.0f, 0.0f, 0.0f, 0.0f,                     // 4x\r\n        0.0f, 0.0f, 0.0f, fAlphaSlope,              // 16x\r\n    };\r\n\r\n\tset_pixel_shader( PixelShaderFocusIntegrate );\r\n    EngineGlobals.p_Device->SetPixelShaderConstant( 0, Constants, 4 );\r\n    \r\n    // Set render state\r\n\tset_render_state( RS_ZWRITEENABLE,\t\t0 );\r\n\tset_render_state( RS_ZTESTENABLE,\t\t0 );\r\n    set_render_state( RS_ALPHATESTENABLE,\t1 );\r\n\tset_render_state( RS_ALPHABLENDENABLE,\t1 );\r\n    set_render_state( RS_ALPHACUTOFF,\t\t1 );\r\n    EngineGlobals.p_Device->SetRenderState( D3DRS_SRCBLEND,         D3DBLEND_ONE );\r\n    EngineGlobals.p_Device->SetRenderState( D3DRS_DESTBLEND,        D3DBLEND_INVSRCALPHA );\r\n\r\n\t// Set texture state.\r\n    set_texture( 0, &ZBufferTexture );\r\n\tset_texture( 1, m_pBlur );\r\n\tset_texture( 2, NULL );\r\n    set_texture( 3, NULL );\r\n\r\n\tset_render_state( RS_UVADDRESSMODE0, 0x00010001UL );\r\n\tset_render_state( RS_UVADDRESSMODE1, 0x00010001UL );\r\n\tset_render_state( RS_UVADDRESSMODE2, 0x00010001UL );\r\n\tset_render_state( RS_UVADDRESSMODE3, 0x00010001UL );\r\n    \r\n    // Render the screen-aligned quadrilateral\r\n\tset_vertex_shader( D3DFVF_XYZRHW | D3DFVF_TEX4 );\r\n    EngineGlobals.p_Device->DrawPrimitiveUP( D3DPT_QUADSTRIP, 1, v, sizeof( VERTEX ));\r\n\r\n    // Reset render states\r\n    set_render_state( RS_ALPHATESTENABLE,\t1 );\r\n\tset_render_state( RS_ALPHABLENDENABLE,\t1 );\r\n\tset_render_state( RS_ZWRITEENABLE,\t\t1 );\r\n\tset_render_state( RS_ZTESTENABLE,\t\t1 );\r\n\r\n\tset_pixel_shader( 0 );\r\n\r\n\tset_texture( 0, NULL );\r\n\tset_texture( 1, NULL );\r\n\tset_texture( 2, NULL );\r\n\tset_texture( 3, NULL );\r\n\r\n    return S_OK;\r\n}\r\n\t\r\n\r\n\t\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: DrawFocusLookup()\r\n// Desc: Choose the focus range by mapping z through a lookup texture.\r\n//\r\n//       See media/shaders/focuslookup.psh for more detail.\r\n//\r\n//       This technique has lower performance than using DrawFocus(),\r\n//       but the focus values can be arbitrary, rather than the\r\n//       limited types of z-to-focus value mappings available with\r\n//       pixel shader arithmetic.\r\n//\r\n//       High focus values leave the back-buffer unchanged.\r\n//       Low focus values blend in the blurred texture computed by Blur().\r\n//-----------------------------------------------------------------------------\r\nstatic HRESULT draw_focus_effect_using_lookup( void )\r\n{\r\n    // Make a D3DTexture wrapper around the depth buffer surface\r\n    D3DTexture ZBufferTexture;\r\n    XGSetTextureHeader( EngineGlobals.backbuffer_width, EngineGlobals.backbuffer_height, 1, 0, \r\n                        D3DFMT_LIN_A8B8G8R8, 0, &ZBufferTexture,\r\n                        EngineGlobals.p_ZStencilSurface->Data, EngineGlobals.backbuffer_width * 4 );\r\n\r\n    // Get size of blur texture for setting texture coords of final blur\r\n    D3DSURFACE_DESC descBlur;\r\n    m_pBlur->GetLevelDesc( 0, &descBlur );\r\n    FLOAT fOffsetX = 0.0f;\r\n    FLOAT fOffsetY = 0.5f / (FLOAT)descBlur.Height; // vertical blur\r\n\r\n    // Define a set of vertices to draw a quad in screenspace\r\n    struct VERTEX \r\n    {\r\n        D3DXVECTOR4 p;\r\n        FLOAT tu0, tv0;\r\n        FLOAT tu1, tv1;\r\n        FLOAT tu2, tv2;\r\n        FLOAT tu3, tv3;\r\n    } v[4];\r\n    v[0].p = D3DXVECTOR4( -0.5f,                      -0.5f,                       1.0f, 1.0f );\r\n    v[1].p = D3DXVECTOR4( EngineGlobals.backbuffer_width - 0.5f, -0.5f,                       1.0f, 1.0f );\r\n    v[2].p = D3DXVECTOR4( -0.5f,                      EngineGlobals.backbuffer_height - 0.5f, 1.0f, 1.0f );\r\n    v[3].p = D3DXVECTOR4( EngineGlobals.backbuffer_width - 0.5f, EngineGlobals.backbuffer_height - 0.5f, 1.0f, 1.0f );\r\n    v[0].tu0 = 0.0f;                       v[0].tv0 = 0.0f;\r\n    v[1].tu0 = (float)EngineGlobals.backbuffer_width; v[1].tv0 = 0.0f;\r\n    v[2].tu0 = 0.0f;                       v[2].tv0 = (float)EngineGlobals.backbuffer_height;\r\n    v[3].tu0 = (float)EngineGlobals.backbuffer_width; v[3].tv0 = (float)EngineGlobals.backbuffer_height;\r\n\r\n    // tu1 and tv1 are ignored\r\n    // offset final set of texture coords to apply an additional blur\r\n    v[0].tu2 = -fOffsetX;                         v[0].tv2 = -fOffsetY;\r\n    v[1].tu2 = -fOffsetX + (FLOAT)descBlur.Width; v[1].tv2 = -fOffsetY;\r\n    v[2].tu2 = -fOffsetX;                         v[2].tv2 = -fOffsetY + (FLOAT)descBlur.Height;\r\n    v[3].tu2 = -fOffsetX + (FLOAT)descBlur.Width; v[3].tv2 = -fOffsetY + (FLOAT)descBlur.Height;\r\n    v[0].tu3 =  fOffsetX;                         v[0].tv3 =  fOffsetY;\r\n    v[1].tu3 =  fOffsetX + (FLOAT)descBlur.Width; v[1].tv3 =  fOffsetY;\r\n    v[2].tu3 =  fOffsetX;                         v[2].tv3 =  fOffsetY + (FLOAT)descBlur.Height;\r\n    v[3].tu3 =  fOffsetX + (FLOAT)descBlur.Width; v[3].tv3 =  fOffsetY + (FLOAT)descBlur.Height;\r\n\r\n    // Set pixel shader\r\n\tset_pixel_shader( PixelShaderFocusLookupIntegrate );\r\n\r\n    // Set texture state\r\n\tset_texture( 0, &ZBufferTexture );\r\n\tset_texture( 1, m_pTextureFocusRange );\r\n\tset_texture( 2, m_pBlur );\r\n\tset_texture( 3, m_pBlur );\r\n\r\n\tset_render_state( RS_UVADDRESSMODE0, 0x00010001UL );\r\n\tset_render_state( RS_UVADDRESSMODE1, 0x00010001UL );\r\n\tset_render_state( RS_UVADDRESSMODE2, 0x00010001UL );\r\n\tset_render_state( RS_UVADDRESSMODE3, 0x00010001UL );\r\n    \r\n    // Set render state\r\n\tset_render_state( RS_ZWRITEENABLE,\t\t0 );\r\n\tset_render_state( RS_ZTESTENABLE,\t\t0 );\r\n    set_render_state( RS_ALPHATESTENABLE,\t1 );\r\n\tset_render_state( RS_ALPHABLENDENABLE,\t1 );\r\n    set_render_state( RS_ALPHACUTOFF,\t\t1 );\r\n    EngineGlobals.p_Device->SetRenderState( D3DRS_SRCBLEND,         D3DBLEND_ONE );\r\n    EngineGlobals.p_Device->SetRenderState( D3DRS_DESTBLEND,        D3DBLEND_INVSRCALPHA );\r\n\r\n    // Render the screen-aligned quadrilateral\r\n\tset_vertex_shader( D3DFVF_XYZRHW | D3DFVF_TEX4 );\r\n\tEngineGlobals.p_Device->DrawPrimitiveUP( D3DPT_QUADSTRIP, 1, v, sizeof( VERTEX ));\r\n\r\n    // Reset render states\r\n    set_render_state( RS_ALPHATESTENABLE,\t1 );\r\n\tset_render_state( RS_ALPHABLENDENABLE,\t1 );\r\n\tset_render_state( RS_ZWRITEENABLE,\t\t1 );\r\n\tset_render_state( RS_ZTESTENABLE,\t\t1 );\r\n\r\n\tset_pixel_shader( 0 );\r\n\r\n\tset_texture( 0, NULL );\r\n\tset_texture( 1, NULL );\r\n\tset_texture( 2, NULL );\r\n\tset_texture( 3, NULL );\r\n\r\n    return S_OK;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid set_focus_blur_focus( Mth::Vector & focal_point, float offset, float near_depth, float far_depth )\r\n{\r\n\tMth::Vector diff\t\t= focal_point - Mth::Vector( EngineGlobals.cam_position[0], EngineGlobals.cam_position[1], EngineGlobals.cam_position[2] );\r\n\tMth::Vector unit_diff\t= diff.Normalize();\r\n\r\n\tMth::Vector p0\t\t\t= focal_point + (( offset - near_depth ) * unit_diff );\r\n\tMth::Vector p1\t\t\t= focal_point + (( offset + far_depth ) * unit_diff );\r\n\r\n\tD3DXVECTOR4 v0( p0[X], p0[Y], p0[Z], 1.0f );\r\n\tD3DXVECTOR4 v1( p1[X], p1[Y], p1[Z], 1.0f );\r\n\r\n    D3DXVec4Transform( &v0, &v0, (D3DXMATRIX*)&EngineGlobals.view_matrix );\r\n    D3DXVec4Transform( &v0, &v0, (D3DXMATRIX*)&EngineGlobals.projection_matrix );\r\n\r\n    D3DXVec4Transform( &v1, &v1, (D3DXMATRIX*)&EngineGlobals.view_matrix );\r\n    D3DXVec4Transform( &v1, &v1, (D3DXMATRIX*)&EngineGlobals.projection_matrix );\r\n    \r\n\tm_fDepth0\t\t\t\t= v0.z / v0.w;\r\n\tm_fDepth1\t\t\t\t= v1.z / v1.w;\r\n\r\n\t// If a z value ends up > 1.0, it is likely from intersecting the near plane, in which case just set it to 0.\r\n\tif( m_fDepth0 > 1.0f )\r\n\t\tm_fDepth0 = 0.0f;\r\n\r\n//\tprintf( \"%.4f %.4f\\n\", m_fDepth0, m_fDepth1 );\r\n\r\n\t// If the two values are sufficiently close, it will cause problems since they have\r\n\t// to get quantized down. We have to ensure that ( 1 / ( d1 - d0 )) < 16, that is ( d1 - d0 ) > ( 1 / 16 ).\r\n//\tm_fDepth0 = m_fDepth1  - 0.0625f;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid start_focus_blur( void )\r\n{\r\n\tD3DDevice_SetRenderTarget( NxXbox::EngineGlobals.p_RenderSurface, NxXbox::EngineGlobals.p_ZStencilSurface );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid finish_focus_blur( void )\r\n{\r\n\t// If the focus blur is active, we want to render into a the blur buffer, otherwise into the regular frame buffer.\r\n\tif(( EngineGlobals.focus_blur > 0 ) && ( EngineGlobals.focus_blur_duration > 1 ))\r\n\t{\r\n\t\tEngineGlobals.p_Device->BlockUntilIdle();\r\n\r\n\t\t// Store and reset the min filter for each stage.\r\n\t\tDWORD min_filter[4];\r\n\t\tfor( int s = 0; s < 4; ++s )\r\n\t\t{\r\n\t\t\tD3DDevice_GetTextureStageState( s, D3DTSS_MINFILTER, &min_filter[s] );\r\n\t\t\tD3DDevice_SetTextureStageState( s, D3DTSS_MINFILTER, D3DTEXF_LINEAR );\r\n\t\t}\r\n\t\t\r\n\t\t// First step is to render the back buffer into the blur texture.\r\n//\t\tfill_focus_range_texture( false );\r\n\r\n\t\tfocus_blur();\r\n\r\n//\t\tdraw_focus_effect_using_range();\r\n//\t\tdraw_focus_effect_using_lookup();\r\n\t\tdraw_focus_effect_using_planes();\r\n\r\n\t\t// Restore the min filter for each stage.\r\n\t\tfor( int s = 0; s < 4; ++s )\r\n\t\t{\r\n\t\t\tD3DDevice_SetTextureStageState( s, D3DTSS_MINFILTER, min_filter[s] );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid start_screen_blur( void )\r\n{\r\n\t// If the screen blur is active, we want to render into a the blur buffer, otherwise into the regular frame buffer.\r\n\tif(( EngineGlobals.screen_blur > 0 ) && ( EngineGlobals.screen_blur_duration > 1 ))\r\n\t{\r\n\t\tD3DDevice_SetRenderTarget( NxXbox::EngineGlobals.p_BlurSurface[0], NxXbox::EngineGlobals.p_ZStencilSurface );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tD3DDevice_SetRenderTarget( NxXbox::EngineGlobals.p_RenderSurface, NxXbox::EngineGlobals.p_ZStencilSurface );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid finish_screen_blur( void )\r\n{\r\n\t// If the screen blur is active, we want to render into a the blur buffer, otherwise into the regular frame buffer.\r\n\tif(( EngineGlobals.screen_blur > 0 ) && ( EngineGlobals.screen_blur_duration > 1 ))\r\n\t{\r\n\t\tEngineGlobals.p_Device->BlockUntilIdle();\r\n\r\n\t\t// Now that everything has been drawn, set the backbuffer as the rendertarget, and draw the poly on top of it.\r\n\t\tD3DDevice_SetRenderTarget( NxXbox::EngineGlobals.p_RenderSurface, NxXbox::EngineGlobals.p_ZStencilSurface );\r\n\r\n\t\tNxXbox::set_blend_mode( NxXbox::vBLEND_MODE_BLEND );\r\n\t\r\n\t\t// Turn on clamping so that the linear textures work\r\n\t\tNxXbox::set_render_state( RS_UVADDRESSMODE0, 0x00010001UL );\r\n\r\n\t\t// Use a default vertex and pixel shader\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 );\r\n\t\tNxXbox::set_pixel_shader( PixelShader4 );\r\n\r\n\t\t// Select the texture (flush first, since the blur texture is linear).\r\n\t\tNxXbox::set_texture( 0, NULL );\r\n\t\tNxXbox::set_texture( 0, (IDirect3DTexture8*)NxXbox::EngineGlobals.p_BlurSurface[0] );\r\n\r\n\t\t// Setup up the vertices.\r\n\t\tstruct sBlurVert\r\n\t\t{\r\n\t\t\tfloat\tsx,sy,sz;\r\n\t\t\tfloat\trhw;\r\n\t\t\tuint32\tcolor;\r\n\t\t\tfloat\ttu,tv;\r\n\t\t};\r\n\t\r\n\t\tsBlurVert vertices[4];\r\n\r\n\t\tuint32 alpha\t\t= ( 0xFF - EngineGlobals.screen_blur ) / 2;\r\n\t\talpha\t\t\t\t= ( alpha < 0x20 ) ? 0x20 : alpha;\r\n\t\t\r\n\t\tvertices[0].sx\t\t= 0;\r\n\t\tvertices[0].sy\t\t= 0;\r\n\t\tvertices[0].sz\t\t= 0.0f;\r\n\t\tvertices[0].rhw\t\t= 1.0f;\r\n\t\tvertices[0].color\t= ( alpha << 24 ) | 0x808080;\r\n\t\tvertices[0].tu\t\t= 0.0f;\r\n\t\tvertices[0].tv\t\t= 0.0f;\r\n\r\n\t\tvertices[1]\t\t\t= vertices[0];\r\n\t\tvertices[1].sx\t\t= 640;\r\n\t\tvertices[1].tu\t\t= 640.0f;\r\n\r\n\t\tvertices[2]\t\t\t= vertices[0];\r\n\t\tvertices[2].sy\t\t= 480;\r\n\t\tvertices[2].tv\t\t= 480.0f;\r\n\r\n\t\tvertices[3]\t\t\t= vertices[1];\r\n\t\tvertices[3].sy\t\t= vertices[2].sy;\r\n\t\tvertices[3].tv\t\t= vertices[2].tv;\r\n\r\n\t\t// Adjust if we are in letterbox mode.\r\n\t\tif( NxXbox::EngineGlobals.letterbox_active )\r\n\t\t{\r\n\t\t\tvertices[0].sy\t+= NxXbox::EngineGlobals.backbuffer_height / 8;\r\n\t\t\tvertices[1].sy\t+= NxXbox::EngineGlobals.backbuffer_height / 8;\r\n\t\t\tvertices[0].tv\t+= (float)( NxXbox::EngineGlobals.backbuffer_height / 8 );\r\n\t\t\tvertices[1].tv\t+= (float)( NxXbox::EngineGlobals.backbuffer_height / 8 );\r\n\r\n\t\t\tvertices[2].sy\t-= NxXbox::EngineGlobals.backbuffer_height / 8;\r\n\t\t\tvertices[3].sy\t-= NxXbox::EngineGlobals.backbuffer_height / 8;\r\n\t\t\tvertices[2].tv\t-= (float)( NxXbox::EngineGlobals.backbuffer_height / 8 );\r\n\t\t\tvertices[3].tv\t-= (float)( NxXbox::EngineGlobals.backbuffer_height / 8 );\r\n\t\t}\r\n\r\n\t\t// Draw the vertices.\r\n\t\tset_render_state( RS_CULLMODE,\t\tD3DCULL_NONE );\r\n\t\tset_render_state( RS_ZWRITEENABLE,\t0 );\r\n\t\tset_render_state( RS_ZTESTENABLE,\t0 );\r\n\r\n\t\tD3DDevice_DrawVerticesUP( D3DPT_TRIANGLESTRIP, 4, vertices, sizeof( sBlurVert ));\r\n\r\n\t\t// Reflush linear texture.\r\n\t\tNxXbox::set_texture( 0, NULL );\r\n\t}\r\n}\r\n\r\n\r\n} // namespace NxXbox\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/screenfx.h",
    "content": "#ifndef __SCREENFX_H\r\n#define __SCREENFX_H\r\n\r\nnamespace NxXbox\r\n{\r\n\tvoid\tstart_screen_blur( void );\r\n\tvoid\tfinish_screen_blur( void );\r\n\r\n\tvoid\tstart_focus_blur( void );\r\n\tvoid\tfinish_focus_blur( void );\r\n\tvoid\tset_focus_blur_focus( Mth::Vector & focal_point, float offset, float near_depth, float far_depth );\r\n\r\n\tvoid\tdraw_rain( void );\r\n} // namespace NxXbox\r\n\r\n#endif // __SCREENFX_H\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/sprite.cpp",
    "content": "#include <string.h>\r\n#include <core/defines.h>\r\n#include <core/macros.h>\r\n#include <core/debug.h>\r\n#include <sys/config/config.h>\r\n#include <sys/file/filesys.h>\r\n#include \"nx_init.h\"\r\n#include \"scene.h\"\r\n#include \"render.h\"\r\n#include \"sprite.h\"\r\n\r\nextern DWORD PixelShader4;\r\nextern DWORD PixelShader5;\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* SDraw2D\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSDraw2D *SDraw2D::sp_2D_draw_list = NULL;\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nSDraw2D::SDraw2D( float pri, bool hide )\r\n{\r\n\tm_hidden\t= hide;\r\n\tm_pri\t\t= pri;\r\n\tm_zvalue\t= 0.0f;\r\n\r\n\tmp_next = NULL;\r\n\r\n\t// add to draw list\r\n\tif( !m_hidden )\r\n\t{\r\n\t\tInsertDrawList();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nSDraw2D::~SDraw2D()\r\n{\r\n\t// Try removing from draw list\r\n\tRemoveDrawList();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SDraw2D::SetPriority( float pri )\r\n{\r\n\tif( m_pri != pri )\r\n\t{\r\n\t\tm_pri = pri;\r\n\r\n\t\t// By removing and re-inserting, we re-sort the list\r\n\t\tif( !m_hidden )\r\n\t\t{\r\n\t\t\tRemoveDrawList();\r\n\t\t\tInsertDrawList();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SDraw2D::SetZValue( float z )\r\n{\r\n\tm_zvalue = z;\r\n\r\n\tif( z > 0.0f )\r\n\t{\r\n\t\t// Set the priority to zero so it will always draw before everything else.\r\n\t\tSetPriority( 0.0f );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SDraw2D::SetHidden( bool hide )\r\n{\r\n\tif (m_hidden != hide)\r\n\t{\r\n\t\tm_hidden = hide;\r\n\t\tif (hide)\r\n\t\t{\r\n\t\t\tRemoveDrawList();\r\n\t\t} else {\r\n\t\t\tInsertDrawList();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SDraw2D::DrawAll( void )\r\n{\r\n\tstatic uint32 z_test_required = 0;\r\n\t\r\n\tset_blend_mode( vBLEND_MODE_BLEND );\r\n\tset_render_state( RS_UVADDRESSMODE0, 0x00010001UL );\r\n\tset_render_state( RS_ZBIAS, 0 );\r\n\r\n\t// Set the alpha cutoff value.\r\n\tset_render_state( RS_ALPHACUTOFF, 1 );\r\n\r\n\tset_render_state( RS_ZWRITEENABLE,\t0 );\r\n\tset_texture( 1, NULL );\r\n\tset_texture( 2, NULL );\r\n\tset_texture( 3, NULL );\r\n\r\n\tif( EngineGlobals.color_sign[0] != ( D3DTSIGN_RUNSIGNED | D3DTSIGN_GUNSIGNED | D3DTSIGN_BUNSIGNED ))\r\n\t{\r\n\t\tEngineGlobals.color_sign[0] = ( D3DTSIGN_RUNSIGNED | D3DTSIGN_GUNSIGNED | D3DTSIGN_BUNSIGNED );\r\n\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_COLORSIGN, D3DTSIGN_RUNSIGNED | D3DTSIGN_GUNSIGNED | D3DTSIGN_BUNSIGNED );\r\n\t}\r\n\r\n\t// Unfortunately, now that we have 3D text, we may need to enable the z test for some strings.\r\n\tset_render_state( RS_ZTESTENABLE,\tz_test_required );\r\n\r\n\tSDraw2D *pDraw\t= sp_2D_draw_list;\r\n\tuint32\tz_test\t= 0;\r\n\r\n\twhile( pDraw )\r\n\t{\r\n\t\tif (!pDraw->m_hidden)\r\n\t\t{\r\n\t\t\tpDraw->BeginDraw();\r\n\t\t\tpDraw->Draw();\r\n\t\t\tpDraw->EndDraw();\r\n\r\n\t\t\tif(( z_test == 0 ) && ( pDraw->GetZValue() > 0.0f ))\r\n\t\t\t{\r\n\t\t\t\t// There is at least one peice of text with nonzero z, so we need to z test.\r\n\t\t\t\tz_test = 1;\r\n\t\t\t}\r\n\t\t}\r\n\t\tpDraw = pDraw->mp_next;\r\n\t}\r\n\r\n\tz_test_required = z_test;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SDraw2D::InsertDrawList( void )\r\n{\r\n\tif( !sp_2D_draw_list || ( m_pri <= sp_2D_draw_list->m_pri ))\r\n\t{\r\n\t\t// Empty or start of list.\r\n\t\tmp_next\t\t\t= sp_2D_draw_list;\r\n\t\tsp_2D_draw_list\t= this;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSDraw2D *p_cur\t= sp_2D_draw_list;\r\n\t\r\n\t\t// Find where to insert.\r\n\t\twhile( p_cur->mp_next )\r\n\t\t{\r\n\t\t\tif( m_pri <= p_cur->mp_next->m_pri )\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tp_cur\t\t= p_cur->mp_next;\r\n\t\t}\r\n\r\n\t\t// Insert at this point.\r\n\t\tmp_next\t\t\t= p_cur->mp_next;\r\n\t\tp_cur->mp_next\t= this;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SDraw2D::RemoveDrawList( void )\r\n{\r\n\t// Take out from draw list\r\n\tif (sp_2D_draw_list == this)\r\n\t{\r\n\t\tsp_2D_draw_list = mp_next;\r\n\t} \r\n\telse if (sp_2D_draw_list)\r\n\t{\r\n\t\tSDraw2D *p_cur = sp_2D_draw_list;\r\n\r\n\t\twhile(p_cur->mp_next)\r\n\t\t{\r\n\t\t\tif (p_cur->mp_next == this)\r\n\t\t\t{\r\n\t\t\t\tp_cur->mp_next = mp_next;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tp_cur = p_cur->mp_next;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\t\r\n\r\ntypedef struct\r\n{\r\n\tfloat\t\tx, y, z;\r\n\tfloat\t\trhw;\r\n\tD3DCOLOR\tcol;\r\n\tfloat\t\tu, v;\r\n}\r\nsSpriteVert;\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsSprite::sSprite( float pri ) : SDraw2D( pri, true )\r\n{\r\n\tmp_texture = NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsSprite::~sSprite()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sSprite::BeginDraw( void )\r\n{\r\n\tset_vertex_shader( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2( 0 ));\r\n\r\n\tif( mp_texture )\r\n\t{\r\n\t\tset_pixel_shader( PixelShader4 );\r\n\t\tset_texture( 0, mp_texture->pD3DTexture, mp_texture->pD3DPalette );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tset_pixel_shader( PixelShader5 );\r\n\t\tset_texture( 0, NULL );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sSprite::Draw( void )\r\n{\r\n\t// Sprites are based on .img files, which in turn are converted from .png files, which are upside down,\r\n\t// so reverse the v components of the texture coordinates.\r\n\tfloat u0 = 0.0f;\r\n\tfloat v0 = 1.0f;\r\n\tfloat u1, v1;\r\n\r\n\tif( mp_texture )\r\n\t{\r\n\t\tu1\t= (float)mp_texture->ActualWidth / (float)mp_texture->BaseWidth;\r\n\t\tv1\t= 1.0f - ((float)mp_texture->ActualHeight / (float)mp_texture->BaseHeight );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tu1\t= 1.0f;\r\n\t\tv1\t= 0.0f;\r\n\t}\r\n\r\n\t// Check for flip.\r\n\tfloat abs_scale_x = m_scale_x;\r\n\tfloat abs_scale_y = m_scale_y;\r\n\tif( abs_scale_x < 0.0f )\r\n\t{\r\n\t\tfloat temp = u0;\r\n\t\tu0 = u1;\r\n\t\tu1 = temp;\r\n\t\tabs_scale_x = -abs_scale_x;\r\n\t}\r\n\tif( abs_scale_y < 0.0f )\r\n\t{\r\n\t\tfloat temp = v0;\r\n\t\tv0 = v1;\r\n\t\tv1 = temp;\r\n\t\tabs_scale_y = -abs_scale_y;\r\n\t}\r\n\r\n\tfloat x0 = -( m_xhot * abs_scale_x );\r\n\tfloat y0 = -( m_yhot * abs_scale_y );\r\n\tfloat x1 = x0 + ( m_width * abs_scale_x );\r\n\tfloat y1 = y0 + ( m_height * abs_scale_y );\r\n\r\n\tDWORD\tcurrent_color\t= ( m_rgba & 0xFF00FF00 ) | (( m_rgba & 0xFF ) << 16 ) | (( m_rgba & 0xFF0000 ) >> 16 );\r\n\tDWORD*\tp_push;\r\n\r\n\tif( m_rot != 0.0f )\r\n\t{\r\n\t\tMth::Vector p0( x0, y0, 0.0f, 0.0f );\r\n\t\tMth::Vector p1( x1, y0, 0.0f, 0.0f );\r\n\t\tMth::Vector p2( x0, y1, 0.0f, 0.0f );\r\n\t\tMth::Vector p3( x1, y1, 0.0f, 0.0f );\r\n\r\n\t\tp0.RotateZ( m_rot );\r\n\t\tp1.RotateZ( m_rot );\r\n\t\tp2.RotateZ( m_rot );\r\n\t\tp3.RotateZ( m_rot );\r\n\r\n\t\tp0[X]\t= SCREEN_CONV_X( p0[X] + m_xpos );\r\n\t\tp0[Y]\t= SCREEN_CONV_Y( p0[Y] + m_ypos );\r\n\t\tp1[X]\t= SCREEN_CONV_X( p1[X] + m_xpos );\r\n\t\tp1[Y]\t= SCREEN_CONV_Y( p1[Y] + m_ypos );\r\n\t\tp2[X]\t= SCREEN_CONV_X( p2[X] + m_xpos );\r\n\t\tp2[Y]\t= SCREEN_CONV_Y( p2[Y] + m_ypos );\r\n\t\tp3[X]\t= SCREEN_CONV_X( p3[X] + m_xpos );\r\n\t\tp3[Y]\t= SCREEN_CONV_Y( p3[Y] + m_ypos );\r\n\r\n\t\t// Now grab the push buffer space required.\r\n\t\tp_push\t\t\t= D3DDevice_BeginPush( 34 );\r\n\t\tp_push[0]\t\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1]\t\t= D3DPT_QUADLIST;\r\n\t\tp_push[2]\t\t= D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, 28 );\r\n\r\n\t\t// Vertex0.\r\n\t\tp_push[3]\t\t= *((uint32*)&p0[X] ); \r\n\t\tp_push[4]\t\t= *((uint32*)&p0[Y] );\r\n\t\tp_push[5]\t\t= 0;\r\n\t\tp_push[6]\t\t= 0;\r\n\t\tp_push[7]\t\t= current_color;\r\n\t\tp_push[8]\t\t= *((uint32*)&u0 );\r\n\t\tp_push[9]\t\t= *((uint32*)&v0 );\r\n\r\n\t\t// Vertex1.\r\n\t\tp_push[10]\t\t= *((uint32*)&p2[X] ); \r\n\t\tp_push[11]\t\t= *((uint32*)&p2[Y] );\r\n\t\tp_push[12]\t\t= 0;\r\n\t\tp_push[13]\t\t= 0;\r\n\t\tp_push[14]\t\t= current_color;\r\n\t\tp_push[15]\t\t= *((uint32*)&u0 );\r\n\t\tp_push[16]\t\t= *((uint32*)&v1 );\r\n\r\n\t\t// Vertex2.\r\n\t\tp_push[17]\t\t= *((uint32*)&p3[X] ); \r\n\t\tp_push[18]\t\t= *((uint32*)&p3[Y] );\r\n\t\tp_push[19]\t\t= 0;\r\n\t\tp_push[20]\t\t= 0;\r\n\t\tp_push[21]\t\t= current_color;\r\n\t\tp_push[22]\t\t= *((uint32*)&u1 );\r\n\t\tp_push[23]\t\t= *((uint32*)&v1 );\r\n\r\n\t\t// Vertex3.\r\n\t\tp_push[24]\t\t= *((uint32*)&p1[X] ); \r\n\t\tp_push[25]\t\t= *((uint32*)&p1[Y] );\r\n\t\tp_push[26]\t\t= 0;\r\n\t\tp_push[27]\t\t= 0;\r\n\t\tp_push[28]\t\t= current_color;\r\n\t\tp_push[29]\t\t= *((uint32*)&u1 );\r\n\t\tp_push[30]\t\t= *((uint32*)&v0 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tx0 += m_xpos;\r\n\t\ty0 += m_ypos;\r\n\t\tx1 += m_xpos;\r\n\t\ty1 += m_ypos;\r\n\r\n\t\t// Nasty hack - if the sprite is intended to cover the screen from top to bottom or left to right,\r\n\t\t// bypass the addtional offset added by SCREEN_CONV.\r\n\t\tif(( x0 <= 0.0f ) && ( x1 >= 640.0f ))\r\n\t\t{\r\n\t\t\tx0 = 0.0f;\r\n\t\t\tx1 = (float)NxXbox::EngineGlobals.backbuffer_width;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tx0 = SCREEN_CONV_X( x0 );\r\n\t\t\tx1 = SCREEN_CONV_X( x1 );\r\n\t\t}\r\n\r\n\t\tif(( y0 <= 0.0f ) && ( y1 >= 480.0f ))\r\n\t\t{\r\n\t\t\ty0 = 0.0f;\r\n\t\t\ty1 = (float)NxXbox::EngineGlobals.backbuffer_height;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ty0 = SCREEN_CONV_Y( y0 );\r\n\t\t\ty1 = SCREEN_CONV_Y( y1 );\r\n\t\t}\r\n\r\n\r\n\t\t// Now grab the push buffer space required.\r\n\t\tp_push\t\t\t= D3DDevice_BeginPush( 34 );\r\n\t\tp_push[0]\t\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1]\t\t= D3DPT_QUADLIST;\r\n\t\tp_push[2]\t\t= D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, 28 );\r\n\r\n\t\t// Vertex0.\r\n\t\tp_push[3]\t\t= *((uint32*)&x0 ); \r\n\t\tp_push[4]\t\t= *((uint32*)&y0 );\r\n\t\tp_push[5]\t\t= 0;\r\n\t\tp_push[6]\t\t= 0;\r\n\t\tp_push[7]\t\t= current_color;\r\n\t\tp_push[8]\t\t= *((uint32*)&u0 );\r\n\t\tp_push[9]\t\t= *((uint32*)&v0 );\r\n\r\n\t\t// Vertex1.\r\n\t\tp_push[10]\t\t= *((uint32*)&x0 ); \r\n\t\tp_push[11]\t\t= *((uint32*)&y1 );\r\n\t\tp_push[12]\t\t= 0;\r\n\t\tp_push[13]\t\t= 0;\r\n\t\tp_push[14]\t\t= current_color;\r\n\t\tp_push[15]\t\t= *((uint32*)&u0 );\r\n\t\tp_push[16]\t\t= *((uint32*)&v1 );\r\n\r\n\t\t// Vertex2.\r\n\t\tp_push[17]\t\t= *((uint32*)&x1 ); \r\n\t\tp_push[18]\t\t= *((uint32*)&y1 );\r\n\t\tp_push[19]\t\t= 0;\r\n\t\tp_push[20]\t\t= 0;\r\n\t\tp_push[21]\t\t= current_color;\r\n\t\tp_push[22]\t\t= *((uint32*)&u1 );\r\n\t\tp_push[23]\t\t= *((uint32*)&v1 );\r\n\r\n\t\t// Vertex3.\r\n\t\tp_push[24]\t\t= *((uint32*)&x1 ); \r\n\t\tp_push[25]\t\t= *((uint32*)&y0 );\r\n\t\tp_push[26]\t\t= 0;\r\n\t\tp_push[27]\t\t= 0;\r\n\t\tp_push[28]\t\t= current_color;\r\n\t\tp_push[29]\t\t= *((uint32*)&u1 );\r\n\t\tp_push[30]\t\t= *((uint32*)&v0 );\r\n\t}\r\n\r\n\t// End of vertex data for this sprite.\r\n\tp_push[31] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\tp_push[32] = 0;\r\n\tp_push += 33;\r\n\tD3DDevice_EndPush( p_push );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sSprite::EndDraw( void )\r\n{\r\n\t// Vertices have been submitted - nothing more to do.\r\n}\r\n\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/sprite.h",
    "content": "#ifndef __SPRITE_H\r\n#define __SPRITE_H\r\n\r\n#include \"texture.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\nstruct SDraw2D\r\n{\r\n\t\t\t\t\tSDraw2D( float pri = 0.0f, bool hide = true );\r\n\tvirtual\t\t\t~SDraw2D( void );\r\n\r\n\tvoid\t\t\tSetPriority( float pri );\r\n\tfloat\t\t\tGetPriority( void ) const;\r\n\tvoid\t\t\tSetZValue( float z );\r\n\tfloat\t\t\tGetZValue( void )\t\t\t{ return m_zvalue; }\r\n\r\n\tvoid\t\t\tSetHidden( bool hide );\r\n\tbool\t\t\tIsHidden( void ) const;\r\n\r\n\t// members\r\n\tSDraw2D\t\t\t*mp_next;\r\n\r\n\t// Statics\r\n\tstatic void\t\tDrawAll( void );\r\n\r\nprivate:\r\n\tvoid\t\t\tInsertDrawList( void );\r\n\tvoid\t\t\tRemoveDrawList( void );\r\n\r\n\tvirtual void\tBeginDraw( void ) = 0;\r\n\tvirtual void\tDraw( void ) = 0;\r\n\tvirtual void\tEndDraw( void ) = 0;\r\n\r\n\t// Not even the derived classes should have direct access\r\n\tbool\t\t\tm_hidden;\r\n\tfloat\t\t\tm_pri;\r\n\tfloat\t\t\tm_zvalue;\r\n\r\n\t// 2D draw list (sorted by priority);\r\n\tstatic SDraw2D\t*sp_2D_draw_list;\r\n};\r\n\r\n\r\nstruct sSprite : public SDraw2D\r\n{\r\n\tpublic:\r\n\t\t\t\t\tsSprite( float pri = 0.0f );\r\n\t\t\t\t\t~sSprite();\r\n\r\n\tsTexture\t\t*mp_texture;\r\n\r\n\tfloat\t\t\tm_xpos;\r\n\tfloat\t\t\tm_ypos;\r\n\tuint16\t\t\tm_width;\r\n\tuint16\t\t\tm_height;\r\n\tfloat\t\t\tm_scale_x;\r\n\tfloat\t\t\tm_scale_y;\r\n\tfloat\t\t\tm_xhot;\r\n\tfloat\t\t\tm_yhot;\r\n\tfloat\t\t\tm_rot;\r\n\tuint32\t\t\tm_rgba;\r\n\r\nprivate:\r\n\t\r\n\tvoid\t\t\t\t\tBeginDraw();\r\n\tvoid\t\t\t\t\tDraw();\r\n\tvoid\t\t\t\t\tEndDraw(void);\r\n};\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n\r\n#endif // __SPRITE_H\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/swizzleformat.h",
    "content": "//////////////////////////////////////////////////////////////////////\r\n// Swizzled to linear and back format mapping.\r\n//\r\n//  Copyright (C) 2001 Microsoft Corporation\r\n//  All rights reserved.\r\n//////////////////////////////////////////////////////////////////////\r\ninline D3DFORMAT MapLinearToSwizzledFormat(D3DFORMAT fmt)\r\n{\r\n    switch (fmt)\r\n    {\r\n    case D3DFMT_LIN_A1R5G5B5:     return D3DFMT_A1R5G5B5;\r\n    case D3DFMT_LIN_A4R4G4B4:     return D3DFMT_A4R4G4B4;\r\n    case D3DFMT_LIN_A8:         return D3DFMT_A8;\r\n    case D3DFMT_LIN_A8B8G8R8:     return D3DFMT_A8B8G8R8;\r\n    case D3DFMT_LIN_A8R8G8B8:     return D3DFMT_A8R8G8B8;\r\n    case D3DFMT_LIN_B8G8R8A8:     return D3DFMT_B8G8R8A8;\r\n    case D3DFMT_LIN_G8B8:         return D3DFMT_G8B8;\r\n    case D3DFMT_LIN_R4G4B4A4:     return D3DFMT_R4G4B4A4;\r\n    case D3DFMT_LIN_R5G5B5A1:     return D3DFMT_R5G5B5A1;\r\n    case D3DFMT_LIN_R5G6B5:     return D3DFMT_R5G6B5;\r\n    case D3DFMT_LIN_R6G5B5:     return D3DFMT_R6G5B5;\r\n    case D3DFMT_LIN_R8B8:         return D3DFMT_R8B8;\r\n    case D3DFMT_LIN_R8G8B8A8:     return D3DFMT_R8G8B8A8;\r\n    case D3DFMT_LIN_X1R5G5B5:     return D3DFMT_X1R5G5B5;\r\n    case D3DFMT_LIN_X8R8G8B8:     return D3DFMT_X8R8G8B8;\r\n    case D3DFMT_LIN_A8L8:         return D3DFMT_A8L8;\r\n    case D3DFMT_LIN_AL8:         return D3DFMT_AL8;\r\n    case D3DFMT_LIN_L16:         return D3DFMT_L16;\r\n    case D3DFMT_LIN_L8:         return D3DFMT_L8;\r\n    case D3DFMT_LIN_V16U16:     return D3DFMT_V16U16;\r\n    case D3DFMT_LIN_D24S8:         return D3DFMT_D24S8;\r\n    case D3DFMT_LIN_F24S8:         return D3DFMT_F24S8;\r\n    case D3DFMT_LIN_D16:         return D3DFMT_D16;\r\n    case D3DFMT_LIN_F16:         return D3DFMT_F16;\r\n    default:\r\n        return fmt;\r\n    }\r\n}\r\n\r\ninline D3DFORMAT MapSwizzledToLinearFormat(D3DFORMAT fmt)\r\n{\r\n    switch (fmt)\r\n    {\r\n    case D3DFMT_A1R5G5B5:     return D3DFMT_LIN_A1R5G5B5;\r\n    case D3DFMT_A4R4G4B4:     return D3DFMT_LIN_A4R4G4B4;\r\n    case D3DFMT_A8:         return D3DFMT_LIN_A8;\r\n    case D3DFMT_A8B8G8R8:     return D3DFMT_LIN_A8B8G8R8;\r\n    case D3DFMT_A8R8G8B8:     return D3DFMT_LIN_A8R8G8B8;\r\n    case D3DFMT_B8G8R8A8:     return D3DFMT_LIN_B8G8R8A8;\r\n    case D3DFMT_G8B8:         return D3DFMT_LIN_G8B8;\r\n    case D3DFMT_R4G4B4A4:     return D3DFMT_LIN_R4G4B4A4;\r\n    case D3DFMT_R5G5B5A1:     return D3DFMT_LIN_R5G5B5A1;\r\n    case D3DFMT_R5G6B5:     return D3DFMT_LIN_R5G6B5;\r\n    case D3DFMT_R6G5B5:     return D3DFMT_LIN_R6G5B5;\r\n    case D3DFMT_R8B8:         return D3DFMT_LIN_R8B8;\r\n    case D3DFMT_R8G8B8A8:     return D3DFMT_LIN_R8G8B8A8;\r\n    case D3DFMT_X1R5G5B5:     return D3DFMT_LIN_X1R5G5B5;\r\n    case D3DFMT_X8R8G8B8:     return D3DFMT_LIN_X8R8G8B8;\r\n    case D3DFMT_A8L8:         return D3DFMT_LIN_A8L8;\r\n    case D3DFMT_AL8:         return D3DFMT_LIN_AL8;\r\n    case D3DFMT_L16:         return D3DFMT_LIN_L16;\r\n    case D3DFMT_L8:         return D3DFMT_LIN_L8;\r\n    case D3DFMT_V16U16:     return D3DFMT_LIN_V16U16;\r\n    case D3DFMT_D24S8:         return D3DFMT_LIN_D24S8;\r\n    case D3DFMT_F24S8:         return D3DFMT_LIN_F24S8;\r\n    case D3DFMT_D16:         return D3DFMT_LIN_D16;\r\n    case D3DFMT_F16:         return D3DFMT_LIN_F16;\r\n    default:\r\n        return fmt;\r\n    }\r\n}\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/texture.cpp",
    "content": "#include <string.h>\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <sys/file/filesys.h>\r\n#include \"nx_init.h\"\r\n#include \"chars.h\"\r\n#include \"texture.h\"\r\n#include \"render.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsTexture::sTexture()\r\n{\r\n\tpD3DTexture = NULL;\r\n\tpD3DPalette\t= NULL;\r\n\tpD3DSurface\t= NULL;\t\t// If used as a render target.\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsTexture::~sTexture()\r\n{\r\n\tULONG rr;\r\n\r\n\tif( pD3DTexture )\r\n\t{\r\n\t\trr = pD3DTexture->Release();\r\n\t\tDbg_Assert( rr == 0 );\r\n\r\n\t\t// Ensure that this texture is no longer referenced in the EngineGlobals.\r\n\t\tfor( int p = 0; p < 4; ++p )\r\n\t\t{\r\n\t\t\tif( EngineGlobals.p_texture[p] == pD3DTexture )\r\n\t\t\t{\r\n\t\t\t\tset_texture( p, NULL );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif( pD3DPalette )\r\n\t{\r\n\t\trr = pD3DPalette->Release();\r\n\t\tDbg_Assert( rr == 0 );\r\n\t}\r\n\tif( pD3DSurface )\r\n\t{\r\n\t\trr = pD3DSurface->Release();\r\n\t\tDbg_Assert( rr == 0 );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sTexture::Set( int pass )\r\n{\r\n\t// Set this texture as the active texture for a specific pass.\r\n\tset_texture( pass, pD3DTexture, pD3DPalette );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool sTexture::SetRenderTarget( int width, int height, int depth, int z_depth )\r\n{\r\n\tHRESULT\t\thr;\r\n\t\r\n\tif( pD3DTexture )\r\n\t{\r\n\t\tpD3DTexture->Release();\r\n\t}\r\n\tif( pD3DPalette )\r\n\t{\r\n\t\tpD3DPalette->Release();\r\n\t}\r\n\r\n\t// Create the shadow buffer (essentially just a depth buffer).\r\n\thr = D3DDevice_CreateTexture( width, height, 1, 0, D3DFMT_LIN_D24S8, 0, &pD3DTexture );\r\n\tDbg_Assert( hr == D3D_OK );\r\n\tif( hr == D3D_OK )\r\n\t{\r\n\t\t// Set fields to reflect surface characteristics.\r\n\t\tChecksum\t\t= 0;\r\n\t\tBaseWidth\t\t= ActualWidth\t= width;\r\n\t\tBaseHeight\t\t= ActualHeight\t= height;\r\n\t\tLevels\t\t\t= 1;\r\n\t\tTexelDepth\t\t= depth;\r\n\t\tPaletteDepth\t= 0;\r\n\t\tDXT\t\t\t\t= 0;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n// Eeeek - the .img contains PS2 specific register values for bit depth.\r\n// Use these values to convert them.\r\n#define PSMCT32\t\t0x00\r\n#define PSMCT24\t\t0x01\r\n#define PSMCT16\t\t0x02\r\n#define PSMCT16S\t0x0A\r\n#define PS_GPU24\t0x12\r\n#define PSMT8\t\t0x13\r\n#define PSMT4\t\t0x14\r\n#define PSMT8H\t\t0x1B\r\n#define PSMT4HL\t\t0x24\r\n#define PSMT4HH\t\t0x2C\r\n#define PSMZ32\t\t0x30\r\n#define PSMZ24\t\t0x31\r\n#define PSMZ16\t\t0x32\r\n#define PSMZ16S\t\t0x3A\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic bool is_power_of_two( uint32 a )\r\n{\r\n\tif( a == 0 )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\treturn (( a & ( a - 1 )) == 0 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsTexture *LoadTexture( const char *p_filename )\r\n{\r\n\tstruct sIMGHeader\r\n\t{\r\n\t\tuint32\tversion;\r\n\t\tuint32\tchecksum;\r\n\t\tuint32\twidth;\r\n\t\tuint32\theight;\r\n\t\tuint32\tbit_depth;\r\n\t\tuint32\tclut_bit_depth;\r\n\t\tuint16\toriginal_width;\r\n\t\tuint16\toriginal_height;\r\n\t\tuint32\tpalette_data_size;\r\n\t};\r\n\r\n\tvoid *p_FH = File::Open( p_filename, \"rb\" );\r\n\t\r\n\tif( p_FH )\r\n\t{\r\n\t\t// Read header.\r\n\t\tsIMGHeader header;\r\n\t\tFile::Read( &header, sizeof( sIMGHeader ), 1, p_FH );\r\n\t\t\r\n\t\t// Bits per texel and palette size.\r\n\t\tswitch( header.bit_depth )\r\n\t\t{\r\n\t\t\tcase PSMCT32:\r\n\t\t\t\theader.bit_depth = 32;\r\n\t\t\t\tbreak;\r\n\t\t\tcase PSMCT16:\r\n\t\t\t\theader.bit_depth = 16;\r\n\t\t\t\tbreak;\r\n\t\t\tcase PSMT8:\r\n\t\t\t\theader.bit_depth = 8;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t}\r\n\r\n\t\t// Bits per clut entry.\r\n\t\tif(\theader.bit_depth < 16 )\r\n\t\t{\r\n\t\t\tswitch( header.clut_bit_depth )\r\n\t\t\t{\r\n\t\t\t\tcase PSMCT32:\r\n\t\t\t\t\theader.clut_bit_depth = 32;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\theader.clut_bit_depth = 0;\r\n\t\t}\r\n\t\t\r\n\t\t{\r\n\t\t\t// Create the texture object.\r\n\t\t\tsTexture *p_texture = new sTexture();\r\n\r\n\t\t\t// Create palette if required.\r\n\t\t\tif( header.clut_bit_depth == 0 )\r\n\t\t\t{\r\n\t\t\t\tp_texture->pD3DPalette = NULL;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( D3D_OK != D3DDevice_CreatePalette( D3DPALETTE_256, &p_texture->pD3DPalette ))\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t}\r\n\t\t\r\n\t\t\t\t// Read clut bitmap data.\r\n\t\t\t\tD3DCOLOR *p_clut;\r\n\t\t\t\tp_texture->pD3DPalette->Lock( &p_clut, 0 );\r\n\r\n\t\t\t\tint len\t= File::Read( p_clut, header.palette_data_size, 1, p_FH );\r\n\t\t\t\tDbg_MsgAssert( len == header.palette_data_size, ( \"Couldn't read clut from texture file %s\", p_filename ));\r\n\t\t\t}\r\n\r\n\t\t\t// Textures of width 512 and above will not have been resized. This means they cannot be in a swizzled format.\r\n//\t\t\tbool arbitrary_texture_size = ( header.original_width >= 512 );\r\n\t\t\tbool arbitrary_texture_size = false;\r\n\t\t\t\r\n\t\t\tif( !is_power_of_two( header.width ) || !is_power_of_two( header.height ))\r\n\t\t\t\tarbitrary_texture_size = true;\r\n\r\n\t\t\t// Create texture resource. Linear for arbitrary sized textures, swizzled for standard sizes.\r\n\t\t\tuint32 num_bytes;\r\n\t\t\tif( arbitrary_texture_size )\r\n\t\t\t{\r\n\t\t\t\tif( D3D_OK != D3DDevice_CreateTexture(\theader.original_width,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\theader.original_height,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t1,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t0,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t( header.bit_depth <= 8 ) ? D3DFMT_P8 : (( header.bit_depth == 16 ) ? D3DFMT_LIN_A1R5G5B5 : D3DFMT_LIN_A8R8G8B8 ),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t0,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&p_texture->pD3DTexture ))\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t}\r\n\t\t\t\tp_texture->BaseWidth\t= header.original_width;\r\n\t\t\t\tp_texture->BaseHeight\t= header.original_height;\r\n\t\t\t\tp_texture->ActualWidth\t= header.original_width;\r\n\t\t\t\tp_texture->ActualHeight\t= header.original_height;\r\n\t\t\t\tnum_bytes\t\t\t\t= ((( header.bit_depth / 8 ) * ( header.original_width ) * ( header.original_height )) + 3 ) & 0xFFFFFFFC;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( D3D_OK != D3DDevice_CreateTexture(\theader.width,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\theader.height,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t1,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t0,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t( header.bit_depth <= 8 ) ? D3DFMT_P8 : (( header.bit_depth == 16 ) ? D3DFMT_A1R5G5B5 : D3DFMT_A8R8G8B8 ),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t0,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&p_texture->pD3DTexture ))\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t}\r\n\t\t\t\tp_texture->BaseWidth\t= (uint16)header.width;\r\n\t\t\t\tp_texture->BaseHeight\t= (uint16)header.height;\r\n\t\t\t\tp_texture->ActualWidth\t= header.original_width;\r\n\t\t\t\tp_texture->ActualHeight\t= header.original_height;\r\n\t\t\t\tnum_bytes\t\t\t\t= ((( header.bit_depth / 8 ) * header.width * header.height ) + 3 ) & 0xFFFFFFFC;\r\n\t\t\t}\r\n\t\r\n\t\t\t// Lock the texture so we can read data into it directly.\r\n\t\t\tD3DLOCKED_RECT locked_rect;\r\n\t\t\tif( D3D_OK != p_texture->pD3DTexture->LockRect( 0, &locked_rect, NULL, 0 ))\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\r\n\t\t\t// Read texture bitmap data directly into texture. \r\n\t\t\tint len = File::Read( locked_rect.pBits, num_bytes, 1, p_FH );\r\n\t\t\tDbg_MsgAssert( len == num_bytes, ( \"couldn't read texture data from texture file %s\", p_filename ));\r\n\t\t\r\n\t\t\tFile::Close( p_FH );\r\n\r\n\t\t\t// Set up some member values.\r\n\t\t\tp_texture->PaletteDepth\t= (uint8)header.clut_bit_depth;\r\n\t\t\tp_texture->TexelDepth\t= (uint8)header.bit_depth;\r\n\t\t\tp_texture->DXT\t\t\t= 0;\r\n\t\t\tp_texture->Levels\t\t= 1;\r\n\t\t\t\r\n\t\t\treturn p_texture;\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n} // namespace NxXbox\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/texture.h",
    "content": "#ifndef __TEXTURE_H\r\n#define __TEXTURE_H\r\n\r\n#include <core/HashTable.h>\r\n\r\nnamespace NxXbox\r\n{\r\n\r\nstruct sTexture\r\n{\r\n\t\t\t\t\t\tsTexture();\r\n\t\t\t\t\t\t~sTexture();\r\n\t\t\t\t\t\t\r\n\tbool\t\t\t\tSetRenderTarget( int width, int height, int depth, int z_depth );\r\n\tvoid\t\t\t\tSet( int pass );\r\n\r\n\tuint32\t\t\t\tChecksum;\r\n\tuint16\t\t\t\tBaseWidth, BaseHeight;\t\t// The size of the D3D texture (will be power of 2).\r\n\tuint16\t\t\t\tActualWidth, ActualHeight;\t// The size of the texture itself (may not be power of 2).\r\n\r\n\tuint8\t\t\t\tLevels;\r\n\tuint8\t\t\t\tTexelDepth;\r\n\tuint8\t\t\t\tPaletteDepth;\r\n\tuint8\t\t\t\tDXT;\r\n\r\n\tIDirect3DTexture8*\tpD3DTexture;\r\n\tIDirect3DPalette8*\tpD3DPalette;\r\n\tIDirect3DSurface8*\tpD3DSurface;\r\n};\r\n\r\nsTexture\t*LoadTexture( const char *p_filename );\r\n\r\n} // namespace NxXbox\r\n\r\n#endif // __TEXTURE_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/verlet.cpp",
    "content": "#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n\r\n\r\n#include \"verlet.h\"\r\n#include \"render.h\"\r\n\r\n\r\nconst int\tNUM_PARTICLES\t= 16;\r\nconst float\tPARTICLES_DIST\t= 5.0f;\r\n\r\n\r\nsVerletSystem*\t\t\t\tpSystem\t\t\t\t= NULL;\r\nObj::CSkeletonComponent*\tpSkeletonComponent\t= NULL;\r\nfloat\t\t\t\t\t\tground\t\t\t\t= -110.0f;\r\n\r\n\r\nvoid CreateSystem( void )\r\n{\r\n\tObj::CCompositeObject *p_obj = (Obj::CCompositeObject *)Obj::CCompositeObjectManager::Instance()->GetObjectByID( 0 );\r\n\tif( p_obj )\r\n\t{\r\n\t\tpSkeletonComponent = GetSkeletonComponentFromObject( p_obj );\r\n\t}\r\n\r\n\tif( pSkeletonComponent )\r\n\t{\r\n\t\tpSystem = new sVerletSystem( NUM_PARTICLES );\r\n\r\n\t\tpSystem->m_timestep\t= ( 1.0f / 60.0f );\r\n\t\tpSystem->m_gravity\t= Mth::Vector( 0.0f, -1200.0f, 0.0f );\r\n\r\n\t\t// Get the skater's head position.\r\n\t\tMth::Vector bone_pos;\r\n\t\tpSkeletonComponent->GetBoneWorldPosition( CRCD(0xe638eebc,\"Bone_Forefinger_Tip_R\"), &bone_pos );\r\n\r\n\t\tfor( int i = 0; i < NUM_PARTICLES; ++i )\r\n\t\t{\r\n\t\t\tpSystem->mp_particles[i].m_pos\t\t= bone_pos - ( Mth::Vector( 0.0f, PARTICLES_DIST * i, 0.0f ));\r\n\t\t\tpSystem->mp_particles[i].m_old_pos\t= pSystem->mp_particles[i].m_pos;\r\n\t\t}\r\n\r\n\t\tfor( int i = 0; i < ( NUM_PARTICLES - 1 ); ++i )\r\n\t\t{\r\n\t\t\tsVerletConstraint*\tp_c = pSystem->AddConstraint();\r\n\t\t\tp_c->m_particle0\t\t= i;\r\n\t\t\tp_c->m_particle1\t\t= i + 1;\r\n\t\t\tp_c->m_constraint_dist\t= PARTICLES_DIST;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nvoid UpdateVerletSystem( void )\r\n{\r\n\tif( pSystem == NULL )\r\n\t{\r\n\t\tCreateSystem();\r\n\t}\r\n\r\n\tif( pSystem )\r\n\t{\r\n\t\t// Set particle 0 to always be at the skater's head position.\r\n\t\tMth::Vector bone_pos;\r\n\t\tpSkeletonComponent->GetBoneWorldPosition( CRCD(0xe638eebc,\"Bone_Forefinger_Tip_R\"), &bone_pos );\r\n\t\tpSystem->mp_particles[0].m_pos = bone_pos;\r\n\r\n\t\tpSystem->TimeStep();\r\n\t}\r\n}\r\n\r\nvoid DrawVerletSystem( void )\r\n{\r\n\tstruct sVerletDrawVert\r\n\t{\r\n\t\tfloat\t\tx, y, z;\r\n\t\tD3DCOLOR\tcol;\r\n\t};\r\n\r\n\tif( pSystem )\r\n\t{\r\n\t\tsVerletDrawVert\tdv[NUM_PARTICLES];\r\n\t\tfor( int i = 0; i < NUM_PARTICLES; ++i )\r\n\t\t{\r\n\t\t\tdv[i].x\t\t= pSystem->mp_particles[i].m_pos[X];\r\n\t\t\tdv[i].y\t\t= pSystem->mp_particles[i].m_pos[Y];\r\n\t\t\tdv[i].z\t\t= pSystem->mp_particles[i].m_pos[Z];\r\n\t\t\tdv[i].col\t= 0xFFFFFFFF;\r\n\t\t}\r\n\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\t\tNxXbox::set_pixel_shader( PixelShader5 );\r\n\r\n\t\tNxXbox::EngineGlobals.p_Device->DrawVerticesUP( D3DPT_LINESTRIP, NUM_PARTICLES, dv, sizeof( sVerletDrawVert ));\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsVerletParticle::sVerletParticle( void )\r\n{\r\n\tm_pos\t\t= Mth::Vector( 0.0f, 0.0f, 0.0f );\r\n\tm_old_pos\t= m_pos;\r\n\tm_acc\t\t= m_pos;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsVerletParticle::~sVerletParticle( void )\r\n{\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sVerletConstraint::Apply( sVerletParticle *p_particles )\r\n{\r\n\tsVerletParticle* p_p0\t\t\t= p_particles + m_particle0;\r\n\tsVerletParticle* p_p1\t\t\t= p_particles + m_particle1;\r\n\r\n\tMth::Vector\t\tdelta\t\t\t= p_p1->m_pos - p_p0->m_pos;\r\n\tfloat\t\t\tdelta_length\t= delta.Length();\r\n\tfloat\t\t\tdiff\t\t\t= ( delta_length - m_constraint_dist ) / delta_length;\r\n\r\n\tif( m_particle0 == 0 )\r\n\t{\r\n\t\t// Move the points.\r\n\t\tp_p0->m_pos += delta * 0.0f * diff;\r\n\t\tp_p1->m_pos -= delta * 1.0f * diff;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Move the points.\r\n\t\tp_p0->m_pos += delta * 0.5f * diff;\r\n\t\tp_p1->m_pos -= delta * 0.5f * diff;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsVerletSystem::sVerletSystem( int num_particles )\r\n{\r\n\tm_num_particles = num_particles;\r\n\tmp_particles\t= new sVerletParticle[num_particles];\r\n\tmp_constraints\t= new Lst::Head <sVerletConstraint>;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsVerletSystem::~sVerletSystem( void )\r\n{\r\n\tdelete [] mp_particles;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsVerletConstraint* sVerletSystem::AddConstraint( void )\r\n{\r\n\tsVerletConstraint*\t\t\t\tp_constraint\t= new sVerletConstraint;\r\n\tLst::Node<sVerletConstraint>*\tp_node\t\t\t= new Lst::Node<sVerletConstraint>( p_constraint );\r\n\r\n\tmp_constraints->AddToTail( p_node );\r\n\r\n\treturn p_constraint;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sVerletSystem::Verlet( void )\r\n{\r\n\tfor( int i = 0; i < m_num_particles; ++i )\r\n\t{\r\n\t\tMth::Vector &x\t\t= mp_particles[i].m_pos;\r\n\t\tMth::Vector t\t\t= x;\r\n\t\tMth::Vector &o\t\t= mp_particles[i].m_old_pos;\r\n\t\tMth::Vector a\t\t= mp_particles[i].m_acc;\r\n\t\tx\t\t\t\t\t= ( x * 2.0f ) - o + ( a * m_timestep * m_timestep );\r\n\t\to\t\t\t\t\t= t;\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sVerletSystem::AccumulateForces( void )\r\n{\r\n\t// All particles are influenced by gravity.\r\n\tfor( int i = 0; i < m_num_particles; ++i )\r\n\t{\r\n\t\tmp_particles[i].m_acc = m_gravity;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sVerletSystem::SatisfyConstraints( void )\r\n{\r\n\tLst::Node<sVerletConstraint>* p_node, *p_next;\r\n\r\n\tfor( int i = 0; i < 2; ++i )\r\n\t{\r\n\t\t// Satisfy distance constraints.\r\n\t\tfor( p_node = mp_constraints->GetNext(); p_node; p_node = p_next )\r\n\t\t{\r\n\t\t\tp_next = p_node->GetNext();\r\n\t\t\tsVerletConstraint *p_constraint = p_node->GetData();\r\n\t\t\tp_constraint->Apply( mp_particles );\r\n\t\t}\r\n\r\n\t\t// Satisfy ground constraints.\r\n\t\tfor( int i = 0; i < m_num_particles; ++i )\r\n\t\t{\r\n\t\t\tif( mp_particles[i].m_pos[Y] < ground )\r\n\t\t\t{\r\n\t\t\t\tmp_particles[i].m_pos[Y] = ground;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sVerletSystem::TimeStep( void )\r\n{\r\n\tAccumulateForces();\r\n\tVerlet();\r\n\tSatisfyConstraints();\r\n}\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/verlet.h",
    "content": "#ifndef __VERLET_H\r\n#define __VERLET_H\r\n\r\n#include <core/math.h>\r\n\r\nvoid\t\t\tUpdateVerletSystem( void );\r\nvoid\t\t\tDrawVerletSystem( void );\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sVerletParticle\r\n{\r\n\t\t\t\t\t\tsVerletParticle( void );\r\n\t\t\t\t\t\t~sVerletParticle( void );\r\n\r\n\tMth::Vector\t\t\tm_pos;\r\n\tMth::Vector\t\t\tm_old_pos;\r\n\tMth::Vector\t\t\tm_acc;\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sVerletConstraint\r\n{\r\n\tint\t\t\t\t\tm_particle0;\r\n\tint\t\t\t\t\tm_particle1;\r\n\tfloat\t\t\t\tm_elasticity;\r\n\tfloat\t\t\t\tm_constraint_dist;\r\n\tvoid\t\t\t\tApply( sVerletParticle *p_particles );\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sVerletSystem\r\n{\r\n\t\t\t\t\t\t\t\t\tsVerletSystem( int num_particles );\r\n\t\t\t\t\t\t\t\t\t~sVerletSystem();\r\n\r\n\tvoid\t\t\t\t\t\t\tTimeStep( void );\r\n\tvoid\t\t\t\t\t\t\tVerlet( void );\r\n\tvoid\t\t\t\t\t\t\tSatisfyConstraints( void );\r\n\tvoid\t\t\t\t\t\t\tAccumulateForces( void );\r\n\r\n\tsVerletConstraint*\t\t\t\tAddConstraint( void );\t\r\n\r\n\tint\t\t\t\t\t\t\t\tm_num_particles;\r\n\tsVerletParticle*\t\t\t\tmp_particles;\r\n\tMth::Vector\t\t\t\t\t\tm_gravity;\r\n\tfloat\t\t\t\t\t\t\tm_timestep;\r\n\r\n\tLst::Head <sVerletConstraint>*\tmp_constraints;\r\n};\r\n\r\n\r\n\r\n\r\n\r\n#endif // __NX_INIT_H\r\n"
  },
  {
    "path": "Code/Gfx/XBox/NX/xbmemfnt.h",
    "content": "\r\n#define XBMEMFNT_LEN 68168\r\n\r\n static unsigned char xbmemfnt[]=\r\n {\r\n  0x48,0x0a,0x01,0x00,0x83,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x13,\r\n  0x00,0x00,0x00,0x10,0x00,0x41,0x00,0x10,0x00,0x42,0x00,0x10,0x00,\r\n  0x43,0x00,0x10,0x00,0x44,0x00,0x10,0x00,0x45,0x00,0x10,0x00,0x46,\r\n  0x00,0x10,0x00,0x47,0x00,0x10,0x00,0x48,0x00,0x10,0x00,0x49,0x00,\r\n  0x10,0x00,0x4a,0x00,0x10,0x00,0x4b,0x00,0x10,0x00,0x4c,0x00,0x10,\r\n  0x00,0x4d,0x00,0x10,0x00,0x4e,0x00,0x10,0x00,0x4f,0x00,0x10,0x00,\r\n  0x50,0x00,0x10,0x00,0x51,0x00,0x10,0x00,0x52,0x00,0x10,0x00,0x53,\r\n  0x00,0x10,0x00,0x54,0x00,0x10,0x00,0x55,0x00,0x10,0x00,0x56,0x00,\r\n  0x10,0x00,0x57,0x00,0x10,0x00,0x58,0x00,0x10,0x00,0x59,0x00,0x10,\r\n  0x00,0x5a,0x00,0x0d,0x00,0x61,0x00,0x10,0x00,0x62,0x00,0x0d,0x00,\r\n  0x63,0x00,0x10,0x00,0x64,0x00,0x0d,0x00,0x65,0x00,0x10,0x00,0x66,\r\n  0x00,0x0d,0x00,0x67,0x00,0x10,0x00,0x68,0x00,0x10,0x00,0x69,0x00,\r\n  0x10,0x00,0x6a,0x00,0x10,0x00,0x6b,0x00,0x10,0x00,0x6c,0x00,0x0d,\r\n  0x00,0x6d,0x00,0x0d,0x00,0x6e,0x00,0x0d,0x00,0x6f,0x00,0x0d,0x00,\r\n  0x70,0x00,0x0d,0x00,0x71,0x00,0x0d,0x00,0x72,0x00,0x0d,0x00,0x73,\r\n  0x00,0x0f,0x00,0x74,0x00,0x0d,0x00,0x75,0x00,0x0d,0x00,0x76,0x00,\r\n  0x0d,0x00,0x77,0x00,0x0d,0x00,0x78,0x00,0x0d,0x00,0x79,0x00,0x0d,\r\n  0x00,0x7a,0x00,0x0f,0x00,0x30,0x00,0x0f,0x00,0x31,0x00,0x0f,0x00,\r\n  0x32,0x00,0x0f,0x00,0x33,0x00,0x0f,0x00,0x34,0x00,0x0f,0x00,0x35,\r\n  0x00,0x10,0x00,0x36,0x00,0x0f,0x00,0x37,0x00,0x0f,0x00,0x38,0x00,\r\n  0x10,0x00,0x39,0x00,0x08,0x00,0x2e,0x00,0x08,0x00,0x2c,0x00,0x0a,\r\n  0x00,0x2d,0x00,0x10,0x00,0x21,0x00,0x10,0x00,0x3f,0x00,0x0d,0x00,\r\n  0x3a,0x00,0x10,0x00,0x27,0x00,0x0e,0x00,0x2b,0x00,0x10,0x00,0x2f,\r\n  0x00,0x10,0x00,0x5e,0x00,0x10,0x00,0xae,0x00,0x10,0x00,0x28,0x00,\r\n  0x10,0x00,0x29,0x00,0x10,0x00,0x2a,0x00,0x10,0x00,0x40,0x00,0x12,\r\n  0x00,0x60,0x00,0x10,0x00,0xa1,0x00,0x0f,0x00,0xa2,0x00,0x0f,0x00,\r\n  0xa3,0x00,0x0f,0x00,0xa4,0x00,0x0f,0x00,0xa5,0x00,0x10,0x00,0xa6,\r\n  0x00,0x10,0x00,0xa7,0x00,0x11,0x00,0xa8,0x00,0x10,0x00,0xa9,0x00,\r\n  0x10,0x00,0xaa,0x00,0x0b,0x00,0xab,0x00,0x0b,0x00,0xac,0x00,0x10,\r\n  0x00,0x7b,0x00,0x02,0x00,0x5f,0x00,0x10,0x00,0x23,0x00,0x10,0x00,\r\n  0x24,0x00,0x10,0x00,0x25,0x00,0x10,0x00,0x26,0x00,0x11,0x00,0x5c,\r\n  0x00,0x0c,0x00,0x3d,0x00,0x0e,0x00,0x3c,0x00,0x0e,0x00,0x3e,0x00,\r\n  0x10,0x00,0xdf,0x00,0x13,0x00,0xc4,0x00,0x13,0x00,0xdc,0x00,0x13,\r\n  0x00,0xd6,0x00,0x11,0x00,0xe0,0x00,0x11,0x00,0xe2,0x00,0x13,0x00,\r\n  0xc4,0x00,0x11,0x00,0xea,0x00,0x12,0x00,0xe8,0x00,0x12,0x00,0xe9,\r\n  0x00,0x11,0x00,0xeb,0x00,0x11,0x00,0xec,0x00,0x11,0x00,0xee,0x00,\r\n  0x11,0x00,0xef,0x00,0x11,0x00,0xf4,0x00,0x11,0x00,0xf2,0x00,0x13,\r\n  0x00,0xd6,0x00,0x12,0x00,0xf9,0x00,0x11,0x00,0xfb,0x00,0x13,0x00,\r\n  0xdc,0x00,0x0d,0x00,0xe7,0x00,0x0d,0x00,0x9c,0x00,0x11,0x00,0xfc,\r\n  0x00,0x11,0x00,0xe4,0x00,0x11,0x00,0xf6,0x00,0x10,0x00,0xbc,0x00,\r\n  0x10,0x00,0xbd,0x00,0x10,0x00,0xbe,0x00,0x10,0x00,0xbf,0x00,0x10,\r\n  0x00,0xba,0x00,0x10,0x00,0xe0,0xff,0x2c,0x08,0x01,0x00,0x00,0x01,\r\n  0x00,0x01,0x08,0x00,0xfc,0xfe,0x12,0x00,0xdf,0xf2,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,\r\n  0x35,0x35,0x35,0x35,0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x20,0x35,0x35,0x35,0x35,0x35,0x35,0x20,0x00,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x08,0x30,0x39,0x0f,\r\n  0x2f,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x0e,0x35,0x35,\r\n  0x35,0x35,0x35,0x20,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,\r\n  0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x34,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x0e,0x35,0x35,0x35,0x35,0x35,0x35,0x0e,0x34,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x2e,0x3a,0x1b,0x3a,0x2e,0x2b,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x35,0x35,0x35,0x35,\r\n  0x01,0x00,0x2b,0x20,0x35,0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x20,\r\n  0x35,0x20,0x2b,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x34,0x35,0x35,0x35,0x35,0x01,0x01,0x01,0x01,0x01,0x35,\r\n  0x35,0x35,0x35,0x00,0x01,0x01,0x35,0x35,0x20,0x0e,0x20,0x01,0x01,\r\n  0x01,0x01,0x01,0x34,0x35,0x35,0x35,0x20,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x0e,0x35,0x35,0x35,0x35,0x35,0x34,0x01,0x20,\r\n  0x0e,0x35,0x35,0x35,0x0e,0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x35,\r\n  0x35,0x35,0x35,0x35,0x00,0x01,0x00,0x35,0x35,0x0e,0x00,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x34,0x3c,0x0f,0x11,0x37,0x3c,0x34,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x08,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,\r\n  0x01,0x01,0x01,0x01,0x3d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x3d,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x04,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x04,0x01,0x01,0x01,0x01,0x01,\r\n  0x17,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x17,0x01,0x01,\r\n  0x01,0x01,0x01,0x04,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x38,0x2b,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x3d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x2c,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x3d,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x2c,0x01,0x01,0x01,0x3d,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x3d,0x01,0x01,0x01,0x3d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x3d,0x1e,0x1e,0x1e,0x1e,0x1e,0x3d,0x01,0x01,0x01,0x01,0x2b,\r\n  0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x20,0x07,0x1e,0x2d,0x2d,0x09,0x09,0x2d,0x2d,0x1e,0x32,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x09,0x2d,0x09,0x09,0x09,0x09,\r\n  0x2d,0x09,0x1e,0x1e,0x07,0x2b,0x01,0x01,0x01,0x01,0x08,0x1e,0x1e,\r\n  0x09,0x2a,0x29,0x0d,0x26,0x31,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x0f,\r\n  0x1e,0x18,0x10,0x09,0x09,0x09,0x09,0x2d,0x09,0x1e,0x1e,0x40,0x2b,\r\n  0x01,0x01,0x17,0x1e,0x1e,0x2d,0x2d,0x09,0x09,0x09,0x09,0x2d,0x2d,\r\n  0x18,0x1e,0x30,0x01,0x20,0x07,0x1e,0x10,0x09,0x09,0x09,0x09,0x09,\r\n  0x09,0x10,0x18,0x1e,0x1c,0x01,0x01,0x01,0x17,0x1e,0x1e,0x09,0x28,\r\n  0x15,0x15,0x15,0x28,0x1e,0x1e,0x1e,0x17,0x01,0x01,0x01,0x30,0x1e,\r\n  0x18,0x2d,0x2d,0x2d,0x2d,0x1e,0x1e,0x21,0x09,0x2d,0x2d,0x1e,0x38,\r\n  0x01,0x01,0x38,0x1e,0x09,0x2d,0x09,0x21,0x1e,0x1e,0x2f,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x2c,0x1e,0x18,0x2d,0x09,0x2d,0x2d,0x1e,\r\n  0x38,0x01,0x38,0x1e,0x2d,0x2d,0x2d,0x2d,0x1e,0x1e,0x1e,0x2d,0x2d,\r\n  0x09,0x10,0x09,0x1e,0x3b,0x01,0x1c,0x1e,0x18,0x2d,0x09,0x2d,0x09,\r\n  0x1e,0x3e,0x34,0x01,0x01,0x01,0x01,0x38,0x1e,0x10,0x2d,0x09,0x09,\r\n  0x2d,0x2d,0x1e,0x1e,0x09,0x10,0x09,0x09,0x09,0x10,0x1e,0x1e,0x3a,\r\n  0x01,0x08,0x1e,0x1e,0x2d,0x2d,0x09,0x2d,0x2d,0x1e,0x1e,0x1e,0x2d,\r\n  0x2d,0x10,0x1e,0x1e,0x2e,0x01,0x01,0x2b,0x3e,0x1e,0x1e,0x2a,0x06,\r\n  0x19,0x24,0x16,0x1e,0x1e,0x1e,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3c,0x1e,0x16,\r\n  0x13,0x13,0x13,0x13,0x13,0x13,0x03,0x1e,0x2e,0x01,0x01,0x01,0x01,\r\n  0x35,0x1e,0x09,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x16,\r\n  0x1e,0x38,0x01,0x01,0x01,0x3c,0x1e,0x1e,0x12,0x0c,0x13,0x1f,0x1f,\r\n  0x13,0x05,0x14,0x2d,0x1e,0x38,0x01,0x01,0x39,0x1e,0x02,0x13,0x13,\r\n  0x13,0x13,0x13,0x13,0x13,0x13,0x25,0x1e,0x38,0x01,0x01,0x0f,0x1e,\r\n  0x06,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x22,0x1e,0x32,0x01,\r\n  0x08,0x1e,0x25,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0b,0x1e,\r\n  0x1d,0x01,0x01,0x35,0x40,0x1e,0x06,0x13,0x0c,0x22,0x1f,0x1f,0x1f,\r\n  0x13,0x26,0x1e,0x33,0x0e,0x01,0x01,0x32,0x1e,0x22,0x0c,0x13,0x05,\r\n  0x14,0x1e,0x15,0x13,0x13,0x13,0x13,0x1e,0x1e,0x01,0x36,0x1e,0x31,\r\n  0x13,0x13,0x13,0x13,0x24,0x1e,0x37,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x07,0x1e,0x05,0x13,0x13,0x13,0x13,0x1e,0x1e,0x01,0x1e,0x1e,\r\n  0x13,0x0c,0x22,0x1f,0x12,0x1e,0x02,0x0c,0x13,0x1f,0x1f,0x29,0x1e,\r\n  0x30,0x01,0x1d,0x1e,0x23,0x05,0x14,0x13,0x13,0x16,0x1e,0x3c,0x01,\r\n  0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,0x13,0x13,0x13,0x13,0x02,0x1e,\r\n  0x13,0x13,0x13,0x13,0x13,0x13,0x27,0x1e,0x2c,0x01,0x1c,0x1e,0x12,\r\n  0x1f,0x1f,0x13,0x05,0x14,0x23,0x1e,0x06,0x13,0x0c,0x13,0x29,0x1e,\r\n  0x04,0x01,0x01,0x38,0x1e,0x2a,0x13,0x13,0x13,0x13,0x13,0x13,0x13,\r\n  0x15,0x1e,0x1d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x3a,0x1e,0x26,0x13,0x13,0x13,0x13,\r\n  0x13,0x13,0x0d,0x1e,0x2c,0x01,0x01,0x01,0x01,0x34,0x1e,0x18,0x1f,\r\n  0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x1e,0x1e,0x01,0x01,\r\n  0x01,0x04,0x1e,0x24,0x13,0x0b,0x1f,0x0c,0x05,0x0c,0x0c,0x13,0x1f,\r\n  0x1e,0x1e,0x2f,0x01,0x37,0x1e,0x06,0x23,0x14,0x13,0x13,0x13,0x13,\r\n  0x13,0x13,0x13,0x10,0x1e,0x1b,0x01,0x3c,0x1e,0x16,0x13,0x13,0x13,\r\n  0x13,0x13,0x13,0x13,0x13,0x27,0x1e,0x2c,0x01,0x36,0x1e,0x31,0x13,\r\n  0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x27,0x1e,0x2c,0x01,0x01,0x3a,\r\n  0x1e,0x25,0x0c,0x0c,0x0c,0x13,0x1f,0x14,0x0c,0x13,0x0b,0x0a,0x1e,\r\n  0x11,0x01,0x01,0x30,0x1e,0x24,0x14,0x13,0x05,0x02,0x1e,0x25,0x0c,\r\n  0x23,0x14,0x13,0x1e,0x1e,0x01,0x35,0x1e,0x2d,0x05,0x13,0x13,0x13,\r\n  0x0a,0x1e,0x3b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x1e,0x0d,\r\n  0x13,0x13,0x13,0x0c,0x1e,0x33,0x01,0x1e,0x1e,0x0c,0x0c,0x13,0x13,\r\n  0x2a,0x1e,0x13,0x0b,0x1f,0x0c,0x05,0x1e,0x1e,0x3b,0x01,0x1c,0x1e,\r\n  0x24,0x05,0x02,0x14,0x13,0x21,0x1e,0x2b,0x01,0x01,0x01,0x01,0x1e,\r\n  0x1e,0x13,0x13,0x13,0x13,0x13,0x13,0x29,0x1e,0x22,0x13,0x13,0x13,\r\n  0x13,0x13,0x26,0x1e,0x0f,0x01,0x3b,0x1e,0x0a,0x0c,0x05,0x0c,0x0c,\r\n  0x13,0x19,0x1e,0x2a,0x14,0x14,0x13,0x28,0x1e,0x1b,0x01,0x36,0x1e,\r\n  0x21,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x31,0x1e,0x0f,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x2c,0x1e,0x27,0x13,0x13,0x14,0x13,0x13,0x13,0x05,0x1e,\r\n  0x40,0x01,0x01,0x01,0x01,0x34,0x1e,0x18,0x0c,0x13,0x13,0x13,0x06,\r\n  0x12,0x13,0x13,0x13,0x13,0x1e,0x1e,0x01,0x01,0x01,0x3e,0x1e,0x14,\r\n  0x13,0x0c,0x13,0x0d,0x31,0x13,0x02,0x14,0x0c,0x06,0x1e,0x37,0x01,\r\n  0x37,0x1e,0x06,0x19,0x12,0x14,0x14,0x27,0x0b,0x14,0x13,0x13,0x27,\r\n  0x1e,0x2c,0x01,0x08,0x1e,0x25,0x13,0x13,0x13,0x13,0x14,0x23,0x14,\r\n  0x05,0x06,0x1e,0x0f,0x01,0x36,0x1e,0x31,0x13,0x13,0x13,0x13,0x14,\r\n  0x19,0x14,0x0c,0x06,0x1e,0x0f,0x01,0x01,0x39,0x1e,0x1a,0x19,0x13,\r\n  0x0c,0x19,0x1e,0x0c,0x0c,0x13,0x0c,0x0c,0x1e,0x33,0x01,0x01,0x3d,\r\n  0x1e,0x29,0x0c,0x1f,0x23,0x0c,0x1e,0x2a,0x1f,0x19,0x12,0x14,0x1e,\r\n  0x1e,0x01,0x35,0x1e,0x2d,0x1f,0x13,0x13,0x13,0x28,0x1e,0x2e,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x04,0x1e,0x1a,0x13,0x13,0x13,0x0c,\r\n  0x1e,0x33,0x01,0x1e,0x1e,0x13,0x0c,0x14,0x13,0x2a,0x25,0x13,0x0c,\r\n  0x13,0x05,0x16,0x1e,0x38,0x01,0x01,0x1c,0x1e,0x24,0x23,0x13,0x0b,\r\n  0x02,0x21,0x1e,0x36,0x01,0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,0x13,\r\n  0x13,0x13,0x13,0x27,0x10,0x14,0x13,0x13,0x13,0x13,0x1f,0x15,0x1e,\r\n  0x0f,0x01,0x2e,0x1e,0x0a,0x05,0x1f,0x13,0x02,0x14,0x0c,0x1e,0x10,\r\n  0x0c,0x0c,0x1f,0x28,0x1e,0x1b,0x01,0x3a,0x1e,0x26,0x0b,0x14,0x13,\r\n  0x22,0x10,0x05,0x13,0x13,0x13,0x19,0x1e,0x11,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x1e,0x18,\r\n  0x1f,0x13,0x13,0x16,0x05,0x13,0x13,0x13,0x1e,0x1e,0x34,0x01,0x01,\r\n  0x01,0x34,0x1e,0x18,0x0c,0x13,0x13,0x0c,0x1e,0x1e,0x13,0x13,0x13,\r\n  0x13,0x1e,0x1e,0x01,0x01,0x01,0x07,0x1e,0x22,0x0c,0x22,0x13,0x0a,\r\n  0x1e,0x0c,0x1f,0x13,0x0c,0x1a,0x1e,0x39,0x01,0x37,0x1e,0x06,0x0b,\r\n  0x0c,0x1f,0x12,0x1e,0x24,0x24,0x14,0x13,0x05,0x1e,0x07,0x01,0x08,\r\n  0x1e,0x25,0x13,0x13,0x13,0x13,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x17,\r\n  0x01,0x36,0x1e,0x31,0x13,0x13,0x13,0x1f,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x17,0x01,0x01,0x38,0x1e,0x23,0x0c,0x13,0x0c,0x24,0x1e,0x31,\r\n  0x1a,0x29,0x12,0x06,0x1e,0x1e,0x00,0x01,0x3d,0x1e,0x06,0x0b,0x0c,\r\n  0x19,0x14,0x1e,0x0a,0x14,0x0b,0x0c,0x1f,0x1e,0x1e,0x01,0x35,0x1e,\r\n  0x2d,0x1f,0x13,0x13,0x13,0x28,0x1e,0x2e,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x04,0x1e,0x1a,0x13,0x13,0x13,0x0c,0x1e,0x33,0x01,0x1e,\r\n  0x1e,0x13,0x0c,0x13,0x1f,0x25,0x27,0x0c,0x22,0x13,0x22,0x1e,0x07,\r\n  0x2b,0x01,0x01,0x1c,0x1e,0x12,0x19,0x05,0x05,0x14,0x21,0x1e,0x36,\r\n  0x01,0x01,0x01,0x01,0x1e,0x1e,0x05,0x13,0x13,0x13,0x1f,0x13,0x19,\r\n  0x2a,0x05,0x13,0x05,0x13,0x13,0x13,0x06,0x1e,0x0f,0x01,0x2e,0x1e,\r\n  0x0a,0x0c,0x0c,0x0c,0x05,0x13,0x0c,0x16,0x2d,0x27,0x0b,0x0c,0x28,\r\n  0x1e,0x1b,0x01,0x2c,0x1e,0x0d,0x02,0x24,0x14,0x1a,0x1e,0x12,0x05,\r\n  0x13,0x13,0x02,0x1e,0x39,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x17,0x1e,0x31,0x22,0x13,0x13,0x2a,\r\n  0x1a,0x13,0x13,0x13,0x16,0x1e,0x3b,0x01,0x01,0x01,0x34,0x1e,0x18,\r\n  0x0c,0x13,0x13,0x13,0x12,0x0d,0x13,0x13,0x13,0x1f,0x1e,0x40,0x01,\r\n  0x01,0x0e,0x1e,0x10,0x05,0x0c,0x13,0x05,0x26,0x1e,0x2a,0x16,0x16,\r\n  0x25,0x21,0x1e,0x3a,0x01,0x37,0x1e,0x24,0x02,0x19,0x1f,0x23,0x1e,\r\n  0x28,0x0c,0x14,0x27,0x0b,0x1e,0x1d,0x01,0x08,0x1e,0x25,0x13,0x13,\r\n  0x13,0x13,0x12,0x15,0x06,0x06,0x1e,0x1e,0x00,0x01,0x36,0x1e,0x31,\r\n  0x13,0x13,0x13,0x13,0x0d,0x28,0x06,0x06,0x10,0x1e,0x36,0x01,0x00,\r\n  0x1e,0x1e,0x0b,0x0c,0x13,0x1f,0x1a,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x3d,0x01,0x01,0x3d,0x1e,0x29,0x0c,0x05,0x22,0x0c,0x06,0x29,\r\n  0x0c,0x02,0x19,0x1f,0x1e,0x1e,0x01,0x35,0x1e,0x2d,0x23,0x13,0x13,\r\n  0x1f,0x0a,0x1e,0x2e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x04,0x1e,\r\n  0x1a,0x13,0x13,0x13,0x0c,0x1e,0x33,0x01,0x1e,0x1e,0x13,0x1f,0x0c,\r\n  0x13,0x23,0x1f,0x0c,0x13,0x05,0x31,0x1e,0x3d,0x01,0x01,0x01,0x1c,\r\n  0x1e,0x24,0x22,0x0c,0x24,0x0d,0x31,0x1e,0x36,0x01,0x01,0x01,0x01,\r\n  0x1e,0x1e,0x26,0x22,0x13,0x0c,0x29,0x1f,0x22,0x15,0x1f,0x0c,0x02,\r\n  0x0c,0x13,0x0c,0x06,0x1e,0x0f,0x01,0x2e,0x1e,0x0a,0x23,0x0c,0x14,\r\n  0x29,0x0c,0x13,0x29,0x2a,0x1f,0x0c,0x05,0x15,0x1e,0x1b,0x01,0x3d,\r\n  0x1e,0x12,0x0b,0x0c,0x14,0x12,0x1e,0x29,0x26,0x22,0x13,0x14,0x1e,\r\n  0x3e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x3a,0x1e,0x15,0x0c,0x19,0x0b,0x2d,0x25,0x1f,0x13,0x13,\r\n  0x29,0x1e,0x04,0x01,0x01,0x01,0x34,0x1e,0x18,0x0c,0x13,0x13,0x13,\r\n  0x13,0x13,0x13,0x13,0x0c,0x1e,0x1e,0x39,0x01,0x01,0x0e,0x1e,0x10,\r\n  0x1f,0x05,0x0c,0x13,0x06,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x11,0x01,\r\n  0x01,0x37,0x1e,0x06,0x14,0x1f,0x0d,0x29,0x1e,0x28,0x0b,0x13,0x05,\r\n  0x23,0x1e,0x32,0x01,0x08,0x1e,0x25,0x13,0x13,0x13,0x13,0x13,0x13,\r\n  0x13,0x13,0x21,0x1e,0x2b,0x01,0x36,0x1e,0x31,0x13,0x13,0x13,0x13,\r\n  0x13,0x13,0x13,0x13,0x26,0x1e,0x3a,0x01,0x20,0x1e,0x09,0x1f,0x0c,\r\n  0x05,0x05,0x12,0x10,0x29,0x12,0x24,0x12,0x26,0x1e,0x38,0x01,0x01,\r\n  0x3d,0x1e,0x06,0x0c,0x0c,0x22,0x0b,0x14,0x23,0x22,0x14,0x1f,0x0d,\r\n  0x1e,0x1e,0x01,0x35,0x1e,0x2d,0x14,0x19,0x0b,0x14,0x16,0x1e,0x2e,\r\n  0x01,0x01,0x01,0x3c,0x37,0x1b,0x1c,0x04,0x1e,0x1a,0x13,0x13,0x13,\r\n  0x0c,0x1e,0x33,0x01,0x1e,0x1e,0x05,0x05,0x13,0x05,0x13,0x13,0x05,\r\n  0x0c,0x19,0x1e,0x32,0x34,0x01,0x01,0x01,0x1c,0x1e,0x12,0x22,0x0b,\r\n  0x14,0x23,0x21,0x1e,0x36,0x01,0x01,0x01,0x01,0x1e,0x1e,0x1f,0x0c,\r\n  0x19,0x23,0x15,0x06,0x14,0x1a,0x0c,0x05,0x12,0x14,0x13,0x1f,0x06,\r\n  0x1e,0x0f,0x01,0x2e,0x1e,0x0a,0x05,0x0c,0x13,0x29,0x22,0x23,0x22,\r\n  0x0a,0x1a,0x0c,0x0c,0x28,0x1e,0x1b,0x01,0x3d,0x1e,0x29,0x27,0x0b,\r\n  0x13,0x27,0x1e,0x1a,0x1f,0x0c,0x19,0x0b,0x1e,0x1e,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x39,0x1e,\r\n  0x12,0x13,0x05,0x0b,0x1e,0x18,0x0c,0x02,0x22,0x22,0x1e,0x3e,0x01,\r\n  0x01,0x01,0x34,0x1e,0x18,0x0c,0x13,0x13,0x13,0x19,0x1f,0x13,0x13,\r\n  0x1f,0x15,0x1e,0x38,0x01,0x01,0x0e,0x1e,0x10,0x14,0x05,0x13,0x0c,\r\n  0x24,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x2b,0x01,0x37,0x1e,0x06,\r\n  0x22,0x05,0x0c,0x02,0x1e,0x15,0x0c,0x02,0x0d,0x19,0x1e,0x32,0x01,\r\n  0x08,0x1e,0x16,0x22,0x0c,0x13,0x13,0x13,0x13,0x13,0x13,0x31,0x1e,\r\n  0x36,0x01,0x36,0x1e,0x31,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,\r\n  0x06,0x1e,0x0f,0x01,0x35,0x1e,0x2d,0x02,0x0c,0x1f,0x22,0x26,0x12,\r\n  0x0c,0x05,0x05,0x13,0x0c,0x1e,0x1e,0x01,0x01,0x3d,0x1e,0x29,0x05,\r\n  0x27,0x05,0x0b,0x06,0x27,0x14,0x22,0x05,0x0c,0x1e,0x1e,0x01,0x35,\r\n  0x1e,0x2d,0x1f,0x05,0x0b,0x14,0x0a,0x1e,0x2e,0x01,0x01,0x32,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1a,0x13,0x13,0x13,0x0c,0x1e,0x33,0x01,\r\n  0x1e,0x1e,0x1f,0x22,0x13,0x1f,0x05,0x05,0x05,0x13,0x0c,0x09,0x1e,\r\n  0x08,0x01,0x01,0x01,0x1c,0x1e,0x26,0x05,0x0b,0x06,0x27,0x31,0x1e,\r\n  0x36,0x01,0x01,0x01,0x01,0x1e,0x1e,0x02,0x13,0x05,0x19,0x21,0x0c,\r\n  0x0c,0x0d,0x0b,0x0b,0x15,0x0c,0x0c,0x02,0x06,0x1e,0x0f,0x01,0x2e,\r\n  0x1e,0x0a,0x0c,0x13,0x1f,0x06,0x29,0x05,0x1f,0x0d,0x14,0x05,0x27,\r\n  0x15,0x1e,0x1b,0x01,0x3d,0x1e,0x12,0x14,0x0c,0x02,0x24,0x1e,0x29,\r\n  0x02,0x13,0x05,0x0b,0x1e,0x1e,0x00,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x1e,0x18,0x05,0x19,0x12,0x14,\r\n  0x28,0x28,0x13,0x14,0x22,0x1f,0x1e,0x33,0x00,0x01,0x01,0x34,0x1e,\r\n  0x18,0x0c,0x13,0x13,0x13,0x09,0x18,0x0c,0x13,0x13,0x1f,0x10,0x1e,\r\n  0x0e,0x01,0x0e,0x1e,0x10,0x14,0x23,0x13,0x0c,0x06,0x1e,0x0d,0x23,\r\n  0x27,0x19,0x15,0x1e,0x37,0x01,0x37,0x1e,0x28,0x14,0x22,0x29,0x02,\r\n  0x1e,0x26,0x1f,0x0c,0x14,0x19,0x1e,0x1d,0x01,0x08,0x1e,0x16,0x22,\r\n  0x0c,0x13,0x13,0x0a,0x31,0x2a,0x2a,0x1e,0x38,0x01,0x01,0x36,0x1e,\r\n  0x31,0x13,0x13,0x13,0x13,0x26,0x21,0x25,0x16,0x09,0x1e,0x17,0x01,\r\n  0x34,0x1e,0x18,0x05,0x0c,0x0c,0x13,0x24,0x2a,0x0c,0x1f,0x23,0x13,\r\n  0x23,0x1e,0x1d,0x01,0x01,0x3d,0x1e,0x12,0x13,0x23,0x22,0x1f,0x10,\r\n  0x24,0x29,0x14,0x22,0x29,0x1e,0x1e,0x01,0x35,0x1e,0x2d,0x02,0x12,\r\n  0x14,0x23,0x25,0x1e,0x2e,0x01,0x3b,0x1e,0x03,0x24,0x15,0x24,0x28,\r\n  0x1e,0x1a,0x13,0x13,0x13,0x0c,0x1e,0x33,0x01,0x1e,0x1e,0x0c,0x13,\r\n  0x0c,0x19,0x06,0x23,0x23,0x13,0x0c,0x12,0x1e,0x38,0x01,0x01,0x01,\r\n  0x1c,0x1e,0x06,0x22,0x1f,0x0c,0x14,0x10,0x1e,0x1e,0x38,0x1b,0x01,\r\n  0x01,0x1e,0x1e,0x0c,0x19,0x12,0x0b,0x18,0x27,0x13,0x0b,0x22,0x19,\r\n  0x03,0x05,0x13,0x23,0x06,0x1e,0x0f,0x01,0x2e,0x1e,0x0a,0x1f,0x13,\r\n  0x05,0x25,0x21,0x1f,0x13,0x19,0x0b,0x13,0x23,0x28,0x1e,0x1b,0x01,\r\n  0x3d,0x1e,0x29,0x22,0x1f,0x0c,0x1a,0x1e,0x0d,0x0c,0x19,0x12,0x02,\r\n  0x1e,0x1d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x36,0x1e,0x21,0x1f,0x0c,0x0b,0x22,0x1f,0x13,0x23,0x0d,\r\n  0x1f,0x22,0x2a,0x1e,0x08,0x01,0x01,0x34,0x1e,0x18,0x0c,0x13,0x13,\r\n  0x13,0x1e,0x1e,0x1f,0x13,0x0c,0x1f,0x0a,0x1e,0x2e,0x01,0x01,0x3e,\r\n  0x1e,0x14,0x13,0x0c,0x23,0x16,0x1e,0x23,0x05,0x0c,0x1f,0x02,0x1e,\r\n  0x11,0x01,0x37,0x1e,0x15,0x02,0x1f,0x1f,0x0d,0x1e,0x1a,0x05,0x29,\r\n  0x22,0x14,0x1e,0x40,0x01,0x08,0x1e,0x2a,0x1f,0x22,0x13,0x13,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x08,0x01,0x36,0x1e,0x31,0x13,0x13,0x13,\r\n  0x0c,0x2d,0x1e,0x1e,0x1e,0x1e,0x2c,0x01,0x01,0x00,0x1e,0x1e,0x02,\r\n  0x0c,0x1f,0x1f,0x06,0x1e,0x15,0x13,0x13,0x0c,0x27,0x1e,0x32,0x01,\r\n  0x01,0x3d,0x1e,0x29,0x0c,0x05,0x13,0x19,0x1e,0x03,0x02,0x02,0x1f,\r\n  0x1f,0x1e,0x1e,0x01,0x35,0x1e,0x2d,0x14,0x0b,0x22,0x1f,0x0a,0x1e,\r\n  0x2e,0x01,0x30,0x1e,0x24,0x0c,0x13,0x0c,0x05,0x1e,0x06,0x13,0x13,\r\n  0x13,0x0c,0x1e,0x33,0x01,0x1e,0x1e,0x1f,0x1f,0x13,0x1f,0x16,0x24,\r\n  0x13,0x0c,0x23,0x05,0x18,0x1e,0x08,0x01,0x01,0x1c,0x1e,0x24,0x13,\r\n  0x19,0x02,0x05,0x10,0x1e,0x1e,0x1e,0x1e,0x1b,0x01,0x1e,0x1e,0x1f,\r\n  0x0c,0x0b,0x0b,0x1e,0x13,0x23,0x0d,0x1f,0x12,0x10,0x1f,0x05,0x27,\r\n  0x26,0x1e,0x0f,0x01,0x2e,0x1e,0x25,0x05,0x13,0x23,0x16,0x1e,0x1f,\r\n  0x0c,0x05,0x0c,0x0c,0x05,0x15,0x1e,0x1b,0x01,0x2c,0x1e,0x24,0x05,\r\n  0x05,0x29,0x0d,0x1e,0x12,0x1f,0x0c,0x0b,0x27,0x1e,0x38,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3b,0x1e,\r\n  0x25,0x13,0x1a,0x19,0x13,0x0b,0x05,0x0c,0x0b,0x05,0x1f,0x29,0x1e,\r\n  0x30,0x01,0x01,0x34,0x1e,0x18,0x0c,0x13,0x1f,0x0c,0x1a,0x14,0x22,\r\n  0x13,0x0c,0x1f,0x0a,0x1e,0x3b,0x01,0x01,0x07,0x1e,0x22,0x1f,0x13,\r\n  0x1f,0x19,0x26,0x13,0x0c,0x0b,0x05,0x25,0x1e,0x37,0x01,0x37,0x1e,\r\n  0x06,0x0c,0x0b,0x02,0x05,0x0d,0x02,0x0c,0x05,0x1f,0x24,0x1e,0x2c,\r\n  0x01,0x08,0x1e,0x16,0x05,0x1f,0x13,0x13,0x0c,0x14,0x22,0x13,0x24,\r\n  0x1e,0x1c,0x01,0x36,0x1e,0x31,0x13,0x13,0x13,0x13,0x03,0x1e,0x08,\r\n  0x3c,0x20,0x01,0x01,0x01,0x01,0x39,0x1e,0x27,0x0c,0x0c,0x13,0x23,\r\n  0x21,0x14,0x1f,0x1f,0x13,0x23,0x1e,0x32,0x01,0x01,0x3d,0x1e,0x12,\r\n  0x1f,0x22,0x0c,0x23,0x1e,0x25,0x14,0x0c,0x0b,0x02,0x1e,0x1e,0x01,\r\n  0x35,0x1e,0x2d,0x0d,0x19,0x13,0x0b,0x0a,0x1e,0x2e,0x01,0x1b,0x1e,\r\n  0x15,0x14,0x13,0x1f,0x13,0x06,0x14,0x13,0x1f,0x0c,0x14,0x1e,0x1e,\r\n  0x01,0x1e,0x1e,0x0c,0x13,0x0b,0x0b,0x2a,0x1e,0x1f,0x13,0x1f,0x0c,\r\n  0x29,0x1e,0x38,0x34,0x01,0x1c,0x1e,0x06,0x0c,0x23,0x22,0x05,0x22,\r\n  0x05,0x0b,0x12,0x1e,0x2c,0x01,0x1e,0x1e,0x13,0x1a,0x19,0x1f,0x1e,\r\n  0x14,0x0c,0x0b,0x14,0x12,0x2d,0x1f,0x13,0x05,0x26,0x1e,0x0f,0x01,\r\n  0x2e,0x1e,0x0a,0x1f,0x0b,0x13,0x28,0x1e,0x14,0x1f,0x02,0x05,0x1f,\r\n  0x22,0x15,0x1e,0x1b,0x01,0x3a,0x1e,0x0a,0x02,0x0c,0x05,0x05,0x28,\r\n  0x0b,0x13,0x1a,0x19,0x12,0x1e,0x1c,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x37,0x1e,0x28,0x13,0x05,0x22,\r\n  0x02,0x18,0x1e,0x29,0x19,0x13,0x0b,0x23,0x1e,0x1d,0x01,0x01,0x34,\r\n  0x1e,0x18,0x1f,0x13,0x1f,0x0c,0x23,0x13,0x13,0x13,0x05,0x14,0x1e,\r\n  0x1e,0x35,0x01,0x01,0x04,0x1e,0x2a,0x13,0x0b,0x23,0x13,0x05,0x05,\r\n  0x0c,0x1f,0x1f,0x1e,0x1e,0x35,0x01,0x37,0x1e,0x26,0x22,0x0b,0x22,\r\n  0x1f,0x14,0x0c,0x14,0x27,0x0c,0x2d,0x1e,0x3b,0x01,0x3c,0x1e,0x16,\r\n  0x13,0x0b,0x13,0x13,0x13,0x14,0x1f,0x13,0x0d,0x1e,0x04,0x01,0x36,\r\n  0x1e,0x31,0x13,0x13,0x13,0x0c,0x31,0x1e,0x36,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x3a,0x1e,0x0a,0x13,0x1f,0x13,0x13,0x0c,0x13,0x1f,0x14,\r\n  0x0b,0x1a,0x1e,0x1d,0x01,0x01,0x30,0x1e,0x12,0x23,0x0b,0x05,0x29,\r\n  0x1e,0x25,0x0b,0x22,0x0b,0x22,0x1e,0x1e,0x01,0x35,0x1e,0x2d,0x22,\r\n  0x22,0x14,0x14,0x0a,0x1e,0x2e,0x01,0x2b,0x1e,0x1e,0x1f,0x13,0x0c,\r\n  0x13,0x0c,0x13,0x13,0x1f,0x0c,0x28,0x1e,0x38,0x01,0x1e,0x1e,0x1f,\r\n  0x13,0x13,0x0c,0x25,0x1e,0x14,0x0b,0x23,0x13,0x05,0x1e,0x1e,0x04,\r\n  0x01,0x1c,0x1e,0x06,0x05,0x29,0x02,0x1f,0x0b,0x22,0x0b,0x27,0x1e,\r\n  0x38,0x01,0x1e,0x1e,0x13,0x05,0x22,0x22,0x1e,0x0d,0x1a,0x19,0x13,\r\n  0x2a,0x2d,0x13,0x05,0x22,0x26,0x1e,0x0f,0x01,0x3b,0x1e,0x16,0x0c,\r\n  0x05,0x05,0x26,0x1e,0x0d,0x0c,0x13,0x0c,0x23,0x0b,0x15,0x1e,0x1b,\r\n  0x01,0x2b,0x1e,0x2d,0x0c,0x14,0x27,0x0c,0x19,0x12,0x13,0x05,0x22,\r\n  0x18,0x1e,0x08,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x2c,0x1e,0x1a,0x1f,0x0b,0x1f,0x06,0x1e,0x1e,0x29,\r\n  0x23,0x22,0x22,0x13,0x31,0x1e,0x36,0x01,0x35,0x1e,0x2d,0x13,0x13,\r\n  0x13,0x05,0x14,0x13,0x23,0x13,0x14,0x09,0x1e,0x38,0x01,0x01,0x01,\r\n  0x34,0x3e,0x1e,0x2a,0x13,0x1f,0x13,0x14,0x13,0x14,0x19,0x1e,0x1e,\r\n  0x38,0x01,0x01,0x39,0x1e,0x29,0x14,0x0d,0x19,0x1f,0x0b,0x05,0x14,\r\n  0x23,0x10,0x1e,0x38,0x01,0x01,0x0f,0x1e,0x15,0x22,0x22,0x13,0x13,\r\n  0x13,0x13,0x22,0x13,0x22,0x1e,0x32,0x01,0x08,0x1e,0x16,0x13,0x13,\r\n  0x1f,0x13,0x25,0x1e,0x08,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x33,\r\n  0x1e,0x26,0x05,0x13,0x0c,0x0c,0x13,0x2d,0x1f,0x13,0x1f,0x1e,0x1e,\r\n  0x00,0x01,0x32,0x1e,0x0b,0x05,0x05,0x0c,0x0c,0x1e,0x0a,0x23,0x14,\r\n  0x0d,0x19,0x1e,0x1e,0x01,0x36,0x1e,0x21,0x0b,0x1f,0x0b,0x24,0x24,\r\n  0x1e,0x37,0x01,0x01,0x11,0x1e,0x1e,0x0c,0x13,0x13,0x05,0x13,0x13,\r\n  0x13,0x25,0x1e,0x1e,0x36,0x01,0x1e,0x1e,0x14,0x13,0x0c,0x0c,0x29,\r\n  0x1e,0x06,0x13,0x1f,0x13,0x14,0x14,0x1e,0x07,0x01,0x38,0x1e,0x02,\r\n  0x0c,0x0c,0x22,0x02,0x23,0x14,0x0d,0x19,0x1e,0x1e,0x01,0x1e,0x1e,\r\n  0x1f,0x0b,0x1f,0x0b,0x1e,0x0d,0x05,0x19,0x22,0x03,0x31,0x13,0x05,\r\n  0x0c,0x29,0x1e,0x2c,0x01,0x1c,0x1e,0x06,0x0c,0x27,0x13,0x0d,0x1e,\r\n  0x24,0x05,0x05,0x0c,0x14,0x05,0x0d,0x1e,0x04,0x01,0x01,0x38,0x1e,\r\n  0x10,0x14,0x22,0x1f,0x05,0x0c,0x1f,0x0b,0x2d,0x1e,0x38,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3a,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1d,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x2b,0x3e,0x1e,\r\n  0x1e,0x10,0x0a,0x16,0x28,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x0f,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,\r\n  0x01,0x01,0x17,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x30,0x01,0x20,0x07,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x40,\r\n  0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x17,0x1e,0x1e,0x1e,0x2a,\r\n  0x25,0x0a,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,0x30,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,\r\n  0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x2f,0x01,0x01,\r\n  0x0e,0x11,0x1e,0x1e,0x18,0x0a,0x16,0x0a,0x03,0x1e,0x1e,0x33,0x36,\r\n  0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x04,0x01,0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x3a,\r\n  0x01,0x3c,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x2e,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x2d,0x25,\r\n  0x16,0x25,0x2d,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3a,0x38,0x1e,0x1e,\r\n  0x1e,0x38,0x3c,0x3b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,\r\n  0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x33,0x39,\r\n  0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x33,0x39,0x35,0x01,0x01,0x01,0x01,0x0f,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x40,0x2c,0x20,0x01,0x01,0x01,0x01,0x17,\r\n  0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x32,0x30,0x01,0x01,\r\n  0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x17,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,\r\n  0x33,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x30,0x32,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x2b,0x38,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x2f,0x01,0x01,0x01,0x01,0x0e,0x39,0x33,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x2b,0x38,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x3b,0x38,0x1e,0x1e,0x1e,0x1e,0x07,0x04,\r\n  0x34,0x01,0x01,0x1c,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x2b,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x38,0x1e,0x1e,\r\n  0x1e,0x38,0x38,0x1e,0x1e,0x1e,0x38,0x3a,0x01,0x01,0x01,0x3c,0x38,\r\n  0x1e,0x1e,0x1e,0x38,0x1b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2e,\r\n  0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x3b,0x3c,0x2e,0x0e,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x34,0x2f,0x08,0x3b,0x35,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x3b,0x3c,0x3b,\r\n  0x17,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x35,0x08,0x08,0x08,0x35,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x00,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x20,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x2e,0x3a,0x3a,0x1b,0x2b,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x35,0x35,0x35,0x35,\r\n  0x35,0x35,0x35,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x34,0x08,0x30,0x1d,0x30,0x1b,0x36,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x00,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x0e,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x0e,0x20,0x0e,0x34,0x01,0x20,\r\n  0x35,0x35,0x35,0x20,0x01,0x01,0x01,0x01,0x01,0x34,0x35,0x35,0x35,\r\n  0x0e,0x01,0x01,0x00,0x0e,0x35,0x35,0x35,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x35,0x35,0x35,0x34,0x01,0x34,0x35,0x35,0x35,0x35,0x35,\r\n  0x01,0x01,0x0e,0x35,0x35,0x00,0x01,0x01,0x01,0x01,0x01,0x34,0x0e,\r\n  0x20,0x35,0x35,0x01,0x01,0x34,0x35,0x35,0x20,0x36,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x35,0x0e,0x20,0x0e,0x34,0x01,0x01,0x20,0x35,0x35,\r\n  0x35,0x20,0x01,0x01,0x01,0x01,0x01,0x20,0x35,0x35,0x35,0x35,0x35,\r\n  0x35,0x35,0x0e,0x20,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,\r\n  0x2e,0x3d,0x3d,0x04,0x3d,0x2e,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x35,0x35,0x35,0x35,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x20,0x3b,0x3d,0x04,0x3d,0x04,0x3a,0x17,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3d,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1d,0x30,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x34,0x04,0x3e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1d,0x1c,0x01,0x01,\r\n  0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x17,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x3d,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,\r\n  0x01,0x3d,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x2b,0x01,0x01,0x3d,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x3d,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x39,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x3d,0x01,0x01,0x01,0x04,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,\r\n  0x39,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x00,0x2c,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x2c,0x01,\r\n  0x01,0x0e,0x11,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x11,0x0e,0x01,0x01,0x01,0x01,0x01,0x1c,0x33,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x33,0x0f,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x04,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x17,0x07,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x3b,0x1e,0x1e,0x2d,0x2d,0x09,0x09,0x09,0x09,0x2d,\r\n  0x09,0x1e,0x1e,0x2c,0x01,0x01,0x01,0x01,0x01,0x04,0x1e,0x1e,0x2d,\r\n  0x28,0x26,0x15,0x28,0x2d,0x1e,0x1e,0x04,0x34,0x01,0x01,0x38,0x1e,\r\n  0x2d,0x2d,0x09,0x09,0x09,0x09,0x2d,0x2d,0x1e,0x1e,0x1e,0x17,0x01,\r\n  0x01,0x01,0x01,0x2b,0x32,0x1e,0x1e,0x16,0x12,0x0b,0x28,0x15,0x1e,\r\n  0x1e,0x1e,0x2b,0x01,0x01,0x01,0x3c,0x1e,0x1e,0x2d,0x2d,0x09,0x09,\r\n  0x09,0x09,0x09,0x2d,0x10,0x1e,0x1e,0x2b,0x01,0x37,0x1e,0x18,0x10,\r\n  0x09,0x10,0x18,0x1e,0x18,0x2d,0x09,0x2d,0x09,0x1e,0x38,0x01,0x17,\r\n  0x1e,0x18,0x2d,0x2d,0x09,0x10,0x1e,0x1e,0x1e,0x10,0x09,0x2d,0x2d,\r\n  0x1e,0x38,0x01,0x01,0x01,0x38,0x1e,0x2d,0x2d,0x2d,0x18,0x1e,0x18,\r\n  0x2d,0x09,0x09,0x2d,0x2d,0x1e,0x1e,0x10,0x2d,0x2d,0x1e,0x1e,0x2f,\r\n  0x01,0x2f,0x1e,0x18,0x10,0x09,0x2d,0x2d,0x1e,0x1e,0x1e,0x2d,0x09,\r\n  0x09,0x31,0x1e,0x38,0x01,0x01,0x3d,0x1e,0x09,0x10,0x09,0x10,0x18,\r\n  0x1e,0x1e,0x09,0x2d,0x2d,0x2d,0x09,0x1e,0x0f,0x01,0x11,0x1e,0x18,\r\n  0x2d,0x09,0x09,0x09,0x09,0x09,0x09,0x10,0x09,0x1e,0x11,0x01,0x01,\r\n  0x01,0x01,0x1c,0x1e,0x1e,0x28,0x0d,0x0d,0x1a,0x29,0x28,0x1e,0x1e,\r\n  0x0f,0x01,0x01,0x01,0x38,0x1e,0x2d,0x2d,0x2d,0x2d,0x18,0x1e,0x1c,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x17,0x1e,0x1e,0x16,0x29,\r\n  0x24,0x26,0x29,0x26,0x09,0x1e,0x38,0x35,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x30,\r\n  0x1e,0x29,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0b,0x09,0x1e,\r\n  0x30,0x01,0x01,0x01,0x0f,0x1e,0x1e,0x14,0x0c,0x22,0x1f,0x1f,0x1f,\r\n  0x13,0x23,0x1e,0x1e,0x04,0x01,0x01,0x1e,0x1e,0x0c,0x13,0x05,0x14,\r\n  0x13,0x13,0x13,0x13,0x13,0x26,0x1e,0x07,0x20,0x01,0x01,0x01,0x38,\r\n  0x1e,0x03,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x15,0x1e,0x32,0x00,\r\n  0x01,0x01,0x1c,0x1e,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,\r\n  0x13,0x28,0x1e,0x2e,0x01,0x38,0x1e,0x23,0x13,0x13,0x13,0x02,0x1e,\r\n  0x13,0x13,0x13,0x0c,0x22,0x1e,0x1e,0x01,0x0f,0x1e,0x26,0x13,0x05,\r\n  0x14,0x13,0x21,0x1e,0x19,0x0c,0x13,0x05,0x14,0x2d,0x1e,0x35,0x01,\r\n  0x2b,0x1e,0x21,0x13,0x13,0x13,0x19,0x1e,0x0c,0x13,0x13,0x13,0x13,\r\n  0x13,0x1e,0x06,0x13,0x13,0x13,0x06,0x1e,0x0f,0x01,0x0f,0x1e,0x06,\r\n  0x13,0x13,0x0c,0x22,0x26,0x1e,0x14,0x13,0x0c,0x13,0x1f,0x1e,0x1e,\r\n  0x01,0x01,0x3e,0x1e,0x19,0x05,0x1f,0x0b,0x14,0x1e,0x09,0x1f,0x1f,\r\n  0x13,0x05,0x1a,0x1e,0x11,0x01,0x1e,0x1e,0x22,0x13,0x13,0x13,0x13,\r\n  0x13,0x13,0x13,0x13,0x0c,0x09,0x1e,0x20,0x01,0x01,0x2f,0x1e,0x1e,\r\n  0x0b,0x13,0x13,0x13,0x13,0x13,0x13,0x02,0x1e,0x33,0x0e,0x01,0x01,\r\n  0x1e,0x1e,0x1f,0x1f,0x1f,0x13,0x23,0x1e,0x1d,0x2c,0x1b,0x0e,0x01,\r\n  0x01,0x01,0x01,0x01,0x38,0x1e,0x26,0x14,0x14,0x0b,0x0c,0x1f,0x19,\r\n  0x05,0x09,0x1e,0x39,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,0x0a,0x13,0x13,\r\n  0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0b,0x1e,0x1d,0x01,0x01,0x01,\r\n  0x38,0x1e,0x02,0x0c,0x0c,0x13,0x13,0x14,0x0c,0x13,0x0b,0x0b,0x1e,\r\n  0x3e,0x01,0x01,0x1e,0x1e,0x14,0x13,0x05,0x02,0x14,0x13,0x0c,0x23,\r\n  0x14,0x13,0x16,0x1e,0x2e,0x01,0x01,0x0e,0x1e,0x10,0x13,0x13,0x13,\r\n  0x13,0x0c,0x13,0x13,0x13,0x13,0x2a,0x1e,0x1b,0x01,0x01,0x1b,0x1e,\r\n  0x15,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x16,0x1e,0x3c,\r\n  0x01,0x1c,0x1e,0x12,0x13,0x13,0x13,0x29,0x1e,0x23,0x0c,0x0c,0x0c,\r\n  0x23,0x1e,0x1d,0x01,0x17,0x1e,0x18,0x0c,0x0c,0x13,0x1f,0x31,0x1e,\r\n  0x19,0x14,0x13,0x05,0x06,0x1e,0x38,0x01,0x01,0x01,0x1d,0x1e,0x0b,\r\n  0x13,0x13,0x12,0x1e,0x23,0x13,0x13,0x13,0x13,0x13,0x1e,0x06,0x13,\r\n  0x13,0x13,0x21,0x1e,0x2f,0x01,0x2f,0x1e,0x1e,0x27,0x0c,0x0c,0x13,\r\n  0x0d,0x1e,0x0c,0x13,0x0b,0x1f,0x2d,0x1e,0x38,0x01,0x01,0x3d,0x1e,\r\n  0x18,0x0b,0x22,0x14,0x02,0x1e,0x25,0x05,0x27,0x22,0x1f,0x1e,0x1e,\r\n  0x0f,0x01,0x1d,0x1e,0x0d,0x14,0x13,0x0c,0x23,0x14,0x13,0x13,0x13,\r\n  0x0b,0x1e,0x1e,0x00,0x01,0x01,0x37,0x1e,0x24,0x1f,0x1f,0x13,0x14,\r\n  0x22,0x13,0x13,0x13,0x0a,0x1e,0x3b,0x01,0x01,0x33,0x1e,0x0c,0x14,\r\n  0x0c,0x13,0x26,0x1e,0x1e,0x1e,0x1e,0x33,0x2b,0x01,0x01,0x01,0x17,\r\n  0x1e,0x18,0x24,0x0d,0x0c,0x02,0x19,0x1f,0x05,0x22,0x19,0x1e,0x33,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x2e,0x1e,0x28,0x13,0x13,0x13,0x0c,0x0d,0x14,\r\n  0x13,0x13,0x13,0x0c,0x2d,0x1e,0x35,0x01,0x35,0x1e,0x2d,0x19,0x13,\r\n  0x0c,0x14,0x15,0x26,0x0c,0x13,0x0c,0x13,0x10,0x1e,0x0e,0x01,0x1e,\r\n  0x1e,0x0c,0x1f,0x23,0x13,0x0d,0x31,0x23,0x19,0x12,0x14,0x0d,0x1e,\r\n  0x04,0x01,0x01,0x3b,0x1e,0x0a,0x13,0x13,0x13,0x13,0x1e,0x05,0x13,\r\n  0x13,0x13,0x1a,0x1e,0x04,0x01,0x01,0x08,0x1e,0x16,0x22,0x02,0x13,\r\n  0x13,0x13,0x13,0x0c,0x19,0x0c,0x31,0x1e,0x36,0x01,0x30,0x1e,0x29,\r\n  0x13,0x13,0x13,0x29,0x1e,0x19,0x19,0x13,0x0c,0x02,0x1e,0x1d,0x01,\r\n  0x01,0x32,0x1e,0x22,0x02,0x14,0x0c,0x28,0x1e,0x1f,0x0c,0x1f,0x23,\r\n  0x06,0x1e,0x0f,0x01,0x01,0x01,0x38,0x1e,0x23,0x0b,0x14,0x19,0x1e,\r\n  0x14,0x13,0x13,0x13,0x13,0x13,0x1e,0x0d,0x13,0x13,0x1f,0x1e,0x40,\r\n  0x01,0x01,0x01,0x3a,0x1e,0x09,0x13,0x0c,0x14,0x05,0x0d,0x0c,0x13,\r\n  0x0c,0x0b,0x1e,0x32,0x2b,0x01,0x01,0x00,0x39,0x1e,0x27,0x05,0x23,\r\n  0x0c,0x18,0x26,0x22,0x27,0x12,0x26,0x1e,0x38,0x01,0x01,0x1c,0x1e,\r\n  0x12,0x19,0x0d,0x02,0x27,0x12,0x14,0x13,0x13,0x0d,0x1e,0x11,0x01,\r\n  0x01,0x01,0x08,0x1e,0x16,0x27,0x0a,0x0a,0x1e,0x26,0x13,0x13,0x13,\r\n  0x29,0x1e,0x30,0x01,0x01,0x33,0x1e,0x0c,0x0c,0x0c,0x13,0x06,0x1e,\r\n  0x27,0x1a,0x28,0x1e,0x1e,0x2b,0x01,0x01,0x3a,0x1e,0x15,0x14,0x23,\r\n  0x22,0x1a,0x21,0x0d,0x1a,0x0c,0x27,0x1e,0x1e,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x2e,0x1e,0x28,0x13,0x13,0x13,0x1f,0x1e,0x09,0x13,0x13,0x13,0x13,\r\n  0x2a,0x1e,0x2f,0x01,0x36,0x1e,0x31,0x0c,0x13,0x0c,0x13,0x1e,0x1e,\r\n  0x0c,0x0c,0x22,0x13,0x03,0x1e,0x2f,0x01,0x1e,0x1e,0x0b,0x0c,0x19,\r\n  0x05,0x2a,0x1e,0x25,0x0b,0x0c,0x1f,0x12,0x1e,0x39,0x01,0x01,0x3a,\r\n  0x1e,0x26,0x13,0x13,0x13,0x13,0x1e,0x2a,0x31,0x31,0x15,0x03,0x1e,\r\n  0x1b,0x01,0x01,0x20,0x07,0x1e,0x1e,0x1e,0x13,0x13,0x13,0x13,0x02,\r\n  0x1e,0x1e,0x1e,0x1d,0x01,0x01,0x30,0x1e,0x29,0x13,0x13,0x13,0x29,\r\n  0x1e,0x23,0x0c,0x13,0x0c,0x0b,0x1e,0x1d,0x01,0x01,0x3d,0x1e,0x12,\r\n  0x1f,0x13,0x0c,0x12,0x1e,0x27,0x0b,0x0c,0x19,0x16,0x1e,0x3c,0x01,\r\n  0x01,0x01,0x37,0x1e,0x06,0x02,0x24,0x1a,0x1e,0x05,0x05,0x05,0x13,\r\n  0x13,0x13,0x1e,0x14,0x13,0x13,0x22,0x1e,0x32,0x01,0x01,0x01,0x01,\r\n  0x38,0x1e,0x1a,0x0c,0x13,0x1f,0x0b,0x0c,0x0c,0x22,0x18,0x1e,0x30,\r\n  0x01,0x01,0x01,0x01,0x3a,0x1e,0x2a,0x23,0x02,0x14,0x06,0x27,0x22,\r\n  0x19,0x05,0x1e,0x1e,0x08,0x01,0x01,0x08,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x27,0x0c,0x1f,0x19,0x05,0x10,0x1e,0x0f,0x01,0x01,0x01,0x2b,0x1e,\r\n  0x1e,0x18,0x28,0x06,0x06,0x0b,0x0c,0x13,0x13,0x0d,0x1e,0x3d,0x01,\r\n  0x01,0x33,0x1e,0x05,0x0b,0x0c,0x0c,0x02,0x13,0x0c,0x0c,0x0c,0x28,\r\n  0x1e,0x04,0x01,0x01,0x3d,0x1e,0x12,0x06,0x27,0x14,0x24,0x1e,0x2a,\r\n  0x28,0x0a,0x25,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,0x28,0x13,\r\n  0x13,0x13,0x1f,0x1e,0x18,0x13,0x13,0x13,0x13,0x16,0x1e,0x3c,0x01,\r\n  0x36,0x1e,0x31,0x0c,0x13,0x1f,0x0c,0x1e,0x21,0x0c,0x0c,0x13,0x05,\r\n  0x25,0x1e,0x3b,0x01,0x1e,0x1e,0x0c,0x05,0x22,0x0c,0x06,0x25,0x05,\r\n  0x02,0x19,0x1f,0x2a,0x1e,0x3a,0x01,0x01,0x3b,0x1e,0x0a,0x13,0x13,\r\n  0x1f,0x1f,0x13,0x02,0x28,0x09,0x1e,0x1e,0x32,0x00,0x01,0x01,0x01,\r\n  0x20,0x3d,0x1e,0x1e,0x13,0x13,0x13,0x13,0x19,0x1e,0x1e,0x11,0x0e,\r\n  0x01,0x01,0x30,0x1e,0x29,0x13,0x13,0x13,0x29,0x1e,0x19,0x0c,0x13,\r\n  0x1f,0x23,0x1e,0x1d,0x01,0x01,0x3b,0x1e,0x16,0x02,0x0c,0x13,0x02,\r\n  0x1e,0x1f,0x0c,0x05,0x0b,0x09,0x1e,0x20,0x01,0x01,0x01,0x08,0x1e,\r\n  0x16,0x0b,0x0c,0x23,0x03,0x14,0x0b,0x26,0x0b,0x13,0x13,0x1e,0x22,\r\n  0x13,0x13,0x0b,0x1e,0x1d,0x01,0x01,0x01,0x01,0x1b,0x1e,0x1e,0x1f,\r\n  0x0c,0x13,0x1f,0x0c,0x0c,0x1a,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,\r\n  0x34,0x3e,0x1e,0x27,0x0b,0x05,0x24,0x12,0x19,0x1a,0x0d,0x1e,0x32,\r\n  0x01,0x01,0x01,0x01,0x08,0x2c,0x07,0x1e,0x24,0x1a,0x27,0x1f,0x05,\r\n  0x25,0x1e,0x38,0x01,0x01,0x01,0x01,0x2c,0x1e,0x0a,0x23,0x27,0x13,\r\n  0x14,0x22,0x0c,0x13,0x13,0x29,0x1e,0x30,0x01,0x01,0x33,0x1e,0x0c,\r\n  0x1f,0x0c,0x0c,0x13,0x05,0x23,0x0c,0x05,0x1a,0x18,0x1e,0x34,0x01,\r\n  0x1c,0x1e,0x24,0x0c,0x14,0x29,0x0d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x04,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,0x28,0x13,0x13,0x13,0x13,0x29,\r\n  0x0b,0x13,0x13,0x13,0x0c,0x09,0x1e,0x35,0x01,0x36,0x1e,0x31,0x0c,\r\n  0x05,0x05,0x13,0x1e,0x21,0x13,0x05,0x0c,0x13,0x16,0x1e,0x08,0x01,\r\n  0x1e,0x1e,0x0c,0x0c,0x22,0x0b,0x14,0x23,0x22,0x14,0x1f,0x25,0x1e,\r\n  0x3e,0x00,0x01,0x01,0x0e,0x1e,0x18,0x19,0x0b,0x14,0x06,0x1f,0x13,\r\n  0x13,0x13,0x1a,0x1e,0x1e,0x3c,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,\r\n  0x13,0x13,0x13,0x13,0x19,0x1e,0x11,0x01,0x01,0x01,0x01,0x30,0x1e,\r\n  0x29,0x13,0x13,0x13,0x12,0x1e,0x19,0x0c,0x05,0x05,0x0b,0x1e,0x1d,\r\n  0x01,0x01,0x2b,0x1e,0x21,0x13,0x05,0x23,0x23,0x21,0x02,0x0c,0x0c,\r\n  0x1a,0x1e,0x38,0x01,0x01,0x01,0x01,0x3c,0x1e,0x16,0x27,0x0b,0x22,\r\n  0x03,0x0b,0x05,0x12,0x19,0x19,0x0b,0x1e,0x06,0x1f,0x13,0x27,0x1e,\r\n  0x39,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x26,0x13,0x05,0x13,0x13,\r\n  0x05,0x18,0x1e,0x2e,0x01,0x01,0x01,0x01,0x01,0x01,0x1c,0x1e,0x16,\r\n  0x22,0x19,0x0b,0x19,0x23,0x0b,0x1e,0x1e,0x30,0x01,0x01,0x01,0x01,\r\n  0x01,0x38,0x1e,0x21,0x27,0x19,0x26,0x12,0x24,0x1e,0x33,0x2b,0x01,\r\n  0x01,0x01,0x34,0x1e,0x18,0x23,0x1f,0x13,0x19,0x1e,0x03,0x22,0x13,\r\n  0x13,0x29,0x1e,0x30,0x01,0x01,0x33,0x1e,0x14,0x13,0x13,0x05,0x22,\r\n  0x06,0x05,0x0c,0x13,0x1f,0x09,0x1e,0x20,0x01,0x2c,0x1e,0x12,0x02,\r\n  0x05,0x02,0x15,0x1e,0x02,0x14,0x27,0x0b,0x1e,0x1e,0x00,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x2e,0x1e,0x28,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,\r\n  0x23,0x1e,0x38,0x01,0x01,0x36,0x1e,0x21,0x0c,0x1f,0x22,0x13,0x1e,\r\n  0x21,0x05,0x05,0x13,0x0c,0x16,0x1e,0x08,0x01,0x1e,0x1e,0x05,0x27,\r\n  0x05,0x0b,0x06,0x27,0x14,0x22,0x05,0x29,0x1e,0x33,0x0e,0x01,0x01,\r\n  0x01,0x38,0x1e,0x09,0x0d,0x14,0x0c,0x0c,0x02,0x22,0x0c,0x13,0x12,\r\n  0x1e,0x2c,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,0x13,0x13,\r\n  0x19,0x1e,0x11,0x01,0x01,0x01,0x01,0x30,0x1e,0x29,0x13,0x13,0x13,\r\n  0x29,0x1e,0x0d,0x0c,0x1f,0x22,0x0b,0x1e,0x1d,0x01,0x01,0x34,0x1e,\r\n  0x18,0x05,0x13,0x05,0x1f,0x28,0x13,0x05,0x27,0x12,0x1e,0x3d,0x01,\r\n  0x01,0x01,0x01,0x2b,0x1e,0x21,0x14,0x0c,0x27,0x26,0x22,0x0b,0x26,\r\n  0x19,0x05,0x0b,0x21,0x0c,0x0c,0x02,0x24,0x1e,0x30,0x01,0x01,0x01,\r\n  0x01,0x01,0x38,0x1e,0x29,0x13,0x1f,0x0c,0x05,0x05,0x2d,0x1e,0x11,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x40,0x1e,0x23,0x02,0x06,0x1a,\r\n  0x0b,0x23,0x1e,0x40,0x01,0x01,0x01,0x01,0x01,0x37,0x1e,0x1e,0x0d,\r\n  0x27,0x19,0x22,0x05,0x09,0x1e,0x3a,0x01,0x01,0x01,0x01,0x20,0x1e,\r\n  0x09,0x0b,0x0b,0x05,0x14,0x2d,0x12,0x1f,0x22,0x13,0x29,0x1e,0x30,\r\n  0x01,0x01,0x33,0x1e,0x05,0x0c,0x05,0x05,0x06,0x1e,0x0c,0x13,0x1f,\r\n  0x05,0x21,0x1e,0x36,0x01,0x1b,0x1e,0x03,0x22,0x05,0x14,0x0b,0x06,\r\n  0x02,0x1f,0x27,0x02,0x1e,0x1e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,0x28,\r\n  0x22,0x13,0x13,0x22,0x13,0x13,0x13,0x13,0x19,0x18,0x1e,0x37,0x01,\r\n  0x01,0x36,0x1e,0x31,0x0c,0x0c,0x13,0x0c,0x1e,0x31,0x1f,0x23,0x13,\r\n  0x0c,0x0a,0x1e,0x3b,0x01,0x1e,0x1e,0x13,0x23,0x22,0x1f,0x24,0x18,\r\n  0x29,0x14,0x22,0x29,0x0a,0x1e,0x3b,0x01,0x01,0x2f,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x2d,0x0b,0x14,0x22,0x0c,0x13,0x1f,0x1e,0x40,0x01,0x01,\r\n  0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,0x13,0x13,0x19,0x1e,0x11,0x01,\r\n  0x01,0x01,0x01,0x30,0x1e,0x12,0x13,0x13,0x1f,0x12,0x1e,0x23,0x0c,\r\n  0x0c,0x13,0x23,0x1e,0x1d,0x01,0x01,0x01,0x39,0x1e,0x02,0x1f,0x1f,\r\n  0x13,0x24,0x14,0x13,0x23,0x28,0x1e,0x1b,0x01,0x01,0x01,0x01,0x0e,\r\n  0x1e,0x10,0x22,0x1f,0x1f,0x02,0x22,0x05,0x21,0x24,0x12,0x14,0x06,\r\n  0x27,0x13,0x14,0x03,0x1e,0x08,0x01,0x01,0x01,0x01,0x30,0x1e,0x31,\r\n  0x13,0x0c,0x19,0x0c,0x1f,0x23,0x1f,0x1e,0x33,0x2b,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x2c,0x1e,0x28,0x02,0x1f,0x0b,0x12,0x09,0x1e,0x2c,\r\n  0x01,0x01,0x01,0x01,0x2b,0x07,0x1e,0x29,0x06,0x24,0x1a,0x29,0x03,\r\n  0x1e,0x1e,0x38,0x0f,0x01,0x01,0x01,0x34,0x1e,0x18,0x0b,0x14,0x13,\r\n  0x0d,0x02,0x23,0x0b,0x13,0x13,0x06,0x1e,0x38,0x01,0x01,0x33,0x1e,\r\n  0x19,0x0c,0x1f,0x23,0x28,0x1e,0x1f,0x13,0x05,0x13,0x03,0x1e,0x17,\r\n  0x01,0x00,0x1e,0x1e,0x02,0x1f,0x0b,0x22,0x0b,0x22,0x1f,0x14,0x29,\r\n  0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,0x28,0x22,0x0c,0x13,0x1f,\r\n  0x25,0x21,0x2a,0x21,0x1e,0x1e,0x04,0x01,0x01,0x01,0x2b,0x1e,0x21,\r\n  0x0c,0x1f,0x1f,0x13,0x1e,0x1e,0x13,0x13,0x0c,0x23,0x31,0x1e,0x36,\r\n  0x01,0x1e,0x1e,0x0c,0x05,0x13,0x19,0x25,0x1e,0x27,0x02,0x1f,0x1f,\r\n  0x15,0x1e,0x3a,0x01,0x01,0x37,0x1e,0x06,0x02,0x1a,0x19,0x16,0x1e,\r\n  0x24,0x1f,0x22,0x13,0x1f,0x09,0x1e,0x20,0x01,0x01,0x01,0x01,0x1e,\r\n  0x1e,0x13,0x13,0x13,0x13,0x19,0x1e,0x11,0x01,0x01,0x01,0x01,0x30,\r\n  0x1e,0x29,0x13,0x0c,0x1f,0x29,0x1e,0x29,0x0c,0x1f,0x1f,0x14,0x1e,\r\n  0x3e,0x01,0x01,0x01,0x0f,0x1e,0x06,0x0c,0x1f,0x0c,0x0b,0x0c,0x0c,\r\n  0x05,0x31,0x1e,0x36,0x01,0x01,0x01,0x01,0x01,0x1d,0x1e,0x19,0x05,\r\n  0x29,0x19,0x1f,0x0b,0x10,0x15,0x0b,0x22,0x0b,0x13,0x23,0x0d,0x10,\r\n  0x1e,0x0e,0x01,0x01,0x01,0x0e,0x40,0x1e,0x0b,0x1f,0x13,0x1f,0x13,\r\n  0x13,0x13,0x0c,0x03,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x17,\r\n  0x1e,0x03,0x19,0x27,0x02,0x0d,0x1e,0x1e,0x20,0x01,0x01,0x01,0x01,\r\n  0x38,0x1e,0x2a,0x27,0x02,0x29,0x1a,0x24,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x3d,0x01,0x01,0x01,0x39,0x1e,0x16,0x24,0x13,0x05,0x02,0x16,0x22,\r\n  0x23,0x13,0x1f,0x09,0x1e,0x20,0x01,0x33,0x1e,0x05,0x13,0x13,0x13,\r\n  0x1a,0x1e,0x05,0x13,0x23,0x14,0x2d,0x1e,0x35,0x01,0x01,0x38,0x1e,\r\n  0x2d,0x02,0x23,0x14,0x0d,0x19,0x1f,0x12,0x1e,0x1e,0x3b,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x2e,0x1e,0x28,0x1f,0x14,0x13,0x05,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x37,0x01,0x01,0x01,0x01,0x35,0x1e,0x2d,0x0c,0x0c,0x13,0x0b,\r\n  0x0d,0x02,0x1f,0x1f,0x13,0x1f,0x09,0x1e,0x20,0x01,0x1e,0x1e,0x1f,\r\n  0x22,0x0c,0x23,0x15,0x1e,0x22,0x0c,0x0b,0x02,0x28,0x1e,0x2e,0x01,\r\n  0x01,0x38,0x1e,0x12,0x19,0x13,0x0b,0x05,0x1e,0x19,0x05,0x1f,0x13,\r\n  0x22,0x1e,0x32,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x0c,0x14,0x13,\r\n  0x22,0x19,0x1e,0x11,0x01,0x01,0x01,0x01,0x3d,0x1e,0x0d,0x13,0x0c,\r\n  0x1f,0x1f,0x0d,0x05,0x0c,0x0c,0x13,0x0d,0x1e,0x11,0x01,0x01,0x01,\r\n  0x2f,0x1e,0x2a,0x0b,0x05,0x1f,0x02,0x05,0x1f,0x23,0x1e,0x07,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x11,0x1e,0x29,0x0c,0x05,0x1f,0x19,0x22,\r\n  0x03,0x03,0x19,0x13,0x0b,0x05,0x0c,0x23,0x1e,0x1e,0x01,0x01,0x01,\r\n  0x01,0x11,0x1e,0x25,0x0b,0x13,0x23,0x0d,0x16,0x0b,0x1f,0x22,0x1f,\r\n  0x1e,0x1e,0x3c,0x01,0x01,0x01,0x01,0x01,0x2f,0x1e,0x03,0x02,0x0b,\r\n  0x22,0x0b,0x18,0x1e,0x34,0x01,0x01,0x01,0x01,0x1e,0x1e,0x23,0x24,\r\n  0x27,0x22,0x23,0x02,0x0d,0x02,0x29,0x12,0x1e,0x1e,0x34,0x01,0x01,\r\n  0x35,0x40,0x1e,0x18,0x25,0x2a,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x01,0x01,0x33,0x1e,0x02,0x1f,0x0b,0x1f,0x22,0x14,0x0c,0x0c,\r\n  0x13,0x05,0x09,0x1e,0x20,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x2d,0x28,\r\n  0x25,0x21,0x1e,0x1e,0x1e,0x1b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,\r\n  0x28,0x14,0x1f,0x13,0x1f,0x09,0x1e,0x2f,0x2b,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x38,0x1e,0x1a,0x1f,0x13,0x13,0x0c,0x13,0x1f,0x13,\r\n  0x0b,0x0d,0x1e,0x38,0x01,0x01,0x1e,0x1e,0x23,0x0b,0x05,0x29,0x0a,\r\n  0x1e,0x0b,0x22,0x0b,0x22,0x25,0x1e,0x38,0x01,0x01,0x37,0x1e,0x16,\r\n  0x22,0x14,0x14,0x13,0x1a,0x19,0x13,0x0b,0x13,0x16,0x1e,0x30,0x01,\r\n  0x01,0x01,0x01,0x01,0x1e,0x1e,0x0c,0x23,0x13,0x13,0x19,0x1e,0x11,\r\n  0x01,0x01,0x01,0x01,0x3b,0x1e,0x18,0x13,0x05,0x05,0x13,0x05,0x0c,\r\n  0x13,0x1f,0x13,0x1e,0x1e,0x37,0x01,0x01,0x01,0x20,0x1e,0x09,0x05,\r\n  0x1f,0x0c,0x13,0x0c,0x23,0x02,0x1e,0x32,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x1c,0x1e,0x12,0x14,0x27,0x0c,0x19,0x12,0x2d,0x25,0x22,0x14,\r\n  0x14,0x13,0x1a,0x02,0x1e,0x33,0x01,0x01,0x01,0x1c,0x1e,0x1e,0x0c,\r\n  0x14,0x13,0x13,0x24,0x1e,0x27,0x13,0x0b,0x19,0x06,0x1e,0x38,0x01,\r\n  0x01,0x01,0x01,0x01,0x2f,0x1e,0x03,0x29,0x29,0x02,0x23,0x1e,0x1e,\r\n  0x00,0x01,0x01,0x01,0x01,0x1e,0x1e,0x29,0x1a,0x23,0x27,0x19,0x0b,\r\n  0x12,0x27,0x14,0x1a,0x1e,0x1e,0x00,0x01,0x01,0x01,0x2b,0x38,0x1e,\r\n  0x1e,0x1e,0x1e,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x33,\r\n  0x1e,0x14,0x0c,0x02,0x13,0x0b,0x23,0x13,0x14,0x05,0x0b,0x1e,0x1e,\r\n  0x00,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,\r\n  0x1b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x30,0x1e,0x29,0x13,0x22,0x13,\r\n  0x13,0x10,0x1e,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,\r\n  0x1e,0x1e,0x12,0x13,0x0c,0x0c,0x13,0x05,0x13,0x06,0x1e,0x1e,0x37,\r\n  0x01,0x01,0x1e,0x1e,0x05,0x05,0x0c,0x0c,0x0d,0x1e,0x19,0x14,0x0d,\r\n  0x19,0x1f,0x1e,0x1e,0x00,0x01,0x20,0x07,0x1e,0x2a,0x0b,0x24,0x13,\r\n  0x05,0x23,0x22,0x22,0x10,0x1e,0x3e,0x34,0x01,0x01,0x01,0x01,0x01,\r\n  0x1e,0x1e,0x05,0x14,0x13,0x0b,0x1f,0x1e,0x40,0x01,0x01,0x01,0x01,\r\n  0x01,0x38,0x1e,0x10,0x1f,0x14,0x13,0x05,0x0c,0x1f,0x05,0x2a,0x1e,\r\n  0x38,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x23,0x13,0x05,0x05,0x0c,\r\n  0x05,0x1a,0x1e,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x3d,0x1e,0x12,\r\n  0x14,0x22,0x1f,0x05,0x0c,0x16,0x09,0x1f,0x0b,0x24,0x13,0x05,0x23,\r\n  0x1e,0x1e,0x01,0x01,0x01,0x1d,0x1e,0x23,0x1f,0x0b,0x13,0x0c,0x21,\r\n  0x1e,0x0d,0x13,0x19,0x1f,0x05,0x09,0x1e,0x20,0x01,0x01,0x01,0x01,\r\n  0x1b,0x1e,0x28,0x0c,0x22,0x27,0x19,0x2d,0x1e,0x35,0x01,0x01,0x01,\r\n  0x01,0x1e,0x1e,0x05,0x27,0x1a,0x0d,0x26,0x0d,0x27,0x19,0x1a,0x02,\r\n  0x18,0x1e,0x20,0x01,0x01,0x01,0x01,0x01,0x35,0x3b,0x3c,0x34,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x1f,0x14,0x23,\r\n  0x13,0x0a,0x1f,0x13,0x0b,0x13,0x2a,0x1e,0x3d,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x0e,0x2e,0x08,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x08,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,0x1e,0x1e,\r\n  0x22,0x0c,0x1f,0x29,0x1e,0x1e,0x1e,0x37,0x01,0x01,0x01,0x38,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,\r\n  0x01,0x01,0x01,0x2b,0x3e,0x1e,0x1e,0x31,0x25,0x2a,0x25,0x09,0x1e,\r\n  0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x2c,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,\r\n  0x1e,0x2d,0x25,0x16,0x28,0x10,0x1e,0x1e,0x32,0x2b,0x01,0x01,0x01,\r\n  0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x3a,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x3b,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,\r\n  0x01,0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x2b,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x11,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x16,\r\n  0x16,0x1e,0x1e,0x3e,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x08,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x3b,0x1e,0x1e,0x02,0x0c,0x1f,0x22,\r\n  0x1f,0x1e,0x33,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x39,0x33,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,\r\n  0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x40,0x2c,\r\n  0x20,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x3a,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x3b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x38,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x1c,0x1d,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x0f,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,\r\n  0x2b,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x11,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x40,0x1e,0x05,0x13,0x13,0x13,0x1f,0x1e,0x1e,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x36,\r\n  0x3b,0x3c,0x08,0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x08,0x3c,0x2e,0x0e,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x20,0x08,0x08,0x20,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x39,\r\n  0x1e,0x2d,0x29,0x12,0x0d,0x12,0x1e,0x1e,0x00,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x39,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x3d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x3b,0x30,0x1c,0x3d,0x1c,0x3c,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x35,\r\n  0x35,0x35,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3c,0x37,0x04,\r\n  0x3d,0x2c,0x37,0x3c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x35,0x35,0x35,0x0e,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x2f,\r\n  0x37,0x2c,0x3d,0x3b,0x2b,0x2e,0x3b,0x3b,0x0e,0x01,0x01,0x01,0x01,\r\n  0x01,0x35,0x35,0x35,0x35,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x00,0x35,0x35,0x35,0x0e,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x20,0x35,0x20,0x0e,0x00,0x01,0x01,0x01,0x01,0x01,0x34,\r\n  0x35,0x35,0x0e,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x34,0x0e,0x35,0x35,0x34,0x01,0x01,0x01,0x01,0x01,\r\n  0x2b,0x1b,0x3b,0x1b,0x36,0x2e,0x04,0x2c,0x3a,0x17,0x3b,0x3d,0x2c,\r\n  0x37,0x2f,0x01,0x01,0x01,0x01,0x01,0x36,0x3a,0x08,0x2e,0x17,0x2f,\r\n  0x37,0x39,0x2c,0x1b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,\r\n  0x2e,0x3d,0x3d,0x3d,0x04,0x2e,0x35,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x17,0x2e,0x3b,0x3b,0x35,0x1b,0x04,0x2c,0x30,0x08,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x2f,0x37,0x39,0x04,0x1b,0x17,0x3b,0x3b,\r\n  0x2e,0x17,0x01,0x01,0x01,0x01,0x01,0x17,0x2e,0x3b,0x2e,0x0e,0x08,\r\n  0x30,0x3d,0x3b,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x3c,0x37,0x2c,\r\n  0x30,0x04,0x30,0x3b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,\r\n  0x3b,0x30,0x0f,0x1c,0x08,0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x3d,\r\n  0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x35,0x39,0x40,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x38,0x2b,0x01,0x01,0x2b,0x11,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x11,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x3d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x30,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x3d,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x04,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3d,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x2c,0x20,0x01,0x01,0x11,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x01,\r\n  0x01,0x01,0x36,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1d,0x2b,0x01,0x01,0x01,0x01,0x01,0x30,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x40,0x30,0x01,0x01,0x01,0x01,0x35,0x32,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1b,0x01,0x01,0x01,0x01,0x01,\r\n  0x3d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1d,0x35,\r\n  0x01,0x2b,0x32,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x3d,\r\n  0x01,0x01,0x01,0x01,0x2b,0x32,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1d,0x2b,0x01,0x01,0x01,0x01,0x01,0x0e,0x33,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x40,0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x38,0x1e,0x21,0x09,0x2d,0x09,0x1e,0x1e,0x2b,0x01,0x01,0x2b,\r\n  0x3e,0x1e,0x21,0x24,0x1a,0x0d,0x27,0x24,0x21,0x1e,0x1d,0x2b,0x01,\r\n  0x01,0x01,0x01,0x39,0x1e,0x1e,0x2d,0x2d,0x09,0x2d,0x18,0x1e,0x38,\r\n  0x01,0x01,0x11,0x1e,0x2d,0x24,0x24,0x12,0x10,0x21,0x28,0x0a,0x0a,\r\n  0x10,0x1e,0x2e,0x01,0x38,0x1e,0x2d,0x2d,0x2d,0x2d,0x1e,0x1e,0x3c,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x2f,0x1e,0x1e,0x2d,0x2d,0x2d,0x2d,\r\n  0x1e,0x38,0x01,0x01,0x01,0x38,0x1e,0x09,0x2d,0x09,0x10,0x1e,0x1e,\r\n  0x3c,0x01,0x38,0x1e,0x18,0x2d,0x09,0x10,0x18,0x1e,0x30,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,0x18,0x10,0x09,0x2d,0x18,\r\n  0x1e,0x2c,0x01,0x2e,0x1e,0x10,0x15,0x0a,0x15,0x09,0x10,0x1a,0x27,\r\n  0x26,0x1e,0x31,0x29,0x27,0x06,0x1e,0x1e,0x1c,0x01,0x01,0x38,0x1e,\r\n  0x15,0x25,0x0a,0x03,0x1e,0x06,0x0d,0x1a,0x31,0x1e,0x38,0x01,0x01,\r\n  0x01,0x01,0x30,0x1e,0x1e,0x28,0x12,0x12,0x0d,0x1a,0x0a,0x1e,0x1e,\r\n  0x30,0x01,0x01,0x01,0x39,0x1e,0x03,0x28,0x0a,0x0a,0x1e,0x21,0x1a,\r\n  0x27,0x29,0x1e,0x1e,0x1b,0x01,0x01,0x01,0x0f,0x1e,0x1e,0x24,0x02,\r\n  0x0d,0x1e,0x03,0x0a,0x25,0x28,0x03,0x1e,0x39,0x01,0x38,0x1e,0x03,\r\n  0x0a,0x25,0x0a,0x09,0x2d,0x12,0x24,0x1e,0x1e,0x00,0x01,0x01,0x2b,\r\n  0x3e,0x1e,0x03,0x06,0x27,0x12,0x24,0x29,0x31,0x1e,0x3e,0x2b,0x01,\r\n  0x01,0x01,0x01,0x1c,0x1e,0x0a,0x12,0x06,0x24,0x25,0x1e,0x30,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3b,0x30,0x39,0x1e,0x1e,0x13,\r\n  0x13,0x13,0x13,0x28,0x1e,0x1b,0x01,0x01,0x38,0x1e,0x16,0x13,0x13,\r\n  0x13,0x13,0x13,0x13,0x13,0x31,0x1e,0x38,0x01,0x01,0x01,0x00,0x1e,\r\n  0x1e,0x1f,0x13,0x13,0x13,0x13,0x0c,0x1e,0x1e,0x01,0x01,0x1e,0x1e,\r\n  0x1f,0x0c,0x1f,0x13,0x0c,0x1f,0x13,0x27,0x0b,0x0d,0x1e,0x04,0x01,\r\n  0x1e,0x1e,0x13,0x13,0x13,0x13,0x12,0x1e,0x39,0x2c,0x1b,0x35,0x01,\r\n  0x01,0x01,0x37,0x1e,0x24,0x13,0x13,0x13,0x13,0x1e,0x1e,0x01,0x01,\r\n  0x36,0x1e,0x21,0x13,0x13,0x13,0x13,0x12,0x1e,0x1c,0x01,0x1e,0x1e,\r\n  0x1f,0x1f,0x13,0x0c,0x0b,0x1e,0x1d,0x3a,0x08,0x2e,0x2e,0x0e,0x01,\r\n  0x01,0x01,0x04,0x1e,0x1a,0x13,0x13,0x13,0x05,0x1e,0x07,0x01,0x04,\r\n  0x1e,0x29,0x13,0x13,0x13,0x05,0x0c,0x13,0x13,0x13,0x15,0x13,0x13,\r\n  0x13,0x13,0x19,0x1e,0x38,0x01,0x01,0x1e,0x1e,0x0c,0x0c,0x0c,0x1f,\r\n  0x1f,0x0c,0x1f,0x13,0x27,0x21,0x1e,0x3b,0x01,0x01,0x08,0x1e,0x1e,\r\n  0x1a,0x05,0x02,0x24,0x14,0x13,0x13,0x19,0x1e,0x1e,0x1b,0x01,0x01,\r\n  0x33,0x1e,0x0c,0x13,0x13,0x13,0x22,0x13,0x13,0x13,0x13,0x1a,0x1e,\r\n  0x38,0x01,0x01,0x01,0x38,0x1e,0x19,0x13,0x13,0x13,0x02,0x13,0x0c,\r\n  0x13,0x1f,0x23,0x1e,0x33,0x01,0x1e,0x1e,0x13,0x0c,0x1f,0x13,0x27,\r\n  0x0b,0x0c,0x19,0x2d,0x1e,0x35,0x01,0x01,0x38,0x1e,0x2a,0x02,0x24,\r\n  0x22,0x13,0x0c,0x14,0x14,0x2a,0x1e,0x38,0x01,0x01,0x01,0x2b,0x3e,\r\n  0x1e,0x19,0x13,0x1f,0x14,0x0b,0x1e,0x1e,0x04,0x01,0x01,0x01,0x01,\r\n  0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x13,0x13,0x13,0x13,0x2a,\r\n  0x1e,0x2f,0x01,0x36,0x1e,0x1e,0x13,0x13,0x13,0x0c,0x02,0x13,0x13,\r\n  0x13,0x13,0x1e,0x1e,0x01,0x01,0x01,0x04,0x1e,0x03,0x13,0x13,0x13,\r\n  0x0c,0x22,0x15,0x1e,0x38,0x01,0x17,0x1e,0x31,0x0c,0x05,0x02,0x0c,\r\n  0x13,0x1f,0x0c,0x1f,0x0c,0x15,0x1e,0x3a,0x01,0x1e,0x1e,0x13,0x13,\r\n  0x13,0x13,0x16,0x1e,0x1e,0x1e,0x1e,0x33,0x2b,0x01,0x01,0x2f,0x1e,\r\n  0x03,0x14,0x22,0x22,0x1f,0x1e,0x40,0x01,0x01,0x20,0x1e,0x18,0x02,\r\n  0x14,0x0b,0x13,0x2a,0x1e,0x3c,0x01,0x38,0x1e,0x0d,0x0c,0x13,0x0b,\r\n  0x12,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x39,0x01,0x01,0x3a,0x1e,\r\n  0x26,0x0c,0x23,0x14,0x0d,0x1e,0x2c,0x01,0x3a,0x1e,0x25,0x22,0x13,\r\n  0x13,0x1f,0x1f,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0c,0x0c,0x21,\r\n  0x1e,0x2b,0x01,0x1e,0x1e,0x23,0x0c,0x05,0x02,0x0c,0x13,0x1f,0x0c,\r\n  0x1f,0x29,0x1e,0x3d,0x01,0x01,0x1c,0x1e,0x24,0x05,0x22,0x0b,0x05,\r\n  0x14,0x27,0x0c,0x0b,0x15,0x1e,0x2c,0x01,0x01,0x39,0x1e,0x27,0x13,\r\n  0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x2d,0x1e,0x0e,0x01,0x0e,\r\n  0x1e,0x10,0x13,0x13,0x13,0x0c,0x0c,0x13,0x1f,0x0c,0x13,0x1a,0x1e,\r\n  0x39,0x01,0x38,0x1e,0x02,0x13,0x1f,0x0c,0x1f,0x0c,0x05,0x0b,0x18,\r\n  0x1e,0x34,0x01,0x01,0x1e,0x1e,0x22,0x0b,0x1f,0x22,0x26,0x14,0x0b,\r\n  0x15,0x0b,0x1e,0x1e,0x34,0x01,0x01,0x38,0x1e,0x2a,0x1a,0x14,0x0c,\r\n  0x14,0x0b,0x2a,0x18,0x1e,0x20,0x01,0x01,0x01,0x01,0x38,0x1e,0x10,\r\n  0x29,0x02,0x06,0x1e,0x13,0x13,0x13,0x13,0x2a,0x1e,0x2f,0x01,0x1b,\r\n  0x1e,0x15,0x13,0x13,0x13,0x02,0x1e,0x24,0x13,0x13,0x13,0x10,0x1e,\r\n  0x08,0x01,0x1b,0x1e,0x18,0x0d,0x13,0x13,0x1f,0x19,0x26,0x10,0x1e,\r\n  0x11,0x01,0x2e,0x1e,0x28,0x0c,0x13,0x13,0x05,0x1e,0x1e,0x14,0x02,\r\n  0x0c,0x26,0x1e,0x3a,0x01,0x1e,0x1e,0x13,0x13,0x0b,0x14,0x25,0x10,\r\n  0x02,0x27,0x0a,0x1e,0x07,0x34,0x01,0x0e,0x1e,0x0a,0x0a,0x0a,0x0a,\r\n  0x0a,0x1e,0x38,0x01,0x01,0x00,0x1e,0x1e,0x0a,0x0a,0x0a,0x0a,0x0a,\r\n  0x1e,0x2b,0x01,0x39,0x1e,0x02,0x0c,0x13,0x0c,0x29,0x1e,0x10,0x26,\r\n  0x16,0x0a,0x0a,0x2d,0x1e,0x35,0x01,0x0f,0x1e,0x28,0x1f,0x19,0x12,\r\n  0x29,0x1e,0x04,0x01,0x0f,0x1e,0x26,0x0c,0x19,0x0b,0x23,0x26,0x1f,\r\n  0x13,0x13,0x13,0x02,0x14,0x13,0x1f,0x0c,0x16,0x1e,0x3c,0x01,0x1e,\r\n  0x1e,0x05,0x0c,0x13,0x13,0x19,0x27,0x0c,0x14,0x02,0x19,0x1e,0x38,\r\n  0x01,0x01,0x11,0x1e,0x24,0x1a,0x0c,0x27,0x16,0x0a,0x05,0x0c,0x05,\r\n  0x22,0x1e,0x07,0x01,0x01,0x39,0x1e,0x27,0x13,0x13,0x13,0x0c,0x06,\r\n  0x13,0x13,0x13,0x13,0x10,0x1e,0x0e,0x01,0x3b,0x1e,0x0a,0x13,0x14,\r\n  0x13,0x05,0x1a,0x14,0x05,0x13,0x05,0x27,0x1e,0x39,0x01,0x11,0x1e,\r\n  0x27,0x23,0x0c,0x14,0x02,0x0c,0x0c,0x22,0x09,0x1e,0x20,0x01,0x01,\r\n  0x1e,0x1e,0x0c,0x27,0x27,0x1f,0x16,0x16,0x0a,0x03,0x16,0x1e,0x1e,\r\n  0x34,0x01,0x35,0x1e,0x2d,0x0c,0x1f,0x13,0x0c,0x1f,0x13,0x27,0x16,\r\n  0x1e,0x08,0x01,0x01,0x01,0x3b,0x1e,0x2d,0x13,0x13,0x13,0x13,0x29,\r\n  0x13,0x13,0x13,0x13,0x2a,0x1e,0x2f,0x01,0x3a,0x1e,0x26,0x13,0x13,\r\n  0x13,0x0c,0x02,0x1f,0x13,0x13,0x13,0x29,0x1e,0x30,0x01,0x04,0x1e,\r\n  0x1a,0x13,0x13,0x13,0x13,0x0c,0x13,0x1f,0x1e,0x33,0x01,0x2e,0x1e,\r\n  0x0a,0x13,0x1f,0x1f,0x14,0x1e,0x1e,0x0c,0x13,0x05,0x28,0x1e,0x3a,\r\n  0x01,0x1e,0x1e,0x19,0x05,0x02,0x24,0x23,0x13,0x13,0x05,0x05,0x16,\r\n  0x1e,0x1c,0x01,0x2e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x01,\r\n  0x01,0x35,0x1e,0x2d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1b,0x01,0x39,\r\n  0x1e,0x0d,0x0c,0x0c,0x22,0x12,0x1e,0x1f,0x0c,0x1f,0x13,0x0c,0x10,\r\n  0x1e,0x0e,0x01,0x0f,0x1e,0x26,0x14,0x0b,0x0c,0x0d,0x1e,0x04,0x01,\r\n  0x0f,0x1e,0x28,0x13,0x05,0x0b,0x24,0x1e,0x1f,0x02,0x22,0x1f,0x1e,\r\n  0x0b,0x0c,0x02,0x0c,0x28,0x1e,0x1b,0x01,0x1e,0x1e,0x0c,0x13,0x1f,\r\n  0x1f,0x1e,0x2a,0x1f,0x0c,0x13,0x0b,0x1e,0x07,0x01,0x20,0x1e,0x09,\r\n  0x14,0x14,0x14,0x14,0x10,0x1e,0x0d,0x05,0x0b,0x27,0x2d,0x1e,0x35,\r\n  0x01,0x39,0x1e,0x27,0x13,0x13,0x13,0x27,0x1e,0x13,0x13,0x13,0x13,\r\n  0x03,0x1e,0x17,0x01,0x1b,0x1e,0x15,0x13,0x13,0x0c,0x02,0x1e,0x02,\r\n  0x22,0x13,0x1f,0x27,0x1e,0x39,0x01,0x11,0x1e,0x19,0x05,0x1f,0x0c,\r\n  0x13,0x05,0x24,0x23,0x18,0x1e,0x34,0x01,0x01,0x1e,0x1e,0x14,0x14,\r\n  0x1f,0x27,0x15,0x1a,0x06,0x16,0x1e,0x1e,0x3d,0x01,0x01,0x00,0x1e,\r\n  0x1e,0x02,0x02,0x0c,0x13,0x1f,0x0c,0x0b,0x21,0x1e,0x2b,0x01,0x01,\r\n  0x01,0x30,0x1e,0x29,0x1f,0x1f,0x13,0x13,0x13,0x13,0x13,0x13,0x13,\r\n  0x2a,0x1e,0x2f,0x01,0x1b,0x1e,0x15,0x13,0x13,0x13,0x13,0x13,0x0b,\r\n  0x1a,0x27,0x0b,0x26,0x1e,0x3a,0x01,0x1b,0x1e,0x25,0x13,0x13,0x13,\r\n  0x0c,0x0c,0x13,0x12,0x1e,0x11,0x01,0x3b,0x1e,0x0a,0x13,0x05,0x13,\r\n  0x23,0x1e,0x1e,0x22,0x14,0x13,0x15,0x1e,0x3a,0x01,0x1e,0x1e,0x05,\r\n  0x22,0x0b,0x0c,0x14,0x27,0x0c,0x0b,0x26,0x27,0x1e,0x38,0x01,0x3c,\r\n  0x1e,0x16,0x13,0x13,0x13,0x13,0x1e,0x1e,0x01,0x01,0x20,0x1e,0x09,\r\n  0x05,0x13,0x13,0x13,0x25,0x1e,0x08,0x01,0x39,0x1e,0x27,0x0c,0x0c,\r\n  0x13,0x0a,0x09,0x0c,0x05,0x02,0x0c,0x03,0x1e,0x38,0x01,0x01,0x0f,\r\n  0x1e,0x28,0x0c,0x02,0x19,0x0d,0x1e,0x04,0x01,0x0f,0x1e,0x26,0x19,\r\n  0x12,0x14,0x06,0x1e,0x0c,0x14,0x22,0x0c,0x1e,0x02,0x13,0x23,0x1f,\r\n  0x0a,0x1e,0x3b,0x01,0x1e,0x1e,0x1f,0x13,0x05,0x13,0x1e,0x21,0x13,\r\n  0x22,0x14,0x22,0x1e,0x3e,0x01,0x0e,0x1e,0x10,0x29,0x14,0x1f,0x22,\r\n  0x2a,0x1e,0x14,0x14,0x05,0x14,0x18,0x1e,0x34,0x01,0x39,0x1e,0x27,\r\n  0x13,0x13,0x13,0x24,0x1e,0x13,0x22,0x13,0x13,0x28,0x1e,0x2e,0x01,\r\n  0x2e,0x1e,0x28,0x1f,0x1f,0x13,0x1f,0x1e,0x02,0x13,0x0c,0x19,0x27,\r\n  0x1e,0x39,0x01,0x11,0x1e,0x02,0x1f,0x13,0x22,0x14,0x2d,0x1e,0x09,\r\n  0x1e,0x04,0x01,0x01,0x01,0x38,0x1e,0x21,0x23,0x14,0x1f,0x0b,0x22,\r\n  0x22,0x0c,0x29,0x1e,0x1e,0x00,0x01,0x01,0x3d,0x1e,0x18,0x0b,0x05,\r\n  0x23,0x0c,0x27,0x1e,0x1e,0x1e,0x00,0x01,0x01,0x01,0x2c,0x1e,0x29,\r\n  0x14,0x06,0x1f,0x0c,0x24,0x13,0x13,0x13,0x13,0x2a,0x1e,0x2f,0x01,\r\n  0x37,0x1e,0x24,0x13,0x13,0x13,0x29,0x1e,0x18,0x16,0x03,0x16,0x21,\r\n  0x1e,0x36,0x01,0x35,0x40,0x1e,0x15,0x14,0x13,0x1f,0x14,0x21,0x1e,\r\n  0x1e,0x08,0x01,0x1b,0x1e,0x28,0x13,0x23,0x05,0x1f,0x25,0x1e,0x05,\r\n  0x0c,0x0c,0x26,0x1e,0x3a,0x01,0x1e,0x1e,0x1a,0x0c,0x27,0x0b,0x22,\r\n  0x19,0x0c,0x05,0x1f,0x22,0x1e,0x3e,0x01,0x3c,0x1e,0x16,0x13,0x13,\r\n  0x13,0x13,0x1e,0x1e,0x01,0x01,0x20,0x1e,0x09,0x1f,0x13,0x13,0x13,\r\n  0x25,0x1e,0x08,0x01,0x39,0x1e,0x02,0x13,0x05,0x0c,0x1a,0x27,0x0c,\r\n  0x13,0x13,0x1a,0x1e,0x32,0x2b,0x01,0x01,0x0f,0x1e,0x15,0x22,0x14,\r\n  0x1f,0x06,0x1e,0x04,0x01,0x0f,0x1e,0x26,0x0c,0x0b,0x22,0x12,0x1e,\r\n  0x23,0x0d,0x1f,0x23,0x1e,0x23,0x05,0x27,0x1f,0x0a,0x1e,0x3b,0x01,\r\n  0x1e,0x1e,0x05,0x13,0x23,0x05,0x1e,0x31,0x0c,0x05,0x0c,0x0b,0x1e,\r\n  0x3e,0x01,0x34,0x1e,0x18,0x0b,0x05,0x27,0x05,0x18,0x1e,0x22,0x0c,\r\n  0x0b,0x14,0x10,0x1e,0x0e,0x01,0x39,0x1e,0x0d,0x13,0x13,0x13,0x27,\r\n  0x1e,0x13,0x0c,0x13,0x13,0x21,0x1e,0x36,0x01,0x0f,0x1e,0x26,0x1f,\r\n  0x13,0x05,0x0b,0x1e,0x23,0x1f,0x13,0x1f,0x27,0x1e,0x39,0x01,0x11,\r\n  0x1e,0x02,0x1f,0x0c,0x05,0x02,0x1e,0x38,0x1e,0x04,0x01,0x01,0x01,\r\n  0x01,0x38,0x1e,0x1e,0x09,0x16,0x28,0x1a,0x1f,0x19,0x22,0x1f,0x21,\r\n  0x1e,0x2b,0x01,0x01,0x01,0x39,0x1e,0x27,0x13,0x05,0x1f,0x1a,0x1e,\r\n  0x1e,0x3d,0x01,0x01,0x01,0x01,0x38,0x1e,0x1a,0x14,0x0c,0x0c,0x12,\r\n  0x1e,0x0c,0x13,0x13,0x13,0x2a,0x1e,0x2f,0x01,0x2f,0x1e,0x03,0x0c,\r\n  0x14,0x13,0x19,0x09,0x27,0x13,0x1f,0x13,0x03,0x1e,0x17,0x01,0x01,\r\n  0x17,0x1e,0x03,0x13,0x0c,0x02,0x22,0x1e,0x1e,0x3d,0x01,0x01,0x3c,\r\n  0x1e,0x16,0x0c,0x13,0x0c,0x0b,0x05,0x1f,0x02,0x05,0x1f,0x15,0x1e,\r\n  0x3a,0x01,0x1e,0x1e,0x14,0x14,0x14,0x0c,0x1e,0x21,0x05,0x0b,0x02,\r\n  0x0b,0x1e,0x1d,0x01,0x3c,0x1e,0x16,0x13,0x13,0x13,0x13,0x1e,0x1e,\r\n  0x01,0x01,0x20,0x1e,0x09,0x1f,0x13,0x13,0x13,0x25,0x1e,0x08,0x01,\r\n  0x39,0x1e,0x02,0x05,0x05,0x13,0x0c,0x0c,0x13,0x1f,0x22,0x1e,0x1e,\r\n  0x3a,0x01,0x01,0x01,0x0f,0x1e,0x28,0x14,0x22,0x05,0x0d,0x1e,0x04,\r\n  0x01,0x0f,0x1e,0x26,0x1a,0x19,0x13,0x24,0x1e,0x1f,0x0b,0x14,0x05,\r\n  0x1e,0x19,0x13,0x05,0x22,0x0a,0x1e,0x3b,0x01,0x1e,0x1e,0x1f,0x0b,\r\n  0x13,0x0c,0x1e,0x31,0x1f,0x02,0x05,0x0b,0x1e,0x3e,0x01,0x01,0x11,\r\n  0x1e,0x29,0x1f,0x27,0x02,0x1a,0x12,0x1f,0x19,0x22,0x22,0x1e,0x3e,\r\n  0x01,0x01,0x39,0x1e,0x27,0x13,0x13,0x13,0x1f,0x23,0x13,0x1f,0x13,\r\n  0x14,0x10,0x1e,0x0e,0x01,0x17,0x1e,0x03,0x1f,0x0c,0x13,0x13,0x1f,\r\n  0x0c,0x13,0x0b,0x0b,0x02,0x1e,0x39,0x01,0x11,0x1e,0x0d,0x05,0x1f,\r\n  0x02,0x0d,0x1e,0x04,0x20,0x01,0x01,0x01,0x01,0x00,0x1e,0x1e,0x1a,\r\n  0x29,0x0b,0x24,0x31,0x27,0x23,0x13,0x06,0x31,0x1e,0x17,0x01,0x01,\r\n  0x01,0x38,0x1e,0x19,0x1f,0x23,0x13,0x1a,0x1e,0x11,0x01,0x01,0x01,\r\n  0x01,0x00,0x1e,0x1e,0x02,0x23,0x27,0x13,0x24,0x1e,0x0c,0x13,0x13,\r\n  0x13,0x2a,0x1e,0x2f,0x01,0x01,0x1e,0x1e,0x0c,0x23,0x13,0x13,0x13,\r\n  0x13,0x13,0x13,0x13,0x1e,0x1e,0x01,0x01,0x01,0x08,0x1e,0x16,0x1f,\r\n  0x13,0x0c,0x14,0x18,0x1e,0x34,0x01,0x01,0x20,0x1e,0x1e,0x05,0x05,\r\n  0x0c,0x1f,0x1f,0x0c,0x13,0x0c,0x23,0x15,0x1e,0x3a,0x01,0x1e,0x1e,\r\n  0x14,0x1f,0x22,0x1f,0x1e,0x2d,0x14,0x05,0x0c,0x1a,0x1e,0x1d,0x01,\r\n  0x3c,0x1e,0x16,0x13,0x13,0x22,0x13,0x1e,0x1e,0x01,0x01,0x20,0x1e,\r\n  0x09,0x1f,0x13,0x13,0x13,0x25,0x1e,0x08,0x01,0x39,0x1e,0x02,0x1f,\r\n  0x23,0x13,0x0c,0x1f,0x13,0x05,0x14,0x1e,0x1e,0x08,0x01,0x01,0x01,\r\n  0x0f,0x1e,0x26,0x29,0x14,0x22,0x26,0x1e,0x04,0x01,0x3a,0x1e,0x26,\r\n  0x05,0x22,0x14,0x24,0x1e,0x1a,0x19,0x13,0x02,0x1e,0x19,0x05,0x22,\r\n  0x1f,0x0a,0x1e,0x3b,0x01,0x1e,0x1e,0x0c,0x05,0x05,0x0c,0x1e,0x31,\r\n  0x0c,0x13,0x0c,0x27,0x1e,0x32,0x01,0x01,0x37,0x1e,0x28,0x1f,0x14,\r\n  0x0c,0x14,0x27,0x0c,0x19,0x12,0x29,0x1e,0x3d,0x01,0x01,0x39,0x1e,\r\n  0x0d,0x13,0x13,0x13,0x14,0x1f,0x13,0x0c,0x13,0x0c,0x09,0x1e,0x20,\r\n  0x01,0x20,0x1e,0x09,0x14,0x13,0x05,0x0c,0x13,0x1f,0x13,0x13,0x0c,\r\n  0x27,0x1e,0x39,0x01,0x38,0x1e,0x27,0x1f,0x0c,0x13,0x1a,0x1e,0x39,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x23,0x14,0x22,0x29,0x14,\r\n  0x02,0x06,0x13,0x0b,0x1e,0x3e,0x00,0x01,0x01,0x01,0x11,0x1e,0x02,\r\n  0x0c,0x23,0x05,0x29,0x1e,0x1e,0x2c,0x01,0x01,0x01,0x01,0x1d,0x1e,\r\n  0x02,0x1f,0x13,0x23,0x06,0x1e,0x22,0x13,0x13,0x13,0x2a,0x1e,0x2f,\r\n  0x01,0x01,0x38,0x1e,0x18,0x0b,0x13,0x0b,0x13,0x13,0x1f,0x13,0x1e,\r\n  0x1e,0x38,0x01,0x01,0x01,0x08,0x1e,0x16,0x13,0x05,0x22,0x14,0x1e,\r\n  0x1e,0x00,0x01,0x01,0x01,0x38,0x1e,0x1e,0x19,0x14,0x23,0x0a,0x12,\r\n  0x05,0x0c,0x05,0x15,0x1e,0x3a,0x01,0x1e,0x1e,0x05,0x27,0x05,0x05,\r\n  0x1e,0x10,0x0c,0x0b,0x1f,0x23,0x1e,0x1d,0x01,0x3c,0x1e,0x16,0x13,\r\n  0x13,0x22,0x0c,0x1e,0x1e,0x01,0x01,0x20,0x1e,0x09,0x1f,0x13,0x13,\r\n  0x0c,0x25,0x1e,0x08,0x01,0x39,0x1e,0x02,0x13,0x13,0x0c,0x0d,0x02,\r\n  0x13,0x23,0x05,0x29,0x1e,0x38,0x01,0x01,0x01,0x0f,0x1e,0x26,0x02,\r\n  0x02,0x1f,0x0d,0x1e,0x04,0x01,0x04,0x1e,0x0d,0x0b,0x1f,0x0b,0x26,\r\n  0x1e,0x05,0x19,0x22,0x23,0x1e,0x13,0x05,0x0c,0x23,0x24,0x1e,0x1c,\r\n  0x01,0x1e,0x1e,0x0c,0x27,0x13,0x14,0x1e,0x0a,0x05,0x05,0x0c,0x14,\r\n  0x1e,0x1e,0x01,0x01,0x36,0x1e,0x1e,0x16,0x0b,0x05,0x14,0x22,0x1f,\r\n  0x05,0x06,0x1e,0x1e,0x3b,0x01,0x01,0x39,0x1e,0x0d,0x13,0x13,0x13,\r\n  0x27,0x27,0x13,0x13,0x13,0x03,0x1e,0x38,0x01,0x01,0x01,0x38,0x1e,\r\n  0x15,0x13,0x05,0x0c,0x26,0x19,0x13,0x0c,0x0c,0x02,0x1e,0x39,0x01,\r\n  0x1e,0x1e,0x23,0x13,0x05,0x05,0x05,0x1e,0x33,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x38,0x1e,0x31,0x23,0x14,0x19,0x05,0x22,0x22,0x05,0x18,\r\n  0x1e,0x04,0x01,0x01,0x01,0x01,0x1d,0x1e,0x23,0x0b,0x0b,0x0b,0x02,\r\n  0x06,0x09,0x1e,0x35,0x01,0x01,0x01,0x2c,0x1e,0x1a,0x0b,0x05,0x0c,\r\n  0x0b,0x22,0x1f,0x13,0x13,0x13,0x2a,0x1e,0x2f,0x01,0x01,0x2b,0x38,\r\n  0x1e,0x1e,0x1e,0x25,0x0a,0x2a,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,\r\n  0x01,0x08,0x1e,0x16,0x0c,0x13,0x13,0x14,0x1e,0x1e,0x00,0x01,0x01,\r\n  0x20,0x1e,0x09,0x1a,0x27,0x23,0x06,0x1e,0x0d,0x13,0x14,0x19,0x12,\r\n  0x1e,0x1c,0x01,0x1e,0x1e,0x1f,0x27,0x02,0x0c,0x1e,0x10,0x19,0x22,\r\n  0x13,0x29,0x1e,0x1d,0x01,0x3c,0x1e,0x16,0x13,0x13,0x1f,0x14,0x1e,\r\n  0x1e,0x01,0x01,0x20,0x1e,0x09,0x1f,0x22,0x13,0x0c,0x25,0x1e,0x08,\r\n  0x01,0x39,0x1e,0x02,0x1f,0x1f,0x13,0x25,0x16,0x0c,0x13,0x0c,0x0b,\r\n  0x2d,0x1e,0x2e,0x01,0x01,0x0f,0x1e,0x26,0x14,0x0c,0x0b,0x24,0x1e,\r\n  0x04,0x01,0x1b,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x3c,0x01,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,\r\n  0x01,0x36,0x07,0x1e,0x1e,0x03,0x16,0x16,0x03,0x1e,0x1e,0x1e,0x3b,\r\n  0x01,0x01,0x01,0x39,0x1e,0x15,0x13,0x13,0x13,0x27,0x1e,0x21,0x28,\r\n  0x18,0x1e,0x32,0x2b,0x01,0x01,0x01,0x36,0x1e,0x1e,0x18,0x28,0x31,\r\n  0x1e,0x27,0x0c,0x1f,0x0c,0x27,0x1e,0x39,0x01,0x38,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x39,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x1d,\r\n  0x1e,0x1e,0x09,0x16,0x25,0x16,0x18,0x1e,0x1e,0x11,0x34,0x01,0x01,\r\n  0x01,0x01,0x04,0x1e,0x0d,0x1f,0x0b,0x1f,0x13,0x05,0x31,0x1e,0x36,\r\n  0x01,0x01,0x01,0x1c,0x1e,0x24,0x14,0x13,0x1a,0x19,0x13,0x0b,0x13,\r\n  0x13,0x13,0x03,0x1e,0x2f,0x01,0x01,0x01,0x20,0x2c,0x40,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x3c,0x1e,0x16,\r\n  0x13,0x05,0x0c,0x14,0x1e,0x1e,0x00,0x01,0x01,0x35,0x1e,0x2d,0x05,\r\n  0x0c,0x1f,0x0c,0x14,0x23,0x0c,0x13,0x14,0x31,0x1e,0x3c,0x01,0x1e,\r\n  0x1e,0x1f,0x14,0x0c,0x14,0x1e,0x10,0x19,0x12,0x13,0x19,0x1e,0x1d,\r\n  0x01,0x3c,0x1e,0x16,0x13,0x13,0x14,0x1f,0x1e,0x1e,0x01,0x01,0x20,\r\n  0x1e,0x09,0x05,0x13,0x13,0x05,0x25,0x1e,0x08,0x01,0x38,0x1e,0x27,\r\n  0x1f,0x13,0x0b,0x28,0x1e,0x05,0x05,0x0c,0x1f,0x0d,0x1e,0x1e,0x3c,\r\n  0x01,0x3a,0x1e,0x26,0x0b,0x22,0x0b,0x12,0x1e,0x04,0x01,0x01,0x1b,\r\n  0x38,0x1e,0x1e,0x1e,0x38,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x38,0x3c,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,\r\n  0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x2b,0x38,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2f,0x01,0x01,0x01,0x01,0x39,\r\n  0x1e,0x27,0x1f,0x23,0x13,0x02,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,\r\n  0x01,0x01,0x01,0x01,0x36,0x38,0x1e,0x1e,0x1e,0x1e,0x19,0x1f,0x19,\r\n  0x0c,0x27,0x1e,0x39,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x33,0x39,\r\n  0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x11,0x0e,0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,\r\n  0x2a,0x23,0x13,0x19,0x05,0x0c,0x16,0x1e,0x08,0x01,0x01,0x01,0x08,\r\n  0x1e,0x1e,0x24,0x13,0x05,0x23,0x2a,0x22,0x13,0x13,0x13,0x28,0x1e,\r\n  0x2e,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x08,0x3b,0x3c,0x34,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x3a,0x1e,0x15,0x13,0x05,0x0c,0x1f,\r\n  0x09,0x1e,0x20,0x01,0x01,0x01,0x33,0x1e,0x23,0x0c,0x13,0x0c,0x05,\r\n  0x19,0x14,0x1f,0x0b,0x1e,0x32,0x01,0x01,0x1e,0x1e,0x1f,0x0b,0x05,\r\n  0x14,0x1e,0x2a,0x05,0x0c,0x1f,0x0b,0x1e,0x1e,0x01,0x3a,0x1e,0x26,\r\n  0x13,0x13,0x13,0x22,0x1e,0x1e,0x01,0x01,0x35,0x1e,0x09,0x05,0x23,\r\n  0x13,0x1f,0x25,0x1e,0x08,0x01,0x1e,0x1e,0x13,0x05,0x13,0x13,0x23,\r\n  0x1e,0x02,0x13,0x14,0x23,0x13,0x24,0x1e,0x37,0x01,0x04,0x1e,0x24,\r\n  0x23,0x14,0x0d,0x27,0x1e,0x07,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x17,0x08,0x08,\r\n  0x17,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1d,0x1e,0x19,0x05,0x14,\r\n  0x13,0x22,0x1e,0x3e,0x2e,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x2b,0x1b,0x33,0x1e,0x1a,0x0c,0x0c,0x13,0x0b,0x1e,0x1d,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x3b,0x3b,0x08,0x20,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x3e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x07,0x20,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x03,\r\n  0x0a,0x09,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x2b,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x17,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,\r\n  0x01,0x01,0x11,0x1e,0x1e,0x12,0x05,0x0c,0x14,0x23,0x05,0x03,0x1e,\r\n  0x1e,0x30,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x17,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x01,0x20,0x40,0x1e,0x1e,0x05,0x1f,0x13,0x13,0x25,0x1e,\r\n  0x08,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x3c,0x01,0x2e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x04,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x30,0x1e,0x0a,0x29,0x12,0x29,0x28,0x1e,0x3d,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x39,0x1e,0x15,0x12,0x24,0x29,0x0a,0x1e,0x30,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,\r\n  0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x1e,\r\n  0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x17,\r\n  0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x0e,0x11,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x32,0x30,0x01,0x01,0x01,\r\n  0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x38,0x1e,0x1e,0x1e,0x1e,0x38,\r\n  0x2b,0x01,0x01,0x17,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x2e,\r\n  0x1e,0x25,0x05,0x13,0x0b,0x0c,0x0b,0x25,0x1e,0x1b,0x01,0x2b,0x38,\r\n  0x1e,0x1e,0x1e,0x1e,0x32,0x30,0x1d,0x1e,0x1e,0x1e,0x1e,0x38,0x3c,\r\n  0x01,0x01,0x01,0x2e,0x38,0x1e,0x1e,0x1e,0x07,0x04,0x20,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x0e,0x33,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x0e,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x36,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x33,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x00,0x17,0x1b,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x08,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x33,0x11,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3d,0x1e,0x0d,0x05,0x13,\r\n  0x0c,0x1f,0x22,0x09,0x1e,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x2e,0x04,\r\n  0x1c,0x3d,0x2e,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x36,0x1b,0x30,0x1c,0x30,0x3b,0x0e,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x0f,0x1e,0x06,0x13,0x14,0x27,0x0c,0x16,0x1e,\r\n  0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x17,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x40,0x2b,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x17,0x38,0x1e,\r\n  0x33,0x07,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x2e,0x3b,0x2e,0x08,\r\n  0x35,0x08,0x2e,0x3b,0x2e,0x0e,0x01,0x01,0x01,0x01,0x20,0x08,0x2e,\r\n  0x3b,0x3b,0x0e,0x01,0x36,0x3a,0x08,0x3b,0x1b,0x2b,0x01,0x01,0x01,\r\n  0x01,0x35,0x08,0x2e,0x1b,0x2f,0x00,0x17,0x3b,0x3b,0x3b,0x3b,0x08,\r\n  0x35,0x2f,0x1b,0x3b,0x1b,0x2b,0x01,0x01,0x01,0x01,0x01,0x2b,0x2e,\r\n  0x3b,0x1b,0x17,0x00,0x17,0x2e,0x08,0x2e,0x3c,0x34,0x01,0x01,0x01,\r\n  0x01,0x0e,0x3b,0x3b,0x08,0x3a,0x36,0x0e,0x3b,0x3b,0x08,0x3a,0x17,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x36,0x1b,0x08,0x3b,0x3b,0x3b,0x08,\r\n  0x3a,0x17,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x37,0x11,\r\n  0x1d,0x32,0x1d,0x30,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x35,0x3b,0x30,0x0f,0x37,0x37,0x2f,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x00,0x0f,0x11,0x32,0x1d,0x32,0x30,0x3c,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x20,0x3a,0x2c,0x32,0x1d,0x1d,0x3d,0x3b,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x36,0x3a,0x37,0x0f,\r\n  0x0f,0x1c,0x3b,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x1b,0x37,\r\n  0x0f,0x0f,0x0f,0x0f,0x0f,0x1c,0x1b,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x20,0x3c,0x1c,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,\r\n  0x1c,0x0f,0x2f,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x08,0x30,0x32,\r\n  0x1d,0x32,0x1d,0x1c,0x17,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x11,0x1e,0x1e,0x1e,0x1e,0x1e,0x40,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x11,0x01,0x01,0x2b,0x07,0x1e,0x1e,0x1e,0x1e,0x1e,0x39,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x2b,0x01,0x01,0x04,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x32,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x40,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x04,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x32,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x3e,0x34,0x01,0x01,0x39,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x33,0x1e,0x1e,0x1e,0x1e,0x1e,0x1d,0x01,0x01,0x01,\r\n  0x00,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x11,0x01,\r\n  0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x39,0x01,0x01,0x01,0x01,0x37,0x32,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x08,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x04,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x33,\r\n  0x0e,0x01,0x01,0x01,0x01,0x30,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x3d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x17,\r\n  0x1c,0x1d,0x1e,0x1e,0x3e,0x38,0x1c,0x0e,0x01,0x01,0x01,0x01,0x35,\r\n  0x07,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x04,\r\n  0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,\r\n  0x10,0x0a,0x0a,0x28,0x16,0x1e,0x25,0x28,0x0a,0x28,0x10,0x1e,0x2e,\r\n  0x01,0x38,0x1e,0x16,0x25,0x0a,0x0a,0x10,0x1e,0x10,0x15,0x25,0x0a,\r\n  0x28,0x1e,0x38,0x01,0x20,0x1e,0x09,0x25,0x0a,0x28,0x2a,0x1e,0x03,\r\n  0x16,0x16,0x25,0x25,0x16,0x1e,0x2a,0x28,0x25,0x28,0x09,0x1e,0x20,\r\n  0x01,0x2b,0x1e,0x21,0x28,0x25,0x15,0x03,0x1e,0x03,0x25,0x25,0x0a,\r\n  0x03,0x1e,0x3c,0x01,0x35,0x1e,0x2d,0x0a,0x0a,0x25,0x26,0x1e,0x1e,\r\n  0x0a,0x0a,0x25,0x26,0x31,0x1e,0x0f,0x01,0x01,0x3d,0x1e,0x21,0x15,\r\n  0x25,0x25,0x25,0x0a,0x16,0x15,0x10,0x1e,0x3b,0x01,0x01,0x01,0x01,\r\n  0x38,0x1e,0x1e,0x0a,0x19,0x0b,0x22,0x0b,0x28,0x1e,0x1e,0x38,0x20,\r\n  0x01,0x01,0x20,0x07,0x1e,0x18,0x25,0x12,0x06,0x06,0x26,0x2d,0x1e,\r\n  0x35,0x01,0x01,0x37,0x1e,0x1e,0x03,0x02,0x22,0x23,0x22,0x24,0x21,\r\n  0x1e,0x1e,0x2b,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x25,0x27,0x22,\r\n  0x23,0x0b,0x0d,0x21,0x1e,0x1e,0x08,0x01,0x01,0x01,0x01,0x01,0x17,\r\n  0x1e,0x18,0x26,0x24,0x06,0x06,0x24,0x25,0x1e,0x11,0x01,0x01,0x01,\r\n  0x00,0x1e,0x1e,0x28,0x24,0x26,0x26,0x06,0x06,0x06,0x24,0x28,0x1e,\r\n  0x1e,0x00,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x33,0x30,0x01,0x01,0x01,0x39,0x1e,0x16,0x24,0x06,\r\n  0x26,0x06,0x06,0x06,0x06,0x24,0x06,0x09,0x1e,0x20,0x01,0x01,0x34,\r\n  0x3e,0x1e,0x10,0x24,0x19,0x0b,0x22,0x23,0x06,0x1e,0x1e,0x38,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x04,0x1e,0x0d,0x1f,0x19,0x05,\r\n  0x02,0x1e,0x14,0x13,0x13,0x05,0x0d,0x1e,0x04,0x01,0x1e,0x1e,0x13,\r\n  0x0c,0x13,0x0c,0x23,0x1e,0x24,0x0c,0x0c,0x22,0x13,0x1e,0x1e,0x01,\r\n  0x36,0x1e,0x31,0x13,0x27,0x0b,0x0c,0x18,0x05,0x22,0x22,0x22,0x23,\r\n  0x14,0x1e,0x27,0x22,0x29,0x24,0x03,0x1e,0x2f,0x01,0x3b,0x1e,0x0a,\r\n  0x27,0x0b,0x0c,0x19,0x1e,0x05,0x14,0x14,0x0b,0x0a,0x1e,0x3b,0x01,\r\n  0x3c,0x1e,0x16,0x13,0x05,0x05,0x13,0x2a,0x1e,0x13,0x13,0x13,0x13,\r\n  0x19,0x1e,0x11,0x01,0x01,0x32,0x1e,0x0b,0x22,0x13,0x0c,0x0c,0x0c,\r\n  0x1f,0x13,0x29,0x1e,0x3d,0x01,0x01,0x01,0x0f,0x1e,0x2d,0x0c,0x23,\r\n  0x14,0x13,0x13,0x13,0x13,0x13,0x18,0x1e,0x2c,0x01,0x01,0x3b,0x1e,\r\n  0x16,0x1f,0x0c,0x05,0x0c,0x0c,0x13,0x25,0x1e,0x08,0x01,0x0e,0x33,\r\n  0x1e,0x27,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x28,0x1e,0x32,0x00,\r\n  0x01,0x01,0x38,0x1e,0x1e,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,\r\n  0x29,0x1e,0x1d,0x01,0x01,0x01,0x01,0x01,0x04,0x1e,0x06,0x13,0x13,\r\n  0x0c,0x0c,0x0c,0x1f,0x1e,0x33,0x01,0x01,0x01,0x34,0x1e,0x18,0x13,\r\n  0x1f,0x14,0x13,0x14,0x14,0x13,0x05,0x02,0x2d,0x1e,0x0e,0x01,0x01,\r\n  0x01,0x01,0x38,0x1e,0x1e,0x06,0x0b,0x13,0x13,0x14,0x23,0x0a,0x1e,\r\n  0x1e,0x30,0x01,0x01,0x40,0x1e,0x05,0x0c,0x0c,0x13,0x13,0x14,0x0c,\r\n  0x13,0x0b,0x1f,0x16,0x1e,0x3c,0x01,0x01,0x04,0x1e,0x2a,0x13,0x05,\r\n  0x02,0x14,0x13,0x0c,0x23,0x14,0x1e,0x1e,0x3c,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x3a,0x1e,0x28,0x1f,0x05,0x22,0x23,0x1e,0x14,0x27,\r\n  0x0c,0x0b,0x25,0x1e,0x3a,0x01,0x38,0x1e,0x29,0x0c,0x13,0x1f,0x19,\r\n  0x1e,0x27,0x0c,0x0c,0x13,0x26,0x1e,0x38,0x01,0x01,0x38,0x1e,0x19,\r\n  0x1f,0x0c,0x19,0x03,0x23,0x06,0x0d,0x1f,0x1a,0x02,0x2d,0x19,0x0b,\r\n  0x0b,0x22,0x18,0x1e,0x34,0x01,0x0e,0x33,0x1e,0x24,0x05,0x05,0x22,\r\n  0x1a,0x24,0x0d,0x0c,0x0d,0x1e,0x33,0x0e,0x01,0x34,0x3e,0x1e,0x19,\r\n  0x0b,0x26,0x22,0x2a,0x1e,0x1f,0x1f,0x13,0x13,0x2d,0x1e,0x0f,0x01,\r\n  0x01,0x3d,0x1e,0x06,0x13,0x02,0x02,0x0c,0x05,0x02,0x0c,0x26,0x1e,\r\n  0x0f,0x01,0x01,0x01,0x11,0x1e,0x29,0x1f,0x19,0x12,0x22,0x14,0x13,\r\n  0x0b,0x14,0x05,0x1e,0x40,0x01,0x01,0x30,0x1e,0x29,0x13,0x22,0x1f,\r\n  0x13,0x02,0x14,0x03,0x1e,0x17,0x01,0x3b,0x1e,0x25,0x12,0x14,0x13,\r\n  0x13,0x27,0x14,0x13,0x13,0x13,0x2a,0x1e,0x3b,0x01,0x01,0x1e,0x1e,\r\n  0x13,0x13,0x13,0x13,0x13,0x0b,0x13,0x13,0x13,0x13,0x31,0x1e,0x36,\r\n  0x01,0x01,0x01,0x00,0x1e,0x1e,0x14,0x13,0x1f,0x19,0x13,0x0c,0x27,\r\n  0x1e,0x38,0x01,0x01,0x01,0x00,0x1e,0x1e,0x23,0x0c,0x14,0x0c,0x14,\r\n  0x22,0x0b,0x23,0x0b,0x18,0x1e,0x20,0x01,0x01,0x01,0x1b,0x1e,0x18,\r\n  0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0b,0x1e,0x1d,0x01,0x01,\r\n  0x39,0x1e,0x24,0x13,0x1f,0x0b,0x1f,0x0c,0x0c,0x13,0x0c,0x1f,0x09,\r\n  0x1e,0x20,0x01,0x01,0x07,0x1e,0x14,0x1f,0x23,0x13,0x02,0x27,0x1f,\r\n  0x19,0x12,0x24,0x1e,0x11,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3a,\r\n  0x1e,0x15,0x0d,0x1a,0x0c,0x27,0x1e,0x13,0x05,0x0c,0x05,0x15,0x1e,\r\n  0x3a,0x01,0x3b,0x1e,0x31,0x1f,0x05,0x05,0x23,0x1e,0x22,0x13,0x05,\r\n  0x0c,0x18,0x1e,0x2f,0x01,0x01,0x1c,0x1e,0x06,0x02,0x1f,0x19,0x16,\r\n  0x27,0x22,0x1a,0x23,0x14,0x0b,0x16,0x0d,0x14,0x1a,0x29,0x1e,0x11,\r\n  0x01,0x01,0x01,0x08,0x1e,0x09,0x26,0x14,0x22,0x0b,0x22,0x23,0x22,\r\n  0x1e,0x1e,0x3d,0x01,0x01,0x01,0x37,0x1e,0x25,0x05,0x1f,0x0c,0x28,\r\n  0x25,0x14,0x06,0x0b,0x0b,0x1e,0x32,0x01,0x01,0x01,0x2f,0x1e,0x18,\r\n  0x09,0x10,0x05,0x0c,0x13,0x13,0x22,0x09,0x1e,0x17,0x01,0x01,0x34,\r\n  0x1e,0x18,0x23,0x14,0x0b,0x0c,0x21,0x09,0x05,0x02,0x24,0x22,0x09,\r\n  0x1e,0x20,0x01,0x3b,0x1e,0x18,0x10,0x31,0x0c,0x0c,0x1f,0x13,0x03,\r\n  0x1e,0x17,0x01,0x37,0x1e,0x06,0x0c,0x1f,0x19,0x24,0x1e,0x24,0x14,\r\n  0x13,0x13,0x12,0x1e,0x30,0x01,0x01,0x38,0x1e,0x23,0x22,0x0b,0x23,\r\n  0x2d,0x1e,0x13,0x13,0x13,0x13,0x2a,0x1e,0x2f,0x01,0x01,0x01,0x2e,\r\n  0x1e,0x31,0x13,0x13,0x0b,0x05,0x13,0x0c,0x23,0x1e,0x38,0x01,0x01,\r\n  0x01,0x00,0x1e,0x1e,0x14,0x0c,0x1f,0x24,0x1e,0x03,0x2a,0x21,0x1e,\r\n  0x1e,0x04,0x01,0x01,0x01,0x01,0x2c,0x1e,0x0d,0x13,0x13,0x13,0x05,\r\n  0x05,0x13,0x13,0x13,0x13,0x31,0x1e,0x08,0x01,0x3b,0x1e,0x09,0x21,\r\n  0x21,0x1e,0x0a,0x0b,0x0c,0x0c,0x22,0x1a,0x1e,0x39,0x01,0x01,0x0e,\r\n  0x1e,0x10,0x0b,0x0c,0x19,0x14,0x1e,0x2a,0x14,0x0b,0x0c,0x05,0x1e,\r\n  0x1e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3a,0x1e,0x15,0x0c,0x14,\r\n  0x14,0x14,0x1e,0x02,0x0d,0x05,0x0b,0x28,0x1e,0x3a,0x01,0x01,0x33,\r\n  0x1e,0x14,0x1f,0x22,0x0b,0x21,0x05,0x05,0x05,0x13,0x1e,0x1e,0x01,\r\n  0x01,0x01,0x3b,0x1e,0x0a,0x13,0x05,0x1a,0x12,0x12,0x26,0x24,0x02,\r\n  0x22,0x0b,0x0a,0x19,0x23,0x14,0x0a,0x1e,0x3a,0x01,0x01,0x01,0x01,\r\n  0x38,0x1e,0x16,0x1a,0x1a,0x27,0x26,0x27,0x28,0x1e,0x38,0x00,0x01,\r\n  0x01,0x01,0x35,0x1e,0x18,0x23,0x02,0x13,0x24,0x06,0x14,0x1f,0x0c,\r\n  0x15,0x1e,0x30,0x01,0x01,0x01,0x01,0x04,0x1e,0x1e,0x0d,0x0c,0x13,\r\n  0x1f,0x1f,0x2a,0x1e,0x39,0x01,0x01,0x01,0x0e,0x1e,0x10,0x0d,0x0c,\r\n  0x02,0x19,0x1e,0x1e,0x22,0x0b,0x1f,0x14,0x10,0x1e,0x0e,0x01,0x01,\r\n  0x04,0x1e,0x1e,0x1e,0x0c,0x05,0x02,0x0c,0x03,0x1e,0x17,0x01,0x3c,\r\n  0x1e,0x2d,0x25,0x03,0x2d,0x1e,0x31,0x1f,0x14,0x27,0x0c,0x12,0x1e,\r\n  0x3d,0x01,0x00,0x1e,0x1e,0x1e,0x1e,0x1e,0x18,0x1e,0x2a,0x0c,0x13,\r\n  0x13,0x13,0x31,0x1e,0x36,0x01,0x01,0x01,0x38,0x1e,0x1a,0x13,0x13,\r\n  0x16,0x14,0x13,0x1f,0x19,0x1e,0x38,0x01,0x01,0x01,0x00,0x1e,0x1e,\r\n  0x14,0x13,0x1f,0x27,0x29,0x23,0x23,0x02,0x10,0x1e,0x32,0x01,0x01,\r\n  0x01,0x01,0x1d,0x1e,0x06,0x14,0x13,0x13,0x06,0x1e,0x24,0x19,0x23,\r\n  0x13,0x29,0x1e,0x30,0x01,0x01,0x2c,0x1e,0x1e,0x1e,0x1e,0x0d,0x1f,\r\n  0x0c,0x0c,0x13,0x2d,0x1e,0x1b,0x01,0x01,0x01,0x3e,0x1e,0x14,0x05,\r\n  0x22,0x1f,0x21,0x28,0x0c,0x02,0x19,0x29,0x1e,0x11,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x3a,0x1e,0x15,0x29,0x14,0x1f,0x0b,0x1e,0x14,\r\n  0x14,0x14,0x05,0x26,0x1e,0x3a,0x01,0x01,0x1d,0x1e,0x19,0x0c,0x13,\r\n  0x23,0x0a,0x1f,0x1f,0x1a,0x02,0x1e,0x38,0x01,0x01,0x01,0x2b,0x1e,\r\n  0x21,0x14,0x1f,0x27,0x06,0x22,0x1f,0x02,0x06,0x0b,0x0d,0x26,0x0b,\r\n  0x02,0x0b,0x31,0x1e,0x36,0x01,0x01,0x01,0x01,0x2c,0x1e,0x03,0x23,\r\n  0x02,0x23,0x05,0x14,0x31,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x11,\r\n  0x1e,0x1a,0x0c,0x19,0x26,0x23,0x23,0x1a,0x05,0x1e,0x1e,0x2f,0x01,\r\n  0x01,0x01,0x01,0x38,0x1e,0x2a,0x0c,0x1f,0x13,0x05,0x29,0x1e,0x32,\r\n  0x35,0x01,0x01,0x01,0x36,0x1e,0x31,0x23,0x22,0x14,0x1f,0x1e,0x18,\r\n  0x0c,0x27,0x27,0x0c,0x2d,0x1e,0x35,0x01,0x01,0x01,0x20,0x1e,0x09,\r\n  0x1f,0x13,0x13,0x05,0x03,0x1e,0x17,0x01,0x01,0x39,0x1e,0x1e,0x1e,\r\n  0x10,0x02,0x27,0x0b,0x13,0x05,0x0c,0x0a,0x1e,0x2e,0x01,0x01,0x30,\r\n  0x1e,0x38,0x32,0x1e,0x19,0x13,0x13,0x13,0x13,0x05,0x2a,0x1e,0x1d,\r\n  0x01,0x01,0x01,0x17,0x1e,0x10,0x13,0x14,0x29,0x2d,0x0c,0x05,0x05,\r\n  0x23,0x1e,0x38,0x35,0x01,0x01,0x34,0x1e,0x18,0x14,0x23,0x0c,0x14,\r\n  0x02,0x0c,0x0c,0x22,0x0b,0x03,0x1e,0x1b,0x01,0x01,0x01,0x3e,0x1e,\r\n  0x0b,0x14,0x27,0x0c,0x12,0x18,0x06,0x27,0x06,0x1e,0x18,0x1e,0x08,\r\n  0x01,0x01,0x01,0x35,0x2e,0x1e,0x09,0x05,0x13,0x13,0x05,0x27,0x1e,\r\n  0x11,0x01,0x01,0x01,0x01,0x04,0x1e,0x09,0x14,0x22,0x0b,0x14,0x23,\r\n  0x22,0x14,0x27,0x1e,0x1e,0x3b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x3a,0x1e,0x15,0x1f,0x05,0x27,0x05,0x1e,0x29,0x22,0x0c,0x0b,0x15,\r\n  0x1e,0x3a,0x01,0x01,0x30,0x1e,0x25,0x1f,0x1f,0x0c,0x19,0x1f,0x13,\r\n  0x0c,0x03,0x1e,0x0f,0x01,0x01,0x01,0x34,0x1e,0x18,0x14,0x05,0x14,\r\n  0x22,0x0d,0x27,0x26,0x12,0x27,0x22,0x0d,0x14,0x27,0x22,0x10,0x1e,\r\n  0x0e,0x01,0x01,0x01,0x17,0x1e,0x1e,0x14,0x02,0x0d,0x27,0x29,0x05,\r\n  0x02,0x1e,0x1e,0x1b,0x01,0x01,0x01,0x01,0x3a,0x1e,0x16,0x1f,0x0c,\r\n  0x19,0x22,0x05,0x1f,0x0d,0x1e,0x38,0x01,0x01,0x01,0x01,0x2e,0x1e,\r\n  0x1e,0x0c,0x23,0x05,0x13,0x27,0x1e,0x1e,0x1e,0x38,0x01,0x01,0x01,\r\n  0x36,0x1e,0x21,0x27,0x14,0x22,0x05,0x1e,0x1e,0x14,0x14,0x1f,0x27,\r\n  0x2d,0x1e,0x35,0x01,0x01,0x01,0x20,0x1e,0x09,0x0c,0x1f,0x1f,0x13,\r\n  0x03,0x1e,0x17,0x01,0x01,0x30,0x1e,0x1e,0x0b,0x14,0x14,0x14,0x0c,\r\n  0x02,0x0d,0x24,0x1e,0x33,0x0e,0x01,0x01,0x01,0x17,0x0f,0x1e,0x1e,\r\n  0x13,0x13,0x13,0x13,0x13,0x0c,0x03,0x1e,0x38,0x01,0x01,0x01,0x38,\r\n  0x1e,0x06,0x13,0x13,0x1e,0x1e,0x1f,0x1f,0x22,0x1a,0x1e,0x1e,0x40,\r\n  0x35,0x01,0x34,0x1e,0x18,0x0c,0x05,0x1f,0x02,0x1e,0x22,0x27,0x05,\r\n  0x0b,0x15,0x1e,0x2c,0x01,0x01,0x00,0x1e,0x1e,0x19,0x13,0x05,0x0c,\r\n  0x05,0x1f,0x0c,0x19,0x0b,0x15,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,\r\n  0x38,0x1e,0x0d,0x1f,0x0c,0x05,0x05,0x31,0x1e,0x0f,0x01,0x01,0x01,\r\n  0x01,0x38,0x1e,0x21,0x27,0x05,0x0b,0x06,0x27,0x14,0x22,0x23,0x1e,\r\n  0x1e,0x11,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x37,0x1e,0x15,0x02,\r\n  0x1f,0x27,0x02,0x05,0x05,0x1f,0x19,0x22,0x26,0x1e,0x3a,0x01,0x01,\r\n  0x35,0x1e,0x1e,0x0c,0x13,0x0b,0x19,0x22,0x1f,0x14,0x18,0x1e,0x34,\r\n  0x01,0x01,0x01,0x01,0x39,0x1e,0x1a,0x14,0x22,0x1f,0x19,0x0b,0x26,\r\n  0x0a,0x23,0x1a,0x27,0x14,0x0d,0x0d,0x1e,0x1e,0x00,0x01,0x01,0x2b,\r\n  0x38,0x1e,0x28,0x14,0x0b,0x19,0x27,0x23,0x05,0x14,0x1a,0x1e,0x38,\r\n  0x2b,0x01,0x01,0x01,0x35,0x1e,0x18,0x0b,0x1a,0x1a,0x0c,0x23,0x22,\r\n  0x0a,0x1e,0x37,0x01,0x01,0x01,0x01,0x04,0x1e,0x29,0x13,0x0b,0x1f,\r\n  0x1f,0x06,0x2d,0x16,0x31,0x1e,0x0f,0x01,0x01,0x36,0x1e,0x21,0x14,\r\n  0x29,0x14,0x22,0x1e,0x18,0x1f,0x23,0x14,0x1f,0x2d,0x1e,0x35,0x01,\r\n  0x01,0x01,0x20,0x1e,0x09,0x1f,0x05,0x13,0x1f,0x03,0x1e,0x17,0x01,\r\n  0x01,0x32,0x1e,0x02,0x29,0x14,0x1f,0x22,0x14,0x12,0x31,0x1e,0x1e,\r\n  0x3c,0x01,0x01,0x01,0x2c,0x1e,0x1e,0x1e,0x1e,0x1e,0x16,0x1a,0x13,\r\n  0x13,0x22,0x13,0x21,0x1e,0x3c,0x01,0x00,0x1e,0x1e,0x13,0x1f,0x1f,\r\n  0x27,0x02,0x0c,0x0c,0x13,0x1f,0x29,0x25,0x1e,0x2e,0x01,0x17,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x12,0x23,0x22,0x1f,0x0b,0x1e,0x1e,\r\n  0x00,0x01,0x01,0x07,0x1e,0x14,0x02,0x0d,0x05,0x19,0x29,0x13,0x05,\r\n  0x0b,0x14,0x18,0x1e,0x17,0x01,0x01,0x01,0x36,0x1e,0x18,0x0c,0x19,\r\n  0x0c,0x1f,0x23,0x1e,0x33,0x01,0x01,0x01,0x01,0x20,0x1e,0x09,0x13,\r\n  0x23,0x22,0x1f,0x03,0x15,0x29,0x14,0x22,0x29,0x1e,0x1e,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x3b,0x1e,0x25,0x22,0x1f,0x22,0x0c,0x14,\r\n  0x27,0x0c,0x19,0x12,0x26,0x1e,0x3a,0x01,0x01,0x01,0x1e,0x1e,0x05,\r\n  0x13,0x13,0x22,0x1f,0x1f,0x0b,0x1e,0x32,0x01,0x01,0x01,0x01,0x01,\r\n  0x3a,0x1e,0x28,0x1a,0x0b,0x0b,0x12,0x02,0x0a,0x0a,0x22,0x23,0x22,\r\n  0x14,0x14,0x06,0x1e,0x30,0x01,0x01,0x01,0x38,0x1e,0x1e,0x22,0x19,\r\n  0x24,0x0d,0x03,0x12,0x1f,0x0b,0x22,0x1e,0x1e,0x38,0x01,0x01,0x01,\r\n  0x01,0x39,0x1e,0x12,0x05,0x22,0x14,0x23,0x14,0x1e,0x1e,0x0e,0x01,\r\n  0x01,0x01,0x01,0x07,0x1e,0x14,0x0b,0x02,0x13,0x05,0x0b,0x1f,0x19,\r\n  0x27,0x1e,0x39,0x01,0x01,0x35,0x1e,0x2d,0x05,0x02,0x02,0x1f,0x1e,\r\n  0x1e,0x1a,0x22,0x05,0x24,0x2d,0x1e,0x35,0x01,0x01,0x01,0x20,0x1e,\r\n  0x09,0x0b,0x23,0x05,0x0c,0x03,0x1e,0x17,0x01,0x36,0x1e,0x21,0x1f,\r\n  0x1f,0x05,0x15,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x32,0x00,0x01,0x20,\r\n  0x1e,0x09,0x26,0x26,0x06,0x26,0x1e,0x1e,0x0b,0x13,0x0c,0x13,0x12,\r\n  0x1e,0x1c,0x01,0x34,0x1e,0x18,0x0c,0x1f,0x13,0x05,0x22,0x0c,0x1f,\r\n  0x1f,0x13,0x1f,0x0d,0x1e,0x04,0x01,0x0f,0x1e,0x26,0x02,0x0d,0x19,\r\n  0x1e,0x1e,0x06,0x05,0x13,0x19,0x0d,0x1e,0x1e,0x00,0x01,0x00,0x1e,\r\n  0x1e,0x14,0x0c,0x14,0x14,0x06,0x1e,0x27,0x12,0x14,0x23,0x15,0x1e,\r\n  0x0f,0x01,0x01,0x01,0x04,0x1e,0x28,0x13,0x1f,0x13,0x13,0x28,0x1e,\r\n  0x11,0x01,0x01,0x01,0x01,0x08,0x1e,0x25,0x0c,0x05,0x13,0x27,0x1e,\r\n  0x1e,0x02,0x02,0x1f,0x1f,0x1e,0x1e,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x35,0x40,0x1e,0x0d,0x1f,0x19,0x05,0x27,0x22,0x1f,0x14,0x1f,\r\n  0x0d,0x1e,0x2c,0x01,0x01,0x01,0x11,0x1e,0x1a,0x13,0x0c,0x0c,0x22,\r\n  0x05,0x26,0x1e,0x30,0x01,0x01,0x01,0x01,0x01,0x3b,0x1e,0x25,0x19,\r\n  0x05,0x14,0x1f,0x0b,0x16,0x21,0x22,0x29,0x19,0x22,0x23,0x06,0x1e,\r\n  0x37,0x01,0x01,0x01,0x1e,0x1e,0x02,0x06,0x14,0x0b,0x1a,0x1e,0x02,\r\n  0x02,0x23,0x14,0x0d,0x1e,0x1e,0x01,0x01,0x01,0x01,0x2e,0x1e,0x2a,\r\n  0x23,0x02,0x0b,0x26,0x27,0x1e,0x32,0x01,0x01,0x01,0x01,0x00,0x1e,\r\n  0x1e,0x13,0x13,0x22,0x13,0x14,0x0c,0x23,0x27,0x1f,0x1e,0x1e,0x00,\r\n  0x01,0x34,0x1e,0x18,0x0b,0x14,0x0c,0x0b,0x24,0x06,0x1a,0x1a,0x1f,\r\n  0x05,0x1e,0x1e,0x34,0x01,0x01,0x01,0x20,0x1e,0x09,0x05,0x13,0x0c,\r\n  0x0b,0x03,0x1e,0x17,0x01,0x1b,0x1e,0x15,0x27,0x02,0x1f,0x0d,0x29,\r\n  0x0b,0x23,0x22,0x02,0x03,0x1e,0x17,0x01,0x20,0x1e,0x09,0x05,0x1f,\r\n  0x13,0x13,0x12,0x10,0x14,0x13,0x1f,0x13,0x06,0x1e,0x37,0x01,0x34,\r\n  0x1e,0x1e,0x0c,0x1f,0x0c,0x13,0x13,0x0c,0x0c,0x13,0x0b,0x0b,0x24,\r\n  0x1e,0x37,0x01,0x11,0x1e,0x02,0x0b,0x05,0x1f,0x02,0x10,0x1f,0x22,\r\n  0x0c,0x23,0x29,0x1e,0x2c,0x01,0x01,0x01,0x3e,0x1e,0x23,0x29,0x22,\r\n  0x0c,0x0a,0x1e,0x23,0x0b,0x22,0x1f,0x24,0x1e,0x37,0x01,0x01,0x2b,\r\n  0x3e,0x1e,0x0b,0x0b,0x27,0x13,0x1f,0x1e,0x1e,0x2b,0x01,0x01,0x01,\r\n  0x01,0x08,0x1e,0x25,0x1f,0x22,0x0c,0x23,0x25,0x24,0x14,0x0c,0x0b,\r\n  0x02,0x1e,0x1e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x37,0x1e,\r\n  0x1e,0x2d,0x25,0x21,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1b,0x01,\r\n  0x01,0x01,0x3a,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x17,\r\n  0x01,0x01,0x01,0x01,0x01,0x35,0x33,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x3c,0x01,0x01,0x01,\r\n  0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x01,0x01,0x01,0x3d,0x1e,0x1e,0x1e,0x27,0x0b,0x1f,0x0c,\r\n  0x21,0x1e,0x30,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x39,0x01,0x01,0x01,0x04,0x1e,\r\n  0x12,0x0b,0x22,0x0b,0x22,0x05,0x23,0x14,0x22,0x06,0x1e,0x38,0x01,\r\n  0x01,0x01,0x01,0x20,0x1e,0x18,0x02,0x05,0x0c,0x1f,0x31,0x1e,0x17,\r\n  0x01,0x3a,0x1e,0x15,0x0b,0x22,0x1f,0x22,0x0c,0x14,0x27,0x0c,0x19,\r\n  0x2a,0x1e,0x08,0x01,0x01,0x1e,0x1e,0x13,0x0b,0x13,0x13,0x13,0x14,\r\n  0x1f,0x13,0x0c,0x13,0x03,0x1e,0x3c,0x01,0x01,0x38,0x1e,0x18,0x1e,\r\n  0x1e,0x1e,0x21,0x13,0x1f,0x13,0x19,0x1e,0x1e,0x1e,0x2f,0x01,0x0f,\r\n  0x1e,0x16,0x1f,0x1f,0x0c,0x13,0x0c,0x23,0x0b,0x05,0x29,0x2a,0x1e,\r\n  0x1b,0x01,0x01,0x01,0x11,0x1e,0x19,0x05,0x1f,0x19,0x29,0x25,0x0d,\r\n  0x19,0x13,0x0b,0x15,0x1e,0x1b,0x01,0x01,0x38,0x1e,0x2a,0x1f,0x13,\r\n  0x1f,0x13,0x28,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x0e,0x1e,0x10,\r\n  0x23,0x0b,0x05,0x29,0x02,0x1f,0x0b,0x22,0x0b,0x22,0x1e,0x1e,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x37,0x38,0x1e,0x1e,0x1e,\r\n  0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x1b,0x01,0x01,0x01,0x01,0x01,0x3a,\r\n  0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x17,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x38,0x3c,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x32,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,\r\n  0x34,0x1e,0x18,0x12,0x0d,0x29,0x02,0x23,0x02,0x1e,0x1e,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x33,0x39,0x35,0x01,0x01,0x01,0x08,0x1e,0x1e,0x15,0x14,0x0d,\r\n  0x02,0x1f,0x02,0x23,0x26,0x1e,0x1e,0x1b,0x01,0x01,0x01,0x01,0x0e,\r\n  0x1e,0x10,0x02,0x13,0x14,0x23,0x0a,0x1e,0x3b,0x01,0x30,0x1e,0x12,\r\n  0x06,0x19,0x1f,0x19,0x05,0x14,0x22,0x1f,0x14,0x28,0x1e,0x1b,0x01,\r\n  0x01,0x38,0x1e,0x1e,0x02,0x13,0x13,0x13,0x13,0x22,0x13,0x13,0x25,\r\n  0x1e,0x32,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x03,0x1f,\r\n  0x14,0x13,0x0c,0x1e,0x1e,0x3d,0x01,0x01,0x20,0x07,0x1e,0x03,0x13,\r\n  0x05,0x05,0x0c,0x05,0x05,0x0c,0x31,0x1e,0x3e,0x34,0x01,0x01,0x01,\r\n  0x37,0x1e,0x0a,0x27,0x0c,0x19,0x12,0x13,0x05,0x22,0x14,0x14,0x1e,\r\n  0x1e,0x36,0x01,0x01,0x1e,0x1e,0x05,0x13,0x0c,0x14,0x13,0x1e,0x1e,\r\n  0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x2d,0x05,0x0c,0x0c,\r\n  0x22,0x02,0x23,0x14,0x12,0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x2e,0x2b,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x1e,0x18,0x0c,\r\n  0x14,0x05,0x22,0x02,0x21,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x08,0x1e,0x1e,0x1e,0x2d,0x25,0x0a,0x21,0x1e,\r\n  0x1e,0x1e,0x1b,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x33,0x0e,0x01,0x3b,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x2b,0x01,0x01,0x2b,0x38,0x1e,\r\n  0x1e,0x1e,0x2a,0x25,0x16,0x16,0x09,0x1e,0x1e,0x40,0x2b,0x01,0x01,\r\n  0x01,0x01,0x01,0x34,0x34,0x34,0x32,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x01,0x01,0x01,0x01,0x2b,0x32,0x1e,0x1e,0x18,0x25,0x16,0x16,\r\n  0x09,0x1e,0x1e,0x1d,0x2b,0x01,0x01,0x01,0x01,0x2b,0x1e,0x1e,0x0a,\r\n  0x1f,0x05,0x0c,0x1f,0x0b,0x1f,0x0b,0x2d,0x1e,0x38,0x01,0x01,0x01,\r\n  0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x03,0x25,0x0a,0x10,0x1e,\r\n  0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x34,0x1e,0x18,0x0b,0x19,0x19,0x1a,0x31,\r\n  0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x17,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2f,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,\r\n  0x01,0x01,0x01,0x3b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x30,0x1d,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,\r\n  0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x1e,0x1e,0x1e,0x2d,0x25,0x16,\r\n  0x28,0x18,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x1c,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x04,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1d,0x2b,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x0e,0x08,0x2e,0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x2f,0x08,0x08,0x3c,0x20,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x20,0x08,0x08,0x08,0x20,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,\r\n  0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,\r\n  0x2f,0x3b,0x2e,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x30,\r\n  0x32,0x1e,0x33,0x33,0x39,0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x35,0x08,0x3c,0x1b,0x36,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x20,0x3c,0x2b,0x17,0x20,0x01,0x01,0x01,0x01,0x01,0x0e,\r\n  0x36,0x36,0x17,0x20,0x01,0x01,0x01,0x01,0x01,0x3c,0x37,0x3d,0x1c,\r\n  0x1c,0x2c,0x1b,0x0e,0x01,0x01,0x01,0x01,0x35,0x0e,0x20,0x35,0x20,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x17,0x30,0x1d,0x30,0x3a,\r\n  0x17,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x17,0x2b,0x2f,0x20,\r\n  0x01,0x01,0x01,0x01,0x01,0x00,0x34,0x00,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x0e,0x3c,0x3c,0x34,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x36,0x38,0x1e,0x38,\r\n  0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x35,0x35,0x34,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x3b,\r\n  0x37,0x3d,0x3b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x00,0x35,0x35,0x20,0x0e,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,\r\n  0x20,0x35,0x35,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,\r\n  0x3d,0x32,0x2c,0x1b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x34,0x3c,0x1c,0x38,0x30,0x3b,0x35,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x34,0x35,0x35,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x08,0x30,0x08,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x37,0x38,0x07,\r\n  0x1e,0x07,0x38,0x1c,0x2f,0x01,0x01,0x01,0x01,0x01,0x2c,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x2c,0x01,0x01,0x01,0x11,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x04,0x01,0x01,0x01,0x04,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x33,\r\n  0x0e,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x39,0x0e,0x01,0x01,\r\n  0x01,0x0e,0x11,0x33,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,\r\n  0x01,0x01,0x01,0x04,0x1e,0x1e,0x1e,0x1e,0x1e,0x04,0x01,0x01,0x01,\r\n  0x3d,0x1e,0x1e,0x1e,0x3d,0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x11,\r\n  0x1e,0x1e,0x1e,0x07,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x36,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,0x01,\r\n  0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x08,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x04,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x17,0x01,0x01,0x01,0x01,0x01,0x00,0x11,0x1e,0x1e,0x1e,0x1e,\r\n  0x1b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2f,0x38,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x32,0x30,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x30,0x1e,0x1d,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x3d,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x3d,0x1e,0x1e,0x1e,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x35,0x39,0x1e,0x1e,0x1e,0x1e,0x18,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x2b,0x01,0x01,0x2b,0x1e,0x09,0x2a,0x21,0x03,0x09,0x1e,\r\n  0x36,0x01,0x0f,0x1e,0x10,0x31,0x31,0x03,0x18,0x1e,0x35,0x01,0x34,\r\n  0x1e,0x18,0x24,0x29,0x06,0x24,0x0d,0x25,0x1e,0x30,0x01,0x38,0x1e,\r\n  0x09,0x10,0x09,0x2d,0x09,0x1e,0x39,0x01,0x01,0x01,0x11,0x1e,0x1e,\r\n  0x03,0x26,0x0b,0x24,0x26,0x03,0x1e,0x1e,0x38,0x20,0x01,0x20,0x1e,\r\n  0x18,0x03,0x21,0x2a,0x18,0x1e,0x2b,0x01,0x30,0x1e,0x1e,0x18,0x1e,\r\n  0x1e,0x1b,0x01,0x01,0x01,0x01,0x01,0x2c,0x1e,0x10,0x2a,0x16,0x1e,\r\n  0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x04,0x1e,0x26,0x13,0x10,0x1e,0x17,0x01,0x01,0x01,0x0e,0x38,0x1e,\r\n  0x18,0x2d,0x2d,0x18,0x1e,0x38,0x34,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x1c,0x1e,0x1e,0x1e,0x25,0x06,0x29,0x10,0x1e,0x1e,0x38,0x2b,0x01,\r\n  0x01,0x01,0x01,0x38,0x1e,0x1e,0x2d,0x09,0x09,0x10,0x18,0x1e,0x0f,\r\n  0x01,0x35,0x40,0x1e,0x21,0x09,0x09,0x2d,0x18,0x1e,0x1e,0x17,0x01,\r\n  0x01,0x01,0x3d,0x1e,0x1e,0x10,0x22,0x27,0x1e,0x1e,0x38,0x2b,0x01,\r\n  0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x16,0x15,0x02,0x29,\r\n  0x2a,0x2d,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x00,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,0x3a,0x1e,0x1e,0x2d,0x09,0x21,\r\n  0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x36,0x04,0x1e,0x1e,0x29,0x1e,\r\n  0x1e,0x04,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x39,\r\n  0x1e,0x1e,0x28,0x23,0x05,0x13,0x05,0x23,0x24,0x18,0x1e,0x38,0x01,\r\n  0x01,0x1b,0x1e,0x15,0x13,0x13,0x13,0x26,0x1e,0x3a,0x01,0x39,0x1e,\r\n  0x02,0x1f,0x1f,0x13,0x25,0x1e,0x3b,0x01,0x0e,0x1e,0x2d,0x1f,0x13,\r\n  0x05,0x1f,0x0c,0x0b,0x1e,0x32,0x01,0x1e,0x1e,0x13,0x13,0x13,0x13,\r\n  0x0c,0x1e,0x1e,0x00,0x01,0x3a,0x1e,0x18,0x0c,0x13,0x13,0x13,0x13,\r\n  0x13,0x13,0x13,0x1e,0x1e,0x2c,0x01,0x08,0x1e,0x25,0x13,0x13,0x13,\r\n  0x15,0x1e,0x1b,0x01,0x1d,0x1e,0x0b,0x13,0x27,0x1e,0x2c,0x01,0x01,\r\n  0x01,0x01,0x01,0x07,0x1e,0x14,0x0c,0x13,0x1e,0x1e,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x1e,0x1e,0x05,0x13,\r\n  0x06,0x1e,0x0f,0x01,0x01,0x01,0x11,0x1e,0x1e,0x13,0x13,0x13,0x13,\r\n  0x1e,0x1e,0x04,0x01,0x01,0x01,0x01,0x01,0x1c,0x1e,0x1e,0x29,0x1f,\r\n  0x1f,0x13,0x05,0x14,0x13,0x2d,0x1e,0x38,0x2b,0x01,0x01,0x30,0x1e,\r\n  0x10,0x14,0x13,0x05,0x14,0x13,0x02,0x1e,0x39,0x01,0x3b,0x1e,0x0a,\r\n  0x13,0x13,0x13,0x13,0x13,0x06,0x1e,0x11,0x01,0x01,0x0e,0x1e,0x1e,\r\n  0x1e,0x31,0x13,0x13,0x1e,0x18,0x1e,0x38,0x01,0x01,0x01,0x01,0x2b,\r\n  0x38,0x1e,0x1e,0x06,0x13,0x1f,0x1f,0x13,0x05,0x14,0x13,0x19,0x18,\r\n  0x1e,0x38,0x00,0x01,0x01,0x2b,0x1e,0x21,0x0b,0x13,0x2d,0x1e,0x1c,\r\n  0x01,0x01,0x01,0x39,0x1e,0x02,0x13,0x13,0x13,0x10,0x1e,0x0e,0x01,\r\n  0x01,0x01,0x08,0x1e,0x1e,0x1e,0x15,0x13,0x28,0x1e,0x1e,0x1e,0x08,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x33,0x1e,0x0c,0x13,0x13,\r\n  0x13,0x13,0x13,0x13,0x13,0x13,0x09,0x1e,0x1b,0x01,0x0f,0x1e,0x26,\r\n  0x13,0x1f,0x0c,0x26,0x1e,0x0f,0x01,0x1d,0x1e,0x23,0x0c,0x13,0x0b,\r\n  0x0a,0x1e,0x2e,0x01,0x35,0x1e,0x2d,0x13,0x1f,0x1f,0x13,0x22,0x27,\r\n  0x1e,0x38,0x01,0x38,0x1e,0x26,0x13,0x13,0x13,0x12,0x1e,0x39,0x01,\r\n  0x01,0x39,0x1e,0x27,0x13,0x13,0x13,0x05,0x13,0x13,0x13,0x13,0x05,\r\n  0x1e,0x07,0x01,0x08,0x1e,0x25,0x13,0x13,0x13,0x15,0x1e,0x1b,0x01,\r\n  0x32,0x1e,0x22,0x13,0x02,0x1e,0x39,0x01,0x01,0x01,0x20,0x08,0x2c,\r\n  0x1e,0x12,0x0c,0x0c,0x1e,0x1e,0x2e,0x0e,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x2c,0x1e,0x0a,0x14,0x13,0x1e,0x1e,0x17,0x01,\r\n  0x01,0x1b,0x1e,0x1e,0x0c,0x13,0x13,0x13,0x13,0x14,0x1e,0x1e,0x2b,\r\n  0x01,0x01,0x01,0x2b,0x1e,0x1e,0x1a,0x1f,0x19,0x31,0x1e,0x1e,0x2a,\r\n  0x05,0x22,0x10,0x1e,0x38,0x01,0x01,0x32,0x1e,0x23,0x13,0x1f,0x14,\r\n  0x13,0x14,0x0d,0x1e,0x2c,0x01,0x3c,0x1e,0x2a,0x13,0x13,0x13,0x13,\r\n  0x13,0x0c,0x09,0x1e,0x20,0x01,0x3a,0x1e,0x28,0x13,0x12,0x13,0x14,\r\n  0x12,0x13,0x2d,0x1e,0x17,0x01,0x01,0x01,0x38,0x1e,0x1e,0x13,0x0b,\r\n  0x1f,0x0b,0x29,0x0a,0x24,0x0b,0x1f,0x14,0x13,0x2d,0x1e,0x3d,0x01,\r\n  0x01,0x01,0x38,0x1e,0x19,0x13,0x0b,0x1e,0x3e,0x34,0x01,0x01,0x3a,\r\n  0x1e,0x26,0x13,0x13,0x13,0x09,0x1e,0x20,0x01,0x01,0x08,0x1e,0x1e,\r\n  0x15,0x05,0x13,0x13,0x13,0x14,0x28,0x1e,0x1e,0x08,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x3a,0x1e,0x25,0x13,0x13,0x13,0x13,0x02,0x1f,0x13,\r\n  0x13,0x13,0x27,0x1e,0x2c,0x01,0x1b,0x1e,0x15,0x13,0x1f,0x0c,0x28,\r\n  0x1e,0x3a,0x01,0x11,0x1e,0x19,0x1f,0x13,0x13,0x0a,0x1e,0x3b,0x01,\r\n  0x20,0x1e,0x09,0x02,0x05,0x19,0x19,0x05,0x29,0x1e,0x30,0x01,0x37,\r\n  0x1e,0x15,0x14,0x13,0x13,0x12,0x1e,0x3d,0x01,0x01,0x33,0x1e,0x0c,\r\n  0x13,0x13,0x13,0x1e,0x1a,0x13,0x13,0x13,0x13,0x1e,0x1e,0x01,0x08,\r\n  0x1e,0x25,0x13,0x13,0x13,0x15,0x1e,0x1b,0x01,0x38,0x1e,0x23,0x13,\r\n  0x1a,0x1e,0x04,0x01,0x01,0x04,0x1e,0x1e,0x1e,0x1e,0x12,0x0c,0x0c,\r\n  0x1e,0x1e,0x1e,0x1e,0x11,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,\r\n  0x1e,0x1e,0x02,0x12,0x2d,0x1e,0x38,0x01,0x01,0x08,0x1e,0x1e,0x27,\r\n  0x13,0x13,0x24,0x23,0x13,0x13,0x15,0x1e,0x33,0x35,0x01,0x01,0x38,\r\n  0x1e,0x28,0x0c,0x24,0x16,0x1a,0x0c,0x29,0x03,0x1e,0x22,0x1f,0x1e,\r\n  0x1e,0x2f,0x01,0x32,0x1e,0x12,0x14,0x0c,0x27,0x22,0x19,0x0a,0x1e,\r\n  0x1b,0x01,0x0e,0x1e,0x10,0x19,0x14,0x13,0x0b,0x14,0x0c,0x10,0x1e,\r\n  0x0e,0x01,0x39,0x1e,0x27,0x13,0x13,0x13,0x13,0x13,0x13,0x26,0x1e,\r\n  0x0f,0x01,0x01,0x1b,0x1e,0x1e,0x0c,0x13,0x1f,0x16,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x0b,0x0c,0x0b,0x1e,0x32,0x01,0x01,0x01,0x37,0x1e,\r\n  0x1e,0x27,0x13,0x2a,0x1e,0x3c,0x01,0x01,0x1c,0x1e,0x12,0x13,0x13,\r\n  0x13,0x2d,0x1e,0x35,0x01,0x01,0x38,0x1e,0x12,0x13,0x13,0x13,0x13,\r\n  0x13,0x13,0x13,0x29,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x39,\r\n  0x1e,0x1a,0x13,0x13,0x13,0x14,0x1e,0x12,0x13,0x13,0x13,0x22,0x1e,\r\n  0x32,0x01,0x3d,0x1e,0x0d,0x13,0x13,0x05,0x0d,0x1e,0x2c,0x01,0x1e,\r\n  0x1e,0x1f,0x14,0x13,0x0c,0x15,0x1e,0x1b,0x01,0x01,0x04,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x3b,0x01,0x0f,0x1e,0x06,0x1f,0x19,\r\n  0x05,0x28,0x1e,0x1b,0x01,0x01,0x39,0x1e,0x15,0x27,0x27,0x28,0x1e,\r\n  0x22,0x13,0x13,0x13,0x13,0x1e,0x1e,0x01,0x3c,0x1e,0x16,0x13,0x0c,\r\n  0x13,0x0a,0x1e,0x3b,0x01,0x40,0x1e,0x1f,0x13,0x23,0x1e,0x38,0x01,\r\n  0x20,0x1e,0x18,0x16,0x0a,0x10,0x23,0x13,0x05,0x18,0x25,0x0a,0x10,\r\n  0x1e,0x3c,0x01,0x01,0x01,0x01,0x01,0x01,0x39,0x1e,0x28,0x0b,0x14,\r\n  0x1e,0x07,0x2b,0x01,0x01,0x30,0x1e,0x29,0x13,0x13,0x05,0x1e,0x1e,\r\n  0x13,0x13,0x13,0x0a,0x1e,0x3b,0x01,0x01,0x1e,0x1e,0x0c,0x19,0x1e,\r\n  0x19,0x0c,0x23,0x05,0x13,0x06,0x1e,0x0c,0x15,0x1e,0x39,0x01,0x1d,\r\n  0x1e,0x27,0x02,0x22,0x27,0x26,0x1e,0x1e,0x33,0x35,0x01,0x01,0x11,\r\n  0x1e,0x1e,0x2a,0x05,0x02,0x24,0x0b,0x2d,0x1e,0x35,0x01,0x3a,0x1e,\r\n  0x21,0x29,0x13,0x13,0x13,0x05,0x0a,0x10,0x1e,0x17,0x01,0x01,0x38,\r\n  0x1e,0x12,0x0c,0x0c,0x1e,0x1e,0x25,0x27,0x1a,0x31,0x25,0x31,0x09,\r\n  0x13,0x27,0x31,0x1e,0x3c,0x01,0x01,0x01,0x37,0x1e,0x1e,0x05,0x24,\r\n  0x1e,0x37,0x01,0x01,0x2e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x34,\r\n  0x01,0x0e,0x1e,0x1e,0x13,0x13,0x13,0x13,0x0b,0x13,0x13,0x13,0x13,\r\n  0x31,0x1e,0x36,0x01,0x01,0x01,0x01,0x01,0x11,0x1e,0x15,0x22,0x13,\r\n  0x13,0x19,0x1e,0x06,0x13,0x13,0x13,0x0b,0x1e,0x1d,0x01,0x3b,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1b,0x01,0x11,0x1e,0x1e,0x0d,0x0c,\r\n  0x1f,0x10,0x1e,0x36,0x01,0x01,0x01,0x37,0x11,0x1e,0x1d,0x1d,0x1e,\r\n  0x38,0x3b,0x01,0x01,0x2f,0x1e,0x03,0x1f,0x05,0x22,0x2a,0x1e,0x2f,\r\n  0x01,0x01,0x36,0x1e,0x1e,0x1e,0x1e,0x1e,0x13,0x13,0x13,0x13,0x13,\r\n  0x15,0x1e,0x38,0x01,0x20,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x35,\r\n  0x01,0x39,0x1e,0x24,0x14,0x15,0x1e,0x1c,0x01,0x17,0x1e,0x03,0x22,\r\n  0x13,0x1f,0x0c,0x05,0x05,0x13,0x0c,0x0c,0x12,0x1e,0x1c,0x01,0x01,\r\n  0x01,0x01,0x01,0x36,0x1e,0x1e,0x1f,0x02,0x21,0x1e,0x04,0x01,0x01,\r\n  0x01,0x3a,0x1e,0x26,0x12,0x29,0x1e,0x1e,0x1e,0x1e,0x0d,0x1a,0x15,\r\n  0x1e,0x1b,0x01,0x35,0x1e,0x2d,0x0c,0x15,0x1e,0x0d,0x0c,0x18,0x29,\r\n  0x1f,0x0c,0x1e,0x05,0x22,0x1e,0x33,0x01,0x1d,0x1e,0x29,0x14,0x0b,\r\n  0x19,0x0d,0x1e,0x2c,0x35,0x01,0x01,0x01,0x01,0x30,0x1e,0x0a,0x22,\r\n  0x0b,0x0c,0x0b,0x2d,0x1e,0x35,0x01,0x01,0x38,0x1e,0x2a,0x13,0x13,\r\n  0x13,0x1f,0x1e,0x1e,0x11,0x01,0x01,0x2b,0x1e,0x21,0x1f,0x0c,0x10,\r\n  0x1e,0x27,0x23,0x0c,0x05,0x02,0x0c,0x13,0x1e,0x26,0x1f,0x24,0x1e,\r\n  0x1c,0x01,0x01,0x01,0x01,0x04,0x1e,0x1e,0x1e,0x1e,0x3c,0x01,0x01,\r\n  0x0e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,0x3b,0x1e,0x0a,\r\n  0x13,0x13,0x13,0x0c,0x1e,0x1a,0x13,0x13,0x13,0x15,0x1e,0x1b,0x01,\r\n  0x01,0x01,0x01,0x01,0x37,0x1e,0x06,0x0c,0x19,0x0b,0x22,0x10,0x27,\r\n  0x13,0x13,0x13,0x0b,0x1e,0x1d,0x01,0x01,0x3b,0x38,0x1e,0x1e,0x1e,\r\n  0x38,0x1b,0x01,0x01,0x3c,0x1e,0x1e,0x14,0x1f,0x0d,0x1e,0x38,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x01,\r\n  0x36,0x1e,0x31,0x0d,0x1a,0x0c,0x0a,0x1e,0x1b,0x01,0x01,0x01,0x36,\r\n  0x3a,0x33,0x1e,0x05,0x13,0x13,0x13,0x13,0x16,0x1e,0x1e,0x2b,0x01,\r\n  0x2f,0x1e,0x2a,0x1f,0x14,0x13,0x25,0x1e,0x08,0x01,0x3c,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x36,0x01,0x17,0x1e,0x03,0x13,0x0c,0x19,0x0c,0x1f,\r\n  0x23,0x13,0x0c,0x1f,0x24,0x1e,0x37,0x01,0x01,0x01,0x01,0x01,0x38,\r\n  0x1e,0x28,0x22,0x27,0x1e,0x1d,0x20,0x01,0x01,0x01,0x17,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x04,0x11,0x1e,0x1e,0x1e,0x1e,0x1e,0x36,0x01,0x36,\r\n  0x1e,0x31,0x05,0x31,0x1e,0x27,0x1f,0x19,0x13,0x22,0x2a,0x1e,0x0d,\r\n  0x02,0x1e,0x1e,0x01,0x1d,0x1e,0x12,0x29,0x23,0x1a,0x12,0x1e,0x39,\r\n  0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,0x25,0x0c,0x1a,0x0b,0x05,0x2d,\r\n  0x1e,0x35,0x01,0x20,0x1e,0x09,0x13,0x13,0x28,0x14,0x13,0x05,0x1e,\r\n  0x07,0x01,0x01,0x2e,0x1e,0x0a,0x13,0x1f,0x1e,0x26,0x13,0x05,0x25,\r\n  0x03,0x13,0x05,0x06,0x1e,0x25,0x02,0x0d,0x1e,0x04,0x01,0x01,0x01,\r\n  0x01,0x34,0x04,0x07,0x04,0x3c,0x01,0x01,0x01,0x2e,0x1e,0x0a,0x14,\r\n  0x0b,0x13,0x18,0x1e,0x34,0x01,0x0f,0x1e,0x06,0x13,0x13,0x13,0x13,\r\n  0x1e,0x1e,0x21,0x09,0x10,0x18,0x1e,0x36,0x01,0x01,0x01,0x01,0x01,\r\n  0x3c,0x1e,0x1e,0x13,0x05,0x0b,0x14,0x0c,0x0c,0x02,0x22,0x0c,0x0b,\r\n  0x1e,0x1d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x1c,0x1e,0x12,0x27,0x0c,0x21,0x1e,0x37,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x1e,0x10,0x1f,\r\n  0x1a,0x19,0x21,0x1e,0x36,0x01,0x01,0x01,0x01,0x34,0x1e,0x18,0x29,\r\n  0x0d,0x1a,0x22,0x2a,0x1e,0x07,0x2b,0x01,0x01,0x3b,0x1e,0x25,0x0c,\r\n  0x14,0x13,0x15,0x1e,0x1b,0x01,0x01,0x3c,0x04,0x3e,0x04,0x36,0x01,\r\n  0x01,0x00,0x1e,0x1e,0x10,0x10,0x1e,0x02,0x13,0x13,0x1e,0x10,0x10,\r\n  0x18,0x1e,0x3c,0x01,0x01,0x01,0x01,0x17,0x1e,0x18,0x27,0x14,0x03,\r\n  0x1e,0x37,0x01,0x01,0x01,0x01,0x01,0x17,0x3a,0x30,0x3d,0x2e,0x01,\r\n  0x01,0x3b,0x3d,0x04,0x1b,0x36,0x01,0x01,0x2b,0x1e,0x21,0x05,0x16,\r\n  0x1e,0x02,0x13,0x05,0x05,0x27,0x1e,0x1e,0x27,0x0c,0x1e,0x1e,0x01,\r\n  0x1d,0x1e,0x02,0x22,0x23,0x22,0x1a,0x1e,0x39,0x01,0x01,0x01,0x01,\r\n  0x01,0x2e,0x1e,0x25,0x19,0x22,0x0c,0x27,0x2d,0x1e,0x35,0x01,0x01,\r\n  0x38,0x1e,0x0a,0x02,0x1e,0x10,0x14,0x31,0x1e,0x2c,0x01,0x01,0x37,\r\n  0x1e,0x06,0x0c,0x15,0x1e,0x13,0x0c,0x14,0x1e,0x1e,0x1f,0x13,0x15,\r\n  0x1e,0x12,0x13,0x12,0x1e,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x1c,0x1e,0x12,0x02,0x22,0x0c,0x18,0x1e,\r\n  0x20,0x01,0x0f,0x1e,0x06,0x13,0x13,0x13,0x13,0x18,0x1e,0x10,0x18,\r\n  0x2d,0x18,0x1e,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,\r\n  0x0a,0x12,0x29,0x06,0x23,0x14,0x22,0x0c,0x0b,0x1e,0x1d,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3c,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x34,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x20,0x01,0x01,0x01,0x01,0x01,0x3d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x3e,0x2b,0x01,0x01,0x01,0x3c,0x1e,0x16,0x0c,0x23,0x13,0x28,0x1e,\r\n  0x2e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x30,0x1e,\r\n  0x1e,0x1e,0x1e,0x0d,0x1f,0x1f,0x1e,0x1e,0x1e,0x1e,0x04,0x01,0x01,\r\n  0x01,0x01,0x01,0x38,0x1e,0x26,0x14,0x06,0x1e,0x32,0x00,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x20,0x1e,0x18,0x23,0x0d,0x1e,0x19,0x1f,0x0d,\r\n  0x0c,0x05,0x1e,0x1e,0x0b,0x02,0x1e,0x3e,0x01,0x1d,0x1e,0x24,0x0b,\r\n  0x14,0x22,0x29,0x1e,0x39,0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,0x0a,\r\n  0x23,0x0b,0x1f,0x05,0x2d,0x1e,0x35,0x01,0x01,0x2b,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1d,0x20,0x01,0x01,0x1c,0x1e,0x26,0x0c,0x21,\r\n  0x1e,0x13,0x0c,0x28,0x1e,0x1e,0x13,0x1f,0x03,0x1e,0x02,0x14,0x16,\r\n  0x1e,0x08,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x1b,0x1e,0x15,0x14,0x22,0x0c,0x10,0x1e,0x2b,0x01,0x3b,0x1e,\r\n  0x0a,0x13,0x13,0x13,0x0c,0x1e,0x26,0x13,0x13,0x13,0x0a,0x1e,0x3b,\r\n  0x01,0x01,0x01,0x01,0x01,0x2f,0x1e,0x31,0x15,0x15,0x29,0x28,0x1e,\r\n  0x28,0x0d,0x1f,0x22,0x0b,0x1e,0x1d,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x3c,0x38,0x1e,0x1e,0x38,0x2b,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x2b,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x3c,0x01,0x01,0x01,\r\n  0x01,0x00,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x01,0x01,0x01,\r\n  0x01,0x0f,0x1e,0x06,0x05,0x14,0x13,0x06,0x1e,0x30,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x0e,0x2c,0x1e,0x1a,\r\n  0x1f,0x13,0x1e,0x1e,0x0e,0x34,0x01,0x01,0x01,0x01,0x01,0x08,0x1e,\r\n  0x1e,0x02,0x05,0x21,0x1e,0x3a,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x40,0x1e,0x1f,0x0c,0x1e,0x06,0x1f,0x09,0x19,0x0b,0x16,0x25,\r\n  0x22,0x03,0x1e,0x3d,0x01,0x1d,0x1e,0x02,0x14,0x0d,0x22,0x0d,0x1e,\r\n  0x39,0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,0x25,0x0d,0x19,0x05,0x12,\r\n  0x2d,0x1e,0x35,0x01,0x01,0x01,0x2b,0x1c,0x1d,0x1c,0x3d,0x3e,0x3d,\r\n  0x00,0x01,0x01,0x01,0x1c,0x1e,0x12,0x13,0x16,0x1e,0x0c,0x23,0x2a,\r\n  0x1e,0x0d,0x05,0x19,0x1e,0x16,0x05,0x0c,0x1e,0x1e,0x20,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x04,0x1e,0x12,\r\n  0x0d,0x1f,0x22,0x28,0x1e,0x2e,0x01,0x35,0x1e,0x18,0x13,0x1f,0x0c,\r\n  0x14,0x14,0x22,0x13,0x13,0x13,0x21,0x1e,0x2b,0x01,0x01,0x01,0x01,\r\n  0x01,0x0f,0x1e,0x06,0x1a,0x19,0x13,0x23,0x15,0x23,0x0b,0x05,0x1f,\r\n  0x22,0x1e,0x32,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x17,0x1e,0x31,\r\n  0x02,0x1f,0x27,0x25,0x1e,0x2e,0x01,0x01,0x01,0x01,0x00,0x1e,0x1e,\r\n  0x0b,0x0b,0x05,0x1f,0x1e,0x1e,0x01,0x01,0x01,0x01,0x17,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x08,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x40,0x1e,0x05,0x05,0x13,0x1e,0x1e,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x06,0x22,0x02,0x1e,\r\n  0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x39,0x1e,0x10,\r\n  0x22,0x1f,0x09,0x1e,0x1e,0x1e,0x1e,0x29,0x05,0x0d,0x1e,0x32,0x00,\r\n  0x01,0x1d,0x1e,0x29,0x02,0x29,0x27,0x06,0x1e,0x38,0x3b,0x01,0x01,\r\n  0x01,0x2b,0x38,0x1e,0x03,0x29,0x27,0x0c,0x22,0x2d,0x1e,0x35,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x0f,0x1e,0x15,0x1f,0x0d,0x1e,0x22,0x1f,0x05,0x23,0x13,0x0c,0x19,\r\n  0x02,0x1f,0x02,0x2a,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x39,0x1e,0x27,0x0b,0x05,0x1f,0x15,\r\n  0x1e,0x1b,0x01,0x01,0x38,0x1e,0x0d,0x1f,0x0c,0x23,0x13,0x13,0x13,\r\n  0x13,0x29,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x2f,0x1e,0x1e,\r\n  0x05,0x22,0x14,0x14,0x13,0x1a,0x19,0x13,0x0b,0x15,0x1e,0x3d,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x17,0x1e,0x31,0x22,0x1f,0x14,0x25,\r\n  0x1e,0x08,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x12,0x19,0x13,0x0b,\r\n  0x1e,0x1e,0x01,0x01,0x01,0x01,0x01,0x17,0x38,0x1e,0x1e,0x1e,0x38,\r\n  0x08,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x2c,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x1b,0x1e,0x1e,0x29,0x02,0x2d,0x1e,0x37,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x38,0x1e,0x03,0x19,0x14,0x0d,\r\n  0x16,0x25,0x0b,0x1f,0x14,0x1e,0x1e,0x30,0x01,0x01,0x1d,0x1e,0x27,\r\n  0x14,0x0b,0x1f,0x0b,0x2d,0x1e,0x1e,0x3b,0x01,0x00,0x32,0x1e,0x1e,\r\n  0x12,0x14,0x23,0x14,0x1a,0x2d,0x1e,0x0e,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x17,0x1e,0x31,0x0c,\r\n  0x02,0x1e,0x21,0x23,0x13,0x14,0x1a,0x23,0x1f,0x1f,0x14,0x09,0x1e,\r\n  0x3e,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x38,0x1e,0x06,0x19,0x13,0x0b,0x16,0x1e,0x38,0x01,0x01,\r\n  0x2e,0x1e,0x1e,0x28,0x14,0x14,0x13,0x0b,0x0c,0x0a,0x1e,0x1e,0x3b,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x2d,0x1f,0x0b,0x24,\r\n  0x13,0x05,0x23,0x22,0x16,0x1e,0x1e,0x36,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x3c,0x1e,0x2a,0x19,0x1f,0x0b,0x26,0x1e,0x0f,0x01,0x01,\r\n  0x01,0x01,0x34,0x1e,0x18,0x05,0x23,0x22,0x22,0x1e,0x1e,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x2c,\r\n  0x40,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x1d,0x1e,\r\n  0x1a,0x0c,0x0d,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x2b,0x32,0x1e,0x1e,0x1a,0x02,0x13,0x23,0x19,0x0a,\r\n  0x1e,0x1e,0x39,0x01,0x01,0x01,0x38,0x1e,0x12,0x19,0x23,0x0b,0x19,\r\n  0x0b,0x24,0x1e,0x30,0x01,0x17,0x1e,0x31,0x27,0x19,0x1a,0x19,0x14,\r\n  0x0b,0x09,0x1e,0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x1d,0x1e,0x1a,0x23,0x13,0x2d,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x02,0x09,0x1e,0x1c,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x1e,0x2d,\r\n  0x05,0x23,0x22,0x22,0x13,0x1e,0x1e,0x01,0x01,0x01,0x2e,0x1e,0x1e,\r\n  0x1e,0x03,0x13,0x31,0x1e,0x1e,0x33,0x3b,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x16,0x25,0x25,0x18,0x1e,\r\n  0x1e,0x07,0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x07,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x2f,0x01,0x01,0x01,0x01,0x01,0x38,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x36,0x1e,0x31,0x22,0x19,0x18,0x1e,\r\n  0x3a,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x33,0x39,0x0e,0x01,\r\n  0x01,0x01,0x30,0x1e,0x29,0x19,0x23,0x22,0x29,0x12,0x24,0x1e,0x2c,\r\n  0x01,0x3c,0x1e,0x16,0x19,0x02,0x29,0x0a,0x0d,0x0d,0x1e,0x32,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x3a,0x1e,0x1e,0x1a,0x13,0x14,0x0b,0x03,0x1e,0x1e,0x0a,\r\n  0x02,0x13,0x14,0x19,0x1e,0x1d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,0x2b,0x11,0x1e,0x2d,0x19,0x09,\r\n  0x1e,0x39,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,\r\n  0x38,0x2f,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x1e,0x1e,0x22,0x27,0x1e,0x1d,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3a,0x38,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x3b,0x1e,\r\n  0x1e,0x25,0x29,0x12,0x29,0x19,0x0a,0x1e,0x1b,0x01,0x0e,0x1e,0x10,\r\n  0x27,0x06,0x12,0x27,0x24,0x1e,0x1e,0x3d,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x39,\r\n  0x1e,0x1e,0x19,0x19,0x05,0x23,0x24,0x05,0x22,0x0c,0x13,0x29,0x1e,\r\n  0x1e,0x1c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x39,0x1e,0x1e,0x1e,0x2c,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x20,\r\n  0x3c,0x08,0x3b,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,\r\n  0x1e,0x1e,0x1e,0x1e,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3b,0x33,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x2b,0x01,0x01,0x11,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x3d,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x39,0x1e,0x1e,0x1e,\r\n  0x28,0x02,0x02,0x05,0x0b,0x15,0x1e,0x1e,0x1e,0x1c,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x0f,0x11,0x0f,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1d,0x30,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x35,0x3a,0x2c,0x04,0x3d,0x1d,0x30,0x2b,\r\n  0x01,0x01,0x01,0x20,0x2c,0x40,0x2c,0x04,0x39,0x1c,0x08,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x37,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x38,0x0f,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x36,0x39,0x33,0x1e,0x1e,0x07,0x04,0x36,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x0e,0x37,0x38,0x3e,0x1d,0x32,0x04,0x2e,0x00,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x04,0x32,\r\n  0x1d,0x1d,0x1c,0x3c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3b,0x3d,\r\n  0x0f,0x37,0x37,0x2f,0x34,0x3b,0x30,0x0f,0x30,0x0f,0x2f,0x01,0x01,\r\n  0x01,0x01,0x01,0x34,0x20,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x00,0x2f,0x1c,0x38,0x1c,0x1b,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x34,0x34,0x01,0x34,0x34,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x2f,0x37,0x30,0x3b,0x35,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x08,0x1c,0x3a,0x17,0x00,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x1b,0x2c,0x3d,0x2e,0x2b,0x1b,0x30,0x2c,\r\n  0x1b,0x01,0x01,0x01,0x01,0x01,0x00,0x17,0x3c,0x3c,0x3c,0x3c,0x3c,\r\n  0x3c,0x3c,0x08,0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x2f,0x0f,0x08,0x35,0x01,0x01,0x01,0x01,0x01,0x2b,0x2e,0x3a,0x3b,\r\n  0x2e,0x2e,0x2e,0x1b,0x1b,0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x0e,0x0e,0x00,0x01,0x35,0x0e,0x34,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3b,0x3d,0x3b,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x00,0x34,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x3d,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x32,0x17,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x36,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x2b,0x01,0x01,0x01,0x01,0x39,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x3e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x2f,0x01,0x01,0x2b,0x38,0x1e,\r\n  0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x00,0x3d,0x3e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,\r\n  0x3e,0x1e,0x1e,0x04,0x34,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x38,0x17,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x34,\r\n  0x04,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1b,0x01,0x01,\r\n  0x01,0x35,0x32,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x40,\r\n  0x2b,0x01,0x01,0x01,0x2c,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,\r\n  0x1e,0x1e,0x1e,0x38,0x1e,0x1e,0x1e,0x04,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x2b,0x1d,0x1e,0x1e,0x1e,0x3d,0x20,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x3a,0x39,0x07,0x3e,0x3d,0x35,0x01,0x01,0x17,\r\n  0x38,0x1e,0x1e,0x3d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x3a,0x39,0x32,0x1e,0x33,0x38,0x1c,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3d,0x1e,0x1e,0x28,0x23,0x22,\r\n  0x23,0x22,0x0d,0x03,0x1e,0x1e,0x17,0x01,0x01,0x01,0x01,0x01,0x36,\r\n  0x1e,0x1e,0x10,0x29,0x19,0x23,0x23,0x12,0x18,0x1e,0x40,0x2b,0x01,\r\n  0x01,0x35,0x1e,0x2d,0x0d,0x06,0x24,0x24,0x21,0x1e,0x2a,0x29,0x06,\r\n  0x29,0x06,0x1e,0x38,0x01,0x01,0x38,0x1e,0x1e,0x18,0x1e,0x32,0x00,\r\n  0x01,0x01,0x01,0x3d,0x1e,0x1e,0x2a,0x25,0x23,0x12,0x15,0x1e,0x1e,\r\n  0x33,0x2b,0x01,0x01,0x00,0x32,0x1e,0x18,0x18,0x1e,0x18,0x18,0x1e,\r\n  0x04,0x01,0x01,0x01,0x2b,0x1d,0x1e,0x1e,0x31,0x06,0x29,0x25,0x18,\r\n  0x1e,0x1e,0x0f,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x10,0x12,0x26,\r\n  0x03,0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,0x04,0x1e,0x1e,0x1a,0x29,\r\n  0x28,0x1e,0x28,0x24,0x1a,0x1e,0x38,0x01,0x01,0x01,0x39,0x1e,0x03,\r\n  0x2a,0x16,0x2a,0x03,0x2a,0x16,0x16,0x25,0x21,0x1e,0x3a,0x01,0x01,\r\n  0x01,0x01,0x38,0x1e,0x1e,0x31,0x06,0x25,0x1e,0x38,0x01,0x01,0x20,\r\n  0x1e,0x09,0x28,0x26,0x0a,0x0a,0x0a,0x25,0x28,0x15,0x1e,0x38,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1d,0x1e,0x10,0x10,0x1e,0x1e,\r\n  0x2d,0x10,0x18,0x1e,0x3c,0x01,0x01,0x01,0x20,0x2c,0x40,0x1e,0x1e,\r\n  0x03,0x0d,0x18,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x20,0x39,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x33,0x2b,0x17,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x18,\r\n  0x1e,0x1e,0x1e,0x1e,0x3a,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x00,0x3e,0x1e,0x14,0x13,0x13,0x13,0x13,0x0c,0x0c,0x0c,\r\n  0x26,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x26,0x1f,0x14,\r\n  0x13,0x14,0x14,0x13,0x05,0x16,0x1e,0x38,0x01,0x01,0x01,0x1e,0x1e,\r\n  0x13,0x13,0x13,0x13,0x27,0x1e,0x0b,0x13,0x13,0x13,0x13,0x1e,0x1e,\r\n  0x01,0x0e,0x1e,0x10,0x13,0x13,0x03,0x1e,0x17,0x01,0x01,0x08,0x1e,\r\n  0x1e,0x14,0x13,0x13,0x13,0x13,0x0c,0x22,0x0a,0x1e,0x38,0x01,0x01,\r\n  0x2f,0x1e,0x2a,0x0c,0x22,0x0b,0x13,0x05,0x1e,0x07,0x01,0x01,0x2b,\r\n  0x3e,0x1e,0x31,0x13,0x13,0x13,0x13,0x13,0x13,0x26,0x1e,0x1e,0x0f,\r\n  0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,0x13,0x0c,0x22,0x1f,0x09,0x1e,\r\n  0x2e,0x01,0x01,0x2f,0x1e,0x1e,0x02,0x0c,0x14,0x0a,0x16,0x0c,0x22,\r\n  0x0b,0x1e,0x1e,0x01,0x01,0x34,0x1e,0x18,0x05,0x05,0x0c,0x05,0x1f,\r\n  0x0c,0x19,0x0b,0x14,0x26,0x1e,0x39,0x01,0x01,0x01,0x20,0x1e,0x18,\r\n  0x13,0x13,0x13,0x13,0x1e,0x1e,0x00,0x01,0x2f,0x1e,0x03,0x05,0x13,\r\n  0x13,0x27,0x0c,0x0c,0x13,0x13,0x1e,0x1e,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x34,0x3a,0x1e,0x31,0x1f,0x14,0x0a,0x18,0x14,0x1f,0x24,0x1e,\r\n  0x1c,0x01,0x01,0x01,0x2c,0x1e,0x1e,0x21,0x16,0x22,0x13,0x24,0x21,\r\n  0x09,0x1e,0x1d,0x2b,0x01,0x01,0x01,0x2c,0x1e,0x2d,0x02,0x05,0x14,\r\n  0x0a,0x1e,0x38,0x38,0x1e,0x26,0x13,0x25,0x1e,0x08,0x01,0x01,0x01,\r\n  0x01,0x01,0x00,0x32,0x1e,0x21,0x27,0x22,0x13,0x0c,0x23,0x28,0x1e,\r\n  0x1e,0x3a,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x08,0x1e,\r\n  0x03,0x13,0x13,0x13,0x1f,0x0d,0x19,0x13,0x0c,0x14,0x21,0x1e,0x2b,\r\n  0x01,0x01,0x01,0x17,0x1e,0x10,0x14,0x0c,0x14,0x0c,0x14,0x0c,0x1f,\r\n  0x23,0x13,0x10,0x1e,0x0e,0x01,0x01,0x38,0x1e,0x0a,0x14,0x13,0x13,\r\n  0x1a,0x1e,0x14,0x13,0x13,0x13,0x1e,0x1e,0x38,0x01,0x0e,0x1e,0x10,\r\n  0x13,0x13,0x2a,0x1e,0x2f,0x01,0x01,0x30,0x1e,0x29,0x13,0x13,0x13,\r\n  0x23,0x0c,0x0c,0x13,0x13,0x21,0x1e,0x36,0x01,0x2b,0x1e,0x10,0x13,\r\n  0x05,0x26,0x13,0x02,0x1e,0x11,0x01,0x01,0x38,0x1e,0x2a,0x13,0x13,\r\n  0x03,0x1e,0x1e,0x21,0x02,0x13,0x19,0x1e,0x3e,0x2b,0x01,0x0e,0x1e,\r\n  0x10,0x13,0x23,0x02,0x29,0x13,0x13,0x29,0x1e,0x04,0x01,0x01,0x38,\r\n  0x1e,0x06,0x05,0x1f,0x24,0x18,0x05,0x27,0x14,0x1e,0x1e,0x38,0x01,\r\n  0x01,0x34,0x1e,0x18,0x27,0x0d,0x05,0x0b,0x02,0x13,0x05,0x0b,0x14,\r\n  0x1a,0x1e,0x2c,0x01,0x01,0x01,0x08,0x1e,0x25,0x13,0x13,0x13,0x0b,\r\n  0x1e,0x1d,0x01,0x01,0x08,0x1e,0x16,0x13,0x13,0x13,0x0c,0x1f,0x1f,\r\n  0x13,0x13,0x1e,0x1e,0x00,0x01,0x01,0x01,0x01,0x2b,0x3e,0x1e,0x1e,\r\n  0x27,0x19,0x27,0x1e,0x06,0x1a,0x02,0x1e,0x1e,0x1d,0x01,0x01,0x1c,\r\n  0x1e,0x1e,0x22,0x02,0x14,0x13,0x0c,0x23,0x14,0x13,0x03,0x1e,0x38,\r\n  0x01,0x01,0x01,0x40,0x1e,0x1f,0x13,0x13,0x13,0x13,0x21,0x1e,0x1e,\r\n  0x09,0x13,0x13,0x1e,0x1e,0x35,0x01,0x01,0x01,0x01,0x01,0x1b,0x1e,\r\n  0x03,0x13,0x13,0x13,0x13,0x13,0x0c,0x1f,0x1a,0x1e,0x38,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x30,0x1e,0x29,0x13,0x13,0x13,\r\n  0x26,0x1e,0x29,0x13,0x0c,0x13,0x2a,0x1e,0x2f,0x01,0x01,0x35,0x33,\r\n  0x1e,0x26,0x13,0x0c,0x1f,0x14,0x1e,0x29,0x19,0x1a,0x14,0x03,0x1e,\r\n  0x2f,0x01,0x01,0x38,0x1e,0x10,0x24,0x14,0x13,0x23,0x25,0x14,0x13,\r\n  0x13,0x1f,0x18,0x1e,0x38,0x01,0x35,0x1e,0x2d,0x0c,0x13,0x03,0x1e,\r\n  0x17,0x01,0x01,0x04,0x1e,0x1a,0x13,0x13,0x1f,0x1e,0x10,0x1f,0x0b,\r\n  0x13,0x15,0x1e,0x1b,0x01,0x00,0x1e,0x1e,0x03,0x2a,0x09,0x2a,0x31,\r\n  0x1e,0x0f,0x01,0x36,0x1e,0x18,0x13,0x0b,0x1e,0x03,0x1f,0x13,0x12,\r\n  0x1e,0x1a,0x13,0x16,0x1e,0x38,0x01,0x2b,0x07,0x1e,0x24,0x06,0x1a,\r\n  0x19,0x14,0x13,0x29,0x1e,0x3d,0x01,0x01,0x1e,0x1e,0x1f,0x1f,0x13,\r\n  0x2d,0x16,0x13,0x23,0x1a,0x1e,0x3e,0x2b,0x01,0x01,0x01,0x39,0x1e,\r\n  0x10,0x21,0x10,0x10,0x10,0x2d,0x2d,0x23,0x23,0x12,0x1e,0x39,0x01,\r\n  0x01,0x01,0x3c,0x1e,0x16,0x13,0x13,0x27,0x1e,0x1e,0x1c,0x01,0x01,\r\n  0x20,0x07,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,\r\n  0x01,0x01,0x01,0x01,0x2b,0x1e,0x1e,0x2a,0x16,0x0c,0x1f,0x02,0x2d,\r\n  0x02,0x13,0x0d,0x16,0x31,0x1e,0x08,0x01,0x1d,0x1e,0x19,0x23,0x13,\r\n  0x0b,0x27,0x05,0x19,0x12,0x14,0x13,0x09,0x1e,0x35,0x01,0x0e,0x1e,\r\n  0x10,0x13,0x13,0x1e,0x13,0x13,0x1a,0x1e,0x1e,0x05,0x13,0x21,0x1e,\r\n  0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x1e,0x27,0x13,0x13,0x13,\r\n  0x25,0x2a,0x27,0x02,0x1f,0x21,0x1e,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x3b,0x1e,0x2d,0x13,0x13,0x13,0x0a,0x1e,0x1e,0x25,\r\n  0x25,0x25,0x18,0x1e,0x34,0x01,0x01,0x04,0x1e,0x25,0x27,0x0c,0x13,\r\n  0x1f,0x1f,0x0a,0x02,0x23,0x12,0x21,0x1e,0x32,0x00,0x01,0x34,0x1e,\r\n  0x18,0x0b,0x0c,0x14,0x27,0x1f,0x02,0x26,0x22,0x13,0x13,0x1f,0x1e,\r\n  0x1e,0x01,0x35,0x1e,0x2d,0x13,0x13,0x03,0x1e,0x17,0x01,0x01,0x1b,\r\n  0x1e,0x15,0x13,0x13,0x13,0x06,0x2a,0x16,0x2d,0x1e,0x18,0x1e,0x2b,\r\n  0x01,0x01,0x3d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1d,0x01,0x01,0x0f,\r\n  0x1e,0x28,0x05,0x1e,0x03,0x14,0x13,0x05,0x05,0x05,0x1e,0x0c,0x13,\r\n  0x1e,0x1e,0x01,0x38,0x1e,0x16,0x13,0x0c,0x14,0x27,0x13,0x1f,0x24,\r\n  0x1e,0x30,0x01,0x01,0x38,0x1e,0x21,0x1f,0x0c,0x14,0x1e,0x02,0x05,\r\n  0x13,0x03,0x1e,0x38,0x01,0x01,0x01,0x35,0x39,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x02,0x1f,0x1a,0x1e,0x2c,0x01,0x01,0x01,0x3c,0x1e,\r\n  0x16,0x13,0x13,0x2a,0x1e,0x3d,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,\r\n  0x3d,0x1e,0x28,0x1f,0x1f,0x1f,0x12,0x23,0x1f,0x0d,0x05,0x14,0x0b,\r\n  0x06,0x1e,0x1c,0x01,0x1e,0x1e,0x22,0x19,0x05,0x23,0x26,0x24,0x02,\r\n  0x0c,0x1f,0x19,0x25,0x1e,0x08,0x01,0x0e,0x1e,0x10,0x13,0x13,0x1e,\r\n  0x13,0x13,0x0d,0x1e,0x15,0x13,0x1a,0x1e,0x38,0x2b,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x11,0x1e,0x19,0x13,0x13,0x13,0x10,0x09,0x0c,0x1f,\r\n  0x0c,0x31,0x1e,0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,\r\n  0x1e,0x0d,0x13,0x13,0x14,0x23,0x15,0x2d,0x1e,0x1e,0x1e,0x1e,0x04,\r\n  0x01,0x01,0x34,0x1e,0x18,0x19,0x13,0x05,0x23,0x0c,0x14,0x0d,0x0b,\r\n  0x22,0x24,0x1e,0x38,0x0e,0x01,0x01,0x01,0x38,0x1e,0x28,0x16,0x13,\r\n  0x05,0x0c,0x05,0x1f,0x0c,0x0d,0x25,0x25,0x1e,0x38,0x01,0x35,0x1e,\r\n  0x2d,0x0c,0x13,0x03,0x1e,0x17,0x01,0x01,0x17,0x1e,0x1e,0x05,0x13,\r\n  0x0c,0x0c,0x13,0x23,0x27,0x10,0x1e,0x1d,0x01,0x01,0x01,0x01,0x00,\r\n  0x17,0x2f,0x20,0x3c,0x36,0x01,0x01,0x01,0x11,0x1e,0x27,0x0b,0x1e,\r\n  0x0b,0x14,0x2d,0x1e,0x0d,0x26,0x1e,0x26,0x13,0x1e,0x1e,0x01,0x1e,\r\n  0x1e,0x13,0x0c,0x0c,0x29,0x2a,0x0c,0x13,0x06,0x1e,0x11,0x01,0x01,\r\n  0x2b,0x38,0x1e,0x28,0x1f,0x02,0x12,0x21,0x22,0x0c,0x23,0x18,0x1e,\r\n  0x34,0x01,0x01,0x01,0x01,0x0e,0x2b,0x0e,0x0e,0x0e,0x30,0x1e,0x18,\r\n  0x2d,0x1e,0x1e,0x1b,0x01,0x01,0x00,0x3d,0x1e,0x31,0x13,0x13,0x03,\r\n  0x1e,0x17,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x32,0x1e,0x0b,0x1f,\r\n  0x05,0x1f,0x14,0x1f,0x22,0x22,0x22,0x28,0x12,0x1e,0x1e,0x08,0x01,\r\n  0x1e,0x1e,0x23,0x12,0x1f,0x15,0x25,0x1a,0x0a,0x21,0x09,0x2a,0x09,\r\n  0x1e,0x35,0x01,0x0e,0x1e,0x10,0x0c,0x13,0x2d,0x1f,0x13,0x12,0x1e,\r\n  0x13,0x13,0x1e,0x1e,0x1e,0x38,0x0f,0x01,0x01,0x01,0x01,0x01,0x3d,\r\n  0x1e,0x0d,0x13,0x13,0x13,0x13,0x1f,0x1f,0x0c,0x19,0x1e,0x1e,0x1e,\r\n  0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,0x13,\r\n  0x13,0x0c,0x02,0x02,0x1e,0x40,0x1e,0x38,0x08,0x01,0x01,0x01,0x04,\r\n  0x1e,0x2a,0x05,0x13,0x05,0x1f,0x1f,0x25,0x12,0x06,0x09,0x1e,0x3b,\r\n  0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x29,0x0d,0x05,0x0b,0x02,\r\n  0x13,0x2a,0x1e,0x1e,0x1e,0x38,0x01,0x36,0x1e,0x31,0x13,0x13,0x25,\r\n  0x1e,0x08,0x01,0x01,0x38,0x1e,0x26,0x14,0x13,0x1f,0x0c,0x05,0x05,\r\n  0x13,0x05,0x03,0x1e,0x1b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x38,0x1e,0x12,0x19,0x09,0x0b,0x13,0x09,0x1e,\r\n  0x1e,0x1e,0x1e,0x16,0x0b,0x1e,0x1e,0x01,0x38,0x1e,0x24,0x1f,0x0c,\r\n  0x05,0x05,0x13,0x05,0x0c,0x1e,0x1e,0x00,0x01,0x01,0x36,0x1e,0x1e,\r\n  0x18,0x18,0x09,0x1e,0x1e,0x18,0x09,0x1e,0x38,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x04,0x1e,0x1e,0x1e,0x3d,0x01,\r\n  0x01,0x00,0x3e,0x1e,0x1e,0x1a,0x13,0x13,0x25,0x1e,0x08,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x39,0x1e,0x1e,0x10,0x1f,0x23,0x28,0x1e,\r\n  0x22,0x23,0x06,0x18,0x10,0x1e,0x04,0x01,0x01,0x32,0x1e,0x23,0x19,\r\n  0x23,0x23,0x02,0x0b,0x29,0x24,0x25,0x1e,0x1e,0x2c,0x01,0x01,0x01,\r\n  0x07,0x1e,0x27,0x0b,0x14,0x06,0x1f,0x1e,0x19,0x13,0x10,0x1e,0x03,\r\n  0x10,0x1e,0x1e,0x3d,0x01,0x01,0x01,0x01,0x2e,0x1e,0x1e,0x05,0x13,\r\n  0x14,0x22,0x05,0x05,0x0a,0x1e,0x1e,0x1e,0x09,0x1e,0x35,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x38,0x1e,0x25,0x22,0x1f,0x1f,0x23,0x31,0x18,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x08,0x01,0x20,0x1e,0x18,0x0b,0x13,0x1f,\r\n  0x1f,0x13,0x22,0x14,0x0c,0x26,0x1e,0x1e,0x1e,0x38,0x01,0x01,0x34,\r\n  0x1e,0x18,0x22,0x1f,0x0c,0x14,0x14,0x05,0x0c,0x19,0x12,0x14,0x23,\r\n  0x1e,0x1e,0x01,0x34,0x1e,0x18,0x0a,0x29,0x09,0x1e,0x35,0x01,0x2b,\r\n  0x1e,0x21,0x13,0x13,0x0c,0x27,0x2d,0x28,0x22,0x13,0x1f,0x1a,0x1e,\r\n  0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x1d,0x1e,0x02,0x02,0x1e,0x0c,0x02,0x1e,0x1e,0x03,0x28,0x1e,0x16,\r\n  0x0b,0x1e,0x1e,0x01,0x3c,0x1e,0x1e,0x24,0x27,0x24,0x21,0x25,0x26,\r\n  0x0a,0x1e,0x1e,0x34,0x01,0x01,0x01,0x36,0x38,0x1e,0x1e,0x1e,0x38,\r\n  0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x34,0x35,0x00,0x01,0x01,0x01,0x2f,0x1e,0x2a,\r\n  0x22,0x13,0x13,0x13,0x03,0x1e,0x17,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x3a,0x1e,0x2d,0x31,0x2a,0x1f,0x05,0x28,0x31,0x29,0x05,0x06,0x10,\r\n  0x1e,0x38,0x34,0x01,0x01,0x30,0x1e,0x1e,0x12,0x02,0x28,0x06,0x14,\r\n  0x23,0x02,0x0b,0x19,0x1e,0x1e,0x36,0x01,0x01,0x04,0x1e,0x18,0x12,\r\n  0x27,0x27,0x31,0x10,0x22,0x29,0x1e,0x13,0x13,0x13,0x02,0x18,0x1e,\r\n  0x17,0x01,0x01,0x2b,0x3e,0x1e,0x09,0x1f,0x13,0x0c,0x0c,0x27,0x27,\r\n  0x18,0x0a,0x23,0x1f,0x25,0x1e,0x3b,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x2b,0x40,0x1e,0x24,0x1f,0x13,0x16,0x1e,0x09,0x22,0x14,0x13,0x12,\r\n  0x1e,0x30,0x01,0x34,0x1e,0x18,0x1e,0x27,0x0c,0x1f,0x0c,0x22,0x1e,\r\n  0x29,0x1a,0x26,0x06,0x21,0x1e,0x2b,0x01,0x01,0x38,0x1e,0x0a,0x2a,\r\n  0x31,0x19,0x0c,0x0b,0x1f,0x1a,0x2a,0x16,0x2a,0x1e,0x38,0x01,0x01,\r\n  0x04,0x1e,0x1e,0x1e,0x1e,0x39,0x01,0x01,0x08,0x1e,0x25,0x1f,0x1f,\r\n  0x13,0x22,0x1e,0x2d,0x13,0x0c,0x19,0x0d,0x1e,0x04,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x04,0x1e,0x29,0x1f,\r\n  0x1e,0x02,0x0c,0x24,0x31,0x05,0x0c,0x1e,0x28,0x14,0x1e,0x1e,0x01,\r\n  0x01,0x1b,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x3d,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x34,0x34,0x20,0x01,0x00,0x34,0x35,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x37,0x1e,0x24,0x22,0x13,0x13,0x1a,\r\n  0x1e,0x32,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1a,0x05,\r\n  0x1f,0x0c,0x0d,0x0b,0x05,0x0d,0x0b,0x14,0x05,0x1e,0x1e,0x34,0x01,\r\n  0x01,0x3d,0x1e,0x1e,0x1e,0x09,0x28,0x19,0x26,0x06,0x02,0x26,0x29,\r\n  0x15,0x1e,0x1b,0x01,0x01,0x34,0x04,0x1e,0x1e,0x1e,0x1e,0x1e,0x14,\r\n  0x22,0x1e,0x19,0x13,0x19,0x0b,0x13,0x26,0x1e,0x0f,0x01,0x01,0x38,\r\n  0x1e,0x2a,0x13,0x13,0x1f,0x14,0x1f,0x0c,0x1f,0x1f,0x0c,0x1f,0x12,\r\n  0x1e,0x40,0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x0c,\r\n  0x1f,0x0c,0x06,0x18,0x19,0x0c,0x13,0x0b,0x12,0x1e,0x04,0x01,0x01,\r\n  0x04,0x1e,0x1e,0x15,0x0b,0x05,0x1f,0x27,0x03,0x1f,0x22,0x0c,0x23,\r\n  0x21,0x1e,0x36,0x01,0x01,0x2b,0x33,0x1e,0x1e,0x1e,0x19,0x19,0x22,\r\n  0x13,0x15,0x1e,0x1e,0x1e,0x3e,0x2b,0x01,0x20,0x1e,0x18,0x26,0x1a,\r\n  0x2d,0x1e,0x35,0x01,0x2b,0x1e,0x21,0x1f,0x13,0x05,0x22,0x27,0x05,\r\n  0x1f,0x13,0x1f,0x26,0x1e,0x3a,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x2e,0x1e,0x25,0x27,0x16,0x1e,0x29,0x22,\r\n  0x0c,0x0b,0x15,0x1e,0x0b,0x02,0x1e,0x32,0x01,0x01,0x01,0x1b,0x04,\r\n  0x39,0x1c,0x3c,0x08,0x0f,0x3b,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x2f,0x1e,0x03,0x05,0x13,0x13,0x13,0x21,0x1e,0x2b,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x20,0x1e,0x09,0x14,0x05,0x22,0x1f,0x22,0x0c,\r\n  0x1f,0x05,0x0c,0x29,0x24,0x1e,0x38,0x01,0x01,0x01,0x32,0x1e,0x06,\r\n  0x1a,0x24,0x24,0x26,0x26,0x24,0x23,0x14,0x14,0x28,0x1e,0x37,0x01,\r\n  0x01,0x01,0x01,0x2e,0x04,0x07,0x1e,0x02,0x0d,0x03,0x1e,0x13,0x13,\r\n  0x16,0x27,0x0c,0x12,0x1e,0x1c,0x01,0x01,0x1e,0x1e,0x13,0x13,0x0c,\r\n  0x22,0x18,0x23,0x19,0x0b,0x05,0x14,0x15,0x1e,0x1e,0x3a,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x13,0x05,0x05,0x13,0x05,0x0c,\r\n  0x13,0x1f,0x13,0x13,0x28,0x1e,0x1b,0x01,0x01,0x01,0x36,0x1e,0x1e,\r\n  0x1f,0x1f,0x0c,0x13,0x0c,0x23,0x0b,0x05,0x29,0x1e,0x40,0x01,0x01,\r\n  0x01,0x01,0x0e,0x3b,0x32,0x1e,0x0b,0x19,0x12,0x13,0x12,0x1e,0x30,\r\n  0x3c,0x34,0x01,0x01,0x0e,0x1e,0x10,0x13,0x1f,0x2a,0x1e,0x2f,0x01,\r\n  0x01,0x38,0x1e,0x15,0x0c,0x13,0x13,0x0c,0x0c,0x13,0x23,0x31,0x1e,\r\n  0x1e,0x17,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x35,0x40,0x1e,0x12,0x02,0x03,0x1e,0x03,0x16,0x1e,0x1e,0x1a,\r\n  0x19,0x1e,0x1e,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x32,\r\n  0x1e,0x1e,0x12,0x14,0x13,0x16,0x1e,0x08,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x00,0x1e,0x1e,0x1e,0x16,0x14,0x19,0x2d,0x10,0x14,0x23,0x0a,0x1e,\r\n  0x1e,0x1e,0x3a,0x01,0x01,0x01,0x1e,0x1e,0x23,0x14,0x29,0x27,0x19,\r\n  0x26,0x29,0x23,0x12,0x22,0x28,0x1e,0x0f,0x01,0x01,0x01,0x01,0x2b,\r\n  0x38,0x1e,0x16,0x1f,0x02,0x1e,0x2d,0x14,0x13,0x03,0x02,0x14,0x24,\r\n  0x1e,0x37,0x01,0x34,0x1e,0x18,0x13,0x22,0x0c,0x14,0x18,0x24,0x0c,\r\n  0x0c,0x1f,0x0c,0x19,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x38,0x1e,0x28,0x1f,0x23,0x23,0x05,0x0c,0x1f,0x05,0x13,0x14,\r\n  0x1e,0x1e,0x2b,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x05,0x05,0x05,\r\n  0x0c,0x05,0x05,0x02,0x1e,0x1e,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x1e,0x1e,0x1f,0x05,0x0c,0x1f,0x27,0x1e,0x32,0x01,0x01,0x01,0x01,\r\n  0x35,0x1e,0x2d,0x13,0x0c,0x03,0x1e,0x17,0x01,0x01,0x2f,0x1e,0x1e,\r\n  0x1e,0x1e,0x26,0x13,0x1f,0x13,0x13,0x12,0x1e,0x38,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x37,0x1e,\r\n  0x1e,0x05,0x14,0x0d,0x15,0x31,0x26,0x13,0x05,0x2d,0x1e,0x38,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x39,0x1e,0x03,0x0c,\r\n  0x13,0x2a,0x1e,0x2f,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3d,0x1e,0x1e,\r\n  0x24,0x05,0x0c,0x1e,0x0a,0x02,0x23,0x1e,0x1e,0x38,0x3a,0x01,0x01,\r\n  0x01,0x01,0x38,0x1e,0x03,0x14,0x15,0x28,0x1f,0x02,0x02,0x02,0x19,\r\n  0x05,0x2d,0x1e,0x17,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1f,0x1a,\r\n  0x1e,0x1e,0x2d,0x23,0x13,0x24,0x23,0x1f,0x06,0x1e,0x37,0x01,0x01,\r\n  0x3e,0x1e,0x22,0x0c,0x14,0x0b,0x14,0x14,0x14,0x0c,0x05,0x05,0x13,\r\n  0x0c,0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x1e,0x1e,\r\n  0x2d,0x1e,0x1e,0x1e,0x1e,0x16,0x28,0x31,0x1e,0x1e,0x2c,0x01,0x01,\r\n  0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x28,0x16,0x03,0x1e,0x1e,\r\n  0x1e,0x2c,0x20,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x30,0x01,0x01,0x01,0x01,0x35,0x1e,0x2d,0x0c,\r\n  0x13,0x03,0x1e,0x17,0x01,0x01,0x3d,0x1e,0x26,0x1a,0x27,0x26,0x1e,\r\n  0x19,0x13,0x0c,0x0c,0x21,0x1e,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x39,0x1e,0x1e,0x28,0x22,\r\n  0x1f,0x05,0x0c,0x27,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x3c,0x1e,0x2a,0x05,0x13,0x03,0x1e,0x04,\r\n  0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x1e,0x21,0x02,0x13,0x1a,0x1e,\r\n  0x0c,0x23,0x02,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x3e,\r\n  0x1e,0x0a,0x14,0x0b,0x27,0x29,0x0b,0x06,0x28,0x2d,0x1e,0x38,0x01,\r\n  0x01,0x01,0x01,0x01,0x1e,0x1e,0x24,0x05,0x03,0x1e,0x38,0x1e,0x29,\r\n  0x13,0x0b,0x13,0x22,0x2d,0x1e,0x2f,0x01,0x01,0x3d,0x1e,0x18,0x19,\r\n  0x05,0x0b,0x0b,0x05,0x27,0x28,0x22,0x14,0x1f,0x05,0x0c,0x2d,0x1e,\r\n  0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x3e,0x1d,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x40,0x2c,0x20,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x20,0x2c,0x40,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x37,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x32,0x30,\r\n  0x01,0x01,0x01,0x01,0x01,0x35,0x1e,0x2d,0x13,0x1f,0x03,0x1e,0x17,\r\n  0x01,0x01,0x32,0x1e,0x0b,0x13,0x14,0x0c,0x10,0x0b,0x0c,0x1f,0x0c,\r\n  0x31,0x1e,0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x35,0x39,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x3c,0x1e,0x2a,0x13,0x13,0x12,0x1e,0x1e,0x04,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x37,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x33,0x1e,0x1e,0x1e,\r\n  0x0a,0x0d,0x10,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x38,0x1e,0x28,0x0a,0x1e,0x32,0x2e,0x1e,0x1e,0x21,0x28,0x16,0x1e,\r\n  0x1e,0x38,0x01,0x01,0x01,0x00,0x38,0x1e,0x1e,0x31,0x28,0x25,0x10,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x35,0x01,0x01,0x01,0x34,0x3c,0x1b,0x36,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,\r\n  0x1b,0x08,0x2f,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x35,0x1e,0x2d,0x0c,0x0c,0x03,0x1e,0x17,0x01,0x01,0x3d,0x1e,\r\n  0x28,0x0c,0x05,0x13,0x13,0x14,0x1f,0x19,0x05,0x1e,0x40,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x3a,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x08,0x1e,0x16,\r\n  0x1f,0x13,0x13,0x22,0x1e,0x07,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,\r\n  0x38,0x1e,0x1e,0x38,0x38,0x1e,0x1e,0x38,0x37,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x21,0x28,0x18,0x1e,\r\n  0x1d,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x33,0x1e,0x1e,\r\n  0x33,0x2b,0x01,0x2e,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,\r\n  0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x36,0x1e,0x31,\r\n  0x13,0x22,0x25,0x1e,0x08,0x01,0x01,0x2f,0x1e,0x1e,0x2a,0x05,0x13,\r\n  0x13,0x27,0x0c,0x0d,0x1e,0x1e,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x1e,0x10,0x05,0x13,0x13,0x0c,\r\n  0x1e,0x1e,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x04,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x2e,0x2e,0x0e,0x01,0x01,0x01,\r\n  0x01,0x2b,0x2e,0x08,0x20,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x36,0x2e,0x08,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x40,\r\n  0x35,0x01,0x01,0x01,0x2f,0x3e,0x1e,0x1e,0x1e,0x03,0x1e,0x1e,0x1e,\r\n  0x1e,0x2c,0x20,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x38,0x1e,0x1e,0x06,0x27,0x15,0x1e,0x39,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x3c,0x37,0x3c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,\r\n  0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2e,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,\r\n  0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x36,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x00,0x17,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2f,0x0f,0x2c,\r\n  0x1b,0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x1b,0x1b,0x2e,\r\n  0x2e,0x2e,0x2e,0x2e,0x2e,0x1b,0x17,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x17,0x00,0x01,0x01,0x01,\r\n  0x01,0x01,0x34,0x17,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x08,0x1c,0x1d,0x3d,0x3a,\r\n  0x17,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,\r\n  0x1e,0x38,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x2b,0x38,0x1e,0x1e,0x38,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x1c,0x38,0x1e,0x38,0x1e,0x1e,0x1d,0x30,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x38,\r\n  0x3a,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x34,0x04,0x3e,0x38,0x37,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x08,0x38,0x1e,0x40,0x38,0x1e,0x1d,0x1c,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3a,0x2c,0x3e,0x3d,0x2e,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x00,0x35,0x01,0x34,0x20,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x08,0x11,0x33,0x11,0x17,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x0f,0x38,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x3d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x32,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x2b,0x39,0x1e,0x1e,0x1e,0x30,0x01,0x01,0x01,0x04,0x1e,0x1e,\r\n  0x1e,0x11,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x30,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x35,0x33,0x1e,0x1e,0x1e,0x1e,0x30,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x32,0x1e,0x1e,0x1e,\r\n  0x1e,0x39,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x08,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x3a,0x1e,0x1e,0x1e,0x1e,0x1e,0x2e,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x30,0x1e,0x3e,0x3d,0x3b,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x3d,\r\n  0x32,0x1e,0x2c,0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,\r\n  0x1e,0x1e,0x38,0x1e,0x1e,0x38,0x08,0x01,0x01,0x01,0x01,0x01,0x3d,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x17,0x01,0x01,0x01,0x01,0x01,0x0f,0x1e,\r\n  0x1e,0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,\r\n  0x1e,0x1e,0x28,0x15,0x28,0x28,0x28,0x28,0x28,0x28,0x15,0x03,0x1e,\r\n  0x3d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3c,0x38,0x1e,0x1e,0x1e,\r\n  0x03,0x1e,0x1e,0x00,0x01,0x34,0x1e,0x18,0x31,0x18,0x1e,0x1e,0x11,\r\n  0x3c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x1e,0x1e,0x09,\r\n  0x25,0x26,0x0b,0x29,0x26,0x21,0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,\r\n  0x01,0x20,0x1e,0x09,0x13,0x13,0x10,0x13,0x13,0x21,0x1e,0x2b,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,0x27,0x13,0x13,\r\n  0x28,0x1e,0x2e,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x23,0x13,\r\n  0x26,0x13,0x13,0x0b,0x1e,0x1d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x3b,0x1e,0x0a,0x13,0x02,0x1e,0x1e,0x36,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x38,0x1e,0x03,0x14,0x23,0x2d,0x1e,0x3a,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x30,0x1e,0x29,0x13,0x05,0x12,0x13,\r\n  0x0b,0x1e,0x1d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x1e,\r\n  0x1e,0x27,0x14,0x0d,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x1b,0x1e,0x1e,0x1e,0x1e,0x1e,0x3b,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x40,0x1e,0x1e,0x1e,0x1e,0x2c,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x2d,0x1e,0x18,\r\n  0x09,0x1e,0x1e,0x08,0x01,0x01,0x01,0x00,0x1e,0x1e,0x29,0x0c,0x26,\r\n  0x1e,0x38,0x00,0x01,0x01,0x01,0x01,0x38,0x1e,0x19,0x13,0x1e,0x1e,\r\n  0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x1e,0x2d,0x13,0x13,\r\n  0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x14,0x1e,0x3e,0x01,0x01,0x01,\r\n  0x01,0x20,0x1b,0x38,0x1e,0x1e,0x09,0x15,0x22,0x13,0x2d,0x1e,0x35,\r\n  0x01,0x17,0x1e,0x03,0x19,0x1f,0x28,0x2d,0x1e,0x1e,0x38,0x3a,0x00,\r\n  0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x28,0x13,0x13,0x13,0x13,0x13,\r\n  0x13,0x13,0x13,0x1e,0x1e,0x3c,0x01,0x01,0x01,0x01,0x34,0x1e,0x18,\r\n  0x05,0x13,0x18,0x13,0x13,0x2d,0x1e,0x35,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x34,0x1e,0x1e,0x13,0x13,0x26,0x05,0x13,0x2a,0x1e,0x2f,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x1c,0x1e,0x12,0x13,0x2a,0x19,0x13,0x29,\r\n  0x1e,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x1e,0x18,0x13,\r\n  0x13,0x15,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3b,\r\n  0x1e,0x1e,0x13,0x13,0x13,0x27,0x1e,0x07,0x20,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x1b,0x1e,0x15,0x13,0x1a,0x26,0x13,0x12,0x1e,0x1c,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x28,0x13,0x13,0x13,\r\n  0x09,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x1e,0x1a,\r\n  0x14,0x29,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x2c,0x1e,0x25,0x0b,0x22,0x1e,0x40,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,0x21,0x13,0x13,0x29,0x1e,0x30,\r\n  0x01,0x01,0x01,0x01,0x3d,0x1e,0x03,0x13,0x13,0x09,0x1e,0x3d,0x01,\r\n  0x01,0x01,0x34,0x1e,0x18,0x13,0x13,0x21,0x1e,0x38,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x20,0x1e,0x18,0x05,0x13,0x0c,0x13,0x13,0x13,\r\n  0x13,0x13,0x13,0x27,0x1e,0x2c,0x01,0x01,0x01,0x37,0x40,0x1e,0x1e,\r\n  0x21,0x24,0x13,0x0c,0x13,0x1f,0x18,0x1e,0x34,0x01,0x0e,0x1e,0x10,\r\n  0x1f,0x1f,0x12,0x23,0x24,0x21,0x1e,0x1e,0x3e,0x0f,0x01,0x01,0x01,\r\n  0x2f,0x1e,0x09,0x14,0x13,0x0c,0x23,0x23,0x0c,0x13,0x13,0x13,0x24,\r\n  0x1e,0x37,0x01,0x01,0x01,0x01,0x01,0x04,0x1e,0x21,0x28,0x1e,0x31,\r\n  0x25,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x3d,0x1e,0x1e,0x1e,\r\n  0x31,0x25,0x2d,0x03,0x16,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,\r\n  0x01,0x1c,0x1e,0x18,0x26,0x18,0x21,0x28,0x18,0x1e,0x04,0x34,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x13,0x13,0x09,0x1e,\r\n  0x20,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x30,0x1e,0x29,0x13,0x12,\r\n  0x27,0x22,0x16,0x1e,0x3c,0x01,0x01,0x01,0x01,0x01,0x01,0x36,0x1e,\r\n  0x1e,0x28,0x18,0x18,0x28,0x09,0x1e,0x08,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,0x03,0x13,0x13,0x1e,0x1e,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x1b,0x1e,0x10,0x13,0x13,0x1e,0x1e,\r\n  0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2f,0x1e,0x1e,\r\n  0x14,0x1f,0x26,0x1e,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,\r\n  0x1e,0x27,0x14,0x1e,0x1f,0x13,0x0a,0x1e,0x3b,0x01,0x01,0x01,0x01,\r\n  0x01,0x1d,0x1e,0x03,0x13,0x22,0x1e,0x32,0x01,0x01,0x01,0x01,0x38,\r\n  0x1e,0x25,0x1a,0x22,0x1e,0x1e,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x38,0x1e,0x18,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1b,0x01,0x01,0x1d,0x1e,0x1e,0x25,0x27,0x0c,0x0c,0x13,0x1f,\r\n  0x05,0x15,0x1e,0x38,0x01,0x01,0x01,0x38,0x1e,0x28,0x14,0x14,0x1f,\r\n  0x14,0x22,0x0d,0x03,0x1e,0x1e,0x38,0x01,0x01,0x37,0x1e,0x24,0x0b,\r\n  0x02,0x1f,0x19,0x1e,0x31,0x13,0x13,0x0b,0x0d,0x1e,0x2c,0x01,0x01,\r\n  0x01,0x01,0x37,0x1e,0x1e,0x1e,0x1e,0x18,0x1e,0x1e,0x09,0x1e,0x38,\r\n  0x01,0x01,0x01,0x01,0x1b,0x1e,0x1e,0x10,0x09,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x18,0x2d,0x2d,0x1e,0x38,0x01,0x01,0x34,0x04,0x1e,0x1e,0x09,\r\n  0x2d,0x0d,0x26,0x03,0x1e,0x1e,0x1e,0x39,0x35,0x01,0x01,0x01,0x01,\r\n  0x2b,0x38,0x1e,0x1e,0x1e,0x21,0x14,0x2d,0x1e,0x1d,0x2b,0x01,0x01,\r\n  0x01,0x01,0x01,0x2b,0x38,0x1e,0x02,0x19,0x1e,0x1e,0x05,0x25,0x1e,\r\n  0x08,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x2d,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x32,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x1e,\r\n  0x10,0x1f,0x10,0x1e,0x15,0x14,0x1e,0x07,0x2b,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x38,0x1e,0x1e,0x13,0x13,0x1e,0x1e,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x37,0x1e,0x06,0x1f,0x26,0x1e,0x1e,\r\n  0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x2a,0x1e,\r\n  0x10,0x31,0x1e,0x33,0x1b,0x01,0x01,0x01,0x01,0x01,0x11,0x1e,0x1e,\r\n  0x2a,0x23,0x1e,0x1d,0x20,0x01,0x01,0x01,0x2b,0x1e,0x1e,0x15,0x06,\r\n  0x25,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x25,\r\n  0x25,0x16,0x16,0x16,0x16,0x16,0x16,0x25,0x21,0x1e,0x0f,0x01,0x3b,\r\n  0x1e,0x03,0x23,0x14,0x13,0x1f,0x0c,0x02,0x0a,0x1e,0x1e,0x1e,0x36,\r\n  0x01,0x01,0x01,0x2b,0x1e,0x1e,0x1e,0x25,0x02,0x14,0x23,0x0b,0x23,\r\n  0x12,0x21,0x1e,0x08,0x01,0x37,0x1e,0x06,0x0b,0x23,0x14,0x27,0x1e,\r\n  0x29,0x19,0x05,0x02,0x03,0x1e,0x3a,0x01,0x01,0x01,0x01,0x38,0x1e,\r\n  0x23,0x13,0x13,0x13,0x13,0x13,0x13,0x1e,0x1e,0x01,0x01,0x01,0x01,\r\n  0x2c,0x1e,0x1a,0x13,0x13,0x13,0x13,0x1e,0x0d,0x13,0x13,0x13,0x13,\r\n  0x1e,0x1e,0x01,0x01,0x04,0x1e,0x1e,0x0b,0x05,0x14,0x13,0x05,0x14,\r\n  0x13,0x22,0x1e,0x1e,0x39,0x01,0x01,0x01,0x0e,0x38,0x1e,0x10,0x24,\r\n  0x1a,0x26,0x16,0x26,0x31,0x1e,0x3e,0x2b,0x01,0x01,0x01,0x35,0x38,\r\n  0x1e,0x2d,0x03,0x16,0x0d,0x12,0x21,0x18,0x1e,0x3e,0x2b,0x01,0x01,\r\n  0x01,0x01,0x36,0x1e,0x1e,0x14,0x13,0x0c,0x13,0x05,0x14,0x2a,0x1e,\r\n  0x2f,0x01,0x01,0x01,0x01,0x01,0x2b,0x1e,0x1e,0x09,0x03,0x06,0x1a,\r\n  0x28,0x03,0x21,0x1e,0x3e,0x2b,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,\r\n  0x1e,0x1e,0x06,0x22,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x2b,0x38,0x1e,0x1e,0x0d,0x27,0x1e,0x1e,0x1e,0x3e,0x3c,0x01,0x01,\r\n  0x01,0x01,0x01,0x38,0x1e,0x09,0x25,0x15,0x24,0x28,0x26,0x31,0x1e,\r\n  0x1e,0x1b,0x01,0x01,0x01,0x2e,0x1e,0x10,0x26,0x2d,0x2d,0x31,0x1e,\r\n  0x2c,0x01,0x01,0x01,0x01,0x38,0x1e,0x31,0x14,0x1a,0x1e,0x1e,0x2f,\r\n  0x01,0x01,0x01,0x01,0x01,0x20,0x1e,0x09,0x06,0x12,0x19,0x22,0x13,\r\n  0x13,0x22,0x23,0x0c,0x02,0x1e,0x39,0x01,0x3d,0x1e,0x0d,0x13,0x13,\r\n  0x0c,0x06,0x1e,0x1e,0x1e,0x33,0x39,0x36,0x01,0x01,0x01,0x01,0x01,\r\n  0x2b,0x2c,0x33,0x1e,0x1e,0x1e,0x29,0x23,0x26,0x27,0x06,0x1e,0x1c,\r\n  0x01,0x0f,0x1e,0x06,0x15,0x2a,0x0b,0x24,0x26,0x14,0x22,0x22,0x1a,\r\n  0x1e,0x07,0x20,0x01,0x01,0x01,0x01,0x38,0x1e,0x23,0x13,0x13,0x13,\r\n  0x13,0x13,0x13,0x09,0x1e,0x36,0x01,0x01,0x01,0x3a,0x1e,0x26,0x13,\r\n  0x13,0x13,0x14,0x1e,0x28,0x13,0x13,0x0c,0x0c,0x1e,0x1e,0x01,0x01,\r\n  0x07,0x1e,0x0b,0x0c,0x0c,0x13,0x1f,0x14,0x13,0x14,0x14,0x1f,0x1e,\r\n  0x40,0x01,0x01,0x01,0x11,0x1e,0x2d,0x02,0x24,0x14,0x13,0x13,0x05,\r\n  0x05,0x2a,0x1e,0x38,0x01,0x01,0x01,0x39,0x1e,0x10,0x13,0x13,0x0c,\r\n  0x13,0x0c,0x13,0x1f,0x03,0x1e,0x38,0x01,0x01,0x01,0x01,0x04,0x1e,\r\n  0x15,0x13,0x14,0x14,0x13,0x05,0x02,0x15,0x1e,0x0f,0x01,0x01,0x01,\r\n  0x01,0x01,0x38,0x1e,0x28,0x13,0x05,0x05,0x13,0x13,0x13,0x13,0x2a,\r\n  0x1e,0x38,0x01,0x01,0x01,0x2b,0x32,0x1e,0x10,0x06,0x1a,0x25,0x16,\r\n  0x24,0x21,0x1e,0x07,0x2b,0x01,0x01,0x01,0x0e,0x38,0x1e,0x09,0x26,\r\n  0x15,0x2a,0x29,0x29,0x2a,0x1e,0x1e,0x3c,0x01,0x01,0x01,0x1c,0x1e,\r\n  0x09,0x0c,0x19,0x05,0x05,0x14,0x14,0x0b,0x1a,0x1e,0x1e,0x36,0x01,\r\n  0x01,0x04,0x1e,0x29,0x13,0x13,0x13,0x05,0x1e,0x07,0x01,0x01,0x01,\r\n  0x01,0x2b,0x1e,0x1e,0x02,0x22,0x26,0x1e,0x11,0x01,0x01,0x01,0x01,\r\n  0x01,0x20,0x1e,0x09,0x19,0x02,0x22,0x1f,0x13,0x13,0x1f,0x0b,0x14,\r\n  0x1a,0x1e,0x2c,0x01,0x2c,0x1e,0x27,0x1f,0x1f,0x13,0x23,0x16,0x1e,\r\n  0x1e,0x1e,0x38,0x0f,0x01,0x01,0x01,0x01,0x01,0x0f,0x38,0x1e,0x1e,\r\n  0x1e,0x2a,0x02,0x14,0x05,0x14,0x15,0x1e,0x3d,0x01,0x0f,0x1e,0x15,\r\n  0x23,0x02,0x0b,0x12,0x10,0x24,0x25,0x05,0x27,0x16,0x1e,0x04,0x01,\r\n  0x01,0x01,0x36,0x1e,0x21,0x13,0x13,0x13,0x22,0x13,0x13,0x13,0x26,\r\n  0x1e,0x30,0x01,0x01,0x01,0x0f,0x1e,0x26,0x13,0x13,0x13,0x05,0x1e,\r\n  0x28,0x13,0x1f,0x19,0x13,0x1e,0x1e,0x01,0x0e,0x1e,0x10,0x1f,0x13,\r\n  0x02,0x14,0x16,0x15,0x0c,0x0c,0x0c,0x1f,0x21,0x1e,0x2b,0x01,0x01,\r\n  0x33,0x1e,0x0b,0x0b,0x0c,0x14,0x12,0x05,0x0b,0x26,0x22,0x09,0x1e,\r\n  0x20,0x01,0x01,0x33,0x1e,0x1f,0x13,0x0c,0x0c,0x1a,0x05,0x0c,0x13,\r\n  0x1f,0x18,0x1e,0x34,0x01,0x01,0x01,0x07,0x1e,0x23,0x0c,0x0c,0x05,\r\n  0x22,0x23,0x13,0x0d,0x1e,0x11,0x01,0x01,0x01,0x01,0x0e,0x1e,0x10,\r\n  0x27,0x0c,0x0b,0x26,0x12,0x13,0x13,0x1f,0x1f,0x1e,0x1e,0x0e,0x01,\r\n  0x01,0x38,0x1e,0x2a,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x16,0x1e,\r\n  0x38,0x01,0x01,0x01,0x39,0x1e,0x10,0x0c,0x13,0x1f,0x0b,0x0c,0x0c,\r\n  0x22,0x24,0x1e,0x38,0x01,0x01,0x01,0x1d,0x1e,0x23,0x05,0x22,0x0c,\r\n  0x26,0x0d,0x0c,0x02,0x19,0x15,0x1e,0x0f,0x01,0x01,0x0f,0x1e,0x0a,\r\n  0x22,0x13,0x13,0x1a,0x1e,0x2c,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,\r\n  0x2d,0x28,0x0d,0x1e,0x1e,0x3c,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,\r\n  0x18,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1b,0x01,\r\n  0x1b,0x1e,0x18,0x06,0x13,0x05,0x22,0x0c,0x1f,0x0d,0x18,0x1e,0x1e,\r\n  0x0f,0x01,0x01,0x01,0x04,0x1e,0x1e,0x09,0x1a,0x14,0x05,0x0c,0x29,\r\n  0x0d,0x15,0x18,0x1e,0x3b,0x01,0x0f,0x1e,0x15,0x28,0x06,0x14,0x19,\r\n  0x1e,0x28,0x0b,0x22,0x0d,0x02,0x1e,0x07,0x01,0x01,0x01,0x08,0x1e,\r\n  0x25,0x13,0x13,0x13,0x25,0x13,0x13,0x13,0x22,0x1e,0x32,0x01,0x01,\r\n  0x01,0x0f,0x1e,0x26,0x13,0x13,0x13,0x05,0x1e,0x28,0x13,0x13,0x0c,\r\n  0x13,0x1e,0x1e,0x01,0x17,0x1e,0x31,0x0c,0x0c,0x1f,0x13,0x1e,0x1e,\r\n  0x13,0x27,0x0b,0x0c,0x03,0x1e,0x2f,0x01,0x20,0x1e,0x18,0x0d,0x26,\r\n  0x28,0x09,0x1e,0x0b,0x05,0x1f,0x0c,0x21,0x1e,0x36,0x01,0x00,0x1e,\r\n  0x1e,0x24,0x0d,0x26,0x10,0x1e,0x23,0x13,0x05,0x13,0x21,0x1e,0x2b,\r\n  0x01,0x01,0x01,0x1e,0x1e,0x1f,0x13,0x27,0x1a,0x29,0x19,0x05,0x14,\r\n  0x1e,0x1e,0x00,0x01,0x01,0x01,0x3b,0x1e,0x0a,0x05,0x0c,0x05,0x12,\r\n  0x1e,0x0d,0x0b,0x14,0x06,0x0a,0x1e,0x3b,0x01,0x36,0x1e,0x1e,0x13,\r\n  0x13,0x13,0x13,0x1a,0x13,0x13,0x13,0x13,0x10,0x1e,0x0e,0x01,0x01,\r\n  0x33,0x1e,0x1f,0x1f,0x0c,0x13,0x0d,0x14,0x0c,0x13,0x05,0x2d,0x1e,\r\n  0x0f,0x01,0x35,0x1e,0x2d,0x1f,0x0c,0x22,0x0b,0x1e,0x10,0x22,0x14,\r\n  0x1f,0x24,0x1e,0x39,0x01,0x01,0x0f,0x1e,0x26,0x0c,0x19,0x0b,0x0d,\r\n  0x1e,0x2c,0x01,0x01,0x01,0x01,0x01,0x2b,0x33,0x1e,0x23,0x19,0x06,\r\n  0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x3d,0x01,0x01,0x01,0x3d,0x1e,0x1e,\r\n  0x18,0x25,0x13,0x0c,0x0c,0x13,0x0b,0x0d,0x1e,0x38,0x01,0x01,0x34,\r\n  0x1e,0x18,0x29,0x12,0x05,0x14,0x23,0x1f,0x2a,0x1e,0x1e,0x1e,0x3d,\r\n  0x01,0x01,0x0f,0x1e,0x26,0x22,0x22,0x26,0x06,0x1e,0x25,0x29,0x1f,\r\n  0x02,0x23,0x1e,0x1e,0x01,0x01,0x01,0x1c,0x1e,0x06,0x13,0x13,0x13,\r\n  0x1e,0x13,0x13,0x13,0x1f,0x1e,0x33,0x01,0x01,0x01,0x0f,0x1e,0x26,\r\n  0x13,0x13,0x13,0x05,0x1e,0x28,0x13,0x0c,0x0c,0x13,0x1e,0x1e,0x01,\r\n  0x3c,0x1e,0x2a,0x0c,0x05,0x02,0x0c,0x18,0x2d,0x0c,0x1f,0x0c,0x05,\r\n  0x16,0x1e,0x08,0x01,0x01,0x04,0x1e,0x1e,0x2a,0x26,0x26,0x24,0x05,\r\n  0x0b,0x02,0x13,0x10,0x1e,0x2b,0x01,0x01,0x3d,0x1e,0x1e,0x31,0x15,\r\n  0x06,0x02,0x22,0x13,0x1f,0x0c,0x10,0x1e,0x0e,0x01,0x01,0x2f,0x1e,\r\n  0x1e,0x1f,0x0c,0x1f,0x12,0x2a,0x22,0x0c,0x24,0x10,0x1e,0x17,0x01,\r\n  0x01,0x01,0x0f,0x1e,0x15,0x0d,0x05,0x0b,0x1a,0x23,0x05,0x0b,0x14,\r\n  0x0c,0x29,0x1e,0x30,0x01,0x3a,0x1e,0x26,0x13,0x13,0x13,0x14,0x1e,\r\n  0x26,0x13,0x13,0x13,0x16,0x1e,0x1b,0x01,0x34,0x1e,0x1e,0x05,0x05,\r\n  0x13,0x23,0x1e,0x15,0x05,0x0c,0x13,0x27,0x1e,0x11,0x01,0x17,0x1e,\r\n  0x03,0x05,0x27,0x05,0x23,0x26,0x0d,0x14,0x22,0x05,0x22,0x1e,0x3e,\r\n  0x01,0x01,0x0f,0x1e,0x28,0x13,0x05,0x0b,0x0d,0x1e,0x2c,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x39,0x1e,0x1e,0x0b,0x23,0x1e,0x1e,0x17,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x34,0x00,0x01,0x01,0x01,0x01,0x01,0x2f,0x38,0x1e,0x1e,0x1e,0x21,\r\n  0x22,0x13,0x13,0x0c,0x1e,0x1e,0x00,0x01,0x35,0x1e,0x2d,0x0c,0x0c,\r\n  0x1f,0x1a,0x21,0x1e,0x1e,0x1e,0x38,0x36,0x01,0x01,0x01,0x0f,0x1e,\r\n  0x15,0x12,0x22,0x27,0x12,0x1e,0x0a,0x14,0x24,0x12,0x22,0x1e,0x1e,\r\n  0x01,0x01,0x01,0x1d,0x1e,0x26,0x1f,0x13,0x13,0x1e,0x13,0x13,0x13,\r\n  0x13,0x21,0x1e,0x3c,0x01,0x01,0x0f,0x1e,0x26,0x13,0x13,0x13,0x05,\r\n  0x1e,0x28,0x13,0x1f,0x0c,0x05,0x1e,0x1e,0x01,0x37,0x1e,0x06,0x0c,\r\n  0x13,0x13,0x05,0x18,0x09,0x14,0x02,0x0c,0x0c,0x26,0x1e,0x37,0x01,\r\n  0x01,0x1d,0x1e,0x1a,0x22,0x1f,0x0c,0x14,0x14,0x05,0x0c,0x19,0x10,\r\n  0x1e,0x2b,0x01,0x34,0x07,0x1e,0x29,0x13,0x23,0x1f,0x0c,0x1a,0x0c,\r\n  0x19,0x0c,0x10,0x1e,0x0e,0x01,0x01,0x38,0x1e,0x26,0x0c,0x14,0x02,\r\n  0x26,0x2d,0x22,0x0b,0x14,0x28,0x1e,0x0f,0x01,0x01,0x01,0x37,0x1e,\r\n  0x06,0x14,0x14,0x05,0x1f,0x19,0x24,0x29,0x29,0x29,0x25,0x1e,0x3b,\r\n  0x01,0x3a,0x1e,0x26,0x13,0x13,0x13,0x1f,0x19,0x05,0x13,0x13,0x13,\r\n  0x1a,0x1e,0x04,0x01,0x2f,0x1e,0x2a,0x1f,0x22,0x13,0x05,0x02,0x05,\r\n  0x05,0x13,0x0c,0x22,0x1e,0x07,0x01,0x2f,0x1e,0x2a,0x13,0x23,0x22,\r\n  0x05,0x05,0x0b,0x06,0x29,0x27,0x15,0x1e,0x3d,0x01,0x01,0x0f,0x1e,\r\n  0x26,0x19,0x12,0x14,0x29,0x1e,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x35,0x38,0x1e,0x12,0x0d,0x15,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x09,0x19,0x0c,\r\n  0x2d,0x1e,0x35,0x01,0x3c,0x1e,0x2a,0x22,0x27,0x18,0x1e,0x1e,0x1e,\r\n  0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x0f,0x1e,0x28,0x27,0x05,0x12,\r\n  0x0d,0x1e,0x24,0x22,0x0d,0x12,0x14,0x1e,0x1e,0x01,0x01,0x0e,0x1e,\r\n  0x10,0x0c,0x0c,0x02,0x22,0x1e,0x1a,0x13,0x13,0x13,0x24,0x1e,0x37,\r\n  0x01,0x01,0x0f,0x1e,0x26,0x13,0x13,0x13,0x05,0x1e,0x28,0x0c,0x02,\r\n  0x0c,0x1f,0x1e,0x1e,0x01,0x08,0x1e,0x25,0x13,0x1f,0x1f,0x13,0x18,\r\n  0x09,0x0c,0x13,0x05,0x27,0x15,0x1e,0x3a,0x01,0x36,0x1e,0x31,0x27,\r\n  0x05,0x05,0x26,0x1e,0x0d,0x0b,0x1f,0x0c,0x10,0x1e,0x2b,0x01,0x3c,\r\n  0x1e,0x16,0x13,0x05,0x27,0x02,0x1e,0x12,0x13,0x1f,0x13,0x10,0x1e,\r\n  0x0e,0x01,0x01,0x1e,0x1e,0x05,0x1f,0x0c,0x13,0x10,0x1e,0x05,0x0b,\r\n  0x06,0x12,0x1e,0x39,0x01,0x01,0x01,0x0f,0x1e,0x0a,0x22,0x0c,0x0b,\r\n  0x2a,0x1e,0x09,0x2a,0x03,0x25,0x10,0x1e,0x17,0x01,0x1b,0x1e,0x15,\r\n  0x13,0x22,0x13,0x13,0x0c,0x14,0x0d,0x27,0x19,0x26,0x1e,0x3a,0x01,\r\n  0x0f,0x1e,0x26,0x0c,0x13,0x0c,0x19,0x0c,0x23,0x29,0x1a,0x02,0x26,\r\n  0x1e,0x04,0x01,0x36,0x1e,0x31,0x0c,0x05,0x13,0x27,0x1e,0x1e,0x16,\r\n  0x03,0x2a,0x03,0x1e,0x0f,0x01,0x01,0x0f,0x1e,0x26,0x0c,0x0b,0x22,\r\n  0x1a,0x1e,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1c,0x1e,0x09,\r\n  0x26,0x27,0x2d,0x1e,0x2f,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x20,0x2c,0x40,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,\r\n  0x34,0x3e,0x1e,0x1e,0x1e,0x1e,0x40,0x2c,0x20,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x0f,0x1e,0x0a,0x28,0x1f,0x02,0x12,0x16,0x19,0x05,\r\n  0x12,0x02,0x0b,0x1e,0x40,0x01,0x01,0x08,0x1e,0x16,0x27,0x13,0x14,\r\n  0x0b,0x2a,0x23,0x13,0x13,0x22,0x19,0x1e,0x38,0x01,0x01,0x0f,0x1e,\r\n  0x06,0x13,0x13,0x13,0x14,0x1e,0x28,0x13,0x0c,0x0c,0x0c,0x1e,0x1e,\r\n  0x01,0x2b,0x1e,0x21,0x13,0x05,0x13,0x1f,0x18,0x09,0x22,0x14,0x13,\r\n  0x23,0x03,0x1e,0x2f,0x01,0x17,0x1e,0x03,0x27,0x02,0x0c,0x0d,0x21,\r\n  0x27,0x22,0x13,0x1a,0x21,0x1e,0x2b,0x01,0x3a,0x1e,0x26,0x0c,0x13,\r\n  0x05,0x0d,0x09,0x1f,0x0b,0x27,0x13,0x09,0x1e,0x0e,0x01,0x01,0x1e,\r\n  0x1e,0x1f,0x13,0x22,0x14,0x12,0x15,0x22,0x1f,0x0c,0x0b,0x1e,0x1e,\r\n  0x00,0x01,0x01,0x08,0x1e,0x16,0x1f,0x19,0x22,0x19,0x1e,0x02,0x0c,\r\n  0x23,0x05,0x26,0x1e,0x0f,0x01,0x37,0x1e,0x24,0x13,0x0c,0x13,0x27,\r\n  0x1e,0x18,0x0a,0x03,0x16,0x21,0x1e,0x36,0x01,0x17,0x1e,0x31,0x1f,\r\n  0x1f,0x13,0x1a,0x1e,0x1e,0x2a,0x2a,0x03,0x03,0x1e,0x0f,0x01,0x35,\r\n  0x1e,0x2d,0x1f,0x22,0x0c,0x23,0x09,0x06,0x14,0x05,0x0b,0x29,0x1e,\r\n  0x11,0x01,0x01,0x0f,0x1e,0x06,0x1a,0x19,0x13,0x29,0x1e,0x2c,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x24,0x22,0x28,0x1e,\r\n  0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x37,0x38,0x1e,0x38,0x2b,0x01,0x01,0x01,0x2b,0x38,0x1e,\r\n  0x38,0x37,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x39,\r\n  0x1e,0x0d,0x0b,0x27,0x29,0x27,0x15,0x28,0x1f,0x02,0x27,0x1e,0x1e,\r\n  0x39,0x01,0x01,0x30,0x1e,0x24,0x13,0x23,0x0d,0x1f,0x22,0x13,0x13,\r\n  0x13,0x22,0x14,0x1e,0x40,0x01,0x01,0x1b,0x1e,0x15,0x13,0x13,0x13,\r\n  0x22,0x1e,0x03,0x05,0x22,0x0c,0x1f,0x1e,0x1e,0x01,0x2f,0x1e,0x2a,\r\n  0x13,0x23,0x05,0x0c,0x1e,0x1e,0x05,0x0c,0x0c,0x05,0x16,0x1e,0x3c,\r\n  0x01,0x17,0x1e,0x03,0x14,0x0c,0x14,0x27,0x0c,0x19,0x12,0x13,0x05,\r\n  0x18,0x1e,0x3d,0x01,0x08,0x1e,0x25,0x13,0x05,0x22,0x1f,0x1f,0x1f,\r\n  0x13,0x1f,0x13,0x21,0x1e,0x11,0x01,0x08,0x1e,0x10,0x1f,0x0c,0x05,\r\n  0x0c,0x0c,0x05,0x13,0x19,0x02,0x05,0x03,0x1e,0x17,0x01,0x01,0x20,\r\n  0x1e,0x18,0x0c,0x19,0x12,0x13,0x05,0x22,0x14,0x14,0x13,0x1e,0x1e,\r\n  0x17,0x01,0x3c,0x1e,0x03,0x13,0x1f,0x13,0x14,0x1e,0x1a,0x1f,0x1f,\r\n  0x14,0x0a,0x1e,0x3b,0x01,0x01,0x1e,0x1e,0x0c,0x13,0x0b,0x23,0x10,\r\n  0x1a,0x1f,0x1f,0x1f,0x02,0x1e,0x11,0x01,0x01,0x11,0x1e,0x06,0x0b,\r\n  0x05,0x29,0x02,0x1f,0x0b,0x22,0x0b,0x15,0x1e,0x0f,0x01,0x01,0x0f,\r\n  0x1e,0x26,0x05,0x22,0x14,0x0d,0x1e,0x39,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x08,0x1e,0x09,0x19,0x02,0x09,0x1e,0x37,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3a,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x39,0x35,0x01,0x01,0x1d,\r\n  0x1e,0x27,0x23,0x1f,0x23,0x0b,0x05,0x14,0x13,0x22,0x1f,0x14,0x31,\r\n  0x1e,0x17,0x01,0x08,0x1e,0x25,0x13,0x22,0x13,0x0c,0x0d,0x23,0x13,\r\n  0x13,0x0c,0x0c,0x1e,0x1e,0x01,0x20,0x1e,0x09,0x0c,0x13,0x0c,0x0b,\r\n  0x24,0x1a,0x02,0x05,0x1f,0x22,0x18,0x1e,0x20,0x01,0x00,0x32,0x1e,\r\n  0x0d,0x05,0x14,0x22,0x27,0x12,0x0c,0x1f,0x0b,0x0b,0x1e,0x3e,0x01,\r\n  0x35,0x40,0x1e,0x22,0x05,0x0c,0x23,0x02,0x1a,0x0c,0x14,0x13,0x14,\r\n  0x1e,0x1e,0x01,0x38,0x1e,0x06,0x05,0x1f,0x02,0x05,0x1f,0x22,0x0c,\r\n  0x23,0x22,0x05,0x26,0x1e,0x0f,0x01,0x01,0x01,0x38,0x1e,0x2d,0x05,\r\n  0x0c,0x1f,0x0b,0x1f,0x0b,0x06,0x1e,0x1e,0x38,0x01,0x01,0x01,0x1e,\r\n  0x1e,0x13,0x0c,0x13,0x0c,0x13,0x13,0x1f,0x0c,0x23,0x10,0x1e,0x0e,\r\n  0x01,0x01,0x1d,0x1e,0x23,0x13,0x13,0x0c,0x13,0x1f,0x13,0x0b,0x23,\r\n  0x1e,0x1e,0x0f,0x01,0x01,0x3b,0x1e,0x1e,0x12,0x0c,0x0c,0x22,0x02,\r\n  0x23,0x14,0x31,0x1e,0x1e,0x36,0x01,0x01,0x04,0x1e,0x0d,0x0b,0x1f,\r\n  0x0b,0x24,0x1e,0x40,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x38,0x1e,0x15,0x28,0x24,0x1e,0x11,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x3a,0x38,0x1e,0x1e,0x1e,0x32,0x38,0x1e,\r\n  0x1e,0x1e,0x33,0x39,0x35,0x01,0x01,0x08,0x1e,0x09,0x22,0x1f,0x1a,\r\n  0x19,0x25,0x1e,0x1e,0x13,0x13,0x14,0x1f,0x26,0x1e,0x04,0x01,0x35,\r\n  0x1e,0x1e,0x13,0x13,0x13,0x05,0x14,0x13,0x05,0x0c,0x13,0x03,0x1e,\r\n  0x38,0x01,0x01,0x38,0x1e,0x1a,0x05,0x0c,0x1f,0x1f,0x0c,0x13,0x0c,\r\n  0x23,0x1a,0x1e,0x38,0x01,0x01,0x01,0x37,0x1e,0x1e,0x21,0x0a,0x10,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x3d,0x01,0x01,0x30,0x1e,0x1e,\r\n  0x21,0x0a,0x31,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x11,0x01,0x1e,\r\n  0x1e,0x05,0x1f,0x0c,0x13,0x23,0x1e,0x09,0x1a,0x29,0x02,0x1f,0x29,\r\n  0x1e,0x38,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x18,0x16,0x25,0x16,\r\n  0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x38,0x1e,0x1e,0x14,0x13,\r\n  0x05,0x13,0x13,0x13,0x14,0x09,0x1e,0x38,0x01,0x01,0x01,0x30,0x1e,\r\n  0x1e,0x0b,0x0c,0x0c,0x13,0x05,0x13,0x13,0x10,0x1e,0x38,0x01,0x01,\r\n  0x01,0x01,0x3b,0x1e,0x1e,0x1e,0x03,0x16,0x25,0x2d,0x1e,0x1e,0x32,\r\n  0x36,0x01,0x01,0x01,0x1b,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x39,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x3b,0x1e,0x21,0x05,\r\n  0x15,0x1e,0x37,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x1c,0x1e,0x06,0x24,0x05,0x05,0x23,0x31,0x1e,0x1e,\r\n  0x13,0x0b,0x13,0x22,0x22,0x1e,0x07,0x01,0x01,0x38,0x1e,0x1e,0x02,\r\n  0x13,0x1f,0x22,0x13,0x05,0x0c,0x15,0x1e,0x32,0x2b,0x01,0x01,0x3a,\r\n  0x1e,0x1e,0x29,0x14,0x23,0x13,0x05,0x05,0x0c,0x0d,0x1e,0x1e,0x37,\r\n  0x01,0x01,0x01,0x01,0x37,0x38,0x1e,0x1e,0x1e,0x38,0x38,0x1e,0x1e,\r\n  0x1e,0x3e,0x3d,0x00,0x01,0x01,0x01,0x30,0x32,0x1e,0x1e,0x1e,0x1d,\r\n  0x38,0x1e,0x1e,0x1e,0x1e,0x11,0x0e,0x01,0x1e,0x1e,0x19,0x13,0x05,\r\n  0x05,0x23,0x1e,0x1e,0x27,0x0c,0x22,0x02,0x23,0x10,0x1e,0x0e,0x01,\r\n  0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x32,0x30,0x01,\r\n  0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x28,0x25,0x16,0x1e,\r\n  0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x30,0x1e,0x1e,0x1e,0x31,\r\n  0x16,0x28,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x3b,\r\n  0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,\r\n  0x01,0x1b,0x38,0x1e,0x1e,0x1e,0x40,0x39,0x35,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x17,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x08,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1d,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x04,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x18,0x25,0x25,0x28,\r\n  0x10,0x1e,0x1e,0x1e,0x36,0x01,0x01,0x01,0x01,0x3a,0x1e,0x1e,0x1e,\r\n  0x03,0x25,0x25,0x2a,0x1e,0x1e,0x1e,0x37,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x36,0x1b,0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x36,0x2e,0x36,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x20,0x08,0x08,0x08,0x20,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x34,0x04,0x3e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x11,0x2b,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x30,0x1d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x2f,0x08,\r\n  0x08,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x2b,0x38,0x1e,0x38,0x17,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x08,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x38,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x07,0x04,0x34,0x01,\r\n  0x01,0x01,0x20,0x2c,0x07,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x36,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x3b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x1b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1d,0x30,0x0f,0x38,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x0e,0x2e,0x08,0x3c,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x17,0x08,0x1b,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x20,0x08,0x08,0x2e,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x17,0x08,0x08,0x2f,0x34,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x11,\r\n  0x33,0x11,0x0f,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x34,0x01,\r\n  0x35,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x30,0x32,\r\n  0x3e,0x3d,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x39,\r\n  0x33,0x39,0x0f,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x35,0x39,0x33,0x1e,0x38,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x39,0x33,\r\n  0x38,0x37,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,\r\n  0x1e,0x1e,0x38,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x34,0x2e,0x3d,0x04,0x3d,0x2c,0x0f,0x17,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x35,0x2e,0x3d,0x3d,0x2c,0x1c,0x3c,0x2f,\r\n  0x0f,0x2c,0x3d,0x3d,0x3b,0x20,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x0e,0x01,0x00,0x35,0x00,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x20,0x01,0x20,0x20,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x34,0x01,\r\n  0x20,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x34,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x32,0x1e,0x1e,0x1e,0x1e,0x38,\r\n  0x01,0x01,0x01,0x01,0x08,0x38,0x1e,0x1e,0x38,0x1e,0x1e,0x3d,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x35,0x3e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x11,0x1e,0x1e,0x1e,0x1e,0x39,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x39,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x30,0x1e,0x1d,0x30,0x36,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x2b,0x3e,0x1e,0x1e,0x1e,0x1e,0x39,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x33,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x3e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x2e,0x33,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x07,0x3b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x37,0x38,\r\n  0x1e,0x38,0x1e,0x1e,0x1e,0x3d,0x00,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x2b,0x38,0x1e,0x1e,0x38,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x33,0x1e,0x1e,0x04,0x34,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x3c,0x1c,0x1c,0x0f,0x17,0x01,0x01,\r\n  0x01,0x2b,0x38,0x1e,0x1e,0x3d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x2b,0x1b,0x37,0x2c,0x3a,0x01,0x01,0x01,0x01,0x1c,0x1d,0x1e,\r\n  0x1e,0x3d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x38,0x1e,0x03,0x0c,0x19,0x21,0x1e,0x3a,0x01,0x01,0x08,\r\n  0x1e,0x1e,0x09,0x18,0x1e,0x2d,0x18,0x1e,0x30,0x01,0x01,0x01,0x01,\r\n  0x01,0x2c,0x1e,0x2a,0x22,0x22,0x21,0x1e,0x3a,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x0e,0x1e,0x10,0x0c,0x02,0x2d,0x1e,0x3a,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x00,0x1e,0x1e,0x0c,0x13,0x12,0x13,0x13,\r\n  0x21,0x1e,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1c,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x38,0x1e,0x2a,0x1f,0x19,0x2d,0x1e,0x3b,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,0x1e,0x13,0x13,0x0a,0x1e,0x3b,\r\n  0x01,0x01,0x01,0x01,0x01,0x2b,0x40,0x1e,0x2a,0x0d,0x0d,0x29,0x27,\r\n  0x06,0x2d,0x1e,0x38,0x2b,0x01,0x01,0x01,0x2e,0x1e,0x1e,0x0a,0x0d,\r\n  0x29,0x1a,0x24,0x1e,0x18,0x06,0x1a,0x06,0x12,0x16,0x1e,0x1e,0x3b,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x37,0x1e,0x1e,0x10,0x1e,0x1e,0x2d,\r\n  0x1e,0x1e,0x3d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x18,\r\n  0x09,0x1e,0x09,0x09,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x00,\r\n  0x3e,0x1e,0x18,0x18,0x1e,0x09,0x1e,0x1e,0x04,0x01,0x01,0x01,0x01,\r\n  0x2b,0x32,0x1e,0x1e,0x1e,0x1e,0x1e,0x04,0x01,0x34,0x38,0x1e,0x1e,\r\n  0x1e,0x1e,0x17,0x01,0x01,0x01,0x01,0x01,0x34,0x11,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x11,0x01,0x01,0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x00,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x1e,0x1e,\r\n  0x13,0x13,0x13,0x27,0x1e,0x40,0x20,0x01,0x1c,0x1e,0x12,0x13,0x05,\r\n  0x29,0x13,0x22,0x1e,0x32,0x01,0x01,0x01,0x01,0x2f,0x1e,0x1e,0x1f,\r\n  0x13,0x13,0x27,0x1e,0x40,0x35,0x01,0x01,0x01,0x01,0x01,0x01,0x07,\r\n  0x1e,0x22,0x13,0x27,0x1e,0x3e,0x00,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x38,0x1e,0x23,0x13,0x16,0x22,0x13,0x2d,0x1e,0x35,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x1d,0x1e,0x0b,0x0b,0x15,0x1e,0x38,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2f,0x1e,0x1e,0x13,\r\n  0x1f,0x1f,0x29,0x1e,0x32,0x00,0x01,0x01,0x01,0x01,0x01,0x34,0x33,\r\n  0x1e,0x0c,0x13,0x1e,0x13,0x13,0x2a,0x1e,0x2f,0x01,0x01,0x01,0x01,\r\n  0x01,0x38,0x1e,0x25,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x1e,\r\n  0x38,0x01,0x01,0x34,0x3e,0x1e,0x0d,0x1f,0x0b,0x0c,0x0c,0x22,0x22,\r\n  0x05,0x0c,0x0c,0x1f,0x13,0x0c,0x29,0x1e,0x40,0x20,0x01,0x01,0x01,\r\n  0x01,0x01,0x38,0x1e,0x23,0x13,0x25,0x13,0x13,0x22,0x1e,0x3e,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,0x31,0x13,0x13,\r\n  0x18,0x1e,0x34,0x01,0x01,0x01,0x01,0x01,0x2f,0x1e,0x2a,0x13,0x13,\r\n  0x0c,0x13,0x05,0x1e,0x07,0x01,0x01,0x01,0x01,0x38,0x1e,0x03,0x24,\r\n  0x12,0x15,0x18,0x1e,0x34,0x04,0x1e,0x10,0x1f,0x26,0x1e,0x0f,0x01,\r\n  0x01,0x01,0x01,0x01,0x04,0x1e,0x10,0x15,0x24,0x27,0x10,0x1e,0x36,\r\n  0x2b,0x32,0x1e,0x0b,0x0b,0x1e,0x1d,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x1c,0x1e,0x28,0x13,0x27,0x02,0x13,\r\n  0x25,0x1e,0x08,0x01,0x3b,0x1e,0x0a,0x13,0x0b,0x16,0x13,0x1a,0x1e,\r\n  0x04,0x01,0x01,0x01,0x01,0x0f,0x1e,0x06,0x13,0x1a,0x23,0x0c,0x25,\r\n  0x1e,0x08,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x1e,0x1e,0x14,0x0c,\r\n  0x2a,0x1e,0x2f,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,\r\n  0x21,0x28,0x1e,0x16,0x16,0x1e,0x38,0x2f,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x1c,0x1e,0x2a,0x13,0x13,0x1e,0x1e,0x0f,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x36,0x37,0x1e,0x26,0x05,0x12,0x27,0x14,0x03,\r\n  0x1e,0x17,0x01,0x01,0x01,0x01,0x3d,0x1e,0x1e,0x1e,0x21,0x0a,0x1e,\r\n  0x0a,0x03,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x2f,0x1e,0x1e,0x13,\r\n  0x13,0x1f,0x1f,0x13,0x13,0x13,0x13,0x13,0x1e,0x1e,0x01,0x01,0x1b,\r\n  0x1e,0x2a,0x0c,0x13,0x1f,0x0c,0x1f,0x13,0x05,0x23,0x0c,0x23,0x29,\r\n  0x0c,0x13,0x1f,0x25,0x1e,0x08,0x01,0x01,0x01,0x01,0x35,0x37,0x1e,\r\n  0x06,0x13,0x03,0x19,0x13,0x29,0x1e,0x3d,0x35,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x3e,0x1e,0x14,0x13,0x1e,0x13,0x0c,0x1e,0x33,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x0e,0x1e,0x10,0x13,0x0b,0x24,0x13,0x1a,0x1e,\r\n  0x04,0x01,0x01,0x01,0x2b,0x1e,0x21,0x0c,0x0c,0x0c,0x13,0x10,0x1e,\r\n  0x2b,0x07,0x1e,0x22,0x0c,0x31,0x1e,0x17,0x01,0x01,0x01,0x01,0x01,\r\n  0x07,0x1e,0x14,0x0c,0x23,0x14,0x15,0x1e,0x1b,0x38,0x1e,0x03,0x13,\r\n  0x27,0x1e,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x1d,0x1e,0x0b,0x24,0x1e,0x1e,0x0b,0x26,0x1e,0x3a,0x01,\r\n  0x35,0x1e,0x18,0x2d,0x18,0x1e,0x10,0x2d,0x1e,0x1b,0x01,0x01,0x01,\r\n  0x35,0x39,0x1e,0x29,0x23,0x1e,0x1e,0x14,0x25,0x1e,0x04,0x34,0x01,\r\n  0x01,0x01,0x01,0x1c,0x40,0x1e,0x1e,0x1e,0x22,0x0a,0x1e,0x1e,0x04,\r\n  0x34,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x10,0x16,0x0d,0x26,\r\n  0x21,0x09,0x1e,0x1e,0x2f,0x01,0x01,0x01,0x01,0x00,0x17,0x1b,0x3e,\r\n  0x1e,0x06,0x0c,0x1a,0x1e,0x11,0x3b,0x35,0x01,0x01,0x01,0x01,0x36,\r\n  0x1e,0x1e,0x1e,0x1a,0x06,0x1e,0x1e,0x0d,0x10,0x1e,0x1e,0x1d,0x00,\r\n  0x01,0x37,0x1e,0x18,0x2d,0x2d,0x1e,0x1e,0x1e,0x1e,0x1e,0x18,0x2d,\r\n  0x09,0x1e,0x38,0x01,0x01,0x37,0x1e,0x06,0x19,0x0b,0x14,0x26,0x09,\r\n  0x13,0x13,0x13,0x13,0x18,0x1e,0x34,0x01,0x04,0x1e,0x0d,0x13,0x05,\r\n  0x13,0x26,0x2a,0x0c,0x13,0x05,0x0c,0x1e,0x2d,0x05,0x23,0x0c,0x24,\r\n  0x1e,0x39,0x01,0x01,0x01,0x2b,0x40,0x1e,0x1e,0x1e,0x21,0x1e,0x09,\r\n  0x2d,0x1e,0x1e,0x1e,0x40,0x2b,0x01,0x01,0x01,0x01,0x36,0x3e,0x1e,\r\n  0x2d,0x16,0x1e,0x31,0x2d,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x2f,0x3e,0x1e,0x10,0x21,0x1e,0x2a,0x1e,0x1e,0x38,0x2b,0x01,0x01,\r\n  0x01,0x38,0x1e,0x10,0x05,0x0c,0x14,0x2d,0x1e,0x38,0x1e,0x03,0x13,\r\n  0x24,0x1e,0x1d,0x01,0x01,0x01,0x01,0x01,0x01,0x04,0x1e,0x1e,0x12,\r\n  0x19,0x12,0x16,0x1e,0x08,0x1e,0x1e,0x13,0x13,0x1e,0x1e,0x1b,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1c,0x1e,\r\n  0x1e,0x31,0x25,0x16,0x1e,0x1e,0x1e,0x36,0x01,0x01,0x38,0x1e,0x21,\r\n  0x2a,0x16,0x03,0x1e,0x1e,0x2b,0x01,0x01,0x01,0x39,0x1e,0x1e,0x31,\r\n  0x16,0x24,0x12,0x2a,0x03,0x1e,0x1e,0x04,0x01,0x01,0x01,0x1c,0x1e,\r\n  0x1e,0x25,0x0d,0x24,0x03,0x15,0x28,0x1e,0x1e,0x04,0x01,0x01,0x01,\r\n  0x01,0x38,0x1e,0x21,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x24,0x1e,\r\n  0x1e,0x2b,0x01,0x01,0x00,0x32,0x1e,0x1e,0x1e,0x1e,0x1e,0x02,0x1a,\r\n  0x1e,0x1e,0x1e,0x1e,0x04,0x01,0x01,0x01,0x38,0x1e,0x28,0x25,0x2d,\r\n  0x18,0x1e,0x18,0x2d,0x31,0x0a,0x31,0x1e,0x3d,0x01,0x11,0x1e,0x19,\r\n  0x13,0x05,0x14,0x13,0x1e,0x22,0x13,0x13,0x13,0x13,0x18,0x1e,0x34,\r\n  0x01,0x30,0x1e,0x29,0x05,0x0b,0x14,0x02,0x1e,0x03,0x28,0x0a,0x26,\r\n  0x1e,0x38,0x01,0x01,0x38,0x1e,0x27,0x13,0x1f,0x0c,0x10,0x1e,0x13,\r\n  0x0c,0x0c,0x13,0x0d,0x14,0x13,0x05,0x1f,0x05,0x1e,0x1e,0x00,0x01,\r\n  0x01,0x38,0x1e,0x25,0x25,0x16,0x03,0x1e,0x1e,0x31,0x2a,0x0a,0x0a,\r\n  0x1e,0x38,0x01,0x01,0x01,0x36,0x1e,0x1e,0x2a,0x26,0x26,0x29,0x26,\r\n  0x25,0x18,0x1e,0x38,0x01,0x01,0x01,0x01,0x2f,0x1e,0x1e,0x2a,0x15,\r\n  0x06,0x24,0x26,0x15,0x09,0x1e,0x38,0x0e,0x01,0x01,0x2b,0x3e,0x1e,\r\n  0x22,0x0c,0x13,0x2d,0x1e,0x1e,0x1e,0x22,0x13,0x1e,0x1e,0x3d,0x3d,\r\n  0x1c,0x08,0x01,0x01,0x01,0x34,0x04,0x1e,0x16,0x0b,0x0c,0x25,0x1e,\r\n  0x38,0x1e,0x16,0x14,0x24,0x1e,0x3e,0x1d,0x1c,0x3c,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x1e,0x1e,0x13,0x13,0x13,\r\n  0x13,0x21,0x1e,0x36,0x01,0x01,0x1e,0x1e,0x13,0x13,0x13,0x13,0x15,\r\n  0x1e,0x1b,0x01,0x01,0x2e,0x1e,0x18,0x0c,0x13,0x13,0x0c,0x13,0x0c,\r\n  0x13,0x22,0x1e,0x40,0x20,0x01,0x2e,0x1e,0x1e,0x19,0x1f,0x13,0x27,\r\n  0x0b,0x0c,0x19,0x0b,0x1e,0x1e,0x2e,0x01,0x01,0x00,0x1e,0x1e,0x13,\r\n  0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x15,0x1e,0x3d,0x01,0x01,\r\n  0x30,0x1e,0x03,0x15,0x25,0x0a,0x31,0x1e,0x2d,0x28,0x0a,0x0a,0x09,\r\n  0x1e,0x35,0x01,0x20,0x1e,0x09,0x1f,0x0c,0x27,0x19,0x1e,0x26,0x14,\r\n  0x19,0x22,0x19,0x1e,0x32,0x01,0x37,0x1e,0x26,0x13,0x05,0x02,0x14,\r\n  0x1e,0x12,0x23,0x14,0x13,0x22,0x1e,0x1e,0x00,0x01,0x37,0x1e,0x15,\r\n  0x12,0x14,0x23,0x0d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,\r\n  0x11,0x1e,0x02,0x0c,0x19,0x0c,0x21,0x18,0x13,0x0c,0x1f,0x13,0x14,\r\n  0x05,0x0d,0x1a,0x19,0x24,0x1e,0x39,0x01,0x01,0x34,0x1e,0x18,0x0b,\r\n  0x0c,0x1f,0x19,0x1e,0x06,0x24,0x14,0x13,0x13,0x1e,0x1e,0x01,0x01,\r\n  0x34,0x3e,0x1e,0x15,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x2d,0x1e,\r\n  0x3a,0x01,0x01,0x00,0x32,0x1e,0x06,0x13,0x13,0x13,0x13,0x13,0x13,\r\n  0x13,0x09,0x1e,0x11,0x01,0x01,0x01,0x07,0x1e,0x14,0x1f,0x1f,0x2d,\r\n  0x1e,0x1e,0x0a,0x13,0x26,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x08,0x01,\r\n  0x01,0x01,0x1b,0x1e,0x15,0x02,0x19,0x25,0x1e,0x1e,0x1e,0x0c,0x22,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x39,0x35,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,0x13,0x1f,0x2d,0x1e,0x35,\r\n  0x01,0x01,0x1e,0x1e,0x13,0x13,0x13,0x13,0x2a,0x1e,0x2f,0x01,0x01,\r\n  0x04,0x1e,0x0d,0x13,0x13,0x0c,0x0c,0x0c,0x1f,0x0c,0x13,0x25,0x1e,\r\n  0x1c,0x01,0x38,0x1e,0x0d,0x13,0x1f,0x0c,0x1f,0x05,0x05,0x22,0x0c,\r\n  0x26,0x1e,0x04,0x01,0x01,0x3b,0x1e,0x2a,0x13,0x13,0x13,0x0c,0x03,\r\n  0x27,0x13,0x13,0x13,0x14,0x1e,0x3e,0x01,0x01,0x1d,0x1e,0x0b,0x13,\r\n  0x13,0x0c,0x05,0x1e,0x13,0x1f,0x0b,0x0c,0x25,0x1e,0x3b,0x01,0x00,\r\n  0x1e,0x1e,0x1f,0x05,0x05,0x1f,0x1e,0x15,0x05,0x24,0x12,0x24,0x1e,\r\n  0x04,0x01,0x37,0x1e,0x24,0x1f,0x23,0x13,0x0b,0x1e,0x12,0x19,0x12,\r\n  0x14,0x22,0x1e,0x1e,0x00,0x01,0x3d,0x1e,0x29,0x0b,0x22,0x1f,0x27,\r\n  0x1e,0x24,0x1f,0x23,0x13,0x1e,0x1e,0x01,0x01,0x11,0x1e,0x02,0x13,\r\n  0x1f,0x13,0x21,0x1e,0x0c,0x23,0x05,0x13,0x1e,0x1e,0x25,0x03,0x2a,\r\n  0x16,0x1e,0x2e,0x01,0x01,0x01,0x1e,0x1e,0x02,0x19,0x1f,0x05,0x1e,\r\n  0x0a,0x0c,0x14,0x27,0x0c,0x1e,0x1e,0x01,0x01,0x2f,0x1e,0x2a,0x13,\r\n  0x13,0x13,0x13,0x27,0x13,0x13,0x13,0x27,0x1e,0x39,0x01,0x01,0x08,\r\n  0x1e,0x03,0x13,0x13,0x13,0x0c,0x0c,0x13,0x13,0x13,0x13,0x1e,0x1e,\r\n  0x01,0x01,0x01,0x33,0x1e,0x22,0x05,0x13,0x2d,0x1e,0x1e,0x05,0x0c,\r\n  0x1e,0x1e,0x15,0x0d,0x0d,0x24,0x1e,0x38,0x01,0x01,0x01,0x3a,0x1e,\r\n  0x15,0x14,0x1f,0x16,0x1e,0x1e,0x26,0x0b,0x03,0x1e,0x02,0x23,0x19,\r\n  0x24,0x1e,0x1e,0x39,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x1e,0x1e,0x13,0x13,0x13,0x1f,0x2d,0x1e,0x35,0x01,0x01,0x1e,0x1e,\r\n  0x13,0x13,0x13,0x13,0x2a,0x1e,0x2f,0x01,0x34,0x1e,0x18,0x14,0x14,\r\n  0x13,0x1f,0x25,0x06,0x05,0x13,0x05,0x23,0x1e,0x1d,0x01,0x1e,0x1e,\r\n  0x05,0x23,0x0c,0x14,0x0a,0x31,0x0c,0x22,0x0b,0x23,0x1e,0x3e,0x01,\r\n  0x01,0x3d,0x1e,0x15,0x14,0x13,0x13,0x0b,0x1e,0x16,0x13,0x13,0x13,\r\n  0x0c,0x18,0x1e,0x34,0x01,0x39,0x1e,0x02,0x13,0x0c,0x0c,0x1a,0x1e,\r\n  0x0c,0x13,0x1f,0x0c,0x31,0x1e,0x36,0x01,0x00,0x1e,0x1e,0x22,0x23,\r\n  0x02,0x22,0x1e,0x15,0x19,0x0b,0x19,0x12,0x1e,0x04,0x01,0x37,0x1e,\r\n  0x26,0x0c,0x27,0x0b,0x05,0x1e,0x24,0x0b,0x0c,0x1f,0x1a,0x1e,0x1e,\r\n  0x00,0x01,0x1b,0x1e,0x0a,0x19,0x22,0x0b,0x23,0x15,0x19,0x23,0x1f,\r\n  0x22,0x1e,0x1e,0x01,0x01,0x1c,0x1e,0x12,0x23,0x19,0x1f,0x0d,0x29,\r\n  0x22,0x1f,0x0c,0x0c,0x2d,0x28,0x0b,0x22,0x1f,0x24,0x1e,0x04,0x01,\r\n  0x01,0x00,0x1e,0x1e,0x14,0x1f,0x0d,0x1a,0x1e,0x25,0x0b,0x13,0x05,\r\n  0x0c,0x1e,0x1e,0x01,0x01,0x3c,0x1e,0x16,0x27,0x06,0x06,0x1e,0x09,\r\n  0x13,0x13,0x13,0x05,0x18,0x1e,0x34,0x01,0x1c,0x1e,0x12,0x13,0x13,\r\n  0x13,0x12,0x31,0x0c,0x13,0x13,0x13,0x1e,0x1e,0x01,0x01,0x01,0x40,\r\n  0x1e,0x14,0x22,0x13,0x2d,0x1e,0x24,0x05,0x0a,0x1e,0x03,0x13,0x1f,\r\n  0x1f,0x13,0x1e,0x1e,0x01,0x01,0x01,0x3a,0x1e,0x15,0x22,0x05,0x0a,\r\n  0x1e,0x1e,0x14,0x14,0x1e,0x0d,0x05,0x0b,0x02,0x13,0x14,0x1e,0x40,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,\r\n  0x13,0x1f,0x2d,0x1e,0x35,0x01,0x01,0x1e,0x1e,0x13,0x13,0x13,0x13,\r\n  0x2a,0x1e,0x2f,0x01,0x0e,0x1e,0x10,0x13,0x13,0x0c,0x02,0x1e,0x25,\r\n  0x22,0x13,0x1f,0x0c,0x1e,0x1e,0x01,0x33,0x1e,0x1f,0x05,0x1f,0x0c,\r\n  0x2d,0x1e,0x27,0x05,0x0b,0x06,0x09,0x1e,0x20,0x01,0x38,0x1e,0x19,\r\n  0x14,0x27,0x0c,0x23,0x1e,0x16,0x13,0x13,0x1f,0x05,0x18,0x1e,0x34,\r\n  0x01,0x39,0x1e,0x1a,0x13,0x1f,0x0c,0x0d,0x1e,0x13,0x05,0x13,0x13,\r\n  0x03,0x1e,0x17,0x01,0x00,0x1e,0x1e,0x14,0x0b,0x0c,0x22,0x1e,0x15,\r\n  0x02,0x06,0x1a,0x29,0x1e,0x04,0x01,0x37,0x1e,0x15,0x14,0x27,0x15,\r\n  0x15,0x1e,0x12,0x1a,0x27,0x1f,0x23,0x1e,0x1e,0x00,0x01,0x36,0x1e,\r\n  0x1e,0x22,0x22,0x14,0x13,0x0d,0x02,0x23,0x0b,0x29,0x1e,0x38,0x01,\r\n  0x01,0x08,0x1e,0x21,0x13,0x05,0x0c,0x02,0x13,0x0b,0x23,0x13,0x14,\r\n  0x05,0x0c,0x1f,0x1f,0x0c,0x2a,0x1e,0x2e,0x01,0x01,0x00,0x1e,0x1e,\r\n  0x22,0x05,0x0c,0x14,0x1e,0x0a,0x0c,0x02,0x0d,0x05,0x1e,0x1e,0x01,\r\n  0x01,0x34,0x07,0x1e,0x1e,0x16,0x12,0x24,0x1f,0x13,0x13,0x13,0x0c,\r\n  0x2d,0x1e,0x35,0x01,0x1c,0x1e,0x12,0x13,0x13,0x13,0x15,0x1e,0x05,\r\n  0x13,0x13,0x13,0x1e,0x1e,0x01,0x01,0x01,0x39,0x1e,0x10,0x31,0x21,\r\n  0x1e,0x1e,0x1f,0x23,0x1e,0x1e,0x27,0x13,0x14,0x13,0x1f,0x1e,0x1e,\r\n  0x2b,0x01,0x01,0x36,0x1e,0x18,0x21,0x2a,0x18,0x1e,0x02,0x22,0x1e,\r\n  0x1e,0x14,0x12,0x16,0x02,0x19,0x12,0x10,0x1e,0x2b,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x13,0x13,0x22,0x1f,0x2d,0x1e,\r\n  0x35,0x01,0x01,0x1e,0x1e,0x13,0x13,0x13,0x13,0x2a,0x1e,0x2f,0x01,\r\n  0x0e,0x1e,0x10,0x1f,0x1f,0x13,0x1f,0x1e,0x15,0x13,0x0c,0x19,0x0c,\r\n  0x1e,0x1e,0x01,0x33,0x1e,0x05,0x1f,0x13,0x22,0x03,0x2d,0x23,0x22,\r\n  0x1f,0x0c,0x31,0x1e,0x17,0x01,0x39,0x1e,0x29,0x13,0x05,0x0c,0x22,\r\n  0x1e,0x25,0x19,0x0b,0x14,0x06,0x18,0x1e,0x34,0x01,0x39,0x1e,0x02,\r\n  0x0c,0x02,0x0c,0x0d,0x1e,0x13,0x1f,0x0c,0x05,0x31,0x1e,0x17,0x01,\r\n  0x00,0x1e,0x1e,0x0c,0x0b,0x0b,0x02,0x1e,0x0a,0x02,0x1f,0x0b,0x26,\r\n  0x1e,0x04,0x01,0x37,0x1e,0x06,0x1f,0x19,0x19,0x22,0x1e,0x26,0x19,\r\n  0x26,0x12,0x29,0x1e,0x1e,0x00,0x01,0x01,0x38,0x1e,0x18,0x19,0x24,\r\n  0x13,0x05,0x02,0x19,0x0d,0x1e,0x1e,0x08,0x01,0x01,0x01,0x38,0x1e,\r\n  0x03,0x1f,0x14,0x23,0x13,0x23,0x15,0x27,0x0b,0x13,0x14,0x23,0x13,\r\n  0x10,0x1e,0x3e,0x00,0x01,0x01,0x00,0x1e,0x1e,0x14,0x22,0x29,0x14,\r\n  0x1e,0x16,0x1f,0x0c,0x14,0x14,0x1e,0x1e,0x01,0x01,0x1b,0x1e,0x10,\r\n  0x23,0x0c,0x13,0x13,0x14,0x22,0x13,0x13,0x23,0x09,0x1e,0x20,0x01,\r\n  0x1c,0x1e,0x12,0x13,0x13,0x13,0x06,0x1e,0x1f,0x13,0x13,0x13,0x1e,\r\n  0x1e,0x01,0x01,0x01,0x35,0x39,0x1e,0x1e,0x1e,0x1e,0x12,0x13,0x16,\r\n  0x1e,0x2d,0x05,0x21,0x28,0x05,0x1f,0x1e,0x1e,0x38,0x01,0x01,0x01,\r\n  0x04,0x1e,0x1e,0x1e,0x1e,0x1e,0x27,0x22,0x1e,0x1e,0x1e,0x0b,0x23,\r\n  0x1f,0x0c,0x0b,0x1e,0x1e,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x1e,0x1e,0x0c,0x13,0x0c,0x1f,0x2d,0x1e,0x35,0x01,0x01,0x1e,\r\n  0x1e,0x13,0x13,0x13,0x13,0x2a,0x1e,0x2f,0x01,0x0e,0x1e,0x10,0x1f,\r\n  0x13,0x05,0x22,0x1e,0x16,0x1f,0x13,0x1f,0x13,0x1e,0x1e,0x01,0x33,\r\n  0x1e,0x1f,0x1f,0x0c,0x05,0x2d,0x1e,0x05,0x13,0x19,0x1a,0x1e,0x1e,\r\n  0x00,0x01,0x39,0x1e,0x27,0x02,0x0d,0x05,0x19,0x1e,0x25,0x05,0x0b,\r\n  0x14,0x05,0x18,0x1e,0x34,0x01,0x39,0x1e,0x27,0x13,0x0b,0x0c,0x1a,\r\n  0x1e,0x0c,0x19,0x0c,0x1f,0x31,0x1e,0x17,0x01,0x20,0x1e,0x09,0x05,\r\n  0x22,0x0c,0x05,0x21,0x15,0x19,0x27,0x02,0x06,0x1e,0x04,0x01,0x37,\r\n  0x1e,0x28,0x0d,0x02,0x12,0x06,0x1e,0x26,0x19,0x22,0x05,0x12,0x1e,\r\n  0x1e,0x00,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x27,0x19,0x0a,0x1e,\r\n  0x1e,0x1e,0x3a,0x01,0x01,0x01,0x01,0x2b,0x32,0x1e,0x1e,0x21,0x16,\r\n  0x15,0x1e,0x1e,0x1e,0x1e,0x28,0x25,0x21,0x1e,0x1e,0x38,0x2b,0x01,\r\n  0x01,0x01,0x00,0x1e,0x1e,0x02,0x1f,0x1f,0x05,0x2d,0x26,0x05,0x29,\r\n  0x22,0x0c,0x1e,0x1e,0x01,0x01,0x04,0x1e,0x06,0x1f,0x22,0x13,0x0a,\r\n  0x1e,0x22,0x0c,0x13,0x05,0x09,0x1e,0x20,0x01,0x30,0x1e,0x29,0x13,\r\n  0x13,0x13,0x0a,0x1e,0x14,0x13,0x13,0x13,0x1e,0x1e,0x01,0x01,0x01,\r\n  0x01,0x01,0x0e,0x2e,0x1e,0x09,0x13,0x0b,0x1e,0x1e,0x29,0x0c,0x05,\r\n  0x1f,0x0c,0x0b,0x05,0x1e,0x1e,0x01,0x01,0x01,0x01,0x34,0x2b,0x32,\r\n  0x1e,0x23,0x27,0x1e,0x1e,0x1e,0x19,0x19,0x22,0x29,0x09,0x1e,0x1e,\r\n  0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x14,\r\n  0x13,0x1f,0x1f,0x2d,0x1e,0x35,0x01,0x01,0x1e,0x1e,0x13,0x13,0x13,\r\n  0x13,0x2a,0x1e,0x2f,0x01,0x00,0x1e,0x1e,0x23,0x0c,0x13,0x13,0x0d,\r\n  0x27,0x13,0x0b,0x0b,0x02,0x1e,0x38,0x01,0x3e,0x1e,0x02,0x05,0x1f,\r\n  0x02,0x0d,0x06,0x22,0x0c,0x23,0x23,0x1e,0x40,0x01,0x01,0x38,0x1e,\r\n  0x02,0x0c,0x14,0x14,0x22,0x1e,0x2a,0x12,0x14,0x23,0x27,0x18,0x1e,\r\n  0x20,0x01,0x11,0x1e,0x02,0x05,0x0b,0x0c,0x05,0x1e,0x13,0x1f,0x13,\r\n  0x13,0x03,0x1e,0x17,0x01,0x01,0x1e,0x1e,0x05,0x02,0x02,0x19,0x22,\r\n  0x14,0x02,0x0b,0x22,0x29,0x1e,0x04,0x01,0x37,0x1e,0x06,0x27,0x19,\r\n  0x05,0x02,0x1e,0x28,0x1a,0x29,0x29,0x27,0x1e,0x1e,0x00,0x01,0x01,\r\n  0x01,0x2b,0x38,0x1e,0x1e,0x10,0x23,0x22,0x28,0x1e,0x3a,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x38,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x33,\r\n  0x1e,0x1f,0x0b,0x02,0x1f,0x1a,0x02,0x0c,0x05,0x1f,0x19,0x1e,0x1e,\r\n  0x01,0x00,0x1e,0x1e,0x27,0x05,0x1f,0x13,0x31,0x26,0x1f,0x14,0x13,\r\n  0x14,0x09,0x1e,0x20,0x01,0x1c,0x1e,0x06,0x13,0x13,0x13,0x02,0x24,\r\n  0x13,0x13,0x13,0x13,0x1e,0x1e,0x01,0x01,0x01,0x01,0x01,0x20,0x07,\r\n  0x1e,0x0d,0x13,0x10,0x1e,0x1e,0x12,0x13,0x05,0x05,0x0c,0x1f,0x1f,\r\n  0x1e,0x1e,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x31,0x1f,0x12,0x1e,\r\n  0x1e,0x10,0x0c,0x19,0x24,0x06,0x24,0x24,0x1e,0x38,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x1f,0x13,0x0c,0x1f,0x2d,\r\n  0x1e,0x35,0x01,0x01,0x1e,0x1e,0x13,0x13,0x13,0x13,0x2a,0x1e,0x2f,\r\n  0x01,0x01,0x3d,0x1e,0x06,0x13,0x05,0x0c,0x13,0x1f,0x13,0x13,0x0c,\r\n  0x21,0x1e,0x0f,0x01,0x3d,0x1e,0x25,0x1f,0x0c,0x13,0x0c,0x23,0x0b,\r\n  0x05,0x29,0x26,0x1e,0x2c,0x01,0x01,0x3d,0x1e,0x12,0x29,0x22,0x0c,\r\n  0x02,0x1e,0x25,0x0b,0x22,0x1f,0x05,0x1e,0x1e,0x00,0x01,0x1c,0x1e,\r\n  0x06,0x13,0x05,0x0c,0x0b,0x1f,0x23,0x19,0x1f,0x0b,0x03,0x1e,0x17,\r\n  0x01,0x01,0x1e,0x1e,0x05,0x13,0x0c,0x19,0x0b,0x22,0x29,0x29,0x02,\r\n  0x12,0x1e,0x04,0x01,0x37,0x1e,0x26,0x14,0x0b,0x27,0x27,0x1e,0x28,\r\n  0x1a,0x05,0x02,0x24,0x09,0x1e,0x20,0x01,0x01,0x01,0x01,0x11,0x1e,\r\n  0x1a,0x03,0x31,0x1f,0x24,0x1e,0x04,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x2b,0x08,0x1b,0x36,0x01,0x01,0x2b,0x1b,0x08,0x2b,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x27,0x0b,0x22,\r\n  0x1f,0x14,0x0c,0x14,0x27,0x0c,0x19,0x1e,0x1e,0x01,0x01,0x2c,0x1e,\r\n  0x12,0x13,0x0b,0x13,0x13,0x13,0x14,0x1f,0x13,0x0b,0x1e,0x1e,0x2f,\r\n  0x01,0x3c,0x1e,0x09,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x23,\r\n  0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x3c,0x1e,0x16,0x0c,0x22,0x1e,\r\n  0x32,0x1e,0x1e,0x1e,0x1e,0x22,0x14,0x23,0x1e,0x1e,0x38,0x01,0x01,\r\n  0x01,0x01,0x01,0x1e,0x1e,0x19,0x1f,0x1e,0x1e,0x1e,0x31,0x1f,0x05,\r\n  0x0c,0x1f,0x0b,0x1f,0x1e,0x1e,0x00,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x34,0x1e,0x1e,0x22,0x13,0x13,0x13,0x21,0x1e,0x2b,0x01,0x01,\r\n  0x1e,0x1e,0x13,0x1f,0x13,0x13,0x15,0x1e,0x1b,0x01,0x01,0x2f,0x1e,\r\n  0x1e,0x29,0x05,0x0c,0x1f,0x05,0x13,0x0c,0x16,0x1e,0x38,0x01,0x01,\r\n  0x20,0x40,0x1e,0x15,0x05,0x05,0x0c,0x05,0x05,0x0c,0x06,0x1e,0x1e,\r\n  0x2f,0x01,0x01,0x3b,0x1e,0x10,0x05,0x1f,0x19,0x22,0x26,0x29,0x19,\r\n  0x13,0x0b,0x02,0x1e,0x38,0x01,0x01,0x08,0x1e,0x16,0x05,0x1f,0x13,\r\n  0x14,0x13,0x13,0x05,0x0c,0x02,0x31,0x1e,0x17,0x01,0x01,0x38,0x1e,\r\n  0x21,0x14,0x1f,0x14,0x14,0x27,0x0c,0x22,0x27,0x27,0x1e,0x3e,0x01,\r\n  0x3a,0x1e,0x15,0x0d,0x23,0x23,0x24,0x25,0x0b,0x23,0x19,0x27,0x0d,\r\n  0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x33,0x1e,0x1f,0x0c,0x22,0x05,\r\n  0x21,0x1e,0x2e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x37,0x1e,0x2d,0x0d,0x19,0x1f,0x0b,0x29,0x14,\r\n  0x22,0x1f,0x05,0x1e,0x1e,0x01,0x01,0x1b,0x1e,0x09,0x22,0x22,0x13,\r\n  0x13,0x15,0x13,0x22,0x13,0x13,0x24,0x1e,0x37,0x01,0x01,0x38,0x1e,\r\n  0x21,0x13,0x1f,0x13,0x13,0x13,0x13,0x23,0x1e,0x1e,0x1c,0x01,0x01,\r\n  0x01,0x01,0x01,0x36,0x1e,0x31,0x15,0x1e,0x1e,0x30,0x1b,0x38,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x20,0x1e,\r\n  0x09,0x15,0x21,0x1e,0x38,0x1d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,0x01,0x38,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x2b,0x01,0x01,0x01,0x3b,0x1e,0x1e,0x1e,0x31,\r\n  0x25,0x28,0x10,0x1e,0x1e,0x07,0x2b,0x01,0x01,0x01,0x36,0x1e,0x1e,\r\n  0x1e,0x2d,0x0a,0x16,0x10,0x1e,0x1e,0x1e,0x2f,0x01,0x01,0x01,0x01,\r\n  0x1e,0x1e,0x27,0x0c,0x19,0x12,0x13,0x05,0x22,0x14,0x14,0x16,0x1e,\r\n  0x37,0x01,0x01,0x20,0x07,0x1e,0x19,0x0c,0x1f,0x0b,0x14,0x22,0x1f,\r\n  0x14,0x23,0x0a,0x1e,0x3b,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x28,0x2a,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x04,0x01,0x36,0x1e,0x18,0x29,\r\n  0x06,0x29,0x1a,0x23,0x27,0x19,0x0b,0x12,0x15,0x1e,0x1c,0x01,0x01,\r\n  0x01,0x01,0x01,0x11,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x38,0x1e,0x1e,0x16,0x25,0x18,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x01,0x01,0x01,0x38,0x1e,0x1e,0x31,0x15,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x2f,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x18,0x25,\r\n  0x28,0x03,0x1e,0x1e,0x1e,0x1c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x1d,0x1e,0x1e,0x1e,0x30,0x01,0x01,0x01,0x00,0x3d,0x32,0x1e,0x1e,\r\n  0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x04,0x1e,0x1e,0x1e,0x38,\r\n  0x2b,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x2b,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,\r\n  0x01,0x01,0x01,0x01,0x01,0x3b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,\r\n  0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x36,0x38,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x38,0x2f,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x0b,\r\n  0x05,0x0c,0x1f,0x0b,0x1f,0x0b,0x03,0x1e,0x07,0x34,0x01,0x01,0x01,\r\n  0x30,0x1e,0x1e,0x31,0x0a,0x31,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x33,\r\n  0x35,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x33,0x38,0x1e,0x1e,\r\n  0x1e,0x3e,0x04,0x34,0x01,0x01,0x38,0x1e,0x1e,0x05,0x05,0x27,0x1a,\r\n  0x0d,0x26,0x0d,0x25,0x1e,0x1e,0x3c,0x01,0x01,0x01,0x01,0x01,0x0e,\r\n  0x11,0x33,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,\r\n  0x1e,0x1e,0x1e,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,\r\n  0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x1e,0x1e,0x1e,0x1e,0x38,0x2f,\r\n  0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1d,\r\n  0x1c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x36,0x1b,0x2b,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x2b,0x1b,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x17,0x08,0x1b,0x2b,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x2e,0x08,0x0e,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x18,0x16,0x25,0x25,\r\n  0x21,0x1e,0x1e,0x3e,0x2b,0x01,0x01,0x01,0x01,0x01,0x30,0x32,0x1e,\r\n  0x1e,0x1e,0x3e,0x3e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x2b,0x1b,0x3c,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x2b,0x38,0x1e,0x1e,0x18,0x2a,0x2a,0x16,0x21,0x1e,0x1e,\r\n  0x33,0x3c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x3c,0x2e,0x0e,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x2f,\r\n  0x1b,0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x20,0x08,0x2e,0x17,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x00,0x3d,0x3e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x36,0x3b,0x36,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,\r\n  0x11,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x20,0x3c,0x08,0x08,0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x08,\r\n  0x08,0x08,0x36,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x34,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x20,0x0e,0x20,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x36,0x1b,0x0f,0x17,0x01,0x01,0x01,0x01,0x01,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,\r\n  0x0f,0x11,0x1d,0x04,0x2e,0x34,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x3d,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x2c,0x1e,0x1e,\r\n  0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x38,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x09,0x13,0x13,0x13,\r\n  0x13,0x13,0x13,0x13,0x13,0x13,0x3f,0x18,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1b,0x32,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x3e,0x2b,0x2b,0x32,0x1e,0x18,0x1e,0x1e,0x20,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x04,0x1e,0x09,0x10,0x09,0x10,0x1e,0x32,\r\n  0x00,0x01,0x01,0x01,0x01,0x01,0x38,0x1e,0x1e,0x21,0x15,0x06,0x10,\r\n  0x1e,0x1e,0x07,0x2b,0x01,0x09,0x13,0x13,0x13,0x13,0x13,0x13,0x13,\r\n  0x13,0x13,0x3f,0x18,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x1b,0x1e,0x1e,0x2a,0x19,0x0b,0x1a,0x2a,0x1e,0x1e,0x38,\r\n  0x1e,0x03,0x13,0x25,0x1e,0x08,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x07,0x1e,0x22,0x13,0x0c,0x13,0x03,0x1e,0x17,0x01,0x01,0x01,\r\n  0x01,0x1b,0x1e,0x1e,0x14,0x13,0x13,0x13,0x13,0x13,0x25,0x1e,0x38,\r\n  0x01,0x09,0x13,0x16,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x24,0x0c,0x1e,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x1e,\r\n  0x27,0x13,0x13,0x13,0x13,0x13,0x28,0x1e,0x1e,0x1e,0x13,0x13,0x1e,\r\n  0x1e,0x20,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x11,0x1e,0x02,\r\n  0x13,0x0b,0x1f,0x10,0x1e,0x0e,0x01,0x01,0x01,0x01,0x2c,0x1e,0x0d,\r\n  0x02,0x14,0x19,0x05,0x23,0x14,0x13,0x1e,0x1e,0x01,0x09,0x13,0x16,\r\n  0x2c,0x00,0x00,0x00,0x00,0x11,0x24,0x0c,0x1e,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x34,0x1e,0x18,0x28,0x12,0x31,0x06,\r\n  0x13,0x13,0x02,0x1e,0x1e,0x0a,0x13,0x0a,0x1e,0x38,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x32,0x1e,0x0b,0x13,0x0c,0x13,0x31,\r\n  0x1e,0x36,0x01,0x01,0x01,0x01,0x2c,0x1e,0x29,0x13,0x0b,0x18,0x2a,\r\n  0x19,0x12,0x14,0x1e,0x1e,0x01,0x09,0x13,0x16,0x2c,0x00,0x00,0x00,\r\n  0x00,0x11,0x24,0x0c,0x1e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x04,0x1e,0x1e,0x1e,0x27,0x13,0x13,0x13,0x18,0x1e,\r\n  0x1e,0x13,0x13,0x1e,0x1e,0x3d,0x3d,0x2e,0x2b,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x30,0x1e,0x15,0x27,0x12,0x19,0x09,0x1e,0x20,0x01,0x01,\r\n  0x01,0x01,0x2c,0x1e,0x12,0x05,0x05,0x09,0x31,0x0b,0x0c,0x1f,0x1e,\r\n  0x1e,0x01,0x09,0x13,0x16,0x2c,0x00,0x00,0x00,0x00,0x11,0x24,0x0c,\r\n  0x1e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x1e,\r\n  0x1e,0x18,0x25,0x06,0x0d,0x13,0x13,0x15,0x1e,0x19,0x13,0x03,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x2b,0x01,0x01,0x01,0x01,0x0e,0x11,0x1e,\r\n  0x09,0x16,0x03,0x2a,0x1e,0x1d,0x01,0x01,0x01,0x01,0x01,0x2c,0x1e,\r\n  0x0d,0x0c,0x24,0x06,0x19,0x02,0x19,0x1f,0x1e,0x1e,0x01,0x09,0x13,\r\n  0x16,0x39,0x00,0x00,0x00,0x00,0x11,0x24,0x1f,0x1e,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x35,0x1e,0x2d,0x13,0x13,0x0a,\r\n  0x06,0x13,0x13,0x0b,0x1e,0x13,0x1f,0x1e,0x1e,0x12,0x0d,0x0d,0x28,\r\n  0x1e,0x2c,0x01,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x05,0x05,0x0c,0x13,\r\n  0x03,0x1e,0x17,0x01,0x01,0x01,0x01,0x3a,0x1e,0x2d,0x0b,0x14,0x23,\r\n  0x22,0x14,0x1f,0x28,0x1e,0x38,0x01,0x09,0x19,0x2a,0x39,0x00,0x00,\r\n  0x00,0x00,0x11,0x24,0x22,0x1e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x38,0x1e,0x0d,0x13,0x13,0x13,0x13,0x13,0x1e,\r\n  0x22,0x13,0x1e,0x1e,0x16,0x13,0x13,0x13,0x1f,0x1e,0x40,0x01,0x01,\r\n  0x01,0x38,0x1e,0x2d,0x1f,0x05,0x05,0x13,0x0c,0x1e,0x1e,0x40,0x39,\r\n  0x17,0x01,0x01,0x01,0x38,0x1e,0x21,0x28,0x24,0x0d,0x06,0x31,0x1e,\r\n  0x1e,0x17,0x01,0x09,0x05,0x03,0x39,0x00,0x00,0x00,0x00,0x38,0x24,\r\n  0x1f,0x1e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x2e,0x1e,0x1e,0x09,0x03,0x16,0x31,0x1e,0x1e,0x13,0x23,0x1e,0x1e,\r\n  0x14,0x13,0x1f,0x13,0x23,0x1e,0x38,0x01,0x01,0x35,0x1e,0x09,0x19,\r\n  0x0c,0x1f,0x23,0x13,0x24,0x1e,0x1e,0x1e,0x1e,0x1e,0x17,0x01,0x01,\r\n  0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x17,0x01,0x01,0x18,\r\n  0x12,0x2a,0x11,0x00,0x00,0x00,0x00,0x38,0x06,0x05,0x1e,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x38,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x0c,0x13,0x1e,0x1e,0x2a,0x13,0x21,0x2a,0x13,\r\n  0x29,0x1e,0x1e,0x1c,0x01,0x08,0x1e,0x25,0x1f,0x13,0x13,0x13,0x1e,\r\n  0x0a,0x22,0x05,0x19,0x26,0x1e,0x3a,0x01,0x01,0x01,0x01,0x3c,0x1c,\r\n  0x2c,0x2c,0x1c,0x3c,0x01,0x01,0x01,0x01,0x09,0x0b,0x2a,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x06,0x1f,0x1e,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x17,0x38,0x1e,0x2a,\r\n  0x13,0x26,0x1e,0x1e,0x23,0x0c,0x0b,0x05,0x22,0x13,0x23,0x1e,0x38,\r\n  0x01,0x08,0x1e,0x16,0x0b,0x13,0x1f,0x1f,0x1e,0x14,0x0c,0x0c,0x13,\r\n  0x15,0x1e,0x1b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x18,0x19,0x13,0x0b,0x05,0x0c,0x0b,0x14,0x05,\r\n  0x1f,0x05,0x18,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x0f,0x1e,0x1e,0x0c,0x13,0x1e,0x1e,0x1e,\r\n  0x0b,0x0c,0x23,0x13,0x13,0x13,0x22,0x1e,0x33,0x01,0x2b,0x1e,0x21,\r\n  0x0c,0x13,0x1f,0x13,0x0b,0x23,0x13,0x05,0x05,0x1e,0x1e,0x36,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x09,0x22,0x14,0x14,0x13,0x1a,0x19,0x13,0x02,0x05,0x05,0x18,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x11,0x1e,0x19,0x13,0x25,0x1e,0x38,0x1e,0x1e,0x1e,0x1e,0x0b,\r\n  0x23,0x13,0x1e,0x1e,0x11,0x01,0x01,0x38,0x1e,0x21,0x13,0x05,0x13,\r\n  0x13,0x1f,0x13,0x14,0x21,0x1e,0x38,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x1e,0x1e,\r\n  0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0f,0x1e,0x16,\r\n  0x28,0x1e,0x40,0x2b,0x04,0x3e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,\r\n  0x0e,0x01,0x01,0x2b,0x38,0x1e,0x1e,0x21,0x0a,0x16,0x25,0x03,0x1e,\r\n  0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x07,0x1e,0x1e,0x1e,0x2b,0x01,\r\n  0x01,0x01,0x01,0x1c,0x1d,0x1e,0x1e,0x38,0x2b,0x01,0x01,0x01,0x01,\r\n  0x2b,0x38,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x38,0x2b,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x20,0x3c,0x2e,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,\r\n  0x3b,0x3c,0x08,0x17,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,\r\n  0x00,0x00,0x00,0x02,0xff,0xff,0xff,0x00,0xb3,0xb3,0xb3,0x80,0x3b,\r\n  0x3b,0x3b,0x80,0x00,0x00,0x00,0x52,0xe4,0xe4,0xe4,0x80,0x7b,0x7b,\r\n  0x7b,0x80,0x00,0x00,0x00,0x72,0x00,0x00,0x00,0x2a,0x14,0x14,0x14,\r\n  0x80,0x5b,0x5b,0x5b,0x80,0xcc,0xcc,0xcc,0x80,0xf4,0xf4,0xf4,0x80,\r\n  0x9b,0x9b,0x9b,0x80,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x3e,0x23,\r\n  0x23,0x23,0x80,0x00,0x00,0x00,0x5e,0x8c,0x8c,0x8c,0x80,0xfe,0xfe,\r\n  0xfe,0x80,0xdc,0xdc,0xdc,0x80,0x6b,0x6b,0x6b,0x80,0x4b,0x4b,0x4b,\r\n  0x80,0x00,0x00,0x00,0x1e,0x0b,0x0b,0x0b,0x80,0xbc,0xbc,0xbc,0x80,\r\n  0xa4,0xa4,0xa4,0x80,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x46,0x00,\r\n  0x00,0x00,0x66,0x00,0x00,0x00,0x80,0xec,0xec,0xec,0x80,0x00,0x00,\r\n  0x00,0x0a,0x2b,0x2b,0x2b,0x80,0xd4,0xd4,0xd4,0x80,0xc4,0xc4,0xc4,\r\n  0x80,0x84,0x84,0x84,0x80,0x54,0x54,0x54,0x80,0x74,0x74,0x74,0x80,\r\n  0xac,0xac,0xac,0x80,0x64,0x64,0x64,0x80,0x94,0x94,0x94,0x80,0x44,\r\n  0x44,0x44,0x80,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x56,0x1b,0x1b,\r\n  0x1b,0x80,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x22,0x00,0x00,0x00,\r\n  0x4a,0x33,0x33,0x33,0x80,0x00,0x00,0x00,0x6a,0x00,0x00,0x00,0x7a,\r\n  0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x1a,0x00,\r\n  0x00,0x00,0x42,0x00,0x00,0x00,0x62,0x00,0x00,0x00,0x5a,0x00,0x00,\r\n  0x00,0x3a,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0x26,0x00,0x00,0x00,\r\n  0x4e,0x00,0x00,0x00,0x6e,0xe7,0xe8,0xe8,0x80,0x00,0x00,0x00,0x76,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x00,0x00,\r\n  0x00,0x01,0x00,0x01,0x00,0x11,0x00,0x11,0x00,0x13,0x00,0x01,0x00,\r\n  0x10,0x00,0x11,0x00,0x24,0x00,0x01,0x00,0x10,0x00,0x12,0x00,0x35,\r\n  0x00,0x01,0x00,0x0f,0x00,0x11,0x00,0x45,0x00,0x01,0x00,0x0e,0x00,\r\n  0x11,0x00,0x54,0x00,0x01,0x00,0x0e,0x00,0x11,0x00,0x63,0x00,0x01,\r\n  0x00,0x11,0x00,0x12,0x00,0x75,0x00,0x01,0x00,0x0f,0x00,0x11,0x00,\r\n  0x85,0x00,0x01,0x00,0x0a,0x00,0x11,0x00,0x90,0x00,0x01,0x00,0x0f,\r\n  0x00,0x12,0x00,0xa0,0x00,0x01,0x00,0x10,0x00,0x11,0x00,0xb1,0x00,\r\n  0x01,0x00,0x0d,0x00,0x11,0x00,0xbf,0x00,0x01,0x00,0x13,0x00,0x11,\r\n  0x00,0xd3,0x00,0x01,0x00,0x11,0x00,0x11,0x00,0xe5,0x00,0x01,0x00,\r\n  0x10,0x00,0x12,0x00,0x01,0x00,0x1a,0x00,0x10,0x00,0x11,0x00,0x12,\r\n  0x00,0x1a,0x00,0x10,0x00,0x15,0x00,0x23,0x00,0x1a,0x00,0x10,0x00,\r\n  0x11,0x00,0x34,0x00,0x1a,0x00,0x10,0x00,0x12,0x00,0x45,0x00,0x1a,\r\n  0x00,0x0f,0x00,0x11,0x00,0x55,0x00,0x1a,0x00,0x0f,0x00,0x12,0x00,\r\n  0x65,0x00,0x1a,0x00,0x11,0x00,0x11,0x00,0x77,0x00,0x1a,0x00,0x16,\r\n  0x00,0x11,0x00,0x8e,0x00,0x1a,0x00,0x11,0x00,0x12,0x00,0xa0,0x00,\r\n  0x1a,0x00,0x10,0x00,0x11,0x00,0xb1,0x00,0x1a,0x00,0x0f,0x00,0x11,\r\n  0x00,0xc1,0x00,0x1a,0x00,0x10,0x00,0x0f,0x00,0xd2,0x00,0x1a,0x00,\r\n  0x0f,0x00,0x12,0x00,0xe2,0x00,0x1a,0x00,0x0f,0x00,0x0f,0x00,0x01,\r\n  0x00,0x33,0x00,0x10,0x00,0x12,0x00,0x12,0x00,0x33,0x00,0x0f,0x00,\r\n  0x0f,0x00,0x22,0x00,0x33,0x00,0x0c,0x00,0x11,0x00,0x2f,0x00,0x33,\r\n  0x00,0x0f,0x00,0x12,0x00,0x3f,0x00,0x33,0x00,0x0e,0x00,0x11,0x00,\r\n  0x4e,0x00,0x33,0x00,0x09,0x00,0x11,0x00,0x58,0x00,0x33,0x00,0x0b,\r\n  0x00,0x15,0x00,0x64,0x00,0x33,0x00,0x10,0x00,0x11,0x00,0x75,0x00,\r\n  0x33,0x00,0x09,0x00,0x11,0x00,0x7f,0x00,0x33,0x00,0x14,0x00,0x0e,\r\n  0x00,0x94,0x00,0x33,0x00,0x0e,0x00,0x0e,0x00,0xa3,0x00,0x33,0x00,\r\n  0x10,0x00,0x0f,0x00,0xb4,0x00,0x33,0x00,0x0f,0x00,0x12,0x00,0xc4,\r\n  0x00,0x33,0x00,0x0f,0x00,0x12,0x00,0xd4,0x00,0x33,0x00,0x0d,0x00,\r\n  0x0e,0x00,0xe2,0x00,0x33,0x00,0x0f,0x00,0x0f,0x00,0xf2,0x00,0x33,\r\n  0x00,0x0d,0x00,0x10,0x00,0x01,0x00,0x4c,0x00,0x0f,0x00,0x0f,0x00,\r\n  0x11,0x00,0x4c,0x00,0x0f,0x00,0x0e,0x00,0x21,0x00,0x4c,0x00,0x16,\r\n  0x00,0x0e,0x00,0x38,0x00,0x4c,0x00,0x0f,0x00,0x0e,0x00,0x48,0x00,\r\n  0x4c,0x00,0x10,0x00,0x12,0x00,0x59,0x00,0x4c,0x00,0x0f,0x00,0x0e,\r\n  0x00,0x69,0x00,0x4c,0x00,0x10,0x00,0x11,0x00,0x7a,0x00,0x4c,0x00,\r\n  0x0c,0x00,0x10,0x00,0x87,0x00,0x4c,0x00,0x0f,0x00,0x10,0x00,0x97,\r\n  0x00,0x4c,0x00,0x10,0x00,0x11,0x00,0xa8,0x00,0x4c,0x00,0x10,0x00,\r\n  0x10,0x00,0xb9,0x00,0x4c,0x00,0x10,0x00,0x11,0x00,0xca,0x00,0x4c,\r\n  0x00,0x10,0x00,0x12,0x00,0xdb,0x00,0x4c,0x00,0x0f,0x00,0x10,0x00,\r\n  0xeb,0x00,0x4c,0x00,0x0f,0x00,0x11,0x00,0x01,0x00,0x65,0x00,0x0f,\r\n  0x00,0x12,0x00,0x11,0x00,0x65,0x00,0x09,0x00,0x09,0x00,0x1b,0x00,\r\n  0x65,0x00,0x09,0x00,0x0c,0x00,0x25,0x00,0x65,0x00,0x0b,0x00,0x09,\r\n  0x00,0x31,0x00,0x65,0x00,0x0a,0x00,0x12,0x00,0x3c,0x00,0x65,0x00,\r\n  0x0e,0x00,0x12,0x00,0x4b,0x00,0x65,0x00,0x09,0x00,0x0e,0x00,0x55,\r\n  0x00,0x65,0x00,0x07,0x00,0x0a,0x00,0x5d,0x00,0x65,0x00,0x0f,0x00,\r\n  0x0f,0x00,0x6d,0x00,0x65,0x00,0x0e,0x00,0x13,0x00,0x7c,0x00,0x65,\r\n  0x00,0x0e,0x00,0x0a,0x00,0x8b,0x00,0x65,0x00,0x11,0x00,0x11,0x00,\r\n  0x9d,0x00,0x65,0x00,0x0b,0x00,0x13,0x00,0xa9,0x00,0x65,0x00,0x0c,\r\n  0x00,0x13,0x00,0xb6,0x00,0x65,0x00,0x0c,0x00,0x0c,0x00,0xc3,0x00,\r\n  0x65,0x00,0x14,0x00,0x14,0x00,0xd8,0x00,0x65,0x00,0x09,0x00,0x09,\r\n  0x00,0xe2,0x00,0x65,0x00,0x0a,0x00,0x11,0x00,0xed,0x00,0x65,0x00,\r\n  0x0f,0x00,0x12,0x00,0x01,0x00,0x7e,0x00,0x0f,0x00,0x11,0x00,0x11,\r\n  0x00,0x7e,0x00,0x11,0x00,0x11,0x00,0x23,0x00,0x7e,0x00,0x10,0x00,\r\n  0x10,0x00,0x34,0x00,0x7e,0x00,0x08,0x00,0x14,0x00,0x3d,0x00,0x7e,\r\n  0x00,0x0f,0x00,0x15,0x00,0x4d,0x00,0x7e,0x00,0x0a,0x00,0x08,0x00,\r\n  0x58,0x00,0x7e,0x00,0x10,0x00,0x11,0x00,0x69,0x00,0x7e,0x00,0x0d,\r\n  0x00,0x0c,0x00,0x77,0x00,0x7e,0x00,0x0e,0x00,0x0b,0x00,0x86,0x00,\r\n  0x7e,0x00,0x0f,0x00,0x0a,0x00,0x96,0x00,0x7e,0x00,0x0c,0x00,0x15,\r\n  0x00,0xa3,0x00,0x7e,0x00,0x0e,0x00,0x07,0x00,0xb2,0x00,0x7e,0x00,\r\n  0x12,0x00,0x11,0x00,0xc5,0x00,0x7e,0x00,0x0f,0x00,0x13,0x00,0xd5,\r\n  0x00,0x7e,0x00,0x13,0x00,0x12,0x00,0xe9,0x00,0x7e,0x00,0x13,0x00,\r\n  0x12,0x00,0x01,0x00,0x97,0x00,0x0e,0x00,0x14,0x00,0x10,0x00,0x97,\r\n  0x00,0x0f,0x00,0x0c,0x00,0x20,0x00,0x97,0x00,0x0f,0x00,0x0f,0x00,\r\n  0x30,0x00,0x97,0x00,0x0f,0x00,0x0f,0x00,0x40,0x00,0x97,0x00,0x0f,\r\n  0x00,0x11,0x00,0x50,0x00,0x97,0x00,0x11,0x00,0x14,0x00,0x62,0x00,\r\n  0x97,0x00,0x0f,0x00,0x15,0x00,0x72,0x00,0x97,0x00,0x10,0x00,0x15,\r\n  0x00,0x83,0x00,0x97,0x00,0x0f,0x00,0x13,0x00,0x93,0x00,0x97,0x00,\r\n  0x0f,0x00,0x13,0x00,0xa3,0x00,0x97,0x00,0x11,0x00,0x14,0x00,0xb5,\r\n  0x00,0x97,0x00,0x0f,0x00,0x13,0x00,0xc5,0x00,0x97,0x00,0x0f,0x00,\r\n  0x14,0x00,0xd5,0x00,0x97,0x00,0x0f,0x00,0x14,0x00,0xe5,0x00,0x97,\r\n  0x00,0x0f,0x00,0x13,0x00,0xf5,0x00,0x97,0x00,0x0a,0x00,0x12,0x00,\r\n  0x01,0x00,0xb0,0x00,0x0a,0x00,0x13,0x00,0x0c,0x00,0xb0,0x00,0x0a,\r\n  0x00,0x12,0x00,0x17,0x00,0xb0,0x00,0x0f,0x00,0x13,0x00,0x27,0x00,\r\n  0xb0,0x00,0x0f,0x00,0x13,0x00,0x37,0x00,0xb0,0x00,0x10,0x00,0x15,\r\n  0x00,0x48,0x00,0xb0,0x00,0x0f,0x00,0x14,0x00,0x58,0x00,0xb0,0x00,\r\n  0x0f,0x00,0x13,0x00,0x68,0x00,0xb0,0x00,0x10,0x00,0x15,0x00,0x79,\r\n  0x00,0xb0,0x00,0x0f,0x00,0x12,0x00,0x89,0x00,0xb0,0x00,0x15,0x00,\r\n  0x0f,0x00,0x9f,0x00,0xb0,0x00,0x0f,0x00,0x13,0x00,0xaf,0x00,0xb0,\r\n  0x00,0x10,0x00,0x13,0x00,0xc0,0x00,0xb0,0x00,0x0e,0x00,0x13,0x00,\r\n  0xcf,0x00,0xb0,0x00,0x15,0x00,0x12,0x00,0xe5,0x00,0xb0,0x00,0x15,\r\n  0x00,0x12,0x00,0x01,0x00,0xc9,0x00,0x16,0x00,0x12,0x00,0x18,0x00,\r\n  0xc9,0x00,0x0f,0x00,0x12,0x00,0x28,0x00,0xc9,0x00,0x0c,0x00,0x0c,\r\n  0x00,0x35,0x00,0xc9,0x00,0x0c,0x00,0x0f,0x00,0x00\r\n  };\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxGeom.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxGeom.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  3/4/2002\r\n//****************************************************************************\r\n\r\n\r\n#include <gfx/xbox/p_nxgeom.h>\r\n\r\n#include <core/math.h>\r\n\r\n#include <gfx/skeleton.h>\r\n#include <gfx/xbox/p_nxmesh.h>\r\n#include <gfx/xbox/p_nxmodel.h>\r\n#include <gfx/xbox/p_nxtexture.h>\r\n#include <gfx/xbox/nx/instance.h>\r\n\r\n#include <xbdm.h>\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxGeom::CXboxGeom() : mp_init_mesh_list( NULL ), m_mesh_array( NULL ), m_visible( 0xDEADBEEF )\r\n{\r\n\tmp_instance = NULL;\r\n//\tmp_sector\t= NULL;\r\n\tm_scale.Set( 1.0f, 1.0f, 1.0f );\r\n\tm_active\t= true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxGeom::~CXboxGeom( void )\r\n{\r\n\tDestroyMeshArray();\r\n\r\n\tif( mp_instance != NULL )\r\n\t{\r\n\t\tdelete mp_instance;\r\n\t\tmp_instance = NULL;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Mesh List Functions\r\n//\r\n// The mesh list is only for initialization of the CGeom.  As we find all the\r\n// meshes for the CGeoms, we add them to the temporary lists.  When we are\r\n// done, the list is copied into a permanent array.\r\n//\r\n// All the list functions use the TopDownHeap for memory allocation.\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::InitMeshList( void )\r\n{\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().TopDownHeap());\r\n\tmp_init_mesh_list = new Lst::Head< NxXbox::sMesh >;\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::AddMesh( NxXbox::sMesh *mesh )\r\n{\r\n\tDbg_Assert( mp_init_mesh_list );\r\n\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().TopDownHeap());\r\n\tLst::Node< NxXbox::sMesh > *node = new Lst::Node< NxXbox::sMesh > (mesh);\r\n\tmp_init_mesh_list->AddToTail( node );\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::CreateMeshArray( void )\r\n{\r\n\tif( !m_mesh_array )\r\n\t{\r\n\t\tDbg_Assert( mp_init_mesh_list );\r\n\r\n\t\tm_num_mesh = mp_init_mesh_list->CountItems();\r\n\t\tif (m_num_mesh)\r\n\t\t{\r\n\t\t\tLst::Node< NxXbox::sMesh > *mesh, *next;\r\n\r\n\t\t\tm_mesh_array = new NxXbox::sMesh*[m_num_mesh];\r\n\t\t\tint k = 0;\r\n\t\t\tfor( mesh = mp_init_mesh_list->GetNext(); mesh; mesh = next )\r\n\t\t\t{\r\n\t\t\t\tnext\t\t\t= mesh->GetNext();\r\n\t\t\t\tm_mesh_array[k]\t= mesh->GetData();\r\n\t\t\t\tdelete mesh;\r\n\t\t\t\tk++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Delete temporary list.\r\n\t\tdelete mp_init_mesh_list;\r\n\t\tmp_init_mesh_list = NULL;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxGeom::RegisterMeshArray( bool just_count )\r\n{\r\n\t// Tells the engine to count or add the meshes for this sector to the rendering list for supplied scene id.\r\n\tif( just_count )\r\n\t{\r\n\t\tmp_scene->GetEngineScene()->CountMeshes( m_num_mesh, m_mesh_array );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_scene->GetEngineScene()->AddMeshes( m_num_mesh, m_mesh_array );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::DestroyMeshArray( void )\r\n{\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\t// Tells the engine to remove the meshes for this sector from the rendering list for supplied scene id.\r\n\t\tif( mp_scene && mp_scene->GetEngineScene())\r\n\t\t{\r\n\t\t\tmp_scene->GetEngineScene()->RemoveMeshes( m_num_mesh, m_mesh_array );\r\n\t\t}\r\n\r\n\t\t// Now actually go through and delete each mesh.\r\n\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[m];\r\n\t\t\tdelete p_mesh;\r\n\t\t}\r\n\r\n\t\tdelete [] m_mesh_array;\r\n\t\tm_mesh_array = NULL;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Generates an entirely new engine scene.                        */\r\n/* Used when instance-cloning CGeoms.                             */\r\n/*                                                                */\r\n/******************************************************************/\r\nNxXbox::sScene* CXboxGeom::GenerateScene( void )\r\n{\r\n\tNxXbox::sScene *p_scene = new NxXbox::sScene();\r\n\r\n\tp_scene->CountMeshes( m_num_mesh, m_mesh_array );\r\n\tp_scene->CreateMeshArrays();\r\n\tp_scene->AddMeshes( m_num_mesh, m_mesh_array );\r\n\tp_scene->SortMeshes();\r\n\r\n\t// Set the bounding box and bounding sphere.\r\n\tp_scene->m_bbox = m_bbox;\r\n\tp_scene->FigureBoundingVolumes();\r\n\t\r\n\treturn p_scene;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxGeom::plat_load_geom_data( CMesh *pMesh, CModel *pModel, bool color_per_material )\r\n{\r\n\t// The skeleton must exist by this point (unless it's a hacked up car).\r\n\tint\t\t\tnumBones = pModel->GetNumBones();\r\n\tMth::Matrix\ttemp;\r\n\t\r\n\ttemp.Identity();\r\n\r\n\tCXboxMesh *p_xbox_mesh = static_cast<CXboxMesh*>( pMesh );\r\n\t\r\n\t// Store a pointer to the CXboxMesh, used for obtaining CAS poly removal data.\r\n\tmp_mesh = p_xbox_mesh;\r\n\r\n\tCXboxModel *p_xbox_model = static_cast<CXboxModel*>( pModel );\r\n\r\n\tNxXbox::CInstance *p_instance = new NxXbox::CInstance( p_xbox_mesh->GetScene()->GetEngineScene(), temp, numBones, pModel->GetBoneTransforms());\r\n\t\r\n\tSetInstance( p_instance );\r\n\tp_instance->SetModel( pModel );\r\n\r\n    return true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_finalize( void )\r\n{\r\n\t// Scan through and remove degenerate indices...\r\n\tif( mp_instance )\r\n\t{\r\n\t\tNxXbox::sScene *p_scene = mp_instance->GetScene();\r\n\t\tif( p_scene )\r\n\t\t{\r\n\t\t\tfor( int m = 0; m < p_scene->m_num_mesh_entries; ++m )\r\n\t\t\t{\r\n\t\t\t\tNxXbox::sMesh *p_mesh = p_scene->m_meshes[m];\r\n\t\t\t\tp_mesh->Crunch();\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_set_active( bool active )\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\tmp_instance->SetActive( active );\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tm_active = active;\r\n\t\tif( m_mesh_array )\r\n\t\t{\r\n\t\t\tfor( uint m = 0; m < m_num_mesh; ++m )\r\n\t\t\t{\r\n\t\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[m];\r\n\t\t\t\tp_mesh->SetActive( active );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxGeom::plat_is_active( void ) const\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\treturn mp_instance->GetActive();\r\n\t}\t\r\n\treturn m_active;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::Vector &CXboxGeom::plat_get_world_position( void ) const\r\n{\r\n\tstatic Mth::Vector pos;\r\n\t\r\n\tif( mp_instance )\r\n\t{\r\n\t\tpos = mp_instance->GetTransform()->GetPos();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpos.Set( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\r\n\t\tNxXbox::sMesh *p_mesh = m_mesh_array[0];\r\n\t\tif( p_mesh )\r\n\t\t{\r\n\t\t\tp_mesh->GetPosition( &pos );\r\n\t\t}\r\n\t}\r\n\tDbg_Assert( pos[W] == 1.0f );\r\n\treturn pos;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_set_world_position( const Mth::Vector& pos )\r\n{\r\n\t// Ensure w component is correct.\r\n\tMth::Vector proper_pos( pos[X], pos[Y], pos[Z], 1.0f );\r\n\r\n\tif( mp_instance )\r\n\t{\r\n\t\tmp_instance->GetTransform()->SetPos( proper_pos );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Go through and adjust the individual meshes.\r\n\t\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[i];\r\n\t\t\tp_mesh->SetPosition( proper_pos );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::CBBox & CXboxGeom::plat_get_bounding_box( void ) const\r\n{\r\n\treturn m_bbox;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_set_bounding_sphere( const Mth::Vector& boundingSphere )\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\tNxXbox::sScene *p_scene = mp_instance->GetScene();\r\n\t\tif( p_scene )\r\n\t\t{\r\n\t\t\tp_scene->m_sphere_center.x\t= boundingSphere[X];\r\n\t\t\tp_scene->m_sphere_center.y\t= boundingSphere[Y];\r\n\t\t\tp_scene->m_sphere_center.z\t= boundingSphere[Z];\r\n\t\t\tp_scene->m_sphere_radius\t= boundingSphere[W];\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::Vector CXboxGeom::plat_get_bounding_sphere( void ) const\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\tNxXbox::sScene *p_scene = mp_instance->GetScene();\r\n\t\tif( p_scene )\r\n\t\t{\r\n\t\t\treturn Mth::Vector( p_scene->m_sphere_center.x, p_scene->m_sphere_center.y,  p_scene->m_sphere_center.z, p_scene->m_sphere_radius );\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn Mth::Vector( 0.0f, 0.0f, 0.0f, 10000.0f );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_set_orientation( const Mth::Matrix& orient )\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\tMth::Matrix *p_matrix = mp_instance->GetTransform();\r\n\t\tMth::Matrix new_orientation = *p_matrix;\r\n\t\tnew_orientation[X] = orient[X];\r\n\t\tnew_orientation[Y] = orient[Y];\r\n\t\tnew_orientation[Z] = orient[Z];\r\n\t\tmp_instance->SetTransform( new_orientation );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::Matrix &CXboxGeom::plat_get_orientation( void ) const\r\n{\r\n\tstatic Mth::Matrix orientation;\r\n\t\r\n\tif( mp_instance )\r\n\t{\r\n\t\torientation = *( mp_instance->GetTransform());\r\n\t\torientation[W] = Mth::Vector( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\t}\r\n\telse\r\n\t{\r\n\t\torientation.Identity();\r\n\t}\r\n\r\n\treturn orientation;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_rotate_y( Mth::ERot90 rot )\r\n{\r\n\tif( rot != Mth::ROT_0 )\r\n\t{\r\n\t\tif( mp_instance )\r\n\t\t{\r\n\t\t\tMth::Matrix *p_matrix = mp_instance->GetTransform();\r\n\r\n\t\t\t// Zero out translation component.\r\n\t\t\tMth::Matrix\tinstance_transform = *p_matrix;\r\n\t\t\tinstance_transform[W] = Mth::Vector(0.0f, 0.0f, 0.0f, 1.0f);\r\n\r\n\t\t\t// Build rotation matrix.\r\n\t\t\tMth::Matrix\trot_mat;\r\n\t\t\tfloat\t\trad = (float)((int)rot) * ( Mth::PI * 0.5f );\r\n\t\t\tMth::CreateRotateYMatrix( rot_mat, rad );\r\n\r\n\t\t\t// Rotate matrix.\r\n\t\t\trot_mat\t= instance_transform * rot_mat;\r\n\r\n\t\t\t// Replace translation component.\r\n\t\t\trot_mat[W] = p_matrix->GetPos();\r\n\r\n\t\t\tmp_instance->SetTransform( rot_mat );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Go through and adjust the individual meshes.\r\n\t\t\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n\t\t\t{\r\n\t\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[i];\r\n\t\t\t\tp_mesh->SetYRotation( rot );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxGeom::plat_render(Mth::Matrix* pRootMatrix, Mth::Matrix* pBoneMatrices, int numBones)\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\tmp_instance->SetTransform( *pRootMatrix );\r\n\t}\r\n    return true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_set_bone_matrix_data( Mth::Matrix* pBoneMatrices, int numBones )\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\tMth::Matrix* p_bone_matrices\t= mp_instance->GetBoneTransforms();\r\n\t\tCopyMemory( p_bone_matrices, pBoneMatrices, numBones * sizeof( Mth::Matrix ));\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxGeom::plat_hide_polys( uint32 mask )\r\n{\r\n\tif( mp_mesh )\r\n\t{\r\n\t\t// Obtain a pointer to the Xbox scene.\r\n\t\tNxXbox::sScene *p_engine_scene = GetInstance()->GetScene();\r\n\r\n\t\t// Request the scene to hide the relevant polys.\r\n\t\tp_engine_scene->HidePolys( mask, mp_mesh->GetCASData(), mp_mesh->GetNumCASData());\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_set_visibility( uint32 mask )\r\n{\r\n\t// Set values\r\n\tm_visible = mask;\r\n\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\tfor( uint m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[m];\r\n\t\t\tp_mesh->SetVisibility((uint8)mask );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 CXboxGeom::plat_get_visibility( void ) const\r\n{\r\n\treturn m_visible | 0xFFFFFF00;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_set_color( Image::RGBA rgba )\r\n{\r\n\t// If we are setting the color (which is used as a multiplier) to (0x80,0x80,0x80), it is effectively\r\n\t// just turning the coloring off...\r\n\t// Note that some indoor stuff is set to 0x808081, since on Ps2 it needs to be set to something\r\n\t// other than 0x808080 in order to ensure that it doesn't inherit the color from the parent node.\r\n\t// This is not an issue for Xbox, so it treats the two values the same.\r\n\tif((( rgba.r == 0x80 ) || ( rgba.r == 0x81 )) && ( rgba.g == 0x80 ) && ( rgba.b == 0x80 ))\r\n\t{\r\n\t\tplat_clear_color();\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Oofa, nasty hack.\r\n\tif( mp_instance )\r\n\t{\r\n\t\t// Grab the engine scene from the geom, and set all meshes to the color.\r\n\t\tNxXbox::sScene *p_scene = mp_instance->GetScene();\r\n\t\tfor( int i = 0; i < p_scene->m_num_mesh_entries; ++i )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = p_scene->m_meshes[i];\r\n\t\t\tp_mesh->m_flags |= NxXbox::sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE;\r\n\t\t\tp_mesh->m_material_color_override[0] = (float)rgba.r / 255.0f;\r\n\t\t\tp_mesh->m_material_color_override[1] = (float)rgba.g / 255.0f;\r\n\t\t\tp_mesh->m_material_color_override[2] = (float)rgba.b / 255.0f;\r\n\t\t}\r\n\t}\r\n\telse if( m_mesh_array != NULL )\r\n\t{\r\n\t\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[i];\r\n\t\t\tp_mesh->m_flags |= NxXbox::sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE;\r\n\t\t\tp_mesh->m_material_color_override[0] = (float)rgba.r / 255.0f;\r\n\t\t\tp_mesh->m_material_color_override[1] = (float)rgba.g / 255.0f;\r\n\t\t\tp_mesh->m_material_color_override[2] = (float)rgba.b / 255.0f;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_clear_color( void )\r\n{\r\n\t// Oofa, nasty hack.\r\n\tif( mp_instance )\r\n\t{\r\n\t\t// Grab the engine scene from the geom, and clear all meshes of the flag.\r\n\t\tNxXbox::sScene *p_scene = mp_instance->GetScene();\r\n\t\tfor( int i = 0; i < p_scene->m_num_mesh_entries; ++i )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = p_scene->m_meshes[i];\r\n\t\t\tp_mesh->m_flags &= ~NxXbox::sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE;\r\n\t\t}\r\n\t}\r\n\telse if( m_mesh_array != NULL )\r\n\t{\r\n\t\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[i];\r\n\t\t\tp_mesh->m_flags &= ~NxXbox::sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxGeom::plat_set_material_color( uint32 mat_name_checksum, int pass, Image::RGBA rgba )\r\n{\r\n\tbool something_changed = false;\r\n\r\n\tif( mp_instance && mp_instance->GetScene())\r\n\t{\r\n\t\tfor( int m = 0; m < mp_instance->GetScene()->m_num_mesh_entries; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh\t\t*p_mesh\t= mp_instance->GetScene()->m_meshes[m];\r\n\t\t\tNxXbox::sMaterial\t*p_mat\t= p_mesh->mp_material;\r\n\t\t\tif( p_mat )\r\n\t\t\t{\r\n\t\t\t\tbool\twant_this_material\t= false;\r\n\t\t\t\tint\t\tadjusted_pass\t\t= pass;\r\n\r\n\t\t\t\t// We are searching for materials with a matching name. However there is a caveat in that the\r\n\t\t\t\t// conversion process sometimes creates new materials for geometry flagged as 'render as separate', or for\r\n\t\t\t\t// geometry which is mapped with only certain passes of a multipass material (or both cases).\r\n\t\t\t\t// In such a case, the new material name checksum will differ from the original material name checksum,\r\n\t\t\t\t// with the following bits having significance (i.e. consider bitflags = new_namechecksum - old_namechecksum ):\r\n\t\t\t\t//\r\n\t\t\t\t// Bits 3->6\tPass flags indicating which passes of the original material this material uses\r\n\t\t\t\t// Bits 0->2\tAbsolute number ('render as separate' flagged geometry) indicating which single pass of the material this material represents.\r\n\t\t\t\tif( p_mat->m_name_checksum == mat_name_checksum )\r\n\t\t\t\t\twant_this_material = true;\r\n\t\t\t\telse if(( p_mat->m_name_checksum > mat_name_checksum ) && (( p_mat->m_name_checksum - mat_name_checksum ) <= 0x7F ))\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 checksum_diff\t\t= p_mat->m_name_checksum - mat_name_checksum;\r\n\t\t\t\t\tuint32 render_separate_pass\t= checksum_diff & 0x07;\r\n\t\t\t\t\tuint32 pass_flags\t\t\t= checksum_diff >> 3;\r\n\r\n\t\t\t\t\tif( render_separate_pass )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( render_separate_pass == ( pass + 1 ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\twant_this_material = true;\r\n\r\n\t\t\t\t\t\t\t// Readjust the pass to zero, since this material was formed as a single pass of a multipass material.\r\n\t\t\t\t\t\t\tadjusted_pass = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( pass_flags )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// This material was created during scene conversion from another material with more passes.\r\n\t\t\t\t\t\tif( pass_flags & ( 1 << pass ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\twant_this_material = true;\r\n\t\t\t\t\t\t\tfor( int p = 0; p < pass; ++p )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif(( pass_flags & ( 1 << p )) == 0 )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Readjust the pass down by 1, since this material was created as a subset of another material.\r\n\t\t\t\t\t\t\t\t\t--adjusted_pass;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( want_this_material )\r\n\t\t\t\t{\r\n\t\t\t\t\tif((uint32)adjusted_pass < p_mat->m_passes )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( !( p_mat->m_flags[adjusted_pass] & MATFLAG_PASS_COLOR_LOCKED ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_mat->m_color[adjusted_pass][0] = (float)rgba.r / 255.0f;\r\n\t\t\t\t\t\t\tp_mat->m_color[adjusted_pass][1] = (float)rgba.g / 255.0f;\r\n\t\t\t\t\t\t\tp_mat->m_color[adjusted_pass][2] = (float)rgba.b / 255.0f;\r\n\r\n\t\t\t\t\t\t\tsomething_changed = true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn something_changed;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nImage::RGBA\tCXboxGeom::plat_get_color( void ) const\r\n{\r\n\tImage::RGBA rgba( 0, 0, 0, 0 );\r\n\r\n\tNxXbox::sMesh *p_mesh = NULL;\r\n\r\n\tif( mp_instance )\r\n\t{\r\n\t\t// Grab the engine scene from the geom, and get a mesh color.\r\n\t\tNxXbox::sScene *p_scene = mp_instance->GetScene();\r\n\r\n\t\tif( p_scene->m_num_mesh_entries > 0 )\r\n\t\t\tp_mesh = p_scene->m_meshes[0];\r\n\t}\r\n\telse if( m_mesh_array != NULL )\r\n\t{\r\n\t\tp_mesh = m_mesh_array[0];\r\n\t}\r\n\r\n\tif( p_mesh && ( p_mesh->m_flags & NxXbox::sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE ))\r\n\t{\r\n\t\trgba.r = (uint8)( p_mesh->m_material_color_override[0] * 255.0f );\r\n\t\trgba.g = (uint8)( p_mesh->m_material_color_override[1] * 255.0f );\r\n\t\trgba.b = (uint8)( p_mesh->m_material_color_override[2] * 255.0f );\r\n\t}\r\n\t\r\n\treturn rgba;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CXboxGeom::plat_get_num_render_verts( void )\r\n{\r\n\tDbg_MsgAssert( m_mesh_array, ( \"Invalid for instanced sectors\" ));\r\n\t\r\n\tint total_verts = 0;\r\n\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[m];\r\n\t\t\ttotal_verts += p_mesh->m_num_vertices;\r\n\t\t}\r\n\t}\r\n\treturn total_verts;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_get_render_verts( Mth::Vector *p_verts )\r\n{\r\n\tDbg_MsgAssert( m_mesh_array, ( \"Invalid for instanced sectors\" ));\r\n\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[m];\r\n\r\n\t\t\t// Obtain a read-only lock on the mesh data.\r\n\t\t\tD3DVECTOR *p_pos;\r\n\t\t\tp_mesh->mp_vertex_buffer[0]->Lock( 0, 0, (BYTE**)&p_pos, D3DLOCK_READONLY | D3DLOCK_NOFLUSH );\r\n\r\n\t\t\t// Copy over every vertex position in this mesh.\r\n\t\t\tfor( uint32 v = 0; v < p_mesh->m_num_vertices; ++v )\r\n\t\t\t{\r\n\t\t\t\tp_verts->Set( p_pos->x, p_pos->y, p_pos->z );\r\n\r\n\t\t\t\t++p_verts;\r\n\t\t\t\tp_pos = (D3DVECTOR*)((BYTE*)p_pos + p_mesh->m_vertex_stride );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_get_render_colors( Image::RGBA *p_colors )\r\n{\r\n\tDbg_MsgAssert( m_mesh_array, ( \"Invalid for instanced sectors\" ));\r\n\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[m];\r\n\r\n\t\t\t// Obtain a read-only lock on the mesh data.\r\n\t\t\tImage::RGBA *p_col;\r\n\t\t\tp_mesh->mp_vertex_buffer[0]->Lock( 0, 0, (BYTE**)&p_col, D3DLOCK_READONLY | D3DLOCK_NOFLUSH );\r\n\t\t\tp_col = (Image::RGBA*)((BYTE*)p_col + p_mesh->m_diffuse_offset );\r\n\r\n\t\t\t// Copy over every vertex color in this mesh, swapping red and blue.\r\n\t\t\tfor( uint32 v = 0; v < p_mesh->m_num_vertices; ++v )\r\n\t\t\t{\r\n\t\t\t\tp_colors->r = p_col->b;\r\n\t\t\t\tp_colors->g = p_col->g;\r\n\t\t\t\tp_colors->b = p_col->r;\r\n\t\t\t\tp_colors->a = p_col->a;\r\n\r\n\t\t\t\t++p_colors;\r\n\t\t\t\tp_col = (Image::RGBA*)((BYTE*)p_col + p_mesh->m_vertex_stride );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_set_render_verts( Mth::Vector *p_verts )\r\n{\r\n\tDbg_MsgAssert( m_mesh_array, ( \"Invalid for instanced sectors\" ));\r\n\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[m];\r\n\r\n\t\t\t// Obtain a writeable lock on the mesh data.\r\n\t\t\tD3DVECTOR *p_pos;\r\n\t\t\tp_mesh->mp_vertex_buffer[0]->Lock( 0, 0, (BYTE**)&p_pos, D3DLOCK_NOFLUSH );\r\n\r\n\t\t\t// Will need to store the min and max points in order to calculate the new bounding sphere for the mesh.\r\n\t\t\tMth::CBBox bbox;\r\n\r\n\t\t\t// Copy over every vertex position in this mesh.\r\n\t\t\tfor( uint32 v = 0; v < p_mesh->m_num_vertices; ++v )\r\n\t\t\t{\r\n\t\t\t\tp_pos->x = p_verts->GetX();\r\n\t\t\t\tp_pos->y = p_verts->GetY();\r\n\t\t\t\tp_pos->z = p_verts->GetZ();\r\n\r\n\t\t\t\t// Add this point to the bounding box.\r\n\t\t\t\tbbox.AddPoint( *p_verts );\r\n\r\n\t\t\t\t++p_verts;\r\n\t\t\t\tp_pos = (D3DVECTOR*)((BYTE*)p_pos + p_mesh->m_vertex_stride );\r\n\t\t\t}\r\n\r\n\t\t\t// Now refigure the bounding sphere.\r\n\t\t\tMth::Vector sphere_center\t= bbox.GetMin() + ( 0.5f * ( bbox.GetMax() - bbox.GetMin()));\r\n\t\t\tp_mesh->m_sphere_center.x\t= sphere_center[X];\r\n\t\t\tp_mesh->m_sphere_center.y\t= sphere_center[Y];\r\n\t\t\tp_mesh->m_sphere_center.z\t= sphere_center[Z];\r\n\t\t\tp_mesh->m_sphere_radius\t\t= ( bbox.GetMax() - sphere_center ).Length();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_set_render_colors( Image::RGBA *p_colors )\r\n{\r\n\tDbg_MsgAssert( m_mesh_array, ( \"Invalid for instanced sectors\" ));\r\n\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh*\tp_mesh\t\t\t= m_mesh_array[m];\r\n\t\t\tImage::RGBA*\tp_colors_save\t= p_colors;\r\n\r\n\t\t\t// The mesh may contain more than one vertex set, usually in the case of vertex wibbling.\r\n\t\t\tfor( uint32 v = 0; v < p_mesh->m_num_vertex_buffers; ++v )\r\n\t\t\t{\r\n\t\t\t\tp_colors = p_colors_save;\r\n\r\n\t\t\t\t// Obtain a writeable lock on the mesh data.\r\n\t\t\t\tImage::RGBA *p_col;\r\n\t\t\t\tp_mesh->mp_vertex_buffer[v]->Lock( 0, 0, (BYTE**)&p_col, D3DLOCK_NOFLUSH );\r\n\t\t\t\tp_col = (Image::RGBA*)((BYTE*)p_col + p_mesh->m_diffuse_offset );\r\n\r\n\t\t\t\t// Copy over every vertex color in this mesh, swapping red and blue.\r\n\t\t\t\tfor( uint32 v = 0; v < p_mesh->m_num_vertices; ++v )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_col->b = p_colors->r;\r\n\t\t\t\t\tp_col->g = p_colors->g;\r\n\t\t\t\t\tp_col->r = p_colors->b;\r\n\t\t\t\t\tp_col->a = p_colors->a;\r\n\r\n\t\t\t\t\t++p_colors;\r\n\t\t\t\t\tp_col = (Image::RGBA*)((BYTE*)p_col + p_mesh->m_vertex_stride );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_set_scale( const Mth::Vector & scale )\r\n{\r\n\tDbg_MsgAssert( m_mesh_array, ( \"Invalid for instanced sectors\" ));\r\n\r\n\tm_scale = scale;\r\n\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[m];\r\n\r\n\t\t\tMth::Vector current_pos( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\t\t\tp_mesh->GetPosition( &current_pos );\r\n\t\t\t\r\n\t\t\t// Obtain a writeable lock on the mesh data.\r\n\t\t\tD3DVECTOR *p_pos;\r\n\t\t\tp_mesh->mp_vertex_buffer[0]->Lock( 0, 0, (BYTE**)&p_pos, D3DLOCK_NOFLUSH );\r\n\r\n\t\t\t// Scale over every vertex position in this mesh.\r\n\t\t\tfor( uint32 v = 0; v < p_mesh->m_num_vertices; ++v )\r\n\t\t\t{\r\n\t\t\t\tp_pos->x\t= (( p_pos->x - current_pos[X] ) * scale[X] ) + current_pos[X];\r\n\t\t\t\tp_pos->y\t= (( p_pos->y - current_pos[Y] ) * scale[Y] ) + current_pos[Y];\r\n\t\t\t\tp_pos->z\t= (( p_pos->z - current_pos[Z] ) * scale[Z] ) + current_pos[Z];\r\n\r\n\t\t\t\tp_pos\t\t= (D3DVECTOR*)((BYTE*)p_pos + p_mesh->m_vertex_stride );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nMth::Vector CXboxGeom::plat_get_scale() const\r\n{\r\n\treturn m_scale;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_set_uv_wibble_params( float u_vel, float u_amp, float u_freq, float u_phase,\r\n\t\t\t\t\t\t\t\t\t\t   float v_vel, float v_amp, float v_freq, float v_phase )\r\n{\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh\t\t*p_mesh\t= m_mesh_array[m];\r\n\t\t\tNxXbox::sMaterial\t*p_mat\t= p_mesh->mp_material;\r\n\t\t\tif( p_mat )\r\n\t\t\t{\r\n\t\t\t\t// Find the first pass that wibbles.\r\n\t\t\t\tfor( uint32 p = 0; p < p_mat->m_passes; ++p )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( p_mat->mp_UVWibbleParams[p] )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UVel\t\t\t= u_vel;\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_VVel\t\t\t= v_vel;\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UAmplitude\t= u_amp;\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_VAmplitude\t= v_amp;\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UFrequency\t= u_freq;\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_VFrequency\t= v_freq;\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UPhase\t\t= u_phase;\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_VPhase\t\t= v_phase;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_use_explicit_uv_wibble( bool yes )\r\n{\r\n\tif( mp_instance && mp_instance->GetScene())\r\n\t{\r\n\t\tfor( int m = 0; m < mp_instance->GetScene()->m_num_mesh_entries; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh\t\t*p_mesh\t= mp_instance->GetScene()->m_meshes[m];\r\n\t\t\tNxXbox::sMaterial\t*p_mat\t= p_mesh->mp_material;\r\n\t\t\tif( p_mat )\r\n\t\t\t{\r\n\t\t\t\tfor( uint32 p = 0; p < p_mat->m_passes; ++p )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( p_mat->mp_UVWibbleParams[p] )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_mat->m_flags[p] |= MATFLAG_EXPLICIT_UV_WIBBLE;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_set_uv_wibble_offsets( float u_offset, float v_offset )\r\n{\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh\t\t*p_mesh\t= m_mesh_array[m];\r\n\t\t\tNxXbox::sMaterial\t*p_mat\t= p_mesh->mp_material;\r\n\t\t\tif( p_mat )\r\n\t\t\t{\r\n\t\t\t\t// Find the first pass that wibbles.\r\n\t\t\t\tfor( uint32 p = 0; p < p_mat->m_passes; ++p )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( p_mat->mp_UVWibbleParams[p] )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UVMatrix[2] = u_offset;\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UVMatrix[3] = v_offset;\r\n\t\t\t\t\t\tplat_use_explicit_uv_wibble( true );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxGeom::plat_set_uv_wibble_offsets( uint32 mat_name_checksum, int pass, float u_offset, float v_offset )\r\n{\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\tfor( uint32 m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh\t\t*p_mesh\t= m_mesh_array[m];\r\n\t\t\tNxXbox::sMaterial\t*p_mat\t= p_mesh->mp_material;\r\n\t\t\tif( p_mat && ( p_mat->m_name_checksum == mat_name_checksum ))\r\n\t\t\t{\r\n\t\t\t\t// Find the first pass that wibbles.\r\n//\t\t\t\tfor( uint32 p = 0; p < p_mat->m_passes; ++p )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( p_mat->mp_UVWibbleParams[p] )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_UWibbleOffset = u_offset;\r\n//\t\t\t\t\t\tp_mat->mp_UVWibbleParams[p]->m_VWibbleOffset = v_offset;\r\n//\t\t\t\t\t\tplat_use_explicit_uv_wibble( true );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxGeom::plat_set_uv_matrix( uint32 mat_name_checksum, int pass, const Mth::Matrix& mat )\r\n{\r\n\tif( mp_instance && mp_instance->GetScene())\r\n\t{\r\n\t\tfor( int m = 0; m < mp_instance->GetScene()->m_num_mesh_entries; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh\t\t*p_mesh\t= mp_instance->GetScene()->m_meshes[m];\r\n\t\t\tNxXbox::sMaterial\t*p_mat\t= p_mesh->mp_material;\r\n\t\t\tif( p_mat )\r\n\t\t\t{\r\n\t\t\t\tbool\twant_this_material\t= false;\r\n\t\t\t\tint\t\tadjusted_pass\t\t= pass;\r\n\r\n\t\t\t\t// We are searching for materials with a matching name. However there is a caveat in that the\r\n\t\t\t\t// conversion process sometimes creates new materials for geometry flagged as 'render as separate', or for\r\n\t\t\t\t// geometry which is mapped with only certain passes of a multipass material (or both cases).\r\n\t\t\t\t// In such a case, the new material name checksum will differ from the original material name checksum,\r\n\t\t\t\t// with the following bits having significance (i.e. consider bitflags = new_namechecksum - old_namechecksum ):\r\n\t\t\t\t//\r\n\t\t\t\t// Bits 3->6\tPass flags indicating which passes of the original material this material uses\r\n\t\t\t\t// Bits 0->2\tAbsolute number ('render as separate' flagged geometry) indicating which single pass of the material this material represents.\r\n\t\t\t\tif( p_mat->m_name_checksum == mat_name_checksum )\r\n\t\t\t\t{\r\n\t\t\t\t\twant_this_material = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if(( p_mat->m_name_checksum > mat_name_checksum ) && (( p_mat->m_name_checksum - mat_name_checksum ) <= 0x7F ))\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 checksum_diff\t\t= p_mat->m_name_checksum - mat_name_checksum;\r\n\t\t\t\t\tuint32 render_separate_pass\t= checksum_diff & 0x07;\r\n\t\t\t\t\tuint32 pass_flags\t\t\t= checksum_diff >> 3;\r\n\r\n\t\t\t\t\tif( render_separate_pass )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( render_separate_pass == ( pass + 1 ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\twant_this_material = true;\r\n\r\n\t\t\t\t\t\t\t// Readjust the pass to zero, since this material was formed as a single pass of a multipass material.\r\n\t\t\t\t\t\t\tadjusted_pass = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( pass_flags )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// This material was created during scene conversion from another material with more passes.\r\n\t\t\t\t\t\tif( pass_flags & ( 1 << pass ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\twant_this_material = true;\r\n\t\t\t\t\t\t\tfor( int p = 0; p < pass; ++p )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif(( pass_flags & ( 1 << p )) == 0 )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Readjust the pass down by 1, since this material was created as a subset of another material.\r\n\t\t\t\t\t\t\t\t\t--adjusted_pass;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( want_this_material )\r\n\t\t\t\t{\r\n\t\t\t\t\tif((uint32)adjusted_pass < p_mat->m_passes )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Create the wibble params if they don't exist already.\r\n\t\t\t\t\t\tif( p_mat->mp_UVWibbleParams[adjusted_pass] == NULL )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_mat->mp_UVWibbleParams[adjusted_pass]\t= new NxXbox::sUVWibbleParams;\r\n\r\n\t\t\t\t\t\t\t// Need to set flags to indicate that uv wibble is now in effect.\r\n\t\t\t\t\t\t\tp_mat->m_uv_wibble\t\t\t\t= true;\r\n\t\t\t\t\t\t\tp_mat->m_flags[adjusted_pass]  |= MATFLAG_UV_WIBBLE | MATFLAG_EXPLICIT_UV_WIBBLE;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Also need to switch vertex shaders if the current vertex shader does not support UV Transforms.\r\n\t\t\t\t\t\tif( p_mesh->m_vertex_shader[0] == WeightedMeshVS_VXC_1Weight )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_mesh->m_vertex_shader[0] = WeightedMeshVS_VXC_1Weight_UVTransform;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse if( p_mesh->m_vertex_shader[0] == WeightedMeshVS_VXC_2Weight )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_mesh->m_vertex_shader[0] = WeightedMeshVS_VXC_2Weight_UVTransform;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse if( p_mesh->m_vertex_shader[0] == WeightedMeshVS_VXC_3Weight )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_mesh->m_vertex_shader[0] = WeightedMeshVS_VXC_3Weight_UVTransform;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Set the matrix values.\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[adjusted_pass]->m_UVMatrix[0]\t= mat[0][0];\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[adjusted_pass]->m_UVMatrix[1]\t= mat[0][1];\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[adjusted_pass]->m_UVMatrix[2]\t= mat[3][0];\r\n\t\t\t\t\t\tp_mat->mp_UVWibbleParams[adjusted_pass]->m_UVMatrix[3]\t= mat[3][1];\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxGeom::plat_allocate_uv_matrix_params( uint32 mat_name_checksum, int pass )\r\n{\r\n\tif( mp_instance && mp_instance->GetScene())\r\n\t{\r\n\t\tbool changed_something = false;\r\n\r\n\t\tfor( int m = 0; m < mp_instance->GetScene()->m_num_mesh_entries; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh\t\t*p_mesh\t= mp_instance->GetScene()->m_meshes[m];\r\n\t\t\tNxXbox::sMaterial\t*p_mat\t= p_mesh->mp_material;\r\n\t\t\tif( p_mat )\r\n\t\t\t{\r\n\t\t\t\tbool\twant_this_material\t= false;\r\n\t\t\t\tint\t\tadjusted_pass\t\t= pass;\r\n\r\n\t\t\t\t// We are searching for materials with a matching name. However there is a caveat in that the\r\n\t\t\t\t// conversion process sometimes creates new materials for geometry flagged as 'render as separate', or for\r\n\t\t\t\t// geometry which is mapped with only certain passes of a multipass material (or both cases).\r\n\t\t\t\t// In such a case, the new material name checksum will differ from the original material name checksum,\r\n\t\t\t\t// with the following bits having significance (i.e. consider bitflags = new_namechecksum - old_namechecksum ):\r\n\t\t\t\t//\r\n\t\t\t\t// Bits 3->6\tPass flags indicating which passes of the original material this material uses\r\n\t\t\t\t// Bits 0->2\tAbsolute number ('render as separate' flagged geometry) indicating which single pass of the material this material represents.\r\n\t\t\t\tif( p_mat->m_name_checksum == mat_name_checksum )\r\n\t\t\t\t{\r\n\t\t\t\t\twant_this_material = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if(( p_mat->m_name_checksum > mat_name_checksum ) && (( p_mat->m_name_checksum - mat_name_checksum ) <= 0x7F ))\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 checksum_diff\t\t= p_mat->m_name_checksum - mat_name_checksum;\r\n\t\t\t\t\tuint32 render_separate_pass\t= checksum_diff & 0x07;\r\n\t\t\t\t\tuint32 pass_flags\t\t\t= checksum_diff >> 3;\r\n\r\n\t\t\t\t\tif( render_separate_pass )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( render_separate_pass == ( pass + 1 ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\twant_this_material = true;\r\n\r\n\t\t\t\t\t\t\t// Readjust the pass to zero, since this material was formed as a single pass of a multipass material.\r\n\t\t\t\t\t\t\tadjusted_pass = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( pass_flags )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// This material was created during scene conversion from another material with more passes.\r\n\t\t\t\t\t\tif( pass_flags & ( 1 << pass ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\twant_this_material = true;\r\n\t\t\t\t\t\t\tfor( int p = 0; p < pass; ++p )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif(( pass_flags & ( 1 << p )) == 0 )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Readjust the pass down by 1, since this material was created as a subset of another material.\r\n\t\t\t\t\t\t\t\t\t--adjusted_pass;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( want_this_material )\r\n\t\t\t\t{\r\n\t\t\t\t\tif((uint32)adjusted_pass < p_mat->m_passes )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Create the wibble params if they don't exist already.\r\n\t\t\t\t\t\tif( p_mat->mp_UVWibbleParams[adjusted_pass] == NULL )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_mat->mp_UVWibbleParams[adjusted_pass]\t= new NxXbox::sUVWibbleParams;\r\n\r\n\t\t\t\t\t\t\t// Need to set flags to indicate that uv wibble is now in effect.\r\n\t\t\t\t\t\t\tp_mat->m_uv_wibble\t\t\t\t\t\t= true;\r\n\t\t\t\t\t\t\tp_mat->m_flags[adjusted_pass]\t\t   |= MATFLAG_UV_WIBBLE | MATFLAG_EXPLICIT_UV_WIBBLE;\r\n\r\n\t\t\t\t\t\t\tchanged_something = true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn changed_something;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxGeom::plat_set_model_lights( CModelLights* p_model_lights )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxGeom *CXboxGeom::plat_clone( bool instance, CScene *p_dest_scene )\r\n{\r\n\tCXboxGeom *p_clone = NULL;\r\n\t\r\n\t// This is a CXboxGeom 'hanging' from a sector. Create a new CXboxGeom which will store the CInstance.\r\n\tp_clone = new CXboxGeom();\r\n\t\r\n\t// Create new meshes for the clone.\r\n\tp_clone->m_mesh_array\t= new NxXbox::sMesh*[m_num_mesh];\r\n\tp_clone->m_num_mesh\t\t= m_num_mesh;\r\n\tfor( uint32 m = 0; m < p_clone->m_num_mesh; ++m )\r\n\t{\r\n\t\tp_clone->m_mesh_array[m] = m_mesh_array[m]->Clone( instance );\r\n\t}\r\n\t\r\n\tif( instance == false )\r\n\t{\r\n\t\tp_clone->SetActive( true );\r\n\r\n\t\t// In this situation, we need to add the individual meshes to the scene.\r\n\t\t// Grab a temporary workspace buffer.\r\n\t\tNx::CXboxScene *p_xbox_scene\t\t\t\t\t\t= static_cast<CXboxScene*>( p_dest_scene );\r\n\t\tNxXbox::sScene *p_scene\t\t\t\t\t\t\t\t= p_xbox_scene->GetEngineScene();\r\n\t\tNxXbox::sMesh **p_temp_mesh_buffer\t\t\t\t\t= ( p_scene->m_num_mesh_entries > 0 ) ? new NxXbox::sMesh*[p_scene->m_num_mesh_entries] : NULL;\r\n\r\n\t\t// Set the scene pointer for the clone.\r\n\t\tp_clone->SetScene( p_xbox_scene );\r\n\t\t\r\n\t\t// Copy meshes over into the temporary workspace buffer.\r\n\t\tfor( int i = 0; i < p_scene->m_num_mesh_entries; ++i )\r\n\t\t{\r\n\t\t\tp_temp_mesh_buffer[i]\t= p_scene->m_meshes[i];\r\n\t\t}\r\n\r\n\t\t// Store how many meshes were present.\r\n\t\tint old_num_mesh_entries\t= p_scene->m_num_mesh_entries;\r\n\t\t\r\n\t\t// Delete current mesh array.\r\n\t\tdelete [] p_scene->m_meshes;\r\n\r\n\t\t// Important to set this to NULL.\r\n\t\tp_scene->m_meshes\t\t\t= NULL;\r\n\t\t\r\n\t\t// Include new meshes in count.\r\n\t\tp_scene->CountMeshes( m_num_mesh, m_mesh_array );\r\n\r\n\t\t// Allocate new mesh arrays.\r\n\t\tp_scene->CreateMeshArrays();\r\n\r\n\t\t// Copy old mesh data back in.\r\n\t\tfor( int i = 0; i < old_num_mesh_entries; ++i )\r\n\t\t{\r\n\t\t\tp_scene->m_meshes[i] = p_temp_mesh_buffer[i];\r\n\t\t}\r\n\r\n\t\t// Remove temporary arrays.\r\n\t\tdelete [] p_temp_mesh_buffer;\r\n\t\t\r\n\t\t// Add new meshes.\r\n\t\tp_scene->AddMeshes( p_clone->m_num_mesh, p_clone->m_mesh_array );\r\n\r\n\t\t// Sort the meshes.\r\n\t\tp_scene->SortMeshes();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Create a new scene which will be attached via the instance.\r\n\t\tp_clone->m_bbox\t\t\t= m_bbox;\r\n\t\tNxXbox::sScene *p_scene = p_clone->GenerateScene();\r\n\r\n\t\tp_clone->SetActive( true );\r\n\t\r\n\t\t// Create the instance.\r\n\t\tMth::Matrix temp;\r\n\t\ttemp.Identity();\r\n\t\tNxXbox::CInstance *p_instance = new NxXbox::CInstance( p_scene, temp, 1, NULL );\r\n\t\t\r\n\t\t// This instance will be the only object maintaining a reference to the attached scene, so we want to delete\r\n\t\t// the scene when the instance gets removed.\r\n\t\tp_instance->SetFlag( NxXbox::CInstance::INSTANCE_FLAG_DELETE_ATTACHED_SCENE );\r\n\r\n\t\t// Hook the clone up to the instance.\t\t\r\n\t\tp_clone->SetInstance( p_instance );\r\n\t}\r\n\treturn p_clone;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxGeom* CXboxGeom::plat_clone( bool instance, CModel* p_dest_model )\r\n{\r\n\tCXboxGeom* p_clone = NULL;\r\n\r\n\tNx::CXboxScene* p_xbox_scene = new CXboxScene;\r\n\tp_xbox_scene->SetEngineScene( mp_instance->GetScene() );\r\n\r\n\tp_clone\t\t\t\t= new CXboxGeom();\r\n\tp_clone->mp_scene\t= p_xbox_scene;\r\n\r\n\tint num_mesh\t\t= mp_instance->GetScene()->m_num_mesh_entries;\r\n\r\n\t// Create new meshes for the clone.\r\n\tp_clone->m_mesh_array\t= num_mesh ? new NxXbox::sMesh*[num_mesh] : NULL;\r\n\tp_clone->m_num_mesh\t\t= num_mesh;\r\n\tfor( uint32 m = 0; m < p_clone->m_num_mesh; ++m )\r\n\t{\r\n\t\tp_clone->m_mesh_array[m] = mp_instance->GetScene()->m_meshes[m]->Clone( instance );\r\n\t}\r\n\r\n\t// Create a new scene which will be attached via the instance.\r\n\tp_clone->m_bbox\t\t\t= m_bbox;\r\n\tNxXbox::sScene* p_scene = p_clone->GenerateScene();\r\n\r\n\t// Kill the temp scene.\r\n\tp_xbox_scene->SetEngineScene( NULL );\r\n\tdelete p_xbox_scene;\r\n\tp_clone->mp_scene\t\t= NULL;\r\n\r\n\tp_clone->SetActive( true );\r\n\r\n\t// Create the new bone array.\r\n\tint\t\t\t\tnum_bones\t= p_dest_model->GetNumBones();\r\n\tMth::Matrix*\tp_bones\t\t= new Mth::Matrix[num_bones];\r\n\tfor( int b = 0; b < num_bones; ++b )\r\n\t{\r\n\t\tp_bones[b].Identity();\r\n\t}\r\n\r\n\t// Create the instance.\r\n\tMth::Matrix temp;\r\n\ttemp.Identity();\r\n\tNxXbox::CInstance* p_instance\t= new NxXbox::CInstance( p_scene, temp, num_bones, p_bones );\r\n\t\r\n\tNx::CXboxModel* p_xbox_model\t= static_cast<CXboxModel*>( p_dest_model );\r\n\t((CXboxModel*)p_dest_model )->SetInstance( p_instance );\r\n\r\n\t// This instance will be the only object maintaining a reference to the attached scene, so we want to delete\r\n\t// the scene when the instance gets removed.\r\n\tp_instance->SetFlag( NxXbox::CInstance::INSTANCE_FLAG_DELETE_ATTACHED_SCENE );\r\n\r\n\t// Hook the clone up to the instance.\t\t\r\n\tp_clone->SetInstance( p_instance );\r\n\r\n\treturn p_clone;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxGeom.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxGeom.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  3/5/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_GEOM_H__\r\n#define\t__GFX_P_NX_GEOM_H__\r\n    \r\n#include \"gfx/nxgeom.h\"\r\n#include \"gfx/xbox/p_nxsector.h\"\r\n#include \"gfx/xbox/p_nxmesh.h\"\r\n\r\nnamespace Mth\r\n{\r\n\tclass Matrix;\r\n}\r\n\r\nnamespace NxXbox\r\n{\r\n\tclass CInstance;\r\n}\r\n\t\t\t\t\t\t   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CGeom\r\nclass CXboxGeom : public CGeom\r\n{\r\n                                      \r\npublic:\r\n\t\t\t\t\t\t\t\tCXboxGeom();\r\n\tvirtual \t\t\t\t\t~CXboxGeom();\r\n\tvoid\t\t\t\t\t\tSetInstance( NxXbox::CInstance *p_instance )\t\t{ mp_instance = p_instance; }\r\n\tNxXbox::CInstance\t\t\t*GetInstance( void )\t\t\t\t\t\t\t\t{ return mp_instance; }\r\n\tvoid\t\t\t\t\t\tInitMeshList();\r\n\tvoid\t\t\t\t\t\tClearMeshList();\r\n\tvoid\t\t\t\t\t\tAddMesh( NxXbox::sMesh * );\r\n\tLst::Head< NxXbox::sMesh >\t*GetMeshList();\r\n\r\n\tvoid\t\t\t\t\t\tCreateMeshArray();\r\n\tbool\t\t\t\t\t\tRegisterMeshArray( bool just_count );\r\n\tvoid\t\t\t\t\t\tDestroyMeshArray( void );\r\n\r\n\tconst Mth::CBBox &\t\t\tGetBoundingBox( void )\t\t\t{ return m_bbox; }\r\n\tvoid\t\t\t\t\t\tSetScene( CXboxScene *p_scene )\t{ mp_scene = p_scene; }\r\n\tNxXbox::sScene\t\t\t\t*GenerateScene( void );\r\n\r\n\r\nprivate:\t\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvirtual\tbool\t\t\t\t\tplat_load_geom_data( CMesh *pMesh, CModel *pModel, bool color_per_material );\r\n\tvirtual void\t\t\t\t\tplat_finalize( void );\r\n\tvirtual\tvoid\t\t\t\t\tplat_set_active( bool active );\r\n\tvirtual bool\t\t\t\t\tplat_is_active( void ) const;\r\n\tvirtual const Mth::CBBox &\t\tplat_get_bounding_box( void ) const;\r\n\tvirtual const Mth::Vector\t\tplat_get_bounding_sphere( void ) const;\r\n\tvirtual void\t\t\t\t\tplat_set_bounding_sphere( const Mth::Vector& boundingSphere );\r\n\r\n\tvirtual const Mth::Vector &\t\tplat_get_world_position( void ) const;\r\n\tvirtual void\t\t\t\t\tplat_set_world_position( const Mth::Vector& pos );\r\n\tvirtual const Mth::Matrix &\t\tplat_get_orientation( void ) const;\r\n\tvirtual void\t\t\t\t\tplat_set_orientation( const Mth::Matrix& orient );\r\n\tvirtual void\t\t\t\t\tplat_set_scale( const Mth::Vector & scale );\r\n\tvirtual Mth::Vector\t\t\t\tplat_get_scale( void ) const;\r\n\tvirtual void\t\t\t\t\tplat_rotate_y( Mth::ERot90 rot );\r\n\tvirtual bool\t\t\t\t\tplat_render( Mth::Matrix* pRootMatrix, Mth::Matrix* ppBoneMatrices, int numBones );\r\n\tvirtual void\t\t\t\t\tplat_set_bone_matrix_data( Mth::Matrix* pBoneMatrices, int numBones );\r\n\tvirtual bool\t\t\t\t\tplat_hide_polys( uint32 mask );\r\n\tvirtual uint32\t\t\t\t\tplat_get_visibility( void ) const;\r\n\tvirtual\tvoid\t\t\t\t\tplat_set_visibility( uint32 mask );\r\n\tvirtual void\t\t\t\t\tplat_set_color( Image::RGBA rgba );\r\n\tvirtual void\t\t\t\t\tplat_clear_color( void );\r\n\tvirtual Image::RGBA\t\t\t\tplat_get_color( void ) const;\r\n\tvirtual\tint\t\t\t\t\t\tplat_get_num_render_verts( void );\r\n\tvirtual\tvoid\t\t\t\t\tplat_get_render_verts( Mth::Vector *p_verts );\r\n\tvirtual\tvoid\t\t\t\t\tplat_get_render_colors( Image::RGBA *p_colors );\r\n\tvirtual void\t\t\t\t\tplat_set_render_verts( Mth::Vector *p_verts );\r\n\tvirtual\tvoid\t\t\t\t\tplat_set_render_colors( Image::RGBA *p_colors );\r\n\tvirtual void\t\t\t\t\tplat_set_model_lights( CModelLights* p_model_lights );\r\n\tvirtual void\t\t\t\t\tplat_set_uv_wibble_params( float u_vel, float u_amp, float u_freq, float u_phase, float v_vel, float v_amp, float v_freq, float v_phase );\r\n\tvirtual void\t\t\t\t\tplat_use_explicit_uv_wibble( bool yes );\r\n\tvirtual void\t\t\t\t\tplat_set_uv_wibble_offsets( float u_offset, float v_offset );\r\n\tvirtual bool\t\t\t\t\tplat_set_uv_wibble_offsets( uint32 mat_name_checksum, int pass, float u_offset, float v_offset );\r\n\tvirtual bool\t\t\t\t\tplat_set_uv_matrix( uint32 mat_name_checksum, int pass, const Mth::Matrix& mat );\r\n\tvirtual bool\t\t\t\t\tplat_set_material_color( uint32 mat_name_checksum, int pass, Image::RGBA rgba );\r\n\tvirtual bool\t\t\t\t\tplat_allocate_uv_matrix_params( uint32 mat_checksum, int pass );\r\n\r\n\tvirtual CXboxGeom*\t\t\t\tplat_clone( bool instance, CScene *p_dest_scene = NULL );\r\n\tvirtual CXboxGeom*\t\t\t\tplat_clone( bool instance, CModel *p_dest_model );\r\n\r\npublic:\r\n\tMth::CBBox\t\t\t\t\t\tm_bbox;\t\r\n\t\r\n\tCXboxScene *\t\t\t\t\tmp_scene;\r\n\tLst::Head< NxXbox::sMesh >\t\t*mp_init_mesh_list;   \r\n\tNxXbox::sMesh **\t\t\t\tm_mesh_array;\r\n\tuint\t\t\t\t\t\t\tm_num_mesh;\r\n\tuint32\t\t\t\t\t\t\tm_visible;\r\n\tbool\t\t\t\t\t\t\tm_active;\r\n\r\nprivate:\r\n\tNxXbox::CInstance\t\t\t\t*mp_instance;\r\n\tCXboxMesh\t\t\t\t\t\t*mp_mesh;\t\t// Used for obtaining CAS poly removal data.\r\n\tMth::Vector\t\t\t\t\t\tm_scale;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n#endif \r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxImposter.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxImposter.cpp\r\n\r\n#include \t\"sys/timer.h\"\r\n#include \t\"gfx/xbox/p_NxGeom.h\"\r\n#include \t\"gfx/xbox/p_NxImposter.h\"\r\n#include \t\"gfx/xbox/nx/nx_init.h\"\r\n#include \t\"gfx/xbox/nx/render.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n\t\r\nconst int XBOX_IMPOSTER_UPDATE_LIMIT\t\t= 30;\r\nconst int XBOX_IMPOSTER_MAX_U_TEXTURE_SIZE\t= 128;\r\nconst int XBOX_IMPOSTER_MAX_V_TEXTURE_SIZE\t= 128;\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void frustum_project_box( Mth::CBBox &bbox, XGMATRIX *p_view_matrix, Mth::Vector *p_max_x, Mth::Vector *p_max_y, Mth::Vector *p_mid )\r\n{\r\n\tfloat\tmax_projected_xx, max_projected_xz;\t\t// The camera space position of the point with the greatest x axis value when projected to z = mid_z.\r\n\tfloat\tmax_projected_x_mid_z;\t\t\t\t\t// The projected x axis value when this point is projected to z = mid_z;\r\n\r\n\tfloat\tmax_projected_yy, max_projected_yz;\t\t// The camera space position of the point furthest along the y axis when projected to z = mid_z.\r\n\tfloat\tmax_projected_y_mid_z;\t\t\t\t\t// The projected y axis value when this point is projected to z = mid_z;\r\n\r\n\tfloat\tmin_x = bbox.GetMin().GetX();\r\n\tfloat\tmin_y = bbox.GetMin().GetY();\r\n\tfloat\tmin_z = bbox.GetMin().GetZ();\r\n\tfloat\tmax_x = bbox.GetMax().GetX();\r\n\tfloat\tmax_y = bbox.GetMax().GetY();\r\n\tfloat\tmax_z = bbox.GetMax().GetZ();\r\n\r\n\t// Project the midpoint of the box, since this is the point through which the imposter polygon will pass.\r\n\tXGVECTOR3 mid_in( min_x + ( 0.5f * ( max_x - min_x )), min_y + ( 0.5f * ( max_y - min_y )), min_z + ( 0.5f * ( max_z - min_z )));\r\n\tXGVECTOR4 mid_out;\r\n\tXGVec3Transform( &mid_out, &mid_in, p_view_matrix );\r\n\r\n\tfor( uint32 v = 0; v < 8; ++v )\r\n\t{\r\n\t\tXGVECTOR3 in;\r\n\t\tXGVECTOR4 out;\r\n\r\n\t\tin.x = ( v & 0x04 ) ? max_x : min_x;\r\n\t\tin.y = ( v & 0x02 ) ? max_y : min_y;\r\n\t\tin.z = ( v & 0x01 ) ? max_z : min_z;\r\n\t\t\r\n\t\tXGVec3Transform( &out, &in, p_view_matrix );\r\n\r\n\t\tout.x = fabsf( out.x );\r\n\t\tout.y = fabsf( out.y );\r\n\r\n\t\tfloat projected_x_mid_z\t= out.x * ( mid_out.z / out.z );\r\n\t\tfloat projected_y_mid_z\t= out.y * ( mid_out.z / out.z );\r\n\r\n\t\tif( v == 0 )\r\n\t\t{\r\n\t\t\tmax_projected_x_mid_z\t= projected_x_mid_z;\r\n\t\t\tmax_projected_xx\t\t= out.x;\r\n\t\t\tmax_projected_xz\t\t= out.z;\r\n\r\n\t\t\tmax_projected_y_mid_z\t= projected_y_mid_z;\r\n\t\t\tmax_projected_yy\t\t= out.y;\r\n\t\t\tmax_projected_yz\t\t= out.z;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif( projected_x_mid_z > max_projected_x_mid_z )\r\n\t\t\t{\r\n\t\t\t\tmax_projected_xx\t\t= out.x;\r\n\t\t\t\tmax_projected_xz\t\t= out.z;\r\n\t\t\t\tmax_projected_x_mid_z\t= projected_x_mid_z;\r\n\t\t\t}\r\n\r\n\t\t\tif( projected_y_mid_z > max_projected_y_mid_z )\r\n\t\t\t{\r\n\t\t\t\tmax_projected_yy\t\t= out.y;\r\n\t\t\t\tmax_projected_yz\t\t= out.z;\r\n\t\t\t\tmax_projected_y_mid_z\t= projected_y_mid_z;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tp_max_x->Set( max_projected_xx, 0.0f, max_projected_xz, 0.0f );\r\n\tp_max_y->Set( 0.0f, max_projected_yy, max_projected_yz, 0.0f );\r\n\tp_mid->Set( mid_out.x, mid_out.y, mid_out.z );\r\n}\r\n\t\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCImposterGroup* CImposterManager::plat_create_imposter_group( void )\r\n{\r\n\treturn new CXboxImposterGroup;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterManager::plat_pre_render_imposters( void )\r\n{\r\n\t// Set up the common material attributes for the imposters.\r\n//\tNxXbox::set_blend_mode( NxXbox::vBLEND_MODE_BLEND );\r\n\tNxXbox::set_blend_mode( NxXbox::vBLEND_MODE_ONE_INV_SRC_ALPHA );\r\n\r\n\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2( 0 ));\r\n\tNxXbox::set_pixel_shader( PixelShader2 );\r\n\r\n\tNxXbox::set_render_state( RS_UVADDRESSMODE0,\t0x00010001UL );\r\n\tNxXbox::set_render_state( RS_ALPHACUTOFF,\t\t1 );\r\n\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t\t1 );\r\n\tNxXbox::set_render_state( RS_ZTESTENABLE,\t\t1 );\r\n\tNxXbox::set_render_state( RS_CULLMODE,\t\t\tD3DCULL_NONE );\r\n\r\n\tD3DDevice_SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );\r\n\tD3DDevice_SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | 0 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CImposterManager::plat_post_render_imposters( void )\r\n{\r\n\t// Clean up the common material attributes for the imposters.\r\n\tNxXbox::set_texture( 0, NULL );\r\n\tNxXbox::set_render_state( RS_CULLMODE, D3DCULL_CW );\r\n}\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CImposterGroup\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxImposterGroup::CXboxImposterGroup()\r\n{\r\n\tmp_texture\t\t\t\t\t= NULL;\r\n\tm_update_count\t\t\t\t= Mth::Rnd( XBOX_IMPOSTER_UPDATE_LIMIT );\r\n\tmp_removed_textures_list\t= new Lst::Head <sRemovedTextureDetails>;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxImposterGroup::~CXboxImposterGroup()\r\n{\r\n\tif( mp_texture )\r\n\t{\r\n\t\tmp_texture->Release();\r\n\t\tmp_texture = NULL;\r\n\t}\r\n\r\n\t// Remove all nodes from the removed textures table.\r\n\tLst::Node<sRemovedTextureDetails> *p_node, *p_next;\r\n\tfor( p_node = mp_removed_textures_list->GetNext(); p_node; p_node = p_next )\r\n\t{\r\n\t\tp_next = p_node->GetNext();\r\n\r\n\t\tsRemovedTextureDetails\t*p_details\t= p_node->GetData();\r\n\t\tIDirect3DTexture8\t\t*p_texture\t= p_details->mp_texture;\r\n\t\tp_texture->Release();\r\n\r\n\t\tdelete p_details;\r\n\t\tdelete p_node;\r\n\t}\r\n\r\n\t// Remove the table itself.\r\n\tdelete mp_removed_textures_list;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxImposterGroup::process_removed_textures( void )\r\n{\r\n\tLst::Node<sRemovedTextureDetails> *p_node, *p_next;\r\n\tfor( p_node = mp_removed_textures_list->GetNext(); p_node; p_node = p_next )\r\n\t{\r\n\t\tp_next = p_node->GetNext();\r\n\r\n\t\tsRemovedTextureDetails\t*p_details\t= p_node->GetData();\r\n\t\tint\t\t\t\t\t\ttime\t\t= p_details->m_time_removed;\r\n\t\tif((( NxXbox::EngineGlobals.render_start_time - time ) > 250 ) || ( time > NxXbox::EngineGlobals.render_start_time ))\r\n\t\t{\r\n\t\t\tIDirect3DTexture8*\tp_texture\t= p_details->mp_texture;\r\n\t\t\tp_texture->Release();\r\n\r\n\t\t\tdelete p_details;\r\n\t\t\tdelete p_node;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxImposterGroup::plat_process( void )\r\n{\r\n\tprocess_removed_textures();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxImposterGroup::plat_create_imposter_polygon( void )\r\n{\r\n\tDbg_Assert( !m_imposter_polygon_exists );\r\n\r\n\t// Generate a camera matrix that will point the camera directly at the midpoint of the bounding box.\r\n\tXGMATRIX\tcam_mat;\r\n\tXGVECTOR3\tlook_at( m_composite_bbox_mid[X], m_composite_bbox_mid[Y], m_composite_bbox_mid[Z] );\r\n\tXGMatrixLookAtRH( &cam_mat, &NxXbox::EngineGlobals.cam_position, &look_at, &NxXbox::EngineGlobals.cam_up );\r\n\r\n\t// Using this camera matrix, project all eight corners of the bounding box, in order to determine the best size for the texture.\r\n\tMth::Vector proj_max_x, proj_max_y, proj_mid;\r\n\tfrustum_project_box( m_composite_bbox, &cam_mat, &proj_max_x, &proj_max_y, &proj_mid );\r\n\r\n\t// Now project the minimum and maximum x and y values onto the projection plane - the plane through the midpoint of the box.\r\n\tfloat max_projected_x\t= proj_max_x[X] * ( proj_mid[Z] / proj_max_x[Z] );\r\n\tfloat max_projected_y\t= proj_max_y[Y] * ( proj_mid[Z] / proj_max_y[Z] );\r\n\r\n\t// Calculate the maximum width and height at the near plane.\r\n\tfloat wnp\t\t\t\t= 2.0f * proj_max_x[X] * ( NxXbox::EngineGlobals.near_plane / fabsf( proj_max_x[Z] ));\r\n\tfloat hnp\t\t\t\t= 2.0f * proj_max_y[Y] * ( NxXbox::EngineGlobals.near_plane / fabsf( proj_max_y[Z] ));\r\n\r\n\tm_tex_width\t\t\t\t= 16 + Ftoi_ASM(( 640.0f * wnp ) / NxXbox::EngineGlobals.near_plane_width );\r\n\tm_tex_height\t\t\t= 16 + Ftoi_ASM(( 480.0f * hnp ) / NxXbox::EngineGlobals.near_plane_height );\r\n\r\n\t// Round texture to the nearest 16 pixel limit.\r\n\tm_tex_width\t\t\t\t= (( m_tex_width + 0x0F ) & ~0x0F );\r\n\tm_tex_height\t\t\t= (( m_tex_height + 0x0F ) & ~0x0F );\r\n\r\n\t// Clamp texture to maximum allowed size.\r\n\tm_tex_width\t\t\t\t= ( m_tex_width > XBOX_IMPOSTER_MAX_U_TEXTURE_SIZE ) ? XBOX_IMPOSTER_MAX_U_TEXTURE_SIZE : m_tex_width;\r\n\tm_tex_height\t\t\t= ( m_tex_height > XBOX_IMPOSTER_MAX_V_TEXTURE_SIZE ) ? XBOX_IMPOSTER_MAX_V_TEXTURE_SIZE : m_tex_height;\r\n\r\n\t// Calculate the corresponding projection matrix.\r\n\tXGMATRIX proj_mat;\r\n\tXGMatrixPerspectiveRH( &proj_mat, wnp, hnp, NxXbox::EngineGlobals.near_plane, NxXbox::EngineGlobals.far_plane );\r\n\r\n\t// Set the calculated view and projection matrices.\r\n\tD3DDevice_SetTransform( D3DTS_VIEW, &cam_mat );\r\n\tD3DDevice_SetTransform( D3DTS_PROJECTION, &proj_mat );\r\n\r\n\t// Create a render target texture into which the object will be drawn.\r\n\tHRESULT hr;\r\n\tif( mp_texture == NULL )\r\n\t{\r\n\t\thr = D3DDevice_CreateTexture( m_tex_width, m_tex_height, 1, 0, D3DFMT_LIN_A8R8G8B8, 0, &mp_texture );\r\n\t\tDbg_Assert( hr == D3D_OK );\r\n\t}\r\n\r\n\t// Create a corresponding depth texture (we need this only for the render - then it can be removed).\r\n\tIDirect3DTexture8* p_depth_buffer;\r\n\thr = D3DDevice_CreateTexture( m_tex_width, m_tex_height, 1, 0, D3DFMT_LIN_D24S8, 0, &p_depth_buffer );\r\n\tDbg_Assert( hr == D3D_OK );\r\n\r\n\t// This call will increase the reference count of the IDirect3DTexture8 object.\r\n\tLPDIRECT3DSURFACE8 p_surface, p_depth_surface;\r\n\tmp_texture->GetSurfaceLevel( 0, &p_surface );\r\n\tp_depth_buffer->GetSurfaceLevel( 0, &p_depth_surface );\r\n\r\n\t// This call will increase the reference count of the IDirect3DSurface8 object.\r\n\tD3DDevice_SetRenderTarget( p_surface, p_depth_surface );\r\n\t\t\t\r\n\t// Clear the render target.\r\n\tD3DDevice_Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, 0x00000000, 1.0f, 0 );\r\n//\tD3DDevice_Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, 0x80800000, 1.0f, 0 );\r\n\r\n\t// The imposter polygon has now been created.\r\n\tm_imposter_polygon_exists = true;\r\n\r\n\t// Set the camera position at the time of creation.\r\n\tm_cam_pos.Set( NxXbox::EngineGlobals.cam_position.x, NxXbox::EngineGlobals.cam_position.y, NxXbox::EngineGlobals.cam_position.z );\r\n\r\n\t// Build a list of meshes, so we can sort them dynamically into draw order.\r\n\tNxXbox::sMesh*\tmesh_list[256];\r\n\tuint32\t\t\tnum_meshes = 0;\r\n\r\n\tLst::Node<Nx::CGeom> *node, *next;\r\n\tfor( node = mp_geom_list->GetNext(); node; node = next )\r\n\t{\r\n\t\tnext = node->GetNext();\r\n\t\tNx::CXboxGeom *p_xbox_geom = static_cast<Nx::CXboxGeom*>( node->GetData());\r\n\r\n\t\tfor( uint32 m = 0; m < p_xbox_geom->m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tDbg_Assert( num_meshes < 256 );\r\n\t\t\tNxXbox::sMesh* p_mesh\t= p_xbox_geom->m_mesh_array[m];\r\n\t\t\tmesh_list[num_meshes++]\t= p_mesh;\r\n\t\t}\r\n\t}\r\n\r\n\tif( num_meshes > 0 )\r\n\t{\r\n\t\t// Sort the array of pointers into draw order.\r\n\t\tqsort( mesh_list, num_meshes, sizeof( NxXbox::sMesh* ), NxXbox::sort_by_material_draw_order );\r\n\t}\r\n\r\n\t// Render each mesh into the render target.\r\n\tNxXbox::EngineGlobals.blend_mode_override = NxXbox::vBLEND_MODE_ONE_INV_SRC_ALPHA;\r\n\tNxXbox::sMaterial*\tp_material = NULL;\r\n\tfor( uint32 m = 0; m < num_meshes; ++m )\r\n\t{\r\n\t\tNxXbox::sMesh* p_mesh = mesh_list[m];\r\n\t\tif( p_mesh->mp_material != p_material )\r\n\t\t{\r\n\t\t\tp_material\t= p_mesh->mp_material;\r\n\t\t\tp_material->Submit();\r\n\t\t}\r\n\t\tp_mesh->Submit();\r\n\t}\r\n\tNxXbox::EngineGlobals.blend_mode_override = 0;\r\n\r\n\t// Can now set the meshes in the geom inactive.\r\n\tfor( node = mp_geom_list->GetNext(); node; node = next )\r\n\t{\r\n\t\tnext = node->GetNext();\r\n\t\tNx::CXboxGeom *p_xbox_geom = static_cast<Nx::CXboxGeom*>( node->GetData());\r\n\t\tp_xbox_geom->SetActive( false );\r\n\t}\r\n\r\n\t// Remove references to surfaces.\r\n\tp_surface->Release();\r\n\tp_depth_surface->Release();\r\n\tp_depth_buffer->Release();\r\n\r\n\t// Restore the default render target.\r\n\tD3DDevice_SetRenderTarget( NxXbox::EngineGlobals.p_RenderSurface, NxXbox::EngineGlobals.p_ZStencilSurface );\r\n\r\n\t// Restore the view and projection transforms.\r\n\tD3DDevice_SetTransform( D3DTS_VIEW, &NxXbox::EngineGlobals.view_matrix );\r\n\tD3DDevice_SetTransform( D3DTS_PROJECTION, &NxXbox::EngineGlobals.projection_matrix );\r\n\r\n\t// Now figure the vertex positions for the polygon.\r\n\tMth::Vector at = m_composite_bbox_mid - m_cam_pos;\r\n\tat.Normalize();\r\n\tMth::Vector right\t= Mth::CrossProduct( Mth::Vector( NxXbox::EngineGlobals.cam_up.x, NxXbox::EngineGlobals.cam_up.y, NxXbox::EngineGlobals.cam_up.z ), at );\r\n\tright.Normalize();\r\n\tMth::Vector up\t\t= Mth::CrossProduct( at, right );\r\n\r\n\tMth::Vector\tverts[4];\r\n\tverts[0]\t\t\t= m_composite_bbox_mid - ( max_projected_x * right ) + ( max_projected_y * up );\r\n\tverts[1]\t\t\t= m_composite_bbox_mid + ( max_projected_x * right ) + ( max_projected_y * up );\r\n\tverts[2]\t\t\t= m_composite_bbox_mid + ( max_projected_x * right ) - ( max_projected_y * up );\r\n\tverts[3]\t\t\t= m_composite_bbox_mid - ( max_projected_x * right ) - ( max_projected_y * up );\r\n\r\n\tfor( int v = 0; v < 4; ++v )\r\n\t{\r\n\t\tm_vertex_buffer[v].x\t= verts[v][X];\r\n\t\tm_vertex_buffer[v].y\t= verts[v][Y];\r\n\t\tm_vertex_buffer[v].z\t= verts[v][Z];\r\n\t}\r\n\r\n\t// The texture is a linear format, so the uv's are in texel space.\r\n\tm_vertex_buffer[0].u\t\t= (float)m_tex_width;\r\n\tm_vertex_buffer[0].v\t\t= 0.0f;\r\n\tm_vertex_buffer[1].u\t\t= 0.0f;\r\n\tm_vertex_buffer[1].v\t\t= 0.0f;\r\n\tm_vertex_buffer[2].u\t\t= 0.0f;\r\n\tm_vertex_buffer[2].v\t\t= (float)m_tex_height;\r\n\tm_vertex_buffer[3].u\t\t= (float)m_tex_width;\r\n\tm_vertex_buffer[3].v\t\t= (float)m_tex_height;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxImposterGroup::plat_remove_imposter_polygon( void )\r\n{\r\n\tif( m_imposter_polygon_exists )\r\n\t{\r\n\t\tm_imposter_polygon_exists = false;\r\n\r\n\t\tif( mp_texture )\r\n\t\t{\r\n\t\t\t// At this point move the texture resource into a list of removed textures. Here it will remain\r\n\t\t\t// for sufficient time to ensure that the GPU will no longer try to access it during push buffer processing.\r\n\t\t\tsRemovedTextureDetails\t*p_new_details\t\t\t= new sRemovedTextureDetails;\r\n\t\t\tp_new_details->mp_texture\t\t\t\t\t\t= mp_texture;\r\n\t\t\tp_new_details->m_time_removed\t\t\t\t\t= NxXbox::EngineGlobals.render_start_time;\r\n\r\n\t\t\tLst::Node<sRemovedTextureDetails> *p_new_node\t= new Lst::Node<sRemovedTextureDetails>( p_new_details );\r\n\t\t\tmp_removed_textures_list->AddToTail( p_new_node );\r\n\r\n\t\t\tmp_texture = NULL;\r\n\t\t}\r\n\r\n\t\tLst::Node<Nx::CGeom> *node, *next;\r\n\t\tfor( node = mp_geom_list->GetNext(); node; node = next )\r\n\t\t{\r\n\t\t\tnext = node->GetNext();\r\n\t\t\tNx::CXboxGeom *p_xbox_geom = static_cast<Nx::CXboxGeom*>( node->GetData());\r\n\r\n\t\t\t// Can now set the meshes in the geom active.\r\n\t\t\tp_xbox_geom->SetActive( true );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxImposterGroup::plat_update_imposter_polygon( void )\r\n{\r\n\t// Calculate the new vector from bounding box midpoint to camera.\r\n\tMth::Vector new_vec( NxXbox::EngineGlobals.cam_position.x - m_composite_bbox_mid[X], \r\n\t\t\t\t\t\t NxXbox::EngineGlobals.cam_position.y - m_composite_bbox_mid[Y],\r\n\t\t\t\t\t\t NxXbox::EngineGlobals.cam_position.z - m_composite_bbox_mid[Z] );\r\n\tnew_vec.Normalize();\r\n\r\n\t// Calculate the old vector from bounding box midpoint to camera when the imposter was created.\r\n\tMth::Vector old_vec = m_cam_pos - m_composite_bbox_mid;\r\n\told_vec.Normalize();\r\n\r\n\tfloat angle_change = acosf( Mth::DotProduct( new_vec, old_vec ));\r\n\r\n\t// Rebuild the imposter polygon if the angle change is beyond some limit.\r\n\tif( angle_change > Mth::DegToRad( 5.0f ))\r\n\t{\r\n\t\tRemoveImposterPolygon();\r\n\t\tCreateImposterPolygon();\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Check intermittently to see if the projected screen area of the imposter has changed sufficienty\r\n\t// to warrant regenerating a new texture.\r\n\tif( m_update_count >= XBOX_IMPOSTER_UPDATE_LIMIT )\r\n\t{\r\n\t\tm_update_count = 0;\r\n\r\n\t\t// Generate a camera matrix that will point the camera directly at the midpoint of the bounding box.\r\n\t\tXGMATRIX\tcam_mat;\r\n\t\tXGVECTOR3\tlook_at( m_composite_bbox_mid[X], m_composite_bbox_mid[Y], m_composite_bbox_mid[Z] );\r\n\t\tXGMatrixLookAtRH( &cam_mat, &NxXbox::EngineGlobals.cam_position, &look_at, &NxXbox::EngineGlobals.cam_up );\r\n\r\n\t\t// Using this camera matrix, project all eight corners of the bounding box, in order to determine the best size for the texture.\r\n\t\tMth::Vector proj_max_x, proj_max_y, proj_mid;\r\n\t\tfrustum_project_box( m_composite_bbox, &cam_mat, &proj_max_x, &proj_max_y, &proj_mid );\r\n\r\n\t\t// Calculate the maximum width and height at the near plane.\r\n\t\tfloat wnp\t\t= 2.0f * proj_max_x[X] * ( NxXbox::EngineGlobals.near_plane / fabsf( proj_max_x[Z] ));\r\n\t\tfloat hnp\t\t= 2.0f * proj_max_y[Y] * ( NxXbox::EngineGlobals.near_plane / fabsf( proj_max_y[Z] ));\r\n\r\n\t\t// Round texture to the nearest 16 pixel limit.\r\n\t\tint tex_width\t= 16 + Ftoi_ASM(( 640.0f * wnp ) / NxXbox::EngineGlobals.near_plane_width );\r\n\t\tint tex_height\t= 16 + Ftoi_ASM(( 480.0f * hnp ) / NxXbox::EngineGlobals.near_plane_height );\r\n\t\ttex_width\t\t= ( tex_width + 0x0F ) & ~0x0F;\r\n\t\ttex_height\t\t= ( tex_height + 0x0F ) & ~0x0F;\r\n\r\n\t\t// Clamp texture to maximum allowed size.\r\n\t\ttex_width\t\t= ( tex_width > XBOX_IMPOSTER_MAX_U_TEXTURE_SIZE ) ? XBOX_IMPOSTER_MAX_U_TEXTURE_SIZE : tex_width;\r\n\t\ttex_height\t\t= ( tex_height > XBOX_IMPOSTER_MAX_V_TEXTURE_SIZE ) ? XBOX_IMPOSTER_MAX_V_TEXTURE_SIZE : tex_height;\r\n\r\n\t\tif(( tex_width != m_tex_width ) || ( tex_height != m_tex_height ))\r\n\t\t{\r\n\t\t\tRemoveImposterPolygon();\r\n\t\t\tCreateImposterPolygon();\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxImposterGroup::plat_draw_imposter_polygon( void )\r\n{\r\n\t// Have to clear texture 0 before switching to the imposter texture, because it is a linear format.\r\n\tNxXbox::set_texture( 0, NULL );\r\n\tNxXbox::set_texture( 0, mp_texture );\r\n\r\n\tNxXbox::EngineGlobals.p_Device->DrawPrimitiveUP( D3DPT_QUADLIST, 1, m_vertex_buffer, sizeof( sImposterPolyVert ));\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nfloat CXboxImposterGroup::plat_check_distance( void )\r\n{\r\n\t// First check the visibility, using the bounding sphere.\r\n\tbool visible = NxXbox::frustum_check_sphere((D3DXVECTOR3*)&( m_composite_bbox_mid[X] ), m_composite_bsphere_radius );\r\n\r\n\tif( !visible )\r\n\t\treturn 0.0f;\r\n\r\n\tfloat\tmin_x = m_composite_bbox.GetMin().GetX();\r\n\tfloat\tmin_y = m_composite_bbox.GetMin().GetY();\r\n\tfloat\tmin_z = m_composite_bbox.GetMin().GetZ();\r\n\tfloat\tmax_x = m_composite_bbox.GetMax().GetX();\r\n\tfloat\tmax_y = m_composite_bbox.GetMax().GetY();\r\n\tfloat\tmax_z = m_composite_bbox.GetMax().GetZ();\r\n\r\n\t// The camera-space distance to the nearest point on the composite bounding box of the imposter.\r\n\tfloat\tnearest = NxXbox::EngineGlobals.far_plane;\r\n\r\n\tfor( uint32 v = 0; v < 8; ++v )\r\n\t{\r\n\t\tXGVECTOR3 test_in( ( v & 0x04 ) ? max_x : min_x, ( v & 0x02 ) ? max_y : min_y, ( v & 0x01 ) ? max_z : min_z );\r\n\t\tXGVECTOR4 test_mid;\r\n\t\t\r\n\t\tXGVec3Transform( &test_mid, &test_in, &NxXbox::EngineGlobals.view_matrix );\r\n\r\n\t\t// Do z-checking here.\r\n\t\tif( -test_mid.z < m_switch_distance )\r\n\t\t{\r\n\t\t\treturn -test_mid.z;\r\n\t\t}\r\n\t\telse if( -test_mid.z < nearest )\r\n\t\t{\r\n\t\t\tnearest = -test_mid.z;\r\n\t\t}\r\n\t}\r\n\treturn nearest;\r\n}\r\n\r\n\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxImposter.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxFont.h\r\n\r\n#ifndef\t__GFX_P_NX_IMPOSTER_H__\r\n#define\t__GFX_P_NX_IMPOSTER_H__\r\n\r\n#include \t\"gfx/NxImposter.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sImposterPolyVert\r\n{\r\n\tfloat\t\tx, y, z;\r\n\tfloat\t\tu, v;\r\n};\r\n\t\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\nstruct sRemovedTextureDetails\r\n{\r\n\tIDirect3DTexture8*\tmp_texture;\r\n\tint\t\t\t\t\tm_time_removed;\r\n};\r\n\r\n\r\n\r\n// Here's a machine specific implementation of the CImposterGroup\r\nclass CXboxImposterGroup : public CImposterGroup\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\t\t\t\t\t\tCXboxImposterGroup();\r\n\tvirtual\t\t\t\t\t\t\t\t\t\t~CXboxImposterGroup();\r\n\r\n\r\n\tprivate:\t\t\t\t\t\t\t\t\t// It's all private, as it is machine specific\r\n\r\n\tvirtual void\t\t\t\t\t\t\t\tplat_create_imposter_polygon( void );\r\n\tvirtual void\t\t\t\t\t\t\t\tplat_remove_imposter_polygon( void );\r\n\tvirtual bool\t\t\t\t\t\t\t\tplat_update_imposter_polygon( void );\r\n\tvirtual void\t\t\t\t\t\t\t\tplat_draw_imposter_polygon( void );\r\n\tvirtual float\t\t\t\t\t\t\t\tplat_check_distance( void );\r\n\tvirtual void\t\t\t\t\t\t\t\tplat_process( void );\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\t\tprocess_removed_textures( void );\r\n\r\n\t// Machine specific members\r\n\tsImposterPolyVert\t\t\t\t\t\t\tm_vertex_buffer[4];\r\n\tIDirect3DTexture8*\t\t\t\t\t\t\tmp_texture;\r\n\tLst::Head <sRemovedTextureDetails> *\t\tmp_removed_textures_list;\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxLight.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxLight.cpp - Xbox platform specific interface to CModelLights\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gfx/xbox/p_NxLight.h>\r\n#include <gfx/xbox/nx/nx_init.h>\r\n\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxModelLights::CXboxModelLights()\r\n{\r\n\tm_flags = 0;\r\n\r\n\tEnableAmbientLight( false );\r\n\tfor( int i = 0; i < CLightManager::MAX_LIGHTS; ++i )\r\n\t{\r\n\t\tEnableDiffuseLight( i, false );\r\n\t}\r\n\t\r\n\t// Set valid default direction.\r\n\tm_diffuse_direction[0].Set( 0.0f, 1.0f, 0.0f );\r\n\tm_diffuse_direction[1].Set( 0.0f, 1.0f, 0.0f );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxModelLights::~CXboxModelLights()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxModelLights::plat_update_brightness()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxModelLights::plat_update_engine( Mth::Vector & pos, bool add_scene_light )\r\n{\r\n\tif( m_flags & mUSE_MODEL_AMBIENT )\r\n\t{\r\n\t\t// Use the local ambient color, modulate it with the local ambient brightness.\r\n\t\tNxXbox::EngineGlobals.ambient_light_color[0] = m_ambient_color.r * ( 1.0f / 128.0f ) * m_ambient_brightness;\r\n\t\tNxXbox::EngineGlobals.ambient_light_color[1] = m_ambient_color.g * ( 1.0f / 128.0f ) * m_ambient_brightness;\r\n\t\tNxXbox::EngineGlobals.ambient_light_color[2] = m_ambient_color.b * ( 1.0f / 128.0f ) * m_ambient_brightness;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Use the default ambient color, but modulate it with the local ambient brightness.\r\n\t\tImage::RGBA\tamb = CLightManager::sGetLightAmbientColor();\r\n\t\tNxXbox::EngineGlobals.ambient_light_color[0] = amb.r * ( 1.0f / 128.0f ) * m_ambient_brightness;\r\n\t\tNxXbox::EngineGlobals.ambient_light_color[1] = amb.g * ( 1.0f / 128.0f ) * m_ambient_brightness;\r\n\t\tNxXbox::EngineGlobals.ambient_light_color[2] = amb.b * ( 1.0f / 128.0f ) * m_ambient_brightness;\r\n\t}\r\n\r\n\tfor( int i = 0; i < 2; ++i )\r\n\t{\r\n\t\tif( m_flags & (( i == 0 ) ? mUSE_MODEL_DIFFUSE_0 : mUSE_MODEL_DIFFUSE_1 ))\r\n\t\t{\r\n\t\t\t// Use the local directional color, modulate it with the local directional brightness.\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 4] = m_diffuse_color[i].r * ( 1.0f / 128.0f ) * m_diffuse_brightness[i];\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 5] = m_diffuse_color[i].g * ( 1.0f / 128.0f ) * m_diffuse_brightness[i];\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 6] = m_diffuse_color[i].b * ( 1.0f / 128.0f ) * m_diffuse_brightness[i];\r\n\r\n\t\t\t// Use the local direction.\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 0] = -m_diffuse_direction[i][X];\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 1] = -m_diffuse_direction[i][Y];\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 2] = -m_diffuse_direction[i][Z];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Use the default directional color, but modulate it with the local directional brightness.\r\n\t\t\tImage::RGBA\tdif = CLightManager::sGetLightDiffuseColor( i );\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 4] = dif.r * ( 1.0f / 128.0f ) * m_diffuse_brightness[i];\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 5] = dif.g * ( 1.0f / 128.0f ) * m_diffuse_brightness[i];\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 6] = dif.b * ( 1.0f / 128.0f ) * m_diffuse_brightness[i];\r\n\r\n\t\t\t// Use the default direction.\r\n\t\t\tMth::Vector dir = CLightManager::sGetLightDirection( i );\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 0] = -dir[X];\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 1] = -dir[Y];\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 2] = -dir[Z];\r\n\t\t}\r\n\t}\r\n\r\n\t// Figure Scene Lighting if required.\r\n\tif( add_scene_light )\r\n\t{\r\n\t\tNx::CSceneLight *p_scene_light = CLightManager::sGetOptimumSceneLight( pos );\r\n\t\tif( p_scene_light )\r\n\t\t{\r\n\t\t\tMth::Vector light_pos = p_scene_light->GetLightPosition();\r\n\r\n\t\t\tfloat dist\t= Mth::Distance( pos, light_pos );\r\n\t\t\tfloat ratio\t= dist * p_scene_light->GetLightReciprocalRadius();\r\n\r\n\t\t\tlight_pos = ( pos - light_pos ).Normalize();\r\n\r\n\t\t\t// Figure the direction...\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( 2 * 8 ) + 0] = light_pos[X];\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( 2 * 8 ) + 1] = light_pos[Y];\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( 2 * 8 ) + 2] = light_pos[Z];\r\n\r\n\t\t\t// ...and the color.\r\n\t\t\tratio\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t= sqrtf( 1.0f - ratio ) * ( 1.0f / 255.0f ) * p_scene_light->GetLightIntensity();\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( 2 * 8 ) + 4]\t= ratio * p_scene_light->GetLightColor().r;\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( 2 * 8 ) + 5]\t= ratio * p_scene_light->GetLightColor().g;\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( 2 * 8 ) + 6]\t= ratio * p_scene_light->GetLightColor().b;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Disbale this light by setting zero color.\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( 2 * 8 ) + 4] = 0.0f;\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( 2 * 8 ) + 5] = 0.0f;\r\n\t\t\tNxXbox::EngineGlobals.directional_light_color[( 2 * 8 ) + 6] = 0.0f;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxModelLights::plat_set_light_ambient_color( const Image::RGBA &rgba )\r\n{\r\n\tm_ambient_color = rgba;\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nImage::RGBA\tCXboxModelLights::plat_get_light_ambient_color() const\r\n{\r\n\treturn m_ambient_color;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxModelLights::plat_set_light_direction( int light_index, const Mth::Vector &direction )\r\n{\r\n\tm_diffuse_direction[light_index] = direction;\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::Vector &\tCXboxModelLights::plat_get_light_direction( int light_index ) const\r\n{\r\n\tif( plat_is_diffuse_light_enabled( light_index ))\r\n\t\treturn m_diffuse_direction[light_index];\r\n\telse\r\n\t\treturn Nx::CLightManager::sGetLightDirection( light_index );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxModelLights::plat_set_light_diffuse_color( int light_index, const Image::RGBA &rgba )\r\n{\r\n\tm_diffuse_color[light_index] = rgba;\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nImage::RGBA\tCXboxModelLights::plat_get_light_diffuse_color( int light_index ) const\r\n{\r\n\treturn m_diffuse_color[light_index];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxModelLights::plat_enable_ambient_light( bool enable )\r\n{\r\n\tif( enable )\r\n\t\tm_flags |= mUSE_MODEL_AMBIENT;\r\n\telse\r\n\t\tm_flags &= ~mUSE_MODEL_AMBIENT;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxModelLights::plat_enable_diffuse_light( int light_index, bool enable )\r\n{\r\n\tif( enable )\r\n\t\tm_flags |= ( light_index == 0 ) ? mUSE_MODEL_DIFFUSE_0 : mUSE_MODEL_DIFFUSE_1;\r\n\telse\r\n\t\tm_flags &= ~(( light_index == 0 ) ? mUSE_MODEL_DIFFUSE_0 : mUSE_MODEL_DIFFUSE_1 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxModelLights::plat_is_ambient_light_enabled() const\r\n{\r\n\treturn ( m_flags & mUSE_MODEL_AMBIENT ) > 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxModelLights::plat_is_diffuse_light_enabled( int light_index ) const\r\n{\r\n\treturn (( light_index == 0 ) ? (( m_flags & mUSE_MODEL_DIFFUSE_0 ) > 0 ) : (( m_flags & mUSE_MODEL_DIFFUSE_1 ) > 0 ));\r\n}\r\n\r\n} \r\n \r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxLight.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// p_NxLight.H - Neversoft Engine, Rendering portion, Platform dependent interface\r\n\r\n#ifndef\t__GFX_P_NX_LIGHT_H__\r\n#define\t__GFX_P_NX_LIGHT_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/math.h>\r\n#include <gfx/image/imagebasic.h>\r\n#include <gfx/nxlight.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// Nx::CXboxModelLights\r\nclass\tCXboxModelLights : public CModelLights\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCXboxModelLights();\r\n\tvirtual\t\t\t\t\t\t~CXboxModelLights();\r\n\r\nprivate:\t\r\n\r\n\t// Platform-specific calls\r\n\tvirtual void\t\t\t\tplat_update_engine( Mth::Vector & pos, bool add_scene_light );\r\n\tvirtual bool\t\t\t\tplat_set_light_ambient_color(const Image::RGBA &rgba);\r\n\tvirtual bool\t\t\t\tplat_set_light_direction(int light_index, const Mth::Vector &direction);\r\n\tvirtual bool\t\t\t\tplat_set_light_diffuse_color(int light_index, const Image::RGBA &rgba);\r\n\tvirtual Image::RGBA\t\t\tplat_get_light_ambient_color() const;\r\n\tvirtual const Mth::Vector &\tplat_get_light_direction(int light_index) const;\r\n\tvirtual Image::RGBA\t\t\tplat_get_light_diffuse_color(int light_index) const;\r\n\r\n\tvirtual void\t\t\t\tplat_update_brightness();\r\n\r\n\tvirtual void\t\t\t\tplat_enable_ambient_light(bool enable);\r\n\tvirtual void\t\t\t\tplat_enable_diffuse_light(int light_index, bool enable);\r\n\tvirtual bool\t\t\t\tplat_is_ambient_light_enabled() const;\r\n\tvirtual bool\t\t\t\tplat_is_diffuse_light_enabled(int light_index) const;\r\n\r\n\tuint32\t\t\t\t\t\tm_flags;\r\n\tImage::RGBA\t\t\t\t\tm_ambient_color;\r\n\tImage::RGBA\t\t\t\t\tm_diffuse_color[CLightManager::MAX_LIGHTS];\r\n\tMth::Vector\t\t\t\t\tm_diffuse_direction[CLightManager::MAX_LIGHTS];\r\n};\r\n\r\n\r\n}\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxLightMan.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxLightMan.cpp - Xbox platform specific interface to CLightManager\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/NxLightMan.h\"\r\n#include \"gfx/xbox/p_NxLight.h\"\r\n#include \"gfx/xbox/nx/nx_init.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLightManager::s_plat_update_engine( void )\r\n{\r\n\tNxXbox::EngineGlobals.ambient_light_color[0] = s_world_lights.m_light_ambient_rgba.r * ( 1.0f / 128.0f ) * s_ambient_brightness;\r\n\tNxXbox::EngineGlobals.ambient_light_color[1] = s_world_lights.m_light_ambient_rgba.g * ( 1.0f / 128.0f ) * s_ambient_brightness;\r\n\tNxXbox::EngineGlobals.ambient_light_color[2] = s_world_lights.m_light_ambient_rgba.b * ( 1.0f / 128.0f ) * s_ambient_brightness;\r\n\r\n\tfor( int i = 0; i < 2; ++i )\r\n\t{\r\n\t\tImage::RGBA\tdif = CLightManager::sGetLightDiffuseColor( i );\r\n\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 4] = dif.r * ( 1.0f / 128.0f ) * s_diffuse_brightness[i];\r\n\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 5] = dif.g * ( 1.0f / 128.0f ) * s_diffuse_brightness[i];\r\n\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 6] = dif.b * ( 1.0f / 128.0f ) * s_diffuse_brightness[i];\r\n\r\n\t\tMth::Vector dir = CLightManager::sGetLightDirection( i );\r\n\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 0] = -dir[X];\r\n\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 1] = -dir[Y];\r\n\t\tNxXbox::EngineGlobals.directional_light_color[( i * 8 ) + 2] = -dir[Z];\r\n\t}\r\n\r\n\t// Set third color to black.\r\n\tNxXbox::EngineGlobals.directional_light_color[( 2 * 8 ) + 4] = 0.0f;\r\n\tNxXbox::EngineGlobals.directional_light_color[( 2 * 8 ) + 5] = 0.0f;\r\n\tNxXbox::EngineGlobals.directional_light_color[( 2 * 8 ) + 6] = 0.0f;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLightManager::s_plat_update_lights( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CLightManager::s_plat_set_light_ambient_color( void )\r\n{\r\n\tNxXbox::EngineGlobals.ambient_light_color[0] = s_world_lights.m_light_ambient_rgba.r * ( 1.0f / 128.0f ) * s_ambient_brightness;\r\n\tNxXbox::EngineGlobals.ambient_light_color[1] = s_world_lights.m_light_ambient_rgba.g * ( 1.0f / 128.0f ) * s_ambient_brightness;\r\n\tNxXbox::EngineGlobals.ambient_light_color[2] = s_world_lights.m_light_ambient_rgba.b * ( 1.0f / 128.0f ) * s_ambient_brightness;\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nImage::RGBA\tCLightManager::s_plat_get_light_ambient_color()\r\n{\r\n\treturn s_world_lights.m_light_ambient_rgba;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CLightManager::s_plat_set_light_direction( int light_index )\r\n{\r\n\tint array_index = ( light_index * 8 );\r\n\t\r\n\tNxXbox::EngineGlobals.directional_light_color[array_index]\t\t= -s_world_lights.m_light_direction[light_index][X];\r\n\tNxXbox::EngineGlobals.directional_light_color[array_index + 1]\t= -s_world_lights.m_light_direction[light_index][Y];\r\n\tNxXbox::EngineGlobals.directional_light_color[array_index + 2]\t= -s_world_lights.m_light_direction[light_index][Z];\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::Vector & CLightManager::s_plat_get_light_direction( int light_index )\r\n{\r\n\tstatic Mth::Vector dir;\r\n\tdir.Set( s_world_lights.m_light_direction[light_index][X], s_world_lights.m_light_direction[light_index][Y], s_world_lights.m_light_direction[light_index][Z] );\r\n\treturn dir;\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CLightManager::s_plat_set_light_diffuse_color( int light_index )\r\n{\r\n\tint array_index = ( light_index * 8 ) + 4;\r\n\t\r\n\tNxXbox::EngineGlobals.directional_light_color[array_index]\t\t= s_world_lights.m_light_diffuse_rgba[light_index].r * ( 1.0f / 128.0f ) * s_diffuse_brightness[light_index];\r\n\tNxXbox::EngineGlobals.directional_light_color[array_index + 1]\t= s_world_lights.m_light_diffuse_rgba[light_index].g * ( 1.0f / 128.0f ) * s_diffuse_brightness[light_index];\r\n\tNxXbox::EngineGlobals.directional_light_color[array_index + 2]\t= s_world_lights.m_light_diffuse_rgba[light_index].b * ( 1.0f / 128.0f ) * s_diffuse_brightness[light_index];\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nImage::RGBA\tCLightManager::s_plat_get_light_diffuse_color( int light_index )\r\n{\r\n\treturn s_world_lights.m_light_diffuse_rgba[light_index];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLightManager::s_plat_update_colors( void )\r\n{\r\n\ts_plat_set_light_ambient_color();\r\n\tfor( int i = 0; i < MAX_LIGHTS; ++i )\r\n\t{\r\n\t\ts_plat_set_light_diffuse_color( i );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCModelLights *CLightManager::s_plat_create_model_lights()\r\n{\r\n\treturn new CXboxModelLights;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CLightManager::s_plat_free_model_lights( CModelLights *p_model_lights )\r\n{\r\n\tDbg_Assert( p_model_lights );\r\n\r\n\tdelete p_model_lights;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n} \r\n \r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxLoadScreen.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxLoadScreen.cpp - Xbox platform specific interface for the load screen\r\n//\r\n//\r\n\r\n#include\t\"gfx\\Nx.h\"\r\n#include\t\"gfx\\NxLoadScreen.h\"\r\n#include\t\"gfx\\xbox\\p_NxTexture.h\"\r\n#include\t\"gfx\\xbox\\p_NxSprite.h\"\r\n#include\t\"gfx\\xbox\\NX\\sprite.h\"\r\n#include\t\"gfx\\xbox\\NX\\scene.h\"\r\n#include\t\"gfx\\xbox\\NX\\render.h\"\r\n#include\t\"sys\\config\\config.h\"\r\n\r\n#include\t\"core\\macros.h\"\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\nNx::CXboxTexture\t*sp_load_screen_texture;\r\nNx::CXboxSprite\t*sp_load_screen_sprite;\r\n\r\nstatic float\t\tloadingBarTotalSeconds;\r\nstatic float\t\tloadingBarCurrentSeconds;\r\nstatic float\t\tloadingBarDeltaSeconds;\r\nstatic int\t\t\tloadingBarStartColor[3];\t\t// r,g,b\r\nstatic int\t\t\tloadingBarEndColor[3];\t\t\t// r,g,b\r\nstatic uint32\t\tloadingBarColors[1280][3];\t\t// r,g,b\r\nstatic bool\t\t\tloadingBarColorsSet = false;\r\nstatic int\t\t\tloadingBarWidth;\r\nstatic uint32\t\tloadingBarBorderColor;\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n#define USE_SPRITES 0\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CALLBACK loadingBarTimerCallback( UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2 )\r\n{\r\n\tif( NxXbox::EngineGlobals.loadingbar_timer_event != 0 )\r\n\t{\r\n\t\tloadingBarCurrentSeconds += loadingBarDeltaSeconds;\r\n\t\tfloat mult\t\t\t= loadingBarCurrentSeconds / loadingBarTotalSeconds;\r\n\t\tmult\t\t\t\t= ( mult > 1.0f ) ? 1.0f : mult;\r\n\t\tint bar_width\t\t= (int)( loadingBarWidth * mult );\r\n\t\t\r\n\t\t// Get pointer to front buffer memory.\r\n\t\tIDirect3DSurface8\t*p_buffer;\r\n\t\tD3DLOCKED_RECT\t\tlocked_rect;\r\n\t\tNxXbox::EngineGlobals.p_Device->GetBackBuffer( -1, D3DBACKBUFFER_TYPE_MONO, &p_buffer );\r\n\t\tp_buffer->LockRect( &locked_rect, NULL, D3DLOCK_TILED );\r\n\t\tuint32 *p_screen = (uint32*)locked_rect.pBits;\r\n\r\n\t\t// ----------------------------------\r\n\t\t// | ||||||||||||||||||||||          |\r\n\t\t// ----------------------------------\r\n\t\t// ^ ^                    ^          ^\r\n\t\t// a b                    c\t\t\t d\r\n\t\t// \r\n\t\t// a = surround start\r\n\t\t// b = bar start\r\n\t\t// c = bar end\r\n\t\t// d = surround end\r\n\t\tint bar_start\t\t\t= ( 640 - loadingBarWidth ) / 2;\r\n\t\tint surround_start\t\t= bar_start - 5;\r\n\t\tint bar_end\t\t\t\t= bar_start + bar_width;\r\n\t\tint surround_end\t\t= surround_start + loadingBarWidth + 10;\r\n\r\n\t\tconst int HDTV_OFFSET\t= 48;\t\r\n\t\t\r\n\t\tbar_start\t\t\t\t= (int)SCREEN_CONV_X( bar_start );\r\n\t\tsurround_start\t\t\t= (int)SCREEN_CONV_X( surround_start );\r\n\t\tbar_end\t\t\t\t\t= (int)SCREEN_CONV_X( bar_end );\r\n\t\tsurround_end\t\t\t= (int)SCREEN_CONV_X( surround_end );\r\n\t\t\r\n\t\tif( NxXbox::EngineGlobals.backbuffer_width > 640 )\r\n\t\t{\r\n\t\t\tbar_start\t\t\t+= HDTV_OFFSET;\r\n\t\t\tsurround_start\t\t+= HDTV_OFFSET;\r\n\t\t\tbar_end\t\t\t\t+= HDTV_OFFSET;\r\n\t\t\tsurround_end\t\t+= HDTV_OFFSET;\r\n\t\t}\r\n\t\t\r\n\t\tint base_y\t\t\t\t= (int)SCREEN_CONV_Y( 410 );\r\n\t\t\r\n\t\tfor( int i = 0; i < 20; ++i )\r\n\t\t{\r\n\t\t\tuint32 *p_loop = p_screen + (( base_y + i ) * NxXbox::EngineGlobals.backbuffer_width );\r\n\r\n\t\t\tif(( i < 5 ) || ( i >= 15 ))\r\n\t\t\t{\r\n\t\t\t\tfor( int j = surround_start; j < surround_end; ++j )\r\n\t\t\t\t\tp_loop[j] = loadingBarBorderColor;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfor( int j = surround_start; j < ( surround_start + 5 ); ++j )\r\n\t\t\t\t\tp_loop[j] = loadingBarBorderColor;\r\n\r\n\t\t\t\tfor( int j = bar_end; j < surround_end; ++j )\r\n\t\t\t\t\tp_loop[j] = loadingBarBorderColor;\r\n\r\n\t\t\t\tfor( int j = bar_start; j < bar_end; ++j )\t\t\t\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 idx\t\t\t= ( j - bar_start >= 1279 ) ? 1279 : ( j - bar_start );\r\n\t\t\t\t\tuint32 write_value\t= 0x80000000UL | ( loadingBarColors[idx][0] << 16 ) | ( loadingBarColors[idx][1] << 8 ) | ( loadingBarColors[idx][2] << 0 );\r\n\t\t\t\t\tp_loop[j]\t\t\t= write_value;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic bool is_power_of_two( uint32 a )\r\n{\r\n\tif( a == 0 )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\treturn (( a & ( a - 1 )) == 0 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLoadScreen::s_plat_display(const char* filename, bool just_freeze, bool blank)\r\n{\r\n\t// Wait for asyncronous rendering to finish.\r\n\tNxXbox::EngineGlobals.p_Device->BlockUntilIdle();\r\n\r\n\tif( !just_freeze )\r\n\t{\r\n\t\tif( blank )\r\n\t\t{\r\n\t\t\tD3DDevice_Clear( 0, NULL, D3DCLEAR_TARGET, 0x00000000UL, 1.0f, 0 );\r\n\t\t\tD3DDevice_Swap( D3DSWAP_DEFAULT );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Engine stuff\r\n\t\t\tDbg_Assert(!sp_load_screen_texture);\r\n\t\t\tDbg_Assert(!sp_load_screen_sprite);\r\n\r\n\t\t\tsp_load_screen_texture = new CXboxTexture();\r\n\r\n#\t\t\tifdef __PAL_BUILD__\r\n\t\t\tswitch( Config::GetLanguage())\r\n\t\t\t{\r\n\t\t\t\tcase Config::LANGUAGE_FRENCH:\r\n\t\t\t\t{\r\n\t\t\t\t\tchar t_filename[200];\r\n\t\t\t\t\tsprintf( t_filename, \"PALImages/FRImages/%s\", filename );\r\n\t\t\t\t\tif( !sp_load_screen_texture->LoadTexture( t_filename, true ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_Error( \"Can't load texture %s\", t_filename );\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase Config::LANGUAGE_GERMAN:\r\n\t\t\t\t{\r\n\t\t\t\t\tchar t_filename[200];\r\n\t\t\t\t\tsprintf( t_filename, \"PALImages/GRImages/%s\", filename );\r\n\t\t\t\t\tif( !sp_load_screen_texture->LoadTexture( t_filename, true ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_Error( \"Can't load texture %s\", t_filename );\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t{\r\n\t\t\t\t\tif( !sp_load_screen_texture->LoadTexture( filename, true ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_Error( \"Can't load texture %s\", filename );\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n#\t\t\telse\r\n\t\t\tif( !sp_load_screen_texture->LoadTexture( filename, true ))\r\n\t\t\t{\r\n\t\t\t\tDbg_Error( \"Can't load texture %s\", filename );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n#\t\t\tendif // __PAL_BUILD__\r\n\r\n\t\t\t// Copy into frame buffer.\r\n\t\t\tfloat x_offset\t\t= 0.0f;\r\n\t\t\tfloat y_offset\t\t= 0.0f;\r\n\t\t\tfloat x_scale\t\t= 1.0f;\r\n\t\t\tfloat y_scale\t\t= 1.0f;\r\n\t\t\tfloat alpha_level\t= 1.0f;\r\n\t\r\n\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );\r\n\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );\r\n\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );\r\n\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );\r\n\r\n\t\t\t// Store the stage zero minfilter, since it may be anisotropic.\r\n\t\t\tDWORD\tstage_zero_minfilter;\r\n\t\t\tD3DDevice_GetTextureStageState( 0, D3DTSS_MINFILTER, &stage_zero_minfilter );\r\n\r\n\t\t\t// Turn on texture filtering when scaling...\r\n\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );\r\n\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );\r\n\r\n\t\t\t// Turn on clamping so that the linear textures work\r\n\t\t\tNxXbox::set_render_state( RS_UVADDRESSMODE0, 0x00010001UL );\r\n\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_LIGHTING,\t\t\t\tFALSE );\r\n\t\r\n\t\t\t// Use a default vertex shader\r\n\t\t\tNxXbox::set_pixel_shader( 0 );\r\n\t\t\tNxXbox::set_vertex_shader( D3DFVF_XYZRHW | D3DFVF_TEX1 );\r\n\t\t\tNxXbox::set_blend_mode( NxXbox::vBLEND_MODE_DIFFUSE );\r\n\r\n\t\t\t// Select the texture (flush first, since the screen texture is linear).\r\n\t\t\tNxXbox::set_texture( 0, NULL );\r\n\t\t\tNxXbox::set_texture( 0, sp_load_screen_texture->GetEngineTexture()->pD3DTexture, sp_load_screen_texture->GetEngineTexture()->pD3DPalette );\r\n\r\n\t\t\t// Setup up the vertices.\r\n\t\t\ttypedef struct\r\n\t\t\t{\r\n\t\t\t\tfloat\tsx,sy,sz;\r\n\t\t\t\tfloat\trhw;\r\n\t\t\t\tfloat\ttu,tv;\r\n\t\t\t}\r\n\t\t\tLOADSCREEN_VERT;\r\n\t\r\n\t\t\t// Get the width height from the texture itself, since we may be using a texture not designed especially\r\n\t\t\t// for this screen dimension.\r\n\t\t\tfloat tex_w = (float)sp_load_screen_texture->GetEngineTexture()->ActualWidth;\r\n\t\t\tfloat tex_h = (float)sp_load_screen_texture->GetEngineTexture()->ActualHeight;\r\n\t\t\tfloat scr_w = (float)NxXbox::EngineGlobals.backbuffer_width;\r\n\t\t\tfloat scr_h = (float)NxXbox::EngineGlobals.backbuffer_height;\r\n\r\n\t\t\tLOADSCREEN_VERT\tvertices[4];\r\n\r\n\t\t\t// The texture coordinate addressing will differ depending on whether this is a linear texture or not.\r\n\t\t\tif( is_power_of_two( sp_load_screen_texture->GetEngineTexture()->ActualWidth ) &&\r\n\t\t\t\tis_power_of_two( sp_load_screen_texture->GetEngineTexture()->ActualHeight ))\r\n\t\t\t{\r\n\t\t\t\t// Not a linear texture, will be swizzled, max uv is (1.0, 1.0).\r\n\t\t\t\tvertices[0].sx\t\t= x_offset;\r\n\t\t\t\tvertices[0].sy\t\t= y_offset;\r\n\t\t\t\tvertices[0].sz\t\t= 0.0f;\r\n\t\t\t\tvertices[0].rhw\t\t= 0.0f;\r\n\t\t\t\tvertices[0].tu\t\t= 0.0f;\r\n\t\t\t\tvertices[0].tv\t\t= 1.0f;\r\n\t\t\t\tvertices[1]\t\t\t= vertices[0];\r\n\t\t\t\tvertices[1].sy\t\t= y_offset + ( scr_h * y_scale );\r\n\t\t\t\tvertices[1].tv\t\t= 0.0f;\r\n\t\t\t\tvertices[2]\t\t\t= vertices[0];\r\n\t\t\t\tvertices[2].sx\t\t= x_offset + ( scr_w * x_scale );\r\n\t\t\t\tvertices[2].tu\t\t= 1.0f;\r\n\t\t\t\tvertices[3]\t\t\t= vertices[2];\r\n\t\t\t\tvertices[3].sy\t\t= vertices[1].sy;\r\n\t\t\t\tvertices[3].tv\t\t= 0.0f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Linear texture, won't be swizzled, max uv is (tex_w, tex_h).\r\n\t\t\t\tvertices[0].sx\t\t= x_offset;\r\n\t\t\t\tvertices[0].sy\t\t= y_offset;\r\n\t\t\t\tvertices[0].sz\t\t= 0.0f;\r\n\t\t\t\tvertices[0].rhw\t\t= 0.0f;\r\n\t\t\t\tvertices[0].tu\t\t= -0.5f;\r\n\t\t\t\tvertices[0].tv\t\t= tex_h - 0.5f;\r\n\t\t\t\tvertices[1]\t\t\t= vertices[0];\r\n\t\t\t\tvertices[1].sy\t\t= y_offset + ( scr_h * y_scale );\r\n\t\t\t\tvertices[1].tv\t\t= -0.5f;\r\n\t\t\t\tvertices[2]\t\t\t= vertices[0];\r\n\t\t\t\tvertices[2].sx\t\t= x_offset + ( scr_w * x_scale );\r\n\t\t\t\tvertices[2].tu\t\t= tex_w - 0.5f;\r\n\t\t\t\tvertices[3]\t\t\t= vertices[2];\r\n\t\t\t\tvertices[3].sy\t\t= vertices[1].sy;\r\n\t\t\t\tvertices[3].tv\t\t= -0.5f;\r\n\t\t\t}\r\n\r\n\t\t\t// Draw the vertices, and make sure they're displayed.\r\n\t\t\tD3DDevice_DrawVerticesUP( D3DPT_TRIANGLESTRIP, 4, vertices, sizeof( LOADSCREEN_VERT ));\r\n\t\t\tD3DDevice_Swap( D3DSWAP_DEFAULT );\r\n\r\n\t\t\t// Done with texture\r\n\t\t\tdelete sp_load_screen_texture;\r\n\t\t\tsp_load_screen_texture = NULL;\r\n\r\n\t\t\t// Reflush linear texture out.\r\n\t\t\tNxXbox::set_texture( 0, NULL );\r\n\r\n\t\t\t// Restore the stage zero minfilter.\r\n\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER, stage_zero_minfilter );\r\n\t\t}\r\n\t}\r\n\r\n\t// Indicate that the loading screen is visible, to stop any more rendering until it is hidden.\r\n\tNxXbox::EngineGlobals.loadingscreen_visible = true;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::s_plat_hide()\r\n{\r\n\t// Remove the loading bar.\r\n\tif( NxXbox::EngineGlobals.loadingbar_timer_event != 0 )\r\n\t{\r\n\t\ttimeKillEvent( NxXbox::EngineGlobals.loadingbar_timer_event );\r\n\t\tNxXbox::EngineGlobals.loadingbar_timer_event = 0;\r\n\t}\r\n\r\n\t// Indicate that the loading screen is no longer visible.\r\n\tNxXbox::EngineGlobals.loadingscreen_visible = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLoadScreen::s_plat_clear()\r\n{\r\n\tif( sp_load_screen_sprite )\r\n\t{\r\n\t\tCEngine::sDestroySprite(sp_load_screen_sprite);\r\n\t\tsp_load_screen_sprite = NULL;\r\n\t}\r\n\r\n\tif( sp_load_screen_texture )\r\n\t{\r\n\t\tdelete sp_load_screen_texture;\r\n\t\tsp_load_screen_texture = NULL;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLoadScreen::s_plat_start_loading_bar( float seconds )\r\n{\r\n\tloadingBarTotalSeconds\t\t= seconds * 0.6f;\r\n\tloadingBarCurrentSeconds\t= 0.0f;\r\n\tloadingBarDeltaSeconds\t\t= 0.03f;\t// 30 milliseconds.\r\n\t\r\n\ts_plat_update_bar_properties();\r\n\r\n\t// Set up the timer event.\r\n\tif( NxXbox::EngineGlobals.loadingbar_timer_event == 0 )\r\n\t{\r\n\t\tNxXbox::EngineGlobals.loadingbar_timer_event = timeSetEvent( (uint32)( loadingBarDeltaSeconds * 1000.0f ),\t// Delay (ms).\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t 0,\t\t\t\t\t\t\t\t\t\t\t\t// Ignored resolution (ms).\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t loadingBarTimerCallback,\t\t\t\t\t\t// Callback function.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t 0,\t\t\t\t\t\t\t\t\t\t\t\t// Callback data.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t TIME_PERIODIC | TIME_CALLBACK_FUNCTION );\r\n\t\tDbg_Assert( NxXbox::EngineGlobals.loadingbar_timer_event != 0 );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CLoadScreen::s_plat_update_bar_properties( void )\r\n{\r\n\r\n\tloadingBarStartColor[0] = s_bar_start_color.r;\r\n\tloadingBarStartColor[1] = s_bar_start_color.g;\r\n\tloadingBarStartColor[2] = s_bar_start_color.b;\r\n\r\n\tloadingBarEndColor[0]\t= s_bar_end_color.r;\r\n\tloadingBarEndColor[1]\t= s_bar_end_color.g;\r\n\tloadingBarEndColor[2]\t= s_bar_end_color.b;\r\n\r\n\tloadingBarWidth\t\t\t= s_bar_width;\r\n\tloadingBarBorderColor\t= 0x80000000 | ((uint32)s_bar_border_color.r << 16 ) | ((uint32)s_bar_border_color.g << 8 )  | (uint32)s_bar_border_color.b;\r\n\r\n\t// Build the interpolated color array.\r\n\tint last_color = (int)( loadingBarWidth * NxXbox::EngineGlobals.screen_conv_x_multiplier );\r\n\tfor( int i = 0; i < last_color; ++i )\r\n\t{\r\n\t\tfor( int c = 0; c < 3; ++c )\r\n\t\t{\r\n\t\t\tloadingBarColors[i][c] = loadingBarStartColor[c] + ((( loadingBarEndColor[c] - loadingBarStartColor[c] ) * i ) / last_color );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n} \r\n \r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxMesh.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxMesh.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/15/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include <core/string/stringutils.h>\r\n#include <sys/file/filesys.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxtexman.h>\r\n#include <gfx/xbox/p_nxmesh.h>\r\n#include <gfx/xbox/p_nxscene.h>\r\n#include <gfx/xbox/nx/scene.h>\r\n#include <gfx/xbox/nx/texture.h>\r\n\r\n//extern Nx::CXboxScene *p_skater;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int cmp( const void *p1, const void *p2 )\r\n{\r\n\tNxXbox::sCASData *p_casdata1 = (NxXbox::sCASData*)p1;\r\n\tNxXbox::sCASData *p_casdata2 = (NxXbox::sCASData*)p2;\r\n\t\r\n\tuint32 mesh1 = p_casdata1->data0 >> 16;\r\n\tuint32 mesh2 = p_casdata2->data0 >> 16;\r\n\t\r\n\tif( mesh1 > mesh2 )\r\n\t{\r\n\t\treturn 1;\r\n\t}\r\n\telse if( mesh1 < mesh2 )\r\n\t{\r\n\t\treturn -1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tuint32 indexzero1 = p_casdata1->data0 & 0xFFFF;\r\n\t\tuint32 indexzero2 = p_casdata2->data0 & 0xFFFF;\r\n\t\tif( indexzero1 > indexzero2 )\r\n\t\t{\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t\telse if( indexzero1 < indexzero2 )\r\n\t\t{\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxMesh::build_casdata_table( const char* pFileName )\r\n{\r\n\tvoid *pFile = File::Open( pFileName, \"rb\" );\r\n\tDbg_MsgAssert( pFile, ( \"Couldn't open CAS data file %s\\n\", pFileName ));\r\n\r\n\tuint32 version;\r\n\tFile::Read( &version, sizeof( uint32 ), 1, pFile );\r\n\r\n\tif( version >= 2 )\r\n\t{\r\n\t\tFile::Read( &m_CASRemovalMask, sizeof( uint32 ), 1, pFile );\r\n\t}\r\n\t\r\n\tFile::Read( &m_numCASData, sizeof( int ), 1, pFile );\r\n\r\n\tif( m_numCASData > 0 )\r\n\t{\r\n\t\t// CAS flags.\r\n\t\tmp_CASData = new NxXbox::sCASData[m_numCASData];\r\n\r\n\t\tfor( uint32 i = 0; i < m_numCASData; ++i )\r\n\t\t{\r\n\t\t\tFile::Read( &mp_CASData[i].mask, sizeof( uint32 ) * 3, 1, pFile );\r\n\t\t}\r\n\r\n\t\t// Sort the CAS data based first on mesh, then on the first tri index, lowest to highest. This allows some efficient early-out checking\r\n\t\t// during the poly removal.\r\n\t\tqsort( mp_CASData, m_numCASData, sizeof( NxXbox::sCASData ), cmp );\r\n\t}\r\n\r\n\tFile::Close( pFile );\r\n\t\r\n\treturn ( m_numCASData > 0 );\r\n}\r\n\r\n\r\n\r\n#define MemoryRead( dst, size, num, src )\tCopyMemory(( dst ), ( src ), (( num ) * ( size )));\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t( src ) += (( num ) * ( size ))\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxMesh::build_casdata_table_from_memory( void **pp_mem )\r\n{\r\n\tuint8 *p_data = (uint8*)( *pp_mem );\r\n\r\n\tuint32 version;\r\n\tMemoryRead( &version, sizeof( uint32 ), 1, p_data );\r\n\r\n\tif( version >= 2 )\r\n\t{\r\n\t\tMemoryRead( &m_CASRemovalMask, sizeof( uint32 ), 1, p_data );\r\n\t}\r\n\t\r\n\tMemoryRead( &m_numCASData, sizeof( int ), 1, p_data );\r\n\r\n\tif( m_numCASData > 0 )\r\n\t{\r\n\t\t// CAS flags.\r\n\t\tmp_CASData = new NxXbox::sCASData[m_numCASData];\r\n\r\n\t\tfor( uint32 i = 0; i < m_numCASData; ++i )\r\n\t\t{\r\n\t\t\tMemoryRead( &mp_CASData[i].mask, sizeof( uint32 ) * 3, 1, p_data );\r\n\t\t}\r\n\r\n\t\t// Sort the CAS data based first on mesh, then on the first tri index, lowest to highest. This allows some efficient early-out checking\r\n\t\t// during the poly removal.\r\n\t\tqsort( mp_CASData, m_numCASData, sizeof( NxXbox::sCASData ), cmp );\r\n\t}\r\n\t\r\n\t// Set the data pointer to the new position on return.\r\n\t*pp_mem = p_data;\r\n\r\n\treturn ( m_numCASData > 0 );\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxMesh::CXboxMesh( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxMesh::CXboxMesh( const char *pMeshFileName )\r\n{\r\n\t// Only do the CAS flag building for skinned objects.\r\n\tif( strstr( pMeshFileName, \"skin\" ))\r\n\t{\r\n\t\tchar CASFileName[256];\r\n\t\tstrcpy( CASFileName, pMeshFileName );\r\n\t\tStr::LowerCase( CASFileName );\r\n\t\tchar *pExt = strstr( CASFileName, \"skin.xbx\" );\r\n\t\tif( pExt )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( pExt, ( \"Couldn't find skin.xbx extension in %s\", CASFileName ));\r\n\t\t\tstrcpy( pExt, \"cas.xbx\" );\r\n\t\t\tbuild_casdata_table( CASFileName );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxMesh::~CXboxMesh( void )\r\n{\r\n\tif( mp_CASData )\r\n\t{\r\n\t\tdelete [] mp_CASData;\r\n\t}\r\n\tif( mp_scene )\r\n\t{\r\n\t\tCEngine::sUnloadScene( mp_scene );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxMesh::SetCASData( uint8 *p_cas_data )\r\n{\r\n\tif( p_cas_data )\r\n\t{\r\n\t\tbuild_casdata_table_from_memory((void**)&p_cas_data );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxMesh::SetScene( CXboxScene *p_scene )\r\n{\r\n\tmp_scene = p_scene;\r\n\r\n\t// Copy the hierarchy info from the scene so that above the p-line stuff can access it.\r\n\tmp_hierarchyObjects\t\t= mp_scene->GetEngineScene()->mp_hierarchyObjects;\r\n\tm_numHierarchyObjects\t= mp_scene->GetEngineScene()->m_numHierarchyObjects;\r\n\r\n\t// Now that we have a scene attached, resolve any cas flag data into specific indexes in the mesh data.\r\n\tif( mp_CASData )\r\n\t{\r\n\t\tNxXbox::sCASData *p_cas_entry = mp_CASData;\r\n\t\tfor( uint32 entry = 0; entry < m_numCASData; ++entry, ++p_cas_entry )\r\n\t\t{\r\n\t\t\t// Get the mesh this entry references.\r\n\t\t\tuint32\t\t\tload_order\t= p_cas_entry->data0 >> 16;\r\n\t\t\tNxXbox::sMesh\t*p_mesh\t\t= p_scene->GetEngineScene()->GetMeshByLoadOrder( load_order );\r\n\t\t\tif( p_mesh )\r\n\t\t\t{\r\n\t\t\t\t// Get the indices of the poly referenced.\r\n\t\t\t\tuint32 i0 = p_cas_entry->data0 & 0xFFFF;\r\n\t\t\t\tuint32 i1 = p_cas_entry->data1 >> 16;\r\n\t\t\t\tuint32 i2 = p_cas_entry->data1 & 0xFFFF;\r\n\r\n\t\t\t\t// For every vertex index in this mesh...\r\n\t\t\t\tuint16 *p_indices\t= p_mesh->mp_index_buffer[0];\r\n\t\t\t\tuint32 index0\t\t= p_indices[0] & 0x7FFF;\r\n\t\t\t\tuint32 index1\t\t= p_indices[1] & 0x7FFF;\r\n\t\t\t\tfor( uint32 i = 2; i < p_mesh->m_num_indices[0]; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 index2 = p_indices[i] & 0x7FFF;\r\n\t\t\t\t\tif(( index0 == i0 ) && ( index1 == i1 ) && ( index2 == i2 ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_cas_entry->start_index = i - 2;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tindex0\t= index1;\r\n\t\t\t\t\tindex1\t= index2;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxMesh.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxMesh.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/15/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_MESH_H__\r\n#define\t__GFX_P_NX_MESH_H__\r\n    \r\n#include \"gfx/nxmesh.h\"\r\n#include \"p_nxscene.h\"\r\n\r\nnamespace NxXbox\r\n{\r\n\tstruct sScene;\r\n}\r\n\t\t\t \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CMesh\r\n    \r\nclass CXboxMesh : public CMesh\r\n{\r\n                                      \r\npublic:\r\n\t\t\t\t\t\tCXboxMesh( void );\r\n\t\t\t\t\t\tCXboxMesh( const char *pMeshFileName );\r\n\tvirtual \t\t\t~CXboxMesh();\r\n\tvoid\t\t\t\tSetScene( CXboxScene *p_scene );\r\n\tvoid\t\t\t\tSetTexDict( Nx::CTexDict *p_tex_dict )\t{ mp_texDict = p_tex_dict; }\r\n\tvoid\t\t\t\tSetCASData( uint8 *p_cas_data );\r\n\tCXboxScene\t\t\t*GetScene( void )\t\t\t\t\t\t{ return mp_scene; }\r\n\r\n\tNxXbox::sCASData\t*GetCASData( void )\t\t\t\t\t\t{ return mp_CASData; }\r\n\tuint32\t\t\t\tGetNumCASData( void )\t\t\t\t\t{ return m_numCASData; }\r\n\r\nprotected:\r\n\tbool\t\t\t\tbuild_casdata_table(const char* pFileName);\r\n\tbool\t\t\t\tbuild_casdata_table_from_memory( void **pp_mem );\r\n\r\n\tNxXbox::sCASData\t*mp_CASData;\r\n\tuint32\t\t\t\tm_numCASData;\r\n\r\nprivate:\r\n\tCXboxScene\t\t\t*mp_scene;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n#endif \r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxModel.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxModel.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/21/2002\r\n//****************************************************************************\r\n\r\n#include <core/math.h>\r\n\r\n#include \"gfx/nxmodel.h\"\r\n#include \"gfx/skeleton.h\"\r\n#include <gfx/xbox/p_nxmesh.h>\r\n#include \"gfx/xbox/p_nxmodel.h\"\r\n#include \"gfx/xbox/p_nxscene.h\"\r\n#include \"gfx/xbox/p_nxgeom.h\"\r\n#include \"gfx/xbox/nx/texture.h\"\r\n#include \"gfx/xbox/nx/render.h\"\r\n\t\t\t   \r\n#include <gel/assman/assman.h>\r\n#include <gel/assman/skinasset.h>\r\n\r\nint\t\t\ttest_num_bones\t\t\t= 0;\r\nMth::Matrix\t*p_test_bone_matrices\t= NULL;\r\nMth::Matrix\ttest_root_matrix;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxModel::plat_init_skeleton( int num_bones )\r\n{\r\n//\tif ( !mp_instance ) return false;\r\n//\tMth::Matrix * p_bone = new Mth::Matrix[numBones];\r\n//\r\n//\tmp_instance->SetBoneTransforms( p_bone );\r\n//\tfor ( int i = 0; i < numBones; i++ )\r\n//\t{\r\n//\t\tp_bone[i].Identity();\r\n//\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/*\r\n\tbool CXboxModel::plat_load_file(const char* p_fileName)\r\n{\r\n\t// Machine specific code here ............\r\n\t\r\n\t// TODO:  Make this more generalized\r\n\r\n\t// Load in the texture dictionary for the model.\r\n\tLst::HashTable< NxXbox::sTexture > *p_texture_table = NxXbox::LoadTextureFile( \"models/testskin/testskin.tex.xbx\" );\r\n\r\n    return true;\r\n}\r\n*/\r\n\r\n\r\n/*\r\nbool CXboxModel::plat_load_mesh( CMesh* pMesh )\r\n{\r\n\t// The skeleton must exist by this point (unless it's a hacked up car).\r\n\tint numBones;\r\n\tnumBones = mp_skeleton ? mp_skeleton->GetNumBones() : 1;\r\n\t\r\n\tMth::Matrix temp;\r\n\tCXboxMesh *p_xbox_mesh = static_cast<CXboxMesh*>( pMesh );\r\n\tmp_instance = new NxXbox::CInstance( p_xbox_mesh->GetScene()->GetEngineScene(), temp, numBones, mp_boneTransforms );\r\n\r\n    return true;\r\n}\r\n*/\t\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nbool CXboxModel::plat_unload_mesh( void )\r\n{\r\n\tif ( mp_instance != NULL )\r\n\t{\r\n\t\tdelete mp_instance;\r\n\t\tmp_instance = NULL;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n*/\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nbool CXboxModel::plat_set_render_mode(ERenderMode mode)\r\n{\r\n\t// Machine specific code here ............\r\n    return true;\r\n}\r\n*/\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nbool CXboxModel::plat_set_color(uint8 r, uint8 g, uint8 b, uint8 a)\r\n{\r\n\t// Machine specific code here ............\r\n    return true;\r\n}\r\n*/\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nbool CXboxModel::plat_set_visibility(uint32 mask)\r\n{\r\n    return true;\r\n}\r\n*/\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nbool CXboxModel::plat_set_active( bool active )\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\tmp_instance->SetActive( active );\r\n\t}\r\n\treturn true;\r\n}\r\n*/\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nbool CXboxModel::plat_set_scale(float scaleFactor)\r\n{\r\n\t// Machine specific code here ............\r\n    return true;\r\n}\r\n*/\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nbool CXboxModel::plat_replace_texture(char* p_srcFileName, char* p_dstFileName)\r\n{\r\n\t// Machine specific code here ............\r\n    return true;\r\n}\r\n*/\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nbool CXboxModel::plat_render( Mth::Matrix *pRootMatrix, Mth::Matrix *pBoneMatrices, int numBones )\r\n{\r\n\tif( mp_instance )\r\n\t{\r\n\t\tmp_instance->SetTransform( *pRootMatrix );\r\n\t}\r\n    return true;\r\n}\r\n*/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxModel::CXboxModel()\r\n{\r\n\tmp_instance = NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxModel::~CXboxModel()\r\n{\r\n\t// make sure it's deleted\r\n//\tplat_unload_mesh();\r\n\r\n\tif( mp_instance && mp_instance->GetBoneTransforms())\r\n\t{\r\n\t\tdelete mp_instance->GetBoneTransforms();\r\n\t\tmp_instance->SetBoneTransforms( NULL );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxModel::plat_set_bounding_sphere( const Mth::Vector& boundingSphere )\r\n{\r\n\t// Loop over all spheres.\r\n\tfor( int i = 0; i < m_numGeoms; i++ )\r\n\t{\r\n\t\tmp_geom[i]->SetBoundingSphere( boundingSphere );\r\n\t}\r\n}\r\n\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nMth::Vector CXboxModel::plat_get_bounding_sphere( void )\r\n{\r\n\tMth::Vector sphere, sphere1, sum, diff;\r\n\tfloat dist;\r\n\r\n\t// This should probably never happen.\r\n\tif( m_numGeoms == 0 )\r\n\t\treturn Mth::Vector( 0.0f, 0.0f, 0.0f, 0.0f );\r\n\r\n\t// Combine the spheres of all geoms (this should really be done once at load time).\r\n\r\n\t// Start with first sphere.\r\n\tsphere = mp_geom[0]->GetBoundingSphere();\r\n\r\n\t// Loop over remaining spheres, expanding as necessary.\r\n\tfor( int i = 1; i < m_numGeoms; ++i )\r\n\t{\r\n\t\t// Get next sphere.\r\n\t\tsphere1 = mp_geom[i]->GetBoundingSphere();\r\n\r\n\t\t// Centre-to-centre vector, and distance.\r\n\t\tdiff\t= sphere1-sphere;\r\n\t\tdist\t= diff.Length();\r\n\r\n\t\t// Test for sphere1 inside sphere.\r\n\t\tif( dist + sphere1[3] <= sphere[3] )\r\n\t\t\tcontinue;\t\t\t// keep sphere\r\n\r\n\t\t// Test for sphere inside sphere1.\r\n\t\tif( dist + sphere[3] <= sphere1[3] )\r\n\t\t{\r\n\t\t\tsphere = sphere1;\t// replace sphere\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Otherwise make a larger sphere that contains both.\r\n\t\tsum\t\t\t= sphere+sphere1;\r\n\t\tsphere\t\t= 0.5f * ( sum + ( diff[3] / dist ) * diff );\r\n\t\tsphere[3]\t= 0.5f * ( dist + sum[3] );\r\n\t}\r\n\r\n\tsphere[3] *= 2.0f;\r\n\t\r\n\treturn sphere;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // Nx\r\n\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxModel.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxModel.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  1/8/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_MODEL_H__\r\n#define\t__GFX_P_NX_MODEL_H__\r\n    \r\n#include \"gfx/nxmodel.h\"\r\n#include \"gfx/xbox/nx/instance.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CModel\r\n    \r\nclass CXboxModel : public CModel\r\n{\r\npublic:\r\n\t\t\t\t\t\tCXboxModel();\r\n\tvirtual \t\t\t~CXboxModel();\r\n\tNxXbox::CInstance\t*GetInstance( void )\t\t\t\t\t\t\t\t{ return mp_instance; }\r\n\tvoid\t\t\t\tSetInstance( NxXbox::CInstance *p_instance )\t\t{ mp_instance = p_instance; }\r\n\r\nprivate:\t\t\t\t// It's all private, as it is machine specific\r\n\tvirtual Mth::Vector\tplat_get_bounding_sphere( void );\r\n\tvirtual void\t\tplat_set_bounding_sphere( const Mth::Vector& boundingSphere );\r\n\r\n\tbool\t\t\t\tplat_init_skeleton( int num_bones );\r\n\r\n\tNxXbox::CInstance\t*mp_instance;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n#endif \r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxParticleRibbonTrail.cpp",
    "content": "#include <core/defines.h>\r\n#include <gfx/xbox/nx/render.h>\r\n\r\n#include \"gfx/xbox/p_nxparticleRibbonTrail.h\"\r\n\r\nextern DWORD PixelShader1;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleRibbonTrail::CXboxParticleRibbonTrail()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleRibbonTrail::CXboxParticleRibbonTrail( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum\t\t= checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\tm_mid_time\t\t= -1.0f;\r\n\tm_history\t\t= history;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float*[( history + 1)];\r\n\tfor( int lp = 0; lp < ( history + 1 ); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n\t// Create the engine representation.\r\n\tmp_engine_particle = new NxXbox::sParticleSystem( max_particles, NxXbox::PARTICLE_TYPE_RIBBONTRAIL, texture_checksum, blendmode_checksum, fix, num_segments, history );\r\n\r\n\t// Default color.\r\n\tm_start_color = new Image::RGBA[m_num_vertex_buffers];\r\n\tm_mid_color = new Image::RGBA[m_num_vertex_buffers];\r\n\tm_end_color = new Image::RGBA[m_num_vertex_buffers];\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 255;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 255;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 255;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleRibbonTrail::~CXboxParticleRibbonTrail()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\r\n\tdelete [] m_start_color;\r\n\tdelete [] m_mid_color;\r\n\tdelete [] m_end_color;\r\n\tdelete mp_engine_particle;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleRibbonTrail::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleRibbonTrail::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleRibbonTrail::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CXboxParticleRibbonTrail::plat_get_num_particle_colors( void ) { return m_num_vertex_buffers; }\r\nint CXboxParticleRibbonTrail::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CXboxParticleRibbonTrail::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CXboxParticleRibbonTrail::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CXboxParticleRibbonTrail::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CXboxParticleRibbonTrail::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CXboxParticleRibbonTrail::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CXboxParticleRibbonTrail::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CXboxParticleRibbonTrail::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CXboxParticleRibbonTrail::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CXboxParticleRibbonTrail::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CXboxParticleRibbonTrail::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CXboxParticleRibbonTrail::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CXboxParticleRibbonTrail::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleRibbonTrail::plat_render( void )\r\n{\r\n\t// Draw the particles.\r\n\tif( m_num_particles > 0 )\r\n\t{\r\n\t\tint\t\t\t\tlp;\r\n\t\tCParticleEntry\t*p_particle;\r\n\t\tfloat\t\t\t*p_v;\r\n//\t\tMth::Vector\t\tmin, max;\t// For dynamic bounding box calculation.\r\n\r\n\t\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\t\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\r\n\t\tImage::RGBA color[2];\r\n\t\tImage::RGBA *p_col0;\r\n\t\tImage::RGBA *p_col1;\r\n\r\n\t\t// Obtain push buffer lock.\r\n\t\tDWORD *p_push; \r\n\t\tDWORD dwords_per_particle\t= 16 * ( m_num_vertex_buffers - 1 );\r\n\t\tDWORD dword_count\t\t\t= dwords_per_particle * m_num_particles;\r\n\r\n\t\t// Submit particle material.\r\n\t\tmp_engine_particle->mp_material->Submit();\r\n\t\t\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\t\tNxXbox::set_pixel_shader( PixelShader1 );\r\n\t\t\r\n\t\t// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.\r\n\t\tp_push = D3DDevice_BeginPush( dword_count + 32 );\r\n\r\n\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1]\t= D3DPT_QUADLIST;\r\n\t\tp_push\t\t+= 2;\r\n\r\n\t\t// Set up loop variables here, since we be potentially enetering the loop more than once.\r\n\t\tlp\t\t\t= 0;\r\n\t\tp_particle\t= mp_particle_array;\r\n\t\tp_v\t\t\t= mp_vertices[0];\r\n\r\n\t\twhile( dword_count > 0 )\r\n\t\t{\r\n\t\t\tint dwords_written = 0;\r\n\r\n\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, ( dword_count > 2047 ) ? ((int)( 2047 / dwords_per_particle )) * dwords_per_particle: dword_count );\r\n\t\t\t++p_push;\r\n\t\t\r\n\t\t\tfor( ; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t\t\t{\r\n\t\t\t\t// Check to see if writing another particle will take us over the edge.\r\n\t\t\t\tif(( dwords_written + dwords_per_particle ) > 2047 )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\t\t\tMth::Vector\tpos[2];\r\n\t\t\t\tp_v = &mp_vertices[0][lp*3];\r\n\t\t\t\tpos[0].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\t\t\tp_v = &mp_vertices[1][lp*3];\r\n\t\t\t\tpos[1].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\r\n\t\t\t\tMth::Vector\tpart_vec = pos[1] - pos[0];\r\n\t\t\t\tMth::Vector perp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\t\t\tperp_vec.Normalize();\r\n\r\n\t\t\t\t// Dynamic bounding box calculation.\r\n//\t\t\t\tif( lp == 0 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tmin = pos[0];\r\n//\t\t\t\t\tmax = pos[0];\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( pos[0][X] < min[X] ) min[X] = pos[0][X]; else if( pos[0][X] > max[X] ) max[X] = pos[0][X];\r\n//\t\t\t\t\tif( pos[0][Y] < min[Y] ) min[Y] = pos[0][Y]; else if( pos[0][Y] > max[Y] ) max[Y] = pos[0][Y];\r\n//\t\t\t\t\tif( pos[0][Z] < min[Z] ) min[Z] = pos[0][Z]; else if( pos[0][Z] > max[Z] ) max[Z] = pos[0][Z];\r\n//\t\t\t\t}\r\n\r\n\t\t\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\t\r\n\t\t\t\tMth::Vector tmp[4];\r\n\r\n\t\t\t\tif( m_mid_time >= 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( terp < m_mid_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\t\tp_col1 = m_mid_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\t\t\tp_col1 = m_end_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No mid color specified.\r\n\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\t\tcolor[0].b = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\t\tcolor[0].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\t\tcolor[0].r = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\t\tcolor[0].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\r\n\t\t\t\ttmp[0]\t\t= pos[0] + ( perp_vec * w );\r\n\t\t\t\ttmp[1]\t\t= pos[0] - ( perp_vec * w );\r\n\r\n\t\t\t\tfor( int c = 1; c < m_num_vertex_buffers; c++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tstart = *p_col0++;\r\n\t\t\t\t\tend = *p_col1++;\r\n\r\n\t\t\t\t\tcolor[1].b = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\t\t\tcolor[1].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\t\t\tcolor[1].r = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\t\t\tcolor[1].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\r\n\t\t\t\t\tif( c > 1 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_v = &mp_vertices[c][lp*3];\r\n\t\t\t\t\t\tpos[1].Set( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\t\t\t\t\tpart_vec = pos[1] - pos[0];\r\n\t\t\t\t\t\tperp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\t\t\t\t\tperp_vec.Normalize();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttmp[2]\t\t= pos[1] + ( perp_vec * w );\r\n\t\t\t\t\ttmp[3]\t\t= pos[1] - ( perp_vec * w );\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[0][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[0][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[0][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[1][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[1][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[1][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[3][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[3][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[3][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[2][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[2][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[2][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\t\t\t\t\t\r\n\t\t\t\t\tcolor[0] = color[1];\r\n\t\t\t\t\tpos[0] = pos[1];\r\n\t\t\t\t\ttmp[0] = tmp[2];\r\n\t\t\t\t\ttmp[1] = tmp[3];\r\n\t\t\t\t}\r\n\t\t\t\tdwords_written\t+= dwords_per_particle;\r\n\t\t\t\tdword_count\t\t-= dwords_per_particle;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1] = 0;\r\n\t\tp_push += 2;\r\n\t\tD3DDevice_EndPush( p_push );\r\n\r\n\t\t// Set the mesh bounding box and sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMin( min );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMax( max );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center = D3DXVECTOR3( min[X] + (( max[X] - min[X] ) * 0.5f ), min[Y] + (( max[Y] - min[Y] ) * 0.5f ), min[Z] + (( max[Z] - min[Z] ) * 0.5f ));\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius = 360.0f;\r\n\r\n\t\t// And the scene bounding sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_center = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center;\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_radius = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius;\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxParticleRibbonTrail.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLERibbonTrail_H__\r\n#define\t__GFX_P_NX_PARTICLERibbonTrail_H__\r\n    \r\n#include \"gfx/xbox/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CXboxParticleRibbonTrail : public CParticle\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\t\tCXboxParticleRibbonTrail();\r\n\t\t\t\t\t\t\t\tCXboxParticleRibbonTrail( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t\t~CXboxParticleRibbonTrail();\r\n\r\n\tNxXbox::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\n\r\n\tprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\tint\t\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tint\t\t\t\t\t\t\tm_history;\r\n\tfloat**\t\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\t\tm_blend;\r\n\tNxXbox::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tImage::RGBA*\t\t\t\tm_start_color;\t\t\t\t// Start color for each corner.\r\n\tImage::RGBA*\t\t\t\tm_mid_color;\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA*\t\t\t\tm_end_color;\t\t\t\t// End color for each corner.\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxParticleShaded.cpp",
    "content": "#include <core/defines.h>\r\n#include <gfx/xbox/nx/render.h>\r\n#include \"gfx/xbox/p_NxParticleShaded.h\"\r\n\r\nextern DWORD PixelShader0;\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleShaded::CXboxParticleShaded()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleShaded::CXboxParticleShaded( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix )\r\n{\r\n\tm_checksum\t\t= checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\tm_mid_time\t\t= -1.0f;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices\t\t= new float[max_particles * 3];\r\n\r\n\t// Create the engine representation.\r\n\tmp_engine_particle = new NxXbox::sParticleSystem( max_particles, NxXbox::PARTICLE_TYPE_SHADED, texture_checksum, blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tfor( int c = 0; c < 4; ++c )\r\n\t{\r\n\t\tm_start_color[c].r = 128;\r\n\t\tm_start_color[c].g = 128;\r\n\t\tm_start_color[c].b = 128;\r\n\t\tm_start_color[c].a = 255;\r\n\r\n\t\tm_mid_color[c].r = 128;\r\n\t\tm_mid_color[c].g = 128;\r\n\t\tm_mid_color[c].b = 128;\r\n\t\tm_mid_color[c].a = 255;\r\n\r\n\t\tm_end_color[c].r = 128;\r\n\t\tm_end_color[c].g = 128;\r\n\t\tm_end_color[c].b = 128;\r\n\t\tm_end_color[c].a = 255;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleShaded::~CXboxParticleShaded()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n\tdelete mp_engine_particle;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleShaded::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleShaded::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleShaded::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CXboxParticleShaded::plat_get_num_particle_colors( void )\r\n{\r\n\treturn 4;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleShaded::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CXboxParticleShaded::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CXboxParticleShaded::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CXboxParticleShaded::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CXboxParticleShaded::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CXboxParticleShaded::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CXboxParticleShaded::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CXboxParticleShaded::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CXboxParticleShaded::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CXboxParticleShaded::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CXboxParticleShaded::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CXboxParticleShaded::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleShaded::plat_render( void )\r\n{\r\n\t// Draw the particles.\r\n\tif( m_num_particles > 0 )\r\n\t{\r\n\t\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\r\n\t\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\t\tMth::Vector up( 0.0f, 1.0f, 0.0f );\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\t\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\t\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\t\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\t\tscreen_right.Normalize();\r\n\t\tscreen_up.Normalize();\r\n\r\n\t\tint\t\t\t\tlp;\r\n\t\tCParticleEntry\t*p_particle;\r\n\t\tfloat\t\t\t*p_v;\r\n//\t\tMth::Vector\t\tmin, max;\t// For dynamic bounding box calculation.\r\n\t\r\n\t\t// Obtain push buffer lock.\r\n\t\tDWORD *p_push; \r\n\t\tDWORD dwords_per_particle\t= 24;\r\n\t\tDWORD dword_count\t\t\t= dwords_per_particle * m_num_particles;\r\n\r\n\t\t// Submit particle material.\r\n\t\tmp_engine_particle->mp_material->Submit();\r\n\t\t\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2( 0 ));\r\n\t\tNxXbox::set_pixel_shader( PixelShader0 );\r\n\t\t\r\n\t\t// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.\r\n\t\tp_push = D3DDevice_BeginPush( dword_count + 16 );\r\n\r\n\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1]\t= D3DPT_QUADLIST;\r\n\t\tp_push\t\t+= 2;\r\n\r\n\t\t// Set up loop variables here, since we be potentially enetering the loop more than once.\r\n\t\tlp\t\t\t= 0;\r\n\t\tp_particle\t= mp_particle_array;\r\n\t\tp_v\t\t\t= mp_vertices;\r\n\r\n\t\twhile( dword_count > 0 )\r\n\t\t{\r\n\t\t\tint dwords_written = 0;\r\n\r\n\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, ( dword_count > 2047 ) ? ((int)( 2047 / dwords_per_particle )) * dwords_per_particle: dword_count );\r\n\t\t\t++p_push;\r\n\t\t\r\n\t\t\tfor( ; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t\t\t{\r\n\t\t\t\t// Check to see if writing another particle will take us over the edge.\r\n\t\t\t\tif(( dwords_written + dwords_per_particle ) > 2047 )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfloat terp\t= p_particle->m_time / p_particle->m_life;\r\n\t\t\t\tfloat w\t\t= p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\t\t\tfloat h\t\t= p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\t\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\t\t\tMth::Vector\tss_right, ss_up, ss_pos;\r\n\t\t\t\tMth::Vector tmp;\r\n\t\r\n\t\t\t\t// Dynamic bounding box calculation.\r\n//\t\t\t\tif( lp == 0 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tmin = pos;\r\n//\t\t\t\t\tmax = pos;\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( pos[X] < min[X] ) min[X] = pos[X]; else if( pos[X] > max[X] ) max[X] = pos[X];\r\n//\t\t\t\t\tif( pos[Y] < min[Y] ) min[Y] = pos[Y]; else if( pos[Y] > max[Y] ) max[Y] = pos[Y];\r\n//\t\t\t\t\tif( pos[Z] < min[Z] ) min[Z] = pos[Z]; else if( pos[Z] > max[Z] ) max[Z] = pos[Z];\r\n//\t\t\t\t}\r\n\t\t\r\n\t\t\t\tss_right\t= screen_right * w;\r\n\t\t\t\tss_up\t\t= screen_up * h;\r\n\r\n\t\t\t\tImage::RGBA color[4];\r\n\t\t\t\tImage::RGBA *p_col0;\r\n\t\t\t\tImage::RGBA *p_col1;\r\n\t\t\r\n\t\t\t\tif( m_mid_time >= 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( terp < m_mid_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\t\tp_col1 = m_mid_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\t\t\tp_col1 = m_end_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No mid color specified.\r\n\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( int c = 0; c < 4; c++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\t\t\t// Swap red and blue here.\r\n\t\t\t\t\tcolor[c].b = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\t\t\tcolor[c].r = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t\t\t}\r\n\t\t\r\n\t\t\t\ttmp\t\t\t= pos - ss_right + ss_up;\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\tp_push[4]\t= 0x00000000UL;\r\n\t\t\t\tp_push[5]\t= 0x00000000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\t\r\n\t\t\t\ttmp\t\t\t= pos + ss_right + ss_up;\t\t\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\tp_push[4]\t= 0x3F800000UL;\r\n\t\t\t\tp_push[5]\t= 0x00000000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\r\n\t\t\t\ttmp\t\t\t= pos + ss_right - ss_up;\t\t\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[2] );\r\n\t\t\t\tp_push[4]\t= 0x3F800000UL;\r\n\t\t\t\tp_push[5]\t= 0x3F800000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\t\t\r\n\t\t\t\ttmp\t\t\t= pos - ss_right - ss_up;\t\t\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[3] );\r\n\t\t\t\tp_push[4]\t= 0x00000000UL;\r\n\t\t\t\tp_push[5]\t= 0x3F800000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\r\n\t\t\t\tdwords_written\t+= dwords_per_particle;\r\n\t\t\t\tdword_count\t\t-= dwords_per_particle;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1] = 0;\r\n\t\tp_push += 2;\r\n\t\tD3DDevice_EndPush( p_push );\r\n\r\n\t\t// Set the mesh bounding box and sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMin( min );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMax( max );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center = D3DXVECTOR3( min[X] + (( max[X] - min[X] ) * 0.5f ), min[Y] + (( max[Y] - min[Y] ) * 0.5f ), min[Z] + (( max[Z] - min[Z] ) * 0.5f ));\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius = 360.0f;\r\n\r\n\t\t// And the scene bounding sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_center = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center;\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_radius = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius;\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\t\t\t\t\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxParticleShaded.h",
    "content": "#ifndef\t__GFX_P_NX_PARTICLESHADED_H__\r\n#define\t__GFX_P_NX_PARTICLESHADED_H__\r\n    \r\n#include \"gfx/nxparticle.h\"\r\n#include \"gfx/xbox/nx/particles.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CXboxParticleShaded : public CParticle\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\tCXboxParticleShaded();\r\n\t\t\t\t\t\t\tCXboxParticleShaded( uint32 checksum, int max_particles = 256, uint32 texture_checksum = 0, uint32 blendmode_checksum = 0, int fix = 128 );\r\n\tvirtual \t\t\t\t~CXboxParticleShaded();\r\n\r\n\tNxXbox::sParticleSystem\t*GetEngineParticle( void )\t{ return mp_engine_particle; }\r\n\r\n\r\n\tprivate:\t\t\t\t// It's all private, as it is machine specific\r\n\tvirtual void\t\t\tplat_render( void );\r\n\tvirtual void\t\t\tplat_get_position( int entry, int list, float *x, float *y, float *z );\r\n\tvirtual void\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvirtual void\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tvirtual int\t\t\t\tplat_get_num_particle_colors( void );\r\n\tvirtual int\t\t\t\tplat_get_num_vertex_lists( void )\t\t{ return 1; }\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\r\n\tImage::RGBA\t\t\t\tm_start_color[4];\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color[4];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color[4];\t\t\t\t// End color for each corner.\r\n\t\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tNxXbox::sParticleSystem\t*mp_engine_particle;\r\n\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n#endif \r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxParticleStar.cpp",
    "content": "#include <core/defines.h>\r\n#include \"gfx/xbox/nx/render.h\"\r\n\r\n#include \"gfx/xbox/p_nxparticleStar.h\"\r\n\r\nextern DWORD PixelShader1;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleStar::CXboxParticleStar()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleStar::CXboxParticleStar( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split )\r\n{\r\n\tm_checksum\t\t= checksum;\r\n\tm_max_particles\t= max_particles;\r\n\tm_num_particles\t= 0;\r\n\tm_mid_time\t\t= -1.0f;\r\n\tm_num_segments\t= num_segments;\r\n\tm_split\t\t\t= split;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n\t// Create the engine representation.\r\n\tmp_engine_particle = new NxXbox::sParticleSystem( max_particles, NxXbox::PARTICLE_TYPE_STAR, texture_checksum, blendmode_checksum, fix, num_segments );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 3; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 255;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 255;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 255;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleStar::~CXboxParticleStar()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n\tdelete mp_engine_particle;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleStar::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleStar::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleStar::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CXboxParticleStar::plat_get_num_particle_colors( void ) { return 3; }\r\nint CXboxParticleStar::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CXboxParticleStar::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CXboxParticleStar::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CXboxParticleStar::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CXboxParticleStar::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CXboxParticleStar::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CXboxParticleStar::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CXboxParticleStar::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CXboxParticleStar::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CXboxParticleStar::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CXboxParticleStar::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CXboxParticleStar::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CXboxParticleStar::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleStar::plat_render( void )\r\n{\r\n\t// Draw the particles.\r\n\tif( m_num_particles > 0 )\r\n\t{\r\n\t\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\r\n\t\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\t\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\t\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\t\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\t\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\t\tscreen_right.Normalize();\r\n\t\tscreen_up.Normalize();\r\n\t\r\n\t\tint\t\t\t\tlp;\r\n\t\tCParticleEntry\t*p_particle;\r\n\t\tfloat\t\t\t*p_v;\r\n//\t\tMth::Vector\t\tmin, max;\t// For dynamic bounding box calculation.\r\n\r\n\t\t// Obtain push buffer lock.\r\n\t\tDWORD *p_push; \r\n\t\tDWORD dwords_per_particle\t= 16 * m_num_segments;\r\n\t\tDWORD dword_count\t\t\t= dwords_per_particle * m_num_particles;\r\n\r\n\t\t// Submit particle material.\r\n\t\tmp_engine_particle->mp_material->Submit();\r\n\t\t\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\t\tNxXbox::set_pixel_shader( PixelShader1 );\r\n\t\t\r\n\t\t// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.\r\n\t\tp_push = D3DDevice_BeginPush( dword_count + 32 );\r\n\r\n\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1]\t= D3DPT_QUADLIST;\r\n\t\tp_push\t\t+= 2;\r\n\r\n\t\t// Set up loop variables here, since we be potentially enetering the loop more than once.\r\n\t\tlp\t\t\t= 0;\r\n\t\tp_particle\t= mp_particle_array;\r\n\t\tp_v\t\t\t= mp_vertices;\r\n\r\n\t\twhile( dword_count > 0 )\r\n\t\t{\r\n\t\t\tint dwords_written = 0;\r\n\r\n\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, ( dword_count > 2047 ) ? ((int)( 2047 / dwords_per_particle )) * dwords_per_particle: dword_count );\r\n\t\t\t++p_push;\r\n\t\t\r\n\t\t\tfor( ; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t\t\t{\r\n\t\t\t\t// Check to see if writing another particle will take us over the edge.\r\n\t\t\t\tif(( dwords_written + dwords_per_particle ) > 2047 )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfloat terp\t= p_particle->m_time / p_particle->m_life;\r\n\t\t\t\tfloat w\t\t= p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\t\t\tfloat h\t\t= p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\t\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\t\t\tMth::Vector\tss_right, ss_up;\r\n\t\t\t\tMth::Vector tmp[3];\r\n\t\r\n\t\t\t\t// Dynamic bounding box calculation.\r\n//\t\t\t\tif( lp == 0 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tmin = pos;\r\n//\t\t\t\t\tmax = pos;\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( pos[X] < min[X] ) min[X] = pos[X]; else if( pos[X] > max[X] ) max[X] = pos[X];\r\n//\t\t\t\t\tif( pos[Y] < min[Y] ) min[Y] = pos[Y]; else if( pos[Y] > max[Y] ) max[Y] = pos[Y];\r\n//\t\t\t\t\tif( pos[Z] < min[Z] ) min[Z] = pos[Z]; else if( pos[Z] > max[Z] ) max[Z] = pos[Z];\r\n//\t\t\t\t}\r\n\r\n\t\t\t\tss_right\t= screen_right * w;\r\n\t\t\t\tss_up\t\t= screen_up * h;\r\n\t\r\n\t\t\t\tImage::RGBA color[3];\r\n\t\t\t\tImage::RGBA *p_col0;\r\n\t\t\t\tImage::RGBA *p_col1;\r\n\r\n\t\t\t\tif( m_mid_time >= 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( terp < m_mid_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\t\tp_col1 = m_mid_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\t\t\tp_col1 = m_end_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No mid color specified.\r\n\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor( int c = 0; c < 3; c++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\t\t\t// Swap red and blue here.\r\n\t\t\t\t\tcolor[c].b = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\t\t\tcolor[c].r = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttmp[0]  = pos;\r\n\t\t\t\ttmp[0] += ss_right * sinf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\t\t\t\ttmp[0] += ss_up    * cosf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\r\n\t\t\t\tfor( int lp2 = 0; lp2 < m_num_segments; lp2++ )\r\n\t\t\t\t{\r\n\t\t\t\t\ttmp[1]  = pos;\r\n\t\t\t\t\ttmp[1] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\t\t\t\t\ttmp[1] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments) ) * ( lp2 + 1 ) ) ) ) * m_split;\r\n\r\n\t\t\t\t\ttmp[2]  = pos;\r\n\t\t\t\t\ttmp[2] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) );\r\n\t\t\t\t\ttmp[2] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) );\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&pos[X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&pos[Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&pos[Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[0][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[0][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[0][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[2][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[2][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[2][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[2] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[1][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[1][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[1][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\ttmp[0] = tmp[1];\r\n\t\t\t\t}\r\n\t\t\t\tdwords_written\t+= dwords_per_particle;\r\n\t\t\t\tdword_count\t\t-= dwords_per_particle;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1] = 0;\r\n\t\tp_push += 2;\r\n\t\tD3DDevice_EndPush( p_push );\r\n\r\n\t\t// Set the mesh bounding box and sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMin( min );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMax( max );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center = D3DXVECTOR3( min[X] + (( max[X] - min[X] ) * 0.5f ), min[Y] + (( max[Y] - min[Y] ) * 0.5f ), min[Z] + (( max[Z] - min[Z] ) * 0.5f ));\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius = 360.0f;\r\n\r\n\t\t// And the scene bounding sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_center = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center;\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_radius = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius;\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxParticleStar.h",
    "content": "#ifndef\t__GFX_P_NX_PARTICLEStar_H__\r\n#define\t__GFX_P_NX_PARTICLEStar_H__\r\n    \r\n#include \"gfx/xbox/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CXboxParticleStar : public CParticle\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\tCXboxParticleStar();\r\n\t\t\t\t\t\t\tCXboxParticleStar( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split );\r\n\tvirtual \t\t\t\t~CXboxParticleStar();\r\n\r\n\tNxXbox::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\n\r\n\tprivate:\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n\r\n\tNxXbox::sParticleSystem*\tmp_engine_particle;\r\n\tint\t\t\t\t\t\tm_num_segments;\r\n\tfloat\t\t\t\t\tm_split;\r\n\tImage::RGBA\t\t\t\tm_start_color[3];\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color[3];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color[3];\t\t\t\t// End color for each corner.\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxSprite.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxSprite.cpp\r\n\r\n#include \t\"Gfx/xbox/p_NxSprite.h\"\r\n#include \t\"Gfx/xbox/p_NxTexture.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CSprite\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCXboxSprite::CXboxSprite()\r\n{\r\n\tmp_plat_sprite = new NxXbox::sSprite();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCXboxSprite::~CXboxSprite()\r\n{\r\n\tdelete mp_plat_sprite;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CXboxSprite::plat_initialize()\r\n{\r\n\tplat_update_engine();\r\n\tplat_update_priority();\r\n\tplat_update_hidden();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxSprite::plat_update_hidden()\r\n{\r\n\t// Take sprite on or off draw list\r\n\tmp_plat_sprite->SetHidden( m_hidden );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxSprite::plat_update_engine()\r\n{\r\n\tCXboxTexture *p_xbox_texture = static_cast<CXboxTexture *>( mp_texture );\r\n\r\n\tif( p_xbox_texture )\r\n\t{\r\n\t\t// Rebuild sprite primitives\r\n\t\tmp_plat_sprite->mp_texture\t= p_xbox_texture->GetEngineTexture();\r\n\t}\r\n\t\r\n\tmp_plat_sprite->m_xpos\t\t= m_pos_x;\r\n\tmp_plat_sprite->m_ypos\t\t= m_pos_y;\r\n\tmp_plat_sprite->m_width\t\t= m_width;\r\n\tmp_plat_sprite->m_height\t= m_height;\r\n\tmp_plat_sprite->m_scale_x\t= m_scale_x;\r\n\tmp_plat_sprite->m_scale_y\t= m_scale_y;\r\n\r\n\tmp_plat_sprite->m_xhot\t\t= (( m_anchor_x + 1.0f ) * 0.5f) * ( m_width );\r\n\tmp_plat_sprite->m_yhot\t\t= (( m_anchor_y + 1.0f ) * 0.5f) * ( m_height );\r\n\r\n\tmp_plat_sprite->m_rot\t\t= m_rotation;\r\n\tmp_plat_sprite->m_rgba\t\t= *((uint32 *) &m_rgba);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxSprite::plat_update_priority()\r\n{\r\n\t// Update draw list.\r\n\tif( mp_plat_sprite )\r\n\t{\r\n\t\tmp_plat_sprite->SetPriority( m_priority );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCSprite::plat_enable_constant_z_value(bool enable)\r\n{\r\n\t//NxPs2::SSprite::EnableConstantZValue(enable);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCSprite::plat_set_constant_z_value(Nx::ZBufferValue z)\r\n{\r\n\t//NxPs2::SSprite::SetConstantZValue(z);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::ZBufferValue\tCSprite::plat_get_constant_z_value()\r\n{\r\n\t//return NxPs2::SSprite::GetConstantZValue();\r\n\treturn 0;\r\n}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxSprite.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxScene.h\r\n\r\n#ifndef\t__GFX_P_NX_SPRITE_H__\r\n#define\t__GFX_P_NX_SPRITE_H__\r\n\r\n#include \t\"Gfx/NxSprite.h\"\r\n#include \t\"Gfx/xbox/NX/texture.h\"\r\n#include \t\"Gfx/xbox/NX/sprite.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Machine specific implementation of the CSprite\r\nclass\tCXboxSprite : public CSprite\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCXboxSprite();\r\n\tvirtual\t\t\t\t\t\t~CXboxSprite();\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\tvirtual void\t\t\t\tplat_initialize();\r\n\r\n\tvirtual void\t\t\t\tplat_update_hidden();\t\t// Tell engine of update\r\n\tvirtual void\t\t\t\tplat_update_engine();\t\t// Update engine primitives\r\n\tvirtual void\t\t\t\tplat_update_priority();\r\n\r\n\tNxXbox::sSprite *\t\t\tmp_plat_sprite;\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxTextured3dPoly.cpp",
    "content": "#include \t\"Gfx/Xbox/p_NxTextured3dPoly.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CTextured3dPoly\r\n\r\nCXboxTextured3dPoly::CXboxTextured3dPoly( void )\r\n{\r\n}\r\n\r\nCXboxTextured3dPoly::~CXboxTextured3dPoly( void )\r\n{\r\n}\r\n\r\nvoid CXboxTextured3dPoly::plat_render( void )\r\n{\r\n}\r\n\r\n} // Namespace NxXbox  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxTextured3dPoly.h",
    "content": "#ifndef\t__GFX_P_NX_TEXTURED_3D_POLY_H__\r\n#define\t__GFX_P_NX_TEXTURED_3D_POLY_H__\r\n\r\n#include <gfx/nxtextured3dpoly.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n// Machine specific implementation of CTextured3dPoly\r\nclass\tCXboxTextured3dPoly : public Nx::CTextured3dPoly\r\n{\r\npublic:\r\n\t\t   \t\t\t\t\tCXboxTextured3dPoly();\r\n\tvirtual\t\t\t\t\t~CXboxTextured3dPoly();\r\nprivate:\r\n\tvirtual void\t\t\tplat_render();\r\n};\r\n\r\n}\t// namespace NxXbox\r\n\r\n#endif\r\n\t\t\t\t   \r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxViewMan.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxViewMan.cpp - Xbox platform specific interface to CViewportManager\r\n\r\n#include <core/defines.h>\r\n\r\n#include \"gfx/NxViewMan.h\"\r\n#include \"gfx/Xbox/p_NxViewport.h\"\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCViewport *CViewportManager::s_plat_create_viewport( const Mth::Rect *rect, Gfx::Camera *cam )\r\n{\r\n\treturn new CXboxViewport( rect, cam );\r\n}\r\n\r\n} \r\n \r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxViewport.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxViewport.cpp\r\n\r\n#include \t\"Gfx/NxViewMan.h\"\r\n#include \t\"Gfx/Xbox/p_NxViewport.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CViewport\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxViewport::CXboxViewport()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxViewport::CXboxViewport( const Mth::Rect *rect, Gfx::Camera *cam) : CViewport( rect, cam )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxViewport::~CXboxViewport()\r\n{\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nfloat CXboxViewport::plat_transform_to_screen_coord( const Mth::Vector & world_pos, float & screen_pos_x, float & screen_pos_y, ZBufferValue & screen_pos_z )\r\n{\r\n\tD3DXVECTOR3\tin( world_pos[X], world_pos[Y], world_pos[Z] );\r\n\tD3DXVECTOR4\tmid;\r\n\tD3DXVECTOR3\tout;\r\n\tD3DXVec3Transform( &mid, &in, (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix );\r\n\r\n\tin.x = mid.x;\r\n\tin.y = mid.y;\r\n\tin.z = mid.z;\r\n\tD3DXVec3TransformCoord( &out, &in, (D3DXMATRIX*)&NxXbox::EngineGlobals.projection_matrix );\r\n\r\n\t// Convert from homogenous cube (-1.0, 1.0) to pixel coordinates. Have to be careful here, the initial\r\n\t// feeling is to use the backbuffer width and height as multipliers, but since this value is being used\r\n\t// for text which has it's position re-converted at draw time, we actually want to use the fixed Ps2 screen\r\n\t// values here.\r\n\tscreen_pos_x = (( out.x + 1.0f ) * 0.5f ) * 640.0f;\r\n\tscreen_pos_y = (( -out.y + 1.0f ) * 0.5f ) * 448.0f;\r\n\t\r\n\tfloat scale = -1.0f;\r\n\t\r\n\tif( out.z < 1.0f )\r\n\t{\r\n\t\t// Text is not clipped. Calculate scale factor.\r\n\t\tfloat d_noscale = Nx::CViewportManager::sGet2DIn3DSpaceNoscaleDistance();\r\n\t\tfloat s_min\t\t= Nx::CViewportManager::sGet2DIn3DSpaceMinScale();\r\n\t\tfloat s_max\t\t= Nx::CViewportManager::sGet2DIn3DSpaceMaxScale();\r\n\t\t\r\n\t\tscale = d_noscale / -mid.z;\r\n\r\n\t\t// Clamp scale.\r\n\t\tif( scale > s_max )\r\n\t\t{\r\n\t\t\tscale = s_max;\r\n\t\t}\r\n\t\telse if( scale < s_min )\r\n\t\t{\r\n\t\t\tscale = s_min;\r\n\t\t}\r\n\t\t\r\n\t\t// The z value is passed in as a uint32, so set the value here based on fixed point 16:16.\r\n\t\tscreen_pos_z = (uint32)( out.z * 65536.0f );\r\n\t}\r\n\t\t\r\n\t// This is the scale factor. Returning a value < 0 will cause the text to be hidden.\r\n\treturn scale;\r\n}\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxViewport.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxViewport.h\r\n\r\n#ifndef\t__GFX_P_NX_VIEWPORT_H__\r\n#define\t__GFX_P_NX_VIEWPORT_H__\r\n\r\n#include \"Gfx/NxViewport.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Machine specific implementation of the CViewport\r\nclass\tCXboxViewport : public CViewport\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCXboxViewport();\r\n\t\t\t\t\t\t\t\tCXboxViewport( const Mth::Rect *rect, Gfx::Camera *cam = NULL );\r\n\tvirtual\t\t\t\t\t\t~CXboxViewport();\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n//\tvirtual void\t\t\t\tplat_initialize();\r\n\tvirtual float\t\t\t\tplat_transform_to_screen_coord( const Mth::Vector & world_pos, float & screen_pos_x, float & screen_pos_y, ZBufferValue & screen_pos_z );\r\n\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxWin2D.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxWin2D.cpp\r\n\r\n#include \t\"Gfx/Xbox/p_NxWin2D.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxWindow2D::CXboxWindow2D( int x, int y, int width, int height) : CWindow2D( x, y, width, height )\r\n{\r\n\tplat_update_engine();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxWindow2D::~CXboxWindow2D()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxWindow2D::plat_update_engine()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CWindow2DManager::s_plat_alloc_window2d_pool()\r\n{\r\n\tfor( int i = 0; i < vMAX_WINDOW_INSTANCES; i++ )\r\n\t{\r\n\t   \tCXboxWindow2D *p_window = new CXboxWindow2D;\r\n\t\tp_window->mp_next\t= sp_window_list;\r\n\t\tsp_window_list\t\t= p_window;\r\n\t}\r\n}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_NxWin2D.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxWin2D.h\r\n\r\n#ifndef\t__GFX_P_NX_WIN2D_H__\r\n#define\t__GFX_P_NX_WIN2D_H__\r\n\r\n#include \t\"Gfx/NxWin2D.h\"\r\n#include \t\"Gfx/Xbox/NX/sprite.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of the CWindow2D\r\nclass\tCXboxWindow2D : public CWindow2D\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCXboxWindow2D( int x = 0, int y = 0, int width = 640, int height = 480 );\r\n\t\t\t\t\t\t\t\tCXboxWindow2D( const Mth::Rect & win_rect);\r\n\tvirtual\t\t\t\t\t\t~CXboxWindow2D();\r\n\r\nprivate:\r\n\t//\r\n\tvirtual void\t\t\t\tplat_update_engine();\t\t// Update engine primitives\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_gfxman.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics (GFX)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_gfxman.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t07/26/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGraphics device manager\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\r\n#include <xtl.h>\r\n#include <xgraphics.h>\r\n#include <sys/file/filesys.h>\r\n#include <gfx/gfxman.h>\r\n#include <gfx/xbox/nx/nx_init.h>\r\n#include <gfx/xbox/nx/gamma.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Manager::SetGammaNormalized( float fr, float fg, float fb )\r\n{\r\n\tNxXbox::SetGammaNormalized( fr, fg, fb );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Manager::GetGammaNormalized( float *fr, float *fg, float *fb )\r\n{\r\n\tNxXbox::GetGammaNormalized( fr, fg, fb );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::DumpVRAMUsage( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::ScreenShot( const char *fileroot )\r\n{\r\n\t// Called twice per frame - once to request the screenshot, and once (post Swap()), to actually perform it.\r\n\tif( NxXbox::EngineGlobals.screenshot_name[0] == 0 )\r\n\t{\r\n\t\tstrcpy( NxXbox::EngineGlobals.screenshot_name, fileroot );\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tchar fileName[32];\r\n\tchar fullFileName[64];\r\n\t\r\n\t// Try to find a good filename of the format filebasexxx.bmp. \"Good\" is defined here as one that isn't already used.\r\n\tfor( int i = 0;; ++i )\r\n\t{\r\n\t\tsprintf( fileName, \"screens\\\\%s%03d.bmp\", fileroot, i );\r\n\r\n\t\t// Found an unused one! Yay!\r\n\t\tif( !File::Exist( fileName ))\r\n\t\t{\r\n\t\t\tsprintf( fullFileName, \"d:\\\\data\\\\screens\\\\%s%03d.bmp\", fileroot, i );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Obtain the render surface.\r\n\tIDirect3DSurface8 *p_render_target = NxXbox::EngineGlobals.p_RenderSurface;\r\n\r\n\t// Get the surface description, just for s and g.\r\n\tD3DSURFACE_DESC surface_desc;\r\n\tp_render_target->GetDesc( &surface_desc );\r\n\r\n\t// This is great - this function spits surfaces straight out into a file.\r\n\tHRESULT hr = XGWriteSurfaceToFile( p_render_target, fullFileName );\r\n\tDbg_Assert( hr == S_OK );\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n} // namespace Gfx\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_loadscreen.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGfx\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tLoadScreen\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_loadscreen.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t05/08/02\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXBox-specific loading screen calls\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n#include <core/defines.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/timer.h>\r\n#include <gel/mainloop.h>\r\n#include <gfx/gfxman.h>\r\n#include <gfx/nxviewport.h>\r\n#include <gel/scripting/script.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace LoadScreen\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Skate3 code, disabled for now.\r\n#if 0\r\nextern \"C\" RwBool _rwXbSetRenderState(RwRenderState nState, void *pParam);\r\nextern \"C\" RwBool _rwXbGetRenderState(RwRenderState nState, void *pParam);\r\nextern \"C\" RwBool _rwXbRenderStateTextureRaster(RwRaster *raster);\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass LoadingIconData\r\n{\r\npublic:\r\n\tint\tm_X;\r\n\tint\tm_Y;\r\n\tint m_FrameDelay;\r\n//\tSkate3 code, disabled for now.\r\n#\tif 0\r\n\tRwRaster** m_Rasters;\r\n#\tendif\r\n\tint m_NumFrames;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic bool\t\t\t\ts_loading_screen_on\t\t= false;\r\nstatic MMRESULT\t\t\ts_timer_event\t\t\t= 0;\r\nstatic LoadingIconData\ts_load_icon_data\t\t= { 0 };\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\nvoid CALLBACK loadIconTimerCallback( UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2 )\r\n{\r\n\tstatic int current_image = 0;\r\n\r\n//\tSkate3 code, disabled for now.\r\n#\tif 0\r\n\t\r\n\t// Here is where the load icon will be written to the screen.\r\n\tRwRect rect;\r\n\trect.x = s_load_icon_data.m_X;\r\n\trect.y = s_load_icon_data.m_Y;\r\n\r\n\trect.w = SCREEN_CONV_X( 32.0f ) - SCREEN_CONV_X( 0.0f );\r\n\trect.h = SCREEN_CONV_Y( 32.0f ) - SCREEN_CONV_Y( 0.0f );\r\n\r\n\tSpt::SingletonPtr< Gfx::Manager > gfx_manager;\r\n\r\n\t_rwXbSetRenderState( rwRENDERSTATETEXTURERASTER, (void *)NULL );\r\n\r\n\tRwRaster* p_context_raster;\r\n\tp_context_raster = gfx_manager->DefaultViewport().GetFrameBuffer();\r\n\r\n\tRwRasterPushContext( p_context_raster );\r\n\r\n\tRwRasterRenderScaled( s_load_icon_data.m_Rasters[current_image], &rect );\r\n\tRwRasterShowRaster( p_context_raster, NULL, 0 );\r\n\r\n\tRwRasterPopContext();\r\n\r\n#\tendif\r\n\t\r\n\tcurrent_image = ( current_image + 1 ) % s_load_icon_data.m_NumFrames ;\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid SetLoadingIconProperties( int x, int y, int frame_delay, int num_frames, char* basename, char* ext )\r\n{\r\n\tint i;\r\n\r\n//\tSkate3 code, disabled for now.\r\n#\tif 0\r\n\r\n\tif( s_load_icon_data.m_NumFrames > 0  )\r\n\t{   \r\n\t\tfor( i = 0; i < s_load_icon_data.m_NumFrames; i++ )\r\n\t\t{\r\n\t\t\tRwRasterDestroy( s_load_icon_data.m_Rasters[i] );\r\n\t\t}\r\n\t\tdelete [] s_load_icon_data.m_Rasters;\r\n\t}\r\n\r\n\ts_load_icon_data.m_X\t\t\t= SCREEN_CONV_X( x );\r\n\ts_load_icon_data.m_Y\t\t\t= SCREEN_CONV_Y( y );\r\n\ts_load_icon_data.m_FrameDelay = frame_delay;\r\n\ts_load_icon_data.m_NumFrames = num_frames;\r\n\ts_load_icon_data.m_Rasters = new RwRaster*[s_load_icon_data.m_NumFrames];\r\n\r\n\tRwImageSetPath(\"\");\r\n\tfor( i = 0; i < s_load_icon_data.m_NumFrames; i++ )\r\n\t{\r\n\t\tchar image_name[64];\r\n\t\t//sprintf( image_name, \"Images/PanelSprites/wheel_0%d.png\", i+1 );\r\n\t\tsprintf( image_name, \"%s%d.%s\", basename, i+1, ext );\r\n\t\ts_load_icon_data.m_Rasters[i] = RwRasterRead( image_name );\r\n\t}\r\n\r\n#\tendif\r\n}\r\n\r\nvoid Display( char* filename, bool just_freeze, bool blank )\r\n{\r\n\t// Redundancy Check\r\n\tif( s_loading_screen_on )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n    \r\n\t// Set filename up for foreign languages.\r\n\tchar name[256];\r\n\r\n\t// Seems that filename may sometimes be NULL.\r\n\tif( filename )\r\n\t{\r\n\t\tchar * p8 = &filename[strlen(filename)];\r\n\r\n\t\tif( IsEnglish())\r\n\t\t{\r\n\t\t\tstrcpy ( name, filename );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tswitch ( XGetLanguage() ) {\r\n\t\t\t\tcase XC_LANGUAGE_FRENCH:\r\n\t\t\t\t\twhile ( ( *p8 != '\\\\' ) && ( *p8 != '/' ) ) p8--;\r\n\t\t\t\t\tsprintf( name, \"images\\\\frimages\\\\%s\", &p8[1] );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase XC_LANGUAGE_GERMAN:\r\n\t\t\t\t\twhile ( ( *p8 != '\\\\' ) && ( *p8 != '/' ) ) p8--;\r\n\t\t\t\t\tsprintf( name, \"images\\\\grimages\\\\%s\", &p8[1] );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tstrcpy ( name, filename );\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n//\tTmr::Time start_time = Tmr::GetTime();\r\n\r\n//\tSkate3 code, disabled for now.\r\n#\tif 0\r\n    if (!just_freeze && ! blank)\r\n\t{\r\n\t\tRwImageSetPath( \"\" );\r\n\t\tRwRaster* raster = RwRasterRead( name );\r\n\t\r\n\t\tif( raster == NULL )\r\n\t\t{\r\n\t\t\t// Try the english version.\r\n\t\t\traster = RwRasterRead( filename );\r\n\t\t\tif( raster == NULL )\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"Could not load %s\\n\", filename );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Wait a few VBlanks for RW stuff to disappear.\r\n//\t\twhile( Tmr::GetTime() - start_time < Tmr::VBlanks( 4 ));\r\n\r\n\t\tRwRect rect;\r\n\t\trect.x = SCREEN_CONV_X( 0 );\r\n\t\trect.y = SCREEN_CONV_Y( 0 );\r\n\t\trect.w = SCREEN_CONV_X( 640 ) - SCREEN_CONV_X( 0 );\r\n\t\trect.h = SCREEN_CONV_Y( 448 ) - SCREEN_CONV_Y( 0 );\r\n\r\n\t\tSpt::SingletonPtr< Gfx::Manager > gfx_manager;\r\n\r\n\t\t_rwXbSetRenderState( rwRENDERSTATETEXTURERASTER, (void *)NULL );\r\n\r\n\t\tRwRaster* p_context_raster;\r\n\t\tp_context_raster = gfx_manager->DefaultViewport().GetFrameBuffer();\r\n\r\n\t\tRwInt32 format = p_context_raster->cFormat & 0x0000FF00L;\r\n\t\tRwRGBA black = { 0, 0, 0, 0 }; \r\n\r\n\t\tRwRasterPushContext( p_context_raster );\r\n\t\t\r\n\t\tRwRasterClear( RwRGBAToPixel( &black, format ));\t\t// 0: Clear to black\r\n\t\tRwRasterShowRaster( p_context_raster, NULL, 0 );\r\n\r\n\t\tRwRasterClear( RwRGBAToPixel( &black, format ));        // 1: Clear to black \r\n\t\tRwRasterShowRaster( p_context_raster, NULL, 0 );\r\n\r\n\t\tRwRasterRenderScaled( raster, &rect );\t\t\t        // 2: Draw image\r\n\t\tRwRasterShowRaster( p_context_raster, NULL, 0 );\r\n\r\n\t\tRwRasterRenderScaled( raster, &rect );                  // 3: Draw image\r\n\t\tRwRasterShowRaster( p_context_raster, NULL, 0 );\r\n\t\tRwRasterPopContext();\r\n\r\n\t\tRwRasterDestroy( raster );\r\n\r\n\t\t// Set up the timer event last so that the icon will only ever appear once the loadscreen is visible.\r\n\t\tif( s_timer_event == 0 )\r\n\t\t{\r\n\t\t\ts_timer_event = timeSetEvent(\t( 1000 * s_load_icon_data.m_FrameDelay ) / 60,\t// Delay (ms).\r\n\t\t\t\t\t\t\t\t\t\t\t0,\t\t\t\t\t\t\t\t\t\t\t\t// Ignored resolution (ms).\r\n\t\t\t\t\t\t\t\t\t\t\tloadIconTimerCallback,\t\t\t\t\t\t\t// Callback function.\r\n\t\t\t\t\t\t\t\t\t\t\t0,\t\t\t\t\t\t\t\t\t\t\t\t// Callback data.\r\n\t\t\t\t\t\t\t\t\t\t\tTIME_PERIODIC | TIME_CALLBACK_FUNCTION );\r\n\r\n\r\n\t\t\tDbg_Assert( s_timer_event != 0 );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (just_freeze)\r\n\t\t{\r\n\t\t\tScript::RunScript( \"PreFreezeScreen\" );\r\n//\t\t\tif( skyFrameBit & 0x1 )\r\n//\t\t\t{\r\n//\t\t\t\tcopy_buffer( 1 );\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\tcopy_buffer( 0 );\r\n//\t\t\t}\r\n\r\n\t\t\tScript::RunScript( \"PostFreezeScreen\" );\r\n\t\t}\r\n\t\telse if( blank )\r\n\t\t{\r\n\t\t\tRwRect rect;\r\n\t\t\trect.x = SCREEN_CONV_X( 0 );\r\n\t\t\trect.y = SCREEN_CONV_Y( 0 );\r\n\t\t\trect.w = SCREEN_CONV_X( 640 ) - SCREEN_CONV_X( 0 );\r\n\t\t\trect.h = SCREEN_CONV_Y( 448 ) - SCREEN_CONV_Y( 0 );\r\n\r\n\t\t\tSpt::SingletonPtr< Gfx::Manager > gfx_manager;\r\n\r\n\t\t\t_rwXbSetRenderState( rwRENDERSTATETEXTURERASTER, (void *)NULL );\r\n\r\n\t\t\tRwRaster* p_context_raster;\r\n\t\t\tp_context_raster = gfx_manager->DefaultViewport().GetFrameBuffer();\r\n\r\n\t\t\tRwInt32 format = p_context_raster->cFormat & 0x0000FF00L;\r\n\t\t\tRwRGBA black = { 0, 0, 0, 0 }; \r\n\r\n\t\t\tRwRasterPushContext( p_context_raster );\r\n\r\n\t\t\tRwRasterClear( RwRGBAToPixel( &black, format ));\t\t// 0: Clear to black\r\n\t\t\tRwRasterShowRaster( p_context_raster, NULL, 0 );\r\n\r\n\t\t\tRwRasterClear( RwRGBAToPixel( &black, format ));        // 1: Clear to black \r\n\t\t\tRwRasterShowRaster( p_context_raster, NULL, 0 );\r\n\r\n\t\t\tRwRasterPopContext();\r\n\t\t}\r\n\t}\r\n\r\n#\tendif\r\n\t\r\n\tSpt::SingletonPtr< Mlp::Manager > mlp_man;\r\n\ts_loading_screen_on = true;\r\n\tmlp_man->PauseDisplayTasks( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Hide( void )\r\n{\r\n\tif( s_timer_event != 0 )\r\n\t{\r\n\t\ttimeKillEvent( s_timer_event );\r\n\t\ts_timer_event = 0;\r\n\t}\r\n\r\n\tSpt::SingletonPtr< Mlp::Manager > mlp_man;\r\n\tmlp_man->PauseDisplayTasks( false ); \r\n\r\n\tif( !s_loading_screen_on )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\ts_loading_screen_on = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStartProgressBar( char* tick_image, int num_ticks, int x, int y )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tProgressTick( int num_ticks )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tEndProgressBar( void )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace LoadScreen\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_memview.cpp",
    "content": "//////////////////////////////////////////////////////\r\n// p_memview.cpp\r\n//\r\n// code for tracking memory usage, and displaying it in a graphical manner\r\n// keeps extra info about allocated blocks\r\n// including the call stack, so we can print out information\r\n// about specific allocated blocks\r\n// which we will select using the graphical memory browser\r\n//\r\n//\r\n// tried to use a little of the task system as possible\r\n// so we can run the inspector\r\n// without it messing with the heap it inspects\r\n//\r\n//\r\n\r\n\r\n//extern char _mem_dump_start[];\r\n//extern char _map_file_start[];\r\n//extern char _symbols_start[];\r\n//extern char _callstack_start[];\r\n//extern char _code_end[];\r\n//extern char\t_std_mem_end[];\r\n//extern char\t_stack_size[];\r\n\r\n//extern char __text_org[];\r\n//extern char __data_org[];\r\n//extern char __rodata_org[];\r\n//extern char __bss_org[];\r\n\r\n//extern char __rodata_orgend[];\r\n//extern char __bss_objend[];\r\n//extern char __text_objend[];\r\n\r\n//extern char _rwheapdebug_start[];\r\n\r\n\t\t\t \r\n#define\tSTACKDEPTH  30\t\t\t \r\n\r\n\r\n\t\t\t \r\nextern \"C\"\t\t\t\t \r\n{\r\nextern void* ENTRYPOINT;\t\t\r\n}\r\n\r\n#include <gfx/gfxman.h>\r\n#include <gfx/nxviewport.h>\r\n#include <gel/inpman.h>\t\t\t\t\t// needed for buttons\r\n#include <gfx/xbox/p_memview.h>\r\n#include <sys/file/filesys.h> \t\t\t// needed for loading map file\r\n#include <gel/scripting/script.h>\r\n\r\n#include <stdio.h>\r\n#include <string.h>\r\n\r\n#include <sys\\mem\\memman.h>\r\n#include <sys\\mem\\heap.h>\r\n#include <sys\\mem\\region.h>\r\n#include <sys/config/config.h>\r\n\r\n// needed for some VerticalMenu specific debugging\t\t\t\t\t\t\t\r\n#include <core/support.h>\r\n#include <core/list.h>\r\n#include <core/String/CString.h>\r\n\r\n\r\nextern volatile int\ttest_vblanks;\r\n\r\n\r\nclass CCallStack\r\n{\r\npublic:\r\n\tvoid Append(CCallStack *p);\r\n\tvoid Remove();\r\n\tvoid InitHead();\r\n\tint\tused;\r\n\tint\tsize;\r\n\tCCallStack *pNext;\r\n\tCCallStack *pPrev;\r\n\tint\taddr[STACKDEPTH];\r\n\tuint32\tflags;\r\n\tMem::Allocator::BlockHeader * pBlock;\t// pointer to block that has this callstack\r\n\r\n};\r\n\r\nCCallStack\t\tfree_list;\t// list of created objects\r\nCCallStack\t\tused_list;\t// list of created objects\r\n\r\n// init a node, so it can act as the head\t\t\t \r\ninline void CCallStack::InitHead()\r\n{\r\n\tpPrev = this;\r\n\tpNext = this;\r\n}\r\n\t\r\n// append node p to this node (after it)\t\t\t\t\t\t\t\t\t \r\ninline void CCallStack::Append(CCallStack *p)\r\n{\r\n\r\n\tp->pNext = this->pNext;\r\n\tp->pPrev = this;\r\n\tthis->pNext = p;\r\n\tp->pNext->pPrev = p;\r\n}\r\n\r\n// simply unlink it from the list\t\t\t   \r\ninline void CCallStack::Remove()\r\n{\r\n\tpPrev->pNext = pNext;\r\n\tpNext->pPrev = pPrev;\r\n}\r\n\r\n\r\n\t\t\t\t\t\t\r\n//CCallStack * CallStack_FirstFree;\r\n//CCallStack * CallStack_FirstUsed; \r\n\r\nstatic int MemView_Active = 0;\r\n\r\n\r\n\r\n#define\tMAX_CALLSTACK (8192 * 8)\t\t// we got 8 mb, woo woo.\r\n\r\n\r\nstatic float step = 128.0f;\r\n\r\n\r\nstatic char HexByte(char a)\r\n{\r\n\tif (a >= '0' && a <='9')\r\n\t{\r\n\t\treturn a-'0';\r\n\t}\r\n\tif (a >= 'A' && a <='F')\r\n\t{\r\n\t\treturn 10 + a-'A';\r\n\t}\r\n\tif (a >= 'a' && a <='f')\r\n\t{\r\n\t\treturn 10 + a-'a';\r\n\t}\r\n\r\n\t// should really be an error, but just ignore it and return 0\r\n\t// as this is only used for parsing the map file\t\r\n\treturn 0;\r\n\t\r\n\t\r\n}\r\n\r\n\r\nstatic int doneonce = 0;\r\n\r\n\r\nchar *MemView_GetFunctionName(int pc, int *p_size)\r\n{\r\n\treturn \"UNKNOWN\";\r\n\t\r\n}\r\n\r\n// Modifed version of Jamie's unwind stack function\r\n// ignores the fp, and just goes directly off the sp\r\n// seems to work much better (and faster too)\r\nint DumpUnwindStack( int iMaxDepth, int *pDest )\r\n{\r\n\treturn 0;\r\n}\r\n\t\t\t\t   \r\n\t\t\t\t   \r\n//        mD_L2           = nBit( vD_L2 ),\r\n//        mD_R2           = nBit( vD_R2 ),\r\n//        mD_L1           = nBit( vD_L1 ),\r\n//        mD_R1           = nBit( vD_R1 ),\r\n//        mD_TRIANGLE     = nBit( vD_TRIANGLE ),\r\n//\t      mD_CIRCLE       = nBit( vD_CIRCLE ),\r\n//        mD_X            = nBit( vD_X ),\r\n//        mD_SQUARE       = nBit( vD_SQUARE ),\r\n//        mD_SELECT       = nBit( vD_SELECT ),\r\n//        mD_L3           = nBit( vD_L3 ),\r\n//        mD_R3           = nBit( vD_R3 ),\r\n//        mD_START        = nBit( vD_START ),\r\n//        mD_UP           = nBit( vD_UP ),\r\n//        mD_RIGHT        = nBit( vD_RIGHT ),\r\n//        mD_DOWN         = nBit( vD_DOWN ),\r\n//        mD_LEFT         = nBit( vD_LEFT ),\r\n\r\n\r\nvoid MemViewToggle()\r\n{\r\n\tMemView_Active ^=1;\r\n}\r\n\r\n\r\n\t \r\n\r\nvoid MemView_Alloc( void *v)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\r\n\r\n#ifdef\t__NOPT_CDROM__OLD\r\n   return;\r\n#endif \t\r\n\r\n#endif\r\n}\r\n\r\nvoid MemView_Free( void *v)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n#endif\t\r\n}\r\n\r\n\r\nMem::Allocator::BlockHeader *MemView_FindBlock( int addr)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\r\n\t\r\n\tMem::Allocator::BlockHeader *pSmallestBlock\t= NULL;\r\n\tuint32 smallest_block_size = 100000000;\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\tfor (Mem::Heap* heap = mem_man.FirstHeap(); heap != NULL; heap = mem_man.NextHeap(heap))\r\n\t{\r\n\t\tMem::Allocator::BlockHeader *pBlock = (Mem::Allocator::BlockHeader *) heap->find_block((void*)addr);\t\r\n\t\tif (pBlock)\r\n\t\t{\r\n\t\t\tif (pBlock->mSize < smallest_block_size)\r\n\t\t\t{\r\n\t\t\t\tsmallest_block_size = pBlock->mSize;\r\n\t\t\t\tpSmallestBlock = pBlock;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn pSmallestBlock;\r\n#else\r\n\treturn NULL;\r\n#endif\r\n}\r\n\r\nchar * MemView_GetClassName(CCallStack *c)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\tint *ra = (int*)(c->addr[4]);\r\n\tint count = STACKDEPTH-4;\r\n\twhile (count--)\r\n\t{\r\n\t\tint instruction = *ra++;\r\n\t\tif (instruction >> 24 == 0x0c)\r\n\t\t{\r\n\t\t\tint code = (instruction & 0xffffff)<<2;\r\n\t\t\tint size;\r\n\t\t\tchar *p = MemView_GetFunctionName(code,&size); \r\n\t\t\t// to tell if this is class or not\r\n\t\t\t// we see if the text is of the form  \r\n\t\t\t//    classname::classname (teminated by a 0)\r\n\t\t\t// as that indicates that it is a constructor\r\n\t\t\t// dude... this is where we need a regular expression....\r\n\t\t\tchar *end = p;\r\n\t\t\twhile (*end) end++;\t   \t\t\t\t\t\t// scan to end\r\n\t\t\twhile (end[-1] != ':' && end > p)\tend--;\t// skip to char after the last :\r\n\t\t\tchar *other = strstr(p,end);\t\t\t\t// find fist occurance of end of string\r\n\t\t\tif (other != end)\t\t\t\t\t\t\t// if different, then this is it!!\r\n\t\t\t{\r\n\t\t\t\treturn MemView_GetFunctionName(code,&size);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\r\n\treturn NULL;\r\n}\r\n\r\n\r\nvoid MemView_DumpBlockInfo(int cursor)\r\n{\r\n#\tifdef\t__LINKED_LIST_HEAP__\r\n\t\r\n\tchar os[256];\r\n\t\r\n\tMem::Allocator::BlockHeader *pBlock = MemView_FindBlock( cursor );\r\n\tif( !pBlock )\r\n\t{\r\n\t\t// should search free blocks here???\r\n\t}\r\n\r\n\t// find this in the allocators used list\r\n\t// and say if it is free, or not\t\r\n\tif( pBlock == NULL )\r\n\t{\r\n/*\t\tif (cursor > (int)__text_org && cursor < (int)__bss_objend)\t\t// check to see if in code/data\r\n\t\t{\r\n\t\t\t\r\n\t\t\tif (cursor < (int)__data_org)\r\n\t\t\t\tprintf(\"Code: \");\r\n\t\t\telse if (cursor < (int)__rodata_org)\r\n\t\t\t\tprintf(\"Data: \");\r\n\t\t\telse if (cursor < (int)__bss_org)\r\n\t\t\t\tprintf(\"RO-Data: \");\r\n\t\t\telse \r\n\t\t\t\tprintf(\"BSS: \");\r\n\t\t\t\r\n\t\t\r\n\t\t\tint size;\r\n\t\t\tchar *p_name = MemView_GetFunctionName(cursor,&size);\r\n\t\t\tprintf ( \"%s, size %d\\n\",p_name,size);\r\n\t\t}\r\n\t\telse\r\n*/\r\n\t\t{\r\n\t\t\tOutputDebugString( \"Block Not Found\\n\" );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tvoid * p_start = (void*)((uint)pBlock + Mem::Allocator::BlockHeader::sSize);\r\n\t\tsprintf( os, \"Block found, addr = %p, size = %d (Header = %d)\\n\",p_start,pBlock->mSize,Mem::Allocator::BlockHeader::sSize);\r\n\t\tOutputDebugString( os );\r\n\r\n\t\tCCallStack *c = (CCallStack*)pBlock->mp_debug_data;\r\n\t\tif (!c)\r\n\t\t{\r\n//\t\t\tOutputDebugString( \"Block with No Debug Info!!\\n\" );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// assume this is a \"new\", then the fourth callstack ra will point to the \r\n\t\t\t// jal xxxxxx  instruction, where xxxxx is the constructor for the \r\n\t\t\t// or it might be sortly thereafter, so check 16 instructions\r\n\t\t\tchar *classname = MemView_GetClassName( c );\r\n\t\t\tif( classname )\r\n\t\t\t{\r\n\t\t\t\tsprintf( os, \"CLASS: %s\\n\", classname );\r\n\t\t\t\tOutputDebugString( os );\r\n\t\t\t}\r\n\r\n\t\t\t// then list out the call stack (skipping the MemView_Alloc, as that's a given, and irrelevant);\t\t\t\r\n\t\t\r\n\t\t\tint *p = c->addr + 1;\r\n\t\t\twhile (p[1])\t\t\t// also skip the ENTRYPOINT, just go back to main()\r\n\t\t\t{\r\n\t\t\t\tint size;\r\n\t\t\t\tsprintf( os, \"%p: %s\\n\", (void*)*p,MemView_GetFunctionName(*p,&size));\r\n\t\t\t\tOutputDebugString( os );\r\n\t\t\t\tp++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\nstatic\tint\tblockstart;\r\n\r\nstatic float cursor;\r\n\r\nvoid \t\tMemView_Display()\r\n{\r\n#\tifdef\t__NOPT_CDROM__OLD\r\n\treturn;\r\n#\tendif \t\r\n}\r\n\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\r\nstatic int num_used;\r\n\r\nstatic void ScanRegion(uint32 *p_start, uint32 *p_end)\r\n{\r\n#if 0\r\n\tprintf (\"scanning from %p to %p\\n\",p_start,p_end);\r\n\t// scan the whole range of memeory\r\n\twhile (p_start<p_end)\r\n\t{\r\n\t\t// get value that might be a pointer\r\n\t\tuint32 x = *p_start++;\r\n\t\t// check to see if it's not odd, and it lays in the heap area\r\n\t\tif (!(x&3) && x > (uint32)_code_end /*&& x < (uint32)_std_mem_end*/) // don't check for end now, as we have some debug heaps up there we want to include\r\n\t\t{\r\n\t\t\t// check to see if it points to one of the heap members\r\n\t\t\t\r\n\t\t\tuint32 *p_refs = (uint32*)_mem_dump_start;\r\n\t\t\t\r\n\t\t#if 0\r\n\t\t\tfor (int i=0;i<num_used;i++)\r\n\t\t\t{\r\n\t\t\t\tif (*p_refs == x)\t  \t\r\n\t\t\t\t{\r\n\t\t\t\t\t// got it, increment the reference counter\r\n\t\t\t\t\tp_refs[1]++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tp_refs+=2;\r\n\t\t\t} \r\n\t\t\t\r\n\t\t#else\r\n\t\t\r\n\t\t\t// we want to do it twice, once for x, and once for x+16\r\n\t\t\t// the reason being, a class this is allocated with\r\n\t\t\t// the [] operator will actually start 16 bytes before the ref\r\n\t\t\t// so we need to go back 16 bytes when looking for the block\r\n\r\n\t\t\tint oldx = x;\r\n\t\t\tfor (int i=0;i<2;i++)\r\n\t\t\t{\r\n\t\t\t\r\n\t\t\t\t// binary search folks.....\r\n\t\t\t\tint low = 0;\r\n\t\t\t\tint high = num_used-1;\r\n\t\t\t\twhile (1)\r\n\t\t\t\t{\r\n\t\t\t\t\tint mid = (low + high) /2;\r\n\t\t\t\t\tif (p_refs[mid<<1] == x)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_refs[(mid<<1)+1] ++;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (high == low)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (p_refs[mid<<1] > x)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\thigh = mid;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// if the low point is already the same as the mid point\r\n\t\t\t\t\t\t// then the only way to go is up!\r\n\t\t\t\t\t\t// as this will only occur when low + 1 == high\r\n\t\t\t\t\t\tif (low == mid)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tlow = high;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tlow = mid;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tx -= 16;\r\n\t\t\t}\r\n\t\t\tx = oldx;\r\n\t\t#endif\t\t\t\t\t\t  \t\t\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n#endif\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__\r\nstatic uint32 *p_used;\t\t\r\n#endif\r\n\r\nint MemView_CountBlocks(Mem::Allocator::BlockHeader *p_header)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\tint num_used = 0;\r\n\twhile ( p_header )\r\n\t{\r\n\t\tvoid * p_start = (void*)((uint)p_header + Mem::Allocator::BlockHeader::sSize);\r\n\t\t\r\n\t\t*p_used++ = (uint32)p_start;\t \t\t// store the start of the block\r\n\t\t*p_used++ = 0;\t\t\t\t\t\t\t// store a count\r\n\t\tp_header = p_header->mp_next_used;\r\n\t\tnum_used++;\r\n\t}\r\n\treturn num_used;\r\n#else\r\n\treturn 0;\r\n#endif\r\n}\r\n\r\n// Find memory leaks\r\n// the algorithm is quite simple:\r\n// 1) Make a list of all \"used\" memory blocks, and set their usage count to 0\r\n// 2) Scan all of the heap, and the stack, for each word that looks like a pointer, \r\n//    check to see if it is in the list of \"used\", and increment the usage count if so\r\n// 3) Scan the list of used pointers, and check for any with usage == 0\r\n\r\n// NEED OT EXTEND FOR TOP_DOWN heap.....\t\t\r\n\t\t\r\nvoid MemView_FindLeaks()\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n#if 0\r\n\t\tp_used  =  (uint32*)_mem_dump_start;\t\t\r\n\t\tnum_used = 0;\r\n\t\tprintf (\"Counting blocks....\");\t\t\r\n\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().BottomUpHeap()->first_block()); \r\n\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().TopDownHeap()->first_block()); \r\n\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().FrontEndHeap()->first_block()); \r\n\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().NetworkHeap()->first_block()); \r\n\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().ScriptHeap()->first_block()); \r\n\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().SkaterHeap(0)->first_block()); \r\n//\t\tnum_used += MemView_CountBlocks(Mem::Manager::sHandle().DebugHeap()->first_block()); \r\n\t\tprintf (\" %d\\n\",num_used);\r\n\t\tprintf (\"Sorting .....\\n\");\t\t\t\r\n\t\t// Now we've done that, let's sort the list, so we can use a binary search later\r\n\t\tuint32 *p_top  =  (uint32*)_mem_dump_start;\t\t\r\n\t\tfor\t(int i = 0;i<num_used-1;i++)\r\n\t\t{\r\n\t\t\tuint32 top = *p_top;\r\n\t\t\tuint32 *p_scan  =  p_top+2;\t  \r\n\t\t\tuint32 *p_best = p_top;  \t\t\t\r\n\t\t\tfor (int j = i;j<num_used-1;j++)\r\n\t\t\t{\r\n\t\t\t\tuint32 scan = *p_scan;\r\n\t\t\t\tif (scan < top)\r\n\t\t\t\t{\r\n\t\t\t\t\ttop = scan;\r\n\t\t\t\t\tp_best = p_scan;\r\n\t\t\t\t}\r\n\t\t\t\tp_scan+=2;\r\n\t\t\t}\r\n\t\t\tuint64 t = *(uint64*)p_top;\r\n\t\t\t*(uint64*)p_top = *(uint64*)p_best;\r\n\t\t\t*(uint64*)p_best = t;\t\t\r\n\t\t\tp_top +=2;\r\n\t\t}\r\n\r\n\r\n\r\n\t\t// now scan all appropiate regions of memory\r\n\t\t\r\n\t\t// First scan the code, data and regular heap\r\n\t\tScanRegion((uint32*)_code_end,(uint32*)_std_mem_end);\r\n\r\n\t\t// Next scan the alternate area or memory, where the script heap goes\r\n\t\tScanRegion((uint32*)(_rwheapdebug_start),(uint32*)(_rwheapdebug_start + 0x04970000 - 0x04500000));\r\n\r\n\t\t// then scan the stack\r\n//\t\tuint64* sp;\t\t\t\t\t\t\t\t\t\t\t// frame pointer\r\n//\t\tasm ( \"daddu %0, $29, $0\" : \"=r\" (sp) );\t\t\t// get current sp\r\n//\t\tuint32 *stack_start = (uint32*)sp;\r\n//\t\t// stack end is stack start rounded up by the stack size\r\n//\t\t// assumes that things are nice powers of 2\r\n//\t\tuint32 *stack_end = (uint32*)(((int)(stack_start) + (int)_stack_size-4) & ~(int)(_stack_size-1));\r\n//\t\tScanRegion(stack_start,stack_end);\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\t\tbool\tLeaksFound = false;\r\n\r\n\t\t// then check for any with zero reference\r\n\t\tuint32 *p_refs = (uint32*)_mem_dump_start;\r\n\t\tfor (int i=0;i<num_used;i++)\r\n\t\t{\r\n\t\t\tif (!p_refs[1])\t  \t\r\n\t\t\t{\r\n\t\t\t\tuint32 addr = *p_refs;\r\n\t\t\t\tif (!LeaksFound)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf (\"-----------------------------------------------------------------------\\n\");\r\n\t\t\t\t\tprintf (\"-----------  LEAKS FOUND !!!!!!!!!!!!!!           ---------------------\\n\");\r\n\t\t\t\t\tprintf (\"-----------------------------------------------------------------------\\n\");\r\n\t\t\t\t\tLeaksFound = true;\r\n\t\t\t\t}\r\n\t\t\t\tprintf (\"\\nPossible leak, addr %p\\n\",(void*)addr);\t\t\t\t\r\n\t\t\t\tMemView_DumpBlockInfo(addr);\r\n\t\t\t}\r\n\t\t\tp_refs+=2;\r\n\t\t}\t\t\t\r\n\t\t\r\n\t\tif (LeaksFound)\r\n\t\t{\r\n\t\t\tprintf (\"-----------------------------------------------------------------------\\n\");\r\n\t\t\tprintf (\"-----------  END OF LEAKS                         ---------------------\\n\");\r\n\t\t\tprintf (\"-----------------------------------------------------------------------\\n\");\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tprintf (\"-----------  NO LEAKS DETECTED!!!  ---------------------\\n\");\r\n\t\t}\r\n#endif\r\n#endif\r\n}\r\n\r\n\r\n// Given a block addr, then search all the other blocks to see \r\n// which block contains a reference to this block\r\n// and recursivly step back through the blocks until\r\n// we can't find another reference, or the address is not in a block\r\nvoid MemView_DumpRefs(int addr)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n#if 0\r\n\tprintf (\"\\n\\nDumping references for %p\\n\",(void*)addr);\r\n\tMemView_DumpBlockInfo(addr);\r\n\tuint32 *p_first = NULL;\t\r\n\tint last_addr = 0;\r\n\tint count = 0 ;\r\n\twhile (1)\r\n\t{\r\n\t\t// now just do a simple search through the heap reagion\r\n\t\t// to find another reference\r\n\t\tuint32 *p_start = (uint32*)_code_end;\r\n\t\tuint32 *p_end = (uint32*)_std_mem_end;\r\n\t\twhile (p_start<p_end && count < 10)\r\n\t\t{\r\n\t\t\tif (*p_start == (uint32)addr && p_start != (uint32*)&blockstart)\r\n\t\t\t{\r\n\t\t\t\tcount++;\r\n\t\t\t\tprintf (\"\\nReference level %d in %p\\n\",count,(void*)p_start);\r\n\t\t\t\tMemView_DumpBlockInfo((int)p_start);\r\n\t\t\t\taddr = (int)p_start;\r\n\r\n\r\n\t\t\t\tMem::Allocator::BlockHeader *pBlock = MemView_FindBlock(addr);\t\t\t\t\r\n\t\t\t\taddr = (int)((uint)pBlock + Mem::Allocator::BlockHeader::sSize);\r\n\t\t\t\tif (addr == (int) p_first || addr == last_addr)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf (\"LOOPING .....\\n\");\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tlast_addr = addr;\r\n\t\t\t\tif (!p_first)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_first = (uint32*)addr;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\tp_start++;\r\n\t\t}\r\n\t\tif (count >= 10)\r\n\t\t{\r\n\t\t\tprintf (\"Stopping after %d refs\\n\",count);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (p_start >= p_end)\r\n\t\t{\r\n\t\t\tprintf (\"No more References Found in heap \\n\");\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n#endif\r\n#endif\r\n}\r\n\r\n// Find the first block in the free list\r\n// if no free blocks, then return\r\n// scan all used blocks, and print out the info for all the blocks\r\n// that have an address above the first free block\r\nvoid MemView_DumpFragments(Mem::Heap *pHeap)\r\n{\r\n#\tifdef __LINKED_LIST_HEAP__ \r\n\r\n\tchar os[256];\r\n\r\n\tif (!pHeap->mFreeBlocks.m_count)\r\n\t{\r\n\t\tOutputDebugString( \"NO Fragmentation\\n\" );\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif( !pHeap->mp_context->mp_free_list )\r\n\t{\r\n\t\tsprintf( os, \"!!!!!! No free list, but there are %d free blocks???\\n\",pHeap->mFreeBlocks.m_count);\r\n\t\tOutputDebugString( os );\r\n\t\treturn;\r\n\t}\r\n\r\n\tMem::Allocator::BlockHeader *p_free = pHeap->mp_context->mp_free_list;\r\n\tMem::Allocator::BlockHeader *p_full = pHeap->mp_context->mp_used_list;\r\n\t\r\n\tsprintf( os, \"!!!!!! Free list starts at %p\\n\",p_free );\r\n\tOutputDebugString( os );\r\n\r\n\t// The first p_free will be the start of fragmentations\r\n\twhile (p_full)\r\n\t{\r\n\t\tif (p_full > p_free)\r\n\t\t{\r\n\t\t\tOutputDebugString( \"Framgented Block: \" );\r\n\t\t\tvoid * p_start = (void*)((uint)p_full + Mem::Allocator::BlockHeader::sSize);\r\n\t\t\tMemView_DumpBlockInfo((int)p_start);\r\n\t\t}\r\n\t\tp_full = p_full->mp_next_used;\r\n\t}\r\n\t#endif\r\n}\r\n\r\nvoid MemView_DumpHeap( Mem::Heap *pHeap )\r\n{\r\n\t#ifdef\t__LINKED_LIST_HEAP__    \r\n\tMem::Allocator::BlockHeader *p_full = pHeap->mp_context->mp_used_list;\r\n\t\r\n\t// The first p_free will be the start of fragmentations\r\n\twhile( p_full )\r\n\t{\r\n\t\tprintf (\"\\n\");\r\n\t\tvoid * p_start = (void*)((uint)p_full + Mem::Allocator::BlockHeader::sSize);\r\n\t\tMemView_DumpBlockInfo((int)p_start);\r\n\t\tp_full = p_full->mp_next_used;\r\n\t}\r\n\t#endif\r\n}\r\n\r\n\r\n\r\nvoid MemView_DumpBottomFragments()\r\n{\r\n\r\n\tMemView_DumpFragments(Mem::Manager::sHandle().BottomUpHeap());\r\n}\r\n\r\nvoid MemView_DumpTopFragments()\r\n{\r\n\r\n\tMemView_DumpFragments(Mem::Manager::sHandle().TopDownHeap());\r\n}\r\n\r\n\r\n\r\n/*\r\nclass CCallStack\r\n{\r\npublic:\r\n\tvoid Append(CCallStack *p);\r\n\tvoid Remove();\r\n\tvoid InitHead();\r\n\tint\tused;\r\n\tint\tsize;\r\n\tCCallStack *pNext;\r\n\tCCallStack *pPrev;\r\n\tint\taddr[STACKDEPTH];\r\n\r\n};\r\n*/\r\n\r\nstruct SBlockType\r\n{\r\n\tint\treturn_addr; \t\t\t// first meaningful return addr \r\n\t\r\n\tint\tsize;\t\t\t\t\t// size of block (if we want to sort by it\r\n\tint\ttotal;\t\t\t\t\t// total size of this type\r\n\tint\tactual;\t\t\t\t\t// actual total size, including headers\r\n\tchar *p_class;\t\t\t\t// points to class node \r\n\t\r\n\tint\tcount;\r\n};\r\n\r\n// scan throught the list of \"used\" blocks\r\n// and sort them into a list, organized by \"type\"\r\n// the \"type\" is determined by the first return address after\r\n// a callstack entry that is either \"Malloc\" or \"Spt::Class::operator new\"\r\n// the \"type\" is furthur sorted by either \"size\" or \"Class\"\r\n// where \"size\" is the size of the block (for a Malloc)\r\n// and \"Class\" is the type of class that constructed this block \r\n\r\n#define\tMAX_TYPES 10000\r\n\r\n\r\nvoid MemView_DumpAnalysis( SBlockType* blocks, int numBlocksToPrint )\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\t// Sorts the types, and print out totals\r\n\r\n\tint temp;\r\n\r\n\tfor (int i = 0; i < numBlocksToPrint; i++)\r\n\t{\r\n\t\tfor (int j = i+1;j<numBlocksToPrint;j++)\r\n\t\t{\r\n\t\t\tbool swap = false;\r\n\t\t\tif (blocks[i].actual < blocks[j].actual)\r\n\t\t\t{\r\n\t\t\t\tswap = true;\r\n\t\t\t}\r\n\r\n\t\t\tif (swap)\r\n\t\t\t{\r\n\t\t\t\tSBlockType t = blocks[i];\r\n\t\t\t\tblocks[i] = blocks[j];\r\n\t\t\t\tblocks[j] = t;\t\t\t\t\r\n\t\t\t}\t\t\t\r\n\t\t}\r\n\r\n\t\t// i is sorted, so print it out\r\n\t\tprintf (\"%7d bytes, (%6d hdrs) %4d blks, avg %6d bytes, class %s, function %s\\n\", \t\t\r\n\t\t\t\tblocks[i].actual,\r\n\t\t\t\tblocks[i].actual-blocks[i].total,\r\n\t\t\t\tblocks[i].count,\t\t\t\t \r\n\t\t\t\tblocks[i].total/blocks[i].count,\r\n\t\t\t\tblocks[i].p_class,\r\n\t\t\t\tMemView_GetFunctionName(blocks[i].return_addr,&temp)\r\n\t\t\t   );\t   \r\n\t\tfor (int xx=0;xx<2000000;xx++);\t\t// little delay, to allow printfs to work\r\n\t}\r\n#endif\r\n}\r\n\r\nvoid MemView_AnalyzeCallStack( CCallStack* pCallStack, SBlockType* pBlocks, int& num )\r\n{\r\n\t// for each block we find the three things:\r\n\t//  return_addr after Malloc or Spt::Class::operator new\r\n\t//  size\r\n\t//  class\r\n\r\n\tint\tsize = pCallStack->size;\t  \t// size is the only thing we know for sure\r\n\tint\treturn_addr = 0;\t\t\t\t// default unknown return address\r\n\tchar *p_class = \"not a class\";\r\n\tint latest = 1;\r\n\tint i = 0;\r\n\t\r\n\tfor ( i = 1; i < 8; i++ )\r\n\t{\r\n\t\tint xsize;\r\n\r\n\t\t/*\r\n\t\t// the types of call stack we may encounter:\r\n\t\t// need to \r\n\t\t\t0x10be48: Mem::Heap::allocate                                                   \r\n\t\t\t0x109914: Mem::Manager::New                                                     \r\n\t\t\t0x1035b0: Spt::Class::operator new                                              \r\n\t\t\t0x161094: Front::KeyboardControl::sCreateInstance   \r\n\r\n\t\t\t0x10be48: Mem::Heap::allocate                                                   \r\n\t\t\t0x109914: Mem::Manager::New                                                     \r\n\t\t\t0x10a150: Malloc                                                                \r\n\t\t\t0x222df8: _SkyBuildPktForUpLoadAlignedContiguousRectangle  \r\n\r\n\t\t\t0x10be48: Mem::Heap::allocate                                                   \r\n\t\t\t0x109914: Mem::Manager::New                                                     \r\n\t\t\t0x10a210: Malloc_FreeList                                                       \r\n\t\t\t0x257034: _rwFreeListAllocReal\r\n\t\t*/\r\n\r\n\t\tchar *p_name = MemView_GetFunctionName(pCallStack->addr[i],&xsize);\r\n\t\tif (!strcmp(\"Malloc\",p_name) \r\n\t\t\t|| !strcmp(\"Spt::Class::operator new\",p_name)\r\n\t\t\t|| !strcmp(\"Mem::Manager::New\",p_name)\r\n\t\t\t|| !strcmp(\"_rwFreeListAllocReal\",p_name))\r\n\t\t{\r\n\t\t\tlatest = i;\r\n\t\t}\r\n\t}\r\n\r\n\tif (latest != 1)\r\n\t{\r\n\t\treturn_addr = pCallStack->addr[latest+1];\r\n\t}\r\n\r\n\tp_class = MemView_GetClassName(pCallStack);\t\t\t\t// get class\r\n\t// right, now we have all the info on this block\r\n\t// let's see if we've got one just like it\r\n\r\n\t//\t\tif (!p_class && !MemView_GetFunctionName(return_addr,&temp))\r\n\t/*\t\t\r\n\t\t\tif (!return_addr)\r\n\t\t\t{\r\n\t\t\t\tfor (int i = 0;i<STACKDEPTH;i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf (\"%2d: >>%s<<\\n\",i,MemView_GetFunctionName(p->addr[i],&temp));\r\n\r\n\t\t\t\t}\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\t*/\r\n\t\r\n\t\t\t\t\t\t\t\t\t  \r\n\t// check if it is a string, and print it out, if so\t\t\t\t\t\r\n/*\t\r\n\tint temp;\t\t\t\t  \r\n\tif (!strcmp(\"Str::String::copy\",MemView_GetFunctionName(return_addr,&temp)))\r\n\t{\r\n\t\tprintf (\"String <%s>\\n\",(char*)((char*)(pCallStack->pBlock)+32)); \r\n\t}\r\n\t\r\n\t\r\n\tif (!strcmp(\"Front::VerticalMenu::sCreateInstance\",MemView_GetFunctionName(return_addr,&temp)))\r\n\t{\r\n\t\tvoid *p_start  =  (void*)((char*)(pCallStack->pBlock)+32);\r\n\t\tprintf (\"\\nVertical Menu \"); \r\n\t\t\r\n\t\tFront::ScreenElement *pV =  (Front::ScreenElement *)p_start;\r\n\t\tprintf (\" id = %s\\n\", Script::FindChecksumName(pV->GetID()));\r\n//\t\tMemView_DumpBlockInfo((int)p_start);\r\n\t\t\r\n\t}\t\r\n*/\t\r\n\r\n\t// check to see if this block is already included\r\n\tfor ( i = 0; i < num; i++ )\r\n\t{\r\n\t\tif ( pBlocks[i].p_class == p_class\r\n\t\t\t/*&& pBlocks[i].size == size */\r\n\t\t\t && pBlocks[i].return_addr == return_addr )\r\n\t\t{\r\n\t\t\tpBlocks[i].count++;\r\n\t\t\tpBlocks[i].total += size;\r\n\t\t\tpBlocks[i].actual += size + Mem::Allocator::BlockHeader::sSize;\r\n\t\t\tbreak;\t\t\t\t\r\n\t\t}\r\n\t}\r\n\r\n\t// if not, then add the block\r\n\tif ( i == num )\r\n\t{\r\n\t\tpBlocks[i].p_class = p_class;\r\n\t\tpBlocks[i].size = size;\r\n\t\tpBlocks[i].total = size;\r\n\t\tpBlocks[i].actual = size + Mem::Allocator::BlockHeader::sSize;\r\n\t\tpBlocks[i].return_addr = return_addr;\r\n\t\tpBlocks[i].count = 1;\r\n\t\tnum++;\r\n\t}\r\n}\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__\r\nstatic int bbb = 0;\t   \t// compiler patch var, see below\r\n#endif\r\n\r\nvoid MemView_AnalyzeBlocks(uint32 mask)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n#if 0\r\n\tSBlockType  *pBlocks = (SBlockType  *)_mem_dump_start;\t// temp memory\r\n\tint\tnum_blocks = 0;\r\n\tint num = 0;\r\n\r\n\tprintf (\"\\nAnalyzing blocks....\\n\");\r\n\t\r\n\tCCallStack *p = used_list.pNext;  \r\n\twhile (p != &used_list)\r\n\t{\r\n\t\t// Get the actualy block we referred to\r\n//\t\tMem::Allocator::BlockHeader * pBlock = p->pBlock;\r\n//\t\tvoid * p_start = (void*)((uint)pBlock + Mem::Allocator::BlockHeader::sSize);\r\n\t\t// Otionally check to see if it on the front end heap\r\n//\t\tif (Mem::SameContext(p_start,Mem::Manager::sHandle().FrontEndHeap()))\r\n\t\t{\r\n\t\t\tif (!mask || !(p->flags & mask))\r\n\t\t\t{\r\n\t\t\t\tMemView_AnalyzeCallStack( p, pBlocks, num );\t\t\t\r\n\t\t\t\tnum_blocks++;\r\n\t\t\t}\r\n\t\t}\r\n\t\tp = p->pNext; \r\n\t}\r\n\t\r\n\tprintf (\"%d types, in %d total blocks\\n\", num, num_blocks); \r\n\r\n\tMemView_DumpAnalysis( pBlocks, num );\r\n\tif (bbb)\r\n\t{\r\n\t\tMemView_DumpBottomFragments();\t\t\t// just to get it compiling \r\n\t\tMemView_DumpTopFragments();\t\t\t// just to get it compiling \r\n\t}\t\t\r\n#endif\r\n#endif\r\n}\r\n\r\n\r\nvoid MemView_MarkBlocks(uint32 mask)\r\n{\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n\r\n\tCCallStack *p = used_list.pNext;  \r\n\twhile (p != &used_list)\r\n\t{\r\n\t\tp->flags |= mask;\r\n\t\t\r\n\t\tp = p->pNext;\r\n\t}\r\n#endif\r\n}\r\n\r\n\r\n\r\nvoid MemView_Input(uint buttons, uint makes, uint breaks)\r\n{\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\r\n\r\n//\tif (makes & Inp::Data::mD_TRIANGLE)\r\n//\t{\r\n//\t\tMemView_Active = !MemView_Active;\r\n//\t}\r\n\r\n\r\n\tif (!MemView_Active)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t\t\t\t\t  \r\n\tfloat step1 = step;\r\n\t\r\n\tfloat zoom = 1.1f;\r\n\t\r\n\tfloat scroll = 4.0f;\r\n\r\n\t\r\n\r\n\r\n\r\n\tif (buttons & Inp::Data::mD_LEFT)\r\n\t{\r\n\t\tstep1 = step * zoom;\r\n\t}\r\n\tif (buttons & Inp::Data::mD_RIGHT)\r\n\t{\r\n\t\tstep1 = step / zoom;\r\n\t}\r\n\t\r\n\tif (buttons & Inp::Data::mD_UP)\r\n\t{\r\n//\t\tstart = start - scroll * 512.0f * 2.0f * step;\r\n\t\tcursor = cursor - scroll * 512.0f * 2.0f * step;\r\n\t}\r\n\tif (buttons & Inp::Data::mD_DOWN)\r\n\t{\r\n//\t\tstart = start + scroll * 512.0f * 2.0f * step;\r\n\t\tcursor = cursor + scroll * 512.0f * 2.0f * step;\r\n\t}\r\n\r\n\tif (buttons & Inp::Data::mD_L1)\r\n\t{\r\n//\t\tstart = start - scroll * 512.0f * 2.0f * step / 256.0f;\r\n\t\tcursor = cursor - scroll * 2.0f * 2.0f * step;\r\n\t}\r\n\tif (buttons & Inp::Data::mD_L2)\r\n\t{\r\n//\t\tstart = start + scroll * 512.0f * 2.0f * step / 256.0f;\r\n\t\tcursor = cursor + scroll * 2.0f * 2.0f * step;\r\n\t}\r\n\r\n#define \tMMMIN \t(0.0078125f)\r\n\t \t\t\t\t\r\n\tif (step1 <MMMIN)\r\n\t{\r\n\t\tstep1 = MMMIN;\r\n\t}\r\n\t\r\n\tif (step1>1024.0f)\r\n\t{\r\n\t\tstep1 = 1024.0f;\r\n\t}\r\n\r\n//\tstart = start + (512.0f * 2.0f * 128.0f * (step - step1));\r\n\r\n\tstep = step1;\r\n\r\n\tif (makes & Inp::Data::mD_CIRCLE)\r\n\t{\r\n\t\tif (blockstart)\r\n\t\t{\r\n\t\t\tMemView_DumpRefs(blockstart);\r\n\t\t}\r\n//\t\tMemView_MarkBlocks(1);\r\n\t}\r\n\r\n\t// We don't look for leaks automatically now, so I'v put it on \"SQUARE\"\t\r\n\tif (makes & Inp::Data::mD_SQUARE)\r\n\t{\r\n\t\tMemView_FindLeaks();\r\n//\tMem::Manager& mem_man = Mem::Manager::sHandle();\t\tMemView_DumpHeap(1);\r\n//\theap\t= mem_man.TopDownHeap();\r\n//\tMemView_DumpFragments(heap);\r\n//\tMemView_DumpHeap(heap,1);\r\n\r\n\t}\r\n\r\n\tif (makes & Inp::Data::mD_X)\r\n\t{\r\n\t\tMemView_AnalyzeBlocks();\r\n\t}\r\n\r\n\t// Triangle = Dump Fragmentation\r\n/*\tif (makes & Inp::Data::mD_TRIANGLE)\r\n\t{\r\n\t\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\t\tMem::Heap* heap = mem_man.BottomUpHeap();\r\n\t\tMem::Region* region = heap->ParentRegion();\r\n\t\tprintf (\"BottomUp Frag %dK, %d Blocks\\n\",heap->mFreeMem.m_count / 1024, heap->mFreeBlocks.m_count);\r\n\t\tprintf (\"Region %d/%d K\", region->MemAvailable() / 1024, region->TotalSize() / 1024 );\r\n\t\tMemView_DumpFragments(heap);\r\n\t}\r\n*/\t\r\n\r\n}\r\n\r\nvoid MemView_AnalyzeHeap(Mem::Heap *pHeap)\r\n{\r\n\tif ( !pHeap )\r\n\t\treturn;\r\n\t\r\n#ifdef\t__LINKED_LIST_HEAP__\r\n#if 0\r\n\tSBlockType  *pBlocks = (SBlockType  *)_mem_dump_start;\t// temp memory\r\n\tint\tnum_blocks = 0;\r\n\tint num = 0;\r\n\r\n\tMem::Allocator::BlockHeader *p_full = pHeap->mp_context->mp_used_list;\r\n\r\n\twhile (p_full)\r\n\t{\r\n\t\tCCallStack* pCallStack = (CCallStack*)p_full->mp_debug_data;\r\n\r\n\t\tif ( pCallStack )\r\n\t\t{\r\n\t\t\tMemView_AnalyzeCallStack( pCallStack, pBlocks, num );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tprintf (\"Block with No Debug Info!!\\n\");\r\n\t\t}\r\n\r\n\t\tp_full = p_full->mp_next_used;\r\n\t}\r\n\r\n\tprintf (\"%d types, in %d total blocks\\n\", num, num_blocks); \r\n\r\n\tMemView_DumpAnalysis( pBlocks, num );\r\n#endif\r\n#endif\r\n}\r\n  \r\n  \r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_memview.h",
    "content": "////\r\n\r\n#ifndef\t__P_MEMVIEW_H__\r\n#define\t__P_MEMVIEW_H__\r\n\r\nvoid MemView_Display();\r\nvoid MemView_Input(uint buttons, uint makes, uint breaks);\r\nvoid MemView_Alloc( void *v);\r\nvoid MemView_Free( void *v);\r\nvoid MemViewToggle();\r\nvoid MemView_FindLeaks();\r\nint DumpUnwindStack( int iMaxDepth, int *pDest );\r\nchar *MemView_GetFunctionName(int pc, int *p_size);\r\nvoid MemView_DumpFragments(Mem::Heap *pHeap);\r\nvoid MemView_AnalyzeBlocks(uint32 mask = 0);\r\nvoid MemView_MarkBlocks(uint32 flags = 1 );\r\nvoid MemView_DumpHeap(Mem::Heap *pHeap);\r\nvoid MemView_AnalyzeHeap(Mem::Heap *pHeap);\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nx.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\t\t\t \t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgfx/xbox/p_nx.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/16/2002\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXbox platform specific interface to the engine\t\t\t**\r\n**\t\t\t\t\tThis is Xbox SPECIFIC!!!!!! If there is anything in\t\t**\r\n**\t\t\t\t\there that is not Xbox specific, then it needs to be\t\t**\r\n**\t\t\t\t\tin nx.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include\t<xtl.h>\r\n#include\t<xgraphics.h>\r\n#include\t<sys/file/filesys.h>\r\n\r\n#include\t\"gfx\\camera.h\"\r\n#include\t\"gfx\\gfxman.h\"\r\n#include\t\"gfx\\nx.h\"\r\n#include\t\"gfx\\nxtexman.h\"\r\n#include\t\"gfx\\nxviewman.h\"\r\n#include\t\"gfx\\NxQuickAnim.h\"\r\n#include\t\"gfx\\NxParticleMgr.h\"\r\n#include\t\"gfx\\NxMiscFX.h\"\r\n#include\t\"gfx\\debuggfx.h\"\r\n#include\t\"gfx\\xbox\\p_NxSector.h\"\r\n#include\t\"gfx\\xbox\\p_NxScene.h\"\r\n#include\t\"gfx\\xbox\\p_NxModel.h\"\r\n#include\t\"gfx\\xbox\\p_NxGeom.h\"\r\n#include\t\"gfx\\xbox\\p_NxMesh.h\"\r\n#include\t\"gfx\\xbox\\p_NxSprite.h\"\r\n#include\t\"gfx\\xbox\\p_NxTexture.h\"\r\n#include\t\"gfx\\xbox\\p_NxParticle.h\"\r\n#include\t\"gfx\\xbox\\p_NxTextured3dPoly.h\"\r\n#include\t\"gfx\\xbox\\p_NxNewParticleMgr.h\"\r\n#include\t\"gfx\\xbox\\p_NxWeather.h\"\r\n#include\t\"core\\math.h\"\r\n#include \t\"sk\\engine\\SuperSector.h\"\t\t\t\t\t\r\n#include \t\"gel\\scripting\\script.h\"\r\n\r\n#include \t\"gfx\\xbox\\nx\\nx_init.h\"\r\n#include \t\"gfx\\xbox\\nx\\texture.h\"\r\n#include \t\"gfx\\xbox\\nx\\material.h\"\r\n#include \t\"gfx\\xbox\\nx\\render.h\"\r\n#include \t\"gfx\\xbox\\nx\\screenfx.h\"\r\n#include \t\"gfx\\xbox\\nx\\occlude.h\"\r\n#include \t\"gfx\\xbox\\nx\\scene.h\"\r\n#include \t\"gfx\\xbox\\nx\\chars.h\"\r\n\r\n#include\t\"gel\\music\\xbox\\p_soundtrack.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_start_engine( void )\r\n{\r\n\tNxXbox::InitialiseEngine();\r\n\r\n\tmp_particle_manager\t= new CXboxNewParticleManager;\r\n\tmp_weather\t\t\t= new CXboxWeather;\r\n\r\n\t// If the user selected widescreen from the dashboard, reset the default screen angle and aspect ratio.\r\n\tif( XGetVideoFlags() & ( XC_VIDEO_FLAGS_WIDESCREEN | XC_VIDEO_FLAGS_HDTV_720p ))\r\n\t{\r\n\t\tScript::RunScript( \"screen_setup_widescreen\" );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_pre_render( void )\r\n{\r\n\t// The screen clear is now added to the push buffer directly after the swap, in s_plat_post_render().\r\n\r\n\t// No rendering should take place whilst the loading screen is visible.\r\n//\tif( !NxXbox::EngineGlobals.loadingscreen_visible )\r\n//\t{\r\n//\t\tD3DCOLOR col = 0x00506070;\r\n//\r\n//\t\tif( NxXbox::EngineGlobals.screen_blur > 0 )\r\n//\t\t{\r\n//\t\t\tD3DDevice_Clear( 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, col, 1.0f, 0 );\r\n//\t\t\t++NxXbox::EngineGlobals.screen_blur_duration;\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tD3DDevice_Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, col, 1.0f, 0 );\r\n//\t\t\tNxXbox::EngineGlobals.screen_blur_duration = 0;\r\n//\t\t}\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_post_render( void )\r\n{\r\n\t// No rendering should take place whilst the loading screen is visible.\r\n\tif( !NxXbox::EngineGlobals.loadingscreen_visible )\r\n\t{\r\n\t\tD3DDevice_Swap( D3DSWAP_DEFAULT );\r\n\r\n\t\tif( NxXbox::EngineGlobals.screenshot_name[0] != 0 )\r\n\t\t{\r\n\t\t\tSpt::SingletonPtr< Gfx::Manager > gfx_manager;\r\n\t\t\tgfx_manager->ScreenShot( NxXbox::EngineGlobals.screenshot_name );\r\n\t\t\tNxXbox::EngineGlobals.screenshot_name[0] = 0;\r\n\t\t}\r\n\r\n\t\t// Now that the swap instruction has been pushed, clear the buffer for next frame.\r\n\t\tif( NxXbox::EngineGlobals.screen_blur > 0 )\r\n\t\t{\r\n\t\t\tD3DDevice_Clear( 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, NxXbox::EngineGlobals.clear_color, 1.0f, 0 );\r\n\t\t\t++NxXbox::EngineGlobals.screen_blur_duration;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif( NxXbox::EngineGlobals.letterbox_active )\r\n\t\t\t{\r\n\t\t\t\tD3DDevice_Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, 0x00000000UL, 1.0f, 0 );\r\n\t\t\t}\r\n\t\t\telse if( NxXbox::EngineGlobals.clear_color_buffer )\r\n\t\t\t{\r\n\t\t\t\tD3DDevice_Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, NxXbox::EngineGlobals.clear_color, 1.0f, 0 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tD3DDevice_Clear( 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, NxXbox::EngineGlobals.clear_color, 1.0f, 0 );\r\n\t\t\t}\r\n\t\t\tNxXbox::EngineGlobals.screen_blur_duration = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_render_world( void )\r\n{\r\n\t// Remove the loading bar.\r\n\tif( NxXbox::EngineGlobals.loadingbar_timer_event != 0 )\r\n\t{\r\n\t\ttimeKillEvent( NxXbox::EngineGlobals.loadingbar_timer_event );\r\n\t\tNxXbox::EngineGlobals.loadingbar_timer_event = 0;\r\n\t}\r\n\r\n\t// No rendering should take place whilst the loading screen is visible.\r\n\tif( !NxXbox::EngineGlobals.loadingscreen_visible )\r\n\t{\r\n\t\t// Store time at start of render, used as reference throughout.\r\n\t\tNxXbox::EngineGlobals.render_start_time = (int)Tmr::GetTime();\r\n\r\n\t\t// Render objects of interest for the render target (shadow objects).\r\n\t\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t1 );\r\n\t\tNxXbox::set_render_state( RS_ZTESTENABLE,\t1 );\r\n\r\n\t\tNxXbox::render_shadow_targets();\r\n\r\n\t\tCEngine::sGetImposterManager()->ProcessImposters();\r\n\r\n\t\t// Start up the screen blur if we're using it.\r\n\t\tNxXbox::start_screen_blur();\r\n\r\n\t\tint num_viewports = CViewportManager::sGetNumActiveViewports();\r\n\t\tfor( int v = 0; v < num_viewports; ++v )\r\n\t\t{\r\n\t\t\tCViewport\t*p_cur_viewport\t= CViewportManager::sGetActiveViewport( v );\r\n\t\t\tGfx::Camera\t*p_cur_camera\t= p_cur_viewport->GetCamera();\r\n\t\t\t\r\n\t\t\t// Check for a valid camera.\r\n\t\t\tif( p_cur_camera == NULL )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\r\n\t\t\tNxXbox::EngineGlobals.viewport.X\t\t= (DWORD)( p_cur_viewport->GetOriginX() * NxXbox::EngineGlobals.backbuffer_width );\r\n\t\t\tNxXbox::EngineGlobals.viewport.Y\t\t= (DWORD)( p_cur_viewport->GetOriginY() * NxXbox::EngineGlobals.backbuffer_height );\r\n\t\t\tNxXbox::EngineGlobals.viewport.Width\t= (DWORD)( p_cur_viewport->GetWidth() * NxXbox::EngineGlobals.backbuffer_width );\r\n\t\t\tNxXbox::EngineGlobals.viewport.Height\t= (DWORD)( p_cur_viewport->GetHeight() * NxXbox::EngineGlobals.backbuffer_height );\r\n\t\t\tNxXbox::EngineGlobals.viewport.MinZ\t\t= 0.0f;\r\n\t\t\tNxXbox::EngineGlobals.viewport.MaxZ\t\t= 1.0f;\r\n\r\n\t\t\tif( NxXbox::EngineGlobals.letterbox_active )\r\n\t\t\t{\t\r\n\t\t\t\tNxXbox::EngineGlobals.viewport.Y\t\t+= (DWORD)( NxXbox::EngineGlobals.backbuffer_height / 8 );\r\n\t\t\t\tNxXbox::EngineGlobals.viewport.Height\t-= (DWORD)( NxXbox::EngineGlobals.backbuffer_height / 4 );\r\n\t\t\t}\r\n\r\n\t\t\tD3DDevice_SetViewport( &NxXbox::EngineGlobals.viewport );\r\n\r\n\t\t\t// There is no bounding box transform for rendering the world.\r\n\t\t\tNxXbox::set_frustum_bbox_transform( NULL );\r\n\t\t\r\n\t\t\t// Set up the camera..\r\n\t\t\tfloat aspect_ratio = p_cur_viewport->GetAspectRatio();\r\n\r\n\t\t\tNxXbox::set_camera( &( p_cur_camera->GetMatrix()), &( p_cur_camera->GetPos()), p_cur_camera->GetAdjustedHFOV(), aspect_ratio );\r\n\r\n\t\t\t// Render the non-sky world scenes.\r\n\t\t\tfor( int i = 0; i < MAX_LOADED_SCENES; i++ )\r\n\t\t\t{\r\n\t\t\t\tif( sp_loaded_scenes[i] )\r\n\t\t\t\t{\r\n\t\t\t\t\tCXboxScene *pXboxScene = static_cast<CXboxScene *>( sp_loaded_scenes[i] );\r\n\r\n\t\t\t\t\tif( !pXboxScene->IsSky())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Build relevant occlusion poly list, now that the camera is set.\r\n\t\t\t\t\t\tNxXbox::BuildOccluders( &( p_cur_camera->GetPos()), v );\r\n\r\n\t\t\t\t\t\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t1 );\r\n\t\t\t\t\t\tNxXbox::set_render_state( RS_ZTESTENABLE,\t1 );\r\n\r\n\t\t\t\t\t\t// Flag this scene as receiving shadows.\r\n\t\t\t\t\t\tpXboxScene->GetEngineScene()->m_flags |= SCENE_FLAG_RECEIVE_SHADOWS;\r\n\r\n\t\t\t\t\t\tNxXbox::render_scene( pXboxScene->GetEngineScene(), NxXbox::vRENDER_OPAQUE |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNxXbox::vRENDER_OCCLUDED |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNxXbox::vRENDER_SORT_FRONT_TO_BACK |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNxXbox::vRENDER_BILLBOARDS, v );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t0 );\r\n\t\t\tNx::TextureSplatRender();\r\n\t\t\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t1 );\r\n\r\n\t\t\tCEngine::sGetImposterManager()->DrawImposters();\r\n\r\n\t\t\t// Render all opaque instances.\r\n\t\t\tNxXbox::render_instances( NxXbox::vRENDER_OPAQUE );\r\n\t\t\r\n\t\t\t// Now that opaque geometry is drawn, do the render tests for the light glows.\r\n\t\t\tNxXbox::render_light_glows( true );\r\n\r\n\t\t\t// Render the sky, followed by all the non-sky semitransparent scene geometry. There is no bounding box transform for rendering the world.\r\n\t\t\tNxXbox::set_frustum_bbox_transform( NULL );\r\n\r\n\t\t\t// Set up the sky camera.\r\n\t\t\tMth::Vector\tcentre_pos( 0.0f, 0.0f, 0.0f );\r\n\t\t\tNxXbox::set_camera( &( p_cur_camera->GetMatrix()), &centre_pos, p_cur_camera->GetAdjustedHFOV(), aspect_ratio, true );\r\n\r\n\t\t\t// Render the sky. We have to fudge the fog here to ensure the sky is fully fogged, since it is rendered with a non-standard projection\r\n\t\t\t// matrix to ensure a constant z=1, but which breaks the fog interpolation value.\r\n\t\t\tfloat fog_start = NxXbox::EngineGlobals.fog_start;\r\n\t\t\tfloat fog_end\t= NxXbox::EngineGlobals.fog_end;\r\n\t\t\tNxXbox::EngineGlobals.fog_start\t= -20.0f;\r\n\t\t\tNxXbox::EngineGlobals.fog_end\t= -21.0f;\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_FOGSTART,\t*((DWORD*)( &NxXbox::EngineGlobals.fog_start )));\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_FOGEND,\t\t*((DWORD*)( &NxXbox::EngineGlobals.fog_end )));\r\n\r\n\t\t\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t0 );\r\n\t\t\tNxXbox::set_render_state( RS_ZTESTENABLE,\t1 );\r\n\t\t\tfor( int i = 0; i < MAX_LOADED_SCENES; i++ )\r\n\t\t\t{\r\n\t\t\t\tif( sp_loaded_scenes[i] )\r\n\t\t\t\t{\r\n\t\t\t\t\tCXboxScene *pXboxScene = static_cast<CXboxScene *>( sp_loaded_scenes[i] );\r\n\t\t\t\t\tif( pXboxScene->IsSky())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// No anisotropic filtering for the sky.\r\n\t\t\t\t\t\tDWORD stage_zero_minfilter, stage_zero_mipfilter;\r\n\t\t\t\t\t\tD3DDevice_GetTextureStageState( 0, D3DTSS_MINFILTER, &stage_zero_minfilter );\r\n\t\t\t\t\t\tD3DDevice_GetTextureStageState( 0, D3DTSS_MIPFILTER, &stage_zero_mipfilter );\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE );\r\n\r\n\t\t\t\t\t\tNxXbox::render_scene( pXboxScene->GetEngineScene(), NxXbox::vRENDER_OPAQUE | NxXbox::vRENDER_SEMITRANSPARENT, v );\r\n\t\t\t\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_MIPFILTER, stage_zero_mipfilter );\r\n\t\t\t\t\t\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER, stage_zero_minfilter );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t1 );\r\n\r\n\t\t\t// Restore fog values.\r\n\t\t\tNxXbox::EngineGlobals.fog_start\t= fog_start;\r\n\t\t\tNxXbox::EngineGlobals.fog_end\t= fog_end;\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_FOGSTART,\t*((DWORD*)( &NxXbox::EngineGlobals.fog_start )));\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_FOGEND,\t\t*((DWORD*)( &NxXbox::EngineGlobals.fog_end )));\r\n\r\n\t\t\t// Revert to the regular camera.\r\n\t\t\tNxXbox::set_camera( &( p_cur_camera->GetMatrix()), &( p_cur_camera->GetPos()), p_cur_camera->GetAdjustedHFOV(), aspect_ratio );\r\n\r\n\t\t\t// Render all semitransparent instances.\r\n\t\t\tNxXbox::render_instances( NxXbox::vRENDER_SEMITRANSPARENT | NxXbox::vRENDER_INSTANCE_PRE_WORLD_SEMITRANSPARENT );\r\n\r\n\t\t\t// Render the non-sky semitransparent scene geometry.\r\n\t\t\t// Setting the depth clip control to clamp here means that semitransparent periphary objects that would usually cull out\r\n\t\t\t// are now drawn correctly (since they will clamp at 1.0, and the z test is <=).\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_DEPTHCLIPCONTROL, D3DDCC_CLAMP );\r\n\t\t\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t1 );\r\n\t\t\tNxXbox::set_render_state( RS_ZTESTENABLE,\t1 );\r\n\t\t\tfor( int i = 0; i < MAX_LOADED_SCENES; i++ )\r\n\t\t\t{\r\n\t\t\t\tif( sp_loaded_scenes[i] )\r\n\t\t\t\t{\r\n\t\t\t\t\tCXboxScene *pXboxScene = static_cast<CXboxScene *>( sp_loaded_scenes[i] );\r\n\t\t\t\t\tif( !pXboxScene->IsSky())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Build relevant occlusion poly list, now that the camera is set.\r\n\t\t\t\t\t\tNxXbox::render_scene( pXboxScene->GetEngineScene(), NxXbox::vRENDER_SEMITRANSPARENT |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNxXbox::vRENDER_OCCLUDED |\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNxXbox::vRENDER_BILLBOARDS, v );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tD3DDevice_SetRenderState( D3DRS_DEPTHCLIPCONTROL, D3DDCC_CULLPRIMITIVE );\r\n\r\n\t\t\t// Render the particles.\r\n\t\t\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t0 );\r\n\t\t\trender_particles();\r\n\r\n\t\t\t// New style particles. Update should probably be somewhere else.\r\n\t\t\tmp_particle_manager->UpdateParticles();\r\n\t\t\tmp_particle_manager->RenderParticles();\r\n\r\n\t\t\t// Render weather effects.\r\n\t\t\tmp_weather->Process( Tmr::FrameLength());\r\n\t\t\tmp_weather->Render();\r\n\r\n\t\t\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t1 );\r\n\r\n\t\t\t// We want shatter objects to be rendered after the sky since they will typically be semitransparent.\r\n\t\t\tNx::ShatterRender();\r\n\r\n\t\t\t// Render all semitransparent instances.\r\n\t\t\tNxXbox::render_instances( NxXbox::vRENDER_SEMITRANSPARENT | NxXbox::vRENDER_INSTANCE_POST_WORLD_SEMITRANSPARENT );\r\n\r\n\t\t\t// Render the light glows (the visibility tests were performed earlier).\r\n\t\t\tNxXbox::render_light_glows( false );\r\n\r\n\t\t\t// Render the shadow volumes.\r\n//\t\t\tfor( int i = 0; i < MAX_LOADED_SCENES; i++ )\r\n//\t\t\t{\r\n//\t\t\t\tif( sp_loaded_scenes[i] )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tCXboxScene *pXboxScene = static_cast<CXboxScene *>( sp_loaded_scenes[i] );\r\n//\t\t\t\t\tif( !pXboxScene->IsSky())\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tNxXbox::render_scene( pXboxScene->GetEngineScene(), NxXbox::vRENDER_SHADOW_VOLUMES, v );\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n\t\t\t\r\n\t\t\tNx::ScreenFlashRender( v, 0 );\r\n\t\t}\r\n\r\n\t\t// This x86 instruction writes back and invalidates the cache. This should hopefully mean that all updated vertex buffer\r\n\t\t// data (vc wibble) are flushed out by the time the GPU hits them.\r\n\t\t_asm\r\n\t\t{\r\n\t\t\twbinvd;\r\n\t\t}\r\n\r\n\t\t// Draw debug lines.\r\n#\t\tifdef __NOPT_ASSERT__\r\n\t\tGfx::DebugGfx_Draw();\r\n#\t\tendif\r\n\r\n\t\t// Reset viewport so text appears on full screen.\r\n\t\tNxXbox::EngineGlobals.viewport.X\t\t= 0;\r\n\t\tNxXbox::EngineGlobals.viewport.Y\t\t= 0;\r\n\t\tNxXbox::EngineGlobals.viewport.Width\t= NxXbox::EngineGlobals.backbuffer_width;\r\n\t\tNxXbox::EngineGlobals.viewport.Height\t= NxXbox::EngineGlobals.backbuffer_height;\r\n\t\tNxXbox::EngineGlobals.viewport.MinZ\t\t= 0.0f;\r\n\t\tNxXbox::EngineGlobals.viewport.MaxZ\t\t= 1.0f;\r\n\r\n\t\tif( NxXbox::EngineGlobals.letterbox_active )\r\n\t\t{\t\r\n\t\t\tNxXbox::EngineGlobals.viewport.Y\t\t+= (DWORD)( NxXbox::EngineGlobals.backbuffer_height / 8 );\r\n\t\t\tNxXbox::EngineGlobals.viewport.Height\t-= (DWORD)( NxXbox::EngineGlobals.backbuffer_height / 4 );\r\n\t\t}\r\n\r\n\t\tD3DDevice_SetViewport( &NxXbox::EngineGlobals.viewport );\r\n\r\n//\t\tObj::CSkater *pSkater = Mdl::Skate::Instance()->GetLocalSkater();\r\n//\t\tMth::Vector pos = pSkater->GetPos();\r\n//\t\tNxXbox::set_focus_blur_focus( pos, 0.0f, 10.0f * 12.0f, 100.0f * 12.0f );\r\n//\t\tNxXbox::finish_focus_blur();\r\n\r\n\t\t// Horrible hack - this should be somewhere else ASAP.\r\n\t\tNxXbox::SDraw2D::DrawAll();\r\n\r\n\t\t// Finish the screen blur if we're using it.\r\n\t\tNxXbox::finish_screen_blur();\r\n\t}\r\n\r\n\t// Reset viewport so screen clear will work.\r\n\tNxXbox::EngineGlobals.viewport.X\t\t= 0;\r\n\tNxXbox::EngineGlobals.viewport.Y\t\t= 0;\r\n\tNxXbox::EngineGlobals.viewport.Width\t= NxXbox::EngineGlobals.backbuffer_width;\r\n\tNxXbox::EngineGlobals.viewport.Height\t= NxXbox::EngineGlobals.backbuffer_height;\r\n\tNxXbox::EngineGlobals.viewport.MinZ\t\t= 0.0f;\r\n\tNxXbox::EngineGlobals.viewport.MaxZ\t\t= 1.0f;\r\n\tD3DDevice_SetViewport( &NxXbox::EngineGlobals.viewport );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCScene\t*CEngine::s_plat_create_scene( const char *p_name, CTexDict *p_tex_dict, bool add_super_sectors )\r\n{\r\n\t// Create scene class instance\r\n\tCXboxScene\t*p_xbox_scene\t= new CXboxScene;\r\n\tCScene\t\t*p_new_scene\t= p_xbox_scene;\r\n\tp_new_scene->SetInSuperSectors( add_super_sectors );\r\n\tp_new_scene->SetIsSky( false );\r\n\r\n\t// Create a new sScene so the engine can track assets for this scene.\r\n\tNxXbox::sScene *p_engine_scene = new NxXbox::sScene();\r\n\tp_xbox_scene->SetEngineScene( p_engine_scene );\r\n\r\n\treturn p_new_scene;\r\n}\r\n\r\n\r\n\r\n#define MemoryRead( dst, size, num, src )\tCopyMemory(( dst ), ( src ), (( num ) * ( size )));\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t( src ) += (( num ) * ( size ))\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCScene *CEngine::s_plat_load_scene_from_memory( void *p_mem, CTexDict *p_tex_dict, bool add_super_sectors, bool is_sky, bool is_dictionary )\r\n{\r\n\tuint8\t\t\t*p_data = (uint8*)p_mem;\r\n\tCSector\t\t\t*pSector;\r\n\tCXboxSector\t\t*pXboxSector;\r\n\r\n\t// Create a new sScene so the engine can track assets for this scene.\r\n\tNxXbox::sScene *p_engine_scene = new NxXbox::sScene();\r\n\r\n\t// Set the dictionary flag.\r\n\tp_engine_scene->m_is_dictionary\t= is_dictionary;\r\n\r\n\t// Version numbers.\r\n\tuint32 mat_version, mesh_version, vert_version;\r\n\tMemoryRead( &mat_version, sizeof( uint32 ), 1, p_data );\r\n\tMemoryRead( &mesh_version, sizeof( uint32 ), 1, p_data );\r\n\tMemoryRead( &vert_version, sizeof( uint32 ), 1, p_data );\r\n\r\n\t// Import materials (they will now be associated at the engine-level with this scene).\r\n\tp_engine_scene->pMaterialTable = NxXbox::LoadMaterialsFromMemory( (void**)&p_data, p_tex_dict->GetTexLookup());\r\n\r\n\t// Read number of sectors.\r\n\tint num_sectors;\r\n\tMemoryRead( &num_sectors, sizeof( int ), 1, p_data );\r\n\r\n\t// Figure optimum hash table lookup size.\r\n\tuint32 optimal_table_size\t= num_sectors * 2;\r\n\tuint32 test\t\t\t\t\t= 2;\r\n\tuint32 size\t\t\t\t\t= 1;\r\n\tfor( ;; test <<= 1, ++size )\r\n\t{\r\n\t\t// Check if this iteration of table size is sufficient, or if we have hit the maximum size.\r\n\t\tif(( optimal_table_size <= test ) || ( size >= 12 ))\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// Create scene class instance, using optimum size sector table.\r\n\tCScene* new_scene = new CXboxScene( size );\r\n\tnew_scene->SetInSuperSectors( add_super_sectors );\r\n\tnew_scene->SetIsSky( is_sky );\r\n\r\n\t// Get a scene id from the engine.\r\n\tCXboxScene *p_new_xbox_scene = static_cast<CXboxScene *>( new_scene );\r\n\tp_new_xbox_scene->SetEngineScene( p_engine_scene );\r\n\r\n\tfor( int s = 0; s < num_sectors; ++s )\r\n\t{\r\n\t\t// Create a new sector to hold the incoming details.\r\n\t\tpSector\t\t\t\t\t\t= p_new_xbox_scene->CreateSector();\r\n\t\tpXboxSector\t\t\t\t\t= static_cast<CXboxSector*>( pSector );\r\n\t\t\r\n\t\t// Generate a hanging geom for the sector, used for creating level objects etc.\r\n\t\tCXboxGeom\t*p_xbox_geom\t= new CXboxGeom();\r\n\t\tp_xbox_geom->SetScene( p_new_xbox_scene );\r\n\t\tpXboxSector->SetGeom( p_xbox_geom );\r\n\t\t\r\n\t\t// Prepare CXboxGeom for receiving data.\r\n\t\tp_xbox_geom->InitMeshList();\r\n\t\t\r\n\t\t// Load sector data.\r\n\t\tif( pXboxSector->LoadFromMemory( (void**)&p_data ))\r\n\t\t{\r\n\t\t\tnew_scene->AddSector( pSector );\r\n\t\t}\r\n\t}\r\n\r\n\t// At this point get the engine scene to figure it's bounding volumes.\r\n\tp_engine_scene->FigureBoundingVolumes();\r\n\t\r\n\t// Read hierarchy information.\r\n\tint num_hierarchy_objects;\r\n\tMemoryRead( &num_hierarchy_objects, sizeof( int ), 1, p_data );\r\n\r\n\tif( num_hierarchy_objects > 0 )\r\n\t{\r\n\t\tp_engine_scene->mp_hierarchyObjects = new CHierarchyObject[num_hierarchy_objects];\r\n\t\tMemoryRead( p_engine_scene->mp_hierarchyObjects, sizeof( CHierarchyObject ), num_hierarchy_objects, p_data );\r\n\t\tp_engine_scene->m_numHierarchyObjects = num_hierarchy_objects;\r\n\t}\r\n\r\n\treturn new_scene;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCScene *CEngine::s_plat_load_scene( const char *p_name, CTexDict *p_tex_dict, bool add_super_sectors, bool is_sky, bool is_dictionary )\r\n{\r\n\tCSector*\t\tpSector;\r\n\tCXboxSector*\tpXboxSector;\r\n\r\n\tDbg_Message( \"loading scene from file %s\\n\", p_name );\r\n\r\n\t// Create a new NxXbox::sScene so the engine can track assets for this scene.\r\n\tNxXbox::sScene *p_engine_scene = new NxXbox::sScene();\r\n\r\n\t// Set the dictionary flag.\r\n\tp_engine_scene->m_is_dictionary\t= is_dictionary;\r\n\r\n\t// Open the scene file.\r\n\tvoid* p_file = File::Open( p_name, \"rb\" );\r\n\tif( !p_file )\r\n\t{\r\n\t\tDbg_MsgAssert( p_file, ( \"Couldn't open scene file %s\\n\", p_name ));\r\n\t\treturn NULL;\r\n\t}\r\n\t\r\n\t// Version numbers.\r\n\tuint32 mat_version, mesh_version, vert_version;\r\n\tFile::Read( &mat_version, sizeof( uint32 ), 1, p_file );\r\n\tFile::Read( &mesh_version, sizeof( uint32 ), 1, p_file );\r\n\tFile::Read( &vert_version, sizeof( uint32 ), 1, p_file );\r\n\r\n\t// Import materials (they will now be associated at the engine-level with this scene).\r\n\tp_engine_scene->pMaterialTable = NxXbox::LoadMaterials( p_file, p_tex_dict->GetTexLookup());\r\n\r\n\t// Read number of sectors.\r\n\tint num_sectors;\r\n\tFile::Read( &num_sectors, sizeof( int ), 1, p_file );\r\n\r\n\t// Figure optimum hash table lookup size.\r\n\tuint32 optimal_table_size\t= num_sectors * 2;\r\n\tuint32 test\t\t\t\t\t= 2;\r\n\tuint32 size\t\t\t\t\t= 1;\r\n\tfor( ;; test <<= 1, ++size )\r\n\t{\r\n\t\t// Check if this iteration of table size is sufficient, or if we have hit the maximum size.\r\n\t\tif(( optimal_table_size <= test ) || ( size >= 12 ))\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// Create scene class instance, using optimum size sector table.\r\n\tCScene* new_scene = new CXboxScene( size );\r\n\tnew_scene->SetInSuperSectors( add_super_sectors );\r\n\tnew_scene->SetIsSky( is_sky );\r\n\r\n\t// Get a scene id from the engine.\r\n\tCXboxScene *p_new_xbox_scene = static_cast<CXboxScene *>( new_scene );\r\n\tp_new_xbox_scene->SetEngineScene( p_engine_scene );\r\n\r\n\tfor( int s = 0; s < num_sectors; ++s )\r\n\t{\r\n\t\t// Create a new sector to hold the incoming details.\r\n\t\tpSector\t\t\t\t\t\t= p_new_xbox_scene->CreateSector();\r\n\t\tpXboxSector\t\t\t\t\t= static_cast<CXboxSector*>( pSector );\r\n\t\t\r\n\t\t// Generate a hanging geom for the sector, used for creating level objects etc.\r\n\t\tCXboxGeom\t*p_xbox_geom\t= new CXboxGeom();\r\n\t\tp_xbox_geom->SetScene( p_new_xbox_scene );\r\n\t\tpXboxSector->SetGeom( p_xbox_geom );\r\n\t\t\r\n\t\t// Prepare CXboxGeom for receiving data.\r\n\t\tp_xbox_geom->InitMeshList();\r\n\t\t\r\n\t\t// Load sector data.\r\n\t\tif( pXboxSector->LoadFromFile( p_file ))\r\n\t\t{\r\n\t\t\tnew_scene->AddSector( pSector );\r\n\t\t}\r\n\t}\r\n\r\n\t// At this point get the engine scene to figure it's bounding volumes.\r\n\tp_engine_scene->FigureBoundingVolumes();\r\n\t\r\n\t// Read hierarchy information.\r\n\tint num_hierarchy_objects;\r\n\tFile::Read( &num_hierarchy_objects, sizeof( int ), 1, p_file );\r\n\r\n\tif( num_hierarchy_objects > 0 )\r\n\t{\r\n\t\tp_engine_scene->mp_hierarchyObjects = new CHierarchyObject[num_hierarchy_objects];\r\n\t\tFile::Read( p_engine_scene->mp_hierarchyObjects, sizeof( CHierarchyObject ), num_hierarchy_objects, p_file );\r\n\t\tp_engine_scene->m_numHierarchyObjects = num_hierarchy_objects;\r\n\t}\r\n\t\r\n\tFile::Close( p_file );\r\n\r\n\treturn new_scene;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CEngine::s_plat_unload_scene( CScene *p_scene )\r\n{\r\n\tDbg_MsgAssert( p_scene,( \"Trying to delete a NULL scene\" ));\r\n\r\n\tCXboxScene *p_xbox_scene = (CXboxScene*)p_scene;\r\n\r\n\t// Ask the engine to remove the associated meshes for each sector in the scene.\r\n\tp_xbox_scene->DestroySectorMeshes();\r\n\r\n\t// Get the engine specific scene data and pass it to the engine to delete.\r\n\tNxXbox::DeleteScene( p_xbox_scene->GetEngineScene());\r\n\tp_xbox_scene->SetEngineScene( NULL );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CEngine::s_plat_add_scene( CScene *p_scene, const char *p_filename )\r\n{\r\n\t// Function to incrementally add geometry to a scene - should NOT be getting called on Xbox.\r\n\tDbg_Assert( 0 );\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//CTexDict* CEngine::s_plat_load_textures( const char* p_name )\r\n//{\r\n//\tNxXbox::LoadTextureFile( p_name );\r\n//\treturn NULL;\r\n//}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCModel* CEngine::s_plat_init_model( void )\r\n{\r\n\tCXboxModel *pModel = new CXboxModel;\r\n\t\r\n\treturn pModel;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CEngine::s_plat_uninit_model( CModel* pModel )\r\n{\r\n\tdelete pModel;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCGeom* CEngine::s_plat_init_geom( void )\r\n{\r\n\tCXboxGeom *pGeom = new CXboxGeom;\r\n\treturn pGeom;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CEngine::s_plat_uninit_geom( CGeom *p_geom )\r\n{\r\n\tdelete p_geom;\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCQuickAnim* CEngine::s_plat_init_quick_anim()\r\n{\r\n\tCQuickAnim* pQuickAnim = new CQuickAnim;\r\n\treturn pQuickAnim;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_uninit_quick_anim(CQuickAnim* pQuickAnim)\r\n{\r\n\tdelete pQuickAnim;\r\n\treturn;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCMesh* CEngine::s_plat_load_mesh( const char* pMeshFileName, Nx::CTexDict* pTexDict, uint32 texDictOffset, bool isSkin, bool doShadowVolume )\r\n{\r\n\t// Load the scene.\r\n\tNx::CScene *p_scene = Nx::CEngine::s_plat_load_scene( pMeshFileName, pTexDict, false, false, false );\r\n\r\n\t// Store the checksum of the scene name.\r\n\tp_scene->SetID(Script::GenerateCRC( pMeshFileName )); \t// store the checksum of the scene name\r\n\r\n\tp_scene->SetTexDict( pTexDict );\r\n\tp_scene->PostLoad( pMeshFileName );\r\n\t\r\n\t// Disable any scaling.\r\n\tNxXbox::DisableMeshScaling();\r\n\r\n\tCXboxMesh *pMesh = new CXboxMesh( pMeshFileName );\r\n\r\n\tNx::CXboxScene *p_xbox_scene = static_cast<Nx::CXboxScene*>( p_scene );\r\n\tpMesh->SetScene( p_xbox_scene );\r\n\tpMesh->SetTexDict( pTexDict );\r\n\r\n\treturn pMesh;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCMesh* CEngine::s_plat_load_mesh( uint32 id, uint32 *p_model_data, int model_data_size, uint8 *p_cas_data, Nx::CTexDict* pTexDict, uint32 texDictOffset, bool isSkin, bool doShadowVolume )\r\n{\r\n\t// Convert the id into a usable string.\r\n\tDbg_Assert( id > 0 );\r\n\tchar id_as_string[16];\r\n\tsprintf( id_as_string, \"%d\\n\", id );\r\n\r\n\t// Load the scene.\r\n\tNx::CScene *p_scene = Nx::CEngine::s_plat_load_scene_from_memory( p_model_data, pTexDict, false, false, false );\r\n\r\n\t// Store the checksum of the scene name.\r\n\tp_scene->SetID( Script::GenerateCRC( id_as_string ));\r\n\r\n\tp_scene->SetTexDict( pTexDict );\r\n\tp_scene->PostLoad( id_as_string );\r\n\t\r\n\tCXboxMesh *pMesh = new CXboxMesh();\r\n\r\n\t// Set CAS data for mesh.\r\n\tpMesh->SetCASData( p_cas_data );\r\n\r\n\t// Disable any scaling.\r\n\tNxXbox::DisableMeshScaling();\r\n\r\n\tNx::CXboxScene *p_xbox_scene = static_cast<Nx::CXboxScene*>( p_scene );\r\n\tpMesh->SetScene( p_xbox_scene );\r\n\tpMesh->SetTexDict( pTexDict );\r\n\treturn pMesh;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CEngine::s_plat_unload_mesh( CMesh *pMesh )\r\n{\r\n\tdelete pMesh;\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_set_mesh_scaling_parameters( SMeshScalingParameters* pParams )\r\n{\r\n\tNxXbox::SetMeshScalingParameters( pParams );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCSprite *CEngine::s_plat_create_sprite( CWindow2D *p_window )\r\n{\r\n\treturn new CXboxSprite;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CEngine::s_plat_destroy_sprite( CSprite *p_sprite )\r\n{\r\n\tdelete p_sprite;\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTextured3dPoly *\tCEngine::s_plat_create_textured_3d_poly()\r\n{\r\n\treturn new CXboxTextured3dPoly;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tCEngine::s_plat_destroy_textured_3d_poly(CTextured3dPoly *p_poly)\r\n{\r\n\tdelete p_poly;\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nNx::CTexture *CEngine::s_plat_create_render_target_texture( int width, int height, int depth, int z_depth )\r\n{\r\n\t// Create the CXBoxTexture (just a container class for the NxXbox::sTexture).\r\n\tCXboxTexture *p_texture = new CXboxTexture();\r\n\r\n\t// Create the NxXbox::sTexture.\r\n\tNxXbox::sTexture *p_engine_texture = new NxXbox::sTexture;\r\n\tp_texture->SetEngineTexture( p_engine_texture );\r\n\t\r\n\t// Set the texture as a render target.\r\n\tp_engine_texture->SetRenderTarget( width, height, depth, z_depth );\r\n\t\r\n\treturn p_texture;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_project_texture_into_scene( Nx::CTexture *p_texture, Nx::CModel *p_model, Nx::CScene *p_scene )\r\n{\r\n\tNx::CXboxTexture\t*p_xbox_texture\t= static_cast<CXboxTexture*>( p_texture );\r\n\tNx::CXboxModel\t\t*p_xbox_model\t= static_cast<CXboxModel*>( p_model );\r\n//\tNx::CXboxScene\t\t*p_xbox_scene\t= static_cast<CXboxScene*>( p_scene );\r\n//\tNxXbox::create_texture_projection_details( p_xbox_texture->GetEngineTexture(), p_xbox_model, p_xbox_scene->GetEngineScene());\r\n\tNxXbox::create_texture_projection_details( p_xbox_texture->GetEngineTexture(), p_xbox_model, NULL );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_set_projection_texture_camera( Nx::CTexture *p_texture, Gfx::Camera *p_camera )\r\n{\r\n\tNx::CXboxTexture\t*p_xbox_texture\t= static_cast<CXboxTexture*>( p_texture );\r\n\tXGVECTOR3\t\t\tpos( p_camera->GetPos()[X], p_camera->GetPos()[Y], p_camera->GetPos()[Z] );\r\n\tXGVECTOR3\t\t\tat = pos + D3DXVECTOR3( p_camera->GetMatrix()[Z][X], p_camera->GetMatrix()[Z][Y], p_camera->GetMatrix()[Z][Z] );\r\n\t\r\n\tNxXbox::set_texture_projection_camera( p_xbox_texture->GetEngineTexture(), &pos, &at );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_stop_projection_texture( Nx::CTexture *p_texture )\r\n{\r\n\tNx::CXboxTexture *p_xbox_texture = static_cast<CXboxTexture*>( p_texture );\r\n\tNxXbox::destroy_texture_projection_details( p_xbox_texture->GetEngineTexture());\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_add_occlusion_poly( uint32 num_verts, Mth::Vector *p_vert_array, uint32 checksum )\r\n{\r\n\tif( num_verts == 4 )\r\n\t{\r\n\t\tNxXbox::AddOcclusionPoly( p_vert_array[0], p_vert_array[1], p_vert_array[2], p_vert_array[3], checksum );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_enable_occlusion_poly( uint32 checksum, bool enable )\r\n{\r\n\tNxXbox::EnableOcclusionPoly( checksum, enable );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_remove_all_occlusion_polys( void )\r\n{\r\n\tNxXbox::RemoveAllOcclusionPolys();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// returns true if the sphere at \"center\", with the \"radius\"\r\n// is visible to the current camera\r\n// (note, currently this is the last frame's camera on PS2)\r\nbool CEngine::s_plat_is_visible( Mth::Vector& center, float radius )\r\n{\r\n\treturn NxXbox::IsVisible( center, radius );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_set_max_multipass_distance( float dist )\r\n{\r\n\t// Has no meaning for Xbox.\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst char* CEngine::s_plat_get_platform_extension( void )\r\n{\r\n\t// String literals are statically allocated so can be returned safely, (Bjarne, p90)\r\n\treturn \"Xbx\";\r\n}\r\n\r\n\r\n/******************************************************************/\r\n// Wait for any pending asyncronous rendering to finish, so rendering\r\n// data can be unloaded\r\n/******************************************************************/\r\nvoid CEngine::s_plat_finish_rendering()\r\n{\r\n\t// Wait for asyncronous rendering to finish.\r\n\tNxXbox::EngineGlobals.p_Device->BlockUntilIdle();\r\n} \r\n\r\n/******************************************************************/\r\n// Set the amount that the previous frame is blended with this frame\r\n// 0 = none\t  \t(just see current frame) \t\r\n// 128 = 50/50\r\n// 255 = 100% \t(so you only see the previous frame)\t\t\t\t\t\t\t\t\t\t\t\t  \r\n/******************************************************************/\r\nvoid CEngine::s_plat_set_screen_blur( uint32 amount )\r\n{\r\n\t// Only set the blur if we have a blur buffer into which to render.\r\n\tif( NxXbox::EngineGlobals.p_BlurSurface[0] )\r\n\t{\r\n\t\tNxXbox::EngineGlobals.screen_blur = amount;\r\n\t}\r\n} \r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint\tCEngine::s_plat_get_num_soundtracks( void )\r\n{\r\n\treturn Pcm::GetNumSoundtracks();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst char* CEngine::s_plat_get_soundtrack_name( int soundtrack_number )\r\n{\r\n\tstatic char buf[128];\r\n\r\n\tconst WCHAR* p_soundtrack_name_wide = Pcm::GetSoundtrackName( soundtrack_number );\r\n\r\n\tif( p_soundtrack_name_wide )\r\n\t{\r\n\t\t// If p_soundtrack_name_wide contains characters not recognized by the XBox then wsprintfA\r\n\t\t// will write an empty string. It does this for the test bad soundtrack names provided by\r\n\t\t// the certification tool.\r\n\t\t// However, I'm not sure if wsprintf will write an empty string if there is just one bad\r\n\t\t// character in the name, or if it will only write an empty string if they are all bad.\r\n\t\t// So just to be sure, do a wsprintfA for each character in turn. That way, any good characters\r\n\t\t// will definitely be printed OK, and all bad characters will appear as xbox null characters.\r\n\t\tchar *p_dest = buf;\r\n\t\tint count=0;\r\n\t\tWCHAR p_temp[2]; // A buffer for holding one WCHAR at a time for sending to wsprintfA.\r\n\t\tp_temp[1]\t= 0;\r\n\t\tconst WCHAR *p_scan = p_soundtrack_name_wide;\r\n\r\n\t\twhile( *p_scan ) // WCHAR strings are terminated by a 0 just like normal strings, except its a 2byte 0.\r\n\t\t{\r\n\t\t\tp_temp[0] = *p_scan++;\r\n\t\t\t\t\r\n\t\t\tchar p_one_char[10];\r\n\t\t\twsprintfA( p_one_char, \"%ls\", p_temp);\r\n\r\n\t\t\t// p_one_char now contains a one char string.\r\n\t\t\tif( count < 99 )\r\n\t\t\t{\r\n\t\t\t\tif( *p_one_char )\r\n\t\t\t\t{\r\n\t\t\t\t\t*p_dest = *p_one_char;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Bad char, so write a ~ so that it appears as a xbox null char.\r\n\t\t\t\t\t*p_dest='~';\r\n\t\t\t\t}\t\r\n\t\t\t\t++p_dest;\r\n\t\t\t\t++count;\r\n\t\t\t}\r\n\t\t}\t\r\n\t\t*p_dest = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// In theory this should never happen, but make sure p_buf contains something if it does.\r\n\t\tsprintf( buf, \"~\" );\r\n\t}\t\r\n\t\t\r\n\tint len = strlen( buf );\r\n\tfor( int c = 0; c < len; ++c )\r\n\t{\r\n\t\t// Force any special characters (arrows or button icons) to be displayed\r\n\t\t// as the xbox NULL character by changing them to an invalid character.\r\n\t\tswitch( buf[c] )\r\n\t\t{\r\n\t\t\tcase '': case '': case '': case '':\r\n\t\t\tcase '': case '': case '': case '':\r\n\t\t\tcase '': case '': case '': case '':\r\n\t\t\t\tbuf[c] = '~';\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\t\r\n\t}\r\n\treturn buf;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_set_letterbox( bool letterbox )\r\n{\r\n\t// Letterbox mode is designed for use on a regular 4:3 screen.\r\n\t// It should use the same, wider viewing angle as for widescreen mode, but shrink the resultant image down\r\n\t// vertically by 25%.\r\n\tif( letterbox )\r\n\t{\r\n\t\tif( NxXbox::EngineGlobals.letterbox_active == false )\r\n\t\t{\r\n\t\t\t// Need to adjust the screen y offset and multiplier to ensure sprites are scaled properly for this mode.\r\n\t\t\tNxXbox::EngineGlobals.screen_conv_y_offset\t\t+= ( NxXbox::EngineGlobals.backbuffer_height / 4 ) / 2;\r\n\t\t\tNxXbox::EngineGlobals.screen_conv_y_multiplier\t= 0.75f;\r\n\t\t\tNxXbox::EngineGlobals.letterbox_active\t\t\t= true;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( NxXbox::EngineGlobals.letterbox_active == true )\r\n\t\t{\r\n\t\t\t// Restore the screen y offset and multiplier.\r\n\t\t\tNxXbox::EngineGlobals.screen_conv_y_offset\t\t-= ( NxXbox::EngineGlobals.backbuffer_height / 4 ) / 2;\r\n\t\t\tNxXbox::EngineGlobals.screen_conv_y_multiplier\t= 1.0f;\r\n\t\t\tNxXbox::EngineGlobals.letterbox_active\t\t\t= false;\r\n\t\t}\r\n\t}\r\n} \r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::s_plat_set_color_buffer_clear( bool clear )\r\n{\r\n//\tNxXbox::EngineGlobals.clear_color_buffer = clear;\r\n}\r\n\r\n} // namespace Nx\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxfont.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxFont.cpp\r\n\r\n#include \t\"gfx/xbox/p_nxfont.h\"\r\n#include \t\"sys/config/config.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CFont\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCXboxFont::CXboxFont() : mp_plat_font(NULL)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCXboxFont::~CXboxFont()\r\n{\r\n\tif (mp_plat_font)\r\n\t{\r\n\t\tplat_unload();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxFont::plat_load(const char *filename)\r\n{\r\n#\tifdef __PAL_BUILD__\r\n\t// <Sigh>. Have to trap the small font, which needs to be loaded from a different\r\n\t// location for the French build.\r\n\tif( Config::GetLanguage() == Config::LANGUAGE_FRENCH )\r\n\t{\r\n\t\tif( strstr( filename, \"small\" ))\r\n\t\t{\r\n\t\t\tmp_plat_font = NxXbox::LoadFont( \"small_fr\" );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_plat_font = NxXbox::LoadFont( filename );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_plat_font = NxXbox::LoadFont(filename);\r\n\t}\r\n#\telse\r\n\tmp_plat_font = NxXbox::LoadFont(filename);\r\n#\tendif\r\n\r\n\treturn (mp_plat_font != NULL);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CXboxFont::plat_set_spacings(int charSpacing, int spaceSpacing)\r\n{\r\n\tmp_plat_font->mCharSpacing = charSpacing;\r\n\tif (spaceSpacing > 0)\r\n\t\tmp_plat_font->mSpaceSpacing = spaceSpacing;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CXboxFont::plat_set_rgba_table(Image::RGBA *pTab)\r\n{\r\n\tfor (int i = 0; i < 16; i++)\r\n\t\tmp_plat_font->mRGBATab[i] = *((uint32 *) &pTab[i]);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CXboxFont::plat_mark_as_button_font(bool isButton)\r\n{\r\n\tNxXbox::pButtonsFont = (isButton) ? mp_plat_font : NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CXboxFont::plat_unload()\r\n{\r\n\tNxXbox::UnloadFont(mp_plat_font);\r\n\tmp_plat_font = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 CXboxFont::plat_get_default_height() const\r\n{\r\n\tDbg_Assert(mp_plat_font);\r\n\r\n\treturn mp_plat_font->GetDefaultHeight();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 CXboxFont::plat_get_default_base() const\r\n{\r\n\tDbg_Assert(mp_plat_font);\r\n\r\n\treturn mp_plat_font->GetDefaultBase();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//void CXboxFont::plat_begin_text(uint32 rgba, float Scale)\r\n//{\r\n//\tDbg_Assert(mp_plat_font);\r\n//\r\n//\tmp_plat_font->BeginText(rgba, Scale);\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//void CXboxFont::plat_draw_string(char *String, float x0, float y0)\r\n//{\r\n//\tDbg_Assert(mp_plat_font);\r\n//\r\n//\tmp_plat_font->DrawString(String, x0, y0);\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//void CXboxFont::plat_end_text(void)\r\n//{\r\n//\tDbg_Assert(mp_plat_font);\r\n//\r\n//\tmp_plat_font->EndText();\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxFont::plat_query_string(char *String, float &width, float &height) const\r\n{\r\n\tDbg_Assert(mp_plat_font);\r\n\r\n\tmp_plat_font->QueryString(String, width, height);\r\n}\r\n\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of the CText\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxText::CXboxText()\r\n{\r\n\tmp_plat_text\t= new NxXbox::SText();\r\n\tm_zvalue\t\t= 0;\r\n\r\n\tplat_initialize();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxText::~CXboxText()\r\n{\r\n\tif( mp_plat_text )\r\n\t{\r\n\t\tdelete mp_plat_text;\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CXboxText::plat_initialize()\r\n{\r\n\tplat_update_engine();\r\n\tplat_update_priority();\r\n\tplat_update_hidden();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CXboxText::plat_update_hidden()\r\n{\r\n\tmp_plat_text->SetHidden(m_hidden);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxText::plat_update_engine()\r\n{\r\n\tCXboxFont *p_xbox_font = static_cast<CXboxFont *>( mp_font );\r\n\r\n\tmp_plat_text->mp_string\t= m_string;\r\n\tif( p_xbox_font)\r\n\t{\r\n\t\tmp_plat_text->mp_font = p_xbox_font->GetEngineFont();\r\n\t}\r\n\r\n\tmp_plat_text->m_xpos\t= m_xpos;\r\n\tmp_plat_text->m_ypos\t= m_ypos;\r\n\tmp_plat_text->m_xscale\t= m_xscale;\r\n\tmp_plat_text->m_yscale\t= m_yscale;\r\n\tmp_plat_text->m_rgba\t= *((uint32 *) &m_rgba);\r\n\tmp_plat_text->m_color_override = m_color_override;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxText::plat_update_priority( void )\r\n{\r\n\t// Update draw list\r\n\tmp_plat_text->SetPriority( m_priority );\r\n\r\n\tif( m_use_zbuffer )\r\n\t{\r\n\t\t// Convert the 16:16 fixed z value to a float here.\r\n\t\tfloat z = (float)m_zvalue / 65536.0f;\r\n\t\tmp_plat_text->SetZValue( z );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_plat_text->SetZValue( 0.0f );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CTextMan::s_plat_alloc_text_pool( void )\r\n{\r\n\tfor( int i = 0; i < vMAX_TEXT_INSTANCES; ++i )\r\n\t{\r\n\t   \tCXboxText *p_text\t\t= new CXboxText;\r\n\t\tp_text->mp_next\t\t\t= sp_dynamic_text_list;\r\n\t\tsp_dynamic_text_list\t= p_text;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxfont.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxFont.h\r\n\r\n#ifndef\t__GFX_P_NX_FONT_H__\r\n#define\t__GFX_P_NX_FONT_H__\r\n\r\n#include \t\"gfx/nxfont.h\"\r\n#include \t\"gfx/xbox/nx/chars.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CFont\r\nclass CXboxFont : public CFont\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCXboxFont();\r\n\tvirtual\t\t\t\t\t\t~CXboxFont();\r\n\tNxXbox::SFont\t\t\t\t*GetEngineFont() const;\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\tvirtual\tbool\t\t\t\tplat_load(const char *filename);\r\n\tvirtual void\t\t\t\tplat_set_spacings(int charSpacing, int spaceSpacing);\r\n\tvirtual void\t\t\t\tplat_set_rgba_table(Image::RGBA *pTab);\r\n\tvirtual void \t\t\t\tplat_mark_as_button_font(bool isButton);\r\n\tvirtual void\t\t\t\tplat_unload();\r\n\r\n\tvirtual\tuint32\t\t\t\tplat_get_default_height() const;\r\n\tvirtual\tuint32\t\t\t\tplat_get_default_base() const;\r\n//\tvirtual void\t\t\t\tplat_begin_text(uint32 rgba, float Scale);\r\n//\tvirtual void\t\t\t\tplat_draw_string(char *String, float x0, float y0);\r\n//\tvirtual void\t\t\t\tplat_end_text(void);\r\n\tvirtual void\t\t\t\tplat_query_string(char *String, float &width, float &height) const;\r\n\r\n\t// Machine specific members\r\n\tNxXbox::SFont *\t\t\t\tmp_plat_font;\t\t// Pointer to engine font\r\n};\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of the CText\r\nclass\tCXboxText : public CText\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCXboxText();\r\n\tvirtual\t\t\t\t\t\t~CXboxText();\r\n\r\nprivate:\r\n\t//\r\n\tvirtual void\t\t\t\tplat_initialize();\r\n\r\n\tvirtual void\t\t\t\tplat_update_hidden();\t\t// Tell engine of update\r\n\tvirtual void\t\t\t\tplat_update_engine();\t\t// Update engine primitives\r\n\tvirtual void\t\t\t\tplat_update_priority();\r\n\r\n\t// Machine specific members\r\n\tNxXbox::SText\t\t\t\t*mp_plat_text;\t\t// Pointer to engine text\r\n};\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ninline NxXbox::SFont *CXboxFont::GetEngineFont() const\r\n{\r\n\treturn mp_plat_font;\r\n}\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxfontman.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\t\t\t \t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgfx/xbox/p_nxfontman.cpp\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/16/2002\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXbox platform specific interface to the Font Manager\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include\t\"gfx\\nx.h\"\r\n#include\t\"gfx\\NxFontMan.h\"\r\n#include\t\"gfx\\xbox\\p_NxFont.h\"\r\n#include \t\"gfx\\xbox\\nx\\chars.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCFont* CFontManager::s_plat_load_font( const char* pName )\r\n{\r\n\tCXboxFont *p_new_font = new CXboxFont;\r\n\tp_new_font->Load( pName );\r\n\treturn p_new_font;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CFontManager::s_plat_unload_font( CFont* pFont )\r\n{\r\n\tpFont->Unload();\r\n}\r\n\r\n} // namespace Nx\r\n \r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxmiscfx.cpp",
    "content": "#include <core/defines.h>\r\n\r\n#include <gel/collision/collision.h>\r\n#include <gel/collision/colltridata.h>\r\n#include <gel/collision/movcollman.h>\r\n#include <gel/collision/batchtricoll.h>\r\n#include <engine/SuperSector.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/nxtexman.h>\r\n#include <gfx/debuggfx.h>\r\n#include <gfx/NxViewMan.h>\r\n#include <gfx/NxMiscFX.h>\r\n\r\n#include <gfx/xbox/p_nxgeom.h>\r\n#include <gfx/xbox/p_nxtexture.h>\r\n\r\n#include <gfx/xbox/nx/render.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\n#define\tDRAW_DEBUG_LINES\t\t0\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sXboxScreenFlashVert\r\n{\r\n\tfloat\t\tx, y, z;\r\n\tfloat\t\trhw;\r\n\tD3DCOLOR\tcol;\r\n\tfloat\t\tu, v;\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sXboxSplatVert\r\n{\r\n\tD3DXVECTOR3\t\tpos;\r\n\tD3DCOLOR\t\tcol;\r\n\tfloat\t\t\tu, v;\r\n};\r\n\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sXboxSplatInstanceDetails : public sSplatInstanceDetails\r\n{\r\n\t// Platform specific part.\r\n\tNxXbox::CInstance\t*mp_instance;\r\n\tNxXbox::sMaterial\t*mp_material;\r\n\tsXboxSplatVert\t\tm_verts[SPLAT_POLYS_PER_MESH * 3];\r\n};\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sXboxShatterInstanceDetails : public sShatterInstanceDetails\r\n{\r\n\t// Platform specific part.\r\n\r\n\t\t\t\t\t\tsXboxShatterInstanceDetails( int num_tris, NxXbox::sMesh *p_mesh );\r\n\t\t\t\t\t\t~sXboxShatterInstanceDetails( void );\r\n\t\r\n\tNxXbox::sMesh\t\t*mp_mesh;\r\n\tuint8\t\t\t\t*mp_vertex_buffer;\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsXboxShatterInstanceDetails::sXboxShatterInstanceDetails( int num_tris, NxXbox::sMesh *p_mesh ) : sShatterInstanceDetails( num_tris )\r\n{\r\n\tmp_mesh\t\t\t\t= p_mesh;\r\n\tmp_vertex_buffer\t= new uint8[num_tris * 3 * p_mesh->m_vertex_stride];\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsXboxShatterInstanceDetails::~sXboxShatterInstanceDetails( void )\r\n{\r\n\tdelete [] mp_vertex_buffer;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsXboxSplatInstanceDetails * getDetailsForTextureSplat( NxXbox::sTexture *p_texture )\r\n{\r\n\tsXboxSplatInstanceDetails *p_xbox_details;\r\n\r\n\tDbg_Assert( p_splat_details_table );\r\n\t\r\n\t// Check to see whether we have a scene already created for this type of texture splat.\r\n\tp_splat_details_table->IterateStart();\r\n\tsSplatInstanceDetails *p_details = p_splat_details_table->IterateNext();\r\n\twhile( p_details )\r\n\t{\r\n\t\tp_xbox_details\t\t\t\t\t= static_cast<sXboxSplatInstanceDetails*>( p_details );\r\n\t\tNxXbox::sMaterial *p_material\t= p_xbox_details->mp_material;\r\n\t\tif( p_material->mp_tex[0] == p_texture )\r\n\t\t{\r\n\t\t\t// This scene contains a material with the required texture, so use this scene.\r\n\t\t\treturn p_xbox_details;\r\n\t\t}\r\n\t\tp_details = p_splat_details_table->IterateNext();\r\n\t}\r\n\t\r\n\t// Create an (opaque) material used to render the mesh.\r\n\tNxXbox::sMaterial *p_material\t= new NxXbox::sMaterial();\r\n\tp_material->m_flags[0]\t\t\t= (( p_texture ) ? MATFLAG_TEXTURED : 0 );\r\n\tp_material->m_checksum\t\t\t= (uint32)rand() * (uint32)rand();\r\n\tp_material->m_passes\t\t\t= 1;\r\n\tp_material->mp_tex[0]\t\t\t= p_texture;\r\n\tp_material->m_no_bfc\t\t\t= true;\r\n\tp_material->m_zbias\t\t\t\t= 1;\t\t\t\t// To ensure it will sort above most geometry.\r\n\tp_material->m_reg_alpha[0]\t\t= 0x00000005UL;\t\t// Blend for now.\r\n\tp_material->m_color[0][0]\t\t= 0x80;\r\n\tp_material->m_color[0][1]\t\t= 0x80;\r\n\tp_material->m_color[0][2]\t\t= 0x80;\r\n\tp_material->m_uv_addressing[0]\t= 0x00020002UL;\t\t// We want the texture to border - most efficient for alphakill.\r\n\tp_material->m_k[0]\t\t\t\t= 0.0f;\r\n\tp_material->m_alpha_cutoff\t\t= 1;\r\n\r\n\tp_xbox_details = new sXboxSplatInstanceDetails;\r\n\tp_xbox_details->m_highest_active_splat\t= 0;\r\n\tp_xbox_details->mp_material\t\t\t\t= p_material;\r\n\tZeroMemory( p_xbox_details->m_lifetimes, sizeof( int ) * SPLAT_POLYS_PER_MESH );\r\n\r\n\tfor( int v = 0; v < SPLAT_POLYS_PER_MESH * 3; ++v )\r\n\t{\r\n\t\tp_xbox_details->m_verts[v].pos = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );\r\n\t\tp_xbox_details->m_verts[v].col = D3DCOLOR_RGBA( 0x80, 0x80, 0x80, 0x80 );\r\n\t}\r\n\t\r\n\tp_splat_details_table->PutItem((uint32)p_xbox_details, p_xbox_details );\r\n\r\n\treturn p_xbox_details;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool subdivide_tri_stack( uint8 **p_write, NxXbox::sMesh *p_mesh )\r\n{\r\n\t// Three temporary buffers.\r\n\tstatic uint8 v0[128];\r\n\tstatic uint8 v1[128];\r\n\tstatic uint8 v2[128];\r\n\r\n\t// Three more temporary buffers.\r\n\tstatic uint8 i01[128];\r\n\tstatic uint8 i12[128];\r\n\tstatic uint8 i20[128];\r\n\r\n\t// If there are elements on the stack, pop off the top three vertices and subdivide if necessary.\r\n\tif( triSubdivideStack.IsEmpty())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tD3DXVECTOR3\t*p_v0 = (D3DXVECTOR3*)v0;\r\n\tD3DXVECTOR3\t*p_v1 = (D3DXVECTOR3*)v1;\r\n\tD3DXVECTOR3\t*p_v2 = (D3DXVECTOR3*)v2;\r\n\t\r\n\t// Stack is LIFO, so Pop() off in reverse order.\r\n\ttriSubdivideStack.Pop( p_v2 );\r\n\ttriSubdivideStack.Pop( p_v1 );\r\n\ttriSubdivideStack.Pop( p_v0 );\r\n\t\r\n\t// Calculate the area of this tri.\r\n\tMth::Vector p(\tp_v1->x - p_v0->x, p_v1->y - p_v0->y, p_v1->z - p_v0->z );\r\n\tMth::Vector q(\tp_v2->x - p_v0->x, p_v2->y - p_v0->y, p_v2->z - p_v0->z );\r\n\tMth::Vector r(( p[Y] * q[Z] ) - ( q[Y] * p[Z] ), ( p[Z] * q[X] ) - ( q[Z] * p[X] ), ( p[X] * q[Y] ) - ( q[X] * p[Y] ));\r\n\tfloat area_squared = r.LengthSqr();\r\n\r\n\tif( area_squared > shatterAreaTest )\r\n\t{\r\n\t\t// We need to subdivide this tri. Calculate the three intermediate points.\r\n\t\tint block_size = triSubdivideStack.GetBlockSize();\r\n\r\n\t\tmemcpy( i01, v0, block_size );\r\n\t\tmemcpy( i12, v1, block_size );\r\n\t\tmemcpy( i20, v2, block_size );\r\n\r\n\t\t// Deal with positions (always present).\r\n\t\t((D3DXVECTOR3*)i01 )->x = p_v0->x + (( p_v1->x - p_v0->x ) * 0.5f );\r\n\t\t((D3DXVECTOR3*)i01 )->y = p_v0->y + (( p_v1->y - p_v0->y ) * 0.5f );\r\n\t\t((D3DXVECTOR3*)i01 )->z = p_v0->z + (( p_v1->z - p_v0->z ) * 0.5f );\r\n\r\n\t\t((D3DXVECTOR3*)i12 )->x = p_v1->x + (( p_v2->x - p_v1->x ) * 0.5f );\r\n\t\t((D3DXVECTOR3*)i12 )->y = p_v1->y + (( p_v2->y - p_v1->y ) * 0.5f );\r\n\t\t((D3DXVECTOR3*)i12 )->z = p_v1->z + (( p_v2->z - p_v1->z ) * 0.5f );\r\n\r\n\t\t((D3DXVECTOR3*)i20 )->x = p_v2->x + (( p_v0->x - p_v2->x ) * 0.5f );\r\n\t\t((D3DXVECTOR3*)i20 )->y = p_v2->y + (( p_v0->y - p_v2->y ) * 0.5f );\r\n\t\t((D3DXVECTOR3*)i20 )->z = p_v2->z + (( p_v0->z - p_v2->z ) * 0.5f );\r\n\r\n\t\t// Deal with colors (not always present).\r\n\t\tif( p_mesh->m_diffuse_offset > 0 )\r\n\t\t{\r\n\t\t\tuint8\t*p_v0col\t= (uint8*)( v0 + p_mesh->m_diffuse_offset );\r\n\t\t\tuint8\t*p_v1col\t= (uint8*)( v1 + p_mesh->m_diffuse_offset );\r\n\t\t\tuint8\t*p_v2col\t= (uint8*)( v2 + p_mesh->m_diffuse_offset );\r\n\t\t\tuint8\t*p_i01col\t= (uint8*)( i01 + p_mesh->m_diffuse_offset );\r\n\t\t\tuint8\t*p_i12col\t= (uint8*)( i12 + p_mesh->m_diffuse_offset );\r\n\t\t\tuint8\t*p_i20col\t= (uint8*)( i20 + p_mesh->m_diffuse_offset );\r\n\t\t\r\n\t\t\tfor( int i = 0; i < 4; ++i )\r\n\t\t\t{\r\n\t\t\t\tp_i01col[i]\t\t= p_v0col[i] + (((int)p_v1col[i] - (int)p_v0col[i] ) / 2 );\r\n\t\t\t\tp_i12col[i]\t\t= p_v1col[i] + (((int)p_v2col[i] - (int)p_v1col[i] ) / 2 );\r\n\t\t\t\tp_i20col[i]\t\t= p_v2col[i] + (((int)p_v0col[i] - (int)p_v2col[i] ) / 2 );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Deal with uv0 (not always present).\r\n\t\tif( p_mesh->m_uv0_offset > 0 )\r\n\t\t{\r\n\t\t\tfloat\t*p_v0uv\t\t= (float*)( v0 + p_mesh->m_uv0_offset );\r\n\t\t\tfloat\t*p_v1uv\t\t= (float*)( v1 + p_mesh->m_uv0_offset );\r\n\t\t\tfloat\t*p_v2uv\t\t= (float*)( v2 + p_mesh->m_uv0_offset );\r\n\t\t\tfloat\t*p_i01uv\t= (float*)( i01 + p_mesh->m_uv0_offset );\r\n\t\t\tfloat\t*p_i12uv\t= (float*)( i12 + p_mesh->m_uv0_offset );\r\n\t\t\tfloat\t*p_i20uv\t= (float*)( i20 + p_mesh->m_uv0_offset );\r\n\t\t\r\n\t\t\tfor( int i = 0; i < 2; ++i )\r\n\t\t\t{\r\n\t\t\t\tp_i01uv[i]\t\t= p_v0uv[i] + (( p_v1uv[i] - p_v0uv[i] ) * 0.5f );\r\n\t\t\t\tp_i12uv[i]\t\t= p_v1uv[i] + (( p_v2uv[i] - p_v1uv[i] ) * 0.5f );\r\n\t\t\t\tp_i20uv[i]\t\t= p_v2uv[i] + (( p_v0uv[i] - p_v2uv[i] ) * 0.5f );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Push the four new tris onto the stack.\r\n\t\ttriSubdivideStack.Push( v0 );\r\n\t\ttriSubdivideStack.Push( i01 );\r\n\t\ttriSubdivideStack.Push( i20 );\r\n\r\n\t\ttriSubdivideStack.Push( i01 );\r\n\t\ttriSubdivideStack.Push( v1 );\r\n\t\ttriSubdivideStack.Push( i12 );\r\n\r\n\t\ttriSubdivideStack.Push( i01 );\r\n\t\ttriSubdivideStack.Push( i12 );\r\n\t\ttriSubdivideStack.Push( i20 );\r\n\r\n\t\ttriSubdivideStack.Push( i20 );\r\n\t\ttriSubdivideStack.Push( i12 );\r\n\t\ttriSubdivideStack.Push( v2 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Don't need to subdivide this tri.\r\n\t\tint block_size = triSubdivideStack.GetBlockSize();\r\n\r\n\t\t// Just copy the tri into the next available slot.\r\n\t\tmemcpy( *p_write, v0, block_size );\r\n\t\t*p_write += block_size;\r\n\t\tmemcpy( *p_write, v1, block_size );\r\n\t\t*p_write += block_size;\r\n\t\tmemcpy( *p_write, v2, block_size );\r\n\t\t*p_write += block_size;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_screen_flash_render( sScreenFlashDetails *p_details )\r\n{\r\n\t// Get viewport details.\r\n\tCViewport *p_vp = CViewportManager::sGetActiveViewport( p_details->m_viewport );\r\n\r\n\tsXboxScreenFlashVert verts[4];\r\n\r\n\tverts[0].x\t= p_vp->GetOriginX() * NxXbox::EngineGlobals.backbuffer_width;\r\n\tverts[0].y\t= p_vp->GetOriginY() * NxXbox::EngineGlobals.backbuffer_height;\r\n\tverts[0].z\t= p_details->m_z;\r\n\t\r\n\tverts[1].x\t= verts[0].x + ( p_vp->GetWidth() * NxXbox::EngineGlobals.backbuffer_width );\r\n\tverts[1].y\t= verts[0].y;\r\n\tverts[1].z\t= verts[0].z;\r\n\r\n\tverts[2].x\t= verts[0].x + ( p_vp->GetWidth() * NxXbox::EngineGlobals.backbuffer_width );\r\n\tverts[2].y\t= verts[0].y + ( p_vp->GetHeight() * NxXbox::EngineGlobals.backbuffer_height );\r\n\tverts[2].z\t= verts[0].z;\r\n\r\n\tverts[3].x\t= verts[0].x;\r\n\tverts[3].y\t= verts[0].y + ( p_vp->GetHeight() * NxXbox::EngineGlobals.backbuffer_height );\r\n\tverts[3].z\t= verts[0].z;\r\n\r\n\tfor( int v = 0; v < 4; ++v )\r\n\t{\r\n\t\tverts[v].col = D3DCOLOR_ARGB( p_details->m_current.a, p_details->m_current.r, p_details->m_current.g, p_details->m_current.b );\r\n\t\tverts[v].rhw = 1.0f;\r\n\t}\r\n\r\n\tif( p_details->mp_texture )\r\n\t{\r\n\t\tverts[0].u\t= 0.0f;\r\n\t\tverts[0].v\t= 0.0f;\r\n\t\tverts[1].u\t= 1.0f;\r\n\t\tverts[1].v\t= 0.0f;\r\n\t\tverts[2].u\t= 1.0f;\r\n\t\tverts[2].v\t= 1.0f;\r\n\t\tverts[3].u\t= 0.0f;\r\n\t\tverts[3].v\t= 1.0f;\r\n\r\n\t\tNx::CXboxTexture *p_xbox_texture = static_cast<CXboxTexture*>( p_details->mp_texture );\r\n\r\n\t\tNxXbox::set_texture( 0, p_xbox_texture->GetEngineTexture()->pD3DTexture, p_xbox_texture->GetEngineTexture()->pD3DPalette );\r\n\t\tNxXbox::set_render_state( RS_UVADDRESSMODE0, 0x00010001UL );\r\n\t}\r\n\telse\t\r\n\t{\r\n\t\tNxXbox::set_texture( 0, NULL );\r\n\t}\r\n\t\r\n\tNxXbox::set_blend_mode( NxXbox::vBLEND_MODE_BLEND );\r\n\r\n\tNxXbox::set_render_state( RS_ZWRITEENABLE,\t0 );\r\n\tNxXbox::set_render_state( RS_ZTESTENABLE,\t0 );\r\n\r\n\tNxXbox::set_pixel_shader( 0 );\r\n\tNxXbox::set_vertex_shader( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2( 0 ));\r\n\t\r\n\tNxXbox::EngineGlobals.p_Device->DrawPrimitiveUP( D3DPT_QUADLIST, 1, verts, sizeof( sXboxScreenFlashVert ));\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_texture_splat_initialize( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_texture_splat_cleanup( void )\r\n{\r\n\tsXboxSplatInstanceDetails *p_xbox_details;\r\n\r\n\tDbg_Assert( p_splat_details_table );\r\n\t\r\n\tp_splat_details_table->IterateStart();\r\n\tsSplatInstanceDetails *p_details = p_splat_details_table->IterateNext();\r\n\twhile( p_details )\r\n\t{\r\n\t\tp_xbox_details = static_cast<sXboxSplatInstanceDetails*>( p_details );\r\n\r\n\t\tdelete p_xbox_details->mp_material;\r\n\t\t\r\n\t\tp_details = p_splat_details_table->IterateNext();\r\n\r\n\t\tp_splat_details_table->FlushItem((uint32)p_xbox_details );\r\n\t\tdelete p_xbox_details;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_texture_splat_reset_poly( sSplatInstanceDetails *p_details, int index )\r\n{\r\n\t// Cast the details to Xbox details.\r\n\tsXboxSplatInstanceDetails *p_xbox_details = static_cast<sXboxSplatInstanceDetails *>( p_details );\r\n\t\r\n\t// Force this poly to be degenerate.\r\n\tp_xbox_details->m_verts[index * 3 + 1]\t= p_xbox_details->m_verts[index * 3];\r\n\tp_xbox_details->m_verts[index * 3 + 2]\t= p_xbox_details->m_verts[index * 3];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ninline float CrossProduct2D( const Mth::Vector& v1, const Mth::Vector& v2 )\r\n{\t\r\n\t// Assumes for both v1 and v2 that the [z] and [w] components are 0.\r\n\treturn ( v1[X] * v2[Y] ) - ( v1[Y] * v2[X] );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic bool same_side( Mth::Vector &p1, Mth::Vector &p2, Mth::Vector &a, Mth::Vector &b )\r\n{\r\n\tfloat cp1 = CrossProduct2D( b - a, p1 - a );\r\n\tfloat cp2 = CrossProduct2D( b - a, p2 - a );\r\n\tif(( cp1 * cp2 ) >= 0.0f )\r\n\t\treturn true;\r\n    else\r\n\t\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic bool point_in_triangle( Mth::Vector &p, Mth::Vector &a, Mth::Vector &b, Mth::Vector &c )\r\n{\r\n\tif( same_side( p, a, b, c ) && same_side( p, b, c, a ) && same_side( p, c, a, b ))\r\n\t\treturn true;\r\n    else\r\n\t\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline bool line_segment_intersection( float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4 )\r\n{\r\n\tfloat ax = x2 - x1;\r\n\tfloat bx = x3 - x4;\r\n\tfloat ay = y2 - y1;\r\n\tfloat by = y3 - y4;\r\n\tfloat cx = x1 - x3;\r\n\tfloat cy = y1 - y3;\r\n\tfloat d = by * cx - bx * cy;\t// Alpha numerator.\r\n\tfloat f = ay * bx - ax * by;\t// Both denominator.\r\n\r\n\t// Alpha tests.\r\n\tif( f > 0.0f )\r\n\t{\r\n\t\tif( d < 0.0f || d > f )\r\n\t\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( d > 0 || d < f )\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\tfloat e = ax * cy - ay * cx;\t// Beta numerator.\r\n\t\r\n\t// Beta tests.\r\n\tif( f > 0.0f )\r\n\t{\r\n\t\tif( e < 0.0f || e > f )\r\n\t\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( e > 0 || e < f )\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline bool tri_texture_intersect( float u0, float v0, float u1, float v1, float u2, float v2 )\r\n{\r\n\t// Trivial check to see if all three points are outside range of texture.\r\n\tif(( u0 < -1.0f ) && ( u1 < -1.0f ) && ( u2 < -1.0f ))\r\n\t\treturn false;\r\n\tif(( u0 > 1.0f ) && ( u1 > 1.0f ) && ( u2 > 1.0f ))\r\n\t\treturn false;\r\n\tif(( v0 < -1.0f ) && ( v1 < -1.0f ) && ( v2 < -1.0f ))\r\n\t\treturn false;\r\n\tif(( v0 > 1.0f ) && ( v1 > 1.0f ) && ( v2 > 1.0f ))\r\n\t\treturn false;\r\n\t\r\n\t// Perform the check to see if any line segment forming the tri intersects any line segment forming the texture.\r\n\tMth::Vector texture_square[4] = {\tMth::Vector( -1.0f, -1.0f, 0.0f, 0.0f ),\r\n\t\t\t\t\t\t\t\t\t\tMth::Vector(  1.0f, -1.0f, 0.0f, 0.0f ),\r\n\t\t\t\t\t\t\t\t\t\tMth::Vector(  1.0f,  1.0f, 0.0f, 0.0f ),\r\n\t\t\t\t\t\t\t\t\t\tMth::Vector( -1.0f,  1.0f, 0.0f, 0.0f )};\r\n\tfor( int p = 0; p < 4; ++p )\r\n\t{\r\n\t\tint q = ( p + 1 ) % 4;\r\n\t\tif( line_segment_intersection( u0, v0, u1, v1, texture_square[p][X], texture_square[p][Y], texture_square[q][X], texture_square[q][Y] ))\r\n\t\t\treturn true;\r\n\t\tif( line_segment_intersection( u1, v1, u2, v2, texture_square[p][X], texture_square[p][Y], texture_square[q][X], texture_square[q][Y] ))\r\n\t\t\treturn true;\r\n\t\tif( line_segment_intersection( u2, v2, u0, v0, texture_square[p][X], texture_square[p][Y], texture_square[q][X], texture_square[q][Y] ))\r\n\t\t\treturn true;\r\n\t}\r\n\r\n\t// If we reach this point there are three remaining possibilities:\r\n\t// 1) That the tri lies entirely within the texture\r\n\t// 2) That the texture lies entirely within the tri\r\n\t// 3) That there is no space shared by tri and texture\r\n\r\n\t// 1) Perform a trivial check to see whether a corner of the tri lies within the texture.\r\n\tif(( u0 >= -1.0f ) && ( u0 <= 1.0f ) && ( v0 >= -1.0f ) && ( v0 <= 1.0f ))\r\n\t\treturn true;\r\n\tif(( u1 >= -1.0f ) && ( u1 <= 1.0f ) && ( v1 >= -1.0f ) && ( v1 <= 1.0f ))\r\n\t\treturn true;\r\n\tif(( u2 >= -1.0f ) && ( u2 <= 1.0f ) && ( v2 >= -1.0f ) && ( v2 <= 1.0f ))\r\n\t\treturn true;\r\n\r\n\t// 2) Check that at least one corner of the texture falls within the tri.\r\n\tMth::Vector a( u0, v0, 0.0f );\r\n\tMth::Vector b( u1, v1, 0.0f );\r\n\tMth::Vector c( u2, v2, 0.0f );\r\n\tfor( int p = 0; p < 4; ++p )\r\n\t{\r\n\t\tif( point_in_triangle( texture_square[p], a, b, c ))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// 3) No space shared.\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool plat_texture_splat( Nx::CSector **pp_sectors, Nx::CCollStatic **pp_collision, Mth::Vector& start, Mth::Vector& end, float size, float lifetime, Nx::CTexture *p_texture, Nx::sSplatTrailInstanceDetails *p_trail_details )\r\n{\r\n\tXGMATRIX view_matrix, ortho_matrix, projection_matrix;\r\n\r\n#\tif DRAW_DEBUG_LINES\r\n\tGfx::AddDebugLine( start, end, MAKE_RGB( 200, 200, 0 ), MAKE_RGB( 200, 200, 0 ), 1 );\r\n#\tendif // DRAW_DEBUG_LINES\r\n\t\r\n\t// The length of the start->end line defines the view depth of the frustum.\r\n\tMth::Vector\tsplat_vector\t= end - start;\r\n\tfloat\t\tview_depth\t\t= splat_vector.Length();\r\n\tsplat_vector.Normalize();\r\n\t\r\n\t// Calculate the parallel projection matrix. Generally the projection vector will tend to point downwards, so we use a\r\n\t// random vector in the x-z plane to define the up vector for the projection. However if this splat is part of a trail,\r\n\t// use the previous point to generate the up vector.\r\n\tMth::Vector up;\r\n\tif( p_trail_details )\r\n\t{\r\n\t\tup.Set( start[X] - p_trail_details->m_last_pos[X], start[Y] - p_trail_details->m_last_pos[Y], start[Z] - p_trail_details->m_last_pos[Z] );\r\n\r\n\t\t// The height of the viewport is defined by the distance between the two points.\r\n\t\tfloat height = up.Length() * 0.5f;\r\n\r\n\t\t// Now we move start and end halfway back along the up vector.\r\n\t\tstart\t-= up * 0.5f;\r\n\t\tend\t\t-= up * 0.5f;\r\n\t\t\r\n\t\tup.Normalize();\r\n\t\t\r\n\t\tXGMatrixLookAtRH( &view_matrix, (XGVECTOR3*)( &start[X] ), (XGVECTOR3*)( &end[X] ), (XGVECTOR3*)( &up[X] ));\r\n\t\tXGMatrixOrthoRH( &ortho_matrix, size, height, 0.1f, view_depth );\r\n\t}\r\n\telse if( fabsf( splat_vector[Y] ) > 0.5f )\r\n\t{\r\n\t\tfloat angle = ((float)rand() * 2.0f * Mth::PI ) / (float)RAND_MAX;\r\n\t\tup.Set( sinf( angle ), 0.0f, cosf( angle ));\r\n\t\tXGMatrixLookAtRH( &view_matrix, (XGVECTOR3*)( &start[X] ), (XGVECTOR3*)( &end[X] ), (XGVECTOR3*)( &up[X] ));\r\n\t\tXGMatrixOrthoRH( &ortho_matrix, size, size, 0.1f, view_depth );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tup.Set( 0.0f, 1.0f, 0.0f );\r\n\t\tXGMatrixLookAtRH( &view_matrix, (XGVECTOR3*)( &start[X] ), (XGVECTOR3*)( &end[X] ), (XGVECTOR3*)( &up[X] ));\r\n\t\tXGMatrixOrthoRH( &ortho_matrix, size, size, 0.1f, view_depth );\r\n\t}\r\n\r\n\tXGMatrixMultiply( &projection_matrix, &view_matrix, &ortho_matrix );\r\n\t\r\n\t// Pointer to the mesh we will be modifying. (Don't want to set the pointer up until we know for\r\n\t// sure that we will be adding some polys).\r\n\tsXboxSplatInstanceDetails\t*p_details\t\t= NULL;\r\n\tsXboxSplatVert\t\t\t\t*p_target_verts\t= NULL;\r\n\r\n\tNx::CSector *p_sector;\r\n\r\n\twhile( p_sector = *pp_sectors )\r\n\t{\r\n\t\tNx::CXboxGeom *p_xbox_geom = static_cast<Nx::CXboxGeom*>( p_sector->GetGeom());\r\n\r\n\t\tif( p_xbox_geom )\r\n\t\t{\r\n#\t\t\tif DRAW_DEBUG_LINES\r\n\t\t\tMth::Vector min = p_xbox_geom->GetBoundingBox().GetMin();\r\n\t\t\tMth::Vector max = p_xbox_geom->GetBoundingBox().GetMax();\r\n\r\n\t\t\tMth::Vector box[8];\r\n\t\t\tbox[0] = box[1] = box[2] = box[3] = max;\r\n\t\t\tbox[1][X] = min[X];\r\n\t\t\tbox[2][Y] = min[Y];\r\n\t\t\tbox[3][Z] = min[Z];\r\n\t\t\tbox[5] = box[6] = box[7] = box[4] = min;;\r\n\t\t\tbox[5][X] = max[X];\r\n\t\t\tbox[6][Y] = max[Y];\r\n\t\t\tbox[7][Z] = max[Z];\r\n\r\n\t\t\tfor ( int i = 1; i < 4; i++ )\r\n\t\t\t{\r\n\t\t\t\tGfx::AddDebugLine( box[0], box[i], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\t}\r\n\t\t\tfor ( int i = 5; i < 8; i++ )\r\n\t\t\t{\r\n\t\t\t\tGfx::AddDebugLine( box[4], box[i], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\t}\r\n\t\t\tGfx::AddDebugLine( box[1], box[6], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\tGfx::AddDebugLine( box[1], box[7], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\tGfx::AddDebugLine( box[2], box[5], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\tGfx::AddDebugLine( box[2], box[7], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\tGfx::AddDebugLine( box[3], box[5], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n\t\t\tGfx::AddDebugLine( box[3], box[6], MAKE_RGB( 200, 0, 0 ), MAKE_RGB( 200, 0, 0 ), 1 );\r\n#\t\t\tendif // DRAW_DEBUG_LINES\r\n\t\t\t\r\n\t\t\t// For each mesh in the geom...\r\n\t\t\tfor( uint32 m = 0; m < p_xbox_geom->m_num_mesh; ++m )\r\n\t\t\t{\r\n\t\t\t\tNxXbox::sMesh *p_mesh = p_xbox_geom->m_mesh_array[m];\r\n\r\n\t\t\t\t// Not allowed on meshes which are flagged not to shadow.\r\n\t\t\t\tif( p_mesh->m_flags & NxXbox::sMesh::MESH_FLAG_NO_SKATER_SHADOW )\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t// Check the bounding box of this mesh falls within the scope of the line.\r\n\t\t\t\t\r\n\t\t\t\t// Transform the mesh bounding box to see whether it falls within the projection frustum.\r\n\t\t\t\t\r\n\t\t\t\t// If it falls within the projection frustum, we need to explicitly transform all the vertices.\r\n\t\t\t\tBYTE *p_vert_data;\r\n\t\t\t\tp_mesh->mp_vertex_buffer[0]->Lock( 0, 0, &p_vert_data, D3DLOCK_READONLY );\r\n\t\t\t\t\r\n\t\t\t\t// Now scan through each non-degenerate tri, checking the verts to see if they are within scope.\r\n\t\t\t\tuint32 index0;\r\n\t\t\t\tuint32 index1 = p_mesh->mp_index_buffer[0][0];\r\n\t\t\t\tuint32 index2 = p_mesh->mp_index_buffer[0][1];\r\n\t\t\t\tfor( uint32 i = 2; i < p_mesh->m_num_indices[0]; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Wrap the indices round.\r\n\t\t\t\t\tindex0 = index1;\r\n\t\t\t\t\tindex1 = index2;\r\n\t\t\t\t\tindex2 = p_mesh->mp_index_buffer[0][i];\r\n\r\n\t\t\t\t\tif(( index0 != index1 ) && ( index0 != index2 ) && ( index1 != index2 ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tXGVECTOR3 uvprojections[3];\r\n\t\t\t\t\t\tXGVec3TransformCoord( &uvprojections[0], (XGVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index0 )), &projection_matrix );\r\n\t\t\t\t\t\tXGVec3TransformCoord( &uvprojections[1], (XGVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index1 )), &projection_matrix );\r\n\t\t\t\t\t\tXGVec3TransformCoord( &uvprojections[2], (XGVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index2 )), &projection_matrix );\r\n\r\n\t\t\t\t\t\t// Check the z-values here, everything else is checked in tri_texture_intersect().\r\n\t\t\t\t\t\tif(( uvprojections[0].z < 0.0f ) && ( uvprojections[1].z < 0.0f ) && ( uvprojections[2].z < 0.0f ))\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\tif(( uvprojections[0].z > 1.0f ) && ( uvprojections[1].z > 1.0f ) && ( uvprojections[2].z > 1.0f ))\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// Okay, this tri lies within the projection frustum. Now check that it intersects the texture\r\n\t\t\t\t\t\tif( !tri_texture_intersect( uvprojections[0].x, uvprojections[0].y,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tuvprojections[1].x, uvprojections[1].y,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tuvprojections[2].x, uvprojections[2].y ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// Get a pointer to the mesh used for rendering texture splats with the given texture.\r\n\t\t\t\t\t\t// (Note this will create a new instance to handle texture splats of this texture if one does not already exist).\r\n\t\t\t\t\t\tif( p_target_verts == NULL )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tCXboxTexture *p_xbox_texture\t= static_cast<CXboxTexture*>( p_texture );\r\n\t\t\t\t\t\t\tp_details\t\t\t\t\t\t= getDetailsForTextureSplat( p_xbox_texture->GetEngineTexture());\r\n\t\t\t\t\t\t\tp_target_verts\t\t\t\t\t= p_details->m_verts;\r\n\t\t\t\t\t\t\tDbg_Assert( p_target_verts );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// Scan through the lifetimes, finding a 'dead' poly (lifetime == 0), or the oldest.\r\n\t\t\t\t\t\tuint32 idx\t\t\t\t\t\t= p_details->GetOldestSplat();\r\n\r\n\t\t\t\t\t\t// Convert lifetime from seconds to milliseconds.\r\n\t\t\t\t\t\tp_details->m_lifetimes[idx]\t\t= (int)( lifetime * 1000.0f );\r\n\r\n\t\t\t\t\t\t// Set up the corresponding vertices. First write the positions...\r\n\t\t\t\t\t\tuint32 index\t\t\t\t\t= idx * 3;\r\n\t\t\t\t\t\tp_target_verts[index + 0].pos\t= *(D3DXVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index0 ));\r\n\t\t\t\t\t\tp_target_verts[index + 1].pos\t= *(D3DXVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index1 ));\r\n\t\t\t\t\t\tp_target_verts[index + 2].pos\t= *(D3DXVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index2 ));\r\n\r\n\t\t\t\t\t\t// ...then the uv's...\r\n\t\t\t\t\t\tp_target_verts[index + 0].u\t\t= ( uvprojections[0].x + 1.0f ) * 0.5f;\r\n\t\t\t\t\t\tp_target_verts[index + 0].v\t\t= ( uvprojections[0].y + 1.0f ) * 0.5f;\r\n\t\t\t\t\t\tp_target_verts[index + 1].u\t\t= ( uvprojections[1].x + 1.0f ) * 0.5f;\r\n\t\t\t\t\t\tp_target_verts[index + 1].v\t\t= ( uvprojections[1].y + 1.0f ) * 0.5f;\r\n\t\t\t\t\t\tp_target_verts[index + 2].u\t\t= ( uvprojections[2].x + 1.0f ) * 0.5f;\r\n\t\t\t\t\t\tp_target_verts[index + 2].v\t\t= ( uvprojections[2].y + 1.0f ) * 0.5f;\r\n\r\n\t\t\t\t\t\t// ...then the vertex colors.\r\n\t\t\t\t\t\tp_target_verts[index + 0].col\t= ( *(D3DCOLOR*)( p_vert_data + ( p_mesh->m_vertex_stride * index0 ) + p_mesh->m_diffuse_offset ) & 0xFFFFFFUL ) | 0x80000000UL;\r\n\t\t\t\t\t\tp_target_verts[index + 1].col\t= ( *(D3DCOLOR*)( p_vert_data + ( p_mesh->m_vertex_stride * index1 ) + p_mesh->m_diffuse_offset ) & 0xFFFFFFUL ) | 0x80000000UL;\r\n\t\t\t\t\t\tp_target_verts[index + 2].col\t= ( *(D3DCOLOR*)( p_vert_data + ( p_mesh->m_vertex_stride * index2 ) + p_mesh->m_diffuse_offset ) & 0xFFFFFFUL ) | 0x80000000UL;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tD3DXVECTOR3\t*p_v0 = &( p_target_verts[index + 0].pos );\r\n\t\t\t\t\t\tD3DXVECTOR3\t*p_v1 = &( p_target_verts[index + 1].pos );\r\n\t\t\t\t\t\tD3DXVECTOR3\t*p_v2 = &( p_target_verts[index + 2].pos );\r\n\t\t\t\t\t\tMth::Vector pv(\tp_v1->x - p_v0->x, p_v1->y - p_v0->y, p_v1->z - p_v0->z );\r\n\t\t\t\t\t\tMth::Vector qv(\tp_v2->x - p_v0->x, p_v2->y - p_v0->y, p_v2->z - p_v0->z );\r\n\t\t\t\t\t\tMth::Vector r(( pv[Y] * qv[Z] ) - ( qv[Y] * pv[Z] ), ( pv[Z] * qv[X] ) - ( qv[Z] * pv[X] ), ( pv[X] * qv[Y] ) - ( qv[X] * pv[Y] ));\r\n\t\t\t\t\t\tfloat area_squared = r.LengthSqr();\r\n\r\n\t\t\t\t\t\t// Set the shatter test to ensure that we don't subdivide too far. Note that each successive subdivision will quarter\r\n\t\t\t\t\t\t// the area of each triangle, which means the area *squared* of each triangle will become 1/16th of the previous value.\r\n\t\t\t\t\t\tshatterAreaTest = area_squared / 128.0f;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\ttriSubdivideStack.Reset();\r\n\t\t\t\t\t\ttriSubdivideStack.SetBlockSize( sizeof( sXboxSplatVert ));\r\n\t\t\t\t\t\ttriSubdivideStack.Push( &p_target_verts[index + 0] );\r\n\t\t\t\t\t\ttriSubdivideStack.Push( &p_target_verts[index + 1] );\r\n\t\t\t\t\t\ttriSubdivideStack.Push( &p_target_verts[index + 2] );\r\n\r\n\t\t\t\t\t\t// Allocate a block of memory into which the subdivision stack will write the results.\r\n\t\t\t\t\t\tuint8\t\t\t*p_array\t\t= new uint8[8 * 1024];\r\n\t\t\t\t\t\tuint8\t\t\t*p_array_start\t= p_array;\r\n\t\t\t\t\t\tuint8\t\t\t*p_array_loop\t= p_array;\r\n\t\t\t\t\t\tmemset( p_array, 0, 8 * 1024 );\r\n\r\n\t\t\t\t\t\tNxXbox::sMesh\t*p_dummy_mesh\t= new NxXbox::sMesh();\r\n\t\t\t\t\t\tp_dummy_mesh->m_diffuse_offset\t= 12;\r\n\t\t\t\t\t\tp_dummy_mesh->m_uv0_offset\t\t= 16;\r\n\r\n\t\t\t\t\t\twhile( subdivide_tri_stack( &p_array, p_dummy_mesh ));\r\n\r\n\t\t\t\t\t\t// Ensure we haven't overrun the buffer.\r\n\t\t\t\t\t\tDbg_Assert((uint32)p_array - (uint32)p_array_loop < ( 8 * 1024 ));\r\n\r\n\t\t\t\t\t\tbool subdivided_tri_added = false;\r\n\r\n\t\t\t\t\t\twhile( p_array_loop != p_array )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Add this triangle, *if* it is valid.\r\n\t\t\t\t\t\t\tif( tri_texture_intersect((((sXboxSplatVert*)p_array_loop )[0].u * 2.0f ) - 1.0f,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  (((sXboxSplatVert*)p_array_loop )[0].v * 2.0f ) - 1.0f,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  (((sXboxSplatVert*)p_array_loop )[1].u * 2.0f ) - 1.0f,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  (((sXboxSplatVert*)p_array_loop )[1].v * 2.0f ) - 1.0f,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  (((sXboxSplatVert*)p_array_loop )[2].u * 2.0f ) - 1.0f,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  (((sXboxSplatVert*)p_array_loop )[2].v * 2.0f ) - 1.0f ))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// We have added at least one subdivided tri.\r\n\t\t\t\t\t\t\t\tsubdivided_tri_added = true;\r\n\r\n\t\t\t\t\t\t\t\t// Convert lifetime from seconds to milliseconds.\r\n\t\t\t\t\t\t\t\tp_details->m_lifetimes[idx]\t\t= (int)( lifetime * 1000.0f );\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tp_target_verts[index + 0].pos\t= ((sXboxSplatVert*)p_array_loop )[0].pos;\r\n\t\t\t\t\t\t\t\tp_target_verts[index + 1].pos\t= ((sXboxSplatVert*)p_array_loop )[1].pos;\r\n\t\t\t\t\t\t\t\tp_target_verts[index + 2].pos\t= ((sXboxSplatVert*)p_array_loop )[2].pos;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tp_target_verts[index + 0].u\t\t= ((sXboxSplatVert*)p_array_loop )[0].u;\r\n\t\t\t\t\t\t\t\tp_target_verts[index + 0].v\t\t= ((sXboxSplatVert*)p_array_loop )[0].v;\r\n\t\t\t\t\t\t\t\tp_target_verts[index + 1].u\t\t= ((sXboxSplatVert*)p_array_loop )[1].u;\r\n\t\t\t\t\t\t\t\tp_target_verts[index + 1].v\t\t= ((sXboxSplatVert*)p_array_loop )[1].v;\r\n\t\t\t\t\t\t\t\tp_target_verts[index + 2].u\t\t= ((sXboxSplatVert*)p_array_loop )[2].u;\r\n\t\t\t\t\t\t\t\tp_target_verts[index + 2].v\t\t= ((sXboxSplatVert*)p_array_loop )[2].v;\r\n\r\n\t\t\t\t\t\t\t\tp_target_verts[index + 0].col\t= (((sXboxSplatVert*)p_array_loop )[0].col & 0xFFFFFFUL ) | 0x80000000UL;\r\n\t\t\t\t\t\t\t\tp_target_verts[index + 1].col\t= (((sXboxSplatVert*)p_array_loop )[1].col & 0xFFFFFFUL ) | 0x80000000UL;\r\n\t\t\t\t\t\t\t\tp_target_verts[index + 2].col\t= (((sXboxSplatVert*)p_array_loop )[2].col & 0xFFFFFFUL ) | 0x80000000UL;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tidx\t\t\t\t\t\t\t\t= p_details->GetOldestSplat();\r\n\t\t\t\t\t\t\t\tindex\t\t\t\t\t\t\t= idx * 3;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tp_array_loop\t\t\t\t\t\t+= ( sizeof( sXboxSplatVert ) * 3 );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif( !subdivided_tri_added )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// No subdivided tris were added. This means we still have the large tri sitting in the list, which we don't want.\r\n\t\t\t\t\t\t\tp_details->m_lifetimes[idx]\t\t\t= 0;\r\n\t\t\t\t\t\t\tplat_texture_splat_reset_poly( p_details, idx );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tdelete p_dummy_mesh;\r\n\t\t\t\t\t\tdelete [] p_array_start;\r\n\r\n#\t\t\t\t\t\tif DRAW_DEBUG_LINES\r\n\t\t\t\t\t\tD3DXVECTOR3* p_d3dvert;\r\n\t\t\t\t\t\tp_d3dvert = (D3DXVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index0 ));\r\n\t\t\t\t\t\tMth::Vector v0( p_d3dvert->x, p_d3dvert->y, p_d3dvert->z );\r\n\t\t\t\t\t\tp_d3dvert = (D3DXVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index1 ));\r\n\t\t\t\t\t\tMth::Vector v1( p_d3dvert->x, p_d3dvert->y, p_d3dvert->z );\r\n\t\t\t\t\t\tp_d3dvert = (D3DXVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index2 ));\r\n\t\t\t\t\t\tMth::Vector v2( p_d3dvert->x, p_d3dvert->y, p_d3dvert->z );\r\n\t\t\t\t\t\tGfx::AddDebugLine( v0, v1, MAKE_RGB( 0, 200, 200 ), MAKE_RGB( 0, 200, 200 ), 1 );\r\n\t\t\t\t\t\tGfx::AddDebugLine( v1, v2, MAKE_RGB( 0, 200, 200 ), MAKE_RGB( 0, 200, 200 ), 1 );\r\n\t\t\t\t\t\tGfx::AddDebugLine( v2, v0, MAKE_RGB( 0, 200, 200 ), MAKE_RGB( 0, 200, 200 ), 1 );\r\n#\t\t\t\t\t\tendif // DRAW_DEBUG_LINES\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t++pp_sectors;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_texture_splat_render( void )\r\n{\r\n\tsXboxSplatInstanceDetails *p_xbox_details;\r\n\r\n\tDbg_Assert( p_splat_details_table );\r\n\r\n\tNxXbox::set_pixel_shader( 0 );\t\r\n\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2( 0 ));\r\n\t\r\n\tD3DDevice_SetTextureStageState( 0, D3DTSS_BORDERCOLOR, 0x00000000UL );\r\n\r\n\t// Store the stage zero minfilter, since it may be anisotropic.\r\n\tDWORD stage_zero_minfilter;\r\n\tD3DDevice_GetTextureStageState( 0, D3DTSS_MINFILTER, &stage_zero_minfilter );\r\n\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );\r\n\r\n\tp_splat_details_table->IterateStart();\r\n\tsSplatInstanceDetails *p_details = p_splat_details_table->IterateNext();\r\n\t\r\n\twhile( p_details )\r\n\t{\r\n\t\tp_xbox_details = static_cast<sXboxSplatInstanceDetails*>( p_details );\r\n\r\n\t\tif( p_xbox_details->m_highest_active_splat >= 0 )\r\n\t\t{\r\n\t\t\tp_xbox_details->mp_material->Submit();\r\n\t\t\tNxXbox::EngineGlobals.p_Device->DrawPrimitiveUP( D3DPT_TRIANGLELIST, p_xbox_details->m_highest_active_splat + 1, p_xbox_details->m_verts, sizeof( sXboxSplatVert ));\r\n\t\t}\r\n\t\t\r\n\t\tp_details = p_splat_details_table->IterateNext();\r\n\t}\r\n\r\n\t// Restore the stage zero minfilter.\r\n\tD3DDevice_SetTextureStageState( 0, D3DTSS_MINFILTER, stage_zero_minfilter );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_shatter_initialize( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_shatter_cleanup( void )\r\n{\r\n\tsXboxShatterInstanceDetails *p_xbox_details;\r\n\r\n\tDbg_Assert( p_shatter_details_table );\r\n\t\r\n\tp_shatter_details_table->IterateStart();\r\n\tsShatterInstanceDetails *p_details = p_shatter_details_table->IterateNext();\r\n\twhile( p_details )\r\n\t{\r\n\t\tp_xbox_details = static_cast<sXboxShatterInstanceDetails*>( p_details );\r\n\t\t\r\n\t\tp_details = p_shatter_details_table->IterateNext();\r\n\r\n\t\tp_shatter_details_table->FlushItem((uint32)p_xbox_details );\r\n\t\tdelete p_xbox_details;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid plat_shatter( CGeom *p_geom )\r\n{\r\n\tCXboxGeom *p_xbox_geom = static_cast<CXboxGeom*>( p_geom );\r\n\r\n\t// For each mesh in the geom...\r\n\tfor( uint32 m = 0; m < p_xbox_geom->m_num_mesh; ++m )\r\n\t{\r\n\t\tNxXbox::sMesh *p_mesh = p_xbox_geom->m_mesh_array[m];\r\n\r\n\t\tif( p_mesh->m_num_indices[0] >= 3 )\r\n\t\t{\r\n\t\t\t// Set the block size for this mesh.\r\n\t\t\ttriSubdivideStack.SetBlockSize( p_mesh->m_vertex_stride );\r\n\t\t\t\r\n\t\t\t// Get a pointer to the renderable data.\r\n\t\t\tBYTE *p_vert_data;\r\n\t\t\tp_mesh->mp_vertex_buffer[0]->Lock( 0, 0, &p_vert_data, D3DLOCK_READONLY );\r\n\t\t\t\t\r\n\t\t\t// First scan through each non-degenerate tri, counting them to see how many verts we'll need.\r\n\t\t\t// We also have to figure the area of the tris here, since we need to calculate the worst case given the requirements for subdivision.\r\n\t\t\tuint32 valid_tris\t= 0;\r\n\t\t\tuint32 index0;\r\n\t\t\tuint32 index1\t\t= p_mesh->mp_index_buffer[0][0];\r\n\t\t\tuint32 index2\t\t= p_mesh->mp_index_buffer[0][1];\r\n\t\t\tfor( uint32 i = 2; i < p_mesh->m_num_indices[0]; ++i )\r\n\t\t\t{\r\n\t\t\t\t// Wrap the indices round.\r\n\t\t\t\tindex0 = index1;\r\n\t\t\t\tindex1 = index2;\r\n\t\t\t\tindex2 = p_mesh->mp_index_buffer[0][i];\r\n\r\n\t\t\t\tif(( index0 != index1 ) && ( index0 != index2 ) && ( index1 != index2 ))\r\n\t\t\t\t{\r\n\t\t\t\t\t++valid_tris;\r\n\r\n\t\t\t\t\tD3DXVECTOR3 *p_vert0 = (D3DXVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index0 ));\r\n\t\t\t\t\tD3DXVECTOR3 *p_vert1 = (D3DXVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index1 ));\r\n\t\t\t\t\tD3DXVECTOR3 *p_vert2 = (D3DXVECTOR3*)( p_vert_data + ( p_mesh->m_vertex_stride * index2 ));\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Push this tri onto the stack.\r\n\t\t\t\t\ttriSubdivideStack.Push( p_vert0 );\r\n\t\t\t\t\ttriSubdivideStack.Push( p_vert1 );\r\n\t\t\t\t\ttriSubdivideStack.Push( p_vert2 );\r\n\r\n\t\t\t\t\t// Figure the area of this tri.\r\n\t\t\t\t\tMth::Vector p(\tp_vert1->x - p_vert0->x, p_vert1->y - p_vert0->y, p_vert1->z - p_vert0->z );\r\n\t\t\t\t\tMth::Vector q(\tp_vert2->x - p_vert0->x, p_vert2->y - p_vert0->y, p_vert2->z - p_vert0->z );\r\n\t\t\t\t\tMth::Vector r(( p[Y] * q[Z] ) - ( q[Y] * p[Z] ), ( p[Z] * q[X] ) - ( q[Z] * p[X] ), ( p[X] * q[Y] ) - ( q[X] * p[Y] ));\r\n\t\t\t\t\tfloat area_squared = r.LengthSqr();\r\n\t\t\t\t\tif( area_squared > shatterAreaTest )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// We will need to subdivide - each subdivision will result in an area one quarter the previous area\r\n\t\t\t\t\t\t// (and thusly the square of the area will be one sixteenth the previous area).\r\n\t\t\t\t\t\tint num_extra_tris = 1;\r\n\t\t\t\t\t\twhile( area_squared > shatterAreaTest )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnum_extra_tris *= 4;\r\n\t\t\t\t\t\t\tarea_squared *= ( 1.0f / 16.0f );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t// This original tri will not be added...\r\n\t\t\t\t\t\t--valid_tris;\r\n\r\n\t\t\t\t\t\t// ...however, the subdivided versions will.\r\n\t\t\t\t\t\tvalid_tris += num_extra_tris;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif( valid_tris == 0 )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Create a tracking structure for this mesh.\r\n\t\t\tsXboxShatterInstanceDetails *p_details\t\t= new sXboxShatterInstanceDetails( valid_tris, p_mesh );\r\n\t\t\tuint8\t\t\t\t\t\t*p_write_vertex\t= p_details->mp_vertex_buffer;\r\n\t\t\tuint32\t\t\t\t\t\tdetails_index\t= 0;\r\n\r\n\t\t\tMth::Vector\t\t\t\t\tspread_center\t= shatterVelocity * -shatterSpreadFactor;\r\n\t\t\tfloat\t\t\t\t\t\tbase_speed\t\t= shatterVelocity.Length();\r\n\r\n\t\t\tspread_center += Mth::Vector( p_mesh->m_sphere_center.x, p_mesh->m_sphere_center.y, p_mesh->m_sphere_center.z );\r\n\t\t\t\r\n\t\t\t// Add the tracking structure to the table.\r\n\t\t\tp_shatter_details_table->PutItem((uint32)p_details, p_details );\r\n\t\t\t\r\n\t\t\t// Process-subdivide the entire stack.\r\n\t\t\tuint8 *p_copy_vertex = p_write_vertex;\r\n\t\t\twhile( subdivide_tri_stack( &p_write_vertex, p_mesh ));\r\n\t\t\t\t\t\r\n\t\t\t// Copy the (possibly subdivided) vertex data over.\r\n\t\t\tDbg_Assert(((uint32)p_write_vertex - (uint32)p_copy_vertex ) <= ( valid_tris * 3 * p_mesh->m_vertex_stride ));\r\n\t\t\twhile( p_copy_vertex < p_write_vertex )\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( details_index < valid_tris );\r\n\t\t\t\t\r\n\t\t\t\tD3DXVECTOR3 *p_vert0 = (D3DXVECTOR3*)( p_copy_vertex + ( p_mesh->m_vertex_stride * 0 ));\r\n\t\t\t\tD3DXVECTOR3 *p_vert1 = (D3DXVECTOR3*)( p_copy_vertex + ( p_mesh->m_vertex_stride * 1 ));\r\n\t\t\t\tD3DXVECTOR3 *p_vert2 = (D3DXVECTOR3*)( p_copy_vertex + ( p_mesh->m_vertex_stride * 2 ));\r\n\r\n\t\t\t\t// Calculate position as the midpoint of the three vertices per poly.\r\n\t\t\t\tp_details->mp_positions[details_index][X] = ( p_vert0->x + p_vert1->x + p_vert2->x ) * ( 1.0f / 3.0f );\r\n\t\t\t\tp_details->mp_positions[details_index][Y] = ( p_vert0->y + p_vert1->y + p_vert2->y ) * ( 1.0f / 3.0f );\r\n\t\t\t\tp_details->mp_positions[details_index][Z] = ( p_vert0->z + p_vert1->z + p_vert2->z ) * ( 1.0f / 3.0f );\r\n\r\n\t\t\t\t// Calculate the vector <velocity> back from the bounding box of the object. Then use this to figure the 'spread' of the\r\n\t\t\t\t// shards by calculating the vector from this position to the center of each shard.\r\n\t\t\t\tfloat speed = base_speed + ( base_speed * (( shatterVelocityVariance * rand() ) / RAND_MAX ));\r\n\t\t\t\tp_details->mp_velocities[details_index] = ( p_details->mp_positions[details_index] - spread_center ).Normalize( speed );\r\n\r\n\t\t\t\tMth::Vector axis( -1.0f + ( 2.0f * (float)rand() / RAND_MAX ), -1.0f + ( 2.0f * (float)rand() / RAND_MAX ), -1.0f + ( 2.0f * (float)rand() / RAND_MAX ));\r\n\t\t\t\taxis.Normalize();\r\n\t\t\t\tp_details->mp_matrices[details_index].Ident();\r\n\t\t\t\tp_details->mp_matrices[details_index].Rotate( axis, 0.1f * ((float)rand() / RAND_MAX ));\r\n\r\n\t\t\t\tp_copy_vertex += ( p_mesh->m_vertex_stride * 3 );\r\n\t\t\t\t\t\t\r\n\t\t\t\t++details_index;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************************\r\n *\r\n * \r\n *****************************************************************************/\r\nvoid plat_shatter_update( sShatterInstanceDetails *p_details, float framelength )\r\n{\r\n\tsXboxShatterInstanceDetails *p_xbox_details = static_cast<sXboxShatterInstanceDetails*>( p_details );\r\n\t\r\n\tBYTE *p_vert_data = p_xbox_details->mp_vertex_buffer;\r\n\t\r\n\t// Load up initial three vertex pointers.\r\n\tD3DXVECTOR3 *p_v0\t= (D3DXVECTOR3*)( p_vert_data );\r\n\tD3DXVECTOR3 *p_v1\t= (D3DXVECTOR3*)( p_vert_data + p_xbox_details->mp_mesh->m_vertex_stride );\r\n\tD3DXVECTOR3 *p_v2\t= (D3DXVECTOR3*)( p_vert_data + ( 2 * p_xbox_details->mp_mesh->m_vertex_stride ));\r\n\t\r\n\tfor( int i = 0; i < p_details->m_num_triangles; ++i )\r\n\t{\r\n\t\t// To move the shatter pieces:\r\n\t\t// 1) subtract position from each vertex\r\n\t\t// 2) rotate\r\n\t\t// 3) update position with velocity\r\n\t\t// 4) add new position to each vertex\r\n\r\n\t\t// The matrix holds 3 vectors at once.\r\n\t\tMth::Matrix m;\r\n\t\tm[X].Set( p_v0->x - p_details->mp_positions[i][X], p_v0->y - p_details->mp_positions[i][Y], p_v0->z - p_details->mp_positions[i][Z] );\r\n\t\tm[Y].Set( p_v1->x - p_details->mp_positions[i][X], p_v1->y - p_details->mp_positions[i][Y], p_v1->z - p_details->mp_positions[i][Z] );\r\n\t\tm[Z].Set( p_v2->x - p_details->mp_positions[i][X], p_v2->y - p_details->mp_positions[i][Y], p_v2->z - p_details->mp_positions[i][Z] );\r\n         \r\n\t\tm[X].Rotate( p_details->mp_matrices[i] );\r\n\t\tm[Y].Rotate( p_details->mp_matrices[i] );\r\n\t\tm[Z].Rotate( p_details->mp_matrices[i] );\r\n\r\n\t\t// Update the position and velocity of the shatter piece, dealing with bouncing if necessary.\r\n\t\tp_details->UpdateParameters( i, framelength );\r\n      \r\n\t\tm[X] += p_details->mp_positions[i]; \r\n\t\tm[Y] += p_details->mp_positions[i]; \r\n\t\tm[Z] += p_details->mp_positions[i];\r\n\r\n\t\tp_v0->x = m[X][X]; p_v0->y = m[X][Y]; p_v0->z = m[X][Z];\r\n\t\tp_v1->x = m[Y][X]; p_v1->y = m[Y][Y]; p_v1->z = m[Y][Z];\r\n\t\tp_v2->x = m[Z][X]; p_v2->y = m[Z][Y]; p_v2->z = m[Z][Z];\r\n\r\n\t\tp_v0 = (D3DXVECTOR3*)(((BYTE*)p_v0 ) + ( p_xbox_details->mp_mesh->m_vertex_stride * 3 ));\r\n\t\tp_v1 = (D3DXVECTOR3*)(((BYTE*)p_v1 ) + ( p_xbox_details->mp_mesh->m_vertex_stride * 3 ));\r\n\t\tp_v2 = (D3DXVECTOR3*)(((BYTE*)p_v2 ) + ( p_xbox_details->mp_mesh->m_vertex_stride * 3 ));\r\n\t}\r\n\r\n\t// Also process normals if they exist.\r\n\tif( p_xbox_details->mp_mesh->m_normal_offset > 0 )\r\n\t{\r\n\t\tp_v0\t= (D3DXVECTOR3*)( p_vert_data + p_xbox_details->mp_mesh->m_normal_offset );\r\n\t\tp_v1\t= (D3DXVECTOR3*)( p_vert_data + p_xbox_details->mp_mesh->m_normal_offset + p_xbox_details->mp_mesh->m_vertex_stride );\r\n\t\tp_v2\t= (D3DXVECTOR3*)( p_vert_data + p_xbox_details->mp_mesh->m_normal_offset + ( 2 * p_xbox_details->mp_mesh->m_vertex_stride ));\r\n\t\r\n\t\tfor( int i = 0; i < p_details->m_num_triangles; ++i )\r\n\t\t{\r\n\t\t\t// The matrix holds 3 vectors at once.\r\n\t\t\tMth::Matrix m;\r\n\t\t\tm[X].Set( p_v0->x, p_v0->y, p_v0->z );\r\n\t\t\tm[Y].Set( p_v1->x, p_v1->y, p_v1->z );\r\n\t\t\tm[Z].Set( p_v2->x, p_v2->y, p_v2->z );\r\n         \r\n\t\t\tm[X].Rotate( p_details->mp_matrices[i] );\r\n\t\t\tm[Y].Rotate( p_details->mp_matrices[i] );\r\n\t\t\tm[Z].Rotate( p_details->mp_matrices[i] );\r\n\r\n\t\t\tp_v0->x = m[X][X]; p_v0->y = m[X][Y]; p_v0->z = m[X][Z];\r\n\t\t\tp_v1->x = m[Y][X]; p_v1->y = m[Y][Y]; p_v1->z = m[Y][Z];\r\n\t\t\tp_v2->x = m[Z][X]; p_v2->y = m[Z][Y]; p_v2->z = m[Z][Z];\r\n\r\n\t\t\tp_v0 = (D3DXVECTOR3*)(((BYTE*)p_v0 ) + ( p_xbox_details->mp_mesh->m_vertex_stride * 3 ));\r\n\t\t\tp_v1 = (D3DXVECTOR3*)(((BYTE*)p_v1 ) + ( p_xbox_details->mp_mesh->m_vertex_stride * 3 ));\r\n\t\t\tp_v2 = (D3DXVECTOR3*)(((BYTE*)p_v2 ) + ( p_xbox_details->mp_mesh->m_vertex_stride * 3 ));\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************************\r\n *\r\n * \r\n *****************************************************************************/\r\nvoid plat_shatter_render( sShatterInstanceDetails *p_details )\r\n{\r\n\tsXboxShatterInstanceDetails *p_xbox_details = static_cast<sXboxShatterInstanceDetails*>( p_details );\r\n\r\n\tp_xbox_details->mp_mesh->mp_material->Submit();\r\n\r\n\tNxXbox::set_pixel_shader( p_xbox_details->mp_mesh->m_pixel_shader );\r\n\tNxXbox::set_vertex_shader( p_xbox_details->mp_mesh->m_vertex_shader[0] );\r\n\r\n\tNxXbox::EngineGlobals.p_Device->DrawPrimitiveUP( D3DPT_TRIANGLELIST, p_xbox_details->m_num_triangles, p_xbox_details->mp_vertex_buffer, p_xbox_details->mp_mesh->m_vertex_stride );\r\n}\r\n\r\n\t\r\n///////////////////////////////////////////////////////////////////\r\n//\r\n// FOG\r\n//\r\n///////////////////////////////////////////////////////////////////\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CFog::s_plat_enable_fog( bool enable )\r\n{\r\n\tif( enable != (bool)NxXbox::EngineGlobals.fog_enabled )\r\n\t{\r\n\t\tNxXbox::EngineGlobals.fog_enabled = enable;\r\n\t\tD3DDevice_SetRenderState( D3DRS_FOGENABLE, NxXbox::EngineGlobals.fog_enabled );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CFog::s_plat_set_fog_near_distance( float distance )\r\n{\r\n\tNxXbox::EngineGlobals.fog_start\t= -distance;\r\n\r\n\t// Test code for now.\r\n\tNxXbox::EngineGlobals.fog_end\t= NxXbox::EngineGlobals.fog_start - FEET_TO_INCHES( 600.0f );\r\n\r\n\tD3DDevice_SetRenderState( D3DRS_FOGSTART,\t*((DWORD*)( &NxXbox::EngineGlobals.fog_start )));\r\n\tD3DDevice_SetRenderState( D3DRS_FOGEND,\t\t*((DWORD*)( &NxXbox::EngineGlobals.fog_end )));\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CFog::s_plat_set_fog_exponent( float exponent )\r\n{\r\n\t// This is no longer a valid call.\r\n//\tif( exponent > 0.0f )\r\n//\t{\r\n//\t\ts_plat_enable_fog( true );\r\n//\r\n//\t\tNxXbox::EngineGlobals.fog_start\t\t\t\t= FEET_TO_INCHES( -20.0f );\r\n//\t\tNxXbox::EngineGlobals.fog_end\t\t\t\t= FEET_TO_INCHES( -60.0f );\r\n//\t\tD3DDevice_SetRenderState( D3DRS_FOGSTART,\t*((DWORD*)( &NxXbox::EngineGlobals.fog_start )));\r\n//\t\tD3DDevice_SetRenderState( D3DRS_FOGEND,\t\t*((DWORD*)( &NxXbox::EngineGlobals.fog_end )));\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\ts_plat_enable_fog( false );\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CFog::s_plat_set_fog_color( void )\r\n{\r\n}\r\n\t\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CFog::s_plat_fog_update( void )\r\n{\r\n}\r\n\t\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CFog::s_plat_set_fog_rgba( Image::RGBA rgba )\r\n{\r\n\t// Alpha effectively determines the fog density, with zero alpha meaning no fog.\r\n\tif( rgba.a == 0 )\r\n\t{\r\n\t\ts_plat_enable_fog( false );\r\n\t}\r\n\telse\r\n\t{\r\n\t\ts_plat_enable_fog( true );\r\n\t}\r\n\r\n\t// Calculate alpha (and clamp between 0.0 and 1.0).\r\n\tfloat f_alpha = (float)rgba.a / 128.0f;\r\n\tf_alpha = Mth::Min( f_alpha, 1.0f );\r\n\tf_alpha = Mth::Max( f_alpha, 0.0f );\r\n\r\n\t// Set the density register in the pixel shader constants (uses c4.r/g/b).\r\n\tNxXbox::EngineGlobals.pixel_shader_constants[16] = f_alpha;\r\n\tNxXbox::EngineGlobals.pixel_shader_constants[17] = f_alpha;\r\n\tNxXbox::EngineGlobals.pixel_shader_constants[18] = f_alpha;\r\n\r\n\tNxXbox::EngineGlobals.fog_color\t= ((uint32)rgba.r << 16 ) | ((uint32)rgba.g << 8 ) | ((uint32)rgba.b );\r\n\tD3DDevice_SetRenderState( D3DRS_FOGCOLOR, NxXbox::EngineGlobals.fog_color );\r\n}\r\n\r\n} // Nx\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxnewparticle.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_NxNewParticle.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/25/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXbox new parametric particle system\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gfx/xbox/p_nxnewparticle.h>\r\n\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/xbox/p_nxtexture.h>\r\n#include <gfx/xbox/nx/nx_init.h>\r\n#include <gfx/xbox/nx/render.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic int rand_seed;\r\nstatic int rand_a\t= 314159265;\r\nstatic int rand_b\t= 178453311;\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void seed_particle_rnd( int s, int a, int b )\r\n{\r\n\trand_seed\t\t= s;\r\n\trand_a\t\t\t= a;\r\n\trand_b\t\t\t= b;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic inline int particle_rnd( int n )\r\n{\r\n\trand_seed\t= rand_seed * rand_a + rand_b;\r\n\trand_a\t\t= ( rand_a ^ rand_seed ) + ( rand_seed >> 4 );\r\n\trand_b\t\t+= ( rand_seed >> 3 ) - 0x10101010L;\r\n\treturn (int)(( rand_seed & 0xffff ) * n ) >> 16;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CParticleStream::AdvanceSeed( int num_places )\r\n{\r\n\t// Seed the random number generator back to the current seed.\r\n\tseed_particle_rnd( m_rand_seed, m_rand_a, m_rand_b );\r\n\r\n\t// Each particle will call the random function four times.\r\n\tfor( int i = 0; i < ( num_places * 4 ); i++ )\r\n\t{\r\n\t\trand_seed\t= rand_seed * rand_a + rand_b;\r\n\t\trand_a\t\t= ( rand_a ^ rand_seed ) + ( rand_seed >> 4 );\r\n\t\trand_b\t\t+= ( rand_seed >> 3 ) - 0x10101010L;\r\n\t}\r\n\r\n\tm_rand_seed = rand_seed;\r\n\tm_rand_a\t= rand_a;\r\n\tm_rand_b\t= rand_b;\r\n}\r\n\t\r\n\t\r\n\t\r\ninline DWORD FtoDW( FLOAT f ) { return *((DWORD*)&f); }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxNewParticle::plat_render( void )\r\n{\r\n\tCParticleStream* p_stream;\r\n\tint i;\r\n\r\n\t// Process the streams.\r\n\tif( m_params.m_EmitRate && ( !m_emitting || ( m_params.m_EmitRate != mp_newest_stream->m_rate )))\r\n\t{\t\r\n\t\tif( m_num_streams < m_max_streams )\r\n\t\t{\r\n\t\t\t// Add new stream to cyclic buffer\r\n\t\t\tm_num_streams++;\r\n\t\t\tmp_newest_stream++;\r\n\t\t\tif( mp_newest_stream == mp_stream + m_max_streams )\r\n\t\t\t{\r\n\t\t\t\tmp_newest_stream = mp_stream;\r\n\t\t\t}\r\n\r\n\t\t\t// Initialise new stream.\r\n\t\t\tmp_newest_stream->m_rate\t\t\t= m_params.m_EmitRate;\r\n\t\t\tmp_newest_stream->m_interval\t\t= 1.0f / m_params.m_EmitRate;\r\n\t\t\tmp_newest_stream->m_oldest_age\t\t= 0.0f;\r\n\t\t\tmp_newest_stream->m_num_particles\t= 0;\r\n\t\t\tmp_newest_stream->m_rand_seed\t\t= rand();\r\n\t\t\tmp_newest_stream->m_rand_a\t\t\t= 314159265;\r\n\t\t\tmp_newest_stream->m_rand_b\t\t\t= 178453311;\r\n\t\t\tm_emitting = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_emitting = false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_emitting = m_params.m_EmitRate;\r\n\t}\r\n\r\n\tif( !m_num_streams )\r\n\t\treturn;\r\n\r\n\t// Age all streams.\r\n\tfor( i = 0, p_stream = mp_oldest_stream; i < m_num_streams; ++i )\r\n\t{\r\n\t\t// Increase age of oldest particle.\r\n\t\tp_stream->m_oldest_age += 1.0f / 60.0f;\r\n\r\n\t\t// Step pointer within cyclic buffer.\r\n\t\tp_stream++;\r\n\t\tif( p_stream == mp_stream + m_max_streams )\r\n\t\t{\r\n\t\t\tp_stream = mp_stream;\r\n\t\t}\r\n\t}\r\n\r\n\t// Births into newest stream.\r\n\tif( m_emitting )\r\n\t{\r\n\t\t// How many particles so far emitted?\r\n\t\tmp_newest_stream->m_num_particles = (int)( mp_newest_stream->m_oldest_age * mp_newest_stream->m_rate + 1.0f );\r\n\t}\r\n\r\n\t// Deaths from oldest stream.\r\n\tif( mp_oldest_stream->m_oldest_age > m_params.m_Lifetime )\r\n\t{\r\n\t\t// Work out number dead.\r\n\t\tint particles_dead = (int)(( mp_oldest_stream->m_oldest_age - m_params.m_Lifetime ) * mp_oldest_stream->m_rate + 1.0f );\r\n\r\n\t\t// Remove dead particles.\r\n\t\tmp_oldest_stream->m_num_particles -= particles_dead;\r\n\r\n\t\t// Should we keep processing the oldest stream?\r\n\t\tif( mp_oldest_stream->m_num_particles > 0 || ( m_num_streams == 1 && m_emitting ))\r\n\t\t{\r\n\t\t\t// Adjust age of oldest particle.\r\n\t\t\tmp_oldest_stream->m_oldest_age -= (float)particles_dead * mp_oldest_stream->m_interval;\r\n\r\n\t\t\t// Advance seed.\r\n\t\t\tmp_oldest_stream->AdvanceSeed( particles_dead );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Remove oldest stream and wrap in cyclic buffer if necessary.\r\n\t\t\tm_num_streams--;\r\n\t\t\tmp_oldest_stream++;\r\n\t\t\tif( mp_oldest_stream == mp_stream + m_max_streams )\r\n\t\t\t{\r\n\t\t\t\tmp_oldest_stream = mp_stream;\r\n\t\t\t}\r\n\t\t\tif( !m_num_streams )\r\n\t\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\t// Now render the streams. after checking the bounding sphere is visible (for no dynamic systems).\r\n\tif( !m_params.m_LocalCoord )\r\n\t{\r\n\t\tD3DXVECTOR3\tcenter( m_bsphere[X], m_bsphere[Y], m_bsphere[Z] );\r\n\t\tif( !NxXbox::frustum_check_sphere( &center, m_bsphere[W] ))\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\t// Swap the r and b color components in the params.\r\n\tfor( i = 0; i < vNUM_BOXES; ++i )\r\n\t{\r\n\t\tuint8 swap = m_params.m_Color[i].r;\r\n\t\tm_params.m_Color[i].r\t= m_params.m_Color[i].b;\r\n\t\tm_params.m_Color[i].b\t= swap;\r\n\t}\r\n\r\n\t// Figure the distance from the camera to the system, and use a different technique accordingly.\r\n\t// Need to do this because point sprites are limited to 64 pixels in each dimension, and sometimes\r\n\t// you can get close enough to a system that a single particle will occupy more than this.\r\n\t// A more sophisticated approach would be to figure what the max particle size could be at a given distance,\r\n\t// rather than using the current hardcoded distance value of 20 feet.\r\n\tfloat dist_squared = Mth::DistanceSqr( Mth::Vector( m_bsphere[X], m_bsphere[Y], m_bsphere[Z], 0.0f ),\r\n\t\t\t\t\t\t\t\t\t\t   Mth::Vector( NxXbox::EngineGlobals.cam_position.x, NxXbox::EngineGlobals.cam_position.y, NxXbox::EngineGlobals.cam_position.z, 0.0f ));\r\n\tif( dist_squared < 57600.0f )\r\n\t{\r\n\t\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\r\n\t\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\t\tMth::Vector up( 0.0f, 1.0f, 0.0f );\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\t\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\t\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\t\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\t\tscreen_right.Normalize();\r\n\t\tscreen_up.Normalize();\r\n\r\n\t\t// Submit particle material.\r\n\t\tmp_material->Submit();\r\n\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( ParticleNewFlatVS );\r\n\t\tNxXbox::set_pixel_shader( PixelShader0 );\r\n\r\n\t\t// Load up the combined world->view_projection matrix.\r\n\t\tXGMATRIX\tdest_matrix;\r\n\t\tXGMATRIX\tprojMatrix;\r\n\t\tXGMATRIX\tviewMatrix;\r\n\t\t\t\r\n\t\t// Projection matrix.\r\n\t\tXGMatrixTranspose( &projMatrix, &NxXbox::EngineGlobals.projection_matrix );\r\n\t\t\r\n\t\t// View matrix.\r\n\t\tXGMatrixTranspose( &viewMatrix, &NxXbox::EngineGlobals.view_matrix );\r\n\t\tviewMatrix.m[3][0] = 0.0f;\r\n\t\tviewMatrix.m[3][1] = 0.0f;\r\n\t\tviewMatrix.m[3][2] = 0.0f;\r\n\t\tviewMatrix.m[3][3] = 1.0f;\r\n\r\n\t\t// Calculate composite world->view->projection matrix (simplified since world transform will be indentity).\r\n\t\tXGMatrixMultiply( &dest_matrix, &projMatrix, &viewMatrix );\r\n\r\n\t\t// Load up the combined world, camera & projection matrix.\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 0, (void*)&dest_matrix, 4 );\r\n\r\n\t\tfloat vector_upload[8];\r\n\t\tvector_upload[0]\t= screen_right[X];\r\n\t\tvector_upload[1]\t= screen_right[Y];\r\n\t\tvector_upload[2]\t= screen_right[Z];\r\n\t\tvector_upload[4]\t= screen_up[X];\r\n\t\tvector_upload[5]\t= screen_up[Y];\r\n\t\tvector_upload[6]\t= screen_up[Z];\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 4, (void*)( &vector_upload[0] ), 2 );\r\n\r\n\t\tstatic float vconstants[32]\t= {\t0.0f,  0.0f, 1.0f, 1.0f,\t\t// Vert tex coords in C8 through C11\r\n\t\t\t\t\t\t\t\t\t\t1.0f,  0.0f, 1.0f, 1.0f,\r\n\t\t\t\t\t\t\t\t\t\t1.0f,  1.0f, 1.0f, 1.0f,\r\n\t\t\t\t\t\t\t\t\t\t0.0f,  1.0f, 1.0f, 1.0f,\r\n\t\t\t\t\t\t\t\t\t-1.0f,  1.0f, 1.0f, 1.0f,\t\t// Vert w/h multipliers in C12 through C15\r\n\t\t\t\t\t\t\t\t\t\t1.0f,  1.0f, 1.0f, 1.0f,\r\n\t\t\t\t\t\t\t\t\t\t1.0f, -1.0f, 1.0f, 1.0f,\r\n\t\t\t\t\t\t\t\t\t-1.0f, -1.0f, 1.0f, 1.0f };\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 8, (void*)( &vconstants[0] ), 8 );\r\n\r\n\t\tfloat stream_params[24];\r\n\t\tstream_params[0]\t= m_s0[X];\r\n\t\tstream_params[1]\t= m_s0[Y];\r\n\t\tstream_params[2]\t= m_s0[Z];\r\n\t\tstream_params[3]\t= m_s0[W];\r\n\r\n\t\tstream_params[4]\t= m_s1[X];\r\n\t\tstream_params[5]\t= m_s1[Y];\r\n\t\tstream_params[6]\t= m_s1[Z];\r\n\t\tstream_params[7]\t= m_s1[W];\r\n\r\n\t\tstream_params[8]\t= m_s2[X];\r\n\t\tstream_params[9]\t= m_s2[Y];\r\n\t\tstream_params[10]\t= m_s2[Z];\r\n\t\tstream_params[11]\t= m_s2[W];\r\n\r\n\t\tstream_params[12]\t= m_p0[X];\r\n\t\tstream_params[13]\t= m_p0[Y];\r\n\t\tstream_params[14]\t= m_p0[Z];\r\n\t\tstream_params[15]\t= m_p0[W];\r\n\r\n\t\tstream_params[16]\t= m_p1[X];\r\n\t\tstream_params[17]\t= m_p1[Y];\r\n\t\tstream_params[18]\t= m_p1[Z];\r\n\t\tstream_params[19]\t= m_p1[W];\r\n\r\n\t\tstream_params[20]\t= m_p2[X];\r\n\t\tstream_params[21]\t= m_p2[Y];\r\n\t\tstream_params[22]\t= m_p2[Z];\r\n\t\tstream_params[23]\t= m_p2[W];\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 18, (void*)( &stream_params[0] ), 6 );\r\n\r\n\t\t// Construct a packet with data for each stream.\r\n\t\tfor( i = 0, p_stream = mp_oldest_stream; i < m_num_streams; i++, p_stream++ )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( p_stream->m_num_particles < 65536, ( \"particle limit reached\" ));\r\n\r\n\t\t\t// Wrap at end of cyclic buffer.\r\n\t\t\tif( p_stream == mp_stream + m_max_streams )\r\n\t\t\t{\r\n\t\t\t\tp_stream = mp_stream;\r\n\t\t\t}\r\n\r\n\t\t\t// Calculate space needed.\r\n\t\t\tDWORD dwords_per_particle\t= 28;\r\n\t\t\tDWORD dword_count\t\t\t= dwords_per_particle * p_stream->m_num_particles;\r\n\r\n\t\t\t// Obtain push buffer lock.\r\n\t\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\t\tDWORD *p_push; \r\n\t\t\tp_push = D3DDevice_BeginPush( dword_count );\r\n\r\n\t\t\tfloat t\t\t\t\t= p_stream->m_oldest_age;\r\n\t\t\tfloat midpoint_time = m_params.m_Lifetime * ( m_params.m_ColorMidpointPct * 0.01f );\r\n\r\n\t\t\t// Seed the random number generators for this stream.\r\n\t\t\tseed_particle_rnd( p_stream->m_rand_seed, p_stream->m_rand_a, p_stream->m_rand_b );\r\n\r\n\t\t\tfor( int p = 0; p < p_stream->m_num_particles; ++p )\r\n\t\t\t{\r\n\t\t\t\t// Generate random vector. Each component in the range [1.0, 2.0].\r\n\t\t\t\tfloat r[4];\r\n\t\t\t\tr[0] = 1.0f + ((float)particle_rnd( 16384 ) / 16384 );\r\n\t\t\t\tr[1] = 1.0f + ((float)particle_rnd( 16384 ) / 16384 );\r\n\t\t\t\tr[2] = 1.0f + ((float)particle_rnd( 16384 ) / 16384 );\r\n\t\t\t\tr[3] = 1.0f + ((float)particle_rnd( 16384 ) / 16384 );\r\n\r\n\t\t\t\tfloat color_interpolator;\r\n\t\t\t\tImage::RGBA\tcol0, col1;\r\n\r\n\t\t\t\tif( m_params.m_UseMidcolor )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( t > midpoint_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcolor_interpolator\t= ( t - midpoint_time ) * ReciprocalEstimate_ASM( m_params.m_Lifetime - midpoint_time );\r\n\t\t\t\t\t\tcol0\t\t\t\t= m_params.m_Color[1];\r\n\t\t\t\t\t\tcol1\t\t\t\t= m_params.m_Color[2];\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcolor_interpolator\t= t * ReciprocalEstimate_ASM( midpoint_time );\r\n\t\t\t\t\t\tcol0\t\t\t\t= m_params.m_Color[0];\r\n\t\t\t\t\t\tcol1\t\t\t\t= m_params.m_Color[1];\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse \r\n\t\t\t\t{\r\n\t\t\t\t\tcolor_interpolator\t\t= t * ReciprocalEstimate_ASM( m_params.m_Lifetime );\r\n\t\t\t\t\tcol0\t\t\t\t\t= m_params.m_Color[0];\r\n\t\t\t\t\tcol1\t\t\t\t\t= m_params.m_Color[2];\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// We're going to be loading constants.\r\n\t\t\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_TRANSFORM_CONSTANT_LOAD, 1 );\r\n\r\n\t\t\t\t// Specify the starting register (physical registers are offset by 96 from the D3D logical register).\r\n\t\t\t\tp_push[1]\t= 96 + 16;\r\n\r\n\t\t\t\t// Specify the number of DWORDS to load. 8 DWORDS for 2 constants.\r\n\t\t\t\tp_push[2]\t= D3DPUSH_ENCODE( D3DPUSH_SET_TRANSFORM_CONSTANT, 8 );\r\n\r\n\t\t\t\t// Load r vector.\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&r[0] );\r\n\t\t\t\tp_push[4]\t= *((DWORD*)&r[1] );\r\n\t\t\t\tp_push[5]\t= *((DWORD*)&r[2] );\r\n\t\t\t\tp_push[6]\t= *((DWORD*)&r[3] );\r\n\r\n\t\t\t\t// Load interpolator values.\r\n\t\t\t\tp_push[7]\t= *((DWORD*)&t );\r\n\t\t\t\tp_push[8]\t= *((DWORD*)&color_interpolator );\r\n\t\t\t\tp_push\t\t+= 11;\r\n\r\n\t\t\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\t\t\tp_push[1]\t= D3DPT_QUADLIST;\r\n\t\t\t\tp_push\t\t+= 2;\r\n\r\n\t\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, 12 );\r\n\t\t\t\t++p_push;\r\n\r\n\t\t\t\t// Now we can start the actual vertex data.\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&col0 );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&col1 );\r\n\t\t\t\tp_push[2]\t= 0x00000000UL;\r\n\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&col0 );\r\n\t\t\t\tp_push[4]\t= *((DWORD*)&col1 );\r\n\t\t\t\tp_push[5]\t= 0x00010001UL;\r\n\r\n\t\t\t\tp_push[6]\t= *((DWORD*)&col0 );\r\n\t\t\t\tp_push[7]\t= *((DWORD*)&col1 );\r\n\t\t\t\tp_push[8]\t= 0x00020002UL;\r\n\t\t\t\t\r\n\t\t\t\tp_push[9]\t= *((DWORD*)&col0 );\r\n\t\t\t\tp_push[10]\t= *((DWORD*)&col1 );\r\n\t\t\t\tp_push[11]\t= 0x00030003UL;\r\n\r\n\t\t\t\tp_push\t\t+= 12;\r\n\r\n\t\t\t\t// End of vertex data for this particle.\r\n\t\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\t\t\tp_push[1] = 0;\r\n\t\t\t\tp_push += 2;\r\n\r\n\t\t\t\t// Reduce t by particle interval.\r\n\t\t\t\tt -= p_stream->m_interval;\r\n\t\t\t}\r\n\t\t\tD3DDevice_EndPush( p_push );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Submit particle material.\r\n\t\tmp_material->Submit();\r\n\r\n\t\t// Point sprites actually use texture stage 3...\r\n\t\tNxXbox::set_render_state( RS_UVADDRESSMODE3, 0x00000000UL );\r\n\t\tmp_material->mp_tex[0]->Set( 3 );\r\n\r\n\t\t// Set up point sprite rendering.\r\n\t\tD3DDevice_SetRenderState( D3DRS_POINTSPRITEENABLE,\tTRUE );\r\n\t\tD3DDevice_SetRenderState( D3DRS_POINTSCALEENABLE,\tTRUE );\r\n//\t\tD3DDevice_SetRenderState( D3DRS_POINTSCALE_A,\t\tFtoDW( 0.00f ));\r\n//\t\tD3DDevice_SetRenderState( D3DRS_POINTSCALE_B,\t\tFtoDW( 0.00f ));\r\n//\t\tD3DDevice_SetRenderState( D3DRS_POINTSCALE_C,\t\tFtoDW( 1.00f ));\r\n\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( ParticleNewFlatPointSpriteVS );\r\n\t\tNxXbox::set_pixel_shader( PixelShaderPointSprite );\r\n\r\n\t\t// Load up the combined world->view_projection matrix.\r\n\t\tXGMATRIX\tdest_matrix;\r\n\t\tXGMATRIX\tprojMatrix;\r\n\t\tXGMATRIX\tviewMatrix;\r\n\t\t\t\r\n\t\t// Projection matrix.\r\n\t\tXGMatrixTranspose( &projMatrix, &NxXbox::EngineGlobals.projection_matrix );\r\n\t\t\r\n\t\t// View matrix.\r\n\t\tXGMatrixTranspose( &viewMatrix, &NxXbox::EngineGlobals.view_matrix );\r\n\t\tviewMatrix.m[3][0] = 0.0f;\r\n\t\tviewMatrix.m[3][1] = 0.0f;\r\n\t\tviewMatrix.m[3][2] = 0.0f;\r\n\t\tviewMatrix.m[3][3] = 1.0f;\r\n\r\n\t\t// Calculate composite world->view->projection matrix (simplified since world transform will be indentity).\r\n\t\tXGMatrixMultiply( &dest_matrix, &projMatrix, &viewMatrix );\r\n\r\n\t\t// Load up the combined world, camera & projection matrix.\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 0, (void*)&dest_matrix, 4 );\r\n\r\n\t\t// Load up the stream parameters.\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 18, (void*)( &m_s0[X] ), 1 );\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 19, (void*)( &m_s1[X] ), 1 );\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 20, (void*)( &m_s2[X] ), 1 );\r\n\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 21, (void*)( &m_p0[X] ), 1 );\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 22, (void*)( &m_p1[X] ), 1 );\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 23, (void*)( &m_p2[X] ), 1 );\r\n\r\n\t\t// Load up the camera position and viewport height.\r\n\t\tstatic float cam_pos_viewport_height[4];\r\n\t\tcam_pos_viewport_height[0]\t= NxXbox::EngineGlobals.cam_position.x;\r\n\t\tcam_pos_viewport_height[1]\t= NxXbox::EngineGlobals.cam_position.y;\r\n\t\tcam_pos_viewport_height[2]\t= NxXbox::EngineGlobals.cam_position.z;\r\n\t\tcam_pos_viewport_height[3]\t= NxXbox::EngineGlobals.viewport.Height * 2.0f;\r\n\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 24, (void*)( &cam_pos_viewport_height[0] ), 1 );\r\n\r\n\t\t// Construct a packet with data for each stream.\r\n\t\tfor( i = 0, p_stream = mp_oldest_stream; i < m_num_streams; i++, p_stream++ )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( p_stream->m_num_particles < 65536, ( \"particle limit reached\" ));\r\n\r\n\t\t\t// Wrap at end of cyclic buffer.\r\n\t\t\tif( p_stream == mp_stream + m_max_streams )\r\n\t\t\t{\r\n\t\t\t\tp_stream = mp_stream;\r\n\t\t\t}\r\n\r\n\t\t\t// Calculate space needed.\r\n\t\t\tDWORD dwords_per_particle\t= 13;\r\n\t\t\tDWORD dword_count\t\t\t= dwords_per_particle * p_stream->m_num_particles;\r\n\r\n\t\t\t// Obtain push buffer lock.\r\n\t\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\t\tDWORD *p_push; \r\n\t\t\tp_push = D3DDevice_BeginPush( dword_count );\r\n\r\n\t\t\tfloat t\t\t\t\t= p_stream->m_oldest_age;\r\n\t\t\tfloat midpoint_time = m_params.m_Lifetime * ( m_params.m_ColorMidpointPct * 0.01f );\r\n\r\n\t\t\t// Seed the random number generators for this stream.\r\n\t\t\tseed_particle_rnd( p_stream->m_rand_seed, p_stream->m_rand_a, p_stream->m_rand_b );\r\n\r\n\t\t\tfor( int p = 0; p < p_stream->m_num_particles; ++p )\r\n\t\t\t{\r\n\t\t\t\t// Generate random vector. Each component in the range [1.0, 2.0].\r\n\t\t\t\tfloat r[4];\r\n\t\t\t\tr[0] = 1.0f + ((float)particle_rnd( 16384 ) / 16384 );\r\n\t\t\t\tr[1] = 1.0f + ((float)particle_rnd( 16384 ) / 16384 );\r\n\t\t\t\tr[2] = 1.0f + ((float)particle_rnd( 16384 ) / 16384 );\r\n\t\t\t\tr[3] = 1.0f + ((float)particle_rnd( 16384 ) / 16384 );\r\n\r\n\t\t\t\tfloat color_interpolator;\r\n\t\t\t\tImage::RGBA\tcol0, col1;\r\n\r\n\t\t\t\tif( m_params.m_UseMidcolor )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( t > midpoint_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcolor_interpolator\t= ( t - midpoint_time ) * ReciprocalEstimate_ASM( m_params.m_Lifetime - midpoint_time );\r\n\t\t\t\t\t\tcol0\t\t\t\t= m_params.m_Color[1];\r\n\t\t\t\t\t\tcol1\t\t\t\t= m_params.m_Color[2];\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcolor_interpolator\t= t * ReciprocalEstimate_ASM( midpoint_time );\r\n\t\t\t\t\t\tcol0\t\t\t\t= m_params.m_Color[0];\r\n\t\t\t\t\t\tcol1\t\t\t\t= m_params.m_Color[1];\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse \r\n\t\t\t\t{\r\n\t\t\t\t\tcolor_interpolator\t\t= t * ReciprocalEstimate_ASM( m_params.m_Lifetime );\r\n\t\t\t\t\tcol0\t\t\t\t\t= m_params.m_Color[0];\r\n\t\t\t\t\tcol1\t\t\t\t\t= m_params.m_Color[2];\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Signal the primitive type to follow.\r\n\t\t\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\t\t\tp_push[1]\t= D3DPT_POINTLIST;\r\n\t\t\t\tp_push\t\t+= 2;\r\n\r\n\t\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, 8 );\r\n\t\t\t\t++p_push;\r\n\r\n\t\t\t\t// Now we can start the actual vertex data.\r\n\r\n\t\t\t\t// Load r vector.\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&r[0] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&r[1] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&r[2] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&r[3] );\r\n\r\n\t\t\t\t// Load time and color interpolator values.\r\n\t\t\t\tp_push[4]\t= *((DWORD*)&t );\r\n\t\t\t\tp_push[5]\t= *((DWORD*)&color_interpolator );\r\n\r\n\t\t\t\t// Load colors.\r\n\t\t\t\tp_push[6]\t= *((DWORD*)&col0 );\r\n\t\t\t\tp_push[7]\t= *((DWORD*)&col1 );\r\n\r\n\t\t\t\tp_push\t\t+= 8;\r\n\r\n\t\t\t\t// End of vertex data for this particle.\r\n\t\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\t\t\tp_push[1] = 0;\r\n\t\t\t\tp_push += 2;\r\n\r\n\t\t\t\t// Reduce t by particle interval.\r\n\t\t\t\tt -= p_stream->m_interval;\r\n\t\t\t}\r\n\t\t\tD3DDevice_EndPush( p_push );\r\n\t\t}\r\n\r\n\t\t// Restore render states.\r\n\t\tD3DDevice_SetRenderState( D3DRS_POINTSPRITEENABLE, FALSE );\r\n\t}\r\n\r\n\t// Swap the r and b color components back in the params.\r\n\tfor( i = 0; i < vNUM_BOXES; ++i )\r\n\t{\r\n\t\tuint8 swap = m_params.m_Color[i].r;\r\n\t\tm_params.m_Color[i].r\t= m_params.m_Color[i].b;\r\n\t\tm_params.m_Color[i].b\t= swap;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxNewParticle::update_position( void )\r\n{\r\n\t// Convert 3-point -> PVA format\r\n\tfloat t1 = m_params.m_Lifetime * m_params.m_MidpointPct * 0.01f;\r\n\tfloat t2 = m_params.m_Lifetime;\r\n\tMth::Vector u, a_;\r\n\r\n\tMth::Vector x0\t= m_params.m_BoxPos[0];\r\n\tx0[3]\t\t\t= m_params.m_Radius[0];\r\n\tMth::Vector x1\t= m_params.m_BoxPos[1];\r\n\tx1[3]\t\t\t= m_params.m_Radius[1];\r\n\tMth::Vector x2\t= m_params.m_BoxPos[2];\r\n\tx2[3]\t\t\t= m_params.m_Radius[2];\r\n\r\n\tif( m_params.m_UseMidpoint )\r\n\t{\r\n\t\tu  = ( t2 * t2 * ( x1 - x0 ) - t1 * t1 * ( x2 - x0 )) / ( t1 * t2 * ( t2 - t1 ));\r\n\t\ta_ = ( t1 * ( x2 - x0 ) - t2 * ( x1 - x0 )) / ( t1 * t2 * ( t2 - t1 ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tu  = ( x2 - x0 ) / t2;\r\n\t\ta_.Set( 0, 0, 0, 0 );\r\n\t}\r\n\r\n\tm_p0 = x0 - 1.5f * m_s0;\r\n\tm_p1 = u  - 1.5f * m_s1;\r\n\tm_p2 = a_ - 1.5f * m_s2;\r\n\tm_p0[3] = x0[3] - 1.5f * m_s0[3];\r\n\tm_p1[3] = u[3]  - 1.5f * m_s1[3];\r\n\tm_p2[3] = a_[3] - 1.5f * m_s2[3];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxNewParticle::plat_update( void )\r\n{\r\n\tif( m_params.m_LocalCoord )\r\n\t{\r\n\t\tupdate_position();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxNewParticle::plat_build( void )\r\n{\r\n\t// Reduce emit rate selectively to improve performance.\r\n\tm_params.m_EmitRate\t= m_params.m_EmitRate * 0.5f;\r\n\r\n\t// Initialise streams.\r\n\tm_max_streams\t\t= 5;\r\n\tm_num_streams\t\t= 0;\r\n\r\n\tmp_stream\t\t\t= new CParticleStream[m_max_streams]; \r\n\tmp_newest_stream\t= mp_stream + m_max_streams - 1;\r\n\tmp_oldest_stream\t= mp_stream;\r\n\tm_emitting\t\t\t= false;\r\n\r\n\t// Create a (semi-transparent) material used to render the mesh.\r\n\tmp_material\t\t\t= new NxXbox::sMaterial;\r\n\tZeroMemory( mp_material, sizeof( NxXbox::sMaterial ));\r\n\r\n\tmp_material->m_flags[0]\t\t= MATFLAG_TRANSPARENT | MATFLAG_TEXTURED;\r\n\tmp_material->m_passes\t\t= 1;\r\n\tmp_material->m_alpha_cutoff\t= 1;\r\n\tmp_material->m_no_bfc\t\t= true;\r\n\tmp_material->m_color[0][0]\t= 0.5f;\r\n\tmp_material->m_color[0][1]\t= 0.5f;\r\n\tmp_material->m_color[0][2]\t= 0.5f;\r\n\tmp_material->m_color[0][3]\t= m_params.m_FixedAlpha * ( 1.0f /  128.0f );\r\n\tmp_material->m_reg_alpha[0]\t= NxXbox::GetBlendMode( m_params.m_BlendMode );\r\n\r\n\t// Get texture.\r\n\tNx::CTexture*\t\tp_texture;\r\n\tNx::CXboxTexture*\tp_xbox_texture;\r\n\tmp_material->mp_tex[0]\t= NULL;\r\n\tp_texture\t\t\t\t= Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( m_params.m_Texture );\r\n\tp_xbox_texture\t\t\t= static_cast<Nx::CXboxTexture*>( p_texture );\r\n\tif( p_xbox_texture )\r\n\t{\r\n\t\tmp_material->mp_tex[0] = p_xbox_texture->GetEngineTexture();\r\n\t}\r\n\r\n\t// Convert 3-point -> PVA format.\r\n\tfloat t1 = m_params.m_Lifetime * m_params.m_MidpointPct * 0.01f;\r\n\tfloat t2 = m_params.m_Lifetime;\r\n\tMth::Vector x0,x1,x2,u,a_;\r\n\r\n\tx0    = m_params.m_BoxDims[0];\r\n\tx0[3] = m_params.m_RadiusSpread[0];\r\n\tx1    = m_params.m_BoxDims[1];\r\n\tx1[3] = m_params.m_RadiusSpread[1];\r\n\tx2    = m_params.m_BoxDims[2];\r\n\tx2[3] = m_params.m_RadiusSpread[2];\r\n\r\n\tif( m_params.m_UseMidpoint )\r\n\t{\r\n\t\tu  = ( t2 * t2 * ( x1 - x0 ) - t1 * t1 * ( x2 - x0 )) / ( t1 * t2 * ( t2 - t1 ));\r\n\t\ta_ = ( t1 * ( x2 - x0 ) - t2 * ( x1 - x0 )) / ( t1 * t2 * ( t2 - t1 ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tu  = ( x2 - x0 ) / t2;\r\n\t\ta_.Set( 0.0f, 0.0f, 0.0f, 0.0f );\r\n\t}\r\n\r\n\tm_s0 = x0;\r\n\tm_s1 = u;\r\n\tm_s2 = a_;\r\n\r\n\tx0    = m_params.m_BoxPos[0];\r\n\tx0[3] = m_params.m_Radius[0];\r\n\tx1    = m_params.m_BoxPos[1];\r\n\tx1[3] = m_params.m_Radius[1];\r\n\tx2    = m_params.m_BoxPos[2];\r\n\tx2[3] = m_params.m_Radius[2];\r\n\r\n\tif( m_params.m_UseMidpoint )\r\n\t{\r\n\t\tu  =  ( t2 * t2 * ( x1 - x0 ) - t1 * t1 * ( x2 - x0 )) / ( t1 * t2 * ( t2 - t1 ));\r\n\t\ta_ =  ( t1 * ( x2 - x0 ) - t2 * ( x1 - x0 )) / ( t1 * t2 * ( t2 - t1 ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tu  = ( x2 - x0 ) / t2;\r\n\t\ta_.Set( 0.0f, 0.0f, 0.0f, 0.0f );\r\n\t}\r\n\r\n\tm_p0\t= x0 - 1.5f * m_s0;\r\n\tm_p1\t= u  - 1.5f * m_s1;\r\n\tm_p2\t= a_ - 1.5f * m_s2;\r\n\tm_p0[3]\t= x0[3] - 1.5f * m_s0[3];\r\n\tm_p1[3]\t= u[3]  - 1.5f * m_s1[3];\r\n\tm_p2[3]\t= a_[3] - 1.5f * m_s2[3];\r\n\r\n\tupdate_position();\r\n\r\n\t// Color.\r\n\tif( m_params.m_UseMidcolor )\r\n\t{\r\n\t\tfloat q0 = 100.0f / ( m_params.m_Lifetime * m_params.m_ColorMidpointPct );\r\n\t\tfloat q1 = 100.0f / ( m_params.m_Lifetime * ( 100.0f - m_params.m_ColorMidpointPct ));\r\n\r\n//\t\tm_systemDmaData.m_c0[0] = ((float)m_params.m_Color[1].r - (float)m_params.m_Color[0].r) * q0;\r\n//\t\tm_systemDmaData.m_c0[1] = ((float)m_params.m_Color[1].g - (float)m_params.m_Color[0].g) * q0;\r\n//\t\tm_systemDmaData.m_c0[2] = ((float)m_params.m_Color[1].b - (float)m_params.m_Color[0].b) * q0;\r\n//\t\tm_systemDmaData.m_c0[3] = ((float)m_params.m_Color[1].a - (float)m_params.m_Color[0].a) * q0;\r\n\r\n//\t\tm_systemDmaData.m_c1[0] = (float)m_params.m_Color[1].r;\r\n//\t\tm_systemDmaData.m_c1[1] = (float)m_params.m_Color[1].g;\r\n//\t\tm_systemDmaData.m_c1[2] = (float)m_params.m_Color[1].b;\r\n//\t\tm_systemDmaData.m_c1[3] = (float)m_params.m_Color[1].a;\r\n\r\n//\t\tm_systemDmaData.m_c2[0] = ((float)m_params.m_Color[2].r - (float)m_params.m_Color[1].r) * q1;\r\n//\t\tm_systemDmaData.m_c2[1] = ((float)m_params.m_Color[2].g - (float)m_params.m_Color[1].g) * q1;\r\n//\t\tm_systemDmaData.m_c2[2] = ((float)m_params.m_Color[2].b - (float)m_params.m_Color[1].b) * q1;\r\n//\t\tm_systemDmaData.m_c2[3] = ((float)m_params.m_Color[2].a - (float)m_params.m_Color[1].a) * q1;\r\n\t}\r\n\telse // else suppress mid-colour\r\n\t{\r\n\t\tfloat q = 1.0f / m_params.m_Lifetime;\r\n\r\n//\t\tm_systemDmaData.m_c1[0] = (float)m_params.m_Color[0].r;\r\n//\t\tm_systemDmaData.m_c1[1] = (float)m_params.m_Color[0].g;\r\n//\t\tm_systemDmaData.m_c1[2] = (float)m_params.m_Color[0].b;\r\n//\t\tm_systemDmaData.m_c1[3] = (float)m_params.m_Color[0].a;\r\n\r\n//\t\tm_systemDmaData.m_c2[0] = ((float)m_params.m_Color[2].r - (float)m_params.m_Color[0].r) * q;\r\n//\t\tm_systemDmaData.m_c2[1] = ((float)m_params.m_Color[2].g - (float)m_params.m_Color[0].g) * q;\r\n//\t\tm_systemDmaData.m_c2[2] = ((float)m_params.m_Color[2].b - (float)m_params.m_Color[0].b) * q;\r\n//\t\tm_systemDmaData.m_c2[3] = ((float)m_params.m_Color[2].a - (float)m_params.m_Color[0].a) * q;\r\n\t}\r\n\r\n\t// Rotation matrix.\r\n\tm_rotation.Identity();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxNewParticle::plat_destroy( void )\r\n{\r\n\tif( mp_stream )\r\n\t{\r\n\t\tdelete [] mp_stream;\r\n\t}\r\n\r\n\tif( mp_material )\r\n\t{\r\n\t\tdelete mp_material;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxnewparticle.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_NxNewParticle.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/24/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXbox implementation of new parametric particle system\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_XBOX_P_NXNEWPARTICLE_H__\r\n#define __GFX_XBOX_P_NXNEWPARTICLE_H__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/nxnewparticle.h>\r\n#include <gfx/xbox/nx/material.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n                        \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CParticleStream\r\n{\r\npublic:\r\n\tint\t\t\t\t\t\tm_num_particles;\r\n\tfloat\t\t\t\t\tm_rate;\r\n\tfloat\t\t\t\t\tm_interval;\r\n\tfloat\t\t\t\t\tm_oldest_age;\r\n\tuint32\t\t\t\t\tm_rand_seed;\r\n\tuint32\t\t\t\t\tm_rand_a;\r\n\tuint32\t\t\t\t\tm_rand_b;\r\n\tvoid\t\t\t\t\tAdvanceSeed( int num_places );\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CXboxNewParticle : public CNewParticle\r\n{\r\n\tbool\t\t\t\tm_emitting;\r\n\tint\t\t\t\t\tm_max_streams;\r\n\tint\t\t\t\t\tm_num_streams;\r\n\tCParticleStream*\tmp_stream;\r\n\tCParticleStream*\tmp_newest_stream;\r\n\tCParticleStream*\tmp_oldest_stream;\r\n\tMth::Matrix \t\tm_rotation;\r\n\tMth::Matrix\t\t\tm_new_matrix;\r\n\tNxXbox::sMaterial*\tmp_material;\r\n\r\n\tMth::Vector\t\t\tm_s0;\r\n\tMth::Vector\t\t\tm_s1;\r\n\tMth::Vector\t\t\tm_s2;\r\n\tMth::Vector\t\t\tm_p0;\r\n\tMth::Vector\t\t\tm_p1;\r\n\tMth::Vector\t\t\tm_p2;\r\n\r\nprotected:\r\n\tvoid\tplat_build( void );\r\n\tvoid\tplat_destroy( void );\r\n\tvoid\tplat_render( void );\r\n\tvoid\tplat_update( void );\r\n\tvoid\tupdate_position( void );\r\n};\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n#endif\t// __GFX_XBOX_P_NXNEWPARTICLE_H__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxnewparticlemgr.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_NxNewParticleMgr.cpp\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/25/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXbox-specific parametric particle system manager\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gfx/xbox/p_nxnewparticle.h>\r\n#include <gfx/xbox/p_nxnewparticlemgr.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCNewParticle*\tCXboxNewParticleManager::plat_create_particle( void )\r\n{\r\n\treturn new CXboxNewParticle;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxnewparticlemgr.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5 \t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGfx\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_nxnewparticlemgr.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t3/24/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXbox-specific new parametric particle system manager\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_XBOX_P_NXNEWPARTICLEMGR_H__\r\n#define __GFX_XBOX_P_NXNEWPARTICLEMGR_H__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/nxnewparticlemgr.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CXboxNewParticleManager : public CNewParticleManager\r\n{\r\nprotected:\r\n\tvirtual\tCNewParticle*\tplat_create_particle( void );\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Nx\r\n\r\n#endif\t// __GFX_XBOX_P_NXNEWPARTICLEMGR_H__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticle.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.cpp\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/xbox/nx/nx_init.h\"\r\n#include \"gfx/xbox/p_nxparticle.h\"\r\n#include \"gfx/xbox/p_nxparticleline.h\"\r\n#include \"gfx/xbox/p_nxparticleflat.h\"\r\n#include \"gfx/xbox/p_nxparticleshaded.h\"\r\n#include \"gfx/xbox/p_nxparticlesmooth.h\"\r\n#include \"gfx/xbox/p_nxparticleglow.h\"\r\n#include \"gfx/xbox/p_nxparticlestar.h\"\r\n#include \"gfx/xbox/p_nxparticlesmoothstar.h\"\r\n#include \"gfx/xbox/p_nxparticleribbon.h\"\r\n#include \"gfx/xbox/p_nxparticlesmoothribbon.h\"\r\n#include \"gfx/xbox/p_nxparticleribbontrail.h\"\r\n#include \"gfx/xbox/p_nxparticleglowribbontrail.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCParticle *plat_create_particle( uint32 checksum, uint32 type_checksum, int max_particles, int max_streams, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tswitch( type_checksum )\r\n\t{\r\n\t\tcase 0x2eeb4b09:\t// Line\r\n\t\t{\r\n\t\t\tCXboxParticleLine *p_particle = new CXboxParticleLine( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split );\r\n\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t}\r\n\r\n\t\tcase 0xaab555bb:\t// Flat\r\n\t\t{\r\n\t\t\tCXboxParticleFlat *p_particle = new CXboxParticleFlat( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split );\r\n\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t}\r\n\r\n\t\tcase 0xf4d8d486:\t// Shaded\r\n\t\t{\r\n\t\t\tCXboxParticleShaded *p_particle = new CXboxParticleShaded( checksum, max_particles, texture_checksum, blendmode_checksum, fix );\r\n\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x8addac1f:\t// Smooth\r\n\t\t{\r\n\t\t\tCXboxParticleSmooth *p_particle = new CXboxParticleSmooth( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split );\r\n\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x15834eea:\t// Glow\r\n\t\t{\r\n\t\t\tCXboxParticleGlow *p_particle = new CXboxParticleGlow( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split );\r\n\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t}\r\n\r\n\t\tcase 0x3624a5eb:\t// Star\r\n\t\t{\r\n\t\t\tCXboxParticleStar *p_particle = new CXboxParticleStar( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split );\r\n\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x97cb7a9:\t\t// SmoothStar\r\n\t\t{\r\n\t\t\tCXboxParticleSmoothStar *p_particle = new CXboxParticleSmoothStar( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split );\r\n\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t}\r\n\r\n\t\tcase 0xee6fc5b:\t\t// Ribbon\r\n\t\t{\r\n\t\t\tCXboxParticleRibbon *p_particle = new CXboxParticleRibbon( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t}\r\n\r\n\t\tcase 0x3f109fcc:\t// SmoothRibbon\r\n\t\t{\r\n\t\t\tCXboxParticleSmoothRibbon *p_particle = new CXboxParticleSmoothRibbon( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t}\r\n\r\n\t\tcase 0xc4d5a4cb:\t// RibbonTrail\r\n\t\t{\r\n\t\t\tCXboxParticleRibbonTrail *p_particle = new CXboxParticleRibbonTrail( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t}\r\n\r\n\t\tcase 0x7ec7252d:\t// GlowRibbonTrail\r\n\t\t{\r\n\t\t\tCXboxParticleGlowRibbonTrail *p_particle = new CXboxParticleGlowRibbonTrail( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t}\r\n\r\n\t\tcase 0xdedfc057:\t// NewFlat\r\n\t\t{\r\n\t\t\t// Just default to old flat for now.\r\n\t\t\tCXboxParticleFlat *p_particle = new CXboxParticleFlat( checksum, max_particles, texture_checksum, blendmode_checksum, fix, num_segments, split );\r\n\t\t\treturn static_cast<CParticle*>( p_particle );\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Unsupported particle type\" ));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n} // Nx\r\n\r\n\t\t\t\t\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticle.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticle.h\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLE_H__\r\n#define\t__GFX_P_NX_PARTICLE_H__\r\n    \r\n#include \"gfx/nxparticle.h\"\r\n#include \"gfx/xbox/nx/particles.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n#endif \r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticleflat.cpp",
    "content": "#include <core/defines.h>\r\n#include <gfx/xbox/nx/render.h>\r\n#include \"gfx/xbox/p_nxparticleflat.h\"\r\n\r\nextern DWORD PixelShader0;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleFlat::CXboxParticleFlat()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleFlat::CXboxParticleFlat( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split )\r\n{\r\n\tm_checksum\t\t= checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\t\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n\t// Create the engine representation.\r\n\tmp_engine_particle = new NxXbox::sParticleSystem( max_particles, NxXbox::PARTICLE_TYPE_FLAT, texture_checksum, blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tm_start_color.r = m_start_color.g = m_start_color.b = 128;\r\n\tm_start_color.a = 255;\r\n\tm_mid_color.r = m_mid_color.g = m_mid_color.b = 128;\r\n\tm_mid_color.a = 255;\r\n\tm_end_color.r = m_end_color.g = m_end_color.b = 128;\r\n\tm_end_color.a = 255;\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleFlat::~CXboxParticleFlat()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n\tdelete mp_engine_particle;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleFlat::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleFlat::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleFlat::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CXboxParticleFlat::plat_get_num_particle_colors( void ) { return 1; }\r\nint CXboxParticleFlat::plat_get_num_vertex_lists( void ) { return 1; }\r\n\r\n// Note these are r/b reversed for direct uploading to Xbox GPU.\r\nvoid CXboxParticleFlat::plat_set_sr( int entry, uint8 value ) { m_start_color.b = value; }\r\nvoid CXboxParticleFlat::plat_set_sg( int entry, uint8 value ) { m_start_color.g = value; }\r\nvoid CXboxParticleFlat::plat_set_sb( int entry, uint8 value ) { m_start_color.r = value; }\r\nvoid CXboxParticleFlat::plat_set_sa( int entry, uint8 value ) { m_start_color.a = value; }\r\nvoid CXboxParticleFlat::plat_set_mr( int entry, uint8 value ) { m_mid_color.b = value; }\r\nvoid CXboxParticleFlat::plat_set_mg( int entry, uint8 value ) { m_mid_color.g = value; }\r\nvoid CXboxParticleFlat::plat_set_mb( int entry, uint8 value ) { m_mid_color.r = value; }\r\nvoid CXboxParticleFlat::plat_set_ma( int entry, uint8 value ) { m_mid_color.a = value; }\r\nvoid CXboxParticleFlat::plat_set_er( int entry, uint8 value ) { m_end_color.b = value; }\r\nvoid CXboxParticleFlat::plat_set_eg( int entry, uint8 value ) { m_end_color.g = value; }\r\nvoid CXboxParticleFlat::plat_set_eb( int entry, uint8 value ) { m_end_color.r = value; }\r\nvoid CXboxParticleFlat::plat_set_ea( int entry, uint8 value ) { m_end_color.a = value; }\r\n\r\n\r\n\t\t\r\n\r\n\r\n\r\n#if 1\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleFlat::plat_render( void )\r\n{\r\n\t// Draw the particles.\r\n\tif( m_num_particles > 0 )\r\n\t{\r\n\t\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\r\n\t\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\t\tMth::Vector up( 0.0f, 1.0f, 0.0f );\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\t\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\t\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\t\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\t\tscreen_right.Normalize();\r\n\t\tscreen_up.Normalize();\r\n\r\n\t\tint\t\t\t\tlp;\r\n\t\tCParticleEntry\t*p_particle;\r\n\t\tfloat\t\t\t*p_v;\r\n\r\n\t\t// Calculate space needed.\r\n\t\tDWORD dwords_per_particle\t= 32;\r\n\t\tDWORD dword_count\t\t\t= dwords_per_particle * m_num_particles;\r\n\r\n\t\t// Submit particle material.\r\n\t\tmp_engine_particle->mp_material->Submit();\r\n\t\t\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( ParticleFlatVS );\r\n\t\tNxXbox::set_pixel_shader( PixelShader0 );\r\n\t\t\r\n\t\t// Load up the combined world->view_projection matrix.\r\n\t\tXGMATRIX\ttemp_matrix;\r\n\t\tXGMATRIX\tdest_matrix;\r\n\t\tXGMATRIX\tprojMatrix;\r\n\t\tXGMATRIX\tviewMatrix;\r\n\t\tXGMATRIX\tworldMatrix;\r\n\t\t\r\n\t\t// Projection matrix.\r\n\t\tXGMatrixTranspose( &projMatrix, &NxXbox::EngineGlobals.projection_matrix );\r\n\t\r\n\t\t// View matrix.\r\n\t\tXGMatrixTranspose( &viewMatrix, &NxXbox::EngineGlobals.view_matrix );\r\n\t\tviewMatrix.m[3][0] = 0.0f;\r\n\t\tviewMatrix.m[3][1] = 0.0f;\r\n\t\tviewMatrix.m[3][2] = 0.0f;\r\n\t\tviewMatrix.m[3][3] = 1.0f;\r\n\r\n\t\t// World space transformation matrix, set to be a translation matrix corresponding to the emitter position.\r\n\t\tXGMatrixTranslation( &worldMatrix, m_pos[0], m_pos[1], m_pos[2] );\r\n\t\tXGMatrixTranspose( &worldMatrix, &worldMatrix );\r\n\r\n\t\t// Calculate composite world->view->projection matrix.\r\n\t\tXGMatrixMultiply( &temp_matrix, &viewMatrix, &worldMatrix );\r\n\t\tXGMatrixMultiply( &dest_matrix, &projMatrix, &temp_matrix );\r\n\r\n\t\t// Load up the combined world, camera & projection matrix.\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 0, (void*)&dest_matrix, 4 );\r\n\r\n\t\tfloat vector_upload[8];\r\n\t\tvector_upload[0]\t= screen_right[X];\r\n\t\tvector_upload[1]\t= screen_right[Y];\r\n\t\tvector_upload[2]\t= screen_right[Z];\r\n\t\tvector_upload[4]\t= screen_up[X];\r\n\t\tvector_upload[5]\t= screen_up[Y];\r\n\t\tvector_upload[6]\t= screen_up[Z];\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 4, (void*)( &vector_upload[0] ), 2 );\r\n\r\n\t\tstatic float vconstants[32]\t= {\t0.0f,  0.0f, 1.0f, 1.0f,\t\t// Vert tex coords in C8 through C11\r\n\t\t\t\t\t\t\t\t\t\t1.0f,  0.0f, 1.0f, 1.0f,\r\n\t\t\t\t\t\t\t\t\t\t1.0f,  1.0f, 1.0f, 1.0f,\r\n\t\t\t\t\t\t\t\t\t\t0.0f,  1.0f, 1.0f, 1.0f,\r\n\t\t\t\t\t\t\t\t\t   -1.0f,  1.0f, 1.0f, 1.0f,\t\t// Vert w/h multipliers in C12 through C15\r\n\t\t\t\t\t\t\t\t\t\t1.0f,  1.0f, 1.0f, 1.0f,\r\n\t\t\t\t\t\t\t\t\t\t1.0f, -1.0f, 1.0f, 1.0f,\r\n\t\t\t\t\t\t\t\t\t   -1.0f, -1.0f, 1.0f, 1.0f };\r\n\t\tD3DDevice_SetVertexShaderConstantFast( 8, (void*)( &vconstants[0] ), 8 );\r\n\r\n\t\t// Obtain push buffer lock.\r\n\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\tDWORD *p_push; \r\n\t\tp_push = D3DDevice_BeginPush( dword_count );\r\n\r\n\t\t// Set up loop variables here, since we be potentially enetering the loop more than once.\r\n\t\tlp\t\t\t= 0;\r\n\t\tp_particle\t= mp_particle_array;\r\n\t\tp_v\t\t\t= mp_vertices;\r\n\r\n\t\tfor( ; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t\t{\r\n\t\t\t// Calculate the interpolator ( 1.0f / particle_life ).\r\n\t\t\tfloat terp\t= p_particle->m_time * ReciprocalEstimateNR_ASM( p_particle->m_life );\r\n\r\n\t\t\t// Separate interpolator for color.\r\n\t\t\tfloat col_terp;\r\n\r\n\t\t\tMth::Vector\tpos( p_v[0], p_v[1], p_v[2] );\r\n\t\t\tImage::RGBA *p_col0;\r\n\t\t\tImage::RGBA *p_col1;\r\n\t\t\r\n\t\t\tif( m_mid_time >= 0.0f )\r\n\t\t\t{\r\n\t\t\t\tif( terp < m_mid_time )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_col0\t\t= &m_start_color;\r\n\t\t\t\t\tp_col1\t\t= &m_mid_color;\r\n\r\n\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\tcol_terp\t= terp / m_mid_time;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_col0\t\t= &m_mid_color;\r\n\t\t\t\t\tp_col1\t\t= &m_end_color;\r\n\r\n\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\tcol_terp\t= ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// No mid color specified.\r\n\t\t\t\tp_col0\t\t= &m_start_color;\r\n\t\t\t\tp_col1\t\t= &m_end_color;\r\n\r\n\t\t\t\t// Color interpoltor value is the same as the regular interpolator.\r\n\t\t\t\tcol_terp\t= terp;\r\n\t\t\t}\r\n\r\n\t\t\t// We're going to be loading constants.\r\n\t\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_TRANSFORM_CONSTANT_LOAD, 1 );\r\n\r\n\t\t\t// Specify the starting register (physical registers are offset by 96 from the D3D logical register).\r\n\t\t\tp_push[1]\t= 96 + 16;\r\n\r\n\t\t\t// Specify the number of DWORDS to load. 12 DWORDS for 3 constants.\r\n\t\t\tp_push[2]\t= D3DPUSH_ENCODE( D3DPUSH_SET_TRANSFORM_CONSTANT, 12 );\r\n\r\n\t\t\t// Load position.\r\n\t\t\tp_push[3]\t= *((DWORD*)&pos[X] );\r\n\t\t\tp_push[4]\t= *((DWORD*)&pos[Y] );\r\n\t\t\tp_push[5]\t= *((DWORD*)&pos[Z] );\r\n\r\n\t\t\t// Load start and end width and height.\r\n\t\t\tp_push[7]\t= *((DWORD*)&p_particle->m_sw );\r\n\t\t\tp_push[8]\t= *((DWORD*)&p_particle->m_sh );\r\n\t\t\tp_push[9]\t= *((DWORD*)&p_particle->m_ew );\r\n\t\t\tp_push[10]\t= *((DWORD*)&p_particle->m_eh );\r\n\r\n\t\t\t// Load size and color interpolators.\r\n\t\t\tp_push[11]\t= *((DWORD*)&terp );\r\n\t\t\tp_push[12]\t= *((DWORD*)&col_terp );\r\n\r\n\t\t\tp_push\t\t+= 15;\r\n\r\n\t\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\t\tp_push[1]\t= D3DPT_QUADLIST;\r\n\t\t\tp_push\t\t+= 2;\r\n\r\n\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, 12 );\r\n\t\t\t++p_push;\r\n\r\n\t\t\t// Now we can start the actual vertex data.\r\n\t\t\tp_push[0]\t= *((DWORD*)p_col0 );\r\n\t\t\tp_push[1]\t= *((DWORD*)p_col1 );\r\n\t\t\tp_push[2]\t= 0x00000000UL;\r\n\r\n\t\t\tp_push[3]\t= *((DWORD*)p_col0 );\r\n\t\t\tp_push[4]\t= *((DWORD*)p_col1 );\r\n\t\t\tp_push[5]\t= 0x00010001UL;\r\n\r\n\t\t\tp_push[6]\t= *((DWORD*)p_col0 );\r\n\t\t\tp_push[7]\t= *((DWORD*)p_col1 );\r\n\t\t\tp_push[8]\t= 0x00020002UL;\r\n\t\t\t\r\n\t\t\tp_push[9]\t= *((DWORD*)p_col0 );\r\n\t\t\tp_push[10]\t= *((DWORD*)p_col1 );\r\n\t\t\tp_push[11]\t= 0x00030003UL;\r\n\r\n\t\t\tp_push\t\t+= 12;\r\n\r\n\t\t\t// End of vertex data for this particle.\r\n\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\t\tp_push[1] = 0;\r\n\t\t\tp_push += 2;\r\n\t\t}\r\n\t\tD3DDevice_EndPush( p_push );\r\n\t}\r\n\r\n\t// Deal with the Ps2 specific extensions.\r\n\tif( m_emit_rate > 0.0f )\r\n\t{\r\n\t\tm_emit_rate_fractional += ( m_emit_rate * ( 1.0f / 60.0f ));\r\n\r\n\t\tif( m_emit_rate_fractional >= 1.0f )\r\n\t\t{\r\n\t\t\t// This should actually deal with fractional values by accumulating them.\r\n\t\t\temit( Ftoi_ASM( m_emit_rate_fractional ));\r\n\t\t\tm_emit_rate_fractional -= (float)Ftoi_ASM( m_emit_rate_fractional );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n#else\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleFlat::plat_render( void )\r\n{\r\n\t// Draw the particles.\r\n\tif( m_num_particles > 0 )\r\n\t{\r\n\t\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\r\n\t\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\t\tMth::Vector up( 0.0f, 1.0f, 0.0f );\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\t\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\t\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\t\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\t\tscreen_right.Normalize();\r\n\t\tscreen_up.Normalize();\r\n\r\n\t\tint\t\t\t\tlp;\r\n\t\tCParticleEntry\t*p_particle;\r\n\t\tfloat\t\t\t*p_v;\r\n\r\n\t\t// Submit particle material.\r\n\t\tmp_engine_particle->mp_material->Submit();\r\n\t\t\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2( 0 ));\r\n\t\tNxXbox::set_pixel_shader( PixelShader0 );\r\n\t\t\r\n\t\tDWORD dwords_per_particle\t= 24;\r\n\t\tDWORD dword_count\t\t\t= dwords_per_particle * m_num_particles;\r\n\r\n\t\t// Obtain push buffer lock.\r\n\t\t// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.\r\n\t\tDWORD *p_push; \r\n\t\tp_push = D3DDevice_BeginPush( dword_count + ( dword_count / 2047 ) + 16 );\r\n\r\n\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1]\t= D3DPT_QUADLIST;\r\n\t\tp_push\t\t+= 2;\r\n\r\n\t\t// Set up loop variables here, since we be potentially enetering the loop more than once.\r\n\t\tlp\t\t\t= 0;\r\n\t\tp_particle\t= mp_particle_array;\r\n\t\tp_v\t\t\t= mp_vertices;\r\n\r\n\t\twhile( dword_count > 0 )\r\n\t\t{\r\n\t\t\tint dwords_written = 0;\r\n\r\n\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, ( dword_count > 2047 ) ? ((int)( 2047 / dwords_per_particle )) * dwords_per_particle: dword_count );\r\n\t\t\t++p_push;\r\n\t\t\r\n\t\t\tfor( ; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t\t\t{\r\n\t\t\t\t// Check to see if writing another particle will take us over the edge.\r\n\t\t\t\tif(( dwords_written + dwords_per_particle ) > 2047 )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// Calculate the interpolator ( 1.0f / particle_life ).\r\n\t\t\t\tfloat terp\t= p_particle->m_time * ReciprocalEstimateNR_ASM( p_particle->m_life );\r\n\t\t\t\tfloat w\t\t= p_particle->m_sw + (( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\t\t\tfloat h\t\t= p_particle->m_sh + (( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\t\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\t\t\tMth::Vector\tss_right, ss_up;\r\n\t\t\t\tMth::Vector tmp;\r\n\t\t\r\n\t\t\t\tss_right\t= screen_right * w;\r\n\t\t\t\tss_up\t\t= screen_up * h;\r\n\r\n\t\t\t\tImage::RGBA color;\r\n\t\t\t\tImage::RGBA *p_col0;\r\n\t\t\t\tImage::RGBA *p_col1;\r\n\t\t\r\n\t\t\t\tif( m_mid_time >= 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( terp < m_mid_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = &m_start_color;\r\n\t\t\t\t\t\tp_col1 = &m_mid_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = &m_mid_color;\r\n\t\t\t\t\t\tp_col1 = &m_end_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No mid color specified.\r\n\t\t\t\t\tp_col0 = &m_start_color;\r\n\t\t\t\t\tp_col1 = &m_end_color;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tImage::RGBA start\t= *p_col0++;\r\n\t\t\t\tImage::RGBA end\t\t= *p_col1++;\r\n\r\n\t\t\t\t// Use fixed point math to avoid _ftol2 calls.\r\n\t\t\t\tint f_terp\t= Ftoi_ASM( terp * 4096.0f );\r\n\t\t\t\tcolor.r\t\t= ((((int)start.r ) * 4096 ) + (((int)end.r - (int)start.r ) * f_terp )) / 4096;\r\n\t\t\t\tcolor.g\t\t= ((((int)start.g ) * 4096 ) + (((int)end.g - (int)start.g ) * f_terp )) / 4096;\r\n\t\t\t\tcolor.b\t\t= ((((int)start.b ) * 4096 ) + (((int)end.b - (int)start.b ) * f_terp )) / 4096;\r\n\t\t\t\tcolor.a\t\t= ((((int)start.a ) * 4096 ) + (((int)end.a - (int)start.a ) * f_terp )) / 4096;\r\n\t\t\r\n\t\t\t\ttmp\t\t\t= pos - ss_right + ss_up;\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color );\r\n\t\t\t\tp_push[4]\t= 0x00000000UL;\r\n\t\t\t\tp_push[5]\t= 0x00000000UL;\r\n\t\r\n\t\t\t\ttmp\t\t\t= pos + ss_right + ss_up;\t\t\r\n\t\t\t\tp_push[6]\t= *((DWORD*)&tmp[X] );\r\n\t\t\t\tp_push[7]\t= *((DWORD*)&tmp[Y] );\r\n\t\t\t\tp_push[8]\t= *((DWORD*)&tmp[Z] );\r\n\t\t\t\tp_push[9]\t= *((DWORD*)&color );\r\n\t\t\t\tp_push[10]\t= 0x3F800000UL;\r\n\t\t\t\tp_push[11]\t= 0x00000000UL;\r\n\r\n\t\t\t\ttmp\t\t\t= pos + ss_right - ss_up;\t\t\r\n\t\t\t\tp_push[12]\t= *((DWORD*)&tmp[X] );\r\n\t\t\t\tp_push[13]\t= *((DWORD*)&tmp[Y] );\r\n\t\t\t\tp_push[14]\t= *((DWORD*)&tmp[Z] );\r\n\t\t\t\tp_push[15]\t= *((DWORD*)&color );\r\n\t\t\t\tp_push[16]\t= 0x3F800000UL;\r\n\t\t\t\tp_push[17]\t= 0x3F800000UL;\r\n\t\t\t\r\n\t\t\t\ttmp\t\t\t= pos - ss_right - ss_up;\t\t\r\n\t\t\t\tp_push[18]\t= *((DWORD*)&tmp[X] );\r\n\t\t\t\tp_push[19]\t= *((DWORD*)&tmp[Y] );\r\n\t\t\t\tp_push[20]\t= *((DWORD*)&tmp[Z] );\r\n\t\t\t\tp_push[21]\t= *((DWORD*)&color );\r\n\t\t\t\tp_push[22]\t= 0x00000000UL;\r\n\t\t\t\tp_push[23]\t= 0x3F800000UL;\r\n\r\n\t\t\t\tp_push\t\t+= 24;\r\n\r\n\t\t\t\tdwords_written\t+= dwords_per_particle;\r\n\t\t\t\tdword_count\t\t-= dwords_per_particle;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1] = 0;\r\n\t\tp_push += 2;\r\n\t\tD3DDevice_EndPush( p_push );\r\n\t}\r\n}\r\n#endif\r\n\r\n\r\n\r\n} // Nx\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticleflat.h",
    "content": "#ifndef\t__GFX_P_NX_PARTICLEFLAT_H__\r\n#define\t__GFX_P_NX_PARTICLEFLAT_H__\r\n    \r\n#include \"gfx/xbox/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CXboxParticleFlat : public CParticle\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\tCXboxParticleFlat();\r\n\t\t\t\t\t\t\tCXboxParticleFlat( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split );\r\n\tvirtual \t\t\t\t~CXboxParticleFlat();\r\n\r\n//\tNxXbox::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\tfloat*\t\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\t\tm_blend;\r\n\tNxXbox::sParticleSystem*\tmp_engine_particle;\r\n\tfloat\t\t\t\t\t\tm_emit_rate_fractional;\t\t// Deals with the fractional part of m_emit_rate for the pseudo parametric systems.\r\n\r\n\tImage::RGBA\t\t\t\t\tm_start_color;\t\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\t\tm_mid_color;\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\t\tm_end_color;\t\t\t\t// End color for each corner.\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticleglow.cpp",
    "content": "#include <core/defines.h>\r\n#include \"gfx/xbox/nx/render.h\"\r\n\r\n#include \"gfx/xbox/p_nxparticleGlow.h\"\r\n\r\nextern DWORD PixelShader1;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleGlow::CXboxParticleGlow()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleGlow::CXboxParticleGlow( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split )\r\n{\r\n\tm_checksum\t\t= checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\tm_num_segments\t= num_segments;\r\n\tm_split\t\t\t= split;\r\n\tm_mid_time\t\t= -1.0f;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n\t// Create the engine representation.\r\n\tmp_engine_particle = new NxXbox::sParticleSystem( max_particles, NxXbox::PARTICLE_TYPE_GLOW, texture_checksum, blendmode_checksum, fix, num_segments );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 3; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 255;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 255;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 255;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleGlow::~CXboxParticleGlow()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n\tdelete mp_engine_particle;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleGlow::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleGlow::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleGlow::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CXboxParticleGlow::plat_get_num_particle_colors( void ) { return 3; }\r\nint CXboxParticleGlow::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CXboxParticleGlow::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CXboxParticleGlow::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CXboxParticleGlow::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CXboxParticleGlow::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CXboxParticleGlow::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CXboxParticleGlow::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CXboxParticleGlow::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CXboxParticleGlow::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CXboxParticleGlow::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CXboxParticleGlow::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CXboxParticleGlow::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CXboxParticleGlow::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleGlow::plat_render( void )\r\n{\r\n\t// Draw the particles.\r\n\tif( m_num_particles > 0 )\r\n\t{\r\n\t\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\r\n\t\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\t\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\t\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\t\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\t\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\t\tscreen_right.Normalize();\r\n\t\tscreen_up.Normalize();\r\n\t\r\n\t\tint\t\t\t\tlp;\r\n\t\tCParticleEntry\t*p_particle;\r\n\t\tfloat\t\t\t*p_v;\r\n\r\n//\t\tMth::Vector\t\tmin, max;\t// For dynamic bounding box calculation.\r\n\r\n\t\t// Obtain push buffer lock.\r\n\t\tDWORD *p_push; \r\n\t\tDWORD dwords_per_particle\t= 36 * m_num_segments;\r\n\t\tDWORD dword_count\t\t\t= dwords_per_particle * m_num_particles;\r\n\r\n\t\t// Submit particle material.\r\n\t\tmp_engine_particle->mp_material->Submit();\r\n\t\t\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\t\tNxXbox::set_pixel_shader( PixelShader1 );\r\n\t\t\r\n\t\t// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.\r\n\t\tp_push = D3DDevice_BeginPush( dword_count + ( dword_count / 2047 ) + 16 );\r\n\r\n\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1]\t= D3DPT_TRIANGLELIST;\r\n\t\tp_push\t\t+= 2;\r\n\r\n\t\t// Set up loop variables here, since we be potentially enetering the loop more than once.\r\n\t\tlp\t\t\t= 0;\r\n\t\tp_particle\t= mp_particle_array;\r\n\t\tp_v\t\t\t= mp_vertices;\r\n\r\n\t\twhile( dword_count > 0 )\r\n\t\t{\r\n\t\t\tint dwords_written = 0;\r\n\r\n\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, ( dword_count > 2047 ) ? ((int)( 2047 / dwords_per_particle )) * dwords_per_particle: dword_count );\r\n\t\t\t++p_push;\r\n\t\t\r\n\t\t\tfor( ; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t\t\t{\r\n\t\t\t\t// Check to see if writing another particle will take us over the edge.\r\n\t\t\t\tif(( dwords_written + dwords_per_particle ) > 2047 )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfloat terp\t= p_particle->m_time / p_particle->m_life;\r\n\t\t\t\tfloat w\t\t= p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\t\t\tfloat h\t\t= p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\t\t\tMth::Vector\tss_right, ss_up;\r\n\t\t\t\tMth::Vector tmp0, tmp1, tmp2, tmp3;\r\n\t\r\n\t\t\t\t// Dynamic bounding box calculation.\r\n//\t\t\t\tif( lp == 0 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tmin = pos;\r\n//\t\t\t\t\tmax = pos;\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( pos[X] < min[X] ) min[X] = pos[X]; else if( pos[X] > max[X] ) max[X] = pos[X];\r\n//\t\t\t\t\tif( pos[Y] < min[Y] ) min[Y] = pos[Y]; else if( pos[Y] > max[Y] ) max[Y] = pos[Y];\r\n//\t\t\t\t\tif( pos[Z] < min[Z] ) min[Z] = pos[Z]; else if( pos[Z] > max[Z] ) max[Z] = pos[Z];\r\n//\t\t\t\t}\r\n\r\n\t\t\t\tss_right\t= screen_right * w;\r\n\t\t\t\tss_up\t\t= screen_up * h;\r\n\t\r\n\t\t\t\tImage::RGBA color[3];\r\n\t\t\t\tImage::RGBA *p_col0;\r\n\t\t\t\tImage::RGBA *p_col1;\r\n\r\n\t\t\t\tif ( m_mid_time >= 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( terp < m_mid_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\t\tp_col1 = m_mid_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\t\t\tp_col1 = m_end_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No mid color specified.\r\n\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Swap red and blue here.\r\n\t\t\t\tfor( int c = 0; c < 3; c++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tImage::RGBA start\t= *p_col0++;\r\n\t\t\t\t\tImage::RGBA end\t\t= *p_col1++;\r\n\r\n\t\t\t\t\tcolor[c].b = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\t\t\tcolor[c].r = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttmp0  = pos;\r\n\t\t\t\ttmp0 += ss_right * sinf( 0.0f ) * m_split;\r\n\t\t\t\ttmp0 += ss_up    * cosf( 0.0f ) * m_split;\r\n\r\n\t\t\t\ttmp2  = pos;\r\n\t\t\t\ttmp2 += ss_right * sinf( 0.0f );\r\n\t\t\t\ttmp2 += ss_up    * cosf( 0.0f );\r\n\r\n\t\t\t\tfloat radians_per_segment\t= ( 2.0f * Mth::PI ) / (float)m_num_segments;\r\n\r\n\t\t\t\tfor( int lp2 = 0; lp2 < m_num_segments; lp2++ )\r\n\t\t\t\t{\r\n\t\t\t\t\ttmp1  = pos;\r\n\t\t\t\t\ttmp1 += ss_right * sinf( radians_per_segment * ( lp2 + 1 )) * m_split;\r\n\t\t\t\t\ttmp1 += ss_up    * cosf( radians_per_segment * ( lp2 + 1 )) * m_split;\r\n\r\n\t\t\t\t\ttmp3  = pos;\r\n\t\t\t\t\ttmp3 += ss_right * sinf( radians_per_segment * ( lp2 + 1 ));\r\n\t\t\t\t\ttmp3 += ss_up    * cosf( radians_per_segment * ( lp2 + 1 ));\r\n\r\n\t\t\t\t\t// Triangle zero.\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&pos[X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&pos[Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&pos[Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\r\n\t\t\t\t\tp_push[4]\t= *((DWORD*)&tmp0[X] );\r\n\t\t\t\t\tp_push[5]\t= *((DWORD*)&tmp0[Y] );\r\n\t\t\t\t\tp_push[6]\t= *((DWORD*)&tmp0[Z] );\r\n\t\t\t\t\tp_push[7]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_push[8]\t= *((DWORD*)&tmp1[X] );\r\n\t\t\t\t\tp_push[9]\t= *((DWORD*)&tmp1[Y] );\r\n\t\t\t\t\tp_push[10]\t= *((DWORD*)&tmp1[Z] );\r\n\t\t\t\t\tp_push[11]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\r\n\t\t\t\t\t// Triangle one.\r\n\t\t\t\t\tp_push[12]\t= *((DWORD*)&tmp0[X] );\r\n\t\t\t\t\tp_push[13]\t= *((DWORD*)&tmp0[Y] );\r\n\t\t\t\t\tp_push[14]\t= *((DWORD*)&tmp0[Z] );\r\n\t\t\t\t\tp_push[15]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_push[16]\t= *((DWORD*)&tmp1[X] );\r\n\t\t\t\t\tp_push[17]\t= *((DWORD*)&tmp1[Y] );\r\n\t\t\t\t\tp_push[18]\t= *((DWORD*)&tmp1[Z] );\r\n\t\t\t\t\tp_push[19]\t= *((DWORD*)&color[1] );\r\n\r\n\t\t\t\t\tp_push[20]\t= *((DWORD*)&tmp2[X] );\r\n\t\t\t\t\tp_push[21]\t= *((DWORD*)&tmp2[Y] );\r\n\t\t\t\t\tp_push[22]\t= *((DWORD*)&tmp2[Z] );\r\n\t\t\t\t\tp_push[23]\t= *((DWORD*)&color[2] );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Triangle two.\r\n\t\t\t\t\tp_push[24]\t= *((DWORD*)&tmp1[X] );\r\n\t\t\t\t\tp_push[25]\t= *((DWORD*)&tmp1[Y] );\r\n\t\t\t\t\tp_push[26]\t= *((DWORD*)&tmp1[Z] );\r\n\t\t\t\t\tp_push[27]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_push[28]\t= *((DWORD*)&tmp2[X] );\r\n\t\t\t\t\tp_push[29]\t= *((DWORD*)&tmp2[Y] );\r\n\t\t\t\t\tp_push[30]\t= *((DWORD*)&tmp2[Z] );\r\n\t\t\t\t\tp_push[31]\t= *((DWORD*)&color[2] );\r\n\r\n\t\t\t\t\tp_push[32]\t= *((DWORD*)&tmp3[X] );\r\n\t\t\t\t\tp_push[33]\t= *((DWORD*)&tmp3[Y] );\r\n\t\t\t\t\tp_push[34]\t= *((DWORD*)&tmp3[Z] );\r\n\t\t\t\t\tp_push[35]\t= *((DWORD*)&color[2] );\r\n\t\t\t\t\tp_push\t\t+= 36;\r\n\t\t\t\t\t\r\n\t\t\t\t\ttmp0 = tmp1;\r\n\t\t\t\t\ttmp2 = tmp3;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tdwords_written\t+= dwords_per_particle;\r\n\t\t\t\tdword_count\t\t-= dwords_per_particle;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1] = 0;\r\n\t\tp_push += 2;\r\n\t\tD3DDevice_EndPush( p_push );\r\n\r\n\t\t// Set the mesh bounding box and sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMin( min );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMax( max );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center = D3DXVECTOR3( min[X] + (( max[X] - min[X] ) * 0.5f ), min[Y] + (( max[Y] - min[Y] ) * 0.5f ), min[Z] + (( max[Z] - min[Z] ) * 0.5f ));\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius = 360.0f;\r\n\r\n\t\t// And the scene bounding sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_center = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center;\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_radius = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius;\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticleglow.h",
    "content": "#ifndef\t__GFX_P_NX_PARTICLEGlow_H__\r\n#define\t__GFX_P_NX_PARTICLEGlow_H__\r\n    \r\n#include \"gfx/xbox/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CXboxParticleGlow : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCXboxParticleGlow();\r\n\t\t\t\t\t\t\tCXboxParticleGlow( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split );\r\n\tvirtual \t\t\t\t~CXboxParticleGlow();\r\n\r\n\tNxXbox::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n\r\n\tNxXbox::sParticleSystem*\tmp_engine_particle;\r\n\tint\t\t\t\t\t\tm_num_segments;\r\n\tfloat\t\t\t\t\tm_split;\r\n\tImage::RGBA\t\t\t\tm_start_color[3];\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color[3];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color[3];\t\t\t\t// End color for each corner.\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticleglowribbontrail.cpp",
    "content": "#include <core/defines.h>\r\n#include \"gfx/xbox/nx/render.h\"\r\n\r\n#include \"gfx/xbox/p_nxparticleGlowRibbonTrail.h\"\r\n\r\nextern DWORD PixelShader1;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCXboxParticleGlowRibbonTrail::CXboxParticleGlowRibbonTrail()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleGlowRibbonTrail::CXboxParticleGlowRibbonTrail( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum\t\t= checksum;\r\n\tm_max_particles\t= max_particles;\r\n\tm_num_particles\t= 0;\r\n\tm_mid_time\t\t= -1.0f;\r\n\tm_num_segments\t= num_segments;\r\n\tm_segment_step\t= 360.0f / m_num_segments;\r\n\tm_history\t\t= history;\r\n\tm_split\t\t\t= split;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float*[( history + 1)];\r\n\tfor( int lp = 0; lp < ( history + 1 ); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n\t// Create the engine representation.\r\n\tmp_engine_particle = new NxXbox::sParticleSystem( max_particles, NxXbox::PARTICLE_TYPE_GLOWRIBBONTRAIL, texture_checksum, blendmode_checksum, fix, num_segments, history );\r\n\r\n\t// Default color.\r\n\tm_start_color = new Image::RGBA[m_num_vertex_buffers + 3];\r\n\tm_mid_color = new Image::RGBA[m_num_vertex_buffers + 3];\r\n\tm_end_color = new Image::RGBA[m_num_vertex_buffers + 3];\r\n\tfor ( int lp = 0; lp < ( m_num_vertex_buffers + 3 ); lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 128;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 128;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 128;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleGlowRibbonTrail::~CXboxParticleGlowRibbonTrail()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\r\n\tdelete [] m_start_color;\r\n\tdelete [] m_mid_color;\r\n\tdelete [] m_end_color;\r\n\tdelete mp_engine_particle;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleGlowRibbonTrail::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleGlowRibbonTrail::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleGlowRibbonTrail::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CXboxParticleGlowRibbonTrail::plat_get_num_particle_colors( void ) { return m_num_vertex_buffers + 3; }\r\nint CXboxParticleGlowRibbonTrail::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CXboxParticleGlowRibbonTrail::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CXboxParticleGlowRibbonTrail::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CXboxParticleGlowRibbonTrail::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CXboxParticleGlowRibbonTrail::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value >> 1; }\r\nvoid CXboxParticleGlowRibbonTrail::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CXboxParticleGlowRibbonTrail::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CXboxParticleGlowRibbonTrail::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CXboxParticleGlowRibbonTrail::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value >> 1; }\r\nvoid CXboxParticleGlowRibbonTrail::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CXboxParticleGlowRibbonTrail::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CXboxParticleGlowRibbonTrail::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CXboxParticleGlowRibbonTrail::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value >> 1; }\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleGlowRibbonTrail::plat_render( void )\r\n{\r\n\t// Draw the particles.\r\n\tif( m_num_particles > 0 )\r\n\t{\r\n\t\tint\t\t\t\tlp;\r\n\t\tCParticleEntry\t*p_particle;\r\n\t\tfloat\t\t\t*p_v0, *p_v1;\r\n\r\n\t\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\r\n\t\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\t\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\t\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\t\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\t\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\t\tImage::RGBA color[3];\r\n\t\tImage::RGBA *p_col0;\r\n\t\tImage::RGBA *p_col1;\r\n\t\t\r\n\t\t// Obtain push buffer lock.\r\n\t\tDWORD *p_push; \r\n\t\tDWORD dwords_per_particle\t= ( 36 * m_num_segments ) + ( 24 * ( m_num_vertex_buffers - 1 ));\r\n\t\tDWORD dword_count\t\t\t= dwords_per_particle * m_num_particles;\r\n\r\n\t\t// Submit particle material.\r\n\t\tmp_engine_particle->mp_material->Submit();\r\n\t\t\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\t\tNxXbox::set_pixel_shader( PixelShader1 );\r\n\t\t\r\n\t\t// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.\r\n\t\tp_push = D3DDevice_BeginPush( dword_count + 32 );\r\n\r\n\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1]\t= D3DPT_TRIANGLELIST;\r\n\t\tp_push\t\t+= 2;\r\n\r\n\t\t// Set up loop variables here, since we be potentially enetering the loop more than once.\r\n\t\tlp\t\t\t= 0;\r\n\t\tp_particle\t= mp_particle_array;\r\n\t\tp_v0\t\t= mp_vertices[0];\r\n\t\tp_v1\t\t= mp_vertices[(m_num_vertex_buffers - 1)];\r\n\r\n\t\twhile( dword_count > 0 )\r\n\t\t{\r\n\t\t\tint dwords_written = 0;\r\n\r\n\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, ( dword_count > 2047 ) ? ((int)( 2047 / dwords_per_particle )) * dwords_per_particle: dword_count );\r\n\t\t\t++p_push;\r\n\t\t\r\n\t\t\tfor( ; lp < m_num_particles; lp++, p_particle++, p_v0 += 3, p_v1 += 3 )\r\n\t\t\t{\r\n\t\t\t\t// Check to see if writing another particle will take us over the edge.\r\n\t\t\t\tif(( dwords_written + dwords_per_particle ) > 2047 )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// Calculate the interpolator ( 1.0f / particle_life ).\r\n\t\t\t\tfloat terp = p_particle->m_time * ReciprocalEstimateNR_ASM( p_particle->m_life );\r\n\r\n\t\t\t\tMth::Vector\tpos[2];\r\n\t\t\t\tp_v0 = &mp_vertices[0][lp*3];\r\n\t\t\t\tpos[0].Set( p_v0[0] + m_pos[X], p_v0[1] + m_pos[Y], p_v0[2] + m_pos[Z] );\r\n\t\t\t\tp_v0 = &mp_vertices[1][lp*3];\r\n\t\t\t\tpos[1].Set( p_v0[0] + m_pos[X], p_v0[1] + m_pos[Y], p_v0[2] + m_pos[Z] );\r\n\t\t\t\r\n\t\t\t\tMth::Vector\tpart_vec = pos[1] - pos[0];\r\n\t\t\t\tMth::Vector perp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\t\t\tperp_vec.Normalize();\r\n\r\n\t\t\t\tfloat w = p_particle->m_sw + (( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\t\t\tfloat h = p_particle->m_sh + (( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\t\t\r\n\t\t\t\tMth::Vector tmp[4];\r\n\r\n\t\t\t\tif( m_mid_time >= 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( terp < m_mid_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = &m_start_color[3];\r\n\t\t\t\t\t\tp_col1 = &m_mid_color[3];\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = &m_mid_color[3];\r\n\t\t\t\t\t\tp_col1 = &m_end_color[3];\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No mid color specified.\r\n\t\t\t\t\tp_col0 = &m_start_color[3];\r\n\t\t\t\t\tp_col1 = &m_end_color[3];\r\n\t\t\t\t}\r\n\r\n\t\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\t\t// Interpolate and swap red and blue here. Use fixed point math to avoid _ftol2 calls.\r\n\t\t\t\tint f_terp\t= Ftoi_ASM( terp * 4096.0f );\r\n\t\t\t\tcolor[0].b\t= ((((int)start.r ) * 4096 ) + (((int)end.r - (int)start.r ) * f_terp )) / 4096;\r\n\t\t\t\tcolor[0].g\t= ((((int)start.g ) * 4096 ) + (((int)end.g - (int)start.g ) * f_terp )) / 4096;\r\n\t\t\t\tcolor[0].r\t= ((((int)start.b ) * 4096 ) + (((int)end.b - (int)start.b ) * f_terp )) / 4096;\r\n\t\t\t\tcolor[0].a\t= ((((int)start.a ) * 4096 ) + (((int)end.a - (int)start.a ) * f_terp )) / 4096;\r\n\r\n\t\t\t\ttmp[0]\t\t= pos[0] + ( perp_vec * w * m_split );\r\n\t\t\t\ttmp[1]\t\t= pos[0] - ( perp_vec * w * m_split );\r\n\r\n\t\t\t\tfor( int c = 1; c < m_num_vertex_buffers; c++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tstart = *p_col0++;\r\n\t\t\t\t\tend = *p_col1++;\r\n\r\n\t\t\t\t\t// Interpolate and swap red and blue here. Use fixed point math to avoid _ftol2 calls.\r\n\t\t\t\t\tcolor[1].b\t= ((((int)start.r ) * 4096 ) + (((int)end.r - (int)start.r ) * f_terp )) / 4096;\r\n\t\t\t\t\tcolor[1].g\t= ((((int)start.g ) * 4096 ) + (((int)end.g - (int)start.g ) * f_terp )) / 4096;\r\n\t\t\t\t\tcolor[1].r\t= ((((int)start.b ) * 4096 ) + (((int)end.b - (int)start.b ) * f_terp )) / 4096;\r\n\t\t\t\t\tcolor[1].a\t= ((((int)start.a ) * 4096 ) + (((int)end.a - (int)start.a ) * f_terp )) / 4096;\r\n\r\n\t\t\t\t\tif ( c > 1 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_v0 = &mp_vertices[c][lp*3];\r\n\t\t\t\t\t\tpos[1].Set( p_v0[0] + m_pos[X], p_v0[1] + m_pos[Y], p_v0[2] + m_pos[Z] );\r\n\t\t\t\t\t\tpart_vec = pos[1] - pos[0];\r\n\t\t\t\t\t\tperp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\t\t\t\t\tperp_vec.Normalize();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttmp[2]\t\t= pos[1] + ( perp_vec * w * m_split );\r\n\t\t\t\t\ttmp[3]\t\t= pos[1] - ( perp_vec * w * m_split );\r\n\r\n\t\t\t\t\t// First tri.\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[0][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[0][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[0][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[1][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[1][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[1][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[2][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[2][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[2][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\t// Second tri.\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[1][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[1][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[1][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[3][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[3][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[3][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[2][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[2][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[2][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tcolor[0] = color[1];\r\n\t\t\t\t\tpos[0] = pos[1];\r\n\t\t\t\t\ttmp[0] = tmp[2];\r\n\t\t\t\t\ttmp[1] = tmp[3];\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Now draw the glow.\r\n\t\t\t\tp_v0 = &mp_vertices[0][lp*3];\r\n\t\t\t\tpos[0].Set( p_v0[0] + m_pos[X], p_v0[1] + m_pos[Y], p_v0[2] + m_pos[Z] );\r\n\t\t\t\tMth::Vector\tss_right, ss_up;\r\n\t\r\n\t\t\t\tss_right\t= screen_right * w;\r\n\t\t\t\tss_up\t\t= screen_up * h;\r\n\r\n\t\t\t\tif( m_mid_time >= 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( terp < m_mid_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\t\tp_col1 = m_mid_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\t\t\tp_col1 = m_end_color;\r\n\t\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No mid color specified.\r\n\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t}\r\n\t\t\r\n\t\t\t\t// Swap red and blue here.\r\n\t\t\t\tfor( int c = 0; c < 3; c++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\t\t\t// Interpolate and swap red and blue here. Use fixed point math to avoid _ftol2 calls.\r\n\t\t\t\t\tcolor[c].b\t= ((((int)start.r ) * 4096 ) + (((int)end.r - (int)start.r ) * f_terp )) / 4096;\r\n\t\t\t\t\tcolor[c].g\t= ((((int)start.g ) * 4096 ) + (((int)end.g - (int)start.g ) * f_terp )) / 4096;\r\n\t\t\t\t\tcolor[c].r\t= ((((int)start.b ) * 4096 ) + (((int)end.b - (int)start.b ) * f_terp )) / 4096;\r\n\t\t\t\t\tcolor[c].a\t= ((((int)start.a ) * 4096 ) + (((int)end.a - (int)start.a ) * f_terp )) / 4096;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// We know that sin( 0 ) = 0, and cos( 0 ) = 1, so we can optimise the first iteration.\r\n\t\t\t\ttmp[0]  = pos[0];\r\n\t\t\t\ttmp[0] += ss_right * 0.0f * m_split;\r\n\t\t\t\ttmp[0] += ss_up    * 1.0f * m_split;\r\n\r\n\t\t\t\ttmp[2]  = pos[0];\r\n\t\t\t\ttmp[2] += ss_right * 0.0f;\r\n\t\t\t\ttmp[2] += ss_up    * 1.0f;\r\n\r\n\t\t\t\tfor ( int lp2 = 0; lp2 < m_num_segments; lp2++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tfloat rt\t= sinf( Mth::DegToRad( m_segment_step * ( lp2 + 1 )));\r\n\t\t\t\t\tfloat up\t= cosf( Mth::DegToRad( m_segment_step * ( lp2 + 1 )));\r\n\r\n\t\t\t\t\ttmp[1]  = pos[0];\r\n\t\t\t\t\ttmp[1] += ss_right * rt * m_split;\r\n\t\t\t\t\ttmp[1] += ss_up    * up * m_split;\r\n\r\n\t\t\t\t\ttmp[3]  = pos[0];\r\n\t\t\t\t\ttmp[3] += ss_right * rt;\r\n\t\t\t\t\ttmp[3] += ss_up    * up;\r\n\r\n\t\t\t\t\t// First tri.\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&pos[0][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&pos[0][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&pos[0][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[0][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[0][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[0][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[1][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[1][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[1][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\t// Second tri.\t\t\t\t\t\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[0][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[0][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[0][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[1][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[1][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[1][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[2][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[2][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[2][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[2] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\t// Third tri.\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[1][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[1][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[1][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[2][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[2][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[2][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[2] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[3][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[3][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[3][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[2] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\ttmp[0] = tmp[1];\r\n\t\t\t\t\ttmp[2] = tmp[3];\r\n\t\t\t\t}\r\n\t\t\t\tdwords_written\t+= dwords_per_particle;\r\n\t\t\t\tdword_count\t\t-= dwords_per_particle;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1] = 0;\r\n\t\tp_push += 2;\r\n\t\tD3DDevice_EndPush( p_push );\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticleglowribbontrail.h",
    "content": "#ifndef\t__GFX_P_NX_PARTICLEGlowRibbonTrail_H__\r\n#define\t__GFX_P_NX_PARTICLEGlowRibbonTrail_H__\r\n    \r\n#include \"gfx/xbox/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CXboxParticleGlowRibbonTrail : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCXboxParticleGlowRibbonTrail();\r\n\t\t\t\t\t\t\tCXboxParticleGlowRibbonTrail( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CXboxParticleGlowRibbonTrail();\r\n\r\n\tNxXbox::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\tint\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tfloat**\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n\tNxXbox::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tint\t\t\t\t\t\tm_num_segments;\r\n\tfloat\t\t\t\t\tm_segment_step;\t\t\t\t// 360.0f / m_num_segments;\r\n\tint\t\t\t\t\t\tm_history;\r\n\tfloat\t\t\t\t\tm_split;\r\n\tImage::RGBA*\t\t\tm_start_color;\t\t\t\t// Start color for each corner.\r\n\tImage::RGBA*\t\t\tm_mid_color;\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA*\t\t\tm_end_color;\t\t\t\t// End color for each corner.\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticleline.cpp",
    "content": "#include <core/defines.h>\r\n#include \"gfx/xbox/nx/render.h\"\r\n\r\n#include \"gfx/xbox/p_nxparticleLine.h\"\r\n\r\nextern DWORD PixelShader1;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleLine::CXboxParticleLine()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleLine::CXboxParticleLine( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split )\r\n{\r\n\tm_checksum\t\t= checksum;\r\n\tm_max_particles\t= max_particles;\r\n\tm_num_particles\t= 0;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices[0] = new float[max_particles * 3];\r\n\tmp_vertices[1] = new float[max_particles * 3];\t\t// 2nd buffer to keep history.\r\n\r\n\t// Create the engine representation.\r\n\tmp_engine_particle\t= new NxXbox::sParticleSystem( max_particles, NxXbox::PARTICLE_TYPE_LINE, texture_checksum, blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 2; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = m_start_color[lp].g = m_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 255;\r\n\t\tm_mid_color[lp].r = m_mid_color[lp].g = m_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 255;\r\n\t\tm_end_color[lp].r = m_end_color[lp].g = m_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 255;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleLine::~CXboxParticleLine()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices[0];\r\n\tdelete [] mp_vertices[1];\r\n\r\n\tdelete mp_engine_particle;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleLine::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleLine::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleLine::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CXboxParticleLine::plat_get_num_particle_colors( void ) { return 2; }\r\nint CXboxParticleLine::plat_get_num_vertex_lists( void ) { return 2; }\r\nvoid CXboxParticleLine::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CXboxParticleLine::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CXboxParticleLine::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CXboxParticleLine::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CXboxParticleLine::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CXboxParticleLine::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CXboxParticleLine::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CXboxParticleLine::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CXboxParticleLine::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CXboxParticleLine::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CXboxParticleLine::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CXboxParticleLine::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleLine::plat_render( void )\r\n{\r\n\tif( m_num_particles > 0 )\r\n\t{\r\n\t\tint\t\t\t\tlp;\r\n\t\tCParticleEntry\t*p_particle;\r\n\t\tfloat\t\t\t*p_v0, *p_v1;\r\n//\t\tMth::Vector\t\tmin, max;\t// For dynamic bounding box calculation.\r\n\t\r\n\t\t// Obtain push buffer lock.\r\n\t\tDWORD *p_push; \r\n\t\tDWORD dwords_per_particle\t= 8;\r\n\t\tDWORD dword_count\t\t\t= dwords_per_particle * m_num_particles;\r\n\r\n\t\t// Submit particle material.\r\n\t\tmp_engine_particle->mp_material->Submit();\r\n\t\t\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\t\tNxXbox::set_pixel_shader( PixelShader1 );\r\n\t\t\r\n\t\t// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.\r\n\t\tp_push = D3DDevice_BeginPush( dword_count + 32 );\r\n\r\n\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1]\t= D3DPT_LINELIST;\r\n\t\tp_push\t\t+= 2;\r\n\r\n\t\t// Set up loop variables here, since we be potentially enetering the loop more than once.\r\n\t\tlp\t\t\t= 0;\r\n\t\tp_particle\t= mp_particle_array;\r\n\t\tp_v0\t\t= mp_vertices[0];\r\n\t\tp_v1\t\t= mp_vertices[1];\r\n\r\n\t\twhile( dword_count > 0 )\r\n\t\t{\r\n\t\t\tint dwords_written = 0;\r\n\r\n\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, ( dword_count > 2047 ) ? ((int)( 2047 / dwords_per_particle )) * dwords_per_particle: dword_count );\r\n\t\t\t++p_push;\r\n\t\t\r\n\t\t\tfor( ; lp < m_num_particles; lp++, p_particle++, p_v0 += 3, p_v1 += 3 )\r\n\t\t\t{\r\n\t\t\t\t// Check to see if writing another particle will take us over the edge.\r\n\t\t\t\tif(( dwords_written + dwords_per_particle ) > 2047 )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\t\t\t// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.\r\n\t\t\t\tMth::Vector\tpos0( p_v0[0] + m_pos[X], p_v0[1] + m_pos[Y], p_v0[2] + m_pos[Z] );\r\n\t\t\t\tMth::Vector\tpos1( p_v1[0] + m_pos[X], p_v1[1] + m_pos[Y], p_v1[2] + m_pos[Z] );\r\n\t\r\n\t\t\t\t// Dynamic bounding box calculation.\r\n//\t\t\t\tif( lp == 0 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tmin = pos0;\r\n//\t\t\t\t\tmax = pos0;\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( pos0[X] < min[X] ) min[X] = pos0[X]; else if( pos0[X] > max[X] ) max[X] = pos0[X];\r\n//\t\t\t\t\tif( pos0[Y] < min[Y] ) min[Y] = pos0[Y]; else if( pos0[Y] > max[Y] ) max[Y] = pos0[Y];\r\n//\t\t\t\t\tif( pos0[Z] < min[Z] ) min[Z] = pos0[Z]; else if( pos0[Z] > max[Z] ) max[Z] = pos0[Z];\r\n//\t\t\t\t}\r\n\r\n\t\t\t\tImage::RGBA color[2];\r\n\t\t\t\tImage::RGBA *p_col0[2];\r\n\t\t\t\tImage::RGBA *p_col1[2];\r\n\t\t\r\n\t\t\t\tif( m_mid_time >= 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( terp < m_mid_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0[0] = &m_start_color[0];\r\n\t\t\t\t\t\tp_col1[0] = &m_mid_color[0];\r\n\t\t\t\t\t\tp_col0[1] = &m_start_color[1];\r\n\t\t\t\t\t\tp_col1[1] = &m_mid_color[1];\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0[0] = &m_mid_color[0];\r\n\t\t\t\t\t\tp_col1[0] = &m_end_color[0];\r\n\t\t\t\t\t\tp_col0[1] = &m_mid_color[1];\r\n\t\t\t\t\t\tp_col1[1] = &m_end_color[1];\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No mid color specified.\r\n\t\t\t\t\tp_col0[0] = &m_start_color[0];\r\n\t\t\t\t\tp_col1[0] = &m_end_color[0];\r\n\t\t\t\t\tp_col0[1] = &m_start_color[1];\r\n\t\t\t\t\tp_col1[1] = &m_end_color[1];\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Swap red and blue here.\r\n\t\t\t\tfor( int c = 0; c < 2; ++c )\r\n\t\t\t\t{\r\n\t\t\t\t\tImage::RGBA start\t= *( p_col0[c] );\r\n\t\t\t\t\tImage::RGBA end\t\t= *( p_col1[c] );\r\n\t\t\t\t\tcolor[c].b = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\t\t\tcolor[c].r = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t\t\t}\r\n\t\t\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&pos0[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&pos0[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&pos0[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&pos1[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&pos1[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&pos1[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\tdwords_written\t+= dwords_per_particle;\r\n\t\t\t\tdword_count\t\t-= dwords_per_particle;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1] = 0;\r\n\t\tp_push += 2;\r\n\t\tD3DDevice_EndPush( p_push );\r\n\r\n\t\t// Set the mesh bounding box and sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMin( min );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMax( max );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center = D3DXVECTOR3( min[X] + (( max[X] - min[X] ) * 0.5f ), min[Y] + (( max[Y] - min[Y] ) * 0.5f ), min[Z] + (( max[Z] - min[Z] ) * 0.5f ));\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius = 360.0f;\r\n\r\n\t\t// And the scene bounding sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_center = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center;\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_radius = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius;\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticleline.h",
    "content": "#ifndef\t__GFX_P_NX_PARTICLELine_H__\r\n#define\t__GFX_P_NX_PARTICLELine_H__\r\n    \r\n#include \"gfx/xbox/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CXboxParticleLine : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCXboxParticleLine();\r\n\t\t\t\t\t\t\t\tCXboxParticleLine( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split );\r\n\tvirtual\t\t\t\t\t\t~CXboxParticleLine();\r\n\r\n\tNxXbox::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\n\tprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\tfloat*\t\t\t\t\t\tmp_vertices[2];\r\n\tuint32*\t\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\t\tm_blend;\r\n\tNxXbox::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tImage::RGBA\t\t\t\t\tm_start_color[2];\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\t\tm_mid_color[2];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\t\tm_end_color[2];\t\t\t\t// End color for each corner.\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticleribbon.cpp",
    "content": "#include <core/defines.h>\r\n#include \"gfx/xbox/nx/render.h\"\r\n\r\n#include \"gfx/xbox/p_nxparticleRibbon.h\"\r\n\r\nextern DWORD PixelShader1;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleRibbon::CXboxParticleRibbon()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleRibbon::CXboxParticleRibbon( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum\t\t= checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\tm_mid_time\t\t= -1.0f;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float*[history + 1];\r\n\tfor( int lp = 0; lp < ( history + 1 ); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n\t// Create the engine representation.\r\n\tmp_engine_particle = new NxXbox::sParticleSystem( max_particles, NxXbox::PARTICLE_TYPE_RIBBON, texture_checksum, blendmode_checksum, fix, num_segments );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 2; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 255;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 255;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 255;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleRibbon::~CXboxParticleRibbon()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor ( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\r\n\tdelete mp_engine_particle;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleRibbon::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleRibbon::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleRibbon::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CXboxParticleRibbon::plat_get_num_particle_colors( void ) { return 2; }\r\nint CXboxParticleRibbon::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CXboxParticleRibbon::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CXboxParticleRibbon::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CXboxParticleRibbon::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CXboxParticleRibbon::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CXboxParticleRibbon::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CXboxParticleRibbon::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CXboxParticleRibbon::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CXboxParticleRibbon::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CXboxParticleRibbon::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CXboxParticleRibbon::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CXboxParticleRibbon::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CXboxParticleRibbon::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleRibbon::plat_render( void )\r\n{\r\n\t// Draw the particles.\r\n\tif( m_num_particles > 0 )\r\n\t{\r\n\t\tint\t\t\t\tlp;\r\n\t\tCParticleEntry\t*p_particle;\r\n\t\tfloat\t\t\t*p_v0;\r\n\t\tfloat\t\t\t*p_v1;\r\n//\t\tMth::Vector\t\tmin, max;\t// For dynamic bounding box calculation.\r\n\r\n\t\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\t\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\r\n\t\tImage::RGBA color[2];\r\n\t\tImage::RGBA *p_col0;\r\n\t\tImage::RGBA *p_col1;\r\n\t\t\r\n\t\t// Obtain push buffer lock.\r\n\t\tDWORD *p_push; \r\n\t\tDWORD dwords_per_particle\t= 16;\r\n\t\tDWORD dword_count\t\t\t= dwords_per_particle * m_num_particles;\r\n\r\n\t\t// Submit particle material.\r\n\t\tmp_engine_particle->mp_material->Submit();\r\n\t\t\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\t\tNxXbox::set_pixel_shader( PixelShader1 );\r\n\t\t\r\n\t\t// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.\r\n\t\tp_push = D3DDevice_BeginPush( dword_count + 32 );\r\n\r\n\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1]\t= D3DPT_QUADLIST;\r\n\t\tp_push\t\t+= 2;\r\n\r\n\t\t// Set up loop variables here, since we be potentially enetering the loop more than once.\r\n\t\tlp\t\t\t= 0;\r\n\t\tp_particle\t= mp_particle_array;\r\n\t\tp_v0\t\t= mp_vertices[0];\r\n\t\tp_v1\t\t= mp_vertices[(m_num_vertex_buffers - 1)];\r\n\r\n\t\twhile( dword_count > 0 )\r\n\t\t{\r\n\t\t\tint dwords_written = 0;\r\n\r\n\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, ( dword_count > 2047 ) ? ((int)( 2047 / dwords_per_particle )) * dwords_per_particle: dword_count );\r\n\t\t\t++p_push;\r\n\t\t\r\n\t\t\tfor( ; lp < m_num_particles; lp++, p_particle++, p_v0 += 3, p_v1 += 3 )\r\n\t\t\t{\r\n\t\t\t\t// Check to see if writing another particle will take us over the edge.\r\n\t\t\t\tif(( dwords_written + dwords_per_particle ) > 2047 )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\t\t\tMth::Vector\tpos0( p_v0[0] + m_pos[X], p_v0[1] + m_pos[Y], p_v0[2] + m_pos[Z] );\r\n\t\t\t\tMth::Vector\tpos1( p_v1[0] + m_pos[X], p_v1[1] + m_pos[Y], p_v1[2] + m_pos[Z] );\r\n\r\n\t\t\t\t// Dynamic bounding box calculation.\r\n//\t\t\t\tif( lp == 0 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tmin = pos0;\r\n//\t\t\t\t\tmax = pos0;\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( pos0[X] < min[X] ) min[X] = pos0[X]; else if( pos0[X] > max[X] ) max[X] = pos0[X];\r\n//\t\t\t\t\tif( pos0[Y] < min[Y] ) min[Y] = pos0[Y]; else if( pos0[Y] > max[Y] ) max[Y] = pos0[Y];\r\n//\t\t\t\t\tif( pos0[Z] < min[Z] ) min[Z] = pos0[Z]; else if( pos0[Z] > max[Z] ) max[Z] = pos0[Z];\r\n//\t\t\t\t}\r\n\r\n\t\t\t\tMth::Vector\tpart_vec = pos1 - pos0;\r\n\t\t\t\tMth::Vector perp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\t\t\tperp_vec.Normalize();\r\n\r\n\t\t\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\t\r\n\t\t\t\tMth::Vector tmp[4];\r\n\t\t\t\ttmp[0]\t\t= pos0 + ( perp_vec * w );\r\n\t\t\t\ttmp[1]\t\t= pos0 - ( perp_vec * w );\r\n\t\t\t\ttmp[2]\t\t= pos1 - ( perp_vec * w );\r\n\t\t\t\ttmp[3]\t\t= pos1 + ( perp_vec * w );\r\n\t\r\n\t\t\t\tif ( m_mid_time >= 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( terp < m_mid_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\t\tp_col1 = m_mid_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\t\t\tp_col1 = m_end_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No mid color specified.\r\n\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( int c = 0; c < 2; c++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\t\t\t// Swap red and blue here.\r\n\t\t\t\t\tcolor[c].b = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\t\t\tcolor[c].r = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor( int v = 0; v < 4; ++v )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[v][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[v][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[v][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[v / 2] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\t\t\t\t}\r\n\t\t\t\tdwords_written\t+= dwords_per_particle;\r\n\t\t\t\tdword_count\t\t-= dwords_per_particle;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1] = 0;\r\n\t\tp_push += 2;\r\n\t\tD3DDevice_EndPush( p_push );\r\n\r\n\t\t// Set the mesh bounding box and sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMin( min );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMax( max );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center = D3DXVECTOR3( min[X] + (( max[X] - min[X] ) * 0.5f ), min[Y] + (( max[Y] - min[Y] ) * 0.5f ), min[Z] + (( max[Z] - min[Z] ) * 0.5f ));\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius = 360.0f;\r\n\r\n\t\t// And the scene bounding sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_center = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center;\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_radius = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius;\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticleribbon.h",
    "content": "#ifndef\t__GFX_P_NX_PARTICLERibbon_H__\r\n#define\t__GFX_P_NX_PARTICLERibbon_H__\r\n    \r\n#include \"gfx/xbox/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CXboxParticleRibbon : public CParticle\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\tCXboxParticleRibbon();\r\n\t\t\t\t\t\t\tCXboxParticleRibbon( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CXboxParticleRibbon();\r\n\r\n\tNxXbox::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\n\r\n\tprivate:\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\tint\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tfloat**\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n\tNxXbox::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tImage::RGBA\t\t\t\tm_start_color[2];\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color[2];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color[2];\t\t\t\t// End color for each corner.\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticlesmooth.cpp",
    "content": "#include <core/defines.h>\r\n#include \"gfx/xbox/nx/render.h\"\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/xbox/p_nxtexture.h>\r\n#include \"gfx/xbox/nx/mesh.h\"\r\n#include \"gfx/xbox/p_nxparticleSmooth.h\"\r\n\r\nextern DWORD PixelShader0;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleSmooth::CXboxParticleSmooth()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleSmooth::CXboxParticleSmooth( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split )\r\n{\r\n\tm_checksum\t\t= checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\tm_mid_time\t\t= -1.0f;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n\t// Create the engine representation.\r\n\tmp_engine_particle = new NxXbox::sParticleSystem( max_particles, NxXbox::PARTICLE_TYPE_SMOOTH, texture_checksum, blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 2; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 255;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 255;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 255;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleSmooth::~CXboxParticleSmooth()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n\tdelete mp_engine_particle;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleSmooth::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleSmooth::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleSmooth::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CXboxParticleSmooth::plat_get_num_particle_colors( void ) { return 2; }\r\nint CXboxParticleSmooth::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CXboxParticleSmooth::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CXboxParticleSmooth::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CXboxParticleSmooth::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CXboxParticleSmooth::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CXboxParticleSmooth::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CXboxParticleSmooth::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CXboxParticleSmooth::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CXboxParticleSmooth::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CXboxParticleSmooth::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CXboxParticleSmooth::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CXboxParticleSmooth::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CXboxParticleSmooth::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleSmooth::plat_render( void )\r\n{\r\n\t// Draw the particles.\r\n\tif( m_num_particles > 0 )\r\n\t{\r\n\t\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\r\n\t\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\t\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\t\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\t\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\t\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\t\tscreen_right.Normalize();\r\n\t\tscreen_up.Normalize();\r\n\t\r\n\t\tint\t\t\t\tlp;\r\n\t\tCParticleEntry\t*p_particle;\r\n\t\tfloat\t\t\t*p_v;\r\n//\t\tMth::Vector\t\tmin, max;\t// For dynamic bounding box calculation.\r\n\r\n\t\t// Obtain push buffer lock.\r\n\t\tDWORD *p_push; \r\n\t\tDWORD dwords_per_particle\t= 72;\r\n\t\tDWORD dword_count\t\t\t= dwords_per_particle * m_num_particles;\r\n\r\n\t\t// Submit particle material.\r\n\t\tmp_engine_particle->mp_material->Submit();\r\n\t\t\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2( 0 ));\r\n\t\tNxXbox::set_pixel_shader( PixelShader0 );\r\n\t\t\r\n\t\t// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.\r\n\t\tp_push = D3DDevice_BeginPush( dword_count + 32 );\r\n\r\n\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1]\t= D3DPT_TRIANGLELIST;\r\n\t\tp_push\t\t+= 2;\r\n\r\n\t\t// Set up loop variables here, since we be potentially enetering the loop more than once.\r\n\t\tlp\t\t\t= 0;\r\n\t\tp_particle\t= mp_particle_array;\r\n\t\tp_v\t\t\t= mp_vertices;\r\n\r\n\t\twhile( dword_count > 0 )\r\n\t\t{\r\n\t\t\tint dwords_written = 0;\r\n\r\n\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, ( dword_count > 2047 ) ? ((int)( 2047 / dwords_per_particle )) * dwords_per_particle: dword_count );\r\n\t\t\t++p_push;\r\n\t\t\r\n\t\t\tfor( ; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t\t\t{\r\n\t\t\t\t// Check to see if writing another particle will take us over the edge.\r\n\t\t\t\tif(( dwords_written + dwords_per_particle ) > 2047 )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfloat terp\t= p_particle->m_time / p_particle->m_life;\r\n\t\t\t\tfloat w\t\t= p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\t\t\tfloat h\t\t= p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\t\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\t\t\tMth::Vector tmp[4];\r\n\t\r\n\t\t\t\t// Dynamic bounding box calculation.\r\n//\t\t\t\tif( lp == 0 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tmin = pos;\r\n//\t\t\t\t\tmax = pos;\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( pos[X] < min[X] ) min[X] = pos[X]; else if( pos[X] > max[X] ) max[X] = pos[X];\r\n//\t\t\t\t\tif( pos[Y] < min[Y] ) min[Y] = pos[Y]; else if( pos[Y] > max[Y] ) max[Y] = pos[Y];\r\n//\t\t\t\t\tif( pos[Z] < min[Z] ) min[Z] = pos[Z]; else if( pos[Z] > max[Z] ) max[Z] = pos[Z];\r\n//\t\t\t\t}\r\n\r\n\t\t\t\tss_right\t= screen_right * w;\r\n\t\t\t\tss_up\t\t= screen_up * h;\r\n\t\t\r\n\t\t\t\ttmp[0]\t\t= pos - ss_right + ss_up;\r\n\t\t\t\ttmp[1]\t\t= pos + ss_right + ss_up;\t\t\r\n\t\t\t\ttmp[2]\t\t= pos + ss_right - ss_up;\t\t\r\n\t\t\t\ttmp[3]\t\t= pos - ss_right - ss_up;\t\t\r\n\t\r\n\t\t\t\tImage::RGBA color[2];\r\n\t\t\t\tImage::RGBA *p_col0;\r\n\t\t\t\tImage::RGBA *p_col1;\r\n\t\t\r\n\t\t\t\tif ( m_mid_time >= 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( terp < m_mid_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\t\tp_col1 = m_mid_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\t\t\tp_col1 = m_end_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No mid color specified.\r\n\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( int c = 0; c < 2; c++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\t\t\tcolor[c].r = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\t\t\tcolor[c].b = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// First triangle.\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&pos[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&pos[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&pos[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\tp_push[4]\t= 0x00000000UL;\r\n\t\t\t\tp_push[5]\t= 0x00000000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[0][X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[0][Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[0][Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\tp_push[4]\t= 0x00000000UL;\r\n\t\t\t\tp_push[5]\t= 0x00000000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[1][X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[1][Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[1][Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\tp_push[4]\t= 0x3F800000UL;\r\n\t\t\t\tp_push[5]\t= 0x00000000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\t\t\t\t\t\r\n\t\t\t\t// Second triangle.\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&pos[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&pos[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&pos[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\tp_push[4]\t= 0x00000000UL;\r\n\t\t\t\tp_push[5]\t= 0x00000000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[1][X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[1][Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[1][Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\tp_push[4]\t= 0x3F800000UL;\r\n\t\t\t\tp_push[5]\t= 0x00000000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[2][X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[2][Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[2][Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\tp_push[4]\t= 0x3F800000UL;\r\n\t\t\t\tp_push[5]\t= 0x3F800000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\t\t\t\t\t\r\n\t\t\t\t// Third triangle.\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&pos[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&pos[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&pos[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\tp_push[4]\t= 0x00000000UL;\r\n\t\t\t\tp_push[5]\t= 0x00000000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[2][X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[2][Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[2][Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\tp_push[4]\t= 0x3F800000UL;\r\n\t\t\t\tp_push[5]\t= 0x3F800000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[3][X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[3][Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[3][Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\tp_push[4]\t= 0x00000000UL;\r\n\t\t\t\tp_push[5]\t= 0x3F800000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\t\t\t\t\t\r\n\t\t\t\t// Fourth triangle.\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&pos[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&pos[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&pos[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\tp_push[4]\t= 0x00000000UL;\r\n\t\t\t\tp_push[5]\t= 0x00000000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[3][X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[3][Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[3][Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\tp_push[4]\t= 0x00000000UL;\r\n\t\t\t\tp_push[5]\t= 0x3F800000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[0][X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[0][Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[0][Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\tp_push[4]\t= 0x00000000UL;\r\n\t\t\t\tp_push[5]\t= 0x00000000UL;\r\n\t\t\t\tp_push\t\t+= 6;\r\n\r\n\t\t\t\tdwords_written\t+= dwords_per_particle;\r\n\t\t\t\tdword_count\t\t-= dwords_per_particle;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1] = 0;\r\n\t\tp_push += 2;\r\n\t\tD3DDevice_EndPush( p_push );\r\n\r\n\t\t// Set the mesh bounding box and sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMin( min );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMax( max );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center = D3DXVECTOR3( min[X] + (( max[X] - min[X] ) * 0.5f ), min[Y] + (( max[Y] - min[Y] ) * 0.5f ), min[Z] + (( max[Z] - min[Z] ) * 0.5f ));\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius = 360.0f;\r\n\r\n\t\t// And the scene bounding sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_center = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center;\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_radius = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius;\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticlesmooth.h",
    "content": "#ifndef\t__GFX_P_NX_PARTICLESmooth_H__\r\n#define\t__GFX_P_NX_PARTICLESmooth_H__\r\n    \r\n#include \"gfx/xbox/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CXboxParticleSmooth : public CParticle\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\tCXboxParticleSmooth();\r\n\t\t\t\t\t\t\tCXboxParticleSmooth( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split );\r\n\tvirtual \t\t\t\t~CXboxParticleSmooth();\r\n\r\n\tNxXbox::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\n\r\n\tprivate:\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\tfloat*\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n\tNxXbox::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tImage::RGBA\t\t\t\tm_start_color[2];\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color[2];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color[2];\t\t\t\t// End color for each corner.\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticlesmoothribbon.cpp",
    "content": "#include <core/defines.h>\r\n#include \"gfx/xbox/nx/render.h\"\r\n\r\n#include \"gfx/xbox/p_nxparticleSmoothRibbon.h\"\r\n\r\nextern DWORD PixelShader1;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleSmoothRibbon::CXboxParticleSmoothRibbon()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleSmoothRibbon::CXboxParticleSmoothRibbon( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history )\r\n{\r\n\tm_checksum\t\t= checksum;\r\n\tm_max_particles = max_particles;\r\n\tm_num_particles = 0;\r\n\tm_mid_time\t\t= -1.0f;\r\n\r\n\tmp_particle_array = new CParticleEntry[max_particles];\r\n\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float*[( history + 1)];\r\n\tfor ( int lp = 0; lp < ( history + 1 ); lp++ )\r\n\t{\r\n\t\tmp_vertices[lp] = new float[max_particles * 3];\r\n\t}\r\n\tm_num_vertex_buffers = history + 1;\r\n\r\n\t// Create the engine representation.\r\n\tmp_engine_particle = new NxXbox::sParticleSystem( max_particles, NxXbox::PARTICLE_TYPE_SMOOTHRIBBON, texture_checksum, blendmode_checksum, fix );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 4; lp++ )\r\n\t{\r\n\t\tm_start_color[lp].r = 128;\r\n\t\tm_start_color[lp].g = 128;\r\n\t\tm_start_color[lp].b = 128;\r\n\t\tm_start_color[lp].a = 255;\r\n\t\tm_mid_color[lp].r = 128;\r\n\t\tm_mid_color[lp].g = 128;\r\n\t\tm_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 255;\r\n\t\tm_end_color[lp].r = 128;\r\n\t\tm_end_color[lp].g = 128;\r\n\t\tm_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 255;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleSmoothRibbon::~CXboxParticleSmoothRibbon()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tfor( int lp = 0; lp < m_num_vertex_buffers; lp++ )\r\n\t{\r\n\t\tdelete [] mp_vertices[lp];\r\n\t}\r\n\tdelete [] mp_vertices;\r\n\tdelete mp_engine_particle;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleSmoothRibbon::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleSmoothRibbon::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleSmoothRibbon::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[list][entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CXboxParticleSmoothRibbon::plat_get_num_particle_colors( void ) { return 4; }\r\nint CXboxParticleSmoothRibbon::plat_get_num_vertex_lists( void ) { return m_num_vertex_buffers; }\r\nvoid CXboxParticleSmoothRibbon::plat_set_sr( int entry, uint8 value ) { m_start_color[entry].r = value; }\r\nvoid CXboxParticleSmoothRibbon::plat_set_sg( int entry, uint8 value ) { m_start_color[entry].g = value; }\r\nvoid CXboxParticleSmoothRibbon::plat_set_sb( int entry, uint8 value ) { m_start_color[entry].b = value; }\r\nvoid CXboxParticleSmoothRibbon::plat_set_sa( int entry, uint8 value ) { m_start_color[entry].a = value; }\r\nvoid CXboxParticleSmoothRibbon::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CXboxParticleSmoothRibbon::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CXboxParticleSmoothRibbon::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CXboxParticleSmoothRibbon::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CXboxParticleSmoothRibbon::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CXboxParticleSmoothRibbon::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CXboxParticleSmoothRibbon::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CXboxParticleSmoothRibbon::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleSmoothRibbon::plat_render( void )\r\n{\r\n\t// Draw the particles.\r\n\tif( m_num_particles > 0 )\r\n\t{\r\n\t\tint\t\t\t\tlp;\r\n\t\tCParticleEntry\t*p_particle;\r\n\t\tfloat\t\t\t*p_v0;\r\n\t\tfloat\t\t\t*p_v1;\r\n\t\tMth::Vector\t\tmin, max;\t// For dynamic bounding box calculation.\r\n\r\n\t\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\t\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\r\n\t\tImage::RGBA color[4];\r\n\t\tImage::RGBA *p_col0;\r\n\t\tImage::RGBA *p_col1;\r\n\t\t\r\n\t\t// Obtain push buffer lock.\r\n\t\tDWORD *p_push; \r\n\t\tDWORD dwords_per_particle\t= 32;\r\n\t\tDWORD dword_count\t\t\t= dwords_per_particle * m_num_particles;\r\n\r\n\t\t// Submit particle material.\r\n\t\tmp_engine_particle->mp_material->Submit();\r\n\t\t\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\t\tNxXbox::set_pixel_shader( PixelShader1 );\r\n\t\t\r\n\t\t// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.\r\n\t\tp_push = D3DDevice_BeginPush( dword_count + 32 );\r\n\r\n\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1]\t= D3DPT_QUADLIST;\r\n\t\tp_push\t\t+= 2;\r\n\r\n\t\t// Set up loop variables here, since we be potentially enetering the loop more than once.\r\n\t\tlp\t\t\t= 0;\r\n\t\tp_particle\t= mp_particle_array;\r\n\t\tp_v0\t\t= mp_vertices[0];\r\n\t\tp_v1\t\t= mp_vertices[(m_num_vertex_buffers - 1)];\r\n\r\n\t\twhile( dword_count > 0 )\r\n\t\t{\r\n\t\t\tint dwords_written = 0;\r\n\r\n\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, ( dword_count > 2047 ) ? ((int)( 2047 / dwords_per_particle )) * dwords_per_particle: dword_count );\r\n\t\t\t++p_push;\r\n\t\t\r\n\t\t\tfor( ; lp < m_num_particles; lp++, p_particle++, p_v0 += 3, p_v1 += 3 )\r\n\t\t\t{\r\n\t\t\t\t// Check to see if writing another particle will take us over the edge.\r\n\t\t\t\tif(( dwords_written + dwords_per_particle ) > 2047 )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfloat terp = p_particle->m_time / p_particle->m_life;\r\n\r\n\t\t\t\tMth::Vector\tpos0( p_v0[0] + m_pos[X], p_v0[1] + m_pos[Y], p_v0[2] + m_pos[Z] );\r\n\t\t\t\tMth::Vector\tpos1( p_v1[0] + m_pos[X], p_v1[1] + m_pos[Y], p_v1[2] + m_pos[Z] );\r\n\r\n\t\t\t\t// Dynamic bounding box calculation.\r\n//\t\t\t\tif( lp == 0 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tmin = pos0;\r\n//\t\t\t\t\tmax = pos0;\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( pos0[X] < min[X] ) min[X] = pos0[X]; else if( pos0[X] > max[X] ) max[X] = pos0[X];\r\n//\t\t\t\t\tif( pos0[Y] < min[Y] ) min[Y] = pos0[Y]; else if( pos0[Y] > max[Y] ) max[Y] = pos0[Y];\r\n//\t\t\t\t\tif( pos0[Z] < min[Z] ) min[Z] = pos0[Z]; else if( pos0[Z] > max[Z] ) max[Z] = pos0[Z];\r\n//\t\t\t\t}\r\n\r\n\t\t\t\tMth::Vector\tpart_vec = pos1 - pos0;\r\n\t\t\t\tMth::Vector perp_vec = Mth::CrossProduct( part_vec, at );\r\n\t\t\t\tperp_vec.Normalize();\r\n\r\n\t\t\t\tfloat w = p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\t\r\n\t\t\t\tMth::Vector tmp[4];\r\n\t\t\t\ttmp[0]\t\t= pos0 + ( perp_vec * w );\r\n\t\t\t\ttmp[1]\t\t= pos0 - ( perp_vec * w );\r\n\t\t\t\ttmp[2]\t\t= pos1 - ( perp_vec * w );\r\n\t\t\t\ttmp[3]\t\t= pos1 + ( perp_vec * w );\r\n\t\r\n\t\t\t\tif( m_mid_time >= 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( terp < m_mid_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\t\tp_col1 = m_mid_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\t\t\tp_col1 = m_end_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No mid color specified.\r\n\t\t\t\t\tp_col0 = m_start_color;\r\n\t\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor( int c = 0; c < 4; c++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tImage::RGBA start = *p_col0++;\r\n\t\t\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\t\t\t// Swap red and blue here.\r\n\t\t\t\t\tcolor[c].b = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));\r\n\t\t\t\t\tcolor[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));\r\n\t\t\t\t\tcolor[c].r = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));\r\n\t\t\t\t\tcolor[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// First quad.\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&pos0[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&pos0[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&pos0[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&pos1[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&pos1[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&pos1[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[3] );\r\n\t\t\t\tp_push\t\t+= 4;\r\n\t\t\t\t\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[3][X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[3][Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[3][Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[2] );\r\n\t\t\t\tp_push\t\t+= 4;\r\n\t\t\t\t\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[0][X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[0][Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[0][Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\tp_push\t\t+= 4;\r\n\t\t\t\t\r\n\t\t\t\t// Second quad.\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&pos0[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&pos0[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&pos0[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&pos1[X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&pos1[Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&pos1[Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[3] );\r\n\t\t\t\tp_push\t\t+= 4;\r\n\t\t\t\t\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[2][X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[2][Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[2][Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[2] );\r\n\t\t\t\tp_push\t\t+= 4;\r\n\t\t\t\t\r\n\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[1][X] );\r\n\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[1][Y] );\r\n\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[1][Z] );\r\n\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\tdwords_written\t+= dwords_per_particle;\r\n\t\t\t\tdword_count\t\t-= dwords_per_particle;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1] = 0;\r\n\t\tp_push += 2;\r\n\t\tD3DDevice_EndPush( p_push );\r\n\r\n\t\t// Set the mesh bounding box and sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMin( min );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMax( max );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center = D3DXVECTOR3( min[X] + (( max[X] - min[X] ) * 0.5f ), min[Y] + (( max[Y] - min[Y] ) * 0.5f ), min[Z] + (( max[Z] - min[Z] ) * 0.5f ));\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius = 360.0f;\r\n\r\n\t\t// And the scene bounding sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_center = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center;\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_radius = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius;\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticlesmoothribbon.h",
    "content": "#ifndef\t__GFX_P_NX_PARTICLESmoothRibbon_H__\r\n#define\t__GFX_P_NX_PARTICLESmoothRibbon_H__\r\n    \r\n#include \"gfx/xbox/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Here's a machine specific implementation of the CParticle\r\n    \r\nclass CXboxParticleSmoothRibbon : public CParticle\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCXboxParticleSmoothRibbon();\r\n\t\t\t\t\t\t\tCXboxParticleSmoothRibbon( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n\tvirtual \t\t\t\t~CXboxParticleSmoothRibbon();\r\n\r\n\tNxXbox::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\n\r\n\tprivate:\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\tint\t\t\t\t\t\tm_num_vertex_buffers;\r\n\tfloat**\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\tm_blend;\r\n\tNxXbox::sParticleSystem*\tmp_engine_particle;\r\n\r\n\tImage::RGBA\t\t\t\tm_start_color[4];\t\t\t// Start color for each corner.\r\n\tImage::RGBA\t\t\t\tm_mid_color[4];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\tm_end_color[4];\t\t\t\t// End color for each corner.\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticlesmoothstar.cpp",
    "content": "#include <core/defines.h>\r\n#include <gfx/xbox/nx/render.h>\r\n\r\n#include \"gfx/xbox/p_nxparticleSmoothStar.h\"\r\n\r\nextern DWORD PixelShader1;\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleSmoothStar::CXboxParticleSmoothStar()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleSmoothStar::CXboxParticleSmoothStar( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split )\r\n{\r\n\tm_checksum\t\t\t= checksum;\r\n\tm_max_particles\t\t= max_particles;\r\n\tm_num_particles\t\t= 0;\r\n\tm_num_segments\t\t= num_segments;\r\n\tm_split\t\t\t\t= split;\r\n\r\n\tmp_particle_array\t= new CParticleEntry[max_particles];\r\n\r\n\t// Allocate vertex buffer.\r\n\tmp_vertices = new float[max_particles * 3];\r\n\r\n\t// Create the engine representation.\r\n\tmp_engine_particle = new NxXbox::sParticleSystem( max_particles, NxXbox::PARTICLE_TYPE_SMOOTHSTAR, texture_checksum, blendmode_checksum, fix, num_segments );\r\n\r\n\t// Default color.\r\n\tfor ( int lp = 0; lp < 3; lp++ )\r\n\t{\r\n\t\tm_SmoothStart_color[lp].r = m_SmoothStart_color[lp].g = m_SmoothStart_color[lp].b = 128;\r\n\t\tm_SmoothStart_color[lp].a = 255;\r\n\t\tm_mid_color[lp].r = m_mid_color[lp].g = m_mid_color[lp].b = 128;\r\n\t\tm_mid_color[lp].a = 255;\r\n\t\tm_end_color[lp].r = m_end_color[lp].g = m_end_color[lp].b = 128;\r\n\t\tm_end_color[lp].a = 255;\r\n\t}\r\n\r\n\tm_mid_time = -1.0f;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxParticleSmoothStar::~CXboxParticleSmoothStar()\r\n{\r\n\tdelete [] mp_particle_array;\r\n\tdelete [] mp_vertices;\r\n\tdelete mp_engine_particle;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleSmoothStar::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\t*x = p_v[0];\r\n\t*y = p_v[1];\r\n\t*z = p_v[2];\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleSmoothStar::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] = x;\r\n\tp_v[1] = y;\r\n\tp_v[2] = z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleSmoothStar::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tfloat* p_v = &mp_vertices[entry*3];\r\n\tp_v[0] += x;\r\n\tp_v[1] += y;\r\n\tp_v[2] += z;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CXboxParticleSmoothStar::plat_get_num_particle_colors( void ) { return 3; }\r\nint CXboxParticleSmoothStar::plat_get_num_vertex_lists( void ) { return 1; }\r\nvoid CXboxParticleSmoothStar::plat_set_sr( int entry, uint8 value ) { m_SmoothStart_color[entry].r = value; }\r\nvoid CXboxParticleSmoothStar::plat_set_sg( int entry, uint8 value ) { m_SmoothStart_color[entry].g = value; }\r\nvoid CXboxParticleSmoothStar::plat_set_sb( int entry, uint8 value ) { m_SmoothStart_color[entry].b = value; }\r\nvoid CXboxParticleSmoothStar::plat_set_sa( int entry, uint8 value ) { m_SmoothStart_color[entry].a = value; }\r\nvoid CXboxParticleSmoothStar::plat_set_mr( int entry, uint8 value ) { m_mid_color[entry].r = value; }\r\nvoid CXboxParticleSmoothStar::plat_set_mg( int entry, uint8 value ) { m_mid_color[entry].g = value; }\r\nvoid CXboxParticleSmoothStar::plat_set_mb( int entry, uint8 value ) { m_mid_color[entry].b = value; }\r\nvoid CXboxParticleSmoothStar::plat_set_ma( int entry, uint8 value ) { m_mid_color[entry].a = value; }\r\nvoid CXboxParticleSmoothStar::plat_set_er( int entry, uint8 value ) { m_end_color[entry].r = value; }\r\nvoid CXboxParticleSmoothStar::plat_set_eg( int entry, uint8 value ) { m_end_color[entry].g = value; }\r\nvoid CXboxParticleSmoothStar::plat_set_eb( int entry, uint8 value ) { m_end_color[entry].b = value; }\r\nvoid CXboxParticleSmoothStar::plat_set_ea( int entry, uint8 value ) { m_end_color[entry].a = value; }\r\n\r\n\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxParticleSmoothStar::plat_render( void )\r\n{\r\n\t// Draw the particles.\r\n\tif( m_num_particles > 0 )\r\n\t{\r\n\t\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n\t\tD3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;\r\n\r\n\t\t// Concatenate p_matrix with the emmission angle to create the direction.\r\n\t\tMth::Vector up( 0.0f, 1.0f, 0.0f, 0.0f );\r\n\r\n\t\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n\t\tMth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );\r\n\t\tMth::Vector screen_right\t= Mth::CrossProduct( at, up );\r\n\t\tMth::Vector screen_up\t\t= Mth::CrossProduct( screen_right, at );\r\n\r\n\t\tscreen_right.Normalize();\r\n\t\tscreen_up.Normalize();\r\n\t\r\n\t\tint\t\t\t\tlp;\r\n\t\tCParticleEntry\t*p_particle;\r\n\t\tfloat\t\t\t*p_v;\r\n//\t\tMth::Vector\t\tmin, max;\t// For dynamic bounding box calculation.\r\n\r\n\t\t// Obtain push buffer lock.\r\n\t\tDWORD *p_push; \r\n\t\tDWORD dwords_per_particle\t= 32 * m_num_segments;\r\n\t\tDWORD dword_count\t\t\t= dwords_per_particle * m_num_particles;\r\n\r\n\t\t// Submit particle material.\r\n\t\tmp_engine_particle->mp_material->Submit();\r\n\t\t\r\n\t\t// Set up correct vertex and pixel shader.\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\t\tNxXbox::set_pixel_shader( PixelShader1 );\r\n\t\t\r\n\t\t// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.\r\n\t\tp_push = D3DDevice_BeginPush( dword_count + 32 );\r\n\r\n\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1]\t= D3DPT_QUADLIST;\r\n\t\tp_push\t\t+= 2;\r\n\r\n\t\t// Set up loop variables here, since we be potentially enetering the loop more than once.\r\n\t\tlp\t\t\t= 0;\r\n\t\tp_particle\t= mp_particle_array;\r\n\t\tp_v\t\t\t= mp_vertices;\r\n\r\n\t\twhile( dword_count > 0 )\r\n\t\t{\r\n\t\t\tint dwords_written = 0;\r\n\r\n\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, ( dword_count > 2047 ) ? ((int)( 2047 / dwords_per_particle )) * dwords_per_particle: dword_count );\r\n\t\t\t++p_push;\r\n\t\t\r\n\t\t\tfor( ; lp < m_num_particles; lp++, p_particle++, p_v += 3 )\r\n\t\t\t{\r\n\t\t\t\t// Check to see if writing another particle will take us over the edge.\r\n\t\t\t\tif(( dwords_written + dwords_per_particle ) > 2047 )\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfloat terp\t= p_particle->m_time / p_particle->m_life;\r\n\t\t\t\tfloat w\t\t= p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );\r\n\t\t\t\tfloat h\t\t= p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );\r\n\r\n\t\t\t\tMth::Vector\tpos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );\r\n\t\t\t\tMth::Vector\tss_right, ss_up;\t//, ss_pos;\r\n\t\t\t\tMth::Vector tmp[4];\r\n\t\r\n\t\t\t\t// Dynamic bounding box calculation.\r\n//\t\t\t\tif( lp == 0 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tmin = pos;\r\n//\t\t\t\t\tmax = pos;\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif( pos[X] < min[X] ) min[X] = pos[X]; else if( pos[X] > max[X] ) max[X] = pos[X];\r\n//\t\t\t\t\tif( pos[Y] < min[Y] ) min[Y] = pos[Y]; else if( pos[Y] > max[Y] ) max[Y] = pos[Y];\r\n//\t\t\t\t\tif( pos[Z] < min[Z] ) min[Z] = pos[Z]; else if( pos[Z] > max[Z] ) max[Z] = pos[Z];\r\n//\t\t\t\t}\r\n\r\n\t\t\t\tss_right\t= screen_right * w;\r\n\t\t\t\tss_up\t\t= screen_up * h;\r\n\t\r\n\t\t\t\tImage::RGBA color[3];\r\n\t\t\t\tImage::RGBA *p_col0;\r\n\t\t\t\tImage::RGBA *p_col1;\r\n\r\n\t\t\t\tif( m_mid_time >= 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( terp < m_mid_time )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_SmoothStart_color;\r\n\t\t\t\t\t\tp_col1 = m_mid_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = terp / m_mid_time;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_col0 = m_mid_color;\r\n\t\t\t\t\t\tp_col1 = m_end_color;\r\n\r\n\t\t\t\t\t\t// Adjust interpolation for this half of the color blend.\r\n\t\t\t\t\t\tterp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No mid color specified.\r\n\t\t\t\t\tp_col0 = m_SmoothStart_color;\r\n\t\t\t\t\tp_col1 = m_end_color;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Swap red and blue here during interpolation.\r\n\t\t\t\tfor ( int c = 0; c < 3; c++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tImage::RGBA SmoothStart = *p_col0++;\r\n\t\t\t\t\tImage::RGBA end = *p_col1++;\r\n\r\n\t\t\t\t\tcolor[c].b = SmoothStart.r + (uint8)(( ((float)( end.r - SmoothStart.r )) * terp ));\r\n\t\t\t\t\tcolor[c].g = SmoothStart.g + (uint8)(( ((float)( end.g - SmoothStart.g )) * terp ));\r\n\t\t\t\t\tcolor[c].r = SmoothStart.b + (uint8)(( ((float)( end.b - SmoothStart.b )) * terp ));\r\n\t\t\t\t\tcolor[c].a = SmoothStart.a + (uint8)(( ((float)( end.a - SmoothStart.a )) * terp ));\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttmp[1]  = pos;\r\n\t\t\t\ttmp[1] += ss_right * sinf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\t\t\t\ttmp[1] += ss_up    * cosf( Mth::DegToRad( 0.0f ) ) * m_split;\r\n\r\n\t\t\t\tfor( int lp2 = 0; lp2 < m_num_segments; lp2++ )\r\n\t\t\t\t{\r\n\t\t\t\t\ttmp[0]  = pos;\r\n\t\t\t\t\ttmp[0] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) ) * m_split;\r\n\t\t\t\t\ttmp[0] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) ) * m_split;\r\n\t\t\t\r\n\t\t\t\t\ttmp[3]  = pos;\r\n\t\t\t\t\ttmp[3] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 2 ) ) ) ) * m_split;\r\n\t\t\t\t\ttmp[3] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 2 ) ) ) ) * m_split;\r\n\t\t\t\r\n\t\t\t\t\ttmp[2]  = pos;\r\n\t\t\t\t\ttmp[2] += ss_right * sinf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) );\r\n\t\t\t\t\ttmp[2] += ss_up    * cosf( Mth::DegToRad( ( ( 360.0f / ((float)m_num_segments*2) ) * ( ( lp2 * 2 ) + 1 ) ) ) );\r\n\r\n\t\t\t\t\t// First quad.\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[0][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[0][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[0][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&pos[X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&pos[Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&pos[Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[3][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[3][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[3][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[2] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[2][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[2][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[2][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[2] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\t// Second quad.\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[0][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[0][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[0][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[1] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&pos[X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&pos[Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&pos[Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[0] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[1][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[1][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[1][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[2] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\tp_push[0]\t= *((DWORD*)&tmp[2][X] );\r\n\t\t\t\t\tp_push[1]\t= *((DWORD*)&tmp[2][Y] );\r\n\t\t\t\t\tp_push[2]\t= *((DWORD*)&tmp[2][Z] );\r\n\t\t\t\t\tp_push[3]\t= *((DWORD*)&color[2] );\r\n\t\t\t\t\tp_push\t\t+= 4;\r\n\r\n\t\t\t\t\ttmp[1] = tmp[3];\r\n\t\t\t\t}\r\n\t\t\t\tdwords_written\t+= dwords_per_particle;\r\n\t\t\t\tdword_count\t\t-= dwords_per_particle;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1] = 0;\r\n\t\tp_push += 2;\r\n\t\tD3DDevice_EndPush( p_push );\r\n\r\n\t\t// Set the mesh bounding box and sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMin( min );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMax( max );\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center = D3DXVECTOR3( min[X] + (( max[X] - min[X] ) * 0.5f ), min[Y] + (( max[Y] - min[Y] ) * 0.5f ), min[Z] + (( max[Z] - min[Z] ) * 0.5f ));\r\n//\t\tmp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius = 360.0f;\r\n\r\n\t\t// And the scene bounding sphere.\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_center = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center;\r\n//\t\tmp_engine_particle->mp_scene->m_sphere_radius = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius;\r\n\t}\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxparticlesmoothstar.h",
    "content": "#ifndef\t__GFX_P_NX_PARTICLESmoothStar_H__\r\n#define\t__GFX_P_NX_PARTICLESmoothStar_H__\r\n    \r\n#include \"gfx/xbox/p_nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CXboxParticleSmoothStar : public CParticle\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\t\tCXboxParticleSmoothStar();\r\n\t\t\t\t\t\t\t\tCXboxParticleSmoothStar( uint32 checksum, int max_particles, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split );\r\n\tvirtual \t\t\t\t\t~CXboxParticleSmoothStar();\r\n\r\n\tNxXbox::sParticleSystem*\tGetEngineParticle( void )\t{ return mp_engine_particle; }\r\n\r\n\tprivate: // It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvoid\t\t\t\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvoid\t\t\t\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tint\t\t\t\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tint\t\t\t\t\t\t\tplat_get_num_particle_colors( void );\r\n\r\n\tvoid\t\t\t\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvoid\t\t\t\t\t\tplat_set_ea( int entry, uint8 value );\r\n\t\t\r\n\tfloat*\t\t\t\t\t\tmp_vertices;\r\n\tuint32*\t\t\t\t\t\tmp_colors;\r\n\tuint64\t\t\t\t\t\tm_blend;\r\n\r\n\tNxXbox::sParticleSystem*\tmp_engine_particle;\r\n\tint\t\t\t\t\t\t\tm_num_segments;\r\n\tfloat\t\t\t\t\t\tm_split;\r\n\tImage::RGBA\t\t\t\t\tm_SmoothStart_color[3];\t\t\t// SmoothStart color for each corner.\r\n\tImage::RGBA\t\t\t\t\tm_mid_color[3];\t\t\t\t// Mid color for each corner.\r\n\tImage::RGBA\t\t\t\t\tm_end_color[3];\t\t\t\t// End color for each corner.\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxscene.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxScene.cpp\r\n\r\n#include \t\"gfx/xbox/p_NxScene.h\"\r\n#include \t\"gfx/xbox/p_NxSector.h\"\r\n#include \t\"gfx/xbox/p_NxGeom.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxScene::CXboxScene( int sector_table_size ) : CScene( sector_table_size )\r\n{\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxScene::DestroySectorMeshes( void )\r\n{\r\n\t// Iterate through the list of sectors, removing each one in turn, and requesting the engine to\r\n\t// remove the meshes.\r\n\tmp_sector_table->IterateStart();\r\n\tCSector* pSector = mp_sector_table->IterateNext();\r\n\twhile( pSector )\r\n\t{\r\n\t\t// Access platform dependent data.\r\n\t\tCXboxSector* pXboxSector = static_cast<CXboxSector *>(pSector);\r\n\r\n\t\t// Remove this mesh array from the engine.\r\n//\t\tpXboxSector->DestroyMeshArray();\r\n\r\n\t\tpSector = mp_sector_table->IterateNext();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CScene\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxScene::plat_post_load()\r\n{\r\n\t// Now turn the temporary mesh lists into mesh arrays.\r\n\tmp_sector_table->IterateStart();\r\n\tCSector* pSector = mp_sector_table->IterateNext();\r\n\twhile( pSector )\r\n\t{\r\n\t\tCXboxGeom *p_xbox_geom = static_cast<CXboxGeom*>(pSector->GetGeom());\r\n\r\n\t\tp_xbox_geom->CreateMeshArray();\r\n\r\n\t\t// First time through we just want to count the meshes,\r\n\t\tp_xbox_geom->RegisterMeshArray( true );\r\n\r\n\t\tpSector = mp_sector_table->IterateNext();\r\n\t}\r\n\r\n\t// Now we have counted all the meshes, tell the engine to create the arrays to hold them.\r\n\tGetEngineScene()->CreateMeshArrays();\r\n\t\r\n\t// Now go through and actually add the meshes.\r\n\tmp_sector_table->IterateStart();\r\n\tpSector = mp_sector_table->IterateNext();\r\n\twhile( pSector )\r\n\t{\r\n\t\t// Access platform dependent data.\r\n\t\tCXboxGeom *p_xbox_geom = static_cast<CXboxGeom*>(pSector->GetGeom());\r\n\r\n\t\tp_xbox_geom->RegisterMeshArray( false );\r\n\r\n\t\tpSector = mp_sector_table->IterateNext();\r\n\t}\r\n\r\n\t// Now all meshes are registered, tell the engine to sort them.\r\n\tGetEngineScene()->SortMeshes();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxScene::plat_load_textures(const char* p_name)\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxScene::plat_load_collision(const char* p_name)\r\n{\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxScene::plat_unload_add_scene( void )\r\n{\r\n\t// Not sure what this is supposed to do, but added for now to remove annoying stub output.\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Create an empty sector\r\nCSector\t*CXboxScene::plat_create_sector()\r\n{\r\n\tCXboxSector *p_xbox_sector\t= new CXboxSector();\r\n\treturn p_xbox_sector;\r\n}\r\n\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxscene.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxScene.h\r\n\r\n#ifndef\t__GFX_P_NX_SCENE_H__\r\n#define\t__GFX_P_NX_SCENE_H__\r\n\r\n#include \"Gfx/Nx.h\"\r\n#include \"Gfx/xbox/nx/scene.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CScene\r\nclass\tCXboxScene : public CScene\r\n{\r\npublic:\r\n\r\n\t\t\t\t\t\t\t\tCXboxScene( int sector_table_size = 10 );\r\n\tNxXbox::sScene *\t\t\tGetEngineScene() const\t\t\t\t\t\t{ return mp_engine_scene; }\r\n\tvoid\t\t\t\t\t\tSetEngineScene( NxXbox::sScene *p_scene )\t{ mp_engine_scene = p_scene; }\r\n\tvoid\t\t\t\t\t\tDestroySectorMeshes( void );\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\tvirtual void\t\t\t\tplat_post_load();\t\r\n\tvirtual bool\t\t\t\tplat_load_textures( const char *p_name );\t// load textures \r\n\tvirtual bool\t\t\t\tplat_load_collision( const char *p_name );\t// load collision data\r\n\tvirtual bool\t\t\t\tplat_unload_add_scene( void );\r\n\tvirtual\tCSector\t*\t\t\tplat_create_sector();\t \t\t\t\t\t// empty sector\r\n\r\n\r\n\tNxXbox::sScene\t\t\t\t*mp_engine_scene;\r\n\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxsector.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxSector.cpp\r\n\r\n#include\t<sys/file/filesys.h>\r\n\r\n#include \t\"gfx/xbox/p_NxSector.h\"\r\n#include \t\"gfx/xbox/p_NxGeom.h\"\r\n#include \t\"gfx/NxMiscFX.h\"\r\n#include \t\"gfx/xbox/nx/grass.h\"\r\n#include \t\"gfx/xbox/nx/billboard.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n//CXboxSector::CXboxSector() : mp_init_mesh_list( NULL ), m_mesh_array( NULL ), m_visible( 0xDEADBEEF )\r\nCXboxSector::CXboxSector()\r\n{\r\n\tm_pos_offset.Set( 0.0f, 0.0f, 0.0f );\r\n}\r\n\r\n\r\n\r\n\r\n#define MemoryRead( dst, size, num, src )\tCopyMemory(( dst ), ( src ), (( num ) * ( size )));\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t( src ) += (( num ) * ( size ))\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxSector::LoadFromMemory( void **pp_mem )\r\n{\r\n\tDbg_Assert( mp_geom );\r\n\r\n\tuint8\t\t*p_data\t= (uint8*)( *pp_mem );\r\n\tCXboxGeom\t*p_geom = static_cast<CXboxGeom*>( mp_geom );\r\n\t\r\n\t// Read sector checksum.\r\n\tuint32 sector_checksum;\r\n\tMemoryRead( &sector_checksum, sizeof( uint32 ), 1, p_data );\r\n\tSetChecksum( sector_checksum );\r\n\r\n\t// Read bone index.\r\n\tint bone_idx;\r\n\tMemoryRead( &bone_idx, sizeof( int ), 1, p_data );\r\n\r\n\t// Read sector flags.\r\n\tMemoryRead( &m_flags, sizeof( int ), 1, p_data );\r\n\r\n\t// Read number of meshes.\r\n\tMemoryRead( &p_geom->m_num_mesh, sizeof( uint ), 1, p_data );\r\n\r\n\t// Read bounding box.\r\n\tfloat bbox[6];\r\n\tMemoryRead( &bbox[0], sizeof( float ), 6, p_data );\r\n\tMth::Vector\tinf( bbox[0], bbox[1], bbox[2] );\r\n\tMth::Vector\tsup( bbox[3], bbox[4], bbox[5] );\r\n\tp_geom->m_bbox.Set( inf, sup );\r\n\t\t\r\n\t// Read bounding sphere.\r\n\tfloat bsphere[4];\r\n\tMemoryRead( &bsphere[0], sizeof( float ), 4, p_data );\r\n\t\t\r\n\t// Read billboard data if present.\r\n\tuint32\t\tbillboard_type;\r\n\tMth::Vector\tbillboard_origin;\r\n\tMth::Vector billboard_pivot_pos;\r\n\tMth::Vector billboard_pivot_axis;\r\n\tif( m_flags & 0x00800000UL )\r\n\t{\r\n\t\tMemoryRead( &billboard_type,\t\t\tsizeof( uint32 ), 1, p_data );\r\n\t\tMemoryRead( &billboard_origin[X],\t\tsizeof( float ) * 3, 1, p_data );\r\n\t\tMemoryRead( &billboard_pivot_pos[X],\tsizeof( float ) * 3, 1, p_data );\r\n\t\tMemoryRead( &billboard_pivot_axis[X],\tsizeof( float ) * 3, 1, p_data );\r\n\r\n\t\tbillboard_origin[Z]\t\t= -billboard_origin[Z];\r\n\t\tbillboard_pivot_pos[Z]\t= -billboard_pivot_pos[Z];\r\n\t}\r\n\r\n\t// Read num vertices.\r\n\tint num_vertices;\r\n\tMemoryRead( &num_vertices, sizeof( int ), 1, p_data );\r\n\t\r\n\t// Read vertex data stride.\r\n\tint vertex_data_stride;\r\n\tMemoryRead( &vertex_data_stride, sizeof( int ), 1, p_data );\r\n\r\n\t// We want all the temporary buffer allocations to come off of the top down heap.\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().TopDownHeap());\r\n\t\r\n\t// Grab a buffer for the raw vertex data position stream, and read it.\r\n\tfloat* p_vertex_positions = new float[num_vertices * 3];\r\n\tMemoryRead( p_vertex_positions, sizeof( float ) * 3, num_vertices, p_data );\r\n\t\r\n\t// Grab a buffer for the raw vertex data normal stream (if present), and read it.\r\n\tfloat* p_vertex_normals = ( m_flags & 0x04 ) ? new float[num_vertices * 3] : NULL;\r\n\tif( p_vertex_normals )\r\n\t{\r\n\t\tMemoryRead( p_vertex_normals, sizeof( float ) * 3, num_vertices, p_data );\r\n\t}\r\n\r\n\t// Grab a buffer for the raw vertex data weights stream (if present), and read it.\r\n\tuint32* p_vertex_weights = ( m_flags & 0x10 ) ? new uint32[num_vertices] : NULL;\r\n\tif( p_vertex_weights )\r\n\t{\r\n\t\tMemoryRead( p_vertex_weights, sizeof( uint32 ), num_vertices, p_data );\r\n\t}\r\n\t\r\n\t// Grab a buffer for the raw vertex data bone indices stream (if present), and read it.\r\n\tuint16* p_vertex_bone_indices = ( m_flags & 0x10 ) ? new uint16[num_vertices * 4] : NULL;\r\n\tif( p_vertex_bone_indices )\r\n\t{\r\n\t\tMemoryRead( p_vertex_bone_indices, sizeof( uint16 ) * 4, num_vertices, p_data );\r\n\t}\r\n\r\n\t// Grab a buffer for the raw vertex texture coordinate stream (if present), and read it.\r\n\tint\t\tnum_tc_sets\t\t\t= 0;\r\n\tfloat*\tp_vertex_tex_coords\t= NULL;\r\n\tif( m_flags & 0x01 )\r\n\t{\r\n\t\tMemoryRead( &num_tc_sets, sizeof( int ), 1, p_data );\r\n\t\t\r\n\t\tif( num_tc_sets > 0 )\r\n\t\t{\r\n\t\t\tp_vertex_tex_coords = new float[num_vertices * 2 * num_tc_sets];\r\n\t\t\tMemoryRead( p_vertex_tex_coords, sizeof( float ) * 2 * num_tc_sets, num_vertices, p_data );\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Grab a buffer for the raw vertex colors stream (if present), and read it.\r\n\tDWORD* p_vertex_colors = ( m_flags & 0x02 ) ? new DWORD[num_vertices] : NULL;\r\n\tif( p_vertex_colors )\r\n\t{\r\n\t\tMemoryRead( p_vertex_colors, sizeof( DWORD ), num_vertices, p_data );\r\n\t}\r\n\r\n\t// Grab a buffer for the vertex color wibble stream (if present), and read it.\r\n\tchar* p_vc_wibble_indices = ( m_flags & 0x800 ) ? new char[num_vertices] : NULL;\r\n\tif( p_vc_wibble_indices )\r\n\t{\r\n\t\tMemoryRead( p_vc_wibble_indices, sizeof( char ), num_vertices, p_data );\r\n\t}\r\n\t\r\n\t// Remove TopDownHeap context.\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Preprocess verts that require cutscene scaling.\r\n\tNxXbox::ApplyMeshScaling( p_vertex_positions, num_vertices );\r\n\r\n\tfor( uint m = 0; m < p_geom->m_num_mesh; ++m )\r\n\t{\r\n\t\tunsigned long\tmaterial_checksum;\r\n\t\tunsigned int\tflags, num_lod_index_levels;\r\n\r\n\t\tNxXbox::sMesh*\tp_mesh = new NxXbox::sMesh;\r\n\r\n\t\t// Read bounding sphere and box data.\r\n\t\tfloat\t\trad;\r\n\t\tMth::Vector inf, sup, cen;\r\n\t\tMemoryRead( &cen[X], sizeof( float ), 3, p_data );\r\n\t\tMemoryRead( &rad, sizeof( float ), 1, p_data );\r\n\t\tMemoryRead( &inf[X], sizeof( float ), 3, p_data );\r\n\t\tMemoryRead( &sup[X], sizeof( float ), 3, p_data );\r\n\r\n\t\t// Read and deal with flags, including skater shadow flag.\r\n\t\tMemoryRead( &flags, sizeof( uint32 ), 1, p_data );\r\n\t\tif( flags & 0x400 )\r\n\t\t{\r\n\t\t\tp_mesh->m_flags |= NxXbox::sMesh::MESH_FLAG_NO_SKATER_SHADOW;\r\n\t\t}\r\n\t\tif( flags & NxXbox::sMesh::MESH_FLAG_UNLIT )\r\n\t\t{\r\n\t\t\tp_mesh->m_flags |= NxXbox::sMesh::MESH_FLAG_UNLIT;\r\n\t\t}\r\n\r\n\t\t// The material checksum for this mesh.\r\n\t\tMemoryRead( &material_checksum,\tsizeof( unsigned long ), 1, p_data );\r\n\r\n\t\t// How many levels of LOD indices? Should be at least 1!\r\n\t\tMemoryRead( &num_lod_index_levels, sizeof( unsigned int ), 1, p_data );\r\n\r\n\t\t// Can have up to 8 levels of LOD indices.\r\n\t\tuint16*\tp_indices[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };\r\n\t\tint\t\tnum_indices[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };\r\n\r\n\t\tfor( unsigned int lod_level = 0; lod_level < num_lod_index_levels; ++lod_level )\r\n\t\t{\r\n\t\t\tMemoryRead( &num_indices[lod_level], sizeof( int ), 1, p_data );\r\n\t\t\r\n\t\t\t// Again, we want all the temporary buffer allocations to come off of the top down heap.\r\n\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\tp_indices[lod_level] = new uint16[num_indices[lod_level]];\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t\tMemoryRead( p_indices[lod_level], sizeof( uint16 ), num_indices[lod_level], p_data );\r\n\t\t}\r\n\r\n\t\t// Set the load order of this mesh.\r\n\t\tp_mesh->m_load_order = m;\r\n\r\n\t\t// Set up the mesh.\r\n\t\tp_mesh->Initialize(\tnum_vertices,\r\n\t\t\t\t\t\t\tp_vertex_positions,\r\n\t\t\t\t\t\t\tp_vertex_normals,\r\n\t\t\t\t\t\t\tp_vertex_tex_coords,\r\n\t\t\t\t\t\t\tnum_tc_sets,\r\n\t\t\t\t\t\t\tp_vertex_colors,\r\n\t\t\t\t\t\t\tnum_lod_index_levels,\r\n\t\t\t\t\t\t\tnum_indices,\r\n\t\t\t\t\t\t\tp_indices,\r\n\t\t\t\t\t\t\tmaterial_checksum,\r\n\t\t\t\t\t\t\tp_geom->mp_scene->GetEngineScene(),\r\n\t\t\t\t\t\t\tp_vertex_bone_indices,\r\n\t\t\t\t\t\t\tp_vertex_weights,\r\n\t\t\t\t\t\t\t( flags & 0x800 ) ? p_vc_wibble_indices : NULL );\r\n\t\t\r\n\t\t// Set the bounding data (sphere and box) for the mesh.\r\n\t\tp_mesh->SetBoundingData( cen, rad, inf, sup );\r\n\r\n\t\t// Add the bounding data to the scene.\r\n\t\tp_geom->mp_scene->GetEngineScene()->m_bbox.AddPoint( inf );\r\n\t\tp_geom->mp_scene->GetEngineScene()->m_bbox.AddPoint( sup );\r\n\r\n\t\t// Set up as a billboard if required.\r\n\t\tif( m_flags & 0x00800000UL )\r\n\t\t{\r\n\t\t\tp_mesh->SetBillboardData( billboard_type, billboard_pivot_pos, billboard_pivot_axis );\r\n\t\t\tNxXbox::BillboardManager.AddEntry( p_mesh );\r\n\t\t}\r\n\r\n\t\t// Flag the mesh as being a shadow volume if applicable.\r\n\t\tif( m_flags & 0x200000 )\r\n\t\t{\r\n\t\t\tp_mesh->m_flags |= NxXbox::sMesh::MESH_FLAG_SHADOW_VOLUME;\r\n\t\t}\r\n\r\n\t\t// Add the mesh to the attached CXboxGeom.\r\n\t\tp_geom->AddMesh( p_mesh );\r\n\r\n\t\t// Set the mesh bone index (mostly not applicable).\r\n\t\tp_mesh->SetBoneIndex( bone_idx );\r\n\t\r\n\t\t// Test code - if the mesh is mapped with a grass texture, add grass meshes.\r\n\t\tAddGrass( p_geom, p_mesh );\r\n\t\t\r\n\t\t// Done with the raw index data.\r\n\t\tfor( int lod_level = 0; lod_level < 8; ++lod_level )\r\n\t\t{\r\n\t\t\tdelete[] p_indices[lod_level];\r\n\t\t}\r\n\t}\r\n\r\n\t// Recount the number of meshes in case any have been added.\r\n\tp_geom->m_num_mesh = p_geom->mp_init_mesh_list->CountItems();\r\n\t\r\n\t// Done with the raw vertex data.\r\n\tdelete[] p_vc_wibble_indices;\r\n\tdelete[] p_vertex_colors;\r\n\tdelete[] p_vertex_tex_coords;\r\n\tdelete[] p_vertex_bone_indices;\r\n\tdelete[] p_vertex_weights;\r\n\tdelete[] p_vertex_normals;\r\n\tdelete[] p_vertex_positions;\r\n\t\r\n\t// Set the data pointer to the new position on return.\r\n\t*pp_mem = p_data;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxSector::LoadFromFile( void* p_file )\r\n{\r\n\tDbg_Assert( mp_geom );\r\n\r\n\tCXboxGeom *p_geom = static_cast<CXboxGeom*>( mp_geom );\r\n\t\r\n\t// Read sector checksum.\r\n\tuint32 sector_checksum;\r\n\tFile::Read( &sector_checksum, sizeof( uint32 ), 1, p_file );\r\n\tSetChecksum( sector_checksum );\r\n\r\n\t// Read bone index.\r\n\tint bone_idx;\r\n\tFile::Read( &bone_idx, sizeof( int ), 1, p_file );\r\n\r\n\t// Read sector flags.\r\n\tFile::Read( &m_flags, sizeof( int ), 1, p_file );\r\n\r\n\t// Read number of meshes.\r\n\tFile::Read( &p_geom->m_num_mesh, sizeof( uint ), 1, p_file );\r\n\r\n\t// Read bounding box.\r\n\tfloat bbox[6];\r\n\tFile::Read( &bbox[0], sizeof( float ), 6, p_file );\r\n\tMth::Vector\tinf( bbox[0], bbox[1], bbox[2] );\r\n\tMth::Vector\tsup( bbox[3], bbox[4], bbox[5] );\r\n\tp_geom->m_bbox.Set( inf, sup );\r\n\t\t\r\n\t// Read bounding sphere.\r\n\tfloat bsphere[4];\r\n\tFile::Read( &bsphere[0], sizeof( float ), 4, p_file );\r\n\t\t\r\n\t// Read billboard data if present.\r\n\tuint32\t\tbillboard_type;\r\n\tMth::Vector\tbillboard_origin;\r\n\tMth::Vector billboard_pivot_pos;\r\n\tMth::Vector billboard_pivot_axis;\r\n\tif( m_flags & 0x00800000UL )\r\n\t{\r\n\t\tFile::Read( &billboard_type,\t\t\tsizeof( uint32 ), 1, p_file );\r\n\t\tFile::Read( &billboard_origin[X],\t\tsizeof( float ) * 3, 1, p_file );\r\n\t\tFile::Read( &billboard_pivot_pos[X],\tsizeof( float ) * 3, 1, p_file );\r\n\t\tFile::Read( &billboard_pivot_axis[X],\tsizeof( float ) * 3, 1, p_file );\r\n\r\n\t\tbillboard_origin[Z]\t\t= -billboard_origin[Z];\r\n\t\tbillboard_origin[W]\t\t= 0.0f;\r\n\r\n\t\tbillboard_pivot_pos[Z]\t= -billboard_pivot_pos[Z];\r\n\t\tbillboard_pivot_pos[W]\t= 0.0f;\r\n\r\n\t\tbillboard_pivot_axis[W]\t= 0.0f;\r\n\t}\r\n\r\n\t// Read num vertices.\r\n\tint num_vertices;\r\n\tFile::Read( &num_vertices, sizeof( int ), 1, p_file );\r\n\t\r\n\t// Read vertex data stride.\r\n\tint vertex_data_stride;\r\n\tFile::Read( &vertex_data_stride, sizeof( int ), 1, p_file );\r\n\r\n\t// We want all the temporary buffer allocations to come off of the top down heap.\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().TopDownHeap());\r\n\t\r\n\t// Grab a buffer for the raw vertex data position stream, and read it.\r\n\tfloat* p_vertex_positions = new float[num_vertices * 3];\r\n\tFile::Read( p_vertex_positions, sizeof( float ) * 3, num_vertices, p_file );\r\n\t\r\n\t// Grab a buffer for the raw vertex data normal stream (if present), and read it.\r\n\tfloat* p_vertex_normals = ( m_flags & 0x04 ) ? new float[num_vertices * 3] : NULL;\r\n\tif( p_vertex_normals )\r\n\t{\r\n\t\tFile::Read( p_vertex_normals, sizeof( float ) * 3, num_vertices, p_file );\r\n\t}\r\n\r\n\t// Grab a buffer for the raw vertex data weights stream (if present), and read it.\r\n\tuint32* p_vertex_weights = ( m_flags & 0x10 ) ? new uint32[num_vertices] : NULL;\r\n\tif( p_vertex_weights )\r\n\t{\r\n\t\tFile::Read( p_vertex_weights, sizeof( uint32 ), num_vertices, p_file );\r\n\t}\r\n\t\r\n\t// Grab a buffer for the raw vertex data bone indices stream (if present), and read it.\r\n\tuint16* p_vertex_bone_indices = ( m_flags & 0x10 ) ? new uint16[num_vertices * 4] : NULL;\r\n\tif( p_vertex_bone_indices )\r\n\t{\r\n\t\tFile::Read( p_vertex_bone_indices, sizeof( uint16 ) * 4, num_vertices, p_file );\r\n\t}\r\n\r\n\t// Grab a buffer for the raw vertex texture coordinate stream (if present), and read it.\r\n\tint\t\tnum_tc_sets\t\t\t= 0;\r\n\tfloat*\tp_vertex_tex_coords\t= NULL;\r\n\tif( m_flags & 0x01 )\r\n\t{\r\n\t\tFile::Read( &num_tc_sets, sizeof( int ), 1, p_file );\r\n\t\t\r\n\t\tif( num_tc_sets > 0 )\r\n\t\t{\r\n\t\t\tp_vertex_tex_coords = new float[num_vertices * 2 * num_tc_sets];\r\n\t\t\tFile::Read( p_vertex_tex_coords, sizeof( float ) * 2 * num_tc_sets, num_vertices, p_file );\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Grab a buffer for the raw vertex colors stream (if present), and read it.\r\n\tDWORD* p_vertex_colors = ( m_flags & 0x02 ) ? new DWORD[num_vertices] : NULL;\r\n\tif( p_vertex_colors )\r\n\t{\r\n\t\tFile::Read( p_vertex_colors, sizeof( DWORD ), num_vertices, p_file );\r\n\t}\r\n\r\n\t// Grab a buffer for the vertex color wibble stream (if present), and read it.\r\n\tchar* p_vc_wibble_indices = ( m_flags & 0x800 ) ? new char[num_vertices] : NULL;\r\n\tif( p_vc_wibble_indices )\r\n\t{\r\n\t\tFile::Read( p_vc_wibble_indices, sizeof( char ), num_vertices, p_file );\r\n\t}\r\n\t\r\n\t// Remove TopDownHeap context.\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tfor( uint m = 0; m < p_geom->m_num_mesh; ++m )\r\n\t{\r\n\t\tunsigned long\tmaterial_checksum;\r\n\t\tunsigned int\tflags, num_lod_index_levels;\r\n\r\n\t\tNxXbox::sMesh*\tp_mesh = new NxXbox::sMesh;\r\n\r\n\t\t// Read bounding sphere and box data.\r\n\t\tfloat\t\trad;\r\n\t\tMth::Vector cen;\r\n\t\tFile::Read( &cen[X], sizeof( float ), 3, p_file );\r\n\t\tFile::Read( &rad, sizeof( float ), 1, p_file );\r\n\t\tFile::Read( &inf[X], sizeof( float ), 3, p_file );\r\n\t\tFile::Read( &sup[X], sizeof( float ), 3, p_file );\r\n\r\n\t\t// Read and deal with flags, including skater shadow flag.\r\n\t\tFile::Read( &flags, sizeof( uint32 ), 1, p_file );\r\n\t\tif( flags & 0x400 )\r\n\t\t{\r\n\t\t\tp_mesh->m_flags |= NxXbox::sMesh::MESH_FLAG_NO_SKATER_SHADOW;\r\n\t\t}\r\n\t\tif( flags & NxXbox::sMesh::MESH_FLAG_UNLIT )\r\n\t\t{\r\n\t\t\tp_mesh->m_flags |= NxXbox::sMesh::MESH_FLAG_UNLIT;\r\n\t\t}\r\n\r\n\t\t// The material checksum for this mesh.\r\n\t\tFile::Read( &material_checksum,\tsizeof( unsigned long ), 1, p_file );\r\n\r\n\t\t// How many levels of LOD indices? Should be at least 1!\r\n\t\tFile::Read( &num_lod_index_levels, sizeof( unsigned int ), 1, p_file );\r\n\r\n\t\t// Can have up to 8 levels of LOD indices.\r\n\t\tuint16*\tp_indices[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };\r\n\t\tint\t\tnum_indices[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };\r\n\r\n\t\tfor( unsigned int lod_level = 0; lod_level < num_lod_index_levels; ++lod_level )\r\n\t\t{\r\n\t\t\tFile::Read( &num_indices[lod_level], sizeof( int ), 1, p_file );\r\n\t\t\r\n\t\t\t// Again, we want all the temporary buffer allocations to come off of the top down heap.\r\n\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\tp_indices[lod_level] = new uint16[num_indices[lod_level]];\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t\tFile::Read( p_indices[lod_level], sizeof( uint16 ), num_indices[lod_level], p_file );\r\n\t\t}\r\n\r\n\t\t// Set the load order of this mesh.\r\n\t\tp_mesh->m_load_order = m;\r\n\r\n\t\t// Set up the mesh.\r\n\t\tp_mesh->Initialize(\tnum_vertices,\r\n\t\t\t\t\t\t\tp_vertex_positions,\r\n\t\t\t\t\t\t\t( m_flags & 0x00800000UL ) ? NULL : p_vertex_normals,\t\t// No normals allowed for billboards.\r\n\t\t\t\t\t\t\tp_vertex_tex_coords,\r\n\t\t\t\t\t\t\tnum_tc_sets,\r\n\t\t\t\t\t\t\tp_vertex_colors,\r\n\t\t\t\t\t\t\tnum_lod_index_levels,\r\n\t\t\t\t\t\t\tnum_indices,\r\n\t\t\t\t\t\t\tp_indices,\r\n\t\t\t\t\t\t\tmaterial_checksum,\r\n\t\t\t\t\t\t\tp_geom->mp_scene->GetEngineScene(),\r\n\t\t\t\t\t\t\tp_vertex_bone_indices,\r\n\t\t\t\t\t\t\tp_vertex_weights,\r\n\t\t\t\t\t\t\t( flags & 0x800 ) ? p_vc_wibble_indices : NULL );\r\n\t\t\r\n\t\t// Set the bounding data (sphere and box) for the mesh.\r\n\t\tp_mesh->SetBoundingData( cen, rad, inf, sup );\r\n\r\n\t\t// Add the bounding data to the scene.\r\n\t\tp_geom->mp_scene->GetEngineScene()->m_bbox.AddPoint( inf );\r\n\t\tp_geom->mp_scene->GetEngineScene()->m_bbox.AddPoint( sup );\r\n\r\n\t\t// Set up as a billboard if required.\r\n\t\tif( m_flags & 0x00800000UL )\r\n\t\t{\r\n\t\t\tp_mesh->SetBillboardData( billboard_type, billboard_pivot_pos, billboard_pivot_axis );\r\n\t\t\tNxXbox::BillboardManager.AddEntry( p_mesh );\r\n\t\t}\r\n\r\n\t\t// Flag the mesh as being a shadow volume if applicable.\r\n\t\tif( m_flags & 0x200000 )\r\n\t\t{\r\n\t\t\tp_mesh->m_flags |= NxXbox::sMesh::MESH_FLAG_SHADOW_VOLUME;\r\n\t\t}\r\n\r\n\t\t// Add the mesh to the attached CXboxGeom.\r\n\t\tp_geom->AddMesh( p_mesh );\r\n\r\n\t\t// Set the mesh bone index (mostly not applicable).\r\n\t\tp_mesh->SetBoneIndex( bone_idx );\r\n\t\r\n\t\t// Test code - if the mesh is mapped with a grass texture, add grass meshes.\r\n\t\tAddGrass( p_geom, p_mesh );\r\n\t\t\r\n\t\t// Done with the raw index data.\r\n\t\tfor( int lod_level = 0; lod_level < 8; ++lod_level )\r\n\t\t{\r\n\t\t\tdelete[] p_indices[lod_level];\r\n\t\t}\r\n\t}\r\n\r\n\t// Recount the number of meshes in case any have been added.\r\n\tp_geom->m_num_mesh = p_geom->mp_init_mesh_list->CountItems();\r\n\t\r\n\r\n\t// Test code for creating imposters.\r\n#\tif 0\r\n\tif( p_vertex_weights == NULL )\r\n\t{\r\n\t\tchar *p_ok_sectors[] = {\t\"NJ_Houses_North_09\",\r\n\t\t\t\t\t\t\t\t\t\"NJ_Houses_North_10\" };\r\n/*\r\nchar *p_ok_sectors[] = { \"CP_telephonepole43\",\r\n\t\t\t\t\t\t\t\t\"CP_telephonepole51\",\r\n\t\t\t\t\t\t\t\t\"CP_telephonepole52\",\r\n\t\t\t\t\t\t\t\t\"NJ_TelePole_Node03\",\r\n\t\t\t\t\t\t\t\t\"NJ_TelePole_Node02\",\r\n\t\t\t\t\t\t\t\t\"NJ_TelePole_Node04\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_00\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_01\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_02\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_03\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_04\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_05\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_06\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_07\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_08\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_09\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_12\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_13\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_14\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_15\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_16\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_17\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_18\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_19\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_20\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_21\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_22\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_23\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_24\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_25\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_26\",\r\n\t\t\t\t\t\t\t\t\"CP_telephonepole11\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_27\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_28\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_29\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_30\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_31\",\r\n\t\t\t\t\t\t\t\t\"NJ_Telepole_32\" };\r\n*/\r\n\r\n\t\tfor( int s = 0; s < ( sizeof( p_ok_sectors ) / sizeof( char* )); ++s )\r\n\t\t{\r\n\t\t\tuint32 checksum = Crc::GenerateCRCFromString( p_ok_sectors[s] );\r\n\t\t\tif( checksum == m_checksum )\r\n\t\t\t{\r\n//\t\t\t\tNx::CEngine::sGetImposterManager()->AddGeomToImposter( checksum, p_geom );\r\n\t\t\t\tNx::CEngine::sGetImposterManager()->AddGeomToImposter( 0xb88905d6UL, p_geom );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#\tendif\r\n\r\n\t// Done with the raw vertex data.\r\n\tdelete[] p_vc_wibble_indices;\r\n\tdelete[] p_vertex_colors;\r\n\tdelete[] p_vertex_tex_coords;\r\n\tdelete[] p_vertex_bone_indices;\r\n\tdelete[] p_vertex_weights;\r\n\tdelete[] p_vertex_normals;\r\n\tdelete[] p_vertex_positions;\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CSector\r\n// and we will also have a CXboxSector, CNgcSector, even a CPcSector\r\n// maybe in the future we will have a CPS3Sector?\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxSector::plat_set_visibility(uint32 mask)\r\n{\r\n/*\r\n\t// Set values\r\n\tm_visible = mask;\r\n\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\tfor( uint m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[m];\r\n\t\t\tp_mesh->SetVisibility( mask );\r\n\t\t}\r\n\t}\r\n*/\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxSector::plat_set_active( bool on )\r\n{\r\n/*\r\n\t// Set values\r\n\tm_active = on;\r\n\r\n\tif( m_mesh_array )\r\n\t{\r\n\t\tfor( uint m = 0; m < m_num_mesh; ++m )\r\n\t\t{\r\n\t\t\tNxXbox::sMesh *p_mesh = m_mesh_array[m];\r\n\t\t\tp_mesh->SetActive( on );\r\n\t\t}\r\n\t}\r\n*/\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxSector::plat_set_color( Image::RGBA rgba )\r\n{\r\n/*\r\n\tif( m_mesh_array == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n\t{\r\n\t\tNxXbox::sMesh *p_mesh = m_mesh_array[i];\r\n\t\tp_mesh->m_flags |= NxXbox::sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE;\r\n\t\tp_mesh->m_material_color_override[0] = (float)rgba.r / 255.0f;\r\n\t\tp_mesh->m_material_color_override[1] = (float)rgba.g / 255.0f;\r\n\t\tp_mesh->m_material_color_override[2] = (float)rgba.b / 255.0f;\r\n\t}\r\n*/\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxSector::plat_clear_color( void )\r\n{\r\n/*\r\n\tif( m_mesh_array == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n\t{\r\n\t\tNxXbox::sMesh *p_mesh = m_mesh_array[i];\r\n\t\tp_mesh->m_flags &= ~NxXbox::sMesh::MESH_FLAG_MATERIAL_COLOR_OVERRIDE;\r\n\t}\r\n*/\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxSector::plat_set_world_position( const Mth::Vector& pos )\r\n{\r\n/*\r\n\tMth::Vector new_offset = pos - m_pos_offset;\r\n\r\n\t// Go through and adjust the individual meshes.\r\n\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n\t{\r\n\t\tNxXbox::sMesh *p_mesh = m_mesh_array[i];\r\n\t\tp_mesh->Move( new_offset );\r\n\t}\r\n*/\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::CBBox &CXboxSector::plat_get_bounding_box( void ) const\r\n{\r\n\tstatic Mth::CBBox dummy;\r\n\t\r\n\t//\treturn m_bbox;\r\n\treturn dummy;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst Mth::Vector &CXboxSector::plat_get_world_position( void ) const\r\n{\r\n\treturn m_pos_offset;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxSector::plat_set_shatter( bool on )\r\n{\r\n\tif( on && mp_geom )\r\n\t{\r\n\t\tShatter( mp_geom );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCSector *CXboxSector::plat_clone( bool instance, CScene *p_dest_scene )\r\n{\r\n\tCXboxSector *p_xbox_sector = new CXboxSector();\r\n\r\n\t/*\r\n\r\n\r\n\t// Copies over much of the standard stuff, individual stuff will be overwritten later.\r\n\tCopyMemory( p_xbox_sector, this, sizeof( CXboxSector ));\r\n\r\n\tif( instance )\r\n\t{\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Need to create a new set of meshes. First create the mesh pointer array...\r\n\t\tp_xbox_sector->m_mesh_array = new NxXbox::sMesh*[m_num_mesh];\r\n\r\n\t\t// ...then clone the meshes themselves.\r\n\t\tfor( uint32 i = 0; i < m_num_mesh; ++i )\r\n\t\t{\r\n\t\t\tp_xbox_sector->m_mesh_array[i] = m_mesh_array[i]->Clone();\r\n\t\t}\r\n\r\n\t\t// Grab a temporary workspace buffer.\r\n\t\tNxXbox::sScene *p_scene\t\t\t\t\t\t\t\t= ( static_cast<CXboxScene*>( p_dest_scene ))->GetEngineScene();\r\n\t\tNxXbox::sMesh **p_temp_opaque_mesh_buffer\t\t\t= new NxXbox::sMesh*[p_scene->m_num_opaque_entries];\r\n\t\tNxXbox::sMesh **p_temp_semitransparent_mesh_buffer\t= new NxXbox::sMesh*[p_scene->m_num_semitransparent_entries];\r\n\r\n\t\t// Copy meshes over into the temporary workspace buffer.\r\n\t\tfor( int i = 0; i < p_scene->m_num_opaque_entries; ++i )\r\n\t\t{\r\n\t\t\tp_temp_opaque_mesh_buffer[i] = p_scene->m_opaque_meshes[i];\r\n\t\t}\r\n\t\tfor( int i = 0; i < p_scene->m_num_semitransparent_entries; ++i )\r\n\t\t{\r\n\t\t\tp_temp_semitransparent_mesh_buffer[i] = p_scene->m_semitransparent_meshes[i];\r\n\t\t}\r\n\r\n\t\t// Delete current mesh arrays.\r\n\t\tdelete [] p_scene->m_opaque_meshes;\r\n\t\tdelete [] p_scene->m_semitransparent_meshes;\r\n\r\n\t\t// Include new meshes in count.\r\n\t\tp_scene->CountMeshes( p_xbox_sector->m_num_mesh, p_xbox_sector->m_mesh_array );\r\n\r\n\t\t// Allocate new mesh arrays.\r\n\t\tp_scene->CreateMeshArrays();\r\n\r\n\t\t// Copy old mesh data back in.\r\n\t\tfor( int i = 0; i < p_scene->m_num_opaque_entries; ++i )\r\n\t\t{\r\n\t\t\tp_scene->m_opaque_meshes[i] = p_temp_opaque_mesh_buffer[i];\r\n\t\t}\r\n\t\tfor( int i = 0; i < p_scene->m_num_semitransparent_entries; ++i )\r\n\t\t{\r\n\t\t\tp_scene->m_semitransparent_meshes[i] = p_temp_semitransparent_mesh_buffer[i];\r\n\t\t}\r\n\r\n\t\t// Add new meshes.\r\n\t\tp_scene->AddMeshes( p_xbox_sector->m_num_mesh, p_xbox_sector->m_mesh_array );\r\n\r\n\t\t// Sort the meshes.\r\n\t\tp_scene->SortMeshes();\r\n\t}\r\n*/\r\n\treturn p_xbox_sector;\r\n\r\n}\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxsector.h",
    "content": "#ifndef\t__GFX_P_NX_SECTOR_H__\r\n#define\t__GFX_P_NX_SECTOR_H__\r\n\r\n#include \t<core\\math.h>\r\n#include \t<core\\math\\geometry.h>\r\n#include \t\"gfx\\NxSector.h\"\r\n#include \t\"gfx\\Image\\ImageBasic.h\"\r\n\r\n#include \t\"gfx\\xbox\\p_nxscene.h\"\r\n#include \t\"gfx\\xbox\\nx\\mesh.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Here's a machine specific implementation of the CSector\r\nclass CXboxSector : public CSector\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\t\t\tCXboxSector();\r\n\r\n\tbool\t\t\t\t\t\t\tLoadFromFile( void* p_file );\r\n\tbool\t\t\t\t\t\t\tLoadFromMemory( void **p_mem );\r\n\r\n\tNxXbox::sScene\t\t\t\t\t*GenerateScene( void );\r\n\t\r\n\tprivate:\t\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvirtual void\t\t\t\t\tplat_set_color( Image::RGBA rgba );\r\n\tvirtual void\t\t\t\t\tplat_clear_color( void );\r\n\tvirtual void\t\t\t\t\tplat_set_visibility( uint32 mask );\r\n\tvirtual void\t\t\t\t\tplat_set_active( bool on );\r\n\tvirtual void\t\t\t\t\tplat_set_world_position( const Mth::Vector& pos );\r\n\tvirtual const Mth::CBBox\t\t&plat_get_bounding_box( void ) const;\r\n\tvirtual const Mth::Vector\t\t&plat_get_world_position( void ) const;\r\n\tvirtual void\t\t\t\t\tplat_set_shatter( bool on );\r\n\tvirtual CSector\t\t\t\t\t*plat_clone( bool instance, CScene *p_scene = NULL );\r\n\r\n\tint\t\t\t\t\t\t\t\tm_flags;\r\n\r\n\tMth::Vector\t\t\t\t\t\tm_pos_offset;\r\n\r\n\tImage::RGBA\t\t\t\t\t\tm_rgba;\r\n};\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif"
  },
  {
    "path": "Code/Gfx/XBox/p_nxtexman.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\r\n// p_NxTexMan.cpp - Xbox platform specific interface to CTexMan\r\n//\r\n\r\n#include <core/defines.h>\r\n\r\n#include \"gfx/NxTexMan.h\"\r\n#include \"gfx/xbox/p_NxTexture.h\"\r\n#include \"gfx/xbox/nx/texture.h\"\r\n\r\nnamespace\tNx\r\n{\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Functions\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCTexDict* CTexDictManager::s_plat_load_texture_dictionary( const char *p_tex_dict_name, bool is_level_data, uint32 texDictOffset, bool is_skin, bool forceTexDictLookup )\r\n{\r\n\treturn new CXboxTexDict( p_tex_dict_name );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCTexDict* CTexDictManager::s_plat_load_texture_dictionary( uint32 checksum, uint32 *p_data, int data_size, bool is_level_data, uint32 texDictOffset, bool is_skin, bool forceTexDictLookup )\r\n{\r\n\tCXboxTexDict *p_dict = new CXboxTexDict( checksum );\r\n\tp_dict->LoadTextureDictionaryFromMemory( p_data );\r\n\treturn p_dict;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCTexDict* CTexDictManager::s_plat_create_texture_dictionary( uint32 checksum )\r\n{\r\n\treturn new CXboxTexDict( checksum );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CTexDictManager::s_plat_unload_texture_dictionary( CTexDict* p_tex_dict )\r\n{\r\n\tdelete p_tex_dict;\r\n\treturn true;\r\n}\r\n\r\n\r\n} \r\n \r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxtexture.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxTexture.cpp\r\n\r\n#include \t\"Gfx/Nx.h\"\r\n#include \t\"Gfx/xbox/p_NxTexture.h\"\r\n#include\t\"sys/file/filesys.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CTexture\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxTexture::CXboxTexture() :  m_transparent( false ), mp_texture( NULL )\r\n{\r\n\tm_num_mipmaps = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxTexture::~CXboxTexture()\r\n{\r\n\tif( mp_texture )\r\n\t{\r\n\t\tdelete mp_texture;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxTexture::SetEngineTexture( NxXbox::sTexture *p_texture )\r\n{\r\n\tmp_texture\t= p_texture;\r\n\tm_checksum\t= p_texture->Checksum;\r\n}\r\n\r\n\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxTexture::plat_load_texture( const char *p_texture_name, bool sprite, bool alloc_vram )\r\n{\r\n\tchar filename[256];\r\n\r\n\tstrcpy( filename, p_texture_name );\r\n\t\r\n\t// Append '.img.xbx' to the end.\r\n\tstrcat( filename, \".img.xbx\" );\r\n\r\n\tmp_texture = NxXbox::LoadTexture( filename );\r\n\t\r\n\treturn mp_texture;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxTexture::plat_replace_texture( CTexture *p_texture )\r\n{\t\t\t\t\t\t\t\t \t\r\n\tCXboxTexture *p_xbox_texture = static_cast<CXboxTexture *>( p_texture );\r\n\r\n\t// Go through and copy the texture.\r\n\tNxXbox::sTexture *p_src\t= p_xbox_texture->GetEngineTexture();\r\n\tNxXbox::sTexture *p_dst\t= GetEngineTexture();\r\n\r\n\tif( p_dst->pD3DTexture )\r\n\t{\r\n\t\tp_dst->pD3DTexture->Release();\r\n\t}\r\n\tif( p_dst->pD3DPalette )\r\n\t{\r\n\t\tp_dst->pD3DPalette->Release();\r\n\t}\r\n\r\n\tD3DSURFACE_DESC\tdesc;\r\n\tuint32\t\t\tnum_levels = p_src->pD3DTexture->GetLevelCount();\r\n\tp_src->pD3DTexture->GetLevelDesc( 0, &desc );\r\n\tif( D3D_OK != D3DDevice_CreateTexture(\tdesc.Width,\r\n\t\t\t\t\t\t\t\t\t\t\tdesc.Height,\r\n\t\t\t\t\t\t\t\t\t\t\tnum_levels,\r\n\t\t\t\t\t\t\t\t\t\t\t0,\r\n\t\t\t\t\t\t\t\t\t\t\tdesc.Format,\r\n\t\t\t\t\t\t\t\t\t\t\t0,\r\n\t\t\t\t\t\t\t\t\t\t\t&p_dst->pD3DTexture ))\r\n\t{\r\n\t\texit( 0 );\r\n\t}\r\n\r\n\t// Create and copy the palette if present.\r\n\tif( p_src->pD3DPalette )\r\n\t{\r\n\t\tif( D3D_OK != D3DDevice_CreatePalette( D3DPALETTE_256, &p_dst->pD3DPalette ))\r\n\t\t{\r\n\t\t\texit( 0 );\r\n\t\t}\r\n\t\t\r\n\t\tD3DCOLOR *p_src_palette;\r\n\t\tD3DCOLOR *p_dst_palette;\r\n\t\tp_src->pD3DPalette->Lock( &p_src_palette, D3DLOCK_READONLY );\r\n\t\tp_dst->pD3DPalette->Lock( &p_dst_palette, 0 );\r\n\t\tCopyMemory( p_dst_palette, p_src_palette, sizeof( D3DCOLOR ) * 256 );\r\n\t}\r\n\t\r\n\tfor( uint32 l = 0; l < num_levels; ++l )\r\n\t{\r\n\t\tp_src->pD3DTexture->GetLevelDesc( l, &desc );\r\n\r\n\t\tD3DLOCKED_RECT src_rect, dst_rect;\r\n\t\tp_src->pD3DTexture->LockRect( l, &src_rect, NULL, D3DLOCK_READONLY );\r\n\t\tp_dst->pD3DTexture->LockRect( l, &dst_rect, NULL, 0 );\r\n\r\n\t\tCopyMemory( dst_rect.pBits, src_rect.pBits, desc.Size );\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxTexture::plat_add_to_vram( void )\r\n{\t\t\t\t\t\t\t\t \t\r\n\t// Meaningless on Xbox, added to remove annoying debug stub output.\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxTexture::plat_remove_from_vram( void )\r\n{\t\t\t\t\t\t\t\t \t\r\n\t// Meaningless on Xbox, added to remove annoying debug stub output.\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint16\tCXboxTexture::plat_get_width() const\r\n{\r\n\tif( mp_texture )\r\n\t\treturn mp_texture->ActualWidth;\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint16\tCXboxTexture::plat_get_height() const\r\n{\r\n\tif( mp_texture )\r\n\t\treturn mp_texture->ActualHeight;\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\tCXboxTexture::plat_get_bitdepth() const\r\n{\r\n\tif( mp_texture )\r\n\t\treturn mp_texture->TexelDepth;\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\tCXboxTexture::plat_get_num_mipmaps() const\r\n{\r\n\treturn m_num_mipmaps;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCXboxTexture::plat_is_transparent() const\r\n{\r\n\treturn m_transparent;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n// Here's a machine specific implementation of CTexDict\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCXboxTexDict::CXboxTexDict( uint32 checksum ) : CTexDict( checksum )\r\n{\r\n\t// Load nothing\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCXboxTexDict::CXboxTexDict( const char *p_tex_dict_name ) : CTexDict( p_tex_dict_name, true )\r\n{\r\n\t LoadTextureDictionary( p_tex_dict_name );\t// the derived class will does this\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxTexDict::~CXboxTexDict()\r\n{\r\n\tUnloadTextureDictionary();\t\t\t\t// the derived class does this\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxTexDict::LoadTextureDictionary( const char *p_tex_dict_name )\r\n{\r\n\t// Count the number of entries in the lookup table. If it is empty, it is safe\r\n\t// to delete it and create a new, optimum sized one during the load process itself.\r\n\tif( mp_texture_lookup )\r\n\t{\r\n\t\tint num_items = 0;\r\n\t\tmp_texture_lookup->IterateStart();\r\n\t\twhile( mp_texture_lookup->IterateNext())\r\n\t\t\t++num_items;\r\n\r\n\t\tif( num_items == 0 )\r\n\t\t\tmp_texture_lookup = Nx::LoadTextureFile( p_tex_dict_name, mp_texture_lookup, true );\r\n\t\telse\r\n\t\t\tNx::LoadTextureFile( p_tex_dict_name, mp_texture_lookup );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNx::LoadTextureFile( p_tex_dict_name, mp_texture_lookup );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxTexDict::LoadTextureDictionaryFromMemory( void *p_mem )\r\n{\r\n\t// Count the number of entries in the lookup table. If it is empty, it is safe\r\n\t// to delete it and create a new, optimum sized one during the load process itself.\r\n\tif( mp_texture_lookup )\r\n\t{\r\n\t\tint num_items = 0;\r\n\t\tmp_texture_lookup->IterateStart();\r\n\t\twhile( mp_texture_lookup->IterateNext())\r\n\t\t\t++num_items;\r\n\r\n\t\tif( num_items == 0 )\r\n\t\t\tmp_texture_lookup =\tNx::LoadTextureFileFromMemory( &p_mem, mp_texture_lookup, true );\r\n\t\telse\r\n\t\t\tNx::LoadTextureFileFromMemory( &p_mem, mp_texture_lookup );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNx::LoadTextureFileFromMemory( &p_mem, mp_texture_lookup );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxTexDict::UnloadTextureDictionary( void )\r\n{\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCTexture *CXboxTexDict::plat_load_texture( const char *p_texture_name, bool sprite, bool alloc_vram )\r\n{\r\n\tCXboxTexture *p_texture = new CXboxTexture;\r\n\tif( !p_texture->LoadTexture( p_texture_name, sprite ))\r\n\t{\r\n\t\tDbg_Error(\"Can't load texture %s\", p_texture_name);\r\n\t}\r\n\treturn p_texture;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCTexture *CXboxTexDict::plat_reload_texture( const char *p_texture_name )\r\n{\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxTexDict::plat_unload_texture( CTexture *p_texture )\r\n{\r\n\tdelete p_texture;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxTexDict::plat_add_texture( CTexture *p_texture )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxTexDict::plat_remove_texture( CTexture *p_texture )\r\n{\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n#define MemoryRead( dst, size, num, src )\tCopyMemory(( dst ), ( src ), (( num ) * ( size )));\t\\\r\n\t\t\t\t\t\t\t\t\t\t\t( src ) += (( num ) * ( size ))\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nLst::HashTable<Nx::CTexture>* LoadTextureFileFromMemory( void **pp_mem, Lst::HashTable<Nx::CTexture> *p_texture_table, bool okay_to_rebuild_texture_table )\r\n{\r\n\tuint8 *p_data = (uint8*)( *pp_mem );\r\n\r\n\t// Read the texture file version and number of textures.\r\n\tint version, num_textures;\r\n\tMemoryRead( &version, sizeof( int ), 1, p_data );\r\n\tMemoryRead( &num_textures, sizeof( int ), 1, p_data );\r\n\r\n\t// If allowed, rebuild the texture table to the optimum size, using the same heap as the original table.\r\n\tif( okay_to_rebuild_texture_table )\r\n\t{\r\n\t\tuint32 optimal_table_size\t= num_textures * 2;\r\n\t\tuint32 test\t\t\t\t\t= 2;\r\n\t\tuint32 size\t\t\t\t\t= 1;\r\n\t\tfor( ;; test <<= 1, ++size )\r\n\t\t{\r\n\t\t\t// Check if this iteration of table size is sufficient, or if we have hit the maximum size.\r\n\t\t\tif(( optimal_table_size <= test ) || ( size >= 12 ))\r\n\t\t\t{\r\n\t\t\t\tMem::Allocator::BlockHeader*\tp_bheader\t= Mem::Allocator::BlockHeader::sRead( p_texture_table );\r\n\t\t\t\tMem::Allocator*\t\t\t\t\tp_allocater\t= p_bheader->mpAlloc;\r\n\r\n\t\t\t\tdelete p_texture_table;\r\n\r\n\t\t\t\tMem::Manager::sHandle().PushContext( p_allocater );\r\n\t\t\t\tp_texture_table = new Lst::HashTable<Nx::CTexture>( size );\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor( int t = 0; t < num_textures; ++t )\r\n\t{\r\n\t\t// Create the engine level texture.\r\n\t\tNxXbox::sTexture *p_texture = new NxXbox::sTexture;\r\n\r\n\t\tuint32 base_width, base_height, levels, texel_depth, palette_depth, dxt, palette_size;\r\n\t\tMemoryRead( &p_texture->Checksum,\tsizeof( uint32 ), 1, p_data );\r\n\t\tMemoryRead( &base_width,\t\t\tsizeof( uint32 ), 1, p_data );\r\n\t\tMemoryRead( &base_height,\t\t\tsizeof( uint32 ), 1, p_data );\r\n\t\tMemoryRead( &levels,\t\t\t\tsizeof( uint32 ), 1, p_data );\r\n\t\tMemoryRead( &texel_depth,\t\t\tsizeof( uint32 ), 1, p_data );\r\n\t\tMemoryRead( &palette_depth,\t\t\tsizeof( uint32 ), 1, p_data );\r\n\t\tMemoryRead( &dxt,\t\t\t\t\tsizeof( uint32 ), 1, p_data );\r\n\t\tMemoryRead( &palette_size,\t\t\tsizeof( uint32 ), 1, p_data );\r\n\r\n\t\tp_texture->BaseWidth\t= (uint16)base_width;\r\n\t\tp_texture->BaseHeight\t= (uint16)base_height;\r\n\t\tp_texture->Levels\t\t= (uint8)levels;\r\n\t\tp_texture->TexelDepth\t= (uint8)texel_depth;\r\n\t\tp_texture->PaletteDepth\t= (uint8)palette_depth;\r\n\t\tp_texture->DXT\t\t\t= (uint8)dxt;\r\n\t\t\r\n\t\tD3DFORMAT\ttexture_format;\r\n\t\tif( p_texture->DXT > 0 )\r\n\t\t{\r\n\t\t\tif(( p_texture->DXT == 1 ) || ( p_texture->DXT == 2 ))\r\n\t\t\t{\r\n\t\t\t\ttexture_format = D3DFMT_DXT1;\r\n\t\t\t}\r\n\t\t\telse if( p_texture->DXT == 5 )\r\n\t\t\t{\r\n\t\t\t\ttexture_format = D3DFMT_DXT5;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( p_texture->TexelDepth == 8 )\r\n\t\t{\r\n\t\t\ttexture_format = D3DFMT_P8;\r\n\t\t}\r\n\t\telse if( p_texture->TexelDepth == 16 )\r\n\t\t{\r\n\t\t\ttexture_format = D3DFMT_A1R5G5B5;\t// Could also be X1R5G5B5;\r\n\t\t}\r\n\t\telse if( p_texture->TexelDepth == 32 )\r\n\t\t{\r\n\t\t\ttexture_format = D3DFMT_A8R8G8B8;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t}\r\n\t\t\r\n\t\tif( D3D_OK != D3DDevice_CreateTexture(\tp_texture->BaseWidth, p_texture->BaseHeight, p_texture->Levels,\t0, texture_format, 0, &p_texture->pD3DTexture ))\r\n\t\t{\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t}\r\n\r\n\t\tif( palette_size > 0 )\r\n\t\t{\r\n\t\t\t// Create and lock the palette.\r\n\t\t\tif( D3D_OK != D3DDevice_CreatePalette(\tpalette_size == ( 256 * sizeof( D3DCOLOR )) ? D3DPALETTE_256 : D3DPALETTE_32, &p_texture->pD3DPalette ))\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tD3DCOLOR* p_colors;\r\n\t\t\t\tif( D3D_OK != p_texture->pD3DPalette->Lock( &p_colors, 0 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Read in palette data.\r\n\t\t\t\t\tMemoryRead( p_colors, palette_size, 1, p_data );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_texture->pD3DPalette = NULL;\r\n\t\t}\r\n\r\n\t\tfor( uint32 mip_level = 0; mip_level < p_texture->Levels; ++mip_level )\r\n\t\t{\r\n\t\t\tuint32 texture_level_data_size;\r\n\t\t\tMemoryRead( &texture_level_data_size, sizeof( uint32 ), 1, p_data );\r\n\r\n\t\t\tD3DLOCKED_RECT locked_rect;\r\n\t\t\tif( D3D_OK != p_texture->pD3DTexture->LockRect( mip_level, &locked_rect, NULL, 0 ))\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMemoryRead( locked_rect.pBits, texture_level_data_size, 1, p_data );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Add this texture to the table.\r\n\t\tNx::CXboxTexture *p_xbox_texture = new Nx::CXboxTexture();\r\n\t\tp_xbox_texture->SetEngineTexture( p_texture );\r\n\t\tp_texture_table->PutItem( p_texture->Checksum, p_xbox_texture );\r\n\t}\r\n\treturn p_texture_table;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nLst::HashTable<Nx::CTexture>* LoadTextureFile( const char *Filename, Lst::HashTable<Nx::CTexture> *p_texture_table, bool okay_to_rebuild_texture_table )\r\n{\r\n\t// Open the texture file.\r\n\tvoid *p_FH = File::Open( Filename, \"rb\" );\r\n\tif( !p_FH )\r\n\t{\r\n\t\tDbg_Message( \"Couldn't open texture file %s\\n\", Filename );\r\n\t\treturn p_texture_table;\r\n\t}\r\n\r\n\t// Read the texture file version and number of textures.\r\n\tint version, num_textures;\r\n\tFile::Read( &version, sizeof( int ), 1, p_FH );\r\n\tFile::Read( &num_textures, sizeof( int ), 1, p_FH );\r\n\r\n\t// If allowed, rebuild the texture table to the optimum size, using the same heap as the original table.\r\n\tif( okay_to_rebuild_texture_table )\r\n\t{\r\n\t\tuint32 optimal_table_size\t= num_textures * 2;\r\n\t\tuint32 test\t\t\t\t\t= 2;\r\n\t\tuint32 size\t\t\t\t\t= 1;\r\n\t\tfor( ;; test <<= 1, ++size )\r\n\t\t{\r\n\t\t\t// Check if this iteration of table size is sufficient, or if we have hit the maximum size.\r\n\t\t\tif(( optimal_table_size <= test ) || ( size >= 12 ))\r\n\t\t\t{\r\n\t\t\t\tMem::Allocator::BlockHeader*\tp_bheader\t= Mem::Allocator::BlockHeader::sRead( p_texture_table );\r\n\t\t\t\tMem::Allocator*\t\t\t\t\tp_allocater\t= p_bheader->mpAlloc;\r\n\r\n\t\t\t\tdelete p_texture_table;\r\n\r\n\t\t\t\tMem::Manager::sHandle().PushContext( p_allocater );\r\n\t\t\t\tp_texture_table = new Lst::HashTable<Nx::CTexture>( size );\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor( int t = 0; t < num_textures; ++t )\r\n\t{\r\n\t\t// Create the engine level texture.\r\n\t\tNxXbox::sTexture *p_texture = new NxXbox::sTexture;\r\n\r\n\t\tuint32 base_width, base_height, levels, texel_depth, palette_depth, dxt, palette_size;\r\n\t\tFile::Read( &p_texture->Checksum,\tsizeof( uint32 ), 1, p_FH );\r\n\t\tFile::Read( &base_width,\t\t\tsizeof( uint32 ), 1, p_FH );\r\n\t\tFile::Read( &base_height,\t\t\tsizeof( uint32 ), 1, p_FH );\r\n\t\tFile::Read( &levels,\t\t\t\tsizeof( uint32 ), 1, p_FH );\r\n\t\tFile::Read( &texel_depth,\t\t\tsizeof( uint32 ), 1, p_FH );\r\n\t\tFile::Read( &palette_depth,\t\t\tsizeof( uint32 ), 1, p_FH );\r\n\t\tFile::Read( &dxt,\t\t\t\t\tsizeof( uint32 ), 1, p_FH );\r\n\t\tFile::Read( &palette_size,\t\t\tsizeof( uint32 ), 1, p_FH );\r\n\r\n\t\tp_texture->BaseWidth\t= (uint16)base_width;\r\n\t\tp_texture->BaseHeight\t= (uint16)base_height;\r\n\t\tp_texture->Levels\t\t= (uint8)levels;\r\n\t\tp_texture->TexelDepth\t= (uint8)texel_depth;\r\n\t\tp_texture->PaletteDepth\t= (uint8)palette_depth;\r\n\t\tp_texture->DXT\t\t\t= (uint8)dxt;\r\n\t\t\r\n\t\tD3DFORMAT\ttexture_format;\r\n\t\tif( p_texture->DXT > 0 )\r\n\t\t{\r\n\t\t\tif(( p_texture->DXT == 1 ) || ( p_texture->DXT == 2 ))\r\n\t\t\t{\r\n\t\t\t\ttexture_format = D3DFMT_DXT1;\r\n\t\t\t}\r\n\t\t\telse if( p_texture->DXT == 5 )\r\n\t\t\t{\r\n\t\t\t\ttexture_format = D3DFMT_DXT5;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( p_texture->TexelDepth == 8 )\r\n\t\t{\r\n\t\t\ttexture_format = D3DFMT_P8;\r\n\t\t}\r\n\t\telse if( p_texture->TexelDepth == 16 )\r\n\t\t{\r\n\t\t\ttexture_format = D3DFMT_A1R5G5B5;\t// Could also be X1R5G5B5;\r\n\t\t}\r\n\t\telse if( p_texture->TexelDepth == 32 )\r\n\t\t{\r\n\t\t\ttexture_format = D3DFMT_A8R8G8B8;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t}\r\n\t\t\r\n\t\tif( D3D_OK != D3DDevice_CreateTexture(\tp_texture->BaseWidth, p_texture->BaseHeight, p_texture->Levels,\t0, texture_format, 0, &p_texture->pD3DTexture ))\r\n\t\t{\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t}\r\n\r\n\t\tif( palette_size > 0 )\r\n\t\t{\r\n\t\t\t// Create and lock the palette.\r\n\t\t\tif( D3D_OK != D3DDevice_CreatePalette(\tpalette_size == ( 256 * sizeof( D3DCOLOR )) ? D3DPALETTE_256 : D3DPALETTE_32, &p_texture->pD3DPalette ))\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tD3DCOLOR* p_colors;\r\n\t\t\t\tif( D3D_OK != p_texture->pD3DPalette->Lock( &p_colors, 0 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Read in palette data.\r\n\t\t\t\t\tFile::Read( p_colors, palette_size, 1, p_FH );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_texture->pD3DPalette = NULL;\r\n\t\t}\r\n\r\n\t\tfor( uint32 mip_level = 0; mip_level < p_texture->Levels; ++mip_level )\r\n\t\t{\r\n\t\t\tuint32 texture_level_data_size;\r\n\t\t\tFile::Read( &texture_level_data_size, sizeof( uint32 ), 1, p_FH );\r\n\r\n\t\t\tD3DLOCKED_RECT locked_rect;\r\n\t\t\tif( D3D_OK != p_texture->pD3DTexture->LockRect( mip_level, &locked_rect, NULL, 0 ))\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tFile::Read( locked_rect.pBits, texture_level_data_size, 1, p_FH );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Add this texture to the table.\r\n\t\tNx::CXboxTexture *p_xbox_texture = new Nx::CXboxTexture();\r\n\t\tp_xbox_texture->SetEngineTexture( p_texture );\r\n\t\tp_texture_table->PutItem( p_texture->Checksum, p_xbox_texture );\r\n\t}\r\n\tFile::Close( p_FH );\r\n\r\n\treturn p_texture_table;\r\n}\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxtexture.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// p_NxScene.h\r\n\r\n#ifndef\t__GFX_P_NX_TEXTURE_H__\r\n#define\t__GFX_P_NX_TEXTURE_H__\r\n\r\n#include \t\"Gfx/NxTexture.h\"\r\n#include \t\"Gfx/xbox/nx/texture.h\"\r\n#include \t\"Gfx/xbox/nx/material.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// Private classes\r\n//\r\n// Machine specific implementation of the CTexture\r\nclass\tCXboxTexture : public CTexture\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCXboxTexture();\r\n\tvirtual\t\t\t\t\t\t~CXboxTexture();\r\n\r\n\tNxXbox::sTexture\t\t\t*GetEngineTexture() const;\r\n\tvoid\t\t\t\t\t\tSetEngineTexture( NxXbox::sTexture *p_texture );\r\n\r\n\r\nprivate:\t\t// It's all private, as it is machine specific\r\n\tvirtual bool\t\t\t\tplat_load_texture( const char *p_texture_name, bool sprite, bool alloc_vram );\r\n\tvirtual bool\t\t\t\tplat_replace_texture( CTexture *p_texture );\r\n\tvirtual bool\t\t\t\tplat_add_to_vram( void );\r\n\tvirtual bool\t\t\t\tplat_remove_from_vram( void );\r\n\r\n\tvirtual uint16\t\t\t\tplat_get_width() const;\r\n\tvirtual uint16\t\t\t\tplat_get_height() const;\r\n\tvirtual uint8\t\t\t\tplat_get_bitdepth() const;\r\n\tvirtual uint8\t\t\t\tplat_get_num_mipmaps() const;\r\n\tvirtual bool\t\t\t\tplat_is_transparent() const;\r\n\r\n\tuint8\t\t\t\t\t\tm_num_mipmaps;\r\n\tbool\t\t\t\t\t\tm_transparent;\r\n\r\n\t// The actual data in the engine\r\n\tNxXbox::sTexture *\t\t\tmp_texture;\r\n\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ninline NxXbox::sTexture\t*CXboxTexture::GetEngineTexture() const\r\n{\r\n\treturn mp_texture;\r\n}\r\n\r\n\r\n\r\n//////////////////////////////////////////////////////////////////////////////////\r\n// Machine specific implementation of the CMaterial\r\nclass\tCXboxMaterial : public CMaterial\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCXboxMaterial();\r\n\tvirtual\t\t\t\t\t\t~CXboxMaterial();\r\n\r\nprivate:\r\n\tImage::RGBA\t\t\t\t\tplat_get_rgba() const;\r\n\tvoid\t\t\t\t\t\tplat_set_rgba(Image::RGBA rgba);\r\n\tvoid\t\t\t\t\t\tplat_set_texture();\r\n\r\n\tImage::RGBA\t\t\t\t\tm_rgba;\r\n\r\n\t// The actual data in the engine\r\n\tNxXbox::sMaterial *\t\t\tmp_material;\r\n};\r\n\r\n//////////////////////////////////////////////////////////////////////////////////\r\n// Machine specific implementation of the CTexDict\r\nclass\tCXboxTexDict : public CTexDict\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCXboxTexDict( uint32 checksum );\t\t// loads nothing\r\n\t\t\t\t\t\t\t\tCXboxTexDict(const char *p_tex_dict_name);\r\n\tvirtual\t\t\t\t\t\t~CXboxTexDict();\r\n\r\n\tbool\t\t\t\t\t\tLoadTextureDictionary( const char *p_tex_dict_name );\r\n\tbool\t\t\t\t\t\tLoadTextureDictionaryFromMemory( void *p_mem );\r\n\tbool\t\t\t\t\t\tUnloadTextureDictionary();\r\n\r\nprivate:\r\n\r\n\t// Platform-specific calls\r\n\tvirtual CTexture *\t\t\tplat_load_texture( const char *p_texture_name, bool sprite, bool alloc_vram );\r\n\tvirtual CTexture *\t\t\tplat_reload_texture( const char *p_texture_name );\r\n\tvirtual bool\t\t\t\tplat_unload_texture( CTexture *p_texture );\r\n\tvirtual void\t\t\t\tplat_add_texture( CTexture *p_texture );\r\n\tvirtual bool\t\t\t\tplat_remove_texture( CTexture *p_texture );\r\n};\r\n\r\nLst::HashTable<Nx::CTexture>*\tLoadTextureFile( const char *Filename, Lst::HashTable<Nx::CTexture> *p_texture_table, bool okay_to_rebuild_texture_table = false );\r\nLst::HashTable<Nx::CTexture>*\tLoadTextureFileFromMemory( void **pp_mem, Lst::HashTable<Nx::CTexture> *p_texture_table, bool okay_to_rebuild_texture_table = false );\r\n\r\n\r\n} // Namespace Nx  \t\t\t\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxweather.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_NxWeather.cpp\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  6/19/2003\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/xbox/nx/render.h\"\r\n\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/xbox/p_nxtexture.h>\r\n#include \"gfx/xbox/nx/mesh.h\"\r\n#include \"gfx/xbox/p_nxweather.h\"\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/skater.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <engine/SuperSector.h>\r\n#include \"gfx/nx.h\"\r\n\r\n#include \"gfx/xbox/nx/sprite.h\"\r\n\r\n#define FEELER_START\t\t\t50000.0f\r\n#define NUM_LINES_PER_BATCH\t\t80\r\n#define NUM_SPRITES_PER_BATCH\t80\r\n\r\n#define PRECISION_SHIFT\t\t\t4\r\n\r\n#define RENDER_DIST\t\t\t\t16\r\n#define SEQ_START\t\t\t\t411\t\t// Between 1 and 4095.\r\n#define SEQ_MASK\t\t\t\t0x0240\r\n\r\nunsigned char grid_bytes[70*1024];\r\n\r\n//1-3: 0x03\r\n//1-7: 0x06\r\n//1-15: 0x0C\r\n//1-31: 0x14\r\n//1-63: 0x30\r\n//1-127: 0x60\r\n//1-255: 0xB8\r\n//1-511: 0x0110\r\n//1-1023: 0x0240\r\n//1-2047: 0x0500\r\n//1-4095: 0x0CA0\r\n//1-8191: 0x1B00\r\n//1-16383: 0x3500\r\n//1-32767: 0x6000\r\n//1-65535: 0xB400\r\n//0x00012000\r\n//0x00020400\r\n//0x00072000\r\n//0x00090000\r\n//0x00140000\r\n//0x00300000\r\n//0x00400000\r\n//0x00D80000\r\n//0x01200000\r\n//0x03880000\r\n//0x07200000\r\n//0x09000000\r\n//0x14000000\r\n//0x32800000\r\n//0x48000000\r\n//0xA3000000\r\n\r\n\r\nnamespace Nx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxWeather::CXboxWeather()\r\n{\r\n\tmp_roof_height_index\t= NULL;\r\n\tmp_rain_texture\t\t\t= NULL;\r\n\r\n\tm_rain_blend\t\t\t= NxXbox::GetBlendMode( CRCD( 0xa86285a1, \"fixadd\" )) | 0x80000000UL;\r\n\tm_splash_blend\t\t\t= NxXbox::GetBlendMode( CRCD( 0xa86285a1, \"fixadd\" )) | 0x80000000UL;\r\n\tm_snow_blend\t\t\t= NxXbox::GetBlendMode( CRCD( 0xa86285a1, \"fixadd\" )) | 0x80000000UL;\r\n\r\n\tm_rain_rate\t\t\t\t= 0.0f;\r\n\tm_splash_rate\t\t\t= 0.0f;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxWeather::~CXboxWeather()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxWeather::plat_update_grid( void )\r\n{\r\n\tm_system_active = false;\r\n\r\n\t// Get super sector manager.\r\n\tSSec::Manager *ss_man;\r\n\tMth::Line line;\r\n\tss_man = Nx::CEngine::sGetNearestSuperSectorManager( line );\t\t// Line is ignored, 1st manager is returned.\r\n\tif ( !ss_man ) return;\r\n\r\n\t// Calculate the size of the world in cels.\r\n\tint min_x = ( ((int)ss_man->GetWorldBBox()->GetMin()[X]) / WEATHER_CEL_SIZE ) - 1;\r\n\tint max_x = ( ((int)ss_man->GetWorldBBox()->GetMax()[X]) / WEATHER_CEL_SIZE ) + 1;\r\n\tint min_z = ( ((int)ss_man->GetWorldBBox()->GetMin()[Z]) / WEATHER_CEL_SIZE ) - 1;\r\n\tint max_z = ( ((int)ss_man->GetWorldBBox()->GetMax()[Z]) / WEATHER_CEL_SIZE ) + 1;\r\n\r\n\t// Define a maximum...\r\n\tif(( max_x - min_x ) > 350 )\r\n\t{\r\n\t\tint wid = ( max_x - min_x );\r\n\t\tint excess = ( wid - 350 );\r\n\t\tmin_x += ( excess / 2 );\r\n\t\tmax_x -= ( excess / 2 );\r\n\t}\r\n\r\n\tif(( max_z - min_z ) > 300 )\r\n\t{\r\n\t\tint wid = ( max_z - min_z );\r\n\t\tint excess = ( wid - 300 );\r\n\t\tmin_z += ( excess / 2 );\r\n\t\tmax_z -= ( excess / 2 );\r\n\t}\r\n\r\n\t// This is the actual width.\r\n\tm_width = ( max_x - min_x ) + 1;\r\n\tm_height = ( max_z - min_z ) + 1;\r\n\r\n\tm_min_x = (float)( min_x * WEATHER_CEL_SIZE );\r\n\tm_min_z = (float)( min_z * WEATHER_CEL_SIZE );\r\n\r\n\t// Temporary buffer for the raw array.\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tunsigned char * p8 = new unsigned char[m_width*m_height];\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Go through and get the height for each cel corner.\r\n\tCFeeler feeler;\r\n\tint num_heights = 0;\r\n\tint xx, zz;\r\n\tfor ( zz = min_z; zz <= max_z; zz++ )\r\n\t{\r\n\t\tfor ( xx = min_x; xx <= max_x; xx++ )\r\n\t\t{\r\n\t\t\t// The cel to fill.\r\n\t\t\tint cel = ( ( zz - min_z ) * m_width ) + ( xx - min_x );\r\n\r\n\t\t\t// The position to check.\r\n\t\t\tMth::Vector pos;\r\n\t\t\tpos[X] = (float)( xx * WEATHER_CEL_SIZE );\r\n\t\t\tpos[Y] = FEELER_START;\r\n\t\t\tpos[Z] = (float)( zz * WEATHER_CEL_SIZE );\r\n\t\t\tpos[W] = 1.0f;\r\n\r\n\t\t\tfeeler.SetStart( pos );\r\n\t\t\tpos[Y] = -FEELER_START;\r\n\t\t\tfeeler.SetEnd( pos );\r\n\r\n\t\t\t// Get the y position.\r\n\t\t\tsint32 y;\r\n\t\t\tif ( feeler.GetCollision( false, false ) )\t\t// No movables, nearest collision.\r\n\t\t\t{\r\n\t\t\t\ty = (sint32)( feeler.GetPoint()[Y] * SUB_INCH_PRECISION );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ty = (sint32)( FEELER_START * SUB_INCH_PRECISION );\r\n\t\t\t}\r\n\r\n\t\t\t// See if a close enough y pos already exists.\r\n\t\t\tint found = -1;\r\n\t\t\tfor ( int lp = 0; lp < num_heights; lp++ )\r\n\t\t\t{\r\n\t\t\t\tif ( abs( ( m_roof_height[lp] - y ) ) < HEIGHT_TOLERANCE )\r\n\t\t\t\t{\r\n\t\t\t\t\tfound = lp;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Fill in the cel.\r\n\t\t\tif ( found != -1 )\r\n\t\t\t{\r\n\t\t\t\t// Existing height.\r\n\t\t\t\tp8[cel] = found;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// New height.\r\n\t\t\t\tp8[cel] = num_heights;\r\n\t\t\t\tm_roof_height[num_heights] = y;\r\n\t\t\t\tnum_heights++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Work out highest height for each cel.\r\n\tfor ( zz = min_z; zz <= max_z; zz++ )\r\n\t{\r\n\t\tfor ( xx = min_x; xx <= max_x; xx++ )\r\n\t\t{\r\n\t\t\t// The cel to fill.\r\n\t\t\tint cel = ( ( zz - min_z ) * m_width ) + ( xx - min_x );\r\n\t\t\tint celx = ( ( zz - min_z ) * m_width ) + ( ( xx + 1 ) - min_x );\r\n\t\t\tint celz = ( ( ( zz + 1 ) - min_z ) * m_width ) + ( xx - min_x );\r\n\t\t\tint celxz = ( ( ( zz + 1 ) - min_z ) * m_width ) + ( ( xx + 1 ) - min_x );\r\n\r\n\t\t\tif ( m_roof_height[p8[celx]] > m_roof_height[p8[cel]] ) p8[cel] = p8[celx];\r\n\t\t\tif ( m_roof_height[p8[celz]] > m_roof_height[p8[cel]] ) p8[cel] = p8[celz];\r\n\t\t\tif ( m_roof_height[p8[celxz]] > m_roof_height[p8[cel]] ) p8[cel] = p8[celxz];\r\n\t\t}\r\n\t}\r\n\r\n\t// Create a sparse array.\r\n\tmp_roof_row = (sRowEntry *)grid_bytes;\r\n\tmp_roof_height_index = (unsigned char *)&mp_roof_row[m_height];\r\n\r\n\t// 0 = offset\r\n\t// 1 = width\r\n\t// 2 = index\r\n\r\n\tunsigned short index = 0;\r\n\tfor ( zz = 0; zz <= m_height; zz++ )\r\n\t{\r\n\t\tunsigned short start = 0;\r\n\t\tunsigned short end = m_width - 1;\r\n\r\n\t\t// Scan to find the start.\r\n\t\tbool start_set = false;\r\n\t\tfor ( xx = 0; xx < m_width; xx++ )\r\n\t\t{\r\n\t\t\tint cel = ( zz * m_width ) + xx;\r\n\r\n\t\t\tif ( m_roof_height[p8[cel]] != (sint32)( FEELER_START * SUB_INCH_PRECISION ) )\r\n\t\t\t{\r\n\t\t\t\tif ( !start_set )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Set start value.\r\n\t\t\t\t\tstart = xx;\r\n\t\t\t\t\tstart_set = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Set end value.\r\n\t\t\t\t\tend = xx;\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Copy data & set row entry.\r\n\t\tif ( start < end )\r\n\t\t{\r\n\t\t\tmp_roof_row[zz].start = start;\r\n\t\t\tmp_roof_row[zz].end = end;\r\n\t\t\tmp_roof_row[zz].index = index;\r\n\t\t\tfor ( xx = start; xx <= end ; xx++ )\r\n\t\t\t{\r\n\t\t\t\tint cel = ( zz * m_width ) + xx;\r\n\r\n\t\t\t\tmp_roof_height_index[index] = p8[cel];\r\n\t\t\t\tindex++;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Row doesn't exist.\r\n\t\t\tmp_roof_row[zz].start = 16384;\r\n\t\t\tmp_roof_row[zz].end = 0;\r\n\t\t\tmp_roof_row[zz].index = 0;\r\n\t\t}\r\n\t}\r\n\r\n\tdelete p8;\r\n\r\n\tint new_size = ( m_height * 6 ) + index;\r\n\r\n\tDbg_Message( \"Grid Size: Old: %d New: %d Num Heights: %d\\n\", ( m_width * m_height ), new_size, num_heights );\r\n\r\n\t// Set all drip time counters to 255.\r\n\t// 255 means the drop won't be rendered.\r\n\t// Setting to anything other than 255 will mean that it will increment to 255 and stop.\r\n\tfor ( int lp = 0; lp < ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ); lp++ )\r\n\t{\r\n\t\tm_drop_time[lp] = 255;\r\n\t\tm_x_offset[lp] = Mth::Rnd( 255 );\r\n\t\tm_z_offset[lp] = Mth::Rnd( 255 );\r\n\t}\r\n\tm_active_drops = 0;\r\n\r\n\tm_seq = SEQ_START;\r\n\r\n\t// Get the texture.\r\n\tNx::CTexture*\t\tp_texture;\r\n\tNx::CXboxTexture*\tp_xbox_texture;\r\n\tmp_rain_texture = NULL;\r\n\r\n\t// Set Rain Texture.\r\n\tp_texture\t\t= Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( CRCD( 0x45c7eb0f,\"splash\" ));\r\n\tp_xbox_texture\t= static_cast<Nx::CXboxTexture*>( p_texture );\r\n\tif( p_xbox_texture )\r\n\t{\r\n\t\tmp_rain_texture = p_xbox_texture->GetEngineTexture();\r\n\t}\r\n\r\n\t// Set Snow Texture.\r\n\tp_texture = Nx::CTexDictManager::sp_particle_tex_dict->GetTexture( CRCD( 0xc97c5a4c,\"snow\" ));\r\n\tp_xbox_texture = static_cast<Nx::CXboxTexture*>( p_texture );\r\n\tif( p_xbox_texture )\r\n\t{\r\n\t\tmp_snow_texture = p_xbox_texture->GetEngineTexture();\r\n\t}\r\n\r\n\tm_system_active = true;\r\n\r\n\t// Zero out the splashes.\r\n\tfor( int sp = 0; sp < NUM_SPLASH_ACTIVE; sp++ )\r\n\t{\r\n\t\tm_splash_current_life[sp] = 0;\r\n\t}\r\n\tm_current_splash = 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxWeather::plat_process( float delta_time )\r\n{\r\n\tif( !m_system_active ) return;\r\n\r\n\tif( m_raining )\r\n\t{\r\n\t\t// It's raining.\r\n\t\tfloat rate = m_rain_drops_per_frame;\r\n\t\tif( rate > (float)(( DROP_SIZE * DROP_SIZE * DROP_LAYERS ) / m_rain_frames ))\r\n\t\t{\r\n\t\t\trate = (float)( ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ) / m_rain_frames );\r\n\t\t}\r\n\r\n\t\tfloat last = m_rain_rate;\r\n\t\tm_rain_rate += rate;\r\n\t\tint new_drops = (int)m_rain_rate - (int)last;\r\n\r\n\t\tfor( int lp = 0; lp < new_drops; lp++ )\r\n\t\t{\r\n\t\t\t// If this cel is not inactive, we caught up with ourselves.\r\n\t\t\tif ( m_drop_time[m_seq] != 255 ) break;\r\n\r\n\t\t\t// Setup the drop.\r\n\t\t\tm_drop_time[m_seq] = ( 254 - m_rain_frames );\r\n\t\t\tm_x_offset[m_seq] = Mth::Rnd( 255 );\r\n\t\t\tm_z_offset[m_seq] = Mth::Rnd( 255 );\r\n\t\t\tm_active_drops++;\r\n\r\n\t\t\t// Calculate next sequence value. Notice hack to get entry 0 into the sequence.\r\n\t\t\tswitch ( m_seq )\r\n\t\t\t{\r\n\t\t\t\tcase SEQ_START:\r\n\t\t\t\t\tm_seq = 0;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tm_seq = SEQ_START;\r\n\t\t\t\t\t// Fall through to default case...\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tif ( m_seq & 1 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_seq = ( m_seq >> 1 ) ^ SEQ_MASK;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_seq = ( m_seq >> 1 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// It's snowing.\r\n\t\tfloat rate = m_snow_flakes_per_frame;\r\n\t\tif ( rate > (float)( ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ) / m_snow_frames ) ) rate = (float)( ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ) / m_snow_frames );\r\n\r\n\t\tfloat last = m_snow_rate;\r\n\t\tm_snow_rate += rate;\r\n\t\tint new_drops = (int)m_snow_rate - (int)last;\r\n\r\n\t\tfor ( int lp = 0; lp < new_drops; lp++ )\r\n\t\t{\r\n\t\t\t// If this cel is not inactive, we caught up with ourselves.\r\n\t\t\tif ( m_drop_time[m_seq] != 255 ) break;\r\n\r\n\t\t\t// Setup the drop.\r\n\t\t\tm_drop_time[m_seq] = ( 254 - m_snow_frames );\r\n\t\t\tm_x_offset[m_seq] = Mth::Rnd( 255 );\r\n\t\t\tm_z_offset[m_seq] = Mth::Rnd( 255 );\r\n\t\t\tm_active_drops++;\r\n\r\n\t\t\t// Calculate next sequence value. Notice hack to get entry 0 into the sequence.\r\n\t\t\tswitch ( m_seq )\r\n\t\t\t{\r\n\t\t\t\tcase SEQ_START:\r\n\t\t\t\t{\r\n\t\t\t\t\tm_seq = 0;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase 0:\r\n\t\t\t\t{\r\n\t\t\t\t\tm_seq = SEQ_START;\r\n\t\t\t\t\t// Fall through to default case...\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( m_seq & 1 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_seq = ( m_seq >> 1 ) ^ SEQ_MASK;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_seq = ( m_seq >> 1 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\ninline DWORD FtoDW( FLOAT f ) { return *((DWORD*)&f); }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxWeather::plat_render_snow( float skx, float skz )\r\n{\r\n\t// Early out if no drops to draw.\r\n\tif( !m_active_drops ) return;\r\n\r\n\t// Get skater position.\r\n\tint x = (int)(( skx - m_min_x ) / WEATHER_CEL_SIZE );\r\n\tint z = (int)(( skz - m_min_z ) / WEATHER_CEL_SIZE );\r\n\r\n\t// Calculate area to render.\r\n\tint sx = x - RENDER_DIST;\r\n\tint ex = x + DROP_SIZE;\t//RENDER_DIST;\r\n\tint sz = z - RENDER_DIST;\r\n\tint ez = z + DROP_SIZE;\t//RENDER_DIST;\r\n\r\n\t// Clip z values.\r\n\tif( ez < 0 ) return;\r\n\tif( sz > ( m_height - 1 )) return;\r\n\r\n\t// Pointsprites use texture stage 3 for some reason...\r\n\tNxXbox::set_blend_mode( m_snow_blend );\r\n\tNxXbox::set_render_state( RS_ALPHACUTOFF, 0 );\r\n\tNxXbox::set_render_state( RS_UVADDRESSMODE3, 0x00000000UL );\r\n\tmp_snow_texture->Set( 3 );\r\n\r\n\t// Set up point sprite rendering.\r\n\tD3DDevice_SetRenderState( D3DRS_POINTSPRITEENABLE,\tTRUE );\r\n\tD3DDevice_SetRenderState( D3DRS_POINTSCALEENABLE,\tTRUE );\r\n\tD3DDevice_SetRenderState( D3DRS_POINTSIZE,\t\t\tFtoDW( m_snow_size ));\r\n\tD3DDevice_SetRenderState( D3DRS_POINTSCALE_A,\t\tFtoDW( 0.00f ));\r\n\tD3DDevice_SetRenderState( D3DRS_POINTSCALE_B,\t\tFtoDW( 0.00f ));\r\n\tD3DDevice_SetRenderState( D3DRS_POINTSCALE_C,\t\tFtoDW( 1.00f ));\r\n\r\n\tNxXbox::set_pixel_shader( PixelShaderPointSprite );\r\n\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\r\n\tfloat minx = m_min_x;\r\n\tfloat minz = m_min_z;\r\n\t\r\n\t// Calculate drop height list.\r\n\tint lp;\r\n\tfloat y_off[256];\r\n\tfor( lp = ( 254 - m_snow_frames ); lp < 256; lp++ )\r\n\t{\r\n\t\ty_off[lp] = m_snow_height - (((float)(( lp - 254 ) + m_snow_frames ) / (float)m_snow_frames ) * m_snow_height );\r\n\t}\r\n\r\n\t// Calculate xz offset list.\r\n\tfloat xz_off[256];\r\n\tfor( lp = 0; lp < 256; lp++ )\r\n\t{\r\n\t\txz_off[lp] = ((float)lp * (float)( WEATHER_CEL_SIZE / 2 )) / 255.0f;\r\n\t}\r\n\r\n\t// Calculate sine wave.\r\n\tfloat sin_off[256];\r\n\r\n\tfor( lp = 0; lp < 256; lp++ )\r\n\t{\r\n\t\tsin_off[lp] = sinf( Mth::PI * 2.0f * ((float)lp / 256.0f )) * ( WEATHER_CEL_SIZE / 2 );\r\n\t}\r\n\r\n\t// Get Xbox format color.\r\n\tuint32 snow_color = ((uint32)m_snow_color.a << 24 ) | ((uint32)m_snow_color.r << 16 ) | ((uint32)m_snow_color.g << 8 ) | ((uint32)m_snow_color.b << 0 );\r\n\r\n\tint\tflakes = 0;\r\n\r\n\tDWORD* p_push\t\t\t\t= NULL;\r\n\tDWORD* p_push_encode_fixup\t= NULL;\r\n\tuint32 dwords_written\t\t= 0;\r\n\tuint32 total_dwords_written\t= 2;\r\n\r\n\tfor( int lzz = sz; lzz <= ez; lzz++ )\r\n\t{\r\n\t\tint zz = ( lzz < 0 ) ? 0 : ( lzz > ( m_height - 1 ) ) ? ( m_height - 1 ) : lzz;\r\n\r\n\t\tif( mp_roof_row[zz].start == 16384 ) continue;\r\n\r\n\t\tfloat vx = ((float)sx * (float)WEATHER_CEL_SIZE ) + minx;\r\n\t\tfloat vz = ((float)zz * (float)WEATHER_CEL_SIZE ) + minz;\r\n\r\n\t\tint cel = mp_roof_row[zz].index + ( sx - mp_roof_row[zz].start );\r\n\r\n\t\tint drop_cel_z = (( zz & ( DROP_SIZE - 1 )) << DROP_SIZE_SHIFT );\r\n\r\n\t\tfor( int lxx = sx; lxx <= ex; lxx++, cel++ )\r\n\t\t{\r\n\t\t\tint xx = ( lxx > mp_roof_row[zz].start ) ? ( ( lxx < mp_roof_row[zz].end ) ? lxx : mp_roof_row[zz].end ) : mp_roof_row[zz].start;\r\n\r\n\t\t\t// Get the current drop value. Skip this one if it's inactive.\r\n\t\t\tint drop_cel = drop_cel_z + ( xx & ( DROP_SIZE - 1 ));\r\n\r\n\t\t\tvx += (float)WEATHER_CEL_SIZE;\r\n\t\t\tfloat vy = (float)( m_roof_height[mp_roof_height_index[cel]] >> PRECISION_SHIFT );\r\n\r\n\t\t\tfor( int d = 0; d < DROP_LAYERS; d++, drop_cel += ( DROP_SIZE * DROP_SIZE ))\r\n\t\t\t{\r\n\t\t\t\tif( m_drop_time[drop_cel] == 255 )\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t// Create the position for rendering.\r\n\t\t\t\tfloat v0x = vx + xz_off[m_x_offset[drop_cel]] + sin_off[(m_z_offset[drop_cel]+m_drop_time[drop_cel])&255];\r\n\t\t\t\tfloat v0y = vy + y_off[m_drop_time[drop_cel]] + m_snow_size;\r\n\t\t\t\tfloat v0z = vz + xz_off[m_z_offset[drop_cel]] + sin_off[(m_x_offset[drop_cel]+m_drop_time[drop_cel])&255];\r\n\r\n\t\t\t\tif( flakes == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tflakes = NUM_SPRITES_PER_BATCH;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Grab the push buffer if we don't have it yet.\r\n\t\t\t\tif( p_push == NULL )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Grab 32k of push buffer.\t\r\n\t\t\t\t\tp_push = D3DDevice_BeginPush( 32 * 1024 / 4 );\r\n\r\n\t\t\t\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t\t\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t\t\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\t\t\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\t\t\t\tp_push[1]\t= D3DPT_POINTLIST;\r\n\t\t\t\t\tp_push\t\t+= 2;\r\n\r\n\t\t\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\t\t\t// As yet, we don't know how many dwords we will write, so save a pointer to the current push buffer location\r\n\t\t\t\t\t// so we can fix up this value at the end.\r\n\t\t\t\t\tp_push_encode_fixup = p_push;\r\n\t\t\t\t\t++p_push;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tp_push[0]\t\t\t\t= *((uint32*)&v0x );\r\n\t\t\t\tp_push[1]\t\t\t\t= *((uint32*)&v0y );\r\n\t\t\t\tp_push[2]\t\t\t\t= *((uint32*)&v0z );\r\n\t\t\t\tp_push[3]\t\t\t\t= snow_color;\r\n\r\n\t\t\t\tp_push\t\t\t\t\t+= 4;\r\n\t\t\t\tdwords_written\t\t\t+= 4;\r\n\t\t\t\ttotal_dwords_written\t+= 4;\r\n\r\n\t\t\t\t// Check for hitting the max dwords for this encode block, in which case we need to end this block\r\n\t\t\t\t// and start another one.\r\n\t\t\t\tif( dwords_written >= 2044 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Now we know exactly how many dwords written, fix-up our earlier entry.\r\n\t\t\t\t\tp_push_encode_fixup[0]\t= D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, dwords_written );\r\n\r\n\t\t\t\t\t// Are we approaching the end of this push buffer? If so, close it out and start a new one.\r\n\t\t\t\t\tif( total_dwords_written > 6000 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// End the push buffer.\r\n\t\t\t\t\t\ttotal_dwords_written\t= 0;\r\n\t\t\t\t\t\tp_push[0]\t\t\t\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\t\t\t\t\tp_push[1]\t\t\t\t= 0;\r\n\t\t\t\t\t\tp_push\t\t\t\t\t+= 2;\r\n\t\t\t\t\t\tD3DDevice_EndPush( p_push );\r\n\r\n\t\t\t\t\t\tp_push\t\t\t\t\t= NULL;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// As yet, we don't know how many dwords we will write, so save a pointer to the current push buffer location\r\n\t\t\t\t\t\t// so we can fix up this value at the end.\r\n\t\t\t\t\t\tp_push_encode_fixup\t\t= p_push;\r\n\t\t\t\t\t\t++p_push;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tdwords_written = 0;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tflakes--;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif( p_push )\r\n\t{\r\n\t\t// Now we know exactly how many dwords written, fix-up our earlier entry.\r\n\t\tp_push_encode_fixup[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, dwords_written );\r\n\r\n\t\t// End the push buffer.\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1] = 0;\r\n\t\tp_push += 2;\r\n\t\tD3DDevice_EndPush( p_push );\r\n\t}\r\n\r\n\t// Restore render states.\r\n\tD3DDevice_SetRenderState( D3DRS_POINTSPRITEENABLE, FALSE );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxWeather::plat_render_rain( float skx, float skz )\r\n{\r\n\t// Early out if no drops to draw.\r\n\tif ( !m_active_drops ) return;\r\n\r\n\t// Get skater position.\r\n\tint x = (int)(( skx - m_min_x ) / WEATHER_CEL_SIZE );\r\n\tint z = (int)(( skz - m_min_z ) / WEATHER_CEL_SIZE );\r\n\r\n\t// Calculate area to render.\r\n\tint sx = x - RENDER_DIST;\r\n\tint ex = x + DROP_SIZE;\t//RENDER_DIST;\r\n\tint sz = z - RENDER_DIST;\r\n\tint ez = z + DROP_SIZE;\t//RENDER_DIST;\r\n\r\n\t// Clip z values.\r\n\tif ( ez < 0 ) return;\r\n\tif ( sz > ( m_height - 1 ) ) return;\r\n\r\n\t// Get Xbox format top and bottom color.\r\n\tuint32 top_color = ((uint32)m_rain_top_color.a << 24 ) | ((uint32)m_rain_top_color.r << 16 ) | ((uint32)m_rain_top_color.g << 8 ) | ((uint32)m_rain_top_color.b << 0 );\r\n\tuint32 bot_color = ((uint32)m_rain_bottom_color.a << 24 ) | ((uint32)m_rain_bottom_color.r << 16 ) | ((uint32)m_rain_bottom_color.g << 8 ) | ((uint32)m_rain_bottom_color.b << 0 );\r\n\r\n\t// Deal with FIXED_BRIGHTEN mode, which doesn't work.\r\n\tif(( m_rain_blend & NxXbox::sMaterial::BLEND_MODE_MASK ) == NxXbox::vBLEND_MODE_BRIGHTEN_FIXED )\r\n\t{\r\n\t\tset_blend_mode( NxXbox::vBLEND_MODE_BRIGHTEN );\r\n\r\n\t\ttop_color = ( top_color & 0x00FFFFFFUL ) | ( m_rain_blend & 0xFF000000UL );\r\n\t\tbot_color = ( bot_color & 0x00FFFFFFUL ) | ( m_rain_blend & 0xFF000000UL );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNxXbox::set_blend_mode( m_rain_blend );\r\n\t}\r\n\r\n\tNxXbox::set_render_state( RS_ALPHACUTOFF, 0 );\r\n\r\n\tNxXbox::set_pixel_shader( PixelShader5 );\r\n\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\r\n\tsint32 minx\t\t= (sint32)( m_min_x * SUB_INCH_PRECISION );\r\n\tsint32 minz\t\t= (sint32)( m_min_z * SUB_INCH_PRECISION );\r\n\tsint32 rlength\t= (sint32)( m_rain_length * SUB_INCH_PRECISION );\r\n\t\r\n\t// Calculate drop height list.\r\n\tint lp;\r\n\tsint32 y_off[256];\r\n\r\n\tfor( lp = ( 254 - m_rain_frames ); lp < 256; lp++ )\r\n\t{\r\n\t\ty_off[lp] = (sint32)(( m_rain_height - (((float)(( lp - 254 ) + m_rain_frames ) / (float)m_rain_frames ) * m_rain_height )) * SUB_INCH_PRECISION );\r\n\t}\r\n\r\n\t// Calculate xz offset list.\r\n\tsint32 xz_off[256];\r\n\tfor( lp = 0; lp < 256; lp++ )\r\n\t{\r\n\t\txz_off[lp] = (sint32)((((float)lp * (float)WEATHER_CEL_SIZE * SUB_INCH_PRECISION ) / 255.0f ));\r\n\t}\r\n\r\n\tint lines = 0;\r\n\r\n\tDWORD* p_push\t\t\t\t= NULL;\r\n\tDWORD* p_push_encode_fixup\t= NULL;\r\n\tuint32 dwords_written\t\t= 0;\r\n\tuint32 total_dwords_written\t= 2;\r\n\r\n\tfor ( int lzz = sz; lzz <= ez; lzz++ )\r\n\t{\r\n\t\tint zz = ( lzz < 0 ) ? 0 : ( lzz > ( m_height - 1 ) ) ? ( m_height - 1 ) : lzz;\r\n\r\n\t\tif ( mp_roof_row[zz].start == 16384 ) continue;\r\n\r\n\t\tsint32 vx = ( (sint32)sx << ( WEATHER_CEL_SIZE_SHIFT + PRECISION_SHIFT ) ) + minx;\r\n\t\tsint32 vz = ( (sint32)zz << ( WEATHER_CEL_SIZE_SHIFT + PRECISION_SHIFT ) ) + minz;\r\n\r\n\t\tint cel = mp_roof_row[zz].index + ( sx - mp_roof_row[zz].start );\r\n\r\n\t\tint drop_cel_z = ( ( zz & ( DROP_SIZE - 1 ) ) << DROP_SIZE_SHIFT );\r\n\r\n\t\tfor ( int lxx = sx; lxx <= ex; lxx++, cel++ )\r\n\t\t{\r\n\t\t\tint xx = ( lxx > mp_roof_row[zz].start ) ? ( ( lxx < mp_roof_row[zz].end ) ? lxx : mp_roof_row[zz].end ) : mp_roof_row[zz].start;\r\n\r\n\t\t\t// Get the current drop value. Skip this one if it's inactive.\r\n\t\t\tint drop_cel = drop_cel_z + ( xx & ( DROP_SIZE - 1 ) );\r\n\r\n\t\t\tvx += ( WEATHER_CEL_SIZE << PRECISION_SHIFT );\r\n\t\t\tsint32 vy = m_roof_height[mp_roof_height_index[cel]];\r\n\r\n\t\t\tfor ( int d = 0; d < DROP_LAYERS; d++, drop_cel += ( DROP_SIZE * DROP_SIZE ) )\r\n\t\t\t{\r\n\t\t\t\tif ( m_drop_time[drop_cel] == 255 )\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t// Create the position for rendering.\r\n\t\t\t\tfloat v0x = ( vx + xz_off[m_x_offset[drop_cel]] ) * ( 1.0f / (float)( 1 << PRECISION_SHIFT ));\r\n\t\t\t\tfloat v0y = ( vy + y_off[m_drop_time[drop_cel]] ) * ( 1.0f / (float)( 1 << PRECISION_SHIFT ));\r\n\t\t\t\tfloat v0z = ( vz + xz_off[m_z_offset[drop_cel]] ) * ( 1.0f / (float)( 1 << PRECISION_SHIFT ));\r\n\t\t\t\tfloat v1y = v0y + ( rlength * ( 1.0f / (float)( 1 << PRECISION_SHIFT )));\r\n\r\n\t\t\t\tif ( lines == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tlines = NUM_LINES_PER_BATCH;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Grab the push buffer if we don't have it yet.\r\n\t\t\t\tif( p_push == NULL )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Grab 32k of push buffer.\t\r\n\t\t\t\t\tp_push = D3DDevice_BeginPush( 32 * 1024 / 4 );\r\n\r\n\t\t\t\t\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t\t\t\t\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t\t\t\t\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\t\t\t\t\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\t\t\t\tp_push[1]\t= D3DPT_LINELIST;\r\n\t\t\t\t\tp_push\t\t+= 2;\r\n\r\n\t\t\t\t\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t\t\t\t\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t\t\t\t\t// As yet, we don't know how many dwords we will write, so save a pointer to the current push buffer location\r\n\t\t\t\t\t// so we can fix up this value at the end.\r\n\t\t\t\t\tp_push_encode_fixup = p_push;\r\n\t\t\t\t\t++p_push;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tp_push[0] = *((DWORD*)&v0x);\r\n\t\t\t\tp_push[1] = *((DWORD*)&v0y);\r\n\t\t\t\tp_push[2] = *((DWORD*)&v0z);\r\n\t\t\t\tp_push[3] = bot_color;\r\n\r\n\t\t\t\tp_push[4] = *((DWORD*)&v0x);\r\n\t\t\t\tp_push[5] = *((DWORD*)&v1y);\r\n\t\t\t\tp_push[6] = *((DWORD*)&v0z);\r\n\t\t\t\tp_push[7] = top_color;\r\n\r\n\t\t\t\tp_push\t\t\t\t\t+= 8;\r\n\t\t\t\tdwords_written\t\t\t+= 8;\r\n\t\t\t\ttotal_dwords_written\t+= 8;\r\n\r\n\t\t\t\t// Check for hitting the max dwords for this encode block, in which case we need to end this block\r\n\t\t\t\t// and start another one.\r\n\t\t\t\tif( dwords_written >= 2040 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Now we know exactly how many dwords written, fix-up our earlier entry.\r\n\t\t\t\t\tp_push_encode_fixup[0]\t\t= D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, dwords_written );\r\n\r\n\t\t\t\t\t// Are we approaching the end of this push buffer? If so, close it out and start a new one.\r\n\t\t\t\t\tif( total_dwords_written > 6000 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// End the push buffer.\r\n\t\t\t\t\t\ttotal_dwords_written\t= 0;\r\n\t\t\t\t\t\tp_push[0]\t\t\t\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\t\t\t\t\tp_push[1]\t\t\t\t= 0;\r\n\t\t\t\t\t\tp_push\t\t\t\t\t+= 2;\r\n\t\t\t\t\t\tD3DDevice_EndPush( p_push );\r\n\r\n\t\t\t\t\t\tp_push\t\t\t\t\t= NULL;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// As yet, we don't know how many dwords we will write, so save a pointer to the current push buffer location\r\n\t\t\t\t\t\t// so we can fix up this value at the end.\r\n\t\t\t\t\t\tp_push_encode_fixup\t\t= p_push;\r\n\t\t\t\t\t\t++p_push;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdwords_written = 0;\r\n\t\t\t\t}\r\n\t\t\t\tlines--;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif( p_push )\r\n\t{\r\n\t\t// Now we know exactly how many dwords written, fix-up our earlier entry.\r\n\t\tp_push_encode_fixup[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, dwords_written );\r\n\r\n\t\t// End the push buffer.\r\n\t\tp_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\t\tp_push[1] = 0;\r\n\t\tp_push += 2;\r\n\t\tD3DDevice_EndPush( p_push );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxWeather::plat_render_splashes( float skx, float skz )\r\n{\r\n\t// Create a new splash if required.\r\n\tfloat last = m_splash_rate;\r\n\tm_splash_rate += m_splash_per_frame;\r\n\tint new_splashes = (int)m_splash_rate - (int)last;\r\n\r\n\tif ( new_splashes )\r\n\t{\r\n\t\tCFeeler feeler;\r\n\t\tMth::Vector pos;\r\n\r\n\t\tpos[X] = NxXbox::EngineGlobals.cam_position[X];\r\n\t\tpos[Y] = FEELER_START;\r\n\t\tpos[Z] = NxXbox::EngineGlobals.cam_position[Z];\r\n\t\tpos[W] = 1.0f;\r\n\r\n\t\tMth::Vector dir;\r\n\t\tdir[X] = skx - NxXbox::EngineGlobals.cam_position[X];\r\n\t\tdir[Y] = 0.0f;\r\n\t\tdir[Z] = skz - NxXbox::EngineGlobals.cam_position[Z];\r\n\t\tdir[W] = 1.0f;\r\n\t\tdir.Normalize();\r\n\r\n\t\t// Add distance.\r\n\t\tfloat r1 = (float)Mth::Rnd( 32768 ) / 32768.0f;\r\n\t\tpos\t\t+= ( dir * ((float)WEATHER_CEL_SIZE * RENDER_DIST * r1 ));\r\n\r\n\t\t// Add lateral.\r\n\t\tMth::Vector lat( dir[Z], 0.0f, -dir[X], 1.0f );\r\n\r\n\t\tfloat r2 = 1.0f - ( (float)Mth::Rnd( 32768 ) / 32768.0f );\r\n\t\tif ( m_current_splash & 1 )\r\n\t\t{\r\n\t\t\tpos += ( lat * ( (float)WEATHER_CEL_SIZE * RENDER_DIST * r1 * r2 ) );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpos += ( lat * ( (float)WEATHER_CEL_SIZE * RENDER_DIST * r1 * -r2 ) );\r\n\t\t}\r\n\r\n\t\tfeeler.SetStart( pos );\r\n\t\tpos[Y] = -FEELER_START;\r\n\t\tfeeler.SetEnd( pos );\r\n\r\n\t\t// Get the y position.\r\n\t\tfloat y;\r\n\t\tif ( feeler.GetCollision( false, false ) )\t\t// No movables, nearest collision.\r\n\t\t{\r\n\t\t\ty = feeler.GetPoint()[Y];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ty = FEELER_START;\r\n\t\t}\r\n\r\n\t\tm_splash_x[m_current_splash]\t\t\t= pos[X];\r\n\t\tm_splash_y[m_current_splash]\t\t\t= y + 4.0f;\t// Move up slightly.\r\n\t\tm_splash_z[m_current_splash]\t\t\t= pos[Z];\r\n\t\tm_splash_current_life[m_current_splash]\t= m_splash_life;\r\n\r\n\t\tm_current_splash++;\r\n\t\tm_current_splash %= NUM_SPLASH_ACTIVE;\r\n\t}\r\n\t\r\n\t// Render the splashes.\r\n\tNxXbox::set_blend_mode( m_splash_blend );\r\n\tNxXbox::set_render_state( RS_ALPHACUTOFF, 0 );\r\n\tNxXbox::set_render_state( RS_UVADDRESSMODE0, 0x00000000UL );\r\n\tmp_rain_texture->Set( 0 );\r\n\r\n\tNxXbox::set_pixel_shader( PixelShader4 );\r\n\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2( 0 ));\r\n\r\n\tuint32 dword_count\t\t= 24 * NUM_SPLASH_ACTIVE;\r\n\tuint32 dwords_written\t= 0;\r\n\tDbg_Assert( dword_count < 2048 );\r\n\r\n\t// Obtain push buffer lock.\r\n\t// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.\r\n\tDWORD* p_push\t\t\t\t= D3DDevice_BeginPush( dword_count + 16 );\r\n\tDWORD* p_push_encode_fixup\t= NULL;\r\n\r\n\t// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be\r\n\t// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the\r\n\t// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.\r\n\tp_push[0]\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\tp_push[1]\t= D3DPT_QUADLIST;\r\n\tp_push\t\t+= 2;\r\n\r\n\t// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex\r\n\t// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.\r\n\t// As yet, we don't know how many dwords we will write, so save a pointer to the current push buffer location\r\n\t// so we can fix up this value at the end.\r\n\tp_push_encode_fixup = p_push;\r\n\t++p_push;\r\n\r\n\tfor ( int spl = 0; spl < NUM_SPLASH_ACTIVE; spl++ )\r\n\t{\r\n\t\tif( m_splash_current_life[spl] == 0 )\r\n\t\t\tcontinue;\r\n\r\n\t\t// Interpolate color (and switch to Xbox format at the same time).\r\n\t\tImage::RGBA\ticol;\r\n\t\ticol.b\t\t= (uint8)(((int)m_splash_color.r * m_splash_current_life[spl] ) / m_splash_life );\r\n\t\ticol.g\t\t= (uint8)(((int)m_splash_color.g * m_splash_current_life[spl] ) / m_splash_life );\r\n\t\ticol.r\t\t= (uint8)(((int)m_splash_color.b * m_splash_current_life[spl] ) / m_splash_life );\r\n\t\ticol.a\t\t= (uint8)(((int)m_splash_color.a * m_splash_current_life[spl] ) / m_splash_life );\r\n\r\n\t\t// Draw splashes...\r\n\t\tfloat vx0\t= m_splash_x[spl] - ( m_splash_size * 0.5f );\r\n\t\tfloat vx1\t= m_splash_x[spl] + ( m_splash_size * 0.5f );\r\n\t\tfloat vy\t= m_splash_y[spl];\r\n\t\tfloat vz0\t= m_splash_z[spl] - ( m_splash_size * 0.5f );\r\n\t\tfloat vz1\t= m_splash_z[spl] + ( m_splash_size * 0.5f );\r\n\r\n\t\tp_push[0]\t= *((DWORD*)&vx0 );\r\n\t\tp_push[1]\t= *((DWORD*)&vy );\r\n\t\tp_push[2]\t= *((DWORD*)&vz0 );\r\n\t\tp_push[3]\t= *((DWORD*)&icol );\r\n\t\tp_push[4]\t= 0x00000000UL;\r\n\t\tp_push[5]\t= 0x00000000UL;\r\n\r\n\t\tp_push[6]\t= *((DWORD*)&vx1 );\r\n\t\tp_push[7]\t= *((DWORD*)&vy );\r\n\t\tp_push[8]\t= *((DWORD*)&vz0 );\r\n\t\tp_push[9]\t= *((DWORD*)&icol );\r\n\t\tp_push[10]\t= 0x3F800000UL;\r\n\t\tp_push[11]\t= 0x00000000UL;\r\n\r\n\t\tp_push[12]\t= *((DWORD*)&vx1 );\r\n\t\tp_push[13]\t= *((DWORD*)&vy );\r\n\t\tp_push[14]\t= *((DWORD*)&vz1 );\r\n\t\tp_push[15]\t= *((DWORD*)&icol );\r\n\t\tp_push[16]\t= 0x3F800000UL;\r\n\t\tp_push[17]\t= 0x3F800000UL;\r\n\r\n\t\tp_push[18]\t= *((DWORD*)&vx0 );\r\n\t\tp_push[19]\t= *((DWORD*)&vy );\r\n\t\tp_push[20]\t= *((DWORD*)&vz1 );\r\n\t\tp_push[21]\t= *((DWORD*)&icol );\r\n\t\tp_push[22]\t= 0x00000000UL;\r\n\t\tp_push[23]\t= 0x3F800000UL;\r\n\r\n\t\tp_push\t\t\t+= 24;\r\n\t\tdwords_written\t+= 24;\r\n\t\tm_splash_current_life[spl]--;\r\n\t}\r\n\r\n\tp_push_encode_fixup[0]\t= D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, dwords_written );\r\n\tp_push[0]\t\t\t\t= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );\r\n\tp_push[1]\t\t\t\t= 0;\r\n\tD3DDevice_EndPush( p_push + 2 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxWeather::plat_render( void )\r\n{\r\n\tif ( !m_system_active ) return;\r\n\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = pSkate->GetSkater(0);\r\n\tif (!pSkater) return;\r\n\t\r\n\tfloat skx = pSkater->m_pos[X];\r\n\tfloat skz = pSkater->m_pos[Z];\r\n\r\n\tif ( m_raining )\r\n\t{\r\n\t\tplat_render_splashes( skx, skz );\r\n\t\tplat_render_rain( skx, skz );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tplat_render_snow( skx, skz );\r\n\t}\r\n\r\n\t// Increment rain drop/snow flake positions.\r\n\tif ( m_active_drops )\r\n\t{\r\n\t\tfor ( int lp = 0; lp < ( DROP_SIZE * DROP_SIZE * DROP_LAYERS ); lp++ )\r\n\t\t{\r\n\t\t\tswitch ( m_drop_time[lp] )\r\n\t\t\t{\r\n\t\t\t\tcase 255:\r\n\t\t\t\t\t// Inactive.\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 254:\r\n\t\t\t\t\t// About to become inactive, so decrement active drops.\r\n\t\t\t\t\tm_active_drops--;\r\n\t\t\t\t\t// Deliberately falls through...\r\n\t\t\t\tdefault:\r\n\t\t\t\t\t// Increment time.\r\n\t\t\t\t\tm_drop_time[lp]++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxWeather::plat_set_rain_blend_mode( uint32 blendmode_checksum, int fix )\r\n{\r\n\tm_rain_blend = NxXbox::GetBlendMode( blendmode_checksum ) | ((uint32)fix << 24 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxWeather::plat_set_splash_blend_mode( uint32 blendmode_checksum, int fix )\r\n{\r\n\tm_splash_blend = NxXbox::GetBlendMode( blendmode_checksum ) | ((uint32)fix << 24 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxWeather::plat_set_snow_blend_mode( uint32 blendmode_checksum, int fix )\r\n{\r\n\tm_snow_blend = NxXbox::GetBlendMode( blendmode_checksum ) | ((uint32)fix << 24 );\r\n}\r\n\r\n} // Nx\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/XBox/p_nxweather.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_NxWeather.h\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  6/19/2003\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_WEATHER_H__\r\n#define\t__GFX_P_NX_WEATHER_H__\r\n    \r\n#include \"gfx/nxweather.h\"\r\n\r\nnamespace Nx\r\n{\r\n\r\n#define SUB_INCH_PRECISION\t\t16.0f\r\n#define WEATHER_CEL_SIZE\t\t128\r\n#define WEATHER_CEL_SIZE_SHIFT\t7\r\n#define HEIGHT_TOLERANCE\t\t(sint32)( 30.0f * SUB_INCH_PRECISION )\r\n#define DROP_SIZE\t\t\t\t16\r\n#define DROP_SIZE_SHIFT\t\t\t4\r\n#define DROP_LAYERS\t\t\t\t4\r\n#define NUM_SPLASH_ACTIVE\t\t32\r\n\r\ntypedef struct\r\n{\r\n\tunsigned short start;\r\n\tunsigned short end;\r\n\tunsigned short index;\r\n}\r\nsRowEntry;\r\n\r\nclass CXboxWeather : public CWeather\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCXboxWeather();\r\n\tvirtual \t\t\t\t~CXboxWeather();\r\n\r\nprivate:\t\t\t\t\t// It's all private, as it is machine specific\r\n\tvoid\t\t\t\t\tplat_update_grid( void );\r\n\tvirtual void\t\t\tplat_process( float delta_time );\r\n\tvirtual void\t\t\tplat_render( void );\r\n\tvoid\t\t\t\t\tplat_set_rain_blend_mode( uint32 blendmode_checksum, int fix );\r\n\tvoid\t\t\t\t\tplat_set_splash_blend_mode( uint32 blendmode_checksum, int fix );\r\n\tvoid\t\t\t\t\tplat_set_snow_blend_mode( uint32 blendmode_checksum, int fix );\r\n\r\n\tvoid\t\t\t\t\tplat_render_splashes( float skx, float skz );\r\n\tvoid\t\t\t\t\tplat_render_rain( float skx, float skz );\r\n\tvoid\t\t\t\t\tplat_render_snow( float skx, float skz );\r\n\r\n\tNxXbox::sTexture*\t\tmp_rain_texture;\r\n\tNxXbox::sTexture*\t\tmp_snow_texture;\r\n\r\n\tunsigned char *\t\t\tmp_roof_height_index;\r\n\tsRowEntry *\t\t\t\tmp_roof_row;\r\n\tsint32\t\t\t\t\tm_roof_height[256];\r\n\tint\t\t\t\t\t\tm_width;\r\n\tint\t\t\t\t\t\tm_height;\r\n\r\n\tfloat\t\t\t\t\tm_min_x;\r\n\tfloat\t\t\t\t\tm_min_z;\r\n\r\n\tfloat\t\t\t\t\tm_rain_rate;\r\n\tfloat\t\t\t\t\tm_splash_rate;\r\n\tfloat\t\t\t\t\tm_snow_rate;\r\n\r\n\tMth::Vector\t\t\t\tm_grid_base;\r\n\r\n\tunsigned char\t\t\tm_drop_time[DROP_SIZE*DROP_SIZE*DROP_LAYERS];\r\n\tunsigned char\t\t\tm_x_offset[DROP_SIZE*DROP_SIZE*DROP_LAYERS];\r\n\tunsigned char\t\t\tm_z_offset[DROP_SIZE*DROP_SIZE*DROP_LAYERS];\r\n\r\n\tuint32\t\t\t\t\tm_seq;\r\n\r\n\tuint32\t\t\t\t\tm_rain_blend;\r\n\tuint32\t\t\t\t\tm_splash_blend;\r\n\tuint32\t\t\t\t\tm_snow_blend;\r\n\r\n\tfloat\t\t\t\t\tm_splash_x[NUM_SPLASH_ACTIVE];\r\n\tfloat\t\t\t\t\tm_splash_y[NUM_SPLASH_ACTIVE];\r\n\tfloat\t\t\t\t\tm_splash_z[NUM_SPLASH_ACTIVE];\r\n\tint\t\t\t\t\t\tm_splash_current_life[NUM_SPLASH_ACTIVE]; \r\n\tint\t\t\t\t\t\tm_current_splash;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // Nx\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/baseanimcontroller.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       BaseAnimController.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/06/2003\r\n//****************************************************************************\r\n\r\n#include <gfx/baseanimcontroller.h>\r\n\r\n#include <gel/components/skeletoncomponent.h>\r\n#include <gel/object/compositeobject.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\t\t\t\t\t\t\t \r\n#include <gfx/blendchannel.h>\r\n#include <gfx/skeleton.h>\r\n\t\t\t\t\t\t  \r\nnamespace Gfx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseAnimController::CBaseAnimController( CBlendChannel* pBlendChannel ) : mp_blendChannel( pBlendChannel )\r\n{\r\n\tm_name = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseAnimController::~CBaseAnimController()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBaseAnimController::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tpParams->GetChecksum( CRCD(0x40c698af,\"id\"), &m_name, Script::NO_ASSERT );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBaseAnimController::Update()\r\n{\r\n\tDbg_Assert( 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBaseAnimController::GetPose( Gfx::CPose* pResultPose )\r\n{\r\n\t// not handled\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBaseAnimController::GetDebugInfo( Script::CStruct* p_info )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nEAnimFunctionResult CBaseAnimController::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\treturn AF_NOT_EXECUTED;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CCompositeObject* CBaseAnimController::GetObject()\r\n{\r\n\treturn mp_blendChannel->GetObject();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGfx::CSkeleton* CBaseAnimController::GetSkeleton()\r\n{\r\n\tObj::CSkeletonComponent* pSkeletonComponent = GetSkeletonComponentFromObject( GetObject() );\r\n\tif ( pSkeletonComponent )\r\n\t{\r\n\t\treturn pSkeletonComponent->GetSkeleton();\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gfx/baseanimcontroller.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       BaseAnimController.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/6/2003\r\n//****************************************************************************\r\n\r\n#ifndef __GFX_BASEANIMCONTROLLER_H__\r\n#define __GFX_BASEANIMCONTROLLER_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n// for procedural bones, which will be moved to another file...\r\n#include <core/math.h>\r\n\r\nnamespace Obj\r\n{\r\n\tclass CCompositeObject;\r\n}\r\n\t\t\t\t\r\nnamespace Script\r\n{\r\n\tclass CScript;\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Gfx\r\n{\r\n\tclass CBlendChannel;\r\n\tclass CPose;\r\n\tclass CSkeleton;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// (If the order of these change, then please also\r\n// change Obj::CBaseComponent::EMemberFunctionResult)\r\nenum EAnimFunctionResult\r\n{\r\n\tAF_FALSE \t\t= 0,\r\n\tAF_TRUE  \t\t= 1,\r\n\tAF_NOT_EXECUTED = 2\r\n};\r\n\r\n// maybe anim controllers should subclass from Obj::CBaseComponent\r\n// so that they can access to the same CallMemberFunction interface?\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// TODO:  Move this to some generic animcontrollertypes.h\r\n\r\nstruct SWobbleDetails\r\n{\r\n    float\t\t\t\twobbleAmpA;\r\n    float\t\t\t\twobbleAmpB;\r\n    float\t\t\t\twobbleK1;\r\n    float\t\t\t\twobbleK2;\r\n    float\t\t\t\tspazFactor;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// TODO:  Move this to some generic procanim.h\r\n\r\nclass CProceduralBone\r\n{\r\npublic:\r\n\tCProceduralBone()\r\n\t{\r\n\t\tm_name = 0;\r\n\t}\r\n\r\npublic:\r\n\tuint32\t\t\t\t\tm_name;\r\n\t\r\n\tbool\t\t\t\t\ttransEnabled;\r\n\tMth::Vector\t\t\t\ttrans0;\r\n\tMth::Vector\t\t\t\ttrans1;\r\n\tMth::Vector\t\t\t\tdeltaTrans;\r\n\tMth::Vector\t\t\t\tcurrentTrans;\r\n\t\r\n\tbool\t\t\t\t\trotEnabled;\r\n\tMth::Vector\t\t\t\trot0;\r\n\tMth::Vector\t\t\t\trot1;\r\n\tMth::Vector\t\t\t\tdeltaRot;\r\n\tMth::Vector\t\t\t\tcurrentRot;\r\n\t\r\n\tbool\t\t\t\t\tscaleEnabled;\r\n\tMth::Vector\t\t\t\tscale0;\r\n\tMth::Vector\t\t\t\tscale1;\r\n\tMth::Vector\t\t\t\tdeltaScale;\r\n\tMth::Vector\t\t\t\tcurrentScale;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass CBaseAnimController : public Spt::Class\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCBaseAnimController( CBlendChannel* pBlendChannel );\r\n\tvirtual \t\t\t\t\t~CBaseAnimController();\r\n\r\n\tvirtual bool\t\t\t\tGetPose( Gfx::CPose* pResultPose );\r\n\tvirtual void\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n    virtual EAnimFunctionResult CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\npublic:\r\n\tvirtual void \t\t\t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void \t\t\t\tUpdate();\r\n\r\n\tint\t\t\t\t\t\t\tGetPriority() const\r\n\t{\r\n\t\treturn m_priority;\r\n\t}\r\n\r\n\tvoid\t\t\t\t\t\tSetPriority( int priority )\r\n\t{\r\n\t\tm_priority = priority;\r\n\t}\r\n\r\n\tuint32\t\t\t\t\t\tGetID() const\r\n\t{\r\n\t\treturn m_name;\r\n\t}\r\n\r\nprotected:\r\n\tObj::CCompositeObject*\t\tGetObject();\r\n\tGfx::CSkeleton*\t\t\t\tGetSkeleton();\r\n\r\nprotected:\r\n\tCBlendChannel*\t\t\t\tmp_blendChannel;\r\n\tObj::CCompositeObject*\t\tmp_object;\r\n\tint\t\t\t\t\t\t\tm_priority;\r\n\tuint32\t\t\t\t\t\tm_name;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/bbox.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics (GFX)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tbbox.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t02/01/00\t-\tmjb\t(actualy Matt's now)\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tsome functions for line/box intersection\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <gfx/bbox.h>\r\n#include <core/math/vector.h>\r\n#include <core/math/vector.inl>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Gfx\r\n{\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool PointInsideBox( const Mth::Vector &point, const Mth::Vector &boxMax, const Mth::Vector &boxMin )\r\n{\r\n\t\r\n\tif ( point[ X ] > boxMax[ X ] )\r\n\t\treturn ( false );\r\n\tif ( point[ Y ] > boxMax[ Y ] )\r\n\t\treturn ( false );\r\n\tif ( point[ Z ] > boxMax[ Z ] )\r\n\t\treturn ( false );\r\n\tif ( point[ X ] < boxMin[ X ] )\r\n\t\treturn ( false );\r\n\tif ( point[ Y ] < boxMin[ Y ] )\r\n\t\treturn ( false );\r\n\tif ( point[ Z ] < boxMin[ Z ] )\r\n\t\treturn ( false );\r\n\t\r\n\treturn ( true );\r\n}// end of PointInsideBox( )\r\n\r\n\r\n// Checks whether pStart-pEnd collides with the axis-aligned bounding box defined by\r\n// pMax and pMin.\r\nbool LineCollidesWithBox( const Mth::Vector &pStart, const Mth::Vector &pEnd, const Mth::Vector &pMax, const Mth::Vector &pMin )\r\n{\r\n\t\r\n\r\n\t// if either point is in the box... that counts!\r\n\tif ( PointInsideBox( pStart, pMax, pMin ) ||\r\n\t\tPointInsideBox( pEnd, pMax, pMin ) )\r\n\t{\r\n\t\treturn ( true );\r\n\t}\r\n\r\n\t// Trivial rejection.\r\n\tif((pStart[ Y ]>pMax[ Y ])&&( pEnd[ Y ]>pMax[ Y ])) return false;\r\n\tif((pStart[ Y ]<pMin[ Y ])&&( pEnd[ Y ]<pMin[ Y ])) return false;\r\n\tif((pStart[ X ]>pMax[ X ])&&( pEnd[ X ]>pMax[ X ])) return false;\r\n\tif((pStart[ X ]<pMin[ X ])&&( pEnd[ X ]<pMin[ X ])) return false;\r\n\tif((pStart[ Z ]>pMax[ Z ])&&( pEnd[ Z ]>pMax[ Z ])) return false;\r\n\tif((pStart[ Z ]<pMin[ Z ])&&( pEnd[ Z ]<pMin[ Z ])) return false;\r\n\r\n\tfloat dx=pEnd[ X ]-pStart[ X ];\r\n\tfloat dy=pEnd[ Y ]-pStart[ Y ];\r\n\tfloat dz=pEnd[ Z ]-pStart[ Z ];\r\n\t\r\n\t// avoid divide by zeros.\r\n\tif ( !dx )\r\n\t{\r\n\t\tdx = ( 0.000001 );\r\n\t}\r\n\tif ( !dy )\r\n\t{\r\n\t\tdy = ( 0.000001 );\r\n\t}\r\n\tif ( !dz )\r\n\t{\r\n\t\tdz = ( 0.000001 );\r\n\t}\r\n\r\n\t// Check the max-x face.\r\n\tif (pStart[ X ]>pMax[ X ] && pEnd[ X ]<pMax[ X ])\r\n\t{\r\n\t\t// It crosses the plane of the face, so calculate the y & z coords\r\n\t\t// of the intersection and see if they are in the face,\r\n\t\tfloat d=pMax[ X ]-pStart[ X ];\r\n\t\tfloat y=d*dy/dx+pStart[ Y ];\r\n\t\tfloat z=d*dz/dx+pStart[ Z ];\r\n\t\tif (y<pMax[ Y ] && y>pMin[ Y ] && z<pMax[ Z ] && z>pMin[ Z ])\r\n\t\t{\r\n\t\t\t// It does collide!\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Check the min-x face.\r\n\tif (pStart[ X ]<pMin[ X ] && pEnd[ X ]>pMin[ X ])\r\n\t{\r\n\t\t// It crosses the plane of the face, so calculate the y & z coords\r\n\t\t// of the intersection and see if they are in the face,\r\n\t\tfloat d=pMin[ X ]-pStart[ X ];\r\n\t\tfloat y=d*dy/dx+pStart[ Y ];\r\n\t\tfloat z=d*dz/dx+pStart[ Z ];\r\n\t\tif (y<pMax[ Y ] && y>pMin[ Y ] && z<pMax[ Z ] && z>pMin[ Z ])\r\n\t\t{\r\n\t\t\t// It does collide!\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Check the max-y face.\r\n\tif (pStart[ Y ]>pMax[ Y ] && pEnd[ Y ]<pMax[ Y ])\r\n\t{\r\n\t\t// It crosses the plane of the face, so calculate the x & z coords\r\n\t\t// of the intersection and see if they are in the face,\r\n\t\tfloat d=pMax[ Y ]-pStart[ Y ];\r\n\t\tfloat x=d*dx/dy+pStart[ X ];\r\n\t\tfloat z=d*dz/dy+pStart[ Z ];\r\n\t\tif (x<pMax[ X ] && x>pMin[ X ] && z<pMax[ Z ] && z>pMin[ Z ])\r\n\t\t{\r\n\t\t\t// It does collide!\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Check the min-y face.\r\n\tif (pStart[ Y ]<pMin[ Y ] && pEnd[ Y ]>pMin[ Y ])\r\n\t{\r\n\t\t// It crosses the plane of the face, so calculate the x & z coords\r\n\t\t// of the intersection and see if they are in the face,\r\n\t\tfloat d=pMin[ Y ]-pStart[ Y ];\r\n\t\tfloat x=d*dx/dy+pStart[ X ];\r\n\t\tfloat z=d*dz/dy+pStart[ Z ];\r\n\t\tif (x<pMax[ X ] && x>pMin[ X ] && z<pMax[ Z ] && z>pMin[ Z ])\r\n\t\t{\r\n\t\t\t// It does collide!\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Check the max-z face.\r\n\tif (pStart[ Z ]>pMax[ Z ] && pEnd[ Z ]<pMax[ Z ])\r\n\t{\r\n\t\t// It crosses the plane of the face, so calculate the x & y coords\r\n\t\t// of the intersection and see if they are in the face,\r\n\t\tfloat d=pMax[ Z ]-pStart[ Z ];\r\n\t\tfloat x=d*dx/dz+pStart[ X ];\r\n\t\tfloat y=d*dy/dz+pStart[ Y ];\r\n\t\tif (x<pMax[ X ] && x>pMin[ X ] && y<pMax[ Y ] && y>pMin[ Y ])\r\n\t\t{\r\n\t\t\t// It does collide!\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t// Check the min-z face.\r\n\tif (pStart[ Z ]<pMin[ Z ] && pEnd[ Z ]>pMin[ Z ])\r\n\t{\r\n\t\t// It crosses the plane of the face, so calculate the x & y coords\r\n\t\t// of the intersection and see if they are in the face,\r\n\t\tfloat d=pMin[ Z ]-pStart[ Z ];\r\n\t\tfloat x=d*dx/dz+pStart[ X ];\r\n\t\tfloat y=d*dy/dz+pStart[ Y ];\r\n\t\tif (x<pMax[ X ] && x>pMin[ X ] && y<pMax[ Y ] && y>pMin[ Y ])\r\n\t\t{\r\n\t\t\t// It does collide!\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n} // namespace Gfx\r\n"
  },
  {
    "path": "Code/Gfx/bbox.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics  (GFX)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgfx/bbox.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t06/22/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_BBOX_H\r\n#define __GFX_BBOX_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/support.h>\r\n#include <core/math/vector.h>\r\n\r\n#ifdef __PLAT_NGC__\r\n#include \"sys/ngc/p_camera.h\"\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\nbool PointInsideBox( const Mth::Vector &point, const Mth::Vector &boxMax, const Mth::Vector &boxMin );\r\nbool LineCollidesWithBox( const Mth::Vector &pStart, const Mth::Vector &pEnd, const Mth::Vector &pMax, const Mth::Vector &pMin );\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n#endif\t// __GFX_BBOX_H\r\n"
  },
  {
    "path": "Code/Gfx/blendchannel.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       BlendChannel.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/12/2002\r\n//****************************************************************************\r\n\r\n#include <gfx/blendchannel.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n\r\n#include <gel/components/animationcomponent.h>\r\n\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n\t\t\t\t\t\t\t \r\n#include <gfx/baseanimcontroller.h>\r\n#include <gfx/bonedanim.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxanimcache.h>\r\n#include <gfx/pose.h>\r\n#include <gfx/skeleton.h>\r\n#include <gfx/subanimcontroller.h>\r\n\r\n#include <sys/timer.h>\r\n\t\t\t\t  \r\nnamespace Gfx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBlendChannel::CBlendChannel( Obj::CCompositeObject* pCompositeObject )\r\n{\r\n\tm_numControllers = 0;\r\n\r\n\t// immediately starts active when it's created\r\n\tm_status = ANIM_STATUS_ACTIVE;\r\n\r\n\tmp_object = pCompositeObject;\r\n\tDbg_MsgAssert( mp_object, ( \"Blend channel has no object\" ) );\r\n}\r\n\r\n// how to handle conflicts between controllers?\r\n// you should really only have either the boned anim or the wobble controller\r\n// maybe each item should have its own local time...\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBlendChannel::~CBlendChannel()\r\n{\r\n\tremove_controllers();\r\n\r\n\t// wipe out any old keys\r\n\tdelete_custom_keys();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseAnimController* CBlendChannel::AddController( Script::CStruct* pParams )\r\n{\r\n\tuint32 type;\r\n\tpParams->GetChecksum( CRCD(0x7321a8d6,\"type\"), &type, Script::ASSERT );\r\n\r\n\tCBaseAnimController* pController = NULL;\r\n\r\n\tint priority = 500;\r\n\r\n\tswitch ( type )\r\n\t{\r\n\t\tcase 0xcb4533ff:\t// bonedanim\r\n\t\t\t{\r\n\t\t\t\tpController = new CBonedAnimController( this );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0xd079853e:\t// ik\r\n\t\t\t{\r\n\t\t\t\tpController = new CIKController( this );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0x6d941203:\t// wobble\r\n\t\t\t{\r\n\t\t\t\tpController = new CWobbleController( this );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t\t\t \r\n\t\tcase 0xcfc5b380:\t// pose\r\n\t\t\t{\r\n\t\t\t\tpController = new CPoseController( this );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0xfdf0436c:\t// proceduralanim\r\n\t\t\t{\r\n\t\t\t\tpController = new CProceduralAnimController( this );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase 0xdf5c091a:\t// fliprotate\r\n\t\t\t{\r\n\t\t\t\tpController = new CFlipRotateController( this );\r\n\t\t\t\t\r\n\t\t\t\t// make it be processed later\r\n\t\t\t\t// (so that partial anims can take effect of flipping)\r\n\t\t\t\tpriority = 100;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\r\n\t\tcase 0x26205db6:\t// lookat\r\n\t\t\t{\r\n\t\t\t\tpController = new CLookAtController( this );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase 0x659bf355:\t// partialanim\r\n\t\t\t{\r\n\t\t\t\tpController = new CPartialAnimController( this );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"Unrecognized controller %s\", Script::FindChecksumName(type) ) );\r\n\t\t\t}\r\n\t}\r\n\r\n\t// override priority, if necessary\r\n\tpParams->GetInteger( CRCD(0x9d5923d8,\"priority\"), &priority, Script::NO_ASSERT );\r\n\r\n\tDbg_MsgAssert( pController, ( \"No controller\" ) );\r\n\tpController->InitFromStructure( pParams );\r\n\tpController->SetPriority( priority );\r\n\tadd_controller( pController, priority );\r\n\r\n\treturn pController;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBlendChannel::add_controller( CBaseAnimController* pAnimController, int priority )\r\n{\r\n\tDbg_MsgAssert( m_numControllers < vMAX_CONTROLLERS, ( \"Too many controllers for this channel on %s\", Script::FindChecksumName( GetObject()->GetID() ) ) );\t\r\n\tDbg_MsgAssert( pAnimController, ( \"No controller\" ) );\r\n\t\t\r\n\tint i = 0;\r\n\tfor ( i = 0; i < m_numControllers; i++ )\r\n\t{\r\n\t\tif ( priority > mp_controllers[i]->GetPriority() )\r\n\t\t{\r\n\t\t\t// shift all of them\r\n\t\t\tfor ( int j = m_numControllers; j > i; j-- )\r\n\t\t\t{\r\n\t\t\t\tmp_controllers[j] = mp_controllers[j - 1];\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tmp_controllers[i] = pAnimController;\r\n\tm_numControllers++;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBlendChannel::remove_controllers()\r\n{\r\n\tfor ( int i = 0; i < m_numControllers; i++ )\r\n\t{\r\n\t\tdelete mp_controllers[i];\r\n\t\tmp_controllers[i] = NULL;\r\n\t}\r\n\r\n\tm_numControllers = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBlendChannel::remove_controller( CBaseAnimController* pAnimController )\r\n{\r\n\t// TODO:  Should make sure that high-level\r\n\t// function is not currently traversing the list...\r\n\t\r\n\tfor ( int i = 0; i < m_numControllers; i++ )\r\n\t{\r\n\t\tif ( pAnimController == mp_controllers[i] )\r\n\t\t{\r\n\t\t\tdelete mp_controllers[i];\r\n\t\t\tmp_controllers[i] = NULL;\r\n\r\n\t\t\t// shift the rest of them\r\n\t\t\tfor ( int j = i; j < m_numControllers - 1; j++ )\r\n\t\t\t{\r\n\t\t\t\tmp_controllers[j] = mp_controllers[j + 1];\r\n\t\t\t}\r\n\r\n\t\t\tm_numControllers--;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseAnimController* CBlendChannel::get_controller_by_id( uint32 id )\r\n{\r\n\tfor ( int i = 0; i < m_numControllers; i++ )\r\n\t{\r\n\t\tif ( mp_controllers[i]->GetID() == id )\r\n\t\t{\r\n\t\t\treturn mp_controllers[i];\r\n\t\t}\r\n\t}\r\n\r\n\t// not found\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBlendChannel::Update()\r\n{\r\n\t// reset the anim complete field for this frame\r\n\tm_animComplete = false;\r\n\r\n\tif ( GetStatus() == ANIM_STATUS_DEGENERATING )\r\n\t{\r\n\t\tm_degenerationTime -= ( m_blendSpeed * Tmr::FrameRatio() );\r\n\t\tif ( m_degenerationTime <= 0.0f )\r\n\t\t{\t\t\t\t\t\t\t\t    \r\n\t\t\t// This animation is no longer active.\r\n\t\t\tSetStatus( ANIM_STATUS_INACTIVE );\r\n\t\t}\r\n\t\telse if ( ( m_degenerationTime * m_degenerationTimeToBlendMultiplier ) < 0.0f )\r\n\t\t{\r\n\t\t\t// Check for being too small to care about.\r\n\t\t\tSetStatus( ANIM_STATUS_INACTIVE ); \r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// don't really need to do this any more, because\r\n\t\t// the update happens in the CBonedAnimController...\r\n\t\t//\t\tCAnimChannel::Update();\r\n\t}\r\n\t\r\n\tif ( GetStatus() == ANIM_STATUS_ACTIVE )\r\n\t{\r\n\t\tfor ( int i = 0; i < m_numControllers; i++ )\r\n\t\t{\r\n\t\t\t// one of these update functions should set the correct m_time for this frame\r\n\t\t\tmp_controllers[i]->Update();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBlendChannel::GetPose( Gfx::CPose* pResultPose )\r\n{\r\n\tfor ( int i = 0; i < m_numControllers; i++ )\r\n\t{\r\n\t\tmp_controllers[i]->GetPose( pResultPose );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBlendChannel::Degenerate( float blend_period )\r\n{\r\n\tif ( blend_period == 0.0f )\r\n\t{\r\n\t\t// no point in degenerating it\r\n\t\t// so consider it \"done\"\r\n\t\tSetStatus( ANIM_STATUS_INACTIVE );\r\n\t}\r\n\r\n\t// only degenerate if it's active\r\n\tif( GetStatus() == ANIM_STATUS_ACTIVE )\r\n\t{\r\n\t\tSetStatus( ANIM_STATUS_DEGENERATING );\r\n\t\tm_degenerationTime = blend_period;\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CBlendChannel::GetBlendValue()\r\n{\r\n\tEAnimStatus theStatus = GetStatus();\r\n\r\n\tswitch ( theStatus )\r\n\t{\r\n\t\tcase ANIM_STATUS_ACTIVE:\r\n\t\t\treturn 1.0f;\r\n\t\tcase ANIM_STATUS_INACTIVE:\r\n\t\t\treturn 0.0f;\r\n\t\tcase ANIM_STATUS_DEGENERATING:\r\n\t\t\treturn m_degenerationTime * m_degenerationTimeToBlendMultiplier;\r\n\t\tdefault:\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t\treturn 0.0f;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBlendChannel::GetDebugInfo( Script::CStruct* p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tCAnimChannel::GetDebugInfo( p_info );\r\n\t\r\n\tfor ( int i = 0; i < m_numControllers; i++ )\r\n\t{\r\n\t\tmp_controllers[i]->GetDebugInfo( p_info );\r\n\t}\r\n\r\n\tp_info->AddFloat( CRCD(0x98146e11,\"m_degenerationTime\"), m_degenerationTime );\r\n\tp_info->AddFloat( CRCD(0x0897053d,\"m_degenerationTimeToBlendMultiplier\"), m_degenerationTimeToBlendMultiplier );\r\n\t\r\n\tuint32 status_checksum = 0;\r\n\tswitch ( m_status )\r\n\t{\r\n\t\tcase ANIM_STATUS_INACTIVE:\r\n\t\t\tstatus_checksum = CRCD(0xbc4202a3,\"ANIM_STATUS_INACTIVE\");\r\n\t\t\tbreak;\r\n\t\tcase ANIM_STATUS_DEGENERATING:\r\n\t\t\tstatus_checksum = CRCD(0x5071e935,\"ANIM_STATUS_DEGENERATING\");\r\n\t\t\tbreak;\r\n\t\tcase ANIM_STATUS_ACTIVE:\r\n\t\t\tstatus_checksum = CRCD(0x7009388b,\"ANIM_STATUS_ACTIVE\");\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Unknown status found in CBlendChannel::GetDebugInfo.  Was the enum changed?\" ) );\r\n\t\t\tbreak;\r\n\t}\r\n\tp_info->AddChecksum( CRCD(0xce6cc81d,\"m_status\"), status_checksum );\r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBlendChannel::Reset()\r\n{\r\n\tCAnimChannel::Reset();\r\n\r\n    m_status\t\t\t\t\t\t\t\t\t= ANIM_STATUS_INACTIVE;\r\n\r\n\tm_degenerationTime\t\t\t\t\t\t    = 0.0f;\r\n\tm_degenerationTimeToBlendMultiplier\t        = 0.0f;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBlendChannel::InvalidateCache()\r\n{\r\n\tfor ( int i = 0; i < m_numControllers; i++ )\r\n\t{\r\n\t\tmp_controllers[i]->CallMemberFunction( CRCD(0x5f495ae0,\"InvalidateCache\"), NULL, NULL );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nEAnimStatus CBlendChannel::GetStatus() const\r\n{\r\n\treturn m_status;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBlendChannel::SetStatus( EAnimStatus status )\r\n{\r\n\tm_status = status;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBlendChannel::IsActive()\r\n{\r\n\treturn ( GetStatus() != Gfx::ANIM_STATUS_INACTIVE );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBlendChannel::IsDegenerating()\r\n{\r\n\treturn ( GetStatus() == Gfx::ANIM_STATUS_DEGENERATING );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBlendChannel::PlaySequence( uint32 anim_name, float start_time, float end_time, EAnimLoopingType loop_type, float blend_period, float speed, bool flipped )\r\n{\r\n\t// clear out any old custom keys, and add the new ones\r\n\tdelete_custom_keys();\r\n\tadd_custom_keys( anim_name );\r\n\t\r\n\tm_status = ANIM_STATUS_ACTIVE;\r\n\t\r\n\tm_blendSpeed = speed / 60.0f;\r\n\r\n\tScript::CStruct* pTempParams = NULL;\r\n\t \r\n\tif ( loop_type == Gfx::LOOPING_WOBBLE )\r\n\t{\r\n\t\tpTempParams = new Script::CStruct;\r\n\t\tpTempParams->AddChecksum( CRCD(0x7321a8d6,\"type\"), CRCD(0x6d941203,\"wobble\") );\r\n\t\tthis->AddController( pTempParams );\r\n\t\tdelete pTempParams;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpTempParams= new Script::CStruct;\r\n\t\tpTempParams->AddChecksum( CRCD(0x7321a8d6,\"type\"), CRCD(0xcb4533ff,\"bonedanim\") );\r\n\t\tthis->AddController( pTempParams );\r\n\t\tdelete pTempParams;\r\n\t}\r\n\r\n\tpTempParams= new Script::CStruct;\r\n\tpTempParams->AddChecksum( CRCD(0x7321a8d6,\"type\"), CRCD(0xdf5c091a,\"fliprotate\") );\r\n    pTempParams->AddInteger( \"flipped\", flipped );\r\n\tthis->AddController( pTempParams );\r\n\tdelete pTempParams;\r\n\r\n#if 0\r\n\t// if it's the skater, then add a procedural anim controller\r\n\tif ( GetObject()->GetID() == 0 )\r\n\t{\r\n\t\tpTempParams = new Script::CStruct;\r\n\t\tpTempParams->AddChecksum( CRCD(0x7321a8d6,\"type\"), CRCD(0xfdf0436c,\"proceduralanim\") );\r\n\t\tthis->AddController( pTempParams );\r\n\t\tdelete pTempParams;\r\n\t}\r\n#endif\r\n\t\r\n#if 0\r\n\t// if it's the skater, then add a partial anim controller\r\n\tif ( GetObject()->GetID() == 0 )\r\n\t{\r\n\t\tpTempParams = new Script::CStruct;\r\n\t\tpTempParams->AddChecksum( CRCD(0x7321a8d6,\"type\"), CRCD(0x659bf355,\"partialanim\") );\r\n\t\tpTempParams->AddChecksum( CRCD(0x6c2bfb7f,\"animname\"), Script::GenerateCRC(\"Taunt1\") );\r\n\t\tpTempParams->AddFloat( CRCD(0xd16b61e6,\"starttime\"), 0.0f );\r\n\t\tpTempParams->AddFloat( CRCD(0xab81bb3d,\"endtime\"), 1.0f );\r\n\t\tpTempParams->AddInteger( CRCD(0xcd8d7c1b,\"looptype\"), Gfx::LOOPING_CYCLE );\r\n\t\tpTempParams->AddFloat( CRCD(0x8f0d24ed,\"blendperiod\"), 0.0f );\r\n\t\tpTempParams->AddFloat( CRCD(0xf0d90109,\"speed\"), 1.0f );\r\n\t\tthis->AddController( pTempParams );\r\n\t\tdelete pTempParams;\r\n\t}\r\n#endif\r\n\r\n\tpTempParams = new Script::CStruct;\r\n\tpTempParams->AddFloat( CRCD(0x4d747fa0,\"wobbleTargetAlpha\"), 0.0f );\r\n\tfor ( int i = 0; i < m_numControllers; i++ )\r\n\t{\r\n\t\tmp_controllers[i]->CallMemberFunction( CRCD(0xd0209498,\"setWobbleTarget\"), pTempParams, NULL );\r\n\t}\r\n\tdelete pTempParams;\r\n\r\n\tpTempParams = new Script::CStruct;\r\n\tpTempParams->AddChecksum( CRCD(0x6c2bfb7f,\"animname\"), anim_name );\r\n\tpTempParams->AddFloat( CRCD(0xd16b61e6,\"starttime\"), start_time );\r\n\tpTempParams->AddFloat( CRCD(0xab81bb3d,\"endtime\"), end_time );\r\n\tpTempParams->AddInteger( CRCD(0xcd8d7c1b,\"looptype\"), loop_type );\r\n\tpTempParams->AddFloat( CRCD(0x8f0d24ed,\"blendperiod\"), blend_period );\r\n\tpTempParams->AddFloat( CRCD(0xf0d90109,\"speed\"), speed );\r\n\tfor ( int i = 0; i < m_numControllers; i++ )\r\n\t{\r\n\t\tmp_controllers[i]->CallMemberFunction( CRCD(0xaf2fae19,\"PlaySequence\"), pTempParams, NULL );\r\n\t}\r\n\tdelete pTempParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBlendChannel::delete_custom_keys()\r\n{\r\n\tm_customAnimKeyList.DestroyAllNodes();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBlendChannel::add_custom_keys( uint32 animName )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tif ( !pAnimationComponent )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tuint32 animEventTableName = pAnimationComponent->GetAnimEventTableName();\r\n\tif ( !animEventTableName )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tScript::CStruct* pAnimEventTable = Script::GetStructure( animEventTableName, Script::ASSERT );\r\n\tif ( pAnimEventTable )\r\n\t{\r\n\t\tScript::CArray* pSubArray;\r\n\t\tif ( pAnimEventTable->GetArray( animName, &pSubArray, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tfor ( uint32 i = 0; i < pSubArray->GetSize(); i++ )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pSubStruct;\r\n\t\t\t\tpSubStruct = pSubArray->GetStructure( i );\r\n    \r\n\t\t\t\tint frame = 0;\r\n\t\t\t\t// if the frame is not specified, then look for a time value\r\n\t\t\t\tif ( !pSubStruct->GetInteger( CRCD(0x4a07c332,\"frame\"), &frame, Script::NO_ASSERT ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tfloat keyTime = 0.0f;\r\n\t\t\t\t\t\tpSubStruct->GetFloat( CRCD(0x906b67ba,\"time\"), &keyTime, Script::ASSERT );\r\n\t\t\t\t\t\tframe = (int)(keyTime * 60.0f);\r\n\t\t\t\t}\r\n\r\n                uint32 eventType;\r\n\t\t\t\tpSubStruct->GetChecksum( CRCD(0xc451f558,\"event\"), &eventType, Script::ASSERT );\r\n\r\n\t\t\t\tScript::CStruct* pEventParams = NULL;\r\n\t\t\t\tpSubStruct->GetStructure( CRCD(0x7031f10c,\"params\"), &pEventParams, Script::NO_ASSERT );\r\n                \r\n\t\t\t\tGfx::CCustomAnimKey* pKey = new Gfx::CEventKey( frame, eventType, pEventParams );\r\n\t\t\t\tpKey->SetActive( true );\r\n\t\t\t\tm_customAnimKeyList.AddToTail( pKey );\r\n\t\t\t}\r\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBlendChannel::ResetCustomKeys()\r\n{\r\n\tint customKeyCount = m_customAnimKeyList.CountItems();\r\n\tfor ( int i = 0; i < customKeyCount; i++ )\r\n\t{\r\n\t\tGfx::CCustomAnimKey* pKey = (Gfx::CCustomAnimKey*)m_customAnimKeyList.GetItem(i);\r\n\t\tpKey->SetActive( true );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBlendChannel::ProcessCustomKeys( float startTime, float endTime )\r\n{\r\n\t// Only fire off events on the primary anim\r\n\tif ( GetStatus() == ANIM_STATUS_ACTIVE )\r\n\t{\r\n\t\tstartTime *= 60.0f;\r\n\t\tendTime *= 60.0f;\r\n\r\n\t\t// we've just looped, so reset the keys\r\n\t\tif ( m_direction == ANIM_DIR_FORWARDS )\r\n\t\t{\r\n\t\t\tif ( startTime > endTime )\r\n\t\t\t{\r\n\t\t\t\tResetCustomKeys();\r\n\t\t\t\tstartTime = m_startTime;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( endTime > startTime )\r\n\t\t\t{\r\n\t\t\t\tResetCustomKeys();\r\n\t\t\t\tstartTime = m_startTime;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tint customKeyCount = m_customAnimKeyList.CountItems();\r\n\t\tfor ( int i = 0; i < customKeyCount; i++ )\r\n\t\t{\r\n\t\t\tGfx::CCustomAnimKey* pKey = (Gfx::CCustomAnimKey*)m_customAnimKeyList.GetItem(i);\r\n\t\t\tif ( pKey->WithinRange( startTime, endTime ) )\r\n\t\t\t{\r\n//\t\t\t\tprintf( \"Processing key at %f (%f %f)\\n\", 0.0f, startTime, endTime );\r\n\t\t\t\tpKey->ProcessKey( GetObject() );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n//\t\t\t\tprintf( \"Not processing key at %f (%f %f)\\n\", custom_key_time, startTime, endTime );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// TODO:  reset the custom keys when it loops?\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nEAnimFunctionResult CBlendChannel::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tcase 0x83654874:\t// AddAnimController\r\n\t\t{\r\n\t\t\tAddController( pParams );\r\n\t\t\treturn AF_TRUE;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0x986d274e:\t// RemoveAnimController\r\n\t\t{\r\n\t\t\tuint32 id;\r\n\t\t\tpParams->GetChecksum( CRCD(0x40c698af,\"id\"), &id, Script::ASSERT );\r\n\t\t\tCBaseAnimController* pAnimController = get_controller_by_id( id );\r\n\t\t\tif ( pAnimController )\r\n\t\t\t{\r\n\t\t\t\tremove_controller( pAnimController );\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\r\n\tfor ( int i = 0; i < m_numControllers; i++ )\r\n\t{\r\n\t\tEAnimFunctionResult theResult = mp_controllers[i]->CallMemberFunction( Checksum, pParams, pScript );\r\n\t\t\r\n\t\tif ( theResult != AF_NOT_EXECUTED )\r\n\t\t{\r\n\t\t\treturn theResult;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn AF_NOT_EXECUTED;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CCompositeObject* CBlendChannel::GetObject()\r\n{\r\n\treturn mp_object;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Gfx/blendchannel.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       BlendChannel.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  12/12/2002\r\n//****************************************************************************\r\n\r\n#ifndef __GFX_BLENDCHANNEL_H__\r\n#define __GFX_BLENDCHANNEL_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gfx/animcontroller.h>\r\n#include <gfx/baseanimcontroller.h>\r\n#include <gfx/customanimkey.h>\r\n\t\r\nnamespace Object\r\n{\r\n\tclass CObject;\r\n}\r\n\t\t\t \r\nnamespace Script\r\n{\r\n\tclass CScript;\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Gfx\r\n{\r\n\tclass CBlendChannel;\r\n\tclass CPose;\r\n\tclass CBaseAnimController;\r\n\r\n\t// NOTE: if you change this enum, update the GetDebugInfo switch statement!\t\r\n\tenum EAnimStatus\r\n\t{\t\t\t\t\t\t\t\t \r\n\t\tANIM_STATUS_INACTIVE\t\t= 0,\t// No animation playing.\r\n\t\tANIM_STATUS_DEGENERATING,\t\t\t// Animation playing, but being faded out.\r\n\t\tANIM_STATUS_ACTIVE\t\t\t\t\t// Animation playing.\r\n\t};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass CBlendChannel : public CAnimChannel\r\n{\r\nprotected:\r\n\t// TODO:  Replace with a more efficient list structure?\r\n\tenum\r\n\t{\r\n\t\tvMAX_CONTROLLERS = 4\r\n\t};\r\n\r\npublic:\r\n\tCBlendChannel( Obj::CCompositeObject* pCompositeObject );\r\n\tvirtual\t~CBlendChannel();\r\n\r\npublic:\r\n\tCBaseAnimController*\t\tAddController( Script::CStruct* pParams );\r\n\tbool\t\t\t\t\t\tGetPose( Gfx::CPose* pPose );\r\n\tfloat\t\t\t\t\t\tGetBlendValue();\r\n\tbool\t\t\t\t\t\tIsActive();\r\n\tbool\t\t\t\t\t\tIsDegenerating();\r\n\tvoid\t\t\t\t\t\tInvalidateCache();\r\n    virtual EAnimFunctionResult\tCallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\npublic:\r\n\tvirtual void\t\t\t\tUpdate();\r\n\tvirtual void\t\t\t\tReset();\r\n\tvirtual void\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\tvirtual void        \t\tPlaySequence( uint32 animName, float start_time, float end_time, EAnimLoopingType loop_type, float blend_period, float speed, bool flipped );\r\n\r\npublic:\r\n\tfloat\t\t\t\t\t\tGetDegenerationTime() { return m_degenerationTime; }\r\n\tfloat\t\t\t\t\t\tGetDegenerationTimeToBlendMultiplier() { return m_degenerationTimeToBlendMultiplier; }\r\n\tvoid\t\t\t\t\t\tSetDegenerationTime( float time ) { m_degenerationTime = time; }\r\n\tvoid\t\t\t\t\t\tSetDegenerationTimeToBlendMultiplier( float mult ) { m_degenerationTimeToBlendMultiplier = mult; }\r\n\tbool\t\t\t\t\t\tDegenerate( float blendPeriod );\r\n\r\nprotected:\t\t\r\n\tvoid\t\t\t\t\t\tadd_controller( CBaseAnimController* pAnimController, int priority = 0 );\r\n\tvoid\t\t\t\t\t\tremove_controllers();\r\n\tvoid\t\t\t\t\t\tremove_controller( CBaseAnimController* pAnimController );\r\n\tCBaseAnimController* \t\tget_controller_by_id( uint32 id );\r\n\r\nprotected:\r\n\tEAnimStatus\t\t\t\t\tGetStatus() const;\r\n\r\npublic:\r\n\tvoid\t\t\t\t\t\tSetStatus(EAnimStatus status);\r\n\tObj::CCompositeObject*\t\tGetObject();\r\n\r\nprotected:\r\n\tEAnimStatus\t\t\t\t\tm_status;\r\n                       \r\nprotected:\r\n\tCBaseAnimController*\t\tmp_controllers[vMAX_CONTROLLERS];\r\n\tint\t\t\t\t\t\t\tm_numControllers;\r\n    \r\n\tfloat\t\t\t\t\t\tm_blendSpeed;\r\n\tfloat\t\t\t\t\t\tm_degenerationTime;\r\n    float\t\t\t\t\t\tm_degenerationTimeToBlendMultiplier;\r\n\r\n\tuint32\t\t\t\t\t\tm_animScriptName;\r\n\tObj::CCompositeObject*\t\tmp_object;\r\n\r\npublic:\r\n\t// for doing anim events...\r\n\tvoid\t\t\t\t\t\t\tProcessCustomKeys(float startTime, float endTime);\r\n\tvoid\t\t\t\t\t\t\tResetCustomKeys();\r\n\r\nprotected:\r\n\tvoid \t\t\t\t\t\t\tadd_custom_keys( uint32 animName );\r\n\tvoid\t\t\t\t\t\t\tdelete_custom_keys();\r\n\tLst::Head<Gfx::CCustomAnimKey>\tm_customAnimKeyList;\t\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/camera.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       camera.cpp\r\n//* OWNER:          Mark Burton\r\n//* CREATION DATE:  1/31/1999\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/math.h>\r\n#include <core/singleton.h>\r\n#include <gfx/gfxman.h>\r\n#include <gfx/camera.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxviewman.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nconst float\tCamera::vDEFAULT_NEARZ\t\t= 12.0f;\r\nconst float\tCamera::vDEFAULT_FARZ\t\t= 12000.0f;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nconst float Camera::vUSE_PIXEL_RATIO\t= 0.0f;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCamera::Camera ( )\r\n{\t\r\n\t//SetFOV ( Mth::DegToRad ( 60.0f ));\r\n\tSetHFOV(Nx::CViewportManager::sGetDefaultAngle());\r\n\r\n\tm_matrix.Ident();\t// Since the default constructor doesn't do this\r\n\r\n\tm_near_clip = vDEFAULT_NEARZ;\r\n\tm_far_clip = vDEFAULT_FARZ;\r\n\tm_pos.Set();\r\n\tm_old_pos.Set();\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCamera::~Camera ( void )\r\n{   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Camera::SetHFOV(float h_fov)\r\n{\r\n\tm_h_fov = h_fov;\r\n\t//Dbg_Message(\"Changed camera %x to angle %f\", this, m_h_fov);\r\n\r\n\tUpdateAdjustedHFOV();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Camera::UpdateAdjustedHFOV()\r\n{\r\n\tm_adj_h_fov = Mth::RadToDeg( 2.0f * atanf( tanf( Mth::DegToRad( m_h_fov / 2.0f ) ) * Nx::CViewportManager::sGetScreenAngleFactor() ) );\r\n\t//Dbg_Message(\"%x: Orig angle %f; Adjusted angle %f\", this, m_h_fov, m_adj_h_fov);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat Camera::GetAdjustedHFOV()\r\n{\r\n\t// Garrett: m_adj_h_fov may not be right, so we calculate it every time we need it now.  Will try to keep it\r\n\t// up-to-date at a later date.\r\n\tUpdateAdjustedHFOV();\r\n\r\n\treturn m_adj_h_fov;\r\n#if 0\r\n\treturn Mth::RadToDeg( 2.0f * atanf( tanf( Mth::DegToRad( m_h_fov / 2.0f ) ) * Nx::CViewportManager::sGetScreenAngleFactor() ) );\r\n#endif\r\n}\r\n\r\n#if 0\r\n/******************************************************************************\r\n *\r\n * Function:\t\tCamera::SetFocalLength ( float focal_length, float h_aspect )\r\n *\r\n * Description:\t\tSets the camera viewplane according to focal length\r\n *\r\n * Parameters:\t\tfocal_length = focal length of lens in meters \r\n *\t\t\t\t\th_aspect = horizontal aspect scale factor\r\n *\r\n * Notes:\t\t\tfocal_length of 0.035 is equal to a 35mm lens.\r\n *\r\n *\t\t\t\t\tYou cannot set horizontally or vertically flipped\r\n *\t\t\t\t\tviewplanes diRectly with this function\r\n *\r\n *\t\t\t\t\tfocal_length is clamped to a minimum value of N_EPSILON\r\n *\r\n ******************************************************************************/\r\n\r\nvoid Camera::SetFocalLength ( float focal_length, float h_aspect )\r\n{\r\n\tfloat fov = atanf (( 18.0f / 1000.0f) / Mth::Max ( Mth::EPSILON, focal_length )) * 2.0f;\r\n\t\r\n\tSetFOV ( fov, h_aspect );\r\n}\r\n\r\n/******************************************************************************\r\n *\r\n * Function:\t\tCamera::SetViewPlane ( float h_fov, float v_fov )\r\n *\r\n * Description:\t\tSets the camera view plane with two FOV angles \r\n *\r\n * Parameters:\t\th_fov\t= horizontal FOV angle in radians [-N_PI,+N_PI]\r\n *\t\t\t\t\tv_fov\t= vertical FOV angle in radians\t  [_N_PI,+N_PI]\r\n *\r\n * Notes:\t\t\tThe FOV angles are clamped separately, i.e. if clamping\r\n *\t\t\t\t\toccurs due to too large an angle, the aspect ratio is\r\n *\t\t\t\t\taffected.\r\n *\t\t\t\t\t\r\n ******************************************************************************/\r\n\r\nvoid Camera::SetViewPlane ( float h_fov, float v_fov )\r\n{\r\n\t\r\n\r\n}\r\n\r\n/******************************************************************************\r\n *\r\n * Function:\t\tCamera::SetFOV ( float fov, float h_aspect )\r\n *\r\n * Description:\t\tSets camera view plane with a field-of-view angle\r\n *\t\t\t\t\tand an aspect ratio\r\n *\r\n * Parameters:\t\tfov\t\t = FOV angle in radians\r\n *\t\t\t\t\th_aspect = horizontal aspect ratio ( default: vp pixel ratio )\r\n *\t\t\t\t\t\r\n ******************************************************************************/\r\n\r\nvoid Camera::SetFOV ( float v_fov, float h_aspect )\r\n{\r\n\t\r\n/*\r\n\tfloat x,y \r\n\t\r\n\tv_fov = Mth::Abs ( v_fov );\r\n\tv_fov = Mth::Clamp ( v_fov, Mth::EPSILON, Mth::PI - Mth::EPSILON );\r\n\t\r\n\tv_fov = tan ( v_fov / 2.0f );\r\n\t\r\n\th_aspect = ( h_aspect == vUSE_PIXEL_RATIO ) ? m_viewport->GetPixelRatio() : h_aspect; \r\n\r\n\tx = v_fov * h_aspect;\r\n\ty = v_fov;\r\n  \r\n// Mick: x and y contain the view window x and y   \r\n*/\r\n    \r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat Camera::GetFOV ( void )\r\n{\r\n\t// Mick: not meaningful......\r\n\treturn 0.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat Camera::GetFocalLength ( void )\r\n{\t\r\n\t// Mick: not meaningful......\r\n\treturn 0.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat Camera::GetAspectRatio ( void )\r\n{\r\n\t// Mick: not meaningful......\r\n\treturn 0.0f;\r\n\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Camera::StoreOldPos( void )\r\n{\r\n\tm_old_pos = GetPos();\t\t   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Note these are returned by value, until\r\n// we can store them explicity in the camera, and return them by reference\r\nvoid Camera::SetPos(const Mth::Vector& pos)\r\n{\r\n\tm_pos = pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector & Camera::GetPos()\r\n{\r\n\treturn  m_pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Camera::SetMatrix(const Mth::Matrix& mat)\r\n{\r\n\tm_matrix = mat;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Matrix & Camera::GetMatrix()\r\n{\r\n\treturn m_matrix;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Camera::CallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( checksum )\r\n\t{\r\n\t\tcase 0x44ea2b6d:\t\t// ChangeCameraFOV\r\n\t\t\t{\r\n\t\t\t\tfloat fov;\r\n\t\t\t\tpParams->GetFloat( NONAME, &fov, Script::ASSERT );\r\n\t\t\t\t//Nx::CViewportManager::sSetScreenAngle( Mth::RadToDeg( fov ) );\r\n\t\t\t\tSetHFOV(Mth::RadToDeg(fov));\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\treturn Obj::CObject::CallMemberFunction( checksum, pParams, pScript );\r\n}\r\n\r\n} // namespace Gfx\r\n"
  },
  {
    "path": "Code/Gfx/camera.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       camera.cpp\r\n//* OWNER:          Mark Burton\r\n//* CREATION DATE:  11/11/1999\r\n//****************************************************************************\r\n\r\n#ifndef __GFX_CAMERA_H\r\n#define __GFX_CAMERA_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/support.h>\r\n#include <core/math.h>\r\n#ifdef __PLAT_NGC__\r\n#include \"sys/ngc/p_camera.h\"\r\n#endif\t\t// __PLAT_NGC__\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Gfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Camera : public Obj::CObject\r\n{\r\n\t\r\npublic:\r\n\tstatic const float vUSE_PIXEL_RATIO;\r\n\r\n\tCamera( void );\r\n\tvirtual ~Camera( void );\r\n\r\npublic:\t\r\n\tvoid\t\t\tSetPos(const Mth::Vector& pos);\t\t// Set the position of the camera\r\n\tMth::Vector\t&\tGetPos();\t\t\t\t\t\t\t// Return the position of the camera\r\n\tvoid\t\t\tSetMatrix(const Mth::Matrix& mat);\t// Set the orientation matrix\r\n\tMth::Matrix\t&\tGetMatrix();\t\t\t\t\t\t// Return the orientation matrix\r\n\r\n\r\n\tvoid\t\t\tSetHFOV(float h_fov);\r\n\tfloat\t\t\tGetHFOV() const;\r\n\tvoid\t\t\tUpdateAdjustedHFOV();\r\n\tfloat\t\t\tGetAdjustedHFOV();\r\n\r\n#if 0\r\n\tvoid\t\t\tSetFOV ( float v_fov, float h_aspect = vUSE_PIXEL_RATIO );\r\n\tvoid\t\t\tSetViewPlane ( float h_fov, float v_fov );\r\n\tvoid\t\t\tSetFocalLength ( float focal_length, float h_aspect = vUSE_PIXEL_RATIO );\r\n\r\n\tfloat\t\t\tGetFOV ( void );\r\n\tfloat\t\t\tGetFocalLength ( void );\r\n\tfloat\t\t\tGetAspectRatio ( void );\r\n#endif\r\n\r\n\tvoid\t\t\tSetNearFarClipPlanes ( float nearPlane, float farPlane );\r\n\tvoid\t\t\tSetFogNearPlane ( float nearPlane );\r\n\t\r\n\tfloat\t\t\tGetNearClipPlane() const;\r\n\tfloat\t\t\tGetFarClipPlane() const;\r\n\r\n\tstatic const float\tvDEFAULT_NEARZ;\r\n\tstatic const float\tvDEFAULT_FARZ;\r\n\r\n\tvoid\t\t\tStoreOldPos( void );\r\n\tMth::Vector\t\tm_old_pos;\r\n\r\npublic:\r\n\tbool\t\t\tCallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript ); \r\n\r\nprotected:  \t\r\n\tMth::Vector\t\tm_pos;\t\t\t\t\t\t\t\t// camera position\r\n\tMth::Matrix\t\tm_matrix;\t\t\t\t\t\t\t// orientation matrix\r\n\r\n\tfloat\t\t\tm_h_fov;\t\t\t\t\t\t\t// horizontal field of view angle (degrees)\r\n\tfloat\t\t\tm_adj_h_fov;\t\t\t\t\t\t// screen adjusted horizontal field of view angle (degrees)\r\n\r\n\tfloat\t\t\tm_near_clip;\t\t\t\t\t\t// near clip plane\r\n\tfloat\t\t\tm_far_clip;\t\t\t\t\t\t\t// far clip plane\r\n};\r\n\r\n/*****************************s************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float Camera::GetHFOV() const\r\n{\r\n\treturn m_h_fov;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void Camera::SetNearFarClipPlanes ( float nearPlane, float farPlane ) \r\n{\r\n\tDbg_MsgAssert( farPlane > 0.0f,( \"Far Plane <= 0\" ));\r\n\tDbg_MsgAssert( nearPlane > 0.0f,( \"Near Plane <= 0\" ));\r\n\tDbg_MsgAssert( farPlane > nearPlane,( \"Far Plane <= Near Plane\" ));\r\n\r\n\tm_far_clip = farPlane;\r\n\tm_near_clip = nearPlane;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void Camera::SetFogNearPlane ( float nearPlane ) \r\n{\r\n//\tprintf (\"STUBBED:  SetFogNearPlane\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float Camera::GetNearClipPlane() const\r\n{\r\n\treturn m_near_clip;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline float Camera::GetFarClipPlane() const\r\n{\r\n\treturn m_far_clip;\r\n}\r\n\r\n} // namespace Gfx\r\n\r\n#endif\t// __GFX_CAMERA_H\r\n"
  },
  {
    "path": "Code/Gfx/debuggfx.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGFX\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tdebuggfx.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t11/01/00\t-\tmjd\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tDraws debug lines, other debug graphics\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <string.h>\r\n\r\n\r\n#include <core/defines.h>\r\n#include <gfx/debuggfx.h>\r\n#include <sys/timer.h>\t\t\t\t// Including for debugging\r\n#include <sys/config/config.h>\r\n#include <sys/profiler.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/nxviewman.h>\t\t\t// for camera\r\n\r\n#ifdef\t__PLAT_NGPS__\t\r\n#include <gfx/ngps/nx/line.h>\r\n#include <gfx/ngps/nx/render.h>\r\nnamespace Sys\r\n{\r\n\textern void\t\t\tbox(int x0,int y0, int x1, int y1, uint32 color);\r\n}\r\n#endif\r\n\r\n#ifdef\t__PLAT_XBOX__\r\n#include <gfx/xbox/nx/nx_init.h>\r\n#include <gfx/xbox/nx/render.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#define DEBUGGERY_LINE_ARRAY_SIZE\t\t10000\t\t\t// * 48 bytes = 4.8MB off the debug heap\r\n#else\r\n#define DEBUGGERY_LINE_ARRAY_SIZE\t\t2048\r\n#endif\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstruct SDebuggeryLine{\r\n\tMth::Vector\t\t\tv0, v1;\r\n\tunsigned int\trgb0, rgb1;\r\n\tint\t\t\t\tin_use;\r\n\tint\t\t\t\tnum_draw_frames;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __PLAT_NGC__\r\nSDebuggeryLine *DebuggeryLineArray = NULL;\t\t//[ DEBUGGERY_LINE_ARRAY_SIZE ];\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n#ifdef\t__DEBUG_CODE__\r\nstatic bool\tsActive = false;\r\n#endif\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid DebuggeryLines_Draw( void );\r\nvoid DebuggeryLines_CleanUp( void );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nvoid DebuggeryLines_CleanUp( void )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n#ifndef __PLAT_NGC__\r\n\tif (!DebuggeryLineArray)\r\n\t{\r\n\t\t// DOn't bother if not allocated yet\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tint i;\r\n\t\r\n\tfor ( i = 0; i < DEBUGGERY_LINE_ARRAY_SIZE; i++ )\r\n\t{\r\n\t\tDebuggeryLineArray[ i ].in_use = 0;\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n#endif\r\n}\r\n\r\n#ifndef __PLAT_NGC__\r\n#ifdef\t__DEBUG_CODE__\r\nstatic bool DebuggeryLinesInitialized = 0;\r\n#endif\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\r\nvoid DebuggeryLines_Draw( void )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\r\n\r\n\tif (!sActive)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tsActive = false;\r\n#\tif defined( __PLAT_NGPS__ )\r\n\r\n\tMth::Vector\tcam_fwd;\r\n\t\r\n\tif (Nx::CViewportManager::sGetActiveCamera())\r\n\t{\r\n\t\tcam_fwd = Nx::CViewportManager::sGetActiveCamera()->GetMatrix()[Z];\r\n\t}\r\n\telse\r\n\t{\r\n\t\tprintf(\"WARNING: called Gfx::DebuggeryLines_Draw without a camera\\n\");\r\n\t\treturn;\r\n\t}\r\n\r\n\t// can remove this when this module is properly initialized:\r\n\tint i;\r\n\tuint32\tlast_color = 0x33333333;\t \t// the dodginess of my code astounds me!\r\n\r\n\tif ( !DebuggeryLinesInitialized )\r\n\t{\r\n\t\tDebuggeryLines_CleanUp( );\r\n\t\tDebuggeryLinesInitialized = 1;\r\n\t}\r\n\r\n\tSDebuggeryLine* p_debugline = DebuggeryLineArray;\t\r\n\tfor ( i = DEBUGGERY_LINE_ARRAY_SIZE; i ; i-- )\r\n\t{\r\n\t\tif ( p_debugline->in_use )\r\n\t\t{\r\n\t\t\r\n\t\t\tNxPs2::DMAOverflowOK = 2;\r\n\t\t\r\n\t\t\tif ( last_color != p_debugline->rgb0)\r\n\t\t\t{\r\n\t\t\t\tif (last_color != 0x33333333)\r\n\t\t\t\t{\r\n\t\t\t\t\tNxPs2::ChangeLineColor(0x80000000 + (0x00ffffff & p_debugline->rgb0));\r\n\t\t\t\t}\t\t\t\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tNxPs2::BeginLines3D(0x80000000 + (0x00ffffff & p_debugline->rgb0));\r\n\t\t\t\t}\r\n\t\t\t\tlast_color = p_debugline->rgb0;\r\n\t\t\t}\r\n\t\t\r\n\t\t\tsActive = true;\r\n\t\t\tNxPs2::DrawLine3D(p_debugline->v0[X],\r\n\t\t\t\t\t   p_debugline->v0[Y],\r\n\t\t\t\t\t   p_debugline->v0[Z],\r\n\t\t\t\t\t   p_debugline->v1[X],\r\n\t\t\t\t\t   p_debugline->v1[Y],\r\n\t\t\t\t\t   p_debugline->v1[Z]);\r\n\t\t\tNxPs2::DrawLine3D(p_debugline->v0[X],\r\n\t\t\t\t\t   p_debugline->v0[Y],\r\n\t\t\t\t\t   p_debugline->v0[Z],\r\n\t\t\t\t\t   p_debugline->v1[X],\r\n\t\t\t\t\t   p_debugline->v1[Y],\r\n\t\t\t\t\t   p_debugline->v1[Z]);\r\n\r\n\r\n\t\t\tif ( p_debugline->in_use == 2 )\r\n\t\t\t{\r\n\t\t\t\t\t\r\n\t\t\t\t// Calculate and draw an arrowhead \r\n\t\t\t\t// 1/4th the length, at ~30 degrees\t\t\t\t\t   \r\n\t\t\t\tMth::Vector\ta = p_debugline->v0;\r\n\t\t\t\tMth::Vector b = p_debugline->v1;\r\n\t\t\t\tMth::Vector\tab = (b-a);\r\n\t\t\t\tab /= 4.0f;\r\n\t\t\t\tMth::Vector out;\r\n\t\t\t\tout = ab;\r\n\t\t\t\tout.Normalize();\r\n\t\t\t\tout = Mth::CrossProduct(out, cam_fwd);\r\n\t\t\t\tout *= ab.Length()/3.0f;\t\t\t\r\n\t\t\t\t\r\n\t\t\t\tMth::Vector left =  b - ab + out;\r\n\t\t\t\tMth::Vector right = b - ab - out;\r\n\t\r\n\t\t\t\tNxPs2::DrawLine3D(left[X],left[Y],left[Z],b[X],b[Y],b[Z]);\r\n\t\t\t\tNxPs2::DrawLine3D(right[X],right[Y],right[Z],b[X],b[Y],b[Z]);\r\n\t\t\t\tNxPs2::DrawLine3D(right[X],right[Y],right[Z],left[X],left[Y],left[Z]);\t // crossbar\r\n\t\t\t\t// have to draw it twice for some stupid reason\t(final segment of a particular color is not rendered)\r\n\t\t\t\tNxPs2::DrawLine3D(left[X],left[Y],left[Z],b[X],b[Y],b[Z]);\r\n\t\t\t\tNxPs2::DrawLine3D(right[X],right[Y],right[Z],b[X],b[Y],b[Z]);\r\n\t\t\t\tNxPs2::DrawLine3D(right[X],right[Y],right[Z],left[X],left[Y],left[Z]);\r\n\t\t\t\t\r\n\t\t\t}\t\t\t   \r\n\t\t\t\t\t   \r\n\t\t\t\t\t   \r\n\t\t\tif ( p_debugline->num_draw_frames )\r\n\t\t\t{\r\n\t\t\t\tp_debugline->num_draw_frames--;\r\n\t\t\t\tif ( !p_debugline->num_draw_frames )\r\n\t\t\t\t\tp_debugline->in_use = false;\r\n\t\t\t}\r\n\t\t}\r\n\t\tp_debugline++;\r\n\t}\r\n\r\n\tif (last_color != 0x33333333)\r\n\t{\r\n\t\tNxPs2::EndLines3D();\r\n\t}\t\t\t\r\n#\telif defined( __PLAT_XBOX__ )\r\n\tstruct sLineVert\r\n\t{\r\n\t\tD3DVECTOR\tpos;\r\n\t\tD3DCOLOR\tcol;\r\n\t};\r\n\r\n\tstatic sLineVert\tline_verts[DEBUGGERY_LINE_ARRAY_SIZE * 2];\r\n\tuint32\t\t\t\tlast_color = 0x33333333;\r\n\tuint32\t\t\t\tindex = 0;\r\n\tif( !DebuggeryLinesInitialized )\r\n\t{\r\n\t\tDebuggeryLines_CleanUp();\r\n\t\tDebuggeryLinesInitialized = 1;\r\n\t}\r\n\t\r\n\tfor( int i = 0; i < DEBUGGERY_LINE_ARRAY_SIZE; ++i )\r\n\t{\r\n\t\tDbg_Assert( index < DEBUGGERY_LINE_ARRAY_SIZE * 2 );\r\n\t\tif( DebuggeryLineArray[i].in_use )\r\n\t\t{\r\n\t\t\tif( DebuggeryLineArray[ i ].num_draw_frames )\r\n\t\t\t{\r\n\t\t\t\tDebuggeryLineArray[ i ].num_draw_frames--;\r\n\t\t\t\tif( !DebuggeryLineArray[i].num_draw_frames )\r\n\t\t\t\t\tDebuggeryLineArray[i].in_use = false;\r\n\t\t\t}\r\n\t\t\tsActive = true;\r\n\t\t\t\r\n\t\t\t// Need to switch rgba to bgra.\r\n\t\t\tuint32 rgb0 = ( DebuggeryLineArray[i].rgb0 & 0xFF00FF00UL ) | (( DebuggeryLineArray[i].rgb0 & 0x00FF0000UL ) >> 16 ) |(( DebuggeryLineArray[i].rgb0 & 0x000000FFUL ) << 16 );\r\n\t\t\tuint32 rgb1 = ( DebuggeryLineArray[i].rgb1 & 0xFF00FF00UL ) | (( DebuggeryLineArray[i].rgb1 & 0x00FF0000UL ) >> 16 ) |(( DebuggeryLineArray[i].rgb1 & 0x000000FFUL ) << 16 );\r\n\t\t\t\r\n\t\t\tline_verts[index].col\t= rgb0;\r\n\t\t\tline_verts[index].pos.x\t= DebuggeryLineArray[i].v0[X];\r\n\t\t\tline_verts[index].pos.y\t= DebuggeryLineArray[i].v0[Y];\r\n\t\t\tline_verts[index].pos.z\t= DebuggeryLineArray[i].v0[Z];\r\n\t\t\t++index;\r\n\t\t\tline_verts[index].col\t= rgb1;\r\n\t\t\tline_verts[index].pos.x\t= DebuggeryLineArray[i].v1[X];\r\n\t\t\tline_verts[index].pos.y\t= DebuggeryLineArray[i].v1[Y];\r\n\t\t\tline_verts[index].pos.z\t= DebuggeryLineArray[i].v1[Z];\r\n\t\t\t++index;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif( index > 0 )\r\n\t{\r\n\t\tNxXbox::set_texture( 0, NULL );\r\n\t\tNxXbox::set_blend_mode( NxXbox::vBLEND_MODE_DIFFUSE );\r\n\t\tNxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE );\r\n\t\tNxXbox::set_pixel_shader( 0 );\r\n\t\tHRESULT hr = NxXbox::EngineGlobals.p_Device->DrawPrimitiveUP( D3DPT_LINELIST, index / 2, line_verts, sizeof( sLineVert ));\r\n\t}\r\n#\tendif\r\n#endif\r\n}  // end of DebuggeryLines_Draw( )\r\n\r\n \r\n// Draw a bunch of 2D rectangles that we added to the list this frame. \r\n// currently used for the framerate indicator.\r\n\r\n\r\nvoid DebuggeryRects_Draw( float time)\r\n{\r\n\r\n#ifdef\t__DEBUG_CODE__\r\n\r\n\t#ifdef\t__PLAT_NGPS__\r\n\t#ifdef\t\t__USE_PROFILER__\r\n\t\r\n\t\t\t\t\t\t  \r\n\t\tif (Script::GetInteger(CRCD(0xd9859988,\"Display_framerate_box\")) == 0)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\t\t\t\t  \r\n\t\tif (time < 0.016667f)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\tif (Config::CD())\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tint size = (int) (time * 400); \r\n\r\n\t\t\r\n\t\tint x = 70-size;\r\n\t\tint y = 200-size;\r\n\t\tint w = size*2;\r\n\t\tint h = size*2;\r\n\r\n\t\t\r\n\t\tSys::box( x,y,x+w,y+h, 0x0000ff);\r\n\t\tSys::box( x+w/4,y+h/4,x+w*3/4,y+h*3/4, 0xffffff);\r\n\t\r\n\t#endif\r\n\t#endif\r\n#endif\r\n\r\n}\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// given a movement vector v0, then move all the debug lines by this amount\r\n// (this allows us to see the lines relative to a moving object)\r\nvoid AdjustDebugLines( const Mth::Vector &v0)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\r\n#ifndef __PLAT_NGC__\r\n\tif (!DebuggeryLineArray)\r\n\t{\r\n\t\t// DOn't bother if not allocated yet\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (int i= 0; i< DEBUGGERY_LINE_ARRAY_SIZE; i++ )\r\n\t{\r\n\t\tif ( DebuggeryLineArray[ i ].in_use )\r\n\t\t{\r\n\t\t\tDebuggeryLineArray[ i ].v0 += v0;\r\n\t\t\tDebuggeryLineArray[ i ].v1 += v0;\r\n\t\t}\r\n\t}\r\n\r\n#endif\t\t// __PLAT_NGC__\r\n#endif\r\n}\r\n\r\n\r\n/*\tAdds a line to our debug line buffer, to be drawn every frame\r\n\tuntil the buffer wraps around again...\r\n*/\t\t\t\t\t\t   \r\nvoid AddDebugLine( const Mth::Vector &v0, const Mth::Vector &v1, int rgb0, int rgb1, int numDrawFrames )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n#ifndef __PLAT_NGC__\r\n\t\r\n    static int DebuggeryLineIndex = 0;\r\n\t\r\n\tif (!DebuggeryLineArray)\r\n\t{\r\n\t\tif (!Config::GotExtraMemory())\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t\tDebuggeryLineArray  = (SDebuggeryLine *) Mem::Malloc(DEBUGGERY_LINE_ARRAY_SIZE * sizeof (SDebuggeryLine));\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\tDebuggeryLines_CleanUp( );\t  //initialize it\r\n\t\t\r\n\t}\r\n\t\r\n//\tDbg_MsgAssert((v0-v1).Length() < 1000,(\"Suspiciously long line....\"));\r\n\r\n\tif ( !DebuggeryLinesInitialized )\r\n\t{\r\n\t\tDebuggeryLines_CleanUp( );\r\n\t\tDebuggeryLinesInitialized = 1;\r\n\t}\r\n\r\n\tif ( rgb1 == SAME_COLOR_AS_RGB0_PLEASE )\r\n\t{\r\n\t\trgb1 = rgb0;\r\n\t}\r\n\t\r\n\tDebuggeryLineArray[ DebuggeryLineIndex ].v0 = v0;\r\n\t\r\n\tDebuggeryLineArray[ DebuggeryLineIndex ].v1 = v1;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\tDebuggeryLineArray[ DebuggeryLineIndex ].rgb0 = rgb0;\r\n\tDebuggeryLineArray[ DebuggeryLineIndex ].rgb1 = rgb1;\r\n\r\n\tDebuggeryLineArray[ DebuggeryLineIndex ].in_use = 1;\r\n\t\r\n\tDebuggeryLineArray[ DebuggeryLineIndex ].num_draw_frames = numDrawFrames;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\tif ( ++DebuggeryLineIndex >= DEBUGGERY_LINE_ARRAY_SIZE )\r\n\t{\r\n\t\tDebuggeryLineIndex = 0;\r\n\t}\r\n\t\r\n\tsActive = true;\r\n\t\r\n#endif\t\t// __PLAT_NGC__\r\n#endif\r\n} // end of AddDebugLine( )\r\n\r\n\r\nvoid AddDebugArrow( const Mth::Vector &v0, const Mth::Vector &v1, int rgb0, int rgb1, int numDrawFrames )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n#ifndef __PLAT_NGC__\r\n\t\r\n    static int DebuggeryLineIndex = 0;\r\n\t\r\n\tif (!DebuggeryLineArray)\r\n\t{\r\n\t\tif (!Config::GotExtraMemory())\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t\tDebuggeryLineArray  = (SDebuggeryLine *) Mem::Malloc(DEBUGGERY_LINE_ARRAY_SIZE * sizeof (SDebuggeryLine));\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\tDebuggeryLines_CleanUp( );\t  //initialize it\r\n\t\t\r\n\t}\r\n\t\r\n//\tDbg_MsgAssert((v0-v1).Length() < 1000,(\"Suspiciously long line....\"));\r\n\r\n\tif ( !DebuggeryLinesInitialized )\r\n\t{\r\n\t\tDebuggeryLines_CleanUp( );\r\n\t\tDebuggeryLinesInitialized = 1;\r\n\t}\r\n\r\n\tif ( rgb1 == SAME_COLOR_AS_RGB0_PLEASE )\r\n\t{\r\n\t\trgb1 = rgb0;\r\n\t}\r\n\t\r\n\tDebuggeryLineArray[ DebuggeryLineIndex ].v0 = v0;\r\n\t\r\n\tDebuggeryLineArray[ DebuggeryLineIndex ].v1 = v1;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\tDebuggeryLineArray[ DebuggeryLineIndex ].rgb0 = rgb0;\r\n\tDebuggeryLineArray[ DebuggeryLineIndex ].rgb1 = rgb1;\r\n\r\n\tDebuggeryLineArray[ DebuggeryLineIndex ].in_use = 2;\r\n\t\r\n\tDebuggeryLineArray[ DebuggeryLineIndex ].num_draw_frames = numDrawFrames;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\tif ( ++DebuggeryLineIndex >= DEBUGGERY_LINE_ARRAY_SIZE )\r\n\t{\r\n\t\tDebuggeryLineIndex = 0;\r\n\t}\r\n\t\r\n\tsActive = true;\r\n\t\r\n#endif\t\t// __PLAT_NGC__\r\n#endif\r\n} // end of AddDebugLine( )\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid AddDebugStar(Mth::Vector v0, float r, int rgb0, int numDrawFrames)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tMth::Vector v1,v2;\r\n\t\r\n\tv1 = v0; v2 = v0; v1[X]+=r; v2[X]-=r; AddDebugLine(v1,v2,rgb0,rgb0,numDrawFrames);\r\n\tv1 = v0; v2 = v0; v1[Y]+=r; v2[Y]-=r; AddDebugLine(v1,v2,rgb0,rgb0,numDrawFrames);\r\n\tv1 = v0; v2 = v0; v1[Z]+=r; v2[Z]-=r; AddDebugLine(v1,v2,rgb0,rgb0,numDrawFrames);\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid AddDebugCircle(Mth::Vector v0, int numPoints, float r, int rgb0, int numDrawFrames)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tMth::Vector v1, v2;\r\n\r\n\tMth::Vector fwd( 0.0f, 0.0f, r );\r\n\r\n\tv1 = v0 + fwd;\r\n\r\n\tfor ( int i = 0; i < numPoints; i++ )\r\n\t{\r\n\t\tfwd.RotateY( 2.0f * Mth::PI / (float)numPoints );\r\n\t\tv2 = v0 + fwd;\r\n\r\n\t\tAddDebugLine(v1,v2,rgb0,rgb0,numDrawFrames);\r\n\t\t\r\n\t\tv1 = v2;\r\n\t}\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid AddDebugBone( const Mth::Vector& p1, const Mth::Vector& p2, float red, float green, float blue )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\t// GJ:  Pretty much the same as AddDebugLine, but with \r\n\t// a more convenient interface for the skeleton code\r\n\r\n\tGfx::AddDebugLine( p1, p2,\r\n\t\t\t\t\t   MAKE_RGB( (int)(red * 255), (int)(green * 255), (int)(blue * 255) ),\r\n\t\t\t\t\t   MAKE_RGB( (int)(red * 255), (int)(green * 255), (int)(blue * 255) ),\r\n\t\t\t\t\t   1 );\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid AddDebugBox( const Mth::Matrix& root, const Mth::Vector& pos, SBBox *pBox, Mth::Vector *pOffset, int numFrames, Mth::Vector *pRot, int rgb )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\t\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tMth::Vector box[ 8 ];\r\n\tMth::Matrix m;\r\n\tint i;\r\n\r\n\tm = root;\r\n\tif ( pRot )\r\n\t{\r\n\t\tm.RotateLocal( *pRot );\r\n\t}\r\n\r\n\tbox[ 0 ] = box[ 1 ] = box[ 2 ] = box[ 3 ] = pBox->m_max;\r\n\r\n\tbox[ 1 ][ X ] = pBox->m_min[ X ];\r\n\tbox[ 2 ][ Y ] = pBox->m_min[ Y ];\r\n\tbox[ 3 ][ Z ] = pBox->m_min[ Z ];\r\n\t\r\n\tbox[ 5 ] = box[ 6 ] = box[ 7 ] = box[ 4 ] = pBox->m_min;\r\n\t\r\n\tbox[ 5 ][ X ] = pBox->m_max[ X ];\r\n\tbox[ 6 ][ Y ] = pBox->m_max[ Y ];\r\n\tbox[ 7 ][ Z ] = pBox->m_max[ Z ];\r\n\t\r\n\t\r\n\tfor ( i = 0; i < 8; i++ )\r\n\t{\r\n//\t\tfloat tempY = box[ i ][ Y ];\r\n//\t\tbox[ i ][ Y ] = box[ i ][ Z ];\r\n//\t\tbox[ i ][ Z ] = -tempY;\r\n\t\tif ( pOffset )\r\n\t\t{\r\n\t\t\tbox[ i ] += *pOffset;\r\n\t\t}\r\n\t\tbox[ i ] = m.Transform( box[ i ] );\r\n\t\tbox[ i ] += pos;\r\n\t}\r\n\r\n\tfor ( i = 1; i < 4; i++ )\r\n\t{\r\n\t\tGfx::AddDebugLine( box[ 0 ], box[ i ], rgb, rgb, numFrames );\r\n\t}\r\n\tfor ( i = 5; i < 8; i++ )\r\n\t{\r\n\t\tGfx::AddDebugLine( box[ 4 ], box[ i ], rgb, rgb, numFrames );\r\n\t}\r\n\t// fill in the cracks:\r\n\tGfx::AddDebugLine( box[ 1 ], box[ 6 ], rgb, rgb, numFrames );\r\n\tGfx::AddDebugLine( box[ 1 ], box[ 7 ], rgb, rgb, numFrames );\r\n\r\n\tGfx::AddDebugLine( box[ 2 ], box[ 5 ], rgb, rgb, numFrames );\r\n\tGfx::AddDebugLine( box[ 2 ], box[ 7 ], rgb, rgb, numFrames );\r\n\r\n\tGfx::AddDebugLine( box[ 3 ], box[ 5 ], rgb, rgb, numFrames );\r\n\tGfx::AddDebugLine( box[ 3 ], box[ 6 ], rgb, rgb, numFrames );\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid DebugGfx_Draw( void )\r\n{\t\r\n#ifdef\t__DEBUG_CODE__\r\n\tDebuggeryLines_Draw( );\r\n   \r\n//\tMdl::FrontEnd* p_frontend = Mdl::FrontEnd::Instance();\r\n//\tif( !p_frontend->GamePaused())\r\n\t{\r\n\t\tDebuggeryRects_Draw(Tmr::FrameLength());\t \r\n\t}\t\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid DebugGfx_CleanUp( void )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\t\r\n\t\r\n\tDebuggeryLines_CleanUp( );\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/debuggfx.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGFX\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tdebuggfx.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t11/01/00\t-\tmjd\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__DEBUG_GFX_H\r\n#define\t__DEBUG_GFX_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#include <core/math.h>\r\n#include <core/support.h>\r\n#include <core/singleton.h>\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Gfx\r\n{\r\n\r\n// use this macro to create the last two params to AddDebugLine( )\r\n#define MAKE_RGBA( r, g, b, a )\t( ( ( a ) << 24 ) | ( ( b ) << 16 ) | ( ( g ) << 8 ) | ( r ) )\r\n#define MAKE_RGB( r, g, b )\t\t( ( ( 255 ) << 24 ) | ( ( b ) << 16 ) | ( ( g ) << 8 ) | ( r ) )\r\n#define GET_R( rgba ) \t( ( ( rgba ) ) & 255 )\r\n#define GET_G( rgba ) \t( ( ( rgba ) >> 8 ) & 255 )\r\n#define GET_B( rgba ) \t( ( ( rgba ) >> 16 ) & 255 )\r\n#define GET_A( rgba ) \t( ( ( rgba ) >> 24 ) & 255 )\r\n\t\t\t\t\t\t\t\t\t\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// if i put them here, would they be private any more?\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define SAME_COLOR_AS_RGB0_PLEASE ( 1 << 31 )\r\n\r\n/*\tAdds a line to our debug line buffer, to be drawn every frame\r\n\tuntil the buffer wraps around again.\r\n*/\t\t\t\t\t\t   \r\nvoid AddDebugStar(Mth::Vector v0, float r = 12.0f, int rgb0 = MAKE_RGB( 127, 0, 127 ), int numDrawFrames = 0);\r\n\r\nvoid AddDebugCircle(Mth::Vector v0, int numPoints, float r, int rgb0, int numDrawFrames);\r\n\r\nvoid AdjustDebugLines( const Mth::Vector &v0);\r\nvoid AddDebugLine( const Mth::Vector &v0, const Mth::Vector &v1, int rgb0 = MAKE_RGB( 127, 127, 127 ), int rgb1 = SAME_COLOR_AS_RGB0_PLEASE, int numDrawFrames = 0 );\r\nvoid AddDebugArrow( const Mth::Vector &v0, const Mth::Vector &v1, int rgb0 = MAKE_RGB( 127, 127, 127 ), int rgb1 = SAME_COLOR_AS_RGB0_PLEASE, int numDrawFrames = 0 );\r\n\r\n// For drawing skeleton\r\nvoid AddDebugBone( const Mth::Vector& p1, const Mth::Vector& p2, float red = 1.0f, float green = 0.5f, float blue = 0.5f );\r\n\r\n// For drawing bounding box\r\nvoid AddDebugBox( const Mth::Matrix& root, const Mth::Vector& pos, SBBox *pBox, Mth::Vector *pOffset, int numFrames, Mth::Vector *pRot, int rgb = MAKE_RGB( 200, 0, 0 ) );\r\n\r\n// Call every frame from the renderer.\r\nvoid DebugGfx_Draw( void );\r\n\r\n// Cleanup code for this module:\r\nvoid DebugGfx_CleanUp( void );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n#endif\t// __DEBUG_GFX_H\r\n\r\n"
  },
  {
    "path": "Code/Gfx/gfxman.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics (GFX)\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgfxman.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t07/26/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGraphics device manager\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#include <core/defines.h>\r\n#include <core/debug.h>\r\n\r\n#include <sys/profiler.h>\r\n#include <sys/timer.h>\r\n\r\n#include <gfx/gfxman.h>\r\n#include <gfx/nxviewport.h>\r\n#include <gfx/camera.h>\r\n\r\n#include <gel/mainloop.h>\r\n#include <sys/config/config.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDbg_DefineProject ( GfxLib, \"Graphics Library\" )\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nuint32 Gfx_LastVBlank = 0;\r\n\r\nnamespace Gfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefineSingletonClass( Manager, \"Gfx Manager\" )\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nvoid\t\tManager::s_timer_code( const Tsk::Task< Manager >& task )\r\n{\r\n\t\r\n\t\r\n\t\r\n\tDbg_AssertType ( &task, Tsk::Task< Manager > );\r\n\r\n\tManager& gfx_manager = task.GetData();\r\n\r\n\tgfx_manager.m_time += (Tmr::Time) (int) (( Tmr::FrameLength() * 60.0f ) * \r\n\t\t\t\t\t\t\t\t\t\t( Tmr::vRESOLUTION / Config::FPS() ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#ifdef __PLAT_NGC__\r\nint gDumpMem = 0;\r\n#endif\t\t// __PLAT_NGC__\r\n\r\nvoid\t\tManager::s_start_render_code ( const Tsk::Hook< Manager >& hook )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::s_end_render_code ( const Tsk::Hook< Manager >& hook )\r\n{\r\n\r\n// Note: not currently called.... just left in to show the timing stuff....\r\n\t\r\n\tDbg_AssertType ( &hook, Tsk::Hook< Manager > );\r\n\tManager&\tgfx_manager = hook.GetData();\r\n    \r\n\tuint64 this_vblank;\r\n\t\r\n\tdo\r\n\t{\r\n\t\tthis_vblank = Tmr::GetVblanks();\r\n\t}\r\n\twhile(( this_vblank - Gfx_LastVBlank ) < gfx_manager.m_min_vblank_wait );\r\n\tGfx_LastVBlank = this_vblank;\r\n\r\n\tTmr::OncePerRender();   \t\t// update the frame counter\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::start_engine( void )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::stop_engine( void )\r\n{\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n\r\nManager::Manager ( void )\r\n{\r\n\t\r\n\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\r\n\tm_render_start_hook = new Tsk::Hook< Manager > ( s_start_render_code, *this );\r\n\tmlp_man->RegisterRenderStartHook ( m_render_start_hook );\r\n\r\n\tm_render_end_hook = new Tsk::Hook< Manager > ( s_end_render_code, *this );\r\n\tmlp_man->RegisterRenderEndHook ( m_render_end_hook );\r\n\r\n\tm_timer_task = new Tsk::Task< Manager > ( s_timer_code, *this );\r\n\tm_timer_task->SetMask(1<<3);\r\n\tmlp_man->AddLogicTask( *m_timer_task );\r\n\t\t\r\n\tm_min_vblank_wait = 0;\r\n\r\n\tm_metrics_active = false;\r\n\tm_vram_viewer_active = false;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager ( void )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType ( m_render_start_hook, Tsk::Hook< Manager > );\r\n\tdelete m_render_start_hook;\r\n\r\n\tDbg_AssertType ( m_render_end_hook, Tsk::Hook< Manager > );\r\n\tdelete m_render_end_hook;\r\n\r\n\tDbg_AssertType( m_timer_task, Tsk::Task< Manager > );\r\n\tdelete m_timer_task;\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tDbg_SetScreenAssert( false );\r\n#endif\r\n\r\n\tstop_engine();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nvoid\tManager::ToggleMetrics( void )\r\n{\r\n\t\r\n\t\r\n\tm_metrics_active = !m_metrics_active;\r\n\r\n#ifdef\t\t__USE_PROFILER__\r\n\tif( m_metrics_active )\r\n\t{\r\n\t\tSys::Profiler::sEnable();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSys::Profiler::sDisable();\r\n\t}\r\n#endif\r\n}\r\n\r\n#ifdef __NOPT_ASSERT__\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::AssertText ( int line, const char* text )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::AssertFlush( void )\r\n{\r\n// not needed...\t\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#endif /* __NOPT_ASSERT__ */\r\n\r\n} // namespace Gfx\r\n"
  },
  {
    "path": "Code/Gfx/gfxman.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics  (GFX)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgfx/gfxman.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t07/26/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_GFXMAN_H\r\n#define __GFX_GFXMAN_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/support.h>\r\n#include <core/singleton.h>\r\n#include <core/task.h>\r\n#include <core/macros.h>\r\n\r\n#include <sys/timer.h>\r\n\r\n\r\n\t\t\t  \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define USE_SKIN\r\n\r\nnamespace Gfx\r\n{\r\n\r\n#define OBJECT_RENDER_FLAG_BASIC_ATOMIC\t\t( 1 << 0 )\r\n#define OBJECT_RENDER_FLAG_SKIN_ATOMIC\t\t( 1 << 1 )\r\n#define OBJECT_RENDER_FLAG_PARTICLE_ATOMIC\t( 1 << 2 )\r\n#define OBJECT_RENDER_FLAG_HUD_ATOMIC\t\t( 1 << 3 )\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n     \r\nclass  Manager  : public Spt::Class\r\n{\r\n\t\r\n\t\r\npublic :\r\n\t\t\r\n\r\n//\tstatic const int vDEFAULT_VIDEO_HEIGHT = SCREEN_CONV_Y( 448 );\r\n// Mick, this only applies to the virtual viewport, so don't convert for PAL\t\r\n\tstatic const int vDEFAULT_VIDEO_HEIGHT = ( 448 );\r\n\r\n//\tstatic \tImage::RGBA\t\t\t\tsBackgroundColor; \r\n\r\n\r\n\tvoid\t\t\t\t\t\tToggleMetrics( void );\r\n\tvoid\t\t\t\t\t\tToggleVRAMViewer( void );\r\n\tvoid\t\t\t\t\t\tDumpVRAMUsage( void );\r\n\tvoid\t\t\t\t\t\tSetTrivialFarZClip( bool on )\t{ m_trivial_far_z_clip = on; }\r\n\r\n//\tMetrics*\t\t\t\t\tGetMetrics( void );\r\n#ifdef __NOPT_ASSERT__\r\n\tvoid\t\t\t\t\t\tAssertText( int line, const char* text );\r\n\tvoid\t\t\t\t\t\tAssertFlush( void );\r\n#endif\r\n\r\n#\tifdef __PLAT_XBOX__\r\n\tvoid\t\t\t\t\t\tSetGammaNormalized( float fr, float fg, float fb );\r\n\tvoid\t\t\t\t\t\tGetGammaNormalized( float *fr, float *fg, float *fb );\r\n#\tendif\r\n\r\n\tvoid\t\t\t\t\t\tScreenShot( const char *fileroot );\r\n\tvoid\t\t\t\t\t\tDumpMemcardScreeenshots();\r\n\t\r\n\r\n\tvoid\t\t\t\t\t\tSetMinVblankWait( int num_vblanks );\r\n\r\n\t// used by other graphics system to update displays\r\n\t// This is used instead of GetTime() because this will\r\n\t// stop incrementing when the game is paused\r\n\tTmr::Time\t\t\t\t\tGetGfxTime( void ) {return m_time; }\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\nprivate :\r\n\r\n\t\t\t\t\t\t\t\t~Manager( void );\r\n\t\t\t\t\t\t\t\tManager( void );\r\n\t\r\n\tstatic\tTsk::Hook< Manager >::Code\ts_start_render_code;\r\n\tstatic\tTsk::Hook< Manager >::Code\ts_end_render_code;\r\n\tstatic\tTsk::Task< Manager >::Code\ts_timer_code;\r\n\r\n\tTsk::Hook< Manager >*\t\tm_render_start_hook;\r\n\tTsk::Hook< Manager >*\t\tm_render_end_hook;\r\n\tTsk::Task< Manager >*\t\tm_timer_task;\r\n\r\n\tvoid\t\t\t\t\t\tstart_engine( void );\r\n\tvoid\t\t\t\t\t\tstop_engine( void );\r\n\t\r\n//\tMetrics*\t\t\t\t\tm_metrics;\r\n\tbool\t\t\t\t\t\tm_metrics_active;\r\n\tbool\t\t\t\t\t\tm_vram_viewer_active;\r\n\tbool\t\t\t\t\t\tm_trivial_far_z_clip;\r\n\r\n\r\n\tuint32\t\t\t\t\t\tm_min_vblank_wait;\r\n\tTmr::Time\t\t\t\t\tm_time;\t// used by other graphics system to update displays\r\n\t\t\t\t\t\t\t\t\t\t// This is used instead of GetTime() because this will\r\n\t\t\t\t\t\t\t\t\t\t// stop incrementing when the game is paused\r\n\t\r\n\tDeclareSingletonClass(Manager)\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\tManager::ToggleVRAMViewer( void )\r\n{\r\n\t\r\n\t\r\n\tm_vram_viewer_active = !m_vram_viewer_active;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\tManager::SetMinVblankWait( int num_vblanks )\r\n{\r\n\tm_min_vblank_wait = num_vblanks;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n#endif\t// __GFX_GFXMAN_H\r\n"
  },
  {
    "path": "Code/Gfx/gfxutils.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       GfxUtils.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  02/01/2001\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/gfxutils.h>\r\n\r\n#include <core/math.h>\r\n#include <core/math/vector.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   PrivateFunctions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid RGBtoHSV( float r, float g, float b, float *h, float *s, float *v )\r\n{\r\n\tfloat min, max, delta;\r\n\tmin = Mth::Min3( r, g, b );\r\n\tmax = Mth::Max3( r, g, b );\r\n\t*v = max;\t\t\t\t// v\r\n\tdelta = max - min;\r\n\tif( max != 0.0f )\r\n\t\t*s = delta / max;\t\t// s\r\n\telse {\r\n\t\t// r = g = b = 0\t\t// s = 0, v is undefined\r\n\t\t*s = 0.0f;\r\n\t\t*h = -1.0f;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// GJ:\r\n\tif (delta == 0.0f)\r\n\t\treturn;\r\n\r\n\tif( r == max )\r\n\t\t*h = ( g - b ) / delta;\t\t// between yellow & magenta\r\n\telse if( g == max )\r\n\t\t*h = 2.0f + ( b - r ) / delta;\t// between cyan & yellow\r\n\telse\r\n\t\t*h = 4.0f + ( r - g ) / delta;\t// between magenta & cyan\r\n\t*h *= 60.0f;\t\t\t\t// degrees\r\n\tif( *h < 0.0f )\r\n\t\t*h += 360.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid HSVtoRGB( float *r, float *g, float *b, float h, float s, float v )\r\n{\r\n\tint i;\r\n\tfloat f, p, q, t;\r\n\tif( s == 0.0f ) {\r\n\t\t// achromatic (grey)\r\n\t\t*r = *g = *b = v;\r\n\t\treturn;\r\n\t}\r\n\th /= 60.0f;\t\t\t// sector 0 to 5\r\n\ti = (int)h;\t\t\t// basically, the floor\r\n\tf = h - i;\t\t\t// factorial part of h\r\n\tp = v * ( 1.0f - s );\r\n\tq = v * ( 1.0f - s * f );\r\n\tt = v * ( 1.0f - s * ( 1.0f - f ) );\r\n\tswitch( i ) {\r\n\t\tcase 0:\r\n\t\t\t*r = v;\r\n\t\t\t*g = t;\r\n\t\t\t*b = p;\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\t*r = q;\r\n\t\t\t*g = v;\r\n\t\t\t*b = p;\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\t*r = p;\r\n\t\t\t*g = v;\r\n\t\t\t*b = t;\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\t*r = p;\r\n\t\t\t*g = q;\r\n\t\t\t*b = v;\r\n\t\t\tbreak;\r\n\t\tcase 4:\r\n\t\t\t*r = t;\r\n\t\t\t*g = p;\r\n\t\t\t*b = v;\r\n\t\t\tbreak;\r\n\t\tdefault:\t\t// case 5:\r\n\t\t\t*r = v;\r\n\t\t\t*g = p;\r\n\t\t\t*b = q;\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat FRAMES_TO_TIME(int frames)\r\n{\r\n\treturn (frames / 60.0f);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint TIME_TO_FRAMES(float time)\r\n{\r\n\treturn (int)(time * 60.0f + 0.5f);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid GetModelFromFileName ( char* filename, char* pModelNameBuf )\r\n{\r\n\tchar* pModelName = NULL;\r\n\twhile (*filename)\r\n\t{\r\n\t\tif (*filename == '\\\\' || *filename == '/')\r\n\t\t{\r\n\t\t\tpModelName = filename + 1;\r\n\t\t}\r\n\t\tfilename++;\r\n\t}\r\n\r\n\tDbg_MsgAssert ( pModelName,( \"Not full path name\" ));\r\n\r\n\tstrcpy(pModelNameBuf, pModelName);\r\n\r\n\t// strip out extension\r\n\tfor (unsigned int i = 0; i < strlen(pModelNameBuf); i++)\r\n\t{\r\n\t\tif (pModelNameBuf[i] == '.')\r\n\t\t{\r\n\t\t\tpModelNameBuf[i] = 0;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool GetScaleFromParams( Mth::Vector* pScaleVector, Script::CStruct* pParams )\r\n{\r\n\tif ( pParams->ContainsComponentNamed( CRCD(0x13b9da7b,\"scale\") ) )\r\n\t{\r\n\t\tfloat scaleValue;\r\n\t\tif ( pParams->GetFloat( CRCD(0x13b9da7b,\"scale\"), &scaleValue, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\t*pScaleVector = Mth::Vector( scaleValue, scaleValue, scaleValue );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse if ( pParams->GetVector( CRCD(0x13b9da7b,\"scale\"), pScaleVector, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Scale should be either a float or a vector\" ) );\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tbool xFound = pParams->GetFloat( CRCD(0x7323e97c,\"x\"), &(*pScaleVector)[X], false );\r\n\tbool yFound = pParams->GetFloat( CRCD(0x424d9ea,\"y\"), &(*pScaleVector)[Y], false );\r\n\tbool zFound = pParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &(*pScaleVector)[Z], false );\r\n\r\n\treturn ( xFound || yFound || zFound );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool GetLoopingTypeFromParams( Gfx::EAnimLoopingType* pLoopingType, Script::CStruct* pParams )\r\n{\r\n\t*pLoopingType = Gfx::LOOPING_HOLD;\r\n\t\r\n\tif ( pParams->ContainsFlag( CRCD(0x4f792e6c,\"Cycle\") ) )\r\n\t{\r\n\t\t*pLoopingType=Gfx::LOOPING_CYCLE;\r\n\t}\r\n\telse if ( pParams->ContainsFlag( CRCD(0x3153e314,\"PingPong\") ) )\r\n\t{\r\n\t\t*pLoopingType=Gfx::LOOPING_PINGPONG;\r\n\t}\r\n\telse if ( pParams->ContainsFlag( CRCD(0x6d941203,\"Wobble\") ) )\r\n\t{\r\n\t\t*pLoopingType=Gfx::LOOPING_WOBBLE;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool GetTimeFromParams( float* pStart, float* pEnd, float Current, float Duration, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tfloat From = 0.0f;\r\n\tfloat To = Duration;\r\n\r\n\tuint32 FromChecksum=0;\r\n\tif ( pParams->GetChecksum( CRCD(0x46e55e8f,\"From\"), &FromChecksum ) )\r\n\t{\r\n\t\tswitch (FromChecksum)\r\n\t\t{\r\n\t\tcase 0x6086aa70: // Start\r\n\t\t\tFrom=0;\r\n\t\t\tbreak;\r\n\t\tcase 0xff03cc4e: // End\r\n\t\t\tFrom=Duration;\r\n\t\t\tbreak;\r\n\t\tcase 0x230ccbf4: // Current\r\n\t\t\tFrom=Current;\r\n\t\t\tbreak;\r\n\t\tcase 0x617fe530: // Middle\r\n\t\t\tFrom=Duration / 2.0f;\r\n\t\t\tbreak;\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nUnrecognized value '%s' for From in PlayAnim\",pScript?pScript->GetScriptInfo():\"???\",Script::FindChecksumName(FromChecksum)));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\tuint32 ToChecksum=0;\r\n\tif (pParams->GetChecksum( CRCD(0x28782d3b,\"To\"), &ToChecksum) )\r\n\t{\r\n\t\tswitch (ToChecksum)\r\n\t\t{\r\n\t\tcase 0x6086aa70: // Start\r\n\t\t\tTo=0;\r\n\t\t\tbreak;\r\n\t\tcase 0xff03cc4e: // End\r\n\t\t\tTo=Duration;\r\n\t\t\tbreak;\r\n\t\tcase 0x230ccbf4: // Current\r\n\t\t\tTo=Current;\r\n\t\t\tbreak;\t\r\n\t\tcase 0x617fe530: // Middle\r\n\t\t\tTo=Duration / 2.0f;\r\n\t\t\tbreak;\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nUnrecognized value '%s' for To in PlayAnim\",pScript?pScript->GetScriptInfo():\"???\",Script::FindChecksumName(ToChecksum)));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\t// also check if From and To were specified as integers, in which case use units of 60ths.\r\n\tfloat FromFrames=0;\r\n\tif (pParams->GetFloat( CRCD(0x46e55e8f,\"From\"), &FromFrames ) )\r\n\t{\r\n\t\tif ( pParams->ContainsFlag( CRCD(0xd029f619,\"seconds\") ) )\r\n\t\t{\r\n\t\t\tFrom = FromFrames;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tFrom = Gfx::FRAMES_TO_TIME((int)FromFrames);\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tfloat ToFrames=0;\r\n\tif ( pParams->GetFloat( CRCD(0x28782d3b,\"To\"), &ToFrames ) )\r\n\t{\r\n\t\tif ( pParams->ContainsFlag( CRCD(0xd029f619,\"seconds\") ) )\r\n\t\t{\r\n\t\t\tTo = ToFrames;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tTo = Gfx::FRAMES_TO_TIME((int)ToFrames);\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( pParams->ContainsFlag( CRCD(0xf8cfd515,\"Backwards\") ) )\r\n\t{\r\n\t\tfloat Temp=From;\r\n\t\tFrom=To;\r\n\t\tTo=Temp;\r\n\t}\t\r\n\r\n\t*pStart = From;\r\n\t*pEnd = To;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStr::String GetModelFileName(const char* pName, const char* pExtension)\r\n{\r\n\tchar fullName[512];\r\n\r\n\tif ( strstr( pName, \"/\" ) || strstr( pName, \"\\\\\" ) )\r\n\t{\r\n\t\tDbg_MsgAssert( strstr( pName, \".\" ), ( \"Filename %s is missing extension\", pName ) ); \r\n\t\t\r\n\t\tsprintf( fullName, \"models\\\\%s\", pName ); \r\n\t}\r\n\telse\r\n\t{\r\n\t\tsprintf( fullName, \"models\\\\%s\\\\%s%s\", pName, pName, pExtension );\r\n\t}\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\t// replace all forward slashes with backslashes\r\n\tchar temp[512];\r\n\tstrcpy( temp, fullName );\r\n\tchar* pString = temp;\r\n\twhile ( *pString )\r\n\t{\r\n\t\tif ( *pString == '/' )\r\n\t\t{\r\n\t\t\t*pString = '\\\\';\r\n\t\t}\r\n\t\tpString++;\r\n\t}\r\n\t// look for double backslashes, which are bad\r\n\tDbg_MsgAssert( !strstr( temp, \"\\\\\\\\\" ), ( \"Filename %s has double backslash\", temp ) ); \r\n#endif\r\n\r\n\treturn Str::String( fullName );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid GetModelFileName(const char* pName, const char* pExtension, char* pTarget)\r\n{\r\n\tif ( strstr( pName, \"/\" ) || strstr( pName, \"\\\\\" ) )\r\n\t{\r\n\t\tDbg_MsgAssert( strstr( pName, \".\" ), ( \"Filename %s is missing extension\", pName ) ); \r\n\t\t\r\n\t\tDbg_MsgAssert( pTarget, ( \"No target buffer\" ) );\r\n\t\tsprintf( pTarget, \"models\\\\%s\", pName ); \r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert( pTarget, ( \"No target buffer\" ) );\r\n\t\tsprintf( pTarget, \"models\\\\%s\\\\%s%s\", pName, pName, pExtension );\r\n\t}\r\n\t\r\n#ifdef __NOPT_ASSERT__\r\n\t// replace all forward slashes with backslashes\r\n\tchar temp[512];\r\n\tstrcpy( temp, pTarget );\r\n\tchar* pString = temp;\r\n\twhile ( *pString )\r\n\t{\r\n\t\tif ( *pString == '/' )\r\n\t\t{\r\n\t\t\t*pString = '\\\\';\r\n\t\t}\r\n\t\tpString++;\r\n\t}\r\n\t// look for double backslashes, which are bad\r\n\tDbg_MsgAssert( !strstr( temp, \"\\\\\\\\\" ), ( \"Filename %s has double backslash\", temp ) ); \r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n"
  },
  {
    "path": "Code/Gfx/gfxutils.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       GfxUtils.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  02/01/2001\r\n//****************************************************************************\r\n\r\n#ifndef __GFX_UTILS_H\r\n#define __GFX_UTILS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <core/math/math.h>\r\n#include <core/string/cstring.h>\r\n\r\n#include <gfx/bonedanimtypes.h>\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mth\r\n{\r\n\tclass Vector;\r\n};\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n};\r\n\r\nnamespace Gfx\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid RGBtoHSV( float r, float g, float b, float *h, float *s, float *v );\r\nvoid HSVtoRGB( float *r, float *g, float *b, float h, float s, float v );\r\n\r\nvoid inlineRGBtoHSV( float r, float g, float b, float *h, float *s, float *v );\r\nvoid inlineHSVtoRGB( float *r, float *g, float *b, float h, float s, float v );\r\n\r\n// some time conversion functions\r\nfloat FRAMES_TO_TIME(int frames);\r\nint TIME_TO_FRAMES(float time);\r\n\r\nvoid \t\tGetModelFromFileName( char* filename, char* pModelNameBuf );\r\nbool \t\tGetScaleFromParams( Mth::Vector* pScaleVector, Script::CStruct* pParams );\r\nbool \t\tGetLoopingTypeFromParams( Gfx::EAnimLoopingType* pLoopingType, Script::CStruct* pParams );\r\nbool \t\tGetTimeFromParams( float* pStart, float* pEnd, float Current, float Duration, Script::CStruct* pParams, Script::CScript* pScript );\r\nStr::String\tGetModelFileName(const char* pName, const char* pExt);\r\nvoid    \tGetModelFileName(const char* pName, const char* pExt, char* pTargetBuffer);\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void inlineRGBtoHSV( float r, float g, float b, float &h, float &s, float &v )\r\n{\r\n\tfloat min, max, delta;\r\n\tmin = Mth::Min3( r, g, b );\r\n\tmax = Mth::Max3( r, g, b );\r\n\tv = max;\t\t\t\t// v\r\n\tdelta = max - min;\r\n\tif( max != 0.0f )\r\n\t\ts = delta / max;\t\t// s\r\n\telse {\r\n\t\t// r = g = b = 0\t\t// s = 0, v is undefined\r\n\t\ts = 0.0f;\r\n\t\th = -1.0f;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// GJ:\r\n\tif (delta == 0.0f)\r\n\t\treturn;\r\n\r\n\tif( r == max )\r\n\t\th = ( g - b ) / delta;\t\t// between yellow & magenta\r\n\telse if( g == max )\r\n\t\th = 2.0f + ( b - r ) / delta;\t// between cyan & yellow\r\n\telse\r\n\t\th = 4.0f + ( r - g ) / delta;\t// between magenta & cyan\r\n\th *= 60.0f;\t\t\t\t// degrees\r\n\tif( h < 0.0f )\r\n\t\th += 360.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void inlineHSVtoRGB( float &r, float &g, float &b, float h, float s, float v )\r\n{\r\n\tif( s == 0.0f ) {\r\n\t\t// achromatic (grey)\r\n\t\tr = g = b = v;\r\n\t\treturn;\r\n\t}\r\n\r\n\tint i;\r\n\tfloat f, p, q, t;\r\n\r\n\th *= (1.0f/60.0f);\t// sector 0 to 5\r\n\ti = (int)h;\t\t\t// basically, the floor\r\n\tf = h - i;\t\t\t// factorial part of h\r\n\tp = v * ( 1.0f - s );\r\n\tq = v * ( 1.0f - s * f );\r\n\tt = v * ( 1.0f - s * ( 1.0f - f ) );\r\n\tswitch( i ) {\r\n\t\tcase 0:\r\n\t\t\tr = v;\r\n\t\t\tg = t;\r\n\t\t\tb = p;\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tr = q;\r\n\t\t\tg = v;\r\n\t\t\tb = p;\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tr = p;\r\n\t\t\tg = v;\r\n\t\t\tb = t;\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tr = p;\r\n\t\t\tg = q;\r\n\t\t\tb = v;\r\n\t\t\tbreak;\r\n\t\tcase 4:\r\n\t\t\tr = t;\r\n\t\t\tg = p;\r\n\t\t\tb = v;\r\n\t\t\tbreak;\r\n\t\tdefault:\t\t// case 5:\r\n\t\t\tr = v;\r\n\t\t\tg = p;\r\n\t\t\tb = q;\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n} // namespace Gfx\r\n\r\n#endif // __GFX_UTILS_H"
  },
  {
    "path": "Code/Gfx/nx.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// NX.CPP - Platform independent interface to the platfrom specific engine code \r\n\r\n#include <gfx/nx.h>\r\n\r\n#include <core/debug.h>\r\n#include <core/string/stringutils.h>\r\n\r\n#include <gel/objman.h>\r\n                               \r\n#include <gel/scripting/script.h>\t   \r\n#include <gel/scripting/struct.h>\t   \r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/nxfont.h>\r\n#include <gfx/nxmesh.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/nxsector.h>\r\n#include <gfx/nxtexman.h>\r\n#include <gfx/nxviewman.h>\r\n#include <gfx/nxwin2d.h>\r\n#include <gfx/nxmiscfx.h>\r\n#include <gfx/nxparticlemgr.h>\r\n#include <gfx/nxquickanim.h>\r\n#include <gfx/nxlightman.h>\r\n#include <gfx\\nxweather.h>\r\n#ifdef __PLAT_NGC__\r\n#include <gfx\\ngc\\p_nxscene.h>\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n//#include <sk/modules/skate/skate.h>\t\t// For getting list of movable objects\r\n\r\n#include <sys/replay/replay.h>\r\n\r\n#ifdef\t__PLAT_NGPS__\r\nnamespace NxPs2\r\n{\r\n\textern int geom_stats_total;\r\n\textern int geom_stats_inactive ;\r\n\textern int geom_stats_sky;\r\n\textern int geom_stats_transformed;\r\n\textern int geom_stats_skeletal;\r\n\textern int geom_stats_camera_sphere;\r\n\textern int geom_stats_culled;\r\n\textern int geom_stats_leaf_culled;\r\n\textern int geom_stats_clipcull;\r\n\textern int geom_stats_boxcheck;\r\n\textern int geom_stats_occludecheck;\r\n\textern int geom_stats_occluded;\r\n\textern int geom_stats_colored;\r\n\textern int geom_stats_leaf;\r\n\textern int geom_stats_wibbleUV;\r\n\textern int geom_stats_wibbleVC;\r\n\textern int geom_stats_sendcontext;\r\n\textern int geom_stats_sorted;\r\n\textern int geom_stats_shadow;\r\n\r\n\textern bool DoLetterbox;\r\n}\r\n#endif\r\n\r\nnamespace\tNx\r\n{\r\n\r\n///////////////////////////////////////////////////////////////////\r\n// Static definitions\r\n\r\nCScene *\t\t\t\t\t\tCEngine::sp_loaded_scenes[CEngine::MAX_LOADED_SCENES];\r\nLst::HashTable< CParticle >*\tCEngine::p_particle_table = NULL;\r\nuint32\t\t\t\t\t\t\tCEngine::s_next_avail_sector_checksum = 1;\t// 0 is invalid\r\nuint32\t\t\t\t\t\t\tCEngine::s_render_mode;\r\nuint32\t\t\t\t\t\t\tCEngine::s_wireframe_mode;\r\nuint32\t\t\t\t\t\t\tCEngine::s_screen_blur;\r\nuint32\t\t\t\t\t\t\tCEngine::s_debug_ignore_1;\r\nuint32\t\t\t\t\t\t\tCEngine::s_debug_ignore_0;\r\nObj::CGeneralManager*\t\t\tCEngine::sp_moving_object_manager;\r\nCImposterManager*\t\t\t\tCEngine::mp_imposter_manager\t= NULL;\r\nCNewParticleManager*\t\t\tCEngine::mp_particle_manager\t= NULL;\r\nCWeather*\t\t\t\t\t\tCEngine::mp_weather = NULL;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* get a sector pointer, based on the checksum of the name\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSector\t*\t\tCEngine::sGetSector(uint32 sector_checksum)\r\n{\r\n\tfor (int i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t{\r\n\t\tif (sp_loaded_scenes[i])\r\n\t\t{\r\n\t\t\tCSector *ret_sector = sp_loaded_scenes[i]->GetSector(sector_checksum);\r\n\t\t\tif (ret_sector) return ret_sector;\r\n\t\t}\r\n\t}\r\n\r\n\t// If we got here, we didn't find anything\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCEngine::sStartEngine()\r\n{\t\t\r\n\tfor (int i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t{\r\n\t\tDbg_Assert(!sp_loaded_scenes[i]);\t// Make sure it was deallocated\r\n\t}\r\n\r\n\t// Allocate CTexts and CWindow2Ds\r\n\tNx::CTextMan::sAllocTextPool();\r\n\tNx::CWindow2DManager::sAllocWindow2DPool();\r\n\r\n\tCViewportManager::sSetScreenAspect(4.0f/3.0f);\r\n\tCViewportManager::sSetDefaultAngle( Script::GetFloat(\"camera_fov\") );\r\n\tCViewportManager::sSetScreenAngle( 0.0f);\t\t// set to default\r\n\r\n\tCViewportManager::sInit();\r\n\tCViewportManager::sSetScreenMode(vONE_CAM);\r\n\r\n\t//sSetMaxMultipassDistance(3000.0f);\r\n\r\n\t// Allocate particle system table\r\n\tp_particle_table = new Lst::HashTable<CParticle>( 6 ); \r\n\t\t\t\t\t\t \r\n\t// Create the imposter manager.\r\n\tmp_imposter_manager = new CImposterManager;\r\n\r\n\t// Startup effects allocations.\r\n\tNx::MiscFXInitialize();\r\n\r\n\ts_plat_start_engine();\t\t\t\t\r\n\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCEngine::sSuspendEngine()\r\n{\r\n\tprintf (\"STUB: SuspendEngine\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCEngine::sResumeEngine()\r\n{\r\n\tprintf (\"STUB: ResumeEngine\\n\");\r\n}\r\n\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCEngine::sPreRender()\r\n{\r\n\ts_plat_pre_render();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCEngine::sPostRender()\r\n{\r\n\ts_plat_post_render();\r\n\r\n\t// Clear away any old cameras\r\n\tCViewportManager::sDeleteMarkedCameras();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCEngine::sRenderWorld()\r\n{\r\n\tprocess_particles( Tmr::FrameLength() ); \r\n\r\n\tScreenFlashUpdate();\r\n\tTextureSplatUpdate();\r\n\tShatterUpdate();\r\n\t\r\n\tCLightManager::sUpdateVCLights();\r\n\t\r\n\ts_plat_render_world();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCScene\t*\t\tCEngine::sCreateScene(const char *p_name, CTexDict *p_tex_dict,\r\n\t\t\t\t\t\t\t\t\t  bool add_super_sectors)\r\n{\r\n\tCScene *p_created_scene = s_plat_create_scene(p_name, p_tex_dict, add_super_sectors);\r\n\r\n\tp_created_scene->SetID(Script::GenerateCRC(p_name)); \t// store the checksum of the scene name\r\n\r\n\tp_created_scene->SetTexDict(p_tex_dict);\t\t\t\t\t  \r\n\r\n\t// Put in scene array\r\n\tint i;\r\n\tfor (i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t{\r\n\t\tif (!sp_loaded_scenes[i])\r\n\t\t{\r\n\t\t\tsp_loaded_scenes[i] = p_created_scene;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert(i < MAX_LOADED_SCENES, (\"Have more than MAX_LOADED SCENES\"));\r\n\r\n\treturn p_created_scene;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCScene\t*\t\tCEngine::sLoadScene(const char *p_name, CTexDict *p_tex_dict,\r\n\t\t\t\t\t\t\t\t\tbool add_super_sectors, bool is_sky, bool is_dictionary, bool is_net)\r\n{\r\n\t// first expand the scene file name out to include the path\r\n\t// the level directory, and the platform specific extension\r\n\t// e.g.,  \"can\" become levels\\can\\can.scn.ps2\r\n\r\n\t\r\n\r\n\tchar\tfull_name[128];\r\n#ifdef __PLAT_NGPS__\r\n\tsprintf(full_name,\"levels\\\\%s\\\\%s%s.geom.%s\",p_name,p_name,is_net?\"_net\":\"\",sGetPlatformExtension());\r\n#else\r\n\tsprintf(full_name,\"levels\\\\%s\\\\%s%s.scn.%s\",  p_name,p_name,is_net?\"_net\":\"\",sGetPlatformExtension());\r\n#endif\r\n\r\n\tMem::PushMemProfile((char*)full_name);\r\n\r\n\tCScene *loaded_scene = s_plat_load_scene(full_name, p_tex_dict, add_super_sectors, is_sky, is_dictionary);\r\n\r\n\tloaded_scene->SetID(Script::GenerateCRC(p_name)); \t// store the checksum of the scene name\r\n\r\n\tloaded_scene->SetTexDict(p_tex_dict);\t\t\t\t\t  \r\n\t\t\t\t\t  \r\n\t// Do post-load processing\r\n\tloaded_scene->PostLoad(full_name);\r\n\r\n\t// Put in scene array\r\n\tint i;\r\n\tfor (i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t{\r\n\t\tif (!sp_loaded_scenes[i])\r\n\t\t{\r\n\t\t\tsp_loaded_scenes[i] = loaded_scene;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert(i < MAX_LOADED_SCENES, (\"Have more than MAX_LOADED SCENES\"));\r\n\t\r\n\tMem::PopMemProfile(/*p_name*/);\r\n\r\n\treturn loaded_scene;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCScene\t*\t\tCEngine::sAddScene(const char *p_scene_name, const char *p_filename)\r\n{\r\n\t// first expand the scene file name out to include the path\r\n\t// the level directory, and the platform specific extension\r\n\t// e.g.,  \"can\" become levels\\can\\can.scn.ps2\r\n\r\n\tchar\tfull_name[128];\r\n#ifdef __PLAT_NGPS__\r\n\tsprintf(full_name,\"levels\\\\%s\\\\%s.geom.%s\",p_filename,p_filename,sGetPlatformExtension());\r\n#else\r\n\tsprintf(full_name,\"levels\\\\%s\\\\%s.scn.%s\",p_filename,p_filename,sGetPlatformExtension());\r\n#endif\r\n\r\n\tchar\ttexture_dict_name[128];\r\n\tsprintf(texture_dict_name,\"levels\\\\%s\\\\%s.tex\",p_filename,p_filename);\r\n\r\n\tCScene *p_scene = sGetScene(Script::GenerateCRC(p_scene_name));\r\n\r\n\tDbg_MsgAssert(p_scene, (\"sAddScene(): Can't find existing scene %s\", p_scene_name));\r\n\r\n\tDbg_Message(\"Adding to scene %s with file %s\", p_scene_name, full_name);\r\n\r\n\t// Check if we need to unload old one\r\n\tif (strcmp(p_scene->GetAddSceneFilename(), full_name) == 0)\r\n\t{\r\n\t\tDbg_Message(\"Unloading old added scene %s\", full_name);\r\n\t\tp_scene->UnloadAddScene();\r\n\r\n\t\tNx::CTexDict * p_old_tex_dict = Nx::CTexDictManager::sGetTextureDictionary(Crc::GenerateCRCFromString(texture_dict_name));\r\n\t\tif (p_old_tex_dict)\t\t// See if we previously loaded this\r\n\t\t{\r\n\t\t\tDbg_Message(\"Unloading old texture dictionary %s\", texture_dict_name);\r\n\t\t\tNx::CTexDictManager::sUnloadTextureDictionary(p_old_tex_dict);\r\n\t\t} else {\r\n\t\t\tDbg_Assert(0);\r\n\t\t}\r\n\t}\r\n\r\n\tNx::CTexDict * p_tex_dict = Nx::CTexDictManager::sLoadTextureDictionary(texture_dict_name,true);\r\n\tDbg_MsgAssert(p_tex_dict, (\"ERROR loading tex dict for %s\\n\",texture_dict_name));\r\n\r\n\tDbg_Message(\"Adding to scene %s with file %s\", p_scene_name, full_name);\r\n\r\n\ts_plat_add_scene(p_scene, full_name);\r\n\r\n\t// Do post-add processing\r\n\tp_scene->PostAdd(full_name, p_tex_dict);\r\n\r\n\treturn p_scene;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCEngine::sToggleAddScenes()\r\n{\r\n\tfor (int i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t{\r\n\t\tif (sp_loaded_scenes[i])\r\n\t\t{\r\n\t\t\tsp_loaded_scenes[i]->ToggleAddScene();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCEngine::sUnloadScene(CScene *p_scene)\r\n{\r\n\r\n\t// Wait for the frame to finish rendering before we unload the scene\r\n\t// otherwise we might be trying to render something that is no longer there\t\r\n\t// (Without this line, the engine can hang when doing a quickview, and seems\r\n\t// to be more crashy when using particle systems)\r\n\tNx::CEngine::sFinishRendering();\t\r\n\t\r\n\t// Remove Incremental Data first\r\n\t// (Doesn't work yet because the replace CSectors are lost and the texture dictionary is still around)\r\n\tp_scene->UnloadAddScene();\r\n\r\n\t// remove platform specific assets\r\n\tif (s_plat_unload_scene(p_scene))\r\n\t{\r\n//#ifdef __PLAT_NGC__\r\n//\t\tCNgcScene *p_ngc_scene = (CNgcScene*)p_scene;\r\n//\t\tNxNgc::sScene * p_engine_scene = p_ngc_scene->GetEngineScene();\r\n//#endif\t\t// __PLAT_NGC__\r\n\r\n\t\t// delete the scene object itself. \r\n\t\tdelete\tp_scene;\r\n\r\n//#ifdef __PLAT_NGC__\r\n//\t\t// Get the engine specific scene data and pass it to the engine to delete.\r\n//\t\tNxNgc::DeleteScene( p_engine_scene );\r\n//\t\tp_ngc_scene->SetEngineScene( NULL );\r\n//#endif\t\t// __PLAT_NGC__\r\n\r\n\t\t// and remove it from the list of scenes\r\n\t\tfor (int i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t\t{\r\n\t\t\tif (sp_loaded_scenes[i] == p_scene)\r\n\t\t\t{\r\n\t\t\t\tsp_loaded_scenes[i] = NULL;\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_Error(\"Could not find CScene to unload\");\r\n\treturn false;\r\n}\r\n\r\n\r\n// (Not working yet!!!)\t\t\t\t\t\t\t  \r\n// This is useful function to be only used during development\r\n// it attempts to reload just the .scn part of a level\r\n// without reloading the texture dictionary (assumes it stays the same)\r\n// and without reloading the collision (assumes you are in viewer mode, and don't need it)  \t\t\t\t  \r\nbool\t\t\tCEngine::sQuickReloadGeometry(const char *p_scene_name)\r\n{\t\r\n\t// find the scene\r\n\tNx::CScene\t*p_scene = sGetScene(p_scene_name);\r\n\t\r\n\tif (p_scene)\r\n\t{\r\n\t\tCTexDict *p_tex_dict = p_scene->GetTexDict();\r\n\t\tbool\tis_sky = p_scene->IsSky();\r\n\t\t\r\n\t\tsUnloadScene(p_scene);\r\n\t\t/*Nx::CScene\t*p_new_scene = */ sLoadScene(p_scene_name,p_tex_dict,!is_sky,is_sky);\r\n//\t\tsUnloadScene(p_scene);\r\n//\t\tp_new_scene = sLoadScene(p_scene_name,p_tex_dict,!is_sky,is_sky);\r\n\t\t\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n// Given the id of a scene, then return the CScene that has this id\r\n// returns NULL if scene not found\r\nCScene *\t\tCEngine::sGetScene(uint32 id)\r\n{\r\n\tfor (int i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t{\r\n\t\tif (sp_loaded_scenes[i] && (sp_loaded_scenes[i]->GetID() == id))\r\n\t\t{\r\n\t\t\treturn sp_loaded_scenes[i];\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\nCScene *\t\tCEngine::sGetScene(const char *p_name)\r\n{\r\n\treturn\t\tsGetScene(Script::GenerateCRC(p_name));\r\n}\r\n\r\n\r\n// Get the last non-sky scene.  Kind of application dependent, as it assumes \r\n// that the \"Main\" scene is the last non sky scene\r\n// but that's a pretty safe bet for what we are doing now.\r\n// (Mick:  I'm only using this for the \"Disco\" cheat in THPS4)\r\n// (Mick: now this function is used in ParseNodeArray, so I had to change this from\r\n// using the first non-sky to the last non-sky, so now it's even dodgier....\r\n// we need a better way of saying what is the \"main\" scene\r\nCScene *  \t\tCEngine::sGetMainScene()\r\n{\r\n\tfor (int i = MAX_LOADED_SCENES-1; i >= 0; i--)\r\n\t{\r\n\t\tif (sp_loaded_scenes[i] && !sp_loaded_scenes[i]->IsSky())\r\n\t\t{\r\n\t\t\treturn sp_loaded_scenes[i];\r\n\t\t}\r\n\t}\r\n\treturn NULL;\t\r\n}\r\n\r\n// Get the first sky scene.\r\nCScene *  \t\tCEngine::sGetSkyScene()\r\n{\r\n\tfor (int i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t{\r\n\t\tif (sp_loaded_scenes[i] && sp_loaded_scenes[i]->IsSky())\r\n\t\t{\r\n\t\t\treturn sp_loaded_scenes[i];\r\n\t\t}\r\n\t}\r\n\treturn NULL;\t\r\n}\r\n\r\n  \r\n// Mick:::::   ........  \r\n// a temporary utility function\r\n// unloads all loaded scenes, (level and sky)\r\n// and also unloads the texture dictionaries\r\n// (or at least decrements the reference counts)\r\nbool\t\tCEngine::sUnloadAllScenesAndTexDicts()\r\n{\r\n\tfor (int i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t{\r\n\t\tCScene * p_scene = sp_loaded_scenes[i];\r\n\t\tif (p_scene)\r\n\t\t{\r\n\t\t\tCTexDict *p_tex_dict = p_scene->GetTexDict();\r\n\r\n    \t\tsUnloadScene(p_scene);\r\n\t\t\t// must unload dictionary after scene\r\n\t\t\tif (p_tex_dict)\r\n\t\t\t{\r\n\t\t\t\tCTexDictManager::sUnloadTextureDictionary(p_tex_dict);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Remove occlusion polys.\r\n\ts_plat_remove_all_occlusion_polys();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSprite *\t\tCEngine::sCreateSprite(CWindow2D *p_window)\r\n{\r\n\treturn s_plat_create_sprite(p_window);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCEngine::sDestroySprite(CSprite *p_sprite)\r\n{\r\n\treturn s_plat_destroy_sprite(p_sprite);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTextured3dPoly *CEngine::sCreateTextured3dPoly()\r\n{\r\n\treturn s_plat_create_textured_3d_poly();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CEngine::sDestroyTextured3dPoly(CTextured3dPoly *p_poly)\r\n{\r\n\treturn s_plat_destroy_textured_3d_poly(p_poly);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTexture *CEngine::sCreateRenderTargetTexture( int width, int height, int depth, int z_depth )\r\n{\r\n\treturn s_plat_create_render_target_texture( width, height, depth, z_depth );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CEngine::sProjectTextureIntoScene( Nx::CTexture *p_texture, Nx::CModel *p_model, Nx::CScene *p_scene )\r\n{\r\n\t// usually we don't want to know the scene, so we pass in NULL\r\n\t// and let the engine figure it out\r\n\t// if we have multiple scenes, then we would need to figure this out externally\r\n\r\n\tif (!p_scene)\r\n\t{\r\n\t\t// find the first non-sky scene\r\n\t\tfor (int i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t\t{\r\n\t\t\tif (sp_loaded_scenes[i] && !sp_loaded_scenes[i]->IsSky())\r\n\t\t\t{\r\n\t\t\t\tp_scene = sp_loaded_scenes[i];\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// It no longer matters if the scene is NULL.\r\n\ts_plat_project_texture_into_scene( p_texture, p_model, p_scene );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CEngine::sSetProjectionTextureCamera( Nx::CTexture *p_texture, Gfx::Camera *p_camera )\r\n{\r\n\ts_plat_set_projection_texture_camera( p_texture, p_camera );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::sStopProjectionTexture( Nx::CTexture *p_texture )\r\n{\r\n\ts_plat_stop_projection_texture( p_texture );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::sAddOcclusionPoly( uint32 num_verts, Mth::Vector *p_vert_array, uint32 checksum )\r\n{\r\n\ts_plat_add_occlusion_poly( num_verts, p_vert_array, checksum );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::sEnableOcclusionPoly( uint32 checksum, bool enable )\r\n{\r\n\ts_plat_enable_occlusion_poly( checksum, enable );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEngine::sDebugCheckForHoles()\r\n{\r\n\r\n\tTmr::Time start_time, end_time;\r\n\tstart_time = Tmr::GetTime();\r\n\r\n\tfor (int i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t{\r\n\t\tif (sp_loaded_scenes[i] && !sp_loaded_scenes[i]->IsSky())\r\n\t\t{\r\n\t\t\tsp_loaded_scenes[i]->DebugCheckForHoles();\r\n\t\t}\r\n\t}\r\n\r\n\tend_time = Tmr::GetTime();\r\n\r\n\tDbg_Message(\"CheckForHoles() took %d msecs\", end_time - start_time);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCModel*\t\t\tCEngine::sInitModel(void)\r\n{\r\n\treturn s_plat_init_model();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCEngine::sUninitModel(CModel* pModel)\r\n{\r\n\t// Wait for any async rendering to finish before we proceed\t\r\n#ifndef __PLAT_NGC__\r\n\tsFinishRendering();\r\n#endif\t\t// __PLAT_NGC__\r\n\treturn s_plat_uninit_model(pModel);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGeom*\t\t\tCEngine::sInitGeom()\r\n{\r\n\treturn s_plat_init_geom();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCEngine::sUninitGeom(CGeom* pGeom)\r\n{\r\n\t// Wait for any async rendering to finish before we proceed\t\r\n#ifndef __PLAT_NGC__\r\n\tsFinishRendering();\r\n#endif\t\t// __PLAT_NGC__\r\n\treturn s_plat_uninit_geom(pGeom);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCQuickAnim*\t\tCEngine::sInitQuickAnim(void)\r\n{\r\n\treturn s_plat_init_quick_anim();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\r\nvoid\t\t\tCEngine::sUninitQuickAnim(CQuickAnim* pQuickAnim)\r\n{\r\n\ts_plat_uninit_quick_anim(pQuickAnim);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMesh*\t\t\tCEngine::sLoadMesh(const char* pFileName, uint32 texDictOffset, bool forceTexDictLookup, bool doShadowVolume)\r\n{\r\n\tchar baseName[512];\r\n\tstrcpy( baseName, pFileName );\r\n\r\n\tchar* pEnd;\r\n\r\n\tbool foundSkin = false;\r\n\tpEnd = strstr( baseName, \".skin\" );\r\n\tfoundSkin = ( pEnd != NULL );\r\n\tif ( foundSkin )\r\n\t{\r\n\t\t*pEnd = NULL;\r\n\t}\r\n\r\n\tbool foundModel = false;\r\n\tpEnd = strstr( baseName, \".mdl\" );\r\n\tfoundModel = ( pEnd != NULL );\r\n\tif ( foundModel )\r\n\t{\r\n\t\t*pEnd = NULL;\r\n\t}\r\n\r\n\tDbg_Assert( foundSkin || foundModel );\r\n\r\n\tchar meshName[512];\r\n\tStr::LowerCase( meshName );\r\n\tsprintf( meshName, \"%s.%s.%s\", baseName, foundSkin ? \"skin\" : \"mdl\", sGetPlatformExtension() );\r\n\r\n\tchar textureName[512];\r\n\tsprintf( textureName, \"%s.tex\", baseName );\r\n\r\n\t// brad - special case for boardshop boards.\r\n\t// (ideally, this would be coming in from a\r\n\t// higher level, such as with the\r\n\t// \"forceTexDictLookup\" flag\r\n\tif ( strstr( meshName, \"thps4board_01\" ) )\r\n\t{\r\n\t\tforceTexDictLookup = true;\r\n\t}\r\n\t\r\n\tNx::CTexDict* pTexDict = Nx::CTexDictManager::sLoadTextureDictionary(textureName, false, texDictOffset, foundSkin, forceTexDictLookup);\r\n\tDbg_MsgAssert(pTexDict,(\"ERROR loading tex dict for %s\\n\",textureName));\r\n\r\n\tMem::PushMemProfile((char*)meshName);\t\r\n\tCMesh* p_mesh = s_plat_load_mesh(meshName, pTexDict, texDictOffset, foundSkin, doShadowVolume);\r\n\tMem::PopMemProfile(/*(char*)meshname*/);\t\r\n\treturn p_mesh;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMesh*\t\t\tCEngine::sLoadMesh(uint32 id, uint32* pModelData, int modelDataSize, uint8* pCASData, uint32 textureDictChecksum, uint32* pTextureData, int textureDataSize, uint32 textureDictOffset, bool isSkin, bool doShadowVolume )\r\n{\r\n\tDbg_MsgAssert( id != 0, ( \"invalid id checksum\" ) );\r\n\r\n\tbool forceTexDictLookup = false;\r\n\r\n\tNx::CTexDict* pTexDict = Nx::CTexDictManager::sLoadTextureDictionary(textureDictChecksum, pTextureData, textureDataSize, false, textureDictOffset, isSkin, forceTexDictLookup);\r\n\tDbg_MsgAssert(pTexDict,(\"ERROR loading tex dict from buffer\"));\r\n\r\n\tMem::PushMemProfile((char*)\"model_data_buffer\");\t\r\n\tCMesh*\tp_mesh = s_plat_load_mesh(id, pModelData, modelDataSize, pCASData, pTexDict, textureDictOffset, isSkin, doShadowVolume);\r\n\tMem::PopMemProfile(/*(char*)meshname*/);\t\r\n\treturn p_mesh;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tCEngine::sUnloadMesh(CMesh* pMesh)\r\n{\r\n\tCTexDict *p_tex_dict = pMesh->GetTextureDictionary();\r\n\t\r\n\tbool result = s_plat_unload_mesh(pMesh);\r\n\r\n\tCTexDictManager::sUnloadTextureDictionary( p_tex_dict );\r\n\r\n\treturn result;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCEngine::sSetMeshScalingParameters( SMeshScalingParameters* pParams )\r\n{\r\n\ts_plat_set_mesh_scaling_parameters( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Set the moving object manager.  Perviously we asked the skater module for \r\n// this, but now we are independent of Skate, so we have to be told\r\n\r\nvoid\tCEngine::sSetMovableObjectManager(Obj::CGeneralManager* p_object_manager)\r\n{\r\n\tDbg_MsgAssert(p_object_manager,(\"NULL Movable Object Manager\"));\r\n\tsp_moving_object_manager = p_object_manager;\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nLst::Head<Obj::CObject> & CEngine::sGetMovableObjects()\r\n{\r\n\r\n\tDbg_MsgAssert( sp_moving_object_manager, (\"NULL sp_moving_object_manager\"));\r\n\treturn sp_moving_object_manager->GetRefObjectList();\r\n}\r\n\r\nLst::HashTable< CParticle > * CEngine::sGetParticleTable()\r\n{\r\n\treturn p_particle_table;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSSec::Manager *\tCEngine::sGetNearestSuperSectorManager(Mth::Line &collision_line)\r\n{\r\n\t// For now, just return the first manager\r\n\tfor (int i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t{\r\n\t\tif (sp_loaded_scenes[i])\r\n\t\t{ \r\n\t\t\tSSec::Manager *p_man = sp_loaded_scenes[i]->GetSuperSectorManager();\r\n\t\t\tif (p_man) return p_man;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSSec::Manager *\tCEngine::sGetNearestSuperSectorManager(Mth::Vector &collision_point)\r\n{\r\n\t// For now, just return the first manager\r\n\tfor (int i = 0; i < MAX_LOADED_SCENES; i++)\r\n\t{\r\n\t\tif (sp_loaded_scenes[i])\r\n\t\t{ \r\n\t\t\tSSec::Manager *p_man = sp_loaded_scenes[i]->GetSuperSectorManager();\r\n\t\t\tif (p_man) return p_man;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\t\t\tCEngine::sGetUnusedSectorChecksum()\r\n{\r\n\t// Make sure this checksum isn't being used\r\n\twhile (sGetSector(s_next_avail_sector_checksum))\r\n\t\ts_next_avail_sector_checksum++;\r\n\r\n\treturn s_next_avail_sector_checksum++;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* return platform specifc extension, like \".PS2\"\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char *\tCEngine::sGetPlatformExtension()\r\n{\r\n\treturn s_plat_get_platform_extension();\r\n}\r\n\r\n/******************************************************************/\r\n// Wait for any pending asyncronous rendering to finish, so rendering\r\n// data can be unloaded\r\n// (Might be a wait, or a flush, depending on platform)\r\n// This function should generally return immediatly if there is no\r\n// pending rendering.  However, it might stall for up to a frame if\r\n// there are things waiting to render.\r\n// so if it is to be used in a real-time situation, then you want to\r\n// call it as late as possible in the frame (preferably the last thing)\r\n// so it incurs as little wait as possible\r\n// this might be accomplished by making the \"task\" that uses it\r\n// be as low priority as possible\r\n/******************************************************************/\t\t\t\t\t  \r\n\r\nvoid\tCEngine::sFinishRendering()\r\n{\r\n\ts_plat_finish_rendering();\r\n}\r\n\r\n\r\nvoid\t\t\t\tCEngine::sToggleRenderMode()\r\n{\r\n\ts_render_mode++;\r\n\tif (s_render_mode == 4)\r\n\t{\r\n\t\ts_render_mode = 0;\t\r\n\t}\r\n}\r\n\r\n\r\nvoid\t\t\t\tCEngine::sSetDebugIgnore(uint32 ignore_1, uint32 ignore_0)\r\n{\r\n\ts_debug_ignore_0 = ignore_0;\r\n\ts_debug_ignore_1 = ignore_1;\r\n}\r\n\r\nbool\t\t\t\tCEngine::sIsVisible(Mth::Vector &center, float radius)\r\n{\r\n\t// PATCH for multiple viewports\r\n\t// always return true, until we sort out the per-viewport visibility (which might not be needed)\t\t\t\t   \r\n\tif (Nx::CViewportManager::sGetNumActiveViewports() > 1)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn s_plat_is_visible(center,radius);\r\n}\r\n\r\nvoid\t\t\t\tCEngine::sSetMaxMultipassDistance(float dist)\r\n{\r\n\ts_plat_set_max_multipass_distance(dist);\r\n}\r\n\r\nvoid\t\t\t\tCEngine::sSetScreenBlur(uint32 amount)\r\n{\r\n\tDbg_MsgAssert(amount >=0 && amount <=255,(\"Screen blur amount out of range of 0..255 (it's %d)\",amount));\r\n\ts_screen_blur = amount;\r\n\ts_plat_set_screen_blur(amount);\r\n}\r\n\r\nuint32 CEngine::sGetScreenBlur()\r\n{\r\n\tuint32\tamount = s_screen_blur; \r\n\tDbg_MsgAssert(amount >=0 && amount <=255,(\"s_screen_blur out of range of 0..255 (it's %d), maybe corrupted???\",amount));\r\n\treturn amount;\t\r\n}\r\n\r\nint CEngine::sGetNumSoundtracks()\r\n{\r\n\treturn s_plat_get_num_soundtracks();\r\n}\r\n\r\nconst char* CEngine::sGetSoundtrackName( int soundtrack_number )\r\n{\r\n\tconst char* p_soundtrack_name_wide = s_plat_get_soundtrack_name( soundtrack_number );\r\n\treturn p_soundtrack_name_wide;\r\n}\r\n\r\n// Added by Ken for use by replay code.\r\n// \r\nint CEngine::sWriteSectorStatusBitfield(uint32 *p_bitfield, int numUint32s)\r\n{\r\n\treturn 0;\r\n\t\r\n\t// Removed since we no longer have saving of replays to mem card.\r\n\t// Leaving this code in was causing a problem in that the passed numUint32s\r\n\t// was too small for the Skillzilla Park. Rather than increasing numUint32's\r\n\t// and hence using up more memory, it was safer just to remove the contents of this function.\r\n\t#if 0\r\n\tDbg_MsgAssert(p_bitfield,(\"NULL p_bitfield\"));\r\n\r\n\tint i;\r\n\tfor (i=0; i<numUint32s; ++i)\r\n\t{\r\n\t\tp_bitfield[i]=0;\r\n\t}\r\n\t\t\r\n\tint long_index=0;\r\n\tint bit_index=0;\r\n\t\r\n\tfor (i = 0; i<MAX_LOADED_SCENES; ++i)\r\n\t{\r\n\t\tif (sp_loaded_scenes[i])\r\n\t\t{\r\n\t\t\tLst::HashTable<CSector> *p_table=sp_loaded_scenes[i]->GetSectorList();\r\n\t\t\tDbg_MsgAssert(p_table,(\"NULL p_table\"));\r\n\t\t\t\r\n\t\t\tp_table->IterateStart();\r\n\t\t\tCSector *p_sector=p_table->IterateNext();\r\n\t\t\twhile (p_sector)\r\n\t\t\t{\r\n\t\t\t\tif (p_sector->GetActiveAtReplayStart())\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(long_index<numUint32s,(\"Too many sectors for bitfield !\"));\r\n\t\t\t\t\tp_bitfield[long_index] |= (1<<bit_index);\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t++bit_index;\r\n\t\t\t\tif (bit_index>=32)\r\n\t\t\t\t{\r\n\t\t\t\t\tbit_index=0;\r\n\t\t\t\t\t++long_index;\r\n\t\t\t\t}\t\r\n\r\n\t\t\t\tif (p_sector->GetVisibleAtReplayStart())\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(long_index<numUint32s,(\"Too many sectors for bitfield !\"));\r\n\t\t\t\t\tp_bitfield[long_index] |= (1<<bit_index);\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t++bit_index;\r\n\t\t\t\tif (bit_index>=32)\r\n\t\t\t\t{\r\n\t\t\t\t\tbit_index=0;\r\n\t\t\t\t\t++long_index;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\tp_sector=p_table->IterateNext();\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n\t\r\n\treturn long_index*32+bit_index;\r\n\t#endif\r\n}\r\n\r\nvoid CEngine::sReadSectorStatusBitfield(uint32 *p_bitfield, int numUint32s)\r\n{\r\n\treturn;\r\n\t\r\n\t// Removed since we no longer have saving of replays to mem card.\r\n\t// Leaving this code in was causing a problem in that the passed numUint32s\r\n\t// was too small for the Skillzilla Park. Rather than increasing numUint32's\r\n\t// and hence using up more memory, it was safer just to remove the contents of this function.\r\n\t#if 0\r\n\tDbg_MsgAssert(p_bitfield,(\"NULL p_bitfield\"));\r\n\r\n\tint long_index=0;\r\n\tint bit_index=0;\r\n\t\r\n\tfor (int i = 0; i<MAX_LOADED_SCENES; ++i)\r\n\t{\r\n\t\tif (sp_loaded_scenes[i])\r\n\t\t{\r\n\t\t\tLst::HashTable<CSector> *p_table=sp_loaded_scenes[i]->GetSectorList();\r\n\t\t\tDbg_MsgAssert(p_table,(\"NULL p_table\"));\r\n\t\t\t\r\n\t\t\tp_table->IterateStart();\r\n\t\t\tCSector *p_sector=p_table->IterateNext();\r\n\t\t\twhile (p_sector)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(long_index<numUint32s,(\"sReadSectorStatusBitfield: Too many sectors for bitfield !\"));\r\n\t\t\t\tif (p_bitfield[long_index] & (1<<bit_index))\r\n\t\t\t\t{\r\n\t\t\t\t\tp_sector->SetActiveAtReplayStart(true);\r\n\t\t\t\t}\t\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_sector->SetActiveAtReplayStart(false);\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t++bit_index;\r\n\t\t\t\tif (bit_index>=32)\r\n\t\t\t\t{\r\n\t\t\t\t\tbit_index=0;\r\n\t\t\t\t\t++long_index;\r\n\t\t\t\t}\t\r\n\r\n\t\t\t\tDbg_MsgAssert(long_index<numUint32s,(\"sReadSectorStatusBitfield: Too many sectors for bitfield !\"));\r\n\t\t\t\tif (p_bitfield[long_index] & (1<<bit_index))\r\n\t\t\t\t{\r\n\t\t\t\t\tp_sector->SetVisibleAtReplayStart(true);\r\n\t\t\t\t}\t\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_sector->SetVisibleAtReplayStart(false);\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t++bit_index;\r\n\t\t\t\tif (bit_index>=32)\r\n\t\t\t\t{\r\n\t\t\t\t\tbit_index=0;\r\n\t\t\t\t\t++long_index;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\tp_sector=p_table->IterateNext();\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n\t#endif\r\n}\r\n\r\nvoid CEngine::sInitReplayStartState()\r\n{\r\n\t//printf(\"Calling sInitReplayStartState()\\n\");\r\n\tfor (int i = 0; i<MAX_LOADED_SCENES; ++i)\r\n\t{\r\n\t\tif (sp_loaded_scenes[i])\r\n\t\t{\r\n\t\t\tLst::HashTable<CSector> *p_table=sp_loaded_scenes[i]->GetSectorList();\r\n\t\t\tDbg_MsgAssert(p_table,(\"NULL p_table\"));\r\n\t\t\t\r\n\t\t\tp_table->IterateStart();\r\n\t\t\tCSector *p_sector=p_table->IterateNext();\r\n\t\t\twhile (p_sector)\r\n\t\t\t{\r\n\t\t\t\tp_sector->SetActiveAtReplayStart(p_sector->IsActive());\r\n\t\t\t\tp_sector->SetVisibleAtReplayStart(p_sector->GetVisibility()&0x01);\r\n\t\t\t\t// Just to be safe\r\n\t\t\t\tp_sector->SetStoredActive(p_sector->IsActive());\r\n\t\t\t\tp_sector->SetStoredVisible(p_sector->GetVisibility()&0x01);\r\n\t\t\t\t\r\n\t\t\t\tp_sector=p_table->IterateNext();\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\nvoid CEngine::sPrepareSectorsForReplayPlayback(bool store_initial_state)\r\n{\r\n\t//printf(\"Calling sPrepareSectorsForReplayPlayback()\\n\");\r\n\tfor (int i = 0; i<MAX_LOADED_SCENES; ++i)\r\n\t{\r\n\t\tif (sp_loaded_scenes[i])\r\n\t\t{\r\n\t\t\tLst::HashTable<CSector> *p_table=sp_loaded_scenes[i]->GetSectorList();\r\n\t\t\tDbg_MsgAssert(p_table,(\"NULL p_table\"));\r\n\t\t\t\r\n\t\t\tp_table->IterateStart();\r\n\t\t\tCSector *p_sector=p_table->IterateNext();\r\n\t\t\twhile (p_sector)\r\n\t\t\t{\r\n\t\t\t\tif (store_initial_state)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_sector->SetStoredActive(p_sector->IsActive());\r\n\t\t\t\t\tp_sector->SetStoredVisible(p_sector->GetVisibility()&0x01);\r\n\t\t\t\t}\t  \r\n\t\t\t\t  \t\t\r\n\t\t\t\tp_sector->SetActive(p_sector->GetActiveAtReplayStart());\r\n\t\t\t\tp_sector->SetVisibility(p_sector->GetVisibleAtReplayStart()?0xff:0x00);\r\n\t\t\t\t\r\n\t\t\t\tp_sector=p_table->IterateNext();\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\nvoid CEngine::sRestoreSectorsAfterReplayPlayback()\r\n{\r\n\t//printf(\"Calling sRestoreSectorsAfterReplayPlayback()\\n\");\r\n\tfor (int i = 0; i<MAX_LOADED_SCENES; ++i)\r\n\t{\r\n\t\tif (sp_loaded_scenes[i])\r\n\t\t{\r\n\t\t\tLst::HashTable<CSector> *p_table=sp_loaded_scenes[i]->GetSectorList();\r\n\t\t\tDbg_MsgAssert(p_table,(\"NULL p_table\"));\r\n\t\t\t\r\n\t\t\tp_table->IterateStart();\r\n\t\t\tCSector *p_sector=p_table->IterateNext();\r\n\t\t\twhile (p_sector)\r\n\t\t\t{\r\n\t\t\t\tp_sector->SetActive(p_sector->GetStoredActive());\r\n\t\t\t\tp_sector->SetVisibility(p_sector->GetStoredVisible()?0xff:0x00);\r\n\t\t\t\t\r\n\t\t\t\tp_sector=p_table->IterateNext();\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\nbool ScriptToggleAddScenes(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// Just call engine function\r\n\tCEngine::sToggleAddScenes();\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\nbool ScriptSetScreenBlur(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint amount = 0;\r\n\tpParams->GetInteger(NONAME,&amount,false);\r\n\tCEngine::sSetScreenBlur(amount);\r\n\treturn true;\r\n}\r\n\r\n\r\n// Given a script structure, add some metrics to it\r\n// like number of objects, polygons, collision polygons, etc\r\nvoid\tCEngine::sGetMetrics(Script::CStruct * p_info)\r\n{\r\n\r\n\t// Do main scene first, as it's more interesting\r\n\tif (sGetMainScene())\r\n\t{\r\n\t\tScript::CStruct *p_main = new Script::CStruct();\r\n\t\tsGetMainScene()->GetMetrics(p_main);\r\n\t\tp_info->AddStructurePointer(CRCD(0x9b10525c,\"MainScene\"),p_main);\r\n\t}\r\n\t\t\r\n\t// But also do the sky, just in case\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\tif (sGetSkyScene())\r\n\t{\r\n\t\tScript::CStruct *p_sky = new Script::CStruct();\r\n\t\tsGetSkyScene()->GetMetrics(p_sky);\r\n\t\tp_info->AddStructurePointer(CRCD(0x2c5ea34,\"SkyScene\"),p_sky);\r\n\t}\r\n\r\n\t#ifdef\t__PLAT_NGPS__\r\n\t\r\n\r\n\t\tScript::CStruct *p_ps2 = new Script::CStruct();\r\n\t\tp_ps2->AddInteger(CRCD(0x3dd01ea1,\"total\"), NxPs2::geom_stats_total);        \r\n\t\tp_ps2->AddInteger(CRCD(0x742cf11f,\"inactive\"), NxPs2::geom_stats_inactive );    \r\n\t\tp_ps2->AddInteger(CRCD(0xf9d98b10,\"sky\"), NxPs2::geom_stats_sky);          \r\n\t\tp_ps2->AddInteger(CRCD(0x6d65d103,\"transformed\"), NxPs2::geom_stats_transformed);  \r\n\t\tp_ps2->AddInteger(CRCD(0x52aa1a77,\"skeletal\"), NxPs2::geom_stats_skeletal);     \r\n\t\tp_ps2->AddInteger(CRCD(0xaf792e8d,\"camera_sphere\"), NxPs2::geom_stats_camera_sphere);\r\n\t\tp_ps2->AddInteger(CRCD(0xa863e48c,\"clipcull\"), NxPs2::geom_stats_clipcull);     \r\n\t\tp_ps2->AddInteger(CRCD(0x93070c4b,\"culled\"), NxPs2::geom_stats_culled);     \r\n\t\tp_ps2->AddInteger(CRCD(0xac43724a,\"leaf_culled\"), NxPs2::geom_stats_leaf_culled);     \r\n\t\tp_ps2->AddInteger(CRCD(0x68306ffe,\"boxcheck\"), NxPs2::geom_stats_boxcheck);     \r\n\t\tp_ps2->AddInteger(CRCD(0xae81c5f6,\"occludecheck\"), NxPs2::geom_stats_occludecheck); \r\n\t\tp_ps2->AddInteger(CRCD(0xba802ab0,\"occluded\"), NxPs2::geom_stats_occluded);     \r\n\t\tp_ps2->AddInteger(CRCD(0x1bc830f2,\"colored\"), NxPs2::geom_stats_colored);      \r\n\t\tp_ps2->AddInteger(CRCD(0x3960ff18,\"leaf\"), NxPs2::geom_stats_leaf);         \r\n\t\tp_ps2->AddInteger(CRCD(0x506a239f,\"wibbleUV\"), NxPs2::geom_stats_wibbleUV);     \r\n\t\tp_ps2->AddInteger(CRCD(0x169a94b7,\"wibbleVC\"), NxPs2::geom_stats_wibbleVC);     \r\n\t\tp_ps2->AddInteger(CRCD(0x7b471ba2,\"sendcontext\"), NxPs2::geom_stats_sendcontext);  \r\n\t\tp_ps2->AddInteger(CRCD(0x18725397,\"sorted\"), NxPs2::geom_stats_sorted);       \r\n\t\tp_ps2->AddInteger(CRCD(0x8a897dd2,\"shadow\"), NxPs2::geom_stats_shadow);       \r\n\t\t\r\n\t\tp_info->AddStructurePointer(CRCD(0xf2316b47,\"PS2_Info\"),p_ps2);\r\n\r\n\t\ts_plat_get_metrics(p_info);\r\n\r\n#endif\r\n\r\n\r\n}\r\n\t\t\t\t\t \t\t\t\t\t  \r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid\tCEngine::sSetLetterbox(bool letterbox)\r\n{\r\n\ts_plat_set_letterbox( letterbox );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid\tCEngine::sSetColorBufferClear(bool clear)\r\n{\r\n\ts_plat_set_color_buffer_clear( clear );\r\n}\r\n\r\n\r\n\r\n} // namespace Nx\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/nx.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////\r\n// NX.H - Neversoft Engine, Rendering portion, Platform independent interface\r\n\r\n#ifndef\t__GFX_NX_H__\r\n#define\t__GFX_NX_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/hashtable.h>\r\n\r\n#include <gfx/NxScene.h>\r\n#include <gfx/NxSector.h>\r\n#include <gfx/NxSprite.h>\r\n#include <gfx/NxImposter.h>\r\n#include <gfx/NxNewParticleMgr.h>\r\n#include <gfx/nxtexture.h>\r\n#include <gfx/nxtextured3dpoly.h>\r\n#include <gfx/nxweather.h>\r\n\r\nnamespace Obj\r\n{\r\n\tclass CObject;\r\n}\r\n\r\nnamespace Gfx\r\n{\r\n\tclass Camera;\r\n}\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\t// forward declarations\r\n\tclass CGeom;\r\n\tclass CMesh;\r\n\tclass CModel;\r\n\tclass CQuickAnim;\r\n\tclass CWindow2D;\r\n\tclass CParticle;\r\n\r\n// GJ:  The following is for doing cutscene head scaling...\r\n// These parameters will only be active during the loading\r\n// of the next CMesh.\r\nstruct SMeshScalingParameters\r\n{\r\n\tchar* \t\t\tpWeightIndices;\r\n\tfloat* \t\t\tpWeights;\r\n\tMth::Vector* \tpBonePositions;\r\n\tMth::Vector* \tpBoneScales;\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////\r\n// Globally accessible Engine functions ar public static functions, \r\n// just use them like:\r\n//\r\n//  Nx::CSector * p_sector = Nx::CEngine::sGetSector(checksum);\r\n//\r\n// // NOT // I might change this later so the engine is a class, so it would become:\r\n// // NOT // Nx::CSector * p_sector = Nx::CEngine::Instance()->GetSector(checksum);\r\n\r\n\r\n// The engine class is all static\r\nclass CEngine\r\n{\r\npublic:\r\n\tstatic CSector\t*\t\t\tsGetSector(uint32 sector_checksum);\t\t\t// get a sector pointer, based on the checksum of the name\r\n\tstatic void\t\t\t\t\tsStartEngine();\r\n\tstatic void\t\t\t\t\tsSuspendEngine();\r\n\tstatic void\t\t\t\t\tsResumeEngine();\r\n\tstatic void\t\t\t\t\tsPreRender();\r\n\tstatic void\t\t\t\t\tsPostRender();\r\n\tstatic void\t\t\t\t\tsRenderWorld();\r\n\t\r\n\tstatic void\t\t\t\t\tsFinishRendering();\r\n\r\n\tstatic void\t\t\t\t\tsSetScreenBlur(uint32 amount);\t\r\n\tstatic uint32\t\t\t\tsGetScreenBlur();\t\r\n\t\r\n\tstatic CScene\t*\t\t\tsCreateScene(const char *p_name, CTexDict *p_tex_dict,\r\n\t\t\t\t\t\t\t\t\t\t\t bool add_super_sectors = true);\t// creates an empty scene\r\n\tstatic CScene\t*\t\t\tsLoadScene(const char *p_name, CTexDict *p_tex_dict, bool add_super_sectors = true,\r\n\t\t\t\t\t\t\t\t\t\t   bool is_sky = false, bool is_dictionary = false, bool is_net=false);\t// load a platform specific scene file\r\n\tstatic CScene\t*\t\t\tsAddScene(const char *p_scene_name, const char *p_filename);\t// add a scene file to an existing scene\r\n\tstatic void\t\t\t\t\tsToggleAddScenes();\r\n\tstatic bool\t\t\t\t\tsUnloadScene(CScene *p_scene);\r\n\tstatic bool\t\t\t\t\tsQuickReloadGeometry(const char *p_scene_name);\t\r\n\r\n\tstatic SSec::Manager * \t\tsGetNearestSuperSectorManager(Mth::Line &);\t\t// Returns the closest SuperSector Manager\r\n\tstatic SSec::Manager * \t\tsGetNearestSuperSectorManager(Mth::Vector &);\t// Returns the closest SuperSector Manager\r\n\r\n\tstatic\tconst char *\t\tsGetPlatformExtension();   \t\t\t\t\t// return platform specifc extension, like \".PS2\"\r\n\t\r\n\tstatic bool\t\t\t\t\tsUnloadAllScenesAndTexDicts();\t\t\t\t// unloads all loaded scenes and their associated texture dicts\r\n\t\r\n\tstatic\tCScene *\t\t\tsGetScene(uint32 id);\t\t  \t\t\t\t// get scene, given the checksum id of the name\r\n\tstatic\tCScene *\t\t\tsGetScene(const char *p_name);\t\t\t\t// get scene, given name\r\n\tstatic \tCScene *  \t\t\tsGetMainScene();\t\t\t\t\t\t\t// get first non-sky scene\r\n\tstatic \tCScene *  \t\t\tsGetSkyScene();\t\t\t\t\t\t\t\t// get first sky scene\r\n\r\n\tstatic CSprite *\t\t\tsCreateSprite(CWindow2D *p_window = NULL);\r\n\tstatic bool\t\t\t\t\tsDestroySprite(CSprite *p_sprite);\r\n\t\t\t\t\t\t\t\t\r\n\tstatic CTextured3dPoly *\tsCreateTextured3dPoly();\r\n\tstatic bool\t\t\t\t\tsDestroyTextured3dPoly(CTextured3dPoly *p_poly);\r\n\t\r\n\t\t\t\t\t\t\t\t\t\t\t  \r\n\tstatic CTexture *\t\t\tsCreateRenderTargetTexture( int width, int height, int depth, int z_depth );\r\n\tstatic void\t\t\t\t\tsProjectTextureIntoScene( Nx::CTexture *p_texture, Nx::CModel *p_model, Nx::CScene *p_scene = NULL);\r\n\tstatic void\t\t\t\t\tsSetProjectionTextureCamera( Nx::CTexture *p_texture, Gfx::Camera *p_camera );\r\n\tstatic void\t\t\t\t\tsStopProjectionTexture( Nx::CTexture *p_texture );\r\n\r\n\tstatic void\t\t\t\t\tsAddOcclusionPoly( uint32 num_verts, Mth::Vector *p_vert_array, uint32 checksum = 0 );\r\n\tstatic void\t\t\t\t\tsEnableOcclusionPoly( uint32 checksum, bool enable );\r\n\t\r\n\tstatic CModel*\t\t\t\tsInitModel();\r\n\tstatic bool\t\t\t\t\tsUninitModel(CModel* pModel);\r\n\r\n\tstatic CGeom*\t\t\t\tsInitGeom();\r\n\tstatic bool\t\t\t\t\tsUninitGeom(CGeom* pGeom);\r\n\r\n\tstatic CQuickAnim*\t\t\tsInitQuickAnim();\r\n\tstatic void\t\t\t\t\tsUninitQuickAnim(CQuickAnim* pQuickAnim);\r\n\r\n\tstatic CMesh*\t\t\t\tsLoadMesh(const char* pFileName, uint32 texDictOffset, bool forceTexDictLookup, bool doShadowVolume);\r\n\tstatic CMesh*\t\t\t\tsLoadMesh(uint32 id, uint32* pModelData, int modelDataSize, uint8* pCASData, uint32 textureDictChecksum, uint32* pTextureData, int textureDataSize, uint32 textureDictOffset, bool isSkin, bool doShadowVolume );\r\n\tstatic bool\t\t\t\t\tsUnloadMesh(CMesh* pMesh);\r\n\r\n\tstatic void\t\t\t\t\tsSetMeshScalingParameters( SMeshScalingParameters* pParams );\r\n\r\n\tstatic\tvoid\t\t\t\tsSetMovableObjectManager(Obj::CGeneralManager* p_object_manager);\r\n\tstatic Lst::Head<Obj::CObject> & sGetMovableObjects();\t\t\t\t\t// Returns the list of all movable objects\r\n\tstatic \tLst::HashTable< CParticle > * sGetParticleTable();\r\n\r\n\tstatic CImposterManager*\tsGetImposterManager( void )\t{ return mp_imposter_manager; }\r\n\tstatic CNewParticleManager*\tsGetParticleManager( void )\t{ return mp_particle_manager; }\r\n\r\n\tstatic uint32\t\t\t\tsGetUnusedSectorChecksum();\t\t\t\t\t// Gets a unique sector checksum for cloning\r\n\r\n\tstatic bool\t\t\t\t\tsIsVisible(Mth::Vector &center, float radius);\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\r\n\tstatic void\t\t\t\t\tsSetMaxMultipassDistance(float dist);\t\t// Sets distance at which multipass will stop drawing\r\n\r\n\tstatic void\t\t\t\t\tsSetLetterbox(bool lettterbox);\r\n\r\n\tstatic void\t\t\t\t\tsSetColorBufferClear(bool clear);\t\t\t\t// Indicates whether a per-frame color buffer clear is required (in addition to z-buffer clear).\r\n\tstatic CWeather*\t\t\tsGetWeather( void ) { return mp_weather; }\r\n\r\n\t// K: Added so that park editor can update the grid after geometry has changed.\r\n\tstatic bool\t\t\t\t\tScriptWeatherUpdateGrid( Script::CStruct* pParams, Script::CScript* pScript ) { mp_weather->UpdateGrid(); return true; }\r\n\t\r\n\tstatic bool\t\t\t\t\tScriptWeatherSetRainHeight( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetRainHeight( pParams, pScript ); }\r\n\tstatic bool\t\t\t\t\tScriptWeatherSetRainFrames( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetRainFrames( pParams, pScript ); } \r\n\tstatic bool\t\t\t\t\tScriptWeatherSetRainLength( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetRainLength( pParams, pScript ); } \r\n\tstatic bool\t\t\t\t\tScriptWeatherSetRainBlendMode( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetRainBlendMode( pParams, pScript ); } \r\n\tstatic bool\t\t\t\t\tScriptWeatherSetRainRate( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetRainRate( pParams, pScript ); } \r\n\tstatic bool\t\t\t\t\tScriptWeatherSetRainColor( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetRainColor( pParams, pScript ); }  \r\n\r\n\tstatic bool\t\t\t\t\tScriptWeatherSetSplashRate( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetSplashRate( pParams, pScript ); } \r\n\tstatic bool\t\t\t\t\tScriptWeatherSetSplashLife( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetSplashLife( pParams, pScript ); } \r\n\tstatic bool\t\t\t\t\tScriptWeatherSetSplashSize( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetSplashSize( pParams, pScript ); } \r\n\tstatic bool\t\t\t\t\tScriptWeatherSetSplashColor( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetSplashColor( pParams, pScript ); } \r\n\tstatic bool\t\t\t\t\tScriptWeatherSetSplashBlendMode( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetSplashBlendMode( pParams, pScript ); } \r\n\r\n\tstatic bool\t\t\t\t\tScriptWeatherSetSnowHeight( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetSnowHeight( pParams, pScript ); }\r\n\tstatic bool\t\t\t\t\tScriptWeatherSetSnowFrames( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetSnowFrames( pParams, pScript ); } \r\n\tstatic bool\t\t\t\t\tScriptWeatherSetSnowSize( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetSnowSize( pParams, pScript ); } \r\n\tstatic bool\t\t\t\t\tScriptWeatherSetSnowBlendMode( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetSnowBlendMode( pParams, pScript ); } \r\n\tstatic bool\t\t\t\t\tScriptWeatherSetSnowRate( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetSnowRate( pParams, pScript ); } \r\n\tstatic bool\t\t\t\t\tScriptWeatherSetSnowColor( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetSnowColor( pParams, pScript ); }  \r\n\t\r\n\tstatic bool\t\t\t\t\tScriptWeatherSetSnowActive( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetSnowActive( pParams, pScript ); }  \r\n\tstatic bool\t\t\t\t\tScriptWeatherSetRainActive( Script::CStruct* pParams, Script::CScript* pScript ) { return mp_weather->ScriptWeatherSetRainActive( pParams, pScript ); }  \r\n\r\n\t//Some Debugging functions\r\n\tstatic\tvoid\t\t\t\tsToggleRenderMode();\r\n\tstatic\tvoid\t\t\t\tsSetRenderMode(int mode) {s_render_mode = mode;}\r\n\tstatic\tvoid\t\t\t\tsSetWireframeMode(int mode) {s_wireframe_mode = mode;}\r\n\tstatic\tvoid\t\t\t\tsSetDebugIgnore(uint32 ignore_1, uint32 ignore_0);\r\n\tstatic\tvoid\t\t\t\tsDebugCheckForHoles();\r\n\tstatic  uint32\t\t\t\tGetRenderMode() {return s_render_mode;}\r\n\tstatic  uint32\t\t\t\tGetWireframeMode() {return s_wireframe_mode;}\r\n\t\r\n\t// Debug inspection stuff\t\t\t\t\t\t\t\t\r\n\tstatic\tvoid\t\t\t\tsGetMetrics(Script::CStruct* p_info);\r\n\r\n\t// soundtrack stuff (hook to xbox specific funcs)\r\n\tstatic\tint\t\t\t\t\tsGetNumSoundtracks();\r\n\tstatic\tconst char*\t\t\tsGetSoundtrackName( int soundtrack_number );\r\n\r\n\t// Added by Ken, for use by replay code, which needs to store the status of the sectors\r\n\t// so that they can be restored when the replay finishes.\r\n\tstatic\tint\t\t\t\t\tsWriteSectorStatusBitfield(uint32 *p_bitfield, int numUint32s);\r\n\tstatic\tvoid\t\t\t\tsReadSectorStatusBitfield(uint32 *p_bitfield, int numUint32s);\r\n\t\r\n\tstatic\tvoid\t\t\t\tsInitReplayStartState();\r\n\tstatic\tvoid\t\t\t\tsPrepareSectorsForReplayPlayback(bool store_initial_state);\r\n\tstatic\tvoid\t\t\t\tsRestoreSectorsAfterReplayPlayback();\r\n\t\r\n\t\r\n\t\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tMAX_LOADED_SCENES = 4\r\n\t};\r\n\r\nprivate:\r\n\t// Platform specific function calls\t\r\n\tstatic void\t\t\t\t\ts_plat_start_engine();\r\n\tstatic void\t\t\t\t\ts_plat_suspend_engine();\r\n\tstatic void\t\t\t\t\ts_plat_resumeEngine();\r\n\tstatic void\t\t\t\t\ts_plat_pre_render();\r\n\tstatic void\t\t\t\t\ts_plat_post_render();\r\n\tstatic void\t\t\t\t\ts_plat_render_world();\r\n\t\r\n\tstatic void\t\t\t\t\ts_plat_set_screen_blur(uint32 amount);\r\n\r\n\tstatic void\t\t\t\t\ts_plat_set_letterbox(bool letterbox);\r\n\tstatic void\t\t\t\t\ts_plat_set_color_buffer_clear(bool clear);\r\n\t\t\t  \r\n\tstatic CScene\t*\t\t\ts_plat_create_scene(const char *p_name, CTexDict *p_tex_dict,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tbool add_super_sectors = true);\t// creates an empty scene\r\n\tstatic CScene\t*\t\t\ts_plat_load_scene(const char *p_name, CTexDict *p_tex_dict, bool add_super_sectors,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  bool is_sky, bool is_dictionary);\t\t// load a platform specific scene file\r\n\tstatic CScene\t*\t\t\ts_plat_load_scene_from_memory(void *p_data, CTexDict *p_tex_dict, bool add_super_sectors,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  bool is_sky, bool is_dictionary);\t\t// load a platform specific scene file\r\n\tstatic bool\t\t\t\t\ts_plat_add_scene(CScene *p_scene, const char *p_filename);\r\n\tstatic bool\t\t\t\t\ts_plat_unload_scene(CScene *p_scene);\r\n\r\n\tstatic CSprite *\t\t\ts_plat_create_sprite(CWindow2D *p_window);\r\n\tstatic bool\t\t\t\t\ts_plat_destroy_sprite(CSprite *p_sprite);\r\n\r\n\tstatic CTextured3dPoly *\ts_plat_create_textured_3d_poly();\r\n\tstatic bool\t\t\t\t\ts_plat_destroy_textured_3d_poly(CTextured3dPoly *p_poly);\r\n\r\n\tstatic CTexture *\t\t\ts_plat_create_render_target_texture( int width, int height, int depth, int z_depth );\r\n\tstatic void\t\t\t\t\ts_plat_project_texture_into_scene( Nx::CTexture *p_texture, Nx::CModel *p_model, Nx::CScene *p_scene );\r\n\tstatic void\t\t\t\t\ts_plat_set_projection_texture_camera( Nx::CTexture *p_texture, Gfx::Camera *p_camera );\r\n\tstatic void\t\t\t\t\ts_plat_stop_projection_texture( Nx::CTexture *p_texture );\r\n\r\n\tstatic void\t\t\t\t\ts_plat_add_occlusion_poly( uint32 num_verts, Mth::Vector *p_vert_array, uint32 checksum = 0 );\r\n\tstatic void\t\t\t\t\ts_plat_enable_occlusion_poly( uint32 checksum, bool enable );\r\n\tstatic void\t\t\t\t\ts_plat_remove_all_occlusion_polys( void );\r\n\r\n\tstatic\tconst char *\t\ts_plat_get_platform_extension();\r\n\r\n\tstatic CModel*\t\t\t\ts_plat_init_model();\r\n\tstatic bool\t\t\t\t\ts_plat_uninit_model(CModel* pModel);\r\n\r\n\tstatic CGeom*\t\t\t\ts_plat_init_geom();\r\n\tstatic bool\t\t\t\t\ts_plat_uninit_geom(CGeom* pGeom);\r\n\r\n\tstatic CQuickAnim*\t\t\ts_plat_init_quick_anim();\r\n\tstatic void\t\t\t\t\ts_plat_uninit_quick_anim(CQuickAnim* pQuickAnim);\r\n\r\n\tstatic CMesh*\t\t\t\ts_plat_load_mesh(const char* pMeshFileName, Nx::CTexDict* pTexDict, uint32 texDictOffset, bool isSkin, bool doShadowVolume);\r\n\tstatic CMesh*\t\t\t\ts_plat_load_mesh(uint32 id, uint32* pModelData, int modelDataSize, uint8* pCASData, Nx::CTexDict* pTexDict, uint32 texDictOffset, bool isSkin, bool doShadowVolume);\r\n\tstatic bool\t\t\t\t\ts_plat_unload_mesh(CMesh* pMesh);\r\n\t\r\n\tstatic void\t\t\t\t\ts_plat_set_mesh_scaling_parameters( SMeshScalingParameters* pParams );\r\n\r\n\tstatic bool\t\t\t\t\ts_plat_is_visible(Mth::Vector& center, float radius);\t\t\t\t\t\t\t\t\t\t\r\n\r\n\tstatic void\t\t\t\t\ts_plat_set_max_multipass_distance(float dist);\r\n\r\n\tstatic\tvoid\t\t\t\ts_plat_finish_rendering();\r\n\t\t\r\n\tstatic \tint\t\t\t\t\ts_plat_get_num_soundtracks();\r\n\tstatic\tconst char*\t\t\ts_plat_get_soundtrack_name( int soundtrack_number );\r\n\t\r\n\t#ifdef\t__PLAT_NGPS__\r\n\t// a debug function just for the PS2 - although we could well have it on all platforms\r\n\tstatic \tvoid \t\t\t\ts_plat_get_metrics(Script::CStruct * p_info);\r\n\t#endif\r\n\r\n\t// Member variables\r\n\tstatic CScene *\t\t\t\tsp_loaded_scenes[MAX_LOADED_SCENES];\r\n\r\n\tstatic uint32\t\t\t\ts_next_avail_sector_checksum;\t\t\t\t// next checksum available for clones\r\n\t\r\n\tstatic\tuint32\t\t\t\ts_screen_blur;\r\n\tstatic\tuint32\t\t\t\ts_render_mode;\r\n\tstatic\tuint32\t\t\t\ts_wireframe_mode;\r\n\tstatic\tuint32\t\t\t\ts_debug_ignore_0;\r\n\tstatic\tuint32\t\t\t\ts_debug_ignore_1;\r\n\t\r\n\tstatic \tLst::HashTable< CParticle > *p_particle_table;\r\n\tstatic  Obj::CGeneralManager* \t\tsp_moving_object_manager;\r\n\r\n\tstatic CImposterManager*\tmp_imposter_manager;\t\r\n\tstatic CNewParticleManager*\tmp_particle_manager;\r\n\tstatic CWeather*\t\t\tmp_weather;\r\n};\r\n\r\n\r\nbool ScriptToggleAddScenes(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetScreenBlur(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\n\r\n}\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/nxflags.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n// nxflags.h - flag definitions that used to be in nxplugin\r\n//\r\n\r\n#ifndef\t__GFX_NXFLAGS_H\r\n#define\t__GFX_NXFLAGS_H\r\n\r\n\r\n// Face flags\r\nenum\r\n{\r\n\tmFD_SKATABLE\t\t\t= 0x00000001,\r\n\tmFD_NOT_SKATABLE\t\t= 0x00000002,\r\n\tmFD_WALL_RIDABLE\t\t= 0x00000004,\r\n\tmFD_VERT\t\t\t\t= 0x00000008,\r\n\tmFD_NON_COLLIDABLE\t\t= 0x00000010,\r\n\tmFD_DECAL\t\t\t\t= 0x00000020,\r\n\tmFD_TRIGGER\t\t\t\t= 0x00000040,\r\n\tmFD_CAMERA_COLLIDABLE\t= 0x00000080,\r\n\tmFD_NO_SKATER_SHADOW\t= 0x00000100,\r\n\tmFD_SKATER_SHADOW\t\t= 0x00000200,\r\n\tmFD_NO_SKATER_SHADOW_WALL=0x00000400,\r\n\tmFD_UNDER_OK\t\t\t= 0x00000800,\r\n    mFD_INVISIBLE\t\t\t= 0x00001000,\r\n\tmFD_CASFACEFLAGSEXIST   = 0x00002000,\r\n\tmFD_PASS_1_DISABLED     = 0x00004000,\r\n\tmFD_PASS_2_ENABLED      = 0x00008000,\r\n\tmFD_PASS_3_ENABLED      = 0x00010000,\r\n\tmFD_PASS_4_ENABLED      = 0x00020000,\r\n\tmFD_RENDER_SEPARATE\t\t= 0x00040000,\r\n\tmFD_LIGHTMAPPED\t\t\t= 0x00080000,\r\n   \tmFD_NON_WALL_RIDABLE\t= 0x00100000,\r\n\tmFD_NON_CAMERA_COLLIDABLE = 0x00200000,\r\n\tmFD_EXPORT_COLLISION\t= 0x00400000,\r\n};\r\n\r\n// Object flags\r\nenum\r\n{\r\n\tmSD_INVISIBLE\t\t\t= 0x0001,\t// Invisible in primary viewport\r\n\tmSD_NON_COLLIDABLE\t\t= 0x0002,\r\n\tmSD_KILLED\t\t\t\t= 0x0004,\r\n\tmSD_DONT_FOG\t\t\t= 0x0008,\r\n\tmSD_ALWAYS_FACE\t\t\t= 0x0010,\r\n\tmSD_NO_SKATER_SHADOW\t= 0x0020,\t// This is set at runtime for sectors with every face flagged mFD_SKATER_SHADOW.\r\n\tmSD_INVISIBLE2\t\t\t= 0x0040,\t// Invisible in secondary viewport (Mick)\r\n\tmSD_OCCLUDER\t\t\t= 0x0080,\t// Occluder (it's a single plane that hides stuff)\r\n\tmSD_CLONE\t\t\t\t= 0x8000,\t// Cloned collision object (Garrett)\r\n};\r\n\r\n\r\n// Material flags\r\nenum ETerrainType\r\n{\r\n\t// If you change any of these,\r\n\t// don't forget to change terrain.q\r\n\t// to match!\r\n\tvTERRAIN_DEFAULT, \t\r\n\tvTERRAIN_CONCSMOOTH,\t\r\n\tvTERRAIN_CONCROUGH,\t\r\n\tvTERRAIN_METALSMOOTH,\r\n\tvTERRAIN_METALROUGH,\t\r\n\tvTERRAIN_METALCORRUGATED,\t\r\n\tvTERRAIN_METALGRATING,\r\n\tvTERRAIN_METALTIN,\t\r\n\tvTERRAIN_WOOD,\t\t\r\n\tvTERRAIN_WOODMASONITE,\r\n\tvTERRAIN_WOODPLYWOOD,\r\n\tvTERRAIN_WOODFLIMSY,\t\r\n\tvTERRAIN_WOODSHINGLE,\r\n\tvTERRAIN_WOODPIER,\t\r\n\tvTERRAIN_BRICK,\t\t\r\n\tvTERRAIN_TILE,\t\t\r\n\tvTERRAIN_ASPHALT,\t\r\n\tvTERRAIN_ROCK,\t\t\r\n\tvTERRAIN_GRAVEL,\t\t\r\n\tvTERRAIN_SIDEWALK,\t\r\n\tvTERRAIN_GRASS,\t\t\r\n\tvTERRAIN_GRASSDRIED,\t\r\n\tvTERRAIN_DIRT,\t\t\r\n\tvTERRAIN_DIRTPACKED,\t\r\n\tvTERRAIN_WATER,\t\t\r\n\tvTERRAIN_ICE,\t\t\r\n\tvTERRAIN_SNOW,\t\t\r\n\tvTERRAIN_SAND,\t\t\r\n\tvTERRAIN_PLEXIGLASS,\t\r\n\tvTERRAIN_FIBERGLASS,\t\r\n\tvTERRAIN_CARPET,\t\t\r\n\tvTERRAIN_CONVEYOR,\t\r\n\tvTERRAIN_CHAINLINK,\r\n\tvTERRAIN_METALFUTURE,\r\n\tvTERRAIN_GENERIC1,\t\r\n\tvTERRAIN_GENERIC2,\r\n\tvTERRAIN_WHEELS, // K: Used only by the skateboard wheels, as a means of identifying them so their color can be changed.\t\r\n\tvTERRAIN_WETCONC,\r\n\tvTERRAIN_METALFENCE,\r\n\tvTERRAIN_GRINDTRAIN,\r\n\tvTERRAIN_GRINDROPE,\r\n\tvTERRAIN_GRINDWIRE,\r\n\tvTERRAIN_GRINDCONC,\t\t\t// New as of 7/29/03\r\n\tvTERRAIN_GRINDROUNDMETALPOLE,\r\n\tvTERRAIN_GRINDCHAINLINK,\r\n\tvTERRAIN_GRINDMETAL,\r\n\tvTERRAIN_GRINDWOODRAILING,\r\n\tvTERRAIN_GRINDWOODLOG,\r\n\tvTERRAIN_GRINDWOOD,\r\n\tvTERRAIN_GRINDPLASTIC,\r\n\tvTERRAIN_GRINDELECTRICWIRE,\r\n\tvTERRAIN_GRINDCABLE,\r\n\tvTERRAIN_GRINDCHAIN,\r\n\tvTERRAIN_GRINDPLASTICBARRIER,\r\n\tvTERRAIN_GRINDNEONLIGHT,\r\n\tvTERRAIN_GRINDGLASSMONSTER,\r\n\tvTERRAIN_GRINDBANYONTREE,\r\n\tvTERRAIN_GRINDBRASSRAIL,\r\n\tvTERRAIN_GRINDCATWALK,\r\n\tvTERRAIN_GRINDTANKTURRET,\r\n\r\n\t// If anyone adds a new terrain so that vNUM_TERRAIN_TYPES > 64, let Steve G know\r\n\tvNUM_TERRAIN_TYPES\r\n};\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Gfx/nxparticle.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxParticle.cpp\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/math.h>\r\n#include <gfx/NxParticle.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/script.h>\r\n#include <sk/modules/frontend/frontend.h>\r\n#include <gel/components/suspendcomponent.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/debuggfx.h>\r\n#include <sys/replay/replay.h>\r\n\r\n#define next_random() ((((float)rand() / RAND_MAX ) * 2.0f ) - 1.0f)\r\n\r\n//NsVector pright;\r\n//NsVector pup;\r\n//NsVector pat;\r\n\r\nnamespace\tNx\r\n{\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CParticle::plat_render( void )\r\n{\r\n\tprintf (\"STUB: plat_render\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CParticle::plat_get_position( int entry, int list, float * x, float * y, float * z )\r\n{\r\n\tprintf (\"STUB: plat_get_position\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CParticle::plat_set_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tprintf (\"STUB: plat_set_position\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CParticle::plat_add_position( int entry, int list, float x, float y, float z )\r\n{\r\n\tprintf (\"STUB: plat_add_position\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CParticle::plat_set_active( bool active )\r\n{\r\n\t// PS2 & Gamecube do nothing here.\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CParticle::plat_build_path( void )\r\n{\r\n\tprintf (\"STUB: plat_build_path\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CParticle::plat_get_num_particle_colors( void ) { printf (\"STUB: plat_get_num_particle_colors\\n\"); return 0; };\r\nint CParticle::plat_get_num_vertex_lists( void ) { printf (\"STUB: plat_get_num_vertex_lists\\n\"); return 0; };\r\nvoid CParticle::plat_set_sr( int entry, uint8 value ) { printf (\"STUB: plat_set_sr\\n\"); }\r\nvoid CParticle::plat_set_sg( int entry, uint8 value ) { printf (\"STUB: plat_set_sg\\n\"); }\r\nvoid CParticle::plat_set_sb( int entry, uint8 value ) { printf (\"STUB: plat_set_sb\\n\"); }\r\nvoid CParticle::plat_set_sa( int entry, uint8 value ) { printf (\"STUB: plat_set_sa\\n\"); }\r\nvoid CParticle::plat_set_mr( int entry, uint8 value ) { printf (\"STUB: plat_set_mr\\n\"); }\r\nvoid CParticle::plat_set_mg( int entry, uint8 value ) { printf (\"STUB: plat_set_mg\\n\"); }\r\nvoid CParticle::plat_set_mb( int entry, uint8 value ) { printf (\"STUB: plat_set_mb\\n\"); }\r\nvoid CParticle::plat_set_ma( int entry, uint8 value ) { printf (\"STUB: plat_set_ma\\n\"); }\r\nvoid CParticle::plat_set_er( int entry, uint8 value ) { printf (\"STUB: plat_set_er\\n\"); }\r\nvoid CParticle::plat_set_eg( int entry, uint8 value ) { printf (\"STUB: plat_set_eg\\n\"); }\r\nvoid CParticle::plat_set_eb( int entry, uint8 value ) { printf (\"STUB: plat_set_eb\\n\"); }\r\nvoid CParticle::plat_set_ea( int entry, uint8 value ) { printf (\"STUB: plat_set_ea\\n\"); }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCParticleEntry::CParticleEntry()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCParticleEntry::~CParticleEntry()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CParticle::set_defaults( void )\r\n{\r\n#define px 0x800\t\t//0x4a1;\r\n#define py 0x90\t\t\t//-0x117;\t\t//0xfffffee9;\r\n#define pz -0x3a0\t\t//0xb96;\r\n\r\n\tmp_emit_script = NULL;\r\n\tmp_update_script = NULL;\r\n\tmp_params = NULL;\r\n\tm_life_set = false;\r\n\tm_end_set = false;\r\n\r\n\r\n\t// Temp: Set up some debug values.\r\n\tm_pos[X] = px;\r\n\tm_pos[Y] = py;\r\n\tm_pos[Z] = pz;\r\n\r\n\tm_sw = 2.0f;\r\n\tm_sh = 2.0f;\r\n\tm_ew = 2.0f;\r\n\tm_eh = 2.0f;\r\n\t\r\n\tm_life_min = 2.0f;\r\n\tm_life_max = 2.0f;\r\n\r\n\tm_emit_w = 1.0f;\t//16.0f;\r\n\tm_emit_h = 1.0f;    //16.0f;\r\n\tm_emit_angle_spread = 0.5f;\t\t//0.5f;\r\n\r\n\tm_fx = 0.0f;\r\n\tm_fy = -0.02f;\r\n\tm_fz = 0.0f;\r\n\r\n\tm_tx = 0.0f;\t\t// Default target: straight up.\r\n\tm_ty = 1.0f;\r\n\tm_tz = 0.0f;\r\n\r\n\tm_ax = 0.0f;\t\t// Default angles: No rotation.\r\n\tm_ay = 0.0f;\r\n\tm_az = 0.0f;\r\n\r\n\tm_speed_min = 1.0f;\r\n\tm_speed_max = 2.0f;\r\n\r\n\tm_random_angle = false;\r\n\tm_circular_emit = true;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCParticle::CParticle()\r\n{\r\n\tset_defaults();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCParticle::CParticle( uint32 checksum )\r\n{\r\n\tset_defaults();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCParticle::CParticle( uint32 checksum, int maxParticles )\r\n{\r\n\tset_defaults();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCParticle::~CParticle()\r\n{\r\n\tif ( mp_emit_script )\r\n\t{\r\n\t\tdelete mp_emit_script;\r\n\t}\r\n\tif ( mp_update_script )\r\n\t{\r\n\t\tdelete mp_update_script;\r\n\t}\r\n\tif ( mp_params )\r\n\t{\r\n\t\tdelete mp_params;\r\n\t}\r\n\tCEngine::sGetParticleTable()->FlushItem( m_checksum );\t\t// remove reference from hash table\r\n//\tprintf (\"\\nJust Deleted 0x%x, contenets are now:\\n\",m_checksum);\r\n//\tCEngine::sGetParticleTable()->PrintContents();\r\n}\r\n\r\nvoid CParticle::process( float delta_time )\r\n{\r\n\tint\t\t\t\tlp;\r\n\tCParticleEntry*\tp_particle;\r\n\r\n\t// If flagged for deletion, check if the particle system is empty and delete if it is.\r\n\tif ( m_delete_when_empty )\r\n\t{\r\n\t\tif ( !m_num_particles )\r\n\t\t{\r\n\t\t\t// removing reference is sone in the destructor\r\n\t\t\t//CEngine::sGetParticleTable()->FlushItem( m_checksum );\t\t// remove reference from hash table\r\n\t\t\tdelete this;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\t// Don't process if paused.\r\n\tif (Mdl::FrontEnd::Instance()->GamePaused() && !Replay::RunningReplay())\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tif (Replay::Paused())\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tif ( GetSuspendComponent()->SkipLogic( ) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t\r\n\r\n\t// Script updates.\r\n\tif ( mp_update_script )\r\n\t{\r\n\t\tmp_update_script->Update();\r\n\t}\r\n\r\n// We can't check for off screen or not until we've run the update script\r\n// as that might change the position (like for sparks)\r\n\r\n\t// Don't process if off screen\r\n//\tif (!Nx::CEngine::sIsVisible(m_pos,m_bounding_radius))\r\n//\t{\r\n//\t\t//printf (\"Off - process\\n\");\r\n//\t\tGfx::AddDebugLine(m_pos,Mth::Vector(0,0,0),0x0000ff,0x0000ff,100);\t \t// where is it?\r\n//\t\treturn;\r\n//\t}\r\n\r\n\r\n\tif ( mp_emit_script )\r\n\t{\r\n\t\tmp_emit_script->Update();\r\n//\t\tif ( mp_emit_script->Update() == Script::ESCRIPTRETURNVAL_FINISHED )\r\n//\t\t{\r\n//\t\t\tm_delete_when_empty = true;\r\n//\t\t}\r\n\t}\r\n\r\n\r\n\r\n\t// If life was not set, assume we're a screen-facing system.\r\n\tif ( !m_life_set ) return;\r\n\r\n\t// Physics update.\r\n\tfor ( lp = 0, p_particle = mp_particle_array; lp < m_num_particles; lp++, p_particle++ )\r\n\t{\r\n\t\t// Update time/life.\r\n\t\tp_particle->m_time += delta_time;\r\n\r\n\t\t// Apply force to velocity.\r\n\t\tp_particle->m_vx += p_particle->m_fx;\r\n\t\tp_particle->m_vy += p_particle->m_fy;\r\n\t\tp_particle->m_vz += p_particle->m_fz;\r\n\r\n\t\t// Copy history.\r\n\t\tfloat x, y, z;\r\n\t\tfor ( int lp2 = ( plat_get_num_vertex_lists() - 1 ); lp2 > 0; lp2-- )\r\n\t\t{\r\n\t\t\tplat_get_position( lp, lp2 - 1, &x, &y, &z );\r\n\t\t\tplat_set_position( lp, lp2, x, y, z );\r\n\t\t}\r\n\r\n\t\t// Apply velocity to position.\r\n\t\tplat_add_position( lp, 0, p_particle->m_vx, p_particle->m_vy, p_particle->m_vz );\r\n\t}\r\n\r\n\t// Delete old particles.\r\n\tfor ( lp = 0, p_particle = mp_particle_array; lp < m_num_particles; lp++, p_particle++ )\r\n\t{\r\n\t\tif ( p_particle->m_time > p_particle->m_life )\r\n\t\t{\r\n\t\t\t// Delete old particles by copying last entry to entry that is being deleted.\r\n\t\t\tm_num_particles--;\r\n\t\t\tmemcpy( p_particle, &mp_particle_array[m_num_particles], sizeof( CParticleEntry ) );\r\n\r\n\t\t\tfloat x, y, z;\r\n\t\t\tfor ( int lp2 = 0; lp2 < plat_get_num_vertex_lists(); lp2++ )\r\n\t\t\t{\r\n\t\t\t\tplat_get_position( m_num_particles, lp2, &x, &y, &z );\r\n\t\t\t\tplat_set_position( lp, lp2, x, y, z );\r\n\t\t\t\tplat_set_position( m_num_particles, lp2, 1024.0f, 1024.0f, 1024.0f );\r\n\t\t\t}\r\n\r\n\t\t\t// Since we copied the last one to the current slot, decrement lp counter & particle\r\n\t\t\t// pointer so that the copied entry gets checked for deletion as well.\r\n\t\t\tp_particle--;\r\n\t\t\tlp--;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CParticle::render( void )\r\n{\r\n\r\n\tif ( GetSuspendComponent()->SkipRender( ) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tplat_render();\r\n}\r\n\r\nvoid CParticle::emit( int count )\r\n{\r\n\tint first, last;\r\n\r\n\t// Do nothing here if flagged for deletion.\r\n\tif ( m_delete_when_empty )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Calculate the range of array entries to emit to.\r\n\tfirst = m_num_particles;\r\n\tif ( ( m_num_particles + count ) <= m_max_particles )\r\n\t{\r\n\t\tm_num_particles += count;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_num_particles = m_max_particles;\r\n\t}\r\n\tlast = m_num_particles;\r\n\r\n\t// Build matrix to rotate the particle to the target.\r\n\tMth::Matrix mt;\r\n\r\n\tmt.GetPos().Set();\r\n\tmt.GetAt().Set( m_tx, m_ty, m_tz );\r\n\tmt.GetAt().Normalize();\r\n\r\n\tMth::Vector temp;\r\n\ttemp.Set( 0.0f, 1.0f, 0.0f );\r\n\tif ( ( fabs( mt.GetAt()[Y] ) > fabs( mt.GetAt()[X] ) ) && ( fabs( mt.GetAt()[Y] ) > fabs( mt.GetAt()[Z] ) ) )\r\n\t{\r\n\t\t// Y Major - use Z as up.\r\n\t\ttemp.Set( 0.0f, 0.0f, 1.0f );\r\n\t}\r\n\r\n\tmt.GetRight() = Mth::CrossProduct( temp, mt.GetAt() ); \r\n\tmt.GetRight().Normalize();\r\n\tmt.GetUp() = Mth::CrossProduct( mt.GetRight(), mt.GetAt() ); \r\n\tmt.GetUp().Normalize();\r\n\r\n\t// Add on rotation.\r\n\tmt.RotateX( Mth::DegToRad(m_ax) );\r\n\tmt.RotateY( Mth::DegToRad(m_ay) );\r\n\tmt.RotateZ( Mth::DegToRad(m_az) );\r\n\r\n//\tpright.set( mt.GetRight()[X], mt.GetRight()[Y], mt.GetRight()[Z] );\r\n//\tpup.set( mt.GetUp()[X], mt.GetUp()[Y], mt.GetUp()[Z] );\r\n//\tpat.set( mt.GetAt()[X], mt.GetAt()[Y], mt.GetAt()[Z] );\r\n\r\n\t// Emit particles.\r\n\tfor ( int lp = first; lp < last; lp++ )\r\n\t{\r\n\t\tif ( m_life_set )\r\n\t\t{\r\n\t\t\t// Random values for this emission.\r\n\t\t\tfloat rx = next_random();\r\n\t\t\tfloat ry = next_random();\r\n\r\n\t\t\t// Calculate emission initial velocity.\t\t\r\n\t\t\tMth::Vector velocity;\r\n\t\t\tvelocity[X] = rx * ( Mth::PI * ( m_emit_angle_spread / 4.0f ) );\r\n\t\t\tvelocity[Y] = ry * ( Mth::PI * ( m_emit_angle_spread / 4.0f ) );  \r\n\t\t\tvelocity[Z] = 1.0f - (( velocity[X] * velocity[X] ) + ( velocity[Y] * velocity[Y] ));\r\n\t\t\tvelocity[W] = 1.0f;\r\n\r\n\t\t\tfloat speed_mul = ( ( m_speed_max - m_speed_min ) * ((float)rand() / RAND_MAX ) ) + m_speed_min;\r\n\t\t\tvelocity[X] *= speed_mul;\r\n\t\t\tvelocity[Y] *= speed_mul;\r\n\t\t\tvelocity[Z] *= speed_mul;\r\n\r\n\t\t\t// Get new rx, ry to make the particles cross over one another.\r\n\t\t\tif ( m_random_angle )\r\n\t\t\t{\r\n\t\t\t\trx = next_random();\r\n\t\t\t\try = next_random();\r\n\t\t\t}\r\n\r\n\t\t\t// Normalize rx, ry to make a circular emission.\r\n\t\t\tif ( m_circular_emit )\r\n\t\t\t{\r\n\t\t\t\tfloat l = 1.0f / sqrtf( ( rx * rx ) + ( ry * ry ) );\r\n\t\t\t\trx = rx * ( l * (float)fabs( rx ) );\t\t// Note: length is scaled by random factor.\r\n\t\t\t\try = ry * ( l * (float)fabs( ry ) );\r\n\t\t\t}\r\n\r\n\t\t\t// Set position around emitter width/height.\r\n\t\t\tMth::Vector pos;\r\n\t\t\tpos[X] = m_emit_w * rx;\r\n\t\t\tpos[Y] = m_emit_h * ry;\r\n\t\t\tpos[Z] = 0.0f;\r\n\t\t\tpos[W] = 1.0f;\r\n\r\n\t\t\t// Set force.\r\n\t\t\tmp_particle_array[lp].m_fx = m_fx;\r\n\t\t\tmp_particle_array[lp].m_fy = m_fy;\r\n\t\t\tmp_particle_array[lp].m_fz = m_fz;\r\n\r\n\t\t\t// Set particle w/h\r\n\t\t\tmp_particle_array[lp].m_sw = m_sw;\r\n\t\t\tmp_particle_array[lp].m_sh = m_sh;\r\n\t\t\tmp_particle_array[lp].m_ew = m_ew;\r\n\t\t\tmp_particle_array[lp].m_eh = m_eh;\r\n\r\n\t\t\t// Set time & life.\r\n\t\t\tmp_particle_array[lp].m_time = 0.0f;\r\n\t\t\tmp_particle_array[lp].m_life = ( ( m_life_max - m_life_min ) * ((float)rand() / RAND_MAX ) ) + m_life_min;\r\n\r\n\t\t\t// Orient the particles to the target.\r\n\t\t\tMth::Vector v;\r\n\t\t\tv = mt.Transform( velocity );\r\n\t\t\tmp_particle_array[lp].m_vx = v[X];\r\n\t\t\tmp_particle_array[lp].m_vy = v[Y];\r\n\t\t\tmp_particle_array[lp].m_vz = v[Z];\r\n\t\t\t\r\n\t\t\tv = mt.Transform( pos );\r\n\r\n\t\t\tfor ( int lp2 = 0; lp2 < plat_get_num_vertex_lists(); lp2++ )\r\n\t\t\t{\r\n\t\t\t\tplat_set_position( lp, lp2, v[X], v[Y], v[Z] );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Set particle w/h\r\n\t\t\tmp_particle_array[lp].m_sw = m_sw;\r\n\t\t\tmp_particle_array[lp].m_sh = m_sh;\r\n\t\t\tmp_particle_array[lp].m_ew = m_ew;\r\n\t\t\tmp_particle_array[lp].m_eh = m_eh;\r\n\r\n\t\t\t// Set time & life.\r\n\t\t\tmp_particle_array[lp].m_time = 0.0f;\r\n\t\t\tmp_particle_array[lp].m_life = ( ( m_life_max - m_life_min ) * ((float)rand() / RAND_MAX ) ) + m_life_min;\r\n\r\n\t\t\t// Screen-facing poly. Just set to 0,0,0.\r\n\t\t\tfor ( int lp2 = 0; lp2 < plat_get_num_vertex_lists(); lp2++ )\r\n\t\t\t{\r\n\t\t\t\tplat_set_position( lp, lp2, 0, 0, 0 );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n}\r\n\r\nvoid CParticle::set_emit_script( uint32 checksum, Script::CStruct* pParams )\r\n{\r\n\tif ( checksum )\r\n\t{\r\n\t\tif ( !mp_emit_script )\r\n\t\t{\r\n\t\t\tmp_emit_script = new Script::CScript();\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tmp_emit_script->SetCommentString(\"Created in CParticle::set_emit_script(...)\");\r\n\t\t\t#endif\r\n\t\t}\r\n\t\tif ( !mp_params )\r\n\t\t{\r\n\t\t\tmp_params = new Script::CStruct;\r\n\t\t}\r\n\t\tmp_params->AppendStructure( pParams );\r\n\t\tmp_emit_script->SetScript( checksum, mp_params, this );\r\n//\t\tmp_emit_script->Update();\r\n\t}\r\n}\r\n\r\nvoid CParticle::set_update_script( uint32 checksum, Script::CStruct* pParams )\r\n{\r\n\tif ( checksum )\r\n\t{\r\n\t\tif ( !mp_update_script )\r\n\t\t{\r\n\t\t\tmp_update_script = new Script::CScript();\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tmp_update_script->SetCommentString(\"Created in CParticle::set_update_script(...)\");\r\n\t\t\t#endif\r\n\t\t}\r\n\t\tif ( !mp_params )\r\n\t\t{\r\n\t\t\tmp_params = new Script::CStruct;\r\n\t\t}\r\n\t\tmp_params->AppendStructure( pParams );\r\n\t\tmp_update_script->SetScript( checksum, mp_params, this );\r\n\t}\r\n}\r\n\r\n\r\n// Refresh a particle system after things like position have changed \r\n\r\nvoid CParticle::Refresh()\r\n{\r\n\tplat_build_path();\r\n}\r\n\r\n\r\n\r\nvoid CParticle::SetActive( bool active )\r\n{\r\n\tm_active = active;\r\n\tplat_set_active( active );\r\n}\r\n\r\n/******************************************************************/\r\n/*   CParticle::CallMemberFunction                               */\r\n/*   Call a member function, based on a checksum                  */\r\n/*   This is usually the checksum of the name of the function     */\r\n/*   but can actually be any number, as it just uses a switch     */\r\n/*   note this is a virtual function, so the same checksum        */\r\n/*   can do differnet things for different objects                */\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CParticle::CallMemberFunction( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n    \r\n\tDbg_MsgAssert(pScript,(\"NULL pScript\"));\r\n\r\n\tswitch(Checksum)\r\n\t{\r\n\t\t// @script | SetPos | Sets the position of the particle system.\r\n\t\t// @parmopt vector | pos | world position.\r\n\t\t// @parmopt float | x\t| x world position.\r\n\t\t// @parmopt float | y\t| y world position.\r\n\t\t// @parmopt float | z\t| z world position.\r\n\t\tcase 0x99cd17b:\t\t// SetPos\r\n\t\t\t{\r\n\t\t\t\tMth::Vector pos;\r\n\t\t\t\tfloat x = 0.0f;\r\n\t\t\t\tfloat y = 0.0f;\r\n\t\t\t\tfloat z = 0.0f;\r\n\t\t\t\tif ( pParams->GetVector(CRCD(0x7f261953,\"pos\"),&pos) )\r\n\t\t\t\t{\r\n\t\t\t\t\tx = pos[X];\r\n\t\t\t\t\ty = pos[Y];\r\n\t\t\t\t\tz = pos[Z];\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpParams->GetFloat(CRCD(0x7323e97c,\"x\"),&x);\r\n\t\t\t\t\tpParams->GetFloat(CRCD(0x424d9ea,\"y\"),&y);\r\n\t\t\t\t\tpParams->GetFloat(CRCD(0x9d2d8850,\"z\"),&z);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tset_pos( x, y, z );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t// @script | SetSpeedRange | Sets the min & max speed of the particles upon emission.\r\n\t\t// @parm float | min | minimum speed. If only min is provided, all speeds will be set to min.\r\n\t\t// @parmopt float | max | maximum speed.\r\n\t\tcase 0x63274395:\t\t// SetSpeedRange\r\n\t\t\t{\r\n\t\t\t\tfloat min = 0.0f;\r\n\t\t\t\tpParams->GetFloat(CRCD(0x5e84e22f,\"min\"),&min);\r\n\t\t\t\tfloat max = min;\r\n\t\t\t\tpParams->GetFloat(CRCD(0x6289dd76,\"max\"),&max);\r\n\r\n\t\t\t\tset_speed_range( min, max );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t// @script | SetEmitRange | Sets the emission range (width and height).\r\n\t\t// @parm float | width | Width of emission area. If only width is provided, height will be set to width.\r\n\t\t// @parmopt float | height | Height of emission area.\r\n\t\tcase 0x8ffdef38:\t\t// SetEmitRange\r\n\t\t\t{\r\n\t\t\t\tfloat width = 0.0f;\r\n\t\t\t\tpParams->GetFloat(CRCD(0x73e5bad0,\"width\"),&width);\r\n\t\t\t\tfloat height = width;\r\n\t\t\t\tpParams->GetFloat(CRCD(0xab21af0,\"height\"),&height);\r\n\t\t\t\r\n\t\t\t\tset_emit_range( width, height );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t// @script | SetAngleSpread | Sets the angle spread for particle emissions.\r\n\t\t// @parm float | spread | Angle spread. 0=No spread. 1=Full spread (180 degrees).\r\n\t\tcase 0x7911855b:\t\t// SetAngleSpread\r\n\t\t\t{\r\n\t\t\t\tfloat spread = 0.0f;\r\n\t\t\t\tpParams->GetFloat(CRCD(0x834a5f87,\"spread\"),&spread);\r\n\t\t\t\r\n\t\t\t\tset_emit_angle_spread( spread );\r\n\t\t\t}\r\n\t\tbreak;\r\n\t\r\n\r\n\t\t// @script | SetRandomAngle | Sets whether the emission angle is random or not.\r\n\t\t// @parm int | random | 1 means choose a random angle regardless of the emission position. 0 means use the emission position to define the emission angle.\r\n\t\tcase 0xdb8621f7:\t\t// SetRandomAngle\r\n\t\t\t{\r\n\t\t\t\tint random = 0;\r\n\t\t\t\tpParams->GetInteger(\"random\",(int*)&random);\r\n\t\t\t\r\n\t\t\t\tset_random_angle( random > 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | SetCircularEmit | Sets whether the emission area is circular or square.\r\n\t\t// @parm int | circular | 1 means use a circular emission area. 0 means use a square emission area.\r\n\t\tcase 0xe985a9a6:\t\t// SetCircularEmit\r\n\t\t\t{\r\n\t\t\t\tint circular = 0;\r\n\t\t\t\tpParams->GetInteger(\"circular\",(int*)&circular);\r\n\t\t\t\r\n\t\t\t\tset_circular_emit( circular > 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | SetForce | Sets the force acting on the particles.\r\n\t\t// @parmopt vector | force\t| Force.\r\n\t\t// @parmopt float | x\t| x force.\r\n\t\t// @parmopt float | y\t| y force.\r\n\t\t// @parmopt float | z\t| z force.\r\n\t\tcase 0xa075ee45:\t\t// SetForce\r\n\t\t\t{\r\n\t\t\t\tMth::Vector force;\r\n\t\t\t\tfloat x = 0.0f;\r\n\t\t\t\tfloat y = 0.0f;\r\n\t\t\t\tfloat z = 0.0f;\r\n\t\t\t\tif ( pParams->GetVector(\"force\",&force) )\r\n\t\t\t\t{\r\n\t\t\t\t\tx = force[X];\r\n\t\t\t\t\ty = force[Y];\r\n\t\t\t\t\tz = force[Z];\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpParams->GetFloat(\"x\",&x);\r\n\t\t\t\t\tpParams->GetFloat(\"y\",&y);\r\n\t\t\t\t\tpParams->GetFloat(\"z\",&z);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tset_force( x, y, z );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | SetParticleSize | Sets the size of the particles.\r\n\t\t// @parm float | sw | Start width of the particle. If only width is provided, height is set to width.\r\n\t\t// @parmopt float | sh | Start height of the particle.\r\n\t\t// @parm float | ew | End width of the particle. If only width is provided, height is set to width.\r\n\t\t// @parmopt float | eh | End height of the particle.\r\n\t\tcase 0x2a479569:\t\t// SetParticleSize\r\n\t\t\t{\r\n\t\t\t\tfloat sw = 0.0f;\r\n\t\t\t\tpParams->GetFloat(\"sw\",&sw);\r\n\t\t\t\tfloat sh = sw;\r\n\t\t\t\tpParams->GetFloat(\"sh\",&sh);\r\n\t\t\t\r\n\t\t\t\tset_particle_start_size( sw, sh );\r\n\r\n\t\t\t\tfloat ew = sw;\r\n\t\t\t\tfloat eh;\r\n\t\t\t\tif ( pParams->GetFloat(\"ew\",&ew) )\r\n\t\t\t\t{\r\n\t\t\t\t\teh = ew;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\teh = sh;\r\n\t\t\t\t}\r\n\t\t\t\tpParams->GetFloat(\"eh\",&eh);\r\n\t\t\t\r\n\t\t\t\tset_particle_end_size( ew, eh );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | SetLife | Sets the life of the particles in seconds.\r\n\t\t// @parm float | min | Minimum life of the particle. 1.0 = 1 second.\r\n\t\t// @parmopt float | max | Maximum life of the particle. 1.0 = 1 second. If not specified, will be set to same as min.\r\n\t\tcase 0xd3f1d333:\t\t// SetLife\r\n\t\t\t{\r\n\t\t\t\tfloat min = 0.0f;\r\n\t\t\t\tpParams->GetFloat(\"min\",&min);\r\n\t\t\t\tfloat max = min;\r\n\t\t\t\tpParams->GetFloat(\"max\",&max);\r\n\t\t\t\r\n\t\t\t\tset_particle_life( min, max );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | SetEmitTarget | Sets the target position that the particle system will emit particles towards.\r\n\t\t// @parmopt vector | target\t| Target.\r\n\t\t// @parmopt float | x\t| x target.\r\n\t\t// @parmopt float | y\t| y target.\r\n\t\t// @parmopt float | z\t| z target.\r\n\t\tcase 0xb373fb6e:\t\t// SetEmitTarget\r\n\t\t\t{\r\n\t\t\t\tMth::Vector target;\r\n\t\t\t\tfloat x = 0.0f;\r\n\t\t\t\tfloat y = 0.0f;\r\n\t\t\t\tfloat z = 0.0f;\r\n\t\t\t\tif ( pParams->GetVector(\"target\",&target) )\r\n\t\t\t\t{\r\n\t\t\t\t\tx = target[X];\r\n\t\t\t\t\ty = target[Y];\r\n\t\t\t\t\tz = target[Z];\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpParams->GetFloat(\"x\",&x);\r\n\t\t\t\t\tpParams->GetFloat(\"y\",&y);\r\n\t\t\t\t\tpParams->GetFloat(\"z\",&z);\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// If it's just 0,1,0, then rotate it by the angles of the node\r\n\t\t\t\tif (x == 0.0f && y == 1.0f && z == 0.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\t// not done here though....\r\n\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tset_emit_target( x, y, z );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t// @script | SetEmitAngle | Sets the emission angle. This is done after the target, so you can set a target as well as angles to rotate in addition to the target angle. Target defaults to 0,1,0 (straight up), so all angles rotate from there.\r\n\t\t// @parmopt vector | angle\t| Angle (in degrees).\r\n\t\t// @parmopt float | x\t| x angle.\r\n\t\t// @parmopt float | y\t| y angle.\r\n\t\t// @parmopt float | z\t| z angle.\r\n\t\tcase 0x1cfbf078:\t\t// SetEmitAngle\r\n\t\t\t{\r\n\t\t\t\tMth::Vector angle;\r\n\t\t\t\tfloat x = 0.0f;\r\n\t\t\t\tfloat y = 0.0f;\r\n\t\t\t\tfloat z = 0.0f;\r\n\t\t\t\tif ( pParams->GetVector(\"angle\",&angle) )\r\n\t\t\t\t{\r\n\t\t\t\t\tx = angle[X];\r\n\t\t\t\t\ty = angle[Y];\r\n\t\t\t\t\tz = angle[Z];\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpParams->GetFloat(\"x\",&x);\r\n\t\t\t\t\tpParams->GetFloat(\"y\",&y);\r\n\t\t\t\t\tpParams->GetFloat(\"z\",&z);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tset_emit_angle( x, y, z );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t// CreateParticleSystem colorentries=n\t// default 2.\r\n\t\t// SetColorEntry slot=n r=n g=n b=n\r\n\r\n\r\n\t\t// @script | SetColor | Sets the color for the next particle emission.\r\n\t\t// @parmopt int | corner | | The corner to set. Omitting this paramter means set all corners.\r\n\t\t// @parmopt int | sr | | Start red color element to set (0-255). 128 is normal.\r\n\t\t// @parmopt int | sg | | Start green color element to set (0-255). 128 is normal.\r\n\t\t// @parmopt int | sb | | Start blue color element to set (0-255). 128 is normal.\r\n\t\t// @parmopt int | sa | | Start alpha color element to set (0-255). 255 is opaque, 0 is invisible.\r\n\t\t// @parmopt int | mr | | Mid red color element to set (0-255). 128 is normal.\r\n\t\t// @parmopt int | mg | | Mid green color element to set (0-255). 128 is normal.\r\n\t\t// @parmopt int | mb | | Mid blue color element to set (0-255). 128 is normal.\r\n\t\t// @parmopt int | ma | | Mid alpha color element to set (0-255). 255 is opaque, 0 is invisible.\r\n\t\t// @parmopt int | er | | End red color element to set (0-255). 128 is normal.\r\n\t\t// @parmopt int | eg | | End green color element to set (0-255). 128 is normal.\r\n\t\t// @parmopt int | eb | | End blue color element to set (0-255). 128 is normal.\r\n\t\t// @parmopt int | ea | | End alpha color element to set (0-255). 255 is opaque, 0 is invisible.\r\n\t\t// @parmopt int | midtime | | Sets the % through the particle's life that the mid color is reached.\r\n\t\t// 0.5 means halfway through. Use values from 0-1. By default, the mid color is not used. By setting\r\n\t\t// the mid time, the middle color will be used.\r\n\t\tcase 0x514b2584:\t\t// SetColor\r\n\t\t\t{\r\n\t\t\t\tint corner;\r\n\t\t\t\tint first = 0;\r\n\t\t\t\tint last = 0;\r\n\t\t\t\tif ( pParams->GetInteger(\"corner\",&corner) )\r\n\t\t\t\t{\r\n\t\t\t\t\tfirst = last = corner;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tfirst = 0;\r\n\t\t\t\t\tlast = plat_get_num_particle_colors() - 1;\r\n\t\t\t\t}\r\n\t\t\t\tif ( ( first < plat_get_num_particle_colors() ) && ( last < plat_get_num_particle_colors() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int entry = first; entry < ( last + 1 ); entry++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( entry < plat_get_num_particle_colors() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tint elem;\r\n\t\t\t\t\t\t\tif ( pParams->GetInteger(\"er\",&elem) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tplat_set_er( entry, elem );\r\n\t\t\t\t\t\t\t\tm_end_set = true;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif ( pParams->GetInteger(\"eg\",&elem) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tplat_set_eg( entry, elem );\r\n\t\t\t\t\t\t\t\tm_end_set = true;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif ( pParams->GetInteger(\"eb\",&elem) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tplat_set_eb( entry, elem );\r\n\t\t\t\t\t\t\t\tm_end_set = true;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif ( pParams->GetInteger(\"ea\",&elem) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tplat_set_ea( entry, elem );\r\n\t\t\t\t\t\t\t\tm_end_set = true;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif ( pParams->GetInteger(\"mr\",&elem) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tplat_set_mr( entry, elem );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif ( pParams->GetInteger(\"mg\",&elem) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tplat_set_mg( entry, elem );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif ( pParams->GetInteger(\"mb\",&elem) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tplat_set_mb( entry, elem );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif ( pParams->GetInteger(\"ma\",&elem) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tplat_set_ma( entry, elem );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif ( pParams->GetInteger(\"sr\",&elem) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tplat_set_sr( entry, elem );\r\n\t\t\t\t\t\t\t\tif ( !m_end_set ) plat_set_er( entry, elem ); \r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif ( pParams->GetInteger(\"sg\",&elem) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tplat_set_sg( entry, elem );\r\n\t\t\t\t\t\t\t\tif ( !m_end_set ) plat_set_eg( entry, elem ); \r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif ( pParams->GetInteger(\"sb\",&elem) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tplat_set_sb( entry, elem );\r\n\t\t\t\t\t\t\t\tif ( !m_end_set ) plat_set_eb( entry, elem ); \r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif ( pParams->GetInteger(\"sa\",&elem) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tplat_set_sa( entry, elem );\r\n\t\t\t\t\t\t\t\tif ( !m_end_set ) plat_set_ea( entry, elem ); \r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tpParams->GetFloat(\"midtime\",&m_mid_time);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t// @script | Emit | Emits the specified number of particles.\r\n\t\t// @parm int | num | Number of particles to emit.\r\n\t\tcase 0x711b1a6a:\t\t// Emit\r\n\t\t\t{\r\n\t\t\t\tint num = 1;\t\t// Defaults to 1 particle emitted.\r\n\t\t\t\tpParams->GetInteger(\"num\",&num);\r\n\r\n\t\t\t\temit( num );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t// @script | EmitRate | Emits at the specified rate - 1=1 particle per frame.\r\n\t\t// @parm float | rate | The rate to emit at.\r\n\t\tcase 0x35b65bd4:\t\t// EmitRate\r\n\t\t\t{\r\n\t\t\t\tfloat rate = 1.0f;\t\t// Defaults to 1 particle emitted per frame.\r\n\t\t\t\tpParams->GetFloat(\"rate\",&rate);\r\n\r\n\t\t\t\tset_emit_rate( rate );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t// @script | BuildPath | Builds a path based on the current physics data.\r\n\t\tcase 0xa8699e0e:\t\t// BuildPath\r\n\t\t\t{\r\n\t\t\t\tplat_build_path();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | EmptySystem | Empties the particle system immediately (sets number of particles to 0.\r\n\t\tcase 0x482482c6:\t\t// EmptySystem\r\n\t\t\t{\r\n\t\t\t\tm_num_particles = 0;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\treturn Obj::CMovingObject::CallMemberFunction( Checksum, pParams, pScript );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gfx/nxparticle.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxParticle.h\r\n\r\n\r\n\r\n#ifndef\t__GFX_NXPARTICLE_H__\r\n#define\t__GFX_NXPARTICLE_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <gfx/image/imagebasic.h>\r\n#include <gfx/nxtexture.h>\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n#include <sk/objects/movingobject.h>\r\n\r\n\r\n\r\nnamespace Script\r\n{\r\n\r\n// Forward declarations\r\nclass CScript;\r\n\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\n// Forward declarations\r\nclass CParticleEntry;\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n// The CParticle class is the platform independent abstract base class\r\n// of the platform specific CParticle classes\r\nclass\tCParticle : public Obj::CMovingObject\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCParticle();\r\n\t\t\t\t\t\t\tCParticle( uint32 checksum );\r\n\t\t\t\t\t\t\tCParticle( uint32 checksum, int maxParticles );\r\n\tvirtual\t\t\t\t\t~CParticle();\r\n\r\n\tvoid\t\t\t\t\tprocess( float delta_time );\r\n\tvoid\t\t\t\t\trender( void );\r\n\r\n\tvoid\t\t\t\t\temit( int count );\r\n\r\n\tvoid\t\t\t\t\tset_pos( float x, float y, float z )\t\t\t{ m_pos[X] = x; m_pos[Y] = y; m_pos[Z] = z; }\r\n\tvoid\t\t\t\t\tset_speed_range( float min, float max )\t\t\t{ m_speed_min = min; m_speed_max = max; }\r\n\tvoid\t\t\t\t\tset_emit_range( float width, float height )\t\t{ m_emit_w = width; m_emit_h = height; }\r\n\tvoid\t\t\t\t\tset_emit_angle_spread( float spread )\t\t\t{ m_emit_angle_spread = spread; }\r\n\tvoid\t\t\t\t\tset_random_angle( bool random_angle )\t\t\t{ m_random_angle = random_angle; }\r\n\tvoid\t\t\t\t\tset_circular_emit( bool circular_emit )\t\t\t{ m_circular_emit = circular_emit; }\r\n\tvoid\t\t\t\t\tset_force( float x, float y, float z )\t\t\t{ m_fx = x; m_fy = y; m_fz = z; }\r\n\tvoid\t\t\t\t\tset_particle_start_size( float w, float h )\t\t{ m_sw = w; m_sh = h; }\r\n\tvoid\t\t\t\t\tset_particle_end_size( float w, float h )\t\t{ m_ew = w; m_eh = h; }\r\n\tvoid\t\t\t\t\tset_particle_life( float min, float max )\t\t{ m_life_min = min; m_life_max = max; m_life_set = true; }\r\n\tvoid\t\t\t\t\tset_emit_target( float x, float y, float z )\t{ m_tx = x; m_ty = y; m_tz = z; }\r\n\tvoid\t\t\t\t\tset_emit_angle( float x, float y, float z )\t\t{ m_ax = x; m_ay = y; m_az = z; }\r\n\tvoid\t\t\t\t\tset_emit_rate( float rate )\t\t\t\t\t\t{ m_emit_rate = rate; }\r\n\r\n\tvoid\t\t\t\t\tset_checkum(uint32 checksum) {m_checksum = checksum;}\r\n\r\n\tvoid\t\t\t\t\tdelete_when_empty( void )\t\t\t\t\t\t{ m_delete_when_empty = true; }\r\n\r\n\tbool\t\t\t\t\tCallMemberFunction (uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript);\t// Call a member function based on the checksum of the function name\r\n\r\n\tvoid\t\t\t\t\tset_emit_script( uint32 checksum, Script::CStruct* pParams );\r\n\tvoid\t\t\t\t\tset_update_script( uint32 checksum, Script::CStruct* pParams );\r\n\r\n\tvoid\t\t\t\t\tSetActive( bool active );\r\n\tbool\t\t\t\t\tIsActive()\t\t\t\t\t\t\t\t\t\t{ return m_active; }\r\n\t\r\n\tvoid\t\t\t\t\tSetEmitting( bool emitting )\t\t\t\t\t{ m_emitting = emitting; }\r\n\tbool\t\t\t\t\tIsEmitting()\t\t\t\t\t\t\t\t\t{ return m_emitting; }\r\n\r\n\r\n\tvoid\t\t\t\t\tSetPerm( bool perm )\t\t\t\t\t\t\t{ m_perm = perm; }\r\n\tbool\t\t\t\t\tIsPerm()\t\t\t\t\t\t\t\t\t\t{ return m_perm; }\r\n\r\n\tvoid\t\t\t\t\tSetNumParticles( int num )\t\t\t\t\t\t{ m_num_particles = num; }\r\n\tint\t\t\t\t\t\tGetNumParticles( void )\t\t\t\t\t\t\t{ return m_num_particles; }\r\n\r\n\tvoid \t\t\t\t\tRefresh();\t\t\r\n\r\n\r\nprotected:\r\n\t// Extensions for Mike's system.\r\n\tfloat\t\t\t\t\tm_emit_rate;\t\t\t// The rate of emission - 1.0 = 1 per frame.\r\n\r\n\t// Member variables (protected so the p-classes can access them)\r\n\tint\t\t\t\t\t\tm_max_particles;\t\t// Maximum size of particle array.\r\n\tint\t\t\t\t\t\tm_num_particles;\t\t// Current number of active particles.\r\n\t\t\r\n\tfloat\t\t\t\t\tm_speed_min;\t\t\t// Initial Speed setting.\r\n\tfloat\t\t\t\t\tm_speed_max;\r\n\tfloat\t\t\t\t\tm_emit_w, m_emit_h;\t\t// Emitter dimensions.\r\n\tfloat\t\t\t\t\tm_emit_angle_spread;\t// Angle spread from 0 to 1.\r\n\t\r\n\t// Should be changed to a flag value...\r\n\tbool\t\t\t\t\tm_random_angle;\t\t\t// true means use a random angle, regardless of the emit pos.\r\n\tbool\t\t\t\t\tm_circular_emit;\t\t// true means emit in a circle.\r\n\r\n\tfloat\t\t\t\t\tm_fx, m_fy, m_fz;\t\t// Initial Force values. fy is gravity, will not dec to 0.\r\n\tfloat\t\t\t\t\tm_sw, m_sh;\t\t\t\t// Initial width & height.\r\n\tfloat\t\t\t\t\tm_ew, m_eh;\t\t\t\t// Initial width & height.\r\n\tfloat\t\t\t\t\tm_life_min, m_life_max;\t// Life min & max\r\n\r\n\tfloat\t\t\t\t\tm_tx, m_ty, m_tz;\t\t// Target position.\r\n\tfloat\t\t\t\t\tm_ax, m_ay, m_az;\t\t// Angle rotations.\r\n\t\r\n\tuint32\t\t\t\t\tm_checksum;\r\n\r\n\tbool\t\t\t\t\tm_delete_when_empty;\t// When m_num_particles == 0, this system will self-delete.\r\n\r\n\tCParticleEntry*\t\t\tmp_particle_array;\t\t// Pointer to array of particles.\r\n\r\n\tScript::CScript*\t\tmp_emit_script;\r\n\tScript::CScript*\t\tmp_update_script;\r\n\r\n\t// parameters that will be passed to the emit/update scripts\r\n\t// generally used for passing the ID of a moving object\r\n\tScript::CStruct*\t\tmp_params;\r\n\tbool\t\t\t\t\tm_active;\r\n\tbool\t\t\t\t\tm_emitting;\r\n\r\n\tfloat\t\t\t\t\tm_mid_time;\t\t\t\t\t// Time of the mid color.\r\n\r\n\tbool\t\t\t\t\tm_life_set;\r\n\r\n\tbool\t\t\t\t\tm_end_set;\r\n\r\n\tbool\t\t\t\t\tm_perm;\t\t\t\t\t\t// true if not deleted between levels\r\n\r\n\t// The virtual functions have a stub implementation.\r\nprivate:\r\n\tvirtual void\t\t\tplat_render( void );\r\n\tvirtual void\t\t\tplat_get_position( int entry, int list, float * x, float * y, float * z );\r\n\tvirtual void\t\t\tplat_set_position( int entry, int list, float x, float y, float z );\r\n\tvirtual void\t\t\tplat_add_position( int entry, int list, float x, float y, float z );\r\n\tvirtual int\t\t\t\tplat_get_num_vertex_lists( void );\r\n\tvirtual int\t\t\t\tplat_get_num_particle_colors( void );\r\n\tvirtual void\t\t\tplat_set_sr( int entry, uint8 value );\r\n\tvirtual void\t\t\tplat_set_sg( int entry, uint8 value );\r\n\tvirtual void\t\t\tplat_set_sb( int entry, uint8 value );\r\n\tvirtual void\t\t\tplat_set_sa( int entry, uint8 value );\r\n\tvirtual void\t\t\tplat_set_mr( int entry, uint8 value );\r\n\tvirtual void\t\t\tplat_set_mg( int entry, uint8 value );\r\n\tvirtual void\t\t\tplat_set_mb( int entry, uint8 value );\r\n\tvirtual void\t\t\tplat_set_ma( int entry, uint8 value );\r\n\tvirtual void\t\t\tplat_set_er( int entry, uint8 value );\r\n\tvirtual void\t\t\tplat_set_eg( int entry, uint8 value );\r\n\tvirtual void\t\t\tplat_set_eb( int entry, uint8 value );\r\n\tvirtual void\t\t\tplat_set_ea( int entry, uint8 value );\r\n\tvirtual void\t\t\tplat_set_active( bool active );\r\n\tvirtual void\t\t\tplat_build_path( void );\r\n\r\n\tvoid\t\t\t\t\tset_defaults( void );\r\n};\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n// Particle system entry. Does very little other than hold information. The controller does all the work.\r\nclass CParticleEntry\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCParticleEntry();\r\n\t\t\t\t\t\t\t~CParticleEntry();\r\n\r\n//\t\t\t\t\t\t\tfloat\t\t\t\t\tm_x, m_y, m_z;\t\t\t\t// Current x, y, z positions.\r\n\t\t\t\t\t\t\tfloat\t\t\t\t\tm_vx, m_vy, m_vz;\t\t\t// Current velocity.\r\n\t\t\t\t\t\t\tfloat\t\t\t\t\tm_fx, m_fy, m_fz;\t\t\t// Current force.\r\n\t\t\t\t\t\t\tfloat\t\t\t\t\tm_sw, m_sh;\t\t\t\t\t// Start Width & Height.\r\n\t\t\t\t\t\t\tfloat\t\t\t\t\tm_ew, m_eh;\t\t\t\t\t// EndWidth & Height.\r\n\t\t\t\t\t\t\tfloat\t\t\t\t\tm_time, m_life;\t\t\t\t// Current time & life of particle.\r\nprotected:\r\nprivate:\r\n\tfriend CParticle;\r\n};\r\n\r\n}\r\n\r\n#endif // \r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/nxparticlemgr.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticleMgr.cpp\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#include <core/defines.h>\r\n#include \"gfx/nx.h\"\r\n#include \"gfx/nxparticlemgr.h\"\r\n\r\nnamespace Nx\r\n{\r\nvoid process_particles( float delta_time )\r\n{\r\n//\tplat_process_particles( delta_time );\r\n\tif( CEngine::sGetParticleTable() )\r\n\t{\r\n\t\tCParticle *p_particle;\r\n\t\tCEngine::sGetParticleTable()->IterateStart();\r\n\t\twhile(( p_particle = CEngine::sGetParticleTable()->IterateNext()))\r\n\t\t{\r\n\t\t\tif ( p_particle->IsActive() ) p_particle->process( delta_time );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid render_particles( void )\r\n{\r\n//\tplat_process_particles( delta_time );\r\n\tif( CEngine::sGetParticleTable() )\r\n\t{\r\n\t\tCParticle *p_particle;\r\n\t\tCEngine::sGetParticleTable()->IterateStart();\r\n\t\twhile(( p_particle = CEngine::sGetParticleTable()->IterateNext()))\r\n\t\t{\r\n\t\t\tif ( p_particle->IsActive() ) p_particle->render();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nCParticle* get_particle( uint32 checksum )\r\n{\r\n\tCParticle *p_particle = NULL;\r\n\tif( CEngine::sGetParticleTable() )\r\n\t{\r\n\t\tp_particle = CEngine::sGetParticleTable()->GetItem( checksum );\r\n\t}\r\n\treturn p_particle;\r\n}\r\n\r\nCParticle* create_particle( uint32 checksum, uint32 type_checksum, int max_particles, int max_streams, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history, int perm )\r\n{\r\n\t// Types to add:\r\n\t// 1. Flat color quad\r\n\t// 2. Gouraud quad\r\n\t// 3. n sided glow (center color + outer color)\r\n\t// 4. n sided 2 layer glow ( center color + mid color + outer color)\r\n\t// 5. n spiked star (center color + mid color + spike color)\r\n\t// 6. Lines (current color + previous color)\r\n\t// 7. Ribbons - volumetric lines made from quads (current color + previous color)\r\n\r\n\tCParticle *p_particle =  plat_create_particle( checksum, type_checksum, max_particles, max_streams, texture_checksum, blendmode_checksum, fix, num_segments, split, history );\r\n\t\r\n\tp_particle->SetPerm(perm);\r\n\t\r\n\tp_particle->SetActive( true );\r\n\tp_particle->SetEmitting( false ); \t// This is already set to false, this si just a reminder\r\n\r\n\t// Add to our list of particles.\r\n\tCEngine::sGetParticleTable()->PutItem( checksum, p_particle );\r\n\treturn p_particle;\r\n}\r\n\r\nvoid destroy_particle( uint32 checksum )\r\n{\r\n\tCParticle * p = get_particle( checksum );\t \t// get item\r\n\tCEngine::sGetParticleTable()->FlushItem( checksum );\t\t// remove reference from hash table\r\n\tdelete p;\t\t\t\t\t\t\t\t\t\t// deleted particle, will remove itself from the table\r\n}\r\n\r\nvoid destroy_particle_when_empty( uint32 checksum )\r\n{\r\n\tCParticle * p = get_particle( checksum );\t \t// get item\r\n\tp->delete_when_empty();\r\n}\r\n\r\nvoid destroy_all_particles(  )\r\n{\r\n\tif( CEngine::sGetParticleTable() )\r\n\t{\r\n\t\tCParticle *p_particle;\r\n\t\tCEngine::sGetParticleTable()->IterateStart();\r\n\t\twhile(( p_particle = CEngine::sGetParticleTable()->IterateNext()))\r\n\t\t{\r\n\t\t\tdelete p_particle;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid destroy_all_temp_particles(  )\r\n{\r\n\tif( CEngine::sGetParticleTable() )\r\n\t{\r\n\t\tCParticle *p_particle;\r\n\t\tCEngine::sGetParticleTable()->IterateStart();\r\n\t\twhile(( p_particle = CEngine::sGetParticleTable()->IterateNext()))\r\n\t\t{\r\n\t\t\tif (!p_particle->IsPerm())\r\n\t\t\t{\r\n\t\t\t\tdelete p_particle;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n} // Nx\r\n"
  },
  {
    "path": "Code/Gfx/nxparticlemgr.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       p_nxParticleMgr.h\r\n//* OWNER:          Paul Robinson\r\n//* CREATION DATE:  3/27/2002\r\n//****************************************************************************\r\n\r\n#ifndef\t__GFX_P_NX_PARTICLE_MGR_H__\r\n#define\t__GFX_P_NX_PARTICLE_MGR_H__\r\n    \r\n#include \"gfx/nxparticle.h\"\r\n                   \r\nnamespace Nx\r\n{\r\n\r\nvoid process_particles( float delta_time );\r\nvoid render_particles( void );\r\nCParticle* get_particle( uint32 checksum );\r\nCParticle* create_particle( uint32 checksum, uint32 type_checksum, int max_particles, int max_streams, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history, int perm );\r\nvoid\t   destroy_particle( uint32 checksum );\r\nvoid\t   destroy_particle_when_empty( uint32 checksum );\r\nvoid destroy_all_particles(  );\r\nvoid destroy_all_temp_particles(  );\r\n\r\nvoid plat_process_particles( float delta_time );\r\nCParticle* plat_get_particle( uint32 checksum );\r\nCParticle* plat_create_particle( uint32 checksum, uint32 type_checksum, int max_particles, int max_streams, uint32 texture_checksum, uint32 blendmode_checksum, int fix, int num_segments, float split, int history );\r\n} // Nx\r\n\r\n#endif \r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/nxweather.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxWeather.cpp\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/math.h>\r\n#include <gfx/NxWeather.h>\r\n//#include <gel/scripting/struct.h>\r\n//#include <gel/scripting/script.h>\r\n//#include <sk/modules/frontend/frontend.h>\r\n//#include <gel/components/suspendcomponent.h>\r\n//#include <gfx/nx.h>\r\n//#include <gfx/debuggfx.h>\r\n//#include <sys/replay/replay.h>\r\n\r\n#define next_random() ((((float)rand() / RAND_MAX ) * 2.0f ) - 1.0f)\r\n\r\n//NsVector pright;\r\n//NsVector pup;\r\n//NsVector pat;\r\n\r\nnamespace\tNx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWeather::plat_update_grid( void )\r\n{\r\n\tprintf (\"STUB: plat_update_grid\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWeather::plat_process( float delta_time )\r\n{\r\n\tprintf (\"STUB: plat_process\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CWeather::plat_render( void )\r\n{\r\n\tprintf (\"STUB: plat_render\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWeather::plat_set_rain_blend_mode( uint32 blendmode_checksum, int fix )\r\n{\r\n\tprintf (\"STUB: plat_set_rain_blend_mode\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWeather::plat_set_splash_blend_mode( uint32 blendmode_checksum, int fix )\r\n{\r\n\tprintf (\"STUB: plat_set_splash_blend_mode\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWeather::plat_set_snow_blend_mode( uint32 blendmode_checksum, int fix )\r\n{\r\n\tprintf (\"STUB: plat_set_snow_blend_mode\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCWeather::CWeather()\r\n{\r\n\tm_rain_height = 2000.0f;\r\n\tm_rain_frames = 40;\r\n\tm_rain_length = 100.0f;\r\n\tm_rain_drops_per_frame = 0.0f;\r\n\tm_rain_top_color.r = 0x00;\r\n\tm_rain_top_color.g = 0x00;\r\n\tm_rain_top_color.b = 0x00;\r\n\tm_rain_top_color.a = 0x00;\r\n\tm_rain_bottom_color.r = 0xff;\r\n\tm_rain_bottom_color.g = 0xff;\r\n\tm_rain_bottom_color.b = 0xff;\r\n\tm_rain_bottom_color.a = 0xff;\r\n\r\n\tm_splash_per_frame = 0.0f;\r\n\tm_splash_life = 8;\r\n\tm_splash_size = 16.0f;\r\n\tm_splash_color.r = 0x80;\r\n\tm_splash_color.g = 0x80;\r\n\tm_splash_color.b = 0x80;\r\n\tm_splash_color.a = 0x80;\r\n\r\n\tm_snow_height = 500.0f;\r\n\tm_snow_frames = 254;\r\n\tm_snow_size = 4.0f;\r\n\tm_snow_flakes_per_frame = 0.0f;\r\n\tm_snow_color.r = 0x80;\r\n\tm_snow_color.g = 0x80;\r\n\tm_snow_color.b = 0x80;\r\n\tm_snow_color.a = 0x80;\r\n\r\n\tm_raining = true;\r\n\r\n\tm_system_active = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCWeather::~CWeather()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWeather::UpdateGrid( void )\r\n{\r\n\tplat_update_grid();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWeather::Process( float delta_time )\r\n{\r\n\tplat_process( delta_time );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWeather::Render( void )\r\n{\r\n\tplat_render();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetRainHeight | Sets the height of the rain above the ground.\r\n// @parm height | The height of the rain in inches - defaults to 2000 inches.\r\nbool CWeather::ScriptWeatherSetRainHeight( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tm_rain_height = 2000.0f;\t\t// Default\r\n\tpParams->GetFloat( NONAME, &m_rain_height );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetRainFrames | Sets the number of frames it takes a rain drop to fall.\r\n// @parm frames | Number of frames for the rain to fall from RainHeight to the ground. Defaults to 40 frames.\r\nbool CWeather::ScriptWeatherSetRainFrames( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tm_rain_frames = 40;\t\t// Default\r\n\tpParams->GetInteger( NONAME, &m_rain_frames );\r\n\tif ( m_rain_frames < 0 ) m_rain_frames = 0;\r\n\tif ( m_rain_frames > 254 ) m_rain_frames = 254;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetRainLength | Sets the length of the rain drops (the rain drop is a line).\r\n// @parm length | Length of the rain drops in inches. Defaults to 100 inches.\r\nbool CWeather::ScriptWeatherSetRainLength( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tm_rain_length = 100.0f;\t\t// Default\r\n\tpParams->GetFloat( NONAME, &m_rain_length );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetRainBlendMode | Sets the blendmode of the rain particles.\r\n// @parm blendmode | The name of the blend mode. Type are: blend/add/sub/modulate/brighten &\r\n// fixblend/fixadd/fixsub/fixmodulate/fixbrighten & diffuse (no blend at all). Defaults to fixadd.\r\n// @parmopt int | Fixed alpha value. Defaults to 64. Range is 0-255. Only required if using fix blend modes.\r\nbool CWeather::ScriptWeatherSetRainBlendMode( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 blendmode_checksum = 0;\r\n\tif ( !pParams->GetChecksum( NONAME, &blendmode_checksum ) )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\tint fix = 32;\t\t// Default\r\n\tpParams->GetInteger( NONAME, &fix );\r\n\r\n\tplat_set_rain_blend_mode( blendmode_checksum, fix );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetRainRate | Sets the rate that the rain drops fall in drops per frame.\r\n// @parm rate | The number of new drops of rain per frame. Defaults to 0 (off).\r\nbool CWeather::ScriptWeatherSetRainRate( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tm_rain_drops_per_frame = 0.0f;\t\t// Default\r\n\tpParams->GetFloat( NONAME, &m_rain_drops_per_frame );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetRainColor | Sets the color of the rain.\r\n// @parm top | The color of the rain at the top of the droplet. Defaults to 0x00000000\r\n// @parm bottom | The color of the rain at the bottom of the droplet. Defaults to 0xffffffff\r\nbool CWeather::ScriptWeatherSetRainColor( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 color;\r\n\r\n\tcolor = 0x00000000;\r\n\tpParams->GetInteger( \"top\", (int*)&color ); \r\n\r\n\tm_rain_top_color.r = (uint8)((color)&0xff);\r\n\tm_rain_top_color.g = (uint8)((color>>8)&0xff);\r\n\tm_rain_top_color.b = (uint8)((color>>16)&0xff);\r\n\tm_rain_top_color.a = (uint8)((color>>24)&0xff); \r\n\r\n\tcolor = 0xffffffff;\r\n\tpParams->GetInteger( \"bottom\", (int*)&color ); \r\n\r\n\tm_rain_bottom_color.r = (uint8)((color)&0xff);\r\n\tm_rain_bottom_color.g = (uint8)((color>>8)&0xff);\r\n\tm_rain_bottom_color.b = (uint8)((color>>16)&0xff);\r\n\tm_rain_bottom_color.a = (uint8)((color>>24)&0xff); \r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetSplashRate | Sets the rate that the splashes appear.\r\n// @parm rate | The number of splashes per frame. 1 is the maximum. Defaults to 0 (off).\r\nbool CWeather::ScriptWeatherSetSplashRate( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tm_splash_per_frame = 0.0f;\t\t// Default\r\n\tpParams->GetFloat( NONAME, &m_splash_per_frame );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetSplashLife | Sets the number of frames a splash will stay on screen.\r\n// @parm life | Number of frames the splash is on screen. Defaults to 8. Maximum is 32.\r\nbool CWeather::ScriptWeatherSetSplashLife( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tm_splash_life = 8;\t\t// Default\r\n\tpParams->GetInteger( NONAME, &m_splash_life );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetSplashSize | Sets the size of the splashes on-screen in inches.\r\n// @parm size | Sets the size of a splash on screen - defaults to 16 inches.\r\nbool CWeather::ScriptWeatherSetSplashSize( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tm_splash_size = 16.0f;\t\t// Default\r\n\tpParams->GetFloat( NONAME, &m_splash_size );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetSplashColor | Sets the color of the splash.\r\n// @parm color | The color of the splash. Defaults to 0x80808080.\r\nbool CWeather::ScriptWeatherSetSplashColor( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 color;\r\n\r\n\tcolor = 0x80808080;\r\n\tpParams->GetInteger( NONAME, (int*)&color ); \r\n\r\n\tm_splash_color.r = (uint8)((color)&0xff);\r\n\tm_splash_color.g = (uint8)((color>>8)&0xff);\r\n\tm_splash_color.b = (uint8)((color>>16)&0xff);\r\n\tm_splash_color.a = (uint8)((color>>24)&0xff); \r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetSplashBlendMode | Sets the blendmode of the splashes.\r\n// @parm blendmode | The name of the blend mode. Type are: blend/add/sub/modulate/brighten &\r\n// fixblend/fixadd/fixsub/fixmodulate/fixbrighten & diffuse (no blend at all). Defaults to fixadd.\r\n// @parmopt int | Fixed alpha value. Defaults to 64. Range is 0-255. Only required if using fix blend modes.\r\nbool CWeather::ScriptWeatherSetSplashBlendMode( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 blendmode_checksum = 0;\r\n\tif ( !pParams->GetChecksum( NONAME, &blendmode_checksum ) )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\tint fix = 32;\t\t// Default\r\n\tpParams->GetInteger( NONAME, &fix );\r\n\r\n\tplat_set_splash_blend_mode( blendmode_checksum, fix );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetSnowHeight | Sets the height of the snow above the ground.\r\n// @parm height | The height of the snow in inches - defaults to 500 inches.\r\nbool CWeather::ScriptWeatherSetSnowHeight( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tm_snow_height = 500.0f;\t\t// Default\r\n\tpParams->GetFloat( NONAME, &m_snow_height );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetSnowFrames | Sets the number of frames it takes a snow flake to fall.\r\n// @parm frames | Number of frames for the snow to fall from SnowHeight to the ground. Defaults to 254 frames.\r\nbool CWeather::ScriptWeatherSetSnowFrames( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tm_snow_frames = 254;\t\t// Default\r\n\tpParams->GetInteger( NONAME, &m_snow_frames );\r\n\r\n\tif ( m_snow_frames < 0 ) m_snow_frames = 0;\r\n\tif ( m_snow_frames > 254 ) m_snow_frames = 254;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetSnowSize | Sets the size of the snow flake image.\r\n// @parm size | Size of the snow flakes in inches. Defaults to 4 inches.\r\nbool CWeather::ScriptWeatherSetSnowSize( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tm_snow_size = 4.0f;\t\t// Default\r\n\tpParams->GetFloat( NONAME, &m_snow_size );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetSnowBlendMode | Sets the blendmode of the snow flakes.\r\n// @parm blendmode | The name of the blend mode. Type are: blend/add/sub/modulate/brighten &\r\n// fixblend/fixadd/fixsub/fixmodulate/fixbrighten & diffuse (no blend at all). Defaults to fixadd.\r\n// @parmopt int | Fixed alpha value. Defaults to 64. Range is 0-255. Only required if using fix blend modes.\r\nbool CWeather::ScriptWeatherSetSnowBlendMode( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 blendmode_checksum = 0;\r\n\tif ( !pParams->GetChecksum( NONAME, &blendmode_checksum ) )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\tint fix = 32;\t\t// Default\r\n\tpParams->GetInteger( NONAME, &fix );\r\n\r\n\tplat_set_snow_blend_mode( blendmode_checksum, fix );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetSnowRate | Sets the rate that the snow flakes fall in flakes per frame.\r\n// @parm rate | The number of new flakes of snow per frame. Defaults to 0 (off).\r\nbool CWeather::ScriptWeatherSetSnowRate( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tm_snow_flakes_per_frame = 0.0f;\t\t// Default\r\n\tpParams->GetFloat( NONAME, &m_snow_flakes_per_frame );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetSnowColor | Sets the color of the snow.\r\n// @parm col | The color of the snow. Defaults to 0x80808080\r\nbool CWeather::ScriptWeatherSetSnowColor( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 color;\r\n\r\n\tcolor = 0x80808080;\r\n\tpParams->GetInteger( NONAME, (int*)&color ); \r\n\r\n\tm_snow_color.r = (uint8)((color)&0xff);\r\n\tm_snow_color.g = (uint8)((color>>8)&0xff);\r\n\tm_snow_color.b = (uint8)((color>>16)&0xff);\r\n\tm_snow_color.a = (uint8)((color>>24)&0xff);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetSnowActive | Sets weather system to snow mode.\r\nbool CWeather::ScriptWeatherSetSnowActive( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tm_raining = false;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | WeatherSetRainActive | Sets weather system to rain mode.\r\nbool CWeather::ScriptWeatherSetRainActive( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tm_raining = true;\r\n\r\n\treturn true;\r\n}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gfx/nxweather.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n// NxParticle.h\r\n\r\n\r\n\r\n#ifndef\t__GFX_WEATHER_H__\r\n#define\t__GFX_WEATHER_H__\r\n\r\n#include <gel/Scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gfx/image/imagebasic.h>\r\n\r\nnamespace Nx\r\n{\r\n\r\nclass CWeather\r\n{\r\npublic:\r\n\t\t\t\t\t\t\tCWeather();\r\n\tvirtual\t\t\t\t\t~CWeather();\r\n\r\n\tvoid\t\t\t\t\tUpdateGrid( void );\r\n\r\n\tvoid\t\t\t\t\tProcess( float delta_time );\r\n\tvoid\t\t\t\t\tRender( void );\r\n\r\n\t// Script functions.\r\n\tbool\t\t\t\t\tScriptWeatherSetRainHeight( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetRainFrames( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetRainLength( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetRainBlendMode( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetRainRate( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetRainColor( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\n\tbool\t\t\t\t\tScriptWeatherSetSplashRate( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetSplashLife( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetSplashSize( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetSplashColor( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetSplashBlendMode( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\n\tbool\t\t\t\t\tScriptWeatherSetSnowHeight( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetSnowFrames( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetSnowSize( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetSnowBlendMode( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetSnowRate( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetSnowColor( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\n\tbool\t\t\t\t\tScriptWeatherSetSnowActive( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\tScriptWeatherSetRainActive( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\n\t// The virtual functions have a stub implementation.\r\nprivate:\r\n\tvirtual void\t\t\tplat_update_grid( void );\r\n\tvirtual void\t\t\tplat_process( float delta_time );\r\n\tvirtual void\t\t\tplat_render( void );\r\n\tvirtual void\t\t\tplat_set_rain_blend_mode( uint32 blendmode_checksum, int fix );\r\n\tvirtual void\t\t\tplat_set_splash_blend_mode( uint32 blendmode_checksum, int fix );\r\n\tvirtual void\t\t\tplat_set_snow_blend_mode( uint32 blendmode_checksum, int fix );\r\n\r\nprotected:\r\n\tfloat\t\t\t\t\tm_rain_height;\r\n\tint\t\t\t\t\t\tm_rain_frames;\r\n\tfloat\t\t\t\t\tm_rain_length;\r\n\tfloat\t\t\t\t\tm_rain_drops_per_frame;\r\n\tImage::RGBA\t\t\t\tm_rain_top_color;\r\n\tImage::RGBA\t\t\t\tm_rain_bottom_color;\r\n\r\n\tfloat\t\t\t\t\tm_splash_per_frame;\r\n\tint\t\t\t\t\t\tm_splash_life;\r\n\tfloat\t\t\t\t\tm_splash_size;\r\n\tImage::RGBA\t\t\t\tm_splash_color;\r\n\r\n\tint\t\t\t\t\t\tm_active_drops;\r\n\r\n\tbool\t\t\t\t\tm_system_active;\r\n\r\n\tfloat\t\t\t\t\tm_snow_height;\r\n\tint\t\t\t\t\t\tm_snow_frames;\r\n\tfloat\t\t\t\t\tm_snow_size;\r\n\tfloat\t\t\t\t\tm_snow_flakes_per_frame;\r\n\tImage::RGBA\t\t\t\tm_snow_color;\r\n\r\n\tbool\t\t\t\t\tm_raining;\r\n};\r\n\r\n}\r\n\r\n#endif // \r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Gfx/shadow.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tshadow.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tShadow interface code\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/shadow.h>\r\n\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/camera.h>\r\n#include <gfx/gfxutils.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/nxtextured3dpoly.h>\r\n\r\nnamespace Gfx\r\n{\r\n\r\nCShadow::CShadow()\r\n{\r\n\tm_type=vUNDEFINED_SHADOW;\r\n}\r\n\r\nCShadow::~CShadow()\r\n{\r\n}\r\n\r\nCDetailedShadow::CDetailedShadow(Nx::CModel *p_model, Mth::Vector camera_direction, float camera_distance)\r\n{\r\n\tm_type=vDETAILED_SHADOW;\r\n\tmp_texture = Nx::CEngine::sCreateRenderTargetTexture( 256, 256, 16, 16 );\t\t// maybe platform dependent?\r\n\t\r\n\t// Note, engine will figure out scene for itself\r\n\tNx::CEngine::sProjectTextureIntoScene( mp_texture, p_model );\t\t\r\n\r\n\tm_distance = camera_distance;\r\n\tm_direction = camera_direction;\r\n\tm_direction.Normalize();\r\n\tmp_camera = new Camera();\r\n\tmp_camera->SetPos(Mth::Vector(0,0,0));\r\n\t// construct an orientation matrix for the camera\r\n\t// so it is looking in the required direction\r\n\tMth::Matrix orient;\r\n\torient.Ident();\t\t \t\t// initialize (since it aint)\r\n\torient[Z] = m_direction;\r\n\torient[Z].Normalize();\r\n\t\r\n\t// X and Y are at right angles to Z  \r\n\torient[X][X] =  orient[Z][Z];\r\n\torient[X][Y] = -orient[Z][X];\r\n\torient[X][Z] = -orient[Z][Y];\r\n\t\r\n\torient[Y][X] =  orient[Z][Y];\r\n\torient[Y][Y] = -orient[Z][Z];\r\n\torient[Y][Z] = -orient[Z][X];\r\n\tmp_camera->SetMatrix(orient);\r\n\r\n\t// this loops through all the existing shadows,\r\n\t// and sets their shadow flags...  the model\r\n\t// also remembers its shadow state, for any\r\n\t// subsequent geoms that are added\r\n\tp_model->EnableShadow( true ); \r\n}\r\n\r\n\t\r\nCDetailedShadow::~CDetailedShadow()\r\n{\t\r\n\tNx::CEngine::sStopProjectionTexture( mp_texture );\r\n\t\r\n\tif ( mp_texture )\r\n\t{\r\n\t\tdelete mp_texture;\r\n\t}\r\n\r\n\tdelete mp_camera;\r\n}\r\n\r\n\r\n// set the position for the projection camera to point at\r\nvoid\t\tCDetailedShadow::UpdatePosition(Mth::Vector pos)\r\n{\r\n\tmp_camera->SetPos(pos - m_direction * m_distance);\r\n\tNx::CEngine::sSetProjectionTextureCamera( mp_texture, mp_camera );\r\n}\r\n\r\n\r\n\r\n// set the direction in which the projection camera points\r\nvoid CDetailedShadow::UpdateDirection( const Mth::Vector& dir )\r\n{\r\n\t// Store camera position.\r\n\tMth::Vector cam_pos = mp_camera->GetPos();\r\n\r\n\t// Set new direction and normalize.\t\r\n\tm_direction = dir;\r\n\tm_direction.Normalize();\r\n\t\r\n\t// Zero out camera position.\r\n\tmp_camera->SetPos( Mth::Vector( 0, 0, 0 ));\r\n\r\n\t// Construct an orientation matrix for the camera so it is looking in the required direction.\r\n\tMth::Matrix orient;\r\n\torient.Identity();\r\n\torient[Z] = m_direction;\r\n\t\r\n\t// X and Y are at right angles to Z.\r\n\torient[X][X] =  orient[Z][Z];\r\n\torient[X][Y] = -orient[Z][X];\r\n\torient[X][Z] = -orient[Z][Y];\r\n\torient[Y][X] =  orient[Z][Y];\r\n\torient[Y][Y] = -orient[Z][Z];\r\n\torient[Y][Z] = -orient[Z][X];\r\n\tmp_camera->SetMatrix( orient );\r\n\r\n\t// Restore camera position.\r\n\tmp_camera->SetPos( cam_pos );\r\n\r\n\t// Pass camera details on to engine.\r\n\tNx::CEngine::sSetProjectionTextureCamera( mp_texture, mp_camera );\r\n}\r\n\r\n\r\n\r\nCSimpleShadow::CSimpleShadow()\r\n{\r\n\tm_type=vSIMPLE_SHADOW;\r\n\tm_scale=1.0f;\r\n\tm_offset=1.0f;\t\r\n\tmp_model=NULL;\r\n\t/*\r\n\tmp_poly=Nx::CEngine::sCreateTextured3dPoly();\r\n\tDbg_MsgAssert(mp_poly,(\"Could not create textured 3d poly for shadow\"));\r\n\tmp_poly->SetTexture(\"pedshadow\");\r\n\t*/\r\n}\r\n\r\nCSimpleShadow::~CSimpleShadow()\r\n{\r\n\t/*\r\n\tDbg_MsgAssert(mp_poly,(\"NULL mp_poly ?\"));\r\n\tNx::CEngine::sDestroyTextured3dPoly(mp_poly);\r\n\t*/\r\n\t\r\n\tif (mp_model)\r\n\t{\r\n\t\tNx::CEngine::sUninitModel(mp_model);\r\n\t\tmp_model=NULL;\r\n\t}\t\r\n}\r\n\r\nvoid CSimpleShadow::SetModel(const char *p_model_name)\r\n{\r\n\tif (mp_model)\r\n\t{\r\n\t\tNx::CEngine::sUninitModel(mp_model);\r\n\t\tmp_model=NULL;\r\n\t}\t\r\n\r\n\tmp_model=Nx::CEngine::sInitModel();\r\n\t\r\n\tDbg_MsgAssert(p_model_name,(\"NULL p_model_name\"));\r\n\t\r\n\t// TODO: Change to use a geom file instead for PS2, more efficient than mdl ...\r\n\tmp_model->AddGeom(Gfx::GetModelFileName(p_model_name, \".mdl\").getString(), 0, true);\r\n}\r\n\r\nvoid CSimpleShadow::UpdatePosition(Mth::Vector& parentPos, Mth::Matrix& parentMatrix, Mth::Vector normal)\r\n{\r\n\t/*\r\n\tDbg_MsgAssert(mp_poly,(\"NULL mp_poly ?\"));\r\n\tfloat w=Script::GetFloat(\"shadowwidth\");\r\n\tmp_poly->SetPos(pos,w,w,normal);\r\n\t*/\r\n\t\t\r\n\tMth::Matrix display_matrix;\r\n\tdisplay_matrix[Y]=normal;\r\n\tdisplay_matrix[Z]=parentMatrix[Z];\r\n\tdisplay_matrix[X]=Mth::CrossProduct(display_matrix[Y],display_matrix[Z]);\r\n\t\r\n\tMth::Vector scale(m_scale,m_scale,m_scale,1.0f);\r\n\tdisplay_matrix.Scale(scale);\r\n\t\r\n\t// Change requested by LF/Andre:  use the passed normal\r\n\tdisplay_matrix.SetPos(parentPos+normal*m_offset);  //WAS: parentPos+parentMatrix[Y]*m_offset\r\n \t\r\n\t//Dbg_MsgAssert(mp_model,(\"NULL mp_model\"));\r\n\tif (mp_model)\r\n\t{\r\n\t\tmp_model->Render(&display_matrix,true,NULL);\r\n\t}\t\r\n}\r\n\r\nvoid CSimpleShadow::Hide()\r\n{\r\n\t//Dbg_MsgAssert(mp_model,(\"NULL mp_model\"));\r\n\tif (mp_model)\r\n\t{\r\n\t\tmp_model->SetActive(false);\r\n\t}\t\r\n}\r\n\r\nvoid CSimpleShadow::UnHide()\r\n{\r\n\t//Dbg_MsgAssert(mp_model,(\"NULL mp_model\"));\r\n\tif (mp_model)\r\n\t{\r\n\t\tmp_model->SetActive(true);\r\n\t}\t\r\n}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gfx/shadow.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2001 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tShadow  (GFX)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgfx/shadow.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t01/25/01\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_SHADOW_H\r\n#define __GFX_SHADOW_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/support.h>\r\n#include <core/math.h>\r\n\r\nnamespace Nx\r\n{\r\n\tclass CModel;\r\n\tclass CTexture;\r\n\tclass CTextured3dPoly;\r\n}\r\n\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t\t \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\nenum EShadowType\r\n{\r\n\tvUNDEFINED_SHADOW,\r\n\tvDETAILED_SHADOW,\r\n\tvSIMPLE_SHADOW\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nclass\tCShadow : public Spt::Class\r\n{\r\nprotected:\r\n\tEShadowType\tm_type;\r\n\t\r\npublic:\r\n\t\t\t\t\t\t\t\tCShadow();\r\n\tvirtual\t\t\t\t\t\t~CShadow();\r\n\tvirtual void\t\t\t\tUpdatePosition(Mth::Vector pos) {}\r\n\tvirtual void\t\t\t\tUpdatePosition(Mth::Vector& parentPos, Mth::Matrix& parentMatrix, Mth::Vector normal) {}\r\n\tvirtual void\t\t\t\tUpdateDirection( const Mth::Vector& dir ) {}\r\n\tvirtual void\t\t\t\tHide() {}\r\n\tvirtual void\t\t\t\tUnHide() {}\r\n\tEShadowType\t\t\t\t\tGetShadowType() {return m_type;}\r\n};\r\n\r\nclass\tCSimpleShadow : public CShadow\r\n{\r\n\t//Nx::CTextured3dPoly *mp_poly;\r\n\tNx::CModel\t*mp_model;\r\n\tfloat m_scale;\r\n\tfloat m_offset;\r\n\t\r\npublic:\r\n\t\t\t\t\t\t\t\tCSimpleShadow();\r\n\t\t\t\t\t\t\t\t~CSimpleShadow();\r\n\tvoid\t\t\t\t\t\tSetScale(float scale) {m_scale=scale;}\r\n\tvoid\t\t\t\t\t\tSetOffset(float offset) {m_offset=offset;}\r\n\tvoid\t\t\t\t\t\tSetModel(const char *p_model_name);\r\n\tvoid\t\t\t\t\t\tUpdatePosition(Mth::Vector& parentPos, Mth::Matrix& parentMatrix, Mth::Vector normal);\r\n\tvoid\t\t\t\t\t\tHide();\r\n\tvoid\t\t\t\t\t\tUnHide();\r\n};\r\n\r\n\r\nclass\tCamera;\t\t\t\t \r\nclass\tCDetailedShadow : public CShadow\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCDetailedShadow(Nx::CModel *p_model, Mth::Vector camera_direction = Mth::Vector(0.0f,-1.0f,0.0f), float camera_distance = 72.0f);\r\n\t\t\t\t\t\t\t\t~CDetailedShadow();\r\n\tvoid    \t\t\t\t\tUpdatePosition(Mth::Vector\tpos);\t\t// the position of the target\r\n\tvoid    \t\t\t\t\tUpdateDirection( const Mth::Vector& dir );\t\t// the direction in which the camera points\r\n\r\nprivate:\r\n\tCamera*\t\t\t\t\t\tmp_camera;\r\n\tNx::CTexture*\t\t\t\tmp_texture;\r\n\tMth::Vector\t\t\t\t\tm_direction;\r\n\tfloat\t\t\t\t\t\tm_distance;\r\n};\r\n\t   \r\n\r\n} // namespace Gfx\r\n\r\n#endif\t// __GFX_SHADOW_H\r\n"
  },
  {
    "path": "Code/Gfx/stdafx.h",
    "content": "// You cannot conditionally compile-out stdafx.h in the PC project\r\n// so the only recourse is to always include \"stdafx.h\" in both\r\n// projects and to include this dummy version on the PS2 project\r\n"
  },
  {
    "path": "Code/Gfx/subanimcontroller.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       SubAnimController.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/06/2003\r\n//****************************************************************************\r\n\r\n#include <gfx/subanimcontroller.h>\r\n\r\n#include <core/math.h>\r\n\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/object/compositeobject.h>\r\n\t\t\t\t\t\t\t\t\t\t   \r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n\t\t\t\t\t\t \r\n#include <gfx/blendchannel.h>\r\n#include <gfx/gfxutils.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxanimcache.h>\r\n#include <gfx/nxquickanim.h>\r\n#include <gfx/pose.h>\r\n#include <gfx/skeleton.h>\r\n\r\n#include <sk/components/skaterflipandrotatecomponent.h>\r\n\t\t\t\t\t\t  \r\nnamespace Gfx\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBonedAnimController::CBonedAnimController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel )\r\n{\r\n\tmp_quickAnim = Nx::CEngine::sInitQuickAnim();\r\n\tmp_quickAnim->Enable( false );\r\n\t\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tm_animScriptName = pAnimationComponent->GetAnimScriptName();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBonedAnimController::~CBonedAnimController()\r\n{\r\n\tif ( mp_quickAnim )\r\n\t{\r\n\t\tNx::CEngine::sUninitQuickAnim( mp_quickAnim );\r\n\t\tmp_quickAnim = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBonedAnimController::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tCBaseAnimController::InitFromStructure( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBonedAnimController::GetPose( Gfx::CPose* pResultPose )\r\n{\r\n\tDbg_MsgAssert( pResultPose, ( \"No return data\" ) );\r\n\r\n//\tint skipList[vMAX_BONES];\r\n//\tGetSkeleton()->GetSkipList( &skipList[0] );\r\n\tuint32*\tp_skip_list = GetSkeleton()->GetBoneSkipList();\r\n\tuint32\tskip_index\t= GetSkeleton()->GetBoneSkipIndex();\r\n\r\n\tDbg_Assert( mp_quickAnim );\r\n//\tmp_quickAnim->GetInterpolatedFrames( pResultPose->m_rotations, pResultPose->m_translations, &skipList[0], mp_blendChannel->GetCurrentAnimTime() );\r\n\tmp_quickAnim->GetInterpolatedFrames( pResultPose->m_rotations, pResultPose->m_translations, p_skip_list, skip_index, mp_blendChannel->GetCurrentAnimTime() );\r\n\tmp_quickAnim->Enable( true );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBonedAnimController::Update()\r\n{\r\n\tDbg_MsgAssert( mp_blendChannel->m_loopingType != Gfx::LOOPING_WOBBLE, ( \"Not supposed to be wobble type\" ) );\r\n\t\t\t\r\n\tfloat oldTime = mp_blendChannel->m_currentTime;\r\n\r\n\tmp_blendChannel->m_currentTime = mp_blendChannel->get_new_anim_time();\r\n\r\n\tmp_blendChannel->ProcessCustomKeys( oldTime, mp_blendChannel->m_currentTime );\r\n\r\n\tif ( mp_blendChannel->m_currentTime < oldTime )\r\n\t{\r\n\t\tmp_quickAnim->Enable( false );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nEAnimFunctionResult CBonedAnimController::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tcase 0x5f495ae0:\t// invalidateCache\r\n\t\t{\r\n\t\t\tmp_quickAnim->Enable( false );\r\n\t\t\t\r\n\t\t\t// want the other controllers to be invalidated too\r\n\t\t\treturn AF_NOT_EXECUTED;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0xaf2fae19:\t// playsequence\r\n\t\t{\r\n\t\t\tuint32 anim_name;\r\n\t\t\tfloat start_time;\r\n\t\t\tfloat end_time;\r\n\t\t\tint loop_type;\r\n\t\t\tfloat blend_period;\r\n\t\t\tfloat speed;\r\n\r\n\t\t\tpParams->GetChecksum( CRCD(0x6c2bfb7f,\"animname\"), &anim_name, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0xd16b61e6,\"starttime\"), &start_time, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0xab81bb3d,\"endtime\"), &end_time, Script::ASSERT );\r\n\t\t\tpParams->GetInteger( CRCD(0xcd8d7c1b,\"looptype\"), &loop_type, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0x8f0d24ed,\"blendperiod\"), &blend_period, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0xf0d90109,\"speed\"), &speed, Script::ASSERT );\r\n\t\t\t\r\n\t\t\tmp_blendChannel->CAnimChannel::PlaySequence( anim_name, start_time, end_time, (Gfx::EAnimLoopingType)loop_type, blend_period, speed);\r\n\t\t\r\n\t\t\tDbg_Assert( mp_quickAnim );\r\n\t\t\tmp_quickAnim->SetAnimAssetName( m_animScriptName + anim_name );\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn AF_NOT_EXECUTED;\r\n\t}\r\n\r\n\treturn AF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCWobbleController::CWobbleController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel )\r\n{\r\n\tm_wobbleTargetTime\t\t\t = 0.0f;\r\n\r\n\tm_wobbleDetails.wobbleAmpA    = 0.0f;\r\n\tm_wobbleDetails.wobbleAmpB    = 0.0f;\r\n\tm_wobbleDetails.wobbleK1      = 0.0f;\r\n\tm_wobbleDetails.wobbleK2      = 0.0f;\r\n\tm_wobbleDetails.spazFactor    = 0.0f;\t\r\n\t\r\n\tmp_quickAnim = Nx::CEngine::sInitQuickAnim();\r\n\tmp_quickAnim->Enable( false );\r\n\t\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tm_animScriptName = pAnimationComponent->GetAnimScriptName();\r\n\t\r\n\t/*\r\n\tfloat startTime;\r\n\tfloat endTime;\r\n\r\n\tif ( pParams->GetFloat( \"startTime\", &startTime, Script::NO_ASSERT );\r\n\t\t&& pParams->GetFloat( \"endTime\", &endTime, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tm_wobbleTargetTime = ( startTime + endTime ) / 2;\r\n\t}\r\n\t*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCWobbleController::~CWobbleController()\r\n{\r\n\tif ( mp_quickAnim )\r\n\t{\r\n\t\tNx::CEngine::sUninitQuickAnim( mp_quickAnim );\r\n\t\tmp_quickAnim = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWobbleController::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tCBaseAnimController::InitFromStructure( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CWobbleController::GetPose( Gfx::CPose* pResultPose )\r\n{\r\n\tDbg_MsgAssert( pResultPose, ( \"No return data\" ) );\r\n\r\n//\tint skipList[vMAX_BONES];\r\n//\tGetSkeleton()->GetSkipList( &skipList[0] );\r\n\tuint32*\tp_skip_list = GetSkeleton()->GetBoneSkipList();\r\n\tuint32\tskip_index\t= GetSkeleton()->GetBoneSkipIndex();\r\n\t\r\n\tDbg_Assert( mp_quickAnim );\r\n//\tmp_quickAnim->GetInterpolatedFrames( pResultPose->m_rotations, pResultPose->m_translations, &skipList[0], mp_blendChannel->GetCurrentAnimTime() );\r\n\tmp_quickAnim->GetInterpolatedFrames( pResultPose->m_rotations, pResultPose->m_translations, p_skip_list, skip_index, mp_blendChannel->GetCurrentAnimTime() );\r\n\tmp_quickAnim->Enable( true );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CWobbleController::get_new_wobble_time()\r\n{\r\n\tfloat AmpA = m_wobbleDetails.wobbleAmpA;\r\n\tfloat AmpB = m_wobbleDetails.wobbleAmpB;\r\n\tfloat k1 = m_wobbleDetails.wobbleK1;\r\n\tfloat k2 = m_wobbleDetails.wobbleK2;\r\n\tfloat SpazFactor = m_wobbleDetails.spazFactor;\r\n\r\n\tfloat new_time = m_wobbleTargetTime;\r\n\r\n\tDbg_MsgAssert( mp_blendChannel->m_startTime < mp_blendChannel->m_endTime, (\"start time must be smaller than end time for LOOPING_WOBBLE\"));\r\n\tfloat l = ( mp_blendChannel->m_endTime - mp_blendChannel->m_startTime ) / 2;\r\n\tfloat mid = ( mp_blendChannel->m_endTime + mp_blendChannel->m_startTime ) / 2;\r\n\tfloat d = Mth::Abs( new_time - mid );\r\n\tSpazFactor = 1 + ( SpazFactor - 1 ) * d / l;\r\n\tAmpA *= SpazFactor;\r\n\tAmpB *= SpazFactor;\r\n\r\n\tif ( new_time - AmpA - AmpB < mp_blendChannel->m_startTime )\r\n\t{\r\n\t\tnew_time = mp_blendChannel->m_startTime + AmpA + AmpB;\r\n\t}\t\r\n\tif ( new_time + AmpA + AmpB > mp_blendChannel->m_endTime )\r\n\t{\r\n\t\tnew_time = mp_blendChannel->m_endTime - AmpA - AmpB;\r\n\t}\t\r\n\r\n\tfloat t = (int)Tmr::ElapsedTime( 0 ) * k1;\r\n\tt -= 16.0f * ( ((int)t) / 16.0f );\r\n\tfloat amp = AmpA + AmpB * sinf( t * 2.0f * Mth::PI );\r\n\r\n\tt = (int)Tmr::ElapsedTime( 0 ) * k2;\r\n\tt -= 16.0f * ( ((int)t) / 16.0f );\r\n\r\n\tnew_time += amp * sinf( t * 2.0f * Mth::PI );\r\n\r\n\t// These should never be true, but just in case.\r\n\tif (new_time < mp_blendChannel->m_startTime)\r\n\t{\r\n\t\tnew_time = mp_blendChannel->m_startTime;\r\n\t}\r\n\tif (new_time > mp_blendChannel->m_endTime)\r\n\t{\r\n\t\tnew_time = mp_blendChannel->m_endTime;\r\n\t}\r\n\r\n\treturn new_time;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWobbleController::Update()\r\n{\r\n\t// the looping check below is only needed until\r\n\t// we stop automatically adding the wobble\r\n\t// controller to all channels\r\n\tDbg_MsgAssert ( mp_blendChannel->m_loopingType == Gfx::LOOPING_WOBBLE, ( \"Was supposed to be wobble type %d\", mp_blendChannel->m_loopingType ) );\r\n\r\n\t// remember old time, so that we know whether to use the quick anim\r\n\tfloat oldTime = mp_blendChannel->m_currentTime;\r\n\r\n\tmp_blendChannel->m_currentTime = get_new_wobble_time();\r\n\r\n\t// remember to use the quick anim\r\n\tif ( mp_blendChannel->m_currentTime < oldTime )\r\n\t{\r\n\t\tmp_quickAnim->Enable( false );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CWobbleController::GetDebugInfo( Script::CStruct* p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tp_info->AddFloat( CRCD(0x359ac119,\"m_wobbleTargetTime\"), m_wobbleTargetTime );\r\n\r\n\tp_info->AddFloat( CRCD(0xfd266a26,\"wobbleAmpA\"), m_wobbleDetails.wobbleAmpA );\r\n\tp_info->AddFloat( CRCD(0x642f3b9c,\"wobbleAmpB\"), m_wobbleDetails.wobbleAmpB );\r\n\tp_info->AddFloat( CRCD(0x0f43fd49,\"wobbleK1\"), m_wobbleDetails.wobbleK1 );\r\n\tp_info->AddFloat( CRCD(0x964aacf3,\"wobbleK2\"), m_wobbleDetails.wobbleK2 );\r\n\tp_info->AddFloat( CRCD(0xf90b0824,\"spazFactor\"), m_wobbleDetails.spazFactor );\r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nEAnimFunctionResult CWobbleController::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tcase 0x5f495ae0:\t// invalidateCache\r\n\t\t{\r\n\t\t\tmp_quickAnim->Enable( false );\r\n\t\t\t\r\n\t\t\t// want the other controllers to be invalidated too\r\n\t\t\treturn AF_NOT_EXECUTED;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0xaf2fae19:\t// playsequence\r\n\t\t{\r\n\t\t\tuint32 anim_name;\r\n\t\t\tfloat start_time;\r\n\t\t\tfloat end_time;\r\n\t\t\tint loop_type;\r\n\t\t\tfloat blend_period;\r\n\t\t\tfloat speed;\r\n\r\n\t\t\tpParams->GetChecksum( CRCD(0x6c2bfb7f,\"animname\"), &anim_name, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0xd16b61e6,\"starttime\"), &start_time, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0xab81bb3d,\"endtime\"), &end_time, Script::ASSERT );\r\n\t\t\tpParams->GetInteger( CRCD(0xcd8d7c1b,\"looptype\"), &loop_type, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0x8f0d24ed,\"blendperiod\"), &blend_period, Script::ASSERT );\r\n\t\t\tpParams->GetFloat( CRCD(0xf0d90109,\"speed\"), &speed, Script::ASSERT );\r\n\t\t\t\r\n\t\t\tmp_blendChannel->CAnimChannel::PlaySequence( anim_name, start_time, end_time, (Gfx::EAnimLoopingType)loop_type, blend_period, speed);\r\n\t\t\r\n\t\t\tDbg_Assert( mp_quickAnim );\r\n\t\t\tmp_quickAnim->SetAnimAssetName( m_animScriptName + anim_name );\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\t\r\n\t\tcase 0xd0209498:\t// setwobbletarget\r\n\t\t{\r\n\t\t\tfloat wobbleTargetAlpha;\r\n\r\n\t\t\tif ( pParams->GetFloat( CRCD(0x4d747fa0,\"wobbletargetalpha\"), &wobbleTargetAlpha, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\t// check bounds\r\n\t\t\t\tif ( wobbleTargetAlpha < 0.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\twobbleTargetAlpha = 0.0f;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( wobbleTargetAlpha > 1.0f )\r\n\t\t\t\t{\r\n\t\t\t\t\twobbleTargetAlpha = 1.0f;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tm_wobbleTargetTime = mp_blendChannel->m_startTime + ( mp_blendChannel->m_endTime - mp_blendChannel->m_startTime ) * wobbleTargetAlpha;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\t\r\n\t\tcase 0xea6d0efd:\t// setwobbledetails\r\n\t\t{\r\n\t\t\tfloat wobbleAmpA;\r\n\t\t\tfloat wobbleAmpB;\r\n\t\t\tfloat wobbleK1;\r\n\t\t\tfloat wobbleK2;\r\n\t\t\tfloat spazFactor;\r\n\r\n\t\t\tif ( pParams->GetFloat( CRCD(0xfd266a26,\"wobbleAmpA\"), &wobbleAmpA, Script::NO_ASSERT )\r\n\t\t\t\t && pParams->GetFloat( CRCD(0x642f3b9c,\"wobbleAmpB\"), &wobbleAmpB, Script::NO_ASSERT )\r\n\t\t\t\t && pParams->GetFloat( CRCD(0x0f43fd49,\"wobbleK1\"), &wobbleK1, Script::NO_ASSERT )\r\n\t\t\t\t && pParams->GetFloat( CRCD(0x964aacf3,\"wobbleK2\"), &wobbleK2, Script::NO_ASSERT )\r\n\t\t\t\t && pParams->GetFloat( CRCD(0xf90b0824,\"spazFactor\"), &spazFactor, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tm_wobbleDetails.wobbleAmpA = wobbleAmpA;\r\n\t\t\t\tm_wobbleDetails.wobbleAmpB = wobbleAmpB;\r\n\t\t\t\tm_wobbleDetails.wobbleK1 = wobbleK1;\r\n\t\t\t\tm_wobbleDetails.wobbleK2 = wobbleK2;\r\n\t\t\t\tm_wobbleDetails.spazFactor = spazFactor;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\treturn AF_NOT_EXECUTED;\r\n\t}\r\n\r\n\treturn AF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCFlipRotateController::CFlipRotateController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel )\r\n{\r\n\tm_flipped = false;\r\n\tm_rotated = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCFlipRotateController::~CFlipRotateController()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFlipRotateController::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tCBaseAnimController::InitFromStructure( pParams );\r\n\r\n\tint flipped;\r\n\tif ( pParams->GetInteger( CRCD(0x0c7a712c,\"flipped\"), &flipped, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tm_flipped = flipped;\r\n\t}\r\n\r\n\tint rotated;\r\n\tif ( pParams->GetInteger( CRCD(0x6ea3704a,\"rotated\"), &rotated, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tm_rotated = rotated;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CFlipRotateController::Update()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CFlipRotateController::GetPose( Gfx::CPose* pResultPose )\r\n{\r\n\t// rather than using the m_flipped and m_rotated flags,\r\n\t// we should use the one stored in the CAnimationComponent\r\n\t// temporarily...  this is because right now we don't want \r\n\t// to blend across the flip (but eventually we will want to)\r\n\r\n\tCSkeleton* pSkeleton = GetSkeleton();\r\n\tDbg_MsgAssert( pSkeleton, ( \"No skeleton?\" ) );\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t{\t// remove this scope if you actually want to use pAnimationComponent\r\n\t\t// in something other than the assertion\r\n\t\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\t\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t}\r\n\t#endif\r\n\t\r\n\tObj::CSkaterFlipAndRotateComponent* pSkaterFlipAndRotateComponent = GetSkaterFlipAndRotateComponentFromObject( GetObject() );\r\n\r\n\tif ( pSkaterFlipAndRotateComponent && pSkaterFlipAndRotateComponent->IsBoardRotated() )\r\n//\tif ( m_rotated )\r\n\t{\r\n\t\tint idx;\r\n\t\t\r\n\t\t// name of skateboard bone in new skeleton\r\n\t\tidx = pSkeleton->GetBoneIndexById( CRCD(0x98971faf, \"bone_board_root\") );\r\n\t\tif ( idx != -1 )\r\n\t\t{\t   \r\n\t\t\tMth::Quat* pQuat = (pResultPose->m_rotations + idx);\r\n\t\t\t*pQuat = Mth::Quat(0.0f,0.0f,1.0f,0.0f) * *pQuat;\r\n\t\t\tpQuat->Normalize();\r\n\t\t}\t\t\r\n\t}\r\n\r\n\t// GJ:  this remembers the flip state when the animation was\r\n\t// first launched, so that we can blend across the flip...  \r\n\t// it produces some weird effects currently in the THPS5, \r\n\t// (such as the pelvis rotating 180 degrees), but this may \r\n\t// be due to the way the scripts were originally written...\r\n\t// i'll take a look at it later, but hopefully this will \r\n\t// give Left Field some of the functionality they've been\r\n\t// looking for...\r\n\tif ( m_flipped )\r\n//\tif ( pAnimationComponent->IsFlipped() )\r\n\t{\r\n\t\tint i;\r\n\t\tGfx::CPose oldPose;\r\n\t\tint numBones = pSkeleton->GetNumBones();\r\n\r\n//\t\toldPose = *pResultPose;\r\n\t\tfor ( i = 0; i < numBones; i++ )\r\n\t\t{\r\n\t\t\toldPose.m_rotations[i] = pResultPose->m_rotations[i];\r\n\t\t}\t\r\n\t\tfor ( i = 0; i < numBones; i++ )\r\n\t\t{\r\n\t\t\toldPose.m_translations[i] = pResultPose->m_translations[i];\r\n\t\t}\t\r\n\r\n\t\tMth::Quat* pQuat = (pResultPose->m_rotations);\r\n\t\tMth::Vector* pTrans = (pResultPose->m_translations);\r\n\r\n\t\tfor ( i = 0; i < numBones; i++ )\r\n\t\t{\r\n\t\t\tint flipIndex = pSkeleton->GetFlipIndex(i);\t\r\n\t\t\tif ( flipIndex != -1 )\r\n\t\t\t{\r\n\t\t\t\t*pQuat = *(oldPose.m_rotations+flipIndex);\r\n\t\t\t\t*pTrans = *(oldPose.m_translations+flipIndex);\t\t\t\t\r\n\t   \t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t*pQuat = *(oldPose.m_rotations+i);\r\n\t\t\t\t*pTrans = *(oldPose.m_translations+i);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// flip all rotations and translations on Y.\r\n\t\t\t(*pQuat)[X] = -(*pQuat)[X];\r\n\t\t\t(*pQuat)[W] = -(*pQuat)[W];\r\n\t\t\t(*pTrans)[X] = -(*pTrans)[X];\r\n\r\n\t\t\tpQuat++;\r\n\t\t\tpTrans++;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCIKController::CIKController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCIKController::~CIKController()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CIKController::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tCBaseAnimController::InitFromStructure( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CIKController::Update()\r\n{\r\n\t// here we'd do things like grab the position of the bike pedals\r\n\t// from the CBikeComponent, and override the leg bones, or whatever\r\n\r\n\t// if data needs be shared among different\r\n\t// blend channels, then we might want to consider\r\n\t// storing it in a CIKComponent...  then, the\r\n\t// Update() function can grab it like so:\r\n\t// Obj::CIKComponent* pIKComponent = GetIKComponentFromObject( GetObject() );\r\n\t// if ( pIKComponent )\r\n\t// {\r\n\t//\t\tMth::Vector steering_column_pos = pIKComponent->GetBonePosition( \"steering_column\" );\r\n\t//\t\tMth::Vector left_handle_bar_pos\t= pIKComponent->GetBonePosition( \"left_handle_bar\" );\r\n\t// }\r\n\r\n\t// if each blend channel needs its own set of IK data\r\n\t// then we can just do it like so:\r\n\t// Mth::Vector steering_column_pos = m_steering_column_pos;\r\n\t// Mth::Vector left_handle_bar_pos = m_left_handle_bar_pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CIKController::GetDebugInfo( Script::CStruct* p_info )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nEAnimFunctionResult CIKController::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn AF_NOT_EXECUTED;\r\n\t}\r\n\r\n\treturn AF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CIKController::GetPose( Gfx::CPose* pResultPose )\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCProceduralAnimController::CProceduralAnimController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCProceduralAnimController::~CProceduralAnimController()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CProceduralAnimController::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tCBaseAnimController::InitFromStructure( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CProceduralAnimController::Update()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CProceduralAnimController::GetPose( Gfx::CPose* pResultPose )\r\n{\r\n\t// To be consistent with THPS4, we should actually do this \r\n\t// AFTER building the object-space transform of each bone\r\n\t// (but i'll wait until someone actually asks for this feature)\r\n\t\r\n\t// I didn't fully re-implement this functionality from THPS4,\r\n\t// since we're going to do our procedural cloth animations\r\n\t// in a different way for THPS5.  I've left this partial\r\n\t// implementation in as an example for other developers\r\n\t// to write their own controllers.\r\n\r\n\t// THPS4 had ping-ponging animations (so that we can animate\r\n\t// the shirt rising and falling)...  we can re-implement\r\n\t// this later if we end up deciding to use this controller...\r\n\r\n\tCSkeleton* pSkeleton = GetSkeleton();\r\n\tDbg_MsgAssert( pSkeleton, ( \"No skeleton?\" ) );\r\n\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tint numProceduralBones = pAnimationComponent->GetNumProceduralBones(); \r\n\tCProceduralBone* p_current_procedural_bone = pAnimationComponent->GetProceduralBones();\r\n\r\n\tfor ( int i = 0; i < numProceduralBones; i++ )\r\n\t{\r\n\t\tint idx = pSkeleton->GetBoneIndexById( p_current_procedural_bone->m_name );\r\n\t\tif ( idx != -1 )\r\n\t\t{\r\n\t\t\tMth::Quat* pQuat = pResultPose->m_rotations + idx;\r\n\r\n\t\t\tif ( p_current_procedural_bone->rotEnabled )\r\n\t\t\t{\r\n\t\t\t\tMth::Vector theRotVector = p_current_procedural_bone->currentRot;\r\n\t\t\t\ttheRotVector.Scale( Mth::PI * 2.0f / 4096.0f );\r\n\t\t\t\tMth::Quat theRotQuat = Mth::EulerToQuat( theRotVector );\r\n\t\t\t\t\r\n\t\t\t\t// TODO:  should I be post-rotating this?\r\n\t\t\t\t*pQuat = theRotQuat * *pQuat;\r\n\t\t\t\t\r\n\t\t\t\tpQuat->Normalize();\r\n\t\t\t}\r\n\t\t}\r\n\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\tp_current_procedural_bone++;\r\n    }\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneTransMin( uint32 boneName, const Mth::Vector& vec )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->trans0 = vec;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneTransMax( uint32 boneName, const Mth::Vector& vec )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->trans1 = vec;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneTransSpeed( uint32 boneName, const Mth::Vector& vec )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->deltaTrans = vec;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneTransActive( uint32 boneName, bool enabled )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->transEnabled = enabled;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneTransCurrent( uint32 boneName, const Mth::Vector& vec )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->currentTrans = vec;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneRotMin( uint32 boneName, const Mth::Vector& vec )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->rot0[X] = vec[X] * 2.0f * Mth::PI / 4096.0f;\r\n\t\tpProceduralBone->rot0[Y] = vec[Y] * 2.0f * Mth::PI / 4096.0f;\r\n\t\tpProceduralBone->rot0[Z] = vec[Z] * 2.0f * Mth::PI / 4096.0f;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneRotMax( uint32 boneName, const Mth::Vector& vec )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->rot1[X] = vec[X] * 2.0f * Mth::PI / 4096.0f;\r\n\t\tpProceduralBone->rot1[Y] = vec[Y] * 2.0f * Mth::PI / 4096.0f;\r\n\t\tpProceduralBone->rot1[Z] = vec[Z] * 2.0f * Mth::PI / 4096.0f;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneRotSpeed( uint32 boneName, const Mth::Vector& vec )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->deltaRot = vec;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneRotCurrent( uint32 boneName, const Mth::Vector& vec )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->currentRot = vec;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneRotActive( uint32 boneName, bool enabled )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->rotEnabled = enabled;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneScaleMin( uint32 boneName, const Mth::Vector& vec )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->scale0 = vec;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneScaleMax( uint32 boneName, const Mth::Vector& vec )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->scale1 = vec;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneScaleSpeed( uint32 boneName, const Mth::Vector& vec )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->deltaScale = vec;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneScaleCurrent( uint32 boneName, const Mth::Vector& vec )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->currentScale = vec;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CProceduralAnimController::SetProceduralBoneScaleActive( uint32 boneName, bool enabled )\r\n{\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tDbg_MsgAssert( pAnimationComponent, ( \"No animation component?\" ) );\r\n\t\r\n\tCProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName );\r\n\r\n\tif ( pProceduralBone )\r\n\t{\r\n\t\tpProceduralBone->scaleEnabled = enabled;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// TODO:  It's kind of backwards for the CAnimationComponent to be calling\r\n// member functions in the CProceduralAnimController that set values\r\n// back inside the CAnimationComponent...  This is because I haven't\r\n// really decided whether each blend channel should have its own\r\n// proc anim data, or whether the blend channels should share a single\r\n// set of proc anim data.  Right now, the blend channels all share\r\n// a single set of proc anim data (stored in the CAnimationComponent).\r\n\r\nEAnimFunctionResult CProceduralAnimController::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t    // @script | SetBoneTransMin | Sets the minimum translation extent for procedurally animated bone (in world units)\r\n        // @parmopt float | x | 0 | minimum extent x\r\n        // @parmopt float | y | 0 | minimum extent y\r\n        // @parmopt float | z | 0 | minimum extent z\r\n        // @parm name | bone | name of procedural bone\r\n\t\tcase 0x02565bd1: //\tSetBoneTransMin\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec(0.0f,0.0f,0.0f);\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tpParams->GetFloat( CRCD(0x7323e97c,\"x\"), &vec[X], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x0424d9ea,\"y\"), &vec[Y], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &vec[Z], false );\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\t\t\t\t\r\n\t\t\t\tthis->SetProceduralBoneTransMin( boneName, vec );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | SetBoneTransMax | Sets the maximum translation extent for procedurally animated bone (in world units)\r\n\t\t// @parmopt float | x | 0 | maximum extent x\r\n\t\t// @parmopt float | y | 0 | maximum extent y\r\n\t\t// @parmopt float | z | 0 | maximum extent z\r\n\t\t// @parm name | bone | name of procedural bone\r\n\t\tcase 0x3e5b6488: //\tSetBoneTransMax\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec(0.0f,0.0f,0.0f);\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tpParams->GetFloat( CRCD(0x7323e97c,\"x\"), &vec[X], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x0424d9ea,\"y\"), &vec[Y], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &vec[Z], false );\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\t\t\t\t\r\n\t\t\t\tthis->SetProceduralBoneTransMax( boneName, vec );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | SetBoneTransSpeed | Sets the speed at which the bone's translation will procedurally animate (in 4096 notation)\r\n\t\t// @parmopt int | x | 0 | speed x (2048 immediately goes from T0 to T1)\r\n\t\t// @parmopt int | y | 0 | speed y (2048 immediately goes from T0 to T1)\r\n\t\t// @parmopt int | z | 0 | speed z (2048 immediately goes from T0 to T1)\r\n\t\t// @parm name | bone | name of procedural bone\r\n\t\tcase 0xc85b9ac0: //\tSetBoneTransSpeed\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec(0.0f,0.0f,0.0f);\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tpParams->GetFloat( CRCD(0x7323e97c,\"x\"), &vec[X], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x0424d9ea,\"y\"), &vec[Y], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &vec[Z], false );\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\t\t\t\t\r\n\t\t\t\tDbg_Assert( mp_blendChannel );\r\n\t\t\t\tthis->SetProceduralBoneTransSpeed( boneName, vec );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | SetBoneTransCurrent | Immediately sets the procedurally animated bone to a specific translation (in 4096 notation)\r\n\t\t// @parmopt int | x | 0 | current x (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0)\r\n\t\t// @parmopt int | y | 0 | current y (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0)\r\n\t\t// @parmopt int | z | 0 | current z (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0)\r\n\t\t// @parm name | bone | name of procedural bone\r\n\t\tcase 0x5ee9d5bd: //\tSetBoneTransCurrent\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec(0.0f,0.0f,0.0f);\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tpParams->GetFloat( CRCD(0x7323e97c,\"x\"), &vec[X], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x0424d9ea,\"y\"), &vec[Y], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &vec[Z], false );\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\t\t\t\t\r\n\t\t\t\tthis->SetProceduralBoneTransCurrent( boneName, vec );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | SetBoneTransActive | Sets whether the bone should procedurally animate its translation\r\n\t\t// @uparm int | active (either 0 or 1)\r\n\t\t// @parm name | bone | name of procedural bone\r\n\t\tcase 0x5661fb72: //\tSetBoneTransActive\r\n\t\t\t{\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tint enabled;\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\t\t\t\tpParams->GetInteger( NONAME, &enabled, true );\r\n\t\t\t\t\r\n                Dbg_Assert( mp_blendChannel );\r\n                this->SetProceduralBoneTransActive( boneName, enabled );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | SetBoneRotMin | Sets the minimum rotation extent for procedurally animated bone (in 4096 notation)\r\n\t\t// @parmopt int | x | 0 | minimum extent x (in 4096 notation)\r\n\t\t// @parmopt int | y | 0 | minimum extent y (in 4096 notation)\r\n\t\t// @parmopt int | z | 0 | minimum extent z (in 4096 notation)\r\n\t\t// @parm name | bone | name of procedural bone\r\n\t\tcase 0xa47767f2: //\tSetBoneRotMin\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec(0.0f,0.0f,0.0f);\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tpParams->GetFloat( CRCD(0x7323e97c,\"x\"), &vec[X], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x0424d9ea,\"y\"), &vec[Y], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &vec[Z], false );\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\t\t\t\t\r\n\t\t\t\tthis->SetProceduralBoneRotMin( boneName, vec );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | SetBoneRotMax | Sets the maximum rotation extent for procedurally animated bone (in 4096 notation)\r\n\t\t// @parmopt int | x | 0 | maximum extent x (in 4096 notation)\r\n\t\t// @parmopt int | y | 0 | maximum extent y (in 4096 notation)\r\n\t\t// @parmopt int | z | 0 | maximum extent z (in 4096 notation)\r\n\t\tcase 0x987a58ab: //\tSetBoneRotMax\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec(0.0f,0.0f,0.0f);\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tpParams->GetFloat( CRCD(0x7323e97c,\"x\"), &vec[X], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x0424d9ea,\"y\"), &vec[Y], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &vec[Z], false );\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\t\t\t\t\r\n\t\t\t\tthis->SetProceduralBoneRotMax( boneName, vec );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | SetBoneRotSpeed | Sets the speed at which the bone's rotation will procedurally animate (in 4096 notation)\r\n\t\t// @parmopt int | x | 0 | speed x (2048 immediately goes from T0 to T1)\r\n\t\t// @parmopt int | y | 0 | speed y (2048 immediately goes from T0 to T1)\r\n\t\t// @parmopt int | z | 0 | speed z (2048 immediately goes from T0 to T1)\r\n\t\t// @parm name | bone | name of procedural bone\r\n\t\tcase 0x599d3707: //\tSetBoneRotSpeed\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec(0.0f,0.0f,0.0f);\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tpParams->GetFloat( CRCD(0x7323e97c,\"x\"), &vec[X], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x0424d9ea,\"y\"), &vec[Y], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &vec[Z], false );\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\r\n\t\t\t\tthis->SetProceduralBoneRotSpeed( boneName, vec );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | SetBoneRotCurrent | Immediately sets the procedurally animated bone to a specific rotation (in 4096 notation)\r\n\t\t// @parmopt int | x | 0 | current x (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0)\r\n\t\t// @parmopt int | y | 0 | current y (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0)\r\n\t\t// @parmopt int | z | 0 | current z (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0)\r\n\t\t// @parm name | bone | name of procedural bone\r\n\t\tcase 0x7235daa7: //\tSetBoneRotCurrent\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec(0.0f,0.0f,0.0f);\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tpParams->GetFloat( CRCD(0x7323e97c,\"x\"), &vec[X], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x0424d9ea,\"y\"), &vec[Y], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &vec[Z], false );\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\t\t\t\t\r\n\t\t\t\tthis->SetProceduralBoneRotCurrent( boneName, vec );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | SetBoneRotActive | Sets whether the bone should procedurally animate its rotation\r\n\t\t// @uparm int | active (either 0 or 1)\r\n\t\t// @parm name | bone | name of procedural bone\r\n\t\tcase 0x53f06acc: //\tSetBoneRotActive\r\n\t\t\t{\t\t\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tint enabled;\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\t\t\t\tpParams->GetInteger( NONAME, &enabled, true );\r\n\r\n                this->SetProceduralBoneRotActive( boneName, enabled );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | SetBoneScaleMin | Sets the minimum translation extent for procedurally animated bone (in world units)\r\n        // @parmopt float | x | 0 | minimum extent x\r\n        // @parmopt float | y | 0 | minimum extent y\r\n        // @parmopt float | z | 0 | minimum extent z\r\n        // @parm name | bone | name of procedural bone\r\n\t\tcase 0xc6889e91: //\tSetBoneScaleMin\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec(0.0f,0.0f,0.0f);\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tpParams->GetFloat( CRCD(0x7323e97c,\"x\"), &vec[X], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x0424d9ea,\"y\"), &vec[Y], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &vec[Z], false );\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\t\t\t\t\r\n\t\t\t\tthis->SetProceduralBoneScaleMin( boneName, vec );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | SetBoneScaleMax | Sets the maximum translation extent for procedurally animated bone (in world units)\r\n\t\t// @parmopt float | x | 0 | maximum extent x\r\n\t\t// @parmopt float | y | 0 | maximum extent y\r\n\t\t// @parmopt float | z | 0 | maximum extent z\r\n\t\t// @parm name | bone | name of procedural bone\r\n\t\tcase 0xfa85a1c8: //\tSetBoneScaleMax\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec(0.0f,0.0f,0.0f);\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tpParams->GetFloat( CRCD(0x7323e97c,\"x\"), &vec[X], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x0424d9ea,\"y\"), &vec[Y], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &vec[Z], false );\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\t\t\t\t\r\n\t\t\t\tthis->SetProceduralBoneScaleMax( boneName, vec );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | SetBoneScaleSpeed | Sets the speed at which the bone's translation will procedurally animate (in 4096 notation)\r\n\t\t// @parmopt int | x | 0 | speed x (2048 immediately goes from T0 to T1)\r\n\t\t// @parmopt int | y | 0 | speed y (2048 immediately goes from T0 to T1)\r\n\t\t// @parmopt int | z | 0 | speed z (2048 immediately goes from T0 to T1)\r\n\t\t// @parm name | bone | name of procedural bone\r\n\t\tcase 0xd32c2724: //\tSetBoneScaleSpeed\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec(0.0f,0.0f,0.0f);\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tpParams->GetFloat( CRCD(0x7323e97c,\"x\"), &vec[X], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x0424d9ea,\"y\"), &vec[Y], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &vec[Z], false );\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\t\t\t\t\r\n\t\t\t\tthis->SetProceduralBoneScaleSpeed( boneName, vec );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | SetBoneScaleCurrent | Immediately sets the procedurally animated bone to a specific translation (in 4096 notation)\r\n\t\t// @parmopt int | x | 0 | current x (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0)\r\n\t\t// @parmopt int | y | 0 | current y (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0)\r\n\t\t// @parmopt int | z | 0 | current z (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0)\r\n\t\t// @parm name | bone | name of procedural bone\r\n\t\tcase 0xd12b3713: //\tSetBoneScaleCurrent\r\n\t\t\t{\r\n\t\t\t\tMth::Vector vec(0.0f,0.0f,0.0f);\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tpParams->GetFloat( CRCD(0x7323e97c,\"x\"), &vec[X], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x0424d9ea,\"y\"), &vec[Y], false );\r\n\t\t\t\tpParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &vec[Z], false );\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, true );\r\n\t\t\t\t\r\n\t\t\t\tthis->SetProceduralBoneScaleCurrent( boneName, vec );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | SetBoneScaleActive | Sets whether the bone should procedurally animate its translation\r\n\t\t// @uparm int | active (either 0 or 1)\r\n\t\t// @parm name | bone | name of procedural bone\r\n\t\tcase 0xf11daaae: //\tSetBoneScaleActive\r\n\t\t\t{\r\n\t\t\t\tuint32 boneName;\r\n\t\t\t\tint enabled;\r\n\t\t\t\tpParams->GetChecksum( \"bone\", &boneName, true );\r\n\t\t\t\tpParams->GetInteger( NONAME, &enabled, true );\r\n\t\t\t\t\r\n                this->SetProceduralBoneScaleActive( boneName, enabled );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tdefault:\r\n\t\t\treturn AF_NOT_EXECUTED;\r\n\t}\r\n\r\n\treturn AF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPoseController::CPoseController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPoseController::~CPoseController()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPoseController::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tCBaseAnimController::InitFromStructure( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPoseController::Update()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPoseController::SetPose( Gfx::CPose* pPose )\r\n{\r\n\tmemcpy( &m_pose, pPose, sizeof(Gfx::CPose) );\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPoseController::GetPose( Gfx::CPose* pResultPose )\r\n{\r\n\t// this nukes the existing pose, meaning that\r\n\t// this should be the only controller in the list...\r\n\tmemcpy( pResultPose, &m_pose, sizeof(Gfx::CPose) );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCLookAtController::CLookAtController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCLookAtController::~CLookAtController()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLookAtController::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tCBaseAnimController::InitFromStructure( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CLookAtController::Update()\r\n{\r\n\tDbg_MsgAssert( 0, ( \"Unimplemented function\" ) );\r\n\r\n\t// GJ:  This is just a sample controller...  I was thinking\r\n\t// that this could be used for orienting the head towards\r\n\t// an object in the scene, given some constraints\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPartialAnimController::CPartialAnimController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel )\r\n{\r\n\tmp_quickAnim = Nx::CEngine::sInitQuickAnim();\r\n\tmp_quickAnim->Enable( false );\r\n\t\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tm_animScriptName = pAnimationComponent->GetAnimScriptName();\r\n\r\n\tmp_animChannel = new Gfx::CAnimChannel;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPartialAnimController::~CPartialAnimController()\r\n{\r\n\tif ( mp_quickAnim )\r\n\t{\r\n\t\tNx::CEngine::sUninitQuickAnim( mp_quickAnim );\r\n\t\tmp_quickAnim = NULL;\r\n\t}\r\n\r\n\tif ( mp_animChannel )\r\n\t{\r\n\t\tdelete mp_animChannel;\r\n\t\tmp_animChannel = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPartialAnimController::InitFromStructure( Script::CStruct* pParams )\r\n{   \r\n\tCBaseAnimController::InitFromStructure( pParams );\r\n\t\r\n\tuint32 anim_name;\r\n\tpParams->GetChecksum( CRCD(0x6c2bfb7f,\"animName\"), &anim_name, Script::ASSERT );\r\n\t\r\n\tfloat From = 0.0f;\r\n\tfloat To = 0.0f;\r\n\tfloat Current = 0.0f;\r\n\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() );\r\n\tfloat Duration = pAnimationComponent->AnimDuration( anim_name );\r\n\tGfx::GetTimeFromParams( &From, &To, Current, Duration, pParams, NULL );\r\n\t  \r\n\tGfx::EAnimLoopingType loopingType;\r\n\tGfx::GetLoopingTypeFromParams( &loopingType, pParams );\r\n\r\n\tfloat speed = 1.0f;\r\n\tpParams->GetFloat( CRCD(0xf0d90109,\"speed\"), &speed, Script::NO_ASSERT );\r\n\t\r\n\tpParams->GetFloat(CRCD(0x230ccbf4, \"Current\"), &Current);\r\n\r\n\tfloat blend_period = 0.0f;\r\n\r\n\tmp_animChannel->PlaySequence( anim_name, From, To, loopingType, blend_period, speed);\r\n\t\r\n\tif (Current != 0.0f)\r\n\t{\r\n\t\tmp_animChannel->AddTime(Current);\r\n\t}\r\n\r\n\tDbg_Assert( mp_quickAnim );\r\n\tmp_quickAnim->SetAnimAssetName( m_animScriptName + anim_name );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPartialAnimController::GetPose( Gfx::CPose* pResultPose )\r\n{\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t{\r\n\t\tCSkeleton* pSkeleton = GetSkeleton();\r\n\t\tDbg_MsgAssert( pSkeleton, ( \"No skeleton?\" ) );\t\r\n\t\tDbg_MsgAssert( pResultPose, ( \"No return data\" ) );\r\n\t}\r\n\t#endif\r\n\t\r\n//\tint skipList[vMAX_BONES];\r\n//\tGetSkeleton()->GetSkipList( &skipList[0] );\r\n\tuint32*\tp_skip_list = GetSkeleton()->GetBoneSkipList();\r\n\tuint32\tskip_index\t= GetSkeleton()->GetBoneSkipIndex();\r\n\r\n#if 1\r\n\tDbg_Assert( mp_quickAnim );\r\n\tmp_quickAnim->GetInterpolatedFrames( pResultPose->m_rotations, pResultPose->m_translations, p_skip_list, skip_index, mp_animChannel->GetCurrentAnimTime() );\r\n\tmp_quickAnim->Enable( true );\r\n#else\r\n\tMth::Quat theRot[128];\r\n\tMth::Vector theTrans[128];\r\n\r\n\tDbg_Assert( mp_quickAnim );\r\n\tmp_quickAnim->GetInterpolatedFrames( theRot, theTrans, p_skip_list, skip_index, mp_animChannel->GetCurrentAnimTime() );\r\n\tmp_quickAnim->Enable( true );\r\n\t\r\n\tScript::CArray* pArray = Script::GetArray( m_boneListName, Script::ASSERT );\r\n\tfor ( uint32 i = 0; i < pArray->GetSize(); i++ )\r\n\t{\r\n\t\tint idx = pSkeleton->GetBoneIndexById( pArray->GetChecksum(i) );\r\n\t\tif ( idx != -1 )\r\n\t\t{\r\n\t\t\t*(pResultPose->m_rotations+idx)=theRot[idx];\r\n\t\t\t*(pResultPose->m_translations+idx)=theTrans[idx];\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPartialAnimController::Update()\r\n{\r\n\t// This class is used for either appending,\r\n\t// or overwriting a subset of the bones in the RT array,\r\n\t// given a CBonedAnimFrameData...\r\n\tDbg_MsgAssert( mp_animChannel->m_loopingType != Gfx::LOOPING_WOBBLE, ( \"Not supposed to be wobble type\" ) );\r\n\t\t\t\r\n\tfloat oldTime = mp_animChannel->m_currentTime;\r\n\r\n\tmp_animChannel->m_currentTime = mp_animChannel->get_new_anim_time();\r\n\r\n//\tmp_animChannel->ProcessCustomKeys( oldTime, mp_animChannel->m_currentTime );\r\n\r\n\tif ( mp_animChannel->m_currentTime < oldTime )\r\n\t{\r\n\t\tmp_quickAnim->Enable( false );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nEAnimFunctionResult CPartialAnimController::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tcase 0x5f495ae0:\t// InvalidateCache\r\n\t\t{\r\n\t\t\tmp_quickAnim->Enable( false );\r\n\t\t\t\r\n\t\t\t// want the other controllers to be invalidated too\r\n\t\t\treturn AF_NOT_EXECUTED;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0xd63a1b81:\t// GetPartialAnimParams\r\n\t\t{\r\n\t\t\tDbg_Assert( pScript );\r\n\t\t\tpScript->GetParams()->AddFloat( CRCD(0xaaecb346,\"partialAnimTime\"), mp_animChannel->GetCurrentAnimTime() );\r\n\t\t\tpScript->GetParams()->AddChecksum( CRCD(0x659bf355,\"partialAnim\"), mp_animChannel->GetCurrentAnim() );\r\n\t\t\tpScript->GetParams()->AddInteger( CRCD(0x4966cc11,\"partialAnimComplete\"), mp_animChannel->IsAnimComplete() );\r\n\r\n\t\t\treturn AF_TRUE;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0xbd4edd44: // SetPartialAnimSpeed\r\n\t\t{\r\n\t\t\tfloat speed;\r\n\t\t\tpParams->GetFloat( CRCD(0xf0d90109,\"speed\"), &speed, Script::ASSERT );\t\t\t\r\n\t\t\tmp_animChannel->SetAnimSpeed( speed );\r\n\r\n\t\t\treturn AF_TRUE;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0x6aaeb76f: // IncrementPartialAnimTime\r\n\t\t{\r\n\t\t\tfloat incVal;\r\n\t\t\tpParams->GetFloat( CRCD(0x06c9f278,\"incVal\"), &incVal, Script::ASSERT );\t\t\t\r\n\t\t\t\r\n\t\t\t// GJ:  a way to fool the animation controller\r\n\t\t\t// into incrementing its time (frame rate\r\n\t\t\t// independent) for the viewer object\r\n\r\n\t\t\tfloat oldAnimSpeed = mp_animChannel->GetAnimSpeed();\r\n\r\n\t\t\tmp_animChannel->SetAnimSpeed( 0.0f );\r\n\r\n\t\t\tmp_animChannel->m_currentTime += incVal;\r\n\r\n\t\t\tmp_animChannel->Update();\r\n\r\n\t\t\tmp_animChannel->SetAnimSpeed( oldAnimSpeed );\r\n\r\n\t\t\treturn AF_TRUE;\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\t\r\n\t\tcase 0xf5e2b871: // ReversePartialAnimDirection\r\n\t\t{\r\n\t\t\tmp_animChannel->ReverseDirection();\r\n\r\n\t\t\treturn AF_TRUE;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\treturn AF_NOT_EXECUTED;\r\n\t}\r\n\r\n\treturn AF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Gfx/subanimcontroller.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       SubAnimController.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  2/06/2003\r\n//****************************************************************************\r\n\r\n#ifndef __GFX_SUBANIMCONTROLLER_H__\r\n#define __GFX_SUBANIMCONTROLLER_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <core/math.h>\r\n\r\n#include <gfx/baseanimcontroller.h>\r\n#include <gfx/pose.h>\r\n\r\n// This file contains all the custom animation controllers\r\n// which can be chained together by an animation channel\r\n// to produce its final array of RT data for each frame.\r\n// For example, an animated skeleton might need to:\r\n//   (1) grab interpolated keyframe data\r\n//   (2) flip the skeleton\r\n//   (3) rotate the skateboard by 180 degrees\r\n//   (4) perform IK on the leg bones to lock them to the skateboard\r\n//   (5) apply an additional keyframed anim to only the cloth bones\r\n//   (6) orient the head towards the closest pedestrian.\r\n// In this case, there would be one animation channel with\r\n// six animation controllers.\r\n\r\n// Eventually, we'll probably want to break up this\r\n// code into a separate file for each animation\r\n// controller, and perhaps create a factory class so that\r\n// BlendChannel.cpp doesn't need to be updated every time\r\n// a new animation controller is added.\r\n\t\t\t\t\t\t   \r\nnamespace Script\r\n{\r\n\tclass CScript;\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\tclass CQuickAnim;\r\n}\r\n\r\nnamespace Gfx\r\n{\r\n\tclass CBlendChannel;\r\n\tclass CProceduralBone;\r\n\tclass CAnimChannel;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// This controller is used for getting interpolated\r\n// keyframe data from a CBonedAnimFrameData.  It\r\n// accesses it through a Nx::CQuickAnim, which allows\r\n// for future optimizations.\r\n\r\nclass CBonedAnimController : public CBaseAnimController\r\n{\r\npublic:\r\n\tCBonedAnimController( CBlendChannel* pBlendChannel );\r\n\tvirtual\t~CBonedAnimController();\r\n\r\npublic:\r\n\tvirtual void \t\t\t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void \t\t\t\tUpdate();\r\n    virtual EAnimFunctionResult CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual bool\t\t\t\tGetPose( Gfx::CPose* pResultPose );\r\n\t\r\nprotected:\r\n\tNx::CQuickAnim*\t\t\t\tmp_quickAnim;\r\n\tuint32\t\t\t\t\t\tm_animScriptName;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// This controller is used for wobble effects (such\r\n// as grinding and manualling).  It's very similar to\r\n// the boned anim controller, and should probably be\r\n// refactored to share some code at some point.\r\n\r\nclass CWobbleController : public CBaseAnimController\r\n{\r\npublic:\r\n\tCWobbleController( CBlendChannel* pBlendChannel );\r\n\tvirtual\t~CWobbleController();\r\n\r\npublic:\r\n\tvirtual void \t\t\t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void \t\t\t\tUpdate();\r\n\tvirtual void\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n    virtual EAnimFunctionResult CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual bool\t\t\t\tGetPose( Gfx::CPose* pResultPose );\r\n\r\nprotected:\r\n    SWobbleDetails  \t\t\tm_wobbleDetails;\r\n    float\t\t\t\t\t\tm_wobbleTargetTime;\r\n\tNx::CQuickAnim*\t\t\t\tmp_quickAnim;\r\n\tuint32\t\t\t\t\t\tm_animScriptName;\r\n\r\nprotected:\r\n\tfloat\t\t\t\t\t\tget_new_wobble_time();\r\n\r\npublic:\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// This controller is used for flipping the skeleton\r\n// and rotating the skateboard.  Truthfully, the two\r\n// actions are completely unrelated, but they are\r\n// so simple that it seemed like a waste to separate\r\n// them into two controllers.  Later on, I may decide\r\n// to add separate controllers for each.\r\n\r\nclass CFlipRotateController : public CBaseAnimController\r\n{\r\npublic:\r\n\tCFlipRotateController( CBlendChannel* pBlendChannel );\r\n\tvirtual ~CFlipRotateController();\r\n\r\npublic:\r\n\tvirtual void \t\t\t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void \t\t\t\tUpdate();\r\n\tvirtual bool\t\t\t\tGetPose( Gfx::CPose* pResultPose );\r\n\t\r\nprotected:\r\n\tbool\t\t\t\t\t\tm_flipped;\r\n\tbool\t\t\t\t\t\tm_rotated;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// This controller is a placeholder for Left Field's\r\n// IK code.  Although THPS4 did not use IK, it would\r\n// be easy to add once LF and Neversoft both reorganized\r\n// their code to use this system of animation channels\r\n// and animation controllers.\r\n\r\nclass CIKController : public CBaseAnimController\r\n{\r\npublic:\r\n\tCIKController( CBlendChannel* pBlendChannel );\r\n\tvirtual ~CIKController();\r\n\r\npublic:\r\n\tvirtual void \t\t\t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void \t\t\t\tUpdate();\r\n\tvirtual void\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n    virtual EAnimFunctionResult CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual bool\t\t\t\tGetPose( Gfx::CPose* pResultPose );\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// This controller is also a placeholder.  On THPS4,\r\n// we implemented something similar in order to\r\n// programmatically animate our cloth bones.  This\r\n// system was inefficient and unwieldy, and we've\r\n// decided to scrap it in order to implement \r\n// \"partial animations\", which means the animators \r\n// can create SKA files containing animation\r\n// data for only the cloth bones.  Left Field can\r\n// potentially use the CProceduralAnimController\r\n// to do programmatic animation on the bike's tires.\r\n\r\nclass CProceduralAnimController : public CBaseAnimController\r\n{\r\npublic:\r\n\tCProceduralAnimController( CBlendChannel* pBlendChannel );\r\n\tvirtual ~CProceduralAnimController();\r\n\r\npublic:\r\n\tvirtual void \t\t\t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void \t\t\t\tUpdate();    \r\n\tvirtual EAnimFunctionResult CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual bool\t\t\t\tGetPose( Gfx::CPose* pResultPose );\r\n\t\r\nprotected:\r\n\tCProceduralBone*\t\t\tget_procedural_bone_by_id( uint32 boneName );\r\n\t\r\nprotected:\r\n\tvoid\t\t   \t\t\t\tSetProceduralBoneTransMin( uint32 boneName, const Mth::Vector& vec );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneTransMax( uint32 boneName, const Mth::Vector& vec );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneTransSpeed( uint32 boneName, const Mth::Vector& vec );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneTransCurrent( uint32 boneName, const Mth::Vector& vec );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneTransActive( uint32 boneName, bool enabled );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneRotMin( uint32 boneName, const Mth::Vector& vec );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneRotMax( uint32 boneName, const Mth::Vector& vec );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneRotSpeed( uint32 boneName, const Mth::Vector& vec );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneRotCurrent( uint32 boneName, const Mth::Vector& vec );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneRotActive( uint32 boneName, bool enabled );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneScaleMin( uint32 boneName, const Mth::Vector& vec );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneScaleMax( uint32 boneName, const Mth::Vector& vec );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneScaleSpeed( uint32 boneName, const Mth::Vector& vec );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneScaleCurrent( uint32 boneName, const Mth::Vector& vec );\r\n\tvoid\t\t\t\t\t\tSetProceduralBoneScaleActive( uint32 boneName, bool enabled );\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// This controller just stores a single Gfx::CPose.\r\n// Perhaps degenerating blend channels can\r\n// collapse their list of animation controllers\r\n// and replace them with the CPoseController\r\n// as a slight optimization.\r\n\r\nclass CPoseController : public CBaseAnimController\r\n{\r\npublic:\r\n\tCPoseController( CBlendChannel* pBlendChannel );\r\n\tvirtual\t~CPoseController();\r\n\r\npublic:\r\n\tvirtual void \t\t\t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void \t\t\t\tUpdate();\r\n\tvirtual bool\t\t\t\tGetPose( Gfx::CPose* pResultPose );\r\n\r\npublic:\r\n\tvoid\t\t\t\t\t\tSetPose( Gfx::CPose* pPose );\r\n\r\nprotected:\r\n\tGfx::CPose\t\t\t\t\tm_pose;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// This controller hasn't been implemented yet.\r\n// I was thinking that it could be used to\r\n// reorient the head towards a particular lookup\r\n// target.\r\n\r\nclass CLookAtController : public CBaseAnimController\r\n{\r\npublic:\r\n\tCLookAtController( CBlendChannel* pBlendChannel );\r\n\tvirtual\t~CLookAtController();\r\n\r\npublic:\r\n\tvirtual void \t\t\t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void \t\t\t\tUpdate();\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// This controller hasn't been implemented yet.\r\n// It will be used to read a partial SKA anim \r\n// from a file, for animating cloth bones and\r\n// for doing secondary anims (for example, we\r\n// may want to apply an additional wobble animation\r\n// to the upper body when the skater lands from\r\n// a particular high trick)\r\nclass CPartialAnimController : public CBaseAnimController\r\n{\r\n\r\npublic:\r\n\tCPartialAnimController( CBlendChannel* pBlendChannel );\r\n\tvirtual ~CPartialAnimController();\r\n\r\npublic:\r\n\tvirtual void \t\t\t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void \t\t\t\tUpdate();\r\n\tvirtual bool\t\t\t\tGetPose( Gfx::CPose* pResultPose );\r\n\tEAnimFunctionResult\t\t\tCallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\npublic:\r\n\tGfx::CAnimChannel*\t\t\tmp_animChannel;\r\n\tNx::CQuickAnim*\t\t\t\tmp_quickAnim;\r\n\tuint32\t\t\t\t\t\tm_animScriptName;\r\n};\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/vecfont.cpp",
    "content": "#if 0\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics Lib (gfx)\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tvecfont.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/31/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tVector font class\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gfx/vecfont.h>\r\n#include <sys/mem/memman.h>\r\n#include <gfx/image/imagebasic.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Gfx\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nuint32\t\t\t\tVecFont::s_char_length[256];\r\nVecFont::CharLine*\t\tVecFont::s_char_maps[256];\r\nVecFont::CharLine\t\tVecFont::s_symbol_maps1[15][16] =\r\n{\r\n\t {{64,0,64,16},\r\n      {64,32,64,128}},          /* ! */\r\n     {{32,96,32,128},\r\n      {96,96,96,128}},          /* \" */\r\n     {{32,0,32,128},\r\n      {96,0,96,128},\r\n      {0,32,128,32},\r\n      {0,96,128,96}},           /* # */\r\n     {{0,0,128,0},\r\n      {128,0,128,64},\r\n      {128,64,0,64},\r\n      {0,64,0,128},\r\n      {0,128,128,128},\r\n      {64,0,64,128}},           /* $ */\r\n     {{0,0,128,128},\r\n      {0,112,16,128},\r\n      {112,0,128,16}},          /* % */\r\n     {{0,0,0,0}},               /* & - yeah,   right */\r\n     {{64,96,64,128}},          /* ' */\r\n     {{96,128,64,96},\r\n      {64,96,64,32},\r\n      {64,32,96,0}},            /* ( */\r\n     {{32,128,64,96},\r\n      {64,96,64,32},\r\n      {64,32,32,0}},            /* ) */\r\n     {{64,0,64,128},\r\n      {0,64,128,64},\r\n      {32,32,96,96},\r\n      {32,96,96,32}},           /* * */\r\n     {{64,32,64,96},\r\n      {32,64,96,32}},           /* + */\r\n     {{64,0,96,32}},            /* , */\r\n     {{32,64,96,64}},           /* - */\r\n     {{64,0,64,32}},            /* . */     \r\n     {{0,0,128,128}}\r\n};          /* / */\r\n\r\nVecFont::CharLine VecFont::s_symbol_maps2[7][16] =\r\n{\r\n\t {{64,0,64,16},\r\n\t  {64,128,64,112}},         /* : */\r\n     {{32,0,64,32},\r\n      {64,128,64,112}},         /* ; */\r\n     {{128,128,0,64},\r\n      {0,64,128,0}},            /* < */\r\n     {{0,32,128,32},\r\n      {0,96,128,96}},           /* =\r\n                                 */\r\n     {{0,128,128,64},\r\n      {128,64,0,0}},            /* > */\r\n     {{0,0,0,0}},               /* ? - yeah, right */\r\n     {{0,0,0,0}}                /* @ - yeah, right */\r\n};              \r\n\r\nVecFont::CharLine VecFont::s_digit_maps[10][16] =\r\n{\r\n\t {{0,0,128,0},\r\n      {128,0,128,128},\r\n      {128,128,0,128},\r\n      {0,128,0,0}},             /* 0 */\r\n     {{128,0,128,128}},         /* 1 */\r\n     {{0,128,128,128},\r\n      {128,128,128,64},\r\n      {128,64,0,64},\r\n      {0,64,0,0},\r\n      {0,0,128,0}},             /* 2 */\r\n     {{0,128,128,128},\r\n      {128,128,128,0},\r\n      {128,0,0,0},\r\n      {128,64,0,64}},           /* 3 */\r\n     {{0,128,0,64},\r\n      {0,64,128,64},\r\n      {128,128,128,0}},         /* 4 */\r\n     {{128,128,0,128},\r\n      {0,128,0,64},\r\n      {0,64,128,64},\r\n      {128,64,128,0},\r\n      {128,0,0,0}},             /* 5 */\r\n     {{128,128,0,128},\r\n      {0,128,0,0},\r\n      {0,0,128,0},\r\n      {128,0,128,64},\r\n      {128,64,0,64}},           /* 6 */\r\n     {{0,128,128,128},\r\n      {128,128,128,0}},         /* 7 */\r\n     {{0,0,128,0},\r\n      {128,0,128,128},\r\n      {128,128,0,128},\r\n      {0,128,0,0},\r\n      {0,64,128,64}},           /* 8 */\r\n     {{0,0,128,0},\r\n      {128,0,128,128},\r\n      {128,128,0,128},\r\n      {0,128,0,64},      {0,64,128,64}}\r\n}; /* 9 */\r\n\r\nVecFont::CharLine VecFont::s_alpha_maps[26][16] =\r\n{\r\n\t {{0,0,64,128},\r\n      {64,128,128,0},\r\n      {32,64,96,64}},           /* a */\r\n     {{0,128,0,0},\r\n      {0,0,128,0},\r\n      {128,0,128,64},\r\n      {128,64,0,64}},           /* b */\r\n     {{128,128,0,128},\r\n      {0,128,0,0},\r\n      {0,0,128,0}},             /* c */\r\n     {{0,0,0,128},\r\n      {0,128,128,64},\r\n      {128,64,128,0},\r\n      {128,0,0,0}},             /* d */\r\n     {{128,128,0,128},\r\n      {0,128,0,0},\r\n      {0,0,128,0},\r\n      {0,64,64,64}},            /* e */\r\n     {{128,128,0,128},\r\n      {0,128,0,0},\r\n      {0,64,64,64}},            /* f */\r\n     {{128,128,0,128},\r\n      {0,128,0,0},\r\n      {0,0,128,0},\r\n      {128,0,128,64}},          /* g */\r\n     {{0,128,0,0},\r\n      {0,64,128,64},\r\n      {128,128,128,0}},         /* h */\r\n     {{64,0,64,128}},           /* i */\r\n     {{0,0,128,0},\r\n      {128,0,128,128}},         /* j */\r\n     {{0,0,0,128},\r\n      {128,0,0,64},\r\n      {0,64,128,128}},          /* k */\r\n     {{0,0,0,128},\r\n      {0,0,128,0}},             /* l */\r\n     {{0,0,0,128},\r\n      {0,128,64,0},\r\n      {64,0,128,128},\r\n      {128,128,128,0}},         /* m */\r\n     {{0,0,0,128},\r\n      {0,128,128,128},\r\n      {128,128,128,0}},         /* n */\r\n     {{0,0,128,0},\r\n      {128,0,128,128},\r\n      {128,128,0,128},\r\n      {0,128,0,0}},             /* o */\r\n     {{0,0,0,128},\r\n      {0,128,128,128},\r\n      {128,128,128,64},\r\n      {128,64,0,64}},           /* p */\r\n     {{128,0,128,128},\r\n      {128,128,0,128},\r\n      {0,128,0,64},\r\n      {0,64,128,64}},           /* q */\r\n     {{0,0,0,128},\r\n      {0,128,128,128},\r\n      {128,128,128,64},\r\n      {128,64,0,64},\r\n      {0,64,128,0}},            /* r */\r\n     {{0,0,128,0},\r\n      {128,0,128,64},\r\n      {128,64,0,64},\r\n      {0,64,0,128},\r\n      {0,128,128,128}},         /* s */\r\n     {{0,128,128,128},\r\n      {64,128,64,0}},           /* t */\r\n     {{0,128,0,0},\r\n      {0,0,128,0},\r\n      {128,0,128,128}},         /* u */\r\n     {{0,128,64,0},\r\n      {64,0,128,128}},          /* v */\r\n     {{0,128,0,0},\r\n      {0,0,64,128},\r\n      {64,128,128,0},\r\n      {128,0,128,128}},         /* w */\r\n     {{0,128,128,0},\r\n      {0,0,128,128}},           /* x */\r\n     {{0,0,128,0},\r\n      {128,0,128,128},\r\n      {0,128,0,64},\r\n      {0,64,128,64}},           /* y */\r\n     {{128,0,0,0},\r\n      {0,0,128,128},      \r\n      {128,128,0,128}}\t\t\t/* z */\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid VecFont::assign_line_list( uint32 target, CharLine* lineList )\r\n{\r\n    s_char_length[target] = 0;\r\n    s_char_maps[target] = lineList;\r\n\r\n    while ( lineList->startX | lineList->startY | lineList->endX | lineList->endY )\r\n    {\r\n        s_char_length[target]++;\r\n        lineList++;\r\n    }\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nVecFont::VecFont( const Image::RGBA color, float w, float h )\r\n{\r\n/*\r\n        \r\n//\tRwV2dScale( &m_size, size, (RwReal)(1.0f/192.0f) );\r\n\t\r\n\tm_color = color;\r\n\tm_lineVertBuffer = NULL;\r\n\tm_lineVertBufferSize = 0;\r\n\r\n    uint32 i;\r\n\r\n    for (i = 0; i < 256; i++)\r\n    {\r\n        s_char_length[i] = 0;\r\n    }\r\n\r\n    for (i = 0; i < 15; i++)\r\n    {\r\n        assign_line_list('!'+i, s_symbol_maps1[i]);\r\n    }\r\n\r\n    for (i = 0; i < 10; i++)\r\n    {\r\n        assign_line_list('0'+i, s_digit_maps[i]);\r\n    }\r\n\r\n    for (i = 0; i < 7; i++)\r\n    {\r\n        assign_line_list(':'+i, s_symbol_maps2[i]);\r\n    }\r\n\r\n    for (i = 0; i < 26; i++)\r\n    {\r\n        assign_line_list('a'+i, s_alpha_maps[i]);\r\n        assign_line_list('A'+i, s_alpha_maps[i]);\r\n    }\r\n*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#define\tVECFONTSIZE  50000\r\n\r\nvoid\tVecFont::Print( float x, float y, const char* string )\r\n{\r\n\t\r\n#if 0\r\n\r\n#ifndef __PLAT_NGC__\r\n    uint32 i, numLines;\r\n    RwV2d    localPos = pos;\r\n\r\n    /* Make sure that the line vertex buffer is big enough */\r\n    i = numLines = 0;\r\n    while (string[i])\r\n    {\r\n        numLines += s_char_length[(uint32)string[i]];\r\n        i++;\r\n    }\r\n\r\n\r\n\r\n    /* Will it fit? */\r\n    if (numLines > m_lineVertBufferSize)\r\n    {\r\n        uint32\t\tnewSize = 2 * sizeof(RWIM2DVERTEX) * numLines;\r\n\r\n\t\tif (newSize < VECFONTSIZE)\r\n\t\t{\r\n\t\t\tnumLines = VECFONTSIZE / (2 * sizeof(RWIM2DVERTEX))  + 1;\r\n\t\t\tnewSize = 2 * sizeof(RWIM2DVERTEX) * numLines;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"metric vector font overflow, numLines = %d, m_lineVertBufferSize %d \", numLines, m_lineVertBufferSize));\r\n\t\t}\r\n\t\t\r\n\t\tprintf(\">>>>>>>>>>>>>>>>>>>>>>>>> newSize = %d\\n\",newSize);\r\n\t\t\r\n        RWIM2DVERTEX*\tnewLineVertBuffer;\r\n\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().RwHeap());\r\n        if ( m_lineVertBuffer )\r\n        {\r\n            newLineVertBuffer = (RWIM2DVERTEX *)RwRealloc( m_lineVertBuffer, newSize );\r\n        }\r\n        else\r\n        {\r\n            newLineVertBuffer = (RWIM2DVERTEX *)RwMalloc(newSize);\r\n        }\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\r\n        if (newLineVertBuffer)\r\n        {\r\n            /* Got through and set all uv, recip z, screen z, etc */\r\n            for (i = m_lineVertBufferSize*2; i < numLines*2; i++ )\r\n            {\r\n\t\t\t\tRwReal\tnear_z = RwIm2DGetNearScreenZ();\r\n\t\t\t\tRwReal\trecip_z = 1.0f/near_z;\r\n                RWIM2DVERTEXSetScreenZ( &newLineVertBuffer[i], near_z );\r\n                RWIM2DVERTEXSetRecipCameraZ( &newLineVertBuffer[i], recip_z );\r\n                RWIM2DVERTEXSetU(&newLineVertBuffer[i], (RwReal)(0.0f), (RwReal)(1.0f));\r\n                RWIM2DVERTEXSetV(&newLineVertBuffer[i], (RwReal)(0.0f), (RwReal)(1.0f));\r\n                RWIM2DVERTEXSetIntRGBA(&newLineVertBuffer[i], m_color.red, m_color.green,\r\n                                      m_color.blue, m_color.alpha);\r\n            }\r\n\t\t\tm_lineVertBuffer = newLineVertBuffer;\r\n            m_lineVertBufferSize = numLines;\r\n        }\r\n    }\r\n\r\n    /* Will it fit now */\r\n    if ( numLines <= m_lineVertBufferSize )\r\n    {\r\n        RWIM2DVERTEX*\tcurLineVerts = m_lineVertBuffer;\r\n\r\n        i = 0;\r\n        while (string[i])\r\n        {\r\n            uint32 \tnumCharLines = s_char_length[(uint32)string[i]];\r\n            CharLine*\tcurLine \t = s_char_maps[(uint32)string[i]];\r\n\r\n            while (numCharLines--)\r\n            {\r\n                RwLine line;\r\n\r\n                line.start.x = localPos.x + ((RwReal)curLine->startX * m_size.x);\r\n                line.start.y = localPos.y + ((RwReal)(128-curLine->startY) * m_size.y);\r\n                line.end.x = localPos.x + ((RwReal)curLine->endX * m_size.x);\r\n                line.end.y = localPos.y + ((RwReal)(128-curLine->endY) * m_size.y);\r\n\r\n                RWIM2DVERTEXSetScreenX(&curLineVerts[0], line.start.x);\r\n                RWIM2DVERTEXSetScreenY(&curLineVerts[0], line.start.y);\r\n                RWIM2DVERTEXSetScreenX(&curLineVerts[1], line.end.x);\r\n                RWIM2DVERTEXSetScreenY(&curLineVerts[1], line.end.y);\r\n\r\n                curLineVerts += 2;\r\n                curLine++;\r\n            }\r\n\r\n            localPos.x += m_size.x * (RwReal)(192.0f);\r\n            i++;\r\n        }\r\n\r\n        /* We don't need to corrupt too much render state here */\r\n        RwRenderStateSet(rwRENDERSTATETEXTURERASTER, NULL);\r\n\r\n        RwIm2DRenderPrimitive(rwPRIMTYPELINELIST, m_lineVertBuffer, numLines*2);\r\n    }\r\n#endif\t\t// __PLAT_NGC__\r\n#endif\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nVecFont::~VecFont( void )\r\n{\r\n\t\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Gfx/vecfont.h",
    "content": "#if 0\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tGFX (Graphics Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGraphics  (GFX)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tgfx/vecfont.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t11/11/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GFX_VECFONT_H\r\n#define __GFX_VECFONT_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <gfx/image/imagebasic.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  VecFont  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic:\r\n\t\t\t\t\t\tVecFont( const Image::RGBA color, float w, float h);\r\n\t\t\t\t\t\t~VecFont( void );\t\t \r\n\r\n\tvoid\t\t\t\tPrint( float x, float y, const char* string );\r\n\r\nprivate:\r\n\r\n\r\n\tstruct CharLine\r\n\t{\r\n\t\tuint8\t\t\tstartX;\r\n\t\tuint8\t\t\tstartY;\r\n\t\tuint8\t\t\tendX;\r\n\t\tuint8\t\t\tendY;\r\n\t};\r\n\r\n\tvoid\t\t\t\tassign_line_list( uint32 target, CharLine* lineList );\r\n\r\n\tfloat\t\t\t\tm_size_x,m_size_y;\r\n\tImage::RGBA\t\t\tm_color;\r\n\t\r\n//\tRWIM2DVERTEX*\t\tm_lineVertBuffer;\r\n//\tRwUInt32\t\t\tm_lineVertBufferSize;\r\n\r\n\tstatic uint32\t\ts_char_length[256];\r\n\tstatic CharLine*\ts_char_maps[256];\r\n\tstatic CharLine\t\ts_symbol_maps1[15][16];\r\n\tstatic CharLine\t\ts_symbol_maps2[7][16];\r\n\tstatic CharLine\t\ts_digit_maps[10][16];\r\n\tstatic CharLine\t\ts_alpha_maps[26][16];\r\n};\r\n\r\n\r\n/*****************************s************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Gfx\r\n\r\n#endif // __GFX_VECFONT_H\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Sk/Components/EditorCameraComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       EditorCameraComponent.cpp\r\n//* OWNER:          KSH\r\n//* CREATION DATE:  26 Mar 2003\r\n//****************************************************************************\r\n\r\n#include <sk/components/editorcameracomponent.h>\r\n#include <sk/components/raileditorcomponent.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/parse.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <sk/engine/feeler.h>\r\n#include <gfx/shadow.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <sys/config/config.h>\r\n#include <sk/parkeditor2/parked.h>\r\n\r\n//#define DEBUG_COLLISION\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\nstatic bool sHitKillPoly=false;\r\n// If a poly's node's trigger script contains any of these then it is considered a Kill poly\r\nstatic uint32 spKillScripts[]=\r\n{\r\n\tCRCC(0xdea3057b,\"SK3_KillSkater\"),\r\n\tCRCC(0xb1058546,\"SK3_KillSkater_Water\"),\r\n\tCRCC(0xb38ed6b,\"SK3_KillSkater_Finish\"),\r\n\tCRCC(0x1310920e,\"SK3_KillSkater_Pungee\"),\r\n\tCRCC(0x979a99ab,\"NY_KillWater\"),\r\n\tCRCD(0x7aae1282,\"RU_KillSkater\"),\r\n\tCRCD(0xcb1b1d9e,\"RU_KillSkater2\"),\r\n\tCRCD(0x84e5c703,\"NY_LeavingMessage\"),\r\n\tCRCD(0xf66fdf6e,\"SJ_Televator\"),\r\n\tCRCD(0xb21175da,\"HI_KillSkater_LittleDogs\"),\r\n\tCRCD(0xd9d60165,\"VC_CAG_boundary\"),\r\n};\r\n\r\nstatic void s_check_if_kill_poly ( CFeeler* p_feeler )\r\n{\r\n\tif (!p_feeler->GetTrigger() || !p_feeler->GetNodeChecksum())\r\n\t{\r\n\t\t#ifdef DEBUG_COLLISION\r\n\t\t//printf(\"Not got trigger or not got node checksum\\n\");\r\n\t\t#endif\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tint node = SkateScript::FindNamedNode(p_feeler->GetNodeChecksum(), false);// false means don't assert\r\n\tif (node < 0)\r\n\t{\r\n\t\t// Got a trigger, but no node, so assume it is a kill poly. This case arises in the park editor\r\n\t\t// where a kill piece such as water or lava has been placed but the node array has not been generated yet.\r\n\t\t//sHitKillPoly=true;\r\n\t\t// Note: Commented out, to fix TT8832, where the cursor could get stuck on cars.\r\n\t\t// The PE now allows the cursor to go anywhere, even onto kill polys.\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tScript::CArray *p_node_array = Script::GetArray(CRCD(0xc472ecc5, \"NodeArray\"));\r\n\tScript::CStruct *p_node = p_node_array->GetStructure(node);\r\n\t\r\n\tuint32 trigger_script=0;\r\n\tp_node->GetChecksum(CRCD(0x2ca8a299,\"TriggerScript\"),&trigger_script);\r\n\t\r\n\tif (trigger_script)\r\n\t{\r\n\t\t//printf(\"trigger_script=%s\\n\",Script::FindChecksumName(trigger_script));\r\n\t\tif (Script::ScriptContainsAnyOfTheNames(trigger_script,spKillScripts,sizeof(spKillScripts)/sizeof(uint32)))\r\n\t\t{\r\n\t\t\tsHitKillPoly=true;\r\n\t\t}\t\r\n\t}\t\r\n}\r\n\r\n// Checks whether the vector posA -> posB goes through any Kill polys.\r\n// Does not check collidable polys.\r\nstatic bool s_goes_through_kill_poly(const Mth::Vector &posA, const Mth::Vector &posB)\r\n{\r\n\tsHitKillPoly=false;\r\n\t\r\n\tCFeeler feeler;\r\n\t\r\n\tfeeler.m_start = posA;\r\n\tfeeler.m_end = posB;\r\n\r\n\tfeeler.SetIgnore(0, mFD_NON_COLLIDABLE | mFD_TRIGGER);\r\n\tfeeler.SetCallback(s_check_if_kill_poly);\r\n\t//feeler.DebugLine(0,255,0);\r\n\tfeeler.GetCollision();\r\n\t\r\n\treturn sHitKillPoly;\r\n}\r\n\r\nbool CEditorCameraComponent::find_y(Mth::Vector start, Mth::Vector end, float *p_y)\r\n{\r\n\t#ifdef DEBUG_COLLISION\r\n\t//printf(\"s_find_y: \");\r\n\t#endif\r\n\t\r\n\tCFeeler feeler;\r\n\tfeeler.SetStart(start);\r\n\tfeeler.SetEnd(end);\r\n\t// Ignore invisible polys, otherwise one can get stuck on top of the hotel in Hawaii,\r\n\t// because it is surrounded by horizontal invisible polys.\r\n\t//feeler.SetIgnore(mFD_INVISIBLE, 0);\t\r\n\t\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tif (m_simple_collision)\r\n\t\t{\r\n\t\t\t#ifdef DEBUG_COLLISION\r\n\t\t\tprintf(\"Simple drop down\\n\");\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tsHitKillPoly=false;\r\n\t\t\tMth::Vector point=feeler.GetPoint();\r\n\t\t\t*p_y=point[Y];\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t\r\n\t\tsHitKillPoly=false;\r\n\t\ts_check_if_kill_poly(&feeler);\r\n\t\tif (sHitKillPoly)\r\n\t\t{\r\n\t\t\t// Can't go onto collidable Kill polys\r\n\t\t\t#ifdef DEBUG_COLLISION\r\n\t\t\tprintf(\"Kill poly!\\n\");\r\n\t\t\t#endif\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\t\t\r\n\t\t// Check the steepness\r\n\t\tMth::Vector normal=feeler.GetNormal();\r\n\t\t// .087=max steepness of 85 degrees\r\n\t\tif (normal[Y] < 0.087f/*sinf(Mth::DegToRad(90.0f-Script::GetFloat(CRCD(0x87b926b4,\"MaxSteepness\"))))*/)\r\n\t\t{\r\n\t\t\t// The ground is too steep!\r\n\t\t\t// Need this check otherwise the skater can be placed halfway down the almost vertical\r\n\t\t\t// riverbank in NJ\r\n\t\t\t#ifdef DEBUG_COLLISION\r\n\t\t\tprintf(\"Too steep!\\n\");\r\n\t\t\t#endif\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\r\n\t\t#ifdef DEBUG_COLLISION\r\n\t\t//printf(\"Found y=%f normal[Y]=%f\\n\",feeler.GetPoint()[Y],normal[Y]);\r\n\t\t#endif\r\n\t\t\r\n\t\tMth::Vector point=feeler.GetPoint();\r\n\t\t*p_y=point[Y];\r\n\r\n\t\t// But, before returning true, check whether there are any kill polys between the start and the\r\n\t\t// collision point.\r\n\t\tif (s_goes_through_kill_poly(start, point))\r\n\t\t{\r\n\t\t\t#ifdef DEBUG_COLLISION\r\n\t\t\tprintf(\"Kill poly above found collision!\\n\");\r\n\t\t\t#endif\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\t\t\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\t#ifdef DEBUG_COLLISION\r\n\tprintf(\"No collision\\n\");\r\n\t#endif\r\n\t\r\n\treturn false;\r\n}\r\n\r\nbool CEditorCameraComponent::find_collision_at_offset(Mth::Vector oldCursorPos, float upOffset)\r\n{\r\n\tMth::Vector start=m_cursor_pos;\r\n\tstart[Y]+=upOffset;\r\n\tMth::Vector end=m_cursor_pos;\r\n\tend[Y]+=Script::GetFloat(CRCD(0xf230d521,\"EditorCam_CursorCollisionDownOffset\"));\r\n\t\r\n\tbool new_position_is_ok=false;\r\n\t\r\n\tfloat y;\r\n\tif (find_y(start,end,&y))\r\n\t{\r\n\t\tnew_position_is_ok=true;\r\n\t}\r\n\t\r\n\tif (new_position_is_ok)\r\n\t{\r\n\t\tMth::Vector from = oldCursorPos;\r\n\t\tMth::Vector to = m_cursor_pos;\r\n\t\tto[Y]=y;\r\n\t\tto[Y]+=72.0f; // 6 feet above the ground\r\n\t\t// Make it really be horizontal to avoid steep collision check weirdness\r\n\t\tfrom[Y]=to[Y]; \r\n\t\t\r\n\t\tif (!m_simple_collision)\r\n\t\t{\r\n\t\t\t// Do a horizontal collision check to see if the cursor \r\n\t\t\t// is going to move through a kill poly\r\n\t\t\tif (s_goes_through_kill_poly(from, to))\r\n\t\t\t{\r\n\t\t\t\t#ifdef DEBUG_COLLISION\r\n\t\t\t\tprintf(\"Goes through kill poly\\n\");\r\n\t\t\t\t#endif\r\n\t\t\t\tnew_position_is_ok=false;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif (!m_allow_movement_through_walls)\r\n\t\t{\r\n\t\t\t// Also don't allow moving through walls\r\n\t\t\tCFeeler feeler;\r\n\t\t\tfeeler.SetIgnore(mFD_NON_COLLIDABLE, 0);\r\n\t\t\tfeeler.SetStart(from);\r\n\t\t\tfeeler.SetEnd(to);\r\n\t\t\tif (feeler.GetCollision())\r\n\t\t\t{\r\n\t\t\t\t#ifdef DEBUG_COLLISION\r\n\t\t\t\tprintf(\"oof\\n\");\r\n\t\t\t\t#endif\r\n\t\t\t\tnew_position_is_ok=false;\r\n\t\t\t}\r\n\t\t}\t\r\n\t}\r\n\r\n\tif (new_position_is_ok)\r\n\t{\r\n\t\tm_cursor_pos[Y]=y;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\t\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CEditorCameraComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CEditorCameraComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCEditorCameraComponent::CEditorCameraComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_EDITORCAMERA );\r\n\t\r\n\tm_camera_focus_pos.Set();\r\n\tm_cam_pos.Set();\r\n\tm_cursor_pos.Set();\r\n\tm_cursor_u.Set();\r\n\tm_cursor_v.Set();\r\n\t\r\n\tm_radius=0.0f;\r\n\tm_radius_min=0.0f;\r\n\tm_radius_max=0.0f;\r\n\t\r\n\tm_angle=0.0f;\r\n\tm_tilt_angle=0.0f;\r\n\tm_tilt_angle_min=0.0f;\r\n\tm_tilt_angle_max=0.0f;\r\n\t\r\n\tm_cursor_height=0.0f;\r\n\tm_min_height=0.0f;\r\n\t\r\n\tmp_shadow=NULL;\r\n\tmp_input_component=NULL;\r\n\t\r\n\tm_simple_collision=false;\r\n\tm_allow_movement_through_walls=false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCEditorCameraComponent::~CEditorCameraComponent()\r\n{\r\n\tdelete_shadow();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CEditorCameraComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// ** Add code to parse the structure, and initialize the component\r\n\r\n\tm_min_height=0.0f;\r\n\tpParams->GetFloat(CRCD(0x9cdf40cd,\"min_height\"),&m_min_height);\r\n\t\r\n\tm_radius_min=100.0f;\r\n\tpParams->GetFloat(CRCD(0x52eecb98,\"min_radius\"),&m_radius_min);\r\n\t\r\n\tm_radius_max=2000.0f;\r\n\tpParams->GetFloat(CRCD(0x53e2512c,\"max_radius\"),&m_radius_max);\r\n\t\r\n\tm_simple_collision=pParams->ContainsFlag(CRCD(0xa0d7fbab,\"SimpleCollision\"));\r\n\tm_allow_movement_through_walls=pParams->ContainsFlag(CRCD(0xf5680def,\"AllowMovementThroughWalls\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CEditorCameraComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calline InitFromStructure()\r\n\t// but if that does not handle it, then will need to write a specific \r\n\t// function here. \r\n\t// The user might only want to update a single field in the structure\r\n\t// and we don't want to be asserting becasue everything is missing \r\n\t\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\nvoid CEditorCameraComponent::Hide( bool shouldHide )\r\n{\r\n\tif (shouldHide)\r\n\t{\r\n\t\tdelete_shadow();\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tcreate_shadow();\r\n\t}\r\n}\r\n\r\nvoid CEditorCameraComponent::GetCursorOrientation(Mth::Vector *p_u, Mth::Vector *p_v)\r\n{\r\n\t*p_u=m_cursor_u;\r\n\t*p_v=m_cursor_v;\r\n}\r\n\r\nvoid CEditorCameraComponent::create_shadow()\r\n{\r\n\tif (!mp_shadow)\r\n\t{\r\n\t\tmp_shadow = new Gfx::CSimpleShadow;\r\n\t\tmp_shadow->SetScale( SHADOW_SCALE );\r\n\t\tmp_shadow->SetModel( \"Ped_Shadow\" );\r\n\t}\t\r\n}\r\n\r\nvoid CEditorCameraComponent::delete_shadow()\r\n{\r\n\tif (mp_shadow)\r\n\t{\r\n\t\tdelete mp_shadow;\r\n\t\tmp_shadow=NULL;\r\n\t}\t\r\n}\r\n\r\nvoid CEditorCameraComponent::update_shadow()\r\n{\r\n\tMth::Vector cursor_pos=m_cursor_pos;\t\t\r\n\tcursor_pos[Y]+=m_cursor_height;\r\n\r\n\tCFeeler feeler;\r\n\tfeeler.SetStart(cursor_pos);\r\n\tfeeler.SetEnd(cursor_pos + Mth::Vector(0.0f,SHADOW_COLLISION_CHECK_DISTANCE,0.0f,0.0f));\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tcreate_shadow();\r\n\t\t\r\n\t\tMth::Matrix mat;\r\n\t\tmat.Ident();\r\n\r\n\t\tMth::Vector shadow_pos=feeler.GetPoint();\r\n\t\tMth::Vector shadow_normal=feeler.GetNormal();\r\n\t\tmp_shadow->UpdatePosition(shadow_pos,\r\n\t\t\t\t\t\t\t\t\t\t mat,\r\n\t\t\t\t\t\t\t\t\t\t shadow_normal);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tdelete_shadow();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CEditorCameraComponent::Finalize()\r\n{\r\n\t// Get the pointers to the other required components.\r\n\tDbg_MsgAssert(mp_input_component==NULL,(\"mp_input_component not NULL ?\"));\r\n\tmp_input_component = GetInputComponentFromObject(GetObject());\r\n\tDbg_MsgAssert(mp_input_component,(\"CEditorCameraComponent requires parent object to have an input component!\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CEditorCameraComponent::Update()\r\n{\r\n\tDbg_MsgAssert(mp_input_component,(\"NULL mp_input_component\"));\r\n\t\r\n\t// TODO: When in park editor, use different values here, cos they'll need to be\r\n\t// tweaked according to the shell geometry.\r\n\tm_tilt_angle_min=Script::GetFloat(CRCD(0x7d16d113,\"EditorCam_TiltMin\"));\r\n\tm_tilt_angle_max=Script::GetFloat(CRCD(0x411bee4a,\"EditorCam_TiltMax\"));\r\n\t\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\r\n\t\r\n\t// Update m_angle\r\n\tfloat angle_vel=Script::GetFloat(CRCD(0x8242d878,\"EditorCam_TurnSpeed\"))*control_pad.m_scaled_rightX;\r\n\tm_angle+=angle_vel;\r\n\twhile (m_angle > 2*3.141592654f)\r\n\t{\r\n\t\tm_angle -= 2*3.141592654f;\r\n\t}\t\r\n\twhile (m_angle < 0.0f)\r\n\t{\r\n\t\tm_angle += 2*3.141592654f;\r\n\t}\t\r\n\t\r\n\t// Update m_tilt_angle\r\n\tangle_vel=-Script::GetFloat(CRCD(0x3cfa3a72,\"EditorCam_TiltSpeed\"))*control_pad.m_scaled_rightY;\r\n\tm_tilt_angle+=angle_vel;\r\n\tif (m_tilt_angle > m_tilt_angle_max)\r\n\t{\r\n\t\tm_tilt_angle = m_tilt_angle_max;\r\n\t}\t\r\n\tif (m_tilt_angle < m_tilt_angle_min)\r\n\t{\r\n\t\tm_tilt_angle = m_tilt_angle_min;\r\n\t}\t\r\n\t\r\n\t// Update m_radius\r\n\tbool zoom_in_button_pressed=false;\r\n\tbool zoom_out_button_pressed=false;\r\n\tbool raise_pressed=false;\r\n\tbool lower_pressed=false;\r\n\tswitch (Config::GetHardware())\r\n\t{\r\n\t\tcase Config::HARDWARE_XBOX:\r\n\t\t{\r\n\t\t\tuint32 input_mask = mp_input_component->GetInputMask();\r\n\t\t\tif (input_mask & Inp::Data::mA_BLACK)\r\n\t\t\t{\r\n\t\t\t\tzoom_out_button_pressed=true;\r\n\t\t\t}\t\r\n\t\t\tif (input_mask & Inp::Data::mA_WHITE)\r\n\t\t\t{\r\n\t\t\t\tzoom_in_button_pressed=true;\r\n\t\t\t}\t\r\n\t\t\t// Note: See p_siodev.cpp for the low level code that does the weird XBox buttons mappings\r\n\t\t\tif (Ed::CParkEditor::Instance()->EditingCustomPark())\r\n\t\t\t{\r\n\t\t\t\t// When editing a park, XBox L gives L2, XBox R gives L1\r\n\t\t\t\t// We want XBox L to lower, XBox R to raise\r\n\t\t\t\tif (input_mask & Inp::Data::mA_L1)\r\n\t\t\t\t{\r\n\t\t\t\t\traise_pressed=true;\r\n\t\t\t\t}\t\r\n\t\t\t\tif (input_mask & Inp::Data::mA_L2)\r\n\t\t\t\t{\r\n\t\t\t\t\tlower_pressed=true;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// When not editing a park, XBox L gives L1, XBox R gives R1\r\n\t\t\t\t// We want XBox L to lower, XBox R to raise\r\n\t\t\t\tif (input_mask & Inp::Data::mA_R1)\r\n\t\t\t\t{\r\n\t\t\t\t\traise_pressed=true;\r\n\t\t\t\t}\t\r\n\t\t\t\tif (input_mask & Inp::Data::mA_L1)\r\n\t\t\t\t{\r\n\t\t\t\t\tlower_pressed=true;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase Config::HARDWARE_NGC:\r\n\t\t{\r\n\t\t\tuint32 input_mask = mp_input_component->GetInputMask();\r\n\t\t\tif (input_mask & Inp::Data::mA_Z)\r\n\t\t\t{\r\n\t\t\t\tif (input_mask & Inp::Data::mA_R1)\r\n\t\t\t\t{\r\n\t\t\t\t\tzoom_out_button_pressed=true;\r\n\t\t\t\t}\r\n\t\t\t\tif (input_mask & Inp::Data::mA_L1)\r\n\t\t\t\t{\r\n\t\t\t\t\tzoom_in_button_pressed=true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (input_mask & Inp::Data::mA_R1)\r\n\t\t\t\t{\r\n\t\t\t\t\tlower_pressed=true;\r\n\t\t\t\t}\r\n\t\t\t\tif (input_mask & Inp::Data::mA_L1)\r\n\t\t\t\t{\r\n\t\t\t\t\traise_pressed=true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\t\r\n\t\t{\r\n\t\t\tzoom_out_button_pressed=control_pad.m_R1.GetPressed();\r\n\t\t\tzoom_in_button_pressed=control_pad.m_R2.GetPressed();\r\n\t\t\traise_pressed=control_pad.m_L1.GetPressed();\r\n\t\t\tlower_pressed=control_pad.m_L2.GetPressed();\r\n\t\t\tbreak;\t\t\r\n\t\t}\t\r\n\t}\r\n\t\r\n\tfloat radius_vel=Script::GetFloat(CRCD(0x4e58f829,\"EditorCam_InOutSpeed\"));\r\n\tif (zoom_out_button_pressed)\r\n\t{\r\n\t}\t\r\n\telse if (zoom_in_button_pressed)\r\n\t{\r\n\t\tradius_vel=-radius_vel;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tradius_vel=0.0f;\r\n\t}\r\n\t\t\r\n\t// Make the speed proportional to the current radius so that the camera can be zoomed\r\n\t// out to the max nice and quick.\r\n\tradius_vel*=m_radius;\r\n\t\r\n\tm_radius+=radius_vel;\r\n\tif (m_radius < m_radius_min)\r\n\t{\r\n\t\tm_radius = m_radius_min;\r\n\t}\t\r\n\tif (m_radius > m_radius_max)\r\n\t{\r\n\t\tm_radius = m_radius_max;\r\n\t}\t\r\n\tfloat zoom_factor=(m_radius-m_radius_min)/(m_radius_max-m_radius_min);\r\n\t// zoom_factor is between 0 and 1 and indicates how far out the camera is zoomed.\r\n\t// 0 = closest to cursor, 1 = furthest away.\r\n\r\n\r\n\t// Update the height\r\n\tfloat height_vel_min=Script::GetFloat(CRCD(0x604961f4,\"EditorCam_UpDownSpeedMin\"));\r\n\tfloat height_vel_max=Script::GetFloat(CRCD(0x5c445ead,\"EditorCam_UpDownSpeedMax\"));\r\n\tfloat height_vel=height_vel_min + zoom_factor * (height_vel_max-height_vel_min);\r\n\t\r\n\t// If very close in allow very fine movements, needed for rail placement in rail editor.\r\n\t// TODO: Fix this so that the change in speed is not so sudden, make it linear like above.\r\n\tif (m_radius < 100)\r\n\t{\r\n\t\theight_vel=0.2f;\r\n\t}\r\n\t\r\n\tif (raise_pressed)\r\n\t{\r\n\t}\t\r\n\telse if (lower_pressed)\r\n\t{\r\n\t\theight_vel=-height_vel;\r\n\t}\r\n\telse\r\n\t{\r\n\t\theight_vel=0.0f;\r\n\t}\t\r\n\t\r\n\tm_cursor_height+=height_vel;\r\n\tfloat max_height=Script::GetFloat(CRCD(0x61d56fa0,\"EditorCam_MaxHeight\"));\r\n\tif (m_cursor_height > max_height)\r\n\t{\r\n\t\tm_cursor_height=max_height;\r\n\t}\r\n\r\n\t// Switch off collision on any created-rail sectors whilst doing collision checks.\r\n\t// This is because the rail sectors have a vertical collidable poly, which occasionally does cause\r\n\t// collisions, making the cursor ping up into the air. Must be some sort of floating point innaccuracy\r\n\t// (or too much accuracy), probably because the collision check vector is straight down the vertical poly.\r\n\tMdl::Skate * p_skate_mod =  Mdl::Skate::Instance();\r\n\tif (p_skate_mod->m_cur_level == CRCD(0xe8b4b836,\"load_sk5ed\"))\r\n\t{\r\n\t\tObj::GetRailEditor()->SetSectorActiveStatus(false);\r\n\t}\t\r\n\r\n\t// Make sure that the cursor cannot be raised through a collidable poly, otherwise it\r\n\t// can be raised through the stadium roof in slam city jam (TT3142)\r\n\tCFeeler feeler;\r\n\tfeeler.SetStart(m_cursor_pos);\r\n\tfeeler.SetEnd(m_cursor_pos + Mth::Vector(0.0f, m_cursor_height+10.0f, 0.0f));\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tm_cursor_height=feeler.GetPoint()[Y]-m_cursor_pos[Y]-10.0f;\r\n\t}\r\n\t\r\n\t// This allows the height to be less than m_min_height, but as soon as it goes\r\n\t// over m_min_height it won't be able to go below it again.\r\n\t// This is for the rail editor, where the min height needs to be limited whilst\r\n\t// still allowing snapping to a vertex.\r\n\tif (height_vel < 0.0f && m_cursor_height-height_vel+0.01 >= m_min_height)\r\n\t{\r\n\t\tif (m_cursor_height < m_min_height)\r\n\t\t{\r\n\t\t\tm_cursor_height=m_min_height;\r\n\t\t}\r\n\t}\t\r\n\tif (m_cursor_height < 0.0f)\r\n\t{\r\n\t\tm_cursor_height=0.0f;\r\n\t}\r\n\t\t\r\n\t// Update m_cursor_pos ...\r\n\r\n\t// First move it horizontally according to the left analogue stick\r\n\tm_cursor_u.Set(cosf(m_angle),0.0f,-sinf(m_angle));\r\n\tm_cursor_v.Set(sinf(m_angle),0.0f,cosf(m_angle));\r\n\t\r\n\tfloat speed_min=Script::GetFloat(CRCD(0x83bde786,\"EditorCam_MoveSpeedMin\"));\r\n\tfloat speed_max=Script::GetFloat(CRCD(0xbfb0d8df,\"EditorCam_MoveSpeedMax\"));\r\n\t// Make the speed proportional to the zoom factor so that fine movements can be done\r\n\t// when zoomed in, whilst fast movements can be made when zoomed out.\r\n\tfloat speed = speed_min + zoom_factor * (speed_max-speed_min);\r\n\t\r\n\t// If very close in allow very fine movements, needed for rail placement in rail editor.\r\n\t// TODO: Fix this so that the change in speed is not so sudden, make it linear like above.\r\n\tif (m_radius < 100)\r\n\t{\r\n\t\tspeed=1.0f;\r\n\t}\r\n\t\t\r\n\tfloat horiz=control_pad.m_leftX / 128.0f;\r\n\tfloat vert=control_pad.m_leftY / 128.0f;\r\n\tif (fabs(horiz) < 0.01f)\r\n\t{\r\n\t\tif (control_pad.m_left.GetPressed())\r\n\t\t{\r\n\t\t\thoriz=-0.5f;\r\n\t\t}\t\r\n\t\tif (control_pad.m_right.GetPressed())\r\n\t\t{\r\n\t\t\thoriz=0.5f;\r\n\t\t}\t\r\n\t}\r\n\t\t\r\n\tif (fabs(vert) < 0.01f)\r\n\t{\r\n\t\tif (control_pad.m_up.GetPressed())\r\n\t\t{\r\n\t\t\tvert=-0.5f;\r\n\t\t}\t\r\n\t\tif (control_pad.m_down.GetPressed())\r\n\t\t{\r\n\t\t\tvert=0.5f;\r\n\t\t}\t\r\n\t}\t\r\n\t\t\r\n\tMth::Vector vel = m_cursor_u * horiz*speed+\r\n\t\t\t\t\t  m_cursor_v * vert*speed;\r\n\tMth::Vector old_pos=m_cursor_pos;\t\t\t\t\t  \r\n\tm_cursor_pos+=vel;\r\n\r\n\t// Now do a collision check to find the y.\t\r\n\tif (!find_collision_at_offset(old_pos, Script::GetFloat(CRCD(0xc7210318,\"EditorCam_CursorCollisionFirstUpOffset\"))))\r\n\t{\r\n\t\t// Do an upwards collision check to check for a ceiling above the skater, and do not\r\n\t\t// do the check for higher collision if there is a ceiling. This is to fix a bug where in Slam City\r\n\t\t// the goal cursor would pop up into the stands if hitting the teleport poly in the escalator D corridor.\r\n\t\tCFeeler feeler;\r\n\t\tfeeler.SetStart(old_pos);\r\n\t\tMth::Vector high=old_pos;\r\n\t\thigh[Y]+=120.0f;\r\n\t\tfeeler.SetEnd(high);\r\n\t\tif (feeler.GetCollision())\r\n\t\t{\r\n\t\t\t// Undo the movement so that the cursor does not move.\r\n\t\t\tm_cursor_pos=old_pos;\r\n\t\t}\r\n\t\telse if (!find_collision_at_offset(old_pos, Script::GetFloat(CRCD(0x56c2bff2,\"EditorCam_CursorCollisionSecondUpOffset\"))))\r\n\t\t{\r\n\t\t\t// Undo the movement so that the cursor does not move.\r\n\t\t\tm_cursor_pos=old_pos;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Did find higher collision, which is going to cause the cursor to pop to a high place, such\r\n\t\t\t// as the roof of a building. In this case, zero the cursor height, because it seems weird to\r\n\t\t\t// have it maintain it's hover height in that case. (TT10272)\r\n\t\t\tm_cursor_height=m_min_height;\r\n\t\t}\t\r\n\t}\r\n\t\t\r\n\tif (p_skate_mod->m_cur_level == CRCD(0xe8b4b836,\"load_sk5ed\"))\r\n\t{\r\n\t\tObj::GetRailEditor()->SetSectorActiveStatus(true);\r\n\t}\t\r\n\r\n\t\r\n\t// Calculate the camera position, which equals the cursor position but has a lag\r\n\t// applied so that as the cursor follows the contours of the ground it does not make\r\n\t// the camera glitch.\r\n\tm_camera_focus_pos[X]=m_cursor_pos[X];\r\n\tm_camera_focus_pos[Z]=m_cursor_pos[Z];\r\n\tm_camera_focus_pos[Y]+=(m_cursor_pos[Y]+m_cursor_height-m_camera_focus_pos[Y])*Script::GetFloat(CRCD(0x725ad02c,\"EditorCam_YCatchUpFactor\"));\r\n\t\r\n\tMth::Vector tilted_v;\r\n\ttilted_v[X]=m_cursor_v[X]*cosf(m_tilt_angle);\r\n\ttilted_v[Z]=m_cursor_v[Z]*cosf(m_tilt_angle);\r\n\ttilted_v[Y]=sinf(m_tilt_angle);\r\n\r\n\tMth::Matrix mat;\r\n\tmat[Z]=tilted_v;\r\n\tmat[X]=m_cursor_u;\r\n\tmat[Y]=Mth::CrossProduct(tilted_v,m_cursor_u);\r\n\tmat[X][W]=0.0f;\r\n\tmat[Y][W]=0.0f;\r\n\tmat[Z][W]=0.0f;\r\n\tmat[W].Set();\r\n\tGetObject()->SetMatrix(mat);\r\n\t\r\n\tMth::Vector start=m_camera_focus_pos;\r\n\t/*\r\n\tMth::Vector end;\r\n\tfloat radius=m_radius;\r\n\twhile (true)\r\n\t{\r\n\t\tend=start+tilted_v*radius;\r\n\r\n\t\tif (radius > Script::GetFloat(CRCD(0xf612c474,\"EditorCam_CursorCollisionEnableDistMax\")))\r\n\t\t{\r\n\t\t\tprintf(\"Not checksing for collision\\n\");\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tMth::Vector p_rays[4];\r\n\t\tp_rays[0]=start;\r\n\t\tp_rays[1]=start-120*u+Mth::Vector(0.0f,70.0f,0.0f,0.0f);\r\n\t\tp_rays[2]=start+Mth::Vector(0.0f,70.0f,0.0f,0.0f);\r\n\t\tp_rays[3]=start+120*u+Mth::Vector(0.0f,70.0f,0.0f,0.0f);\r\n\t\tif (cursor_occluded(p_rays,4,end))\r\n\t\t{\r\n\t\t\tradius=radius*0.9f; // TODO: Hmmm, should find out the exact distance ...\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t}\r\n\r\n\tm_cam_pos+=(end-m_cam_pos)*Script::GetFloat(CRCD(0xf151a64,\"EditorCam_CameraCatchUpFactor\"));\r\n\t*/\r\n\t// TODO: Fix the camera collision above, then comment out this line for it to have effect.\r\n\tm_cam_pos=start + tilted_v*m_radius;\r\n\r\n\tm_cam_pos[W]=1.0f;\r\n\tGetObject()->SetPos(m_cam_pos);\r\n\t\r\n\t\r\n\tupdate_shadow();\r\n}\r\n\r\nbool CEditorCameraComponent::cursor_occluded(Mth::Vector *p_ray_starts, int numRays, Mth::Vector end)\r\n{\r\n\tCFeeler feeler;\r\n\tfor (int i=0; i<numRays; ++i)\r\n\t{\r\n\t\tfeeler.SetStart(p_ray_starts[i]);\r\n\t\tfeeler.SetEnd(end);\r\n\t\tif (feeler.GetMovableCollision())\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\t\r\n\t\tif (!feeler.GetCollision())\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CEditorCameraComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tcase 0xf362bbbf: // EditorCam_Initialise\r\n\t\t\tpParams->GetVector(CRCD(0xb9d31b0a,\"position\"),&m_cursor_pos);\r\n\t\t\tm_camera_focus_pos=m_cursor_pos;\r\n\t\t\tm_radius=700.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0xc48391a5,\"radius\"),&m_radius);\r\n\t\t\tm_tilt_angle=0.6f;\r\n\t\t\tpParams->GetFloat(CRCD(0xe3c07609,\"tilt\"),&m_tilt_angle);\r\n\t\t\tm_cursor_height=0.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0xb8d629ca,\"cursor_height\"),&m_cursor_height);\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0x69cb3ae1: // EditorCam_SetCursorPos\r\n\t\t{\r\n\t\t\tMth::Vector pos;\r\n\t\t\tpParams->GetVector(CRCD(0xb9d31b0a,\"position\"),&pos,Script::ASSERT);\r\n\t\t\tm_cursor_pos=pos;\r\n\t\t\tm_cursor_height=0.0f;\r\n\t\t\t\r\n\t\t\t// Call update to do the ground collision check.\r\n\t\t\tUpdate();\r\n\t\t\t// That might have changed m_cursor_pos[Y], so adjust the height so that the cursor does \r\n\t\t\t// appear at the required position.\r\n\t\t\tm_cursor_height=pos[Y]-m_cursor_pos[Y];\r\n\t\t\t// Note: If the above call to Update() followed by adjusting the height were not done, then it would not\r\n\t\t\t// be possible to snap to rail vertices, because rails are uncollidable, so on the next frame the cursor\r\n\t\t\t// would fall through the rail back to the ground.\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CEditorCameraComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CEditorCameraComponent::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddInteger(\"m_active\",m_active);\r\n\tp_info->AddVector(\"m_camera_focus_pos\",m_camera_focus_pos.GetX(),m_camera_focus_pos.GetY(),m_camera_focus_pos.GetZ());\r\n\tp_info->AddVector(\"m_cursor_pos\",m_cursor_pos.GetX(),m_cursor_pos.GetY(),m_cursor_pos.GetZ());\r\n\tp_info->AddFloat(\"m_cursor_height\",m_cursor_height);\r\n\tp_info->AddFloat(\"m_radius\",m_radius);\r\n\tp_info->AddFloat(\"m_radius_min\",m_radius_min);\r\n\tp_info->AddFloat(\"m_radius_max\",m_radius_max);\r\n\tp_info->AddFloat(\"m_angle\",m_angle);\r\n\tp_info->AddFloat(\"m_tilt_angle\",m_tilt_angle);\r\n\tp_info->AddFloat(\"m_tilt_angle_min\",m_tilt_angle_min);\r\n\tp_info->AddFloat(\"m_tilt_angle_max\",m_tilt_angle_max);\r\n\r\n// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/EditorCameraComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components/\r\n//* FILENAME:       EditorCameraComponent.h\r\n//* OWNER:          KSH\r\n//* CREATION DATE:  26 Mar 2003\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_EDITORCAMERACOMPONENT_H__\r\n#define __COMPONENTS_EDITORCAMERACOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n// Replace this with the CRCD of the component you are adding\r\n#define\t\tCRC_EDITORCAMERA CRCD(0xac8946e2,\"EditorCamera\")\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or \r\n//  given an object\t\t\t\t \r\n#define\t\tGetEditorCameraComponent() ((Obj::CEditorCameraComponent*)GetComponent(CRC_EDITORCAMERA))\r\n#define\t\tGetEditorCameraComponentFromObject(pObj) ((Obj::CEditorCameraComponent*)(pObj)->GetComponent(CRC_EDITORCAMERA))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Nx\r\n{\r\n\tclass CModel;\r\n}\r\n\r\nnamespace Gfx\r\n{\r\n\tclass CSimpleShadow;\r\n}\r\n\t\r\nnamespace Obj\r\n{\r\nclass CInputComponent;\r\n\r\nclass CEditorCameraComponent : public CBaseComponent\r\n{\r\n\tbool m_active;\r\n\t\r\n\t// The point at which the camera looks. This basically equals m_cursor_pos\r\n\t// except it smoothly catches up with m_cursor_pos so as to smooth out glitches.\r\n\tMth::Vector m_camera_focus_pos;\r\n\tMth::Vector m_cam_pos;\r\n\t\r\n\t// The position of the Goal model that get moves around by the controls.\r\n\tMth::Vector m_cursor_pos;\r\n\t\r\n\t// The orthogonal horizontal vectors that define the cursor's orientation\t\t\t\t\t \r\n\tMth::Vector m_cursor_u;\r\n\tMth::Vector m_cursor_v;\r\n\t\r\n\tfloat m_radius;\r\n\tfloat m_radius_min;\r\n\tfloat m_radius_max;\r\n\t\r\n\tfloat m_angle;\r\n\tfloat m_tilt_angle;\r\n\tfloat m_tilt_angle_min;\r\n\tfloat m_tilt_angle_max;\r\n\r\n\tfloat m_cursor_height;\r\n\tfloat m_min_height;\r\n\r\n\tbool m_simple_collision;\r\n\tbool m_allow_movement_through_walls;\r\n\t\t\r\n\tCInputComponent *mp_input_component;\r\n\t\r\n\tGfx::CSimpleShadow *mp_shadow;\r\n\tvoid create_shadow();\r\n\tvoid delete_shadow();\r\n\tvoid update_shadow();\r\n\t#define SHADOW_COLLISION_CHECK_DISTANCE -10000.0f\r\n\t#define SHADOW_SCALE 1.2f\r\n\t\r\n\tbool cursor_occluded(Mth::Vector *p_ray_starts, int numRays, Mth::Vector end);\r\n\r\n\tbool find_y(Mth::Vector start, Mth::Vector end, float *p_y);\r\n\tbool find_collision_at_offset(Mth::Vector oldCursorPos, float upOffset);\r\n\t\r\n\r\npublic:\r\n    CEditorCameraComponent();\r\n    virtual ~CEditorCameraComponent();\r\n\r\npublic:\r\n\tMth::Vector&\t\t\t\t\tGetCursorPos() {return m_cursor_pos;}\r\n\tvoid\t\t\t\t\t\t\tSetCursorPos(const Mth::Vector& pos) {m_cursor_pos=pos;}\r\n\tvoid\t\t\t\t\t\t\tGetCursorOrientation(Mth::Vector *p_u, Mth::Vector *p_v);\r\n\tfloat\t\t\t\t\t\t\tGetCursorOrientation() {return m_angle;}\r\n\tvoid\t\t\t\t\t\t\tSetCursorOrientation(float angle) {m_angle=angle;}\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetCursorHeight(float height) {m_cursor_height=height;}\r\n\tfloat\t\t\t\t\t\t\tGetCursorHeight() {return m_cursor_height;}\r\n\tvoid\t\t\t\t\t\t\tSetCursorMinHeight(float minHeight) {m_min_height=minHeight;}\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetSimpleCollision(bool whatever) {m_simple_collision=whatever;}\r\n\t\r\n\tvirtual\tvoid \t\t\t\t\tFinalize();\r\n\tvirtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tHide( bool shouldHide );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n};\r\n\r\n}\r\n\r\n#endif // __COMPONENTS_EDITORCAMERACOMPONENT_H__\r\n"
  },
  {
    "path": "Code/Sk/Components/GoalEditorComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       GoalEditorComponent.cpp\r\n//* OWNER:          Kendall Harrison\r\n//* CREATION DATE:  3/21/2003\r\n//****************************************************************************\r\n\r\n#include <sk/components/GoalEditorComponent.h>\r\n#include <sk/components/EditorCameraComponent.h>\r\n#include <sk/parkeditor2/parked.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <gel/objman.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/nxmodel.h>\r\n#include <sk/engine/feeler.h>\r\n#include <gel/objtrack.h>\r\n\r\n//#define SIZE_TEST\r\n\r\nnamespace Obj\r\n{\r\n\r\nstatic uint32 s_convert_level(uint32 level)\r\n{\r\n\tif (level==CRCD(0xb664035d,\"Load_Sk5Ed_gameplay\"))\r\n\t{\r\n\t\t// Map Load_Sk5Ed_gameplay back to Load_Sk5Ed \r\n\t\tlevel=CRCD(0xe8b4b836,\"Load_Sk5Ed\");\r\n\t}\r\n\t\r\n\treturn level;\r\n}\r\n\r\n// Often in the scripts the value returned by GetCurrentLevel is passed on to commands like GetEditedGoalsInfo\r\n// However sometimes the level might be returned as Load_Sk5Ed_gameplay rather than Load_Sk5Ed, so\r\n// this will map it back to Load_Sk5Ed\r\nstatic uint32 s_get_level_checksum(Script::CStruct *p_params)\r\n{\r\n\tuint32 level=0;\r\n\tp_params->GetChecksum(CRCD(0x651533ec,\"level\"),&level);\r\n\t\r\n\tlevel=s_convert_level(level);\r\n\t\t\t\r\n\treturn level;\r\n}\r\n\r\nstatic uint32 s_get_current_level()\r\n{\r\n\tMdl::Skate *p_skate_module = Mdl::Skate::Instance();\r\n\tuint32 current_level=p_skate_module->m_cur_level;\r\n\t\r\n\tcurrent_level=s_convert_level(current_level);\t\t\t\t\t\t \r\n\t\r\n\treturn current_level;\r\n}\t\r\n\t\r\nstatic const char *s_generate_letter_model_filename(uint32 goalType, int letterIndex)\r\n{\r\n\tconst char *p_model_file_name=NULL;\r\n\tswitch (goalType)\r\n\t{\r\n\t\tcase 0x54166acd: // Skate\r\n\t\t\tswitch (letterIndex)\r\n\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tp_model_file_name=\"gameobjects\\\\skate\\\\letter_s\\\\letter_s.mdl\";\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tp_model_file_name=\"gameobjects\\\\skate\\\\letter_k\\\\letter_k.mdl\";\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tp_model_file_name=\"gameobjects\\\\skate\\\\letter_a\\\\letter_a.mdl\";\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\tp_model_file_name=\"gameobjects\\\\skate\\\\letter_t\\\\letter_t.mdl\";\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 4:\r\n\t\t\t\t\tp_model_file_name=\"gameobjects\\\\skate\\\\letter_e\\\\letter_e.mdl\";\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\t\t\r\n\t\t\tbreak;\r\n\t\tcase 0x4ec3cfb5: // Combo\r\n\t\t\tswitch (letterIndex)\r\n\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tp_model_file_name=\"gameobjects\\\\combo\\\\goal_combo_c\\\\goal_combo_c.mdl\";\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tp_model_file_name=\"gameobjects\\\\combo\\\\goal_combo_o\\\\goal_combo_o.mdl\";\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tp_model_file_name=\"gameobjects\\\\combo\\\\goal_combo_m\\\\goal_combo_m.mdl\";\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\tp_model_file_name=\"gameobjects\\\\combo\\\\goal_combo_b\\\\goal_combo_b.mdl\";\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 4:\r\n\t\t\t\t\tp_model_file_name=\"gameobjects\\\\combo\\\\goal_combo_o\\\\goal_combo_o.mdl\";\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\t\t\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\t\t\t\r\n\treturn p_model_file_name;\r\n}\r\n\r\nstatic uint32 s_generate_letter_node_type_checksum(uint32 goalType, int letterIndex)\r\n{\r\n\tuint32 checksum=0;\r\n\tswitch (goalType)\r\n\t{\r\n\t\tcase 0x54166acd: // Skate\r\n\t\t\tswitch (letterIndex)\r\n\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tchecksum=CRCD(0xf75425ea,\"Letter_S\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tchecksum=CRCD(0xe438bdbc,\"Letter_K\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tchecksum=CRCD(0x4ed54a2,\"Letter_A\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\tchecksum=CRCD(0x6930b049,\"Letter_T\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 4:\r\n\t\t\t\t\tchecksum=CRCD(0x38090bb,\"Letter_E\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\t\t\r\n\t\t\tbreak;\r\n\t\tcase 0x4ec3cfb5: // Combo\r\n\t\t\tswitch (letterIndex)\r\n\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tchecksum=CRCD(0x7bf1ba66,\"Combo_C\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tchecksum=CRCD(0x7247f64d,\"Combo_O\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tchecksum=CRCD(0x9c499761,\"Combo_M\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\tchecksum=CRCD(0xcf68af0,\"Combo_B\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 4:\r\n\t\t\t\t\tchecksum=CRCD(0x7247f64d,\"Combo_O\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\t\t\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\t\t\t\r\n\treturn checksum;\r\n}\r\n\r\nstatic uint32 s_generate_node_name_checksum(int goalIndex, int positionIndex)\r\n{\r\n\tchar p_name[100];\r\n\tp_name[0]=0;\r\n\t\r\n\tswitch (positionIndex)\r\n\t{\r\n\t\tcase 0:\r\n\t\t\tsprintf(p_name,\"TRG_EditedGoal%d_Pro\",goalIndex);\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tsprintf(p_name,\"TRG_EditedGoal%d_Restart\",goalIndex);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tsprintf(p_name,\"TRG_EditedGoal%d_Letter_%d\",goalIndex,positionIndex-2);\r\n\t\t\tbreak;\t\r\n\t}\r\n\t\r\n\treturn Script::GenerateCRC(p_name);\r\n}\r\n\r\nstatic const Script::CStruct *s_get_default_goal_params(uint32 goalType)\r\n{\r\n\tScript::CStruct *p_default_params=NULL;\r\n\t\r\n\tswitch (goalType)\r\n\t{\r\n\t\tcase 0x54166acd: // Skate\r\n\t\t\tp_default_params=Script::GetStructure(CRCD(0x3328976a,\"Goal_SkateLetters_genericParams\"));\r\n\t\t\tbreak;\r\n\t\tcase 0x4ec3cfb5: // Combo\r\n\t\t\tp_default_params=Script::GetStructure(CRCD(0xb4f5801d,\"Goal_amateurCOMBOline_genericParams\"));\r\n\t\t\tbreak;\r\n\t\tcase 0x6fe44c6d: // HighScore\r\n\t\t\tp_default_params=Script::GetStructure(CRCD(0xef8f345f,\"Goal_HighScore_genericParams\"));\r\n\t\t\tbreak;\r\n\t\tcase 0xec414b76: // HighCombo\r\n\t\t\tp_default_params=Script::GetStructure(CRCD(0xb520a510,\"goal_highcombo_genericParams\"));\r\n\t\t\tbreak;\r\n\t\tcase 0x7fe2238a: // SkateTris\r\n\t\tcase 0x0fc6f698: // ComboSkateTris\r\n\t\tcase 0xea7ba666: // TrickTris\r\n\t\t\tp_default_params=Script::GetStructure(CRCD(0x675816b5,\"goal_tetris_genericParams\"));\r\n\t\t\tbreak;\r\n\t\tcase 0x61c5d092: // Gap\r\n\t\t\tp_default_params=Script::GetStructure(CRCD(0x5756a675,\"Goal_Gaps_genericParams\"));\t\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\t\t\r\n\treturn p_default_params;\r\n}\r\n\r\nstatic const Script::CStruct *s_get_extra_goal_params(uint32 goalType)\r\n{\r\n\tScript::CStruct *p_extra_params=NULL;\r\n\t\r\n\tswitch (goalType)\r\n\t{\r\n\t\tcase 0x54166acd: // Skate\r\n\t\t\tp_extra_params=Script::GetStructure(CRCD(0xe41e0e04,\"EditedGoal_ExtraParams_Skate\"));\r\n\t\t\tbreak;\r\n\t\tcase 0x4ec3cfb5: // Combo\r\n\t\t\tp_extra_params=Script::GetStructure(CRCD(0xfecbab7c,\"EditedGoal_ExtraParams_Combo\"));\r\n\t\t\tbreak;\r\n\t\tcase 0x6fe44c6d: // HighScore\r\n\t\t\tp_extra_params=Script::GetStructure(CRCD(0x28c7b799,\"EditedGoal_ExtraParams_HighScore\"));\r\n\t\t\tbreak;\r\n\t\tcase 0xec414b76: // HighCombo\r\n\t\t\tp_extra_params=Script::GetStructure(CRCD(0xab62b082,\"EditedGoal_ExtraParams_HighCombo\"));\r\n\t\t\tbreak;\r\n\t\tcase 0x7fe2238a: // SkateTris\r\n\t\t\tp_extra_params=Script::GetStructure(CRCD(0x38c1d87e,\"EditedGoal_ExtraParams_SkateTris\"));\r\n\t\t\tbreak;\r\n\t\tcase 0x0fc6f698: // ComboSkateTris\r\n\t\t\tp_extra_params=Script::GetStructure(CRCD(0x6626b0d8,\"EditedGoal_ExtraParams_ComboSkateTris\"));\r\n\t\t\tbreak;\r\n\t\tcase 0xea7ba666: // TrickTris\t\r\n\t\t\tp_extra_params=Script::GetStructure(CRCD(0xad585d92,\"EditedGoal_ExtraParams_TrickTris\"));\r\n\t\t\tbreak;\r\n\t\tcase 0x61c5d092: // Gap\r\n\t\t\tp_extra_params=Script::GetStructure(CRCD(0x9005703a,\"EditedGoal_ExtraParams_Gap\"));\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\treturn p_extra_params;\r\n}\r\n\t\t\t\r\nvoid InsertGoalEditorNodes()\r\n{\r\n\tScript::CArray *p_node_array=GetArray(CRCD(0xc472ecc5,\"NodeArray\"),Script::ASSERT);\r\n\t\r\n\tuint32 new_node_index=0;\r\n\tif (p_node_array->GetSize()==0)\r\n\t{\r\n\t\t// If it's empty, it'll need its type setting too.\r\n\t\tp_node_array->SetSizeAndType(MAX_POSITIONS_PER_GOAL*MAX_GOALS_PER_LEVEL,ESYMBOLTYPE_STRUCTURE);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tnew_node_index=p_node_array->GetSize();\r\n\t\tp_node_array->Resize(p_node_array->GetSize() + MAX_POSITIONS_PER_GOAL*MAX_GOALS_PER_LEVEL);\r\n\t}\t\r\n\t\r\n\tScript::CStruct *p_new_node=NULL;\r\n\tfor (int g=0; g<MAX_GOALS_PER_LEVEL; ++g)\r\n\t{\r\n\t\tp_new_node=new Script::CStruct;\r\n\t\tp_new_node->AppendStructure(Script::GetStructure(CRCD(0x8f0f67d7,\"EditedGoal_Pro_Node\"),Script::ASSERT));\r\n\t\tp_new_node->AddChecksum(CRCD(0xa1dc81f9,\"Name\"),s_generate_node_name_checksum(g,0));\r\n\t\tp_new_node->AddInteger(CRCD(0xe50d6573,\"NodeIndex\"),new_node_index);\r\n\t\tp_node_array->SetStructure(new_node_index++,p_new_node);\r\n\t\t\r\n\t\tp_new_node=new Script::CStruct;\r\n\t\tp_new_node->AppendStructure(Script::GetStructure(CRCD(0xc9119673,\"EditedGoal_Restart_Node\"),Script::ASSERT));\r\n\t\tp_new_node->AddChecksum(CRCD(0xa1dc81f9,\"Name\"),s_generate_node_name_checksum(g,1));\r\n\t\tp_new_node->AddInteger(CRCD(0xe50d6573,\"NodeIndex\"),new_node_index);\r\n\t\tp_node_array->SetStructure(new_node_index++,p_new_node);\r\n\t\t\r\n\t\tfor (int i=0; i<MAX_POSITIONS_PER_GOAL-2; ++i)\r\n\t\t{\r\n\t\t\tp_new_node=new Script::CStruct;\r\n\t\t\tp_new_node->AppendStructure(Script::GetStructure(CRCD(0x1aaf51ba,\"EditedGoal_Letter_Node\"),Script::ASSERT));\r\n\t\t\t\r\n\t\t\tp_new_node->AddChecksum(CRCD(0xa1dc81f9,\"Name\"),s_generate_node_name_checksum(g,i+2));\r\n\t\t\tp_new_node->AddInteger(CRCD(0xe50d6573,\"NodeIndex\"),new_node_index);\r\n\t\t\t\r\n\t\t\tp_node_array->SetStructure(new_node_index++,p_new_node);\r\n\t\t}\t\r\n\t}\t\r\n}\r\n\r\nCEditGoal::CEditGoal()\r\n{\r\n\tClear();\r\n}\r\n\r\nCEditGoal::~CEditGoal()\r\n{\r\n}\r\n\r\nvoid CEditGoal::Clear()\r\n{\r\n\tm_used=false;\r\n\tm_level_script=0;\r\n\tmp_goal_name[0]=0;\t\r\n\tmp_goal_description[0]=0;\r\n\tmp_win_message[0]=0;\r\n\tmp_ped_name[0]=0;\r\n\tm_goal_type=0;\r\n\t\r\n\tm_num_positions_set=0;\r\n\tm_num_positions_required=0;\r\n\tm_current_position_index=0;\r\n\tm_placed_last_position=false;\r\n\tm_has_won_goal=false;\r\n\t\t\r\n\tm_score=100;\r\n\tm_time_limit=120;\r\n\t\r\n\tm_acceleration_interval=5;\r\n\tm_acceleration_percent=0.1f;\r\n\tm_trick_time=3000;\r\n\tm_time_to_stop_adding_tricks=5;\r\n\tm_max_tricks=11;\r\n\tm_spin=360;\r\n\t\r\n\tm_single_combo=false;\r\n\tm_combo_size=2;\r\n\t\r\n\tm_tricktris_block_size=3;\r\n\tm_tricktris_total_to_win=8;\r\n\r\n\tm_num_combo_sets=0;\r\n\r\n\tm_control_type=CRCD(0x54166acd,\"skate\");\r\n\t\r\n\tm_num_gaps=0;\r\n\tmp_trick_name[0]=0;\r\n\t\t\t\t\r\n\tfor (int i=0; i<MAX_POSITIONS_PER_GOAL; ++i)\r\n\t{\r\n\t\tmp_item_positions[i].mType=CGoalPos::NONE;\r\n\t\tmp_item_positions[i].mHeight=0.0f;\r\n\t}\r\n\tm_level_goal_index=0;\r\n}\r\n\r\nconst char *CEditGoal::GetIDString()\r\n{\r\n\tstatic char sp_id_string[20];\r\n\tsprintf(sp_id_string,\"CreatedGoal%d\",m_level_goal_index);\r\n\treturn sp_id_string;\r\n}\r\n\r\nuint32 CEditGoal::GetId()\r\n{\r\n\treturn Script::GenerateCRC(GetIDString());\r\n}\r\n\r\nvoid CEditGoal::refresh_position_using_collision_check(uint positionIndex)\r\n{\r\n\tDbg_MsgAssert(positionIndex < MAX_POSITIONS_PER_GOAL,(\"Bad positionIndex\"));\r\n\t\r\n\tMth::Vector pos=mp_item_positions[positionIndex].mPos;\r\n\t// First, do a drop down check from the current position\r\n\tMth::Vector start=pos;\r\n\tstart[Y]+=10000.0f;\r\n\tMth::Vector end=pos;\r\n\tend[Y]-=10000.0f;\r\n\t\r\n\tCFeeler feeler;\r\n\tfeeler.SetStart(start);\r\n\tfeeler.SetEnd(end);\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tmp_item_positions[positionIndex].mPos=feeler.GetPoint();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// No collision found, so try starting from much higher up\r\n\tstart[Y]+=10000.0f;\t\r\n\tfeeler.SetStart(start);\r\n\tfeeler.SetEnd(end);\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tmp_item_positions[positionIndex].mPos=feeler.GetPoint();\r\n\t}\r\n}\r\n\r\nvoid CEditGoal::RefreshPositionsUsingCollisionCheck()\r\n{\r\n\tfor (int i=0; i<m_num_positions_set; ++i)\r\n\t{\r\n\t\trefresh_position_using_collision_check(i);\r\n\t\t\r\n\t\tScript::CStruct params;\r\n\t\tparams.AddChecksum(\"Name\",generate_goal_object_name(i));\r\n\t\r\n\t\tparams.AddVector(\"Pos\",mp_item_positions[i].mPos[X],\r\n\t\t\t\t\t\t\t   mp_item_positions[i].mPos[Y]+mp_item_positions[i].mHeight,\r\n\t\t\t\t\t\t\t   mp_item_positions[i].mPos[Z]);\r\n\t\t\r\n\t\tScript::RunScript(CRCD(0x79582240,\"goal_editor_refresh_goal_object_position\"),&params);\r\n\t}\t\r\n}\r\n\r\nvoid CEditGoal::add_goal_params(Script::CStruct *p_params)\r\n{\r\n\tDbg_MsgAssert(p_params,(\"NULL p_params\"));\r\n\r\n\tp_params->AppendStructure(s_get_default_goal_params(m_goal_type));\r\n\tp_params->AppendStructure(s_get_extra_goal_params(m_goal_type));\r\n\t\r\n\t// Now change the node names to be those of the special nodes created just for edited goals.\r\n    p_params->AddChecksum(CRCD(0x2d7e03d,\"trigger_obj_id\"),s_generate_node_name_checksum(m_level_goal_index,0));\r\n    p_params->AddChecksum(CRCD(0x3494f170,\"restart_node\"),s_generate_node_name_checksum(m_level_goal_index,1));\r\n\t\r\n\t// Then write in other misc params.\r\n\t\r\n\tswitch (m_goal_type)\r\n\t{\r\n\t\tcase 0x54166acd: // Skate\r\n\t\t{\r\n\t\t\tp_params->AddChecksum(CRCD(0xba54bd5c,\"S_obj_id\"),s_generate_node_name_checksum(m_level_goal_index,2));\r\n\t\t\tp_params->AddChecksum(CRCD(0x150a97c2,\"K_obj_id\"),s_generate_node_name_checksum(m_level_goal_index,3));\r\n\t\t\tp_params->AddChecksum(CRCD(0x84ca8b0a,\"A_obj_id\"),s_generate_node_name_checksum(m_level_goal_index,4));\r\n\t\t\tp_params->AddChecksum(CRCD(0xb091b445,\"T_obj_id\"),s_generate_node_name_checksum(m_level_goal_index,5));\r\n\t\t\tp_params->AddChecksum(CRCD(0x008085f0,\"E_obj_id\"),s_generate_node_name_checksum(m_level_goal_index,6));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase 0x4ec3cfb5: // Combo\r\n\t\t{\r\n\t\t\tScript::CArray *p_array=new Script::CArray;\r\n\t\t\tp_array->SetSizeAndType(5,ESYMBOLTYPE_STRUCTURE);\r\n\t\t\t\r\n\t\t\tScript::CStruct *p_struct=new Script::CStruct;\r\n\t\t\tp_struct->AddChecksum(CRCD(0x99f6ccbb,\"obj_id\"),s_generate_node_name_checksum(m_level_goal_index,2));\r\n\t\t\tp_struct->AddString(CRCD(0xc4745838,\"text\"),\"C\");\r\n\t\t\tp_array->SetStructure(0,p_struct);\r\n\r\n\t\t\tp_struct=new Script::CStruct;\r\n\t\t\tp_struct->AddChecksum(CRCD(0x99f6ccbb,\"obj_id\"),s_generate_node_name_checksum(m_level_goal_index,3));\r\n\t\t\tp_struct->AddString(CRCD(0xc4745838,\"text\"),\"O\");\r\n\t\t\tp_array->SetStructure(1,p_struct);\r\n\r\n\t\t\tp_struct=new Script::CStruct;\r\n\t\t\tp_struct->AddChecksum(CRCD(0x99f6ccbb,\"obj_id\"),s_generate_node_name_checksum(m_level_goal_index,4));\r\n\t\t\tp_struct->AddString(CRCD(0xc4745838,\"text\"),\"M\");\r\n\t\t\tp_array->SetStructure(2,p_struct);\r\n\r\n\t\t\tp_struct=new Script::CStruct;\r\n\t\t\tp_struct->AddChecksum(CRCD(0x99f6ccbb,\"obj_id\"),s_generate_node_name_checksum(m_level_goal_index,5));\r\n\t\t\tp_struct->AddString(CRCD(0xc4745838,\"text\"),\"B\");\r\n\t\t\tp_array->SetStructure(3,p_struct);\r\n\r\n\t\t\tp_struct=new Script::CStruct;\r\n\t\t\tp_struct->AddChecksum(CRCD(0x99f6ccbb,\"obj_id\"),s_generate_node_name_checksum(m_level_goal_index,6));\r\n\t\t\tp_struct->AddString(CRCD(0xc4745838,\"text\"),\"O\");\r\n\t\t\tp_array->SetStructure(4,p_struct);\r\n\t\t\t\r\n\t\t\tp_params->AddArrayPointer(CRCD(0xb3c7f1b2,\"letter_info\"),p_array);\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tWriteGoalSpecificParams(p_params,WRITING_TO_GOAL_MANAGER);\r\n\t\r\n\tif (mp_goal_description[0])\r\n\t{\r\n\t\tp_params->AddString(CRCD(0xc5d7e6b,\"goal_description\"),mp_goal_description);\r\n\t}\r\n\r\n\tif (mp_win_message[0])\r\n\t{\r\n\t\tScript::CArray *p_default_success_cam_anims=Script::GetArray(CRCD(0x8070c110,\"EditedGoal_success_cam_anims\"),Script::ASSERT);\r\n\t\tDbg_MsgAssert(p_default_success_cam_anims->GetSize()==1,(\"Expected EditedGoal_success_cam_anims to contain just one structure\"));\r\n\t\t\r\n\t\tScript::CArray *p_success_cam_anims=new Script::CArray;\r\n\t\tScript::CopyArray(p_success_cam_anims, p_default_success_cam_anims);\r\n\t\tp_success_cam_anims->GetStructure(0)->AddString(CRCD(0xa7ab3b6d,\"cam_anim_text\"), mp_win_message);\r\n\t\tp_success_cam_anims->GetStructure(0)->AddChecksum(CRCD(0x531e4d28,\"targetid\"),s_generate_node_name_checksum(m_level_goal_index,0));\r\n\t\t\t\r\n\t\tp_params->AddArrayPointer(CRCD(0x27cd32e1,\"success_cam_anims\"), p_success_cam_anims);\r\n\t}\r\n\r\n\tp_params->AddString(CRCD(0xbfecc45b,\"goal_name\"),GetIDString());\r\n\t\r\n\tif (mp_goal_name[0])\r\n\t{\r\n\t\tp_params->AddString(CRCD(0x4bc5229d,\"view_goals_text\"),mp_goal_name);\r\n\t}\t\r\n\t\t\r\n\tif (mp_ped_name[0])\r\n\t{\r\n\t\tp_params->AddString(CRCD(0x243b9c3b,\"full_name\"),mp_ped_name);\r\n\t}\t\r\n\t\r\n\tp_params->AddInteger(CRCD(0x906b67ba,\"time\"),m_time_limit);\r\n\tp_params->AddChecksum(CRCD(0x81cff663,\"control_type\"),m_control_type);\t\t\r\n\t\r\n\t\r\n\t// This is so that the goal manager can tell that this is an edited goal, and hence not save its\r\n\t// details to the mem card.\r\n\tp_params->AddChecksum(NONAME,CRCD(0x981d3ad0,\"edited_goal\"));\r\n}\r\n\r\nuint32 CEditGoal::generate_marker_object_name(int index)\r\n{\r\n\tstatic char p_name[100];\r\n\tsprintf(p_name,\"GoalEditorMarkerObject%d\",index);\r\n\treturn Script::GenerateCRC(p_name);\r\n}\t\r\n\r\nuint32 CEditGoal::generate_goal_object_name(int index)\r\n{\r\n\tstatic char p_name[100];\r\n\t\r\n\tif (index == 0)\r\n\t{\r\n\t\tsprintf(p_name,\"TRG_EditedGoal%d_Pro\",m_level_goal_index);\r\n\t}\r\n\telse if (index > 1)\r\n\t{\r\n\t\tsprintf(p_name,\"TRG_EditedGoal%d_Letter_%d\",m_level_goal_index,index-2);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Position 1 is the restart, so no object exists.\r\n\t\treturn 0;\r\n\t}\t\r\n\t\r\n\treturn Script::GenerateCRC(p_name);\r\n}\t\r\n\r\nvoid CEditGoal::create_marker(int index)\r\n{\r\n\tDbg_MsgAssert(index<MAX_POSITIONS_PER_GOAL,(\"Bad index\"));\r\n\r\n\tScript::CStruct params;\r\n\t\r\n\tswitch (mp_item_positions[index].mType)\r\n\t{\r\n\t\tcase CGoalPos::PED:\r\n\t\t\tparams.AddChecksum(CRCD(0x7321a8d6,\"Type\"),CRCD(0x61a741e,\"Ped\"));\r\n\t\t\tbreak;\r\n\r\n\t\tcase CGoalPos::RESTART:\r\n\t\t\tparams.AddChecksum(CRCD(0x7321a8d6,\"Type\"),CRCD(0x1806ddf8,\"Restart\"));\r\n\t\t\tparams.AddString(\"Model\",\"gameobjects\\\\p1_cursor\\\\p1_cursor.mdl\");\r\n\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\tcase CGoalPos::LETTER:\r\n\t\t{\r\n\t\t\tparams.AddChecksum(CRCD(0x7321a8d6,\"Type\"),CRCD(0x71fd11f5,\"Letter\"));\r\n\t\t\r\n\t\t\t// The -2 is because the first two positions are the ped and restart\r\n\t\t\tDbg_MsgAssert(index>=2,(\"Bad index\"));\r\n\t\t\tconst char *p_letter_model_filename=s_generate_letter_model_filename(m_goal_type,index-2);\r\n\t\t\tparams.AddString(\"Model\",p_letter_model_filename);\r\n\t\t\tparams.AddChecksum(NONAME,CRCD(0x3bd176d9,\"RotateAndHover\"));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\t\t\t\t\t\r\n\tparams.AddChecksum(\"Name\",generate_marker_object_name(index));\r\n\r\n\tparams.AddVector(\"Pos\",mp_item_positions[index].mPos[X],\r\n\t\t\t\t\t\t   mp_item_positions[index].mPos[Y]+mp_item_positions[index].mHeight,\r\n\t\t\t\t\t\t   mp_item_positions[index].mPos[Z]);\r\n\tparams.AddFloat(\"Angle\",mp_item_positions[index].mAngle * 180.0f/3.141592654f);\r\n\t\r\n\tScript::RunScript(\"goal_editor_create_marker_object\",&params);\r\n}\r\n\r\nvoid CEditGoal::delete_marker(int index)\r\n{\r\n\tDbg_MsgAssert(index<MAX_POSITIONS_PER_GOAL,(\"Bad index\"));\r\n\r\n\tScript::CStruct params;\r\n\tparams.AddChecksum(\"Name\",generate_marker_object_name(index));\r\n\tScript::RunScript(\"goal_editor_delete_marker_object\",&params);\r\n}\r\n\r\nbool CEditGoal::position_too_close_to_existing_positions(const Mth::Vector& pos)\r\n{\r\n\tfloat default_min_dist_allowable=Script::GetFloat(CRCD(0x71b20276,\"GoalEditor_DefaultMinDistBetweenPositions\"));\r\n\tfloat letter_skater_min_dist_allowable=Script::GetFloat(CRCD(0x4e9755c1,\"GoalEditor_MinDistBetweenLettersandSkater\"));\r\n\t\r\n\tfor (int i=0; i<m_num_positions_set; ++i)\r\n\t{\r\n\t\t// Ignore the current cursor position, otherwise a piece won't be able to be placed\r\n\t\t// back at its original position when navigating forward/back with X and triangle.\r\n\t\tif (i != m_current_position_index)\r\n\t\t{\r\n\t\t\tCGoalPos::EType this_type=mp_item_positions[m_current_position_index].mType;\r\n\t\t\tCGoalPos::EType that_type=mp_item_positions[i].mType;\r\n\t\t\t\r\n\t\t\tfloat min_dist_allowable=default_min_dist_allowable;\r\n\t\t\tif ((this_type==CGoalPos::LETTER && that_type==CGoalPos::RESTART) ||\r\n\t\t\t\t(this_type==CGoalPos::RESTART && that_type==CGoalPos::LETTER))\r\n\t\t\t{\r\n\t\t\t\tmin_dist_allowable=letter_skater_min_dist_allowable;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tMth::Vector p=mp_item_positions[i].mPos;\r\n\t\t\tp[Y]+=mp_item_positions[i].mHeight;\r\n\t\t\t\r\n\t\t\tif ((p-pos).Length() < min_dist_allowable)\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\t\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\nbool CEditGoal::position_ok_to_place(const Mth::Vector& pos, float height)\r\n{\r\n\tMdl::Skate * p_skate_mod =  Mdl::Skate::Instance();\r\n\tif (p_skate_mod->m_cur_level == CRCD(0xe8b4b836,\"load_sk5ed\") )\r\n\t{\r\n\t\t// Don't allow the pos to be too close to the park boundary, otherwise the ped can be made to\r\n\t\t// be embedded in the wall.\r\n\t\tif (!Ed::IsWithinParkBoundaries(pos, 30.0f))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\t\t\r\n\tMth::Vector pos_with_height=pos;\r\n\tpos_with_height[Y]+=height;\r\n\tif (position_too_close_to_existing_positions(pos_with_height))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n// Used by the GetEditedGoalsInfo script command for use when creating the menu of existing goals.\r\n// Also used by GetCurrentEditedGoalInfo command.\r\n// Also used for writing the goal info to the mem card.\r\n// And used by GetDebugInfo for sending stuff to the script debugger.\r\nvoid CEditGoal::WriteIntoStructure(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info\"));\r\n\t\r\n\tp_info->AddChecksum(NONAME,CRCD(0x981d3ad0,\"edited_goal\"));\r\n\t\r\n\tp_info->AddChecksum(CRCD(0x651533ec,\"level\"),m_level_script);\r\n\tp_info->AddInteger(CRCD(0x60ce75ae,\"level_goal_index\"),m_level_goal_index);\r\n\tp_info->AddChecksum(CRCD(0x9982e501,\"goal_id\"),GetId());\r\n\tp_info->AddInteger(CRCD(0xc51bf6e3,\"time_limit\"),m_time_limit);\r\n\tp_info->AddInteger(CRCD(0x14938611,\"won_goal\"),m_has_won_goal);\r\n\tp_info->AddChecksum(CRCD(0x81cff663,\"control_type\"),m_control_type);\t\t\r\n\t\r\n\tp_info->AddString(CRCD(0x4bc5229d,\"view_goals_text\"),mp_goal_name);\r\n\tp_info->AddString(CRCD(0xc5d7e6b,\"goal_description\"),mp_goal_description);\r\n\tp_info->AddString(CRCD(0x5de57284,\"win_message\"),mp_win_message);\r\n\tp_info->AddString(CRCD(0xb9426608,\"ped_name\"),mp_ped_name);\r\n\tp_info->AddChecksum(CRCD(0x6d11ed74,\"goal_type\"),m_goal_type);\r\n\tp_info->AddChecksum(CRCD(0x71fc348b,\"pro_name\"),s_generate_node_name_checksum(m_level_goal_index,0));\r\n\t\r\n\tWriteGoalSpecificParams(p_info);\r\n\r\n\tif (m_num_positions_set)\r\n\t{\r\n\t\tScript::CArray *p_position_array=new Script::CArray;\r\n\t\tp_position_array->SetSizeAndType(m_num_positions_set,ESYMBOLTYPE_STRUCTURE);\r\n\t\tfor (uint i=0; i<m_num_positions_set; ++i)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_pos_info=new Script::CStruct;\r\n\t\t\tp_pos_info->AddVector(CRCD(0x7f261953,\"Pos\"),mp_item_positions[i].mPos[X],\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t mp_item_positions[i].mPos[Y],\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t mp_item_positions[i].mPos[Z]);\r\n\t\t\tp_pos_info->AddFloat(CRCD(0xab21af0,\"Height\"),mp_item_positions[i].mHeight);\r\n\t\t\tp_pos_info->AddFloat(CRCD(0xff7ebaf6,\"Angle\"),mp_item_positions[i].mAngle);\r\n\t\t\tp_position_array->SetStructure(i,p_pos_info);\r\n\t\t}\r\n\t\tp_info->AddArrayPointer(CRCD(0x32df12e0,\"node_positions\"),p_position_array);\r\n\t}\t\r\n}\r\n\r\nvoid CEditGoal::ReadFromStructure(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info\"));\r\n\t\r\n\tClear();\r\n\tm_used=true;\r\n\r\n\tint won_goal=0;\r\n    //p_info->GetInteger(CRCD(0x14938611,\"won_goal\"),&won_goal);\r\n\tm_has_won_goal=won_goal;\r\n\t\r\n\tm_level_script=s_get_level_checksum(p_info);\r\n\tDbg_MsgAssert(m_level_script,(\"Zero m_level_script\"));\r\n\t\r\n\tp_info->GetInteger(CRCD(0x60ce75ae,\"level_goal_index\"),&m_level_goal_index);\r\n\t\r\n\tp_info->GetChecksum(CRCD(0x6d11ed74,\"goal_type\"),&m_goal_type);\r\n\tDbg_MsgAssert(m_goal_type,(\"Zero m_goal_type\"));\r\n\t// Calling SetType will set up m_num_positions_required\r\n\tSetType(m_goal_type);\r\n\r\n\tp_info->GetInteger(CRCD(0xcd66c8ae,\"score\"),&m_score);\r\n\r\n\tp_info->GetInteger(CRCD(0xc51bf6e3,\"time_limit\"),&m_time_limit);\r\n\tp_info->GetChecksum(CRCD(0x81cff663,\"control_type\"),&m_control_type);\r\n\t\r\n\tconst char *p_string=\"\";\r\n\tp_info->GetString(CRCD(0x4bc5229d,\"view_goals_text\"),&p_string);\r\n\tDbg_MsgAssert(strlen(p_string)<GOAL_NAME_BUFFER_SIZE,(\"goal name '%s' too long\",p_string));\r\n\tstrcpy(mp_goal_name,p_string);\r\n\t\r\n\tp_string=\"\";\r\n\tp_info->GetString(CRCD(0xc5d7e6b,\"goal_description\"),&p_string);\r\n\tDbg_MsgAssert(strlen(p_string)<GOAL_DESCRIPTION_BUFFER_SIZE,(\"goal description '%s' too long\",p_string));\r\n\tstrcpy(mp_goal_description,p_string);\r\n\r\n\tp_string=\"\";\r\n\tp_info->GetString(CRCD(0x5de57284,\"win_message\"),&p_string);\r\n\tDbg_MsgAssert(strlen(p_string)<GOAL_WIN_MESSAGE_BUFFER_SIZE,(\"Win message '%s' too long\",p_string));\r\n\tstrcpy(mp_win_message,p_string);\r\n\t\r\n\tp_string=\"\";\r\n\tp_info->GetString(CRCD(0xb9426608,\"ped_name\"),&p_string);\r\n\tDbg_MsgAssert(strlen(p_string)<PED_NAME_BUFFER_SIZE,(\"ped name '%s' too long\",p_string));\r\n\tstrcpy(mp_ped_name,p_string);\r\n\t\r\n\t\r\n\tScript::CArray *p_position_array=NULL;\r\n\tif (p_info->GetArray(CRCD(0x32df12e0,\"node_positions\"),&p_position_array))\r\n\t{\r\n\t\tDbg_MsgAssert(p_position_array->GetSize()==m_num_positions_required,(\"Bad node_positions size for goal '%s'\",mp_goal_name));\r\n\t\t\r\n\t\tm_num_positions_set=p_position_array->GetSize();\r\n\t\tfor (uint i=0; i<m_num_positions_set; ++i)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_struct=p_position_array->GetStructure(i);\r\n\t\t\tp_struct->GetVector(CRCD(0x7f261953,\"Pos\"),&mp_item_positions[i].mPos);\r\n\t\t\tp_struct->GetFloat(CRCD(0xab21af0,\"Height\"),&mp_item_positions[i].mHeight);\r\n\t\t\tp_struct->GetFloat(CRCD(0xff7ebaf6,\"Angle\"),&mp_item_positions[i].mAngle);\r\n\t\t}\t\r\n\t}\r\n\t\t\r\n\tReadGoalSpecificParams(p_info);\r\n}\r\n\r\nvoid CEditGoal::AddGap(uint8 gap_number)\r\n{\r\n\tif (GotGap(gap_number))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tif (m_num_gaps>=MAX_GAPS)\r\n\t{\r\n\t\tprintf(\"Warning! MAX_GAPS limit reached!\\n\");\r\n\t\treturn;\r\n\t}\t\r\n\tDbg_MsgAssert(m_num_gaps<MAX_GAPS,(\"Too many gaps added\"));\r\n\tmp_gap_numbers[m_num_gaps++]=gap_number;\r\n}\r\n\r\nvoid CEditGoal::RemoveGap(uint8 gap_number)\r\n{\r\n\tfor (int i=0; i<m_num_gaps; ++i)\r\n\t{\r\n\t\tif (mp_gap_numbers[i]==gap_number)\r\n\t\t{\r\n\t\t\tfor (int j=i; j<m_num_gaps-1; ++j)\r\n\t\t\t{\r\n\t\t\t\tmp_gap_numbers[j]=mp_gap_numbers[j+1];\r\n\t\t\t}\r\n\t\t\t--m_num_gaps;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\t\t\t\r\n}\r\n\r\n// This is used when a gap is removed from the park editor. Once removed,\r\n// any references to gaps with a gap number higher than the one removed will\r\n// need to be decremented.\r\nvoid CEditGoal::RemoveGapAndReorder(uint8 gap_number)\r\n{\r\n\tRemoveGap(gap_number);\r\n\tfor (int i=0; i<m_num_gaps; ++i)\r\n\t{\r\n\t\tif (mp_gap_numbers[i] > gap_number)\r\n\t\t{\r\n\t\t\t--mp_gap_numbers[i];\r\n\t\t}\r\n\t}\r\n}\r\n\t\r\nbool CEditGoal::GotGap(uint8 gap_number)\r\n{\r\n\tfor (int i=0; i<m_num_gaps; ++i)\r\n\t{\r\n\t\tif (mp_gap_numbers[i]==gap_number)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\t\t\r\n}\r\n\r\nvoid CEditGoal::AddKeyComboSet(int setIndex, bool requirePerfect, int spin, int numTaps)\r\n{\r\n\tint array_index=0;\r\n\tbool found=false;\r\n\tfor (int i=0; i<m_num_combo_sets; ++i)\r\n\t{\r\n\t\tif (mp_combo_sets[i].mSetIndex==setIndex)\r\n\t\t{\r\n\t\t\tarray_index=i;\r\n\t\t\tfound=true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif (!found)\r\n\t{\r\n\t\tDbg_MsgAssert(m_num_combo_sets<MAX_COMBO_SETS,(\"Too many key combo sets added, may need to increase MAX_COMBO_SETS in goaleditorcomponent.h (currently=%d)\",MAX_COMBO_SETS));\r\n\t\tarray_index=m_num_combo_sets;\r\n\t\t++m_num_combo_sets;\r\n\t}\t\r\n\t\r\n\tmp_combo_sets[array_index].mNumTaps=numTaps;\r\n\tmp_combo_sets[array_index].mRequirePerfect=requirePerfect;\r\n\tmp_combo_sets[array_index].mSetIndex=setIndex;\r\n\tDbg_MsgAssert((spin%180)==0,(\"spin must be a multiple of 180\"));\r\n\tmp_combo_sets[array_index].mSpin=spin/180;\r\n}\r\n\r\nvoid CEditGoal::RemoveKeyComboSet(int setIndex)\r\n{\r\n\tbool found=false;\r\n\tfor (int i=0; i<m_num_combo_sets; ++i)\r\n\t{\r\n\t\tif (mp_combo_sets[i].mSetIndex==setIndex)\r\n\t\t{\r\n\t\t\t// Move the ones above down. Won't take long, they're only 4 bytes each.\r\n\t\t\tfor (int j=i; j<m_num_combo_sets-1; ++j)\r\n\t\t\t{\r\n\t\t\t\tmp_combo_sets[j]=mp_combo_sets[j+1];\r\n\t\t\t}\t\r\n\t\t\tfound=true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif (found)\r\n\t{\r\n\t\t--m_num_combo_sets;\r\n\t}\t\r\n}\r\n\r\nSPreDefinedKeyComboSet *CEditGoal::GetKeyComboSet(int setIndex)\r\n{\r\n\tfor (int i=0; i<m_num_combo_sets; ++i)\r\n\t{\r\n\t\tif (mp_combo_sets[i].mSetIndex==setIndex)\r\n\t\t{\r\n\t\t\treturn &mp_combo_sets[i];\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n// Used when generating the goal_tetris_key_combos array from the mp_combo_sets array,\r\n// for sending to the goal manager.\r\nvoid CEditGoal::generate_key_combos_array(Script::CStruct *p_info)\r\n{\r\n\tif (!m_num_combo_sets)\r\n\t{\r\n\t\tprintf(\"!!!!!!!! Warning! No combo sets specified, using emergency_key_combos\\n\");\r\n\t\tp_info->AddChecksum(CRCD(0x7be1e689,\"goal_tetris_key_combos\"),CRCD(0x6d641bcb,\"emergency_key_combos\"));\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tScript::CArray *p_predefined_key_combos=Script::GetArray(CRCD(0xba9358a5,\"cag_skatetris_key_combos\"),Script::ASSERT);\r\n\r\n\tint size=0;\r\n\t\r\n\t// Calculate the total size of the goal_tetris_key_combos array.\r\n\tfor (int i=0; i<m_num_combo_sets; ++i)\r\n\t{\r\n\t\tScript::CStruct *p_struct=p_predefined_key_combos->GetStructure(mp_combo_sets[i].mSetIndex);\r\n\t\tScript::CArray *p_key_combos=NULL;\r\n\t\tp_struct->GetArray(CRCD(0x79704516,\"key_combos\"),&p_key_combos);\r\n\t\tDbg_MsgAssert(p_key_combos,(\"Missing key_combos array in element %d of array cag_skatetris_key_combos\",i));\r\n\t\tsize+=p_key_combos->GetSize();\r\n\t}\r\n\r\n\tDbg_MsgAssert(size,(\"Zero size for goal_tetris_key_combos array!\"));\r\n\r\n\tScript::CArray *p_goal_tetris_key_combos=new Script::CArray;\r\n\tp_goal_tetris_key_combos->SetSizeAndType(size,ESYMBOLTYPE_STRUCTURE);\r\n\r\n\tint dest_index=0;\r\n\tfor (int i=0; i<m_num_combo_sets; ++i)\r\n\t{\r\n\t\tScript::CStruct *p_struct=p_predefined_key_combos->GetStructure(mp_combo_sets[i].mSetIndex);\r\n\t\tScript::CArray *p_key_combos=NULL;\r\n\t\tp_struct->GetArray(CRCD(0x79704516,\"key_combos\"),&p_key_combos);\r\n\t\tDbg_MsgAssert(p_key_combos,(\"Missing key_combos array in element %d of array cag_skatetris_key_combos\",i));\r\n\t\t\r\n\t\tfor (uint32 j=0; j<p_key_combos->GetSize(); ++j)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_entry=new Script::CStruct;\r\n\r\n\t\t\tif (p_key_combos->GetType()==ESYMBOLTYPE_NAME)\r\n\t\t\t{\r\n\t\t\t\tp_entry->AddChecksum(CRCD(0xacfdb27a,\"key_combo\"),p_key_combos->GetChecksum(j));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_entry->AppendStructure(p_key_combos->GetStructure(j));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Overlay any extra params the user specified for this set.\r\n\t\t\tif (mp_combo_sets[i].mNumTaps)\r\n\t\t\t{\r\n\t\t\t\tp_entry->AddInteger(CRCD(0xa4bee6a1,\"num_taps\"),mp_combo_sets[i].mNumTaps);\r\n\t\t\t}\r\n\t\t\tif (mp_combo_sets[i].mRequirePerfect)\r\n\t\t\t{\r\n\t\t\t\tp_entry->AddChecksum(NONAME,CRCD(0x687e2c25,\"require_perfect\"));\r\n\t\t\t}\r\n\t\t\t//if (mp_combo_sets[i].mSpin)\r\n\t\t\t//{\r\n\t\t\t//\tp_entry->AddInteger(CRCD(0x8c8abd19,\"random_spin\"),mp_combo_sets[i].mSpin*180);\r\n\t\t\t//}\r\n\t\t\t\r\n\t\t\t// Originally each set could have it's own spin, but it was decided that that was not\r\n\t\t\t// necessary and that instead a single spin value would be specified for the whole goal.\r\n\t\t\tif (m_spin)\r\n\t\t\t{\r\n\t\t\t\t// random_spin means the goal manager will actually choose a random spin up to the m_spin value.\r\n\t\t\t\tp_entry->AddInteger(CRCD(0x8c8abd19,\"random_spin\"),m_spin);\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tp_goal_tetris_key_combos->SetStructure(dest_index++,p_entry);\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tp_info->AddArrayPointer(CRCD(0x7be1e689,\"goal_tetris_key_combos\"),p_goal_tetris_key_combos);\r\n}\r\n\r\n// Used for writing the mp_combo_sets array to mem card.\r\n// Also used in GetDebugInfo\r\nvoid CEditGoal::write_combo_sets(Script::CStruct *p_info)\r\n{\r\n\tif (!m_num_combo_sets)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tScript::CArray *p_array=new Script::CArray;\r\n\tp_array->SetSizeAndType(m_num_combo_sets,ESYMBOLTYPE_STRUCTURE);\r\n\tfor (int i=0; i<m_num_combo_sets; ++i)\r\n\t{\r\n\t\tScript::CStruct *p_struct=new Script::CStruct;\r\n\t\t\r\n\t\tp_struct->AddInteger(CRCD(0xeb7d6498,\"set_index\"),mp_combo_sets[i].mSetIndex);\r\n\t\tif (mp_combo_sets[i].mRequirePerfect)\r\n\t\t{\r\n\t\t\tp_struct->AddChecksum(NONAME,CRCD(0x687e2c25,\"require_perfect\"));\r\n\t\t}\r\n\t\tp_struct->AddInteger(CRCD(0xedf5db70,\"spin\"),mp_combo_sets[i].mSpin*180);\r\n\t\tp_struct->AddInteger(CRCD(0xa4bee6a1,\"num_taps\"),mp_combo_sets[i].mNumTaps);\r\n\t\t\r\n\t\tp_array->SetStructure(i,p_struct);\r\n\t}\t\r\n\tp_info->AddArrayPointer(CRCD(0x490f171,\"combo_sets\"),p_array);\r\n}\r\n\r\nvoid CEditGoal::read_combo_sets(Script::CStruct *p_info)\r\n{\r\n\tScript::CArray *p_array=NULL;\r\n\tif (!p_info->GetArray(CRCD(0x490f171,\"combo_sets\"),&p_array))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tm_num_combo_sets=p_array->GetSize();\r\n\tDbg_MsgAssert(m_num_combo_sets<=MAX_COMBO_SETS,(\"m_num_combo_sets of %d too big\",m_num_combo_sets));\r\n\t\r\n\tfor (int i=0; i<m_num_combo_sets; ++i)\r\n\t{\r\n\t\tScript::CStruct *p_struct=p_array->GetStructure(i);\r\n\t\t\r\n\t\tint int_val=0;\r\n\t\tp_struct->GetInteger(CRCD(0xeb7d6498,\"set_index\"),&int_val);\r\n\t\tmp_combo_sets[i].mSetIndex=int_val;\r\n\t\t\r\n\t\tint_val=0;\r\n\t\tp_struct->GetInteger(CRCD(0xedf5db70,\"spin\"),&int_val);\r\n\t\tDbg_MsgAssert((int_val%180)==0,(\"Bad spin of %d\",int_val));\r\n\t\tmp_combo_sets[i].mSpin=int_val/180;\r\n\t\t\r\n\t\tint_val=0;\r\n\t\tp_struct->GetInteger(CRCD(0xa4bee6a1,\"num_taps\"),&int_val);\r\n\t\tmp_combo_sets[i].mNumTaps=int_val;\r\n\t\t\r\n\t\tmp_combo_sets[i].mRequirePerfect=p_struct->ContainsFlag(CRCD(0x687e2c25,\"require_perfect\"));\r\n\t}\t\r\n}\r\n\r\n// The dest parameter determines the format in which the combo sets are written out.\r\n// When generating params for the goal manager, the full goal_tetris_key_combos array is\r\n// generated. When writing to mem card the chosen pre-defined set numbers are written instead.\r\nvoid CEditGoal::write_skatetris_params(Script::CStruct *p_info, EWriteDest dest)\r\n{\r\n\tp_info->AddInteger(CRCD(0x1181b29,\"acceleration_interval\"),m_acceleration_interval);\r\n\tp_info->AddFloat(CRCD(0x76f65c8,\"acceleration_percent\"),m_acceleration_percent);\r\n\tp_info->AddInteger(CRCD(0xded8540a,\"trick_time\"),m_trick_time);\r\n\tp_info->AddInteger(CRCD(0xa6d96603,\"time_to_stop_adding_tricks\"),m_time_to_stop_adding_tricks);\r\n\tp_info->AddInteger(CRCD(0x89473db7,\"max_tricks\"),m_max_tricks);\r\n\t\r\n\tif (dest==WRITING_TO_GOAL_MANAGER)\r\n\t{\r\n\t\t// When writing params out for the goal manager, the m_spin value is given to all of\r\n\t\t// the key combos.\r\n\t\tgenerate_key_combos_array(p_info);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_info->AddInteger(CRCD(0xedf5db70,\"spin\"),m_spin);\r\n\t\twrite_combo_sets(p_info);\r\n\t}\r\n}\r\n\r\nvoid CEditGoal::read_skatetris_params(Script::CStruct *p_info)\r\n{\r\n\tp_info->GetInteger(CRCD(0x1181b29,\"acceleration_interval\"),&m_acceleration_interval);\r\n\tp_info->GetFloat(CRCD(0x76f65c8,\"acceleration_percent\"),&m_acceleration_percent);\r\n\tp_info->GetInteger(CRCD(0xded8540a,\"trick_time\"),&m_trick_time);\r\n\tp_info->GetInteger(CRCD(0xa6d96603,\"time_to_stop_adding_tricks\"),&m_time_to_stop_adding_tricks);\r\n\tp_info->GetInteger(CRCD(0x89473db7,\"max_tricks\"),&m_max_tricks);\r\n\tp_info->GetInteger(CRCD(0xedf5db70,\"spin\"),&m_spin);\r\n\t\r\n\tread_combo_sets(p_info);\r\n}\r\n\r\n// The dest parameter determines the format in which the combo sets are written out.\r\n// When generating params for the goal manager, the full goal_tetris_key_combos array is\r\n// generated. When writing to mem card the chosen pre-defined set numbers are written instead.\r\nvoid CEditGoal::WriteGoalSpecificParams(Script::CStruct *p_info, EWriteDest dest)\r\n{\r\n\tswitch (m_goal_type)\r\n\t{\r\n\t\tcase 0xea7ba666: // TrickTris\r\n\t\t\tp_info->AddChecksum(NONAME,CRCD(0xea7ba666,\"tricktris\"));\r\n\t\t\tp_info->AddInteger(CRCD(0x45a375c9,\"tricktris_block_size\"),m_tricktris_block_size);\r\n\t\t\tp_info->AddInteger(CRCD(0xbfd3a831,\"tricktris_total_to_win\"),m_tricktris_total_to_win);\r\n\t\t\t// Needed otherwise the goal will fail straight away for block size 13, total to win 12 (TT5933)\r\n\t\t\tm_max_tricks=m_tricktris_block_size;\r\n\t\t\twrite_skatetris_params(p_info,dest);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase 0x0fc6f698: // ComboSkateTris\r\n\t\t\tp_info->AddChecksum(NONAME,CRCD(0x4ec3cfb5,\"combo\"));\r\n\t\t\tp_info->AddInteger(CRCD(0x67dd90ca,\"combo_size\"),m_combo_size);\r\n\t\t\tif (m_single_combo)\r\n\t\t\t{\r\n\t\t\t\tp_info->AddChecksum(NONAME,CRCD(0xdf47b144,\"single_combo\"));\r\n\t\t\t\t\r\n\t\t\t\t// Needed otherwise the goal will fail straight away for a single combo size of 12 (TT7652)\r\n\t\t\t\tm_max_tricks=m_combo_size;\r\n\t\t\t}\r\n\t\t\twrite_skatetris_params(p_info,dest);\r\n\t\t\tbreak;\t\r\n\t\t\t\r\n\t\tcase 0x7fe2238a: // SkateTris\r\n\t\t\twrite_skatetris_params(p_info,dest);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase 0x6fe44c6d: // HighScore\r\n\t\tcase 0xec414b76: // HighCombo\r\n\t\t{\r\n\t\t\tp_info->AddInteger(CRCD(0xcd66c8ae,\"score\"),m_score);\r\n\t\t\tif (dest==WRITING_TO_GOAL_MANAGER)\r\n\t\t\t{\r\n\t\t\t\tconst char *p_text=NULL;\r\n\t\t\t\tif (m_goal_type==CRCD(0xec414b76,\"HighCombo\"))\r\n\t\t\t\t{\r\n\t\t\t\t\tp_text=Script::GetString(CRCD(0x3693bfe4,\"edited_high_combo_goal_text\"));\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_text=Script::GetString(CRCD(0xd6efb1b5,\"edited_high_score_goal_text\"));\r\n\t\t\t\t}\t\r\n\t\t\t\tchar p_temp[100];\r\n\t\t\t\tsprintf(p_temp,p_text,m_score);\r\n\t\t\t\tp_info->AddString(CRCD(0xda441d9a,\"goal_text\"),p_temp);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0x61c5d092: // Gap\r\n\t\t{\r\n\t\t\tp_info->AddString(CRCD(0x730844a3,\"required_trick_name\"),mp_trick_name);\r\n\t\t\t\r\n\t\t\tif (dest==WRITING_TO_GOAL_MANAGER)\r\n\t\t\t{\r\n\t\t\t\tScript::CArray *p_goal_flags=new Script::CArray;\r\n\t\t\t\tp_goal_flags->SetSizeAndType(m_num_gaps,ESYMBOLTYPE_NAME);\r\n\t\t\t\tchar p_foo[20];\r\n\t\t\t\tfor (int i=0; i<m_num_gaps; ++i)\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf(p_foo,\"got_%d\",i+1);\r\n\t\t\t\t\tp_goal_flags->SetChecksum(i,Script::GenerateCRC(p_foo));\r\n\t\t\t\t}\t\r\n\t\t\t\tp_info->AddArrayPointer(CRCD(0xcc3c4cc4,\"goal_flags\"),p_goal_flags);\r\n\r\n\t\t\t\t\r\n\t\t\t\tScript::CArray *p_required_gaps=new Script::CArray;\r\n\t\t\t\tp_required_gaps->SetSizeAndType(m_num_gaps,ESYMBOLTYPE_INTEGER);\r\n\t\t\t\t\r\n\t\t\t\tfor (int i=0; i<m_num_gaps; ++i)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_required_gaps->SetInteger(i,mp_gap_numbers[i]);\r\n\t\t\t\t}\t\r\n\t\t\t\tp_info->AddArrayPointer(CRCD(0x52d4489e,\"required_gaps\"),p_required_gaps);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (m_num_gaps)\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CArray *p_gaps=new Script::CArray;\r\n\t\t\t\t\tp_gaps->SetSizeAndType(m_num_gaps,ESYMBOLTYPE_INTEGER);\r\n\t\t\t\t\tfor (int i=0; i<m_num_gaps; ++i)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_gaps->SetInteger(i,mp_gap_numbers[i]);\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tp_info->AddArrayPointer(CRCD(0xd76c173e,\"Gaps\"),p_gaps);\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\t\t\r\n}\r\n\r\nvoid CEditGoal::ReadGoalSpecificParams(Script::CStruct *p_params)\r\n{\r\n\tswitch (m_goal_type)\r\n\t{\r\n\t\tcase 0xea7ba666: // TrickTris\r\n\t\t\tp_params->GetInteger(CRCD(0x45a375c9,\"tricktris_block_size\"),&m_tricktris_block_size);\r\n\t\t\tp_params->GetInteger(CRCD(0xbfd3a831,\"tricktris_total_to_win\"),&m_tricktris_total_to_win);\r\n\t\t\tread_skatetris_params(p_params);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase 0x0fc6f698: // ComboSkateTris\r\n\t\t\tp_params->GetInteger(CRCD(0x67dd90ca,\"combo_size\"),&m_combo_size);\r\n\t\t\t\r\n\t\t\t// Note: This only sets the m_single_combo if the flag single_combo is specified,\r\n\t\t\t// if single_combo is not specified it will leave m_single_combo the way it was.\r\n\t\t\t// Need this otherwise m_single_combo will get switched off if ReadGoalSpecificParams\r\n\t\t\t// is used to just set combo_size.\r\n\t\t\tif (p_params->ContainsFlag(CRCD(0xdf47b144,\"single_combo\")))\r\n\t\t\t{\r\n\t\t\t\tm_single_combo=true;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tread_skatetris_params(p_params);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase 0x7fe2238a: // SkateTris\r\n\t\t\tread_skatetris_params(p_params);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase 0x6fe44c6d: // HighScore\r\n\t\tcase 0xec414b76: // HighCombo\r\n\t\t{\r\n\t\t\tp_params->GetInteger(CRCD(0xcd66c8ae,\"score\"),&m_score);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase 0x61c5d092: // Gap\r\n\t\t{\r\n\t\t\tconst char *p_trick_name=NULL;\r\n\t\t\tif (p_params->GetString(CRCD(0x730844a3,\"required_trick_name\"),&p_trick_name))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(strlen(p_trick_name)<=MAX_GAP_TRICK_NAME_CHARS,(\"trick_name '%s' too long\",p_trick_name));\r\n\t\t\t\tstrcpy(mp_trick_name,p_trick_name);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tScript::CArray *p_gaps=NULL;\r\n\t\t\tp_params->GetArray(CRCD(0xd76c173e,\"Gaps\"),&p_gaps);\r\n\t\t\tif (p_gaps)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(p_gaps->GetSize()<=MAX_GAPS,(\"Gaps array too big, max is %d\",MAX_GAPS));\r\n\t\t\t\tm_num_gaps=p_gaps->GetSize();\r\n\t\t\t\tfor (int i=0; i<m_num_gaps; ++i)\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_gap_numbers[i]=p_gaps->GetInteger(i);\r\n\t\t\t\t}\r\n\t\t\t}\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\t\t\r\n}\r\n\r\nvoid CEditGoal::RemoveGoalSpecificFlag(Script::CStruct *p_params)\r\n{\r\n\tuint32 flag=0;\r\n\tp_params->GetChecksum(NONAME,&flag);\r\n\t\r\n\tswitch (m_goal_type)\r\n\t{\r\n\t\tcase 0x0fc6f698: // ComboSkateTris\r\n\t\t\tif (flag==CRCD(0xdf47b144,\"single_combo\"))\r\n\t\t\t{\r\n\t\t\t\tm_single_combo=false;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\t\t\r\n}\r\n\t\r\nvoid CEditGoal::EditGoal()\r\n{\r\n//\tDbg_MsgAssert(m_num_positions_set == m_num_positions_required,(\"Tried to edit a goal that was not fully defined originally\"));\r\n\t// Note: The index starts at 1, because the cursor will initially be at index 0, and the cursor object is\r\n\t// not a marker object.\r\n\tfor (int index=1; index<m_num_positions_set; ++index)\r\n\t{\r\n\t\tcreate_marker(index);\r\n\t}\r\n\tm_current_position_index=0;\r\n\t\r\n\tm_has_won_goal=false;\r\n}\r\n\r\nbool CEditGoal::GotAllPositions()\r\n{\r\n\treturn m_num_positions_set == m_num_positions_required;\r\n}\r\n\r\nbool CEditGoal::SetPosition(const Mth::Vector& pos, float height, float angle)\r\n{\r\n\tm_placed_last_position=false;\r\n\r\n\tif (!position_ok_to_place(pos,height))\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\tDbg_MsgAssert(m_current_position_index<MAX_POSITIONS_PER_GOAL,(\"Bad m_current_position_index\"));\r\n\r\n\tmp_item_positions[m_current_position_index].mPos=pos;\r\n\tmp_item_positions[m_current_position_index].mHeight=height;\r\n\tmp_item_positions[m_current_position_index].mAngle=angle;\r\n\t\r\n\tif (m_current_position_index == m_num_positions_required-1)\r\n\t{\r\n\t\tm_placed_last_position=true;\r\n\t}\t\r\n\tif (m_current_position_index==0)\r\n\t{\r\n\t\t// Just placed the ped position, so update the helper text so as to have the 'back' option\r\n\t\tScript::RunScript(CRCD(0xd066a889,\"create_cag_helper_text\"));\r\n\t}\r\n\t\t\r\n\tcreate_marker(m_current_position_index);\r\n\t\r\n\t++m_current_position_index;\r\n\t\r\n\tdelete_marker(m_current_position_index);\r\n\t\r\n\t// Update m_num_positions_set, which is the total number of valid positions set so far.\r\n\tif (m_current_position_index >= m_num_positions_set)\r\n\t{\r\n\t\tm_num_positions_set=m_current_position_index;\r\n\t\tif (m_num_positions_set == m_num_positions_required)\r\n\t\t{\r\n\t\t\tm_current_position_index=m_num_positions_required-1;\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t\t\r\n\t\t// Make the new position default to the last position\r\n\t\tmp_item_positions[m_current_position_index].mPos=pos;\r\n\t\tmp_item_positions[m_current_position_index].mHeight=height;\r\n\t\tmp_item_positions[m_current_position_index].mAngle=angle;\r\n\t\t\r\n\t\t// When moving on to the first letter of the skate or combo line, add in a tweak to \r\n\t\t// the height so that the letter does not appear initially half way through the ground.\r\n\t\tif ((m_goal_type==CRCD(0x4ec3cfb5,\"Combo\") || m_goal_type==CRCD(0x54166acd,\"Skate\")) &&  \r\n\t\t\t m_current_position_index == 2 )\r\n\t\t{\r\n\t\t\tmp_item_positions[m_current_position_index].mHeight+=Script::GetFloat(CRCD(0x82a694e,\"GoalEditor_LetterHeight\"));\r\n\t\t}\r\n\t}\t\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\nbool CEditGoal::GetPosition(Mth::Vector *p_pos, float *p_height, float *p_angle)\r\n{\r\n\t*p_pos=mp_item_positions[m_current_position_index].mPos;\r\n\t*p_height=mp_item_positions[m_current_position_index].mHeight;\r\n\t*p_angle=mp_item_positions[m_current_position_index].mAngle;\r\n\treturn true;\r\n}\r\n\r\nvoid CEditGoal::GetPosition(Mth::Vector *p_pos, int index)\r\n{\r\n\tDbg_MsgAssert(m_num_positions_set > index,(\"Called GetPedPosition with index=%d but m_num_positions_set=%d\",index,m_num_positions_set));\r\n\t*p_pos=mp_item_positions[index].mPos;\r\n\t(*p_pos)[Y]+=mp_item_positions[index].mHeight;\r\n}\r\n\r\nCGoalPos::EType CEditGoal::GetPositionType()\r\n{\r\n\tif (m_num_positions_set)\r\n\t{\r\n\t\treturn mp_item_positions[m_current_position_index].mType;\r\n\t}\r\n\treturn CGoalPos::PED;\r\n}\r\n\r\nbool CEditGoal::BackUp(const Mth::Vector& pos, float height, float angle)\r\n{\r\n\t// Can't back up if at the first position\r\n\tif (m_current_position_index == 0)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (!position_ok_to_place(pos,height))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\t// First, set the position as though X had been pressed, so that a marker is dropped at the current\r\n\t// position which can be got back to by pressing X again.\r\n\tDbg_MsgAssert(m_current_position_index<MAX_POSITIONS_PER_GOAL,(\"Bad m_current_position_index\"));\r\n\r\n\tmp_item_positions[m_current_position_index].mPos=pos;\r\n\tmp_item_positions[m_current_position_index].mHeight=height;\r\n\tmp_item_positions[m_current_position_index].mAngle=angle;\r\n\r\n\tcreate_marker(m_current_position_index);\r\n\t\t\r\n\tif (m_current_position_index==m_num_positions_set)\r\n\t{\r\n\t\t++m_num_positions_set;\r\n\t}\r\n\t\r\n\t// Then decrement the position index, and delete the marker at that position.\r\n\t// The cursor will then appear there on the next call to refresh_cursor_object\r\n\tDbg_MsgAssert(m_current_position_index,(\"Zero m_current_position_index ?\"));\r\n\t--m_current_position_index;\r\n\t\r\n\tdelete_marker(m_current_position_index);\r\n\r\n\tif (m_current_position_index == 0)\r\n\t{\r\n\t\t// Returned to the ped position, so update the helper text so as to not have the 'back' option\r\n\t\tScript::CStruct *p_params=new Script::CStruct;\r\n\t\tp_params->AddChecksum(NONAME,CRCD(0x7f1538e0,\"PedPosition\"));\r\n\t\tScript::RunScript(CRCD(0xd066a889,\"create_cag_helper_text\"), p_params);\r\n\t\tdelete p_params;\r\n\t}\t\r\n\r\n\treturn true;\t\r\n}\r\n\r\nuint CEditGoal::GetCurrentLetterIndex()\r\n{\r\n\tuint index=0;\r\n\t\r\n\tswitch (m_goal_type)\r\n\t{\r\n\t\tcase 0x4ec3cfb5: // Combo\r\n\t\tcase 0x54166acd: // Skate\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(m_current_position_index>=2,(\"Current position is not that of a letter\"));\r\n\t\t\tindex=m_current_position_index-2;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Called GetCurrentLetterIndex() when goal type is %s\\n\",Script::FindChecksumName(m_goal_type)));\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\treturn index;\r\n}\r\n\r\nvoid CEditGoal::SetType(uint32 type)\r\n{\r\n\tm_goal_type=type;\r\n\t\r\n\tmp_item_positions[0].mType=CGoalPos::PED;\r\n\tmp_item_positions[0].mHeight=0.0f;\r\n\tmp_item_positions[1].mType=CGoalPos::RESTART;\r\n\tmp_item_positions[1].mHeight=0.0f;\r\n\t\r\n\tconst Script::CStruct *p_default_params=s_get_default_goal_params(m_goal_type);\r\n\t\r\n\tswitch (m_goal_type)\r\n\t{\r\n\t\tcase 0x54166acd: // Skate\r\n\t\t{\r\n\t\t\tm_num_positions_required=7;\r\n\t\t\t\r\n\t\t\tfor (int i=2; i<MAX_POSITIONS_PER_GOAL; ++i)\r\n\t\t\t{\r\n\t\t\t\tmp_item_positions[i].mType=CGoalPos::LETTER;\r\n\t\t\t\tmp_item_positions[i].mHeight=0.0f;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase 0x4ec3cfb5: // Combo\r\n\t\t{\r\n\t\t\tm_num_positions_required=7;\r\n\t\t\t\r\n\t\t\tfor (int i=2; i<MAX_POSITIONS_PER_GOAL; ++i)\r\n\t\t\t{\r\n\t\t\t\tmp_item_positions[i].mType=CGoalPos::LETTER;\r\n\t\t\t\tmp_item_positions[i].mHeight=0.0f;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\r\n\t\tcase 0x6fe44c6d: // HighScore\r\n\t\tcase 0xec414b76: // HighCombo\r\n\t\tcase 0x7fe2238a: // SkateTris\r\n\t\tcase 0x0fc6f698: // ComboSkateTris\r\n\t\tcase 0xea7ba666: // TrickTris\r\n\t\tcase 0x61c5d092: // Gap\r\n\t\t{\r\n\t\t\tm_num_positions_required=2;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\t\t\r\n\t\r\n\tif (p_default_params)\r\n\t{\r\n\t\tp_default_params->GetInteger(CRCD(0xc51bf6e3,\"time_limit\"),&m_time_limit);\r\n\t\tp_default_params->GetInteger(CRCD(0xcd66c8ae,\"score\"),&m_score);\r\n\t\t\r\n\t\tconst char *p_string=\"\";\r\n\t\tp_default_params->GetString(CRCD(0x4bc5229d,\"view_goals_text\"),&p_string);\r\n\t\tDbg_MsgAssert(strlen(p_string)<GOAL_NAME_BUFFER_SIZE,(\"goal name '%s' too long\",p_string));\r\n\t\tstrcpy(mp_goal_name,p_string);\r\n\t}\t\r\n}\r\n\r\nvoid CEditGoal::SetGoalDescription(const char *p_text)\r\n{\r\n\tDbg_MsgAssert(p_text,(\"NULL p_text ?\"));\r\n\tDbg_MsgAssert(strlen(p_text)<GOAL_DESCRIPTION_BUFFER_SIZE,(\"Goal description too long!\"));\r\n\tstrcpy(mp_goal_description,p_text);\r\n}\r\n\r\nvoid CEditGoal::SetWinMessage(const char *p_text)\r\n{\r\n\tDbg_MsgAssert(p_text,(\"NULL p_text ?\"));\r\n\tDbg_MsgAssert(strlen(p_text)<GOAL_WIN_MESSAGE_BUFFER_SIZE,(\"Win message too long!\"));\r\n\tstrcpy(mp_win_message,p_text);\r\n}\r\n\r\nvoid CEditGoal::SetGoalName(const char *p_name)\r\n{\r\n\tDbg_MsgAssert(p_name,(\"NULL p_name ?\"));\r\n\tDbg_MsgAssert(strlen(p_name)<GOAL_NAME_BUFFER_SIZE,(\"Goal name too long!\"));\r\n\tstrcpy(mp_goal_name,p_name);\r\n}\r\n\r\nvoid CEditGoal::SetPedName(const char *p_name)\r\n{\r\n\tDbg_MsgAssert(p_name,(\"NULL p_name ?\"));\r\n\tDbg_MsgAssert(strlen(p_name)<PED_NAME_BUFFER_SIZE,(\"Goal name too long!\"));\r\n\tstrcpy(mp_ped_name,p_name);\r\n}\r\n\r\nvoid CEditGoal::SetTimeLimit(int timeLimit)\r\n{\r\n\tm_time_limit=timeLimit;\r\n\t\r\n\tswitch (m_goal_type)\r\n\t{\r\n\t\tcase 0x7fe2238a: // SkateTris\r\n\t\tcase 0x0fc6f698: // ComboSkateTris\r\n\t\tcase 0xea7ba666: // TrickTris\r\n\t\t\t// Make sure that m_time_to_stop_adding_tricks is valid.\r\n\t\t\tif (m_time_to_stop_adding_tricks > m_time_limit)\r\n\t\t\t{\r\n\t\t\t\tm_time_to_stop_adding_tricks=m_time_limit;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\t\r\n}\r\n\r\nvoid CEditGoal::SetControlType(uint32 controlType)\r\n{\r\n\tm_control_type=controlType;\r\n}\r\n\r\nvoid CEditGoal::AddGoalToGoalManager(bool markUnbeaten)\r\n{\r\n\tScript::CStruct *p_params=new Script::CStruct;\r\n\tadd_goal_params(p_params);\r\n\t\r\n\tGame::CGoalManager* p_goal_manager = Game::GetGoalManager();\r\n\tDbg_MsgAssert(p_goal_manager,(\"NULL p_goal_manager ?\"));\r\n\tp_goal_manager->AddGoal(GetId(),p_params);\r\n\r\n\tGame::CGoal *p_goal=p_goal_manager->GetGoal(GetId());\r\n\t// Mark it as seen so that it is selectable in the view-goals menu\r\n\tp_goal->SetHasSeen();\t\t\r\n\r\n\tif (markUnbeaten)\r\n\t{\r\n\t\tm_has_won_goal=false;\r\n\t}\r\n\t\t\r\n\tif (m_has_won_goal)\r\n\t{\r\n\t\tp_goal->MarkBeaten();\r\n\t}\t\r\n\t\r\n\tdelete p_params;\r\n}\r\n\r\nvoid CEditGoal::write_position_into_node(uint index, uint32 nodeName)\r\n{\r\n\tDbg_MsgAssert(index<m_num_positions_set,(\"Bad index of %d\",index));\r\n\r\n\tScript::CStruct *p_node=SkateScript::GetNode(SkateScript::FindNamedNode(nodeName));\r\n\tp_node->AddVector(CRCD(0x7f261953,\"Pos\"),\tmp_item_positions[index].mPos.GetX(),\r\n\t\t\t\t\t\t\t\t\t\t\t\tmp_item_positions[index].mPos.GetY()+mp_item_positions[index].mHeight,\r\n\t\t\t\t\t\t\t\t\t\t\t\tmp_item_positions[index].mPos.GetZ());\r\n\tp_node->AddVector(CRCD(0x9d2d0915,\"Angles\"),0,\r\n\t\t\t\t\t\t\t\t\t\t\t\tmp_item_positions[index].mAngle-3.141592654f,\r\n\t\t\t\t\t\t\t\t\t\t\t\t0);\r\n\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t// For letter nodes, the type and model filename need to be added.\r\n\tif (index >=2 )\r\n\t{\r\n\t\tp_node->AddChecksum(CRCD(0x7321a8d6,\"Type\"),s_generate_letter_node_type_checksum(m_goal_type,index-2));\r\n\t\tp_node->AddString(CRCD(0x286a8d26,\"Model\"),s_generate_letter_model_filename(m_goal_type,index-2));\r\n\t}\t\r\n}\r\n\r\nvoid CEditGoal::WriteNodePositions()\r\n{\r\n\tfor (int i=0; i<m_num_positions_set; ++i)\r\n\t{\r\n\t\twrite_position_into_node(i,s_generate_node_name_checksum(m_level_goal_index,i));\r\n\t}\t\r\n}\r\n\r\nbool CEditGoal::GoalIsOutsideArea(float x0, float z0, float x1, float z1)\r\n{\r\n\tif (m_num_positions_set > 1)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_item_positions[1].mType==CGoalPos::RESTART,(\"Strange type for goal position 1\"));\r\n\t\tfloat x=mp_item_positions[1].mPos.GetX();\r\n\t\tfloat z=mp_item_positions[1].mPos.GetZ();\r\n\t\t\r\n\t\tif (x < x0 || x > x1 || z < z0 || z > z1)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\t\t\r\n\treturn false;\r\n}\r\n\r\nvoid CEditGoal::GetDebugInfo(Script::CStruct* p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tWriteIntoStructure(p_info);\r\n#endif\t\t\t\t \r\n}\r\n\r\n#ifdef SIZE_TEST\t\r\nvoid CEditGoal::FillNameBuffers()\r\n{\r\n\tint i;\r\n\tfor (i=0; i<MAX_GAP_TRICK_NAME_CHARS; ++i)\r\n\t{\r\n\t\tmp_trick_name[i]='?';\r\n\t}\r\n\tmp_trick_name[MAX_GAP_TRICK_NAME_CHARS]=0;\r\n\t\r\n\tfor (i=0; i<GOAL_NAME_BUFFER_SIZE-1; ++i)\r\n\t{\r\n\t\tmp_goal_name[i]='?';\r\n\t}\r\n\tmp_goal_name[GOAL_NAME_BUFFER_SIZE-1]=0;\r\n\r\n\tfor (i=0; i<PED_NAME_BUFFER_SIZE-1; ++i)\r\n\t{\r\n\t\tmp_ped_name[i]='?';\r\n\t}\r\n\tmp_ped_name[PED_NAME_BUFFER_SIZE-1]=0;\r\n\t\r\n\tfor (i=0; i<GOAL_DESCRIPTION_BUFFER_SIZE-1; ++i)\r\n\t{\r\n\t\tmp_goal_description[i]='?';\r\n\t}\r\n\tmp_goal_description[GOAL_DESCRIPTION_BUFFER_SIZE-1]=0;\r\n\t\r\n\tfor (i=0; i<GOAL_WIN_MESSAGE_BUFFER_SIZE-1; ++i)\r\n\t{\r\n\t\tmp_win_message[i]='?';\r\n\t}\r\n\tmp_win_message[GOAL_WIN_MESSAGE_BUFFER_SIZE-1]=0;\r\n}\r\n\r\nuint32 CEditGoal::GetSkateGoalMaxSize()\r\n{\r\n\tClear();\r\n\tSetType(CRCD(0x54166acd,\"Skate\"));\r\n\tMth::Vector pos;\r\n\tSetPosition(pos,0.0f,0.0f);\r\n\tpos[X]+=200.0f;\r\n\tSetPosition(pos,0.0f,0.0f);\r\n\tpos[X]+=200.0f;\r\n\tSetPosition(pos,0.0f,0.0f);\r\n\tpos[X]+=200.0f;\r\n\tSetPosition(pos,0.0f,0.0f);\r\n\tpos[X]+=200.0f;\r\n\tSetPosition(pos,0.0f,0.0f);\r\n\tpos[X]+=200.0f;\r\n\tSetPosition(pos,0.0f,0.0f);\r\n\tpos[X]+=200.0f;\r\n\tSetPosition(pos,0.0f,0.0f);\r\n\tDbg_MsgAssert(GotAllPositions(),(\"Eh?\"));\r\n\tFillNameBuffers();\r\n\t\r\n\tScript::CStruct *p_struct=new Script::CStruct;\r\n\tWriteIntoStructure(p_struct);\r\n\t\r\n\tuint8 *p_temp=(uint8*)Mem::Malloc(10000);\r\n\tuint32 size=Script::WriteToBuffer(p_struct,p_temp,10000);\r\n\tMem::Free(p_temp);\r\n\t\r\n\tdelete p_struct;\r\n\t\r\n\tClear();\r\n\treturn size;\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\n\r\nCBaseComponent* CGoalEditorComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CGoalEditorComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCGoalEditorComponent::CGoalEditorComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_GOALEDITOR );\r\n\t\r\n\tClearAllExceptParkGoals();\r\n\tClearOnlyParkGoals();\r\n\tmp_input_component=NULL;\r\n\tmp_editor_camera_component=NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCGoalEditorComponent::~CGoalEditorComponent()\r\n{\r\n\tScript::RunScript(\"goal_editor_destroy_cursor\");\r\n}\r\n\r\n// For writing to memcard\r\nvoid CGoalEditorComponent::WriteIntoStructure(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info\"));\r\n\t\t\r\n\tint goal_count=0;\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\t// Do not count goals for the park, since those are stored in the park file.\r\n\t\tif (mp_goals[i].Used() && mp_goals[i].GetLevel() != CRCD(0xe8b4b836,\"Load_Sk5Ed\"))\r\n\t\t{\r\n\t\t\t++goal_count;\r\n\t\t}\r\n\t}\t\t\r\n\tif (!goal_count)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tScript::CArray *p_goals_array=new Script::CArray;\r\n\tp_goals_array->SetSizeAndType(goal_count,ESYMBOLTYPE_STRUCTURE);\r\n\tint goal_index=0;\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\t// Does not write out the goals for the park, since those are stored in the park file.\r\n\t\tif (mp_goals[i].Used() && mp_goals[i].GetLevel() != CRCD(0xe8b4b836,\"Load_Sk5Ed\"))\r\n\t\t{\r\n\t\t\tScript::CStruct *p_goal_info=new Script::CStruct;\r\n\t\t\tmp_goals[i].WriteIntoStructure(p_goal_info);\r\n\t\t\tp_goals_array->SetStructure(goal_index++,p_goal_info);\r\n\t\t}\t\r\n\t}\r\n\tDbg_MsgAssert(goal_index==goal_count,(\"Bad goal_index ?\"));\r\n\tp_info->AddArrayPointer(CRCD(0x38dbe1d0,\"Goals\"),p_goals_array);\r\n}\r\n\r\n// This just writes in the goals for a particular level. Used when sending goal info\r\n// across the network for network goal attack games.\r\nvoid CGoalEditorComponent::WriteIntoStructure(uint32 levelScript, Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info\"));\r\n\t\r\n\tint num_goals=CountGoalsForLevel(levelScript);\r\n\t\t\t\r\n\tScript::CArray *p_goals_array=new Script::CArray;\r\n\tp_goals_array->SetSizeAndType(num_goals,ESYMBOLTYPE_STRUCTURE);\r\n\tint goal_index=0;\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used() && mp_goals[i].GetLevel()==levelScript)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_goal_info=new Script::CStruct;\r\n\t\t\tmp_goals[i].WriteIntoStructure(p_goal_info);\r\n\t\t\tp_goals_array->SetStructure(goal_index++,p_goal_info);\r\n\t\t}\t\r\n\t}\r\n\tDbg_MsgAssert(goal_index==num_goals,(\"Bad num_goals ?\"));\r\n\t\r\n\tp_info->AddArrayPointer(CRCD(0x38dbe1d0,\"Goals\"),p_goals_array);\r\n}\r\n\r\n// Writes out the goals for a particular level into a uint8* buffer.\r\n// Used when sending goal info across the network for network goal attack games.\r\nuint32 CGoalEditorComponent::WriteToBuffer(uint32 levelScript, uint8 *p_buffer, uint32 bufferSize)\r\n{\r\n\tDbg_MsgAssert(p_buffer,(\"NULL p_buffer\"));\r\n\t\r\n\t// Warning! It's feasible that we could run out of memory here ... \r\n\t// The structure could contain around 6K of stuff.\t\r\n\tScript::CStruct *p_struct=new Script::CStruct;\r\n\tWriteIntoStructure( s_convert_level( levelScript ), p_struct);\r\n\tuint32 bytes_written=Script::WriteToBuffer(p_struct, p_buffer, bufferSize);\r\n\tdelete p_struct;\r\n\t\r\n\treturn bytes_written;\r\n}\r\n\r\nuint8 *CGoalEditorComponent::ReadFromBuffer(uint32 levelScript, uint8 *p_buffer)\r\n{\r\n\tDbg_MsgAssert(p_buffer,(\"NULL p_buffer\"));\r\n\r\n\tlevelScript=s_convert_level(levelScript);\r\n\t\r\n\tScript::CStruct *p_struct=new Script::CStruct;\r\n\tuint8 *p_end=Script::ReadFromBuffer(p_struct, p_buffer);\r\n\t\r\n\t// Run through all the goals clearing any that exist for this level.\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used() && mp_goals[i].GetLevel()==levelScript)\r\n\t\t{\r\n\t\t\tmp_goals[i].Clear();\r\n\t\t}\r\n\t}\t\r\n\t// Clear this just in case it was one of those that got cleared.\r\n\tmp_current_goal=NULL;\r\n\t\r\n\tScript::CArray *p_goals_array=NULL;\r\n\tp_struct->GetArray(CRCD(0x38dbe1d0,\"Goals\"),&p_goals_array,Script::ASSERT);\r\n\r\n\tuint32 array_index=0;\r\n\tint num_goals_left_to_load=p_goals_array->GetSize();\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (!num_goals_left_to_load)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tif (!mp_goals[i].Used())\r\n\t\t{\r\n\t\t\tmp_goals[i].ReadFromStructure(p_goals_array->GetStructure(array_index++));\r\n\t\t\tmp_goals[i].SetLevel(levelScript);\r\n\t\t\t--num_goals_left_to_load;\r\n\t\t}\r\n\t}\r\n\tDbg_MsgAssert(num_goals_left_to_load == 0,(\"Could not load all the goals\"));\r\n\t\r\n\tdelete p_struct;\r\n\treturn p_end;\r\n}\r\n\r\n// For reading from memcard\r\nvoid CGoalEditorComponent::ReadFromStructure(Script::CStruct *p_info, EBoolLoadingParkGoals loadingParkGoals)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info\"));\r\n\r\n\tif (loadingParkGoals)\r\n\t{\r\n\t\tClearOnlyParkGoals();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tClearAllExceptParkGoals();\r\n\t}\r\n\t\r\n\tScript::CArray *p_goals_array=NULL;\r\n\tp_info->GetArray(CRCD(0x38dbe1d0,\"Goals\"),&p_goals_array);\r\n\tif (!p_goals_array)\r\n\t{\r\n\t\t// No Goals array means no goals.\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tuint32 array_size=p_goals_array->GetSize();\r\n\r\n\tfor (uint32 array_index=0; array_index<array_size; ++array_index)\r\n\t{\r\n\t\tScript::CStruct *p_struct=p_goals_array->GetStructure(array_index);\r\n\t\tif ( (loadingParkGoals && s_get_level_checksum(p_struct) == CRCD(0xe8b4b836,\"Load_Sk5Ed\")) ||\r\n\t\t\t (!loadingParkGoals && s_get_level_checksum(p_struct) != CRCD(0xe8b4b836,\"Load_Sk5Ed\")))\r\n\t\t{\r\n\t\t\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (!mp_goals[i].Used())\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_goals[i].ReadFromStructure(p_struct);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\t\t\t\t\r\n\t\t}\t\r\n\t}\r\n\t\r\n\tmp_current_goal=NULL;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CGoalEditorComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// ** Add code to parse the structure, and initialize the component\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CGoalEditorComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calline InitFromStructure()\r\n\t// but if that does not handle it, then will need to write a specific \r\n\t// function here. \r\n\t// The user might only want to update a single field in the structure\r\n\t// and we don't want to be asserting becasue everything is missing \r\n\t\r\n\tInitFromStructure(pParams);\r\n\r\n\r\n}\r\n\r\nvoid CGoalEditorComponent::Hide( bool shouldHide )\r\n{\r\n\tif (shouldHide)\r\n\t{\r\n\t\tScript::RunScript(\"goal_editor_destroy_cursor\");\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\t// Make sure we're using the skater's pad (TT10311)\r\n\t\tScript::CStruct *p_params=new Script::CStruct;\r\n\t\tp_params->AddInteger(CRCD(0x67e6859a,\"player\"),0);\r\n\t\tmp_input_component->InitFromStructure(p_params);\r\n\t\tdelete p_params;\r\n\t\t\r\n\t\trefresh_cursor_object();\r\n\t}\r\n}\r\n\r\nObj::CCompositeObject *CGoalEditorComponent::get_cursor()\r\n{\r\n\treturn (Obj::CCompositeObject*)Obj::CTracker::Instance()->GetObject(CRCD(0x9211b125,\"GoalEditorCursor\"));\r\n}\r\n\r\nvoid CGoalEditorComponent::refresh_cursor_object()\r\n{\r\n\tconst char *p_model_filename=\"\";\r\n\r\n\tDbg_MsgAssert(mp_current_goal,(\"NULL mp_current_goal\"));\r\n\tswitch (mp_current_goal->GetPositionType())\r\n\t{\r\n\t\tcase CGoalPos::RESTART:\r\n\t\t\tDbg_MsgAssert(mp_current_goal,(\"NULL mp_current_goal?\"));\r\n\t\t\tp_model_filename=\"gameobjects\\\\p1_cursor\\\\p1_cursor.mdl\";\r\n\t\t\tbreak;\r\n\t\tcase CGoalPos::LETTER:\r\n\t\t\tDbg_MsgAssert(mp_current_goal,(\"NULL mp_current_goal?\"));\r\n\t\t\tp_model_filename=s_generate_letter_model_filename(mp_current_goal->GetType(),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  mp_current_goal->GetCurrentLetterIndex());\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tp_model_filename=\"gameobjects\\\\goal_cursor\\\\goal_cursor.mdl\";\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\tScript::CStruct params;\r\n\tif (mp_current_goal->GetPositionType()==CGoalPos::PED)\r\n\t{\r\n\t\tparams.AddChecksum(CRCD(0x7321a8d6,\"Type\"),CRCD(0x61a741e,\"Ped\"));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tparams.AddChecksum(CRCD(0x7321a8d6,\"Type\"),0);\r\n\t\tparams.AddString(CRCD(0x286a8d26,\"Model\"),p_model_filename);\r\n\t}\r\n\t\r\n\tScript::RunScript(CRCD(0x36791e3c,\"goal_editor_create_cursor\"),&params,GetObject());\r\n\t\r\n\t// Choose whether the cursor should be allowed to be moved over kill polys.\r\n\t// Only the restart position is not allowed to, to allow letters to be placed over kill polys.\r\n\tupdate_cursor_collision_type();\r\n}\r\n\r\nvoid CGoalEditorComponent::get_pos_from_camera_component(Mth::Vector *p_pos, float *p_height, float *p_angle)\r\n{\r\n\tDbg_MsgAssert(mp_editor_camera_component,(\"NULL mp_editor_camera_component ?\"));\r\n\t*p_pos=mp_editor_camera_component->GetCursorPos();\r\n\t*p_height=mp_editor_camera_component->GetCursorHeight();\r\n\t*p_angle=mp_editor_camera_component->GetCursorOrientation();\r\n}\r\n\r\nvoid CGoalEditorComponent::update_cursor_collision_type()\r\n{\r\n\tDbg_MsgAssert(mp_editor_camera_component,(\"NULL mp_editor_camera_component ?\"));\r\n\t\r\n\t// Restart positions are not allowed to go over kill polys, otherwise the skater will\r\n\t// die straight away.\r\n\t// Note that the ped position also has to not be allowed to go over kill polys, otherwise\r\n\t// as soon as it is placed the restart cursor will be over the kill poly, and hence be stuck.\r\n\tif (mp_current_goal->GetPositionType()==CGoalPos::PED ||\r\n\t\tmp_current_goal->GetPositionType()==CGoalPos::RESTART)\r\n\t{\r\n\t\tMdl::Skate * p_skate_mod =  Mdl::Skate::Instance();\r\n\t\tif (p_skate_mod->m_cur_level == CRCD(0xe8b4b836,\"load_sk5ed\") )\r\n\t\t{\r\n\t\t\t// In the park editor, allow the cursor to move anywhere, otherwise the cursor\r\n\t\t\t// will get stuck if initialised on a kill poly.\r\n\t\t\tmp_editor_camera_component->SetSimpleCollision(true);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_editor_camera_component->SetSimpleCollision(false);\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_editor_camera_component->SetSimpleCollision(true);\r\n\t}\r\n}\r\n\r\nCEditGoal *CGoalEditorComponent::find_goal(const char *p_name)\r\n{\r\n\tuint32 current_level=s_get_current_level();\r\n\r\n\tDbg_MsgAssert(p_name,(\"NULL p_name ?\"));\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used() && \r\n\t\t\tmp_goals[i].GetLevel()==current_level && \r\n\t\t\tstricmp(mp_goals[i].GetGoalName(),p_name)==0)\r\n\t\t{\r\n\t\t\treturn &mp_goals[i];\r\n\t\t}\r\n\t}\r\n\treturn NULL;\t\t\r\n}\r\n\r\nCEditGoal *CGoalEditorComponent::find_goal(uint32 id)\r\n{\r\n\tuint32 current_level=s_get_current_level();\r\n\t\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used() && \r\n\t\t\tmp_goals[i].GetLevel()==current_level && \r\n\t\t\tmp_goals[i].GetId()==id)\r\n\t\t{\r\n\t\t\treturn &mp_goals[i];\r\n\t\t}\r\n\t}\r\n\treturn NULL;\t\t\r\n}\r\n\r\nCEditGoal *CGoalEditorComponent::find_goal(Script::CStruct *p_params)\r\n{\r\n\tuint32 id=0;\r\n\tif (p_params->GetChecksum(CRCD(0x9982e501,\"goal_id\"),&id))\r\n\t{\r\n\t\treturn find_goal(id);\r\n\t}\r\n\t\r\n\tconst char *p_name=NULL;\r\n\tif (p_params->GetString(CRCD(0xbfecc45b,\"goal_name\"),&p_name))\r\n\t{\r\n\t\treturn find_goal(p_name);\r\n\t}\r\n\t\r\n\tint index=0;\r\n\tif (p_params->GetInteger(CRCD(0x474a6a7f,\"goal_index\"),&index))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"find_goal called for an index\"));\r\n\t\t\r\n\t\tuint32 current_level=s_get_current_level();\r\n\t\t\r\n\t\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t\t{\r\n\t\t\tif (mp_goals[i].Used() && \r\n\t\t\t\tmp_goals[i].GetLevel()==current_level && \r\n\t\t\t\tmp_goals[i].GetLevelGoalIndex()==index)\r\n\t\t\t{\r\n\t\t\t\treturn &mp_goals[i];\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn NULL;\r\n\t}\r\n\t\r\n\treturn mp_current_goal;\t\r\n}\r\n\r\nint\tCGoalEditorComponent::GetNumGoals()\r\n{\r\n\tint n=0;\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used())\r\n\t\t{\r\n\t\t\t++n;\r\n\t\t}\r\n\t}\r\n\treturn n;\r\n}\r\n\r\nint CGoalEditorComponent::CountGoalsForLevel(uint32 level)\r\n{\r\n\tint n=0;\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used() && (level==0 || mp_goals[i].GetLevel()==level) && mp_goals[i].GotAllPositions())\r\n\t\t{\r\n\t\t\t++n;\r\n\t\t}\r\n\t}\r\n\treturn n;\r\n}\r\n\t\r\nvoid CGoalEditorComponent::update_camera_pos()\r\n{\r\n\tDbg_MsgAssert(mp_editor_camera_component,(\"NULL mp_editor_camera_component\"));\r\n\tDbg_MsgAssert(mp_current_goal,(\"NULL mp_current_goal\"));\r\n\t\r\n\tMth::Vector pos(0.0f,0.0f,0.0f);\r\n\tfloat height=0.0f;\r\n\tfloat angle=0.0f;\r\n\tmp_current_goal->GetPosition(&pos,&height,&angle);\r\n\t\r\n\tmp_editor_camera_component->SetCursorHeight(height);\r\n\tmp_editor_camera_component->SetCursorOrientation(angle);\r\n\tmp_editor_camera_component->SetCursorPos(pos);\r\n}\r\n\r\nvoid CGoalEditorComponent::update_cursor_position()\r\n{\r\n\tScript::CStruct params;\r\n\t\r\n\tMth::Vector cursor_pos(0.0f,0.0f,0.0f);\t\t\r\n\tfloat cursor_height=0.0f;\r\n\tfloat cursor_angle=0.0f;\r\n\tget_pos_from_camera_component(&cursor_pos,&cursor_height,&cursor_angle);\r\n\tcursor_pos[Y]+=cursor_height;\r\n\t\r\n\tparams.AddVector(CRCD(0x7f261953,\"Pos\"),cursor_pos[X],cursor_pos[Y],cursor_pos[Z]);\r\n\tparams.AddFloat(CRCD(0xff7ebaf6,\"Angle\"),mp_editor_camera_component->GetCursorOrientation());\r\n\t\r\n\tScript::RunScript(CRCD(0xdea7fe56,\"goal_editor_update_cursor_position\"),&params);\r\n}\r\n\r\nvoid CGoalEditorComponent::remove_goal(CEditGoal *p_goal)\r\n{\r\n\tDbg_MsgAssert(p_goal,(\"NULL p_goal\"));\r\n\t\r\n\tif (p_goal->Used())\r\n\t{\r\n\t\tGame::CGoalManager* p_goal_manager = Game::GetGoalManager();\r\n\t\tDbg_MsgAssert(p_goal_manager,(\"NULL p_goal_manager ?\"));\r\n\t\t\r\n\t\tif (p_goal_manager->GoalExists(p_goal->GetId()))\r\n\t\t{\r\n\t\t\tp_goal_manager->RemoveGoal(p_goal->GetId());\r\n\t\t}\t\r\n\t}\t\r\n\tp_goal->Clear();\r\n\t\r\n\tif (mp_current_goal==p_goal)\r\n\t{\r\n\t\tmp_current_goal=NULL;\r\n\t}\r\n\tif (GetNumGoals()==0)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_current_goal==NULL,(\"mp_current_goal not NULL ?\"));\r\n\t}\t\r\n}\r\n\r\nbool CGoalEditorComponent::too_close_to_another_goal_position(const Mth::Vector &pos, float height, uint32 level, int positionIndex)\r\n{\r\n\tMth::Vector pos_with_height=pos;\r\n\tpos_with_height[Y]+=height;\r\n\t\r\n\tfloat default_min_dist_allowable=Script::GetFloat(CRCD(0x71b20276,\"GoalEditor_DefaultMinDistBetweenPositions\"));\r\n\t\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used() && \r\n\t\t\tmp_goals[i].GetLevel()==level &&\r\n\t\t\tmp_goals[i].GetNumPositionsSet() > positionIndex)\r\n\t\t{\r\n\t\t\tMth::Vector p;\r\n\t\t\tmp_goals[i].GetPosition(&p, positionIndex);\r\n\t\t\tp-=pos_with_height;\r\n\t\t\tif (p.Length() < default_min_dist_allowable)\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\t\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CGoalEditorComponent::Finalize()\r\n{\r\n\t// Get the pointers to the other required components.\r\n\t\r\n\tDbg_MsgAssert(mp_input_component==NULL,(\"mp_input_component not NULL ?\"));\r\n\tmp_input_component = GetInputComponentFromObject(GetObject());\r\n\tDbg_MsgAssert(mp_input_component,(\"CGoalEditorComponent requires parent object to have an input component!\"));\r\n\r\n\tDbg_MsgAssert(mp_editor_camera_component==NULL,(\"mp_editor_camera_component not NULL ?\"));\r\n\tmp_editor_camera_component = GetEditorCameraComponentFromObject(GetObject());\r\n\tDbg_MsgAssert(mp_editor_camera_component,(\"CGoalEditorComponent requires parent object to have an EditorCamera component!\"));\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CGoalEditorComponent::Update()\r\n{\r\n\tif (mp_current_goal)\r\n\t{\r\n\t\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\tif (control_pad.m_x.GetTriggered())\r\n\t\t{\r\n\t\t\tcontrol_pad.m_x.ClearTrigger();\r\n\t\r\n\t\t\tMth::Vector cursor_pos(0.0f,0.0f,0.0f);\r\n\t\t\tfloat cursor_height=0.0f;\r\n\t\t\tfloat cursor_angle=0.0f;\r\n\t\t\tget_pos_from_camera_component(&cursor_pos,&cursor_height,&cursor_angle);\r\n\t\t\t\r\n\t\t\tif ((mp_current_goal->GetPositionType() == CGoalPos::RESTART && \r\n\t\t\t\ttoo_close_to_another_goal_position(cursor_pos,cursor_height,mp_current_goal->GetLevel(),0)) || // 0 = ped\r\n\t\t\t\t(mp_current_goal->GetPositionType() == CGoalPos::PED && \r\n\t\t\t\ttoo_close_to_another_goal_position(cursor_pos,cursor_height,mp_current_goal->GetLevel(),1))) // 1 = restart\r\n\t\t\t{\r\n\t\t\t\t// Can't place restart positions too close to another goal's ped position, or\r\n\t\t\t\t// ped positions too close to another goal's restart position.\r\n\t\t\t\tScript::RunScript(CRCD(0xaebc7020,\"goal_editor_play_placement_fail_sound\"),NULL,GetObject());\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (mp_current_goal->SetPosition(cursor_pos,cursor_height,cursor_angle))\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(CRCD(0x718b071b,\"goal_editor_play_placement_success_sound\"),NULL,GetObject());\r\n\t\t\t\t\t// Once a position is set, the cursor model will need to change for the next position.\r\n\t\t\t\t\trefresh_cursor_object();\r\n\t\t\t\t\tupdate_camera_pos();\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(CRCD(0xaebc7020,\"goal_editor_play_placement_fail_sound\"),NULL,GetObject());\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tif (mp_current_goal->PlacedLastPosition())\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript(CRCD(0x89119628,\"goal_editor_finished_placing_letters\"),NULL,GetObject());\r\n\t\t\t}\r\n\t\t}\t\r\n\t\r\n\t\tif (control_pad.m_triangle.GetTriggered())\r\n\t\t{\r\n\t\t\tcontrol_pad.m_triangle.ClearTrigger();\r\n\t\r\n\t\t\tMth::Vector cursor_pos(0.0f,0.0f,0.0f);\r\n\t\t\tfloat cursor_height=0.0f;\r\n\t\t\tfloat cursor_angle=0.0f;\r\n\t\t\tget_pos_from_camera_component(&cursor_pos,&cursor_height,&cursor_angle);\r\n\t\r\n\t\t\tDbg_MsgAssert(mp_current_goal,(\"NULL mp_current_goal\"));\r\n\t\t\tif ((mp_current_goal->GetPositionType() == CGoalPos::RESTART && \r\n\t\t\t\ttoo_close_to_another_goal_position(cursor_pos,cursor_height,mp_current_goal->GetLevel(),0)) || // 0 = ped\r\n\t\t\t\t(mp_current_goal->GetPositionType() == CGoalPos::PED && \r\n\t\t\t\ttoo_close_to_another_goal_position(cursor_pos,cursor_height,mp_current_goal->GetLevel(),1))) // 1 = restart\r\n\t\t\t{\r\n\t\t\t\t// Can't place restart positions too close to another goal's ped position, or\r\n\t\t\t\t// ped positions too close to another goal's restart position.\r\n\t\t\t\tScript::RunScript(CRCD(0xade100d6,\"goal_editor_play_backup_fail_sound\"),NULL,GetObject());\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (mp_current_goal->BackUp(cursor_pos,cursor_height,cursor_angle))\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(CRCD(0xfa275cc5,\"goal_editor_play_backup_success_sound\"),NULL,GetObject());\r\n\t\t\t\t\trefresh_cursor_object();\r\n\t\t\t\t\tupdate_camera_pos();\r\n\t\t\t\t}\t\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(CRCD(0xade100d6,\"goal_editor_play_backup_fail_sound\"),NULL,GetObject());\r\n\t\t\t\t}\t\t\t\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t}\r\n\t\r\n\tupdate_cursor_position();\r\n}\r\n\r\nvoid CGoalEditorComponent::ClearAllExceptParkGoals()\r\n{\r\n\tfor (uint i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used() && mp_goals[i].GetLevel() != CRCD(0xe8b4b836,\"Load_Sk5Ed\"))\r\n\t\t{\r\n\t\t\tmp_goals[i].Clear();\r\n\t\t}\t\r\n\t}\r\n\t\r\n\tmp_current_goal=NULL;\r\n}\t\r\n\r\nvoid CGoalEditorComponent::ClearOnlyParkGoals()\r\n{\r\n\tfor (uint i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used() && mp_goals[i].GetLevel() == CRCD(0xe8b4b836,\"Load_Sk5Ed\"))\r\n\t\t{\r\n\t\t\tmp_goals[i].Clear();\r\n\t\t}\t\r\n\t}\t\r\n\t\r\n\tmp_current_goal=NULL;\r\n}\r\n\r\nvoid CGoalEditorComponent::CleanOutUnfinishedGoals()\r\n{\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used() && !mp_goals[i].GotAllPositions())\r\n\t\t{\r\n\t\t\tmp_goals[i].Clear();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CGoalEditorComponent::NewGoal()\r\n{\r\n\tCleanOutUnfinishedGoals();\r\n\r\n\tuint32 current_level=s_get_current_level();\r\n\t\r\n\tint level_goal_index=0;\r\n\t\t\r\n\twhile (true)\r\n\t{\r\n\t\tbool found_suitable_index=true;\r\n\t\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t\t{\r\n\t\t\tif (mp_goals[i].Used() && \r\n\t\t\t\tmp_goals[i].GotAllPositions() && \r\n\t\t\t\tmp_goals[i].GetLevel()==current_level && \r\n\t\t\t\tmp_goals[i].GetLevelGoalIndex()==level_goal_index)\r\n\t\t\t{\r\n\t\t\t\t++level_goal_index;\r\n\t\t\t\tfound_suitable_index=false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\t\r\n\t\tif (found_suitable_index)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\t\t\r\n\tDbg_MsgAssert(level_goal_index<MAX_GOALS_PER_LEVEL,(\"Bad level_goal_index!\"));\r\n\t\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (!mp_goals[i].Used())\r\n\t\t{\r\n\t\t\tmp_current_goal=&mp_goals[i];\r\n\t\t\tmp_current_goal->Clear();\r\n\t\t\tmp_current_goal->SetUsedFlag(true);\r\n\t\t\r\n\t\t\tmp_current_goal->SetLevel(current_level);\r\n\t\t\tmp_current_goal->SetLevelGoalIndex(level_goal_index);\r\n\t\t\t\r\n\t\t\trefresh_cursor_object();\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\t\t\t\t\t\t\t\r\n\tDbg_MsgAssert(0,(\"Exceeded CGoalEditorComponent::MAX_GOALS_TOTAL of %d\",MAX_GOALS_TOTAL));\r\n}\r\n\r\nvoid CGoalEditorComponent::SetGoalType(uint32 type)\r\n{\r\n\tDbg_MsgAssert(mp_current_goal,(\"NULL mp_current_goal\"));\r\n\tmp_current_goal->SetType(type);\r\n}\r\n\t\r\nbool CGoalEditorComponent::ThereAreGoalsOutsideArea(float x0, float z0, float x1, float z1)\r\n{\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used() && mp_goals[i].GetLevel()==CRCD(0xe8b4b836,\"Load_Sk5Ed\"))\r\n\t\t{\r\n\t\t\tif (mp_goals[i].GoalIsOutsideArea(x0,z0,x1,z1))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\t\r\n\treturn false;\r\n}\r\n\r\nvoid CGoalEditorComponent::DeleteGoalsOutsideArea(float x0, float z0, float x1, float z1)\r\n{\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used() && \r\n\t\t\tmp_goals[i].GetLevel()==CRCD(0xe8b4b836,\"Load_Sk5Ed\") &&\r\n\t\t\tmp_goals[i].GoalIsOutsideArea(x0,z0,x1,z1))\r\n\t\t{\r\n\t\t\tremove_goal(&mp_goals[i]);\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\nvoid CGoalEditorComponent::RefreshGoalPositionsUsingCollisionCheck()\r\n{\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used() && \r\n\t\t\tmp_goals[i].GetLevel()==CRCD(0xe8b4b836,\"Load_Sk5Ed\"))\r\n\t\t{\r\n\t\t\tmp_goals[i].RefreshPositionsUsingCollisionCheck();\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\nvoid CGoalEditorComponent::RefreshGapGoalsAfterGapRemovedFromPark(int gapNumber)\r\n{\r\n\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t{\r\n\t\tif (mp_goals[i].Used() && \r\n\t\t\tmp_goals[i].GetLevel()==CRCD(0xe8b4b836,\"Load_Sk5ed\") && \r\n\t\t\tmp_goals[i].GetType()==CRCD(0x61c5d092,\"Gap\"))\r\n\t\t{\r\n\t\t\tmp_goals[i].RemoveGapAndReorder(gapNumber);\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CGoalEditorComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | EditedGoalAddGap\r\n\t\tcase 0xab710f3: // EditedGoalAddGap\r\n\t\t{\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tint gap_number=0;\r\n\t\t\t\tpParams->GetInteger(CRCD(0x3ac9ab5e,\"gap_number\"),&gap_number);\r\n\t\t\t\tp_goal->AddGap(gap_number);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | EditedGoalRemoveGap\r\n\t\tcase 0x5c155a29: // EditedGoalRemoveGap\r\n\t\t{\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tint gap_number=0;\r\n\t\t\t\tpParams->GetInteger(CRCD(0x3ac9ab5e,\"gap_number\"),&gap_number);\r\n\t\t\t\tp_goal->RemoveGap(gap_number);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | EditedGoalGotGap\r\n\t\tcase 0xfb279560: // EditedGoalGotGap\r\n\t\t{\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tint gap_number=0;\r\n\t\t\t\tpParams->GetInteger(CRCD(0x3ac9ab5e,\"gap_number\"),&gap_number);\r\n\t\t\t\tif (p_goal->GotGap(gap_number))\r\n\t\t\t\t{\r\n\t\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | AddKeyComboSet\r\n\t\tcase 0xcca11c78: // AddKeyComboSet\r\n\t\t{\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tint set_index=0;\r\n\t\t\t\tpParams->GetInteger(CRCD(0xeb7d6498,\"set_index\"),&set_index);\r\n\t\t\t\tint spin=0;\r\n\t\t\t\tpParams->GetInteger(CRCD(0xedf5db70,\"spin\"),&spin);\r\n\t\t\t\tint num_taps=0;\r\n\t\t\t\tpParams->GetInteger(CRCD(0xa4bee6a1,\"num_taps\"),&num_taps);\r\n\t\t\t\tp_goal->AddKeyComboSet(set_index,\r\n\t\t\t\t\t\t\t\t\t   pParams->ContainsFlag(CRCD(0x687e2c25,\"require_perfect\")),\r\n\t\t\t\t\t\t\t\t\t   spin,\r\n\t\t\t\t\t\t\t\t\t   num_taps);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | RemoveKeyComboSet\r\n\t\tcase 0x1d30a7b6: // RemoveKeyComboSet\r\n\t\t{\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tint set_index=0;\r\n\t\t\t\tpParams->GetInteger(CRCD(0xeb7d6498,\"set_index\"),&set_index);\r\n\t\t\t\tp_goal->RemoveKeyComboSet(set_index);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | GetKeyComboSet\r\n\t\tcase 0xe5ed63b7: // GetKeyComboSet\r\n\t\t{\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tint set_index=0;\r\n\t\t\t\tpParams->GetInteger(CRCD(0xeb7d6498,\"set_index\"),&set_index);\r\n\t\t\t\t\r\n\t\t\t\tSPreDefinedKeyComboSet *p_keycombo_set=p_goal->GetKeyComboSet(set_index);\r\n\t\t\t\tif (p_keycombo_set)\r\n\t\t\t\t{\r\n\t\t\t\t\tpScript->GetParams()->AddInteger(CRCD(0xedf5db70,\"Spin\"),p_keycombo_set->mSpin*180);\r\n\t\t\t\t\tpScript->GetParams()->AddInteger(CRCD(0xa4bee6a1,\"num_taps\"),p_keycombo_set->mNumTaps);\r\n\t\t\t\t\tif (p_keycombo_set->mRequirePerfect)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpScript->GetParams()->AddChecksum(NONAME,CRCD(0x687e2c25,\"require_perfect\"));\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | RemoveGoalSpecificFlag\r\n\t\tcase 0x3ebd2c9: // RemoveGoalSpecificFlag\r\n\t\t{\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tp_goal->RemoveGoalSpecificFlag(pParams);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | SetGoalSpecificParams\r\n\t\tcase 0x47208c6d: // SetGoalSpecificParams\r\n\t\t{\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tp_goal->ReadGoalSpecificParams(pParams);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | FlagGoalAsWon\r\n\t\tcase 0x769309e1: // FlagGoalAsWon\r\n\t\t{\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tp_goal->FlagAsWon();\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t\r\n\t\t// @script | FindUnfinishedGoal\r\n\t\tcase 0x88d54a10: // FindUnfinishedGoal\r\n\t\t{\r\n\t\t\tuint32 type=0;\r\n\t\t\tpParams->GetChecksum(\"type\",&type);\r\n\t\t\t\r\n\t\t\tmp_current_goal=NULL;\r\n\t\t\t\r\n\t\t\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (mp_goals[i].Used() && mp_goals[i].GetType()==type && !mp_goals[i].GotAllPositions())\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_current_goal=&mp_goals[i];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (!mp_current_goal)\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\t\r\n\t\t\tbreak;\t\r\n\t\t}\r\n\r\n\t\tcase 0xff9e8752: // GoalExists\r\n\t\t{\r\n\t\t\tif (!find_goal(pParams))\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\t\t\t\t\t\t\t\t\t\r\n\t\t\r\n        // @script | NewEditorGoal | \r\n\t\tcase 0x259c59dd: // NewEditorGoal\r\n\t\t{\r\n\t\t\tNewGoal();\r\n\t\t\tDbg_MsgAssert(mp_current_goal,(\"NULL mp_current_goal ?\"));\r\n\t\t\t//printf(\"Max skate goal size = %d\\n\",mp_current_goal->GetSkateGoalMaxSize());\r\n\t\t\t\r\n\t\t\tpScript->GetParams()->AddChecksum(\"goal_id\",mp_current_goal->GetId());\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\t// @script | RemovedCreatedGoal |\r\n\t\tcase 0x1f80b5ae: // RemovedCreatedGoal\r\n\t\t{\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tremove_goal(p_goal);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | GoalHasAllPositionsSet |\r\n\t\tcase 0x26848221: // GoalHasAllPositionsSet\r\n\t\t{\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tif (!p_goal->GotAllPositions())\r\n\t\t\t\t{\r\n\t\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\t\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | SetCurrentEditorGoal |\r\n\t\tcase 0xfdb2c514: // SetCurrentEditorGoal\r\n\t\t{\r\n\t\t\tmp_current_goal=find_goal(pParams);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        // @script | SetEditorGoalType | \r\n\t\tcase 0x98abbd09: // SetEditorGoalType\r\n\t\t{\r\n\t\t\tuint32 type=0;\r\n\t\t\tpParams->GetChecksum(\"type\",&type);\r\n\t\t\t\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tp_goal->SetType(type);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | SetEditorGoalDescription | \r\n\t\tcase 0x66a33157: // SetEditorGoalDescription\r\n\t\t{\r\n\t\t\tconst char *p_text=\"\";\r\n\t\t\tpParams->GetString(\"text\",&p_text);\r\n\t\t\t\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tp_goal->SetGoalDescription(p_text);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | SetEditorGoalWinMessage | \r\n\t\tcase 0x7aabbc09: // SetEditorGoalWinMessage\r\n\t\t{\r\n\t\t\tconst char *p_text=\"\";\r\n\t\t\tpParams->GetString(\"text\",&p_text);\r\n\t\t\t\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tp_goal->SetWinMessage(p_text);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | GetCurrentEditedGoalInfo\r\n\t\tcase 0x69b872e3: // GetCurrentEditedGoalInfo\r\n\t\t{\r\n\t\t\tif (mp_current_goal)\r\n\t\t\t{\r\n\t\t\t\tmp_current_goal->WriteIntoStructure(pScript->GetParams());\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | GetEditedGoalsInfo\r\n\t\t// @parmopt name | Level | If specified, it will only include goals for this level.\r\n\t\t// The level is specified using the name of its load script.\r\n\t\tcase 0x96f11bd3: // GetEditedGoalsInfo\r\n\t\t{\r\n\t\t\tuint32 level=s_get_level_checksum(pParams);\r\n\t\t\t\r\n\t\t\tint n=CountGoalsForLevel(level);\r\n\t\t\tif (n==0)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tScript::CArray *p_info_array=new Script::CArray;\r\n\t\t\tp_info_array->SetSizeAndType(n, ESYMBOLTYPE_STRUCTURE);\r\n\t\t\tint index=0;\r\n\t\t\t\r\n\t\t\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (mp_goals[i].Used() && (level==0 || mp_goals[i].GetLevel()==level) && mp_goals[i].GotAllPositions())\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct *p_info=new Script::CStruct;\r\n\t\t\t\t\tmp_goals[i].WriteIntoStructure(p_info);\r\n\t\t\t\t\tp_info_array->SetStructure(index++,p_info);\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tDbg_MsgAssert(index==n,(\"Eh?\"));\r\n\t\t\t\r\n\t\t\tpScript->GetParams()->AddArrayPointer(\"EditedGoalsInfo\",p_info_array);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | GetNumEditedGoals\t\r\n\t\t// @parmopt name | Level | If specified, it will only count goals for this level.\r\n\t\t// The level is specified using the name of its load script.\r\n\t\tcase 0x96874358: // GetNumEditedGoals\r\n\t\t{\r\n\t\t\tuint32 level=s_get_level_checksum(pParams);\r\n\t\t\t\r\n\t\t\tint n=CountGoalsForLevel(level);\r\n\t\t\tif (level==0 && pParams->ContainsFlag(CRCD(0xb99f6330,\"ExcludeParkEditorGoals\")))\r\n\t\t\t{\r\n\t\t\t\tn-=CountGoalsForLevel(CRCD(0xe8b4b836,\"Load_Sk5Ed\"));\r\n\t\t\t\tDbg_MsgAssert(n>=0,(\"More editor goals (%d) than total goals? (%d)\",CountGoalsForLevel(CRCD(0xe8b4b836,\"Load_Sk5Ed\")),CountGoalsForLevel(0)));\r\n\t\t\t}\r\n\t\t\tpScript->GetParams()->AddInteger(\"NumGoals\",n);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | GetCurrentEditedGoalId\r\n\t\tcase 0x5bd8050a: // GetCurrentEditedGoalId\r\n\t\t{\r\n\t\t\tpScript->GetParams()->RemoveComponent(\"goal_id\");\r\n\t\t\tif (mp_current_goal)\r\n\t\t\t{\r\n\t\t\t\tpScript->GetParams()->AddChecksum(\"goal_id\",mp_current_goal->GetId());\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | WriteEditedGoalNodePositions\r\n\t\tcase 0x5408ac04: // WriteEditedGoalNodePositions\r\n\t\t{\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tp_goal->WriteNodePositions();\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | AddEditedGoalToGoalManager\r\n\t\tcase 0xb525b113: // AddEditedGoalToGoalManager\r\n\t\t{\r\n\t\t\tCEditGoal *p_goal=find_goal(pParams);\r\n\t\t\tif (p_goal)\r\n\t\t\t{\r\n\t\t\t\tp_goal->AddGoalToGoalManager(pParams->ContainsFlag(CRCD(0xc6322a25,\"MarkUnbeaten\")));\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | SetEditorGoalName |\r\n\t\tcase 0x4a569426: // SetEditorGoalName\r\n\t\t{\r\n\t\t\tconst char *p_name=\"\";\r\n\t\t\tif (mp_current_goal && pParams->GetString(\"Name\",&p_name))\r\n\t\t\t{\r\n\t\t\t\tmp_current_goal=find_goal(pParams);\r\n\t\t\t\tmp_current_goal->SetGoalName(p_name);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | SetEditorPedName |\r\n\t\tcase 0x410821df: // SetEditorPedName\r\n\t\t{\r\n\t\t\tconst char *p_name=\"\";\r\n\t\t\tif (mp_current_goal && pParams->GetString(\"Name\",&p_name))\r\n\t\t\t{\r\n\t\t\t\tmp_current_goal=find_goal(pParams);\r\n\t\t\t\tmp_current_goal->SetPedName(p_name);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | MaxEditedGoalsReached | Returns true if there is no space for any more\r\n\t\t// goals, or if the max goals per level has been reached for this level.\r\n\t\t// @parmopt name | Level | The level, specified using its load script name.\r\n\t\tcase 0x60288abe: // MaxEditedGoalsReached\r\n\t\t{\r\n\t\t\tif (GetNumGoals()==MAX_GOALS_TOTAL)\r\n\t\t\t{\r\n\t\t\t\t// Definitely reached the max if got MAX_GOALS_TOTAL\r\n\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Otherwise, count up how many goals exist for this level, \r\n\t\t\t// and compare with MAX_GOALS_PER_LEVEL\r\n\t\t\tuint32 level=s_get_level_checksum(pParams);\r\n\t\t\tDbg_MsgAssert(level,(\"\\n%s\\nNo Level specified\",pScript->GetScriptInfo()));\r\n\t\t\t\r\n\t\t\tif (CountGoalsForLevel(level) >= MAX_GOALS_PER_LEVEL)\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | EditGoal |\r\n\t\tcase 0x831eca10: // EditGoal\r\n\t\t\tmp_current_goal=find_goal(pParams);\r\n\t\t\tif (mp_current_goal)\r\n\t\t\t{\r\n\t\t\t\tmp_current_goal->EditGoal();\r\n\t\t\t\tupdate_camera_pos();\r\n\t\t\t\trefresh_cursor_object();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | NukeAllGoals\t\r\n\t\tcase 0xdba8e3fc: // NukeAllGoals\r\n\t\t{\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0x98439808,\"OnlyParkEditorGoals\")))\r\n\t\t\t{\r\n\t\t\t\tClearOnlyParkGoals();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tClearAllExceptParkGoals();\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | GetMaxGoalsPerLevel\t\t\r\n\t\tcase 0xd7258335: // GetMaxGoalsPerLevel\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddInteger(CRCD(0x8bc2e0db,\"max_goals\"),MAX_GOALS_PER_LEVEL);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0x9e5a634a: // SetGoalScore\r\n\t\t{\r\n\t\t\tmp_current_goal=find_goal(pParams);\r\n\t\t\tif (mp_current_goal)\r\n\t\t\t{\r\n\t\t\t\tint score=0;\r\n\t\t\t\tif (pParams->GetInteger(NONAME,&score))\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_current_goal->SetScore(score);\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | SetGoalTimeLimit\r\n\t\tcase 0x7d5073f6: // SetGoalTimeLimit\r\n\t\t{\r\n\t\t\tmp_current_goal=find_goal(pParams);\r\n\t\t\tif (mp_current_goal)\r\n\t\t\t{\r\n\t\t\t\tint time=120;\r\n\t\t\t\tif (pParams->GetInteger(NONAME,&time))\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_current_goal->SetTimeLimit(time);\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | SetGoalControlType\r\n\t\tcase 0xec316a9c: // SetGoalControlType\r\n\t\t{\r\n\t\t\tmp_current_goal=find_goal(pParams);\r\n\t\t\tif (mp_current_goal)\r\n\t\t\t{\r\n\t\t\t\tuint32 control_type=CRCD(0x54166acd,\"skate\");\r\n\t\t\t\tif (pParams->GetChecksum(NONAME,&control_type))\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_current_goal->SetControlType(control_type);\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | RefreshGoalCursorPosition\r\n\t\tcase 0x20b566b1: // RefreshGoalCursorPosition\r\n\t\t{\r\n\t\t\tif (mp_current_goal)\r\n\t\t\t{\r\n\t\t\t\tMth::Vector cursor_pos(0.0f,0.0f,0.0f);\t\t\r\n\t\t\t\tfloat angle=0.0f;\r\n\t\t\t\tfloat height=0.0f;\r\n\t\t\t\tmp_current_goal->GetPosition(&cursor_pos,&height,&angle);\r\n\t\t\t\t\r\n\t\t\t\tScript::CStruct params;\r\n\t\t\t\tparams.AddVector(CRCD(0x7f261953,\"Pos\"),cursor_pos[X],cursor_pos[Y]+height,cursor_pos[Z]);\r\n\t\t\t\tparams.AddFloat(CRCD(0xff7ebaf6,\"Angle\"),angle);\r\n\t\t\t\tScript::RunScript(CRCD(0xdea7fe56,\"goal_editor_update_cursor_position\"),&params);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalEditorComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CGoalEditorComponent::GetDebugInfo\"));\r\n\r\n\tint num_goals=GetNumGoals();\r\n\tp_info->AddInteger(\"NumGoals\",num_goals);\r\n\tif (mp_current_goal)\r\n\t{\r\n\t\tScript::CStruct *p_struct=new Script::CStruct;\r\n\t\tmp_current_goal->GetDebugInfo(p_struct);\r\n\t\tp_info->AddStructurePointer(\"CurrentGoal\",p_struct);\r\n\t}\r\n\t\r\n\tif (num_goals)\r\n\t{\r\n\t\tScript::CArray *p_array=new Script::CArray;\r\n\t\tp_array->SetSizeAndType(num_goals,ESYMBOLTYPE_STRUCTURE);\r\n\t\tint index=0;\r\n\t\tfor (int i=0; i<MAX_GOALS_TOTAL; ++i)\r\n\t\t{\r\n\t\t\tif (mp_goals[i].Used())\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct *p_struct=new Script::CStruct;\r\n\t\t\t\tmp_goals[i].GetDebugInfo(p_struct);\r\n\t\t\t\tp_array->SetStructure(index++,p_struct);\r\n\t\t\t}\t\r\n\t\t}\r\n\t\tDbg_MsgAssert(index==num_goals,(\"Bad num_goals ?\"));\r\n\t\tp_info->AddArrayPointer(\"Goals\",p_array);\r\n\t}\r\n\t\t\r\n// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\nObj::CGoalEditorComponent *GetGoalEditor()\r\n{\r\n\tObj::CCompositeObject *p_obj=(Obj::CCompositeObject*)Obj::CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0x81f01058,\"GoalEditor\"));\r\n\tDbg_MsgAssert(p_obj,(\"No GoalEditor object\"));\r\n\tObj::CGoalEditorComponent *p_goal_editor=GetGoalEditorComponentFromObject(p_obj);\r\n\tDbg_MsgAssert(p_goal_editor,(\"No goal editor component ???\"));\r\n\t\r\n\treturn p_goal_editor;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/GoalEditorComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       GoalEditorComponent.h\r\n//* OWNER:          Kendall Harrison\r\n//* CREATION DATE:  3/21/2003\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_GOALEDITORCOMPONENT_H__\r\n#define __COMPONENTS_GOALEDITORCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n// Replace this with the CRCD of the component you are adding\r\n#define\t\tCRC_GOALEDITOR CRCD(0x81f01058,\"GoalEditor\")\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or \r\n//  given an object\t\t\t\t \r\n#define\t\tGetGoalEditorComponent() ((Obj::CGoalEditorComponent*)GetComponent(CRC_GOALEDITOR))\r\n#define\t\tGetGoalEditorComponentFromObject(pObj) ((Obj::CGoalEditorComponent*)(pObj)->GetComponent(CRC_GOALEDITOR))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\tclass CModel;\r\n}\r\n\r\nnamespace Obj\r\n{\r\nenum\r\n{\r\n\t// The number of nodes used by a goal\r\n\tMAX_POSITIONS_PER_GOAL=8,\r\n\t// Limited to 20 because a ped will need to be created for each goal\r\n\t// Note: If this value is changed, it would be a good idea to update VERSION_CREATEDGOALS\r\n\t// in memcard.q too, to prevent loading old mem card saves that may have more goals than\r\n\t// the new value allows.\r\n\tMAX_GOALS_PER_LEVEL=10,\r\n\t\r\n\t// Note: MAX_POSITIONS_PER_GOAL*MAX_GOALS_PER_LEVEL nodes will get added to the NodeArray\r\n\t\r\n\t// The total number of goals stored in the GoalEditor composite object.\r\n\tMAX_GOALS_TOTAL=50,\r\n};\r\n\r\nclass CInputComponent;\r\nclass CEditorCameraComponent;\r\n\r\nclass CGoalPos\r\n{\r\npublic:\r\n\tenum EType\r\n\t{\r\n\t\tNONE,\r\n\t\tPED,\r\n\t\tRESTART,\r\n\t\tLETTER,\r\n\t};\r\n\t\r\n\tEType mType;\r\n\tMth::Vector mPos;\r\n\tfloat mHeight;\r\n\tfloat mAngle;\r\n};\t\r\n\r\nstruct SPreDefinedKeyComboSet\r\n{\r\n\tuint8 mSetIndex; // Index into the cag_skatetris_key_combos array defined in goal_editor.q\r\n\t\r\n\t// Note: These three are not really used at the moment. They used to be settable from menus,\r\n\t// but are now all left as zero for simplicity, with only a global spin value settable for the\r\n\t// whole goal.\r\n\t// So if it stays this way, there is no need for this structure, could just have a simple array\r\n\t// of set indices instead.\r\n\tuint8 mRequirePerfect;\r\n\tuint8 mSpin; // Actually the spin/180\r\n\tuint8 mNumTaps;\r\n};\r\n\t\r\nclass CEditGoal\r\n{\r\n\t// Identifies which level this goal is for via the level load script name.\r\n\tuint32 m_level_script;\r\n\t\r\n\tenum\r\n\t{\r\n\t\t// These needs to be at least 1 bigger than the max_length value passed to\r\n\t\t// the create_onscreen_keyboard script.\r\n\t\tGOAL_NAME_BUFFER_SIZE=50,\r\n\t\tPED_NAME_BUFFER_SIZE=21,\r\n\t\tGOAL_DESCRIPTION_BUFFER_SIZE=100,\r\n\t\tGOAL_WIN_MESSAGE_BUFFER_SIZE=100,\r\n\t};\r\n\tchar mp_goal_name[GOAL_NAME_BUFFER_SIZE];\r\n\tchar mp_ped_name[PED_NAME_BUFFER_SIZE];\r\n\tchar mp_goal_description[GOAL_DESCRIPTION_BUFFER_SIZE];\r\n\tchar mp_win_message[GOAL_WIN_MESSAGE_BUFFER_SIZE];\r\n\r\n\r\n\tuint32 m_goal_type;\r\n\t\r\n\tCGoalPos mp_item_positions[MAX_POSITIONS_PER_GOAL];\r\n\tuint8 m_num_positions_required;\r\n\tuint8 m_num_positions_set;\r\n\tuint8 m_current_position_index;\r\n\tuint8 m_placed_last_position;\r\n\t\r\n\tuint8 m_has_won_goal;\r\n\t\r\n\tuint8 m_used; // Indicates whether this slot in the array of CEditGoals is used or not.\r\n\t\r\n\t// m_level_goal_index has a value from 0 to MAX_GOALS_PER_LEVEL-1\r\n\t// From the level goal index is also derived the goal's id string\r\n\t// which the goal manager needs when creating the goal ped arrows\r\n\t// and the goal id, which is just the checksum of the id string. \r\n\tint m_level_goal_index;\r\n\t\r\n\tint m_time_limit;\r\n\t\r\n\t// One of skate, walk, junkercar or rallycar\r\n\tuint32 m_control_type;\r\n\t\r\n\t// The following are goal specific params.\r\n\t// Could have stored these in a CStruct instead, but that would have caused varying\r\n\t// memory requirements depending on how many goals the user had added, making it harder to test.\r\n\t\r\n\t// The score value for high-score, high-combo etc.\r\n\tint m_score;\r\n\r\n\t// Skatetris specific\r\n\tint m_acceleration_interval;\r\n\tfloat m_acceleration_percent;\r\n\tint m_trick_time;\r\n\tint m_time_to_stop_adding_tricks;\r\n\tint m_max_tricks;\r\n\t\r\n\tint m_spin;\r\n\r\n\t// Combo skatetris specific\r\n\tbool m_single_combo;\r\n\tint m_combo_size;\r\n\r\n\t// Tricktris specific\r\n\tint m_tricktris_block_size;\r\n\tint m_tricktris_total_to_win;\r\n\t\r\n\tenum\r\n\t{\r\n\t\tMAX_COMBO_SETS=10\r\n\t};\t\r\n\tSPreDefinedKeyComboSet mp_combo_sets[MAX_COMBO_SETS];\r\n\tint m_num_combo_sets;\r\n\t// Used for writing/reading the above array to mem card.\r\n\tvoid write_combo_sets(Script::CStruct *p_info);\r\n\tvoid read_combo_sets(Script::CStruct *p_info);\r\n\t\r\n\t// Generates the goal_tetris_key_combos array and inserts it into p_info, for sending to\r\n\t// the goal manager.\r\n\tvoid generate_key_combos_array(Script::CStruct *p_info);\r\n\t\r\n\t\r\n\tenum\r\n\t{\r\n\t\tMAX_GAPS=10,\r\n\t\tMAX_GAP_TRICK_NAME_CHARS=50,\r\n\t};\r\n\tuint8 mp_gap_numbers[MAX_GAPS];\r\n\tuint8 m_num_gaps;\r\n\tchar mp_trick_name[MAX_GAP_TRICK_NAME_CHARS+1];\r\n\t\r\n\t\r\n\tvoid write_position_into_node(uint index, uint32 nodeName);\r\n\tvoid add_goal_params(Script::CStruct *p_params);\r\n\tuint32 generate_marker_object_name(int index);\r\n\tuint32 generate_goal_object_name(int index);\r\n\tvoid create_marker(int index);\r\n\tvoid delete_marker(int index);\r\n\tbool position_too_close_to_existing_positions(const Mth::Vector& pos);\r\n\tbool position_ok_to_place(const Mth::Vector& pos, float height);\r\n\r\n\tvoid refresh_position_using_collision_check(uint positionIndex);\r\n\r\npublic:\r\n\tenum EWriteDest\r\n\t{\r\n\t\tNOT_WRITING_TO_GOAL_MANAGER=0,\r\n\t\tWRITING_TO_GOAL_MANAGER=1,\r\n\t};\t\r\nprivate:\r\n\t\r\n\t// The dest parameter determines the format in which the combo sets are written out.\r\n\t// When generating params for the goal manager, the full goal_tetris_key_combos array is\r\n\t// generated. When writing to mem card the chosen pre-defined set numbers are written instead,\r\n\t// so that after loading they can still be edited.\r\n\tvoid write_skatetris_params(Script::CStruct *p_info, EWriteDest dest);\r\n\tvoid read_skatetris_params(Script::CStruct *p_info);\r\n\t\r\npublic:\r\n\tCEditGoal();\r\n\t~CEditGoal();\r\n\t\r\n\tvoid Clear();\r\n\r\n\t#ifdef SIZE_TEST\t\r\n\t// For testing, this fills the name buffers, eg mp_goal_name, mp_trick_name etc, to their\r\n\t// max size.\r\n\tvoid FillNameBuffers();\r\n\tuint32 GetSkateGoalMaxSize();\r\n\t#endif\r\n\t\r\n\tbool Used() {return m_used;}\r\n\tvoid SetUsedFlag(bool used) {m_used=used;}\r\n\t\r\n\tvoid SetLevelGoalIndex(uint index) {m_level_goal_index=index;}\r\n\tint GetLevelGoalIndex() {return m_level_goal_index;}\r\n\t\r\n\tuint32 GetId();\r\n\tconst char *GetIDString();\r\n\t\r\n\tbool SetPosition(const Mth::Vector& pos, float height, float angle);\r\n\tbool GetPosition(Mth::Vector *p_pos, float *p_height, float *p_angle);\r\n\tCGoalPos::EType GetPositionType();\r\n\tvoid GetPosition(Mth::Vector *p_pos, int index);\r\n\tint GetNumPositionsSet() {return m_num_positions_set;}\r\n\t\r\n\tbool BackUp(const Mth::Vector& pos, float height, float angle);\r\n\tbool GotAllPositions();\r\n\tuint GetCurrentLetterIndex();\r\n\tbool PlacedLastPosition() {return m_placed_last_position;}\r\n\t\r\n\tvoid SetGoalDescription(const char *p_text);\r\n\tvoid SetWinMessage(const char *p_text);\r\n\tvoid SetGoalName(const char *p_name);\r\n\tvoid SetPedName(const char *p_name);\r\n\tbool PositionClashesWithExistingPositions(Mth::Vector& pos);\r\n\t\r\n\tint  GetScore() {return m_score;}\r\n\tvoid SetScore(int score) {m_score=score;}\r\n\tvoid SetTimeLimit(int timeLimit);\r\n\tvoid SetControlType(uint32 controlType);\r\n\t\r\n\tvoid EditGoal();\r\n\r\n\tvoid WriteIntoStructure(Script::CStruct *p_info);\r\n\tvoid ReadFromStructure(Script::CStruct *p_info);\r\n\r\n\tvoid WriteGoalSpecificParams(Script::CStruct *p_info, EWriteDest dest=NOT_WRITING_TO_GOAL_MANAGER);\r\n\tvoid ReadGoalSpecificParams(Script::CStruct *p_params);\r\n\tvoid RemoveGoalSpecificFlag(Script::CStruct *p_params);\r\n\t\r\n\tuint32 GetType() {return m_goal_type;}\r\n\tvoid SetType(uint32 type);\r\n\tvoid SetLevel(uint32 levelScript) {m_level_script=levelScript;}\r\n\tuint32 GetLevel() {return m_level_script;}\r\n\tconst char *GetGoalName() {return mp_goal_name;}\r\n\tconst char *GetPedName() {return mp_ped_name;}\r\n\tvoid FlagAsWon() {m_has_won_goal=true;}\r\n\t\r\n\tvoid AddKeyComboSet(int setIndex, bool requirePerfect, int spin, int numTaps);\r\n\tvoid RemoveKeyComboSet(int setIndex);\r\n\tSPreDefinedKeyComboSet *GetKeyComboSet(int setIndex);\r\n\t\r\n\tvoid AddGap(uint8 gap_number);\r\n\tvoid RemoveGap(uint8 gap_number);\r\n\tvoid RemoveGapAndReorder(uint8 gap_number);\r\n\tbool GotGap(uint8 gap_number);\r\n\t\r\n\tvoid AddGoalToGoalManager(bool markUnbeaten=false);\r\n\tvoid WriteNodePositions();\r\n\t\r\n\tbool GoalIsOutsideArea(float x0, float z0, float x1, float z1);\r\n\tvoid RefreshPositionsUsingCollisionCheck();\r\n\t\r\n\tvoid GetDebugInfo(Script::CStruct* p_info);\r\n};\r\n\r\nclass CGoalEditorComponent : public CBaseComponent\r\n{\r\n\tCEditGoal \tmp_goals[MAX_GOALS_TOTAL];\r\n\tCEditGoal \t*mp_current_goal;\r\n\r\n\tCInputComponent \t\t*mp_input_component;\r\n\tCEditorCameraComponent \t*mp_editor_camera_component;\r\n\tvoid get_pointers_to_required_components();\r\n\tObj::CCompositeObject *get_cursor();\r\n\tvoid refresh_cursor_object();\r\n\r\n\tvoid get_pos_from_camera_component(Mth::Vector *p_pos, float *p_height, float *p_angle);\r\n\tvoid update_cursor_collision_type();\r\n\t\r\n\tCEditGoal *find_goal(const char *p_name);\r\n\tCEditGoal *find_goal(uint32 id);\r\n\tCEditGoal *find_goal(Script::CStruct *p_params);\r\n\t\r\n\tvoid update_camera_pos();\r\n\tvoid update_cursor_position();\r\n\tvoid remove_goal(CEditGoal *p_goal);\r\n\tbool too_close_to_another_goal_position(const Mth::Vector &pos, float height, uint32 level, int positionIndex);\r\n\t\r\npublic:\r\n    CGoalEditorComponent();\r\n    virtual ~CGoalEditorComponent();\r\n\r\npublic:\r\n\tvoid\t\t\t\t\t\t\tClearAllExceptParkGoals();\r\n\tvoid\t\t\t\t\t\t\tClearOnlyParkGoals();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tCleanOutUnfinishedGoals();\r\n\tvoid\t\t\t\t\t\t\tNewGoal();\r\n\tvoid\t\t\t\t\t\t\tSetGoalType(uint32 type);\r\n\tvoid\t\t\t\t\t\t\tAddGoalsToGoalManager();\r\n\tvoid\t\t\t\t\t\t\tWriteNodePositions();\r\n\tint\t\t\t\t\t\t\t\tGetNumGoals();\r\n\tbool\t\t\t\t\t\t\tThereAreGoalsOutsideArea(float x0, float z0, float x1, float z1);\r\n\tvoid\t\t\t\t\t\t\tDeleteGoalsOutsideArea(float x0, float z0, float x1, float z1);\r\n\tint \t\t\t\t\t\t\tCountGoalsForLevel(uint32 level);\r\n\t\r\n\tvoid\t\t\t\t\t\t\tRefreshGoalPositionsUsingCollisionCheck();\r\n\tvoid\t\t\t\t\t\t\tRefreshGapGoalsAfterGapRemovedFromPark(int gapNumber);\r\n\t\r\n\t\r\n\t// For reading/writing to memcard\r\n\tvoid\t\t\t\t\t\t\tWriteIntoStructure(Script::CStruct *p_info);\r\n\tenum EBoolLoadingParkGoals\r\n\t{\r\n\t\tNOT_LOADING_PARK_GOALS=0,\r\n\t\tLOADING_PARK_GOALS=1,\r\n\t};\t\r\n\tvoid\t\t\t\t\t\t\tReadFromStructure(Script::CStruct *p_info, EBoolLoadingParkGoals loadingParkGoals=NOT_LOADING_PARK_GOALS);\r\n\t\r\n\tvoid\t\t\t\t\t\t\tWriteIntoStructure(uint32 levelScript, Script::CStruct *p_info);\r\n\tuint32\t\t\t\t\t\t\tWriteToBuffer(uint32 levelScript, uint8 *p_buffer, uint32 bufferSize);\r\n\tuint8 *\t\t\t\t\t\t\tReadFromBuffer(uint32 levelScript, uint8 *p_buffer);\r\n\t\r\n\r\n\tvirtual\tvoid \t\t\t\t\tFinalize();\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\tvirtual void\t\t\t\t\tHide( bool shouldHide );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n};\r\n\r\n//char p[sizeof(CGoalEditorComponent)/0];\r\n\r\nvoid InsertGoalEditorNodes();\r\nObj::CGoalEditorComponent *GetGoalEditor();\r\n\r\n} // namespace Obj\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/ProjectileCollisionComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       ProjectileCollisionComponent.cpp\r\n//* OWNER:          SPG\r\n//* CREATION DATE:  7/10/03\r\n//****************************************************************************\r\n\r\n// The CEmptyComponent class is an skeletal version of a component\r\n// It is intended that you use this as the basis for creating new\r\n// components.  \r\n// To create a new component called \"Watch\", (CWatchComponent):\r\n//  - copy emptycomponent.cpp/.h to watchcomponent.cpp/.h\r\n//  - in both files, search and replace \"Empty\" with \"Watch\", preserving the case\r\n//  - in WatchComponent.h, update the CRCD value of CRC_WATCH\r\n//  - in CompositeObjectManager.cpp, in the CCompositeObjectManager constructor, add:\r\n//\t\t  \tRegisterComponent(CRC_WATCH,\t\t\tCWatchComponent::s_create); \r\n//  - and add the include of the header\r\n//\t\t\t#include <gel/components/watchcomponent.h> \r\n//  - Add it to build\\gel.mkf, like:\r\n//          $(NGEL)/components/WatchComponent.cpp\\\r\n//  - Fill in the OWNER (yourself) and the CREATION DATE (today's date) in the .cpp and the .h files\r\n//\t- Insert code as needed and remove generic comments\r\n//  - remove these comments\r\n//  - add comments specfic to the component, explaining its usage\r\n\r\n#include <sk/components/ProjectileCollisionComponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/net/server/netserv.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/components/skaterscorecomponent.h>\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#define vSKATER_RADIUS\tFEET( 4 )\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\n\r\nCBaseComponent* CProjectileCollisionComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CProjectileCollisionComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCProjectileCollisionComponent::CProjectileCollisionComponent() : CBaseComponent()\r\n{\r\n    SetType( CRC_PROJECTILECOLLISION );\r\n\tm_radius = 0.0f;\r\n\tm_owner_id = 0;\r\n\tm_death_script = 0;\r\n\tm_scale = 0;\r\n\tm_dying = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCProjectileCollisionComponent::~CProjectileCollisionComponent()\r\n{   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CProjectileCollisionComponent::SetCollisionRadius( float radius )\r\n{\r\n\tm_radius = radius;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CProjectileCollisionComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tpParams->GetFloat(CRCD(0xc48391a5,\"radius\"), &m_radius, Script::ASSERT);\r\n\tpParams->GetFloat(CRCD(0x13b9da7b,\"scale\"), &m_scale, Script::ASSERT);\r\n\tpParams->GetChecksum(CRCD(0x81c39e06,\"owner_id\"), &m_owner_id, Script::ASSERT);\r\n\tpParams->GetChecksum(CRCD(0x6647adc3,\"death_script\"), &m_death_script, Script::ASSERT);\r\n\r\n\tm_vel.Set( 0, 0, 1 );\r\n\tpParams->GetVector(CRCD(0xc4c809e, \"vel\"), &m_vel, Script::ASSERT);\r\n\tm_vel.Normalize();\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CProjectileCollisionComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calline InitFromStructure()\r\n\t// but if that does not handle it, then will need to write a specific \r\n\t// function here. \r\n\t// The user might only want to update a single field in the structure\r\n\t// and we don't want to be asserting becasue everything is missing \r\n\t\r\n\t//InitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CProjectileCollisionComponent::Finalize()\r\n{\r\n\tmp_suspend_component =  GetSuspendComponentFromObject( GetObject() );\r\n}\r\n\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCProjectileCollisionComponent::Hide( bool should_hide )\r\n{\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CProjectileCollisionComponent::Update()\r\n{\r\n\tfloat radii;\r\n\r\n\tradii = m_radius + vSKATER_RADIUS;\r\n\tif (!mp_suspend_component->SkipLogic() && !m_dying )\r\n\t{\r\n\t\tfloat dist;\r\n\t\tbool team_game;\r\n\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\t\tuint32 NumSkaters = skate_mod->GetNumSkaters();\r\n\t\tGameNet::PlayerInfo* target_player, *src_player;\r\n\r\n\t\tteam_game = skate_mod->GetGameMode()->IsTeamGame();\r\n\t\tfor( uint32 i = 0; i < NumSkaters; i++ )\r\n\t\t{\r\n\t\t\tObj::CSkater *pSkater = skate_mod->GetSkater(i);\r\n\t\t\tObj::CSkaterScoreComponent* p_score_comp;\r\n\t\t\tMdl::Score* score;\r\n\r\n\t\t\t// Can't hit yourself with your own projectile\r\n\t\t\tif( pSkater->GetID() == m_owner_id )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tsrc_player = gamenet_man->GetPlayerByObjectID( m_owner_id );\r\n\t\t\ttarget_player = gamenet_man->GetPlayerByObjectID( pSkater->GetID());\r\n\t\t\t\r\n\t\t\t// Allow players to get up after being knocked down\r\n\t\t\tif( target_player->IsVulnerable() == false )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tp_score_comp = GetSkaterScoreComponentFromObject( pSkater );\r\n\t\t\tscore = p_score_comp->GetScore();\r\n\r\n\t\t\t// Don't target dead players\r\n\t\t\tif( score->GetTotalScore() <= 0 )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif( team_game )\r\n\t\t\t{\r\n\t\t\t\tif( src_player->m_Team == target_player->m_Team )\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 enabled;\r\n\r\n\t\t\t\t\tenabled = gamenet_man->GetNetworkPreferences()->GetPreferenceChecksum( CRCD(0xe959c43a,\"friendly_fire\"), CRCD(0x21902065,\"checksum\"));\r\n\t\t\t\t\tif( enabled != CRCD(0xf81bc89b,\"boolean_true\"))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tdist = (pSkater->GetPos() - GetObject()->GetPos()).Length();\r\n\t\t\tif( dist < radii )\r\n\t\t\t{\r\n\t\t\t\tGameNet::MsgProjectileHit hit_msg;\r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\t\tNet::Server* server;\r\n\t\t\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\t\t\t\tserver = gamenet_man->GetServer();\r\n\r\n\t\t\t\t//Dbg_Printf( \"COLLISION: Skater %d: owner: %d\\n\", pSkater->GetID(), m_owner_id);\r\n\t\t\t\tGetObject()->MarkAsDead();\r\n\t\t\t\tif( m_death_script != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct* params;\r\n\t\t\t\t\tMth::Vector pos;\r\n\r\n\t\t\t\t\tpos = GetObject()->GetPos();\r\n\t\t\t\t\tparams = new Script::CStruct;\r\n\t\t\t\t\t\r\n\t\t\t\t\tparams->AddVector( CRCD(0x7f261953,\"pos\"), pos );\r\n\t\t\t\t\tparams->AddVector( CRCD(0xc4c809e,\"vel\"), m_vel );\r\n\t\t\t\t\tparams->AddFloat( CRCD(0x13b9da7b,\"scale\"), m_scale );\r\n\r\n\t\t\t\t\tScript::RunScript( m_death_script, params );\r\n\t\t\t\t\tdelete params;\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\t// a message explaining \"You've been hit down by ID for N damage\"\r\n\t\t\t\thit_msg.m_Id = m_owner_id;\r\n\t\t\t\thit_msg.m_Damage = get_damage_amount();\r\n\t\r\n\t\t\t\t/*if (CInputComponent* p_input_component = GetInputComponentFromObject(GetObject()))\r\n\t\t\t\t{\r\n\t\t\t\t\tp_input_component->DisableInput();\r\n\t\t\t\t}\r\n\t\t\t\tp_player->MarkAsNonCollidable();*/\r\n\t\t\t\t\r\n\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_SKATER_HIT_BY_PROJECTILE;\r\n\t\t\t\tmsg_desc.m_Data = &hit_msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof(GameNet::MsgProjectileHit);\r\n\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\ttarget_player->SetHitTime( Tmr::GetTime());\r\n\t\t\t\tserver->EnqueueMessage( target_player->GetConnHandle(), &msg_desc );\r\n\t\r\n\t\t\t\t// basically a message explaining \"You hit someone\"\r\n\t\t\t\thit_msg.m_Id = pSkater->GetID();\r\n\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_SKATER_PROJECTILE_HIT_TARGET;\r\n\t\t\t\tserver->EnqueueMessage( src_player->GetConnHandle(), &msg_desc );\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\tif(( score->GetTotalScore() - get_damage_amount() ) <= 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// If this shot is killing them...\r\n\t\t\t\t\tif( score->GetTotalScore() > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( target_player->IsLocalPlayer() == false )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tScript::CStruct* params;\r\n\t\r\n\t\t\t\t\t\t\tDbg_Printf( \"*** Elimination\\n\" );\r\n\t\r\n\t\t\t\t\t\t\tparams = new Script::CStruct;\r\n\t\t\t\t\t\t\tparams->AddString( CRCD(0xa1dc81f9,\"name\"), pSkater->GetDisplayName());\r\n\t\t\t\t\t\t\tScript::RunScript( CRCD(0x9b043179,\"announce_elimination\"), params );\r\n\t\t\t\t\t\t\tdelete params;\r\n\t\t\t\t\t\t\tskate_mod->HideSkater( pSkater, true );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tscore->SetTotalScore( 0 );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tscore->SetTotalScore( score->GetTotalScore() - get_damage_amount());\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CProjectileCollisionComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CProjectileCollisionComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CProjectileCollisionComponent::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\t\r\n\r\n// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint\tCProjectileCollisionComponent::get_damage_amount( void )\r\n{\r\n\treturn (int) m_scale * 10;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CProjectileCollisionComponent::MarkAsDying( void )\r\n{\r\n\tm_dying = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/ProjectileCollisionComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       ProjectileCollisionComponent.h\r\n//* OWNER:          SPG\r\n//* CREATION DATE:  07/14/03\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_PROJECTILECOLLISIONCOMPONENT_H__\r\n#define __COMPONENTS_PROJECTILECOLLISIONCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/components/suspendcomponent.h>\r\n\r\n// Replace this with the CRCD of the component you are adding\r\n#define\t\tCRC_PROJECTILECOLLISION CRCD(0x7767d6d7,\"ProjectileCollision\")\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or \r\n//  given an object\t\t\t\t \r\n#define\t\tGetProjectileCollisionComponent() ((Obj::CProjectileCollisionComponent*)GetComponent(CRC_PROJECTILECOLLISION))\r\n#define\t\tGetProjectileCollisionComponentFromObject(pObj) ((Obj::CProjectileCollisionComponent*)(pObj)->GetComponent(CRC_PROJECTILECOLLISION))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CProjectileCollisionComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CProjectileCollisionComponent();\r\n    virtual ~CProjectileCollisionComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void\t\t\t\t\tHide( bool should_hide );\r\n\tvirtual void\t\t\t\t\tFinalize();\r\n\t\r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\r\n\tvoid\t\t\t\t\t\t\tSetCollisionRadius( float radius );\r\n\tvoid\t\t\t\t\t\t\tMarkAsDying( void );\r\n\r\nprivate:\r\n\tint\t\t\t\t\t\t\t\tget_damage_amount( void );\r\n\r\n\tCSuspendComponent*\tmp_suspend_component;\r\n\r\n\tfloat\t\t\t\tm_radius;\t// Radius for spherical collision detection\r\n\tfloat\t\t\t\tm_scale;\r\n\tuint32\t\t\t\tm_death_script;\r\n\tuint32\t\t\t\tm_owner_id;\r\n\tMth::Vector\t\t\tm_vel;\r\n\tbool\t\t\t\tm_dying;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/RailEditorComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       RailEditorComponent.cpp\r\n//* OWNER:          Kendall Harrison\r\n//* CREATION DATE:  3/21/2003\r\n//****************************************************************************\r\n\r\n#include <sk/components/RailEditorComponent.h>\r\n#include <sk/components/EditorCameraComponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/string.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gfx/nx.h>\r\n#include <sk/parkeditor2/parked.h>\r\n#include <sk/engine/feeler.h>\r\n\r\nDefinePoolableClass(Obj::CEditedRailPoint);\r\nDefinePoolableClass(Obj::CEditedRail);\r\n\r\n// TODO: The m_mode member could in theory be removed, just use the tags to store it instead.\r\n// Hence could remove the SetEditingMode and GetEditingMode functions.\r\n// (Nice to have as much logic moved to script as possible)\r\n\r\nnamespace Obj\r\n{\r\nMth::Vector ZeroVector;\r\n\r\n#define RAIL_SECTOR_HEIGHT 2.625f\r\n\r\nstatic uint32 s_rail_unique_id=1;\r\nstatic int s_highlight_flash_counter=0;\r\n\r\n// This will rotate pos-rotateCentre by degrees about Y, add the result to newCentre, and return the result.\r\n// Needed by the clipboard when displaying the copied rails as they rotate with the cursor.\r\nstatic Mth::Vector s_rotate_and_translate(Mth::Vector& pos, Mth::Vector& rotateCentre, Mth::Vector& newCentre, float degrees)\r\n{\r\n\tMth::Vector d=pos-rotateCentre;\r\n\t\r\n\tfloat rad=degrees*3.141592654f/180.0f;\r\n\tfloat s=sinf(rad);\r\n\tfloat c=cosf(rad);\r\n\r\n\tMth::Vector rotated;\r\n\trotated[X]=c*d[X]+s*d[Z];\r\n\trotated[Y]=d[Y];\r\n\trotated[Z]=c*d[Z]-s*d[X];\r\n\t\r\n\treturn newCentre+rotated;\r\n}\r\n\r\n// SPEEDOPT: Pass false to updateSuperSectors when creating a batch of sectors, and call\r\n// UpdateSuperSectors afterwards.\r\nstatic Nx::CSector *s_clone_sector(uint32 sector_name)\r\n{\r\n\tNx::CScene *p_source_scene=Nx::CEngine::sGetScene(\"sk5ed\");\r\n\tif (!p_source_scene)\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\t\t\r\n\tNx::CScene *p_cloned_scene=Ed::CParkManager::sInstance()->GetGenerator()->GetClonedScene();\r\n\tif (!p_cloned_scene)\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\t\t\r\n\tuint32 new_sector_checksum = p_source_scene->CloneSector(sector_name, p_cloned_scene, false, true);\r\n\t\r\n\t// SPEEDOPT: If a batch of sectors are cloned, only do this once at the end.\r\n\tp_cloned_scene->UpdateSuperSectors();\r\n\t\r\n\tNx::CSector *p_new_sector = Nx::CEngine::sGetSector(new_sector_checksum);\r\n\r\n\treturn p_new_sector;\r\n}\r\n\r\n\r\nstatic void s_generate_end_vert_positions(Mth::Vector &pos, Mth::Vector &dir, \r\n\t\t\t\t\t\t\t\t\t\t  Mth::Vector *p_geom_verts,\r\n\t\t\t\t\t\t\t\t\t\t  int *p_vert_indices,\r\n\t\t\t\t\t\t\t\t\t\t  int numIndices)\r\n{\r\n\t// Need to copy the origin into a local var cos the source is about to be modified.\r\n\tMth::Vector origin=p_geom_verts[p_vert_indices[0]];\r\n\t\r\n\tMth::Vector up(0.0f,1.0f,0.0f);\r\n\tMth::Vector u=dir;\r\n\tu.Normalize();\r\n\t\r\n\tMth::Vector w;\r\n\tif (fabs(u[Y]) > 0.99999f)\r\n\t{\r\n\t\tw.Set(0.0f,0.0f,1.0f);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tw=Mth::CrossProduct(up,u);\r\n\t\tw.Normalize();\r\n\t}\t\r\n\t\r\n\tMth::Vector v=Mth::CrossProduct(u,w);\r\n\tv.Normalize();\r\n\tMth::Matrix rot;\r\n\trot[Mth::RIGHT]=u;\r\n\trot[Mth::UP]=v;\r\n\trot[Mth::AT]=w;\r\n\trot[3][3]=1.0f;\r\n\t\r\n\tfor (int i=0; i<numIndices; ++i)\r\n\t{\r\n\t\tMth::Vector *p_geom_vert=&p_geom_verts[p_vert_indices[i]];\r\n\t\tMth::Vector off=*p_geom_vert-origin;\r\n\t\toff=off*rot;\r\n\t\t*p_geom_vert=off+pos;\r\n\t}\r\n}\r\n\r\n// Used for the rails, and the dotted line going from the cursor to the last rail point placed.\r\n\r\n// Given a cloned rail sector, this will write in the vertex coords such that the rail goes from\r\n// startPos to endPos.\r\n// This assumes a certain hard-wired vertex ordering, so currently sourceSectorChecksum can only be\r\n// Sk5Ed_RA_Dynamic or Sk5Ed_RADot_Dynamic\r\n// If p_lastRailSector is not NULL then it will make the vertices of the start of the rail match up\r\n// with those at the end of p_lastRailSector.\r\n\r\n// TODO: Fix bug where end of rail shrinks when rail is very steep.\r\nstatic void s_calculate_rail_sector_vertex_coords(Mth::Vector &lastPos, Mth::Vector &startPos, Mth::Vector &endPos, \r\n\t\t\t\t\t\t\t\t\t\t\t\t  Nx::CSector *p_clonedSector, uint32 sourceSectorChecksum, \r\n\t\t\t\t\t\t\t\t\t\t\t\t  Nx::CSector *p_lastRailSector, bool update_collision)\r\n{\r\n\t// These arrays are figured out manually by printf'ing the vertex coords.\r\n\t// Each end of the rail has 5 vertices, a top one, 2 middle ones and 2 bottom ones, forming a house shape.\r\n\t// The top one has the highest y coord. All the verts for one end have the same x coord.\r\n\t// Some of the vertices are duplicated however, which is why there is more than one top coord, & more than 2 middle, etc.\r\n\t// For each vertex in p_end_verts_a, the corresponding vertex in p_end_verts_b must have the same y and z coords.\r\n\t// This is so that the start of one rail piece can join up with the end of the last by tieing the vertices together.\r\n\t\r\n\t// TODO: These indices will need to be different on Xbox and GameCube\r\n#\tifdef __PLAT_NGC__\r\n\tint p_end_verts_a[]=\r\n\t{\r\n\t\t2, 13,\t\t\t\t// Top \r\n\t\t0, 4, 11, 15,\t\t// Middle \r\n\t\t1, 3, 17, 19,       // Bottom \r\n\t};\r\n\tint p_end_verts_b[]=\r\n\t{\r\n\t\t7, 12,\t\t\t\t// Top     \r\n\t\t5, 9, 10, 14,       // Middle  \r\n\t\t6, 8, 16, 18,       // Bottom  \r\n\t};\r\n#else\r\n#\tifdef __PLAT_XBOX__\r\n\tint p_end_verts_a[]=\r\n\t{\r\n\t\t1,9,             \t// Top\r\n\t\t3,10,14,19,\t\t\t// Middle\r\n\t\t0,13,2,16,\t\t\t// Bottom\r\n\t};\r\n\tint p_end_verts_b[]=\r\n\t{\r\n\t\t6,11,\t\t\t\t// Top\r\n\t\t7,8,15,18,\t\t\t// Middle\r\n\t\t4,12,5,17,\t\t\t// Bottom\r\n\t};\r\n#\telse\r\n\tint p_end_verts_a[]=\r\n\t{\r\n\t\t2,19,             \t// Top\r\n\t\t0,4,11,17,21,\t\t// Middle\r\n\t\t1,3,13,15,\t\t\t// Bottom\r\n\t};\r\n\tint p_end_verts_b[]=\r\n\t{\r\n\t\t7,18,\t\t\t\t// Top\r\n\t\t9,5,10,16,20,\t\t// Middle\r\n\t\t8,6,12,14,\t\t\t// Bottom\r\n\t};\r\n#\tendif\r\n#\tendif\r\n\r\n\tDbg_MsgAssert(sizeof(p_end_verts_a)==sizeof(p_end_verts_b),(\"End vert array size mismatch!\"));\r\n\tint num_indices=sizeof(p_end_verts_a)/sizeof(int);\r\n\r\n\t// Get the default coords of the sectors vertices. These will be relative to the sectors origin.\r\n\tNx::CSector *p_source_sector=Nx::CEngine::sGetSector(sourceSectorChecksum);\r\n\tNx::CGeom *p_source_geom=p_source_sector->GetGeom();\r\n\tDbg_MsgAssert(p_source_geom,(\"NULL p_source_geom ?\"));\r\n\t\r\n\tint num_render_verts=p_source_geom->GetNumRenderVerts();\r\n\tDbg_MsgAssert(num_render_verts==num_indices*2,(\"Unexpected extra vertices in rail sector, expected %d, got %d\",2*num_indices,num_render_verts));\r\n\t\r\n\t// SPEEDOPT: If necessary, could use a static buffer for the verts\r\n\tMth::Vector *p_modified_render_verts=(Mth::Vector*)Mem::Malloc(num_render_verts * sizeof(Mth::Vector));\r\n\tp_source_geom->GetRenderVerts(p_modified_render_verts);\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tfor (int i=0; i<num_indices; ++i)\r\n\t{\r\n\t\tDbg_MsgAssert(p_modified_render_verts[p_end_verts_a[i]].GetY()==p_modified_render_verts[p_end_verts_b[i]].GetY(),(\"Rail sector vertex Y mismatch between vertices %d and %d\",p_end_verts_a[i],p_end_verts_b[i]));\r\n\t\tDbg_MsgAssert(p_modified_render_verts[p_end_verts_a[i]].GetZ()==p_modified_render_verts[p_end_verts_b[i]].GetZ(),(\"Rail sector vertex Z mismatch between vertices %d and %d\",p_end_verts_a[i],p_end_verts_b[i]));\r\n\t}\t\r\n\t\r\n\tfloat rail_height=p_modified_render_verts[p_end_verts_a[0]].GetY()-p_modified_render_verts[p_end_verts_a[num_indices-1]].GetY();\r\n\tDbg_MsgAssert(rail_height==RAIL_SECTOR_HEIGHT,(\"Need to update RAIL_SECTOR_HEIGHT to be %f\",rail_height));\r\n\t#endif\r\n\t\r\n\tMth::Vector dir;\r\n\tif (p_lastRailSector)\r\n\t{\r\n\t\tdir=((startPos-lastPos)+(endPos-startPos)) / 2.0f;\r\n\t\t\r\n\t\ts_generate_end_vert_positions(startPos, dir, p_modified_render_verts, p_end_verts_a, num_indices);\r\n\t\t\r\n\t\t// Set the last sector's end verts equal to the just calculated set of coords too.\r\n\t\tNx::CGeom *p_last_geom=p_lastRailSector->GetGeom();\r\n\t\tDbg_MsgAssert(p_last_geom,(\"NULL p_last_geom ?\"));\r\n\t\t\r\n\t\tint last_num_render_verts=p_last_geom->GetNumRenderVerts();\r\n\t\t// SPEEDOPT: If necessary, could use a static buffer for the verts\r\n\t\tMth::Vector *p_last_verts=(Mth::Vector*)Mem::Malloc(last_num_render_verts * sizeof(Mth::Vector));\r\n\t\tp_last_geom->GetRenderVerts(p_last_verts);\r\n\r\n\t\t// Tie the end verts to the new start verts.\r\n\t\tfor (int i=0; i<num_indices; ++i)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(p_end_verts_b[i] < last_num_render_verts,(\"Bad index into p_last_verts\"));\r\n\t\t\tp_last_verts[p_end_verts_b[i]]=p_modified_render_verts[p_end_verts_a[i]];\r\n\t\t}\t\r\n\r\n\t\tp_last_geom->SetRenderVerts(p_last_verts);\r\n\r\n\t\tMem::Free(p_last_verts);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tdir=endPos-startPos;\r\n\t\ts_generate_end_vert_positions(startPos, dir, p_modified_render_verts, p_end_verts_a, num_indices);\r\n\t}\t\r\n\t\r\n\tdir=endPos-startPos;\r\n\ts_generate_end_vert_positions(endPos, dir, p_modified_render_verts, p_end_verts_b, num_indices);\r\n\t\r\n\r\n\t// Write the vertex coords just calculated into the cloned sector.\r\n\tDbg_MsgAssert(p_clonedSector,(\"NULL p_clonedSector\"));\r\n\tNx::CGeom *p_geom=p_clonedSector->GetGeom();\r\n\tDbg_MsgAssert(p_geom,(\"NULL p_geom ?\"));\r\n\tDbg_MsgAssert(p_geom->GetNumRenderVerts()==p_source_geom->GetNumRenderVerts(),(\"Source geom num verts mismatch\"));\r\n\tp_geom->SetRenderVerts(p_modified_render_verts);\r\n\r\n\t/////////////////////////////////////////////////////////////////\r\n\t// Now update the collision verts\r\n\t/////////////////////////////////////////////////////////////////\r\n\t\r\n\tif (update_collision) // Uncomment this once the rail pieces have been reexported with correct collision\r\n\t{\r\n\t\t// Get the source render verts again so that we can match up the source collision verts with them, and hence get\r\n\t\t// the index of the modified render vert to use for each collision vert.\r\n\t\tMth::Vector *p_source_render_verts=(Mth::Vector*)Mem::Malloc(num_render_verts * sizeof(Mth::Vector));\r\n\t\tp_source_geom->GetRenderVerts(p_source_render_verts);\r\n\t\t// The source render verts are in relative coords.\r\n\t\r\n\t\t// Get the source collision verts, which will also be in relative coords.\r\n\t\tNx::CCollObjTriData *p_source_col_data=p_source_geom->GetCollTriData();\r\n\t\tint num_source_col_verts=p_source_col_data->GetNumVerts();\r\n\r\n\t\tMth::Vector *p_collision_verts=(Mth::Vector*)Mem::Malloc(num_source_col_verts * sizeof(Mth::Vector));\r\n\t\tp_source_col_data->GetRawVertices(p_collision_verts);\r\n\t\r\n\t\t// For each of the collision verts, look for a matching coord in the source render verts,\r\n\t\t// and if found, write in the world coords calculated for it earlier.\r\n\t\tfor (int i=0; i<num_source_col_verts; ++i)\r\n\t\t{\r\n\t\t\tMth::Vector pos=p_collision_verts[i];\r\n\r\n\t\t\t// All but two of the collision verts should be found by this loop.\r\n\t\t\tbool found_exact_match=false;\t\t\r\n\t\t\tfor (int j=0; j<num_render_verts; ++j)\r\n\t\t\t{\r\n\t\t\t\tif (p_source_render_verts[j][X] == pos[X] && \r\n\t\t\t\t\tp_source_render_verts[j][Y] == pos[Y] &&\r\n\t\t\t\t\tp_source_render_verts[j][Z] == pos[Z])\r\n\t\t\t\t{\r\n\t\t\t\t\tp_collision_verts[i]=p_modified_render_verts[j];\r\n\t\t\t\t\tfound_exact_match=true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\t\t\r\n\t\t\r\n\t\t\tif (!found_exact_match)\r\n\t\t\t{\r\n\t\t\t\tbool found_match=false;\r\n\t\t\t\r\n\t\t\t\t// The two verts that have no corresponding render vert are the two bottom vertices\r\n\t\t\t\t// of the collision poly that hangs below the rail.\r\n\t\t\t\t// For these, find the render verts that match the x & z, and use their world position,\r\n\t\t\t\t// but just drop the y down the same distance as it was below it in the original relative coords.\r\n\t\t\t\tfor (int j=0; j<num_render_verts; ++j)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (p_source_render_verts[j][X] == pos[X] && \r\n\t\t\t\t\t\tp_source_render_verts[j][Z] == pos[Z])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Get the y difference in the original relative coords ...\r\n\t\t\t\t\t\tfloat y_off=pos[Y]-p_source_render_verts[j][Y];\r\n\t\t\t\t\t\t// Set the collision vertex equal to the previously calculated world coords of the vertex ...\r\n\t\t\t\t\t\tp_collision_verts[i]=p_modified_render_verts[j];\r\n\t\t\t\t\t\t// Then move it down by the y difference again.\r\n\t\t\t\t\t\tp_collision_verts[i][Y]+=y_off;\r\n\t\t\t\t\t\r\n\t\t\t\t\t\tfound_match=true;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\t\r\n\t\t\t\r\n\t\t\t\tif (!found_match)\r\n\t\t\t\t{\r\n\t\t\t\t\t// If no match was found, then maybe the sector got re-exported in a strange manner.\r\n\t\t\t\t\tpos.PrintContents();\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"Could not find a render-vert match for collision vert %d\",i));\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t}\t\r\n\r\n\t\t// Write the new collision verts into the cloned sector.\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tNx::CCollObjTriData *p_dest_col_data=p_geom->GetCollTriData();\r\n\t\tDbg_MsgAssert(p_dest_col_data->GetNumVerts()==num_source_col_verts,(\"Bad p_dest_col_data->GetNumVerts() ?\"));\r\n\t\t#endif\r\n\r\n\t\tp_clonedSector->SetRawCollVertices(p_collision_verts);\r\n\t\tMem::Free(p_collision_verts);\r\n\t\tMem::Free(p_source_render_verts);\r\n\t}\r\n\t\r\n\tMem::Free(p_modified_render_verts);\t\r\n} \r\n\r\n// Returns true if the skater will be able to grind from a to b to c without being forced off\r\n// due to the angle being too big.\r\nstatic bool s_angle_is_ok_to_grind(Mth::Vector &a, Mth::Vector &b, Mth::Vector &c)\r\n{\r\n\tMth::Vector ab=b-a;\r\n\tab[Y]=0.0f;\r\n\tab.Normalize();\r\n\t\r\n\tMth::Vector bc=c-b;\r\n\tbc[Y]=0.0f;\r\n\tbc.Normalize();\r\n\t\r\n\tfloat cosine=Mth::DotProduct(ab,bc);\r\n\tif (cosine < cosf(Mth::DegToRad(Script::GetFloat(CRCD(0x76c1da15,\"Rail_Corner_Leave_Angle\")))))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\treturn true;\t\r\n}\r\n\r\nstatic bool s_distance_is_too_long(Mth::Vector &a, Mth::Vector &b)\r\n{\r\n\tMth::Vector d=a-b;\r\n\t// The distance at which the dotted line will flash red to indicate the distance is too long\r\n\treturn d.Length() > 4000.0f;\r\n}\r\n\r\nstatic bool s_distance_is_way_too_long(Mth::Vector &a, Mth::Vector &b)\r\n{\r\n\tMth::Vector d=a-b;\r\n\t// The distance at which the dotted line will disappear completely to avoid rendering problems.\r\n\treturn d.Length() > 4500.0f;\r\n}\r\n\r\nstatic bool s_positions_OK(Mth::Vector &a, Mth::Vector &b)\r\n{\r\n\tif (s_distance_is_too_long(a, b))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tMth::Vector diff=a-b;\r\n\t\r\n\t// Don't allow consecutive points to be placed too close, otherwise the user may accidentally\r\n\t// place points on top of each other, & it could cause weirdness in the calculations due\r\n\t// to zero vectors trying to get normalized etc.\r\n\tif (diff.Length() < Script::GetFloat(CRCD(0x8bea1c03,\"RailEditorMinimumPointSeparation\")))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// Also don't allow the rail segment to get too steep.\r\n\tdiff.Normalize();\r\n\tif (fabs(diff[Y]) > sinf(Mth::DegToRad(Script::GetFloat(CRCD(0x9fd761af,\"RailEditorMaxSlope\")))))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\t\t\t\t\t\t\t\t\t\t  \r\nCEditedRailPoint::CEditedRailPoint()\r\n{\r\n\tmPos.Set();\r\n\tmHasPost=false;\r\n\tmHighlighted=false;\r\n\tmHeightAboveGround=0.0f;\r\n\tmpNext=NULL;\r\n\tmpPrevious=NULL;\r\n\tmpClonedRailSector=NULL;\r\n\tmpPostSector=NULL;\r\n}\r\n\r\nCEditedRailPoint::~CEditedRailPoint()\r\n{\r\n\tDestroyRailGeometry();\r\n\tDestroyPostGeometry();\r\n}\r\n\r\n// Creates the rail sector if it does not exist already, then writes the world\r\n// positions into the vertices.\r\n// rotateCentre, newCentre, and degrees allow the rail to be displayed rotated and translated from its original\r\n// position. This is used when displaying a rail section on the clipboard cursor in the park editor.\r\nvoid CEditedRailPoint::UpdateRailGeometry(Mth::Vector& rotateCentre, Mth::Vector& newCentre, float degrees)\r\n{\r\n\t// Note: The last point that was placed is actually the next in the list, since they get added to the front.\r\n\tif (!mpNext)\r\n\t{\r\n\t\t// There is no last point, so a rail can't be created because there is nothing to join to.\r\n\t\t\r\n\t\t// TODO: Could maybe still make a small section of rail, so that the first post of a rail has\r\n\t\t// a bit of rail overhanging it. Would look better than having the rail stop right above the post.\r\n\t\t\r\n\t\t// Make sure any existing rail is destroyed.\r\n\t\tDestroyRailGeometry();\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Clone the sector if necessary\r\n\tif (!mpClonedRailSector)\r\n\t{\r\n\t\tmpClonedRailSector=s_clone_sector(CRCD(0x66fe99bf,\"Sk5Ed_RA_Dynamic\"));\r\n\t}\r\n\t\r\n\tMth::Vector a, b, c;\r\n\t\r\n\t// Don't tie the end vertices of the two rail sections together if they meet at too great\r\n\t// an angle, cos otherwise one of the sections gets too thin.\r\n\tbool join_to_last_sector=true;\r\n\tif (mpNext->mpNext)\r\n\t{\r\n\t\ta=mpNext->mPos-mpNext->mpNext->mPos;\r\n\t\tb=mPos-mpNext->mPos;\r\n\t\ta.Normalize();\r\n\t\tb.Normalize();\r\n\t\tif (Mth::DotProduct(a,b) < cosf(Mth::DegToRad(Script::GetFloat(CRCD(0xb1459a78,\"RailEditorMaxJoinAngle\")))))\r\n\t\t{\r\n\t\t\tjoin_to_last_sector=false;\r\n\t\t}\t\r\n\r\n\t\ta=s_rotate_and_translate(mpNext->mpNext->mPos, rotateCentre, newCentre, degrees);\r\n\t\tb=s_rotate_and_translate(mpNext->mPos, rotateCentre, newCentre, degrees);\r\n\t\tc=s_rotate_and_translate(mPos, rotateCentre, newCentre, degrees);\r\n\t\t\r\n\t\ts_calculate_rail_sector_vertex_coords(a, b, c,\r\n\t\t\t\t\t\t\t\t\t\t\t  mpClonedRailSector, CRCD(0x66fe99bf,\"Sk5Ed_RA_Dynamic\"),\r\n\t\t\t\t\t\t\t\t\t\t\t  join_to_last_sector ? mpNext->mpClonedRailSector:NULL, true);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(mpNext->mpClonedRailSector==NULL,(\"Expected mpNext->mpClonedRailSector to be NULL ?\"));\r\n\t\t\r\n\t\tMth::Vector dummy;\r\n\t\ta=s_rotate_and_translate(mpNext->mPos, rotateCentre, newCentre, degrees);\r\n\t\tb=s_rotate_and_translate(mPos, rotateCentre, newCentre, degrees);\r\n\t\ts_calculate_rail_sector_vertex_coords(dummy, a, b, \r\n\t\t\t\t\t\t\t\t\t\t\t  mpClonedRailSector, CRCD(0x66fe99bf,\"Sk5Ed_RA_Dynamic\"),\r\n\t\t\t\t\t\t\t\t\t\t\t  NULL, true);\r\n\t}\t\t\t\t\t\t\t\t\t\t\t  \r\n}\r\n\r\n// Creates the post sector if it does not exist already, then writes the correct world\r\n// positions into the vertices.\r\n// This is called when the post is first created, and also gets called for all posts whenever a cell in\r\n// the park is raised or lowered, so that the posts maintain contact with the ground.\r\n\r\n// rotateCentre, newCentre, and degrees allow the post to be displayed rotated and translated from its original\r\n// position. This is used when displaying a rail section on the clipboard cursor in the park editor.\r\nvoid CEditedRailPoint::UpdatePostGeometry(Mth::Vector& rotateCentre, Mth::Vector& newCentre, float degrees)\r\n{\r\n\tif (!mHasPost)\r\n\t{\r\n\t\tDestroyPostGeometry();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// Don't place a post if the rail is so close to the ground that there is not enough room for a post.\r\n\t// This often happens when snapping a rail point to the edge of some level geometry for example.\t\r\n\tif (mHeightAboveGround < RAIL_SECTOR_HEIGHT)\r\n\t{\r\n\t\tDestroyPostGeometry();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// Get the coords of the source sectors vertices. These will be relative to the sectors origin,\r\n\t// which is in the middle of the post.\r\n\tNx::CSector *p_source_sector=Nx::CEngine::sGetSector(CRCD(0x2756c52d,\"Sk5Ed_RAp_Dynamic\"));\r\n\tNx::CGeom *p_source_geom=p_source_sector->GetGeom();\r\n\tDbg_MsgAssert(p_source_geom,(\"NULL p_source_geom ?\"));\r\n\t\r\n\tint num_verts=p_source_geom->GetNumRenderVerts();\r\n\t// SPEEDOPT: If necessary, could use a static buffer for the verts\r\n\tMth::Vector *p_verts=(Mth::Vector*)Mem::Malloc(num_verts * sizeof(Mth::Vector));\r\n\tp_source_geom->GetRenderVerts(p_verts);\r\n\r\n\t// Find the y coords of the top and bottom\r\n\tfloat min_y=1000000.0f;\r\n\tfloat max_y=-1000000.0f;\r\n\tfor (int i=0; i < num_verts; ++i)\r\n\t{\r\n\t\tfloat y=p_verts[i].GetY();\r\n\t\tif (y < min_y)\r\n\t\t{\r\n\t\t\tmin_y=y;\r\n\t\t}\r\n\t\tif (y > max_y)\r\n\t\t{\r\n\t\t\tmax_y=y;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\t// Check that max_y and min_y are the same, just opposite in sign.\r\n\tDbg_MsgAssert(fabs(max_y-(-min_y)) < 0.01f,(\"Expected post geometry to have origin in centre, but min_y=%f, max_y=%f\",min_y,max_y));\r\n\tDbg_MsgAssert(max_y > 0.0f,(\"max_y < 0 ??  (max_y=%f)\",max_y));\r\n\t\r\n\tfloat half_post_height=max_y;\r\n\t\r\n\tfloat rail_sector_height=RAIL_SECTOR_HEIGHT;\r\n\t// If the next post is at a different height, the height of the rail be a bit smaller than normal\r\n\t// due to the end face being tilted to point towards the next post.\r\n\tif (mpNext && mpPrevious)\r\n\t{\r\n\t\tMth::Vector a=mpPrevious->mPos-mPos;\r\n\t\tMth::Vector b=mPos-mpNext->mPos;\r\n\t\t// The end-face's normal will be the average of the two rails\r\n\t\tMth::Vector av=(a+b)/2.0f;\r\n\t\tav.Normalize();\r\n\t\t// av[Y] is the sine of the angle, but we want the cosine\r\n\t\trail_sector_height *= sqrtf(1.0f-av[Y]*av[Y]);\r\n\t}\t\r\n\r\n\tMth::Vector translated_rail_point=s_rotate_and_translate(mPos, rotateCentre, newCentre, degrees);\r\n\t\r\n\t// Translate the post so that it is centred on the rail point, then shift the y's down so that the\r\n\t// top of the post is at the bottom of the rail piece.\r\n\t// The height of the rail section needs to be added too because the rail point (mPos) is at the apex of the\r\n\t// rail section.\r\n\tfloat shift_down_amount=half_post_height+rail_sector_height;\r\n\tfor (int i=0; i < num_verts; ++i)\r\n\t{\r\n\t\tp_verts[i]+=translated_rail_point;\r\n\t\tp_verts[i][Y]-=shift_down_amount;\r\n\t}\r\n\r\n\t// The top of the post is now in the correct position.\r\n\t// Now we need to move the bottom vertices down to ground level.\r\n\t\r\n\t// This array figured out manually, by printing out the vertex coords.\r\n\t// TODO: These indices will need to be different on Xbox and GameCube\r\n#\tifdef __PLAT_NGC__\r\n\tint p_bottom_vert_indices[]=\r\n\t{\r\n\t\t0,2,4,6,\t\t// Post bottom\r\n\t\t8,9,10,11\t\t// Base plate\r\n\t};\r\n#else\r\n#\tifdef __PLAT_XBOX__\r\n\tint p_bottom_vert_indices[]=\r\n\t{\r\n\t\t8,9,10,11,\t\t// Post bottom\r\n\t\t1,2,5,6\t\t\t// Base plate\r\n\t};\r\n#\telse\r\n\tint p_bottom_vert_indices[]=\r\n\t{\r\n\t\t1,3,5,7,9,\t\t// Post bottom\r\n\t\t10,11,12,13\t\t// Base plate\r\n\t};\r\n#\tendif\r\n#\tendif\r\n\tint num_bottom_vertices=sizeof(p_bottom_vert_indices)/sizeof(int);\r\n\tDbg_MsgAssert(num_bottom_vertices <= num_verts,(\"Too many bottom vertices!\"));\r\n\r\n\t// The amount that the bottom vertices need to be moved down is the height, minus the\r\n\t// previous shift_down_amount cos we've already moved them by that much, minus\r\n\t// half the height of the post so that the bottom is on the ground.\r\n\tshift_down_amount=mHeightAboveGround-shift_down_amount-half_post_height;\r\n\t\r\n\tfor (int i=0; i<num_bottom_vertices; ++i)\r\n\t{\r\n\t\tp_verts[p_bottom_vert_indices[i]][Y]-=shift_down_amount;\r\n\t}\t\r\n\r\n\t// Now rotate the post about the y so that it is aligned with\r\n\t// the previous rail section.\r\n\tif (mpNext)\r\n\t{\r\n\t\tMth::Vector u=mPos-mpNext->mPos;\r\n\t\tu[Y]=0.0f;\r\n\t\tu.Normalize();\r\n\t\tfloat ux=u[X];\r\n\t\tfloat uz=u[Z];\r\n\t\tfloat vx=-uz;\r\n\t\tfloat vz=ux;\r\n\r\n\t\tfor (int i=0; i < num_verts; ++i)\r\n\t\t{\r\n\t\t\tfloat dx=p_verts[i][X]-translated_rail_point[X];\r\n\t\t\tfloat dz=p_verts[i][Z]-translated_rail_point[Z];\r\n\t\t\tp_verts[i][X]=ux*dx+vx*dz+translated_rail_point[X];\r\n\t\t\tp_verts[i][Z]=uz*dx+vz*dz+translated_rail_point[Z];\r\n\t\t}\t\t\t\r\n\t}\r\n\r\n\t// Clone the sector if necessary and write in the vertex coords just calculated.\r\n\tif (!mpPostSector)\r\n\t{\r\n\t\tmpPostSector=s_clone_sector(CRCD(0x2756c52d,\"Sk5Ed_RAp_Dynamic\"));\r\n\t}\r\n\t\r\n\tNx::CGeom *p_geom=mpPostSector->GetGeom();\r\n\tDbg_MsgAssert(p_geom,(\"NULL p_geom ?\"));\r\n\tDbg_MsgAssert(p_geom->GetNumRenderVerts()==p_source_geom->GetNumRenderVerts(),(\"Source geom num verts mismatch\"));\r\n\tp_geom->SetRenderVerts(p_verts);\r\n\tMem::Free(p_verts);\t\r\n}\r\n\r\nvoid CEditedRailPoint::DestroyRailGeometry()\r\n{\r\n\tif (mpClonedRailSector)\r\n\t{\r\n\t\tNx::CScene *p_cloned_scene=Ed::CParkManager::sInstance()->GetGenerator()->GetClonedScene();\r\n\t\tDbg_MsgAssert(p_cloned_scene,(\"Missing cloned scene!\"));\r\n\t\tp_cloned_scene->DeleteSector(mpClonedRailSector);\r\n\t\tmpClonedRailSector=NULL;\r\n\r\n\t\t#ifdef __PLAT_NGC__\r\n\t\tNx::CEngine::sFinishRendering();\r\n\t\t#endif\r\n\r\n\t\t// SPEEDOPT: If a batch of things are deleted, only do this once at the end.\r\n\t\tif (CRailEditorComponent::sUpdateSuperSectorsAfterDeletingRailSectors)\r\n\t\t{\r\n\t\t\tp_cloned_scene->UpdateSuperSectors();\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\nvoid CEditedRailPoint::DestroyPostGeometry()\r\n{\r\n\tif (mpPostSector)\r\n\t{\r\n\t\tNx::CScene *p_cloned_scene=Ed::CParkManager::sInstance()->GetGenerator()->GetClonedScene();\r\n\t\tDbg_MsgAssert(p_cloned_scene,(\"Missing cloned scene!\"));\r\n\t\tp_cloned_scene->DeleteSector(mpPostSector);\r\n\t\tmpPostSector=NULL;\r\n\t\t\r\n\t\t#ifdef __PLAT_NGC__\r\n\t\tNx::CEngine::sFinishRendering();\r\n\t\t#endif\r\n\t\t\r\n\t\t// SPEEDOPT: If a batch of things are deleted, only do this once at the end.\r\n\t\tif (CRailEditorComponent::sUpdateSuperSectorsAfterDeletingRailSectors)\r\n\t\t{\r\n\t\t\tp_cloned_scene->UpdateSuperSectors();\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n// Does a drop down collision check to find the height of mPos above the ground.\r\nfloat CEditedRailPoint::FindGroundY()\r\n{\r\n\tMth::Vector off(0.0f,10000.0f,0.0f,0.0f);\r\n\t\r\n\tCFeeler feeler;\r\n\tfeeler.SetStart(mPos + off );\r\n\tfeeler.SetEnd(mPos - off );\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\treturn feeler.GetPoint().GetY();\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 0.0f;\r\n\t}\t\r\n}\r\n\r\n// This will adjust mPos[Y] to be mHeightAboveGround above the ground.\r\n// This is used to update the rails whenever the ground is raised or lowered.\r\n// The rails will maintain the post heights if a post was on the ground\r\n// that moved.\r\nvoid CEditedRailPoint::AdjustY()\r\n{\r\n\tif (mHasPost)\r\n\t{\r\n\t\tmPos[Y]=FindGroundY()+mHeightAboveGround;\r\n\t}\t\r\n}\r\n\r\nvoid CEditedRailPoint::InitialiseHeight()\r\n{\r\n\tmHeightAboveGround=mPos[Y]-FindGroundY();\r\n}\r\n\r\nvoid CEditedRailPoint::Highlight(EFlash flash, EEndPosts includeEndPosts)\r\n{\r\n\tif (mHighlighted)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tuint32 vis=0xffffffff;\r\n\tif (flash)\r\n\t{\r\n\t\tint flash_rate=Script::GetInteger(CRCD(0x4551e901,\"RailEditorHighlightFlashRate\"));\r\n\t\tif (s_highlight_flash_counter < flash_rate/2)\r\n\t\t{\r\n\t\t\tvis=0xffffffff;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tvis=0;\r\n\t\t}\r\n\t\t\t\r\n\t\t++s_highlight_flash_counter;\r\n\t\tif (s_highlight_flash_counter >= flash_rate)\r\n\t\t{\r\n\t\t\ts_highlight_flash_counter=0;\r\n\t\t}\t\r\n\t}\r\n\r\n\tuint8 good_r=Script::GetInteger(CRCD(0xad28b18b,\"RailEditorHighlightColourR\"));\r\n\tuint8 good_g=Script::GetInteger(CRCD(0xc0f55560,\"RailEditorHighlightColourG\"));\r\n\tuint8 good_b=Script::GetInteger(CRCD(0xb09fa1ef,\"RailEditorHighlightColourB\"));\r\n\r\n\tuint8 bad_r=Script::GetInteger(CRCD(0x89b66fb9,\"RailEditorBadAngleHighlightColourR\"));\r\n\tuint8 bad_g=Script::GetInteger(CRCD(0xe46b8b52,\"RailEditorBadAngleHighlightColourG\"));\r\n\tuint8 bad_b=Script::GetInteger(CRCD(0x94017fdd,\"RailEditorBadAngleHighlightColourB\"));\r\n\t\r\n\tuint8 r=good_r;\r\n\tuint8 g=good_g;\r\n\tuint8 b=good_b;\r\n\t\t\r\n\tbool section_stretched_too_long=false;\r\n\tif (mpNext)\r\n\t{\r\n\t\tif (s_distance_is_too_long(mPos, mpNext->mPos))\r\n\t\t{\r\n\t\t\tsection_stretched_too_long=true;\r\n\t\t}\r\n\t}\t\t\r\n\tif (mpPrevious)\r\n\t{\r\n\t\tif (s_distance_is_too_long(mPos, mpPrevious->mPos))\r\n\t\t{\r\n\t\t\tsection_stretched_too_long=true;\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\tif (mpPostSector)\r\n\t{\r\n\t\tif (AngleIsOKToGrind() && !section_stretched_too_long)\r\n\t\t{\r\n\t\t\tr=good_r;\r\n\t\t\tg=good_g;\r\n\t\t\tb=good_b;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tr=bad_r;\r\n\t\t\tg=bad_g;\r\n\t\t\tb=bad_b;\r\n\t\t}\t\r\n\t\tmpPostSector->SetColor(Image::RGBA(r,g,b,0));\r\n\t\tmpPostSector->SetVisibility(vis);\r\n\t}\t\r\n\t\r\n\tif (mpClonedRailSector)\r\n\t{\r\n\t\tif (mpNext)\r\n\t\t{\r\n\t\t\tif (mpNext->AngleIsOKToGrind() && AngleIsOKToGrind() && !section_stretched_too_long)\r\n\t\t\t{\r\n\t\t\t\t// The angle at the point at the other end of mpClonedRailSector is OK,\r\n\t\t\t\t// and so is the angle at this point, so all OK.\r\n\t\t\t\tr=good_r;\r\n\t\t\t\tg=good_g;\r\n\t\t\t\tb=good_b;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tr=bad_r;\r\n\t\t\t\tg=bad_g;\r\n\t\t\t\tb=bad_b;\r\n\t\t\t}\t\r\n\t\t}\r\n\t\t\r\n\t\tmpClonedRailSector->SetColor(Image::RGBA(r,g,b,0));\r\n\t\tmpClonedRailSector->SetVisibility(vis);\r\n\t}\r\n\tif (mpPrevious && mpPrevious->mpClonedRailSector)\r\n\t{\r\n\t\tif (mpPrevious->AngleIsOKToGrind() && AngleIsOKToGrind() && !section_stretched_too_long)\r\n\t\t{\r\n\t\t\t// The angle at the point at the other end of the next segment is OK,\r\n\t\t\t// and so is the angle at this point, so all OK.\r\n\t\t\tr=good_r;\r\n\t\t\tg=good_g;\r\n\t\t\tb=good_b;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tr=bad_r;\r\n\t\t\tg=bad_g;\r\n\t\t\tb=bad_b;\r\n\t\t}\t\r\n\t\t\r\n\t\tmpPrevious->mpClonedRailSector->SetColor(Image::RGBA(r,g,b,0));\r\n\t\tmpPrevious->mpClonedRailSector->SetVisibility(vis);\r\n\t}\t\r\n\r\n\tif (includeEndPosts)\r\n\t{\r\n\t\tif (mpNext && !mpNext->mpNext && mpNext->mpPostSector)\r\n\t\t{\r\n\t\t\tmpNext->mpPostSector->SetColor(Image::RGBA(good_r,good_g,good_b,0));\r\n\t\t\tmpNext->mpPostSector->SetVisibility(vis);\r\n\t\t}\r\n\t\tif (mpPrevious && !mpPrevious->mpPrevious && mpPrevious->mpPostSector)\r\n\t\t{\r\n\t\t\tmpPrevious->mpPostSector->SetColor(Image::RGBA(good_r,good_g,good_b,0));\r\n\t\t\tmpPrevious->mpPostSector->SetVisibility(vis);\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tmHighlighted=true;\r\n}\r\n\r\nvoid CEditedRailPoint::UnHighlight()\r\n{\r\n\tif (mHighlighted)\r\n\t{\r\n\t\tif (mpPostSector)\r\n\t\t{\r\n\t\t\tmpPostSector->ClearColor();\r\n\t\t\tmpPostSector->SetVisibility(0xffffffff);\r\n\t\t}\t\r\n\t\tif (mpClonedRailSector)\r\n\t\t{\r\n\t\t\tmpClonedRailSector->ClearColor();\r\n\t\t\tmpClonedRailSector->SetVisibility(0xffffffff);\r\n\t\t}\r\n\t\tif (mpPrevious && mpPrevious->mpClonedRailSector)\r\n\t\t{\r\n\t\t\tmpPrevious->mpClonedRailSector->ClearColor();\r\n\t\t\tmpPrevious->mpClonedRailSector->SetVisibility(0xffffffff);\r\n\t\t}\t\r\n\r\n\t\tif (mpNext && !mpNext->mpNext && mpNext->mpPostSector)\r\n\t\t{\r\n\t\t\tmpNext->mpPostSector->ClearColor();\r\n\t\t\tmpNext->mpPostSector->SetVisibility(0xffffffff);\r\n\t\t}\t\r\n\t\tif (mpPrevious && !mpPrevious->mpPrevious && mpPrevious->mpPostSector)\r\n\t\t{\r\n\t\t\tmpPrevious->mpPostSector->ClearColor();\r\n\t\t\tmpPrevious->mpPostSector->SetVisibility(0xffffffff);\r\n\t\t}\t\r\n\t\t\r\n\t\tmHighlighted=false;\r\n\t}\t\r\n}\r\n\r\n// Used by graffiti games\r\nvoid CEditedRailPoint::SetColor(Image::RGBA rgba)\r\n{\r\n\tif (mpPostSector)\r\n\t{\r\n\t\tmpPostSector->SetColor(rgba);\r\n\t}\t\r\n\tif (mpClonedRailSector)\r\n\t{\r\n\t\tmpClonedRailSector->SetColor(rgba);\r\n\t}\t\r\n}\r\n\r\n// Used by graffiti games\r\nvoid CEditedRailPoint::ClearColor()\r\n{\r\n\tif (mpPostSector)\r\n\t{\r\n\t\tmpPostSector->ClearColor();\r\n\t}\t\r\n\tif (mpClonedRailSector)\r\n\t{\r\n\t\tmpClonedRailSector->ClearColor();\r\n\t}\t\r\n}\r\n\r\nvoid CEditedRailPoint::SetSectorActiveStatus(bool active)\r\n{\r\n\tif (mpPostSector)\r\n\t{\r\n\t\tmpPostSector->SetActive(active);\r\n\t}\t\r\n\tif (mpClonedRailSector)\r\n\t{\r\n\t\tmpClonedRailSector->SetActive(active);\r\n\t}\t\r\n}\r\n\r\nbool CEditedRailPoint::AngleIsOKToGrind()\r\n{\r\n\tif (mpNext && mpPrevious)\r\n\t{\r\n\t\treturn s_angle_is_ok_to_grind(mpNext->mPos, mPos, mpPrevious->mPos);\r\n\t}\r\n\treturn true;\t\r\n}\r\n\r\nvoid CEditedRailPoint::WriteCompressedRailPoint(SCompressedRailPoint *p_dest)\r\n{\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest\"));\r\n\t\r\n\tp_dest->mHasPost=mHasPost;\r\n\t\r\n\t// Sometimes the point may have a height that is fractionally below zero, so instead of asserting\r\n\t// clamp it to zero.\r\n\t//Dbg_MsgAssert(mHeightAboveGround >= 0.0f,(\"Expected mHeightAboveGround to be >= 0 ? (is %f)\",mHeightAboveGround));\r\n\tif (mHeightAboveGround < 0.0f)\r\n\t{\r\n\t\tp_dest->mHeight=0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_dest->mHeight=(uint16)(mHeightAboveGround*16.0f);\r\n\t}\t\r\n\t\r\n\tDbg_MsgAssert(fabs(mPos[X]*8.0f)<=32767.0f,(\"Rail point position x=%f out of range\",mPos[X]));\r\n\tDbg_MsgAssert(fabs(mPos[Y]*8.0f)<=32767.0f,(\"Rail point position y=%f out of range\",mPos[Y]));\r\n\tDbg_MsgAssert(fabs(mPos[Z]*8.0f)<=32767.0f,(\"Rail point position z=%f out of range\",mPos[Z]));\r\n\t\r\n\tp_dest->mX=(sint16)(mPos[X]*8.0f);\r\n\tp_dest->mY=(sint16)(mPos[Y]*8.0f);\r\n\tp_dest->mZ=(sint16)(mPos[Z]*8.0f);\r\n}\r\n\r\nCEditedRail::CEditedRail()\r\n{\r\n\tmId=s_rail_unique_id++;\r\n\t\r\n\tmpRailPoints=NULL;\r\n\tmpNext=NULL;\r\n\tmpPrevious=NULL;\r\n\tClear();\r\n}\r\n\r\nCEditedRail::~CEditedRail()\r\n{\r\n\tClear();\r\n}\r\n\r\nvoid CEditedRail::Clear()\r\n{\r\n\tCEditedRailPoint *p_rail_point=mpRailPoints;\r\n\twhile (p_rail_point)\r\n\t{\r\n\t\tCEditedRailPoint *p_next=p_rail_point->mpNext;\r\n\t\tdelete p_rail_point;\r\n\t\tp_rail_point=p_next;\r\n\t}\t\r\n\tmpRailPoints=NULL;\r\n}\r\n\r\n// Runs through all the points and adjusts the y coords so that the stored heights match the actual\r\n// heights above the ground. This is used to keep the post heights constant when raising or lowering the\r\n// ground in the park editor.\r\nvoid CEditedRail::AdjustYs()\r\n{\r\n\tCEditedRailPoint *p_rail_point=mpRailPoints;\r\n\twhile (p_rail_point)\r\n\t{\r\n\t\tp_rail_point->AdjustY();\r\n\t\tp_rail_point=p_rail_point->mpNext;\r\n\t}\t\r\n}\r\n\r\nvoid CEditedRail::InitialiseHeights()\r\n{\r\n\tCEditedRailPoint *p_rail_point=mpRailPoints;\r\n\twhile (p_rail_point)\r\n\t{\r\n\t\tp_rail_point->InitialiseHeight();\r\n\t\tp_rail_point=p_rail_point->mpNext;\r\n\t}\t\r\n}\r\n\r\nvoid CEditedRail::UpdateRailGeometry(Mth::Vector& rotateCentre, Mth::Vector& newCentre, float degrees)\r\n{\r\n\t// Find the last rail point.\r\n\tCEditedRailPoint *p_rail_point=mpRailPoints;\r\n\tCEditedRailPoint *p_last=NULL;\r\n\twhile (p_rail_point)\r\n\t{\r\n\t\tp_last=p_rail_point;\r\n\t\tp_rail_point=p_rail_point->mpNext;\r\n\t}\t\r\n\r\n\t// It is necessary to traverse the list backwards because UpdateRailGeometry() uses some of the vertices of the next\r\n\t// rail in the list for the end points of its rail, so the next rail needs to have been updated first.\r\n\tp_rail_point=p_last;\r\n\twhile (p_rail_point)\r\n\t{\r\n\t\tp_rail_point->UpdateRailGeometry(rotateCentre, newCentre, degrees);\r\n\t\tp_rail_point=p_rail_point->mpPrevious;\r\n\t}\t\r\n}\r\n\r\nvoid CEditedRail::UpdatePostGeometry(Mth::Vector& rotateCentre, Mth::Vector& newCentre, float degrees)\r\n{\r\n\tCEditedRailPoint *p_rail_point=mpRailPoints;\r\n\twhile (p_rail_point)\r\n\t{\r\n\t\tp_rail_point->UpdatePostGeometry(rotateCentre, newCentre, degrees);\r\n\t\tp_rail_point=p_rail_point->mpNext;\r\n\t}\t\r\n}\r\n\r\nvoid CEditedRail::DestroyRailGeometry()\r\n{\r\n\tCEditedRailPoint *p_rail_point=mpRailPoints;\r\n\twhile (p_rail_point)\r\n\t{\r\n\t\tp_rail_point->DestroyRailGeometry();\r\n\t\tp_rail_point=p_rail_point->mpNext;\r\n\t}\t\r\n}\r\n\r\nvoid CEditedRail::DestroyPostGeometry()\r\n{\r\n\tCEditedRailPoint *p_rail_point=mpRailPoints;\r\n\twhile (p_rail_point)\r\n\t{\r\n\t\tp_rail_point->DestroyPostGeometry();\r\n\t\tp_rail_point=p_rail_point->mpNext;\r\n\t}\t\r\n}\r\n\r\nCEditedRailPoint *CEditedRail::AddPoint()\r\n{\r\n\tif (CEditedRailPoint::SGetNumUsedItems()==MAX_EDITED_RAIL_POINTS)\r\n\t{\r\n\t\t// No space left on the pool to store a new point.\r\n\t\treturn NULL;\r\n\t}\r\n\t\r\n\tCEditedRailPoint *p_new=new CEditedRailPoint;\r\n\tp_new->mpNext=mpRailPoints;\r\n\tif (mpRailPoints)\r\n\t{\r\n\t\tmpRailPoints->mpPrevious=p_new;\r\n\t}\r\n\tp_new->mpPrevious=NULL;\r\n\tmpRailPoints=p_new;\r\n\t\r\n\treturn p_new;\t\r\n}\r\n\r\nint CEditedRail::CountPoints()\r\n{\r\n\tint num_points=0;\r\n\tCEditedRailPoint *p_point=mpRailPoints;\r\n\twhile (p_point)\r\n\t{\r\n\t\t++num_points;\r\n\t\tp_point=p_point->mpNext;\r\n\t}\r\n\treturn num_points;\r\n}\r\n\r\nbool CEditedRail::FindNearestRailPoint(Mth::Vector &pos,\r\n\t\t\t\t\t\t\t\t\t   Mth::Vector *p_nearest_pos, float *p_dist_squared, int *p_rail_point_index, \r\n\t\t\t\t\t\t\t\t\t   int ignore_index)\r\n{\r\n\tif (!mpRailPoints)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\tCEditedRailPoint *p_point=mpRailPoints;\r\n\tint rail_point_index=0;\r\n\tfloat min_dist_squared=100000000.0f;\r\n\twhile (p_point)\r\n\t{\r\n\t\tif (rail_point_index != ignore_index)\r\n\t\t{\r\n\t\t\tMth::Vector diff=p_point->mPos-pos;\r\n\t\t\t// Zero the y so that one does not have to raise the cursor to make high rails highlight.\r\n\t\t\t// (Make's a big difference!)\r\n\t\t\tdiff[Y]=0.0f;\r\n\t\t\tfloat dd=diff.LengthSqr();\r\n\t\t\t\r\n\t\t\tif (dd < min_dist_squared)\r\n\t\t\t{\r\n\t\t\t\tmin_dist_squared=dd;\r\n\t\t\t\t\r\n\t\t\t\t*p_nearest_pos=p_point->mPos;\r\n\t\t\t\t*p_dist_squared=min_dist_squared;\r\n\t\t\t\t*p_rail_point_index=rail_point_index;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\t\r\n\t\tp_point=p_point->mpNext;\r\n\t\t++rail_point_index;\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\nint CEditedRail::CountPointsInArea(float x0, float z0, float x1, float z1)\r\n{\r\n\tint num_points=0;\r\n\r\n   \tCEditedRailPoint *p_point=mpRailPoints;\r\n\twhile (p_point)\r\n\t{\r\n\t\tif (p_point->mPos[X] > x0 && p_point->mPos[X] < x1 &&\r\n\t\t\tp_point->mPos[Z] > z0 && p_point->mPos[Z] < z1)\r\n\t\t{\r\n\t\t\t// The point is inside the area\r\n\t\t\t++num_points;\r\n\t\t}\r\n\t\t\t\r\n\t\tp_point=p_point->mpNext;\r\n\t}\t\r\n\t\r\n\treturn num_points;\r\n}\r\n\r\nvoid CEditedRail::DuplicateAndAddPoint(CEditedRailPoint *p_point)\r\n{\r\n\tDbg_MsgAssert(p_point,(\"NULL p_point\"));\r\n\t\r\n\tCEditedRailPoint *p_new_point=AddPoint();\r\n\tDbg_MsgAssert(p_new_point,(\"NULL p_new_point\"));\r\n\t\r\n\tp_new_point->mPos=p_point->mPos;\r\n\tp_new_point->mHasPost=p_point->mHasPost;\r\n\t\r\n\tp_new_point->mHeightAboveGround=p_point->mHeightAboveGround;\r\n}\r\n\r\nCEditedRail *CEditedRail::GenerateDuplicateRails(float x0, float z0, float x1, float z1, CEditedRail *p_head)\r\n{\r\n\tbool inside=false;\r\n\tCEditedRailPoint *p_first_point_of_new_rail=NULL;\r\n\t\r\n   \tCEditedRailPoint *p_point=mpRailPoints;\r\n\twhile (p_point)\r\n\t{\r\n\t\tif (p_point->mPos[X] > x0 && p_point->mPos[X] < x1 &&\r\n\t\t\tp_point->mPos[Z] > z0 && p_point->mPos[Z] < z1)\r\n\t\t{\r\n\t\t\t// The point is inside the area\r\n\t\t\t\r\n\t\t\tif (inside)\r\n\t\t\t{\r\n\t\t\t\tif (p_first_point_of_new_rail)\r\n\t\t\t\t{\r\n\t\t\t\t\tCEditedRail *p_new_rail=new CEditedRail;\r\n\t\t\t\t\tp_new_rail->mpNext=p_head;\r\n\t\t\t\t\tp_head=p_new_rail;\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_head->DuplicateAndAddPoint(p_first_point_of_new_rail);\r\n\t\t\t\t\tp_first_point_of_new_rail=NULL;\r\n\t\t\t\t}\t\r\n\t\t\t\tp_head->DuplicateAndAddPoint(p_point);\r\n\t\t\t}\r\n\t\t\telse\t\r\n\t\t\t{\r\n\t\t\t\t// Gone from outside to inside, so it's time to make a new rail.\r\n\t\t\t\t// Don't actually create the rail yet though, since it may only end up containing\r\n\t\t\t\t// one point, & don't want to create those.\r\n\t\t\t\tp_first_point_of_new_rail=p_point;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tinside=true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_first_point_of_new_rail=NULL;\r\n\t\t\tinside=false;\t\r\n\t\t}\r\n\t\t\t\r\n\t\tp_point=p_point->mpNext;\r\n\t}\t\r\n\r\n\treturn p_head;\r\n}\r\n\r\nvoid CEditedRail::UnHighlight()\r\n{\r\n   \tCEditedRailPoint *p_point=mpRailPoints;\r\n\twhile (p_point)\r\n\t{\r\n\t\tp_point->UnHighlight();\r\n\t\tp_point=p_point->mpNext;\r\n\t}\t\r\n}\r\n\r\nCEditedRailPoint *CEditedRail::GetRailPointFromIndex(int index)\r\n{\r\n   \tCEditedRailPoint *p_point=mpRailPoints;\r\n\twhile (index)\r\n\t{\r\n\t\tif (!p_point)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tp_point=p_point->mpNext;\r\n\t\t--index;\r\n\t}\t\r\n\tDbg_MsgAssert(p_point,(\"Could not find rail point with index %d\",index));\r\n\t\r\n\treturn p_point;\r\n}\r\n\r\n// Deletes p_point from the rail, and returns a pointer to any fragment that gets created.\r\n// If the max rails has been reached and deleting the point will result in a fragment,\r\n// then it won't delete the point after all, because a new rail will not be able to be created for\r\n// the fragment.\r\nCEditedRailPoint *CEditedRail::DeleteRailPoint(CEditedRailPoint *p_point)\r\n{\r\n\tif (!p_point)\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\t\r\n\t// Check that p_point is in the rail ...\r\n\t#ifdef __NOPT_ASSERT__\r\n\tbool found=false;\r\n\tCEditedRailPoint *p_check=mpRailPoints;\r\n\twhile (p_check)\r\n\t{\r\n\t\tif (p_check == p_point)\r\n\t\t{\r\n\t\t\tfound=true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tp_check=p_check->mpNext;\r\n\t}\r\n\tDbg_MsgAssert(found,(\"p_point is not in the rail !\"));\t\t\r\n\t#endif\r\n\t\r\n\tif (p_point->mpPrevious && p_point->mpNext)\r\n\t{\r\n\t\t// A new rail will need to be created so bail out if there is not enough\r\n\t\t// space to create one.\r\n\t\tif (CEditedRail::SGetNumUsedItems()==MAX_EDITED_RAILS)\r\n\t\t{\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Update this rail if removing its first point.\r\n\tif (p_point == mpRailPoints)\r\n\t{\r\n\t\tDbg_MsgAssert(p_point->mpPrevious==NULL,(\"Expected p_point->mpPrevious==NULL\"));\r\n\t\tmpRailPoints=p_point->mpNext;\r\n\t\tif (p_point->mpNext)\r\n\t\t{\r\n\t\t\tp_point->mpNext->mpPrevious=NULL;\r\n\t\t}\r\n\t\tdelete p_point;\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tDbg_MsgAssert(p_point->mpPrevious,(\"Expected p_point->mpPrevious not to be NULL\"));\r\n\t// Remove any rail geometry connecting the adjacent point to this one.\r\n\tp_point->mpPrevious->DestroyRailGeometry();\r\n\t// Terminate this rail.\r\n\tp_point->mpPrevious->mpNext=NULL;\r\n\t\r\n\t// Return the new rail fragment.\r\n\tCEditedRailPoint *p_fragment_start=p_point->mpNext;\r\n\tdelete p_point;\r\n\t\r\n\tif (p_fragment_start)\r\n\t{\r\n\t\tp_fragment_start->mpPrevious=NULL;\r\n\t}\r\n\treturn p_fragment_start;\r\n}\r\n\r\nbool CEditedRail::UpdateRailPointPosition(int rail_point_index, Mth::Vector &pos, EUpdateSuperSectors updateSuperSectors)\r\n{\r\n   \tCEditedRailPoint *p_point=GetRailPointFromIndex(rail_point_index);\r\n\t\r\n\t// UpdateRailPointPosition returns false if the position is bad in that it is\r\n\t// too close to an adjacent point or causes the rail to be too steep.\r\n\t// It still writes in the position so that the rail always stays attached to\r\n\t// the cursor as the user moves it around when in grab mode.\r\n\t// However, it won't write in the position if one of the rails will be stretched too long,\r\n\t// because that causes rendering problems.\r\n\t\r\n\tbool position_is_ok=true;\r\n\tif (p_point->mpNext)\r\n\t{\r\n\t\tif (!s_positions_OK(pos,p_point->mpNext->mPos))\r\n\t\t{\r\n\t\t\tposition_is_ok=false;\r\n\t\t}\r\n\t}\r\n\tif (p_point->mpPrevious)\r\n\t{\r\n\t\tif (!s_positions_OK(pos,p_point->mpPrevious->mPos))\r\n\t\t{\r\n\t\t\tposition_is_ok=false;\r\n\t\t}\r\n\t}\r\n\r\n\t// Don't allow points to be placed too close to the boundary of the park (TT5464)\r\n\tif (!Ed::IsWithinParkBoundaries(pos,PARK_BOUNDARY_MARGIN))\r\n\t{\r\n\t\tposition_is_ok=false;\r\n\t}\r\n\r\n\tbool ok_to_update=true;\r\n\tif (p_point->mpNext)\r\n\t{\r\n\t\tif (s_distance_is_way_too_long(pos,p_point->mpNext->mPos))\r\n\t\t{\r\n\t\t\tok_to_update=false;\r\n\t\t}\t\r\n\t}\r\n\tif (p_point->mpPrevious)\r\n\t{\r\n\t\tif (s_distance_is_way_too_long(pos,p_point->mpPrevious->mPos))\r\n\t\t{\r\n\t\t\tok_to_update=false;\r\n\t\t}\t\r\n\t}\r\n\r\n\r\n\tif (ok_to_update)\r\n\t{\r\n\t\tp_point->mPos=pos;\r\n\t\tp_point->InitialiseHeight();\r\n\t\tp_point->UpdatePostGeometry();\r\n\t\tp_point->UpdateRailGeometry();\r\n\t\tif (p_point->mpPrevious)\r\n\t\t{\r\n\t\t\tp_point->mpPrevious->UpdateRailGeometry();\r\n\t\t}\t\r\n\t\r\n\t\t// Updating the super sectors is technically required every time the collision verts on a sector\r\n\t\t// are modified, as they will be by this function.\r\n\t\t// If UpdateSuperSectors is not done, then when attempting to delete the sector later the low-level code\r\n\t\t// (in nxscene) will assert.\r\n\t\t// However, it can be slow to call UpdateSuperSectors every frame, so when a rail point is being dragged\r\n\t\t// around in grab mode it is not called. It is only called when placing the new point or when backing\r\n\t\t// out and restoring the old position.\r\n\t\tif (updateSuperSectors)\r\n\t\t{\r\n\t\t\tNx::CScene *p_cloned_scene=Ed::CParkManager::sInstance()->GetGenerator()->GetClonedScene();\r\n\t\t\tDbg_MsgAssert(p_cloned_scene,(\"NULL p_cloned_scene ?\"));\r\n\t\t\tp_cloned_scene->UpdateSuperSectors();\r\n\t\t}\r\n\t}\r\n\t\t\r\n\treturn position_is_ok;\r\n}\r\n\r\n// Used when pasting a rail\r\nvoid CEditedRail::CopyRail(CEditedRail *p_source_rail)\r\n{\r\n\tClear();\r\n\t\r\n\tDbg_MsgAssert(p_source_rail,(\"NULL p_source_rail\"));\r\n\t\r\n\tCEditedRailPoint *p_source_point=p_source_rail->mpRailPoints;\r\n\twhile (p_source_point)\r\n\t{\r\n\t\tCEditedRailPoint *p_new_point=AddPoint();\r\n\t\t\r\n\t\tp_new_point->mPos=p_source_point->mPos;\r\n\t\tp_new_point->mHasPost=p_source_point->mHasPost;\r\n\t\tp_new_point->mHeightAboveGround=p_source_point->mHeightAboveGround;\r\n\t\t\r\n\t\tp_source_point=p_source_point->mpNext;\r\n\t}\t\r\n}\r\n\r\n// Used when pasting a rail\r\nvoid CEditedRail::RotateAndTranslate(Mth::Vector& rotateCentre, Mth::Vector& newCentre, float degrees)\r\n{\r\n\tCEditedRailPoint *p_point=mpRailPoints;\r\n\twhile (p_point)\r\n\t{\r\n\t\tp_point->mPos=s_rotate_and_translate(p_point->mPos, rotateCentre, newCentre, degrees);\r\n\t\tp_point=p_point->mpNext;\r\n\t}\r\n}\r\n\r\nSCompressedRailPoint *CEditedRail::WriteCompressedRailPoints(SCompressedRailPoint *p_dest)\r\n{\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest\"));\r\n\r\n\tCEditedRailPoint *p_point=mpRailPoints;\r\n\t// Skip to the end of the list of points so that it can be traversed backwards.\r\n\t// This is so that when the rails are regenerated using InitUsingCompressedRailsBuffer()\r\n\t// they get recreated with the points in the original order, and hence the rail node indices \r\n\t// will match on the server and client. \r\n\twhile (p_point && p_point->mpNext)\r\n\t{\r\n\t\tp_point=p_point->mpNext;\r\n\t}\r\n\t\r\n\twhile (p_point)\r\n\t{\r\n\t\tp_point->WriteCompressedRailPoint(p_dest++);\r\n\t\tp_point=p_point->mpPrevious;\r\n\t}\r\n\treturn p_dest;\r\n}\r\n\r\n// Used by graffiti games\r\nvoid CEditedRail::ModulateRailColor(int seqIndex)\r\n{\r\n\tScript::CArray* p_graffiti_col_tab = Script::GetArray( CRCD(0x7f1ba1aa,\"graffitiColors\") );\r\n\tDbg_MsgAssert( (uint) seqIndex < p_graffiti_col_tab->GetSize(), ( \"graffitiColors array too small\" ) );\r\n\r\n\tScript::CArray *p_entry = p_graffiti_col_tab->GetArray(seqIndex);\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tint size = p_entry->GetSize();\r\n\tDbg_MsgAssert(size >= 3 && size <= 4, (\"wrong size %d for color array\", size));\r\n\t#endif\r\n\t\r\n\tImage::RGBA color;\r\n\r\n\tcolor.r = p_entry->GetInteger( 0 );\r\n\tcolor.g = p_entry->GetInteger( 1 );\r\n\tcolor.b = p_entry->GetInteger( 2 );\r\n\tcolor.a = 128;\r\n\t\r\n\tCEditedRailPoint *p_point=mpRailPoints;\r\n\twhile (p_point)\r\n\t{\r\n\t\tp_point->SetColor(color);\r\n\t\tp_point=p_point->mpNext;\r\n\t}\r\n}\r\n\r\n// Used by graffiti games\r\nvoid CEditedRail::ClearRailColor()\r\n{\r\n\tCEditedRailPoint *p_point=mpRailPoints;\r\n\twhile (p_point)\r\n\t{\r\n\t\tp_point->ClearColor();\r\n\t\tp_point=p_point->mpNext;\r\n\t}\r\n}\r\n\r\nvoid CEditedRail::SetSectorActiveStatus(bool active)\r\n{\r\n\tCEditedRailPoint *p_point=mpRailPoints;\r\n\twhile (p_point)\r\n\t{\r\n\t\tp_point->SetSectorActiveStatus(active);\r\n\t\tp_point=p_point->mpNext;\r\n\t}\r\n}\r\n\r\nvoid CEditedRail::GetDebugInfo( Script::CStruct* p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info\"));\r\n\t\r\n\tp_info->AddChecksum(CRCD(0x40c698af,\"id\"),mId);\r\n\t\r\n\tint num_points=CountPoints();\r\n\t\t\r\n\tif (num_points)\r\n\t{\r\n\t\tScript::CArray *p_array=new Script::CArray;\r\n\t\tp_array->SetSizeAndType(num_points,ESYMBOLTYPE_STRUCTURE);\r\n\r\n\t\tint i=0;\r\n\t\tCEditedRailPoint *p_point=mpRailPoints;\r\n\t\twhile (p_point)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_struct=new Script::CStruct;\r\n\t\t\tp_struct->AddVector(CRCD(0x7f261953,\"pos\"),p_point->mPos[X],p_point->mPos[Y],p_point->mPos[Z]);\r\n\t\t\tp_struct->AddFloat(CRCD(0xab21af0,\"Height\"),p_point->mHeightAboveGround);\r\n\t\t\tp_struct->AddInteger(CRCD(0x41a51a93,\"mpClonedRailSector\"),(int)p_point->mpClonedRailSector);\r\n\t\t\tp_struct->AddInteger(CRCD(0x79ffd768,\"mpPostSector\"),(int)p_point->mpPostSector);\r\n\t\t\t\r\n\t\t\tp_array->SetStructure(i,p_struct);\r\n\t\t\t++i;\r\n\t\t\tp_point=p_point->mpNext;\r\n\t\t}\r\n\t\t\r\n\t\tp_info->AddArrayPointer(CRCD(0xd84571d6,\"Points\"),p_array);\r\n\t}\r\n#endif\t\t\t\t \r\n}\r\n\r\nbool CEditedRail::ThereAreRailPointsOutsideArea(float x0, float z0, float x1, float z1)\r\n{\r\n\tDbg_MsgAssert(x0 <= x1 && z0 <= z1,(\"Bad area\"));\r\n\t\r\n   \tCEditedRailPoint *p_point=mpRailPoints;\r\n\twhile (p_point)\r\n\t{\r\n\t\tif (p_point->mPos[X] < x0 || p_point->mPos[X] > x1 ||\r\n\t\t\tp_point->mPos[Z] < z0 || p_point->mPos[Z] > z1)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t\tp_point=p_point->mpNext;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CRailEditorComponent::sUpdateSuperSectorsAfterDeletingRailSectors=true;\r\n\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\n\r\nCBaseComponent* CRailEditorComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CRailEditorComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCRailEditorComponent::CRailEditorComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_RAILEDITOR );\r\n\r\n\tDbg_MsgAssert(MAX_EDITED_RAILS == MAX_EDITED_RAIL_POINTS/2,(\"Bad MAX_EDITED_RAILS\"));\r\n\t\r\n\tCEditedRailPoint::SCreatePool(MAX_EDITED_RAIL_POINTS, \"CEditedRailPoint\");\r\n\tCEditedRail::SCreatePool(MAX_EDITED_RAILS, \"CEditedRail\");\r\n\r\n\tmp_input_component=NULL;\r\n\tmp_editor_camera_component=NULL;\r\n\tmp_dotted_line_sector=NULL;\r\n\tm_dotted_line_sector_name=0;\r\n\tmp_edited_rails=NULL;\r\n\r\n\tclear_compressed_rails_buffer();\r\n\tClear();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCRailEditorComponent::~CRailEditorComponent()\r\n{\r\n\tClear();\r\n\tCEditedRailPoint::SRemovePool();\r\n\tCEditedRail::SRemovePool();\r\n}\r\n\r\nvoid CRailEditorComponent::clear_compressed_rails_buffer()\r\n{\r\n\tfor (uint i=0; i<sizeof(mp_compressed_rails_buffer); ++i)\r\n\t{\r\n\t\tmp_compressed_rails_buffer[i]=0;\r\n\t}\r\n}\r\n\r\nvoid CRailEditorComponent::generate_compressed_rails_buffer()\r\n{\r\n\tclear_compressed_rails_buffer();\r\n\t\r\n\t*(uint16*)mp_compressed_rails_buffer=count_rails();\r\n\tuint16 *p_num_points_in_rail=(uint16*)(mp_compressed_rails_buffer+2);\r\n\tSCompressedRailPoint *p_rail_point=(SCompressedRailPoint*)(p_num_points_in_rail+MAX_EDITED_RAILS);\r\n\t\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\t// Skip to the end of the list of rails so that it can be traversed backwards.\r\n\t// This is so that when the rails are regenerated using InitUsingCompressedRailsBuffer()\r\n\t// they get recreated in the original order, and hence the rail node indices will match on the\r\n\t// server and client. \r\n\twhile (p_rail && p_rail->mpNext)\r\n\t{\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n\t\t\r\n\twhile (p_rail)\r\n\t{\r\n\t\t*p_num_points_in_rail++=p_rail->CountPoints();\r\n\t\tp_rail_point=p_rail->WriteCompressedRailPoints(p_rail_point);\t\r\n\t\t\r\n\t\tp_rail=p_rail->mpPrevious;\r\n\t}\r\n\t\r\n\tDbg_MsgAssert((uint8*)p_rail_point <= mp_compressed_rails_buffer+sizeof(mp_compressed_rails_buffer),(\"p_rail_point overwrote end of buffer\"));\r\n\tDbg_MsgAssert(p_num_points_in_rail-(uint16*)(mp_compressed_rails_buffer+2)==*(uint16*)mp_compressed_rails_buffer,(\"Num rails mismatch\"));\r\n}\r\n\r\n// Used when sending rail info over the net.\r\nuint8 *CRailEditorComponent::GetCompressedRailsBuffer()\r\n{\r\n\tgenerate_compressed_rails_buffer();\r\n\treturn mp_compressed_rails_buffer;\r\n}\r\n\r\nvoid CRailEditorComponent::SetCompressedRailsBuffer(uint8 *p_buffer)\r\n{\r\n\tDbg_MsgAssert(p_buffer,(\"NULL p_buffer\"));\r\n\tmemcpy(mp_compressed_rails_buffer, p_buffer, sizeof(mp_compressed_rails_buffer));\r\n}\r\n\r\nvoid CRailEditorComponent::InitUsingCompressedRailsBuffer()\r\n{\r\n\tClear();\r\n\t\r\n\tuint16 num_rails=*(uint16*)mp_compressed_rails_buffer;\r\n\tuint16 *p_num_points_in_rail=(uint16*)(mp_compressed_rails_buffer+2);\r\n\tSCompressedRailPoint *p_rail_point=(SCompressedRailPoint*)(p_num_points_in_rail+MAX_EDITED_RAILS);\r\n\t\r\n\tfor (uint i=0; i<num_rails; ++i)\r\n\t{\r\n\t\tuint16 num_points=*p_num_points_in_rail++;\r\n\t\t\r\n\t\tCEditedRail *p_new_rail=NewRail();\r\n\t\tfor (uint p=0; p<num_points; ++p)\r\n\t\t{\r\n\t\t\tCEditedRailPoint *p_point=p_new_rail->AddPoint();\r\n\t\t\tif (p_point)\r\n\t\t\t{\r\n\t\t\t\tp_point->mHasPost=p_rail_point->mHasPost;\r\n\t\t\t\tp_point->mHeightAboveGround=p_rail_point->mHeight / 16.0f;\r\n\t\t\t\tp_point->mPos[X]=p_rail_point->mX / 8.0f;\r\n\t\t\t\tp_point->mPos[Y]=p_rail_point->mY / 8.0f;\r\n\t\t\t\tp_point->mPos[Z]=p_rail_point->mZ / 8.0f;\r\n\t\t\t}\r\n\t\t\t++p_rail_point;\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\nvoid CRailEditorComponent::AdjustYs()\r\n{\r\n\tSetSectorActiveStatus(false);\r\n\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tp_rail->AdjustYs();\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n\r\n\tSetSectorActiveStatus(true);\r\n}\r\n\r\nvoid CRailEditorComponent::InitialiseHeights()\r\n{\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tp_rail->InitialiseHeights();\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n}\r\n\r\nvoid CRailEditorComponent::UpdateRailGeometry()\r\n{\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tp_rail->UpdateRailGeometry();\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n\t\r\n\tNx::CScene *p_cloned_scene=Ed::CParkManager::sInstance()->GetGenerator()->GetClonedScene();\r\n\tDbg_MsgAssert(p_cloned_scene,(\"NULL p_cloned_scene ?\"));\r\n\tp_cloned_scene->UpdateSuperSectors();\r\n}\r\n\r\nvoid CRailEditorComponent::UpdatePostGeometry()\r\n{\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tp_rail->UpdatePostGeometry();\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n\t\r\n\tNx::CScene *p_cloned_scene=Ed::CParkManager::sInstance()->GetGenerator()->GetClonedScene();\r\n\tDbg_MsgAssert(p_cloned_scene,(\"NULL p_cloned_scene ?\"));\r\n\tp_cloned_scene->UpdateSuperSectors();\r\n}\r\n\r\nvoid CRailEditorComponent::DestroyRailGeometry()\r\n{\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tp_rail->DestroyRailGeometry();\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n}\r\n\r\nvoid CRailEditorComponent::DestroyPostGeometry()\r\n{\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tp_rail->DestroyPostGeometry();\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n}\r\n\r\nvoid CRailEditorComponent::RefreshGeometry()\r\n{\r\n\tInitialiseHeights();\r\n\tUpdateRailGeometry();\r\n\tUpdatePostGeometry();\r\n}\r\n\r\nvoid CRailEditorComponent::UnHighlightAllRails()\r\n{\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tp_rail->UnHighlight();\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n}\r\n\r\n// Removes the point p_point from the rail p_rail, so p_rail may contain no points afterwards.\r\n// May result in the creation of a new rail, if the point was not one of the end points of p_rail.\r\n// Returns true if it did create a new rail.\r\nbool CRailEditorComponent::DeleteRailPoint(CEditedRail *p_rail, CEditedRailPoint *p_point)\r\n{\r\n\tDbg_MsgAssert(p_rail,(\"NULL p_rail\"));\r\n\tDbg_MsgAssert(p_point,(\"NULL p_point\"));\r\n\r\n\tCEditedRailPoint *p_fragment=p_rail->DeleteRailPoint(p_point);\r\n\tif (p_fragment)\r\n\t{\r\n\t\tCEditedRail *p_new_rail=NewRail();\r\n\t\tp_new_rail->mpRailPoints=p_fragment;\r\n\t\treturn true;\r\n\t}\t\r\n\t\r\n\treturn false;\r\n}\r\n\r\n// Used when resizing the park, or when deleting rail points within an area using the area-select tool.\r\n// This will remove all rail points outside of, or inside of (x0,z0) (x1,z1)\r\n// It needs to be a member function of CRailEditorComponent rather than CEditedRail, because\r\n// it could result in the creation of new rails.\r\n// Returns true if it did create new rails.\r\nbool CRailEditorComponent::ClipRail(CEditedRail *p_rail, float x0, float z0, float x1, float z1, EClipType clipType)\r\n{\r\n\tDbg_MsgAssert(x0 <= x1,(\"Need x0 <= x1\"));\r\n\tDbg_MsgAssert(z0 <= z1,(\"Need z0 <= z1\"));\r\n\r\n\tCEditedRailPoint *p_point=p_rail->mpRailPoints;\r\n\twhile (p_point)\r\n\t{\r\n\t\tCEditedRailPoint *p_next=p_point->mpNext;\r\n\t\t\r\n\t\tbool delete_point=false;\r\n\t\t\r\n\t\tif (p_point->mPos[X] > x0 && p_point->mPos[X] < x1 &&\r\n\t\t\tp_point->mPos[Z] > z0 && p_point->mPos[Z] < z1)\r\n\t\t{\r\n\t\t\t// The point is inside the area\r\n\t\t\tif (clipType==DELETE_POINTS_INSIDE)\r\n\t\t\t{\r\n\t\t\t\tdelete_point=true;\r\n\t\t\t}\t\r\n\t\t}\r\n\t\telse\t\r\n\t\t{\r\n\t\t\t// The point is outside the area\r\n\t\t\tif (clipType==DELETE_POINTS_OUTSIDE)\r\n\t\t\t{\r\n\t\t\t\tdelete_point=true;\r\n\t\t\t}\t\r\n\t\t}\r\n\t\t\r\n\t\tif (delete_point)\r\n\t\t{\r\n\t\t\tif (DeleteRailPoint(p_rail, p_point))\r\n\t\t\t{\r\n\t\t\t\t// Deleting the point resulted in a new rail being created, which means that\r\n\t\t\t\t// p_next no longer belongs to this rail, so bail out.\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tp_point=p_next;\r\n\t}\t\t\r\n\t\r\n\treturn false;\r\n}\r\n\r\nvoid CRailEditorComponent::ClipRails(float x0, float z0, float x1, float z1, EClipType clipType)\r\n{\r\n\tif (x0 > x1)\r\n\t{\r\n\t\tfloat t=x0;\r\n\t\tx0=x1;\r\n\t\tx1=t;\r\n\t}\r\n\tif (z0 > z1)\r\n\t{\r\n\t\tfloat t=z0;\r\n\t\tz0=z1;\r\n\t\tz1=t;\r\n\t}\r\n\t\t\r\n\twhile (true)\r\n\t{\r\n\t\tbool created_new_rails=false;\r\n\t\t\r\n\t\tCEditedRail *p_rail=mp_edited_rails;\r\n\t\twhile (p_rail)\r\n\t\t{\r\n\t\t\tif (ClipRail(p_rail, x0, z0, x1, z1, clipType))\r\n\t\t\t{\r\n\t\t\t\tcreated_new_rails=true;\r\n\t\t\t}\t\r\n\t\t\tp_rail=p_rail->mpNext;\r\n\t\t}\t\t\r\n\t\t\r\n\t\t// Repeat until no new rails were created.\r\n\t\t// Any new rails created by the above ClipRail calls will have been stuck on the front of\r\n\t\t// the list, so mp_edited_rails will be different next time around.\r\n\t\tif (!created_new_rails)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n\tRemoveEmptyAndSinglePointRails();\r\n}\r\n\r\nbool CRailEditorComponent::ThereAreRailPointsOutsideArea(float x0, float z0, float x1, float z1)\r\n{\r\n\tif (x0 > x1)\r\n\t{\r\n\t\tfloat t=x0;\r\n\t\tx0=x1;\r\n\t\tx1=t;\r\n\t}\r\n\tif (z0 > z1)\r\n\t{\r\n\t\tfloat t=z0;\r\n\t\tz0=z1;\r\n\t\tz1=t;\r\n\t}\r\n\t\t\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tif (p_rail->ThereAreRailPointsOutsideArea(x0, z0, x1, z1))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\t\t\r\n\t\t\r\n\treturn false;\t\r\n}\r\n\r\n// Used when copying a set of rails to the clipboard.\r\n// Counts how many rail points will need to be created when copying the given area to the clipboard.\r\n// This allows it to bail out before attempting to copy if there are not enough points left in the pool.\r\nint CRailEditorComponent::CountPointsInArea(float x0, float z0, float x1, float z1)\r\n{\r\n\tif (x0 > x1)\r\n\t{\r\n\t\tfloat t=x0;\r\n\t\tx0=x1;\r\n\t\tx1=t;\r\n\t}\r\n\tif (z0 > z1)\r\n\t{\r\n\t\tfloat t=z0;\r\n\t\tz0=z1;\r\n\t\tz1=t;\r\n\t}\r\n\t\t\r\n\tint num_points=0;\r\n\t\t\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tnum_points += p_rail->CountPointsInArea(x0, z0, x1, z1);\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\t\t\r\n\t\r\n\treturn num_points;\r\n}\r\n\r\nbool CRailEditorComponent::AbleToCopyRails(float x0, float z0, float x1, float z1)\r\n{\r\n\treturn CountPointsInArea(x0,z0,x1,z1) <= GetNumFreePoints();\r\n}\r\n\r\nCEditedRail *CRailEditorComponent::GenerateDuplicateRails(float x0, float z0, float x1, float z1)\r\n{\r\n\tCEditedRail *p_duplicated_rails=NULL;\r\n\t\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tp_duplicated_rails=p_rail->GenerateDuplicateRails(x0, z0, x1, z1, p_duplicated_rails);\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n\t\t\r\n\treturn p_duplicated_rails;\r\n}\r\n\r\nbool CRailEditorComponent::FindNearestRailPoint(Mth::Vector &pos, Mth::Vector *p_nearest_pos, \r\n\t\t\t\t\t\t\t\t\t\t\t\tfloat *p_dist, \r\n\t\t\t\t\t\t\t\t\t\t\t\tuint32 *p_rail_id, int *p_rail_point_index,\r\n\t\t\t\t\t\t\t\t\t\t\t\tuint32 ignore_rail_id, int ignore_rail_point_index)\r\n{\r\n\tfloat min_dist_squared=100000000.0f;\r\n\tbool found_nearest_point=false;\r\n\t\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tMth::Vector nearest;\r\n\t\tfloat dist;\r\n\t\tint rail_point_index=0;\r\n\t\t\r\n\t\tint ignore_index=-1;\r\n\t\tif (p_rail->mId==ignore_rail_id)\r\n\t\t{\r\n\t\t\tignore_index=ignore_rail_point_index;\r\n\t\t}\t\r\n\t\t\r\n\t\tif (p_rail->FindNearestRailPoint(pos, &nearest, &dist, &rail_point_index, ignore_index))\r\n\t\t{\r\n\t\t\tif (dist < min_dist_squared)\r\n\t\t\t{\r\n\t\t\t\tmin_dist_squared=dist;\r\n\t\t\t\t*p_nearest_pos=nearest;\r\n\t\t\t\t*p_dist=dist;\r\n\t\t\t\t*p_rail_id=p_rail->mId;\r\n\t\t\t\t*p_rail_point_index=rail_point_index;\r\n\t\t\t\tfound_nearest_point=true;\r\n\t\t\t}\t\r\n\t\t}\r\n\t\t\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n\t\r\n\treturn found_nearest_point;\r\n}\r\n\r\n// For writing to memcard\r\nvoid CRailEditorComponent::WriteIntoStructure(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info\"));\r\n\t\r\n\tint num_rails=count_rails();\r\n\t\r\n\tScript::CArray *p_rails=new Script::CArray;\r\n\tp_rails->SetSizeAndType(num_rails,ESYMBOLTYPE_STRUCTURE);\r\n\t\r\n\tint index=0;\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tScript::CStruct *p_rail_info=new Script::CStruct;\r\n\t\t\r\n\t\t// Note: Don't need to write out the mId member because ReadFromBuffer will create new rails,\r\n\t\t// which will each get a new id on creation.\r\n\t\t\r\n\t\tint num_points=p_rail->CountPoints();\r\n\t\tScript::CArray *p_points=new Script::CArray;\r\n\t\tp_points->SetSizeAndType(num_points,ESYMBOLTYPE_STRUCTURE);\r\n\t\t\r\n\t\tint point_index=0;\r\n\t\tCEditedRailPoint *p_point=p_rail->mpRailPoints;\r\n\t\twhile (p_point)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_point_info=new Script::CStruct;\r\n\t\t\tp_point_info->AddVector(CRCD(0x7f261953,\"Pos\"),p_point->mPos[X],p_point->mPos[Y],p_point->mPos[Z]);\r\n\t\t\tif (p_point->mpPostSector)\r\n\t\t\t{\r\n\t\t\t\tp_point_info->AddChecksum(NONAME,CRCD(0xdcded772,\"HasPost\"));\r\n\t\t\t}\t\r\n\t\t\tp_points->SetStructure(point_index,p_point_info);\r\n\t\t\t\r\n\t\t\tp_point=p_point->mpNext;\r\n\t\t\t++point_index;\r\n\t\t}\t\r\n\r\n\t\tp_rail_info->AddArrayPointer(CRCD(0xd84571d6,\"Points\"),p_points);\r\n\t\tp_rails->SetStructure(index,p_rail_info);\r\n\t\t++index;\r\n\t\t\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n\t\r\n\tp_info->AddArrayPointer(CRCD(0x244550a6,\"CreatedRails\"),p_rails);\r\n}\r\n\r\n// For reading from memcard\r\nvoid CRailEditorComponent::ReadFromStructure(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info\"));\r\n\t\r\n\tClear();\r\n\t\r\n\tScript::CArray *p_rails=NULL;\r\n\tp_info->GetArray(CRCD(0x244550a6,\"CreatedRails\"),&p_rails);\r\n\tif (!p_rails)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tDbg_MsgAssert((int)p_rails->GetSize() <= GetNumFreeRails(),(\"Too many rails, got %d, max is %d\",p_rails->GetSize(),GetNumFreeRails()));\r\n\t\r\n\tfor (uint32 i=0; i<p_rails->GetSize(); ++i)\r\n\t{\r\n\t\tScript::CStruct *p_rail_info=p_rails->GetStructure(i);\r\n\t\tDbg_MsgAssert(p_rail_info,(\"Eh? NULL p_rail_info ?\"));\r\n\t\t\r\n\t\tNewRail();\r\n\t\t\r\n\t\tScript::CArray *p_points=NULL;\r\n\t\tp_rail_info->GetArray(CRCD(0xd84571d6,\"Points\"),&p_points,Script::ASSERT);\r\n\t\tfor (uint32 p=0; p<p_points->GetSize(); ++p)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(mp_current_rail,(\"NULL mp_current_rail ?\"));\r\n\t\t\tCEditedRailPoint *p_new_point=mp_current_rail->AddPoint();\r\n\t\t\t\r\n\t\t\tScript::CStruct *p_point_info=p_points->GetStructure(p);\r\n\t\t\tp_point_info->GetVector(CRCD(0x7f261953,\"pos\"),&p_new_point->mPos);\r\n\t\t\tif (p_point_info->ContainsFlag(CRCD(0xdcded772,\"HasPost\")))\r\n\t\t\t{\r\n\t\t\t\tp_new_point->mHasPost=true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CRailEditorComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// ** Add code to parse the structure, and initialize the component\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CRailEditorComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calline InitFromStructure()\r\n\t// but if that does not handle it, then will need to write a specific \r\n\t// function here. \r\n\t// The user might only want to update a single field in the structure\r\n\t// and we don't want to be asserting becasue everything is missing \r\n\t\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\nvoid CRailEditorComponent::Hide( bool shouldHide )\r\n{\r\n\tEd::CParkManager *p_park_manager=Ed::CParkManager::sInstance();\r\n\r\n\tif (shouldHide)\r\n\t{\r\n\t\tScript::RunScript(CRCD(0xec0a515,\"rail_editor_destroy_cursor\"));\r\n\t\tp_park_manager->GetGenerator()->CleanUpOutRailSet();\r\n\t\tUnHighlightAllRails();\r\n\t\tDeleteDottedLine();\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tScript::RunScript(CRCD(0x52d1ce6f,\"rail_editor_create_cursor\"));\r\n\r\n\t\t// Create the 'out rail' set within the park generator, required for snapping to the\r\n\t\t// nearest rail point.\r\n\t\tp_park_manager->GetGenerator()->GenerateOutRailSet(p_park_manager->GetConcreteMetaList());\r\n\t\t\r\n\t\t// Make sure we're using the skater's pad\r\n\t\tScript::CStruct *p_params=new Script::CStruct;\r\n\t\tp_params->AddInteger(CRCD(0x67e6859a,\"player\"),0);\r\n\t\tmp_input_component->InitFromStructure(p_params);\r\n\t\tdelete p_params;\r\n\r\n\t\t\r\n\t\t// This is a quick fix to a bug where button triggers are stored up whilst the\r\n\t\t// rail editor component is suspended. I think it's a bug in the input component, cos\r\n\t\t// surely it should ignore the pad whist suspended?\r\n\t\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\tcontrol_pad.Reset();\r\n\t}\r\n}\r\n\r\nvoid CRailEditorComponent::get_pos_from_camera_component(Mth::Vector *p_pos, float *p_height, float *p_angle)\r\n{\r\n\tDbg_MsgAssert(mp_editor_camera_component,(\"NULL mp_editor_camera_component ?\"));\r\n\t*p_pos=mp_editor_camera_component->GetCursorPos();\r\n\t*p_height=mp_editor_camera_component->GetCursorHeight();\r\n\t*p_angle=mp_editor_camera_component->GetCursorOrientation();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CRailEditorComponent::Finalize()\r\n{\r\n\t// Get the pointers to the other required components.\r\n\t\r\n\tDbg_MsgAssert(mp_input_component==NULL,(\"mp_input_component not NULL ?\"));\r\n\tmp_input_component = GetInputComponentFromObject(GetObject());\r\n\tDbg_MsgAssert(mp_input_component,(\"CRailEditorComponent requires parent object to have an input component!\"));\r\n\r\n\tDbg_MsgAssert(mp_editor_camera_component==NULL,(\"mp_editor_camera_component not NULL ?\"));\r\n\tmp_editor_camera_component = GetEditorCameraComponentFromObject(GetObject());\r\n\tDbg_MsgAssert(mp_editor_camera_component,(\"CRailEditorComponent requires parent object to have an EditorCamera component!\"));\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CRailEditorComponent::Update()\r\n{\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\r\n\tif (control_pad.m_x.GetTriggered())\r\n\t{\r\n\t\tcontrol_pad.m_x.ClearTrigger();\r\n\t\tScript::RunScript(CRCD(0x415f2afa,\"RailEditorX\"),NULL,GetObject());\r\n\t}\t\r\n\r\n\t#ifdef __PLAT_NGC__\r\n\tif (control_pad.m_square.GetTriggered())\r\n\t{\r\n\t\tcontrol_pad.m_square.ClearTrigger();\r\n\t\tScript::RunScript(CRCD(0x3ad21c4e,\"RailEditorTriangle\"),NULL,GetObject());\r\n\t}\t\r\n\r\n\tif (control_pad.m_triangle.GetTriggered())\r\n\t{\r\n\t\tcontrol_pad.m_triangle.ClearTrigger();\r\n\t\tScript::RunScript(CRCD(0xd8d956c9,\"RailEditorSquare\"),NULL,GetObject());\r\n\t}\t\r\n\t#else\r\n\tif (control_pad.m_triangle.GetTriggered())\r\n\t{\r\n\t\tcontrol_pad.m_triangle.ClearTrigger();\r\n\t\tScript::RunScript(CRCD(0x3ad21c4e,\"RailEditorTriangle\"),NULL,GetObject());\r\n\t}\t\r\n\r\n\tif (control_pad.m_square.GetTriggered())\r\n\t{\r\n\t\tcontrol_pad.m_square.ClearTrigger();\r\n\t\tScript::RunScript(CRCD(0xd8d956c9,\"RailEditorSquare\"),NULL,GetObject());\r\n\t}\t\r\n\t#endif\r\n\t\r\n\tif (control_pad.m_circle.GetTriggered())\r\n\t{\r\n\t\tcontrol_pad.m_circle.ClearTrigger();\r\n\t\tScript::RunScript(CRCD(0xc18d5b19,\"RailEditorCircle\"),NULL,GetObject());\r\n\t}\t\r\n\r\n\tScript::RunScript(CRCD(0x97153f0e,\"RailEditorEveryFrame\"),NULL,GetObject());\r\n}\r\n\r\nvoid CRailEditorComponent::Clear()\r\n{\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tCEditedRail *p_next=p_rail->mpNext;\r\n\t\tdelete p_rail;\r\n\t\tp_rail=p_next;\r\n\t}\r\n\tmp_edited_rails=NULL;\r\n\tmp_current_rail=NULL;\r\n\tm_mode=0;\r\n\tDeleteDottedLine();\r\n}\t\r\n\r\nvoid CRailEditorComponent::DeleteRail(CEditedRail *p_rail)\r\n{\r\n\tif (mp_edited_rails==p_rail)\r\n\t{\r\n\t\tmp_edited_rails=p_rail->mpNext;\r\n\t}\t\r\n\tif (mp_current_rail==p_rail)\r\n\t{\r\n\t\tmp_current_rail=p_rail->mpNext;\r\n\t}\t\r\n\r\n\tif (p_rail->mpNext)\r\n\t{\r\n\t\tp_rail->mpNext->mpPrevious=p_rail->mpPrevious;\r\n\t}\r\n\tif (p_rail->mpPrevious)\r\n\t{\r\n\t\tp_rail->mpPrevious->mpNext=p_rail->mpNext;\r\n\t}\r\n\tdelete p_rail;\r\n}\r\n\r\nCEditedRail *CRailEditorComponent::NewRail()\r\n{\r\n\tCEditedRail *p_new=new CEditedRail;\r\n\t\r\n\tp_new->mpNext=mp_edited_rails;\r\n\tp_new->mpPrevious=NULL;\r\n\tif (p_new->mpNext)\r\n\t{\r\n\t\tp_new->mpNext->mpPrevious=p_new;\r\n\t}\r\n\tmp_edited_rails=p_new;\r\n\tmp_current_rail=p_new;\t\r\n\t\r\n\treturn p_new;\r\n}\r\n\r\nCEditedRail *CRailEditorComponent::GetRail(uint32 id)\r\n{\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tif (p_rail->mId==id)\r\n\t\t{\r\n\t\t\treturn p_rail;\r\n\t\t}\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\t\t\r\n\treturn NULL;\r\n}\r\n\r\nvoid CRailEditorComponent::RemoveEmptyAndSinglePointRails()\r\n{\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tCEditedRail *p_next=p_rail->mpNext;\r\n\t\t\r\n\t\tif (p_rail->mpRailPoints == NULL || (p_rail->mpRailPoints && p_rail->mpRailPoints->mpNext==NULL))\r\n\t\t{\r\n\t\t\tDeleteRail(p_rail);\r\n\t\t}\t\r\n\t\tp_rail=p_next;\r\n\t}\t\t\r\n}\r\n\r\nint CRailEditorComponent::count_rails()\r\n{\r\n\tint num_rails=0;\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\t++num_rails;\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n\treturn num_rails;\r\n}\r\n\r\nint CRailEditorComponent::GetTotalRailNodesRequired()\r\n{\r\n\tint total_nodes=0;\r\n\t\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tCEditedRailPoint *p_point=p_rail->mpRailPoints;\r\n\t\twhile (p_point)\r\n\t\t{\r\n\t\t\t++total_nodes;\r\n\t\t\tp_point=p_point->mpNext;\r\n\t\t}\t\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n\t\r\n\treturn total_nodes;\r\n}\r\n\r\nvoid CRailEditorComponent::SetUpRailNodes(Script::CArray *p_nodeArray, int *p_nodeNum, uint32 firstID)\r\n{\r\n\tDbg_MsgAssert(p_nodeArray,(\"NULL p_nodeArray\"));\r\n\tDbg_MsgAssert(p_nodeNum,(\"NULL p_nodeNum\"));\r\n\t\r\n\tint node_index=*p_nodeNum;\r\n\tuint32 rail_point_id=firstID;\r\n\r\n\tint rail_index=0;\t\r\n\tchar p_rail_name[50];\r\n\t\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tCEditedRailPoint *p_point=p_rail->mpRailPoints;\r\n\t\twhile (p_point)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_node=p_nodeArray->GetStructure(node_index++);\r\n\t\r\n\t\t\tp_node->AddVector(CRCD(0x7f261953,\"Pos\"),p_point->mPos[X],p_point->mPos[Y],p_point->mPos[Z]);\r\n\t\t\tp_node->AddVector(CRCD(0x9d2d0915,\"Angles\"),0.0f,0.0f,0.0f);\r\n\t\t\t\r\n\t\t\tp_node->AddChecksum(CRCD(0xa1dc81f9,\"Name\"),rail_point_id++);\r\n\t\t\t\r\n\t\t\tp_node->AddChecksum(CRCD(0x12b4e660,\"Class\"),CRCD(0x8e6b02ad,\"RailNode\"));\r\n\t\t\tp_node->AddChecksum(NONAME,CRCD(0x7c2552b9,\"CreatedAtStart\"));\r\n\t\t\t\r\n\t\t\tp_node->AddChecksum(NONAME,CRCD(0x1645b830,\"TrickObject\"));\r\n\t\t\tsprintf(p_rail_name,\"CreatedRailCluster%d\",rail_index);\r\n\t\t\tp_node->AddChecksum(CRCD(0x1a3a966b,\"Cluster\"),Script::GenerateCRC(p_rail_name));\r\n\t\t\t\r\n\t\t\t// hardwire to metal for the moment\r\n\t\t\tp_node->AddChecksum(CRCD(0x54cf8532,\"TerrainType\"),CRCD(0xa9ecf4e9,\"TERRAIN_METALSMOOTH\"));\r\n\t\t\t\r\n\t\t\tif (p_point->mpNext)\r\n\t\t\t{\r\n\t\t\t\tScript::CArray *p_links = new Script::CArray();\r\n\t\t\t\tp_links->SetSizeAndType(1,ESYMBOLTYPE_INTEGER);\r\n\t\t\t\tp_links->SetInteger(0, node_index);\r\n\t\t\t\tp_node->AddArrayPointer(CRCD(0x2e7d5ee7,\"Links\"), p_links);\r\n\t\t\t}\t\t\t\r\n\r\n\t\t\t// An attempt to make graffiti mode able to tag created rails, didn't work though\r\n\t\t\t// (TT11801)\r\n\t\t\t//p_node->AddChecksum(NONAME,CRCD(0x1645b830,\"TrickObject\"));\r\n\t\t\t//char p_cluster_name[20];\r\n\t\t\t//sprintf(p_cluster_name,\"RailCluster%d\",node_index);\r\n\t\t\t//p_node->AddChecksum(CRCD(0x1a3a966b,\"Cluster\"),Script::GenerateCRC(p_cluster_name));\r\n\t\t\t\r\n\t\t\tp_point=p_point->mpNext;\r\n\t\t}\t\r\n\t\tp_rail=p_rail->mpNext;\r\n\t\t++rail_index;\r\n\t}\r\n\r\n\t*p_nodeNum=node_index;\r\n}\r\n\r\nvoid CRailEditorComponent::DeleteDottedLine()\r\n{\r\n\tif (mp_dotted_line_sector)\r\n\t{\r\n\t\tNx::CScene *p_cloned_scene=Ed::CParkManager::sInstance()->GetGenerator()->GetClonedScene();\r\n\t\tDbg_MsgAssert(p_cloned_scene,(\"Missing cloned scene!\"));\r\n\t\tp_cloned_scene->DeleteSector(mp_dotted_line_sector);\r\n\t\t\r\n\t\tmp_dotted_line_sector=NULL;\r\n\t\tm_dotted_line_sector_name=0;\r\n\r\n\t\t#ifdef __PLAT_NGC__\r\n\t\tNx::CEngine::sFinishRendering();\r\n\t\t#endif\r\n\t\t\r\n\t\tp_cloned_scene->UpdateSuperSectors();\r\n\t}\t\r\n}\r\n\r\nvoid CRailEditorComponent::DrawDottedLine(Mth::Vector& pos)\r\n{\r\n\t// Do nothing if there is no last position to draw from.\r\n\tif (!mp_current_rail || !mp_current_rail->mpRailPoints)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tCEditedRailPoint *p_last_point=mp_current_rail->mpRailPoints;\r\n\t\r\n\t\r\n\tuint32 dotted_line_sector_name=CRCD(0x5dc3c690,\"Sk5Ed_RAdot_Dynamic_Green\");\r\n\tif (s_distance_is_too_long(p_last_point->mPos, pos))\r\n\t{\r\n\t\tif (s_distance_is_way_too_long(p_last_point->mPos, pos))\r\n\t\t{\r\n\t\t\t// If the rail sector is stretched too far it renders all weird, so don't draw it at all.\r\n\t\t\tDeleteDottedLine();\r\n\t\t\treturn;\r\n\t\t}\t\r\n\r\n\t\tdotted_line_sector_name=CRCD(0x8dda17d6,\"Sk5Ed_RADot_Dynamic\");\r\n\t}\r\n\telse if (p_last_point->mpNext)\r\n\t{\r\n\t\tif (!s_angle_is_ok_to_grind(p_last_point->mpNext->mPos, p_last_point->mPos, pos))\r\n\t\t{\r\n\t\t\tdotted_line_sector_name=CRCD(0x8dda17d6,\"Sk5Ed_RADot_Dynamic\");\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\t\r\n\t// Clone the sector if the dotted line does not exist or needs changing colour\r\n\tif (!mp_dotted_line_sector || dotted_line_sector_name != m_dotted_line_sector_name)\r\n\t{\r\n\t\tDeleteDottedLine();\r\n\t\tmp_dotted_line_sector=s_clone_sector(dotted_line_sector_name);\r\n\t\tm_dotted_line_sector_name=dotted_line_sector_name;\r\n\t}\r\n\t\r\n\tMth::Vector dummy;\r\n\ts_calculate_rail_sector_vertex_coords(dummy, p_last_point->mPos, pos, \r\n\t\t\t\t\t\t\t\t\t\t  mp_dotted_line_sector, m_dotted_line_sector_name,\r\n\t\t\t\t\t\t\t\t\t\t  NULL, false);\r\n\r\n\tif (dotted_line_sector_name==CRCD(0x8dda17d6,\"Sk5Ed_RADot_Dynamic\"))\r\n\t{\r\n\t\tint flash_rate=Script::GetInteger(CRCD(0xeebe4394,\"RailEditorRedLineFlashRate\"));\r\n\t\tuint32 vis=0xffffffff;\r\n\t\tif (s_highlight_flash_counter >= flash_rate/2)\r\n\t\t{\r\n\t\t\tvis=0;\r\n\t\t}\r\n\t\t\t\r\n\t\t++s_highlight_flash_counter;\r\n\t\tif (s_highlight_flash_counter >= flash_rate)\r\n\t\t{\r\n\t\t\ts_highlight_flash_counter=0;\r\n\t\t}\t\r\n\t\tmp_dotted_line_sector->SetVisibility(vis);\r\n\t}\r\n\t\t\t\t\t\t\t\t\t\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CRailEditorComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tcase 0x8f3e0b97: // GetCursorPosition\r\n\t\t{\r\n\t\t\tMth::Vector cursor_pos(0.0f,0.0f,0.0f);\t\t\r\n\t\t\tfloat cursor_height=0.0f;\r\n\t\t\tfloat cursor_angle=0.0f;\r\n\t\t\tget_pos_from_camera_component(&cursor_pos,&cursor_height,&cursor_angle);\r\n\t\t\tcursor_pos[Y]+=cursor_height;\r\n\t\t\t\r\n\t\t\tpScript->GetParams()->AddVector(CRCD(0x7f261953,\"Pos\"),cursor_pos[X],cursor_pos[Y],cursor_pos[Z]);\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0xff7ebaf6,\"Angle\"),mp_editor_camera_component->GetCursorOrientation()*180.0f/3.141592654f);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// Returns false if a new rail could not be created, due to the limit on the number of rails \r\n\t\t// being reached.\r\n\t\tcase 0xd2c98192: // NewRail\r\n\t\t{\r\n\t\t\tif (GetNumFreePoints()==0)\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tNewRail();\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0x31f66e6b: // MaxRailsReached\r\n\t\t{\r\n\t\t\tif (GetNumFreePoints()==0)\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase 0x5828e852: // AddNewPosition\r\n\t\t{\r\n\t\t\tMth::Vector pos;\r\n\t\t\tpos.Set();\r\n\t\t\tpParams->GetVector(CRCD(0x7f261953,\"pos\"),&pos);\r\n\t\t\tif (mp_current_rail)\r\n\t\t\t{\r\n\t\t\t\tCEditedRailPoint *p_last_point=mp_current_rail->mpRailPoints;\r\n\t\t\t\tif (p_last_point)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Don't allow placement of points that are too close, or segments that are too steep\r\n\t\t\t\t\tif (!s_positions_OK(p_last_point->mPos, pos))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// But return true anyway, otherwise the script will make the cursor switch out\r\n\t\t\t\t\t\t// of rail-layout mode.\r\n\t\t\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\r\n\r\n\t\t\t\t// Don't allow points to be placed too close to the boundary of the park (TT5464)\r\n\t\t\t\tif (!Ed::IsWithinParkBoundaries(pos,PARK_BOUNDARY_MARGIN))\r\n\t\t\t\t{\r\n\t\t\t\t\tif (p_last_point)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// We must be in rail-layout mode, so do not add the point but return true\r\n\t\t\t\t\t\t// so that the cursor stays in rail layout mode.\r\n\t\t\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\t\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\tSpt::SingletonPtr<Ed::CParkEditor> p_editor;\r\n\t\t\t\tif (p_editor->IsParkFull())\r\n\t\t\t\t{\r\n\t\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\r\n\t\t\r\n\t\t\t\tCEditedRailPoint *p_point=mp_current_rail->AddPoint();\r\n\t\t\t\tif (p_point)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_point->mPos=pos;\r\n\t\t\t\t\tp_point->mHeightAboveGround=pos[Y]-p_point->FindGroundY();\r\n\t\t\t\t\tp_point->mHasPost=pParams->ContainsFlag(CRCD(0xcb4b4880,\"AddPost\"));\r\n\t\t\t\t\tp_point->UpdateRailGeometry();\r\n\t\t\t\t\tp_point->UpdatePostGeometry();\r\n\t\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase 0x9c0762c4: // ClearRailEditor\r\n\t\t{\r\n\t\t\tClear();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x1cc3a173: // SetEditingMode\r\n\t\t{\r\n\t\t\tpParams->GetChecksum(CRCD(0x6835b854,\"mode\"),&m_mode);\r\n\t\t\t\r\n\t\t\tScript::CStruct *p_params=new Script::CStruct;\r\n\t\t\tp_params->AddChecksum(CRCD(0x6835b854,\"mode\"),CRCD(0xffd81c08,\"rail_placement\"));\r\n\t\t\tScript::RunScript(CRCD(0x9db065ad,\"parked_set_helper_text_mode\"),p_params);\r\n\t\t\tdelete p_params;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x63dd1204: // GetEditingMode\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddChecksum(CRCD(0x6835b854,\"mode\"),m_mode);\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\tcase 0xaa438d71: // DrawDottedLine\r\n\t\t{\r\n\t\t\tMth::Vector pos;\r\n\t\t\tpParams->GetVector(CRCD(0x7f261953,\"pos\"),&pos);\r\n\t\t\tDrawDottedLine(pos);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0x9386dcd9: // DeleteDottedLine\r\n\t\t{\r\n\t\t\tDeleteDottedLine();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x6d2eee1b: // UpdateRailPointPosition\r\n\t\t{\r\n\t\t\tuint32 rail_id=0;\r\n\t\t\tpParams->GetChecksum(CRCD(0xa61e7cd9,\"rail_id\"),&rail_id);\r\n\t\t\t\r\n\t\t\tint rail_point_index=0;\r\n\t\t\tpParams->GetInteger(CRCD(0xab3c14,\"rail_point_index\"),&rail_point_index);\r\n\t\t\t\r\n\t\t\tMth::Vector pos;\r\n\t\t\tpParams->GetVector(CRCD(0x7f261953,\"Pos\"),&pos);\r\n\r\n\t\t\tCEditedRail *p_rail=GetRail(rail_id);\r\n\t\t\tif (p_rail)\r\n\t\t\t{\r\n\t\t\t\t// UpdateRailPointPosition will always write in the new position, but returns\r\n\t\t\t\t// false if the position is bad in that it is too close to an adjacent point\r\n\t\t\t\t// or causes the rail to be too steep.\r\n\t\t\t\t// It still writes in the position so that the rail always stays attached to\r\n\t\t\t\t// the cursor as the user moves it around.\r\n\t\t\t\tif (!p_rail->UpdateRailPointPosition(rail_point_index, pos, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t (CEditedRail::EUpdateSuperSectors)pParams->ContainsFlag(CRCD(0xddf9a2bb,\"UpdateSuperSectors\"))))\r\n\t\t\t\t{\r\n\t\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\t\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0x8798e959: // HighlightRailPoint\r\n\t\t{\r\n\t\t\tuint32 rail_id=0;\r\n\t\t\tpParams->GetChecksum(CRCD(0xa61e7cd9,\"rail_id\"),&rail_id);\r\n\t\t\t\r\n\t\t\tint rail_point_index=0;\r\n\t\t\tpParams->GetInteger(CRCD(0xab3c14,\"rail_point_index\"),&rail_point_index);\r\n\r\n\t\t\tCEditedRail *p_rail=GetRail(rail_id);\r\n\t\t\tif (p_rail)\r\n\t\t\t{\r\n\t\t\t\tCEditedRailPoint *p_point=p_rail->GetRailPointFromIndex(rail_point_index);\r\n\t\t\t\tp_point->Highlight((CEditedRailPoint::EFlash)pParams->ContainsFlag(CRCD(0x5031a0fc,\"Flash\")), \r\n\t\t\t\t\t\t\t\t   (CEditedRailPoint::EEndPosts)pParams->ContainsFlag(CRCD(0x1a52e4b8,\"IncludeEndPosts\")));\r\n\t\t\t}\t\t\t\t\t   \r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0x6716227c: // DeleteRailPoint\r\n\t\t{\r\n\t\t\tuint32 rail_id=0;\r\n\t\t\tpParams->GetChecksum(CRCD(0xa61e7cd9,\"rail_id\"),&rail_id);\r\n\t\t\tCEditedRail *p_rail=GetRail(rail_id);\r\n\t\t\tif (!p_rail)\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tint rail_point_index=0;\r\n\t\t\tpParams->GetInteger(CRCD(0xab3c14,\"rail_point_index\"),&rail_point_index);\r\n\t\t\tCEditedRailPoint *p_point=p_rail->GetRailPointFromIndex(rail_point_index);\r\n\t\t\tif (!p_point)\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tDeleteRailPoint(p_rail, p_point);\r\n\t\t\tRemoveEmptyAndSinglePointRails();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase 0xd5a87eee: // UnHighlightAllRails\r\n\t\t{\r\n\t\t\tUnHighlightAllRails();\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\r\n\t\tcase 0xfb6a0888: // GetEditedRailInfo\r\n\t\t{\r\n\t\t\tuint32 rail_id=0;\r\n\t\t\tpParams->GetChecksum(CRCD(0xa61e7cd9,\"rail_id\"),&rail_id);\r\n\t\t\tCEditedRail *p_rail=GetRail(rail_id);\r\n\t\t\t\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0xe234f2b2,\"CurrentRail\")))\r\n\t\t\t{\r\n\t\t\t\tp_rail=mp_current_rail;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (p_rail)\r\n\t\t\t{\r\n\t\t\t\tpScript->GetParams()->AddChecksum(CRCD(0xa61e7cd9,\"rail_id\"),p_rail->mId);\r\n\t\t\t\tpScript->GetParams()->AddInteger(CRCD(0x6164266e,\"num_points\"),p_rail->CountPoints());\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tcase 0x353ea2a9: // DeleteRail\r\n\t\t{\r\n\t\t\tuint32 rail_id=0;\r\n\t\t\tpParams->GetChecksum(CRCD(0xa61e7cd9,\"rail_id\"),&rail_id);\r\n\t\t\tCEditedRail *p_rail=GetRail(rail_id);\r\n\t\t\tif (p_rail)\r\n\t\t\t{\r\n\t\t\t\tDeleteRail(p_rail);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0xd70781c3: // DestroyEditedRailSectors\r\n\t\t{\r\n\t\t\tCRailEditorComponent::sUpdateSuperSectorsAfterDeletingRailSectors=true;\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0x23a11cbc,\"DoNotUpdateSuperSectors\")))\r\n\t\t\t{\r\n\t\t\t\tCRailEditorComponent::sUpdateSuperSectorsAfterDeletingRailSectors=false;\r\n\t\t\t}\t\r\n\t\t\tDestroyRailGeometry();\r\n\t\t\tDestroyPostGeometry();\r\n\t\t\tCRailEditorComponent::sUpdateSuperSectorsAfterDeletingRailSectors=true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\nint CRailEditorComponent::GetNumFreePoints()\r\n{\r\n\treturn MAX_EDITED_RAIL_POINTS-CEditedRailPoint::SGetNumUsedItems();\r\n}\r\n\r\nint CRailEditorComponent::GetNumFreeRails()\r\n{\r\n\treturn MAX_EDITED_RAILS-CEditedRail::SGetNumUsedItems();\r\n}\r\n\r\nCEditedRail *CRailEditorComponent::get_rail_from_cluster_name(uint32 clusterChecksum)\r\n{\r\n\tchar p_rail_cluster_name[50];\r\n\tint rail_index=0;\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tsprintf(p_rail_cluster_name,\"CreatedRailCluster%d\",rail_index);\r\n\t\tif (clusterChecksum == Script::GenerateCRC(p_rail_cluster_name))\r\n\t\t{\r\n\t\t\treturn p_rail;\r\n\t\t}\t\r\n\t\t\t\r\n\t\tp_rail=p_rail->mpNext;\r\n\t\t++rail_index;\r\n\t}\t\r\n\treturn NULL;\r\n}\r\n\r\n// Used by graffiti games\r\nvoid CRailEditorComponent::ModulateRailColor(uint32 clusterChecksum, int seqIndex)\r\n{\r\n\tCEditedRail *p_rail=get_rail_from_cluster_name(clusterChecksum);\r\n\tif (p_rail)\r\n\t{\r\n\t\tp_rail->ModulateRailColor(seqIndex);\r\n\t}\t\r\n}\r\n\r\n// Used by graffiti games\r\nvoid CRailEditorComponent::ClearRailColor(uint32 clusterChecksum)\r\n{\r\n\tCEditedRail *p_rail=get_rail_from_cluster_name(clusterChecksum);\r\n\tif (p_rail)\r\n\t{\r\n\t\tp_rail->ClearRailColor();\r\n\t}\t\r\n}\r\n\r\n// Used for switching off collision on any created-rail sectors whilst the rail editor\r\n// cursor is doing collision checks.\r\n// This is because the rail sectors have a vertical collidable poly, which occasionally does cause\r\n// collisions, making the cursor ping up into the air. Must be some sort of floating point innaccuracy\r\n// (or too much accuracy), probably because the collision check vector is straight down the vertical poly.\r\nvoid CRailEditorComponent::SetSectorActiveStatus(bool active)\r\n{\r\n\tCEditedRail *p_rail=mp_edited_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tp_rail->SetSectorActiveStatus(active);\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CRailEditorComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CRailEditorComponent::GetDebugInfo\"));\r\n\r\n\tp_info->AddInteger(CRCD(0x8c75a6c1,\"NumFreeRailPoints\"),GetNumFreePoints());\r\n\tp_info->AddInteger(CRCD(0xe954b3d4,\"NumFreeRails\"),GetNumFreeRails());\r\n\t\r\n\tif (mp_current_rail)\r\n\t{\r\n\t\tScript::CStruct *p_struct=new Script::CStruct;\r\n\t\tmp_current_rail->GetDebugInfo(p_struct);\r\n\t\tp_info->AddStructurePointer(CRCD(0xe234f2b2,\"CurrentRail\"),p_struct);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_info->AddChecksum(CRCD(0xe234f2b2,\"CurrentRail\"),CRCD(0xda3403b0,\"NULL\"));\r\n\t}\r\n\t\t\r\n\tint num_rails=count_rails();\r\n\tif (num_rails)\r\n\t{\r\n\t\tScript::CArray *p_array=new Script::CArray;\r\n\t\tp_array->SetSizeAndType(num_rails,ESYMBOLTYPE_STRUCTURE);\r\n\t\t\r\n\t\tint i=0;\r\n\t\tCEditedRail *p_rail=mp_edited_rails;\r\n\t\twhile (p_rail)\r\n\t\t{\r\n\t\t\tScript::CStruct *p_struct=new Script::CStruct;\r\n\t\t\tp_rail->GetDebugInfo(p_struct);\r\n\t\t\tp_array->SetStructure(i,p_struct);\r\n\t\t\t++i;\r\n\t\t\tp_rail=p_rail->mpNext;\r\n\t\t}\r\n\t\tDbg_MsgAssert(i==num_rails,(\"Eh ?\"));\r\n\t\t\r\n\t\tp_info->AddArrayPointer(CRCD(0x7e17dfa9,\"Rails\"),p_array);\r\n\t}\r\n\t\t\r\n\t\r\n\t// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CRailEditorComponent *GetRailEditor()\r\n{\r\n\tObj::CCompositeObject *p_obj=(Obj::CCompositeObject*)Obj::CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0x5b509ad3,\"RailEditor\"));\r\n\tDbg_MsgAssert(p_obj,(\"No RailEditor object\"));\r\n\tObj::CRailEditorComponent *p_rail_editor=GetRailEditorComponentFromObject(p_obj);\r\n\tDbg_MsgAssert(p_rail_editor,(\"No rail editor component ???\"));\r\n\t\r\n\treturn p_rail_editor;\r\n}\r\n\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Components/RailEditorComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       RailEditorComponent.h\r\n//* OWNER:          Kendall Harrison\r\n//* CREATION DATE:  6/19/2003\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_RAILEDITORCOMPONENT_H__\r\n#define __COMPONENTS_RAILEDITORCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#ifndef __SYS_MEM_POOLABLE_H\r\n#include <sys/mem/poolable.h>\r\n#endif\r\n\r\n#ifndef __OBJECT_BASECOMPONENT_H__\r\n#include <gel/object/basecomponent.h>\r\n#endif\r\n\r\n#ifndef __GFX_IMAGE_IMAGEBASIC_H\r\n#include <gfx/image/imagebasic.h>\r\n#endif\r\n\r\n// Replace this with the CRCD of the component you are adding\r\n#define\t\tCRC_RAILEDITOR CRCD(0x5b509ad3,\"RailEditor\")\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or \r\n//  given an object\t\t\t\t \r\n#define\t\tGetRailEditorComponent() ((Obj::CRailEditorComponent*)GetComponent(CRC_RAILEDITOR))\r\n#define\t\tGetRailEditorComponentFromObject(pObj) ((Obj::CRailEditorComponent*)(pObj)->GetComponent(CRC_RAILEDITOR))\r\n\r\nnamespace Nx\r\n{\r\n\tclass CSector;\r\n}\r\n\t\r\nnamespace Obj\r\n{\r\nextern Mth::Vector ZeroVector;\r\n\r\nenum\r\n{\r\n\tMAX_EDITED_RAIL_POINTS=400,\r\n\t\r\n\t// Single point rails are not allowed, so the maximum possible number of rails will be half the\r\n\t// number of points, since the shortest rail will have 2 points.\r\n\tMAX_EDITED_RAILS=MAX_EDITED_RAIL_POINTS/2,\r\n};\r\n\r\nstruct SCompressedRailPoint\r\n{\r\n\t// These are the original float values * 8\r\n\tsint16 mX,mY,mZ;\r\n\t// This is the original float height * 16\r\n\tuint16 mHeight;\r\n\tuint16 mHasPost;\r\n};\r\n\t\r\nclass CEditedRailPoint : public Mem::CPoolable<CEditedRailPoint>\r\n{\r\npublic:\r\n\tCEditedRailPoint();\r\n\t~CEditedRailPoint();\r\n\r\n\tvoid WriteCompressedRailPoint(SCompressedRailPoint *p_dest);\r\n\t\r\n\tvoid UpdateRailGeometry(Mth::Vector& rotateCentre=ZeroVector, Mth::Vector& newCentre=ZeroVector, float degrees=0.0f);\r\n\tvoid UpdatePostGeometry(Mth::Vector& rotateCentre=ZeroVector, Mth::Vector& newCentre=ZeroVector, float degrees=0.0f);\r\n\tvoid DestroyRailGeometry();\r\n\tvoid DestroyPostGeometry();\r\n\t\r\n\tfloat FindGroundY();\r\n\tvoid AdjustY();\r\n\tvoid InitialiseHeight();\r\n\r\n\t// These enums are just to avoid passing multiple bools to Highlight()\r\n\tenum EFlash\r\n\t{\r\n\t\tDONT_FLASH=0,\r\n\t\tFLASH=1,\r\n\t};\r\n\tenum EEndPosts\r\n\t{\r\n\t\tDONT_INCLUDE_END_POSTS=0,\r\n\t\tINCLUDE_END_POSTS=1,\r\n\t};\t\r\n\tvoid Highlight(EFlash flash, EEndPosts includeEndPosts);\r\n\tvoid UnHighlight();\r\n\r\n\tvoid SetColor(Image::RGBA rgba);\r\n\tvoid ClearColor();\r\n\r\n\tvoid SetSectorActiveStatus(bool active);\r\n\t\r\n\tbool AngleIsOKToGrind();\r\n\t\t\r\n\t// This class needs to be kept as small as possible since a pool of them exists.\t\r\n\t\r\n\t// MEMOPT: Change pos to be 3 sint16's, would save 10K for 400 points.\r\n\t// Used x(fixed)=int(9.0f*x(float)+0.5f) if x>0, x(fixed)=int(9.0f*x(float)-0.5f) if x<0\r\n\tMth::Vector mPos;\r\n\t//sint16 m_x,m_y,m_z;\r\n\t\r\n\t// MEMOPT: Change to be bitfield of flags.\r\n\tbool mHasPost;\r\n\tbool mHighlighted;\r\n\t\r\n\t// The height is stored so that if the ground moves up or down, mPos[Y] can be recalculated\r\n\t// so as to maintain the post height.\r\n\tfloat mHeightAboveGround;\r\n\r\n\t\r\n\tCEditedRailPoint *mpNext;\t\r\n\t// TODO: MEMOPT\r\n\t// Don't really need the list to be doubly linked\r\n\tCEditedRailPoint *mpPrevious;\t\r\n\r\n\r\n\t// The rail geometry joining the last point to this point.\r\n\t// If this is the first point of the rail, mpClonedRailSector will be NULL.\r\n\tNx::CSector *mpClonedRailSector;\t\r\n\r\n\t// The post geometry joining this point to the ground. May be NULL, since the user chooses\r\n\t// whether they want a post.\r\n\t// Also, mpPostSector may be NULL even when mHasPost is true, because we don't always want \r\n\t// the geometry for the rail to exist.\r\n\t// For example, when loading a park off the memory card in the skateshop it will set the mPos\r\n\t// and mHasPost members, but the sector pointers will remain NULL until it is time to build the park.\r\n\tNx::CSector *mpPostSector;\r\n};\r\n\r\nclass CEditedRail : public Mem::CPoolable<CEditedRail>\r\n{\r\npublic:\r\n\tCEditedRail();\r\n\t~CEditedRail();\r\n\r\n\tvoid Clear();\r\n\r\n\tCEditedRail *mpNext;\t\r\n\tCEditedRail *mpPrevious;\r\n\t\r\n\tCEditedRailPoint *mpRailPoints;\r\n\t\r\n\tuint32 mId;\r\n\r\n\tCEditedRailPoint *AddPoint();\r\n\r\n\tvoid AdjustYs();\r\n\tvoid InitialiseHeights();\r\n\tvoid UpdateRailGeometry(Mth::Vector& rotateCentre=ZeroVector, Mth::Vector& newCentre=ZeroVector, float degrees=0.0f);\r\n\tvoid UpdatePostGeometry(Mth::Vector& rotateCentre=ZeroVector, Mth::Vector& newCentre=ZeroVector, float degrees=0.0f);\r\n\tvoid DestroyRailGeometry();\r\n\tvoid DestroyPostGeometry();\r\n\t\r\n\tint CountPoints();\r\n\tbool FindNearestRailPoint(Mth::Vector &pos, \r\n\t\t\t\t\t\t\t  Mth::Vector *p_nearest_pos, float *p_dist_squared, int *p_rail_point_index, \r\n\t\t\t\t\t\t\t  int ignore_index=-1);\r\n\t\t\t\t\t\t\t  \r\n\tint CountPointsInArea(float x0, float z0, float x1, float z1);\r\n\tvoid DuplicateAndAddPoint(CEditedRailPoint *p_point);\r\n\tCEditedRail *GenerateDuplicateRails(float x0, float z0, float x1, float z1, CEditedRail *p_head);\t\r\n\t\t\t\t\t\t\t  \r\n\tenum EUpdateSuperSectors\r\n\t{\r\n\t\tDONT_UPDATE_SUPER_SECTORS=0,\r\n\t\tUPDATE_SUPER_SECTORS=1\r\n\t};\t\r\n\tbool UpdateRailPointPosition(int rail_point_index, Mth::Vector &pos, EUpdateSuperSectors updateSuperSectors);\r\n\tCEditedRailPoint *GetRailPointFromIndex(int index);\r\n\tvoid UnHighlight();\r\n\r\n\tCEditedRailPoint *DeleteRailPoint(CEditedRailPoint *p_point);\r\n\t\r\n\tvoid CopyRail(CEditedRail *p_source_rail);\r\n\tvoid RotateAndTranslate(Mth::Vector& rotateCentre, Mth::Vector& newCentre, float degrees);\r\n\r\n\tSCompressedRailPoint *WriteCompressedRailPoints(SCompressedRailPoint *p_dest);\r\n\r\n\tbool ThereAreRailPointsOutsideArea(float x0, float z0, float x1, float z1);\r\n\r\n\t// Used by graffiti games\r\n\tvoid ModulateRailColor(int seqIndex);\r\n\tvoid ClearRailColor();\r\n\r\n\tvoid SetSectorActiveStatus(bool active);\r\n\t\r\n\tvoid GetDebugInfo( Script::CStruct* p_info );\r\n};\r\n\r\nclass CInputComponent;\r\nclass CEditorCameraComponent;\r\n\r\nclass CRailEditorComponent : public CBaseComponent\r\n{\r\n\tCInputComponent \t\t*mp_input_component;\r\n\tCEditorCameraComponent \t*mp_editor_camera_component;\r\n\tvoid get_pointers_to_required_components();\r\n\r\n\tvoid get_pos_from_camera_component(Mth::Vector *p_pos, float *p_height, float *p_angle);\r\n\t\t\r\n\tint count_rails();\r\n\t\r\n\tCEditedRail *mp_edited_rails;\r\n\tCEditedRail *mp_current_rail;\r\n\t\r\n\t// The mode that the cursor is in, ie FreeRoaming, RailLayout or Grab\r\n\t// This is stored as a checksum rather than an enum because it will mostly\r\n\t// be scripts that are doing logic based on the mode, and this way I don't\r\n\t// have to define a bunch of script global integers to match the enum.\r\n\tuint32 m_mode;\r\n\t\r\n\tuint32 m_dotted_line_sector_name;\t\r\n\tNx::CSector *mp_dotted_line_sector;\r\n\r\n\tenum\r\n\t{\r\n\t\tCOMPRESSED_RAILS_BUFFER_SIZE = sizeof(uint16) + // Num rails\r\n\t\t\t\t\t\t\t\t\t   MAX_EDITED_RAILS * sizeof(uint16) + // Num points in each rail\r\n\t\t\t\t\t\t\t\t\t   MAX_EDITED_RAIL_POINTS * sizeof(SCompressedRailPoint), // The rail points\r\n\t};\t\t\t\t\t\t\t\t\t   \r\n\t\t\r\n\tuint8 mp_compressed_rails_buffer[COMPRESSED_RAILS_BUFFER_SIZE];\r\n\tvoid generate_compressed_rails_buffer();\r\n\tvoid clear_compressed_rails_buffer();\r\n\t\r\n\t// Used by graffiti games\r\n\tCEditedRail *get_rail_from_cluster_name(uint32 clusterChecksum);\r\n\t\r\npublic:\r\n    CRailEditorComponent();\r\n    virtual ~CRailEditorComponent();\r\n\r\npublic:\r\n\tuint8 *\t\t\t\t\t\t\tGetCompressedRailsBuffer();\r\n\tint\t\t\t\t\t\t\t\tGetCompressedRailsBufferSize() {return COMPRESSED_RAILS_BUFFER_SIZE;}\r\n\tvoid\t\t\t\t\t\t\tSetCompressedRailsBuffer(uint8 *p_buffer);\r\n\tvoid\t\t\t\t\t\t\tInitUsingCompressedRailsBuffer();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tClear();\r\n\tCEditedRail *\t\t\t\t\tNewRail();\r\n\tbool\t\t\t\t\t\t\tNewRail(const char *p_railName);\r\n\tvoid\t\t\t\t\t\t\tDeleteRail(CEditedRail *p_rail);\r\n\tCEditedRail *\t\t\t\t\tGetRail(uint32 id);\r\n\tvoid\t\t\t\t\t\t\tRemoveEmptyAndSinglePointRails();\r\n\t\r\n\tint\t\t\t\t\t\t\t\tGetTotalRailNodesRequired();\r\n\tvoid\t\t\t\t\t\t\tSetUpRailNodes(Script::CArray *p_nodeArray, int *p_nodeNum, uint32 firstID);\r\n\r\n\tvoid\t\t\t\t\t\t\tAdjustYs();\r\n\tvoid\t\t\t\t\t\t\tInitialiseHeights();\r\n\tvoid\t\t\t\t\t\t\tUpdateRailGeometry();\r\n\tvoid\t\t\t\t\t\t\tUpdatePostGeometry();\r\n\tvoid\t\t\t\t\t\t\tDestroyRailGeometry();\r\n\tvoid\t\t\t\t\t\t\tDestroyPostGeometry();\r\n\r\n\tvoid\t\t\t\t\t\t\tRefreshGeometry();\r\n\tvoid\t\t\t\t\t\t\tUnHighlightAllRails();\r\n\t\r\n\tbool\t\t\t\t\t\t\tDeleteRailPoint(CEditedRail *p_rail, CEditedRailPoint *p_point);\r\n\r\n\tenum EClipType\r\n\t{\r\n\t\tDELETE_POINTS_OUTSIDE=0,\r\n\t\tDELETE_POINTS_INSIDE=1\r\n\t};\r\n\tbool\t\t\t\t\t\t\tClipRail(CEditedRail *p_rail, float x0, float z0, float x1, float z1, EClipType clipType);\r\n\tvoid\t\t\t\t\t\t\tClipRails(float x0, float z0, float x1, float z1, EClipType clipType);\r\n\tbool\t\t\t\t\t\t\tThereAreRailPointsOutsideArea(float x0, float z0, float x1, float z1);\r\n\t\r\n\r\n\tint\t\t\t\t\t\t\t\tCountPointsInArea(float x0, float z0, float x1, float z1);\r\n\tbool\t\t\t\t\t\t\tAbleToCopyRails(float x0, float z0, float x1, float z1);\r\n\tCEditedRail *\t\t\t\t\tGenerateDuplicateRails(float x0, float z0, float x1, float z1);\r\n\t\t\t\t\t\t\t\t\t\r\n\tbool\t\t\t\t\t\t\tFindNearestRailPoint(Mth::Vector &pos, Mth::Vector *p_nearest_pos, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t float *p_dist_squared, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t uint32 *p_rail_id, int *p_rail_point_index,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t uint32 ignore_rail_index=0, int ignore_rail_point_index=-1);\r\n\r\n\t\r\n\tvoid\t\t\t\t\t\t\tDeleteDottedLine();\r\n\tvoid\t\t\t\t\t\t\tDrawDottedLine(Mth::Vector& pos);\r\n\r\n\tint\t\t\t\t\t\t\t\tGetNumFreePoints();\r\n\tint\t\t\t\t\t\t\t\tGetNumFreeRails();\r\n\t\r\n\t// Used by graffiti games\r\n\tvoid\t\t\t\t\t\t\tModulateRailColor(uint32 clusterChecksum, int seqIndex);\r\n\tvoid\t\t\t\t\t\t\tClearRailColor(uint32 clusterChecksum);\r\n\r\n\tvoid\t\t\t\t\t\t\tSetSectorActiveStatus(bool active);\r\n\t\r\n\t// A quick hack to allow UpdateSuperSectors not to be called when loading a new park in a net game.\r\n\t// If it is called, the whole park disappears due to all the sectors having been flagged for deletion.\r\n\tstatic bool\t\t\t\t\t\tsUpdateSuperSectorsAfterDeletingRailSectors;\r\n\t\r\n\t// For reading/writing to memcard\r\n\tvoid\t\t\t\t\t\t\tWriteIntoStructure(Script::CStruct *p_info);\r\n\tvoid\t\t\t\t\t\t\tReadFromStructure(Script::CStruct *p_info);\r\n\r\n\tvirtual\tvoid \t\t\t\t\tFinalize();\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\tvirtual void\t\t\t\t\tHide( bool shouldHide );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n};\r\n\r\nObj::CRailEditorComponent *GetRailEditor();\r\n\r\n\r\n// This will print the memory used by the rail editor component, via a compiler error.\r\n// Need to keep it within 30K, since it exists in memory permanently.\r\n//char p[(sizeof(CRailEditorComponent)+MAX_EDITED_RAIL_POINTS*sizeof(CEditedRailPoint)+MAX_EDITED_RAILS*sizeof(CEditedRail))/0];\r\n\r\n} // namespace Obj\r\n\r\n#endif // #ifndef __COMPONENTS_RAILEDITORCOMPONENT_H__\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterAdjustPhysicsComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterAdjustPhysicsComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/26/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skateradjustphysicscomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/engine/contact.h>\r\n#include <sk/engine/feeler.h>\r\n#include <sk/parkeditor2/parked.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/shadowcomponent.h>\r\n#include <gel/components/movablecontactcomponent.h>\r\n\r\nvoid\tTrackingLine2(int type, Mth::Vector &start, Mth::Vector &end)\r\n{\r\n\tif\t(Script::GetInt(CRCD(0x19fb78fa,\"output_tracking_lines\")))\r\n\t{\r\n//\t\tGfx::AddDebugLine(start, end, 0xffffff);\r\n\t\tprintf (\"Tracking%d %.2f,%.2f,%.2f,%.2f,%.2f,%.2f\\n\",type, start[X], start[Y], start[Z], end[X], end[Y], end[Z]);\r\n\t}\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSkaterAdjustPhysicsComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterAdjustPhysicsComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterAdjustPhysicsComponent::CSkaterAdjustPhysicsComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERADJUSTPHYSICS );\r\n\t\r\n\tmp_core_physics_component = NULL;\r\n\tmp_model_component = NULL;\r\n\tmp_shadow_component = NULL;\r\n\tmp_movable_contact_component = NULL;\r\n\t\r\n\tm_uber_frigged_this_frame = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterAdjustPhysicsComponent::~CSkaterAdjustPhysicsComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterAdjustPhysicsComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterAdjustPhysicsComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterAdjustPhysicsComponent::Finalize (   )\r\n{\r\n\tmp_core_physics_component = GetSkaterCorePhysicsComponentFromObject(GetObject());\r\n\tmp_model_component = GetModelComponentFromObject(GetObject());\r\n\tmp_shadow_component = GetShadowComponentFromObject(GetObject());\r\n\tmp_movable_contact_component = GetMovableContactComponentFromObject(GetObject());\r\n\tmp_state_component = GetSkaterStateComponentFromObject(GetObject());\r\n\r\n\tDbg_Assert(mp_core_physics_component);\r\n\tDbg_Assert(mp_model_component);\r\n\tDbg_Assert(mp_shadow_component);\r\n\tDbg_Assert(mp_movable_contact_component);\r\n\tDbg_Assert(mp_state_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterAdjustPhysicsComponent::Update()\r\n{\r\n\t// If on the ground, or moving downwards, then allow us to hit a car again\t\t\r\n\tif (mp_core_physics_component->GetState() == GROUND || GetObject()->m_vel[Y] < 0.0f)\r\n\t{\r\n\t\tmp_core_physics_component->SetFlagTrue(CAN_HIT_CAR);\r\n\t}\r\n\r\n\tif (!mp_core_physics_component->GetFlag(SKITCHING))\r\n\t{\r\n\t\tcheck_inside_objects();\r\n\t}\r\n\r\n\tuber_frig();\r\n\r\n\tGetObject()->m_old_pos = GetObject()->m_pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterAdjustPhysicsComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterAdjustPhysicsComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterAdjustPhysicsComponent::GetDebugInfo\"));\r\n\t\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t\r\nvoid CSkaterAdjustPhysicsComponent::uber_frig (   )\r\n{\r\n\t// Uberfrig() will attempt to see if we are in a region with valid collision\r\n\t// if were are not, then it will attempt to move us back to a position that is valid; generally this is the old position\r\n\t\r\n\tm_uber_frigged_this_frame = false;\r\n\r\n\tif (GetObject()->m_pos != mp_core_physics_component->m_safe_pos)\r\n\t{\t\t\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tif (! (Tmr::GetRenderFrame() & 15) )\r\n\t\t{\r\n\t\t\tTrackingLine2(4, GetObject()->m_old_pos, GetObject()->m_pos);\t  // 4 = line\r\n\t\t}\r\n\t\t#endif\r\n\t\t\r\n\t\tmp_core_physics_component->m_col_start = GetObject()->m_pos;\r\n\t\tmp_core_physics_component->m_col_end = GetObject()->m_pos;\r\n\r\n\t\t// Very minor adjustment to move origin away from vert walls\r\n\t\tmp_core_physics_component->m_col_start += GetObject()->m_matrix[Y] * 0.001f;\r\n\t\t\r\n\t\tmp_core_physics_component->m_col_start[Y] += 8.0f;\r\n\t\tmp_core_physics_component->m_col_end[Y] -= FEET(400);\r\n\t\t\t   \r\n\t\tif (mp_core_physics_component->get_member_feeler_collision())\r\n\t\t{\r\n\t\t\t// if we are in \"contact\" with something, and on the ground or in air, then that should be what we collide with\r\n\t\t\t// so if not, we need to leave contact, and impart the final velocity\r\n\t\t\t// (\"on ground\" just means skating on something, which could be the moving object\r\n\t\t\tif (!mp_core_physics_component->GetFlag(SKITCHING) && !mp_core_physics_component->GetFlag(SPINE_PHYSICS))\r\n\t\t\t{\r\n\t\t\t\t// but we leave it if skitching, or attempting to spin between them\r\n\t\t\t\tif (mp_movable_contact_component->HaveContact()\r\n\t\t\t\t\t&& (mp_core_physics_component->GetState() == GROUND || mp_core_physics_component->GetState() == AIR))\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!mp_core_physics_component->m_feeler.IsMovableCollision() \r\n\t\t\t\t\t\t|| mp_core_physics_component->m_feeler.GetMovingObject() != mp_movable_contact_component->GetContact()->GetObject())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tGetObject()->m_vel += mp_movable_contact_component->GetContact()->GetObject()->GetVel();\r\n\t\t\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\t\t\tmp_movable_contact_component->LoseAnyContact();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tstatic Mth::Vector xa, xb, xc;\r\n\r\n\t\t\tfloat height = GetObject()->m_pos[Y] - mp_core_physics_component->m_feeler.GetPoint()[Y];\r\n\r\n\t\t\tmp_state_component->m_height = height;\r\n\t\t\t\r\n\t\t\t// if we are below the ground, then move him up\r\n\t\t\tif (height < 0.001f)\r\n\t\t\t{\r\n\t\t\t\tGetObject()->m_pos[Y] = mp_core_physics_component->m_feeler.GetPoint()[Y] + 0.001f; \t// above ground by a fraction of an inch\r\n\t\t\t\tDUMP_POSITION;\r\n\t\t\t\theight = 0.0f;\r\n\t\t\t}\r\n\r\n\t\t\tif (mp_core_physics_component->GetState() != RAIL)\r\n\t\t\t{\r\n\t\t\t\tmp_model_component->ApplyLightingFromCollision(mp_core_physics_component->m_feeler);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Store these values off for the simple shadow calculation.\r\n\t\t\tmp_shadow_component->SetShadowPos(mp_core_physics_component->m_feeler.GetPoint());\r\n\t\t\tmp_shadow_component->SetShadowNormal(mp_core_physics_component->m_feeler.GetNormal()); \r\n\t\t\r\n\t\t\tif (Ed::CParkEditor::Instance()->UsingCustomPark())\r\n\t\t\t{\r\n\t\t\t\t// when we are in the park editor, there are other checks we might want to do\r\n\t\t\t\tCFeeler feeler;\r\n\t\t\t\t\r\n\t\t\t\t// ignore non-collidable, under-ok\r\n\t\t\t\tfeeler.SetIgnore(mFD_NON_COLLIDABLE | mFD_UNDER_OK, 0);\r\n\t\t\t\tfeeler.SetStart(GetObject()->m_pos + Mth::Vector(0.0f, 3000.0f, 0.0f, 0.0f));\r\n\t\t\t\tfeeler.SetEnd(GetObject()->m_pos + GetObject()->m_matrix[Y]);\r\n\t\t\t\tif (feeler.GetCollision())\r\n\t\t\t\t{\r\n\t\t\t\t\t// Something above me that I'm not supposed to be under; just move the skater back to the old pos, and flip him\r\n\t\t\t\t\t\r\n\t\t\t\t\t// if only just under it, then pop me up\r\n\t\t\t\t\tif ((GetObject()->m_pos - feeler.GetPoint()).LengthSqr() < 6.0f * 6.0f)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tGetObject()->m_pos = feeler.GetPoint();\r\n\t\t\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// if we are not moving, then pop us up above the face we detected a collision with\r\n\t\t\t\t\t\tif ((GetObject()->m_pos - mp_core_physics_component->m_safe_pos).LengthSqr() < 1.0f * 1.0f)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tGetObject()->m_pos = feeler.GetPoint();\r\n\t\t\t\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tGetObject()->m_pos = mp_core_physics_component->m_safe_pos;\r\n\t\t\t\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tGetObject()->m_vel = GetObject()->m_vel * (-1.0f / 2.0f);\r\n\t\t\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\t\t\tif (mp_core_physics_component->GetState() == RAIL)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmp_core_physics_component->SetState(AIR);\t\t\t// Stop grinding\r\n\t\t\t\t\t\t\tGetObject()->SelfEvent(CRCD(0xafaa46ba, \"OffRail\"));\t\t\t\t\t// regular exception\r\n\t\t\t\t\t\t\tGetObject()->m_pos[Y] += 2.0f;\t\t\t\t\t\t\t\t// make sure we are out of the rail...\r\n\t\t\t\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tm_nudge = 0;\t\r\n\t\t\t\r\n\t\t\t // Mick:  Set a safe position.  Here there was a collision, so safe\r\n\t\t\tmp_core_physics_component->m_safe_pos = GetObject()->m_pos;\r\n\t\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// I'm going to assume that if we are on a rail, then the uberfrig is just a problem with the collision getting parallel to the wall\t\t\r\n\t\t\t// so I can safely ignore it, as no rail should be laid out into nothingness\r\n\t\t\t// except in the park editor, dammit...\r\n\t\t\tif ((mp_core_physics_component->GetState() != RAIL && mp_core_physics_component->GetState() != LIP)\r\n\t\t\t\t|| Ed::CParkEditor::Instance()->UsingCustomPark())\r\n\t\t\t{\r\n\t\t\t\tm_uber_frigged_this_frame = true;\r\n\t\t\t\t\r\n\t\t\t\t// first nudge is zero\r\n\t\t\t\tstatic Mth::Vector uberfrig_nudges[] =\r\n\t\t\t\t{\r\n\t\t\t\t\tMth::Vector(0.0f, 0.0f, 0.0f),\r\n\t\t\t\t\tMth::Vector(0.1f, 0.1f, 0.1f),\r\n\t\t\t\t\tMth::Vector(-0.2f, 0.0f, 0.0f),\r\n\t\t\t\t\tMth::Vector(0.0f, 0.0f, -0.2f),\r\n\t\t\t\t\tMth::Vector(0.2f, 0.0f, 0.0f)\r\n\t\t\t\t};\r\n\t\t\t\t\r\n\t\t\t\tif (m_nudge < 5)\r\n\t\t\t\t{\r\n\t\t\t\t\tGetObject()->m_pos = mp_core_physics_component->m_safe_pos + uberfrig_nudges[m_nudge++];\r\n\t\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// just reset it, and hope for the best.  Probably we are just over a seam, and will get over it.\r\n\t\t\t\t\tm_nudge = 0;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tGetObject()->m_vel = -GetObject()->m_vel + Mth::Vector(0.101f, 0.101f, 0.1001f);\r\n\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\t\r\n\t\t\t\t// special case for wallrides, lip tricks and suchlike\r\n\t\t\t\t// just change them to air state; bit of a patch, but prevent you getting stuck in a state\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\tif (mp_core_physics_component->GetState() != GROUND && mp_core_physics_component->GetState() != AIR)\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_core_physics_component->SetState(AIR);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tmp_state_component->m_height = 0.0f;\r\n\t\t}\r\n\t} \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterAdjustPhysicsComponent::check_inside_objects (   )\r\n{\r\n\tif (mp_movable_contact_component->CheckInsideObjects(GetObject()->m_pos, mp_core_physics_component->m_safe_pos))\r\n\t{\r\n\t\tMESSAGE(\"found to be inside a moving object\");\r\n\t\t\r\n\t\t// Whichever way we rcover from being inside a moving object, this abrupt change in velocity and position means any rail grinding might\r\n\t\t// be messed up, either with zero velocity, or being moved away from the rail; so, the best thing to do is skate off the rail\r\n\r\n\t\tif (mp_core_physics_component->GetState() == RAIL)\r\n\t\t{\r\n\t\t\tmp_core_physics_component->SetState(AIR);\r\n\t\t\tGetObject()->SelfEvent(CRCD(0xafaa46ba, \"OffRail\"));\r\n\t\t}\r\n\t\telse if (GetObject()->m_pos == mp_core_physics_component->m_safe_pos)\r\n\t\t{\r\n\t\t\t// Set velocity to zero, otherwise we can get stuck inside things as the velocity from this frame will keep pushing you back inside things\r\n\t\t\t// especially if m_safe_pos is just inside the object, when there will be no collision detected\r\n\t\t\t// If we are on a rail, let them keep the velocity as maybe we can handle it next frame\r\n\t\t\tGetObject()->GetVel().Set();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterAdjustPhysicsComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterAdjustPhysicsComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/26/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERADJUSTPHYSICSCOMPONENT_H__\r\n#define __COMPONENTS_SKATERADJUSTPHYSICSCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#define\t\tCRC_SKATERADJUSTPHYSICS CRCD(0x9f9cc949, \"SkaterAdjustPhysics\")\r\n\r\n#define\t\tGetSkaterAdjustPhysicsComponent() ((Obj::CSkaterAdjustPhysicsComponent*)GetComponent(CRC_SKATERADJUSTPHYSICS))\r\n#define\t\tGetSkaterAdjustPhysicsComponentFromObject(pObj) ((Obj::CSkaterAdjustPhysicsComponent*)(pObj)->GetComponent(CRC_SKATERADJUSTPHYSICS))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CSkaterCorePhysicsComponent;\r\n\tclass CModelComponent;\r\n\tclass CShadowComponent;\r\n\tclass CMovableContactComponent;\r\n\tclass CSkaterStateComponent;\r\n\r\nclass CSkaterAdjustPhysicsComponent : public CBaseComponent\r\n{\r\n\tfriend CSkaterNonLocalNetLogicComponent;\r\n\t\r\npublic:\r\n    CSkaterAdjustPhysicsComponent();\r\n    virtual ~CSkaterAdjustPhysicsComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\t\r\n\tbool\t\t\t\t\t\t\tUberFriggedThisFrame (  ) { return m_uber_frigged_this_frame; }\r\n\t\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\tuber_frig (   );\r\n\tvoid\t\t\t\t\t\t\tcheck_inside_objects (   );\r\n\t\r\nprivate:\r\n\tint\t\t\t\t\t\t\t\tm_nudge;\t\t\t\t\t\t// counter for which nudges to attempt if we get stuck in an uberfrig\r\n\r\n\tbool\t\t\t\t\t\t\tm_uber_frigged_this_frame;\r\n\t\r\n\t// peer components\r\n\tCSkaterCorePhysicsComponent*\tmp_core_physics_component;\r\n\tCModelComponent*\t\t\t\tmp_model_component;\r\n\tCShadowComponent*\t\t\t\tmp_shadow_component;\r\n\tCMovableContactComponent*\t\tmp_movable_contact_component;\r\n\tCSkaterStateComponent*\t\t\tmp_state_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterBalanceTrickComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterBalanceTrickComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  328/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skaterbalancetrickcomponent.h>\r\n#include <sk/components/skaterscorecomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent* CSkaterBalanceTrickComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterBalanceTrickComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterBalanceTrickComponent::CSkaterBalanceTrickComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERBALANCETRICK );\r\n\t\r\n\tmp_animation_component = NULL;\r\n\t\r\n\tmpBalanceParams = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterBalanceTrickComponent::~CSkaterBalanceTrickComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterBalanceTrickComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tmManual.Init(GetSkater());\r\n\tmGrind.Init(GetSkater());\r\n\tmLip.Init(GetSkater());\r\n\tmSkitch.Init(GetSkater());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterBalanceTrickComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterBalanceTrickComponent::Finalize (   )\r\n{\r\n\t\r\n\tmp_animation_component = GetAnimationComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_animation_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterBalanceTrickComponent::Update()\r\n{\r\n\tSuspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterBalanceTrickComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | SetWobbleDetails | gets called from the animation\r\n\t\t// component's PlayAnim handler (needs to come after the\r\n\t\t// animation has launched...)\r\n\t\tcase CRCC(0xea6d0efd,\"SetWobbleDetails\"):\r\n\t\t{\r\n\t\t\t// Intercepts the animation component's PlayAnim member function and handle's skater specific logic\r\n\t\t\t\r\n\t\t\t// If this is a wobbling balance anim, then allow the manual or grind to programmatically wobble it.\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0x6d941203, \"Wobble\")))\r\n\t\t\t{\r\n\t\t\t\tmManual.EnableWobble();\r\n\t\t\t\tmGrind.EnableWobble();\r\n\t\t\t\tmLip.EnableWobble();\r\n\t\t\t\tmSkitch.EnableWobble();\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tScript::CStruct* p_wobble_params = Script::GetStructure(CRCD(0x5adb96d4, \"DefaultWobbleParams\"), Script::ASSERT);\r\n\t\t\tpParams->GetStructure(CRCD(0xd095379c, \"WobbleParams\"), &p_wobble_params);\r\n\t\t\tset_wobble_params(p_wobble_params);\r\n\t\t\t\r\n\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t}\r\n\t\t\r\n        // @script | DoBalanceTrick | \r\n        // @parmopt int | Tweak | 0 | \r\n        // @parm name | ButtonA | \r\n        // @parm name | ButtonB |                       \r\n        // @parmopt name | Type | 0 | balance trick type (NoseManual, \r\n        // Manual, Grind, Slide, Lip)\r\n        // @flag DoFlipCheck | If set, the range anim will be played backwards if the skater is flipped.\r\n        // @flag PlayRangeAnimBackwards | If set, the range anim will be played backwards. Can be\r\n\t\t// used in conjunction with DoFlipCheck. Ie, if both flags are set, then the anim will be\r\n\t\t// played forwards if the skater is flipped.\r\n\t\t// @flag ClearCheese | If set this will reset any previous cheese.\r\n        // @parmopt structure | BalanceParams | | If not specified then the balance trick will use\r\n\t\t// the params defined by the script globals LipParams, or ManualParams etc depending on the\r\n\t\t// Type value. \r\n\t\tcase CRCC(0x7e92670c, \"DoBalanceTrick\"):\t  \r\n\t\t{\r\n\t\t\tif (mpBalanceParams)\r\n\t\t\t{\r\n\t\t\t\tdelete mpBalanceParams;\r\n\t\t\t\tmpBalanceParams = NULL;\r\n\t\t\t}\r\n\t\t\tScript::CStruct* p_balance_params = NULL;\r\n\t\t\tif (pParams->GetStructure(CRCD(0x647facc2, \"BalanceParams\"), &p_balance_params))\r\n\t\t\t{\r\n\t\t\t\tset_balance_trick_params(p_balance_params);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tint Tweak = 0;\r\n\t\t\tpParams->GetInteger(CRCD(0x2bfd3d35, \"Tweak\"), &Tweak);\r\n\t\t\t\r\n\t\t\tuint32 ButtonA = 0;\r\n\t\t\tuint32 ButtonB = 0;\r\n\t\t\tpParams->GetChecksum(CRCD(0x4f1a0b01, \"ButtonA\"), &ButtonA, Script::ASSERT);\r\n\t\t\tpParams->GetChecksum(CRCD(0xd6135abb, \"ButtonB\"), &ButtonB, Script::ASSERT);\r\n\t\t\t\r\n\t\t\tuint32 NewBalanceTrickType = 0;\r\n\t\t\tpParams->GetChecksum(CRCD(0x7321a8d6, \"Type\"), &NewBalanceTrickType);\r\n\r\n\t\t\t// Do nothing if already doing the same type of balance trick.  This is so that the meter does not glitch when switching to\r\n\t\t\t// a balance trick from another balance trick where there is no StopBalanceTrick script command in between.\r\n\t\t\tif (mBalanceTrickType == NewBalanceTrickType) break;\r\n\t\t\tmBalanceTrickType = NewBalanceTrickType;\r\n\t\t\t\r\n\t\t\tbool DoFlipCheck = pParams->ContainsFlag(CRCD(0x1304e677, \"DoFlipCheck\"));\r\n\t\t\tbool PlayRangeAnimBackwards = pParams->ContainsFlag(CRCD(0x8fe31ed, \"PlayRangeAnimBackwards\"));\r\n\t\t\t\r\n\t\t\t// This needed because for the extra grind tricks (eg left triangle triangle) the\r\n\t\t\t// DoBalanceTrick command gets called twice in a row, once for the first time the grind is detected\r\n\t\t\t// by the first triangle, then again once the extra trick is detected.\r\n\t\t\t// In that case the cheese needs to be reset otherwise it thinks you've jumped and re-railed & you\r\n\t\t\t// fall off straight away.\r\n\t\t\tbool clear_cheese=pParams->ContainsFlag(CRCD(0xbbdb0f78,\"ClearCheese\"));\r\n\t\t\t\t\r\n\t\t\tswitch (mBalanceTrickType)\r\n\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tDbg_MsgAssert(false, (\"\\n%s\\nMust specify a type in DoBalanceTrick, eg Type=NoseManual\", pScript->GetScriptInfo()));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase CRCC(0xac90769, \"NoseManual\"):\r\n\t\t\t\tcase CRCC(0xef24413b, \"Manual\"):\r\n\t\t\t\t\tif (clear_cheese)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmManual.Reset();\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tmManual.UpdateRecord();\r\n\t\t\t\t\tmManual.SetUp(ButtonA, ButtonB, Tweak, DoFlipCheck, PlayRangeAnimBackwards);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase CRCC(0x255ed86f, \"Grind\"):\r\n\t\t\t\tcase CRCC(0x8d10119d, \"Slide\"):\r\n\t\t\t\t\tif (clear_cheese)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmGrind.Reset();\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tmGrind.UpdateRecord();\r\n\t\t\t\t\tmGrind.SetUp(ButtonA, ButtonB, Tweak, DoFlipCheck, PlayRangeAnimBackwards);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase CRCC(0xa549b57b, \"Lip\"):\r\n\t\t\t\t\tif (clear_cheese)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmLip.Reset();\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tmLip.UpdateRecord();\r\n\t\t\t\t\tmLip.SetUp(ButtonA, ButtonB, Tweak, DoFlipCheck, PlayRangeAnimBackwards);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase CRCC(0x3506ce64, \"Skitch\"):\r\n\t\t\t\t\tif (clear_cheese)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmSkitch.Reset();\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tmSkitch.UpdateRecord();\r\n\t\t\t\t\tmSkitch.SetUp(ButtonA, ButtonB, Tweak, DoFlipCheck, PlayRangeAnimBackwards);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tdefault:\t\r\n\t\t\t\t\tDbg_Assert(false);\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        // @script | AdjustBalance | Make minor adjustments, nudges, to the current balance trick, if any\r\n        // @parmopt float | TimeAdd | 0.0 | \r\n        // @parmopt float | LeanAdd | 0.0 | \r\n        // @parmopt float | SpeedAdd | 0.0 | \r\n        // @parmopt float | TimeMult | 1.0 | \r\n        // @parmopt float | LeanMult | 1.0 | \r\n        // @parmopt float | SpeedMult | 1.0 | \r\n\t\tcase CRCC(0x7a0dcd4b, \"AdjustBalance\"):\r\n\t\t{\r\n\t\t\tif (mBalanceTrickType)\r\n\t\t\t{\r\n\t\t\t\tfloat TimeMult = 1.0f;\r\n\t\t\t\tfloat LeanMult = 1.0f;\r\n\t\t\t\tfloat SpeedMult = 1.0f;\r\n\t\t\t\tfloat TimeAdd = 0.0f;\r\n\t\t\t\tfloat LeanAdd = 0.0f;\r\n\t\t\t\tfloat SpeedAdd = 0.0f;\r\n\t\t\t\tpParams->GetFloat(CRCD(0x3a4e9413, \"TimeAdd\"), &TimeAdd);\r\n\t\t\t\tpParams->GetFloat(CRCD(0xb4cecc1, \"LeanAdd\"), &LeanAdd);\r\n\t\t\t\tpParams->GetFloat(CRCD(0xeb9ecabb, \"SpeedAdd\"), &SpeedAdd);\r\n\t\t\t\tpParams->GetFloat(CRCD(0x4c074698, \"TimeMult\"), &TimeMult);\r\n\t\t\t\tpParams->GetFloat(CRCD(0x24ebf718, \"LeanMult\"), &LeanMult);\r\n\t\t\t\tpParams->GetFloat(CRCD(0x94dbbd1c, \"SpeedMult\"), &SpeedMult);\r\n\r\n\t\t\t\t// Get whichever balance trick we are doing\t\r\n\t\t\t\tCManual* pBalance;\r\n\t\t\t\tswitch (mBalanceTrickType)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase CRCC(0x255ed86f, \"Grind\"):\r\n\t\t\t\t\tcase CRCC(0x8d10119d, \"Slide\"):\r\n\t\t\t\t\t\tpBalance = &mGrind;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\tcase CRCC(0xa549b57b, \"Lip\"):\r\n\t\t\t\t\t\tpBalance = &mLip;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\t\tcase CRCC(0x3506ce64, \"Skitch\"):\r\n\t\t\t\t\t\tpBalance = &mSkitch;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\tcase CRCC(0xac90769, \"NoseManual\"):\r\n\t\t\t\t\tcase CRCC(0xef24413b, \"Manual\"):\r\n\t\t\t\t\t\tpBalance = &mManual;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tpBalance = NULL;\r\n\t\t\t\t\t\tDbg_Assert(false);\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tpBalance->mManualTime *= TimeMult;\r\n\t\t\t\tpBalance->mManualTime += TimeAdd;\r\n\t\t\t\tif (pBalance->mManualTime < 0.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\tpBalance->mManualTime = 0.0f;\r\n\t\t\t\t}\r\n\t\t\t\tpBalance->mManualLean *= LeanMult;\r\n\t\t\t\tpBalance->mManualLean += LeanAdd * Mth::Sgn(pBalance->mManualLean);\r\n\t\t\t\tpBalance->mManualLeanDir *= SpeedMult;\r\n\t\t\t\tpBalance->mManualLeanDir += SpeedAdd  * Mth::Sgn(pBalance->mManualLeanDir);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | StopBalanceTrick | \r\n\t\tcase CRCC(0xe553a5b8, \"StopBalanceTrick\"):\r\n\t\t\tstop_balance_trick();\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | StartBalanceTrick | \r\n\t\tcase CRCC(0x6cc475b7, \"StartBalanceTrick\"):\r\n\t\t\tmDoingBalanceTrick = true;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x78e669ab, \"SwitchOffBalanceMeter\"):\r\n\t\t{\r\n\t\t\tCSkaterScoreComponent* p_score_component = GetSkaterScoreComponentFromObject(GetObject());\r\n\t\t\tDbg_Assert(p_score_component);\r\n\t\t\t\r\n\t\t\tp_score_component->GetScore()->SetBalanceMeter(false);\r\n\t\t\tp_score_component->GetScore()->SetManualMeter(false);\r\n\t\t\t\r\n\t\t\tmManual.SwitchOffMeters();\r\n\t\t\tmGrind.SwitchOffMeters();\r\n\t\t\tmLip.SwitchOffMeters();\r\n\t\t\tmSkitch.SwitchOffMeters();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        // @script | SwitchOnBalanceMeter |\r\n\t\tcase CRCC(0x73727701, \"SwitchOnBalanceMeter\"):\r\n\t\t\tmManual.SwitchOnMeters();\r\n\t\t\tmGrind.SwitchOnMeters();\r\n\t\t\tmLip.SwitchOnMeters();\r\n\t\t\tmSkitch.SwitchOnMeters();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterBalanceTrickComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterBalanceTrickComponent::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddChecksum(\"mDoingBalanceTrick\", mDoingBalanceTrick ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\tp_info->AddChecksum(\"mBalanceTrickType\", mBalanceTrickType);\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterBalanceTrickComponent::ClearMaxTimes (   )\r\n{\r\n   \tmManual.ClearMaxTime();\r\n\tmGrind.ClearMaxTime();\r\n\tmLip.ClearMaxTime();\r\n\tmSkitch.ClearMaxTime();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterBalanceTrickComponent::UpdateRecord (   )\r\n{\r\n\tmManual.UpdateRecord();\t\t   \r\n\tmGrind.UpdateRecord();\t\t   \r\n\tmLip.UpdateRecord();\t\t   \r\n\tmSkitch.UpdateRecord();\t\t   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterBalanceTrickComponent::Reset (   )\r\n{\r\n\tmManual.Reset();\r\n\tmGrind.Reset();\r\n\tmSkitch.Reset();\r\n\tmLip.Reset();\r\n\t\r\n\tmBalanceTrickType = 0;\r\n\tmDoingBalanceTrick = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSkaterBalanceTrickComponent::ExcludeBalanceButtons ( int& numButtonsToIgnore, uint32 pButtonsToIgnore[] )\r\n{\r\n\t// If a balance trick is being done, then this will stop the buttons being used to control the balance from\r\n\t// generating the events used to trigger tricks.\r\n\t// Otherwise, ChrisR can't do kickflips by very quickly jumping out of a grind & kickflipping by rolling\r\n\t// from X to Square.\r\n\t\r\n\t// Note, in case of problems later:\r\n\t// Now, potentially a button could be pressed just before the balance trick,\r\n\t// then released during the balance trick, and the release would not get recorded as an event.\r\n\t// So if the event buffer were analysed, it would appear that the button was still pressed.\r\n\t// However, this does not seem to cause any problems, because generally if we want to know if a button\r\n\t// is pressed right now we just read the pad. Just noting this if any problems occur later.\r\n\tswitch (mBalanceTrickType)\r\n\t{\r\n\t\tcase CRCC(0xac90769, \"NoseManual\"):\r\n\t\tcase CRCC(0xef24413b, \"Manual\"):\r\n\t\t\tnumButtonsToIgnore = 2;\r\n\t\t\tpButtonsToIgnore[0] = mManual.mButtonAChecksum;\r\n\t\t\tpButtonsToIgnore[1] = mManual.mButtonBChecksum;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0xa549b57b, \"Lip\"):\r\n\t\t\tnumButtonsToIgnore = 2;\r\n\t\t\tpButtonsToIgnore[0] = mLip.mButtonAChecksum;\r\n\t\t\tpButtonsToIgnore[1] = mLip.mButtonBChecksum;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x255ed86f, \"Grind\"):\r\n\t\tcase CRCC(0x8d10119d, \"Slide\"):\r\n\t\t\tnumButtonsToIgnore = 2;\r\n\t\t\tpButtonsToIgnore[0] = mGrind.mButtonAChecksum;\r\n\t\t\tpButtonsToIgnore[1] = mGrind.mButtonBChecksum;\r\n\t\t\tbreak;\t\t\t\r\n\t\t\t\r\n\t\tcase CRCC(0x3506ce64, \"Skitch\"):\r\n\t\t\tnumButtonsToIgnore = 2;\r\n\t\t\tpButtonsToIgnore[0] = mSkitch.mButtonAChecksum;\r\n\t\t\tpButtonsToIgnore[1] = mSkitch.mButtonBChecksum;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\t\r\n\t\t\tnumButtonsToIgnore = 0;\r\n\t\t\tbreak;\r\n\t}\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CSkaterBalanceTrickComponent::GetBalanceStat ( uint32 Checksum )\r\n{\r\n\t// If some custom params have been set, use them.\r\n\tif (mpBalanceParams)\r\n\t{\r\n\t\treturn GetSkater()->GetScriptedStat(Checksum, mpBalanceParams);\r\n\t}\r\n\t\t\r\n\tswitch (mBalanceTrickType)\r\n\t{\r\n\t\tcase CRCC(0xac90769, \"NoseManual\"):\r\n\t\tcase CRCC(0xef24413b, \"Manual\"):\r\n\t\t\treturn GetSkater()->GetScriptedStat(Checksum, Script::GetStructure(CRCD(0xb8cc8633, \"ManualParams\")));\r\n\t\t\t\r\n\t\tcase CRCC(0x255ed86f, \"Grind\"):\r\n\t\tcase CRCC(0x8d10119d, \"Slide\"):\r\n\t\t\treturn GetSkater()->GetScriptedStat(Checksum, Script::GetStructure(CRCD(0x6b7fdadd, \"GrindParams\")));\r\n\t\t\t\r\n\t\tcase CRCC(0xa549b57b, \"Lip\"):\r\n\t\t\treturn GetSkater()->GetScriptedStat(Checksum, Script::GetStructure(CRCD(0xbe615d0a, \"LipParams\")));\r\n\t\t\r\n\t\tcase CRCC(0x3506ce64, \"Skitch\"):\r\n\t\t\treturn GetSkater()->GetScriptedStat(Checksum, Script::GetStructure(CRCD(0xfc87cc01, \"SkitchParams\")));\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_Assert(false);\r\n\t\t\treturn 0.0f;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSkaterBalanceTrickComponent::ClearBalanceParameters (   )\r\n{\r\n\tif (mpBalanceParams)\r\n\t{\r\n\t\tdelete mpBalanceParams;\r\n\t\tmpBalanceParams = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterBalanceTrickComponent::stop_balance_trick (   )\r\n{\r\n\t// Stops doing any balance trick.\r\n\t// Called when going into the lip state, and also called by the StopBalanceTrick script command.\r\n\tmManual.Stop();\t\r\n\tmGrind.Stop();\t\r\n\tmLip.Stop();\t\r\n\tmSkitch.Stop();\r\n\t\t\r\n\tmBalanceTrickType = 0;\r\n\tmDoingBalanceTrick = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterBalanceTrickComponent::set_wobble_params ( Script::CStruct *pParams )\r\n{\r\n\tif (!GetObject()->GetScript())\r\n\t{\r\n\t\tGetObject()->SetScript(new Script::CScript);\r\n\t}\r\n\r\n\tDbg_Assert(pParams);\r\n\r\n\t// Extract all the wobble details and stick them in WobbleDetails, then send that to SetWobbleDetails\r\n\t\r\n\tScript::CStruct* pStat = NULL;\r\n\tGfx::SWobbleDetails theWobbleDetails;\r\n\r\n\tpParams->GetStructure(CRCD(0xfd266a26, \"WobbleAmpA\"), &pStat, Script::ASSERT);\r\n\ttheWobbleDetails.wobbleAmpA = GetSkater()->GetScriptedStat(pStat);\r\n\r\n\tpParams->GetStructure(CRCD(0x642f3b9c, \"WobbleAmpB\"), &pStat, Script::ASSERT);\r\n\ttheWobbleDetails.wobbleAmpB = GetSkater()->GetScriptedStat(pStat);\r\n\r\n\tpParams->GetStructure(CRCD(0xf43fd49, \"WobbleK1\"), &pStat, Script::ASSERT);\r\n\ttheWobbleDetails.wobbleK1 = GetSkater()->GetScriptedStat(pStat);\r\n\r\n\tpParams->GetStructure(CRCD(0x964aacf3, \"WobbleK2\"), &pStat, Script::ASSERT);\r\n\ttheWobbleDetails.wobbleK2 = GetSkater()->GetScriptedStat(pStat);\r\n\r\n\tpParams->GetStructure(CRCD(0xf90b0824, \"SpazFactor\"), &pStat, Script::ASSERT);\r\n\ttheWobbleDetails.spazFactor = GetSkater()->GetScriptedStat(pStat);\r\n\r\n\tmp_animation_component->SetWobbleDetails(theWobbleDetails, true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterBalanceTrickComponent::set_balance_trick_params ( Script::CStruct *pParams )\r\n{\r\n\tDbg_Assert(pParams);\r\n\r\n\tif (!mpBalanceParams)\r\n\t{\r\n\t\tmpBalanceParams = new Script::CStruct;\r\n\t}\r\n\tmpBalanceParams->Clear();\r\n\tmpBalanceParams->AppendStructure(pParams);\t\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterBalanceTrickComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterBalanceTrickComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  328/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERBALANCETRICKCOMPONENT_H__\r\n#define __COMPONENTS_SKATERBALANCETRICKCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/manual.h>\r\n\r\n#define\t\tCRC_SKATERBALANCETRICK CRCD(0x589e5fb3, \"SkaterBalanceTrick\")\r\n\r\n#define\t\tGetSkaterBalanceTrickComponent() ((Obj::CSkaterBalanceTrickComponent*)GetComponent(CRC_SKATERBALANCETRICK))\r\n#define\t\tGetSkaterBalanceTrickComponentFromObject(pObj) ((Obj::CSkaterBalanceTrickComponent*)(pObj)->GetComponent(CRC_SKATERBALANCETRICK))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n\t\r\nnamespace Mdl\r\n{\r\n\tclass Skate;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CAnimationComponent;\r\n\r\nclass CSkaterBalanceTrickComponent : public CBaseComponent\r\n{\r\n\tfriend Mdl::Skate;\r\n\tfriend class CSkater;\r\n\tfriend class CManual;\r\n\tfriend class CSkaterCam;\r\n\tfriend class CSkaterCameraComponent;\r\n\tfriend class CSkaterCorePhysicsComponent;\r\n\t\r\npublic:\r\n    CSkaterBalanceTrickComponent();\r\n    virtual ~CSkaterBalanceTrickComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\t\r\n\tuint32\t\t\t\t\t\t\tGetBalanceTrickType (   ) { return mBalanceTrickType; }\r\n\tbool\t\t\t\t\t\t\tDoingBalanceTrick (   ) { return mDoingBalanceTrick; }\r\n\t\r\n\tvoid\t\t\t\t\t\t\tClearMaxTimes (   );\r\n\tvoid\t\t\t\t\t\t\tUpdateRecord (   );\r\n\tvoid\t\t\t\t\t\t\tReset (   );\r\n\tvoid\t\t\t\t\t\t\tExcludeBalanceButtons ( int& numButtonsToIgnore, uint32 pButtonsToIgnore[] );\r\n\tfloat\t\t\t\t\t\t\tGetBalanceStat ( uint32 Checksum );\r\n\tvoid\t\t\t\t\t\t\tClearBalanceParameters (   );\r\n\t\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\tstop_balance_trick (   );\r\n\tvoid\t\t\t\t\t\t\tset_balance_trick_params ( Script::CStruct *pParams );\r\n\tvoid\t\t\t\t\t\t\tset_wobble_params ( Script::CStruct *pParams );\r\n\t\r\nprivate:\r\n\tuint32 \t\t\t\t\t\t\tmBalanceTrickType;\t\t\t\t// Nosemanual,manual,grind or slide (checksum of)\r\n\tbool   \t\t\t\t\t\t\tmDoingBalanceTrick;\t\t\t\t// set in script when we are doing a balance trick, but not actually into it yet\r\n\t\r\n\tScript::CStruct*\t\t\t\tmpBalanceParams;\r\n\t\r\n\tCManual \t\t\t\t\t\tmManual;\r\n\tCManual \t\t\t\t\t\tmGrind;\r\n\tCManual \t\t\t\t\t\tmLip;\r\n\tCManual \t\t\t\t\t\tmSkitch;\r\n\t\r\n\t// peer components\r\n\tCAnimationComponent*\t\t\tmp_animation_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterCleanupStateComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterCleanupStateComponent.cpp\r\n//* OWNER:        \tDan\r\n//* CREATION DATE:  3/26/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skatercleanupstatecomponent.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/components/suspendcomponent.h>\r\n\r\n#include <sys/replay/replay.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSkaterCleanupStateComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterCleanupStateComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterCleanupStateComponent::CSkaterCleanupStateComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERCLEANUPSTATE );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterCleanupStateComponent::~CSkaterCleanupStateComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCleanupStateComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tmp_state_component = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCleanupStateComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCleanupStateComponent::Finalize(   )\r\n{\r\n\tmp_state_component = GetSkaterStateComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_state_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCleanupStateComponent::Update()\r\n{\r\n\t// Make sure the sparks are off if not on a rail\r\n\tif (GetSkater()->mSparksRequireRail && mp_state_component->GetState() != RAIL)\r\n\t{\r\n\t\tGetSkater()->SparksOff();\r\n\t}\r\n\t\t\r\n\t// Dan: shouldn't need to do this; the suspend components update themselves\r\n\t// Perform LOD/culling/occluding\r\n\t// NOTE: Move to CModeldComponent::Update?  Ask Gary about this.\r\n\t// GetSuspendComponentFromObject(GetObject())->CheckModelActive();\r\n\t\r\n\t// Don't update the shadow if running a replay. The replay code will update it, using the replay dummy skater's position and matrix.\r\n\t// if (!Replay::RunningReplay())\r\n\t// {\r\n\tGetSkater()->UpdateShadow(GetObject()->m_pos, GetObject()->m_matrix);\r\n\t// }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterCleanupStateComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCleanupStateComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterCleanupStateComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterCleanupStateComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterCleanupStateComponent.h\r\n//* OWNER:        \tDan\r\n//* CREATION DATE:  3/26/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERCLEANUPSTATECOMPONENT_H__\r\n#define __COMPONENTS_SKATERCLEANUPSTATECOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_SKATERCLEANUPSTATE CRCD(0xd8cc3428, \"SkaterCleanupState\")\r\n\r\n#define\t\tGetSkaterCleanupStateComponent() ((Obj::CSkaterCleanupStateComponent*)GetComponent(CRC_SKATERCLEANUPSTATE))\r\n#define\t\tGetSkaterCleanupStateComponentFromObject(pObj) ((Obj::CSkaterCleanupStateComponent*)(pObj)->GetComponent(CRC_SKATERCLEANUPSTATE))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CSkaterStateComponent;\r\n\r\nclass CSkaterCleanupStateComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkaterCleanupStateComponent();\r\n    virtual ~CSkaterCleanupStateComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n\tvirtual void\t\t\t\t\tFinalize(   );\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\t\r\nprivate:\r\n\tCSkaterStateComponent*\t\t\tmp_state_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterCorePhysicsComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterCorePhysicsComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/21/3\r\n//****************************************************************************\r\n\r\n#include <sk/objects/rail.h>\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/objects/gap.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skatersoundcomponent.h>\r\n#include <sk/components/skaterrotatecomponent.h>\r\n#include <sk/components/skaterscorecomponent.h>\r\n#include <sk/components/skatermatrixqueriescomponent.h>\r\n#include <sk/components/skaterendruncomponent.h>\r\n#include <sk/components/skaterbalancetrickcomponent.h>\r\n#include <sk/components/skaterloopingsoundcomponent.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n#include <sk/components/skaterflipandrotatecomponent.h>\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n#include <sk/components/skatergapcomponent.h>\r\n\r\n#include <gel/objtrack.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/skitchcomponent.h>\r\n#include <gel/components/triggercomponent.h>\r\n#include <gel/components/trickcomponent.h>\r\n#include <gel/components/railmanagercomponent.h>\r\n#include <gel/components/motioncomponent.h>\r\n#include <gel/components/shadowcomponent.h>\r\n#include <gel/components/movablecontactcomponent.h>\r\n#include <gel/components/walkcomponent.h>\r\n#include <gel/collision/collcache.h>\r\n\r\n#include <sk/engine/contact.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/parkeditor2/parked.h>\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#include <core/math/slerp.h>\r\n\r\n#define\tFLAGEXCEPTION(X) GetObject()->SelfEvent(X)\r\n\t\t\t\t\t\t\t\r\nvoid\tTrackingLine(int type, Mth::Vector &start, Mth::Vector &end)\r\n{\r\n\tif\t(Script::GetInt(CRCD(0x19fb78fa,\"output_tracking_lines\")))\r\n\t{\r\n//\t\tGfx::AddDebugLine(start, end, 0xffffff);\r\n\t\tprintf (\"Tracking%d %.2f,%.2f,%.2f,%.2f,%.2f,%.2f\\n\",type, start[X], start[Y], start[Z], end[X], end[Y], end[Z]);\r\n\t}\r\n}\r\n \r\nextern bool g_CheatsEnabled;\r\n\r\nnamespace Obj\r\n{\r\n\tMth::Vector acid_hold;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSkaterCorePhysicsComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterCorePhysicsComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterCorePhysicsComponent::CSkaterCorePhysicsComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERCOREPHYSICS );\r\n\t\r\n\tmp_input_component = NULL;\r\n\tmp_trigger_component = NULL;\r\n\tmp_sound_component = NULL;\r\n\tmp_trick_component = NULL;\r\n\tmp_rotate_component = NULL;\r\n\tmp_score_component = NULL;\r\n\tmp_balance_trick_component = NULL;\r\n\tmp_state_component = NULL;\r\n\tmp_movable_contact_component = NULL;\r\n\tmp_physics_control_component = NULL;\r\n\tmp_walk_component = NULL;\r\n\t\r\n\tmp_coll_cache = Nx::CCollCacheManager::sCreateCollCache();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterCorePhysicsComponent::~CSkaterCorePhysicsComponent()\r\n{\r\n\tNx::CCollCacheManager::sDestroyCollCache(mp_coll_cache);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tDbg_MsgAssert(GetObject()->GetType() == SKATE_TYPE_SKATER, (\"CSkaterCorePhysicsComponent added to non-skater composite object\"));\r\n\t\r\n\tm_rolling_friction = GetPhysicsFloat(CRCD(0x78f80ec4, \"Physics_Rolling_Friction\"));\r\n\t\r\n    GetPos().Set(0.0f, 0.0f, 0.0f);\r\n\tDUMP_POSITION;\r\n\r\n\tGetMatrix().Identity();\r\n    ResetLerpingMatrix();\r\n\r\n\tm_display_normal.Set(0.0f, 1.0f, 0.0f);\r\n\tm_current_normal = m_display_normal;\r\n\tm_last_display_normal = m_display_normal;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::Finalize (   )\r\n{\r\n\tmp_input_component = GetInputComponentFromObject(GetObject());\r\n\tmp_sound_component = GetSkaterSoundComponentFromObject(GetObject());\r\n\tmp_trigger_component = GetTriggerComponentFromObject(GetObject());\r\n\tmp_trick_component = GetTrickComponentFromObject(GetObject());\r\n\tmp_rotate_component = GetSkaterRotateComponentFromObject(GetObject());\r\n\tmp_score_component = GetSkaterScoreComponentFromObject(GetObject());\r\n\tmp_balance_trick_component = GetSkaterBalanceTrickComponentFromObject(GetObject());\r\n\tmp_state_component = GetSkaterStateComponentFromObject(GetObject());\r\n\tmp_movable_contact_component = GetMovableContactComponentFromObject(GetObject());\r\n\tmp_physics_control_component = GetSkaterPhysicsControlComponentFromObject(GetObject());\r\n\tmp_walk_component = GetWalkComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_input_component);\r\n\tDbg_Assert(mp_sound_component);\r\n\tDbg_Assert(mp_trigger_component);\r\n\tDbg_Assert(mp_trick_component);\r\n\tDbg_Assert(mp_rotate_component);\r\n\tDbg_Assert(mp_score_component);\r\n\tDbg_Assert(mp_balance_trick_component);\r\n\tDbg_Assert(mp_movable_contact_component);\r\n\tDbg_Assert(mp_physics_control_component);\r\n\tDbg_Assert(mp_walk_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::Update()\r\n{\r\n\tDUMP_POSITION;\r\n\t\r\n\tm_frame_length = Tmr::FrameLength();\r\n\t\r\n\t// bool up = GetVel()[Y] > 0.0f;\r\n\r\n\tm_landed_this_frame = false;\r\n\r\n\tm_began_frame_in_lip_state = GetState() == LIP;\r\n\tm_began_frame_in_transfer = GetFlag(SPINE_PHYSICS);\r\n\t\r\n\thandle_tensing();\r\n\r\n\tlimit_speed();\r\n\r\n\tSetFlagFalse(SNAPPED_OVER_CURB);  // this flag only gets set for one frame, to fix camera snaps\r\n\tSetFlagFalse(SNAPPED);  // this flag only gets set for one frame, to fix camera snaps\r\n\t\r\n\tsetup_default_collision_cache();\r\n\t\r\n\tswitch (GetState())\r\n\t{\r\n\t\tcase GROUND:\r\n\t\t\t// Mick: Remember the last ground position for calculating which side of the rail we're on later.\r\n\t\t\t// Note, we do this BEFORE we move as the movement might take us off the ground\r\n\t\t\tm_last_ground_pos = GetPos();\r\n\t\t\tdo_on_ground_physics();\r\n\t\t\tmaybe_skitch();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase AIR:\r\n\t\t\tdo_in_air_physics();\r\n\t\t\tif (GetState() == GROUND)\r\n\t\t\t{\r\n\t\t\t\tm_landed_this_frame = true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase WALL:\r\n\t\t\tdo_wallride_physics();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase LIP:\r\n\t\t\tdo_lip_physics();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase RAIL:\r\n\t\t\tdo_rail_physics();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase WALLPLANT:\r\n\t\t\tdo_wallplant_physics();\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\thandle_post_transfer_limit_overrides();\r\n\t\r\n\t// NOTE: moved this call from after CSkaterRotateComponent::Update to before it\r\n\tmaybe_stick_to_rail();\r\n\t\r\n\tupdate_special_friction_index();\r\n\t\r\n\t// if (up && GetVel()[Y] < 0.0f)\r\n\t// {\r\n\t\t// DUMPF(GetPos()[Y]);\r\n\t// }\r\n\t\r\n\tif (m_vert_air_last_frame != (GetState() == AIR && GetFlag(VERT_AIR) && !GetFlag(SPINE_PHYSICS)))\r\n\t{\r\n\t\tm_vert_air_last_frame = !m_vert_air_last_frame;\r\n        GetObject()->BroadcastEvent(m_vert_air_last_frame ? CRCD(0xf225fe69, \"SkaterEnterVertAir\") : CRCD(0x5e27200a, \"SkaterExitVertAir\"));\r\n\t}\r\n\t\r\n\t#ifdef __USER_DAN__\r\n\t// Gfx::AddDebugArrow(GetPos(), GetPos() + 60.0f * GetMatrix()[Z], RED, 0, 1);\r\n\t// Gfx::AddDebugArrow(GetPos(), GetPos() + 60.0f * GetMatrix()[X], BLUE, 0, 1);\r\n\t// Gfx::AddDebugArrow(GetPos(), GetPos() + 60.0f * GetMatrix()[Y], GREEN, 0, 1);\r\n\t#endif\r\n\t\r\n\tCFeeler::sClearDefaultCache();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterCorePhysicsComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | Jump | \r\n        // @flag BonelessHeight | \r\n\t\tcase CRCC(0x584cf9e9, \"Jump\"):\r\n\t\t\tdo_jump(pParams);\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | Flipped | true if flipped\r\n\t\tcase CRCC(0xc7a712c, \"Flipped\"):\r\n\t\t\treturn GetFlag(FLIPPED) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | Switched | true if switched\r\n\t\tcase CRCC(0x8f66b80b, \"Switched\"):\r\n\t\t\treturn IsSwitched() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | Crouched | true if skater crouched\r\n\t\tcase CRCC(0x4adc6c2a, \"Crouched\"):\r\n\t\t\treturn GetFlag(TENSE) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | OnGround | true if current state is on ground\r\n\t\tcase CRCC(0x5ea287f2, \"OnGround\"):\r\n\t\t\treturn GetState() == GROUND ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | InAir | true if current state is in air\r\n\t\tcase CRCC(0x3527fc07, \"InAir\"):\r\n\t\t\treturn GetState() == AIR ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | OnWall | true if current state is on wall\r\n\t\tcase CRCC(0xa32c1a15, \"OnWall\"):\r\n\t\t\treturn GetState() == WALL ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | OnLip | true if current state is on lip\r\n\t\tcase CRCC(0x5cb1fbd8, \"OnLip\"):\r\n\t\t\treturn GetState() == LIP ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | OnRail | true if current state is on rail\r\n\t\tcase CRCC(0xe9851e62, \"OnRail\"):\r\n\t\t\treturn GetState() == RAIL ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | InWallplant | true if current state is in wallplant\r\n\t\tcase CRCC(0xa64dcf8b, \"InWallplant\"):\r\n\t\t\treturn GetState() == WALLPLANT ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\r\n\t\t// @script | FirstTimeOnThisRail | true if this is the first time we grinded this rail wihout doing something else\r\n\t\t// like skating or wallriding\r\n\t\tcase CRCC(0x262d42d5,\"FirstTimeOnThisRail\"):\r\n\t\t\treturn GetFlag(NEW_RAIL) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\r\n\t\t// @script | StartSkitch | Start skitch physics\r\n\t\t// This will send a SkitchOn exception to the object\r\n\t\tcase CRCC(0xca6b3809, \"StartSkitch\"):\r\n\t\t\tstart_skitch();\r\n\t\t\tbreak;\r\n\r\n        // @script | Skitching | Returns True if we are skitching\r\n\t\tcase CRCC(0x9c6a7e41, \"Skitching\"):\r\n\t\t\treturn GetFlag(SKITCHING) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\r\n        // @script | StopSkitch | Stop Skitch physics\r\n\t\t// this wills send a SkitchOff exeception to the object\r\n\t\tcase CRCC(0x32dcc9cf, \"StopSkitch\"):\r\n\t\t\tStopSkitch();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | CancelWallpush | Cancels the current wallpush event\r\n\t\tcase CRCC(0x5e8f9e77, \"CancelWallpush\"):\r\n\t\t\tSetFlagTrue(CANCEL_WALL_PUSH);\r\n\t\t\tbreak;\r\n\t\t\t \r\n        // @script | AirTimeLessThan | true if the air time is\r\n        // less than the specified time\r\n        // @uparm 1.0 | time (default is milliseconds)\r\n        // @flag seconds | time in seconds\r\n        // @flag frames | time in frames\r\n        case CRCC(0xc890a84, \"AirTimeLessThan\"):\r\n        // @script | AirTimeGreaterThan | true if the air time is \r\n        // greater than the specified time\r\n        // @uparm 1.0 | time (default is milliseconds)\r\n        // @flag seconds | time in seconds\r\n        // @flag frames | time in frames\r\n\t\tcase CRCC(0xbbf2b570, \"AirTimeGreaterThan\"):\r\n\t\t{\r\n\t\t\tfloat t = 0;\r\n\t\t\tpParams->GetFloat(NO_NAME, &t);\r\n\t\r\n\t\t\tTmr::Time TestTime;\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0xd029f619, \"seconds\")) || pParams->ContainsFlag(CRCD(0x49e0ee96, \"second\")))\r\n\t\t\t{\r\n\t\t\t\tTestTime = static_cast< Tmr::Time >(t * 1000);\r\n\t\t\t}\t\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0x19176c5, \"frames\")) || pParams->ContainsFlag(CRCD(0x4a07c332, \"frame\")))\r\n\t\t\t{\r\n\t\t\t\tTestTime = static_cast< Tmr::Time >(t * (1000 / 60));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tTestTime = static_cast< Tmr::Time >(t);\r\n\t\t\t}\r\n\r\n\t\t\tTmr::Time AirTime;\r\n\t\t\tif (GetState() == AIR || GetState() == WALL)\r\n\t\t\t{\r\n\t\t\t\tAirTime = Tmr::ElapsedTime(m_went_airborne_time);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tAirTime = m_landed_time - m_went_airborne_time;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tif (Checksum == CRCD(0xc890a84, \"AirTimeLessThan\"))\r\n\t\t\t{\r\n\t\t\t\treturn AirTime < TestTime ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn AirTime > TestTime ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t}\t\r\n\t\t}\r\n\r\n\t\t// @script | GetAirTime | Puts the air time, in seconds, into a param called airtime\r\n\t\tcase CRCC(0xde583e34, \"GetAirTime\"):\r\n\t\t{\r\n\t\t\tTmr::Time AirTime;\r\n\t\t\tif (GetState() == AIR || GetState() == WALL)\r\n\t\t\t{\r\n\t\t\t\tAirTime = Tmr::ElapsedTime(m_went_airborne_time);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tAirTime = m_landed_time - m_went_airborne_time;\r\n\t\t\t}\t\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0xad6bcdb4, \"AirTime\"), AirTime * (1.0f / 1000.0f));\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | GetAirTimeLeft | Puts the amount of air time left before landing, in seconds, into a param called AirTimeLeft\r\n\t\tcase CRCC(0x1996b797, \"GetAirTimeLeft\"):\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x7e2a8993, \"AirTimeLeft\"),\r\n\t\t\t\tMth::ClampMin(calculate_time_to_reach_height(GetPos()[Y] - mp_state_component->m_height, GetPos()[Y], GetVel()[Y]), 0.0f));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\t\t\r\n        // @script | Braking | true if skater is braking\r\n\t\tcase CRCC(0x1f8bbd05, \"Braking\"):\r\n\t\t\treturn is_braking() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\r\n\t\tcase CRCC(0xebbcf455, \"CanBrakeOff\"):\r\n\t\t\tm_pressing_down_brakes = false;\r\n\t\t\tbreak;\r\n\r\n\t\tcase CRCC(0xbc19e291, \"CanBrakeOn\"):\r\n\t\t\tm_pressing_down_brakes = true;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | CanKick | true if skater can kick\r\n\t\tcase CRCC(0x2f66333, \"CanKick\"):\r\n\t\t\treturn can_kick() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\r\n        // @script | CanKickOn | sets can kick to true\r\n\t\tcase CRCC(0x68bf6c13, \"CanKickOn\"):\r\n\t\t\tm_force_cankick_off = false;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | CanKickOff | sets can kick to false\r\n\t\tcase CRCC(0xe8deb0d7, \"CanKickOff\"):\r\n\t\t\tm_force_cankick_off = true;\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | ForceAutokickOn | turns on auto kick\r\n\t\tcase CRCC(0x34dcfc97, \"ForceAutokickOn\"):\r\n\t\t\tm_auto_kick = true;\r\n\t\t\tbreak;\r\n\r\n        // @script | ForceAutoKickOff | turns off auto kick\r\n\t\tcase CRCC(0x257947e, \"ForceAutokickOff\"):\r\n\t\t\tm_auto_kick = false;\r\n\t\t\tbreak;\r\n\r\n\t    // @script | AutoKickIsOff | true if auto kick is off\r\n\t\tcase CRCC(0x1baa1d9, \"AutoKickIsOff\"):\r\n\t\t\treturn m_auto_kick == false ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | RestoreAutokick | restores auto kick to \r\n        // original preferences\r\n\t\tcase CRCC(0x9fcfdfeb, \"RestoreAutokick\"):\r\n\t\t\tm_auto_kick = Mdl::Skate::Instance()->mp_controller_preferences[GetSkater()->m_skater_number].AutoKickOn;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | DoCarPlantBoost | boost after doing car plant\r\n\t\tcase CRCC(0x17846595, \"DoCarPlantBoost\"):\r\n\t\t{\r\n\t\t\tGetVel()[Y] = Mth::ClampMin(GetVel()[Y], 0.0f);\r\n\t\t\tGetVel()[Y] += GetPhysicsFloat(CRCD(0xcb49b3f2, \"Carplant_upward_boost\"));\t\r\n\t\t\t\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t\t\r\n\t\t\tMth::Vector front = GetVel();\r\n\t\t\tfront[Y] = 0.0f;\r\n\t\t\tif (front.LengthSqr() < 10.0f * 10.0f)\r\n\t\t\t{\r\n\t\t\t\tfront = GetMatrix()[Z];\t\t\t\t\r\n\t\t\t\tfront[Y] = 0.0f;\r\n\t\t\t\tif (front.LengthSqr() < 0.01f * 0.01f)\r\n\t\t\t\t{\r\n\t\t\t\t\tfront.Set(1.0f, 0.0f, 1.0f);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tfront.Normalize();\r\n\t\t\tGetVel() += front * GetPhysicsFloat(CRCD(0xb7422173, \"Carplant_forward_boost\"));\r\n\t\t\t\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | HandleLipOllieDirection |\r\n\t\tcase CRCC(0x259cb90d, \"HandleLipOllieDirection\"):\r\n\t\t{\r\n\t\t\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\t\t\r\n\t\t\tMth::Vector out = GetMatrix()[Z];\r\n\t\t\tout[Y] = 0.0f;\r\n\t\t\tout.Normalize();\t \r\n\t\t\tMth::Vector along(out[Z], 0.0f, -out[X], 0.0f);\r\n\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\t\t// We've jumped off a lip, so we want to give us some velocity to the left\r\n\t\t\tif (control_pad.m_right.GetPressed())\r\n\t\t\t{\r\n\t\t\t\t// don't allow right jumping\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t\telse if (BREAK_SPINE_BUTTONS)\r\n\t\t\t{\r\n\t\t\t\tGetVel() += out * GetPhysicsFloat(CRCD(0x1f96c224, \"Lip_side_hop_speed\"));\r\n\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t} \r\n\t\t\telse if (control_pad.m_left.GetPressed()\r\n\t\t\t\t&& static_cast< int >(control_pad.m_left.GetPressedTime()) > GetPhysicsInt(CRCD(0x3080e9e7, \"Lip_held_jump_out_time\")))\r\n\t\t\t{\r\n\t\t\t\tGetVel() += out * GetPhysicsFloat(CRCD(0xdc818b7e, \"Lip_side_jump_speed\")); \r\n\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t} \r\n\t\t\tif (control_pad.m_up.GetPressed()\r\n\t\t\t\t&& static_cast< int >(control_pad.m_up.GetPressedTime()) > GetPhysicsInt(CRCD(0x9b25142a, \"Lip_held_jump_along_time\")))\r\n\t\t\t{\r\n\t\t\t\tGetVel() -= along * GetPhysicsFloat(CRCD(0x1ab3809f, \"Lip_along_jump_speed\")); \r\n\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t}\r\n\t\t\telse if (control_pad.m_down.GetPressed()\r\n\t\t\t\t&& static_cast< int >(control_pad.m_down.GetPressedTime()) > GetPhysicsInt(CRCD(0x9b25142a,\"Lip_held_jump_along_time\")))\r\n\t\t\t{\r\n\t\t\t\tGetVel() += along * GetPhysicsFloat(CRCD(0x1ab3809f, \"Lip_along_jump_speed\"));\r\n\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t\t} \r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t}  \t\r\n\t\t\t\r\n        // @script | OrientToNormal | \r\n\t\tcase CRCC(0x1d1fd4f0, \"OrientToNormal\"):\r\n\t\t\tm_display_normal = GetMatrix()[Y];\r\n\t\t\tm_current_normal = GetMatrix()[Y];\r\n\t\t\tnew_normal(m_feeler.GetNormal());\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | SetSpeed | \r\n        // @uparm 0.0 | speed in inches per second, so 3000 is very very fast\r\n\t\t// The skater's max speed is about 1100 inches per second (depends on stats)\r\n\t\t// this is usually used in conjunction with Overridelimits, to provide a temporary speed boost\r\n\t\tcase CRCC(0x383b939b, \"SetSpeed\"):\r\n\t\t{\r\n\t\t\tfloat Speed = 0.0f;\r\n\t\t\tpParams->GetFloat(NO_NAME, &Speed);\r\n\t\t\tfloat length_sqr = GetVel().LengthSqr();\r\n\t\t\tif (length_sqr < 0.001f)\r\n\t\t\t{\r\n\t\t\t\tGetVel() = GetMatrix()[Z];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tGetVel() *= 1.0f / sqrtf(length_sqr);\r\n\t\t\t}\r\n\t\t\tGetVel() *= Speed;\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        // @script | NoSpin | sets flag, disabling spin\r\n\t\tcase CRCC(0x54ef2b79, \"NoSpin\"):\r\n\t\t\tmNoSpin = true;\r\n\t\t\tSetFlagFalse(AUTOTURN);\r\n\t\t\tbreak;\r\n\r\n        // @script | CanSpin | sets flag enabling spin\r\n\t\tcase CRCC(0xe2998b9, \"CanSpin\"):\r\n\t\t\tmNoSpin = false;\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | InBail | sets is_bailing flag \r\n\t\tcase CRCC(0x6fc5aae0, \"InBail\"):\r\n\t\t{\r\n\t\t\tSetFlagTrue(IS_BAILING);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        // @script | NotInBail | clears is_bailing flag\r\n\t\tcase CRCC(0xbd4303f4, \"NotInBail\"):\r\n\t\t{\r\n\t\t\tSetFlagFalse(IS_BAILING);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n        // @script | IsInBail | true if bailing (as defined by is_bailing flag)\r\n\t\tcase CRCC(0xa901a50c, \"IsInBail\"):\r\n\t\t\treturn GetFlag(IS_BAILING) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\r\n\t    // @script | BailOn | turn bails on\r\n\t\tcase CRCC(0xe0df1f0a, \"BailOn\"):\r\n\t\t\tm_bail = true;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | BailOff | turn bails off\r\n\t\tcase CRCC(0x8c3d7864, \"BailOff\"):\r\n\t\t\tm_bail = false;\r\n\t\t\tbreak;\r\n\r\n        // @script | BailIsOn | true if bails on\r\n\t\tcase CRCC(0xe1d5168, \"BailIsOn\"):\r\n\t\t\treturn m_bail ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\r\n        // @script | FrontTruckSparks | true if sparks should be coming from the front trucks, false if from rear\r\n        case CRCC(0xe0760055, \"FrontTruckSparks\"):\r\n\t\t\treturn m_front_truck_sparks ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\r\n        // @script | SetFrontTruckSparks | sets sparks to come from front trucks\r\n\t\tcase CRCC(0x19d0e5fb, \"SetFrontTruckSparks\"):\r\n\t\t\tm_front_truck_sparks = true;\r\n\t\t\tbreak;\r\n\r\n        // @script | SetRearTruckSparks | sets sparks to come from rear trucks\r\n\t\tcase CRCC(0xb48ec756, \"SetRearTruckSparks\"):\r\n\t\t\tm_front_truck_sparks = false;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | SetState | sets the state to the specified state\r\n        // @uparm name | state name (lip, air, ground)\r\n\t\tcase CRCC(0x948ebf96, \"SetState\"):\r\n\t\t{\r\n\t\t\tuint32 StateChecksum = 0;\r\n\t\t\tpParams->GetChecksum(NO_NAME, &StateChecksum);\r\n\t\t\t\r\n\t\t\tif (GetState() == LIP && StateChecksum != CRCD(0xa549b57b, \"Lip\"))\r\n\t\t\t{\r\n\t\t\t\t// Trigger the lip off event.\r\n\t\t\t\tmaybe_trip_rail_trigger(TRIGGER_LIP_OFF);\r\n\t\t\t}\r\n\r\n\t\t\t// If we are going to \"LIP\" via script then clear the rail node, as it's a patch to get the skater to freeze\r\n\t\t\tif (GetState() != LIP && StateChecksum == CRCD(0xa549b57b, \"Lip\"))\r\n\t\t\t{\r\n\t\t\t\tmp_rail_node = NULL;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// if script alters state from wallride (like for a bail), then snap upright   \r\n\t\t\t// note, this command does not support setting TO wall, if it does, we should check here\r\n\t\t\tif (GetState() == WALL)\r\n\t\t\t{\r\n\t\t\t\tnew_normal(Mth::Vector(0.0f, 1.0f, 0.0f));\r\n\t\t\t\tResetLerpingMatrix();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tswitch (StateChecksum)\r\n\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase CRCC(0x439f4704, \"Air\"):\r\n\t\t\t\t\tSetState(AIR);\r\n\t\t\t\t\tbreak;\t\r\n\t\t\t\tcase CRCC(0x58007c97, \"Ground\"):\r\n\t\t\t\t\tm_last_ground_feeler.SetTrigger(0); // prevent spurious gaps\r\n\t\t\t\t\tSetState(GROUND);\r\n\t\t\t\t\tbreak;\t\r\n\t\t\t\tcase CRCC(0xa549b57b, \"Lip\"):\r\n\t\t\t\t\tSetState(LIP);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDbg_Assert(false);\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | SetRailSound | sets the rail sound to either grind or slide\r\n        // @uparm Grind | pass either Grind or Slide\r\n\t\tcase CRCC(0x947fccf4, \"SetRailSound\"):\r\n\t\t{\r\n\t\t\tuint32 rail_sound_checksum = 0;\r\n\t\t\tpParams->GetChecksum(NO_NAME, &rail_sound_checksum, Script::ASSERT);\r\n\t\t\tDbg_MsgAssert(rail_sound_checksum == CRCD(0x255ed86f,\"Grind\") || rail_sound_checksum == CRCD(0x8d10119d, \"Slide\"),\r\n\t\t\t\t(\"\\n%s\\nBad rail sound type '%s' sent to SetRailSound\", pScript->GetScriptInfo(), Script::FindChecksumName(rail_sound_checksum)));\r\n\t\t\tif (rail_sound_checksum == CRCD(0x8d10119d, \"Slide\"))\r\n\t\t\t{\r\n\t\t\t\tSetFlagTrue(RAIL_SLIDING);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tSetFlagFalse(RAIL_SLIDING);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | LockVelocityDirection | When passed the flag On this will cause the skater's\r\n\t\t// velocity to be locked in its current direction and be unaffected by the skater's rotation.\r\n\t\t// Only works when on the ground however.\r\n\t\t// @flag On | Enable\r\n\t\t// @flag Off | Disable (Ie, back to normal)\r\n\t\tcase CRCC(0xacb82c02, \"LockVelocityDirection\"):\r\n\t\t\tm_lock_velocity_direction = pParams->ContainsFlag(CRCD(0xf649d637, \"On\"));\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | SetRollingFriction | change the rolling friction value\r\n        // @flag Default | use the default value\r\n        // @uparm 0.0 | friction coeff\r\n\t\tcase CRCC(0x510f983b, \"SetRollingFriction\"):\r\n\t\t\tpParams->GetFloat(NO_NAME, &m_rolling_friction);\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0x1ca1ff20, \"Default\")))\r\n\t\t\t{\r\n\t\t\t\tif (m_special_friction_duration == 0.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_rolling_friction = GetPhysicsFloat(CRCD(0x78f80ec4, \"Physics_Rolling_Friction\"));\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n        \r\n        // @script | SetGrindTweak | \r\n        // @uparm int | grind tweak\r\n\t\tcase CRCC(0x71b993b7, \"SetGrindTweak\"):\r\n\t\t\tpParams->GetInteger(NO_NAME, &mGrindTweak);\r\n\t\t\tbreak;\r\n   \r\n        // @script | Ledge | true if ledge\r\n\t\tcase CRCC(0x315d9ed4, \"Ledge\"):\r\n\t\t\treturn mLedge ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | BadLedge | true if bad ledge\r\n\t\tcase CRCC(0xbe371b7b, \"BadLedge\"):\r\n\t\t\treturn mBadLedge ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | SkateInAble | Do a collision check using a horizontal line a bit below the skater, and return true if it hits something skatable.\r\n        // @flag Left | go left to right\r\n\t\t// Parameters in physics.q: SkateInAble_HorizOffset and SkateInAble_DownOffset\r\n        // @flag Lip | This will do a check to see if the other side of the spine that the\r\n\t\t// skater might be doing a lip trick on is skateinable.\r\n\t\t// The collision check is down relative to the skater, but horizontal relative to \r\n\t\t// the world because of the skater's wacky orientation when doing a lip trick.\r\n\t\t// The direction of the collision check is towards the skater, so that it detects the\r\n\t\t// other side of the spine.\r\n\t\t// Parameters in physics.q: SkateInAble_LipHorizOffset and SkateInAble_LipDownOffset\r\n\t\tcase CRCC(0x55934543, \"SkateInAble\"):\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0xa549b57b, \"Lip\")))\r\n\t\t\t{\r\n\t\t\t\tfloat HorizOff = GetPhysicsFloat(CRCD(0xb92cbe3b, \"SkateInAble_LipHorizOffset\"));\r\n\t\t\t\tfloat DownOff = GetPhysicsFloat(CRCD(0xefdfe781, \"SkateInAble_LipDownOffset\"));\r\n\t\t\t\tm_col_end = GetPos();\r\n\t\t\t\tm_col_end[Y] -= DownOff;\r\n\t\t\t\tm_col_start = m_col_end - HorizOff * GetMatrix()[Y];\r\n\t\t\t\tif (get_member_feeler_collision())\r\n\t\t\t\t{\r\n\t\t\t\t\treturn m_col_flag_vert ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// If the first check fails, do another check straight down. This is for when the skater is doing a lip trick on a high up rail that\r\n\t\t\t\t\t// still has vert beneath it.\r\n\t\t\t\t\tHorizOff = GetPhysicsFloat(CRCD(0x108613cb, \"SkateInAble_LipExtraCheckHorizOffset\"));\r\n\t\t\t\t\tDownOff = GetPhysicsFloat(CRCD(0xf9dc446d, \"SkateInAble_LipExtraCheckDownOffset\"));\r\n\t\t\t\t\tm_col_start = GetPos() - HorizOff * GetMatrix()[Y];\r\n\t\t\t\t\tm_col_end = m_col_start;\r\n\t\t\t\t\tm_col_end[Y] -= DownOff;\r\n\t\t\t\t\tif (get_member_feeler_collision())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn m_col_flag_vert ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfloat HorizOff=GetPhysicsFloat(CRCD(0xc78ebe56,\"SkateInAble_HorizOffset\"));\r\n\t\t\t\tMth::Vector a = GetPos() + HorizOff * GetMatrix()[X];\r\n\t\t\t\ta[Y] -= GetPhysicsFloat(CRCD(0xfca3378c,\"SkateInAble_DownOffset\"));\r\n\t\t\t\tMth::Vector b = a - 2.0f * HorizOff * GetMatrix()[X];\r\n\t\t\t\t\r\n\t\t\t\tif (pParams->ContainsFlag(CRCD(0x85981897,\"Left\")))\r\n\r\n\t\t\t\t{\r\n\t\t\t\t\tm_col_start = a;\r\n\t\t\t\t\tm_col_end = b;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_col_start = b;\r\n\t\t\t\t\tm_col_end = a;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\tif (get_member_feeler_collision())\r\n\t\t\t\t{\r\n\t\t\t\t\treturn m_col_flag_vert ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\t\r\n\t\t\t}\t\r\n\t\t\treturn CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | LastSpinWas | check if last spin was frontside or backside (requires one flag)\r\n        // @flag Backside |\r\n        // @flag Frontside |\r\n\t\tcase CRCC(0x6c8a1316, \"LastSpinWas\"):\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0x47953f00, \"Backside\")))\r\n\t\t\t{\r\n\t\t\t\tif (GetFlag(FLIPPED))\r\n\t\t\t\t{\r\n\t\t\t\t\treturn !mYAngleIncreased ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\treturn mYAngleIncreased ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\t\t\t\t\r\n\t\t\t}\t\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0x996d5512, \"Frontside\")))\r\n\t\t\t{\r\n\t\t\t\tif (GetFlag(FLIPPED))\r\n\t\t\t\t{\r\n\t\t\t\t\treturn mYAngleIncreased ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\treturn !mYAngleIncreased ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\t\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(false, (\"LastSpinWas requires a FrontSide or BackSide flag\"));\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | LandedFromSpine | \r\n\t\tcase CRCC(0x448e3630, \"LandedFromSpine\"):\r\n\t\t\treturn mLandedFromSpine ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | LandedFromVert | \r\n\t\tcase CRCC(0xf37ce040, \"LandedFromVert\"):\r\n\t\t\treturn mLandedFromVert ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n   \r\n        // @script | SetLandedFromVert | sets the mlandedfromvert flag \r\n        // (check with LandedFromVert)\r\n\t\tcase CRCC(0x133e1293, \"SetLandedFromVert\"):\r\n\t\t\tmLandedFromVert = true;\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | ResetLandedFromVert | clears mlandedfromvert flag\r\n        // (check with LandedFromVert)\r\n\t\tcase CRCC(0xf922431, \"ResetLandedFromVert\"):\r\n\t\t\tmLandedFromVert = false;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | IsInVertAir | check if VERT_AIR flag is set\r\n\t\tcase CRCC(0xdfb8f052, \"InVertAir\"):\r\n\t\t\treturn GetFlag(VERT_AIR) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | AllowLipNoGrind | \r\n\t\tcase CRCC(0xc5b4b390, \"AllowLipNoGrind\"):\r\n\t\t\tmAllowLipNoGrind = true;\r\n\t\t\tbreak;\r\n\r\n        // @script | ClearAllLipNoGrind |\r\n\t\tcase CRCC(0xb9eebff6, \"ClearAllowLipNoGrind\"):\r\n\t\t\tmAllowLipNoGrind = false;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | NoRailTricks | don't allow rail tricks\r\n        // (turn on with AllowRailTricks)\r\n\t\tcase CRCC(0xec681a59, \"NoRailTricks\"):\r\n\t\t\tmNoRailTricks = true;\r\n\t\t\tbreak;\r\n\r\n        // @script | AllowRailTricks | turn off with NoRailTricks\r\n\t\tcase CRCC(0x65a559a, \"AllowRailTricks\"):\r\n\t\t\tmNoRailTricks = false;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | TurnToFaceVelocity | turn to face the proper direction\r\n\t\tcase CRCC(0x461e5b92, \"TurnToFaceVelocity\"):\r\n\t\t\t// Mick: Don't do it if vel is too short as skater will collapse\r\n\t\t\tif (GetVel().LengthSqr() < 0.01f * 0.01f) break;\r\n\t\t\t\r\n\t\t\tGetMatrix()[Z] = GetVel();\r\n\t\t\tGetMatrix()[Z].Normalize();\t\t\t\t\t\t\r\n\t\t\tGetMatrix()[X] = Mth::CrossProduct(GetMatrix()[Y], GetMatrix()[Z]);\r\n\t\t\tGetMatrix()[X].Normalize();\r\n\t\t\tGetMatrix()[Y] = Mth::CrossProduct(GetMatrix()[Z], GetMatrix()[X]);\r\n\t\t\tGetMatrix()[Y].Normalize();\r\n\t\t\t\r\n\t\t\tResetLerpingMatrix();\t\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | OverrideLimits | Overrides the limits to the maximum speed that the skater\r\n\t\t// can achieve.  This allows us to do temporary speed boosts whihc are much faster \r\n\t\t// than regular gameplay.  \r\n\t\t// You can specify a time that this speed limit will last for \r\n        // @parm float | max | Maximum speed in inches per second (normal gameplay is around 1000, so 5000 is nice)\r\n\t\t// @parmopt float | max_max | max | usualy the same as above.  It's a hard cap, making it bigger that max will give\r\n\t\t// you a smoother limit to the speed.\r\n\t\t// @parmopt float | friction | 0.0000020 | air friction.  Slows you down at a rate proportional to speed. So reduce this to stay fast longer\r\n\t\t// @parmopt float | gravity | physics default | down_gravity. gravity that slows you down when going up a slope\r\n\t\t// @parmopt float | time | 10000000000000,0f | time in seconds that this effect should last for\r\n\t\t// @flag end | end the effect (other parameters are unneeded and ignored if end is flagged)\r\n\t\tcase CRCC(0x90f1d8d5, \"OverrideLimits\"):\r\n\t\t{\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0xff03cc4e, \"end\")))\r\n\t\t\t{\r\n\t\t\t\tm_override_limits_time = 0.0f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpParams->GetFloat(CRCD(0x6289dd76, \"max\"), &m_override_max, Script::ASSERT);\r\n\t\t\t\tm_override_max_max = m_override_max;\r\n\t\t\t\tpParams->GetFloat(CRCD(0x73a19e3a, \"max_max\"), &m_override_max_max);\r\n\t\t\t\tm_override_limits_time = 10000000000000.0f;\r\n\t\t\t\tpParams->GetFloat(CRCD(0x906b67ba, \"time\"), &m_override_limits_time);\r\n\t\t\t\tm_override_air_friction = 0.0000020f;\r\n\t\t\t\tpParams->GetFloat(CRCD(0xedf3e7f4, \"friction\"), &m_override_air_friction);\r\n\t\t\t\tm_override_down_gravity = GetPhysicsFloat(CRCD(0x6618a713, \"Physics_Ground_Gravity\"));\r\n\t\t\t\tpParams->GetFloat(CRCD(0xa5e2da58, \"gravity\"), &m_override_down_gravity);\r\n\t\t\t\t\r\n\t\t\t\tif (pParams->ContainsFlag(CRCD(0xdf312928, \"NoTimeLimit\")))\r\n\t\t\t\t{\r\n\t\t\t\t\t// magic number meaning no time limit\r\n\t\t\t\t\tm_override_limits_time = -1.0f;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | SetSpecialFriction | This command is used in the Revert script to specify a set of friction values that should be used for\r\n\t\t// each Revert in the combo. m_special_friction_index gets reset as soon as the combo ends, ie by the ClearPanel_Landed & ClearPanel_Bailed\r\n\t    // functions.\r\n        // @uparm [] | array of friction values\r\n\t\tcase CRCC(0x5e8d9b80,\"SetSpecialFriction\"):\r\n\t\t{\r\n\t\t\tScript::CArray* pArray = NULL;\r\n\t\t\tpParams->GetArray(NO_NAME, &pArray);\r\n\t\t\tDbg_MsgAssert(pArray, (\"\\n%s\\nSetSpecialFriction requires an array of friction values\", pScript->GetScriptInfo()));\r\n\t\t\tif (m_special_friction_index >= static_cast< int >(pArray->GetSize()))\r\n\t\t\t{\r\n\t\t\t\tm_special_friction_index = static_cast< int >(pArray->GetSize()) - 1;\r\n\t\t\t}\t\r\n\t\t\tm_rolling_friction = pArray->GetFloat(m_special_friction_index);\r\n\t\t\tif (m_special_friction_index == 0)\r\n\t\t\t{\r\n\t\t\t\tm_special_friction_decrement_time_stamp = Tmr::GetTime();\r\n\t\t\t}\r\n\t\t\t++m_special_friction_index;\r\n\t\t\t\r\n\t\t\tpParams->GetFloat(CRCD(0x79a07f3f, \"Duration\"), &m_special_friction_duration);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | OverrideCancelGround | Overrided the Cancel_Ground flag in gaps\r\n\t\t// for use with reverts\r\n        // @flag Off | turn this flag off\r\n\t\tcase CRCC(0xb94bc0c6, \"OverrideCancelGround\"):\r\n\t\t\tSetFlag(OVERRIDE_CANCEL_GROUND, !pParams->ContainsFlag(CRCD(0xd443a2bc, \"Off\")));\r\n\t\t\tbreak;\t\r\n\t\t     \t\t\t\r\n        // @script | SetExtraPush | \r\n        // @parmopt float | radius | 48.0 | wall push radius\r\n        // @parmopt float | speed | 100.0 | wall push speed\r\n        // @parmopt float | turn | 6.0 | wall rotate speed\r\n\t\tcase CRCC(0xe47ff4b5, \"SetExtraPush\"):\r\n\t\t{\r\n\t\t\tm_wall_push_radius = 48.0f;\r\n\t\t\tm_wall_push_speed = 100.0f;\r\n\t\t\tm_wall_rotate_speed = 6.0f;\r\n\t\t\tpParams->GetFloat(CRCD(0xc48391a5, \"radius\"), &m_wall_push_radius);\r\n\t\t\tpParams->GetFloat(CRCD(0xf0d90109, \"speed\"), &m_wall_push_speed);\r\n\t\t\tpParams->GetFloat(CRCD(0xdfdfeab8, \"turn\"), &m_wall_rotate_speed);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | GetMatrixNormal | places the skater's matrix normal in x, y, and z\r\n\t\tcase CRCC(0x5144783, \"GetMatrixNormal\"):\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x7323e97c, \"x\"), GetMatrix()[Y][X]);\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x0424d9ea, \"y\"), GetMatrix()[Y][Y]);\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x9d2d8850, \"z\"), GetMatrix()[Y][Z]);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// Overloading the CMotionComponent member function for skater specific logic\r\n\t\tcase CRCC(0x8819dd8b, \"Obj_MoveToNode\"):\r\n\t\t{\r\n\t\t\tCMotionComponent* p_motion_component = GetMotionComponentFromObject(GetObject());\r\n\t\t\tDbg_Assert(p_motion_component);\r\n\t\t\t\r\n\t\t\t// call the member function, which will set m_matrix and m_pos\r\n\t\t\tbool result = p_motion_component->CallMemberFunction( Checksum, pParams, pScript );\r\n\t\t\t\r\n\t\t\t// and copy this into m_display_matrix\r\n\t\t\tResetLerpingMatrix();\r\n\r\n\t\t\t// set the shadow to stick to his feet, assuming we are on the ground\r\n\t\t\t// Note: These are used by the simple shadow, not the detailed one.\r\n\t\t\tCShadowComponent* p_shadow_component = GetShadowComponentFromObject(GetObject());\r\n\t\t\tDbg_Assert(p_shadow_component);\r\n\t\t\t\r\n\t\t\tp_shadow_component->SetShadowPos( GetSkater()->m_pos );\r\n\t\t\tp_shadow_component->SetShadowNormal( GetSkater()->m_matrix[Y] );\r\n\r\n\t\t\tm_safe_pos = GetPos();\t\t\t// needed for uberfrig\r\n\t\t\tGetOldPos() = GetPos();\t\t\t// needed for camera, so it thinks we've stopped\r\n\t\t\t\r\n\t\t\tGetObject()->SetTeleported();\r\n\r\n\t\t\t// Force an update of the skater's camera if this is a local skater\t\t\t\r\n\t\t\tif( GetSkater()->IsLocalClient())\r\n\t\t\t{\r\n\t\t\t\tObj::CCompositeObject *p_obj = GetSkater()->GetCamera();\r\n\t\t\t\tif (p_obj)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_obj->Update();\t // Not the best way of doing it...\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (!pParams->ContainsFlag( CRCD(0xd607e2e6,\"NoReset\") ))\r\n\t\t\t{\r\n\t\t\t\t// assume we want the skater to stop...\t\t\t\t\t\t\r\n\t\t\t\tm_last_ground_feeler.SetTrigger(0);  // patch to stop spurious gaps\r\n\t\t\t\tGetVel().Set();\r\n\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\tSetState(GROUND);\r\n\t\t\t\t\r\n\t\t\t\t// Make sure the flippedness of the skater is in a stable state\r\n\t\t\t\t// that reflects if he is goofy or not\r\n                SetFlag(FLIPPED, !GetSkater()->m_isGoofy);\r\n\t\t\t\t\r\n\t\t\t\t// reset any flippedness of animation\r\n\t\t\t\tCSkaterFlipAndRotateComponent* p_flip_and_rotate_component = GetSkaterFlipAndRotateComponentFromObject(GetObject());\r\n\t\t\t\tDbg_Assert(p_flip_and_rotate_component);\r\n\t\t\t\tp_flip_and_rotate_component->ApplyFlipState();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// the \"NoReset\" flag is set\r\n\t\t\t\t// so velocity is maintained\r\n\t\t\t\t// but we need to check if the orient flag is set\r\n\t\t\t\t// as that indicates that we want the velocity\r\n\t\t\t\t// to be oriented as well.\r\n\t\t\t\t// (if NoReset was set, then velocity will be zero)\r\n\t\t\t\tif ( pParams->ContainsFlag( CRCD(0x90a91232, \"orient\") ))\r\n\t\t\t\t{\r\n\t\t\t\t\tfloat y_vel = GetVel()[Y];\t   \t\t\t// y velocity is preserved.....\r\n\t\t\t\t\tGetVel()[Y] = 0.0f;\r\n\t\t\t\t\tfloat speed = GetVel().Length();  \t\t// how fast are we going?\r\n\t\t\t\t\tGetVel() = GetMatrix()[Z] * speed;\t\t// face forward, at that speed\r\n\t\t\t\t\tGetVel()[Y] = y_vel;\r\n\t\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn result ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\r\n\t\t// Used by the create-a-goal cursor to initialise the cursor position.\r\n\t\t// Cannot use the current skater's position because he might have just bailed by\r\n\t\t// jumping into water, which would then cause the cursor to get stuck.\r\n\t\tcase 0xf7e21884: // GetLastGroundPos\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddVector(CRCD(0x7f261953,\"Pos\"),m_last_ground_pos[X],m_last_ground_pos[Y],m_last_ground_pos[Z]);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterCorePhysicsComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::Reset (   )\r\n{\r\n\t// In Network games, don't set the skater to 0,0,0 because he is about to be teleported to a starting position and 0,0,0 means nothing.\r\n\tif (!GameNet::Manager::Instance()->InNetGame())\r\n\t{\r\n\t\t/*\r\n\t\tGetPos().Set(0.0f, 0.0f, 0.0f);\r\n\t\tGetOldPos().Set(0.0f, 0.0f, 0.0f);\r\n\t\tm_safe_pos.Set(0.0f, 0.0f, 0.0f);\r\n\t\t*/\r\n\t\tGetOldPos() = GetPos();\r\n\t\tm_safe_pos = GetPos();\r\n\t\tDUMP_POSITION;\r\n\t}\r\n\t\r\n\tm_pre_lip_pos.Set();\r\n\t\r\n\t/*\r\n\tGetMatrix().Identity();\r\n\tResetLerpingMatrix();\r\n\t*/\r\n\t\r\n\tm_state_change_timestamp = Tmr::GetTime();\r\n\t\r\n\tGetVel().Set(0.0f, 0.0f, 0.0f);\r\n\tDUMP_VELOCITY;\r\n\t\r\n\tSetState(GROUND);\r\n\tm_previous_state = GROUND;\r\n\t\r\n\tfor (int flag = NUM_ESKATERFLAGS; flag--; )\r\n\t{\r\n\t\tSetFlagTrue(static_cast< ESkaterFlag >(flag));\r\n\t\tSetFlagFalse(static_cast< ESkaterFlag >(flag));\r\n\t}\r\n\tSetFlag(FLIPPED, !GetSkater()->m_isGoofy);\r\n\t\r\n\tmp_movable_contact_component->LoseAnyContact();\r\n\t\r\n\t// bit nasty, prevents us getting \"SKATE_OFF_EDGE\" triggers\r\n\tm_last_ground_feeler.SetTrigger(0);\r\n\r\n\tm_wall_push_radius = 0.0f;\r\n\t\r\n\tm_tense_time = 0;\r\n\r\n\tmWallrideTime = 0;\r\n\t\r\n\tmNoSpin = false;\r\n\t\r\n\tm_bail = false;\r\n\t\r\n\tm_force_cankick_off = false;\r\n\tm_pressing_down_brakes = true;\r\n\t\r\n\tmp_state_component->mJumpedOutOfLipTrick = false;\r\n\t\t\r\n\t// mp_rail_node points to previous rail grinded, which might no longer be valid\r\n\t// best to set it to NULL  (fixed crash in park editor with multiple test-plays TT#678)\t\r\n\tmp_rail_node = NULL;\r\n\t\r\n\tm_override_limits_time = 0.0f;\r\n\tm_transfer_overrides_factor = 1.0f;\r\n\t\r\n\tm_last_wallplant_time_stamp = 0;\r\n\tm_last_wallpush_time_stamp = 0;\r\n\t\r\n\tm_last_jump_time_stamp = 0;\r\n\t\r\n\tm_special_friction_duration = 0.0f;\r\n}\r\n          \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::ReadySkateState ( bool to_ground_state, const SRailData* p_rail_data, const SAcidDropData* p_acid_drop_data )\r\n{\r\n\t// setup the state in preparation for being in skating mode next object update\r\n\t\r\n\t// reset all flags except FLIPPED\r\n\tResetFlags();\r\n\t\r\n\tif (to_ground_state)\r\n\t{\r\n\t\tSetState(GROUND);\r\n\t\tm_previous_state = GROUND;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSetState(AIR);\r\n\t\tm_previous_state = AIR;\r\n\t\t\r\n\t\t// no in-air orientation control after walking\r\n\t\tSetFlagTrue(NO_ORIENTATION_CONTROL);\r\n\t\t\r\n\t\tif (mp_walk_component->m_disallow_acid_drops)\r\n\t\t{\r\n\t\t\tSetFlagTrue(AIR_ACID_DROP_DISALLOWED);\r\n\t\t}\r\n\t}\r\n\t\r\n\tm_state_change_timestamp = Tmr::GetTime();\r\n\t\r\n\tResetLerpingMatrix();\r\n\t\r\n\tm_display_normal = m_last_display_normal = m_current_normal = GetMatrix()[Y];\r\n\t\r\n\tGetOldPos() = m_safe_pos = GetPos();\r\n\t\r\n\t// bit nasty, prevents us getting \"SKATE_OFF_EDGE\" triggers\r\n\tm_last_ground_feeler.SetTrigger(0);\r\n\r\n\tm_wall_push_radius = 0.0f;\r\n\t\r\n\tm_tense_time = 0;\r\n\r\n\tmWallrideTime = 0;\r\n\t\r\n\tmNoSpin = false;\r\n\t\r\n\t// m_bail = false;\r\n\t\r\n\tm_force_cankick_off = false;\r\n\tm_pressing_down_brakes = true;\r\n\t\r\n\tmp_state_component->mJumpedOutOfLipTrick = false;\r\n\t\t\r\n\tm_override_limits_time = 0.0f;\r\n\tm_transfer_overrides_factor = 1.0f;\r\n\t\r\n\tm_last_wallplant_time_stamp = 0;\r\n\tm_last_wallpush_time_stamp = 0;\r\n\t\r\n\tm_last_jump_time_stamp = 0;\r\n\t\r\n\t// handle special transitions\r\n\tif (p_rail_data)\r\n\t{\r\n\t\t// TT8717.  If walker had a movable contact, but that contact was not the same as the object containing the relavent rail manager component,\r\n\t\t// the skater was asserting in do_rail_physics.  We need to lose any old contact and acquire the appropriate contact.\r\n\t\tmp_movable_contact_component->LoseAnyContact();\r\n\t\tif (p_rail_data->p_movable_contact)\r\n\t\t{\r\n\t\t\tmp_movable_contact_component->ObtainContact(p_rail_data->p_movable_contact);\r\n\t\t}\r\n\t\tgot_rail(p_rail_data->rail_pos, p_rail_data->p_node, p_rail_data->p_rail_man, true, true);\r\n\t\tGetOldPos() = m_safe_pos = GetPos();\r\n\t}\r\n\telse if (p_acid_drop_data)\r\n\t{\r\n\t\tenter_acid_drop(*p_acid_drop_data);\r\n\t}\r\n\t\r\n\t#if 0\r\n\tconst char* p_state_names [   ] =\r\n\t{\r\n\t\t\"GROUND\",\r\n\t\t\"AIR\",\r\n\t\t\"WALL\",\r\n\t\t\"LIP\",\r\n\t\t\"RAIL\",\r\n\t\t\"WALLPLANT\"\r\n\t};\r\n\tDUMPS(p_state_names[GetState()]);\r\n\t#endif\r\n}\r\n          \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::CleanUpSkateState (   )\r\n{\r\n\tif (m_vert_air_last_frame)\r\n\t{\r\n\t\tm_vert_air_last_frame = false;\r\n        GetObject()->BroadcastEvent(CRCD(0x5e27200a, \"SkaterExitVertAir\"));\r\n\t}\r\n\t\r\n\t// longer rerail delay when walking\r\n\tm_rerail_time = static_cast< Tmr::Time >(GetPhysicsFloat(CRCD(0xe4412eb7, \"Rail_walk_rerail_time\")));\r\n\t\r\n\t// lip time counts towards rerail delay when walking\r\n\tif (m_lip_time > m_rail_time)\r\n\t{\r\n\t\tm_rail_time = m_lip_time;\r\n\t}\r\n\t\r\n\t// no grinding from walking after jumping out of a lip\r\n\tif (GetState() == AIR && m_previous_state == LIP)\r\n\t{\r\n\t\tSetFlagFalse(CAN_RERAIL);\r\n\t}\r\n\t\r\n\t// Extra clean up so that an observing camera will act OK while walking.  Note that observing cameras always use skater camera logic, even when the\r\n\t// observed player is walking.\r\n\tmp_state_component->m_state = GROUND;\r\n\tmp_state_component->m_camera_display_normal.Set(0.0f, 1.0f, 0.0f);\r\n\tmp_state_component->m_camera_current_normal.Set(0.0f, 1.0f, 0.0f);\r\n\tmp_state_component->m_spine_vel.Set();\r\n\tmp_state_component->mJumpedOutOfLipTrick = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSkaterCorePhysicsComponent::ResetFlags (   )\r\n{\r\n\t// reset all flags except FLIPPED\r\n\tfor (int flag = NUM_ESKATERFLAGS; flag--; )\r\n\t{\r\n\t\tESkaterFlag skater_flag = static_cast< ESkaterFlag >(flag);\r\n\t\tif (skater_flag == FLIPPED) continue;\r\n\t\tSetFlagTrue(skater_flag);\r\n\t\tSetFlagFalse(skater_flag);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::SetState ( EStateType state )\r\n{\r\n\tif (mp_state_component->m_state != state)\r\n\t{\r\n\t\tm_state_change_timestamp = Tmr::GetTime();\r\n\t\tm_previous_state = mp_state_component->m_state;\r\n\t}\r\n\t\r\n\t// if going out of lip state, and previous lip pos is valid (not zero), then move back to the previous lip position (so we drop down nicely)\r\n\tif (mp_state_component->m_state == LIP\r\n\t\t&& state != LIP \r\n\t\t&& (m_pre_lip_pos[X] != 0.0f || m_pre_lip_pos[Y] != 0.0f || m_pre_lip_pos[Z] != 0.0f))\r\n\t{\r\n\t\t// *** (SetState(LIP))  kind of nasty, but we want to allow them to move through the lip\r\n\t\t// we leave m_old_trigger_pos alone\r\n\t\tGetPos() = m_pre_lip_pos;\r\n\t\tGetOldPos() = GetPos();\r\n\t\tDUMP_POSITION;\r\n\t}\r\n\r\n\t// If setting the state to anything other than lip then kill the pre_lip_pos\t\r\n\tif (state != LIP)\r\n\t{\r\n\t\tm_pre_lip_pos.Set(0.0f, 0.0f, 0.0f);\r\n\t}\r\n\r\n\tif (state != GROUND)\r\n\t{\r\n\t\t// start recording graffiti tricks\r\n\t\tmp_trick_component->SetGraffitiTrickStarted( true );\r\n\t}\r\n\r\n\tif (mp_state_component->m_state == RAIL && state != RAIL)\r\n\t{\r\n\t\tSetFlagFalse(RAIL_SLIDING);\r\n\t}\r\n\r\n\tif (mp_state_component->m_state == AIR && state != AIR)\r\n\t{\r\n\t\t// If going from AIR to any other state, record the landing time. Required for the AirTimeLessThan and AirTimeGreaterThan functions.\r\n\t\tm_landed_time = Tmr::GetTime();\r\n\t\t\r\n\t\tSetFlagFalse(NO_ORIENTATION_CONTROL);\r\n\t\tSetFlagFalse(OLLIED_FROM_RAIL);\r\n\t}\t\r\n\telse if (mp_state_component->m_state != AIR && state == AIR)\r\n\t{\r\n\t\t// If going to AIR, record the takeoff time, unless going from WALL to AIR.\r\n\t\t// (The 'unless' bit fixes TT493, where hitting the ground from doing a wall-ride was not setting a big enough airtime)\r\n\t\tif (mp_state_component->m_state != WALL)\r\n\t\t{\r\n\t\t\tm_went_airborne_time = Tmr::GetTime();\r\n\t\t}\t\r\n\r\n\t\t// Reset the spin tracking stuff.\r\n\t\tmp_trick_component->mTallyAngles = 0.0f;\r\n\t\t\r\n\t\t// Clear the L1 and R1 triggers, since they're used for spin taps.\r\n\t\tmp_input_component->GetControlPad().m_L1.ClearTrigger();\r\n\t\tmp_input_component->GetControlPad().m_R1.ClearTrigger();\r\n\t\t// Just to be sure\r\n\t\tm_tap_turns = 0.0f;\r\n\t}   \r\n\t\r\n\tmp_state_component->m_state = state;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\tmp_sound_component->SetState(state);\r\n}\r\n          \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::ReverseFacing (   )\r\n{\r\n\tGetMatrix()[Z] = -GetMatrix()[Z];\r\n\tGetMatrix()[X] = -GetMatrix()[X];\r\n\tResetLerpingMatrix();\r\n\tmRail_Backwards = !mRail_Backwards;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (DebugSkaterScripts && GetObject()->GetType() == SKATE_TYPE_SKATER)\r\n\t{\r\n\t\tprintf(\"%d: Rotating skater\\n\", (int) Tmr::GetRenderFrame());\r\n\t}\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::CollideWithOtherSkaterLost ( CCompositeObject* p_other_skater )\r\n{\r\n\t// reset all flags except FLIPPED\r\n\tResetFlags();\r\n\r\n\tSetState(AIR);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::limit_speed (   )\r\n{\r\n\tfloat save_y = GetVel()[Y];\r\n\tGetVel()[Y] = 0.0f;\r\n\t\r\n\tfloat speed = GetVel().Length();\r\n\tfloat max_max_speed = GetSkater()->GetScriptedStat(CRCD(0xcc5f87aa, \"Skater_Max_Max_Speed_Stat\")); \r\n\tfloat max_speed = GetSkater()->GetScriptedStat(CRCD(0x2eacddb3, \"Skater_Max_Speed_Stat\"));\r\n\r\n\tif (m_override_limits_time != 0.0f)\r\n\t{\r\n\t\t// -1.0f is a magic number causing no time limit\r\n\t\tif (m_override_limits_time != -1.0f)\r\n\t\t{\r\n\t\t\tm_override_limits_time -= m_frame_length;\r\n\t\t\tif (m_override_limits_time < 0.0f)\r\n\t\t\t{\r\n\t\t\t\tm_override_limits_time = 0.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t\tmax_max_speed = m_override_max_max;\r\n\t\tmax_speed = m_override_max;\r\n\t}\r\n\t\r\n\tif (speed > max_max_speed)\r\n\t{\r\n\t\tspeed = max_max_speed;\r\n\t\tGetVel().Normalize(speed);\r\n\t\tDUMP_VELOCITY;\r\n\t}\r\n\t\r\n\tif (speed > max_speed)\r\n\t{\r\n\t\tapply_wind_resistance(GetPhysicsFloat(CRCD(0x850eb87a, \"Physics_Heavy_Air_Friction\")));\r\n\t}\r\n\t\r\n\tGetVel()[Y] = save_y;\r\n\t\r\n\t// decrement the special friction counter\r\n\tif (m_special_friction_duration != 0.0f)\r\n\t{\r\n\t\tm_special_friction_duration -= m_frame_length;\r\n\t\tif (m_special_friction_duration <= 0.0f)\r\n\t\t{\r\n\t\t\t// reset the special friction to default\r\n\t\t\tm_special_friction_duration = 0.0f;\r\n\t\t\tm_rolling_friction = GetPhysicsFloat(CRCD(0x78f80ec4, \"Physics_Rolling_Friction\"));\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::apply_wind_resistance ( float friction )\r\n{\r\n\t// air friction is proportional to the square of the velocity; this is a limiting friction, and has much more effect at high speeds\r\n\tfloat speed_squared = GetVel().LengthSqr();\r\n\tif (speed_squared < 0.00001f) return;\r\n\t\r\n\tMth::Vector air_friction = GetVel();\r\n\tair_friction.Normalize(friction * 60.0f * m_frame_length * speed_squared);\r\n\t\r\n\tif (air_friction.LengthSqr() > speed_squared)\r\n\t{\r\n\t\tGetVel().Set();\r\n\t\tDUMP_VELOCITY;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGetVel() -= air_friction;\r\n\t\tDUMP_VELOCITY;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::do_on_ground_physics (  )\r\n{\t\t\r\n\t// clear any flags that have no meaning when on the ground\r\n\tSetFlagFalse(CAN_BREAK_VERT);\r\n\tSetFlagFalse(VERT_AIR);\r\n\tSetFlagFalse(TRACKING_VERT);\r\n\tSetFlagFalse(SPINE_PHYSICS);\r\n\tSetFlagFalse(IN_ACID_DROP);\r\n\tSetFlagFalse(IN_RECOVERY);\r\n\tSetFlagFalse(AIR_ACID_DROP_DISALLOWED);\r\n\r\n\t// ground skateing will cancel any memory of what rail we were on, so the next one seems fresh\t\r\n\tmp_rail_node = NULL;\r\n\tm_last_rail_trigger_node_name = 0;\r\n\t\r\n\t// rotate velocity, so it lays in the plane we are on: (as skaters orientation can lag behind)\t\r\n\t// Dave note: calling RotateToPlane() with too small |vector| causes Nan problems - fix at some point.\r\n\tif( GetVel().Length() > 0.001f )\r\n\t{\r\n\t\tGetVel().RotateToPlane(m_current_normal);\r\n\t}\r\n\t\t\r\n\t// get gravitational force \t\r\n\tMth::Vector gravity(0.0f, GetPhysicsFloat(CRCD(0x6618a713, \"Physics_Ground_Gravity\")), 0.0f);\r\n\r\n\t// allow for override if we are going up the slope (we might want to set gravity to zero when rolling up a slope)\r\n\tif (m_override_limits_time != 0.0f && GetVel()[Y] > 0.0f)\r\n\t{\r\n\t\tgravity.Set(0.0f, m_override_down_gravity, 0.0f);\r\n\t}\r\n\r\n\t// project gravity onto the plane we are on\r\n\tgravity.ProjectToPlane(m_current_normal);\r\n\t\r\n\t// add gravity into our velocity, adjusting for time\r\n\tGetVel() += gravity * m_frame_length;\r\n\tDUMP_VELOCITY;\r\n\r\n\t// based on if we are doing a balance trick, then either handle braking/kicking, or do the balance physics\r\n\tswitch (mp_balance_trick_component->mBalanceTrickType)\r\n\t{\r\n\t\tcase 0:\r\n\t\t\t// Only do braking & speeding up when not doing a balance trick like a manual\t\t\t\r\n\t\t\tif (is_trying_to_brake())\r\n\t\t\t{\r\n\t\t\t\tdo_brake();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_braking = false;\r\n\t\t\t\tif (can_kick())\r\n\t\t\t\t{\r\n\t\t\t\t\tdo_kick();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0xac90769, \"NoseManual\"):\r\n\t\tcase CRCC(0xef24413b, \"Manual\"):\r\n\t\t\tm_braking = false;\r\n\t\t\t\r\n\t\t\tmp_balance_trick_component->mManual.DoManualPhysics();\r\n\r\n\t\t\t// start recording graffiti tricks\r\n\t\t\tmp_trick_component->SetGraffitiTrickStarted(true);\r\n\t\t\t\r\n\t\t\tif (Mdl::Skate::Instance()->GetCareer()->GetCheat(CRCD(0xb38341c9, \"CHEAT_PERFECT_MANUAL\")))\r\n\t\t\t{\r\n\t\t\t\t// Here, set the flag. It may seem redundant, but the above line is very likely\r\n\t\t\t\t// to be hacked by gameshark. They probably won't notice this one, which will\r\n\t\t\t\t// set the flags as if they had actually enabled the cheat -- which enables us\r\n\t\t\t\t// to detect that it has been turned on more easily.\r\n\t\t\t\tMdl::Skate::Instance()->GetCareer()->SetGlobalFlag( Script::GetInteger(CRCD(0xb38341c9, \"CHEAT_PERFECT_MANUAL\")));\r\n\t\t\t\tmp_balance_trick_component->mManual.mManualLean = 0.0f;\r\n\t\t\t\tmp_balance_trick_component->mManual.mManualLeanDir = 0.0f;\r\n\t\t\t\tg_CheatsEnabled = true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x3506ce64, \"Skitch\"):\r\n\t\t\tmp_balance_trick_component->mSkitch.DoManualPhysics();\r\n            if (Mdl::Skate::Instance()->GetCareer()->GetCheat(CRCD(0x69a1ce96, \"CHEAT_PERFECT_SKITCH\")))\r\n\t\t\t{\r\n\t\t\t\t// Here, set the flag. It may seem redundant, but the above line is very likely\r\n\t\t\t\t// to be hacked by gameshark. They probably won't notice this one, which will\r\n\t\t\t\t// set the flags as if they had actually enabled the cheat -- which enables us\r\n\t\t\t\t// to detect that it has been turned on more easily.\r\n\t\t\t\tMdl::Skate::Instance()->GetCareer()->SetGlobalFlag( Script::GetInteger(CRCD(0x69a1ce96, \"CHEAT_PERFECT_SKITCH\")));\r\n\t\t\t\tmp_balance_trick_component->mSkitch.mManualLean = 0.0f;\r\n\t\t\t\tmp_balance_trick_component->mSkitch.mManualLeanDir = 0.0f;\r\n\t\t\t\tg_CheatsEnabled = true;\r\n\t\t\t}\r\n\t\t\tbreak;\t\t\t\r\n\t\t\t\r\n\t\tcase CRCC(0x255ed86f, \"Grind\"):\r\n\t\tcase CRCC(0x8d10119d, \"Slide\"):\r\n\t\t{\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tCSkaterEndRunComponent* p_endrun_component = GetSkaterEndRunComponentFromObject(GetObject());\r\n\t\t\tDbg_Assert(p_endrun_component);\r\n            Dbg_MsgAssert(!p_endrun_component->IsEndingRun() || !p_endrun_component->RunHasEnded(), (\"Grind balance trick done on ground?\"));\r\n\t\t\t#endif\r\n\t\t\tbreak;\t\t\t\r\n\t\t}\r\n\t\t\t\r\n\t\tcase CRCC(0xa549b57b, \"Lip\"):\t\r\n\t\t{\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tCSkaterEndRunComponent* p_endrun_component = GetSkaterEndRunComponentFromObject(GetObject());\r\n\t\t\tDbg_Assert(p_endrun_component);\r\n\t\t\tDbg_MsgAssert(!p_endrun_component->IsEndingRun() || !p_endrun_component->RunHasEnded(), (\"Lip balance trick done on ground?\"));\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\t\r\n\t\t{\r\n\t\t\tDbg_Assert(false);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\t\t\r\n\r\n\t// Ground friction is rolling friction + wind resistance\r\n\t// Update velocity for friction before using velocity\r\n\thandle_ground_friction();\r\n\r\n\t// if too close to a wall, then adjust velocity to move the skater away from it\r\n\t// the distance that is checked can be changed by script, and probably gets big in bails, to stop the skater clipping through walls\r\n\tpush_away_from_walls();\r\n\r\n\t// Calculate how much we want to move, based on the velocity\r\n\tMth::Vector m_movement = GetVel() * m_frame_length;\r\n\r\n\t// when skitching, we get sucked into the skitch point\r\n\tif (GetFlag(SKITCHING))\r\n\t{\r\n\t\tif (mp_movable_contact_component->GetContact() && mp_movable_contact_component->GetContact()->GetObject())\r\n\t\t{\r\n\t\t\tGetVel() = mp_movable_contact_component->GetContact()->GetObject()->GetVel() * GetPhysicsFloat(CRCD(0xdef25b34, \"skitch_speed_match\"));\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t}\r\n\t\tm_movement.Set();\r\n\t\tmove_to_skitch_point();\r\n\t}\r\n\r\n\t// if we are in contact with something, then factor in that \"movement,\" but not if (we are skitching, and in not in initial movement) \r\n\tif (mp_movable_contact_component->UpdateContact(GetPos()))  // still need to update it every frame, otherwise it gets confused\r\n\t{\r\n\t\tif (!GetFlag(SKITCHING))\r\n\t\t{\r\n\t\t\t// handle movement due to contact seperately from normal physic movement \r\n\t\t\t\r\n\t\t\tGetPos() += mp_movable_contact_component->GetContact()->GetMovement();\t\t \r\n\t\t\tGetOldPos() = GetPos();\t// (WITH CONTACT) frig, as movement is due to something carying us, no need to incorporate that into collision   \r\n\t\t\tm_safe_pos = GetPos();\t// (WITH CONTACT) frig, as movement is due to something carying us, no need to incorporate that into collision\r\n\t\t\tDUMP_POSITION;\r\n\t\t\t\r\n\t\t\tif (mp_movable_contact_component->GetContact()->IsRotated())\r\n\t\t\t{\r\n\t\t\t\tGetMatrix() *= mp_movable_contact_component->GetContact()->GetRotation();\r\n\t\t\t\tm_lerping_display_matrix *= mp_movable_contact_component->GetContact()->GetRotation();\r\n\t\t\t}\r\n\t\t}\r\n\t\t\t\r\n\t}\r\n\t\r\n\t// set \"move_again\" flag, for while loop\r\n\t// generally this will be cleared after the first time through the loop\r\n\t// but it can be set again, indicating that out movmeent was brought short\r\n\t// by hitting a curver surface that we can track around (like a Qp)\t\t\t  \r\n\tbool move_again = true;\r\n\t\r\n\t// we only let them move again once\r\n\t// so we have a flag that says if we have already done it this frame\r\n\tbool already_moved_again = false;\t\r\n\t\r\n\twhile (move_again)\r\n\t{\r\n\t\tmove_again = false;\r\n\t\t\r\n\t\tMth::Vector\tstart_pos = GetPos();\t  \t\t// remember where we started on this iteration\r\n\t\tGetPos() += m_movement;\t  \t\t\t\t// Move him\r\n\t\tDUMP_POSITION;\r\n\t\t\t\r\n\t\t// Handle collisions //////////////////////////////////////////////\t\t\t\t\t\t\r\n\t\tif (!GetFlag(SKITCHING))   \t// if skitching, then dont bother with forward collision\r\n\t\t{\r\n \t\t\thandle_forward_collision();\t\t\t\t\t\t\t\r\n\t\t}\r\n\t\t\r\n\r\n\t\t// Mick - removed the test for m_moving_to_skitch for now\r\n\t\t// as we want the cars to be able to drag the player over gaps and jumps\r\n\t\t// and it does not seem to look bad this way\r\n\t\t// the only problem might be during very abrupt cahnges in ground angle, \r\n\t\t// or maybe very uneven ground\t\t\r\n\t\tif (GetFlag(SKITCHING) /* && m_moving_to_skitch*/)\r\n\t\t{\r\n\t\t\t// moving to skitch point, so don't snap to ground, as\r\n\t\t\t// we might snap onto the vehicle\r\n\t\t\t// instead, just project the skater onto the plane of the car\r\n\t\t\t\r\n\t\t\t// Dan: We still need to update terrain, however\r\n\t\t\tm_feeler.m_start = GetPos() + 36.0f * GetMatrix()[Y];\r\n\t\t\tm_feeler.m_end = GetPos() - 200.0f * GetMatrix()[Y];\r\n\t\t\tif (get_member_feeler_collision())\r\n\t\t\t{\r\n\t\t\t\tset_terrain(m_feeler.GetTerrain());\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsnap_to_ground();\r\n\t\t}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t// now see how far we have moved\r\n\t\t// interestingly we often move more than we are supposed to\r\n\t\t// probably due to the \"snap to ground\" stuff.\t\t\r\n\t\tMth::Vector actual_movement_vector;\r\n\t\tactual_movement_vector = GetPos() - start_pos;\r\n\t\tfloat actual_distance_moved = actual_movement_vector.Length();\r\n\t\tfloat attempted_distance = m_movement.Length();\r\n\r\n\t\tif (!already_moved_again && GetState() == GROUND)\r\n\t\t{\r\n\t\t\tif (actual_distance_moved < (attempted_distance - 0.1f))\r\n\t\t\t{\r\n\t\t\t\tm_movement = GetVel();\t\t\t\t\t \t\r\n\t\t\t\tm_movement.Normalize();\t\t\t  \t\t\t\t\t\t\t\t// get new direction of travel\r\n\t\t\t\tm_movement *= attempted_distance;\t\t\t\t\t\t\t\t\t// at old speed\r\n\t\t\t\tm_movement *= 1.0f - actual_distance_moved / attempted_distance;\t// scale to account for movement\t\t\t\t\t\t\t\r\n\t\t\t\tmove_again = true;\r\n\t\t\t\talready_moved_again = true;\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// The remaining \"ground physics\" should only be done if we are still on the ground (might have skated off it) \r\n\tif (GetState() == GROUND)\r\n\t{\r\n\t\thandle_ground_rotation();\t\t\t\r\n\t\t\r\n\t\t// don't let the board slide sideways\t\r\n\t\t// K: Avoid anything that might change the velocity direction if this flag is set.\r\n\t\tif (!m_lock_velocity_direction)\r\n\t\t{\r\n\t\t\tremove_sideways_velocity(GetVel());\r\n\t\t}\t\r\n\t\r\n\t\tif (!GetFlag(SKITCHING))\r\n\t\t{\r\n\t\t\t// check if we are too close to a wall, and pop us out and away\t\t\r\n\t\t\tcheck_side_collisions();\t\t\r\n\t\t\t\r\n\t\t\t// check if we are moving slowly and leaning, and mush us more away from a wall if so\r\n\t\t\tcheck_leaning_into_wall();\r\n\t\t}\r\n\t\t\r\n\t\t// K: This flag is to allow the skater to be rotated on the ground without affecting his\r\n\t\t// velocity direction, so also disable the flipping otherwise 360 rotations won't be possible.\r\n\t\tif (!m_lock_velocity_direction)\r\n\t\t{\r\n\t\t\t// might have gone upa  slope, and gravity pulled us down, so we are not skating backwards\r\n\t\t\tflip_if_skating_backwards();\t\r\n\t\t}\t\r\n\t\r\n\t\t// Check for jumping\r\n\t\tif (maybe_flag_ollie_exception())\t\r\n\t\t{\r\n\t\t\tmaybe_straight_up();\r\n\t\t\tSetFlagTrue(CAN_BREAK_VERT);\r\n\t\t}\r\n\t\r\n\t\tmp_trick_component->TrickOffObject(m_last_ground_feeler.GetNodeChecksum());\r\n\t\t\t\r\n\t\tm_tap_turns = 0.0f;\t\r\n\t}\r\n\t\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (Script::GetInteger(CRCD(0x3ae85eef, \"skater_trails\")))\r\n\t{\r\n\t\tGfx::AddDebugLine(GetPos() + m_current_normal, GetOldPos() + m_current_normal, GREEN, 0, 0);\r\n\t}\r\n\t#endif\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::is_trying_to_brake (   )\r\n{\t\t\t\t\t\t\t\t   \r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\r\n\t// if not autokick, and not accelerating (square pressed), and going slow, then brake\t\r\n\tif (!m_auto_kick && !control_pad.m_square.GetPressed() && GetVel().Length() < 50.0f)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn control_pad.m_down.GetPressed() \t\t\t\t// Down must be pressed\r\n\t\t&& m_pressing_down_brakes\t\t\t\t\t\t// and must be enabled\r\n\t\t&&\r\n\t\t(\r\n\t\t\tGetVel().Length() < 50.0f\t\t   \t// and either going really slow\r\n\t\t\t||\r\n\t\t\t(\r\n\t\t\t\t!control_pad.m_right.GetPressed()\t\t// or not pressed right or left\r\n\t\t\t\t &&\r\n\t\t\t\t!control_pad.m_left.GetPressed()\r\n\t\t\t)\r\n\t\t\t||\r\n\t\t\t(                                           // or going backwards\r\n\t\t\t\tMth::DotProduct(GetVel(), GetMatrix()[Z]) < 0.0f\r\n\t\t\t)\r\n\t\t);\t\t\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::do_brake (   )\r\n{\t\t\r\n\t// Handle braking\r\n\t\r\n\tm_braking = true;\r\n\t\r\n\tif (on_steep_slow_slope())\r\n\t{\r\n\t\tm_braking = false;\r\n\t\treturn;\r\n\t}\r\n\r\n\tfloat speed = GetVel().Length();\r\n\r\n\t// if already really slow (or stopped), then just stop\r\n\tif (speed < GetPhysicsFloat(CRCD(0xe5d73f6f, \"Physics_Brake_Acceleration\")) * 2.0f * m_frame_length)\r\n\t{\r\n\t\t\tGetVel().Set();\r\n\t\t\tDUMP_VELOCITY;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t#if 0 // old code, this check doesn't seem necessary given the above if branch; Dan\r\n\t\t// Mth::Vector forward = GetVel();\r\n\t\t// forward.Normalize();\r\n\t\t// forward *= -PHYSICS_BRAKE_ACCELERATION;\r\n\t\t// Mth::Vector old_vel = GetVel();\t\t\t\t\t// remember old velocity\t\t\r\n\t\t// m_vel += forward * m_frame_length;\t\t\t\t\t\t \t// apply braking force\r\n\t\t// if (Mth::DotProduct(GetVel(), old_vel) < 0.0f)\t// if the velocty now in other direction\r\n\t\t// {\r\n\t\t\t// GetVel().Set();\t\t\t\t\t\t\t\t// then clear it to zero velocity\r\n\t\t// }\r\n\t\t#else\r\n\t\tMth::Vector brake = GetVel();\r\n\t\tbrake.Normalize(-GetPhysicsFloat(CRCD(0xe5d73f6f, \"Physics_Brake_Acceleration\")) * m_frame_length);\r\n\t\tGetVel() += brake;\r\n\t\tDUMP_VELOCITY;\r\n\t\t#endif\r\n\t}\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::on_steep_slow_slope (   )\r\n{\r\n\tfloat speed = GetVel().Length();\r\n\tif (speed < GetPhysicsFloat(CRCD(0x62a1fa03,\"Skater_max_sloped_turn_speed\"))\r\n\t\t&& m_current_normal[Y] < GetPhysicsFloat(CRCD(0xc3527ef2, \"Skater_max_sloped_turn_cosine\")))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::can_kick (   )\r\n{\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\t\t\t\t\t \r\n\t\r\n\tif (m_force_cankick_off)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// don't allow kicking if autokick is off and square not pressed\t\r\n\tif (!m_auto_kick && !control_pad.m_square.GetPressed())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// don't allow kicking (accelerating) if \"down\" is pressed\r\n\t// as we would either be braking or sharp turning  \r\n\tif (control_pad.m_down.GetPressed())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfloat speed = GetVel().Length();\r\n\t\r\n\tif (!GetFlag(TENSE))\r\n\t{\r\n\t\tif (speed > GetSkater()->GetScriptedStat(CRCD(0x4610c2e3, \"Skater_Max_Standing_Kick_Speed_Stat\")))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (speed > GetSkater()->GetScriptedStat(CRCD(0x92e0247c, \"Skater_Max_Crouched_Kick_Speed_Stat\")))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\r\n\tDbg_Assert(m_auto_kick || control_pad.m_square.GetPressed());\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::do_kick (   )\r\n{\r\n\t// Get skater's forward direction\r\n\tMth::Vector forward;\r\n\t\r\n\t// K: Avoid anything that might change the velocity direction if this flag is set.\r\n\tif (m_lock_velocity_direction)\r\n\t{\r\n\t\tforward = GetVel();\r\n\t\t\r\n\t\t// Make sure the skater doesn't get stuck unable to move.\r\n\t\tif (forward.Length() < 0.5f)\r\n\t\t{\r\n\t\t\tforward = GetMatrix()[Z];\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tforward.Normalize();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tforward = GetMatrix()[Z];\r\n\t}\r\n\t\t\r\n\tif (GetFlag(TENSE))\r\n\t{\r\n\t\tforward *= GetSkater()->GetScriptedStat(CRCD(0x3d24128e, \"Physics_crouching_Acceleration_stat\"));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tforward *= GetSkater()->GetScriptedStat(CRCD(0x5f9b864d, \"Physics_Standing_Acceleration_stat\"));\r\n\t}\r\n\t\t\r\n\t// apply to velocity\r\n\tGetVel() += forward * m_frame_length;\r\n\tDUMP_VELOCITY;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::handle_ground_friction (   )\r\n{\r\n\t// Apply the various type of friction that are acting when on the ground\r\n\t\r\n\t// if no autokick, and we are not bailing, and we have default friction then don't apply any friction\r\n\t// as it sucks to slow down when you do not have autokick\r\n\tif (!m_auto_kick && !GetFlag(IS_BAILING) && m_rolling_friction == GetPhysicsFloat(CRCD(0x78f80ec4, \"Physics_Rolling_Friction\")))\r\n\t{\r\n\t\t// autokick friction\r\n\t\t// currently none\r\n\t}\r\n\telse\r\n\t{\t\r\n\t\t// non-autokick friction\r\n\t\thandle_wind_resistance();\r\n\t\thandle_rolling_resistance();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::handle_wind_resistance (   )\r\n{\t\r\n\t// Wind resistance differs, based on if we are crouched or not (as when we are crouched, we have a lower profile, so less wind resistance)\r\n\t\r\n\tfloat crouched_friction = GetPhysicsFloat(CRCD(0xbed96eda, \"Physics_Crouched_Air_Friction\"));\r\n\tfloat standing_friction = GetPhysicsFloat(CRCD(0x1a78b6fc, \"Physics_Standing_Air_Friction\"));\r\n\t\r\n\tif (m_override_limits_time != 0.0f)\r\n\t{\r\n\t\tcrouched_friction = m_override_air_friction;\r\n\t\tstanding_friction = m_override_air_friction;\r\n\t}\r\n\t\t  \r\n\tif (GetFlag(TENSE))\r\n\t{\r\n\t\tapply_wind_resistance(crouched_friction);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tapply_wind_resistance(standing_friction);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\r\nvoid CSkaterCorePhysicsComponent::handle_rolling_resistance (   )\r\n{\t\r\n\t// Only have rolling resistance if we are not going slow on a steep slope.\t\r\n\tif (!slide_off_slow_steep_slope())\r\n\t{\r\n\t\tapply_rolling_friction();\r\n\t}\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::slide_off_slow_steep_slope (   )\r\n{\r\n\t// If we are on very steep ground and moving slowly then do not allow the skater to brake\r\n\tif (on_steep_slow_slope())\r\n\t{\r\n\t\tfloat speed = GetVel().Length();\r\n\t\t\r\n\t\tMth::Vector forward;\r\n\t\tif (speed < 0.001f)\r\n\t\t{\r\n\t\t\tforward = GetMatrix()[Z];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tforward = GetVel();\r\n\t\t\t\r\n\t\t}\r\n\t\t\r\n\t\tMth::Vector fall(0.0f, -1.0f, 0.0f);\r\n\t\tfall.ProjectToPlane(m_current_normal);\t  \r\n\t\t\r\n\t\tfloat angle = Mth::GetAngleAbout(forward, fall, GetMatrix()[Y]);\r\n\t\tfloat rot = GetPhysicsFloat(CRCD(0x7dd5678b, \"Skater_Slow_Turn_on_slopes\")) * Mth::Sgn(angle) * m_frame_length;\r\n\t\tif (Mth::Abs(rot) > Mth::Abs(angle))\r\n\t\t{\r\n\t\t\t// just about done, so just turn the last bit of angle left\r\n\t\t\trot = angle;\r\n\t\t}\r\n\t\tGetMatrix().RotateYLocal(rot);\t\t\t\t\r\n\t\tm_lerping_display_matrix.RotateYLocal(rot);\t\t\t\t\r\n\t\t\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::apply_rolling_friction (   )\r\n{\r\n\t// apply a constant braking friction; if the velocity reaches 0, then we will stop (and not change direction)  \t\t\r\n\t// This funtion will typically be used for rolling resistance\r\n\t\r\n\t// rolling friction is a constant, and is mostly noticable at slow speeds\r\n\t// if your speed is less than that produced by the force of rolling friction, then you will abruptly stop\r\n\tMth::Vector rolling_friction = GetVel();\r\n\tfloat length = rolling_friction.Length();\r\n\t\r\n\tif (length < 0.0001f)\r\n\t{\r\n\t\tGetVel().Set();\r\n\t\tDUMP_VELOCITY;\r\n\t\treturn;\r\n\t}\r\n\t\r\n\trolling_friction *= 60.0f * m_rolling_friction * m_frame_length / length;\r\n\t\r\n\tif (rolling_friction.LengthSqr() > length * length)\r\n\t{\r\n\t\tGetVel().Set();\r\n\t\tDUMP_VELOCITY;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGetVel() -= rolling_friction;\r\n\t\tDUMP_VELOCITY;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\r\nvoid CSkaterCorePhysicsComponent::push_away_from_walls (   )\r\n{\r\n\tif (!m_wall_push_radius || !m_wall_push_speed) return;\r\n\t\r\n\tm_wall_push.Set();\r\n\tm_wall_dist = 1.0f;\r\n\t\r\n\tMth::Vector\tstart, end;\r\n\t\r\n\tstart = GetPos() + GetMatrix()[Y] * GetPhysicsFloat(CRCD(0xb45b39e2, \"Skater_side_collide_height\"));\r\n\t\r\n\tend = start + GetMatrix()[X] * m_wall_push_radius;\r\n\tcheck_for_wall_push(start, end, 0);\r\n\t\r\n\tend = start - GetMatrix()[X] * m_wall_push_radius;\r\n\tcheck_for_wall_push(start, end, 1);\r\n\t\r\n\tend = start + GetMatrix()[Z] * m_wall_push_radius;\r\n\tcheck_for_wall_push(start, end, 2);\r\n\t\r\n\tend = start - GetMatrix()[Z] * m_wall_push_radius;\r\n\tcheck_for_wall_push(start, end, 3);\r\n\r\n\tif (m_wall_dist == 1.0f) return;\r\n\t\r\n\tfloat push_speed = m_wall_push_speed * (1.0f - m_wall_dist);\r\n\tm_wall_push.Normalize(push_speed);\r\n\tGetVel() += m_wall_push;\r\n\tGetVel().RotateToPlane(m_current_normal);\r\n\tDUMP_VELOCITY;\r\n\t\r\n\t// if facing into the wall, then rotate away from it\r\n\tif (Mth::DotProduct(GetMatrix()[Z], m_feeler.GetNormal()) < 0.0f)\r\n\t{\r\n\t\tMth::Vector target = GetMatrix()[Z];\r\n\t\ttarget.RotateToPlane(m_feeler.GetNormal());\r\n\t\tfloat angle = Mth::GetAngleAbout(GetMatrix()[Z], target, GetMatrix()[Y]);\r\n\t\t\r\n\t\tfloat rot = m_wall_rotate_speed * Mth::Sgn(angle) * m_frame_length;\r\n\t\tif (Mth::Abs(rot) > Mth::Abs(angle))\r\n\t\t{\r\n\t\t\t// just about done, so just turn the last bit of angle left\r\n\t\t\trot = angle;\r\n\t\t}\r\n\t\tGetMatrix().RotateYLocal(rot);\t\t\t\t\r\n\t\tm_lerping_display_matrix.RotateYLocal(rot);\t   \r\n\t} \t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::check_for_wall_push ( const Mth::Vector& start, const Mth::Vector& end, int index )\r\n{\r\n\t// do not allow a push in this direction until a push in any other direction has NOT happenend for half a second\r\n\t// this should prevent the nasty flickering\r\n\tfor (int i = 0; i < 4; i++)\r\n\t{\r\n\t\tif (i == index) continue;\r\n\t\t\r\n\t\t// get time for opposite direction\r\n\t\tTmr::Time t = Tmr::ElapsedTime(m_push_time[index ^ 1]);\r\n\t\t\r\n\t\tif (t > 500)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tm_col_start = start;\r\n\tm_col_end = end;\r\n\t\r\n\tif (get_member_feeler_collision())\r\n\t{\r\n\t\tm_wall_push += m_feeler.GetNormal();\r\n\t\tif (m_feeler.GetDist() < m_wall_dist)\r\n\t\t{\r\n\t\t\tm_wall_dist = m_feeler.GetDist();\r\n\t\t}\r\n\t\tm_push_time[index] = Tmr::GetTime();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::move_to_skitch_point (   )\t\t\t\t\t\t\r\n{\r\n\t\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\r\n\tif (!mp_movable_contact_component->GetContact() || !mp_movable_contact_component->GetContact()->GetObject())\r\n\t{\r\n\t\tFLAGEXCEPTION(CRCD(0x47d44b84, \"OffMeterBottom\"));\r\n\t\treturn;\r\n\t}\r\n\r\n\tCCompositeObject* p_skitch_object = mp_movable_contact_component->GetContact()->GetObject();\r\n\t\r\n\tCSkitchComponent* p_skitch_comp = GetSkitchComponentFromObject(p_skitch_object);\r\n\tDbg_Assert(p_skitch_comp);\r\n\t\r\n\t////////////////////////////////////////////////////////\r\n\t// Do moving between the skitch nodes\r\n\t// if L1 or R1 pressed\r\n\t// Basically we just look for nodes to the left or right of us at a\r\n\t// one foot interval\r\n\t// up a a maximum of 10 feet\r\n\t// if one is found, then switch the m_node_index to that node \r\n\r\n\tfloat dir = 0.0f;\t   \r\n\t   \r\n\tif (control_pad.m_L1.GetTriggered())\r\n\t{\t\t\r\n\t\tcontrol_pad.m_L1.ClearTrigger();\r\n\t\tdir = 1.0f;\r\n\t}\t\r\n\r\n\tif (control_pad.m_R1.GetTriggered())\r\n\t{\t\t\r\n\t\tcontrol_pad.m_R1.ClearTrigger();\r\n\t\tdir = -1.0f;\r\n\t}\t\r\n\r\n\tif (control_pad.m_L2.GetTriggered())\r\n\t{\t\t\r\n\t\tcontrol_pad.m_L2.ClearTrigger();\r\n\t\tdir = 1.0f;\r\n\t}\t\r\n\r\n\tif (control_pad.m_R2.GetTriggered())\r\n\t{\t\t\r\n\t\tcontrol_pad.m_R2.ClearTrigger();\r\n\t\tdir = -1.0f;\r\n\t}\t\r\n\r\n\t// if moving, and either was not moving or moving in opposite direction, then we can actually try looking for a node\r\n\tif (dir != 0.0f && (!m_moving_to_skitch || dir != m_skitch_dir))\r\n\t{\r\n\t\tfloat len = 6.0f;\r\n\t\tfloat step = 6.0f;\r\n\t\tfloat max = 12.0f * 10.0f;\r\n\t\twhile (len < max)\r\n\t\t{\r\n\t\t\t// get an offset to the right or left\r\n\t\t\tMth::Vector offset = GetMatrix()[X];  // X points left, from the camera's POV\t\t\t\r\n\t\t\toffset *= len * dir;\r\n\t\t\tMth::Vector\ttest_pos = GetPos() + offset;\r\n\t\r\n\t\t\t// see if there is a skitch point there\r\n\t\t\tMth::Vector dummy(0.0f, 0.0f, 0.0f);\r\n\t\t\tint index = p_skitch_comp->GetNearestSkitchPoint(&dummy, test_pos);\r\n\t\r\n\t\t\t// if there is, then switch to that point\r\n\t\t\tif (index != m_skitch_index)\r\n\t\t\t{\r\n\t\t\t\tm_skitch_index = index;\r\n\t\t\t\tm_moving_to_skitch = true;\r\n\t\t\t\tm_skitch_dir = dir;\r\n\t\t\t\t\r\n\t\t\t\tif (dir == 1.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\tFLAGEXCEPTION(CRCD(0x74bf80cf, \"SkitchLeft\"));\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tFLAGEXCEPTION(CRCD(0x2e7474b5, \"SkitchRight\"));\r\n\t\t\t\t}\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\r\n\t\t\tlen += step;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// \r\n\t// end of moving between skitch nodes\r\n\t///////////////////////////////////////////////////\r\n\t\r\n\tif (!mp_movable_contact_component->GetContact() || !GetFlag(SKITCHING)) return;\r\n\r\n\t///////////////////////////////////////////////////////\r\n\t// Do the actual movement\r\n\r\n\tMth::Vector skitch_point;\r\n\tif (!p_skitch_comp->GetIndexedSkitchPoint( &skitch_point, m_skitch_index)) return;\r\n\r\n\t// zero out W component to prevent overflows (in theory this should not be necessary)\r\n\tGetPos()[W] = 0.0f;\r\n\r\n\tMth::Vector target = skitch_point + GetPhysicsFloat(CRCD(0x21fb182c, \"skitch_offset\")) * -p_skitch_object->GetMatrix()[Z];\r\n\r\n\tif (m_moving_to_skitch)\r\n\t{\r\n\t\tMth::Vector con_move = mp_movable_contact_component->GetContact()->GetMovement();\r\n\r\n\t\tGetPos() += con_move;\r\n\t\tDUMP_POSITION;\r\n\r\n\t\tMth::Vector dir = target - GetPos();\r\n\t\tfloat dir_length_sqr = dir.LengthSqr();\r\n\t\tfloat suck_speed = GetPhysicsFloat(CRCD(0x97496256, \"skitch_suck_speed\")) * m_frame_length;\r\n\r\n\t\t// if skater is stuck in a wall, then end the skitch when car is fifteen feet away \t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\tif (dir_length_sqr > FEET(15.0f) * FEET(15.0f))\r\n\t\t{\r\n\t\t\tFLAGEXCEPTION(CRCD(0x47d44b84, \"OffMeterBottom\"));\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (dir_length_sqr <= suck_speed * suck_speed)\r\n\t\t{\r\n\t\t\t// we have arrived, so no need for sucking later\r\n\t\t\tGetPos() = target;\r\n\t\t\tm_moving_to_skitch = false;\r\n\t\t\tDUMP_POSITION;\r\n\t\t}\t\t\t\t\t\t\t   \r\n\t\telse\r\n\t\t{\r\n\t\t\tdir *= suck_speed / sqrtf(dir_length_sqr);\r\n\t\t\tGetPos() += dir;\r\n\t\t\tDUMP_POSITION;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t\tGetPos() = target;\r\n\t\t\tDUMP_POSITION;\r\n\t}\r\n\t\r\n\t// Copy the objects Display matrix over the skater's\r\n\t// will orient the skater the same way as the thing that is dragging it, so if the car looks solid, then so should the skater...\r\n\tGetMatrix() = p_skitch_object->GetDisplayMatrix();\r\n\t\r\n\t// we also set the display matrix, to avoid little glitches\r\n\tResetLerpingMatrix();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n     \r\nvoid CSkaterCorePhysicsComponent::handle_forward_collision (   )\r\n{\r\n\tif (GetPos() == GetOldPos()) return;\r\n\t\r\n\tMth::Vector\tforward = GetPos() - GetOldPos();\r\n\tforward.Normalize();\t\r\n\t\r\n\tMth::Vector up_offset = GetMatrix()[Y] * GetPhysicsFloat(CRCD(0xd4205c9b, \"Skater_First_Forward_Collision_Height\"));\r\n\t\r\n\tm_col_start = GetOldPos() + up_offset;\r\n\t\r\n\tm_col_end = GetPos() + up_offset + forward * GetPhysicsFloat(CRCD(0x20102726, \"Skater_First_Forward_Collision_Length\"));\r\n\r\n\tif (!get_member_feeler_collision()) return;\r\n\t\r\n\t// we have hit something going forward\r\n\t// either it is a wall, and we need to bounce off it or it is a steep QP, and we need to stick to it.\r\n\t// (note, with the slow normal changing, then it is possible that we might even collide with the poly that we are on\r\n\t\r\n\tMth::Vector\tnormal = m_feeler.GetNormal();\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\tfloat dot = Mth::DotProduct(normal, m_current_normal);\t\t\t\r\n\r\n\t// For fairly shallow curves, the dot between two normals will be pretty large\r\n\t// it's very important here to distinguish between a tight curve (like in a narrow QP) and a direct hit with a wall.\r\n\t\t\t   \r\n\tif (!m_col_flag_skatable || Mth::Abs(dot) < 0.01f)\r\n\t{\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_BONK, m_feeler);\r\n\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\t\r\n\t\tbounce_off_wall(normal);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// it's a qp, stick to it\r\n\t\t\r\n\t\t// Just move our contact point to the point of collision.  This is not right, as it could kill a lot of the movement for this frame\r\n\t\t// but should do for now (and stops you falling through)\t\t\t\t\t\t\t\t\t\t\t\r\n\t\tGetPos() = m_feeler.GetPoint();\r\n\t\t\r\n\t\t// move it off the surface a little, so we are not IN it (which would be indeterminates as to which side)\r\n\t\tGetPos() += normal * 0.1f;\r\n\t\tDUMP_POSITION;\r\n\t}\r\n}\t\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::bounce_off_wall ( const Mth::Vector& normal )\r\n{\r\n\tif (check_for_wallpush()) return;\r\n\t\r\n\t// Given the normal of the wall, then bounce off it, turning the skater away from the wall\r\n\t\r\n\tMth::Vector\tforward = GetPos() - GetOldPos();\r\n\tMth::Vector movement = forward;\t\t\t\t   \t\t// remember how far we moved\r\n\tforward.Normalize();\r\n\t\r\n\tMth::Vector up_offset = GetMatrix()[Y] * GetPhysicsFloat(CRCD(0xd4205c9b,\"Skater_First_Forward_Collision_Height\"));\r\n\r\n\tfloat turn_angle;\r\n\tfloat angle = rotate_away_from_wall(normal, turn_angle);\r\n\r\n\tfloat min = Mth::DegToRad(GetPhysicsFloat(CRCD(0x1483fd01, \"Wall_Bounce_Dont_Slow_Angle\"))); \r\n\t\t\t\t\t \t\t\t\t\t\t\t\r\n\tif (Mth::Abs(angle) > min)\r\n\t{\r\n\t\tfloat old_speed = GetVel().Length();\r\n\t\t\r\n\t\t// The maximum value of Abs(angle) would be PI/2 (90 degrees), so scale the velocity \r\n\t\tfloat x = Mth::Abs(angle) - min;\r\n\t\tx /= (Mth::PI / 2.0f) - min;\t\t// get in the range 0 .. 1\r\n\t\tx = 1.0f - x; \t\t\t\t\t\t// invert, as we want to stop when angle is 90\r\n\t\t\r\n\t\tGetVel() *= x;\r\n\t\tDUMP_VELOCITY;\r\n\r\n\t\t// if (negative ^ flipped) then backwards flail, otherwise forward flail\t\r\n\r\n\t\tif (old_speed > GetPhysicsFloat(CRCD(0xbe0a58a0, \"Wall_Bounce_Dont_Flail_Speed\")))\r\n\t\t{\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\t{\r\n\t\t\t\tMth::Vector\tup_offset = GetMatrix()[Y] * GetPhysicsFloat(CRCD(0xd4205c9b,\"Skater_First_Forward_Collision_Height\"));\r\n\t\t\t\tMth::Vector start = up_offset+GetOldPos();\r\n\t\t\t\tMth::Vector end = up_offset+GetPos();\r\n\t\t\t\tTrackingLine(1, start, end);\t  // 1 = wall bounce flail\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tif ((angle < 0.0f) ^ (GetFlag(FLIPPED)))\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\t\t\t{\r\n\t\t\t\tFLAGEXCEPTION(CRCD(0xb4101d70,\"FlailLeft\"));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tFLAGEXCEPTION(CRCD(0x756a7535,\"FlailRight\"));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Player's terrain isn't set to the terrain in m_feeler, as this is a wall we're bouncing off of (or chain link fence or something)...\r\n\t\t\t// Steve: we gots ta figure out how to do this...\r\n\t\t\t// Perhaps have another terrain value sent to client skaters that tell them to play a bonk sound?\r\n\t\t\tmp_sound_component->PlayBonkSound( old_speed / GetSkater()->GetScriptedStat(CRCD(0xcc5f87aa, \"Skater_Max_Max_Speed_Stat\")), m_feeler.GetTerrain());\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Bit of a patch here to move the skater away from the wall\r\n\t// Not needed so much with new sideways collision checks but we keep it in for low ledges.\r\n\t// Should perhaps standardize the height so collision checks for side and front but we'd probably still have problems.\r\n\t\r\n\tGetPos() = m_feeler.GetPoint() - up_offset;\r\n\tGetPos() += normal * 6.0f;\r\n\tDUMP_POSITION;\r\n\t\r\n\t// Now the majority of cases have been taken care of; we need to see if the skater is going to get stuck in a corner.\r\n\r\n\tfloat old_speed = movement.Length();\t\t \t\t\t\t\t// get how much we moved last time\r\n\tMth::Vector next_movement = GetVel();\t\t\t\t\t// get new direction of velocity\r\n\tforward = GetVel();\r\n\tforward.Normalize();\r\n\tnext_movement = forward * old_speed;\t\t\t\t\t\t\t// extend by same movment as last time\r\n\t\r\n\tm_col_start = GetPos() + up_offset;\r\n\tm_col_start += up_offset;\r\n\t\r\n\tm_col_end = GetPos() + up_offset + next_movement\r\n\t\t+ forward * GetPhysicsFloat(CRCD(0x20102726, \"Skater_First_Forward_Collision_Length\"));\r\n\t\r\n\tif (get_member_feeler_collision() && GetSkater()->IsLocalClient())\r\n\t{\r\n\t\t// Just rotating the skater will lead to another collision, so try just inverting the skater's velocity from it's original and halving it....\r\n\t\t\r\n\t\t// First reverse the rotation, and rotate 180 degrees\r\n\t\tGetVel().RotateY(Mth::DegToRad(180.0f) - turn_angle);\r\n\t\tGetMatrix().RotateYLocal(Mth::DegToRad(180.0f) - turn_angle);\r\n\t\tResetLerpingMatrix();\r\n\t\t\r\n\t\tGetVel() *= 0.5f; \r\n\t\tDUMP_VELOCITY;\r\n\t\t\r\n\t\tif (old_speed > GetPhysicsFloat(CRCD(0xbe0a58a0, \"Wall_Bounce_Dont_Flail_Speed\")))\r\n\t\t{\r\n\t\t\tFLAGEXCEPTION(CRCD(0xb4101d70, \"FlailLeft\"));\r\n\t\t}\r\n\t}\r\n}\t\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::snap_to_ground (   )\r\n{\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\r\n\tfloat up_dot = 0.0f;\r\n\t\r\n\t// Since we really don't want to loose contact with the ground while skitching, we use a much bigger snap up dist\r\n\t// The problem will come when we get dragged down a slope.  The car will flatten out well ahead of us, so pushing us down through the slop\r\n\t// (as we are a few feet behind it) and we will be so far under the ground that our normal snap up will not be able to dig us out of it,\r\n\t// so we go in air, uberfrig, and get dragged to a random spot under the level.\r\n\t// (This would not happen if we just skitch on flat ground)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\r\n\t// Dan: snap_to_ground is never called while skitching\r\n\t// if (GetFlag(SKITCHING))\r\n\t// {\r\n\t\t// m_col_start = GetMatrix()[Y] * GetPhysicsFloat(CRCD(0x5c0d9610,\"Physics_Ground_Snap_Up_SKITCHING\"));\t// much above feet\r\n\t// }\r\n\t// else\r\n\t// {\r\n\t\tm_col_start = GetMatrix()[Y] * GetPhysicsFloat(CRCD(0xe4d79235, \"Physics_Ground_Snap_Up\"));\t  \t\t// bit above the feet\r\n\t// }\r\n\t\r\n\tm_col_end = GetMatrix()[Y] * -200.0f;\t\t    // WAY! below the feet, we check distance later\r\n\r\n\tm_col_start += GetPos();\r\n\tm_col_end += GetPos();\r\n\t\t \r\n\tbool sticking = false;\t\t\t\r\n\t// get disatnce to ground and snap the skater to it, but only if the ground is skatable, otherwise we just go to \"AIR\"\r\n\tif (get_member_feeler_collision())\r\n\t{\r\n\t\tMth::Vector movement = GetPos() - m_feeler.GetPoint(); \r\n\t\tfloat drop_dist = movement.Length();\r\n\t\tfloat drop_sign = Mth::DotProduct(GetMatrix()[Y], movement); // might be approx +/- 0.00001f\r\n\t\tif (!m_col_flag_skatable)\t\r\n\t\t{\r\n\t\t\t// if below the face (or very close to it), then push us away from it\t\t\t\t\r\n\t\t\tif (drop_sign < 0.001f)\r\n\t\t\t{\r\n\t\t\t\t// at point of contact, and move away from surface\r\n\t\t\t\tGetPos() = m_feeler.GetPoint() + m_feeler.GetNormal();\t\r\n\t\t\t\tDUMP_POSITION;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsticking = true;\r\n\t\t\t\r\n\t\t\t// Note the two ways of calculating the angle between two faces\r\n\t\t\t// the more \"accurate\" method simply takes angle between the two normals\r\n\t\t\t// however, this fails to account for the direction the skater is travelling\r\n\t\t\t// when in conjunction with the \"snap\" up.\r\n\t\t\t// If the skater approaches a slope from the side, then he can snap up to the slope\r\n\t\t\t// however, if the angle between the ground and the face to which we are snapping up to \r\n\t\t\t// is too great, then we transition to in-air\r\n\t\t\t// and will drop through the slope\r\n\t\t\t// the solution is to take the angle between the front vector rotated onto each face.\r\n\t\t\t\r\n\t\t\t// Firstly we check the angle between the two faces\t\r\n\t\t\tMth::Vector normal = m_feeler.GetNormal();\r\n\t\t\t\r\n\t\t\tMth::Vector\tforward = GetMatrix()[Z];\r\n\t\t\tfloat front_dot = Mth::DotProduct(forward,normal);\r\n\r\n\t\t\tMth::Vector\told_forward = forward;\r\n\t\t\tforward.RotateToPlane(normal);\r\n\t\t\told_forward.RotateToPlane(m_current_normal);\r\n\r\n\t\t\t// angle between front vectors, projected onto faces\r\n\t\t\tup_dot = Mth::DotProduct(forward, old_forward);\r\n\t\t\t\r\n\t\t\tfloat stick_angle_cosine;\r\n\t\t\tif (!control_pad.m_up.GetPressed())\r\n\t\t\t{\r\n\t\t\t\tstick_angle_cosine = cosf(Mth::DegToRad(GetPhysicsFloat(CRCD(0xef161c2a, \"Ground_stick_angle\"))));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tstick_angle_cosine = cosf(Mth::DegToRad(GetPhysicsFloat(CRCD(0x4138283e, \"Ground_stick_angle_forward\"))));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (front_dot > 0.0f  && up_dot > 0.0f && up_dot < stick_angle_cosine)\r\n\t\t\t{\r\n\t\t\t\tsticking = false;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// only need to test if snap is downwards\r\n\t\t\t\tif (drop_sign > 0.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\t// angle between the old plane and the new plane is either the same, or withing the set limits\r\n\t\t\t\t\t// (like, < 60 degrees, or so, see physics.q) now calculate the drop distance, based on the angle\r\n\t\t\t\t\t\r\n#ifdef __PLAT_NGC__\r\n\t\t\t\t\tfloat angle = acosf(Mth::Clamp(up_dot, -1.0f, 1.0f));\r\n#else\r\n\t\t\t\t\tfloat angle = acosf(up_dot);\r\n#endif // __PLAT_NGC__\r\n\r\n\t\t\t\t\tMth::Vector\tlast_move = GetPos() - GetOldPos();\r\n\t\t\t\t\t\r\n\t\t\t\t\tfloat max_drop = last_move.Length() * tanf(angle);\r\n\t\t\t\t\t\r\n\t\t\t\t\tfloat min_drop = GetPhysicsFloat(CRCD(0x899ba3d0, \"Physics_Ground_Snap_Down\"));\t\t\t\t\r\n                    // if (GetFlag(SKITCHING))\r\n\t\t\t\t\t// {\r\n\t\t\t\t\t\t// min_drop = GetPhysicsFloat(CRCD(0x20df7e33, \"Physics_Ground_Snap_Down_Skitching\"));\t\t\t\t\r\n\t\t\t\t\t// }\r\n\r\n\t\t\t\t\tif (max_drop < min_drop)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmax_drop = min_drop;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (drop_dist > max_drop)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsticking = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (sticking)\r\n\t\t\t\t{\t\t  \r\n\t\t\t\t\tSetFlag(LAST_POLY_WAS_VERT, m_col_flag_vert);\r\n\t\t\t\t\tnew_normal(normal);\r\n\t\t\t\t}\t\t \r\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\t}\r\n\t\t\t\t\t\r\n\t\tif (sticking)\r\n\t\t{\t\r\n\t\t\t// if there is a collision, then snap to it\r\n\t\t\tGetPos() = m_feeler.GetPoint();\r\n\t\t\tDUMP_POSITION;\r\n\t\t\t\r\n\t\t\tif (GetState() == GROUND && movement.Length() > 2.0f)\r\n\t\t\t{\r\n\t\t\t\t// curbs are assumed to be between parallel surfaces, so check this...\r\n\t\t\t\tif (up_dot > 0.99f)\r\n\t\t\t\t{\r\n\t\t\t\t\tSetFlag(SNAPPED_OVER_CURB, true);\r\n\t\t\t\t}\t\t\t\t\r\n\t\t\t}\r\n\r\n\t\t\t// will return trivially if terrain is already set to this type...\r\n\t\t\tset_terrain(m_feeler.GetTerrain());\r\n\t\t\t\r\n\t\t\tadjust_normal();\r\n\r\n\t\t\t// check to see if we have skated onto a movable object\r\n\t\t\tcheck_movable_contact();\r\n\r\n\t\t\t// still on ground, so store the latest ground collision data\r\n\t\t\t// check first to see if we are about to change\r\n\t\t\tif (m_last_ground_feeler.GetSector() != m_feeler.GetSector())\r\n\t\t\t{\r\n\t\t\t\t// changin sectors, so check the sector we came from and the one we are going to\r\n\t\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_OFF, m_last_ground_feeler);\r\n\t\t\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\t\t\t\r\n\t\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_ONTO, m_feeler);\r\n\t\t\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\t\t}\r\n\r\n\t\t\tif (!mp_trick_component->GraffitiTrickStarted())\r\n\t\t\t{\r\n\t\t\t\t// clear the graffiti trick buffer if we're moving to a new world sector, but haven't started our trick yet...\r\n\t\t\t\tmp_trick_component->SetGraffitiTrickStarted(false);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tset_last_ground_feeler(m_feeler);\r\n\t\t}\r\n\t}\r\n\t\r\n\t// skated off surface into the air\r\n\tif (!sticking)\r\n\t{\r\n\t\tSetState(AIR);\r\n\t\tGetObject()->BroadcastEvent(CRCD(0xd96f01f1, \"SkaterOffEdge\"));\r\n\t\tFLAGEXCEPTION(CRCD(0x3b1001b6, \"GroundGone\"));\r\n\t\t\r\n\t\tmaybe_straight_up();\r\n\t\t\r\n\t\tif (GetFlag(VERT_AIR))\r\n\t\t{\r\n\t\t\tSetFlagTrue(CAN_BREAK_VERT);\r\n\r\n\t\t\t// we want to break vert, but don't want to go into spine physics for a frame\r\n\t\t\t// so don't do this check if we are trying to break the spine\r\n\t\t\t// (we can still break vert or spine on the next frame, when in the air)\r\n \t\t\tif (!BREAK_SPINE_BUTTONS)\r\n\t\t\t{\r\n\t\t\t\tmaybe_break_vert();\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// if we did not break vert now\r\n\t\t\t// then only allow us to break vert later if we've been tapping the \"up\" button\r\n\t\t\t// this is indicated by us having RELEASED or Pressed in teh last few ticks\r\n\t\t\tif (static_cast< int >(control_pad.m_up.GetReleasedTime()) > GetPhysicsInt(CRCD(0x6bb5b751, \"Skater_vert_active_up_time\"))\r\n\t\t\t\t&& static_cast< int >(control_pad.m_up.GetPressedTime()) > GetPhysicsInt(CRCD(0x6bb5b751, \"Skater_vert_active_up_time\")))\t\t\t\r\n\t\t\t{\r\n\t\t\t\t// \"UP\" was not pressed any time recently, so don't let us break late\r\n\t\t\t\tSetFlagFalse(CAN_BREAK_VERT);\t\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if (BREAK_SPINE_BUTTONS)\r\n\t\t{\r\n\t\t\tSAcidDropData acid_drop_data;\r\n\t\t\tif (maybe_acid_drop(true, GetPos(), GetOldPos(), GetVel(), acid_drop_data))\r\n\t\t\t{\r\n\t\t\t\tenter_acid_drop(acid_drop_data);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_OFF_EDGE, m_last_ground_feeler);\r\n\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t}\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::new_normal ( Mth::Vector normal )\r\n{\r\n\tif (Ed::CParkEditor::Instance()->UsingCustomPark())\r\n\t{\r\n\t\t// check if this new normal will make us lean into a wall\r\n\t\tif (normal[Y] > 0.0f)\r\n\t\t{\r\n\t\t\tCFeeler\tfeeler(GetPos(), GetPos() + 72.0f * normal);\r\n\t\t\tif (feeler.GetCollision())\r\n\t\t\t{\r\n\t\t\t\tnormal.Set(0.0f,1.0f,0.0f);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (normal != m_current_normal)\r\n\t{\r\n\t\tm_current_normal = normal;\t  \t\t\t\t\t\t\t\t\t\t// remember this, for detecting if it changes\r\n\t\tm_last_display_normal = m_display_normal;\t\t\t\t// remember start position for lerping\t\r\n\t\tm_normal_lerp = 1.0f;\t\t\t\t\t\t\t\t\t\t\t\t// set lerp counter\r\n\t\t\r\n\t\tGetMatrix()[Y] = normal;\r\n\t\tGetMatrix().OrthoNormalizeAbout(Y);\t\t\t\t\t\t\t\t\t// set regular normal immediately\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::adjust_normal (   )\r\n{\r\n\t///////////////////////////////////////////////////////////////////////////////\r\n\t///////////////////////////////////////////////////////////////////////////////\r\n\t//\r\n\t// As the skater moves over the ground, he will go from being in contact\r\n\t// with one polygon, to another.\r\n\t// The \"normal\" of a polygon is the vector perpendicular to the surface of\r\n\t// the polygon, and the skater is normally aligned so that the \"up\" vector\r\n\t// of the skater (the Y component of the orientation matrix) is the same\r\n\t// as the normal or the polgon he is in contact with.\r\n\t//\r\n\t// However, as we go from one polygon to another (in a quarterpipe, for example)\r\n\t// the normal will change abruptly, and this looks very jerky\r\n\t// So, we try to smooth this out by remembering the old normal, and interpolating \r\n\t// towards the current display normal\r\n\t// this is done at a fixed speed, controled by the script value \"Normal_Lerp_Speed\" \r\n\t// whihc is defined in phsyics.q\r\n\t//\r\n\t// m_normal_lerp represents how far off the current face normal we are, it\r\n\t// will vary from 1.0 (still at the last display normal) to 0.0 (at current normal)\r\n\t// the intermediate normal is stored in m_display_normal\r\n\t// and is also copied directly into m_lerping_display_matrix, to rotate the skater \r\n\r\n\t// if m_normal_lerp is 0.0, then we don't need to do anything, as we should already be there\r\n\tif (m_normal_lerp != 0.0f)\t   \t\t// if lerping\r\n\t{\t\t\t\r\n\t\t// If the last display normal is the same as the current normal, then we can't interpolate between them\r\n\t\tif (m_last_display_normal == m_current_normal)\r\n\t\t{\r\n\t\t\tm_normal_lerp = 0.0f;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// adjust lerp at constant speed from 1.0 to 0.0, accounting for framerate\r\n\t\t\tm_normal_lerp -= GetPhysicsFloat(CRCD(0xd8120182, \"Normal_Lerp_Speed\")) * m_frame_length * 60.0f;\r\n\t\r\n\t\t\t// if gone all the way, then clear lerping values and set m_display_normal to be the current face normal\r\n\t\t\tif (m_normal_lerp <= 0.0f)\r\n\t\t\t{\r\n\t\t\t\tm_normal_lerp = 0.0f;\r\n\t\t\t\tm_display_normal = m_current_normal;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Still between old and current normal, so calculate intermediate normal\r\n\t\t\t\tm_display_normal = Mth::Lerp(m_current_normal, m_last_display_normal, m_normal_lerp);\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\tm_display_normal.Normalize();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Now update the orientation matrix.\r\n\t// We need our up (Y) vector to be this vector\r\n\t// if it changes, rotate the X and Z vectors to match\r\n\tif (m_lerping_display_matrix[Y] != m_display_normal)\r\n\t{\r\n\t\t// lerp the y axis\r\n\t\tm_lerping_display_matrix[Y] = m_display_normal;\r\n\t\tm_lerping_display_matrix.OrthoNormalizeAbout(Y);\t\r\n\t\tm_lerping_display_matrix[X] = GetMatrix()[X];\r\n\t\tm_lerping_display_matrix[Z] = GetMatrix()[Z];\t\t\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::check_movable_contact (   )\r\n{\r\n\t// given m_feeler is our current contact point with the ground, then check if our mp_movable_contact_component->GetContact() information needs updating\t\t\t\t\r\n\t\r\n\tif (GetFlag(SKITCHING)) return;\r\n\t\r\n\tif (mp_movable_contact_component->CheckForMovableContact(m_feeler))\r\n\t{\r\n\t\tGetVel() -= mp_movable_contact_component->GetContact()->GetObject()->GetVel();\r\n\t\tDUMP_VELOCITY;\r\n\t}\r\n}\t\t\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::maybe_straight_up (   )\r\n{\t\t\t\r\n\t// Skater has just left gound, either jumped, or skated off it\r\n\t// so we need to check if the ground we left was flagged as VERT and if it is,\r\n\t// then we need to set our skater's velocity and orientation so they go straight up\r\n\t\r\n\tif (GetFlag(LAST_POLY_WAS_VERT))\t\r\n\t{\r\n\t\tTrackingLine(3, GetOldPos(), GetPos());\t  // 3 = going vert\r\n\t\t\r\n\t\t// Get the normal to the plane we jumped from\r\n\t\tMth::Vector\tup_plane_normal = m_current_normal;\r\n\r\n\t\tm_vert_normal = m_current_normal;\r\n\t\tm_vert_pos = GetOldPos();\r\n\t\t\r\n\t\t// move vert pos down one inch to better track subtle changes in edge height\r\n\t\tm_vert_pos[Y] -= 1.0f;\r\n\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t// clear any Y component to this plane, makes it vertical\r\n\t\tup_plane_normal[Y] = 0.0f;\r\n\t\t\r\n\t\tif (up_plane_normal.Length() > 0.001f)\r\n\t\t{\r\n\t\t\t// and re-normalize to get a unit normal to the vertical plane.\r\n\t\t\tup_plane_normal.Normalize();\r\n\t\t\t\r\n\t\t\tGetVel().RotateToPlane(up_plane_normal);\r\n\t\t\tDUMP_VELOCITY;\r\n\t\r\n\t\t\tnew_normal(up_plane_normal);\r\n\t\t\t\r\n\t\t\t// Fall line is used for auto turn\r\n\t\t\tm_fall_line = GetMatrix()[Z];\r\n\t\t\tm_fall_line[Y] = -m_fall_line[Y];\r\n\t\t\t\t\r\n\t\t\t// offset the jumper away from the plane by an inch\r\n\t\t\tGetPos() += up_plane_normal * GetPhysicsFloat(CRCD(0x78384871, \"Physics_Vert_Push_Out\"));\r\n\t\t\tDUMP_POSITION;\r\n\t\t\t\r\n\t\t\tSetFlagTrue(VERT_AIR);\r\n\t\t\tSetFlagTrue(TRACKING_VERT);\r\n\t\t\tSetFlagTrue(AUTOTURN);\r\n\t\t\tm_vert_upstep = 6.0f;\t\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tSetFlagFalse(VERT_AIR);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSetFlagFalse(VERT_AIR);\r\n\t}\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::maybe_break_vert (   )\r\n{\r\n\t// We \"Break Vert\" when we are pressing forward at the start of transitioning from the ground into a \"vert\" state\r\n\t// however, we need to defer the test until there is no ground in that \"forward\" direction (which will be directly beneath the skater's feet)\r\n\t\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\r\n\tif (\r\n\t\t(\t\r\n\t\t\tcontrol_pad.m_up.GetPressed() \r\n\t\t\t&& static_cast< int >(control_pad.m_up.GetPressedTime()) > GetPhysicsInt(CRCD(0x9d2f8cc8, \"Skater_vert_push_time\"))\r\n\t\t\t&& !control_pad.m_left.GetPressed()\t\t// must be JUST up, to avoid accidents when turning\r\n\t\t\t&& !control_pad.m_right.GetPressed()\r\n\t\t\t&& !control_pad.m_square.GetPressed()\t// and don't break if trying to do a trick involving up\r\n\t\t\t&& !control_pad.m_circle.GetPressed()\r\n\t\t)\r\n\t\t||\r\n\t\t(\r\n\t\t\tBREAK_SPINE_BUTTONS\r\n\t\t)\r\n\t)\r\n\t{\r\n\t\t// aha... up is pressed, so we want to break the air poly\r\n\r\n\t\tif (!BREAK_SPINE_BUTTONS)\r\n\t\t{\r\n\t\t\t// normal breaking the air polygon, we just fly forward\r\n\t\t\t\r\n\t\t\tfloat speed = GetVel().Length() * GetPhysicsFloat(CRCD(0x13f33b41, \"physics_break_air_speed_scale\"));\r\n\t\t\t\r\n\t\t\tGetVel()[X] += -m_display_normal[X] * speed;\r\n\t\t\tGetVel()[Z] += -m_display_normal[Z] * speed;\r\n\t\t\tGetVel()[Y] *= GetPhysicsFloat(CRCD(0x848c5cd6, \"physics_break_air_up_scale\"));\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t\t\r\n\t\t\t// Now, since we broke the vert poly, the way it was set up, the skater will have alrready been snapped to vertical position\r\n\t\t\t// so we need to rotate him forwads 45 degrees to componsate\r\n\t\t\tGetMatrix().RotateXLocal(Mth::DegToRad(GetPhysicsFloat(CRCD(0xd757f4bb, \"Skater_Break_Vert_forward_tilt\"))));\t\t\t\t\r\n\r\n\t\t\tSetFlagFalse(VERT_AIR);\t   \t// just regular air, if we broke the air poly\r\n\t\t\tSetFlagFalse(TRACKING_VERT);\t// and certainly not tracking the vert\r\n\t\t\tSetFlagFalse(CAN_BREAK_VERT);\t// and as we broke vert, we don't want to do it again\r\n\t\t\tSetFlagFalse(AIR_ACID_DROP_DISALLOWED);\t// allow acid drops once once again\r\n\r\n\t\t\t// and we want to be going in the direction of our velocity, so set front x and Z, but leave Y\r\n\t\t\tMth::Vector vel_normal = GetVel();\r\n\t\t\tvel_normal.Normalize();\r\n\t\t\t\r\n\t\t\tGetMatrix()[Z][X] = vel_normal[X];\r\n\t\t\tGetMatrix()[Z][Z] = vel_normal[Z];\r\n\t\t\tGetMatrix()[Z].Normalize();\t\t\r\n\t\t\tGetMatrix().OrthoNormalizeAbout(Z); \r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (!maybe_spine_transfer())\r\n\t\t\t{\r\n\t\t\t\t// cannot find a transfer target, so just break the air polygon\r\n\t\t\t\tGetVel()[X] += -m_display_normal[X] * 24.0f;\r\n\t\t\t\tGetVel()[Z] += -m_display_normal[Z] * 24.0f;\r\n\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\tGetMatrix().RotateXLocal(Mth::DegToRad(GetPhysicsFloat(CRCD(0xd757f4bb, \"Skater_Break_Vert_forward_tilt\"))));\t\t\t\t\r\n\t\r\n\t\t\t\tSetFlagFalse(VERT_AIR);\t   \t// just regular air, if we broke the air poly\r\n\t\t\t\tSetFlagFalse(TRACKING_VERT);\t// and certainly not tracking the vert\r\n\t\t\t\tSetFlagFalse(CAN_BREAK_VERT);\t// and as we broke vert, we don't want to do it again\r\n\t\t\t\tSetFlagTrue(IN_RECOVERY);\t\t// tell him to just upright himself\r\n\t\t\t\t\r\n\t\t\t\t// and we want to be going in the direction of our velocity, so set front X and Z, but leave Y\r\n\t\t\t\tMth::Vector vel_normal = GetVel();\r\n\t\t\t\tvel_normal.Normalize();\r\n\t\t\t\t\r\n\t\t\t\tGetMatrix()[Z][X] = vel_normal[X];\r\n\t\t\t\tGetMatrix()[Z][Z] = vel_normal[Z];\r\n\t\t\t\tGetMatrix()[Z].Normalize();\t\t\r\n\t\t\t\tGetMatrix().OrthoNormalizeAbout(Z); \r\n\t\t\t\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tResetLerpingMatrix();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n                    \r\nbool CSkaterCorePhysicsComponent::maybe_spine_transfer (   )\r\n{\r\n\t// Break spin button is pressed, so try to break the spine\r\n\t\t\t\r\n\t// The line to check along is the skater's forward directinal vector, rotated onto the XZ plane\r\n\t// if you go straight up the wall, then this will be the same as the normal of the wall (in XY) as we previously calculated\r\n\t// however we also want to handle the cases where you approach the QP at an angle\r\n\t\r\n\t// Need to take the forward vector (Z) and rotate it \"forward\" 90 degrees\r\n\t// Rotate about an axis perpendicular to both the horizontal part of m_matrix[Y] and also the world up (0,1,0)\r\n\t\r\n\tMth::Vector skater_up = GetMatrix()[Y];\t// skater_up is expected to be horizontal here, as we are \"vert\"\r\n\tskater_up[Y] = 0.0f;\r\n\tskater_up.Normalize();\r\n\t\r\n\t// get a vector perpendicular to the plane containing m_matrix[Z] and the world up \t\r\n\t#if 0 // old code - crossing by axis alined\tvector bugs me\r\n\t// Mth::Vector world_up(0.0f, 1.0f, 0.0f);\r\n\t// Mth::Vector side = Mth::CrossProduct(skater_up, world_up);\r\n\t#else\r\n\tMth::Vector side(-skater_up[Z], 0.0f, skater_up[X], 0.0f);\r\n\t#endif\r\n\t\r\n\t// assuming we have not slowed down much, then our velocity should roughly be in the direction we took off from \r\n\tMth::Vector forward = -GetVel();\r\n\tforward.Normalize();\r\n\t\t\t\t\r\n\tMth::Vector wall_out = forward; \t\t\t\t\t\t\t// forward facing vector\r\n\twall_out.Rotate(side, Mth::PI / 2.0f);\t\t\t\t\t// rotate fowrad 90 degrees\r\n\t\r\n\tfloat speed;\r\n\tfloat dist = 12.0f;\r\n\tfloat time = 1.0f;\r\n\tbool hip_transfer = false;\t\t\t\t\t\t\t  \r\n\t\t\t  \r\n\tCFeeler feeler;\r\n\t\r\n\t// Here the \"wall\" is what we are currently skating on, anything with \"wall\" in the name refers to that\r\n\r\n\tMth::Vector target;\r\n\tMth::Vector target_normal;\r\n\tbool target_found = false;\t\t\t\r\n\r\n\t// First find a point beneath our current position\r\n\t// Nice long line, higher than we can posibly jump\r\n\tfeeler.m_start = GetPos() + wall_out * 0.5f;\r\n\tfeeler.m_end = GetPos() + wall_out * 0.5f;\r\n\tfeeler.m_end[Y] -= 4000.0f;\r\n\t\r\n\t// ignore everything that is NOT vert\r\n\t// feeler.SetIgnore(0, mFD_VERT);\r\n\t\r\n\tMth::Vector\twall_pos;\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\twall_pos = feeler.GetPoint();\r\n\r\n\t\tMth::Vector start_normal = feeler.GetNormal();\r\n\t\tstart_normal[Y] = 0.0f;\r\n\t\tstart_normal.Normalize();\r\n\t\t\r\n\t\ttarget_found = look_for_transfer_target(-wall_out, start_normal, hip_transfer, target, target_normal);\r\n\t\t\t\r\n\t\tif (!target_found)\r\n\t\t{\r\n\t\t\tMth::Vector left_along_vert(-start_normal[Z], 0.0f, start_normal[X]);\r\n\t\t\t\r\n\t\t\t// no target was found in the forward direction, perhaps we should look slightly left or right; look in the horizontal direction which is\r\n\t\t\t// halfway between the previous search direction and the plane of the vert\r\n\t\t\tif (mp_input_component->GetControlPad().m_left.GetPressed() && !mp_input_component->GetControlPad().m_right.GetPressed())\r\n\t\t\t{\r\n\t\t\t\tMth::Vector search_dir = left_along_vert + -wall_out;\r\n\t\t\t\tsearch_dir.Normalize();\r\n\t\t\t\ttarget_found = look_for_transfer_target(search_dir, start_normal, hip_transfer, target, target_normal);\r\n\t\t\t}\r\n\t\t\telse if (mp_input_component->GetControlPad().m_right.GetPressed() && !mp_input_component->GetControlPad().m_left.GetPressed())\r\n\t\t\t{\r\n\t\t\t\tMth::Vector search_dir = -left_along_vert + -wall_out;\r\n\t\t\t\tsearch_dir.Normalize();\r\n\t\t\t\ttarget_found = look_for_transfer_target(search_dir, start_normal, hip_transfer, target, target_normal);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (!target_found) return false;\r\n\t\r\n\tMth::Vector XZ_to_target = target - wall_pos;\r\n\tXZ_to_target[Y] = 0.0f;\r\n\tdist = XZ_to_target.Length();\r\n\t\r\n\t// We are only going to allow this later if the target point is the same level\r\n\t// as the takeoff point, and we have a clear line\r\n\t// so set it to this now, so we calculate the time correctly\r\n\ttarget[Y] = GetPos()[Y];\r\n\r\n\t// if the two faces are not really perpendicular or if the spine is wider than\r\n\t// then we determine that we are on a \"hip\" and we just want to go across it without drifting left or right\r\n\t// so we want to project all our velocity straight up\r\n\r\n\tMth::Vector\thorizontal_target_normal = target_normal;\r\n\thorizontal_target_normal[Y] = 0.0f;\r\n\thorizontal_target_normal.Normalize();\r\n\t\r\n\tMth::Vector cache_vel = GetVel();\r\n\t\r\n\tfloat face_dot = Mth::Abs(Mth::DotProduct(skater_up, horizontal_target_normal));\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tif (face_dot < 0.9f)\r\n\t{\r\n\t\tGetVel()[Y] = GetVel().Length();\r\n\t\tGetVel()[X] = 0.0f;\r\n\t\tGetVel()[Z] = 0.0f;\r\n\t\tDUMP_VELOCITY;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// if spine more than two feet wide, then also don't allow drift\r\n\t\tif (dist > FEET(2.0f))\r\n\t\t{\r\n\t\t\tGetVel()[Y] = GetVel().Length();\r\n\t\t\tGetVel()[X] = 0.0f;\r\n\t\t\tGetVel()[Z] = 0.0f;\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// one inch out, to ensure miss the lip\r\n\tdist += 1.0f;\r\n\r\n\t#if 0 // old transfer code\r\n\t// get angle to rotate about, being the vector perpendicular to the world up vector and the difference between the two face normals\r\n\t// (generally for a spine these normals will be opposite, however they might be up to 90 degrees or more off when doing a hip)\r\n\t\r\n\tMth::Vector normal_diff = target_normal - skater_up;\r\n\tnormal_diff[Y] = 0.0f;\r\n\tnormal_diff.Normalize();\r\n\t\r\n\tm_spine_rotate_axis[X] = -normal_diff[Z];\r\n\tm_spine_rotate_axis[Y] = 0.0f;\r\n\tm_spine_rotate_axis[Z] = normal_diff[X];\r\n\tm_spine_rotate_axis[W] = 0.0f;;\r\n\t#endif\r\n\t\r\n\t// for gravity calculations, temporarily pretend we are doing spine physics, so g is constant\r\n\tSetFlagTrue(SPINE_PHYSICS);\r\n\ttime = calculate_time_to_reach_height(target[Y], GetPos()[Y], GetVel()[Y]);\r\n\tSetFlagFalse(SPINE_PHYSICS);\r\n\r\n\t// subtract some frames of time, to ensure we make it\r\n\t// time -= m_frame_length * 2.0f;\r\n\t\r\n\tif (time < 0.1f)\r\n\t{\r\n\t\ttime = 0.1f;\r\n\t}\r\n\t\r\n\tspeed = dist / time;\r\n\t\r\n\t// if spine more than two foot wide, then make sure that we have enough speed to get over it\r\n\t// otherwise, just do a little pop over, and allow them to recover\t\t\t\t\t\t  \r\n\tif (dist > 24.0f && speed * speed > GetVel().LengthSqr())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// we have found a target point, either by looking directly in front or by doing the drop-down method\r\n\t// but we don't want to go for it until there is a clear line from our current position to the target\r\n\t\r\n\tMth::Vector\ttarget_XZ = target;\r\n\ttarget_XZ[Y] = GetPos()[Y];\r\n\t\r\n\tfeeler.m_start = GetPos();\r\n\tfeeler.m_end = target_XZ;\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t// don't do anything.  We have a valid transfer but we can wait until we get high enough before we try for it\r\n\t\treturn true;\r\n\t}\r\n\t\t\r\n\t// setup the transfer's matrix slerp\r\n\t\r\n\tMth::Vector land_facing;\r\n\tif (!hip_transfer)\r\n\t{\r\n\t\tland_facing = target - GetPos();\r\n\t\tland_facing[Y] = -(land_facing[X] * target_normal[X] + land_facing[Z] * target_normal[Z]) / target_normal[Y];\r\n\t\tland_facing.Normalize();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMth::Vector offset = target - GetPos();\r\n\t\toffset.Normalize();\r\n\t\tfloat dot = Mth::DotProduct(offset, horizontal_target_normal);\r\n\t\tif (dot < 0.0f)\r\n\t\t{\r\n\t\t\tland_facing.Set(0.0f, 1.0f, 0.0f);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tland_facing.Set(0.0f, -1.0f, 0.0f);\r\n\t\t}\r\n\t}\r\n\r\n\tMth::Matrix transfer_slerp_start = GetMatrix();\r\n\r\n\t// calculate the facing we want when we land; retain our horizontal direction and choose a vertical component which puts us parallel so the target\r\n\t// poly's plane\r\n\r\n\t// calculate goal matrix\r\n\tMth::Matrix transfer_slerp_goal;\r\n\ttransfer_slerp_goal[Z] = land_facing;\r\n\ttransfer_slerp_goal[Z].ProjectToPlane(target_normal);\r\n\ttransfer_slerp_goal[Z].Normalize();\r\n\ttransfer_slerp_goal[Y] = target_normal;\r\n\ttransfer_slerp_goal[X] = Mth::CrossProduct(transfer_slerp_goal[Y], transfer_slerp_goal[Z]);\r\n\ttransfer_slerp_goal[W].Set();\r\n\t\r\n\t// store the goal facing for use in adjusting the velocity at land time\r\n\tm_transfer_goal_facing = transfer_slerp_goal[Z];\r\n\r\n\t// if the skater is entering the spine transfer with an odd facing due to rotation, we want to preserve that angle in the slerp's goal matrix\r\n\r\n\t// calculate the deviation between the skater's velocity and facing\r\n\tfloat angle = Mth::GetAngleAbout(GetMatrix()[Z], cache_vel, GetMatrix()[Y]);\r\n\t\r\n\t// be a bit forgiving for hip transfers, as you often have to hit left/right to trigger them, which causes rotation\r\n\tif (Mth::Abs(angle) < Mth::DegToRad(30.0f))\r\n\t{\r\n\t\tangle = 0.0f;\r\n\t}\r\n\r\n\t// rotate goal facing to reflect the deviation in the initial facing\r\n\ttransfer_slerp_goal.RotateYLocal(-angle);\r\n\r\n\t// setup the slerp state\r\n\tm_transfer_slerper.setMatrices(&transfer_slerp_start, &transfer_slerp_goal);\r\n\tm_transfer_slerp_timer = 0.0f;\r\n\tm_transfer_slerp_duration = Mth::ClampMin(time, 0.9f); // clamp the time to stop super fast rotations\r\n\tm_transfer_slerp_previous_matrix = transfer_slerp_start;\r\n\t\r\n\t// insure that the slerp takes us over the top, and doesn't invert us\r\n\tMth::Matrix slerp_test;\r\n\tm_transfer_slerper.getMatrix(&slerp_test, 0.5f);\r\n\tif (slerp_test[Y][Y] < 0.0f)\r\n\t{\r\n\t\tm_transfer_slerper.invertDirection();\r\n\t}\r\n\t\r\n\t// remember the height we are aiming for, so when we come down through this height\r\n\t// then we remove the non vert velocity (or make it very small....)\r\n\tm_transfer_target_height = target[Y];\r\n\t\r\n\t// set velocity over the wall fast enough to land on the target point\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\tmp_state_component->m_spine_vel = (target - GetPos()) / time;\t\t// velocity from start to target\r\n\tmp_state_component->m_spine_vel[Y] = 0.0f;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// but ignore Y, as gravity handles that...\r\n\t\r\n\t// tell the code we are doing spine physics, so we lean quicker \r\n\tif (!hip_transfer)\r\n\t{\r\n\t\tGetObject()->SpawnAndRunScript(CRCD(0xa5179e9e, \"SkaterAwardTransfer\"));\t// award a trick (might want to do it as an exception later)\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGetObject()->SpawnAndRunScript(CRCD(0x283bb5d6, \"SkaterAwardHipTransfer\"));\t// award a trick (might want to do it as an exception later)\r\n\t}\r\n\t\r\n\t// no late jumps during a transfer\r\n\tGetObject()->RemoveEventHandler(CRCD(0x8ffefb28, \"Ollied\"));\r\n\t\r\n\tSetFlagTrue(SPINE_PHYSICS);\t// flag in spin physics, to do the lean forward, and also allow downcoming lip tricks\r\n\tSetFlagFalse(IN_ACID_DROP);\r\n\tSetFlagFalse(TRACKING_VERT);\t// we are still vert, but not tracking the vert\r\n\tSetFlagFalse(CAN_BREAK_VERT);\t// and as we \"broke\" vert, we don't want to do it again\r\n\t\r\n\treturn true;\r\n }\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n                    \r\nbool CSkaterCorePhysicsComponent::look_for_transfer_target ( const Mth::Vector& search_dir, const Mth::Vector& start_normal, bool& hip_transfer, Mth::Vector& target, Mth::Vector& target_normal )\r\n{\r\n\t// take a bunch of steps forward until we find one\t\t\r\n\t// This is not very good, as we have to do 80 collision checks....\r\n\t// we really need to optimize our collision detection to be able to select a set of \"nearby\" object\r\n\t// or to select a set that intersects a sphere, or a plane\r\n\t// (here, we could just get the set that intersects the plane)\r\n\t// this could be statically cached by the colision code, and have one set\r\n\t// or perhaps more flexibly, each \"feeler\" could have a set of objects\r\n\t// that it deals with (defaulting to the set of all objects)\r\n\t\r\n\tCFeeler feeler;\r\n\t\r\n\t// setup collision cache\r\n\tNx::CCollCache* p_coll_cache = Nx::CCollCacheManager::sCreateCollCache();\r\n\tMth::CBBox bbox;\r\n\tMth::Vector p;\r\n\tp = GetPos() + search_dir * 10.0f;\r\n\tbbox.AddPoint(p);\r\n\tp[Y] -= 4000.0f;\r\n\tbbox.AddPoint(p);\r\n\tp = GetPos() + search_dir * 500.0f;\r\n\tbbox.AddPoint(p);\r\n\tp[Y] -= 4000.0f;\r\n\tbbox.AddPoint(p);\r\n\tp_coll_cache->Update(bbox);\r\n\tfeeler.SetCache(p_coll_cache);\r\n\t\r\n\tfor (float step = 10.0f; step < 500.0f; step += 6.0f)\t\t\r\n\t{\r\n\t\t// First find a VERT point a bit in front of us\r\n\t\t// can be some distance below us \r\n\t\t// allowing us to transfer from high to low pools\r\n\t\t// (and low to high, proving you can jump up from the low point to the high point first)\r\n\t\tfeeler.m_start = GetPos() + search_dir * step;\t\t// start at current height\r\n\t\tfeeler.m_end = feeler.m_start;\r\n\t\tfeeler.m_end[Y] -= 4000.0f;\t\t\t\t\t\t\t\t\t// long way below\r\n\t\t\r\n\t\tif (feeler.GetCollision() && (feeler.GetFlags() & mFD_VERT) && is_vert_for_transfers(feeler.GetNormal()))\r\n\t\t{\r\n\t\t\tMth::Vector horizontal_normal = feeler.GetNormal();\r\n\t\t\thorizontal_normal[Y] = 0.0f;\r\n\t\t\thorizontal_normal.Normalize();\r\n\t\t\tfloat dot = Mth::DotProduct(start_normal, horizontal_normal);\r\n\t\t\tif (dot <= 0.95f)\r\n\t\t\t{\r\n\t\t\t\ttarget = feeler.GetPoint();\r\n\t\t\t\ttarget_normal = feeler.GetNormal();\r\n\t\t\t\t\r\n\t\t\t\thip_transfer = dot > -0.866f;\r\n\t\t\t\t\r\n\t\t\t\t// feeler.m_end[Y] += 3960.0f;\r\n\t\t\t\t// feeler.DebugLine(255, 100, 100, 0);\r\n\t\t\t\t\r\n\t\t\t\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\t\t\t\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// feeler.m_end[Y] += 3960.0f;\r\n\t\t\t\t// feeler.DebugLine(100, 255, 100, 0);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// feeler.m_end[Y] += 3960.0f;\r\n\t\t\t// feeler.DebugLine(100, 100, 255, 0);\r\n\t\t}\r\n\t}\r\n\t\r\n\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n                    \r\nbool CSkaterCorePhysicsComponent::maybe_acid_drop ( bool skated_off_edge, const Mth::Vector &pos, const Mth::Vector& old_pos, Mth::Vector& vel, SAcidDropData& acid_drop_data )\r\n{\r\n\t// horizontal direction in which a drop would occur\r\n\tMth::Vector drop_direction;\r\n\tif (mp_physics_control_component->IsSkating())\r\n\t{\r\n\t\tdrop_direction = vel;\r\n\t\tdrop_direction[Y] = 0.0f;\r\n\t\tfloat length = drop_direction.Length();\r\n\t\tif (length < 0.01f) return false;\r\n\t\tdrop_direction *= 1.0f / length;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tdrop_direction = mp_walk_component->m_facing;\r\n\t}\r\n\t\r\n\tbool target_found = false;\r\n\tMth::Vector target;\r\n\t\r\n\t// in order not to miss vert polys with a thin horizontal projection, we check for them starting at this frame's initial position\r\n\tMth::Vector search_pos = old_pos;\r\n\tsearch_pos[Y] = Mth::Max(pos[Y], old_pos[Y]);\r\n\t\r\n\tfloat scan_distance = 500.0f;\r\n\tfloat scan_height = 0.0f;\r\n\tif (mp_physics_control_component->IsWalking())\r\n\t{\r\n\t\tif (mp_walk_component->m_state == CWalkComponent::WALKING_GROUND)\r\n\t\t{\r\n\t\t\t// and use a reduced scan distance\r\n\t\t\tscan_distance = Script::GetFloat(CRCD(0xe50a9d56, \"Physics_Acid_Drop_Walking_On_Ground_Search_Distance\"));\r\n\r\n\t\t\t// and look for vert polys above us\r\n\t\t\tscan_height = 200.0f;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// look slightly behind us for acid drops (we may be facing down a vert we're standing on)\r\n\t\t\tsearch_pos -= 12.0f * drop_direction;\r\n\t\t}\r\n\t}\r\n\t\r\n\tCFeeler feeler;\r\n\t\r\n\t// setup collision cache\r\n\tNx::CCollCache* p_coll_cache = Nx::CCollCacheManager::sCreateCollCache();\r\n\tMth::CBBox bbox;\r\n\tMth::Vector p;\r\n\tp = search_pos;\r\n\tp[Y] += scan_height;\r\n\tbbox.AddPoint(p);\r\n\tp[Y] -= 4200.0f;\r\n\tbbox.AddPoint(p);\r\n\tp = search_pos + drop_direction * scan_distance;\r\n\tp[Y] += scan_height;\r\n\tbbox.AddPoint(p);\r\n\tp[Y] -= 4200.0f;\r\n\tbbox.AddPoint(p);\r\n\tp_coll_cache->Update(bbox);\r\n\tfeeler.SetCache(p_coll_cache);\r\n\t\r\n\tMth::Vector target_normal;\r\n\tMth::Vector horizontal_target_normal;\r\n\tfloat distance;\r\n\tfor (distance = 0.01f; distance < scan_distance; distance += 3.0f)\r\n\t{\r\n\t\t// look for a vert poly below us\r\n\t\tfeeler.m_start = search_pos + distance * drop_direction;\r\n\t\tfeeler.m_end = feeler.m_start;\r\n\t\tfeeler.m_start[Y] += scan_height;\r\n\t\tfeeler.m_end[Y] -= 4000.0f;\r\n\t\tif (feeler.GetCollision() && (feeler.GetFlags() & mFD_VERT) && is_vert_for_transfers(feeler.GetNormal()))\r\n\t\t{\r\n\t\t\t// the horizontal projection of the vert's normal just correspond somewhat to our direction\t\t\t \r\n\t\t\ttarget_normal = horizontal_target_normal = feeler.GetNormal();\r\n\t\t\thorizontal_target_normal[Y] = 0.0f;\r\n\t\t\thorizontal_target_normal.Normalize();\r\n\t\t\t\r\n\t\t\tif (mp_physics_control_component->IsWalking() && mp_walk_component->m_state == CWalkComponent::WALKING_AIR)\r\n\t\t\t{\r\n\t\t\t\t// special acceptance rules for walking in-air acid drops\r\n\t\t\t\ttarget_found = Mth::DotProduct(drop_direction, horizontal_target_normal) <= -0.25f\r\n\t\t\t\t\t|| Mth::DotProduct(drop_direction, horizontal_target_normal) >= 0.05f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ttarget_found = Mth::DotProduct(drop_direction, horizontal_target_normal) >= 0.05f;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (target_found)\r\n\t\t\t{\r\n\t\t\t\ttarget = feeler.GetPoint();\r\n\t\t\t\t// feeler.m_end[Y] += 3960.0f;\r\n\t\t\t\t// feeler.DebugLine(255, 100, 100, 0);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// feeler.m_end[Y] += 3960.0f;\r\n\t\t\t\t// feeler.DebugLine(100, 255, 100, 0);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// feeler.m_end[Y] += 3960.0f;\r\n\t\t\t// feeler.DebugLine(100, 100, 255, 0);\r\n\t\t}\r\n\t\t\r\n\t\t// use a larger incrememt at larger distances, as we have several frames yet to find these polys\r\n\t\tif (distance > 100.0f)\r\n\t\t{\r\n\t\t\tdistance += 24.0f;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (!target_found)\r\n\t{\r\n\t\t// no valid acid drop target found\r\n\t\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tfloat original_target_height = target[Y];\r\n\t\r\n\t// because our search began behind us, the horizontal offset to the target may not be forward\r\n\tMth::Vector horizontal_offset = target - pos;\r\n\thorizontal_offset[Y] = 0.0f;\r\n\tdistance = horizontal_offset.Length();\r\n\tif (Mth::DotProduct(horizontal_offset, drop_direction) < 0.0f)\r\n\t{\r\n\t\tdistance = -distance;\r\n\t}\r\n\tdrop_direction = horizontal_offset / distance;\r\n\t\r\n\t// stash a copy of velocity so we can pretend it has an adjusted value\r\n\tMth::Vector hold_vel = vel;\r\n\t\r\n\tif (mp_physics_control_component->IsWalking())\r\n\t{\r\n\t\t// because when walking they are necessarily in the same direction, project our horizontal velocity in the drop direction\r\n\t\tvel.ProjectToNormal(drop_direction);\r\n\t\tvel[Y] = hold_vel[Y];\r\n\t}\r\n\t\r\n\t// calculate our effective horizontal velocity\r\n\tfloat initial_horiz_speed = sqrtf(vel[X] * vel[X] + vel[Z] * vel[Z]);\r\n\t\r\n\tif (mp_physics_control_component->IsWalking())\r\n\t{\r\n\t\t// boost our effective horizontal speed up to maximum run speed\r\n\t\tfloat horizontal_boost = mp_walk_component->get_run_speed();\r\n\t\tif (initial_horiz_speed < horizontal_boost)\r\n\t\t{\r\n\t\t\tvel[X] = horizontal_boost * GetWalkComponentFromObject(GetObject())->m_facing[X];\r\n\t\t\tvel[Z] = horizontal_boost * GetWalkComponentFromObject(GetObject())->m_facing[Z];\r\n\t\t\tinitial_horiz_speed = horizontal_boost;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// give a slight upward pop\r\n\tif (skated_off_edge)\r\n\t{\r\n\t\tvel[Y] = Mth::Max(vel[Y], GetPhysicsFloat(CRCD(0x95a79c32, \"Physics_Acid_Drop_Pop_Speed\")));\r\n\t}\r\n\t\r\n\t// but limit upward speed to something reasonable\r\n\tif (!mp_physics_control_component->IsWalking() || mp_walk_component->m_state != CWalkComponent::WALKING_GROUND)\r\n\t{\r\n\t\tvel[Y] = Mth::Min(vel[Y], 2.0f * GetPhysicsFloat(CRCD(0x95a79c32, \"Physics_Acid_Drop_Pop_Speed\")));\r\n\t}\r\n\t\r\n\t// grab the acceleration we will have during our acid drop\r\n\tSetFlagTrue(SPINE_PHYSICS);\r\n\tfloat acceleration = get_air_gravity();\r\n\tSetFlagFalse(SPINE_PHYSICS);\r\n\t\r\n\t// calculate what height we would have if we used our current horizontal velocity to reach the target position\r\n\tfloat final_height;\r\n\tif (distance > 0.0f && initial_horiz_speed > 0.0001f)\r\n\t{\r\n\t\tfloat time_to_target = distance / initial_horiz_speed;\r\n\t\tfinal_height = pos[Y] + vel[Y] * time_to_target + 0.5f * acceleration * time_to_target * time_to_target;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// for backwards acid drops, just act as through we are directly over the target point\r\n\t\tfinal_height = pos[Y];\r\n\t}\r\n\t\r\n\t// if we need to jump up to the target\r\n\tif (mp_physics_control_component->IsWalking() && vel[Y] > 0.0f && pos[Y] < target[Y])\r\n\t{\r\n\t\t// check to see if we'll ever reach that height with our effective upward velocity\r\n\t\tfloat max_height = pos[Y] + vel[Y] * vel[Y] / (-2.0f * acceleration);\r\n\t\tfloat time_to_target = Mth::Abs(distance) / initial_horiz_speed;\r\n\t\tfloat time_to_max_height = vel[Y] / -acceleration;\r\n\t\tif (time_to_target < time_to_max_height)\r\n\t\t{\r\n\t\t\t// effectively, this means that we're willing to reduce our horizontal boost in order allow more time to reach the required height\r\n\t\t\tfinal_height = max_height;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// if we can't reach the target with our current velocity, ditch the acid drop\r\n\tif (final_height < target[Y])\r\n\t{\r\n\t\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\tvel = hold_vel;\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// calculate the air time before the acid drop would hit its true target; prevent acid drops from occuring moments before landing\r\n\tSetFlagTrue(SPINE_PHYSICS);\r\n\tfloat time_to_reach_target_height = calculate_time_to_reach_height(original_target_height, pos[Y], vel[Y]);\r\n\tSetFlagFalse(SPINE_PHYSICS);\r\n\tif (time_to_reach_target_height < Script::GetFloat(CRCD(0x32c20f7e, \"Physics_Acid_Drop_Min_Air_Time\")))\r\n\t{\r\n\t\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\tvel = hold_vel;\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// ensure that we have a clear shot to the target\r\n\t\r\n\tbool clear_path = false;\r\n    \r\n\t// keep shifting our target point up until we can get a clear shot to it, or we get to an unreachable height\r\n\twhile (target[Y] < final_height)\r\n\t{\r\n\t\tfeeler.m_start = pos;\r\n\t\t\r\n\t\t// check a path constructed from two concatenated lines, with the midpoint halfway along the acid drop trajectory; this is an attempt\r\n\t\t// to allow most acid drop which might be disallowed by a ledge which would block a straight line\r\n\t\t\r\n\t\t// calculate the time span required to fall to the target height\r\n\t\tSetFlagTrue(SPINE_PHYSICS);\r\n\t\tfloat half_time_to_reach_target_height = 0.5f * calculate_time_to_reach_height(target[Y], pos[Y], vel[Y]);\r\n\t\tSetFlagFalse(SPINE_PHYSICS);\r\n\t\t\r\n\t\t// calculate the spine velocity which would be used for this target\r\n\t\tfloat required_speed = 0.5f * distance / half_time_to_reach_target_height;\r\n\t\t\r\n\t\t// calculate the height we will be at halfway through the acid drop\r\n\t\tfloat height_halfway = pos[Y] + vel[Y] * half_time_to_reach_target_height\r\n\t\t\t+ 0.5f * acceleration * Mth::Sqr(half_time_to_reach_target_height);\r\n\t\t\r\n\t\t// calculate the point halfway through the acid drop\r\n\t\tMth::Vector halfway_point = pos;\r\n\t\thalfway_point[Y] = height_halfway;\r\n\t\thalfway_point += required_speed * half_time_to_reach_target_height * drop_direction;\r\n\t\t\r\n\t\t// check for collisions alone the two-line path\r\n\t\tfeeler.m_end = halfway_point;\r\n\t\tif (!feeler.GetCollision())\r\n\t\t{\r\n\t\t\t// feeler.DebugLine(255, 255, 0);\r\n\t\t\tfeeler.m_start = feeler.m_end;\r\n\t\t\tfeeler.m_end = target;\r\n\t\t\tfeeler.m_end[Y] += 1.0f;\r\n\t\t\tif (!feeler.GetCollision())\r\n\t\t\t{\r\n\t\t\t\t// feeler.DebugLine(255, 255, 0);\r\n\t\t\t\tclear_path = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// feeler.DebugLine(0, 0, 0, 0);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// feeler.DebugLine(0, 0, 0, 0);\r\n\t\t\r\n\t\t// try a higher target point\r\n\t\ttarget[Y] += 24.0f;\r\n\t}\r\n\t\r\n\t// no clear path was found along the acid drop\r\n\tif (!clear_path)\r\n\t{\r\n\t\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\tvel = hold_vel;\r\n\t\treturn false;\r\n\t}\r\n\tDUMP_VELOCITY;\r\n\t\r\n\tNx::CCollCacheManager::sDestroyCollCache(p_coll_cache);\r\n\t\r\n\tacid_drop_data.target_pos = target;\r\n\tacid_drop_data.target_normal = target_normal;\r\n\tacid_drop_data.true_target_height = original_target_height;\r\n\treturn true;\r\n}\r\n\r\nvoid CSkaterCorePhysicsComponent::enter_acid_drop ( const SAcidDropData& acid_drop_data )\r\n{\r\n\tconst Mth::Vector& target_pos = acid_drop_data.target_pos;\r\n\tconst Mth::Vector& target_normal = acid_drop_data.target_normal;\r\n\tconst float& true_target_height = acid_drop_data.true_target_height;\r\n\t\r\n\t// setup the skater state for the acid drop\r\n\t\r\n\tMth::Vector horizontal_offset = target_pos - GetPos();\r\n\thorizontal_offset[Y] = 0.0f;\r\n\tfloat distance = horizontal_offset.Length();\r\n\tif (Mth::DotProduct(horizontal_offset, GetVel()) < 0.0f)\r\n\t{\r\n\t\tdistance = -distance;\r\n\t}\r\n\tMth::Vector drop_direction = horizontal_offset / distance;\r\n\t\r\n\t// calculate the spine speed required to reach the target given our current vertical velocity\r\n\tSetFlagTrue(SPINE_PHYSICS);\r\n\tfloat time_to_reach_target_height = calculate_time_to_reach_height(target_pos[Y], GetPos()[Y], GetVel()[Y]);\r\n\tfloat required_speed = distance / time_to_reach_target_height;\r\n\tSetFlagFalse(SPINE_PHYSICS);\r\n\tmp_state_component->m_spine_vel.Set(required_speed * drop_direction[X], 0.0f, required_speed * drop_direction[Z]);\r\n\tacid_hold = mp_state_component->m_spine_vel;\r\n\t\r\n\t// once we reach this height, the skater's horizontal velocity will be zeroed out\r\n\tm_transfer_target_height = target_pos[Y];\r\n\t\r\n\t// Gfx::AddDebugStar(target, 24.0f, RED, 0);\r\n\t\r\n\t// enter the acid drop state\r\n\tSetFlagTrue(SPINE_PHYSICS);\r\n\tSetFlagTrue(VERT_AIR);\r\n\tSetFlagTrue(IN_ACID_DROP);\r\n\tSetFlagFalse(TRACKING_VERT);\r\n\tSetFlagFalse(AUTOTURN);\r\n\t\r\n\t// zero our horizontal velocity\r\n\tGetVel()[X] = 0.0f;\r\n\tGetVel()[Z] = 0.0f;\r\n\tDUMP_VELOCITY;\r\n\t\r\n\t// setup the acid drop's matrix slerp\r\n\t\r\n\tMth::Matrix acid_drop_slerp_start = GetMatrix();\r\n\t\r\n\t// calculate the facing we want when we land; retain our horizontal direction and choose a vertical component which puts us parallel so the target\r\n\t// poly's plane\r\n\tMth::Vector land_facing = drop_direction;\r\n\tland_facing[Y] = -(land_facing[X] * target_normal[X] + land_facing[Z] * target_normal[Z]) / target_normal[Y];\r\n\tland_facing.Normalize();\r\n\t\r\n\t// calculate goal matrix\r\n\tMth::Matrix acid_drop_slerp_goal;\r\n\tacid_drop_slerp_goal[Z] = land_facing;\r\n\tacid_drop_slerp_goal[Z].ProjectToPlane(target_normal);\r\n\tacid_drop_slerp_goal[Z].Normalize();\r\n\tacid_drop_slerp_goal[Y] = target_normal;\r\n\tacid_drop_slerp_goal[X] = Mth::CrossProduct(acid_drop_slerp_goal[Y], acid_drop_slerp_goal[Z]);\r\n\tacid_drop_slerp_goal[W].Set();\r\n\t\r\n\t// store the goal facing for use in adjusting the velocity at land time\r\n\tm_transfer_goal_facing = acid_drop_slerp_goal[Z];\r\n\t\r\n\t// setup a good camera matrix for the acid drop (before applying any deviation preserving adjustments)\r\n\tm_acid_drop_camera_matrix = acid_drop_slerp_goal;\r\n\tif (m_acid_drop_camera_matrix[Z][Y] > 0.0f)\r\n\t{\r\n\t\tm_acid_drop_camera_matrix[Z] *= -1.0f;\r\n\t\tm_acid_drop_camera_matrix[X] *= -1.0f;\r\n\t}\r\n\t\r\n\t// if the skater is entering the acid drop with an odd facing due to rotation, we want to preserve that angle in the slerp's goal matrix\r\n\t\r\n\t// calculate the deviation between the skater's velocity and facing\r\n\tMth::Vector horizontal_facing = GetMatrix()[Z];\r\n\thorizontal_facing[Y] = 0.0f;\r\n\tfloat angle = Mth::GetAngleAbout(horizontal_facing, drop_direction, GetMatrix()[Y]);\r\n\t\r\n\t// rotate goal facing to reflect the deviation in the initial facing\r\n\tacid_drop_slerp_goal.RotateYLocal(-angle);\r\n\r\n\t// setup the slerp state\r\n\tm_transfer_slerper.setMatrices(&acid_drop_slerp_start, &acid_drop_slerp_goal);\r\n\tm_transfer_slerp_timer = 0.0f;\r\n\tm_transfer_slerp_duration = time_to_reach_target_height;\r\n\tm_transfer_slerp_previous_matrix = acid_drop_slerp_start;\r\n\t\r\n\t// trigger the appropriate script\r\n\tScript::CStruct* p_params = new Script::CStruct;\r\n\tp_params->AddFloat(CRCD(0xbb00fe40, \"DropHeight\"), GetPos()[Y] - true_target_height);\r\n\tGetObject()->SpawnAndRunScript(CRCD(0xc7ed5fef, \"SkaterAcidDropTriggered\"), -1, false, false, p_params);\r\n\t\r\n\t// no late jumps during an acid drop\r\n\tGetObject()->RemoveEventHandler(CRCD(0x8ffefb28, \"Ollied\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n                    \r\nvoid CSkaterCorePhysicsComponent::handle_post_transfer_limit_overrides (   )\r\n{\r\n\t// After a transfer, if we are above our standard speed limits, we ignore those limits for a short duration.  Over the duration the speed limits\r\n\t// lerp from our starting speed down to the standard speed limits.  Only non-air time is counted towards the duration.\r\n\t\r\n\t// detect leaving an acid drop\r\n\tif (m_began_frame_in_transfer && !GetFlag(SPINE_PHYSICS) && !GetFlag(IS_BAILING))\r\n\t{\r\n\t\t// only override limits if we start above the limits\r\n\t\tfloat standard_max = GetSkater()->GetScriptedStat(CRCD(0x2eacddb3, \"Skater_Max_Speed_Stat\"));\r\n\t\tfloat speed = GetVel().Length();\r\n\t\tif (speed < 1.25f * standard_max) return;\r\n\t\t\r\n\t\t// setup state to ignore speed limits\r\n\t\tm_transfer_overrides_factor = Mth::Min(speed / standard_max, GetPhysicsFloat(CRCD(0xc6b38be0, \"Physics_Transfer_Speed_Limit_Override_Max\")));\r\n\t\t\r\n\t\t// large values\r\n\t\tm_override_max = 1e20f;\r\n\t\tm_override_max_max = 1e20f;\r\n\t}\r\n\telse if (m_transfer_overrides_factor == 1.0f) return;\r\n\t\r\n\t// turn on speed limit overrides\r\n\tm_override_limits_time = -1.0f;\r\n\t\r\n\t// count our timer down\r\n\tm_transfer_overrides_factor -= m_frame_length * GetPhysicsFloat(CRCD(0xf9b006aa, \"Physics_Transfer_Speed_Limit_Override_Drop_Rate\"));\r\n\t\r\n\t// end the ignoring of speed limits if the duration is up\r\n\tif (m_transfer_overrides_factor < 1.0f)\r\n\t{\r\n\t\tm_transfer_overrides_factor = 1.0f;\r\n\t\tm_override_limits_time = 0.0f;\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// grab the standard speed limit\r\n\tfloat standard_max = GetSkater()->GetScriptedStat(CRCD(0x2eacddb3, \"Skater_Max_Speed_Stat\")); \r\n\t\r\n\t// calculate the appropriate speed limit based on the time since the acid drop and the speed at the end of the acid drop\r\n\tfloat time_based_appropriate_max = m_transfer_overrides_factor * standard_max;\r\n\t\r\n\t// calculate a speed limit based on the current speed; thus, if we break during the ignoring of speed limits, our speed limits will turn back on\r\n\tfloat speed_based_appropriate_max = 1.1f * GetVel().Length();\r\n\t\r\n\t// take the lowest speed limit; never increase the speed limit\r\n\tfloat appropriate_max;\r\n\tif (GetState() != AIR)\r\n\t{\r\n\t\tappropriate_max = Mth::Min3(time_based_appropriate_max, speed_based_appropriate_max, m_override_max);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// in air, don't drop the limits when your current speed drops; otherwise you lose your overrides as the top of vert air\r\n\t\tappropriate_max = Mth::Min(time_based_appropriate_max, m_override_max);\r\n\t}\r\n\t\r\n\t// end the ignoring of speed limits if the duration is up\r\n\tif (appropriate_max < standard_max)\r\n\t{\r\n\t\tm_transfer_overrides_factor = 1.0f;\r\n\t\tm_override_limits_time = 0.0f;\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// set the artificially high speed limit override\r\n\tm_override_max = appropriate_max;\r\n\t\r\n\t// the max max speed limit will never fall below the standard max max speed limit\r\n\tm_override_max_max = m_override_max / standard_max * GetSkater()->GetScriptedStat(CRCD(0x2eacddb3, \"Skater_Max_Speed_Stat\"));\r\n\t\r\n\tPERIODIC(10)\r\n\t{\r\n\t\tprintf(\"Post-Transfer Speed Limit Overrides:  current / standard = %.2f\\n\", m_override_max / standard_max);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n                    \r\nfloat CSkaterCorePhysicsComponent::get_air_gravity (   )\r\n{\r\n\t// given that we are in the air, figure out what gravity to use\t\r\n\t// based on if we are VERT or regular air and the cheat modes\r\n\t// make sure that if you use this in calculations, then your flags do not change while you expect it to be the same\r\n\tfloat gravity;\r\n\r\n\tif (GetFlag(VERT_AIR) || GetFlag(SPINE_PHYSICS))   // Note, spine is treated same as vert\r\n\t{\t\t\t\t\t\t\t  \r\n\t\t// gravity = GetPhysicsFloat(CRCD(0xfaa40754, \"Physics_Air_Gravity\")) / GetSkater()->GetScriptedStat(CRCD(0x441c38a0, \"Physics_vert_hang_Stat\"));\r\n\t\tgravity = GetPhysicsFloat(CRCD(0xfaa40754, \"Physics_Air_Gravity\")) / GetPhysicsFloat(CRCD(0x441c38a0, \"Physics_vert_hang_Stat\"));\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// gravity = GetPhysicsFloat(CRCD(0xfaa40754, \"Physics_Air_Gravity\")) / GetSkater()->GetScriptedStat(CRCD(0xc31ca696, \"Physics_Air_hang_Stat\"));\r\n\t\tgravity = GetPhysicsFloat(CRCD(0xfaa40754, \"Physics_Air_Gravity\")) / GetPhysicsFloat(CRCD(0xc31ca696, \"Physics_Air_hang_Stat\"));\r\n\t}\r\n\t\r\n\tif (Mdl::Skate::Instance()->GetCareer()->GetCheat(CRCD(0x9c8c6df1, \"CHEAT_MOON\")))\r\n\t{\r\n\t\t// Here, set the flag. It may seem redundant, but the above line is very likely\r\n\t\t// to be hacked by gameshark. They probably won't notice this one, which will\r\n\t\t// set the flags as if they had actually enabled the cheat -- which enables us\r\n\t\t// to detect that it has been turned on more easily.\r\n\t\tMdl::Skate::Instance()->GetCareer()->SetGlobalFlag( Script::GetInteger(CRCD(0x9c8c6df1, \"CHEAT_MOON\")));\r\n\t\tgravity *= GetPhysicsFloat(CRCD(0xec128f0, \"moon_gravity\"));\r\n\t\tg_CheatsEnabled = true;\r\n\t}\r\n\t \r\n\treturn gravity;\r\n} \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\r\nfloat CSkaterCorePhysicsComponent::calculate_time_to_reach_height ( float target_height, float pos_Y, float vel_Y )\r\n{\r\n\t// s = ut - 1/2 * g * t^2\t\t\t (note, -g = a in the more traditional formula)\r\n\t// solve this using the quadratic equation, gives us the formula below\r\n\t// Note the sign of s is important.....\r\n\tfloat distance = pos_Y - target_height; \r\n\tfloat velocity = vel_Y;\r\n\tfloat acceleration = -get_air_gravity();\r\n\treturn (velocity + sqrtf(velocity * velocity + 2.0f * acceleration * distance)) / acceleration; \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::handle_ground_rotation (   )\r\n{\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\t\r\n\r\n\tfloat rot = 0.0f; \r\n\tfloat speed = GetVel().Length();\t\t\t\t\t\t\r\n\t\r\n\tif (control_pad.m_left.GetPressed())\r\n\t{\r\n\t\tif (!control_pad.m_down.GetPressed())\r\n\t\t{\r\n\t\t\trot = GetPhysicsFloat(CRCD(0x374e056b, \"Physics_Ground_Rotation\"));\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\trot = GetPhysicsFloat(CRCD(0x7933a8ef, \"Physics_Ground_Sharp_Rotation\")); \r\n\t\t\tif (speed < 10.0f)\r\n\t\t\t{\r\n\t\t\t\t// If not moving, then we want more control over turning, so ramp up the turing speed over a second\r\n\t\t\t\tint pressed_time = control_pad.m_left.GetPressedTime();\r\n\t\t\t\tif (pressed_time < STOPPED_TURN_RAMP_TIME)\r\n\t\t\t\t{\r\n\t\t\t\t\trot = rot * pressed_time / STOPPED_TURN_RAMP_TIME;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if (control_pad.m_right.GetPressed())\r\n\t{\r\n\t\tif (!control_pad.m_down.GetPressed())\r\n\t\t{\r\n\t\t\trot = -GetPhysicsFloat(CRCD(0x374e056b, \"Physics_Ground_Rotation\"));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\trot = -GetPhysicsFloat(CRCD(0x7933a8ef, \"Physics_Ground_Sharp_Rotation\")); \r\n\t\t\tif (speed < 10.0f)\r\n\t\t\t{\r\n\t\t\t\t// If not moving, then we want more control over turning, so ramp up the turing speed over a second\r\n\t\t\t\tint pressed_time = control_pad.m_right.GetPressedTime();\r\n\t\t\t\tif (pressed_time < STOPPED_TURN_RAMP_TIME)\r\n\t\t\t\t{\r\n\t\t\t\t\trot = rot * pressed_time / STOPPED_TURN_RAMP_TIME;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/*\r\n\tbool do_cess = false;\t\t\t\t\t\t\t\r\n\tif (CESS_SLIDE_BUTTONS)\r\n\t{\r\n\t\tfloat cess_turn_min_speed = GetPhysicsFloat(CRCD(0xae84e34a, \"cess_turn_min_speed\"));\r\n\t\tif (speed > cess_turn_min_speed)\r\n\t\t{\r\n\t\t\tdo_cess = true;\r\n\t\t\t\r\n\t\t\tfloat cess_turn_cap_speed = GetPhysicsFloat(CRCD(0x8242c4fe, \"cess_turn_cap_speed\"));\r\n\t\t\t\r\n\t\t\tfloat scale = speed;\r\n\t\t\tif (scale > cess_turn_cap_speed)\r\n\t\t\t{\r\n\t\t\t\tscale = cess_turn_cap_speed;\r\n\t\t\t}\r\n\t\t\tscale -= cess_turn_min_speed;\r\n\t\t\tscale /= cess_turn_cap_speed - cess_turn_min_speed;\r\n\t\t\r\n\t\t\trot = rot * scale * GetPhysicsFloat(CRCD(0x22834151, \"cess_turn_multiplier\"));\r\n\t\t}\r\n\t}\r\n\t*/\r\n\r\n\tif (rot == 0.0f) return;\r\n\t\r\n\trot *= m_frame_length;\r\n\t\r\n\tmYAngleIncreased = rot > 0.0f;\r\n\t\r\n\t// K: Avoid anything that might change the velocity direction if this flag is set.\r\n\tif (!m_lock_velocity_direction /* && !do_cess*/)\r\n\t{\r\n\t\tGetVel().RotateY(rot);\t\t\t\t\t// Note:  Need to rotate this about UP vector\t\t\r\n\t\tDUMP_VELOCITY;\r\n\t}\t\r\n\t\r\n\tGetMatrix().RotateYLocal(rot);\t\t\t\t\r\n\tm_lerping_display_matrix.RotateYLocal(rot);\t\t\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::remove_sideways_velocity ( Mth::Vector& vel )\r\n{\t\t\t\t\r\n\t// Remove any non-forward component of the velocity\r\n\t\r\n\tfloat speed = vel.Length(); \t\t// get size of velocity\r\n\tif (speed > 0.00001f)\r\n\t{\r\n\t\t// if (!USE_BIKE_PHYSICS)\r\n\t\t// {\t\t\r\n\t\t\tvel *= 1.0f / speed;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// get unit vector in direction of velocity\r\n\t\t\tfloat direction = Mth::Sgn(Mth::DotProduct(vel, GetMatrix()[Z]));\t// get fwds or backwards\r\n\t\t\t\r\n\t\t\tvel = GetMatrix()[Z];\t\t\t\t\t\t\t\t\t\t\t\t// get forward direction\r\n\t\t\tvel *= speed * direction;\t\t\t\t\t\t\t\t\t\t\t\t\t// apply all speed in this direction\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t// }\r\n\t\t// else\r\n\t\t// {\r\n\t\t  // Mth::Vector old_vel = vel;\r\n\t\t  \r\n\t\t  // vel.ProjectToNormal(GetMatrix()[Z]); \t\t\t\t\t\t\t\t// leave forward velocity alone\r\n\t\t  \r\n\t\t  // old_vel -= GetVel();\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t\t// find remaining sideways velocity\r\n\t\t  \r\n\t\t  // old_vel *= 1.0f - GetPhysicsFloat(CRCD(0x53385759, \"cess_Friction\"));\r\n\t\t  // vel += old_vel;\r\n\t\t  // DUMP_VELOCITY;\r\n\t\t// }\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::check_side_collisions (   )\r\n{\r\n\t// check for collisins left and right of the skater; if we get collisions on both sides then restore him to the original position\r\n\t\r\n\tMth::Vector debounce = GetPos();\r\n\r\n\tfloat side_col = GetPhysicsFloat(CRCD(0x406b425f, \"Skater_side_collide_length\"));\r\n\r\n\tif (check_side(-1.0f, side_col))\r\n\t{\r\n\t\tif (check_side(1.0f, side_col))\r\n\t\t{\r\n\t\t\tGetPos() = debounce;\t\t\t// two collisions, back to safety\r\n\t\t\tDUMP_POSITION;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (check_side(1.0f, side_col))\r\n\t\t{\r\n\t\t\tif (check_side(-1.0f, side_col))\r\n\t\t\t{\r\n\t\t\t\tGetPos() = debounce;\t\t// two collisions, back to safety\r\n\t\t\t\tDUMP_POSITION;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::check_side ( float side, float side_col )\r\n{\r\n\t#ifdef STICKY_WALLRIDES\r\n\t// Prevous checks might have put us into a wall ride, so just ignore future checks\t\t\t\t\t \r\n\tif (GetState() == WALL)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t#endif\r\n\t\t\t  \r\n\t// - - - side collision detection  - - - - - - - - - - - - - - - - -\r\n\r\n\tm_col_start = GetPos() + GetMatrix()[Y] * GetPhysicsFloat(CRCD(0xb45b39e2, \"Skater_side_collide_height\"));\r\n\t\r\n\tfloat col_len = side_col;\r\n\t#ifdef STICKY_WALLRIDES\r\n\tif (GetState() == AIR)\r\n\t{\r\n\t\tcol_len += GetPhysicsFloat(CRCD(0x1c58c8b4, \"Skater_air_extra_side_col\"));\r\n\t}\r\n\t#endif\r\n\tm_col_end = m_col_start + side * GetMatrix()[X] * col_len;  \r\n\r\n\tif (!get_member_feeler_collision()) return false;\r\n\t\r\n\tMth::Vector WallFloorNormal = m_feeler.GetNormal();\r\n\r\n\t#ifdef STICKY_WALLRIDES\r\n\tif (GetState() == AIR)\r\n\t{\r\n\t\tif (check_for_wallride())\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// push a bit away from the wall if in the air\r\n\t\t\tMth::Vector to_wall = m_feeler.GetPoint();\r\n\t\t\tto_wall -= m_col_start;\t\t\t\t// vector towards the wall\r\n\t\t\tfloat push_dist = to_wall.Length();\t\t\t\t\t// distance to wall\r\n\t\t\tpush_dist -= col_len - side_col;\t   \t\t\t\t// adjust by the extra push we gave\r\n\t\t\tif (push_dist > 0.0f)\t\t\t\t\t\t\t\t// if closer to wall than side_col\r\n\t\t\t{\r\n\t\t\t\tto_wall.Normalize(push_dist);\t\t\t\t    // then get direction to wall, scaled by dist we want to move\t\t\t\t\r\n\t\t\t\tGetPos() -= to_wall / 10.0f;\t\t    // move 1/10th of the way, for nice lerp\r\n\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t\r\n\t\t\t\tfloat turn_angle;\t\t\t\t\t\r\n\t\t\t\t// Rotate away from wall only if not rotating myself\r\n\t\t\t\t// otherwise velocity can be continually rotated one way while \r\n\t\t\t\t// the orientation is rated the other way via the d-pad \r\n\t\t\t\t\r\n\t\t\t\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\r\n\t\t\t\t// don't rotate at all if in the air, as it changes our direction, usually not what we want\r\n\t\t\t\tif (GetState() != AIR\r\n\t\t\t\t\t&& !control_pad.m_R1.GetPressed()\r\n\t\t\t\t\t&& !control_pad.m_L1.GetPressed() \r\n\t\t\t\t\t&& !control_pad.m_left.GetPressed() \r\n\t\t\t\t\t&& !control_pad.m_right.GetPressed()) \r\n\t\t\t\t{\r\n\t\t\t\t\trotate_away_from_wall(WallFloorNormal, turn_angle, 0.2f); \t// and rotate away from the wall\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t#endif\r\n\t{\r\n\t\tfloat angle = Mth::DotProduct(WallFloorNormal, GetMatrix()[Y]);\r\n\t\t// Consider 90+-30 degrees as wall (_0_5)\r\n\t\t// Consider 90+-15 degrees as wall (_0_25)\r\n\t\tif (angle < 0.25f && angle > -0.25f)\r\n\t\t{\r\n\t\t\t// Undo movement\r\n\t\t\tGetPos() = m_safe_pos;\r\n\t\t\tDUMP_POSITION;\r\n\r\n\t\t\tfloat turn_angle;\r\n\t\t\trotate_away_from_wall(WallFloorNormal, turn_angle, 0.2f);\r\n\r\n\t\t\t// Try moving him off the wall:\r\n\t\t\tCFeeler\tfeeler(m_feeler.GetPoint() + WallFloorNormal, m_feeler.GetPoint() + WallFloorNormal * side_col);\t\r\n\t\t\tif (!feeler.GetCollision())\r\n\t\t\t{\r\n\t\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_BONK, m_feeler);\r\n\t\t\t\tif (mp_physics_control_component->HaveBeenReset()) return false;\r\n\t\t\t\t\r\n\t\t\t\t// Lower skater back down to the ground\r\n\t\t\t\tGetPos() = feeler.m_end - GetMatrix()[Y] * GetPhysicsFloat(CRCD(0xb45b39e2,\"Skater_side_collide_height\"));\r\n\t\t\t\tDUMP_POSITION;\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::check_for_wallpush (   )\r\n{\r\n\t// requires that m_feeler is a wall\r\n\t\r\n\tif (!mp_input_component->GetControlPad().m_triangle.GetPressed()) return false;\r\n\t\r\n\t// last wallpush must not have been too recently\r\n\tif (Tmr::ElapsedTime(m_last_wallpush_time_stamp) < Script::GetFloat(CRCD(0x17d543, \"Physics_Disallow_Rewallpush_Duration\"))) return false;\r\n\t\r\n\t// wall normal must be opposite our forward direction; just under the maximum flail angle\r\n\tif (Mth::DotProduct(GetMatrix()[Z], m_feeler.GetNormal()) >= -sinf(Mth::DegToRad(Script::GetFloat(CRCD(0x1483fd01, \"Wall_Bounce_Dont_Slow_Angle\")) - 1.0f))) return false;\r\n\t\r\n\t// last wallplant must not have been too recently\r\n\tif (Tmr::ElapsedTime(m_last_wallplant_time_stamp) < Script::GetFloat(CRCD(0x17d543, \"Physics_Disallow_Rewallpush_Duration\"))) return false;\r\n\t\r\n\t// throw a wallpush event for the scripts\r\n\tGetObject()->SelfEvent(CRCD(0x4c03635b, \"WallPush\"));\r\n\t\r\n\t// check to see if the wallpush has been canceled during the event\r\n\tif (GetFlag(CANCEL_WALL_PUSH))\r\n\t{\r\n\t\tSetFlagFalse(CANCEL_WALL_PUSH);\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// reverse direction of velocity perpendicular to the wall\r\n\tMth::Vector perp_vel = Mth::DotProduct(GetVel(), m_feeler.GetNormal()) * m_feeler.GetNormal();\r\n\tGetVel() -= 2.0f * perp_vel;\r\n\t\r\n\t// damp horizontal velocity\r\n\tfloat speed = GetVel().Length();\r\n\tif (speed > 0.001f)\r\n\t{\r\n\t\tGetVel() *= Mth::Max(\r\n\t\t\tScript::GetFloat(CRCD(0xb78542c2, \"Physics_Wallpush_Min_Exit_Speed\")),\r\n\t\t\tspeed - Script::GetFloat(CRCD(0x1112fb1c, \"Physics_Wallpush_Speed_Loss\"))\r\n\t\t) / speed;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGetVel() = -Script::GetFloat(CRCD(0xb78542c2, \"Physics_Wallpush_Min_Exit_Speed\")) * GetMatrix()[Z];\r\n\t}\r\n\t\r\n\t// project the resulting velocity into the ground's plane\r\n\tGetVel().RotateToPlane(m_current_normal);\r\n    \r\n\tDUMP_VELOCITY;\r\n\t\r\n\t// set orientation along new velocity\r\n\tGetMatrix()[Z] = GetVel();\r\n\tGetMatrix()[Z].Normalize();\r\n\tGetMatrix()[Y] = m_current_normal;\r\n\tGetMatrix()[X] = Mth::CrossProduct(GetMatrix()[Y], GetMatrix()[Z]);\r\n\tResetLerpingMatrix();\r\n\t\r\n\t// time stamp the wallplant\r\n\tm_last_wallpush_time_stamp = Tmr::GetTime();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::check_for_wallplant (   )\r\n{\r\n\t// requires that m_feeler is a wall\r\n\t\r\n\t// we must be somewhat vertical\r\n\tif (GetMatrix()[Y][Y] < 0.1f) return false;\r\n\t\r\n\t// last wallplant must not have been too recently\r\n\tif (Tmr::ElapsedTime(m_last_wallplant_time_stamp) < Script::GetFloat(CRCD(0x82135dd7, \"Physics_Disallow_Rewallplant_Duration\"))) return false;\r\n\t\r\n\t// not when you're too near the ground\r\n\tif (mp_state_component->m_height < Script::GetFloat(CRCD(0xd5349cc6, \"Physics_Min_Wallplant_Height\"))) return false;\r\n\t\r\n\t// wall must be substantially vertical\r\n\tif (!(m_feeler.GetFlags() & mFD_VERT) && Mth::Abs(m_feeler.GetNormal()[Y]) > 0.1f) return false;\r\n\t\r\n\tfloat speed = GetVel().Length();\r\n\tif (speed < 0.01f) return false;\r\n\tMth::Vector forward = GetVel() / speed;\r\n\t\t\r\n\t// horizontal wall normal must be opposite our horizontal velocity\r\n\tMth::Vector horizontal_forward = forward;\r\n\thorizontal_forward[Y] = 0.0f;\r\n\thorizontal_forward.Normalize();\r\n\tMth::Vector horizontal_normal = m_feeler.GetNormal();\r\n\thorizontal_normal[Y] = 0.0f;\r\n\thorizontal_normal.Normalize();\r\n\tif (Mth::DotProduct(horizontal_forward, horizontal_normal) > -sinf(Mth::DegToRad(Script::GetFloat(CRCD(0x8f79cc1c, \"Physics_Wallplant_Min_Approach_Angle\"))))) return false;\r\n\t\r\n\t// here we attempt to stop wallplant when in is more likely that the player is going for a grind\r\n\tif (GetVel()[Y] > 0.0f && mp_input_component->GetControlPad().m_triangle.GetPressed())\r\n\t{\r\n\t\tMth::Vector wall_point = m_feeler.GetPoint();\r\n\t\tMth::Vector\twall_normal = m_feeler.GetNormal();\r\n\r\n\t\tMth::Vector wall_up_vel(0.0f, GetVel()[Y] * 0.15f, 0.0f);\t\t// check 0.15 seconds ahead\r\n\t\twall_up_vel.RotateToPlane(wall_normal);  \r\n\r\n\t\t// check at what height will be in two frames\r\n\t\twall_point += wall_up_vel;\t\t\r\n\r\n\t\tCFeeler feeler(wall_point + wall_normal * 6.0f, wall_point - wall_normal * 6.0f);\r\n\t\tif (!feeler.GetCollision())\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tif (Script::GetInteger(CRCD(0x3ae85eef, \"skater_trails\")))\r\n\t\t\t{\r\n\t\t\t\tfeeler.DebugLine(255, 255, 0, 0);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t#ifdef __USER_DAN__\r\n\t\t\tif (Script::GetInteger(CRCD(0x3ae85eef, \"skater_trails\")))\r\n\t\t\t{\r\n\t\t\t\tfeeler.DebugLine(255, 0, 255, 0);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t}\r\n\t}\r\n\t\t\r\n\t// check for wallplant trick\r\n\t// K: Modified this to take an array of triggers, so that Kurt could check out using\r\n\t// Down,X DownLeft,X or DownRight,X as a trigger.\r\n\tbool triggered=false;\r\n\tScript::CArray *p_trick_query_array=Script::GetArray(CRCD(0x5d1f84a7, \"Wallplant_Trick\"));\r\n\tfor (uint32 i=0; i<p_trick_query_array->GetSize(); ++i)\r\n\t{\r\n\t\tScript::CStruct *p_trick_query_struct=p_trick_query_array->GetStructure(i);\r\n\t\tif (mp_trick_component->QueryEvents(p_trick_query_struct))\r\n\t\t{\r\n\t\t\ttriggered=true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif (!triggered)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// trip wallplant triggers\r\n\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_JUMP_OFF, m_feeler);\r\n\tif (mp_physics_control_component->HaveBeenReset()) return true;\r\n\t\r\n\t// zero vertical velocity\r\n\tGetVel()[Y] = 0.0f;\r\n\t\r\n\t// reverse velocity in the direction of the wall's normal\r\n\tMth::Vector perp_vel = Mth::DotProduct(GetVel(), horizontal_normal) * horizontal_normal;\r\n\tGetVel() -= 2.0f * perp_vel;\r\n\t\r\n\t// damp horizontal velocity\r\n\tfloat horizontal_speed = sqrtf(GetVel()[X] * GetVel()[X] + GetVel()[Z] * GetVel()[Z]);\r\n\tif (horizontal_speed > 0.0001f)\r\n\t{\r\n\t\tGetVel()[Y] = 0.0f;\r\n\t\tGetVel().Normalize(Mth::Max(\r\n\t\t\tScript::GetFloat(CRCD(0x7cee396c, \"Physics_Wallplant_Min_Exit_Speed\")),\r\n\t\t\thorizontal_speed - Script::GetFloat(CRCD(0x9b2d4a3, \"Physics_Wallplant_Speed_Loss\"))\r\n\t\t));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGetVel() = -Script::GetFloat(CRCD(0x7cee396c, \"Physics_Wallplant_Min_Exit_Speed\")) * horizontal_forward;\r\n\t}\r\n\t\r\n\t// replace vertical velocity with a wallplant boost\r\n\tGetVel()[Y] = Script::GetFloat(CRCD(0x74957fa, \"Physics_Wallplant_Vertical_Exit_Speed\"));\r\n\t\r\n\tif (m_feeler.IsMovableCollision())\r\n\t{\r\n\t\t// if the wall is moving, we are now in contact with it\r\n\t\tif (!mp_movable_contact_component->HaveContact() || m_feeler.GetMovingObject() != mp_movable_contact_component->GetContact()->GetObject())\r\n\t\t{\r\n\t\t\tmp_movable_contact_component->LoseAnyContact();\r\n\t\t\tmp_movable_contact_component->ObtainContact(m_feeler.GetMovingObject());\r\n\t\t}\r\n\t}\r\n\t\r\n\tDUMP_VELOCITY;\r\n\t\r\n\t// move to just outside the wall, insuring that there is no additional collision along the line to that point\r\n\tm_feeler.m_start = m_feeler.GetPoint();\r\n\tm_feeler.m_end = m_feeler.GetPoint() + Script::GetFloat(CRCD(0x24be8f0, \"Physics_Wallplant_Distance_From_Wall\")) * m_feeler.GetNormal();\r\n\tif (m_feeler.GetCollision())\r\n\t{\r\n\t\tGetPos() = m_feeler.GetPoint() + 0.1f * m_feeler.GetNormal();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGetPos() = m_feeler.m_end;\r\n\t}\r\n\tDUMP_POSITION;\r\n\t\r\n\t// set orientation along new velocity\r\n\tGetMatrix()[Z] = GetVel();\r\n\tGetMatrix()[Z][Y] = 0.0f;\r\n\tGetMatrix()[Z].Normalize();\r\n\tGetMatrix()[Y].Set(0.0f, 1.0f, 0.0f);\r\n\tGetMatrix()[X] = Mth::CrossProduct(GetMatrix()[Y], GetMatrix()[Z]);\r\n\tResetLerpingMatrix();\r\n\t\r\n\t// time stamp the wallplant\r\n\tm_last_wallplant_time_stamp = Tmr::GetTime();\r\n\t\r\n\t// throw a wallplant event for the scripts\r\n\tGetObject()->SelfEvent(CRCD(0xcf74f6b7, \"WallPlant\"));\r\n\t\r\n\t// trick off the object\r\n\tmp_trick_component->TrickOffObject(m_feeler.GetNodeChecksum());\r\n\t\r\n\t// turn back on orientation control in case we just came out of walking\r\n\tSetFlagFalse(NO_ORIENTATION_CONTROL);\r\n\t\r\n\t// acid drops are always allowed after a wallplant\r\n\tSetFlagFalse(AIR_ACID_DROP_DISALLOWED);\r\n\t\r\n\t// let the camera know we're snapping our position slightly\r\n\tSetFlagTrue(SNAPPED);\r\n\t\r\n\t// enter wallplant state\r\n\tSetState(WALLPLANT);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::check_for_wallride (   )\r\n{\r\n\t// Requires that m_feeler is a valid wall\r\n\t\r\n\tif (!m_col_flag_wallable) return false;\r\n\t\t\r\n\t// Allow a wall-ride attempt if triangle being pressed & long enough after the last wall-ride.\t\r\n\tif ((mp_trick_component->GetButtonState(CRCD(0x20689278, \"Triangle\")) || mp_trick_component->TriggeredInLastNMilliseconds(\r\n\t\t\tCRCD(0x20689278, \"Triangle\"),\r\n\t\t\t1000 * GetPhysicsFloat(CRCD(0x5d241b00, \"Wall_Ride_Triangle_Window\"))\r\n\t\t)) && static_cast< int >(Tmr::ElapsedTime(mWallrideTime)) > 1000 * GetPhysicsFloat(CRCD(0xf0c74ec2, \"Wall_Ride_Delay\")))\r\n\t{\r\n\t\t////////////////////////////////////////////////\r\n\t\t// check to see if we are going upwards, and within 0.15 seconds from the top of the wall (based on current up speed)\r\n\t\t// and we are going upwards, then don't wallride, as we will probably snap into a rail soon after\r\n\t\t//\r\n\r\n\t\tif (GetVel()[Y] > 0.0f)\r\n\t\t{\r\n\t\t\tMth::Vector wall_point = m_feeler.GetPoint();\r\n\t\t\tMth::Vector\twall_normal = m_feeler.GetNormal();\r\n\t\r\n\t\t\tMth::Vector wall_up_vel(0.0f, GetVel()[Y] * 0.15f, 0.0f);\t\t// check 0.15 seconds ahead\r\n\t\t\twall_up_vel.RotateToPlane(wall_normal);  \r\n\t\t\t\r\n\t\t\t// check at what height will be in two frames\r\n\t\t\twall_point += wall_up_vel;\t\t\r\n\t\t\t\r\n\t\t\tCFeeler check_feeler(wall_point + wall_normal * 6.0f, wall_point - wall_normal * 6.0f);\r\n\t\t\tif (!check_feeler.GetCollision()) return false;\r\n\t\t}\t\r\n\t\t\r\n\t\t////////////////////////////////////////////////\r\n\t\tmWallNormal = m_feeler.GetNormal();\r\n\t\t\r\n\t\tMth::Vector SquashedWallNormal = mWallNormal;\t\t\t // wall normal in the XZ plane\r\n\t\tSquashedWallNormal[Y] = 0;\r\n\t\tSquashedWallNormal.Normalize();\r\n\t\t\r\n\t\tMth::Vector SquashedVel = GetVel();\t\t\t \t\t\t// velocity in the XZ plane\r\n\t\tSquashedVel[Y] = 0;\r\n\t\tSquashedVel.Normalize();\r\n\t\t\r\n\t\t// Calculate the speed \"along\" the wall (i.e., in the XZ plane) needed to have enough speed along the wall to make the wallride viable \r\n\t\t// (otherwise we just go up and down, and end up at odd angles)\r\n\t\tMth::Vector vel_along_wall = GetVel();\r\n\t\tvel_along_wall[Y] = 0;\r\n\t\tvel_along_wall.ProjectToPlane(SquashedWallNormal);\r\n\t\tfloat speed_along_wall = vel_along_wall.Length();\r\n\t\t\r\n\t\tif (speed_along_wall < GetPhysicsFloat(CRCD(0xf0636a67, \"Wall_Ride_Min_Speed\"))) return false;\r\n\t\t\r\n\t\tfloat dot = fabsf(Mth::DotProduct(SquashedVel, SquashedWallNormal));\r\n\t\t\r\n\t\t// If all angles OK then trigger a wall-ride.\r\n\t\tif (mWallNormal[Y] > -sinf(Mth::DegToRad(GetPhysicsFloat(CRCD(0xae23e850, \"Wall_Ride_Upside_Down_Angle\")))) && \r\n\t\t\tdot < sinf(Mth::DegToRad(GetPhysicsFloat(CRCD(0x6ac9f64d, \"Wall_Ride_Max_Incident_Angle\")))) && \r\n\t\t\tGetMatrix()[Y][Y] > cosf(Mth::DegToRad(GetPhysicsFloat(CRCD(0xbfcbb7e8, \"Wall_Ride_Max_Tilt\")))))\r\n\t\t{\r\n\t\t\tif (!mp_trick_component->GraffitiTrickStarted())\r\n\t\t\t{\r\n\t\t\t\t// clear the graffiti trick buffer if we're moving to a new\r\n\t\t\t\t// world sector, but haven't started our trick yet...\r\n\t\t\t\tmp_trick_component->SetGraffitiTrickStarted(false);\r\n\t\t\t}\r\n\r\n\t\t\t// landed in a wall ride, check for triggers associated with this object\r\n\t\t\t// note we pass \"TRIGGER_LAND_ON\", perhaps not semanticaly correct but we use it for landing on rails,\r\n\t\t\t// so the meaning is the same across ground-rail-wallride\r\n\t\t\tset_last_ground_feeler(m_feeler);\r\n\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_LAND_ON, m_last_ground_feeler);\r\n\t\t\tif (mp_physics_control_component->HaveBeenReset()) return false;\r\n\r\n\t\t\tMth::Vector\tpoint = m_feeler.GetPoint();\t\t\t\t   \r\n\r\n\t\t\t// check to see if we are going into a corner\r\n\t\t\t// by checking the vector from out current pos along a line parallel to our movment rotated onto the wall.\r\n\t\t\tMth::Vector\tforward_vel = GetPos() - GetOldPos();\r\n\t\t\tforward_vel.RotateToPlane(mWallNormal);\r\n\t\t\tm_col_start = GetPos();\r\n\t\t\tm_col_end = GetPos() + forward_vel * 3.0f;\r\n\t\t\tif (get_member_feeler_collision()) return false;\r\n\t\t\t\r\n\t\t\t// Record start time.\r\n\t\t\tmWallrideTime = static_cast< int >(Tmr::GetTime());\r\n\t\t\t\r\n\t\t\t// Snap position to wall.\r\n\t\t\t// we don't want to snap too close\r\n\t\t\t// previously we moved him an inch away from the wall after snapping him to the collision point.\r\n\t\t\t// However, this seemed to cause problems in corner so now I just move him back one inch along the collision line\r\n\t\t\t// which is hence guarenteed not to push him through walls.\r\n\t\t\t\r\n\t\t\tGetPos() = point;\t   \t\t\t\t\t// move skater\r\n\t\t\tGetPos() += mWallNormal;\t// move away from surface\r\n\t\t\tDUMP_POSITION;\r\n\t\t\t\r\n\t\t\t// Rotate velocity to plane.\r\n\t\t\tGetVel().RotateToPlane(mWallNormal);\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t\t\r\n\t\t\t// Mick: if we set the velocity as direction, skater will keep going up more\r\n\t\t\tGetMatrix()[Z] = GetVel();\r\n\t\t\t\r\n\t\t\tGetMatrix()[Z].Normalize();\r\n\t\t\tGetMatrix()[Y] = mWallNormal;\r\n\t\t\tGetMatrix()[X] = Mth::CrossProduct(GetMatrix()[Y], GetMatrix()[Z]);\r\n\t\t\tGetMatrix()[X].Normalize();\r\n\t\t\tResetLerpingMatrix();\r\n\r\n\t\t\t// Decide whether left or right wall-ride.\r\n\t\t\t#if 0 // old code\r\n\t\t\t// Mth::Vector Up(0.0f, 1.0f, 0.0f);\r\n\t\t\t// Mth::Vector Cross = Mth::CrossProduct(mWallNormal, Up);\r\n\t\t\t#else\r\n\t\t\tMth::Vector Cross(-mWallNormal[Z], 0.0f, mWallNormal[X], 0.0f);\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tif (Mth::DotProduct(GetVel(), Cross) < 0.0f)\r\n\t\t\t{\r\n\t\t\t\t// Let the script do any extra logic, like playing anims & stuff.\r\n\t\t\t\tFLAGEXCEPTION(CRCD(0x5de19c83, \"WallRideLeft\"));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tFLAGEXCEPTION(CRCD(0x51372712, \"WallRideRight\"));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tSetState(WALL);\r\n\r\n\t\t\t// Handle contact\t\t\t\r\n\t\t\tcheck_movable_contact();\r\n\t\t\t\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Otherwise trigger the bail script.\r\n\t\t\t// FLAGEXCEPTION(CRCD(0x2ec3c7f5, \"WallRideBail\"));\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CSkaterCorePhysicsComponent::rotate_away_from_wall ( const Mth::Vector& normal, float &turn_angle, float lerp )\r\n{\r\n\t// given a wall normal, then calculate the \"turn_angle\" to rotate the skater by and rotate the matrix and display matrix by this\r\n\t// return the angle between the skater and the wall\r\n\t// note turn_angle is passed by reference, and is altered !!!!\r\n\t\r\n\t// given m_right(dot)normal, we should be able to get a nice angle\r\n\tfloat dot_right_normal = Mth::DotProduct(GetMatrix()[X], normal);\r\n\r\n\tfloat angle = acosf(Mth::Clamp(dot_right_normal, -1.0f, 1.0f)); \t\r\n\r\n\tif (angle > Mth::PI / 2.0f)\r\n\t{\r\n\t\tangle -= Mth::PI;\r\n\t}\r\n\t\r\n\t// angle away from the wall\r\n\tturn_angle = angle * GetPhysicsFloat(CRCD(0xe07ee1a9, \"Wall_Bounce_Angle_Multiplier\")) * lerp;\r\n\t\r\n\t// Rotate the skater so he is at a slight angle to the wall, especially if we are in a right angled corner, where the skater will bounce out\r\n\r\n\tGetVel().RotateY(turn_angle);\r\n\tDUMP_VELOCITY;\r\n\tGetMatrix().RotateYLocal(turn_angle);\r\n\tm_lerping_display_matrix.RotateYLocal(turn_angle);\t   \r\n\t\r\n\treturn angle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::check_leaning_into_wall (   )\r\n{\r\n\t// If we are leaning left or right, then do a collision check in that direction, and proportional to the amount of the lean.\r\n\t// If there is a collision, then push the skater away from the wall.\r\n\t\r\n\t// First determine if we actually need to be doing this\r\n\t\r\n\t// Need to be moving at a reasonable rate\r\n\tif (GetVel().Length() > GetPhysicsFloat(CRCD(0xbc33d268, \"Skate_min_wall_lean_push_speed\"))) return;\r\n\t\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\r\n\tfloat time;\r\n\tif (control_pad.m_left.GetPressed())\r\n\t{\r\n\t\ttime = control_pad.m_left.GetPressedTime();\r\n\t}\r\n\telse if (control_pad.m_right.GetPressed())\r\n\t{\r\n\t\ttime = control_pad.m_right.GetPressedTime();\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\ttime *= 1.0f / 1000.0f;\r\n\r\n\t// Calculate the length of the vector based on how long you have held down the left or right button.  \r\n\t// (Ideally it would be tied to the animation, but this is simple, and it works)\t\r\n\tfloat min_time = GetPhysicsFloat(CRCD(0x435f0653, \"Skate_wall_lean_push_time\"));\r\n\tif (time > min_time)\r\n\t{\r\n\t\ttime = min_time;\r\n\t}\r\n\t\r\n\tif (control_pad.m_right.GetPressed())\r\n\t{\r\n\t\ttime = -time;\r\n\t}\r\n\tfloat length = time / min_time * GetPhysicsFloat(CRCD(0x4b8bab12, \"Skate_wall_lean_push_length\"));\t\r\n\r\n\t\r\n\t// Now we've got the length, and in the right direction, check for a collision\r\n\t\r\n\tm_col_start = GetPos() + GetMatrix()[Y] * GetPhysicsFloat(CRCD(0xbfbbd0af, \"Skate_wall_lean_push_height\"));\r\n\tm_col_end = m_col_start + GetMatrix()[X] * length;\r\n\tif (get_member_feeler_collision())\r\n\t{\r\n\t\r\n\t\t// see how much we are into the wall\r\n\t\tMth::Vector push = m_feeler.GetPoint() - m_col_end;\r\n\t\t\r\n\t\t// Only push directly out from the wall (like the upwards collision, otherwise we get pushed back)\r\n\t\tMth::Vector normal = m_feeler.GetNormal();\r\n\t\tpush.ProjectToNormal(normal);\r\n\t\t\r\n\t\tm_col_start = GetPos() + GetMatrix()[Y];\r\n\t\tm_col_end = m_col_start + push;\r\n\t\tif (!get_member_feeler_collision())\r\n\t\t{\r\n\t\t\t// just move him, might put him 1 inch above the ground, but regular physics should snap him down\r\n\t\t\tGetPos() = m_col_end - GetMatrix()[Y];\r\n\t\t\tDUMP_POSITION;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::flip_if_skating_backwards (   )\r\n{\t\r\n\t// if sufficient speed, and facing backwards\r\n\tif (!GetFlag(IS_BAILING)\r\n\t\t&& !GetFlag(SKITCHING)\t\t// if skitching, probably just car turning a slow sharp corner\r\n\t\t&& !is_braking()\r\n\t\t&& Mth::DotProduct(GetVel(), GetMatrix()[Z]) < 0.0f\r\n\t\t&& GetVel().LengthSqr() > Mth::Sqr(GetPhysicsFloat(CRCD(0x2bf71eeb, \"Skater_Flip_Speed\")))\r\n\t\t)\r\n\t{\r\n\t\t// flip Z and X, to rotate 180 degrees about y\r\n\t\tGetMatrix()[Z] = -GetMatrix()[Z];\r\n\t\tGetMatrix()[X] = -GetMatrix()[X];\r\n\t\tm_lerping_display_matrix[Z] = -m_lerping_display_matrix[Z];\r\n\t\tm_lerping_display_matrix[X] = -m_lerping_display_matrix[X];\r\n\r\n\t\t// Dan: we can no longer flip mid animation\r\n\t\t/*\r\n\t\tCSkaterFlipAndRotateComponent* p_flip_and_rotate_component = GetSkaterFlipAndRotateComponentFromObject(GetObject());\r\n\t\tDbg_Assert(p_flip_and_rotate_component);\r\n\t\tp_flip_and_rotate_component->ToggleFlipState();\r\n\t\t*/\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::maybe_flag_ollie_exception (   )\r\n{\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (GetFlag(TENSE) && Script::GetInteger(\"TurboOllie\"))\r\n\t{\r\n\t\tm_tense_time = GetFlagElapsedTime(TENSE);\r\n\t\tSetFlagFalse(TENSE);\r\n\t\tFLAGEXCEPTION(CRCD(0x8ffefb28, \"Ollied\"));\r\n\t\treturn true;\r\n\t}\r\n\t#endif\r\n\t\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\r\n\tif (GetFlag(TENSE) && !control_pad.m_x.GetPressed())\r\n\t{\r\n\t\t// Remember the tense time, cause it will be needed when the Jump script command executes.\r\n\t\tm_tense_time = GetFlagElapsedTime(TENSE);\r\n\t\t\r\n\t\tSetFlagFalse(TENSE);\r\n\t\t\r\n\t\tcontrol_pad.m_x.ClearRelease();\r\n\t\t\r\n\t\tFLAGEXCEPTION(CRCD(0x8ffefb28, \"Ollied\"));\r\n\t\t\r\n\t\treturn true;\r\n\t}\t\r\n\r\n\treturn false;\r\n}  \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n \r\nvoid CSkaterCorePhysicsComponent::maybe_skitch (   )\r\n{\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\r\n\tif (GetFlag(SKITCHING) || !SKITCH_BUTTON || GetState() != GROUND) return;\r\n\t\r\n\t// Find the nearest skitch point.\r\n\tMth::Vector closest_pos;\r\n\tfloat closest_dist = GetPhysicsFloat(CRCD(0x2928f080, \"Skitch_Max_Distance\"));\r\n\tCCompositeObject* p_closest = NULL;\r\n\t\r\n\tfor (CSkitchComponent *p_skitch_comp = static_cast< CSkitchComponent* >(CCompositeObjectManager::Instance()->GetFirstComponentByType(CRC_SKITCH));\r\n\t\t  p_skitch_comp;\r\n\t\t  p_skitch_comp = static_cast< CSkitchComponent* >(p_skitch_comp->GetNextSameType()))\r\n\t{\r\n\t\tif (!p_skitch_comp->CanSkitch()) continue;\r\n\t\t\r\n\t\tCCompositeObject* p_composite_object = p_skitch_comp->GetObject();\r\n\t\tif (p_composite_object == GetObject()) continue;\r\n\t\t\r\n\t\tMth::Vector\tskitch_point(0.0f, 0.0f, 0.0f);\r\n\t\tint skitch_index = p_skitch_comp->GetNearestSkitchPoint(&skitch_point, GetPos());\r\n\t\tif (skitch_index == -1) continue;\r\n\t\t\r\n\t\tMth::Vector line_to = skitch_point - GetPos();\r\n\t\tfloat dist_to = line_to.Length();\r\n\t\tif ( dist_to < closest_dist)\r\n\t\t{\r\n\t\t\tclosest_dist = dist_to;\r\n\t\t\tp_closest = p_composite_object;\r\n\t\t\tclosest_pos\t= skitch_point;\r\n\t\t\tm_skitch_index = skitch_index;\r\n\t\t}\r\n\t}\r\n\r\n\tif (p_closest)\r\n\t{\r\n\t\t// Clear any triggers, so old L1/R1 presses don't affect us.\r\n\t\tcontrol_pad.m_L1.ClearTrigger();\r\n\t\tcontrol_pad.m_R1.ClearTrigger();\r\n\t\tmp_skitch_object = p_closest;\r\n\r\n\t\tFLAGEXCEPTION(CRCD(0x2f184eb1, \"Skitched\"));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::do_in_air_physics (   )\r\n{\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\r\n\t// Acceleration is re-calculated every frame\r\n\t// here it is just set to the air gravity \r\n\t// there are generally no other forces that we would use in the air\r\n\r\n\tMth::Vector acc(0.0f, get_air_gravity(), 0.0f);\r\n\r\n\tSetFlagFalse(LAST_POLY_WAS_VERT);\r\n\t\r\n\t// disallow acid drops before this frame's breaking of vert air\r\n\tif (GetFlag(VERT_AIR) || GetFlag(SPINE_PHYSICS) || GetFlag(IN_ACID_DROP) || GetFlag(IS_BAILING))\r\n\t{\r\n\t\tSetFlagTrue(AIR_ACID_DROP_DISALLOWED);\r\n\t}\r\n\t\r\n\t///////////////////////////////////////////////////////////////////////////////\r\n\t// Adjust orientation before we do any movement\r\n\t// in the air the orientation is independent of the velocity but it will affect the collision checks we do (left/right/forwards/up)\r\n\r\n\thandle_air_rotation(); \t\t// rotate left/right (spinning by holding left/right or L1/R1)\r\n\t\r\n\thandle_air_lean();\t\t\t// lean forwards backwards (by hold up/down) also handles spine leans\r\n\t\r\n\thandle_transfer_slerping();\t// during acid drops, we slerp to our required orientation\r\n\t\r\n\tif (GetFlag(IN_RECOVERY) || VERT_RECOVERY_BUTTONS)\r\n\t{\r\n\t\t// no control here, except for the VERT_RECOVERY_BUTTONS, above \r\n\t\thandle_air_vert_recovery();\t// recovering from going off the end of a vert polygon\r\n\t}\r\n\t\r\n\t// Upright if not vert, and not doing a spine transfer\r\n\tif (!GetFlag(VERT_AIR) && !GetFlag(SPINE_PHYSICS) && !mp_rotate_component->IsApplyingRotation(X) && !mp_rotate_component->IsApplyingRotation(Z))\r\n\t{\r\n\t\trotate_upright();\r\n\t}\t\t\r\n\r\n\t// end of adjusting orientation in air\r\n\t////////////////////////////////////////////////////////////////////\r\n\t\r\n\t//////////////////////////////////////////////////////////////////////////////\r\n\t// Apply special friction even in the air\r\n\t\r\n\tif (m_special_friction_duration != 0.0f)\r\n\t{\r\n\t\tapply_rolling_friction();\r\n\t}\r\n\t\r\n\t// end of friction\r\n\t////////////////////////////////////////////////////////////////////////////\r\n\r\n\t///////////////////////////////////////////////////////////////////////////////\r\n\t// Calculate what velocity to use\r\n\t// generally this is just the stored m_vel, but if we are doing\r\n\t// a spine transfer\twe a\tdd in m_spine_vel\r\n\t// (note, we also update the state of the spine transfer here, \r\n\t// perhaps that would be better done elsewhere)\r\n\t\r\n\tMth::Vector vel = GetVel();\r\n\t\r\n\t///////////////////////////////////////////////////////////////////////////\r\n\r\n\tif (GetFlag(SPINE_PHYSICS))\r\n\t{\r\n\t\t// this check is only valid if we are not in contact with a moving object\t\t\r\n\t\tif (vel[Y] < 0.0f && GetPos()[Y] < m_transfer_target_height)\t// just check if we have dropped below the target height\t\t\r\n\t\t{\r\n\t\t\t// if (Mth::Abs(mp_state_component->m_spine_vel.Length() - 0.1f) > 1.0f)\r\n\t\t\t// {\r\n\t\t\t\t// Gfx::AddDebugStar(GetPos(), 24, GREEN, 0);\r\n\t\t\t// }\r\n\t\t\tmp_state_component->m_spine_vel.Normalize(0.1f); // make spine velocity very small, but still there, so camera works\r\n\t\t}\t\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tvel += mp_state_component->m_spine_vel;\r\n\t\t}\r\n\t}\r\n\r\n\t///////////////////////////////////////////////////\r\n\t// calculate contact movement\r\n\t// If the skater is in contact with an object, then his velocity (m_vel) is considered to be local to that object, so here we have to add in the\r\n\t// movement of the object from the last frame; we also account for rotation here, in the call to mp_movable_contact_component->UpdateContact\r\n\r\n\tMth::Vector\tcontact_movement;\r\n\tcontact_movement.Set(0.0f, 0.0f, 0.0f);\r\n\r\n\t// if we are in contact with something, then factor in that \"movement\"\r\n\tif (mp_movable_contact_component->UpdateContact(GetPos()))\r\n\t{\r\n\t\tcontact_movement = mp_movable_contact_component->GetContact()->GetMovement();\r\n\t}\r\n\r\n\t// end of calculating contact movment\r\n\t/////////////////////////////////////////////////////////////////////////\r\n\r\n\t///////////////////////////////////////////////////////////////\r\n\t// Update position\r\n\t\r\n\t// Update position using correct equations of motion (S = ut + 0.5at^2)\r\n\tGetPos() += vel * m_frame_length + acc * (0.5f * m_frame_length * m_frame_length);\r\n\tDUMP_POSITION;\r\n\t\r\n\t// add in movement due to contact\r\n\tGetPos() += contact_movement;\r\n\tDUMP_POSITION;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (Script::GetInteger(CRCD(0x3ae85eef, \"skater_trails\")))\r\n\t{\r\n\t\tif (GetFlag(SPINE_PHYSICS))\r\n\t\t{\r\n\t\t\tGfx::AddDebugLine(GetPos(), GetOldPos(), RED, 0, 0);\r\n\t\t}\r\n\t\telse if (GetFlag(VERT_AIR))\r\n\t\t{\r\n\t\t\tGfx::AddDebugLine(GetPos(), GetOldPos(), YELLOW, 0, 0);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tGfx::AddDebugLine(GetPos(), GetOldPos(), BLUE, 0, 0);\r\n\t\t}\r\n\t}\r\n\t#endif\r\n\t\r\n\t//\r\n\t// end updating position\r\n\t//////////////////////////////////////////////////////////////\r\n\t\r\n\t\r\n\t/////////////////////////////////////////////////////////////////\r\n\t// update velocity\r\n\t//\r\n\t\r\n\t// Update Velocity in air\t\r\n\tGetVel() += acc * m_frame_length;\r\n\tDUMP_VELOCITY;\r\n\t\r\n\t//\r\n\t// end updating velocity\r\n\t/////////////////////////////////////////////////////////////////\r\n\r\n\t/////////////////////////////////////////////////////////////////\r\n\t// Handle trying to break VERT\t\r\n\t//\t\r\n\t\r\n\tif (GetFlag(CAN_BREAK_VERT))\r\n\t{\r\n\t\tif (GetFlag(TRACKING_VERT) && GetFlag(VERT_AIR))\r\n\t\t{\r\n\t\t\t// might want to check how long we've been in the air before allowing this\r\n\t\t\t// also don't want to do it if we've been doing tricks and stuff \r\n\t\t\t\r\n\t\t\t// first of all, check if there is a collision beneath my feet\r\n\t\t\tm_col_start = GetPos() + GetMatrix()[Y] * 1.0f;\t\t// bit above the feet\r\n\t\t\tm_col_end = GetPos() + GetMatrix()[Y] * -23.0f;\r\n\t\t\tif (!get_member_feeler_collision())\r\n\t\t\t{\r\n\t\t\t\tmaybe_break_vert();\r\n\t\t\t\t\r\n\t\t\t\t// if we did not break vert now, then only allow us to break vert later if we've been tapping the \"up\" button\r\n\t\t\t\t// this is indicated by us having RELEASED or Pressed in the last few ticks\r\n\t\t\t\tif (static_cast< int >(control_pad.m_up.GetReleasedTime()) > GetPhysicsInt(CRCD(0x6bb5b751, \"Skater_vert_active_up_time\"))\r\n\t\t\t\t\t&& static_cast< int >(control_pad.m_up.GetPressedTime()) > GetPhysicsInt(CRCD(0x6bb5b751, \"Skater_vert_active_up_time\")))\r\n\t\t\t\t{\r\n\t\t\t\t\t// \"UP\" was not pressed any time recently, so don't let us break late\r\n\t\t\t\t\tSetFlagFalse(CAN_BREAK_VERT);\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\t \r\n\t\t   \r\n\t\t// Allow us to break vert polys for a while after we ge onto them\r\n\t\t// to make it more robust\r\n\t\t// Essentially lets CAN_BREAK_VERT flag expire....\r\n\t\tif (static_cast< int >(Tmr::ElapsedTime(GetFlagTime(CAN_BREAK_VERT))) > GetPhysicsInt(CRCD(0x26495947, \"Skater_Vert_Allow_break_Time\")))\r\n\t\t{\r\n\t\t\tSetFlagFalse(CAN_BREAK_VERT);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// We are flagged as not being able to break vert\r\n\t\t// however, we still want to be able to do this at any time on the up journey\r\n\t\t// if we try break the spine\r\n\t\tif (GetFlag(VERT_AIR) && BREAK_SPINE_BUTTONS && !GetFlag(SPINE_PHYSICS) && GetVel()[Y] > 0.0f)\r\n\t\t{\r\n\t\t\tmaybe_break_vert();\r\n\t\t}\r\n\t\r\n\t}\r\n\t\r\n\t//\r\n\t// End of Handling breaking Vert\r\n\t////////////////////////////////////////\r\n\t\r\n\tif (!mp_movable_contact_component->HaveContact())\r\n\t{\r\n\t\t\r\n\t\t//////////////////////////////////////////////////////////////////////\r\n\t\t// Now update the tracking position before we do a collision check\t   \r\n\t\t// \"Tracking\" is used when we are \"vert\" (moving in a vertical plane through the air above a quarterpipe), to track the ground directly\r\n\t\t// benath us, and if the QP bends, to move the skater appropiately so he can catch vert air along bent QPs, and round corners. \t\t \r\n\t\t\r\n\t\tif (GetFlag(TRACKING_VERT) && GetFlag(VERT_AIR))\r\n\t\t{\r\n\t\t\tm_col_start[X] = GetPos()[X];\r\n\t\t\tm_col_start[Y] = m_vert_pos[Y];\r\n\t\t\tm_col_start[Z] = GetPos()[Z];\r\n\t\r\n\t\t\tm_col_end = m_col_start;\r\n\t\t\t\r\n\t\t\tm_col_start += m_vert_normal * 30;\t\t\t// Away from face\r\n\t\t\tm_col_end -= m_vert_normal * 30;\t\t\t// into face\r\n\t\r\n\t\t\t// Now see if there is a collision, and track it if so\r\n\t\r\n\t\t\t// First we try an above this position\r\n\t\t\t// raising us up by m_vert_upstep\r\n\t\t\t// which starts at 6 inches, and is halved down until\r\n\t\t\t// less than half an inch, at which point we stop trying to move up\r\n\t\r\n\t\t\tbool collision;\r\n\t\r\n\t\t\tif (m_vert_upstep > 0.5f)\r\n\t\t\t{\r\n\t\t\t\tm_col_start[Y] += m_vert_upstep;\r\n\t\t\t\tm_col_end[Y] += m_vert_upstep;\r\n\t\t\t\t// Only check for vert polys, ignore collision info\r\n\t\t\t\tcollision = get_member_feeler_collision(0, mFD_VERT);  \r\n\t\t\r\n\t\t\t\t// If we did not find a collision six inches above, then check back at the old height\r\n\t\t\t\tif (!collision)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_col_start[Y] -= m_vert_upstep;\r\n\t\t\t\t\tm_col_end[Y] -= m_vert_upstep;\t\r\n\t\t\t\t\tm_vert_upstep *= 1.0f / 2.0f;\t\t\t// binary search will zoom in on the edge\t\t\r\n\t\t\t\t\tcollision = get_member_feeler_collision(0, mFD_VERT);  \r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tcollision = get_member_feeler_collision(0, mFD_VERT);  \t\r\n\t\t\t}\r\n\t\r\n\t\r\n\t\t\tif (!collision)\r\n\t\t\t{\r\n\t\t\t\t// there is no collision, which usually mean we have gone off the end of a qp but might mean the tracking point has drifted off the top\r\n\t\t\t\t// of the very polygon (it might not be exactly horizontal), so try tracking down up to 30 inches to see if we can find it again\r\n\t\t\t\tfor (int i = 0; i < 10; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_col_start[Y] -= 3.0f;\r\n\t\t\t\t\tm_col_end[Y] -= 3.0f;\r\n\t\t\t\t\tcollision = get_member_feeler_collision(0, mFD_VERT);  \r\n\t\t\t\t\tif (collision)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// need to store new m_vert_pos\r\n\t\t\t\t\t\t// as code below does not generally allow us to go below it\r\n\t\t\t\t\t\tm_vert_pos[Y] = m_feeler.GetPoint()[Y];\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\r\n\t\r\n\t\t\t// Dot product in the XZ plane is the angle between them\t\t\t\r\n\t\t\tfloat change_dot = sqrtf(\r\n\t\t\t\tm_vert_normal[X] * m_feeler.GetNormal()[X] + m_vert_normal[Z] * m_feeler.GetNormal()[Z]\r\n\t\t\t);\r\n\t\t\t\r\n\t\t\t// the dot check is a fix for sharp corners, nearly are right angles, TT#438\r\n\t\t\tif (collision && change_dot > 0.02f)\r\n\t\t\t{\r\n\t\t\t\t// let's just track it simple for now\r\n\t\t\t\tMth::Vector track_point = m_feeler.GetPoint();\r\n\t\r\n\t\t\t\t// This is a bit of a patch\r\n\t\t\t\t// basically clamp the tracking point at the hihgest level it has reached, that way we can never \"slip\" down a slope\r\n\t\t\t\t// which the rest of the physics makes you do, for reasons best explained with a diagram\r\n\t\t\t\tif (m_vert_pos[Y] > track_point[Y])  \r\n\t\t\t\t{\r\n\t\t\t\t\ttrack_point[Y] = m_vert_pos[Y];\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// keep vert pos updated (only used for height)\r\n\t\t\t\tm_vert_pos = track_point;\r\n\t\t\t\t\r\n\t\t\t\tGetPos()[X] = track_point[X];\t\r\n\t\t\t\tGetPos()[Z] = track_point[Z];\t\r\n\t\t\t\tm_vert_normal = m_feeler.GetNormal();\r\n\t\r\n\t\t\t\t// offset the jumper away from the plane\r\n\t\t\t\tGetPos() += m_vert_normal * (GetPhysicsFloat(CRCD(0x78384871, \"Physics_Vert_Push_Out\")));\r\n\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t\r\n\t\t\t\t// The normal we might be tracking might not be vert, so need to adjust it so it is fully horizontal\r\n\t\t\t\t// it should never be fully horizontal (which would cause it to implode\t\t\t\t\t\t\t\t\t\r\n\t\t\t\tMth::Vector\tflat_normal = m_vert_normal;\r\n\t\t\t\tflat_normal[Y] = 0.0f;\r\n\t\t\t\tflat_normal.Normalize();\r\n\t\t\t\t\r\n\t\t\t\t// adjust the orientation to match the plane\r\n\t\t\t\tnew_normal(flat_normal);\r\n\t\t\t\t\r\n\t\t\t\t// now velocity\r\n\t\t\t\tGetVel().RotateToPlane(flat_normal);\r\n\t\t\t} \r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tSetFlagFalse(TRACKING_VERT);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t//\r\n\t// End of updating tracking\r\n\t////////////////////////////////////////////////////////////////////////////////////////\t\r\n    \r\n\t///////////////////////////////////////////////////////\r\n\t// Adjust the normal while in the air\t\r\n\t//\r\n\t\r\n\t// When on an air poly, we have the usual drifting of the UP vector to smooth out changes in the normal\r\n\t// (note, we can be in VERT_AIR, but also SPINE_PHYSICS, in whcih case the orientation is controled by the \"lean\" routine\r\n\t// which is leaning the skater forward, so he comes down on the opposing face)\r\n\tif (GetFlag(VERT_AIR) && !GetFlag(SPINE_PHYSICS)\r\n\t\t&& !mp_rotate_component->IsApplyingRotation(X) && !mp_rotate_component->IsApplyingRotation(Z))\r\n\t{\r\n\t\tadjust_normal();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// otherwise, the matrix is same for display and physics\r\n\t\tResetLerpingMatrix();\r\n\t}\r\n\t\r\n\t//\r\n\t// End of adjusting normal\r\n\t//////////////////////////////////////////////////////////\r\n\r\n\r\n\t///////////////////////////////////////////////////////////\r\n\t// Handle any collisions resultant from our movement\r\n\t// remember at this point m_pos is the new position\r\n\t// and we might have gone through a wall\r\n\t\r\n\t// here again, we are factoring in the contact_movement to the start position\t\t\t\t\t\t\t\t\t\t\t \r\n\t// We check if there is anything in font of us\r\n\tbool snapped_up = handle_forward_collision_in_air(GetOldPos() + contact_movement);\t\t\t\t\t\r\n\r\n\t// If we are now in the WALL (Wallride) state, then just return\t\r\n\tif (GetState() == WALL || GetState() == WALLPLANT)\r\n\t{\r\n\t\t// Maybe call DoWallPhysics() to avoid a glitch? Maybe not, cos GetOldPos() will be wrong ?\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\t// check for actual movement collision (along the full line of travel)\r\n\t// note we factor in the contact_movement here which effectivly ignores it\r\n\t// so contact movement could possibly drag us through a solid object\r\n\t// if this is a problem, then we need to add another collision check, just for the contact movement\r\n\tm_col_start = GetOldPos() + contact_movement;\r\n\tm_col_end = GetPos();\r\n\t\t\t\t\t\t\t\t\r\n\tif (!snapped_up && get_member_feeler_collision())\r\n\t{\r\n\t\tbool hit_vertical = m_feeler.GetNormal()[Y] < 0.1f;\r\n\t\t\r\n\t\tif (check_for_air_snap_up(GetOldPos() + contact_movement) && (GetVel()[Y] > 10.0f || hit_vertical) && mp_movable_contact_component->GetTimeSinceLastLostContact() > 500)\r\n\t\t{\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tMth::Vector normal = m_feeler.GetNormal();\r\n\t\t\t\t\r\n\t\t\t// set our position (the point of contact) to be that point we just found\r\n\t\t\tGetPos() = m_feeler.GetPoint();\r\n\t\t\t\r\n\t\t\t// Move point up one inch to avoid dropping through geometry with something below it (like canada blades, and park editor stuff)\r\n\t\t\tGetPos() += normal;\r\n\t\t\tDUMP_POSITION;\r\n\t\t\t\r\n\t\t\tif (m_col_flag_skatable)\r\n\t\t\t{\r\n\t\t\t\t//////////////////////////////////////////////////////////////////////////\r\n\t\t\t\t// handle landing on the ground\r\n\t\t\t\t// Collided with a skatable face!! yay, let's stick to it!\r\n\t\t\t\t\r\n\t\t\t\tSetState(GROUND);\r\n\t\t\t\tcheck_movable_contact();\r\n\t\t\t\t\r\n\t\t\t\t// Used by the LandedFromVert script command.\r\n\t\t\t\t// landing from a spine transfer is considered to be the same as landing from vert\r\n\t\t\t\tif (GetFlag(VERT_AIR) || GetFlag(SPINE_PHYSICS))\r\n\t\t\t\t{\r\n\t\t\t\t\t// Note: Not setting it to false if the VERT_AIR flag is not set.\r\n\t\t\t\t\t// This is because sometimes Scott wants to force the mLandedFromVert to be on from in script. Don't want landing to override that.\r\n\t\t\t\t\t// mLandedFromVert never gets reset by the C-code, only by the ResetLandedFromVert script command.\r\n\t\t\t\t\tmLandedFromVert = true;\r\n\t\t\t\t\t\r\n\t \t\t\t\t// This flag however cannot be cleared by script\r\n\t\t\t\t\t// Added this flag for use by ClearPanel_Landed, because mLandedFromVert is false at that point even if landing from vert,\r\n\t\t\t\t\t// due to being cleared by script.\r\n\t\t\t\t\tm_true_landed_from_vert = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_true_landed_from_vert = false;\r\n\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\tmLandedFromSpine = GetFlag(SPINE_PHYSICS);\r\n\r\n\t\t\t\tset_terrain(m_feeler.GetTerrain());\r\n\t\t\t\t\r\n\t\t\t\tmp_sound_component->PlayLandSound(GetObject()->GetVel().Length() / GetSkater()->GetScriptedStat(CRCD(0xcc5f87aa, \"Skater_Max_Max_Speed_Stat\")), mp_state_component->m_terrain);\r\n\r\n\t\t\t\tif (!mp_trick_component->GraffitiTrickStarted())\r\n\t\t\t\t{\r\n\t\t\t\t\t// clear the graffiti trick buffer if we're moving to a new world sector, but haven't started our trick yet...\r\n\t\t\t\t\tmp_trick_component->SetGraffitiTrickStarted(false);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tset_last_ground_feeler(m_feeler);\r\n\t\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_LAND_ON, m_last_ground_feeler);\r\n\r\n\t\t\t\t// Now, we landed, and triggered an event, which might have reset us, so we should possibly abort here if we were restarted\r\n\t\t\t\tif (mp_physics_control_component->HaveBeenReset())\r\n\t\t\t\t{\r\n\t\t\t\t\t// K: I added this here to be consistent with the above change on 7 Mar (see above comment)\r\n\t\t\t\t\t// Need it though?\r\n\t\t\t\t\tFLAGEXCEPTION(CRCD(0x532b16ef, \"Landed\"));\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\tif (!m_true_landed_from_vert \t\t\t// not if coming down off vert\r\n\t\t\t\t\t&& !mLandedFromVert\t\t\t\t// and not pretending to (like jumping out of a lip trick)\r\n\t\t\t\t\t&& GetVel()[X] == 0.0f\r\n\t\t\t\t\t&& GetVel()[Z] == 0.0f \r\n\t\t\t\t\t&& control_pad.m_down.GetPressed())\r\n\t\t\t\t{\r\n\t\t\t\t\t// we had just jumped straight up, and are braking, and not on vert\r\n\t\t\t\t\tGetVel()[Y] = 0.0f;\t\r\n\t\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!GetFlag(SPINE_PHYSICS))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tGetVel().ProjectToPlane(m_feeler.GetNormal());\t   \t// kill vel that is perpendicular to normal\r\n\t\t\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// special landing from transfers to prevent speed loss\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tMth::Vector landing_vel = GetVel();\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// rotate all velocity to the facing direction\r\n\t\t\t\t\t\tGetVel().RotateToNormal(m_transfer_goal_facing);\r\n\t\t\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// now, rotate into the plane instead of projecting (actually, m_transfer_goal_facing should already be in the plane)\r\n\t\t\t\t\t\tGetVel().RotateToPlane(m_feeler.GetNormal());\r\n\t\t\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// test what velocity we will have once the ground physics removes sideways velocity\r\n\t\t\t\t\t\tMth::Vector test_vel = GetVel();\r\n\t\t\t\t\t\tremove_sideways_velocity(test_vel);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// if we'd be moving upwards (this can occur because sometimes an acid drop's goal facing is along a vert, not down it; and thus,\r\n\t\t\t\t\t\t// a slight upwards rotation means that the skater will land pointing up and immediately hop off the vert; this looks very\r\n\t\t\t\t\t\t// bizzare, so we prevent it here)\r\n\t\t\t\t\t\tif (test_vel[Y] > 0.0f)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// use a standard landing instead\r\n\t\t\t\t\t\t\tGetVel() = landing_vel;\r\n\t\t\t\t\t\t\tGetVel().ProjectToPlane(m_feeler.GetNormal());\r\n\t\t\t\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif (GetVel().LengthSqr() < Mth::Sqr(Script::GetFloat(CRCD(0x59484878, \"Physics_Acid_Drop_Min_Land_Speed\"))))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tGetVel().Normalize(Script::GetFloat(CRCD(0x59484878, \"Physics_Acid_Drop_Min_Land_Speed\")));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tGetVel().ZeroIfShorterThan(10.0f);\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tSetFlagFalse(VERT_AIR);\r\n\t\t\t\t\r\n\t\t\t\tm_display_normal = m_feeler.GetNormal();\r\n\t\t\t\tm_current_normal = m_display_normal;\r\n\t\t\t\tm_last_display_normal = m_display_normal;\r\n\t\t\t\t\r\n\t\t\t\tGetMatrix()[Y] = m_display_normal;\r\n\t\t\t\tGetMatrix().OrthoNormalizeAbout(Y);   \r\n\t\t\t\tResetLerpingMatrix();\r\n\r\n\t\t\t\t// Flagging the exceptions needs to be the last thing done, as the script for the\r\n\t\t\t\t// excpetion is executed immediately, and might need some of the above values\r\n\t\t\t\t// Like, PitchGreaterThan requires m_last_display_matrix to be correct (as calculated above)\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\tFLAGEXCEPTION(CRCD(0x532b16ef, \"Landed\"));\r\n\t\t\t\t\r\n\t\t\t\treturn;\r\n\t\t\t\t \t\r\n\t\t\t\t//\r\n\t\t\t\t// end of handling landing\r\n\t\t\t\t//////////////////////////////////////////////////////////////\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// it's a wall, bounce off it\r\n\t\t\t\tGetVel().RotateToPlane(normal);\t\t\t\r\n\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\tGetMatrix()[Z].RotateToPlane(normal);\r\n\t\t\t\tGetMatrix().OrthoNormalizeAbout(Z);\r\n\t\t\t\tResetLerpingMatrix();\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t// Bit of a patach here to move the skater away from the wall\r\n\t\t\t\tGetPos() += normal * GetPhysicsFloat(CRCD(0x23410c14, \"Skater_Min_Distance_To_Wall\"));\r\n\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t\r\n\t\t\t\t// no acid drops after an in-air collision\r\n\t\t\t\tSetFlagTrue(AIR_ACID_DROP_DISALLOWED);\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// No forward collision was found, so nothing to do   \r\n\t\t\r\n\t\t// so do another check to push me away from walls, will also need a wallride check here \r\n\t\t#ifdef\t\tSTICKY_WALLRIDES\r\n\t\tif (!GetFlag(VERT_AIR))\r\n\t\t{\r\n\t\t\t// check if we are too close to a wall, and pop us out and away\t\t\r\n\t\t\tcheck_side_collisions();\r\n\t\t}\r\n\t\t#endif\r\n\t}\r\n\t\r\n\t// Push skater down from any roof he might now be under\t\t\t\r\n\tif (handle_upward_collision_in_air())\r\n\t{\r\n\t\t// no acid drops after an in-air collision\r\n\t\tSetFlagTrue(AIR_ACID_DROP_DISALLOWED);\r\n\t}\r\n\t\r\n\t//\r\n\t// End of handling collisions\r\n\t/////////////////////////////////////////////////////////////////////////////////////////////////\r\n\t\r\n\t// If we've triggered a jump, then do the jump (note, same as jump from ground for now, might want to make it different) \t\r\n\tmaybe_flag_ollie_exception();\r\n\t\r\n\t// if in standard vanilla air, check for acid drop\r\n    if (!GetFlag(AIR_ACID_DROP_DISALLOWED) && BREAK_SPINE_BUTTONS)\r\n\t{\r\n\t\tbool count_as_skate_off_edge = m_went_airborne_time > m_last_jump_time_stamp\r\n\t\t\t&& Tmr::ElapsedTime(m_went_airborne_time) < 250;\r\n\t\t\r\n\t\tSAcidDropData acid_drop_data;\r\n\t\tif (maybe_acid_drop(count_as_skate_off_edge, GetPos(), GetOldPos(), GetVel(), acid_drop_data))\r\n\t\t{\r\n\t\t\tenter_acid_drop(acid_drop_data);\r\n\t\t}\r\n\t}\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::handle_air_rotation (   )\r\n{\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\t\t \r\n\r\n\t//////////////////////////////////////////////////////////////////////////////////\r\n\t// Part 1 - Decide on what spin to do, based on the controls\r\n\r\n\tif (mNoSpin) return;\r\n\t\r\n\t// IF doing a spine transfer, then no auto turning....\t\r\n\tif (GetFlag(SPINE_PHYSICS))\r\n\t{\r\n\t\tSetFlagFalse(AUTOTURN);\r\n\t}\r\n\t\r\n\tint time = 0; \t\t\t\r\n\tfloat rot = 0.0f;\r\n\tfloat no_time = 0.0f;\r\n\tfloat ramp_time = 0.0f;\r\n\r\n\t// if (!USE_BIKE_PHYSICS)\r\n\t// {\r\n\t\tif (m_spin_taps)\r\n\t\t{\r\n\t\t\tif (control_pad.m_L1.GetTriggered())\r\n\t\t\t{\r\n\t\t\t\tcontrol_pad.m_L1.ClearTrigger();\r\n\t\t\t\tif (!control_pad.m_R1.GetPressed())\t \t// ignore it if R1 is pressed\r\n\t\t\t\t{\r\n\t\t\t\t\tm_tap_turns += Mth::PI;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (control_pad.m_R1.GetTriggered())\r\n\t\t\t{\r\n\t\t\t\tcontrol_pad.m_R1.ClearTrigger();\r\n\t\t\t\tif (!control_pad.m_L1.GetPressed())\t \t// ignore it if L1 is pressed\r\n\t\t\t\t{\r\n\t\t\t\t\tm_tap_turns -= Mth::PI;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\r\n\t\t\tif (m_tap_turns != 0.0f)\r\n\t\t\t{\r\n\t\t\t\ttime = 1;\r\n\t\t\t\tfloat turn_amount = Mth::Sgn(m_tap_turns) * GetSkater()->GetScriptedStat(CRCD(0xf7a2acc1, \"Physics_air_tap_turn_speed_stat\"));\r\n\t\t\t\tif (Mth::Abs(turn_amount * m_frame_length) > Mth::Abs(m_tap_turns))\r\n\t\t\t\t{\r\n\t\t\t\t\tm_tap_turns = 0.0f;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_tap_turns -= turn_amount * m_frame_length;\r\n\t\t\t\t}\t\r\n\t\t\t\trot = turn_amount;\r\n\t\t\t}\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (control_pad.m_L1.GetPressed() && !control_pad.m_R1.GetPressed())\r\n\t\t\t{\r\n\t\t\t\trot = GetSkater()->GetScriptedStat(CRCD(0x4957db43, \"Physics_air_rotation_stat\"));\t\r\n\t\t\t\ttime = 1;\r\n\t\t\t\tif (control_pad.m_L1.GetPressedTime() > GetPhysicsFloat(CRCD(0xabdd3395, \"skater_autoturn_cancel_time\")))\r\n\t\t\t\t{\r\n\t\t\t\t\tSetFlagFalse(AUTOTURN);\r\n\t\t\t\t}\r\n\t\t\t}\t\t\t\t\t\t\t\t\r\n\t\t\t\r\n\t\t\tif (control_pad.m_R1.GetPressed() && !control_pad.m_L1.GetPressed())\r\n\t\t\t{\r\n\t\t\t\trot = -GetSkater()->GetScriptedStat(CRCD(0x4957db43, \"Physics_air_rotation_stat\"));\r\n\t\t\t\ttime = 1;\r\n\t\t\t\tif (control_pad.m_R1.GetPressedTime() > GetPhysicsFloat(CRCD(0xabdd3395, \"skater_autoturn_cancel_time\")))\r\n\t\t\t\t{\r\n\t\t\t\t\tSetFlagFalse(AUTOTURN);\r\n\t\t\t\t}\r\n\t\t\t}\t\t\t\t\t\t\t\t\r\n\t\t}\r\n\t// }\r\n\t\r\n\t// if just transitioned from walking, ignore Left/Right for rotation purposes\r\n\tif (!GetFlag(NO_ORIENTATION_CONTROL))\r\n\t{\r\n\t\t// if time is set, then we just ignore the Left/Right button and take no account of the spinning ramp\r\n\t\tif (!time)\r\n\t\t{\r\n\t\t\tif (control_pad.m_left.GetPressed())\r\n\t\t\t{\r\n\t\t\t\trot = GetSkater()->GetScriptedStat(CRCD(0x4957db43, \"Physics_air_rotation_stat\"));\t\r\n\t\t\t\ttime = control_pad.m_left.GetPressedTime();\r\n\t\t\t\tif (time > GetPhysicsFloat(CRCD(0xabdd3395, \"skater_autoturn_cancel_time\")))\r\n\t\t\t\t{\r\n\t\t\t\t\tSetFlagFalse(AUTOTURN);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\r\n\t\t\tif (control_pad.m_right.GetPressed())\r\n\t\t\t{\r\n\t\t\t\trot = -GetSkater()->GetScriptedStat(CRCD(0x4957db43, \"Physics_air_rotation_stat\"));\t\r\n\t\t\t\ttime = control_pad.m_right.GetPressedTime();\r\n\t\t\t\tif (time > GetPhysicsFloat(CRCD(0xabdd3395, \"skater_autoturn_cancel_time\")))\r\n\t\t\t\t{\r\n\t\t\t\t\tSetFlagFalse(AUTOTURN);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tno_time = GetPhysicsFloat(CRCD(0xa092b2be, \"Physics_Air_No_Rotate_Time\"));\r\n\t\t\tramp_time = GetPhysicsFloat(CRCD(0x5d756349, \"Physics_Air_Ramp_Rotate_Time\"));\r\n\t\t\r\n\t\t\t// if just tapped, then no leaning for a while\r\n\t\t\tif (time <= no_time)\r\n\t\t\t{\r\n\t\t\t\trot = 0;\r\n\t\t\t}\r\n\t\t\r\n\t\t\t// if tapped enough, then ramp up to full speed over a small amount of time\t\t\r\n\t\t\tif (time < ramp_time)\r\n\t\t\t{\r\n\t\t\t\trot = rot * (time - no_time) / (ramp_time - no_time);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// if we are not rotating by hand, then might want to auto-turn\t\r\n\tif (!rot && GetFlag(VERT_AIR) && GetFlag(AUTOTURN))\r\n\t{\r\n\t\tfloat angle_from_vert = acosf(Mth::Clamp(GetMatrix()[Z][Y], -1.0f, 1.0f));\r\n\t\t\r\n\t\tif (angle_from_vert < Mth::DegToRad(GetPhysicsFloat(CRCD(0x61224f2e, \"skater_autoturn_vert_angle\"))))\r\n\t\t{\r\n\t\t\t// If pointing more or less straight up, then don't auto-turn\r\n\t\t\tSetFlagFalse(AUTOTURN);\t\t\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfloat angle = Mth::GetAngleAbout(GetMatrix()[Z], m_fall_line, GetMatrix()[Y]);\r\n\t\t\t\t\t\t\t\r\n\t\t\trot = Mth::Sgn(angle) * GetPhysicsFloat(CRCD(0x9db33213, \"Skater_autoturn_speed\"));\r\n\t\t\tif (Mth::Abs(rot * m_frame_length) > Mth::Abs(angle))\r\n\t\t\t{\r\n\t\t\t\t// just about done, so just turn the last bit of angle left\r\n\t\t\t\trot = angle / m_frame_length;\r\n\t\t\t\tSetFlagFalse(AUTOTURN);\r\n\t\t\t}\r\n\t\t\t#if 0 // Dan: removed as this code has no effect\r\n\t\t\ttime = 1;\t  \t\t// frig, we really don't want to start auto turn immediately\r\n\t\t\tramp_time = 0;\r\n\t\t\t#endif\r\n\t\t}\r\n\t}\r\n\t\r\n\t// End of Part 1\r\n\t//////////////////////////////////////////////////////////////////////////////////\r\n\t\r\n\tif (rot == 0.0f) return;\r\n\t\r\n\t//////////////////////////////////////////////////////////////////////////////////\r\n\t// Part 2 - Do the actual rotation\r\n\r\n\tmYAngleIncreased = rot > 0.0f;\r\n\t\t\t\r\n\trot *= m_frame_length;\r\n\tGetMatrix().RotateYLocal(rot);\t\t\t\t\r\n\tm_lerping_display_matrix.RotateYLocal(rot);\t\t\t\t\r\n\t\r\n\t// End of Part 2\r\n\t//////////////////////////////////////////////////////////////////////////////////\r\n\t\t\r\n\t\t\t\t\t\t\t   \r\n\t//////////////////////////////////////////////////////////////////////////////////\r\n\t// Part 3 - tracking rotation for the purposes of score (Spin multipliers)\t\t\t\t\t\t\t\t   \r\n\t// Keep track of the total angle spun through.\r\n\t\r\n\tmp_trick_component->mTallyAngles += Mth::RadToDeg(rot);\r\n\t\r\n\t// Set the spin.\r\n\tif (GetFlag(VERT_AIR) && !GetFlag(SPINE_PHYSICS))\r\n\t{\r\n\t\t// If in vert air, only count the spin if it is at least 360, because getting 180 is too easy.\r\n\t\tif (Mth::Abs(mp_trick_component->mTallyAngles) >= 360.0f - GetPhysicsFloat(CRCD(0x50c5cc2f, \"spin_count_slop\")) + 0.1f)\r\n\t\t{\r\n\t\t\tmp_score_component->GetScore()->UpdateSpin(mp_trick_component->mTallyAngles);\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_score_component->GetScore()->UpdateSpin(mp_trick_component->mTallyAngles);\r\n\t}\t\r\n\t\r\n\t// End of Part 3\r\n\t//////////////////////////////////////////////////////////////////////////////////\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::handle_air_lean (   )\r\n{\t\t\t\t\t\t\r\n\t// Handle leaning formward and backwards in the air\r\n\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t//////////////////////////////////////////////////////////////////////////////////\r\n\t// Spine specific lean, should be seperated out for spine physics\r\n\t// we automatically rotate forward but don't let skaters's up vector to go past horizontal \r\n\t\r\n\t// no leaning during transfers; we slerp instead\r\n\tif (GetFlag(SPINE_PHYSICS) || GetFlag(NO_ORIENTATION_CONTROL)) return;\r\n\t\r\n\t#if 0 // old transfer code\r\n\tif (GetFlag(SPINE_PHYSICS))\r\n\t{\r\n\t\tif (GetMatrix()[Y][Y] > -0.05f)\t   // if y component of up vector (the Y vector) is +ve, then we are heads up\r\n\t\t{\r\n\t\t\tfloat rot = GetSkater()->GetScriptedStat(CRCD(0x110a1742, \"Physics_spine_lean_stat\"));\r\n\t\t\t\t\r\n\t\t\tGetMatrix().Rotate(m_spine_rotate_axis, -rot*m_frame_length);\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\t#endif\r\n\t\r\n\t//\r\n\t//////////////////////////////////////////////////////////////////////////////////\r\n\t\r\n\t///////////////////////////////////////////////////////////////////////////////////\r\n\t// 1 - Control Logic\t\r\n\t//\r\n\t\r\n\t// don't even try to lean if in VERT_AIR\t\t  \r\n\tif (GetFlag(VERT_AIR)) return;\r\n\t\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\r\n\t// Don't want to lean if \"grab\" or \"kick\" pressed, as we could be doing some kind of grab trick\r\n\tif (control_pad.m_circle.GetPressed() || control_pad.m_square.GetPressed()) return;\r\n\t\r\n\tfloat rot = 0.0f;\r\n\tint time = 0;\r\n\t\r\n\tif (control_pad.m_up.GetPressed())\r\n\t{\r\n\t\trot = GetSkater()->GetScriptedStat(CRCD(0xcbfdd841, \"Physics_air_lean_stat\"));\r\n\t\ttime = control_pad.m_up.GetPressedTime();\r\n\t}\r\n\r\n\tif (control_pad.m_down.GetPressed())\r\n\t{\r\n\t\trot = -GetSkater()->GetScriptedStat(CRCD(0xcbfdd841, \"Physics_air_lean_stat\"));\t\r\n\t\ttime = control_pad.m_down.GetPressedTime();\r\n\t}\r\n\r\n\tfloat no_time = GetPhysicsFloat(CRCD(0x5f70ef46, \"Physics_Air_No_Lean_Time\"));\r\n\tfloat ramp_time = GetPhysicsFloat(CRCD(0x12cd2d14, \"Physics_Air_Ramp_Lean_Time\"));\r\n\r\n\t// if just tapped, then no rotation for a while\r\n\tif (time <= no_time) return;\r\n\t\r\n\t// if tapped enough, then ramp up to full speed over a small amount of time\t\t\r\n\tif (time < ramp_time)\r\n\t{\r\n\t\trot = rot * (time - no_time) / (ramp_time - no_time);\r\n\t}\r\n\r\n\t// end of control logic\r\n\t//////////////////////////////////////////////////////////////////////////////////\r\n\t\r\n\r\n\t//////////////////////////////////////////////////////////////////////////////////\r\n\t// air lean physics\r\n\t\r\n\tif (rot == 0.0f) return;\r\n\t\r\n\tGetMatrix().RotateXLocal(rot*m_frame_length);\t\t\t\t\r\n\tm_lerping_display_matrix.RotateXLocal(rot*m_frame_length);\t\t\t\t\r\n\t\r\n\t// end of air lean physics\r\n\t//////////////////////////////////////////////////////////////////////////////////\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::handle_transfer_slerping (   )\r\n{\r\n\t// during transfers, we slerp to our required orientation\r\n\tif (!GetFlag(SPINE_PHYSICS)) return;\r\n\t\r\n\t// we can't simply use the slerp's result vector at the skater's vector, because we need to allow the skater to rotate; instead, we apply\r\n\t// the change in the result vector each frame\r\n\t\r\n\t// increment the timer\r\n\tm_transfer_slerp_timer += m_frame_length;\r\n\t\r\n\t// calculate this frame's slerp result\r\n\tMth::Matrix transfer_slerp_current_matrix;\r\n\tm_transfer_slerper.getMatrix(\r\n\t\t&transfer_slerp_current_matrix,\r\n\t\tMth::SmoothStep(Mth::ClampMax(m_transfer_slerp_timer / m_transfer_slerp_duration, 1.0f))\r\n\t);\r\n\t\r\n\t// invert the slerp result vector from last frame\r\n\tMth::Matrix inverse_transfer_slerp_previous_matrix = m_transfer_slerp_previous_matrix;\r\n\tinverse_transfer_slerp_previous_matrix.InvertUniform();\r\n\t\r\n\t// calculate the change between the frames\r\n\tMth::Matrix transfer_slerp_delta_matrix = inverse_transfer_slerp_previous_matrix * transfer_slerp_current_matrix;\r\n\t\r\n\t// apply the change to the skater's matrix\r\n\tGetMatrix() *= transfer_slerp_delta_matrix;\r\n\tResetLerpingMatrix();\r\n\t\r\n\t// store this frame's matrix\r\n\tm_transfer_slerp_previous_matrix = transfer_slerp_current_matrix;\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::handle_air_vert_recovery (   )\r\n{\t\t\t\t\t\t   \r\n\t// recovering from going off the end of a vert polygon\t\r\n\r\n\t// don't want to recover during a transfer\r\n\tif (GetFlag(SPINE_PHYSICS)) return;\r\n\r\n\tif (GetVel()[Y] > 0.0f && mp_movable_contact_component->GetContact()) return;\r\n\t\r\n\t// right, we are in vert, but no longer tracking, so perhaps we are over flat ground?\r\n\tCFeeler\tfeeler;\r\n\tfeeler.m_start = GetPos();\r\n\tfeeler.m_end = GetPos();\r\n\tfeeler.m_end[Y] -= 500.0f;\r\n\t\r\n\t// can't find ground\r\n\tif (!feeler.GetCollision()) return;\r\n\r\n\t// still over vert poly\r\n\tif (feeler.GetFlags() & mFD_VERT) return;\r\n\t\r\n\t// still over steep ground\r\n\tif (feeler.GetNormal()[Y] < 0.2f) return;\r\n\r\n\tif (GetFlag(VERT_AIR))\r\n\t{\r\n\t\tSetFlagFalse(VERT_AIR);\r\n\t}\r\n\r\n\tSetFlagTrue(IN_RECOVERY);\r\n\r\n\t// we want to smoothly rotate the skater in the plane formed by the up vector, and the skater's up vector\r\n\t\r\n\t// got sufficently far up \r\n\tif (GetMatrix()[Y][Y] > 0.9f) return;\r\n\t\r\n\tfloat rot = GetSkater()->GetScriptedStat(CRCD(0xe7116a96,\"Physics_recover_rate_stat\"));\t\r\n\t\r\n\t// need to rotate the Y vector in the plane formed by the XZ velocity and the (0,1,0) up vector\r\n\t// (or rather, rotate it about the vector prependicular to this\r\n\t\r\n\t// get a vector perpendicular to the plane containing m_matrix[Z] and the world up \t\r\n\tMth::Vector forward = GetMatrix()[Y];\r\n\tforward[Y] = 0.0f;\r\n\tforward.Normalize();\r\n\t#if 0 // old code\r\n\t// Mth::Vector world_up(0.0f,1.0f,0.0f);\r\n\t// Mth::Vector side = Mth::CrossProduct(forward,world_up);\r\n\t#else\r\n\tMth::Vector side(-forward[Z], 0.0f, forward[X], 0.0f);\r\n\t#endif\r\n\t\r\n\tGetMatrix().Rotate(side, rot * m_frame_length);\r\n\t\r\n\tResetLerpingMatrix();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::rotate_upright (   )\r\n{\r\n\t// Attempt to upright player (sideways) while going through air\r\n\t//\r\n\t// Cannot just check angle between mUp and world_up as that would include\r\n\t// tilting forward/backward when character is already uprighted sideways\r\n\t// (and tilting forward/backward should solely be under player control).\r\n\t// Thus, should rotate about mFront only.\r\n\t//\r\n\t// Then, basically what we want to do is:\r\n\t// 1) Rotate about mFront so that mUp is in the plane of world_up and mUp.\r\n\t// 2) Pick one of CW/CCW to rotate by, such that angle between mUp and\r\n\t//    world_up is <= 90 degrees.\r\n\t//\r\n\t// As we can be off by at most 180 degrees, rotating by 5 degrees would\r\n\t// upright us in 180/5=36 frames. For 45 degrees off (more likely), we\r\n\t// would be uprighted in 45/5=9 frames.\r\n\t//\r\n\t// Your average jump is probably around 30 frames long, so try 1 degree?\r\n\t\r\n\t// If the skater's Z vector is nearly straight up or down, then \r\n\t// uprighting sideways will not look good \r\n\t// (On XBox, some innacuracy in Z causes the skater to rotate oddly during \"drop-in\" situations)\r\n\t// so, here we test for this case, and just return if so\r\n\tif (Mth::Abs(GetMatrix()[Z][Y]) > 0.95f) return;\r\n\t\r\n\t// get a vector perpendicular to the plane containing m_matrix[Z] and the world up \t\r\n\t#if 0 // old code\r\n\t// Mth::Vector v;\r\n\t// Mth::Vector world_up;\r\n\t// world_up.Set(0.0f,1.0f,0.0f);\r\n\t// v = Mth::CrossProduct(GetMatrix()[Z],world_up);\r\n\t#else\r\n\tMth::Vector v(-GetMatrix()[Z][Z], 0.0f, GetMatrix()[Z][X], 0.0f);\r\n\t#endif\r\n\r\n\t// Then get the dot product of the up vector with this \t\r\n\t// if up vector is in the same plane, then this will be zero\r\n\tfloat dot = Mth::DotProduct(GetMatrix()[Y], v);\r\n\tif (dot > 0.02f * m_frame_length * 60.0f) // prevent wobbling\r\n\t{\r\n\t\tfloat rot = Mth::DegToRad(Script::GetFloat(CRCD(0xabd57877, \"skater_upright_sideways_speed\")));\r\n\t\tGetMatrix().RotateZLocal(rot * m_frame_length);\t\t\t\t\r\n\t\tResetLerpingMatrix();\r\n\t}\r\n\telse if (dot < -0.02f * m_frame_length * 60.0f)\r\n\t{\r\n\t\tfloat rot = Mth::DegToRad(Script::GetFloat(CRCD(0xabd57877, \"skater_upright_sideways_speed\")));\r\n\t\tGetMatrix().RotateZLocal(-rot * m_frame_length);\t\t\t\t\r\n\t\tResetLerpingMatrix();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::handle_forward_collision_in_air ( const Mth::Vector &start_pos )\r\n{\r\n\t// return true if there was a collision, but we snapped up over it\r\n\t\r\n\tMth::Vector\tforward = GetPos() - start_pos;\r\n\tforward.Normalize();\t\r\n\t\r\n\tMth::Vector up_offset = GetMatrix()[Y] * GetPhysicsFloat(CRCD(0xd4205c9b, \"Skater_First_Forward_Collision_Height\"));\r\n\t\r\n\tm_col_start = start_pos + up_offset;\r\n\tm_col_end = GetPos() + up_offset + forward * GetPhysicsFloat(CRCD(0x20102726, \"Skater_First_Forward_Collision_Length\"));\r\n\t\r\n\tif (get_member_feeler_collision())\r\n\t{\r\n\t\t// we have hit something going forward\r\n\t\t// either it is a wall, and we need to bounce off it\r\n\t\t// or it is a floor, and we need to stick to it.\r\n\t\t\t\t\t\t\t \r\n\t\tMth::Vector normal = m_feeler.GetNormal();\r\n\r\n\t\tfloat dot = Mth::DotProduct(normal, m_current_normal);\r\n\t\tif (!m_col_flag_skatable || (dot < 0.8f && normal[Y] < 0.5f))\r\n\t\t{\r\n\r\n\t\t   // at this point we have hit something that is not skatable and is fairly vertical\r\n\t\t   // so we are considering if we want to bounce off it\r\n\t\t   // one possibility is that it is a low ledge\r\n\t\t   //\r\n\t\t   // so, we check for snapping up, and if we do snap up, and hit_vertical is true, then we don't bounce off the wall\r\n\t\t\t\r\n\t\t\t/*\r\n\t\t\t// View from side\r\n\t\t\t\t\t\t\t\t\t   /\r\n\t\t\t\t\t\t\t\t\t  /\t <---------- Movement of skater\r\n\t\t\t\t\t\t\t\t\t /\r\n\t\t\t\t\t\t\t\t\t/\r\n\t\t\t\t---------------+   /\r\n\t\t\t\t\t\t\t   |  /\r\n\t\t\t\t\t\t\t   | /\r\n\t\t\t\t\t\t\t   |/\r\n\t\t\t\t\t\t\t   /  <-------------  point of collision \r\n\t\t\t\t\t\t\t  /|\r\n\t\t\t\t\t\t\t / |\r\n\t\t\t\t\t\t\t/  |\r\n\t\t\t\t\t\t   /   |\r\n\t\t\t\t\t\t  /    +---------------\t <-------------- The ground\r\n\t\t\t\t\t\t /\r\n\t\t\t\t\t\t/\r\n\t\t\t\t\t   /\r\n\t\t\t\t\t  /\r\n\t\t\t\t\t /\t<------------ where we end up\r\n\t\t\t*/\r\n\t\t   \r\n\t\t\t// Need to store m_feeler, as it is corrupted by CheckForAirSnapUp\r\n\t\t\tCFeeler tmp_feeler = m_feeler;\r\n\t\t\t\r\n\t\t\tbool hit_vertical = m_feeler.GetNormal()[Y] < 0.1f;\r\n\t\t\t\r\n\t\t\t// Since this collision had the forward vector added into it, we need to temporarily add in the forward vector again\r\n\t\t\t// so we can check for snapping up; note this will result in the skater snapping forward by the length of the forward vector (currently 10\")\r\n\t\t\t// whenever we snap up in this particular check\t\t    \t\t\t\r\n\t\t\tMth::Vector\ttmp = GetPos();\r\n\t\t\tGetPos() = m_col_end - up_offset;\t\t\t\t\t\r\n\t\t\tif (check_for_air_snap_up(start_pos))\r\n\t\t\t{\r\n\t\t\t\t// we snapped up, so if we are either moving upward or the first collision was near vertical, then we return true, allowing us to continue\r\n\t\t\t\t// if we were moving upwards, then we would continue into the air\r\n\t\t\t\t// if we were moving down, but the collision was near vert, then we do not want to bonk off the surface, and instead we let\r\n\t\t\t\t// the landing happen in the next frame\r\n\t\t\t\tif (GetVel()[Y] > 10.0f || hit_vertical) return true;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tGetPos() = tmp;\r\n\t\t\tDUMP_POSITION;\r\n\t\t\tm_feeler = tmp_feeler;\r\n\r\n\t\t\t#ifdef\t\tSNAP_OVER_THIN_WALLS\r\n\t\t\t// we have hit a wall, and we can't snap up over i;  see if we can just move up and go over it....\r\n\r\n\t\t\t// only do this if we are roughly vertical and going up and the wall is very verticle\r\n\t\t\tif (GetMatrix()[Y][Y] > 0.5f\t\t   // skater is upright\r\n\t\t\t    && GetVel()[Y] > 0.0f\t\t\t   // skater travelling upwards\r\n\t\t\t\t&& normal[Y] < 0.01f)\t\t\t\t\t   // thing we hit is not far off vert\r\n\t\t\t{\r\n\t\t\t\t \r\n\t\t\t\tfloat snap_Y = GetPhysicsFloat(CRCD(0x786b3272, \"Physics_Air_Snap_Up\"));\r\n\t\t\t\ttmp_feeler.m_start[Y] += snap_Y;\r\n\t\t\t\ttmp_feeler.m_end[Y] += snap_Y;\r\n\t\t\t\t\t\t   \r\n\t\t\t\tif (!tmp_feeler.GetCollision())\r\n\t\t\t\t{\r\n\t\t\t\t\twhile (snap_Y > 4.0f)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// move down until we get a collision\r\n\t\t\t\t\t\t// so as to minimize the amount we snap up\r\n\t\t\t\t\t\ttmp_feeler.m_start[Y] -= 2.0f;\r\n\t\t\t\t\t\ttmp_feeler.m_end[Y] -= 2.0f;\r\n\t\t\t\t\t\tif (tmp_feeler.GetCollision()) break;\r\n\t\t\t\t\t\tsnap_Y -= 2.0f;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tGetPos()[Y] += snap_Y;\r\n\t\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\t// If we are on a vert poly, then just slide off the wall\r\n\t\t\t// just kill velocity perpendicular to the wall\r\n\t\t\tif (GetFlag(VERT_AIR))\r\n\t\t\t{\r\n\t\t\t\tGetPos() = m_feeler.GetPoint() - up_offset;\r\n\t\t\t\tGetPos() += normal * GetPhysicsFloat(CRCD(0x23410c14, \"Skater_Min_Distance_To_Wall\"));\t\t\t\t\r\n\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t\r\n\t\t\t\tif (!GetFlag(SPINE_PHYSICS))\r\n\t\t\t\t{\r\n\t\t\t\t\tGetVel().ProjectToPlane(normal);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tGetVel().RotateToPlane(m_feeler.GetNormal());\r\n\t\t\t\t}\r\n\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\treturn false;\t\t\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// maybe wall plant\r\n\t\t\tif (check_for_wallplant()) return false;\r\n\t\t\t\r\n\t\t\t// maybe wall ride\r\n\t\t\tif (check_for_wallride()) return false;\r\n\t\t\t\r\n\t\t\t// no acid drops after a in-air collision\r\n\t\t\tSetFlagTrue(AIR_ACID_DROP_DISALLOWED);\r\n\t\t\t\t\r\n\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_BONK, m_feeler);\r\n\t\t\tif (mp_physics_control_component->HaveBeenReset()) return false;\r\n\r\n\t\t\t// only play bonk sound for things that are near vert \t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\t\tif (m_feeler.GetNormal().GetY() < 0.05f)\r\n\t\t\t{\r\n\t\t\t\tmp_sound_component->PlayBonkSound(GetObject()->GetVel().Length() / GetSkater()->GetScriptedStat(CRCD(0xcc5f87aa, \"Skater_Max_Max_Speed_Stat\")), m_feeler.GetTerrain());\r\n\t\t\t}\r\n\r\n\t\t\t// it's a wall, bounce off it\r\n\t\t\t\r\n\t\t\tfloat vel_y = 0.0f;\r\n\r\n\t\t\t// ignore y vel if the polygon is not too much upside down \r\n\t\t\tif (normal[Y] > -0.1f)\r\n\t\t\t{\r\n\t\t\t\tvel_y = GetVel()[Y];\t\t\t\t\t// remember old Y vel\r\n\t\t\t\tGetVel()[Y] = 0.0f;\t\t\t\t\t// kill Y vel\r\n\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tGetVel().ProjectToPlane(normal);\t\t\t\t\t\t\t\t\t\t\t// project X and Z to plane of collision poly\t\r\n\t\t\tGetVel() += normal * (GetVel().Length() * (1.0f / 10.0f));\t\t// 10% tiny push away.....\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t\t\r\n\t\t\tif (normal[Y] > -0.1f)\r\n\t\t\t{\r\n\t\t\t\tGetVel()[Y] = vel_y;\t\t\t\t\t// restore old Y vel, so it's impossible to jump higher by jumping against a wall\r\n\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t}\t\t\t\r\n\t\t\t\r\n\t\t\tfloat Z_Y = GetMatrix()[Z][Y];\r\n\t\t\tGetMatrix()[Z][Y] = 0.0f;\r\n\t\t\tGetMatrix()[Z].RotateToPlane(normal);\r\n\t\t\tGetMatrix()[Z][Y] = Z_Y;\r\n\t\t\tGetMatrix()[Z] += (1.0f / 20.0f) * normal;\r\n\t\t\tGetMatrix()[Z].Normalize();\t\t\t\r\n\t\t\tGetMatrix()[X] = Mth::CrossProduct(GetMatrix()[Y], GetMatrix()[Z]);\r\n\t\t\tGetMatrix()[X].Normalize();\r\n\t\t\tGetMatrix()[Y] = Mth::CrossProduct(GetMatrix()[Z], GetMatrix()[X]);\r\n\t\t\tGetMatrix()[Y].Normalize();\r\n\t\t\t\r\n\t\t\t// Bit of a patach here to move the skater away from the wall\r\n\t\t\tGetPos() = m_feeler.GetPoint() - up_offset;\r\n\t\t\tGetPos() += normal * GetPhysicsFloat(CRCD(0x23410c14, \"Skater_Min_Distance_To_Wall\"));\r\n\t\t\tDUMP_POSITION;\r\n\t\t\t\r\n\t\t\t// if the thing we have collided with is a movable object, then add in the last movement to move us away \r\n\t\t\tif (m_feeler.IsMovableCollision())\r\n\t\t\t{\r\n\t\t\t\tMth::Vector obj_vel = m_feeler.GetMovingObject()->GetVel();\r\n\r\n\t\t\t\t// if object is moving in same direction as face normal\r\n\t\t\t\tif (Mth::DotProduct(obj_vel, m_feeler.GetNormal()) > 0.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\t// then add in the velocity, just to be on the safe side\r\n\t\t\t\t\tGetPos() += obj_vel * m_frame_length * 2.0f;\t\t// 2.0f is a safety factor\r\n\t\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t\t// and move with the thing we just hit\r\n\t\t\t\t\tGetVel() += obj_vel;\t\t\t\t\t\r\n\t\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\t \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::check_for_air_snap_up ( const Mth::Vector& start_pos )\r\n{\r\n\t////////////////////////////////////////////////////////////////////////////////////////\r\n\t// We moved from GetOldPos() to m_pos\r\n\t// and some collision was detected\r\n\t// either along this line, or along the \"forward\" line, which is 8 inches above\r\n\t// regardless, we want to see if the new m_pos (considered bad)\r\n\t// can be snapped upwards to a surface, where the normal is in the same direction as\r\n\t// the current movement\r\n\t// and check to see if there is a clear line to this position\r\n\t// currently in physics.q:  Physics_Air_Snap_Up = 15       \r\n\t//\r\n\t// Note, we ignore if the skater is going up or down, the calling code has to \r\n\t// handle that (for the spcial case of hitting a wall coming down, when we can snap over it)\r\n\r\n\t// don't do it if bailing, to avoid snapping through loops\r\n\tif (GetFlag(IS_BAILING)) return false;\r\n\t\r\n\tCFeeler feeler;\r\n\t\r\n\tfloat up_len = GetPhysicsFloat(CRCD(0x786b3272,\"Physics_Air_Snap_Up\"));\r\n\t\r\n\tfeeler.m_start = GetPos();\r\n\tfeeler.m_start[Y] += up_len;\r\n\tfeeler.m_end = GetPos();\r\n\t\r\n\t// Since the new pos might actually be ABOVE the ledge (i.e., we might have just clipped though the corner, and not be inside it)\r\n\t// then we need to check all the way down to the previous height, but only if moving upwards\r\n\tif (start_pos[Y] < GetPos()[Y])\r\n\t{\r\n\t\tfeeler.m_end[Y] = start_pos[Y];\t\t\r\n\t}\r\n\r\n\t// if the start pos, plus the snap up distance was above the top of the collision line, then extend the collision line up to that\t\r\n\tif (start_pos[Y] + up_len > feeler.m_start[Y])\r\n\t{\r\n\t\tfeeler.m_start[Y] = start_pos[Y] + up_len;\r\n\t}\r\n\t\r\n\t// set up the feeler, now check for collision\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t// Collision, possibly something we can snap up to\r\n\t\t\r\n\t\t// movement vector is in same direction as face normal, so we are moving away from it\r\n\t\t// usually this implies we are moving up, away from the horizontal face at the top of a wall, or a curb\r\n\t\tif (feeler.GetNormal().GetY() > 0.5f)\t\t// not if too vertical\r\n\t\t{\t\t\t\r\n\t\t\t// Okay, we can snap up, so all we have to do is see if the line is clear\r\n\t\t\tMth::Vector\tsnap_point = feeler.GetPoint() + feeler.GetNormal();\r\n\t\t\t\r\n\t\t\tfeeler.m_start = start_pos;\r\n\t\t\tfeeler.m_start[Y] += up_len;\r\n\t\t\tfeeler.m_end = snap_point;\r\n\t\t\tfeeler.m_end[Y] += up_len;\r\n\t\t\t\r\n\t\t\tif (!feeler.GetCollision())\r\n\t\t\t{\r\n\t\t\t\t// No collision along upper line,so we consider it safe to move\r\n\t\t\t\t// note, this will generally result in passing through the corner of some geometry (generally like the top of a wall, or a curb)\r\n\t\t\t\tGetPos() = snap_point;\t \t\t// set to snap point\r\n\t\t\t\tGetPos()[Y] += 0.1f;\t\t\t\t// offset up a little, so we are outside the plane\r\n\t\t\t\tDUMP_POSITION;\r\n\t\t\t\treturn true;\t\t\t\t\t\t\t\t// return true, indicating we snapped up, so carry on in air\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// was a collision when trying to move to new position, so don't move\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// too vert, so don't allow snap (probably on a QP)\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// No collision, so don't do anything, probably deep within a wall, or off the level.\r\n\t}\r\n\r\n\treturn false;\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::handle_upward_collision_in_air (   )\r\n{\r\n\t// return true if there was a collision, but we snapped up over it\r\n\t\r\n\t// if we are upside down, then return false\r\n\tif (GetMatrix()[Y][Y] < 0.0f) return false;\r\n\t\r\n\tfloat head_height = GetPhysicsFloat(CRCD(0x542cf0c7, \"Skater_default_head_height\"));\r\n\t\r\n\t// ignore head collisions for a duration after wallplants\r\n    if (Tmr::ElapsedTime(m_last_wallplant_time_stamp) <= static_cast< Tmr::Time >(Script::GetInteger(CRCD(0x2757ed2c, \"Physics_Ignore_Ceilings_After_Wallplant_Duration\"))))\r\n\t{\r\n\t\thead_height = 6.0f;\r\n\t}\r\n\t\r\n\tMth::Vector up_offset = GetMatrix()[Y] * head_height;\r\n\t\r\n\tm_col_start = GetPos();\r\n\t\r\n\tm_col_end = GetPos();\r\n\tm_col_end += up_offset;\r\n\t\r\n\tif (get_member_feeler_collision())\r\n\t{\r\n\t\tMth::Vector ceiling_normal = m_feeler.GetNormal();\r\n\t\t\r\n\t\t// if it's not at least tilted a bit downwards, then ignore it and return false\t   \r\n\t\tif (ceiling_normal[Y] > -0.1f) return false;\r\n\t\t\t\t\t  \r\n\t\t// get the vector we need to push down\r\n\t\tMth::Vector push_down = m_feeler.GetPoint() - m_col_end;\r\n\t\t\r\n\t\t// only push down away from the ceiling\t(otherwise we would push back along the line of travel, jerky)\r\n\t\tpush_down.ProjectToNormal(ceiling_normal);\r\n\r\n\t\t// push down as far as we can go, so check for collisions\t\t\r\n\t\tm_col_start = GetPos();\r\n\t\tm_col_end = GetPos() + push_down;\r\n\t\tif (get_member_feeler_collision())\r\n\t\t{\r\n\t\t\tGetPos() = m_feeler.GetPoint() + 0.001f * m_feeler.GetNormal();\r\n\t\t\tDUMP_POSITION;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tGetPos() = m_col_end;\r\n\t\t\tDUMP_POSITION;\r\n\t\t}\r\n\t\t\r\n\t\tGetVel().ProjectToPlane(ceiling_normal);\r\n\t\tDUMP_VELOCITY;\r\n\t\t\r\n\t\treturn true; \t// we have had a collision, so return true\r\n\t}\r\n\t\r\n\treturn false;  // no collision found, return false\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::handle_upward_collision_in_wallride (   )\r\n{\r\n\tm_col_start = GetPos() + 18.0f * mWallNormal;\r\n\t\r\n\tm_col_end = m_col_start;\r\n\tm_col_end[Y] += GetPhysicsFloat(CRCD(0x542cf0c7, \"Skater_default_head_height\"));\r\n\t\r\n\tif (get_member_feeler_collision())\r\n\t{\r\n\t\tMth::Vector ceiling_normal = m_feeler.GetNormal();\r\n\t\t\r\n\t\t// if it's not at least tilted a bit downwards, then ignore it and return false\t   \r\n\t\tif (ceiling_normal[Y] > -0.1f) return false;\r\n\t\t\t\t\t  \r\n\t\t// get the vector we need to push down\r\n\t\tMth::Vector push_down = m_feeler.GetPoint() - m_col_end;\r\n\t\t\r\n\t\t// only push down away from the ceiling\t(otherwise we would push back along the line of travel, jerky)\r\n\t\tpush_down.ProjectToNormal(ceiling_normal);\r\n\r\n\t\t// push down as far as we can go, so check for collisions\t\t\r\n\t\tm_col_start = GetPos();\r\n\t\tm_col_end = GetPos() + push_down;\r\n\t\tif (get_member_feeler_collision())\r\n\t\t{\r\n\t\t\tGetPos() = m_feeler.GetPoint() + m_feeler.GetNormal();\r\n\t\t\tDUMP_POSITION;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tGetPos() = m_col_end;\r\n\t\t\tDUMP_POSITION;\r\n\t\t}\r\n\t\t\r\n\t\tGetVel().ProjectToPlane(ceiling_normal);\r\n\t\tDUMP_VELOCITY;\r\n\t\t\r\n\t\treturn true; \t// we have had a collision, so return true\r\n\t}\r\n\t\r\n\treturn false;  // no collision found, return false\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::do_wallride_physics (   )\r\n{\r\n\tSetFlagFalse(SPINE_PHYSICS);\r\n\tSetFlagFalse(IN_ACID_DROP);\r\n\tSetFlagFalse(IN_RECOVERY);\r\n\tSetFlagFalse(AIR_ACID_DROP_DISALLOWED);\r\n\r\n\t// Wallriding will cancel any memory of what rail we were on, so the next one seems fresh\t\r\n\tmp_rail_node = NULL;\r\n\tm_last_rail_trigger_node_name = 0;\r\n\t\r\n\r\n\r\n\t// Keep updating the time, cos it needs to be the time that the last wall ride finished.\r\n\tmWallrideTime = Tmr::GetTime();\r\n\r\n\t// set wallride movement to nothing\r\n\tMth::Vector m_movement(0.0f, 0.0f, 0.0f);\r\n\t\r\n\t// if we are in contact with something, then factor in that \"movement\"\r\n\tif (mp_movable_contact_component->UpdateContact(GetPos()))\r\n\t{\r\n\t\tm_movement = mp_movable_contact_component->GetContact()->GetMovement();\r\n\t\tif (mp_movable_contact_component->GetContact()->IsRotated())\r\n\t\t{\r\n\t\t\tGetMatrix() *= mp_movable_contact_component->GetContact()->GetRotation();\r\n\t\t\tm_lerping_display_matrix *= mp_movable_contact_component->GetContact()->GetRotation();\r\n\t\t}\r\n\t}\r\n\r\n\t// Mick: changed to include gravity\r\n\t// note this is the way THPS2 worked\r\n\t// the physics might not be intuitive, but it works\t\r\n\t// also note we are intentionally not removing sideways components of velocity, so we get to drift up a bit\r\n\t// after we hit the wall, allowing us to to the \"claw\" trick (Jump-WallRide-Jump-Grind)\r\n\t\r\n\tMth::Vector acc(0.0f, GetPhysicsFloat(CRCD(0xc617caf, \"Wall_Ride_Gravity\")), 0.0f);\r\n\tGetPos() += GetVel() * m_frame_length + acc * (0.5f * m_frame_length * m_frame_length);\r\n\tGetPos() += m_movement;\r\n\tDUMP_POSITION;\r\n\tGetVel() += acc * m_frame_length;\r\n\tDUMP_VELOCITY;\r\n\t\t\t  \r\n\t#if 0 // old code\r\n\t// Mth::Vector Down(0.0f,-1.0f,0.0f);\r\n\t// Mth::Vector Horiz=Mth::CrossProduct(mWallNormal,Down);\r\n\t#else\r\n\tMth::Vector Horiz(mWallNormal[Z], 0.0f, -mWallNormal[X], 0.0f);\r\n\t#endif\r\n\tHoriz.Normalize();\r\n\t\r\n\t// Down is a unit vector pointing down along the plane of the wall.\r\n\tMth::Vector Down = Mth::CrossProduct(Horiz, mWallNormal);\r\n\t\r\n\tfloat Theta = GetPhysicsFloat(CRCD(0x64a48a64, \"Wall_Ride_Turn_Speed\"));\r\n\t\r\n\t// Check if Theta is bigger than the angle the skater's z is already making with the Down vector.\r\n\t// If Theta is bigger, don't rotate by it, otherwise the skater will turn beyond the vertical.\r\n\tfloat zdot = Mth::DotProduct(GetMatrix()[Z], Down);\r\n\tif (zdot > 0.68f || (zdot > 0.0f && zdot > cosf(Theta)))\r\n\t{\r\n\t\t// Pointing pretty much straight down, so don't turn.\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Choose which way to turn.\r\n\t\t// Need to turn one way or the other depending on whether the skater's z axis is on the left or right side of the down vector.\r\n\t\t// This is the same as whether the skater's x axis is pointing up or down, so just check the sign of the dot product of x with down.\r\n\t\tfloat xdot = Mth::DotProduct(GetMatrix()[X], Down);\r\n\t\tif (xdot <= 0.0f)\r\n\t\t{\r\n\t\t\tTheta = -Theta;\r\n\t\t}\t\r\n\r\n\t\t// Not strictly required for NGPS, fixes a problem on NGC. However, given m_vel is used only\r\n\t\t// as a three-element vector, not a bad idea to set this for all platforms.\r\n\t\tGetVel()[W] = 1.0f;\r\n\t\r\n\t\t// Rotate both the skater and the skater's velocity by Theta about the wall normal axis.\r\n\t\tGetVel().Rotate(mWallNormal, Theta);\r\n\t\tDUMP_VELOCITY;\r\n\r\n\t\t// set skater to face in the same direction as velocity\r\n\t\tGetMatrix()[Z] = GetVel();\r\n\t\t\r\n\t\tGetMatrix()[Z].Normalize();\r\n\t\tGetMatrix()[Y] = mWallNormal;\r\n\t\tGetMatrix()[X] = Mth::CrossProduct(GetMatrix()[Y], GetMatrix()[Z]);\r\n\t\tGetMatrix()[X].Normalize();\r\n\t\tResetLerpingMatrix();\r\n\t}\t\r\n\t\r\n\t// Forward collision check\t\r\n\tMth::Vector forward = GetPos() - GetOldPos();\r\n\tforward.Normalize();\t\r\n\t\r\n\tm_col_start = GetOldPos();\r\n\t\r\n\tm_col_end = GetPos();\r\n\tm_col_end += forward * GetPhysicsFloat(CRCD(0x20102726, \"Skater_First_Forward_Collision_Length\"));\r\n\r\n\tif (get_member_feeler_collision())\r\n\t{\r\n\t\t// we have hit something going forward\r\n\t\t// either it is a wall, and we need to bounce off it or it is a steep QP, and we need to stick to it.\r\n\t\t// (note, with the slow normal changing, then it is possible that we might even collide with the poly that we are on)\r\n\t\t\r\n\t\tMth::Vector\tnormal = m_feeler.GetNormal();\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\tfloat dot = Mth::DotProduct(normal, mWallNormal);\t\t\t\r\n\r\n\t\tGetPos() = m_feeler.GetPoint() + normal;\r\n\t\tDUMP_POSITION;\r\n\r\n\t\t// For fairly shallow curves, the dot between two normals will be pretty large\r\n\t\t// it's very important here to distinguish between a tight curve (like in a narrow QP) and a direct hit with a wall.\r\n\t\t\r\n\t\tif (!m_col_flag_wallable || Mth::Abs(dot) < 0.01f)\r\n\t\t{\r\n\t\t\tif (normal[Y] > 0.9f)\r\n\t\t\t{\r\n\t\t\t\t// If the new poly is the ground, pop upright and set the landed exception.\r\n\t\t\t\tGetPos() = m_feeler.GetPoint();\r\n\t\t\t\tDUMP_POSITION;\r\n\r\n\t\t\t\t// Set every orientation type thing I can think of so as to\r\n\t\t\t\t// pop his orientation to that of the ground.\t\t\t\t\r\n\t\t\t\tGetMatrix()[Z] = GetVel();\r\n\t\t\t\tGetMatrix()[Z].ProjectToPlane(normal);\t // Mick: project forward vel to ground\r\n\t\t\t\tGetMatrix()[Z].Normalize();\r\n\t\t\t\tGetMatrix()[Y] = normal;\t\t\t\t  \t\t\r\n\t\t\t\tGetMatrix()[X] = Mth::CrossProduct(GetMatrix()[Y],GetMatrix()[Z]);\r\n\t\t\t\tGetMatrix()[X].Normalize();\r\n\t\t\t\t\r\n\t\t\t\tResetLerpingMatrix();\r\n\t\t\t\t\r\n\t\t\t\tGetSkaterMatrixQueriesComponentFromObject(GetObject())->ResetLatestMatrix();\r\n\t\t\t\t\r\n\t\t\t\tm_last_display_normal = GetMatrix()[Y];\r\n\t\t\t\tm_display_normal = GetMatrix()[Y];\r\n\t\t\t\tm_current_normal = GetMatrix()[Y];\r\n\t\t\t\t\r\n\t\t\t\t// check for sticking to rail first; use the \"override_air\" to stick to rail)\r\n\t\t\t\tmaybe_stick_to_rail(true);\r\n\t\t\t\tif (GetState() != RAIL)\r\n\t\t\t\t{\r\n\t\t\t\t\tSetState(GROUND);\r\n\t\t\t\t\tFLAGEXCEPTION(CRCD(0x532b16ef, \"Landed\"));\r\n\t\t\t\t}\t\t\t\t\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tnew_normal(Mth::Vector(0.0f, 1.0f, 0.0f));\r\n\t\t\t\t\r\n\t\t\t\tGetPos() += 18.0f * mWallNormal;\r\n\t\t\t\tDUMP_POSITION;\r\n\t\t\t\r\n\t\t\t\tSetState(AIR);\r\n\t\t\t\tGetObject()->BroadcastEvent(CRCD(0xd96f01f1, \"SkaterOffEdge\"));\r\n\t\t\t\tFLAGEXCEPTION(CRCD(0x3b1001b6, \"GroundGone\"));\r\n\r\n\r\n\t\t\t}\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmWallNormal = normal;\t\t\t// update the normal to the new one...\t\t\t\r\n\t\t\tnew_normal(mWallNormal);\r\n            ResetLerpingMatrix();\r\n\t\t\tGetVel().RotateToPlane(mWallNormal);\t\t// make velocity go along it\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (handle_upward_collision_in_wallride())\r\n\t{\r\n\t\tnew_normal(Mth::Vector(0.0f, 1.0f, 0.0f));\r\n\t\t\r\n\t\tGetPos() += 18.0f * mWallNormal;\r\n\t\tDUMP_POSITION;\r\n\r\n\t\tSetState(AIR);\r\n\t\tGetObject()->BroadcastEvent(CRCD(0xd96f01f1, \"SkaterOffEdge\"));\r\n\t\tFLAGEXCEPTION(CRCD(0x3b1001b6, \"GroundGone\"));\r\n\t}\r\n\r\n\t// Downwards collision check (down in direction of skater's y)\r\n\t\r\n\tm_col_start = GetMatrix()[Y] * GetPhysicsFloat(CRCD(0xe4d79235, \"Physics_Ground_Snap_Up\"));\r\n\tm_col_start += GetPos();\r\n\t\r\n\tm_col_end = GetMatrix()[Y] * GetPhysicsFloat(CRCD(0x438ba168, \"Wall_Ride_Down_Collision_Check_Length\"));\r\n\tm_col_end += GetPos();\r\n\t\r\n\tif (get_member_feeler_collision())\r\n\t{\r\n\t\tmWallNormal=m_feeler.GetNormal();\r\n\r\n \t\t// Snap position to wall.\r\n\t\tGetPos() = m_feeler.GetPoint();\r\n\t\t// but one inch out from it\r\n\t\tGetPos() += mWallNormal;\r\n\t\tDUMP_POSITION;\r\n\t\t\t\r\n\t\t// Rotate velocity to plane.\r\n\t\tGetVel().RotateToPlane(mWallNormal);\r\n\t\tDUMP_VELOCITY;\r\n\t\t\t\r\n\t\t// Snap skater's orientation to the plane.\r\n\t\tnew_normal(mWallNormal);\r\n\t\tResetLerpingMatrix();\r\n\t\t\r\n\t\tif (!m_col_flag_wallable)\r\n\t\t{\r\n\t\t\tGetVel() += mWallNormal * 100.0f;\t\t// boost away from the wall\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t\t\r\n\t\t\tnew_normal(Mth::Vector(0.0f, 1.0f, 0.0f));\r\n            ResetLerpingMatrix();\r\n\t\t\tSetState(AIR);\r\n\t\t\t\r\n\t\t\tGetObject()->BroadcastEvent(CRCD(0xd96f01f1, \"SkaterOffEdge\"));\r\n\t\t\tFLAGEXCEPTION(CRCD(0x3b1001b6, \"GroundGone\"));\r\n\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_OFF_EDGE, m_last_ground_feeler);\r\n\t\t\t\r\n\t\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// handle wallride transition from one object to the next\r\n\t\t\tif (m_feeler.GetSector() != m_last_ground_feeler.GetSector())\r\n\t\t\t{\r\n\t\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_OFF_EDGE, m_last_ground_feeler);\r\n\t\t\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_ONTO, m_last_ground_feeler);\r\n\t\t\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\t\t}\r\n\t\t\tif (!mp_trick_component->GraffitiTrickStarted())\r\n\t\t\t{\r\n\t\t\t\t// clear the graffiti trick buffer if we're moving to a new world sector, but haven't started our trick yet...\r\n\t\t\t\tmp_trick_component->SetGraffitiTrickStarted(false);\r\n\t\t\t}\r\n\r\n\t\t\tset_last_ground_feeler(m_feeler);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tnew_normal(Mth::Vector(0.0f, 1.0f, 0.0f));\r\n\t\tResetLerpingMatrix();\r\n\t\tGetPos() += 18.0f * mWallNormal;\r\n\t\tDUMP_POSITION;\r\n\t\tSetState(AIR);\r\n\t\tGetObject()->BroadcastEvent(CRCD(0xd96f01f1, \"SkaterOffEdge\"));\r\n\t\tFLAGEXCEPTION(CRCD(0x3b1001b6, \"GroundGone\"));\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_SKATE_OFF_EDGE, m_last_ground_feeler);\r\n\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t}\r\n\t\r\n\t// look for head collisions\r\n\t\r\n\t\r\n\t// This was cut-and-past'd from DoOnGroundPhysics\r\n\thandle_tensing();\r\n\t\r\n\tif (maybe_flag_ollie_exception())\r\n\t{\r\n\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_JUMP_OFF, m_last_ground_feeler);\r\n\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\t\r\n\t\tGetVel() += GetPhysicsFloat(CRCD(0x349d02d4, \"Wall_Ride_Jump_Out_Speed\")) * mWallNormal;\r\n\t\tGetVel()[Y] += GetPhysicsFloat(CRCD(0x5a9de35a, \"Wall_Ride_Jump_Up_Speed\"));\r\n\t\tDUMP_VELOCITY;\r\n\t\t\r\n\t\t// Pop the skater upright again immediately.\r\n\t\tGetMatrix()[Y].Set(0.0f, 1.0f, 0.0);\r\n\t\tGetMatrix().OrthoNormalizeAbout(Y);\r\n\t\tResetLerpingMatrix();\r\n\r\n\t\t// and immediately adjust the normal, to prevent single frame snaps when walliing and the 90 degree swoop when wallride to grind\r\n\t\tm_normal_lerp = 0.0f;\r\n\t\tm_display_normal = GetMatrix()[Y];\r\n\t\tm_current_normal  = m_display_normal;\r\n\t\tm_last_display_normal  = m_display_normal;\r\n\t}\r\n\t\r\n\t// if we've already started doing a trick, then start remembering our trick chain\r\n\t// GJ:  It's possible to do a wallride while mNumTricksInCombo == 0, for some reason\r\n\tmp_trick_component->TrickOffObject(m_last_ground_feeler.GetNodeChecksum());\r\n\t\t\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (Script::GetInteger(CRCD(0x3ae85eef, \"skater_trails\")))\r\n\t{\r\n\t\tGfx::AddDebugLine(GetPos() + m_current_normal, GetOldPos() + m_current_normal, PURPLE, 0, 0);\r\n\t}\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::do_wallplant_physics (   )\r\n{\r\n\t// check if the wallplant duration is up\r\n\tif (Tmr::ElapsedTime(m_state_change_timestamp) > Script::GetFloat(CRCD(0xa06e446b, \"Physics_Wallplant_Duration\")))\r\n\t{\r\n\t\tSetState(AIR);\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Wallplanting will cancel any memory of what rail we were on, so the next one seems fresh\t\r\n\tmp_rail_node = NULL;\r\n\tm_last_rail_trigger_node_name = 0;\r\n\r\n\t\r\n\t// during a wallplant, our velocity is set to the exit velocity, but we simply ignore it\r\n\t\r\n\t// the only movement comes from our moving contact; we assume that this movement does not lead to collisions\r\n\tif (mp_movable_contact_component->UpdateContact(GetPos()))\r\n\t{\r\n\t\tGetPos() += mp_movable_contact_component->GetContact()->GetMovement();\r\n\t\tDUMP_POSITION;\r\n\t\tif (mp_movable_contact_component->GetContact()->IsRotated())\r\n\t\t{\r\n\t\t\tGetMatrix() *= mp_movable_contact_component->GetContact()->GetRotation();\r\n\t\t\tm_lerping_display_matrix *= mp_movable_contact_component->GetContact()->GetRotation();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::maybe_stick_to_rail ( bool override_air )\r\n{\r\n\t// Only alow them to grind if we are in the air, that way we will avoid nasty problem with snapping through geometry onto rails \r\n\tif (GetState() != AIR && !override_air) return;\r\n\r\n\t// K: Don't allow a grind trick if bailing, otherwise you can late-trick into a liptrick, bail, get snapped into a grind, & hence bail again.\r\n\tif (GetFlag(IS_BAILING)) return;\r\n\t\t\r\n\t// K: No grinds or lip tricks are allowed if this flag is set. This is switched on and off by the NoGrind and AllowGrind script commands.\r\n\t// These are used when jumping out of a lip trick to disallow going straight into a grind.\r\n\tif (mNoRailTricks) return;\r\n\r\n\tif (!mp_input_component->GetControlPad().m_triangle.GetPressed())\r\n\t{\r\n\t\t// Mick: not sure why this was removed\r\n\t\t// SetFlagTrue(CAN_RERAIL);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// don't grind for a short duration after a wallplant\r\n\tif (Tmr::ElapsedTime(m_last_wallplant_time_stamp) < static_cast< Tmr::Time >(Script::GetInteger(CRCD(0x96dca7dc,\"Physics_Wallplant_Disallow_Grind_Duration\")))) return;\r\n\r\n\tMth::Vector a = GetOldPos();\r\n\tMth::Vector b = GetPos();\r\n\t\r\n\t// if we were on a rail recently, and in the park editor, then don't let us snap to rails that are very perpendicular to us for a while\r\n\tfloat min_dot;\r\n\tif (Ed::CParkEditor::Instance()->UsingCustomPark() && Tmr::ElapsedTime(m_rail_time) < m_rerail_time)\r\n\t{\r\n\t\t// Should only do this if we've recently been on a rail\r\n\t\tmin_dot = cosf(Mth::DegToRad(GetPhysicsFloat(CRCD(0x76c1da15, \"Rail_Corner_Leave_Angle\"))));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmin_dot = 1.0f;\r\n\t}\r\n\r\n\t// eventually we should get the rail manager base on whatever rail we are on\r\n\tCRailManager* p_rail_man = Mdl::Skate::Instance()->GetRailManager();\r\n\t\t\r\n\t// first check the world rail manager (rails that do not move)\r\n\tCRailNode* pNode;\t\t\r\n\tMth::Vector rail_pos;\r\n\tif (p_rail_man->StickToRail(a, b, &rail_pos, &pNode, NULL, min_dot))\r\n\t{\r\n\t\tTrackingLine(2,GetOldPos(), GetPos());\t  // 2 = stick to rail\r\n\t\t\r\n\t\tmp_movable_contact_component->LoseAnyContact();\r\n\t\tif (will_take_rail(pNode, p_rail_man))\r\n\t\t{\r\n\t\t\tgot_rail(rail_pos, pNode, p_rail_man);\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// iterate through all rail manager components, starting with the first one\r\n\tfor (CRailManagerComponent* p_railmanager_component = static_cast< CRailManagerComponent* >(CCompositeObjectManager::Instance()->GetFirstComponentByType(CRC_RAILMANAGER));\r\n\t\tp_railmanager_component;\r\n\t\tp_railmanager_component = static_cast< CRailManagerComponent* >(p_railmanager_component->GetNextSameType()))\r\n\t{\r\n\t\tCRailManager* p_rail_man = p_railmanager_component->GetRailManager();\r\n\t\t\r\n\t\tMth::Matrix\ttotal_mat = p_railmanager_component->UpdateRailManager();\r\n\t\tMth::Matrix\tinv = total_mat;\r\n\t\tinv.Invert();\r\n\r\n\t\ta[W] = 1.0f;\r\n\t\tb[W] = 1.0f;\r\n\r\n\t\t// Transform a,b into the space of the object\t\t\t\r\n\t\tMth::Vector local_a = inv.Transform(a);\r\n\t\tMth::Vector local_b = inv.Transform(b);\r\n\r\n\t\tif (p_rail_man->StickToRail(local_a, local_b, &rail_pos, &pNode, NULL, min_dot))\r\n\t\t{\r\n\t\t\t// transform from object space to world space\r\n\t\t\trail_pos[W] = 1.0f;\r\n\t\t\trail_pos = total_mat.Transform(rail_pos);\r\n\t\t\tif (will_take_rail(pNode, p_rail_man))\r\n\t\t\t{\r\n\t\t\t\tgot_rail(rail_pos, pNode, p_rail_man); \r\n\t\t\t\tmp_movable_contact_component->ObtainContact(p_railmanager_component->GetObject());\r\n\t\t\t\t\r\n\t\t\t\tGetVel() -= mp_movable_contact_component->GetContact()->GetObject()->GetVel();\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::will_take_rail ( const CRailNode* pNode, CRailManager* p_rail_man, bool from_walk )\r\n{\r\n\t// no grinding if we're in an acid drop which was generated from an ollie out of a grind; prevents acid-grind-acid-grind repetition\r\n\tif (GetState() == AIR && GetFlag(IN_ACID_DROP) && GetFlag(OLLIED_FROM_RAIL)\r\n\t\t&& (mp_rail_node == pNode || mp_rail_node == pNode->GetNextLink() || mp_rail_node == pNode->GetPrevLink()))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// if it's a different rail, then allow rerailing\r\n\tif (!mp_rail_node\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// if there was no last rail\r\n\t\t\r\n\t\t// Dan: removed this line to prevent occasional rerailing when you grind off the end of a car; why was it here in the first place?\r\n\t\t// || (mp_rail_man && mp_rail_man->IsMoving() && !mp_movable_contact_component->HaveContact())\t// or last rail was movable, and we've lost contact\r\n\t\t\r\n\t\t|| mp_rail_node != pNode\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// or not same segment\r\n\t\t&& mp_rail_node != pNode->GetNextLink()  \t\t\t\t\t\t\t\t\t\t\t\t// or the one before\r\n\t\t&& mp_rail_node != pNode->GetPrevLink()) \t\t\t\t\t\t\t\t\t\t\t\t// of the one after\r\n\t{\r\n\t\tif (mp_rail_node && Ed::CParkEditor::Instance()->UsingCustomPark())\r\n\t\t{\r\n\t\t\tDbg_Assert(mp_rail_man);\r\n\t\t\t\r\n\t\t\t// in park editor rail must also not share end points to be considered different\r\n\t\t\tMth::Vector a = mp_rail_man->GetPos(mp_rail_node) - mp_rail_man->GetPos(pNode);\r\n\t\t\tMth::Vector b = mp_rail_man->GetPos(mp_rail_node) - mp_rail_man->GetPos(pNode->GetNextLink());\r\n\t\t\tMth::Vector c = mp_rail_man->GetPos(mp_rail_node->GetNextLink()) - mp_rail_man->GetPos(pNode);\r\n\t\t\tMth::Vector d = mp_rail_man->GetPos(mp_rail_node->GetNextLink()) - mp_rail_man->GetPos(pNode->GetNextLink());\r\n\r\n\t\t\tif (Mth::Abs(a.Length()) > 6.0f\t\t\t\r\n\t\t\t\t&& Mth::Abs(b.Length()) > 6.0f\t\t\t\r\n\t\t\t\t&& Mth::Abs(c.Length()) > 6.0f\t\t\t\r\n\t\t\t\t&& Mth::Abs(d.Length()) > 6.0f)\r\n\t\t\t{\r\n\t\t\t\tSetFlagTrue(CAN_RERAIL);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tSetFlagTrue(CAN_RERAIL);\r\n\t\t}\r\n\t}\r\n\t\r\n    return (GetFlag(CAN_RERAIL) || Tmr::ElapsedTime(m_rail_time) > m_rerail_time)\r\n\t\t&& (from_walk\r\n\t\t\t|| (GetState() != RAIL \t\t\t\t\t\t\t\t\t// not already on a rail\r\n\t\t\t&& (!GetFlag(TRACKING_VERT) || GetVel()[Y] > 0.0f)));\t\t// must be not vert, or going up \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::got_rail ( const Mth::Vector& rail_pos, const CRailNode* pNode, CRailManager* p_rail_man, bool no_lip_tricks, bool from_walk )\r\n{\r\n\t// got a point on rail, with start node number from a particular rail manager\r\n\t// use this info to start grinding or lipping on the rail\r\n\t\r\n\tCControlPad& control_pad = mp_input_component->GetControlPad();\r\n\t\r\n\tCSkaterFlipAndRotateComponent* p_flip_and_rotate_component = GetSkaterFlipAndRotateComponentFromObject(GetObject());\r\n\tDbg_Assert(p_flip_and_rotate_component);\r\n\tp_flip_and_rotate_component->DoAnyFlipRotateOrBoardRotateAfters();\r\n\r\n\r\n\t// Mick - landed on a rail\r\n\t// if it's a \"new\" rail, then tell the robot detector about it\r\n\tif (mp_rail_node != pNode)\r\n\t{\r\n\t\tint rail_index = p_rail_man->GetNodeIndex(pNode);\t\t\r\n\t\tmp_score_component->GetScore()->UpdateRobotDetection(rail_index);\r\n\t}\r\n\r\n\tmp_rail_node = pNode;\t\t\t\t\t  \r\n\tmp_rail_man = p_rail_man;\r\n\t\r\n\t// handle single node rails\r\n\tif (!pNode->GetPrevLink() && !pNode->GetNextLink())\r\n\t{\r\n\t\t// for a single node rail, we apply in a single frame all the effects of entering and exiting the rail state;\r\n\r\n\t\t/////////////////////////////////////////////////////\r\n\t\t// Emulate entering the rail state (with horizontal dir direction)\r\n\r\n\t\t// check for collision in moving from m_pos to rail_pos\r\n\t\t\r\n\t\tm_col_start = GetPos();\r\n\t\tm_col_end = rail_pos;\r\n\t\tif (get_member_feeler_collision())\r\n\t\t{\r\n\t\t\t// check distance from the rail to the collision point\r\n\t\t\tif ((rail_pos - m_feeler.GetPoint()).LengthSqr() > 6.0f * 6.0f) \r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// check first if we are not moving much in the XY and if not, then se the XZ velocity to the matrix[Z], so we always go forward\r\n\t\tif (Mth::Abs(GetVel()[X]) < 0.01f && Mth::Abs(GetVel()[Z]) < 0.01f)\r\n\t\t{\r\n\t\t\tGetVel()[X] = GetMatrix()[Z][X];\r\n\t\t\tGetVel()[Z] = GetMatrix()[Z][Z];\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t}\r\n\t\t\r\n\t\tif (!from_walk && GetVel()[X] * GetVel()[X] + GetVel()[Z] * GetVel()[Z] > 10.0f * 10.0f)\r\n\t\t{\r\n\t\t\tGetVel().RotateToPlane(Mth::Vector(0.0f, 1.0f, 0.0f));\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t}\r\n\r\n\t\t// rail direction is taken to always simply be along our horizontal velocity, rotated up\r\n\t\tMth::Vector dir = GetVel();\r\n\t\tdir[Y] = 0.0f;\r\n\t\tdir.Normalize();\r\n\t\tfloat angle = Mth::DegToRad(Script::GetFloat(CRCD(0xbb357ecb,\"Physics_Point_Rail_Kick_Upward_Angle\")));\r\n\t\tfloat c = cosf(angle);\r\n\t\tfloat s = sinf(angle);\r\n\t\tMth::Vector boost_dir(c * dir[X], s, c * dir[Z]);\r\n\t\t\r\n\t\t// get the rail node name\r\n\t\tScript::CArray* pNodeArray = mp_rail_man->GetNodeArray();\r\n\t\tScript::CStruct* pNode = pNodeArray->GetStructure(mp_rail_node->GetNode());\r\n\t\tpNode->GetChecksum(CRCD(0xa1dc81f9, \"Name\"), &m_last_rail_node_name, Script::ASSERT);\r\n\t\t\r\n\t\tmp_trick_component->TrickOffObject(m_last_rail_node_name);\r\n\r\n\t\t// Now we want to see if the rail has a trigger, and if it does, trigger it....\r\n\t\t\r\n\t\tuint32 trigger_script = 0;\r\n\t\t\r\n\t\t// no need to call maybe_trip_rail_trigger for a single node rail\r\n\t\tif (pNode->GetChecksum(CRCD(0x2ca8a299, \"TriggerScript\"), &trigger_script))\r\n\t\t{\r\n\t\t\tmp_trigger_component->TripTrigger(\r\n\t\t\t\tTRIGGER_LAND_ON,\r\n\t\t\t\tm_last_rail_node_name,\r\n\t\t\t\tpNodeArray == Script::GetArray(CRCD(0xc472ecc5, \"NodeArray\")) ? NULL : pNodeArray,\r\n\t\t\t\tmp_movable_contact_component->HaveContact() ? mp_movable_contact_component->GetContact()->GetObject() : NULL\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tGetPos() = rail_pos;\r\n\t\tDUMP_POSITION;\r\n\r\n\t\t// Now we'v got onto the rail, we need to:\r\n\t\t// 1) kill velocity perpendicular to the rail\r\n\t\t// 2) add a speed boost in the direction we are going.\r\n\r\n\t\tSetFlagFalse(VERT_AIR);\r\n\t\tSetFlagFalse(TRACKING_VERT);\r\n\r\n\t\t// if we are transitioning from wall to rail, then snap him upright\t\t\r\n\t\tif (GetState() == WALL)\r\n\t\t{\r\n\t\t\tnew_normal(Mth::Vector(0.0f, 1.0f, 0.0f));\r\n\t\t\tResetLerpingMatrix();\r\n\t\t}\r\n\r\n\t\tSetState(RAIL);\r\n\r\n\t\tset_terrain(mp_rail_node->GetTerrain());\r\n\t\tmp_sound_component->PlayLandSound(GetObject()->GetVel().Length() / GetSkater()->GetScriptedStat(CRCD(0xcc5f87aa, \"Skater_Max_Max_Speed_Stat\")), mp_state_component->m_terrain);\r\n\t\t\r\n\t\tfloat old_y = GetVel()[Y];\r\n\t\tGetVel().ProjectToNormal(dir);\t   \t\t\t\t\t\t\t// kill perp velocity\r\n\t\tif (from_walk && Mth::DotProduct(GetVel(), GetMatrix()[Z]) < 0.0f)\r\n\t\t{\r\n\t\t\tif (GetVel().LengthSqr() < Mth::Sqr(1.1f * mp_walk_component->s_get_param(CRCD(0x896c8888, \"jump_adjust_speed\"))))\r\n\t\t\t{\r\n\t\t\t\tGetVel().Set();\r\n\t\t\t\tdir = GetMatrix()[Z];\r\n\t\t\t\tdir[Y] = 0.0f;\r\n\t\t\t\tdir.Normalize();\r\n\t\t\t}\r\n\r\n\t\t}\r\n\t\tGetVel()[Y] = old_y;\t\t\t\t\t\t\t\t\t\t\t// except for Y\r\n\r\n\t\tGetVel() += dir * GetPhysicsFloat(CRCD(0xa3ef4833, \"Point_Rail_Speed_Boost\"));\t// add speed boost\t\t\t\r\n\t\tDUMP_VELOCITY;\r\n\r\n\r\n\t\t// (Mick) Set m_rail_time, otherwise there is a single frame where it is invalid\r\n\t\t// and this allows us to immediately re-rail and hence do the \"insta-bail\", since the triangle button will be held down   \r\n\t\tm_rail_time  = Tmr::GetTime();\r\n\r\n\t\t/////////////////////////////////////////////////////\r\n\t\t// Emulate effects of rail state (with boost_dir direction)\r\n\r\n\t\tSetFlagFalse(SPINE_PHYSICS);\r\n\t\tSetFlagFalse(IN_ACID_DROP);\r\n\t\tSetFlagFalse(IN_RECOVERY);\r\n\t\tSetFlagFalse(AIR_ACID_DROP_DISALLOWED);\r\n\r\n\t\t// set default rerail time\t\r\n\t\tm_rerail_time = static_cast< Tmr::Time >(GetPhysicsFloat(CRCD(0x2b4645ad, \"Rail_Minimum_Rerail_Time\")));\r\n\t\t// and dissalow any overriding of this\r\n\t\tSetFlagFalse(CAN_RERAIL);\t\t// dont allow rerailing after coming off a segment\r\n\t\t\r\n\t\tGetVel().RotateToNormal(boost_dir);\r\n\t\tDUMP_VELOCITY;\r\n\r\n\t\t/////////////////////////////////////////////////////\r\n\t\t// Emulate exiting the rail state\r\n\r\n\t\t// no need to call maybe_trip_rail_trigger for a single node rail\r\n\t\tif (trigger_script)\r\n\t\t{\r\n\t\t\tmp_trigger_component->TripTrigger(\r\n\t\t\t\tTRIGGER_SKATE_OFF,\r\n\t\t\t\tm_last_rail_node_name,\r\n\t\t\t\tpNodeArray == Script::GetArray(CRCD(0xc472ecc5, \"NodeArray\")) ? NULL : pNodeArray,\r\n\t\t\t\tmp_movable_contact_component->HaveContact() ? mp_movable_contact_component->GetContact()->GetObject() : NULL\r\n\t\t\t);\r\n\t\t}\r\n\t\t\t\r\n\t\tSetState(AIR);\r\n\t\tGetPos()[Y] += 1.0f;\r\n\t\tDUMP_POSITION;\r\n\r\n\t\t/////////////////////////////////////////////////////\r\n\t\t// Do extra point rail logic\r\n\r\n\t\t// trigger the appropriate script\r\n\t\tGetObject()->SelfEvent(CRCD(0xb8048f1d, \"PointRail\"));\r\n\t\t\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t///////////////////////////////////////////////////////////////////////////\r\n\t// \t\t\t\t\t\tCheck for lip trick\r\n\t///////////////////////////////////////////////////////////////////////////\r\n\t\r\n\tfloat LipAllowSine = sinf(Mth::DegToRad(GetPhysicsFloat(CRCD(0x8157c5d9, \"LipAllowAngle\"))));\r\n\tif (pNode->GetFlag(LIP_OVERRIDE))\r\n\t{\r\n\t\tLipAllowSine = sinf(Mth::DegToRad(GetPhysicsFloat(CRCD(0xf3b6f95e, \"LipAllowAngle_Override\"))));\r\n\t}\r\n\tfloat HorizSine = sinf(Mth::DegToRad(GetPhysicsFloat(CRCD(0xe2a85fbb, \"LipPlayerHorizontalAngle\"))));\r\n\tfloat VertCos = cosf(Mth::DegToRad(GetPhysicsFloat(CRCD(0x61079462, \"LipRampVertAngle\"))));\r\n\r\n\tif ((mAllowLipNoGrind\t\t\t\t\t\t\t\t\t\t\t// This flag makes lip tricks always happen, hooray!\r\n\t\t|| (\r\n\t\t\tGetVel()[Y] > 0.0f\t\t\t\t\t\t\t\t\t\t\t// going upwards\r\n\t\t\t&& Mth::Abs(GetMatrix()[Y][Y]) < HorizSine\t\t   \t\t\t// fairly horizontal skater\r\n\t\t\t&& GetMatrix()[Z][Y] > 0.0f\t\t\t\t\t\t\t\t\t// Facing fairly up in the air\r\n\t\t\t&& Mth::Abs(m_current_normal[Y]) < VertCos\t\t\t\t\t// last poly we were on was near vert\r\n\t\t\t&& Mth::Abs(GetMatrix()[X][Y]) < LipAllowSine\t\t \t\t\t// skater pointing fairly straight up\r\n\t\t)) && !no_lip_tricks)\r\n\t{\r\n\t\t// Reset a bunch of stuff.\r\n\t\tGetVel().Set(0.0f, 0.0f, 0.0f);\r\n\t\tDUMP_VELOCITY;\r\n\t\tSetFlagFalse(VERT_AIR);\r\n\t\tSetFlagFalse(TRACKING_VERT);\r\n\t\tSetFlagFalse(LAST_POLY_WAS_VERT);\r\n\t\tSetFlagFalse(CAN_BREAK_VERT);\r\n\t\t// SetFlagFalse(LEAN);\r\n\t\t\r\n\t\t// Make sure any other balance trick is stopped.\r\n\t\tmp_balance_trick_component->stop_balance_trick();\r\n\t\t\r\n\t\tm_pre_lip_pos = GetPos();\r\n\t\t\r\n\t\t// Into the lip state\r\n\t\tSetState(LIP);\r\n\t\t\r\n\t\t// Snap the position\r\n\t\tGetPos() = rail_pos;\r\n\t\tDUMP_POSITION;\r\n\t\r\n\t\t// Pop the skater horizontal\r\n\t\tMth::Vector u = m_current_normal;\r\n\t\tu[Y] = 0.0f;\r\n\t\tu.Normalize();\r\n\t\tGetMatrix()[Y] = u;\t\t\r\n\t\t\r\n\t\tGetMatrix()[Z].Set(0.0f, 1.0f, 0.0f);\r\n\t\t\r\n\t\t#if 0 // old code\r\n\t\t// GetMatrix()[X] = Mth::CrossProduct(m_matrix[Y],m_matrix[Z]);\r\n\t\t// GetMatrix()[X].Normalize();\r\n\t\t#else\r\n\t\tGetMatrix()[X].Set(\r\n\t\t\t-GetMatrix()[Y][Z],\r\n\t\t\t0.0f,\r\n\t\t\tGetMatrix()[Y][X],\r\n\t\t\t0.0f\r\n\t\t);\r\n\t\t#endif\r\n\r\n\t\tResetLerpingMatrix();\r\n\t\t\r\n\t\t// Update the \"Require_Lip\" flag so lip only gaps don't need to wait on frame\r\n\t\tGetSkaterGapComponentFromObject(GetObject())->UpdateCancelRequire(0,REQUIRE_LIP);\r\n\t\t\r\n\t\t\r\n\t\t// Trigger the lip on event.\r\n\t\tmaybe_trip_rail_trigger(TRIGGER_LIP_ON);\r\n\r\n\t\tmp_trick_component->mUseSpecialTrickText = false;\r\n\t\t\r\n\t\tif (!GetObject()->GetScript())\r\n\t\t{\r\n\t\t\tGetObject()->SetScript(new Script::CScript);\r\n\t\t}\r\n\r\n\t\t// Run the lip script.\r\n\t\tGetObject()->GetScript()->SetScript(CRCD(0x1647cf96, \"LipTrick\"), NULL, GetObject());\r\n\t\tGetObject()->GetScript()->Update();\r\n\t\r\n\t\t// Set the mDoingTrick flag so that the camera can detect that a trick is being done.\r\n\t\tmp_state_component->SetDoingTrick(true);\r\n\r\n\t\tset_terrain(mp_rail_node->GetTerrain());\r\n\t\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// no lip trick, so we rail\r\n\t\r\n\tset_terrain(mp_rail_node->GetTerrain());\r\n\t\t\t  \r\n\tconst CRailNode* pStart = mp_rail_node;\r\n\tconst CRailNode* pEnd = pStart->GetNextLink();\r\n\r\n\tMth::Vector\tdir = mp_rail_man->GetPos(pEnd) - mp_rail_man->GetPos(pStart);\r\n\tdir.Normalize();\r\n\t\r\n\t// Now, we've get a rail\r\n\t\r\n\t// check for collision in moving from m_pos to rail_pos\r\n\t\r\n\tm_col_start = GetPos();\r\n\tm_col_end = rail_pos;\r\n\tif (get_member_feeler_collision())\r\n\t{\r\n\t\t// check distance from the rail to the collision point\r\n\t\tif ((rail_pos - m_feeler.GetPoint()).LengthSqr() > 6.0f * 6.0f) \r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (GetFlag(IN_ACID_DROP))\r\n\t{\r\n\t\tMESSAGE(\"GRINDING FROM ACID DROP\");\r\n\t\tDUMPV(acid_hold);\r\n\t\tDUMP_VELOCITY;\r\n\t\tGetVel() += acid_hold;\r\n\t\tDUMP_VELOCITY;\r\n\t}\r\n\r\n\t// we need to check if this is the end of the rail and we are going to come off it next frame, then we don't want to get on it....\r\n\r\n\t// check first if we are not moving much in the XY and if not, then se the XZ velocity to the matrix[Z], so we always go forward\r\n\tif (GetVel()[X] == 0.0f && GetVel()[Z] == 0.0f)\r\n\t{\r\n\t\tGetVel()[X] = GetMatrix()[Z][X];\r\n\t\tGetVel()[Z] = GetMatrix()[Z][Z];\r\n\t}\r\n\t\r\n\t//////////////////////////////////////////////////////////////////\t\t\t\r\n\t// Mick: Start of patch\r\n\t// (For Oil Rig type problem with steep rails)\r\n\t// if we are moving forward, then rotate velocity onto a horizontal plane\r\n\t// so we don't seem to be going backwards up steep rails when we jump onto them\r\n\t\r\n\t#if 0 // old code\r\n\t// Mth::Vector flat_vel = GetVel();\r\n\t// flat_vel[Y] = 0;\r\n\t// if (flat_vel.Length() > 10.0f)\r\n\t// {\r\n\t\t// GetVel().RotateToPlane(Mth::Vector(0.0f,1.0f,0.0f));\r\n\t//}\r\n\t#else\r\n\tif (!from_walk && GetVel()[X] * GetVel()[X] + GetVel()[Z] * GetVel()[Z] > 10.0f * 10.0f)\r\n\t{\r\n\t\tGetVel().RotateToPlane(Mth::Vector(0.0f, 1.0f, 0.0f));\r\n\t\tDUMP_VELOCITY;\r\n\t}\r\n\t#endif\r\n\t\r\n\t//\r\n\t// Mick: end of patch\r\n\t/////////////////////////////////////////////////////////////////////\r\n\r\n\tfloat dot = Mth::DotProduct(dir, GetVel());\r\n\t\r\n\t// sign is which way we are going along the rail\r\n\tfloat sign;\r\n\tif (dot == 0.0f)\r\n\t{\r\n\t\t// if the dot product can not determine the direction (pull up from hangs), choose randomly\r\n\t\tsign = Mth::Rnd(2) ? 1.0f : -1.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t   sign = Mth::Sgn(dot);\r\n\t}\r\n\t\r\n\tif (sign < 0.0f)\r\n\t{\r\n\t\t// will be going backwards along the rail\r\n\t\t\r\n\t\t// if the rail stick point is this last point, then we don't want to snap to it as we will immediatly fly off,\r\n\t\t// and the point might be coincident with a wall or the ground and that will cause problems\r\n\t\tif (!pStart->GetPrevLink() && mp_rail_man->GetPos(pStart) == rail_pos) return;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// same for going forward along the rail\r\n\t\tif (!pEnd->GetNextLink() && mp_rail_man->GetPos(pEnd) == rail_pos) return;\r\n\t}\r\n\t\r\n\t// Now we want to see if the rail has a trigger, and if it does, trigger it....\r\n\tmaybe_trip_rail_trigger(TRIGGER_LAND_ON);\r\n\t\r\n\tGetPos() = rail_pos;\r\n\tDUMP_POSITION;\r\n\t\r\n\t// Now we'v got onto the rail, we need to:\r\n\t// 1) kill velocity perpendicular to the rail\r\n\t// 2) add a speed boost in the direction we are going.\r\n\t\r\n\tSetFlagFalse(VERT_AIR);\r\n\tSetFlagFalse(TRACKING_VERT);\r\n\r\n\t// if we are transitioning from wall to rail, then snap him upright\t\t\r\n\tif (GetState() == WALL)\r\n\t{\r\n\t\tnew_normal(Mth::Vector(0.0f, 1.0f, 0.0f));\r\n\t\tResetLerpingMatrix();\r\n\t}\r\n\t\r\n\tSetState(RAIL);\r\n\t\r\n\t// don't play the rail sound when coming onto a rail from walking\r\n\tif (Tmr::ElapsedTime(mp_physics_control_component->GetStateSwitchTime()) != 0)\r\n\t{\r\n\t\t// play sound based on pre-rail velocity\r\n\t\tmp_sound_component->PlayLandSound(GetObject()->GetVel().Length() / GetSkater()->GetScriptedStat(CRCD(0xcc5f87aa, \"Skater_Max_Max_Speed_Stat\")), mp_state_component->m_terrain);\r\n\t}\r\n\r\n\tfloat old_y = GetVel()[Y];\r\n\tGetVel().ProjectToNormal(dir);\t   \t\t\t\t\t\t\t// kill perp velocity\r\n\tif (from_walk && Mth::DotProduct(GetVel(), GetMatrix()[Z]) < 0.0f)\r\n\t{\r\n\t\tif (GetVel().LengthSqr() < Mth::Sqr(1.1f * mp_walk_component->s_get_param(CRCD(0x896c8888, \"jump_adjust_speed\"))))\r\n\t\t{\r\n\t\t\tGetVel().Set();\r\n\t\t\tsign = Mth::Sgn(Mth::DotProduct(dir, GetMatrix()[Z]));\r\n\t\t}\r\n\t\t\r\n\t}\r\n\tGetVel()[Y] = old_y;\t\t\t\t\t\t\t\t\t\t\t// except for Y\r\n\t\r\n\tGetVel() += dir * sign * GetPhysicsFloat(CRCD(0x457bb395, \"Rail_Speed_Boost\"));\t// add speed boost\t\t\t\r\n\tDUMP_VELOCITY;\r\n\t\r\n\t// Ken stuff ...\r\n\tbool Rail_RightOfRail = false;\r\n\tbool Rail_Parallel = false;\r\n\tmRail_Backwards = false;\r\n\r\n\tif (sign < 0.0f)\r\n\t{\r\n\t\tdir = -dir;\r\n\t}\r\n\t// dir is now the unit vector pointing along the rail in the direction we will be moving on the rail\r\n\t\t\r\n\t// Calculate which side of the rail we're on\r\n\t#if 0 // old code\r\n\t// Mth::Vector d = rail_pos - m_last_ground_pos;\r\n\t// Mth::Vector side_vel(d.GetZ(), 0.0f, -d.GetX());\r\n\t// if (Mth::DotProduct(dir, side_vel) < 0.0f)\r\n\t// {\r\n\t\t// Rail_RightOfRail = true;\r\n\t// }\t\r\n\t#else\r\n\tfloat side_vel_X = rail_pos[Z] - m_last_ground_pos[Z];\r\n\tfloat side_vel_Z = -(rail_pos[X] - m_last_ground_pos[X]);\r\n\tif (dir[X] * side_vel_X + dir[Z] * side_vel_Z < 0.0f)\r\n\t{\r\n\t\tRail_RightOfRail = true;\r\n\t}\r\n\t#endif\r\n\t\r\n\t///////////////////////////////////////////////////////////////////////////////////\r\n\t// \t\t\t\t\t\t\t   Bad ledge detection\r\n\t///////////////////////////////////////////////////////////////////////////////////\r\n\t\r\n\t// Calculate the up and down offsets for collision test.\r\n\tm_col_start.Set(0.0f, GetPhysicsFloat(CRCD(0xe4d79235, \"Physics_Ground_Snap_Up\")), 0.0f, 0.0f);\r\n\tm_col_end.Set(0.0f, -GetPhysicsFloat(CRCD(0x9cd7ed5c, \"Rail_Bad_Ledge_Drop_Down_Dist\")), 0.0f, 0.0f);\r\n\t\r\n\t// Add the rail pos, so start and end are now above and below the rail.\r\n\tm_col_start += rail_pos;\r\n\tm_col_end += rail_pos;\r\n\r\n\t// Calculate a side offset, using the rail direction rotated 90 degrees.\r\n\tMth::Vector Off(dir[Z], 0.0f, -dir[X], 0.0f);\r\n\tOff *= GetPhysicsFloat(CRCD(0x31669752, \"Rail_Bad_Ledge_Side_Dist\"));\r\n\r\n\t// Add the offset and do the left collision.\r\n\tm_col_start += Off;\r\n\tm_col_end += Off;\r\n\tbool LeftCollision = get_member_feeler_collision();\r\n\t\r\n\t// Move across to the other side and do the right collision.\r\n\tm_col_start -= 2.0f * Off;\r\n\tm_col_end -= 2.0f * Off;\r\n\tbool RightCollision = get_member_feeler_collision();\r\n\t\r\n\t// Bit of logic to get whether it's a bad ledge or not.\r\n\tmBadLedge = (LeftCollision && !Rail_RightOfRail) || (RightCollision && Rail_RightOfRail);\r\n\tmLedge = LeftCollision || RightCollision;\r\n\t\r\n\t///////////////////////////////////////////////////////////////////////////////////\r\n\t\r\n\tfloat RightDot = Mth::DotProduct(dir, GetMatrix()[X]);\r\n\tfloat FrontDot = Mth::DotProduct(dir, GetMatrix()[Z]);\r\n\t\r\n\tif (Mth::Abs(RightDot) < GetPhysicsFloat(CRCD(0xd0688d4e, \"Rail_Tolerance\")))\r\n\t{\r\n\t\t// The skater's right vector is close to perpendicular to the rail, so the skater must be pointing fairly parallel to it.\r\n\t\tRail_Parallel = true;\r\n\t\t\r\n\t\t// Use the front vector to determine forwards/backwards, since the front vector is fairly parallel to the rail.\r\n\t\tif (FrontDot < 0.0f)\r\n\t\t{\r\n\t\t\tmRail_Backwards = true;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (GetFlag(FLIPPED))\r\n\t\t{\r\n\t\t\tRightDot = -RightDot;\r\n\t\t}\r\n\t\t\t\r\n\t\t// The skater's right vector is fairly parallel to the rail, so use it to determine forwards/backwards.\r\n\t\tif (RightDot < 0.0f)\r\n\t\t{\r\n\t\t\tmRail_Backwards = true;\r\n\t\t}\r\n\t}\r\n\r\n\tmp_trick_component->mUseSpecialTrickText = false;\r\n\r\n\tif (!mp_trick_component->TriggerAnyExtraGrindTrick(\r\n\t\t\tRail_RightOfRail,\r\n\t\t\tRail_Parallel,\r\n\t\t\tmRail_Backwards,\r\n\t\t\tGetFlag(FLIPPED))\r\n\t\t)\r\n\t{\r\n\t\tdo_grind_trick(CSkaterPad::sGetDirection(\r\n\t\t\tcontrol_pad.m_up.GetPressed(),\r\n\t\t\tcontrol_pad.m_down.GetPressed(),\r\n\t\t\tcontrol_pad.m_left.GetPressed(),\r\n\t\t\tcontrol_pad.m_right.GetPressed()\r\n\t\t), Rail_RightOfRail, Rail_Parallel, mRail_Backwards, GetFlag(FLIPPED));\r\n\t}\t\r\n\t\r\n\t// (Mick) Set m_rail_time, otherwise there is a single frame where it is invalid\r\n\t// and this allows us to immediately re-rail and hence do the \"insta-bail\", since the triangle button will be held down   \r\n\tm_rail_time  = Tmr::GetTime();\r\n}\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::do_lip_physics (   )\r\n{\r\n\tSetFlagFalse(SPINE_PHYSICS);\r\n\tSetFlagFalse(IN_ACID_DROP);\r\n\tSetFlagFalse(IN_RECOVERY);\r\n\t\r\n\tif (mp_movable_contact_component->UpdateContact(GetPos()))\r\n\t{\r\n\t\tGetPos() += mp_movable_contact_component->GetContact()->GetMovement();\r\n\t\tDUMP_POSITION;\r\n\t\t\r\n\t\t// this is close to correct, 'cept that but because of rotation, it's not quite right\r\n\t\tm_pre_lip_pos += mp_movable_contact_component->GetContact()->GetMovement();\r\n\t\t\r\n\t\tif (mp_movable_contact_component->GetContact()->IsRotated())\r\n\t\t{\r\n\r\n\t\t\tGetMatrix() *= mp_movable_contact_component->GetContact()->GetRotation();\r\n\t\t\tm_lerping_display_matrix *= mp_movable_contact_component->GetContact()->GetRotation();\r\n\t\t}\r\n\t}\r\n\t\r\n\t#ifdef __USER_DAN__\r\n\tif (Script::GetInteger(CRCD(0x1a5eab7, \"rail_highlights\")))\r\n\t{\r\n\t\tGfx::AddDebugLine(mp_rail_man->GetPos(mp_rail_node), mp_rail_man->GetPos(mp_rail_node->GetNextLink()), MAKE_RGB(Mth::Rnd(256), Mth::Rnd(256), Mth::Rnd(256)), 0, 1);\r\n\t\tGfx::AddDebugLine(mp_rail_man->GetPos(mp_rail_node) + Mth::Vector(1.0f, 0.0f, 0.0f), mp_rail_man->GetPos(mp_rail_node->GetNextLink()) + Mth::Vector(1.0f, 0.0f, 0.0f), MAKE_RGB(Mth::Rnd(256), Mth::Rnd(256), Mth::Rnd(256)), 0, 1);\r\n\t\tGfx::AddDebugLine(mp_rail_man->GetPos(mp_rail_node) + Mth::Vector(0.0f, 1.0f, 0.0f), mp_rail_man->GetPos(mp_rail_node->GetNextLink()) + Mth::Vector(0.0f, 1.0f, 0.0f), MAKE_RGB(Mth::Rnd(256), Mth::Rnd(256), Mth::Rnd(256)), 0, 1);\r\n\t\tGfx::AddDebugLine(mp_rail_man->GetPos(mp_rail_node) + Mth::Vector(0.0f, 0.0f, 1.0f), mp_rail_man->GetPos(mp_rail_node->GetNextLink()) + Mth::Vector(0.0f, 0.0f, 1.0f), MAKE_RGB(Mth::Rnd(256), Mth::Rnd(256), Mth::Rnd(256)), 0, 1);\r\n\t}\r\n\t#endif\r\n\t\r\n\t// Update any balance control required.\r\n\tif (mp_balance_trick_component->mBalanceTrickType == CRCD(0xa549b57b, \"Lip\"))\r\n\t{\r\n\t\tif (Mdl::Skate::Instance()->GetCareer()->GetCheat(CRCD(0xcd09e062, \"CHEAT_PERFECT_RAIL\")))\r\n\t\t{\r\n\t\t\t// Here, set the flag. It may seem redundant, but the above line is very likely\r\n\t\t\t// to be hacked by gameshark. They probably won't notice this one, which will\r\n\t\t\t// set the flags as if they had actually enabled the cheat -- which enables us\r\n\t\t\t// to detect that it has been turned on more easily.\r\n\t\t\tMdl::Skate::Instance()->GetCareer()->SetGlobalFlag( Script::GetInteger(CRCD(0xcd09e062, \"CHEAT_PERFECT_RAIL\")));\r\n\t\t\tmp_balance_trick_component->mLip.mManualLean = 0.0f;\r\n\t\t\tmp_balance_trick_component->mLip.mManualLeanDir = 0.0f;\r\n\t\t\tg_CheatsEnabled = true;\r\n\t\t}\r\n\t\tmp_balance_trick_component->mLip.DoManualPhysics();\r\n\t}\r\n\t\r\n\thandle_tensing();\r\n\tif (maybe_flag_ollie_exception())\t\r\n\t{\r\n\t\t// Trigger the lip jump event.\r\n\t\tmaybe_trip_rail_trigger(TRIGGER_LIP_JUMP);\r\n\t}\r\n\r\n\t// lip tricks are very rail-like when determining which world sector you've just tricked off of\r\n\tif (mp_rail_node)\r\n\t{\r\n\t\tif (mp_rail_man->GetNodeArray())\r\n\t\t{\r\n\t\t\tconst CRailNode* pRail = mp_rail_node;\r\n\t\t\tScript::CArray* pNodeArray = Script::GetArray(CRCD(0xc472ecc5, \"NodeArray\"));\r\n\t\t\tScript::CStruct* pNode = pNodeArray->GetStructure(pRail->GetNode());\r\n\t\t\tpNode->GetChecksum(CRCD(0xa1dc81f9, \"name\"), &m_last_rail_node_name, Script::ASSERT);\r\n\t\t\tmp_trick_component->TrickOffObject(m_last_rail_node_name);\r\n\t\t}\r\n\t}\r\n\t\r\n\tm_lip_time = Tmr::GetTime();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::do_rail_physics (   )\r\n{\r\n\tSetFlagFalse(SPINE_PHYSICS);\r\n\tSetFlagFalse(IN_ACID_DROP);\r\n\tSetFlagFalse(IN_RECOVERY);\r\n\tSetFlagFalse(AIR_ACID_DROP_DISALLOWED);\r\n\r\n\t// First of all we apply the movement due to contact; best to do it first, as then we will be on the rail we are moving along\r\n\r\n\tif (mp_movable_contact_component->HaveContact())\r\n\t{\r\n\t\t// need to update the transform of the rail manager\r\n\t\t// no need to do this\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\tCRailManagerComponent* p_rail_manager_component = GetRailManagerComponentFromObject(mp_movable_contact_component->GetContact()->GetObject());\r\n\t\tDbg_Assert(p_rail_manager_component);\r\n\t\t\r\n\t\tp_rail_manager_component->UpdateRailManager();\r\n\t\r\n\t\tif (mp_movable_contact_component->UpdateContact(GetPos()))\r\n\t\t{\r\n\t\t\t\r\n\t\t\tGetPos() += mp_movable_contact_component->GetContact()->GetMovement();\r\n\t\t\tDUMP_POSITION;\r\n\t\t\tif (mp_movable_contact_component->GetContact()->IsRotated())\r\n\t\t\t{\r\n\t\t\t\tGetMatrix() *= mp_movable_contact_component->GetContact()->GetRotation();\r\n\t\t\t\tm_lerping_display_matrix *= mp_movable_contact_component->GetContact()->GetRotation();\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t}\r\n\t}\r\n\r\n\t// set default rerail time\t\r\n\tm_rerail_time = static_cast< Tmr::Time >(GetPhysicsFloat(CRCD(0x2b4645ad, \"Rail_minimum_rerail_time\")));\r\n\t// and dissalow any overriding of this\r\n\tSetFlagFalse(CAN_RERAIL);\t\t// dont allow rerailing after coming off a segment\r\n\r\n\t\r\n\tif (maybe_flag_ollie_exception())\r\n\t{\r\n\t\tmaybe_trip_rail_trigger(TRIGGER_JUMP_OFF);\r\n\t\t\r\n\t\tm_rerail_time = static_cast< Tmr::Time >(GetPhysicsFloat(CRCD(0xbf35053, \"Rail_jump_rerail_time\")));\r\n\t\t\r\n\t\tSetFlagTrue(OLLIED_FROM_RAIL);\r\n\t\t\r\n\t\t// when we jump off a rail, then raise him up one inch, so we don't collide with the top of a fence or something\r\n\t\tGetPos()[Y] += 1.0f;\t\t\t// up one inch......\r\n\t\tDUMP_POSITION;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tswitch (mp_balance_trick_component->mBalanceTrickType)\r\n\t\t{\r\n\t\t\tcase 0:\r\n\t\t\tcase 0x0ac90769: // NoseManual\t\r\n\t\t\tcase 0xef24413b: // Manual\r\n\t\t\tcase 0xa549b57b: // Lip\t\r\n\t\t\t\tbreak;\r\n\t\t\t\t\r\n\t\t\tcase 0x255ed86f: // Grind\r\n\t\t\tcase 0x8d10119d: // Slide\r\n\t\t\t\tmp_balance_trick_component->mGrind.DoManualPhysics();\r\n\t\t\t\tif (Mdl::Skate::Instance()->GetCareer()->GetCheat(CRCD(0xcd09e062, \"CHEAT_PERFECT_RAIL\")))\r\n\t\t\t\t{\r\n\t\t\t\t\t// Here, set the flag. It may seem redundant, but the above line is very likely\r\n\t\t\t\t\t// to be hacked by gameshark. They probably won't notice this one, which will\r\n\t\t\t\t\t// set the flags as if they had actually enabled the cheat -- which enables us\r\n\t\t\t\t\t// to detect that it has been turned on more easily.\r\n\t\t\t\t\tMdl::Skate::Instance()->GetCareer()->SetGlobalFlag( Script::GetInteger(CRCD(0xcd09e062, \"CHEAT_PERFECT_RAIL\")));\r\n\t\t\t\t\tmp_balance_trick_component->mGrind.mManualLean = 0.0f;\r\n\t\t\t\t\tmp_balance_trick_component->mGrind.mManualLeanDir = 0.0f;\r\n\t\t\t\t\tg_CheatsEnabled = true;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\t\r\n\t\t\t\t\t\t\r\n\t\t\tdefault:\t\r\n\t\t\t\tDbg_Assert(false);\r\n\t\t\t\tbreak;\r\n\t\t}\t\t\r\n\t\r\n\t\t// Get the rail segments\r\n\r\n\t\tconst CRailNode* pStart = mp_rail_node;\r\n\t\tconst CRailNode* pEnd = pStart->GetNextLink();\r\n\t\t\r\n\t\tconst CRailNode* pFrom = pStart;\r\n\t\tconst CRailNode* pOnto = NULL;\r\n\t\t\r\n\t\t#ifdef __USER_DAN__\r\n\t\tif (Script::GetInteger(CRCD(0x1a5eab7, \"rail_highlights\")))\r\n\t\t{\r\n\t\t\tGfx::AddDebugLine(mp_rail_man->GetPos(pStart), mp_rail_man->GetPos(pEnd), MAKE_RGB(Mth::Rnd(256), Mth::Rnd(256), Mth::Rnd(256)), 0, 1);\r\n\t\t\tGfx::AddDebugLine(mp_rail_man->GetPos(pStart) + Mth::Vector(1.0f, 0.0f, 0.0f), mp_rail_man->GetPos(pEnd) + Mth::Vector(1.0f, 0.0f, 0.0f), MAKE_RGB(Mth::Rnd(256), Mth::Rnd(256), Mth::Rnd(256)), 0, 1);\r\n\t\t\tGfx::AddDebugLine(mp_rail_man->GetPos(pStart) + Mth::Vector(0.0f, 1.0f, 0.0f), mp_rail_man->GetPos(pEnd) + Mth::Vector(0.0f, 1.0f, 0.0f), MAKE_RGB(Mth::Rnd(256), Mth::Rnd(256), Mth::Rnd(256)), 0, 1);\r\n\t\t\tGfx::AddDebugLine(mp_rail_man->GetPos(pStart) + Mth::Vector(0.0f, 0.0f, 1.0f), mp_rail_man->GetPos(pEnd) + Mth::Vector(0.0f, 0.0f, 1.0f), MAKE_RGB(Mth::Rnd(256), Mth::Rnd(256), Mth::Rnd(256)), 0, 1);\r\n\t\t}\r\n\t\t#endif\r\n\t\t\r\n\t\tMth::Vector\tdir = mp_rail_man->GetPos(pEnd) - mp_rail_man->GetPos(pStart);\r\n\t\tfloat segment_length = dir.Length();\r\n\t\tdir *= 1.0f / segment_length;\r\n\r\n\t\t// sign is which way we are going along the rail\r\n\t\tfloat old_sign = Mth::Sgn(Mth::DotProduct(dir, GetVel()));\r\n\r\n\t\t// Get gravity force \t\r\n\t\tMth::Vector gravity(0.0f, GetPhysicsFloat(CRCD(0xd1f46992, \"Physics_Rail_Gravity\")), 0.0f);\r\n\r\n\t\t// Project gravity onto the line we are on\r\n\t\tgravity.ProjectToNormal(dir);\r\n\t\tGetVel() += gravity * m_frame_length;\r\n\t\tDUMP_VELOCITY;\r\n\t\t\r\n\t\t// sign is which way we are going along the rail\r\n\t\tfloat sign = Mth::Sgn(Mth::DotProduct(dir, GetVel()));\r\n\t\t\r\n\t\t// sign might have changed here\r\n\t\t// so could do the \"flipping on a rail\" thing\r\n\t\t// .................\r\n\t\t\r\n\t\tif (sign != old_sign)\r\n\t\t{\r\n\t\t\t// Note, we JUST flip the \"Backwards\" flag, as we want to stay in essentailly the same\r\n\t\t\t// pose as before, and as the sign of our velocity dotted with the rail has\r\n\t\t\t// changed, then all we need to to is tell the code we are\r\n\t\t\t// going in the opposite direction to what we were going before, and the\r\n\t\t\t// target vector will be calculated correctly.\r\n\t\t\tmRail_Backwards = !mRail_Backwards;\t\t\t \t\t\r\n\t\t}\r\n\t\t\r\n\t\t// check to see if we are on the last segment of the rail\r\n\t\t// this logic could be folded into the logic below but it's perhps clearer to have it here\r\n\t\tbool last_segment = false;\r\n\t\tif (sign < 0.0f)\r\n\t\t{\r\n\t\t\tif (pStart->GetPrevLink() && pStart->GetPrevLink()->IsActive())\r\n\t\t\t{\r\n\t\t\t\tMth::Vector v1, v2;\r\n\t\t\t\tv1 = mp_rail_man->GetPos(pEnd) - mp_rail_man->GetPos(pStart);\r\n\t\t\t\tv2 = mp_rail_man->GetPos(pStart) - mp_rail_man->GetPos(pStart->GetPrevLink());\r\n\t\t\t\tv1[Y] = 0.0f;\r\n\t\t\t\tv2[Y] = 0.0f;\r\n\t\t\t\tv1.Normalize();\r\n\t\t\t\tv2.Normalize();\r\n\t\t\t\tfloat dot = Mth::DotProduct(v1, v2);\r\n\t\t\t\tif (dot < cosf(Mth::DegToRad(GetPhysicsFloat(CRCD(0x76c1da15, \"Rail_Corner_Leave_Angle\")))))\r\n\t\t\t\t{\r\n\t\t\t\t\t// there is more, but angle is too sharp\r\n\t\t\t\t\tlast_segment = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpOnto = pStart->GetPrevLink();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tlast_segment = true;\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (pEnd && pEnd->GetNextLink() && pEnd->GetNextLink()->IsActive())\r\n\t\t\t{\r\n\t\t\t\tMth::Vector  v1,v2;\r\n\t\t\t\tv1 = mp_rail_man->GetPos(pStart) - mp_rail_man->GetPos(pEnd);\r\n\t\t\t\tv2 = mp_rail_man->GetPos(pEnd) - mp_rail_man->GetPos(pEnd->GetNextLink());\r\n\t\t\t\tv1[Y] = 0.0f;\r\n\t\t\t\tv2[Y] = 0.0f;\r\n\t\t\t\tv1.Normalize();\r\n\t\t\t\tv2.Normalize();\r\n\t\t\t\tfloat dot = Mth::DotProduct(v1,v2);\r\n\t\t\t\tif (dot < cosf(Mth::DegToRad(GetPhysicsFloat(CRCD(0x76c1da15,\"Rail_Corner_Leave_Angle\")))))\r\n\t\t\t\t{\r\n\t\t\t\t\t// there is more, but angle is too sharp\r\n\t\t\t\t\tlast_segment = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpOnto = pEnd;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tlast_segment = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Now we need to see if we have gone beyond the end of the rail segment\r\n\t\t\r\n\t\tfloat extra_dist = 0.0f;\r\n\t\t\t\r\n\t\tfloat length_along;\r\n\t\tif (sign < 0.0f)\r\n\t\t{\r\n\t\t\t// going backwards, so it's the distance from the end of the segment\r\n\t\t\tlength_along = (GetPos() - mp_rail_man->GetPos(pEnd)).Length();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// going forwards, so it's the distance from the start\r\n\t\t\tlength_along = (GetPos() - mp_rail_man->GetPos(pStart)).Length();\r\n\t\t}\r\n\t\t\r\n\t\tif (length_along > segment_length + 0.1f)\t// 0.1 inch, so we don't get stuck\r\n\t\t{\r\n\t\t\t// remember this, so we can move along next segment\r\n\t\t\textra_dist = length_along - segment_length;\r\n\t\t\t\r\n\t\t\t// gone off the end of the segment\r\n\t\t\tif (sign < 0.0f)\r\n\t\t\t{\r\n\t\t\t\tif (pStart->GetPrevLink()\r\n\t\t\t\t\t&& pStart->GetPrevLink()->IsActive()\r\n\t\t\t\t\t&& Rail_ValidInEditor(mp_rail_man->GetPos(pStart), mp_rail_man->GetPos(pStart->GetPrevLink())))\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!last_segment)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// go onto previous segment\r\n\t\t\t\t\t\tGetPos() = mp_rail_man->GetPos(pStart);\r\n\t\t\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t\t\tmp_rail_node = pStart->GetPrevLink();\r\n\t\t\t\t\t\tset_terrain(mp_rail_node->GetTerrain());\r\n\t\t\t\t\t\tmaybe_trip_rail_trigger(TRIGGER_SKATE_ONTO);\r\n\t\t\t\t\t}\t\t   \r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tskate_off_rail(mp_rail_man->GetPos(pStart));\r\n\t\t\t\t\t} \t\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tskate_off_rail(mp_rail_man->GetPos(pStart));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (pEnd->GetNextLink()\r\n\t\t\t\t\t&& pEnd->IsActive()\r\n\t\t\t\t\t&& Rail_ValidInEditor(mp_rail_man->GetPos(pEnd), mp_rail_man->GetPos(pEnd->GetNextLink())))\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!last_segment)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tGetPos() = mp_rail_man->GetPos(pEnd);\r\n\t\t\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t\t\tmp_rail_node = pEnd;\t\t\t\t\t\r\n\t\t\t\t\t\tset_terrain(mp_rail_node->GetTerrain());\r\n\t\t\t\t\t\tmaybe_trip_rail_trigger(TRIGGER_SKATE_ONTO);\t\t\t\t\t\t\r\n\t\t\t\t\t}\t\t   \r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tskate_off_rail(mp_rail_man->GetPos(pEnd));\r\n\t\t\t\t\t} \t\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tskate_off_rail(mp_rail_man->GetPos(pEnd));\r\n\t\t\t\t}\r\n\t\t\t}\t\t\r\n\t\t}\r\n\t\t\r\n\t\tif (GetState() == RAIL)\r\n\t\t{\r\n\t\t\t// recalculate start, end, dir, as we might be on a new segment\r\n\t\t\tconst CRailNode* pStart = mp_rail_node;\r\n\t\t\tconst CRailNode* pEnd = pStart->GetNextLink();\r\n\t\t\t\r\n\t\t\tMth::Vector\tdir = mp_rail_man->GetPos(pEnd) - mp_rail_man->GetPos(pStart);\r\n\t\t\tdir.Normalize();\r\n\r\n\t\t    // sign also may have changed, now that we are auto-linking rail segments\r\n\t\t\t\r\n\t\t\t// sign is which way we are going along the rail\r\n\t\t\tfloat sign = Mth::Sgn(Mth::DotProduct(dir,GetVel()));\r\n\r\n\t\t\tm_rail_time = Tmr::GetTime();\r\n\t\t\t\t\t\t\t\t\r\n\t\t\tGetVel().RotateToNormal(dir);\r\n\t\t\tGetVel() *= sign;\t\t\t\t\t\t   \t\t\t\t\t\t// sign won't be on a new segment\r\n\t\t\tDUMP_VELOCITY;\r\n\r\n\t\t\tfloat facing_sign = mRail_Backwards ? -sign : sign;\r\n\t\t\t\r\n\t\t\t// z is forward\r\n\t\t\tMth::Vector target_forward = dir * facing_sign;\r\n\r\n\t\t\tm_lerping_display_matrix[Z] = Mth::Lerp(m_lerping_display_matrix[Z], target_forward, 0.3f);\r\n\t\t\tm_lerping_display_matrix[Z].Normalize(); \r\n\t\t\t\r\n\t\t\t#if 0 // old code\r\n\t\t\t// m_lerping_display_matrix[Y].Set(0.0f, 1.0f, 0.0f);\r\n\t\t\t// m_lerping_display_matrix[X] = Mth::CrossProduct(\r\n\t\t\t\t// m_lerping_display_matrix[Y],\r\n\t\t\t\t// m_lerping_display_matrix[Z]\r\n\t\t\t// );\r\n\t\t\t#else\r\n\t\t\tm_lerping_display_matrix[X].Set(\r\n\t\t\t\tm_lerping_display_matrix[Z][Z],\r\n\t\t\t\t0.0f,\r\n\t\t\t\t-m_lerping_display_matrix[Z][X],\r\n\t\t\t\t0.0f\r\n\t\t\t);\r\n\t\t\t#endif\r\n\t\t\tm_lerping_display_matrix[X].Normalize();\r\n\t\t\t\r\n\t\t\tm_lerping_display_matrix[Y] = Mth::CrossProduct(\r\n\t\t\t\tm_lerping_display_matrix[Z],\r\n\t\t\t\tm_lerping_display_matrix[X]\r\n\t\t\t);\r\n\t\t\tm_lerping_display_matrix[Y].Normalize();\r\n\r\n\t\t\t// adjust our Z value towards the new value\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\tGetMatrix()[Z] = target_forward;\r\n\t\t\tGetMatrix()[Z].Normalize(); \r\n\t\t\t\r\n\t\t\t#if 0 // old code\r\n\t\t\t// GetMatrix()[Y].Set(0.0f, 1.0f, 0.0f);\r\n\t\t\t// GetMatrix()[X] = Mth::CrossProduct(GetMatrix()[Y],GetMatrix()[Z]);\r\n\t\t\t#else\r\n\t\t\tGetMatrix()[X].Set(\r\n\t\t\t\tGetMatrix()[Z][Z],\r\n\t\t\t\t0.0f,\r\n\t\t\t\t-GetMatrix()[Z][X],\r\n\t\t\t\t0.0f\r\n\t\t\t);\r\n\t\t\t#endif\r\n\t\t\tGetMatrix()[X].Normalize();\r\n\t\t\t\r\n\t\t\tGetMatrix()[Y] = Mth::CrossProduct(GetMatrix()[Z], GetMatrix()[X]);\r\n\t\t\tGetMatrix()[Y].Normalize();\r\n\r\n\t\t\tMth::Vector m_movement(0.0f, 0.0f, 0.0f);\r\n\t\t\t\r\n\t\t\t// This is where we do the actual movement\r\n\t\t\t\r\n\t\t\t// if this makes us bump into the wall or the ground, then we should leave the rail\r\n\t\t\t\r\n\t\t\tMth::Vector old_pos = GetPos();  \t\r\n\t\t\tGetPos() += GetVel() * m_frame_length;\t\t\t// current movement\r\n\t\t\tGetPos() += extra_dist * target_forward;\t\t\t\t\t\t// any extra dist from previous segment\r\n\t\t\tGetPos() += m_movement;\t\t\t\t\t\t\t// movement due to contact with moving object\r\n\t\t\tDUMP_POSITION;\r\n\t\t\t\r\n\t\t\t// Mick:  use \"old_pos\" to generate the direction\r\n\t\t\t// so it is guarenteed to be parallel to the rail\r\n\t\t\t// and m_pos might have been adjusted if we continued from\r\n\t\t\t// one rail to another (in-line) rail, like in the park editor\r\n\t\t\tMth::Vector movement = GetPos() - old_pos;\r\n\t\t\tMth::Vector direction = movement;\r\n\t\t\tdirection.Normalize();\r\n\t\t\t\r\n\t\t\tbool always_check = false;\r\n\t\t\tif (!last_segment && Ed::CParkEditor::Instance()->UsingCustomPark())\r\n\t\t\t{\r\n\t\t\t\t// in the park editor we can have tight curves that end in walls, so we want to always do the forward check\r\n\t\t\t\t// if we are on a segment that is horizontal, and leads to another segment that is also horizontal\r\n\t\t\t\tMth::Vector from = mp_rail_man->GetPos(pFrom->GetNextLink()) - mp_rail_man->GetPos(pFrom);\t\t\t\t\r\n\t\t\t\tMth::Vector onto = mp_rail_man->GetPos(pOnto->GetNextLink()) - mp_rail_man->GetPos(pOnto);\t\t\r\n\t\t\t\tfrom.Normalize();\r\n\t\t\t\tonto.Normalize();\r\n\t\t\t\tfloat delta = Mth::Abs(from[Y] - onto[Y]);\t\t\r\n\t\t\t\tif (delta < 0.01f)\r\n\t\t\t\t{\r\n\t\t\t\t\t// lines have a sufficently close Y angle\r\n\t\t\t\t\talways_check = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Only check for hitting a wall if we are on a segment of rail that has no more rail\r\n\t\t\tif (last_segment || always_check)\r\n\t\t\t{\r\n\t\t\t\tm_col_start = old_pos;\r\n\t\t\t\tm_col_end = GetPos();\r\n\t\t\t\tm_col_end += movement + (direction * 6.0f);\r\n\t\t\t\t\r\n\t\t\t\t// raise them up one inch, so we don't collide with the rail\r\n\t\t\t\tm_col_start += GetMatrix()[Y];\t\t\t \r\n\t\t\t\tm_col_end += GetMatrix()[Y];  \r\n\t\t\t\tif (get_member_feeler_collision())\r\n\t\t\t\t{\r\n\t\t\t\t\t// if in the park editor, then ignore collision with invisible surfaces \r\n\t\t\t\t\tif (!Ed::CParkEditor::Instance()->UsingCustomPark() || !(m_feeler.GetFlags() & mFD_INVISIBLE))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmaybe_trip_rail_trigger(TRIGGER_SKATE_OFF);\r\n\t\t\t\t\t\t// don't let him make this movement!!\r\n\t\t\t\t\t\tGetPos() = GetOldPos();\r\n\t\t\t\t\t\tGetPos()[Y] += 1.0f;\r\n\t\t\t\t\t\tDUMP_POSITION;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// project velocity along the plane if we run into a wall\r\n\t\t\t\t\t\tGetVel().ProjectToPlane(m_feeler.GetNormal());\r\n\t\t\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tSetState(AIR);\t\t\t// knocked off rail, as something in front\r\n\t\t\t\t\t\tFLAGEXCEPTION(CRCD(0xafaa46ba, \"OffRail\"));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\t\r\n\t}\t\t\t\r\n\t\r\n\t// set the normal value, so the camera is not too confused\r\n\tm_current_normal = GetMatrix()[Y];\r\n\t  \r\n\t// Add mGrindTweak to the score.\r\n\t// adjusted by the robot rail mult (1.0 to 0.1, depending on how much you've ground the rail)\r\n\tmp_score_component->GetScore()->TweakTrick(mGrindTweak * mp_score_component->GetScore()->GetRobotRailMult());\r\n\r\n\t// if we've already started doing a trick, then start remembering our trick chain\r\n\t{\r\n\t\tconst CRailNode* pRail = mp_rail_node;\r\n\t\tDbg_Assert(pRail);\r\n\r\n\t\tif (mp_rail_man->GetNodeArray())\r\n\t\t{\r\n\t\t\tScript::CArray* pNodeArray=Script::GetArray(CRCD(0xc472ecc5, \"NodeArray\"));\r\n\t\t\tScript::CStruct* pNode=pNodeArray->GetStructure(pRail->GetNode());\r\n\t\t\tpNode->GetChecksum(CRCD(0xa1dc81f9, \"name\"), &m_last_rail_node_name, true);\r\n\t\t\tmp_trick_component->TrickOffObject(m_last_rail_node_name);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::ollie_off_rail_rotate (   )\r\n{\r\n\tfloat rot;\r\n\tif (mp_input_component->GetControlPad().m_left.GetPressed())\r\n\t{\r\n\t\trot = Mth::DegToRad(GetPhysicsFloat(CRCD(0x38505ef3, \"Rail_Jump_Angle\")));\r\n\t}\r\n\telse if (mp_input_component->GetControlPad().m_right.GetPressed())\r\n\t{\r\n\t\trot = -Mth::DegToRad(GetPhysicsFloat(CRCD(0x38505ef3, \"Rail_Jump_Angle\")));\r\n\t}\r\n\telse return;\r\n\r\n\tGetVel().RotateY(rot);\t\t \r\n\tGetMatrix().RotateYLocal(rot);\t\t\t\t\r\n\tm_lerping_display_matrix.RotateYLocal(rot);\t\t\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::skate_off_rail ( const Mth::Vector& off_point )\r\n{\r\n\t// we have skated off a rail; either it was the end of a rail or we hit a sharp corner\r\n\t// we need to see if there is another rail in front of us that we can continue skating on\r\n\r\n\tbool really_off = true;\r\n\t\r\n\tMth::Vector\ta;\r\n\tif (Ed::CParkEditor::Instance()->UsingCustomPark())\r\n\t{\r\n\t\t// in the park editor, we use the last point on the rail we just took off from as the start of the line to use for looking for new rails\r\n\t\t// so we don't get rail segments earlier in the list\r\n\t\ta = off_point;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// go back a step\r\n\t\ta = GetPos() - GetVel() * m_frame_length;\r\n\t\tDUMP_POSITION;\r\n\t}\r\n\t\r\n\t// use current pos, as we know that is off the end\r\n\tMth::Vector b = GetPos();\r\n\t\r\n\tMth::Vector rail_pos;\t\r\n\tCRailNode* pNode;\t\r\n\t\r\n\r\n\t// we need to tilt the line down, as the rail code currently fails to find a rail if the line we check is exactly parallel with it\t\r\n\ta[Y] += 6.0f;\t\t\t\t\t\t\t   \r\n\tb[Y] += 6.1f;\t\t\t\t\t\t\t   \r\n\r\n\tfloat min_dot = cosf(Mth::DegToRad(GetPhysicsFloat(CRCD(0x76c1da15, \"Rail_Corner_Leave_Angle\"))));\r\n\r\n\t// Note: we are now passing in Rail_Side() of the current rail and velocity\r\n\t// so we can see if we switch from a rail on a left facing ledge to a rail on a right facing ledge, and try to inhibit that type of transition\r\n\t// in favour of one that retains the same side\r\n\tif (mp_rail_man->StickToRail(\r\n\t\t\ta,\r\n\t\t\tb, \r\n\t\t\t&rail_pos,\r\n\t\t\t&pNode,\r\n\t\t\tmp_rail_node,\r\n\t\t\tmin_dot,\r\n\t\t\tmp_rail_node->Side(GetVel())\r\n\t\t))\r\n\t{\t\t\r\n\t\t// Mick, in park editor, we also disallow this if the rail is the next or the prev rail node from our current node\r\n\t\tif (mp_rail_node != pNode && (\r\n\t\t\t\t!Ed::CParkEditor::Instance()->UsingCustomPark()\r\n\t\t\t\t|| mp_rail_node->GetNextLink() != pNode\r\n\t\t\t\t&& mp_rail_node->GetPrevLink() != pNode\r\n\t\t\t))\r\n\t\t{\r\n\t\t\tconst CRailNode* pNewStart = pNode;\r\n\t\t\tconst CRailNode* pNewEnd = pNewStart->GetNextLink();\t\r\n\t\t\t\r\n\t\t\t// check to see if our new position is within the two points\r\n\t\t\tMth::Vector\tto_start = mp_rail_man->GetPos(pNewStart) - GetPos();\r\n\t\t\tMth::Vector\tto_end = mp_rail_man->GetPos(pNewEnd) - GetPos();\r\n\t\t\t\r\n\t\t\tfloat mid_dot = Mth::DotProduct(to_start, to_end);\r\n\r\n\t\t\t// In game, the point must actualy be in the line, so mid dot will be negative\r\n\t\t\tbool ok = mid_dot < 0.0f;\t\t\t\t\t\r\n\t\t\t\r\n\t\t\t// Park Editor specific rail joining\t\t\t\r\n\t\t\tif (!ok && Ed::CParkEditor::Instance()->UsingCustomPark())\r\n\t\t\t{\r\n\t\t\t\t// in the park editor, we let the user overshoot, so he sticks to tight curves that are between two pieces\r\n\t\t\t\tok = true;\r\n\r\n\t\t\t\t// we need to ensure that the rail segment is a good continuation of the segment that we were just on\r\n\t\t\t\t// Namely that one of the new start/end points is close to the end of the rail that we just came off\r\n\t\t\t\t// and that the direction we will be going along is within 45 degrees of the direction we were going along before. \r\n\t\t\t\t// (NOT DONE HERE, as the following test is sufficent)\r\n\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\t// first a simple elimination, if the rail is longer than our velocity projected onto it then we can not posibly have overshot it!!\r\n\t\t\t\tMth::Vector\tnew_rail_segment = mp_rail_man->GetPos(pNewEnd) - mp_rail_man->GetPos(pNewStart);\r\n\t\t\t\tMth::Vector skater_movement = b - a;\r\n\t\t\t\tfloat new_rail_length = new_rail_segment.Length();\r\n\t\t\t\tif (new_rail_length > skater_movement.Length())\r\n\t\t\t\t{\r\n\t\t\t\t\tok = false;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// now we could find the shortest distance between two line segments; should be within 2 inches\r\n\t\t\t\t// (ALSO NOT DONE)\r\n\t\t\t\t\r\n\t\t\t\t// bit of a patch for the park editor, it's gone past the end of the rail, so set him in the middle of the rail, so we can continue nicely\r\n\t\t\t\t// possible glitch here, but better than falling of the rail\r\n\t\t\t\t// It's going to be a small rail anyway, so won't look too bad.\r\n\t\t\t\tif (ok && mid_dot >= 0.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\trail_pos = (mp_rail_man->GetPos(pNewEnd) + mp_rail_man->GetPos(pNewStart)) / 2.0f;\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif (ok)\r\n\t\t\t{\r\n\t\t\t\tMth::Vector\tnewdir = mp_rail_man->GetPos(pNewEnd) - mp_rail_man->GetPos(pNewStart);\r\n\t\t\t\tnewdir.Normalize();\r\n\t\t\t\tif (GetVel()[X] == 0.0f && GetVel()[Z] == 0.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\tGetVel()[X] = GetMatrix()[Z][X];\r\n\t\t\t\t\tGetVel()[Z] = GetMatrix()[Z][Z];\r\n\t\t\t\t\tDUMP_VELOCITY;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// sign is which way we are going along the rail\r\n\t\t\t\tfloat sign = Mth::Sgn(Mth::DotProduct(newdir, GetVel()));\r\n\t\t\t\tGetVel().RotateToNormal(newdir);\r\n\t\t\t\tGetVel() *= sign;\r\n\t\t\t\t\r\n\t\t\t\tmp_rail_node = pNode;\t\t// oh yes, this is the node\r\n\t\t\t\tGetPos() = rail_pos;\t\t\t// move to closest position on the line\r\n\t\t\t\tDUMP_POSITION;\r\n\t\t\t\tmaybe_trip_rail_trigger(TRIGGER_SKATE_ONTO);\r\n\t\t\t\tset_terrain(mp_rail_node->GetTerrain());\r\n\t\t\r\n\t\t\t\treally_off = false;\t\t\t\r\n\t\t\t}\t\t\t\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// new position is outside this rail\r\n\t\t\t}\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// its the same as this one\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// did not find any\r\n\t}\r\n\t\r\n\tif (!really_off) return;\r\n\r\n\tmaybe_trip_rail_trigger(TRIGGER_SKATE_OFF);\r\n\tSetState(AIR);\r\n\tGetPos()[Y] += 1.0f;\r\n\tDUMP_POSITION;\r\n\tFLAGEXCEPTION(CRCD(0xafaa46ba,\"OffRail\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::maybe_trip_rail_trigger ( uint32 type )\r\n{\r\n\t// given that m_rail_node is valid, then trigger any script associated with this rail node\r\n\t// will search backwards for the first rail that has a trigger script, and then execute that.\r\n\t\r\n\tif (!mp_rail_node) return;\r\n\t\r\n\tDbg_Assert(mp_rail_man);\r\n\t\t \r\n\t\r\n\tconst CRailNode* pStartOfRail = mp_rail_node;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\tconst CRailNode* pRail = mp_rail_node;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\r\n\t// no node array in rail manager indicates auto generated rails, so just return\r\n\tScript::CArray* pNodeArray = mp_rail_man->GetNodeArray();\r\n\tif (!pNodeArray) return;\r\n\t\r\n\tScript::CStruct* pNode = pNodeArray->GetStructure(mp_rail_node->GetNode());\r\n\r\n\t// find a rail node that has a \"TriggerScript\" in it\r\n\tuint32 value = 0;\r\n\tif (pNode->GetChecksum(CRCD(0x2ca8a299, \"Triggerscript\"), &value))\r\n\t{\r\n\t\t// we got it \r\n\t}\r\n\telse\r\n\t{\r\n\t\t// did not get it, so scoot backwards until we detect a loop or we find one\r\n\t\tconst CRailNode* p_loop_detect = pRail;\t \t// start loop detect at the start\r\n\t\tpRail = pRail->GetPrevLink(); \t\t\t\t// and the first node we check is the next one\r\n\t\tint loop_advance = 0;\r\n\t\twhile (pRail && pRail != pStartOfRail && pRail != p_loop_detect)\r\n\t\t{\r\n\t\t\tpNode = pNodeArray->GetStructure(pRail->GetNode());\r\n\t\t\tif (pNode->GetChecksum(CRCD(0x2ca8a299, \"Triggerscript\"), &value)) break;\r\n\t\t\t\r\n\t\t\tpRail = pRail->GetPrevLink(); \r\n\t\t\t// The p_loop_detect pointer goes backwards at half speed, so if there is a loop\r\n\t\t\t// then pRail is guarenteed to eventually catch up with p_loop_detect\r\n\t\t\tif (loop_advance)\r\n\t\t\t{\r\n\t\t\t\tp_loop_detect = p_loop_detect->GetPrevLink();\t\t\t\t\r\n\t\t\t}\r\n\t\t\tloop_advance ^= 1;\r\n\t\t}\r\n\t}\r\n\r\n\tif (value)\r\n\t{\r\n\t\t// If this is different to last time, then set flag accordingly\r\n\t\tuint32 new_last_rail_node_name;\r\n\t\tpNode->GetChecksum(CRCD(0xa1dc81f9, \"name\"), &new_last_rail_node_name, Script::ASSERT);\r\n//\t\tprintf (\"%s,%s\\n\",Script::FindChecksumName(new_last_rail_node_name), Script::FindChecksumName(m_last_rail_node_name));\r\n\t\tif (new_last_rail_node_name != m_last_rail_trigger_node_name)\r\n\t\t{\r\n\t\t\tSetFlagTrue(NEW_RAIL);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tSetFlagFalse(NEW_RAIL);\r\n\t\t}\r\n\t\tm_last_rail_node_name = new_last_rail_node_name;\r\n\t\tm_last_rail_trigger_node_name = new_last_rail_node_name;\r\n\t\t\r\n\t\t\r\n\t\t// if we are using the default node array, then set it to NULL, so TriggerEventFromNode can use this default, which is a lot faster\r\n\t\tif (pNodeArray == Script::GetArray(CRCD(0xc472ecc5, \"NodeArray\")))\r\n\t\t{\r\n\t\t\tpNodeArray = NULL;\r\n\t\t}\r\n\t\t\r\n\t\tmp_trigger_component->TripTrigger(\r\n\t\t\ttype,\r\n\t\t\tm_last_rail_node_name,\r\n\t\t\tpNodeArray,\r\n\t\t\tmp_movable_contact_component->HaveContact() ? mp_movable_contact_component->GetContact()->GetObject() : NULL\r\n\t\t);\r\n\t}\r\n}\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::handle_tensing (   )\r\n{\r\n\tif (!GetFlag(TENSE) && mp_input_component->GetControlPad().m_x.GetPressed())\r\n\t{\r\n\t\t// just starting to tense, so set the flag \r\n\t\tSetFlagTrue(TENSE);\t\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCorePhysicsComponent::get_member_feeler_collision ( uint16 ignore_1, uint16 ignore_0 )\r\n{\r\n\t// use m_col_start and m_col_end to set up m_feeler, then check for collision and if there is a collision, then get the various skater collision flags\r\n\r\n\tm_feeler.SetLine(m_col_start, m_col_end);\r\n\tm_feeler.SetIgnore(ignore_1, ignore_0);\r\n\r\n\tbool collision = m_feeler.GetCollision();\r\n\t\r\n\tif (!collision) return false;\r\n\t\r\n\tif (m_feeler.GetNodeChecksum() && m_feeler.GetTrigger())\r\n\t{\r\n\t\t// Given a node name, then find the checksum of the triggerscript in that node\r\n\t\t// note that this is VERY SLOW, as it has to scan the whole node array\r\n\t\t// it's usually only called once per frame, per skater, but might still be a good candidate for optimization\r\n\t\t\r\n\t\t// Now just clear the script, indicating it needed doing later\r\n\t\tm_feeler.SetScript(0);\r\n\t}\r\n\r\n\t// get any skating specific flags here\r\n\tuint16 flags = m_feeler.GetFlags();\r\n\r\n\t// get normal, as it's the kind of things we use in face flag determination\t\t\t\t   \r\n\tMth::Vector\tnormal = m_feeler.GetNormal();\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t// Make wallable default to off.\t\t\t\t\r\n\tm_col_flag_wallable = false;\r\n\t\r\n\t///////////////////////////////////////////////////////////////////\r\n\t// Vert\r\n\t\r\n\tm_col_flag_vert = flags & mFD_VERT;\r\n\t\r\n\t////////////////////////////////////////////////////////////////\r\n\t// Skatable\t\t\t\t\t   \r\n\t   \r\n\tif (flags & mFD_SKATABLE)\r\n\t{\r\n\t\t// if flaged as skatable, than that overrides all other flags\r\n\t\tm_col_flag_skatable = true;\r\n\t}\r\n\telse if (flags & mFD_NOT_SKATABLE)\r\n\t{\r\n\t\t// if flagged as non_skatable, then that overrides all other flags\r\n\t\tm_col_flag_skatable = false;\r\n\t}\r\n\telse if (flags & mFD_VERT)\r\n\t{\t\t\t\r\n\t\t// if flagged as VERT, then it's the top of a QP, so it's skatable and this overrides the angle flag\r\n\t\tm_col_flag_skatable = true;\r\n\t}\r\n\telse if (flags & mFD_WALL_RIDABLE)\r\n\t{\r\n\t\tm_col_flag_skatable = false;\r\n\t\tm_col_flag_wallable = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// determine the skatablitlity based on the angle\r\n\t\t// if angle is > 5 degrees from vert, then it is skatable\r\n\t\t// here the y component of the normal is the cosine of the angle from vertical\r\n\t\t\t\t\t\t\t\t  \r\n\t\tif (normal[Y] < sinf(Mth::DegToRad(GetPhysicsFloat(CRCD(0x3eede4d3,\"Wall_Non_Skatable_Angle\")))))\r\n\t\t{\r\n\t\t\t// get could possibly do another test here to see if there is a polygon beneath this meaning this is a QP\r\n\t\t\t// however, we want to be flagging the tops of all QPs\r\n\t\t\tm_col_flag_skatable = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_col_flag_skatable = true;\r\n\t\t}\r\n\t\t\r\n\t}\r\n\r\n\treturn collision;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::do_jump ( Script::CStruct *pParams )\r\n{\r\n\t// Called by the Jump script command\r\n\t\r\n\t// play sounds before modifying the skater speed, as the sound volume and pitch are based on the pre-jump velocity\r\n\tbool play_sound = !pParams->ContainsFlag(CRCD(0xe13620a8, \"no_sound\"));\r\n\t\r\n\tswitch (GetState())\r\n\t{\r\n\t\tcase GROUND:\r\n\t\t\tmp_trigger_component->CheckFeelerForTrigger(TRIGGER_JUMP_OFF, m_last_ground_feeler);\r\n\t\t\tif (mp_physics_control_component->HaveBeenReset()) return;\r\n\t\t\t\r\n\t\t\t// K: Remember the last ground position for calculating which side of the rail we're on later.\r\n\t\t\tm_last_ground_pos = GetPos();\r\n\t\t\t\r\n\t\t\tif (play_sound)\r\n\t\t\t{\r\n\t\t\t\tmp_sound_component->PlayJumpSound(GetObject()->GetVel().Length() / GetSkater()->GetScriptedStat(CRCD(0xcc5f87aa, \"Skater_Max_Max_Speed_Stat\")), m_last_ground_feeler.GetTerrain());\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tmaybe_straight_up();\r\n\t\t\tSetFlagTrue(CAN_BREAK_VERT);\r\n\t\t\tbreak;\r\n\r\n\t\tcase AIR:\r\n\t\t\tif (play_sound)\r\n\t\t\t{\r\n\t\t\t\tmp_sound_component->PlayJumpSound(GetObject()->GetVel().Length() / GetSkater()->GetScriptedStat(CRCD(0xcc5f87aa, \"Skater_Max_Max_Speed_Stat\")), m_last_ground_feeler.GetTerrain());\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\r\n\t\tcase RAIL:\r\n\t\t\tif (play_sound)\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert(mp_rail_node);\r\n\t\t\t\tmp_sound_component->PlayJumpSound(GetObject()->GetVel().Length() / GetSkater()->GetScriptedStat(CRCD(0xcc5f87aa, \"Skater_Max_Max_Speed_Stat\")), mp_state_component->m_terrain);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\t\t\t  \r\n\tDbg_Assert(pParams);\r\n\t\r\n\tint max_tense_time = GetPhysicsInt(CRCD(0xf733c097, \"skater_max_tense_time\"));\r\n\tm_tense_time = Mth::Min(m_tense_time, max_tense_time);\r\n\t\r\n\tfloat max_jump_speed;\r\n\tfloat min_jump_speed;\r\n\t\r\n\tbool from_vert = GetFlag(VERT_AIR) || (GetState() == GROUND && GetFlag(LAST_POLY_WAS_VERT));\r\n\r\n\tif (pParams->ContainsFlag(CRCD(0xec6b7fc7, \"BonelessHeight\")))\r\n\t{\r\n\t\tif (from_vert)\r\n\t\t{\r\n\t\t\tmax_jump_speed = GetSkater()->GetScriptedStat(CRCD(0x39766891, \"Physics_Boneless_air_Jump_Speed_stat\"));\r\n\t\t\tmin_jump_speed = GetSkater()->GetScriptedStat(CRCD(0x4cdb18cb, \"Physics_Boneless_air_Jump_Speed_min_stat\"));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmax_jump_speed = GetSkater()->GetScriptedStat(CRCD(0x8851a76e, \"Physics_Boneless_Jump_Speed_stat\"));\r\n\t\t\tmin_jump_speed = GetSkater()->GetScriptedStat(CRCD(0x6e8efe38, \"Physics_Boneless_Jump_Speed_min_stat\"));\r\n\t\t}\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tif (from_vert)\r\n\t\t{\r\n\t\t\tmax_jump_speed = GetSkater()->GetScriptedStat(CRCD(0x9f79c8ea, \"Physics_air_Jump_Speed_stat\"));\r\n\t\t\tmin_jump_speed = GetSkater()->GetScriptedStat(CRCD(0x91b07824, \"Physics_air_Jump_Speed_min_stat\"));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmax_jump_speed = GetSkater()->GetScriptedStat(CRCD(0x2ade3ad, \"Physics_Jump_Speed_stat\"));\r\n\t\t\tmin_jump_speed = GetSkater()->GetScriptedStat(CRCD(0xc8815e43, \"Physics_Jump_Speed_min_stat\"));\r\n\t\t}\r\n\t}\t\r\n\t\r\n\tfloat jump_speed = Mth::LinearMap(min_jump_speed, max_jump_speed, m_tense_time, 0.0f, max_tense_time);\r\n\t\r\n\t// If any speed param is specified, then use that instead. Need by Zac for when small skater is doing scripted jumps in the front end.\r\n\tpParams->GetFloat(CRCD(0xf0d90109, \"speed\"), &jump_speed);\r\n\r\n\tSetFlagFalse(TENSE);\r\n\r\n\t// if we have a very high downward velocity and we are landing on vert, then do not jump\r\n\r\n\t// when jumping, don't add in the current velocity if it is less than zero\r\n\t// this will give us nicer feeling jumps when \r\n\t//  - comping down wall rides\r\n\t//  - skating down slopes\r\n\t//  - skating down the back of bumps, liks the speed bumps in CA\r\n\t//  - landing on a QP\r\n\r\n\t\r\n\tif (GetFlag(VERT_AIR) && GetVel()[Y] < 0.0f)\r\n\t{\r\n\t\t \t// push outward\t(and upward) away from vert poly\r\n\t\t\tGetVel() += jump_speed * m_display_normal;\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t\tjump_speed = 0;\r\n\t\t\tSetFlagFalse(VERT_AIR);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (GetVel()[Y] < 0.0f)\r\n\t\t{\r\n\t\t\tGetVel()[Y] = 0.0f;\r\n\t\t\tDUMP_VELOCITY;\r\n\t\t}\r\n\t}\r\n\t\r\n\tGetVel()[Y] += jump_speed;\r\n\tDUMP_VELOCITY;\r\n\r\n\t// if pointing down, then jump down, as moving up will make us pass through whatever we are on\t\r\n\tif (GetMatrix()[Y][Y] < -0.1f)\r\n\t{\r\n\t\tGetVel()[Y] -= jump_speed * 1.5f;\r\n\t\tDUMP_VELOCITY;\r\n\t\tGetPos() += GetMatrix()[Y] * 12.0f;\r\n\t\tDUMP_POSITION;\r\n\t}\r\n\t\r\n\t// allow side jumps when jumping off rails or when late jumping in air after skating off a rail\r\n\tif (GetState() == RAIL || (GetState() == AIR && m_previous_state == RAIL))\r\n\t{\r\n\t\tollie_off_rail_rotate();\r\n\t}\r\n\t\r\n\t// don't change the state until after sound is played, as the above switch relyies on the GROUND/RAIL state...\r\n\tSetState(AIR);\r\n\t\r\n\tm_last_jump_time_stamp = Tmr::GetTime();\r\n\t\r\n\tGetObject()->BroadcastEvent(CRCD(0x8687163a, \"SkaterJump\"));\r\n}\t\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::start_skitch (   )\r\n{\r\n\t// Start Skitching, given that we've queue one up\r\n\t// Note, mp_skitch_object is a smart pointer so there is a slight possibility that it might have died but we check that\r\n\t\r\n\t// Mick:  I'm using .Convert here.   I'm not sure if makes any difference,\r\n\t// but it can't hurt and should compile the same.\r\n\tif (!mp_skitch_object.Convert()) return;\r\n\t\r\n\tmp_movable_contact_component->ObtainContact(mp_skitch_object);\r\n\tSetFlagTrue(SKITCHING);\r\n\tm_moving_to_skitch = true;\r\n\tmove_to_skitch_point();\r\n\t\r\n\t// Mick:  For some reason we sometimes get a NULL smart pointer here\r\n\t// so I'm checking again here, in addition to changing the code\r\n\t// to use .Convert \t\r\n\tif (!mp_skitch_object.Convert()) return;\r\n\t\r\n\tmp_skitch_object->SelfEvent(CRCD(0x35224f25, \"SkitchOn\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::do_grind_trick ( uint Direction, bool Right, bool Parallel, bool Backwards, bool Regular )\r\n{\r\n\tint SubArrayIndex = 0;\r\n\t\r\n\t// Choose which array index to use.\r\n\tswitch (Direction)\r\n\t{\r\n\t\tcase 0: // Nowt\r\n\t\t\tSubArrayIndex = 0;\r\n\t\t\tbreak;\r\n\t\tcase PAD_U: // Up\r\n\t\t\tSubArrayIndex = 1;\r\n\t\t\tbreak;\r\n\t\tcase PAD_D: // Down\r\n\t\t\tSubArrayIndex = 2;\r\n\t\t\tbreak;\r\n\t\tcase PAD_L: // Left\r\n\t\t\tSubArrayIndex = 3;\r\n\t\t\tbreak;\r\n\t\tcase PAD_R: // Right\r\n\t\t\tSubArrayIndex = 4;\r\n\t\t\tbreak;\r\n\t\tcase PAD_UL: // UpLeft\r\n\t\t\tSubArrayIndex = 5;\r\n\t\t\tbreak;\r\n\t\tcase PAD_UR: // UpRight\r\n\t\t\tSubArrayIndex = 6;\r\n\t\t\tbreak;\r\n\t\tcase PAD_DL: // DownLeft\r\n\t\t\tSubArrayIndex = 7;\r\n\t\t\tbreak;\r\n\t\tcase PAD_DR: // DownRight\r\n\t\t\tSubArrayIndex = 8;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(false, (\"Bad button checksum\"));\r\n\t\t\tbreak;\r\n\t}\t\r\n\t\t\r\n\t// GetArray will assert if GrindTrickList not found.\r\n\tScript::CArray* pMainArray = Script::GetArray(CRCD(0x2ab3341d, \"GrindTrickList\"));\r\n\tScript::CArray* pSubArray = pMainArray->GetArray(SubArrayIndex);\r\n\r\n\tuint Index = 0;\r\n\tif (Right) Index |= 1;\r\n\tif (Parallel) Index |= 2;\r\n\tif (Backwards) Index |= 4;\r\n\tif (Regular) Index |= 8;\r\n\r\n\t// Initialise mGrindTweak, which should get set by a SetGrindTweak command in the script that is about to be run.\r\n\tResetGrindTweak();\r\n\t\t\r\n\tCSkaterFlipAndRotateComponent* p_flip_and_rotate_component = GetSkaterFlipAndRotateComponentFromObject(GetObject());\r\n\tDbg_Assert(p_flip_and_rotate_component);\r\n\tp_flip_and_rotate_component->DoAnyFlipRotateOrBoardRotateAfters();\r\n\t\r\n\tif (!GetObject()->GetScript())\r\n\t{\r\n\t\tGetObject()->SetScript(new Script::CScript);\r\n\t}\r\n\t\r\n\tGetObject()->GetScript()->SetScript(pSubArray->GetNameChecksum(Index), NULL, GetObject());\r\n\tGetObject()->GetScript()->Update();\r\n\t\r\n\t// Set the mDoingTrick flag so that the camera can detect that a trick is being done.\r\n\tmp_state_component->SetDoingTrick(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::StopSkitch (   )\r\n{\r\n\t// If we were skitching, then stop it\r\n\t\r\n\tif (!GetFlag(SKITCHING)) return;\r\n\t\r\n\tSetFlagFalse(SKITCHING);\r\n\tif (mp_skitch_object)\r\n\t{\r\n\t\tmp_skitch_object->SelfEvent(CRCD(0x2739b86d, \"SkitchOff\"));\r\n\t\tmp_skitch_object = NULL;\r\n\t}\r\n\tmp_movable_contact_component->LoseAnyContact();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::setup_default_collision_cache (   )\r\n{\r\n\t// reduced Y extent as this no longer subsumes the uberfrig\r\n\tMth::CBBox bbox(\r\n\t\tGetPos() - Mth::Vector(FEET(15.0f), FEET(17.0f), FEET(15.0f), 0.0f),\r\n\t\tGetPos() + Mth::Vector(FEET(15.0f), FEET(8.0f), FEET(15.0f), 0.0f)\r\n\t);\r\n\t\r\n\tmp_coll_cache->Update(bbox);\r\n\tCFeeler::sSetDefaultCache(mp_coll_cache);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCorePhysicsComponent::update_special_friction_index (   )\r\n{\r\n\tif (m_special_friction_index == 0) return;\r\n\t\r\n\tif (Tmr::ElapsedTime(m_special_friction_decrement_time_stamp) > static_cast< Tmr::Time >(1000.0f * Script::GetFloat(CRCD(0xf4813ad5, \"Physics_Time_Before_Free_Revert\"))))\r\n\t{\r\n\t\tm_special_friction_index--;\r\n\t\tMESSAGE(\"You earned a free revert!!!!\");\r\n\t\tif (m_special_friction_index != 0)\r\n\t\t{\r\n\t\t\tm_special_friction_decrement_time_stamp = Tmr::GetTime();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterCorePhysicsComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterCorePhysicsComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/21/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERCOREPHYSICSCOMPONENT_H__\r\n#define __COMPONENTS_SKATERCOREPHYSICSCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/math/slerp.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <sk/engine/feeler.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/skaterflags.h>\r\n#include <sk/objects/manual.h>\r\n#include <sk/objects/rail.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n#include <sk/components/skatersoundcomponent.h>\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n\r\n#define\t\tCRC_SKATERCOREPHYSICS CRCD(0x5bd63b29, \"SkaterCorePhysics\")\r\n\r\n#define\t\tGetSkaterCorePhysicsComponent() ((Obj::CSkaterCorePhysicsComponent*)GetComponent(CRC_SKATERCOREPHYSICS))\r\n#define\t\tGetSkaterCorePhysicsComponentFromObject(pObj) ((Obj::CSkaterCorePhysicsComponent*)(pObj)->GetComponent(CRC_SKATERCOREPHYSICS))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\tclass CCollCache;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CInputComponent;\r\n\tclass CTriggerComponent;\r\n\tclass CSkaterLoopingSoundComponent;\r\n\tclass CTrickComponent;\r\n\tclass CSkaterRotateComponent;\r\n\tclass CSkaterScoreComponent;\r\n\tclass CMovableContactComponent;\r\n\t\r\n\tstruct SRailData;\r\n\r\nclass CSkaterCorePhysicsComponent : public CBaseComponent\r\n{\r\n\tfriend Mdl::Skate;\r\n\tfriend CSkater;\r\n\tfriend CSkaterCam;\r\n\tfriend CManual;\r\n\tfriend CSkaterCameraComponent;\r\n\tfriend CSkaterAdjustPhysicsComponent;\r\n\tfriend CSkaterFinalizePhysicsComponent;\r\n\tfriend CSkaterNonLocalNetLogicComponent;\r\n\tfriend CSkaterRotateComponent;\r\n\tfriend CSkaterPhysicsControlComponent;\r\n\tfriend CSkaterMatrixQueriesComponent;\r\n\tfriend CSkaterStateHistoryComponent;\r\n\tfriend CWalkComponent;\r\n\t\r\npublic:\r\n    CSkaterCorePhysicsComponent();\r\n    virtual ~CSkaterCorePhysicsComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\t\r\npublic:\r\n\tvoid\t\t\t\t\t\t\tReset (   );\r\n\tvoid\t\t\t\t\t\t\tReadySkateState ( bool to_ground_state, const SRailData* p_rail_data, const SAcidDropData* p_acid_drop_data );\r\n\tvoid\t\t\t\t\t\t\tCleanUpSkateState (   );\r\n\t\r\n\tEStateType\t\t\t\t\t\tGetState (   );\r\n\tvoid\t\t\t\t\t\t\tSetState ( EStateType state );\r\n\tbool\t\t\t\t\t\t\tGetFlag ( ESkaterFlag flag );\r\n\tvoid\t\t\t\t\t\t\tSetFlag ( ESkaterFlag flag, bool state = true );\r\n\tvoid\t\t\t\t\t\t\tSetFlagTrue ( ESkaterFlag flag );\r\n\tvoid\t\t\t\t\t\t\tSetFlagFalse ( ESkaterFlag flag );\r\n\tvoid\t\t\t\t\t\t\tToggleFlag ( ESkaterFlag flag );\r\n\tTmr::Time\t\t\t\t\t\tGetFlagTime ( ESkaterFlag flag );\r\n\tTmr::Time\t\t\t\t\t\tGetFlagElapsedTime ( ESkaterFlag flag );\r\n\tvoid\t\t\t\t\t\t\tResetFlags (   );\r\n\tvoid\t\t\t\t\t\t\tResetSpecialFrictionIndex (   );\r\n\tvoid\t\t\t\t\t\t\tReverseFacing (   );\r\n\tbool\t\t\t\t\t\t\tHaveLandedThisFrame (   );\r\n\tETerrainType\t\t\t\t\tGetTerrain (   );\r\n\tETerrainType\t\t\t\t\tGetLastGroundTerrain (   );\r\n\tuint32\t\t\t\t\t\t\tGetLastNodeChecksum (   );\r\n\tbool\t\t\t\t\t\t\tGetTrueLandedFromVert (   );\r\n\tvoid\t\t\t\t\t\t\tResetLerpingMatrix (   );\r\n\tvoid\t\t\t\t\t\t\tStopSkitch (   );\r\n\tbool\t\t\t\t\t\t\tIsSwitched (   );\r\n\tvoid\t\t\t\t\t\t\tResetGrindTweak (   );\r\n\tsint16\t\t\t\t\t\t\tGetRailNode( void );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tCollideWithOtherSkaterLost ( CCompositeObject* p_other_skater );\r\n\t\r\n\tMth::Vector&\t\t\t\t\tGetPos (   ) { return GetObject()->m_pos; }\r\n\tMth::Vector&\t\t\t\t\tGetOldPos (   ) { return GetObject()->m_old_pos; }\r\n\tMth::Matrix&\t\t\t\t\tGetMatrix (   ) { return GetObject()->m_matrix; }\r\n\tMth::Vector&\t\t\t\t\tGetVel (   ) { return GetObject()->m_vel; }\r\n\t\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\tdo_on_ground_physics (   );\r\n\tvoid\t\t\t\t\t\t\tdo_in_air_physics (   );\r\n\tvoid\t\t\t\t\t\t\tdo_wallride_physics (   );\r\n\tvoid\t\t\t\t\t\t\tdo_wallplant_physics (   );\r\n\tvoid\t\t\t\t\t\t\tdo_lip_physics (   );\r\n\tvoid\t\t\t\t\t\t\tdo_rail_physics (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tlimit_speed (   );\r\n\tbool\t\t\t\t\t\t\tis_trying_to_brake (   );\r\n\tbool\t\t\t\t\t\t\tis_braking (   );\r\n\tvoid\t\t\t\t\t\t\tdo_brake (   );\r\n\tbool\t\t\t\t\t\t\ton_steep_slow_slope (   );\r\n\tbool\t\t\t\t\t\t\tcan_kick (   );\r\n\tvoid\t\t\t\t\t\t\tdo_kick (   );\r\n\tvoid\t\t\t\t\t\t\thandle_ground_friction (   );\r\n\tvoid\t\t\t\t\t\t\thandle_wind_resistance (   );\r\n\tvoid\t\t\t\t\t\t\thandle_rolling_resistance (   );\r\n\tbool\t\t\t\t\t\t\tslide_off_slow_steep_slope (   );\r\n\tvoid\t\t\t\t\t\t\tapply_wind_resistance ( float friction );\r\n\tvoid\t\t\t\t\t\t\tapply_rolling_friction (   );\r\n\tvoid\t\t\t\t\t\t\tpush_away_from_walls (   );\r\n\tvoid\t\t\t\t\t\t\tbounce_off_wall ( const Mth::Vector& normal );\r\n\tvoid\t\t\t\t\t\t\tcheck_for_wall_push ( const Mth::Vector& start, const Mth::Vector& end, int index );\r\n\tvoid\t\t\t\t\t\t\tsnap_to_ground (   );\r\n\tvoid\t\t\t\t\t\t\tmaybe_straight_up (   );\r\n\tvoid\t\t\t\t\t\t\tmaybe_break_vert (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_spine_transfer (   );\r\n\tbool\t\t\t\t\t\t\tlook_for_transfer_target ( const Mth::Vector& search_dir, const Mth::Vector& start_normal, bool& hip_transfer, Mth::Vector& target, Mth::Vector& target_normal );\r\n\tbool\t\t\t\t\t\t\tmaybe_acid_drop ( bool skated_off_edge, const Mth::Vector &pos, const Mth::Vector& old_pos, Mth::Vector& vel, SAcidDropData& acid_drop_data );\r\n\tvoid\t\t\t\t\t\t\tenter_acid_drop ( const SAcidDropData& acid_drop_data );\r\n\tvoid\t\t\t\t\t\t\thandle_post_transfer_limit_overrides (   );\r\n\tvoid\t\t\t\t\t\t\thandle_ground_rotation (   );\r\n\tvoid\t\t\t\t\t\t\thandle_air_rotation (   );\r\n\tvoid\t\t\t\t\t\t\tremove_sideways_velocity ( Mth::Vector& vel );\r\n\tvoid\t\t\t\t\t\t\tcheck_side_collisions (   );\r\n\tbool\t\t\t\t\t\t\tcheck_side ( float Side, float SideCol );\r\n\tvoid\t\t\t\t\t\t\thandle_forward_collision (   );\r\n\tfloat\t\t\t\t\t\t\trotate_away_from_wall ( const Mth::Vector& normal, float& turn_angle, float lerp = 1.0f );\r\n\tfloat\t\t\t\t\t\t\tget_air_gravity (   );\r\n\tvoid\t\t\t\t\t\t\tcheck_leaning_into_wall (   );\r\n\tfloat\t\t\t\t\t\t\tcalculate_time_to_reach_height ( float target_height, float pos_Y, float vel_Y );\r\n\tvoid\t\t\t\t\t\t\tflip_if_skating_backwards (   );\r\n\tbool\t\t\t\t\t\t\tmaybe_flag_ollie_exception (   );\r\n\tvoid\t\t\t\t\t\t\thandle_air_lean (   );\r\n\tvoid\t\t\t\t\t\t\thandle_transfer_slerping (   );\r\n\tvoid\t\t\t\t\t\t\thandle_air_vert_recovery (   );\r\n\tvoid\t\t\t\t\t\t\trotate_upright (   );\r\n\tbool\t\t\t\t\t\t\thandle_forward_collision_in_air ( const Mth::Vector& start_pos );\r\n\tbool\t\t\t\t\t\t\tcheck_for_air_snap_up ( const Mth::Vector& start_pos );\r\n\tbool\t\t\t\t\t\t\thandle_upward_collision_in_air (   );\r\n\tbool\t\t\t\t\t\t\thandle_upward_collision_in_wallride (   );\r\n\tvoid\t\t\t\t\t\t\tollie_off_rail_rotate (   );\r\n\tvoid\t\t\t\t\t\t\tskate_off_rail ( const Mth::Vector& off_point );\r\n\tbool\t\t\t\t\t\t\tcheck_for_wallpush (   );\r\n\tbool\t\t\t\t\t\t\tcheck_for_wallplant (   );\r\n\tbool\t\t\t\t\t\t\tcheck_for_wallride (   );\r\n\tvoid\t\t\t\t\t\t\tmaybe_skitch (   );\r\n\tvoid\t\t\t\t\t\t\tmove_to_skitch_point (   );\r\n\tvoid\t\t\t\t\t\t\tcheck_movable_contact (   );\r\n\tvoid\t\t\t\t\t\t\tnew_normal ( Mth::Vector normal );\r\n\tvoid\t\t\t\t\t\t\tadjust_normal (   );\r\n\tvoid\t\t\t\t\t\t\tmaybe_trip_rail_trigger ( uint32 type );\r\n\tvoid\t\t\t\t\t\t\thandle_tensing (   );\r\n\tvoid\t\t\t\t\t\t\tmaybe_stick_to_rail ( bool override_air = false );\r\n\tbool\t\t\t\t\t\t\twill_take_rail ( const CRailNode* pNode, CRailManager* p_rail_man, bool from_walk = false );\r\n\tvoid\t\t\t\t\t\t\tgot_rail ( const Mth::Vector& rail_pos, const CRailNode* pNode, CRailManager* p_rail_man, bool no_lip_tricks = false, bool from_walk = false );\r\n\tbool\t\t\t\t\t\t\tget_member_feeler_collision ( uint16 ignore_1 = mFD_NON_COLLIDABLE, uint16 ignore_0 = 0 );\r\n\tvoid\t\t\t\t\t\t\tstart_skitch (   );\r\n\tvoid\t\t\t\t\t\t\tdo_grind_trick ( uint Direction, bool Right, bool Parallel, bool Backwards, bool Regular );\r\n\tvoid\t\t\t\t\t\t\tset_terrain ( ETerrainType terrain );\r\n\tvoid\t\t\t\t\t\t\tset_last_ground_feeler ( CFeeler& feeler );\r\n\tvoid\t\t\t\t\t\t\tsetup_default_collision_cache (   );\r\n\tbool\t\t\t\t\t\t\tis_vert_for_transfers ( const Mth::Vector& normal );\r\n\tvoid\t\t\t\t\t\t\tupdate_special_friction_index (   );\r\n\t\r\npublic:\r\n\tvoid\t\t\t\t\t\t\tdo_jump ( Script::CStruct *pParams );\r\n\t\r\nprivate:\r\n\tMth::Matrix\t\t\t\t\t\tm_lerping_display_matrix;\r\n\tMth::Vector\t\t\t\t\t\tm_display_normal;\t\t\t\t// current normal the skater is oriented to\r\n\tMth::Vector\t\t\t\t\t\tm_current_normal;   \t\t\t// normal of current polygon \r\n\tMth::Vector\t\t\t\t\t\tm_last_display_normal;   \t\t// last value of m_display_normal\r\n\tfloat\t\t\t\t\t\t\tm_normal_lerp;\t\t\t\t\t// counter 1 to 0 for amount of normal lerp\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_frame_length;\r\n\t\r\n\tTmr::Time\t\t\t\t\t\tm_state_change_timestamp;\t\t// timestamp of the latest state change\r\n\tEStateType\t\t\t\t\t\tm_previous_state;\t\t\t\t// the skater's state previous to the current state\r\n\t\r\n\tMth::Vector\t\t\t\t\t\tm_safe_pos;\t\t\t\t\t\t// Safe world position, to which we can be moved in an emergency\r\n\t\r\n\tCFeeler\t\t\t\t\t\t\tm_feeler;\t   \t\t\t\t\t// collision data from last collision check \r\n\tCFeeler\t\t\t\t\t\t\tm_last_ground_feeler;\t\t\t// and from last time we were in valid contact with ground\r\n\tMth::Vector\t\t\t\t\t\tm_col_start, m_col_end;\t\t\t// start and end of collision line segment\r\n\tbool\t\t\t\t\t\t\tm_col_flag_skatable;\t\t\t// true is last face was skatable\r\n\tbool\t\t\t\t\t\t\tm_col_flag_vert;\t\t\t\t// true if last face was flagged vert\r\n\tbool\t\t\t\t\t\t\tm_col_flag_wallable;\t\t\t// true if last face was flagged wall-ridable\r\n\t\r\n\t// Mth::Vector\t\t\t\t\t\tm_movement;\t\t\t\t\t\t// distance we want to move this frame\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// used when moving over ground so we don't travel short distances\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// when we hit a concave surface which causes collisions\t\t\t\t  \r\n\t\r\n\tconst CRailNode*\t\t\t\tmp_rail_node;\t\t\t\t\t// pointer to current rail node\r\n\tCRailManager*\t\t\t\t\tmp_rail_man;\t\t\t\t\t// pointer to manager of this rail\r\n\tTmr::Time\t\t\t\t\t\tm_rail_time;\t\t\t\t\t// last time we were on a rail\r\n\tTmr::Time\t\t\t\t\t\tm_lip_time;\t\t\t\t\t\t// last time we were on a lip\r\n\tTmr::Time\t\t\t\t\t\tm_rerail_time;\t\t\t\t\t// time that must elapse before we can get back on the same rail\r\n\tuint32\t\t\t\t\t\t\tm_last_rail_node_name;\r\n\tuint32\t\t\t\t\t\t\tm_last_rail_trigger_node_name;\r\n\tbool\t\t\t\t\t\t\tmLedge;                         // Whether it's a ledge. Calculated in MaybeStickToRail.\r\n\tbool\t\t\t\t\t\t\tmBadLedge;                      // Whether this is a bad ledge. Calculated in MaybeStickToRail, and \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// used by the BadLedge script command.\r\n\t\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_moving_to_skitch; \t\t\t// true if in initial movment to skitch\r\n\tint\t\t\t\t\t\t\t\tm_skitch_index;\t\t\t\t\t// index of the node number on the object we are skitching\r\n\tfloat\t\t\t\t\t\t\tm_skitch_dir;\t\t\t\t\t// direction (-1.0f or 1.0f) we are moving in\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_landed_this_frame;\t\t\t// true if we just landed this frame\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_began_frame_in_transfer;\r\n\tbool\t\t\t\t\t\t\tm_began_frame_in_lip_state;\r\n\r\n\tMth::Vector\t\t\t\t\t\tm_pre_lip_pos;\t\t\t\t\t// position we were at before we snapped to a lip\r\n\r\n\tMth::Vector\t\t\t\t\t\tm_vert_pos;\t\t\t\t\t\t// point below us on a vert face\r\n\tMth::Vector\t\t\t\t\t\tm_vert_normal;\t\t\t\t\t// normal of that face\r\n\r\n\tMth::Vector\t\t\t\t\t\tm_fall_line;\t\t\t\t\t// unit vector that points \"down\" the plane\r\n\r\n\tfloat\t\t\t\t\t\t\tm_vert_upstep;\t\t\t\t\t// amount we try to move up each frame when tracking vert\r\n\r\n\tMth::Vector\t\t\t\t\t\tm_extra_ground_push;\t\t\t// extra vector to apply to next \"ground\" movement\r\n\r\n\tMth::Vector\t\t\t\t\t\tm_wall_push; \t\t\t\t\t// direction to push away from wall\r\n\tfloat\t\t\t\t\t\t\tm_wall_dist;\t\t\t\t\t// shortest distance from wall\r\n\tfloat\t\t\t\t\t\t\tm_wall_push_radius;\t\t\t\t// radius to check\r\n\tfloat\t\t\t\t\t\t\tm_wall_push_speed;\t\t\t\t// speed at which to push out\r\n\tfloat \t\t\t\t\t\t\tm_wall_rotate_speed;\t\t\t// speed at which we rotate away\r\n\r\n\tfloat\t\t\t\t\t\t\tm_last_time;\t\t\t\t\t// time at last frame\r\n\t\r\npublic:\r\n\tbool\t\t\t\t\t\t\tm_auto_kick;   \t\t\t\t\t// true if auto kick on\r\n\tbool\t\t\t\t\t\t\tm_spin_taps;\t\t\t\t\t// true when 180 spin taps are enabled.\r\n\t\r\nprotected:\r\n\tfloat\t\t\t\t\t\t\tm_tap_turns;\t\t\t\t\t// How much tap-turn rotation remains.\r\n\r\n\tbool\t\t\t\t\t\t\tm_force_cankick_off;\t\t\t// Set by the CanKickOff script command, so that Scott can\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// force CanKick to return false;\r\n\r\n\tbool\t\t\t\t\t\t\tm_pressing_down_brakes;\t\t\t// Set/Reset by the CanBrakeOn and CanBrakeOff\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// commands.\r\n\r\n\r\n\tfloat\t\t\t\t\t\t\tm_rolling_friction;\t\t\t\t// Friction, set by SetRollingFriction script command.\r\n\tint\t\t\t\t\t\t\t\tm_special_friction_index;\t\t// Index into an array of special friction values, set by the\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// SetSpecialFriction command (used by reverts)\r\n\tTmr::Time\t\t\t\t\t\tm_special_friction_decrement_time_stamp;\r\n\tfloat\t\t\t\t\t\t\tm_special_friction_duration;\t// When m_rolling_friction is set via special friction, it must be given a duration;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// after which it reverts to default.  Calls to set m_rolling_friction to default\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// are ignored during this duration.\r\n\r\n\tbool\t\t\t\t\t\t\tm_braking;\t\t\t\t\t\t// true if currently braking\r\n\tTmr::Time\t\t\t\t\t\tm_push_time[4];\t\t\t\t\t// time of last side push\r\n\r\n\tMth::Vector\t\t\t\t\t\tm_last_ground_pos; \t\t\t\t// Set in DoJump(), & used when calculating which side of rail skater is on.\r\n\tbool\t\t\t\t\t\t\tmRail_Backwards;\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Flags and value to override the speed limits set on the skater\r\n\tfloat\t\t\t\t\t\t\tm_override_limits_time;\t\t\t// 0.0f if not overriding, else time in seconds to override for\r\n\tfloat\t\t\t\t\t\t\tm_override_max;\t\t\t\t\t// override value for max_speed\r\n\tfloat\t\t\t\t\t\t\tm_override_max_max;\t\t\t\t// override value for max_max_speed\r\n\tfloat\t\t\t\t\t\t\tm_override_air_friction;    \t// override value for air friction\r\n\tfloat\t\t\t\t\t\t\tm_override_down_gravity;\t\t// override value for ground gravity (only applied when not going down)\r\n\r\n\tObj::CSmtPtr<Obj::CCompositeObject>\tmp_skitch_object;\r\n\r\n\tbool\t\t\t\t\t\t\tmNoSpin;\t\t\t\t\t\t// Gets set and reset by NoSpin and CanSpin.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Disables left-right pad control of the spin.\r\n\tbool\t\t\t\t\t\t\tm_bail;\t\t\t\t\t\t\t// Set by BailOn, reset by BailOff and tested using BailIsOn\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_front_truck_sparks;\t\t\t// True if sparks come from the front trucks; false if from the rear\r\n\r\n\tbool\t\t\t\t\t\t\tmLandedFromSpine;\t\t\t\t// True if landed from a transfer.\r\n\tbool\t\t\t\t\t\t\tmLandedFromVert;\t\t\t\t// True if landed from vert. Can be set & reset by script commands.\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_true_landed_from_vert;\t\t// This is the 'true' landed from vert flag, which only gets set by the C-code on landing. Scripts\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// cannot change its value.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Used by the Clearpanel_Landed C-code to determine whether or not to count an ollie as a trick.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 180 Ollies are not counted as tricks if you landed from vert, only spins of at least 360 count.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// mLandedFromVert can't be used because the scripts have already cleared it by the time the \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Clearpanel_Landed command is executed.\r\n\t\r\n\tbool\t\t\t\t\t\t\tmAllowLipNoGrind;               // When this is set, then lip tricks will always happen when sticking to a rail,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// and grinds will not be allowed.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Only gets set or reset by script commands, AllowLipNoGrind and ClearAllowLipNoGrind\r\n\t\r\n\tint\t\t\t\t\t\t\t\tm_tense_time;                   // The time that the player was tensed for. Gets recorded by MaybeFlagOllieException,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// and used by the DoJump function.\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_transfer_target_height;\t\t// target point for transfer\r\n\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// These next two needed by the AirTimeLessThan and AirTimeGreaterThan script functions.\r\n\tTmr::Time\t\t\t\t\t\tm_went_airborne_time;\t\t\t// The time when the state change to AIR\r\n\tTmr::Time\t\t\t\t\t\tm_landed_time; \t\t\t\t\t// The time when the state changed from AIR to something else.\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_lock_velocity_direction;\t\t// Ken: Switched on/off by the LockVelocityDirection command.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// This is a way to allow the skater to be able to cross a gap in a loop whilst\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// inverted and technically being on the ground (on an invisible poly) but such that he \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// looks he's in the air. He will be able to be rotated, but his velocity will not turn\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// with his rotation.\r\n\t\r\n\tMth::Vector\t\t\t\t\t\tmWallNormal;\r\n\tuint32\t\t\t\t\t\t\tmWallrideTime; \t\t\t\t\t// The time the wall-ride was triggered. Used to stop the player triggering\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// another one too soon after the last.\r\n\r\n\tbool\t\t\t\t\t\t\tmNoRailTricks;                  // K: No grinds or lip tricks are allowed if this flag is set. This is switched on and off by\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// the NoGrind and AllowGrind script commands. These are used when jumping out of\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// a lip trick to disallow going straight into a grind.\r\n\t\r\n\tbool\t\t\t\t\t\t\tmYAngleIncreased;\t\t\t\t// Keeps track of whether the y angle last increased or decreased.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Used by the LastSpinWas command.\r\n\t\r\n\tint\t\t\t\t\t\t\t\tmGrindTweak;\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_transfer_overrides_factor;\t// Control the overriding of speed limits after an acid drop.\r\n\t\r\n\tMth::Matrix\t\t\t\t\t\tm_acid_drop_camera_matrix;\r\n\t\r\n\tMth::SlerpInterpolator\t\t\tm_transfer_slerper;\t\t\t\t// Variables controlling the slerping of the skater's matrix during an acid drop\r\n\tfloat\t\t\t\t\t\t\tm_transfer_slerp_timer;\r\n\tfloat\t\t\t\t\t\t\tm_transfer_slerp_duration;\r\n\tMth::Vector\t\t\t\t\t\tm_transfer_goal_facing;\r\n\tMth::Matrix\t\t\t\t\t\tm_transfer_slerp_previous_matrix;\r\n\r\n\tTmr::Time\t\t\t\t\t\tm_last_wallplant_time_stamp;\t// Timestamps wallplants in order to not allow a second one for a short duration.\r\n\tTmr::Time\t\t\t\t\t\tm_last_wallpush_time_stamp;\t\t// Timestamps wallpushes in order to not allow a second one for a short duration.\r\n\t\r\n\tTmr::Time\t\t\t\t\t\tm_last_jump_time_stamp;\t\t\t// Timestamps jumps\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_vert_air_last_frame;\t\t\t// Used to broadcast vert air enter and exit events\r\n\t\r\n\tNx::CCollCache*\t\t\t\t\tmp_coll_cache;\r\n\t\r\nprivate:\r\n\t// peer components\r\n\tCInputComponent*\t\t\t\tmp_input_component;\r\n\tCTriggerComponent*\t\t\t\tmp_trigger_component;\r\n\tCSkaterSoundComponent*\t\t\tmp_sound_component;\r\n\tCTrickComponent*\t\t\t\tmp_trick_component;\r\n\tCSkaterRotateComponent*\t\t\tmp_rotate_component;\r\n\tCSkaterScoreComponent*\t\t\tmp_score_component;\r\n\tCSkaterBalanceTrickComponent*\tmp_balance_trick_component;\r\n\tCSkaterStateComponent*\t\t\tmp_state_component;\r\n\tCMovableContactComponent*\t\tmp_movable_contact_component;\r\n\tCSkaterPhysicsControlComponent*\tmp_physics_control_component;\r\n\tCWalkComponent*\t\t\t\t\tmp_walk_component;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline bool CSkaterCorePhysicsComponent::is_braking (   )\r\n{\r\n\t return m_braking;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline bool CSkaterCorePhysicsComponent::is_vert_for_transfers ( const Mth::Vector& normal )\r\n{\r\n\t// cull out non-vert vert polys when looking for spine transfer and acid drop triggers; allows designers to be a little sloppier\r\n\treturn Mth::Abs(normal[Y]) < 0.707f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline EStateType CSkaterCorePhysicsComponent::GetState (   )\r\n{\r\n\treturn mp_state_component->m_state;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Tmr::Time CSkaterCorePhysicsComponent::GetFlagTime ( ESkaterFlag flag )\r\n{\r\n\treturn mp_state_component->m_skater_flags[flag].GetTime();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Tmr::Time CSkaterCorePhysicsComponent::GetFlagElapsedTime ( ESkaterFlag flag )\r\n{\r\n\treturn mp_state_component->m_skater_flags[flag].GetElapsedTime();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CSkaterCorePhysicsComponent::GetFlag ( ESkaterFlag flag )\r\n{\r\n\treturn mp_state_component->m_skater_flags[flag].Get(); \r\n} \t\t\t\t\t\t\t\t \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t\t\t\t \r\ninline void CSkaterCorePhysicsComponent::SetFlag ( ESkaterFlag flag, bool state )\r\n{\r\n\tmp_state_component->m_skater_flags[flag].Set(state);\r\n\tif (flag == RAIL_SLIDING)\r\n\t{\r\n\t\tmp_sound_component->SetIsRailSliding(state);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterCorePhysicsComponent::SetFlagTrue ( ESkaterFlag flag )\r\n{\r\n\tSetFlag(flag, true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterCorePhysicsComponent::SetFlagFalse ( ESkaterFlag flag )\r\n{\r\n\tSetFlag(flag, false);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterCorePhysicsComponent::ToggleFlag ( ESkaterFlag flag )\r\n{\r\n\tSetFlag(flag, !GetFlag(flag));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n \t\t\t\t\t\t\t\t \r\ninline bool CSkaterCorePhysicsComponent::IsSwitched (   )\r\n{\r\n\treturn GetSkater()->m_isGoofy ? GetFlag(FLIPPED) : !GetFlag(FLIPPED);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n \t\t\t\t\t\t\t\t \r\ninline bool CSkaterCorePhysicsComponent::HaveLandedThisFrame (   )\r\n{\r\n\treturn m_landed_this_frame;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline ETerrainType CSkaterCorePhysicsComponent::GetLastGroundTerrain (   )\r\n{\r\n\treturn m_last_ground_feeler.GetTerrain();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint32 CSkaterCorePhysicsComponent::GetLastNodeChecksum (   )\r\n{\r\n\treturn m_last_ground_feeler.GetNodeChecksum();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CSkaterCorePhysicsComponent::GetTrueLandedFromVert (   )\r\n{\r\n\treturn m_true_landed_from_vert;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterCorePhysicsComponent::ResetSpecialFrictionIndex (   )\r\n{\r\n \tm_special_friction_index = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n \t\t\t\t\t\t\t\t \r\ninline ETerrainType CSkaterCorePhysicsComponent::GetTerrain (   )\r\n{\r\n\treturn mp_state_component->m_terrain;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline sint16\tCSkaterCorePhysicsComponent::GetRailNode( void )\r\n{\r\n\tif( mp_rail_node )\r\n\t{\r\n\t\treturn mp_rail_node->GetNode();\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn -1;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n \t\t\t\t\t\t\t\t \r\ninline void CSkaterCorePhysicsComponent::ResetGrindTweak (   )\r\n{\r\n\tmGrindTweak = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ninline void CSkaterCorePhysicsComponent::ResetLerpingMatrix (   )\r\n{\r\n\tm_lerping_display_matrix = GetObject()->m_matrix;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n \t\t\t\t\t\t\t\t \r\ninline void CSkaterCorePhysicsComponent::set_terrain ( ETerrainType terrain )\r\n{\r\n\tmp_state_component->m_terrain = terrain;\r\n\tmp_sound_component->SetTerrain(terrain);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n \t\t\t\t\t\t\t\t \r\ninline void CSkaterCorePhysicsComponent::set_last_ground_feeler ( CFeeler& feeler )\r\n{\r\n\tm_last_ground_feeler = feeler;\r\n\tmp_sound_component->SetLastTerrain(m_last_ground_feeler.GetTerrain());\r\n}\r\n\r\n}\r\n\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterEndRunComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterEndRunComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/28/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skaterendruncomponent.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/objects/skater.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/objtrack.h>\r\n\r\n#define\tFLAGEXCEPTION(X) GetObject()->SelfEvent(X)\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent* CSkaterEndRunComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterEndRunComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterEndRunComponent::CSkaterEndRunComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERENDRUN );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterEndRunComponent::~CSkaterEndRunComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterEndRunComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterEndRunComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterEndRunComponent::Update()\r\n{\r\n\tif (!Mdl::Skate::Instance()->IsMultiplayerGame())\r\n\t{\r\n\t\tSuspend(true);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif( static_cast< CSkater* >(GetObject())->IsLocalClient())\r\n\t{\r\n\t\tif (m_flags.Test(FINISHED_END_OF_RUN) && !GameNet::Manager::Instance()->HaveSentEndOfRunMessage())\r\n\t\t{\r\n\t\t\tGameNet::Manager::Instance()->SendEndOfRunMessage();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterEndRunComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | EndOfRunDone | \r\n\t\tcase CRCC(0x4c58771e, \"EndOfRunDone\"):\r\n\t\t\tm_flags.Set(FINISHED_END_OF_RUN);\r\n\t\t\tm_flags.Clear(IS_ENDING_RUN);\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase CRCC(0xb866bf9b, \"RunStarted\"):\r\n\t\t\tm_flags.Clear(STARTED_END_OF_RUN);\r\n\t\t\tm_flags.Clear( STARTED_GOAL_END_OF_RUN );\r\n\t\t\tm_flags.Clear(FINISHED_END_OF_RUN);\r\n\t\t\tm_flags.Clear( FINISHED_GOAL_END_OF_RUN );\r\n\t\t\tm_flags.Clear(IS_ENDING_RUN);\r\n\t\t\tm_flags.Clear(IS_ENDING_GOAL);\r\n\t\t\tbreak;\r\n\r\n\t\tcase CRCC(0x962dea01, \"EndOfRunStarted\"):\r\n\t\t\tm_flags.Set(STARTED_END_OF_RUN);\r\n\t\t\tbreak;\r\n\r\n\t\tcase CRCC(0xafc6a7,\"Goal_EndOfRunStarted\"):\r\n\t\t\tm_flags.Set(STARTED_GOAL_END_OF_RUN);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | Goal_EndOfRunDone | \r\n\t\tcase CRCC(0x69a9e37f, \"Goal_EndOfRunDone\"):\r\n\t\t\tm_flags.Set(FINISHED_GOAL_END_OF_RUN);\r\n\t\t\tm_flags.Clear(IS_ENDING_GOAL);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x95bdcfcd, \"IsInEndOfRun\"):\r\n\t\t\treturn (m_flags.Test(STARTED_END_OF_RUN) && !m_flags.Test(FINISHED_END_OF_RUN)) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterEndRunComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterEndRunComponent::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddChecksum(CRCD(0x449233d0, \"STARTED_END_OF_RUN\"), m_flags.Test(STARTED_END_OF_RUN) ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\tp_info->AddChecksum(CRCD(0x90259288, \"FINISHED_END_OF_RUN\"), m_flags.Test(FINISHED_END_OF_RUN) ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\tp_info->AddChecksum(CRCD(0x0d2a8609, \"IS_ENDING_RUN\"), m_flags.Test(IS_ENDING_RUN) ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\tp_info->AddChecksum(CRCD(0x80818017, \"STARTED_GOAL_END_OF_RUN\"), m_flags.Test(STARTED_GOAL_END_OF_RUN) ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\tp_info->AddChecksum(CRCD(0x587092f3, \"FINISHED_GOAL_END_OF_RUN\"), m_flags.Test(FINISHED_GOAL_END_OF_RUN) ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\tp_info->AddChecksum(CRCD(0xcc3b2295, \"IS_ENDING_GOAL\"), m_flags.Test(IS_ENDING_GOAL) ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterEndRunComponent::EndRun ( bool force_end )\r\n{\r\n\tif (force_end || Mdl::Skate::Instance()->GetGameMode()->ShouldStopAtZero())\r\n\t{\r\n\t\tif (!m_flags.Test(IS_ENDING_RUN) && !m_flags.Test(FINISHED_END_OF_RUN))\r\n\t\t{\r\n\t\t\t//DumpUnwindStack( 20, 0 );\r\n\t\t\tm_flags.Set(IS_ENDING_RUN);\r\n\t\t\tif (static_cast< CSkater* >(GetObject())->IsLocalClient())\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript(CRCD(0xf4ce3e97, \"ForceEndOfRun\"), NULL, GetObject());\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//DumpUnwindStack( 20, 0 );\r\n\t\tFLAGEXCEPTION(CRCD(0x822e13a9, \"RunHasEnded\"));\r\n\t\tm_flags.Clear(FINISHED_END_OF_RUN);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterEndRunComponent::EndGoalRun ( bool force_end )\r\n{\r\n\tm_flags.Clear(FINISHED_GOAL_END_OF_RUN);\r\n\tFLAGEXCEPTION( CRCD(0xab676175, \"GoalHasEnded\") );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterEndRunComponent::RunHasEnded (   )\r\n{\r\n\treturn m_flags.Test(FINISHED_END_OF_RUN);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterEndRunComponent::GoalRunHasEnded (   )\r\n{\r\n\treturn m_flags.Test(FINISHED_GOAL_END_OF_RUN);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterEndRunComponent::StartedEndOfRun (   )\r\n{\r\n\treturn m_flags.Test(STARTED_END_OF_RUN);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterEndRunComponent::ClearStartedEndOfRunFlag (   )\r\n{\r\n\tm_flags.Clear(STARTED_END_OF_RUN);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterEndRunComponent::StartedGoalEndOfRun (   )\r\n{\r\n\treturn m_flags.Test(STARTED_GOAL_END_OF_RUN);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterEndRunComponent::ClearStartedGoalEndOfRunFlag (   )\r\n{\r\n\tm_flags.Clear(STARTED_GOAL_END_OF_RUN);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterEndRunComponent::IsEndingRun (   )\r\n{\r\n\treturn m_flags.Test(IS_ENDING_RUN);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterEndRunComponent::ClearIsEndingRun (   )\r\n{\r\n\tm_flags.Clear(IS_ENDING_RUN);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nFlags<int>\tCSkaterEndRunComponent::GetFlags( void )\r\n{\r\n\treturn m_flags;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSkaterEndRunComponent::SetFlags( Flags<int> flags )\r\n{\r\n\tm_flags = flags;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterEndRunComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterEndRunComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/28/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERENDRUNCOMPONENT_H__\r\n#define __COMPONENTS_SKATERENDRUNCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_SKATERENDRUN CRCD(0xb1d5a3e1, \"SkaterEndRun\")\r\n\r\n#define\t\tGetSkaterEndRunComponent() ((Obj::CSkaterEndRunComponent*)GetComponent(CRC_SKATERENDRUN))\r\n#define\t\tGetSkaterEndRunComponentFromObject(pObj) ((Obj::CSkaterEndRunComponent*)(pObj)->GetComponent(CRC_SKATERENDRUN))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CSkaterEndRunComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkaterEndRunComponent();\r\n    virtual ~CSkaterEndRunComponent();\r\n\t\r\n\tenum EFlagType\r\n\t{\r\n\t\tSTARTED_END_OF_RUN,\r\n\t\tFINISHED_END_OF_RUN,\r\n\t\tIS_ENDING_RUN,\r\n\t\tSTARTED_GOAL_END_OF_RUN,\r\n\t\tFINISHED_GOAL_END_OF_RUN,\r\n\t\tIS_ENDING_GOAL\r\n\t\t// If adding more than 8 flags, tell Steve\r\n\t};\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tEndRun ( bool force_end = false );\r\n\tvoid\t\t\t\t\t\t\tEndGoalRun ( bool force_end = false );\r\n\tbool\t\t\t\t\t\t\tRunHasEnded (   );\r\n\tbool\t\t\t\t\t\t\tGoalRunHasEnded (   );\r\n\tbool\t\t\t\t\t\t\tStartedEndOfRun (   );\r\n\tvoid\t\t\t\t\t\t\tClearStartedEndOfRunFlag (   );\r\n\tbool\t\t\t\t\t\t\tStartedGoalEndOfRun (   );\r\n\tvoid\t\t\t\t\t\t\tClearStartedGoalEndOfRunFlag (   );\r\n\tbool\t\t\t\t\t\t\tIsEndingRun (   );\r\n\tvoid\t\t\t\t\t\t\tClearIsEndingRun (   );\r\n\tFlags<int>\t\t\t\t\t\tGetFlags( void );\r\n\tvoid\t\t\t\t\t\t\tSetFlags( Flags<int> flags );\r\n\r\n\t\r\nprivate:\r\n\tFlags<int>\t\t\t\t\t\tm_flags;\r\n\t\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterFinalizePhysicsComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         sk/Components\r\n//* FILENAME:       SkaterFinalizePhysicsComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/26/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skaterfinalizephysicscomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n#include <sk/components/skaterloopingsoundcomponent.h>\r\n#include <sk/components/skatersoundcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\t\t\t\t  \r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent* CSkaterFinalizePhysicsComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterFinalizePhysicsComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterFinalizePhysicsComponent::CSkaterFinalizePhysicsComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERFINALIZEPHYSICS );\r\n\r\n\tmp_core_physics_component = NULL;\r\n\tmp_state_component = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterFinalizePhysicsComponent::~CSkaterFinalizePhysicsComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFinalizePhysicsComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFinalizePhysicsComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFinalizePhysicsComponent::Finalize (   )\r\n{\r\n\tmp_core_physics_component = GetSkaterCorePhysicsComponentFromObject(GetObject());\r\n\tmp_state_component = GetSkaterStateComponentFromObject(GetObject());\r\n\t\t\r\n\tDbg_Assert(mp_core_physics_component);\r\n\tDbg_Assert(mp_state_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFinalizePhysicsComponent::Update()\r\n{\r\n\t// setup the state component\r\n\t\r\n\t// Logic for setting/not setting the flag for telling the camera whether to look down on the skater or not.\r\n\tif (mp_core_physics_component->m_began_frame_in_lip_state && mp_state_component->GetState() != LIP)\r\n\t{\r\n\t\t// This flag is sort of badly named now, it really means we changed from the lip state to something other than GROUND or LIP.\r\n\t\tmp_state_component->mJumpedOutOfLipTrick = false;\r\n\t\tif (mp_state_component->GetState() == AIR)\r\n\t\t{\r\n\t\t\t// we only want to set this flag if we jumped straight up; meaning the x and z velocities are close to zero\r\n\t\t\tif (Mth::Abs(GetObject()->m_vel[X]) < 1.0f && Mth::Abs(GetObject()->m_vel[Z]) < 1.0f)\r\n\t\t\t{\r\n\t\t\t\tmp_state_component->mJumpedOutOfLipTrick = true;\r\n\t\t\t}\t\t\t\t\r\n\t\t}\r\n\t}\r\n\t\r\n\t// this flag needs clearing whenever we get out of the air\r\n\tif (mp_state_component->GetState() != AIR)\r\n\t{\r\n\t\tmp_state_component->mJumpedOutOfLipTrick = false;\r\n\t}\r\n\t\r\n\tmp_state_component->m_camera_display_normal = mp_core_physics_component->m_display_normal;\r\n\tmp_state_component->m_camera_current_normal = mp_core_physics_component->m_current_normal;\r\n\t\r\n\t// make sure the matrices don't get distorted\r\n\tGetObject()->m_matrix.OrthoNormalizeAbout(Y);\r\n\tmp_core_physics_component->m_lerping_display_matrix.OrthoNormalizeAbout(Y);\r\n\t\r\n\t// if any part of the matrix has collapsed, then we will neet to patch it up\t\r\n\t// Note, this is a very rare occurence; probably only occurs when you hit things perfectly at right angles, so\r\n\t// you attempt to orthonormalize about an axis that that is now coincident with another axis\r\n\t// would not happen if we rotated the matrix, or used quaternions\r\n\tif (GetObject()->m_matrix.PatchOrthogonality())\r\n\t{\r\n\t\tmp_core_physics_component->ResetLerpingMatrix();\r\n\t}\r\n\t\r\n\t// Extract the informations from the physics object that we need for rendering\r\n\tGetObject()->SetDisplayMatrix(mp_core_physics_component->m_lerping_display_matrix);\r\n\t\r\n\t#ifdef __USER_DAN__\r\n\t// Gfx::AddDebugArrow(GetObject()->GetPos(), GetObject()->GetPos() + 60.0f * GetObject()->GetDisplayMatrix()[Z], RED, 0, 1);\r\n\t// Gfx::AddDebugArrow(GetObject()->GetPos(), GetObject()->GetPos() + 60.0f * GetObject()->GetDisplayMatrix()[X], BLUE, 0, 1);\r\n\t// Gfx::AddDebugArrow(GetObject()->GetPos(), GetObject()->GetPos() + 60.0f * GetObject()->GetDisplayMatrix()[Y], GREEN, 0, 1);\r\n\t#endif\r\n\t\r\n\t// update the sound components' state\r\n\t\r\n\tObj::CSkaterSoundComponent *pSoundComponent = GetSkaterSoundComponentFromObject( GetObject() );\r\n\tDbg_Assert( pSoundComponent );\r\n\t\r\n\tpSoundComponent->SetIsRailSliding( mp_state_component->GetFlag(RAIL_SLIDING) );\r\n\tpSoundComponent->SetTerrain( mp_state_component->GetTerrain() );\r\n\t\r\n\tObj::CSkaterLoopingSoundComponent *pLoopingSoundComponent = GetSkaterLoopingSoundComponentFromObject( GetObject() );\r\n\tDbg_Assert( pLoopingSoundComponent );\r\n\t\r\n\tfloat speed_fraction = sqrtf( GetObject()->GetVel()[X] * GetObject()->GetVel()[X] + GetObject()->GetVel()[Z] * GetObject()->GetVel()[Z] ) / GetSkater()->GetScriptedStat(CRCD(0xcc5f87aa, \"Skater_Max_Max_Speed_Stat\") );\r\n\tpLoopingSoundComponent->SetSpeedFraction( speed_fraction );\r\n\tpLoopingSoundComponent->SetIsBailing(mp_state_component->GetFlag(IS_BAILING));\r\n\tpLoopingSoundComponent->SetIsRailSliding( mp_state_component->GetFlag(RAIL_SLIDING) );\r\n\tpLoopingSoundComponent->SetTerrain( mp_state_component->GetTerrain() );\r\n\tpLoopingSoundComponent->SetState( mp_state_component->GetState() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterFinalizePhysicsComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFinalizePhysicsComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterFinalizePhysicsComponent::GetDebugInfo\"));\r\n\t\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterFinalizePhysicsComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         sk/Components\r\n//* FILENAME:       SkaterFinalizePhysicsComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/26/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERFINALIZEPHYSICSCOMPONENT_H__\r\n#define __COMPONENTS_SKATERFINALIZEPHYSICSCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_SKATERFINALIZEPHYSICS CRCD(0x9b373e58, \"SkaterFinalizePhysics\")\r\n\r\n#define\t\tGetSkaterFinalizePhysicsComponent() ((Obj::CSkaterFinalizePhysicsComponent*)GetComponent(CRC_SKATERFINALIZEPHYSICS))\r\n#define\t\tGetSkaterFinalizePhysicsComponentFromObject(pObj) ((Obj::CSkaterFinalizePhysicsComponent*)(pObj)->GetComponent(CRC_SKATERFINALIZEPHYSICS))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CSkaterStateComponent;\r\n\r\nclass CSkaterFinalizePhysicsComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkaterFinalizePhysicsComponent();\r\n    virtual ~CSkaterFinalizePhysicsComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\t\r\nprivate:\r\n\tCSkaterCorePhysicsComponent* \tmp_core_physics_component;\r\n\tCSkaterStateComponent* \t\t\tmp_state_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterFlipAndRotateComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterFlipAndRotateComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/31/3\r\n//****************************************************************************\r\n\r\n/*\r\n * Encapsulates the dirty, dirty skater flip, skater rotate, and board rotate animation logic.\r\n *\r\n * \"Please!\" says CSkaterFlipAndRotateComponent, \"Deprecate me, and end my torturous existence!\"\r\n */\r\n\r\n#include <sk/components/skaterflipandrotatecomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/net/client/netclnt.h>\r\n\r\nnamespace Obj\r\n{\r\n\textern bool DebugSkaterScripts;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSkaterFlipAndRotateComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterFlipAndRotateComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterFlipAndRotateComponent::CSkaterFlipAndRotateComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERFLIPANDROTATE );\r\n\t\r\n\tmp_animation_component = NULL;\r\n\tmp_model_component = NULL;\r\n\t\r\n\tm_rotate_board = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterFlipAndRotateComponent::~CSkaterFlipAndRotateComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFlipAndRotateComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFlipAndRotateComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFlipAndRotateComponent::Finalize (   )\r\n{\r\n\t// Note: Non-local clients have a CSkaterFlipAndRotateComponent, but not a CSkaterCorePhysicsComponent.\r\n\tmp_core_physics_component = GetSkaterCorePhysicsComponentFromObject(GetObject());\r\n\t\r\n\tmp_model_component = GetModelComponentFromObject(GetObject());\r\n   \tmp_animation_component = GetAnimationComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_model_component);\r\n\tDbg_Assert(mp_animation_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFlipAndRotateComponent::Update()\r\n{\r\n\tSuspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterFlipAndRotateComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | Flip | flip animation\r\n\t\tcase CRCC(0x65011baa, \"Flip\"):\t\r\n\t\t\tToggleFlipState();\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | ResetSwitched | flip if we're switched\r\n\t\tcase CRCC(0x72289a28, \"ResetSwitched\"):\r\n\t\t\tDbg_Assert(mp_core_physics_component);\r\n\t\t\tif (mp_core_physics_component->IsSwitched())\r\n\t\t\t{\r\n\t\t\t\tToggleFlipState();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// These three just set flags, which will cause the appropriate flip/rotate\r\n\t\t// when the next PlayAnim occurs. \r\n        // @script | FlipAfter | sets flag, which will cause the appropriate flip/rotate when the next PlayAnim occurs\r\n\t\tcase CRCC(0xeba11b20, \"FlipAfter\"):\r\n\t\t\tmFlipAfter = true;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | RotateAfter | sets flag, which will cause the appropriate flip/rotate when the next PlayAnim occurs\r\n\t\tcase CRCC(0xacac1bad, \"RotateAfter\"):\r\n\t\t\tmRotateAfter = true;\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | BoardRotateAfter | sets flag, which will cause the appropriate flip/rotate when the next PlayAnim occurs\r\n\t\tcase CRCC(0x63e93f69, \"BoardRotateAfter\"):\r\n\t\t\tmBoardRotateAfter = true;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | IsFlipAfterSet | returns mFlipAfter\r\n\t\tcase CRCC(0xa6243daa, \"IsFlipAfterSet\"):\r\n\t\t\treturn mFlipAfter ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n        // @script | FlipAndRotate | flip Z and X, to rotate 180 degrees about y\r\n\t\tcase CRCC(0xd9de0c65, \"FlipAndRotate\"):\r\n\t\t{\r\n\t\t\tDbg_Assert(mp_core_physics_component);\r\n\t\t\tmp_core_physics_component->ReverseFacing();\r\n\t\t\tToggleFlipState();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | BoardRotate | \r\n        // @flag normal | put the board back to normal (otherwise just flip)\r\n\t\tcase CRCC(0xe0f3a644, \"BoardRotate\"):\r\n\t\t{\r\n\t\t\tGameNet::PlayerInfo* player = GameNet::Manager::Instance()->GetPlayerByObjectID(GetObject()->GetID());\r\n\t\t\tDbg_Assert(player);\r\n\t\t\t\r\n\t\t\tNet::Client* client = GameNet::Manager::Instance()->GetClient(player->GetSkaterNumber());\r\n\t\t\tDbg_Assert(client);\r\n\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0xde7a971b, \"Normal\")))\r\n\t\t\t{\r\n\t\t\t\t// Put the board back to normal\r\n\t\t\t\tRotateSkateboard(GetObject()->GetID(), false, client->m_Timestamp, true);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Otherwise flip it, flip it good.\r\n\t\t\t\tRotateSkateboard(GetObject()->GetID(), !m_rotate_board, client->m_Timestamp, true);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// @script | BoardIsRotated | \r\n\t\tcase CRCC(0x79ee5ccf, \"BoardIsRotated\"):\r\n\t\t\treturn m_rotate_board ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\tcase CRCC(0xb1e7291, \"PlayAnim\"):\r\n\t\t\t// do any required flips and rotates, and then cascade the member function call\r\n\t\t\tDoAnyFlipRotateOrBoardRotateAfters();\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFlipAndRotateComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterFlipAndRotateComponent::GetDebugInfo\"));\r\n\t\r\n\tif (mp_core_physics_component)\r\n\t{\r\n\t\tp_info->AddChecksum(CRCD(0x8f66b80b, \"switched\"), mp_core_physics_component->IsSwitched() ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\t}\r\n\tp_info->AddChecksum(CRCD(0xc7a712c, \"flipped\"), GetSkaterStateComponentFromObject(GetObject())->GetFlag(FLIPPED) ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\t\r\n\tp_info->AddChecksum(CRCD(0xeba11b20, \"FlipAfter\"), mFlipAfter ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\tp_info->AddChecksum(CRCD(0xacac1bad, \"RotateAfter\"), mRotateAfter ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\tp_info->AddChecksum(CRCD(0x63e93f69, \"BoardRotateAfter\"), mBoardRotateAfter ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\t\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterFlipAndRotateComponent::RotateSkateboard ( uint32 objId, bool rotate, uint32 time, bool propagate )\r\n{\r\n\tif ( propagate )\r\n\t{\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tGameNet::PlayerInfo* player;\r\n\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( objId );\r\n\t\tif( player && player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tNet::Client* client;\r\n\t\t\tGameNet::MsgRotateSkateboard msg;\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\tclient = gamenet_man->GetClient( player->GetSkaterNumber());\r\n\t\t\tDbg_Assert( client );\r\n\r\n\t\t\tmsg.m_Rotate = rotate;\r\n\t\t\tmsg.m_ObjId = objId;\r\n\r\n\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_ROTATE_SKATEBOARD;\r\n\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgRotateSkateboard );\r\n\t\t\tclient->EnqueueMessageToServer(\t&msg_desc );\r\n\t\t}\r\n\t}\r\n\r\n\tbool oldRotation = m_rotate_board;\r\n\r\n\tm_rotate_board = rotate;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (DebugSkaterScripts && GetObject()->GetType() == SKATE_TYPE_SKATER)\r\n\t{\r\n\t\tprintf(\"%d: Rotating board [rotated = %s]\\n\", (int) Tmr::GetRenderFrame(), m_rotate_board ? \"true\" : \"false\");\r\n\t}\r\n\t#endif\r\n\r\n\treturn oldRotation;\r\n}\r\n\r\n/******************************************************************/\r\n\r\n/*\r\n\r\nIf any of mFlipAfter, mRotateAfter or mBoardRotateAfter are set\r\nthis will flip or rotate the skater, or rotate the board, and then\r\nreset those flags.\r\n\r\nQuite often the skater needs to be flipped and/or rotated in order to\r\nlook correctly oriented, due to the way the animations are done.\r\nFor example, the nollie heelflip animation is actually animated backwards,\r\nso to look correct the skater has to be flipped and rotated just for the\r\nduration of that animation.\r\nAs soon as any sort of 'event' happens that could result in an animation\r\nchange, or requires that the orientation be correct for the physics, then\r\nthe skater needs to be flipped and rotated back.\r\nSo in the script, when running the nollie heelflip anim, Scott will flip and\r\nrotate the skater first so that he looks correct, then set FlipAfter and RotateAfter.\r\n\r\nIt used to be that I'd check the flags only in the next call to the PlayAnim script \r\nmember function.\r\nHowever, this is often not early enough. For example, when the player lands whilst\r\ndoing a nollie heelflip, the land script will do some checks to see if the player \r\nis facing backwards before doing a playanim, so it will wrongly think the player\r\nis backwards, when he isn't 'really'.\r\n\r\nSo instead I sprinkled calls to the following function whenever anything happens\r\nthat could cause a new script to be executed. In particular, before every SetScript,\r\nand also as soon as a grind gets detected, so that the grind maths won't think the\r\nskater is backwards when landing from a nollie heelflip.\r\n\r\n*/\r\n\r\n/******************************************************************/\r\n\r\nvoid CSkaterFlipAndRotateComponent::DoAnyFlipRotateOrBoardRotateAfters (   )\r\n{\r\n\tif (mFlipAfter)\r\n\t{\r\n\t\tToggleFlipState();\r\n\t\tmFlipAfter = false;\r\n\t}\r\n\t\t\r\n\tif (mRotateAfter)\r\n\t{\r\n\t\tDbg_Assert(mp_core_physics_component);\r\n\t\tmp_core_physics_component->ReverseFacing();\r\n\t\tmRotateAfter = false;\r\n\t}\r\n\t\t\r\n\tif (mBoardRotateAfter)\r\n\t{\r\n\t\tGameNet::PlayerInfo* player = GameNet::Manager::Instance()->GetPlayerByObjectID(GetObject()->GetID());\r\n\t\tDbg_Assert(player);\r\n\r\n\t\tNet::Client* client = GameNet::Manager::Instance()->GetClient(player->GetSkaterNumber());\r\n\t\tDbg_Assert(client);\r\n\r\n\t\t// Rotate the board.\r\n\t\tRotateSkateboard(GetObject()->GetID(), !m_rotate_board, client->m_Timestamp, true);\r\n\t\tmBoardRotateAfter = false;\r\n\t}\t\r\n\t\r\n\t// This makes the skater display facing the correct way again.\r\n\t// The mFlipDisplayMatrix is only used when falling back in from a lip trick.\r\n\t// Since it would be bad if this flag got left on, make sure it is off whenever\r\n\t// a new anim runs. This function is a good place to put it, since it gets\r\n\t// run whenever the anim changes.\r\n\tmp_model_component->mFlipDisplayMatrix = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFlipAndRotateComponent::Reset (   )\r\n{\r\n\tmFlipAfter = false;\r\n\tmRotateAfter = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFlipAndRotateComponent::ToggleFlipState (   )\r\n{\r\n\tGetSkaterStateComponentFromObject(GetObject())->m_skater_flags[FLIPPED].Toggle();\t\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (DebugSkaterScripts && GetObject()->GetType() == SKATE_TYPE_SKATER)\r\n\t{\r\n\t\tprintf(\"%d: Flipping skater [flipped = %s]\\n\", (int) Tmr::GetRenderFrame(), mp_core_physics_component->GetFlag(FLIPPED) ? \"true\" : \"false\");\r\n\t}\r\n\t#endif\r\n\t\r\n\t// Flip the animation to the correct orientation Just setting a flag for Dave's code to handle when rendering\r\n\tApplyFlipState();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFlipAndRotateComponent::ApplyFlipState (   )\r\n{\r\n\tNet::Client* client = GameNet::Manager::Instance()->GetClient(GetSkater()->GetSkaterNumber());\r\n\tDbg_Assert(client);\r\n\t\r\n\tmp_animation_component->FlipAnimation(GetObject()->GetID(), GetSkaterStateComponentFromObject(GetObject())->GetFlag(FLIPPED), client->m_Timestamp, true);\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterFlipAndRotateComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterFlipAndRotateComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/31/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERFLIPANDROTATECOMPONENT_H__\r\n#define __COMPONENTS_SKATERFLIPANDROTATECOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_SKATERFLIPANDROTATE CRCD(0x488af07a, \"SkaterFlipAndRotate\")\r\n\r\n#define\t\tGetSkaterFlipAndRotateComponent() ((Obj::CSkaterFlipAndRotateComponent*)GetComponent(CRC_SKATERFLIPANDROTATE))\r\n#define\t\tGetSkaterFlipAndRotateComponentFromObject(pObj) ((Obj::CSkaterFlipAndRotateComponent*)(pObj)->GetComponent(CRC_SKATERFLIPANDROTATE))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CAnimationComponent;\r\n\tclass CSkaterCorePhysicsComponent;\r\n\tclass CModelComponent;\r\n\r\nclass CSkaterFlipAndRotateComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkaterFlipAndRotateComponent();\r\n    virtual ~CSkaterFlipAndRotateComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t   \t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\r\npublic:\r\n\tvoid\t\t\t\t\t\t\tReset (   );\r\n\t\r\n\tbool\t\t\t\t\t\t\tRotateSkateboard ( uint32 objId, bool rotate, uint32 time, bool propagate );\r\n\tbool\t\t\t\t\t\t\tIsBoardRotated (   ) { return m_rotate_board; }\r\n\t\r\n\tvoid\t\t\t\t\t\t\tDoAnyFlipRotateOrBoardRotateAfters (   );\r\n\t\t\t\t\t\t\t\t\t  \t\r\n\tvoid\t\t\t\t\t\t\tToggleFlipState (   );\r\n\tvoid\t\t\t\t\t\t\tApplyFlipState (   );\r\n\r\nprivate:\r\n\tbool\t\t\t\t\t\t\tm_rotate_board;\r\n\t\r\n\tbool\t\t\t\t\t\t\tmFlipAfter;\r\n\tbool\t\t\t\t\t\t\tmRotateAfter;\r\n\tbool\t\t\t\t\t\t\tmBoardRotateAfter;\r\n\t\r\n\t// peer components\r\n\tCAnimationComponent*\t\t\tmp_animation_component;\r\n\tCModelComponent*\t\t\t\tmp_model_component;\r\n\tCSkaterCorePhysicsComponent*\tmp_core_physics_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterFloatingNameComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterFloatingNameComponent.h\r\n//* OWNER:\t\t\tDan\r\n//* CREATION DATE:  3/13/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skaterfloatingnamecomponent.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n\r\n#include <gfx/2d/screenelement2.h>\r\n#include <gfx/2d/screenelemman.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent* CSkaterFloatingNameComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterFloatingNameComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterFloatingNameComponent::CSkaterFloatingNameComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERFLOATINGNAME );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterFloatingNameComponent::~CSkaterFloatingNameComponent()\r\n{\r\n\tScript::CStruct* pParams = pParams = new Script::CStruct;\r\n\tpParams->AddChecksum(CRCD(0x40c698af, \"id\"), m_screen_element_id);\r\n\t\r\n\tScript::RunScript(CRCD(0x2575b406, \"destroy_object_label\"), pParams);\r\n\t\r\n\tdelete pParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFloatingNameComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tDbg_MsgAssert(GetObject()->GetType() == SKATE_TYPE_SKATER, (\"CSkaterFloatingNameComponent added to non-skater composite object\"));\r\n\t\r\n\tswitch (GetObject()->GetID())\r\n\t{\r\n\t\tcase 0:\r\n\t\t\tm_screen_element_id = CRCD(0xe797a186, \"skater_name_0\");\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tm_screen_element_id = CRCD(0x90909110, \"skater_name_1\");\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tm_screen_element_id = CRCD(0x999c0aa, \"skater_name_2\");\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tm_screen_element_id = CRCD(0x7e9ef03c, \"skater_name_3\");\r\n\t\t\tbreak;\r\n\t\tcase 4:\r\n\t\t\tm_screen_element_id = CRCD(0xe0fa659f, \"skater_name_4\");\r\n\t\t\tbreak;\r\n\t\tcase 5:\r\n\t\t\tm_screen_element_id = CRCD(0x97fd5509, \"skater_name_5\");\r\n\t\t\tbreak;\r\n\t\tcase 6:\r\n\t\t\tm_screen_element_id = CRCD(0xef404b3, \"skater_name_6\");\r\n\t\t\tbreak;\r\n\t\tcase 7:\r\n\t\t\tm_screen_element_id = CRCD(0x79f33425, \"skater_name_7\");\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(false, (\"CSkaterFloatingNameComponent in CCompositeObject with ID of 8 or greater\"));\r\n\t\t\treturn;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFloatingNameComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFloatingNameComponent::Update()\r\n{\r\n\tif (!GameNet::Manager::Instance()->InNetGame() || !GameNet::Manager::Instance()->ShouldDrawPlayerNames())\r\n\t{\r\n\t\tSuspend(true);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif (!GetSkater()->IsInWorld()) return;\r\n\t\r\n\tGameNet::PlayerInfo* player = GameNet::Manager::Instance()->GetPlayerByObjectID(GetObject()->GetID());\r\n\t\r\n\tfloat offset;\r\n\tif (GameNet::Manager::Instance()->GetCurrentlyObservedPlayer() == player)\r\n\t{\r\n\t\toffset = FEET(8.0f);\r\n\t}\r\n\telse\r\n\t{\r\n\t\toffset = FEET(10.0f);\r\n\t}\r\n\r\n\tScript::CStruct* pParams = new Script::CStruct;\r\n\tpParams->AddChecksum(CRCD(0x40c698af, \"id\"), m_screen_element_id);\r\n\r\n\tint color_index;\r\n\tif (Mdl::Skate::Instance()->GetGameMode()->IsTeamGame())\r\n\t{\r\n\t\tcolor_index = player->m_Team + 2;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcolor_index = GetObject()->GetID() + 2;\r\n\t}\r\n\r\n\tchar text[64];\r\n\tsprintf(text, \"\\\\c%d%s\", color_index, GetSkater()->GetDisplayName());\r\n\tpParams->AddString(CRCD(0xc4745838, \"text\"), text);\r\n\tpParams->AddVector(CRCD(0x4b491900, \"pos3D\"), GetObject()->m_pos[X], GetObject()->m_pos[Y] + offset, GetObject()->m_pos[Z]);\r\n\r\n\tFront::CScreenElement *p_name_elem = Front::CScreenElementManager::Instance()->GetElement(m_screen_element_id);\r\n\tif (p_name_elem)\r\n\t{\r\n\t\tp_name_elem->SetProperties(pParams);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tScript::RunScript(CRCD(0x6a060cf0, \"create_object_label\"), pParams);\r\n\t}\r\n\t\r\n\tdelete pParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterFloatingNameComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterFloatingNameComponent::GetDebugInfo ( Script::CStruct *p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterFloatingNameComponent::GetDebugInfo\"));\r\n\t\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterFloatingNameComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterFloatingNameComponent.h\r\n//* OWNER:\t\t\tDan\r\n//* CREATION DATE:  3/13/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERFLOATINGNAMECOMPONENT_H__\r\n#define __COMPONENTS_SKATERFLOATINGNAMECOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#define\t\tCRC_SKATERFLOATINGNAME CRCD(0x125044e2, \"SkaterFloatingName\")\r\n\r\n#define\t\tGetSkaterFloatingNameComponent() ((Obj::CSkaterFloatingNameComponent*)GetComponent(CRC_SKATERFLOATINGNAME))\r\n#define\t\tGetSkaterFloatingNameComponentFromObject(pObj) ((Obj::CSkaterFloatingNameComponent*)(pObj)->GetComponent(CRC_SKATERFLOATINGNAME))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CSkaterFloatingNameComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkaterFloatingNameComponent();\r\n    virtual ~CSkaterFloatingNameComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\t\r\nprivate:\r\n\tuint32\t\t\t\t\t\t\tm_screen_element_id;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterGapComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterGapComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/5/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skatergapcomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skaterbalancetrickcomponent.h>\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/components/trickcomponent.h>\r\n#include <gel/components/walkcomponent.h>\r\n#include <gel/components/vehiclecomponent.h>\r\n#include <gel/objtrack.h>\t\t\t\t\t\t\t// for event broadcasting on sucess of a gap\r\n\r\n#include <sk/objects/gap.h>\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <sk/modules/skate/score.h>\r\n#include <sk/modules/skate/skate.h>\r\n\r\n#include <sk/parkeditor2/parked.h>\r\n\r\n// #define DEBUG_GAPS\r\n\r\nnamespace Obj\r\n{\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSkaterGapComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterGapComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterGapComponent::CSkaterGapComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERGAP );\r\n\t\r\n\tmp_core_physics_component = NULL;\r\n\tmp_balance_trick_component = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterGapComponent::~CSkaterGapComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterGapComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tDbg_MsgAssert(GetObject()->GetType() == SKATE_TYPE_SKATER, (\"CSkaterGapComponent added to non-skater composite object\"));\r\n\t\r\n\tm_frame_count = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterGapComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterGapComponent::Finalize (   )\r\n{\r\n\tmp_core_physics_component = GetSkaterCorePhysicsComponentFromObject(GetObject());\r\n\tmp_balance_trick_component = GetSkaterBalanceTrickComponentFromObject(GetObject());\r\n\tmp_physics_control_component = GetSkaterPhysicsControlComponentFromObject(GetObject());\r\n\tmp_walk_component = GetWalkComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_core_physics_component);\r\n\tDbg_Assert(mp_balance_trick_component);\r\n\tDbg_Assert(mp_physics_control_component);\r\n\tDbg_Assert(mp_walk_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterGapComponent::Update()\r\n{\r\n\tm_frame_count++;\r\n\t\r\n\t// setup flags based on skater state\r\n\tint cancel, require;\r\n\tget_state_flags(cancel, require);\r\n\t\r\n\tUpdateCancelRequire(cancel, require);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Split out the actual updating from Update(), so we co do specific updates\r\n// of the require/cancel flags at arbitart times\r\n// specifically we want to update the \"Lip\" requirements as soon as we land on them\r\n// and do it in isolation, so nothing else is messed up\r\n\r\nvoid CSkaterGapComponent::UpdateCancelRequire(int cancel, int require)\r\n{\r\n\tCGap* pGap = static_cast< CGap* >(m_gap_list.FirstItem());\r\n\t\r\n\t// don't bother determining the state flags if there are no active gaps\r\n\tif (!pGap) return;\r\n\t\r\n\t// update the active gaps based on the flags\r\n\twhile (pGap)\r\n\t{\r\n\t\tCGap* pNext = static_cast< CGap* >(pGap->GetNext());\r\n\t\t\r\n\t\t// Clear any require flags that match the require mask, so if we do all that is required, then the require part of the flags field will be cleared\r\n\t\tpGap->m_flags &= ~require;\r\n\t\r\n\t\t// if any cancel flags match the cancel mask, cancel the gap\r\n\t\tif (pGap->m_flags & cancel)\r\n\t\t{\r\n//\t\t\tprintf (\"Cancelled by %x\\n\",pGap->m_flags & cancel); \r\n\t\t\tif (pGap->m_trickscript)\r\n\t\t\t{\r\n\t\t\t\t// delete the gap trick\r\n\t\t\t\tCGapTrick *pGapTrick = static_cast< CGapTrick* >(m_gaptrick_list.FirstItem());\r\n\t\t\t\twhile (pGapTrick)\r\n\t\t\t\t{\r\n\t\t\t\t\tCGapTrick * pNext = static_cast< CGapTrick* >(pGapTrick->GetNext());\r\n\t\r\n\t\t\t\t\t// only delete gaptricks if you've not been awarded them, and they exactly match the gap we're cancelling\r\n\t\t\t\t\tif (!pGapTrick->m_got\r\n\t\t\t\t\t\t&& pGapTrick->m_id == pGap->m_id\r\n\t\t\t\t\t\t&& pGapTrick->m_script == pGap->m_trickscript\r\n\t\t\t\t\t\t&& pGapTrick->m_node == pGap->m_node)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdelete pGapTrick;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\r\n\t\t\t\t\tpGapTrick = pNext;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t#ifdef DEBUG_GAPS\r\n\t\t\tMESSAGE(\"DELETING GAP\");\r\n\t\t\tDUMPC(pGap->m_id);\r\n\t\t\t#endif\r\n\t\r\n\t\t\t// delete the gap\r\n\t\t\tdelete pGap;\r\n\t\t}\r\n\t\tpGap = pNext;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterGapComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | StartGap | Start a gap...used in conjunction with EndGap. <nl>\r\n        // See online doc for detailed description and examples\r\n        // @parmopt name | GapID | Links | the name of the gap\r\n        // @parmopt array | flags | | array of flags to use\r\n\t\t// @parmopt name | trickscript | | Script that is run when you land a combo that includes this gap\r\n\t\t// subject to the two optional conditions below\r\n\t\t// @parmopt checksum | KeyCombo | | Name of a key combo, like Air_SquareD, you have to do trick with this button combo\r\n\t\t// @parmopt string | TrickText | | This text substring, like 'kickflip' has to be in the combo\r\n\t\t// @nextparm | flags | flags | file | gapflags.lst | done\r\n\t\t// @nextparm | trickscript | script\r\n\t\t// @nextparm | KeyCombo | list | file | keycombo.lst | done\r\n\t\t// @parmopt checksum | combined_flags | | An optional way of specifying the cancel flags as a uint32 consisting\r\n\t\t// of the flag bit values or'd together. Currently only used when the Park Editor calls StartGap from within\r\n\t\t// the c-code.\r\n\t\tcase CRCC(0x65b9ec39, \"StartGap\"):\r\n\t\t\tstart_gap(pParams, pScript);\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | StartGapTrick | This adds a gap trick to the skaters\r\n        // current list\r\n        // @parm string | TrickText | text to look for in the trick text \r\n        // @parm name | gapscript | script to run when you land this gap trick\r\n\t\t// @parmopt checksum | KeyCombo | | Name of a key combo, like Air_SquareD, you have to do trick with this button combo\r\n\t\tcase CRCC(0xfc4f2009, \"StartGapTrick\"):\r\n\t\t\tstart_gap_trick(pParams, pScript);\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | EndGap | end a gap - used with StartGap <nl>\r\n        // See online doc for detailed description and examples\r\n        // @parm name | GapID | gap gap_id\r\n        // @parmopt string | text | \"Unnamed Gap\" | text to display\r\n        // @parmopt int | score | | score to award for this gap\r\n        // @flag NetEnabled | \r\n        // @flag Permanent | \r\n        // @parmopt structure | continue | | for linking gaps <nl>\r\n        // e.g.  continue = { GapID = SecondHalf Cancel = CANCEL_GROUND }\r\n\t\t// @nextparm | score | slidernum | 0 | 999999\r\n\t\tcase CRCC(0xe5399fb2, \"EndGap\"):\r\n\t\t\tend_gap(pParams, pScript);\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | CheckGapTricks | Check to see if there are any gap tricks,\r\n\t\t// then check to see if we did the trick yet\r\n\t\t// if so, then fire them off\r\n\t\t// note, this does not delete gaps that you did not do\r\n\t\t// so you would ahve to call ClearGapTricks\r\n\t\t// in that case\r\n        case CRCC(0x42f80e5e, \"CheckGapTricks\"):\r\n\t\t\tcheck_gap_tricks(pParams);\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | ClearGapTricks | clears all the gap tricks.\r\n        // Currently, I call CheckGapTricks then ClearGapTricks\r\n        // at any point in the skater's logic where he can land\r\n        // a trick combo. So if you just stick a \"StartGapTrick\"\r\n        // in your gap script, then it will automatically work\r\n\t\tcase CRCC(0x196772b, \"ClearGapTricks\"):\r\n\t\t\tclear_gap_tricks(pParams);\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | DuplicateTrigger | quick way of doing two way gaps <nl>\r\n        // see online doc for detailed description and examples\r\n\t\tcase CRCC(0x4562e4a6, \"DuplicateTrigger\"):\r\n\t\t{\r\n\t\t\t// used in a trigger script\r\n\t\t\t// find the first node linked to this one that has\r\n\t\t\t// a trigger script, and execute that instead\r\n\t\t\t{\r\n\t\t\t\tint node = pScript->mNode;\r\n\t\t\t\tDbg_MsgAssert(node != -1,(\"DuplicateTrigger in script with no node,\\n%s\\n\",pScript->GetScriptInfo()));\r\n\t\t\t\tif (node != -1)\t \t\t// Failsafe\r\n\t\t\t\t{\r\n\t\t\t\t\tint links = SkateScript::GetNumLinks(node);\r\n\t\t\t\t\t//dodgy_test(); printf(\"node %d has %d links\\n\",node,links);\r\n\t\t\t\t\t\r\n\t\t\t\t\tDbg_MsgAssert(links>0,(\"DuplicateTrigger in node (%d) with no links,\\n%s\\n\",node,pScript->GetScriptInfo()));\r\n\t\t\t\t\tint i;\r\n\t\t\t\t\tfor (i=0;i<links;i++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint linked_node = SkateScript::GetLink(node,i); \r\n\t\t\t\t\t\tScript::CStruct *pDest = SkateScript::GetNode(linked_node);\r\n\t\t\t\t\t\tuint32 script = 0;\r\n\t\t\t\t\t\t//dodgy_test(); printf(\"node %d linked to node %d\\n\",node,linked_node);\r\n\t\t\t\t\t\tif (pDest->GetChecksum(CRCD(0x2ca8a299, \"TriggerScript\"),&script))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// found another trigger script in the node we are linked to\r\n\t\t\t\t\t\t\tGetObject()->SpawnAndRunScript(script,pScript->mNode);\r\n\t\t\t\t\t\t\tbreak;\t\t\r\n\t\t\t\t\t\t}\t\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\tDbg_MsgAssert(i<links,(\"DuplicateTrigger in node (%d) not linked to trigger,\\n%s\\n\",node,pScript->GetScriptInfo()));\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterGapComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterGapComponent::GetDebugInfo\"));\r\n\t\r\n\tstatic const uint32 p_gap_flag_checksums [   ]\r\n\t= {\r\n\t\tCRCD(0x9a27e74d, \"CANCEL_GROUND\"),\t\t\t\t// 0x00000001\r\n\t\tCRCD(0xc6362354, \"CANCEL_AIR\"),              \t// 0x00000002\r\n\t\tCRCD(0xcd4decee, \"CANCEL_RAIL\"),             \t// 0x00000004\r\n\t\tCRCD(0x87e4e899, \"CANCEL_WALL\"),             \t// 0x00000008\r\n\t\tCRCD(0x20e0d12b, \"CANCEL_LIP\"),              \t// 0x00000010\r\n\t\tCRCD(0x78d5a029, \"CANCEL_WALLPLANT\"),\t\t\t// 0x00000020\r\n\t\tCRCD(0x2d03dae1, \"CANCEL_MANUAL\"),\t\t\t\t// 0x00000040\r\n\t\tCRCD(0x2a7a145a, \"CANCEL_HANG\"),     \t    \t// 0x00000080\r\n\t\tCRCD(0x0a65d800, \"CANCEL_LADDER\"),\t         \t// 0x00000100\r\n\t\tCRCD(0xa4721771, \"CANCEL_SKATE\"),\t\t\t\t// 0x00000200\r\n\t\tCRCD(0x19807d3a, \"CANCEL_WALK\"),   \t\t\t\t// 0x00000400\r\n\t\tCRCD(0x678677cc, \"CANCEL_DRIVE\"),\t\t\t\t// 0x00000800\r\n\t\tCRCD(0xc6aa6589, \"NO_SUCH_GAP_FLAG\"),\t\t\t// 0x00001000\r\n\t\tCRCD(0xc6aa6589, \"NO_SUCH_GAP_FLAG\"),\t\t\t// 0x00002000\r\n\t\tCRCD(0xc6aa6589, \"NO_SUCH_GAP_FLAG\"),\t\t\t// 0x00004000\r\n\t\tCRCD(0xc6aa6589, \"NO_SUCH_GAP_FLAG\"),\t\t\t// 0x00008000\r\n\t\tCRCD(0xae0f7a14, \"REQUIRE_GROUND\"),\t\t\t\t// 0x00010000\r\n\t\tCRCD(0xdfc901ab, \"REQUIRE_AIR\"),             \t// 0x00020000\r\n\t\tCRCD(0xe056fc41, \"REQUIRE_RAIL\"),            \t// 0x00040000\r\n\t\tCRCD(0xaafff836, \"REQUIRE_WALL\"),            \t// 0x00080000\r\n\t\tCRCD(0x391ff3d4, \"REQUIRE_LIP\"),             \t// 0x00100000\r\n\t\tCRCD(0xeae2e98f, \"REQUIRE_WALLPLANT\"),\t\t\t// 0x00200000\r\n\t\tCRCD(0x192b47b8, \"REQUIRE_MANUAL\"),\t\t\t\t// 0x00400000\r\n\t\tCRCD(0x076104f5, \"REQUIRE_HANG\"),\t        \t// 0x00800000\r\n\t\tCRCD(0x3e4d4559, \"REQUIRE_LADDER\"),\t        \t// 0x01000000\r\n\t\tCRCD(0xe236b218, \"REQUIRE_SKATE\"),\t\t\t\t// 0x02000000\r\n\t\tCRCD(0x349b6d95, \"REQUIRE_WALK\"),\t\t\t\t// 0x04000000\r\n\t\tCRCD(0x21c2d2a5, \"REQUIRE_DRIVE\"),\t\t\t\t// 0x08000000\r\n\t\tCRCD(0xc6aa6589, \"NO_SUCH_GAP_FLAG\"),\t\t\t// 0x10000000\r\n\t\tCRCD(0xc6aa6589, \"NO_SUCH_GAP_FLAG\"),\t\t\t// 0x20000000\r\n\t\tCRCD(0xc6aa6589, \"NO_SUCH_GAP_FLAG\"),\t\t\t// 0x40000000\r\n\t\tCRCD(0xc6aa6589, \"NO_SUCH_GAP_FLAG\")\t\t\t// 0x80000000\r\n\t};\r\n\t\r\n\tint gap_count = 0;\r\n\tCGap* pGap = static_cast< CGap* >(m_gap_list.FirstItem());\r\n\twhile (pGap)\r\n\t{\r\n\t\tgap_count++;\r\n\t\tpGap = static_cast< CGap* >(pGap->GetNext());\r\n\t}\r\n\t\r\n\tScript::CArray* p_gaps_array = new Script::CArray;\r\n\tp_gaps_array->SetSizeAndType(gap_count, ESYMBOLTYPE_STRUCTURE);\r\n\t\r\n\tint i = 0;\r\n\tpGap = static_cast< CGap* >(m_gap_list.FirstItem());\r\n\twhile (pGap)\r\n\t{\r\n\t\tScript::CStruct* p_gap_struct = new Script::CStruct;\r\n\t\tp_gap_struct->AddChecksum(CRCD(0x40c698af, \"Id\"), pGap->m_id);\r\n\t\t\r\n\t\tScript::CStruct* p_gap_flags = new Script::CStruct;\r\n\t\tfor (int n = 0; n < 32; n++)\r\n\t\t{\r\n\t\t\tuint32 mask = 1 << n;\r\n\t\t\tif (mask & pGap->m_flags)\r\n\t\t\t{\r\n\t\t\t\tp_gap_flags->AddChecksum(NO_NAME, p_gap_flag_checksums[n]);\r\n\t\t\t}\r\n\t\t}\r\n\t\tp_gap_struct->AddStructurePointer(CRCD(0xf4fabe45, \"Flags\"), p_gap_flags);\r\n\t\t\r\n\t\tp_gaps_array->SetStructure(i, p_gap_struct);\r\n\t\ti++;\r\n\t\tpGap = static_cast< CGap* >(pGap->GetNext());\r\n\t}\r\n\tp_info->AddArrayPointer(CRCD(0xd76c173e, \"Gaps\"), p_gaps_array);\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSkaterGapComponent::ClearActiveGaps (   )\r\n{\r\n\tm_gap_list.DestroyAllNodes();\r\n\tm_gaptrick_list.DestroyAllNodes();\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterGapComponent::ClearPendingGaps (   )\r\n{\r\n\tMdl::Skate::Instance()->GetGapChecklist()->ClearPendingGaps();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSkaterGapComponent::AwardPendingGaps (   )\r\n{\r\n\tMdl::Skate::Instance()->GetGapChecklist()->AwardPendingGaps();\r\n\t\r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\tif (!pCareer->GetGlobalFlag(405/*GOT_ALL_GAPS*/) && pCareer->GotAllGaps())\r\n\t{\r\n\t\tScript::SpawnScript(CRCD(0xcc74cc2e, \"got_all_gaps_screen_create\"));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CSkaterGapComponent::get_state_flags ( int& cancel, int& require )\r\n{\r\n\tcancel = require = 0;\r\n\t\r\n\tif (!mp_physics_control_component->IsDriving())\r\n\t{\r\n\t\tif (mp_physics_control_component->IsSkating())\r\n\t\t{\r\n\t\t\t// skating\r\n\t\t\t\r\n\t\t\tcancel |= CANCEL_SKATE;\r\n\t\t\trequire |= REQUIRE_SKATE;\r\n\t\t\t\r\n\t\t\tswitch (mp_core_physics_component->GetState())\r\n\t\t\t{\r\n\t\t\t\tcase AIR:\r\n\t\t\t\t\tcancel |= CANCEL_AIR;\r\n\t\t\t\t\trequire |= REQUIRE_AIR;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase GROUND:\r\n\t\t\t\t\tif (!mp_core_physics_component->GetFlag(OVERRIDE_CANCEL_GROUND)\r\n\t\t\t\t\t\t&& !mp_balance_trick_component->GetBalanceTrickType()\r\n\t\t\t\t\t\t&& !mp_balance_trick_component->DoingBalanceTrick())\r\n\t\t\t\t\t\t// && !mp_core_physics_component->HaveLandedThisFrame())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcancel |= CANCEL_GROUND;\r\n\t\t\t\t\t\trequire |= REQUIRE_GROUND; \t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (mp_balance_trick_component->GetBalanceTrickType() || mp_balance_trick_component->DoingBalanceTrick())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcancel |= CANCEL_MANUAL;\r\n\t\t\t\t\t\trequire |= REQUIRE_MANUAL;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\r\n\t\t\t\tcase RAIL:\r\n\t\t\t\t\tcancel |= CANCEL_RAIL;\r\n\t\t\t\t\trequire |= REQUIRE_RAIL;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\r\n\t\t\t\tcase WALL:\r\n\t\t\t\t\tcancel |= CANCEL_WALL;\r\n\t\t\t\t\trequire |= REQUIRE_WALL; \t\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase LIP:\r\n\t\t\t\t\tcancel |= CANCEL_LIP;\r\n\t\t\t\t\trequire |= REQUIRE_LIP; \t\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase WALLPLANT:\r\n\t\t\t\t\tcancel |= CANCEL_WALLPLANT;\r\n\t\t\t\t\trequire |= REQUIRE_WALLPLANT; \t\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// walking\r\n\t\t\t\r\n\t\t\tcancel |= CANCEL_WALK;\r\n\t\t\trequire |= REQUIRE_WALK;\r\n\t\t\t\r\n\t\t\tswitch (mp_walk_component->GetState())\r\n\t\t\t{\r\n\t\t\t\tcase CWalkComponent::WALKING_AIR:\r\n\t\t\t\t\tcancel |= CANCEL_AIR;\r\n\t\t\t\t\trequire |= REQUIRE_AIR;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase CWalkComponent::WALKING_GROUND:\r\n\t\t\t\t\tcancel |= CANCEL_GROUND;\r\n\t\t\t\t\trequire |= REQUIRE_GROUND;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase CWalkComponent::WALKING_HANG:\r\n\t\t\t\t\tcancel |= CANCEL_HANG;\r\n\t\t\t\t\trequire |= REQUIRE_HANG;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase CWalkComponent::WALKING_LADDER:\r\n\t\t\t\t\tcancel |= CANCEL_LADDER;\r\n\t\t\t\t\trequire |= REQUIRE_LADDER;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// driving\r\n\t\t\r\n\t\tcancel |= CANCEL_DRIVE;\r\n\t\trequire |= REQUIRE_DRIVE;\r\n\t\t\r\n\t\t// driving gaps are a bit of a kludge right now\r\n\t\t\r\n\t\tCCompositeObject* p_vehicle = static_cast< CCompositeObject* >(CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0x824c6a24, \"PlayerVehicle\")));\r\n\t\tDbg_Assert(p_vehicle);\r\n\t\tCVehicleComponent* p_vehicle_component = GetVehicleComponentFromObject(p_vehicle);\r\n\t\tDbg_Assert(p_vehicle_component);\r\n\t\t\r\n\t\tif (p_vehicle_component->IsOnGround())\r\n\t\t{\r\n\t\t\tcancel |= CANCEL_GROUND;\r\n\t\t\trequire |= REQUIRE_GROUND;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcancel |= CANCEL_AIR;\r\n\t\t\trequire |= REQUIRE_AIR;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterGapComponent::start_gap ( Script::CStruct *pParams, Script::CScript* pScript )\r\n{\r\n\tif (mp_core_physics_component->GetFlag(IS_BAILING)) return;\r\n\t\t\t\t\t\t  \r\n\tuint32 gap_id = 0;\r\n\tpParams->GetChecksum(CRCD(0x3b442e26, \"GapID\"), &gap_id);\r\n\tif (!gap_id)\r\n\t{\r\n\t\t// no gap_id is assumed to indicate a \"Links\" gap\r\n\t\tDbg_MsgAssert(pScript->mNode != -1, (\"\\n%s\\nLink gap with no node\", pScript->GetScriptInfo()));\r\n\t\tDbg_MsgAssert(SkateScript::GetNumLinks(pScript->mNode), (\"\\n%s\\nLink gap with no links\", pScript->GetScriptInfo()));\r\n\t}\r\n\t\r\n\t#ifdef DEBUG_GAPS\r\n\tMESSAGE(\"STARTING GAP\");\r\n\tDUMPC(gap_id);\r\n\t#endif\r\n\t\r\n\t// check to see if there are any other gaps from this node with this ID and delete them\r\n\t// (note that this means you can only have one \"Links\" gap from a single node although there can be many targets)\r\n\tCGap* pGap = static_cast< CGap* >(m_gap_list.FirstItem());\r\n\twhile (pGap)\r\n\t{\r\n\t\tCGap* pNext = static_cast< CGap* >(pGap->GetNext());\r\n\r\n\t\tif (pGap->m_id == gap_id && static_cast< int >(pGap->m_node) == pScript->mNode)\r\n\t\t{\r\n\t\t\tdelete pGap;\r\n\t\t}\r\n\t\tpGap = pNext;\r\n\t}\r\n\r\n\t// create the gap and add the info to it\r\n\tpGap = new CGap;\r\n\tm_gap_list.AddToHead(pGap);\r\n\tpGap->m_id = gap_id;\r\n\tpGap->m_node = pScript->mNode;\r\n\tpGap->m_trickTextChecksum = 0;\r\n\t\r\n\t// Take a snapshot of the skater's position & orientation so that if the gap is successfully\r\n\t// got this info can be recorded into the CGapCheck instance and used to determine a good\r\n\t// camera position for viewing the gap in the view-gaps menu.\r\n\tpGap->m_skater_start_pos=((CSkater*)GetObject())->GetCamera()->GetPos();\r\n\tpGap->m_skater_start_dir=-((CSkater*)GetObject())->GetCamera()->GetMatrix()[Mth::AT];\r\n\r\n\t// if it has a trickscript, it's a gaptrick\r\n\tuint32 trickscript;\r\n\tif (pParams->GetChecksum(CRCD(0xa26994e6, \"trickscript\"), &trickscript))\r\n\t{\r\n\t\tuint32 key_combo;\r\n\t\tconst char* tricktext;\r\n\t\tScript::CArray* p_gapTricks;\r\n\t\t\r\n\t\tpGap->m_trickscript = trickscript;\r\n\t\t\r\n\t\tDbg_Assert(mp_score);\r\n\r\n\t\tif (pParams->GetChecksum(CRCD(0x95e16467,\"KeyCombo\"), &key_combo))\r\n\t\t{\r\n\t\t\tpGap->m_trickChecksum = key_combo;\r\n\r\n\t\t\tint spin;\r\n\t\t\tif ( pParams->GetInteger(CRCD(0xedf5db70, \"spin\"), &spin))\r\n\t\t\t{\r\n\t\t\t\tpGap->m_requirePerfect = pParams->ContainsFlag(CRCD(0x1c39f1b9, \"perfect\"));\r\n\t\t\t\tDbg_MsgAssert(spin % 180 == 0, (\"StartGap called with a spin value of %i which is not a multiple of 180\", spin));\r\n\t\t\t\tpGap->m_spinMult = spin / 180;\r\n\t\t\t}\r\n\t\t\tpParams->GetInteger( CRCD(0xa4bee6a1,\"num_taps\"), &pGap->m_numTaps, Script::NO_ASSERT );\r\n\r\n\t\t\tpGap->m_numTrickOccurrences = mp_score->GetPreviousNumberOfOccurrences( key_combo, pGap->m_spinMult, pGap->m_numTaps );\r\n\t\t}\r\n\t\telse if (pParams->GetString(CRCD(0x3eafa520, \"TrickText\"), &tricktext))\r\n\t\t{\r\n\t\t\tpGap->m_trickTextChecksum = Script::GenerateCRC(tricktext);\r\n\r\n\t\t\tint spin;\r\n\t\t\tif (pParams->GetInteger(CRCD(0xedf5db70, \"spin\"), &spin))\r\n\t\t\t{\r\n\t\t\t\tpGap->m_requirePerfect = pParams->ContainsFlag(CRCD(0x1c39f1b9, \"perfect\"));\r\n\t\t\t\tDbg_MsgAssert(spin % 180 == 0, (\"StartGap called with a spin value of %i which is not a multiple of 180\", spin));\r\n\t\t\t\tpGap->m_spinMult = spin / 180;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tpParams->GetInteger( CRCD(0xa4bee6a1,\"num_taps\"), &pGap->m_numTaps, Script::NO_ASSERT );\r\n\r\n\t\t\tpGap->m_numTrickOccurrences = mp_score->GetPreviousNumberOfOccurrencesByName( pGap->m_trickTextChecksum, pGap->m_spinMult, pGap->m_numTaps );\r\n\t\t}\r\n\t\telse if (pParams->GetArray(CRCD(0x1e26fd3e, \"tricks\"), &p_gapTricks))\r\n\t\t{\r\n\t\t\tScript::CopyArray(pGap->mp_tricks, p_gapTricks);\r\n\t\t\tpGap->m_startGapTrickCount = mp_score->GetCurrentTrickCount();\r\n\t\t}\r\n\t\t\r\n\t\t// create the gap trick object\r\n\t\tstart_gap_trick(pParams, pScript);\r\n\t}\r\n\r\n\t\r\n\tpGap->m_flags = 0;\r\n\tScript::CArray* pArray = NULL;\t\t\t\r\n\tpParams->GetArray(CRCD(0xf4fabe45, \"flags\"), &pArray);\r\n\tif (pArray)\r\n\t{\r\n\t\tfor (uint32 i = 0; i < pArray->GetSize(); i++)\r\n\t\t{\r\n\t\t\tint checksum = pArray->GetChecksum(i);\r\n\t\t\tpGap->m_flags |= Script::GetInteger(checksum);\t\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tuint32 checksum;\r\n\t\tif (pParams->GetChecksum(CRCD(0xf4fabe45, \"flags\"), &checksum, false))\r\n\t\t{\r\n\t\t\tpGap->m_flags |= Script::GetInteger(checksum);\r\n\t\t}\r\n\t}\r\n\r\n\t// K: Added this as part of implementing ability to set cancel type for gaps in the Park Editor. (TT1969)\r\n\t// When the park editor runs the StartGap command, it generates the passed parameters in the C-code.\r\n\t// At that point, the PE already has the or'd together cancel flags. It would be tricky to try to construct\r\n\t// the array of flag checksums at that point, since it would have to do lots of compares with script globals\r\n\t// and if any new ones were added we'd have to remember to update that bit of code.\r\n\t// Easier to just support passing of the combined flags here.\r\n\tuint32 combined_flags=0;\r\n\tif (pParams->GetChecksum(CRCD(0x2760de9e,\"combined_flags\"),&combined_flags))\r\n\t{\r\n\t\tpGap->m_flags |= combined_flags;\r\n\t}\r\n\t\r\n\tuint32 car_cancel_flags=CANCEL_SKATE | CANCEL_WALK;\r\n\t\r\n\tif (pParams->ContainsFlag(CRCD(0xc442e33d, \"carGap\")))\r\n\t{\r\n\t\t// car gaps cancel when skating or walking\r\n\t\tpGap->m_flags |= car_cancel_flags;\r\n\t}\r\n\telse if (pParams->ContainsFlag(CRCD(0xe3ed4ade, \"complexGap\")))\r\n\t{\r\n\t\t// complex gaps must be setup completely by their designer\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// default to gaps which cancel driving\r\n\t\tif (pGap->m_flags & car_cancel_flags)\r\n\t\t{\r\n\t\t\t// Unless we decided we did want to drive earlier\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpGap->m_flags |= CANCEL_DRIVE;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\t// Because the car can trigger multiple trigger scripts in the same frame, we must allow the gap to be canceled immediately.  Otherwise, if one wheel\r\n\t// triggers a start gap and another an end gap in the same frame, the cancel flags of the gap will never be checked.\r\n\tif (mp_physics_control_component->IsDriving() && (pGap->m_flags & CANCEL_DRIVE)\r\n\t\t// Created park gaps can be so close together that we might not have a frame with which to check our cancel flags\r\n\t\t|| Ed::CParkEditor::Instance()->UsingCustomPark())\r\n\t{\r\n\t\tint cancel, require;\r\n\t\tget_state_flags(cancel, require);\r\n\t\tUpdateCancelRequire(cancel, require);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterGapComponent::start_gap_trick ( Script::CStruct *pParams, Script::CScript* pScript )\r\n{\r\n\t// create the gap trick and add the info to it\r\n\tCGapTrick* pGapTrick = new CGapTrick;\r\n\tm_gaptrick_list.AddToHead(pGapTrick);\r\n\tpGapTrick->m_node = pScript->mNode;\r\n\tpGapTrick->m_got = false;\r\n\tpGapTrick->m_frame = m_frame_count;\r\n\r\n\tuint32 gap_id = 0;\r\n\tpParams->GetChecksum(CRCD(0x3b442e26, \"GapId\"), &gap_id);\r\n\tpGapTrick->m_id = gap_id;\r\n\r\n\tconst char *p_trickString = NULL;\r\n\tpParams->GetString(CRCD(0x3eafa520, \"TrickText\"), &p_trickString);\r\n\tpGapTrick->m_trickString = p_trickString;\r\n\t\r\n\tpGapTrick->m_script = 0;\r\n\tpParams->GetChecksum(CRCD(0xa26994e6, \"trickscript\"), &pGapTrick->m_script, Script::ASSERT);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterGapComponent::end_gap ( Script::CStruct *pParams, Script::CScript* pScript )\r\n{\r\n\tif (mp_core_physics_component->GetFlag(IS_BAILING)) return;\r\n\t\r\n\tuint32 gap_id = 0;\r\n\tpParams->GetChecksum(CRCD(0x3b442e26, \"GapID\"), &gap_id);\r\n\t\r\n\t#ifdef DEBUG_GAPS\r\n\tMESSAGE(\"ENDING GAP\");\r\n\tDUMPC(gap_id);\r\n\t#endif\r\n\t\r\n\tDbg_Assert(mp_score);\r\n\r\n\t// find the ending gap in our gap list\r\n\tCGap* pNext;\r\n\tfor (CGap* pGap = static_cast< CGap* >(m_gap_list.FirstItem()); pGap; pGap = pNext)\r\n\t{\r\n\t\tpNext = static_cast< CGap* >(pGap->GetNext());\r\n\t\t\r\n\t\tif (pGap->m_id != gap_id) continue;\r\n\t\t\r\n\t\t// check if its got a gap_id, or if the gaps node is linked to this node\t\t\t\t\t\r\n\t\tif (gap_id == 0 && !SkateScript::IsLinkedTo(pGap->m_node, pScript->mNode)) continue;\r\n\t\t\t\t\r\n\t\t// found the gap\r\n\t\t\r\n\t\t// check requirements\r\n\t\tif (pGap->m_flags & REQUIRE_MASK)\r\n\t\t{\t\t\t\t\t\t\t \r\n\t\t\t// requirements failed, so just delete the gap\r\n\t\t\tdelete pGap;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\t// requirements met\r\n\r\n\t\t// Get the gap name, this is what is displayed as the trick name for this gap.\r\n\t\t// This is not required, and will default if not there.\r\n\t\tconst char *p_name;\r\n\t\tif (!pParams->GetString(CRCD(0xc4745838, \"text\"), &p_name))\r\n\t\t{\r\n\t\t\tp_name = \"Unnamed Gap\";\r\n\t\t}\r\n\t\tchar gap_name[256];\r\n\t\tsprintf(gap_name, \"\\\\c1%s\\\\c0\", p_name);\r\n\r\n\r\n\t\t// check for gap trick; this MUST occur before the gap is added to the trick string\r\n\t\tif (pGap->m_trickscript != 0)\r\n\t\t{\r\n\t\t\tbool gotGapTrick = false;\r\n\t\t\t\r\n\t\t\tif (pGap->m_trickChecksum != 0 || pGap->m_trickTextChecksum != 0 || pGap->mp_tricks->GetSize() > 0)\r\n\t\t\t{\r\n\t\t\t\t// see if the trick has been done since the gap started\r\n\t\t\t\tif ( pGap->m_trickChecksum && pGap->m_numTrickOccurrences < mp_score->GetCurrentNumberOfOccurrences( pGap->m_trickChecksum, pGap->m_spinMult, pGap->m_requirePerfect, pGap->m_numTaps ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tgotGapTrick = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( pGap->m_trickTextChecksum && pGap->m_numTrickOccurrences < mp_score->GetCurrentNumberOfOccurrencesByName( pGap->m_trickTextChecksum, pGap->m_spinMult, pGap->m_requirePerfect, pGap->m_numTaps ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tgotGapTrick = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( pGap->mp_tricks->GetSize() > 0 && mp_score->GetCurrentNumberOfOccurrences( pGap->mp_tricks, pGap->m_startGapTrickCount ) > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tgotGapTrick = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// if they get the gap trick\r\n\t\t\t\tif ( gotGapTrick )\r\n\t\t\t\t{\r\n\t\t\t\t\t// get the gap trick\r\n\t\t\t\t\tCGapTrick* pGapTrick = static_cast< CGapTrick* >(m_gaptrick_list.FirstItem());\r\n\t\t\t\t\twhile ( pGapTrick )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tCGapTrick* pNext = static_cast< CGapTrick* >(pGapTrick->GetNext());\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif (pGapTrick->m_id == pGap->m_id)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tpGapTrick->GetGapTrick();\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tpGapTrick = pNext;\r\n\t\t\t\t\t}\r\n\t\t\t\t} // END if they get the gap trick\r\n\t\t\t}\r\n\t\t\telse \r\n\t\t\t{\r\n\t\t\t\t// if no trick script, look for a no requirement gap trick\r\n\t\t\t\tCGapTrick* pGapTrick = static_cast< CGapTrick* >(m_gaptrick_list.FirstItem());\r\n\t\t\t\twhile (pGapTrick)\r\n\t\t\t\t{\r\n\t\t\t\t\tCGapTrick* pNext = static_cast< CGapTrick* >(pGapTrick->GetNext());\r\n\r\n\t\t\t\t\tif (pGapTrick->m_id == pGap->m_id)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpGapTrick->GetGapTrick();\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tpGapTrick = pNext;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} // END if trickscript != 0\r\n\r\n\r\n\t\tMdl::Skate::Instance()->GetGapChecklist()->SetInfoForCamera(p_name,pGap->m_skater_start_pos,pGap->m_skater_start_dir);\r\n\t\t\r\n\t\t// Get the score for this gap.\r\n\t\t// If there is no score defined, then we don't award a trick.\r\n\t\tint score = 0;\r\n\t\tif (pParams->GetInteger(CRCD(0xcd66c8ae, \"score\"), &score))\r\n\t\t{\r\n\t\t\tMdl::Score::Flags flags = Mdl::Score::vGAP;\r\n\t\t\tif (GetSkater()->IsLocalClient())\r\n\t\t\t{\r\n\t\t\t\tmp_score->Trigger(gap_name, score, flags);\r\n\t\t\t\t\r\n\t\t\t\tCTrickComponent* p_trick_component = GetTrickComponentFromObject(GetObject());\r\n\t\t\t\tDbg_Assert(p_trick_component);\r\n\t\t\t\tp_trick_component->SetFirstTrickStarted(true);\r\n\r\n\t\t\t\tMdl::Skate::Instance()->GetGapChecklist()->GetGapByText(p_name);  \r\n\t\t\t\t  \r\n\t\t\t\tGetObject()->SpawnAndRunScript(CRCD(0x541a2485, \"DefaultGapScript\"));\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t//  execute the gap_script\r\n\t\tuint32 gap_script;\r\n\t\tif (pParams->GetChecksum(CRCD(0x7c9e51ab, \"gapscript\"), &gap_script))\r\n\t\t{\r\n\t\t\tGetObject()->SpawnAndRunScript(\r\n\t\t\t\tgap_script,\r\n\t\t\t\tpScript->mNode,\r\n\t\t\t\tpParams->ContainsFlag(CRCD(0x20209c31, \"NetEnabled\")),\r\n\t\t\t\tpParams->ContainsFlag(CRCD(0x23627fd7, \"Permanent\"))\r\n\t\t\t);\r\n\t\t}\t  \t\t\t  \r\n\t\t\r\n\t\t// handle for continue script parameter\r\n\t\tScript::CStruct * p_continue = NULL;\r\n\t\tif (pParams->GetStructure(CRCD(0xec1cd520, \"continue\"), &p_continue))\r\n\t\t{\r\n\t\t\tstart_gap(p_continue, pScript);\r\n\t\t}\t\t\t\t\t\t\t\t\t\t  \r\n\r\n\t\t// Broadcast an event saying we got the gap\r\n\t\t// won't happen very often, and broadcasing is cheap)\r\n\t\t// we also pass in the parameters, just in case we want to do \r\n\t\tuint32\tid_got = Crc::ExtendCRCWithString(gap_id,\"_Success\");\r\n\t\tObj::CTracker::Instance()->LaunchEvent( id_got, 0xffffffff, GetObject()->GetID(), pParams, true /*, radius */  );\r\n\t\t\t\t\t\t\r\n\t\t// Script functions we might have called could have deleted this gap and maybe the next gap.\r\n\t\t// The safest things is to check to see if this one is still there, delete it, then reset back to the start of the list.\r\n\t\tCGap* pKill = static_cast< CGap* >(m_gap_list.FirstItem());\r\n\t\twhile (pKill)\r\n\t\t{\r\n\t\t\tif (pKill == pGap)\r\n\t\t\t{\r\n\t\t\t\tdelete pGap;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tpKill = static_cast< CGap* >(pKill->GetNext());\r\n\t\t}\r\n\t\t\r\n\t\t// restart our pass through the gaps\r\n\t\tpNext = static_cast< CGap* >(m_gap_list.FirstItem());\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterGapComponent::check_gap_tricks ( Script::CStruct *pParams )\r\n{\r\n\t// look for completed gaps and run their scripts\r\n\tCGapTrick* pGapTrick = static_cast< CGapTrick* >(m_gaptrick_list.FirstItem());\r\n\twhile (pGapTrick)\r\n\t{\r\n\t\tCGapTrick* pNext = static_cast< CGapTrick* >(pGapTrick->GetNext());\r\n\t\tif (pGapTrick->m_got)\r\n\t\t{\r\n\t\t\tGetObject()->SpawnAndRunScript(pGapTrick->m_script, pGapTrick->m_node);\r\n\t\t}\r\n\t\tpGapTrick = pNext;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterGapComponent::clear_gap_tricks ( Script::CStruct *pParams )\r\n{\r\n\tif (pParams->ContainsFlag(CRCD(0x97975226, \"NotInSameFrame\")))\r\n\t{\r\n\t\t// delete all gap tricks leaving those created this frame\r\n\t\tCGapTrick* pGapTrick = static_cast< CGapTrick* >(m_gaptrick_list.FirstItem());\r\n\t\twhile (pGapTrick)\r\n\t\t{\r\n\t\t\tCGapTrick* pNext = static_cast< CGapTrick* >(pGapTrick->GetNext());\r\n\t\t\tif (pGapTrick->m_frame != m_frame_count)\r\n\t\t\t{\r\n\t\t\t\tdelete pGapTrick;\r\n\t\t\t}\r\n\t\t\tpGapTrick = pNext;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// delete all gap tricks\r\n\t\tCGapTrick* pGapTrick = static_cast< CGapTrick* >(m_gaptrick_list.FirstItem());\r\n\t\twhile (pGapTrick)\r\n\t\t{\r\n\t\t\tCGapTrick* pNext = static_cast< CGapTrick* >(pGapTrick->GetNext());\r\n\t\t\tdelete pGapTrick;\r\n\t\t\tpGapTrick = pNext;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterGapComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterGapComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/5/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERGAPCOMPONENT_H__\r\n#define __COMPONENTS_SKATERGAPCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#define\t\tCRC_SKATERGAP CRCD(0x11b4c67f, \"SkaterGap\")\r\n\r\n#define\t\tGetSkaterGapComponent() ((Obj::CSkaterGapComponent*)GetComponent(CRC_SKATERGAP))\r\n#define\t\tGetSkaterGapComponentFromObject(pObj) ((Obj::CSkaterGapComponent*)(pObj)->GetComponent(CRC_SKATERGAP))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n\r\nnamespace Mdl\r\n{\r\n\tclass Score;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CGap;\r\n\tclass CGapTrick;\r\n\tclass CSkaterCorePhysicsComponent;\r\n\tclass CSkaterBalanceTrickComponent;\r\n\tclass CSkaterPhysicsControlComponent;\r\n\tclass CWalkComponent;\r\n\r\nclass CSkaterGapComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkaterGapComponent();\r\n    virtual ~CSkaterGapComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tvoid \t\t\t\t\t\t\tUpdateCancelRequire(int cancel, int require);\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetAssociatedScore ( Mdl::Score* p_score ) { mp_score = p_score; }\r\n\tvoid\t\t\t\t\t\t\tClearActiveGaps (   );\r\n\tvoid\t\t\t\t\t\t\tClearPendingGaps (   );\r\n\tvoid\t\t\t\t\t\t\tAwardPendingGaps (   );\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\tget_state_flags ( int& cancel, int& require );\r\n\tvoid\t\t\t\t\t\t\tstart_gap ( Script::CStruct *pParams, Script::CScript* pScript );\r\n\tvoid\t\t\t\t\t\t\tstart_gap_trick ( Script::CStruct *pParams, Script::CScript* pScript );\r\n\tvoid\t\t\t\t\t\t\tend_gap ( Script::CStruct *pParams, Script::CScript* pScript );\r\n\tvoid\t\t\t\t\t\t\tcheck_gap_tricks ( Script::CStruct *pParams );\r\n\tvoid\t\t\t\t\t\t\tclear_gap_tricks ( Script::CStruct *pParams );\r\n\t\r\nprivate:\r\n\t// list of active gaps\r\n\tLst::Head< CGap >\t\t\t\tm_gap_list;\r\n\t\r\n\t// list of active gapTricks\r\n\tLst::Head< CGapTrick >\t\t\tm_gaptrick_list;\r\n\t\r\n\t// count frames to allow timestamping of gap tricks\r\n\tuint32\t\t\t\t\t\t\tm_frame_count;\r\n\t\r\n\t// associated score object\r\n\tMdl::Score*\t\t\t\t\t\tmp_score;\r\n\t\r\n\t// peer components\r\n\tCSkaterCorePhysicsComponent*\tmp_core_physics_component;\r\n\tCSkaterBalanceTrickComponent*\tmp_balance_trick_component;\r\n\tCSkaterPhysicsControlComponent*\tmp_physics_control_component;\r\n\tCWalkComponent*\t\t\t\t\tmp_walk_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterLocalNetLogicComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterLocalNetLogicComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/12/3\r\n//****************************************************************************\r\n\r\n#include <core/math/slerp.h>\r\n\r\n#include <sk/components/skaterlocalnetlogiccomponent.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n#include <sk/components/skaterendruncomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/net/client/netclnt.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSkaterLocalNetLogicComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterLocalNetLogicComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterLocalNetLogicComponent::CSkaterLocalNetLogicComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERLOCALNETLOGIC );\r\n\t\r\n\tmp_state_component = NULL;\r\n\tmp_physics_component = NULL;\r\n\tm_last_update_time = 0;\r\n\tm_last_sent_terrain = -1;\r\n\tm_last_sent_flags = 0;\r\n\tm_last_sent_state = 0;\r\n\tm_last_sent_doing_trick = -1;\r\n\tm_last_sent_rail = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterLocalNetLogicComponent::~CSkaterLocalNetLogicComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLocalNetLogicComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tDbg_MsgAssert(GetObject()->GetType() == SKATE_TYPE_SKATER, (\"CSkaterLocalNetLogicComponent added to non-skater composite object\"));\r\n\tDbg_MsgAssert(GetSkater()->IsLocalClient(), (\"CSkaterLocalNetLogicComponent added to non-local skater\"));\r\n\t\r\n\tm_last_update_time = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLocalNetLogicComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLocalNetLogicComponent::Finalize (   )\r\n{\r\n\t\r\n\tmp_state_component = GetSkaterStateComponentFromObject(GetObject());\r\n\tmp_physics_component = GetSkaterCorePhysicsComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_state_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLocalNetLogicComponent::Update()\r\n{\r\n\tif (!Mdl::Skate::Instance()->IsMultiplayerGame())\r\n\t{\r\n\t\t//Suspend(true);\r\n\t\treturn;\r\n\t}\r\n\tif( GameNet::Manager::Instance()->GetLocalPlayer() == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tnetwork_update();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterLocalNetLogicComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLocalNetLogicComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterLocalNetLogicComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n\r\n/******************************************************************/\r\n/* Print a graffiti steal message  \t\t\t\t\t\t\t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tCSkaterLocalNetLogicComponent::sHandleStealMessage( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::MsgStealMessage* p_msg = (GameNet::MsgStealMessage *) context->m_Msg;\r\n\t\r\n\tif (p_msg->m_GameId != GameNet::Manager::Instance()->GetNetworkGameId()) return Net::HANDLER_MSG_DONE;\r\n\r\n\tObj::CSkater* pCurrSkater = (CSkater*) context->m_Data;\r\n\tDbg_Assert( pCurrSkater );\r\n\r\n\t// For now, just exit out in these cases to avoid a crash\r\n\tObj::CSkater* pNewSkater = Mdl::Skate::Instance()->GetSkaterById( p_msg->m_NewOwner );\r\n\tif( pNewSkater == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_CONTINUE;\r\n\t}\r\n\r\n\tObj::CSkater* pOldSkater = Mdl::Skate::Instance()->GetSkaterById( p_msg->m_OldOwner );\r\n\tif( pOldSkater == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_CONTINUE;\r\n\t}\r\n\r\n\t// TODO:  Maybe send the color of this skater's graffiti tags\r\n\t\r\n\tif ( pCurrSkater->GetID() == (uint32)p_msg->m_NewOwner )\r\n\t{\r\n\t\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\t\tpTempStructure->Clear();\r\n\t\tpTempStructure->AddComponent( CRCD(0xa4b08520, \"String0\"), ESYMBOLTYPE_STRING, pOldSkater->GetDisplayName() );\r\n\t\tScript::RunScript( CRCD(0xb3ff911, \"GraffitiStealYou\"), pTempStructure, pCurrSkater );\r\n\t\tdelete pTempStructure;\r\n\t}\r\n\telse if ( pCurrSkater->GetID() == (uint32)p_msg->m_OldOwner )\r\n\t{\r\n\t\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\t\tpTempStructure->Clear();\r\n\t\tpTempStructure->AddComponent( CRCD(0xa4b08520, \"String0\"), ESYMBOLTYPE_STRING, pNewSkater->GetDisplayName() );\r\n\t\tScript::RunScript( CRCD(0x4d7f6ffa, \"GraffitiStealOther\"), pTempStructure, pCurrSkater );\r\n\t\tdelete pTempStructure;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// useless steal message encountered\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tCSkaterLocalNetLogicComponent::get_update_flags()\r\n{\r\n\tNet::Client* client;\r\n\tMth::Vector eulers;\r\n\tshort pos[3];\r\n\tshort rot[3];\r\n\tchar doing_trick, state, terrain, walking, driving;\r\n\tFlags< int > skater_flags;\r\n\tFlags< int > end_run_flags;\r\n\tint i;\r\n\tbool on_server, force_send;   \r\n\tint update_flags;\r\n\tsint16 rail_node;\r\n\tObj::CSkaterEndRunComponent* p_skater_endrun_component;\r\n\r\n\tupdate_flags = 0;\r\n\r\n\tclient = GameNet::Manager::Instance()->GetClient( GetSkater()->m_skater_number );\r\n\tDbg_Assert( client );\r\n\r\n\tp_skater_endrun_component = GetSkaterEndRunComponentFromObject(GetSkater());\r\n\r\n\ton_server = GameNet::Manager::Instance()->OnServer();\r\n\tforce_send = on_server || ( !( client->m_FrameCounter % vFORCE_SEND_INTERVAL )); \r\n\r\n\tGetObject()->GetDisplayMatrix().GetEulers( eulers );\r\n\t\r\n\tstate = (char) mp_state_component->m_state;\r\n\tterrain = (char) mp_state_component->m_terrain;\r\n\tdoing_trick = (char) mp_state_component->m_doing_trick;\r\n\twalking = (char) (mp_state_component->m_physics_state == WALKING ? true : false);\r\n\tdriving = (char) mp_state_component->m_driving;\r\n\trail_node = mp_physics_component->GetRailNode();\r\n\r\n\tfor( i = 0; i < NUM_ESKATERFLAGS; i++ )\r\n\t{     \t\t\r\n\t\tskater_flags.Set( i, mp_state_component->m_skater_flags[( ESkaterFlag ) i ].Get() );\r\n\t}\r\n\tend_run_flags = p_skater_endrun_component->GetFlags();\r\n\r\n\tfor( i = 0; i < 3; i++ )\r\n\t{\r\n\t\tif( i == Y )\r\n\t\t{\r\n\t\t\tpos[i] = (short) ( GetObject()->m_pos[i] * 4.0f );\r\n\t\t\t//pos[i] = GetObject()->m_pos[i];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpos[i] = (short) ( GetObject()->m_pos[i] * 2.0f );\r\n\t\t\t//pos[i] = GetObject()->m_pos[i];\r\n\t\t}\r\n\t\tif(( pos[i] != m_last_sent_pos[i] ) || force_send )\r\n\t\t{\r\n\t\t\tif( i == X )\r\n\t\t\t{\r\n\t\t\t\tupdate_flags |= GameNet::mUPDATE_FIELD_POS_X;\r\n\t\t\t}\r\n\t\t\telse if( i == Y )\r\n\t\t\t{\r\n\t\t\t\tupdate_flags |= GameNet::mUPDATE_FIELD_POS_Y;\r\n\t\t\t}\r\n\t\t\telse if( i == Z )\r\n\t\t\t{\r\n\t\t\t\tupdate_flags |= GameNet::mUPDATE_FIELD_POS_Z;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n    \r\n\tfor( i = 0; i < 3; i++ )\r\n\t{\r\n\t\trot[i] = (short) ( eulers[i] * 4096.0f );\r\n\t\tif(( rot[i] != m_last_sent_rot[i] ) || force_send )\r\n\t\t{   \r\n\t\t\tm_last_sent_rot[i] = rot[i];\r\n\t\t\tif( i == X )\r\n\t\t\t{\r\n\t\t\t\tupdate_flags |= GameNet::mUPDATE_FIELD_ROT_X;\r\n\t\t\t}\r\n\t\t\telse if( i == Y )\r\n\t\t\t{\r\n\t\t\t\tupdate_flags |= GameNet::mUPDATE_FIELD_ROT_Y;\r\n\t\t\t}\r\n\t\t\telse if( i == Z )\r\n\t\t\t{\r\n\t\t\t\tupdate_flags |= GameNet::mUPDATE_FIELD_ROT_Z;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n    \r\n\tif( ( state != m_last_sent_state ) ||\r\n\t\t( doing_trick != m_last_sent_doing_trick ) ||\r\n\t\t( terrain != m_last_sent_terrain ) ||\r\n\t\t( walking != m_last_sent_walking ) ||\r\n\t\t( driving != m_last_sent_driving ) ||\r\n\t\t( force_send ))\r\n\t{\r\n\t\t\tupdate_flags |= GameNet::mUPDATE_FIELD_STATE;\r\n\t}\r\n\r\n    if(( skater_flags != m_last_sent_flags ) || \r\n\t   ( end_run_flags != m_last_sent_end_run_flags ) || \r\n\t   ( force_send ))\r\n\t{\r\n\t\tupdate_flags |= GameNet::mUPDATE_FIELD_FLAGS;\r\n\t}\r\n\r\n\tif( rail_node != m_last_sent_rail )\r\n\t{\r\n\t\tupdate_flags |= GameNet::mUPDATE_FIELD_RAIL_NODE;\r\n\t}\r\n\r\n\treturn update_flags;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLocalNetLogicComponent::network_update ( void )\r\n{\r\n\t// update the server with our current state so that he can relay the data to other clients\r\n\t\r\n\tNet::Client* client;\r\n\tNet::MsgMax p_msg;\r\n\tMth::Vector eulers;\r\n\tshort pos[3];\r\n\tshort rot[3];\r\n\tchar doing_trick, state, terrain, walking, driving;\r\n\tFlags< int > skater_flags;\r\n\tFlags< int > end_run_flags;\r\n\tint i, msg_len;\r\n\tsint16 rail_node;\r\n\tint update_flags;\r\n\tbool on_server, force_send;   \r\n\tNet::MsgDesc msg_desc;\r\n\tNet::BitStream stream;\r\n\tObj::CSkaterEndRunComponent* p_skater_endrun_component;\r\n\r\n\tclient = GameNet::Manager::Instance()->GetClient( GetSkater()->m_skater_number );\r\n\tDbg_MsgAssert( client, ( \"Could not find client: %d\\n\", GetSkater()->m_skater_number ));\r\n\r\n\tp_skater_endrun_component = GetSkaterEndRunComponentFromObject(GetSkater());\r\n\r\n\ton_server = GameNet::Manager::Instance()->OnServer();\r\n\tforce_send = on_server || ( !( client->m_FrameCounter % vFORCE_SEND_INTERVAL )); \r\n\r\n\t// Send object updates to narrowband servers only every other frame (except for forced-send frames)\r\n\tif( !on_server && !force_send )\r\n\t{\r\n\t\tLst::Search< Net::Conn > sh;\r\n\t\tNet::Conn* server_conn;\r\n\t\t\r\n\t\tserver_conn = client->FirstConnection( &sh );\r\n\t\tDbg_Assert( server_conn );\r\n\r\n\t\t// Only send object updates as often as we send packets\r\n\t\tif(( client->m_Timestamp - m_last_update_time ) < (unsigned int) server_conn->GetSendInterval())\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tm_last_update_time = client->m_Timestamp;\r\n\r\n\tstream.SetOutputData( p_msg.m_Data, 1024 );\r\n\t\r\n\tGetObject()->GetDisplayMatrix().GetEulers( eulers );\r\n\t\r\n\tstate = (char) mp_state_component->m_state;\r\n\tterrain = (char) mp_state_component->m_terrain;\r\n\tdoing_trick = (char) mp_state_component->m_doing_trick;\r\n\twalking = (char) (mp_state_component->m_physics_state == WALKING ? true : false);\r\n\tdriving = (char) mp_state_component->m_driving;\r\n\trail_node = mp_physics_component->GetRailNode();\r\n\r\n\tfor( i = 0; i < NUM_ESKATERFLAGS; i++ )\r\n\t{     \t\t\r\n\t\tskater_flags.Set( i, mp_state_component->m_skater_flags[( ESkaterFlag ) i ].Get() );\r\n\t}\r\n\t\r\n\tend_run_flags = p_skater_endrun_component->GetFlags();\r\n\r\n\t// Write out the time for which this state info is valid\r\n\tstream.WriteValue( client->m_Timestamp, sizeof( int ) * 8 );\r\n\tupdate_flags = get_update_flags();\r\n\tstream.WriteValue( update_flags, 9 );\r\n\r\n\tif( on_server )\r\n\t{\r\n\t\tstatic Mth::Vector last_pos;\r\n\t\tMth::Vector diff;\r\n\r\n\t\tdiff = GetObject()->m_pos - last_pos;\r\n\t\t//Dbg_Printf( \"Vel: %f %f %f\\n\", diff[X], diff[Y], diff[Z] );\r\n\t\tlast_pos = GetObject()->m_pos;\r\n\t}\r\n\r\n// Write out the object's position as three shorts (fixed-point)\r\n\tfor( i = 0; i < 3; i++ )\r\n\t{\r\n\t\tif( i == Y )\r\n\t\t{\r\n\t\t\tpos[i] = (short) ( GetObject()->m_pos[i] * 4.0f );\r\n\t\t\t//pos[i] = GetObject()->m_pos[i];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpos[i] = (short) ( GetObject()->m_pos[i] * 2.0f );\r\n\t\t\t//pos[i] = GetObject()->m_pos[i];\r\n\t\t}\r\n\t\tif( i == X )\r\n\t\t{\r\n\t\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_X )\r\n\t\t\t{\r\n\t\t\t\tstream.WriteValue( pos[i], sizeof( short ) * 8 );\r\n\t\t\t\t//stream.WriteFloatValue( pos[i] );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( i == Y )\r\n\t\t{\r\n\t\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_Y )\r\n\t\t\t{\r\n\t\t\t\tstream.WriteValue( pos[i], sizeof( short ) * 8 );\r\n\t\t\t\t//stream.WriteFloatValue( pos[i] );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( i == Z )\r\n\t\t{\r\n\t\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_Z )\r\n\t\t\t{\r\n\t\t\t\tstream.WriteValue( pos[i], sizeof( short ) * 8 );\r\n\t\t\t\t//stream.WriteFloatValue( pos[i] );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tm_last_sent_pos[i] = pos[i];\r\n\t}\r\n    \r\n\t// Write out the object's orientation as three short euler angles (fixed-point)\r\n\tfor( i = 0; i < 3; i++ )\r\n\t{\r\n\t\trot[i] = (short) ( eulers[i] * 4096.0f );\r\n\t\tif( i == X )\r\n\t\t{\r\n\t\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_X )\r\n\t\t\t{\r\n\t\t\t\tstream.WriteValue( rot[i], sizeof( short ) * 8 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( i == Y )\r\n\t\t{\r\n\t\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_Y )\r\n\t\t\t{\r\n\t\t\t\tstream.WriteValue( rot[i], sizeof( short ) * 8 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( i == Z )\r\n\t\t{\r\n\t\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_Z )\r\n\t\t\t{\r\n\t\t\t\tstream.WriteValue( rot[i], sizeof( short ) * 8 );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tm_last_sent_rot[i] = rot[i];\r\n\t}\r\n    \r\n\t// Write out the skater's 'state'\r\n\t// Write out the skater's 'doing trick' state\r\n\t// Write out the skater's terrain\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_STATE )\r\n\t{\r\n\t\tchar mask;\r\n\r\n\t\tm_last_sent_state = state;\r\n\t\tm_last_sent_doing_trick = doing_trick;\r\n\t\tm_last_sent_terrain = terrain;\r\n\t\tm_last_sent_walking = walking;\r\n\t\tm_last_sent_driving = driving;\r\n\r\n\t\tmask = state;\r\n\t\tif( doing_trick )\r\n\t\t{\r\n\t\t\tmask |= GameNet::mDOING_TRICK_MASK;\r\n\t\t}\r\n\t\t\r\n\t\tstream.WriteValue( mask, 4 );\r\n\t\tstream.WriteValue( terrain, 6 );\r\n\t\tstream.WriteValue( walking, 1 );\r\n\t\tstream.WriteValue( driving, 1 );\r\n\t}\r\n\r\n    // Write out the skaters' flags\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_FLAGS )\r\n\t{\r\n\t\tm_last_sent_flags = skater_flags;\r\n\t\tm_last_sent_end_run_flags = end_run_flags;\r\n\t\tstream.WriteValue( skater_flags, 5 );\r\n\t\tstream.WriteValue( end_run_flags, 3 );\r\n\t}\r\n\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_RAIL_NODE )\r\n\t{\r\n\t\tm_last_sent_rail = rail_node;\r\n\t\tstream.WriteValue( rail_node, sizeof( sint16 ) * 8 );\r\n\t}\r\n\r\n\tstream.Flush();\r\n\tmsg_len = stream.GetByteLength();\r\n\r\n\tmsg_desc.m_Id = GameNet::MSG_ID_OBJ_UPDATE_STREAM;\r\n\tmsg_desc.m_Length = msg_len;\r\n\tmsg_desc.m_Data = &p_msg;\r\n\tmsg_desc.m_Singular = true;\r\n\tmsg_desc.m_Priority = Net::NORMAL_PRIORITY + 1;\r\n\tclient->EnqueueMessageToServer( &msg_desc );\r\n}\r\n                                           \r\n}"
  },
  {
    "path": "Code/Sk/Components/SkaterLocalNetLogicComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterLocalNetLogicComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/12/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERLOCALNETLOGICCOMPONENT_H__\r\n#define __COMPONENTS_SKATERLOCALNETLOGICCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#define\t\tCRC_SKATERLOCALNETLOGIC CRCD(0x7cd3e6d5, \"SkaterLocalNetLogic\")\r\n\r\n#define\t\tGetSkaterLocalNetLogicComponent() ((Obj::CSkaterLocalNetLogicComponent*)GetComponent(CRC_SKATERLOCALNETLOGIC))\r\n#define\t\tGetSkaterLocalNetLogicComponentFromObject(pObj) ((Obj::CSkaterLocalNetLogicComponent*)(pObj)->GetComponent(CRC_SKATERLOCALNETLOGIC))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CSkaterCorePhysicsComponent;\r\n\tclass CSkaterStateComponent;\r\n\r\nclass CSkaterLocalNetLogicComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkaterLocalNetLogicComponent();\r\n    virtual ~CSkaterLocalNetLogicComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\t\r\n\tstatic int\t\t\t\t\t\tsHandleStealMessage( Net::MsgHandlerContext* context );\r\n\t\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\tnetwork_update();\r\n\tint\t\t\t\t\t\t\t\tget_update_flags();\r\n\t\r\n\tTmr::Time\t\t\t\t\t\tm_last_update_time;\r\n\t\r\n\tchar\t\t\t\t\t\t\tm_last_sent_terrain;\r\n\tshort\t\t\t\t\t\t\tm_last_sent_pos[3];\r\n\tshort\t\t\t\t\t\t\tm_last_sent_rot[3];\r\n\tFlags< int >\t\t\t\t\tm_last_sent_flags;\r\n\tFlags< int >\t\t\t\t\tm_last_sent_end_run_flags;\r\n\tchar\t\t\t\t\t\t\tm_last_sent_state;\r\n\tchar\t\t\t\t\t\t\tm_last_sent_doing_trick;\r\n\tchar\t\t\t\t\t\t\tm_last_sent_walking;\r\n\tchar\t\t\t\t\t\t\tm_last_sent_driving;\r\n\tsint16\t\t\t\t\t\t\tm_last_sent_rail;\r\n\t\r\nprivate:\r\n\tCSkaterStateComponent*\t\t\tmp_state_component;\r\n\tCSkaterCorePhysicsComponent*\tmp_physics_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterLoopingSoundComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterLoopingSoundComponent.cpp\r\n//* OWNERD:\t\t\tDan\r\n//* CREATION DATE:  2/26/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skaterloopingsoundcomponent.h>\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/skaterflags.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/utils.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent* CSkaterLoopingSoundComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterLoopingSoundComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterLoopingSoundComponent::CSkaterLoopingSoundComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERLOOPINGSOUND );\r\n\t\r\n\tm_is_bailing = m_is_rail_sliding = false;\r\n\tm_have_sound_info = false;\r\n\tm_update_sound_info = true;\r\n\tm_StateType = AIR;\r\n\tm_vol_mult = 1.0f;\r\n\tm_active = true;\r\n\tm_unpause = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterLoopingSoundComponent::~CSkaterLoopingSoundComponent()\r\n{\r\n\tStopLoopingSound();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLoopingSoundComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tm_wheelspin_pitch_step = (vSS_WHEELSPIN_MIN_PITCH - (vSS_WHEELSPIN_MIN_PITCH - vSS_WHEELSPIN_MAX_PITCH / 2.0f)) / vSS_MIN_WHEELSPIN_TIME;\r\n\tm_wheelspin_end_pitch = vSS_WHEELSPIN_MIN_PITCH - vSS_WHEELSPIN_MAX_PITCH / 2.0f;\r\n\tpParams->GetFloat( CRCD(0xf1a99b27,\"volume_mult\"), &m_vol_mult, Script::NO_ASSERT );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLoopingSoundComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLoopingSoundComponent::Finalize (   )\r\n{\r\n\tmp_physics_control_component = GetSkaterPhysicsControlComponentFromObject(GetObject());\r\n\t\r\n\t// Dbg_Assert(mp_physics_control_component);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLoopingSoundComponent::Update()\r\n{\r\n\tif (!m_active)\r\n\t{\r\n\t\tSuspend(true);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// update looping sounds\r\n\t\r\n\tSfx::sVolume volume;\r\n\tfloat pitch;\r\n\r\n\tswitch ( m_StateType )\r\n\t{\r\n\t\tcase RAIL:\r\n\t\t{\r\n\t\t\tif ( m_is_bailing )\r\n\t\t\t{\r\n\t\t\t\tm_have_sound_info = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tEnv::ETerrainActionType table;\r\n\t\t\tif ( m_is_rail_sliding )\r\n\t\t\t{\r\n\t\t\t\ttable = Env::vTABLE_SLIDE;\r\n\t\t\t}\r\n\t\t\telse\t\t\t\t\t\t\t\t\r\n\t\t\t{\r\n\t\t\t\ttable = Env::vTABLE_GRIND;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (m_update_sound_info)\r\n\t\t\t{\r\n\t\t\t\tm_have_sound_info = Env::CTerrainManager::sGetTerrainSoundInfo(&m_sound_info, m_terrain, table);\r\n\t\t\t\tm_update_sound_info = false;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase GROUND:\r\n\t\t\tif (m_update_sound_info)\r\n\t\t\t{\r\n\t\t\t\tm_have_sound_info = Env::CTerrainManager::sGetTerrainSoundInfo(&m_sound_info, m_terrain, Env::vTABLE_WHEELROLL);\t\t\t\r\n\t\t\t\tm_update_sound_info = false;\r\n\t\t\t}\r\n\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase AIR:\r\n\t\t\tif (m_update_sound_info)\r\n\t\t\t{\r\n\t\t\t\tm_have_sound_info = true;\r\n\t\t\t\tm_sound_info = AIR_LOOPING_SOUND_INFO;\r\n\t\t\t\tm_update_sound_info = false;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t} // END switch on skater state\r\n\r\n\t// if the sound has changed, turn off the old one\r\n\tif (m_looping_sound_id && (!m_have_sound_info || m_looping_sound_checksum != m_sound_info.m_soundChecksum))\r\n\t{\r\n\t\tSfx::CSfxManager::Instance()->StopSound(m_looping_sound_id);\r\n\t\tm_looping_sound_id = 0;\r\n\t}\r\n\t\r\n\t// we have no sound to play\r\n\tif (!m_have_sound_info) return;\r\n\t\r\n\t// setup the sound's pitch and volume based on the skater's state\r\n\t\r\n\tSfx::CSfxManager* p_sfx_manager = Sfx::CSfxManager::Instance();\r\n\t\r\n\t// adjust volume based of skater's offset from the nearest camera\r\n\tp_sfx_manager->SetVolumeFromPos(&volume, GetObject()->GetPos(), p_sfx_manager->GetDropoffDist(m_sound_info.m_soundChecksum));\r\n\t\r\n\t// if the skater is in the air and this isn't the first frame we've been playing the air looping sound\r\n\tif ( m_StateType == AIR && m_looping_sound_id )\r\n\t{\r\n\t\t// drop the pitch over time\r\n\t\tif (m_wheelspin_pitch > m_wheelspin_end_pitch)\r\n\t\t{\r\n\t\t\tm_wheelspin_pitch -= m_wheelspin_pitch_step * Tmr::FrameLength();\r\n\t\t}\r\n\t\t// then kill the volume\r\n\t\telse\r\n\t\t{\r\n\t\t\tvolume.SetSilent();\r\n\t\t}\r\n\t\t\r\n\t\tpitch = m_wheelspin_pitch;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// adjust the volume and pitch based on the speed\r\n\t\t \r\n\t\tif ( m_speed_fraction > 0.0f)\r\n\t\t{\r\n\t\t\tvolume.PercentageAdjustment(Env::CTerrainManager::sGetVolPercent(&m_sound_info, 100.0f * m_speed_fraction * m_vol_mult));\r\n\t\t\t\r\n\t\t\tpitch = m_speed_fraction * (m_sound_info.m_maxPitch - m_sound_info.m_minPitch) + m_sound_info.m_minPitch;\r\n\t\t\t\r\n\t\t\t// save the current pitch incase we are in the air next frame\r\n\t\t\tm_wheelspin_pitch = pitch;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tvolume.SetSilent();\r\n\t\t\tm_wheelspin_pitch = pitch = 0.0f;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// if the volume is zero\r\n\tif (volume.IsSilent())\r\n\t{\r\n\t\t// stop playing the sound\r\n\t\tif (m_looping_sound_id)\r\n\t\t{\r\n\t\t\tSfx::CSfxManager::Instance()->StopSound(m_looping_sound_id);\r\n\t\t\tm_looping_sound_id = 0;\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// NOTE: removed until I can figure out what to do with this\r\n\t// adjust the sound based on doppler effects\r\n\t// if ( Nx::CViewportManager::sGetScreenMode( ) == 0 ) // that zero should be an enum or something...\r\n\t// {\r\n\t\t// sfx_manager->AdjustPitchForDoppler( &pitch, mp_physics->m_pos, mp_physics->m_old_pos, mp_physics->m_time, Nx::CViewportManager::sGetActiveCamera( 0 ) );\r\n\t// }\r\n\t\r\n\t// NOTE: removing all replay code for now\r\n\t// save pitch information for the replay code\r\n\t// m_pitch_min = sound_info.m_minPitch;\r\n\t// m_pitch_max = sound_info.m_maxPitch;\r\n\t\r\n\t// if we're not already playing a sound\r\n\tif (!m_looping_sound_id)\r\n\t{\r\n\t\tm_last_volume = volume;\r\n\t\tm_last_pitch = pitch;\r\n\t\t\r\n\t\t// start the sound\r\n\t\tm_looping_sound_id = p_sfx_manager->PlaySound(m_sound_info.m_soundChecksum, &volume, pitch, 0, NULL, m_sound_info.mp_soundName);\r\n\t\tif (!m_looping_sound_id)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\t// save the checksum of the currently playing sound\r\n\t\tm_looping_sound_checksum = m_sound_info.m_soundChecksum;\r\n\t}\r\n\t\r\n\t// if we need to update the sound already playing; since we scale all channels equally, we can get away with only checking the first volume\r\n\telse if (m_unpause || Mth::Abs(volume.m_channels[0] - m_last_volume.m_channels[0]) > vSS_MAX_PERCENTAGE_VOLUME_CHANGE_WITHOUT_UPDATE\r\n\t\t|| Mth::Abs(pitch - m_last_pitch) > vSS_MAX_PITCH_CHANGE_WITHOUT_UPDATE)\r\n\t{\r\n\t\tm_last_volume = volume;\r\n\t\tm_last_pitch = pitch;\r\n\t\tm_unpause = false;\r\n\t\t\r\n\t\tp_sfx_manager->UpdateLoopingSound(m_looping_sound_id, &volume, pitch);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterLoopingSoundComponent::CallMemberFunction ( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tcase CRCC(0xede3935f, \"SkaterLoopingSound_TurnOn\"):\r\n\t\t\tSetActive(true);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x9731e193, \"SkaterLoopingSound_TurnOff\"):\r\n\t\t\tSetActive(false);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0xb1e7291, \"PlayAnim\"):\r\n\t\t\t// if a transition anim is interrupted, we must turn the looping sounds on here\r\n\t\t\tDbg_MsgAssert( mp_physics_control_component, ( \"Don't call PlayAnim on a non-skater\" ) );\r\n\t\t\t\r\n\t\t\tScript::CStruct* p_anim_tags_struct;\r\n\t\t\tif (GetObject()->GetTags()\r\n\t\t\t\t&& mp_physics_control_component->IsSkating()\r\n\t\t\t\t&& GetObject()->GetTags()->GetStructure(CRCD(0x5db4115f, \"AnimTags\"), &p_anim_tags_struct)\r\n\t\t\t\t&& p_anim_tags_struct->ContainsFlag(CRCD(0x910d77c1, \"WalkToSkateTransition\")))\r\n\t\t\t{\r\n\t\t\t\tSuspend(false);\r\n\t\t\t\tm_active = true;\r\n\t\t\t}\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\treturn CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLoopingSoundComponent::GetDebugInfo ( Script::CStruct *p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterLoopingSoundComponent::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddInteger(\"m_looping_sound_id\", m_looping_sound_id);\r\n\tp_info->AddChecksum(\"m_looping_sound_checksum\", m_looping_sound_checksum);\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLoopingSoundComponent::Suspend ( bool suspend )\r\n{\r\n\tCBaseComponent::Suspend(suspend);\r\n\t\r\n\tif (suspend)\r\n\t{\r\n\t\tStopLoopingSound();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_update_sound_info = true;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLoopingSoundComponent::StopLoopingSound (   )\r\n{\r\n\tif (m_looping_sound_id)\r\n\t{\r\n\t\tSfx::CSfxManager::Instance()->StopSound(m_looping_sound_id);\r\n\t\tm_looping_sound_id = 0;\r\n\t}\r\n}\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLoopingSoundComponent::SetSpeedFraction( float speed_fraction )\r\n{\r\n\tm_speed_fraction = speed_fraction;\r\n\tif ( m_speed_fraction > 1.0f )\r\n\t{\r\n\t\tm_speed_fraction = 1.0f;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterLoopingSoundComponent::SetVolumeMultiplier( float mult )\r\n{\r\n\tDbg_MsgAssert( mult >= 0.0f && mult <= 1.0f, ( \"SetVolumeMultiplier called with bad mult value: %f\", mult ) );\r\n\tm_vol_mult = mult;\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterLoopingSoundComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterLoopingSoundComponent.h\r\n//* OWNERD:\t\t\tDan\r\n//* CREATION DATE:  2/26/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERLOOPINGSOUNDCOMPONENT_H__\r\n#define __COMPONENTS_SKATERLOOPINGSOUNDCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n#include <gel/environment/terrain.h>\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n#include <sk/objects/skaterflags.h>\r\n\r\n#define\t\tCRC_SKATERLOOPINGSOUND CRCD(0xb5f1e9d2, \"SkaterLoopingSound\")\r\n\r\n#define\t\tGetSkaterLoopingSoundComponent() ((Obj::CSkaterLoopingSoundComponent*)GetComponent(CRC_SKATERLOOPINGSOUND))\r\n#define\t\tGetSkaterLoopingSoundComponentFromObject(pObj) ((Obj::CSkaterLoopingSoundComponent*)(pObj)->GetComponent(CRC_SKATERLOOPINGSOUND))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CSkaterPhysicsControlComponent;\r\n\r\n\tstatic const float vSS_MAX_PITCH_CHANGE_WITHOUT_UPDATE = 0.5f;\r\n\tstatic const float vSS_MAX_PERCENTAGE_VOLUME_CHANGE_WITHOUT_UPDATE = 0.5f;\r\n\t\r\n\tstatic const float vSS_WHEELSPIN_MIN_PITCH = 100.0f;\r\n\tstatic const float vSS_WHEELSPIN_MAX_PITCH = 110.0f;\r\n\tstatic const float vSS_MIN_WHEELSPIN_TIME = 3.0f;\r\n\t\r\n\t// looping sound used when skater is in the air\r\n\tstatic const Env::STerrainSoundInfo AIR_LOOPING_SOUND_INFO =\r\n\t{\r\n\t\t\"wheels01\",\r\n\t\tCRCD(0x24257432, \"wheels01\"),\r\n\t\tvSS_WHEELSPIN_MIN_PITCH,\r\n\t\tvSS_WHEELSPIN_MAX_PITCH\r\n\t};\r\n\t\r\nclass CSkaterLoopingSoundComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkaterLoopingSoundComponent();\r\n    virtual ~CSkaterLoopingSoundComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tFinalize (   );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tSuspend ( bool suspend );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tStopLoopingSound (   );\r\n\r\n\tvoid\t\t\t\t\t\t\tUnPause();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetActive ( bool active );\r\n\r\n\tvoid\t\t\t\t\t\t\tSetIsBailing( bool is_bailing );\r\n\tvoid\t\t\t\t\t\t\tSetIsRailSliding( bool is_sliding );\r\n\r\n\tvoid\t\t\t\t\t\t\tSetState( EStateType new_state );\r\n\tvoid\t\t\t\t\t\t\tSetTerrain( ETerrainType terrain );\r\n\r\n\tvoid\t\t\t\t\t\t\tSetSpeedFraction( float speed_fraction );\r\n\tvoid\t\t\t\t\t\t\tSetVolumeMultiplier( float mult );\r\nprivate:\r\n\t// the ID of the current looping sound\r\n\tuint32\t\t\t\t\t\t\tm_looping_sound_id;\r\n\t\r\n\t// checksum of the current looping sound\r\n\tuint32\t\t\t\t\t\t\tm_looping_sound_checksum;\r\n\t\r\n\t// holds the last frame's looping sound pitch so that can be used when the skater goes airborne\r\n\tfloat\t\t\t\t\t\t\tm_wheelspin_pitch;\r\n\t\r\n\t// optimization variables\r\n\tfloat\t\t\t\t\t\t\tm_last_pitch;\r\n\tSfx::sVolume\t\t\t\t\tm_last_volume;\r\n\t\r\n\t// constant characteristics\r\n\t\r\n\t// the drop in pitch of the air looping sound per second\r\n\tfloat m_wheelspin_end_pitch;\r\n\t\r\n\t// the final pitch of the air looping sound; when reached the sound is turned off\r\n\tfloat m_wheelspin_pitch_step;\r\n\r\n\t// peer components\r\n\tCSkaterPhysicsControlComponent*\tmp_physics_control_component;\r\n\r\n\tETerrainType\t\t\t\t\tm_terrain;\r\n\tEStateType\tm_StateType;\r\n\r\n\tEnv::STerrainSoundInfo\t\t\tm_sound_info;\r\n\tbool\t\t\t\t\t\t\tm_have_sound_info;\r\n\tbool\t\t\t\t\t\t\tm_update_sound_info;\r\n\tbool\t\t\t\t\t\t\tm_unpause;\r\n\r\n\tbool\t\t\t\t\t\t\tm_is_bailing;\r\n\tbool\t\t\t\t\t\t\tm_is_rail_sliding;\r\n\r\n\tfloat\t\t\t\t\t\t\tm_speed_fraction;\r\n\tfloat\t\t\t\t\t\t\tm_vol_mult;\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_active;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterLoopingSoundComponent::SetActive ( bool active )\r\n{\r\n\tif (m_active != active)\r\n\t{\r\n\t\tSuspend(!active);\r\n\t\tm_active = active;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\tCSkaterLoopingSoundComponent::UnPause()\r\n{\r\n\tm_unpause = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterLoopingSoundComponent::SetState( EStateType state )\r\n{\r\n\tm_update_sound_info |= (m_StateType != state);\r\n\tm_StateType = state;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterLoopingSoundComponent::SetTerrain( ETerrainType terrain )\r\n{\r\n\tm_update_sound_info |= (m_terrain != terrain);\r\n\tm_terrain = terrain;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterLoopingSoundComponent::SetIsBailing( bool is_bailing )\r\n{\r\n\tm_is_bailing = is_bailing;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterLoopingSoundComponent::SetIsRailSliding( bool is_rail_sliding )\r\n{\r\n\tm_update_sound_info |= (m_is_rail_sliding != is_rail_sliding);\r\n\tm_is_rail_sliding = is_rail_sliding;\r\n}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterMatrixQueriesComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterMatrixQueriesComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/12/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skatermatrixqueriescomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSkaterMatrixQueriesComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterMatrixQueriesComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterMatrixQueriesComponent::CSkaterMatrixQueriesComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERMATRIXQUERIES );\r\n\t\r\n\tmp_core_physics_component = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterMatrixQueriesComponent::~CSkaterMatrixQueriesComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterMatrixQueriesComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tDbg_MsgAssert(GetObject()->GetType() == SKATE_TYPE_SKATER, (\"CSkaterMatrixQueriesComponent added to non-skater composite object\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterMatrixQueriesComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterMatrixQueriesComponent::Finalize (   )\r\n{\r\n\tmp_core_physics_component = GetSkaterCorePhysicsComponentFromObject(GetObject());\r\n\t\t\r\n\tDbg_Assert(mp_core_physics_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterMatrixQueriesComponent::Update()\r\n{\r\n\t// Store the matrix from the last frame. Used by script functions for measuring angles & stuff. Has to use the last frame's matrix\r\n\t// because the landing physics snaps the orientation to the ground, yet the land script (which executes just after) needs to measure \r\n\t// the angles on impact to maybe trigger bails and such.\r\n\tm_latest_matrix = mp_core_physics_component->m_lerping_display_matrix;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterMatrixQueriesComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | YawBetween | yaw between the two specified angles\r\n        // @uparm (45, 135) | angle range values\r\n\t\tcase CRCC(0xb992f3cc, \"YawBetween\"):\r\n\t\t{\r\n\t\t\t// if (CHEAT_SNOWBOARD) \r\n\t\t\t// {\r\n\t\t\t\t// return false;\r\n\t\t\t// }\r\n\t\t\t\r\n\t\t\tScript::CPair Pair;\r\n\t\t\tif (!pParams->GetPair(NO_NAME, &Pair, Script::ASSERT))\r\n\t\t\tDbg_MsgAssert(Pair.mX < Pair.mY,(\"\\n%s\\n1st angle must be less than the 2nd angle\", pScript->GetScriptInfo()));\r\n\t\t\t\r\n\t\t\tMth::Vector a = GetSkater()->m_vel;\r\n\t\t\ta.RotateToPlane(m_latest_matrix[Y]);\r\n\t\t\treturn (Mth::AngleBetweenGreaterThan(a, m_latest_matrix[Z], Pair.mX)\r\n\t\t\t\t&& !Mth::AngleBetweenGreaterThan(a, m_latest_matrix[Z], Pair.mY))\r\n\t\t\t\t? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\r\n        // @script | YawingLeft | true if currently yawing left\r\n\t\tcase CRCC(0xa745c080, \"YawingLeft\"):\r\n\t\t{\r\n\t\t\tMth::Vector a = GetSkater()->m_vel;\r\n\t\t\ta.RotateToPlane(m_latest_matrix[Y]);\r\n\t\t\treturn Mth::CrossProduct(a, m_latest_matrix[Z])[Y] > 0.0f ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\t\t\r\n        // @script | YawingRight | true if currently yawing right\r\n\t\tcase CRCC(0xc8c4d2f4, \"YawingRight\"):\r\n\t\t{\r\n\t\t\tMth::Vector a = GetSkater()->m_vel;\r\n\t\t\ta.RotateToPlane(m_latest_matrix[Y]);\r\n\t\t\treturn Mth::CrossProduct(a, m_latest_matrix[Z])[Y] < 0.0f ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\t\t\r\n        // @script | PitchGreaterThan | true if the pitch is greater\r\n        // than the specified value\r\n        // @uparm 0.0 | test angle\r\n\t\tcase CRCC(0xa0551543, \"PitchGreaterThan\"):\r\n\t\t{\r\n\t\t\tfloat TestAngle = 0.0f;\r\n\t\t\tpParams->GetFloat(NO_NAME, &TestAngle, Script::ASSERT);\r\n\t\t\t\r\n\t\t\treturn Mth::DotProduct(m_latest_matrix[Y], mp_core_physics_component->m_last_display_normal) < cosf(Mth::DegToRad(TestAngle))\r\n\t\t\t\t? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\r\n\t\tcase CRCC(0x5e269b2b, \"AbsolutePitchGreaterThan\"):\r\n\t\t{\r\n\t\t\tfloat TestAngle = 0.0f;\r\n\t\t\tpParams->GetFloat(NO_NAME, &TestAngle, Script::ASSERT);\r\n\t\t\t\r\n\t\t\treturn m_latest_matrix[Y][Y] < cosf(Mth::DegToRad(TestAngle)) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\t\t\r\n\t\t/*\r\n        // @script | PitchingForward | true if pitching forward\r\n\t\tcase CRCC(0xdaeda59c, \"PitchingForward\"):\r\n\t\t{\r\n\t\t\tMth::Vector b = Mth::CrossProduct(m_latest_matrix[Y], mp_core_physics_component->m_last_display_normal);\r\n\t\t\treturn Mth::DotProduct(b, m_latest_matrix[X]) < 0.0f ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\r\n        // @script | PitchingBackward | true if pitching backward\r\n\t\tcase CRCC(0x7dd9e92c, \"PitchingBackward\"):\r\n\t\t{\r\n\t\t\tMth::Vector b = Mth::CrossProduct(m_latest_matrix[Y], mp_core_physics_component->m_last_display_normal);\r\n\t\t\treturn Mth::DotProduct(b, m_latest_matrix[X]) > 0.0f ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\t*/\r\n\r\n        // @script | RollGreaterThan | true if the roll is greater than\r\n        // the specified angle value\r\n        // @uparm 0.0 | angle value\r\n\t\tcase CRCC(0xd3313e92, \"RollGreaterThan\"):\r\n\t\t{\r\n\t\t\tfloat TestAngle = 0.0f;\r\n\t\t\tpParams->GetFloat(NO_NAME, &TestAngle, Script::ASSERT);\r\n\t\t\t\r\n\t\t\tMth::Vector a = m_latest_matrix[X];\r\n\t\t\ta.RotateToPlane(mp_core_physics_component->m_last_display_normal);\r\n\t\t\treturn Mth::AngleBetweenGreaterThan(a, m_latest_matrix[X], TestAngle) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\r\n\t\t/*\r\n\t\t// @script | RollingLeft | true if rolling left\r\n\t\tcase CRCC(0x7328c9ad, \"RollingLeft\"):\r\n\t\t{\r\n\t\t\tMth::Vector b = Mth::CrossProduct(m_latest_matrix[Y], mp_core_physics_component->m_last_display_normal);\r\n\t\t\treturn Mth::DotProduct(b, m_latest_matrix[Z]) > 0.0f ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\r\n        // @script | RollingRight | true if rolling right\r\n\t\tcase CRCC(0x8dcfe388, \"RollingRight\"):\r\n\t\t{\r\n\t\t\tMth::Vector b = Mth::CrossProduct(m_latest_matrix[Y], mp_core_physics_component->m_last_display_normal);\r\n\t\t\treturn Mth::DotProduct(b, m_latest_matrix[Z]) < 0.0f ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\t*/\r\n\t\t\t\r\n\t\t// @script | GetSlope | Puts the angle of the slope into a param called Slope.\r\n\t\t// Units are degrees. Zero is horizontal, positive is up, negative is down.\r\n\t\t// The change in slope since the last call to GetSlope is put in a parameter\r\n\t\t// called ChangeInSlope\r\n\t\tcase CRCC(0x97201739, \"GetSlope\"):\r\n\t\t{\r\n\t\t\tMth::Vector v = GetObject()->m_matrix[Z];\r\n\t\t\tv[Y] = 0.0f;\r\n\t\t\tfloat slope = Mth::GetAngle(GetObject()->m_matrix[Z], v);\r\n\t\t\tif (GetObject()->m_matrix[Z][Y] < 0.0f)\r\n\t\t\t{\r\n\t\t\t\tslope = -slope;\r\n\t\t\t}\t\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0xa733ba7a, \"Slope\"), slope);\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x21afff16, \"ChangeInSlope\"), slope - m_last_slope);\r\n\t\t\tm_last_slope = slope;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase CRCC(0x8e7833be, \"GetHeading\"):\r\n\t\t{\r\n\t\t\tfloat heading = Mth::RadToDeg(cosf(GetObject()->m_matrix[Z][X]));\r\n\t\t\tif (GetObject()->m_matrix[Z][Z] < 0.0f)\r\n\t\t\t{\r\n\t\t\t\theading = 360.0f - heading;\r\n\t\t\t}\t\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0xfd4bc03e, \"heading\"), heading);\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x2315ef17, \"cosine\"), GetObject()->m_matrix[Z][X]);\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x26910cc0, \"sine\"), GetObject()->m_matrix[Z][Z]);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterMatrixQueriesComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterMatrixQueriesComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterMatrixQueriesComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterMatrixQueriesComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/12/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERMATRIXQUERIESCOMPONENT_H__\r\n#define __COMPONENTS_SKATERMATRIXQUERIESCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#define\t\tCRC_SKATERMATRIXQUERIES CRCD(0xbf518e27, \"SkaterMatrixQueries\")\r\n\r\n#define\t\tGetSkaterMatrixQueriesComponent() ((Obj::CSkaterMatrixQueriesComponent*)GetComponent(CRC_SKATERMATRIXQUERIES))\r\n#define\t\tGetSkaterMatrixQueriesComponentFromObject(pObj) ((Obj::CSkaterMatrixQueriesComponent*)(pObj)->GetComponent(CRC_SKATERMATRIXQUERIES))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CSkaterMatrixQueriesComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkaterMatrixQueriesComponent();\r\n    virtual ~CSkaterMatrixQueriesComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\t\r\n\tvoid\t\t\t\t\t\t\tResetLatestMatrix (   ) { m_latest_matrix = GetObject()->GetMatrix(); }\r\n\t\r\nprivate:\r\n\tMth::Matrix\t\t\t\t\t\tm_latest_matrix;\r\n\tfloat\t\t\t\t\t\t\tm_last_slope;\r\n\t\r\n\t// peer components\r\n\tCSkaterCorePhysicsComponent*\tmp_core_physics_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterNonLocalNetLogicComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterNonLocalNetLogicComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/11/3\r\n//****************************************************************************\r\n\r\n#include <core/math/slerp.h>\r\n\r\n#include <gfx/baseanimcontroller.h>\r\n#include <gfx/animcontroller.h>\r\n#include <gfx/nxlight.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/nxflags.h>\r\n\t\t\t\t\t\t\t\t\r\n#include <sk/components/skaternonlocalnetlogiccomponent.h>\r\n#include <sk/components/skaterstatehistorycomponent.h>\r\n#include <sk/components/skaterendruncomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skaterflipandrotatecomponent.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n#include <sk/components/skaterloopingsoundcomponent.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/specialitemcomponent.h>\r\n#include <gel/components/lockobjcomponent.h>\r\n#include <gel/components/shadowcomponent.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/net/client/netclnt.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSkaterNonLocalNetLogicComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterNonLocalNetLogicComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterNonLocalNetLogicComponent::CSkaterNonLocalNetLogicComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERNONLOCALNETLOGIC );\r\n\t\r\n\tmp_state_history_component = NULL;\r\n\tmp_state_component = NULL;\r\n\tmp_endrun_component = NULL;\r\n\tmp_animation_component = NULL;\r\n\tmp_model_component = NULL;\r\n\tmp_flip_and_rotate_component = NULL;\r\n\tmp_shadow_component = NULL;\r\n\tm_last_pos_index = 0;\r\n\tm_interp_pos = Mth::Vector( 0, 0, 0 );\r\n\tm_old_interp_pos = Mth::Vector( 0, 0, 0 );\r\n\tm_num_mags = 0;\r\n\tm_last_anm_update_time = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterNonLocalNetLogicComponent::~CSkaterNonLocalNetLogicComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterNonLocalNetLogicComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tDbg_MsgAssert(GetObject()->GetType() == SKATE_TYPE_SKATER, (\"CSkaterNonLocalNetLogicComponent added to non-skater composite object\"));\r\n\tDbg_MsgAssert(!GetSkater()->IsLocalClient(), (\"CSkaterNonLocalNetLogicComponent added to non-local skater\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterNonLocalNetLogicComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterNonLocalNetLogicComponent::Finalize (   )\r\n{\r\n\tmp_state_history_component = GetSkaterStateHistoryComponentFromObject(GetObject());\r\n\tmp_state_component = GetSkaterStateComponentFromObject(GetObject());\r\n\tmp_endrun_component = GetSkaterEndRunComponentFromObject(GetObject());\r\n\tmp_animation_component = GetAnimationComponentFromObject(GetObject());\r\n\tmp_flip_and_rotate_component = GetSkaterFlipAndRotateComponentFromObject(GetObject());\r\n\tmp_model_component = GetModelComponentFromObject(GetObject());\r\n\tmp_shadow_component = GetShadowComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_state_history_component);\r\n\tDbg_Assert(mp_state_component);\r\n\tDbg_Assert(mp_endrun_component);\r\n\tDbg_Assert(mp_animation_component);\r\n\tDbg_Assert(mp_flip_and_rotate_component);\r\n\tDbg_Assert(mp_model_component);\r\n\tDbg_Assert(mp_shadow_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterNonLocalNetLogicComponent::Update()\r\n{\r\n\tGameNet::PlayerInfo* local_player;\r\n\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tm_frame_length = Tmr::UncappedFrameLength();\r\n\r\n\tbool BeganFrameInLipState = mp_state_component->GetState() == LIP;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tif( mp_state_component->GetState() != AIR )\r\n\t{\r\n\t\tmp_state_component->m_camera_display_normal = GetObject()->GetMatrix().GetUp();\r\n\t\tmp_state_component->m_camera_current_normal = GetObject()->GetMatrix().GetUp();\r\n\t}\r\n\r\n\tsetup_brightness_and_shadow();             \r\n\t\r\n\tm_old_extrap_pos = GetObject()->m_pos;\r\n\tGetObject()->m_old_pos = GetObject()->m_pos;\r\n\tinterpolate_client_position();\r\n\t// Only extrapolate if we can collide with other players. Otherwise, interpolation looks \r\n\t// much better.\r\n\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\tif( !local_player->IsObserving() &&\r\n\t\t!local_player->IsSurveying())\r\n\t{\r\n\t\tif( ( GameNet::Manager::Instance()->PlayerCollisionEnabled()) ||\r\n\t\t\t( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0xbff33600,\"netfirefight\")) ||\r\n\t\t\t( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0x3d6d444f,\"firefight\")))\r\n\t\t{\r\n\t\t\textrapolate_client_position();\r\n\t\t}\r\n\t}\r\n\tdo_client_animation_update();\r\n\t\r\n\t// NOTE: Below logic is copied from CSkaterFinalizePhysicsComponent and should instead be merged.\r\n\t\r\n\t// Logic for setting/not setting the flag for telling the camera whether to look down on the skater or not.\r\n\tif (BeganFrameInLipState && mp_state_component->GetState() != LIP)\r\n\t{\r\n\t\t// This flag is sort of badly named now, it really means we changed from the lip state to something other than GROUND or LIP.\r\n\t\tmp_state_component->mJumpedOutOfLipTrick = false;\r\n\t\tif (mp_state_component->GetState() == AIR)\r\n\t\t{\r\n\t\t\t// we only want to set this flag if we jumped straight up; meaning the x and z velocities are close to zero\r\n\t\t\tif (Mth::Abs(GetObject()->m_vel[X]) < 1.0f && Mth::Abs(GetObject()->m_vel[Z]) < 1.0f)\r\n\t\t\t{\r\n\t\t\t\tmp_state_component->mJumpedOutOfLipTrick = true;\r\n\t\t\t}\t\t\t\t\r\n\t\t}\r\n\t}\r\n\t\r\n\t// this flag needs clearing whenever we get out of the air\r\n\tif (mp_state_component->GetState() != AIR)\r\n\t{\r\n\t\tmp_state_component->mJumpedOutOfLipTrick = false;\r\n\t}\r\n\t\r\n\t// take the non-local client in and out of the car\r\n\tif (mp_state_component->GetDriving() && mp_state_history_component->GetCurrentVehicleControlType() != 0)\r\n\t{\r\n\t\tScript::CStruct* pParams = new Script::CStruct;\r\n\t\tpParams->AddChecksum(CRCD(0x5b24faaa, \"SkaterId\"), GetObject()->GetID());\r\n\t\tpParams->AddChecksum(CRCD(0x81cff663, \"control_type\"), mp_state_history_component->GetCurrentVehicleControlType());\r\n\t\tRunScript(CRCD(0x7853f8c4, \"NonLocalClientInVehicle\"), pParams);\r\n\t\tdelete pParams;\r\n\t}\r\n\telse if (!mp_state_component->GetDriving() && m_last_driving)\r\n\t{\r\n\t\tScript::CStruct* pParams = new Script::CStruct;\r\n\t\tpParams->AddChecksum(CRCD(0x5b24faaa, \"SkaterId\"), GetObject()->GetID());\r\n\t\tRunScript(CRCD(0xf02e44f, \"NonLocalClientExitVehicle\"), pParams);\r\n\t\tdelete pParams;\r\n\t}\r\n\tm_last_driving = mp_state_component->GetDriving();\r\n\t\r\n\t// update the looping sound component\r\n\tCSkaterLoopingSoundComponent* p_looping_sound_component = GetSkaterLoopingSoundComponentFromObject(GetObject());\r\n\tDbg_Assert(p_looping_sound_component);\r\n\tif (mp_state_component->m_physics_state == SKATING)\r\n\t{\r\n\t\tp_looping_sound_component->SetActive(true);\r\n\t\tfloat speed_fraction = sqrtf(GetObject()->m_vel[X] * GetObject()->m_vel[X] + GetObject()->m_vel[Z] * GetObject()->m_vel[Z]) / 1000.0f;\r\n\t\tp_looping_sound_component->SetSpeedFraction(speed_fraction);\r\n\t\tp_looping_sound_component->SetState(mp_state_component->m_state);\r\n\t\tp_looping_sound_component->SetTerrain(mp_state_component->m_terrain);\r\n\t\tp_looping_sound_component->SetIsBailing(mp_state_component->GetFlag(IS_BAILING));\r\n\t\tp_looping_sound_component->SetIsRailSliding(mp_state_component->GetFlag(RAIL_SLIDING));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_looping_sound_component->SetActive(false);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterNonLocalNetLogicComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterNonLocalNetLogicComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterNonLocalNetLogicComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterNonLocalNetLogicComponent::Resync (   )\r\n{\r\n\tm_client_initial_update_time = 0;\r\n\tm_last_anm_update_time = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterNonLocalNetLogicComponent::snap_to_ground( void  )\r\n{\r\n\tfloat up_dot = 0.0f;\r\n\tMth::Vector col_start, col_end;\r\n\tCFeeler feeler;\r\n\t\r\n\t// Since we really don't want to loose contact with the ground while skitching, we use a much bigger snap up dist\r\n\t// The problem will come when we get dragged down a slope.  The car will flatten out well ahead of us, so pushing us down through the slop\r\n\t// (as we are a few feet behind it) and we will be so far under the ground that our normal snap up will not be able to dig us out of it,\r\n\t// so we go in air, uberfrig, and get dragged to a random spot under the level.\r\n\t// (This would not happen if we just skitch on flat ground)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t// if (mp_state_component->m_skater_flags[SKITCHING].Get())\r\n\t// {\r\n\t\t// col_start = GetObject()->m_matrix[Y] * GetPhysicsFloat(CRCD(0x5c0d9610,\"Physics_Ground_Snap_Up_SKITCHING\"));\t// much above feet\r\n\t// }\r\n\t// else\r\n\t// {\r\n\t\tcol_start = GetObject()->m_matrix[Y] * GetPhysicsFloat(CRCD(0xe4d79235, \"Physics_Ground_Snap_Up\"));\t  \t\t// bit above the feet\r\n\t// }\r\n\t\r\n\tcol_end = GetObject()->m_matrix[Y] * -200.0f;\t\t    // WAY! below the feet, we check distance later\r\n\r\n\tcol_start += GetObject()->m_pos;\r\n\tcol_end += GetObject()->m_pos;\r\n\t\t \r\n\tbool sticking = false;\t\t\t\r\n\t\r\n\tfeeler.SetLine( col_start, col_end );\r\n\tfeeler.SetIgnore( mFD_NON_COLLIDABLE, 0 );\r\n\t// get disatnce to ground and snap the skater to it, but only if the ground is skatable, otherwise we just go to \"AIR\"\r\n\tif( feeler.GetCollision())\r\n\t{\r\n\t\tMth::Vector movement = GetObject()->m_pos - feeler.GetPoint(); \r\n\t\tuint16 flags = feeler.GetFlags();\r\n\t\tfloat drop_dist = movement.Length();\r\n\t\tfloat drop_sign = Mth::DotProduct(GetObject()->m_matrix[Y], movement); // might be approx +/- 0.00001f\r\n\t\tif(\t(!flags & mFD_SKATABLE ) || ( flags & mFD_NOT_SKATABLE ) || (!flags & mFD_VERT) || \r\n\t\t\t(flags & mFD_WALL_RIDABLE) ||\r\n\t\t\t(feeler.GetNormal()[Y] < sinf(Mth::DegToRad(GetPhysicsFloat(CRCD(0x3eede4d3,\"Wall_Non_Skatable_Angle\"))))))\r\n\t\t{\r\n\t\t\t// if below the face (or very close to it), then push us away from it\t\t\t\t\r\n\t\t\tif (drop_sign < 0.001f)\r\n\t\t\t{\r\n\t\t\t\t// at point of contact, and move away from surface\r\n\t\t\t\tGetObject()->m_pos = feeler.GetPoint() + feeler.GetNormal();\t\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsticking = true;\r\n\t\t\t\r\n\t\t\t// Note the two ways of calculating the angle between two faces\r\n\t\t\t// the more \"accurate\" method simply takes angle between the two normals\r\n\t\t\t// however, this fails to account for the direction the skater is travelling\r\n\t\t\t// when in conjunction with the \"snap\" up.\r\n\t\t\t// If the skater approaches a slope from the side, then he can snap up to the slope\r\n\t\t\t// however, if the angle between the ground and the face to which we are snapping up to \r\n\t\t\t// is too great, then we transition to in-air\r\n\t\t\t// and will drop through the slope\r\n\t\t\t// the solution is to take the angle between the front vector rotated onto each face.\r\n\t\t\t\r\n\t\t\t// Firstly we check the angle between the two faces\t\r\n\t\t\tMth::Vector normal = feeler.GetNormal();\r\n\t\t\t\r\n\t\t\tMth::Vector\tforward = GetObject()->m_matrix[Z];\r\n\t\t\tfloat front_dot = Mth::DotProduct(forward,normal);\r\n\r\n\t\t\tMth::Vector\told_forward = forward;\r\n\t\t\tforward.RotateToPlane(normal);\r\n\t\t\told_forward.RotateToPlane(m_current_normal);\r\n\r\n\t\t\t// angle between front vectors, projected onto faces\r\n\t\t\tup_dot = Mth::DotProduct(forward, old_forward);\r\n\t\t\t\r\n\t\t\tfloat stick_angle_cosine;\r\n\t\t\tstick_angle_cosine = cosf(Mth::DegToRad(GetPhysicsFloat(CRCD(0x4138283e, \"Ground_stick_angle_forward\"))));\r\n\t\t\t\r\n\t\t\tif (front_dot > 0.0f  && up_dot > 0.0f && up_dot < stick_angle_cosine)\r\n\t\t\t{\r\n\t\t\t\tsticking = false;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// only need to test if snap is downwards\r\n\t\t\t\tif (drop_sign > 0.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\t// angle between the old plane and the new plane is either the same, or withing the set limits\r\n\t\t\t\t\t// (like, < 60 degrees, or so, see physics.q) now calculate the drop distance, based on the angle\r\n\t\t\t\t\t\r\n\t\t\t\t\t//float max_drop = 60.0f;////last_move.Length() * tanf(angle);\r\n#ifdef __PLAT_NGC__\r\n\t\t\t\t\tfloat angle = acosf(Mth::Clamp(up_dot, -1.0f, 1.0f));\r\n#else\r\n\t\t\t\t\tfloat angle = acosf(up_dot);\r\n#endif // __PLAT_NGC__\r\n\r\n\t\t\t\t\tMth::Vector\tlast_move = GetObject()->m_pos - m_old_extrap_pos;\r\n\t\t\t\t\t\r\n\t\t\t\t\tfloat max_drop = last_move.Length() * tanf(angle);\r\n\t\t\t\t\t\r\n\t\t\t\t\tfloat min_drop = GetPhysicsFloat(CRCD(0x899ba3d0, \"Physics_Ground_Snap_Down\"));\t\t\t\t\r\n                    // if (mp_state_component->m_skater_flags[SKITCHING].Get())\r\n\t\t\t\t\t// {\r\n\t\t\t\t\t\t// min_drop = GetPhysicsFloat(CRCD(0x20df7e33, \"Physics_Ground_Snap_Down_Skitching\"));\t\t\t\t\r\n\t\t\t\t\t// }\r\n\r\n\t\t\t\t\tif (max_drop < min_drop)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmax_drop = min_drop;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (drop_dist > max_drop)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsticking = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (sticking)\r\n\t\t\t\t{    \r\n\t\t\t\t\t//new_normal(normal);\r\n\t\t\t\t\tm_current_normal = normal;\t  \t\t\t\t\t\t\t\t\t\t// remember this, for detecting if it changes\r\n\t\t\r\n\t\t\t\t\tGetObject()->m_matrix[Y] = normal;\r\n\t\t\t\t\tGetObject()->m_matrix.OrthoNormalizeAbout(Y);\t\t\t\t\t\t\t\t\t// set regular normal immediately\r\n\t\t\t\t}\t\t \r\n\t\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\t}\r\n\t\t\t\t\t\r\n\t\tif (sticking)\r\n\t\t{\t\r\n\t\t\t// if there is a collision, then snap to it\r\n\t\t\tGetObject()->m_pos = feeler.GetPoint();\r\n\t\t}\r\n\t}\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCRailNode*\tCSkaterNonLocalNetLogicComponent::travel_on_rail( CRailNode* start_node, float frame_length )\r\n{\r\n\tbool on_rail;\r\n\r\n\tDbg_Assert( start_node );\r\n\r\n\ton_rail = true;\r\n\r\n\tCRailManager* p_rail_man = Mdl::Skate::Instance()->GetRailManager();\r\n\r\n\tconst CRailNode* pStart = start_node;\r\n\tconst CRailNode* pEnd = pStart->GetNextLink();\r\n\tif( pEnd == NULL )\r\n\t{\r\n\t\tDbg_MsgAssert(pEnd,(\"NonLocal Skater on Rail node (%d) with no next link\\n\",start_node->GetNode()));\r\n\t\treturn NULL;\r\n\t}\r\n\t\r\n\t//const CRailNode* pFrom = pStart;\r\n\tconst CRailNode* pOnto = NULL;\r\n\t\r\n\tMth::Vector\tdir = p_rail_man->GetPos(pEnd) - p_rail_man->GetPos(pStart);\r\n\tfloat segment_length = dir.Length();\r\n\tdir *= (1.0f / segment_length);\r\n\r\n\t// sign is which way we are going along the rail\r\n\t//float old_sign = Mth::Sgn(Mth::DotProduct(dir, GetObject()->m_vel));\r\n\r\n\t// Get gravity force \t\r\n\tMth::Vector gravity(0.0f, GetPhysicsFloat(CRCD(0xd1f46992, \"Physics_Rail_Gravity\")), 0.0f);\r\n\r\n\t// Project gravity onto the line we are on\r\n\tgravity.ProjectToNormal(dir);\r\n\tGetObject()->m_vel += gravity * frame_length;\r\n\t\r\n\t// sign is which way we are going along the rail\r\n\tfloat sign = Mth::Sgn(Mth::DotProduct(dir, GetObject()->m_vel));\r\n\t\r\n\t// check to see if we are on the last segment of the rail\r\n\t// this logic could be folded into the logic below but it's perhps clearer to have it here\r\n\tbool last_segment = false;\r\n\tif (sign < 0.0f)\r\n\t{\r\n\t\tif (pStart->GetPrevLink() && pStart->GetPrevLink()->IsActive())\r\n\t\t{\r\n\t\t\tMth::Vector v1, v2;\r\n\t\t\tv1 = p_rail_man->GetPos(pEnd) - p_rail_man->GetPos(pStart);\r\n\t\t\tv2 = p_rail_man->GetPos(pStart) - p_rail_man->GetPos(pStart->GetPrevLink());\r\n\t\t\tv1[Y] = 0.0f;\r\n\t\t\tv2[Y] = 0.0f;\r\n\t\t\tv1.Normalize();\r\n\t\t\tv2.Normalize();\r\n\t\t\tfloat dot = Mth::DotProduct(v1, v2);\r\n\t\t\tif (dot < cosf(Mth::DegToRad(GetPhysicsFloat(CRCD(0x76c1da15, \"Rail_Corner_Leave_Angle\")))))\r\n\t\t\t{\r\n\t\t\t\t// there is more, but angle is too sharp\r\n\t\t\t\tlast_segment = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpOnto = pStart->GetPrevLink();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tlast_segment = true;\t\t\t\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (pEnd && pEnd->GetNextLink() && pEnd->GetNextLink()->IsActive())\r\n\t\t{\r\n\t\t\tMth::Vector  v1,v2;\r\n\t\t\tv1 = p_rail_man->GetPos(pStart) - p_rail_man->GetPos(pEnd);\r\n\t\t\tv2 = p_rail_man->GetPos(pEnd) - p_rail_man->GetPos(pEnd->GetNextLink());\r\n\t\t\tv1[Y] = 0.0f;\r\n\t\t\tv2[Y] = 0.0f;\r\n\t\t\tv1.Normalize();\r\n\t\t\tv2.Normalize();\r\n\t\t\tfloat dot = Mth::DotProduct(v1,v2);\r\n\t\t\tif (dot < cosf(Mth::DegToRad(GetPhysicsFloat(CRCD(0x76c1da15,\"Rail_Corner_Leave_Angle\")))))\r\n\t\t\t{\r\n\t\t\t\t// there is more, but angle is too sharp\r\n\t\t\t\tlast_segment = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpOnto = pEnd;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tlast_segment = true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Now we need to see if we have gone beyond the end of the rail segment\r\n\t\r\n\tfloat extra_dist = 0.0f;\r\n\t\t\r\n\tfloat length_along;\r\n\tif (sign < 0.0f)\r\n\t{\r\n\t\t// going backwards, so it's the distance from the end of the segment\r\n\t\tlength_along = (GetObject()->m_pos - p_rail_man->GetPos(pEnd)).Length();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// going forwards, so it's the distance from the start\r\n\t\tlength_along = (GetObject()->m_pos - p_rail_man->GetPos(pStart)).Length();\r\n\t}\r\n\t\r\n\tif (length_along > segment_length + 0.1f)\t// 0.1 inch, so we don't get stuck\r\n\t{\r\n\t\t// remember this, so we can move along next segment\r\n\t\textra_dist = length_along - segment_length;\r\n\t\t\r\n\t\t// gone off the end of the segment\r\n\t\tif (sign < 0.0f)\r\n\t\t{\r\n\t\t\tif (pStart->GetPrevLink()\r\n\t\t\t\t&& pStart->GetPrevLink()->IsActive()\r\n\t\t\t\t&& Rail_ValidInEditor(p_rail_man->GetPos(pStart), p_rail_man->GetPos(pStart->GetPrevLink())))\r\n\t\t\t{\r\n\t\t\t\tif (!last_segment)\r\n\t\t\t\t{\r\n\t\t\t\t\t// go onto previous segment\r\n\t\t\t\t\tGetObject()->m_pos = p_rail_man->GetPos(pStart);\r\n\t\t\t\t\tstart_node = (CRailNode*) pStart->GetPrevLink();\r\n\t\t\t\t\t//set_terrain(start_node->GetTerrain());\r\n\t\t\t\t\t//maybe_trip_rail_trigger(TRIGGER_SKATE_ONTO);\r\n\t\t\t\t}\t\t   \r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t//skate_off_rail(p_rail_man->GetPos(pStart));\r\n\t\t\t\t\ton_rail = false;\r\n\t\t\t\t} \t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//skate_off_rail(p_rail_man->GetPos(pStart));\r\n\t\t\t\ton_rail = false;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (pEnd->GetNextLink()\r\n\t\t\t\t&& pEnd->IsActive()\r\n\t\t\t\t&& Rail_ValidInEditor(p_rail_man->GetPos(pEnd), p_rail_man->GetPos(pEnd->GetNextLink())))\r\n\t\t\t{\r\n\t\t\t\tif (!last_segment)\r\n\t\t\t\t{\r\n\t\t\t\t\tGetObject()->m_pos = p_rail_man->GetPos(pEnd);\r\n\t\t\t\t\tstart_node = (CRailNode*) pEnd;\t\t\t\t\t\r\n\t\t\t\t\t//set_terrain(start_node->GetTerrain());\r\n\t\t\t\t\t//maybe_trip_rail_trigger(TRIGGER_SKATE_ONTO);\t\t\t\t\t\t\r\n\t\t\t\t}\t\t   \r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t//skate_off_rail(p_rail_man->GetPos(pEnd));\r\n\t\t\t\t\ton_rail = false;\r\n\t\t\t\t} \t\t\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//skate_off_rail(p_rail_man->GetPos(pEnd));\r\n\t\t\t\ton_rail = false;\r\n\t\t\t}\r\n\t\t}\t\t\r\n\t}\r\n\t\r\n\tif( on_rail ) // If still on the rail     GetState() == RAIL)\r\n\t{\r\n\t\t// recalculate start, end, dir, as we might be on a new segment\r\n\t\tconst CRailNode* pStart = start_node;\r\n\t\tconst CRailNode* pEnd = pStart->GetNextLink();\r\n\t\t\r\n\t\tMth::Vector\tdir = p_rail_man->GetPos(pEnd) - p_rail_man->GetPos(pStart);\r\n\t\tdir.Normalize();\r\n\r\n\t\t// sign also may have changed, now that we are auto-linking rail segments\r\n\t\t\r\n\t\t// sign is which way we are going along the rail\r\n\t\tfloat sign = Mth::Sgn(Mth::DotProduct(dir,GetObject()->m_vel));\r\n\r\n\t\t//m_rail_time = Tmr::GetTime();\r\n\t\t\t\t\t\t\t\r\n\t\tGetObject()->m_vel.RotateToNormal(dir);\r\n\t\tGetObject()->m_vel *= sign;\t\t\t\t\t\t   \t\t\t\t\t\t// sign won't be on a new segment\r\n\r\n\t\t//float facing_sign = mRail_Backwards ? -sign : sign;\r\n\t\tfloat facing_sign = sign;\r\n\t\t\r\n\t\t// z is forward\r\n\t\tMth::Vector target_forward = dir * facing_sign;\r\n\r\n\t\t//m_lerping_display_matrix[Z] = Mth::Lerp(m_lerping_display_matrix[Z], target_forward, 0.3f);\r\n\t\t//m_lerping_display_matrix[Z].Normalize(); \r\n\t\t\r\n\t\t#if 0 // old code\r\n\t\t// m_lerping_display_matrix[Y].Set(0.0f, 1.0f, 0.0f);\r\n\t\t// m_lerping_display_matrix[X] = Mth::CrossProduct(\r\n\t\t\t// m_lerping_display_matrix[Y],\r\n\t\t\t// m_lerping_display_matrix[Z]\r\n\t\t// );\r\n\t\t#else\r\n\t\t//m_lerping_display_matrix[X].Set(\r\n\t\t\t//m_lerping_display_matrix[Z][Z],\r\n\t\t\t//0.0f,\r\n\t\t\t//-m_lerping_display_matrix[Z][X],\r\n\t\t\t//0.0f\r\n\t\t//);\r\n\t\t#endif\r\n\t\t//m_lerping_display_matrix[X].Normalize();\r\n\t\t\r\n\t\t//m_lerping_display_matrix[Y] = Mth::CrossProduct(\r\n\t\t\t//m_lerping_display_matrix[Z],\r\n\t\t\t//m_lerping_display_matrix[X]\r\n\t\t//);\r\n\t\t//m_lerping_display_matrix[Y].Normalize();\r\n\r\n\t\t// adjust our Z value towards the new value\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\tGetObject()->m_matrix[Z] = target_forward;\r\n\t\tGetObject()->m_matrix[Z].Normalize(); \r\n\t\t\r\n\t\t#if 0 // old code\r\n\t\t// GetObject()->m_matrix[Y].Set(0.0f, 1.0f, 0.0f);\r\n\t\t// GetObject()->m_matrix[X] = Mth::CrossProduct(GetObject()->m_matrix[Y],GetObject()->m_matrix[Z]);\r\n\t\t#else\r\n\t\tGetObject()->m_matrix[X].Set(\r\n\t\t\tGetObject()->m_matrix[Z][Z],\r\n\t\t\t0.0f,\r\n\t\t\t-GetObject()->m_matrix[Z][X],\r\n\t\t\t0.0f\r\n\t\t);\r\n\t\t#endif\r\n\t\tGetObject()->m_matrix[X].Normalize();\r\n\t\t\r\n\t\tGetObject()->m_matrix[Y] = Mth::CrossProduct(GetObject()->m_matrix[Z], GetObject()->m_matrix[X]);\r\n\t\tGetObject()->m_matrix[Y].Normalize();\r\n\r\n        // This is where we do the actual movement\r\n\t\t// if this makes us bump into the wall or the ground, then we should leave the rail\r\n\t\tGetObject()->m_pos += GetObject()->m_vel * frame_length;\t\t\t// current movement\r\n\t\tGetObject()->m_pos += extra_dist * target_forward;\t\t\t\t\t\t// any extra dist from previous segment\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\treturn start_node;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterNonLocalNetLogicComponent::extrapolate_rail_position( void )\r\n{\r\n\tGameNet::Manager* gamenet_man =  GameNet::Manager::Instance();\r\n\tCRailManager* p_rail_man = Mdl::Skate::Instance()->GetRailManager();\r\n\tCRailNode* start_node;\r\n\tint i, prev_index, most_recent_index, mag_index;\r\n\tSPosEvent* p_pos_history;\r\n\tunsigned int delta_t, net_lag;\r\n\tfloat coeff, ratio, total_mag, total_ratio, total_coeff, vel_mag, frame_length;\r\n\tGameNet::PlayerInfo* local_player;\r\n\tNet::Client* client;\r\n\tMth::Vector vel;\r\n\r\n\tclient = gamenet_man->GetClient( 0 );\r\n\r\n\tp_pos_history = mp_state_history_component->GetPosHistory();\r\n\tmost_recent_index = ( mp_state_history_component->GetNumPosUpdates() - 1 ) % CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\tprev_index = ( m_last_pos_index + ( CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS - 1 )) % CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\t\r\n\tdelta_t = (int) ( m_frame_length * Tmr::vRESOLUTION );\r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\tGameNet::PlayerInfo* player;\r\n\t\tNet::Conn* client_conn;\r\n\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( GetObject()->GetID());\r\n\t\tDbg_Assert( player );\r\n\t\tclient_conn = player->m_Conn;\r\n\t\tnet_lag = client_conn->GetAveLatency();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tLst::Search< Net::Conn > sh;\r\n\t\tNet::Conn* server_conn;\r\n\r\n\t\tserver_conn = client->FirstConnection( &sh );\r\n\t\tnet_lag = server_conn->GetAveLatency();\r\n\t}\r\n\r\n\t// protect against dbz\r\n\tif( delta_t == 0 )\r\n\t{\r\n\t\tratio = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tratio = (float) ( net_lag - delta_t ) / (float) delta_t;\r\n\t\tif( ratio < 0 )\r\n\t\t{\r\n\t\t\tratio = 0;\r\n\t\t}\r\n\t}\r\n\t\r\n\tmag_index = m_num_mags % vMAG_HISTORY_LENGTH;\r\n\tvel = m_interp_pos - m_old_interp_pos;\r\n\r\n\tcoeff = 0.0f;\r\n\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\tif( local_player )\r\n\t{\r\n\t\tMth::Vector my_vel, their_vel;\r\n\r\n\t\tmy_vel = local_player->m_Skater->GetVel();\r\n\t\ttheir_vel = vel;\r\n\r\n\t\tmy_vel.Normalize();\r\n\t\ttheir_vel.Normalize();\r\n\r\n\t\t// Get the dot product of our movement vectors\r\n\t\tcoeff = Mth::DotProduct( my_vel, their_vel );\r\n\r\n\t\t// This will result in a value between -1.0f and 1.0f. Adding one will make that\r\n\t\t// between 0 and 2\r\n\t\tcoeff += 1.0f;\r\n\r\n\t\t// We want a value between 0 and 1, so divide by 2\r\n\t\tcoeff /= 2.0f;\r\n\t}\r\n\r\n\tm_mag_history[mag_index] = ( vel.Length() / delta_t ) * 16;\r\n\tm_ratio_history[mag_index] = ratio;\r\n\tm_extrap_coeff_history[mag_index] = coeff;\r\n\tm_num_mags++;\r\n\r\n\ttotal_mag = 0;\r\n\ttotal_ratio = 0;\r\n\ttotal_coeff = 0;\r\n\tfor( i = 0; i < vMAG_HISTORY_LENGTH; i++ )\r\n\t{\r\n\t\tif( i >= m_num_mags )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\ttotal_mag += m_mag_history[i];\r\n\t\ttotal_ratio += m_ratio_history[i];\r\n\t\ttotal_coeff += m_extrap_coeff_history[i];\r\n\t\t\r\n\t}\r\n\tvel_mag = total_mag / i;\r\n\tcoeff = total_coeff / i;\r\n\tratio = total_ratio / i;\r\n\tratio *= coeff;\r\n\r\n\tvel.Normalize();\r\n\tvel *= vel_mag;\r\n\t\r\n\tframe_length = m_frame_length * ratio;\r\n\t// Sanity check to avoid infinite loops\r\n\tif( frame_length > 1.0f )\r\n\t{\r\n\t\tframe_length = 1.0f;\r\n\t}\r\n\tstart_node = p_rail_man->GetRailNodeByNodeNumber( p_pos_history[m_last_pos_index].RailNode );\r\n\tif( start_node )\r\n\t{\r\n\t\twhile( frame_length > 0 )\r\n\t\t{\r\n\t\t\tif( frame_length > m_frame_length )\r\n\t\t\t{\r\n\t\t\t\tstart_node = travel_on_rail( start_node, m_frame_length );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tstart_node = travel_on_rail( start_node, frame_length );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// If we grinded off a rail, use standard extrapolation instead.\r\n\t\t\tif( start_node == NULL )\r\n\t\t\t{\r\n\t\t\t\tGetObject()->m_pos = m_interp_pos;\r\n\t\t\t\textrapolate_position();\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tframe_length -= m_frame_length;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CSkaterNonLocalNetLogicComponent::rotate_away_from_wall ( Mth::Vector normal, float &turn_angle )\r\n{\r\n\tfloat lerp;\r\n\r\n\tlerp = 1.0f;\r\n\t// given a wall normal, then calculate the \"turn_angle\" to rotate the skater by and rotate the matrix and display matrix by this\r\n\t// return the angle between the skater and the wall\r\n\t// note turn_angle is passed by reference, and is altered !!!!\r\n\t\r\n\t// given m_right(dot)normal, we should be able to get a nice angle\r\n\tfloat dot_right_normal = Mth::DotProduct(GetObject()->m_matrix[X], normal);\r\n\r\n\tfloat angle = acosf(Mth::Clamp(dot_right_normal, -1.0f, 1.0f)); \t\r\n\r\n\tif (angle > Mth::PI / 2.0f)\r\n\t{\r\n\t\tangle -= Mth::PI;\r\n\t}\r\n\t\r\n\t// angle away from the wall\r\n\tturn_angle = angle * GetPhysicsFloat(CRCD(0xe07ee1a9, \"Wall_Bounce_Angle_Multiplier\")) * lerp;\r\n\t\r\n\t// Rotate the skater so he is at a slight angle to the wall, especially if we are in a right angled corner, where the skater will bounce out\r\n\r\n\tGetObject()->m_vel.RotateY(turn_angle);\r\n\tGetObject()->m_matrix.RotateYLocal(turn_angle);\r\n\t\r\n\treturn angle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterNonLocalNetLogicComponent::bounce_off_wall ( const Mth::Vector& normal, const Mth::Vector& point )\r\n{\r\n\t// Given the normal of the wall, then bounce off it, turning the skater away from the wall\r\n\tMth::Vector col_start, col_end;\r\n\tMth::Vector\tforward = GetObject()->m_pos - m_old_extrap_pos;\r\n\tMth::Vector movement = forward;\t\t\t\t   \t\t// remember how far we moved\r\n\tCFeeler feeler;\r\n\r\n    forward.Normalize();\r\n\t\r\n\tMth::Vector up_offset = GetObject()->m_matrix[Y] * GetPhysicsFloat(CRCD(0xd4205c9b,\"Skater_First_Forward_Collision_Height\"));\r\n\r\n\tfloat turn_angle;\r\n\tfloat angle = rotate_away_from_wall(normal, turn_angle);\r\n\r\n\tfloat min = Mth::DegToRad(GetPhysicsFloat(CRCD(0x1483fd01, \"Wall_Bounce_Dont_Slow_Angle\"))); \r\n\t\t\t\t\t \t\t\t\t\t\t\t\r\n\tif (Mth::Abs(angle) > min)\r\n\t{\r\n\t\t//float old_speed = GetObject()->m_vel.Length();\r\n\t\t\r\n\t\t// The maximum value of Abs(angle) would be PI/2 (90 degrees), so scale the velocity \r\n\t\tfloat x = Mth::Abs(angle) - min;\r\n\t\tx /= (Mth::PI / 2.0f) - min;\t\t// get in the range 0 .. 1\r\n\t\tx = 1.0f - x; \t\t\t\t\t\t// invert, as we want to stop when angle is 90\r\n\t\t\r\n\t\tGetObject()->m_vel *= x;\r\n\t}\r\n\t\r\n\t// Bit of a patch here to move the skater away from the wall\r\n\t// Not needed so much with new sideways collision checks but we keep it in for low ledges.\r\n\t// Should perhaps standardize the height so collision checks for side and front but we'd probably still have problems.\r\n\t\r\n\tGetObject()->m_pos = point - up_offset;\r\n\tGetObject()->m_pos += normal * 6.0f;\r\n\t\r\n\t// Now the majority of cases have been taken care of; we need to see if the skater is going to get stuck in a corner.\r\n\r\n\tfloat old_speed = movement.Length();\t\t \t\t\t\t\t// get how much we moved last time\r\n\tMth::Vector next_movement = GetObject()->m_vel;\t\t\t\t\t// get new direction of velocity\r\n\tforward = GetObject()->m_vel;\r\n\tforward.Normalize();\r\n\tnext_movement = forward * old_speed;\t\t\t\t\t\t\t// extend by same movment as last time\r\n\t\r\n\tcol_start = GetObject()->m_pos + up_offset;\r\n\tcol_start += up_offset;\r\n\t\r\n\tcol_end = GetObject()->m_pos + up_offset + next_movement\r\n\t\t+ forward * GetPhysicsFloat(CRCD(0x20102726, \"Skater_First_Forward_Collision_Length\"));\r\n\t\r\n\t// Sanity check to make sure we're not using a line that's a whole level long\r\n\tif(( col_start - col_end ).Length() > FEET( 20 ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tfeeler.SetLine( col_start, col_end );\r\n\tfeeler.SetIgnore( mFD_NON_COLLIDABLE, 0 );\r\n\tif( feeler.GetCollision() && GetSkater()->IsLocalClient())\r\n\t{\r\n\t\t// Just rotating the skater will lead to another collision, so try just inverting the skater's velocity from it's original and halving it....\r\n\t\t\r\n\t\t// First reverse the rotation, and rotate 180 degrees\r\n\t\tGetObject()->m_vel.RotateY(Mth::DegToRad(180.0f) - turn_angle);\r\n\t\tGetObject()->m_matrix.RotateYLocal(Mth::DegToRad(180.0f) - turn_angle);\r\n\t\t//ResetLerpingMatrix();\r\n\t\t\r\n\t\tGetObject()->m_vel *= 0.5f; \r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterNonLocalNetLogicComponent::extrapolate_position( void )\r\n{\r\n\tGameNet::Manager* gamenet_man =  GameNet::Manager::Instance();\r\n\tint i, prev_index, most_recent_index, mag_index;\r\n\tSPosEvent* p_pos_history;\r\n\tunsigned int delta_t, net_lag;\r\n\tfloat coeff, ratio, total_mag, total_ratio, total_coeff, vel_mag;\r\n\tMth::Vector extrap_pos;\r\n\tGameNet::PlayerInfo* local_player;\r\n\tMth::Vector vel;\r\n\tNet::Client* client;\r\n\r\n\tclient = gamenet_man->GetClient( 0 );\r\n\t\t\r\n\tp_pos_history = mp_state_history_component->GetPosHistory();\r\n\tmost_recent_index = ( mp_state_history_component->GetNumPosUpdates() - 1 ) % CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\tprev_index = ( m_last_pos_index + ( CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS - 1 )) % CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\t\r\n\tdelta_t = (int) ( m_frame_length * Tmr::vRESOLUTION );\r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\tGameNet::PlayerInfo* player;\r\n\t\tNet::Conn* client_conn;\r\n\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( GetObject()->GetID());\r\n\t\tDbg_Assert( player );\r\n\t\tclient_conn = player->m_Conn;\r\n\t\tnet_lag = client_conn->GetAveLatency();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tLst::Search< Net::Conn > sh;\r\n\t\tNet::Conn* server_conn;\r\n\r\n\t\tserver_conn = client->FirstConnection( &sh );\r\n\t\tnet_lag = server_conn->GetAveLatency();\r\n\t}\r\n\r\n\t// protect against dbz\r\n\tif( delta_t == 0 )\r\n\t{\r\n\t\tratio = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tratio = (float) ( net_lag - delta_t ) / (float) delta_t;\r\n\t\tif( ratio < 0 )\r\n\t\t{\r\n\t\t\tratio = 0;\r\n\t\t}\r\n\t}\r\n\t\r\n\tmag_index = m_num_mags % vMAG_HISTORY_LENGTH;\r\n\tvel = m_interp_pos - m_old_interp_pos;\r\n\r\n\tcoeff = 0.0f;\r\n\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\tif( local_player && local_player->m_Skater )\r\n\t{\r\n\t\tMth::Vector my_vel, their_vel;\r\n\r\n\t\tmy_vel = local_player->m_Skater->GetVel();\r\n\t\ttheir_vel = vel;\r\n\r\n\t\tmy_vel.Normalize();\r\n\t\ttheir_vel.Normalize();\r\n\r\n\t\t// Get the dot product of our movement vectors\r\n\t\tcoeff = Mth::DotProduct( my_vel, their_vel );\r\n\r\n\t\t// This will result in a value between -1.0f and 1.0f. Adding one will make that\r\n\t\t// between 0 and 2\r\n\t\tcoeff += 1.0f;\r\n\r\n\t\t// We want a value between 0 and 1, so divide by 2\r\n\t\tcoeff /= 2.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcoeff = 0.0f;\r\n\t}\r\n\r\n\tm_mag_history[mag_index] = ( vel.Length() / delta_t ) * 16;\r\n\tm_ratio_history[mag_index] = ratio;\r\n\tm_extrap_coeff_history[mag_index] = coeff;\r\n\tm_num_mags++;\r\n\r\n\ttotal_mag = 0;\r\n\ttotal_ratio = 0;\r\n\ttotal_coeff = 0;\r\n\tfor( i = 0; i < vMAG_HISTORY_LENGTH; i++ )\r\n\t{\r\n\t\tif( i >= m_num_mags )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\ttotal_mag += m_mag_history[i];\r\n\t\ttotal_ratio += m_ratio_history[i];\r\n\t\ttotal_coeff += m_extrap_coeff_history[i];\r\n\t\t\r\n\t}\r\n\tvel_mag = total_mag / i;\r\n\tcoeff = total_coeff / i;\r\n\tratio = total_ratio / i;\r\n\tratio *= coeff;\r\n\r\n\tvel.Normalize();\r\n\tvel *= vel_mag;\r\n\t\r\n\textrap_pos = GetObject()->m_pos + ( vel * ratio );\r\n\textrap_pos[Y] = GetObject()->m_pos[Y];\r\n\tGetObject()->m_pos = extrap_pos;\r\n\t\r\n\tMth::Vector up_offset = GetObject()->m_matrix[Y] * GetPhysicsFloat(CRCD(0xd4205c9b, \"Skater_First_Forward_Collision_Height\"));\r\n\r\n\tMth::Vector col_start = m_interp_pos + up_offset;\r\n\tMth::Vector col_end = GetObject()->m_pos + up_offset;\r\n\r\n\tCFeeler feeler;\r\n\r\n\t// Sanity check to make sure we're not using a line that's a whole level long\r\n\tif(( col_start - col_end ).Length() > FEET( 10 ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tfeeler.SetLine( col_start, col_end );\r\n\tfeeler.SetIgnore( mFD_NON_COLLIDABLE, 0 );\r\n\r\n\tif( feeler.GetCollision())\r\n\t{\r\n\t\tbounce_off_wall( feeler.GetNormal(), feeler.GetPoint());\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterNonLocalNetLogicComponent::extrapolate_client_position (   )\r\n{\r\n\tif( mp_state_history_component->GetNumPosUpdates() >= CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS )\r\n\t{\r\n\t\tif( mp_state_component->GetState() == RAIL )\r\n\t\t{\r\n\t\t\textrapolate_rail_position();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\textrapolate_position();\r\n\t\t\tsnap_to_ground();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterNonLocalNetLogicComponent::interpolate_client_position (   )\r\n{\r\n\tGameNet::Manager* gamenet_man =  GameNet::Manager::Instance();\r\n\tNet::Client* client;\r\n\t\r\n\tSPosEvent* p_pos_history = mp_state_history_component->GetPosHistory();\r\n\r\n\tif(( client = gamenet_man->GetClient( 0 )))\r\n\t{   \r\n\t\t// Wait for the object update buffer to fill up\r\n\t\tif( mp_state_history_component->GetNumPosUpdates() >= CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS )\r\n\t\t{\r\n\t\t\tunsigned int cur_time;\r\n\t\t\tint i, prev_index, start_index, total_t, delta_t;\r\n\t\t\tfloat ratio;\r\n\t\t\tMth::Vector delta_pos;\r\n            \r\n\t\t\t// This will be true only if we've never performed an interpolation\r\n\t\t\tif( m_client_initial_update_time == 0 )\r\n\t\t\t{\r\n\t\t\t\t//Dbg_Printf( \"Resync'd Skater %d\\n\", GetID() );\r\n\t\t\t\t// start off at the latest update and offset ourselves backwards in time from there\r\n\t\t\t\tstart_index = ( mp_state_history_component->GetNumPosUpdates() - 1 ) % CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\t\t\t\t\r\n\t\t\t\tm_client_initial_update_time = client->m_Timestamp;\r\n\t\t\t\t// impose a lag of N frames\r\n\t\t\t\tm_server_initial_update_time = p_pos_history[start_index].GetTime() - Tmr::VBlanksF( vNUM_LAG_FRAMES );\r\n\t\t\t\tm_last_pos_index = start_index;\r\n                \r\n\t\t\t\t//Dbg_Printf( \"(%d) server initial time = %d\\n\", nonlocalnet->m_FrameCounter, (int) m_server_initial_update_time );\r\n\t\t\t\t//Dbg_Printf( \"(%d) nonlocalnet initial time = %d\\n\", nonlocalnet->m_FrameCounter, (int) m_client_initial_update_time );\r\n\t\t\t\t\r\n                GetObject()->SetMatrix( p_pos_history[start_index].Matrix );\r\n\t\t\t\tGetObject()->SetDisplayMatrix( p_pos_history[start_index].Matrix );\r\n\t\t\t\tGetObject()->SetPos(p_pos_history[start_index].Position);\r\n\t\t\t\tGetObject()->SetTeleported(); \r\n\t\t\t\tGetObject()->m_vel.Set(0.0f, 0.0f, 0.0f);\r\n\r\n\t\t\t\t// We don't want to actually render the skaters until we have buffered\r\n\t\t\t\t// up their position updates and are ready to start interpolating. Now we have\r\n\t\t\t\t// that data, so add them to the world\r\n\t\t\t\tif( !GetSkater()->IsInWorld())\r\n\t\t\t\t{\r\n\t\t\t\t\tGameNet::PlayerInfo* player;\r\n                    \r\n\t\t\t\t\tGetSkater()->AddToCurrentWorld();\r\n\t\t\t\t\tScript::RunScript( \"NetIdle\", NULL, GetObject() );\r\n\t\t\t\t\t//Hide( false );\r\n\t\t\t\t\tplayer = gamenet_man->GetPlayerByObjectID( GetObject()->GetID() );\r\n\t\t\t\t\tDbg_Assert( player );\r\n\t\t\t\t\t\r\n                    // We're just adding them to the world.  If they were standing still,\r\n\t\t\t\t\t// UberFrig would not have been done. So let's do it here\r\n\t\t\t\t\tsetup_brightness_and_shadow();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{   \r\n\t\t\t\tMth::SlerpInterpolator slerp;\r\n\r\n\t\t\t\tMth::Matrix interp_matrix;\r\n\t\t\t\tint most_recent_index, flag;\r\n\t\t\t\tGameNet::PlayerInfo* player;\r\n\t\t\t\t\r\n\t\t\t\t// Maybe a little bit overkill, but this will definitely set skaters that we can\r\n\t\t\t\t// see in the level to be \"fully in\", which triggers things like their names in\r\n\t\t\t\t// the score list\r\n\t\t\t\tplayer = gamenet_man->GetPlayerByObjectID( GetObject()->GetID() );\r\n\t\t\t\tif( !player->IsFullyIn())\r\n\t\t\t\t{\r\n\t\t\t\t\tplayer->MarkAsFullyIn();\r\n\t\t\t\t}\r\n\r\n\t\t\t\tstart_index = mp_state_history_component->GetNumPosUpdates() % CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\t\t\t\tmost_recent_index = ( mp_state_history_component->GetNumPosUpdates() - 1 ) % CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\t\t\t\t\r\n\t\t\t\tcur_time = m_server_initial_update_time + ( client->m_Timestamp - m_client_initial_update_time );\r\n\r\n\t\t\t\t// If we've gone past the most recent update, slow down a little to allow updates\r\n\t\t\t\t// to catch up\r\n\t\t\t\t//Dbg_Printf( \"(%d) NonLocalNet Timestamp %d\\n\", nonlocalnet->m_FrameCounter, nonlocalnet->m_Timestamp );\r\n\t\t\t\tif( cur_time > p_pos_history[most_recent_index].GetTime())\r\n\t\t\t\t{\r\n\t\t\t\t\t// If we have some major catching up to do (usually at the beginning\r\n\t\t\t\t\t// when there are long pauses after loading) catch up in one step\r\n\t\t\t\t\tif(( cur_time - p_pos_history[most_recent_index].GetTime()) > Tmr::Seconds( 1 ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//Dbg_Printf( \"************************ (%d) Major catchup\\n\", client->m_FrameCounter );\r\n\t\t\t\t\t\tm_server_initial_update_time -= ( cur_time - p_pos_history[most_recent_index].GetTime());\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//Dbg_Printf( \"************************ (%d) (%d) Slowdown\\n\", GetObject()->GetID(), client->m_FrameCounter );\r\n\t\t\t\t\t\tm_server_initial_update_time -= Tmr::VBlanks( 1 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tcur_time = m_server_initial_update_time + ( client->m_Timestamp - m_client_initial_update_time );\r\n\t\t\t\t\t//Dbg_Printf( \"- Slowdown\\n\" );\r\n\t\t\t\t}\r\n\r\n\t\t\t\ti = start_index;\r\n\t\t\t\tdo\t\t\t\t\t\t\t   \r\n\t\t\t\t{   \r\n\t\t\t\t\tif( cur_time <= p_pos_history[i].GetTime()) \r\n\t\t\t\t\t{\t\t\t\t\t\t \r\n\t\t\t\t\t\tstatic int lag = 0;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tm_last_pos_index = i;\r\n\t\t\t\t\t\tlag = ( start_index + (CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS - i )) % CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// We probably also should adjust if we get too far behind\r\n\t\t\t\t\t\tif( lag >= 10 )\r\n\t\t\t\t\t\t{   \r\n\t\t\t\t\t\t\t//Dbg_Printf( \"************************ (%d) (%d) +7 Catchup. Lag : %d\\n\", client->m_FrameCounter, GetObject()->GetID(), lag );\r\n\t\t\t\t\t\t\tm_server_initial_update_time += Tmr::VBlanks( 10 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse if( lag == 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t//Dbg_Printf( \"************************ (%d) Resync'ing skater %d\\n\", client->m_FrameCounter, GetObject()->GetID() );\r\n\t\t\t\t\t\t\tGetSkater()->Resync();\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tprev_index = ( i + ( CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS - 1 )) % CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tdelta_t = cur_time - p_pos_history[prev_index].GetTime();\r\n\t\t\t\t\t\ttotal_t = p_pos_history[i].GetTime() - p_pos_history[prev_index].GetTime();\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tratio = (float) delta_t / (float) total_t;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tdelta_pos = p_pos_history[i].Position - p_pos_history[prev_index].Position;\r\n\r\n\t\t\t\t\t\tm_old_interp_pos = m_interp_pos;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// Slerp between the two matrices\r\n\t\t\t\t\t\tMth::Matrix t1, t2;\r\n\t\t\t\t\t\tMth::Vector diff;\r\n\r\n\t\t\t\t\t\tdiff = p_pos_history[i].Matrix[Z] - p_pos_history[prev_index].Matrix[Z];\r\n\t\t\t\t\t\t// Don't slerp if the matrices are way different. Just stick with the matrix\r\n\t\t\t\t\t\t// we have until the switch is made. \r\n\t\t\t\t\t\tif( diff.Length() > 0.75f )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tGetObject()->SetMatrix( p_pos_history[prev_index].Matrix );\r\n\t\t\t\t\t\t\tGetObject()->SetDisplayMatrix( p_pos_history[prev_index].Matrix );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tt1 = p_pos_history[prev_index].Matrix;\r\n\t\t\t\t\t\t\tt2 = p_pos_history[i].Matrix;\r\n\t\t\t\t\t\t\tslerp.setMatrices( &t1, &t2 );\r\n\t\t\t\t\t\t\tslerp.getMatrix( &interp_matrix, ratio );\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tGetObject()->SetMatrix( interp_matrix );\r\n\t\t\t\t\t\t\tGetObject()->SetDisplayMatrix( interp_matrix );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif( delta_pos.Length() > FEET( 50 ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tGetObject()->m_pos = p_pos_history[i].Position;\r\n\t\t\t\t\t\t\tGetObject()->m_vel = Mth::Vector( 0, 0, 0 );\r\n\t\t\t\t\t\t\tGetObject()->SetTeleported();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tint idx, mag_index;\r\n\t\t\t\t\t\t\tMth::Vector total_vel;\r\n\r\n\t\t\t\t\t\t\tGetObject()->m_pos = p_pos_history[prev_index].Position + ( delta_pos * ratio );\r\n\t\t\t\t\t\t\tGetObject()->m_vel = ( GetObject()->m_pos - m_old_interp_pos ) / m_frame_length; // do_nonlocalnet_position_update, calculating speed\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tmag_index = m_num_mags % vMAG_HISTORY_LENGTH;\r\n\r\n\t\t\t\t\t\t\t// Smooth out changes in velocity\r\n\t\t\t\t\t\t\tm_vel_history[mag_index] = GetObject()->m_vel;\r\n\t\t\t\t\t\t\tfor( idx = 0; idx < vMAG_HISTORY_LENGTH; idx++ )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif( idx >= m_num_mags )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\ttotal_vel += m_vel_history[idx];\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tif( idx > 0 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tGetObject()->m_vel = total_vel / idx;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tm_interp_pos = GetObject()->m_pos;\r\n\r\n\t\t\t\t\t\t// Apply the state/flag data from this PosEvent\r\n\t\t\t\t\t\tmp_state_component->m_state = static_cast< EStateType >( p_pos_history[i].State );\r\n\t\t\t\t\t\tmp_state_component->m_doing_trick = p_pos_history[i].DoingTrick;\r\n\t\t\t\t\t\tmp_state_component->m_terrain = p_pos_history[i].Terrain;\r\n\t\t\t\t\t\tmp_state_component->m_physics_state = p_pos_history[i].Walking ? WALKING : SKATING;\r\n\t\t\t\t\t\tmp_state_component->m_driving = p_pos_history[i].Driving;\r\n\t\t\t\t\t\tmp_endrun_component->SetFlags(  p_pos_history[i].EndRunFlags );\r\n\t\t\t\t\t\tif( p_pos_history[i].EndRunFlags & CSkaterEndRunComponent::FINISHED_END_OF_RUN )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t//Dbg_Printf( \"*** At END OF RUN ***\\n\" );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tfor( flag = 0; flag < NUM_ESKATERFLAGS; flag++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmp_state_component->m_skater_flags[flag].Set(p_pos_history[i].SkaterFlags.Test( flag ));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif( mp_state_component->m_skater_flags[SPINE_PHYSICS].Get())\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmp_state_component->m_spine_vel = GetObject()->m_vel;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmp_state_component->m_spine_vel.Set(0.0f, 0.0f, 0.0f);\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ti = ( i + 1 ) % CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\t\t\t\t} while( i != start_index );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterNonLocalNetLogicComponent::do_client_animation_update(   )\r\n{\r\n\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\tNet::Client* client;\r\n\r\n\tDbg_Assert( mp_animation_component );\r\n\r\n\tif(( client = gamenet_man->GetClient( 0 )))\r\n\t{   \r\n\t\t// Wait for the object update buffer to fill up\r\n\t\tif( mp_state_history_component->GetNumPosUpdates() >= CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS )\r\n\t\t{\r\n\t\t\tunsigned int cur_time;\r\n\t\t\tint i, start_index;\r\n\t\t\tSAnimEvent* event;\r\n\t\t\tint most_recent_index;\r\n            \r\n\t\t\tstart_index = mp_state_history_component->GetNumAnimUpdates() % CSkaterStateHistoryComponent::vNUM_ANIM_HISTORY_ELEMENTS;\r\n\t\t\tmost_recent_index = ( mp_state_history_component->GetNumAnimUpdates() - 1 ) % CSkaterStateHistoryComponent::vNUM_ANIM_HISTORY_ELEMENTS;\r\n\t\t\t\r\n\t\t\tcur_time = m_server_initial_update_time + ( client->m_Timestamp - m_client_initial_update_time );\r\n\r\n\t\t\ti = start_index;\r\n\t\t\tbool updated = false;\r\n\t\t\tdo\t\t\t\t\t\t\t   \r\n\t\t\t{   \r\n\t\t\t\tevent = &mp_state_history_component->GetAnimHistory()[i];\r\n\t\t\t\t//Dbg_Printf( \"(%d) CurTime: %d EventTime[%d]: %d\\n\", client->m_FrameCounter, cur_time, event->m_MsgId, event->GetTime());\r\n\t\t\t\tif( ( event->GetTime() > m_last_anm_update_time ) &&\r\n\t\t\t\t\t( event->GetTime() <= cur_time ))\r\n\t\t\t\t{   \r\n\t\t\t\t\tupdated = true;\r\n\t\t\t\t\tswitch( event->m_MsgId )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcase GameNet::MSG_ID_PRIM_ANIM_START:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t//Dbg_Printf( \"(%d) Playing primary anim: 0x%x Speed: %f Duration: %d Time:%d\\n\", client->m_Timestamp, event->m_Asset, event->m_Speed, event->m_Duration, event->GetTime());\r\n\t\t\t\t\t\t\tmp_animation_component->PlayPrimarySequence( event->m_Asset, false, event->m_StartTime, event->m_EndTime,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t (Gfx::EAnimLoopingType) event->m_LoopingType, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t event->m_BlendPeriod, event->m_Speed );\r\n\t\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcase GameNet::MSG_ID_SET_WOBBLE_TARGET:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmp_animation_component->SetWobbleTarget( event->m_Alpha, false );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcase GameNet::MSG_ID_ROTATE_SKATEBOARD:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmp_flip_and_rotate_component->RotateSkateboard( event->m_ObjId, event->m_Rotate, 0, false );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcase GameNet::MSG_ID_SET_WOBBLE_DETAILS:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tGfx::SWobbleDetails wobbleDetails;\r\n\t\t\t\t\r\n\t\t\t\t\t\t\twobbleDetails.wobbleAmpA = event->m_WobbleAmpA;\r\n\t\t\t\t\t\t\twobbleDetails.wobbleAmpB = event->m_WobbleAmpB;\r\n\t\t\t\t\t\t\twobbleDetails.wobbleK1 = event->m_WobbleK1;\r\n\t\t\t\t\t\t\twobbleDetails.wobbleK2 = event->m_WobbleK2;\r\n\t\t\t\t\t\t\twobbleDetails.spazFactor = event->m_SpazFactor;\r\n\r\n\t\t\t\t\t\t\tmp_animation_component->SetWobbleDetails( wobbleDetails, false );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcase GameNet::MSG_ID_SET_LOOPING_TYPE:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmp_animation_component->SetLoopingType( (Gfx::EAnimLoopingType) event->m_LoopingType, false );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcase GameNet::MSG_ID_SET_HIDE_ATOMIC:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t   \tmp_model_component->HideGeom( event->m_Asset, event->m_Hide, false );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcase GameNet::MSG_ID_SET_ANIM_SPEED:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmp_animation_component->SetAnimSpeed( event->m_Speed, false );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcase GameNet::MSG_ID_FLIP_ANIM:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmp_animation_component->FlipAnimation( event->m_ObjId, event->m_Flipped, 0, false );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcase GameNet::MSG_ID_ROTATE_DISPLAY:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmp_model_component->m_display_rotation_offset.Set(0,30,0);\r\n\t\t\t\t\t\t\tTmr::Time start_time=Tmr::ElapsedTime(0);\r\n\t\t\t\r\n\t\t\t\t\t\t\tif( event->m_Flags & 1 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tmp_model_component->mpDisplayRotationInfo[0].SetUp(event->m_Duration,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   start_time,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   event->m_StartAngle,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   event->m_DeltaAngle,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   event->m_SinePower,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   event->m_HoldOnLastAngle);\r\n\t\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t\tif( event->m_Flags & 2 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tmp_model_component->mpDisplayRotationInfo[1].SetUp(event->m_Duration,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   start_time,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   event->m_StartAngle,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   event->m_DeltaAngle,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   event->m_SinePower,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   event->m_HoldOnLastAngle);\r\n\t\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t\tif( event->m_Flags & 4 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tmp_model_component->mpDisplayRotationInfo[2].SetUp(event->m_Duration,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   start_time,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   event->m_StartAngle,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   event->m_DeltaAngle,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   event->m_SinePower,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   event->m_HoldOnLastAngle);\r\n\t\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcase (char) GameNet::MSG_ID_CLEAR_ROTATE_DISPLAY:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmp_model_component->mpDisplayRotationInfo[0].Clear();\r\n\t\t\t\t\t\t\tmp_model_component->mpDisplayRotationInfo[1].Clear();\r\n\t\t\t\t\t\t\tmp_model_component->mpDisplayRotationInfo[2].Clear();\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcase GameNet::MSG_ID_CREATE_SPECIAL_ITEM:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tCSpecialItemComponent* pSpecialItemComponent = GetSpecialItemComponentFromObject(GetObject());\r\n\t\t\t\t\t\t\tDbg_MsgAssert( pSpecialItemComponent, ( \"No special item component?\" ) );\r\n\r\n\t\t\t\t\t\t\tScript::CStruct* pSpecialItemParams = Script::GetStructure( event->m_Asset, Script::ASSERT );\r\n\t\t\t\t\t\t\tCCompositeObject* pSpecialItemObject = pSpecialItemComponent->CreateSpecialItem( event->m_Index, pSpecialItemParams );\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tScript::CStruct* pLockParams = new Script::CStruct;\r\n\t\t\t\t\t\t\t// pass along any bone or offset parameters...\r\n\t\t\t\t\t\t\t//pLockParams->AppendStructure( pParams );\r\n\t\t\t\t\t\t\tpLockParams->AddChecksum( CRCD(0xcab94088,\"bone\"), event->m_Bone );\r\n\t\t\t\t\t\t\tpLockParams->AddChecksum( CRCD(0x40c698af,\"id\"), GetObject()->GetID() );\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t// component-based\r\n\t\t\t\t\t\t\tCLockObjComponent* pLockObjComponent = GetLockObjComponentFromObject( pSpecialItemObject );\r\n\t\t\t\t\t\t\tDbg_MsgAssert( pLockObjComponent, ( \"No lockobj component\" ) );\r\n\t\t\t\t\t\t\tpLockObjComponent->InitFromStructure( pLockParams );\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tdelete pLockParams;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase GameNet::MSG_ID_DESTROY_SPECIAL_ITEM:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tCSpecialItemComponent* pSpecialItemComponent = GetSpecialItemComponentFromObject(GetObject());\r\n                            pSpecialItemComponent->DestroySpecialItem( event->m_Index );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\ti = ( i + 1 ) % CSkaterStateHistoryComponent::vNUM_ANIM_HISTORY_ELEMENTS;\r\n\t\t\t} while( i != start_index );\r\n\t\t\t\r\n\t\t\t/*static Tmr::Time s_time = 0;\r\n\r\n\t\t\tif( !updated )\r\n\t\t\t{\r\n\t\t\t\tif(( Tmr::GetTime() - s_time ) > 1000 )\r\n\t\t\t\t{\r\n\t\t\t\t\ti = start_index;\r\n\t\t\t\t\tdo\t\t\t\t\t\t\t   \r\n\t\t\t\t\t{   \r\n\t\t\t\t\t\tevent = &mp_state_history_component->GetAnimHistory()[i];\r\n\t\t\t\t\t\tDbg_Printf( \"(%d) CurTime: %d EventTime[%d]: %d\\n\", client->m_FrameCounter, cur_time, event->m_MsgId, event->GetTime());\r\n\t\t\t\t\t\ti = ( i + 1 ) % CSkaterStateHistoryComponent::vNUM_ANIM_HISTORY_ELEMENTS;\r\n\t\t\t\t\t} while( i != start_index );\r\n\t\t\t\t\ts_time = Tmr::GetTime();\r\n\t\t\t\t}\r\n\t\t\t}*/\r\n            \r\n\t\t\tm_last_anm_update_time = cur_time;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t\r\nvoid CSkaterNonLocalNetLogicComponent::setup_brightness_and_shadow (   )\r\n{\r\n\t// logic extracted from CAdjustComponent::uber_frig which is judged to be required by nonlocal clients\r\n\t\r\n\tCFeeler feeler;\r\n\t\r\n\tfeeler.m_start = GetObject()->m_pos;\r\n\tfeeler.m_end = GetObject()->m_pos;\r\n\r\n\t// Very minor adjustment to move origin away from vert walls\r\n\tfeeler.m_start += GetObject()->m_matrix[Y] * 0.001f;\r\n\t\r\n\tfeeler.m_start[Y] += 8.0f;\r\n\tfeeler.m_end[Y] -= FEET(400);\r\n\t\t   \r\n\tif (!feeler.GetCollision()) return;\r\n\t\r\n\tif (mp_state_component->GetState() != RAIL && feeler.IsBrightnessAvailable())\r\n\t{\r\n\t\tNx::CModelLights *p_model_lights = mp_model_component->GetModel()->GetModelLights();\r\n\t\tif (p_model_lights)\r\n\t\t{\r\n\t\t\tp_model_lights->SetBrightness(feeler.GetBrightness());\r\n\t\t} \r\n\t\telse\r\n\t\t{\r\n\t\t\t// Garrett: This should move to CModel eventually\r\n\t\t\tNx::CLightManager::sSetBrightness(feeler.GetBrightness());\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Store these values off for the simple shadow calculation.\r\n\tmp_shadow_component->SetShadowPos(feeler.GetPoint());\r\n\tmp_shadow_component->SetShadowNormal(feeler.GetNormal()); \r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterNonLocalNetLogicComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterNonLocalNetLogicComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/11/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERNONLOCALNETLOGICCOMPONENT_H__\r\n#define __COMPONENTS_SKATERNONLOCALNETLOGICCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#define\t\tCRC_SKATERNONLOCALNETLOGIC CRCD(0x850eef66, \"SkaterNonLocalNetLogic\")\r\n\r\n#define\t\tGetSkaterNonLocalNetLogicComponent() ((Obj::CSkaterNonLocalNetLogicComponent*)GetComponent(CRC_SKATERNONLOCALNETLOGIC))\r\n#define\t\tGetSkaterNonLocalNetLogicComponentFromObject(pObj) ((Obj::CSkaterNonLocalNetLogicComponent*)(pObj)->GetComponent(CRC_SKATERNONLOCALNETLOGIC))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CSkaterStateHistoryComponent;\r\n\tclass CSkaterCorePhysicsComponent;\r\n\tclass CSkaterStateComponent;\r\n\tclass CSkaterEndRunComponent;\r\n\tclass CSkaterFlipAndRotateComponent;\r\n\tclass CShadowComponent;\r\n\tclass CRailNode;\r\n\t\r\nenum\r\n{\r\n\tvMAG_HISTORY_LENGTH = 20\r\n};\r\n\r\nclass CSkaterNonLocalNetLogicComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkaterNonLocalNetLogicComponent();\r\n    virtual ~CSkaterNonLocalNetLogicComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tResync();\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\t\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\tsetup_brightness_and_shadow (   );\r\n\tvoid\t\t\t\t\t\t\tinterpolate_client_position (   );\r\n\tvoid\t\t\t\t\t\t\textrapolate_client_position (   );\r\n\tvoid\t\t\t\t\t\t\textrapolate_rail_position( void );\r\n\tCRailNode*\t\t\t\t\t\ttravel_on_rail( CRailNode* start_node, float frame_length );\r\n\tfloat \t\t\t\t\t\t\trotate_away_from_wall( Mth::Vector normal, float &turn_angle );\r\n\tvoid \t\t\t\t\t\t\tbounce_off_wall( const Mth::Vector& normal, const Mth::Vector& point );\r\n\tvoid \t\t\t\t\t\t\tsnap_to_ground( void  );\r\n\tvoid\t\t\t\t\t\t\textrapolate_position( void );\r\n\tvoid\t\t\t\t\t\t\tdo_client_animation_update (   );\r\n\t\r\nprivate:\r\n \tTmr::Time\t\t\t\t\t\tm_client_initial_update_time;\r\n\t//Tmr::Time\t\t\t\t\t\tm_client_initial_anm_update_time;\r\n\tTmr::Time\t\t\t\t\t\tm_server_initial_update_time;\r\n\t//Tmr::Time\t\t\t\t\t\tm_server_initial_anm_update_time;\r\n\tTmr::Time\t\t\t\t\t\tm_last_anm_update_time;\r\n\tint\t\t\t\t\t\t\t\tm_last_pos_index;\r\n\t\r\n\tMth::Vector\t\t\t\t\t\tm_interp_pos;\r\n\tMth::Vector\t\t\t\t\t\tm_old_interp_pos;\r\n\tMth::Vector\t\t\t\t\t\tm_old_extrap_pos;\r\n\tMth::Vector\t\t\t\t\t\tm_current_normal;\r\n\tfloat\t\t\t\t\t\t\tm_mag_history[vMAG_HISTORY_LENGTH];\r\n\tfloat\t\t\t\t\t\t\tm_ratio_history[vMAG_HISTORY_LENGTH];\r\n\tfloat\t\t\t\t\t\t\tm_extrap_coeff_history[vMAG_HISTORY_LENGTH];\r\n\tMth::Vector\t\t\t\t\t\tm_vel_history[vMAG_HISTORY_LENGTH];\r\n\tint\t\t\t\t\t\t\t\tm_num_mags;\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_frame_length;\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_last_driving;\r\n\t\r\n\tCSkaterStateHistoryComponent*\tmp_state_history_component;\r\n\tCAnimationComponent*\t\t\tmp_animation_component;\r\n\tCModelComponent*\t\t\t\tmp_model_component;\r\n\tCSkaterStateComponent*\t\t\tmp_state_component;\r\n\tCSkaterEndRunComponent*\t\t\tmp_endrun_component;\r\n\tCSkaterFlipAndRotateComponent*\tmp_flip_and_rotate_component;\r\n    CShadowComponent*\t\t\t\tmp_shadow_component;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterPhysicsControlComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterPhysicsControlComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/7/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/components/triggercomponent.h>\r\n#include <gel/components/walkcomponent.h>\r\n#include <gel/components/skatercameracomponent.h>\r\n#include <gel/components/walkcameracomponent.h>\r\n\r\n#ifdef TESTING_GUNSLINGER\r\n#include <gel/components/ridercomponent.h>\r\n#endif\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skaterrotatecomponent.h>\r\n#include <sk/components/skateradjustphysicscomponent.h>\r\n#include <sk/components/skaterfinalizephysicscomponent.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSkaterPhysicsControlComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterPhysicsControlComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterPhysicsControlComponent::CSkaterPhysicsControlComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERPHYSICSCONTROL );\r\n\t\r\n\tmp_core_physics_component = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterPhysicsControlComponent::~CSkaterPhysicsControlComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterPhysicsControlComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tDbg_MsgAssert(GetObject()->GetType() == SKATE_TYPE_SKATER, (\"CSkaterPhysicsControlComponent added to non-skater composite object\"));\r\n\t\r\n\tm_physics_suspended = false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterPhysicsControlComponent::Finalize(  )\r\n{\r\n\tmp_core_physics_component = GetSkaterCorePhysicsComponentFromObject(GetObject());\r\n\tmp_state_component = GetSkaterStateComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_core_physics_component);\r\n\tDbg_Assert(mp_state_component);\r\n\t\r\n\tmp_state_component->m_physics_state = NO_STATE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterPhysicsControlComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterPhysicsControlComponent::Update()\r\n{\r\n\tm_restarted_this_frame = false;\r\n\t\r\n\t// SkaterPhysicsControlComponent is inactive when physics is NOT suspended.  When physics is suspended SkaterPhysicsControlComponent handles\r\n\t// setting the skater's display matrix.\r\n\tif (!m_physics_suspended) return;\r\n\t\r\n\tswitch (mp_state_component->m_physics_state)\r\n\t{\r\n\t\tcase SKATING:\r\n\t\t\tGetObject()->SetDisplayMatrix(mp_core_physics_component->m_lerping_display_matrix);\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase WALKING:\r\n\t\t\tGetObject()->SetDisplayMatrix(GetObject()->GetMatrix());\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(false, (\"No skater physics state switched on before first skater update\"));\r\n\t}\r\n\t\r\n\t// If the skater is unsuspended, the physics components will unsuspend as well.  We must check for this and resuspend\r\n\tif (!mp_core_physics_component->IsSuspended())\r\n\t{\r\n\t\tsuspend_physics(true);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterPhysicsControlComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | PausePhysics | PausePhysics will stop all programmatic movement and rotation of the skater\r\n\t\tcase CRCC(0x3522d612, \"PausePhysics\"):\r\n\t\t\tif (!m_physics_suspended)\r\n\t\t\t{\r\n\t\t\t\tsuspend_physics(true);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n        // @script | UnPausePhysics | \r\n\t\tcase CRCC(0x595627c, \"UnPausePhysics\"):\r\n\t\t\tif (m_physics_suspended)\r\n\t\t\t{\r\n\t\t\t\tsuspend_physics(false);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x57bfbae8, \"Walking\"):\r\n\t\t\treturn IsWalking() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\tcase CRCC(0xf2813ee5, \"Skating\"):\r\n\t\t\treturn IsSkating() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\tcase CRCC(0xee584cbc, \"Driving\"):\r\n\t\t\treturn IsDriving() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n\t\tcase CRCC(0xb32e9eae, \"SetDriving\"):\r\n\t\t\tmp_state_component->m_driving = true;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x953a7b6d, \"UnsetDriving\"):\r\n\t\t\tmp_state_component->m_driving = false;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x9569d5b1, \"GetTimeSincePhysicsSwitch\"):\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x27f48e93, \"TimeSincePhysicsSwitch\"), Tmr::ElapsedTime(m_physics_state_switch_time_stamp) * (1.0f / 1000.0f));\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0xa887285a, \"GetPreviousPhysicsStateDuration\"):\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x24d061ba, \"PreviousPhysicsStateDuration\"), m_previous_physics_state_duration * (1.0f / 1000.0f));\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x5c038f9b, \"SkaterPhysicsControl_SwitchWalkingToSkating\"):\r\n\t\t\tswitch_walking_to_skating();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x6e8e39b3, \"SkaterPhysicsControl_SwitchSkatingToWalking\"):\r\n\t\t\tswitch_skating_to_walking();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x9366a509, \"SetBoardMissing\"):\r\n\t\t\tm_board_missing = true;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x4830e80, \"UnsetBoardMissing\"):\r\n\t\t\tm_board_missing = false;\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase CRCC(0xd5a9f889, \"IsBoardMissing\"):\r\n\t\t\treturn m_board_missing ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\r\n#\t\tifdef TESTING_GUNSLINGER\r\n\t\tcase CRCC(0x14c4f16b,\"SkaterPhysicsControl_SwitchWalkingToRiding\"):\r\n\t\t\tswitch_walking_to_riding();\r\n\t\t\tbreak;\r\n\r\n\t\tcase CRCC(0x82604c1e,\"SkaterPhysicsControl_SwitchRidingToWalking\"):\r\n\t\t\tswitch_riding_to_walking();\r\n\t\t\tbreak;\r\n#\t\tendif\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterPhysicsControlComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterPhysicsControlComponent::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddChecksum(\"m_physics_suspended\", m_physics_suspended ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\tp_info->AddInteger(\"m_physics_state\", mp_state_component->m_physics_state);\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterPhysicsControlComponent::suspend_physics ( bool suspend )\r\n{\r\n\tm_physics_suspended = suspend;\r\n\t\r\n\t// If the skater is suspended, we don't want to unsuspend the physics components.  We only want to change the CSkaterPhysicsControlComponent state.\r\n\tif (!suspend && GetObject()->IsSuspended()) return;\r\n    \r\n\tswitch (mp_state_component->m_physics_state)\r\n\t{\r\n\t\tcase SKATING:\r\n\t\t\tDbg_Assert(mp_core_physics_component);\r\n\t\t\tDbg_Assert(GetSkaterRotateComponentFromObject(GetObject()));\r\n\t\t\tDbg_Assert(GetSkaterAdjustPhysicsComponentFromObject(GetObject()));\r\n\t\t\tDbg_Assert(GetSkaterFinalizePhysicsComponentFromObject(GetObject()));\r\n\t\t\t\r\n\t\t\tmp_core_physics_component->Suspend(suspend);\r\n\t\t\tGetSkaterRotateComponentFromObject(GetObject())->Suspend(suspend);\r\n\t\t\tGetSkaterAdjustPhysicsComponentFromObject(GetObject())->Suspend(suspend);\r\n\t\t\tGetSkaterFinalizePhysicsComponentFromObject(GetObject())->Suspend(suspend);\r\n\t\t\tbreak;\r\n\r\n\t\tcase WALKING:\r\n\t\t\tDbg_Assert(GetWalkComponentFromObject(GetObject()));\r\n\t\t\t\r\n\t\t\tGetWalkComponentFromObject(GetObject())->Suspend(suspend);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_Assert(false);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterPhysicsControlComponent::switch_walking_to_skating (   )\r\n{\r\n\tif (mp_state_component->m_physics_state == SKATING) return;\r\n\t\r\n\tm_previous_physics_state_duration = Tmr::ElapsedTime(m_physics_state_switch_time_stamp);\r\n\tm_physics_state_switch_time_stamp = Tmr::GetTime();\r\n\t\r\n\tCWalkComponent* p_walk_component = GetWalkComponentFromObject(GetObject());\r\n\tCCompositeObject* p_skater_cam = get_skater_camera();\r\n\tCSkaterCameraComponent* p_skater_camera_component = GetSkaterCameraComponentFromObject(p_skater_cam);\r\n\tCWalkCameraComponent* p_walk_camera_component = GetWalkCameraComponentFromObject(p_skater_cam);\r\n\t\r\n\tDbg_Assert(p_walk_component);\r\n\tDbg_Assert(p_skater_camera_component);\r\n\tDbg_Assert(p_walk_camera_component);\r\n\t\r\n\t// switch off walking\r\n\t\r\n\tp_walk_component->CleanUpWalkState();\r\n\tp_walk_component->Suspend(true);\r\n\t\r\n\tp_walk_camera_component->Suspend(true);\r\n\t\r\n\t// switch on skating\r\n\r\n\tmp_state_component->m_physics_state = SKATING;\r\n\t\r\n\tmp_core_physics_component->Suspend(false);\r\n\tmp_core_physics_component->ReadySkateState(p_walk_component->GetState() == CWalkComponent::WALKING_GROUND, p_walk_component->GetRailData(), p_walk_component->GetAcidDropData());\r\n\t\r\n\tGetSkaterRotateComponentFromObject(GetObject())->Suspend(false);\r\n\tGetSkaterAdjustPhysicsComponentFromObject(GetObject())->Suspend(false);\r\n\tGetSkaterFinalizePhysicsComponentFromObject(GetObject())->Suspend(false);\r\n\t\r\n\tp_skater_camera_component->Suspend(false);\r\n\t\r\n\t// exchange camera states\r\n\tSCameraState camera_state;\r\n\tp_walk_camera_component->GetCameraState(camera_state);\r\n\tp_skater_camera_component->ReadyForActivation(camera_state);\r\n\t\r\n\t// reapply the physics suspend state\r\n\tif (m_physics_suspended)\r\n\t{\r\n\t\tsuspend_physics(m_physics_suspended);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterPhysicsControlComponent::switch_skating_to_walking (   )\r\n{\r\n\tif (mp_state_component->m_physics_state == WALKING) return;\r\n\t\r\n\tm_previous_physics_state_duration = Tmr::ElapsedTime(m_physics_state_switch_time_stamp);\r\n\tm_physics_state_switch_time_stamp = Tmr::GetTime();\r\n\t\r\n\tCWalkComponent* p_walk_component = GetWalkComponentFromObject(GetObject());\r\n\tCCompositeObject* p_skater_cam = get_skater_camera();\r\n\tCSkaterCameraComponent* p_skater_camera_component = GetSkaterCameraComponentFromObject(p_skater_cam);\r\n\tCWalkCameraComponent* p_walk_camera_component = GetWalkCameraComponentFromObject(p_skater_cam);\r\n\t\r\n\tDbg_Assert(p_walk_component);\r\n\tDbg_Assert(p_skater_camera_component);\r\n\tDbg_Assert(p_walk_camera_component);\r\n\t\r\n\t// switch off skating\r\n\t\r\n\tbool ground = mp_core_physics_component->GetState() == GROUND;\r\n\tmp_core_physics_component->CleanUpSkateState();\r\n\tmp_core_physics_component->Suspend(true);\r\n\r\n\tGetSkaterRotateComponentFromObject(GetObject())->Suspend(true);\r\n\tGetSkaterAdjustPhysicsComponentFromObject(GetObject())->Suspend(true);\r\n\tGetSkaterFinalizePhysicsComponentFromObject(GetObject())->Suspend(true);\r\n\r\n\tp_skater_camera_component->Suspend(true);\r\n\t\r\n\t// switch on walking\r\n\t\t\r\n\tmp_state_component->m_physics_state = WALKING;\r\n\t\r\n\tp_walk_component->Suspend(false);\r\n\tp_walk_component->ReadyWalkState(ground);\r\n\t\r\n\tp_walk_camera_component->Suspend(false);\r\n\t\r\n\t// exchange camera states\r\n\tSCameraState camera_state;\r\n\tp_skater_camera_component->GetCameraState(camera_state);\r\n\tp_walk_camera_component->ReadyForActivation(camera_state);\r\n\t\r\n\t// reapply the physics suspend state\r\n\tif (m_physics_suspended)\r\n\t{\r\n\t\tsuspend_physics(m_physics_suspended);\r\n\t}\r\n}\r\n\r\n\r\n#ifdef TESTING_GUNSLINGER\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterPhysicsControlComponent::switch_walking_to_riding( void )\r\n{\r\n\tif (mp_state_component->m_physics_state == SKATING) return;\r\n\tif (mp_state_component->m_physics_state == RIDING) return;\r\n\t\r\n\tCRiderComponent*\t\tp_rider_component\t\t\t= GetRiderComponentFromObject(GetObject());\r\n\r\n\t// Use the rider component to check that this switch is valid.\r\n\tif(\tp_rider_component->ReadyRiderState( true ))\r\n\t{\r\n\t\tCWalkComponent*\t\t\tp_walk_component\t\t\t= GetWalkComponentFromObject(GetObject());\r\n\t\tCCompositeObject*\t\tp_skater_cam\t\t\t\t= get_skater_camera();\r\n\t\tCSkaterCameraComponent*\tp_skater_camera_component\t= GetSkaterCameraComponentFromObject(p_skater_cam);\r\n\t\tCWalkCameraComponent*\tp_walk_camera_component\t\t= GetWalkCameraComponentFromObject(p_skater_cam);\r\n\t\r\n\t\tDbg_Assert(p_walk_component);\r\n\t\tDbg_Assert(p_skater_camera_component);\r\n\t\tDbg_Assert(p_walk_camera_component);\r\n\t\r\n\t\t// switch off walking\r\n\t\tp_walk_component->Suspend(true);\r\n\t\tp_walk_camera_component->Suspend(true);\r\n\t\r\n\t\t// switch on riding\r\n\t\tmp_state_component->m_physics_state = RIDING;\r\n\t\r\n//\t\tmp_core_physics_component->Suspend(false);\r\n//\t\tmp_core_physics_component->ReadySkateState(p_walk_component->GetState() == CWalkComponent::WALKING_GROUND, p_walk_component->GetRailData());\r\n\t\tp_rider_component->Suspend( false );\r\n\t\r\n//\t\tGetSkaterRotateComponentFromObject(GetObject())->Suspend(false);\r\n//\t\tGetSkaterAdjustPhysicsComponentFromObject(GetObject())->Suspend(false);\r\n//\t\tGetSkaterFinalizePhysicsComponentFromObject(GetObject())->Suspend(false);\r\n//\t\tGetSkaterCleanupStateComponentFromObject(GetObject())->Suspend(false);\r\n\t\r\n//\t\tp_skater_camera_component->Suspend(false);\r\n\t\r\n\t\t// exchange camera states\r\n//\t\tSCameraState camera_state;\r\n//\t\tp_walk_camera_component->GetCameraState(camera_state);\r\n//\t\tp_skater_camera_component->ReadyForActivation(camera_state);\r\n\t\r\n\t\t// reapply the physics suspend state\r\n\t\tif (m_physics_suspended)\r\n\t\t{\r\n\t\t\tsuspend_physics(m_physics_suspended);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterPhysicsControlComponent::switch_riding_to_walking( void )\r\n{\r\n//\tif (mp_state_component->m_physics_state == WALKING) return;\r\n\t\r\n\tCWalkComponent*\t\t\tp_walk_component = GetWalkComponentFromObject(GetObject());\r\n\tCRiderComponent*\t\tp_rider_component\t\t\t= GetRiderComponentFromObject(GetObject());\r\n\tCCompositeObject*\t\tp_skater_cam = get_skater_camera();\r\n\tCSkaterCameraComponent*\tp_skater_camera_component = GetSkaterCameraComponentFromObject(p_skater_cam);\r\n\tCWalkCameraComponent*\tp_walk_camera_component = GetWalkCameraComponentFromObject(p_skater_cam);\r\n\t\r\n\tDbg_Assert(p_walk_component);\r\n\tDbg_Assert(p_skater_camera_component);\r\n\tDbg_Assert(p_walk_camera_component);\r\n\t\r\n\t// switch off skating\r\n\tmp_core_physics_component->Suspend(true);\r\n\r\n\tGetSkaterRotateComponentFromObject(GetObject())->Suspend(true);\r\n\tGetSkaterAdjustPhysicsComponentFromObject(GetObject())->Suspend(true);\r\n\tGetSkaterFinalizePhysicsComponentFromObject(GetObject())->Suspend(true);\r\n//\tGetSkaterCleanupStateComponentFromObject(GetObject())->Suspend(true);\r\n\r\n\tp_skater_camera_component->Suspend(true);\r\n\t\r\n\t// Switch off riding.\r\n\tp_rider_component->Suspend( true );\r\n\r\n\t// switch on walking\r\n\tmp_state_component->m_physics_state = WALKING;\r\n\t\r\n\tp_walk_component->Suspend(false);\r\n\tp_walk_component->ReadyWalkState(mp_core_physics_component->GetState() == GROUND);\r\n\tp_walk_camera_component->Suspend( false );\r\n\t\r\n\t// exchange camera states\r\n//\tSCameraState camera_state;\r\n//\tp_skater_camera_component->GetCameraState( camera_state );\r\n//\tp_walk_camera_component->ReadyForActivation( camera_state );\r\n\t\r\n\t// reapply the physics suspend state\r\n\tif (m_physics_suspended)\r\n\t{\r\n\t\tsuspend_physics(m_physics_suspended);\r\n\t}\r\n}\r\n\r\n\r\n\r\n#endif\r\n\r\n\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterPhysicsControlComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterPhysicsControlComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/7/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERPHYSICSCONTROLCOMPONENT_H__\r\n#define __COMPONENTS_SKATERPHYSICSCONTROLCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/objects/skater.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n\r\n#define\t\tCRC_SKATERPHYSICSCONTROL CRCD(0xd9151d4d, \"SkaterPhysicsControl\")\r\n\r\n#define\t\tGetSkaterPhysicsControlComponent() ((Obj::CSkaterPhysicsControlComponent*)GetComponent(CRC_SKATERPHYSICSCONTROL))\r\n#define\t\tGetSkaterPhysicsControlComponentFromObject(pObj) ((Obj::CSkaterPhysicsControlComponent*)(pObj)->GetComponent(CRC_SKATERPHYSICSCONTROL))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CSkaterCorePhysicsComponent;\r\n\tclass CSkaterStateComponent;\r\n\tclass CRailManager;\r\n\tclass CRailNode;\r\n\t\r\n\tenum ESpecialTransitionType\r\n\t{\r\n\t\tNO_SPECIAL_TRANSITION,\r\n\t\tRAIL_TRANSITION,\r\n\t\tACID_DROP_TRANSITION\r\n\t};\r\n\r\n\tstruct SRailData\r\n\t{\r\n\t\tMth::Vector\t\t\t\t\trail_pos;\r\n\t\tCRailManager*\t\t\t\tp_rail_man;\r\n\t\tCRailNode*\t\t\t\t\tp_node;\r\n\t\tCCompositeObject*\t\t\tp_movable_contact;\r\n\t};\r\n\t\r\n\tstruct SAcidDropData\r\n\t{\r\n\t\tMth::Vector\t\t\t\t\ttarget_pos;\r\n\t\tMth::Vector\t\t\t\t\ttarget_normal;\r\n\t\tfloat\t\t\t\t\t\ttrue_target_height;\r\n\t};\r\n\r\nclass CSkaterPhysicsControlComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkaterPhysicsControlComponent();\r\n    virtual ~CSkaterPhysicsControlComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tFinalize();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\t\t \t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\r\n\tvoid\t\t\t\t\t\t\tSuspendPhysics ( bool suspend );\r\n\tbool\t\t\t\t\t\t\tIsPhysicsSuspended (   ) { return m_physics_suspended; }\r\n\t\r\n\tbool\t\t\t\t\t\t\tIsSkating (   );\r\n\tbool\t\t\t\t\t\t\tIsWalking (   );\r\n\tbool\t\t\t\t\t\t\tIsDriving (   );\r\n\t\r\n\tTmr::Time\t\t\t\t\t\tGetStateSwitchTime (   );\r\n\tTmr::Time\t\t\t\t\t\tGetPreviousPhysicsStateDuration (   );\r\n\t\r\n\tbool\t\t\t\t\t\t\tIsBoardMissing (   ) { return m_board_missing; }\r\n\tbool\t\t\t\t\t\t\tHaveBeenReset (   ) { return m_restarted_this_frame; }\r\n\tvoid\t\t\t\t\t\t\tNotifyReset (   ) { m_restarted_this_frame = true; }\r\n\t\r\nprivate:\r\n\tCCompositeObject*\t\t\t\tget_skater_camera (   );\r\n\tvoid\t\t\t\t\t\t\tsuspend_physics ( bool suspend );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tswitch_skating_to_walking (   );\r\n\tvoid\t\t\t\t\t\t\tswitch_walking_to_skating (   );\r\n\r\n#\tifdef TESTING_GUNSLINGER\r\n\tvoid\t\t\t\t\t\t\tswitch_walking_to_riding (   );\r\n\tvoid\t\t\t\t\t\t\tswitch_riding_to_walking (   );\r\n#\tendif\r\n\r\n\r\nprivate:\r\n\tbool\t\t\t\t\t\t\tm_physics_suspended;\r\n\t\r\n\tTmr::Time\t\t\t\t\t\tm_physics_state_switch_time_stamp;\r\n\tTmr::Time\t\t\t\t\t\tm_previous_physics_state_duration;\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_board_missing;\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_restarted_this_frame;  \t\t// Set if a restart occured, so we can early out\r\n\t\r\n\t// peer components\r\n\tCSkaterCorePhysicsComponent*\tmp_core_physics_component;\r\n\tCSkaterStateComponent*\t\t\tmp_state_component;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CSkaterPhysicsControlComponent::IsDriving (   )\r\n{\r\n\treturn mp_state_component->m_driving;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CSkaterPhysicsControlComponent::IsSkating (   )\r\n{\r\n\treturn !IsDriving() && mp_state_component->m_physics_state == SKATING;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CSkaterPhysicsControlComponent::IsWalking (   )\r\n{\r\n\treturn !IsDriving() && mp_state_component->m_physics_state == WALKING;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Tmr::Time CSkaterPhysicsControlComponent::GetStateSwitchTime (   )\r\n{\r\n\treturn m_physics_state_switch_time_stamp;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Tmr::Time CSkaterPhysicsControlComponent::GetPreviousPhysicsStateDuration (   )\r\n{\r\n\treturn m_previous_physics_state_duration;\r\n}\r\n\r\n/*****************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterPhysicsControlComponent::SuspendPhysics ( bool suspend )\r\n{\r\n\tif (m_physics_suspended == suspend) return;\r\n\t\r\n\tsuspend_physics(suspend);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline CCompositeObject* CSkaterPhysicsControlComponent::get_skater_camera (   )\r\n{\r\n\t\r\n\treturn static_cast< CSkater* >(GetObject())->GetCamera();\r\n}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterProximityComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SkaterProximityComponent.cpp\r\n//* OWNER:          Mick West\r\n//* CREATION DATE:  3/20/03\r\n//****************************************************************************\r\n\r\n/*\r\n\r\n\tComponent for raising exceptions/events when the skater gets within a particular radius\r\n\tthis used to be part of the ExceptionComponent, but as that is slated for destruction,\r\n\tI've had to seperate it out.  \t\t\t\t\t\r\n\r\n*/\r\n\t\t\t\t\t\r\n// The CSkaterProximityComponent class is an skeletal version of a component\r\n// It is intended that you use this as the basis for creating new\r\n// components.  \r\n// To create a new component called \"Watch\", (CWatchComponent):\r\n//  - copy SkaterProximitycomponent.cpp/.h to watchcomponent.cpp/.h\r\n//  - in both files, search and replace \"SkaterProximity\" with \"Watch\", preserving the case\r\n//  - in WatchComponent.h, update the CRCD value of CRC_WATCH\r\n//  - in CompositeObjectManager.cpp, in the CCompositeObjectManager constructor, add:\r\n//\t\t  \tRegisterComponent(CRC_WATCH,\t\t\tCWatchComponent::s_create); \r\n//  - and add the include of the header\r\n//\t\t\t#include <gel/components/watchcomponent.h> \r\n//  - Add it to build\\gel.mkf, like:\r\n//          $(NGEL)/components/WatchComponent.cpp\\\r\n//  - Fill in the OWNER (yourself) and the CREATION DATE (today's date) in the .cpp and the .h files\r\n//\t- Insert code as needed and remove generic comments\r\n//  - remove these comments\r\n//  - add comments specfic to the component, explaining its usage\r\n\r\n#include <sk/components/SkaterProximitycomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/objtrack.h>\r\n\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/pathob.h>\r\n#include <sk/objects/skater.h>\r\n\r\n\r\n#define\tFLAGEXCEPTION(X) GetObject()->SelfEvent(X)\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// s_create is what is registered with the component factory \r\n// object, (currently the CCompositeObjectManager) \r\n// s_create\treturns a CBaseComponent*, as it is to be used\r\n// by factor creation schemes that do not care what type of\r\n// component is being created\r\n// **  after you've finished creating this component, be sure to\r\n// **  add it to the list of registered functions in the\r\n// **  CCompositeObjectManager constructor  \r\n\r\nCBaseComponent* CSkaterProximityComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterProximityComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// All components set their type, which is a unique 32-bit number\r\n// (the CRC of their name), which is used to identify the component\t\r\nCSkaterProximityComponent::CSkaterProximityComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERPROXIMITY );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterProximityComponent::~CSkaterProximityComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// InitFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CSkaterProximityComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// ** Add code to parse the structure, and initialize the component\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// RefreshFromStructure is passed a Script::CStruct that contains a\r\n// number of parameters to initialize this component\r\n// this currently is the contents of a node\r\n// but you can pass in anything you like.\t\r\nvoid CSkaterProximityComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\t// Default to just calline InitFromStructure()\r\n\t// but if that does not handle it, then will need to write a specific \r\n\t// function here. \r\n\t// The user might only want to update a single field in the structure\r\n\t// and we don't want to be asserting becasue everything is missing \r\n\t\r\n\tInitFromStructure(pParams);\r\n\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The component's Update() function is called from the CCompositeObject's \r\n// Update() function.  That is called every game frame by the CCompositeObjectManager\r\n// from the s_logic_code function that the CCompositeObjectManager registers\r\n// with the task manger.\r\nvoid CSkaterProximityComponent::Update()\r\n{\r\n\t// GJ TODO:  maybe this should be made more generic\r\n\t// so that it takes a CCompositeObject*\t(it would\r\n\t// make replacing the skater w/ a different player\r\n\t// object easier)\r\n\r\n\t// check skater dist exceptions...\r\n\tfloat distToSkaterSqr = 0.0f;\r\n\t\r\n\tif ( mInnerRadiusSqr )\r\n\t{\r\n\t\tdistToSkaterSqr = GetDistToLocalSkaterSquared();\r\n\t\t//distToSkaterSqr = GetDistToNearestSkaterSquared( );\r\n\t\tif ( distToSkaterSqr <= mInnerRadiusSqr )\r\n\t\t{\r\n\t\t\t// If the local skater is in radius, then flag \"SkaterInRadius\"\r\n\t\t\tFLAGEXCEPTION( CRCD(0xdb7413fb,\"SkaterInRadius\") );\r\n\t\t\tif (!GetObject()->IsDead())\r\n\t\t\t{\r\n\t\t\t\tFLAGEXCEPTION( CRCD(0x5e8eb123,\"AnySkaterInRadius\") );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tdistToSkaterSqr = GetDistToNearestSkaterSquared();\t// MIGHT BE A NETWORK SKATER\r\n\t\t\tif ( distToSkaterSqr <= mInnerRadiusSqr )\r\n\t\t\t{\r\n\t\t\t\tFLAGEXCEPTION( CRCD(0x5e8eb123,\"AnySkaterInRadius\") );\r\n\t\t\t}\r\n\t\t\tdistToSkaterSqr = 0.0f;\t\t// Mick:  need to clear it, otherwise this value will be used for the\r\n\t\t\t\t\t\t\t\t\t\t// AvoidRadius settings, which only apply to local skaters\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( mOuterRadiusSqr )\r\n\t{\r\n\t\tif ( distToSkaterSqr == 0.0f )\r\n\t\t{\r\n\t\t\tdistToSkaterSqr = GetDistToLocalSkaterSquared();\r\n\t\t}\r\n\t\tif ( distToSkaterSqr >= mOuterRadiusSqr )\r\n\t\t{\r\n\t\t\tif (!GetObject()->IsDead())\r\n\t\t\t{\r\n\t\t\t\tFLAGEXCEPTION( CRCD(0xa41f5336,\"SkaterOutOfRadius\") ); \r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( mInnerAvoidRadiusSqr )\r\n\t{\r\n\t\tif ( distToSkaterSqr == 0.0f )\r\n\t\t{\r\n\t\t\tdistToSkaterSqr = GetDistToLocalSkaterSquared();\r\n\t\t}\r\n\t\tif ( distToSkaterSqr <= mInnerAvoidRadiusSqr )\r\n\t\t{\r\n\t\t\tif (!GetObject()->IsDead())\r\n\t\t\t{\r\n\t\t\t\tFLAGEXCEPTION( CRCD(0xfaeec40f,\"SkaterInAvoidRadius\") );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( mOuterAvoidRadiusSqr )\r\n\t{\r\n\t\tif ( distToSkaterSqr == 0.0f )\r\n\t\t{\r\n\t\t\tdistToSkaterSqr = GetDistToLocalSkaterSquared();\r\n\t\t}\r\n\t\tif ( distToSkaterSqr >= mOuterAvoidRadiusSqr )\r\n\t\t{\r\n\t\t\tif (!GetObject()->IsDead())\r\n\t\t\t{\r\n\t\t\t\tFLAGEXCEPTION( CRCD(0x9c5af1a0,\"SkaterOutOfAvoidRadius\") );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the \"Checksum\" of a script command, then possibly handle it\r\n// if it's a command that this component will handle\t\r\nCBaseComponent::EMemberFunctionResult CSkaterProximityComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | Obj_SetInnerRadius | \r\n        // @uparm 1.0 | inner radius\r\n\t\tcase ( 0x82a0a873 ):\t// Obj_SetInnerRadius\r\n\t\t\tif ( pParams->GetFloat( NONAME, &mInnerRadiusSqr ) )\r\n\t\t\t{\r\n\t\t\t\tmInnerRadiusSqr *= FEET_TO_INCHES( 1.0f );\r\n\t\t\t\tmInnerRadiusSqr *= mInnerRadiusSqr;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_SetOuterRadius | \r\n        // @uparm 1.0 | outer radius\r\n\t\tcase ( 0x8cb5d0c0 ):\t// Obj_SetOuterRadius\r\n\t\t\tif ( pParams->GetFloat( NONAME, &mOuterRadiusSqr ) )\r\n\t\t\t{\r\n\t\t\t\tmOuterRadiusSqr *= FEET_TO_INCHES( 1.0f );\r\n\t\t\t\tmOuterRadiusSqr *= mOuterRadiusSqr;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | Obj_SetInnerAvoidRadius | \r\n\t\t// @uparm 1.0 | inner radius\r\n\t\tcase 0x50f28d36: // Obj_SetInnerAvoidRadius\r\n\t\t\tif ( pParams->GetFloat( NONAME, &mInnerAvoidRadiusSqr ) )\r\n\t\t\t{\r\n\t\t\t\tmInnerAvoidRadiusSqr *= FEET_TO_INCHES( 1.0f );\r\n\t\t\t\tmInnerAvoidRadiusSqr *= mInnerAvoidRadiusSqr;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\t// @script | Obj_SetOuterAvoidRadius | \r\n\t\t// @uparm 1.0 | outer radius\r\n\t\tcase 0x2d703b94: // Obj_SetOuterAvoidRadius\r\n\t\t\tif ( pParams->GetFloat( NONAME, &mOuterAvoidRadiusSqr ) )\r\n\t\t\t{\r\n\t\t\t\tmOuterAvoidRadiusSqr *= FEET_TO_INCHES( 1.0f );\r\n\t\t\t\tmOuterAvoidRadiusSqr *= mOuterAvoidRadiusSqr;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n\t// the \"default\" case of the switch statement handles\r\n\t// unrecognized functions;  if we make it down here,\r\n\t// that means that the component already handled it\r\n\t// somehow\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterProximityComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterProximityComponent::GetDebugInfo\"));\r\n\r\n\t// Add any script components to the p_info structure,\r\n\t// and they will be displayed in the script debugger (qdebug.exe)\r\n\t// you will need to add the names to debugger_names.q, if they are not existing checksums\r\n\r\n\t/*\tExample:\r\n\tp_info->AddInteger(\"m_never_suspend\",m_never_suspend);\r\n\tp_info->AddFloat(\"m_suspend_distance\",m_suspend_distance);\r\n\t*/\r\n\tp_info->AddFloat(\"mInnerRadiusSqr\",mInnerRadiusSqr);\r\n\tp_info->AddFloat(\"mOuterRadiusSqr\",mOuterRadiusSqr);\r\n\tp_info->AddFloat(\"mInnerAvoidRadiusSqr\",mInnerAvoidRadiusSqr);\r\n\tp_info->AddFloat(\"mOuterAvoidRadiusSqr\",mOuterAvoidRadiusSqr);\r\n\r\n\t\r\n// we call the base component's GetDebugInfo, so we can add info from the common base component\t\t\t\t\t\t\t\t\t\t \r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#define HUGE_DISTANCE_SQUARED ( HUGE_DISTANCE * HUGE_DISTANCE )\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CSkaterProximityComponent::GetDistToLocalSkaterSquared()\r\n{\r\n\tCCompositeObject* pObj = Mdl::Skate::Instance()->GetLocalSkater();\r\n\t\r\n\tif ( pObj && ( pObj != GetObject() ))\r\n\t{\r\n\t\treturn Mth::DistanceSqr( pObj->GetPos(), GetObject()->GetPos() );\r\n\t}\r\n\t\r\n\treturn ( HUGE_DISTANCE_SQUARED );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CSkaterProximityComponent::GetDistToNearestSkaterSquared()\r\n{\t\r\n\tfloat nearest_distance = HUGE_DISTANCE_SQUARED;\r\n\t\r\n\tint num_skaters = Mdl::Skate::Instance()->GetNumSkaters();\r\n\t\r\n\tfor( int i = 0; i < num_skaters; i++ )\r\n\t{\r\n\t\tCCompositeObject* pObj = Mdl::Skate::Instance()->GetSkater( i );\r\n\t\tif ( pObj && ( pObj != GetObject() ))\r\n\t\t{\r\n\t\t\tfloat this_dist = Mth::DistanceSqr( pObj->GetPos(), GetObject()->GetPos() );\r\n\t\t\tif( this_dist < nearest_distance )\r\n\t\t\t{\r\n\t\t\t\tnearest_distance = this_dist;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn nearest_distance;\r\n}\r\n\r\n\r\n\r\n\t\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterProximityComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gel/Components\r\n//* FILENAME:       SkaterProximityComponent.h\r\n//* OWNER:          ???\r\n//* CREATION DATE:  ??/??/??\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERPROXIMITYCOMPONENT_H__\r\n#define __COMPONENTS_SKATERPROXIMITYCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n// Replace this with the CRCD of the component you are adding\r\n#define\t\tCRC_SKATERPROXIMITY CRCD(0x27457739,\"SkaterProximity\")\r\n\r\n//  Standard accessor macros for getting the component either from within an object, or \r\n//  given an object\t\t\t\t \r\n#define\t\tGetSkaterProximityComponent() ((Obj::CSkaterProximityComponent*)GetComponent(CRC_SkaterProximity))\r\n#define\t\tGetSkaterProximityComponentFromObject(pObj) ((Obj::CSkaterProximityComponent*)(pObj)->GetComponent(CRC_SkaterProximity))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CSkaterProximityComponent : public CBaseComponent\r\n{\r\n\r\n// Bitfield flags, so we don't trigger things twice\r\nenum\t{\r\n\tINNER=0x0001,\r\n\tOUTER=0x0002,\r\n\tINNERAVOID=0x0004,\r\n\tOUTERAVOID=0x0008,\r\n};\r\n\r\npublic:\r\n    CSkaterProximityComponent();\r\n    virtual ~CSkaterProximityComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tfloat\t\t\t\t\tGetDistToLocalSkaterSquared();\r\n\tfloat\t\t\t\t\tGetDistToNearestSkaterSquared();\r\n\r\nprotected:\r\n\tfloat\t\t\t\t\tmInnerRadiusSqr;\r\n\tfloat\t\t\t\t\tmOuterRadiusSqr;\r\n\r\n\tfloat\t\t\t\t\tmInnerAvoidRadiusSqr;\r\n\tfloat\t\t\t\t\tmOuterAvoidRadiusSqr;\r\n\t\r\n\tuint32\t\t\t\t\tm_flags;\r\n\t\r\n\t\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterRotateComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterRotateComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/6/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skaterrotatecomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent* CSkaterRotateComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterRotateComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterRotateComponent::CSkaterRotateComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERROTATE );\r\n\t\r\n\tmp_core_physics_component = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterRotateComponent::~CSkaterRotateComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterRotateComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tfor (int n = 3; n--; )\r\n\t{\r\n\t\tmp_rotations[n].active = false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterRotateComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterRotateComponent::Finalize (   )\r\n{\r\n\tmp_core_physics_component = GetSkaterCorePhysicsComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_core_physics_component);\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterRotateComponent::Update()\r\n{\r\n\tMth::Matrix rotation_matrix;\r\n\t\r\n\tfor (int n = X; n < Z + 1; n++)\r\n\t{\r\n\t\tSRotation& rotation = mp_rotations[n];\r\n\t\t\r\n\t\tif (!rotation.active) continue;\r\n\t\t\r\n\t\tfloat amount = Tmr::FrameLength() * rotation.angle_step;\r\n\t\t\r\n\t\trotation.angle_traversed += Mth::Abs(amount);\r\n\t\t\r\n\t\tif (rotation.angle_traversed >= rotation.angle)\r\n\t\t{\r\n\t\t\trotation.active = false;\r\n\t\t\tamount -= Mth::Sgn(amount) * (rotation.angle_traversed - rotation.angle);\r\n\t\t}\r\n\t\t\r\n\t\tMth::CreateRotateMatrix(rotation_matrix, n, amount);\r\n\t\t\r\n\t\tGetObject()->m_matrix = rotation_matrix * GetObject()->m_matrix;\r\n\t\tmp_core_physics_component->m_lerping_display_matrix = rotation_matrix * mp_core_physics_component->m_lerping_display_matrix;;\r\n\t}\r\n\t\r\n\tif (!mp_rotations[0].active && !mp_rotations[1].active && !mp_rotations[2].active)\r\n\t{\r\n\t\tSuspend(true);\r\n\t}\r\n}\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterRotateComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | Rotate | \r\n        // @parmopt float | Duration | 0.0 | duration time (default is ms)\r\n        // @flag seconds | time in seconds\r\n        // @flag frames | time in frames\r\n        // @parmopt float | x | 0.0 | x rotation angle\r\n        // @parmopt float | y | 0.0 | y rotation angle\r\n        // @parmopt float | z | 0.0 | z rotation angle\r\n        // @parmopt name | Node | | Node to point to. Currently only supported if a duration is specified.\r\n\t\tcase CRCC(0xc876adf3, \"Rotate\"):\r\n\t\t{\r\n\t\t\tfloat duration;\r\n\t\t\tif (pParams->GetFloat(CRCD(0x79a07f3f, \"Duration\"), &duration))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(duration > 0.0f, (\"Zero or negative Rotate Duration\"));\r\n\t\t\t\t\r\n\t\t\t\tif (pParams->ContainsFlag(CRCD(0xd029f619, \"Seconds\")) || pParams->ContainsFlag(CRCD(0x49e0ee96, \"Second\")))\r\n\t\t\t\t{\r\n\t\t\t\t\t// Seconds is what we want, so nothing to do\r\n\t\t\t\t}\r\n\t\t\t\telse if (pParams->ContainsFlag(CRCD(0x19176c5, \"Frames\")) || pParams->ContainsFlag(CRCD(0x4a07c332, \"Frame\")))\r\n\t\t\t\t{\r\n\t\t\t\t\t// Convert from frames to seconds\r\n\t\t\t\t\tduration /= 60.0f;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Convert from milliseconds to seconds\r\n\t\t\t\t\tduration /= 1000.0f;\r\n\t\t\t\t}\t\r\n\r\n\t\t\t\tif (pParams->GetFloat(CRCD(0x7323e97c, \"x\"), &mp_rotations[X].angle))\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_rotations[X].duration = duration;\r\n\t\t\t\t\tmp_rotations[X].angle_step = Mth::DegToRad(mp_rotations[X].angle / mp_rotations[X].duration);\r\n\t\t\t\t\tmp_rotations[X].angle = Mth::Abs(Mth::DegToRad(mp_rotations[X].angle));\r\n\t\t\t\t\tmp_rotations[X].angle_traversed = 0.0f;\r\n\t\t\t\t\tmp_rotations[X].active = true;\r\n\t\t\t\t}\t\r\n\t\t\t\tif (pParams->GetFloat(CRCD(0x424d9ea, \"y\"), &mp_rotations[Y].angle))\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_rotations[Y].duration = duration;\r\n\t\t\t\t\tmp_rotations[Y].angle_step = Mth::DegToRad(mp_rotations[Y].angle / mp_rotations[Y].duration);\r\n\t\t\t\t\tmp_rotations[Y].angle = Mth::Abs(Mth::DegToRad(mp_rotations[Y].angle));\r\n\t\t\t\t\tmp_rotations[Y].angle_traversed = 0.0f;\r\n\t\t\t\t\tmp_rotations[Y].active = true;\r\n\t\t\t\t}\t\r\n\t\t\t\tif (pParams->GetFloat(CRCD(0x9d2d8850, \"z\"), &mp_rotations[Z].angle))\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_rotations[Z].duration = duration;\r\n\t\t\t\t\tmp_rotations[Z].angle_step = Mth::DegToRad(mp_rotations[Z].angle / mp_rotations[Z].duration);\r\n\t\t\t\t\tmp_rotations[Z].angle = Mth::Abs(Mth::DegToRad(mp_rotations[Z].angle));\r\n\t\t\t\t\tmp_rotations[Z].angle_traversed = 0.0f;\r\n\t\t\t\t\tmp_rotations[Z].active = true;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t// If a node is specified, turn to point to it instead.\r\n\t\t\t\t// Added by Ken for use by Brad when making the skater turn around when he goes outside the level limits.\r\n\t\t\t\tuint32 node_name = 0;\r\n\t\t\t\tif (pParams->GetChecksum(CRCD(0x7a8017ba, \"Node\"), &node_name))\r\n\t\t\t\t{\r\n\t\t\t\t\tint node = SkateScript::FindNamedNode(node_name);\r\n\t\t\t\t\tMth::Vector node_pos;\r\n\t\t\t\t\tSkateScript::GetPosition(node, &node_pos);\r\n\t\t\t\t\r\n\t\t\t\t\tmp_rotations[Y].angle = Mth::RadToDeg(Mth::GetAngle(GetObject()->m_matrix, node_pos - GetObject()->m_pos));\r\n\t\t\t\t\t\r\n\t\t\t\t\tmp_rotations[Y].duration = duration;\r\n\t\t\t\t\tmp_rotations[Y].angle_step = Mth::DegToRad(mp_rotations[Y].angle / mp_rotations[Y].duration);\r\n\t\t\t\t\tmp_rotations[Y].angle = Mth::Abs(Mth::DegToRad(mp_rotations[Y].angle));\r\n\t\t\t\t\tmp_rotations[Y].angle_traversed = 0.0f;\r\n\t\t\t\t\tmp_rotations[Y].active = true;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tSuspend(false);\r\n\t\t\t} // END if duration specified\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// rotate immediately\r\n\t\t\t\tfloat angle;\r\n\t\t\t\tif (pParams->GetFloat(CRCD(0x7323e97c, \"x\"), &angle))\r\n\t\t\t\t{\r\n\t\t\t\t\tGetObject()->m_matrix.RotateXLocal(Mth::DegToRad(angle));\t\t\t\t\r\n\t\t\t\t\tmp_core_physics_component->ResetLerpingMatrix();\r\n\t\t\t\t}\r\n\t\t\t\telse if (pParams->GetFloat(CRCD(0x424d9ea, \"y\"), &angle))\r\n\t\t\t\t{\r\n\t\t\t\t\tGetObject()->m_matrix.RotateYLocal(Mth::DegToRad(angle));\t\t\t\t\r\n\t\t\t\t\tmp_core_physics_component->ResetLerpingMatrix();\r\n\t\t\t\t}\r\n\t\t\t\telse if (pParams->GetFloat(CRCD(0x9d2d8850, \"z\"), &angle))\r\n\t\t\t\t{\r\n\t\t\t\t\tGetObject()->m_matrix.RotateZLocal(Mth::DegToRad(angle));\r\n\t\t\t\t\tmp_core_physics_component->ResetLerpingMatrix();\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// if no parameters are given, rotate 180 degrees about Y\r\n\t\t\t\t\tGetObject()->m_matrix[Z].Negate();\r\n\t\t\t\t\tGetObject()->m_matrix[X].Negate();\r\n\t\t\t\t\tmp_core_physics_component->ResetLerpingMatrix();\r\n\t\t\t\t\t\r\n\t\t\t\t\tmp_core_physics_component->mRail_Backwards = !mp_core_physics_component->mRail_Backwards;\r\n\t\t\t\t}\r\n\t\t\t} // END else no Duration specified\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterRotateComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterRotateComponent::GetDebugInfo\"));\r\n\t\r\n\tScript::CArray* p_rotations_array = new Script::CArray;\r\n\tp_rotations_array->SetSizeAndType(3, ESYMBOLTYPE_STRUCTURE);\r\n\tfor (int n = 3; n--; )\r\n\t{\r\n\t\tSRotation& rotation = mp_rotations[n];\r\n\t\t\r\n\t\tScript::CStruct* p_rotation_struct = new Script::CStruct;\r\n\t\tp_rotation_struct->AddInteger(\"active\", rotation.active);\r\n\t\tp_rotation_struct->AddFloat(\"angle\", rotation.angle);\r\n\t\tp_rotation_struct->AddFloat(\"duration\", rotation.duration);\r\n\t\tp_rotation_struct->AddFloat(\"angle_step\", rotation.angle_step);\r\n\t\tp_rotation_struct->AddFloat(\"angle_traversed\", rotation.angle_traversed);\r\n\t\t\r\n\t\tp_rotations_array->SetStructure(n, p_rotation_struct);\r\n\t}\r\n\tp_info->AddArrayPointer(\"mp_rotations\", p_rotations_array);\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterRotateComponent::StopAllRotation (   )\r\n{\r\n\tfor (int n = 3; n--; )\r\n\t{\r\n\t\tmp_rotations[n].active = false;\r\n\t}\r\n}\r\n  \r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterRotateComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterRotateComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/6/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERROTATECOMPONENT_H__\r\n#define __COMPONENTS_SKATERROTATECOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#define\t\tCRC_SKATERROTATE CRCD(0x52d61a0d, \"SkaterRotate\")\r\n\r\n#define\t\tGetSkaterRotateComponent() ((Obj::CSkaterRotateComponent*)GetComponent(CRC_SKATERROTATE))\r\n#define\t\tGetSkaterRotateComponentFromObject(pObj) ((Obj::CSkaterRotateComponent*)(pObj)->GetComponent(CRC_SKATERROTATE))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CSkaterCorePhysicsComponent;\r\n\r\nclass CSkaterRotateComponent : public CBaseComponent\r\n{\r\n\tstruct SRotation\r\n\t{\r\n\t\tfloat angle;\r\n\t\tfloat duration;\r\n\t\tfloat angle_step;\r\n\t\tfloat angle_traversed;\r\n\t\tbool active;\r\n\t};\r\n\t\r\npublic:\r\n    CSkaterRotateComponent();\r\n    virtual ~CSkaterRotateComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tbool\t\t\t\t\t\t\tIsApplyingRotation ( unsigned axis );\r\n\tvoid\t\t\t\t\t\t\tStopAllRotation (   );\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\t\r\nprivate:\r\n\tSRotation\t\t\t\t\t\tmp_rotations[3];\r\n\t\r\n\t// peer components\r\n\tCSkaterCorePhysicsComponent*\tmp_core_physics_component;\r\n};\r\n\r\ninline bool CSkaterRotateComponent::IsApplyingRotation ( unsigned axis )\r\n{\r\n\tDbg_Assert(axis < 3);\r\n\treturn mp_rotations[axis].active;\r\n}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterRunTimerComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterRunTimerComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  7/17/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skaterruntimercomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/components/walkcomponent.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSkaterRunTimerComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterRunTimerComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterRunTimerComponent::CSkaterRunTimerComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERRUNTIMER );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterRunTimerComponent::~CSkaterRunTimerComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterRunTimerComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tm_state = INACTIVE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterRunTimerComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterRunTimerComponent::Finalize()\r\n{\r\n\tmp_walk_component = GetWalkComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_walk_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterRunTimerComponent::Update()\r\n{\r\n\tif (m_state == ACTIVE_RUNNING)\r\n\t{\r\n\t\tswitch (mp_walk_component->GetState())\r\n\t\t{\r\n\t\t\tcase CWalkComponent::WALKING_HANG:\r\n\t\t\tcase CWalkComponent::WALKING_LADDER:\r\n\t\t\tcase CWalkComponent::WALKING_ANIMWAIT:\r\n\t\t\t\tm_timer -= Script::GetFloat(CRCD(0x92fb4d09, \"Hang_Run_Timer_Speed_Adjustment\")) * Tmr::FrameLength();\r\n\t\t\t\tbreak;\r\n\t\t\t\t\r\n\t\t\tdefault:\r\n\t\t\t\tm_timer -= Tmr::FrameLength();\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tif (m_timer < 0.0f)\r\n\t\t{\r\n\t\t\tset_state(ACTIVE_TIME_UP);\r\n\t\t\tGetObject()->SelfEvent(CRCD(0x9e22a8e9, \"RunTimerUp\"));\r\n\t\t}\r\n\t}\r\n\telse if (m_state == ACTIVE_TIME_UP)\r\n\t{\r\n\t\tGetObject()->SelfEvent(CRCD(0x9e22a8e9, \"RunTimerUp\"));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterRunTimerComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | RunTimer_Pause | pauses the run timer\r\n\t\tcase CRCC(0x82445966, \"RunTimer_Pause\"):\r\n\t\t\tpause();\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t// @script | RunTimer_UnPause | unpauses the run timer\r\n\t\tcase CRCC(0x956236b1, \"RunTimer_UnPause\"):\r\n\t\t\tunpause();\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | RunTimer_GetFactorComplete | returns the time left of the run timer as a float between zero and one in FactorComplete\r\n\t\tcase CRCC(0xab04cbf9, \"RunTimer_GetFactorComplete\"):\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x41f56511, \"FactorComplete\"), m_timer / GetSkater()->GetScriptedStat(CRCD(0xb84f532, \"Physics_RunTimer_Duration\")));\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t// @script | RunTimer_GetRunTimerControllerId | returns the id of the display controller script for the run timer in RunTimerControllerId\r\n\t\tcase CRCC(0x96d81d8e, \"RunTimer_GetRunTimerControllerId\"):\r\n\t\t\tpScript->GetParams()->AddChecksum(CRCD(0x39778122, \"RunTimerControllerId\"), get_run_timer_controller_id());\r\n\t\t\tbreak; \r\n\t\t\t\r\n\t\t// @script | RunTimer_GetRunTimerId | returns the id of the display controller script for the run timer in RunTimerId\r\n\t\tcase CRCC(0x81aaa6dd, \"RunTimer_GetRunTimerId\"):\r\n\t\t\tpScript->GetParams()->AddChecksum(CRCD(0x628f21c9, \"RunTimerId\"), CRCD(0x7d42821c, \"the_run_timer\") + GetSkater()->GetSkaterNumber());\r\n\t\t\tbreak; \r\n\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterRunTimerComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterRunTimerComponent::GetDebugInfo\"));\r\n\t\r\n\tstatic const uint32 states [   ] =\r\n\t{\r\n\t\tCRCD(0x742cf11f, \"INACTIVE\"),\r\n\t\tCRCD(0x5392ca8e, \"ACTIVE_RUNNING\"),\r\n\t\tCRCD(0x26776873, \"ACTIVE_PAUSED\"),\r\n\t\tCRCD(0xdef417fa, \"ACTIVE_TIME_UP\")\r\n\t};\r\n\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), states[m_state]);\r\n\t\r\n\tp_info->AddFloat(CRCD(0xd9d89e81, \"m_timer\"), m_timer);\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterRunTimerComponent::ComboEnded (   )\r\n{\r\n\tif (Script::FindSpawnedScriptWithID(get_run_timer_controller_id()))\r\n\t{\r\n\t\tCTracker::Instance()->LaunchEvent(CRCD(0x813cc576, \"HideRunTimer\"), get_run_timer_controller_id(), GetObject()->GetID());\r\n\t}\r\n\t\r\n\tset_state(INACTIVE);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterRunTimerComponent::unpause (   )\r\n{\r\n\tif (m_state == INACTIVE) return;\r\n\t\t\r\n\tset_state(m_timer > 0.0f ? ACTIVE_RUNNING : ACTIVE_TIME_UP);\r\n\t\r\n\tif (m_unpause_count < vRT_NUM_TIME_CHUNKS)\r\n\t{\r\n\t\tfloat max_timer = (vRT_NUM_TIME_CHUNKS - m_unpause_count) * GetSkater()->GetScriptedStat(CRCD(0xb84f532, \"Physics_RunTimer_Duration\")) / vRT_NUM_TIME_CHUNKS;\r\n\t\tm_timer = Mth::Min(m_timer, max_timer);\r\n\t}\r\n\t\r\n\tm_unpause_count++;\r\n\t\r\n\tCTracker::Instance()->LaunchEvent(CRCD(0x47eec244, \"ShowRunTimer\"), get_run_timer_controller_id(), GetObject()->GetID());\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterRunTimerComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterRunTimerComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  7/17/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERRUNTIMERCOMPONENT_H__\r\n#define __COMPONENTS_SKATERRUNTIMERCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/objtrack.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#define\t\tCRC_SKATERRUNTIMER CRCD(0x8bce7e66, \"SkaterRunTimer\")\r\n\r\n#define\t\tGetSkaterRunTimerComponent() ((Obj::CSkaterRunTimerComponent*)GetComponent(CRC_SKATERRUNTIMER))\r\n#define\t\tGetSkaterRunTimerComponentFromObject(pObj) ((Obj::CSkaterRunTimerComponent*)(pObj)->GetComponent(CRC_SKATERRUNTIMER))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tclass CWalkComponent;\r\n\r\nclass CSkaterRunTimerComponent : public CBaseComponent\r\n{\r\n\tenum EState\r\n\t{\r\n\t\tINACTIVE,\r\n\t\tACTIVE_RUNNING,\r\n\t\tACTIVE_PAUSED,\r\n\t\tACTIVE_TIME_UP\r\n\t};\r\n\t\r\n\t// number of divisions of the timer; you always lose at least one chunk of timer per runout\r\n\tenum { vRT_NUM_TIME_CHUNKS = 8 };\r\n\t\r\npublic:\r\n    CSkaterRunTimerComponent();\r\n    virtual ~CSkaterRunTimerComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tFinalize();\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\t\r\n\tvoid\t\t\t\t\t\t\tComboStarted (   );\r\n\tvoid\t\t\t\t\t\t\tComboEnded (   );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\tupdate_timer (   );\r\n\tvoid\t\t\t\t\t\t\tpause (   );\r\n\tvoid\t\t\t\t\t\t\tunpause (   );\r\n\tbool\t\t\t\t\t\t\tis_timer_up (   );\r\n\tvoid\t\t\t\t\t\t\tset_state ( EState state );\r\n\tuint32\t\t\t\t\t\t\tget_run_timer_controller_id (   );\r\n\t\r\nprivate:\r\n\tEState\t\t\t\t\t\t\tm_state;\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_timer;\r\n\t\r\n\tshort\t\t\t\t\t\t\tm_unpause_count;\r\n\t\r\n\tCWalkComponent*\t\t\t\t\tmp_walk_component;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterRunTimerComponent::set_state ( EState state )\r\n{\r\n\tm_state = state;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint32 CSkaterRunTimerComponent::get_run_timer_controller_id (   )\r\n{\r\n\treturn CRCD(0x83321dea, \"RunTimerController\") + GetSkater()->GetSkaterNumber();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterRunTimerComponent::ComboStarted (   )\r\n{\r\n\tm_timer = GetSkater()->GetScriptedStat(CRCD(0xb84f532, \"Physics_RunTimer_Duration\"));\r\n\tm_unpause_count = 0;\r\n\t\r\n\tset_state(ACTIVE_PAUSED);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterRunTimerComponent::update_timer (   )\r\n{\r\n\tm_timer -= Tmr::FrameLength();\r\n\t\r\n\tif (m_timer < 0.0f)\r\n\t{\r\n\t\tset_state(ACTIVE_TIME_UP);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterRunTimerComponent::pause (   )\r\n{\r\n\tif (m_state == INACTIVE) return;\r\n\t\r\n\tset_state(ACTIVE_PAUSED);\r\n\t\r\n\tCTracker::Instance()->LaunchEvent(CRCD(0x813cc576, \"HideRunTimer\"), get_run_timer_controller_id(), GetObject()->GetID());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline bool CSkaterRunTimerComponent::is_timer_up (   )\r\n{\r\n\tDbg_Assert(m_state != INACTIVE);\r\n\t\r\n\treturn m_state == ACTIVE_TIME_UP;\r\n}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterScoreComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterScoreComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/12/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skaterscorecomponent.h>\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/gamenet/gamemsg.h>\r\n#include <sk/modules/skate/skate.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\nextern bool g_CheatsEnabled;\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent* CSkaterScoreComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterScoreComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterScoreComponent::CSkaterScoreComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERSCORE );\r\n\tmp_score = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterScoreComponent::~CSkaterScoreComponent()\r\n{\r\n\tif (mp_score)\r\n\t{\r\n\t\tdelete mp_score;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterScoreComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tDbg_MsgAssert(GetObject()->GetType() == SKATE_TYPE_SKATER, (\"CSkaterScoreComponent added to non-skater composite object\"));\r\n\t\r\n\tif (!mp_score)\r\n\t{\r\n\t\tmp_score = new Mdl::Score();\r\n\t\tmp_score->SetSkaterId(GetObject()->GetID());\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterScoreComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterScoreComponent::Update()\r\n{\r\n\t// NOTE: in fact, non-local skaters may not need a score component at all\r\n\tif (!GetSkater()->IsLocalClient())\r\n\t{\r\n\t\tSuspend(true);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tmp_score->Update();\r\n\t\r\n\tif (GetSkater()->m_always_special || Mdl::Skate::Instance()->GetCareer()->GetCheat(CRCD(0xeefecf1b, \"CHEAT_ALWAYS_SPECIAL\")))\r\n\t{\r\n\t\t// Here, set the flag. It may seem redundant, but the above line is very likely\r\n\t\t// to be hacked by gameshark. They probably won't notice this one, which will\r\n\t\t// set the flags as if they had actually enabled the cheat -- which enables us\r\n\t\t// to detect that it has been turned on more easily.\r\n\t\tMdl::Skate::Instance()->GetCareer()->SetGlobalFlag( Script::GetInteger(CRCD(0xeefecf1b, \"CHEAT_ALWAYS_SPECIAL\")));\r\n\t\tmp_score->ForceSpecial();\r\n\t\tg_CheatsEnabled = true;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterScoreComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\t// @script | LastScoreLandedGreaterThan | Multiplayer-safe version \r\n\t\t// of SkaterLastScoreLandedGreaterThan\r\n\t\t// Example: if LastScoreLandedGreaterThan 2000 --do cool stuff-- endif\r\n\t\t// @uparm 1 | Score (int)\r\n\t\tcase CRCC(0xe0112aab, \"LastScoreLandedGreaterThan\"):\r\n\t\t{\r\n\t\t\tint score;\r\n\t\t\tpParams->GetInteger(NO_NAME, &score, Script::ASSERT);\r\n\t\t\treturn mp_score->GetLastScoreLanded() > score ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | LastScoreLandedLessThan | Multiplayer-safe version \r\n\t\t// of SkaterLastScoreLandedLessThan\r\n\t\t// Example: if LastScoreLandedLessThan 2000 --do cool stuff-- endif\r\n\t\t// @uparm 1 | Score (int)\r\n\t\tcase CRCC(0x3c445a82, \"LastScoreLandedLessThan\"):\r\n\t\t{\r\n\t\t\tint score;\r\n\t\t\tpParams->GetInteger(NO_NAME, &score, Script::ASSERT);\r\n\t\t\treturn mp_score->GetLastScoreLanded() < score ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | TotalScoreGreaterThan | Multiplayer-safe version \r\n\t\t// of SkaterTotalScoreGreaterThan\r\n\t\t// Example: if TotalScoreGreaterThan 2000 --do cool stuff-- endif\r\n\t\t// @uparm 1 | Score (int)\r\n\t\tcase CRCC(0x8bf43831, \"TotalScoreGreaterThan\"):\r\n\t\t{\r\n\t\t\tint score;\r\n\t\t\tpParams->GetInteger(NO_NAME, &score, Script::ASSERT);\r\n\t\t\treturn mp_score->GetTotalScore() > score ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | TotalScoreLessThan | Multiplayer-safe version \r\n\t\t// of SkaterTotalScoreLessThan\r\n\t\t// Example: if TotalScoreLessThan 2000 --do cool stuff-- endif\r\n\t\t// @uparm 1 | Score (int)\r\n\t\tcase CRCC(0xdf14bd98, \"TotalScoreLessThan\"):\r\n\t\t{\r\n\t\t\tint score;\r\n\t\t\tpParams->GetInteger(NO_NAME, &score, Script::ASSERT);\r\n\t\t\treturn mp_score->GetTotalScore() < score ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | CurrentScorePotGreaterThan | Multiplayer-safe version \r\n\t\t// of SkaterCurrentScorePotGreaterThan\r\n\t\t// Example: if CurrentScorePotGreaterThan 2000 --do cool stuff-- endif\r\n\t\t// @uparm 1 | Score (int)\r\n\t\tcase CRCC(0xd19bdb50, \"CurrentScorePotGreaterThan\"):\r\n\t\t{\r\n\t\t\tint score;\r\n\t\t\tpParams->GetInteger(NO_NAME, &score, Script::ASSERT);\r\n\t\t\treturn mp_score->GetScorePotValue() > score ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\r\n\t\t// @script | GetTotalScore | returns the total score of the skater\r\n\t\t// in TotalScore\r\n\t\tcase CRCC( 0x8f2fe3d3, \"GetTotalScore\" ):\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddInteger( CRCD( 0xee5b2b48, \"TotalScore\" ), mp_score->GetTotalScore() );\r\n\t\t\treturn CBaseComponent::MF_TRUE;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | CurrentScorePotLessThan | Multiplayer-safe version \r\n\t\t// of SkaterCurrentScorePotLessThan\r\n\t\t// Example: if CurrentScorePotLessThan 2000 --do cool stuff-- endif\r\n\t\t// @uparm 1 | Score (int)\r\n\t\tcase CRCC(0x56645fc6, \"CurrentScorePotLessThan\"):\r\n\t\t{\r\n\t\t\tint score;\r\n\t\t\tpParams->GetInteger(NO_NAME, &score, Script::ASSERT);\r\n\t\t\treturn mp_score->GetScorePotValue() < score ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | GetNumberOfNonGapTricks | returns number of non-gap tricks currently in the combo\r\n\t\tcase CRCC(0xc068ea59, \"GetNumberOfNonGapTricks\"):\r\n\t\t\tpScript->GetParams()->AddInteger(CRCD(0xffe7e02c, \"NumberOfNonGapTricks\"), mp_score->GetNumberOfNonGapTricks());\r\n\t\t\tbreak;\r\n\t\t\r\n        // @script | GotSpecial | true if special is active\r\n\t\tcase CRCC(0x5589b902, \"GotSpecial\"):\t\r\n\t\t\treturn mp_score->GetSpecialState() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n        \r\n\t\t// @script | TweakTrick | \r\n        // @uparm 0 | tweak\r\n\t\tcase CRCC(0xbe3e5463, \"TweakTrick\"):\r\n\t\t{\r\n\t\t\tint Tweak = 0;\r\n\t\t\tpParams->GetInteger(NO_NAME, &Tweak);\r\n\t\t\t\r\n\t\t\tmp_score->TweakTrick(Tweak);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t// @script | IsLatestTrick | \r\n\t\tcase CRCC(0x2877b61a, \"IsLatestTrick\"):\r\n\t\t{\r\n\t\t\tuint32 key_combo;\r\n\t\t\tif (pParams->GetChecksum(CRCD(0x95e16467, \"KeyCombo\"), &key_combo))\r\n\t\t\t{\r\n\t\t\t\tint spin = 0;\r\n\t\t\t\tif (pParams->GetInteger(CRCD(0xedf5db70, \"Spin\"), &spin))\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(spin % 180 == 0, (\"IsLatestTrick called with a spin value of %i which is not a multiple of 180\", spin));\r\n\t\t\t\t\tspin /= 180;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tint num_taps = 1;\r\n\t\t\t\tpParams->GetInteger(CRCD(0xc82cf71b, \"NumTaps\"), &num_taps);\r\n\t\t\t\t\r\n\t\t\t\treturn mp_score->IsLatestTrick(key_combo, spin, false, num_taps) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tconst char* trick_text;\r\n\t\t\t\tif (pParams->GetString(CRCD(0x3eafa520, \"TrickText\"), &trick_text))\r\n\t\t\t\t{\r\n\t\t\t\t\tint spin = 0;\r\n\t\t\t\t\tif (pParams->GetInteger(CRCD(0xedf5db70, \"Spin\"), &spin))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_MsgAssert(spin % 180 == 0, (\"IsLatestTrick called with a spin value of %i which is not a multiple of 180\", spin));\r\n\t\t\t\t\t\tspin /= 180;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tint num_taps = 1;\r\n\t\t\t\t\tpParams->GetInteger(CRCD(0xc82cf71b, \"NumTaps\"), &num_taps);\r\n\t\t\t\t\t\r\n\t\t\t\t\treturn mp_score->IsLatestTrickByName(Script::GenerateCRC(trick_text), spin, false, num_taps) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(false, (\"IsLatestTrick must have either a KeyCombo or a TrickText parameter\"));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterScoreComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterScoreComponent::GetDebugInfo\"));\r\n\t\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterScoreComponent::Reset (   )\r\n{\r\n\tmp_score->Reset();\r\n\r\n\tmp_score->SetBalanceMeter(false);\r\n\tmp_score->SetManualMeter(false);\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterScoreComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterScoreComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/12/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERSCORECOMPONENT_H__\r\n#define __COMPONENTS_SKATERSCORECOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#define\t\tCRC_SKATERSCORE CRCD(0xd262802f, \"SkaterScore\")\r\n\r\n#define\t\tGetSkaterScoreComponent() ((Obj::CSkaterScoreComponent*)GetComponent(CRC_SKATERSCORE))\r\n#define\t\tGetSkaterScoreComponentFromObject(pObj) ((Obj::CSkaterScoreComponent*)(pObj)->GetComponent(CRC_SKATERSCORE))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CSkaterScoreComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkaterScoreComponent();\r\n    virtual ~CSkaterScoreComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\tMdl::Score*\t\t\t\t\t\tGetScore() { return mp_score; }\r\n\t\r\n\tvoid\t\t\t\t\t\t\tReset (   );\r\n\t\r\nprivate:\r\n\tMdl::Score*\t\t\t\t\t\tmp_score;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterSoundComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterSoundComponent.cpp\r\n//* OWNER:\t\t\tDan\r\n//* CREATION DATE:  2/27/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skatersoundcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/environment/terrain.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent* CSkaterSoundComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterSoundComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterSoundComponent::CSkaterSoundComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERSOUND );\r\n\t\r\n\tm_is_rail_sliding = false;\r\n\tm_max_speed = 1.0f;\r\n\tm_vol_mult = 1.0f;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterSoundComponent::~CSkaterSoundComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tfloat vol_mult;\r\n\tif (pParams->GetFloat( CRCD(0xf1a99b27,\"volume_mult\"), &vol_mult))\r\n\t{\r\n\t\tSetVolumeMultiplier(vol_mult);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::Update()\r\n{\r\n\t// As a minor optimization, CSkaterSoundComponent is always suspended.\r\n\tSuspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterSoundComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | PlayJumpSound |\r\n\t\tcase CRCC(0xe338369, \"PlayJumpSound\"):\r\n\t\t{\r\n\t\t\tswitch ( m_stateType )\r\n\t\t\t{\r\n\t\t\t\tcase GROUND:\r\n\t\t\t\tcase AIR:\r\n\t\t\t\t\tPlayJumpSound(GetObject()->GetVel().Length() / m_max_speed);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t \r\n\t\t\t\tcase RAIL:\r\n\t\t\t\t\tPlayJumpSound(GetObject()->GetVel().Length() / m_max_speed);\r\n\t\t\t\t\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        // @script | PlayLandSound | \r\n\t\tcase CRCC(0x2c779f22, \"PlayLandSound\"):\r\n\t\t{\r\n\t\t\tswitch ( m_stateType )\r\n\t\t\t{\r\n\t\t\t\tcase GROUND:\r\n\t\t\t\tcase AIR:\r\n\t\t\t\t\tPlayLandSound(Mth::Abs(GetObject()->GetVel()[Y]) / m_max_speed);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase RAIL:\r\n\t\t\t\t\tPlayLandSound(GetObject()->GetVel().Length() / m_max_speed);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | PlayBonkSound |\r\n\t\tcase CRCC(0x0069e457, \"PlayBonkSound\"):\r\n\t\t{\r\n\t\t\tPlayBonkSound(GetObject()->GetVel().Length() / m_max_speed);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        // @script | PlayCessSound | \r\n\t\tcase CRCC(0x6f5e9124, \"PlayCessSound\"):\r\n\t\t{\r\n\t\t\tPlayCessSound(GetObject()->GetVel().Length() / m_max_speed);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterSoundComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::PlayLandSound ( float speed_fraction )\r\n{\r\n\tETerrainType terrain;\r\n\tif ( m_stateType == GROUND || m_stateType == AIR )\r\n\t{\r\n\t\tterrain = m_lastTerrain;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tterrain = m_terrain;\r\n\t}\r\n\t\r\n\tPlayLandSound(speed_fraction, terrain);\r\n}\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::PlayLandSound ( float speed_fraction, ETerrainType terrain )\r\n{\r\n\tEnv::ETerrainActionType table;\r\n\tif ( m_stateType == RAIL )\r\n\t{\r\n\t\ttable = m_is_rail_sliding ? Env::vTABLE_SLIDELAND : Env::vTABLE_GRINDLAND;\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttable = Env::vTABLE_LAND;\r\n\t}\r\n\t\r\n\tspeed_fraction *= 100.0f;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (Script::GetInteger(CRCD(0xb9ba2d27, \"debug_skater_triggered_sounds\")))\r\n\t{\r\n\t\tDbg_Message(\"Playing sound [land]:   %.1f\", speed_fraction);\r\n\t}\r\n\t#endif\r\n\t\r\n\tEnv::CTerrainManager::sPlaySound(table, terrain, GetObject()->GetPos(), speed_fraction * m_vol_mult, speed_fraction, speed_fraction);\r\n}\r\n   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::PlayJumpSound ( float speed_fraction )\r\n{\r\n\tETerrainType terrain;\r\n\tif ( m_stateType == GROUND || m_stateType == AIR )\r\n\t{\r\n\t\tterrain = m_lastTerrain;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tterrain = m_terrain;\r\n\t}\r\n\t\r\n\tPlayJumpSound(speed_fraction, terrain);\r\n}\r\n   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::PlayJumpSound ( float speed_fraction, ETerrainType terrain )\r\n{\r\n\tPlayJumpSound(speed_fraction, terrain, m_stateType);\r\n}\r\n   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::PlayJumpSound ( float speed_fraction, ETerrainType terrain, EStateType stateType )\r\n{\r\n\tEnv::ETerrainActionType table;\r\n\tif ( stateType == RAIL )\r\n\t{\r\n\t\ttable = m_is_rail_sliding ? Env::vTABLE_SLIDEJUMP : Env::vTABLE_GRINDJUMP; \r\n\t}\r\n\telse\r\n\t{\r\n\t\ttable = Env::vTABLE_JUMP;\r\n\t}\r\n\t\r\n\tspeed_fraction *= 100.0f;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (Script::GetInteger(CRCD(0xb9ba2d27, \"debug_skater_triggered_sounds\")))\r\n\t{\r\n\t\tDbg_Message(\"Playing sound [ollie]:  %.1f\", speed_fraction);\r\n\t}\r\n\t#endif\r\n\r\n\tEnv::CTerrainManager::sPlaySound(table, terrain, GetObject()->GetPos(), speed_fraction * m_vol_mult, speed_fraction, speed_fraction);\r\n}\r\n   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::PlayBonkSound ( float speed_fraction )\r\n{\r\n\tPlayBonkSound(speed_fraction, m_terrain);\r\n}\r\n   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::PlayBonkSound ( float speed_fraction, ETerrainType terrain )\r\n{\r\n\tspeed_fraction *= 100.0f;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (Script::GetInteger(CRCD(0xb9ba2d27, \"debug_skater_triggered_sounds\")))\r\n\t{\r\n\t\tDbg_Message(\"Playing sound [bonk]:   %.1f\", speed_fraction);\r\n\t}\r\n\t#endif\r\n\r\n\tEnv::CTerrainManager::sPlaySound(Env::vTABLE_BONK, terrain, GetObject()->GetPos(), speed_fraction * m_vol_mult, speed_fraction, speed_fraction);\r\n}\r\n   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::PlayCessSound ( float speed_fraction )\r\n{\r\n\tPlayCessSound(speed_fraction, m_terrain);\r\n}\r\n   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::PlayCessSound ( float speed_fraction, ETerrainType terrain )\r\n{\r\n\tspeed_fraction *= 100.0f;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (Script::GetInteger(CRCD(0xb9ba2d27, \"debug_skater_triggered_sounds\")))\r\n\t{\r\n\t\tDbg_Message(\"Playing sound [revert]: %.1f\", speed_fraction);\r\n\t}\r\n\t#endif\r\n\r\n\tEnv::CTerrainManager::sPlaySound(Env::vTABLE_CESS, terrain, GetObject()->GetPos(), speed_fraction * m_vol_mult, speed_fraction, speed_fraction);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterSoundComponent::SetVolumeMultiplier( float mult )\r\n{\r\n\tDbg_MsgAssert( mult >= 0.0f && mult <= 1.0f, ( \"SetVolumeMultiplier called with bad mult value: %f\", mult ) );\r\n\tm_vol_mult = mult;\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterSoundComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterSoundComponent.cpp\r\n//* OWNER:\t\t\tDan\r\n//* CREATION DATE:  2/27/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERSOUNDCOMPONENT_H__\r\n#define __COMPONENTS_SKATERSOUNDCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/objects/skaterflags.h>\r\n\r\n#include <gfx/nxflags.h>\r\n\r\n#define\t\tCRC_SKATERSOUND CRCD(0x187574fa, \"SkaterSound\")\r\n\r\n#define\t\tGetSkaterSoundComponent() ((Obj::CSkaterSoundComponent*)GetComponent(CRC_SKATERSOUND))\r\n#define\t\tGetSkaterSoundComponentFromObject(pObj) ((Obj::CSkaterSoundComponent*)(pObj)->GetComponent(CRC_SKATERSOUND))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CSkaterSoundComponent : public CBaseComponent\r\n{\r\npublic:\r\n    CSkaterSoundComponent();\r\n    virtual ~CSkaterSoundComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tPlayLandSound ( float speed_fraction );\r\n\tvoid\t\t\t\t\t\t\tPlayJumpSound ( float speed_fraction );\r\n\tvoid\t\t\t\t\t\t\tPlayBonkSound ( float speed_fraction );\r\n\tvoid\t\t\t\t\t\t\tPlayCessSound ( float speed_fraction );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tPlayLandSound ( float speed_fraction, ETerrainType terrain );\r\n\tvoid\t\t\t\t\t\t\tPlayJumpSound ( float speed_fraction, ETerrainType terrain );\r\n\tvoid\t\t\t\t\t\t\tPlayBonkSound ( float speed_fraction, ETerrainType terrain );\r\n\tvoid\t\t\t\t\t\t\tPlayCessSound ( float speed_fraction, ETerrainType terrain );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tPlayJumpSound ( float speed_fraction, ETerrainType terrain, EStateType stateType );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetTerrain ( ETerrainType terrain ) { m_terrain = terrain; }\r\n\tvoid\t\t\t\t\t\t\tSetLastTerrain ( ETerrainType terrain ) { m_lastTerrain = terrain; }\r\n\tvoid\t\t\t\t\t\t\tSetState ( EStateType state ) { m_stateType = state; }\r\n\tvoid\t\t\t\t\t\t\tSetIsRailSliding ( bool is_sliding ) { m_is_rail_sliding = is_sliding; }\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetMaxSpeed ( float max_speed ) { m_max_speed = max_speed; }\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetVolumeMultiplier ( float mult );\r\nprivate:\r\n\tEStateType\t\t\t\t\t\tm_stateType;\r\n\tETerrainType\t\t\t\t\tm_terrain;\r\n\tETerrainType\t\t\t\t\tm_lastTerrain;\r\n\r\n\tbool\t\t\t\t\t\t\tm_is_rail_sliding;\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_max_speed;\r\n\tfloat\t\t\t\t\t\t\tm_vol_mult;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterStancePanelComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterStancePanelComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  2/25/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skaterstancepanelcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <gfx/2d/spriteelement.h>\r\n#include <gfx/2d/screenelemman.h>\r\n\r\nnamespace Obj\r\n{\r\n\t\r\n// Component giving script control through a composite object over the input pad vibrators of the composite object's input handler.\r\n\t\r\n// Only composite objects corresponding to local clients should be given this component.\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSkaterStancePanelComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterStancePanelComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterStancePanelComponent::CSkaterStancePanelComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERSTANCEPANEL );\r\n\t\r\n\tmp_core_physics_component = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterStancePanelComponent::~CSkaterStancePanelComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStancePanelComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tm_last_stance = -1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStancePanelComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStancePanelComponent::Finalize (   )\r\n{\r\n\tmp_core_physics_component = GetSkaterCorePhysicsComponentFromObject(GetObject());\r\n\t\r\n\tDbg_Assert(mp_core_physics_component);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStancePanelComponent::Update()\r\n{\r\n\tFront::CSpriteElement* p_stance_icon = static_cast< Front::CSpriteElement* >(Front::CScreenElementManager::Instance()->GetElement(\r\n\t\tCRCD(0x968ae5dd, \"the_boardstance_sprite\") + static_cast< CSkater* >(GetObject())->GetHeapIndex()\r\n\t).Convert());\r\n\t\r\n\tDbg_Assert(p_stance_icon);\r\n\t\r\n\tint stance = determine_stance();\r\n\t\r\n\tif (stance == m_last_stance) return;\r\n\tm_last_stance = stance;\r\n\t\r\n\tif (stance == 5)\r\n\t{\r\n\t\tp_stance_icon->SetAlpha(0.0f, Front::CScreenElement::FORCE_INSTANT);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tconst static uint32 sp_texture_checksums[] =\r\n\t\t{\r\n            CRCD(0x33a15296, \"nollie_icon\"),\r\n            CRCD(0xbe91f3b6, \"fakie_icon\"),\r\n\t\t\tCRCD(0x9f9d3907, \"switch_icon\"),\r\n            CRCD(0xb793ef40, \"sw_pressure_icon\"),\r\n            CRCD(0x4e304fa1, \"pressure_icon\")\r\n\t\t};\r\n\t\t\r\n\t\tp_stance_icon->SetTexture(sp_texture_checksums[stance]);\r\n\t\tp_stance_icon->SetAlpha(1.0f, Front::CScreenElement::FORCE_INSTANT);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterStancePanelComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | InNollie | true if in nollie\r\n\t\tcase CRCC(0x1eb61dce, \"InNollie\"):\r\n\t\t\treturn m_in_nollie ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\r\n        // @script | NollieOn | sets nollie to on (check with InNollie)\r\n\t\tcase CRCC(0x41eb710b, \"NollieOn\"):\r\n\t\t\tif (m_in_nollie == false)\r\n\t\t\t{\r\n\t\t\t\tm_in_nollie = true;\r\n\t\t\t\tGetObject()->BroadcastEvent(CRCD(0x8157ab31, \"SkaterEnterNollie\"));\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n        // @script | NollieOff | sets nollie to off (check with InNollie)\r\n\t\tcase CRCC(0xfb9b7c9c, \"NollieOff\"):\r\n\t\t\tif (m_in_nollie == true)\r\n\t\t\t{\r\n\t\t\t\tm_in_nollie = false;\r\n\t\t\t\tGetObject()->BroadcastEvent(CRCD(0x3f70881a, \"SkaterExitNollie\"));\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n        // @script | InPressure | true if in pressure\r\n        case CRCC(0x9fab9d0b,\"InPressure\"):\r\n\t\t\treturn m_in_pressure ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\r\n        // @script | PressureOn | sets pressure to on (check with InPressure)\r\n\t\tcase CRCC(0xa23d710,\"PressureOn\"):\r\n\t\t\tif (m_in_pressure == false)\r\n\t\t\t{\r\n\t\t\t\tm_in_pressure = true;\r\n\t\t\t\tGetObject()->BroadcastEvent(CRCD(0x2e8de921,\"SkaterEnterPressure\"));\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n        // @script | PressureOff | sets pressure to off (check with InPressure)\r\n\t\tcase CRCC(0x71b57dd6,\"PressureOff\"):\r\n\t\t\tif (m_in_pressure == true)\r\n\t\t\t{\r\n\t\t\t\tm_in_pressure = false;\r\n\t\t\t\tGetObject()->BroadcastEvent(CRCD(0xfa9adb1d,\"SkaterExitPressure\"));\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n\t\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStancePanelComponent::GetDebugInfo ( Script::CStruct *p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterStancePanelComponent::GetDebugInfo\"));\r\n\t\r\n\tp_info->AddInteger(\"stance\", determine_stance());\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterStancePanelComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterStancePanelComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  2/25/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_STANCEPANELCOMPONENT_H__\r\n#define __COMPONENTS_STANCEPANELCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <sys/siodev.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n\r\n#define\t\tCRC_SKATERSTANCEPANEL CRCD(0x21fc3301, \"SkaterStancePanel\")\r\n\r\n#define\t\tGetSkaterStancePanelComponent() ((Obj::CSkaterStancePanelComponent*)GetComponent(CRC_SKATERSTANCEPANEL))\r\n#define\t\tGetSkaterStancePanelComponentFromObject(pObj) ((Obj::CSkaterStancePanelComponent*)(pObj)->GetComponent(CRC_SKATERSTANCEPANEL))\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass CSkaterStancePanelComponent : public CBaseComponent\r\n{\r\n\t\r\npublic:\r\n    CSkaterStancePanelComponent();\r\n    virtual ~CSkaterStancePanelComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate (   );\r\n    virtual void            \t\tInitFromStructure ( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure ( Script::CStruct* pParams );\r\n\tvirtual void\t\t\t\t\tFinalize (   );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction ( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo ( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tReset (   );\r\n\t\r\nprivate:\r\n\tint\t\t\t\t\t\t\t\tdetermine_stance (   );\r\n\t\r\nprivate:\r\n\tint\t\t\t\t\t\t\t\tm_last_stance;\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_active;\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_in_nollie;\t\t\t\t\t// Whether in Nollie stance or not.\r\n    bool\t\t\t\t\t\t\tm_in_pressure;\t\t\t\t\t// Whether in pressure stance or not.\r\n\r\n\t// peer components\r\n\tCSkaterCorePhysicsComponent*\tmp_core_physics_component;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void CSkaterStancePanelComponent::Reset (   )\r\n{\r\n\tm_last_stance = -1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline int CSkaterStancePanelComponent::determine_stance (   )\r\n{\r\n\t// regular\r\n    int stance = 5;\r\n\t\r\n    // pressure\r\n    if (m_in_pressure)\r\n\t{\r\n        // switch pressure\r\n\t\tif (mp_core_physics_component->IsSwitched())\r\n    \t{\r\n    \t\tstance -= 2;\r\n    \t}\r\n        else\r\n        {\r\n            stance -= 1;\r\n        }\r\n\t}\r\n\telse\r\n    {\r\n        // switch\r\n    \tif (mp_core_physics_component->IsSwitched())\r\n    \t{\r\n    \t\t// fakie\r\n            if (m_in_nollie)\r\n        \t{\r\n                stance -= 4;\r\n            }\r\n            else\r\n            {\r\n                stance -= 3;\r\n            }\r\n    \t}\r\n        else\r\n        {\r\n            // nollie\r\n            if (m_in_nollie)\r\n        \t{\r\n        \t\tstance -= 5;\r\n        \t}\r\n        }\r\n    }\r\n    \r\n    return stance;\r\n}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterStateComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterStateComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/31/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skaterstatecomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n/*\r\n * Holds all skater state which is needed by both local and nonlocal clients.  This way, code external to the skater can access this information in a\r\n * consistent manner, without having to know which components within the skater are controling the state.\r\n *\r\n * Currently, state within the core physics component has not been moved into theis component.\r\n */\r\n \r\nnamespace Obj\r\n{\r\n//\t\t\t\t\t\t\t\t\t\t\tFireball\t\t\t\t\t\t\t\t\t\t\r\nstatic uint32 s_powerups[vNUM_POWERUPS] = { 0xd039432c };\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSkaterStateComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterStateComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterStateComponent::CSkaterStateComponent() : CBaseComponent()\r\n{\r\n\tint i;\r\n\r\n\tSetType( CRC_SKATERSTATE );\r\n\tfor( i = 0; i < vNUM_POWERUPS; i++ )\r\n\t{\r\n\t\tm_powerups[i] = false;\r\n\t}\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterStateComponent::~CSkaterStateComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStateComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tm_state = AIR;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStateComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStateComponent::Update()\r\n{\r\n\tSuspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterStateComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n        // @script | DoingTrick | true if we're doing a trick\r\n\t\tcase 0x58ad903f: // DoingTrick\r\n\t\t\treturn DoingTrick() ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase 0xb07ac662: // HasPowerup\r\n\t\t{\r\n\t\t\tuint32 type;\r\n\r\n\t\t\tpParams->GetChecksum( NONAME, &type, true );\r\n\t\t\treturn HasPowerup( type ) ? CBaseComponent::MF_TRUE : CBaseComponent::MF_FALSE;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0xe11b7ca:\t// PickedUpPowerup\r\n\t\t{\r\n\t\t\tuint32 type;\r\n\r\n\t\t\tpParams->GetChecksum( NONAME, &type, true );\r\n\t\t\tPickedUpPowerup( type );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | GetTerrain | returns the number of the terrain in 'terrain'\r\n\t\tcase CRCC(0x44ba5fce, \"GetTerrain\"):\r\n\t\t\tpScript->GetParams()->AddInteger(CRCD(0x3789ac4e, \"terrain\"), m_terrain);\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStateComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterStateComponent::GetDebugInfo\"));\r\n\t\r\n\tconst uint32 p_state_checksums [   ] =\r\n\t{\r\n\t\tCRCD(0x58007c97, \"GROUND\"),\r\n\t\tCRCD(0x439f4704, \"AIR\"),\r\n\t\tCRCD(0xec0a1009, \"WALL\"),\r\n\t\tCRCD(0xa549b57b, \"LIP\"),\r\n\t\tCRCD(0xa6a3147e, \"RAIL\"),\r\n\t\tCRCD(0xcf74f6b7, \"WALLPLANT\")\r\n\t};\r\n\t\r\n\tconst uint32 p_flag_checksums [ NUM_ESKATERFLAGS ] =\r\n\t{\r\n\t\tCRCD(0x42f41014, \"TENSE\"),\r\n\t\tCRCD(0x0c7a712c, \"FLIPPED\"),\r\n\t\tCRCD(0xb39b4f1b, \"VERT_AIR\"),\r\n\t\tCRCD(0xc6bdeafc, \"TRACKING_VERT\"),\r\n\t\tCRCD(0x7747d16a, \"LAST_POLY_WAS_VERT\"),\r\n\t\tCRCD(0x0b6c902c, \"CAN_BREAK_VERT\"),\r\n\t\tCRCD(0x1261f6a0, \"CAN_RERAIL\"),\r\n\t\tCRCD(0x2bdce1e1, \"RAIL_SLIDING\"),\r\n\t\tCRCD(0xfb2e505c, \"CAN_HIT_CAR\"),\r\n\t\tCRCD(0xb2791a2f, \"AUTOTURN\"),\r\n\t\tCRCD(0x21523880, \"IS_BAILING\"),\r\n\t\tCRCD(0xe8e7a9a1, \"SPINE_PHYSICS\"),\r\n\t\tCRCD(0x4b45106a, \"IN_RECOVERY\"),\r\n\t\tCRCD(0x9c6a7e41, \"SKITCHING\"),\r\n\t\tCRCD(0x468c28b6, \"OVERRIDE_CANCEL_GROUND\"),\r\n\t\tCRCD(0xa29e3a92, \"SNAPPED_OVER_CURB\"),\r\n\t\tCRCD(0x4424288f, \"SNAPPED\"),\r\n\t\tCRCD(0x0849fb13, \"IN_ACID_DROP\"),\r\n\t\tCRCD(0x35f996fb, \"AIR_ACID_DROP_DISALLOWED\"),\r\n\t\tCRCD(0xd1c9cb24, \"CANCEL_WALL_PUSH\"),\r\n\t\tCRCD(0x260e0844, \"NO_ORIENTATION_CONTROL\"),\r\n\t\tCRCD(0x524ea0a3, \"NEW_RAIL\")\r\n\t};\r\n\t\r\n\tp_info->AddChecksum(CRCD(0x109b9260, \"m_state\"), p_state_checksums[m_state]);\r\n\tfor (int flag = 0; flag < NUM_ESKATERFLAGS; flag++)\r\n\t{\r\n\t\tp_info->AddChecksum(p_flag_checksums[flag], GetFlag(static_cast< ESkaterFlag >(flag)) ? CRCD(0x203b372, \"true\") : CRCD(0xd43297cf, \"false\"));\r\n\t}\r\n\t\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStateComponent::Reset (   )\r\n{\r\n\tSetDoingTrick(false);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic int\ts_get_powerup_index( uint32 type )\r\n{\r\n\tint i;\r\n\r\n\tfor( i = 0; i < vNUM_POWERUPS; i++ )\r\n\t{\r\n\t\tif( s_powerups[i] == type )\r\n\t\t{\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\r\n\treturn -1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterStateComponent::HasPowerup( uint32 type )\r\n{\r\n\tint index;\r\n\r\n\tindex = s_get_powerup_index( type );\r\n\tif( index == -1 )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\treturn m_powerups[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStateComponent::ClearPowerups( void )\r\n{\r\n\tint i;\r\n\r\n\tfor( i = 0; i < vNUM_POWERUPS; i++ )\r\n\t{\r\n\t\tm_powerups[i] = false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStateComponent::PickedUpPowerup( uint32 type )\r\n{\r\n\tint index;\r\n\r\n\tindex = s_get_powerup_index( type );\r\n\tif( index == -1 )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tm_powerups[index] = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterStateComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterStateComponent.h\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/31/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERSTATECOMPONENT_H__\r\n#define __COMPONENTS_SKATERSTATECOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/timestampedflag.h>\r\n\r\n#include <sk/objects/skaterflags.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <gfx/nxflags.h>\r\n\r\n#define\t\tCRC_SKATERSTATE CRCD(0x43686585, \"SkaterState\")\r\n\r\n#define\t\tGetSkaterStateComponent() ((Obj::CSkaterStateComponent*)GetComponent(CRC_SKATERSTATE))\r\n#define\t\tGetSkaterStateComponentFromObject(pObj) ((Obj::CSkaterStateComponent*)(pObj)->GetComponent(CRC_SKATERSTATE))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\tenum\r\n\t{\r\n\t\tvFIREBALL,\r\n\t\tvNUM_POWERUPS\r\n\t};\r\n\t\r\n\tenum EPhysicsStateType\r\n\t{\r\n\t\tNO_STATE = -1,\r\n\t\tSKATING,\r\n\t\tWALKING,\r\n#\t\tifdef TESTING_GUNSLINGER\r\n\t\tRIDING\r\n#\t\tendif\r\n\t};\r\n\r\nclass CSkaterStateComponent : public CBaseComponent\r\n{\r\n\tfriend class CSkaterNonLocalNetLogicComponent;\r\n\tfriend class CSkaterLocalNetLogicComponent;\r\n\tfriend class CSkaterCorePhysicsComponent;\r\n\tfriend class CSkaterAdjustPhysicsComponent;\r\n\tfriend class CSkaterFinalizePhysicsComponent;\r\n\tfriend class CSkaterFlipAndRotateComponent;\r\n\tfriend class CSkaterPhysicsControlComponent;\r\n\tfriend class CWalkComponent;\r\n\t\t\t\t  \r\npublic:\r\n    CSkaterStateComponent();\r\n    virtual ~CSkaterStateComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\npublic:\r\n\tvoid\t\t\t\t\t\t\tReset (   );\r\n\t\r\n\tbool\t\t\t\t\t\t\tDoingTrick (   ) { return m_doing_trick; }\r\n\tbool\t\t\t\t\t\t\tHasPowerup( uint32 type );\r\n\tvoid\t\t\t\t\t\t\tClearPowerups( void );\r\n\tvoid\t\t\t\t\t\t\tPickedUpPowerup( uint32 type );\r\n\tvoid\t\t\t\t\t\t\tSetDoingTrick ( bool doing_trick ) { m_doing_trick = doing_trick; }\r\n\tEStateType\t\t\t\t\t\tGetState (   ) { return m_state; }\r\n\tbool\t\t\t\t\t\t\tGetFlag ( ESkaterFlag flag ) { return m_skater_flags[flag].Get(); }\r\n\tETerrainType\t\t\t\t\tGetTerrain (   ) { return m_terrain; }\r\n\tMth::Vector&\t\t\t\t\tGetCameraDisplayNormal (   ) { return m_camera_display_normal; }\r\n\tMth::Vector&\t\t\t\t\tGetCameraCurrentNormal (   ) { return m_camera_current_normal; }\r\n\tMth::Vector&\t\t\t\t\tGetSpineVel (   ) { return m_spine_vel; }\r\n\tbool\t\t\t\t\t\t\tGetJumpedOutOfLipTrick (   ) { return mJumpedOutOfLipTrick; }\r\n\tfloat\t\t\t\t\t\t\tGetHeight (   ) { return m_height; }\r\n\tbool\t\t\t\t\t\t\tGetDriving (   ) { return m_driving; }\r\n\tbool\t\t\t\t\t\t\tGetPhysicsState (   ) { return m_physics_state; }\r\n\t\r\nprivate:\r\n\tEStateType\t\t\t\t\t\tm_state;\r\n\t\r\n\tEPhysicsStateType\t\t\t\tm_physics_state;\r\n\r\n\tCTimestampedFlag\t\t\t\tm_skater_flags [ NUM_ESKATERFLAGS ];\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_doing_trick;\r\n\t\r\n\tETerrainType\t\t\t\t\tm_terrain;\t\t\t\t\t\t// current terrain type on which the skater is skating\r\n\t\r\n\tMth::Vector\t\t\t\t\t\tm_spine_vel;\t\t\t\t\t// velocity to move over the spine\r\n\t\r\n\tbool\t\t\t\t\t\t\tmJumpedOutOfLipTrick;\t\t\t// Gets set when the player jumps out of a lip trick, and reset when they land.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Controlled by the c-code, not script.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Used by the camera.\r\n\t\r\n\tMth::Vector\t\t\t\t\t\tm_camera_display_normal;\t\t// skater's up vector for the purposes of the camera\r\n\tMth::Vector\t\t\t\t\t\tm_camera_current_normal;\t\t// skater's up vector for the purposes of the camera\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_driving;\t\t\t\t\t\t// true if the skater is driving a car\r\n\t\r\n\tfloat\t\t\t\t\t\t\tm_height;\r\n\tbool\t\t\t\t\t\t\tm_powerups[vNUM_POWERUPS];\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterStateHistoryComponent.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterStateHistoryComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/13/3\r\n//****************************************************************************\r\n\r\n#include <sk/components/skaterstatehistorycomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/walkcomponent.h>\r\n#include <gel/net/server/netserv.h>\r\n\r\n#include <sk/objects/crown.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/gamenet/gameNET.h>\r\n#include <sk/gamenet/gamemsg.h>\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/components/skaterscorecomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCBaseComponent* CSkaterStateHistoryComponent::s_create()\r\n{\r\n\treturn static_cast< CBaseComponent* >( new CSkaterStateHistoryComponent );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterStateHistoryComponent::CSkaterStateHistoryComponent() : CBaseComponent()\r\n{\r\n\tSetType( CRC_SKATERSTATEHISTORY );\r\n\r\n\tm_last_anm_time = 0;\r\n\tm_num_pos_updates = 0;\r\n\tm_num_anim_updates = 0;\r\n\tmemset( mp_pos_history, 0, sizeof( SPosEvent ) * vNUM_POS_HISTORY_ELEMENTS );\r\n\tmemset( mp_anim_history, 0, sizeof( SAnimEvent ) * vNUM_ANIM_HISTORY_ELEMENTS );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCSkaterStateHistoryComponent::~CSkaterStateHistoryComponent()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStateHistoryComponent::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStateHistoryComponent::RefreshFromStructure( Script::CStruct* pParams )\r\n{\r\n\tInitFromStructure(pParams);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStateHistoryComponent::Update()\r\n{\r\n\tSuspend(true);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBaseComponent::EMemberFunctionResult CSkaterStateHistoryComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( Checksum )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn CBaseComponent::MF_NOT_EXECUTED;\r\n\t}\r\n    return CBaseComponent::MF_TRUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStateHistoryComponent::GetDebugInfo(Script::CStruct *p_info)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info sent to CSkaterStateHistoryComponent::GetDebugInfo\"));\r\n\r\n\tCBaseComponent::GetDebugInfo(p_info);\t  \r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterStateHistoryComponent::CheckForCrownCollision(   )\r\n{\r\n\tObj::CCrown* crown = GameNet::Manager::Instance()->GetCrown();\r\n\tDbg_Assert(crown && !crown->OnKing());\r\n\t\r\n\treturn (get_latest_position() - crown->GetPosition()).Length() < CCrown::vCROWN_RADIUS;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterStateHistoryComponent::CollideWithOtherSkaters( int start_index )\r\n{\r\n    GameNet::PlayerInfo* p_player;\r\n\r\n\tp_player = GameNet::Manager::Instance()->GetPlayerByObjectID(GetObject()->GetID());\r\n\tif( p_player == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// If we've marked you as non-collidable, you are exempt from collision\r\n\t// In koth, if collision is turned off, only the king is collidable\r\n\tif (p_player->IsNonCollidable()\r\n\t\t|| (!GameNet::Manager::Instance()->PlayerCollisionEnabled() && !p_player->IsKing() && !p_player->HasCTFFlag())) return;\r\n\t\r\n\tCSkaterStateComponent* p_my_state_component = GetSkaterStateComponentFromObject(GetSkater());\r\n\tDbg_Assert(p_my_state_component);\r\n\r\n\t// If this p_player is bailing or noncollidable (and he's NOT the king) he is exempt from being smacked down\r\n\t// If you're in a slap game, you can always be hit; i.e. you've just been slapped but haven't teleported yet\r\n    bool can_fall = !p_my_state_component->GetFlag(IS_BAILING) || CFuncs::ScriptInSlapGame(NULL, NULL);\r\n\t\r\n\t// However, fallen kings are vulnerable\r\n\tif (!can_fall && !p_player->IsKing() && !p_player->HasCTFFlag()) return;\r\n\t\r\n\tbool my_driving = p_my_state_component->GetDriving();\r\n\tMth::Vector my_pos = get_latest_position();\r\n\tMth::Vector my_vel = get_vel();\r\n\tMth::Vector my_dir = my_vel;\r\n\tmy_dir.Normalize();\r\n\r\n\tMth::Line my_line;\r\n\tmy_line.m_start = my_pos;\r\n\r\n\t// Loop through all other skaters and check for collisions\r\n\tfor (int i = start_index; i < Mdl::Skate::vMAX_SKATERS; i++)\r\n\t{\r\n\t\tCSkater* p_other_skater = Mdl::Skate::Instance()->GetSkater(i);\r\n\r\n\t\tif (!p_other_skater\r\n\t\t\t|| p_other_skater == GetSkater()) continue;\r\n\t\t\r\n\t\tCSkaterStateComponent* p_other_state_component = GetSkaterStateComponentFromObject(p_other_skater);\r\n\t\tDbg_Assert(p_other_state_component);\r\n\t\tif (p_other_state_component->GetFlag(IS_BAILING)) continue;\r\n\t\t\r\n\t\tGameNet::PlayerInfo* p_other_player = p_other_player = GameNet::Manager::Instance()->GetPlayerByObjectID(p_other_skater->GetID());\r\n\t\tDbg_Assert(p_other_player);\r\n\t\t\r\n\t\t// Non-Collidable people and kings should never win\r\n\t\tif (p_other_player->IsNonCollidable() || p_other_player->IsKing()) continue;\r\n\r\n\t\t// If both players are carrying flags, and the subject doesn't have the other guy's flag, don't let them collide\r\n\t\tif (p_player->HasCTFFlag() && p_other_player->HasCTFFlag() && p_player->HasWhichFlag() != p_other_player->m_Team) continue;\r\n\r\n\t\t// No smacking teammates\r\n\t\tif (Mdl::Skate::Instance()->GetGameMode()->IsTeamGame() && p_other_player->m_Team == p_player->m_Team) continue;\r\n\r\n\t\tbool other_driving = p_other_state_component->GetDriving();\r\n\t\tMth::Vector other_pos = p_other_skater->mp_skater_state_history_component->get_latest_position();\r\n\t\tMth::Vector other_vel = p_other_skater->mp_skater_state_history_component->get_vel();\r\n\t\tMth::Vector other_dir = other_vel;\r\n\t\tother_dir.Normalize();\r\n\t\t\r\n\t\tif( other_vel.Length() > 100.0f )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tbool collided = false;\r\n\t\t\r\n\t\t// Collision extents are based upon the \"other\" skater -- whether or not he's a remote skater\r\n\t\t\r\n\t\tfloat collide_dist = get_collision_cylinder_radius(my_driving, other_driving);\r\n\t\tfloat driving_radius_multiplier = 1.0f;\r\n\t\tif (my_driving)\r\n\t\t{\r\n\t\t\tdriving_radius_multiplier += Script::GetFloat(\"driving_radius_boost\");\r\n\t\t}\r\n\t\tif (other_driving)\r\n\t\t{\r\n\t\t\tdriving_radius_multiplier += Script::GetFloat(\"driving_radius_boost\");\r\n\t\t}\r\n\t\t\r\n\t\tmy_line.m_end = my_line.m_start + my_dir * get_collision_cylinder_coeff(my_driving);\r\n\t\t\r\n\t\tMth::Line other_line;\r\n\t\tother_line.m_start = other_pos;\r\n\t\tother_line.m_end = other_line.m_start + other_dir * p_other_skater->mp_skater_state_history_component->get_collision_cylinder_coeff(other_driving);\r\n\t\t\r\n\t\tfloat temp;\r\n\t\tMth::Vector my_pt, other_pt;\r\n\t\tif (Mth::LineLineIntersect(my_line, other_line, &my_pt, &other_pt, &temp, &temp, true))\r\n\t\t{\r\n\t\t\tif ((my_pt - other_pt).Length() < collide_dist)\r\n\t\t\t{\r\n\t\t\t\tcollided = true;\r\n\t\t\t}   \r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// No solution exists -- lines must be parallel. Try testing endpoint lengths\r\n\t\t\t// Note: This only really works if velocities are relatively small\r\n\t\t\tif( (other_line.m_start - my_line.m_start).Length() < collide_dist)\r\n\t\t\t{\r\n\t\t\t\tcollided = true;\r\n\t\t\t\tother_pt = other_line.m_start;\r\n\t\t\t\tmy_pt = my_line.m_start;\r\n\t\t\t}\r\n\t\t\telse if ((other_line.m_start - my_line.m_end).Length() < collide_dist)\r\n\t\t\t{\r\n\t\t\t\tcollided = true;\r\n\t\t\t\tother_pt = other_line.m_start;\r\n\t\t\t\tmy_pt = my_line.m_end;\r\n\t\t\t}\r\n\t\t\telse if ((other_line.m_end - my_line.m_start).Length() < collide_dist)\r\n\t\t\t{\r\n\t\t\t\tcollided = true;\r\n\t\t\t\tother_pt = other_line.m_end;\r\n\t\t\t\tmy_pt = my_line.m_start;\r\n\t\t\t}\r\n\t\t\telse if ((other_line.m_end - my_line.m_end).Length() < collide_dist)\r\n\t\t\t{\r\n\t\t\t\tcollided = true;\r\n\t\t\t\tother_pt = other_line.m_end;\r\n\t\t\t\tmy_pt = my_line.m_end;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif (!collided) continue;\r\n\t\t\r\n\t\t// If the \"other\" p_player is going faster or if\r\n\t\t// the subject p_player is king or if\r\n\t\t// the subject is skating and we're driving, the subject loses\r\n\t\tif (((my_driving == other_driving && my_vel.Length() > other_vel.Length())\r\n\t\t\t || (my_driving && !other_driving)) && !p_player->IsKing()) continue;\r\n\t\t\r\n\t\t//Dbg_Printf( \"**** My Vel: %.2f, Theirs: %.2f\\n\", my_vel.Length(), other_vel.Length() );\r\n\t\tNet::Server* p_server = GameNet::Manager::Instance()->GetServer();\r\n\t\tDbg_Assert(p_server);\r\n\t\t\t\r\n\t\tif (can_fall)\r\n\t\t{\r\n\t\t\tGameNet::MsgCollideLost lost_msg;\r\n\t\t\tGameNet::MsgByteInfo won_msg;\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t// basically a one-byte message explaining \"You've been knocked down by ID\"\r\n\t\t\tlost_msg.m_Id = p_other_skater->GetID();\r\n\t\t\tlost_msg.m_Id |= (1 << 7) * other_driving;\r\n\t\t\tlost_msg.m_Offset = my_pt - other_pt;\r\n\r\n\t\t\tif (CInputComponent* p_input_component = GetInputComponentFromObject(GetObject()))\r\n\t\t\t{\r\n\t\t\t\tp_input_component->DisableInput();\r\n\t\t\t}\r\n\t\t\tp_player->MarkAsNonCollidable();\r\n\t\t\t\r\n\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_SKATER_COLLIDE_LOST;\r\n\t\t\tmsg_desc.m_Data = &lost_msg;\r\n\t\t\tmsg_desc.m_Length = sizeof(GameNet::MsgCollideLost);\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\tp_server->EnqueueMessage(p_player->GetConnHandle(), &msg_desc);\r\n\r\n\t\t\t// basically a one-byte message explaining \"You knocked someone down\"\r\n\t\t\twon_msg.m_Data = GetObject()->GetID();\r\n\t\t\twon_msg.m_Data |= (1 << 7) * my_driving;\r\n\r\n\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_SKATER_COLLIDE_WON;\r\n\t\t\tmsg_desc.m_Data = &won_msg;\r\n\t\t\tmsg_desc.m_Length = sizeof(GameNet::MsgByteInfo);\r\n\t\t\tp_server->EnqueueMessage(p_other_player->GetConnHandle(), &msg_desc);\t\r\n\t\t\t\r\n\t\t\tif (CFuncs::ScriptInSlapGame(NULL, NULL))\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert(p_other_skater->mp_skater_score_component);\r\n\t\t\t\tMdl::Score* score = p_other_skater->mp_skater_score_component->GetScore();\r\n\t\t\t\tscore->SetTotalScore(score->GetTotalScore() + 1);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif (Mdl::Skate::Instance()->GetGameMode()->GetNameChecksum() == CRCD(0x6ef8fda0, \"netking\")\r\n\t\t\t|| Mdl::Skate::Instance()->GetGameMode()->GetNameChecksum() == CRCD(0x5d32129c, \"king\"))\r\n\t\t{\r\n\t\t\t// Don't bother switching kings if the game is over\r\n\t\t\tif (Mdl::Skate::Instance()->GetGameMode()->EndConditionsMet()) return;\r\n\t\t\t\r\n\t\t\t// If the king was just slapped, the \"slapper\" (hehe) is the new king\r\n\t\t\tif (!p_player->IsKing()) continue;\r\n\t\t\t\r\n\t\t\t// It is important that we mark the king immediately (rather than through a\r\n\t\t\t// network message) since we do logic based on the \"current\" king\r\n\t\t\tp_other_player->MarkAsKing(true);\r\n\t\t\t\r\n\t\t\tLst::Search< GameNet::PlayerInfo > search;\r\n\t\t\tfor (GameNet::PlayerInfo* p_player = GameNet::Manager::Instance()->FirstPlayerInfo(search, true);\r\n\t\t\t\tp_player;\r\n\t\t\t\tp_player = GameNet::Manager::Instance()->NextPlayerInfo(search, true))\r\n\t\t\t{\r\n\t\t\t\t// Already marked the king for the local p_player (above)\r\n\t\t\t\tif (p_player->IsLocalPlayer()) continue;\r\n\t\t\t\t\r\n\t\t\t\tGameNet::MsgByteInfo msg;\r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\t\t\r\n\t\t\t\tmsg.m_Data = p_other_skater->GetID();\r\n\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_NEW_KING;\r\n\t\t\t\tmsg_desc.m_Length = sizeof(GameNet::MsgByteInfo);\r\n\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\tp_server->EnqueueMessage(p_player->GetConnHandle(), &msg_desc);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if (Mdl::Skate::Instance()->GetGameMode()->GetNameChecksum() == CRCD(0x6c5ff266, \"netctf\"))\r\n\t\t{\r\n\t\t\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\t\t\t// Don't bother handling this if the game is over\r\n\t\t\t//if (Mdl::Skate::Instance()->GetGameMode()->EndConditionsMet())\r\n\t\t\tif( gamenet_man->GameIsOver())\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (!p_player->HasCTFFlag())\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tGameNet::MsgFlagMsg msg;\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\tmsg.m_ObjId = p_other_skater->GetID();\r\n\t\t\tmsg.m_Team = p_player->HasWhichFlag();\r\n\r\n\t\t\tbool retrieve = p_player->HasWhichFlag() == p_other_player->m_Team;\r\n\r\n\t\t\tLst::Search< GameNet::PlayerInfo > search;\r\n\t\t\tfor (GameNet::PlayerInfo* send_player = GameNet::Manager::Instance()->FirstPlayerInfo(search, true);\r\n\t\t\t\tsend_player; \r\n\t\t\t\tsend_player = GameNet::Manager::Instance()->NextPlayerInfo(search, true))\r\n\t\t\t{\r\n\t\t\t\t// If you knock down the p_player with your team's flag, you recover it. Otherwise, you steal it\r\n\t\t\t\tif (retrieve)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (send_player->IsLocalPlayer())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_other_player->RetrievedFlag();\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\t\tmsg_desc.m_Length = sizeof(GameNet::MsgFlagMsg);\r\n\t\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_RETRIEVED_FLAG;\r\n\t\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\t\tp_server->EnqueueMessage(send_player->GetConnHandle(), &msg_desc);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif (send_player->IsLocalPlayer())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_other_player->StoleFlag(p_player->HasWhichFlag());\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\t\tmsg_desc.m_Length = sizeof(GameNet::MsgFlagMsg);\r\n\t\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_STOLE_FLAG;\r\n\t\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\t\tp_server->EnqueueMessage(send_player->GetConnHandle(), &msg_desc);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\tCSkaterStateHistoryComponent::sHandleProjectileHit ( Net::MsgHandlerContext* context )\r\n{\r\n\tCSkater* p_skater = (CSkater*) (context->m_Data);\r\n\tGameNet::MsgProjectileHit* p_msg = (GameNet::MsgProjectileHit*) (context->m_Msg);\r\n\t\r\n\tswitch (context->m_MsgId)\r\n\t{\r\n\t\tcase GameNet::MSG_ID_SKATER_PROJECTILE_HIT_TARGET:\r\n\t\t{\r\n\t\t\tchar name[32] = \"Someone\";\r\n\t\t\t\r\n\t\t\tif (GameNet::PlayerInfo* p_other_player = GameNet::Manager::Instance()->GetPlayerByObjectID(p_msg->m_Id))\r\n\t\t\t{\r\n\t\t\t\tstrncpy(name, p_other_player->m_Skater->GetDisplayName(), 32);\r\n\t\t\t}\r\n\r\n\t\t\tScript::CStruct params;\r\n\t\t\tparams.AddString(CRCD(0xa4b08520, \"String0\"), name);\r\n\t\t\tparams.AddChecksum( NONAME, CRCD(0xd039432c,\"fireball\") );\r\n\t\t\tp_skater->SelfEvent(CRCD(0xa1021af0, \"MadeOtherSkaterBail\"),&params);\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase GameNet::MSG_ID_SKATER_HIT_BY_PROJECTILE:\r\n\t\t{\r\n\t\t\tchar name[32] = \"Someone\";\r\n\r\n\t\t\tif (GameNet::PlayerInfo* p_other_player = GameNet::Manager::Instance()->GetPlayerByObjectID(p_msg->m_Id))\r\n\t\t\t{\r\n\t\t\t\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\t\t\t\tMth::Vector offset = p_skater->GetPos() - p_other_player->m_Skater->GetPos();\r\n\t\t\t\t// Perform a \"safe\" normalization\r\n\t\t\t\tfloat offset_length = offset.Length();\r\n\t\t\t\tif (offset_length < 0.0001f)\r\n\t\t\t\t{\r\n\t\t\t\t\t// if skaters are super close, or coincident then pretend they are not, to avoid zero length vectors\r\n\t\t\t\t\toffset.Set(1.0f, 0.0f, 1.0f);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\toffset /= offset_length;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// fudge it for now\r\n\t\t\t\t// float speed = p_other_skater->GetVel().Length();\r\n\t\t\t\tfloat speed = 300.0f;\r\n\t\t\t\tp_skater->GetVel() = offset * speed * 1.5f; \r\n\t\t\t\tp_skater->GetVel()[Y] = 200.0f;\r\n\r\n\t\t\t\tCSkaterPhysicsControlComponent* p_skater_physics_control_component = GetSkaterPhysicsControlComponentFromObject(p_skater);\r\n\t\t\t\tif (p_skater_physics_control_component->IsSkating())\r\n\t\t\t\t{\r\n\t\t\t\t\tCSkaterCorePhysicsComponent* p_skater_core_physics_component = GetSkaterCorePhysicsComponentFromObject(p_skater);\r\n\t\t\t\t\tp_skater_core_physics_component->CollideWithOtherSkaterLost(p_other_player->m_Skater);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tCWalkComponent* p_walk_component = GetWalkComponentFromObject(p_skater);\r\n\t\t\t\t\tp_walk_component->CollideWithOtherSkaterLost(p_other_player->m_Skater);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tstrncpy(name, p_other_player->m_Skater->GetDisplayName(), 32);\r\n\t\t\t\t\r\n\r\n\t\t\t\tif( gamenet_man->OnServer() == false )\r\n\t\t\t\t{\r\n\t\t\t\t\tMdl::Score* score = p_skater->mp_skater_score_component->GetScore();\r\n\t\t\t\t\tif(( score->GetTotalScore() - p_msg->m_Damage ) < 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tscore->SetTotalScore( 0 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tscore->SetTotalScore( score->GetTotalScore() - p_msg->m_Damage );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tScript::CStruct params;\r\n\t\t\tparams.AddString(CRCD(0xa4b08520, \"String0\"), name);\r\n\t\t\tparams.AddChecksum( NONAME, CRCD(0xd039432c,\"fireball\") );\r\n\t\t\tp_skater->SelfEvent(CRCD(0x915e5e39, \"SkaterCollideBail\"),&params);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_Assert(false);\r\n\t\t\tbreak;\r\n\t}\r\n\t\t\r\n\treturn Net::HANDLER_MSG_DONE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tCSkaterStateHistoryComponent::sHandleCollision( Net::MsgHandlerContext* context )\r\n{\r\n\tCSkater* p_skater = (CSkater*) (context->m_Data);\r\n\t\r\n\tswitch (context->m_MsgId)\r\n\t{\r\n\t\tcase GameNet::MSG_ID_SKATER_COLLIDE_WON:\r\n\t\t{\r\n\t\t\tGameNet::MsgByteInfo* p_msg = (GameNet::MsgByteInfo*) (context->m_Msg);\r\n\t\t\tchar name[32] = \"Someone\";\r\n\t\t\t\r\n\t\t\tbool loser_drivng = p_msg->m_Data & (1 << 7);\r\n\t\t\tp_msg->m_Data &= ~(1 << 7);\r\n\t\t\t\r\n\t\t\tif (GameNet::PlayerInfo* p_other_player = GameNet::Manager::Instance()->GetPlayerByObjectID(p_msg->m_Data))\r\n\t\t\t{\r\n\t\t\t\tstrncpy(name, p_other_player->m_Skater->GetDisplayName(), 32);\r\n\t\t\t}\r\n\r\n\t\t\tScript::CStruct params;\r\n\t\t\tparams.AddString(CRCD(0xa4b08520, \"String0\"), name);\r\n\t\t\tif (loser_drivng)\r\n\t\t\t{\r\n\t\t\t\tparams.AddChecksum(NO_NAME, CRCD(0x7fd0663d, \"LoserIsDriving\"));\r\n\t\t\t}\r\n\t\t\tp_skater->SelfEvent(CRCD(0xa1021af0, \"MadeOtherSkaterBail\"),&params);\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase GameNet::MSG_ID_SKATER_COLLIDE_LOST:\r\n\t\t{\r\n\t\t\tGameNet::MsgCollideLost* p_msg = (GameNet::MsgCollideLost*) (context->m_Msg);\r\n\t\t\tchar name[32] = \"Someone\";\r\n\t\t\t\r\n\t\t\tbool winner_driving = p_msg->m_Id & (1 << 7);\r\n\t\t\tp_msg->m_Id &= ~(1 << 7);\r\n\r\n\t\t\tif (GameNet::PlayerInfo* p_other_player = GameNet::Manager::Instance()->GetPlayerByObjectID(p_msg->m_Id))\r\n\t\t\t{\r\n\t\t\t\tCSkaterPhysicsControlComponent* p_skater_physics_control_component = GetSkaterPhysicsControlComponentFromObject(p_skater);\r\n\t\t\t\t\r\n\t\t\t\tif (!p_skater_physics_control_component->IsDriving())\r\n\t\t\t\t{\r\n\t\t\t\t\tMth::Vector offset = p_skater->GetPos() - p_other_player->m_Skater->GetPos();\r\n\t\t\t\t\t// Perform a \"safe\" normalization\r\n\t\t\t\t\tfloat offset_length = offset.Length();\r\n\t\t\t\t\tif (offset_length < 0.0001f)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// if skaters are super close, or coincident then pretend they are not, to avoid zero length vectors\r\n\t\t\t\t\t\toffset.Set(1.0f, 0.0f, 1.0f);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\toffset /= offset_length;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t// fudge it for now\r\n\t\t\t\t\t// float speed = p_other_skater->GetVel().Length();\r\n\t\t\t\t\tfloat speed = 300.0f;\r\n\t\t\t\t\tp_skater->GetVel() = offset * speed * 1.5f; \r\n\t\t\t\t\tp_skater->GetVel()[Y] = 200.0f;\r\n\t\r\n\t\t\t\t\tif (p_skater_physics_control_component->IsSkating())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tCSkaterCorePhysicsComponent* p_skater_core_physics_component = GetSkaterCorePhysicsComponentFromObject(p_skater);\r\n\t\t\t\t\t\tp_skater_core_physics_component->CollideWithOtherSkaterLost(p_other_player->m_Skater);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tCWalkComponent* p_walk_component = GetWalkComponentFromObject(p_skater);\r\n\t\t\t\t\t\tp_walk_component->CollideWithOtherSkaterLost(p_other_player->m_Skater);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tstrncpy(name, p_other_player->m_Skater->GetDisplayName(), 32);\r\n\t\t\t}\r\n\r\n\t\t\tScript::CStruct params;\r\n\t\t\tparams.AddString(CRCD(0xa4b08520, \"String0\"), name);\r\n\t\t\tparams.AddVector(CRCD(0xa6f5352f, \"Offset\"), p_msg->m_Offset);\r\n\t\t\tif (winner_driving)\r\n\t\t\t{\r\n\t\t\t\tparams.AddChecksum(NO_NAME, CRCD(0x2f679251, \"WinnerIsDriving\"));\r\n\t\t\t}\r\n\t\t\tp_skater->SelfEvent(CRCD(0x915e5e39, \"SkaterCollideBail\"),&params);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_Assert(false);\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t}\r\n\t\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector\tCSkaterStateHistoryComponent::get_vel (   )\r\n{\r\n\treturn GetObject()->m_vel * Tmr::UncappedFrameLength();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CSkaterStateHistoryComponent::get_latest_position(   )\r\n{\r\n\treturn GetObject()->m_pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CSkaterStateHistoryComponent::get_last_position(   )\r\n{\r\n    return GetObject()->m_old_pos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tCSkaterStateHistoryComponent::get_time_between_last_update(   )\r\n{\r\n\tint time_elapsed;\r\n\t\r\n\ttime_elapsed = static_cast< int >(Tmr::FrameLength());\r\n\t\r\n\tif( time_elapsed == 0 )\r\n\t{\r\n\t\ttime_elapsed = Tmr::VBlanks( 1 );\r\n\t}\r\n\treturn time_elapsed;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CSkaterStateHistoryComponent::get_collision_cylinder_coeff( bool driving )\r\n{\r\n    // multiplied by the velocity of the skater to give the length of a line along which to check for collision\r\n\t\r\n\tfloat radius;\r\n\t\r\n\tif (GetSkater()->IsLocalClient())\r\n\t{\r\n        radius = GetPhysicsFloat( CRCD(0xd24273b, \"LanServerCollCoefficient\"), Script::ASSERT);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tradius = GetPhysicsFloat( CRCD(0x25f78481, \"LanClientCollCoefficient\"), Script::ASSERT);\r\n\t}\r\n\t\r\n\tif (!driving)\r\n\t{\r\n\t\treturn radius;\r\n\t}\r\n\telse\r\n\t{\r\n        return radius * (1.0f + Script::GetFloat(CRCD(0xa49ff23, \"DrivingCoefficientBoostFactor\")));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CSkaterStateHistoryComponent::get_collision_cylinder_radius( bool first_driving, bool second_driving )\r\n{\r\n\tfloat radius;\r\n\t\r\n\tif (GetSkater()->IsLocalClient())\r\n\t{\r\n\t\tif (GameNet::Manager::Instance()->InInternetMode())\r\n\t\t{\r\n\t\t\tradius = GetPhysicsFloat(CRCD(0xf2e35fa3, \"InternetServerCollRadius\"), Script::ASSERT);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tradius = GetPhysicsFloat(CRCD(0xecb41860, \"LanServerCollRadius\"), Script::ASSERT);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (GameNet::Manager::Instance()->InInternetMode())\r\n\t\t{\r\n\t\t\tradius = GetPhysicsFloat(CRCD(0xdbd6d58a, \"InternetClientCollRadius\"), Script::ASSERT);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tradius = GetPhysicsFloat(CRCD(0xc5819249, \"LanClientCollRadius\"), Script::ASSERT);\r\n\t\t}\r\n\t}\r\n\t\r\n\tfloat driving_count = 0;\r\n\tif (first_driving)\r\n\t{\r\n\t\tdriving_count++;\r\n\t}\r\n\tif (second_driving)\r\n\t{\r\n\t\tdriving_count++;\r\n\t}\r\n\t\r\n\treturn radius * (1.0f + driving_count * GetPhysicsFloat(CRCD(0xeef4afb3, \"DrivingRadiusBoostFactor\")));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSPosEvent::SPosEvent( void )\r\n{\r\n\tmemset( this, 0, sizeof( SPosEvent ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tSPosEvent::GetTime( void )\r\n{\r\n\tuint32 time;\r\n\r\n\ttime = ( HiTime << 16 ) | ( LoTime );\r\n\r\n\treturn time;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tSPosEvent::SetTime( uint32 time )\r\n{\r\n\tLoTime = (unsigned short) ( time & 0xFFFF );\r\n\tHiTime = (unsigned short) ( time >> 16 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSAnimEvent::SAnimEvent( void )\r\n{\r\n\tmemset( this, 0, sizeof( SAnimEvent ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tSAnimEvent::GetTime( void )\r\n{\r\n\tuint32 time;\r\n\r\n\ttime = ( m_HiTime << 16 ) | ( m_LoTime );\r\n\r\n\treturn time;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tSAnimEvent::SetTime( uint32 time )\r\n{\r\n\tm_LoTime = (unsigned short) ( time & 0xFFFF );\r\n\tm_HiTime = (unsigned short) ( time >> 16 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\t\t\tCSkaterStateHistoryComponent::GetLatestAnimTimestamp( void )\r\n{\r\n\treturn m_last_anm_time;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tCSkaterStateHistoryComponent::SetLatestAnimTimestamp( uint32 timestamp )\r\n{\r\n\tm_last_anm_time = timestamp;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Components/SkaterStateHistoryComponent.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Components\r\n//* FILENAME:       SkaterStateHistoryComponent.cpp\r\n//* OWNER:          Dan\r\n//* CREATION DATE:  3/13/3\r\n//****************************************************************************\r\n\r\n#ifndef __COMPONENTS_SKATERSTATEHISTORYCOMPONENT_H__\r\n#define __COMPONENTS_SKATERSTATEHISTORYCOMPONENT_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <gel/object/basecomponent.h>\r\n\r\n#include <sk/objects/skater.h>\r\n#include <gfx/nxflags.h>\r\n\r\n#define\t\tCRC_SKATERSTATEHISTORY CRCD(0x18223fd6, \"SkaterStateHistory\")\r\n\r\n#define\t\tGetSkaterStateHistoryComponent() ((Obj::CSkaterStateHistoryComponent*)GetComponent(CRC_SKATERSTATEHISTORY))\r\n#define\t\tGetSkaterStateHistoryComponentFromObject(pObj) ((Obj::CSkaterStateHistoryComponent*)(pObj)->GetComponent(CRC_SKATERSTATEHISTORY))\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n}\r\n\r\nnamespace Net\r\n{\r\n\tclass MsgHandlerContext;\r\n}\r\n              \r\nnamespace Obj\r\n{\r\n\r\nclass SPosEvent\r\n{   \r\npublic:\r\n\tSPosEvent( void );\r\n\r\n\tuint32\t\t\tGetTime( void );\r\n\tvoid\t\t\tSetTime( uint32 time );\r\n\r\n\tshort\t\t\tShortPos[3];\r\n\tMth::Matrix\t\tMatrix;\r\n\tMth::Vector\t\tPosition;\r\n\tMth::Vector\t\tEulers;\r\n\tFlags< int >\tSkaterFlags;\r\n\tFlags< int >\tEndRunFlags;\r\n\tint\t\t\t\tState;\r\n\tchar\t\t\tDoingTrick;\r\n\tchar\t\t\tWalking;\r\n\tchar\t\t\tDriving;\r\n\tuint16\t\t\tLoTime;\r\n\tuint16\t\t\tHiTime;\r\n\tETerrainType\tTerrain;\r\n\tsint16\t\t\tRailNode;\r\n};\r\n\r\nclass SAnimEvent\r\n{   \r\npublic:\r\n\tSAnimEvent( void );\r\n\r\n\tuint32\t\t\tGetTime( void );\r\n\tvoid\t\t\tSetTime( uint32 time );\r\n\r\n\tchar\t\t\tm_MsgId;\r\n\tchar\t\t\tm_ObjId;\r\n\tchar\t\t\tm_LoopingType;\r\n\tchar\t\t\tm_Flags;\r\n\tuint16\t\t\tm_LoTime;\r\n\tuint16\t\t\tm_HiTime;\r\n\tbool\t\t\tm_Flipped;\r\n\tbool\t\t\tm_Rotate;\r\n\tbool\t\t\tm_Hide;\r\n\tfloat\t\t\tm_Alpha;\r\n\tfloat\t\t\tm_StartTime;\r\n\tfloat\t\t\tm_EndTime;\r\n\tfloat\t\t\tm_BlendPeriod;\r\n\tfloat \t\t\tm_Speed;\r\n\tuint32\t\t\tm_Asset;\r\n\tuint32\t\t\tm_Bone;\r\n\tfloat\t\t\tm_WobbleAmpA;\r\n\tfloat\t\t\tm_WobbleAmpB;\r\n\tfloat\t\t\tm_WobbleK1;\r\n\tfloat\t\t\tm_WobbleK2;\r\n\tfloat\t\t\tm_SpazFactor;\r\n\tint \t\t\tm_Duration;\r\n\tint \t\t\tm_SinePower;\r\n\tint\t\t\t\tm_Index;\r\n\tfloat \t\t\tm_StartAngle;\r\n\tfloat \t\t\tm_DeltaAngle;\r\n\tbool\t\t\tm_HoldOnLastAngle;\r\n};\r\n\r\nclass CSkaterStateHistoryComponent : public CBaseComponent\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvNUM_POS_HISTORY_ELEMENTS = 20,\r\n\t\tvNUM_ANIM_HISTORY_ELEMENTS = 20\r\n\t};\r\n\t\r\npublic:\r\n    CSkaterStateHistoryComponent();\r\n    virtual ~CSkaterStateHistoryComponent();\r\n\r\npublic:\r\n    virtual void            \t\tUpdate();\r\n    virtual void            \t\tInitFromStructure( Script::CStruct* pParams );\r\n    virtual void            \t\tRefreshFromStructure( Script::CStruct* pParams );\r\n    \r\n    virtual EMemberFunctionResult   CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tvirtual void \t\t\t\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tstatic CBaseComponent*\t\t\ts_create();\r\n\t\r\n\tCSkater*\t\t\t\t\t\tGetSkater() { return static_cast< CSkater* >(GetObject()); }\r\n\t\r\n\tstatic int\t\t\t\t\t\tsHandleCollision ( Net::MsgHandlerContext* context );\r\n\tstatic int\t\t\t\t\t\tsHandleProjectileHit ( Net::MsgHandlerContext* context );\r\n\t\r\n\tSPosEvent*\t\t\t\t\t\tGetPosHistory (   ) { return mp_pos_history; }\r\n\tSPosEvent*\t\t\t\t\t\tGetLatestPosEvent (   ) { return &mp_pos_history[m_num_pos_updates % vNUM_POS_HISTORY_ELEMENTS]; }\r\n\tSPosEvent*\t\t\t\t\t\tGetLastPosEvent (   ) { return &mp_pos_history[(m_num_pos_updates + ( vNUM_POS_HISTORY_ELEMENTS - 1 )) % vNUM_POS_HISTORY_ELEMENTS]; }\r\n\tvoid\t\t\t\t\t\t\tIncrementNumPosUpdates (   ) { m_num_pos_updates++; }\r\n\tvoid\t\t\t\t\t\t\tResetPosHistory (   ) { m_num_pos_updates = 0; }\r\n\tint\t\t\t\t\t\t\t\tGetNumPosUpdates (   ) { return m_num_pos_updates; }\r\n\t\r\n\tuint32\t\t\t\t\t\t\tGetLatestAnimTimestamp( void );\r\n\tvoid\t\t\t\t\t\t\tSetLatestAnimTimestamp( uint32 timestamp );\r\n\tSAnimEvent*\t\t\t\t\t\tGetAnimHistory (   ) { return mp_anim_history; }\r\n\tSAnimEvent*\t\t\t\t\t\tGetLatestAnimEvent (   ) { return &mp_anim_history[m_num_anim_updates % vNUM_ANIM_HISTORY_ELEMENTS]; }\r\n\tSAnimEvent*\t\t\t\t\t\tGetLastAnimEvent (   ) { return &mp_anim_history[(m_num_anim_updates + ( vNUM_ANIM_HISTORY_ELEMENTS - 1 )) % vNUM_ANIM_HISTORY_ELEMENTS]; }\r\n\tvoid\t\t\t\t\t\t\tIncrementNumAnimUpdates (   ) { m_num_anim_updates++; }\r\n\tvoid\t\t\t\t\t\t\tResetAnimHistory (   ) { m_num_anim_updates = 0; }\r\n\tint\t\t\t\t\t\t\t\tGetNumAnimUpdates (   ) { return m_num_anim_updates; }\r\n\t\r\n\tbool\t\t\t\t\t\t\tCheckForCrownCollision (   );\r\n\tvoid\t\t\t\t\t\t\tCollideWithOtherSkaters ( int start_index );\r\n\tbool\t\t\t\t\t\t\tGetCollidingPlayerAndTeam ( Script::CStruct* pParams, Script::CScript* pScript );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetCurrentVehicleControlType ( uint32 control_type ) { m_current_vehicle_control_type = control_type; }\r\n\tuint32\t\t\t\t\t\t\tGetCurrentVehicleControlType (   ) { return m_current_vehicle_control_type; }\r\n\t\r\nprivate:\r\n\tMth::Vector\t\t\t\t\t\tget_latest_position (   );\r\n\tMth::Vector\t\t\t\t\t\tget_last_position (   );\r\n\tMth::Vector\t\t\t\t\t\tget_vel (   );\r\n\tint\t\t\t\t\t\t\t\tget_time_between_last_update (   );\r\n\t\r\n\tfloat\t\t\t\t\t\t\tget_collision_cylinder_coeff ( bool driving );\r\n\tfloat\t\t\t\t\t\t\tget_collision_cylinder_radius ( bool first_driving, bool second_driving );\r\n\t\r\nprivate:\r\n\tint\t\t\t\t\t\t\t\tm_num_pos_updates;\r\n\tSPosEvent\t\t\t\t\t\tmp_pos_history [ vNUM_POS_HISTORY_ELEMENTS ];\r\n\t\r\n\tint\t\t\t\t\t\t\t\tm_num_anim_updates;\r\n\tSAnimEvent\t\t\t\t\t\tmp_anim_history [ vNUM_ANIM_HISTORY_ELEMENTS ];\r\n\r\n        uint32\t\t\t\t\t\t\tm_last_anm_time;\r\n\t// if the non-local client is driving, this control type's model will be used; set via a network message\r\n\tuint32\t\t\t\t\t\t\tm_current_vehicle_control_type;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Engine/RectFeeler.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSk/Engine\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tRectFeeler.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t02/14/2003\t-\tDan\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n\t\t\r\n#include <gfx/debuggfx.h>\r\n\r\n#include <sk/engine/rectfeeler.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nNx::CCollCache* CRectFeeler::sp_default_cache = NULL;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// BUG: getting false collisions when rectangle is flush with axes\r\n\r\nCRectFeeler::CRectFeeler (   )\r\n{\r\n\tinit();\r\n}\r\n\r\nCRectFeeler::CRectFeeler ( const Mth::Vector& corner, const Mth::Vector& first_edge, const Mth::Vector& second_edge )\r\n{\r\n\tm_corner = corner;\r\n\tm_first_edge = first_edge;\r\n\tm_second_edge = second_edge;\r\n\t\r\n\tinit();\r\n}\r\n\r\nvoid CRectFeeler::init (   )\r\n{\r\n\tmp_cache = NULL;\r\n\tm_coll_data.num_surfaces = 0;\r\n\tm_merged_coll_data.num_surfaces = 0;\r\n\t\r\n\tm_coll_data.ignore_1 = mFD_NON_COLLIDABLE;\r\n\tm_coll_data.ignore_0 = 0;\r\n}\r\n\r\nbool CRectFeeler::GetCollision ( bool movables )\r\n{\r\n\tDbg_MsgAssert(!movables, (\"Collision test against movables not yet supported by CRectFeeler\"));\r\n\t\r\n\tRectangle& rect = *this;\r\n\t\r\n\treturn Nx::CCollObj::sFindRectangleStaticCollision(rect, &m_coll_data, mp_cache ? mp_cache : sp_default_cache);\r\n}\r\n\r\nvoid CRectFeeler::MergeCollisionSurfaces (   )\r\n{\r\n\t// precomputed values\r\n\tbool p_surfaces_used[Nx::MAX_NUM_2D_COLLISIONS_REPORTED];\r\n\tMth::Vector p_line_directions[Nx::MAX_NUM_2D_COLLISIONS_REPORTED];\r\n\tfor (int n = m_coll_data.num_surfaces; n--; )\r\n\t{\r\n\t\tp_surfaces_used[n] = false;\r\n\t\t\r\n\t\tp_line_directions[n] = m_coll_data.p_surfaces[n].ends[1].point - m_coll_data.p_surfaces[n].ends[0].point;\r\n\t\tp_line_directions[n].Normalize();\r\n\t}\r\n\t\r\n\t// drop duplicate surfaces\r\n\tfor (int i = m_coll_data.num_surfaces; i--; )\r\n\t{\r\n\t\tNx::S2DCollSurface& surface_i = m_coll_data.p_surfaces[i];\r\n\t\t\r\n\t\tif (p_surfaces_used[i]) continue;\r\n\t\t\r\n\t\tfor (int j = i; j--; )\r\n\t\t{\r\n\t\t\tNx::S2DCollSurface& surface_j = m_coll_data.p_surfaces[j];\r\n\t\t\tif ((very_close(surface_i.ends[0].point, surface_j.ends[0].point) && very_close(surface_i.ends[1].point, surface_j.ends[1].point))\r\n\t\t\t\t|| (very_close(surface_i.ends[0].point, surface_j.ends[1].point) && very_close(surface_i.ends[1].point, surface_j.ends[0].point)))\r\n\t\t\t{\r\n\t\t\t\tif (Mth::DotProduct(surface_i.normal, surface_j.normal) > 0.99f)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_surfaces_used[j] = true;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// we build a merged surface list out of the collision data surface list, attempting to reduce the number of surfaces by merging those which\r\n\t// are equivalent for the purpose of collision lines; that is, merge chains of collision lines which are parallel and have equal surface normals\r\n\t\r\n\t// for each surface, first attempt to absorb as yet unvisited surfaces; then, attempt to absorb the surface into a surface previously accepted into\r\n\t// the merged surface list; if unsuccessful, add the surface to the merged surface list\r\n\t\r\n\tm_merged_coll_data.num_surfaces = 0;\r\n\t\r\n\t// loop over the collision data surfaces\r\n\tfor (int proposed_idx = m_coll_data.num_surfaces; proposed_idx--; )\r\n\t{\r\n\t\tNx::S2DCollSurface proposed_surface = m_coll_data.p_surfaces[proposed_idx];\r\n\t\t\r\n\t\tif (p_surfaces_used[proposed_idx]) continue;\r\n\t\t\r\n\t\t// check to absorb unused surfaces into the proposed surface\r\n\t\t\r\n\t\tbool clean_pass;\r\n\t\tdo // loop over the unused surfaces until we pass through them cleanly, finding no absorption opportunities\r\n\t\t{\r\n\t\t\tclean_pass = true;\r\n\t\t\t\r\n\t\t\tfor (int check_idx = proposed_idx; check_idx--; )\r\n\t\t\t{\r\n\t\t\t\tNx::S2DCollSurface& check_surface = m_coll_data.p_surfaces[check_idx];\r\n\t\t\t\t\r\n\t\t\t\t// check that this line is not already used\r\n\t\t\t\tif (p_surfaces_used[check_idx]) continue;\r\n\t\t\t\t\r\n\t\t\t\t// check that surfaces are parallel\r\n\t\t\t\tif (Mth::DotProduct(proposed_surface.normal, check_surface.normal) < 0.99f) continue;\r\n\t\t\t\t\r\n\t\t\t\t// check that collision lines are parallel\r\n\t\t\t\tif (Mth::Abs(Mth::DotProduct(p_line_directions[proposed_idx], p_line_directions[check_idx])) < 0.99f) continue;\r\n\t\t\t\t\r\n\t\t\t\t// check that collision lines connect\r\n\t\t\t\tif (very_close(proposed_surface.ends[0].point, check_surface.ends[0].point))\r\n\t\t\t\t{\r\n\t   \t\t\t\tproposed_surface.ends[0].point = check_surface.ends[1].point;\r\n\t   \t\t\t\tproposed_surface.ends[0].tangent_exists = check_surface.ends[1].tangent_exists;\r\n\t   \t\t\t\tproposed_surface.ends[0].tangent = check_surface.ends[1].tangent;\r\n\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\telse if (very_close(proposed_surface.ends[0].point, check_surface.ends[1].point))\r\n\t\t\t\t{\r\n\t   \t\t\t\tproposed_surface.ends[0].point = check_surface.ends[0].point;\r\n\t   \t\t\t\tproposed_surface.ends[0].tangent_exists = check_surface.ends[0].tangent_exists;\r\n\t   \t\t\t\tproposed_surface.ends[0].tangent = check_surface.ends[0].tangent;\r\n\t\t\t\t}\r\n\t\t\t\telse if (very_close(proposed_surface.ends[1].point, check_surface.ends[0].point))\r\n\t\t\t\t{\r\n\t\t\t\t\tproposed_surface.ends[1].point = check_surface.ends[1].point;\r\n\t   \t\t\t\tproposed_surface.ends[1].tangent_exists = check_surface.ends[1].tangent_exists;\r\n\t   \t\t\t\tproposed_surface.ends[1].tangent = check_surface.ends[1].tangent;\r\n\t\t\t\t}\r\n\t\t\t\telse if (very_close(proposed_surface.ends[1].point, check_surface.ends[1].point))\r\n\t\t\t\t{\r\n\t\t\t\t\tproposed_surface.ends[1].point = check_surface.ends[0].point;\r\n\t   \t\t\t\tproposed_surface.ends[1].tangent_exists = check_surface.ends[0].tangent_exists;\r\n\t   \t\t\t\tproposed_surface.ends[1].tangent = check_surface.ends[0].tangent;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// we've successfully absorbed check_surface into proposed_surface\r\n\t\t\t\tp_surfaces_used[check_idx] = true;\r\n\t\t\t\t\r\n\t\t\t\tclean_pass = false;\r\n\t\t\t} // END loop over unvisited surfaces\r\n\t\t} while (clean_pass = false);\r\n\t\t\r\n\t\t// accept the poropsed surface into the reduced surface list\r\n\t\t\r\n\t\tm_merged_coll_data.p_surfaces[m_merged_coll_data.num_surfaces++] = proposed_surface;\r\n\t} // END loop over proposing surfaces\r\n}\r\n\r\nvoid CRectFeeler::DebugLines ( int r, int g, int b, int num_frames ) const\r\n{\r\n\tuint32 color = MAKE_RGB(r, g, b);\r\n\t\r\n\tGfx::AddDebugLine(m_corner, m_corner + m_first_edge, color, color, num_frames);\r\n\tGfx::AddDebugLine(m_corner + m_first_edge, m_corner + m_first_edge + m_second_edge, color, color, num_frames);\r\n\tGfx::AddDebugLine(m_corner + m_first_edge + m_second_edge, m_corner + m_second_edge, color, color, num_frames);\r\n\tGfx::AddDebugLine(m_corner + m_second_edge, m_corner, color, color, num_frames);\r\n\t\r\n\t// if we've merged the surfaces\r\n\tif (m_merged_coll_data.num_surfaces > 0)\r\n\t{\r\n\t\t// draw the merged collision lines\r\n\t\tfor (int n = m_merged_coll_data.num_surfaces; n--; )\r\n\t\t{\r\n\t\t\tcolor = MAKE_RGB(r += 201, g += 99, b += 31);\r\n\t\t\tGfx::AddDebugLine(m_merged_coll_data.p_surfaces[n].ends[0].point, m_merged_coll_data.p_surfaces[n].ends[1].point, color, color, 1);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// otherwise, draw the bare collision lines\r\n\t\tfor (int n = m_coll_data.num_surfaces; n--; )\r\n\t\t{\r\n\t\t\tcolor = MAKE_RGB(r += 201, g += 99, b += 31);\r\n\t\t\tGfx::AddDebugLine(m_coll_data.p_surfaces[n].ends[0].point, m_coll_data.p_surfaces[n].ends[1].point, color, color, 1);\r\n\t\t}\r\n\t}\r\n}\r\n\t\r\n\r\n"
  },
  {
    "path": "Code/Sk/Engine/RectFeeler.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSk/Engine\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tRectFeeler.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t02/14/2003\t-\tDan\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SK_ENGINE_RECTFEELER_H\r\n#define\t__SK_ENGINE_RECTFEELER_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n\r\n#include <gel/collision/collision.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass\tCRectFeeler\t: public Mth::Rectangle\r\n{\r\npublic:\r\n\tCRectFeeler (   );\r\n\tCRectFeeler ( const Mth::Vector& corner, const Mth::Vector& first_edge, const Mth::Vector& second_edge );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetRectangle ( const Mth::Rectangle& rect );\r\n\t\r\n\tbool\t\t\t\t\t\t\tGetCollision ( bool movables = false );\r\n\t\r\n\tint\t\t\t\t\t\t\t\tGetNumCollisionSurfaces (   ) const { return m_coll_data.num_surfaces; }\r\n\tconst Nx::S2DCollSurface&\t\tGetCollisionSurface ( int n ) const;\r\n\t\r\n\tint\t\t\t\t\t\t\t\tGetNumMergedCollisionSurfaces (   ) const { return m_merged_coll_data.num_surfaces; }\r\n\tconst Nx::S2DCollSurface&\t\tGetMergedCollisionSurface ( int n ) const;\r\n\t\r\n\tvoid\t\t\t\t\t\t\tMergeCollisionSurfaces (   );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetIgnore ( uint16 ignore_1, uint16 ignore_0 );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetCache ( Nx::CCollCache* p_cache ) { mp_cache = p_cache; }\r\n\tvoid\t\t\t\t\t\t\tClearCache (   ) { mp_cache = NULL; }\r\n\t\r\n\tstatic void\t\t\t\t\t\tsSetDefaultCache ( Nx::CCollCache* p_cache ) { sp_default_cache = p_cache; }\r\n\tstatic void\t\t\t\t\t\tsClearDefaultCache (   ) { sp_default_cache = NULL; }\r\n\t\r\n\t// ReduceCollisionSurfaces (   )\r\n\t\r\n\tvoid\t\t\t\t\t\t\tDebugLines ( int r = 255, int g = 255, int b = 255, int num_frames = 0 ) const;\r\n\r\nprivate:\r\n\tvoid\t\t\t\t\t\t\tinit (   );\r\n\t\r\n\tbool\t\t\t\t\t\t\tvery_close ( const Mth::Vector p, const Mth::Vector q ) const;\r\n\r\nprivate:\r\n\t\r\n\tNx::S2DCollData\t\t\t\t\tm_coll_data;\r\n\tNx::S2DCollData\t\t\t\t\tm_merged_coll_data;\r\n\t\r\n\tNx::CCollCache*\t\t\t\t\tmp_cache;\r\n\t\r\n\tstatic Nx::CCollCache*\t\t\tsp_default_cache;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline void\t\t\t\t\t\t\tCRectFeeler::SetRectangle ( const Mth::Rectangle& rect )\r\n{\r\n\tm_corner = rect.m_corner;\r\n\tm_first_edge = rect.m_first_edge;\r\n\tm_second_edge = rect.m_second_edge;\r\n}\r\n\r\ninline const Nx::S2DCollSurface&\tCRectFeeler::GetCollisionSurface ( int n ) const\r\n{\r\n\tDbg_Assert(n < m_coll_data.num_surfaces);\r\n\treturn m_coll_data.p_surfaces[n];\r\n}\r\n\r\ninline const Nx::S2DCollSurface&\tCRectFeeler::GetMergedCollisionSurface ( int n ) const\r\n{\r\n\tDbg_Assert(n < m_merged_coll_data.num_surfaces);\r\n\tDbg_Assert(!isnanf(m_merged_coll_data.p_surfaces[n].ends[0].point[W]));\r\n\tDbg_Assert(!isnanf(m_merged_coll_data.p_surfaces[n].ends[1].point[W]));\r\n\treturn m_merged_coll_data.p_surfaces[n];\r\n}\r\n\r\ninline void\t\t\t\t\t\t\tCRectFeeler::SetIgnore ( uint16 ignore_1, uint16 ignore_0 )\r\n{\r\n\tm_coll_data.ignore_1 = ignore_1;\r\n\tm_coll_data.ignore_0 = ignore_0;\r\n}\r\n\r\ninline bool\t\t\t\t\t\t\tCRectFeeler::very_close ( const Mth::Vector p, const Mth::Vector q ) const\r\n{\r\n\treturn Mth::Abs(p[X] - q[X]) < 0.1f && Mth::Abs(p[Y] - q[Y]) < 0.1f && Mth::Abs(p[Z] - q[Z]) < 0.1f;\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Engine/SuperSector.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSKATE3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSSEC\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tSuperSector.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t01/12/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tFunctions concerning SuperSectors\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n\r\n#include <engine/SuperSector.h>\t\t\t\t\t\r\n#include <gel/collision/collision.h>\r\n#include <gel/collision/colltridata.h>\r\n\r\n#include <sys/timer.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n\r\nnamespace SSec\r\n{\r\n\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define\tCOLL_LINE_EXTENSION\t0.5f\r\n\r\n#define\tvMAX_QUAL_SECTORS\t\t1024\t   \t// never saw this go above 100\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass WorldSectorNode : public Lst::Node< Nx::CSector >\r\n{\r\npublic:\r\n\tWorldSectorNode( Nx::CSector* sector ) : Lst::Node< Nx::CSector > ( sector ) {}\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic\tuint8\tsOperationId = 0;\t// operation id for sectors\r\n//#ifdef\t__PLAT_NGPS__\r\n//const\tNx::CCollStatic**\tQualCollSectors = (const Nx::CCollStatic**)0x70000000;\t// use ScratchPad Ram (SPR) for speed\r\n//#else\r\nstatic\tNx::CCollStatic*\tQualCollSectors[vMAX_QUAL_SECTORS];\r\n//#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nSector::Sector( void )\r\n{\r\n\t\r\n\r\n\tm_NumSectors = 0;\r\n\tm_NumCollSectors = 0;\r\n\tm_SectorList = NULL;\r\n\tm_CollSectorList = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSector::~Sector( void )\r\n{\r\n\t\r\n\r\n\tif( m_SectorList )\r\n\t{   \r\n\t\tdelete [] m_SectorList;\r\n\t}\r\n\tif( m_CollSectorList )\r\n\t{   \r\n\t\tMem::Free(m_CollSectorList);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tSector::remove_collision(Nx::CCollStatic *p_coll)\r\n{\r\n\tfor (int idx = 0; idx < m_NumCollSectors; idx++)\r\n\t{\r\n\t\tif (m_CollSectorList[idx] == p_coll)\r\n\t\t{\r\n\t\t\t// Shift the rest of the pointers over\r\n\t\t\tfor (int copy_idx = idx + 1; copy_idx < m_NumCollSectors; copy_idx++)\r\n\t\t\t{\r\n\t\t\t\tm_CollSectorList[copy_idx - 1] = m_CollSectorList[copy_idx];\r\n\t\t\t}\r\n\r\n\t\t\t// And put a NULL on the last one (in case it isn't there, yet)\r\n\t\t\tm_CollSectorList[m_NumCollSectors - 1] = NULL;\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Never found it\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tSector::replace_collision(Nx::CCollStatic *p_coll, Nx::CCollStatic *p_replace_coll)\r\n{\r\n\tfor (int idx = 0; idx < m_NumCollSectors; idx++)\r\n\t{\r\n\t\tif (m_CollSectorList[idx] == p_coll)\r\n\t\t{\r\n\t\t\tm_CollSectorList[idx] = p_replace_coll;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Never found it\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tSector::has_collision(Nx::CCollStatic *p_coll)\r\n{\r\n\tfor (int idx = 0; idx < m_NumCollSectors; idx++)\r\n\t{\r\n\t\tif (m_CollSectorList[idx] == p_coll)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Never found it\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\t\tGetCurrentSectorOperationId( void )\r\n{\r\n\t\r\n\r\n\treturn sOperationId;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8\t\tGetNewSectorOperationId( void )\r\n{   \r\n\t\r\n\r\n\treturn ++sOperationId;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nvoid\tManager::GenerateSuperSectors(const Mth::CBBox& world_bbox )\r\n{\r\n\tint i, j;\r\n\tfloat world_width, world_depth;\r\n\tfloat start_x, start_z;\r\n\r\n\tDbg_Printf( \"Generating Blank SuperSectors\\n\" );\r\n\r\n\tm_world_bbox = world_bbox;\r\n\r\n\tworld_width = world_bbox.GetMax()[X] - world_bbox.GetMin()[X];\r\n\tworld_depth = world_bbox.GetMax()[Z] - world_bbox.GetMin()[Z];\r\n\r\n\tm_sector_width = world_width / NUM_PARTITIONS_X;\r\n\tm_sector_depth = world_depth / NUM_PARTITIONS_Z;\r\n\r\n\t// For each super sector, find any world sectors which intersect the ss bounding box\r\n\t// and add that ws to ss's list of ws's\r\n\tstart_x = world_bbox.GetMin()[X];\r\n\t\t\r\n\tMth::Vector sec_min, sec_max;\r\n\tsec_min[W] = 0.0f;\t\t \t\t\t// to avoid assertions\r\n\tsec_max[W] = 0.0f;\r\n\tfor( i = 0; i < NUM_PARTITIONS_X; i++ )\r\n\t{\r\n\t\tstart_z = world_bbox.GetMin()[Z];\r\n\r\n\t\tfor( j = 0; j < NUM_PARTITIONS_Z; j++ )\r\n\t\t{\r\n\t\t\tsec_min[X] = start_x;\r\n\t\t\tsec_min[Y] = (float) -1000000000000.0f; //world_bbox.GetMin()[Y];\r\n\t\t\tsec_min[Z] = start_z;\r\n            \r\n\t\t\tsec_max[X] = start_x + m_sector_width;\r\n\t\t\tsec_max[Y] = (float) 1000000000000.0f; //world_bbox.GetMax()[Y];\r\n\t\t\tsec_max[Z] = start_z + m_sector_depth;\r\n\r\n\t\t\tm_super_sector_list[i][j].m_Bbox.Set(sec_min, sec_max);\r\n\t\t\t\r\n\t\t\tstart_z += m_sector_depth;\r\n\t\t}\r\n\r\n\t\tstart_x += m_sector_width;\r\n\t}\r\n\r\n\tm_num_sectors_x = NUM_PARTITIONS_X;\r\n\tm_num_sectors_z = NUM_PARTITIONS_Z;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::AddCollisionToSuperSectors( Nx::CCollStatic *coll, int num_coll_sectors )\r\n{\r\n\tLst::Head< Nx::CCollStatic > sector_list;\r\n\tLst::Node< Nx::CCollStatic > *sector, *next;\r\n\r\n//\tfor (int i=0;i<100;i++)\r\n//\t{\r\n//\t\tprintf (\"%f,%f -> %f,%f\\n\",\r\n//\t\tcoll[i].GetGeometry()->GetBBox().GetMin().GetX(),\r\n//\t\tcoll[i].GetGeometry()->GetBBox().GetMin().GetZ(),\r\n//\t\tcoll[i].GetGeometry()->GetBBox().GetMax().GetX(),\r\n//\t\tcoll[i].GetGeometry()->GetBBox().GetMax().GetZ());\r\n//\t}\r\n\r\n\r\n\t\t\t\t\t\r\n\tfor( int i = 0; i < NUM_PARTITIONS_X; i++ )\r\n\t{\r\n\t\tfor( int j = 0; j < NUM_PARTITIONS_Z; j++ )\r\n\t\t{\r\n\t\t\t// Allocate temp list on high heap\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n\t\t\tfor ( int idx = 0; idx < num_coll_sectors; idx++ )\r\n\t\t\t{\r\n\t\t\t\t// Check to see if this collision sector belongs in the SuperSector\r\n\t\t\t\tDbg_Assert(coll[idx].GetGeometry());\r\n\t\t\t\tif (coll[idx].GetGeometry()->GetNumFaces()>0 && coll[idx].GetGeometry()->GetBBox().Intersect(m_super_sector_list[i][j].m_Bbox))\r\n\t\t\t\t{\r\n\t\t\t\t\tLst::Node< Nx::CCollStatic > *node = new Lst::Node< Nx::CCollStatic > ( &(coll[idx]) );\r\n\t\t\t\t\tsector_list.AddToTail( node );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t\tif( sector_list.CountItems() > 0 )\r\n\t\t\t{\r\n\t\t\t\tm_super_sector_list[i][j].m_CollSectorList = (Nx::CCollStatic **) Mem::Malloc(sizeof(Nx::CCollStatic *) * sector_list.CountItems());\r\n\t\t\t\tm_super_sector_list[i][j].m_NumCollSectors = sector_list.CountItems();\r\n\t\t\t\tint k = 0;\r\n\t\t\t\tfor( sector = sector_list.GetNext(); sector; sector = next )\r\n\t\t\t\t{\r\n\t\t\t\t\tnext = sector->GetNext();\r\n\r\n\t\t\t\t\tm_super_sector_list[i][j].m_CollSectorList[k] = sector->GetData();\r\n\t\t\t\t\tdelete sector;\r\n\t\t\t\t\tk++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::UpdateCollisionSuperSectors(Lst::Head<Nx::CCollStatic> &add_list,\r\n\t\t\t\t\t\t\t\t\t\t\t Lst::Head<Nx::CCollStatic> &remove_list,\r\n\t\t\t\t\t\t\t\t\t\t\t Lst::Head<Nx::CCollStatic> &update_list)\r\n{\r\n\tLst::Head< Nx::CCollStatic > sector_add_list;\r\n\tLst::Node< Nx::CCollStatic > *sector, *next;\r\n\tNx::CCollStatic *p_coll_sector;\r\n\r\n\tuint num_add_items = add_list.CountItems();\r\n\tuint num_remove_items = remove_list.CountItems();\r\n\tuint num_update_items = update_list.CountItems();\r\n\r\n\t//Dbg_Message(\"In UpdateCollisionSuperSectors with add size %d, remove size %d\", num_add_items, num_remove_items);\r\n\r\n\tuint idx;\r\n\tint num_change;\r\n\tfor( int i = 0; i < NUM_PARTITIONS_X; i++ )\r\n\t{\r\n\t\tfor( int j = 0; j < NUM_PARTITIONS_Z; j++ )\r\n\t\t{\r\n\t\t\tSSec::Sector *p_super_sector = &(m_super_sector_list[i][j]);\r\n\t\t\tnum_change = 0;\r\n\r\n\t\t\t// Allocate temp list on high heap\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n\t\t\t// Check removed sectors first\r\n\t\t\tsector = remove_list.GetNext();\r\n\t\t\tfor (idx = 0; idx < num_remove_items; idx++)\r\n\t\t\t{\r\n\t\t\t\tp_coll_sector = sector->GetData();\r\n\r\n\t\t\t\t// Check to see if this collision sector should be in the SuperSector\r\n\t\t\t\tif (p_coll_sector->GetGeometry()->GetBBox().Intersect(p_super_sector->m_Bbox))\r\n\t\t\t\t{\r\n\t\t\t\t\t//Dbg_Message(\"Removing collision %x to SuperSector (%d, %d)\", p_coll_sector->GetChecksum(), i, j);\r\n\t\t\t\t\tnum_change = remove_from_super_sector(p_coll_sector, p_super_sector, sector_add_list, num_change);\r\n#if 0\r\n\t\t\t\t} else {\r\n\t\t\t\t\tif (p_super_sector->remove_collision(p_coll_sector))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnum_change--;\r\n\t\t\t\t\t\tDbg_MsgAssert(0, (\"UpdateCollisionSuperSectors: Removed collision %x that shouldn't be in SuperSector (%d, %d)\", \r\n\t\t\t\t\t\t\t\t\t\t  p_coll_sector->GetChecksum(), i, j));\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t}\r\n\r\n\t\t\t\tsector = sector->GetNext();\r\n\t\t\t}\r\n\r\n\t\t\t// Now check added sectors\r\n\t\t\tsector = add_list.GetNext();\r\n\t\t\tfor (idx = 0; idx < num_add_items; idx++)\r\n\t\t\t{\r\n\t\t\t\tp_coll_sector = sector->GetData();\r\n\r\n\t\t\t\t// Check to see if this collision sector belongs in the SuperSector\r\n\t\t\t\tif (p_coll_sector->GetGeometry()->GetBBox().Intersect(p_super_sector->m_Bbox))\r\n\t\t\t\t{\r\n\t\t\t\t\t//Dbg_Message(\"Adding collision %x to SuperSector (%d, %d)\", p_coll_sector->GetChecksum(), i, j);\r\n\t\t\t\t\tnum_change = add_to_super_sector(p_coll_sector, p_super_sector, sector_add_list, num_change);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tsector = sector->GetNext();\r\n\t\t\t}\r\n\t\t\t// And check updated sectors\r\n\t\t\tsector = update_list.GetNext();\r\n\t\t\tfor (idx = 0; idx < num_update_items; idx++)\r\n\t\t\t{\r\n\t\t\t\tp_coll_sector = sector->GetData();\r\n\t\t\t\tbool on_list = p_super_sector->has_collision(p_coll_sector);\r\n\t\t\t\tif (p_coll_sector->GetGeometry()->GetBBox().Intersect(p_super_sector->m_Bbox) != on_list)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (on_list)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//Dbg_Message(\"Removing updated collision %x to SuperSector (%d, %d)\", p_coll_sector->GetChecksum(), i, j);\r\n\t\t\t\t\t\t// Remove sector\r\n\t\t\t\t\t\tnum_change = remove_from_super_sector(p_coll_sector, p_super_sector, sector_add_list, num_change);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//Dbg_Message(\"Adding updated collision %x to SuperSector (%d, %d)\", p_coll_sector->GetChecksum(), i, j);\r\n\t\t\t\t\t\t// Add sector\r\n\t\t\t\t\t\tnum_change = add_to_super_sector(p_coll_sector, p_super_sector, sector_add_list, num_change);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tsector = sector->GetNext();\r\n\t\t\t}\r\n\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t\tint new_size = p_super_sector->m_NumCollSectors + num_change;\r\n\r\n\t\t\tif (num_change < 0)\t\t\t\t// Re-alloc array down\r\n\t\t\t{\r\n\t\t\t\tif (!p_super_sector->m_CollSectorList ||\r\n\t\t\t\t\t!Mem::Manager::sHandle().ReallocateShrink(sizeof(Nx::CCollStatic *) * new_size, p_super_sector->m_CollSectorList))\r\n\t\t\t\t{\r\n\t\t\t\t\t// If we can't realloc down, then we have to use the old realloc\r\n\t\t\t\t\tp_super_sector->m_CollSectorList = (Nx::CCollStatic **) Mem::Realloc(p_super_sector->m_CollSectorList,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t sizeof(Nx::CCollStatic *) * new_size);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (num_change > 0)\t\t// Re-alloc array up and copy in sector_add_list\r\n\t\t\t{\r\n\t\t\t\tif (!p_super_sector->m_CollSectorList ||\r\n\t\t\t\t    !Mem::Manager::sHandle().ReallocateUp(sizeof(Nx::CCollStatic *) * new_size, p_super_sector->m_CollSectorList))\r\n\t\t\t\t{\r\n\t\t\t\t\t// If we can't realloc up, then we have to use the old realloc\r\n\t\t\t\t\tp_super_sector->m_CollSectorList = (Nx::CCollStatic **) Mem::Realloc(p_super_sector->m_CollSectorList,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t sizeof(Nx::CCollStatic *) * new_size);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Copy add list in\r\n\t\t\t\tidx = p_super_sector->m_NumCollSectors;\r\n\t\t\t\tfor(sector = sector_add_list.GetNext(); sector; sector = next)\r\n\t\t\t\t{\r\n\t\t\t\t\tnext = sector->GetNext();\r\n\r\n\t\t\t\t\tp_super_sector->m_CollSectorList[idx] = sector->GetData();\r\n\t\t\t\t\tdelete sector;\r\n\t\t\t\t\tidx++;\r\n\t\t\t\t}\r\n\t\t\t\t//Dbg_Message(\"Adding %d sectors to [%d, %d]. New size %d\", num_change, i, j, new_size);\r\n\t\t\t}\r\n\r\n\t\t\tDbg_Assert(sector_add_list.IsEmpty());\r\n\r\n\t\t\tp_super_sector->m_NumCollSectors = new_size;\r\n\t\t}\r\n\t}\r\n\t\r\n\t\r\n\t\r\n\tfor( int i = 0; i < NUM_PARTITIONS_X; i++ )\r\n\t{\r\n\t\tfor( int j = 0; j < NUM_PARTITIONS_Z; j++ )\r\n\t\t{\r\n\t\t\tSSec::Sector *p_super_sector = &(m_super_sector_list[i][j]);\r\n\t\t\tNx::CCollStatic** pp_old = p_super_sector->m_CollSectorList;\r\n\t\t\tif (pp_old)\r\n\t\t\t{\r\n\t\t\t\tuint32 count = p_super_sector->m_NumCollSectors;\r\n\t\t\t\tif (count)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_super_sector->m_CollSectorList = (Nx::CCollStatic**)Mem::Malloc(4*(count));\r\n\t\t\t\t\tmemcpy(p_super_sector->m_CollSectorList, pp_old, 4*(count));\r\n\t\t\t\t\tMem::Free(pp_old);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_super_sector->m_CollSectorList = NULL;\r\n\t\t\t\t\tMem::Free(pp_old);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::add_to_super_sector(Nx::CCollStatic *p_coll, SSec::Sector *p_super_sector, Lst::Head< Nx::CCollStatic > & add_list, int num_changes)\r\n{\r\n\tif (num_changes < 0)\r\n\t{\r\n\t\t// Just append to end of existing array\r\n\t\tint avail_idx = p_super_sector->m_NumCollSectors + num_changes;\r\n\t\tp_super_sector->m_CollSectorList[avail_idx] = p_coll;\r\n\t} else {\r\n\t\t// Append to add list\r\n\t\tLst::Node< Nx::CCollStatic > *node = new Lst::Node< Nx::CCollStatic > (p_coll);\r\n\t\tadd_list.AddToTail(node);\r\n\t}\r\n\r\n\treturn ++num_changes;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::remove_from_super_sector(Nx::CCollStatic *p_coll, SSec::Sector *p_super_sector, Lst::Head< Nx::CCollStatic > & add_list, int num_changes)\r\n{\r\n\tif (num_changes > 0)\r\n\t{\r\n\t\t// Move a sector off the add list, if there is one\r\n\t\tLst::Node< Nx::CCollStatic > *p_sector_node;\r\n\r\n\t\tp_sector_node = add_list.GetNext();\r\n\t\tif (!p_super_sector->replace_collision(p_coll, p_sector_node->GetData()))\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"UpdateCollisionSuperSectors: Can't replace collision %x that should be in SuperSector\", \r\n\t\t\t\t\t\t\t  p_coll->GetChecksum()));\r\n\t\t}\r\n\t\tdelete p_sector_node;\r\n\t}\r\n\telse \r\n\t{\r\n\t\t// Just remove the sector\r\n\t\tif (!p_super_sector->remove_collision(p_coll))\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"UpdateCollisionSuperSectors: Can't remove collision %x that should be in SuperSector\", \r\n\t\t\t\t\t\t\t  p_coll->GetChecksum()));\r\n\t\t}\r\n\t}\r\n\r\n\treturn --num_changes;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::ClearCollisionSuperSectors()\r\n{\r\n\t// Just delete all the arrays, since whoever called this knows they are all going away\r\n\tfor( int i = 0; i < NUM_PARTITIONS_X; i++ )\r\n\t{\r\n\t\tfor( int j = 0; j < NUM_PARTITIONS_Z; j++ )\r\n\t\t{\r\n\t\t\tSSec::Sector *p_super_sector = &(m_super_sector_list[i][j]);\r\n\r\n\t\t\tif( p_super_sector->m_CollSectorList )\r\n\t\t\t{   \r\n\t\t\t\tMem::Free(p_super_sector->m_CollSectorList);\r\n\t\t\t\tp_super_sector->m_CollSectorList = NULL;\r\n\t\t\t}\r\n\r\n\t\t\tp_super_sector->m_NumCollSectors = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::CCollStatic** Manager::GetIntersectingCollSectors( Mth::CBBox& bbox )\r\n{\r\n\tint op_id = GetNewSectorOperationId();\r\n\t\r\n\tfloat x_min = bbox.GetMin()[X] - m_world_bbox.GetMin()[X];\r\n\tfloat x_max = bbox.GetMax()[X] - m_world_bbox.GetMin()[X];\r\n\tfloat z_min = bbox.GetMin()[Z] - m_world_bbox.GetMin()[Z];\r\n\tfloat z_max = bbox.GetMax()[Z] - m_world_bbox.GetMin()[Z];\r\n\t\r\n\t// extent the min and max in each direction to catch boundary conditions\r\n\tx_min -= COLL_LINE_EXTENSION;\r\n\tx_max += COLL_LINE_EXTENSION;\r\n\tz_min -= COLL_LINE_EXTENSION;\r\n\tz_max += COLL_LINE_EXTENSION;\r\n\t\r\n\t// determine the corresponding rectangle in terms of super sectors indicies\r\n\tint start_x_box = static_cast< int >(x_min / m_sector_width);\r\n\tint start_z_box = static_cast< int >(z_min / m_sector_depth);\r\n\tint end_x_box = static_cast< int >(x_max / m_sector_width);\r\n\tint end_z_box = static_cast< int >(z_max / m_sector_depth);\r\n\t\r\n\t// cap the super sector indicies\r\n\tif (start_x_box < 0)\r\n\t{\r\n\t\tstart_x_box = 0;\r\n\t}\r\n\telse if (start_x_box >= m_num_sectors_x)\r\n\t{\r\n\t\tstart_x_box = m_num_sectors_x - 1;\r\n\t}\r\n\tif (start_z_box < 0)\r\n\t{\r\n\t\tstart_z_box = 0;\r\n\t}\r\n\telse if (start_z_box >= m_num_sectors_z)\r\n\t{\r\n\t\tstart_z_box = m_num_sectors_z - 1;\r\n\t}\r\n\tif (end_x_box < 0)\r\n\t{\r\n\t\tend_x_box = 0;\r\n\t}\r\n\telse if (end_x_box >= m_num_sectors_x)\r\n\t{\r\n\t\tend_x_box = m_num_sectors_x - 1;\r\n\t}\r\n\tif (end_z_box < 0)\r\n\t{\r\n\t\tend_z_box = 0;\r\n\t}\r\n\telse if (end_z_box >= m_num_sectors_z)\r\n\t{\r\n\t\tend_z_box = m_num_sectors_z - 1;\r\n\t}\r\n\t\r\n\t// loop over the corresponding super sectors and add the sectors to the qualifying list\r\n\tint qual_sector_idx = 0;\r\n\tfor (int i = start_x_box; i <= end_x_box; i++)\r\n\t{\r\n\t\tfor (int j = start_z_box; j <= end_z_box; j++)\r\n\t\t{\r\n\t\t\tfor (int k = 0; k < m_super_sector_list[i][j].m_NumCollSectors; k++)\r\n\t\t\t{\r\n\t\t\t\tNx::CCollStatic* cs = m_super_sector_list[i][j].m_CollSectorList[k];\r\n\t\t\t\t\r\n\t\t\t\tif (cs->GetObjectFlags() & (mSD_NON_COLLIDABLE | mSD_KILLED)) continue;\r\n\t\t\t\t\r\n\t\t\t\tif (cs->GetSuperSectorID() == op_id) continue;\r\n\t\t\t\t\r\n\t\t\t\tQualCollSectors[qual_sector_idx++] = cs;\r\n\t\t\t\t\r\n\t\t\t\tcs->SetSuperSectorID(op_id);\r\n\t\t\t\t\r\n\t\t\t\tDbg_MsgAssert(qual_sector_idx < (vMAX_QUAL_SECTORS*8/10),(\"Too many %d qualifying collision sectors\",qual_sector_idx));\t\t\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tQualCollSectors[qual_sector_idx] = NULL;\r\n\t\r\n\treturn static_cast< Nx::CCollStatic** >(QualCollSectors);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::CCollStatic** Manager::GetIntersectingCollSectors( Mth::Line &line )\r\n{\r\n\t\r\n\t\r\n\tint qual_sector_idx;\r\n\tMth::Line test_line;\r\n\tMth::Vector dir;\r\n\tfloat x_offset, z_offset;\r\n\tint start_x_box, start_z_box;\r\n\tint end_x_box, end_z_box;\r\n\tint temp,k;\r\n\tint op_id;\r\n\t\t\r\n\tqual_sector_idx = 0;\r\n\r\n\r\n\t// Extend the line a foot in each direction just to catch boundary conditions\r\n\tdir = Mth::Vector( line.m_end[X] - line.m_start[X],\r\n\t\t\t\t\t   line.m_end[Y] - line.m_start[Y],\r\n\t\t\t\t\t   line.m_end[Z] - line.m_start[Z] );\r\n\tdir.Normalize();\r\n\tdir.Scale( COLL_LINE_EXTENSION );\r\n\ttest_line.m_start[X]\t= line.m_start[X] - dir.GetX();\r\n\ttest_line.m_start[Y]\t= line.m_start[Y] - dir.GetY();\r\n\ttest_line.m_start[Z]\t= line.m_start[Z] - dir.GetZ();\r\n\ttest_line.m_end[X]\t\t= line.m_end[X] + dir.GetX();\r\n\ttest_line.m_end[Y]\t\t= line.m_end[Y] + dir.GetY();\r\n\ttest_line.m_end[Z]\t\t= line.m_end[Z] + dir.GetZ();\r\n\r\n\t// Figure out which super sector the start point is in\r\n\tx_offset = test_line.m_start[X] - m_world_bbox.GetMin()[X];\r\n\tz_offset = test_line.m_start[Z] - m_world_bbox.GetMin()[Z];\r\n\r\n\tstart_x_box = (int) ( x_offset / m_sector_width );\r\n\tstart_z_box = (int) ( z_offset / m_sector_depth );\r\n\r\n//#define DISABLE_SUPER_SECTORS\r\n#ifdef DISABLE_SUPER_SECTORS\r\n\tstart_x_box = start_z_box = 0;\r\n#endif // DISABLE_SUPER_SECTORS\r\n\r\n\t// Some sanity checks\r\n\tif( start_x_box < 0 )\r\n\t{\r\n\t\tstart_x_box = 0;\r\n\t}\r\n\telse if( start_x_box >= m_num_sectors_x )\r\n\t{\r\n\t\tstart_x_box = m_num_sectors_x - 1;\r\n\t}\r\n\r\n\tif( start_z_box < 0 )\r\n\t{\r\n\t\tstart_z_box = 0;\r\n\t}\r\n\telse if( start_z_box >= m_num_sectors_z )\r\n\t{\r\n\t\tstart_z_box = m_num_sectors_z - 1;\r\n\t}\r\n\r\n\t// Figure out which super sector the end point is in\r\n\tx_offset = test_line.m_end[X] - m_world_bbox.GetMin()[X];\r\n\tz_offset = test_line.m_end[Z] - m_world_bbox.GetMin()[Z];\r\n\t\t\r\n\tend_x_box = (int) ( x_offset / m_sector_width );\r\n\tend_z_box = (int) ( z_offset / m_sector_depth );\r\n\r\n#ifdef DISABLE_SUPER_SECTORS\r\n\tend_x_box = m_num_sectors_x - 1;\r\n\tend_z_box = m_num_sectors_z - 1;\r\n#endif // DISABLE_SUPER_SECTORS\r\n\r\n\t// Some sanity checks\r\n\tif( end_x_box < 0 )\r\n\t{\r\n\t\tend_x_box = 0;\r\n\t}\r\n\telse if( end_x_box >= m_num_sectors_x )\r\n\t{\r\n\t\tend_x_box = m_num_sectors_x - 1;\r\n\t}\r\n\r\n\tif( end_z_box < 0 )\r\n\t{\r\n\t\tend_z_box = 0;\r\n\t}\r\n\telse if( end_z_box >= m_num_sectors_z )\r\n\t{\r\n\t\tend_z_box = m_num_sectors_z - 1;\r\n\t}\r\n\r\n\t// Organize vars for two-dimensional \"for\" loop\r\n\tif( end_x_box < start_x_box )\r\n\t{\r\n\t\ttemp = end_x_box;\r\n\t\tend_x_box = start_x_box;\r\n\t\tstart_x_box = temp;\r\n\t}\r\n\r\n\tif( end_z_box < start_z_box )\r\n\t{\r\n\t\ttemp = end_z_box;\r\n\t\tend_z_box = start_z_box;\r\n\t\tstart_z_box = temp;\r\n\t}\r\n\r\n\t//Dbg_Message(\"SuperSector collision start(%d, %d) end(%d, %d)\", start_x_box, start_z_box, end_x_box, end_z_box);\r\n\t//Dbg_Message(\"SuperSector testline start(%f, %f) end(%f, %f)\", test_line.m_start[X], test_line.m_start[Z], test_line.m_end[X], test_line.m_end[Z]);\r\n\t//Dbg_Message(\"SuperSector world start(%f, %f) sector size(%f, %f)\", m_world_bbox.inf.x, m_world_bbox.inf.z, m_sector_width, m_sector_depth);\r\n\r\n\r\n// Optimize for the case (95%) where start and end are the same\r\n// Just copy over the qualifying sectors pointers from one supersector\r\n// This makes the routine about 30% fater on average.  \r\n\tif (start_x_box == end_x_box && start_z_box == end_z_box)\r\n\t{\r\n\t\tSector * p_sec = &m_super_sector_list[start_x_box][start_z_box]; \r\n\t\tint num = p_sec->m_NumCollSectors;\r\n\t\tNx::CCollStatic** pp_cs = p_sec->m_CollSectorList; \r\n\t\tNx::CCollStatic**  pp_qual = QualCollSectors;\t\t\r\n//\t\tprintf (\"%8d: %3d (%d,%d)\\n\",(int)Tmr::GetRenderFrame(),num,start_x_box, start_z_box);\r\n\t\tfor( k = 0; k < num; k++ )\r\n\t\t{\r\n\t\t\tNx::CCollStatic* cs= *pp_cs++;\r\n\t\t\tif ( !( cs->GetObjectFlags() & ( mSD_NON_COLLIDABLE | mSD_KILLED ) ) )\r\n\t\t\t{\r\n\t\t\t\t*pp_qual++ = cs;\r\n\t\t\t}\r\n\r\n\t\t}\r\n\t\t*pp_qual = NULL;\r\n\t\treturn (Nx::CCollStatic**)QualCollSectors;\r\n\t}\r\n\t\r\n\r\n//\tint checked = 0;\r\n//\tint passed = 0;\r\n\r\n\r\n\top_id = GetNewSectorOperationId();\r\n\t\t\r\n\t// Add world sectors from these super sectors to the qualifying list\r\n\tfor( int i = start_x_box; i <= end_x_box; i++ )\r\n\t{\r\n\t\tfor( int j = start_z_box; j <= end_z_box; j++ )\r\n\t\t{\r\n\t\t\tfor( k = 0; k < m_super_sector_list[i][j].m_NumCollSectors; k++ )\r\n\t\t\t{\r\n//\t\t\t\tchecked++;\r\n\t\t\t\tNx::CCollStatic* cs;\r\n\t\t\t\t\r\n\t\t\t\tcs = m_super_sector_list[i][j].m_CollSectorList[k];\r\n\t\t\t\t\r\n\t\t\t\tif ( !( cs->GetObjectFlags() & ( mSD_NON_COLLIDABLE | mSD_KILLED ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t// If we haven't already added it, add it\r\n\t\t\t\t\tif( cs->GetSuperSectorID() != op_id )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (qual_sector_idx < vMAX_QUAL_SECTORS-1)\r\n\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tpassed++;\r\n\t\t\t\t\t\t\tQualCollSectors[qual_sector_idx++] = cs;\r\n\t\t\t\t\t\t\t// Mark it as having been added in this operation\r\n\t\t\t\t\t\t\tcs->SetSuperSectorID(op_id);\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t// normally we just return\r\n\t\t\t\t\t\t// but in case someone does something that involves the whole\r\n\t\t\t\t\t\t// world, we add this assertion...\r\n\t\t\t\t\t\tDbg_MsgAssert(qual_sector_idx < (vMAX_QUAL_SECTORS*8/10),(\"Too many %d qualifying collision sectors (%d,%d)-(%d,%d).\\n  Is a non-playable portion of the level flagged as collidable? Maybe the clouds, or the sea?\",\r\n\t\t\t\t\t\tqual_sector_idx, start_x_box,start_z_box,end_x_box,end_z_box ));\t\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}        \r\n\t\r\n\t//printf (\"(%d,%d) to (%d, %d), checked %d, returning %d\\n\",start_x_box,start_z_box,end_x_box,end_z_box,checked, passed);                              \r\n\r\n\tQualCollSectors[qual_sector_idx] = NULL;\r\n\treturn (Nx::CCollStatic**)QualCollSectors;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::CSector**\tManager::GetIntersectingWorldSectors( Mth::Line &line )\r\n{\r\n\r\n\r\n\tDbg_MsgAssert(0,(\"GetIntersectingWorldSectors is an old function\"));\t\r\n\treturn NULL;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace SSec\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Engine/SuperSector.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSSEC\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tSuperSector.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t01/12/2001\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__ENGINE_SUPERSECTOR_H\r\n#define\t__ENGINE_SUPERSECTOR_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/////////////////////////////////////////////////////////////////////////\r\n// Forward declarations\r\nnamespace Nx\r\n{\r\nclass\tCSector;\r\nclass\tCCollObj;\r\nclass\tCCollStatic;\r\n}\r\n\r\n\r\nnamespace SSec\r\n{\r\n\r\n// Forward declaration\r\nclass Manager;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Sector\r\n{\r\npublic:\r\n\tSector( void );\r\n\t~Sector( void );\r\n\r\nprivate:\r\n\t// Remove pointer out of sector array and shift the rest.  Doesn't update m_NumCollSectors!\r\n\tbool\t\t\t\tremove_collision(Nx::CCollStatic *p_coll);\r\n\tbool\t\t\t\treplace_collision(Nx::CCollStatic *p_coll, Nx::CCollStatic *p_replace_coll);\r\n\tbool\t\t\t\thas_collision(Nx::CCollStatic *p_coll);\r\n\r\n\tMth::CBBox\t\t\tm_Bbox;\r\n\tint\t\t\t\t\tm_NumSectors;\r\n\tint\t\t\t\t\tm_NumCollSectors;\r\n\tNx::CSector**\t\tm_SectorList;\r\n\tNx::CCollStatic**\tm_CollSectorList;\r\n\r\n\tfriend Manager;\r\n};\r\n\r\n\r\nclass Manager\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tNUM_PARTITIONS_X = 20,\r\n\t\tNUM_PARTITIONS_Z = 20,\r\n\t};\r\n\r\n\tNx::CSector**\t\tGetIntersectingWorldSectors( Mth::Line &line );\r\n\tNx::CCollStatic**\tGetIntersectingCollSectors( Mth::Line &line );\r\n\tNx::CCollStatic**\tGetIntersectingCollSectors( Mth::CBBox &bbox );\r\n\tvoid\t\t\t\tGenerateSuperSectors( const Mth::CBBox& world_bbox );\r\n\tvoid\t\t\t\tAddCollisionToSuperSectors( Nx::CCollStatic *coll, int num_coll_sectors );\r\n\tvoid\t\t\t\tUpdateCollisionSuperSectors(Lst::Head<Nx::CCollStatic> &add_list,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tLst::Head<Nx::CCollStatic> &remove_list,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tLst::Head<Nx::CCollStatic> &update_list);\r\n\tvoid\t\t\t\tClearCollisionSuperSectors();\r\n\r\n\tMth::CBBox *\t\tGetWorldBBox( void ) { return &m_world_bbox; }\r\n\r\nprivate:\r\n\tint\t\t\t\t\tadd_to_super_sector(Nx::CCollStatic *p_coll, SSec::Sector *p_super_sector, Lst::Head< Nx::CCollStatic > & add_list, int num_changes);\r\n\tint\t\t\t\t\tremove_from_super_sector(Nx::CCollStatic *p_coll, SSec::Sector *p_super_sector, Lst::Head< Nx::CCollStatic > & add_list, int num_changes);\r\n\r\n\tMth::CBBox\t\t\tm_world_bbox;\r\n\tfloat\t\t\t\tm_sector_width;\r\n\tfloat \t\t\t\tm_sector_depth;\r\n\tint \t\t\t\tm_num_sectors_x;\r\n\tint \t\t\t\tm_num_sectors_z;\r\n\tSector\t\t\t\tm_super_sector_list[NUM_PARTITIONS_X][NUM_PARTITIONS_Z];\r\n};\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nuint8\t\tGetCurrentSectorOperationId( void );\r\nuint8\t\tGetNewSectorOperationId( void );\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace SSec\r\n\r\n#endif\t// __ENGINE_SUPERSECTOR_H"
  },
  {
    "path": "Code/Sk/Engine/contact.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Contact.cpp\t  - Mick\r\n//\r\n// a contact is a point \"on\" a moving object\r\n// generally on the  surface of the object\r\n// and more generally at a position realative to it\r\n// it is responsible for maintaining changes in\r\n// position, due to changes on the object it is on\r\n\r\n\r\n#include <engine/contact.h>\r\n#include <sk/objects/movingobject.h>\r\n#include <gfx/debuggfx.h>\r\n#include <gfx/nx.h>\r\n\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\nCContact::CContact()\r\n{\r\n}\r\n\r\nCContact::CContact(Obj::CCompositeObject *p_moving_object )\r\n{\r\n\r\n\tmp_moving_object = p_moving_object;\r\n//\tm_object_id = mp_moving_object->GetID();\r\n\t\r\n\tm_object_last_matrix = mp_moving_object->GetMatrix();\r\n\tm_object_last_pos = mp_moving_object->GetPos();\r\n\t\r\n\tm_movement.Set();\r\n\tm_rotated = false;\r\n}\r\n\r\n\r\n// check to see if the object exists.\t\t\t\t\t\t\t\t\t\r\nbool\t\tCContact::ObjectExists()\r\n{\r\n\t// With smart pointers, GetObject will just return NULL if the object has been deleted \r\n\treturn (GetObject() != NULL);\r\n}\r\n\r\n// call this once per frame, to calculate the movement of the contact point\r\nbool\t\tCContact::Update(const Mth::Vector &pos)\r\n{\t\t\t\t\t\t\t\t\t\t\t\r\n\tif (!mp_moving_object.Convert())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tm_movement = mp_moving_object->GetPos() - m_object_last_pos;\r\n\t\r\n\t// so far we have only accounted for the movement of the object's origin\r\n\t// (mp_moving_object->GetPos()), and we need to see if the object has rotated\r\n\t// which will give us an additional movement vector\r\n\r\n\tif (m_object_last_matrix != mp_moving_object->GetMatrix())\r\n\t{\r\n\t\tm_rotated = true;\r\n//\t\tprintf (\"Object has rotated\\n\");\r\n\t\t// Get the position relative to the origin on the object\r\n\t\tMth::Vector old_offset = pos - m_object_last_pos;\r\n\t\tMth::Vector offset = old_offset;\r\n\r\n//\t\tprintf (\"Offset (%.2f,%.2f,%.2f)\\n\",offset[X],offset[Y],offset[Z]);\r\n\t\t\r\n\t\t// transform by the inverse of the original matrix\r\n\t\tMth::Matrix back = m_object_last_matrix;\t\t  \r\n\t\t// just to be safe\r\n\t\tback[W] = Mth::Vector(0,0,0,1);\r\n\t\tback[X][W] = 0.0f;\r\n\t\tback[Y][W] = 0.0f;\r\n\t\tback[Z][W] = 0.0f;\r\n\t\tback.InvertUniform();\r\n\r\n\t\t// transform to the new matrix\r\n\t\tm_rotation =  mp_moving_object->GetMatrix();\r\n\t\t// just to be safe\r\n\t\tm_rotation[W] = Mth::Vector(0,0,0,1);\r\n\t\tm_rotation[X][W] = 0.0f;\r\n\t\tm_rotation[Y][W] = 0.0f;\r\n\t\tm_rotation[Z][W] = 0.0f;\r\n\t\t\r\n\t\tm_rotation *= back;\t\t\r\n\t\t\r\n\t\tMth::Vector new_offset = m_rotation.Transform(offset);\r\n\r\n//\t\tprintf (\"new Offset (%.2f,%.2f,%.2f)\\n\",new_offset[X],new_offset[Y],new_offset[Z]);\r\n\t\t\r\n\t\t// Calculate the movment due to rotation\r\n\t\tMth::Vector\trotation_movement = (new_offset - old_offset);\r\n\t\r\n\t\t// add it to the movement, so it is included in the skater's movement\r\n\t\tm_movement += rotation_movement;\r\n\r\n\t\tm_object_last_matrix = mp_moving_object->GetMatrix();\r\n\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_rotated = false;\r\n\t}\r\n\t\r\n\tm_object_last_pos = mp_moving_object->GetPos();\r\n\r\n\treturn true;\r\n}\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Engine/contact.h",
    "content": "\r\n#ifndef\t__ENGINE_CONTACT_H__\r\n#define\t__ENGINE_CONTACT_H__\r\n\r\n#include <core/math.h>\r\n#include <gel/objptr.h>\r\n#include <gel/object/compositeobject.h>\r\n\r\nclass\tCContact\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tCContact();\r\n\t\t\t\t\t\t\t\tCContact(Obj::CCompositeObject *p_moving_object);\r\n\r\n\tbool\t\t\t\t\t\tObjectExists();\t\t// returns false if object has been deleted, or is \"dead\" or \"inactive\"\r\n\tbool\t\t\t\t\t\tUpdate(const Mth::Vector &pos);\t\t// Update the position, return false if object no longer exists\r\n\tconst Mth::Vector\t\t&\tGetMovement() const;\t\t// get movement vector of the contact point for this frame \t\r\n\tconst Mth::Matrix\t\t&\tGetRotation() const;\t\t// get rotation matrix for this frame \t\r\n\tbool\t\t\t\t\t\tIsRotated() const;\r\n\t\t\t\t\t\t   \r\nprivate:\r\n\tObj::CSmtPtr<Obj::CCompositeObject>\t\tmp_moving_object;\r\n\tMth::Matrix\t\t\t\t\tm_object_last_matrix; \t// The object's last orientation\r\n\tMth::Vector\t\t\t\t\tm_object_last_pos;\t\t// The object's last position\r\n\r\n\tMth::Vector\t\t\t\t\tm_movement;\r\n\tMth::Matrix\t\t\t\t\tm_rotation;\r\n\t\r\n\tbool \t\t\t\t\t\tm_rotated;\t\t\t\t// set if it was rotated\r\n\r\npublic:\r\n\tObj::CCompositeObject*\t\tGetObject() {return mp_moving_object.Convert();}\t\t// return the object we are in contact with\r\n\r\n\r\n};\r\n\r\ninline const Mth::Vector\t\t&\tCContact::GetMovement() const\r\n{\r\n\treturn\tm_movement;\t\r\n}\r\n\r\ninline bool\t\t\t\t\t\t\tCContact::IsRotated() const\r\n{\r\n\treturn\tm_rotated;\r\n}\r\n\r\ninline const Mth::Matrix\t\t&\tCContact::GetRotation() const\r\n{\r\n\treturn\tm_rotation;\t\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Sk/Engine/feeler.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Feeler.cpp\t  - Mick\r\n//\r\n// A feeler is a 3D line segment that can check for collision with\r\n// the world, and return information about the faces it collides with\r\n//\r\n// it's derived from the line type\r\n// so operations you can do with a line\r\n// can also be done with the feeler\t\t  \r\n// (See geometry.cpp for line operations)\r\n\r\n\r\n#include <engine/feeler.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/math.h>\r\n#include <gfx/debuggfx.h>\r\n#include <core/math/geometry.h>\r\n\r\n#include <gel/collision/collision.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/modman.h>\r\n\r\n#include <gfx/nx.h>\r\n\r\n#define PRINT_TIMES 0\r\n\t\t\t\t\t\t\r\nNx::CCollCache *\t\tCFeeler::sp_default_cache = NULL;\r\n\r\n\t\t\t\t\t\r\nCFeeler::CFeeler()\r\n{\r\n\tinit();\r\n}\r\n\r\nCFeeler::CFeeler(const Mth::Vector &start, const Mth::Vector &end)\r\n{\r\n\tm_start = start;\r\n\tm_end = end;\r\n\tm_col_data.surface.normal.Set(1.0, 1.0, 1.0);\r\n\tinit();\r\n}\r\n\r\nvoid CFeeler::init (   )\r\n{\r\n\t// When we create a feeler\r\n\t// we use the default \"ignore\" settings\r\n\t// as they will be used the most\r\n\tm_col_data.ignore_1 = mFD_NON_COLLIDABLE; \t\t// ignore NON_COLLIDABLES\r\n\tm_col_data.ignore_0 = 0;\t\t\t\t\t\t// don't ignore anything else\r\n\tmp_callback = NULL;\r\n\tmp_cache = NULL;\r\n\r\n\t// Now un-initialized...\r\n\tm_col_data.surface.normal.Set();\r\n\tm_col_data.surface.point.Set();\r\n}\r\n\r\nvoid CFeeler::SetIgnore(uint16 ignore_1, uint16 ignore_0)\r\n{\r\n\tm_col_data.ignore_1 = ignore_1;\r\n\tm_col_data.ignore_0 = ignore_0;\r\n}\r\n\r\n\r\nvoid CFeeler::SetStart(const Mth::Vector &start)\r\n{\r\n\tm_start = start;\r\n}\r\n\r\nvoid CFeeler::SetEnd(const Mth::Vector &end)\r\n{\r\n\tm_end = end;\r\n}\r\n\r\nvoid CFeeler::SetLine(const Mth::Vector &start, const Mth::Vector &end)\r\n{\r\n\tSetStart(start);\r\n\tSetEnd(end);\r\n}\r\n\r\n\t\t\t\t\t\t\t  \r\n\r\n// This callback gets called by the CLd:: collision code\r\n// (which was in turn a callback called from elsewhere)\r\n// and then this calls my Callback\r\n// we should try to simplyify this chain of callbacks\r\n// whilst still keeping platform and engine independence\r\nstatic void s_feeler_collide_callback(Nx::CollData* p_col_data)\r\n{\r\n\tCFeeler *p_feeler = (CFeeler*) p_col_data->p_callback_data;\r\n\tp_feeler->mp_callback(p_feeler); \r\n}\r\n\r\n// This is the guts, the interface to the lower level collision code\r\nbool\tCFeeler::GetCollision(bool movables, bool bfar)\r\n{\r\n#if PRINT_TIMES\r\n\tstatic uint64 s_total_time = 0, s_num_collisions = 0;\r\n\tuint64 start_time = Tmr::GetTimeInUSeconds();\r\n#endif\r\n\t\r\n #ifdef\t__PLAT_NGPS__\t\t\r\n\t//\tsnProfSetRange( -1, (void*)0, (void*)-1);\r\n\t//\tsnProfSetFlagValue(0x01);\r\n #endif\r\n   \r\n\t\r\n\tMth::Line is;\r\n\r\n\t// just copy over the start and the end of the line directly.\r\n\tis.m_start = m_start;\r\n\tis.m_end = m_end;\r\n\r\n\tm_col_data.p_callback_data = this;\t// callback data is this current feeler\r\n\r\n\t// initialize collision info\r\n\tm_col_data.coll_found = false;\r\n\tm_col_data.trigger = false;\r\n\tm_col_data.script = 0;\t\t\t\t// This is a checksum\r\n\r\n\tm_col_data.mp_callback_object = NULL;\r\n\t\t\t\t\t\t  \r\n\tvoid *callback = 0;\t\t\t\t\t\r\n\tif (mp_callback)\r\n\t{\r\n\t   \tcallback = s_feeler_collide_callback;\r\n\t}\r\n\r\n\tNx::CCollCache *p_cache = (mp_cache) ? mp_cache : sp_default_cache;\r\n\r\n\tbool\tcollision;\r\n\tmp_movable_collision_obj = NULL;\r\n\tm_movable_collision_id = 0;\r\n\tif (bfar)\r\n\t{\r\n\t\tcollision = Nx::CCollObj::sFindFarStaticCollision( is, &m_col_data, callback, p_cache );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcollision = Nx::CCollObj::sFindNearestStaticCollision( is, &m_col_data, callback, p_cache );\r\n\t}\r\n\r\n\t// Now see if we can find a closer movable\r\n\tif (movables)\r\n\t{\r\n\t\tif (bfar)\r\n\t\t{\r\n\t\t\tmp_movable_collision_obj = Nx::CCollObj::sFindFarMovableCollision( is, &m_col_data, callback, p_cache );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_movable_collision_obj = Nx::CCollObj::sFindNearestMovableCollision( is, &m_col_data, callback, p_cache );\r\n\t\t}\r\n\t\tif (mp_movable_collision_obj)\r\n\t\t{\r\n\t\t\tm_movable_collision_id = mp_movable_collision_obj->GetID();\r\n\t\t}\r\n\t}\r\n\r\n\tm_dist = m_col_data.dist;\r\n\tm_point = m_col_data.surface.point;\r\n\tm_normal = m_col_data.surface.normal;\r\n\r\n#if 0\r\n\tif (collision)\r\n\t{\r\n\t\tGfx::AddDebugLine(m_point,m_point + (m_normal * 100.0f),coll_color,10);\r\n\t}\r\n\r\n\t//static int num_print = 1;\r\n\tif (/*collision && (num_print++ % 100) ==*/ 0)\r\n\t{\r\n\t\tDbg_Message(\"\\nStart point (%f, %f, %f)\", m_start[X], m_start[Y], m_start[Z]);\r\n\t\tDbg_Message(\"End point (%f, %f, %f)\", m_end[X], m_end[Y], m_end[Z]);\r\n\r\n\t\tDbg_Message(\"Collision Distance %f\", m_dist);\r\n\t\tDbg_Message(\"Collision point (%f, %f, %f)\", m_point[X], m_point[Y], m_point[Z]);\r\n\t\tDbg_Message(\"Collision normal (%f, %f, %f)\", m_normal[X], m_normal[Y], m_normal[Z]);\r\n\t}\r\n#endif\r\n\r\n\r\n #ifdef\t__PLAT_NGPS__\t\t\r\n\t//\tsnProfSetRange( 4, (void*)NULL, (void*)-1);\r\n #endif\t\t\r\n\r\n#if PRINT_TIMES\r\n\tuint64 end_time = Tmr::GetTimeInUSeconds();\r\n\ts_total_time += end_time - start_time;\r\n\r\n\tif (++s_num_collisions >= 1000)\r\n\t{\r\n\t\tDbg_Message(\"Feeler time %d us\", s_total_time);\r\n\t\ts_total_time = s_num_collisions = 0;\r\n\t}\r\n#endif\r\n\r\n\t\r\n\treturn collision || (mp_movable_collision_obj != NULL);\r\n\r\n\r\n\r\n}\r\n\r\n//\r\n// Just checks the movable collisions\r\n//\r\nbool CFeeler::GetMovableCollision(bool bfar)\r\n{\r\n\tMth::Line is;\r\n\r\n\t// just copy over the start and the end of the line directly.\r\n\tis.m_start = m_start;\r\n\tis.m_end = m_end;\r\n\r\n////////////////////////////////////////////////////////////\r\n// Clear data than might have been set on a previous call\r\n// (change suggested by Andre at LF, 4/28/03)\r\n\tm_col_data.coll_found = false;\r\n\tm_col_data.trigger = false;\r\n\tm_col_data.script = 0;\t\t\t\t// This is a checksum\r\n\tm_col_data.mp_callback_object = NULL;\r\n// End of change\r\n////////////////////////////////////////////////////////////\r\n\r\n\r\n\tm_col_data.p_callback_data = this;\t// callback data is this current feeler\r\n\t\t\t\t\t\t  \r\n\tvoid *callback = 0;\t\t\t\t\t\r\n\tif (mp_callback)\r\n\t{\r\n\t   \tcallback = s_feeler_collide_callback;\r\n\t}\r\n\r\n\tNx::CCollCache *p_cache = (mp_cache) ? mp_cache : sp_default_cache;\r\n\r\n\tif (bfar)\r\n\t{\r\n\t\tmp_movable_collision_obj = Nx::CCollObj::sFindFarMovableCollision( is, &m_col_data, callback, p_cache );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_movable_collision_obj = Nx::CCollObj::sFindNearestMovableCollision( is, &m_col_data, callback, p_cache );\r\n\t}\r\n\t\r\n\tif (mp_movable_collision_obj)\r\n\t{\r\n\t\tm_movable_collision_id = mp_movable_collision_obj->GetID();\r\n\t}\r\n\r\n\tm_dist = m_col_data.dist;\r\n\tm_point = m_col_data.surface.point;\r\n\tm_normal = m_col_data.surface.normal;\r\n\r\n\treturn mp_movable_collision_obj != NULL;\r\n}\r\n\r\n// Check to see that if we have collision, that we have enough data to\r\n// calculate the brightness\r\nbool\tCFeeler::IsBrightnessAvailable()\r\n{\r\n\tif (m_col_data.coll_found)\r\n\t{\r\n\t\tDbg_MsgAssert(m_col_data.p_coll_object, (\"IsBrightnessAvailable(): collision w/o a collsion object\"));\r\n\t\treturn m_col_data.p_coll_object->IsTriangleCollision();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// get the brightness 0.0 .. 1.0 of the point of the last\r\n// collision, based on the RGB values of the triangle, interpolatd to\r\n// the collision point\r\nfloat\tCFeeler::GetBrightness()\r\n{\r\n\tfloat brightness;\r\n\t\r\n\tstruct SGPoint\r\n\t{\r\n\t\tMth::Vector\tp;\r\n\t\tfloat\t\tv;\t\t\t// Brightness in range [0.0, 1.0].\r\n\t};\r\n\r\n\tuint32\ti;\r\n\tSGPoint\tpoint[3];\r\n\r\n\t\r\n\t// If no collision found, set default brightness.\r\n\tif( !m_col_data.coll_found )\r\n\t{\r\n\t\tbrightness = 0.5f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNx::CCollObj*\t\t\t\tp_object\t= m_col_data.p_coll_object;\r\n\t\tconst Nx::SCollSurface*\t\tp_face\t\t= &m_col_data.surface;\r\n\t\tuint32\t\t\t\t\t\tface_index\t= p_face->index;\r\n\t\t//Cld::CCollSector::SFace*\tp_polygon\t= p_object->mp_faces + face_index;\r\n\r\n\t\t// Extract contact point.\r\n\t\tfloat x = p_face->point[X];\r\n\t\tfloat y = p_face->point[Y];\r\n\t\tfloat z = p_face->point[Z];\r\n\r\n\t\tDbg_MsgAssert(p_object->IsTriangleCollision(),(\"Not triangle collision !!!\"));\r\n\r\n\t\tNx::CCollObjTriData *p_tri_data=p_object->GetGeometry();\r\n\t\tDbg_MsgAssert(p_tri_data,(\"NULL p_tri_data\"));\r\n\r\n\t\t// Get all the vertices into a nice simple array of (x,y,z,v).\r\n\t\tfor( i = 0; i < 3; ++i )\r\n\t\t{\r\n\t\t\t//uint16 *vert_idxs = p_object->GetFaceVertIndicies(face_index);\r\n\r\n\t\t\tconst Mth::Vector & vertex = p_object->GetVertexPos(p_tri_data->GetFaceVertIndex(face_index,i));\r\n\r\n\t\t\t// Check that the vertices match.\r\n\t\t\tpoint[i].p.Set( vertex.GetX() - x, vertex.GetY() - y, vertex.GetZ() - z );\r\n\r\n\t\t\t// Here is where the conversion is made from values [0,255] to [0,1].\r\n#ifdef __PLAT_NGC__\r\n\t\t\tpoint[i].v\t= (float)( p_tri_data->GetVertexIntensity(face_index, i)) * ( 1.0f / 255.0f );\r\n#else\r\n\t\t\tpoint[i].v\t= (float)( p_tri_data->GetVertexIntensity(p_tri_data->GetFaceVertIndex(face_index, i)) ) * ( 1.0f / 255.0f );\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t}\r\n\r\n\t\t// Calculate the intersection of the line from Point 0 through the origin, with the line 1-2.\r\n\t\tfloat\t\tmua, mub;\r\n\t\tMth::Line\tline1( point[0].p, Mth::Vector( 0.0f, 0.0f, 0.0f ));\r\n\t\tMth::Line\tline2( point[1].p, point[2].p );\r\n\t\tMth::Vector\ta, b;\r\n\r\n\t\tMth::LineLineIntersect( line1, line2, &a, &b, &mua, &mub, false );\r\n\r\n\t\tfloat l0, l1;\r\n\t\tMth::Vector length;\r\n\r\n\t\t// First interpolation a = i( 1, 2 ).\r\n\t\tlength\t\t\t\t= a - point[1].p;\r\n\t\tl0\t\t\t\t\t= length.Length();\r\n\t\tlength\t\t\t\t= point[2].p - point[1].p;\r\n\t\tl1\t\t\t\t\t= length.Length();\r\n\t\tfloat va\t\t\t= point[1].v + (( point[2].v - point[1].v ) * ( l0 / l1 ));\r\n\r\n\t\t// Second interpolation b = i( 0, a ).\r\n\t\tl0\t\t\t\t\t= point[0].p.Length();\r\n\t\tlength\t\t\t\t= a - point[0].p;\r\n\t\tl1\t\t\t\t\t= length.Length();\r\n\t\tbrightness\t= point[0].v + (( va - point[0].v ) * ( l0 / l1 ));\r\n\t}\r\n\t\r\n#\tifdef __PLAT_XBOX__\r\n\t// Xbox vertex colors run on a different scale to Ps2.\r\n\tbrightness *= 0.5f;\r\n#\tendif\r\n\t\r\n\treturn brightness;\r\n}\r\n\r\n\r\nbool CFeeler::GetCollision(const Mth::Vector &start, const Mth::Vector &end, bool movables)\r\n{\r\n\tSetLine(start,end);\r\n\treturn GetCollision(movables);\r\n}\r\n\r\nbool CFeeler::GetMovableCollision(const Mth::Vector &start, const Mth::Vector &end)\r\n{\r\n\tSetLine(start,end);\r\n\treturn GetMovableCollision();\r\n}\r\n\r\nbool\tCFeeler::IsMovableCollision()\r\n{\r\n\tif (mp_movable_collision_obj.Convert())\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n// if it was movable, and now we have no movable object\r\n// then kill the id and the node name\r\n// so we don't get stung by the snap to ground assuming they are still valid....\r\n\tif (m_movable_collision_id)\r\n\t{\r\n\t\tm_movable_collision_id = 0;\r\n\t\tm_col_data.node_name = 0;\t\t// we are SO like not colliding with anything!\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nObj::CCompositeObject *\t\tCFeeler::GetMovingObject()\t// { return mp_movable_collision_obj;}\r\n{\r\n\treturn mp_movable_collision_obj.Convert();\r\n}\r\n\r\n// if we are in the middle of a callback, then\r\n// we need to look at the callback object\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\nObj::CCompositeObject *\t\tCFeeler::GetCallbackObject() const\r\n{\r\n\treturn m_col_data.mp_callback_object;\r\n}\r\n\r\n\r\nvoid CFeeler::DebugLine(int r, int g, int b, int num_frames)\r\n{\t\r\n\tGfx::AddDebugLine( m_start, m_end, MAKE_RGB( r, g, b ),MAKE_RGB( r,g, b ), num_frames );\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Engine/feeler.h",
    "content": "\r\n#ifndef\t__ENGINE_FEELER_H__\r\n#define\t__ENGINE_FEELER_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/math.h>\r\n\r\n#include <core/math.h>\r\n#include <gfx/debuggfx.h>\r\n#include <core/math/geometry.h>\r\n#include <gel/collision/collision.h>\r\n//#include <sk/objects/movingobject.h>\t\t// needed for smart pointer destructor in feeler, dammit\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/objptr.h>\r\n\r\nnamespace Nx\r\n{\r\n\tclass CCollCache;\r\n}\r\n\r\nclass CFeeler;\r\n\r\ntypedef CFeeler CLineFeeler;\r\n\r\ntypedef\tvoid (*FEELER_CB)(CFeeler*);\t\t// feeler callback\r\n\r\nclass\tCFeeler : public Mth::Line\r\n{\r\npublic:\r\n\tCFeeler();\r\n\tCFeeler(const Mth::Vector &start, const Mth::Vector &end);\r\n\r\n\tvoid \t\t\t\t\t\t\tSetIgnore(uint16 ignore_1, uint16 ignore_0);\r\n\tvoid \t\t\t\t\t\t\tSetLine(const Mth::Vector &start, const Mth::Vector &end);\r\n\tvoid \t\t\t\t\t\t\tSetStart(const Mth::Vector &start);\t\r\n\tvoid \t\t\t\t\t\t\tSetEnd(const Mth::Vector &end);\r\n\r\n\tvoid\t\t\t\t\t\t\tDebugLine(int r=255, int g=255, int b=255, int num_frames = 0);\r\n\t\r\n\tbool\t\t\t\t\t\t\tGetCollision(const Mth::Vector &start, const Mth::Vector &end, bool movables = true);\r\n\tbool\t\t\t\t\t\t\tGetCollision(bool movables = true, bool far = false);\r\n\tinline bool\t\t\t\t\t\tGetFarCollision(bool movables = true) {return GetCollision(movables, true);};\r\n\tbool\t\t\t\t\t\t\tGetMovableCollision(const Mth::Vector &start, const Mth::Vector &end);\r\n\tbool\t\t\t\t\t\t\tGetMovableCollision(bool far = false);\r\n\tinline bool\t\t\t\t\t\tGetFarMovableCollision() {return GetMovableCollision(true);};\r\n\tbool\t\t\t\t\t\t\tIsBrightnessAvailable();\r\n\tfloat\t\t\t\t\t\t\tGetBrightness();\r\n\t\r\n\tfloat\t\t\t\t\t\t\tGetDist() const;\r\n\tconst Mth::Vector\t\t\t&\tGetPoint() const;\r\n\tconst Mth::Vector\t\t\t&\tGetNormal() const;\r\n\tint\t\t\t\t\t\t\t\tGetFaceIndex() const;\r\n\t\r\n\tvoid \t\t\t\t\t\t\tSetCallback(FEELER_CB p_callback);\r\n\tvoid \t\t\t\t\t\t\tSetCallbackData(void *p_callback_data);\r\n\tvoid * \t\t\t\t\t\t\tGetCallbackData() const;\r\n\r\n\tvoid\t\t\t\t\t\t\tSetCache(Nx::CCollCache *p_cache);\r\n\tvoid\t\t\t\t\t\t\tClearCache();\r\n\r\n\tuint16 \t\t\t\t\t\t\tGetFlags() const;\r\n\tETerrainType \t\t\t\t\tGetTerrain() const;\r\n\tbool\t\t\t\t\t\t\tIsMovableCollision(); \r\n\tNx::CCollObj *\t \t\t\t\tGetSector() const;\t\t// aieee!!!!!!\r\n\tObj::CCompositeObject *\t\t\tGetMovingObject();\r\n\tObj::CCompositeObject *\t\t\tGetCallbackObject() const;\r\n\tbool \t\t\t\t\t\t\tGetTrigger() const;\r\n\tuint32 \t\t\t\t\t\t\tGetNodeChecksum() const;\r\n\tuint32 \t\t\t\t\t\t\tGetScript() const;\r\n\tvoid \t\t\t\t\t\t\tSetScript(uint32 script);\r\n\tvoid \t\t\t\t\t\t\tSetTrigger(bool trigger);\r\n\r\n\tstatic void\t\t\t\t\t\tsSetDefaultCache(Nx::CCollCache *p_cache);\r\n\tstatic void\t\t\t\t\t\tsClearDefaultCache();\r\n\r\n\t// feeler callback probably should not be public\t\t\t\t\t\t   \r\n\tFEELER_CB\t\t\tmp_callback;\t   // a callback called every frame\r\n\t\t\t\t\t\t   \r\nprivate:\r\n\tvoid\t\t\t\t\t\t\tinit (   );\r\n\t\r\n// for now, our implmentation will just copy over the relevent things from rw\t\t\r\n// as needed\r\n// keep m_col_data private, and eventually we can get rid of it\t\r\n\tNx::CollData \t\tm_col_data;\t \t\t\t// \r\n\tfloat\t\t\t\tm_dist;\r\n\tMth::Vector\t\t\tm_point;\r\n\tMth::Vector\t\t\tm_normal;\r\n\r\n\tObj::CSmtPtr<Obj::CCompositeObject> mp_movable_collision_obj;\t//  set if last collision was with a movable\r\n\tuint32 \t\t\t\tm_movable_collision_id;\t\t// id of this object, so we can check if it is dead.\r\n\t\r\n\tvoid \t\t*\t\tmp_callback_data;\t\t// \tpointer to some data the callback can use\r\n\r\n\tNx::CCollCache *\tmp_cache;\r\n\r\n\tstatic Nx::CCollCache *\tsp_default_cache;\r\n};\r\n\r\ninline float\tCFeeler::GetDist() const\r\n{\r\n\treturn m_dist;\r\n}\r\n\r\ninline const Mth::Vector &CFeeler::GetPoint() const\r\n{\r\n\treturn m_point;\r\n}\r\n\r\ninline const Mth::Vector &CFeeler::GetNormal() const\r\n{\r\n\treturn m_normal;\r\n}\r\n\r\ninline int\t\tCFeeler::GetFaceIndex() const\r\n{\r\n\treturn m_col_data.surface.index;\r\n}\r\n\r\ninline uint16\tCFeeler::GetFlags() const\r\n{\r\n\treturn m_col_data.flags;\r\n}\r\n\r\ninline ETerrainType CFeeler::GetTerrain() const\r\n{\r\n\treturn m_col_data.terrain;\r\n}\r\n\r\ninline Nx::CCollObj* CFeeler::GetSector() const // aieee!!!!!!\r\n{\r\n\treturn m_col_data.p_coll_object;\r\n}\r\n\r\ninline bool\t\tCFeeler::GetTrigger() const\r\n{\r\n\treturn m_col_data.trigger;\r\n}\r\n\r\ninline uint32\tCFeeler::GetNodeChecksum() const\r\n{\r\n\treturn m_col_data.node_name;\r\n}\r\n\r\ninline uint32\tCFeeler::GetScript() const\r\n{\r\n\treturn m_col_data.script;\t\r\n}\r\n\r\ninline void\t\tCFeeler::SetScript(uint32 script)\r\n{\r\n\tm_col_data.script = script; \r\n}\r\n\r\ninline void\t\tCFeeler::SetTrigger(bool trigger)\r\n{\r\n\tm_col_data.trigger = trigger; \r\n}\r\n\r\ninline void\t\tCFeeler::SetCallback(FEELER_CB p_callback)\r\n{\r\n\tmp_callback = p_callback;\r\n}\r\n\r\ninline void\t\tCFeeler::SetCallbackData(void *p_callback_data)\r\n{\r\n\tmp_callback_data = p_callback_data;\r\n}\r\n\r\ninline void *\t\tCFeeler::GetCallbackData() const\r\n{\r\n\treturn mp_callback_data;\r\n}\r\n\r\ninline void\t\tCFeeler::SetCache(Nx::CCollCache *p_cache)\r\n{\r\n\tmp_cache = p_cache;\r\n}\r\n\r\ninline void\t\tCFeeler::ClearCache()\r\n{\r\n\tmp_cache = NULL;\r\n}\r\n\r\ninline void\t\tCFeeler::sSetDefaultCache(Nx::CCollCache *p_cache)\r\n{\r\n\tsp_default_cache = p_cache;\r\n}\r\n\r\ninline void\t\tCFeeler::sClearDefaultCache()\r\n{\r\n\tsp_default_cache = NULL;\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Engine/sounds.cpp",
    "content": "/*\r\n\tThis is just a database for arrays of skater sounds on different terrains.\r\n\t\r\n\tFor each type of sound in sounds.h (like grind, land, slide, wheel roll, etc...)\r\n\tthere is an array of sounds to play, one for each possible terrain type.\r\n\t\r\n\tA terrain type of zero indicates that the sound is the default (for surfaces not\r\n\tdefined in the list).\r\n*/\r\n\r\n\r\n#include <string.h>\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/scripting/checksum.h>\r\n\t\t\t\t\t\t   \r\n#include <engine/sounds.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sys/config/config.h>\r\n#include <sys/replay/replay.h>\r\n\r\n\r\n\r\nnamespace Sk3Sfx\r\n{\r\n\r\n\r\n\r\nDefineSingletonClass( CSk3SfxManager, \"Sk3 Sound FX\" );\r\n\r\nCSk3SfxManager::CSk3SfxManager( void )\r\n{\r\n\t\r\n\tReset( );\r\n}\r\n\r\nCSk3SfxManager::~CSk3SfxManager( void )\r\n{\r\n\t\r\n}\r\n\r\nvoid CSk3SfxManager::Reset( void )\r\n{\r\n\t\r\n\tint i;\r\n\tfor ( i = 0; i < vNUM_SOUND_TYPES; i++ )\r\n\t{\r\n\t\tmNumEntries[ i ] = 0;\r\n\t}\r\n} // end of Reset( )\r\n\r\n// Sound FX for the level...\r\n/*\tThe surface flag indicates which surface the skater is currently on (grass, cement, wood, metal)\r\n\twhichSound is the checksum from the name of the looping sound (should be loaded using LoadSound\r\n\t\tin the script file for each level)\r\n\twhichArray indicates whether this sound belongs in the list of wheels rolling sounds, or\r\n\t\tgrinding sounds, etc...\r\n*/\r\nvoid CSk3SfxManager::SetSkaterSoundInfo( int surfaceFlag, uint32 whichSound, int whichArray,\r\n\tfloat maxPitch, float minPitch, float maxVol, float minVol )\r\n{\r\n\t\r\n\tif (Sfx::NoSoundPlease()) return;\r\n\t\r\n\t// must initialize PInfo!\r\n\tint i;\r\n\tSfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();\r\n\r\n\tif ( NULL == sfx_manager->GetWaveTableIndex( whichSound ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Terrain sound not loaded! surface %d sound %s checksum %d soundType %d\",\r\n\t\t\tsurfaceFlag, Script::FindChecksumName( whichSound ), whichSound, whichArray ));\r\n\t\treturn;\r\n\t}\r\n\tint numEntries = mNumEntries[ whichArray ];\r\n\tSkaterSoundInfo\t*pArray = mSoundArray[ whichArray ];\r\n\tSkaterSoundInfo *pInfo = NULL;\r\n\t\r\n\tfor ( i = 0; i < numEntries; i++ )\r\n\t{\r\n\t\tif ( pArray[ i ].surfaceFlag == surfaceFlag )\r\n\t\t{\r\n\t\t\tDbg_Message( \"Re-defining soundtype %d for surfaceFlag %d\", whichArray, surfaceFlag );\r\n\t\t\tpInfo = &pArray[ i ];\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif ( !pInfo )\r\n\t{\r\n\t\tpInfo = &pArray[ mNumEntries[ whichArray ] ];\r\n\t\tmNumEntries[ whichArray ] += 1;\r\n\t\tDbg_MsgAssert( mNumEntries[ whichArray ] < vMAX_NUM_ENTRIES,( \"Array too small type %d.  Increase MAX_NUM_ENTRIES.\", whichArray ));\r\n\t}\r\n\t\r\n\tDbg_MsgAssert( pInfo,( \"Please fire Matt immediately after kicking him in the nuts.\" ));\r\n\t\r\n\t// surfaceFlag of zero will be used for the default\r\n\tpInfo->surfaceFlag = surfaceFlag;\r\n\t// if soundChecksum is zero, no sound will play on this surface.\r\n\tpInfo->soundChecksum = whichSound;\r\n\tpInfo->maxPitch = maxPitch;\r\n\tpInfo->minPitch = minPitch;\r\n\tpInfo->maxVol = maxVol;\r\n\tpInfo->minVol = minVol;\r\n\r\n} // end of SetSkaterSoundInfo( )\r\n\r\nSkaterSoundInfo\t*CSk3SfxManager::GetSkaterSoundInfo( int surfaceFlag, int whichArray )\r\n{\r\n\t\r\n\tif (Sfx::NoSoundPlease()) return NULL;\r\n\t\r\n\t\r\n\tint numEntries = 0;\r\n\tnumEntries = mNumEntries[ whichArray ];\r\n\tSkaterSoundInfo\t*pArray = mSoundArray[ whichArray ];\r\n\tDbg_MsgAssert( pArray,( \"Fire Matt please.\" ));\r\n\tint i;\r\n\tfor ( i = 0; i < numEntries; i++ )\r\n\t{\r\n\t\tif ( pArray[ i ].surfaceFlag == surfaceFlag )\r\n\t\t{\r\n\t\t\treturn ( &pArray[ i ] );\r\n\t\t}\r\n\t}\r\n\t// couldn't find the surface flag in the table... return the default:\r\n\tfor ( i = 0; i < numEntries; i++ )\r\n\t{\r\n\t\tif ( !pArray[ i ].surfaceFlag )\r\n\t\t{\r\n\t\t\treturn ( &pArray[ i ] );\r\n\t\t}\r\n\t}\r\n\r\n\treturn ( NULL );\r\n} // end of GetSkaterSoundInfo( )\r\n\r\nvoid CSk3SfxManager::PlaySound( int whichArray, int surfaceFlag, const Mth::Vector &pos, float volPercent,\r\n\t\t\t\t\t\t\t\tbool propogate )\r\n{\r\n\tif (Sfx::NoSoundPlease()) return;\r\n\t\r\n\r\n\tReplay::WriteSkaterSoundEffect(whichArray,surfaceFlag,pos,volPercent);\r\n\t\r\n\tSfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();\r\n\tGameNet::Manager * gamenet_manager = GameNet::Manager::Instance();\r\n    \r\n\tSkaterSoundInfo\t*pInfo = GetSkaterSoundInfo( surfaceFlag, whichArray );\r\n\tif ( !pInfo )\r\n\t{\r\n\t\t// no sounds are supposed to be played for this surface on this transition:\r\n\t\treturn;\r\n\t}\r\n\r\n\tif( propogate )\r\n\t{\r\n\t\tNet::Client* client;\r\n\t\tGameNet::MsgPlaySound msg;\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tclient = gamenet_manager->GetClient( 0 );\r\n\t\tDbg_Assert( client );\r\n\r\n\t\tmsg.m_WhichArray = (char) whichArray;\r\n\t\tmsg.m_SurfaceFlag = (char) surfaceFlag;\r\n\t\tmsg.m_Pos[0] = (short) pos[X];\r\n\t\tmsg.m_Pos[1] = (short) pos[Y];\r\n\t\tmsg.m_Pos[2] = (short) pos[Z];\r\n\t\tmsg.m_VolPercent = (char) volPercent;\r\n\r\n\t\tmsg_desc.m_Data = &msg;\r\n\t\tmsg_desc.m_Length = sizeof( GameNet::MsgPlaySound );\r\n\t\tmsg_desc.m_Id = GameNet::MSG_ID_PLAY_SOUND;\r\n\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t}\r\n\r\n//\tfloat volL, volR;\r\n\tSfx::sVolume vol;\r\n//\tsfx_manager->SetVolumeFromPos( &volL, &volR, pos, sfx_manager->GetDropoffDist( pInfo->soundChecksum ) );\r\n\tsfx_manager->SetVolumeFromPos( &vol, pos, sfx_manager->GetDropoffDist( pInfo->soundChecksum ));\r\n\r\n\t// Adjust volume according to speed.\r\n\tvolPercent = GetVolPercent( pInfo, volPercent );\r\n//\tvolL = PERCENT( volL, volPercent );\r\n//\tvolR = PERCENT( volR, volPercent );\r\n\tvol.PercentageAdjustment( volPercent );\r\n\r\n//\tsfx_manager->PlaySound( pInfo->soundChecksum, volL, volR );\r\n\tsfx_manager->PlaySound( pInfo->soundChecksum, &vol );\r\n}\r\n\r\n// set the volume according to the range specified by the designers...\r\nfloat CSk3SfxManager::GetVolPercent( SkaterSoundInfo *pInfo, float volPercent, bool clipToMaxVol )\r\n{\r\n\t\r\n\tDbg_MsgAssert( pInfo,(( \"Fire whoever called this function with this nonsense.\" )));\r\n\tif ( !( ( pInfo->minVol == 0.0f ) && ( pInfo->maxVol == 100.0f ) ) )\r\n\t{\r\n\t\tvolPercent = ( pInfo->minVol + PERCENT( ( pInfo->maxVol - pInfo->minVol ), volPercent ) );\r\n\t}\r\n\t\r\n\tif ( clipToMaxVol )\r\n\t{\r\n\t\tif ( volPercent > pInfo->maxVol )\r\n\t\t\tvolPercent = pInfo->maxVol;\r\n\t}\r\n\treturn ( volPercent );\r\n}\r\n\r\n} // namespace sfx\r\n"
  },
  {
    "path": "Code/Sk/Engine/sounds.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSkate Module (SKATE) \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsk/engine/sounds.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\tMatt Jan. 2001\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tLists of soundFX for terrains, etc...\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GEL_SK_SOUNDS_H\r\n#define __GEL_SK_SOUNDS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/list.h>\r\n#include <core/macros.h>\r\n\r\nnamespace Sk3Sfx\r\n{\r\n\r\n\r\n\r\n\r\nstruct SkaterSoundInfo\r\n{\r\n\tint\t\tsurfaceFlag;\r\n\tuint32\tsoundChecksum;\r\n\tfloat\t\tmaxPitch;\r\n\tfloat\t\tminPitch;\r\n\tfloat\t\tmaxVol;\r\n\tfloat\t\tminVol;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  CSk3SfxManager  : public Spt::Class\r\n{\r\n\t\r\n\tDeclareSingletonClass( CSk3SfxManager );\r\n\r\npublic:\r\n\t// these sound trigger values are also used to\r\n\t// communicate with the sounds.cpp module and scripted\r\n\t// soundfx for jumping/landing... if changed please\r\n\t// change skater_sfx.q also:\r\n\tenum\r\n\t{\r\n\t\tvTABLE_WHEELROLL,\r\n\t\tvTABLE_GRIND, // on a rail...\r\n\t\tvTABLE_JUMP,\r\n\t\tvTABLE_LAND,\r\n\t\tvTABLE_BONK,\r\n\t\tvTABLE_GRINDJUMP,\r\n\t\tvTABLE_GRINDLAND,\r\n\t\tvTABLE_SLIDE, // on a rail\r\n\t\tvTABLE_SLIDEJUMP,\r\n\t\tvTABLE_SLIDELAND,\r\n\t\tvTABLE_CESS,\r\n\t\tvNUM_SOUND_TYPES,\r\n\t};\r\n\t\r\n\tCSk3SfxManager::CSk3SfxManager( void );\r\n\tCSk3SfxManager::~CSk3SfxManager( void );\r\n\r\n\tvoid\t\t\tReset( void );\r\n\tvoid\t\t\tSetSkaterSoundInfo( int surfaceFlag, uint32 whichSound,\r\n\t\t\t\t\t\t\t\t\tint whichArray, float maxPitch, float minPitch, float maxVol, float minVol );\r\n\tSkaterSoundInfo\t*GetSkaterSoundInfo( int surfaceFlag, int whichArray );\r\n\r\n\tfloat\t\t\tGetVolPercent( SkaterSoundInfo *pInfo, float volPercent, bool clipToMaxVol = false );\r\n\r\n\tvoid \t\t\tPlaySound( int whichArray, int surfaceFlag, const Mth::Vector &pos, float volPercent,\r\n\t\t\t\t\t\t\t   bool propogate = true );\r\n\r\nprivate:\r\n\t\r\n\tenum\r\n\t{\r\n\t\tvMAX_NUM_ENTRIES  = 64,\r\n\t};\r\n\r\n\tint mNumEntries[ vNUM_SOUND_TYPES ];\r\n\tSkaterSoundInfo mSoundArray[ vNUM_SOUND_TYPES ][ vMAX_NUM_ENTRIES ];\r\n};\r\n\r\n}  // namespace Sfx\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/GameNet/ExportMsg.h",
    "content": "#ifndef __ENGINE_EXPORTMSG_H__\r\n#define\t__ENGINE_EXPORTMSG_H__\r\n\r\n#include <core/defines.h>\r\n\r\nnamespace Net\r\n{\r\n\r\n#define\tvSERVER_IP_VARIABLE\t\"VIEWER_IP\"\r\n#define vXBOX_SERVER_IP_VARIABLE \"XBOX_VIEWER_IP\"\r\n#define vNGC_SERVER_IP_VARIABLE \"NGC_VIEWER_IP\"\r\n\r\nenum\r\n{\r\n\tvEXPORT_COMM_PORT = 10000,\r\n};\t\r\n\r\nenum\r\n{\t\r\n\tvMSG_ID_QUICKVIEW\t\t= 32,\t//\t32 is the first available user-defined message id\r\n\tvMSG_ID_UPDATE_MATERIAL,\t\t//\tNew material properties\r\n\tvMSG_ID_REMOTE_Q,\r\n\tvMSG_ID_VIEWOBJ_LOAD_MODEL,\r\n\tvMSG_ID_VIEWOBJ_UNLOAD_MODEL,\r\n\tvMSG_ID_VIEWOBJ_SET_ANIM,\r\n\tvMSG_ID_VIEWOBJ_SET_ANIM_SPEED,\r\n\tvMSG_ID_VIEWOBJ_INCREMENT_FRAME,\r\n\tvMSG_ID_VIEWOBJ_SET_ANIM_FILE,\r\n\tvMSG_ID_VIEWOBJ_SET_CAMANIM_FILE,\r\n\tvMSG_ID_INCREMENTAL_UPDATE,\r\n\tvMSG_ID_RUN_SCRIPT_COMMAND,\r\n\tvMSG_ID_VIEWOBJ_PREVIEW_SEQUENCE,\r\n};\r\n\r\nclass MsgViewObjLoadModel\r\n{\r\npublic:\r\n\tchar\tm_ModelName[128];\r\n\tuint32\tm_AnimScriptName;\r\n\tuint32\tm_SkeletonName;\r\n};\r\n\r\nclass MsgViewObjSetAnimSpeed\r\n{\r\npublic:\r\n\tfloat\tm_AnimSpeed;\r\n};\r\n\r\nclass MsgViewObjSetAnim\r\n{\r\npublic:\r\n\tuint32\tm_AnimName;\r\n};\r\n\r\nclass MsgViewObjIncrementFrame\r\n{\r\npublic:\r\n\tbool\tm_Forwards;\r\n};\t\t\t\t   \r\n\r\nclass MsgViewObjSetAnimFile\r\n{\r\npublic:\r\n\tchar    m_Filename[128];\r\n\tuint32  m_checksum;\r\n};\r\n\r\nclass MsgViewObjSetCamAnimFile\r\n{\r\npublic:\r\n\tchar    m_Filename[128];\r\n\tuint32  m_checksum;\r\n};\r\n\r\nclass MsgQuickview\r\n{\r\npublic:\r\n\tchar\tm_Filename[128];\r\n\tchar\tm_UpdateFilename[128];\r\n};\r\n\r\nclass MsgMaterialUpdate\r\n{\r\npublic:\r\n\tunsigned long\tMaterialChecksum;\r\n\tint\t\t\t\tm_BlendMode;\r\n\tint\t\t\t\tm_FixedAlpha;\r\n\tint\t\t\t\tm_MappingMode;\t\t// Explicit or procedural (eg. environment-mapping)\t\r\n\tint\t\t\t\tm_MinFilteringMode;\t// Point/Bi-linear\r\n\tint\t\t\t\tm_MagFilteringMode;\t// Point/Bi-linear/Tri-linear\r\n\tbool\t\t\tm_UVWibbleEnabled;\t\t\r\n\tfloat\t\t\tm_UVel;\r\n\tfloat\t\t\tm_VVel;\t\r\n\tfloat\t\t\tm_UAmplitude;\r\n\tfloat\t\t\tm_VAmplitude;\r\n\tfloat\t\t\tm_UPhase;\r\n\tfloat\t\t\tm_VPhase;\r\n\tfloat\t\t\tm_UFrequency;\r\n\tfloat\t\t\tm_VFrequency;\r\n\tfloat\t\t\tm_MipMapK;\r\n\tint\t\t\t\tm_MipMapL;\t\r\n};\r\n\r\n}\r\n#endif\t// __ENGINE_EXPORTMSG_H__"
  },
  {
    "path": "Code/Sk/GameNet/GameHandler.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tGameHandler.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t08/09/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGame-Side Network Handlers\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <sys/mcman.h>\r\n#include <sys/SIO/keyboard.h>\r\n\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/mainloop.h>\r\n\r\n#include <gfx/vecfont.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/parkeditor2/edmap.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/modules/frontend/frontend.h>\r\n\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/objects/proxim.h>\r\n#include <sk/objects/crown.h>\r\n\r\n#include <sk/components/skaterscorecomponent.h>\r\n#include <sk/components/GoalEditorComponent.h>\r\n#include <sk/components/RailEditorComponent.h>\r\n\r\n#include <sk/scripting/cfuncs.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <sk/objects/skater.h>\t\t   // \t various high level network game things\r\n\r\n#ifdef __PLAT_NGPS__\r\n#include <sk/gamenet/ngps/p_buddy.h>\r\n#include <sk/gamenet/lobby.h>\r\n#include <sk/gamenet/ngps/p_stats.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define vTIME_BEFORE_CHANGING_LEVEL\t\tTmr::Seconds( 3 )\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic Tmr::Time\ts_time_change_level;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Handler Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/* The server has told us to create a new skater and associate it */\r\n/* with a player                                                  */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_new_player( Net::MsgHandlerContext* context )\r\n{\r\n\tMsgNewPlayer* msg;\r\n\tManager* gamenet_man;\r\n\t\r\n\tmsg = (MsgNewPlayer *) context->m_Msg;\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\r\n\tNewPlayerInfo new_player;\r\n\r\n\tstrcpy( new_player.Name, msg->m_Name );\r\n\tnew_player.ObjID = msg->m_ObjId;\r\n\tnew_player.Conn = NULL;\r\n\tnew_player.Flags = msg->m_Flags;\r\n\tnew_player.Team = msg->m_Team;\r\n\tnew_player.Profile = msg->m_Profile;\r\n\tnew_player.Rating = msg->m_Rating;\r\n\tnew_player.Score = msg->m_Score;\r\n\tnew_player.VehicleControlType = msg->m_VehicleControlType;\r\n\r\n\tif( new_player.Flags & PlayerInfo::mLOCAL_PLAYER )\r\n\t{\r\n\t\tDbg_Message( \"(%d) Got local new player with ID %d!\\n\", context->m_App->m_FrameCounter,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmsg->m_ObjId );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Message( \"(%d) Got new player with ID %d!\\n\", context->m_App->m_FrameCounter,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmsg->m_ObjId );\r\n\t}\r\n\r\n\t// Observers and local players do not receive their own appearance data\r\n\tif( !( new_player.Flags & ( PlayerInfo::mOBSERVER | PlayerInfo::mLOCAL_PLAYER )))\r\n\t{\r\n\t\t// GJ:  the appearance is transmitted inside the message,\r\n\t\t// so copy it to the \"new_player\" structure\r\n\t\tnew_player.mpSkaterProfile->ReadFromBuffer( msg->m_AppearanceData );\r\n\t}\r\n\t\r\n\t// If this is all part of our join packet, just load players immediately instead of deferring it\r\n\tif( gamenet_man->ReadyToPlay() == false )\r\n\t{\r\n\t\tDbg_Printf( \"Calling DeferredNewPlayer with no wait\\n\" );\r\n\t\tgamenet_man->DeferredNewPlayer( &new_player, 0 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgamenet_man->CreateNetPanelMessage( false, Script::GenerateCRC(\"net_message_new_player\"), \r\n\t\t\t\t\t\t\t\t\t\t\tnew_player.Name );\r\n\r\n\t\tgamenet_man->DeferredNewPlayer( &new_player );\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_wait_n_seconds( Net::MsgHandlerContext* context )\r\n{\r\n\tchar *num_seconds = (char*) context->m_Msg;\r\n\r\n\tcontext->m_Conn->UpdateCommTime( Tmr::Seconds( *num_seconds ));\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_player_info_ack_req( Net::MsgHandlerContext* context )\r\n{\r\n\tMsgIntInfo* msg;\r\n\tManager* gamenet_man;\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tNet::MsgDesc msg_desc;\r\n\tint i;\r\n\r\n\tDbg_Printf( \"Handling PlayerInfo ack request\\n\" );\r\n\t// At this point, we've received the batch of player info's representing the players\r\n\t// that were in the game at the time of our join. Advance our state machine\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\r\n\tgamenet_man->SetJoinState( GameNet::vJOIN_STATE_GOT_PLAYERS );\r\n    \r\n\tmsg = (MsgIntInfo*) context->m_Msg;\r\n\r\n\tmsg_desc.m_Id = MSG_ID_PLAYER_INFO_ACK;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\r\n\tcontext->m_App->EnqueueMessageToServer( &msg_desc );\r\n\r\n\tif( !gamenet_man->OnServer())\r\n\t{\r\n\t\tfor( i = 0; i < 2; i++ )\r\n\t\t{\r\n\t\t\tNet::Client* client;\r\n\t\r\n\t\t\tif(( client = gamenet_man->GetClient( i )))\r\n\t\t\t{\r\n\t\t\t\tskate_mod->AddNetworkMsgHandlers( client, i );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n                                                            \r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_player_info_ack( Net::MsgHandlerContext* context )\r\n{   \r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tPlayerInfo* player;\r\n\tManager* gamenet_man;\r\n\r\n\tgamenet_man = (Manager*) context->m_Data;\r\n\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tif( player )\r\n\t{\r\n\t\t// tell them what level to load\r\n\t\tif( !( player->m_flags.TestMask( PlayerInfo::mHAS_PLAYER_INFO )))\r\n\t\t{\r\n\t\t\tLst::Search< TriggerEvent > trigger_sh;\r\n\t\t\tTriggerEvent* trigger;\r\n\t\t\tMsgStartInfo start_info_msg;\r\n\t\t\tNet::MsgDesc start_desc;\r\n\t\t\tPlayerInfo* king;\r\n\t\t\tMsgReady ready_msg;\r\n\t\t\r\n\t\t\tready_msg.m_Time = Tmr::GetTime();\r\n\t\r\n\t\t\tplayer->m_flags.SetMask( PlayerInfo::mHAS_PLAYER_INFO );\r\n\t\t\t\r\n\t\t\tstart_info_msg.m_MaxPlayers = gamenet_man->GetMaxPlayers();\r\n\t\t\tif( player->IsLocalPlayer())\r\n\t\t\t{\r\n\t\t\t\tgamenet_man->SetReadyToPlay(true);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// If the game is over, just tell the client to join in net_lobby mode\r\n\t\t\t\tif( gamenet_man->GameIsOver())\r\n\t\t\t\t{\r\n\t\t\t\t\tstart_info_msg.m_GameMode = Script::GenerateCRC( \"netlobby\" );\r\n\t\t\t\t\tstart_info_msg.m_TimeLeft = 0;\r\n\t\t\t\t\tstart_info_msg.m_TimeLimit = 0;\r\n\t\t\t\t\tstart_info_msg.m_TargetScore = 0;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tstart_info_msg.m_GameMode = skate_mod->GetGameMode()->GetNameChecksum();\r\n\t\t\t\t\tstart_info_msg.m_TimeLeft = Tmr::InSeconds( skate_mod->GetGameMode()->GetTimeLeft());\r\n\t\t\t\t\t//start_info_msg.m_TimeLimit = gamenet_man->m_network_preferences.GetPreferenceValue( Script::GenerateCRC(\"time_limit\"), Script::GenerateCRC(\"time\") );\r\n\t\t\t\t\tstart_info_msg.m_TimeLimit = skate_mod->GetGameMode()->GetTimeLimit();\r\n\t\t\t\t\tstart_info_msg.m_TargetScore = gamenet_man->m_network_preferences.GetPreferenceValue( Script::GenerateCRC(\"target_score\"), Script::GenerateCRC(\"score\") );\r\n\t\t\t\t}\r\n\t\t\t\tstart_info_msg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\t\t\t\tstart_info_msg.m_LevelId = gamenet_man->GetNetworkLevelId();\r\n\t\t\t\tstart_info_msg.m_TeamMode = skate_mod->GetGameMode()->NumTeams();\r\n\t\t\t\tstart_info_msg.m_CrownSpawnPoint = gamenet_man->m_crown_spawn_point;\r\n\t\t\t\tstart_info_msg.m_ProSetFlags = gamenet_man->m_proset_flags;\r\n\t\t\t\tmemcpy( start_info_msg.m_StartPoints, gamenet_man->m_skater_starting_points, \r\n\t\t\t\t\t\tMdl::Skate::vMAX_SKATERS * sizeof( int ));\r\n\t\t\t\tif( net_man->GetConnectionType() == Net::vCONN_TYPE_MODEM )\r\n\t\t\t\t{\r\n\t\t\t\t\tstart_info_msg.m_Broadband = 0;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tstart_info_msg.m_Broadband = 1;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tstart_desc.m_Data = &start_info_msg;\r\n\t\t\t\tstart_desc.m_Length = sizeof( MsgStartInfo );\r\n\t\t\t\tstart_desc.m_Id = MSG_ID_START_INFO;\r\n\t\t\t\tstart_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\tstart_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\tgamenet_man->m_server->EnqueueMessage( \tplayer->GetConnHandle(), &start_desc );\r\n\r\n\t\t\t\tif( gamenet_man->UsingCreatedGoals())\r\n\t\t\t\t{\r\n\t\t\t\t\tgamenet_man->LoadGoals( gamenet_man->GetNetworkLevelId());\r\n\t\t\t\t\tgamenet_man->m_server->StreamMessage( player->GetConnHandle(), MSG_ID_GOALS_DATA, gamenet_man->GetGoalsDataSize(), \r\n\t\t\t\t\t\t\t\t\t\t\t\t gamenet_man->GetGoalsData(), \"goals data\", vSEQ_GROUP_PLAYER_MSGS,\r\n\t\t\t\t\t\t\t\t\t\t\t\t false, true );\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// tell them to execute the queue of scripts\r\n\t\t\t\tfor( trigger = trigger_sh.FirstItem( gamenet_man->m_trigger_events ); trigger; \r\n\t\t\t\t\t\ttrigger = trigger_sh.NextItem())\r\n\t\t\t\t{\r\n\t\t\t\t\tMsgSpawnAndRunScript script_msg;\r\n\t\t\t\t\tNet::MsgDesc script_desc;\r\n\t\r\n\t\t\t\t\tscript_msg.m_Node = trigger->m_Node;\r\n\t\t\t\t\tscript_msg.m_ObjID = trigger->m_ObjID;\r\n\t\t\t\t\tscript_msg.m_ScriptName = trigger->m_Script;\r\n\t\t\t\t\tscript_msg.m_Permanent = 0;\r\n\t\r\n\t\t\t\t\tscript_desc.m_Data = &script_msg;\r\n\t\t\t\t\tscript_desc.m_Length = sizeof( MsgSpawnAndRunScript );\r\n\t\t\t\t\tscript_desc.m_Id = MSG_ID_SPAWN_AND_RUN_SCRIPT;\r\n\t\t\t\t\tscript_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\tscript_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\t\tgamenet_man->m_server->EnqueueMessage( \tplayer->GetConnHandle(), &script_desc );\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tif( player->IsLocalPlayer() == false )\r\n\t\t\t\t{\r\n\t\t\t\t\tskate_mod->SendCheatList( player );\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Update the observers with graffiti status\r\n\t\t\t\tif( player->IsObserving())\r\n\t\t\t\t{\r\n\t\t\t\t\tif( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netgraffiti\" ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMsgInitGraffitiState init_graffiti_state_msg;\r\n\t\t\t\t\t\tNet::MsgDesc obs_msg_desc;\r\n\t\t\t\t\t\tuint32 msg_size = skate_mod->GetTrickObjectManager()->SetInitGraffitiStateMessage( &init_graffiti_state_msg );\r\n\t\t\t\t\t\tDbg_Printf( \"Sending graffiti state message %d\\n\", msg_size );\r\n\t\t\r\n\t\t\t\t\t\tobs_msg_desc.m_Data = &init_graffiti_state_msg;\r\n\t\t\t\t\t\tobs_msg_desc.m_Length = msg_size;\r\n\t\t\t\t\t\tobs_msg_desc.m_Id = MSG_ID_OBSERVER_INIT_GRAFFITI_STATE;\r\n\t\t\t\t\t\tobs_msg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\t\tobs_msg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\r\n\t\t\t\t\t\tgamenet_man->m_server->StreamMessage( player->GetConnHandle(), obs_msg_desc.m_Id, obs_msg_desc.m_Length, \r\n\t\t\t\t\t\t   obs_msg_desc.m_Data, \"TrickObj Buffer\", GameNet::vSEQ_GROUP_PLAYER_MSGS );\r\n\t\t\t\t\t\t//gamenet_man->m_server->EnqueueMessage( \tplayer->GetConnHandle(), &obs_msg_desc );\r\n                        \r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t// Compile the list of selected goals to send to the client\r\n\t\t\t\t{\r\n\t\t\t\t\tint i, num_goals;\r\n\t\t\t\t\tGame::CGoalManager* pGoalManager;\r\n\t\t\t\t\tGame::CGoal* pGoal;\r\n\t\t\t\t\tNet::MsgMax msg;\r\n\t\t\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\t\t\tuint32 goal_id;\r\n\t\t\t\t\tchar* data;\r\n\t\t\t\t\t \r\n\t\t\t\t\tpGoalManager = Game::GetGoalManager();\r\n\t\t\t\r\n\t\t\t\t\tdata = msg.m_Data;\r\n\t\t\t\t\t*data++ = 0;\t// This indicates that they should not bring up the goal summary dialog\r\n\t\t\t\t\tnum_goals = pGoalManager->GetNumGoals();\r\n\t\t\t\t\tfor( i = 0; i < num_goals; i++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpGoal = pGoalManager->GetGoalByIndex( i );\r\n\t\t\t\t\t\tDbg_Assert( pGoal );\r\n\t\t\t\t\t\tif( pGoal->IsSelected())\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tgoal_id = pGoal->GetGoalId();\r\n\t\t\t\t\t\t\tmemcpy( data, &goal_id, sizeof( uint32 ));\r\n\t\t\t\t\t\t\tdata += sizeof( uint32 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\t\t// zero-terminate the list of goals\r\n\t\t\t\t\tgoal_id = 0;\r\n\t\t\t\t\tmemcpy( data, &goal_id, sizeof( uint32 ));\r\n\t\t\t\t\tdata += sizeof( uint32 );\r\n\t\t\t\r\n\t\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\t\tmsg_desc.m_Length = (int) ( data - msg.m_Data );\r\n\t\t\t\t\tmsg_desc.m_Id = MSG_ID_SELECT_GOALS;\r\n\t\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\t\tgamenet_man->m_server->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// Update the player with the king of the hill status\r\n\t\t\t\tif(( king = gamenet_man->GetKingOfTheHill()))\r\n\t\t\t\t{\r\n\t\t\t\t\tGameNet::MsgByteInfo msg;\r\n\t\t\t\t\tNet::MsgDesc msg_desc;\r\n\t\r\n\t\t\t\t\tDbg_MsgAssert( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0x6ef8fda0,\"netking\")  ||\r\n\t\t\t\t\t\t\t\t   skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0x5d32129c,\"king\") ,\r\n\t\t\t\t\t\t\t\t\t( \"King exists in non-king of the hill game\" ));\r\n\t\r\n\t\t\t\t\tmsg.m_Data = king->m_Skater->GetID();\r\n\r\n\t\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgByteInfo );\r\n\t\t\t\t\tmsg_desc.m_Id = MSG_ID_NEW_KING;\r\n\t\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\t\tgamenet_man->m_server->EnqueueMessage(\tplayer->GetConnHandle(), &msg_desc );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tNet::MsgDesc proceed_desc;\r\n\r\n\t\t\tproceed_desc.m_Id = MSG_ID_PROCEED_TO_PLAY;\r\n\t\t\tproceed_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tproceed_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t// Send this to let the client know when he has received the full set of initial data\r\n\t\t\tgamenet_man->m_server->EnqueueMessage( \tplayer->GetConnHandle(), &proceed_desc );\r\n\r\n\t\t\tif( gamenet_man->InNetGame())\r\n\t\t\t{\r\n\t\t\t\tgamenet_man->SendFaceDataToPlayer( player );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_ready_query( Net::MsgHandlerContext* context )\r\n{\r\n\tMsgReady* msg;\r\n\tManager* gamenet_man;\r\n\r\n\tgamenet_man = (Manager*) context->m_Data;\r\n\tmsg = (MsgReady*) context->m_Msg;\r\n\t\r\n\tgamenet_man->m_latest_ready_query = msg->m_Time;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_ready_response( Net::MsgHandlerContext* context )\r\n{\r\n\tPlayerInfo* player;\r\n\tManager* gamenet_man;\r\n\tMsgReady* ready_msg;\r\n\r\n\tgamenet_man = (Manager*) context->m_Data;\r\n\tready_msg = (MsgReady* ) context->m_Msg;\r\n\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tif( player )\r\n\t{   \r\n\t\tplayer->MarkAsReady( ready_msg->m_Time );\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Respond to a client who is looking for games to join on the LAN*/\r\n/* Tell them info about the game                                  */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_find_server( Net::MsgHandlerContext* context )\r\n{\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tLst::Search< NewPlayerInfo > new_sh;\r\n\tNewPlayerInfo* np;\r\n    MsgServerDescription msg;\r\n\tMsgFindServer* find_msg;\r\n\tManager* gamenet_man;\r\n\tNet::Server* server;\r\n\tint i;\r\n\tchar name[vMAX_SERVER_NAME_LEN + 1];\r\n\tconst char *server_name;\r\n\tScript::CScriptStructure* pStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();   \r\n\r\n\t//Dbg_Printf( \"Got find server broadcast\\n\" );\r\n\tif( context->m_MsgLength != sizeof( MsgFindServer ))\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\tgamenet_man = (Manager*) context->m_Data;\r\n\tif( gamenet_man->InInternetMode())\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"server_name\") );\r\n\tpStructure->GetText( \"ui_string\", &server_name, true );\r\n\t\r\n\tfind_msg = (MsgFindServer *) context->m_Msg;\r\n    \r\n\tstrncpy( name, server_name, vMAX_SERVER_NAME_LEN );\r\n\tname[ vMAX_SERVER_NAME_LEN ] = '\\0';\r\n\t\r\n\tserver = gamenet_man->GetServer();\r\n\tDbg_Assert( server != NULL );\r\n\r\n\tmsg.m_SkillLevel = gamenet_man->GetSkillLevel();\r\n\tmsg.m_NumPlayers = gamenet_man->GetNumPlayers();\r\n\tmsg.m_MaxPlayers = gamenet_man->GetMaxPlayers();\r\n\tmsg.m_NumObservers = gamenet_man->GetNumObservers();\r\n\tmsg.m_MaxObservers = gamenet_man->GetMaxObservers();\r\n    \r\n\t// Handle the cases where you've just changed the limits and your current number of players/observers\r\n\t// exceeds the limits\r\n\tif( msg.m_MaxPlayers < msg.m_NumPlayers )\r\n\t{\r\n\t\tmsg.m_MaxPlayers = msg.m_NumPlayers;\r\n\t}\r\n\tif( msg.m_MaxObservers < msg.m_NumObservers )\r\n\t{\r\n\t\tmsg.m_MaxObservers = msg.m_NumObservers;\r\n\t}\r\n\r\n\tif( strcmp( gamenet_man->GetPassword(), \"\" ) == 0 )\r\n\t{\r\n\t\tmsg.m_Password = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmsg.m_Password = 1;\r\n\t}\r\n\r\n\tif( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netlobby\" ))\r\n\t{\r\n\t\tmsg.m_GameStarted = false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmsg.m_GameStarted = true;\r\n\t}\r\n\r\n\tmsg.m_HostMode = gamenet_man->GetHostMode();\r\n#ifdef __PLAT_NGPS__\t\r\n\tmsg.m_Ranked = false;\r\n\tif( gamenet_man->InInternetMode())\r\n\t{\r\n\t\tif( gamenet_man->mpBuddyMan->IsLoggedIn())\r\n\t\t{\r\n\t\t\tmsg.m_Ranked = true;\r\n\t\t}\r\n\t}\r\n#endif\r\n\t\r\n\tstrcpy( msg.m_Name, name );\r\n\tsprintf( msg.m_Level, \"%s\", gamenet_man->GetLevelName());\r\n\tsprintf( msg.m_Mode, \"%s\", gamenet_man->GetGameModeName());\r\n\tmsg.m_Timestamp = find_msg->m_Timestamp;\r\n#ifdef __PLAT_XBOX__\r\n\tmemcpy( msg.m_Nonce, find_msg->m_Nonce, 8 );\r\n\tmemcpy( &msg.m_XboxKeyId, &server->m_XboxKeyId, sizeof( XNKID ));\r\n\tmemcpy( &msg.m_XboxKey, &server->m_XboxKey, sizeof( XNKEY ));\r\n\tmemcpy( &msg.m_XboxAddr, &server->m_XboxAddr, sizeof( XNADDR ));\r\n#endif // __PLAT_XBOX__\r\n\r\n\ti = 0;\r\n\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; \r\n\t\t\tplayer = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( !player->IsObserving() || player->IsPendingPlayer())\r\n\t\t{\r\n\t\t\tsprintf( msg.m_PlayerNames[i], player->m_Name );\r\n\t\t\ti++;\r\n\t\t}\r\n\t}\r\n    \r\n\tfor( np = gamenet_man->FirstNewPlayerInfo( new_sh ); np; np = gamenet_man->NextNewPlayerInfo( new_sh ))\r\n\t{\r\n\t\t// Pending players count, observers don't\r\n\t\tif(\t( np->Flags & PlayerInfo::mPENDING_PLAYER ) ||\r\n\t\t\t( np->Flags & PlayerInfo::mJUMPING_IN ) ||\r\n\t\t\t!( np->Flags & PlayerInfo::mOBSERVER ))\r\n\t\t{\r\n\t\t\tsprintf( msg.m_PlayerNames[i], np->Name );\r\n\t\t\ti++;\r\n\t\t}                 \r\n\t}\r\n\t\r\n#ifdef __PLAT_XBOX__\t\r\n\tserver->SendMessageTo( Net::MSG_ID_SERVER_RESPONSE, sizeof( MsgServerDescription ), &msg,\r\n\t\t\t\t\t\t\tINADDR_BROADCAST, context->m_Conn->GetPort(), 0 );\r\n#else\r\n\tserver->SendMessageTo( Net::MSG_ID_SERVER_RESPONSE, sizeof( MsgServerDescription ), &msg,\r\n\t\t\t\t\t\t\tcontext->m_Conn->GetIP(), context->m_Conn->GetPort(), 0 );\t\r\n#endif\t\t\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Got a connection request: For now, just accept it, create a    */\r\n/* skater for the requester, and tell them to create one too      */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_connection( Net::MsgHandlerContext* context )\r\n{   \r\n\tManager* gamenet_man;\r\n\tMsgConnectInfo* connect_msg;\r\n\tint reason;\r\n\t\r\n\tDbg_Assert( context );\r\n\r\n\tgamenet_man = (Manager*) context->m_Data;\r\n\tconnect_msg = (MsgConnectInfo*) context->m_Msg;\r\n    \r\n\tif( context->m_Conn->IsRemote())\r\n\t{\r\n\t\tMsgProceed msg;\r\n\t\tconst char *server_name;\r\n\t\tScript::CScriptStructure* pStructure;\r\n\t\tPrefs::Preferences* pPreferences;\r\n\t\tNet::Manager* net_man = Net::Manager::Instance();\r\n\t\t\r\n\t\tif( !gamenet_man->ok_to_join( reason, connect_msg, context->m_Conn ))\r\n\t\t{\r\n\t\t\tMsgEmbedded msg;\r\n\t\r\n\t\t\tmsg.m_SubMsgId = reason;\r\n\r\n\t\t\tcontext->m_App->SendMessageTo( MSG_ID_JOIN_REFUSED, sizeof( MsgEmbedded ), &msg, \r\n\t\t\t\t\t\t\t\t\t\t   context->m_Conn->GetIP(), context->m_Conn->GetPort(), 0 );\r\n\t\t\treturn Net::HANDLER_HALT;\r\n\t\t}\r\n\r\n\t\tDbg_Printf( \"Sending Join Proceed Message to IP: %x Port: %d MaxPlayers: %d\\n\", context->m_Conn->GetIP(), context->m_Conn->GetPort(), gamenet_man->GetNumPlayers());\r\n\t\tmsg.m_MaxPlayers = gamenet_man->GetMaxPlayers();\r\n\t\tif(\tnet_man->GetConnectionType() == Net::vCONN_TYPE_MODEM )\r\n\t\t{\r\n\t\t\tmsg.m_Broadband = 0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmsg.m_Broadband = 1;\r\n\t\t}\r\n\t\t\r\n\t\tif( gamenet_man->InInternetMode())\r\n\t\t{\r\n\t\t\tmsg.m_Port = gamenet_man->GetJoinPort();\r\n\t\t\tmsg.m_PrivateIP = gamenet_man->GetJoinPrivateIP();\r\n\t\t\tmsg.m_PublicIP = gamenet_man->GetJoinIP();\r\n\t\t}\r\n\t\t\r\n\t\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"server_name\") );\r\n\t\tpStructure->GetText( \"ui_string\", &server_name, true );\r\n\t\r\n\t\tstrncpy( msg.m_ServerName, server_name, vMAX_SERVER_NAME_LEN );\r\n\t\tmsg.m_ServerName[ vMAX_SERVER_NAME_LEN ] = '\\0';\r\n\r\n\t\tcontext->m_App->SendMessageTo( \tMSG_ID_JOIN_PROCEED, sizeof( MsgProceed), &msg,\r\n\t\t\t\t\t\t\t\t\t\tcontext->m_Conn->GetIP(), context->m_Conn->GetPort(), 0 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMsgProceed msg;\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tmsg.m_MaxPlayers = gamenet_man->GetMaxPlayers();\r\n\t\tmsg_desc.m_Id = MSG_ID_JOIN_PROCEED;\r\n\t\tmsg_desc.m_Data = &msg;\r\n\t\tmsg_desc.m_Length = sizeof( MsgProceed );\r\n\t\tcontext->m_App->EnqueueMessage( context->m_Conn->GetHandle(), &msg_desc );\r\n\t\t//context->m_App->SendData();\r\n\t}\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Client wants to join a connected server\t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_join_request( Net::MsgHandlerContext* context )\r\n{   \r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tNewPlayerInfo new_player;\r\n\tManager* gamenet_man;\r\n\tMsgJoinInfo* join_msg;\r\n\tint reason;\r\n\t\r\n\tDbg_Assert( context );\r\n\r\n\tDbg_Printf( \"Got Join Request from ip %x port %d\\n\", context->m_Conn->GetIP(), context->m_Conn->GetPort());\r\n\r\n\tgamenet_man = (Manager*) context->m_Data;\r\n\tjoin_msg = (MsgJoinInfo*) context->m_Msg;\r\n\r\n\t// We'll just accept local clients\r\n\tif( context->m_Conn->IsRemote())\r\n\t{\r\n\t\t// Rule out redundancy\r\n\t\tif( context->m_PacketFlags & Net::mHANDLE_FOREIGN )\r\n\t\t{\r\n\t\t\tNet::Conn* conn;\r\n\r\n\t\t\t// Are we currently accepting players?\r\n\t\t\tif( context->m_App->AcceptsForeignConnections() == false )\r\n\t\t\t{\r\n\t\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Create a more permanent connection\r\n\t\t\tconn = context->m_App->NewConnection( context->m_Conn->GetIP(), context->m_Conn->GetPort());\r\n\t\t\tif( join_msg->m_Broadband )\r\n\t\t\t{\r\n\t\t\t\tconn->SetBandwidthType( Net::Conn::vBROADBAND );\r\n\t\t\t\tconn->SetSendInterval( Tmr::VBlanks( 2 ));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tconn->SetBandwidthType( Net::Conn::vNARROWBAND );\r\n\t\t\t\tconn->SetSendInterval( Tmr::VBlanks( 2 ));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\r\n\t\t\tcontext->m_Conn = conn;\t// the rest of the chain will use this new, valid connection\r\n\t\t\t\r\n\t\t\tif( !gamenet_man->ok_to_join( reason, join_msg, conn ))\r\n\t\t\t{\r\n\t\t\t\tMsgEmbedded msg;\r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\r\n\t\t\t\tmsg.m_SubMsgId = reason;\r\n\t\t\r\n\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( MsgEmbedded );\r\n\t\t\t\tmsg_desc.m_Id = MSG_ID_JOIN_REFUSED;\r\n\t\t\t\tcontext->m_App->EnqueueMessage( context->m_Conn->GetHandle(), &msg_desc );\r\n\t\t\t\tcontext->m_Conn->Invalidate();\r\n\t\t\r\n\t\t\t\treturn Net::HANDLER_HALT;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t}\r\n\t}\r\n\t\r\n\tstrcpy( new_player.Name, join_msg->m_Name );\r\n\tnew_player.ObjID = gamenet_man->GetNextPlayerObjectId();\r\n\tnew_player.Conn = context->m_Conn;\r\n\tnew_player.Flags = 0;\r\n\tnew_player.Profile = join_msg->m_Profile;\r\n\tnew_player.Rating = join_msg->m_Rating;\r\n\tnew_player.VehicleControlType = join_msg->m_VehicleControlType;\r\n\tif( join_msg->m_Observer != 0 )\r\n\t{\r\n\t\tnew_player.Flags |= PlayerInfo::mOBSERVER;\r\n\t}\r\n\telse if(( skate_mod->GetGameMode()->GetNameChecksum() != CRCD(0x1c471c60, \"netlobby\") ) &&\r\n\t\t\t( gamenet_man->GameIsOver() == false ))\r\n\t{\r\n\t\tnew_player.Flags |= ( PlayerInfo::mPENDING_PLAYER | PlayerInfo::mOBSERVER );\r\n\t}\r\n    \r\n\tDbg_Printf( \"====================== GOT JOIN REQUEST FROM PLAYER %d\\n\", new_player.ObjID );\r\n\tif( context->m_Conn->IsLocal())\r\n\t{\r\n\t\t// GJ:  copy the contents of the skater profile from one to the other\r\n\t\t// it'd be nice to just use a copy constructor, but i couldn't\r\n\t\t// get it to work for some reason\r\n\t\tuint8* pTempBuffer = new uint8[vMAX_APPEARANCE_DATA_SIZE];\r\n\t\tskate_mod->GetProfile( new_player.ObjID )->WriteToBuffer(pTempBuffer, vMAX_APPEARANCE_DATA_SIZE);\r\n\t\tnew_player.mpSkaterProfile->ReadFromBuffer(pTempBuffer);\r\n\t\tdelete pTempBuffer;\r\n\r\n\t\tnew_player.Flags = PlayerInfo::mLOCAL_PLAYER;\r\n\t\tgamenet_man->DeferredNewPlayer( &new_player, 0 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( !join_msg->m_Observer )\r\n\t\t{\r\n\t\t\t// GJ:  the appearance is transmitted inside the message,\r\n\t\t\t// so copy it to the \"new_player\" structure\r\n\t\t\tnew_player.mpSkaterProfile->ReadFromBuffer(join_msg->m_AppearanceData);\r\n\t\t}\r\n\t\tgamenet_man->DeferredNewPlayer( &new_player );\r\n\r\n\t\t// Flag this new player's connection as busy so he doesn't get game-related messages\r\n\t\t// in the ineterum\r\n\t\tcontext->m_Conn->ClearStatus( Net::Conn::mSTATUS_READY );\r\n\t\tcontext->m_Conn->SetStatus( Net::Conn::mSTATUS_BUSY );\r\n\t}\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Client wants to enter observer mode\t  \t\t\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_observe( Net::MsgHandlerContext* context )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tManager* gamenet_man;\r\n\tPlayerInfo* player;\r\n\tObj::CSkater* skater;\r\n\t\t\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\r\n\tDbg_Printf( \"Got observe request\\n\" );\r\n\r\n\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tif( !player || player->IsObserving())\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\t// Allow the server to go into observer mode without restriction\r\n\tif( ( player->IsLocalPlayer() == false ) &&\r\n\t\t( gamenet_man->GetNumObservers() >= gamenet_man->GetMaxObservers()))\r\n\t{\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tDbg_Printf( \"Not enough observer spots\\n\" );\r\n\t\tmsg_desc.m_Id = MSG_ID_OBSERVE_REFUSED;\r\n\t\tgamenet_man->m_server->EnqueueMessage( context->m_Conn->GetHandle(), &msg_desc );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n        // Only do this player->observer conversion here for remote players.\r\n\t\t// For our local player, let the observe_proceed message run its course\r\n\t\tif( player->IsLocalPlayer() == false )\r\n\t\t{\r\n\t\t\tskater = player->m_Skater;\r\n\t\t\tgamenet_man->DropPlayer( player, vREASON_OBSERVING );\r\n\t\t\tskate_mod->remove_skater( skater );\r\n\t\t\tplayer->m_flags.SetMask( PlayerInfo::mOBSERVER );\r\n\t\t\tplayer->m_Skater = NULL;\r\n\t\t\tif( player->IsServerPlayer())\r\n\t\t\t{\r\n\t\t\t\tplayer->MarkAsNotServerPlayer();\r\n\t\t\t\tgamenet_man->ChooseNewServerPlayer();\r\n\t\t\t}\r\n\t\t\t// If we're destroying the player we're looking at, change to the next player\r\n\t\t\tif( player == gamenet_man->m_cam_player )\r\n\t\t\t{\r\n\t\t\t\tgamenet_man->m_cam_player = gamenet_man->GetNextPlayerToObserve();\r\n\t\t\t\tif( player == gamenet_man->m_cam_player )\r\n\t\t\t\t{\r\n\t\t\t\t\tgamenet_man->m_cam_player = NULL;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tgamenet_man->ObservePlayer( gamenet_man->m_cam_player );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t}\r\n\r\n\t\tDbg_Printf( \"Sent Proceed to Observe\\n\" );\r\n\t\tmsg_desc.m_Id = MSG_ID_OBSERVE_PROCEED;\r\n\t\tgamenet_man->m_server->EnqueueMessage( context->m_Conn->GetHandle(), &msg_desc );\r\n\t}\r\n    \r\n\treturn Net::HANDLER_CONTINUE;\r\n}   \r\n\r\n/******************************************************************/\r\n/* Got a disconnection request. Accept it at face value for now\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_disconn_request( Net::MsgHandlerContext* context )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tManager* gamenet_man;\r\n\tPlayerInfo* quitter;\r\n\t\t\r\n\t\r\n\r\n    gamenet_man = (Manager *) context->m_Data;\r\n\tquitter = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tif( quitter )\r\n\t{\r\n\t\tif (!quitter->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tObj::CSkater* quitting_skater;\r\n\t\t\tbool observing;\r\n\r\n\t\t\tquitting_skater = quitter->m_Skater;\r\n\t\t\tobserving = quitter->IsObserving();\r\n\r\n\t\t\tgamenet_man->DropPlayer( quitter, vREASON_QUIT );\r\n\t\t\tif( !observing )\r\n\t\t\t{\r\n\t\t\t\tskate_mod->remove_skater( quitting_skater );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tLst::Node< NewPlayerInfo > *node, *next;\r\n\t\tNewPlayerInfo* new_player;\r\n\t\t\t\r\n\t\t\r\n\t\r\n\t\tfor( node = gamenet_man->m_new_players.GetNext(); node; node = next )\r\n\t\t{\r\n\t\t\tnext = node->GetNext();\r\n\t\r\n\t\t\tnew_player = node->GetData();\r\n\t\t\t\r\n\t\t\t// \r\n\t\t\tif( new_player->Conn == context->m_Conn )\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"Removing %s\\n\", new_player->Name );\r\n\t\t\t\tcontext->m_App->TerminateConnection( new_player->Conn );\r\n\t\t\t\t\r\n\t\t\t\tdelete node;\r\n\t\t\t\tdelete new_player;\r\n\t\t\t\t\r\n\t\t\t\t// Return this value to signify that we've destroyed the message (done by\r\n\t\t\t\t// TerminateConnection())\r\n\t\t\t\treturn Net::HANDLER_MSG_DESTROYED;\r\n\t\t\t}\r\n\t\t}\r\n\t\t// Pay no attention to any other pending messages from ths client\r\n\t\treturn Net::HANDLER_HALT;\r\n\t}\r\n    \r\n\t// Return this value to signify that we've destroyed the message (done by\r\n\t// TerminateConnection())\r\n\treturn Net::HANDLER_MSG_DESTROYED;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_client_proceed( Net::MsgHandlerContext* context )\r\n{\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\tManager* gamenet_man;\r\n\t\r\n\t\r\n\tDbg_Printf( \"(%d) Got proceed instruction from server\\n\", context->m_App->m_FrameCounter );\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tgamenet_man->SetReadyToPlay(true);\r\n\t\r\n\tif( !context->m_App->IsLocal())\r\n\t{\r\n\t\tmlp_manager->AddLogicTask( *gamenet_man->m_client_add_new_players_task );\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_observe_proceed( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\t\t\r\n\tDbg_Printf( \"Entering Observer Mode\\n\" );\t\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tScriptExitSurveyorMode( NULL, NULL );\r\n\tgamenet_man->EnterObserverMode(); \r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_observe_refused( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\t\r\n    gamenet_man = (Manager *) context->m_Data;\r\n\tScript::CStruct* p_structure = new Script::CStruct;\r\n\r\n\tp_structure->AddChecksum( \"reason\", Script::GenerateCRC( \"net_reason_full_observers\" ));\r\n\tp_structure->AddChecksum( \"just_dialog\", 0 );\r\n\tScript::RunScript( \"CreateJoinRefusedDialog\", p_structure );\r\n\tdelete p_structure;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_join_refused( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\tMsgEmbedded* msg;\r\n    \r\n\t\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tmsg = (MsgEmbedded *) context->m_Msg;\r\n\r\n\r\n\tswitch( msg->m_SubMsgId )\r\n\t{\r\n\t\tcase JOIN_REFUSED_ID_BANNED:\r\n\t\t\tgamenet_man->m_conn_refused_reason = Script::GenerateCRC(\"net_reason_banned\");\r\n\t\t\tbreak;\r\n\t\tcase JOIN_REFUSED_ID_FULL:\r\n\t\t\tgamenet_man->m_conn_refused_reason = Script::GenerateCRC(\"net_reason_full\");\r\n\t\t\tbreak;\r\n\t\tcase JOIN_REFUSED_ID_FULL_OBSERVERS:\r\n\t\t\tgamenet_man->m_conn_refused_reason = Script::GenerateCRC(\"net_reason_full_observers\");\r\n\t\t\tbreak;\r\n\t\tcase JOIN_REFUSED_ID_PW:\r\n\t\t{   \r\n\t\t\tif( gamenet_man->GetJoinState() == vJOIN_STATE_TRYING_PASSWORD )\r\n\t\t\t{\r\n\t\t\t\tgamenet_man->m_conn_refused_reason = Script::GenerateCRC(\"net_reason_wrong_password\");\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\r\n\t\t\t\tScript::RunScript( \"CreateEnterPasswordControl\" );\r\n\t\t\t\t/*\r\n\t\t\t\tdlg->GoBack();\r\n\t\t\t\t\t\t\t\r\n\t\t\t\tFront::MenuFactory* menu_factory = Front::MenuFactory::Instance();\r\n\t\t\t\tFront::MenuElement *net_menu = menu_factory->GetMenuElement(Script::GenerateCRC(\"net_menu\"));\r\n\t\t\t\tFront::MenuEvent event;\r\n\t\t\t\t\r\n\t\t\t\tevent.SetTypeAndTarget( Front::MenuEvent::vLINK, Script::GenerateCRC(\"enter_password_control\") );\r\n\t\t\t\tnet_menu->LaunchEvent( &event );\r\n\t\t\t\t*/\r\n\r\n\t\t\t\t// Temporarily disable timeout\r\n\t\t\t\tgamenet_man->m_join_timeout_task->Remove();\r\n\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\treturn Net::HANDLER_CONTINUE;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase JOIN_REFUSED_ID_IN_PROGRESS:\r\n\t\t{\r\n\t\t\tDbg_Printf( \"Refused: Joining a game in progress\\n\" );\r\n\t\t\t\r\n\t\t\tScript::RunScript( \"CreateGameInProgressDialog\" );\r\n            \r\n\t\t\tgamenet_man->m_join_timeout_task->Remove();\r\n\t\t\treturn Net::HANDLER_CONTINUE;\r\n\t\t}\r\n\t\tcase JOIN_REFUSED_ID_VERSION:\r\n\t\t\tgamenet_man->m_conn_refused_reason = Script::GenerateCRC(\"net_reason_version\" );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tgamenet_man->m_conn_refused_reason = Script::GenerateCRC(\"net_reason_default\" );\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\tDbg_Printf( \"(%d) Host refused join request: Reason %d\\n\", \tcontext->m_App->m_FrameCounter,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmsg->m_SubMsgId );\r\n\t\r\n\tgamenet_man->CancelJoinServer();\r\n\tgamenet_man->SetJoinState( vJOIN_STATE_REFUSED );\r\n\t\r\n\treturn Net::HANDLER_HALT;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_join_proceed( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\tMsgJoinInfo msg;\r\n    Net::MsgDesc msg_desc;\r\n\tint size;\r\n\tScript::CScriptStructure* pStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tconst char* network_id;\r\n\tMsgProceed* proceed_msg;\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tbool ignore_face_data;\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\t\t\r\n\tproceed_msg = (MsgProceed*) context->m_Msg;\r\n\tif( context->m_Conn->IsRemote())\r\n\t{\r\n\t\t// Note whether or not the server is narrowband/broadband\r\n\t\tif( proceed_msg->m_Broadband )\r\n\t\t{\r\n\t\t\tcontext->m_Conn->SetBandwidthType( Net::Conn::vBROADBAND );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcontext->m_Conn->SetBandwidthType( Net::Conn::vNARROWBAND );\r\n\t\t}\r\n\r\n\t\tgamenet_man->m_join_ip = proceed_msg->m_PublicIP;\r\n\t\tgamenet_man->m_join_private_ip = proceed_msg->m_PrivateIP;\r\n\t\tgamenet_man->SetJoinPort( proceed_msg->m_Port );\r\n\r\n\t\tDbg_Printf( \"**** Setting public IP to %s\\n\", inet_ntoa(*(struct in_addr *) &gamenet_man->m_join_ip ));\r\n#ifdef __PLAT_NGPS__\r\n\t\tif( gamenet_man->mpBuddyMan->IsLoggedIn())\r\n\t\t{\r\n\t\t\tchar location[1024];\r\n\r\n\t\t\tgamenet_man->mpLobbyMan->SetServerName( proceed_msg->m_ServerName );\r\n\t\t\tsprintf( location, \"%d:%d:%d:%s (%s)\", gamenet_man->m_join_ip, gamenet_man->m_join_private_ip, gamenet_man->GetJoinPort(), \r\n\t\t\t\t\t gamenet_man->mpLobbyMan->GetServerName(), gamenet_man->mpLobbyMan->GetLobbyName());\r\n\t\t\tif( gamenet_man->GetJoinMode() == vJOIN_MODE_PLAY )\r\n\t\t\t{\r\n\t\t\t\tgamenet_man->mpBuddyMan->SetStatusAndLocation( GP_PLAYING, (char*) Script::GetString( \"homie_status_playing\" ), location );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tgamenet_man->mpBuddyMan->SetStatusAndLocation( GP_PLAYING, (char*) Script::GetString( \"homie_status_observing\" ), location );\r\n\t\t\t}\r\n\t\t}\r\n#endif\r\n\r\n\t}\r\n\tskate_mod->GetGameMode()->SetMaximumNumberOfPlayers( proceed_msg->m_MaxPlayers );\r\n\r\n\t/*Dbg_Printf( \"******* Got Join Proceed from: %s, private: %s, port: %d\\n\", \r\n\t\t\t\tinet_ntoa(*(struct in_addr *) &gamenet_man->m_join_ip ), \r\n\t\t\t\tinet_ntoa(*(struct in_addr *) &gamenet_man->m_join_private_ip ),\r\n\t\t\t\tgamenet_man->m_join_port );*/\r\n\t\r\n\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"network_id\") );\r\n\tpStructure->GetText( \"ui_string\", &network_id, true );\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tmsg.m_Profile = gamenet_man->mpBuddyMan->GetProfile();\r\n\tmsg.m_Rating = gamenet_man->mpStatsMan->GetStats()->GetRating();\r\n#endif\r\n\tmsg.m_Observer = ( gamenet_man->GetJoinMode() == vJOIN_MODE_OBSERVE );\r\n\tmsg.m_Version = vVERSION_NUMBER;\r\n\tmsg.m_WillingToWait = 1;\r\n\tif(\tnet_man->GetConnectionType() == Net::vCONN_TYPE_MODEM )\r\n\t{\r\n\t\tignore_face_data = true;\r\n\t\tmsg.m_Broadband = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tignore_face_data = false;\r\n\t\tmsg.m_Broadband = 1;\r\n\t}\r\n\t\t\t\r\n\tstrcpy( msg.m_Name, network_id );\r\n\tmsg.m_Password[0] = '\\0';\r\n\tsize = 0;\r\n\tif( !msg.m_Observer )\r\n\t{\r\n\t\t// GJ:  transmit the way you look (slot 0 of the\r\n\t\t// skater profile manager) to the server\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tObj::CSkaterProfile* pSkaterProfile = skate_mod->GetProfile(0);\r\n\t\tNet::Conn *server_conn;\r\n\t\tLst::Search< Net::Conn > sh;\r\n\t\r\n\t\tserver_conn = context->m_App->FirstConnection( &sh );\r\n\t\tif( server_conn->GetBandwidthType() == Net::Conn::vNARROWBAND )\r\n\t\t{\r\n\t\t\tignore_face_data = true;\r\n\t\t}\r\n\r\n\t\tsize = pSkaterProfile->WriteToBuffer(msg.m_AppearanceData, vMAX_APPEARANCE_DATA_SIZE,\r\n\t\t\t\t\t\t\t\t\t\t\t\tignore_face_data );\r\n\t\tDbg_Assert( size < vMAX_APPEARANCE_DATA_SIZE );\r\n\t\tDbg_Printf(\"\\n\\n******************* MsgJoinInfo (%d) appearance data size = %d %d Broadband %d\\n\", MSG_ID_JOIN_REQ,\r\n\t\t\t\tsize, sizeof(MsgJoinInfo) - vMAX_APPEARANCE_DATA_SIZE + size, ignore_face_data );\r\n\t}\r\n\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof(MsgJoinInfo) - vMAX_APPEARANCE_DATA_SIZE + size;\r\n\tmsg_desc.m_Id = MSG_ID_JOIN_REQ;\r\n\tif( context->m_Conn->IsRemote())\r\n\t{\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_IMPORTANT;\r\n\t}\r\n\r\n\tcontext->m_App->EnqueueMessageToServer( &msg_desc );\r\n\t\r\n\t/*context->m_App->StreamMessageToServer( GameNet::MSG_ID_JOIN_REQ, msg_desc.m_Length, \r\n\t\t\t\t\t   msg_desc.m_Data, \"appearance data\", vSEQ_GROUP_PLAYER_MSGS, false );*/\r\n\r\n\tgamenet_man->SetJoinState( vJOIN_STATE_JOINING );\r\n\r\n\treturn Net::HANDLER_MSG_DONE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_join_accepted( Net::MsgHandlerContext* context )\r\n{\r\n\tDbg_Message( \"(%d) Got Join Accepted!\\n\", context->m_App->m_FrameCounter );\r\n\r\n\t// Consider all of our messages up to this point to have been received\r\n\t//context->m_Conn->AckAllMessages();\r\n\t//context->m_Conn->DestroyMessageQueues();\r\n\tif( context->m_Conn->IsRemote())\r\n\t{\r\n\t\tcontext->m_Conn->DestroyImportantMessageQueues();\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_new_king( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\tMsgByteInfo* msg;\r\n\tPlayerInfo* player;\r\n\r\n\tmsg = (MsgByteInfo*) context->m_Msg;\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\t\r\n\tplayer = gamenet_man->GetKingOfTheHill();\r\n\tif( player )\r\n\t{\r\n\t\tplayer->MarkAsKing( false );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNewPlayerInfo* new_player;\r\n\t\tLst::Search< NewPlayerInfo > sh;\r\n\r\n\t\t// Maybe we just haven't officially added the previous king. Search our list of\r\n\t\t// queued up new players\r\n\t\tfor( new_player = gamenet_man->FirstNewPlayerInfo( sh ); new_player;\r\n\t\t\t\tnew_player = gamenet_man->NextNewPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tif( new_player->Flags & PlayerInfo::mKING_OF_THE_HILL )\r\n\t\t\t{\r\n\t\t\t\tnew_player->Flags &= ~PlayerInfo::mKING_OF_THE_HILL;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tplayer = gamenet_man->GetPlayerByObjectID( msg->m_Data );\r\n\tif( player )\r\n\t{\r\n\t\tplayer->MarkAsKing( true );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNewPlayerInfo* new_player;\r\n\t\tLst::Search< NewPlayerInfo > sh;\r\n\r\n\t\t// Maybe we just haven't officially added this new king player. Search our list of\r\n\t\t// queued up new players\r\n\t\tfor( new_player = gamenet_man->FirstNewPlayerInfo( sh ); new_player;\r\n\t\t\t\tnew_player = gamenet_man->NextNewPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tif( new_player->ObjID == msg->m_Data )\r\n\t\t\t{\r\n\t\t\t\tnew_player->Flags |= PlayerInfo::mKING_OF_THE_HILL;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n    \r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_stole_flag( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\tMsgFlagMsg* msg;\r\n\tPlayerInfo* player;\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tmsg = (MsgFlagMsg*) context->m_Msg;\r\n\r\n\tplayer = gamenet_man->GetPlayerByObjectID( msg->m_ObjId );\r\n\tif( player )\r\n\t{\r\n\t\tplayer->StoleFlag( msg->m_Team );\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_took_flag( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\tMsgFlagMsg* msg;\r\n\tPlayerInfo* player;\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tmsg = (MsgFlagMsg*) context->m_Msg;\r\n\r\n\tplayer = gamenet_man->GetPlayerByObjectID( msg->m_ObjId );\r\n\tif( player )\r\n\t{\r\n\t\tplayer->TookFlag( msg->m_Team );\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_captured_flag( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\tMsgFlagMsg* msg;\r\n\tPlayerInfo* player;\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tmsg = (MsgFlagMsg*) context->m_Msg;\r\n\r\n\tplayer = gamenet_man->GetPlayerByObjectID( msg->m_ObjId );\r\n\tif( player )\r\n\t{\r\n\t\tplayer->CapturedFlag( msg->m_Team );\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_retrieved_flag( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\tMsgFlagMsg* msg;\r\n\tPlayerInfo* player;\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tmsg = (MsgFlagMsg*) context->m_Msg;\r\n\r\n\tplayer = gamenet_man->GetPlayerByObjectID( msg->m_ObjId );\r\n\tif( player )\r\n\t{\r\n\t\tplayer->RetrievedFlag();\r\n\t}\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* A player has restarted in koth mode. If it is the king, send\t  */\r\n/* out a message signifying that the king has lost his crown\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_player_restarted( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\tPlayerInfo* player;\r\n\tMdl::Skate * skate_mod;\r\n\t \r\n\tskate_mod =  Mdl::Skate::Instance();\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tif( player )\r\n\t{\r\n\t\tplayer->m_flags.ClearMask( PlayerInfo::mRESTARTING );\r\n\t}\r\n\r\n\tif(\tskate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netctf\" ))\r\n\t{\r\n\t\tif( player && player->HasCTFFlag())\r\n\t\t{\r\n\t\t\tLst::Search< PlayerInfo > sh;\r\n\t\t\tPlayerInfo* send_player, *local_player;\r\n\t\t\tchar team_str[64];\r\n\t\t\tint team;\r\n\t\t\tScript::CStruct* pParams;\r\n\t\t\tMsgFlagMsg msg;\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\t\r\n\t\t\tteam = player->HasWhichFlag();\r\n\t\t\tsprintf( team_str, \"team_%d_name\", team + 1 );\r\n\t\t\tpParams = new Script::CStruct;\r\n\t\r\n\t\t\tpParams->AddInteger( \"team\", team );\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\t\tScript::RunScript( \"flag_returned\", pParams );\r\n\t\r\n\t\t\tdelete pParams;\r\n\t\t\tmsg.m_Team = team;\r\n\t\t\tmsg.m_ObjId = player->m_Skater->GetID();\r\n\r\n\t\t\t// If it's me, remove the message that says \"return the flag to your base\"\r\n\t\t\tif( player->IsLocalPlayer())\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( \"destroy_ctf_panel_message\" );\r\n\t\t\t}\r\n\t\t\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\t\t\tif( local_player && !local_player->IsObserving())\r\n\t\t\t{\r\n\t\t\t\tif( local_player->m_Team == team )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript( \"hide_ctf_arrow\" );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tplayer->ClearCTFState();\r\n\r\n\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\tmsg_desc.m_Length = sizeof( MsgFlagMsg );\r\n\t\t\tmsg_desc.m_Id = MSG_ID_PLAYER_DROPPED_FLAG;\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\tfor( send_player = gamenet_man->FirstPlayerInfo( sh, true ); send_player; \r\n\t\t\t\t\tsend_player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\tif( send_player->IsLocalPlayer())\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tcontext->m_App->EnqueueMessage( send_player->GetConnHandle(), &msg_desc );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if(( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netking\" )) ||\r\n\t\t\t( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"king\" )))\r\n\t{\r\n\t\tif( player && player->IsKing())\r\n\t\t{\r\n\t\t\tLst::Search< PlayerInfo > sh;\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\tchar point;\r\n\t\r\n\t\t\tplayer->MarkAsKing( false );\r\n\t\t\tgamenet_man->m_crown_spawn_point = Mth::Rnd( vNUM_CROWN_SPAWN_POINTS );\r\n            point = (char) gamenet_man->m_crown_spawn_point;\r\n\t\t\t\r\n\t\t\tmsg_desc.m_Data = &point;\r\n\t\t\tmsg_desc.m_Length = sizeof( char );\r\n\t\t\tmsg_desc.m_Id = MSG_ID_KING_DROPPED_CROWN;\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; \r\n\t\t\t\t\tplayer = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\tcontext->m_App->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* The server is notifying the client that he's in an auto-serving*/\r\n/* server\t\t\t\t\t\t\t\t\t  \t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_auto_server_notification( Net::MsgHandlerContext* context )\r\n{\r\n\tScript::RunScript( \"launch_auto_server_notification\" );\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* The server is notifying the client that he is the new\t\t  */\r\n/* operating server\tin this fcfs server\t\t  \t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_fcfs_assignment( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\tPlayerInfo* player;\r\n\tuint32 *checksum;\r\n\tScript::CStruct* pParams;\r\n\t\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\r\n\tplayer = gamenet_man->GetLocalPlayer();\r\n\tDbg_Assert( player );\r\n\r\n\tchecksum = (uint32*) context->m_Msg;\r\n\tplayer->MarkAsServerPlayer();\r\n\tpParams = new Script::CStruct;\r\n\tpParams->AddChecksum( \"checksum\", *checksum );\r\n\tScript::RunScript( \"launch_fcfs_notification\", pParams );\r\n\tdelete pParams;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* The fcfs client is requesting to perform a server operation\t  */\r\n/* \t\t\t\t\t\t\t\t  \t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_fcfs_request( Net::MsgHandlerContext* context )\r\n{\r\n\tPlayerInfo* player;\r\n\tManager* gamenet_man;\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\r\n\tDbg_Printf( \"GOT FCFS REQUEST\\n\" );\r\n\t// First, ensure we even have an fcfs server\r\n\tplayer = gamenet_man->GetServerPlayer();\r\n\tif( player == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\t// Next, make sure the requesting client matches the fcfs client\r\n\tif( player->m_Conn != context->m_Conn )\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\tDbg_Printf( \"GOT FCFS REQUEST 2\\n\" );\r\n\tswitch( context->m_MsgId )\r\n\t{\r\n\t\tcase MSG_ID_FCFS_START_GAME:\r\n\t\t{\r\n\t\t\tMsgStartGameRequest* msg;\r\n\t\t\tPrefs::Preferences* pPreferences;\r\n\t\t\tScript::CStruct* pTempStructure;\r\n\t\t\tconst char* ui_string;\r\n\t\t\tint score, time, fireball_level;\r\n\t\r\n\t\t\tmsg = (MsgStartGameRequest*) context->m_Msg;\r\n\t\t\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\r\n\t\t\t// First, apply the options chosen by the fcfs\r\n\t\t\tpTempStructure = new Script::CStruct;\r\n\t\t\tui_string = gamenet_man->GetNameFromArrayEntry( \"net_game_type_info\", msg->m_GameMode );\r\n\t\t\tDbg_Printf( \"Got Game Mode UI String of %s\\n\", ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, msg->m_GameMode );\r\n\t\t\tpPreferences->SetPreference( Script::GenerateCRC( \"game_type\" ), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tpTempStructure = new Script::CStruct;\r\n\t\t\tui_string = gamenet_man->GetNameFromArrayEntry( \"skill_level_info\", msg->m_SkillLevel );\r\n\t\t\tDbg_Printf( \"Got Skill Level UI String of %s\\n\", ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, msg->m_SkillLevel );\r\n\t\t\tpPreferences->SetPreference( Script::GenerateCRC( \"skill_level\" ), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tpTempStructure = new Script::CStruct;\r\n\t\t\tui_string = gamenet_man->GetNameFromArrayEntry( \"fireball_level_info\", msg->m_FireballLevel );\r\n\t\t\tfireball_level = gamenet_man->GetIntFromArrayEntry( \"fireball_level_info\", msg->m_FireballLevel, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tCRCD(0xce87e4e3,\"fireball_level\") );\r\n\t\t\tDbg_Printf( \"Got Fireball Level UI String of %s\\n\", ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, msg->m_FireballLevel );\r\n\t\t\tpPreferences->SetPreference( Script::GenerateCRC( \"fireball_difficulty\" ), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tpTempStructure = new Script::CStruct;\r\n\t\t\tui_string = gamenet_man->GetNameFromArrayEntry( \"on_off_types\", msg->m_PlayerCollision );\r\n\t\t\tDbg_Printf( \"Got Player Collision UI String of %s\\n\", ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, msg->m_PlayerCollision );\r\n\t\t\tpPreferences->SetPreference( Script::GenerateCRC( \"player_collision\" ), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tpTempStructure = new Script::CStruct;\r\n\t\t\tui_string = gamenet_man->GetNameFromArrayEntry( \"on_off_types\", msg->m_FriendlyFire );\r\n\t\t\tDbg_Printf( \"Got Friendly Fire UI String of %s\\n\", ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, msg->m_FriendlyFire );\r\n\t\t\tpPreferences->SetPreference( Script::GenerateCRC( \"friendly_fire\" ), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tpTempStructure = new Script::CStruct;\r\n\t\t\tui_string = gamenet_man->GetNameFromArrayEntry( \"boolean_types\", msg->m_StopAtZero );\r\n\t\t\tDbg_Printf( \"Got Stop At Zero UI String of %s\\n\", ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, msg->m_StopAtZero );\r\n\t\t\tpPreferences->SetPreference( Script::GenerateCRC( \"stop_at_zero\" ), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tpTempStructure = new Script::CStruct;\r\n\t\t\tui_string = gamenet_man->GetNameFromArrayEntry( \"ctf_type\", msg->m_CTFType );\r\n\t\t\tDbg_Printf( \"Got CTF Type UI String of %s\\n\", ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, msg->m_CTFType );\r\n\t\t\tpPreferences->SetPreference( Script::GenerateCRC( \"ctf_game_type\" ), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n            pTempStructure = new Script::CStruct;\r\n\t\t\tui_string = gamenet_man->GetNameFromArrayEntry( \"time_limit_options\", msg->m_TimeLimit );\r\n\t\t\ttime = gamenet_man->GetIntFromArrayEntry( \"time_limit_options\", msg->m_TimeLimit, CRCD( 0x906b67ba, \"time\" ) );\r\n\t\t\tDbg_Printf( \"Got Time Limit UI String of %s\\n\", ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, msg->m_TimeLimit );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"time\"), ESYMBOLTYPE_INTEGER, time );\r\n\t\t\tpPreferences->SetPreference( Script::GenerateCRC( \"time_limit\" ), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tpTempStructure = new Script::CStruct;\r\n\r\n\t\t\tscore = 0;\r\n\t\t\tui_string = gamenet_man->GetNameFromArrayEntry( \"target_score_options\", msg->m_TargetScore );\r\n\t\t\tscore = gamenet_man->GetIntFromArrayEntry( \"target_score_options\", msg->m_TargetScore, CRCD( 0xcd66c8ae, \"score\" ));\r\n\t\t\t// Our \"target score\" comes from either the target score options array or the time limit options array, depending on\r\n\t\t\t// whether the game type is score challenge or koth\r\n\t\t\tif( ui_string == NULL )\r\n\t\t\t{\r\n\t\t\t\tui_string = gamenet_man->GetNameFromArrayEntry( \"capture_options\", msg->m_TargetScore );\r\n\t\t\t\tscore = gamenet_man->GetIntFromArrayEntry( \"capture_options\", msg->m_TargetScore, CRCD( 0xcd66c8ae, \"score\" ));\r\n\t\t\t\tif( ui_string == NULL )\r\n\t\t\t\t{\r\n\t\t\t\t\tui_string = gamenet_man->GetNameFromArrayEntry( \"time_limit_options\", msg->m_TargetScore );\r\n\t\t\t\t\tscore = gamenet_man->GetIntFromArrayEntry( \"time_limit_options\", msg->m_TargetScore, CRCD( 0x906b67ba, \"time\" ));\r\n\t\t\t\t\tscore *= 1000;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tDbg_Printf( \"Got Target Score %08x UI String of %s, score %d\\n\", msg->m_TargetScore, ui_string, score );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, ui_string );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, msg->m_TargetScore );\r\n\t\t\tif( score > 0 )\r\n\t\t\t{\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"score\"), ESYMBOLTYPE_INTEGER, score );\r\n\t\t\t}\r\n\t\t\tpPreferences->SetPreference( Script::GenerateCRC( \"target_score\" ), pTempStructure );\r\n\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tScript::RunScript( \"chosen_start_game\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase MSG_ID_FCFS_BAN_PLAYER:\r\n\t\t{\r\n\t\t\tMsgRemovePlayerRequest* msg;\r\n\t\t\tPlayerInfo* player, *target_player;\r\n\t\t\tLst::Search< PlayerInfo > sh;\r\n\t\t\tint i;\r\n\r\n\t\t\tmsg = (MsgRemovePlayerRequest*) context->m_Msg;\r\n\r\n\t\t\ti = 0;\r\n\t\t\ttarget_player = NULL;\r\n\t\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\tif( msg->m_Index == i )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( stricmp( msg->m_Name, player->m_Name ) == 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttarget_player = player;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\ti++;\r\n\t\t\t}\r\n\r\n\t\t\tif( target_player == NULL )\r\n\t\t\t{\r\n\t\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t\t}\r\n\r\n\t\t\tif( msg->m_Ban == 1 )\r\n\t\t\t{\r\n\t\t\t\tObj::CSkater* quitting_skater;\r\n\t\t\t\tbool observing;\r\n\t\r\n\t\t\t\tquitting_skater = target_player->m_Skater;\r\n\t\t\t\tobserving = target_player->IsObserving();\r\n\t\t\t\tgamenet_man->DropPlayer( target_player, vREASON_BANNED );\r\n\t\t\t\tif( !observing )\r\n\t\t\t\t{\r\n\t\t\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\t\t\tskate_mod->remove_skater( quitting_skater );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tObj::CSkater* quitting_skater;\r\n\t\t\t\tbool observing;\r\n\t\r\n\t\t\t\tquitting_skater = target_player->m_Skater;\r\n\t\t\t\tobserving = target_player->IsObserving();\r\n\t\t\t\tgamenet_man->DropPlayer( target_player, vREASON_KICKED );\r\n\t\t\t\tif( !observing )\r\n\t\t\t\t{\r\n\t\t\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\t\t\tskate_mod->remove_skater( quitting_skater );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase MSG_ID_FCFS_CHANGE_LEVEL:\r\n\t\t{\r\n\t\t\tMsgIntInfo* msg;\r\n\t\t\tScript::CStruct* pStructure;\r\n\r\n\t\t\tmsg = (MsgIntInfo *) context->m_Msg;\r\n\t\t\tpStructure = new Script::CStruct;\r\n\t\r\n\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"level\" ), ESYMBOLTYPE_NAME, (uint32) msg->m_Data );\r\n\t\t\tpStructure->AddChecksum( \"from_fcfs\", Script::GenerateCRC( \"from_fcfs\" ));\r\n\t\t\tpStructure->AddChecksum( \"show_warning\", Script::GenerateCRC( \"show_warning\" ));\r\n\r\n\t\t\tScript::RunScript( \"change_level\", pStructure );\r\n\r\n\t\t\tdelete pStructure;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase MSG_ID_FCFS_TOGGLE_PROSET:\r\n\t\t{\r\n\t\t\tMsgToggleProSet* msg;\r\n\r\n\t\t\tmsg = (MsgToggleProSet *) context->m_Msg;\r\n\t\t\tgamenet_man->ToggleProSet( msg->m_Bit, msg->m_ParamId );\r\n\t\t\tScript::RunScript( \"toggle_proset_flag\", Script::GetStructure( msg->m_ParamId, Script::ASSERT ));\r\n\t\t\tScript::RunScript( \"toggle_geo_nomenu\", Script::GetStructure( msg->m_ParamId, Script::ASSERT ));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase MSG_ID_FCFS_TOGGLE_GOAL_SELECTION:\r\n\t\t{\r\n\t\t\tGame::CGoalManager* pGoalManager = Game::GetGoalManager();\r\n\t\t\tMsgIntInfo* msg;\r\n\t\t\t\r\n\t\t\tmsg = (MsgIntInfo*) context->m_Msg;\r\n\r\n\t\t\tpGoalManager->ToggleGoalSelection( msg->m_Data );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase MSG_ID_FCFS_END_GAME:\r\n\t\t{\r\n\t\t\tNet::Server* server;\r\n\t\t\tLst::Search< PlayerInfo > sh;\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\tserver = gamenet_man->GetServer();\r\n\r\n\t\t\tScript::RunScript( \"fcfc_end_game_selected\" );\r\n\t\r\n\t\t\tmsg_desc.m_Id = MSG_ID_END_GAME;\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\tif( player->IsLocalPlayer())\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\r\n\t\t\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase MSG_ID_FCFS_SET_NUM_TEAMS:\r\n\t\t{\r\n\t\t\tPrefs::Preferences* prefs;\r\n\t\t\tScript::CStruct* pParams, *pPrefStruct;\r\n\t\t\tMsgByteInfo* msg;\r\n            \r\n\t\t\tmsg = (MsgByteInfo*) context->m_Msg;\r\n\t\t\tDbg_Printf( \"GOT FCFS REQUEST : NUM TEAMS %d\\n\", msg->m_Data );\r\n\t\t\tpParams = new Script::CStruct;\r\n\t\t\tpParams->AddInteger( NONAME, msg->m_Data );\r\n\r\n\t\t\tpPrefStruct = new Script::CScriptStructure;\r\n\t\t\tswitch( msg->m_Data )\r\n\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tpPrefStruct->AddString( \"ui_string\", \"None\" );\r\n\t\t\t\t\tpPrefStruct->AddChecksum( \"checksum\", Script::GenerateCRC( \"teams_none\" ));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tpPrefStruct->AddString( \"ui_string\", \"2\" );\r\n\t\t\t\t\tpPrefStruct->AddChecksum( \"checksum\", Script::GenerateCRC( \"teams_two\" ));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\tpPrefStruct->AddString( \"ui_string\", \"3\" );\r\n\t\t\t\t\tpPrefStruct->AddChecksum( \"checksum\", Script::GenerateCRC( \"teams_three\" ));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 4:\r\n\t\t\t\t\tpPrefStruct->AddString( \"ui_string\", \"4\" );\r\n\t\t\t\t\tpPrefStruct->AddChecksum( \"checksum\", Script::GenerateCRC( \"teams_four\" ));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tprefs = gamenet_man->GetNetworkPreferences();\r\n\t\t\tprefs->SetPreference( Script::GenerateCRC(\"team_mode\"), pPrefStruct );\r\n\t\t\tdelete pPrefStruct;\r\n\r\n\t\t\tScriptSetNumTeams( pParams, NULL );\r\n\r\n\t\t\tdelete pParams;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* The king has lost his crown. Spawn a new one in the world at   */\r\n/* the spawn point specified\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_dropped_crown( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\tPlayerInfo* king, *other_player;\r\n\tchar spawn_pt;\r\n\tObj::CCrown* crown;\r\n\t\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tking = gamenet_man->GetKingOfTheHill();\r\n\tmemcpy( &spawn_pt, context->m_Msg, sizeof( char ));\r\n\tif( king )\r\n\t{\r\n\t\t// He is no longer king\r\n\t\tking->MarkAsKing( false );\r\n\t}\r\n\t\r\n\tif( king && king->IsLocalPlayer())\r\n\t{\r\n\t\tgamenet_man->CreateNetPanelMessage( false, Script::GenerateCRC(\"net_message_dropped_crown_you\"),\r\n\t\t\t\t\t\t\t\t\t\t\tNULL, NULL, king->m_Skater );\r\n\t}\r\n\telse\r\n\t{   \r\n\t\tif( gamenet_man->InNetGame())\r\n\t\t{\r\n\t\t\tgamenet_man->CreateNetPanelMessage( false, Script::GenerateCRC(\"net_message_dropped_crown_other\"));\r\n\t\t}\r\n\t\telse if( king && king->m_Skater )\r\n\t\t{   \r\n\t\t\tint other_id;\r\n\r\n\t\t\t// NOTE: This code only works for 2-player splitscreen. If we ever go to four,\r\n\t\t\t// it needs to be more sophisticated\r\n\t\t\tif( king->m_Skater->GetID() == 0 )\r\n\t\t\t{\r\n\t\t\t\tother_id = 1;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{ \r\n\t\t\t\tother_id = 0;\r\n\t\t\t}\r\n\r\n\t\t\tother_player = gamenet_man->GetPlayerByObjectID( other_id );\r\n\t\t\tif( other_player )\r\n\t\t\t{\r\n\t\t\t\tgamenet_man->CreateNetPanelMessage( false, Script::GenerateCRC(\"net_message_dropped_crown_other\"),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tNULL, NULL, other_player->m_Skater );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tcrown = gamenet_man->GetCrown();\r\n\tif( crown )\r\n\t{\r\n#if 1\r\n\t\tint loop_count = 0;\r\n\t\tbool node_found = false;\r\n\t\t\r\n\t\t// KLUDGE: keep looping through incase spawn_pt is larger than the number of crowns in the node array\r\n\t\twhile (!node_found)\r\n#endif\r\n\t\t{\r\n#if 1\r\n\t\t\t// KLUDGE: make sure we exit this loop at some point\r\n\t\t\tloop_count++;\r\n\t\t\tif (loop_count == 50) break;\r\n#endif\r\n\r\n\t\t\tint i;\r\n\t\t\t\r\n\t\t\tScript::CArray *pNodeArray=Script::GetArray(\"NodeArray\");\r\n\t\r\n\t\t\t// Make sure there's a node array\r\n\t\t\tDbg_Assert( pNodeArray != NULL );\r\n\t\t\t\t\t\t\t \r\n\t\t\ti = 0;\r\n\t\t\t// scan through it for a crown spawn point\r\n\t\t\twhile( i < (int)pNodeArray->GetSize() )\r\n\t\t\t{\r\n\t\t\t\tuint32\tTypeChecksum;\r\n\t\t\t\tMth::Vector pos;\r\n\t\t\t\tScript::CScriptStructure *pNode=pNodeArray->GetStructure(i);\r\n\t\t\t\t\r\n\t\t\t\tTypeChecksum = 0;\r\n\t\t\t\tpNode->GetChecksum(\"Type\",&TypeChecksum);\r\n\t\t\t\tif( TypeChecksum == 0xaf86421b )\t// checksum of \"Crown\"\r\n\t\t\t\t{\r\n\t\t\t\t\t// We want the Nth crown spawn pt\r\n\t\t\t\t\tif( spawn_pt == 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSkateScript::GetPosition( pNode, &pos );\r\n\t\t\t\t\t\tcrown->SetPosition( pos );\r\n#if 1\r\n\t\t\t\t\t\tnode_found = true;\r\n#endif\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tspawn_pt--;\r\n\t\t\t\t}\r\n\t\t\t\ti++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tcrown->RemoveFromKing();\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* The player has dropped a ctf flag.  Relocate it.\t\t\t\t  */\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_dropped_flag( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\tMsgFlagMsg* msg;\r\n\tPlayerInfo* player, *local_player;\r\n\r\n\tgamenet_man = (Manager*) context->m_Data;\r\n\tmsg = (MsgFlagMsg*) context->m_Msg;\r\n\tplayer = gamenet_man->GetPlayerByObjectID( msg->m_ObjId );\r\n\tif( player && player->HasCTFFlag())\r\n\t{\r\n\t\tchar team_str[64];\r\n\t\tint team;\r\n\t\tScript::CStruct* pParams;\r\n\t\t\r\n\t\tteam = player->HasWhichFlag();\r\n\t\tsprintf( team_str, \"team_%d_name\", team + 1 );\r\n\t\tpParams = new Script::CStruct;\r\n\r\n\t\tpParams->AddInteger( \"team\", team );\r\n\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\tScript::RunScript( \"flag_returned\", pParams );\r\n\r\n\t\tdelete pParams;\r\n\r\n\t\t// If it's me, remove the message that says \"return the flag to your base\"\r\n\t\tif( player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tScript::RunScript( \"destroy_ctf_panel_message\" );\r\n\t\t}\r\n\r\n\t\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\t\tif( local_player && !local_player->IsObserving())\r\n\t\t{\r\n\t\t\tif( local_player->m_Team == team )\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( \"hide_ctf_arrow\" );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tplayer->ClearCTFState();\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Streams the level data to the client    \t\t\t\t\t\t  */\r\n/*                                                 \t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_request_level( Net::MsgHandlerContext* context )\r\n{\r\n\tNet::Server* server;\r\n\tMsgRequestLevel* msg;\r\n\tManager* gamenet_man;\r\n\tPlayerInfo* player;\r\n\r\n\tgamenet_man = (Manager*) context->m_Data;\r\n\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tmsg = (MsgRequestLevel*) context->m_Msg;\r\n\t\t \r\n\tserver = (Net::Server*) context->m_App;\r\n\tDbg_Printf( \"************** STREAMING LEVEL DATA ***************\\n\" );\r\n\t\r\n\tserver->StreamMessage( context->m_Conn->GetHandle(), MSG_ID_LEVEL_DATA, Ed::CParkManager::COMPRESSED_MAP_SIZE, \r\n\t\t\t\t\t\t   Ed::CParkManager::sInstance()->GetCompressedMapBuffer(), \"level data\", vSEQ_GROUP_PLAYER_MSGS,\r\n\t\t\t\t\t\t   false, true );\r\n\t\t\t\t\t\t   \r\n\tserver->StreamMessage( context->m_Conn->GetHandle(), MSG_ID_RAIL_DATA, Obj::GetRailEditor()->GetCompressedRailsBufferSize(), \r\n\t\t\t\t\t\t   Obj::GetRailEditor()->GetCompressedRailsBuffer(), \"rail data\", vSEQ_GROUP_PLAYER_MSGS,\r\n\t\t\t\t\t\t   false, true );\r\n\t\t\t\t\t\t   \r\n\t\t\t\t\t\t   \r\n\tif( gamenet_man->UsingCreatedGoals())\r\n\t{\r\n\t\tgamenet_man->LoadGoals( msg->m_LevelId );\r\n\t\tserver->StreamMessage( context->m_Conn->GetHandle(), MSG_ID_GOALS_DATA, gamenet_man->GetGoalsDataSize(),\r\n\t\t\t\t\t\t\t   gamenet_man->GetGoalsData(), \"goals data\", vSEQ_GROUP_PLAYER_MSGS, false, true );\r\n\t}\r\n\r\n\tif( msg->m_Source == MSG_ID_CHANGE_LEVEL )\r\n\t{\r\n\t\tGameNet::MsgReady ready_msg;\r\n\t\tMsgChangeLevel change_msg;\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tDbg_Printf( \"************** SENDING CHANGE LEVEL DATA ***************\\n\" );\r\n\t\t\t\r\n\t\tchange_msg.m_Level = msg->m_LevelId;\r\n\t\tchange_msg.m_ShowWarning = 0;\r\n\t\t\t\r\n\t\tready_msg.m_Time = Tmr::GetTime();\r\n\r\n\t\tmsg_desc.m_Data = &change_msg;\r\n\t\tmsg_desc.m_Length = sizeof(MsgChangeLevel);\r\n\t\tmsg_desc.m_Id = MSG_ID_CHANGE_LEVEL;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\r\n\t\t// Don't send them any non-important messages until they're finished loading\r\n\t\tmsg_desc.m_Data = &ready_msg;\r\n\t\tmsg_desc.m_Length = sizeof(MsgReady);\r\n\t\tmsg_desc.m_Id = MSG_ID_READY_QUERY;\r\n\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t\t\t\r\n\t\tplayer->MarkAsNotReady( ready_msg.m_Time );\r\n\t\t\r\n\t\tserver->SendData();\t\t// Mick, (true) because we want to send it immediatly\r\n\t\t\r\n#ifdef __PLAT_NGPS__\r\n\t\t//server->WaitForAsyncCallsToFinish();\r\n#endif\r\n\t} \r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Handles level data from server    \t\t\t\t\t\t  \t  */\r\n/*                                                 \t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_level_data( Net::MsgHandlerContext* context )\r\n{\r\n    Dbg_Printf( \"received streamed message! size %d\\n\", (int)context->m_MsgLength ); \r\n\t\r\n\tEd::CParkManager::sInstance()->SetCompressedMapBuffer((uint8*) context->m_Msg, true );\r\n\r\n\tuint32 crc;\r\n\tcrc = Crc::GenerateCRCCaseSensitive((char*) Ed::CParkManager::sInstance()->GetCompressedMapBuffer(), Ed::CParkManager::COMPRESSED_MAP_SIZE );\r\n\tDbg_Printf( \"******************** CHECKSUM OF MAP : %08x\\n\", crc );\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Handles rail data from server    \t\t\t\t\t\t  \t  */\r\n/*                                                 \t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_rail_data( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man = (Manager*) context->m_Data;\r\n    \r\n\tDbg_Printf( \"received streamed message! size %d\\n\", (int)context->m_MsgLength ); \r\n\r\n\tif( context->m_PacketFlags & Net::mHANDLE_CRC_MISMATCH )\r\n\t{\r\n\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tif( skate_mod->m_cur_level == CRCD(0x9f2bafb7,\"Load_Skateshop\"))\r\n\t\t{\r\n\t\t\tScript::CStruct* params;\r\n\r\n\t\t\tparams = new Script::CStruct;\r\n\t\t\tparams->AddChecksum( NONAME, CRCD(0x19eca78e,\"show_timeout\"));\r\n\r\n\t\t\t// Set it back to the joining state so that cancel_join_server does not\r\n\t\t\t// opt out early\r\n\t\t\tgamenet_man->m_join_state_task->Remove();\r\n\t\t\tgamenet_man->SetJoinState( vJOIN_STATE_JOINING );\r\n\r\n\t\t\tDbg_Printf( \"************** received bad rails data!! Cancelling join.\\n\" );\r\n\t\t\tScript::RunScript( CRCD(0x60b653db,\"cancel_join_server\" ), params );\r\n\t\t\tdelete params;\r\n\r\n\t\t\treturn Net::HANDLER_MSG_DESTROYED;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Printf( \"************** received bad rails data!! Re-requesting it.\\n\" );\r\n\t\t\tDbg_Printf( \"*** Level was 0x%x : %s\\n\", skate_mod->m_cur_level, Script::FindChecksumName(skate_mod->m_cur_level));\r\n\r\n\t\t\tmsg_desc.m_Id = MSG_ID_REQUEST_RAILS_DATA;\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\r\n\t\t\tcontext->m_App->EnqueueMessageToServer( &msg_desc );\r\n\r\n\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t}\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t\r\n\tObj::GetRailEditor()->SetCompressedRailsBuffer((uint8*) context->m_Msg);\r\n    \r\n    // InitUsingCompressedRailsBuffer will do an initial cleanup of any existing rails, which may result in\r\n    // a call to UpdateSuperSectors (due to sectors being deleted).  \r\n    // Trouble is, UpdateSuperSectors will cause the park to disappear from under the skater, so disable\r\n    // it temporarily.\r\n   \r\n\tObj::CRailEditorComponent::sUpdateSuperSectorsAfterDeletingRailSectors=false;   \r\n    Obj::GetRailEditor()->InitUsingCompressedRailsBuffer();\r\n\tObj::CRailEditorComponent::sUpdateSuperSectorsAfterDeletingRailSectors=true;\r\n\t\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Handles goals data from server    \t\t\t\t\t\t  \t  */\r\n/*                                                 \t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_goals_data( Net::MsgHandlerContext* context )\r\n{\r\n\tuint32 level;\r\n\tuint8* goals_data;\r\n\tManager* gamenet_man;\r\n\tScript::CStruct* params;\r\n\tNet::MsgDesc msg_desc;\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\r\n\tDbg_Printf( \"received goals data\\n\" );\r\n\tif( context->m_PacketFlags & Net::mHANDLE_CRC_MISMATCH )\r\n\t{\r\n\t\tif( skate_mod->m_cur_level == CRCD(0x9f2bafb7,\"Load_Skateshop\"))\r\n\t\t{\r\n\t\t\tScript::CStruct* params;\r\n\t\t\tDbg_Printf( \"************** received bad goals data!! Cancelling join server.\\n\" );\r\n\r\n\t\t\t// Set it back to the joining state so that cancel_join_server does not\r\n\t\t\t// opt out early\r\n\t\t\tgamenet_man->m_join_state_task->Remove();\r\n\t\t\tgamenet_man->SetJoinState( vJOIN_STATE_JOINING );\r\n\r\n\t\t\tparams = new Script::CStruct;\r\n\t\t\tparams->AddChecksum( NONAME, CRCD(0x19eca78e,\"show_timeout\"));\r\n\t\t\tScript::RunScript( CRCD(0x60b653db,\"cancel_join_server\" ), params );\r\n\t\t\tdelete params;\r\n\t\t\treturn Net::HANDLER_MSG_DESTROYED;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Printf( \"************** received bad goals data!! Re-requesting it.\\n\" );\r\n\t\t\t\r\n\t\t\tmsg_desc.m_Id = MSG_ID_REQUEST_GOALS_DATA;\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\r\n\t\t\tcontext->m_App->EnqueueMessageToServer( &msg_desc );\r\n\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t}\r\n\t}\r\n\t\r\n\tmemcpy( &level, context->m_Msg, sizeof( uint32 ));\r\n\r\n\t//Dbg_Printf( \"*** Level: 0x%x  requested level: 0x%x\\n\", level, Mdl::Skate::Instance()->m_requested_level );\r\n\t//skate_mod->m_requested_level = level;\r\n\t//skate_mod->m_cur_level = level;\r\n\r\n\tgoals_data = (uint8*) ( context->m_Msg + sizeof( uint32 ));\r\n\tObj::GetGoalEditor()->ReadFromBuffer( level, goals_data );\r\n\r\n\t\r\n\r\n\tparams = new Script::CStruct;\r\n\tparams->AddChecksum( NONAME, CRCD(0x88001327,\"DoNotCreateGoalPeds\"));\r\n\tScript::RunScript( CRCD(0x6f4180d0,\"InitialiseCreatedGoals\"), params );\r\n\tdelete params;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Handles any sort of change of level. Makes sure we actually    */\r\n/* Have that level                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_new_level( Net::MsgHandlerContext* context )\r\n{\r\n\tDbg_Printf( \"***************** Handling new level!!!\\n\" );\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_change_level( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\tMsgChangeLevel* pMsg;\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\t\r\n\tpMsg = (MsgChangeLevel*) context->m_Msg;\r\n\t\r\n\tDbg_Printf( \"********** GameNet:: Got change level\\n\" );\r\n\tgamenet_man->ClearTriggerEventList();\r\n\tgamenet_man->m_game_over = false;\r\n\t\r\n\tif( pMsg->m_ShowWarning )\r\n\t{\r\n\t\tDbg_Printf( \"******** GameNet:: IN NET GAME!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\\n\" );\r\n\t\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\t\t\t\t\r\n\t\t// Don't allow two quick change level commands\r\n\t\tif( gamenet_man->m_change_level_task->InList())\r\n\t\t{\r\n\t\t\tif( !gamenet_man->OnServer())\r\n\t\t\t{\r\n\t\t\t\tgamenet_man->m_level_id = pMsg->m_Level;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t}\r\n\r\n\t\tgamenet_man->m_level_id = pMsg->m_Level;\r\n\t\ts_time_change_level = Tmr::GetTime() + vTIME_BEFORE_CHANGING_LEVEL;\r\n\r\n\t\tif( gamenet_man->OnServer())\r\n\t\t{                                    \r\n\t\t\tScript::CScriptStructure* pTempStructure;\r\n\t\t\tPrefs::Preferences* pPreferences;\r\n\t\t\t\r\n\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \r\n\t\t\t\t\t\t\t\t\t\t  gamenet_man->GetLevelName( false ));\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, (int) gamenet_man->m_level_id );\r\n\t\t\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\t\t\tpPreferences->SetPreference( Script::GenerateCRC( \"level\"), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\t// Allow a little extra time for the transmission of level data\r\n\t\t\tif( gamenet_man->m_level_id == CRCD(0xb664035d,\"Load_Sk5Ed_gameplay\"))\r\n\t\t\t{\r\n\t\t\t\ts_time_change_level += Tmr::Seconds( 1 );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\t\r\n\t\tmlp_man->AddLogicTask( *gamenet_man->m_change_level_task );\r\n\r\n\t\tgamenet_man->CreateNetPanelMessage( false, Script::GenerateCRC(\"net_message_changing_levels\"),\r\n\t\t\t\t\t\t\t\t\t\t\tgamenet_man->GetLevelName(), NULL, NULL, NULL, false, Tmr::Seconds( 5 ));\r\n\t\t\r\n\t\tScript::RunScript(\"hide_console_window\");\r\n\t\t// Don't let this message pass through the Skate. We don't want to change levels just yet\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_kill_flags( Net::MsgHandlerContext* context )\r\n{\r\n\tScript::RunScript( \"Kill_Team_Flags\" );\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_game_info( Net::MsgHandlerContext* context )\r\n{   \r\n    Manager* gamenet_man;\r\n\tMsgGameInfo* msg;\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tScript::CArray* mode_array;\r\n\tint i;\r\n    \r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\tmsg = (MsgGameInfo*) context->m_Msg;\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\r\n\tDbg_Printf( \"Got game info\\n\" );\r\n\r\n\tgamenet_man->SetSkaterStartingPoints( msg->m_StartPoints );\r\n\tgamenet_man->m_crown_spawn_point = msg->m_CrownSpawnPoint;\r\n\tgamenet_man->m_waiting_for_game_to_start = false;\r\n\r\n\t// Invalidate old positions. Player will be re-added to the world when we get a\r\n\t// sufficient number of object updates\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t{\r\n\t\tif( player->IsLocalPlayer() == false )\r\n\t\t{\r\n\t\t\tplayer->m_Skater->RemoveFromCurrentWorld();\r\n\t\t\tplayer->m_Skater->Resync();\r\n\t\t}\r\n\t}\r\n\r\n\t// set up the game mode for the client cause we're now in the lobby\r\n\t// anything that's lobby-dependent should go after this line\r\n\tskate_mod->GetGameMode()->LoadGameType( msg->m_GameMode );\r\n\t\r\n\t// Remove all currently-running goals\r\n\tskate_mod->GetGoalManager()->DeactivateAllGoals();\t\r\n\r\n\tif( gamenet_man->InNetGame())\r\n\t{\r\n\t\tmode_array = Script::GetArray( \"net_game_type_info\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmode_array = Script::GetArray( \"mp_game_type_info\" );\r\n\t}\r\n\t\r\n\tDbg_Assert( mode_array );\r\n\r\n\t{\r\n\t\tScript::CScriptStructure* pTempStructure = new Script::CScriptStructure;\r\n\r\n\t\t// In king of the hill, interpret time limit as a target time\r\n\t\tif(\t( msg->m_TimeLimit == 0 ) &&\r\n\t\t\t( msg->m_GameMode != Script::GenerateCRC( \"netgoalattack\" )))\r\n\t\t{\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"default_time_limit\"), ESYMBOLTYPE_INTEGER, (int) 0 );\r\n\t\t\tif( ( msg->m_GameMode != CRCD(0x3d6d444f,\"firefight\")) &&\r\n\t\t\t\t( msg->m_GameMode != CRCD(0xbff33600,\"netfirefight\")))\r\n\t\t\t{\r\n\t\t\t\tScript::CArray* pArray = new Script::CArray;\r\n\t\t\t\tScript::CopyArray(pArray,Script::GetArray(\"targetScoreArray\") );\r\n\t\t\t\tScript::CScriptStructure* pSubStruct = pArray->GetStructure(0);\r\n\t\t\t\tDbg_Assert(pSubStruct);\r\n\t\t\t\tpSubStruct->AddComponent(Script::GenerateCRC(\"score\"),ESYMBOLTYPE_INTEGER, msg->m_TargetScore );\r\n\t\t\t\t\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"victory_conditions\"), pArray );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"default_time_limit\"), ESYMBOLTYPE_INTEGER, (int) msg->m_TimeLimit );\r\n\t\t\t\r\n\t\t\tif( msg->m_GameMode == Script::GenerateCRC( \"netctf\" ))\r\n\t\t\t{\r\n\t\t\t\tScript::CArray* pArray = new Script::CArray;\r\n\t\t\t\tScript::CopyArray(pArray,Script::GetArray(\"highestScoreArray\") );\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"victory_conditions\"), pArray );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tDbg_Printf( \"***** GOT FIREBALL LEVEL OF %d\\n\", msg->m_FireballLevel );\r\n\t\tpTempStructure->AddComponent( CRCD(0xce87e4e3,\"fireball_level\"), ESYMBOLTYPE_INTEGER, msg->m_FireballLevel );\r\n\t\tpTempStructure->AddComponent( CRCD(0x48e748b5,\"stop_at_zero\"), ESYMBOLTYPE_INTEGER, msg->m_StopAtZero );\r\n\t    Dbg_Printf( \"******************** Setting time limit to %d\\n\", (int)msg->m_TimeLimit );\r\n\t\tskate_mod->SetTimeLimit( msg->m_TimeLimit );\r\n\t\tskate_mod->GetGameMode()->OverrideOptions( pTempStructure );\r\n\t\tskate_mod->GetGameMode()->SetNumTeams( msg->m_TeamMode );\r\n\t\tdelete pTempStructure;\r\n\t}\r\n\r\n\tScript::RunScript( \"StartingNewNetGame\" );\r\n\t\r\n\t// the following sets up the panel and stuff\r\n\tskate_mod->LaunchGame();\r\n\tgamenet_man->ResetPlayers();\r\n\tgamenet_man->m_game_pending = false;\r\n\tgamenet_man->m_cheating_occurred = false;\r\n\tgamenet_man->MarkReceivedFinalScores( false );\r\n\tgamenet_man->SetCurrentLeader( NULL );\r\n\tgamenet_man->SetCurrentLeadingTeam( vNO_TEAM );\r\n\tgamenet_man->SetNetworkGameId( msg->m_GameId );\r\n\tif( msg->m_GameMode == Script::GenerateCRC( \"netgoalattack\" ))\r\n\t{\r\n\t\tskate_mod->GetGoalManager()->InitializeAllSelectedGoals();\r\n\t}\r\n\tgamenet_man->m_game_over = false;\r\n\t\r\n\t// Clear all scores\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tMdl::Score* score;\r\n\t\t\r\n\t\tplayer->ClearCTFState();\r\n\t\tplayer->ResetProjectileVulnerability();\r\n\t\tif( player->m_Skater )\r\n\t\t{\r\n\t\t\tObj::CSkaterScoreComponent* p_skater_score_component = GetSkaterScoreComponentFromObject(player->m_Skater);\r\n\t\t\tDbg_Assert(p_skater_score_component);\r\n\t\t\tscore = p_skater_score_component->GetScore();\r\n\t\t\tif( score )\r\n\t\t\t{\r\n\t\t\t\tscore->Reset();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n    \r\n\t// Clear king of the hill data\r\n\tplayer = gamenet_man->GetKingOfTheHill();\r\n\tif( player )\r\n\t{\r\n\t\tplayer->MarkAsKing( false );\r\n\t}\r\n\t\r\n\tfor( i = 0; i < (int)mode_array->GetSize(); i++ )\r\n\t{   \r\n\t\tuint32 value, script;\r\n\t\tScript::CStruct* mode_struct;\r\n\t\t \r\n\t\tmode_struct = mode_array->GetStructure( i );\r\n\t\tDbg_Assert( mode_struct );\r\n\t\t\r\n\t\tmode_struct->GetChecksum( \"checksum\", &value, true );\r\n\t\tif( value == msg->m_GameMode )\r\n\t\t{\r\n\t\t\tScript::CStruct* params;\r\n\t\t\t\t\t\t\r\n\t\t\tparams = new Script::CStruct;\r\n\t\t\tparams->AddInteger( \"time\", msg->m_TimeLimit );\r\n\t\t\tparams->AddInteger( \"score\", msg->m_TargetScore );\r\n\t\t\tif( msg->m_TimeLimit == 0 )\r\n\t\t\t{\r\n\t\t\t\tparams->AddInteger( CRCD(0xf0e712d2,\"unlimited_time\"), 1 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tparams->AddInteger( CRCD(0xf0e712d2,\"unlimited_time\"), 0 );\r\n\t\t\t}\r\n\t\t\tmode_struct->GetChecksum( \"goal_script\", &script, true );\r\n\t\t\tScript::RunScript( script, params );\r\n\t\t\tdelete params;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_select_goals( Net::MsgHandlerContext* context )\r\n{\r\n\tNet::MsgMax* msg;\r\n\tGame::CGoalManager* pGoalManager;\r\n\tGame::CGoal* pGoal;\r\n\tchar* data;\r\n\tuint32 goal_id;\r\n\tchar show_summary;\r\n\t\t\r\n\tmsg = (Net::MsgMax*) context->m_Msg;\t \r\n\tdata = msg->m_Data;\r\n\tpGoalManager = Game::GetGoalManager();\r\n\tpGoalManager->DeselectAllGoals();\r\n\tshow_summary = *data++;\r\n\tmemcpy( &goal_id, data, sizeof( uint32 ));\r\n\tdata+= sizeof( uint32 );\r\n\twhile( goal_id )\r\n\t{\r\n\t\tpGoal = pGoalManager->GetGoal( goal_id );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tpGoal->UnBeatGoal();\r\n\t\tpGoal->Select();\r\n\t\t\r\n\t\tmemcpy( &goal_id, data, sizeof( uint32 ));\r\n\t\tdata+= sizeof( uint32 );\r\n\t}\r\n\r\n\tif( show_summary == 1 )\r\n\t{\r\n\t\tScript::CStruct* pParams;\r\n\t\tpParams = new Script::CStruct;\r\n\t\tpParams->AddChecksum( \"goal_summary\", Script::GenerateCRC( \"goal_summary\" ));\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tScript::CScript *p_script=Script::SpawnScript( \"wait_and_create_view_selected_goals_menu\", pParams );\r\n\t\tp_script->SetCommentString(\"Spawned from Manager::s_handle_select_goals\");\r\n\t\t#else\r\n\t\tScript::SpawnScript( \"wait_and_create_view_selected_goals_menu\", pParams );\r\n\t\t#endif\r\n\t\tdelete pParams;\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_panel_message( Net::MsgHandlerContext* context )\r\n{\r\n    GameNet::MsgPanelMessage *msg;\r\n\tManager* gamenet_man;\r\n    \r\n\tmsg = (GameNet::MsgPanelMessage*) context->m_Msg;\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\t\r\n\tgamenet_man->CreateNetPanelMessage( false, msg->m_StringId, msg->m_Parm1, msg->m_Parm2, NULL, NULL, false, msg->m_Time );\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_run_ended( Net::MsgHandlerContext* context )\r\n{   \r\n\tManager* gamenet_man;\r\n\tPlayerInfo* player;\r\n\tbool all_done;\r\n\tunsigned char game_id;\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tmemcpy( &game_id, context->m_Msg, sizeof( unsigned char ));\r\n\t//Dbg_Printf( \"**** Got end of run from player\\n\" );\r\n\r\n\tif( player )\r\n\t{\r\n\t\tLst::Search< PlayerInfo > sh;\r\n\t\tif( player->m_flags.TestMask( PlayerInfo::mRUN_ENDED ))\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"**** Run had already ended\\n\" );\r\n\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t}\r\n\r\n\t\t// Make sure this message pertains to the current game\r\n\t\tif( game_id != gamenet_man->GetNetworkGameId())\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"**** Wrong game id\\n\" );\r\n\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t}\r\n\t\t\r\n\t\tplayer->m_flags.SetMask( PlayerInfo::mRUN_ENDED );\r\n\t\t\r\n\t\tall_done = true;\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player;\r\n\t\t\t\tplayer = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tif( !player->m_flags.TestMask( PlayerInfo::mRUN_ENDED))\r\n\t\t\t{\r\n\t\t\t\tall_done = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( all_done )\r\n\t\t{\r\n\t\t\tNet::Server* server;\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\tserver = gamenet_man->GetServer();\r\n\t\t\tDbg_Assert( server );\r\n\r\n\t\t\tmsg_desc.m_Id = MSG_ID_GAME_OVER;\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player;\r\n\t\t\t\tplayer = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"**** Not all done id\\n\" );\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_game_over( Net::MsgHandlerContext* context )\r\n{   \r\n\tManager* gamenet_man;\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tgamenet_man->MarkGameOver();\r\n\r\n\tif( ( CFuncs::ScriptIsObserving( NULL, NULL )) &&\r\n\t\t( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0xec200eaa,\"netgoalattack\" )))\r\n\t{\r\n\t\tScript::RunScript( CRCD(0xfce4f72d,\"create_rankings\"));\r\n\t}\r\n\t\r\n\t//Script::RunScript( \"set_lobby_mode\" );\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_end_game( Net::MsgHandlerContext* context )\r\n{   \r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CTrickObjectManager* manager = skate_mod->GetTrickObjectManager();\r\n\r\n\tmanager->DeleteAllTrickObjects();\r\n\tScript::RunScript( \"create_game_ended_dialog\" );\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Just calculate the length of the message and pass it back to   */\r\n/* the dispatcher                                                 */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_object_update( Net::MsgHandlerContext* context )\r\n{   \r\n\tManager* gamenet_man;\r\n\tint update_flags;\r\n\tunsigned char obj_id, obj_id_mask;\r\n\tNet::BitStream stream;\r\n    \r\n\tDbg_Assert( context );\r\n     \r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tstream.SetInputData( context->m_Msg, 1024 );\r\n\tobj_id_mask = stream.ReadUnsignedValue( sizeof( char ) * 8 );\r\n\t\t\r\n\tfor( obj_id = 0; obj_id < Mdl::Skate::vMAX_SKATERS; obj_id++ )\r\n\t{\r\n\t\tint value;\r\n\r\n\t\t// If the bit for this player number is not set, that means there is no \r\n\t\t// object update for them. Continue\r\n\t\tif(( obj_id_mask & ( 1 << obj_id )) == 0 )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tvalue = stream.ReadUnsignedValue( sizeof( uint16 ) * 8 );\r\n\t\t//Dbg_Printf( \"Length after timestamp: %d\\n\", stream.GetByteLength());\r\n\t\t\r\n\t\tupdate_flags = stream.ReadUnsignedValue( 9 );\r\n\t\t//Dbg_Printf( \"Length after update flags: %d\\n\", stream.GetByteLength());\r\n\t\t\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_X )\r\n\t\t{   \r\n\t\t\tvalue = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t\t//Dbg_Printf( \"Length after pos X: %d\\n\", stream.GetByteLength());\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_Y )\r\n\t\t{\r\n\t\t\tvalue = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t\t//Dbg_Printf( \"Length after pos Y: %d\\n\", stream.GetByteLength());\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_Z )\r\n\t\t{\r\n\t\t\tvalue = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t\t//Dbg_Printf( \"Length after pos Z: %d\\n\", stream.GetByteLength());\r\n\t\t}   \r\n\t\t\t\t\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_X )\r\n\t\t{\r\n\t\t\tvalue = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t\t//Dbg_Printf( \"Length after rot X: %d\\n\", stream.GetByteLength());\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_Y )\r\n\t\t{\r\n\t\t\tvalue = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t\t//Dbg_Printf( \"Length after rot Y: %d\\n\", stream.GetByteLength());\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_Z )\r\n\t\t{\r\n\t\t\tvalue = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t\t//Dbg_Printf( \"Length after rot Z: %d\\n\", stream.GetByteLength());\r\n\t\t}\r\n        \r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_STATE )\r\n\t\t{   \r\n\t\t\tvalue = stream.ReadUnsignedValue( 4 );\r\n\t\t\t//Dbg_Printf( \"Length after state1: %d\\n\", stream.GetByteLength());\r\n\t\t\tvalue = stream.ReadUnsignedValue( 6 );\r\n\t\t\tvalue = stream.ReadUnsignedValue( 1 );\r\n\t\t\tvalue = stream.ReadUnsignedValue( 1 );\r\n\t\t\t//Dbg_Printf( \"Length after state2: %d\\n\", stream.GetByteLength());\r\n\t\t}\r\n\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_FLAGS )\r\n\t\t{\r\n\t\t\tvalue = stream.ReadUnsignedValue( 8 );\r\n\t\t\t//Dbg_Printf( \"Length after flags: %d\\n\", stream.GetByteLength());\r\n\t\t}\r\n\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_RAIL_NODE )\r\n\t\t{\r\n\t\t\tvalue = stream.ReadSignedValue( sizeof( sint16 ) * 8 );\r\n\t\t\t//Dbg_Printf( \"Length After Rail Node: %d\\n\", stream.GetByteLength());\r\n\t\t}\r\n\t}\r\n\t\t\t\r\n\t// Tell the dispatcher the size of this message because it does not know (optimization)\r\n\tcontext->m_MsgLength = stream.GetByteLength();\r\n\t//Dbg_Printf( \"Message Length %d\\n\", context->m_MsgLength );\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Someone has requested to change teams\t\t\t\t\t\t  */\r\n/*                                                  \t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_team_change_request( Net::MsgHandlerContext* context )\r\n{\r\n\tManager* gamenet_man;\r\n\tPlayerInfo* change_player, *player;\r\n\tMsgChangeTeam* msg;\r\n\tNet::Server* server;\r\n\tMsgChangeTeam change_msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\t\r\n\tmsg = (MsgChangeTeam*) context->m_Msg;\r\n\tchange_player = gamenet_man->GetPlayerByObjectID( msg->m_ObjID );\r\n\tif(( change_player == NULL ) ||\r\n\t   ( change_player->m_Skater == NULL ) ||\r\n\t   ( skate_mod->GetGameMode()->GetNameChecksum() != Script::GenerateCRC( \"netlobby\" )))\t// ignore unless in lobby\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\tchange_msg.m_ObjID = msg->m_ObjID;\r\n\tchange_msg.m_Team = msg->m_Team;\r\n\r\n\tserver = gamenet_man->GetServer();\r\n\tDbg_Assert( server );\r\n\r\n\tmsg_desc.m_Data = &change_msg;\r\n\tmsg_desc.m_Length = sizeof( MsgChangeTeam );\r\n\tmsg_desc.m_Id = MSG_ID_TEAM_CHANGE;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; \r\n\t\t\t\tplayer = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Someone has changed teams  \t\t\t\t\t\t\t\t\t  */\r\n/*                                                  \t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_team_change( Net::MsgHandlerContext* context )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tManager* gamenet_man;\r\n\tPlayerInfo* player, *other_player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tMsgChangeTeam* msg;\r\n\tint num_other_players;\r\n\t\t\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tmsg = (MsgChangeTeam*) context->m_Msg;\r\n\t\r\n\tplayer = gamenet_man->GetPlayerByObjectID( msg->m_ObjID );\r\n\tif( player )\r\n\t{\r\n\t\tchar team_str[64];\r\n\t\tScript::CStruct* pParams;\r\n\t\tbool all_same_team;\r\n\t\t\r\n\t\tplayer->m_Team = msg->m_Team;\r\n\t\tsprintf( team_str, \"team_%d_name\", msg->m_Team + 1 );\r\n\t\tpParams = new Script::CStruct;\r\n\t\tif( player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tif( skate_mod->GetGameMode()->IsTeamGame())\r\n\t\t\t{\r\n\t\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\t\t\tScript::RunScript( \"joined_team_you\", pParams );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif( skate_mod->GetGameMode()->IsTeamGame())\r\n\t\t\t{\r\n\t\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, player->m_Name );\r\n\t\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String1\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\t\t\tScript::RunScript( \"joined_team_other\", pParams );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tdelete pParams;\r\n\r\n\t\tall_same_team = true;\r\n\t\tnum_other_players = 0;\r\n\t\tfor( other_player = gamenet_man->FirstPlayerInfo( sh ); other_player; \r\n\t\t\t\tother_player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tif( other_player != player )\r\n\t\t\t{\r\n\t\t\t\tnum_other_players++;\r\n\t\t\t\tif( msg->m_Team != other_player->m_Team )\r\n\t\t\t\t{\r\n\t\t\t\t\tall_same_team = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( all_same_team && ( num_other_players > 0 ))\r\n\t\t{\r\n\t\t\tif( skate_mod->GetGameMode()->NumTeams() > 0 )\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( CRCD(0x16c9b0dc,\"warn_all_same_team\"));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Client beat a goalattack goal. Verify that no other teammate\t  */\r\n/* has beaten it and relay it to all clients involved  \t\t\t  */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_beat_goal( Net::MsgHandlerContext* context )\r\n{\r\n\tMsgBeatGoal *msg;\r\n\tManager* gamenet_man;\r\n\tGame::CGoalManager* pGoalManager;\r\n\tGame::CGoal* pGoal;    \r\n\t\t\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tmsg = (MsgBeatGoal*) context->m_Msg;\r\n    \r\n\tDbg_Printf( \"*** Got s_handle_beat_goal: 0x%x\\n\", msg->m_GoalId );\r\n\t// Make sure this message pertains to the current game\r\n\tif( msg->m_GameId != gamenet_man->GetNetworkGameId())\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\tpGoalManager = Game::GetGoalManager();\r\n\tpGoal = pGoalManager->GetGoal( msg->m_GoalId );\r\n\tif( pGoal )\r\n\t{\r\n\t\tPlayerInfo* player;\r\n\t\tbool already_beaten;\r\n\r\n\t\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\t\tDbg_Assert( player );\r\n\r\n\t\talready_beaten = false;\r\n\t\tif( player->m_Skater )\r\n\t\t{   \r\n\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\t\t\t// If we're in a team game, flag the goal as completed for all team members just in case someone quits later.\r\n\t\t\t// Also, uninitialize the goal\r\n\t\t\tif( skate_mod->GetGameMode()->IsTeamGame())\r\n\t\t\t{\r\n\t\t\t\tPlayerInfo* team_player;\r\n\t\t\t\tLst::Search< PlayerInfo > sh;\r\n\r\n\t\t\t\tfor( team_player = gamenet_man->FirstPlayerInfo( sh ); team_player; \r\n\t\t\t\t\t\tteam_player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t\t\t{\r\n\t\t\t\t\tif( player->m_Team == team_player->m_Team )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( pGoal->HasWonGoal( team_player->m_Skater->GetID()))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\talready_beaten = true;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif( !already_beaten )\r\n\t\t\t\t{\r\n\t\t\t\t\tpGoal->MarkBeatenBy( player->m_Skater->GetID());\r\n\t\t\t\t\t// Notify all team members of the fact that the goal was beaten\r\n\t\t\t\t\tfor( team_player = gamenet_man->FirstPlayerInfo( sh ); team_player; \r\n\t\t\t\t\t\t\tteam_player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMsgBeatGoalRelay goal_msg;\r\n\t\t\t\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t\t\t\tgoal_msg.m_GoalId = msg->m_GoalId;\r\n\t\t\t\t\t\tgoal_msg.m_ObjId = player->m_Skater->GetID();\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tmsg_desc.m_Data = &goal_msg;\r\n\t\t\t\t\t\tmsg_desc.m_Length = sizeof( MsgBeatGoalRelay );\r\n\t\t\t\t\t\tmsg_desc.m_Id = MSG_ID_BEAT_GOAL;\r\n\t\t\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tcontext->m_App->EnqueueMessage( team_player->GetConnHandle(), &msg_desc );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( pGoal->HasWonGoal( player->m_Skater->GetID()) == false )\r\n\t\t\t\t{\r\n\t\t\t\t\tPlayerInfo* send_player;\r\n\t\t\t\t\tLst::Search< PlayerInfo > sh;\r\n\t\t\t\t\tMsgBeatGoalRelay goal_msg;\r\n\t\t\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t\t\tpGoal->MarkBeatenBy( player->m_Skater->GetID());\r\n\r\n\t\t\t\t\tgoal_msg.m_GoalId = msg->m_GoalId;\r\n\t\t\t\t\tgoal_msg.m_ObjId = player->m_Skater->GetID();\r\n\r\n\t\t\t\t\tmsg_desc.m_Data = &goal_msg;\r\n\t\t\t\t\tmsg_desc.m_Length = sizeof( MsgBeatGoalRelay );\r\n\t\t\t\t\tmsg_desc.m_Id = MSG_ID_BEAT_GOAL;\r\n\t\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\t\tfor( send_player = gamenet_man->FirstPlayerInfo( sh ); send_player; \r\n\t\t\t\t\t\t\tsend_player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontext->m_App->EnqueueMessage( send_player->GetConnHandle(), &msg_desc );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Client beat a goalattack goal\t\t\t\t\t\t  \t  \t  */\r\n/*                                                  \t\t\t  */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_beat_goal_relay( Net::MsgHandlerContext* context )\r\n{\r\n\tMsgBeatGoalRelay *msg;\r\n\tManager* gamenet_man;\r\n\tGame::CGoalManager* pGoalManager;\r\n\tGame::CGoal* pGoal, *pCurrentGoal;\r\n\tint current_goal_index;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n    \r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tmsg = (MsgBeatGoalRelay*) context->m_Msg;\r\n    \r\n\tpGoalManager = Game::GetGoalManager();\r\n\tpGoal = pGoalManager->GetGoal( msg->m_GoalId );\r\n\tpCurrentGoal = NULL;\r\n\tcurrent_goal_index = pGoalManager->GetActiveGoal( true );\r\n\tif( current_goal_index >= 0 )\r\n\t{\r\n\t\tpCurrentGoal = pGoalManager->GetGoalByIndex( current_goal_index );\r\n\t}\r\n\r\n\tif( pGoal )\r\n\t{\r\n\t\tPlayerInfo* local_player, *player;\r\n\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( msg->m_ObjId );\r\n\t\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\t\tDbg_Assert( player );\r\n\r\n\t\tpGoal->MarkBeatenByTeam( player->m_Team );\r\n\r\n\t\tif( player->m_Skater )\r\n\t\t{\r\n\t\t\tpGoal->MarkBeatenBy( player->m_Skater->GetID());\r\n\r\n\t\t\t// If it's not us, it must be a teammate\r\n\t\t\tif( local_player == player )\r\n\t\t\t{\r\n\t\t\t\tint num_goals, num_beaten;\r\n\t\t\t\tScript::CStruct* pParams;\r\n\t\t\t\t\t\r\n\t\t\t\tnum_goals = pGoalManager->GetNumSelectedGoals();\r\n\t\t\t\tnum_beaten = pGoalManager->NumGoalsBeaten();\r\n\t\t\r\n\t\t\t\tif( num_goals > num_beaten )\r\n\t\t\t\t{\r\n\t\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\t\tpParams->AddInteger( \"NumGoalsLeft\", num_goals - num_beaten );\r\n\t\t\t\t\tScript::RunScript( \"goal_attack_completed_goal\", pParams );\r\n\t\t\t\t\tdelete pParams;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tpGoal->mp_goalPed->DestroyGoalPed();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tint num_goals, num_beaten;\r\n\t\t\t\tScript::CStruct* pParams;\r\n\t\t\t\tbool in_same_goal;\r\n\t\t\t\t\t\r\n\t\t\t\tin_same_goal = \t( pCurrentGoal != NULL ) && \r\n\t\t\t\t\t\t\t\t( pGoal->GetRootGoalId() == pCurrentGoal->GetRootGoalId());\r\n\t\t\t\tif( ( skate_mod->GetGameMode()->IsTeamGame()) && \r\n\t\t\t\t\t( local_player->m_Team == player->m_Team ))\r\n\t\t\t\t{\r\n\t\t\t\t\tif( in_same_goal )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( pGoal->GetChildren()->m_relative != 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tGame::CGoal* pChildGoal = pGoal;\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t// get the root node\r\n\t\t\t\t\t\t\tGame::CGoalLink* p_child = pGoal->GetChildren();\r\n\t\t\t\t\t\t\twhile ( p_child && p_child->m_relative != 0 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tpChildGoal = pGoalManager->GetGoal( p_child->m_relative );\r\n\t\t\t\t\t\t\t\tp_child = pChildGoal->GetChildren();\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tpChildGoal->Win();\r\n\t\t\t\t\t\t\tif( pChildGoal != pCurrentGoal )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tpCurrentGoal->Deactivate();\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tpGoal->Win();\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tpCurrentGoal->mp_goalPed->DestroyGoalPed();\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpGoal->mp_goalPed->DestroyGoalPed();\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tpGoal->MarkBeaten();\r\n\t\r\n\t\t\t\t\tnum_goals = pGoalManager->GetNumSelectedGoals();\r\n\t\t\t\t\tnum_beaten = pGoalManager->NumGoalsBeaten();\r\n\t\t\t\r\n\t\t\t\t\tif( num_goals > num_beaten )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tconst char* p_view_goals_text = NULL;\r\n\t\r\n\t\t\t\t\t\tpGoal->GetViewGoalsText( &p_view_goals_text );\r\n\t\t\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\t\t\tpParams->AddInteger( CRCD(0x684a8396, \"NumGoalsLeft\"), num_goals - num_beaten );\r\n\t\t\t\t\t\tpParams->AddString( CRCD(0x9196d920, \"PlayerName\"), player->m_Name );\r\n\t\t\t\t\t\tpParams->AddString( CRCD(0xb8a88b50, \"GoalText\"), p_view_goals_text );\r\n\t\t\t\t\t\tScript::RunScript( CRCD(0xf4748e47, \"goal_attack_completed_goal_other_same_team\"), pParams );\r\n\t\t\t\t\t\tdelete pParams;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Client started a goalattack goal. \t\t\t\t\t\t\t  */\r\n/* Relay it to all clients\t\t\t  \t\t\t  \t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_started_goal( Net::MsgHandlerContext* context )\r\n{\r\n\tMsgStartedGoal *msg;\r\n\tManager* gamenet_man;\r\n\tGame::CGoalManager* pGoalManager;\r\n\tGame::CGoal* pGoal;    \r\n\t\t\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tmsg = (MsgStartedGoal*) context->m_Msg;\r\n    \r\n\t// Make sure this message pertains to the current game\r\n\tif( msg->m_GameId != gamenet_man->GetNetworkGameId())\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\tpGoalManager = Game::GetGoalManager();\r\n\tpGoal = pGoalManager->GetGoal( msg->m_GoalId );\r\n\tif( pGoal )\r\n\t{\r\n\t\tPlayerInfo* player;\r\n\r\n\t\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\t\tDbg_Assert( player );\r\n\r\n\t\tif( player->m_Skater )\r\n\t\t{   \r\n\t\t\tPlayerInfo* other_player;\r\n\t\t\tLst::Search< PlayerInfo > sh;\r\n\t\t\tMsgStartedGoalRelay goal_msg;\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\tgoal_msg.m_GoalId = msg->m_GoalId;\r\n\t\t\tgoal_msg.m_ObjId = player->m_Skater->GetID();\r\n\r\n\t\t\tmsg_desc.m_Data = &goal_msg;\r\n\t\t\tmsg_desc.m_Length = sizeof( MsgStartedGoalRelay );\r\n\t\t\tmsg_desc.m_Id = MSG_ID_STARTED_GOAL;\r\n\t\t\t/* Dan: used to only sent to teammates\r\n\t\t\tfor( team_player = gamenet_man->FirstPlayerInfo( sh ); team_player; \r\n\t\t\t\t\tteam_player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t\t{\r\n\t\t\t\tif( player == team_player )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tif( player->m_Team == team_player->m_Team )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontext->m_App->EnqueueMessage( team_player->GetConnHandle(), &msg_desc );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t*/\r\n\t\t\tfor( other_player = gamenet_man->FirstPlayerInfo( sh ); other_player; \r\n\t\t\t\t\tother_player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t\t{\r\n\t\t\t\tif( player == other_player )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tcontext->m_App->EnqueueMessage( other_player->GetConnHandle(), &msg_desc );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Client started a goalattack goal\t\t\t\t\t\t  \t  \t  */\r\n/*                                                  \t\t\t  */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_started_goal_relay( Net::MsgHandlerContext* context )\r\n{\r\n\tMsgStartedGoalRelay *msg;\r\n\tManager* gamenet_man;\r\n\tGame::CGoalManager* pGoalManager;\r\n\tGame::CGoal* pGoal;\r\n    \r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tmsg = (MsgStartedGoalRelay*) context->m_Msg;\r\n    \r\n\tpGoalManager = Game::GetGoalManager();\r\n\tpGoal = pGoalManager->GetGoal( msg->m_GoalId );\r\n\tif( pGoal )\r\n\t{\r\n\t\tScript::CStruct* pParams;\r\n\t\tconst char* p_view_goals_text = NULL;\r\n\t\tPlayerInfo* player;\r\n\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( msg->m_ObjId );\r\n\t\tDbg_Assert( player );\r\n\r\n\t\tif (gamenet_man->GetLocalPlayer()->m_Team == player->m_Team)\r\n\t\t{\r\n\t\t\tpGoal->GetViewGoalsText( &p_view_goals_text );\r\n\t\t\tpParams = new Script::CStruct;\r\n\t\t\tpParams->AddString( CRCD(0x9196d920, \"PlayerName\"), player->m_Name );\r\n\t\t\tpParams->AddString( CRCD(0xb8a88b50, \"GoalText\"), p_view_goals_text );\r\n\t\t\tScript::RunScript( CRCD(0xa77758de, \"goal_attack_started_goal_other_same_team\"), pParams );\r\n\t\t\tdelete pParams;\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Toggle this proset\t\t\t\t\t\t  \t  \t\t\t\t  */\r\n/*                                                  \t\t\t  */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_toggle_proset( Net::MsgHandlerContext* context )\r\n{\r\n\tMsgToggleProSet* msg;\r\n\tScript::CStruct* pParams;\r\n\tManager* gamenet_man;\r\n\r\n\tmsg = (MsgToggleProSet*) context->m_Msg;\r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tpParams = new Script::CStruct;\r\n\r\n\tDbg_Printf( \"********************* handle toggle proset\" );\r\n\r\n\tScript::RunScript( \"toggle_proset_flag\", Script::GetStructure( msg->m_ParamId, Script::ASSERT ));\r\n\tScript::RunScript( \"toggle_geo_nomenu\", Script::GetStructure( msg->m_ParamId, Script::ASSERT ));\r\n\r\n\tif( gamenet_man->OnServer() == false )\r\n\t{\r\n\t\tgamenet_man->m_proset_flags.Toggle( msg->m_Bit );\r\n\t}\r\n\r\n\tdelete pParams;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Someone has sent us a chat message\t\t\t\t\t\t  \t  */\r\n/*                                                  \t\t\t  */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_chat( Net::MsgHandlerContext* context )\r\n{\r\n\tMsgChat* chat_msg;\r\n\tScript::CStruct* p_params;\r\n\tchar final_msg[256];\r\n\t\r\n\tchat_msg = (MsgChat*) context->m_Msg;\r\n\tp_params = new Script::CStruct;\t\r\n\tsprintf( final_msg, \"\\\\c%i%s\\\\c0 : %s\", ( chat_msg->m_ObjId + 2 ), chat_msg->m_Name, chat_msg->m_ChatMsg );\r\n\tp_params->AddString( \"text\", final_msg );\r\n\tScript::RunScript(\"create_console_message\", p_params );\r\n\tdelete p_params;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Server has changed the number of teams\t\t\t\t\t\t  */\r\n/*                                                  \t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_set_num_teams( Net::MsgHandlerContext* context )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tManager* gamenet_man;\r\n\tMsgByteInfo* msg;\r\n\tint num_teams;\r\n    \r\n\tgamenet_man = (Manager *) context->m_Data;\r\n\tmsg = (MsgByteInfo*) context->m_Msg;\r\n\tnum_teams = msg->m_Data;\r\n\r\n\tif( ( num_teams > 0 ) &&\r\n\t\t( !skate_mod->GetGameMode()->IsTeamGame()))\r\n\t{\r\n\t\tskate_mod->GetGameMode()->SetNumTeams( num_teams );\r\n\r\n\t\tScript::RunScript( \"ChooseTeamMessage\" );\r\n\t\tif( skate_mod->GetLocalSkater())\r\n\t\t{\r\n\t\t\tScript::RunScript( \"PrepareSkaterForMove\", NULL, skate_mod->GetLocalSkater());\r\n\t\t\tskate_mod->move_to_restart_point( skate_mod->GetLocalSkater());\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tskate_mod->GetGameMode()->SetNumTeams( num_teams );\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Server requests client's cheat checksum\t\t\t\t  \t\t  */\r\n/*                                                  \t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_cheat_checksum_request( Net::MsgHandlerContext* context )\r\n{\r\n\tMsgCheatChecksum* msg;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tNet::MsgDesc msg_desc;\r\n\r\n\tmsg = (MsgCheatChecksum*) context->m_Msg;\r\n\tmsg->m_ClientChecksum = skate_mod->GetCheatChecksum();\r\n\r\n\tmsg_desc.m_Id = MSG_ID_CHEAT_CHECKSUM_RESPONSE;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tmsg_desc.m_Data = msg;\r\n\tmsg_desc.m_Length = sizeof( MsgCheatChecksum );\r\n\r\n\tcontext->m_App->EnqueueMessageToServer( &msg_desc );\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Server has sent a GameSpy stats challenge\t\t\t\t\t  */\r\n/*                                                  \t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_challenge( Net::MsgHandlerContext* context )\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\tNet::MsgDesc msg_desc;\r\n\tchar* challenge;\r\n\tchar response[33];\r\n\tPrefs::Preferences* pPreferences;\r\n\tManager* gamenet_man;\r\n\t\r\n\tgamenet_man = (Manager*) context->m_Data;\r\n\r\n\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\tconst char* password = pPreferences->GetPreferenceString( Script::GenerateCRC( \"profile_password\" ), Script::GenerateCRC(\"ui_string\") );\r\n\r\n\tchallenge = context->m_Msg;\r\n\tgamenet_man->mpStatsMan->GenerateAuthResponse( challenge, (char*) password, response );\r\n\r\n\tmsg_desc.m_Id = MSG_ID_CHALLENGE_RESPONSE;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tmsg_desc.m_Data = response;\r\n\tmsg_desc.m_Length = 33;\r\n\r\n\tcontext->m_App->EnqueueMessageToServer( &msg_desc );\r\n#endif\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Client has answered the GameSpy stats challenge\t\t\t\t  */\r\n/*                                                  \t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_challenge_response( Net::MsgHandlerContext* context )\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\tPlayerInfo* player;\r\n\tManager* gamenet_man;\r\n\t\r\n\tgamenet_man = (Manager*) context->m_Data;\r\n\r\n\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tgamenet_man->mpStatsMan->AuthorizePlayer( player->m_Skater->GetID(), context->m_Msg );\r\n#endif\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Client has requested that we re-send level data to them\t\t  */\r\n/*                                                  \t\t\t  */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_level_data_request( Net::MsgHandlerContext* context )\r\n{\r\n\tNet::Server* server;\r\n\tManager* gamenet_man;\r\n\r\n\tserver = (Net::Server*) context->m_App;\r\n\tgamenet_man = (Manager*) context->m_Data;\r\n\r\n\tif( context->m_MsgId == MSG_ID_REQUEST_RAILS_DATA )\r\n\t{\r\n\t\tDbg_Printf( \"***** Client requested rails data\\n\" );\r\n\t\tserver->StreamMessage( context->m_Conn->GetHandle(), MSG_ID_RAIL_DATA, Obj::GetRailEditor()->GetCompressedRailsBufferSize(), \r\n\t\t\t\t\t\t\t   Obj::GetRailEditor()->GetCompressedRailsBuffer(), \"rail data\", vSEQ_GROUP_PLAYER_MSGS,\r\n\t\t\t\t\t\t\t   false, true );\r\n\t\t\t\t\t\t\t   \r\n\t}\r\n\telse if( context->m_MsgId == MSG_ID_REQUEST_GOALS_DATA )\r\n\t{\r\n\t\tDbg_Printf( \"***** Client requested goals data\\n\" );\r\n\t\tif( gamenet_man->UsingCreatedGoals())\r\n\t\t{\r\n\t\t\tserver->StreamMessage( context->m_Conn->GetHandle(), MSG_ID_GOALS_DATA, gamenet_man->GetGoalsDataSize(),\r\n\t\t\t\t\t\t\t\t   gamenet_man->GetGoalsData(), \"goals data\", vSEQ_GROUP_PLAYER_MSGS, false, true );\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Client has responded to the cheat checksum request\t\t\t  */\r\n/*                                                  \t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tManager::s_handle_cheat_checksum_response( Net::MsgHandlerContext* context )\r\n{\r\n\tMsgCheatChecksum* msg;\r\n\tPlayerInfo* player;\r\n\tManager* gamenet_man;\r\n\r\n\tgamenet_man = (Manager*) context->m_Data;\r\n\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tmsg = (MsgCheatChecksum*) context->m_Msg;\r\n\tif(( msg->m_ServerChecksum ^ 0xDEADFACE ) != msg->m_ClientChecksum )\r\n\t{\r\n\t\tDbg_Printf( \"***** CHEATING! 0x%x  0x%x\\n\", msg->m_ServerChecksum ^ 0xDEADFACE, msg->m_ClientChecksum );\r\n\t\tif( gamenet_man->HasCheatingOccurred() == false )\r\n\t\t{\r\n\t\t\tScript::CStruct* p_params;\r\n\t\r\n\t\t\tp_params = new Script::CStruct;\r\n\t\t\tp_params->AddString( CRCD(0xa4b08520,\"String0\"), player->m_Name );\r\n\t\t\tScript::RunScript( CRCD(0x62ddbe0a,\"notify_client_cheating\"), p_params );\r\n\t\t\tdelete p_params;\r\n\t\t\t\r\n\t\t\tgamenet_man->CheatingOccured();\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_change_level_code( const Tsk::Task< Manager >& task )\r\n{\r\n\tManager& man = task.GetData();\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\r\n\tif(( Tmr::GetTime() < s_time_change_level ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tskate_mod->ChangeLevel( man.m_level_id );\r\n\r\n\t// Clear the king of the hill\r\n\tif(( player = man.GetKingOfTheHill()))\r\n\t{\r\n\t\tplayer->MarkAsKing( false );\r\n\t}\r\n\r\n\tfor( player = man.FirstPlayerInfo( sh, true ); player; player = man.NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tplayer->ClearCTFState();\r\n\t}\r\n\r\n\t//man.RespondToReadyQuery();\r\n\tman.m_change_level_task->Remove();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tManager::ok_to_join( int& reason, MsgConnectInfo* connect_msg, Net::Conn* conn )\r\n{\r\n\tchar* password;\r\n\t\r\n\tif( m_server->IsConnectionBanned( conn ))\r\n\t{\r\n\t\treason = JOIN_REFUSED_ID_BANNED;\r\n\t\treturn false;\r\n\t}\r\n\tif( connect_msg->m_Observer )\r\n\t{\r\n\t\tif( GetNumObservers() >= GetMaxObservers())\r\n\t\t{\r\n\t\t\treason = JOIN_REFUSED_ID_FULL_OBSERVERS;\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( GetNumPlayers() >= GetMaxPlayers())\r\n\t\t{\r\n\t\t\treason = JOIN_REFUSED_ID_FULL;\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\t\r\n\t// Version check\r\n\tif( connect_msg->m_Version != vVERSION_NUMBER )\r\n\t{\r\n\t\treason = JOIN_REFUSED_ID_VERSION;\r\n\t\tDbg_Printf( \"Client had the wrong version. Dropping connection\\n\" );\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\t// Game-in-progress check\r\n\tif( !connect_msg->m_WillingToWait && !connect_msg->m_Observer )\r\n\t{\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\t\tif(( skate_mod->GetGameMode()->GetNameChecksum() != Script::GenerateCRC( \"netlobby\" )) &&\r\n\t\t   ( GameIsOver() == false ))\r\n\t\t{\r\n\t\t\treason = JOIN_REFUSED_ID_IN_PROGRESS;\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t// Check if we're password-protected. If so, compare passwords\r\n\tpassword = GetPassword();\r\n\tif( password[0] != '\\0' )\r\n\t{\r\n\t\tDbg_Printf( \"Comparing passwords %s and %s\\n\", password, connect_msg->m_Password );\r\n\t\tif( strcmp( password, connect_msg->m_Password ))\r\n\t\t{          \r\n\t\t\treason = JOIN_REFUSED_ID_PW;\r\n\r\n\t\t\tDbg_Printf( \"Client gave the wrong password. Dropping connection\\n\" );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/GameMsg.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tGameMsg.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/20/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGame-Side Network Messages\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GAMENET_GAMEMSG_H\r\n#define __GAMENET_GAMEMSG_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/math.h>\r\n#include <gel/net/net.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\nenum\r\n{\r\n\tMSG_ID_SKATER_INPUT\t= Net::MSG_ID_USER,\t//\t= 32 : C->S The Client's Pad Input\r\n\tMSG_ID_YOUR_PLAYER_CREATE,\t\t\t\t//\t= 33 : S->C Create local skater\r\n\tMSG_ID_PLAYER_CREATE,\t\t\t\t\t//\t= 34 : S->C Each player's info\r\n\tMSG_ID_OBJ_UPDATE_STREAM,\t\t\t\t//\t= 35 : S->C Stream of object updates\r\n\tMSG_ID_NEW_ALIAS,\t\t\t\t\t\t//\t= 36 : C->S Alias suggestion\r\n\tMSG_ID_READY_QUERY,\t\t\t\t\t\t//\t= 37 : S->C Are you ready to receive more data?\r\n\tMSG_ID_READY_RESPONSE,\t\t\t\t\t//\t= 38 : C->S or S->C Ready query response\r\n\tMSG_ID_PAUSE,\t\t\t\t\t\t\t//\t= 39 : S->C Pause instruction\r\n\tMSG_ID_UNPAUSE,\t\t\t\t\t\t\t//\t= 40 : S->C UnPause instruction\r\n\tMSG_ID_PRIM_ANIM_START,\t\t\t\t\t//\t= 41 : S->C Play primary animation\r\n\tMSG_ID_ROTATE_SKATEBOARD,\t\t\t\t//\t= 42 : S->C Rotate skateboard\r\n\tMSG_ID_SET_WOBBLE_TARGET,\t\t\t\t//\t= 43 : S->C Set wobble target\r\n\tMSG_ID_FLIP_ANIM,\t\t\t\t\t\t//\t= 44 : S->C Flip the animation\r\n\tMSG_ID_PLAYER_QUIT,\t\t\t\t\t\t//\t= 45 : S->C Notification of a player quitting\r\n\tMSG_ID_HOST_REQ,\t\t\t\t\t\t//  = 46 : GameServer->MatchMaker Game Host Request\r\n\tMSG_ID_HOST_PROCEED,\t\t\t\t\t//  = 47 : MatchMaker->GameServer Proceed hosting\r\n\tMSG_ID_GAMELIST_REQ,\t\t\t\t\t//  = 48 : GameClient->MatchMaker Game list request\r\n\tMSG_ID_GAMELIST_RESPONSE,\t\t\t\t//  = 49 : MatchMaker->GameClient Game list response\r\n\tMSG_ID_HOST_QUIT,\t\t\t\t\t\t//\t= 50 : S->C Server is shutting down\r\n\tMSG_ID_START_INFO,\t\t\t\t\t\t//\t= 51 : S->C Startup Game Option\r\n\tMSG_ID_GAME_INFO,\t\t\t\t\t\t//\t= 52 : S->C Game Options\r\n\tMSG_ID_PLAY_SOUND,\t\t\t\t\t\t//\t= 53 : S->C Play Sound\r\n\tMSG_ID_PLAY_LOOPING_SOUND,\t\t\t\t// \t= 54 : S->C Play Looping Sound\r\n\tMSG_ID_SPARKS_ON,\t\t\t\t\t\t//\t= 55 : S->C Sparks on\r\n\tMSG_ID_SPARKS_OFF,\t\t\t\t\t\t//\t= 56 : S->C Sparks off\r\n\tMSG_ID_BLOOD_ON,\t\t\t\t\t\t//\t= 57 : S->C Blood on\r\n\tMSG_ID_BLOOD_OFF,\t\t\t\t\t\t//\t= 58 : S->C Blood off\r\n\tMSG_ID_SCORE,\t\t\t\t\t\t\t//\t= 59 : S->C General Score Msg: See SCORE_MSG_ID...\r\n\tMSG_ID_SET_WOBBLE_DETAILS,\t\t\t\t//\t= 60 : S->C Set the wobbling parameters\r\n\tMSG_ID_SET_LOOPING_TYPE,\t\t\t\t//\t= 61 : S->C Set the desired looping type\r\n\tMSG_ID_SET_HIDE_ATOMIC,\t\t\t\t\t//\t= 62 : S->C Hide an arbitrary atomic on the skin model\r\n\tMSG_ID_PANEL_MESSAGE,\t\t\t\t\t//\t= 63 : S->C Display this panel message\r\n\tMSG_ID_SCORE_UPDATE,\t\t\t\t\t//\t= 64 : S->C Score update for other clients\r\n\tMSG_ID_SET_ANIM_SPEED,\t\t\t\t\t//\t= 65 : S->C Set animation speed\r\n\tMSG_ID_PROCEED_TO_PLAY,\t\t\t\t\t//\t= 66 : S->C Init phase complete: Next state\r\n\tMSG_ID_SKATER_COLLIDE_LOST,\t\t\t\t//\t= 67 : S->C You were involved in a skater collision and lost\r\n\tMSG_ID_SKATER_COLLIDE_WON,\t\t\t\t//\t= 68 : S->C You were involved in a skater collision and won\r\n\tMSG_ID_BAIL_DONE,\t\t\t\t\t\t//\t= 69 : C->S Bail is done\r\n\tMSG_ID_CHANGE_LEVEL,\t\t\t\t\t//\t= 70 : S->C Change level\r\n\tMSG_ID_JOIN_REFUSED,\t\t\t\t\t//\t= 71 : S->C Server refused to allow player to join\r\n\tMSG_ID_RUN_SCRIPT,\t\t\t\t\t\t//  = 72 : C->C Run this script\r\n\tMSG_ID_SPAWN_AND_RUN_SCRIPT,\t\t\t//  = 73 : C->C Spawn and Run this script\r\n\tMSG_ID_OBSERVE,\t\t\t\t\t\t\t//\t= 74 : C->S A request to enter observer mode\r\n\tMSG_ID_STEAL_MESSAGE,\t\t\t\t\t//\t= 75 : S->C A request to display a \"steal message\" in graffiti\r\n\tMSG_ID_CHAT,\t\t\t\t\t\t\t//\t= 76 : C->C Chat message\r\n\tMSG_ID_OBSERVE_PROCEED,\t\t\t\t\t//  = 77 : S->C Proceed to observe\r\n\tMSG_ID_OBSERVE_REFUSED,\t\t\t\t\t//\t= 78 : S->C Server says you can't observe\r\n\tMSG_ID_JOIN_PROCEED,\t\t\t\t\t//\t= 79 : S->C Go ahead and attempt to join\r\n\tMSG_ID_JOIN_REQ,\t\t\t\t\t\t//  = 80 : C->S Request to join a connected server\r\n\tMSG_ID_KICKED,\t\t\t\t\t\t\t//\t= 81 : S->C You've been kicked\r\n\tMSG_ID_LANDED_TRICK,\t\t\t\t\t//\t= 82 : S->C Landed a trick\r\n\tMSG_ID_PLAYER_INFO_ACK_REQ,\t\t\t\t//\t= 83 : S->C Have you received all the player info data?\r\n\tMSG_ID_PLAYER_INFO_ACK,\t\t\t\t\t//\t= 84 : C->S Yes I have received all the player info data\r\n\tMSG_ID_NEW_KING,\t\t\t\t\t\t//\t= 85 : S->C Crown the new king\r\n\tMSG_ID_LEFT_OUT,\t\t\t\t\t\t//  = 86 : S->C Sorry. We're playing without you\r\n\tMSG_ID_MOVED_TO_RESTART,\t\t\t\t//\t= 87 : C->S Client has moved to a restart\r\n\tMSG_ID_KING_DROPPED_CROWN,\t\t\t\t//\t= 88 : S->C Spawn a new crown in the world\r\n\tMSG_ID_RUN_HAS_ENDED,\t\t\t\t\t//\t= 89 : C->S My run has ended\r\n\tMSG_ID_GAME_OVER,\t\t\t\t\t\t//\t= 90 : S->C Game is over\r\n\tMSG_ID_OBSERVER_LOG_TRICK_OBJ,\t\t\t//\t= 91 : S->C Special-case observer trick object report\r\n\tMSG_ID_OBSERVER_INIT_GRAFFITI_STATE,\t//\t= 92 : S->C Special-case observer, to synchronize trick objects with the current graffiti state\r\n\tMSG_ID_PRINTF,\t\t\t\t\t\t\t//  = 93 : S->C Printf\r\n\tMSG_ID_AUTO_SERVER_NOTIFICATION,\t\t//\t= 94 : S->C Notify the client that he's on an auto-serving server\r\n\tMSG_ID_FCFS_ASSIGNMENT,\t\t\t\t\t//\t= 95 : S->C Notify the client that he's the acting host\r\n\tMSG_ID_FCFS_START_GAME,\t\t\t\t\t//\t= 96 : C->S Request to start a game from a FCFS\r\n\tMSG_ID_FCFS_BAN_PLAYER,\t\t\t\t\t//\t= 97 : C->S Request to ban a player from a FCFS\r\n\tMSG_ID_FCFS_CHANGE_LEVEL,\t\t\t\t//\t= 98 : C->S Request to change levels from a FCFS\r\n\tMSG_ID_FCFS_TOGGLE_PROSET,\t\t\t\t//\t= 99 : C->S Request to toggle a pro set\r\n\tMSG_ID_FCFS_TOGGLE_GOAL_SELECTION,\t\t//\t= 100 : C->S Request to toggle a goal selection\r\n\tMSG_ID_FCFS_END_GAME,\t\t\t\t\t//\t= 101 : C->S Request to end the current game\r\n\tMSG_ID_FCFS_SET_NUM_TEAMS,\t\t\t\t//\t= 102 : C->S Request to set the number of teams\r\n\tMSG_ID_REQUEST_CHANGE_TEAM,\t\t\t\t//\t= 103 : C->S Request to change teams\r\n\tMSG_ID_TEAM_CHANGE,\t\t\t\t\t\t//\t= 104 : S->C Team change update\r\n\tMSG_ID_SET_NUM_TEAMS,\t\t\t\t\t//\t= 105 : S->C Change in the number of teams\r\n\tMSG_ID_END_GAME,\t\t\t\t\t\t//\t= 106 : S->C Server has chosen to end the game\r\n\tMSG_ID_REQUEST_LEVEL,\t\t\t\t\t//\t= 107 : C->S Client requests level data\r\n\tMSG_ID_LEVEL_DATA,\t\t\t\t\t\t//\t= 108 : S->C Server sending client level data\r\n\tMSG_ID_SELECT_GOALS,\t\t\t\t\t//\t= 109 : S->C A list of goals to complete\r\n\tMSG_ID_BEAT_GOAL,\t\t\t\t\t\t//\t= 110 : C->S I beat a goal\r\n\tMSG_ID_STARTED_GOAL,\t\t\t\t\t//\t= 111 : C->S I started a goal\r\n\tMSG_ID_TOGGLE_PROSET,\t\t\t\t\t//\t= 112 : S->C Toggle this proset\r\n\tMSG_ID_TOOK_FLAG,\t\t\t\t\t\t//\t= 113 : S->C Player took a ctf flag\r\n\tMSG_ID_CAPTURED_FLAG,\t\t\t\t\t//\t= 114 : S->C Player captured a ctf flag\r\n\tMSG_ID_RETRIEVED_FLAG,\t\t\t\t\t//\t= 115 : S->C Player retrieved a ctf flag\r\n\tMSG_ID_STOLE_FLAG,\t\t\t\t\t\t//\t= 116 : S->C Player stole a ctf flag\r\n\tMSG_ID_PLAYER_DROPPED_FLAG,\t\t\t\t//\t= 117 : S->C Player dropped a flag\r\n\tMSG_ID_ROTATE_DISPLAY,\t\t\t\t\t//\t= 118 : S->C Rotate the skater by this much over time\r\n\tMSG_ID_CREATE_SPECIAL_ITEM,\t\t\t\t//\t= 119 : S->C Create a special item\r\n\tMSG_ID_DESTROY_SPECIAL_ITEM,\t\t\t//\t= 120 : S->C Destroy a special item\r\n\tMSG_ID_JOIN_ACCEPTED,\t\t\t\t\t//\t= 121 : S->C You're in - completely\r\n\tMSG_ID_KILL_TEAM_FLAGS,\t\t\t\t\t//\t= 122 : S->C Kill team flag (i.e. no more switching teams)\r\n\tMSG_ID_WAIT_N_SECONDS,\t\t\t\t\t//\t= 123 : S->C Prepare for a period of N seconds of no communication\r\n\tMSG_ID_CHALLENGE,\t\t\t\t\t\t//\t= 124 : S->C GameSpy Stats Challenge\r\n\tMSG_ID_CHALLENGE_RESPONSE,\t\t\t\t//\t= 125 : C->S GameSpy Stats Challenge Response\r\n\tMSG_ID_FACE_DATA,\t\t\t\t\t\t//\t= 126 : C->C Custom face data\r\n\tMSG_ID_TOGGLE_CHEAT,\t\t\t\t\t//\t= 127 : S->C Toggle a cheat on or off\r\n\tMSG_ID_CHEAT_CHECKSUM_REQUEST,\t\t\t//\t= 128 : S->C Server requesting client's cheat checksum\r\n\tMSG_ID_CHEAT_CHECKSUM_RESPONSE,\t\t\t//\t= 129 : C->S Client responding to server's request\r\n\tMSG_ID_CHEAT_LIST,\t\t\t\t\t\t//\t= 130 : S->C A list of all active cheats\r\n\tMSG_ID_SPAWN_PROJECTILE,\t\t\t\t//  = 131 : C->C Spawn a projectile\r\n\tMSG_ID_SKATER_HIT_BY_PROJECTILE,\t\t//\t= 132 : S->C You were hit by a projectile\r\n\tMSG_ID_SKATER_PROJECTILE_HIT_TARGET,\t//\t= 133 : S->C You hit someone with a projectile\r\n\tMSG_ID_COMBO_REPORT,\t\t\t\t\t//\t= 134 : C->S Reporting combo\r\n\tMSG_ID_GOALS_DATA,\t\t\t\t\t\t//\t= 135 : S->C Server sending client goals data\r\n\tMSG_ID_RAIL_DATA,\t\t\t\t\t\t//\t= 136 : S->C Server sending edited rail data\r\n\tMSG_ID_ENTER_VEHICLE,\t\t\t\t\t//  = 137 : C->S Client entering a vehicle\r\n\tMSG_ID_REQUEST_GOALS_DATA,\t\t\t\t//\t= 138 : C->S Re-requesting goals data\r\n\tMSG_ID_REQUEST_RAILS_DATA,\t\t\t\t//\t= 139 : C->S Re-requesting rails data\r\n\tMSG_ID_CLEAR_ROTATE_DISPLAY,\t\t\t//\t= 140 : S->C Clear any model rotations\r\n};\r\n\r\nenum\r\n{\r\n\tSCORE_MSG_ID_LAND,\t\t\t\t\t\t// = 0 : S->C Tabulate final score\r\n\tSCORE_MSG_ID_LOG_TRICK_OBJECT,\t\t\t// = 1 : S->C Color an object\r\n};\r\n\r\nenum\r\n{\r\n\tJOIN_REFUSED_ID_FULL,\t\t\t\t\t// = 0 : S->C Server Full\r\n\tJOIN_REFUSED_ID_PW,\t\t\t\t\t\t// = 1 : S->C Wrong Password\r\n\tJOIN_REFUSED_ID_VERSION,\t\t\t\t// = 2 : S->C Wrong version\r\n\tJOIN_REFUSED_ID_IN_PROGRESS,\t\t\t// = 3 : S->C Game is in progress\r\n\tJOIN_REFUSED_ID_BANNED,\t\t\t\t\t// = 4 : S->C You've been banned\r\n\tJOIN_REFUSED_ID_FULL_OBSERVERS,\t\t\t// = 5 : S->C Server has no more room for observers\r\n};\r\n\r\nenum\r\n{\r\n\tvSEQ_GROUP_PLAYER_MSGS = 8,\t\t\t\t// Messages about new players & quitting players\r\n\tvSEQ_GROUP_FACE_MSGS,\t\t\t\t\t// Face download messages\r\n};\r\n\r\nenum\r\n{\r\n\tvMAX_CONNECTIONS\t\t\t= 20,\r\n\tvMAX_PLAYERS \t\t\t\t= 8,\r\n\tvMAX_SERVER_NAME_LEN \t\t= 15,\r\n\tvMAX_PLAYER_NAME_LEN \t\t= 15,\r\n\tvMAX_APPEARANCE_DATA_SIZE \t= 4096,\r\n\tvMAX_PASSWORD_LEN\t\t\t= 9,\r\n\tvMAX_CHAT_MSG_LEN\t\t\t= 127,\r\n\tvMAX_TRICK_OBJECTS_IN_LEVEL = 256,\t// actually custom parks can have more than 256 trick objects, so we'll need to address that in THPS4\r\n};\r\n\r\nenum\r\n{\r\n#ifdef __PLAT_XBOX__\r\n\tvCONNECTION_TIMEOUT = 5000,\t\t//  5 seconds in ms\r\n#else\r\n\tvCONNECTION_TIMEOUT = 20000,\t//\t30 seconds in ms\r\n#endif\r\n\tvNOT_READY_TIMEOUT\t= 60000,\t//\tClients are marked \"not ready\" when we tell them to load\r\n\t\t\t\t\t\t\t\t\t//\tlevels/skaters/etc.  If that time exceeds this timeout\r\n\t\t\t\t\t\t\t\t\t//\twe should disconnect them\r\n\tvJOIN_TIMEOUT\t\t= 60000,\t//  20 seconds in ms to join a server\r\n};\r\n\r\nenum\r\n{\r\n\tvHOST_PORT \t\t= 5150,\r\n\tvJOIN_PORT\t\t= 5151,\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tMessages\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass MsgReady\r\n{\r\npublic:\r\n\tunsigned int\tm_Time;\r\n};\r\n\r\nclass MsgPlayPrimaryAnim\r\n{\r\npublic:\r\n\t//uint32\t\t\tm_Time;\r\n\tuint32\t\t\tm_Index;\r\n\tchar\t\t\tm_LoopingType;\r\n\tchar\t\t\tm_ObjId;\r\n\tunsigned short\tm_StartTime;\r\n\tunsigned short\tm_EndTime;\r\n\tunsigned short\tm_BlendPeriod;\r\n\tunsigned short\tm_Speed;\r\n};\r\n\r\nclass MsgFlagMsg\r\n{\r\npublic:\r\n\tchar m_ObjId;\r\n\tchar m_Team;\r\n};\r\n\r\nclass MsgFlipAnim\r\n{\r\npublic:\r\n\t//uint32\t\t\tm_Time;\r\n\tchar\t\t\tm_ObjId;\r\n\tchar\t\t\tm_Flipped;\r\n};\r\n\r\nclass MsgRotateSkateboard\r\n{\r\npublic:\r\n\t//uint32\t\t\tm_Time;\r\n\tchar\t\t\tm_ObjId;\r\n\tchar\t\t\tm_Rotate;\r\n};\r\n\r\nclass MsgRotateDisplay\r\n{\r\npublic:\r\n\t//uint32\t\t\tm_Time;\r\n\tint \t\t\tm_Duration;\r\n\tint \t\t\tm_SinePower;\r\n\tshort \t\t\tm_StartAngle;\r\n\tshort \t\t\tm_DeltaAngle;\r\n\tchar \t\t\tm_ObjId;\r\n\tbool\t\t\tm_HoldOnLastAngle;\r\n\tchar\t\t\tm_Flags;\r\n};\r\n\r\nclass MsgSetWobbleTarget\r\n{\r\npublic:\r\n\t//uint32\t\t\tm_Time;\r\n\tchar\t\t\tm_ObjId;\r\n\tunsigned char\tm_Alpha;\r\n};\r\n\r\nclass MsgSetWobbleDetails\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvWOBBLE_AMP_A,\r\n\t\tvWOBBLE_AMP_B,\r\n\t\tvWOBBLE_K1,\r\n\t\tvWOBBLE_K2,\r\n\t\tvSPAZFACTOR,\r\n\r\n\t\tmWOBBLE_AMPA_MASK\t= 0x03,\r\n\t\tmWOBBLE_AMPB_MASK\t= 0x04,\r\n\t\tmWOBBLE_K1_MASK\t\t= 0x08,\r\n\t\tmWOBBLE_K2_MASK\t\t= 0x10,\r\n\t\tmSPAZFACTOR_MASK\t= 0x20,\r\n\t};\r\n\r\n\t//uint32\t\t\tm_Time;\r\n\tchar\t\t\tm_WobbleDetails;\r\n\tchar\t\t\tm_ObjId;\r\n};\r\n\r\nclass MsgSetLoopingType\r\n{\r\npublic:\r\n\t//uint32\t\t\tm_Time;\r\n\tchar\t\t\tm_ObjId;\r\n\tchar\t\t\tm_LoopingType;\r\n};\r\n\r\nclass MsgSpecialItem\r\n{\r\npublic:\r\n\t//uint32\t\t\tm_Time;\r\n\tunsigned int\tm_Params;\r\n\tuint32\t\t\tm_Bone;\r\n\tchar\t\t\tm_ObjId;\r\n\tchar\t\t\tm_Index;\r\n};\r\n\r\nclass MsgHideAtomic\r\n{\r\npublic:\r\n\t//uint32\t\t\tm_Time;\r\n\tuint32\t\t\tm_AtomicName;\r\n\tchar\t\t\tm_ObjId;\r\n\tchar\t\t\tm_Hide;\r\n};\r\n\r\nclass MsgSetAnimSpeed\r\n{\r\n\tpublic:\r\n\t\t//uint32\t\t\tm_Time;\r\n\t\tfloat\t\t\tm_AnimSpeed;\r\n\t\tchar\t\t\tm_ObjId;\r\n};\r\n\r\n// Game options sent to joining players\r\nclass MsgStartInfo\r\n{\r\npublic:\r\n\tchar\t\t\tm_CrownSpawnPoint;\r\n\tchar\t\t\tm_Broadband;\t// boolean\r\n\tunsigned char\tm_GameId;\r\n\tchar\t\t\tm_ProSetFlags;\r\n\tchar\t\t\tm_MaxPlayers;\r\n\tint\t\t\t\tm_TimeLeft;\r\n\tunsigned long\tm_GameMode;\r\n\tuint32\t\t\tm_LevelId;\r\n\tuint32\t\t\tm_TeamMode;\r\n\t\r\n\tint\t\t\t\tm_TimeLimit;\r\n\tint\t\t\t\tm_TargetScore;\r\n\tint\t\t\t\tm_StartPoints[vMAX_PLAYERS];\r\n};\r\n\r\nclass MsgInitGraffitiState\r\n{\r\npublic:\r\n\tuint8\t\t\tm_NumTrickObjects[vMAX_PLAYERS];\r\n\tuint8\t\t\tm_TrickObjectStream[vMAX_TRICK_OBJECTS_IN_LEVEL];\r\n};\r\n\r\nclass MsgGameInfo\r\n{\r\npublic:\r\n\tunsigned long\tm_GameMode;\r\n\tunsigned long\tm_TimeLimit;\r\n\tunsigned long\tm_TargetScore;\r\n\tint\t\t\t\tm_FireballLevel;\r\n\tchar\t\t\tm_NumPlayers;\r\n\tchar\t\t\tm_AccumulateScore;\r\n\tchar\t\t\tm_DegradeScore;\r\n\tchar\t\t\tm_UseClock;\r\n\tchar\t\t\tm_StopAtZero;\r\n\tunsigned char\tm_GameId;\r\n\tuint32\t\t\tm_TeamMode;\r\n\tchar\t\t\tm_CrownSpawnPoint;\r\n\tint\t\t\t\tm_StartPoints[vMAX_PLAYERS];\r\n};\r\n\r\nclass MsgConnectInfo\r\n{\r\npublic:\r\n\tint\t\t\t\tm_Version;\r\n\tchar\t\t\tm_Observer;\t// Does this player just want to observe?\r\n\tchar\t\t\tm_WillingToWait;\t// Willing to sit out until the next lobby\r\n\tchar\t\t\tm_Password[ vMAX_PASSWORD_LEN + 1 ];\r\n};\r\n\r\nclass MsgJoinInfo : public MsgConnectInfo\r\n{\r\npublic:\r\n\tint\t\t\t\tm_Profile;\r\n\tint\t\t\t\tm_Rating;\r\n\tchar\t\t\tm_Broadband;\t// boolean\r\n\tuint32\t\t\tm_VehicleControlType;\r\n\tchar\t\t\tm_Name[ vMAX_PLAYER_NAME_LEN + 1 ];\r\n\tuint8\t\t\tm_AppearanceData[vMAX_APPEARANCE_DATA_SIZE];\t// stream information for player appearance\r\n};\r\n\r\nclass MsgNewPlayer\r\n{\r\npublic:\r\n\tint\t\t\tm_Profile;\r\n\tint\t\t\tm_Rating;\r\n\tint\t\t\tm_Flags;\r\n\tint\t\t\tm_Score;\r\n\tchar\t\tm_ObjId;\t// object id for this player\r\n\tchar\t\tm_Team;\r\n\tuint32\t\tm_VehicleControlType;\r\n\tchar\t\tm_Name[ vMAX_PLAYER_NAME_LEN + 1 ];\r\n\tuint8\t\tm_AppearanceData[vMAX_APPEARANCE_DATA_SIZE]; // stream information for player appearance\r\n};\r\n\r\nclass MsgPlayerQuit\r\n{\r\npublic:\r\n\tchar\tm_ObjId;\r\n\tchar\tm_Reason;\r\n};\r\n\r\nclass MsgPanelMessage\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvMAX_STRING_PARAM_LENGTH = vMAX_PLAYER_NAME_LEN,\r\n\t};\r\n\r\n\tuint32\tm_PropsStructureCRC;\r\n\tuint32\tm_StringId;\r\n\tint\t\tm_Time;\r\n\tchar\tm_Parm1[vMAX_STRING_PARAM_LENGTH + 1];\r\n\tchar\tm_Parm2[vMAX_STRING_PARAM_LENGTH + 1];\r\n};\r\n\r\nclass MsgNewAlias\r\n{\r\npublic:\r\n\tunsigned char\tm_Alias;\r\n\tchar\t\tm_ObjId;\r\n\tint\t\t\tm_Expiration;\r\n};\r\n\r\n#ifdef __PLAT_XBOX__\r\nclass MsgFindServer : public Net::MsgTimestamp\r\n{\r\npublic:\r\n\tBYTE m_Nonce[8]; \r\n};\r\n#else\r\ntypedef Net::MsgTimestamp\tMsgFindServer;\r\n#endif\r\n\r\nclass MsgServerDescription\r\n{\r\npublic:\r\n#ifdef __PLAT_XBOX__\r\n\tBYTE\tm_Nonce[8]; \r\n\tXNKID\tm_XboxKeyId;\r\n\tXNKEY\tm_XboxKey;\r\n\tXNADDR\tm_XboxAddr;\r\n#endif\r\n\tchar\tm_NumPlayers;\r\n\tchar\tm_MaxPlayers;\r\n\tchar\tm_NumObservers;\r\n\tchar\tm_MaxObservers;\r\n\tchar\tm_Password;\t// boolean\r\n\tchar\tm_GameStarted;\r\n\tchar\tm_HostMode;\r\n\tchar\tm_Ranked;\r\n\tchar\tm_Name[GameNet::vMAX_SERVER_NAME_LEN + 1];\r\n\tchar\tm_Level[32];\r\n\tchar\tm_Mode[32];\r\n\tchar\tm_SkillLevel;\r\n\tint\t\tm_Timestamp;\r\n\tchar\tm_PlayerNames[vMAX_PLAYERS][ vMAX_PLAYER_NAME_LEN + 1 ];\r\n};\r\n\r\nclass ObjectUpdate\r\n{\r\npublic:\r\n\tshort\t\t\tm_ObjId;\r\n\tMth::Vector\t\tm_Pos;\r\n\tMth::Matrix\t\tm_Matrix;\r\n};\r\n\r\nclass MsgScriptedSound\r\n{\r\npublic:\r\n\tchar\t\t\tm_ObjId;\r\n\tuint32 \t\t\tm_SoundChecksum;\r\n\tint \t\t\tm_Volume;\r\n\tint \t\t\tm_Pitch;\r\n};\r\n\r\nclass MsgPlaySound\r\n{\r\npublic:\r\n\tshort \t\t\tm_Pos[3];\r\n\tchar \t\t\tm_WhichArray;\r\n\tchar\t\t\tm_SurfaceFlag;\r\n\tchar \t\t\tm_VolPercent;\r\n\tchar\t\t\tm_PitchPercent;\r\n\tchar\t\t\tm_SoundChoice;\r\n};\r\n\r\nclass MsgObjMessage\r\n{\r\npublic:\r\n\tchar\t\t\tm_ObjId;\r\n};\r\n\r\nclass MsgPlayLoopingSound\r\n{\r\npublic:\r\n\tchar\t\t\tm_ObjId;\r\n\tint \t\t\tm_WhichArray;\r\n\tint\t\t\t\tm_SurfaceFlag;\r\n\tfloat \t\t\tm_VolPercent;\r\n};\r\n\r\nclass MsgBlood : public MsgObjMessage\r\n{\r\npublic:\r\n\tchar\t\t\tm_BodyPart;\r\n\tfloat\t\t\tm_Size;\r\n\tfloat\t\t\tm_Frequency;\r\n\tfloat\t\t\tm_RandomRadius;\r\n};\r\n\r\nclass MsgBloodOff : public MsgObjMessage\r\n{\r\npublic:\r\n\tchar\t\t\tm_BodyPart;\r\n};\r\n\r\nclass MsgActuator\r\n{\r\npublic:\r\n\tchar\t\t\tm_ActuatorId;\t// left/right\r\n\tchar\t\t\tm_Percent;\t\t// between 1 and 100\r\n\tunsigned short\tm_Duration;\t\t// ms duration\r\n};\r\n\r\nclass MsgEmbedded\r\n{\r\npublic:\r\n\tchar\tm_SubMsgId;\t\t// Sub-message\r\n};\r\n\r\nclass MsgScoreLogTrickObject : public MsgEmbedded\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvMAX_PENDING_TRICKS = 512,\t// how much data we can send across\r\n\t};\r\n\t\r\n\tunsigned char\tm_GameId;\r\n\tint\t\tm_OwnerId;\r\n\tint\t\tm_Score;\r\n\tuint32\tm_NumPendingTricks;\r\n\tuint32\tm_PendingTrickBuffer[vMAX_PENDING_TRICKS];\r\n};\r\n\r\nclass MsgObsScoreLogTrickObject\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvMAX_PENDING_TRICKS = 512,\t// how much data we can send across\r\n\t};\r\n\t\r\n\tunsigned char\tm_GameId;\r\n\tint\t\tm_OwnerId;\r\n\tuint32\tm_NumPendingTricks;\r\n\tuint32\tm_PendingTrickBuffer[vMAX_PENDING_TRICKS];\r\n};\r\n\r\nclass MsgScoreLanded\r\n{\r\npublic:\r\n\tunsigned char\tm_GameId;\r\n\tint\t\tm_Score;\r\n};\r\n\r\nclass MsgBeatGoal\r\n{\r\npublic:\r\n\tunsigned char\tm_GameId;\r\n\tuint32\t\t\tm_GoalId;\r\n};\r\n\r\nclass MsgBeatGoalRelay\r\n{\r\npublic:\r\n\tchar\t\t\tm_ObjId;\r\n\tuint32\t\t\tm_GoalId;\r\n};\r\n\r\ntypedef MsgBeatGoal MsgStartedGoal;\r\ntypedef MsgBeatGoalRelay MsgStartedGoalRelay;\r\n\r\nclass MsgScoreUpdate\r\n{\r\npublic:\r\n\tint\t\tm_TimeLeft;\t\t// Time left in the game\r\n\tFlags< int > m_Cheats;\r\n\tchar\tm_Final;\t\t// Final scores?\r\n\tchar\tm_NumScores;\r\n\tchar\tm_ScoreData[256];\r\n};\r\n\r\nclass MsgSpawnAndRunScript\r\n{\r\npublic:\r\n\tuint32\tm_ScriptName;\r\n\tint\t\tm_ObjID;\r\n\tint\t\tm_Node;\r\n\tchar\tm_Permanent;\t// is this an event that the server should queue up for new joiners?\r\n};\r\n\r\nclass MsgToggleProSet\r\n{\r\npublic:\r\n\tuint32\tm_ParamId;\r\n\tchar\tm_Bit;\r\n};\r\n\r\nclass MsgToggleCheat\r\n{\r\npublic:\r\n\tuint32\tm_Cheat;\r\n\tchar\tm_On;\r\n};\r\n\r\nclass MsgEnabledCheats\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvMAX_CHEATS = 32,\r\n\t};\r\n\tint\t\tm_NumCheats;\r\n\tuint32\tm_Cheats[vMAX_CHEATS];\r\n};\r\n\r\nclass MsgStealMessage\r\n{\r\npublic:\r\n\tunsigned char\tm_GameId;\r\n\tint\t\tm_NewOwner;\t\t// new owner of the trick object\r\n\tint\t\tm_OldOwner;\t\t// old owner of the trick object\r\n};\r\n\r\nclass MsgRunScript\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvMAX_SCRIPT_PARAMS_LEN = 1024\r\n\t};\r\n\tuint32\tm_ScriptName;\r\n\tint\t\tm_ObjID;\r\n\tchar\tm_Data[vMAX_SCRIPT_PARAMS_LEN];\r\n};\r\n\r\nclass MsgChangeLevel\r\n{\r\npublic:\r\n\tint\t\tm_Level;\r\n\tchar\tm_ShowWarning;\r\n};\r\n\r\nclass MsgChangeTeam\r\n{\r\npublic:\r\n\tchar\tm_ObjID;\r\n\tchar\tm_Team;\r\n};\r\n\r\nclass MsgByteInfo\t\t// Generic one-byte message\r\n{\r\npublic:\r\n\tchar\tm_Data;\r\n};\r\n\r\nclass MsgIntInfo\t\t// Generic four-byte message\r\n{\r\n\tpublic:\r\n\t\tint\t\tm_Data;\r\n};\r\n\r\nclass MsgChat\r\n{\r\n\tpublic:\r\n\t\tchar\tm_ObjId;\r\n\t\tchar\tm_Name[vMAX_PLAYER_NAME_LEN + 1];\r\n\t\tchar\tm_ChatMsg[vMAX_CHAT_MSG_LEN + 1];\r\n};\r\n\r\nclass MsgRequestLevel\r\n{\r\npublic:\r\n\tuint32\t\tm_LevelId;\r\n\tchar\t\tm_Source;\t// Was this request the result of a \"StartInfo\" message or a \"Change Level\" message\r\n};\r\n\r\nclass MsgRemovePlayerRequest\r\n{\r\npublic:\r\n\tchar\tm_Ban;\t// Should we ban? If not, just kick\r\n\tchar\tm_Index;\r\n\tchar\tm_Name[vMAX_PLAYER_NAME_LEN + 1];\r\n};\r\n\r\nclass MsgStartGameRequest\r\n{\r\npublic:\r\n\tuint32\tm_GameMode;\r\n\tuint32\tm_TimeLimit;\r\n\tuint32\tm_SkillLevel;\r\n\tuint32\tm_FireballLevel;\r\n\tuint32\tm_PlayerCollision;\r\n\tuint32\tm_FriendlyFire;\r\n\tuint32\tm_TeamMode;\r\n\tuint32\tm_TargetScore;\r\n\tuint32\tm_StopAtZero;\r\n\tuint32\tm_CTFType;\r\n};\r\n\r\nclass MsgCheatChecksum\r\n{\r\npublic:\r\n\tuint32\tm_ServerChecksum;\r\n\tuint32\tm_ClientChecksum;\r\n};\r\n\r\nclass MsgProjectile\r\n{\r\npublic:\r\n\tuint32\t\tm_Latency;\r\n\tMth::Vector\tm_Pos;\r\n\tMth::Vector\tm_Vel;\r\n\tuint32\t\tm_Type;\r\n\tint\t\t\tm_Radius;\r\n\tfloat\t\tm_Scale;\r\n\tchar\t\tm_Id;\r\n};\r\n\r\nclass MsgProjectileHit\r\n{\r\npublic:\r\n\tchar\tm_Id;\r\n\tint\t\tm_Damage;\r\n\r\n};\r\n\r\nclass MsgCollideLost\r\n{\r\npublic:\r\n\tchar\t\tm_Id;\r\n\tMth::Vector\tm_Offset;\r\n};\r\n\r\nclass MsgEnterVehicle\r\n{\r\npublic:\r\n\tchar\t\tm_Id;\r\n\tuint32\t\tm_ControlType;\r\n};\r\n\r\nclass MsgProceed\r\n{\r\npublic:\r\n\tint\t\t\tm_PublicIP;\r\n\tint\t\t\tm_PrivateIP;\r\n\tint\t\t\tm_Port;\r\n\tchar\t\tm_ServerName[GameNet::vMAX_SERVER_NAME_LEN + 1];\r\n\tchar\t\tm_MaxPlayers;\r\n\tchar\t\tm_Broadband;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n#endif\t// __GAMENET_GAMEMSG_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/GameNet.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tGameNet.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/01/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGame-Side Network Functionality\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// start autoduck documentation\r\n// @DOC gamenet\r\n// @module gamenet | None\r\n// @subindex Scripting Database\r\n// @index script | gamenet\r\n                          \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <sys/mcman.h>\r\n#include <sys/SIO/keyboard.h>\r\n\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n#include <gfx/nxviewman.h>\r\n#include <gfx/skeleton.h>\r\n#include <gfx/2d/screenelemman.h>\r\n#include <gfx/FaceTexture.h>\r\n#include <gfx/FaceMassage.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/frontend/frontend.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/ParkEditor2/EdMap.h>\r\n#include <sk/ParkEditor2/parked.h>\r\n//#include <sk/modules/frontend/mainmenu.h>\r\n\r\n#include <sk/components/skaterscorecomponent.h>\r\n#include <sk/components/GoalEditorComponent.h>\r\n#include <sk/components/skaterstatehistoryComponent.h>\r\n#include <sk/components/skaterphysicscontrolComponent.h>\r\n\r\n#include <sk/objects/crown.h>\r\n#include <sk/objects/restart.h>\r\n#include <sk/objects/proxim.h>\r\n#include <sk/objects/skatercam.h>\r\n#include <sk/objects/skaterprofile.h>\r\n\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/components/skatercameracomponent.h>\r\n#include <gel/components/walkcameracomponent.h>\r\n\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <sk/components/RailEditorComponent.h>\r\n\r\n#ifdef __PLAT_NGPS__\r\n#include <gamenet/lobby.h>\r\n#include <gamenet/ngps/p_content.h>\r\n#include <gamenet/ngps/p_buddy.h>\r\n#include <gamenet/ngps/p_stats.h>\r\n#endif\r\n\r\n#ifdef __PLAT_XBOX__\r\n#include <Sk/GameNet/Xbox/p_auth.h>\r\n#include <Sk/GameNet/Xbox/p_buddy.h>\r\n#include <Sk/GameNet/Xbox/p_voice.h>\r\n#endif\r\n\r\n#include <sk/objects/skater.h>\t\t   // we do various things with the skater, network play related\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern bool g_CheatsEnabled;\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\r\n\r\nDefineSingletonClass( Manager, \"Game Network Manager\" )\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __PLAT_NGC__\r\nextern\tbool\t gEnteringFromMainMenu;\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n#define USE_DNS\t1\r\nenum\r\n{   \r\n\tvMAX_TOLERABLE_RESENDS = 20\t// we'll allow 20 reseonds of messages to ready coonections but that's our limit\r\n};\r\n\r\n#define vTIME_BEFORE_STARTING_NETGAME   Tmr::Seconds( 3 )\r\n#define vTIME_BEFORE_STARTING_GOALATTACK   Tmr::Seconds( 8 )\r\n#define vAUTO_START_INTERVAL\t\t\tTmr::Seconds( 5 )\r\n#define vLINK_CHECK_FREQUENCY\t\t\tTmr::Seconds( 1 )\r\n#define vTAUNT_INTERVAL\t\t\tTmr::Seconds( 2 )\r\n#define vMAX_FACE_DATA_SIZE\t\t( Gfx::CFaceTexture::vTOTAL_CFACETEXTURE_SIZE )\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic Tmr::Time\ts_time_to_start_game;\r\nstatic Tmr::Time\ts_auto_serve_start_time;\r\n//static bool\t\t\ts_waiting_for_game_to_start = false;\r\n//static Tmr::Time\ts_usage_tracking_start_time;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nManager::Manager( void )\r\n{\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\tint i;\r\n\r\n\t\r\n\r\n\tnet_man->SetMessageName( MSG_ID_SKATER_INPUT, \"Skater Input\" );\r\n\tnet_man->SetMessageName( MSG_ID_PLAYER_CREATE, \"Player Create\" );\r\n\tnet_man->SetMessageName( MSG_ID_JOIN_ACCEPTED, \"Join Accepted\" );\r\n\tnet_man->SetMessageName( MSG_ID_OBJ_UPDATE_STREAM, \"Object Update Stream\" );\r\n\tnet_man->SetMessageName( MSG_ID_NEW_ALIAS, \"New Alias\" );\r\n\tnet_man->SetMessageName( MSG_ID_READY_QUERY, \"Ready Query\" );\r\n\tnet_man->SetMessageName( MSG_ID_READY_RESPONSE, \"Ready Response\" );\r\n\tnet_man->SetMessageName( MSG_ID_PAUSE, \"Pause\" );\r\n\tnet_man->SetMessageName( MSG_ID_UNPAUSE, \"Unpause\" );\r\n\tnet_man->SetMessageName( MSG_ID_PRIM_ANIM_START, \"Primary Animation\" );\r\n\tnet_man->SetMessageName( MSG_ID_FLIP_ANIM, \"Flip Animation\" );\r\n\tnet_man->SetMessageName( MSG_ID_ROTATE_SKATEBOARD, \"Rotate Skateboard\" );\r\n\tnet_man->SetMessageName( MSG_ID_ROTATE_DISPLAY, \"Rotate Display\" );\r\n\tnet_man->SetMessageName( MSG_ID_CLEAR_ROTATE_DISPLAY, \"Clear Rotate Display\" );\r\n\tnet_man->SetMessageName( MSG_ID_CREATE_SPECIAL_ITEM, \"Create Item\" );\r\n\tnet_man->SetMessageName( MSG_ID_DESTROY_SPECIAL_ITEM, \"Destroy Item\" );\r\n\tnet_man->SetMessageName( MSG_ID_SET_WOBBLE_TARGET, \"Set Wobble Target\" );\r\n\tnet_man->SetMessageName( MSG_ID_SET_WOBBLE_DETAILS, \"Set Wobble Details\" );\r\n\tnet_man->SetMessageName( MSG_ID_SET_LOOPING_TYPE, \"Set Looping Type\" );\r\n\tnet_man->SetMessageName( MSG_ID_SET_HIDE_ATOMIC, \"Hide Atomic\" );\r\n\tnet_man->SetMessageName( MSG_ID_SET_ANIM_SPEED, \"Set anim speed\" );\r\n\tnet_man->SetMessageName( MSG_ID_PLAYER_QUIT, \"Player Quit\" );\t\r\n\tnet_man->SetMessageName( MSG_ID_HOST_PROCEED, \"Proceed Hosting\" );\r\n\tnet_man->SetMessageName( MSG_ID_GAMELIST_RESPONSE, \"Gamelist\" );\r\n\tnet_man->SetMessageName( MSG_ID_HOST_QUIT, \"Host Shutdown\" );\r\n\tnet_man->SetMessageName( MSG_ID_START_INFO, \"Start Info\" );\r\n\tnet_man->SetMessageName( MSG_ID_GAME_INFO, \"Game Info\" );\r\n\tnet_man->SetMessageName( MSG_ID_PLAY_SOUND, \"Play Sound\" );\r\n\tnet_man->SetMessageName( MSG_ID_PLAY_LOOPING_SOUND, \"Play Looping Sound\" );\r\n\tnet_man->SetMessageName( MSG_ID_SPARKS_ON, \"Sparks On\" );\r\n\tnet_man->SetMessageName( MSG_ID_SPARKS_OFF, \"Sparks Off\" );\r\n\tnet_man->SetMessageName( MSG_ID_BLOOD_ON, \"Blood On\" );\r\n\tnet_man->SetMessageName( MSG_ID_BLOOD_OFF, \"Blood Off\" );\r\n\tnet_man->SetMessageName( MSG_ID_SCORE, \"Score Msg\" );\r\n\tnet_man->SetMessageName( MSG_ID_PANEL_MESSAGE, \"Panel Message\" );\r\n\tnet_man->SetMessageName( MSG_ID_SCORE_UPDATE, \"Score Update\" );\r\n\tnet_man->SetMessageName( MSG_ID_PROCEED_TO_PLAY, \"Proceed To Play\" );\r\n\tnet_man->SetMessageName( MSG_ID_SKATER_COLLIDE_LOST, \"Skater Col Lost\" );\r\n\tnet_man->SetMessageName( MSG_ID_SKATER_COLLIDE_WON, \"Skater Col Win\" );\r\n\tnet_man->SetMessageName( MSG_ID_SKATER_HIT_BY_PROJECTILE, \"Hit by projectile\" );\r\n\tnet_man->SetMessageName( MSG_ID_SKATER_PROJECTILE_HIT_TARGET, \"Projectile Hit\" );\r\n\tnet_man->SetMessageName( MSG_ID_BAIL_DONE, \"Bail done\" );\r\n\tnet_man->SetMessageName( MSG_ID_RUN_SCRIPT, \"Run Script\" );\r\n\tnet_man->SetMessageName( MSG_ID_SPAWN_AND_RUN_SCRIPT, \"SpawnRun Script\" );\r\n\tnet_man->SetMessageName( MSG_ID_OBSERVE, \"Observe\" );\r\n\tnet_man->SetMessageName( MSG_ID_STEAL_MESSAGE, \"Steal message\" );\r\n\tnet_man->SetMessageName( MSG_ID_CHAT, \"Chat Message\" );\r\n\tnet_man->SetMessageName( MSG_ID_OBSERVE_PROCEED, \"Proceed to Observe\" );\r\n\tnet_man->SetMessageName( MSG_ID_OBSERVE_REFUSED, \"Observe Refused\" );\r\n\tnet_man->SetMessageName( MSG_ID_JOIN_PROCEED, \"Proceed to Join\" );\r\n\tnet_man->SetMessageName( MSG_ID_JOIN_REQ, \"Join Request\" );\r\n\tnet_man->SetMessageName( MSG_ID_KICKED, \"Kick Message\" );\r\n\tnet_man->SetMessageName( MSG_ID_LANDED_TRICK, \"Landed Trick\" );\r\n\tnet_man->SetMessageName( MSG_ID_PLAYER_INFO_ACK_REQ, \"Player Ack Req\" );\r\n\tnet_man->SetMessageName( MSG_ID_PLAYER_INFO_ACK, \"Player Info Ack\" );\r\n\tnet_man->SetMessageName( MSG_ID_NEW_KING, \"New King\" );\r\n\tnet_man->SetMessageName( MSG_ID_LEFT_OUT, \"Left Out\" );\r\n\tnet_man->SetMessageName( MSG_ID_MOVED_TO_RESTART, \"Moved to Restart\" );\r\n\tnet_man->SetMessageName( MSG_ID_KING_DROPPED_CROWN, \"Dropped Crown\" );\r\n\tnet_man->SetMessageName( MSG_ID_PLAYER_DROPPED_FLAG, \"Dropped Flag\" );\r\n\tnet_man->SetMessageName( MSG_ID_RUN_HAS_ENDED, \"Run ended\" );\r\n\tnet_man->SetMessageName( MSG_ID_GAME_OVER, \"Game over\" );\r\n\tnet_man->SetMessageName( MSG_ID_OBSERVER_LOG_TRICK_OBJ, \"Observer Log Trick Object\" );\r\n\tnet_man->SetMessageName( MSG_ID_OBSERVER_INIT_GRAFFITI_STATE, \"Observer Init Graffiti State\" );\r\n\tnet_man->SetMessageName( MSG_ID_AUTO_SERVER_NOTIFICATION, \"Auto-Server Notification\" );\r\n\tnet_man->SetMessageName( MSG_ID_FCFS_ASSIGNMENT, \"FCFS Assignment\" );\r\n\tnet_man->SetMessageName( MSG_ID_FCFS_END_GAME, \"FCFS End Game\" );\r\n\tnet_man->SetMessageName( MSG_ID_FCFS_SET_NUM_TEAMS, \"FCFS Num Teams\" );\r\n\tnet_man->SetMessageName( MSG_ID_END_GAME, \"End Game\" );\r\n\tnet_man->SetMessageName( MSG_ID_SELECT_GOALS, \"Select Goals\" );\r\n\tnet_man->SetMessageName( MSG_ID_BEAT_GOAL, \"Beat Goal\" );\r\n\tnet_man->SetMessageName( MSG_ID_STARTED_GOAL, \"Started Goal\" );\r\n\tnet_man->SetMessageName( MSG_ID_TOGGLE_PROSET, \"Toggle proset\" );\r\n\tnet_man->SetMessageName( MSG_ID_FCFS_TOGGLE_PROSET, \"FCFS Toggle proset\" );\r\n\tnet_man->SetMessageName( MSG_ID_FCFS_TOGGLE_GOAL_SELECTION, \"FCFS Toggle Goal\" );\r\n\tnet_man->SetMessageName( MSG_ID_KILL_TEAM_FLAGS, \"Kill Team Flags\" );\r\n\tnet_man->SetMessageName( MSG_ID_WAIT_N_SECONDS, \"Wait N Seconds\" );\r\n\tnet_man->SetMessageName( MSG_ID_CHEAT_CHECKSUM_REQUEST, \"CC Request\" );\r\n\tnet_man->SetMessageName( MSG_ID_CHEAT_CHECKSUM_RESPONSE, \"CC Response\" );\r\n    \r\n\tnet_man->SetMessageFlags( MSG_ID_OBJ_UPDATE_STREAM, Net::mMSG_SIZE_UNKNOWN );\r\n\t\t\r\n\tfor( i = 0; i < vMAX_LOCAL_CLIENTS; i++ )\r\n\t{\r\n\t\tm_client[i] = NULL;\r\n\t\tm_match_client = NULL;\r\n\t}\r\n\t\r\n\tm_server = NULL;\r\n    \r\n\tm_metrics_on = false;\r\n\tm_scores_on = false;\r\n\tm_cheating_occurred = false;\r\n\tm_draw_player_names = true;\r\n\tm_sort_key = vSORT_KEY_NAME;\r\n\tm_host_mode = vHOST_MODE_SERVE;\r\n\tm_server_list_state = vSERVER_LIST_STATE_SHUTDOWN;\r\n\tm_next_server_list_state = vSERVER_LIST_STATE_SHUTDOWN;\r\n    \r\n\t// initialize the network preferences\r\n\tm_network_preferences.Load( Script::GenerateCRC(\"default_network_preferences\" ) );\r\n\tm_taunt_preferences.Load( Script::GenerateCRC(\"default_taunt_preferences\" ) );\r\n\r\n\tm_timeout_connections_task = new Tsk::Task< Manager > ( s_timeout_connections_code, *this,\r\n\t\t\t\t\t\t\t\t\t\tTsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_TIMEOUT_CONNECTIONS );\r\n\tm_render_metrics_task = new Tsk::Task< Manager > ( s_render_metrics_code, *this );\r\n    m_auto_refresh_task = new Tsk::Task< Manager > ( s_auto_refresh_code, *this );\r\n\tm_auto_server_task = new Tsk::Task< Manager > ( s_auto_server_code, *this );\r\n\tm_render_scores_task = new Tsk::Task< Manager > ( s_render_scores_code, *this );\r\n\tm_client_add_new_players_task = new Tsk::Task< Manager > ( s_client_add_new_players_code, *this, \r\n\t\t\t\t\t\t\t\t\t\tTsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_CLIENT_ADD_NEW_PLAYERS );\r\n\tm_server_add_new_players_task = new Tsk::Task< Manager > ( s_server_add_new_players_code, *this, \r\n\t\t\t\t\t\t\t\t\t\tTsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_SERVER_ADD_NEW_PLAYERS );\r\n    m_enter_chat_task = new Tsk::Task< Manager > ( s_enter_chat_code, *this );\r\n\tm_modem_state_task = new Tsk::Task< Manager > ( s_modem_state_code, *this );\r\n\tm_join_timeout_task = new Tsk::Task< Manager > ( s_join_timeout_code, *this );\r\n\tm_server_list_state_task = new Tsk::Task< Manager > ( s_server_list_state_code, *this );\r\n\tm_join_state_task = new Tsk::Task< Manager > ( s_join_state_code, *this );\r\n\tm_start_network_game_task = new Tsk::Task< Manager > ( s_start_network_game_code, *this );\r\n\tm_change_level_task = new Tsk::Task< Manager > ( s_change_level_code, *this );\r\n\tm_ctf_logic_task = new Tsk::Task< Manager > ( s_ctf_logic_code, *this );\r\n\r\n\tmlp_manager->AddLogicTask( *m_timeout_connections_task );\r\n\r\n\tm_last_modem_state = Net::vMODEM_STATE_DISCONNECTED;\r\n\tm_goals_data_size = 0;\r\n\tm_goals_level = 0;\r\n\r\n#ifdef __PLAT_XBOX__\r\n\tm_XboxKeyRegistered = false;\r\n\tmpAuthMan = new AuthMan;\r\n\tmpBuddyMan = new BuddyMan;\r\n\tmpVoiceMan = new VoiceMan;\r\n#endif\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tm_got_motd = false;\r\n\tmpLobbyMan = new LobbyMan;\r\n\tmpContentMan = new ContentMan;\r\n\tmpBuddyMan = new BuddyMan;\r\n\tmpStatsMan = new StatsMan;\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager( void )\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\tdelete mpLobbyMan;\r\n\tdelete mpContentMan;\r\n\tdelete mpBuddyMan;\r\n\tdelete mpStatsMan;\r\n#endif\r\n\r\n\tdelete m_client_add_new_players_task;\r\n\tdelete m_server_add_new_players_task;\r\n\tdelete m_timeout_connections_task;\r\n\tdelete m_render_metrics_task;\r\n\tdelete m_enter_chat_task;\r\n\tdelete m_server_list_state_task;\r\n\tdelete m_join_state_task;\r\n\tdelete m_start_network_game_task;\r\n\tdelete m_change_level_task;\r\n    delete m_auto_refresh_task;\r\n#ifdef __PLAT_XBOX__\r\n\tdelete mpAuthMan;\r\n\tdelete mpBuddyMan;\r\n\tdelete mpVoiceMan;\r\n#endif // __PLAT_XBOX__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::free_all_players( void )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tPlayerInfo *player, *next;\r\n\tLst::Search< PlayerInfo > sh;\r\n\r\n\tfor( player = FirstPlayerInfo( sh, true ); player; player = next )\r\n\t{\r\n\t\tnext = NextPlayerInfo( sh, true );\r\n\t\t// if this player has a skater\r\n\t\tif( player->m_Skater )\r\n\t\t{\r\n\t\t\t// and the skater is not on the default heap, or it's not a local player\r\n\t\t\tif ( player->m_Skater->GetHeapIndex() != 0 || !player->IsLocalPlayer() )\r\n\t\t\t{\r\n\t\t\t\t// then remove it (deletes the CSkater, which will unload any model)\r\n\t\t\t\tskate_mod->remove_skater( player->m_Skater );\r\n\t\t\t}\r\n\t\t}\r\n\t\tDestroyPlayer( player );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::free_all_pending_players( void )\r\n{\r\n\tLst::Node< NewPlayerInfo > *node, *next;\r\n\tNewPlayerInfo* new_info;\r\n\t\t\r\n\t\r\n\r\n\tDbg_Printf( \"Destroying Pending Players\\n\" );\r\n\tfor( node = m_new_players.GetNext(); node; node = next )\r\n\t{\r\n\t\tnext = node->GetNext();\r\n\r\n\t\tnew_info = node->GetData();\r\n\r\n\t\tif( m_server )\r\n\t\t{\r\n\t\t\tDbg_Printf( \"Removing %s\\n\", new_info->Name );\r\n\t\t\tm_server->TerminateConnection( new_info->Conn );\r\n\t\t}\r\n\t\t\r\n\t\tdelete node;\r\n\t\tdelete new_info;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::s_observer_logic_code ( const Tsk::Task< PlayerInfo >& task )\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\t// Dan: Proxim_Update use is now done through CProximTriggerComponents attached to the camera CCompositeObjects.  Thus, the observer's\r\n\t// camera should handle proxim updating\ton its own.\r\n\t\r\n\t// PlayerInfo* current_player;\r\n\t// current_player = gamenet_man->GetCurrentlyObservedPlayer();\r\n\t// if( current_player )\r\n\t// {\r\n\t\t// Obj::CSkater* skater;\r\n\t\t// skater = local_player.m_cam->GetSkater();\r\n\t\r\n\t\t// if( skater )\r\n\t\t// {   \r\n\t\t\t// Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\t// if( current_player->IsFullyIn())\r\n\t\t\t// {\r\n\t\t\t\t// local_player.m_cam->Update( false );\r\n\t\t\t\r\n\t\t\t\t// if( skate_mod->mpProximManager )\r\n\t\t\t\t// {   \r\n\t\t\t\t\t// if( local_player.m_cam )\r\n\t\t\t\t\t// {\r\n\t\t\t\t\t\t// Obj::Proxim_Update( skater, local_player.m_cam );\r\n\t\t\t\t\t// }\r\n\t\t\t\t// }\r\n\t\t\t// }\r\n\t\t// }\r\n\t// }\r\n\r\n\tif( gamenet_man->GetObserverCommand() == vOBSERVER_COMMAND_NEXT )\r\n\t{\r\n\t\tDbg_Printf( \"Got observer next command.....\\n\" );\r\n\r\n\t\tPlayerInfo*\tplayer;\r\n\t\t\r\n\t\tplayer = gamenet_man->GetNextPlayerToObserve();\r\n\t\tgamenet_man->ObservePlayer( player );\r\n\r\n\t\tgamenet_man->SetObserverCommand( vOBSERVER_COMMAND_NONE );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_observer_input_logic_code ( const Inp::Handler < Manager >& handler )\r\n{\r\n    \r\n\r\n\tManager&\tman = handler.GetData();\r\n\t\r\n\tFront::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();\r\n\tFront::CScreenElement* p_root_window = p_screen_elem_man->GetElement( Script::GenerateCRC( \"root_window\" ) , \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tFront::CScreenElementManager::DONT_ASSERT );\r\n\t// If any operable menus are up, ignore input\r\n\tif( p_root_window )\r\n\t{\r\n\t\tScript::CStruct* pTags = new Script::CStruct();\r\n\t\tp_root_window->CopyTagsToScriptStruct( pTags );\r\n\t\tuint32 menu_state;\r\n\t\tpTags->GetChecksum( \"menu_state\", &menu_state, Script::NO_ASSERT );\r\n\t\tdelete pTags;\r\n\t\tif ( menu_state == Script::GenerateCRC( \"on\" ) )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tif( handler.m_Input->m_Makes & Inp::Data::mD_X )\r\n\t{\r\n\t\tDbg_Printf( \"Got X, inserting command....\\n\" );\r\n\t\tman.SetObserverCommand( vOBSERVER_COMMAND_NEXT );\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_auto_server_code( const Tsk::Task< Manager >& task )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tManager& man = task.GetData();\r\n\r\n\t// Give it a couple of seconds before activating\r\n\tif(( Tmr::GetTime() - s_auto_serve_start_time ) < Tmr::Seconds( 2 ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tif( ( skate_mod->GetGameMode()->GetNameChecksum() != Script::GenerateCRC( \"netlobby\" )))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif( man.GetNumPlayers() < 2 )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif( man.m_waiting_for_game_to_start )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif(( Tmr::GetTime() - man.m_lobby_start_time ) > vAUTO_START_INTERVAL )\r\n\t{\r\n        Dbg_Printf( \"Starting Network Game....\\n\" );\r\n\t\tScript::RunScript( \"LoadPendingPlayers\" );\r\n\t\tScript::RunScript( \"StartNetworkGame\" );\r\n\t\tman.m_waiting_for_game_to_start = true;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_enter_chat_code( const Tsk::Task< Manager >& task )\r\n{\r\n\tint num_chars;\r\n\tchar makes[256];\r\n\tstatic Tmr::Time s_last_taunt_time = 0;\r\n\t\t\r\n\tnum_chars = SIO::KeyboardRead( makes );\r\n\r\n\tif( num_chars > 0 )\r\n\t{\r\n\t\t// Space and enter bring up the chat interface\r\n\t\tif( ( makes[0] == SIO::vKB_ENTER ) ||\r\n\t\t\t( makes[0] == 32 ))\r\n\t\t{\r\n\t\t\tScript::CStruct* pParams;\r\n\t\t\t\r\n\t\t\tpParams = new Script::CStruct;\r\n\t\t\tpParams->AddChecksum( Script::GenerateCRC( \"id\" ), Script::GenerateCRC( \"keyboard_anchor\" ));\r\n\t\t\t\r\n\t\t\t// Enter and space act as \"choose\" only if you're not currently using the on-screen keyboard\r\n\t\t\tif( Obj::ScriptObjectExists( pParams, NULL ) == false )\r\n\t\t\t{\r\n\t\t\t\tpParams->Clear();\r\n\t\t\t\tpParams->AddChecksum( Script::GenerateCRC( \"id\" ), Script::GenerateCRC( \"current_menu_anchor\" ));\r\n\t\t\t\tif( Obj::ScriptObjectExists( pParams, NULL ) == false )\r\n\t\t\t\t{\r\n\t\t\t\t\tpParams->Clear();\r\n\t\t\t\t\tpParams->AddChecksum( Script::GenerateCRC( \"id\" ), Script::GenerateCRC( \"dialog_box_anchor\" ));\r\n\t\t\t\t\tif( Obj::ScriptObjectExists( pParams, NULL ) == false )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tScript::RunScript( \"enter_kb_chat\" );\r\n\t\t\t\t\t\tSIO::KeyboardClear();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( makes[0] == SIO::vKB_F1 )\r\n\t\t{\r\n\t\t\tif(( Tmr::GetTime() - s_last_taunt_time ) > vTAUNT_INTERVAL )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pParams;\r\n\r\n\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\tpParams->AddChecksum( CRCD(0xb53d0e0f,\"string_id\"), CRCD(0xe5fd359,\"props_string\"));\r\n\t\t\t\tScript::RunScript( \"SendTauntMessage\", pParams );\r\n\t\t\t\tdelete pParams;\r\n\r\n\t\t\t\ts_last_taunt_time = Tmr::GetTime();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( makes[0] == SIO::vKB_F2 )\r\n\t\t{\r\n\t\t\tif(( Tmr::GetTime() - s_last_taunt_time ) > vTAUNT_INTERVAL )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pParams;\r\n\r\n\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\tpParams->AddChecksum( CRCD(0xb53d0e0f,\"string_id\"), CRCD(0xbeea3518,\"your_daddy_string\"));\r\n\t\t\t\tScript::RunScript( \"SendTauntMessage\", pParams );\r\n\t\t\t\tdelete pParams;\r\n\r\n\t\t\t\ts_last_taunt_time = Tmr::GetTime();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( makes[0] == SIO::vKB_F3 )\r\n\t\t{\r\n\t\t\tif(( Tmr::GetTime() - s_last_taunt_time ) > vTAUNT_INTERVAL )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pParams;\r\n\r\n\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\tpParams->AddChecksum( CRCD(0xb53d0e0f,\"string_id\"), CRCD(0x4525adbd,\"get_some_string\"));\r\n\t\t\t\tScript::RunScript( \"SendTauntMessage\", pParams );\r\n\t\t\t\tdelete pParams;\r\n\r\n\t\t\t\ts_last_taunt_time = Tmr::GetTime();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( makes[0] == SIO::vKB_F4 )\r\n\t\t{\r\n\t\t\tif(( Tmr::GetTime() - s_last_taunt_time ) > vTAUNT_INTERVAL )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pParams;\r\n\r\n\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\tpParams->AddChecksum( CRCD(0xb53d0e0f,\"string_id\"), CRCD(0xa36dbee1,\"no_way_string\"));\r\n\t\t\t\tScript::RunScript( \"SendTauntMessage\", pParams );\r\n\t\t\t\tdelete pParams;\r\n\r\n\t\t\t\ts_last_taunt_time = Tmr::GetTime();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_join_state_code( const Tsk::Task< Manager >& task )\r\n{\r\n\tManager& man = task.GetData();\r\n\t\t\r\n\tswitch( man.GetJoinState())\r\n\t{   \r\n\t\tcase vJOIN_STATE_TRYING_PASSWORD:\r\n\t\tcase vJOIN_STATE_WAITING:\r\n\t\t{   \r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vJOIN_STATE_CONNECTING:\r\n\t\t{   \r\n\t\t\tScript::RunScript( \"CreateConnectingDialog\" );\r\n\t\t\t\r\n\t\t\tman.SetJoinState( vJOIN_STATE_WAITING );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vJOIN_STATE_JOINING:\r\n\t\t{\r\n\t\t\tNet::Client* client;\r\n\r\n\t\t\tclient = man.GetClient( 0 );\r\n\t\t\tif( !client->IsLocal())\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( \"CreateJoiningDialog\" );\r\n\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\tman.SetJoinState( vJOIN_STATE_WAITING );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vJOIN_STATE_JOINING_WITH_PASSWORD:\r\n\t\t{\r\n\t\t\tScript::RunScript( \"CreateTryingPasswordDialog\" );\r\n\t\t\t\r\n\t\t\tman.SetJoinState( vJOIN_STATE_TRYING_PASSWORD );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vJOIN_STATE_REFUSED:\r\n\t\t{\r\n\t\t\tScript::CStruct* p_structure = new Script::CStruct;\r\n\t\t\tp_structure->AddChecksum( \"reason\", man.m_conn_refused_reason );\r\n\r\n\t\t\tman.m_join_state_task->Remove();\r\n\r\n\t\t\tScript::RunScript( \"CreateJoinRefusedDialog\", p_structure );\r\n\t\t\tdelete p_structure;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vJOIN_STATE_GOT_PLAYERS:\r\n\t\t{\r\n\t\t\tLst::Search< NewPlayerInfo > sh;\r\n\t\t\tNewPlayerInfo* new_player;\t\t\r\n\t\t\t\r\n\t\t\t// If we're observing, we need to remove our skater\r\n\t\t\tfor( new_player = man.FirstNewPlayerInfo( sh ); new_player; new_player = man.NextNewPlayerInfo( sh ))\r\n\t\t\t{\r\n\t\t\t\tif( new_player->Flags & PlayerInfo::mLOCAL_PLAYER )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( new_player->Flags & PlayerInfo::mOBSERVER )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\t\t\t\t\t\tObj::CSkater* skater;\r\n\t\t\t\t\t\tskater = skate_mod->GetLocalSkater();\r\n\t\t\t\t\t\tDbg_Assert( skater );\r\n\t\t\t\t\t\tskate_mod->remove_skater( skater );\r\n\t\t\t\t\t\tman.ObservePlayer( NULL );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tScript::RunScript( \"entered_network_game\" );\r\n\r\n\t\t\tman.SetJoinState( vJOIN_STATE_WAITING_FOR_START_INFO );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vJOIN_STATE_WAITING_FOR_START_INFO:\r\n\t\t\tbreak;\r\n\t\tcase vJOIN_STATE_CONNECTED:\r\n\t\t{\r\n\t\t\tScript::RunScript( \"dialog_box_exit\" );\r\n\t\t\tman.m_join_timeout_task->Remove();\r\n\t\t}\r\n\t\t// Fall-through intentional\r\n\t\tcase vJOIN_STATE_FINISHED:\r\n\t\t{\r\n\t\t\tman.m_join_state_task->Remove();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_ctf_logic_code( const Tsk::Task< Manager >& task )\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tif( skate_mod->GetGameMode()->GetNameChecksum() != Script::GenerateCRC( \"netctf\" ))\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Shouldn't be running CTF logic in non-ctf game\" ));\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t{\r\n\t\tif( player->HasCTFFlag())\r\n\t\t{\r\n\t\t\tint team;\r\n\t\t\tuint32 obj_id;\r\n\t\t\tObj::CMovingObject* obj;\r\n\t\t\tObj::CMovingObject* moving_obj;\r\n\r\n\t\t\tteam = player->HasWhichFlag();\r\n\t\t\tswitch( team )\r\n\t\t\t{\r\n\t\t\t\tcase vTEAM_RED:\r\n\t\t\t\t\tobj_id = Script::GenerateCRC( \"TRG_CTF_Red\" );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vTEAM_BLUE:\r\n\t\t\t\t\tobj_id = Script::GenerateCRC( \"TRG_CTF_Blue\" );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vTEAM_GREEN:\r\n\t\t\t\t\tobj_id = Script::GenerateCRC( \"TRG_CTF_Green\" );\r\n\t\t\t\t\tbreak;\r\n\t\t\tcase vTEAM_YELLOW:\r\n\t\t\t\t\tobj_id = Script::GenerateCRC( \"TRG_CTF_Yellow\" );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t\tobj_id = 0;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tobj = (Obj::CMovingObject *) Obj::ResolveToObject( obj_id );\r\n\t\t\tif( obj == NULL )\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tmoving_obj = static_cast<Obj::CMovingObject *>( obj );\r\n\r\n\t\t\tGfx::CSkeleton* pSkeleton;\r\n\t\t\tpSkeleton = player->m_Skater->GetSkeleton();\r\n\t\t\tDbg_Assert( pSkeleton );\r\n\r\n\t\t\tMth::Matrix& flag_matrix = moving_obj->GetMatrix();\r\n\t\t\tpSkeleton->GetBoneMatrix( CRCD(0xddec28af,\"Bone_Head\"), &flag_matrix );\r\n\t\t\r\n\t\t\tflag_matrix.RotateXLocal( 90.0f );\r\n\r\n\t\t\t// raise the flag by 1 foot\r\n\t\t\tflag_matrix.TranslateLocal( Mth::Vector( 0.0f, FEET(1.0f), 0.0f, 0.0f ) );\r\n\t\t\r\n\t\t\tMth::Vector flag_offset = flag_matrix[Mth::POS];\r\n\t\t\tflag_matrix[Mth::POS] = Mth::Vector( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\t\t\r\n\t\t\t// for some reason, the below doesn't work as expected.\r\n\t\t\t// so instead, use the skater's root matrix for the orientation\r\n\t\t\tflag_matrix = flag_matrix * player->m_Skater->GetMatrix();\r\n\t\t\t//\t\tcrown.m_matrix = crown.mp_king->GetMatrix();\r\n\r\n\t\t\tmoving_obj->m_pos = player->m_Skater->GetMatrix().Transform( flag_offset );\r\n\t\t\tmoving_obj->m_pos += player->m_Skater->m_pos;\r\n\r\n// Mick:  Removed this as it no longer does anything apart from copying over the display matrix\r\n// if that's still needed then do it here\r\n// Might also possibly have some problem with shadows being left behind, but that just indicates the need\r\n// for a proper LOD system for shadows\r\n//\t\t\tmoving_obj->MovingObj_Update();\r\n// Mick:  Like this, but I don't think it's needed  \t\t\r\n//\t\t\tmoving_obj->m_display_matrix = moving_obj->m_matrix;\r\n\t\t\r\n\t//\t\tGfx::AddDebugStar( crown.m_pos, 10, 0x0000ffff, 1 );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_start_network_game_code( const Tsk::Task< Manager >& task )\r\n{\r\n\t//Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tManager& man = task.GetData();\r\n\tstatic bool showing_wait_screen = false;\r\n                                                                                             \r\n\tif( man.NumPartiallyLoadedPlayers() > 0 )\r\n\t{\r\n\t\tif( man.OnServer())\r\n\t\t{\r\n\t\t\tif( showing_wait_screen == false )\r\n\t\t\t{\r\n\t\t\t\tFront::CScreenElementManager* pManager = Front::CScreenElementManager::Instance();\r\n\t\t\t\tFront::CScreenElementPtr p_elem = pManager->GetElement( CRCD(0xf53d1d83,\"current_menu_anchor\"), Front::CScreenElementManager::DONT_ASSERT );\r\n\t\t\t\tif( !p_elem )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript( \"CreateWaitForPlayersDialog\" );\r\n\t\t\t\t\tshowing_wait_screen = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif( showing_wait_screen == false )\r\n\t\t\t{\r\n\t\t\t\tman.CreateNetPanelMessage( true, Script::GenerateCRC(\"net_message_game_will_start\"),\r\n\t\t\t\t\t\t\t\t\t\t   NULL, NULL, NULL, \"netexceptionprops\" );\r\n\t\t\t\tshowing_wait_screen = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn;\r\n\t}\r\n    \r\n\tif( ScriptAllPlayersAreReady( NULL, NULL ) == false )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif(( Tmr::GetTime() < s_time_to_start_game ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tshowing_wait_screen = false;\r\n\tman.StartNetworkGame();\r\n\tman.m_start_network_game_task->Remove();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_modem_state_code( const Tsk::Task< Manager >& task )\r\n{\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\tint new_modem_state;\r\n\tManager& man = task.GetData();\r\n\r\n\tnew_modem_state = net_man->GetModemState();\r\n\t\r\n\t// Check for positive edge\r\n\tif( new_modem_state != man.m_last_modem_state )\r\n\t{\r\n\t\tScript::CStruct* pStructure = new Script::CStruct;\r\n\t\t\r\n\t\tswitch( new_modem_state )\r\n\t\t{\r\n\t\t\tcase Net::vMODEM_STATE_DIALING:\r\n\t\t\t{\r\n\t\t\t\tchar dial_msg[128];\r\n\r\n                if( net_man->GetConnectionType() == Net::vCONN_TYPE_PPPOE )\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf( dial_msg, \"%s\", Script::GetString(\"net_modem_state_conencting\"));\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf( dial_msg, \"%s %s\", Script::GetString(\"net_modem_state_dialing\"), \r\n\t\t\t\t   \t\t\t\t\t\t\tnet_man->GetISPPhoneNumber());\r\n\t\t\t\t}\r\n\r\n\t\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, dial_msg );\r\n\t\t\t\tScript::RunScript( \"create_modem_state_dialog\", pStructure );\r\n                \r\n\t\t\t\tDbg_Printf( \"In modem state code. Got state dialing\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase Net::vMODEM_STATE_CONNECTED:\r\n\t\t\t{\r\n\t\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_modem_state_connected\" ));\r\n\t\t\t\tScript::RunScript( \"create_modem_state_dialog\", pStructure );\r\n\r\n\t\t\t\tDbg_Printf( \"In modem state code. Got state connected\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase Net::vMODEM_STATE_LOGGED_IN:\r\n\t\t\t{\r\n\t\t\t\tchar conn_msg[128];\r\n\r\n\t\t\t\tDbg_Printf( \"In modem state code. Got state logged in\\n\" );\r\n\t\t\t\tif( net_man->GetConnectionType() == Net::vCONN_TYPE_MODEM )\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf( conn_msg, \"%s %d bps\", Script::GetString(\"net_modem_state_logged_in\"), \r\n\t\t\t\t\t\t\t\t\t\tnet_man->GetModemBaudRate());\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf( conn_msg, \"%s\", Script::GetString(\"net_modem_state_logged_in\"));\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, conn_msg );\r\n\t\t\t\tScript::RunScript( \"create_modem_final_state_dialog\", pStructure );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase Net::vMODEM_STATE_DISCONNECTING:\r\n\t\t\t{\r\n\t\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_modem_state_disconnecting\" ));\r\n\t\t\t\tScript::RunScript( \"create_modem_status_dialog\", pStructure );\r\n\t\t\t\t\r\n\r\n\t\t\t\tDbg_Printf( \"In modem state code. Got state disconnecting\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase Net::vMODEM_STATE_HANGING_UP:\r\n\t\t\t{\r\n\t\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_modem_state_hanging_up\" ));\r\n\t\t\t\tScript::RunScript( \"create_modem_status_dialog\", pStructure );\r\n\r\n\t\t\t\tDbg_Printf( \"In modem state code. Got state hanging up\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase Net::vMODEM_STATE_DISCONNECTED:\r\n\t\t\t{\r\n\t\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_modem_state_disconnected\" ));\r\n\t\t\t\tScript::RunScript( \"create_modem_final_state_dialog\", pStructure );\r\n\r\n\t\t\t\tDbg_Printf( \"In modem state code. Got state disconnected\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase Net::vMODEM_STATE_READY_TO_TRANSMIT:\r\n\t\t\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t\tDbg_Printf( \"Removing modem state task\\n\" );\r\n\t\t\t\tman.RemoveModemStateTask();\r\n\t\t\t\t\r\n\t\t\t\tif( man.m_connection_success_script )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript( man.m_connection_success_script );\r\n\t\t\t\t}\r\n#endif\t\t// __PLAT_NGPS__\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase Net::vMODEM_STATE_ERROR:\r\n\t\t\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t\tuint32 modem_error;\r\n\r\n\t\t\t\tswitch( net_man->GetModemError())\r\n\t\t\t\t{\r\n\t\t\t\t\tcase SNTC_ERR_NOMODEM:\r\n\t\t\t\t\t\tmodem_error = Script::GenerateCRC(\"net_modem_error_no_modem\");\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase SNTC_ERR_TIMEOUT:\r\n\t\t\t\t\t\tmodem_error = Script::GenerateCRC(\"net_modem_error_timeout\");\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase SNTC_ERR_CONNECT:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tPrefs::Preferences* prefs;\r\n\t\t\t\t\t\tuint32 config_type;\r\n\r\n\t\t\t\t\t\tprefs = man.GetNetworkPreferences();\r\n\t\t\t\t\t\tconfig_type = prefs->GetPreferenceChecksum( CRCD(0xe381f426,\"config_type\"), \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tCRCD(0x21902065,\"checksum\") );\r\n\t\t\t\t\t\tif( config_type == CRCD(0x99452df9,\"config_manual\"))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmodem_error = Script::GenerateCRC(\"net_modem_error_during_connect\");\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmodem_error = Script::GenerateCRC(\"net_modem_error_during_connect_ync\");\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase SNTC_ERR_BUSY:\r\n\t\t\t\t\t\tmodem_error = Script::GenerateCRC(\"net_modem_error_busy\");\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase SNTC_ERR_NOCARRIER:\r\n\t\t\t\t\tcase SNTC_ERR_NOANSWER:\r\n\t\t\t\t\t\tmodem_error = Script::GenerateCRC(\"net_modem_error_no_connect\");\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase SNTC_ERR_NODIALTONE:\r\n\t\t\t\t\t\tmodem_error = Script::GenerateCRC(\"net_modem_error_no_dialtone\");\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tmodem_error = Script::GenerateCRC(\"net_modem_error_no_connect\");\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tDbg_Printf( \"In modem state error: %s\\n\", Script::GetString( modem_error ));\r\n\t\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( modem_error ));\r\n\t\t\t\tScript::RunScript( \"create_modem_final_state_dialog\", pStructure );\r\n#endif\t\t// __PLAT_NGPS__\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdelete pStructure;\r\n\t}\r\n\r\n\tman.m_last_modem_state = new_modem_state;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_client_add_new_players_code( const Tsk::Task< Manager >& task )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\t\r\n\tManager& man = task.GetData();\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* skater;\r\n\tLst::Node< NewPlayerInfo > *node, *next;\r\n\tNewPlayerInfo* new_player;\r\n\tNet::Conn* server_conn;\r\n\tLst::Search< Net::Conn > sh;\r\n\tbool added_player;\r\n\tint i;\r\n                         \r\n\tadded_player = false;\r\n\tfor( node = man.m_new_players.GetNext(); node; node = next )\r\n\t{\r\n\t\tnext = node->GetNext();\r\n\r\n\t\tnew_player = node->GetData();\r\n\r\n\t\tif( new_player->AllowedJoinFrame > man.m_client[0]->m_FrameCounter )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// GJ:  the \"new_player\" structure should already\r\n\t\t// contain the desired appearance\r\n\r\n\t\tman.ClientAddNewPlayer( new_player );\r\n\r\n\t\tdelete new_player;\r\n\t\tdelete node;\r\n\r\n\t\tadded_player = true;\r\n\t}\r\n\r\n\tif( added_player )\r\n\t{\r\n        for( i = 0; i < vMAX_LOCAL_CLIENTS; i++ )\r\n\t\t{\r\n\t\t\tif( man.m_client[i] )\r\n\t\t\t{\r\n\t\t\t\tserver_conn = man.m_client[i]->FirstConnection( &sh );\r\n\t\t\t\tif( server_conn )\r\n\t\t\t\t{\r\n\t\t\t\t\tserver_conn->UpdateCommTime();\t// update the current comm time so it doesn't time out after\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t// laoding the skater\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor( i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )\r\n\t\t{\r\n\t\t\tskater = skate_mod->GetSkater( i );\r\n\t\t\tif( skater )\r\n\t\t\t{   \r\n\t\t\t\tskater->Resync();\r\n\t\t\t}\r\n\t\t}\r\n        \r\n\t\tman.RespondToReadyQuery();\r\n\t}\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_server_add_new_players_code( const Tsk::Task< Manager >& task )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\tManager& man = task.GetData();\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tLst::Node< NewPlayerInfo > *node, *next;\r\n\tNewPlayerInfo* new_info;\r\n\tNet::MsgDesc msg_desc;\r\n\tNet::Manager* net_man = Net::Manager::Instance();\r\n\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tfor( node = man.m_new_players.GetNext(); node; node = next )\r\n\t{\r\n\t\tObj::CSkater* skater;\r\n\t\tMsgNewPlayer new_player_msg;\r\n\t\tLst::Search< PlayerInfo > sh;\r\n\t\tPlayerInfo* player, *new_player;\r\n\t\tMsgReady ready_msg;\r\n\t\tbool narrowband;\r\n\t\t\t\t\r\n\t\tnext = node->GetNext();\r\n\r\n\t\tnew_info = node->GetData();\r\n\t\r\n\t\tif( new_info->AllowedJoinFrame > man.m_server->m_FrameCounter )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tnarrowband = ( new_info->Conn->GetBandwidthType() == Net::Conn::vNARROWBAND ) ||\r\n\t\t\t\t\t\t( net_man->GetConnectionType() == Net::vCONN_TYPE_MODEM );\r\n\r\n\t\t// Mick: moved onto skater info heap, to prevent fragmentation\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\t\tnew_player = man.NewPlayer( NULL, new_info->Conn, new_info->Flags );\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\tstrcpy( new_player->m_Name, new_info->Name );\r\n\t\tnew_player->CopyProfile( new_info->mpSkaterProfile );\r\n\t\tnew_player->m_jump_in_frame = new_info->JumpInFrame;\r\n\t\tnew_player->m_Profile = new_info->Profile;\r\n\t\tnew_player->m_Rating = new_info->Rating;\r\n\t\tnew_player->m_VehicleControlType = new_info->VehicleControlType;\r\n\r\n\t\tman.AddPlayerToList( new_player );\r\n\t\tready_msg.m_Time = Tmr::GetTime();\r\n        \r\n\t\tif( !new_player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\t// Send the new player's create skater command in such a way that he knows it's his own skater\r\n\t\t\tnew_player_msg.m_ObjId = new_info->ObjID;\r\n\t\t\tnew_player_msg.m_Team = new_player->m_Team;\r\n\t\t\tnew_player_msg.m_Profile = new_player->m_Profile;\r\n\t\t\tnew_player_msg.m_Rating = new_player->m_Rating;\r\n\t\t\tnew_player_msg.m_VehicleControlType = new_player->m_VehicleControlType;\r\n\t\t\tnew_player_msg.m_Score = 0;\r\n\t\t\tstrcpy( new_player_msg.m_Name, new_info->Name );\r\n            \r\n\t\t\tnew_player_msg.m_Flags = PlayerInfo::mLOCAL_PLAYER;\r\n\t\t\tif( new_player->m_flags.TestMask( PlayerInfo::mJUMPING_IN ))\r\n\t\t\t{\r\n\t\t\t\tnew_player_msg.m_Flags |= PlayerInfo::mJUMPING_IN;\r\n\t\t\t}\r\n\t\t\tif( new_player->IsObserving())\r\n\t\t\t{\r\n\t\t\t\tnew_player_msg.m_Flags |= PlayerInfo::mOBSERVER;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tmsg_desc.m_Data = NULL;\r\n\t\t\tmsg_desc.m_Length = 0;\r\n\t\t\tmsg_desc.m_Id = MSG_ID_JOIN_ACCEPTED;\r\n\t\t\tmsg_desc.m_Priority = Net::HIGHEST_PRIORITY;\r\n\t\t\tman.m_server->EnqueueMessage( new_player->GetConnHandle(), &msg_desc );\r\n\t\t\r\n\t\t\tmsg_desc.m_Data = &new_player_msg;\r\n\t\t\tmsg_desc.m_Length = sizeof( MsgNewPlayer ) - vMAX_APPEARANCE_DATA_SIZE;\r\n\t\t\tmsg_desc.m_Id = MSG_ID_PLAYER_CREATE;\r\n\t\t\tman.m_server->EnqueueMessage( new_player->GetConnHandle(), &msg_desc );\r\n\t\t}\r\n\t\t\r\n\r\n\t\tif( !new_player->IsObserving())\r\n\t\t{\r\n\t\t\t// Send the new player's info to existing players\r\n\t\t\tfor( player = man.FirstPlayerInfo( sh, true ); player; \r\n\t\t\t\t\tplayer = man.NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\t// don't send the new player's info to the new player. We sent it separately and specially\r\n\t\t\t\t// Also, don't send to the server (ourselves)\r\n\t\t\t\tif(( new_player != player ) &&\r\n\t\t\t\t   ( !player->IsLocalPlayer()))\r\n\t\t\t\t{   \r\n\t\t\t\t\tnew_player_msg.m_ObjId = new_info->ObjID;\r\n\t\t\t\t\tnew_player_msg.m_Flags = 0;\r\n\t\t\t\t\tnew_player_msg.m_Team = new_player->m_Team;\r\n\t\t\t\t\tnew_player_msg.m_Profile = new_player->m_Profile;\r\n\t\t\t\t\tnew_player_msg.m_Rating = new_player->m_Rating;\r\n\t\t\t\t\tnew_player_msg.m_VehicleControlType = new_player->m_VehicleControlType;\r\n\t\t\t\t\tnew_player_msg.m_Score = 0;\r\n\t\t\t\t\tstrcpy( new_player_msg.m_Name, new_player->m_Name );\r\n\t\t\t\t\tDbg_Assert( new_player->mp_SkaterProfile );\r\n\t\t\t\t\tuint32 data_size = new_player->mp_SkaterProfile->WriteToBuffer(new_player_msg.m_AppearanceData, vMAX_APPEARANCE_DATA_SIZE );\r\n\r\n\t\t\t\t\tmsg_desc.m_Data = &new_player_msg;\r\n\t\t\t\t\tmsg_desc.m_Length = sizeof( MsgNewPlayer ) - vMAX_APPEARANCE_DATA_SIZE + data_size;\r\n\t\t\t\t\tmsg_desc.m_Id = MSG_ID_PLAYER_CREATE;\r\n\t\t\t\t\tmsg_desc.m_Priority = Net::NORMAL_PRIORITY;\r\n\t\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\t\tman.m_server->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Players that are \"jumping in\" already have current players' info\r\n\t\t// Only send them other players who jumped in at the same time\r\n\t\tif( new_player->m_flags.TestMask( PlayerInfo::mJUMPING_IN ))\r\n\t\t{\r\n\t\t\tfor( player = man.FirstPlayerInfo( sh ); player; \r\n\t\t\t\t\tplayer = man.NextPlayerInfo( sh ))\r\n\t\t\t{\r\n\t\t\t\tif( ( new_player != player ) &&\r\n\t\t\t\t\t( player->m_jump_in_frame == new_player->m_jump_in_frame ))\r\n\t\t\t\t{   \r\n\t\t\t\t\tnew_player_msg.m_ObjId = player->m_Skater->GetID();\r\n\t\t\t\t\tnew_player_msg.m_Flags = ( player->m_flags & ( PlayerInfo::mKING_OF_THE_HILL | PlayerInfo::mHAS_ANY_FLAG ));\r\n\t\t\t\t\tnew_player_msg.m_Team = player->m_Team;\r\n\t\t\t\t\tnew_player_msg.m_Profile = player->m_Profile;\r\n\t\t\t\t\tnew_player_msg.m_Rating = player->m_Rating;\r\n\t\t\t\t\tnew_player_msg.m_VehicleControlType = player->m_VehicleControlType;\r\n\t\t\t\t\tnew_player_msg.m_Score = 0;\r\n\t\t\t\t\tstrcpy( new_player_msg.m_Name, player->m_Name );\r\n\t\t\t\t\tDbg_Assert( player->mp_SkaterProfile );\r\n\t\t\t\t\tuint32 data_size = player->mp_SkaterProfile->WriteToBuffer(new_player_msg.m_AppearanceData, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvMAX_APPEARANCE_DATA_SIZE, narrowband );\r\n\r\n\t\t\t\t\tmsg_desc.m_Data = &new_player_msg;\r\n\t\t\t\t\tmsg_desc.m_Length = sizeof( MsgNewPlayer ) - vMAX_APPEARANCE_DATA_SIZE + data_size;\r\n\t\t\t\t\tmsg_desc.m_Id = MSG_ID_PLAYER_CREATE;\r\n\t\t\t\t\tmsg_desc.m_Priority = Net::NORMAL_PRIORITY;\r\n\t\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\t\tman.m_server->EnqueueMessage( new_player->GetConnHandle(), &msg_desc );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Send the new player the info on all current players( except himself )\r\n\t\t\tfor( player = man.FirstPlayerInfo( sh ); player; \r\n\t\t\t\t\tplayer = man.NextPlayerInfo( sh ))\r\n\t\t\t{\r\n\t\t\t\t// don't send the new player's info to the new player. We sent it separately and specially\r\n\t\t\t\t// also only send these messages to remote clients as we've already loaded the player here\r\n\t\t\t\tif( ( new_player != player ) &&\r\n\t\t\t\t\t( !new_player->IsLocalPlayer()))\r\n\t\t\t\t{   \r\n\t\t\t\t\tnew_player_msg.m_ObjId = player->m_Skater->GetID();\r\n\t\t\t\t\tnew_player_msg.m_Flags = ( player->m_flags & ( PlayerInfo::mKING_OF_THE_HILL | PlayerInfo::mHAS_ANY_FLAG ));\r\n\t\t\t\t\tnew_player_msg.m_Team = player->m_Team;\r\n\t\t\t\t\tnew_player_msg.m_Profile = player->m_Profile;\r\n\t\t\t\t\tnew_player_msg.m_Rating = player->m_Rating;\r\n\t\t\t\t\tnew_player_msg.m_VehicleControlType = player->m_VehicleControlType;\r\n\t\t\t\t\tnew_player_msg.m_Score = man.GetPlayerScore( player->m_Skater->GetID() );\r\n\t\t\t\t\tstrcpy( new_player_msg.m_Name, player->m_Name );\r\n\t\t\t\t\tDbg_Assert( player->mp_SkaterProfile );\r\n\t\t\t\t\tuint32 data_size = player->mp_SkaterProfile->WriteToBuffer(new_player_msg.m_AppearanceData, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvMAX_APPEARANCE_DATA_SIZE, narrowband );\r\n\r\n\t\t\t\t\tmsg_desc.m_Data = &new_player_msg;\r\n\t\t\t\t\tmsg_desc.m_Length = sizeof( MsgNewPlayer ) - vMAX_APPEARANCE_DATA_SIZE + data_size;\r\n\t\t\t\t\tmsg_desc.m_Id = MSG_ID_PLAYER_CREATE;\r\n\t\t\t\t\tmsg_desc.m_Priority = Net::NORMAL_PRIORITY;\r\n\t\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\t\tman.m_server->EnqueueMessage( new_player->GetConnHandle(), &msg_desc );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tMsgIntInfo level_msg;\r\n\t\t\tuint32 level;\r\n\r\n\t\t\tlevel = (int) man.GetNetworkLevelId();\r\n\t\t\tif( !new_player->IsLocalPlayer())\r\n\t\t\t{\r\n\t\t\t\tif( level == CRCD(0xb664035d,\"Load_Sk5Ed_gameplay\"))\r\n\t\t\t\t{\r\n\t\t\t\t\tEd::CParkManager::sInstance()->WriteCompressedMapBuffer();\r\n\r\n\t\t\t\t\tman.m_server->StreamMessage( new_player->GetConnHandle(), MSG_ID_LEVEL_DATA, Ed::CParkManager::COMPRESSED_MAP_SIZE, \r\n\t\t\t\t\t\t\t   Ed::CParkManager::sInstance()->GetCompressedMapBuffer(), \"level data\", vSEQ_GROUP_PLAYER_MSGS,\r\n\t\t\t\t\t\t\t\t\t\t\t\t false, true );\r\n\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\t\tman.m_server->StreamMessage( new_player->GetConnHandle(), MSG_ID_RAIL_DATA, Obj::GetRailEditor()->GetCompressedRailsBufferSize(), \r\n\t\t\t\t\t\t\t   Obj::GetRailEditor()->GetCompressedRailsBuffer(), \"rail data\", vSEQ_GROUP_PLAYER_MSGS,\r\n\t\t\t\t\t\t\t\t\t\t\t\t false, true );\r\n\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tlevel_msg.m_Data = (int) level;\r\n\t\t\tDbg_Printf( \"Sending player info ack request\\n\" );\r\n\r\n\t\t\tmsg_desc.m_Data = &level_msg;\r\n\t\t\tmsg_desc.m_Length = sizeof( MsgIntInfo );\r\n\t\t\tmsg_desc.m_Id = MSG_ID_PLAYER_INFO_ACK_REQ;\r\n\t\t\tmsg_desc.m_Priority = Net::NORMAL_PRIORITY;\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\tman.m_server->EnqueueMessage( new_player->GetConnHandle(), &msg_desc );\r\n\t\t}\r\n\t\t\r\n\t\tif( !new_player->IsObserving())\r\n\t\t{   \r\n\t\t\tint skater_num;\r\n\r\n\t\t\t// GJ:  the \"new_info\" should contain the desired\r\n\t\t\t// appearance by this point\r\n\t\t\t\r\n\t\t\t// Mick: if this is a local player in a net game\r\n\t\t\t// then it must be skater 0\r\n\t\t\tif( new_player->IsLocalPlayer() && man.InNetGame())\r\n\t\t\t{\r\n\t\t\t\tskater_num = 0;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Otherwise, for 2P games, nonlocal net players, and P1, \r\n\t\t\t\tskater_num = skate_mod->GetNumSkaters();\r\n\t\t\t}\r\n\t\t\tskater = skate_mod->add_skater( new_info->mpSkaterProfile, new_player->m_Conn->IsLocal(), \r\n\t\t\t\t\t\t\t\t\t\t\tnew_info->ObjID, skater_num );\r\n\t\t\tnew_player->SetSkater( skater );\r\n\t\t\tif( !new_player->IsLocalPlayer())\r\n\t\t\t{\r\n\t\t\t\tskater->RemoveFromCurrentWorld();\r\n\t\t\t}\r\n\r\n\t\t\tfor( player = man.FirstPlayerInfo( sh, true ); player; player = man.NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\tif( new_player == player )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmsg_desc.m_Data = &ready_msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( MsgReady );\r\n\t\t\t\tmsg_desc.m_Id = MSG_ID_READY_QUERY;\r\n\t\t\t\tmsg_desc.m_Priority = Net::NORMAL_PRIORITY;\r\n\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\tman.m_server->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t\tif( !player->IsLocalPlayer() && !player->IsObserving())\r\n\t\t\t\t{\r\n\t\t\t\t\tplayer->m_Skater->Resync();\r\n\t\t\t\t\tplayer->MarkAsNotReady( ready_msg.m_Time );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Mark the client as \"not ready\" so we don't bombard him with non-important messages\r\n\t\t// until he has fully loaded all that he needs to load\r\n\t\tmsg_desc.m_Data = &ready_msg;\r\n\t\tmsg_desc.m_Length = sizeof( MsgReady );\r\n\t\tmsg_desc.m_Id = MSG_ID_READY_QUERY;\r\n\t\tmsg_desc.m_Priority = Net::NORMAL_PRIORITY;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\tman.m_server->EnqueueMessage( new_player->GetConnHandle(), &msg_desc );\r\n\t\tnew_player->MarkAsNotReady( ready_msg.m_Time );\r\n        \r\n\t\tdelete new_info;\r\n\t\tdelete node;\r\n\t}\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_render_metrics_code( const Tsk::Task< Manager >& task )\r\n{\r\n\tLst::Search< Net::Conn > sh;\r\n\tNet::Conn* conn;\r\n\tint conn_num;\r\n\tNet::Metrics* metrics_in, *metrics_out;\r\n\tchar buff[ 1024 ];\r\n\tint i;\r\n\r\n    Manager& man = task.GetData();\r\n\r\n\r\n    for( i = 0; i < 2; i++ )\r\n\t{\r\n\t\tif( man.m_client[0] && !man.m_client[0]->IsLocal())\r\n\t\t{\r\n\t\t\tconn_num = 0;\r\n\t\t\t\r\n\t\r\n\t\t\tfor( conn = man.m_client[0]->FirstConnection( &sh ); conn;\r\n\t\t\t\t\tconn = man.m_client[0]->NextConnection( &sh ))\r\n\t\t\t{\r\n\t\t\t\tif( conn->IsLocal())\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tmetrics_in = conn->GetInboundMetrics();\r\n\t\t\t\tmetrics_out = conn->GetOutboundMetrics();\r\n\t\t\t\t\r\n\t\t\t\tsprintf( buff, \"(%d) Lag: %d Resends: %d Bps: %d %d\", \r\n\t\t\t\t\t\t conn_num, \r\n\t\t\t\t\t\t conn->GetAveLatency(),\r\n\t\t\t\t\t\t conn->GetNumResends(),\r\n\t\t\t\t\t\t metrics_in->GetBytesPerSec(),\r\n\t\t\t\t\t\t metrics_out->GetBytesPerSec());\r\n\t\t\t\t\t\r\n\t\t\t\tScript::CStruct* pParams;\r\n\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\tpParams->AddString( \"text\", buff );\r\n\t\t\t\tScript::RunScript( \"update_net_metrics\", pParams );\r\n\r\n\t\t\t\tdelete pParams;\r\n\t\t\t\tconn_num++;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif( man.m_server )\r\n\t\t{\r\n\t\t\tconn_num = 0;\r\n\t\t\tfor( conn = man.m_server->FirstConnection( &sh ); conn;\r\n\t\t\t\t\tconn = man.m_server->NextConnection( &sh ))\r\n\t\t\t{\r\n\t\t\t\tif( conn->IsLocal())\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmetrics_in = conn->GetInboundMetrics();\r\n\t\t\t\tmetrics_out = conn->GetOutboundMetrics();\r\n\t\t\t\t\r\n\t\t\t\tsprintf( buff, \"(%d) Lag: %d Resends: %d Bps: %d %d\", \r\n\t\t\t\t\t\t conn_num, \r\n\t\t\t\t\t\t conn->GetAveLatency(),\r\n\t\t\t\t\t\t conn->GetNumResends(),\r\n\t\t\t\t\t\t metrics_in->GetBytesPerSec(),\r\n\t\t\t\t\t\t metrics_out->GetBytesPerSec());\r\n\r\n\t\t\t\tScript::CStruct* pParams;\r\n\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\tpParams->AddString( \"text\", buff );\r\n\t\t\t\tScript::RunScript( \"update_net_metrics\", pParams );\r\n\r\n\t\t\t\tdelete pParams;\r\n\t\t\t\t\t\r\n\t\t\t\tconn_num++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_timeout_connections_code( const Tsk::Task< Manager >& task )\r\n{\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo *player, *next;\r\n\tManager& man = task.GetData();\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tbool time_out;\r\n\t\r\n#ifdef __PLAT_XBOX__\r\n\tstatic Tmr::Time s_last_link_check = 0;\r\n\t\r\n\tif(\t( man.InNetMode()) &&\r\n\t\t(( Tmr::GetTime() - s_last_link_check ) > vLINK_CHECK_FREQUENCY ))\r\n\t{\r\n\t\tif( man.InNetGame())\r\n\t\t{\r\n\t\t\ts_last_link_check = Tmr::GetTime();\r\n\t\t\tDWORD dwStatus = XNetGetEthernetLinkStatus();\r\n\t\t\t\r\n        \tif(( dwStatus & XNET_ETHERNET_LINK_ACTIVE ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tFront::CScreenElementManager* pManager = Front::CScreenElementManager::Instance();\r\n\t\t\t\tFront::CScreenElementPtr p_elem = pManager->GetElement( Script::GenerateCRC( \"link_lost_dialog_anchor\" ), Front::CScreenElementManager::DONT_ASSERT );\r\n\t\t\t\tif( !p_elem )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript( \"create_link_unplugged_dialog\" );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ts_last_link_check = Tmr::GetTime();\r\n\t\t\tDWORD dwStatus = XNetGetEthernetLinkStatus();\r\n\t\t\t\r\n        \tif(( dwStatus & XNET_ETHERNET_LINK_ACTIVE ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tFront::CScreenElementManager* pManager = Front::CScreenElementManager::Instance();\r\n\t\t\t\tFront::CScreenElementPtr p_elem = pManager->GetElement( CRCD(0x3b56e746,\"dialog_box_anchor\"), Front::CScreenElementManager::DONT_ASSERT );\r\n\t\t\t\tif( !p_elem )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript( \"create_link_unplugged_front_end_dialog\" );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n#endif\t\r\n\r\n\tif( man.OnServer())\r\n\t{   \r\n\t\tfor( player = man.FirstPlayerInfo( sh, true ); player; player = next )\r\n\t\t{   \r\n\t\t\ttime_out = false;\r\n\t\t\tnext = man.NextPlayerInfo( sh, true );\r\n\t\t\tif( player->m_Conn->IsLocal())\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif( player->m_Conn->TestStatus( Net::Conn::mSTATUS_READY ))\r\n\t\t\t{   \r\n\t\t\t\tif( player->m_Conn->GetTimeElapsedSinceCommunication() > vCONNECTION_TIMEOUT )\r\n\t\t\t\t{\r\n\t\t\t\t\ttime_out = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif( player->m_Conn->GetNumResends() > vMAX_TOLERABLE_RESENDS )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tObj::CSkater* skater;\r\n\t\t\t\t\t\tbool observing;\r\n\r\n\t\t\t\t\t\tskater = player->m_Skater;\r\n\t\t\t\t\t\tobserving = player->IsObserving();\r\n\t\t\t\t\t\tman.DropPlayer( player, vREASON_BAD_CONNECTION );\r\n\t\t\t\t\t\tif( !observing)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tskate_mod->remove_skater( skater );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( player->m_Conn->GetTimeElapsedSinceCommunication() > vNOT_READY_TIMEOUT )\r\n\t\t\t\t{\r\n\t\t\t\t\ttime_out = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif( time_out )\r\n\t\t\t{\r\n\t\t\t\tObj::CSkater* skater;\r\n\t\t\t\tbool observing;\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\t\t\t\tunsigned int cur_time = Tmr::GetTime();\r\n\t\t\t\tunsigned int last_time = player->m_Conn->GetLastCommTime();\r\n\t\t\t\tDbg_Printf( \"Gamenet : Timing client out. Current time (%d) last comm time (%d)\\n\",\r\n\t\t\t\t\t\t\t\tcur_time, last_time );\r\n#endif\t\t\t\t\r\n\t\t\t\tskater = player->m_Skater;\r\n\t\t\t\tobserving = player->IsObserving();\r\n\t\t\t\tman.DropPlayer( player, vREASON_TIMEOUT );\r\n\t\t\t\tif( !observing)\r\n\t\t\t\t{\r\n\t\t\t\t\tskate_mod->remove_skater( skater );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNet::Conn* server_conn;\r\n\t\tLst::Search< Net::Conn > sh;\r\n\t\t\r\n\t\tif( man.m_client[0] )\r\n\t\t{   \r\n            server_conn = man.m_client[0]->FirstConnection( &sh );\r\n\t\t\tif( server_conn == NULL )\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tif(( man.GetJoinState() == vJOIN_STATE_CONNECTED ) ||\r\n\t\t\t   ( man.GetJoinState() == vJOIN_STATE_WAITING_FOR_START_INFO ) || \r\n\t\t\t   ( man.GetJoinState() == vJOIN_STATE_GOT_PLAYERS ))\r\n\t\t\t{\r\n\t\t\t\tif( server_conn->GetTimeElapsedSinceCommunication() > vCONNECTION_TIMEOUT )\r\n\t\t\t\t{  \r\n#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\tunsigned int cur_time = Tmr::GetTime();\r\n\t\t\t\t\tunsigned int last_time = server_conn->GetLastCommTime();\r\n#endif\t\t\t\t\t\r\n#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\tDbg_Printf( \"Gamenet : Timing server out. Current time (%d) last comm time (%d)\\n\",\r\n\t\t\t\t\t\t\t\t\tcur_time, last_time );\r\n#endif              \r\n\t\t\t\t\t\r\n\t\t\t\t\tif( skate_mod->m_cur_level == CRCD(0x9f2bafb7,\"Load_Skateshop\"))\r\n\t\t\t\t\t{\t\t\t\t\t\t\r\n                        // If we got partially in, cancel the join and remove partially-loaded players\r\n\t\t\t\t\t\t// Shut the client down so that it doesn't bombard the server ip with messages\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tScript::RunScript( \"ShowJoinTimeoutNotice\" );\r\n\r\n\t\t\t\t\t\t//man.CancelJoinServer();\r\n\t\t\t\t\t\tman.m_join_state_task->Remove();\r\n\t\t\t\t\t\tman.SetJoinState( vJOIN_STATE_FINISHED );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n// On the xbox, don't show the lost conn dialog if the quit dialog box is up\t\t\t\t\t\r\n#ifdef __PLAT_XBOX__\r\n\t\t\t\t\t\tFront::CScreenElementManager* pManager = Front::CScreenElementManager::Instance();\r\n\t\t\t\t\t\tFront::CScreenElementPtr p_elem = pManager->GetElement( CRCD(0x4c8bf619,\"quit_dialog_anchor\"), Front::CScreenElementManager::DONT_ASSERT );\r\n\t\t\t\t\t\tif( !p_elem )\r\n#endif\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tScript::RunScript( \"CreateLostConnectionDialog\" );\r\n\t\r\n\t\t\t\t\t\t\tman.CleanupPlayers();\r\n\t\t\t\t\t\t\tman.ClientShutdown();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_join_timeout_code( const Tsk::Task< Manager >& task )\r\n{\r\n\tManager& man = task.GetData();\r\n\r\n\tif(( Tmr::GetTime() - man.m_join_start_time ) > vJOIN_TIMEOUT )\r\n\t{\r\n\t\t//Mdl::FrontEnd* front = Mdl::FrontEnd::Instance();\r\n\t\t\r\n\t\t//man.CancelJoinServer();\r\n\t\t//man.SetJoinState( vJOIN_STATE_FINISHED );\r\n        \r\n\t\tman.m_join_state_task->Remove();\r\n\t\tScript::RunScript( \"ShowJoinTimeoutNotice\" );\r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\t\t\t\tManager::SetNetworkMode( NetworkMode mode )\r\n{\r\n\tm_flags.ClearMask( mNETWORK_MODE);\r\n\t\r\n\tif( mode == vLAN_MODE )\r\n\t{\r\n\t\tDbg_Printf( \"************* Setting Lan Mode\\n\" );\r\n\t\tm_flags.SetMask( mLAN );\r\n\t}\r\n\telse if( mode == vINTERNET_MODE )\r\n\t{\r\n\t\tDbg_Printf( \"************* Setting Internet Mode\\n\" );\r\n\t\tm_flags.SetMask( mINTERNET );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Printf( \"************* Clearing Net Mode\\n\" );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tManager::SetJoinMode( JoinMode mode )\r\n{\r\n\tm_join_mode = mode;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nJoinMode\t\t\tManager::GetJoinMode( void )\r\n{\r\n\treturn m_join_mode;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tManager::SetHostMode( HostMode mode )\r\n{\r\n\t// Only accept if it is actually a change in modes\r\n\tif( mode == m_host_mode )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tm_host_mode = mode;\r\n\t\r\n\tswitch( m_host_mode )\r\n\t{\r\n\t\tcase vHOST_MODE_SERVE:\r\n\t\t{\r\n\t\t\t// Do nothing. This is the standard mode\r\n\t\t\tDbg_Printf( \"Got mode serve\\n\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vHOST_MODE_AUTO_SERVE:\r\n\t\t{\r\n\t\t\tRequestObserverMode();\r\n\t\t\tSpawnAutoServer();\r\n\r\n\t\t\t// Should start a game and also spawn a task that starts new games\r\n\t\t\t// after X seconds in a lobby\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase vHOST_MODE_FCFS:\r\n\t\t{\r\n\t\t\tRequestObserverMode();\r\n\t\t\tChooseNewServerPlayer();\r\n\r\n\t\t\t// Should start a game and also spawn a task that starts new games\r\n\t\t\t// after X seconds in a lobby\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\tHostMode\t\t\tManager::GetHostMode( void )\r\n{\r\n\treturn m_host_mode;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tManager::SetServerMode( bool on )\r\n{\r\n\tif( on )\r\n\t{\r\n\t\tm_flags.SetMask( mSERVER );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_flags.ClearMask( mSERVER );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tManager::InNetMode( void )\r\n{\r\n\treturn m_flags.TestMask( mNETWORK_MODE);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tManager::InNetGame( void )\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t// Mick:  Pretend we are in a net game when we are actually in\r\n\t// regular single player\r\n\t// This allows designer to test net games without starting a server\r\n\tif (Script::GetInt(CRCD(0xcbc1a46,\"fake_net\")))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t#endif\r\n\t\r\n\t\r\n\tif( !InNetMode())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif( m_server && !m_server->IsLocal())\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif( m_client[0] && !m_client[0]->IsLocal())\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tManager::InLanMode( void )\r\n{\r\n\treturn m_flags.TestMask( mLAN );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tManager::InInternetMode( void )\r\n{\r\n    return m_flags.TestMask( mINTERNET );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tManager::OnServer( void )\r\n{\r\n\treturn m_flags.TestMask( mSERVER );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tManager::OnClient( void )\r\n{\r\n\treturn m_flags.TestMask( mCLIENT );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\t\tManager::GetSkillLevel( void )\r\n{\r\n\tuint32 checksum;\r\n\tScript::CStruct* pStructure;\r\n\t\t\r\n\tpStructure = m_network_preferences.GetPreference( Script::GenerateCRC(\"skill_level\") );\r\n\tpStructure->GetChecksum( \"Checksum\", &checksum, true );\r\n\tif( checksum == Script::GenerateCRC( \"num_1\" ))\r\n\t{\r\n\t\treturn vSKILL_LEVEL_1;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_2\" ))\r\n\t{\r\n\t\treturn vSKILL_LEVEL_2;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_3\" ))\r\n\t{\r\n\t\treturn vSKILL_LEVEL_3;\r\n\t}                                              \r\n\telse if( checksum == Script::GenerateCRC( \"num_4\" ))\r\n\t{\r\n\t\treturn vSKILL_LEVEL_4;\r\n\t}                                              \r\n\telse if( checksum == Script::GenerateCRC( \"num_5\" ))\r\n\t{\r\n\t\treturn vSKILL_LEVEL_5;\r\n\t}                                              \r\n\r\n\treturn vSKILL_LEVEL_DEFAULT;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\t\tManager::GetMaxPlayers( void )\r\n{\r\n\tuint32 checksum;\r\n\tint max_players = 2;\r\n\tScript::CStruct* pStructure;\r\n\t\t\r\n\tpStructure = m_network_preferences.GetPreference( Script::GenerateCRC(\"num_players\") );\r\n\tpStructure->GetChecksum( \"Checksum\", &checksum, true );\r\n\tif( checksum == Script::GenerateCRC( \"num_2\" ))\r\n\t{\r\n\t\tmax_players = 2;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_3\" ))\r\n\t{\r\n\t\tmax_players = 3;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_4\" ))\r\n\t{\r\n\t\tmax_players = 4;\r\n\t}                                              \r\n\telse if( checksum == Script::GenerateCRC( \"num_5\" ))\r\n\t{\r\n\t\tmax_players = 5;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_6\" ))\r\n\t{\r\n\t\tmax_players = 6;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_7\" ))\r\n\t{\r\n\t\tmax_players = 7;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_8\" ))\r\n\t{\r\n\t\tmax_players = 8;\r\n\t}\r\n\r\n\treturn max_players;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tManager::CreateTeamFlags( int num_teams )\r\n{\r\n\tScript::CStruct* pParams;\r\n\t\r\n\t// First destroy all team flags\r\n\tScript::RunScript( \"Kill_Team_Flags\" );\r\n\r\n\t// Now only create the number of flags we need\r\n\tif( num_teams == 0 )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tpParams = new Script::CStruct;\r\n\tpParams->AddInteger( \"num_teams\", num_teams );\r\n\tScript::RunScript( \"Create_Team_Flags\", pParams );\r\n\tdelete pParams;\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\t\tManager::GetNumTeams( void )\r\n{\r\n\tuint32 checksum;\r\n\tint num_teams = vMAX_TEAMS;\r\n\tScript::CStruct* pStructure;\r\n\t\t\r\n\tpStructure = m_network_preferences.GetPreference( Script::GenerateCRC(\"team_mode\") );\r\n\tpStructure->GetChecksum( \"Checksum\", &checksum, true );\r\n\tif( checksum == Script::GenerateCRC( \"teams_none\" ))\r\n\t{\r\n\t\tnum_teams = 0;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"teams_two\" ))\r\n\t{\r\n\t\tnum_teams = 2;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"teams_three\" ))\r\n\t{\r\n\t\tnum_teams = 3;\r\n\t}                                              \r\n\telse if( checksum == Script::GenerateCRC( \"teams_four\" ))\r\n\t{\r\n\t\tnum_teams = 4;\r\n\t}\r\n\r\n\treturn num_teams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\t\tManager::NumTeamMembers( int team )\r\n{\r\n\tint num_players;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo* player;\r\n\tLst::Search< NewPlayerInfo > new_sh;\r\n\tNewPlayerInfo* np;\r\n\r\n\tnum_players = 0;\r\n\r\n\tfor( player = FirstPlayerInfo( sh ); player; player = NextPlayerInfo( sh ))\r\n\t{\r\n\t\tif( player->m_Team == team )\r\n\t\t{\r\n\t\t\tnum_players++;\r\n\t\t}\r\n\t}\r\n\r\n\tfor( np = new_sh.FirstItem( m_new_players ); np; np = new_sh.NextItem())\r\n\t{\r\n\t\t// Pending players count, observers don't\r\n\t\tif(\t( np->Flags & PlayerInfo::mPENDING_PLAYER ) ||\r\n\t\t\t( np->Flags & PlayerInfo::mJUMPING_IN ) ||\r\n\t\t\t!( np->Flags & PlayerInfo::mOBSERVER ))\r\n\t\t{\r\n\t\t\tif( np->Team == team )\r\n\t\t\t{\r\n\t\t\t\tnum_players++;\r\n\t\t\t}\r\n\t\t}                 \r\n\t}\r\n\r\n\t\r\n\treturn num_players;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tManager::SetMaxPlayers( int max_players )\r\n{\r\n\tScript::CStruct* pTempStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tuint32 checksum;\r\n\tchar check_string[32];\r\n\tchar name_string[32];\r\n\t\r\n\tDbg_Assert(( max_players >= 2 ) && ( max_players <= vMAX_PLAYERS ));\r\n\t\r\n\tsprintf( check_string, \"num_%d\", max_players );\r\n\tchecksum = Script::GenerateCRC( check_string );\r\n\r\n#if ENGLISH == 0\r\n\tsprintf( name_string, \"%d %s\", max_players, Script::GetLocalString( \"netmenu_str_players\" ));\r\n#else\r\n\tsprintf( name_string, \"%d Players\", max_players );\r\n#endif\r\n\r\n\tpTempStructure = new Script::CStruct;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \r\n\t\t\t\t\t\t\t\t  name_string );\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, (int) checksum );\r\n\tpPreferences = GetNetworkPreferences();\r\n\tpPreferences->SetPreference( Script::GenerateCRC( \"num_players\"), pTempStructure );\r\n}\r\n                                        \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\t\tManager::GetMaxObservers( void )\r\n{\r\n\tuint32 checksum;\r\n\tint max_observers = 2;\r\n\tScript::CStruct* pStructure;\r\n\t\t\r\n\tpStructure = m_network_preferences.GetPreference( Script::GenerateCRC(\"num_observers\"));\r\n\tpStructure->GetChecksum( \"Checksum\", &checksum, true );\r\n\tif( checksum == Script::GenerateCRC( \"num_0\" ))\r\n\t{\r\n\t\tmax_observers = 0;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_1\" ))\r\n\t{\r\n\t\tmax_observers = 1;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_2\" ))\r\n\t{\r\n\t\tmax_observers = 2;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_3\" ))\r\n\t{\r\n\t\tmax_observers = 3;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_4\" ))\r\n\t{\r\n\t\tmax_observers = 4;\r\n\t}                                              \r\n\telse if( checksum == Script::GenerateCRC( \"num_5\" ))\r\n\t{\r\n\t\tmax_observers = 5;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_6\" ))\r\n\t{\r\n\t\tmax_observers = 6;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_7\" ))\r\n\t{\r\n\t\tmax_observers = 7;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_8\" ))\r\n\t{\r\n\t\tmax_observers = 8;\r\n\t}                                              \r\n\r\n\treturn max_observers;\r\n}\r\n                                        \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tManager::SetMaxObservers( int max_observers )\r\n{\r\n\tScript::CStruct* pTempStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tuint32 checksum;\r\n\tchar check_string[32];\r\n\tchar name_string[32];\r\n\t\r\n    sprintf( check_string, \"num_%d\", max_observers );\r\n\tchecksum = Script::GenerateCRC( check_string );\r\n\t\r\n#if ENGLISH == 0\r\n\tif( max_observers == 0 )\r\n\t{\r\n\t\tsprintf( name_string, Script::GetLocalString( \"netmenu_str_no_observers\" ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( max_observers == 1 )\r\n\t\t{\r\n\t\t\tsprintf( name_string, \"1 %s\", Script::GetLocalString( \"netmenu_str_observer\" ));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsprintf( name_string, \"%d %s\", max_observers, Script::GetLocalString( \"netmenu_str_observers\" ));\r\n\t\t}\r\n\t}\r\n#else\r\n\tif( max_observers == 0 )\r\n\t{\r\n\t\tsprintf( name_string, \"No Observers\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( max_observers == 1 )\r\n\t\t{\r\n\t\t\tsprintf( name_string, \"1 Observer\" );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsprintf( name_string, \"%d Observers\", max_observers );\r\n\t\t}\r\n\t}\r\n#endif\r\n\tpTempStructure = new Script::CStruct;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \r\n\t\t\t\t\t\t\t\t  name_string );\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, (int) checksum );\r\n\tpPreferences = GetNetworkPreferences();\r\n\tpPreferences->SetPreference( Script::GenerateCRC( \"num_observers\"), pTempStructure );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\t\t\t\tManager::GetPassword( void )\r\n{\r\n\tPrefs::Preferences* pPreferences;\r\n\tScript::CStruct* pStructure;\r\n\tconst char* password;\r\n\t\t\r\n\tpPreferences = GetNetworkPreferences();\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"password\") );\r\n\tpStructure->GetText( \"ui_string\", &password, true );\r\n\r\n\treturn (char*) password;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\t\t\t\tManager::GetLevelName( bool get_created_park_name )\r\n{\r\n\tScript::CArray* pArray = Script::GetArray(\"level_select_menu_level_info\");\r\n\tDbg_Assert( pArray );\r\n\r\n\tfor ( int i = 0; i < (int)pArray->GetSize(); i++ )\r\n\t{   \r\n\t\tuint32 checksum;\r\n\t\tScript::CStruct* pStructure = pArray->GetStructure( i );\r\n\t\tDbg_Assert( pStructure );\r\n\r\n        pStructure->GetChecksum( \"level\", &checksum );\r\n\t\tif( GetNetworkLevelId() == checksum )\r\n\t\t{\r\n\t\t\tconst char* level_name;\r\n\r\n\t\t\tif( get_created_park_name && ( checksum == CRCD(0xb664035d,\"Load_Sk5Ed_gameplay\")))\r\n\t\t\t{\r\n\t\t\t\treturn (char*) Ed::CParkManager::sInstance()->GetParkName();\r\n\t\t\t}\r\n\t\t\tpStructure->GetText( \"text\", &level_name, true );\r\n\t\t\treturn (char *) level_name;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\t\t\t\tManager::GetGameModeName( void )\r\n{\r\n\tScript::CArray* pArray = Script::GetArray(\"mode_info\");\r\n\tDbg_Assert( pArray );\r\n\r\n\tfor ( int i = 0; i < (int)pArray->GetSize(); i++ )\r\n\t{   \r\n\t\tuint32 checksum;\r\n\t\tuint32 game_mode_id;\r\n\t\tScript::CStruct* pStructure = pArray->GetStructure( i );\r\n\t\tDbg_Assert( pStructure );\r\n\t\r\n\t\tgame_mode_id = GetGameTypeFromPreferences();//skate_mod->GetGameMode()->GetNameChecksum();\r\n\t\tpStructure->GetChecksum( \"checksum\", &checksum );\r\n\t\tif( game_mode_id == checksum )\r\n\t\t{\r\n\t\t\tconst char* mode_name;\r\n\r\n\t\t\tpStructure->GetText( \"name\", &mode_name, true );\r\n\t\t\treturn (char *) mode_name;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tManager::PlayerCollisionEnabled( void )\r\n{\r\n\tuint32 collision_pref;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t \r\n\tif(\t( GameIsOver()) ||\r\n\t\t( skate_mod->GetGameMode()->GetNameChecksum() == CRCD( 0x34861a16, \"freeskate\" )) ||\r\n\t\t( skate_mod->GetGameMode()->GetNameChecksum() == CRCD( 0x9d65d0e7, \"horse\" )))\r\n\t{\r\n\t\t// Allow collision in lobbies now, if the option is on\r\n\t\tif( skate_mod->GetGameMode()->GetNameChecksum() != CRCD(0x1c471c60,\"netlobby\"))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}                \r\n\r\n\t// Option is always on in splitscreen games\r\n\tif( CFuncs::ScriptInSplitScreenGame( NULL, NULL ))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// If this option is on, we definitely collide\r\n\tcollision_pref = m_network_preferences.GetPreferenceChecksum( CRCD( 0x43ee978, \"player_collision\"), CRCD( 0x21902065, \"checksum\" ));\r\n\tif( collision_pref == CRCD( 0xf81bc89b, \"boolean_true\" ))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Even if it's turned off, we might still enable collision because player collision is the basis\r\n\t// of some game modes\r\n\tif( ( skate_mod->GetGameMode()->GetNameChecksum() == CRCD( 0xf9d5d933, \"netslap\" )) ||\r\n\t\t( skate_mod->GetGameMode()->GetNameChecksum() == CRCD( 0xca1f360f, \"slap\" )))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ShouldDisplayTeamScores( void )\r\n{\r\n\tuint32 collision_pref;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t \r\n\t// Always just show players in lobbies\r\n\tif( skate_mod->GetGameMode()->GetNameChecksum() == CRCD( 0x1c471c60, \"netlobby\" ))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif(\tskate_mod->GetGameMode()->IsTeamGame() == false )\r\n\t{\r\n\t\treturn false;\r\n\t}                \r\n\r\n\t// If this option is on, we definitely collide\r\n\tcollision_pref = m_network_preferences.GetPreferenceChecksum( CRCD( 0x92a6a8c8, \"score_display\"), CRCD( 0x21902065, \"checksum\") );\r\n\treturn ( collision_pref == CRCD( 0xd071112f, \"score_teams\" ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNet::Server*\t\tManager::SpawnServer( bool local, bool secure )\r\n{\r\n\t\r\n\tint flags;\r\n\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\r\n\tDbg_MsgAssert( m_server == NULL,( \"Failed to spawn new server. Old server still running!\\n\" ));\r\n\r\n\tflags = Net::App::mBROADCAST |\r\n\t\t\tNet::App::mDYNAMIC_RESEND |\r\n\t\t\tNet::App::mACCEPT_FOREIGN_CONN;\r\n\r\n\tif( local )\r\n\t{\r\n\t\tflags |= Net::App::mLOCAL;\r\n\t}\r\n\tif( secure )\r\n\t{\r\n\t\tflags |= Net::App::mSECURE;\r\n\t}\r\n\r\n\tm_server = net_man->CreateNewAppServer( 0, \"Skate4\", vMAX_CONNECTIONS, \r\n\t\t\t\t\t\t\t\t\t\t\tvHOST_PORT, inet_addr( net_man->GetLocalIP()), \r\n\t\t\t\t\t\t\t\t\t\t\tflags );\r\n    \r\n\tSetHostMode( vHOST_MODE_SERVE );\r\n\r\n\tif( m_server )\r\n\t{\r\n\t\tmlp_manager->AddLogicTask( *m_server_add_new_players_task );\r\n\t\t// These handlers will be removed after the server actually starts (i.e. after the lobby shuts down)\r\n\t\tm_server->m_Dispatcher.AddHandler( Net::MSG_ID_CONNECTION_REQ, \r\n\t\t\t\t\t\t\t\t\t\t\ts_handle_connection, \r\n\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE | Net::mHANDLE_FOREIGN,\r\n\t\t\t\t\t\t\t\t\t\t\tthis, Net::LOWEST_PRIORITY );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_JOIN_REQ,\r\n\t\t\t\t\t\t\t\t\t\t   s_handle_join_request,\r\n\t\t\t\t\t\t\t\t\t\t   Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN,\r\n\t\t\t\t\t\t\t\t\t\t   this );\r\n\t\tm_server->m_Dispatcher.AddHandler( Net::MSG_ID_FIND_SERVER, \r\n\t\t\t\t\t\t\t\t\t\t\ts_handle_find_server, \r\n\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE | Net::mHANDLE_FOREIGN , this );\r\n\t\tm_server->m_Dispatcher.AddHandler( Net::MSG_ID_DISCONN_REQ, s_handle_disconn_request, \r\n\t\t\t\t\t\t\t\t\t\t   Net::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_OBSERVE, s_handle_observe, \r\n\t\t\t\t\t\t\t\t\t\t   Net::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_READY_RESPONSE, s_handle_ready_response, \r\n\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_PLAYER_INFO_ACK, s_handle_player_info_ack,\r\n\t\t\t\t\t\t\t\t\t\t   0, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_MOVED_TO_RESTART, s_handle_player_restarted,\r\n\t\t\t\t\t\t\t\t\t\t   0, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_RUN_HAS_ENDED, s_handle_run_ended, 0, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_FCFS_START_GAME, s_handle_fcfs_request, Net::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_FCFS_BAN_PLAYER, s_handle_fcfs_request, Net::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_FCFS_CHANGE_LEVEL, s_handle_fcfs_request, Net::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_FCFS_TOGGLE_PROSET, s_handle_fcfs_request, Net::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_FCFS_TOGGLE_GOAL_SELECTION, s_handle_fcfs_request, Net::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_FCFS_END_GAME, s_handle_fcfs_request, Net::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_FCFS_SET_NUM_TEAMS, s_handle_fcfs_request, Net::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_REQUEST_CHANGE_TEAM, s_handle_team_change_request, Net::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_REQUEST_LEVEL, s_handle_request_level, Net::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_BEAT_GOAL, s_handle_beat_goal, Net::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_STARTED_GOAL, s_handle_started_goal, Net::mHANDLE_LATE, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_LEVEL_DATA, s_handle_level_data, 0, this, Net::HIGHEST_PRIORITY );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_RAIL_DATA, s_handle_rail_data, 0, this, Net::HIGHEST_PRIORITY );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_CHALLENGE_RESPONSE, s_handle_challenge_response, 0, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_CHEAT_CHECKSUM_RESPONSE, s_handle_cheat_checksum_response,\r\n\t\t\t\t\t\t\t\t\t\t\t  0, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_REQUEST_RAILS_DATA, s_handle_level_data_request, 0, this );\r\n\t\tm_server->m_Dispatcher.AddHandler( MSG_ID_REQUEST_GOALS_DATA, s_handle_level_data_request, 0, this );\r\n\r\n\t\tm_last_score_update = 0;\r\n\t\tm_waiting_for_game_to_start = false;\r\n        \t\r\n\t\tRandomizeSkaterStartingPoints();\r\n\t\tm_observer_input_handler = NULL;\t\t// record and handle button inputs\r\n\t}\r\n\telse\r\n\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\tint error = net_man->GetLastError();\r\n\t\tDbg_Printf( \"Spawn Server: Error %d\\n\", error );\r\n#endif\r\n\t\t// Here output appropriate error message to the screen\r\n\t}\r\n\r\n    return m_server;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNet::Client*\t\tManager::SpawnClient( bool broadcast, bool local, bool secure, int index )\r\n{\r\n\t\r\n\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\tint flags;\r\n\r\n\tDbg_MsgAssert( m_client[index] == NULL,( \"Failed to spawn new client. Old client still running!\\n\" ));\r\n\r\n\tflags = 0;\r\n\tif( broadcast )\r\n\t{\r\n\t\tflags |= Net::App::mBROADCAST;\r\n\t}\r\n\tif( local )\r\n\t{\r\n\t\tflags |= Net::App::mLOCAL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tflags |= Net::App::mDYNAMIC_RESEND | Net::App::mACCEPT_FOREIGN_CONN;\r\n\t}\r\n\tif( secure )\r\n\t{\r\n\t\tflags |= Net::App::mSECURE;\r\n\t}\r\n\r\n\tm_client[index] = net_man->CreateNewAppClient( index, \"Skate4\", \r\n\t\t\t\t\t\t\t\t\t\t\tvJOIN_PORT, inet_addr( net_man->GetLocalIP()),\r\n\t\t\t\t\t\t\t\t\t\t\tflags );\r\n\t\t\r\n\tif(( index == 0) && ( m_client[index] ))\r\n\t{  \r\n\t\tm_latest_ready_query = 0;\r\n\t\tm_proset_flags = 0;\r\n\t\tm_cam_player = NULL;\r\n\t\tSetReadyToPlay(false);\r\n\t}\r\n\telse\r\n\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\tint error = net_man->GetLastError();\r\n\t\tDbg_Printf( \"Spawn Client: Error %d\\n\", error );\r\n#endif\r\n\t\t// Here output appropriate error message to the screen\r\n\t}\r\n\r\n\tm_observer_input_handler = NULL;\r\n\tm_game_over = false;\r\n\tm_game_pending = false;\r\n\treturn m_client[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNet::Client*\t\tManager::SpawnMatchClient( void )\r\n{\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\tint flags;\r\n\r\n\tflags = Net::App::mBROADCAST | Net::App::mDYNAMIC_RESEND | Net::App::mACCEPT_FOREIGN_CONN | Net::App::mSECURE;\r\n\r\n\tm_match_client = net_man->CreateNewAppClient( 0, \"Match Skate4\", \r\n\t\t\t\t\t\t\t\t\t\t\tvJOIN_PORT, inet_addr( net_man->GetLocalIP()),\r\n\t\t\t\t\t\t\t\t\t\t\tflags );\r\n\tm_match_client->m_Dispatcher.AddHandler( \tNet::MSG_ID_SERVER_RESPONSE, \r\n\t\t\t\t\t\t\t\t\t\t\t\ts_handle_server_response, \r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE | Net::mHANDLE_FOREIGN,\r\n\t\t\t\t\t\t\t\t\t\t\t\tthis );\r\n\r\n\treturn m_match_client;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SpawnAutoServer( void )\r\n{\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\r\n\ts_auto_serve_start_time = Tmr::GetTime();\r\n\tmlp_man->AddLogicTask( *m_auto_server_task );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::JoinServer( bool observe_only, unsigned long ip, unsigned short port, int index )\r\n{\r\n    \r\n\tNet::Conn* conn;\r\n\tMsgConnectInfo msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tuint32 size;\r\n\tconst char* network_id;\r\n\tScript::CStruct* pStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\t//Net::Manager * net_man = Net::Manager::Instance();\r\n\t\t\r\n\tDbg_MsgAssert( m_client[index] != NULL,( \"Can't join server : Client has not been spawned\\n\" ));\r\n\r\n#ifndef __PLAT_NGC__\r\n\t//Dbg_Printf( \"Joining server at %s %d\\n\", inet_ntoa( *(struct in_addr*) &ip ), port );\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\tpPreferences = GetNetworkPreferences();\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"network_id\") );\r\n\tpStructure->GetText( \"ui_string\", &network_id, true );\r\n\r\n\tif( m_client[index]->IsLocal())\r\n\t{\r\n\t\tNet::Conn* server_conn;\r\n\r\n\t\tDbg_Assert( m_server );\r\n\r\n\t\tserver_conn = m_server->NewConnection( ip, port, Net::Conn::mLOCAL );\r\n\t\tconn = m_client[index]->NewConnection( ip, port, Net::Conn::mLOCAL );\r\n        m_client[index]->AliasConnections( server_conn, conn );\r\n\t}\r\n\telse\r\n\t{   \r\n\t\tm_client[index]->ConnectToServer( ip, port );\r\n\t\tconn = m_client[index]->NewConnection( ip, port );\r\n\r\n\t\tm_join_start_time = Tmr::GetTime();\r\n\t\tmlp_man->AddLogicTask( *m_join_timeout_task );\r\n\t\tSetJoinState( vJOIN_STATE_CONNECTING );\r\n\t\tmlp_man->AddLogicTask( *m_join_state_task );\r\n\t\t\r\n\t\tSetJoinIP( ip );\r\n\t\tSetJoinPort( port );\r\n\t}   \r\n\t\r\n\tmsg.m_Observer = observe_only;\r\n\tsize = 0;\r\n\t\r\n\tmsg.m_Version = vVERSION_NUMBER;\r\n\tmsg.m_Password[0] = '\\0';\r\n\tmsg.m_WillingToWait = 0;\r\n\t\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof(MsgConnectInfo);\r\n\tmsg_desc.m_Id = Net::MSG_ID_CONNECTION_REQ;\r\n\r\n\tm_client[index]->EnqueueMessageToServer( &msg_desc );\r\n\tm_client[index]->SendData();\r\n\r\n\tm_client[index]->m_Dispatcher.AddHandler( \tMSG_ID_PROCEED_TO_PLAY, \r\n\t\t\t\t\t\t\t\t\t\t\t\ts_handle_client_proceed, Net::mHANDLE_LATE, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler( \tMSG_ID_OBSERVE_PROCEED, \r\n\t\t\t\t\t\t\t\t\t\t\t\ts_handle_observe_proceed, Net::mHANDLE_LATE, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler( \tMSG_ID_OBSERVE_REFUSED, \r\n\t\t\t\t\t\t\t\t\t\t\t\ts_handle_observe_refused, Net::mHANDLE_LATE, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler( \tMSG_ID_JOIN_REFUSED, \r\n\t\t\t\t\t\t\t\t\t\t\t\ts_handle_join_refused, Net::mHANDLE_LATE, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler( \tMSG_ID_JOIN_PROCEED, \r\n\t\t\t\t\t\t\t\t\t\t\t\ts_handle_join_proceed, Net::mHANDLE_LATE, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler( \tMSG_ID_READY_QUERY, s_handle_ready_query, \r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler( \tMSG_ID_READY_RESPONSE, s_handle_ready_response, \r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler( \tMSG_ID_PLAYER_INFO_ACK_REQ, s_handle_player_info_ack_req, \r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler(\tMSG_ID_KING_DROPPED_CROWN, s_handle_dropped_crown, 0, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler(\tMSG_ID_PLAYER_DROPPED_FLAG, s_handle_dropped_flag, 0, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler(\tMSG_ID_PANEL_MESSAGE, s_handle_panel_message, \r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler( \tMSG_ID_AUTO_SERVER_NOTIFICATION, s_handle_auto_server_notification,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler( \tMSG_ID_FCFS_ASSIGNMENT, s_handle_fcfs_assignment,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler( \tMSG_ID_TEAM_CHANGE, s_handle_team_change,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler( \tMSG_ID_SET_NUM_TEAMS, s_handle_set_num_teams,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this );\r\n\tm_client[index]->m_Dispatcher.AddHandler( \tMSG_ID_CHAT, s_handle_chat, Net::mHANDLE_LATE );\r\n\tm_client[index]->m_Dispatcher.AddHandler(\tMSG_ID_CHALLENGE, s_handle_challenge,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE, this ); \r\n\t\r\n\tif( index == 0 )\r\n\t{   \r\n\t\tm_client[0]->m_Dispatcher.AddHandler( MSG_ID_SELECT_GOALS, s_handle_select_goals, 0, this );\r\n\t\tm_client[0]->m_Dispatcher.AddHandler( MSG_ID_GAME_INFO, s_handle_game_info, 0, this );\r\n\t\tm_client[0]->m_Dispatcher.AddHandler( MSG_ID_KILL_TEAM_FLAGS, s_handle_kill_flags, 0, this );\r\n\t\tm_client[0]->m_Dispatcher.AddHandler( MSG_ID_BEAT_GOAL, s_handle_beat_goal_relay, 0, this );\r\n\t\tm_client[0]->m_Dispatcher.AddHandler( MSG_ID_STARTED_GOAL, s_handle_started_goal_relay, 0, this );\r\n\t\tm_client[0]->m_Dispatcher.AddHandler( MSG_ID_TOGGLE_PROSET, s_handle_toggle_proset, 0, this );\r\n\t\tm_client[0]->m_Dispatcher.AddHandler( MSG_ID_CHANGE_LEVEL, s_handle_change_level, 0, this,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::HIGHEST_PRIORITY );\r\n\t\tm_client[0]->m_Dispatcher.AddHandler( MSG_ID_CHANGE_LEVEL, s_handle_new_level, 0, this,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::HIGHEST_PRIORITY );\r\n\t\tm_client[0]->m_Dispatcher.AddHandler( MSG_ID_LEVEL_DATA, s_handle_level_data, 0, this,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::HIGHEST_PRIORITY );\r\n\t\tm_client[0]->m_Dispatcher.AddHandler( MSG_ID_RAIL_DATA, s_handle_rail_data, Net::mHANDLE_CRC_MISMATCH, this,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::HIGHEST_PRIORITY );\r\n\t\tm_client[0]->m_Dispatcher.AddHandler( MSG_ID_GOALS_DATA, s_handle_goals_data, Net::mHANDLE_CRC_MISMATCH, this,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNet::HIGHEST_PRIORITY );\r\n\t\tm_client[0]->m_Dispatcher.AddHandler( MSG_ID_CHEAT_CHECKSUM_REQUEST, s_handle_cheat_checksum_request,\r\n\t\t\t\t\t\t\t\t\t\t\t  0, this );\r\n\t\t\r\n\t\t\r\n\t\tif( !m_client[0]->IsLocal())\r\n\t\t{\r\n\t\t\tm_client[index]->m_Dispatcher.AddHandler( MSG_ID_PLAYER_CREATE, s_handle_new_player, 0, this );\r\n\t\t\tm_client[index]->m_Dispatcher.AddHandler( MSG_ID_JOIN_ACCEPTED, s_handle_join_accepted, 0, this );\r\n\t\t\t\r\n\t\t}\r\n\r\n\t\tm_client[index]->m_Dispatcher.AddHandler( MSG_ID_WAIT_N_SECONDS, s_handle_wait_n_seconds, 0, this );\r\n\t\tm_client[index]->m_Dispatcher.AddHandler( MSG_ID_NEW_KING, s_handle_new_king, 0, this );\r\n\t\tm_client[index]->m_Dispatcher.AddHandler( MSG_ID_CAPTURED_FLAG, s_handle_captured_flag, 0, this );\r\n\t\tm_client[index]->m_Dispatcher.AddHandler( MSG_ID_STOLE_FLAG, s_handle_stole_flag, 0, this );\r\n\t\tm_client[index]->m_Dispatcher.AddHandler( MSG_ID_TOOK_FLAG, s_handle_took_flag, 0, this );\r\n\t\tm_client[index]->m_Dispatcher.AddHandler( MSG_ID_RETRIEVED_FLAG, s_handle_retrieved_flag, 0, this );\r\n\t\tm_client[index]->m_Dispatcher.AddHandler( MSG_ID_GAME_OVER, s_handle_game_over, 0, this );\r\n\t\tm_client[index]->m_Dispatcher.AddHandler( MSG_ID_END_GAME, s_handle_end_game, 0, this );\r\n\t\t\r\n\t\t// Add this low-priority object update handler just to advance the dispatcher's stream pointer.\r\n\t\t// Since we no longer send the size of the object update stream with the stream, we need\r\n\t\t// some code to return to the dispatcher the length of the message. If, because of timing,\r\n\t\t// we get one of these messages before our Mdl::Skate object update handler is instantiated\r\n\t\t// this handler will figure out the length of the message and pass it back\r\n\t\tm_client[index]->m_Dispatcher.AddHandler( MSG_ID_OBJ_UPDATE_STREAM, s_handle_object_update, \r\n\t\t\t\t\t\t\t\t\t\t\t\t  Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  Net::HIGHEST_PRIORITY );\r\n\t}\r\n\r\n\tSetObserverCommand( vOBSERVER_COMMAND_NONE );\r\n}\r\n    \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::ReattemptJoin( Net::App* client )\r\n{\r\n\tMsgConnectInfo msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\t\t\r\n\tmsg.m_Observer = ( GetJoinMode() == vJOIN_MODE_OBSERVE );\r\n\tmsg.m_Version = vVERSION_NUMBER;\r\n\tmsg.m_WillingToWait = 1;\r\n\tmsg.m_Password[0] = '\\0';\r\n\t\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof(MsgConnectInfo);\r\n\tmsg_desc.m_Id = Net::MSG_ID_CONNECTION_REQ;\r\n\tclient->EnqueueMessageToServer( &msg_desc );\r\n\tclient->SendData();\r\n\t\r\n\t// Reset join timeout\r\n\tm_join_start_time = Tmr::GetTime();\r\n\tmlp_man->AddLogicTask( *m_join_timeout_task );\r\n\r\n\tSetJoinState( vJOIN_STATE_JOINING );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::CancelJoinServer( void )\r\n{\r\n\tNet::Client* client;\r\n    Net::MsgDesc msg_desc;\r\n\r\n\t// These are \"finished\" states. Don't redundantly cancel our join if we've already cancelled\r\n\tif(\t( GetJoinState() == vJOIN_STATE_FINISHED ) ||\r\n\t\t( GetJoinState() == vJOIN_STATE_CONNECTED ) ||\r\n\t\t( GetJoinState() == vJOIN_STATE_REFUSED ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tclient = GetClient( 0 );\r\n\tDbg_Assert( client );\r\n\r\n    // First, wait for any pending network tasks to finish before sending out final disconn message\r\n#ifdef __PLAT_NGPS__\r\n\t//client->WaitForAsyncCallsToFinish();\r\n#endif  \t\t\r\n\tDbg_Printf( \"Leaving server\\n\" );\r\n\t\t\t\r\n\t// Send off last message, notifying server that I'm about to quit\r\n\tmsg_desc.m_Id = Net::MSG_ID_DISCONN_REQ;\r\n\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t// Wake the network thread up to send the data\r\n\tclient->SendData();\r\n\t\t\r\n\t// Wait for that final send to complete\r\n#ifdef __PLAT_NGPS__\r\n\t//client->WaitForAsyncCallsToFinish();\r\n#endif  \r\n    \r\n\tClientShutdown();\r\n\r\n\tm_join_timeout_task->Remove();\r\n\r\n\t// We may have made it halfway in, so free up any pending players.\r\n\tfree_all_pending_players(); \r\n\r\n#ifdef __PLAT_NGPS__\r\n\tif( mpBuddyMan->IsLoggedIn())\r\n\t{\r\n\t\tmpBuddyMan->SetStatusAndLocation( GP_CHATTING, (char*) Script::GetString( \"homie_status_chatting\" ), \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmpLobbyMan->GetLobbyName());\r\n\t}\r\n#endif\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::ReattemptJoinWithPassword( char* password )\r\n{\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\tScript::CStruct* pStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tconst char* network_id;\r\n\tMsgJoinInfo msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tint size;\r\n\tbool ignore_face_data;\r\n\r\n\tDbg_Printf( \"************* Trying password : %s\\n\", password );\r\n\t\t\r\n\tpPreferences = GetNetworkPreferences();\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"network_id\") );\r\n\tpStructure->GetText( \"ui_string\", &network_id, true );\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tmsg.m_Profile = mpBuddyMan->GetProfile();\r\n\tmsg.m_Rating = mpStatsMan->GetStats()->GetRating();\r\n#endif\r\n\tmsg.m_Observer = ( GetJoinMode() == vJOIN_MODE_OBSERVE );\r\n\tmsg.m_Version = vVERSION_NUMBER;\r\n\tmsg.m_WillingToWait = 1;\r\n\tif(\tnet_man->GetConnectionType() == Net::vCONN_TYPE_MODEM )\r\n\t{\r\n\t\tmsg.m_Broadband = 0;\r\n\t\tignore_face_data = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmsg.m_Broadband = 1;\r\n\t\tignore_face_data = false;\r\n\t}\r\n\tstrcpy( msg.m_Name, network_id );\r\n\tstrcpy( msg.m_Password, password );\r\n\tsize = 0;\r\n\tif( !msg.m_Observer )\r\n\t{\r\n\t\t// GJ:  transmit the way you look (slot 0 of the\r\n\t\t// skater profile manager) to the server\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tObj::CSkaterProfile* pSkaterProfile = skate_mod->GetProfile(0);\r\n\t\tNet::Conn *server_conn;\r\n\t\tLst::Search< Net::Conn > sh;\r\n\t\r\n\t\tserver_conn = m_client[0]->FirstConnection( &sh );\r\n\t\tif( server_conn->GetBandwidthType() == Net::Conn::vNARROWBAND )\r\n\t\t{\r\n\t\t\tignore_face_data = true;\r\n\t\t}\r\n\t\r\n\t\tsize = pSkaterProfile->WriteToBuffer(msg.m_AppearanceData, vMAX_APPEARANCE_DATA_SIZE,\r\n\t\t\t\t\t\t\t\t\t\t\t\tignore_face_data );\r\n\t\tDbg_Assert( size < vMAX_APPEARANCE_DATA_SIZE );\r\n\t\tDbg_Printf(\"\\n\\n******************* MsgJoinInfo appearance data size = %d %d\\n\", size, sizeof(MsgJoinInfo) - vMAX_APPEARANCE_DATA_SIZE + size);\r\n\t}\r\n\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof(MsgJoinInfo) - vMAX_APPEARANCE_DATA_SIZE + size;\r\n\tmsg_desc.m_Id = MSG_ID_JOIN_REQ;\r\n\tmsg_desc.m_Queue = Net::QUEUE_IMPORTANT;\r\n\tm_client[0]->EnqueueMessageToServer( &msg_desc );\r\n    \r\n\t//m_client[0]->SendData();\r\n\r\n\t// Reset join timeout\r\n\tm_join_start_time = Tmr::GetTime();\r\n\tmlp_man->AddLogicTask( *m_join_timeout_task );\r\n\r\n\tSetJoinState( vJOIN_STATE_JOINING_WITH_PASSWORD );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::ServerShutdown( void )\r\n{\r\n\t\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\r\n\tDbg_Message( \"Shutting Server Down\\n\" );\r\n\r\n\tif( m_server )\r\n\t{\r\n#ifndef __PLAT_XBOX__\r\n#ifndef __PLAT_NGC__\r\n\t\tif( !m_server->IsLocal() && InInternetMode())\r\n\t\t{\r\n\t\t\tmpLobbyMan->StopReportingGame();\r\n\t\t\tNNFreeNegotiateList();\r\n\t\t}\r\n#endif\r\n#endif    \r\n\t\tnet_man->DestroyApp( m_server );\r\n\t\tm_server_add_new_players_task->Remove();\r\n\t\tm_start_network_game_task->Remove();\r\n\t\tm_server = NULL;\r\n\t}\r\n\r\n\tm_flags.ClearMask( mSERVER );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t  Manager::ClientShutdown( void )\r\n{\r\n\t\r\n\t\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\tint i;\r\n\r\n#ifdef\t__PLAT_XBOX__\t \r\n\tif( m_client[0] && !m_client[0]->IsLocal())\r\n\t{\r\n\t\tif( m_XboxKeyRegistered )\r\n\t\t{\r\n\t\t\tif( XNetUnregisterKey( &m_XboxKeyId ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tm_XboxKeyRegistered = false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tfor( i = 0; i < vMAX_LOCAL_CLIENTS; i++ )\r\n\t{\r\n\t\tif( m_client[i] )\r\n\t\t{\r\n\t\t\tif(( i == 0 ) && !m_client[i]->IsLocal())\r\n\t\t\t{\r\n\t\t\t\tm_client_add_new_players_task->Remove();\r\n\t\t\t}\r\n\r\n\t\t\tnet_man->DestroyApp( m_client[i] );\r\n\t\t\tm_client[i] = NULL;\r\n\t\t}\r\n\t}\r\n\r\n\tif( m_observer_input_handler )\r\n\t{\r\n\t\tdelete m_observer_input_handler;\r\n\t\tm_observer_input_handler = NULL;\r\n\t}\r\n\r\n\tm_enter_chat_task->Remove();\r\n\tm_render_scores_task->Remove();\r\n\tm_change_level_task->Remove();\r\n\r\n\tClearTriggerEventList();\r\n\tSetReadyToPlay(false);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::MatchClientShutdown( void )\r\n{\r\n\tif( m_match_client )\r\n\t{\r\n\t\tNet::Manager * net_man = Net::Manager::Instance();\r\n\r\n\t\tnet_man->DestroyApp( m_match_client );\r\n\t\tm_match_client = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::AutoServerShutdown( void )\r\n{\r\n\tm_auto_server_task->Remove();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::GetJoinIP( void )\r\n{\r\n\treturn m_join_ip;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::GetJoinPrivateIP( void )\r\n{\r\n\treturn m_join_private_ip;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::GetJoinPort( void )\r\n{\r\n\treturn m_join_port;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetJoinIP( int ip )\r\n{\r\n\tDbg_Printf( \"**** In SetJoinIP: %s\\n\", inet_ntoa(*(struct in_addr *) &ip ));\r\n\tm_join_ip = ip;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetJoinPrivateIP( int ip )\r\n{\r\n\tm_join_private_ip = ip;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetJoinPort( int port )\r\n{\r\n\tm_join_port = port;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNet::Server*  Manager::GetServer( void )\r\n{\r\n\treturn m_server;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNet::Client*   Manager::GetClient( int index )\r\n{\r\n\t\r\n\r\n\tDbg_Assert( index < vMAX_LOCAL_CLIENTS );\r\n   \t\r\n\treturn m_client[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNet::Client*   Manager::GetMatchClient( void )\r\n{   \r\n\treturn m_match_client;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::GetNumPlayers( void )\r\n{\r\n\tint num_players;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo* player;\r\n\tLst::Search< NewPlayerInfo > new_sh;\r\n\tNewPlayerInfo* np;\r\n\r\n\tnum_players = 0;\r\n\r\n\tfor( player = FirstPlayerInfo( sh, true ); player; player = NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( !player->IsObserving() || player->m_flags.TestMask( PlayerInfo::mPENDING_PLAYER ))\r\n\t\t{\r\n\t\t\tnum_players++;\r\n\t\t}\r\n\t}\r\n    \r\n\tfor( np = new_sh.FirstItem( m_new_players ); np; np = new_sh.NextItem())\r\n\t{\r\n\t\t// Pending players count, observers don't\r\n\t\tif(\t( np->Flags & PlayerInfo::mPENDING_PLAYER ) ||\r\n\t\t\t( np->Flags & PlayerInfo::mJUMPING_IN ) ||\r\n\t\t\t!( np->Flags & PlayerInfo::mOBSERVER ))\r\n\t\t{\r\n\t\t\tnum_players++;\r\n\t\t}                 \r\n\t}\r\n\t\r\n\treturn num_players;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::GetNumObservers( void )\r\n{\r\n\tint num_observers;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo* player;\r\n\tLst::Search< NewPlayerInfo > new_sh;\r\n\tNewPlayerInfo* np;\r\n\r\n\tnum_observers = 0;\r\n\r\n\tfor( player = FirstPlayerInfo( sh, true ); player; player = NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\t// Pending players don't count as observers\r\n\t\tif( ( player->IsObserving()) && \r\n\t\t\t( !player->IsPendingPlayer()))\r\n\t\t{   \r\n\t\t\t// Don't count a server who is sitting out as an observer\r\n\t\t\tif(\t( player->IsLocalPlayer() && \r\n\t\t\t\t( GetHostMode() != vHOST_MODE_SERVE )))\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tnum_observers++;\r\n\t\t}\r\n\t}\r\n    \r\n\tfor( np = new_sh.FirstItem( m_new_players ); np; np = new_sh.NextItem())\r\n\t{\r\n\t\t// Don't count pending players as observers\r\n\t\tif(( np->Flags & PlayerInfo::mOBSERVER ) &&\r\n\t\t   ( !( np->Flags & PlayerInfo::mPENDING_PLAYER )))\r\n\t\t{\r\n\t\t\tnum_observers++;\r\n\t\t}                 \r\n\t}\r\n\t\r\n\treturn num_observers;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPlayerInfo*\t\tManager::NewPlayer( Obj::CSkater* skater, Net::Conn* conn, int flags )\r\n{\r\n\tPlayerInfo* new_player;\r\n\t\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\tnew_player = new PlayerInfo( flags );\r\n\r\n\tnew_player->m_Skater = skater;\r\n\tnew_player->m_Conn = conn;\r\n\t\t\r\n\t// By default, count the Local player as our currently observed player\r\n\tif( new_player->IsLocalPlayer())\r\n\t{\r\n\t\tif( new_player->IsObserving())\r\n\t\t{   \r\n\t\t\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\t\t\tInp::Manager * inp_manager = Inp::Manager::Instance();\r\n\t\t\t\r\n\t\t\t/*new_player->m_cam = new Obj::CSkaterCam( 0 );\r\n\t\t\tNx::CViewportManager::sSetCamera( 0, new_player->m_cam );\r\n\t\t\tnew_player->m_cam->SetMode( Obj::CSkaterCam::SKATERCAM_MODE_NORMAL_MEDIUM, 0.0f );*/\r\n\t\t\t\t\t\t\r\n\t\t\tScript::RunScript( \"hide_panel_stuff\" );\r\n\t\t\tObservePlayer( GetNextPlayerToObserve());\r\n\r\n\t\t\tnew_player->m_observer_logic_task = \r\n\t\t\t\t\tnew Tsk::Task< PlayerInfo > ( PlayerInfo::s_observer_logic_code, *new_player );\r\n\t\t\tmlp_manager->AddLogicTask( *new_player->m_observer_logic_task );\r\n\t\t\tm_observer_input_handler = new Inp::Handler< Manager > ( 0,  s_observer_input_logic_code, *this, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Tsk::BaseTask::Node::vHANDLER_PRIORITY_OBSERVER_INPUT_LOGIC );\r\n\t\t\tinp_manager->AddHandler( *m_observer_input_handler );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_cam_player = NULL;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tPlayerInfo* local_player;\r\n\r\n\t\tlocal_player = GetLocalPlayer();\r\n\t\tDbg_MsgAssert( local_player,( \"Should have local player by now\" ));\r\n\r\n\t\tif( local_player->IsObserving())\r\n\t\t{\r\n\t\t\tif( m_cam_player == NULL )\r\n\t\t\t{\r\n\t\t\t\tObservePlayer( new_player );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_Printf( \"Player added : %p with conn %p\\n\", new_player, new_player->m_Conn );\r\n    \r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn new_player;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tManager::SendFaceDataToServer( void )\r\n{\r\n\tbool sent_data;\r\n\tNet::Manager* net_man = Net::Manager::Instance();\r\n\r\n\tDbg_Assert( InNetGame());\r\n\r\n\t// Don't send face data to other players if I'm on a modem\r\n\tif(\tnet_man->GetConnectionType() == Net::vCONN_TYPE_MODEM )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( 0 );\r\n\tGfx::CModelAppearance* pAppearance = pSkaterProfile->GetAppearance();\r\n\tGfx::CFaceTexture* pFaceTexture = pAppearance->GetFaceTexture();\r\n\r\n\tsent_data = false;\r\n\tif( pFaceTexture && pFaceTexture->IsValid())\r\n\t{\r\n\t\tif( OnServer())\r\n\t\t{\r\n\t\t\tPlayerInfo* local_player;\r\n\r\n\t\t\tlocal_player = GetLocalPlayer();\r\n\t\t\t\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetMiscHeap());\r\n\t\t\tlocal_player->m_face_data = new uint8[vMAX_FACE_DATA_SIZE + 1];\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t\tlocal_player->m_face_data[0] = 0;\t// player id\r\n\t\t\tpFaceTexture->WriteToBuffer( &local_player->m_face_data[1], vMAX_FACE_DATA_SIZE );\r\n\t\t\tsent_data = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tNet::Conn *server_conn;\r\n\t\t\tLst::Search< Net::Conn > sh;\r\n\t\t\r\n\t\t\tserver_conn = GetClient(0)->FirstConnection( &sh );\r\n\t\t\tif( server_conn->GetBandwidthType() == Net::Conn::vBROADBAND )\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\t\t\t\tuint8* buffer = new uint8[vMAX_FACE_DATA_SIZE];\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\t\t\t\tpFaceTexture->WriteToBuffer( buffer, vMAX_FACE_DATA_SIZE );\r\n\t\t\t\tGetClient(0)->StreamMessageToServer( MSG_ID_FACE_DATA, vMAX_FACE_DATA_SIZE, buffer, \"Face Data\",\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t vSEQ_GROUP_FACE_MSGS, false, false );\r\n\t\t\t\tdelete[] buffer;\r\n\t\t\t\tsent_data = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn sent_data;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SendFaceDataToPlayer( PlayerInfo* player )\r\n{\r\n\tPlayerInfo* face_player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tNet::Manager* net_man = Net::Manager::Instance();\r\n\r\n\tDbg_Assert( OnServer());\r\n\r\n\t// Don't send face data to other players if I'm on a modem\r\n\tif(\tnet_man->GetConnectionType() == Net::vCONN_TYPE_MODEM )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor( face_player = FirstPlayerInfo( sh ); face_player; face_player = NextPlayerInfo( sh ))\r\n\t{\r\n\t\tbool has_face_data;\r\n\r\n\t\tif( face_player == player )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t// Don't send face data to modem players for bandwidth reasons\r\n\t\tif( player->m_Conn->GetBandwidthType() == Net::Conn::vNARROWBAND )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\thas_face_data = false;\r\n\t\tif( face_player->GetFaceData())\r\n\t\t{\r\n\t\t\thas_face_data = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif( face_player->IsLocalPlayer())\r\n\t\t\t{\r\n\t\t\t\thas_face_data = SendFaceDataToServer();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( has_face_data == false )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t\r\n\t\tm_server->StreamMessageToConn( player->m_Conn, MSG_ID_FACE_DATA, vMAX_FACE_DATA_SIZE + 1, face_player->GetFaceData(), \"Face Data\",\r\n\t\t\t\t\t\t\t\t\t   vSEQ_GROUP_FACE_MSGS, false, true );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::ClientAddNewPlayer( NewPlayerInfo* new_player )\r\n{\r\n\tObj::CSkater* skater;\r\n\tPlayerInfo* player_info;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n    \r\n\tDbg_Assert( !OnServer());\r\n\r\n\tskater = NULL;\r\n    \r\n\tif( !( new_player->Flags & PlayerInfo::mOBSERVER ))\r\n\t{\r\n\t\tObj::CSkaterProfile* pSkaterProfile;\r\n\r\n\t\tif ( CFuncs::ScriptInSplitScreenGame( NULL, NULL ) )\r\n\t\t{\r\n\t\t\t// in splitscreen games, we have to figure out\r\n\t\t\t// which player is currently being added (either 0 or 1)\r\n\t\t\tpSkaterProfile = skate_mod->GetProfile(new_player->ObjID);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// in other types of games, \"your player\" is always\r\n\t\t\t// in slot 0 of the local machine's skater profile manager\r\n\t\t\tpSkaterProfile = skate_mod->GetProfile(0);\r\n\t\t}\r\n\t\tif( InNetGame())\r\n\t\t{\r\n\t\t\tif( new_player->Flags & PlayerInfo::mLOCAL_PLAYER )\r\n\t\t\t{\r\n\t\t\t\tskater = skate_mod->add_skater( pSkaterProfile, true, new_player->ObjID, 0);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tint skater_num;\r\n\r\n\t\t\t\t\r\n\t\t\t\tif( skate_mod->GetLocalSkater())\r\n\t\t\t\t{\r\n\t\t\t\t\tskater_num = skate_mod->GetNumSkaters();\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tskater_num = ( skate_mod->GetNumSkaters() + 1 ) % Mdl::Skate::vMAX_SKATERS;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tskater = skate_mod->add_skater( new_player->mpSkaterProfile, false, new_player->ObjID,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tskater_num );\r\n\t\t\t\t\r\n\t\t\t\tif (new_player->VehicleControlType)\r\n\t\t\t\t{\r\n\t\t\t\t\tObj::CSkaterStateHistoryComponent* p_skater_state_history_component = GetSkaterStateHistoryComponentFromObject(skater);\r\n\t\t\t\t\tDbg_Assert(p_skater_state_history_component);\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_skater_state_history_component->SetCurrentVehicleControlType(new_player->VehicleControlType);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tskater = skate_mod->add_skater( pSkaterProfile, true, new_player->ObjID, skate_mod->GetNumSkaters() );\r\n\t\t}\r\n\t}\r\n\r\n\tplayer_info = GetPlayerByObjectID( new_player->ObjID );\r\n\tif( new_player->Flags & PlayerInfo::mJUMPING_IN )\r\n\t{   \r\n\t\tif( player_info == NULL )\r\n\t\t{\r\n\t\t\tplayer_info = GetLocalPlayer();\r\n\t\t}\r\n\r\n\t\tif( player_info )\r\n\t\t{\r\n\t\t\tDestroyPlayer( player_info );\r\n\t\t\tplayer_info = NULL;\r\n\t\t}\r\n\t}\r\n\r\n\tif( player_info == NULL )\r\n\t{\r\n\t\tint flags;\r\n\r\n\t\tflags = ( new_player->Flags & (\tPlayerInfo::mLOCAL_PLAYER | PlayerInfo::mOBSERVER | PlayerInfo::mHAS_ANY_FLAG ));\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\tplayer_info = NewPlayer( skater, new_player->Conn, flags );\r\n        strcpy( player_info->m_Name, new_player->Name );\r\n\t\tplayer_info->m_Team = new_player->Team;\r\n\t\tplayer_info->m_Profile = new_player->Profile;\r\n\t\tplayer_info->m_Rating = new_player->Rating;\r\n\t\tplayer_info->m_VehicleControlType = new_player->VehicleControlType;\r\n\t\tAddPlayerToList( player_info );\r\n\t\tif( new_player->Flags & PlayerInfo::mKING_OF_THE_HILL )\r\n\t\t{\r\n\t\t\tplayer_info->MarkAsKing( true );\r\n\t\t}\r\n\t}\r\n\t\r\n\t// We get this message when we're added to a network lobby. So go ahead and start it up\r\n\t// on our end\r\n\tif( new_player->Flags & PlayerInfo::mJUMPING_IN )\r\n\t{\r\n\t\t// We're jumping into a game at the lobby so start the lobby game flow.\r\n\t\t// Also send our face texture data to all other players.\r\n\t\tSendFaceDataToServer();\r\n\t\tskate_mod->GetTrickObjectManager()->DeleteAllTrickObjects();\r\n\t\tScript::RunScript( \"do_backend_retry\" );\r\n\t}\r\n\r\n\tif( player_info->IsLocalPlayer() == false )\r\n\t{\r\n\t\tMdl::Score* score = GetSkaterScoreComponentFromObject( skater )->GetScore();\r\n\r\n\t\tskater->RemoveFromCurrentWorld();\r\n\t\tscore->SetTotalScore( new_player->Score );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::DeferredNewPlayer( NewPlayerInfo* new_player, int num_frames )\r\n{\r\n\t\r\n\t\r\n\tLst::Node< NewPlayerInfo > *player;\r\n\tLst::Search< NewPlayerInfo > new_sh;\r\n\tNewPlayerInfo* np;\r\n    \r\n\t// First, make sure we don't already have this new player queued up\r\n\tfor( np = new_sh.FirstItem( m_new_players ); np; np = new_sh.NextItem())\r\n\t{\r\n\t\tif( np->ObjID == new_player->ObjID )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\tnp = new NewPlayerInfo;\r\n\r\n\tstrcpy( np->Name, new_player->Name );\r\n    \r\n\tnp->Conn = new_player->Conn;\r\n\tnp->ObjID = new_player->ObjID;\r\n\tnp->Flags = new_player->Flags;\r\n\tnp->Team = new_player->Team;\r\n\tnp->Profile = new_player->Profile;\r\n\tnp->Rating = new_player->Rating;\r\n\tnp->Score = new_player->Score;\r\n\tnp->VehicleControlType = new_player->VehicleControlType;\r\n\tif(( np->Flags & PlayerInfo::mJUMPING_IN ) && OnServer())\r\n\t{\r\n\t\tnp->JumpInFrame = m_server->m_FrameCounter;\r\n\t}\r\n\r\n\t// Pure observers don't have skater profile date\r\n\tif( (!( np->Flags & PlayerInfo::mOBSERVER ) || ( np->Flags & PlayerInfo::mPENDING_PLAYER )))\r\n\t{\r\n\t\t// GJ:  copy the contents of the skater profile from one to the other\r\n\t\t// it'd be nice to just use a copy constructor, but the compiler\r\n\t\t// doesn't seem to like it.\r\n\t\tuint8* pTempBuffer = new uint8[vMAX_APPEARANCE_DATA_SIZE];\r\n\t\tnew_player->mpSkaterProfile->WriteToBuffer(pTempBuffer, vMAX_APPEARANCE_DATA_SIZE);\r\n\t\tnp->mpSkaterProfile->ReadFromBuffer(pTempBuffer);\r\n\t\tdelete[] pTempBuffer;\r\n\t\t\r\n\t\t// GJ 2/12/03:  the above was written sometime during THPS3,\r\n\t\t// and our current compiler seems to be okay now.  However,\r\n\t\t// i'm afraid of breaking anything by changing this now...\r\n//\t\t*np->mpSkaterProfile = *new_player->mpSkaterProfile;\r\n\t}\r\n\t\t\t\t\t\t \r\n\tif( OnServer())\r\n\t{\r\n        np->AllowedJoinFrame = m_server->m_FrameCounter + num_frames;\r\n\r\n\t\tif( !( np->Flags & PlayerInfo::mLOCAL_PLAYER ))\r\n\t\t{\r\n\t\t\tif( np->Flags & PlayerInfo::mOBSERVER )\r\n\t\t\t{\r\n\t\t\t\tuint32 msg_checksum;\r\n\r\n\t\t\t\tif( np->Flags & PlayerInfo::mPENDING_PLAYER )\r\n\t\t\t\t{\r\n\t\t\t\t\tmsg_checksum = Script::GenerateCRC(\"net_message_join_pending\");\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tmsg_checksum = Script::GenerateCRC(\"net_message_observing\");\r\n\t\t\t\t}\r\n\t\t\t\tCreateNetPanelMessage( true, msg_checksum, new_player->Name );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tCreateNetPanelMessage( false, Script::GenerateCRC(\"net_message_joining\"),\r\n\t\t\t\t\t\t\t\t\t   new_player->Name );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tnp->AllowedJoinFrame = m_client[0]->m_FrameCounter + num_frames;\r\n\t}\r\n\t\r\n\tplayer = new Lst::Node< NewPlayerInfo > ( np );\r\n\r\n\tm_new_players.AddToTail( player );\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::AddPlayerToList( PlayerInfo* player )\r\n{\r\n\t\r\n\r\n\tDbg_Assert( player );\r\n\r\n    m_players.AddToTail( player );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::DestroyPlayer( PlayerInfo* player )\r\n{\r\n\t// If we're destroying the player we're looking at, change to the next player\r\n\tif( player == m_cam_player )\r\n\t{\r\n\t\tPlayerInfo* local_player;\r\n\r\n\t\tm_cam_player = GetNextPlayerToObserve();\r\n\t\tif( player == m_cam_player )\r\n\t\t{\r\n\t\t\tm_cam_player = NULL;\r\n\t\t}\r\n        \r\n\t\tlocal_player = GetLocalPlayer();\r\n\t\tif( local_player && local_player->m_Skater )\r\n\t\t{\r\n\t\t\tObservePlayer( local_player );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tObservePlayer( m_cam_player );\r\n\t\t}\r\n\t}\r\n\r\n\tif( player->IsKing())\r\n\t{\r\n\t\tif( m_crown )\r\n\t\t{\r\n\t\t\tm_crown->RemoveFromKing();\r\n\t\t}\r\n\t}\r\n\r\n\tif( player->HasCTFFlag())\r\n\t{\r\n\t\tchar team_str[64];\r\n\t\tint team;\r\n\t\tScript::CStruct* pParams;\r\n\t\tPlayerInfo* local_player;\r\n\t\t\r\n\t\tteam = player->HasWhichFlag();\r\n\t\tsprintf( team_str, \"team_%d_name\", team + 1 );\r\n\t\tpParams = new Script::CStruct;\r\n\r\n\t\tpParams->AddInteger( \"team\", team );\r\n\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\tScript::RunScript( \"flag_returned\", pParams );\r\n\r\n\t\tdelete pParams;\r\n\r\n\t\tlocal_player = GetLocalPlayer();\r\n\t\tif( local_player && !local_player->IsObserving())\r\n\t\t{\r\n\t\t\tif( local_player->m_Team == team )\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( \"hide_ctf_arrow\" );\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t\tplayer->ClearCTFState();\r\n\t}\r\n\r\n\tdelete player;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPlayerInfo*\t\tManager::GetCurrentlyObservedPlayer( void )\r\n{\r\n\treturn m_cam_player;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPlayerInfo*\t\tManager::GetNextPlayerToObserve( void )\r\n{\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo* new_cam_player;\r\n\r\n\t\r\n\r\n\tnew_cam_player = NULL;\r\n\tfor( new_cam_player = FirstPlayerInfo( sh ); new_cam_player;\r\n\t\t\tnew_cam_player = NextPlayerInfo( sh ))\r\n\t{\r\n\t\t// If we had no 'current' target, just return the first player\r\n\t\tif( m_cam_player == NULL )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// Ok, we found our current cam_player. Return the next one, if there is a next one\r\n\t\tif( new_cam_player == m_cam_player )\r\n\t\t{\r\n\t\t\tnew_cam_player = NextPlayerInfo( sh );\r\n\t\t\tif( new_cam_player == NULL )\r\n\t\t\t{\r\n\t\t\t\t// We've reached the end of the list. Return the first one\r\n\t\t\t\tnew_cam_player = FirstPlayerInfo( sh );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\treturn new_cam_player;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::ObservePlayer( PlayerInfo* player )\r\n{   \r\n\tObj::CSkaterCameraComponent* skater_cam;\r\n\tObj::CWalkCameraComponent* walk_cam;\r\n\tObj::CCompositeObject* cam_obj;\r\n\t\r\n\tcam_obj = (Obj::CCompositeObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0x967c138c,\"skatercam0\"));\r\n\tskater_cam = GetSkaterCameraComponentFromObject( cam_obj );\r\n\twalk_cam = GetWalkCameraComponentFromObject( cam_obj );\r\n\t\r\n\tif (!player || !player->m_Skater)\r\n\t{\r\n\t\tDbg_Printf( \"Attempting to observe NULL player\\n\" );\r\n\t\t\r\n\t\tskater_cam->SetSkater( NULL );\r\n\t\twalk_cam->SetSkater( NULL );\r\n\t\t\r\n\t\tm_cam_player = NULL;\r\n\t\t\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tManager* gamenet_man = Manager::Instance();\r\n\tPlayerInfo* local_player;\r\n\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\t\r\n\tif (player != local_player)\r\n\t{\r\n\t\t// observer camera only use the skater camera logic\r\n\t\t\r\n\t\tDbg_Printf( \"Observing player %d\\n\", player->m_Skater->GetID());\r\n\t\tskater_cam->SetSkater( player->m_Skater );\r\n\t\t\r\n\t\twalk_cam->SetSkater( NULL );\r\n\t\t\r\n\t\tskater_cam->Suspend( false );\r\n\t\twalk_cam->Suspend( true );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// restore the correct camera state for a normal skate camera\r\n\t\t\r\n\t\tObj::CSkaterPhysicsControlComponent* physics_control_comp;\r\n\t\t\r\n\t\tphysics_control_comp = GetSkaterPhysicsControlComponentFromObject( player->m_Skater );\r\n\t\tDbg_MsgAssert(physics_control_comp, (\"Local player has no SkaterPhysicsControlComponent\"));\r\n\t\t\r\n\t\tDbg_Printf( \"Restoring standard camera to player %d\\n\", player->m_Skater->GetID());\r\n\t\t\r\n\t\tskater_cam->SetSkater( player->m_Skater );\r\n\t\twalk_cam->SetSkater( player->m_Skater );\r\n\t\t\r\n\t\tif (physics_control_comp->IsSkating())\r\n\t\t{\r\n\t\t\tskater_cam->Suspend( false );\r\n\t\t\twalk_cam->Suspend( true );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tskater_cam->Suspend( true );\r\n\t\t\twalk_cam->Suspend( false );\r\n\t\t\twalk_cam->Reset();\r\n\t\t}\r\n\t}\r\n\t\r\n\tm_cam_player = player;\r\n\r\n\t/*if( player == NULL )\r\n\t{\r\n\t\tMth::Vector rot;\r\n\t\tMth::Matrix cam_matrix;\r\n\t\tMth::Vector node_pos;\r\n\t\tint node;\r\n\r\n\t\tnode = Obj::GetRestartNode( Script::GenerateCRC( \"Player1\" ), 0 );\r\n\t\tScript::CStruct* pNodeData = SkateScript::GetNode( node ); \r\n\t\t\r\n\t\tcam_matrix.Ident( );\t   \t\t// Set identity before we decided if we need to rotate or not, in case we don't.\r\n\t\t\r\n\t\tSkateScript::GetPosition( node, &node_pos );\r\n\t\tnode_pos[Y] += FEET( 5 );\r\n\t\tDbg_Printf( \"************************ Got Position %f %f %f\\n\", node_pos[X], node_pos[Y], node_pos[Z] );\r\n\t\t\r\n\t\tSkateScript::GetAngles( pNodeData, &rot );\r\n\t\tcam_matrix.RotateY( rot[ Y ] );\r\n\t\tcam_matrix[Z] = -cam_matrix[Z];\r\n\t\tcam_matrix[X] = -cam_matrix[X];\r\n\t\tDbg_Printf( \"************************ Rots X: %f Y: %f Z: %f\\n\", rot[X], rot[Y], rot[Z] );\r\n\t\t\r\n\t\tDbg_Assert( local_player );\r\n\t\tDbg_Assert( local_player->m_cam );\r\n\r\n\t\tlocal_player->m_cam->SetMatrix( cam_matrix );\r\n\t\tlocal_player->m_cam->SetPos( node_pos );\r\n\t\tlocal_player->m_cam->SetSkater( NULL );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Only works in network games\r\n\tif( InNetGame())\r\n\t{   \r\n\t\tif( local_player && local_player->IsObserving())\r\n\t\t{   \r\n\t\t\tm_cam_player = player;\r\n\t\t\tlocal_player->m_cam->SetSkater( m_cam_player->m_Skater );\r\n\t\t}\r\n\t}*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::RequestObserverMode( void )\r\n{\r\n\tPlayerInfo* local_player;\r\n    Net::MsgDesc msg_desc;\r\n\t\r\n\tlocal_player = GetLocalPlayer();\r\n\tDbg_Assert( local_player );\r\n\r\n\tif( local_player->IsObserving())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tDbg_Printf( \"Sent request to enter observer mode\\n\" );\r\n\tmsg_desc.m_Id = MSG_ID_OBSERVE;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tm_client[0]->EnqueueMessageToServer( &msg_desc );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::ChooseNewServerPlayer( void )\r\n{\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tNet::MsgDesc msg_desc;\r\n\r\n\tDbg_Assert(( GetServerPlayer() == NULL ));\t// Shouldn't call this function if one already exists\r\n\tDbg_Assert( m_server );\r\n\r\n\tfor( player = FirstPlayerInfo( sh ); player; player = NextPlayerInfo( sh ))\r\n\t{\r\n\t\tScript::CStruct* pStructure;\r\n\t\tuint32 checksum;\r\n\r\n\t\t// For now, just select the first non-server player info\r\n\t\tif( player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// If we don't have any \"fully in\" players at this point, that's ok. Don't choose a server player.\r\n\t\t// When they are marked as being \"fully in\" they will be chosen as the fcfs and notified\r\n\t\tif( player->IsFullyIn() == false )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tplayer->MarkAsServerPlayer();\r\n\t\t\r\n\t\tpStructure = m_network_preferences.GetPreference( Script::GenerateCRC(\"player_collision\"));\r\n\t\tpStructure->GetChecksum( \"Checksum\", &checksum, true );\r\n\t\t\r\n\t\tmsg_desc.m_Data = &checksum;\r\n\t\tmsg_desc.m_Length = sizeof( uint32 );\r\n\t\tmsg_desc.m_Id = MSG_ID_FCFS_ASSIGNMENT;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\tm_server->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::EnterObserverMode( void )\r\n{\r\n\tPlayerInfo* local_player;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\tInp::Manager * inp_manager = Inp::Manager::Instance();\r\n\tLst::Search< PlayerInfo > first_player;\r\n\t\r\n\tDbg_Printf( \"Entering Observer Mode\\n\" );\r\n\t\r\n\tlocal_player = GetLocalPlayer();\r\n\tDbg_Assert( local_player );\r\n\r\n    if( local_player->IsObserving())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif( OnServer())\r\n\t{\r\n\t\tDropPlayer( local_player, vREASON_OBSERVING );\r\n\t}\r\n\r\n\tif( local_player->IsKing())\r\n\t{\r\n\t\tlocal_player->MarkAsKing( false );\r\n\t\tif( m_crown )\r\n\t\t{\r\n\t\t\tm_crown->RemoveFromKing();\r\n\t\t}\r\n\t}\r\n\tif( local_player->HasCTFFlag())\r\n\t{\r\n\t\tchar team_str[64];\r\n\t\tint team;\r\n\t\tScript::CStruct* pParams;\r\n\t\t\r\n\t\tteam = local_player->HasWhichFlag();\r\n\t\tsprintf( team_str, \"team_%d_name\", team + 1 );\r\n\t\tpParams = new Script::CStruct;\r\n\r\n\t\tpParams->AddInteger( \"team\", team );\r\n\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\tScript::RunScript( \"flag_returned\", pParams );\r\n\r\n\t\tdelete pParams;\r\n\r\n\t\tScript::RunScript( \"hide_ctf_arrow\" );\t\t\r\n\t\tlocal_player->ClearCTFState();\r\n\t}\r\n\r\n\tlocal_player->m_flags.SetMask( PlayerInfo::mOBSERVER );\r\n\r\n\r\n\tskate_mod->remove_skater( local_player->m_Skater );\r\n\tlocal_player->m_Skater = NULL;\r\n\t//skate_mod->HideSkater( local_player->m_Skater );\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterHeap( 0 ));\r\n\r\n\t//Gfx::Camera* p_camera = &(viewer_mod->GetCamera( 0 )->camera );\r\n\t/*local_player->m_cam = new Obj::CSkaterCam( 0 );\r\n\tDbg_Assert( local_player->m_cam );\r\n\tNx::CViewportManager::sSetCamera( 0, local_player->m_cam );\r\n\tlocal_player->m_cam->SetMode( Obj::CSkaterCam::SKATERCAM_MODE_NORMAL_MEDIUM, 0.0f );*/\r\n\r\n\tObservePlayer( GetNextPlayerToObserve());\r\n\r\n\tlocal_player->m_observer_logic_task = \r\n\t\t\tnew Tsk::Task< PlayerInfo > ( PlayerInfo::s_observer_logic_code, *local_player );\r\n\tmlp_manager->AddLogicTask( *local_player->m_observer_logic_task );\r\n\tm_observer_input_handler = new Inp::Handler< Manager > ( 0,  s_observer_input_logic_code, *this, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Tsk::BaseTask::Node::vNORMAL_PRIORITY-1 );\r\n\tinp_manager->AddHandler( *m_observer_input_handler );\r\n\tSetObserverCommand( vOBSERVER_COMMAND_NONE );\r\n\r\n\tScript::RunScript( \"ShowAllObjects\" );\r\n\tScript::RunScript( \"hide_panel_stuff\" );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::GetNextPlayerObjectId( void )\r\n{\r\n\tLst::Search< PlayerInfo > sh;\r\n\tLst::Search< NewPlayerInfo > new_sh;\r\n\tPlayerInfo* player;\r\n\tNewPlayerInfo* new_player;\r\n\tint i;\r\n\tbool taken;\r\n\r\n\t\r\n\r\n\tDbg_MsgAssert( m_flags.TestMask( mSERVER ),( \"Only the server should be assigning ids!\\n\" ));\r\n\t\r\n\tfor( i = 0; i < 16; i++ )\r\n\t{\r\n\t\ttaken = false;\r\n\t\tfor( player = FirstPlayerInfo( sh ); player; player = NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tif( player->m_Skater->GetID() == (uint32)i )\r\n\t\t\t{\r\n\t\t\t\ttaken = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( taken == false )\r\n\t\t{\r\n\t\t\tfor( new_player = FirstNewPlayerInfo( new_sh ); new_player;\r\n\t\t\t\t\tnew_player = NextNewPlayerInfo( new_sh ))\r\n\t\t\t{\r\n\t\t\t\t// Pure observers don't and won't have object ids\r\n\t\t\t\tif(( new_player->Flags & PlayerInfo::mOBSERVER ) &&\r\n\t\t\t\t   ( !( new_player->Flags & PlayerInfo::mPENDING_PLAYER )))\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tif( new_player->ObjID == i )\r\n\t\t\t\t{\r\n\t\t\t\t\ttaken = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( taken == false )\r\n\t\t{\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert( 0,( \"Ran out of player object id's. More than 16 players in game?\\n\" ));\r\n\treturn 16;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CSkater*\tManager::GetSkaterByConnection( Net::Conn* conn )\r\n{\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo *player;\r\n\r\n\tfor( player = FirstPlayerInfo( sh ); player; player = NextPlayerInfo( sh ))\r\n\t{\r\n\t\tif( player->m_Conn == conn )\r\n\t\t{\r\n\t\t\treturn player->m_Skater;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPlayerInfo*\t\tManager::GetPlayerByConnection( Net::Conn* conn )\r\n{\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo *player;\r\n\r\n\tfor( player = FirstPlayerInfo( sh, true ); player; player = NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( player->m_Conn == conn )\r\n\t\t{\r\n\t\t\treturn player;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPlayerInfo*\t\tManager::GetPlayerByObjectID( unsigned short obj_id )\r\n{\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo *player;\r\n\r\n\tfor( player = FirstPlayerInfo( sh ); player; player = NextPlayerInfo( sh ))\r\n\t{\r\n\t\tif( player->m_Skater )\r\n\t\t{\r\n\t\t\tif( player->m_Skater->GetID() == obj_id )\r\n\t\t\t{\r\n\t\t\t\treturn player;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::FindServersOnLAN( void )\r\n{\r\n\tif( m_match_client )\r\n\t{\r\n\t\tMsgFindServer msg;\r\n        \r\n\t\tmsg.m_Timestamp = Tmr::GetTime();\r\n        \r\n#if (defined(__PLAT_NGPS__)||defined(__PLAT_NGC__))\r\n\t\tm_match_client->SendMessageTo( Net::MSG_ID_FIND_SERVER, sizeof( MsgFindServer ), &msg, \r\n\t\t\t\t\t\t\t\t\t0xFFFFFFFF, vHOST_PORT, 0 );\r\n#else\r\n\t\tXNetRandom( m_match_client->m_Nonce, sizeof( m_match_client->m_Nonce ));\r\n\t\tmemcpy( msg.m_Nonce, &m_match_client->m_Nonce, sizeof( m_match_client->m_Nonce ));\r\n\t\tm_match_client->SendMessageTo( Net::MSG_ID_FIND_SERVER, sizeof( MsgFindServer ), &msg,\r\n\t\t\t\t\t\t\t\t\tINADDR_BROADCAST, vHOST_PORT, 0 );\r\n#endif\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPlayerInfo*\t\t\tManager::FirstPlayerInfo( Lst::Search< PlayerInfo > &sh, bool include_observers )\r\n{\r\n\tPlayerInfo* player;\r\n\r\n\tplayer = sh.FirstItem( m_players );\r\n\tif( !include_observers && player && player->IsObserving())\r\n\t{\r\n\t\tplayer = NextPlayerInfo( sh, include_observers );\r\n\t}\r\n\t\r\n\treturn player;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPlayerInfo*\t\t\tManager::NextPlayerInfo( Lst::Search< PlayerInfo > &sh, bool include_observers )\r\n{\r\n\tPlayerInfo* player;\r\n\r\n\tplayer = sh.NextItem();\r\n\tif( !include_observers && player && player->IsObserving())\r\n\t{\r\n\t\tplayer = NextPlayerInfo( sh, include_observers );\r\n\t}\r\n\t\r\n\treturn player;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNewPlayerInfo*\t\tManager::FirstNewPlayerInfo( Lst::Search< NewPlayerInfo > &sh )\r\n{\r\n\tNewPlayerInfo* player;\r\n\r\n\tplayer = sh.FirstItem( m_new_players );\r\n\t\r\n\treturn player;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNewPlayerInfo*\t\tManager::NextNewPlayerInfo( Lst::Search< NewPlayerInfo > &sh )\r\n{\r\n\tNewPlayerInfo* player;\r\n\r\n\tplayer = sh.NextItem();\r\n\t\r\n\treturn player;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNewPlayerInfo*\t\tManager::GetNewPlayerInfoByObjectID( unsigned short obj_id )\r\n{\r\n\tNewPlayerInfo* player;\r\n\tLst::Search< NewPlayerInfo > sh;\r\n\r\n\tfor( player = FirstNewPlayerInfo( sh ); player; player = NextNewPlayerInfo( sh ))\r\n\t{\r\n\t\tif( player->ObjID == obj_id )\r\n\t\t{\r\n\t\t\treturn player;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::DestroyNewPlayer( NewPlayerInfo* new_player )\r\n{\r\n\tLst::Node< NewPlayerInfo > *node;\r\n\tNewPlayerInfo* new_info;\r\n\r\n\tDbg_Assert( new_player );\r\n\tDbg_Printf( \"Destroying Pending Player %d\\n\", new_player->ObjID );\r\n\tfor( node = m_new_players.GetNext(); node; node = node->GetNext())\r\n\t{\r\n\t\tnew_info = node->GetData();\r\n\t\tif( new_info == new_player )\r\n\t\t{\r\n\t\t\tif( m_server )\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"Removing %s\\n\", new_info->Name );\r\n\t\t\t\tm_server->TerminateConnection( new_info->Conn );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"Removing %s\\n\", new_info->Name );\r\n\t\t\t\tif( new_info->Conn )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_client[0]->TerminateConnection( new_info->Conn );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tdelete node;\r\n\t\t\tdelete new_info;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPlayerInfo*\t\t\tManager::GetLocalPlayer( void )\r\n{\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\r\n\tfor( player = FirstPlayerInfo( sh, true ); player;\r\n\t\t\tplayer = NextPlayerInfo( sh, true ))\r\n\t{\r\n        if( player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\treturn player;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPlayerInfo*\t\t\tManager::GetServerPlayer( void )\r\n{\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\r\n\tfor( player = FirstPlayerInfo( sh, true ); player;\r\n\t\t\tplayer = NextPlayerInfo( sh, true ))\r\n\t{\r\n        if( player->IsServerPlayer())\r\n\t\t{\r\n\t\t\treturn player;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPlayerInfo*\t\t\tManager::GetKingOfTheHill( void )\r\n{\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\r\n\tfor( player = FirstPlayerInfo( sh, true ); player;\r\n\t\t\tplayer = NextPlayerInfo( sh, true ))\r\n\t{\r\n        if( player->IsKing())\r\n\t\t{\r\n\t\t\treturn player;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\t\t\t\tManager::GetNetworkLevelId( void )\r\n{\r\n\treturn m_level_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::DisconnectFromServer( void )\r\n{\r\n\tDbg_Message( \"Disconnecting from server\\n\" );\r\n    \r\n\tCleanupPlayers();\r\n\t\r\n\tClientShutdown();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::CleanupPlayers( void )\r\n{\r\n\tfree_all_players();\r\n\tfree_all_pending_players();\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::NumPartiallyLoadedPlayers( void )\r\n{\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tint num;\r\n\r\n\tnum = 0;\r\n\tfor( player = FirstPlayerInfo( sh ); player; player = NextPlayerInfo( sh ))\r\n\t{\r\n\t\tif( player->IsFullyIn() == false )\r\n\t\t{\r\n\t\t\tnum++;\r\n\t\t}\r\n\t}\r\n\r\n\treturn num;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::DropPartiallyLoadedPlayers( void )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tPlayerInfo* player, *next;\r\n\tLst::Search< PlayerInfo > sh;\r\n\r\n\tDbg_Printf( \"****** DROPPING PARTIALLY-LOADED SKATERS\\n\" );\r\n\tfor( player = FirstPlayerInfo( sh ); player; player = next )\r\n\t{\r\n\t\tnext = NextPlayerInfo( sh );\r\n\t\tif( player->IsFullyIn() == false )\r\n\t\t{\r\n\t\t\tObj::CSkater* quitting_skater;\r\n\t\t\t\t\t\t\r\n\t\t\tquitting_skater = player->m_Skater;\r\n\t\t\t\t\t\t\r\n\t\t\tDbg_Printf( \"****** DROPPING PLAYER %d\\n\", quitting_skater->GetID());\r\n\t\t\tDropPlayer( player, vREASON_LEFT_OUT );\r\n            skate_mod->remove_skater( quitting_skater );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::DropPlayer( PlayerInfo* info, DropReason reason )\r\n{\r\n\t\r\n\tchar player_name[vMAX_PLAYER_NAME_LEN + 1];\r\n\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tDbg_Assert( info );\r\n\tDbg_Message( \"Removing player %s from the game\\n\", info->m_Name );\r\n\r\n    strcpy( player_name, info->m_Name );\r\n\t\r\n\tif( !info->IsObserving())\r\n\t{\r\n\t\t// if we're playing a game of graffiti, then free up all of the trick objects accumulated by the dropped client\r\n\t\tif ( skate_mod->GetGameMode()->IsTrue( \"should_modulate_color\" ) )\r\n\t\t{\r\n\t\t\tskate_mod->GetTrickObjectManager()->FreeTrickObjects( info->m_Skater->GetID() );\r\n\t\t}\r\n\t}\r\n\r\n\tif( OnServer())\r\n\t{\r\n\t\tif( !info->IsObserving())\r\n\t\t{\r\n\t\t\t// Inform all others of the quitter's departure\r\n\t\t\tfor( player = FirstPlayerInfo( sh, true ); player;\r\n\t\t\t\t\tplayer = NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\tif( !player->IsLocalPlayer())\r\n\t\t\t\t{\r\n\t\t\t\t\tMsgPlayerQuit msg;\r\n\t\t\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\t\t\t\r\n\t\t\t\t\tmsg.m_ObjId = info->m_Skater->GetID();\r\n\t\t\t\t\tmsg.m_Reason = (char) reason;\r\n\t\t\t\r\n\t\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\t\tmsg_desc.m_Length = sizeof( MsgPlayerQuit );\r\n\t\t\t\t\tmsg_desc.m_Id = MSG_ID_PLAYER_QUIT;\r\n\t\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\t\tm_server->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n#ifdef __PLAT_NGPS__\r\n\t\t\tif( ( reason == vREASON_QUIT ) ||\r\n\t\t\t\t( reason == vREASON_TIMEOUT ) ||\r\n\t\t\t\t( reason == vREASON_BAD_CONNECTION ))\r\n\t\t\t{\r\n\t\t\t\tif( mpStatsMan->IsLoggedIn())\r\n\t\t\t\t{\r\n\t\t\t\t\tmpStatsMan->PlayerLeft( info->m_Skater->GetID());\r\n\t\t\t\t}\r\n\t\t\t}\r\n#endif\r\n\t\t}\r\n\r\n\t\tif(\t( reason == vREASON_BANNED ) ||\r\n\t\t\t( reason == vREASON_KICKED ))\r\n\t\t{\r\n\t\t\tm_server->SendMessageTo( MSG_ID_KICKED, 0, NULL,\r\n\t\t\t\t\t\t\t\t\t   info->m_Conn->GetIP(), info->m_Conn->GetPort(), 0 );\r\n\t\t\tif( reason == vREASON_BANNED )\r\n\t\t\t{\r\n\t\t\t\tm_server->BanConnection( info->m_Conn );\r\n\t\t\t}\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t//m_server->WaitForAsyncCallsToFinish();\r\n#endif // __PLAT_NGPS__\r\n\r\n\t\t}\r\n\t\telse if( reason == vREASON_LEFT_OUT )\r\n\t\t{\r\n\t\t\tm_server->SendMessageTo( MSG_ID_LEFT_OUT, 0, NULL,\r\n\t\t\t\t\t\t\t\t\t   info->m_Conn->GetIP(), info->m_Conn->GetPort(), 0 );\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t//m_server->WaitForAsyncCallsToFinish();\r\n#endif // __PLAT_NGPS__\r\n\t\t}\r\n\t\tif( reason != vREASON_OBSERVING )\r\n\t\t{\r\n\t\t\tif( info->m_Conn )\r\n\t\t\t{\r\n\t\t\t\tinfo->m_Conn->Invalidate();\r\n\t\t\t\t//Dbg_Printf( \"DestroyingAllMessageData 1\\n\" );\r\n\t\t\t\tinfo->m_Conn->DestroyAllMessageData();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tuint32 reason_checksum;\r\n\t\t\r\n\t\tswitch( reason )\r\n\t\t{\r\n\t\t\tcase vREASON_QUIT:\r\n\t\t\t{\r\n\t\t\t\treason_checksum = Script::GenerateCRC(\"net_message_player_quit\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase vREASON_TIMEOUT:\r\n\t\t\t{\r\n\t\t\t\treason_checksum = Script::GenerateCRC(\"net_message_player_timed_out\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase vREASON_OBSERVING:\r\n\t\t\t{\r\n\t\t\t\treason_checksum = Script::GenerateCRC(\"net_message_player_now_observing\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase vREASON_BANNED:\r\n\t\t\t{\r\n\t\t\t\treason_checksum = Script::GenerateCRC(\"net_message_player_banned\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase vREASON_KICKED:\r\n\t\t\t{\r\n\t\t\t\treason_checksum = Script::GenerateCRC(\"net_message_player_kicked\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase vREASON_LEFT_OUT:\r\n\t\t\t{\r\n\t\t\t\treason_checksum = Script::GenerateCRC(\"net_message_player_left_out\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase vREASON_BAD_CONNECTION:\r\n\t\t\t{\r\n\t\t\t\treason_checksum = Script::GenerateCRC(\"net_message_player_dropped\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:\r\n\t\t\t\treason_checksum = Script::GenerateCRC(\"net_message_player_timed_out\");\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// If the info is about the server player, no need to print a panel message.\r\n\t\t// Currently this would only happen if the server decided to sit out\r\n\t\tif( info->IsLocalPlayer() == false )\r\n\t\t{\t   \r\n\t\t\tCreateNetPanelMessage( true, reason_checksum, player_name );\r\n\t\t}\r\n\t\tif( reason == vREASON_OBSERVING )\r\n\t\t{\r\n\t\t\tif( info->IsKing())\r\n\t\t\t{\r\n\t\t\t\tif( m_crown )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_crown->RemoveFromKing();\r\n\t\t\t\t}\r\n\t\t\t\tinfo->MarkAsKing( false );\r\n\t\t\t}\r\n\t\t\tif( info->HasCTFFlag())\r\n\t\t\t{\r\n\t\t\t\tchar team_str[64];\r\n\t\t\t\tint team;\r\n\t\t\t\tScript::CStruct* pParams;\r\n\t\t\t\tPlayerInfo* local_player;\r\n\t\t\t\t\r\n\t\t\t\tteam = info->HasWhichFlag();\r\n\t\t\t\tsprintf( team_str, \"team_%d_name\", team + 1 );\r\n\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\r\n\t\t\t\tpParams->AddInteger( \"team\", team );\r\n\t\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\t\t\tScript::RunScript( \"flag_returned\", pParams );\r\n\t\t\r\n\t\t\t\tdelete pParams;\r\n\t\t\r\n\t\t\t\tlocal_player = GetLocalPlayer();\r\n\t\t\t\tif( local_player && !local_player->IsObserving())\r\n\t\t\t\t{\r\n\t\t\t\t\tif( local_player->m_Team == team )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tScript::RunScript( \"hide_ctf_arrow\" );\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tinfo->ClearCTFState();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbool is_server_player;\r\n\t\t\t\r\n\t\t\tis_server_player = info->IsServerPlayer();\r\n\t\t\t\r\n\t\t\tDbg_Printf( \"Destroying Player %s\\n\", info->m_Name );\r\n\t\t\tDestroyPlayer( info );\r\n\t\t\tif( is_server_player )\r\n\t\t\t{\r\n\t\t\t\tChooseNewServerPlayer();\r\n\t\t\t\tif( GetServerPlayer() == NULL )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( ( skate_mod->GetGameMode()->GetNameChecksum() != Script::GenerateCRC( \"netlobby\" )))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tScript::RunScript( \"network_end_game_selected\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Now see if the leaving of this player satisfies ending conditions\r\n\t\tbool all_done = true;\r\n\t\tfor( player = FirstPlayerInfo( sh ); player;\r\n\t\t\t\tplayer = NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tif( !player->m_flags.TestMask( PlayerInfo::mRUN_ENDED))\r\n\t\t\t{\r\n\t\t\t\tall_done = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t\tif( all_done )\r\n\t\t{\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\tmsg_desc.m_Id = MSG_ID_GAME_OVER;\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\tfor( player = FirstPlayerInfo( sh, true ); player;\r\n\t\t\t\t\tplayer = NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\tm_server->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDestroyPlayer( info );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPrefs::Preferences* Manager::GetNetworkPreferences( void )\r\n{\r\n\treturn &m_network_preferences;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPrefs::Preferences* Manager::GetTauntPreferences( void )\r\n{\r\n\treturn &m_taunt_preferences;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char*\t\t\tManager::GetNameFromArrayEntry( char* array_name, uint32 checksum )\r\n{\r\n\tScript::CArray* pArray;\r\n\tconst char* string = NULL;\r\n\tint i;\r\n\r\n\tpArray = Script::GetArray( array_name );\r\n\tDbg_Assert( pArray );\r\n\r\n\tfor( i = 0; i < (int)pArray->GetSize(); i++ )\r\n\t{   \r\n\t\tuint32 value;\r\n\t\tScript::CStruct* pStructure;\r\n\t\t\r\n\t\t \r\n\t\tpStructure = pArray->GetStructure( i );\r\n\t\tDbg_Assert( pStructure );\r\n\t\t\r\n\t\tpStructure->GetChecksum( \"checksum\", &value, true );\r\n\t\tif( value == checksum )\r\n\t\t{\r\n\t\t\tpStructure->GetText( \"name\", &string, true );\r\n\t\t}\r\n\t}\r\n\r\n\treturn string;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\t\tManager::GetIntFromArrayEntry( char* array_name, uint32 checksum, uint32 field_checksum )\r\n{\r\n\tScript::CArray* pArray;\r\n\tint int_val;\r\n\tint i;\r\n\r\n\tpArray = Script::GetArray( array_name );\r\n\tDbg_Assert( pArray );\r\n\r\n\tint_val = 0;\r\n\tfor( i = 0; i < (int)pArray->GetSize(); i++ )\r\n\t{   \r\n\t\tuint32 value;\r\n\t\tScript::CStruct* pStructure;\r\n\t\t\r\n\t\t \r\n\t\tpStructure = pArray->GetStructure( i );\r\n\t\tDbg_Assert( pStructure );\r\n\t\t\r\n\t\tpStructure->GetChecksum( \"checksum\", &value, true );\r\n\t\tif( value == checksum )\r\n\t\t{\r\n\t\t\tpStructure->GetInteger( field_checksum, &int_val, true );\r\n\t\t}\r\n\t}\r\n\r\n\treturn int_val;\r\n}\r\n\r\n/******************************************************************/\r\n/* Make use of the network preferences we currently have stored\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::UsePreferences( void )\r\n{\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\tPrefs::Preferences* pPreferences;\r\n\tScript::CStruct* pStructure;\r\n\tScript::CArray* pArray;\r\n\tconst char* ip, *phone, *login, *password, *host, *domain;\r\n\tuint32 dev_type, ip_assignment, checksum;\r\n\tbool use_dhcp, use_authentication, use_pcmcia_card;\r\n\tint i;\r\n\r\n\t// Initialize the master server list\r\n\tfor( i = 0; i < vMAX_MASTER_SERVERS; i++ )\r\n\t{\r\n\t\tm_master_servers[i][0] = '\\0';\r\n\t}\r\n\r\n\tpPreferences = GetNetworkPreferences();\r\n\r\n\tpArray = Script::GetArray(\"default_master_servers\");\r\n\tDbg_Assert( pArray );\r\n\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"use_default_master_servers\"));\r\n\tpStructure->GetChecksum( \"Checksum\", &checksum, true );\r\n\tif( checksum == Script::GenerateCRC( \"boolean_true\" ))\r\n\t{\r\n\t\tfor( i = 0; i < (int)pArray->GetSize(); i++ )\r\n\t\t{   \r\n\t\t\tScript::CStruct* pStructure = pArray->GetStructure( i );\r\n\t\t\tDbg_Assert( pStructure );\r\n            \r\n\t\t\tpStructure->GetText( \"name\", &ip, true );\r\n\t\t\tstrcpy( m_master_servers[ i ], ip );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint num_servers;\r\n\r\n\t\tnum_servers = 0;\r\n\r\n\t\t// First, add the manually-entered master servers to the list, if they're not\r\n\t\t// 0.0.0.0\r\n\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"master_server1\") );\r\n\t\tpStructure->GetText( \"ui_string\", &ip, true );\r\n\t\tif( strcmp( ip, \"0.0.0.0\" ))\r\n\t\t{\r\n\t\t\tstrcpy( m_master_servers[ num_servers ], ip );\r\n\t\t\tnum_servers++;\r\n\t\t}\r\n\t\t\t\t\r\n\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"master_server2\") );\r\n\t\tpStructure->GetText( \"ui_string\", &ip, true );\r\n\t\tif( strcmp( ip, \"0.0.0.0\" ))\r\n\t\t{\r\n\t\t\tstrcpy( m_master_servers[ num_servers ], ip );\r\n\t\t\tnum_servers++;\r\n\t\t}\r\n\r\n\t\t// Now tack on our default servers, just in case\r\n\t\tfor( i = 0; i < (int)pArray->GetSize(); i++ )\r\n\t\t{   \r\n\t\t\tScript::CStruct* pStructure = pArray->GetStructure( i );\r\n\t\t\tDbg_Assert( pStructure );\r\n            \r\n\t\t\tpStructure->GetText( \"name\", &ip, true );\r\n\t\t\tstrcpy( m_master_servers[ num_servers + i ], ip );\r\n\t\t}\r\n\t}\r\n\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"broadband_type\") );\r\n\tpStructure->GetChecksum( \"Checksum\", &ip_assignment, true );\r\n\tuse_dhcp = false;\r\n\tif( ip_assignment == Script::GenerateCRC( \"ip_dhcp\" ))\r\n\t{\r\n\t\tDbg_Printf( \"************* Supposed to use DHCP here !! ***************\\n\" );\r\n\t\tuse_dhcp = true;\r\n\t}\r\n\r\n\t// Override IP settings with the viewer_ip script variable, used to launch a server for real-time communication\r\n#ifdef __PLAT_XBOX__\r\n\tconst char* viewer_ip = Script::GetString( \"xbox_viewer_ip\" );\r\n#endif\r\n#ifdef __PLAT_NGPS__\r\n\tconst char* viewer_ip = Script::GetString( \"viewer_ip\" );\r\n#endif\r\n#ifdef __PLAT_NGC__\r\n\tconst char* viewer_ip = Script::GetString( \"ngc_viewer_ip\" );\r\n#endif\r\n\tconst char* viewer_gateway = Script::GetString( \"viewer_gateway\" );\r\n\tif( viewer_ip && !*viewer_ip )\r\n\t{\r\n\t\tviewer_ip = NULL;\r\n\t}\r\n\tif( viewer_ip )\r\n\t{\r\n\t\tDbg_Printf( \"************* Got a viewer IP !! ***************\\n\" );\r\n\t\tPrefs::Preferences* prefs;\r\n        Script::CScriptStructure* pTempStructure;\r\n\r\n\t\tuse_dhcp = false;\r\n\r\n        pTempStructure = new Script::CScriptStructure;\r\n\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \r\n\t\t\t\t\t\t\t\t  viewer_ip );\r\n        prefs = GetNetworkPreferences();\r\n\t\tprefs->SetPreference( Script::GenerateCRC(\"ip_address\"), pTempStructure );\r\n\t\tdelete pTempStructure;\r\n\r\n\t\tif( viewer_gateway && *viewer_gateway )\r\n\t\t{\r\n\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \r\n\t\t\t\t\t\t\t\t\t  viewer_gateway );\r\n\t\t\tprefs = GetNetworkPreferences();\r\n\t\t\tprefs->SetPreference( Script::GenerateCRC(\"gateway\"), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tnet_man->SetDHCP( use_dhcp );\r\n\r\n    if( use_dhcp )\r\n\t{\r\n\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"host_name\") );\r\n\t\tpStructure->GetText( \"ui_string\", &host, true );\r\n\t\tnet_man->SetHostName((char*) host );\r\n\r\n\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"domain_name\") );\r\n\t\tpStructure->GetText( \"ui_string\", &domain, true );\r\n\t\tnet_man->SetDomainName((char*) domain );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"ip_address\") );\r\n\t\tpStructure->GetText( \"ui_string\", &ip, true );\r\n\t\tDbg_Printf( \"****************** Setting Local IP to %s ********** \\n\", ip );\r\n\t\tnet_man->SetLocalIP((char*) ip );\r\n        \r\n\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"gateway\") );\r\n\t\tpStructure->GetText( \"ui_string\", &ip, true );\r\n\t\tDbg_Printf( \"****************** Setting Gateway to %s ********** \\n\", ip );\r\n\t\tnet_man->SetGateway((char*) ip );\r\n\r\n\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"subnet_mask\") );\r\n\t\tpStructure->GetText( \"ui_string\", &ip, true );\r\n\t\tDbg_Printf( \"****************** Setting Subnet to %s ********** \\n\", ip );\r\n\t\tnet_man->SetSubnetMask((char*) ip );\r\n\t}\r\n\r\n#ifdef USE_DNS\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"auto_dns\") );\r\n\tpStructure->GetChecksum( \"Checksum\", &checksum, true );\r\n\tif( checksum == Script::GenerateCRC( \"boolean_true\" ) && ( viewer_ip == NULL ))\r\n\t{\r\n\t\tDbg_Printf( \"****************** Setting DNS to 0.0.0.0 ******** \\n\" );\r\n\t\tnet_man->SetDNSServer( 0, \"\" );\r\n\t\tnet_man->SetDNSServer( 1, \"\" );\r\n\t\tnet_man->SetDNSServer( 2, \"\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( viewer_ip )\r\n\t\t{\r\n\t\t\tnet_man->SetDNSServer( 0, \"205.147.0.100\" );\r\n\t\t\tnet_man->SetDNSServer( 1, \"205.147.0.102\" );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"dns_server\") );\r\n\t\t\tpStructure->GetText( \"ui_string\", &ip, true );\r\n\t\t\tDbg_Printf( \"****************** Setting DNS 1 to %s ******** \\n\", ip );\r\n\t\t\tnet_man->SetDNSServer( 0, (char*) ip );\r\n\t\t\r\n\t\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"dns_server2\") );\r\n\t\t\tpStructure->GetText( \"ui_string\", &ip, true );\r\n\t\t\tDbg_Printf( \"****************** Setting DNS 2 to %s ******** \\n\", ip );\r\n\t\t\tnet_man->SetDNSServer( 1, (char*) ip );\r\n\t\t}\r\n\t}\r\n#else\r\n#ifdef USE_FREE_DNS\r\n\tnet_man->SetDNSServer( 0, \"204.80.125.130\" );\t// Free DNS server in LA\r\n\tnet_man->SetDNSServer( 1, \"204.57.55.100\" );\t// Free DNS server in Boston\r\n\tnet_man->SetDNSServer( 2, \"\" );\r\n#else\r\n\tnet_man->SetDNSServer( 0, \"\" );\t// Free DNS server in LA\r\n\tnet_man->SetDNSServer( 1, \"\" );\t// Free DNS server in Boston\r\n\tnet_man->SetDNSServer( 2, \"\" );\r\n#endif // USE_FREE_DNS\r\n#endif // USE_DNS\r\n\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"dialup_number\") );\r\n\tpStructure->GetText( \"ui_string\", &phone, true );\r\n\tnet_man->SetISPPhoneNumber((char*) phone );\r\n\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"dialup_username\") );\r\n\tpStructure->GetText( \"ui_string\", &login, true );\r\n\tnet_man->SetISPLogin((char*) login );\r\n\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"dialup_password\") );\r\n\tpStructure->GetText( \"ui_string\", &password, true );\r\n\tnet_man->SetISPPassword((char*) password );\r\n\t\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"device_type\") );\r\n\tpStructure->GetChecksum( \"Checksum\", &dev_type, true );\r\n\tconst char* use_pcmcia = Script::GetString( \"use_pcmcia\" );\r\n\tuse_pcmcia_card = use_pcmcia[0] != '\\0';\r\n\t\r\n\tif(( dev_type == Script::GenerateCRC( \"device_broadband_pc\" )) || use_pcmcia_card ) \r\n\t{\r\n\t\tif( viewer_ip )\r\n\t\t{\r\n\t\t\tScript::RunScript( \"spoof_pcmcia_adaptor_setup\" );\r\n\t\t}\r\n\t\tnet_man->SetDeviceType( Net::vDEV_TYPE_PC_ETHERNET );\r\n\t\tnet_man->SetConnectionType( Net::vCONN_TYPE_ETHERNET );\r\n\t}\r\n\telse if(( dev_type == Script::GenerateCRC( \"device_broadband_usb\" )) || ( viewer_ip ))\r\n\t{\r\n\t\tif( viewer_ip )\r\n\t\t{\r\n\t\t\tScript::RunScript( \"spoof_usb_adaptor_setup\" );\r\n\t\t}\r\n\t\tnet_man->SetDeviceType( Net::vDEV_TYPE_USB_ETHERNET );\r\n\t\tnet_man->SetConnectionType( Net::vCONN_TYPE_ETHERNET );\r\n\t}\r\n\telse if( dev_type == Script::GenerateCRC( \"device_broadband_usb_pppoe\" ))\r\n\t{\r\n\t\tnet_man->SetDeviceType( Net::vDEV_TYPE_USB_ETHERNET );\r\n\t\tnet_man->SetConnectionType( Net::vCONN_TYPE_PPPOE );\r\n\t}\r\n\telse if( dev_type == Script::GenerateCRC( \"device_usb_modem\" ))\r\n\t{\r\n\t\tnet_man->SetDeviceType( Net::vDEV_TYPE_USB_MODEM );\r\n\t\tnet_man->SetConnectionType( Net::vCONN_TYPE_MODEM );\r\n\t\tif( GetMaxPlayers() > 3 )\r\n\t\t{\r\n\t\t\tSetMaxPlayers( 3 );\r\n\t\t}\r\n\t\tSetMaxObservers( 0 );\r\n\t}\r\n\telse if( dev_type == Script::GenerateCRC( \"device_sony_modem\" ))\r\n\t{\r\n\t\tnet_man->SetDeviceType( Net::vDEV_TYPE_SONY_MODEM );\r\n\t\tnet_man->SetConnectionType( Net::vCONN_TYPE_MODEM );\r\n\t\tif( GetMaxPlayers() > 3 )\r\n\t\t{\r\n\t\t\tSetMaxPlayers( 3 );\r\n\t\t}\r\n\t\tSetMaxObservers( 0 );\r\n\t}\r\n\telse if( dev_type == Script::GenerateCRC( \"device_broadband_pc_pppoe\" ))\r\n\t{\r\n\t\tnet_man->SetDeviceType( Net::vDEV_TYPE_PC_ETHERNET );\r\n\t\tnet_man->SetConnectionType( Net::vCONN_TYPE_PPPOE );\r\n\t}\r\n\telse\r\n\t{   \r\n\t\tnet_man->SetConnectionType( Net::vCONN_TYPE_NONE );\r\n\t\tnet_man->SetDeviceType( Net::vDEV_TYPE_NONE );\r\n\t}\r\n\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"dialup_authentication\") );\r\n\tpStructure->GetChecksum( \"Checksum\", &checksum, true );\r\n\tuse_authentication = false;\r\n\tif( checksum == Script::GenerateCRC( \"boolean_true\" ))\r\n\t{\r\n\t\tuse_authentication = true;\r\n\t}\r\n\tnet_man->SetDialupAuthentication( use_authentication );\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::RandomizeSkaterStartingPoints( void )\r\n{\r\n\tint i, j, offset, max_skaters;\r\n\r\n\t// choose a random offset for these starting points\r\n\toffset = Mth::Rnd( 256 );\r\n\r\n\tif( InNetGame())\r\n\t{\r\n\t\tmax_skaters = Mdl::Skate::vMAX_SKATERS;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tmax_skaters = skate_mod->GetGameMode()->GetMaximumNumberOfPlayers();\r\n\t\t\r\n\t\t// PATCH  (Mick)\r\n\t\t// If playing a splitscreen game in the park editor\r\n\t\t// then set the Maximum number of players to 2\r\n\t\t// so we only use the 1P and 2P start points\r\n\t\t// oterwise, we will use all the auto-horse points\r\n\t\t// which end up in stupid positions\r\n\t\tif (Ed::CParkEditor::Instance()->UsingCustomPark() && !skate_mod->GetGameMode()->IsTrue(\"is_horse\")) \t\t// is it a custom park and not horse mode?\r\n\t\t{\r\n\t\t\tmax_skaters = 2;\r\n\t\t\toffset = 0;\t   // reset the offset, so they always get used the same way\r\n\t\t}\r\n\t\t\r\n\t\t\r\n\t}\r\n\r\n\tfor( i = 0; i < max_skaters; i++ )\r\n\t{\r\n\t\tm_skater_starting_points[i] = -1;\r\n\t}\r\n\r\n\t// For each skater, choose a random starting point\r\n\tfor( i = 0; i < max_skaters; i++ )\r\n\t{\r\n\t\tbool unique;\r\n        \r\n\t\t// Choose a random starting point until it's unique\r\n\t\tdo\r\n\t\t{\r\n\t\t\tm_skater_starting_points[i] = Mth::Rnd( max_skaters );\r\n\t\t\tunique = true;\r\n\t\t\tfor( j = 0; j < max_skaters; j++ )\r\n\t\t\t{\r\n\t\t\t\t// skip myself\r\n\t\t\t\tif( i == j )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( m_skater_starting_points[i] == m_skater_starting_points[j] )\r\n\t\t\t\t{\r\n\t\t\t\t\tunique = false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} while( !unique );\r\n\t}\r\n\r\n\t// Offset these random sequential numbers by a random number so that we pick\r\n\t// four sequential numbers within a possibly larger range of starting points\r\n\tfor( i = 0; i < max_skaters; i++ )\r\n\t{\r\n\t\tm_skater_starting_points[i] += offset;\r\n\t}\r\n\r\n\tm_crown_spawn_point = Mth::Rnd( vNUM_CROWN_SPAWN_POINTS );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetSkaterStartingPoints( int* start_points )\r\n{\r\n\tint i;\r\n\r\n\tfor( i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tm_skater_starting_points[i] = start_points[i];\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::GetSkaterStartingPoint( int skater_id )\r\n{\r\n\treturn m_skater_starting_points[skater_id];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::LoadPendingPlayers( void )\r\n{\r\n\tPlayerInfo* player, *next;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tint num_new_players;\r\n\r\n\tDbg_Assert( m_server );\r\n\r\n\tnum_new_players = 0;\r\n\r\n#ifdef __PLAT_XBOX__\r\n\t// Since XBOX has a quicker timeout, we need to tell clients that this process (loading pending players) may take much longer\r\n\t// than the timeout allows. Clients will allow the server N seconds to get back to them after receiving this message.\r\n\t// NOTE: This will only be guaranteed to work in LAN mode, because if the packet is lost, the original timeout will stand\r\n\tbool players_pending;\r\n\r\n\tplayers_pending = false;\r\n\t// Add all pending players to the game\r\n\tfor( player = FirstPlayerInfo( sh, true ); player; player = NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( player->IsPendingPlayer())\r\n\t\t{\r\n\t\t\tplayers_pending = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif( players_pending )\r\n\t{\r\n\t\tNet::MsgDesc msg_desc;\r\n\t\tfor( player = FirstPlayerInfo( sh, true ); player; player = NextPlayerInfo( sh, true ))\r\n\t\t{\r\n\t\t\tif( !player->IsLocalPlayer())\r\n\t\t\t{\r\n\t\t\t\tchar num_seconds;\r\n\r\n\t\t\t\tnum_seconds = 15;\r\n\r\n\t\t\t\tmsg_desc.m_Data = &num_seconds;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( char );\r\n\t\t\t\tmsg_desc.m_Id = MSG_ID_WAIT_N_SECONDS;\r\n\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\tm_server->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t}\r\n\t\t}\t\t\r\n\t\tm_server->SendData();\r\n\t}\r\n\t\r\n#endif\t\r\n\r\n\t// Add all pending players to the game\r\n\tfor( player = FirstPlayerInfo( sh, true ); player; player = next )\r\n\t{\r\n\t\tnext = NextPlayerInfo( sh, true );\r\n\t\tif( player->m_flags.TestMask( PlayerInfo::mPENDING_PLAYER ))\r\n\t\t{\r\n\t\t\tNewPlayerInfo new_player;\r\n\r\n\t\t\tDbg_Assert( player->IsObserving());\r\n\r\n\t\t\tnum_new_players++;\r\n\r\n\t\t\tstrcpy( new_player.Name, player->m_Name );\r\n\t\t\tnew_player.ObjID = GetNextPlayerObjectId();\r\n\t\t\tnew_player.Conn = player->m_Conn;\r\n\t\t\tnew_player.Flags = PlayerInfo::mJUMPING_IN;\r\n\t\t\tnew_player.Profile = player->m_Profile;\r\n\t\t\tnew_player.Rating = player->m_Rating;\r\n\t\t\tnew_player.VehicleControlType = player->m_VehicleControlType;\r\n\t\t\t\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\t\t\t*new_player.mpSkaterProfile = *player->mp_SkaterProfile;\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n            \r\n\t\t\tDestroyPlayer( player );\r\n\r\n\t\t\tDeferredNewPlayer( &new_player, ( num_new_players + 1 ) * vDEFERRED_JOIN_FRAMES );\r\n\r\n\t\t}\r\n\t}\r\n\r\n\t// Invalidate old positions. Player will be re-added to the world when we get a\r\n\t// sufficient number of object updates\r\n\tfor( player = FirstPlayerInfo( sh ); player; player = NextPlayerInfo( sh ))\r\n\t{\r\n\t\tif( player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tplayer->m_Skater->RemoveFromCurrentWorld();\r\n\t\tplayer->m_Skater->Resync();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::StartNetworkLobby( void )\r\n{\r\n\tint num_teams;\t\r\n\r\n\t// This version of \"StartNetworkLobby\"\r\n\t// exits the game mode, and enters the lobby\r\n\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n    \r\n\tif( OnServer())\r\n\t{\r\n\t\tm_level_id = GetLevelFromPreferences();\r\n\t\tnum_teams = GetNumTeams();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tnum_teams = skate_mod->GetGameMode()->NumTeams();\r\n\t}\r\n\r\n\t// set the game type for the server\r\n\tm_gamemode_id = Script::GenerateCRC( \"netlobby\" );\r\n\tskate_mod->GetGameMode()->LoadGameType( m_gamemode_id );\r\n\tskate_mod->GetGameMode()->SetNumTeams( num_teams );\r\n\r\n\tm_game_over = false;\r\n\r\n    // launches the game for this client\r\n\t// (should really wait until the clients are ready)\r\n\t\r\n\t//Mdl::ScriptRetry( NULL, NULL );\r\n\r\n\tResetPlayers();\r\n\r\n\tDbg_Printf( \"Starting network lobby\\n\" );\r\n\t\r\n\t// Clear the king of the hill\r\n\tif(( player = GetKingOfTheHill()))\r\n\t{\r\n\t\tplayer->MarkAsKing( false );\r\n\t}\r\n\r\n\tfor( player = FirstPlayerInfo( sh, true ); player; player = NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tplayer->ClearCTFState();\r\n\t}\r\n\r\n\tClearTriggerEventList();\r\n\r\n\tm_lobby_start_time = Tmr::GetTime();\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ShouldStopAtZero( void )\r\n{\r\n\tuint32 should_stop;\r\n\r\n\tif( ( m_gamemode_id == Script::GenerateCRC( \"netgoalattack\" )) ||\r\n\t\t( m_gamemode_id == Script::GenerateCRC( \"king\" )) ||\r\n\t\t( m_gamemode_id == Script::GenerateCRC( \"netking\" )) ||\r\n\t\t( m_gamemode_id == Script::GenerateCRC( \"netscorechallenge\" )) ||\r\n\t\t( m_gamemode_id == Script::GenerateCRC( \"scorechallenge\" )))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif( InNetGame() == false )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif( m_gamemode_id == Script::GenerateCRC( \"netctf\" ))\r\n\t{\r\n\t\tuint32 mode;\r\n\r\n\t\tmode = GetNetworkPreferences()->GetPreferenceChecksum( Script::GenerateCRC(\"ctf_game_type\"), Script::GenerateCRC(\"checksum\") );\r\n\t\tif( mode != CRCD(0x938ab24b,\"timed_ctf\"))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tshould_stop = GetNetworkPreferences()->GetPreferenceChecksum( Script::GenerateCRC(\"stop_at_zero\"), Script::GenerateCRC(\"checksum\") );\r\n\tif( should_stop == CRCD(0xf81bc89b,\"boolean_true\"))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::StartNetworkGame( void )\r\n{\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tint time_limit;\r\n\tPrefs::Preferences* pPreferences;\r\n\tNet::MsgDesc msg_desc;\r\n\r\n\tDbg_MsgAssert( OnServer(),( \"Server-only function called on client\" ));\r\n\r\n\tpPreferences = NULL;\r\n\tif( InNetGame())\r\n\t{\r\n\t\tpPreferences = GetNetworkPreferences();\r\n\t}\r\n\telse \r\n\t{\r\n\t\tpPreferences = skate_mod->GetSplitScreenPreferences();\r\n\t}\r\n\r\n\t\r\n\r\n\tNet::Server* server;\r\n\tserver = GetServer();\r\n\tDbg_MsgAssert( server,( \"Server has not been started\\n\" ));\r\n\r\n\t// Sorry boys, you didn't quite make it in\r\n\tfree_all_pending_players();\r\n\r\n\t// set the game type for the server, from the network preferences\r\n\tm_gamemode_id = GetGameTypeFromPreferences();\r\n\t//skate_mod->GetGameMode()->LoadGameType( m_gamemode_id );\r\n\r\n\t// Mick: Moved this to after the setting of the game type, so we can check for horse mode in it\r\n\t// (used to explicitly set 1P and 2P start points in 2P split screen (not horse) game)\r\n\tRandomizeSkaterStartingPoints();\r\n\r\n\r\n\tif( m_gamemode_id == Script::GenerateCRC( \"horse\" ))\r\n\t{\r\n\t\ttime_limit = pPreferences->GetPreferenceValue( Script::GenerateCRC(\"horse_time_limit\"), Script::GenerateCRC(\"time\") );\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttime_limit = pPreferences->GetPreferenceValue( Script::GenerateCRC(\"time_limit\"), Script::GenerateCRC(\"time\") );\r\n\t}\r\n\r\n\tDbg_Printf(\"Starting network game of type %s with time limit %d\\n\", Script::FindChecksumName(m_gamemode_id), time_limit);\r\n\tm_level_id = GetLevelFromPreferences();\r\n\t\r\n\tMsgGameInfo game_info_msg;\r\n\tgame_info_msg.m_GameMode = m_gamemode_id;\r\n\tgame_info_msg.m_FireballLevel = GetFireballLevelFromPreferences();\r\n\tDbg_Printf( \"***** FIREBALL LEVEL: %d\\n\", game_info_msg.m_FireballLevel );\r\n\tif( ( m_gamemode_id == CRCD(0xec200eaa,\"netgoalattack\")) ||\r\n\t\t( m_gamemode_id == CRCD(0x5d32129c,\"king\")) ||\r\n\t\t( m_gamemode_id == CRCD(0x6ef8fda0,\"netking\")) ||\r\n\t\t( m_gamemode_id == CRCD(0x1498240a,\"netscorechallenge\")) ||\r\n\t\t( m_gamemode_id == CRCD(0xf135ecb6,\"scorechallenge\")) ||\r\n\t\t( m_gamemode_id == CRCD(0x3d6d444f,\"firefight\")) ||\r\n\t\t( m_gamemode_id == CRCD(0xbff33600,\"netfirefight\")))\r\n\t{\r\n\t\tgame_info_msg.m_TimeLimit = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\r\n\t\tif( m_gamemode_id == Script::GenerateCRC( \"netctf\" ))\r\n\t\t{\r\n\t\t\tuint32 mode;\r\n\r\n            mode = pPreferences->GetPreferenceChecksum( Script::GenerateCRC(\"ctf_game_type\"), Script::GenerateCRC(\"checksum\") );\r\n\t\t\tif( mode == CRCD(0x938ab24b,\"timed_ctf\"))\r\n\t\t\t{\r\n\t\t\t\tgame_info_msg.m_TimeLimit = time_limit;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tgame_info_msg.m_TimeLimit = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tgame_info_msg.m_TimeLimit = time_limit;\r\n\t\t}\r\n\t}\r\n\t\r\n\tgame_info_msg.m_StopAtZero = (char) ShouldStopAtZero();\r\n\tgame_info_msg.m_TargetScore = pPreferences->GetPreferenceValue( Script::GenerateCRC(\"target_score\"), Script::GenerateCRC(\"score\") );\r\n\tDbg_Printf( \"Target score %d\\n\", (int)game_info_msg.m_TargetScore );\r\n\tgame_info_msg.m_TeamMode = GetNumTeams();\r\n\r\n\t// Here, make sure we get a game id that does not match our last game id\r\n\tdo\r\n\t{\r\n\t\tgame_info_msg.m_GameId = 1 + (unsigned char) Mth::Rnd( 255 );\r\n\t} while( game_info_msg.m_GameId == m_last_end_of_run_game_id );\r\n\r\n\tgame_info_msg.m_CrownSpawnPoint = m_crown_spawn_point;\r\n\tmemcpy( game_info_msg.m_StartPoints, m_skater_starting_points, Mdl::Skate::vMAX_SKATERS * sizeof( int ));\r\n\r\n\tmsg_desc.m_Data = &game_info_msg;\r\n\tmsg_desc.m_Length = sizeof( MsgGameInfo );\r\n\tmsg_desc.m_Id = MSG_ID_GAME_INFO;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tfor( player = FirstPlayerInfo( sh, true ); player; player = NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tplayer->m_BestCombo = 0;\r\n\t\tplayer->ClearCTFState();\r\n\t\tplayer->m_flags.ClearMask( PlayerInfo::mRESTARTING );\r\n\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\r\n\t\t// In splitscreen games, just send it to the first client\r\n\t\tif( InNetGame() == false )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// Clear the king of the hill\r\n\tif(( player = GetKingOfTheHill()))\r\n\t{\r\n\t\tplayer->MarkAsKing( false );\r\n\t}\r\n\tSetCurrentLeader( NULL );\r\n\tSetCurrentLeadingTeam( vNO_TEAM );\r\n\tClearTriggerEventList();\r\n\tResetPlayers();\r\n\tg_CheatsEnabled = false;\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tif( mpStatsMan->IsLoggedIn())\r\n\t{\r\n\t\tmpStatsMan->StartNewGame();\r\n\t}\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::ResetPlayers( void )\r\n{\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\r\n\tfor( player = FirstPlayerInfo( sh, true ); player;\r\n\t\t\tplayer = NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tMdl::Score* score;\r\n\t\tplayer->m_flags.ClearMask( PlayerInfo::mRUN_ENDED );\r\n\t\tif( player->m_Skater )\r\n\t\t{\r\n\t\t\tObj::CSkaterScoreComponent* p_skater_score_component = GetSkaterScoreComponentFromObject(player->m_Skater);\r\n\t\t\tDbg_Assert(p_skater_score_component);\r\n\t\t\tscore = p_skater_score_component->GetScore();\r\n\t\t\t\r\n\t\t\tif( score )\r\n\t\t\t{\r\n\t\t\t\tscore->Reset();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::SetLevel( uint32 level_id )\r\n{\r\n\tm_level_id = level_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetNetworkGameId( unsigned char id )\r\n{\r\n\tm_game_id = id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nunsigned char\tManager::GetNetworkGameId( void )\r\n{\r\n\treturn m_game_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 Manager::GetGameTypeFromPreferences( void )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tPrefs::Preferences* pPreferences;\r\n\t \r\n\tpPreferences = NULL;\r\n\tif( InNetGame())\r\n\t{\r\n\t\tpPreferences = GetNetworkPreferences();\r\n\t}\r\n\telse \r\n\t{\r\n\t\tpPreferences = skate_mod->GetSplitScreenPreferences();\r\n\t}\r\n\r\n\tScript::CStruct* pStructure = pPreferences->GetPreference( Script::GenerateCRC(\"game_type\") );\r\n\r\n\tDbg_Assert( pStructure );\r\n\r\n\tuint32 gametype_id;\r\n\tpStructure->GetChecksum( \"checksum\", &gametype_id, true );\r\n\r\n\treturn gametype_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 Manager::GetLevelFromPreferences( void )\r\n{\r\n\tuint32 level_id;\r\n\r\n\tPrefs::Preferences* pPreferences;\r\n\r\n\tpPreferences = GetNetworkPreferences();\r\n\tScript::CStruct* pStructure = pPreferences->GetPreference( Script::GenerateCRC(\"level\") );\r\n\r\n\tDbg_Assert( pStructure );\r\n    pStructure->GetChecksum( \"checksum\", &level_id, true );\r\n\t\r\n\treturn level_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::GetFireballLevelFromPreferences( void )\r\n{\r\n\tuint32 checksum;\r\n\tScript::CStruct* pStructure;\r\n\t\t\r\n\tpStructure = m_network_preferences.GetPreference( CRCD(0xce238f5d,\"fireball_difficulty\") );\r\n\tpStructure->GetChecksum( \"Checksum\", &checksum, true );\r\n\tif( checksum == Script::GenerateCRC( \"num_1\" ))\r\n\t{\r\n\t\treturn 1;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_2\" ))\r\n\t{\r\n\t\treturn 2;\r\n\t}\r\n\telse if( checksum == Script::GenerateCRC( \"num_3\" ))\r\n\t{\r\n\t\treturn 3;\r\n\t}                                              \r\n\telse if( checksum == Script::GenerateCRC( \"num_4\" ))\r\n\t{\r\n\t\treturn 4;\r\n\t}                                              \r\n\telse if( checksum == Script::GenerateCRC( \"num_5\" ))\r\n\t{\r\n\t\treturn 5;\r\n\t}                                              \r\n\r\n\treturn 3;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::ToggleMetrics( void )\r\n{\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\r\n\tm_metrics_on ^= 1;\r\n\r\n\tif( m_metrics_on )\r\n\t{\r\n\t\tmlp_manager->AddLogicTask( *m_render_metrics_task );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_render_metrics_task->Remove();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::ToggleScores( void )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tGame::CGameMode* pGameMode;\r\n\tbool show_score;\r\n\r\n\tpGameMode = skate_mod->GetGameMode();\r\n\tshow_score = pGameMode->ShouldAccumulateScore();\r\n\r\n\tm_scores_on ^= 1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::TogglePlayerNames( void )\r\n{\r\n\tm_draw_player_names ^= 1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ShouldDrawPlayerNames( void )\r\n{\r\n\tPrefs::Preferences* pPreferences;\r\n\tScript::CStruct* pStructure;\r\n\tuint32 checksum = 0;\r\n\t\t\r\n\tpPreferences = GetNetworkPreferences();\r\n\tpStructure = pPreferences->GetPreference( CRCD(0xf7dd263,\"show_names\") );\r\n\tpStructure->GetChecksum( CRCD(0x21902065,\"checksum\"), &checksum, false );\r\n\treturn( checksum == CRCD(0xf81bc89b,\"boolean_true\") );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::RemoveModemStateTask( void )\r\n{\r\n\tm_modem_state_task->Remove();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ConnectToInternet( uint32 success_script, uint32 failure_script )\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tbool was_online, is_online;\r\n\r\n\tm_connection_success_script = success_script;\r\n\tm_connection_failure_script = failure_script;\r\n    \r\n\tDbg_Printf( \"Connecting to the internet\\n\" );\r\n\twas_online = net_man->IsOnline();\r\n\tif( was_online )\r\n\t{\r\n\t\tis_online = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_last_modem_state = -1;\r\n\t\tis_online = net_man->ConnectToInternet();\r\n\t}\r\n\t\r\n\tif( is_online )\r\n\t{   \r\n\t\tif( m_connection_success_script > 0 )\r\n\t\t{\r\n\t\t\tScript::RunScript( m_connection_success_script );\r\n\t\t}\r\n\t}\r\n\telse if(( net_man->GetConnectionType() == Net::vCONN_TYPE_MODEM ) ||\r\n\t\t\t( net_man->GetConnectionType() == Net::vCONN_TYPE_PPPOE ))\r\n\t{   \r\n\t\tmlp_man->AddLogicTask( *m_modem_state_task );\r\n\t}\r\n\t\r\n\treturn is_online;\r\n#else\r\n#ifdef __PLAT_XBOX__\r\n\tmpAuthMan->UserLogon();\r\n#endif\t\t// __PLAT_XBOX__\r\n\t\r\n\treturn false;\r\n#endif\t\t// __PLAT_NGPS__\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::CancelConnectToInternet( void )\r\n{\r\n\t\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\tManager * gamenet_man = Manager::Instance();\r\n\t\r\n\tswitch( net_man->GetModemState())\r\n\t{\r\n\t\tcase Net::vMODEM_STATE_DIALING:\r\n\t\tcase Net::vMODEM_STATE_CONNECTED:\r\n\t\t\tgamenet_man->RemoveModemStateTask();\r\n\t\t\tgamenet_man->DisconnectFromInternet();\r\n\t\t\tbreak;\r\n\t\tcase Net::vMODEM_STATE_ERROR:\r\n#ifdef __PLAT_NGPS__\r\n\t\t\tif( net_man->GetModemError() == SNTC_ERR_NOMODEM )\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( gamenet_man->m_connection_failure_script );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tgamenet_man->RemoveModemStateTask();\r\n\t\t\t\tgamenet_man->DisconnectFromInternet();\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n#endif\t\t// __PLAT_NGPS__\r\n\t\t\tgamenet_man->RemoveModemStateTask();\r\n\t\t\tbreak;;\r\n\t\tcase Net::vMODEM_STATE_DISCONNECTED:\r\n\t\t\tDbg_Printf( \"Removing modem state task\\n\" );\r\n\t\t\tgamenet_man->RemoveModemStateTask();\r\n\t\t\tScript::RunScript( gamenet_man->m_connection_failure_script );\r\n\t\t\tbreak;\r\n\t\tcase Net::vMODEM_STATE_LOGGED_IN:\r\n\t\t{\r\n\t\t\tnet_man->SetModemState( Net::vMODEM_STATE_READY_TO_TRANSMIT );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::DisconnectFromInternet( uint32 callback_script )\r\n{\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\r\n\tDbg_Assert(\t( net_man->GetConnectionType() == Net::vCONN_TYPE_MODEM ) ||\r\n\t\t\t\t( net_man->GetConnectionType() == Net::vCONN_TYPE_PPPOE ));\r\n\t   \r\n\tm_last_modem_state = -1;\r\n\tif( callback_script != 0 )\r\n\t{\r\n        m_connection_failure_script = callback_script;\r\n\t}\r\n\r\n\tmlp_man->AddLogicTask( *m_modem_state_task );\r\n\tSetServerListState( vSERVER_LIST_STATE_SHUTDOWN );\r\n\tnet_man->DisconnectFromInternet();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::CreateNetPanelMessage( bool broadcast, uint32 message_checksum, char* string_parm_1,\r\n\t\t\t\t\t\t\t\t\t\tchar* string_parm_2, Obj::CMovingObject* object, char* properties, bool important,\r\n\t\t\t\t\t\t\t\t\t\tint time )\r\n{\r\n\tif( broadcast )\r\n\t{\r\n\t\tPlayerInfo* player;\r\n\t\tLst::Search< PlayerInfo > sh;\r\n\t\tMsgPanelMessage msg;\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tmsg.m_Parm1[0] = '\\0';\r\n\t\tmsg.m_Parm2[0] = '\\0';\r\n\t\tmsg.m_StringId = message_checksum;\r\n\t\tmsg.m_Time = time;\r\n\t\tmsg.m_PropsStructureCRC = (int) Script::GenerateCRC( properties );\r\n\t\tif( string_parm_1 )\r\n\t\t{\r\n\t\t\tstrcpy( msg.m_Parm1, string_parm_1 );\r\n\t\t}\r\n\t\tif( string_parm_2 )\r\n\t\t{\r\n\t\t\tstrcpy( msg.m_Parm2, string_parm_2 );\r\n\t\t}\r\n\r\n\t\tmsg_desc.m_Data = &msg;\r\n\t\tmsg_desc.m_Length = sizeof( MsgPanelMessage );\r\n\t\tmsg_desc.m_Id = MSG_ID_PANEL_MESSAGE;\r\n\t\tif( important )\r\n\t\t{\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t}\r\n\r\n\t\tDbg_Assert( m_server );\r\n        for( player = FirstPlayerInfo( sh, true ); player;\r\n\t\t\t\tplayer = NextPlayerInfo( sh, true ))\r\n\t\t{\r\n\t\t\tm_server->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{   \r\n\t\tScript::CScriptStructure* pStructure = new Script::CScriptStructure;\r\n\t\tconst char* text;\t\r\n\t\tchar temp_msg[256];\r\n\t\tchar final_msg[256];\r\n\t\tchar* format_start;\r\n\r\n\t\ttext = Script::GetLocalString( message_checksum );\r\n\t\tstrcpy( temp_msg, text );\r\n\t\tif(( format_start = strstr( temp_msg, \"%s0\" )))\r\n\t\t{\r\n\t\t\t*format_start = '\\0';\r\n\r\n\t\t\tstrcpy( final_msg, temp_msg );\r\n\t\t\tDbg_Assert( string_parm_1 );\t// Need a parameter for this format string\r\n\t\t\tstrcat( final_msg, string_parm_1 );\r\n\t\t\tformat_start += 3;\t// skip the format tag\r\n\t\t\tstrcat( final_msg, format_start );\r\n\r\n\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"Text\" ), ESYMBOLTYPE_STRING, final_msg );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"Text\" ), ESYMBOLTYPE_STRING, text );\r\n\t\t}\r\n\t\t\r\n\t\tpStructure->AddComponent( Script::GenerateCRC( \"id\" ), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"net_panel_msg\" ));\r\n\t\tpStructure->AddInteger( Script::GenerateCRC( \"msg_time\" ), time );\r\n\t\tScript::RunScript( \"create_net_panel_message\", pStructure );\r\n\t\t\r\n\t\tdelete pStructure;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ShouldSendScoreUpdates( void )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tGame::CGameMode* pGameMode = skate_mod->GetGameMode();\r\n\t\r\n\t// We need to send score updates in goal attack\r\n\tif( ( pGameMode->ShouldAccumulateScore() == false ) &&\r\n\t\t( pGameMode->ShouldTrackBestCombo() == false ) &&\r\n\t\t( pGameMode->GetNameChecksum() != CRCD(0xbff33600,\"netfirefight\")) &&\r\n\t\t( pGameMode->GetNameChecksum() != CRCD(0xec200eaa,\"netgoalattack\")) &&\r\n\t\t( pGameMode->GetNameChecksum() != CRCD(0x6c5ff266,\"netctf\")))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tif( pGameMode->EndConditionsMet() && ( pGameMode->GetNameChecksum() != CRCD(0xbff33600,\"netfirefight\")))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::SetCurrentLeader( PlayerInfo* player )\r\n{\r\n\tm_leader = player;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPlayerInfo*\t\tManager::GetCurrentLeader( void )\r\n{\r\n\treturn m_leader;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::SetCurrentLeadingTeam( int team )\r\n{\r\n\tm_leading_team = team;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\tManager::GetCurrentLeadingTeam( void )\r\n{\r\n\treturn m_leading_team;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetLastScoreUpdateTime( int time )\r\n{\r\n\tm_last_score_update = time;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tManager::GetLastScoreUpdateTime( void )\r\n{\r\n\treturn m_last_score_update;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::MarkReceivedFinalScores( bool received )\r\n{\r\n\tm_received_final_scores = received;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::HaveReceivedFinalScores( void )\r\n{\r\n\treturn m_received_final_scores;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::AddSpawnedTriggerEvent( int node, int obj_id, uint32 script )\r\n{\r\n\tTriggerEvent* queued_script;\r\n\tLst::Search< TriggerEvent > sh;\r\n\t\r\n\t// Check to make sure we don't queue duplicate scripts\r\n\tfor( queued_script = sh.FirstItem( m_trigger_events ); queued_script; \r\n\t\t\tqueued_script = sh.NextItem())\r\n\t{\r\n\t\tif( queued_script->m_Script == script )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\tTriggerEvent* event = new TriggerEvent;\r\n\r\n\tevent->m_Node = node;\r\n\tevent->m_ObjID = obj_id;\r\n\tevent->m_Script = script;\r\n\r\n\tm_trigger_events.AddToTail( event );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::ClearTriggerEventList( void )\r\n{\r\n\tLst::Search< TriggerEvent > sh;\r\n\tTriggerEvent* event, *next;\r\n\r\n\tfor( event = sh.FirstItem( m_trigger_events ); event; event = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tdelete event;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetProSetFlags( char flags )\r\n{\r\n\tm_proset_flags = flags;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SendChatMessage( char* message )\r\n{\r\n\t\r\n\tMsgChat msg;\r\n\tint size;\r\n\tPlayerInfo* player;\r\n\tScript::CStruct* p_params;\r\n\tchar final_msg[256];\r\n\tNet::MsgDesc msg_desc;\r\n\r\n    Dbg_Assert( message );\r\n\tDbg_Assert( m_client[0] );\r\n\r\n\t// No point in printing/sending an empty message\r\n\tif( message[0] == '\\0' )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tplayer = GetLocalPlayer();\r\n\tDbg_Assert( player );\r\n    \r\n\tstrcpy( msg.m_Name, player->m_Name );\r\n\tstrcpy( msg.m_ChatMsg, message );\r\n\tif( player->IsObserving() )\r\n\t{\r\n\t\tmsg.m_ObjId = Mdl::Skate::vMAX_SKATERS; \t// Signifies \"observer\"\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmsg.m_ObjId = player->m_Skater->GetID();\r\n\t}\r\n\r\n\tsize = sizeof( char ) + ( vMAX_PLAYER_NAME_LEN + 1 ) + strlen( message ) + 1;\r\n\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = size;\r\n\tmsg_desc.m_Id = MSG_ID_CHAT;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tm_client[0]->EnqueueMessageToServer( &msg_desc );\r\n\t\r\n\tp_params = new Script::CStruct;\t\r\n\tsprintf( final_msg, \"%s : %s\", player->m_Name, message );\r\n\tp_params->AddString( \"text\", final_msg );\r\n\tScript::RunScript(\"create_console_message\", p_params );\r\n\tdelete p_params;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::SetJoinState( JoinState state )\r\n{\r\n\tm_join_state = state;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nJoinState\t\tManager::GetJoinState( void )\r\n{\r\n\treturn m_join_state;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::SetObserverCommand( ObserverCommand command )\r\n{\r\n\tm_observer_command = command;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObserverCommand\t\tManager::GetObserverCommand( void )\r\n{\r\n\treturn m_observer_command;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::LaunchQueuedScripts( void )\r\n{\r\n\tTriggerEvent* queued_script, *next;\r\n\tLst::Search< TriggerEvent > sh;\r\n\tSfx::CSfxManager * pSfxManager = Sfx::CSfxManager::Instance();\r\n\tMdl::Skate * mod = Mdl::Skate::Instance();\r\n\tScript::CScript* pScript;\r\n    \r\n    Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t\r\n\tmod->SetLaunchingQueuedScripts();\r\n\t// Remember the original volume, then turn sound off so scripts don't make noise\r\n\tfloat orig_volume = pSfxManager->GetMainVolume();\r\n\tpSfxManager->SetMainVolume( 0.0f );\r\n\r\n    Dbg_Printf( \"********************* SPAWNING QUEUED SCRIPTS ******************\\n\" );\r\n\t\r\n\tScript::RunScript( \"PreRunQueuedScripts\" );\r\n\tfor( queued_script = sh.FirstItem( m_trigger_events ); queued_script; queued_script = next )\r\n\t{\r\n\t\tScript::EScriptReturnVal ret_val;\r\n\r\n\t\tnext = sh.NextItem();\r\n\t\r\n\t\tpScript = Script::SpawnScript( queued_script->m_Script, NULL, 0, NULL, \r\n\t\t\t\t\t\t\t\t\t   queued_script->m_Node ); // K: The 0,NULL bit means no callback script specified\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tpScript->SetCommentString(\"Spawned from Manager::LaunchQueuedScripts\");\r\n\t\t#endif\r\n\t\tpScript->mpObject = mod->GetObjectManager()->GetObjectByID( queued_script->m_ObjID );; \r\n\r\n\t\t// Now run script to completion\r\n\t\tdo \r\n\t\t{\r\n\t\t\tret_val = pScript->Update();\r\n\t\t\t// Script must not get blocked, otherwise it'll hang in this loop forever.\r\n\t\t\tDbg_MsgAssert( ret_val!=Script::ESCRIPTRETURNVAL_BLOCKED,(\"\\n%s\\nScript got blocked when being run by RunScript.\",pScript->GetScriptInfo()));\r\n\t\t\r\n\t\t} while( ret_val != Script::ESCRIPTRETURNVAL_FINISHED );\r\n\t\tScript::KillSpawnedScript(pScript);\r\n\t\tdelete queued_script;\r\n\t}\r\n\r\n\tScript::RunScript( \"PostRunQueuedScripts\" );\r\n\r\n\tDbg_Printf( \"********************* FINISHED SPAWNING QUEUED SCRIPTS ******************\\n\" );\r\n\t \r\n\t// Back to normal volume\r\n\tpSfxManager->SetMainVolume( orig_volume );\r\n\tmod->ClearLaunchingQueuedScripts();\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CCrown*\t\tManager::GetCrown( void )\r\n{\r\n\treturn m_crown;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::CleanupObjects( void )\r\n{\r\n\t// Nullify references to now-dead objects\r\n\tm_crown = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::SetCrownSpawnPoint( char spawn_point )\r\n{\r\n\tm_crown_spawn_point = spawn_point;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\t\t\tManager::GetNetThreadStack( void )\r\n{\r\n\treturn m_net_thread_stack;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::SetNetThreadId( int net_thread_id )\r\n{\r\n\tm_net_thread_id = net_thread_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\tManager::GetNetThreadId( void )\r\n{\r\n\treturn m_net_thread_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::SendEndOfRunMessage( void )\r\n{\r\n\tNet::Client* client;\r\n\tNet::MsgDesc msg_desc;\r\n\r\n\tDbg_Assert( HaveSentEndOfRunMessage() == false );\r\n\r\n\tclient = m_client[0];\r\n\tDbg_Assert( client );\r\n\r\n\tmsg_desc.m_Data = &m_game_id;\r\n\tmsg_desc.m_Length = sizeof( char );\r\n\tmsg_desc.m_Id = MSG_ID_RUN_HAS_ENDED;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tclient->EnqueueMessageToServer( &msg_desc );\r\n\r\n\tm_last_end_of_run_game_id = m_game_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tManager::HaveSentEndOfRunMessage( void )\r\n{\r\n\tif( m_last_end_of_run_game_id == m_game_id )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tManager::GameIsOver( void )\r\n{\r\n\treturn m_game_over;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::MarkGameOver( void )\r\n{\r\n\tm_game_over = true;\r\n}\r\n                                          \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::ClearGameOver( void )\r\n{\r\n\tm_game_over = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\tManager::HasCheatingOccurred( void )\r\n{\r\n\treturn m_cheating_occurred;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::CheatingOccured( void )\r\n{\r\n\tm_cheating_occurred = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::ClearCheating( void )\r\n{\r\n\tm_cheating_occurred = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::RespondToReadyQuery( void )\r\n{\r\n\tMsgReady msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tint i;\r\n\r\n\tmsg.m_Time = m_latest_ready_query;\r\n\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof( MsgReady );\r\n\tmsg_desc.m_Id = MSG_ID_READY_RESPONSE;\r\n\tmsg_desc.m_Queue = Net::QUEUE_IMPORTANT;\r\n\tfor( i = 0; i < 2; i++ )\r\n\t{\r\n\t\tif( m_client[i] )\r\n\t\t{\r\n\t\t\tm_client[i]->EnqueueMessageToServer( &msg_desc );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\tManager::ToggleProSet( char bit, uint32 param_id )\r\n{\r\n\tMsgToggleProSet msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tNet::Server* server;\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\r\n\tm_proset_flags.Toggle( bit );\r\n\t\r\n\tmsg.m_Bit = bit;\r\n\tmsg.m_ParamId = param_id;\r\n\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof( MsgToggleProSet );\r\n\tmsg_desc.m_Id = MSG_ID_TOGGLE_PROSET;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\r\n\tserver = GetServer();\r\n\tfor( player = FirstPlayerInfo( sh, true ); player; player = NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tManager::ScriptStartCTFGame(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\r\n\tmlp_man->AddLogicTask( *gamenet_man->m_ctf_logic_task );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tManager::ScriptEndCTFGame(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\tgamenet_man->m_ctf_logic_task->Remove();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptTookFlag(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* player, *capture_player;\r\n\tNet::Server* server;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tMsgFlagMsg msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tint obj_id, team;\r\n\r\n\tpParams->GetInteger( \"player\", &obj_id );\r\n\tpParams->GetInteger( \"flag_team\", &team );\r\n\t\r\n\tcapture_player = gamenet_man->GetPlayerByObjectID( obj_id );\r\n\tif( capture_player == NULL )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tmsg.m_ObjId = (char) obj_id;\r\n\tmsg.m_Team = (char) team;\r\n\t\t\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof( MsgFlagMsg );\r\n\tmsg_desc.m_Id = MSG_ID_TOOK_FLAG;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\r\n\tserver = gamenet_man->GetServer();\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tcapture_player->TookFlag( team );\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptCapturedFlag(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* player, *capture_player;\r\n\tNet::Server* server;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tMsgFlagMsg msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tint obj_id, team;\r\n\r\n\tpParams->GetInteger( \"player\", &obj_id );\r\n\tcapture_player = gamenet_man->GetPlayerByObjectID( obj_id );\r\n\tif(( capture_player == NULL ) || ( capture_player->m_flags.TestMask( PlayerInfo::mRESTARTING )))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tteam = capture_player->HasWhichFlag();\r\n\tmsg.m_ObjId = (char) obj_id;\r\n\tmsg.m_Team = (char) team;\r\n\t\t\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof( MsgFlagMsg );\r\n\tmsg_desc.m_Id = MSG_ID_CAPTURED_FLAG;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\r\n\tserver = gamenet_man->GetServer();\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tMdl::Score* score_obj;\r\n\t\t\t\r\n\t\t\tObj::CSkaterScoreComponent* p_skater_score_component = GetSkaterScoreComponentFromObject(capture_player->m_Skater);\r\n\t\t\tDbg_Assert(p_skater_score_component);\r\n\t\t\tscore_obj = p_skater_score_component->GetScore();\r\n\t\t\t\r\n\t\t\tDbg_Assert(score_obj);\r\n\t\t\tscore_obj->SetTotalScore( score_obj->GetTotalScore() + 1 );\r\n\r\n\t\t\tcapture_player->CapturedFlag( team );\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptRetrievedFlag(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* player, *retrieve_player;\r\n\tNet::Server* server;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tMsgFlagMsg msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tint obj_id, team;\r\n\r\n\tpParams->GetInteger( \"player\", &obj_id );\r\n\tpParams->GetInteger( \"flag_team\", &team );\r\n\t\r\n\tretrieve_player = gamenet_man->GetPlayerByObjectID( obj_id );\r\n\tif( retrieve_player == NULL )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tmsg.m_ObjId = (char) obj_id;\r\n\tmsg.m_Team = (char) team;\r\n\t\t\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof( MsgFlagMsg );\r\n\tmsg_desc.m_Id = MSG_ID_CAPTURED_FLAG;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\r\n\tserver = gamenet_man->GetServer();\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tretrieve_player->CapturedFlag( team );\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptHasFlag(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* player;\r\n\tint obj_id;\r\n\r\n\tpParams->GetInteger( \"player\", &obj_id );\r\n\t\r\n\tplayer = gamenet_man->GetPlayerByObjectID( obj_id );\r\n\tif( player == NULL )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn player->HasCTFFlag();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptDisplayFlagBaseWarning(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tstatic Tmr::Time s_last_show = 0;\r\n\r\n\tif(( Tmr::GetTime() - s_last_show ) > Tmr::Seconds( 3 ))\r\n\t{\r\n\t\tScript::RunScript( CRCD(0x55af7c02,\"display_flag_base_warning\"), NULL );\r\n\t\ts_last_show = Tmr::GetTime();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptTeamFlagTaken(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tint team;\r\n\r\n\tpParams->GetInteger( \"team\", &team );\r\n\t\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t{\r\n\t\tif( player->HasWhichFlag() == team )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SpawnCrown | spawn the king of the hill crown\r\nbool\tManager::ScriptSpawnCrown(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\t// Spawn the king of the hill crown\r\n\tgamenet_man->m_crown = new Obj::CCrown;\r\n\r\n\tint i, spawn_pt;\r\n\t\t\r\n\tScript::CArray *pNodeArray=Script::GetArray(\"NodeArray\");\r\n\r\n\t// if there is no node array, then there are no restart points\r\n\tif (!pNodeArray)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\t\t\t\t\t \r\n\ti = 0;\r\n\tspawn_pt = gamenet_man->m_crown_spawn_point;\r\n\t\t\r\n\t// collect a table of all crown nodes\r\n\tint max_crown_node = 0;\r\n\tScript::CStruct *pCrownNodeTab[vNUM_CROWN_SPAWN_POINTS];\r\n\tint crown_nodes[vNUM_CROWN_SPAWN_POINTS];\r\n\twhile( i < (int)pNodeArray->GetSize() )\r\n\t{\r\n\t\tuint32\tTypeChecksum;\r\n\t\tScript::CStruct *pNode=pNodeArray->GetStructure(i);\r\n\t\t\r\n\t\tTypeChecksum = 0;\r\n\t\tpNode->GetChecksum(\"Type\",&TypeChecksum);\r\n\t\tif( TypeChecksum == 0xaf86421b )\t// checksum of \"Crown\"\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( max_crown_node < vNUM_CROWN_SPAWN_POINTS, ( \"Too many crown spawn points\" ));\r\n\t\t\tcrown_nodes[max_crown_node] = i;\r\n\t\t\tpCrownNodeTab[max_crown_node++] = pNode;\r\n\t\t}\r\n\t\ti++;\r\n\t}\r\n\tDbg_MsgAssert(max_crown_node, (\"no crown nodes found\"));\r\n\t\t\r\n\t// there may be fewer crown points than the one we want, so\r\n\t// truncate the request number if so\r\n\tspawn_pt = spawn_pt % max_crown_node;\r\n\r\n\t// now set up crown point in world\r\n\tMth::Vector pos;\r\n\tSkateScript::GetPosition( pCrownNodeTab[spawn_pt], &pos );\r\n    \r\n\tgamenet_man->m_crown->InitCrown( skate_mod->GetObjectManager(), pCrownNodeTab[spawn_pt] );\r\n\r\n    PlayerInfo* king;\r\n\t//gamenet_man->m_crown->AddToWorld( viewer_mod->GetCurrentWorld(), &pos );\r\n\t\r\n\t// We may have a king \"queued\" up (i.e. we joined a KOTH game in progress.\r\n\t// If so, coronate the king straight away\r\n\tking = gamenet_man->GetKingOfTheHill();\r\n\tif( king )\r\n\t{\r\n\t\tgamenet_man->m_crown->PlaceOnKing( king->m_Skater );\r\n\t}\r\n    \r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | NetworkGamePending | \r\nbool Manager::ScriptNetworkGamePending(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n    \r\n\treturn gamenet_man->m_game_pending;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StartNetworkGame | \r\nbool Manager::ScriptStartNetworkGame(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tManager * gamenet_man = Manager::Instance();\r\n    \r\n\tif( gamenet_man->m_start_network_game_task->InList())\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\tif( gamenet_man->m_change_level_task->InList())\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tgamenet_man->m_game_pending = true;\r\n\tif( gamenet_man->InNetGame())\r\n\t{ \r\n\t\tif( gamenet_man->GetGameTypeFromPreferences() == Script::GenerateCRC( \"netgoalattack\" ))\r\n\t\t{\r\n\t\t\ts_time_to_start_game = Tmr::GetTime() + vTIME_BEFORE_STARTING_GOALATTACK;\r\n\t\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ts_time_to_start_game = Tmr::GetTime() + vTIME_BEFORE_STARTING_NETGAME;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\ts_time_to_start_game = Tmr::GetTime();\r\n\t}\r\n\t\t\t\r\n\tmlp_man->AddLogicTask( *gamenet_man->m_start_network_game_task );\r\n\t\r\n\tif( gamenet_man->InNetGame())\r\n\t{\r\n\t\tif( gamenet_man->GetHostMode() == vHOST_MODE_AUTO_SERVE )\r\n\t\t{\r\n\t\t\tgamenet_man->CreateNetPanelMessage( true, Script::GenerateCRC(\"net_message_auto_starting_game\"),\r\n\t\t\t\t\t\t\t\t\t\t\t gamenet_man->GetGameModeName(), NULL, NULL, \"netstatusprops\", true,\r\n\t\t\t\t\t\t\t\t\t\t\t\tTmr::Seconds( 3 ));    \r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tgamenet_man->CreateNetPanelMessage( true, Script::GenerateCRC(\"net_message_starting_game\"),\r\n\t\t\t\t\t\t\t\t\t\t gamenet_man->GetGameModeName(), NULL, NULL, \"netstatusprops\", true,\r\n\t\t\t\t\t\t\t\t\t\t\tTmr::Seconds( 3 ));\r\n\t\t}\r\n\r\n\t\tif( skate_mod->GetGameMode()->IsTeamGame())\r\n\t\t{\r\n\t\t\tNet::Server* server;\r\n\t\t\tPlayerInfo* player;\r\n\t\t\tLst::Search< PlayerInfo > sh;\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\t\t \r\n\t\t\tserver = gamenet_man->GetServer();\r\n\t\t\tDbg_Assert( server );\r\n\r\n\t\t\tmsg_desc.m_Id = MSG_ID_KILL_TEAM_FLAGS;\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Compile the list of selected goals to send to all clients at the start of goal attack games\r\n\tif( gamenet_man->InNetGame() && ( gamenet_man->GetGameTypeFromPreferences() == Script::GenerateCRC( \"netgoalattack\" )))\r\n\t{\r\n\t\tint i, num_goals;\r\n\t\tGame::CGoalManager* pGoalManager;\r\n\t\tGame::CGoal* pGoal;\r\n\t\tNet::MsgMax msg;\r\n\t\tNet::MsgDesc msg_desc;\r\n\t\tuint32 goal_id;\r\n\t\tchar* data;\r\n\t\tNet::Server* server;\r\n\t\tPlayerInfo* player;\r\n\t\tLst::Search< PlayerInfo > sh;\r\n\t\t \r\n\t\tpGoalManager = Game::GetGoalManager();\r\n\t\tserver = gamenet_man->GetServer();\r\n\t\tDbg_Assert( server );\r\n\r\n\t\tdata = msg.m_Data;\r\n\t\t*data++ = 1;\t// This indicates that they should bring up the goal summary dialog\r\n\t\tnum_goals = pGoalManager->GetNumGoals();\r\n\t\tDbg_Printf( \"*** Num Goals: %d\\n\" );\r\n\t\tfor( i = 0; i < num_goals; i++ )\r\n\t\t{\r\n\t\t\tpGoal = pGoalManager->GetGoalByIndex( i );\r\n\t\t\tDbg_Assert( pGoal );\r\n\t\t\tif( pGoal->IsSelected())\r\n\t\t\t{\r\n\t\t\t\tpGoal->UnBeatGoal();\r\n\t\t\t\tgoal_id = pGoal->GetGoalId();\r\n\t\t\t\tDbg_Printf( \"*** Goals %d selected, id 0x%x\\n\", i, goal_id );\r\n\t\t\t\tmemcpy( data, &goal_id, sizeof( uint32 ));\r\n\t\t\t\tdata += sizeof( uint32 );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// zero-terminate the list of goals\r\n\t\tgoal_id = 0;\r\n\t\tmemcpy( data, &goal_id, sizeof( uint32 ));\r\n\t\tdata += sizeof( uint32 );\r\n\r\n\t\tmsg_desc.m_Data = &msg;\r\n\t\tmsg_desc.m_Length = (int) ( data - msg.m_Data );\r\n\t\tmsg_desc.m_Id = MSG_ID_SELECT_GOALS;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t{\r\n\t\t\t// No need to send to server\r\n\t\t\tif( player->IsLocalPlayer())\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t}\r\n\t\t\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptSendGameOverToObservers(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\tDbg_Printf( \"**** In ScriptSendGameOverToObservers\\n\" );\r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\tNet::Server* server;\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tserver = gamenet_man->GetServer();\r\n\r\n\t\tmsg_desc.m_Id = MSG_ID_GAME_OVER;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t{\r\n\t\t\tif( player->IsObserving())\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"**** Sending message to observer\\n\" );\r\n                server->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tManager::ScriptEndNetworkGame(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\tNet::Server* server;\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tserver = gamenet_man->GetServer();\r\n\r\n\t\tScript::RunScript( \"do_backend_retry\" );\r\n\t\r\n\t\tmsg_desc.m_Id = MSG_ID_END_GAME;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t{\r\n\t\t\tif( player->IsLocalPlayer())\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\r\n\t\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNet::Client* client;\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tclient = gamenet_man->GetClient( 0 );\r\n\r\n\t\tmsg_desc.m_Id = MSG_ID_FCFS_END_GAME;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetJoinMode | \r\n// @uparm 1 | mode (0 for play, anything else for observe)\r\nbool Manager::ScriptSetJoinMode(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tint mode = 0;\r\n    \r\n\tmode = 0;\r\n\tpParams->GetInteger( NONAME, &mode );\r\n\tif( mode == 0 )\r\n\t{\r\n\t\tgamenet_man->SetJoinMode( vJOIN_MODE_PLAY );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgamenet_man->SetJoinMode( vJOIN_MODE_OBSERVE );\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetHostMode | \r\n// @uparm 1 | mode (0 for server, 1 for auto_serve, 2 for fcfs)\r\nbool Manager::ScriptSetHostMode(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tint mode = 0;\r\n    \r\n\tmode = 0;\r\n\tpParams->GetInteger( NONAME, &mode );\r\n\r\n\tgamenet_man->SetHostMode( (HostMode) mode );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptGetNumTeams(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tScript::CStruct* pass_back_params;\r\n\tint num_teams;\r\n\t\r\n\tnum_teams = skate_mod->GetGameMode()->NumTeams();\r\n\tpass_back_params = pScript->GetParams();\r\n\tpass_back_params->AddInteger( \"num_teams\", num_teams );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptGetNumPlayersOnTeam(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tScript::CStruct* pass_back_params;\r\n\tint team_num = 0;\r\n\tint num_players = 0;\r\n\t\r\n\tpParams->GetInteger( \"team\", &team_num, Script::ASSERT );\r\n\tnum_players = gamenet_man->NumTeamMembers( team_num );\r\n\tpass_back_params = pScript->GetParams();\r\n\tpass_back_params->AddInteger( \"num_members\", num_players );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptGetMyTeam(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tScript::CStruct* pass_back_params;\r\n\tPlayerInfo *player;\r\n\t\r\n\tplayer = gamenet_man->GetLocalPlayer();\r\n\tif( player )\r\n\t{\r\n\t\tpass_back_params = pScript->GetParams();\r\n\t\tpass_back_params->AddInteger( \"team\", player->m_Team );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptSetNumTeams(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tPlayerInfo* team_player, *player;\r\n\tLst::Search< PlayerInfo > team_sh, sh;\r\n\tMsgChangeTeam msg;\r\n\tMsgByteInfo num_teams_msg;\r\n\tNet::MsgDesc team_msg_desc;\r\n\tint num_teams = 0;\r\n\tNet::Server* server;\r\n    \r\n\tpParams->GetInteger( NONAME, &num_teams );\r\n\r\n\tif( !gamenet_man->OnServer())\r\n\t{\r\n\t\tNet::Client* client;\r\n\t\tMsgByteInfo team_msg;\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tclient = gamenet_man->GetClient( 0 );\r\n\r\n\t\tteam_msg.m_Data = num_teams;\r\n\t\tDbg_Printf( \"Telling server to create %d teams\\n\", num_teams );\r\n\r\n\t\tmsg_desc.m_Data = &team_msg;\r\n\t\tmsg_desc.m_Length = sizeof( MsgByteInfo );\r\n\t\tmsg_desc.m_Id = MSG_ID_FCFS_SET_NUM_TEAMS;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif( ( num_teams > 0 ) &&\r\n\t\t( !skate_mod->GetGameMode()->IsTeamGame()))\r\n\t{\r\n\t\tskate_mod->GetGameMode()->SetNumTeams( num_teams );\r\n\t\tif( skate_mod->GetLocalSkater())\r\n\t\t{\r\n\t\t\tScript::RunScript( \"PrepareSkaterForMove\", NULL, skate_mod->GetLocalSkater());\r\n\t\t\tskate_mod->move_to_restart_point( skate_mod->GetLocalSkater());\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tskate_mod->GetGameMode()->SetNumTeams( num_teams );\r\n\t}\r\n\t\r\n\tserver = gamenet_man->GetServer();\r\n\tif( server == NULL )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tnum_teams_msg.m_Data = num_teams;\r\n\r\n\tteam_msg_desc.m_Data = &num_teams_msg;\r\n\tteam_msg_desc.m_Length = sizeof( MsgByteInfo );\r\n\tteam_msg_desc.m_Id = MSG_ID_SET_NUM_TEAMS;\r\n\tteam_msg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tteam_msg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tserver->EnqueueMessage( player->GetConnHandle(), &team_msg_desc );\r\n\t}\r\n\r\n\tteam_msg_desc.m_Data = &msg;\r\n\tteam_msg_desc.m_Length = sizeof( MsgChangeTeam );\r\n\tteam_msg_desc.m_Id = MSG_ID_TEAM_CHANGE;\r\n\tteam_msg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tteam_msg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tfor( team_player = gamenet_man->FirstPlayerInfo( team_sh ); team_player; team_player = gamenet_man->NextPlayerInfo( team_sh ))\r\n\t{\r\n\t\tif( team_player->m_Team >= num_teams )\r\n\t\t{\r\n\t\t\tmsg.m_Team = (unsigned char) vTEAM_RED;\r\n\t\t\tmsg.m_ObjID = (unsigned char) team_player->m_Skater->GetID();\r\n\r\n\t\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\tif( player->IsLocalPlayer())\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tserver->EnqueueMessage( player->GetConnHandle(), &team_msg_desc );\r\n\t\t\t}\r\n\t\t\tteam_player->m_Team = vTEAM_RED;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptJoinTeam(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* player;\r\n\tMsgChangeTeam msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tNet::Client* client;\r\n\tuint32 team_checksum;\r\n\tint team;\r\n\tstatic Tmr::Time s_last_join_time = 0;\r\n\r\n\tplayer = gamenet_man->GetLocalPlayer();\r\n\tif( ( player == NULL ) || \r\n\t\t( player->m_Skater == NULL ))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tpParams->GetChecksum( NONAME, &team_checksum );\r\n\tif( team_checksum == Script::GenerateCRC( \"blue\" ))\r\n\t{\r\n\t\tteam = vTEAM_BLUE;\r\n\t}\r\n\telse if( team_checksum == Script::GenerateCRC( \"red\" ))\r\n\t{\r\n\t\tteam = vTEAM_RED;\r\n\t}\r\n\telse if( team_checksum == Script::GenerateCRC( \"green\" ))\r\n\t{\r\n\t\tteam = vTEAM_GREEN;\r\n\t}\r\n\telse \r\n\t{\r\n\t\tteam = vTEAM_YELLOW;\r\n\t}\r\n    \r\n\tmsg.m_Team = (unsigned char) team;\r\n\tmsg.m_ObjID = (unsigned char) player->m_Skater->GetID();\r\n\tclient = gamenet_man->GetClient( 0 );\r\n\tif(( Tmr::GetTime() - s_last_join_time ) < 150 )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\ts_last_join_time = Tmr::GetTime();\r\n\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof( MsgChangeTeam );\r\n\tmsg_desc.m_Id = MSG_ID_REQUEST_CHANGE_TEAM;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tclient->EnqueueMessageToServer( &msg_desc );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptConnectedToPeer(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPEER peer;\r\n\r\n\tpeer = gamenet_man->mpLobbyMan->GetPeer();\r\n\r\n\treturn ( peer && peerIsConnected( peer ));\r\n#else\r\n\treturn false;\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptInGroupRoom(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#ifndef __PLAT_NGPS__\r\n\treturn false;\r\n#else\r\n\tManager * gamenet_man = Manager::Instance();\r\n\treturn gamenet_man->mpLobbyMan->InGroupRoom();\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptIsHost(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* player;\r\n\r\n\tif( gamenet_man->InNetGame() == false )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\treturn( gamenet_man->GetHostMode() == vHOST_MODE_SERVE );\r\n\t}\r\n\r\n\tplayer = gamenet_man->GetLocalPlayer();\r\n\tif( player && player->IsServerPlayer())\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptIsAutoServing(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\t\t\r\n\tif( gamenet_man->InNetGame() == false )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif( gamenet_man->OnServer() == false )\r\n\t{\r\n\t\treturn false;\r\n\t\t\r\n\t}\r\n\r\n\treturn( gamenet_man->GetHostMode() == vHOST_MODE_AUTO_SERVE );\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptChangeLevelPending(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\t\r\n\treturn( gamenet_man->m_change_level_task->InList());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptDownloadMotd(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\tgamenet_man->SetNextServerListState( vSERVER_LIST_STATE_STARTING_MOTD );\r\n\tgamenet_man->SetServerListState( vSERVER_LIST_STATE_INITIALIZE );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptAlreadyGotMotd(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\treturn gamenet_man->m_got_motd;\r\n#else\r\n\treturn true;\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptAlreadySignedIn(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n#ifdef __PLAT_XBOX__\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\treturn gamenet_man->mpAuthMan->SignedIn();\r\n#else\r\n\treturn false;\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptSignOut(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n#ifdef __PLAT_XBOX__\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\tgamenet_man->mpAuthMan->SignOut();\r\n#endif\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptAllPlayersAreReady(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo* player;\r\n\r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t{\r\n\t\t\tif(( player->m_Conn->GetStatus() & Net::Conn::mSTATUS_READY ) == 0 )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptJoinServerComplete(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\treturn gamenet_man->ReadyToPlay();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptJustStartedNetGame(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tif(( Tmr::GetTime() - s_time_to_start_game ) < Tmr::Seconds( 5 ))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptEnteredNetworkGame(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n    \r\n\tmlp_manager->AddLogicTask( *gamenet_man->m_enter_chat_task );\r\n\tmlp_manager->AddLogicTask( *gamenet_man->m_render_scores_task );\r\n\tgamenet_man->m_scores_on = true;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptChooseAccount(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n#ifdef __PLAT_XBOX__\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tint index;\r\n\r\n\tindex = 0;\r\n\tpParams->GetInteger( Script::GenerateCRC(\"index\"), &index );\r\n\tgamenet_man->mpAuthMan->SelectAccount( index );\r\n#endif\t// __PLAT_XBOX__\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptCreatePlayerOptions(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tScript::CScriptStructure* pStructure;\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tint index;\r\n\tconst char* name;\r\n\r\n\tindex = 0;\r\n\tname = NULL;\r\n\tpParams->GetInteger( Script::GenerateCRC(\"index\"), &index );\r\n\tpParams->GetString( Script::GenerateCRC(\"name\"), &name );\r\n\t\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( index == 0 )\r\n\t\t{\r\n\t\t\tif( stricmp( player->m_Name, name ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tplayer->m_flags.SetMask( PlayerInfo::mMARKED_PLAYER );\r\n\r\n\t\t\t\tpStructure = new Script::CScriptStructure;\r\n\r\n#ifdef __PLAT_NGPS__\t\r\n\t\t\t\tif( gamenet_man->InInternetMode())\r\n\t\t\t\t{\r\n\t\t\t\t\tif( ( player->m_Profile ) && \r\n\t\t\t\t\t\t( gamenet_man->mpBuddyMan->IsLoggedIn()))\r\n\t\t\t\t\t{         \r\n\t\t\t\t\t\tpStructure->AddInteger( \"profile\", player->m_Profile );\t\r\n\t\t\t\t\t\tpStructure->AddString( \"nick\", player->m_Name );    \r\n\t\t\t\t\r\n\t\t\t\t\t\tif( gamenet_man->mpBuddyMan->IsAlreadyMyBuddy( player->m_Profile ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tpStructure->AddChecksum( NONAME, Script::GenerateCRC( \"allow_remove_homie\" ));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tpStructure->AddChecksum( NONAME, Script::GenerateCRC( \"allow_add_homie\" ));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n#endif\r\n\t\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"name\" ), ESYMBOLTYPE_STRING, name );\r\n\t\r\n\t\t\t\tScript::RunScript( \"create_player_options_dialog\", pStructure );\r\n\t\r\n\t\t\t\tdelete pStructure;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tindex--;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#ifdef __PLAT_NGPS__\r\nbool Manager::ScriptFillPlayerListMenu( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tScript::CStruct* p_item_params, *p_unfocus_params;\r\n\tScript::CArray* p_colors;\r\n\tint i;\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\r\n\ti = 0;\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\ti++;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tp_colors = new Script::CArray;\r\n\t\tp_colors->SetSizeAndType( 4, ESYMBOLTYPE_INTEGER );\r\n\r\n\t\tif( ( player->m_Profile ) && \r\n\t\t\t( gamenet_man->mpBuddyMan->IsLoggedIn()))\r\n\t\t{         \r\n\t\t\tif( gamenet_man->mpBuddyMan->IsAlreadyMyBuddy( player->m_Profile ))\r\n\t\t\t{\r\n\t\t\t\tp_colors->SetInteger( 0, 128 );\r\n\t\t\t\tp_colors->SetInteger( 1, 128 );\r\n\t\t\t\tp_colors->SetInteger( 2, 0 );\r\n\t\t\t\tp_colors->SetInteger( 3, 128 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_colors->SetInteger( 0, 0 );\r\n\t\t\t\tp_colors->SetInteger( 1, 128 );\r\n\t\t\t\tp_colors->SetInteger( 2, 0 );\r\n\t\t\t\tp_colors->SetInteger( 3, 128 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_colors->SetInteger( 0, 128 );\r\n\t\t\tp_colors->SetInteger( 1, 128 );\r\n\t\t\tp_colors->SetInteger( 2, 128 );\r\n\t\t\tp_colors->SetInteger( 3, 128 );\r\n\t\t}\r\n\t\t\r\n\t\tp_item_params = new Script::CStruct;\t\r\n\t\tp_item_params->AddString( \"text\", player->m_Name );\r\n\t\tp_item_params->AddChecksum( \"centered\", CRCD(0x2a434d05,\"centered\") );\r\n\t\tp_item_params->AddChecksum( \"id\", 123456 + i );\r\n\t\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"choose_selected_player\"));\r\n\t\t\r\n\t\tp_unfocus_params = new Script::CStruct;\r\n\t\tp_unfocus_params->AddArray( \"rgba\", p_colors );\r\n\t\tp_item_params->AddArray( \"rgba\", p_colors );\r\n\t\tp_item_params->AddStructure( \"unfocus_params\", p_unfocus_params );\r\n\t\r\n\t\t// create the parameters that are passed to the X script\r\n\t\tScript::CStruct *p_script_params= new Script::CStruct;\r\n\t\tp_script_params->AddInteger( \"index\", i );\t\r\n\t\tp_script_params->AddString( \"name\", player->m_Name );\t\r\n\t\tp_item_params->AddStructure(\"pad_choose_params\",p_script_params);\t\t\t\r\n\t\r\n\t\tScript::RunScript(\"theme_menu_add_item\",p_item_params);\r\n\t\t\r\n\t\tdelete p_item_params;\r\n\t\tdelete p_script_params;\r\n\t\tdelete p_unfocus_params;\r\n\t\tdelete p_colors;\r\n\t\ti++;\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\treturn true;\r\n}\r\n#endif\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptRemovePlayer(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tScript::CScriptStructure* pStructure;\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tint index;\r\n\tconst char* name;\r\n\r\n\tindex = 0;\r\n\tname = NULL;\r\n\tpParams->GetInteger( Script::GenerateCRC(\"index\"), &index );\r\n\tpParams->GetString( Script::GenerateCRC(\"name\"), &name );\r\n\t\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t{\r\n\t\tif( index == 0 )\r\n\t\t{\r\n\t\t\tif( stricmp( player->m_Name, name ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tplayer->m_flags.SetMask( PlayerInfo::mMARKED_PLAYER );\r\n\r\n\t\t\t\tpStructure = new Script::CScriptStructure;\r\n\t\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"name\" ), ESYMBOLTYPE_STRING, name );\r\n\t\r\n\t\t\t\tScript::RunScript( \"create_kick_ban_menu\", pStructure );\r\n\t\r\n\t\t\t\tdelete pStructure;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tindex--;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptCancelRemovePlayer(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t{\r\n\t\tplayer->m_flags.ClearMask( PlayerInfo::mMARKED_PLAYER );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptKickPlayer(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tint i;\r\n\r\n\ti = 0;\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( player->m_flags.TestMask( PlayerInfo::mMARKED_PLAYER ))\r\n\t\t{\r\n\t\t\tif( gamenet_man->OnServer())\r\n\t\t\t{\r\n\t\t\t\tObj::CSkater* quitting_skater;\r\n\t\t\t\tbool observing;\r\n\t\r\n\t\t\t\tquitting_skater = player->m_Skater;\r\n\t\t\t\tobserving = player->IsObserving();\r\n\t\t\t\tgamenet_man->DropPlayer( player, vREASON_KICKED );\r\n\t\t\t\tif( !observing )\r\n\t\t\t\t{\r\n\t\t\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\t\t\tskate_mod->remove_skater( quitting_skater );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tNet::Client* client;\r\n\t\t\t\tMsgRemovePlayerRequest msg;\r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t\tclient = gamenet_man->GetClient( 0 );\r\n\t\t\t\tDbg_Assert( client );\r\n\r\n\t\t\t\tmsg.m_Ban = 0;\r\n\t\t\t\tmsg.m_Index = i;\r\n\t\t\t\tstrcpy( msg.m_Name, player->m_Name );\r\n\r\n\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( MsgRemovePlayerRequest );\r\n\t\t\t\tmsg_desc.m_Id = MSG_ID_FCFS_BAN_PLAYER;\r\n\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\ti++;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptBanPlayer(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tint i;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\ti = 0;\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( player->m_flags.TestMask( PlayerInfo::mMARKED_PLAYER ))\r\n\t\t{\r\n\t\t\tif( gamenet_man->OnServer())\r\n\t\t\t{\r\n\t\t\t\tObj::CSkater* quitting_skater;\r\n\t\t\t\tbool observing;\r\n\t\r\n\t\t\t\tquitting_skater = player->m_Skater;\r\n\t\t\t\tobserving = player->IsObserving();\r\n\t\t\t\tgamenet_man->DropPlayer( player, vREASON_BANNED );\r\n\t\t\t\tif( !observing )\r\n\t\t\t\t{\r\n\t\t\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\t\t\tskate_mod->remove_skater( quitting_skater );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tNet::Client* client;\r\n\t\t\t\tMsgRemovePlayerRequest msg;\r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t\tclient = gamenet_man->GetClient( 0 );\r\n\t\t\t\tDbg_Assert( client );\r\n\r\n\t\t\t\tmsg.m_Ban = 1;\r\n\t\t\t\tmsg.m_Index = i;\r\n\t\t\t\tstrcpy( msg.m_Name, player->m_Name );\r\n\r\n\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( MsgRemovePlayerRequest );\r\n\t\t\t\tmsg_desc.m_Id = MSG_ID_FCFS_BAN_PLAYER;\r\n\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\ti++;\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptFCFSRequestStartGame(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tMsgStartGameRequest msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tNet::Client* client;\r\n\tPrefs::Preferences* pPreferences;\r\n\t\r\n\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\tmsg.m_SkillLevel = pPreferences->GetPreferenceChecksum( Script::GenerateCRC(\"skill_level\"), Script::GenerateCRC(\"checksum\") );\r\n\tmsg.m_FireballLevel = pPreferences->GetPreferenceChecksum( Script::GenerateCRC(\"fireball_difficulty\"), Script::GenerateCRC(\"checksum\") );\r\n\tmsg.m_GameMode = gamenet_man->GetGameTypeFromPreferences();\r\n\tmsg.m_TimeLimit = pPreferences->GetPreferenceChecksum( Script::GenerateCRC(\"time_limit\"), Script::GenerateCRC(\"checksum\") );\r\n\tmsg.m_TargetScore = 0;\r\n\tmsg.m_TargetScore = pPreferences->GetPreferenceChecksum( Script::GenerateCRC(\"target_score\"), Script::GenerateCRC(\"checksum\") );\r\n\tDbg_Printf( \"************ SENDING TARGET SCORE OF %08x\\n\", msg.m_TargetScore );\r\n\tmsg.m_PlayerCollision = pPreferences->GetPreferenceChecksum( Script::GenerateCRC(\"player_collision\"), Script::GenerateCRC(\"checksum\") );\r\n\tmsg.m_FriendlyFire = pPreferences->GetPreferenceChecksum( Script::GenerateCRC(\"friendly_fire\"), Script::GenerateCRC(\"checksum\") );\r\n\tmsg.m_StopAtZero = pPreferences->GetPreferenceChecksum( Script::GenerateCRC(\"stop_at_zero\"), Script::GenerateCRC(\"checksum\") );\r\n\tmsg.m_CTFType = pPreferences->GetPreferenceChecksum( Script::GenerateCRC(\"ctf_game_type\"), Script::GenerateCRC(\"checksum\") );\r\n\t\r\n\t// FCFS functions should only happen on clients\r\n\tDbg_Assert( !gamenet_man->OnServer());\r\n\r\n\tclient = gamenet_man->GetClient( 0 );\r\n\tDbg_Assert( client );\r\n\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof( MsgStartGameRequest );\r\n\tmsg_desc.m_Id = MSG_ID_FCFS_START_GAME;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tclient->EnqueueMessageToServer( &msg_desc );\r\n\r\n\tgamenet_man->m_game_pending = true;\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptFCFSRequestChangeLevel(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 level;\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tMsgIntInfo msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tNet::Client* client;\r\n\r\n\t// Need to limit this option. Make sure a second request doesn't go out while waiting for the first\r\n\t// to complete\r\n\r\n\t// FCFS functions should only happen on clients\r\n\tDbg_Assert( !gamenet_man->OnServer());\r\n\r\n\tlevel = 0;\r\n\tpParams->GetChecksum( Script::GenerateCRC( \"level\" ), &level );\r\n    msg.m_Data = (int) level;\r\n\r\n\tclient = gamenet_man->GetClient( 0 );\r\n\tDbg_Assert( client );\r\n\r\n\tif( level == CRCD(0xb664035d,\"Load_Sk5Ed_gameplay\"))\r\n\t{\r\n\t\tclient->StreamMessageToServer( MSG_ID_LEVEL_DATA, Ed::CParkManager::COMPRESSED_MAP_SIZE, \r\n\t\t\t\t\t\t   Ed::CParkManager::sInstance()->GetCompressedMapBuffer(), \"level data\", vSEQ_GROUP_PLAYER_MSGS );\r\n\t\t\t\t\t\t   \r\n\t\tclient->StreamMessageToServer( MSG_ID_RAIL_DATA, Obj::GetRailEditor()->GetCompressedRailsBufferSize(), \r\n\t\t\t\t\t\t   Obj::GetRailEditor()->GetCompressedRailsBuffer(), \"rail data\", vSEQ_GROUP_PLAYER_MSGS );\r\n    \r\n\t}\r\n\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof( MsgIntInfo );\r\n\tmsg_desc.m_Id = MSG_ID_FCFS_CHANGE_LEVEL;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tclient->EnqueueMessageToServer( &msg_desc );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptFoundServers(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\t\r\n\treturn( gamenet_man->m_servers.CountItems() > 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptCancelJoinServer(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\tgamenet_man->CancelJoinServer();\r\n\tgamenet_man->SetJoinState( vJOIN_STATE_FINISHED );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptReattemptJoinServer(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\tgamenet_man->ReattemptJoin( gamenet_man->GetClient( 0 ));\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptDropPendingPlayers(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\tgamenet_man->DropPartiallyLoadedPlayers();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptToggleProSet(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tint bit;\r\n\tuint32 param_id;\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\tpParams->GetInteger( \"bit\", &bit, Script::ASSERT );\r\n\tpParams->GetChecksum( \"param_id\", &param_id, Script::ASSERT );\r\n    \r\n\tgamenet_man->ToggleProSet( bit, param_id );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptFCFSRequestToggleProSet(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tNet::Client* client;\r\n\tMsgToggleProSet msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tuint32 param_id;\r\n\tint bit;\r\n\r\n\tpParams->GetInteger( \"bit\", &bit, Script::ASSERT );\r\n\tpParams->GetChecksum( \"param_id\", &param_id, Script::ASSERT );\r\n\r\n\tclient = gamenet_man->GetClient( 0 );\r\n\tDbg_Assert( client );\r\n\r\n\tmsg.m_Bit = bit;\r\n\tmsg.m_ParamId = param_id;\r\n\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof( MsgToggleProSet );\r\n\tmsg_desc.m_Id = MSG_ID_FCFS_TOGGLE_PROSET;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tclient->EnqueueMessageToServer( &msg_desc );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptFCFSRequestToggleGoalSelection(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    uint32 goalId;\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tNet::Client* client;\r\n\tMsgIntInfo msg;\r\n\tNet::MsgDesc msg_desc;\r\n\r\n    pParams->GetChecksum( \"name\", &goalId, Script::ASSERT );\r\n\t\r\n\tclient = gamenet_man->GetClient( 0 );\r\n\tDbg_Assert( client );\r\n\r\n\tmsg.m_Data = goalId;\r\n\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof( MsgIntInfo );\r\n\tmsg_desc.m_Id = MSG_ID_FCFS_TOGGLE_GOAL_SELECTION;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\tclient->EnqueueMessageToServer( &msg_desc );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptResetProSetFlags(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tint i;\r\n\r\n\tfor( i = 0; i < vMAX_NUM_PROSETS; i++ )\r\n\t{\r\n\t\tScript::CStruct* pSetParams;\r\n\t\tpSetParams = new Script::CStruct;\r\n\r\n\t\tpSetParams->AddInteger( \"flag\", Script::GetInt( \"FLAG_PROSET1_GEO_ON\" ) + i );\r\n\t\tif( gamenet_man->m_proset_flags.Test( i ))\r\n\t\t{\r\n\t\t\tScript::RunScript( \"SetFlag\", pSetParams );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tScript::RunScript( \"UnSetFlag\", pSetParams );\r\n\t\t}\r\n\r\n\t\tdelete pSetParams;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptHasSignedDisclaimer(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPrefs::Preferences*\tprefs;\r\n\t\r\n\tprefs = gamenet_man->GetNetworkPreferences();\r\n\tuint32 has_signed = prefs->GetPreferenceChecksum( Script::GenerateCRC( \"signed_disclaimer\" ), Script::GenerateCRC( \"checksum\" ));\r\n\t\r\n\treturn ( has_signed == Script::GenerateCRC( \"boolean_true\" ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptEnterSurveyorMode(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tInp::Manager * inp_manager = Inp::Manager::Instance();\r\n\tMlp::Manager* mlp_man = Mlp::Manager::Instance();\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* local_player;\r\n\r\n\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\tif( local_player->IsObserving() || local_player->IsSurveying())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tDbg_Printf( \"Entering surveyor mode\\n\" );\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\tlocal_player->m_observer_logic_task = \r\n\t\t\t\t\tnew Tsk::Task< PlayerInfo > ( PlayerInfo::s_observer_logic_code, *local_player );\r\n\tmlp_man->AddLogicTask( *local_player->m_observer_logic_task );\r\n\tgamenet_man->m_observer_input_handler = new Inp::Handler< Manager > ( 0,  s_observer_input_logic_code, *gamenet_man, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Tsk::BaseTask::Node::vHANDLER_PRIORITY_OBSERVER_INPUT_LOGIC );\r\n\tinp_manager->AddHandler( *gamenet_man->m_observer_input_handler );\r\n\r\n\tlocal_player->m_flags.SetMask( PlayerInfo::mSURVEYING );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptExitSurveyorMode(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* local_player;\r\n\r\n\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\tif( !local_player )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tDbg_Assert( !( local_player->IsObserving()));\r\n\r\n\tif( local_player->IsSurveying() == false )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tDbg_Printf( \"Exiting surveyor mode\\n\" );\r\n\tgamenet_man->ObservePlayer( local_player );\r\n\tdelete local_player->m_observer_logic_task;\r\n\tlocal_player->m_observer_logic_task = NULL;\r\n\tdelete gamenet_man->m_observer_input_handler;\r\n\tgamenet_man->m_observer_input_handler = NULL;\r\n\r\n\tlocal_player->m_flags.ClearMask( PlayerInfo::mSURVEYING );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetReadyToPlay(bool ready_to_play)\r\n{\r\n\tif (ready_to_play == m_ready_to_play) return;\r\n\t\r\n\tm_ready_to_play = ready_to_play;\r\n\t\r\n\t// Dan: moved from the beginning of CSkater::DoServerLogic().  I'm sort of just moving a hack, instead of fixing it...\r\n\t\r\n\t// keep the skater from skating around before he it ready\r\n\tif (!Mdl::Skate::Instance()->GetGameMode()->IsTrue( \"is_frontend\" ))\r\n\t{\r\n\t\tif (m_ready_to_play)\r\n\t\t{\r\n\t\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\t\tuint32 NumSkaters = skate_mod->GetNumSkaters();\r\n\t\t\tfor (uint32 i = 0; i < NumSkaters; ++i)\r\n\t\t\t{\r\n\t\t\t   Obj::CSkater *pSkater = skate_mod->GetSkater(i);\r\n\t\t\t   if (pSkater)\r\n\t\t\t   {\r\n\t\t\t\t   pSkater->UnPause();\r\n\t\t\t   }\t\r\n\t\t\t}\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\t\tuint32 NumSkaters = skate_mod->GetNumSkaters();\r\n\t\t\tfor (uint32 i = 0; i < NumSkaters; ++i)\r\n\t\t\t{\r\n\t\t\t   Obj::CSkater *pSkater = skate_mod->GetSkater(i);\r\n\t\t\t   if (pSkater)\r\n\t\t\t   {\r\n\t\t\t\t   pSkater->Pause();\r\n\t\t\t   }\t\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\t\tManager::GetGoalsLevel( void )\r\n{\r\n\treturn m_goals_level;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tManager::UsingCreatedGoals( void )\r\n{\r\n\t/*uint32 goals_pref;\r\n\r\n\tgoals_pref = m_network_preferences.GetPreferenceChecksum( CRCD(0x38dbe1d0,\"goals\"), CRCD( 0x21902065, \"checksum\" ));\r\n\tif( goals_pref == CRCD(0xe9354db8,\"goals_created\"))\r\n\t{\r\n\t\treturn true;\r\n\t}*/\r\n\r\n\tif( Obj::GetGoalEditor()->CountGoalsForLevel( 0 ) > 0 )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::LoadGoals( uint32 level )\r\n{\r\n\tm_goals_level = level;\r\n\r\n\t// Store the level as the first 4 bytes\r\n\tmemcpy( m_goals_data, &level, sizeof( uint32 ));\r\n\tm_goals_data_size = Obj::GetGoalEditor()->WriteToBuffer( level, (uint8*) ( m_goals_data + sizeof( uint32 )), \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t vMAX_GOAL_SIZE );\r\n\tm_goals_data_size += sizeof( uint32 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\t\tManager::GetGoalsData( void )\r\n{\r\n\treturn m_goals_data;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\tManager::GetGoalsDataSize( void )\r\n{\r\n\treturn m_goals_data_size;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::SetGoalsData( char* data, uint32 level, int size )\r\n{\r\n\tDbg_Assert( size < vMAX_GOAL_SIZE );\r\n\r\n\tmemcpy( m_goals_data, data, size );\r\n\tm_goals_data_size = size;\r\n\tm_goals_level = level;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/GameNet.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tGameNet.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/01/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGame-Side Network Code \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GAMENET_GAMENET_H\r\n#define __GAMENET_GAMENET_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#include <gel/net/net.h>\r\n#include <gel/prefs/prefs.h>\r\n#include <gel/inpman.h>\r\n\r\n#include <gamenet/gamemsg.h>\r\n\r\n#include <sk/objects/skaterflags.h>\r\n#include <sk/modules/skate/skate.h>\r\n\r\n#ifdef __PLAT_NGPS__\r\n//#include <cengine/goaceng.h>\r\n#include <ghttp/ghttp.h>\r\n#include <peer/peer.h>\r\n#include <gamenet/ngps/p_ezcommon.h>\r\n#include <gamenet/ngps/p_netcnfif.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\t  \r\nnamespace\tObj\r\n{\r\n\tclass\tCSkaterProfile;\r\n\tclass\tCCrown;\r\n    class   CMovingObject;\r\n}\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\nenum\r\n{\r\n\tvVERSION_NUMBER = 0x30036,\t// version number. High word is the integer, lo word is the decimal fraction\r\n};\r\n\r\nenum\r\n{\r\n\tvMAX_RANK\t\t\t=\t10,\r\n\tvMAX_GAME_CREDIT\t=\t500,\r\n\tvNUM_RANKED_LEVELS\t=\t12,\r\n\tvMAX_SCORE_CREDIT\t=\t100,\r\n\tvMAX_COMBO_CREDIT\t=\t100,\r\n\tvMAX_RATING\t\t\t= (( vMAX_GAME_CREDIT ) + ( vNUM_RANKED_LEVELS * ( vMAX_SCORE_CREDIT + vMAX_COMBO_CREDIT ))),\r\n};\r\n\r\nenum NetworkMode\r\n{\r\n\tvNO_NET_MODE,\r\n\tvLAN_MODE,\r\n\tvINTERNET_MODE\r\n};\r\n\r\nenum JoinMode\r\n{\r\n\tvJOIN_MODE_PLAY,\r\n\tvJOIN_MODE_OBSERVE\r\n};\r\n\r\nenum\r\n{\r\n\tmSERVER \t= 0x0001,\r\n\tmCLIENT \t= 0x0002,\r\n\tmINTERNET\t= 0x0004,\r\n\tmLAN\t\t= 0x0008,\r\n\t\r\n\tmNETWORK_MODE = mINTERNET | mLAN\r\n};\r\n\t\t\t\t\t\t \r\nenum\r\n{\r\n\tvMAX_LOCAL_CLIENTS\t\t= 2\t// two-player split screen\r\n};\r\n\r\nenum\r\n{\r\n\tvSKILL_LEVEL_1,\r\n\tvSKILL_LEVEL_2,\r\n\tvSKILL_LEVEL_3,\r\n\tvSKILL_LEVEL_4,\r\n\tvSKILL_LEVEL_5,\r\n\t\r\n\tvSKILL_LEVEL_DEFAULT = vSKILL_LEVEL_3\r\n};\r\n\r\nenum\r\n{\r\n\tvDEFERRED_JOIN_FRAMES\t=\t10\r\n};\r\n\r\nenum\r\n{\r\n\tvSCORE_UPDATE_FREQUENCY\t=\t2000\t// update the score every 2 seconds\r\n};\r\n\r\nenum DropReason\r\n{\r\n\tvREASON_QUIT,\r\n\tvREASON_TIMEOUT,\r\n\tvREASON_OBSERVING,\r\n\tvREASON_BANNED,\r\n\tvREASON_KICKED,\r\n\tvREASON_BAD_CONNECTION,\r\n\tvREASON_LEFT_OUT\r\n};\r\n\r\n// Valid fields of object updates\r\nenum\r\n{\r\n\tmUPDATE_FIELD_POS_X\t\t\t= 0x0001,\r\n\tmUPDATE_FIELD_POS_Y \t\t= 0x0002,\r\n\tmUPDATE_FIELD_POS_Z \t\t= 0x0004,\r\n\tmUPDATE_FIELD_ROT_X\t\t\t= 0x0008,\r\n\tmUPDATE_FIELD_ROT_Y\t\t\t= 0x0010,\r\n\tmUPDATE_FIELD_ROT_Z\t\t\t= 0x0020,\r\n\tmUPDATE_FIELD_STATE\t\t\t= 0x0040,\r\n\tmUPDATE_FIELD_FLAGS \t\t= 0x0080,\r\n\tmUPDATE_FIELD_RAIL_NODE\t\t= 0x0100,\r\n};\r\n\r\nenum\r\n{\r\n\tmSTATE_MASK = 0x07,\r\n\tmDOING_TRICK_MASK = 0x80,\r\n};\r\n\r\nenum ServerListState\r\n{\r\n\tvSERVER_LIST_STATE_WAIT,\r\n\tvSERVER_LIST_STATE_INITIALIZE,\r\n\tvSERVER_LIST_STATE_SHUTDOWN,\r\n\tvSERVER_LIST_STATE_STARTING_MOTD,\r\n\tvSERVER_LIST_STATE_GETTING_MOTD,\r\n\tvSERVER_LIST_STATE_TRACK_USAGE,\r\n\tvSERVER_LIST_STATE_SHOW_MOTD,\r\n\tvSERVER_LIST_STATE_RETRY_MOTD,\r\n\tvSERVER_LIST_STATE_FAILED_MOTD,\r\n\tvSERVER_LIST_STATE_TRACKING_USAGE,\r\n\tvSERVER_LIST_STATE_STARTING_LOBBY_LIST,\r\n\tvSERVER_LIST_STATE_GETTING_LOBBY_LIST,\r\n\tvSERVER_LIST_STATE_GOT_LOBBY_LIST,\r\n\tvSERVER_LIST_STATE_FAILED_LOBBY_LIST,\r\n\tvSERVER_LIST_STATE_FILL_LOBBY_LIST,\r\n};\r\n\r\nenum JoinState\r\n{   \r\n\tvJOIN_STATE_WAITING,\r\n\tvJOIN_STATE_CONNECTING,\r\n\tvJOIN_STATE_JOINING,\r\n\tvJOIN_STATE_JOINING_WITH_PASSWORD,\r\n\tvJOIN_STATE_TRYING_PASSWORD,\r\n\tvJOIN_STATE_GOT_PLAYERS,\r\n\tvJOIN_STATE_WAITING_FOR_START_INFO,\r\n\tvJOIN_STATE_CONNECTED,\r\n\tvJOIN_STATE_REFUSED,\r\n\tvJOIN_STATE_FINISHED\r\n};\r\n\r\nenum ObserverCommand\r\n{\r\n\tvOBSERVER_COMMAND_NONE,\r\n\tvOBSERVER_COMMAND_NEXT,\r\n};\r\n\r\nenum HostMode\r\n{\r\n\tvHOST_MODE_SERVE,\r\n\tvHOST_MODE_AUTO_SERVE,\r\n\tvHOST_MODE_FCFS,      \r\n};\r\n\r\nenum\r\n{\r\n\tvSORT_KEY_NAME,\r\n\tvSORT_KEY_PING,\r\n\tvSORT_KEY_NUMPLAYERS,\r\n\tvSORT_KEY_MODE,\r\n\tvSORT_KEY_LEVEL,\r\n\tvSORT_KEY_SKILL,\r\n\tvNUM_SORT_KEYS\r\n};\r\n\r\nenum\r\n{\r\n\tvTEAM_RED,\r\n\tvTEAM_BLUE,\r\n\tvTEAM_GREEN,\r\n\tvTEAM_YELLOW,\r\n\tvMAX_TEAMS,\r\n\r\n\tvNO_TEAM = -1\r\n};\r\n\r\nenum\r\n{\r\n\tvNET_THREAD_STACK_SIZE = ( 32 * 1024 )\r\n};\r\n\r\nenum\r\n{\r\n\tvNUM_CROWN_SPAWN_POINTS\t= 10\r\n};\r\n\r\nenum\r\n{\r\n\tvMAX_MASTER_SERVERS = 10,\r\n\tvMAX_NUM_PROSETS = 7,\r\n\tvMAX_GOAL_SIZE = 6000,\r\n};\r\n\r\nenum\r\n{\r\n\tvGAMESPY_PRODUCT_ID = 10160\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass LobbyMan;\r\nclass ContentMan;\r\nclass BuddyMan;\r\nclass StatsMan;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  NewPlayerInfo  : public Spt::Class\r\n{\r\n\t\r\n\t\r\n\tpublic:\r\n\t\tNewPlayerInfo();\r\n\t\t~NewPlayerInfo();\r\n\t\t\r\n\tpublic:\r\n\t\tchar\t\t\t\t\tName[ vMAX_PLAYER_NAME_LEN + 1 ];\r\n\t\tchar\t\t\t\t\tObjID;\r\n\t\tNet::Conn*\t\t\t\tConn;\r\n\t\tunsigned int\t\t\tAllowedJoinFrame;\r\n\t\tObj::CSkaterProfile*\tmpSkaterProfile;\r\n\t\tint \t\t\t\t\tFlags;\r\n\t\tint\t\t\t\t\t\tJumpInFrame;\r\n\t\tint\t\t\t\t\t\tTeam;\r\n\t\tint\t\t\t\t\t\tProfile;\r\n\t\tint\t\t\t\t\t\tRating;\r\n\t\tint\t\t\t\t\t\tScore;\r\n\t\tuint32\t\t\t\t\tVehicleControlType;\r\n};\r\n\r\nclass TriggerEvent : public Lst::Node< TriggerEvent >\r\n{   \r\npublic:\r\n\t\tTriggerEvent( void ) \r\n\t\t\t: Lst::Node< TriggerEvent > ( this ) {}\r\n\r\n\t\tint\t\t\t\t\t\tm_Node;\r\n\t\tint\t\t\t\t\t\tm_ObjID;\r\n\t\tuint32\t\t\t\t\tm_Script;\r\n};\r\n\r\nclass LastSentProps\r\n{\r\npublic:\r\n\r\n\tunsigned int\tm_LastSkaterUpdateTime[Mdl::Skate::vMAX_SKATERS];\t// The last time of update\r\n\tchar\t\t\tm_LastSkaterTerrain[Mdl::Skate::vMAX_SKATERS];\t\t// The last terrain of each skater\r\n\tchar\t\t\tm_LastSkaterWalking[Mdl::Skate::vMAX_SKATERS];\t\t// The last walking of each skater\r\n\tchar\t\t\tm_LastSkaterDriving[Mdl::Skate::vMAX_SKATERS];\t\t// The last driving of each skater\r\n\tshort\t\t\tm_LastSkaterPosUpdate[Mdl::Skate::vMAX_SKATERS][3];\t// The last pos of each skater\r\n\tshort\t\t\tm_LastSkaterRotUpdate[Mdl::Skate::vMAX_SKATERS][3];\t// The last pos of each skater\r\n    Flags< int >\tm_LastSkaterFlagsUpdate[Mdl::Skate::vMAX_SKATERS];\t// The last flags \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t// we sent to each skater\r\n\tFlags< int >\tm_LastEndRunFlagsUpdate[Mdl::Skate::vMAX_SKATERS];\t// The last end run flags \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t// we sent to each skater\r\n\tchar\t\t\tm_LastSkaterStateUpdate[Mdl::Skate::vMAX_SKATERS];\t// The last state\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// we sent to each skater\r\n\tchar\t\t\tm_LastDoingTrickUpdate[Mdl::Skate::vMAX_SKATERS];\t// The last \"doing trick\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// state we sent to each skater\r\n\tchar\t\t\tm_LastDrivingUpdate[Mdl::Skate::vMAX_SKATERS];\t\t// The last \"driving\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// state we sent to each skater\r\n\tsint16\t\t\tm_LastRailNodeUpdate[Mdl::Skate::vMAX_SKATERS];\t\t// The last rail node sent to each skater\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass PlayerInfo : public Lst::Node< PlayerInfo >\r\n{\r\npublic:\r\n\t\r\n\tfriend class Manager;\r\n\r\n\tenum SkaterFlagMasks\r\n\t{\r\n\t\tmTENSE = nBit( Obj::TENSE ),\r\n\t\t// mSWITCH = nBit( Obj::SWITCH ),\r\n\t\t// mLEAN = nBit( Obj::LEAN ),\r\n\t\t// mTENSE_ON_GROUND = nBit( Obj::TENSE_ON_GROUND ),\r\n\t\tmFLIPPED = nBit( Obj::FLIPPED ),\r\n\t\tmVERT_AIR = nBit( Obj::VERT_AIR),\r\n\t\tmTRACKING_VERT = nBit( Obj::TRACKING_VERT ),\r\n\t\tmLAST_POLY_WAS_VERT = nBit( Obj::LAST_POLY_WAS_VERT ),\r\n\t\tmCAN_BREAK_VERT = nBit( Obj::CAN_BREAK_VERT ),\r\n\t\tmCAN_RERAIL = nBit( Obj::CAN_RERAIL ),\r\n\t\t// mSHOULD_END_RUN = nBit( Obj::SHOULD_END_RUN ),\r\n\t\t// mFINISHED_END_OF_RUN = nBit( Obj::FINISHED_END_OF_RUN ),\r\n\t\tmRAIL_SLIDING = nBit( Obj::RAIL_SLIDING ),\r\n\t\tmCAN_HIT_CAR = nBit( Obj::CAN_HIT_CAR ),\r\n\t\tmAUTOTURN = nBit( Obj::AUTOTURN ),\r\n\t\tmIS_BAILING = nBit( Obj::IS_BAILING ),\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n\t\tmLOCAL_PLAYER\t=\t0x00000001,\r\n\t\tmNON_COLLIDABLE\t=\t0x00000002,\t// For use, for example, after skater is knocked down so you don't\r\n\t\t\t\t\t\t\t\t\t// knock him down over and over\r\n\t\tmOBSERVER\t\t=\t0x00000004,\r\n\t\tmPENDING_PLAYER\t=\t0x00000008,\t// Player is observing until the game finishes\r\n\t\tmJUMPING_IN\t\t=\t0x00000010,\t// Transitioning from pending to playing\r\n\t\tmFULLY_IN\t\t=\t0x00000020,\t// Player is fully in the game\r\n\t\tmHAS_PLAYER_INFO=\t0x00000040,\t// Player has fully received initial player info packet(s)\r\n\t\tmKING_OF_THE_HILL=\t0x00000080,\t// Player is king of the hill\r\n\t\tmRUN_ENDED\t\t=\t0x00000100,\t// Player's run has ended\r\n\t\tmSERVER_PLAYER\t=\t0x00000200,\t// The player acting as host\r\n\t\tmMARKED_PLAYER\t=\t0x00000400,\t// The player is marked for an operation\r\n\t\tmHAS_RED_FLAG\t=\t0x00000800,\t// The player has the red flag\r\n\t\tmHAS_BLUE_FLAG\t=\t0x00001000,\t// The player has the blue flag\r\n\t\tmHAS_GREEN_FLAG\t=\t0x00002000,\t// The player has the green flag\r\n\t\tmHAS_YELLOW_FLAG=\t0x00004000,\t// The player has the yellow flag\r\n\t\tmRESTARTING\t\t=\t0x00008000,\t// The player is restarting\r\n\t\tmSURVEYING\t\t=\t0x00010000,\t// The player is surveying the playing field\r\n\r\n\t\tmHAS_ANY_FLAG = mHAS_RED_FLAG | mHAS_BLUE_FLAG | mHAS_GREEN_FLAG | mHAS_YELLOW_FLAG,\r\n\t};\r\n\t\r\n\tPlayerInfo( int flags );\r\n\t\r\n\tvoid\t\t\tSetSkater( Obj::CSkater* skater );\r\n\tvoid\t\t\tCopyProfile( Obj::CSkaterProfile* pSkaterProfile );\r\n\r\n\tvoid\t\t\tSetFaceData( uint8* face_data, int size );\r\n\tuint8*\t\t\tGetFaceData( void );\r\n\t\r\n\tbool\t\t\tIsLocalPlayer( void );\r\n\tbool\t\t\tIsServerPlayer( void );\r\n\tbool\t\t\tIsObserving( void );\r\n\tbool\t\t\tIsSurveying( void );\r\n\r\n\tvoid\t\t\tMarkAsServerPlayer( void );\r\n\tvoid\t\t\tMarkAsNotServerPlayer( void );\r\n\tvoid\t\t\tMarkAsReady( int time );\r\n\tvoid\t\t\tMarkAsNotReady( int time );\r\n\tvoid\t\t\tMarkAsRestarting( void );\r\n\tvoid\t\t\tSetReadyQueryTime( int time );\r\n\r\n\tvoid\t\t\tMarkAsNonCollidable( void );\r\n\tvoid\t\t\tClearNonCollidable( void );\r\n\tbool\t\t\tIsNonCollidable( void );\r\n\r\n\tvoid\t\t\tMarkAsFullyIn( void );\r\n\tbool\t\t\tIsFullyIn( void );\r\n\r\n\tvoid\t\t\tMarkAsKing( bool mark );\r\n\tbool\t\t\tIsKing( void );\r\n\r\n\tbool\t\t\tHasCTFFlag( void );\r\n\tint\t\t\t\tHasWhichFlag( void );\r\n\tvoid\t\t\tTookFlag( int team );\r\n\tvoid\t\t\tStoleFlag( int team );\r\n\tvoid\t\t\tCapturedFlag( int team );\r\n\tvoid\t\t\tRetrievedFlag( void );\r\n\tvoid\t\t\tClearCTFState( void );\r\n\r\n\tbool\t\t\tIsVulnerable( void );\r\n\tvoid\t\t\tResetProjectileVulnerability( void );\r\n\tvoid\t\t\tSetHitTime( Tmr::Time hit_time );\r\n\r\n\tbool\t\t\tIsPendingPlayer( void );\r\n\r\n\tint\t\t\t\tGetLastObjectUpdateID( void );\r\n\tvoid\t\t\tSetLastObjectUpdateID( int id );\r\n\tint\t\t\t\tGetMaxObjectUpdates( void );\r\n\r\n\tint\t\t\t\tGetConnHandle( void );\r\n\tint\t\t\t\tGetSkaterNumber( void );\r\n\r\n\tObj::CSkater*\tm_Skater;\r\n\tNet::Conn*\t\tm_Conn;\r\n\tint\t\t\t\tm_Score;\r\n\tint\t\t\t\tm_BestCombo;\r\n\tint\t\t\t\tm_Profile;\r\n\tint\t\t\t\tm_Rating;\r\n\tint\t\t\t\tm_Team;\r\n\tchar\t\t\tm_Name[ vMAX_PLAYER_NAME_LEN + 1 ];\r\n\tuint32\t\t\tm_VehicleControlType;\r\n\tObj::CSkaterProfile*\tmp_SkaterProfile;\t\t\t\t\t\t\t// Appearance information\r\n    \r\n\tLastSentProps\tm_LastSentProps;\r\n\r\nprotected:\r\n\t\t\t\t\t~PlayerInfo();\r\nprivate:\r\n\tstatic\tTsk::Task< PlayerInfo >::Code   \ts_observer_logic_code;\r\n\r\n\tFlags< int >\tm_flags;\r\n\tint\t\t\t\tm_latest_ready_query;\r\n\tint\t\t\t\tm_jump_in_frame;\r\n\tTmr::Time\t\tm_last_bail_time;\r\n\tTmr::Time\t\tm_last_hit_time;\r\n\tint\t\t\t\tm_last_object_update_id;\r\n\tuint8*\t\t\tm_face_data;\r\n\r\n\tTsk::Task< PlayerInfo >*\t\tm_observer_logic_task;\r\n};\r\n\r\nclass ServerInfo : public Lst::Node< ServerInfo >\r\n{\r\n\tpublic:\r\n\t\tServerInfo( void );\r\n\t\t~ServerInfo( void );\r\n\r\n\t\tvoid\tAddPlayer( char* name, int rating = 0 );\r\n\t\tchar*\tGetPlayerName( int index );\r\n\t\tint\t\tGetPlayerRating( int index );\r\n\t\tvoid\tClearPlayerNames( void );\r\n\r\n\t\tchar\tm_Name[vMAX_SERVER_NAME_LEN + 1];\r\n\t\tint\t\tm_Ip;\r\n\t\tint \tm_Port;\r\n\t\tint\t\tm_Latency;\r\n\t\tint\t\tm_NumPlayers;\r\n\t\tint\t\tm_MaxPlayers;\r\n\t\tint\t\tm_NumObservers;\r\n\t\tint\t\tm_MaxObservers;\r\n\t\tchar\tm_Level[32];\r\n\t\tchar\tm_Mode[32];\r\n\t\tbool\tm_Password;\r\n\t\tbool\tm_GameStarted;\r\n\t\tchar\tm_SkillLevel;\r\n\t\tint\t\tm_HostMode;\r\n\t\tbool\tm_Ranked;\r\n\t\tbool\tm_CanDirectConnect;\r\n\t\tbool\tm_Listed;\r\n\t\tbool\tm_InFocus;\r\n\t\tbool\tm_HasBasicInfo;\r\n\t\tbool\tm_HasFullInfo;\r\n#ifdef __PLAT_NGPS__\r\n\t\tSBServer m_GServer;\r\n#endif\r\n#ifdef __PLAT_XBOX__\r\n\t\tXNKID\t\tm_XboxKeyId;\r\n\t\tXNKEY\t\tm_XboxKey;\r\n\t\tXNADDR\t\tm_XboxAddr;\r\n#endif // __PLAT_XBOX__\r\n\r\n\tprivate:\r\n\t\tLst::Head< PlayerInfo > m_players;\r\n};\r\n\r\nclass LobbyInfo : public Lst::Node< LobbyInfo >\r\n{\r\n\tpublic:\r\n\t\tLobbyInfo( void );\r\n\r\n\t\tchar\tm_Name[64];\r\n\t\tint\t\tm_GroupId;\r\n\t\tint\t\tm_NumServers;\r\n\t\tint \tm_MaxServers;\r\n\t\tint\t\tm_MinRating;\r\n\t\tint\t\tm_MaxRating;\r\n\t\tbool\tm_Full;\r\n\t\tbool\tm_OffLimits;\r\n\t\tbool\tm_Official;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  Manager  : public Spt::Class\r\n{\r\n\t\r\npublic:\r\n\tvoid\t\t\t\tUsePreferences( void );\r\n\r\n//\tClient and Server Access\r\n/////////////////////////////\r\n\tNet::Server*\t\tSpawnServer( bool local, bool secure );\r\n\tNet::Client*\t\tSpawnClient( bool broadcast, bool local, bool secure, int index );\r\n\tNet::Client*\t\tSpawnMatchClient( void );\r\n\tvoid\t\t\t\tSpawnAutoServer( void );\r\n\r\n\tvoid\t\t\t\tServerShutdown( void );\r\n\tvoid\t\t\t\tClientShutdown( void );\r\n\tvoid\t\t\t\tMatchClientShutdown( void );\r\n\tvoid\t\t\t\tAutoServerShutdown( void );\r\n\r\n\tNet::Server*\t\tGetServer( void );\r\n\tNet::Client*\t\tGetClient( int index );\r\n\tNet::Client*\t\tGetMatchClient( void );\r\n\r\n\tint\t\t\t\t\tGetJoinIP( void );\r\n\tint\t\t\t\t\tGetJoinPrivateIP( void );\r\n\tint\t\t\t\t\tGetJoinPort( void );\r\n\tvoid\t\t\t\tSetJoinIP( int ip );\r\n\tvoid\t\t\t\tSetJoinPrivateIP( int ip );\r\n\tvoid\t\t\t\tSetJoinPort( int port );\r\n\r\n//\tPlayer Access\r\n/////////////////////////////\r\n\tvoid\t\t\t\tLoadPendingPlayers( void );\r\n\tint\t\t\t\t\tNumPartiallyLoadedPlayers( void );\r\n\tvoid\t\t\t\tDropPartiallyLoadedPlayers( void );\r\n\tvoid\t\t\t\tDropPlayer( PlayerInfo* info, DropReason reason );\r\n\tvoid\t\t\t\tResetPlayers( void );\r\n\tint\t\t\t\t\tGetMaxPlayers( void );\r\n\tint\t\t\t\t\tGetMaxObservers( void );\r\n\tvoid\t\t\t\tSetMaxPlayers( int max_players );\r\n\tvoid\t\t\t\tSetMaxObservers( int max_observers );\r\n\tint\t\t\t\t\tGetNumPlayers( void );\r\n\tint\t\t\t\t\tGetNumObservers( void );\r\n\tint\t\t\t\t\tGetNumTeams( void );\r\n\tint\t\t\t\t\tNumTeamMembers( int team );\r\n\tvoid\t\t\t\tCreateTeamFlags( int num_teams );\r\n\tvoid\t\t\t\tClientAddNewPlayer( NewPlayerInfo* new_player );\r\n\tvoid\t\t\t\tDeferredNewPlayer( NewPlayerInfo* new_player, \r\n\t\t\t\t\t\t\t\t\t\t   int num_frames = vDEFERRED_JOIN_FRAMES );\r\n\tPlayerInfo*\t\t\tNewPlayer( Obj::CSkater* skater, Net::Conn* conn, int flags = 0 );\r\n\tvoid\t\t\t\tAddPlayerToList( PlayerInfo* player );\r\n\tvoid\t\t\t\tDestroyPlayer( PlayerInfo* player );\r\n    \r\n\tint\t\t\t\t\tGetNextPlayerObjectId( void );\r\n\tObj::CSkater*\t\tGetSkaterByConnection( Net::Conn* conn );          \r\n\tPlayerInfo*\t\t\tFirstPlayerInfo( Lst::Search< PlayerInfo > &sh, bool include_observers = false );\r\n\tPlayerInfo*\t\t\tNextPlayerInfo( Lst::Search< PlayerInfo > &sh, bool include_observers = false );\r\n\tPlayerInfo*\t\t\tGetPlayerByConnection( Net::Conn* conn );          \r\n\tPlayerInfo*\t\t\tGetPlayerByObjectID( unsigned short obj_id );\r\n    \r\n\tPlayerInfo*\t\t\tGetLocalPlayer( void );\r\n\tPlayerInfo*\t\t\tGetServerPlayer( void );\r\n\tPlayerInfo*\t\t\tGetNextPlayerToObserve( void );\r\n\tPlayerInfo*\t\t\tGetCurrentlyObservedPlayer( void );\r\n\tPlayerInfo*\t\t\tGetKingOfTheHill( void );\r\n\t\r\n\tNewPlayerInfo*\t\tFirstNewPlayerInfo( Lst::Search< NewPlayerInfo > &sh );\r\n\tNewPlayerInfo*\t\tNextNewPlayerInfo( Lst::Search< NewPlayerInfo > &sh );\r\n\tNewPlayerInfo*\t\tGetNewPlayerInfoByObjectID( unsigned short obj_id );\r\n\tvoid\t\t\t\tDestroyNewPlayer( NewPlayerInfo* new_player );\r\n\r\n\tbool\t\t\t\tSendFaceDataToServer( void );\r\n\tvoid\t\t\t\tSendFaceDataToPlayer( PlayerInfo* player );\r\n\r\n//\tModes and Options\r\n/////////////////////////////\r\n\r\n\tchar*\t\t\t\tGetLevelName( bool get_created_park_name = true );\r\n\tchar*\t\t\t\tGetGameModeName( void );\r\n\tchar*\t\t\t\tGetPassword( void );\r\n\tint\t\t\t\t\tGetSkillLevel( void );\r\n\tvoid\t\t\t\tSetNetworkMode( NetworkMode mode );\r\n    void\t\t\t\tSetJoinMode( JoinMode mode );\r\n\tJoinMode\t\t\tGetJoinMode( void );\r\n\tvoid\t\t\t\tSetServerMode( bool on );\r\n\tHostMode\t\t\tGetHostMode( void );\r\n\tvoid\t\t\t\tSetHostMode( HostMode mode );\r\n\tbool\t\t\t\tPlayerCollisionEnabled( void );\r\n\tbool\t\t\t\tShouldDisplayTeamScores( void );\r\n\tPrefs::Preferences*\tGetNetworkPreferences( void );\r\n\tPrefs::Preferences*\tGetTauntPreferences( void );\r\n\tuint32\t\t\t\tGetNetworkLevelId( void );\r\n\tvoid\t\t\t\tSetNetworkGameId( unsigned char id );\r\n\tunsigned char\t\tGetNetworkGameId( void );\r\n\tconst char*\t\t\tGetNameFromArrayEntry( char* array_name, uint32 checksum );\r\n\tint\t\t\t\t\tGetIntFromArrayEntry( char* array_name, uint32 checksum, uint32 field_checksum );\r\n\tbool\t\t\t\tInNetMode( void );\r\n\tbool\t\t\t\tInNetGame( void );\r\n\tbool\t\t\t\tInLanMode( void );\r\n\tbool\t\t\t\tInInternetMode( void );\r\n\tbool\t\t\t\tOnServer( void );\r\n\tbool\t\t\t\tOnClient( void );\r\n\t\r\n\tvoid\t\t\t\tJoinServer( bool observe_only, unsigned long ip, unsigned short port, int index );\r\n\tvoid\t\t\t\tCancelJoinServer( void );\r\n\tvoid\t\t\t\tReattemptJoin( Net::App* client );\r\n\tvoid\t\t\t\tReattemptJoinWithPassword( char* password );\r\n\tvoid\t\t\t\tFindServersOnLAN( void );\r\n\tvoid\t\t\t\tDisconnectFromServer( void );\r\n\tvoid\t\t\t\tCleanupPlayers();\r\n\t\r\n\tvoid\t\t\t\tRequestObserverMode( void );\r\n\tvoid\t\t\t\tObservePlayer( PlayerInfo* player );\r\n\tvoid\t\t\t\tEnterObserverMode( void );\r\n\t\r\n\tvoid\t\t\t\tChooseNewServerPlayer( void );\r\n\t\r\n\tvoid\t\t\t\tStartNetworkLobby( void );\r\n\tvoid\t\t\t\tStartNetworkGame( void );\r\n\tbool\t\t\t\tShouldStopAtZero( void );\r\n\t\r\n\tvoid\t\t\t\tToggleProSet( char bit, uint32 param_id );\r\n//\tScript Functions\r\n/////////////////////////////\t\r\n    \r\n\tstatic\tbool\t\tScriptJoinTeam(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptSetNumTeams(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptGetNumTeams(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptGetNumPlayersOnTeam(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptGetMyTeam(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptInGroupRoom(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptConnectedToPeer(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptIsHost(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptIsAutoServing(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptChangeLevelPending(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool \t\tScriptSetJoinMode(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool \t\tScriptSetHostMode(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptChooseServer(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptRetrieveServerInfo(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptDescribeServer(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptFoundServers(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic \tbool\t\tScriptRemovePlayer(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic \tbool\t\tScriptAllPlayersAreReady(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptCreatePlayerOptions(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic \tbool\t\tScriptCancelRemovePlayer(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic \tbool\t\tScriptKickPlayer(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic \tbool\t\tScriptBanPlayer(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptStartNetworkGame(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptNetworkGamePending(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptEndNetworkGame(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptSendGameOverToObservers(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptSpawnCrown(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptStartCTFGame(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptEndCTFGame(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptTookFlag(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptCapturedFlag(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptRetrievedFlag(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptHasFlag(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptTeamFlagTaken(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptDisplayFlagBaseWarning(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptAlreadyGotMotd(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptDownloadMotd(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptAlreadySignedIn(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptSignOut(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptJoinServerComplete(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptEnteredNetworkGame(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptJustStartedNetGame(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptChooseAccount(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptCancelJoinServer(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptReattemptJoinServer(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptDropPendingPlayers(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic \tbool\t\tScriptToggleProSet(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic \tbool\t\tScriptResetProSetFlags(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptFCFSRequestStartGame(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptFCFSRequestChangeLevel(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptFCFSRequestToggleProSet(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptFCFSRequestToggleGoalSelection(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool \t\tScriptHasSignedDisclaimer(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\n\tstatic\tbool\t\tScriptGetNumServersInLobby(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\n\tstatic\tbool\t\tScriptEnterSurveyorMode(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptExitSurveyorMode(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\n\t//void\t\t\t\tRequestMatchmakerConnect( void );\r\n\tvoid\t\t\t\tPostGame( void );\r\n\tvoid\t\t\t\tSetLevel( uint32 level_id );\r\n\tuint32\t\t\t\tGetLevelFromPreferences( void );\r\n\tint\t\t\t\t\tGetFireballLevelFromPreferences( void );\r\n\tuint32\t\t\t\tGetGameTypeFromPreferences( void );\r\n\r\n\tvoid\t\t\t\tToggleMetrics( void );\r\n\tvoid\t\t\t\tToggleScores( void );\r\n\tvoid\t\t\t\tTogglePlayerNames( void );\r\n\tbool\t\t\t\tShouldDrawPlayerNames( void );\r\n\r\n\tvoid\t\t\t\tCreateNetPanelMessage( \tbool broadcast, uint32 message_checksum, char* string_parm_1 = NULL,\r\n\t\t\t\t\t\t\t\t\t\t\t\tchar* string_param_2 = NULL, Obj::CMovingObject* object = NULL, char* properties = NULL,\r\n\t\t\t\t\t\t\t\t\t\t\t\tbool important = false, int time = 2000 );\r\n\tbool\t\t\t\tReadyToPlay( void ) { return m_ready_to_play; }\r\n\tvoid\t\t\t\tSetReadyToPlay( bool ready_to_play );\r\n\tvoid\t\t\t\tRespondToReadyQuery( void );\r\n\t\t\r\n\tbool\t\t\t\tShouldSendScoreUpdates( void );\r\n\tvoid\t\t\t\tSetLastScoreUpdateTime( int time );\r\n\tint\t\t\t\t\tGetLastScoreUpdateTime( void );\r\n\tint\t\t\t\t\tGetTeamScore( int team_id );\r\n\tint\t\t\t\t\tGetPlayerScore( int obj_id );\r\n\r\n\tvoid\t\t\t\tMarkReceivedFinalScores( bool received );\r\n\tbool\t\t\t\tHaveReceivedFinalScores( void );\r\n\r\n\tvoid\t\t\t\tSetCurrentLeader( PlayerInfo* player );\r\n\tPlayerInfo*\t\t\tGetCurrentLeader( void );\r\n\r\n\tvoid\t\t\t\tSetCurrentLeadingTeam( int team );\r\n\tint\t\t\t\t\tGetCurrentLeadingTeam( void );\r\n\r\n\tvoid\t\t\t\tAddSpawnedTriggerEvent( int node, int obj_id, uint32 script );\r\n\tvoid\t\t\t\tClearTriggerEventList( void );\r\n\tvoid\t\t\t\tSetProSetFlags( char flags );\r\n\t\r\n//\tServer List Functions\r\n/////////////////////////////\t\r\n\t\r\n\r\n\tvoid\t\t\t\tSetServerListState( ServerListState state );\r\n\tvoid\t\t\t\tSetNextServerListState( ServerListState state );\r\n\tServerListState\t\tGetServerListState( void );\r\n\tServerListState\t\tGetNextServerListState( void );\r\n\r\n\tbool\t\t\t\tStartServerList( void );\r\n\tvoid\t\t\t\tStopServerList( void );\r\n\tvoid\t\t\t\tSortPreviousKey( void );\r\n\tvoid\t\t\t\tSortNextKey( void );\r\n\tvoid\t\t\t\tSortServerList( void );\r\n#ifdef __PLAT_XBOX__\r\n\tbool\t\t\t\tServerAlreadyInList( char* name, XNADDR* xbox_addr );\r\n#else\r\n\tbool\t\t\t\tServerAlreadyInList( char* name, int ip );\r\n#endif\r\n\tvoid\t\t\t\tRefreshServerList( bool force_refresh = false );\r\n\t\r\n\tvoid\t\t\t\tSetServerFocus( ServerInfo* server );\r\n\tvoid\t\t\t\tClearServerFocus( void );\r\n\tServerInfo*\t\t\tGetServerFocus( void );\r\n\tint\t\t\t\t\tNumServersListed( void );\r\n\tvoid\t\t\t\tAddServerToMenu( ServerInfo* server, int index );\r\n\t\r\n\tvoid\t\t\t\tClearServerList( bool refocus = true );\r\n\tvoid\t\t\t\tFreeServerList( void );\r\n\tServerInfo*\t\t\tGetServerInfo( uint32 id );\r\n\r\n\t\r\n\r\n\tvoid\t\t\t\tSendChatMessage( char* message );\r\n\r\n\tvoid\t\t\t\tSetJoinState( JoinState state );\r\n\tJoinState\t\t\tGetJoinState( void );\r\n\r\n\tvoid\t\t\t\tSetObserverCommand( ObserverCommand command );\r\n\tObserverCommand\t\tGetObserverCommand( void );\r\n\r\n\tbool\t\t\t\tConnectToInternet( uint32 success_script, uint32 failure_script );\r\n\tvoid\t\t\t\tDisconnectFromInternet( uint32 callback_script = 0 );\r\n\tvoid\t\t\t\tRemoveModemStateTask( void );\r\n\tvoid\t\t\t\tCancelConnectToInternet( void );\r\n\r\n\tvoid\t\t\t\tRandomizeSkaterStartingPoints( void );\r\n\tvoid\t\t\t\tSetSkaterStartingPoints( int* start_points );\r\n\tint\t\t\t\t\tGetSkaterStartingPoint( int skater_id );\r\n\r\n\tvoid\t\t\t\tLaunchQueuedScripts( void );\r\n\r\n\tObj::CCrown*\t\tGetCrown( void );\r\n\tvoid\t\t\t\tSetCrownSpawnPoint( char spawn_point ); \r\n\tvoid\t\t\t\tCleanupObjects( void );\r\n\r\n\tvoid\t\t\t\tSendEndOfRunMessage( void );\r\n\tbool\t\t\t\tHaveSentEndOfRunMessage(  void );\r\n\tbool\t\t\t\tGameIsOver( void );\r\n\tvoid\t\t\t\tMarkGameOver( void );\r\n\tvoid\t\t\t\tClearGameOver( void );\r\n\r\n\tchar*\t\t\t\tGetNetThreadStack( void );\r\n\tvoid\t\t\t\tSetNetThreadId( int net_thread_id );\r\n\tint\t\t\t\t\tGetNetThreadId( void );\r\n\r\n\tbool\t\t\t\tHasCheatingOccurred( void );\r\n\tvoid\t\t\t\tClearCheating( void );\r\n\tvoid\t\t\t\tCheatingOccured( void );\r\n\r\n\tbool\t\t\t\tUsingCreatedGoals( void );\r\n\tvoid\t\t\t\tLoadGoals( uint32 level );\r\n\tuint32\t\t\t\tGetGoalsLevel( void );\r\n\tchar*\t\t\t\tGetGoalsData( void );\r\n\tint\t\t\t\t\tGetGoalsDataSize( void );\r\n\tvoid\t\t\t\tSetGoalsData( char* data, uint32 level, int size );\r\n\r\n\tLobbyMan*\t\t\tmpLobbyMan;\r\n\tContentMan*\t\t\tmpContentMan;\r\n#ifdef __PLAT_XBOX__\r\n\tbool\t\t\t\tm_XboxKeyRegistered;\r\n\tXNKID\t\t\t\tm_XboxKeyId;\t\r\n\tclass AuthMan\t\t*mpAuthMan;\r\n\tclass BuddyMan\t\t*mpBuddyMan;\r\n\tclass VoiceMan\t\t*mpVoiceMan;\r\n#else\r\n\tBuddyMan* \t\t\tmpBuddyMan;\r\n\tStatsMan*\t\t\tmpStatsMan;\r\n#endif\r\n\r\nprivate:\r\n\tManager( void );\r\n\t~Manager( void );\r\n\t\r\n\tvoid\t\t\t\tfree_all_players( void );\r\n\tvoid\t\t\t\tfree_all_pending_players( void );\r\n\tbool\t\t\t\tok_to_join( int& reason, MsgConnectInfo* connect_msg, Net::Conn* conn );\r\n\r\n\tNet::Server*\tm_server;\r\n\tNet::Client*\tm_client[vMAX_LOCAL_CLIENTS];\r\n\tNet::Client* \tm_match_client;\r\n    \r\n\tuint32\t\t\tm_gamemode_id;\r\n\tuint32 \t\t\tm_level_id;\r\n\tunsigned char\tm_game_id;\r\n\tunsigned char\tm_last_end_of_run_game_id;\r\n\tbool\t\t\tm_game_over;\r\n\tbool\t\t\tm_cheating_occurred;\r\n\r\n\tJoinMode\t\tm_join_mode;\r\n\tHostMode\t\tm_host_mode;\r\n\t\r\n\tbool\t\t\tm_received_final_scores;\r\n\r\n\tbool\t\t\tm_metrics_on;\r\n\tbool\t\t\tm_scores_on;\r\n\tbool\t\t\tm_draw_player_names;\r\n\r\n\tint\t\t\t\tm_skater_starting_points[Mdl::Skate::vMAX_SKATERS];\r\n\tint\t\t\t\tm_crown_spawn_point;\r\n\r\n\tObj::CCrown* \tm_crown;\r\n\r\n\tstatic\tTsk::Task< Manager >::Code\ts_modem_state_code;\r\n\tstatic\tTsk::Task< Manager >::Code \ts_timeout_connections_code;\r\n\tstatic\tTsk::Task< Manager >::Code \ts_render_metrics_code;\r\n\tstatic\tTsk::Task< Manager >::Code \ts_render_scores_code;\r\n\tstatic\tTsk::Task< Manager >::Code \ts_server_add_new_players_code;\r\n\tstatic\tTsk::Task< Manager >::Code \ts_client_add_new_players_code;\r\n\tstatic \tTsk::Task< Manager >::Code\ts_enter_chat_code;\r\n\tstatic\tTsk::Task< Manager >::Code\ts_join_timeout_code;\r\n\tstatic \tTsk::Task< Manager >::Code\ts_server_list_state_code;\r\n\tstatic \tTsk::Task< Manager >::Code\ts_join_state_code;\r\n\tstatic\tTsk::Task< Manager >::Code\ts_start_network_game_code;\r\n\tstatic\tTsk::Task< Manager >::Code\ts_change_level_code;\r\n    static  Tsk::Task< Manager >::Code\ts_auto_refresh_code;\r\n\tstatic  Tsk::Task< Manager >::Code\ts_auto_server_code;\r\n\tstatic\tTsk::Task< Manager >::Code\ts_ctf_logic_code;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_disconn_request;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_find_server;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_connection;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_join_request;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_join_accepted;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_wait_n_seconds;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_new_player;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_game_info;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_kill_flags;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_select_goals;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_change_level;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_request_level;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_new_level;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_level_data;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_rail_data;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_goals_data;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_client_proceed;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_join_refused;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_join_proceed;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_observe;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_server_response;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_observe_proceed;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_observe_refused;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_ready_query;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_ready_response;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_player_info_ack_req;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_player_info_ack;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_new_king;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_stole_flag;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_took_flag;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_captured_flag;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_retrieved_flag;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_player_restarted;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_dropped_crown;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_dropped_flag;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_run_ended;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_game_over;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_end_game;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_object_update;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_panel_message;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_auto_server_notification;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_fcfs_assignment;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_fcfs_request;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_team_change_request;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_team_change;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_set_num_teams;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_chat;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_beat_goal;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_beat_goal_relay;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_started_goal;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_started_goal_relay;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_toggle_proset;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_challenge;\r\n\t\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_challenge_response;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_cheat_checksum_request;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_cheat_checksum_response;\r\n\tstatic Net::MsgHandlerCode\t\t\ts_handle_level_data_request;\r\n\r\n\tTsk::Task< Manager >\t*m_timeout_connections_task;\r\n\tTsk::Task< Manager >\t*m_render_metrics_task;\r\n\tTsk::Task< Manager >\t*m_render_scores_task;\r\n\tTsk::Task< Manager >\t*m_server_add_new_players_task;\r\n\tTsk::Task< Manager >\t*m_client_add_new_players_task;\r\n\tTsk::Task< Manager >\t*m_enter_chat_task;\r\n\tTsk::Task< Manager >\t*m_modem_state_task;\r\n\tTsk::Task< Manager >\t*m_join_timeout_task;\r\n\tTsk::Task< Manager > \t*m_server_list_state_task;\r\n\tTsk::Task< Manager > \t*m_join_state_task;\r\n\tTsk::Task< Manager > \t*m_start_network_game_task;\r\n\tTsk::Task< Manager > \t*m_change_level_task;\r\n    Tsk::Task< Manager >\t*m_auto_refresh_task;\r\n\tTsk::Task< Manager >\t*m_auto_server_task;\r\n\tTsk::Task< Manager >\t*m_ctf_logic_task;\r\n\t\r\n\tstatic\tInp::Handler< Manager >::Code \ts_observer_input_logic_code;      \r\n\tInp::Handler< Manager >*\tm_observer_input_handler;\r\n\tObserverCommand\t\t\tm_observer_command;\r\n\r\n\r\n\tPrefs::Preferences\t\tm_network_preferences;\r\n\t// Ken: Taunt preferences used to be part of the network preferences, but then they were \r\n\t// required to be saved out with the career file when saving to mem card, rather than with\r\n\t// the net settings (See TT6068) so I separated them out into a separate set of preferences.\r\n\tPrefs::Preferences\t\tm_taunt_preferences;\r\n    \r\n\tLst::Head< PlayerInfo >\t\tm_players;\r\n\tLst::Head< NewPlayerInfo >\tm_new_players;\r\n\tLst::Head< TriggerEvent >\tm_trigger_events;\r\n\tLst::Head< ServerInfo > \tm_servers;\r\n    Lst::Head< ServerInfo > \tm_temp_servers;\r\n\tint\t\t\t\t\t\t\tm_sort_key;\r\n\tuint32\t\t\t\t\t\tm_conn_refused_reason;\r\n\t\r\n\t//\t\t\t\t\t\tThese are currently only for clients since servers are currently\r\n\t//\t\t\t\t\t\tthe only ones sending out ready queries. Clients keep track of the latest\r\n\t//\t\t\t\t\t\treceived queries in these members\r\n\tint\t\t\t\t\t\tm_latest_ready_query;\r\n\tbool\t\t\t\t\tm_ready_to_play;\r\n\tint\t\t\t\t\t\tm_last_score_update;\r\n\tFlags< int >\t\t\tm_flags;\r\n\tFlags< char >\t\t\tm_proset_flags;\r\n\tJoinState\t\t\t\tm_join_state;\r\n\tint\t\t\t\t\t\tm_join_ip;\r\n\tint\t\t\t\t\t\tm_join_private_ip;\r\n\tint\t\t\t\t\t\tm_join_port;\r\n\tint\t\t\t\t\t\tm_last_modem_state;\r\n\tTmr::Time\t\t\t\tm_join_start_time;\r\n\tTmr::Time\t\t\t\tm_lobby_start_time;\r\n\tbool\t\t\t\t\tm_game_pending;\r\n\tbool\t\t\t\t\tm_waiting_for_game_to_start;\r\n\r\n\tServerListState \t\tm_server_list_state;\r\n\tServerListState \t\tm_next_server_list_state;\r\n\tTmr::Time\t\t\t\tm_server_list_wait_time;\r\n\r\n\tuint32\t\t\t\t\tm_connection_success_script;\r\n\tuint32\t\t\t\t\tm_connection_failure_script;\r\n\r\n\tPlayerInfo*\t\t\t\tm_cam_player;\t// the player that I'm watching with my camera\r\n\tPlayerInfo*\t\t\t\tm_leader;\r\n\tint\t\t\t\t\t\tm_leading_team;\r\n\r\n\tchar\t\t\t\t\tm_goals_data[vMAX_GOAL_SIZE];\r\n\tint\t\t\t\t\t\tm_goals_data_size;\r\n\tuint32\t\t\t\t\tm_goals_level;\r\n\r\n#\tifndef __PLAT_XBOX__\r\n\tchar\t\t\t\t\tm_net_thread_stack[ vNET_THREAD_STACK_SIZE ]\t__attribute__ ((aligned(16)));\r\n#\telse\r\n#\tpragma pack( 16 )\r\n\tchar\t\t\t\t\tm_net_thread_stack[ vNET_THREAD_STACK_SIZE ];\r\n#\tpragma pack()\r\n#\tendif // __PLAT_XBOX__\r\n\tint\t\t\t\t\t\tm_net_thread_id;\r\n\r\n\tchar\t\t\t\t\tm_master_servers[vMAX_MASTER_SERVERS][16];\r\n\t\r\n#ifdef __PLAT_NGPS__\r\n\t// Gamespy members\r\npublic:\r\n\tvoid\t\t\t\t\tRemoveMessageOfTheDay( void );\r\n\tstatic bool\t\t\t\tScriptLoadNetConfigs(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic bool\t\t\t\tScriptNoNetConfigFiles(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic bool\t\t\t\tScriptFillNetConfigList(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic bool\t\t\t\tScriptChooseNetConfig(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic bool \t\t\tScriptFillPlayerListMenu( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tstatic bool \t\t\tScriptPostGame( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tstatic bool \t\t\tScriptAuthenticateClient( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tstatic bool \t\t\tScriptWriteDNASBinary( Script::CStruct* pParams, Script::CScript* pScript );\r\n\t\r\n\r\nprivate:\r\n\tchar\t\t\t\t\tm_motd[1024];\t// Message of the day text\r\n\tGHTTPRequest \t\t\tm_ghttp_request;\r\n\tTmr::Time\t\t\t\tm_ghttp_start_time;\r\n\tbool\t\t\t\t\tm_got_motd;\r\n\t//ezNetCnfCombination_t*\tmp_combinations[6];\r\n\tezNetCnfCombinationList_t m_combination_list;\r\n\tsceNetcnfifData_t\t\tm_env_data[6];\r\n    \r\n\t\r\n\tstatic void\ts_create_game_callback( PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, \r\n\t\t\t\t\t\t\t\t\t\t\tvoid * param );\r\n\tstatic void s_server_list_callback( PEER peer, PEERBool success, const char * name, SBServer server, PEERBool staging, int msg, int progress, void * param );\r\n\tstatic GHTTPBool MotdComplete( GHTTPRequest request, GHTTPResult result, char* buffer, int buffer_len, \r\n\t\t\t\t\t\t  void* param );\r\n\tstatic GHTTPBool TrackUsageComplete( GHTTPRequest request, GHTTPResult result, char* buffer, int buffer_len, \r\n\t\t\t\t\t\t  void* param );\r\n\r\n\tstatic\tvoid\t\t\ts_threaded_get_message_of_the_day( Manager* gamenet_man );\r\n\tstatic\tvoid\t\t\ts_threaded_track_usage( Manager* gamenet_man );\r\n#endif\r\n\r\n\tDeclareSingletonClass( Manager );\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nclass ScoreRank : public Lst::Node< ScoreRank >\r\n{\r\npublic:\r\n\tScoreRank( void )\r\n\t\t: Lst::Node< ScoreRank > ( this ) {}\r\n\r\n\tchar\tm_Name[32];\r\n\tbool\tm_IsKing;\r\n\tbool\tm_HasFlag;\r\n\tint\t\tm_WhichFlags;\r\n\tint\t\tm_ColorIndex;\r\n\tint\t\tm_TotalScore;\r\n\tint\t\tm_TeamId;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n#endif\t// __GAMENET_GAMENET_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Lobby.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tLobby.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t04/4/02\t-\tspg\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGamespy peer lobby implementation\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/thread.h>\r\n#include <core/singleton.h>\r\n\r\n#include <gel/mainloop.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/gamenet/lobby.h>\r\n#include <sk/gamenet/ngps/p_buddy.h>\r\n#include <sk/gamenet/ngps/p_stats.h>\r\n#include <sk/modules/skate/gamemode.h>                                       \r\n#include <sk/scripting/cfuncs.h>\r\n\r\n#include <peer/peer.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define vPOST_SERVER_TIMEOUT\t\tTmr::Seconds( 90 )\r\n#define vPOST_SERVER_RETRY_TIME\t\tTmr::Seconds( 5 )\r\n#define vGAME_VERSION\t\t\t\t5\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nenum\r\n{\r\n\tvGAMESPY_NO_DATA,\r\n\tvGAMESPY_QUERY_DATA,\r\n\tvGAMESPY_NAT_DATA,\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic Tmr::Time\ts_last_refresh_time = 0;\r\nstatic Tmr::Time\ts_time_of_connection = 0;\r\nstatic\tint\t\ts_gamespy_data_type = vGAMESPY_NO_DATA;\r\nstatic\tchar\ts_gamespy_parse_data[2048];\r\nstatic\tint\t\ts_gamespy_parse_data_len = 0;\r\nstatic\tstruct sockaddr s_gamespy_sender;\r\nstatic\tbool\ts_got_gamespy_callback;\r\nstatic\tTmr::Time\ts_game_start_time;\r\nstatic\tTmr::Time\ts_last_post_time;\r\nstatic\tbool\t\ts_notified_user_not_connected;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::add_lobby_to_menu( LobbyInfo* lobby, int index )\r\n{\r\n\tScript::CStruct* p_item_params;\r\n\tchar lobby_title[64];\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tif( lobby->m_Full )\r\n\t{\r\n\t\tsprintf( lobby_title, \"%s - %d/%d (%s)\", lobby->m_Name, lobby->m_NumServers, lobby->m_MaxServers, Script::GetString( \"net_lobby_full\" ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsprintf( lobby_title, \"%s - %d/%d\", lobby->m_Name, lobby->m_NumServers, lobby->m_MaxServers );\r\n\t}\r\n\r\n\tp_item_params = new Script::CStruct;\t\r\n\tp_item_params->AddString( \"text\", lobby_title );\r\n\tif( lobby->m_Full || lobby->m_OffLimits )\r\n\t{\r\n\t\tp_item_params->AddChecksum( NONAME, CRCD( 0x1d944426, \"not_focusable\" ) );\r\n\t\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"selected_lobby_full\"));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"choose_selected_lobby\"));\r\n\t\tp_item_params->AddChecksum( \"focus_script\",Script::GenerateCRC(\"regions_menu_set_focus\"));\r\n\t}\r\n\r\n\t// create the parameters that are passed to the X script\r\n\tScript::CStruct *p_script_params= new Script::CStruct;\r\n\tp_script_params->AddInteger( \"index\", index );\t\r\n\t\r\n\tif( !( lobby->m_Full || lobby->m_OffLimits ))\r\n\t{\r\n\t\tp_item_params->AddStructure(\"pad_choose_params\",p_script_params);\t\t\t\r\n\t}\r\n\r\n\tScript::RunScript(\"regions_menu_add_item\",p_item_params);\r\n\tdelete p_item_params;\r\n\tdelete p_script_params;\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::add_player_to_menu( LobbyPlayerInfo* player )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tScript::CStruct *p_script_params;\r\n\tScript::CStruct *p_unfocus_params;\r\n\tScript::CStruct* p_item_params;\r\n\tScript::CArray* p_colors;\r\n\tint rank;\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tp_script_params = new Script::CStruct;\r\n\tp_item_params = new Script::CStruct;\t\r\n\tp_colors = new Script::CArray;\r\n\tp_unfocus_params = new Script::CStruct;\r\n\r\n\tp_item_params->AddString( \"text\", PlayerName( player->m_Name ));\r\n\tp_colors->SetSizeAndType( 4, ESYMBOLTYPE_INTEGER );\r\n\r\n\tif( ( player->m_Profile ) && \r\n\t\t( gamenet_man->mpBuddyMan->IsLoggedIn()))\r\n\t{           \r\n\t\t//Dbg_Printf( \"Adding Player %s of %d to list\\n\", player->m_Name, player->m_Profile );\r\n\t\t\r\n\t\t// If it's me (or a buddy), color it differently and don't let me add myself to my own buddy list\r\n\t\tif( player->m_Profile == gamenet_man->mpBuddyMan->GetProfile() || gamenet_man->mpBuddyMan->IsAlreadyMyBuddy( player->m_Profile ))\r\n\t\t{\r\n\t\t\tif( gamenet_man->mpBuddyMan->GetProfile() == player->m_Profile )\r\n\t\t\t{\r\n\t\t\t\tp_colors->SetInteger( 0, 0 );\r\n\t\t\t\tp_colors->SetInteger( 1, 0 );\r\n\t\t\t\tp_colors->SetInteger( 2, 128 );\r\n\t\t\t\tp_colors->SetInteger( 3, 128 );\r\n\r\n\t\t\t\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"cant_add_self_to_buddy_prompt\"));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_colors->SetInteger( 0, 128 );\r\n\t\t\t\tp_colors->SetInteger( 1, 128 );\r\n\t\t\t\tp_colors->SetInteger( 2, 0 );\r\n\t\t\t\tp_colors->SetInteger( 3, 128 );\r\n\r\n\t\t\t\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"already_buddy_prompt\"));\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_colors->SetInteger( 0, 0 );\r\n\t\t\tp_colors->SetInteger( 1, 128 );\r\n\t\t\tp_colors->SetInteger( 2, 0 );\r\n\t\t\tp_colors->SetInteger( 3, 128 );\r\n\r\n\t\t\tp_script_params->AddInteger( \"profile\", player->m_Profile );\t\r\n\t\t\tp_script_params->AddString( \"nick\", player->m_Name );\t\r\n\t\t\tp_script_params->AddString( \"net_name\", PlayerName( player->m_Name ));  \r\n\t\t\tp_item_params->AddStructure( \"pad_choose_params\", p_script_params );\r\n\r\n\t\t\tif( gamenet_man->mpBuddyMan->NumBuddies() < vMAX_BUDDIES )\r\n\t\t\t{\r\n\t\t\t\tp_item_params->AddChecksum( \"pad_choose_script\", Script::GenerateCRC( \"add_buddy_prompt\" ));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_item_params->AddChecksum( \"pad_choose_script\", Script::GenerateCRC( \"cant_add_buddy_prompt_3\" ));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//Dbg_Printf( \"Adding Player %s, no profile\\n\", player->m_Name );\r\n\r\n\t\tp_colors->SetInteger( 0, 128 );\r\n\t\tp_colors->SetInteger( 1, 128 );\r\n\t\tp_colors->SetInteger( 2, 128 );\r\n\t\tp_colors->SetInteger( 3, 128 );\r\n\t\t\r\n\t\tif( gamenet_man->mpBuddyMan->IsLoggedIn())\r\n\t\t{\r\n\t\t\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"cant_add_buddy_prompt_1\"));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"cant_add_buddy_prompt_2\"));\r\n\t\t}\r\n\t\t\r\n\t}\r\n\t\r\n\trank = (int) (((float) player->m_Rating / (float) vMAX_RATING ) * (float) vMAX_RANK );\r\n\tp_item_params->AddInteger( \"rank\", rank );\r\n\tp_item_params->AddChecksum( \"id\", Script::GenerateCRC( player->m_Name ));\r\n\tp_item_params->AddChecksum( \"parent_menu_id\", Script::GenerateCRC( \"lobby_player_list_menu\" ));\r\n\tp_item_params->AddFloat( \"scale\", 1.1f );\r\n\r\n\tp_unfocus_params->AddArray( \"rgba\", p_colors );\r\n\tp_item_params->AddArray( \"rgba\", p_colors );\r\n\tp_item_params->AddStructure( \"unfocus_params\", p_unfocus_params );\r\n\t//Script::RunScript(\"make_text_sub_menu_item\", p_item_params );\r\n\t\r\n\tScript::RunScript(\"player_list_add_item\", p_item_params );\r\n\t\r\n\tdelete p_colors;\r\n\tdelete p_script_params;\r\n\tdelete p_item_params;\r\n\tdelete p_unfocus_params;\r\n\t\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::refresh_player_list( void )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tclear_player_list();\r\n\tScript::RunScript( \"destroy_lobby_user_list_children\" );\r\n\tpeerEnumPlayers( m_peer, GroupRoom, s_enum_players_callback, this );\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::clear_player_list( void )\r\n{\r\n\tLst::Search< LobbyPlayerInfo > sh;\r\n\tLobbyPlayerInfo* player, *next;\r\n\r\n\tfor( player = sh.FirstItem( m_players ); player; player = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tdelete player;\r\n\t}\r\n\r\n\tScript::RunScript( \"update_lobby_player_list\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::fill_player_list( void )\r\n{\r\n\tLst::Search< LobbyPlayerInfo > sh;\r\n\tLobbyPlayerInfo* player;\r\n\r\n\tScript::RunScript( \"destroy_lobby_user_list_children\" );\r\n\r\n    for( player = sh.FirstItem( m_players ); player; player = sh.NextItem())\r\n\t{\r\n\t\tif( player->m_GotInfo )\r\n\t\t{\r\n\t\t\tadd_player_to_menu( player );\r\n\t\t}\r\n\t}\r\n\t\r\n\tScript::RunScript( \"update_lobby_player_list\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::add_buddy_to_menu( LobbyPlayerInfo* player )\r\n{\r\n\tScript::CStruct* p_item_params;\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\t//Dbg_Printf( \"Adding %s of %d to the list\\n\", PlayerName( player->m_Name ), player->m_Profile );\r\n\tp_item_params = new Script::CStruct;\t\r\n\tp_item_params->AddString( \"text\", PlayerName( player->m_Name ));\r\n\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"lobby_add_buddy\"));\r\n\tp_item_params->AddChecksum( \"parent_menu_id\", Script::GenerateCRC( \"lobby_buddy_list_menu\" ));\r\n\r\n\t// create the parameters that are passed to the X script\r\n\tScript::CStruct *p_script_params= new Script::CStruct;\r\n\tp_script_params->AddInteger( \"profile\", player->m_Profile );\t\r\n\tp_script_params->AddString( \"nick\", player->m_Name );\t\r\n\tp_script_params->AddString( \"net_name\", PlayerName( player->m_Name ));  \r\n\tp_item_params->AddStructure( \"pad_choose_params\", p_script_params );\r\n\r\n\tScript::RunScript(\"make_text_sub_menu_item\",p_item_params);\r\n\r\n\tdelete p_item_params;\r\n\tdelete p_script_params;\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::fill_prospective_buddy_list( void )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tLst::Search< LobbyPlayerInfo > sh;\r\n\tLobbyPlayerInfo* player;\r\n\r\n\tScript::RunScript( \"destroy_lobby_buddy_list_children\" );\r\n\r\n\tfor( player = sh.FirstItem( m_players ); player; player = sh.NextItem())\r\n\t{\r\n\t\tif( player->m_Profile == gamenet_man->mpBuddyMan->GetProfile())\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif(\t( player->m_Profile > 0 ) && \r\n\t\t\t( gamenet_man->mpBuddyMan->IsAlreadyMyBuddy( player->m_Profile ) == false ))\r\n\t\t{\r\n\t\t\tadd_buddy_to_menu( player );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::s_threaded_peer_connect( LobbyMan* lobby_man )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\t// Register this thread with the sockets API\r\n\tsockAPIregthr();\r\n\r\n\tPrefs::Preferences* prefs;\r\n\tchar lobby_name[128];\r\n\t\r\n\tprefs = gamenet_man->GetNetworkPreferences();\r\n    const char* network_name = prefs->GetPreferenceString( Script::GenerateCRC( \"network_id\" ), Script::GenerateCRC( \"ui_string\" ));\r\n    \r\n\t// Use our unique Gamespy profile ID as our \"unique number\", if one is available\r\n\tif( gamenet_man->mpBuddyMan->IsLoggedIn())\r\n\t{\r\n\t\tsprintf( lobby_name, \"a%d_%s\", gamenet_man->mpBuddyMan->GetProfile(), network_name );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsprintf( lobby_name, \"a%d_%s\", (int) Tmr::GetTime(), network_name );\r\n\t}\r\n\r\n\tlobby_man->m_connection_in_progress = true;\r\n    peerConnect( lobby_man->m_peer, lobby_name, gamenet_man->mpBuddyMan->GetProfile(), s_nick_error_callback, s_connect_callback, lobby_man, false );\r\n\r\n\t// Deregister this thread with the sockets API\r\n\tsockAPIderegthr();\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid LobbyMan::s_disconnected_callback( PEER peer, const char * reason, void * param )\r\n{\r\n\tLobbyMan* man = (LobbyMan*) param;\r\n\tTmr::Time elapsed_time;\r\n\r\n\telapsed_time = Tmr::GetTime() - s_time_of_connection;\r\n\tprintf( \"Disconnected at %d after %d ms. Reason: %s\\n\", (int) Tmr::GetTime(), (int) elapsed_time, reason );\r\n\r\n\tif( man->m_connection_in_progress )\r\n\t{\r\n\t\tprintf( \"******* Connect Callback FAILED!\\n\" );\r\n\t\tScript::RunScript( \"create_gamespy_connection_failure_dialog\" );\r\n\t\tman->m_connection_in_progress = false;\r\n\t}\r\n\telse if( man->m_expecting_disconnect == false )\r\n\t{\r\n\t\tprintf( \"Wasn't expecting discon.  Attempting to stop hosting game\\n\" );\r\n\t\tScript::RunScript( \"lost_connection_to_gamespy\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tprintf( \"Was expecting discon. Ignore\\n\" );\r\n\t}\r\n\r\n\tman->m_expecting_disconnect = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid LobbyMan::s_room_message_callback( PEER peer, RoomType roomType, const char * nick, const char * message,\r\n\t\t\t\t\t\t\t\t\t\tMessageType messageType, void * param )\r\n{\r\n\tScript::CStruct* p_params;\r\n\tchar msg[1024];\r\n\r\n\tLobbyMan* lobby_man = (LobbyMan*) param;\r\n\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\tsprintf( msg, \"%s: %s\", lobby_man->PlayerName((char*) nick ), message );\r\n\tp_params = new Script::CStruct;\t\r\n\tp_params->AddString( \"text\", msg );\r\n\tScript::RunScript(\"create_console_message\", p_params );\r\n\tdelete p_params;\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid LobbyMan::s_player_message_callback( PEER peer, const char * nick, const char * message, MessageType messageType,\r\n\t\t\t\t\t\t\t\t\t\t\t\tvoid * param )\r\n{\r\n\t//printf( \"Player Message. Nick: %s Message: %s\\n\", nick, message );\r\n\t//LobbyMan* man = (LobbyMan*) param;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid LobbyMan::s_player_proile_id_callback( PEER peer, PEERBool success,  const char * nick, int profileID, void * param )\r\n{\r\n\tLst::Search< LobbyPlayerInfo > sh;\r\n\tLobbyPlayerInfo* player;\r\n\tLobbyMan* lobby_man = (LobbyMan*) param;\r\n\r\n\t//Dbg_Printf( \"Got a player profile id callback on %s : %d\\n\", nick, profileID );\r\n\tfor( player = sh.FirstItem( lobby_man->m_players ); player; player = sh.NextItem())\r\n\t{\r\n\t\tif( stricmp( player->m_Name, nick ) == 0 )\r\n\t\t{\r\n\t\t\tplayer->m_Profile = profileID;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid LobbyMan::s_player_joined_callback( PEER peer, RoomType roomType, const char * nick, void * param )\r\n{\r\n\tScript::CStruct* p_params;\r\n\tchar msg[1024];\r\n\tLst::Search< LobbyPlayerInfo > sh;\r\n\tLobbyPlayerInfo* player;\r\n\t\r\n\tLobbyMan* lobby_man = (LobbyMan*) param;\r\n\r\n\t//printf( \"%s joined the room\\n\", nick );\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tfor( player = sh.FirstItem( lobby_man->m_players ); player; player = sh.NextItem())\r\n\t{\r\n\t\tif( stricmp( player->m_Name, nick ) == 0 )\r\n\t\t{\r\n\t\t\tpeerGetPlayerInfoNoWait( peer, nick, NULL, &player->m_Profile );\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\tplayer->m_GotInfo = true;\r\n\t\t\treturn;\t// already have this player\r\n\t\t}\r\n\t}\r\n\r\n\tplayer = new LobbyPlayerInfo;\r\n\tstrcpy( player->m_Name, nick );\r\n\tpeerGetPlayerInfoNoWait( peer, nick, NULL, &player->m_Profile );\r\n\tplayer->m_GotInfo = true;\r\n\r\n\tlobby_man->m_players.AddToTail( player );\r\n\r\n\tScript::RunScript( \"prepare_lobby_user_list_for_new_children\" );\r\n\tlobby_man->add_player_to_menu( player );\r\n\tScript::RunScript( \"update_lobby_player_list\" );\r\n\t\t\r\n\tsprintf( msg, \"%s %s\", lobby_man->PlayerName((char*) nick ), Script::GetString( \"lobby_status_joined\" ));\r\n\r\n\tp_params = new Script::CStruct;\t\r\n\tp_params->AddString( \"text\", msg );\r\n    p_params->AddChecksum( \"join\", 0 );\r\n\tScript::RunScript(\"create_console_message\", p_params );\r\n\tdelete p_params;\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid LobbyMan::s_player_info_callback( PEER peer, RoomType roomType, const char * nick, unsigned int IP, int profileID,  \r\n                                                void * param )\r\n{\r\n\tLst::Search< LobbyPlayerInfo > sh;\r\n\tLobbyPlayerInfo* player;\r\n\tLobbyMan* lobby_man = (LobbyMan*) param;\r\n\t\r\n\tif( nick == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t//Dbg_Printf( \"Got info on %s : %d\\n\", nick, profileID );\r\n\r\n\tfor( player = sh.FirstItem( lobby_man->m_players ); player; player = sh.NextItem())\r\n\t{\r\n\t\tif( stricmp( player->m_Name, nick ) == 0 )\r\n\t\t{\r\n\t\t\t// If we don't already have this player's profile\r\n\t\t\tif( player->m_Profile == 0 )\r\n\t\t\t{\r\n\t\t\t\tplayer->m_Profile = profileID;\r\n\t\t\t}\r\n\t\t\tplayer->m_GotInfo = true;\r\n\t\t\tlobby_man->add_player_to_menu( player );\r\n            Script::RunScript( \"update_lobby_player_list\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid LobbyMan::s_player_left_callback( PEER peer, RoomType roomType, const char * nick, const char * reason, \r\n\t\t\t\t\t\t\t\t\t\t\t\tvoid * param )\r\n{\r\n\tScript::CStruct* p_params;\r\n\tchar msg[1024];\r\n\tLst::Search< LobbyPlayerInfo > sh;\r\n\tLobbyPlayerInfo* player;\r\n\tLobbyMan* lobby_man = (LobbyMan*) param;\r\n\t\r\n\t//printf( \"%s left the room\\n\", nick );\r\n\r\n\tfor( player = sh.FirstItem( lobby_man->m_players ); player; player = sh.NextItem())\r\n\t{\r\n\t\tif( stricmp( player->m_Name, nick ) == 0 )\r\n\t\t{\r\n\t\t\tp_params = new Script::CStruct;\r\n\r\n\t\t\tp_params->AddChecksum( \"user_id\", Script::GenerateCRC( nick ));\r\n\t\t\tScript::RunScript( \"destroy_lobby_user\", p_params );\r\n\r\n\t\t\tdelete player;\r\n\t\t\tdelete p_params;\r\n\r\n\t\t\tScript::RunScript( \"update_lobby_player_list\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tsprintf( msg, \"%s %s\", lobby_man->PlayerName((char*) nick ), Script::GetString( \"lobby_status_left\" ));\r\n\r\n\tp_params = new Script::CStruct;\t\r\n\tp_params->AddString( \"text\", msg );\r\n    p_params->AddChecksum( \"left\", 0 );\r\n\tScript::RunScript(\"create_console_message\", p_params );\r\n\tdelete p_params;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \tLobbyMan::s_get_room_keys_callback( PEER peer, PEERBool success, RoomType roomType, \r\n\t\t\t\t\t\t\t\t\t\t\tconst char * nick, int num, char ** keys, char ** values, \r\n\t\t\t\t\t\t\t\t\t\t\tvoid * param )\r\n{\r\n\tint i;\r\n\tLobbyMan* lobby_man = (LobbyMan*) param;\r\n\r\n\tfor( i = 0; i < num; i++ )\r\n\t{\r\n\t\t//Dbg_Printf( \"Got Key: %s\\n\", keys[i] );\r\n\t}\r\n\tif( num > 0 )\r\n\t{\r\n\t\tint rank;\r\n\t\tScript::CStruct* p_item_params;\r\n\t\tLst::Search< LobbyPlayerInfo > sh;\r\n\t\tLobbyPlayerInfo* player;\r\n\r\n\t\tif(( keys[0] != NULL )&& stricmp( keys[0], \"b_rating\" ) == 0 )\r\n\t\t{\r\n\t\t\tfor( player = sh.FirstItem( lobby_man->m_players ); player; player = sh.NextItem())\r\n\t\t\t{\r\n\t\t\t\tif( stricmp( player->m_Name, nick ) == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Printf( \"Got rating %d for %s\\n\", player->m_Rating, nick );\r\n\t\t\t\t\tplayer->m_Rating = atoi( values[0] );\r\n\t\t\t\t\trank = (int) (((float) player->m_Rating / (float) vMAX_RATING ) * (float) vMAX_RANK );\r\n\t\t\t\r\n\t\t\t\t\tp_item_params = new Script::CStruct;\r\n\t\t\t\t\tp_item_params->AddChecksum( \"id\", Script::GenerateCRC( player->m_Name ));\r\n\t\t\t\t\tp_item_params->AddInteger( \"rank\", rank );\r\n\t\t\t\t\tScript::RunScript( \"player_list_update_rank\", p_item_params );\r\n\t\t\t\t\tdelete p_item_params;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tLobbyMan::s_enum_players_callback( PEER peer, PEERBool success, RoomType roomType, int index, const char * nick,  // The nick of the player.\r\n\t\t\t\t\t\t\t\t\t\t\t\tint flags, void * param )\r\n{\r\n\tLobbyMan* lobby_man = (LobbyMan*) param;\r\n\tLst::Search< LobbyPlayerInfo > sh;\r\n\tLobbyPlayerInfo* player;\r\n\r\n\tif( success == false )\r\n\t{\r\n\t\t//printf( \"Failed to enum players\\n\" );\r\n\t\treturn;\r\n\t}\r\n\r\n\t//Dbg_Printf( \"Enumerating players\\n\" );\r\n\tif( index == -1 )\r\n\t{\r\n\t\t// List is finished. \r\n\t\t//lobby_man->fill_player_list();\r\n        return;\r\n\t}\r\n\t\r\n\tfor( player = sh.FirstItem( lobby_man->m_players ); player; player = sh.NextItem())\r\n\t{\r\n\t\tif( stricmp( player->m_Name, nick ) == 0 )\r\n\t\t{\r\n\t\t\treturn;\t// already have this player in our list\r\n\t\t}\r\n\t}\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\tplayer = new LobbyPlayerInfo;\r\n\tstrcpy( player->m_Name, nick );\r\n\t//Dbg_Printf( \"Before getting player info on %s : %d\\n\", nick, player->m_Profile );\r\n\tif( peerGetPlayerInfoNoWait( peer, nick, NULL, &player->m_Profile ))\r\n\t{\r\n\t\t//Dbg_Printf( \"***** Got Player Info for %s : %d\\n\", nick, player->m_Profile );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//Dbg_Printf( \"***** Failed to Get Player Info for %s : %d\\n\", nick, player->m_Profile );\r\n\t}\r\n\r\n\tlobby_man->m_players.AddToTail( player );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid LobbyMan::s_new_player_list_callback( PEER peer, RoomType roomType, void * param )\r\n{\r\n\tLobbyMan* lobby_man = (LobbyMan*) param;\r\n    \r\n\t//printf( \"New Player List\\n\" );\r\n\r\n\tlobby_man->refresh_player_list();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid LobbyMan::s_room_key_callback( PEER peer, RoomType roomType, const char * nick, \r\n\t\t\t\t\t\t\t\t\tconst char * key, const char * value, void * param )\r\n{\r\n\tLobbyMan* lobby_man = (LobbyMan*) param;\r\n\tLst::Search< LobbyPlayerInfo > sh;\r\n\tLobbyPlayerInfo* player;\r\n\r\n\tfor( player = sh.FirstItem( lobby_man->m_players ); player; player = sh.NextItem())\r\n\t{\r\n\t\tif( stricmp( player->m_Name, nick ) == 0 )\r\n\t\t{\r\n\t\t\tint rank;\r\n\t\t\tScript::CStruct* p_item_params;\r\n\r\n\t\t\tplayer->m_Rating = atoi( value );\r\n\t\t\trank = (int) (((float) player->m_Rating / (float) vMAX_RATING ) * (float) vMAX_RANK );\r\n\r\n\t\t\tDbg_Printf( \"Got room key for %s. Value: %d\\n\", nick, player->m_Rating );\r\n\r\n\t\t\tp_item_params = new Script::CStruct;\r\n\t\t\tp_item_params->AddChecksum( \"id\", Script::GenerateCRC( player->m_Name ));\r\n\t\t\tp_item_params->AddInteger( \"rank\", rank );\r\n\t\t\tScript::RunScript( \"player_list_update_rank\", p_item_params );\r\n\t\t\tdelete p_item_params;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid LobbyMan::s_nat_negotiate_callback( PEER peer, int cookie, void * param )\r\n{\r\n    NegotiateError err;\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\tNet::Server* server;\r\n\r\n\tif( gamenet_man->mpLobbyMan->m_nat_count.InUse())\r\n\t{\r\n\t\tDbg_Printf( \"******* Ignoring new nat negotiation request\\n\" );\r\n\t\treturn;\r\n\t}\r\n\r\n\tserver = gamenet_man->GetServer();\r\n\tDbg_Assert( server );\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tDbg_Printf( \"******* Beginning new nat negotiation\\n\" );\r\n\terr = NNBeginNegotiationWithSocket( server->GetSocket(), cookie, 0, s_nat_negotiate_progress,\r\n\t\t\t\t\t\t\t\t\t\ts_nat_negotiate_complete, (void*) cookie );\r\n\tif( err != ne_noerror )\r\n\t{\r\n\t\tDbg_Printf( \"******* NAT Neg Error: %d\\n\", err );\r\n\t\tNNCancel( cookie );\r\n\t\tNNThink();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif( gamenet_man->mpLobbyMan->m_nat_count.InUse() == false )\r\n\t{\r\n\t\tmlp_manager->AddLogicTask( *gamenet_man->mpLobbyMan->m_nat_negotiate_task );\r\n\t}\r\n\r\n\tgamenet_man->mpLobbyMan->m_nat_count.Acquire();\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid LobbyMan::s_server_key_callback( PEER peer, int key, qr2_buffer_t buffer, void * param )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tconst char* server_name;\r\n\tPrefs::Preferences* pPreferences;\r\n\tScript::CScriptStructure* pStructure;\r\n    char* password;\r\n\t\r\n\t//Dbg_Printf( \"***** SERVER KEY CALLBACK\\n\" );\r\n\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\r\n    switch(key)\r\n\t{\r\n\t\tcase HOSTNAME_KEY:\r\n\t\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"server_name\") );\r\n\t\t\tpStructure->GetText( \"ui_string\", &server_name, true );\r\n\t\t\t//Dbg_Printf( \"Server name is %s\\n\", server_name );\r\n\t\t\tqr2_buffer_add(buffer, server_name );\r\n\t\t\tbreak;\r\n\t\tcase GAMENAME_KEY:\r\n\t\t\tqr2_buffer_add(buffer, \"thps5ps2\" );\r\n\t\t\tbreak;\r\n\t\tcase GAMEMODE_KEY:\r\n\t\t\tqr2_buffer_add(buffer, gamenet_man->GetGameModeName());\r\n\t\t\tbreak;\r\n\t\tcase HOSTPORT_KEY:\r\n\t\t\tqr2_buffer_add_int(buffer, vHOST_PORT );\r\n\t\t\tbreak;\r\n\t\tcase MAPNAME_KEY:\r\n\t\t\tqr2_buffer_add(buffer, gamenet_man->GetLevelName());\r\n\t\t\tbreak;\r\n\t\tcase GAMETYPE_KEY:\r\n\t\t\tqr2_buffer_add(buffer, gamenet_man->GetGameModeName());\r\n\t\t\tbreak;\r\n\t\tcase TEAMPLAY_KEY:\r\n\t\t\tqr2_buffer_add_int(buffer, 0);\r\n\t\t\tbreak;\r\n\t\tcase NUMPLAYERS_KEY:\r\n\t\t\tqr2_buffer_add_int(buffer, gamenet_man->GetNumPlayers());\r\n\t\t\tbreak;\r\n\t\tcase MAXPLAYERS_KEY:\r\n\t\t\tqr2_buffer_add_int(buffer, gamenet_man->GetMaxPlayers());\r\n\t\t\tbreak;\r\n\t\tcase PASSWORD_KEY:\r\n\t\t\tpassword = gamenet_man->GetPassword();\r\n\t\t\tif( password[0] == '\\0' )\r\n\t\t\t{\r\n\t\t\t\tqr2_buffer_add_int(buffer, 0 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tqr2_buffer_add_int(buffer, 1 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase NUMOBSERVERS_KEY:\r\n\t\t\tqr2_buffer_add_int(buffer, gamenet_man->GetNumObservers());\r\n\t\t\tbreak;\r\n\t\tcase MAXOBSERVERS_KEY:\r\n\t\t\tqr2_buffer_add_int(buffer, gamenet_man->GetMaxObservers());\r\n\t\t\tbreak;\r\n\t\tcase SKILLLEVEL_KEY:\r\n\t\t\tqr2_buffer_add_int(buffer, gamenet_man->GetSkillLevel());\r\n\t\t\tbreak;\r\n\t\tcase STARTED_KEY:\r\n\t\t\tif( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netlobby\" ))\r\n\t\t\t{\r\n\t\t\t\tqr2_buffer_add_int(buffer, 0 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tqr2_buffer_add_int(buffer, 1 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase HOSTED_MODE_KEY:\r\n\t\t\tqr2_buffer_add_int(buffer, gamenet_man->GetHostMode());\r\n\t\t\tbreak;\r\n\t\tcase RANKED_KEY:\r\n\t\t\tqr2_buffer_add_int(buffer, gamenet_man->mpBuddyMan->IsLoggedIn());\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tqr2_buffer_add(buffer, \"\");\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\ts_got_gamespy_callback = true;\r\n}\r\n\r\nvoid LobbyMan::s_player_key_callback( PEER peer, int key, int index, qr2_buffer_t buffer, void * param )\r\n{\r\n\ts_got_gamespy_callback = true;\r\n\r\n\t//Dbg_Printf( \"***** PLAYER KEY %d CALLBACK : for player %d\\n\", key, index );\r\n\tswitch(key)\r\n\t{\r\n\t\tcase RATING__KEY:\r\n\t\t{\r\n\t\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\t\tLst::Search< PlayerInfo > sh;\r\n\t\t\tPlayerInfo* player;\r\n\t\t\tLst::Search< NewPlayerInfo > new_sh;\r\n\t\t\tNewPlayerInfo* np;\r\n\t\t\tint i;\r\n\t\t\t\r\n\t\t\ti = 0;\r\n\t\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; \r\n\t\t\t\t\tplayer = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\tif( !player->IsObserving() || player->IsPendingPlayer())\r\n\t\t\t\t{\r\n\t\t\t\t\tif( i == index )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//printf( \"(2) Added %s's rating: %d to list\\n\", player->m_Name, player->m_Rating );\r\n\t\t\t\t\t\tqr2_buffer_add_int(buffer, player->m_Rating );\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ti++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\r\n\t\t\tfor( np = gamenet_man->FirstNewPlayerInfo( new_sh ); np; np = gamenet_man->NextNewPlayerInfo( new_sh ))\r\n\t\t\t{\r\n\t\t\t\t// Pending players count, observers don't\r\n\t\t\t\tif(\t( np->Flags & PlayerInfo::mPENDING_PLAYER ) ||\r\n\t\t\t\t\t( np->Flags & PlayerInfo::mJUMPING_IN ) ||\r\n\t\t\t\t\t!( np->Flags & PlayerInfo::mOBSERVER ))\r\n\t\t\t\t{\r\n\t\t\t\t\tif( i == index )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//printf( \"(2) Added %s's rating: %d to list\\n\", np->Name, np->Rating );\r\n\t\t\t\t\t\tqr2_buffer_add_int(buffer, np->Rating );\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ti++;\r\n\t\t\t\t}                 \r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t//printf( \"Added empty string to player list\\n\" );\r\n\t\t\t// If we're here, we don't have a player == index\r\n            qr2_buffer_add(buffer, \"\");\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase PLAYER__KEY:\r\n\t\t{\r\n\t\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\t\tLst::Search< PlayerInfo > sh;\r\n\t\t\tPlayerInfo* player;\r\n\t\t\tLst::Search< NewPlayerInfo > new_sh;\r\n\t\t\tNewPlayerInfo* np;\r\n\t\t\tint i;\r\n\t\t\t\r\n\t\t\ti = 0;\r\n\t\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; \r\n\t\t\t\t\tplayer = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\tif( !player->IsObserving() || player->IsPendingPlayer())\r\n\t\t\t\t{\r\n\t\t\t\t\tif( i == index )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//printf( \"Added %s to player list\\n\", player->m_Name );\r\n\t\t\t\t\t\tqr2_buffer_add(buffer, player->m_Name);\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ti++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\r\n\t\t\tfor( np = gamenet_man->FirstNewPlayerInfo( new_sh ); np; np = gamenet_man->NextNewPlayerInfo( new_sh ))\r\n\t\t\t{\r\n\t\t\t\t// Pending players count, observers don't\r\n\t\t\t\tif(\t( np->Flags & PlayerInfo::mPENDING_PLAYER ) ||\r\n\t\t\t\t\t( np->Flags & PlayerInfo::mJUMPING_IN ) ||\r\n\t\t\t\t\t!( np->Flags & PlayerInfo::mOBSERVER ))\r\n\t\t\t\t{\r\n\t\t\t\t\tif( i == index )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//printf( \"(2) Added %s to player list\\n\", player->m_Name );\r\n\t\t\t\t\t\tqr2_buffer_add(buffer, np->Name );\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ti++;\r\n\t\t\t\t}                 \r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t//printf( \"Added empty string to player list\\n\" );\r\n\t\t\t// If we're here, we don't have a player == index\r\n            qr2_buffer_add(buffer, \"\");\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase PING__KEY:\r\n\t\t\tqr2_buffer_add(buffer, \"\");\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid LobbyMan::s_public_address_callback( PEER peer, unsigned int ip, unsigned short port, \r\n\t\t\t\t\t\t\t\t\t\t\t   void * param )\r\n{\r\n\tchar location[1024];\r\n\tconst char *server_name;\r\n\tScript::CScriptStructure* pStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tBuddyMan* buddy_man;\r\n\tLobbyMan* lobby_man;\r\n\r\n\tlobby_man = (LobbyMan*) param;\r\n\tbuddy_man = gamenet_man->mpBuddyMan;\r\n\r\n\tDbg_Printf( \"***** Got public address: %s : %d\\n\", inet_ntoa(*(struct in_addr *) &ip ), port );\r\n\tif( gamenet_man->OnServer() && lobby_man->GetPeer())\r\n\t{\r\n\t\tgamenet_man->SetJoinPort( port );\r\n\t\tgamenet_man->SetJoinIP( ip );\r\n\t\tgamenet_man->SetJoinPrivateIP( peerGetPrivateIP( lobby_man->GetPeer()) );\r\n\t\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"server_name\") );\r\n\t\tpStructure->GetText( \"ui_string\", &server_name, true );\r\n\t\r\n\t\tsprintf( location, \"%d:%d:%d:%s (%s)\", ip, peerGetPrivateIP( lobby_man->GetPeer()), port, server_name, lobby_man->GetLobbyName());\r\n\t\tif( buddy_man->IsLoggedIn())\r\n\t\t{\r\n\t\t\tbuddy_man->SetStatusAndLocation( GP_PLAYING, (char*) Script::GetString( \"homie_status_hosting\" ), location );\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\nvoid LobbyMan::s_add_error_callback( PEER peer, qr2_error_t error, char * errorString, void * param )\r\n{\r\n\tDbg_Printf( \"***** Got an error (%d) adding the server: %s\\n\", (int) error, errorString );\r\n}\r\n\r\nint LobbyMan::s_key_count_callback( PEER peer, qr2_key_type type, void * param )\r\n{\r\n\t//Dbg_Printf( \"*** GOT KEY COUNT CALLBACK\\n\" );\r\n\tswitch( type )\r\n\t{\r\n\t\tcase key_server:\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"*** Server Key Count Request: 15\\n\" );\r\n\t\t\treturn 16;\r\n\t\t}\r\n\t\tcase key_player:\r\n\t\t{\r\n\t\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\t\t//Dbg_Printf( \"*** Player Key Count Request: %d\\n\", gamenet_man->GetNumPlayers() );\r\n\t\t\treturn gamenet_man->GetNumPlayers();\r\n\t\t}\r\n\t\tcase key_team:\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\nvoid LobbyMan::s_key_list_callback( PEER peer, qr2_key_type type, qr2_keybuffer_t keyBuffer, \r\n\t\t\t\t\t\t\t\t\tvoid * param )\r\n{\r\n\t//Dbg_Printf( \"***** Got a key list callback\\n\" );\r\n\t// register the keys we use\r\n\tswitch(type)\r\n\t{\r\n\t\tcase key_server:\r\n\t\t\t//Dbg_Printf( \"***** Got a request for server keys\\n\" );\r\n\t\t\t\r\n\t\t\tqr2_keybuffer_add(keyBuffer, GAMEMODE_KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, GAMENAME_KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, HOSTNAME_KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, HOSTPORT_KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, MAPNAME_KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, GAMETYPE_KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, TEAMPLAY_KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, NUMPLAYERS_KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, MAXPLAYERS_KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, PASSWORD_KEY);\r\n\t\t\t\r\n\t\t\tqr2_keybuffer_add(keyBuffer, NUMOBSERVERS_KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, MAXOBSERVERS_KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, RANKED_KEY);\r\n\t\t\t\r\n\t\t\tqr2_keybuffer_add(keyBuffer, SKILLLEVEL_KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, STARTED_KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, HOSTED_MODE_KEY);\r\n\t\t\tbreak;\r\n\t\tcase key_player:\r\n\t\t\t//Dbg_Printf( \"***** Got a request for player keys\\n\" );\r\n\t\t\tqr2_keybuffer_add(keyBuffer, PLAYER__KEY);\r\n\t\t\tqr2_keybuffer_add(keyBuffer, RATING__KEY);\r\n\t\t\tbreak;\r\n\t\tcase key_team:\r\n\t\t\t//Dbg_Printf( \"***** Got a request for team keys\\n\" );\r\n\t\t\t// no custom team keys\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tLobbyMan::s_nick_error_callback( PEER peer, int type, const char* nick, void *param )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tif( type == PEER_IN_USE )\r\n\t{\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tchar new_nick[128];\r\n\t\tPrefs::Preferences* prefs;\r\n\t\r\n\t\tprefs = gamenet_man->GetNetworkPreferences();\r\n\t\tconst char* network_name = prefs->GetPreferenceString( Script::GenerateCRC( \"network_id\" ), Script::GenerateCRC( \"ui_string\" ));\r\n        \r\n\t\tprintf( \"Nick Error. Nick %s In Use\\n\", nick );\r\n\t\tsprintf( new_nick, \"a%d_%s\", (int) Tmr::GetTime(), network_name );\r\n\t\tpeerRetryWithNick( peer, (const char*) new_nick );\r\n\t}\r\n\telse if( type == PEER_INVALID )\r\n\t{\r\n\t\tchar new_nick[128];\r\n\t\t\r\n\t\tprintf( \"Nick Error. Nick %s is Invalid\\n\", nick );\r\n        chatFixNick( new_nick, nick );\r\n\t\tpeerRetryWithNick( peer, (const char*) new_nick );\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tLobbyMan::s_connect_callback( PEER peer, PEERBool success, void* param )\r\n{\r\n\tLobbyMan* lobby_man = (LobbyMan*) param;\r\n\r\n\tlobby_man->m_connection_in_progress = false;\r\n\tif( success )\r\n\t{\r\n\t\tNet::Manager * net_man = Net::Manager::Instance();\r\n\r\n\t\t//Mlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\t\t//GameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\t//mlp_man->AddLogicTask( *lobby_man->m_lobby_logic_task );\r\n\t\t\r\n\t\tprintf( \"****** Connect Callback Successful\\n\" );\r\n\r\n\t\tnet_man->SetPublicIP( peerGetLocalIP( peer ));\r\n\t\tCFuncs::ScriptStartLobbyList( NULL, NULL );\r\n\t\t//gamenet_man->SetServerListState( vSERVER_LIST_STATE_STARTING_LOBBY_LIST );\r\n\t\tlobby_man->m_expecting_disconnect = false;\r\n\t\ts_time_of_connection = Tmr::GetTime();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tprintf( \"******* Connect Callback FAILED!\\n\" );\r\n\t\tScript::RunScript( \"create_gamespy_connection_failure_dialog\" );\r\n\t}\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tLobbyMan::s_group_rooms_callback( PEER peer, PEERBool success, int groupID, SBServer server,  \r\n\t\t\t\t\t\t\t\t\tconst char * name, int numWaiting, int maxWaiting, int numGames, int numPlaying,\r\n\t\t\t\t\t\t\t\t\tvoid* param )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tLobbyMan* lobby_man = (LobbyMan*) param;\r\n\t// Check for the terminator\r\n\tif( success )\r\n\t{\r\n\t\tif( groupID == 0 )\r\n\t\t{   \r\n\t\t\tgamenet_man->SetServerListState( vSERVER_LIST_STATE_GOT_LOBBY_LIST );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tint max_players, official_key;\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\t\t\tLobbyInfo* lobby_info;\r\n\t\t\tlobby_info = new LobbyInfo;\r\n\t\t\tstrncpy( lobby_info->m_Name, name, 63 );\r\n\t\t\tlobby_info->m_Name[63] = '\\0';\r\n\t\t\tlobby_info->m_NumServers = numGames;\r\n\t\t\tlobby_info->m_GroupId = groupID;\r\n\t\t\tlobby_info->m_MaxServers = maxWaiting;\r\n            max_players = SBServerGetIntValue( server, \"maxplayers\", 0 );\r\n\t\t\tif( numWaiting >= max_players )\r\n\t\t\t{\r\n\t\t\t\tlobby_info->m_Full = true;\r\n\t\t\t}\r\n\r\n\t\t\tlobby_info->m_MaxRating = SBServerGetIntValue( server, \"maxrating\", 100000 );\r\n\t\t\tlobby_info->m_MinRating = SBServerGetIntValue( server, \"minrating\", 0 );\r\n\r\n\t\t\tDbg_Printf( \"Got lobby: %s, max: %d min: %d, rating: %d\\n\", name, lobby_info->m_MaxRating, lobby_info->m_MinRating, gamenet_man->mpStatsMan->GetStats()->GetRating());\r\n\r\n\t\t\tif( gamenet_man->mpStatsMan->GetStats()->GetRating() > lobby_info->m_MaxRating )\r\n\t\t\t{\r\n\t\t\t\tlobby_info->m_OffLimits = true;\r\n\t\t\t}\r\n\r\n\t\t\tif( gamenet_man->mpStatsMan->GetStats()->GetRating() < lobby_info->m_MinRating )\r\n\t\t\t{\r\n\t\t\t\tlobby_info->m_OffLimits = true;\r\n\t\t\t}\r\n\r\n\t\t\tofficial_key = 0;\r\n\t\t\tofficial_key = SBServerGetIntValue( server, \"neversoft\", 0 );\r\n\t\t\tif( official_key )\r\n\t\t\t{\r\n\t\t\t\tlobby_info->m_Official = true;\r\n\t\t\t}\r\n            \r\n\t\t\t//printf( \"Got lobby %d: %s\\n\", groupID, name );\r\n\t\t\t//printf( \"Max Servers of lobby %d: %d\\n\", lobby_info->m_GroupId, lobby_info->m_MaxServers );\r\n\t\t\tif( lobby_info->m_NumServers > lobby_info->m_MaxServers )\r\n\t\t\t{\r\n\t\t\t\tlobby_info->m_MaxServers = lobby_info->m_NumServers;\r\n\t\t\t}\r\n\t\r\n\t\t\tlobby_info->SetPri( -groupID );\r\n\t\t\tlobby_man->m_lobbies.AddNode( lobby_info );\r\n\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgamenet_man->SetServerListState( vSERVER_LIST_STATE_FAILED_LOBBY_LIST );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tLobbyMan::s_join_room_callback( PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, \r\n\t\t\t\t\t\t\t\t\t\tvoid* param )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tLobbyMan* lobby_man = (LobbyMan*) param;\r\n\r\n\t\r\n\tDbg_Assert( roomType == GroupRoom );\r\n\r\n\tif( success )\r\n\t{\r\n\t\t//printf( \"Entered group room\\n\" );\r\n\t\tScript::RunScript( \"dialog_box_exit\" );\r\n\t\tScript::RunScript( \"create_network_select_games_menu\" );\r\n\t\tlobby_man->m_in_group_room = true;\r\n\r\n\t\tlobby_man->refresh_player_list();\r\n\t\tif( gamenet_man->mpBuddyMan->IsLoggedIn())\r\n\t\t{\r\n\t\t\tchar rating_str[64];\r\n\t\t\tchar key[64];\r\n\t\t\tconst char* keys;\r\n\t\t\tconst char* values;\r\n\r\n\t\t\tgamenet_man->mpBuddyMan->SetStatusAndLocation( GP_CHATTING, (char*) Script::GetString( \"homie_status_chatting\" ), \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlobby_man->GetLobbyName());\r\n\t\t\tsprintf( key, \"b_rating\" );\r\n\t\t\tsprintf( rating_str, \"%d\", gamenet_man->mpStatsMan->GetStats()->GetRating());\r\n\t\t\tkeys = key;\r\n\t\t\tvalues = rating_str;\r\n\t\t\tpeerSetRoomKeys(peer, roomType, peerGetNick( peer ), 1, &keys, &values );\r\n\t\t\tpeerGetRoomKeys( peer, roomType, \"*\", 1, &keys, s_get_room_keys_callback, \r\n\t\t\t\t\t\t\t lobby_man, false );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tswitch( result )\r\n\t\t{\r\n\t\t\tcase PEERFullRoom:\r\n\t\t\t\t//printf( \"Full Room\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase PEERInviteOnlyRoom:\r\n\t\t\t\t//printf( \"Invite Only\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase PEERBannedFromRoom:\r\n\t\t\t\t//printf( \"Banned from room\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase PEERBadPassword:\r\n\t\t\t\t//printf( \"Bad Password\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase PEERAlreadyInRoom:\r\n\t\t\t\t//printf( \"Already in Room\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase PEERNoTitleSet:\r\n\t\t\t\t//printf( \"No Title Set\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase PEERJoinFailed:\r\n\t\t\t\t//printf( \"Generic: Join Failed\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\r\n\t\t};\r\n\t\t\r\n\t\tScript::RunScript( \"CreateJoinLobbyFailedDialog\" );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tLobbyMan::s_lobby_logic_code( const Tsk::Task< LobbyMan >& task )\r\n{\r\n\tLobbyMan& man = task.GetData();\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\tpeerThink( man.m_peer );\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tLobbyMan::s_nat_negotiate_think_code( const Tsk::Task< LobbyMan >& task )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\tNNThink();\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid gamespy_data_handler( char* packet_data, int len, struct sockaddr* sender )\r\n{\r\n\t\r\n\r\n\t//Dbg_Printf( \"Got gamepsy data of length %d\\n\", len );\r\n\t//Dbg_Printf( \"Data[0] = %c\\n\", packet_data[0] );\r\n\t//Dbg_Printf( \"Data[1] = %c\\n\", packet_data[1] );\r\n\r\n\tDbg_Assert( len < 2047 );\r\n\t// backslash as the first character signifies a gamespy packet\r\n\tif( ( (unsigned char) packet_data[0] == QR_MAGIC_1 ) &&\r\n\t\t( (unsigned char) packet_data[1] == QR_MAGIC_2 ))\r\n\t{\r\n\t\t//Dbg_Printf( \"************ GOT GAMESPY QUERY CALL!!!!!!!!\\n\" );\r\n\t\tmemcpy( s_gamespy_parse_data, packet_data, len );\r\n\t\ts_gamespy_sender = *sender;\r\n\t\ts_gamespy_parse_data_len = len;\r\n\t\ts_gamespy_data_type = vGAMESPY_QUERY_DATA;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( len >= NATNEG_MAGIC_LEN )\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"Got Nat Neg data of length %d\\n\", len );\r\n\t\t\tif(\t( (unsigned char) packet_data[0] == NN_MAGIC_0 ) &&\r\n\t\t\t\t( (unsigned char) packet_data[1] == NN_MAGIC_1 ) &&\r\n\t\t\t\t( (unsigned char) packet_data[2] == NN_MAGIC_2 ) &&\r\n\t\t\t\t( (unsigned char) packet_data[3] == NN_MAGIC_3 ) &&\r\n\t\t\t\t( (unsigned char) packet_data[4] == NN_MAGIC_4 ) &&\r\n\t\t\t\t( (unsigned char) packet_data[5] == NN_MAGIC_5 ))\r\n\t\t\t{\r\n\t\t\t\t//Dbg_Printf( \"Magic number matches\\n\" );\r\n                memcpy( s_gamespy_parse_data, packet_data, len );\r\n\t\t\t\ts_gamespy_sender = *sender;\r\n\t\t\t\ts_gamespy_parse_data_len = len;\r\n\t\t\t\ts_gamespy_data_type = vGAMESPY_NAT_DATA;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tLobbyMan::s_process_gamespy_queries_code( const Tsk::Task< LobbyMan >& task )\r\n{\r\n\tLobbyMan& man = task.GetData();\r\n\tTmr::Time current_time;\r\n\r\n\tcurrent_time = Tmr::GetTime();\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\t//if( s_gamespy_parse_data[0] != '\\0' )\r\n\tif( s_gamespy_data_type == vGAMESPY_QUERY_DATA )\r\n\t{\r\n\t\t//Dbg_Printf( \"***** Parsing Gamespy Packet Data...\\n\" ); \r\n\t\t//qr_parse_query( NULL, s_gamespy_parse_data, &s_gamespy_sender );\r\n\t\tpeerParseQuery( man.GetPeer(), s_gamespy_parse_data, s_gamespy_parse_data_len, &s_gamespy_sender );\r\n\t\ts_gamespy_parse_data[0] = '\\0';\r\n\t\ts_gamespy_parse_data_len = 0;\r\n\t\ts_gamespy_data_type = vGAMESPY_NO_DATA;\r\n\t}\r\n\telse if( s_gamespy_data_type == vGAMESPY_NAT_DATA )\r\n\t{\r\n\t\t//Dbg_Printf( \"Processing Nat Neg data\\n\" );\r\n        NNProcessData( s_gamespy_parse_data, s_gamespy_parse_data_len, (sockaddr_in*) &s_gamespy_sender );\r\n\t\ts_gamespy_parse_data[0] = '\\0';\r\n\t\ts_gamespy_parse_data_len = 0;\r\n\t\ts_gamespy_data_type = vGAMESPY_NO_DATA;\r\n\t}\r\n\telse if( s_got_gamespy_callback == false )\r\n\t{\r\n\t\tManager * gamenet_man = Manager::Instance();\r\n\r\n\t\tif( gamenet_man->InNetGame() && gamenet_man->OnServer())\r\n\t\t{\r\n\t\t\t// After N seconds, if we have yet to be contacted by GameSpy, notify the user that his server\r\n\t\t\t// was not properly posted to GameSpy\r\n\t\t\tif( ( current_time - s_game_start_time ) > vPOST_SERVER_TIMEOUT )\r\n\t\t\t{\r\n\t\t\t\t\r\n\t\t\t\tif( s_notified_user_not_connected == false )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript( \"CreateNotPostedDialog\" );\r\n\t\t\t\t\ts_notified_user_not_connected = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if(( current_time - s_last_post_time ) > vPOST_SERVER_RETRY_TIME )\r\n\t\t\t{\r\n\t\t\t\t// Gamespy still hasn't queried us for our options. Let's tell them again\r\n\t\t\t\t// that our server is up\r\n\t\t\t\tpeerStateChanged( man.GetPeer());\r\n\t\t\t\ts_last_post_time = current_time;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t//qr_process_queries( NULL );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Handler Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nLobbyMan::LobbyMan( void )\r\n{\r\n\tm_in_group_room = false;\r\n\tm_expecting_disconnect = true;\r\n\tm_peer = NULL;\r\n\r\n\tm_lobby_logic_task = new Tsk::Task< LobbyMan > ( s_lobby_logic_code, *this );\r\n\tm_nat_negotiate_task = new Tsk::Task< LobbyMan > ( s_nat_negotiate_think_code, *this );\r\n\tm_process_gamespy_queries_task = new Tsk::Task< LobbyMan > ( s_process_gamespy_queries_code, *this );\r\n\tqr2_register_key( NUMOBSERVERS_KEY, \"numobservers\" );\r\n\tqr2_register_key( MAXOBSERVERS_KEY, \"maxobservers\" );\r\n\tqr2_register_key( SKILLLEVEL_KEY, \"skilllevel\" );\r\n\tqr2_register_key( STARTED_KEY, \"started\" );\r\n\tqr2_register_key( HOSTED_MODE_KEY, \"hostmode\" );\r\n\tqr2_register_key( RANKED_KEY, \"ranked\" );\r\n\tqr2_register_key( RATING__KEY, \"rating_\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nLobbyMan::~LobbyMan( void )\r\n{\r\n\tdelete m_lobby_logic_task;\r\n\tdelete m_nat_negotiate_task;\r\n\tdelete m_process_gamespy_queries_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::StartReportingGame( void )\r\n{\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tNet::Server* server;\r\n\tPEERBool result;\r\n\r\n\tserver = gamenet_man->GetServer();\r\n\tDbg_Assert( server );\r\n\t\r\n\tserver->SetForeignPacketHandler( gamespy_data_handler );\r\n\ts_gamespy_parse_data[0] = '\\0';\r\n\ts_gamespy_data_type = vGAMESPY_NO_DATA;\r\n    \r\n\tresult = peerStartReportingWithSocket( m_peer, server->GetSocket(), vHOST_PORT );\r\n\tif( result == true )\r\n\t{\r\n\t\tpeerStateChanged( m_peer );\r\n\t}\r\n\r\n\ts_game_start_time = Tmr::GetTime();\r\n\ts_last_post_time = s_game_start_time;\r\n\ts_notified_user_not_connected = false;\r\n\ts_got_gamespy_callback = false;\r\n\tmlp_manager->AddLogicTask( *m_process_gamespy_queries_task );\r\n\tm_reported_game = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::StopReportingGame( void )\r\n{\r\n\tif( m_peer )\r\n\t{\r\n        peerStopGame( m_peer );\r\n\t\tm_process_gamespy_queries_task->Remove();\r\n\t}\r\n\r\n\tm_reported_game = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tLobbyMan::ReportedGame( void )\r\n{\r\n\treturn m_reported_game;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::StartLobbyList( void )\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\t//Thread::PerThreadStruct\tnet_thread_data;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n    gamenet_man->SetServerListState( vSERVER_LIST_STATE_GETTING_LOBBY_LIST );\r\n\r\n\t// Reset the server list refresh time so that the 1-second minimum rule for refreshing server\r\n\t// lists won't apply when going back and forth really quickly to/from lobby/server lists\r\n\ts_last_refresh_time = 0;\r\n\r\n\tpeerListGroupRooms( m_peer, \"\\\\maxplayers\\\\neversoft\\\\maxrating\\\\minrating\", s_group_rooms_callback, this, false );\r\n    \r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::StopLobbyList( void )\r\n{\r\n\tLst::Search< LobbyInfo > sh;\r\n\tLobbyInfo* lobby, *next;\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tif( m_peer )\r\n\t{\r\n\t\tpeerStopListingGames( m_peer );\r\n\t}\r\n\r\n\tfor( lobby = sh.FirstItem( m_lobbies ); lobby; lobby = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tdelete lobby;\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::FillLobbyList( void )\r\n{\r\n\tLst::Search< LobbyInfo > sh;\r\n\tLobbyInfo* lobby;\r\n\tint index;\r\n\r\n\tScript::RunScript( \"dialog_box_exit\" );\r\n\tScript::RunScript( \"create_lobby_list_menu\" );\r\n\t\r\n\tindex = 0;\r\n\tfor( lobby = sh.FirstItem( m_lobbies ); lobby; lobby = sh.NextItem())\r\n\t{\r\n\t\tadd_lobby_to_menu( lobby, index++ );    \r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nLobbyInfo*\tLobbyMan::GetLobbyInfo( int index )\r\n{\r\n\tLst::Search< LobbyInfo > sh;\r\n\tLobbyInfo* lobby;\r\n\r\n\tfor( lobby = sh.FirstItem( m_lobbies ); lobby; lobby = sh.NextItem())\r\n\t{\r\n\t\tif( index == 0 )\r\n\t\t{\r\n\t\t\treturn lobby;\r\n\t\t}\r\n\r\n\t\tindex--;\r\n\t}\r\n\t\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::SetLobbyId( int id )\r\n{\r\n\tm_lobby_id = id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\tLobbyMan::GetLobbyId( void )\r\n{\r\n\treturn m_lobby_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::SetLobbyNumServers( int num_servers )\r\n{\r\n\tm_lobby_num_servers = num_servers;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\tLobbyMan::GetLobbyNumServers( void )\r\n{\r\n\treturn m_lobby_num_servers;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::SetLobbyMaxServers( int max_servers )\r\n{\r\n\tm_lobby_max_servers = max_servers;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\tLobbyMan::GetLobbyMaxServers( void )\r\n{\r\n\treturn m_lobby_max_servers;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::SetLobbyName( char* name )\r\n{\r\n\tDbg_Assert( name );\r\n\r\n\tstrcpy( m_lobby_name, name );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\t\tLobbyMan::GetLobbyName( void )\r\n{\r\n\treturn m_lobby_name;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::SetServerName( char* name )\r\n{\r\n\tstrcpy( m_server_name, name );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\t\tLobbyMan::GetServerName( void )\r\n{\r\n\treturn m_server_name;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tLobbyMan::SetOfficialLobby( bool official )\r\n{\r\n\tm_official = official;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tLobbyMan::IsLobbyOfficial( void )\r\n{\r\n\treturn m_official;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \tLobbyMan::s_nat_negotiate_complete( NegotiateResult result, SOCKET gamesocket, \r\n\t\t\t\t\t\t\t\t\t\t\t\tstruct sockaddr_in *remoteaddr, void *userdata )\r\n{\r\n\tManager* gamenet_man = Manager::Instance();\r\n\tint cookie;\r\n\r\n\tcookie = (int) userdata;\r\n\r\n\tDbg_Printf( \"**** NAT Negotiation Complete: %d\\n\", result );\r\n\tswitch( result )\r\n\t{\r\n\t\tcase nr_success:\r\n\t\t{\r\n\t\t\tDbg_Printf( \"**** NAT Negotiation Complete: Success!\\n\" );\r\n\r\n\t\t\tif( !gamenet_man->OnServer())\r\n\t\t\t{\r\n\t\t\t\tbool observe_only;\r\n\t\t\t\tDbg_Printf( \"**** IP: %s Port: %d\\n\", inet_ntoa( remoteaddr->sin_addr ), ntohs( remoteaddr->sin_port ));\r\n\t\t\t\tobserve_only = ( gamenet_man->GetJoinMode() == GameNet::vJOIN_MODE_OBSERVE );\r\n\t\t\t\tgamenet_man->JoinServer( observe_only, (int) remoteaddr->sin_addr.s_addr, ntohs( remoteaddr->sin_port ), 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase nr_deadbeatpartner:\r\n\t\t\tDbg_Printf( \"**** NAT Negotiation Complete: Deadbeat Partner\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase nr_inittimeout:\r\n\t\t\tDbg_Printf( \"**** NAT Negotiation Complete: Timeout\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase nr_unknownerror:\r\n\t\tdefault:\r\n\t\t\tDbg_Printf( \"**** NAT Negotiation Complete: Unknown Error\\n\" );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\tgamenet_man->mpLobbyMan->m_nat_count.Release();\r\n\t\tif( gamenet_man->mpLobbyMan->m_nat_count.InUse() == false )\r\n\t\t{\r\n\t\t\tgamenet_man->mpLobbyMan->m_nat_negotiate_task->Remove();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNet::Client* client;\r\n\r\n\t\tNNCancel( cookie );\r\n\t\tNNThink();\r\n\t\tNNFreeNegotiateList();\r\n\r\n\t\tclient = gamenet_man->GetClient( 0 );\r\n\t\tclient->SetForeignPacketHandler( NULL );\r\n\t\tgamenet_man->mpLobbyMan->m_nat_negotiate_task->Remove();\r\n\t\tgamenet_man->mpLobbyMan->m_process_gamespy_queries_task->Remove();\r\n\r\n\t\tif( result != nr_success )\r\n\t\t{\r\n\t\t\tScript::RunScript( \"show_nat_timeout\" );\r\n\t\t}\r\n\t}\r\n\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \tLobbyMan::s_nat_negotiate_progress( NegotiateState state, void *userdata )\r\n{\r\n    switch( state )\r\n\t{\r\n\t\tcase ns_initack:\r\n\t\t\tDbg_Printf( \"**** NAT Negotiation : Init Ack State\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase ns_connectping:\r\n\t\t\tDbg_Printf( \"**** NAT Negotiation : Connect Ping State\\n\" );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_Printf( \"**** NAT Negotiation : Unknown State\\n\" );\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tLobbyMan::ScriptCancelNatNegotiation(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager* gamenet_man = Manager::Instance();\r\n\r\n\tNNCancel( gamenet_man->mpLobbyMan->m_cookie );\r\n\tNNThink();\r\n\tNNFreeNegotiateList();\r\n\t\r\n\tgamenet_man->mpLobbyMan->m_nat_negotiate_task->Remove();\r\n\tgamenet_man->mpLobbyMan->m_process_gamespy_queries_task->Remove();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tLobbyMan::ScriptStartNatNegotiation(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager* gamenet_man = Manager::Instance();\r\n\tLobbyMan* lobby_man;\r\n\tMlp::Manager* mlp_manager = Mlp::Manager::Instance();\r\n\tNet::Client* client;\r\n\tconst char *server_ip = NULL;\r\n\tint port = 0;\r\n\tNegotiateError err;\r\n    \r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tlobby_man = gamenet_man->mpLobbyMan;\r\n\tpParams->GetText( NONAME, &server_ip );\r\n\tpParams->GetInteger( NONAME, &port );\r\n\tpParams->GetChecksum( CRCD( 0x751f4599, \"cookie\" ), (uint32*) &lobby_man->m_cookie );\r\n\t\r\n    //port = 9959;\r\n\tDbg_Printf( \"******* Starting NAT Negotiation for server : %s port %p *******\", server_ip, port );\r\n\t\r\n\tclient = gamenet_man->SpawnClient( false, false, true, 0 );\r\n    peerSendNatNegotiateCookie( lobby_man->GetPeer(), inet_addr( server_ip ), \r\n\t\t\t\t\t\t\t\tport, lobby_man->m_cookie );\r\n    err = NNBeginNegotiationWithSocket( client->GetSocket(), lobby_man->m_cookie, 1, s_nat_negotiate_progress, \r\n\t\t\t\t\t\t\t\t\t\ts_nat_negotiate_complete, (void*) lobby_man->m_cookie );\r\n\tif( err != ne_noerror )\r\n\t{\r\n\t\tDbg_Printf( \"******* NAT Neg Error: %d\\n\", err );\r\n\t\tNNFreeNegotiateList();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\treturn false;\r\n\t}\r\n\tDbg_Assert( err == ne_noerror );\r\n\r\n\tDbg_Printf( \"*** Added NAT Task\\n\" );\r\n\tmlp_manager->AddLogicTask( *lobby_man->m_nat_negotiate_task );\r\n\tclient->SetForeignPacketHandler( gamespy_data_handler );\r\n\tmlp_manager->AddLogicTask( *lobby_man->m_process_gamespy_queries_task );\r\n\ts_gamespy_parse_data[0] = '\\0';\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tLobbyMan::ScriptRejoinLobby(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager* gamenet_man = Manager::Instance();\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tpeerJoinGroupRoom( gamenet_man->mpLobbyMan->m_peer, gamenet_man->mpLobbyMan->GetLobbyId(), s_join_room_callback, gamenet_man->mpLobbyMan, false );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tLobbyMan::ScriptChooseLobby(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tLobbyInfo* p_lobby;\r\n\tManager* gamenet_man = Manager::Instance();\r\n\tint index = 0;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tpParams->GetInteger( Script::GenerateCRC(\"index\"), &index );\r\n\t\t\t\t\r\n\tp_lobby = gamenet_man->mpLobbyMan->GetLobbyInfo( index );\r\n\tDbg_Assert( p_lobby );\r\n\t\t\t\t\t\t\t\t\r\n\t//Dbg_Printf( \"Choosing lobby %d\\n\", p_lobby->m_GroupId );\r\n\tgamenet_man->mpLobbyMan->SetLobbyId( p_lobby->m_GroupId );\r\n\tgamenet_man->mpLobbyMan->SetLobbyNumServers( p_lobby->m_NumServers );\r\n\tgamenet_man->mpLobbyMan->SetLobbyMaxServers( p_lobby->m_MaxServers );\r\n\tgamenet_man->mpLobbyMan->SetLobbyName( p_lobby->m_Name );\r\n\tgamenet_man->mpLobbyMan->SetOfficialLobby( p_lobby->m_Official );\r\n\t\r\n    peerJoinGroupRoom( gamenet_man->mpLobbyMan->m_peer, gamenet_man->mpLobbyMan->GetLobbyId(), s_join_room_callback, gamenet_man->mpLobbyMan, false );\r\n\r\n\t// Don't need the lobby list anymore. We have recorded all its data\r\n\tgamenet_man->mpLobbyMan->StopLobbyList();\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tLobbyMan::ScriptGetNumPlayersInLobby(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager* gamenet_man = Manager::Instance();\r\n\tScript::CStruct* p_return_params;\r\n\r\n\tp_return_params = pScript->GetParams();\r\n\tp_return_params->AddInteger( \"num_players\", gamenet_man->mpLobbyMan->m_players.CountItems());\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tLobbyMan::ScriptLeaveLobby(Script::CScriptStructure *pParams, Script::CScript* pScript )\r\n{\r\n\tManager* gamenet_man = Manager::Instance();\r\n\tLobbyMan* lobby_man;\r\n\tBuddyMan* buddy_man;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tlobby_man = gamenet_man->mpLobbyMan;\r\n\tbuddy_man = gamenet_man->mpBuddyMan;\r\n\r\n\tpeerLeaveRoom( lobby_man->m_peer, GroupRoom, NULL );\r\n\tlobby_man->m_in_group_room = false;\r\n\r\n\tif( buddy_man->IsLoggedIn())\r\n\t{\r\n\t\tif( !pParams->ContainsComponentNamed( CRCD(0xb2ab4dab,\"preserve_status\")))\r\n\t\t{\r\n\t\t\tbuddy_man->SetStatusAndLocation( GP_ONLINE, \t(char*) Script::GetString( \"homie_status_online\" ), \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(char*) Script::GetString( \"homie_status_logging_in\" ));\r\n\t\t}\r\n\t}\r\n\r\n\t// Maintain our association with our group room so that, if we're hosting a game, it will\r\n\t// report it to the correct group room\r\n\tpeerSetGroupID( lobby_man->m_peer, lobby_man->GetLobbyId());\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tLobbyMan::ScriptLobbyConnect(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tPEERBool ping_rooms[NumRooms] = {false, true, false};\r\n\tPEERBool x_ping_rooms[NumRooms] = {false, false, false};\r\n\tPEER peer;\r\n\tThread::PerThreadStruct\tnet_thread_data;\r\n    \r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\t\r\n\tgamenet_man->mpLobbyMan->Initialize();\r\n\t\r\n\tpeer = gamenet_man->mpLobbyMan->m_peer;\r\n\tpeerSetTitle( peer, \r\n\t\t\t\t  \"thps5ps2\", \r\n\t\t\t\t  \"G2k8cF\", \r\n\t\t\t\t  \"thps5ps2\", \r\n\t\t\t\t  \"G2k8cF\", \r\n\t\t\t\t  vGAME_VERSION,\r\n\t\t\t\t  15, \r\n\t\t\t\t  true,\r\n\t\t\t\t  ping_rooms, \r\n\t\t\t\t  x_ping_rooms );\r\n\r\n\tDbg_Printf( \"Connecting to lobby 1\\n\" );\r\n\tnet_thread_data.m_pEntry = s_threaded_peer_connect;\r\n\tnet_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY;\r\n\tnet_thread_data.m_pStackBase = gamenet_man->GetNetThreadStack();\r\n\tnet_thread_data.m_iStackSize = vNET_THREAD_STACK_SIZE;\r\n\tnet_thread_data.m_utid = 0x152;\r\n\tThread::CreateThread( &net_thread_data );\r\n\tgamenet_man->SetNetThreadId( net_thread_data.m_osId );\r\n\tStartThread( gamenet_man->GetNetThreadId(), gamenet_man->mpLobbyMan );\r\n\tDbg_Printf( \"Connecting to lobby 2\\n\" );\r\n\tmlp_man->AddLogicTask( *gamenet_man->mpLobbyMan->m_lobby_logic_task );\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tLobbyMan::ScriptLobbyDisconnect(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tDbg_Printf( \"******************************* DISCONNECTING FROM PEER!!!! \\n\" );\r\n\r\n\twhile( gamenet_man->mpLobbyMan->m_nat_count.InUse())\r\n\t{\r\n\t\tgamenet_man->mpLobbyMan->m_nat_count.Release();\r\n\t}\r\n\r\n\tgamenet_man->mpLobbyMan->StopLobbyList();\r\n\tgamenet_man->mpLobbyMan->clear_player_list();\r\n\tgamenet_man->mpLobbyMan->m_lobby_logic_task->Remove();\r\n\tgamenet_man->mpLobbyMan->m_nat_negotiate_task->Remove();\r\n\tgamenet_man->mpLobbyMan->m_in_group_room = false;\r\n\tgamenet_man->mpLobbyMan->m_expecting_disconnect = true;\r\n\tif( gamenet_man->mpLobbyMan->m_peer )\r\n\t{\r\n\t\tpeerStopGame( gamenet_man->mpLobbyMan->m_peer );\r\n\t\tpeerClearTitle( gamenet_man->mpLobbyMan->m_peer );\r\n\t\tpeerDisconnect( gamenet_man->mpLobbyMan->m_peer );\r\n\t}\r\n\tgamenet_man->mpLobbyMan->Shutdown();\r\n\t//peerShutdown( gamenet_man->mpLobbyMan->m_peer );\r\n\t//gamenet_man->mpLobbyMan->m_peer = NULL;\r\n\r\n\t//Dbg_Printf( \"******************************* DISCONNECTED FROM PEER!!!! \\n\" );\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tLobbyMan::ScriptSetQuietMode( Script::CScriptStructure* pParams, Script::CScript* pScript )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\tif( pParams->ContainsFlag( \"off\" ))\r\n\t{\r\n\t\tpeerSetQuietMode( gamenet_man->mpLobbyMan->m_peer, false );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpeerSetQuietMode( gamenet_man->mpLobbyMan->m_peer, true );\r\n\t}\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tLobbyMan::ScriptFillPlayerList( Script::CScriptStructure* pParams, Script::CScript* pScript )\r\n{\r\n\tSpt::SingletonPtr< GameNet\r\n\t\t::Manager > gamenet_man;\r\n\r\n\tgamenet_man->mpLobbyMan->fill_player_list();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tLobbyMan::ScriptFillLobbyProspectiveBuddyList( Script::CScriptStructure* pParams, Script::CScript* pScript )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->mpLobbyMan->fill_prospective_buddy_list();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tLobbyMan::ScriptCanHostGame( Script::CScriptStructure* pParams, Script::CScript* pScript )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tif( gamenet_man->mpLobbyMan->IsLobbyOfficial())\r\n\t{\r\n\t\tif( gamenet_man->mpBuddyMan->IsLoggedIn())\r\n\t\t{\r\n\t\t\tint profile;\r\n\r\n\t\t\tprofile = gamenet_man->mpBuddyMan->GetProfile();\r\n\t\t\tif(\t( profile == 27747931 ) ||\r\n\t\t\t\t( profile == 27747977 ) ||\r\n\t\t\t\t( profile == 27748011 ) ||\r\n\t\t\t\t( profile == 27748097 ) ||\r\n\t\t\t\t( profile == 27748044 ) ||\r\n\t\t\t\t( profile == 27748142 ) ||\r\n\t\t\t\t( profile == 27748187 ) ||\r\n\t\t\t\t( profile == 27748211 ) ||\r\n\t\t\t\t( profile == 27748244 ) ||\r\n\t\t\t\t( profile == 27748273 ))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn( gamenet_man->mpLobbyMan->GetLobbyNumServers() < gamenet_man->mpLobbyMan->GetLobbyMaxServers());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tLobbyMan::ScriptSendMessage( Script::CScriptStructure* pParams, Script::CScript* pScript )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tconst char *p_text;\r\n\t\r\n\tif( pParams->GetText( \"text\", &p_text ))\r\n\t{\r\n\t\tif( pParams->ContainsFlag( \"system_message\" ))\r\n\t\t{\r\n\t\t\tScript::CStruct* p_params;\r\n\t\t\tchar msg[1024];\r\n\t\t\r\n\t\t\tsprintf( msg, \"<System> %s\", p_text );\r\n\t\t\tp_params = new Script::CStruct;\t\r\n\t\t\tp_params->AddString( \"text\", msg );\r\n\t\t\tScript::RunScript(\"create_console_message\", p_params );\r\n\t\t\tdelete p_params;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\t\t\tpeerMessageRoom( gamenet_man->mpLobbyMan->m_peer, GroupRoom, p_text, NormalMessage );\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tLobbyMan::Initialize( void )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\tPEERCallbacks callbacks;\r\n\r\n\tmemset( &callbacks, 0, sizeof( PEERCallbacks ));\r\n\tcallbacks.disconnected = s_disconnected_callback;\r\n\tcallbacks.roomMessage = s_room_message_callback;\r\n\tcallbacks.playerMessage = s_player_message_callback;\r\n\tcallbacks.playerJoined = s_player_joined_callback;\r\n\tcallbacks.playerLeft = s_player_left_callback;\r\n\tcallbacks.playerInfo = s_player_info_callback;\r\n\tcallbacks.newPlayerList = s_new_player_list_callback;\r\n\tcallbacks.roomKeyChanged = s_room_key_callback;\r\n\r\n    callbacks.qrNatNegotiateCallback = s_nat_negotiate_callback;\r\n\tcallbacks.qrKeyList = s_key_list_callback;\r\n\tcallbacks.qrServerKey = s_server_key_callback;\r\n\tcallbacks.qrPlayerKey = s_player_key_callback;\r\n\tcallbacks.qrCount = s_key_count_callback;\r\n\tcallbacks.qrAddError = s_add_error_callback;\r\n\tcallbacks.qrPublicAddressCallback = s_public_address_callback;\r\n\tcallbacks.param = this;\r\n\t\r\n\tm_peer = peerInitialize( &callbacks );\r\n\tDbg_Assert( m_peer );\r\n\t\r\n\tm_in_group_room = false;\r\n\tm_expecting_disconnect = true;\r\n\tm_reported_game = false;\r\n\tm_official = false;\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tLobbyMan::Shutdown( void )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tm_lobby_logic_task->Remove();\r\n\tm_nat_negotiate_task->Remove();\r\n\tm_process_gamespy_queries_task->Remove();\r\n\r\n\tif( m_peer )\r\n\t{\r\n\t\tpeerShutdown( m_peer );\r\n\t}\r\n\tm_peer = NULL;\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPEER\tLobbyMan::GetPeer( void )\r\n{\r\n\treturn m_peer;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nbool\tLobbyMan::InGroupRoom( void )\r\n{\r\n\treturn m_in_group_room;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\tLobbyMan::PlayerName( char* lobby_name )\r\n{\r\n\tchar* player_name;\r\n\r\n\tplayer_name = strchr( lobby_name, '_' );\r\n\tif( player_name == NULL )\r\n\t{\r\n\t\treturn lobby_name;\r\n\t}\r\n\treturn ( player_name + 1 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nLobbyPlayerInfo::LobbyPlayerInfo( void ) : Lst::Node< LobbyPlayerInfo > ( this )\r\n{\r\n\tm_Profile = 0;\r\n\tm_Rating = 0;\r\n\tm_GotInfo = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n} // namespace GameNet\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Lobby.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tLobby.h\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t04/04/02\t- spg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__LOBBY_H\r\n#define\t__LOBBY_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <peer/peer.h>\r\n#include <natneg/natneg.h>\r\n\r\nnamespace GameNet\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nenum\r\n{\r\n\tNUMOBSERVERS_KEY = NUM_RESERVED_KEYS + 1,\r\n\tMAXOBSERVERS_KEY,\r\n\tSKILLLEVEL_KEY,\r\n\tSTARTED_KEY,\r\n\tHOSTED_MODE_KEY,\r\n\tRANKED_KEY,\r\n\tRATING__KEY,\r\n};\r\n\t\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass LobbyPlayerInfo : public Lst::Node< LobbyPlayerInfo >\r\n{\r\n\tpublic:\r\n\t\tLobbyPlayerInfo( void );\r\n\r\n\t\tchar\tm_Name[64];\r\n\t\tint\t\tm_Profile;\r\n\t\tint\t\tm_Rating;\r\n\t\tbool\tm_GotInfo;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass LobbyMan\r\n{\r\npublic:\r\n\t\t\t\tLobbyMan( void );\r\n\t\t\t\t~LobbyMan( void );\r\n\r\n\tvoid\t\tInitialize( void );\r\n\tvoid\t\tShutdown( void );\r\n\r\n\tvoid\t\tStartReportingGame( void );\r\n\tvoid\t\tStopReportingGame( void );\r\n\tbool\t\tReportedGame( void );\r\n\r\n\tvoid\t\tStartLobbyList( void );\r\n\tvoid\t\tStopLobbyList( void );\r\n\tvoid\t\tFillLobbyList( void );\r\n\r\n\tLobbyInfo*\tGetLobbyInfo( int index );\r\n\r\n\tvoid\t\tSetLobbyId( int id );\r\n\tint\t\t\tGetLobbyId( void );\r\n\tvoid\t\tSetLobbyNumServers( int num_servers );\r\n\tint\t\t\tGetLobbyNumServers( void );\r\n\tvoid\t\tSetLobbyMaxServers( int max_servers );\r\n\tint\t\t\tGetLobbyMaxServers( void );\r\n\tchar*\t\tGetServerName( void );\r\n\tvoid\t\tSetServerName( char* name );\r\n\tvoid\t\tSetLobbyName( char* name );\r\n\tchar*\t\tGetLobbyName( void );\r\n\tvoid\t\tSetOfficialLobby( bool official );\r\n\tbool\t\tIsLobbyOfficial( void );\r\n\r\n\tPEER\t\tGetPeer( void );\r\n\tbool\t\tInGroupRoom( void );\r\n\tchar*\t\tPlayerName( char* lobby_name );\r\n    \r\n\tstatic\tbool\tScriptGetNumPlayersInLobby(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\tScriptChooseLobby(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\tScriptRejoinLobby(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\tScriptLeaveLobby(Script::CScriptStructure *pParams, Script::CScript* pScript );\r\n\tstatic\tbool\tScriptLobbyConnect(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\tScriptLobbyDisconnect(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\tScriptSendMessage( Script::CScriptStructure* pParams, Script::CScript* pScript );\r\n\tstatic\tbool\tScriptSetQuietMode( Script::CScriptStructure* pParams, Script::CScript* pScript );\r\n\tstatic\tbool\tScriptFillPlayerList( Script::CScriptStructure* pParams, Script::CScript* pScript );\r\n\tstatic\tbool\tScriptFillLobbyProspectiveBuddyList( Script::CScriptStructure* pParams, Script::CScript* pScript );\r\n\tstatic\tbool\tScriptCanHostGame( Script::CScriptStructure* pParams, Script::CScript* pScript );\r\n\tstatic\tbool\tScriptStartNatNegotiation(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\tScriptCancelNatNegotiation(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nprivate:\r\n\tLst::Head< LobbyInfo > \tm_lobbies;\r\n\tLst::Head< LobbyPlayerInfo > m_players;\r\n\r\n\tint\t\t\t\tm_lobby_id;\r\n\tint\t\t\t\tm_lobby_max_servers;\r\n\tint\t\t\t\tm_lobby_num_servers;\r\n\tchar\t\t\tm_lobby_name[128];\r\n\tchar\t\t\tm_server_name[128];\r\n\tbool\t\t\tm_in_group_room;\r\n\tbool\t\t\tm_official;\r\n\t\r\n\tbool\t\t\tm_expecting_disconnect;\r\n\tbool\t\t\tm_connection_in_progress;\r\n\tbool\t\t\tm_reported_game;\r\n\r\n\tSpt::Ref\t\tm_nat_count;\r\n\t\t\r\n\tPEER\t\t\tm_peer;\r\n\tint\t\t\t\tm_cookie;\r\n\t\r\n\tvoid\t\t\tadd_lobby_to_menu( LobbyInfo* lobby, int index );\r\n\tvoid\t\t\tadd_player_to_menu( LobbyPlayerInfo* player );\r\n\tvoid\t\t\tadd_buddy_to_menu( LobbyPlayerInfo* player );\r\n\tvoid\t\t\trefresh_player_list( void );\r\n\tvoid\t\t\tclear_player_list( void );\r\n\tvoid\t\t\tfill_player_list( void );\r\n\tvoid\t\t\tfill_prospective_buddy_list( void );\r\n\r\n\tTsk::Task< LobbyMan >*\t\tm_lobby_logic_task;\r\n\tTsk::Task< LobbyMan >*\t\tm_nat_negotiate_task;\r\n\tTsk::Task< LobbyMan >*\t\tm_process_gamespy_queries_task;\r\n\tstatic\tTsk::Task< LobbyMan >::Code   \ts_lobby_logic_code;\r\n\tstatic\tTsk::Task< LobbyMan >::Code   \ts_nat_negotiate_think_code;\r\n\tstatic\tTsk::Task< LobbyMan >::Code\t\ts_process_gamespy_queries_code;\r\n\r\n\tstatic\tvoid\ts_enum_players_callback( PEER peer, PEERBool success, RoomType roomType, int index, const char * nick,  // The nick of the player.\r\n\t\t\t\t\t\t\t\t\t\t\t\tint flags, void * param );\r\n\tstatic \tvoid\ts_nick_error_callback( PEER peer, int type, const char* nick, void *param );\r\n\tstatic\tvoid\ts_connect_callback( PEER peer, PEERBool success, void* param );\r\n\r\n\tstatic\tvoid \ts_disconnected_callback( PEER peer, const char* reason, void* param );\r\n\tstatic\tvoid \ts_room_message_callback( PEER peer, RoomType roomType, const char * nick, const char * message,\r\n\t\t\t\t\t\t\t\t\t\tMessageType messageType, void * param );\r\n\tstatic\tvoid \ts_player_message_callback( PEER peer, const char * nick, const char * message, MessageType messageType,\r\n\t\t\t\t\t\t\t\t\t\t\t\tvoid * param );\r\n\tstatic \tvoid \ts_player_joined_callback( PEER peer, RoomType roomType, const char * nick, void * param );\r\n\tstatic\tvoid \ts_player_info_callback( PEER peer, RoomType roomType, const char * nick, unsigned int IP, int profileID,  \r\n                                                void * param );\r\n\tstatic\tvoid\ts_player_proile_id_callback( PEER peer, PEERBool success,  const char * nick, int profileID, void * param );\r\n\tstatic\tvoid\ts_player_left_callback( PEER peer, RoomType roomType, const char * nick, const char * reason, \r\n\t\t\t\t\t\t\t\t\t\t\t\tvoid * param );\r\n\tstatic\tvoid\ts_new_player_list_callback( PEER peer, RoomType roomType, void * param );\r\n\tstatic\tvoid\ts_room_key_callback( PEER peer, RoomType roomType, const char * nick, \r\n\t\t\t\t\t\t\t\t\t\t const char * key, const char * value, void * param );\r\n\tstatic\tvoid\ts_nat_negotiate_callback( PEER peer, int cookie, void * param );\r\n\tstatic\tvoid\ts_key_list_callback( PEER peer, qr2_key_type type, qr2_keybuffer_t keyBuffer, \r\n\t\t\t\t\t\t\t\t\tvoid * param );\r\n\tstatic\tvoid\ts_server_key_callback( PEER peer, int key, qr2_buffer_t buffer, void * param );\r\n\tstatic\tvoid\ts_player_key_callback( PEER peer, int key, int index, qr2_buffer_t buffer, void * param );\r\n\tstatic\tint\t\ts_key_count_callback( PEER peer, qr2_key_type type, void * param );\r\n\tstatic\tvoid    s_add_error_callback( PEER peer, qr2_error_t error, char * errorString, void * param );\r\n\tstatic\tvoid    s_public_address_callback( PEER peer, unsigned int ip, unsigned short port, \r\n\t\t\t\t\t\t\t\t\t\t\t   void * param );\r\n\tstatic\tvoid\ts_public_address_callback( PEER peer, qr2_error_t error, char * errorString, void * param );\r\n\r\n\tstatic\tvoid\ts_group_rooms_callback( PEER peer, PEERBool success, int groupID, SBServer server,  \r\n\t\t\t\t\t\t\t\t\tconst char * name, int numWaiting, int maxWaiting, int numGames, int numPlaying,\r\n\t\t\t\t\t\t\t\t\tvoid* param );\r\n\tstatic\tvoid\ts_join_room_callback( PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, \r\n\t\t\t\t\t\t\t\t\t\tvoid * param );\r\n\tstatic\tvoid \ts_get_room_keys_callback( PEER peer, PEERBool success, RoomType roomType, \r\n\t\t\t\t\t\t\t\t\t\t\tconst char * nick, int num, char ** keys, char ** values, \r\n\t\t\t\t\t\t\t\t\t\t\tvoid * param );\r\n\r\n\t//static \tvoid \ts_lobby_list_callback( GServerList serverlist, int msg, void *instance, void *param1, void *param2 );\r\n\t//static\tvoid\ts_threaded_get_lobby_list( LobbyMan* lobby_man );\r\n\r\n\tstatic\tvoid\ts_threaded_peer_connect( LobbyMan* lobby_man );\r\n\tstatic\tvoid\ts_nat_negotiate_progress( NegotiateState state, void *userdata );\r\n\tstatic\tvoid\ts_nat_negotiate_complete( NegotiateResult result, SOCKET gamesocket, \r\n\t\t\t\t\t\t\t\t\t\t\t\tstruct sockaddr_in *remoteaddr, void *userdata);\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n}\t// namespace GameNet\r\n\r\n#endif\t// __LOBBY_H"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/dnas.cpp",
    "content": "#include <stdio.h>\r\n#include <libgraph.h>\r\n#include <dnas/dnas2.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/config/config.h>\r\n#include <gamenet/gamenet.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <libcdvd.h>\r\n\r\n#define WAIT_VSYNC\t0x1111\r\n#define vAUTH_TIMEOUT\t30\r\n\r\nstatic\tint\ts_extra_time = 0;\r\n\r\n//#define __DNAS_DEBUG__\r\n\r\nstatic int s_get_thread_priority( void )\r\n{\r\n\tstruct ThreadParam info;\r\n\t// Fill info with zeros to be sure the following call is doing\r\n\t// something to info\r\n\tmemset(&info,0,sizeof(info));\r\n\t// return value not defined in 2.0 PDF EE lib ref\r\n\tReferThreadStatus( GetThreadId(), &info );\r\n\treturn ( info.currentPriority );\r\n}\r\n\r\nstatic int netstart_dnas(int proxy_state, const char *proxy_host, u_short proxy_port, int timeout, sceDNAS2Status_t& status) \r\n{\r\n\tint  ret, error = 0;\r\n\tsceDNAS2TitleAuthInfo_t auth_info;\r\n\tsceDNAS2Status_t prev_status;\r\n\tsceDNAS2TimeoutInfo_t timeout_info;\r\n\tint /*fd, */proxy_state_check = 0;\r\n\tchar* auth_data;\r\n\tchar proxy_host_check[512];\r\n\tu_short proxy_port_check;\r\n\tunsigned char* phrase;\r\n\t//int vsync_handler_id;\r\n\tint orig_priority;\r\n\r\n    unsigned char us_english_pass_phrase[] = { 0xfb, 0x31, 0xce, 0xf7, 0x2a, 0x57, 0x2f, 0xf4 };\r\n\tunsigned char uk_english_pass_phrase[] = { 0xea, 0x67, 0x94, 0x2c, 0x37, 0xd1, 0xfc, 0x8f };\r\n\tunsigned char spanish_pass_phrase[] = { 0xb5, 0x05, 0xcb, 0x0b, 0xe5, 0x20, 0x8e, 0x38 };\r\n    unsigned char german_pass_phrase[] = { 0x91, 0xe7, 0x87, 0x5c, 0xc5, 0x3f, 0x70, 0x4c };\r\n    unsigned char french_pass_phrase[] = { 0x15, 0xb3, 0x8d, 0x7f, 0x2d, 0x81, 0xbe, 0x05 };\r\n    unsigned char italian_pass_phrase[] = { 0x88, 0xe9, 0xfa, 0x1e, 0xb4, 0x3d, 0x88, 0x3c };\r\n\r\n\tphrase = NULL;\r\n\r\n\tauth_data = new char[1024*64];\r\n\r\n\t\t/* Initialize ID module for DNAS */\r\n\tvoid *p_file;\r\n\t \r\n\tp_file = NULL;\r\n\tif( Config::gLanguage == Config::LANGUAGE_ENGLISH )\r\n\t{\r\n\t\tif( Config::gDisplayType == Config::DISPLAY_TYPE_NTSC )\r\n\t\t{\r\n#ifdef __DNAS_DEBUG__\r\n\t\t\tscePrintf( \"Auth File: dnas/SLUS20731_client.dat\\n\" );\r\n#endif\r\n\t\t\tp_file = File::Open( \"dnas/SLUS20731_client.dat\", \"rb\" );\r\n\t\t\tphrase = us_english_pass_phrase;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n#ifdef __DNAS_DEBUG__\r\n\t\t\tscePrintf( \"Auth File: dnas/SLES51848_client.dat\\n\" );\r\n#endif\r\n\t\t\tp_file = File::Open( \"dnas/SLES51848_client.dat\", \"rb\" );\r\n\t\t\tphrase = uk_english_pass_phrase;\r\n\t\t}\r\n\t}\r\n\telse if( Config::gLanguage == Config::LANGUAGE_FRENCH )\r\n\t{\r\n#ifdef __DNAS_DEBUG__\r\n\t\tscePrintf( \"Auth File: dnas/SLES51851_client.dat\\n\" );\r\n#endif\r\n\t\tp_file = File::Open( \"dnas/SLES51851_client.dat\", \"rb\" );\r\n\t\tphrase = french_pass_phrase;\r\n\t}\r\n\telse if( Config::gLanguage == Config::LANGUAGE_GERMAN )\r\n\t{\r\n#ifdef __DNAS_DEBUG__\r\n\t\tscePrintf( \"Auth File: dnas/SLES51852_client.dat\\n\" );\r\n#endif\r\n\t\tp_file = File::Open( \"dnas/SLES51852_client.dat\", \"rb\" );\r\n\t\tphrase = german_pass_phrase;\r\n\t}\r\n\telse if( Config::gLanguage == Config::LANGUAGE_ITALIAN )\r\n\t{\r\n#ifdef __DNAS_DEBUG__\r\n\t\tscePrintf( \"Auth File: dnas/SLES51853_client.dat\\n\" );\r\n#endif\r\n\t\tp_file = File::Open( \"dnas/SLES51853_client.dat\", \"rb\" );\r\n\t\tphrase = italian_pass_phrase;\r\n\t}\r\n\telse if( Config::gLanguage == Config::LANGUAGE_SPANISH )\r\n\t{\r\n#ifdef __DNAS_DEBUG__\r\n\t\tscePrintf( \"Auth File: dnas/SLES51854_client.dat\\n\" );\r\n#endif\r\n\t\tp_file = File::Open( \"dnas/SLES51854_client.dat\", \"rb\" );\r\n\t\tphrase = spanish_pass_phrase;\r\n\t}\r\n\telse\r\n\t{\r\n#ifdef __DNAS_DEBUG__\r\n\t\tscePrintf( \"Auth File: NONE!\\n\" );\r\n#endif\r\n\t}\r\n\r\n\tDbg_Assert( p_file != NULL );\r\n\tDbg_Assert( phrase != NULL );\r\n\r\n#ifdef __DNAS_DEBUG__\r\n\tscePrintf( \"p_file: 0x%x  phrase: 0x%x\\n\", p_file, phrase );\r\n#endif\r\n\r\n\t//fd = sceOpen(\"host0:../../authfile/auth.dat\", SCE_RDONLY);\r\n\tDbg_Printf( \"install_dnas(1)\\n\" );\r\n\r\n\tFile::Read( auth_data, 1, 1024 * 64, p_file );\r\n\t//sceRead(fd, auth_data, sizeof(auth_data));\r\n\r\n\tDbg_Printf( \"install_dnas(2)\\n\" );\r\n\tFile::Close( p_file );\r\n\r\n\torig_priority = s_get_thread_priority();\r\n\tChangeThreadPriority( GetThreadId(), 49 );\r\n\r\n\tmemset(&status, 0, sizeof(sceDNAS2Status_t));\r\n\tmemset(&prev_status, 0, sizeof(sceDNAS2Status_t));\r\n\tmemset(&auth_info, 0, sizeof(sceDNAS2TitleAuthInfo_t));\r\n\tif( timeout > 0 )\r\n\t{\r\n\t\tmemset(&timeout_info, 0, sizeof(sceDNAS2TimeoutInfo_t));\r\n\t\ttimeout_info.timeout = timeout;\r\n\t\ttimeout_info.priority = 48;\r\n\t}\r\n\tauth_info.line_type = sceDNAS2_T_INET;\r\n\tauth_info.auth_data.ptr = auth_data;\r\n\tauth_info.auth_data.size = 1024 * 64;//sizeof(auth_data);\r\n\tauth_info.pass_phrase.ptr = phrase;\r\n\tauth_info.pass_phrase.size = sizeof(phrase);\r\n#ifdef __DNAS_DEBUG__\r\n\tscePrintf(\"before sceDNAS2Init()\\n\");\r\n#endif\r\n\r\n\tif(timeout > 0)\r\n\t{\r\n\t\tret = sceDNAS2InitNoHDD(&auth_info, 48, 0, 0, &timeout_info);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tret = sceDNAS2InitNoHDD(&auth_info, 48, 0, 0, NULL);\r\n\t}\r\n\t/* NOTE */\r\n\t/* sceDNAS2InitNoHDD() with Debug flag should never be used in the final release, but for test program only */\r\n#ifdef __DNAS_DEBUG__\r\n\tscePrintf(\"return value of sceDNAS2Init(): %d\\n\", ret);\r\n#endif\r\n\tif(ret < 0)\r\n\t{\r\n\t\tsceDNAS2GetStatus( &status );\r\n\t\t\r\n\t\terror = ret;\r\n\t\tgoto error;\r\n\t}\r\n\r\n\t/*set proxy parameter*/\r\n\tif(proxy_state)\r\n\t{\r\n\t\tret = sceDNAS2SetProxy(1, proxy_host, proxy_port);\r\n#ifdef __DNAS_DEBUG__\r\n\t\tscePrintf(\"return value of sceDNAS2SetProxy = %d\\n\", ret);\r\n#endif\r\n\t\tif(ret < 0)\r\n\t\t{\r\n\t\t\tsceDNAS2GetStatus( &status );\r\n\t\t\terror = ret;\r\n\t\t\tgoto error;\r\n\t\t}\r\n\t}\r\n\r\n\t/*get proxy parameter*/\r\n\tif(proxy_state)\r\n\t{\r\n\t\tret = sceDNAS2GetProxy(&proxy_state_check, proxy_host_check, sizeof(proxy_host_check), &proxy_port_check);\r\n#ifdef __DNAS_DEBUG__\r\n\t\tscePrintf(\"return value of sceDNASGetProxy = %d\\n\", ret);\r\n#endif\r\n\t\tif(ret < 0)\r\n\t\t{\r\n\t\t\tsceDNAS2GetStatus( &status );\r\n\t\t\terror = ret;\r\n\t\t\tgoto error;\r\n\t\t}\r\n#ifdef __DNAS_DEBUG__\r\n\t\tif(proxy_state_check)\r\n\t\t{\r\n\t\t\tscePrintf(\"Proxy Info : Server = %s Port = %d\\n\", proxy_host_check, proxy_port_check);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tscePrintf(\"Proxy Info : no use \\n\");\r\n\t\t}\r\n#endif\r\n\t}\r\n\r\n\tret = sceDNAS2AuthNetStart();\r\n#ifdef __DNAS_DEBUG__\r\n\tscePrintf(\"ret of AuthNetStart() = %d\\n\", ret);\r\n#endif\r\n\tif(ret < 0)\r\n\t{\r\n\t\tsceDNAS2GetStatus( &status );\r\n\t\terror = ret;\r\n\t\tgoto error;\r\n\t}\r\n\r\n\twhile(1)\r\n\t{\r\n\t\tif((ret = sceDNAS2GetStatus(&status)) < 0)\r\n\t\t{\r\n#ifdef __DNAS_DEBUG__\r\n\t\t\tscePrintf(\"ret of sceDNAS2GetStatus() = %d\\n\", ret);\r\n#endif\r\n\t\t\terror = ret;\r\n\t\t\tgoto error;\r\n\t\t}\r\n\t\tif((ret = memcmp(&prev_status, &status, sizeof(sceDNAS2Status_t))) != 0)\r\n\t\t{\r\n\t\t\t/* status changed */\r\n#ifdef __DNAS_DEBUG__\r\n\t\t\tscePrintf(\"code: %d, sub_code: %d, progress: %d\\n\",\r\n\t\t\t\tstatus.code, status.sub_code, status.progress);\r\n#endif\r\n\t\t\tif(status.code == sceDNAS2_S_END)\r\n\t\t\t{\r\n#ifdef __DNAS_DEBUG__\r\n\t\t\t\tscePrintf(\"subcode:type %d, inst_result %d\\n\",\r\n\t\t\t\t\tsceDNAS2Status_SubCode_TYPE(status),\r\n\t\t\t\t\tsceDNAS2Status_SubCode_INST_RESULT(status));\r\n#endif\r\n\t\t\t\tmemcpy(&prev_status, &status, sizeof(sceDNAS2Status_t));\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse if(status.code == sceDNAS2_S_NG || status.code == sceDNAS2_S_COM_ERROR)\r\n\t\t\t{\r\n\t\t\t\terror = -1;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tmemcpy(&prev_status, &status, sizeof(sceDNAS2Status_t));\r\n\t}\r\n\r\nerror:\r\n#ifdef __DNAS_DEBUG__\r\n\tif( error < 0 )\r\n\t{\r\n\t\tscePrintf(\"*********** DNAS failed. Error code : %d**********\\n\", error );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tscePrintf(\"*********** DNAS succeeded.!!!! *************\\n\");\r\n\t}\r\n#endif\r\n\tret = sceDNAS2Shutdown();\r\n#ifdef __DNAS_DEBUG__\r\n\tscePrintf(\"ret of sceDNAS2Shutdown() is %d\\n\", ret);\r\n#endif\r\n\tChangeThreadPriority( GetThreadId(), orig_priority );\r\n\tdelete [] auth_data;\r\n\r\n\treturn error;\r\n}\r\n\r\nstatic\tuint32\ts_get_error_desc( int code )\r\n{\r\n\tswitch( code )\r\n\t{\r\n\t\tcase sceDNAS2_SS_SERVER_BUSY:\r\n\t\t\treturn CRCD(0xf9814711,\"net_auth_error_server_busy\");\r\n\t\t\tbreak;\r\n\t\tcase sceDNAS2_SS_BEFORE_SERVICE:\r\n\t\t\treturn CRCD(0x87da162f,\"net_auth_error_before_service\");\r\n\t\t\tbreak;\r\n\t\tcase sceDNAS2_SS_OUT_OF_SERVICE:\r\n\t\t\treturn CRCD(0xa7b3ce4c,\"net_auth_error_out_of_service\");\r\n\t\t\tbreak;\r\n\t\tcase sceDNAS2_SS_END_OF_SERVICE:\r\n\t\t\treturn CRCD(0x2a52e052,\"net_auth_error_end_of_service\");\r\n\t\t\tbreak;\r\n\t\tcase sceDNAS2_SS_SESSION_TIME_OUT:\r\n\t\t\treturn CRCD(0x6b58d871,\"net_auth_error_time_out\");\r\n\t\t\tbreak;\r\n\t\tcase sceDNAS2_SS_INVALID_SERVER:\r\n\t\t\treturn CRCD(0x3472f158,\"net_auth_error_invalid_server\");\r\n\t\t\tbreak;\r\n\t\tcase sceDNAS2_SS_INTERNAL_ERROR:\r\n\t\t\treturn CRCD(0x3c0c381,\"net_auth_error_internal\");\r\n\t\t\tbreak;\r\n\t\tcase sceDNAS2_SS_EXTERNAL_ERROR:\r\n\t\t\treturn CRCD(0x50617f3a,\"net_auth_error_external\");\r\n\t\t\tbreak;\r\n\t\tcase sceDNAS2_SS_ID_NOUSE:\r\n\t\tcase sceDNAS2_SS_ID_NOT_JOIN_TO_CAT:\r\n\t\t\treturn CRCD(0xe8177760,\"net_auth_error_unique\");\r\n\t\t\tbreak;\r\n\r\n\t\tcase sceDNAS2_SS_DL_NODATA:\r\n\t\tcase sceDNAS2_SS_DL_BEFORE_SERVICE:\r\n\t\tcase sceDNAS2_SS_DL_OUT_OF_SERVICE:\r\n\t\tcase sceDNAS2_SS_DL_NOT_UPDATED:\r\n\t\t\treturn CRCD(0x70295cf2,\"net_auth_error_download\");\r\n\t\t\tbreak;\r\n\r\n\t\tcase sceDNAS2_SS_INVALID_PS2:\r\n\t\tcase sceDNAS2_SS_INVALID_HDD_BINDING:\r\n\t\t\treturn CRCD(0x448c00ef,\"net_auth_error_machine\");\r\n\t\t\tbreak;\r\n\r\n\t\tcase sceDNAS2_SS_INVALID_MEDIA:\r\n\t\tcase sceDNAS2_SS_INVALID_AUTHDATA:\r\n\t\t\treturn CRCD(0x736c330,\"net_auth_error_disc\");\r\n\t\t\tbreak;\r\n\r\n\t\tcase sceDNAS2_ERR_GLUE_ABORT:\r\n\t\tcase sceDNAS2_ERR_NET_PROXY:\r\n\t\tcase sceDNAS2_ERR_NET_SSL:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_HOST_NOT_FOUND:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_TRY_AGAIN:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_NO_RECOVERY:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_NO_DATA:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_OTHERS:\r\n\t\tcase sceDNAS2_ERR_NET_EISCONN:\r\n\t\tcase sceDNAS2_ERR_NET_ETIMEOUT:\r\n\t\tcase sceDNAS2_ERR_NET_TIMEOUT:\r\n\t\tcase sceDNAS2_ERR_NET_ECONNREFUSED:\r\n\t\tcase sceDNAS2_ERR_NET_ENETUNREACH:\r\n\t\tcase sceDNAS2_ERR_NET_ENOTCONN:\r\n\t\tcase sceDNAS2_ERR_NET_ENOBUFS:\r\n\t\tcase sceDNAS2_ERR_NET_EMFILE:\r\n\t\tcase sceDNAS2_ERR_NET_EBADF:\r\n\t\tcase sceDNAS2_ERR_NET_EINVAL:\r\n\t\tcase sceDNAS2_ERR_NET_OTHERS:\r\n\t\t\treturn CRCD(0x310d58d7,\"net_auth_error_network\");\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\treturn CRCD(0xc7c67eb8,\"net_auth_error_generic\");\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\nstatic\tuint32\ts_get_error_footer( int code )\r\n{\r\n\tswitch( code )\r\n\t{\r\n\t\tcase sceDNAS2_SS_BEFORE_SERVICE:\r\n\t\tcase sceDNAS2_SS_OUT_OF_SERVICE:\r\n\t\tcase sceDNAS2_SS_END_OF_SERVICE:\r\n\t\tcase sceDNAS2_SS_INVALID_SERVER:\r\n\t\tcase sceDNAS2_SS_INTERNAL_ERROR:\r\n\t\tcase sceDNAS2_SS_EXTERNAL_ERROR:\r\n\t\tcase sceDNAS2_SS_INVALID_PS2:\r\n\t\tcase sceDNAS2_SS_INVALID_HDD_BINDING:\r\n\t\tcase sceDNAS2_SS_INVALID_MEDIA:\r\n\t\tcase sceDNAS2_SS_INVALID_AUTHDATA:\r\n\t\t\treturn CRCD(0x16ff6a40,\"net_auth_footer_contact\");\r\n\t\tcase sceDNAS2_SS_SERVER_BUSY:\r\n\t\tcase sceDNAS2_SS_SESSION_TIME_OUT:\r\n\t\tcase sceDNAS2_SS_ID_NOUSE:\r\n\t\tcase sceDNAS2_SS_ID_NOT_JOIN_TO_CAT:\r\n\t\tcase sceDNAS2_SS_DL_NODATA:\r\n\t\tcase sceDNAS2_SS_DL_BEFORE_SERVICE:\r\n\t\tcase sceDNAS2_SS_DL_OUT_OF_SERVICE:\r\n\t\tcase sceDNAS2_SS_DL_NOT_UPDATED:\r\n\t\t\treturn CRCD(0x8c671de9,\"net_auth_footer_empty\");\r\n\t\tcase sceDNAS2_ERR_GLUE_ABORT:\r\n\t\tcase sceDNAS2_ERR_NET_PROXY:\r\n\t\tcase sceDNAS2_ERR_NET_SSL:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_HOST_NOT_FOUND:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_TRY_AGAIN:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_NO_RECOVERY:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_NO_DATA:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_OTHERS:\r\n\t\tcase sceDNAS2_ERR_NET_EISCONN:\r\n\t\tcase sceDNAS2_ERR_NET_ETIMEOUT:\r\n\t\tcase sceDNAS2_ERR_NET_TIMEOUT:\r\n\t\tcase sceDNAS2_ERR_NET_ECONNREFUSED:\r\n\t\tcase sceDNAS2_ERR_NET_ENETUNREACH:\r\n\t\tcase sceDNAS2_ERR_NET_ENOTCONN:\r\n\t\tcase sceDNAS2_ERR_NET_ENOBUFS:\r\n\t\tcase sceDNAS2_ERR_NET_EMFILE:\r\n\t\tcase sceDNAS2_ERR_NET_EBADF:\r\n\t\tcase sceDNAS2_ERR_NET_EINVAL:\r\n\t\tcase sceDNAS2_ERR_NET_OTHERS:\r\n\t\t\treturn CRCD(0x3a190bc4,\"net_auth_footer_network\");\r\n\t\tdefault:\r\n\t\t\treturn CRCD(0x16ff6a40,\"net_auth_footer_contact\");\r\n\t}\r\n}\r\n\r\nstatic\tuint32\ts_get_error_footer_pal( int code )\r\n{\r\n\tswitch( code )\r\n\t{\r\n\t\tcase sceDNAS2_SS_SERVER_BUSY:\r\n\t\t\treturn CRCD(0x8c671de9,\"net_auth_footer_empty\");\r\n\t\tcase sceDNAS2_SS_BEFORE_SERVICE:\r\n\t\tcase sceDNAS2_SS_OUT_OF_SERVICE:\r\n\t\t\treturn CRCD(0x99b34c96,\"net_auth_footer_service_pal\");\r\n\t\tcase sceDNAS2_SS_END_OF_SERVICE:\r\n\t\t\treturn CRCD(0x1a95350b,\"net_auth_footer_central_pal\");\r\n\t\tcase sceDNAS2_SS_SESSION_TIME_OUT:\r\n\t\tcase sceDNAS2_SS_INVALID_SERVER:\r\n\t\tcase sceDNAS2_SS_INTERNAL_ERROR:\r\n\t\tcase sceDNAS2_SS_EXTERNAL_ERROR:\r\n\t\t\treturn CRCD(0x3e6e83d0,\"net_auth_footer_cont_customer_pal\");\r\n\t\tcase sceDNAS2_SS_ID_NOUSE:\r\n\t\tcase sceDNAS2_SS_ID_NOT_JOIN_TO_CAT:\r\n\t\tcase sceDNAS2_SS_DL_NODATA:\r\n\t\tcase sceDNAS2_SS_DL_BEFORE_SERVICE:\r\n\t\tcase sceDNAS2_SS_DL_OUT_OF_SERVICE:\r\n\t\tcase sceDNAS2_SS_DL_NOT_UPDATED:\r\n\t\t\treturn CRCD(0x8c671de9,\"net_auth_footer_empty\");\r\n\t\tcase sceDNAS2_SS_INVALID_PS2:\r\n\t\tcase sceDNAS2_SS_INVALID_MEDIA:\r\n\t\tcase sceDNAS2_SS_INVALID_HDD_BINDING:\r\n\t\t\treturn CRCD(0xc13153cc,\"net_auth_footer_customer_pal\");\r\n\t\tcase sceDNAS2_SS_INVALID_AUTHDATA:\r\n\t\t\treturn CRCD(0x85cb1e0c,\"net_auth_footer_clean_pal\");\r\n\t\tcase sceDNAS2_ERR_GLUE_ABORT:\r\n\t\tcase sceDNAS2_ERR_NET_PROXY:\r\n\t\tcase sceDNAS2_ERR_NET_SSL:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_HOST_NOT_FOUND:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_TRY_AGAIN:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_NO_RECOVERY:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_NO_DATA:\r\n\t\tcase sceDNAS2_ERR_NET_DNS_OTHERS:\r\n\t\tcase sceDNAS2_ERR_NET_EISCONN:\r\n\t\tcase sceDNAS2_ERR_NET_ETIMEOUT:\r\n\t\tcase sceDNAS2_ERR_NET_TIMEOUT:\r\n\t\tcase sceDNAS2_ERR_NET_ECONNREFUSED:\r\n\t\tcase sceDNAS2_ERR_NET_ENETUNREACH:\r\n\t\tcase sceDNAS2_ERR_NET_ENOTCONN:\r\n\t\tcase sceDNAS2_ERR_NET_ENOBUFS:\r\n\t\tcase sceDNAS2_ERR_NET_EMFILE:\r\n\t\tcase sceDNAS2_ERR_NET_EBADF:\r\n\t\tcase sceDNAS2_ERR_NET_EINVAL:\r\n\t\tcase sceDNAS2_ERR_NET_OTHERS:\r\n\t\t\treturn CRCD(0x570be62b,\"net_auth_footer_network_pal\");\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\treturn CRCD(0x1a95350b,\"net_auth_footer_central_pal\");\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n\r\nextern char _dnas_start[];\r\nextern char _dnas_size[];\r\n\r\nbool \t\tGameNet::Manager::ScriptAuthenticateClient( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tsceDNAS2Status_t status;\r\n\tint result;\r\n\tvoid *p_file;\r\n\tchar* memory;\r\n\t\r\n\t// Hardware will be flagged as Config::HARDWARE_PS2_DEVSYSTEM if we run a \r\n\t// .elf file.  This is probably different from what we are running on\r\n\t// the cd, so just return true, and don't actually perform the DNAS check\r\n\t// (Note, we must be running off a CD, as the check is only performed on CD burns)\t\t\t\t\t\t\t\t\t\t  \r\n\t// If we actually BOOT the cd on the dev system, it will think it's\r\n\t// on a regular PS2, and the DNAS test will be performed\r\n\tif \t( Config::CD() && Config::GetHardware() == Config::HARDWARE_PS2_DEVSYSTEM ) \r\n\t{\r\n\t\tScript::RunScript( CRCD(0xbd54c02b,\"connected_to_internet\") );\r\n\t\ts_extra_time = 0;\r\n\t\treturn true;\r\n\t}\r\n#ifdef __DNAS_DEBUG__\t\r\n\tscePrintf( \"Available Memory: %d\\n\", Mem::Manager::sHandle().Available());\r\n#endif\r\n\r\n\t// Worst case, if we're out of memory because of leaks or fragmentation, just act as if\r\n\t// DNAS authentication took place and verified the authenticity of the user\r\n\tif( Mem::Manager::sHandle().Available() < (int) ( 1024 * 1024 * 1.7 ))\r\n\t{\r\n#ifdef __DNAS_DEBUG__\r\n\t\tscePrintf( \"Could not allocate overlay buffer. Available mem: %d. Skipping test\\n\", Mem::Manager::sHandle().Available());\r\n#endif\r\n\t\tDbg_MsgAssert( 0, ( \"Could not allocate enough safe memory for DNAS. Tell Steve\\n\" ));\r\n\t\tScript::RunScript( CRCD(0xbd54c02b,\"connected_to_internet\") );\r\n\t\ts_extra_time = 0;\r\n\t\treturn true;\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\tmemory = new char[(int) ( 1024 * 1024 * 1.7 )];\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n#ifdef __DNAS_DEBUG__\r\n\tscePrintf( \"Memory is at : 0x%x\\n\", memory );\r\n\tscePrintf( \"DNAS Start: 0x%x  DNAS Size: %d\\n\", (int) _dnas_start, (int) _dnas_size );\r\n#endif\r\n\t\r\n\tif(\t((uint32) _dnas_start + (uint32) _dnas_size ) > (uint32) ( memory + (int) ( 1024 * 1024 * 1.7 )) ||\r\n\t\t((uint32) _dnas_start < (uint32) memory ))\r\n\t{\r\n\t\t// Worst case, if we're out of memory because of leaks or fragmentation, just act as if\r\n\t\t// DNAS authentication took place and verified the authenticity of the user\r\n\r\n\t\tdelete [] memory;\r\n#ifdef __DNAS_DEBUG__\r\n\t\tscePrintf( \"DNAS didn't fit in the memory that was allocated\\n\" );\r\n#endif\r\n\t\tDbg_MsgAssert( 0, ( \"Could not allocate enough safe memory for DNAS. Tell Steve\\n\" ));\r\n\t\tScript::RunScript( CRCD(0xbd54c02b,\"connected_to_internet\") );\r\n\t\ts_extra_time = 0;\r\n\t\treturn true;\r\n\t}\r\n\t\t \r\n\t// Clear out the destination memory\r\n\tmemset( _dnas_start, 0, (int) _dnas_size );\r\n\r\n\tp_file = NULL;\r\n\tif( Config::gLanguage == Config::LANGUAGE_ENGLISH )\r\n\t{\r\n\t\tif( Config::gDisplayType == Config::DISPLAY_TYPE_NTSC )\r\n\t\t{\r\n\t\t\tp_file = File::Open( \"dnas/dnas.bin\", \"rb\" );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_file = File::Open( \"dnas/dnas_e.bin\", \"rb\" );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_file = File::Open( \"dnas/dnas_e.bin\", \"rb\" );\r\n\t}\r\n\r\n#ifdef __DNAS_DEBUG__\r\n\tif( p_file == NULL )\r\n\t{\r\n\t\tscePrintf( \"Failed to open dnas/dnas(_e).bin\" );\r\n\t}\r\n#endif\r\n\r\n\tFile::Read( _dnas_start, 1, (int) _dnas_size, p_file );\r\n\tFile::Close( p_file );\r\n\r\n#ifndef __PURE_HEAP__\r\n\tDbg_MsgAssert( !Config::CD(), ( \"DNAS will not work with memory debugging enabled.\" ));\r\n#endif\r\n\r\n#ifdef __USE_DNAS_DLL__\r\n\tchar* rel_mem, *buff;\r\n\tvoid *p_file = File::Open( \"dnas/dnas.rel\", \"rb\" );\r\n\tFile::Seek( p_file, 0, SEEK_END );\r\n\tint32 size = File::Tell( p_file );\r\n\tDbg_Printf( \"***************** FILE SIZE IS %d\\n\", size );\r\n\tFile::Seek( p_file, 0, SEEK_SET );\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\trel_mem = new char[size + 127];\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tbuff = (char*) (((int) rel_mem + 127 ) & ~127 ); // Align to 128-byte boundary\r\n\r\n\tFile::Read( buff, sizeof( char ), size, p_file );\r\n\tFile::Close( p_file );\r\n\r\n\tif( snDllLoaded( buff, 0 ))\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Failed to load dnas DLL\\n\" ));\r\n\t\treturn false;\r\n\t}\r\n#endif\r\n\r\n\tif( !Config::CD())\r\n\t{\r\n\t\tsceCdInit(SCECdINIT);\r\n\t\tsceCdMmode(SCECdDVD);\r\n\t\tsceCdDiskReady( 0 );\r\n\t}\r\n\r\n\tmemset( &status, 0, sizeof( sceDNAS2Status_t )); \r\n\tresult = netstart_dnas( 0, NULL, 0, vAUTH_TIMEOUT + s_extra_time, status );\r\n\tDbg_Printf( \"dnas result was : %d\\n\", result );\r\n\t//install_dnas( 0, NULL, 0, 0 );\r\n\r\n\tdelete [] memory;\r\n\r\n\tif( result != 0 )\r\n\t{\r\n\t\tScript::CStruct* pParams;\r\n\t\tuint32 desc;\r\n\t\tuint32 footer;\r\n\t\tconst char* err_desc;\r\n\t\tconst char* err_footer;\r\n\r\n\t\ts_extra_time += 10;\r\n\r\n\t\tpParams = new Script::CStruct;\r\n\t\tif( status.code == 0 )\r\n\t\t{\r\n\t\t\tpParams->AddInteger( CRCD(0x88eacf67,\"code\"), 0 );\r\n\t\t\tpParams->AddInteger( CRCD(0xaf7c50a6,\"sub_code\"), 0 );\r\n\t\t\tdesc = CRCD(0xc7c67eb8,\"net_auth_error_generic\");\r\n\t\t\tif( Config::PAL())\r\n\t\t\t{\r\n\t\t\t\tfooter = CRCD(0xc13153cc,\"net_auth_footer_customer_pal\");\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t\r\n\t\t\t\tfooter = CRCD(0x16ff6a40,\"net_auth_footer_contact\");\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Printf( \" Code: %d  SubCode: %d\\n\", status.code, status.sub_code );\r\n\t\t\tpParams->AddInteger( CRCD(0x88eacf67,\"code\"), status.code );\r\n\t\t\tpParams->AddInteger( CRCD(0xaf7c50a6,\"sub_code\"), status.sub_code );\r\n\t\t\tdesc = s_get_error_desc( status.sub_code );\r\n\t\t\tif( Config::PAL())\r\n\t\t\t{\r\n\t\t\t\tfooter = s_get_error_footer_pal( status.sub_code );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfooter = s_get_error_footer( status.sub_code );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\terr_desc = Script::GetString( desc, Script::ASSERT );\r\n\t\terr_footer = Script::GetString( footer, Script::ASSERT );\r\n\t\tDbg_Printf( \"ERROR DESC: %s\\n\", err_desc );\r\n\t\tDbg_Printf( \"ERROR FOOTER: %s\\n\", err_footer );\r\n\t\tpParams->AddString( CRCD(0xf44a53ab,\"desc\"), err_desc );\r\n\t\tpParams->AddString( CRCD(0x1dcefaac,\"footer\"), err_footer );\r\n\t\tScript::RunScript( CRCD(0xc3bb2b5a,\"display_auth_error\"), pParams );\r\n\r\n\t\tdelete pParams;\r\n\t\treturn false;\r\n\t}\r\n\r\n\tDbg_Printf( \"Success: Showing disclaimer\\n\" );\r\n\tScript::RunScript( CRCD(0xbd54c02b,\"connected_to_internet\") );\r\n\ts_extra_time = 0;\r\n\treturn true;\r\n}\r\n\r\nbool GameNet::Manager::ScriptWriteDNASBinary( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tvoid *p_file;\r\n\tstatic bool written = false;\r\n\r\n\tif( Config::CD())\r\n\t{\r\n\t\twritten = true;\r\n\t}\r\n\t\r\n\tif( !written ) \r\n\t{\r\n\t\tif( Config::gLanguage == Config::LANGUAGE_ENGLISH )\r\n\t\t{\r\n\t\t\tif( Config::gDisplayType == Config::DISPLAY_TYPE_NTSC )\r\n\t\t\t{\r\n\t\t\t\tp_file = File::Open( \"dnas/dnas.bin\", \"wb\" );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_file = File::Open( \"dnas/dnas_e.bin\", \"wb\" );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_file = File::Open( \"dnas/dnas_e.bin\", \"wb\" );\r\n\t\t}\r\n\t\tFile::Write( _dnas_start, 1, (int) _dnas_size, p_file );\r\n\t\tFile::Flush( p_file );\r\n\t\tFile::Close( p_file );\r\n\r\n\t\twritten = true;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/p_buddy.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_buddy.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/28/02\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPS2 Buddy List Code \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gel/mainloop.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <GameNet/GameNet.h>\r\n#include <GameNet/Ngps/p_buddy.h>\r\n#include <GameNet/lobby.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define vBUDDY_CONNECT_TIMEOUT Tmr::Seconds( 10 )\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic \tTmr::Time\ts_connect_start_time = 0;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid BuddyMan::s_error_callback( GPConnection* connection, void* arg, void* param )\r\n{\r\n    GPErrorArg* error;\r\n\tBuddyMan* buddy_man;\r\n\r\n\terror = (GPErrorArg*) arg;\r\n\tbuddy_man = (BuddyMan*) param;\r\n\t\r\n\tDbg_Printf( \"******** ERROR: %d %s\\n\", error->errorCode, error->errorString );\r\n\r\n\tif( error->fatal )\r\n\t{\r\n\t\tDbg_Printf( \"******** ERROR IS FATAL\\n\" );\r\n\t}\r\n\t\r\n\tswitch( error->errorCode )\r\n\t{\r\n\t\tcase GP_NEWUSER_BAD_PASSWORD:\r\n\t\t\tDbg_Printf( \"Bad password\\n\" );\r\n\t\t\tScript::RunScript( \"create_wrong_profile_password_dialog\" );\r\n\t\t\tbuddy_man->Disconnect();\r\n\t\t\tbreak;\r\n\t\tcase GP_NEWUSER_BAD_NICK:\r\n\t\t\tDbg_Printf( \"Bad nick (already exists?) Trying to connect now\\n\" );\r\n\t\t\tbuddy_man->m_state = vSTATE_BEGIN_LOGIN;\r\n\t\t\tbreak;\r\n\t\tcase GP_ADDBUDDY_ALREADY_BUDDY:\r\n\t\t\tScript::RunScript( \"failed_add_buddy_already_buddy\" );\r\n\t\t\tbreak;\r\n\t\tcase GP_LOGIN_CONNECTION_FAILED:\r\n\t\t\tbuddy_man->Disconnect();\r\n\t\t\tScript::RunScript( \"CreateBuddyLoginFailedDialog\" );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_Printf( \"Not handled: %d\\n\", error->errorCode );\r\n\t\t\tbreak;\r\n\t\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid BuddyMan::s_buddy_request( GPConnection* connection, void* arg, void* param )\r\n{\r\n\tBuddyMan* buddy_man;\r\n\tGPRecvBuddyRequestArg* request;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\t\r\n\tbuddy_man = (BuddyMan*) param;\r\n\trequest = (GPRecvBuddyRequestArg*) arg;\r\n\t\r\n\t// Always accept\r\n\tgpAuthBuddyRequest( &buddy_man->m_gp_conn, request->profile );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid BuddyMan::s_buddy_status( GPConnection* connection, void* arg, void* param )\r\n{\r\n\tBuddyMan* buddy_man;\r\n\tGPRecvBuddyStatusArg* status_arg;\r\n\tGPBuddyStatus status;\r\n\tLst::Search< BuddyInfo > sh;\r\n\tBuddyInfo* buddy;\r\n\tchar* join_info;\r\n\tchar* location_str;\r\n\tbool handled;\r\n\tint i;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\tbuddy_man = (BuddyMan*) param;\r\n\tstatus_arg = (GPRecvBuddyStatusArg*) arg;\r\n    \r\n\tgpGetBuddyStatus( &buddy_man->m_gp_conn, status_arg->index, &status );\r\n\r\n\t//Dbg_Printf( \"Got buddy status %d for %d : %s, %s\\n\", status.status, status.profile, status.statusString, status.locationString );\r\n\r\n\thandled = false;\r\n\tfor( buddy = sh.FirstItem( buddy_man->m_buddies ); buddy; buddy = sh.NextItem())\r\n\t{\r\n\t\tif( buddy->m_Profile == status.profile )\r\n\t\t{\r\n\t\t\tScript::CStruct* p_status_params;\r\n\r\n\t\t\tbuddy->m_Status = status.status;\r\n\t\t\t\r\n\t\t\tstrcpy( buddy->m_StatusString, status.statusString );\r\n\t\t\tif( buddy->m_Status == GP_PLAYING )\r\n\t\t\t{\r\n\t\t\t\tlocation_str = strchr( status.locationString, ':' );\r\n\t\t\t\tlocation_str += 1;\r\n\t\t\t\tlocation_str = strchr( location_str, ':' );\r\n\t\t\t\tlocation_str += 1;\r\n\t\t\t\tlocation_str = strchr( location_str, ':' );\r\n\t\t\t\tlocation_str += 1;\r\n\t\r\n\t\t\t\tstrcpy( buddy->m_Location, location_str );\r\n\t\t\t\tjoin_info = strtok( status.locationString, \":\" );\r\n\t\t\t\tDbg_Assert( join_info != NULL );\r\n\t\t\t\tbuddy->m_JoinIP = atoi( join_info );\r\n\t\t\t\tjoin_info = strtok( NULL, \":\" );\r\n\t\t\t\tDbg_Assert( join_info != NULL );\r\n\t\t\t\tbuddy->m_JoinPrivateIP = atoi( join_info );\r\n\t\t\t\tjoin_info = strtok( NULL, \":\" );\r\n\t\t\t\tDbg_Assert( join_info != NULL );\r\n\t\t\t\tbuddy->m_JoinPort = atoi( join_info );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tstrcpy( buddy->m_Location, status.locationString );\r\n\t\t\t}\r\n\r\n\t\t\tif( buddy->m_Pending )\r\n\t\t\t{\r\n\t\t\t\t// This was a pending addition.  Add him to our permanent list\r\n\t\t\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\t\t\tPrefs::Preferences*\tprefs;\r\n\t\t\t\tScript::CArray* buddy_array, *new_array;\r\n\t\t\t\tScript::CStruct* new_buddy;\r\n\t\t\t\tScript::CStruct* params;\r\n                      \r\n\t\t\t\tparams = new Script::CStruct;\t\r\n\t\t\t\tparams->AddString( \"net_name\", buddy->m_Nick );\r\n\r\n\t\t\t\tScript::RunScript( \"added_buddy\", params );\r\n\t\t\t\tdelete params;\r\n\r\n\t\t\t\tbuddy->m_Pending = false;\r\n\r\n\t\t\t\tprefs = gamenet_man->GetNetworkPreferences();\r\n\t\t\t\tbuddy_array = prefs->GetPreferenceArray( Script::GenerateCRC( \"buddy_array\" ));\r\n\r\n\t\t\t\tnew_array = new Script::CArray;\r\n\t\t\t\tnew_array->SetSizeAndType( buddy_array->GetSize() + 1, ESYMBOLTYPE_STRUCTURE );\r\n\r\n\t\t\t\tfor( i = 0; i < (int) buddy_array->GetSize(); i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct* entry, *new_entry;\r\n\r\n\t\t\t\t\tentry = buddy_array->GetStructure( i );\r\n\t\t\t\t\tnew_entry = new Script::CStruct;\r\n\t\t\t\t\t*new_entry = *entry;\r\n\t\t\t\t\tnew_array->SetStructure( i, new_entry );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tnew_buddy = new Script::CStruct;\r\n\t\t\t\tnew_buddy->AddInteger( \"profile\", buddy->m_Profile );\r\n\t\t\t\tnew_buddy->AddString( \"nick\", buddy->m_Nick );\r\n\t\t\t\tnew_array->SetStructure( i, new_buddy );\r\n\t\t\t\t\r\n\t\t\t\tprefs->SetPreference( Script::GenerateCRC( \"buddy_array\" ), new_array );\r\n\t\t\t}\r\n\r\n\t\t\tp_status_params = new Script::CScriptStructure;\r\n\t\t\tp_status_params->AddComponent( Script::GenerateCRC( \"name\" ), ESYMBOLTYPE_STRING, buddy->m_Nick );\r\n\t\t\tp_status_params->AddComponent( Script::GenerateCRC( \"status\" ), ESYMBOLTYPE_STRING, buddy->m_StatusString );\r\n\t\t\tp_status_params->AddComponent( Script::GenerateCRC( \"location\" ), ESYMBOLTYPE_STRING, buddy->m_Location );\r\n\t\t\tp_status_params->AddComponent( Script::GenerateCRC( \"id\" ), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"first_lobby_buddy\" ) + buddy->m_Profile );\r\n\t\t\tScript::RunScript( \"update_buddy_status\", p_status_params );\r\n\t\t\tdelete p_status_params;\r\n\r\n\t\t\thandled = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif( !handled )\r\n\t{\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tPrefs::Preferences*\tprefs;\r\n\t\tScript::CArray* buddy_array;\r\n\t\tint profile;\r\n\r\n\t\tprefs = gamenet_man->GetNetworkPreferences();\r\n\r\n\t\tbuddy = new BuddyInfo;\r\n\t\tbuddy->m_Profile = status.profile;\r\n\t\tbuddy->m_Status = status.status;\r\n\t\tstrcpy( buddy->m_StatusString, status.statusString );\r\n\t\tsprintf( buddy->m_Nick, \"ProSkater\" );\r\n\r\n\t\tif( buddy->m_Status == GP_PLAYING )\r\n\t\t{\r\n\t\t\tlocation_str = strchr( status.locationString, ':' );\r\n\t\t\tlocation_str += 1;\r\n\t\t\tlocation_str = strchr( location_str, ':' );\r\n\t\t\tlocation_str += 1;\r\n\t\t\tlocation_str = strchr( location_str, ':' );\r\n\t\t\tlocation_str += 1;\r\n\t\r\n\t\t\tstrcpy( buddy->m_Location, location_str );\r\n\t\t\tjoin_info = strtok( status.locationString, \":\" );\r\n\t\t\tDbg_Assert( join_info );\r\n\t\t\tbuddy->m_JoinIP = atoi( join_info );\r\n\t\t\tjoin_info = strtok( NULL, \":\" );\r\n\t\t\tDbg_Assert( join_info );\r\n\t\t\tbuddy->m_JoinPrivateIP = atoi( join_info );\r\n\t\t\tjoin_info = strtok( NULL, \":\" );\r\n\t\t\tDbg_Assert( join_info );\r\n\t\t\tbuddy->m_JoinPort = atoi( join_info );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tstrcpy( buddy->m_Location, status.locationString );\r\n\t\t}\r\n\r\n\t\tbuddy_man->m_buddies.AddToTail( buddy );\r\n\r\n\t\t// We now need to find the name by which we know this buddy.  When we added them to our list\r\n\t\t// we added an entry into our network preferences with a matching profile ID and the player's\r\n\t\t// network name\r\n\t\tbuddy_array = prefs->GetPreferenceArray( Script::GenerateCRC( \"buddy_array\" ));\r\n\t\tif( buddy_array )\r\n\t\t{\r\n\t\t\tScript::CStruct* entry;\r\n\t\t\tfor( i = 0; i < (int) buddy_array->GetSize(); i++ )\r\n\t\t\t{\r\n\t\t\t\tentry = buddy_array->GetStructure( i );\r\n\t\t\t\tentry->GetInteger( \"profile\", &profile, Script::ASSERT );\r\n\t\t\t\tif( profile == status.profile )\r\n\t\t\t\t{\r\n\t\t\t\t\tconst char* nick = NULL;\r\n\t\t\t\t\tentry->GetString( \"nick\", &nick, Script::ASSERT );\r\n\r\n\t\t\t\t\tstrcpy( buddy->m_Nick, nick );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n    Mem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid BuddyMan::s_buddy_message( GPConnection* connection, void* arg, void* param )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid BuddyMan::s_game_invite( GPConnection* connection, void* arg, void* param )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid BuddyMan::s_transfer_callback( GPConnection* connection, void* arg, void* param )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid BuddyMan::s_connect_callback( GPConnection* connection, void* arg, void* param )\r\n{\r\n\tBuddyMan* buddy_man;\r\n    GPConnectResponseArg* response;\r\n\r\n\tbuddy_man = (BuddyMan*) param;\r\n\tresponse = (GPConnectResponseArg*) arg;\r\n\tswitch( response->result )\r\n\t{\r\n\t\tcase GP_NO_ERROR:\r\n\t\t\t//Dbg_Printf( \"*************** CONNECTED, NO ERROR\\n\" );\r\n\t\t\tbuddy_man->Connected( response->profile );\r\n\t\t\tbreak;\r\n\t\tcase GP_MEMORY_ERROR:\r\n\t\t\t//Dbg_Printf( \"*************** DIDNT CONNECT: MEMORY ERROR\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GP_PARAMETER_ERROR:\r\n\t\t\t//Dbg_Printf( \"*************** DIDNT CONNECT: PARAMETER ERROR\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GP_NETWORK_ERROR:\r\n\t\t\t//Dbg_Printf( \"*************** DIDNT CONNECT: NETWORK ERROR\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GP_SERVER_ERROR:\r\n\t\t\t//Dbg_Printf( \"*************** DIDNT CONNECT: SERVER ERROR\\n\" );\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBuddyMan::s_buddy_logic_code( const Tsk::Task< BuddyMan >& task )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\tBuddyMan& man = task.GetData();\r\n\tstatic Tmr::Time s_last_process_time = 0;\r\n\r\n\tswitch( man.m_state )\r\n\t{\r\n\t\tcase vSTATE_WAIT:\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_BEGIN_LOGIN:\r\n\t\t\tman.Connect();\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_CREATING_PROFILE:\r\n\t\tcase vSTATE_CONNECTING:\r\n\t\t\tif(( Tmr::GetTime() - s_connect_start_time ) > vBUDDY_CONNECT_TIMEOUT )\r\n\t\t\t{\r\n\t\t\t\t//Dbg_Printf( \"Timing buddy server connection out\\n\" );\r\n\t\t\t\tman.Disconnect();\r\n\t\t\t\tScript::RunScript( \"CreateBuddyLoginFailedDialog\" );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tgpProcess( &man.m_gp_conn );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_LOGGED_IN:\r\n\t\t\tif(( Tmr::GetTime() - s_last_process_time ) > Tmr::Seconds( 1 ))\r\n\t\t\t{\r\n\t\t\t\tgpProcess( &man.m_gp_conn );\r\n\t\t\t\ts_last_process_time = Tmr::GetTime();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t\tbreak;\r\n\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \tBuddyMan::s_threaded_buddy_connect( BuddyMan* buddy_man )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tPrefs::Preferences*\tprefs;\r\n\tGPResult result;\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\t// Register this thread with the sockets API\r\n\tsockAPIregthr();\r\n\r\n\tprefs = gamenet_man->GetNetworkPreferences();\r\n\tconst char* email = prefs->GetPreferenceString( Script::GenerateCRC( \"profile_email\" ), Script::GenerateCRC(\"ui_string\") );\r\n\tconst char* password = prefs->GetPreferenceString( Script::GenerateCRC( \"profile_password\" ), Script::GenerateCRC(\"ui_string\") );\r\n\r\n\tDbg_Printf( \"Connecting to gp with %s : %s\\n\", email, password );\r\n\tresult = gpConnect( &buddy_man->m_gp_conn, \"proskater\", email, password, GP_FIREWALL, GP_NON_BLOCKING, s_connect_callback, buddy_man );\r\n\r\n\t// Deregister this thread with the sockets API\r\n\tsockAPIderegthr();\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \tBuddyMan::s_threaded_buddy_create( BuddyMan* buddy_man )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tPrefs::Preferences*\tprefs;\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\t// Register this thread with the sockets API\r\n\tsockAPIregthr();\r\n\r\n\tprefs = gamenet_man->GetNetworkPreferences();\r\n\tconst char* email = prefs->GetPreferenceString( Script::GenerateCRC( \"profile_email\" ), Script::GenerateCRC(\"ui_string\") );\r\n\tconst char* password = prefs->GetPreferenceString( Script::GenerateCRC( \"profile_password\" ), Script::GenerateCRC(\"ui_string\") );\r\n\r\n\t//Dbg_Printf( \"************ Creating profile: Proskater for account %s, password %s\\n\", email, password );\r\n\tgpConnectNewUser( &buddy_man->m_gp_conn, \"proskater\", email, password, GP_FIREWALL, GP_NON_BLOCKING, s_connect_callback, buddy_man );\r\n\r\n\t/*if( buddy_man->m_command == vCOMMAND_LOGIN )\r\n\t{\r\n\t\t//Dbg_Printf( \"Connecting instead\\n\" );\r\n\t\tScript::RunScript( \"log_in_profile\" );\r\n\t\tbuddy_man->m_command = vCOMMAND_CONNECT;\r\n\t\ts_connect_start_time = Tmr::GetTime();\r\n\t\tresult = gpConnect( &buddy_man->m_gp_conn, \"proskater\", email, password, GP_FIREWALL, GP_NON_BLOCKING, s_connect_callback, buddy_man );\r\n\t}*/\r\n\t//Dbg_Printf( \"called gpconnect\\n\" );\r\n\r\n\t// Deregister this thread with the sockets API\r\n\tsockAPIderegthr();\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tBuddyMan::add_player_to_menu( BuddyInfo* buddy, bool allow_join, bool allow_remove )\r\n{\r\n\tScript::CStruct* p_item_params;\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tp_item_params = new Script::CStruct;\t\r\n\tchar upper_nick[1024];\r\n\r\n\t//Dbg_Printf( \"****** add_player_to_menu. Allow Join %d\\n\", (int) allow_join );\r\n\r\n\tsprintf( upper_nick, buddy->m_Nick );\r\n\r\n\tp_item_params->AddString( \"name\", buddy->m_Nick );\r\n\tp_item_params->AddString( \"status\", buddy->m_StatusString );\r\n\tp_item_params->AddString( \"location\", buddy->m_Location );\r\n\tp_item_params->AddChecksum( \"id\", Script::GenerateCRC( \"first_lobby_buddy\" ) + buddy->m_Profile );\r\n\tif( allow_join || allow_remove )\r\n\t{\r\n\t\t// create the parameters that are passed to the X script\r\n\t\tScript::CStruct *p_script_params= new Script::CStruct;\r\n\t\tp_script_params->AddInteger( \"profile\", buddy->m_Profile );\t\r\n\t\tp_script_params->AddString( \"nick\", strupr( upper_nick ));\t\r\n\t\tp_script_params->AddString( \"status\", buddy->m_StatusString );\t\r\n\t\tp_script_params->AddString( \"location\", buddy->m_Location );\r\n\t\tp_script_params->AddInteger( \"join_ip\", buddy->m_JoinIP );\t\r\n\t\tp_script_params->AddInteger( \"join_private_ip\", buddy->m_JoinPrivateIP );\t\r\n\t\tp_script_params->AddInteger( \"join_port\", buddy->m_JoinPort );\t\r\n\r\n\t\tif( allow_remove )\r\n\t\t{\r\n\t\t\tp_script_params->AddChecksum( NONAME, Script::GenerateCRC( \"allow_remove\" ));\t\r\n\t\t}\r\n\r\n\t\tif( allow_join && ( buddy->m_Status == GP_PLAYING ))\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"****** GP_PLAYING\\n\" );\r\n\t\t\tp_script_params->AddChecksum( NONAME, Script::GenerateCRC( \"allow_join\" ));\t\r\n\t\t}\r\n\r\n\t\tif( allow_join )\r\n\t\t{\r\n\t\t\tp_script_params->AddChecksum( NONAME, Script::GenerateCRC( \"in_lobby\" ));\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_script_params->AddChecksum( \"back_script\", Script::GenerateCRC( \"back_from_shell_buddy_options\" ));   \r\n\t\t\tp_script_params->AddChecksum( \"remove_script\", Script::GenerateCRC( \"shell_remove_buddy\" ));   \r\n\t\t}\r\n\t\tp_item_params->AddStructure( \"pad_choose_params\", p_script_params );\r\n\t\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"present_buddy_options\"));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"do_nothing\"));\r\n\t}\r\n\t\r\n\tp_item_params->AddChecksum( \"parent_menu_id\", Script::GenerateCRC( \"lobby_buddy_list_menu\" ));\r\n\tif( allow_join )\r\n\t{\r\n\t\tp_item_params->AddFloat( \"scale\", 1.1f );\r\n\t}                                            \r\n\r\n\t//Script::RunScript(\"make_text_sub_menu_item\",p_item_params);\r\n\tScript::RunScript(\"homie_list_add_item\",p_item_params);\r\n\tdelete p_item_params;\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tBuddyMan::fill_buddy_list( bool clear_list, bool allow_join, bool allow_remove )\r\n{\r\n\tLst::Search< BuddyInfo > sh;\r\n\tBuddyInfo* buddy;\r\n\r\n\tif( clear_list )\r\n\t{\r\n\t\t//Dbg_Printf( \"Clearing buddy list menu\\n\" );\r\n\t\tScript::RunScript( \"destroy_lobby_buddy_list_children\" );\r\n\t}\r\n\r\n\tfor( buddy = sh.FirstItem( m_buddies ); buddy; buddy = sh.NextItem())\r\n\t{\r\n\t\tif( buddy->m_Pending )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tadd_player_to_menu( buddy, allow_join, allow_remove );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tBuddyMan::fill_prospective_buddy_list( void )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo* player;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tif( player->IsLocalPlayer())\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif( player->m_Profile && !IsAlreadyMyBuddy( player->m_Profile ))\r\n\t\t{\r\n\t\t\tScript::CStruct* p_item_params;\r\n\t\r\n\t\t\t//Dbg_Printf( \"Adding %s of %d to the list\\n\", player->m_Name, player->m_Profile );\r\n\t\t\tp_item_params = new Script::CStruct;\t\r\n\t\t\tp_item_params->AddString( \"text\", player->m_Name );\r\n\t\t\tp_item_params->AddChecksum( \"id\", player->m_Profile );\r\n\t\t\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"add_buddy\"));\r\n\t\t\tp_item_params->AddChecksum( \"parent_menu_id\", Script::GenerateCRC( \"lobby_buddy_list_menu\" ));\r\n\t\t\r\n\t\t\t// create the parameters that are passed to the X script\r\n\t\t\tScript::CStruct *p_script_params= new Script::CStruct;\r\n\t\t\tp_script_params->AddInteger( \"profile\", player->m_Profile );\t\r\n\t\t\tp_script_params->AddString( \"nick\", player->m_Name );\t\r\n\t\t\tp_item_params->AddStructure( \"pad_choose_params\", p_script_params );\r\n\t\t\tp_item_params->AddFloat( \"scale\", 1.1f );\r\n\r\n\t\t\tScript::RunScript(\"make_text_sub_menu_item\",p_item_params);\r\n\r\n\t\t\tdelete p_item_params;\r\n\t\t\tdelete p_script_params;\r\n\t\t}\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBuddyMan::add_buddy( char *name, int profile )\r\n{\r\n\tGPResult result;\r\n\tBuddyInfo* new_buddy;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\tnew_buddy = new BuddyInfo;\r\n\tstrcpy( new_buddy->m_Nick, name );\r\n\tnew_buddy->m_Profile = profile;\r\n\tnew_buddy->m_Status = 0;\r\n\tnew_buddy->m_Pending = true;\r\n\r\n\tm_buddies.AddToTail( new_buddy );\r\n    \r\n\tresult = gpSendBuddyRequest( &m_gp_conn, profile, \"\" );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBuddyMan::cancel_add_buddy( void )\r\n{\r\n\tBuddyInfo* buddy;\r\n\tLst::Search< BuddyInfo > sh;\r\n\r\n\tfor( buddy = sh.FirstItem( m_buddies ); buddy; buddy = sh.NextItem())\r\n\t{\r\n\t\tif( buddy->m_Pending )\r\n\t\t{\r\n\t\t\tdelete buddy;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBuddyMan::remove_buddy( int profile )\r\n{\r\n\tBuddyInfo* buddy;\r\n\tLst::Search< BuddyInfo > sh;\r\n\tScript::CStruct* p_struct;\r\n\r\n\tfor( buddy = sh.FirstItem( m_buddies ); buddy; buddy = sh.NextItem())\r\n\t{\r\n\t\tif( buddy->m_Profile == profile )\r\n\t\t{\r\n\t\t\tdelete buddy;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tgpDeleteBuddy( &m_gp_conn, profile );\r\n                      \r\n\tp_struct = new Script::CStruct;\r\n\tp_struct->AddChecksum( \"id\", Script::GenerateCRC( \"first_lobby_buddy\" ) + profile );\r\n\r\n\tScript::RunScript( \"removed_buddy\", p_struct );\r\n\tdelete p_struct;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nBuddyMan::BuddyMan( void )\r\n{\r\n\tGPResult result;\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\t\r\n\tresult = gpInitialize( &m_gp_conn, vGAMESPY_PRODUCT_ID );\r\n\tDbg_Assert( result == GP_NO_ERROR );\r\n\r\n\tresult = gpSetCallback( &m_gp_conn, GP_ERROR, s_error_callback, this );\r\n\tDbg_Assert( result == GP_NO_ERROR );\r\n\r\n\tresult = gpSetCallback( &m_gp_conn, GP_RECV_BUDDY_REQUEST, s_buddy_request, this );\r\n\tDbg_Assert( result == GP_NO_ERROR );\r\n\r\n\tresult = gpSetCallback( &m_gp_conn, GP_RECV_BUDDY_STATUS, s_buddy_status, this );\r\n\tDbg_Assert( result == GP_NO_ERROR );\r\n\r\n\tresult = gpSetCallback( &m_gp_conn, GP_RECV_BUDDY_MESSAGE, s_buddy_message, this );\r\n\tDbg_Assert( result == GP_NO_ERROR );\r\n\r\n\tresult = gpSetCallback( &m_gp_conn, GP_RECV_GAME_INVITE, s_game_invite, this );\r\n\tDbg_Assert( result == GP_NO_ERROR );\r\n\r\n\tresult = gpSetCallback( &m_gp_conn, GP_TRANSFER_CALLBACK, s_transfer_callback, this );\r\n\tDbg_Assert( result == GP_NO_ERROR );\r\n\r\n\tm_buddy_logic_task = new Tsk::Task< BuddyMan > ( s_buddy_logic_code, *this );\r\n\r\n\tm_logged_in = false;\r\n\tm_state = vSTATE_WAIT;\r\n\tm_profile = 0;\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nBuddyMan::~BuddyMan( void )\r\n{\r\n\tdelete m_buddy_logic_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBuddyMan::Connected( GPProfile profile )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tm_logged_in = true;\r\n\tm_profile = profile;\r\n\tm_state = vSTATE_LOGGED_IN;\r\n\r\n\t//Dbg_Printf( \"******************** PROFILE IS %d\\n\", m_profile );\r\n\tScript::RunScript( \"profile_logged_in\" );\r\n    gpSetStatus( &m_gp_conn, GP_ONLINE, (char*) Script::GetString( \"homie_status_online\" ), \r\n\t\t\t\t\t\t\t\t\t\t(char*) Script::GetString( \"homie_status_logging_in\" ));\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::IsLoggedIn( void )\r\n{\r\n\treturn m_logged_in;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBuddyMan::Connect( void )\r\n{   \r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tThread::PerThreadStruct\tnet_thread_data;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\t\r\n\tm_state = vSTATE_CONNECTING;\r\n\ts_connect_start_time = Tmr::GetTime();\r\n\r\n\tScript::RunScript( \"log_in_profile\" );\r\n\r\n    net_thread_data.m_pEntry = s_threaded_buddy_connect;\r\n\tnet_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY;\r\n\tnet_thread_data.m_pStackBase = gamenet_man->GetNetThreadStack();\r\n\tnet_thread_data.m_iStackSize = vNET_THREAD_STACK_SIZE;\r\n\tnet_thread_data.m_utid = 0x152;\r\n\tThread::CreateThread( &net_thread_data );\r\n\tgamenet_man->SetNetThreadId( net_thread_data.m_osId );\r\n\tStartThread( gamenet_man->GetNetThreadId(), this );\r\n\r\n\tif( !m_buddy_logic_task->InList())\r\n\t{\r\n\t\tmlp_man->AddLogicTask( *m_buddy_logic_task );\r\n\t}\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBuddyMan::CreateProfile( void )\r\n{   \r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tThread::PerThreadStruct\tnet_thread_data;\r\n\r\n\tm_state = vSTATE_CREATING_PROFILE;\r\n\ts_connect_start_time = Tmr::GetTime();\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\t\r\n\tnet_thread_data.m_pEntry = s_threaded_buddy_create;\r\n\tnet_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY;\r\n\tnet_thread_data.m_pStackBase = gamenet_man->GetNetThreadStack();\r\n\tnet_thread_data.m_iStackSize = vNET_THREAD_STACK_SIZE;\r\n\tnet_thread_data.m_utid = 0x152;\r\n\tThread::CreateThread( &net_thread_data );\r\n\tgamenet_man->SetNetThreadId( net_thread_data.m_osId );\r\n\tStartThread( gamenet_man->GetNetThreadId(), this );\r\n\r\n\tmlp_man->AddLogicTask( *m_buddy_logic_task );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBuddyMan::Disconnect( void )\r\n{   \r\n\tBuddyInfo* buddy, *next;\r\n\tLst::Search< BuddyInfo > sh;\r\n\t\r\n\t//Dbg_Printf( \"***** Disconnecting from presence system\\n\" );\r\n\tgpDisconnect( &m_gp_conn );\r\n\tm_buddy_logic_task->Remove();\r\n\tm_logged_in = false;\r\n\r\n\t/*SetStatusAndLocation( GP_OFFLINE, \t(char*) Script::GetString( \"homie_status_offline\" ), \r\n\t\t\t\t\t\t\t\t\t\t\"\" );*/\r\n\tfor( buddy = sh.FirstItem( m_buddies ); buddy; buddy = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tdelete buddy;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tBuddyMan::GetProfile( void )\r\n{\r\n\treturn m_profile;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::IsAlreadyMyBuddy( int profile )\r\n{\r\n\tBuddyInfo* buddy;\r\n\tLst::Search< BuddyInfo > sh;\r\n\t\r\n\tfor( buddy = sh.FirstItem( m_buddies ); buddy; buddy = sh.NextItem())\r\n\t{\r\n\t\tif( buddy->m_Profile == profile )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tBuddyMan::NumBuddies( void )\r\n{\r\n\treturn m_buddies.CountItems();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBuddyMan::SetStatusAndLocation( int status, char* status_string, char* location )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\t//Dbg_Printf( \"Setting status to %d : %s , %s\\n\", status, status_string, location );\r\n\tgpSetStatus( &m_gp_conn, (GPEnum) status, status_string, location );\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptSetUniqueId(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tScript::CStruct* new_params;\r\n\tPrefs::Preferences*\tprefs;\r\n\tTmr::Time time;\r\n\tint ms_time;\r\n\tchar str_time[32];\r\n\r\n\ttime = Tmr::GetTime();\r\n\tms_time = (int) time;\r\n\r\n\t//Dbg_Printf( \"*************** (Getting Time) Setting unique id to %d\\n\", ms_time );\r\n\t\r\n\tprefs = gamenet_man->GetNetworkPreferences();\r\n\tnew_params = new Script::CStruct;\r\n\tsprintf( str_time, \"%d\", ms_time );\r\n\tnew_params->AddString( \"ui_string\", str_time );\r\n\tprefs->SetPreference( Script::GenerateCRC( \"unique_id\" ), new_params );\r\n\tdelete new_params;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptProfileLoggedIn(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tBuddyMan* buddy_man;\r\n\r\n\tbuddy_man = gamenet_man->mpBuddyMan;\r\n\treturn buddy_man->IsLoggedIn();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptProfileLogIn(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tPrefs::Preferences*\tprefs;\r\n\t\r\n\tprefs = gamenet_man->GetNetworkPreferences();\r\n\tuint32 success = prefs->GetPreferenceChecksum( Script::GenerateCRC( \"profile_success\" ), Script::GenerateCRC( \"checksum\" ));\r\n\tif( success != Script::GenerateCRC( \"boolean_true\" ))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tgamenet_man->mpBuddyMan->Connect();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptProfileLogOff(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tBuddyMan* buddy_man;\r\n\r\n\tbuddy_man = gamenet_man->mpBuddyMan;\r\n\tbuddy_man->Disconnect();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptCreateProfile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\r\n\tgamenet_man->mpBuddyMan->CreateProfile();\r\n    \r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptFillBuddyList(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tbool clear_list, allow_join, allow_remove;\r\n\r\n\tclear_list = pParams->ContainsFlag( \"clear_list\" );\r\n\tallow_join = pParams->ContainsFlag( \"allow_join\" );\r\n\tallow_remove = pParams->ContainsFlag( \"allow_remove\" );\r\n\r\n\t//Dbg_Printf( \"****** ScripFillBuddyList. Allow Join %d\\n\", (int) allow_join );\r\n\tgamenet_man->mpBuddyMan->fill_buddy_list( clear_list, allow_join, allow_remove );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptFillProspectiveBuddyList(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\r\n\tgamenet_man->mpBuddyMan->fill_prospective_buddy_list();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptAddBuddy(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tint profile;\r\n\tconst char* nick;\r\n\r\n\tpParams->GetInteger( \"profile\", &profile, Script::ASSERT );\r\n\tpParams->GetString( \"nick\", &nick, Script::ASSERT );\r\n\r\n\tgamenet_man->mpBuddyMan->add_buddy((char *) nick, profile );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptCancelAddBuddy(Script::CStruct *pParams, Script::CScript *pScript)\r\n{                                                               \r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n                                                                \r\n\tgamenet_man->mpBuddyMan->cancel_add_buddy();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptRemoveBuddy(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint profile;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n                                                                \r\n\tpParams->GetInteger( \"profile\", &profile, Script::ASSERT );\r\n\tgamenet_man->mpBuddyMan->remove_buddy( profile );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptJoinBuddy(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tchar location[1024];\r\n\tint join_ip, join_private_ip, join_port;\r\n\tconst char* location_str;\r\n\tbool observing, local;\r\n\tScript::CStruct* p_struct;\r\n\r\n\tobserving = pParams->ContainsFlag( \"observe\" );\r\n\tpParams->GetString( \"location\", &location_str, Script::ASSERT );\r\n\tpParams->GetInteger( \"join_ip\", &join_ip, Script::ASSERT );\r\n\tpParams->GetInteger( \"join_private_ip\", &join_private_ip, Script::ASSERT );\r\n\tpParams->GetInteger( \"join_port\", &join_port, Script::ASSERT );\r\n\tsprintf( location, \"%d:%d:%d:%s\", join_ip, join_private_ip, join_port, location_str );\r\n\r\n\tlocal = false;\r\n\tif((unsigned int) join_ip == peerGetLocalIP( gamenet_man->mpLobbyMan->GetPeer()))\r\n\t{\r\n\t\tjoin_ip = join_private_ip;\r\n\t\tjoin_port = vHOST_PORT;\r\n\t\tlocal = true;\r\n\t}\r\n\t\r\n\tif( observing )\r\n\t{\r\n\t\tgamenet_man->SetJoinMode( vJOIN_MODE_OBSERVE );\r\n\t\tgamenet_man->mpBuddyMan->SetStatusAndLocation( GP_PLAYING, (char*) Script::GetString( \"homie_status_observing\" ), location );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgamenet_man->SetJoinMode( vJOIN_MODE_PLAY );\r\n\t\tgamenet_man->mpBuddyMan->SetStatusAndLocation( GP_PLAYING, (char*) Script::GetString( \"homie_status_playing\" ), location );\r\n\t}\r\n\r\n\tchar *ip_addr;\r\n\tstruct in_addr addr;\r\n\tuint32 cookie;\r\n\t\t\r\n\tp_struct = new Script::CStruct;\r\n\r\n\taddr.s_addr = join_ip;\r\n\tip_addr = inet_ntoa( addr );\r\n\tp_struct->AddComponent( NONAME, ESYMBOLTYPE_INTEGER, join_port );\r\n\tp_struct->AddComponent( NONAME, ESYMBOLTYPE_STRING, ip_addr );\r\n\t\t\r\n\tif( !local )\r\n\t{\r\n\t\tcookie = Mth::Rnd( 65535 );\r\n\t\tp_struct->AddComponent( CRCD( 0x751f4599, \"cookie\" ), ESYMBOLTYPE_NAME, cookie );\r\n\t}\r\n\t\t\r\n\tScript::RunScript( \"net_chosen_join_server\", p_struct );\r\n\tdelete p_struct;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptHasBuddies(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\treturn ( gamenet_man->mpBuddyMan->NumBuddies() > 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptBuddyListFull(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\treturn ( gamenet_man->mpBuddyMan->NumBuddies() >= vMAX_BUDDIES );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tBuddyMan::ScriptSetLobbyStatus(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tDbg_Assert( gamenet_man->mpBuddyMan->IsLoggedIn());\r\n\tgamenet_man->mpBuddyMan->SetStatusAndLocation( GP_CHATTING, (char*) Script::GetString( \"homie_status_chatting\" ), \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgamenet_man->mpLobbyMan->GetLobbyName());\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nBuddyInfo::BuddyInfo( void )\r\n: Lst::Node< BuddyInfo > ( this )\r\n{\r\n\tm_Pending = false;\r\n\tm_Status = 0;\r\n\tm_Location[0] = '\\0';\r\n\tsprintf( m_StatusString, \"Offline\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/p_buddy.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_buddy.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/28/02\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPS2 Buddy List Code \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GAMENET_NGPS_P_BUDDY_H\r\n#define __GAMENET_NGPS_P_BUDDY_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <gp/gp.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace GameNet\r\n{\r\n\r\nenum\r\n{\r\n\tvCOMMAND_NONE,\r\n\tvCOMMAND_CONNECT,\r\n\tvCOMMAND_LOGIN\r\n};\r\n\r\nenum\r\n{\r\n\tvSTATE_WAIT,\r\n\tvSTATE_CREATING_PROFILE,\r\n\tvSTATE_CONNECTING,\r\n\tvSTATE_BEGIN_LOGIN,\r\n\tvSTATE_LOGGED_IN\r\n};\r\n\r\nenum\r\n{\r\n\tvMAX_BUDDIES = 30\r\n};\r\n\r\nclass BuddyInfo : public Lst::Node< BuddyInfo >\r\n{\r\npublic:\r\n\tBuddyInfo( void );\r\n\r\n\tchar\tm_Nick[GP_NICK_LEN];\r\n\tint\t\tm_Profile;\r\n\tint\t\tm_Status;\r\n\tbool\tm_Pending;\r\n\tint\t\tm_JoinIP;\r\n\tint\t\tm_JoinPrivateIP;\r\n\tint\t\tm_JoinPort;\r\n\tchar\tm_Location[GP_LOCATION_STRING_LEN];\r\n\tchar\tm_StatusString[GP_STATUS_STRING_LEN];\r\n};\r\n\r\nclass BuddyMan\r\n{\r\npublic:\r\n\tBuddyMan( void );\r\n\t~BuddyMan( void );\r\n\r\n\tvoid\tConnect( void );\r\n\tvoid\tCreateProfile( void );\r\n\tvoid\tDisconnect( void );\r\n\tvoid\tConnected( GPProfile profile );\r\n\tbool\tIsLoggedIn( void );\r\n\tbool\tIsAlreadyMyBuddy( int profile );\r\n\tint\t\tNumBuddies( void );\r\n\r\n\tint\t\tGetProfile( void );\r\n\tvoid\tSetStatusAndLocation( int status, char* status_string, char* location );\r\n\r\n\tstatic\tbool\t\tScriptSetUniqueId(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptProfileLoggedIn(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptCreateProfile(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptProfileLogOff(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptProfileLogIn(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptFillBuddyList(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptFillProspectiveBuddyList(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptAddBuddy(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptCancelAddBuddy(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptRemoveBuddy(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptJoinBuddy(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptHasBuddies(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic \tbool\t\tScriptBuddyListFull(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic \tbool\t\tScriptSetLobbyStatus(Script::CStruct *pParams, Script::CScript *pScript);\r\n    \r\nprivate:\r\n\tGPConnection\tm_gp_conn;\r\n\tGPProfile\t\tm_profile;\r\n\tint\t\t\t\tm_state;\r\n\r\n\tstatic\tvoid s_connect_callback( GPConnection* connection, void* arg, void* param );\r\n\r\n\tstatic\tvoid s_error_callback( GPConnection* connection, void* arg, void* param );\r\n\tstatic \tvoid s_buddy_request( GPConnection* connection, void* arg, void* param );\r\n\tstatic\tvoid s_buddy_status( GPConnection* connection, void* arg, void* param );\r\n\tstatic\tvoid s_buddy_message( GPConnection* connection, void* arg, void* param );\r\n\tstatic\tvoid s_game_invite( GPConnection* connection, void* arg, void* param );\r\n\tstatic\tvoid s_transfer_callback( GPConnection* connection, void* arg, void* param );\r\n\r\n\tstatic\tvoid s_threaded_buddy_connect( BuddyMan* buddy_man );\r\n\tstatic\tvoid s_threaded_buddy_create( BuddyMan* buddy_man );\r\n\r\n\tvoid\t\tadd_player_to_menu( BuddyInfo* buddy, bool allow_join, bool allow_remove );\r\n\tvoid\t\tfill_buddy_list( bool clear_list, bool allow_join, bool allow_remove );\r\n\tvoid\t\tfill_prospective_buddy_list( void );\r\n\tvoid\t\tadd_buddy( char *name, int profile );\r\n\tvoid\t\tcancel_add_buddy( void );\r\n\tvoid\t\tremove_buddy( int profile );\r\n\r\n\tTsk::Task< BuddyMan >*\t\t\t\t\tm_buddy_logic_task;\r\n\tstatic\tTsk::Task< BuddyMan >::Code   \ts_buddy_logic_code;\r\n\r\n\tbool\tm_logged_in;\r\n\tLst::Head< BuddyInfo > m_buddies;\r\n};\r\n\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n#endif\t// __GAMENET_NGPS_P_BUDDY_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/p_content.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tLobby.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t04/4/02\t-\tspg\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGamespy peer lobby implementation\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/thread.h>\r\n#include <core/singleton.h>\r\n\r\n#include <gel/mainloop.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/utils.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/gamenet/ngps/p_content.h>\r\n#include <sk/gamenet/ngps/p_buddy.h>\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/scripting/mcfuncs.h>\r\n#include <sk/ParkEditor2/EdMap.h>\r\n\r\n// for downloading faces\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/skaterprofile.h>\r\n#include <gfx/facetexture.h>\r\n#include <gfx/modelappearance.h>\r\n\r\n#include <ghttp/ghttp.h>\r\n#include <ghttp/ghttppost.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\nnamespace GameNet\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define vHTTP_COMM_TIMEOUT\tTmr::Seconds( 25 )\r\n#define vMAX_FACE_SIZE\t\t( 32 * 1024 )\r\n#define vMAX_FILE_SIZE\t( 80 * 1024 )\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \tContentMan::s_progress_callback(\tGHTTPRequest request,       // The request.\r\n\t\t\t\t\t\t\t\t\t\t\tGHTTPState state,           // The current state of the request.\r\n\t\t\t\t\t\t\t\t\t\t\tconst char* buffer,        \t// The file's bytes so far, NULL if state<GHTTPReceivingFile.\r\n\t\t\t\t\t\t\t\t\t\t\tint buffer_len,             // The number of bytes in the buffer, 0 if state<GHTTPReceivingFile.\r\n\t\t\t\t\t\t\t\t\t\t\tint bytes_received,         // The total number of bytes receivied, 0 if state<GHTTPReceivingFile.\r\n\t\t\t\t\t\t\t\t\t\t\tint total_size,             // The total size of the file, -1 if unknown.\r\n\t\t\t\t\t\t\t\t\t\t\tvoid * param                // User-data.\r\n\t\t\t\t\t\t\t\t\t\t)\r\n{\r\n\tContentMan* content_man;\r\n\r\n\tcontent_man = (ContentMan*) param;\r\n\r\n\tDbg_Printf( \"state: %d buffer len: %d, bytes received %d, total_size %d\\n\", state, buffer_len, bytes_received, total_size );\r\n\tif(\t( state == GHTTPReceivingFile ) ||\r\n\t\t( state == GHTTPPosting ))\r\n\t{\r\n\t\tif( total_size > 0 )\r\n\t\t{\r\n\t\t\tcontent_man->m_percent_complete = (int) (((float) bytes_received / (float) total_size ) * 100.0f );\r\n\t\t}\r\n\t}\r\n\r\n\tcontent_man->m_last_comm_time = Tmr::GetTime();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGHTTPBool ContentMan::s_dl_completed_callback(\tGHTTPRequest request,       // The request.\r\n\t\t\t\t\t\t\t\t\t\tGHTTPResult result,         // The result (success or an error).\r\n\t\t\t\t\t\t\t\t\t\tchar* buffer,              // The file's bytes (only valid if ghttpGetFile[Ex] was used).\r\n\t\t\t\t\t\t\t\t\t\tint buffer_len,              // The file's length.\r\n\t\t\t\t\t\t\t\t\t\tvoid * param                // User-data.\r\n\t\t\t\t\t\t\t\t\t\t)\r\n{\r\n\tContentMan* content_man;\r\n\r\n\tcontent_man = (ContentMan*) param;\r\n\r\n\tDbg_Printf( \"Got result %d\\n\", result );\r\n\r\n\tcontent_man->m_percent_complete = 100;\r\n\tif( result == GHTTPSuccess )\r\n\t{\r\n\t\tuint32 type;\r\n\r\n\t\tcontent_man->m_result = vCONTENT_RESULT_SUCCESS;\r\n\r\n\t\ttype = 0;\r\n\t\tswitch( content_man->m_vault_type ) \r\n\t\t{\r\n\t\t\tcase 0x5be5569f:\t// parks\r\n\t\t\t\ttype = CRCD(0x3bf882cc,\"park\");\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x7364ea1:\t\t// skaters\r\n\t\t\t\ttype = CRCD(0xb010f357,\"optionsandpros\");\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x38dbe1d0:\t// goals\r\n\t\t\t\ttype = CRCD(0x62896edf,\"createdgoals\");\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x1e26fd3e:\t// tricks\r\n\t\t\t\ttype = CRCD(0x61a1bc57,\"cat\");\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tCFuncs::SetVaultData((uint8*) buffer, type );\r\n\t\t\r\n\t\tcontent_man->m_error = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcontent_man->m_result = vCONTENT_RESULT_FAILURE;\r\n\t\tcontent_man->m_error = result;\r\n\t}\r\n\t\r\n\treturn GHTTPTrue;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGHTTPBool ContentMan::s_face_dl_completed_callback(\tGHTTPRequest request,       // The request.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGHTTPResult result,         // The result (success or an error).\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tchar* buffer,              // The file's bytes (only valid if ghttpGetFile[Ex] was used).\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tint buffer_len,              // The file's length.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tvoid * param                // User-data.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t)\r\n{\r\n\tContentMan* content_man;\r\n\r\n\tcontent_man = (ContentMan*) param;\r\n\r\n\tDbg_Printf( \"Got result %d\\n\", result );\r\n\r\n\tcontent_man->m_percent_complete = 100;\r\n\tif( result == GHTTPSuccess )\r\n\t{\r\n\t\tcontent_man->m_result = vCONTENT_RESULT_SUCCESS;\r\n\t\tcontent_man->m_error = 0;\r\n\t\t\r\n\t\t// Copy the downloaded data to the skater profile\r\n\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\tObj::CSkaterProfile* pSkaterProfile = skate_mod->GetCurrentProfile();\r\n\t\tDbg_Assert( pSkaterProfile );\r\n\t\tDbg_MsgAssert( !pSkaterProfile->IsPro(), ( \"Can only download face onto a custom skater.  UI must make the custom skater active before this point\" ) );\r\n\t\tGfx::CModelAppearance* pAppearance = pSkaterProfile->GetAppearance();\r\n\t\tDbg_Assert( pAppearance );\r\n\t\tGfx::CFaceTexture* pFaceTexture = pAppearance->GetFaceTexture();\r\n\t\tDbg_MsgAssert( pFaceTexture, ( \"Appearance has no face texture\" ) );\r\n\t\t\r\n\t\t// GJ:  The CFaceTexture is permanently allocated in the\r\n\t\t// custom skater, so there should be no need to push \r\n\t\t// any heap contexts here...  if this assumption changes, \r\n\t\t// then we should probably push the skt_info heap\r\n\t\tpFaceTexture->ReadTextureDataFromBuffer( (uint8*)buffer, 0 );\r\n\t\tpFaceTexture->SetValid( true );\r\n\r\n\t\t// rebuild the skater to display the new face\r\n\t\tScript::RunScript( CRCD(0x808008ea,\"refresh_skater_model\") );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcontent_man->m_result = vCONTENT_RESULT_FAILURE;\r\n\t\tcontent_man->m_error = result;\r\n\t}\r\n    \r\n\treturn GHTTPTrue;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGHTTPBool ContentMan::s_ul_completed_callback(\tGHTTPRequest request,       // The request.\r\n\t\t\t\t\t\t\t\t\t\tGHTTPResult result,         // The result (success or an error).\r\n\t\t\t\t\t\t\t\t\t\tchar* buffer,              // The file's bytes (only valid if ghttpGetFile[Ex] was used).\r\n\t\t\t\t\t\t\t\t\t\tint buffer_len,              // The file's length.\r\n\t\t\t\t\t\t\t\t\t\tvoid * param                // User-data.\r\n\t\t\t\t\t\t\t\t\t\t)\r\n{\r\n\tContentMan* content_man;\r\n\r\n\tcontent_man = (ContentMan*) param;\r\n\r\n\tDbg_Printf( \"Got result %d\\n\", result );\r\n\r\n\tcontent_man->m_percent_complete = 100;\r\n\tif( result == GHTTPSuccess )\r\n\t{\r\n\t\tcontent_man->m_result = vCONTENT_RESULT_SUCCESS;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcontent_man->m_result = vCONTENT_RESULT_FAILURE;\r\n\t}\r\n\t\r\n\treturn GHTTPTrue;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tContentMan::s_http_transfer_code( const Tsk::Task< ContentMan > &task )\r\n{\r\n\tContentMan& content_man = task.GetData();\r\n\r\n\tif(( Tmr::GetTime() - content_man.m_last_comm_time ) > vHTTP_COMM_TIMEOUT )\r\n\t{\r\n\t\tif(\tcontent_man.m_state != vCONTENT_STATE_IDLE )\r\n\t\t{\r\n\t\t\tdelete [] content_man.m_buffer;\r\n\t\t}\r\n\r\n\t\tDbg_Printf( \"********* TIMING OUT!!!!\\n\" );\r\n\t\tDbg_Assert( content_man.m_transfer_failed_script );\r\n\r\n\t\tghttpCancelRequest( content_man.m_file_request );\r\n\r\n\t\tScript::RunScript( content_man.m_transfer_failed_script );\r\n\t\tcontent_man.m_state = vCONTENT_STATE_IDLE;\r\n\t\tcontent_man.m_http_transfer_task->Remove();\r\n\r\n        //ghttpCleanup();\r\n\t\treturn;\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\tghttpThink();\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tif( content_man.m_percent_complete < 100 )\r\n\t{\r\n\t\tif(( content_man.m_state == vCONTENT_STATE_DOWNLOADING ) ||\r\n\t\t   ( content_man.m_state == vCONTENT_STATE_DOWNLOADING_FACE ))\r\n\t\t{\r\n\t\t\tScript::CStruct* p_item_params;\r\n\t\t\tchar pct_string[8];\r\n\t\t\r\n\t\t\tsprintf( pct_string, \"%d%%\", content_man.m_percent_complete );\r\n\t\t\t\t\t\r\n\t\t\tp_item_params = new Script::CStruct;\r\n\t\t\tp_item_params->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, pct_string );\r\n\t\t\tDbg_Assert( content_man.m_update_progress_script );\r\n\t\t\tScript::RunScript( content_man.m_update_progress_script, p_item_params );\r\n\t\t\tdelete p_item_params;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( ( content_man.m_state == vCONTENT_STATE_DOWNLOADING ) ||\r\n\t\t\t( content_man.m_state == vCONTENT_STATE_DOWNLOADING_FACE ))\r\n\t\t{\r\n\t\t\tdelete [] content_man.m_buffer;\r\n\t\t}\r\n\r\n\t\t//WaitSema( content_man.m_thread_semaphore_id );\r\n\t\tif(( content_man.m_state == vCONTENT_STATE_DOWNLOADING ) || \r\n\t\t   ( content_man.m_state == vCONTENT_STATE_DOWNLOADING_FACE ) ||\r\n\t\t   ( content_man.m_state == vCONTENT_STATE_UPLOADING ))\r\n\t\t{\r\n\t\t\tint prev_state;\r\n\t\t\t \r\n\t\t\tprev_state = content_man.m_state;\r\n\t\t\tcontent_man.m_http_transfer_task->Remove();\r\n\t\t\tcontent_man.m_state = vCONTENT_STATE_IDLE;\r\n\r\n\t\t\tif( content_man.m_result == vCONTENT_RESULT_SUCCESS )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* params;\r\n\r\n\t\t\t\tparams = new Script::CStruct;\r\n\t\t\t\tparams->AddChecksum( \"type\", content_man.m_vault_type );\r\n\t\t\t\tif( prev_state == vCONTENT_STATE_UPLOADING )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript( \"LaunchUploadCompleteDialog\", params );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( content_man.m_transfer_complete_script );\r\n\t\t\t\t\tScript::RunScript( content_man.m_transfer_complete_script, params );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tdelete params;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( content_man.m_error == GHTTPFileNotFound )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( content_man.m_file_not_found_script );\r\n\t\t\t\t\tScript::RunScript( content_man.m_file_not_found_script );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Assert( content_man.m_transfer_failed_script );\r\n\t\t\t\t\tScript::RunScript( content_man.m_transfer_failed_script );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif( ( prev_state == vCONTENT_STATE_DOWNLOADING ) ||\r\n\t\t\t\t( prev_state == vCONTENT_STATE_DOWNLOADING_FACE ))\r\n\t\t\t{\r\n\t\t\t\t//delete [] content_man.m_buffer;\r\n\t\t\t}\r\n\t\t\tif( prev_state == vCONTENT_STATE_UPLOADING )\r\n\t\t\t{\r\n\t\t\t\tdelete [] content_man.m_buffer;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t//content_man.m_state = vCONTENT_STATE_IDLE;\r\n\t\t\t//content_man.m_http_transfer_task->Remove();\r\n\t\t\t//ghttpCleanup();\r\n\t\t}\r\n\t\telse if( content_man.m_state == vCONTENT_STATE_GETTING_DIR_LIST )\r\n\t\t{\r\n\t\t\tif( content_man.m_result == vCONTENT_RESULT_SUCCESS )\r\n\t\t\t{\r\n\t\t\t\tchar* token;\r\n\t\t\t\tDirectory* dir;\r\n\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\t\t\t\tDbg_Printf( \"**** Parsing directory listing\\n\" );\r\n\t\t\t\ttoken = strtok( content_man.m_buffer, \"\\r\\n\" );\r\n\t\t\t\tif( token )\r\n\t\t\t\t{\r\n\t\t\t\t\tdo\r\n\t\t\t\t\t{   \r\n\t\t\t\t\t\tDbg_Printf( \"**** Got dir %s\\n\", token );\r\n\t\t\t\t\t\tdir = new Directory;\r\n\t\t\t\t\t\tcontent_man.m_directories.AddToHead( dir );\r\n\t\t\t\t\t\tstrcpy( dir->m_Name, token );\r\n\t\t\t\t\t} while(( token = strtok( NULL, \"\\r\\n\" )));\r\n\r\n\t\t\t\t\tcontent_man.m_cur_dir = content_man.m_next_dir_sh.FirstItem( content_man.m_directories );\r\n\t\t\t\t\tif( content_man.m_cur_dir->m_Uploads )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontent_man.m_cur_dir = content_man.m_next_dir_sh.NextItem();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tDbg_Printf( \"**** Getting subdir listing for %s\\n\", content_man.m_cur_dir->m_Name );\r\n\r\n\t\t\t\t\tcontent_man.m_state = vCONTENT_STATE_IDLE;\r\n\t\t\t\t\t//ghttpCleanup();\r\n\t\t\t\t\tdelete [] content_man.m_buffer;\r\n\r\n\t\t\t\t\t//SignalSema( content_man.m_thread_semaphore_id );\r\n\t\t\t\t\tcontent_man.GetSubDirListing( content_man.m_cur_dir );\r\n\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tcontent_man.m_state = vCONTENT_STATE_IDLE;\r\n\t\t\t\tcontent_man.m_http_transfer_task->Remove();\r\n\t\t\t\t//ghttpCleanup();\r\n\t\t\t\tdelete [] content_man.m_buffer;\r\n\r\n\t\t\t\tDbg_Assert( content_man.m_transfer_failed_script );\r\n\t\t\t\tScript::RunScript( content_man.m_transfer_failed_script );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( content_man.m_state == vCONTENT_STATE_GETTING_SUB_DIR_LIST )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\t\t\tDbg_Printf( \"Got sub_dir list\\n\" );\r\n\r\n\t\t\tif( content_man.m_result == vCONTENT_RESULT_SUCCESS )\r\n\t\t\t{\r\n\t\t\t\tContent* content;\r\n\t\t\t\tchar* line, *colon, *token;\r\n\t\t\t\tchar fname[Content::vMAX_FILE_NAME_LEN + 1];\r\n\t\t\t\tchar buff[128];\r\n\r\n\t\t\t\tline = strtok( content_man.m_buffer, \"\\r\\n\" );\r\n\t\t\t\tif( line )\r\n\t\t\t\t{\r\n\t\t\t\t\tdo\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontent = new Content;\r\n\t\t\t\t\t\tcontent_man.m_cur_dir->m_content_list.AddToHead( content );\r\n\r\n\t\t\t\t\t\ttoken = line;\r\n\t\t\t\t\t\tcolon = strstr( line, \":\" );\r\n\t\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\t\tstrcpy( fname, token );\r\n\r\n\t\t\t\t\t\tsprintf( content->m_Path, \"http://www.thugonline.com/%s/%s/%s\", content_man.m_vault_root, content_man.m_cur_dir->m_Name, fname );\r\n\t\t\t\t\t\tDbg_Printf( \"Filename: %s\\n\", fname );\r\n\r\n\t\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\t\tstrcpy( content->m_Name, token );\r\n\t\t\t\t\t\tDbg_Printf( \"Display name: %s\\n\", content->m_Name );\r\n\r\n\t\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\t\tstrcpy( content->m_Creator, token );\r\n\t\t\t\t\t\tDbg_Printf( \"Creator: %s\\n\", content->m_Creator );\r\n\r\n\t\t\t\t\t\t// Read the content size, if we're looking at parks\r\n\t\t\t\t\t\tif( content_man.m_vault_type == CRCD(0x5be5569f,\"parks\") )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\t\t\tstrcpy( content->m_Size, token );\r\n\t\t\t\t\t\t\tDbg_Printf( \"Size: %s\\n\", content->m_Size );\r\n\r\n\t\t\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\t\t\tstrcpy( buff, token );\r\n\t\t\t\t\t\t\tcontent->m_NumPieces = atoi( buff );\r\n\t\t\t\t\t\t\tDbg_Printf( \"Pieces: %d\\n\", content->m_NumPieces );\r\n\r\n\t\t\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\t\t\tstrcpy( buff, token );\r\n\t\t\t\t\t\t\tcontent->m_NumGaps = atoi( buff );\r\n\t\t\t\t\t\t\tDbg_Printf( \"Gaps: %d\\n\", content->m_NumGaps );\r\n\r\n\t\t\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\t\t\tstrcpy( buff, token );\r\n\t\t\t\t\t\t\tcontent->m_NumGoals = atoi( buff );\r\n\t\t\t\t\t\t\tDbg_Printf( \"Goals: %d\\n\", content->m_NumGoals );\r\n\r\n\t\t\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\t\t\tstrcpy( buff, token );\r\n\t\t\t\t\t\t\tcontent->m_Theme = atoi( buff );\r\n\t\t\t\t\t\t\tDbg_Printf( \"Theme: %d\\n\", content->m_Theme );\r\n\r\n\t\t\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\t\t\tstrcpy( buff, token );\r\n\t\t\t\t\t\t\tcontent->m_TODScript = atoi( buff );\r\n\t\t\t\t\t\t\tDbg_Printf( \"Script: 0x%x\\n\", content->m_TODScript );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Read the content score, if we're looking at tricks\r\n\t\t\t\t\t\tif( content_man.m_vault_type == CRCD(0x1e26fd3e,\"tricks\") )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\t\t\tstrcpy( buff, token );\r\n\t\t\t\t\t\t\tcontent->m_Score = atoi( buff );\r\n\t\t\t\t\t\t\tDbg_Printf( \"Score: %d\\n\", content->m_Score );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Read the content sex, if we're looking at skaters\r\n\t\t\t\t\t\tif( content_man.m_vault_type == CRCD(0x7364ea1,\"skaters\") )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\t\t\t//strcpy( content->m_IsMale, token );\r\n\t\t\t\t\t\t\tstrcpy( buff, token );\r\n\t\t\t\t\t\t\tcontent->m_IsMale = atoi( buff );\r\n\t\t\t\t\t\t\tDbg_Printf( \"IsMale: %d\\n\", content->m_IsMale );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Read the content sex, if we're looking at skaters\r\n\t\t\t\t\t\tif( content_man.m_vault_type == CRCD(0x38dbe1d0,\"goals\") )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\t\t\tstrcpy( buff, token );\r\n\t\t\t\t\t\t\tcontent->m_NumGoals = atoi( buff );\r\n\t\t\t\t\t\t\tDbg_Printf( \"Goals: %d\\n\", content->m_NumGoals );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\t\tstrcpy( content->m_Checksum, token );\r\n\t\t\t\t\t\tDbg_Printf( \"Checksum: %s\\n\", content->m_Checksum );\r\n\r\n\t\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\t\tstrcpy( content->m_Description, token );\r\n\t\t\t\t\t\tDbg_Printf( \"Desc: %s\\n\", content->m_Description );\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\t//Dbg_Printf( \"////////////////////////\\n\" );\r\n\t\t\t\t\t\t//Dbg_Printf( \"Name: %s\\n\", content->m_Name );\r\n\t\t\t\t\t\t//Dbg_Printf( \"Creator: %s\\n\", content->m_Creator );\r\n\t\t\t\t\t\t//Dbg_Printf( \"Size: %s\\n\", content->m_Size );\r\n\t\t\t\t\t\t//Dbg_Printf( \"Checksum: %s\\n\", content->m_Checksum );\r\n\t\t\t\t\t\t//Dbg_Printf( \"Desc: %s\\n\", content->m_Description );\r\n\t\t\t\t\t} while(( line = strtok( NULL, \"\\r\\n\" )));\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tcontent_man.m_state = vCONTENT_STATE_IDLE;\r\n\t\t\t\t//ghttpCleanup();\r\n\t\t\t\tdelete [] content_man.m_buffer;\r\n\r\n\t\t\t\tcontent_man.m_cur_dir = content_man.m_next_dir_sh.NextItem();\r\n\t\t\t\tif(( content_man.m_cur_dir == NULL ) || ( content_man.m_cur_dir->m_Uploads ))\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct* pParams;\r\n\t\t\t\t\tcontent_man.m_cur_dir = content_man.m_next_dir_sh.FirstItem( content_man.m_directories );\r\n\r\n\t\t\t\t\t// We are done. Now display the first category of files\r\n\t\t\t\t\t//Dbg_Printf( \"**** Done downloading subdirectory listings\\n\" );\r\n\t\t\t\t\tcontent_man.m_http_transfer_task->Remove();\r\n\t\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\t\tpParams->AddString( \"category\", content_man.m_cur_dir->m_Name );\r\n\t\t\t\t\tpParams->AddChecksum( \"type\", content_man.m_vault_type );\r\n\t\t\t\t\tScript::RunScript( \"net_vault_menu_create\", pParams );\r\n\t\t\t\t\tdelete pParams;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tcontent_man.GetSubDirListing( content_man.m_cur_dir );\r\n\t\t\t\t}\r\n\t\t\t}\r\n            else\r\n\t\t\t{\r\n\t\t\t\tcontent_man.m_state = vCONTENT_STATE_IDLE;\r\n\t\t\t\tcontent_man.m_http_transfer_task->Remove();\r\n\r\n\t\t\t\t//ghttpCleanup();\r\n\t\t\t\tdelete [] content_man.m_buffer;\r\n\t\t\t\tDbg_Assert( content_man.m_transfer_failed_script );\r\n\t\t\t\tScript::RunScript( content_man.m_transfer_failed_script );\r\n\t\t\t}\r\n\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t}\r\n\t\telse if( content_man.m_state == vCONTENT_STATE_GETTING_UPLOADED_LEVELS )\r\n\t\t{\r\n\t\t\tchar* line, *colon, *token;\r\n\t\t\tContent* content;\r\n\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n                                      \r\n\t\t\tline = strtok( content_man.m_buffer, \"\\r\\n\" );\r\n\t\t\tif( line )\r\n\t\t\t{\r\n\t\t\t\tdo\r\n\t\t\t\t{\r\n\t\t\t\t\tcontent = new Content;\r\n\t\t\t\t\tcontent_man.m_cur_dir->m_content_list.AddToHead( content );\r\n\r\n\t\t\t\t\t//Dbg_Printf( \"******************************************\\n\" );\r\n\t\t\t\t\t//Dbg_Printf( \"Line: %s\\n\", line );\r\n\t\t\t\t\tsprintf( content->m_Path, \"http://www.thugonline.com/%s/%s\", content_man.m_vault_root, line );\r\n\r\n\t\t\t\t\ttoken = line;\r\n\t\t\t\t\tcolon = strstr( line, \":\" );\r\n\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\tstrcpy( content->m_Name, token );\r\n\r\n\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\tstrcpy( content->m_Creator, token );\r\n\r\n\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\tstrcpy( content->m_Size, token );\r\n\r\n\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\tcolon = strstr( token, \":\" );\r\n\t\t\t\t\tDbg_Assert( colon );\r\n\t\t\t\t\t*colon = '\\0';\r\n\t\t\t\t\tstrcpy( content->m_Checksum, token );\r\n\r\n\t\t\t\t\ttoken = colon + 1;\r\n\t\t\t\t\tstrcpy( content->m_Description, token );\r\n\r\n\t\t\t\t\t/*Dbg_Printf( \"////////////////////////\\n\" );\r\n\t\t\t\t\tDbg_Printf( \"Name: %s\\n\", content->m_Name );\r\n\t\t\t\t\tDbg_Printf( \"Creator: %s\\n\", content->m_Creator );\r\n\t\t\t\t\tDbg_Printf( \"Size: %s\\n\", content->m_Size );\r\n\t\t\t\t\tDbg_Printf( \"Checksum: %s\\n\", content->m_Checksum );\r\n\t\t\t\t\tDbg_Printf( \"Desc: %s\\n\", content->m_Description );\r\n\t\t\t\t\t*/\r\n\t\t\t\t} while(( line = strtok( NULL, \"\\r\\n\" )));\r\n\t\t\t}\r\n\r\n\t\t\tcontent_man.m_state = vCONTENT_STATE_IDLE;\r\n\t\t\tcontent_man.m_http_transfer_task->Remove();\r\n\r\n\t\t\t//ghttpCleanup();\r\n\t\t\tdelete [] content_man.m_buffer;\r\n\r\n\t\t\tcontent_man.DownloadDirectoryListing();\r\n\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t}\r\n\t\t\r\n\t\t//SignalSema( content_man.m_thread_semaphore_id );\r\n\t}\r\n}\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\t\tContentMan::FreeDirectoryListing( void )\r\n{\r\n\tDirectory* dir, *next;\r\n\tLst::Search< Directory > sh;\r\n\r\n\tfor( dir = sh.FirstItem( m_directories ); dir; dir = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tdelete dir;\r\n\t}\r\n\tghttpCleanup();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tContentMan::GetDirListing( char* path )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tThread::PerThreadStruct\tnet_thread_data;\r\n\r\n\tsprintf( m_download_path, path );\r\n\t//mlp_man->AddLogicTask( *m_http_transfer_task );\r\n\tm_percent_complete = 0;\r\n\tm_last_comm_time = Tmr::GetTime();\r\n\r\n\tm_transfer_complete_script = CRCD(0x89990f,\"LaunchDownloadCompleteDialog\");\r\n\tm_transfer_failed_script = CRCD(0x7335ab7f,\"LaunchTransferFailedDialog\");\r\n\tm_file_not_found_script = CRCD(0xcf040665,\"LaunchGeneralFileNotFoundDialog\");\r\n\tm_update_progress_script = CRCD(0x4b85ee64,\"update_transfer_progress\");\r\n\r\n\tDbg_Printf( \"**** Downloading path %s\\n\", m_download_path );\r\n\r\n\tnet_thread_data.m_pEntry = s_threaded_download_directory_list;\r\n\tnet_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY;\r\n\tnet_thread_data.m_pStackBase = gamenet_man->GetNetThreadStack();\r\n\tnet_thread_data.m_iStackSize = vNET_THREAD_STACK_SIZE;\r\n\tnet_thread_data.m_utid = 0x152;\r\n\tThread::CreateThread( &net_thread_data );\r\n\tgamenet_man->SetNetThreadId( net_thread_data.m_osId );\r\n\r\n\t//WaitSema( m_thread_semaphore_id );\r\n\tStartThread( gamenet_man->GetNetThreadId(), this );\r\n\t//SignalSema( m_thread_semaphore_id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tContentMan::GetSubDirListing( Directory* dir )\r\n{\r\n\tchar subdir_path[128];\r\n\r\n\tsprintf( subdir_path, \"http://www.thugonline.com/%s/%s/dir_list.txt\", m_vault_root, dir->m_Name );\r\n\tm_state = vCONTENT_STATE_GETTING_SUB_DIR_LIST;\r\n\tm_result = vCONTENT_RESULT_UNDETERMINED;\r\n\tGetDirListing( subdir_path );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tContentMan::FillDirectoryListing( char* dir_text )\r\n{\r\n\tchar* token;\r\n\tScript::CStruct* p_item_params;\r\n\tScript::CStruct* p_script_params;\r\n\r\n\t//Dbg_Printf( \"printing buffer\\n\" );\r\n\t//Dbg_Printf( \"Buffer: %s\\n\", dir_text );\r\n\r\n\ttoken = strtok( dir_text, \"\\t\" );\r\n\tif( token )\r\n\t{\r\n\t\tp_item_params = new Script::CStruct;\r\n\t\tp_item_params->AddString( \"text\", token );\r\n\t\ttoken = strtok( NULL, \"\\r\\n\" );\r\n\t\tDbg_Assert( token );\r\n\r\n\t\tp_item_params->AddChecksum( \"pad_choose_script\", Script::GenerateCRC(\"download_selected_file\"));\r\n\r\n\t\t// create the parameters that are passed to the choose script\r\n\t\tp_script_params= new Script::CStruct;\r\n\t\tp_script_params->AddString( \"file\", token );\t\r\n\t\tp_item_params->AddStructure(\"pad_choose_params\",p_script_params);\t\t\t\r\n\r\n\t\tScript::RunScript( \"make_text_sub_menu_item\", p_item_params );\r\n\t\tdelete p_item_params;\r\n\t\tdelete p_script_params;\r\n\r\n        while( token )\r\n\t\t{   \r\n\t\t\tp_item_params = new Script::CStruct;\r\n\t\t\t\r\n\t\t\ttoken = strtok( NULL, \"\\t\" );\r\n\t\t\tif( token == NULL )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tp_item_params->AddString( \"text\", token );\r\n\t\r\n\t\t\tp_item_params->AddChecksum( \"pad_choose_script\", Script::GenerateCRC(\"download_selected_file\"));\r\n\t\r\n\t\t\ttoken = strtok( NULL, \"\\r\\n\" );\r\n\t\t\tDbg_Assert( token );\r\n\r\n\t\t\t// create the parameters that are passed to the choose script\r\n\t\t\tp_script_params= new Script::CStruct;\r\n\t\t\tp_script_params->AddString( \"file\", token );\t\r\n\t\t\tp_item_params->AddStructure(\"pad_choose_params\",p_script_params);\t\t\t\r\n\t\r\n\t\t\tScript::RunScript( \"make_text_sub_menu_item\", p_item_params );\r\n\t\t\tdelete p_item_params;\r\n\t\t\tdelete p_script_params;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nContentMan::ContentMan( void )\r\n{\r\n\tstruct SemaParam params;\r\n\r\n\tm_state = vCONTENT_STATE_IDLE;\r\n\tm_percent_complete = 0;\r\n\tm_last_comm_time = 0;\r\n\tm_http_transfer_task = new Tsk::Task< ContentMan > ( s_http_transfer_code, *this );\r\n\r\n\tparams.initCount = 1;\r\n\tparams.maxCount = 10;\r\n\r\n\tm_thread_semaphore_id = CreateSema( &params );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nContentMan::~ContentMan( void )\r\n{\r\n\tDeleteSema( m_thread_semaphore_id );\r\n\tdelete m_http_transfer_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tContentMan::s_threaded_download_directory_list( ContentMan* content_man )\r\n{\r\n\tWaitSema( content_man->m_thread_semaphore_id );\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\t// Register this thread with the sockets API\r\n\tsockAPIregthr();\r\n\r\n\tcontent_man->m_buffer = new char[100000];\r\n\tmemset( content_man->m_buffer, 0, 100000 );\r\n\r\n\tcontent_man->m_file_request = ghttpGetEx( \tcontent_man->m_download_path,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNULL,\r\n\t\t\t\t\t\t\t\t\t\t\t\tcontent_man->m_buffer,\r\n\t\t\t\t\t\t\t\t\t\t\t\t100000,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNULL,\r\n\t\t\t\t\t\t\t\t\t\t\t\tGHTTPFalse,\r\n\t\t\t\t\t\t\t\t\t\t\t\tGHTTPFalse,\r\n\t\t\t\t\t\t\t\t\t\t\t\ts_progress_callback,\r\n\t\t\t\t\t\t\t\t\t\t\t\ts_ul_completed_callback,\r\n\t\t\t\t\t\t\t\t\t\t\t\tcontent_man );\r\n    \r\n\t//delete buffer;\r\n\r\n\t// Deregister this thread with the sockets API\r\n\tsockAPIderegthr();\r\n\r\n\t//printf( \"******** EXITING DOWNLOAD DIRECTORY THREAD\\n\" );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tSignalSema( content_man->m_thread_semaphore_id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tContentMan::DownloadDirectoryListing( void )\r\n{\r\n\tchar path[128];\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\r\n\tm_state = vCONTENT_STATE_GETTING_DIR_LIST;\r\n\tsprintf( path, \"http://www.thugonline.com/%s/dir_list.txt\", m_vault_root );\r\n\tGetDirListing( path );\r\n\tm_result = vCONTENT_RESULT_UNDETERMINED;;\r\n\tmlp_man->AddLogicTask( *m_http_transfer_task );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tContentMan::DownloadFace( char* filename )\r\n{\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tThread::PerThreadStruct\tnet_thread_data;\r\n\tchar path[256];\r\n    \r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\tm_state = vCONTENT_STATE_DOWNLOADING_FACE;\r\n\tm_result = vCONTENT_RESULT_UNDETERMINED;\r\n\tmlp_man->AddLogicTask( *m_http_transfer_task );\r\n\tm_percent_complete = 0;\r\n\tm_last_comm_time = Tmr::GetTime();\r\n\r\n\tm_transfer_complete_script = CRCD(0x1d53d27f,\"LaunchFaceDownloadCompleteDialog\");\r\n\tm_transfer_failed_script = CRCD(0x7335ab7f,\"LaunchTransferFailedDialog\");\r\n\tm_file_not_found_script = CRCD(0x609f7535,\"LaunchFileNotFoundDialog\");\r\n\tm_update_progress_script = CRCD(0x4b85ee64,\"update_transfer_progress\");\r\n\r\n\tnet_thread_data.m_pEntry = s_threaded_download_face;\r\n\tnet_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY;\r\n\tnet_thread_data.m_pStackBase = gamenet_man->GetNetThreadStack();\r\n\tnet_thread_data.m_iStackSize = vNET_THREAD_STACK_SIZE;\r\n\tnet_thread_data.m_utid = 0x152;\r\n\tThread::CreateThread( &net_thread_data );\r\n\tgamenet_man->SetNetThreadId( net_thread_data.m_osId );\r\n\t\r\n\tDbg_Printf( \"In DownloadFace. Path: %s\\n\", filename );\r\n\tWaitSema( m_thread_semaphore_id );\r\n\t\r\n\tsprintf( path, \"http://www.thugonline.com/faces/%s\", filename );\r\n\tDbg_Printf( \"Downloading %s\\n\", path );\r\n\tStartThread( gamenet_man->GetNetThreadId(), (char*) path );\r\n\tSignalSema( m_thread_semaphore_id );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tContentMan::ScriptDownloadFace(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tContentMan* content_man;\r\n\tBuddyMan* buddy_man;\r\n\tchar filename[128];\r\n\tconst char* key;\r\n\r\n\tpParams->GetString( \"string\", &key, Script::ASSERT );\r\n\tsprintf( filename, \"%s.img.ps2\", key );\r\n\tDbg_Printf( \"Downloading %s...\\n\", filename );\r\n\r\n\tcontent_man = gamenet_man->mpContentMan;\r\n\tbuddy_man = gamenet_man->mpBuddyMan;\r\n\tbuddy_man->GetProfile();\r\n\tcontent_man->DownloadFace( filename );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tContentMan::ScriptDownloadDirectoryList(Script::CScriptStructure *p_item_params, Script::CScript *pScript)\r\n{\r\n    GameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tContentMan* content_man;\r\n\tBuddyMan* buddy_man;\r\n\r\n    content_man = gamenet_man->mpContentMan;\r\n\tbuddy_man = gamenet_man->mpBuddyMan;\r\n\tp_item_params->GetChecksum( NONAME, &content_man->m_vault_type , true );\r\n\tswitch( content_man->m_vault_type )\r\n\t{\r\n\t\tcase 0x5be5569f:\t// parks\r\n\t\t\tsprintf( content_man->m_vault_root, \"levels\" );\r\n\t\t\tbreak;\r\n\t\tcase 0x7364ea1:\t\t// skaters\r\n\t\t\tsprintf( content_man->m_vault_root, \"skaters\" );\r\n\t\t\tbreak;\r\n\t\tcase 0x38dbe1d0:\t// goals\r\n\t\t\tsprintf( content_man->m_vault_root, \"goals\" );\r\n\t\t\tbreak;\r\n\t\tcase 0x1e26fd3e:\t// tricks\r\n\t\t\tsprintf( content_man->m_vault_root, \"tricks\" );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t}\r\n\r\n\tif( buddy_man->GetProfile() == 18549782 )\t// Gamespy profile of our level-verifying account\r\n\t{\r\n\t\tDirectory* dir;\r\n\t\tchar path[128];\r\n\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\t\tdir = new Directory;\r\n\t\tdir->m_Uploads = true;\r\n\t\tcontent_man->m_directories.AddToHead( dir );\r\n\t\tstrcpy( dir->m_Name, \"Uploads\" );\r\n\t\tcontent_man->m_cur_dir = content_man->m_next_dir_sh.FirstItem( content_man->m_directories );\r\n\r\n\t\tcontent_man->m_state = vCONTENT_STATE_GETTING_UPLOADED_LEVELS;\r\n\t\tcontent_man->m_result = vCONTENT_RESULT_UNDETERMINED;\r\n\t\tsprintf( path, \"http://www.thugonline.com/%s/uploads.txt\", content_man->m_vault_root );\r\n\t\tcontent_man->GetDirListing( path );\r\n\t\tmlp_man->AddLogicTask( *content_man->m_http_transfer_task );\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcontent_man->DownloadDirectoryListing();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tContentMan::ScriptFreeDirectoryListing(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tContentMan* content_man;\r\n\r\n\tcontent_man = gamenet_man->mpContentMan;\r\n\tcontent_man->FreeDirectoryListing();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tContentMan::s_threaded_download_file( const char* path )\r\n{\r\n\tint max_size;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tContentMan* content_man;\r\n\r\n\tcontent_man = gamenet_man->mpContentMan;\r\n\tWaitSema( content_man->m_thread_semaphore_id );\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\tmax_size = content_man->m_buffer_size;\r\n\r\n\tcontent_man->m_buffer = new char[max_size];\r\n\r\n\t// Register this thread with the sockets API\r\n\tsockAPIregthr();\r\n\r\n\t//Dbg_Printf( \"downloading %s, size: %d dl complete: %p\\n\", path, max_size, content_man->m_dl_complete );\r\n\tgamenet_man->mpContentMan->m_file_request = ghttpGetEx( path,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcontent_man->m_buffer,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmax_size,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGHTTPFalse,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGHTTPFalse,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ts_progress_callback,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcontent_man->m_dl_complete,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcontent_man );\r\n    \r\n\t// Deregister this thread with the sockets API\r\n\tsockAPIderegthr();\r\n    \r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\tSignalSema( gamenet_man->mpContentMan->m_thread_semaphore_id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tContentMan::s_threaded_download_face( const char* path )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tWaitSema( gamenet_man->mpContentMan->m_thread_semaphore_id );\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\tgamenet_man->mpContentMan->m_buffer = new char[vMAX_FACE_SIZE];\r\n\r\n\t// Register this thread with the sockets API\r\n\tsockAPIregthr();\r\n\r\n\tgamenet_man->mpContentMan->m_file_request = ghttpGetEx( path,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgamenet_man->mpContentMan->m_buffer,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvMAX_FACE_SIZE,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGHTTPFalse,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGHTTPFalse,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ts_progress_callback,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ts_face_dl_completed_callback,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgamenet_man->mpContentMan );\r\n    \r\n\t// Deregister this thread with the sockets API\r\n\tsockAPIderegthr();\r\n    \r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tSignalSema( gamenet_man->mpContentMan->m_thread_semaphore_id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tContentMan::SetPercentComplete( int percent_complete )\r\n{\r\n\tm_percent_complete = percent_complete;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tContentMan::SetResult( int result )\r\n{\r\n\tm_result = result;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tContentMan::SetError( int error )\r\n{\r\n\tm_error = error;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tContentMan::DownloadFile( DownloadContext* context )\r\n{\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tContentMan* content_man;\r\n\tThread::PerThreadStruct\tnet_thread_data;\r\n    \r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\tDbg_Printf( \"Downloading %s\\n\", context->m_path );\r\n\t\r\n\tcontent_man = gamenet_man->mpContentMan;\r\n\tcontent_man->m_state = vCONTENT_STATE_DOWNLOADING;\r\n\tcontent_man->m_result = vCONTENT_RESULT_UNDETERMINED;\r\n\tmlp_man->AddLogicTask( *content_man->m_http_transfer_task );\r\n\tcontent_man->m_percent_complete = 0;\r\n\tcontent_man->m_last_comm_time = Tmr::GetTime();\r\n\t\r\n\tcontent_man->m_buffer_size = context->m_max_size;\r\n\tcontent_man->m_transfer_failed_script = context->m_transfer_failed_script;\r\n\tcontent_man->m_transfer_complete_script = context->m_transfer_complete_script;\r\n\tcontent_man->m_update_progress_script = context->m_update_progress_script;\r\n\tcontent_man->m_file_not_found_script = context->m_file_not_found_script;\r\n\tcontent_man->m_dl_complete = context->m_dl_complete;\r\n\r\n\tnet_thread_data.m_pEntry = s_threaded_download_file;\r\n\tnet_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY;\r\n\tnet_thread_data.m_pStackBase = gamenet_man->GetNetThreadStack();\r\n\tnet_thread_data.m_iStackSize = vNET_THREAD_STACK_SIZE;\r\n\tnet_thread_data.m_utid = 0x152;\r\n\tThread::CreateThread( &net_thread_data );\r\n\tgamenet_man->SetNetThreadId( net_thread_data.m_osId );\r\n\t\r\n\tWaitSema( content_man->m_thread_semaphore_id );\r\n\tStartThread( gamenet_man->GetNetThreadId(), context->m_path );\r\n\tSignalSema( content_man->m_thread_semaphore_id );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tContentMan::ScriptDownloadFile(Script::CScriptStructure *p_item_params, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tContentMan* content_man;\r\n\tconst char* path;\r\n\tDownloadContext context;\r\n\t\r\n\tp_item_params->GetString( \"file\", &path );\r\n\r\n\tcontent_man = gamenet_man->mpContentMan;\r\n\t\r\n\tcontext.m_transfer_complete_script = CRCD(0x89990f,\"LaunchDownloadCompleteDialog\");\r\n\tcontext.m_transfer_failed_script = CRCD(0x7335ab7f,\"LaunchTransferFailedDialog\");\r\n\tcontext.m_file_not_found_script = CRCD(0xcf040665,\"LaunchGeneralFileNotFoundDialog\");\r\n\tcontext.m_update_progress_script = CRCD(0x4b85ee64,\"update_transfer_progress\");\r\n\tcontext.m_max_size = vMAX_FILE_SIZE;\r\n\tsprintf( context.m_path, path );\r\n\tcontext.m_dl_complete = s_dl_completed_callback;\r\n\tcontent_man->DownloadFile( &context );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************\r\n\r\nstatic char* s_fix_name( char* filename )\r\n{\r\n\tchar* ch = filename;\r\n\t\r\n\twhile( *ch )\r\n\t{\r\n\t\tif(( *ch >= '0' ) && ( *ch <= '9' ))\r\n\t\t{\r\n\t\t\tch++;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif(( *ch >= 'A' ) && ( *ch <= 'Z' ))\r\n\t\t{\r\n\t\t\tch++;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif(( *ch >= 'a' ) && ( *ch <= 'z' ))\r\n\t\t{\r\n\t\t\tch++;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif(( *ch == '-' ) || ( *ch =='_' ))\r\n\t\t{\r\n\t\t\tch++;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t*ch = '_';\r\n\t\tch++;\r\n\t}\r\n\r\n\treturn filename;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tContentMan::s_threaded_upload_file( ContentMan* content_man )\r\n{\r\n\tGHTTPPost post;\r\n\tchar *file_buffer; \r\n\tchar filename[64], desc[1024], str[64];\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tPrefs::Preferences* pPreferences;\r\n\tScript::CStruct* pStructure;\r\n\tconst char* network_id;\r\n\tint filesize;\r\n\tuint32 checksum;\r\n\r\n\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"network_id\") );\r\n\tpStructure->GetText( \"ui_string\", &network_id, true );\r\n\r\n\tWaitSema( content_man->m_thread_semaphore_id );\r\n\tsockAPIregthr();\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\tpost = ghttpNewPost();\r\n\tswitch( content_man->m_vault_type )\r\n\t{\r\n\t\tcase 0x5be5569f:\t// parks\r\n\t\t{\r\n\t\t\tfilesize = Script::CalculateBufferSize( content_man->m_upload_struct );\r\n\t\t\tfile_buffer = new char[filesize];\r\n\t\t\tScript::WriteToBuffer( content_man->m_upload_struct, (uint8*) file_buffer, filesize );\r\n\t\t\tchecksum = Crc::GenerateCRC( file_buffer, filesize );\r\n\t\t\r\n\t\t\tstrcpy( filename, content_man->m_upload_filename );\r\n\t\t\tghttpPostAddString( post, \"player\", network_id );\r\n\t\t\tsprintf( str, \"%d\", content_man->m_Width );\r\n\t\t\tghttpPostAddString( post, \"width\", str );\r\n\t\t\tsprintf( str, \"%d\", content_man->m_Height );\r\n\t\t\tghttpPostAddString( post, \"height\", str );\r\n\t\t\tsprintf( str, \"%d\", checksum );\r\n\t\t\tghttpPostAddString( post, \"checksum\", str );\r\n\t\t\t\r\n\t\t\tsprintf( str, \"%d\", content_man->m_NumPieces );\r\n\t\t\tghttpPostAddString( post, \"num_pieces\", str );\r\n\t\t\tsprintf( str, \"%d\", content_man->m_NumGaps );\r\n\t\t\tghttpPostAddString( post, \"num_gaps\", str );\r\n\t\t\tsprintf( str, \"%d\", content_man->m_NumGoals );\r\n\t\t\tghttpPostAddString( post, \"num_goals\", str );\r\n\t\t\tsprintf( str, \"%d\", content_man->m_Theme );\r\n\t\t\tghttpPostAddString( post, \"theme\", str );\r\n\t\t\tsprintf( str, \"0x%x\", content_man->m_TODScript );\r\n\t\t\tghttpPostAddString( post, \"tod_script\", str );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0x7364ea1:\t\t// skaters\r\n\t\t{\r\n\t\t\tghttpPostAddString( post, \"filetype\", \"cas\" );\r\n\t\t\tsprintf( str, \"%d\", content_man->m_IsMale );\r\n\t\t\tghttpPostAddString( post, \"is_male\", str );\r\n\t\t\t\r\n\t\t\tfilesize = Script::CalculateBufferSize( content_man->m_upload_struct );\r\n\t\t\tfile_buffer = new char[filesize];\r\n\t\t\tScript::WriteToBuffer( content_man->m_upload_struct, (uint8*) file_buffer, filesize );\r\n\t\t\tchecksum = Crc::GenerateCRC( file_buffer, filesize );\r\n\t\t\tstrcpy( filename, content_man->m_upload_filename );\r\n\t\t\tghttpPostAddString( post, \"player\", network_id );\r\n\t\t\tsprintf( str, \"%d\", checksum );\r\n\t\t\tghttpPostAddString( post, \"checksum\", str );\r\n\t\t\t\t\r\n\t\t\tDbg_Printf( \"Uploading file: %s\\n\", filename );\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0x38dbe1d0:\t// goals\r\n\t\t{\r\n\t\t\tghttpPostAddString( post, \"filetype\", \"cag\" );\r\n\t\t\tsprintf( str, \"%d\", content_man->m_NumGoals );\r\n\t\t\tghttpPostAddString( post, \"num_goals\", str );\r\n\r\n\t\t\tfilesize = Script::CalculateBufferSize( content_man->m_upload_struct );\r\n\t\t\tfile_buffer = new char[filesize];\r\n\t\t\tScript::WriteToBuffer( content_man->m_upload_struct, (uint8*) file_buffer, filesize );\r\n\t\t\tchecksum = Crc::GenerateCRC( file_buffer, filesize );\r\n\t\t\tstrcpy( filename, content_man->m_upload_filename );\r\n\t\t\tghttpPostAddString( post, \"player\", network_id );\r\n\t\t\tsprintf( str, \"%d\", checksum );\r\n\t\t\tghttpPostAddString( post, \"checksum\", str );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0x1e26fd3e:\t// tricks\r\n\t\t{\r\n\t\t\tghttpPostAddString( post, \"filetype\", \"cat\" );\r\n\t\t\tsprintf( str, \"%d\", content_man->m_Score );\r\n\t\t\tghttpPostAddString( post, \"score\", str );\r\n\r\n\t\t\tfilesize = Script::CalculateBufferSize( content_man->m_upload_struct );\r\n\t\t\tfile_buffer = new char[filesize];\r\n\t\t\tScript::WriteToBuffer( content_man->m_upload_struct, (uint8*) file_buffer, filesize );\r\n\t\t\tchecksum = Crc::GenerateCRC( file_buffer, filesize );\r\n\t\t\tstrcpy( filename, content_man->m_upload_filename );\r\n\t\t\tghttpPostAddString( post, \"player\", network_id );\r\n\t\t\tsprintf( str, \"%d\", checksum );\r\n\t\t\tghttpPostAddString( post, \"checksum\", str );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tfile_buffer = NULL;\r\n\t\t\tfilesize = 0;\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t\tbreak;\r\n\t}\r\n\t\t\r\n\tcontent_man->m_buffer = file_buffer;\r\n\tcontent_man->m_buffer_size = filesize;\r\n\tghttpPostAddFileFromMemory( post, \"filename\", file_buffer, filesize, filename, NULL );\r\n\r\n\tsprintf( desc, \"%s\", content_man->m_upload_description );\r\n\tghttpPostAddString( post, \"description\", desc );\r\n\r\n\tghttpPostAddString( post, \"uniqueid\", GOAGetUniqueID() );\r\n\tswitch( content_man->m_vault_type )\r\n\t{\r\n\t\tcase 0x5be5569f:\t// parks\r\n\t\t\tghttpPostAddString( post, \"filetype\", \"cap\" );\r\n\t\t\tbreak;\r\n\t\tcase 0x7364ea1:\t\t// skaters\r\n\t\t\tghttpPostAddString( post, \"filetype\", \"cas\" );\r\n\t\t\tbreak;\r\n\t\tcase 0x38dbe1d0:\t// goals\r\n\t\t\tghttpPostAddString( post, \"filetype\", \"cag\" );\r\n\t\t\tbreak;\r\n\t\tcase 0x1e26fd3e:\t// tricks\r\n\t\t\tghttpPostAddString( post, \"filetype\", \"cat\" );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\t// debugger log\r\n\tghttpPostAddString( post, \"dblog\", \"1\" );\r\n\r\n\tcontent_man->m_file_request = ghttpPostEx( \"http://www.thugonline.com/cgi-bin/upload2.pl\", NULL, post, GHTTPFalse, GHTTPFalse, s_progress_callback, s_ul_completed_callback, content_man );\t\r\n\t\r\n    \r\n    // Deregister this thread with the sockets API\r\n\tsockAPIderegthr();\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tSignalSema( content_man->m_thread_semaphore_id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tContentMan::ScriptUploadFile(Script::CScriptStructure *p_item_params, Script::CScript *pScript)\r\n{\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tContentMan* content_man;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tThread::PerThreadStruct\tnet_thread_data;\r\n\tconst char* desc, *filename;\r\n\r\n\tcontent_man = gamenet_man->mpContentMan;\r\n\tcontent_man->m_state = vCONTENT_STATE_UPLOADING;\r\n\tcontent_man->m_result = vCONTENT_RESULT_UNDETERMINED;\r\n\tmlp_man->AddLogicTask( *content_man->m_http_transfer_task );\r\n\tcontent_man->m_percent_complete = 0;\r\n\tcontent_man->m_last_comm_time = Tmr::GetTime();\r\n\tcontent_man->m_transfer_failed_script = CRCD(0x7335ab7f,\"LaunchTransferFailedDialog\");\r\n\r\n\t//Script::PrintContents( p_item_params );\r\n\tp_item_params->GetChecksum( \"type\", &content_man->m_vault_type , true );\r\n\tp_item_params->GetStructure( \"data\", &content_man->m_upload_struct );\r\n\tp_item_params->GetString( \"description\", &desc, Script::ASSERT );\r\n\tp_item_params->GetString( \"filename\", &filename, Script::ASSERT );\r\n\tstrcpy( content_man->m_upload_filename, filename );\r\n\tstrcpy( content_man->m_upload_description, desc );\r\n\t\r\n\tp_item_params->GetInteger( \"score\", &content_man->m_Score, false );\r\n\tp_item_params->GetInteger( \"width\", &content_man->m_Width, false );\r\n\tp_item_params->GetInteger( \"length\", &content_man->m_Height, false );\r\n\tp_item_params->GetInteger( \"num_pieces\", &content_man->m_NumPieces, false );\r\n\tp_item_params->GetInteger( \"num_gaps\", &content_man->m_NumGaps, false );\r\n\tp_item_params->GetInteger( \"num_goals\", &content_man->m_NumGoals, false );\r\n\tp_item_params->GetInteger( \"theme\", &content_man->m_Theme, false );\r\n\tp_item_params->GetChecksum( \"tod_script\", &content_man->m_TODScript, false );\r\n\tp_item_params->GetInteger( \"is_male\", &content_man->m_IsMale, false );\r\n    \r\n\tnet_thread_data.m_pEntry = s_threaded_upload_file;\r\n\tnet_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY;\r\n\tnet_thread_data.m_pStackBase = gamenet_man->GetNetThreadStack();\r\n\tnet_thread_data.m_iStackSize = vNET_THREAD_STACK_SIZE;\r\n\tnet_thread_data.m_utid = 0x152;\r\n\tThread::CreateThread( &net_thread_data );\r\n\tgamenet_man->SetNetThreadId( net_thread_data.m_osId );\r\n\r\n\tWaitSema( content_man->m_thread_semaphore_id );\r\n\tStartThread( gamenet_man->GetNetThreadId(), content_man );\r\n\tSignalSema( content_man->m_thread_semaphore_id );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tContentMan::ScriptFillVaultMenu(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tContentMan* content_man;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tLst::Search< Content > sh;\r\n\tContent* content;\r\n\r\n\tcontent_man = gamenet_man->mpContentMan;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tfor( content = sh.FirstItem( content_man->m_cur_dir->m_content_list ); content; content = sh.NextItem())\r\n\t{\r\n\t\tScript::CStruct* pParams, *pChooseParams;\r\n\r\n\t\tpParams = new Script::CStruct;\r\n\r\n\t\tpParams->AddString( \"name\", content->m_Name );\r\n\t\tpParams->AddString( \"creator\", content->m_Creator );\r\n\t\tpParams->AddString( \"size\", content->m_Size );\r\n\t\tpParams->AddInteger( \"score\", content->m_Score );\r\n\t\tpParams->AddInteger( \"num_pieces\", content->m_NumPieces );\r\n\t\tpParams->AddInteger( \"num_gaps\", content->m_NumGaps );\r\n\t\tpParams->AddInteger( \"width\", content->m_Width );\r\n\t\tpParams->AddInteger( \"height\", content->m_Height );\r\n\t\tpParams->AddInteger( \"num_goals\", content->m_NumGoals );\r\n\t\tpParams->AddInteger( \"theme\", content->m_Theme );\r\n\t\tpParams->AddChecksum( \"tod_script\", content->m_TODScript );\r\n\t\tpParams->AddInteger( \"is_male\", content->m_IsMale );\r\n\t\tpParams->AddString( \"description\", content->m_Description );\r\n\r\n\t\tpChooseParams = new Script::CStruct;\r\n\r\n\t\tpChooseParams->AddString( \"file\", content->m_Path );\r\n\t\t\r\n\t\tpParams->AddStructure( \"pad_choose_params\", pChooseParams );\r\n\t\tswitch( content_man->m_vault_type )\r\n\t\t{\r\n\t\t\tcase 0x5be5569f:\t// parks\r\n\t\t\t\tScript::RunScript( \"net_vault_menu_add_park\", pParams );\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x7364ea1:\t\t// skaters\r\n\t\t\t\tScript::RunScript( \"net_vault_menu_add_skater\", pParams );\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x38dbe1d0:\t// goals\r\n\t\t\t\tScript::RunScript( \"net_vault_menu_add_goal\", pParams );\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x1e26fd3e:\t// tricks\r\n\t\t\t\tScript::RunScript( \"net_vault_menu_add_trick\", pParams );\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\r\n\t\tdelete pParams;\r\n\t\tdelete pChooseParams;\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tContentMan::ScriptNextVaultCategory(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tContentMan* content_man;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tScript::CStruct* passback_params;\r\n\r\n\tcontent_man = gamenet_man->mpContentMan;\r\n\tcontent_man->m_cur_dir = content_man->m_next_dir_sh.NextItem();\r\n\tif( content_man->m_cur_dir == NULL )\r\n\t{\r\n\t\tcontent_man->m_cur_dir = content_man->m_next_dir_sh.FirstItem( content_man->m_directories );\r\n\t}\r\n\r\n\tpassback_params = pScript->GetParams();\r\n\tpassback_params->AddString( \"category\", content_man->m_cur_dir->m_Name );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tContentMan::ScriptPrevVaultCategory(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tContentMan* content_man;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tScript::CStruct* passback_params;\r\n\r\n\tcontent_man = gamenet_man->mpContentMan;\r\n\tcontent_man->m_cur_dir = content_man->m_next_dir_sh.PrevItem();\r\n\tif( content_man->m_cur_dir == NULL )\r\n\t{\r\n\t\tcontent_man->m_cur_dir = content_man->m_next_dir_sh.LastItem( content_man->m_directories );\r\n\t}\r\n\r\n\tpassback_params = pScript->GetParams();\r\n\tpassback_params->AddString( \"category\", content_man->m_cur_dir->m_Name );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nDirectory::Directory( void )\r\n: Lst::Node< Directory > ( this )\r\n{\r\n\tm_Uploads = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nDirectory::~Directory( void )\r\n{\r\n\tContent* content, *next;\r\n\tLst::Search< Content > sh;\r\n\r\n\tfor( content = sh.FirstItem( m_content_list ); content; content = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tdelete content;\r\n\t}\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nContent::Content( void )\r\n: Lst::Node< Content > ( this )\r\n{\r\n\tm_Path[0] = '\\0';\r\n\tm_Name[0] = '\\0';\r\n\tm_Creator[0] = '\\0';\r\n\tm_Size[0] = '\\0';\r\n\tm_Checksum[0] = '\\0';\r\n\tm_Description[0] = '\\0';\r\n\tm_Score = 0;\r\n\tm_NumPieces = 0;\r\n\tm_NumGaps = 0;\r\n\tm_NumGoals = 0;\r\n\tm_Theme = 0;\r\n\tm_TODScript = 0;\r\n\tm_IsMale = 0;\r\n\tm_Width = 0;\r\n\tm_Height = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/p_content.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_content.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/28/02\t- spg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__P_CONTENT_H\r\n#define\t__P_CONTENT_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\nnamespace GameNet\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nenum\r\n{\r\n\tvCONTENT_STATE_IDLE,\r\n\tvCONTENT_STATE_GETTING_DIR_LIST,\r\n\tvCONTENT_STATE_GETTING_SUB_DIR_LIST,\r\n\tvCONTENT_STATE_DOWNLOADING,\r\n\tvCONTENT_STATE_UPLOADING,\r\n\tvCONTENT_STATE_GETTING_UPLOADED_LEVELS,\r\n\tvCONTENT_STATE_DOWNLOADING_FACE\r\n};\r\n\r\nenum\r\n{\r\n\tvCONTENT_RESULT_UNDETERMINED,\r\n\tvCONTENT_RESULT_SUCCESS,\r\n\tvCONTENT_RESULT_FAILURE\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Content : public Lst::Node< Content >\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvMAX_FILE_NAME_LEN = 23,\r\n\t\tvMAX_PATH_NAME_LEN = 127,\r\n\t\tvMAX_CREATOR_NAME_LEN = 15,\r\n\t\tvMAX_DIMENSION_LEN = 15,\r\n\t\tvMAX_CHECKSUM_LEN = 32,\r\n\t\tvMAX_DESC_LEN = 255,\r\n\t\tvMAX_NUM_LEN = 15,\r\n\t\tvMAX_THEME_NAME_LEN = 23,\r\n\t\tvMAX_SCRIPT_NAME_LEN = 23,\r\n\t\tvMAX_SEX_NAME_LEN = 15,\r\n\t};\r\n\r\n\tContent( void );\r\n\r\n\tchar\tm_Path[vMAX_PATH_NAME_LEN + 1];\r\n\tchar\tm_Name[vMAX_FILE_NAME_LEN + 1];\r\n\tchar\tm_Creator[vMAX_CREATOR_NAME_LEN + 1];\r\n\tchar\tm_Size[vMAX_DIMENSION_LEN + 1];\r\n\tchar\tm_Checksum[vMAX_CHECKSUM_LEN + 1];\r\n\tchar\tm_Description[vMAX_DESC_LEN + 1];\r\n\tint\t\tm_Score;\r\n\tint\t\tm_Width;\r\n\tint\t\tm_Height;\r\n\tint\t\tm_NumPieces;\r\n\tint\t\tm_NumGaps;\r\n\tint\t\tm_NumGoals;\r\n\tint\t\tm_Theme;\r\n\tuint32\tm_TODScript;\r\n\tint\t\tm_IsMale;\r\n};\r\n\r\nclass Directory : public Lst::Node< Directory >\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvMAX_DIR_NAME_LEN = 23\r\n\t};\r\n\r\n\tDirectory( void );\r\n\t~Directory( void );\r\n\r\n\tbool\tm_Uploads;\r\n\tchar\tm_Name[vMAX_DIR_NAME_LEN + 1];\r\n\tLst::Head< Content > \tm_content_list;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass DownloadContext\r\n{\r\npublic:\r\n\tint\t\t\t\t\t\tm_max_size;\r\n\tchar\t\t\t\t\tm_path[256];\r\n\tghttpCompletedCallback\tm_dl_complete;\r\n\tuint32\t\t\t\t\tm_transfer_failed_script;\r\n\tuint32\t\t\t\t\tm_transfer_complete_script;\r\n\tuint32\t\t\t\t\tm_update_progress_script;\r\n\tuint32\t\t\t\t\tm_file_not_found_script;\r\n\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass ContentMan\r\n{\r\npublic:\r\n\t\t\t\t\tContentMan( void );\r\n\t\t\t\t\t~ContentMan( void );\r\n\r\n\tvoid\t\t\tDownloadDirectoryListing( void );\r\n\tvoid\t\t\tFillDirectoryListing( char* dir_text );\r\n\tvoid\t\t\tFreeDirectoryListing( void );\r\n\tvoid\t\t\tGetDirListing( char* path );\r\n\tvoid\t\t\tGetSubDirListing( Directory* dir );\r\n\tvoid\t\t\tDownloadFace( char* filename );\r\n\tvoid\t\t\tDownloadFile( DownloadContext* context );\r\n\r\n\tvoid\t\t\tSetPercentComplete( int percent_complete );\r\n\tvoid\t\t\tSetResult( int result );\r\n\tvoid\t\t\tSetError( int error );\r\n\r\n\tstatic\tbool\tScriptDownloadFace(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\n    static\tbool\tScriptDownloadDirectoryList(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\tScriptFreeDirectoryListing(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\tScriptDownloadFile(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\tScriptUploadFile(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\n\tstatic\tbool\tScriptFillVaultMenu(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\tScriptNextVaultCategory(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\tScriptPrevVaultCategory(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nprivate:\r\n\r\n\tTsk::Task< ContentMan >*\t\t\t\tm_http_transfer_task;\r\n\tstatic\tTsk::Task< ContentMan >::Code   s_http_transfer_code;\r\n\r\n\tstatic\tvoid\ts_threaded_upload_file( ContentMan* content_man );\r\n\tstatic\tvoid\ts_threaded_download_file( const char* path );\r\n\tstatic\tvoid\ts_threaded_download_face( const char* path );\r\n\tstatic\tvoid\ts_threaded_download_directory_list( ContentMan* content_man );\r\n\r\n\tstatic\tvoid \ts_progress_callback(\tGHTTPRequest request,       // The request.\r\n\t\t\t\t\t\t\t\t\t\t\tGHTTPState state,           // The current state of the request.\r\n\t\t\t\t\t\t\t\t\t\t\tconst char* buffer,        \t// The file's bytes so far, NULL if state<GHTTPReceivingFile.\r\n\t\t\t\t\t\t\t\t\t\t\tint buffer_len,             // The number of bytes in the buffer, 0 if state<GHTTPReceivingFile.\r\n\t\t\t\t\t\t\t\t\t\t\tint bytes_received,         // The total number of bytes receivied, 0 if state<GHTTPReceivingFile.\r\n\t\t\t\t\t\t\t\t\t\t\tint total_size,             // The total size of the file, -1 if unknown.\r\n\t\t\t\t\t\t\t\t\t\t\tvoid * param                // User-data.\r\n\t\t\t\t\t\t\t\t\t\t);\r\n\tstatic\tGHTTPBool s_ul_completed_callback(\tGHTTPRequest request,       // The request.\r\n\t\t\t\t\t\t\t\t\t\t\tGHTTPResult result,         // The result (success or an error).\r\n\t\t\t\t\t\t\t\t\t\t\tchar* buffer,              // The file's bytes (only valid if ghttpGetFile[Ex] was used).\r\n\t\t\t\t\t\t\t\t\t\t\tint buffer_len,              // The file's length.\r\n\t\t\t\t\t\t\t\t\t\t\tvoid * param                // User-data.\r\n\t\t\t\t\t\t\t\t\t\t\t);\r\n\tstatic\tGHTTPBool s_dl_completed_callback(\tGHTTPRequest request,       // The request.\r\n\t\t\t\t\t\t\t\t\t\t\tGHTTPResult result,         // The result (success or an error).\r\n\t\t\t\t\t\t\t\t\t\t\tchar* buffer,              // The file's bytes (only valid if ghttpGetFile[Ex] was used).\r\n\t\t\t\t\t\t\t\t\t\t\tint buffer_len,              // The file's length.\r\n\t\t\t\t\t\t\t\t\t\t\tvoid * param                // User-data.\r\n\t\t\t\t\t\t\t\t\t\t\t);\r\n\tstatic\tGHTTPBool s_face_dl_completed_callback(\tGHTTPRequest request,       // The request.\r\n\t\t\t\t\t\t\t\t\t\t\tGHTTPResult result,         // The result (success or an error).\r\n\t\t\t\t\t\t\t\t\t\t\tchar* buffer,              // The file's bytes (only valid if ghttpGetFile[Ex] was used).\r\n\t\t\t\t\t\t\t\t\t\t\tint buffer_len,              // The file's length.\r\n\t\t\t\t\t\t\t\t\t\t\tvoid * param                // User-data.\r\n\t\t\t\t\t\t\t\t\t\t\t);\r\n\tint\t\t\tm_state;\r\n\tint\t\t\tm_percent_complete;\r\n\tint\t\t\tm_result;\r\n\tint\t\t\tm_error;\r\n\tint\t\t\tm_buffer_size;\r\n\tchar* \t\tm_buffer;\r\n\tTmr::Time\tm_last_comm_time;\r\n\tchar\t\tm_download_path[128];\r\n\tchar\t\tm_upload_filename[128];\r\n\tchar\t\tm_upload_description[512];\r\n\tint\t\t\tm_thread_semaphore_id;\r\n\tGHTTPRequest m_file_request;\r\n\tScript::CStruct* m_upload_struct;\r\n\t\r\n\tint\t\t\tm_Score;\r\n\tint\t\t\tm_Width;\r\n\tint\t\t\tm_Height;\r\n\tint\t\t\tm_NumPieces;\r\n\tint\t\t\tm_NumGaps;\r\n\tint\t\t\tm_NumGoals;\r\n\tint\t\t\tm_Theme;\r\n\tuint32\t\tm_TODScript;\r\n\tint\t\t\tm_IsMale;\r\n\r\n\tLst::Head< Directory > m_directories;\r\n\tLst::Search< Directory > m_next_dir_sh;\r\n\tDirectory\t*m_cur_dir;\r\n\tuint32\t\tm_vault_type;\r\n\tchar\t\tm_vault_root[64];\r\n\r\n\tuint32\t\tm_transfer_failed_script;\r\n\tuint32\t\tm_transfer_complete_script;\r\n\tuint32\t\tm_update_progress_script;\r\n\tuint32\t\tm_file_not_found_script;\r\n\tghttpCompletedCallback\tm_dl_complete;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n}\t// namespace GameNet\r\n\r\n#endif\t// __P_CONTENT_H"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/p_ezcommon.h",
    "content": "/*\r\n//  ------------------------------------------------------------------------\r\n\r\nFile: common.h\r\n\r\nshared headers between EE and IOP projects.\r\n\r\n//  ------------------------------------------------------------------------\r\n*/\r\n\r\n#ifndef\t_COMMON_H\r\n#define\t_COMMON_H\r\n\r\n\r\n/*  --------------------------------------------------------\r\n *  constants\r\n *  --------------------------------------------------------\r\n */\r\n\r\n#define kModName_ezNetCnf \"eznetcnf\"\r\n#define kModName_ezNetCtl \"eznetctl\"\r\n\r\n/*\r\n *  SIF RPC identifier (aka SIFNUM)\r\n *  used with sceSifRegisterRpc() and sceSifBindRpc()\r\n */\r\n#define kRPCId_ezNetCnf\t0x75499128\r\n#define kRPCId_ezNetCtl\t0x75488909\r\n\r\n/*\r\n *  SIF RPC buffer size\r\n */\r\n#define kRPCBufferSize  (256 + 64)\r\n\r\n\r\n/*\r\n *  SIF DMA are performed in 16-byte blocks from IOP -> EE.\r\n *  enforce padding in both DMA directions.\r\n */\r\n#define kDMAWait        0\r\n#define kDMANoWait      1\r\n#define kDMABlockSize   16\r\n#define DMA_PAD(_size)  (((_size) + (kDMABlockSize-1)) & ~(kDMABlockSize-1))\r\n\r\n\r\n/*  --------------------------------------------------------\r\n *  enums\r\n *  --------------------------------------------------------\r\n */\r\n\r\n/*\r\n *  eznetcnf RPC function ids\r\n */\r\ntypedef enum {\r\n  eCnfGetCount = 0,\r\n  eCnfGetCombinationList,\r\n  eCnfGetEnvData,\r\n\r\n  eCnfEnd = 0x1ffff           // for enum size consistency\r\n} ezNetCnfFunctionId;\r\n\r\n/*\r\n *  eznetctl RPC function ids\r\n */\r\ntypedef enum {\r\n  eCtlGetEnvDataAddress = 0,\r\n  eCtlSetConfiguration,\r\n  eCtlSetCombination,\r\n  eCtlWatchStatus,\r\n  eCtlDownInterface,\r\n\r\n  eCtlEnd = 0x1ffff           // for enum size consistency\r\n} ezNetCtlFunctionId;\r\n\r\n/*\r\n *  eznetcnf connection types (deprecated)\r\n */\r\ntypedef enum {\r\n  eConnInvalid = 0,           // invalid combination of devType and ifcType\r\n  eConnStatic,                // Ethernet (static IP)\r\n  eConnDHCP,                  // Ethernet (DHCP)\r\n  eConnPPPoE,                 // Ethernet (PPP over Ethernet)\r\n  eConnPPP,                   // modem (PPP)\r\n  eConnAOLPPP,                // modem (AOL PPP)\r\n\r\n  eConnPadding = 0x1ffff      // for enum size consistency\r\n} ezConnectionType;\r\n\r\n/*\r\n *  network interface protocol family\r\n */\r\ntypedef enum {\r\n  eInterfacePPP,      // modem PPP\r\n  eInterfacePPPoE,    // PPP over Ethernet\r\n  eInterfaceARP       // Ethernet (static IP and DHCP)\r\n} ezInterfaceType;\r\n\r\n/*\r\n *  netcnf file types\r\n */\r\ntypedef enum {\r\n  eCombinationFile = 0,       // net???.cnf\r\n  eInterfaceFile,             // ifc???.cnf\r\n  eDeviceFile,                // dev???.cnf\r\n\r\n  eFilePadding = 0x1ffff      // for enum size consistency\r\n} ezNetCnfType;\r\n\r\n\r\n/*  --------------------------------------------------------\r\n *  typedefs\r\n *  --------------------------------------------------------\r\n */\r\n\r\n#define kMaxCombinations  10  // maximum number of Combinations\r\n#define kStrBufferSize    256 // maximum size for any text field\r\n#define kStrDisplaySize   32  // display size for any text field\r\n\r\n\r\ntypedef struct ezNetCnfCombination {\r\n  int isActive;\r\n  ezConnectionType connectionType;\r\n  char combinationName[kStrDisplaySize];\r\n  char ifcName[kStrDisplaySize];\r\n  char devName[kStrDisplaySize];\r\n} ezNetCnfCombination_t;\r\n\r\n\r\ntypedef struct ezNetCnfCombinationList {\r\n  int listLength;\r\n  unsigned int defaultIndex;\r\n  unsigned int netdbOrder[kMaxCombinations];\r\n  ezNetCnfCombination_t list[kMaxCombinations];\r\n} ezNetCnfCombinationList_t __attribute__((aligned(64)));\r\n\r\n\r\ntypedef struct ezNetCtlStatus {\r\n  u_int clientAddr;\r\n  int id;\r\n  int event;\r\n  int state;\r\n  char message[kStrBufferSize];\r\n} ezNetCtlStatus_t __attribute__((aligned(64)));\r\n\r\n\r\n/*\r\n *  RPC buffer type for ezNetCnfGetCount()\r\n */\r\ntypedef struct {\r\n  int result;\r\n  ezNetCnfType fileType;\r\n  char netdbPath[kStrBufferSize];\r\n} rpcGetCount_t;\r\n\r\n/*\r\n *  RPC buffer type for ezNetCnfGetCombinationList()\r\n */\r\ntypedef struct {\r\n  int result;\r\n  u_int clientAddr;\r\n  char netdbPath[kStrBufferSize];\r\n} rpcGetCombinationList_t;\r\n\r\n/*\r\n *  RPC buffer type for ezNetCnfGetEnvData()\r\n */\r\ntypedef struct {\r\n  int result;\r\n  u_int clientAddr;\r\n  char netdbPath[kStrBufferSize];\r\n  char combinationName[kStrDisplaySize];\r\n} rpcGetEnvData_t;\r\n\r\n#endif\t// _COMMON_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/p_ezconfig.h",
    "content": "/*\r\n//  ------------------------------------------------------------------------\r\n\r\nFile: config.h\r\n\r\ncollection of global variables used for runtime configuration.\r\n\r\n//  ------------------------------------------------------------------------\r\n*/\r\n\r\n#ifndef _CONFIG_H\r\n#define _CONFIG_H\r\n\r\n\r\n/*  --------------------------------------------------------\r\n *  global variables/constants\r\n *  --------------------------------------------------------\r\n *  choose between:\r\n *  -> declaration (GLOBAL undefined), or\r\n *  -> definition  (GLOBAL defined)\r\n *\r\n *  GLOBAL should be defined in exactly one file (per project).\r\n */\r\n\r\n#ifdef GLOBAL\r\n  #define EXTERN\r\n#else\r\n  #define EXTERN extern\r\n#endif\r\n\r\n\r\n    //  select one of the following NET_DB defines.\r\n    //  note that the host0:net.db is unencoded.\r\nEXTERN  char *g_netdb\r\n#ifdef  GLOBAL\r\n        = \"mc0:\";\r\n//        = \"mc1:\";\r\n//        = \"host0:/usr/local/sce/conf/net/net.db\";\r\n//        = \"host0:../conf/good/net.db\";\r\n#endif\r\n;\r\n\r\n\r\n    //  specify path to SCE-supplied modules\r\nEXTERN  char *g_modRoot\t\r\n#ifdef  GLOBAL\r\n        = \"host0:/usr/local/sce/iop/modules/\"\r\n#endif\r\n;\r\n\r\n\r\nEXTERN const char *kConnectionTypeDescs[]\r\n#ifdef  GLOBAL\r\n=\r\n{\r\n  \"invalid\",\r\n  \"Ethernet, static IP\",\r\n  \"Ethernet, DHCP\",\r\n  \"Ethernet, PPPoE\",\r\n  \"Modem, PPP\",\r\n  \"Modem, AOL PPP\"\r\n}\r\n#endif\r\n;\r\n\r\n\r\n/*  --------------------------------------------------------\r\n *  debugging information enable/disable\r\n *  --------------------------------------------------------\r\n */\r\n\r\n#define DEBUG\r\n\r\n\r\n    //  use dprintf() for non-essential debug messages only.\r\n#ifdef  DEBUG\r\n#define dprintf(_args...) \\\r\n        printf(\"%s> \", __FILE__); \\\r\n        printf(_args);\r\n#else\r\n#define dprintf(_args...)\r\n#endif  // DEBUG\r\n\r\n\r\n#endif  // _CONFIG_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/p_ezmain.h",
    "content": "/*  \r\n//  ------------------------------------------------------------------------\r\n\r\nFile: main.h\r\n\r\nheaders for EE library components.\r\n\r\n//  ------------------------------------------------------------------------\r\n*/\r\n\r\n#ifndef _MAIN_H\r\n#define _MAIN_H\r\n\r\n#include <malloc.h>\r\n#include <stdio.h>\r\n#include <string.h>\r\n\r\n#include <eekernel.h>\r\n#include <libcdvd.h>\r\n#include <libmc.h>\r\n#include <libpad.h>\r\n#include <sif.h>\r\n#include <sifdev.h>\r\n#include <sifcmd.h>\r\n#include <sifrpc.h>\r\n\r\n#include <libnet.h>\r\n\r\n\r\n// <sce/common/include/libver.h> only present after 2.4.0\r\n// manually define SCE_LIBRARY_VERSION if necessary.\r\n#if (0)\r\n#define SCE_LIBRARY_VERSION     0x2340\r\n#else\r\n#include <libver.h>\r\n#endif\r\n\r\n#include \"p_netcnfif.h\"\r\n\r\n#include \"p_ezcommon.h\"\r\n#include \"p_ezconfig.h\"\r\n//#include \"util.h\"\r\n#include \"p_libezcnf.h\"\r\n//#include \"libezctl.h\"\r\n//#include \"trc_hdd.h\"\r\n\r\n\r\n#endif  // _MAIN_H\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/p_libezcnf.cpp",
    "content": "/*\r\n//  ------------------------------------------------------------------------\r\n\r\nFile: libezcnf.c\r\n\r\n//  ------------------------------------------------------------------------\r\n*/\r\n\r\n#include \"p_ezmain.h\"\r\n\r\n\r\nstatic int m_rpcRunning = 0;\r\nstatic sceSifClientData m_rpcCd;;\r\nstatic int m_rpcBuf[kRPCBufferSize/4] __attribute__((aligned(64)));\r\n\r\n\r\n#ifdef  DEBUG\r\n#define ASSERT_RPC(_size)           \\\r\n  if (!m_rpcRunning) {              \\\r\n    printf(\"**** RPC services are not currently running\\n\"); \\\r\n    return -1;                      \\\r\n  }                                 \\\r\n  if (_size > kRPCBufferSize) {     \\\r\n    printf(\"**** RPC data size 0x%x exceeds RPC buffer size 0x%x\\n\", \\\r\n           _size, kRPCBufferSize);  \\\r\n    return -1;                      \\\r\n  }\r\n#else\r\n#define ASSERT_RPC(_size)\r\n#endif\t// DEBUG\r\n\r\n\r\n/*  --------------------------------------------------------\r\n *  PUBLIC library initialization and finalization\r\n *  --------------------------------------------------------\r\n */\r\n\r\n/*\r\n *  binds to eznetcnf.irx RPC services.\r\n *  r == 1  after RPC is bound.\r\n */\r\nint\r\ninitEzNetCnf( void )\r\n{\r\n#ifdef  DEBUG\r\n  int id = sceSifSearchModuleByName(kModName_ezNetCnf);\r\n  if (id < 0) {\r\n    printf(\"\\\"%s\\\" module not found (%d)\\n\", kModName_ezNetCnf, id);\r\n  }\r\n#endif\r\n\r\n  // bind RPC\r\n  while (1) {\r\n    int i = 0x10000;\r\n    if (sceSifBindRpc(&m_rpcCd, kRPCId_ezNetCnf, 0) < 0) {\r\n      printf(\"could not bind to eznetcnf service\\n\");\r\n    }\r\n    if (m_rpcCd.serve != 0) break;\r\n    while (i--)\r\n      ;\r\n  }\r\n\r\n  return m_rpcRunning = 1;\r\n}\r\n\r\n/*\r\n *  exit and unload eznetcnf.irx, then unbind RPC services.\r\n *  r == 0  after RPC is unbound.\r\n */\r\nint\r\nexitEzNetCnf( void )\r\n{\r\n  if (m_rpcRunning == 1) {\r\n    // call using non-blocking mode,\r\n    // since eznetcnf unloads and the call cannot return.\r\n    sceSifCallRpc(&m_rpcCd, eCnfEnd, SIF_RPCM_NOWAIT, \r\n                  0, 0, 0, 0, 0, 0);\r\n    // not sure if this is necessary.\r\n    sceSifInitRpc(0);\r\n  }\r\n\r\n  return m_rpcRunning = 0;\r\n}\r\n\r\n\r\n/*  --------------------------------------------------------\r\n *  PUBLIC library interfaces\r\n *  --------------------------------------------------------\r\n */\r\n\r\n/*\r\n *  given the path to a netdb database, and a netcnf file type,\r\n *  return the number of files listed in the database. note\r\n *  sceNetCnfGetCount() returns 0 normally when no netdb file\r\n *  can be found, or even when there is no Memory Card.\r\n *\r\n *  r >  0  for valid netdb with at least 1 Combination,\r\n *  r <= 0  for error or no Combinations.\r\n */\r\nint \r\nezNetCnfGetCount(const char *netdb, ezNetCnfType type)\r\n{\r\n  rpcGetCount_t *rpcData = (rpcGetCount_t *)&m_rpcBuf;\r\n  \r\n  ASSERT_RPC(sizeof(rpcGetCount_t));\r\n  \r\n  // pack RPC data\r\n  strcpy(rpcData->netdbPath, netdb);\r\n  rpcData->fileType = type;\r\n  \r\n  // call RPC\r\n  sceSifCallRpc(&m_rpcCd, eCnfGetCount, \r\n                0,\r\n                &m_rpcBuf, sizeof(rpcGetCount_t),\r\n                &m_rpcBuf, sizeof(rpcGetCount_t),\r\n                0, 0);\r\n  \r\n  dprintf(\"ezNetCnfGetCount returned %d\\n\", rpcData->result);\r\n  return rpcData->result;\r\n}\r\n\r\n/*\r\n *  given the path to a netdb database, retrieve a list of Combinations \r\n *  to the memory address specified at addr. this list contains all the \r\n *  information needed to present to the user.\r\n *\r\n *  r == 6  for valid Memory Card netdb with at least 1 Combination,\r\n *  r == 10 for valid PFS netdb with at least 1 Combination,\r\n *  r == N  for valid host netdb with 0 < N <= 10 Combinations,\r\n *  r <= 0  for error or no Combinations.\r\n */\r\nint\r\nezNetCnfGetCombinationList(char *netdb, ezNetCnfCombinationList_t *addr)\r\n{\r\n  rpcGetCombinationList_t *rpcData = (rpcGetCombinationList_t *)&m_rpcBuf;\r\n\r\n  ASSERT_RPC(sizeof(rpcGetCombinationList_t));\r\n  \r\n  // pack RPC data\r\n  strcpy(rpcData->netdbPath, netdb);\r\n  rpcData->clientAddr = (u_int)addr;\r\n  \r\n  // call RPC\r\n  sceSifCallRpc(&m_rpcCd, eCnfGetCombinationList, \r\n                0,\r\n                &m_rpcBuf, sizeof(rpcGetCombinationList_t),\r\n                &m_rpcBuf, sizeof(rpcGetCombinationList_t),\r\n                0, 0);\r\n  \r\n  dprintf(\"ezNetCnfGetCombinationList returned %d\\n\", rpcData->result);\r\n  return rpcData->result;\r\n}\r\n\r\n/*\r\n *  given a previously generated list of combination configurations,\r\n *  return the Combination designated as the \"default\" in netdb.\r\n *\r\n *  r != NULL   for valid pList,\r\n *  r == NULL   for empty or invalid pList.\r\n */\r\nezNetCnfCombination_t *\r\nezNetCnfGetDefault(ezNetCnfCombinationList_t *pList)\r\n{\r\n  // check for valid parameters\r\n  if (pList == NULL || pList->listLength == 0) {\r\n    printf(\"ezNetCnfGetDefault: pList is empty\\n\");\r\n    return NULL;\r\n  }\r\n  if (pList->defaultIndex >= (unsigned int) pList->listLength) {\r\n    printf(\"ezNetCnfGetDefault: invalid defaultIndex (%d)\\n\",\r\n           pList->defaultIndex);\r\n    return NULL;\r\n  }\r\n\r\n  return &pList->list[pList->defaultIndex];\r\n}\r\n\r\n/*\r\n *  given the list of combinations and an ordinal number (1..N),\r\n *  return \"CombinationN\" -- REMEMBER to adjust zero-based indices.\r\n *\r\n *  r != NULL   for valid pList and valid number,\r\n *  r == NULL   for empty or invalid pList, or invalid number.\r\n */\r\nezNetCnfCombination_t *\r\nezNetCnfGetCombination(ezNetCnfCombinationList_t *pList, int number)\r\n{\r\n  // check for valid parameters\r\n  if (pList == NULL || pList->listLength == 0) {\r\n    printf(\"ezNetCnfGetCombination: pList is empty\\n\");\r\n    return NULL;\r\n  }\r\n  if ((number < 1) || (number > pList->listLength)) {\r\n    printf(\"ezNetCnfGetCombination: invalid Combination number (%d)\\n\",\r\n           number);\r\n    return NULL;\r\n  }\r\n    \r\n  return &pList->list[number-1];\r\n}\r\n\r\n/*\r\n *  given the netdb path and a designated Combination, read and convert\r\n *  the data to a sceNetcnfifData record at the specified memory address.\r\n *  this data will contain all essential configuration properties.\r\n *\r\n *  r == 0  for successfully loading Combination,\r\n *  r <  0  for error.\r\n */\r\nint\r\nezNetCnfGetEnvData(char *netdb, char *combinationName, sceNetcnfifData_t *addr)\r\n{\r\n  rpcGetEnvData_t *rpcData = (rpcGetEnvData_t *)&m_rpcBuf;\r\n\r\n  ASSERT_RPC(sizeof(rpcGetEnvData_t));\r\n  // pack the RPC request structure\r\n  strcpy(rpcData->netdbPath, netdb);\r\n  strcpy(rpcData->combinationName, combinationName);\r\n  rpcData->clientAddr = (u_int)addr;\r\n\r\n  // call RPC\r\n  sceSifCallRpc(&m_rpcCd, eCnfGetEnvData, \r\n                0,\r\n                &m_rpcBuf, sizeof(rpcGetEnvData_t),\r\n                &m_rpcBuf, sizeof(rpcGetEnvData_t),\r\n                0, 0);\r\n  \r\n  dprintf(\"ezNetCnfGetEnvData returned %d\\n\", rpcData->result);\r\n  return rpcData->result;\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/p_libezcnf.h",
    "content": "/*  \r\n//  ------------------------------------------------------------------------\r\n\r\nFile: libezcnf.h\r\n\r\nheaders for libezcnf.c\r\n\r\n//  ------------------------------------------------------------------------\r\n*/\r\n\r\n#ifndef _LIBEZCNF_H\r\n#define _LIBEZCNF_H\r\n\r\nint initEzNetCnf(void);\r\nint exitEzNetCnf(void);\r\n\r\nint ezNetCnfGetCount(const char *, ezNetCnfType);\r\nint ezNetCnfGetCombinationList(char *, ezNetCnfCombinationList_t *);\r\nezNetCnfCombination_t *ezNetCnfGetCombination(ezNetCnfCombinationList_t *, int);\r\nezNetCnfCombination_t *ezNetCnfGetDefault(ezNetCnfCombinationList_t *);\r\nint ezNetCnfGetEnvData(char *, char *, sceNetcnfifData_t *);\r\n\r\n#endif\t// _LIBEZCNF_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/p_netcnfif.h",
    "content": "/* SCE CONFIDENTIAL\r\n \"PlayStation 2\" Programmer Tool Runtime Library Release 2.5\r\n */\r\n/* \r\n *      Netcnf Interface Library\r\n *\r\n *                         Version 1.2\r\n *                         Shift-JIS\r\n *\r\n *      Copyright (C) 2002 Sony Computer Entertainment Inc.\r\n *                        All Rights Reserved.\r\n *\r\n *                         netcnfif.h\r\n *\r\n *       Version        Date            Design      Log\r\n *  --------------------------------------------------------------------\r\n *       1.1            2002.01.28      tetsu       First version\r\n *       1.2            2002.02.10      tetsu       Add SCE_NETCNFIF_CHECK_ADDITIONAL_AT\r\n *                                                  Add sceNETCNFIF_TOO_LONG_STR\r\n */\r\n\r\n#ifndef __netcnfif_common_h_\r\n#define __netcnfif_common_h_\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif /* __cplusplus */\r\n\r\n/* Sifrpc p */\r\n#define SCE_NETCNFIF_SSIZE     (4096)       /* Mf[^obt@̃TCY */\r\n#define SCE_NETCNFIF_INTERFACE (0x80001101) /* NGXgʎq */\r\n\r\n/* Sifrpc T[rX֐pԍ */\r\n#define SCE_NETCNFIF_GET_COUNT           (0)   /* lbg[Nݒt@C̐擾 */\r\n#define SCE_NETCNFIF_GET_LIST            (1)   /* lbg[Nݒt@C̃Xg擾 */\r\n#define SCE_NETCNFIF_LOAD_ENTRY          (2)   /* lbg[Nݒt@C̓e擾 */\r\n#define SCE_NETCNFIF_ADD_ENTRY           (3)   /* lbg[Nݒt@C̒ǉ */\r\n#define SCE_NETCNFIF_EDIT_ENTRY          (4)   /* lbg[Nݒt@C̕ҏW */\r\n#define SCE_NETCNFIF_DELETE_ENTRY        (5)   /* lbg[Nݒt@C̍폜 */\r\n#define SCE_NETCNFIF_SET_LATEST_ENTRY    (6)   /* lbg[Nݒt@C̃XgҏW */\r\n#define SCE_NETCNFIF_DELETE_ALL          (7)   /* Ȃ̃lbg[Nݒt@C폜 */\r\n#define SCE_NETCNFIF_CHECK_CAPACITY      (8)   /* foCX̎ceʂ`FbN */\r\n#define SCE_NETCNFIF_CHECK_ADDITIONAL_AT (9)   /* ǉ AT R}h`FbN */\r\n#define SCE_NETCNFIF_GET_ADDR            (100) /* IOP ̎M̈(sceNetcnfifData)̃AhX擾 */\r\n#define SCE_NETCNFIF_ALLOC_WORKAREA      (101) /* IOP ̃[NGAm */\r\n#define SCE_NETCNFIF_FREE_WORKAREA       (102) /* IOP ̃[NGA */\r\n#define SCE_NETCNFIF_SET_ENV             (103) /* IOP  sceNetCnfEnv ̈ sceNetcnfifData ̓eݒ */\r\n\r\n/* G[R[h(-18 ܂ł netcnf.irx Ɠ) */\r\n#define sceNETCNFIF_NG               (-1)   /* ̑̃G[ */\r\n#define sceNETCNFIF_ALLOC_ERROR      (-2)   /* ̊mۂɎs */\r\n#define sceNETCNFIF_OPEN_ERROR       (-3)   /* t@CJȂ */\r\n#define sceNETCNFIF_READ_ERROR       (-4)   /* ǂݍ݂Ɏs */\r\n#define sceNETCNFIF_WRITE_ERROR      (-5)   /* ݂Ɏs */\r\n#define sceNETCNFIF_SEEK_ERROR       (-6)   /* t@CTCY擾Ɏs */\r\n#define sceNETCNFIF_REMOVE_ERROR     (-7)   /* 폜Ɏs */\r\n#define sceNETCNFIF_ENTRY_NOT_FOUND  (-8)   /* ݒ肪Ȃ */\r\n#define sceNETCNFIF_INVALID_FNAME    (-9)   /* ݒǗt@C̃pXs */\r\n#define sceNETCNFIF_INVALID_TYPE     (-10)  /* Ȃ̃lbg[Nݒt@C̎ނs */\r\n#define sceNETCNFIF_INVALID_USR_NAME (-11)  /* ݒ薼s */\r\n#define sceNETCNFIF_TOO_MANY_ENTRIES (-12)  /* ݒ萔ő吔ɒBĂ */\r\n#define sceNETCNFIF_ID_ERROR         (-13)  /* ID 擾łȂ */\r\n#define sceNETCNFIF_SYNTAX_ERROR     (-14)  /* ݒes */\r\n#define sceNETCNFIF_MAGIC_ERROR      (-15)  /*  \"PlayStation 2\" ŕۑꂽݒ */\r\n#define sceNETCNFIF_CAPACITY_ERROR   (-16)  /* foCX̎ceʂȂ */\r\n#define sceNETCNFIF_UNKNOWN_DEVICE   (-17)  /* m̃foCXw肳Ă */\r\n#define sceNETCNFIF_IO_ERROR         (-18)  /* IO G[ */\r\n#define sceNETCNFIF_TOO_LONG_STR     (-19)  /* w肳ꂽ񂪒 */\r\n#define sceNETCNFIF_NO_DATA          (-100) /* f[^ݒ肳ĂȂ */\r\n\r\n/* Netcnf Interface ɕKvȃf[^ */\r\ntypedef struct sceNetcnfifArg{\r\n    int data;               /* ̑̈/̑̕Ԃl */\r\n    int f_no_decode;        /* no_decode tO */\r\n    int type;               /* Ȃ̃lbg[Nݒt@C̎ */\r\n    int addr;               /* EE ̎M̈̃AhX/IOP AhX̕Ԃl */\r\n    char fname[256];        /* ݒǗt@C̃pX/ǉ AT R}h */\r\n    char usr_name[256];     /* ݒ薼 */\r\n    char new_usr_name[256]; /* Vݒ薼 */\r\n} sceNetcnfifArg_t;\r\n\r\nenum\r\n{\r\n    sceNetcnfifArg_f_no_decode_off, /* f_no_decode ݒ肵Ȃ */\r\n    sceNetcnfifArg_f_no_decode_on   /* f_no_decode ݒ肷 */\r\n};\r\n\r\nenum\r\n{\r\n    sceNetcnfifArg_type_net, /* gݍ킹 */\r\n    sceNetcnfifArg_type_ifc, /* ڑvoC_ݒ */\r\n    sceNetcnfifArg_type_dev  /* ڑ@ݒ */\r\n};\r\n\r\n/* Ȃ̃lbg[Nݒt@C̃Xg */\r\ntypedef struct sceNetcnfifList{\r\n    int type;           /* Ȃ̃lbg[Nݒt@C̎ */\r\n    int stat;           /* t@CXe[^X */\r\n    char sys_name[256]; /* t@C */\r\n    char usr_name[256]; /* ݒ薼 */\r\n    int p0[14];         /* \\̈0 */\r\n} sceNetcnfifList_t __attribute__((aligned(64)));\r\n\r\n/* Ȃ̃lbg[Nݒt@Cɕۑf[^ */\r\ntypedef struct sceNetcnfifData{\r\n    char attach_ifc[256];      /* ڑvoC_ݒt@C(net) */\r\n    char attach_dev[256];      /* ڑ@ݒt@C(net) */\r\n    char dhcp_host_name[256];  /* DHCPpzXg(ifc) */\r\n    char address[256];         /* IPAhX(ifc) */\r\n    char netmask[256];         /* lbg}XN(ifc) */\r\n    char gateway[256];         /* ftHg[^(ifc) */\r\n    char dns1_address[256];    /* vC}DNS(ifc) */\r\n    char dns2_address[256];    /* ZJ_DNS(ifc) */\r\n    char phone_numbers1[256];  /* ڑdbԍ1(ifc) */\r\n    char phone_numbers2[256];  /* ڑdbԍ2(ifc) */\r\n    char phone_numbers3[256];  /* ڑdbԍ3(ifc) */\r\n    char auth_name[256];       /* [UID(ifc) */\r\n    char auth_key[256];        /* pX[h(ifc) */\r\n    char peer_name[256];       /* ڑ̔Fؖ(ifc) */\r\n    char vendor[256];          /* x_(dev) */\r\n    char product[256];         /* v_Ng(dev) */\r\n    char chat_additional[256]; /* ǉATR}h(dev) */\r\n    char outside_number[256];  /* OMԍݒ(ԍݒ蕔)(dev) */\r\n    char outside_delay[256];   /* OMԍݒ(xݒ蕔)(dev) */\r\n    int ifc_type;              /* foCXC̎(ifc) */\r\n    int mtu;                   /* MTU̐ݒ(ifc) */\r\n    int ifc_idle_timeout;      /* ؒfݒ(ifc) */\r\n    int dev_type;              /* foCXC̎(dev) */\r\n    int phy_config;            /* C[Tlbgڑ@̓샂[h(dev) */\r\n    int dialing_type;          /* _CA@(dev) */\r\n    int dev_idle_timeout;      /* ؒfݒ(dev) */\r\n    int p0;                    /* \\̈0 */\r\n    unsigned char dhcp;        /* DHCPgpEsgp(ifc) */\r\n    unsigned char dns1_nego;   /* DNST[oAhX擾EȂ(ifc) */\r\n    unsigned char dns2_nego;   /* DNST[oAhX擾EȂ(ifc) */\r\n    unsigned char f_auth;      /* Fؕ@̎wL(ifc) */\r\n    unsigned char auth;        /* Fؕ@(ifc) */\r\n    unsigned char pppoe;       /* PPPoEgpEsgp(ifc) */\r\n    unsigned char prc_nego;    /* PFClSVG[V̋֎~(ifc) */\r\n    unsigned char acc_nego;    /* ACFClSVG[V̋֎~(ifc) */\r\n    unsigned char accm_nego;   /* ACCMlSVG[V̋֎~(ifc) */\r\n    unsigned char p1;          /* \\̈1 */\r\n    unsigned char p2;          /* \\̈2 */\r\n    unsigned char p3;          /* \\̈3 */\r\n    int p4[5];                 /* \\̈4 */\r\n} sceNetcnfifData_t __attribute__((aligned(64)));\r\n\r\nenum\r\n{\r\n    sceNetcnfifData_type_no_set = -1, /* ݒ肵Ȃ */\r\n    sceNetcnfifData_type_eth = 1,     /* type eth */\r\n    sceNetcnfifData_type_ppp,         /* type ppp */\r\n    sceNetcnfifData_type_nic          /* type nic */\r\n};\r\n\r\nenum\r\n{\r\n    sceNetcnfifData_mtu_no_set = -1,   /* ݒ肵Ȃ */\r\n    sceNetcnfifData_mtu_default = 1454 /* mtu 1454 */\r\n};\r\n\r\nenum\r\n{\r\n    sceNetcnfifData_idle_timeout_no_set = -1 /* ݒ肵Ȃ */\r\n};\r\n\r\nenum\r\n{\r\n    sceNetcnfifData_phy_config_no_set = -1, /* ݒ肵Ȃ */\r\n    sceNetcnfifData_phy_config_auto = 1,    /* phy_config auto */\r\n    sceNetcnfifData_phy_config_10,          /* phy_config 10 */\r\n    sceNetcnfifData_phy_config_10_FD,       /* phy_config 10_fd */\r\n    sceNetcnfifData_phy_config_TX = 5,      /* phy_config tx */\r\n    sceNetcnfifData_phy_config_TX_FD        /* phy_config tx_fd */\r\n};\r\n\r\nenum\r\n{\r\n    sceNetcnfifData_dialing_type_no_set = -1, /* ݒ肵Ȃ */\r\n    sceNetcnfifData_dialing_type_tone = 0,    /* dialing_type tone */\r\n    sceNetcnfifData_dialing_type_pulse        /* dialing_type pulse */\r\n};\r\n\r\nenum\r\n{\r\n    sceNetcnfifData_dhcp_no_set = 0xff, /* ݒ肵Ȃ */\r\n    sceNetcnfifData_dhcp_no_use = 0,    /* -dhcp */\r\n    sceNetcnfifData_dhcp_use            /* dhcp */\r\n};\r\n\r\nenum\r\n{\r\n    sceNetcnfifData_dns_nego_no_set = 0xff, /* ݒ肵Ȃ */\r\n    sceNetcnfifData_dns_nego_on = 1         /* want.dns1_nego/want.dns2_nego */\r\n};\r\n\r\nenum\r\n{\r\n    sceNetcnfifData_f_auth_off, /* allow.auth chap/pap ݒ肵Ȃ */\r\n    sceNetcnfifData_f_auth_on   /* allow.auth chap/pap ݒ肷 */\r\n};\r\n\r\nenum\r\n{\r\n    sceNetcnfifData_auth_chap_pap = 4 /* allow.auth chap/pap */\r\n};\r\n\r\nenum\r\n{\r\n    sceNetcnfifData_pppoe_no_set = 0xff, /* ݒ肵Ȃ */\r\n    sceNetcnfifData_pppoe_use = 1        /* pppoe */\r\n};\r\n\r\nenum\r\n{\r\n    sceNetcnfifData_prc_nego_no_set = 0xff, /* ݒ肵Ȃ */\r\n    sceNetcnfifData_prc_nego_off = 0        /* -want.prc_nego */\r\n};\r\n\r\nenum\r\n{\r\n    sceNetcnfifData_acc_nego_no_set = 0xff, /* ݒ肵Ȃ */\r\n    sceNetcnfifData_acc_nego_off = 0        /* -want.acc_nego */\r\n};\r\n\r\nenum\r\n{\r\n    sceNetcnfifData_accm_nego_no_set = 0xff, /* ݒ肵Ȃ */\r\n    sceNetcnfifData_accm_nego_off = 0        /* -want.accm_nego */\r\n};\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif /* __cplusplus */\r\n\r\n#endif /*__netcnfif_common_h_ */\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/p_netconfig.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_netconfig.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t04/17/02\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNetcnf wrapper\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// start autoduck documentation\r\n// @DOC p_netconfig\r\n// @module p_netconfig | None\r\n// @subindex Scripting Database\r\n// @index script | p_netconfig\r\n                          \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#define GLOBAL 1\r\n#include <gamenet/ngps/p_ezmain.h>\r\n\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/array.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define sceNETCNF_MAGIC_ERROR\t\t(-15)\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\t/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void sceNetcnfifDataDump(sceNetcnfifData_t *data)\r\n{\r\n    Dbg_Printf(\"-----------------------\\n\");\r\n    Dbg_Printf(\"attach_ifc       : \\\"%s\\\"\\n\", data->attach_ifc);\r\n    Dbg_Printf(\"attach_dev       : \\\"%s\\\"\\n\", data->attach_dev);\r\n    Dbg_Printf(\"dhcp_host_name   : \\\"%s\\\"\\n\", data->dhcp_host_name);\r\n    Dbg_Printf(\"address          : \\\"%s\\\"\\n\", data->address);\r\n    Dbg_Printf(\"netmask          : \\\"%s\\\"\\n\", data->netmask);\r\n    Dbg_Printf(\"gateway          : \\\"%s\\\"\\n\", data->gateway);\r\n    Dbg_Printf(\"dns1_address     : \\\"%s\\\"\\n\", data->dns1_address);\r\n    Dbg_Printf(\"dns2_address     : \\\"%s\\\"\\n\", data->dns2_address);\r\n    Dbg_Printf(\"phone_numbers1   : \\\"%s\\\"\\n\", data->phone_numbers1);\r\n    Dbg_Printf(\"phone_numbers2   : \\\"%s\\\"\\n\", data->phone_numbers2);\r\n    Dbg_Printf(\"phone_numbers3   : \\\"%s\\\"\\n\", data->phone_numbers3);\r\n    Dbg_Printf(\"auth_name        : \\\"%s\\\"\\n\", data->auth_name);\r\n    Dbg_Printf(\"auth_key         : \\\"%s\\\"\\n\", data->auth_key);\r\n    Dbg_Printf(\"peer_name        : \\\"%s\\\"\\n\", data->peer_name);\r\n    Dbg_Printf(\"vendor           : \\\"%s\\\"\\n\", data->vendor);\r\n    Dbg_Printf(\"product          : \\\"%s\\\"\\n\", data->product);\r\n    Dbg_Printf(\"chat_additional  : \\\"%s\\\"\\n\", data->chat_additional);\r\n    Dbg_Printf(\"outside_number   : \\\"%s\\\"\\n\", data->outside_number);\r\n    Dbg_Printf(\"outside_delay    : \\\"%s\\\"\\n\", data->outside_delay);\r\n    Dbg_Printf(\"ifc_type         : \\\"%d\\\"\\n\", data->ifc_type);\r\n    Dbg_Printf(\"mtu              : \\\"%d\\\"\\n\", data->mtu);\r\n    Dbg_Printf(\"ifc_idle_timeout : \\\"%d\\\"\\n\", data->ifc_idle_timeout);\r\n    Dbg_Printf(\"dev_type         : \\\"%d\\\"\\n\", data->dev_type);\r\n    Dbg_Printf(\"phy_config       : \\\"%d\\\"\\n\", data->phy_config);\r\n    Dbg_Printf(\"dialing_type     : \\\"%d\\\"\\n\", data->dialing_type);\r\n    Dbg_Printf(\"dev_idle_timeout : \\\"%d\\\"\\n\", data->dev_idle_timeout);\r\n    Dbg_Printf(\"dhcp             : \\\"%d\\\"\\n\", data->dhcp);\r\n    Dbg_Printf(\"dns1_nego        : \\\"%d\\\"\\n\", data->dns1_nego);\r\n    Dbg_Printf(\"dns2_nego        : \\\"%d\\\"\\n\", data->dns2_nego);\r\n    Dbg_Printf(\"f_auth           : \\\"%d\\\"\\n\", data->f_auth);\r\n    Dbg_Printf(\"auth             : \\\"%d\\\"\\n\", data->auth);\r\n    Dbg_Printf(\"pppoe            : \\\"%d\\\"\\n\", data->pppoe);\r\n    Dbg_Printf(\"prc_nego         : \\\"%d\\\"\\n\", data->prc_nego);\r\n    Dbg_Printf(\"acc_nego         : \\\"%d\\\"\\n\", data->acc_nego);\r\n    Dbg_Printf(\"accm_nego        : \\\"%d\\\"\\n\", data->accm_nego);\r\n    Dbg_Printf(\"-----------------------\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\n *  given a combination configuration, display its details.\r\n */\r\nstatic void showConfiguration(ezNetCnfCombination_t *p_conf, sceNetcnfifData_t *p_data)\r\n{\r\n\tif (p_conf == NULL) \r\n\t{\r\n\t\tDbg_Printf(\"showConfiguration: p_conf is NULL\\n\");\r\n\t\treturn;\r\n\t}\r\n  \r\n\tif (p_conf->isActive) \r\n\t{\r\n\t\tDbg_Printf(\"ezNetCnfCombination_t ------------\\n\");\r\n\t\tDbg_Printf(\"net display name\\t%s\\n\", p_conf->combinationName);\r\n\t\tDbg_Printf(\"ifc display name\\t%s\\n\", p_conf->ifcName);\r\n\t\tDbg_Printf(\"dev display name\\t%s\\n\", p_conf->devName);\r\n\t\tDbg_Printf(\"type\\t\\t%s\\n\", kConnectionTypeDescs[p_conf->connectionType]);\r\n//#if (SCE_LIBRARY_VERSION >= 0x2500)\r\n\t\tsceNetcnfifDataDump(p_data);\r\n//#endif\r\n\t} \r\n\telse \r\n\t{\r\n\t\tDbg_Printf(\"\\tempty Combination slot\\n\");\r\n\t}\r\n\r\n\tDbg_Printf(\"\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptLoadNetConfigs(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n    ezNetCnfCombination_t *p_combination = NULL;\r\n\tint i, err;\r\n\r\n\tDbg_Printf( \"****************** LOADING NETWORK CONFIG!!!! ************************ \\n\" );\r\n\r\n\tstatic bool once = false;\r\n\tif( !once )\r\n\t{\r\n\t\tSIO::LoadIRX(\"eznetcnf\" );\t// net config stuff\r\n\t\tinitEzNetCnf();\r\n\t}\r\n\r\n    err = ezNetCnfGetCombinationList( g_netdb, &gamenet_man->m_combination_list );\r\n\tif( err < 0 )\r\n\t{\r\n\t\tif( err != sceNETCNF_MAGIC_ERROR )\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddChecksum( NONAME, CRCD(0x492676a6,\"corrupt\"));\r\n\t\t}\r\n\t\tDbg_Printf( \"ezNetCnfGetCombinationList error = %d\\n\", err );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfor( i = 0; i < gamenet_man->m_combination_list.listLength; i++ )\r\n\t{\r\n\t\tDbg_Printf(\"getting combo %d\\n\", i + 1);\r\n\t\tp_combination = ezNetCnfGetCombination(&gamenet_man->m_combination_list, i + 1);\r\n\t\tif (p_combination != NULL && p_combination->isActive && ( p_combination->connectionType != eConnInvalid )) \r\n\t\t{\r\n\t\t\tDbg_Printf(\"found combo, %s\\n\", p_combination->combinationName);\r\n\t\t\terr = ezNetCnfGetEnvData(g_netdb, p_combination->combinationName, &gamenet_man->m_env_data[i] );\r\n\t\t\tif( err < 0 ) \r\n\t\t\t{\r\n\t\t\t\tDbg_Printf(\"ezNetCnfGetEnvData error = %d\\n\", err);\r\n\t\t\t}\r\n\t\t\tshowConfiguration( p_combination, &gamenet_man->m_env_data[i] );\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*ezNetCnfCombination_t*\tManager::GetNetworkConfig( int index )\r\n{\r\n\treturn mp_combinations[index];\r\n}*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*void\tManager::ExitNetworkConfig( void )\r\n{\r\n\tDbg_Printf( \"****************** EXITING NETWORK CONFIG!!!! ************************ \\n\" );\r\n\t// call using non-blocking mode,\r\n\t// since eznetcnf unloads and the call cannot return.\r\n\tsceSifCallRpc(&g_cd, eFuncEnd, SIF_RPCM_NOWAIT, \r\n\t    \t\t0, 0, 0, 0, 0, 0);\r\n\t// not sure if this is necessary.\r\n\tsceSifInitRpc(0);\r\n}*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptNoNetConfigFiles(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tezNetCnfCombination_t *p_combination;\r\n\r\n\tp_combination = ezNetCnfGetDefault(&gamenet_man->m_combination_list);\r\n\tif( p_combination != NULL && p_combination->isActive ) \r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::ScriptFillNetConfigList(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tezNetCnfCombination_t *p_combination;\r\n\tScript::CStruct* p_item_params;\r\n\tScript::CStruct* p_script_params;\r\n\tint i;\r\n\tchar config_title[64];\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\r\n\tfor( i = 0; i < gamenet_man->m_combination_list.listLength; i++ )\r\n\t{\r\n\t\t// check the Default Combination\r\n\t\tp_combination = ezNetCnfGetCombination(&gamenet_man->m_combination_list, i + 1);\r\n\t\tif( p_combination != NULL && p_combination->isActive && ( p_combination->connectionType != eConnInvalid ))\r\n\t\t{\r\n\t\t\tsprintf( config_title, \"%d %s\", i + 1, p_combination->ifcName );\r\n\t\t\r\n\t\t\tp_item_params = new Script::CStruct;\t\r\n\t\t\tp_item_params->AddString( \"text\", config_title );\r\n\t\t\tp_item_params->AddChecksum( \"id\", Script::GenerateCRC( \"first_net_cfg\" ) + i );\r\n\t\t\tp_item_params->AddChecksum( \"centered\", CRCD(0x2a434d05,\"centered\") );\r\n\t\t\tp_item_params->AddFloat( \"scale\", 0.8f );\r\n\t\t\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"choose_net_config\"));\r\n\t\t\tp_item_params->AddChecksum( \"focus_script\",CRCD(0x6100d1f9,\"main_theme_focus_noscale\"));\r\n\t\t\tp_item_params->AddChecksum( \"unfocus_script\",CRCD(0xe9602a90,\"main_theme_unfocus_noscale\"));\r\n\t\t\tp_item_params->AddChecksum( \"parent_menu_id\", Script::GenerateCRC( \"network_options_load_config_vmenu\" ));\r\n\t\t\r\n\t\t\t// create the parameters that are passed to the X script\r\n\t\t\tp_script_params= new Script::CStruct;\r\n\t\t\tp_script_params->AddInteger( \"index\", i + 1 );\t\r\n\t\t\tp_item_params->AddStructure(\"pad_choose_params\",p_script_params);\t\t\t\r\n\t\t\r\n\t\t\tScript::RunScript(\"theme_menu_add_item\",p_item_params);\r\n\t\t\tdelete p_item_params;\r\n\t\t\tdelete p_script_params;\r\n\t\t}\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tManager::ScriptChooseNetConfig(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPrefs::Preferences* prefs;\r\n\tScript::CScriptStructure* pTempStructure;\r\n\tezNetCnfCombination_t *p_combination;\r\n\tint index;\r\n    sceNetcnfifData* data;\r\n\tchar outside_str[64];\r\n\tchar full_phone[128];\r\n\tchar full_name[256];\r\n\tbool dns_set;\r\n\r\n\tprefs = gamenet_man->GetNetworkPreferences();\r\n\tp_combination = NULL;\r\n\tdata = NULL;\r\n\tif( pParams->GetInteger( \"index\", &index, false ))\r\n\t{\r\n\t\tdata = &gamenet_man->m_env_data[index];\r\n\t\tp_combination = ezNetCnfGetCombination( &gamenet_man->m_combination_list, index );\r\n\t\tsprintf( full_name, \"%d %s\", index, p_combination->ifcName );\r\n\t}\r\n\telse\r\n\t{\t\r\n\t\tconst char* name;\r\n\t\tint i;\r\n\t\tbool found;\r\n\r\n\t\tpParams->GetString( \"name\", &name, Script::ASSERT );\r\n\t\tfound = false;\r\n\t\tfor( i = 0; i < gamenet_man->m_combination_list.listLength; i++ )\r\n\t\t{\r\n\t\t\t// check the Default Combination\r\n\t\t\tp_combination = ezNetCnfGetCombination(&gamenet_man->m_combination_list, i + 1 );\r\n\t\t\t\r\n\t\t\tif(\tp_combination != NULL )\r\n\t\t\t{\r\n\t\t\t\tsprintf( full_name, \"%d %s\", i + 1, p_combination->ifcName );\r\n\t\t\t\r\n\t\t\t\tif(\t( p_combination->isActive ) && \r\n\t\t\t\t\t( strcmp( full_name, name ) == 0 ) && \r\n\t\t\t\t\t( p_combination->connectionType != eConnInvalid ))\r\n\t\t\t\t{   \r\n\t\t\t\t\tindex = i;\r\n\t\t\t\t\tfound = true;\r\n\t\t\t\t\tdata = &gamenet_man->m_env_data[index];\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( !found )\r\n\t\t{\r\n\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, Script::GetString( \"manual_settings_str\" ));\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"config_manual\" ));\r\n\t\t\tprefs->SetPreference( Script::GenerateCRC(\"config_type\"), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tScript::RunScript( \"clear_net_options\" );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\tpTempStructure = new Script::CScriptStructure;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, full_name );\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"config_sony\" ));\r\n\tprefs->SetPreference( Script::GenerateCRC(\"config_type\"), pTempStructure );\r\n\tdelete pTempStructure;\r\n\t\r\n\tpTempStructure = new Script::CScriptStructure;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, data->address );\r\n\tprefs->SetPreference( Script::GenerateCRC(\"ip_address\"), pTempStructure );\r\n\tdelete pTempStructure;\r\n\r\n\tpTempStructure = new Script::CScriptStructure;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, data->netmask );\r\n\tprefs->SetPreference( Script::GenerateCRC(\"subnet_mask\"), pTempStructure );\r\n\tdelete pTempStructure;\r\n\r\n\tpTempStructure = new Script::CScriptStructure;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, data->gateway );\r\n\tprefs->SetPreference( Script::GenerateCRC(\"gateway\"), pTempStructure );\r\n\tdelete pTempStructure;\r\n\r\n\tpTempStructure = new Script::CScriptStructure;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, data->dns1_address );\r\n\tprefs->SetPreference( Script::GenerateCRC(\"dns_server\"), pTempStructure );\r\n\tdelete pTempStructure;\r\n\r\n\tpTempStructure = new Script::CScriptStructure;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, data->dns2_address );\r\n\tprefs->SetPreference( Script::GenerateCRC(\"dns_server2\"), pTempStructure );\r\n\tdelete pTempStructure;\r\n\r\n\tpTempStructure = new Script::CScriptStructure;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, data->dhcp_host_name );\r\n\tprefs->SetPreference( Script::GenerateCRC(\"host_name\"), pTempStructure );\r\n\tdelete pTempStructure;\r\n\r\n\tsprintf( outside_str, \"%s%s\", data->outside_number, data->outside_delay );\r\n\tsprintf( full_phone, \"%s%s\", outside_str, data->phone_numbers1 );\r\n\r\n\tpTempStructure = new Script::CScriptStructure;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, full_phone );\r\n\tprefs->SetPreference( Script::GenerateCRC(\"dialup_number\"), pTempStructure );\r\n\tdelete pTempStructure;\r\n\r\n\tsprintf( full_phone, \"%s%s\", outside_str, data->phone_numbers2 );\r\n\r\n\tpTempStructure = new Script::CScriptStructure;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, full_phone );\r\n\tprefs->SetPreference( Script::GenerateCRC(\"dialup_number2\"), pTempStructure );\r\n\tdelete pTempStructure;\r\n\r\n\tsprintf( full_phone, \"%s%s\", outside_str, data->phone_numbers3 );\r\n\r\n\tpTempStructure = new Script::CScriptStructure;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, full_phone );\r\n\tprefs->SetPreference( Script::GenerateCRC(\"dialup_number3\"), pTempStructure );\r\n\tdelete pTempStructure;\r\n\r\n\tpTempStructure = new Script::CScriptStructure;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, data->auth_name );\r\n\tprefs->SetPreference( Script::GenerateCRC(\"dialup_username\"), pTempStructure );\r\n\tdelete pTempStructure;\r\n\r\n\tpTempStructure = new Script::CScriptStructure;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, data->auth_key );\r\n\tprefs->SetPreference( Script::GenerateCRC(\"dialup_password\"), pTempStructure );\r\n\tdelete pTempStructure;\r\n\r\n\tdns_set = false;\r\n\t\t\t\r\n\tif( ( strlen( data->dns1_address ) > 0 ) ||\r\n\t\t( strlen( data->dns2_address ) > 0 ))\r\n\t{\r\n\t\tdns_set = true;\r\n\t}\r\n\r\n\tswitch((int) p_combination->connectionType )\r\n\t{\r\n\t\tcase eConnStatic:\r\n\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \"Ethernet (Network Adaptor for PS2)\" );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"device_broadband_pc\" ));\r\n\t\t\tprefs->SetPreference( Script::GenerateCRC(\"device_type\"), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \"Static IP Address\" );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"ip_static\" ));\r\n\t\t\tprefs->SetPreference( Script::GenerateCRC(\"broadband_type\"), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \"No\" );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"boolean_false\" ));\r\n\t\t\tprefs->SetPreference( Script::GenerateCRC(\"auto_dns\"), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\t\t\tbreak;\r\n\t\tcase eConnDHCP:\r\n\t\t{\r\n\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \"Ethernet (Network Adaptor for PS2)\" );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"device_broadband_pc\" ));\r\n\t\t\tprefs->SetPreference( Script::GenerateCRC(\"device_type\"), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \"Auto-Detect (DHCP)\" );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"ip_dhcp\" ));\r\n\t\t\tprefs->SetPreference( Script::GenerateCRC(\"broadband_type\"), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tif( dns_set )\r\n\t\t\t{\r\n\t\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \"No\" );\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"boolean_false\" ));\r\n\t\t\t\tprefs->SetPreference( Script::GenerateCRC(\"auto_dns\"), pTempStructure );\r\n\t\t\t\tdelete pTempStructure;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \"Yes\" );\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"boolean_true\" ));\r\n\t\t\t\tprefs->SetPreference( Script::GenerateCRC(\"auto_dns\"), pTempStructure );\r\n\t\t\t\tdelete pTempStructure;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase eConnPPPoE:\r\n\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \"Ethernet (Network Adaptor for PS2) (PPPoE)\" );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"device_broadband_pc_pppoe\" ));\r\n\t\t\tprefs->SetPreference( Script::GenerateCRC(\"device_type\"), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\r\n\t\t\tif( dns_set )\r\n\t\t\t{\r\n\t\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \"No\" );\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"boolean_false\" ));\r\n\t\t\t\tprefs->SetPreference( Script::GenerateCRC(\"auto_dns\"), pTempStructure );\r\n\t\t\t\tdelete pTempStructure;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \"Yes\" );\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"boolean_true\" ));\r\n\t\t\t\tprefs->SetPreference( Script::GenerateCRC(\"auto_dns\"), pTempStructure );\r\n\t\t\t\tdelete pTempStructure;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase eConnPPP:\r\n\t\tcase eConnAOLPPP:\r\n\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \"Modem (Network Adaptor for PS2)\" );\r\n\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"device_sony_modem\" ));\r\n\t\t\tprefs->SetPreference( Script::GenerateCRC(\"device_type\"), pTempStructure );\r\n\t\t\tdelete pTempStructure;\r\n\t\t\tif( dns_set )\r\n\t\t\t{\r\n\t\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \"No\" );\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"boolean_false\" ));\r\n\t\t\t\tprefs->SetPreference( Script::GenerateCRC(\"auto_dns\"), pTempStructure );\r\n\t\t\t\tdelete pTempStructure;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpTempStructure = new Script::CScriptStructure;\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, \"Yes\" );\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, Script::GenerateCRC( \"boolean_true\" ));\r\n\t\t\t\tprefs->SetPreference( Script::GenerateCRC(\"auto_dns\"), pTempStructure );\r\n\t\t\t\tdelete pTempStructure;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_Printf( \"************** GOT %d\\n\", (int) p_combination->connectionType );\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t\tbreak;\r\n\t}\r\n    \r\n\t//Dbg_Printf(\"product          : \\\"%s\\\"\\n\", data->product);\r\n    //Dbg_Printf(\"chat_additional  : \\\"%s\\\"\\n\", data->chat_additional);\r\n    //Dbg_Printf(\"ifc_type         : \\\"%d\\\"\\n\", data->ifc_type);\r\n    //Dbg_Printf(\"mtu              : \\\"%d\\\"\\n\", data->mtu);\r\n    //Dbg_Printf(\"ifc_idle_timeout : \\\"%d\\\"\\n\", data->ifc_idle_timeout);\r\n    //Dbg_Printf(\"dev_type         : \\\"%d\\\"\\n\", data->dev_type);\r\n    //Dbg_Printf(\"phy_config       : \\\"%d\\\"\\n\", data->phy_config);\r\n    //Dbg_Printf(\"dialing_type     : \\\"%d\\\"\\n\", data->dialing_type);\r\n    //Dbg_Printf(\"dev_idle_timeout : \\\"%d\\\"\\n\", data->dev_idle_timeout);\r\n    //Dbg_Printf(\"dhcp             : \\\"%d\\\"\\n\", data->dhcp);\r\n    //Dbg_Printf(\"dns1_nego        : \\\"%d\\\"\\n\", data->dns1_nego);\r\n    //Dbg_Printf(\"dns2_nego        : \\\"%d\\\"\\n\", data->dns2_nego);\r\n    //Dbg_Printf(\"f_auth           : \\\"%d\\\"\\n\", data->f_auth);\r\n    //Dbg_Printf(\"auth             : \\\"%d\\\"\\n\", data->auth);\r\n    //Dbg_Printf(\"pppoe            : \\\"%d\\\"\\n\", data->pppoe);\r\n    //Dbg_Printf(\"prc_nego         : \\\"%d\\\"\\n\", data->prc_nego);\r\n    //Dbg_Printf(\"acc_nego         : \\\"%d\\\"\\n\", data->acc_nego);\r\n    //Dbg_Printf(\"accm_nego        : \\\"%d\\\"\\n\", data->accm_nego);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/p_stats.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_stats.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t04/30/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPS2 Stat-tracking Code \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gel/mainloop.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/net/server/netserv.h>\r\n\r\n#include <objects/skater.h>\r\n\r\n#include <GameNet/GameNet.h>\r\n#include <Gamenet/ngps/p_buddy.h>\r\n#include <Gamenet/ngps/p_content.h>\r\n#include <GameNet/Ngps/p_stats.h>\r\n\r\n#include <sk/components/skaterscorecomponent.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern bool g_CheatsEnabled;\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define vSTATS_CONNECT_TIMEOUT Tmr::Seconds( 10 )\r\n#define vSTATS_REPORT_INTERVAL Tmr::Minutes( 1 )\r\n#define vMAX_STATS_FILE_SIZE ( 150 * 1024 );\r\n#define vMAX_ENTRIES_PER_LEVEL 3\r\n#define vSTATS_PLAYER_COUNT 50\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic \tTmr::Time\ts_connect_start_time = 0;\r\nuint32\ts_levels[] = { \t0xf6c822d4, 0x7276630a, 0xd7720de9, 0xee1c63cf, 0x399bd4e8, \r\n\t\t\t\t\t\t0xd0f0229, 0x9a44ec8, 0x9db7727c, 0x991b5359, \r\n\t\t\t\t\t\t0x73be7e94, 0xa7ff414b, 0x8ca30405 };\r\nchar\ts_stats_files[vNUM_RATINGS_FILES][32] = {\r\n\t\"hs_at.txt\",\r\n\t\"bc_at.txt\",\r\n\t\"hs_mo.txt\",\r\n\t\"bc_mo.txt\",\r\n\t\"ratings.txt\"\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass SortableStats : public Lst::Node< SortableStats >\r\n{\r\npublic:\r\n\tSortableStats( void );\r\n\r\n\tchar\tm_Name[32];\r\n\tuint32\tm_Level;\r\n\tint\t\tm_Score;\r\n\tint\t\tm_Rating;\r\n};\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tStatsMan::parse_ratings( char* buffer )\r\n{\r\n\tStatsKeeper* keeper;\r\n\tchar* token;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tkeeper = &m_stats_keepers[vFILE_RATINGS];\r\n\ttoken = strtok( buffer, \":\" );\r\n    \r\n\twhile( token )\r\n\t{\r\n\t\tStatsPlayer* player;\r\n\r\n\t\tplayer = new StatsPlayer;\r\n\t\tkeeper->m_Players.AddToTail( player );\r\n\t\tplayer->m_Score = atoi( token );\r\n\t\t\r\n\t\t// Now parse, looking for the rating\r\n\t\ttoken = strtok( NULL, \":\" );\r\n\t\t// Guard against corrupt files\r\n\t\tif( token == NULL )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tplayer->m_Rating = atoi( token );\r\n\t\ttoken = strtok( NULL, \"\\n\" );\r\n\t\t// Guard against corrupt files\r\n\t\tif( token == NULL )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tstrcpy( player->m_Name, token );\r\n        \r\n\t\t// Now parse, looking for the next rating\r\n\t\ttoken = strtok( NULL, \":\" );\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStatsMan::parse_score_list( int type, char* buffer, bool read_date )\r\n{\r\n\tStatsLevel* level;\r\n\tchar* token;\r\n\tuint32 level_crc;\r\n\r\n\tDbg_Assert( type <= vFILE_BEST_COMBO_MONTHLY );\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n    if( read_date )\r\n\t{\r\n\t\ttoken = strtok( buffer, \"\\n\" );\r\n\r\n\t\tstrcpy( m_stats_keepers[type].m_Date, token );\r\n\t\tDbg_Printf( \"Date: %s\\n\", m_stats_keepers[type].m_Date );\r\n\t\ttoken = strtok( NULL, \":\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttoken = strtok( buffer, \":\" );\r\n\t}\r\n\t\r\n\twhile( token && ( stricmp( token, \"Level\" ) == 0 ))\r\n\t{\r\n\t\ttoken = strtok( NULL, \"\\n\" );\r\n\t\t// Guard against corrupt files\r\n\t\tif( token == NULL )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tlevel_crc = atoi( token );\r\n\t\tlevel = new StatsLevel;\r\n\t\tlevel->m_Level = level_crc;\r\n\r\n\t\tm_stats_keepers[type].m_Levels.AddToTail( level );\r\n\r\n\t\t// Now parse, looking for a list of players and scores\r\n\t\ttoken = strtok( NULL, \":\" );\r\n\t\t// Guard against corrupt files\r\n\t\tif( token == NULL )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Read until we reach another \"level\" or EOF\r\n\t\twhile( token && stricmp( token, \"Level\" ))\r\n\t\t{\r\n\t\t\tStatsPlayer* player;\r\n\r\n\t\t\tplayer = new StatsPlayer;\r\n\r\n\t\t\tlevel->m_Players.AddToTail( player );\r\n\t\t\tplayer->m_Score = atoi( token );\r\n\t\t\tDbg_Printf( \"Score %d  \", player->m_Score );\r\n\t\t\ttoken = strtok( NULL, \":\" );\r\n\t\t\t// Guard against corrupt files\r\n\t\t\tif( token == NULL )\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tplayer->m_Rating = atoi( token );\r\n\t\t\tDbg_Printf( \"Rating %d  \", player->m_Rating );\r\n\t\t\ttoken = strtok( NULL, \"\\n\" );\r\n\t\t\t// Guard against corrupt files\r\n\t\t\tif( token == NULL )\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tstrcpy( player->m_Name, token );\r\n\t\t\tDbg_Printf( \"Name %s\\n\", player->m_Name );\r\n\r\n\t\t\t// Now parse, looking for the next level or player\r\n\t\t\ttoken = strtok( NULL, \":\" );\r\n\t\t}\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGHTTPBool StatsMan::s_stats_file_dl_complete( GHTTPRequest request, GHTTPResult result, char* buffer,\r\n\t\t\t\t\t\t\t\t\t\t\t  int buffer_len, void * param )\r\n{\r\n\tContentMan* content_man;\r\n\r\n\tcontent_man = (ContentMan*) param;\r\n\r\n\tDbg_Printf( \"Got result %d\\n\", result );\r\n\r\n\tcontent_man->SetPercentComplete( 100 );\r\n\tif( result == GHTTPSuccess )\r\n\t{\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tStatsMan* stats_man;\r\n\r\n\t\tcontent_man->SetResult( vCONTENT_RESULT_SUCCESS );\r\n\t\tcontent_man->SetError( 0 );\r\n\t\t\r\n\t\tstats_man = gamenet_man->mpStatsMan;\r\n\t\tswitch( stats_man->m_cur_file_index )\r\n\t\t{\r\n\t\t\tcase vFILE_HIGH_SCORE_ALL_TIME:\r\n\t\t\tcase vFILE_BEST_COMBO_ALL_TIME:\r\n\t\t\t\tstats_man->parse_score_list( stats_man->m_cur_file_index, buffer, false );\r\n\t\t\t\tbreak;\r\n\t\t\tcase vFILE_HIGH_SCORE_MONTHLY:\r\n\t\t\tcase vFILE_BEST_COMBO_MONTHLY:\r\n\t\t\t{\r\n\t\t\t\tstats_man->parse_score_list( stats_man->m_cur_file_index, buffer, true );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase vFILE_RATINGS:\r\n\t\t\t{\r\n\t\t\t\tstats_man->parse_ratings( buffer );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcontent_man->SetResult( vCONTENT_RESULT_FAILURE );\r\n\t\tcontent_man->SetError( result );\r\n\t}\r\n\t\r\n\treturn GHTTPTrue;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStatsMan::s_stats_logic_code( const Tsk::Task< StatsMan >& task )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\tStatsMan& man = task.GetData();\r\n\r\n\tswitch( man.m_state )\r\n\t{\r\n\t\tcase vSTATS_STATE_WAITING:\r\n\t\t\tbreak;\r\n\t\tcase vSTATS_STATE_CONNECTING:\r\n\t\t\tif(( Tmr::GetTime() - s_connect_start_time ) > vSTATS_CONNECT_TIMEOUT )\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( \"StatsRetrievalFailedDialog\" );\r\n\t\t\t\tman.Disconnect();\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase vSTATS_STATE_CONNECTED:\r\n\t\t\tman.m_state = vSTATS_STATE_LOGGED_IN;\r\n\t\t\tman.Connected();\r\n\t\t\tbreak;\r\n\t\tcase vSTATS_STATE_FAILED_LOG_IN:\r\n\t\t\tScript::RunScript( \"StatsLoginFailedDialog\" );\r\n\t\t\tman.Disconnect();\r\n\t\t\tbreak;\r\n\t\tcase vSTATS_STATE_RETRIEVING:\r\n\t\t\tif(( Tmr::GetTime() - s_connect_start_time ) > vSTATS_CONNECT_TIMEOUT )\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( \"StatsRetrievalFailedDialog\" );\r\n\t\t\t\tman.Disconnect();\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tif( PersistThink() == 0 )\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( \"StatsRetrievalFailedDialog\" );\r\n\t\t\t\tman.Disconnect();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase vSTATS_STATE_LOGGED_IN:\r\n\t\t\tbreak;\r\n\t\tcase vSTATS_STATE_IN_GAME:\r\n\t\t\tif(( Tmr::GetTime() - man.m_time_since_last_report ) > vSTATS_REPORT_INTERVAL )\r\n\t\t\t{\r\n\t\t\t\tman.ReportStats( false );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \tStatsMan::s_threaded_stats_connect( StatsMan* stats_man )\r\n{\r\n\tint result;\r\n\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\t// Register this thread with the sockets API\r\n\tsockAPIregthr();\r\n\r\n    sprintf( gcd_gamename, \"thps5ps2\" );\r\n\tsprintf( gcd_secret_key, \"G2k8cF\" );\r\n\tDbg_Printf( \"About to connect to stats server...\\n\" );\r\n\tresult = InitStatsConnection( GameNet::vHOST_PORT );\r\n\tswitch( result )\r\n\t{\r\n\t\tcase GE_NODNS:\t// Unable to resolve stats server DNS\r\n\t\t\tgamenet_man->mpStatsMan->m_state = vSTATS_STATE_FAILED_LOG_IN;\r\n\t\t\tDbg_Printf( \"Error connecting to stats server: No DNS\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GE_NOSOCKET: // Unable to create data socket\r\n\t\t\tgamenet_man->mpStatsMan->m_state = vSTATS_STATE_FAILED_LOG_IN;\r\n\t\t\tDbg_Printf( \"Error connecting to stats server: No Socket\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GE_NOCONNECT: // Unable to connect to stats server\r\n\t\t\tgamenet_man->mpStatsMan->m_state = vSTATS_STATE_FAILED_LOG_IN;\r\n\t\t\tDbg_Printf( \"Error connecting to stats server: No Connect\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GE_DATAERROR: // Unable to receive challenge from stats server, or bad challenge\r\n\t\t\tgamenet_man->mpStatsMan->m_state = vSTATS_STATE_FAILED_LOG_IN;\r\n\t\t\tDbg_Printf( \"Error connecting to stats server: Data error\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GE_NOERROR: // Connected to stats server and ready to send data\r\n\t\t\tDbg_Printf( \"Connected to stats server\\n\" );\r\n\t\t\tgamenet_man->mpStatsMan->m_state = vSTATS_STATE_CONNECTED;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\t// Deregister this thread with the sockets API\r\n\tsockAPIderegthr();\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStatsMan::StatsMan( void )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\tm_stats_logic_task = new Tsk::Task< StatsMan > ( s_stats_logic_code, *this );\r\n\tm_logged_in = false;\r\n\tm_state = vSTATS_STATE_WAITING;\r\n\tm_cur_game = NULL;\r\n\tm_need_to_retrieve_stats = true;\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStatsMan::~StatsMan( void )\r\n{\r\n\tdelete m_stats_logic_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStatsMan::Connected( void )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\tm_logged_in = true;\r\n\tScript::RunScript( \"stats_logged_in\" );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tStatsMan::IsLoggedIn( void )\r\n{\r\n\tm_logged_in = ( IsStatsConnected() == 1 );\r\n\r\n\treturn m_logged_in;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tStatsMan::NeedToRetrieveStats( void )\r\n{\r\n\treturn m_need_to_retrieve_stats;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStatsMan::Connect( void )\r\n{   \r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tThread::PerThreadStruct\tnet_thread_data;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\t\r\n\tm_state = vSTATS_STATE_CONNECTING;\r\n\ts_connect_start_time = Tmr::GetTime();\r\n\r\n\tScript::RunScript( \"stats_log_in_profile\" );\r\n\r\n    net_thread_data.m_pEntry = s_threaded_stats_connect;\r\n\tnet_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY;\r\n\tnet_thread_data.m_pStackBase = gamenet_man->GetNetThreadStack();\r\n\tnet_thread_data.m_iStackSize = vNET_THREAD_STACK_SIZE;\r\n\tnet_thread_data.m_utid = 0x152;\r\n\tThread::CreateThread( &net_thread_data );\r\n\tgamenet_man->SetNetThreadId( net_thread_data.m_osId );\r\n\tStartThread( gamenet_man->GetNetThreadId(), this );\r\n\r\n\tif( !m_stats_logic_task->InList())\r\n\t{\r\n\t\tmlp_man->AddLogicTask( *m_stats_logic_task );\r\n\t}\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStatsMan::Disconnect( void )\r\n{   \r\n    CloseStatsConnection();\r\n\tm_stats_logic_task->Remove();\r\n\tm_logged_in = false;\r\n\tm_state = vSTATS_STATE_WAITING;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tStatsMan::ScriptStatsLoggedIn(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tStatsMan* stats_man;\r\n\r\n\tstats_man = gamenet_man->mpStatsMan;\r\n\treturn stats_man->IsLoggedIn();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tStatsMan::ScriptStatsLogIn(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\t\r\n\tgamenet_man->mpStatsMan->Connect();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tStatsMan::ScriptStatsLogOff(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tStatsMan* stats_man;\r\n\r\n\tstats_man = gamenet_man->mpStatsMan;\r\n\tstats_man->Disconnect();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tStatsMan::ScriptReportStats(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tStatsMan* stats_man;\r\n\tbool final;\r\n\r\n\tfinal = pParams->ContainsFlag( CRCD(0x132aa339,\"final\"));\r\n\tstats_man = gamenet_man->mpStatsMan;\r\n\tstats_man->ReportStats( final );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStatsMan::s_stats_retrieval_callback( int localid, int profileid, persisttype_t type, \r\n\t\t\t\t\t\t\t\t\t\t\t  int index, int success, char *data, int len, \r\n\t\t\t\t\t\t\t\t\t\t\t  void *instance )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tStats* stats;\r\n\r\n\tDbg_Printf( \"********* Got stats for %d type %d index %d success %d data %s len %d\\n\",\r\n\t\t\t\tprofileid, type, index, success, data, len );\r\n\t\r\n\tif( success < 1 )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tstats = gamenet_man->mpStatsMan->GetStats();\r\n\r\n\t// Rating\r\n\tif( index == 0 )\r\n\t{\r\n\t\tchar* ptr;\r\n        \r\n\t\tptr = strtok( data, \"\\\\\" );\r\n\t\tDbg_Printf( \"Ptr: %s\\n\", ptr );\r\n\t\tif( ptr )\r\n\t\t{\r\n\t\t\tptr = strtok( NULL, \"\\\\\" );\r\n\t\t\tDbg_Printf( \"(2)Ptr: %s\\n\", ptr );\r\n\t\t\tstats->m_rating = atoi( ptr );\r\n\t\t\tDbg_Printf( \"(3)Rating: %d\\n\", stats->m_rating );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tchar* ptr;\r\n        \r\n\t\t// Levels\r\n\t\tptr = strtok( data, \"\\\\\" );\r\n\t\tif( ptr )\r\n\t\t{\r\n\t\t\tDbg_Printf( \"**** 1\\n\" );\r\n\t\t\tif( stricmp( ptr, \"HighScore\" ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"**** 2\\n\" );\r\n\t\t\t\tptr = strtok( NULL, \"\\\\\" );\r\n\t\t\t\tif( ptr )\r\n\t\t\t\t{\r\n\t\t\t\t\tstats->m_highscore[index - 1] = atoi( ptr );\r\n\t\t\t\t\tDbg_Printf( \"**** 3 %d\\n\", stats->m_highscore[index -1 ] );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tptr = strtok( NULL, \"\\\\\" );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif( stricmp( ptr, \"HighCombo\" ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"**** 4\\n\" );\r\n\t\t\t\tptr = strtok( NULL, \"\\\\\" );\r\n\t\t\t\tif( ptr )\r\n\t\t\t\t{\r\n\t\t\t\t\tstats->m_bestcombo[index - 1] = atoi( ptr );\r\n\t\t\t\t\tDbg_Printf( \"**** 5 %d\\n\", stats->m_bestcombo[index -1 ] );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( index == ( vNUM_TRACKED_LEVELS - 1 ))\r\n\t\t{\r\n\t\t\tScript::RunScript( \"stats_retrieved\" );\r\n\t\t\tgamenet_man->mpStatsMan->m_state = vSTATS_STATE_LOGGED_IN;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tStatsMan::ScriptRetrievePersonalStats(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tint i;\r\n\r\n\tDbg_Printf( \"Requesting rating\\n\" );\r\n\tGetPersistDataValues( 0, gamenet_man->mpBuddyMan->GetProfile(), pd_public_ro, 0,\r\n\t\t\t\t\t\t\t  \"\\\\Rating\", s_stats_retrieval_callback, NULL );\r\n\tfor( i = 0; i < vNUM_TRACKED_LEVELS; i++ )\r\n\t{\r\n\t\tGetPersistDataValues( 0, gamenet_man->mpBuddyMan->GetProfile(), pd_public_ro, i + 1,\r\n\t\t\t\t\t\t\t\t  \"\\\\HighScore\\\\HighCombo\", s_stats_retrieval_callback, NULL );\r\n\t\t\r\n\t}\r\n\t\r\n\tgamenet_man->mpStatsMan->m_state = vSTATS_STATE_RETRIEVING;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tStatsMan::ScriptCleanUpTopStats(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tStatsMan* stats_man;\r\n\tScript::CArray *p_high_scores;\r\n\tint i;\r\n\r\n\tstats_man = gamenet_man->mpStatsMan;\r\n\tif( stats_man->m_need_to_retrieve_stats == true )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tfor( i = 0; i < vNUM_RATINGS_FILES; i++ )\r\n\t{\r\n\t\tstats_man->m_stats_keepers[i].Cleanup();\r\n\t}\r\n\tstats_man->m_need_to_retrieve_stats = true;\r\n\t \r\n\tp_high_scores = Script::GetArray(\"high_scores_array_all_time\");\r\n\tScript::CleanUpArray( p_high_scores );\r\n\tp_high_scores = Script::GetArray(\"best_combos_array_all_time\");\r\n\tScript::CleanUpArray( p_high_scores );\r\n\tp_high_scores = Script::GetArray(\"high_scores_array_monthly\");\r\n\tScript::CleanUpArray( p_high_scores );\r\n\tp_high_scores = Script::GetArray(\"best_combos_array_monthly\");\r\n\tScript::CleanUpArray( p_high_scores );\r\n\tp_high_scores = Script::GetArray(\"top_players_array\");\r\n\tScript::CleanUpArray( p_high_scores );\r\n\tp_high_scores = Script::GetArray(\"personal_stats_array\");\r\n\tScript::CleanUpArray( p_high_scores );\r\n\r\n\tghttpCleanup();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tStatsMan::ScriptGetRank(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tStatsMan* stats_man;\r\n\tint rank, rating;\r\n\t \r\n\tstats_man = gamenet_man->mpStatsMan;\r\n\trating = stats_man->m_stats.GetRating();\r\n\trank = (int) (((float) rating / (float) vMAX_RATING ) * (float) vMAX_RANK );\r\n\tpScript->GetParams()->AddInteger( CRCD(0x7786171a,\"rank\"), rank ); \r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tStatsMan::ScriptFillStatsArrays(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t//Script::CArray *p_high_scores;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tStatsMan* stats_man;\r\n\tuint32 array;\r\n\t \r\n\tstats_man = gamenet_man->mpStatsMan;\r\n\r\n\tpParams->GetChecksum( CRCD(0x5ef31148,\"array\"), &array, true );\r\n\tDbg_Printf( \"Array 0x%x\\n\", array );\r\n\tswitch( array )\r\n\t{\r\n\t\tcase 0xcb95928f:\t//high_scores_array_monthly\r\n\t\t\tstats_man->m_stats_keepers[vFILE_HIGH_SCORE_MONTHLY].FillSectionedMenu();\r\n\t\t\tstats_man->m_stats_keepers[vFILE_HIGH_SCORE_MONTHLY].FillMenu();\r\n\t\t\tbreak;\r\n\t\tcase 0x67f1ae8a:\t//best_combos_array_monthly\r\n\t\t\tstats_man->m_stats_keepers[vFILE_BEST_COMBO_MONTHLY].FillSectionedMenu();\r\n\t\t\tstats_man->m_stats_keepers[vFILE_BEST_COMBO_MONTHLY].FillMenu();\r\n\t\t\tbreak;\r\n\t\tcase 0x5299291b: \t//top_players_array\r\n\t\t\tDbg_Printf( \"Filling top players menu\\n\" );\r\n\t\t\tstats_man->m_stats_keepers[vFILE_RATINGS].FillMenu( true );\r\n\t\t\tbreak;\r\n\t\tcase 0xef20d3a1:\t//high_scores_array_all_time\r\n\t\t\tstats_man->m_stats_keepers[vFILE_HIGH_SCORE_ALL_TIME].FillSectionedMenu();\r\n\t\t\tstats_man->m_stats_keepers[vFILE_HIGH_SCORE_ALL_TIME].FillMenu();\r\n\t\t\tbreak;\r\n\t\tcase 0x9fe64312:\t//best_combos_array_all_time\r\n\t\t\tstats_man->m_stats_keepers[vFILE_BEST_COMBO_ALL_TIME].FillSectionedMenu();\r\n\t\t\tstats_man->m_stats_keepers[vFILE_BEST_COMBO_ALL_TIME].FillMenu();\r\n\t\t\tbreak;\r\n\t\tcase 0xfef84fff:\t//personal_stats_array\r\n\t\t\tstats_man->m_stats.FillMenu();\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tStatsMan::ScriptRetrieveTopStats(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tStatsMan* stats_man;\r\n\tDownloadContext context;\r\n\tint file_index;\r\n\r\n\tstats_man = gamenet_man->mpStatsMan;\r\n\r\n\tfile_index = 0;\r\n\tif( pParams->GetInteger( CRCD(0x7360c9ef,\"file\"), &file_index ))\r\n\t{\r\n\t\tstats_man->m_cur_file_index = file_index;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tstats_man->m_cur_file_index++;\r\n\t}\r\n    \r\n\tsprintf( context.m_path, \"http://%s/thug/%s\", SSHOST, s_stats_files[stats_man->m_cur_file_index] );\r\n\tcontext.m_file_not_found_script = CRCD(0x1c049404,\"StatsRetrievalFailed\");\r\n\tcontext.m_transfer_failed_script = CRCD(0x1c049404,\"StatsRetrievalFailed\");\r\n\tcontext.m_update_progress_script = CRCD(0x74e0cd35,\"do_nothing\");\r\n\tcontext.m_max_size = vMAX_STATS_FILE_SIZE;\r\n\r\n\tif( stats_man->m_cur_file_index == ( vNUM_RATINGS_FILES - 1 ))\r\n\t{\r\n\t\tcontext.m_transfer_complete_script = CRCD(0x7346e8e7,\"stats_retrieval_complete\");\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcontext.m_transfer_complete_script = CRCD(0xd932b07b,\"download_more_stats\");\r\n\t}\r\n\t\r\n\tcontext.m_dl_complete = s_stats_file_dl_complete;\r\n\r\n\tgamenet_man->mpContentMan->DownloadFile( &context );\r\n\r\n\tstats_man->m_need_to_retrieve_stats = false;\r\n\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tStatsMan::ScriptNeedToRetrieveTopStats(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tStatsMan* stats_man;\r\n\t\r\n\tstats_man = gamenet_man->mpStatsMan;\r\n\treturn stats_man->NeedToRetrieveStats();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStatsMan::StartNewGame( void )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tScript::CScriptStructure* pStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tconst char* server_name, *challenge;\r\n\tint score_limit, time_limit;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo* player;\r\n\tNet::Server* server;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\tm_cur_game = NewGame( 1 );\r\n\tchallenge = GetChallenge( m_cur_game );\r\n\tserver = gamenet_man->GetServer();\r\n\tDbg_Assert( server != NULL );\r\n\r\n\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"server_name\") );\r\n\tpStructure->GetText( \"ui_string\", &server_name, true );\r\n\r\n\ttime_limit = pPreferences->GetPreferenceValue( Script::GenerateCRC(\"time_limit\"), Script::GenerateCRC(\"time\") );\r\n\tscore_limit = pPreferences->GetPreferenceValue( Script::GenerateCRC(\"target_score\"), Script::GenerateCRC(\"score\") );\r\n\r\n    BucketStringOp( m_cur_game, \"hostname\", bo_set, (char*) server_name, bl_server, 0 );\r\n\tBucketStringOp( m_cur_game, \"mapname\", bo_set, gamenet_man->GetLevelName(), bl_server, 0 );\r\n\tBucketStringOp( m_cur_game, \"gametype\", bo_set, gamenet_man->GetGameModeName(), bl_server, 0 );\r\n\tBucketIntOp( m_cur_game, \"mapcrc\", bo_set, gamenet_man->GetNetworkLevelId(), bl_server, 0 );\r\n\tBucketIntOp( m_cur_game, \"gametypecrc\", bo_set, gamenet_man->GetGameTypeFromPreferences(), bl_server, 0 );\r\n\tBucketIntOp( m_cur_game, \"maxplayers\", bo_set, gamenet_man->GetMaxPlayers(), bl_server, 0 );\r\n\tBucketIntOp( m_cur_game, \"timelimit\", bo_set, time_limit, bl_server, 0 );\r\n\tBucketIntOp( m_cur_game, \"fraglimit\", bo_set, score_limit, bl_server, 0 );\r\n\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t{\r\n\t\tchar key_name[64];\r\n\t\tNet::MsgDesc msg;\r\n\t\tuint32 id;\r\n\r\n\t\tid = player->m_Skater->GetID();\r\n\r\n\t\tNewPlayer( m_cur_game, id, player->m_Name );\r\n\t\t\r\n\t\tsprintf( key_name, \"player\" );\r\n\t\tBucketStringOp( m_cur_game, key_name, bo_set, player->m_Name, bl_player, id );\r\n\t\tsprintf( key_name, \"pid\" );\r\n\t\tBucketIntOp( m_cur_game, key_name, bo_set, player->m_Profile, bl_player, id );\r\n\r\n\t\tif( player->m_Profile > 0 )\r\n\t\t{\r\n\t\t\tmsg.m_Data = (char*) challenge;\r\n\t\t\tmsg.m_Length = strlen( challenge ) + 1;\r\n\t\t\tmsg.m_Id = GameNet::MSG_ID_CHALLENGE;\r\n\t\t\tmsg.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\r\n\t\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg );\r\n\t\t}\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \tStatsMan::ReportStats( bool final )\r\n{\r\n\tint result, cheating_occurred;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo* player;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tif( m_cur_game == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t{\r\n\t\tuint32 id;\r\n\t\tMdl::Score* score_obj;\r\n\t\t\t\t\r\n\t\tObj::CSkaterScoreComponent* p_skater_score_component = GetSkaterScoreComponentFromObject( player->m_Skater );\r\n\t\tDbg_Assert(p_skater_score_component);\r\n\t\r\n\t\tscore_obj = p_skater_score_component->GetScore();\r\n\r\n\t\tid = player->m_Skater->GetID();\r\n\t\t\r\n        BucketIntOp( m_cur_game, \"score\", bo_set, gamenet_man->GetPlayerScore( id ), bl_player, id );\r\n\t\tDbg_Printf( \"**** PLAYER %d, Best combo: %d\\n\", player->m_Skater->GetID(), player->m_BestCombo );\r\n\t\tBucketIntOp( m_cur_game, \"combo\", bo_set, player->m_BestCombo, bl_player, id );\r\n\t}\r\n\r\n\t// 'highscore' will really means 'cheats', but we don't want to give hackers any hints. \r\n\t// It is meant to be misleading.\r\n\tcheating_occurred = g_CheatsEnabled | gamenet_man->HasCheatingOccurred();\r\n\tBucketIntOp( m_cur_game, \"highscore\", bo_set, cheating_occurred, bl_server, 0 );\r\n    result = SendGameSnapShot( m_cur_game, NULL, (int) final );\r\n\t\r\n\tswitch( result )\r\n\t{\r\n\t\tcase GE_DATAERROR: \t// If game is NULL and the last game created by NewGame failed (because the connection was lost and disk logging is disabled)\r\n\t\t\tDbg_Printf( \"Error sending stats\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GE_NOCONNECT: // If the connection is lost and disk logging is disabled\r\n\t\t\tDbg_Printf( \"Error sending stats : No connect\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GE_NOERROR: //The update was sent, or disk logging is enabled and the game was logged\r\n\t\t\tDbg_Printf( \"Sent stats\\n\" );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif( final )\r\n\t{\r\n\t\tEndGame();\r\n\t}\r\n\r\n\tm_time_since_last_report = Tmr::GetTime();\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStatsMan::EndGame( void )\r\n{\r\n\tm_state = vSTATS_STATE_LOGGED_IN;\r\n\tif( m_cur_game )\r\n\t{\r\n\t\tFreeGame( m_cur_game );\r\n\t\tm_cur_game = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStatsMan::PlayerLeft( int id )\r\n{\r\n\tif( m_state == vSTATS_STATE_IN_GAME )\r\n\t{\r\n\t\tRemovePlayer( m_cur_game, id );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\tStatsMan::GenerateAuthResponse( char* challenge, char* password, char* response )\r\n{\r\n\treturn GenerateAuth( challenge, password, response );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStatsMan::AuthorizePlayer( int id, char* response )\r\n{\r\n\tchar key_name[64];\r\n\r\n\tsprintf( key_name, \"auth\" );\r\n\tBucketStringOp( m_cur_game, key_name, bo_set, response, bl_player, id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStats*\tStatsMan::GetStats( void )\r\n{\r\n\treturn &m_stats;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\tStatsMan::GetLevelName( uint32 level_crc )\r\n{\r\n\tint i;\r\n\tScript::CArray* pArray = Script::GetArray(\"stats_level_names\");\r\n\tDbg_Assert( pArray );\r\n\r\n\tfor( i = 0; i < (int)pArray->GetSize(); i++ )\r\n\t{   \r\n\t\tuint32 checksum;\r\n\t\tScript::CStruct* pStructure = pArray->GetStructure( i );\r\n\t\tDbg_Assert( pStructure );\r\n\r\n        pStructure->GetChecksum( \"level\", &checksum );\r\n\t\tif( level_crc == checksum )\r\n\t\t{\r\n\t\t\tconst char* level_name;\r\n\r\n\t\t\tpStructure->GetText( \"text\", &level_name, true );\r\n\t\t\treturn (char *) level_name;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStats::Stats( void )\r\n{\r\n\tm_rating = 0;\r\n\tmemset( m_highscore, 0, sizeof( uint32 ) * vNUM_TRACKED_LEVELS );\r\n\tmemset( m_bestcombo, 0, sizeof( uint32 ) * vNUM_TRACKED_LEVELS );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tStats::GetRating( void )\r\n{\r\n\treturn m_rating;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tStats::GetHighScore( uint32 level )\r\n{\r\n\tint i;\r\n\r\n\tfor( i = 0; i < vNUM_TRACKED_LEVELS; i++ )\r\n\t{\r\n\t\tif( level == s_levels[i] )\r\n\t\t{\r\n\t\t\treturn m_highscore[i];\r\n\t\t}\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tStats::GetBestCombo( uint32 level )\r\n{\r\n\tint i;\r\n\r\n\tfor( i = 0; i < vNUM_TRACKED_LEVELS; i++ )\r\n\t{\r\n\t\tif( level == s_levels[i] )\r\n\t\t{\r\n\t\t\treturn m_bestcombo[i];\r\n\t\t}\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStats::FillMenu( void )\r\n{\r\n\tLst::Search< SortableStats > sh;\r\n\tSortableStats* p_stats, *next;\r\n\tLst::Head< SortableStats > stat_list;\r\n\tint i, count, num_items;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tStatsMan* stats_man;\r\n\r\n\tstats_man = gamenet_man->mpStatsMan;\r\n\r\n\tnum_items = 0;\r\n\tfor( i = 0; i < vNUM_TRACKED_LEVELS; i++ )\r\n\t{\r\n\t\tif( m_highscore[i] > 0 )\r\n\t\t{\r\n\t\t\tp_stats = new SortableStats;\r\n\t\t\tp_stats->SetPri( m_highscore[i] );\r\n\t\t\tp_stats->m_Score = m_highscore[i];\r\n\t\t\tp_stats->m_Level = s_levels[i];\r\n\r\n\t\t\tstat_list.AddNode( p_stats );\r\n\t\t\tnum_items++;\r\n\t\t}\r\n\t}\r\n\r\n\tcount = 0;\r\n\tfor( p_stats = sh.FirstItem( stat_list ); p_stats; p_stats = sh.NextItem())\r\n\t{\r\n\t\tScript::CStruct* p_entry;\r\n\t\t\t\r\n\t\tp_entry = new Script::CStruct;\r\n\t\tp_entry->AddInteger( \"score\", p_stats->m_Score );\r\n\t\tp_entry->AddString( \"level\", stats_man->GetLevelName( p_stats->m_Level ));\r\n\r\n        Script::RunScript( CRCD(0xa6111f30,\"add_stat_personal_menu_item\"), p_entry );\r\n\t\t//Script::RunScript( CRCD(0xac09e3b,\"add_stat_player_menu_item\"), p_entry );\r\n\t}\r\n\tfor( p_stats = sh.FirstItem( stat_list ); p_stats; p_stats = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tdelete p_stats;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStatsPlayer::StatsPlayer( void )\r\n: Lst::Node< StatsPlayer > ( this )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStatsLevel::StatsLevel( void )\r\n: Lst::Node< StatsLevel > ( this )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStatsLevel::~StatsLevel( void )\r\n{\r\n\tLst::Search< StatsPlayer > sh;\r\n\tStatsPlayer* player, *next;\r\n\r\n\tfor( player = sh.FirstItem( m_Players ); player; player = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tdelete player;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tStatsKeeper::NumEntries( int max_entries_per_level )\r\n{\r\n\tint num_entries;\r\n\tLst::Search< StatsLevel > sh;\r\n\tLst::Search< StatsPlayer > player_sh;\r\n\tStatsLevel* level;\r\n\tStatsPlayer* player;\r\n    \r\n\tnum_entries = 0;\r\n\tfor( level = sh.FirstItem( m_Levels ); level; level = sh.NextItem())\r\n\t{\r\n\t\tnum_entries += ( (int) level->m_Players.CountItems() > max_entries_per_level ) ? \r\n\t\t\t\t\t\t\tmax_entries_per_level : level->m_Players.CountItems();\r\n\t}\r\n\r\n\tfor( player = player_sh.FirstItem( m_Players ); player; player = player_sh.NextItem())\r\n\t{\r\n\t\tnum_entries++;\r\n\t}\r\n\r\n\treturn num_entries;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStatsKeeper::FillSectionedMenu( void )\r\n{\r\n\tint rank, count, num_items;\r\n\tLst::Search< StatsLevel > sh;\r\n\tLst::Search< StatsPlayer > player_sh;\r\n\tStatsLevel* level;\r\n\tStatsPlayer* player;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tStatsMan* stats_man;\r\n\tScript::CStruct* p_header;\r\n\r\n\tstats_man = gamenet_man->mpStatsMan;\r\n\tnum_items = NumEntries( vMAX_ENTRIES_PER_LEVEL );\r\n\tcount = 0;\r\n\t\r\n\tDbg_Printf( \"*** Filling sectioned menu\\n\" );\r\n\tfor( level = sh.FirstItem( m_Levels ); level; level = sh.NextItem())\r\n\t{\r\n\t\tint player_count;\r\n\r\n\t\tif( level->m_Players.CountItems() > 0)\r\n\t\t{\r\n\t\t\tScript::CStruct* p_level_entry;\r\n\r\n\t\t\tp_level_entry = new Script::CStruct;\r\n\t\t\tp_level_entry->AddString( \"text\", stats_man->GetLevelName( level->m_Level ));\r\n\t\t\tScript::RunScript( CRCD(0x1aadee21,\"add_stat_header_menu_item\"), p_level_entry );\r\n\r\n\t\t\tdelete p_level_entry;\r\n\t\t}\r\n\t\t\r\n\r\n\t\tplayer_count = 0;\r\n\t\tfor( player = player_sh.FirstItem( level->m_Players ); player; player = player_sh.NextItem())\r\n\t\t{\r\n\t\t\tScript::CStruct* p_entry;\r\n\t\t\t\r\n\t\t\tif( player_count >= vMAX_ENTRIES_PER_LEVEL )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tp_entry = new Script::CStruct;\r\n\t\t\tp_entry->AddInteger( \"rating\", player->m_Rating );\r\n\t\t\tp_entry->AddInteger( \"score\", player->m_Score );\r\n\t\t\trank = (int) (((float) player->m_Rating / (float) vMAX_RATING ) * (float) vMAX_RANK );\r\n\t\t\tp_entry->AddInteger( \"rank\", rank );\r\n\t\t\tp_entry->AddString( \"name\", player->m_Name );\r\n\t\t\tp_entry->AddString( \"level\", stats_man->GetLevelName( level->m_Level ));\r\n\r\n\t\t\tScript::RunScript( CRCD(0x19f7bc28,\"add_stat_score_menu_item\"), p_entry );\r\n\t\t\t\r\n\t\t\tdelete p_entry;\r\n\r\n\t\t\tplayer_count++;\r\n\t\t}\r\n\t}\r\n\r\n    p_header = new Script::CStruct;\r\n\tp_header->AddString( \"text\", Script::GetLocalString( CRCD(0xc2283319,\"category_all_levels\")));\r\n\tScript::RunScript( CRCD(0x1aadee21,\"add_stat_header_menu_item\"), p_header );\r\n\tdelete p_header;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStatsKeeper::FillMenu( bool just_ratings )\r\n{\r\n\tint rank;\r\n\tLst::Search< StatsLevel > sh;\r\n\tLst::Search< StatsPlayer > player_sh;\r\n\tStatsLevel* level;\r\n\tStatsPlayer* player;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tStatsMan* stats_man;\r\n\tSortableStats* p_stats, *next;\r\n\tLst::Head< SortableStats > stat_list;\r\n\tLst::Search< SortableStats > stats_sh;\r\n\tint count;\r\n\r\n\tstats_man = gamenet_man->mpStatsMan;\r\n\tif( just_ratings )\r\n\t{\r\n\t\tfor( player = player_sh.FirstItem( m_Players ); player; player = player_sh.NextItem())\r\n\t\t{\r\n\t\t\tp_stats = new SortableStats;\r\n\t\t\tp_stats->SetPri( player->m_Rating );\r\n\t\t\tp_stats->m_Score = player->m_Score;\r\n\t\t\tp_stats->m_Rating = player->m_Rating;\r\n\t\t\tstrcpy( p_stats->m_Name, player->m_Name );\r\n\t\t\r\n\t\t\tstat_list.AddNode( p_stats );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor( level = sh.FirstItem( m_Levels ); level; level = sh.NextItem())\r\n\t\t{\r\n\t\t\tfor( player = player_sh.FirstItem( level->m_Players ); player; player = player_sh.NextItem())\r\n\t\t\t{\r\n\t\t\t\tp_stats = new SortableStats;\r\n\t\t\t\tp_stats->SetPri( player->m_Score );\r\n\t\t\t\tp_stats->m_Score = player->m_Score;\r\n\t\t\t\tp_stats->m_Level = level->m_Level;\r\n\t\t\t\tp_stats->m_Rating = player->m_Rating;\r\n\t\t\t\tstrcpy( p_stats->m_Name, player->m_Name );\r\n\t\t\t\r\n\t\t\t\tstat_list.AddNode( p_stats );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\t\t\r\n\tcount = 0;\r\n\tfor( p_stats = stats_sh.FirstItem( stat_list ); p_stats; p_stats = stats_sh.NextItem())\r\n\t{\r\n\t\tScript::CStruct* p_entry;\r\n\r\n\t\tif(( p_stats->m_Score == 0 ) || ( count == vSTATS_PLAYER_COUNT ))\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tp_entry = new Script::CStruct;\r\n\t\tp_entry->AddInteger( \"rating\", p_stats->m_Rating );\r\n\t\tp_entry->AddInteger( \"score\", p_stats->m_Score );\r\n\t\trank = (int) (((float) p_stats->m_Rating / (float) vMAX_RATING ) * (float) vMAX_RANK );\r\n\t\tp_entry->AddInteger( \"rank\", rank );\r\n\t\tp_entry->AddString( \"name\", p_stats->m_Name );\r\n\r\n\t\tif( just_ratings )\r\n\t\t{\r\n\t\t\tScript::RunScript( CRCD(0xac09e3b,\"add_stat_player_menu_item\"), p_entry );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_entry->AddString( \"level\", stats_man->GetLevelName( p_stats->m_Level ));\r\n\t\t\tScript::RunScript( CRCD(0x19f7bc28,\"add_stat_score_menu_item\"), p_entry );\r\n\t\t}\r\n\t\tdelete p_entry;\r\n\t\tcount++;\r\n\t}\r\n\r\n\tfor( p_stats = stats_sh.FirstItem( stat_list ); p_stats; p_stats = next )\r\n\t{\r\n\t\tnext = stats_sh.NextItem();\r\n\t\tdelete p_stats;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tStatsKeeper::Cleanup( void )\r\n{\r\n\tLst::Search< StatsLevel > sh;\r\n\tLst::Search< StatsPlayer > player_sh;\r\n\tStatsLevel* level, *next;\r\n\tStatsPlayer* player, *next_player;\r\n\r\n\tfor( level = sh.FirstItem( m_Levels ); level; level = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tdelete level;\r\n\t}\r\n\r\n\tfor( player = player_sh.FirstItem( m_Players ); player; player = next_player )\r\n\t{\r\n\t\tnext_player = player_sh.NextItem();\r\n\t\tdelete player;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSortableStats::SortableStats( void )\r\n: Lst::Node< SortableStats > ( this )\r\n{\r\n\tm_Score = 0;\r\n\tm_Level = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/p_stats.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate5\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_stats.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t04/30/03\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPS2 Stat-tracking code \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GAMENET_NGPS_P_STATS_H\r\n#define __GAMENET_NGPS_P_STATS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gstats/gstats.h>\r\n#include <gstats/gpersist.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define vNUM_TRACKED_LEVELS\t12\r\n\r\nnamespace GameNet\r\n{\r\n\t\r\nenum\r\n{\r\n\tvFILE_HIGH_SCORE_ALL_TIME,\r\n\tvFILE_BEST_COMBO_ALL_TIME,\r\n\tvFILE_HIGH_SCORE_MONTHLY,\r\n\tvFILE_BEST_COMBO_MONTHLY,\r\n\tvFILE_RATINGS,\r\n\tvNUM_RATINGS_FILES\r\n};\r\n\r\nenum\r\n{\r\n\tvSTATS_STATE_WAITING,\r\n\tvSTATS_STATE_CONNECTING,\r\n\tvSTATS_STATE_CONNECTED,\r\n\tvSTATS_STATE_FAILED_LOG_IN,\r\n\tvSTATS_STATE_LOGGED_IN,\r\n\tvSTATS_STATE_RETRIEVING,\r\n\tvSTATS_STATE_IN_GAME,\r\n};\r\n\r\n\r\nclass Stats\r\n{\r\n\tfriend class StatsMan;\r\n\r\npublic:\r\n\tStats( void );\r\n\r\n\tint\t\tGetRating( void );\r\n\tint\t\tGetHighScore( uint32 level );\r\n\tint\t\tGetBestCombo( uint32 level );\r\n\r\n\tvoid\tFillMenu( void );\r\nprivate:\r\n\tint\t\tm_rating;\r\n\tuint32\tm_highscore[vNUM_TRACKED_LEVELS];\r\n\tuint32\tm_bestcombo[vNUM_TRACKED_LEVELS];\r\n};\r\n\r\nclass StatsPlayer : public Lst::Node< StatsPlayer >\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvMAX_STATS_PLAYER_NAME_LEN = 32\r\n\t};\r\n\tStatsPlayer( void );\r\n\t\r\n\tchar\tm_Name[vMAX_STATS_PLAYER_NAME_LEN];\r\n\tuint32\tm_Rating;\r\n\tuint32\tm_Score;\r\n};\r\n\r\nclass StatsLevel : public Lst::Node< StatsLevel >\r\n{\r\npublic:\r\n\tStatsLevel( void );\r\n\t~StatsLevel( void );\r\n\r\n\tuint32\t\tm_Level;\r\n\tLst::Head< StatsPlayer >\tm_Players;\r\n};\r\n\r\nclass StatsKeeper \r\n{\r\npublic:\r\n\t\r\n\tvoid\tCleanup( void );\r\n\tint\t\tNumEntries( int max_entries_per_level );\r\n\tvoid\tFillMenu( bool just_ratings = false );\r\n\tvoid\tFillSectionedMenu( void );\r\n\t\r\n\tLst::Head< StatsLevel > \tm_Levels;\r\n\tLst::Head< StatsPlayer > \tm_Players;\r\n\tchar\tm_Date[32];\r\n};\r\n\r\nclass StatsMan\r\n{\r\npublic:\r\n\tStatsMan( void );\r\n\t~StatsMan( void );\r\n\r\n\tvoid\tConnect( void );\r\n\tvoid\tDisconnect( void );\r\n\tvoid\tConnected( void );\r\n\tbool\tIsLoggedIn( void );\r\n\tbool\tNeedToRetrieveStats( void );\r\n\tchar*\tGetLevelName( uint32 level_crc );\r\n\r\n\tvoid\tStartNewGame( void );\r\n\tvoid\tReportStats( bool final );\r\n\tchar*\tGenerateAuthResponse( char* challenge, char* password, char* response );\r\n\tvoid\tAuthorizePlayer( int id, char* response );\r\n\tvoid\tPlayerLeft( int id );\r\n\tvoid\tEndGame( void );\r\n\tStats*\tGetStats( void );\r\n\r\n\tstatic\tbool\t\tScriptStatsLoggedIn(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptStatsLogOff(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptStatsLogIn(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptReportStats(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptRetrievePersonalStats(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptRetrieveTopStats(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptNeedToRetrieveTopStats(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptCleanUpTopStats(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptFillStatsArrays(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tstatic\tbool\t\tScriptGetRank(Script::CStruct *pParams, Script::CScript *pScript);\r\n    \r\nprivate:\r\n\tstatic\tvoid s_threaded_stats_connect( StatsMan* stats_man );\r\n\tstatic\tvoid s_stats_retrieval_callback(int localid, int profileid, persisttype_t type, \r\n\t\t\t\t\t\t\t\t\t\t\tint index, int success, char *data, int len, \r\n\t\t\t\t\t\t\t\t\t\t\tvoid *instance );\r\n\tstatic\tGHTTPBool s_stats_file_dl_complete(\tGHTTPRequest request,       // The request.\r\n\t\t\t\t\t\t\t\t\t\t\tGHTTPResult result,         // The result (success or an error).\r\n\t\t\t\t\t\t\t\t\t\t\tchar* buffer,              // The file's bytes (only valid if ghttpGetFile[Ex] was used).\r\n\t\t\t\t\t\t\t\t\t\t\tint buffer_len,              // The file's length.\r\n\t\t\t\t\t\t\t\t\t\t\tvoid * param                // User-data.\r\n\t\t\t\t\t\t\t\t\t\t\t);\r\n\r\n\tvoid\tparse_score_list( int type, char* buffer, bool read_date );\r\n\tvoid\tparse_ratings( char* buffer );\r\n\r\n\tTsk::Task< StatsMan >*\t\t\t\t\tm_stats_logic_task;\r\n\tstatic\tTsk::Task< StatsMan >::Code   \ts_stats_logic_code;\r\n\r\n\tbool\t\tm_logged_in;\r\n\tint\t\t\tm_state;\r\n\tstatsgame_t\tm_cur_game;\r\n\tTmr::Time\tm_time_since_last_report;\r\n\tStats\t\tm_stats;\r\n\r\n\tint\t\t\tm_cur_file_index;\r\n\tStatsKeeper\tm_stats_keepers[vNUM_RATINGS_FILES];\r\n\tbool\t\tm_need_to_retrieve_stats;\r\n};\r\n\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n#endif\t// __GAMENET_NGPS_P_STATS_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Ngps/snglue.cpp",
    "content": "/****************************************************************************/\r\n/*                                                                          */\r\n/* Copyright SN Systems Ltd 2003                                            */\r\n/*                                                                          */\r\n/* File:        netglue_sneebsd.c                                           */\r\n/* Version:     1.01                                                        */\r\n/* Description: Netglue implementation file for SN NDK EE BSD API           */\r\n/*                                                                          */\r\n/* Change History:                                                          */\r\n/* Vers Date        Author     Changes                                      */\r\n/* 1.00 19-May-2003 D.Lowther  File Created (for use with DNAS - LN 13419)  */\r\n/* 1.01 02-Jun-2003 D.Lowther  Fixed bug in sceNetGlueSocket() where it was */\r\n/*                             checking for iRetval == 0, should be > 0     */\r\n/*                                                                          */\r\n/*                                                                          */\r\n/****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <stdio.h>\r\n#include <eetypes.h>\r\n#include <eekernel.h>\r\n#include <snsocket.h>\r\n#include <libgraph.h>\r\n#include <string.h>\r\n\r\n/****************************************************************************/\r\n/* Stuff that should come from netglue header files but including netglue.h */\r\n/* causes clashes with snsocket.h                                           */\r\n/****************************************************************************/\r\n\r\nextern \"C\" {\r\n\r\ntypedef long ssize_t;\r\n\r\ntypedef u_char sceNetGlueSaFamily_t;\r\ntypedef u_int  sceNetGlueSocklen_t;\r\n\r\n#define sa_family_t sceNetGlueSaFamily_t\r\n#define socklen_t   sceNetGlueSocklen_t\r\n\r\ntypedef struct sceNetGlueSockaddr \r\n{\r\n    u_char      sa_len;\r\n    sa_family_t sa_family;\r\n    char        sa_data[14];\r\n} sceNetGlueSockaddr_t;\r\n\r\ntypedef struct sceNetGlueHostent\r\n{\r\n    char    *h_name;\r\n    char    **h_aliases;\r\n    int     h_addrtype;\r\n    int     h_length;\r\n    char    **h_addr_list;\r\n#define h_addr h_addr_list[0]\r\n} sceNetGlueHostent_t;\r\n\r\ntypedef struct sceNetGlueInAddr \r\n{\r\n    u_int s_addr;\r\n} sceNetGlueInAddr_t;\r\n\r\n/****************************************************************************/\r\n/* The netglue error codes in the 2.7 lib ref are wrong, Sony's advice is   */\r\n/* to use the values from ee/gcc/ee/include/sys/errno.h, but I can't        */\r\n/* include that file in here because of clashes with the same names in      */ \r\n/* snsocket.h                                                               */ \r\n/* So the following values are copied / pasted from the above errno.h file  */\r\n/* and I've stuck NG_ on the front of the names, they are listed in the     */\r\n/* same order as in the 2.7 lib ref for netglue (not numerical order)       */\r\n/****************************************************************************/\r\n\r\n#define NG_EBADF           9 /* Invalid descriptor specified                */\r\n#define NG_ENOMEM         12 /* Insufficient memory                         */\r\n#define NG_EBUSY          16 /* Library not yet available (before           */\r\n                             /* initialization completes, etc.)             */\r\n#define NG_EINVAL         22 /* Invalid arguments specified                 */\r\n#define NG_EPROTOTYPE    107 /* Unsupported protocol type specified         */\r\n#define NG_EOPNOTSUPP     95 /* Invalid call for socket                     */\r\n#define NG_EPFNOSUPPORT   96 /* Unsupported protocol family specified       */\r\n#define NG_EAFNOSUPPORT  106 /* Specified address family is an unsupported  */\r\n                             /* value for the socket protocol family        */\r\n#define NG_EADDRINUSE    112 /* Tried to bind to port already bound         */\r\n#define NG_EADDRNOTAVAIL 125 /* Invalid address specified                   */\r\n#define NG_ENETDOWN      115 /* Interface is down                           */\r\n#define NG_EHOSTUNREACH  118 /* Network is unreachable                      */\r\n#define NG_ECONNABORTED  113 /* Aborted by call to sceGlueAbort()           */\r\n#define NG_ECONNRESET    104 /* Connection was reset                        */\r\n#define NG_EISCONN       127 /* Specified connection has already been made  */\r\n#define NG_ENOTCONN      128 /* Specified connection does not exist         */\r\n#define NG_ETIMEDOUT     116 /* Timeout                                     */\r\n#define NG_ECONNREFUSED  111 /* Connection request was refused              */\r\n\r\n/* NDK can return other error codes e.g to indicate problems with the       */\r\n/* comms between the EE and IOP, where there isn't an obvious map from NDK  */\r\n/* to Netglue error code, I'll use NG_UNSPECIFIED                           */ \r\n\r\n#define NG_UNSPECIFIED    NG_EINVAL /* Don't know what else to use          */\r\n\r\n/****************************************************************************/\r\n/* Netglue error codes for DNS operations from netdb.h + NG_ on front       */\r\n/****************************************************************************/\r\n\r\n#define NG_NETDB_INTERNAL -1 /* see errno */\r\n#define NG_NETDB_SUCCESS  0  /* no problem */\r\n#define NG_HOST_NOT_FOUND 1  /* Authoritative Answer Host not found */\r\n#define NG_TRY_AGAIN      2  /* Non-Authoritative Host not found, or SERVERFAIL */\r\n#define NG_NO_RECOVERY    3  /* Non recoverable errs, FORMERR, REFUSED, NOTIMP */\r\n#define NG_NO_DATA        4  /* Valid name, no data record of requested type */\r\n#define\tNG_NO_ADDRESS   NG_NO_DATA /* no address, look for MX record */\r\n\r\n\r\n/****************************************************************************/\r\n/* Private data / types                                                     */\r\n/****************************************************************************/\r\n\r\n/* Absolute maximum number of EE threads which may use EE socket API */\r\n#define ABS_MAX_THREADS      10\r\n\r\n/* Structure to hold info for each thread using this netglue API */\r\n\r\ntypedef struct snNetGlueThreadInfo \r\n{\r\n    int                 iErrno;\r\n    int                 iHerrno;\r\n    int                 iThreadId;\r\n    sceNetGlueHostent_t NetGlueHostent;\r\n    /* Following are for sceNetGlueGethostbyaddr */\r\n    sn_uint32           *sn_h_addr_list[2]; /* one plus null terminator */\r\n    sn_uint32           sn_h_addr;          /* above [0] points to this */\r\n} snNetGlueThreadInfo_t;\r\n\r\n/* Array to hold info for all the threads using this netglue API */\r\n/* An element is 'free' if it's iThreadId is zero                */\r\n\r\nstatic snNetGlueThreadInfo_t s_ThreadInfo[ABS_MAX_THREADS] =\r\n\r\n{{ 0, 0, 0, {0,0,0,0,0}, {0,0}, 0},\r\n { 0, 0, 0, {0,0,0,0,0}, {0,0}, 0}, \r\n { 0, 0, 0, {0,0,0,0,0}, {0,0}, 0},\r\n { 0, 0, 0, {0,0,0,0,0}, {0,0}, 0},\r\n { 0, 0, 0, {0,0,0,0,0}, {0,0}, 0},\r\n { 0, 0, 0, {0,0,0,0,0}, {0,0}, 0},\r\n { 0, 0, 0, {0,0,0,0,0}, {0,0}, 0},\r\n { 0, 0, 0, {0,0,0,0,0}, {0,0}, 0},\r\n { 0, 0, 0, {0,0,0,0,0}, {0,0}, 0},\r\n { 0, 0, 0, {0,0,0,0,0}, {0,0}, 0}};\r\n\r\n/****************************************************************************/\r\n/* Private functions                                                        */\r\n/****************************************************************************/\r\n\r\n/****************************************************************************/\r\n/* Private functions - for accessing s_ThreadInfo                           */\r\n/****************************************************************************/\r\n\r\nstatic int snGetThreadInfoIndexForThreadId(int iThreadId)\r\n{\r\n\r\n    /* Searches s_ThreadInfo[].iThreadId for a match with iThreadId         */\r\n    /* If match found returns index in s_ThreadInfo, else returns -1        */\r\n\r\n    int i;\r\n\r\n    for (i=0; i<ABS_MAX_THREADS; i++)\r\n    {\r\n        if (s_ThreadInfo[i].iThreadId == iThreadId)\r\n        {\r\n            return i;\r\n        }\r\n    }\r\n\r\n    return -1;\r\n}\r\n\r\nstatic int snGetThreadInfoIndexFreeEntry(void)\r\n{\r\n    /* Searches s_ThreadInfo[].iThreadId for iThreadId == 0 (free entry)    */\r\n    /* If free entry found returns index in s_ThreadInfo, else returns -1   */\r\n\r\n    int iRetval;\r\n\r\n    iRetval = snGetThreadInfoIndexForThreadId(0);\r\n\r\n    return iRetval;\r\n}\r\n\r\nstatic int snAddToThreadInfo(int iThreadId)\r\n{\r\n    /* Checks that iThreadId is not already stored in s_ThreadInfo, then    */\r\n    /* looks for a free entry and stores it in there.                       */\r\n    /* If there is no space to store iThreadId, returns -1, else returns    */\r\n    /* the index where iThreadId is stored in s_ThreadInfo                  */\r\n\r\n    int iInterruptsWereEnabled;\r\n    int iThreadInfoIndex;\r\n\r\n    /* Do this with interrupts disabled to serialise access */\r\n    iInterruptsWereEnabled = DI();\r\n\r\n    /* If this thread is already registered print a warning and return ok   */\r\n    iThreadInfoIndex = snGetThreadInfoIndexForThreadId(iThreadId);\r\n    if (iThreadInfoIndex >= 0)\r\n    {\r\n        if(iInterruptsWereEnabled != 0)\r\n        {\r\n            EI();\r\n        }\r\n        printf(\"Warning: snAddToThreadInfo() was already added\\n\");\r\n        return iThreadInfoIndex;\r\n    }\r\n\r\n    /* Not already registered, so try and find a spare entry to use */\r\n    iThreadInfoIndex = snGetThreadInfoIndexFreeEntry();\r\n\r\n    /* If the list is full, print error message and return error */\r\n    if (iThreadInfoIndex < 0)\r\n    {\r\n        if(iInterruptsWereEnabled != 0)\r\n        {\r\n            EI();\r\n        }\r\n        printf(\"Error: snAddToThreadInfo() list is full\\n\");\r\n        return -1;\r\n    }\r\n\r\n    /* Store iThreadId in s_ThreadInfo */\r\n    s_ThreadInfo[iThreadInfoIndex].iThreadId = iThreadId;\r\n    s_ThreadInfo[iThreadInfoIndex].iErrno    = 0;\r\n    s_ThreadInfo[iThreadInfoIndex].iHerrno   = 0;\r\n\r\n    if(iInterruptsWereEnabled != 0)\r\n    {\r\n        EI();\r\n    }\r\n    return iThreadInfoIndex;\r\n}\r\n\r\nstatic int snRemoveFromThreadInfo(int iThreadId)\r\n{\r\n    /* Finds iThreadId in s_ThreadInfo and then sets it to zero             */\r\n    /* If it didn't find iThreadId returns -1, else returns index           */\r\n\r\n    int iInterruptsWereEnabled;\r\n    int iThreadInfoIndex;\r\n\r\n    /* Do this with interrupts disabled to serialise access */\r\n    iInterruptsWereEnabled = DI();\r\n\r\n    /* Search s_ThreadInfo for iThreadId */\r\n    iThreadInfoIndex = snGetThreadInfoIndexForThreadId(iThreadId);\r\n    if (iThreadInfoIndex >= 0)\r\n    {\r\n        /* Mark the entry where it was stored as free now */\r\n        s_ThreadInfo[iThreadInfoIndex].iThreadId = 0;\r\n    }\r\n\r\n    if(iInterruptsWereEnabled != 0)\r\n    {\r\n        EI();\r\n    }\r\n    return iThreadInfoIndex;\r\n}\r\n\r\n\r\n/****************************************************************************/\r\n/* Private functions - for converting / storing error codes                 */\r\n/****************************************************************************/\r\n\r\nstatic void snStoreErrno(int iErrno)\r\n{\r\n\r\n    /* iErrno must be a netglue error code, this function will store it     */\r\n    /* in s_ThreadInfo[].iErrno for the entry for this ThreadId             */\r\n\r\n    int iThreadInfoIndex;\r\n\r\n    /* Get index in s_ThreadInfo[] for this thread */\r\n    iThreadInfoIndex = snGetThreadInfoIndexForThreadId(GetThreadId());\r\n\r\n    /* This shouldn't happen, but be defensive */\r\n    if (iThreadInfoIndex < 0)\r\n    {\r\n        printf(\"Warning: snStoreErrno() thread not registered\\n\");\r\n        return;\r\n    }\r\n    \r\n    s_ThreadInfo[iThreadInfoIndex].iErrno = iErrno;\r\n}\r\n\r\nstatic int snConvertNdkErrToNetGlueErr(int iSnErrno)\r\n{\r\n    /* Converts NDK error number in iSnErrno into the closest NetGlue error */\r\n    /* number and returns it                                                */\r\n\r\n    int iRetval = 0;\r\n\r\n    switch(iSnErrno)\r\n    {\r\n        case ENOBUFS:                  /* No memory buffers are available   */\r\n            iRetval = NG_ENOMEM;       /* Insufficient memory               */\r\n        break;\r\n\r\n        case ETIMEDOUT:                /* Operation timed out               */\r\n            iRetval = NG_ETIMEDOUT;    /* Timeout                           */\r\n        break;\r\n\r\n        case EISCONN:                  /* The socket is already connected   */\r\n            iRetval = NG_EISCONN;      /* Connection has already been made  */\r\n        break;\r\n\r\n        case EOPNOTSUPP:               /* Operation not supported           */\r\n            iRetval = NG_EOPNOTSUPP;   /* Invalid call for socket           */\r\n        break;\r\n\r\n        case ECONNABORTED:             /* The connection was aborted        */\r\n            iRetval = NG_ECONNABORTED; /* Aborted by call to sceGlueAbort() */\r\n        break;\r\n\r\n        case EWOULDBLOCK:              /* Caller would block                */\r\n            iRetval = -1;              /* Shouldn't happen in blocking mode */\r\n        break;\r\n\r\n        case ECONNREFUSED:             /* The connection was refused        */\r\n            iRetval = NG_ECONNREFUSED; /* Connection request was refused    */\r\n        break;\r\n\r\n        case ECONNRESET:               /* The connection has been reset     */\r\n            iRetval = NG_ECONNRESET;   /* Connection was reset              */\r\n        break;\r\n\r\n        case ENOTCONN:                 /* The socket is not connected       */\r\n            iRetval = NG_ENOTCONN;     /* Connection does not exist         */\r\n        break;\r\n\r\n        case EALREADY:                 /* Operation is already in progress  */\r\n            iRetval = -1;              /* Shouldn't happen in blocking mode */\r\n        break;\r\n\r\n        case EINVAL:                   /* Invalid parameter                 */\r\n            iRetval = NG_EINVAL;       /* Invalid arguments specified       */\r\n        break;\r\n\r\n        case EMSGSIZE:                 /* Invalid message size              */\r\n            iRetval = -1;              /* Shouldn't happen (not using fn's) */              \r\n        break;\r\n\r\n        case EPIPE:                    /* Cannot send any more              */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_ENOMEM;       /* Insufficient memory               */\r\n        break;\r\n\r\n        case EDESTADDRREQ:             /* Destination address is missing    */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_EINVAL;       /* Invalid arguments specified       */\r\n        break;\r\n\r\n        case ESHUTDOWN:                /* Connection has been shut down     */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_ENOTCONN;     /* Connection does not exist         */\r\n        break;\r\n\r\n        case ENOPROTOOPT:              /* Option unknown for this protocol  */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_EINVAL;       /* Invalid arguments specified       */\r\n        break;\r\n\r\n        case EHAVEOOB:                 /* Have received out-of-band data    */\r\n            iRetval = -1;              /* Shouldn't happen                  */              \r\n        break;\r\n\r\n        case ENOMEM:                   /* No memory available               */\r\n            iRetval = NG_ENOMEM;       /* Insufficient memory               */\r\n        break;\r\n\r\n        case EADDRNOTAVAIL:            /* Specified address not available   */\r\n            iRetval = NG_EADDRNOTAVAIL;/* Invalid address specified         */\r\n        break;\r\n\r\n        case EADDRINUSE:               /* Specified address already in use  */\r\n            iRetval = NG_EADDRINUSE;   /* Tried bind to port already bound  */\r\n        break;\r\n\r\n        case EAFNOSUPPORT:             /* Address family is not supported   */\r\n            iRetval = NG_EAFNOSUPPORT; /* Address family is an unsupported  */\r\n        break;\r\n\r\n        case EINPROGRESS:              /* Operation is in progress          */\r\n            iRetval = -1;              /* Shouldn't happen in blocking mode */\r\n        break;\r\n\r\n        case ELOWER:                   /* Unused                            */\r\n            iRetval = -1;              /* Shouldn't happen                  */\r\n        break;\r\n\r\n        case EBADF:                    /* Socket descriptor is invalid      */\r\n            iRetval = NG_EBADF;        /* Invalid descriptor specified      */\r\n        break;\r\n\r\n        case SN_ENOTINIT:              /* Socket API not initialised        */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_EBUSY;        /* Library not yet available         */\r\n        break;\r\n\r\n        case SN_ETHNOTREG:             /* Thread not registered with API    */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_EINVAL;       /* Invalid arguments specified       */\r\n        break;\r\n\r\n        case SN_EMAXTHREAD:            /* Max no of threads exceeded        */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_EINVAL;       /* Invalid arguments specified       */\r\n        break;\r\n\r\n        case SN_EIOPNORESP:            /* Failed to initialise IOP end      */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_EBUSY;        /* Library not yet available         */\r\n        break;\r\n\r\n        case SN_ENOMEM:                /* Not enough mem to init sock API   */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_ENOMEM;       /* Insufficient memory               */\r\n        break;\r\n\r\n        case SN_EBINDFAIL:             /* sceSifBindRpc failed              */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_EBUSY;        /* Library not yet available         */\r\n        break;\r\n\r\n        case SN_EINVTHREAD:            /* Invalid thread id                 */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_EINVAL;       /* Invalid arguments specified       */\r\n        break;\r\n\r\n        case SN_EALRDYINIT:            /* Socket API already initialised    */\r\n            iRetval = -1;              /* Shouldn't happen                  */\r\n        break;\r\n\r\n        case SN_ESTKDOWN:              /* Stack has not been started        */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_EBUSY;        /* Library not yet available         */\r\n        break;\r\n\r\n        case SN_EIFSTATE:              /* Error in inet_ifstate             */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_EBUSY;        /* Library not yet available         */\r\n        break;\r\n\r\n        case SN_EDNSFAIL:              /* General failure code for DNS      */\r\n            iRetval = -1;              /* Shouldn't get this for socket err */\r\n        break;\r\n\r\n        case SN_SWERROR:               /* Software error in SN sys code     */\r\n            iRetval = -1;              /* Shouldn't happen                  */\r\n        break;\r\n\r\n        case SN_EDNSBUSY:              /* DNS is busy try again later       */\r\n            iRetval = -1;              /* Shouldn't get this for socket err */\r\n        break;\r\n\r\n        case SN_REQSIZE:               /* RPC request is not expected size  */\r\n            iRetval = -1;              /* Shouldn't happen                  */\r\n        break;\r\n\r\n        case SN_REQINV:                /* RPC request is not valid          */\r\n            iRetval = -1;              /* Shouldn't happen                  */\r\n        break;\r\n\r\n        case SN_REQSYNC:               /* RPC general IOP s/w failure       */\r\n            iRetval = -1;              /* Shouldn't happen                  */\r\n        break;\r\n\r\n        case SN_RPCBAD:                /* RPC fn code unknown to IOP        */\r\n            iRetval = -1;              /* Shouldn't happen                  */\r\n        break;\r\n\r\n        case SN_NOTREADY:              /* Device not ready                  */\r\n                                       /* Closest NG error code is ...      */\r\n            iRetval = NG_ENETDOWN;     /* Interface is down                 */\r\n        break;\r\n\r\n        default:                       /* Unknown SN NDK error code         */\r\n            iRetval = -1;              /* Shouldn't happen                  */\r\n    }\r\n\r\n    /* If iRetval is set to -1 (unexpected error) has to be worth printing  */\r\n    /* a debug error message to indicate what the SN error code was         */\r\n\r\n    if (iRetval == -1)\r\n    {\r\n        printf(\"Warning: snConvertNdkErrToNetGlueErr(%d) unexpected\\n\",iSnErrno);\r\n        iRetval = NG_UNSPECIFIED;\r\n    }\r\n\r\n    return iRetval;\r\n}\r\n\r\nstatic void snGetConvStoreSocketError(int iSockId)\r\n{\r\n    /* This should only be called when an SN NDK function that operates on  */\r\n    /* a socket returns -1 indicating that it failed                        */\r\n    /*                                                                      */\r\n    /* Get the sn error number for the socket specified by iSockId, convert */\r\n    /* to a netglue error code and store it in s_ThreadInfo[].iErrno for    */\r\n    /* this thread id                                                       */\r\n\r\n    int iSnErrno;\r\n    int iNgErrno;\r\n\r\n    /* Get the NDK error code */\r\n    iSnErrno = sn_errno(iSockId);\r\n\r\n    /* Convert it to a netglue error code */\r\n    iNgErrno = snConvertNdkErrToNetGlueErr(iSnErrno);\r\n\r\n    /* Store it in s_ThreadInfo[].iErrno for this thread */\r\n    snStoreErrno(iNgErrno);\r\n}\r\n\r\nstatic void snStoreHerrno(int iHerrno)\r\n{\r\n    /* iHerrno must be a netglue error code, this function will store it   */\r\n    /* in s_ThreadInfo[].iErrno for the entry for this ThreadId             */\r\n\r\n    int iThreadInfoIndex;\r\n\r\n    /* Get index in s_ThreadInfo[] for this thread */\r\n    iThreadInfoIndex = snGetThreadInfoIndexForThreadId(GetThreadId());\r\n\r\n    /* This shouldn't happen, but be defensive */\r\n    if (iThreadInfoIndex < 0)\r\n    {\r\n        printf(\"Warning: snStoreHerrno() thread not registered\\n\");\r\n        return;\r\n    }\r\n    \r\n    s_ThreadInfo[iThreadInfoIndex].iHerrno = iHerrno;\r\n}\r\n\r\nstatic void snGetConvStoreDnsError(void)\r\n{\r\n    /* This should only be called when an SN NDK function that results in   */\r\n    /* an error that can be read by sn_h_errno()                            */\r\n    /*                                                                      */\r\n    /* Get the error number from sn_h_errno() and convert to a netglue      */\r\n    /* error code and store it in s_ThreadInfo[].iHerrno for this thread id */\r\n\r\n    int iSnHerrno;\r\n    int iNgHerrno = 0;\r\n\r\n    /* Get the NDK error code */\r\n    iSnHerrno = sn_h_errno();\r\n\r\n    /* Convert it to a netglue error code */\r\n    switch (iSnHerrno)\r\n    {\r\n        /* NDK does not support the standard BSD DNS error codes:           */\r\n        /* HOST_NOT_FOUND, TRY_AGAIN, NO_RECOVERY, NO_DATA, NO_ADDRESS, all */\r\n        /* of these conditions result in NDK returning the following error  */\r\n\r\n        case SN_EDNSFAIL:\r\n            iNgHerrno = NG_HOST_NOT_FOUND; /* not sure what else I can do */\r\n        break;\r\n\r\n        /* Internal errors in the TCP/IP stack state, or, invalid input     */\r\n        /* can result in the following errors:                              */\r\n        /* SN_ESTKDOWN The TCP/IP Stack has not been started                */\r\n        /* EINVAL name was too long or was a NULL pointer                   */\r\n\r\n        default:\r\n            printf(\"Warning: snGetConvStoreDnsError(%d) unexpected\\n\",iSnHerrno);\r\n            iNgHerrno = NG_NETDB_INTERNAL;\r\n            /* The sony comment for the above Herrno says \"see errno\", so I */\r\n            /* I assume I should store something in the errno.              */\r\n            snStoreErrno(NG_UNSPECIFIED);\r\n    }\r\n\r\n    /* Store the Herrno in s_ThreadInfo[].iHerrno for this thread */\r\n    snStoreHerrno(iNgHerrno);\r\n}\r\n\r\n/****************************************************************************/\r\n/* Private functions - convert sceNetGlueSockaddr_t <-> struct sockaddr     */\r\n/****************************************************************************/\r\n\r\nstatic void snConvGlueToNdkSockaddr(sceNetGlueSockaddr_t *psAddr)\r\n{\r\n    /* Does in place conversion                                             */\r\n    /* from: sceNetGlueSockaddr_t                                           */\r\n    /* to:   NDK struct sockaddr                                            */\r\n    \r\n    /* Do nothing if addr is NULL */\r\n    if (psAddr == NULL)\r\n        return;\r\n\r\n    /* Swap the byte order for NDK sa_family (16 bits) doesn't have sa_len  */\r\n    psAddr->sa_len    = psAddr->sa_family;\r\n    psAddr->sa_family = 0;\r\n}\r\n\r\nstatic void snConvNdkToGlueSockaddr(sceNetGlueSockaddr_t *psAddr)\r\n{\r\n    /* Does in place conversion                                             */\r\n    /* from: NDK struct sockaddr                                            */\r\n    /* to:   sceNetGlueSockaddr_t                                           */\r\n    \r\n    /* Do nothing if addr is NULL */\r\n    if (psAddr == NULL)\r\n        return;\r\n    \r\n    /* Swap the byte order for NDK sa_family (16 bits) doesn't have sa_len  */\r\n    psAddr->sa_family = psAddr->sa_len;\r\n    psAddr->sa_len    = 16;\r\n}\r\n\r\n/****************************************************************************/\r\n/* Private functions - misc                                                 */\r\n/****************************************************************************/\r\n\r\nstatic sceNetGlueHostent_t *snConvNdkToGlueHostent(struct hostent *psNdkHostent)\r\n{\r\n    /* convert hostent from NDK format to NetGlue format and store it in    */\r\n    /* s_ThreadInfo[].NetGlueHostent for this thread                        */\r\n\r\n    int iThreadInfoIndex;\r\n    sceNetGlueHostent_t *psRetval = NULL;\r\n\r\n    /* Get the index for this thread in s_ThreadInfo[] */\r\n    iThreadInfoIndex = snGetThreadInfoIndexForThreadId(GetThreadId());\r\n\r\n    if (iThreadInfoIndex < 0)\r\n    {\r\n        printf(\"Error: snConvNdkToGlueHostent() unregistered thread\\n\");\r\n        return NULL;\r\n    }\r\n\r\n    /* Found the index, so now convert from NDK struct hostent, into        */\r\n    /* sceNetGlueHostent_t, only difference is that the two fields          */\r\n    /* h_addrtype and h_length are 16 bit in NDK / 32 bit in Netglue        */\r\n\r\n    psRetval = &s_ThreadInfo[iThreadInfoIndex].NetGlueHostent;    \r\n    memset(psRetval, 0, sizeof(*psRetval)); /* just being defensive */\r\n    psRetval->h_addr_list = psNdkHostent->h_addr_list;\r\n    psRetval->h_addrtype  = psNdkHostent->h_addrtype;\r\n    psRetval->h_aliases   = psNdkHostent->h_aliases;\r\n    psRetval->h_length    = psNdkHostent->h_length;\r\n    psRetval->h_name      = psNdkHostent->h_name;\r\n\r\n    return psRetval;\r\n}\r\n\r\n/****************************************************************************/\r\n/* Functions exported by netglue (in same order as sony libref doc)         */\r\n/****************************************************************************/\r\n\r\nint *__sceNetGlueErrnoLoc(void)\r\n{\r\n    int iThreadInfoIndex;\r\n    int iThreadId;\r\n\r\n    /* Find the index for this thread in s_ThreadInfo */\r\n    iThreadId = GetThreadId();\r\n    iThreadInfoIndex = snGetThreadInfoIndexForThreadId(iThreadId);\r\n\r\n    /* This shouldn't happen, but be defensive */\r\n    if (iThreadInfoIndex < 0)\r\n    {\r\n        printf(\"Error: __sceNetGlueErrnoLoc() unregistered thread (%d)\\n\",iThreadId);\r\n        return NULL;\r\n    }\r\n    \r\n    return &s_ThreadInfo[iThreadInfoIndex].iErrno;\r\n}\r\n\r\nint *__sceNetGlueHErrnoLoc(void)\r\n{\r\n    int iThreadInfoIndex;\r\n    int iThreadId;\r\n\r\n    /* Find the index for this thread in s_ThreadInfo */\r\n    iThreadId = GetThreadId();\r\n    iThreadInfoIndex = snGetThreadInfoIndexForThreadId(iThreadId);\r\n\r\n    /* This shouldn't happen, but be defensive */\r\n    if (iThreadInfoIndex < 0)\r\n    {\r\n        printf(\"Error: __sceNetGlueHErrnoLoc() unregistered thread (%d)\\n\",iThreadId);\r\n        return NULL;\r\n    }\r\n    \r\n    return &s_ThreadInfo[iThreadInfoIndex].iHerrno;\r\n}\r\n\r\nint sceNetGlueAbort(int sockfd)\r\n{\r\n    /* The best approximation to this is to close the socket */\r\n    printf(\"Warning sceNetGlueAbort() just does closesocket\\n\");\r\n    closesocket(sockfd);\r\n    return 0;\r\n}\r\n\r\nint sceNetGlueAbortResolver(int thread_id)\r\n{\r\n    /* Can't see a way to implement this at the moment */\r\n    printf(\"Warning sceNetGlueAbortResolver() does nothing\\n\");\r\n    return 0;\r\n}\r\n\r\nint sceNetGlueAccept\r\n    (int s, sceNetGlueSockaddr_t *addr, sceNetGlueSocklen_t *paddrlen)\r\n{\r\n    int iRetval;\r\n\r\n    /* *addr is an output so no need to convert it before calling NDK */\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = accept(s, (struct sockaddr*) addr, (int*) paddrlen);\r\n\r\n    /* NetGlue and NDK both use positive value for success */\r\n    if (iRetval > 0)\r\n    {\r\n        /* convert *addr from NDK to Netglue format */\r\n        snConvNdkToGlueSockaddr(addr);\r\n        return iRetval;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreSocketError(s);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nint sceNetGlueBind\r\n    (int s, const sceNetGlueSockaddr_t *addr, sceNetGlueSocklen_t addrlen)\r\n{\r\n\r\n    int iRetval;\r\n\r\n    /* *addr is an input so need to convert it before calling NDK */\r\n    /* but it's a const, so have to clone it before converting it */\r\n    sceNetGlueSockaddr_t copyAddr;\r\n    memcpy(&copyAddr, addr, sizeof(copyAddr));\r\n\r\n    /* convert *addr from Netglue to NDK format */\r\n    snConvGlueToNdkSockaddr(&copyAddr);\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = bind(s, (struct sockaddr*) &copyAddr, addrlen);\r\n\r\n    /* NetGlue and NDK both use zero for success */\r\n    if (iRetval == 0)\r\n    {\r\n        return iRetval;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreSocketError(s);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nint sceNetGlueConnect\r\n    (int s, const sceNetGlueSockaddr_t *addr, sceNetGlueSocklen_t addrlen)\r\n{\r\n    int iRetval;\r\n\r\n    /* *addr is an input so need to convert it before calling NDK */\r\n    /* but it's a const, so have to clone it before converting it */\r\n    sceNetGlueSockaddr_t copyAddr;\r\n    memcpy(&copyAddr, addr, sizeof(copyAddr));\r\n\r\n    /* convert *addr from Netglue to NDK format */\r\n    snConvGlueToNdkSockaddr(&copyAddr);\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = connect(s, (struct sockaddr*) &copyAddr, addrlen);\r\n\r\n    /* NetGlue and NDK both use zero for success */\r\n    if (iRetval == 0)\r\n    {\r\n        return iRetval;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreSocketError(s);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nsceNetGlueHostent_t*\r\n    sceNetGlueGethostbyaddr(const char *addr, int len, int type)\r\n{\r\n    /* NDK does not currently support reverse DNS lookup. Advice from Sony  */\r\n    /* is that DNAS does not use this function (although it does appear in  */\r\n    /* the list of symbols for the DNAS lib)                                */\r\n\r\n    /* Without reverse DNS lookup, the best I can do is construct a         */\r\n    /* sceNetGlueHostent_t to return that contains the addr input param and */\r\n    /* and NULL name / alias                                                */\r\n\r\n    int iThreadInfoIndex;\r\n    sceNetGlueHostent_t *psRetval = NULL;\r\n    \r\n    iThreadInfoIndex = snGetThreadInfoIndexForThreadId(GetThreadId());\r\n\r\n    if (iThreadInfoIndex < 0)\r\n    {\r\n        printf(\"Error: sceNetGlueGethostbyaddr() unregistered thread\\n\");\r\n        /* Putting this in Herrno should make app look at Errno */\r\n        snStoreHerrno(NG_NETDB_INTERNAL);\r\n        snStoreErrno(NG_EINVAL);\r\n        return NULL;\r\n    }\r\n\r\n    /* Get pointer to sceNetGlueHostent_t for this thread */\r\n    psRetval = &s_ThreadInfo[iThreadInfoIndex].NetGlueHostent;\r\n\r\n    /* Set up the sceNetGlueHostent_t that's going to be returned */\r\n    psRetval->h_addr_list    = (char**)&s_ThreadInfo[iThreadInfoIndex].sn_h_addr_list;\r\n    psRetval->h_addr_list[0] = (char*) &s_ThreadInfo[iThreadInfoIndex].sn_h_addr;\r\n    psRetval->h_addr_list[1] = NULL;\r\n    psRetval->h_addrtype     = AF_INET; /* NDK and Netglue define this as 2 */\r\n    psRetval->h_aliases      = NULL;\r\n    psRetval->h_length       = 4;\r\n    psRetval->h_name         = NULL;\r\n\r\n    /* Copy the input addr to the sn_h_addr pointed to by above struct */\r\n    memcpy(&s_ThreadInfo[iThreadInfoIndex].sn_h_addr, addr, 4);\r\n\r\n    return psRetval;\r\n}\r\n\r\nsceNetGlueHostent_t *sceNetGlueGethostbyname(const char *name)\r\n{\r\n    struct hostent *psResult      = NULL;\r\n    sceNetGlueHostent_t *psRetval = NULL;\r\n\r\n    /* Call the NDK equivalent */\r\n    psResult = gethostbyname(name);\r\n\r\n    /* NetGlue and NDK both use NULL for error */\r\n    if (psResult != NULL)\r\n    {\r\n        /* convert hostent from NDK format to NetGlue format and store it   */\r\n        /* in s_ThreadInfo[].NetGlueHostent for this thread                 */\r\n        psRetval = snConvNdkToGlueHostent(psResult);\r\n        return psRetval;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreDnsError();\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return NULL;\r\n}\r\n\r\nint sceNetGlueGetpeername\r\n    (int s, sceNetGlueSockaddr_t *addr, sceNetGlueSocklen_t *paddrlen)\r\n{\r\n    int iRetval;\r\n\r\n    /* *addr is an output so no need to convert it before calling NDK */\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = getpeername(s, (struct sockaddr*) addr, (int*) paddrlen);\r\n\r\n    /* NetGlue and NDK both use zero for success */\r\n    if (iRetval == 0)\r\n    {\r\n        /* convert *addr from NDK to Netglue format */\r\n        snConvNdkToGlueSockaddr(addr);\r\n        return iRetval;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreSocketError(s);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nint sceNetGlueGetsockname\r\n    (int s, sceNetGlueSockaddr_t *addr, sceNetGlueSocklen_t *paddrlen)\r\n{\r\n    int iRetval;\r\n\r\n    /* *addr is an output so no need to convert it before calling NDK */\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = getsockname(s, (struct sockaddr*) addr, (int*) paddrlen);\r\n\r\n    /* NetGlue and NDK both use zero for success */\r\n    if (iRetval == 0)\r\n    {\r\n        /* convert *addr from NDK to Netglue format */\r\n        snConvNdkToGlueSockaddr(addr);\r\n        return iRetval;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreSocketError(s);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nint sceNetGlueGetsockopt\r\n    (int s, int level, int optname, void *optval,\r\n     sceNetGlueSocklen_t *optlen)\r\n{\r\n    /* At the moment the only option supported by NetGlue is TCP_NODELAY    */\r\n    /* which uses level = IPPROTO_TCP.                                      */\r\n    /* Because the values defined for IPPROTO_TCP and TCP_NODELAY are the   */\r\n    /* same in NDK and Netglue, there is no need to do any conversion here  */\r\n\r\n    int iRetval;\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = getsockopt(s, level, optname, optval, (int*) optlen);\r\n\r\n    /* NetGlue and NDK both use zero for success */\r\n    if (iRetval == 0)\r\n    {\r\n        return iRetval;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreSocketError(s);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nu_int sceNetGlueHtonl(u_int hostlong)\r\n{\r\n    return htonl(hostlong);\r\n}\r\n\r\nu_short sceNetGlueHtons(u_short hostshort)\r\n{\r\n    return htons(hostshort);\r\n}\r\n\r\nu_int sceNetGlueInetAddr(const char *cp)\r\n{\r\n    int iRetval;\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = inet_addr(cp);\r\n\r\n    /* NetGlue and NDK both use INADDR_NONE (all f's) for failure */\r\n    return iRetval;\r\n}\r\n\r\nint sceNetGlueInetAton(const char *cp, sceNetGlueInAddr_t *addr)\r\n{\r\n    /* sceNetGlueInAddr_t is the same as NDK struct in_addr */\r\n\r\n    int iRetval;\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = inet_aton(cp, (struct in_addr*) addr);\r\n\r\n    /* NetGlue and NDK both use 1 for success / 0 for failure */\r\n    return iRetval;\r\n}\r\n\r\nu_int sceNetGlueInetLnaof(sceNetGlueInAddr_t in)\r\n{\r\n    /* to do not implemented yet - but not used by DNAS 2.7.1 */\r\n    printf(\"Warning: sceNetGlueInetLnaof() not implemented\\n\");\r\n    return 0;\r\n}\r\n\r\nsceNetGlueInAddr_t sceNetGlueInetMakeaddr(u_int net, u_int host)\r\n{\r\n    /* to do not implemented yet - but not used by DNAS 2.7.1 */\r\n    sceNetGlueInAddr_t sRetval;\r\n    memset(&sRetval, 0, sizeof(sRetval));\r\n    printf(\"Warning: sceNetGlueInetMakeaddr() not implemented\\n\");\r\n    return sRetval;\r\n}\r\n\r\nu_int sceNetGlueInetNetof(sceNetGlueInAddr_t in)\r\n{\r\n    /* to do not implemented yet - but not used by DNAS 2.7.1 */\r\n    printf(\"Warning: sceNetGlueInetNetof() not implemented\\n\");\r\n    return 0;\r\n}\r\n\r\nu_int sceNetGlueInetNetwork(const char *cp)\r\n{\r\n    /* to do not implemented yet - but not used by DNAS 2.7.1 */\r\n    printf(\"Warning: sceNetGlueInetNetwork() not implemented\\n\");\r\n    return INADDR_NONE;\r\n}\r\n\r\nchar *sceNetGlueInetNtoa(sceNetGlueInAddr_t in)\r\n{\r\n    char *pszRetval;\r\n\r\n    /* sceNetGlueInAddr_t is the same as NDK struct in_addr, but can't cast */\r\n    /* non scalar in param passed to call, so copy to ndk_in                */\r\n    struct in_addr ndk_in;\r\n    ndk_in.s_addr = in.s_addr;\r\n\r\n    /* Call the NDK equivalent */\r\n    pszRetval = inet_ntoa(ndk_in);\r\n\r\n    /* If NDK fails it returns NULL, netglue doc has no mention of failure  */\r\n    return pszRetval;\r\n}\r\n\r\nint sceNetGlueListen(int s, int backlog)\r\n{\r\n    int iRetval;\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = listen(s, backlog);\r\n\r\n    /* NetGlue and NDK both use 0 for success */\r\n    if (iRetval == 0)\r\n    {\r\n        return iRetval;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreSocketError(s);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nu_int sceNetGlueNtohl(u_int netlong)\r\n{\r\n    return ntohl(netlong);\r\n}\r\n\r\nu_short sceNetGlueNtohs(u_short netshort)\r\n{\r\n    return ntohs(netshort);\r\n}\r\n\r\nssize_t sceNetGlueRecv(int s, void *buf, size_t len, int flags)\r\n{\r\n    int iRetval;\r\n\r\n    /* 2.7.0 Netglue doc says flags \"Not supported (always set to zero)     */\r\n    /* So enforce this and print error if flags != 0                        */\r\n\r\n    if (flags != 0)\r\n    {\r\n        printf(\"Warning: sceNetGlueRecv() called with flags non zero (%d)\\n\",flags);\r\n        flags = 0;\r\n    }\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = recv(s, buf, len, flags);\r\n\r\n    /* NetGlue and NDK both use >= 0 for success */\r\n    if (iRetval >= 0)\r\n    {\r\n        return iRetval;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreSocketError(s);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nssize_t sceNetGlueRecvfrom\r\n    (int s, void *buf, size_t len, int flags,\r\n     sceNetGlueSockaddr_t *addr, sceNetGlueSocklen_t *paddrlen)\r\n{\r\n    int iRetval;\r\n\r\n    /* 2.7.0 Netglue doc says flags \"Not supported (always set to zero)     */\r\n    /* So enforce this and print error if flags != 0                        */\r\n\r\n    if (flags != 0)\r\n    {\r\n        printf(\"Warning: sceNetGlueRecvfrom() called with flags non zero (%d)\\n\",flags);\r\n        flags = 0;\r\n    }\r\n\r\n    /* *addr is an output so no need to convert it before calling NDK */\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = recvfrom(s, buf, len, flags, (struct sockaddr*) addr, (int*) paddrlen);\r\n\r\n    /* NetGlue and NDK both use >= 0 for success */\r\n    if (iRetval >= 0)\r\n    {\r\n        /* convert *addr from NDK to Netglue format */\r\n        snConvNdkToGlueSockaddr(addr);\r\n        return iRetval;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreSocketError(s);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nssize_t sceNetGlueSend(int s, const void *buf, size_t len, int flags)\r\n{\r\n    int iRetval;\r\n\r\n    /* 2.7.0 Netglue doc says flags \"Not supported (always set to zero)     */\r\n    /* So enforce this and print error if flags != 0                        */\r\n\r\n    if (flags != 0)\r\n    {\r\n        printf(\"Warning: sceNetGlueSend() called with flags non zero (%d)\\n\",flags);\r\n        flags = 0;\r\n    }\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = send(s, buf, len, flags);\r\n\r\n    /* NetGlue and NDK both use >= 0 for success */\r\n    if (iRetval >= 0)\r\n    {\r\n        return iRetval;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreSocketError(s);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nssize_t sceNetGlueSendto\r\n    (int s, const void *buf, size_t len, int flags,\r\n     const sceNetGlueSockaddr_t *addr, sceNetGlueSocklen_t addrlen)\r\n{\r\n    int iRetval;\r\n\r\n    /* *addr is an input so need to convert it before calling NDK */\r\n    /* but it's a const, so have to clone it before converting it */\r\n    sceNetGlueSockaddr_t copyAddr;\r\n    memcpy(&copyAddr, addr, sizeof(copyAddr));\r\n\r\n    /* convert *addr from Netglue to NDK format */\r\n    snConvGlueToNdkSockaddr(&copyAddr);\r\n\r\n    /* 2.7.0 Netglue doc says flags \"Not supported (always set to zero)     */\r\n    /* So enforce this and print error if flags != 0                        */\r\n\r\n    if (flags != 0)\r\n    {\r\n        printf(\"Warning: sceNetGlueSendto() called with flags non zero (%d)\\n\",flags);\r\n        flags = 0;\r\n    }\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = sendto(s, buf, len, flags, (struct sockaddr*)&copyAddr, addrlen);\r\n\r\n    /* NetGlue and NDK both use >= 0 for success */\r\n    if (iRetval >= 0)\r\n    {\r\n        return iRetval;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreSocketError(s);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nint sceNetGlueSetSifMBindRpcValue\r\n    (u_int buffersize, u_int stacksize, int priority)\r\n{\r\n    /* According to Sony this function is deprecated and hasn't been        */\r\n    /* implemented in any release of netglue since 2.4                      */\r\n    /* NDK doesn't have the run-time options to support this in any case    */\r\n\r\n    /* Print a warning but return indicating success */\r\n    printf(\"Warning: sceNetGlueSetSifMBindRpcValue() not implemented\\n\");\r\n\r\n    return 0;\r\n}\r\n\r\nint sceNetGlueSetsockopt\r\n    (int s, int level, int optname, const void *optval,\r\n     sceNetGlueSocklen_t optlen)\r\n{\r\n    /* At the moment the only option supported by NetGlue is TCP_NODELAY    */\r\n    /* which uses level = IPPROTO_TCP.                                      */\r\n    /* Because the values defined for IPPROTO_TCP and TCP_NODELAY are the   */\r\n    /* same in NDK and Netglue, there is no need to do any conversion here  */\r\n\r\n    int iRetval;\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = setsockopt(s, level, optname, optval, optlen);\r\n\r\n    /* NetGlue and NDK both use zero for success */\r\n    if (iRetval == 0)\r\n    {\r\n        return iRetval;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreSocketError(s);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nint sceNetGlueShutdown(int s, int how)\r\n{\r\n    int iCloseResult;\r\n    int iShutdownResult;\r\n\r\n    /* NDK and netglue both use the same *values* for the how parameter but */\r\n    /* use different names, like this                                       */\r\n    /* NDK values                 Netglue values                            */\r\n    /* #define SD_RECEIVE  0      #define SHUT_RD    0                      */\r\n    /* #define SD_SEND     1      #define SHUT_WR    1                      */\r\n    /* #define SD_BOTH     2      #define SHUT_RDWR  2                      */\r\n\r\n    /* Also netglue only supports SHUT_RDWR (2.7.0 lib ref) and a call to   */\r\n    /* this also performs the function of closesocket()                     */\r\n    \r\n    if (how != SD_BOTH)\r\n    {\r\n        printf(\"Warning: sceNetGlueShutdown() called with how != SHUT_RDWR (%d)\\n\",how);\r\n        how = SD_BOTH;\r\n    }\r\n\r\n    /* Call the NDK equivalent */\r\n    iShutdownResult = shutdown(s, how);\r\n    iCloseResult    = closesocket(s);\r\n\r\n    /* NetGlue and NDK both use zero for success */\r\n    if ((iShutdownResult == 0) && (iCloseResult == 0))\r\n    {\r\n        return 0;\r\n    }\r\n    \r\n    /* Get / convert / store error detail */\r\n    snGetConvStoreSocketError(s);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nint sceNetGlueSocket(int family, int type, int protocol)\r\n{\r\n    /* NDK and netglue both use the same values and names for the various  */\r\n    /* #defines relevant to the paramters this function is passed:         */\r\n    /*                                                                     */\r\n    /* family may only be AF_INET, both NDK and netglue define this as 2   */\r\n    /*                                                                     */\r\n    /* type may be SOCK_STREAM (NDK and netglue define this as 1)          */\r\n    /*          or SOCK_DGRAM  (NDK and netglue define this as 2)          */\r\n    /*          or SOCK_RAW    (NDK not supported, netglue defines it as 3)*/\r\n    /*                                                                     */\r\n    /* Sony advise that DNAS does not use SOCK_RAW.                        */\r\n    /*                                                                     */\r\n    /* protocol is not supported by netglue (always set to zero), for      */\r\n    /* NDK, protcol is always passed in to socket() as PF_INET             */\r\n\r\n    int iRetval;\r\n\r\n    /* Trap any calls using type SOCK_RAW (and any other unsupported type) */\r\n\r\n    if ((type != SOCK_STREAM) && (type != SOCK_DGRAM))\r\n    {\r\n        printf(\"Error: sceNetGlueSocket() called with type = (%d)\\n\",type);\r\n        snStoreErrno(NG_EINVAL);\r\n        return -1;\r\n    }\r\n\r\n    /* Call the NDK equivalent */\r\n    iRetval = socket(family, type, PF_INET);\r\n\r\n    /* Positive value is a good socket descriptor, return it */ \r\n    if (iRetval > 0) \r\n    { \r\n        return iRetval; \r\n    }     \r\n\r\n    /* NDK doesn't provide a general errno, only provided per socket, but  */\r\n    /* failed to create the socket so no way of knowing why                */\r\n\r\n    snStoreErrno(NG_UNSPECIFIED);\r\n\r\n    /* NetGlue and NDK both use -1 for error */\r\n    return -1;\r\n}\r\n\r\nint sceNetGlueThreadInit(int thread_id)\r\n{\r\n    int iResult;\r\n    int iDontCare;\r\n    int iThisThreadId;\r\n\r\n    iThisThreadId = GetThreadId();\r\n\r\n    /* thread_id == 0 means this thread */\r\n    if (thread_id == 0)\r\n    {\r\n        thread_id = iThisThreadId;\r\n    }\r\n\r\n    /* NDK requires each thread that is going to use the socket API to      */\r\n    /* register *itself* with the NDK API by calling sockAPIregthr() i.e.   */\r\n    /* there is currently no way for thread A to register thread B          */\r\n    /* so trap this and report error.                                       */\r\n\r\n    /* If this restriction turns out to be a problem in practice then it    */\r\n    /* will be necessary for NDK to be modified so that thread A can        */\r\n    /* register thread B e.g. add new fn sockAPIregother()                  */\r\n\r\n    /* so trap this and report error.                                       */\r\n\r\n    if (iThisThreadId != thread_id)\r\n    {\r\n        printf(\"Error: sceNetGlueThreadInit() can only register own thread\\n\");\r\n        return -1;\r\n    }\r\n\r\n    /* Add this to our internal list of registered threads */\r\n    iResult = snAddToThreadInfo(thread_id);\r\n\r\n    /* If it failed (list is full), return now with failure */\r\n    if (iResult < 0)\r\n    {\r\n        return -1;\r\n    }\r\n       \r\n    /* Now register with NDK */\r\n    iResult = sockAPIregthr();\r\n\r\n    /* If it worked ok, return now indicating success */\r\n    if (iResult == 0)\r\n    {\r\n        return 0;\r\n    }\r\n\r\n    /* Failed to register with NDK so remove from local list */\r\n    iDontCare = snRemoveFromThreadInfo(thread_id);\r\n\r\n    return -1;\r\n}\r\n\r\nint sceNetGlueThreadTerminate(int thread_id)\r\n{\r\n    int iResult1;\r\n    int iResult2;\r\n    int iThisThreadId;\r\n\r\n    iThisThreadId = GetThreadId();\r\n\r\n    /* thread_id == 0 means this thread */\r\n    if (thread_id == 0)\r\n    {\r\n        thread_id = iThisThreadId;\r\n    }\r\n\r\n    /* Remove from local list */\r\n    iResult1 = snRemoveFromThreadInfo(thread_id);\r\n\r\n    /* De-register with NDK */\r\n    iResult2 = sockAPIderegother(thread_id);\r\n\r\n    /* If both operations successful return indicating success */\r\n    if ((iResult1 >= 0) && (iResult2 ==0))\r\n    {\r\n        return 0;\r\n    }\r\n\r\n    return -1;\r\n}\r\n\r\n} // end of extern \"C\"\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/Player.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tPlayer.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t08/09/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPlayerInfo functionality\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <sys/mcman.h>\r\n#include <sys/SIO/keyboard.h>\r\n\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/mainloop.h>\r\n\r\n#include <gfx/vecfont.h>\r\n#include <gfx/2d/screenelemman.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/modules/frontend/frontend.h>\r\n//#include <sk/modules/frontend/mainmenu.h>\r\n\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/objects/proxim.h>\r\n#include <sk/objects/crown.h>\r\n#include <sk/objects/skatercam.h>\r\n#include <sk/components/skaterstatehistorycomponent.h>\r\n#include <sk/components/skaterscorecomponent.h>\r\n\r\n#include <sk/scripting/cfuncs.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <sk/objects/skater.h>\t\t   // mostly getting score\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nenum\r\n{\r\n\tvINVULNERABILITY_PERIOD = 10,\t\t// in frames\r\n\tvINVULNERABILITY_BAIL_SECONDS = 1,\t// in seconds\r\n\tvPROJECTILE_INVULNERABILITY_INTERVAL = 5000,// in ms\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint \tManager::GetTeamScore( int team_id )\r\n{\r\n\tPlayerInfo* player, *local_player;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tLst::Search< PlayerInfo > sh;\r\n\tMdl::Score* score_obj;\r\n\tint score;\r\n\tbool in_goal_attack;\r\n\t \r\n\tscore = 0;\r\n\r\n\tlocal_player = GetLocalPlayer();\r\n\tin_goal_attack = skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netgoalattack\" );\r\n\t// Next create a sorted list of the players (sorted in order of highest to lowest score)\r\n\tfor( player = FirstPlayerInfo( sh ); player; player = NextPlayerInfo( sh ))\r\n\t{\r\n\t\t// Only show the names/scores of players that are fully in the game\r\n\t\tif((player->IsFullyIn() == false ) || ( player->m_Team != team_id ))\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif( in_goal_attack && !local_player->IsObserving())\r\n\t\t{\r\n\t\t\tGame::CGoalManager* pGoalManager;\r\n\t\t\t \r\n\t\t\tpGoalManager = Game::GetGoalManager();\r\n\t\t\treturn pGoalManager->NumGoalsBeatenByTeam( team_id );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tObj::CSkaterScoreComponent* p_skater_score_component = GetSkaterScoreComponentFromObject(player->m_Skater);\r\n\t\t\tDbg_Assert(p_skater_score_component);\r\n\t\t\t\r\n\t\t\tscore_obj = p_skater_score_component->GetScore();\r\n\t\t\tscore += score_obj->GetTotalScore();\r\n\t\t}\r\n\t}\r\n\r\n\treturn score;\r\n}\r\n\r\nint \tManager::GetPlayerScore( int obj_id )\r\n{\r\n\tbool in_goal_attack;\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tGameNet::PlayerInfo* local_player;\r\n\t\r\n\tlocal_player = GetLocalPlayer();\r\n\tin_goal_attack = skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netgoalattack\" );\r\n\tif( in_goal_attack && !local_player->IsObserving())\r\n\t{\r\n\t\tGame::CGoalManager* pGoalManager;\r\n\t\t\t \r\n\t\tpGoalManager = Game::GetGoalManager();\r\n\t\treturn pGoalManager->NumGoalsBeatenBy( obj_id );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMdl::Score* score_obj;\r\n\t\tPlayerInfo* player;\r\n\r\n\t\tplayer = GetPlayerByObjectID( obj_id );\r\n\t\tDbg_Assert( player );\r\n\t\t\r\n\t\tObj::CSkaterScoreComponent* p_skater_score_component = GetSkaterScoreComponentFromObject(player->m_Skater);\r\n\t\tDbg_Assert(p_skater_score_component);\r\n\t\r\n\t\tscore_obj = p_skater_score_component->GetScore();\r\n\t\treturn score_obj->GetTotalScore();\r\n\t}\r\n}\r\n\r\nvoid\tManager::s_render_scores_code( const Tsk::Task< Manager >& task )\r\n{\r\n\tFront::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tScript::CScriptStructure *pParams;\r\n\tGame::CGameMode* pGameMode;\r\n\tPlayerInfo* player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tstatic Tmr::Time last_update = 0;\r\n\tTmr::Time cur_time;\r\n\tLst::Head< ScoreRank > rank_list;\r\n\tLst::Search< ScoreRank > rank_sh;\r\n\tScoreRank* rank, *next;\r\n\tbool show_score, king_mode;\r\n\r\n\tManager& man = task.GetData();\r\n    // Only draw the scores in modes in which the score accumulates\r\n\tpGameMode = skate_mod->GetGameMode();\r\n\tshow_score =  skate_mod->GetGameMode()->GetNameChecksum() != CRCD( 0x1c471c60, \"netlobby\" );\r\n\r\n\t// in King of the hill games, \"score\" is actually milliseconds with the crown\r\n\tking_mode =\t( skate_mod->GetGameMode()->GetNameChecksum() == CRCD( 0x6ef8fda0, \"netking\" )) ||\r\n\t\t\t\t( skate_mod->GetGameMode()->GetNameChecksum() == CRCD( 0x5d32129c, \"king\" ));\r\n    \r\n\tcur_time = Tmr::GetTime();\r\n\tif(( cur_time - last_update ) >= Tmr::Seconds( 1 ))\r\n\t{\r\n\t\tint i, j;\r\n\t\tuint32 id;\r\n\t\t\r\n\t\tlast_update = cur_time;\r\n\r\n\t\t// First clear all previous entries\r\n\t\tScript::RunScript( \"clear_scores\" );\r\n        \r\n\t\tif( show_score && man.ShouldDisplayTeamScores())\r\n\t\t{\r\n\t\t\tScoreRank* ranks[vMAX_TEAMS];\r\n            \r\n\t\t\tfor( j = 0; j < skate_mod->GetGameMode()->NumTeams(); j++ )\r\n\t\t\t{\r\n\t\t\t\tif( man.NumTeamMembers( j ) > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 team_name_checksum;\r\n\t\t\t\t\t\r\n\t\t\t\t\tswitch( j )\r\n\t\t\t\t\t{\r\n\t\t\t\t\tcase 0:\r\n\t\t\t\t\t\tteam_name_checksum = CRCD( 0x3224348d, \"team_1_name\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 1:\r\n\t\t\t\t\t\tteam_name_checksum = CRCD( 0xb4b04623, \"team_2_name\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 2:\r\n\t\t\t\t\t\tteam_name_checksum = CRCD( 0x7fec9586, \"team_3_name\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 3:\r\n\t\t\t\t\t\tteam_name_checksum = CRCD( 0x62e9a53e, \"team_4_name\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\t\t\tteam_name_checksum = 0;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\r\n\t\t\t\t\tranks[j] = new ScoreRank;\r\n\t\t\t\t\tstrcpy( ranks[j]->m_Name, Script::GetString( team_name_checksum ));\r\n\t\t\t\t\tranks[j]->m_IsKing = false;\r\n\t\t\t\t\tranks[j]->m_HasFlag = false;\r\n\t\t\t\t\tranks[j]->m_WhichFlags = 0;\r\n\t\t\t\t\tranks[j]->m_ColorIndex = j + 2;\r\n\t\t\t\t\tranks[j]->m_TotalScore = man.GetTeamScore( j );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Next create a sorted list of the players (sorted in order of highest to lowest score)\r\n\t\t\tfor( player = man.FirstPlayerInfo( sh ); player; player = man.NextPlayerInfo( sh ))\r\n\t\t\t{\r\n\t\t\t\t// Only show the names/scores of players that are fully in the game\r\n\t\t\t\tif( !( player->IsFullyIn()))\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tif( player->IsLocalPlayer())\r\n\t\t\t\t{\r\n\t\t\t\t\tchar new_name[64];\r\n\r\n\t\t\t\t\t// This is my team.  Make that obvious to the players\r\n\t\t\t\t\tsprintf( new_name, \"> %s\", ranks[player->m_Team]->m_Name );\r\n\t\t\t\t\tstrcpy( ranks[player->m_Team]->m_Name, new_name );\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tif( player->IsKing())\r\n\t\t\t\t{\r\n\t\t\t\t\tranks[player->m_Team]->m_IsKing = true;\r\n\t\t\t\t}\r\n\t\t\t\tif( player->HasCTFFlag())\r\n\t\t\t\t{\r\n\t\t\t\t\tranks[player->m_Team]->m_HasFlag = true;\r\n\t\t\t\t\tranks[player->m_Team]->m_WhichFlags |= ( 1 << player->HasWhichFlag());\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tfor( j = 0; j < skate_mod->GetGameMode()->NumTeams(); j++ )\r\n\t\t\t{\r\n\t\t\t\tif( man.NumTeamMembers( j ) > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Lists sort based on node's priority so set the node's priority to that of\r\n\t\t\t\t\t// the team's score and add it to the list\r\n\t\t\t\t\tranks[j]->SetPri( ranks[j]->m_TotalScore );\r\n\t\t\t\t\trank_list.AddNode( ranks[j] );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Next create a sorted list of the players (sorted in order of highest to lowest score)\r\n\t\t\tfor( player = man.FirstPlayerInfo( sh ); player; player = man.NextPlayerInfo( sh ))\r\n\t\t\t{\r\n\t\t\t\t// Only show the names/scores of players that are fully in the game\r\n\t\t\t\tif( !( player->IsFullyIn()))\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\trank = new ScoreRank;\r\n\t\t\t\tif( player->IsLocalPlayer())\r\n\t\t\t\t{\r\n\t\t\t\t\t// This is me.  Make that obvious.\r\n\t\t\t\t\tsprintf( rank->m_Name, \"> %s\", player->m_Name );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tstrcpy( rank->m_Name, player->m_Name );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\trank->m_IsKing = player->IsKing();\r\n\t\t\t\tif( skate_mod->GetGameMode()->IsTeamGame())\r\n\t\t\t\t{\r\n\t\t\t\t\trank->m_ColorIndex = player->m_Team + 2;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\trank->m_ColorIndex = player->m_Skater->GetID() + 2;\r\n\t\t\t\t}\r\n\t\t\t\tif( player->HasCTFFlag())\r\n\t\t\t\t{\r\n\t\t\t\t\trank->m_HasFlag = true;\r\n\t\t\t\t\trank->m_WhichFlags |= ( 1 << player->HasWhichFlag());\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif( show_score )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Lists sort based on node's priority so set the node's priority to that of\r\n\t\t\t\t\t// the player's score and add him to the list\r\n\t\t\t\t\trank->SetPri( man.GetPlayerScore( player->m_Skater->GetID()));\r\n\t\t\t\t\trank_list.AddNode( rank );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Just add the player to the list so that the order is the same regardless of score\r\n\t\t\t\t\trank_list.AddToTail( rank );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\r\n\t\t// Now loop through the sorted list in order of highest to lowest score and print them out\r\n\t\ti = 0;\r\n\t\tfor( rank = rank_sh.FirstItem( rank_list ); rank; rank = next )\r\n\t\t{   \r\n\t\t\tchar score_str[64];\r\n\t\t\tchar title[16];\r\n\r\n\t\t\ttitle[0]='\\0';\r\n\t\t\tif( rank->m_IsKing )\r\n\t\t\t{\r\n#if ENGLISH == 0\r\n\t\t\t\tsprintf( title, Script::GetLocalString( \"player_str_king_abbreviation\" ));\r\n#else \r\n\t\t\t\tsprintf( title, \"K\" );\r\n#endif\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( rank->m_HasFlag )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( rank->m_WhichFlags & 1 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( title, \"\\\\s0\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif( rank->m_WhichFlags & 2 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( title, \"\\\\s1\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif( rank->m_WhichFlags & 4 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( title, \"\\\\s2\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif( rank->m_WhichFlags & 8 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcat( title, \"\\\\s3\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\ttitle[0] = '\\0';\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tnext = rank_sh.NextItem();\r\n\t\t\tif( show_score )\r\n\t\t\t{\r\n\t\t\t\tif( king_mode )\r\n\t\t\t\t{\r\n\t\t\t\t\tint seconds;\r\n\r\n\t\t\t\t\tseconds = Tmr::InSeconds( rank->GetPri() );\r\n\t\t\t\t\tif( seconds >= 3600 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsprintf( score_str, \"\\\\c4%s\\\\c%d %s \\\\c%d %d:%.2d:%.2d\", \r\n\t\t\t\t\t\t\t\t   \t\t\t\t\t\t\t\ttitle,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trank->m_ColorIndex, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trank->m_Name,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trank->m_ColorIndex,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tseconds / 3600,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( seconds % 3600 ) / 60,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tseconds % 60 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsprintf( score_str, \"\\\\c4%s\\\\c%d %s \\\\c%d %d:%.2d\", \r\n\t\t\t\t\t\t\t\t\t\t   \t\t\t\t\t\ttitle,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trank->m_ColorIndex, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trank->m_Name,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trank->m_ColorIndex,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tseconds / 60,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tseconds % 60 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf( score_str, \"%s\\\\c%d %s \\\\c%d %d\", \ttitle,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trank->m_ColorIndex, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trank->m_Name,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trank->m_ColorIndex,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trank->GetPri());\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsprintf( score_str, \"\\\\c%d%s\", \trank->m_ColorIndex, rank->m_Name );\r\n\t\t\t}\r\n            \r\n\t\t\tswitch( i )\r\n\t\t\t{\r\n\t\t\tcase 0:\r\n\t\t\t\tid = CRCD( 0x2b083809, \"net_score_1\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1:\r\n\t\t\t\tid = CRCD( 0xb20169b3, \"net_score_2\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\tid = CRCD( 0xc5065925, \"net_score_3\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase 3:\r\n\t\t\t\tid = CRCD( 0x5b62cc86, \"net_score_4\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase 4:\r\n\t\t\t\tid = CRCD( 0x2c65fc10, \"net_score_5\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase 5:\r\n\t\t\t\tid = CRCD( 0xb56cadaa, \"net_score_6\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase 6:\r\n\t\t\t\tid = CRCD( 0xc26b9d3c, \"net_score_7\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase 7:\r\n\t\t\t\tid = CRCD( 0x52d480ad, \"net_score_8\" );\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\tid = 0;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tpParams = new Script::CScriptStructure;\r\n\t\t\tpParams->AddComponent( CRCD( 0xc4745838, \"text\" ), ESYMBOLTYPE_STRING, score_str );\r\n\t\t\tpParams->AddComponent( CRCD( 0x40c698af, \"id\" ), ESYMBOLTYPE_NAME, id );\r\n\t\t\t\r\n\t\t\t\r\n\t\t\tFront::CScreenElement* p_name_elem = p_screen_elem_man->GetElement( id, Front::CScreenElementManager::DONT_ASSERT );\r\n\t\t\t// If any operable menus are up, ignore input\r\n\t\t\tif( p_name_elem )\r\n\t\t\t{\r\n\t\t\t\t//make sure the scores are enabled\r\n\t\t\t\t//if(!Mdl::Skate::Instance()->GetCareer()->GetGlobalFlag(Script::GetInteger(CRCD(0xfbb66146,\"NO_DISPLAY_NET_SCORES\")))))\r\n\t\t\t\t\tp_name_elem->SetProperties( pParams );\r\n\t\t\t}\r\n\t\t\tScript::RunScript( \"update_score\", pParams );\r\n\r\n\t\t\tdelete pParams;\r\n\t\t\tdelete rank;\r\n\t\t\ti++;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPlayerInfo::PlayerInfo( int flags )\r\n: Lst::Node< PlayerInfo > ( this )\r\n{\r\n\tint i, j;\r\n\r\n\tsprintf( m_Name, \"<No Name>\" );\r\n\r\n\tfor( i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tm_LastSentProps.m_LastSkaterFlagsUpdate[i] = -1;\r\n\t\tm_LastSentProps.m_LastSkaterStateUpdate[i] = -1;\r\n\t\tm_LastSentProps.m_LastDoingTrickUpdate[i] = -1;\r\n\t\tfor( j = 0; j < 3; j++ )\r\n\t\t{\r\n\t\t\tm_LastSentProps.m_LastSkaterPosUpdate[i][j] = -1;\r\n\t\t\tm_LastSentProps.m_LastSkaterRotUpdate[i][j] = -1;\r\n\t\t}\r\n\t}\r\n\r\n\tm_flags = flags;\r\n\tm_observer_logic_task = NULL;\r\n\tm_jump_in_frame = 0;\r\n\tm_last_object_update_id = vMAX_PLAYERS - 1;\r\n\tm_face_data = NULL;\r\n\r\n\tm_Skater = NULL;\r\n\tmp_SkaterProfile = NULL;\r\n\tm_last_bail_time = 0;\r\n\tm_last_hit_time = 0;\r\n\tm_Team = vTEAM_RED;\r\n\tm_Profile = 0;\r\n\tm_Rating = 0;\r\n\tm_VehicleControlType = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPlayerInfo::~PlayerInfo( void )\r\n{\r\n\t\r\n\r\n\tif ( mp_SkaterProfile )\r\n\t\tdelete mp_SkaterProfile;\r\n\r\n\tif( m_observer_logic_task )\r\n\t{\r\n\t\tdelete m_observer_logic_task;\r\n\t}\r\n\r\n\tif( m_face_data )\r\n\t{\r\n\t\tdelete [] m_face_data;\r\n\t\tm_face_data = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::SetSkater( Obj::CSkater* skater )\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\t\r\n\tm_Skater = skater;\r\n\tif( !IsLocalPlayer())\r\n\t{\r\n\t\tif( gamenet_man->GetCurrentlyObservedPlayer() == this )\r\n\t\t{\r\n\t\t\tgamenet_man->ObservePlayer( this );\r\n\t\t}\r\n\t}\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::SetFaceData( uint8* face_data, int size )\r\n{\r\n\tuint8 player_id;\r\n\r\n\tDbg_Assert( m_face_data == NULL );\r\n\tDbg_Assert( face_data != NULL );\r\n\tDbg_Assert( m_Skater != NULL );\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetMiscHeap());\r\n\r\n\tplayer_id = m_Skater->GetID();\r\n\t\t \r\n\t// Store the player's skater id as the first byte of the face data\r\n\tm_face_data = new uint8[size+1];\r\n\t*m_face_data = player_id;\r\n\tmemcpy( m_face_data + 1, face_data, size );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The player's skater id is the first byte of the face data\r\nuint8*\tPlayerInfo::GetFaceData( void )\r\n{\r\n\treturn m_face_data;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::CopyProfile( Obj::CSkaterProfile* pSkaterProfile )\r\n{\r\n\t\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\tDbg_Assert( pSkaterProfile );\r\n\r\n#if 0\r\n\t// copy it to the server's player info data\r\n\tuint8* pTempBuffer = new uint8[vMAX_APPEARANCE_DATA_SIZE];\r\n\tuint32 size = pSkaterProfile->WriteToBuffer(pTempBuffer, vMAX_APPEARANCE_DATA_SIZE);\r\n\tDbg_Printf(\"Appearance data size is %d bytes\\n\", size);\r\n\tmp_SkaterProfile = new Obj::CSkaterProfile;\r\n\tDbg_Assert( mp_SkaterProfile );\r\n\tmp_SkaterProfile->ReadFromBuffer(pTempBuffer);\r\n\tdelete pTempBuffer;\r\n#endif\r\n\r\n\t// now uses assignment operator to copy over the info as well\r\n\tmp_SkaterProfile = new Obj::CSkaterProfile;\r\n\t*mp_SkaterProfile = *pSkaterProfile;\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tPlayerInfo::IsLocalPlayer( void )\r\n{\r\n\treturn m_flags.TestMask( mLOCAL_PLAYER );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tPlayerInfo::IsServerPlayer( void )\r\n{\r\n\treturn m_flags.TestMask( mSERVER_PLAYER );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tPlayerInfo::IsObserving( void )\r\n{\r\n\treturn m_flags.TestMask( mOBSERVER );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tPlayerInfo::IsSurveying( void )\r\n{\r\n\treturn m_flags.TestMask( mSURVEYING );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::MarkAsRestarting( void )\r\n{\r\n\tm_flags.SetMask( mRESTARTING );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nvoid\tPlayerInfo::MarkAsNonCollidable( void )\r\n{\r\n\tm_last_bail_time = Tmr::GetTime();\r\n\treturn m_flags.SetMask( mNON_COLLIDABLE );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::ClearNonCollidable( void )\r\n{\r\n\treturn m_flags.ClearMask( mNON_COLLIDABLE );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tPlayerInfo::IsNonCollidable( void )\r\n{\r\n\tMdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n\tif( !m_Conn->TestStatus( Net::Conn::mSTATUS_READY ))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif( m_Skater->IsInWorld() == false )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Make skaters invulnerable for the first 10 frames of the game\r\n\tif( m_Skater->GetStateHistory()->GetNumPosUpdates() < vINVULNERABILITY_PERIOD )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif(( Tmr::GetTime() - m_last_bail_time ) < Tmr::Seconds( vINVULNERABILITY_BAIL_SECONDS ))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Don't collide with eliminated players in firefight\r\n\tif( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0xbff33600,\"netfirefight\"))\r\n\t{\r\n\t\tMdl::Score* score_obj;\r\n\t\tObj::CSkaterScoreComponent* p_score_component = GetSkaterScoreComponentFromObject(m_Skater);\r\n\t\tDbg_Assert(p_score_component);\r\n\t\t\r\n\t\tscore_obj = p_score_component->GetScore();\r\n\t\tif( score_obj->GetTotalScore() <= 0 )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// If they've been in this state for more than 5 seconds, that means that\r\n\t// for one reason or another, we didn't get their \"NotifyBailDone\" message.\r\n\t// This will rectify things.\r\n\tif(( Tmr::GetTime() - m_last_bail_time ) > Tmr::Seconds( 5 ))\r\n\t{\r\n\t\tClearNonCollidable();\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif( m_flags.TestMask( mNON_COLLIDABLE ))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::MarkAsFullyIn( void )\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\tm_flags.SetMask( mFULLY_IN );\r\n\r\n\tif( gamenet_man->InNetGame() && \r\n\t\tgamenet_man->OnServer() &&\r\n\t\t!IsLocalPlayer())\r\n\t{\r\n\t\tswitch( gamenet_man->GetHostMode())\r\n\t\t{\r\n\t\t\tcase vHOST_MODE_SERVE:\r\n\t\t\t\tbreak;\r\n\t\t\tcase vHOST_MODE_AUTO_SERVE:\r\n\t\t\t{\r\n\t\t\t\tNet::Server* server;\r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t\tserver = gamenet_man->GetServer();\r\n\t\t\t\tDbg_Assert( server );\r\n\r\n\t\t\t\tmsg_desc.m_Id = MSG_ID_AUTO_SERVER_NOTIFICATION;\r\n\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\tmsg_desc.m_GroupId = vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\t// Tell the client that they're in an auto-serving server\r\n\t\t\t\tserver->EnqueueMessage( GetConnHandle(), &msg_desc );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase vHOST_MODE_FCFS:\r\n\t\t\t{\r\n\t\t\t\tPlayerInfo* player;\r\n\r\n\t\t\t\tplayer = gamenet_man->GetServerPlayer();\r\n\r\n\t\t\t\t// If we don't currently have a player acting as the host\r\n\t\t\t\t// make this new player the host\r\n\t\t\t\tif( player == NULL )\r\n\t\t\t\t{\r\n\t\t\t\t\tgamenet_man->ChooseNewServerPlayer();\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tPlayerInfo::IsFullyIn( void )\r\n{\r\n\treturn m_flags.TestMask( mFULLY_IN | mLOCAL_PLAYER );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::MarkAsServerPlayer( void )\r\n{\r\n\tm_flags.SetMask( mSERVER_PLAYER );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::MarkAsNotServerPlayer( void )\r\n{\r\n\tm_flags.ClearMask( mSERVER_PLAYER );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tPlayerInfo::HasCTFFlag( void )\r\n{\r\n\treturn m_flags.TestMask( mHAS_ANY_FLAG );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tPlayerInfo::HasWhichFlag( void )\r\n{\r\n\tif( m_flags.TestMask( mHAS_RED_FLAG ))\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\tif( m_flags.TestMask( mHAS_BLUE_FLAG ))\r\n\t{\r\n\t\treturn 1;\r\n\t}\r\n\tif( m_flags.TestMask( mHAS_GREEN_FLAG ))\r\n\t{\r\n\t\treturn 2;\r\n\t}\r\n\tif( m_flags.TestMask( mHAS_YELLOW_FLAG ))\r\n\t{\r\n\t\treturn 3;\r\n\t}\r\n\r\n\treturn -1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::ClearCTFState( void )\r\n{\r\n\tm_flags.ClearMask( mHAS_ANY_FLAG );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::CapturedFlag( int team )\r\n{   \r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* local_player;\r\n\tchar team_str[64];\r\n\tScript::CStruct* pParams;\r\n\t\t\r\n\tsprintf( team_str, \"team_%d_name\", team + 1 );\r\n\r\n\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\r\n\t// Make sure they have a flag on them\r\n\tDbg_Assert( HasCTFFlag());\r\n\r\n\tpParams = new Script::CStruct;\r\n\t\r\n\tif( IsLocalPlayer())\r\n\t{\r\n\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\tpParams->AddInteger( \"team\", team );\r\n\t\tScript::RunScript( \"captured_flag_you\", pParams );\r\n\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Printf( \"***** Captured Flag : My Team %d, Flag Team %d\\n\", local_player->m_Team, team );\r\n\t\tif( ( !local_player->IsObserving()) && \r\n\t\t\t( local_player->m_Team == team ))\r\n\t\t{\r\n\t\t\tDbg_Printf( \"***** Captured Flag 2\\n\" );\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, m_Name );\r\n\t\t\tpParams->AddInteger( \"team\", team );\r\n\t\t\tScript::RunScript( \"hide_ctf_arrow\" );\r\n\t\t\tScript::RunScript( \"captured_your_flag\", pParams );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, m_Name );\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String1\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\t\tpParams->AddInteger( \"team\", team );\r\n\t\t\tScript::RunScript( \"captured_flag_other\", pParams );\r\n\t\t}                                                      \r\n\t}\r\n\t\r\n\tm_flags.ClearMask( mHAS_ANY_FLAG );\r\n\r\n\tdelete pParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::StoleFlag( int team )\r\n{\r\n\t// Shouldn't have any flag already\r\n\tDbg_Assert( !HasCTFFlag());\r\n\r\n\tDbg_Printf( \"********* In StoleFlag\\n\" );\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* local_player, *player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tchar team_str[64];\r\n\tScript::CStruct* pParams;\r\n\t\t\r\n\tsprintf( team_str, \"team_%d_name\", team + 1 );\r\n\tpParams = new Script::CStruct;\r\n\r\n\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\r\n\t\r\n\tif( IsLocalPlayer())\r\n\t{\r\n\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\tScript::RunScript( \"stole_flag_you\", pParams );\r\n\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Printf( \"***** FLAG STOLEN: Team %d, I had %d\\n\", team, local_player->HasWhichFlag() );\r\n\t\tif( !local_player->IsObserving() && ( local_player->HasWhichFlag() == team ))\r\n\t\t{\r\n\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, m_Name );\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String1\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\t\tScript::RunScript( \"stole_flag_from_you\", pParams );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, m_Name );\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String1\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\t\tScript::RunScript( \"stole_flag_other\", pParams );\r\n\t\t}\r\n\t}\r\n\r\n\tdelete pParams;\r\n\t\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t{\r\n\t\tif( player->HasWhichFlag() == team )\r\n\t\t{\r\n\t\t\tplayer->m_flags.ClearMask(( mHAS_RED_FLAG << team ));\r\n\t\t\tplayer->ClearCTFState();\r\n\t\t\tDbg_Assert( !player->HasCTFFlag());\r\n\t\t}\r\n\t}\r\n\r\n\tm_flags.SetMask(( mHAS_RED_FLAG << team ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::TookFlag( int team )\r\n{\r\n\t// Shouldn't have any flag already\r\n\tDbg_Assert( !HasCTFFlag());\r\n\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tPlayerInfo* local_player;\r\n\tchar team_str[64];\r\n\tScript::CStruct* pParams;\r\n\t\t\r\n\tsprintf( team_str, \"team_%d_name\", team + 1 );\r\n\tpParams = new Script::CStruct;\r\n\r\n\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\r\n    if( IsLocalPlayer())\r\n\t{\r\n\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\tScript::RunScript( \"took_flag_you\", pParams );\r\n\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tScript::CStruct* arrow_params;\r\n\r\n\t\tif(( !local_player->IsObserving()) && ( team == local_player->m_Team ))\r\n\t\t{\r\n\t\t\tarrow_params = new Script::CStruct;\r\n\t\t\tarrow_params->AddInteger( \"team\", local_player->m_Team );\r\n\t\t\tScript::RunScript( \"show_ctf_arrow\", arrow_params );\r\n\t\t\tdelete arrow_params;\r\n\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, m_Name );\r\n\t\t\tScript::RunScript( \"took_flag_yours\", pParams );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, m_Name );\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC(\"String1\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\t\tScript::RunScript( \"took_flag_other\", pParams );\r\n\t\t}\r\n\t}\r\n\r\n\tdelete pParams;\r\n\tm_flags.SetMask(( mHAS_RED_FLAG << team ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::RetrievedFlag( void )\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tGameNet::PlayerInfo* player, *local_player;\r\n\tLst::Search< PlayerInfo > sh;\r\n\tchar team_str[64];\r\n\tScript::CStruct* pParams;\r\n\t\t\r\n\tsprintf( team_str, \"team_%d_name\", m_Team + 1 );\r\n\tpParams = new Script::CStruct;\r\n\r\n\tif( IsLocalPlayer())\r\n\t{\r\n\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\tpParams->AddInteger( \"team\", m_Team );\r\n\t\tScript::RunScript( \"hide_ctf_arrow\" );\r\n\t\tScript::RunScript( \"retrieved_flag_you\", pParams );\r\n\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\t\tif( local_player && !local_player->IsObserving())\r\n\t\t{\r\n\t\t\tif( local_player->m_Team == m_Team )\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( \"hide_ctf_arrow\" );\r\n\t\t\t}\r\n\t\t}\r\n\t\tpParams->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, m_Name );\r\n\t\tpParams->AddComponent( Script::GenerateCRC(\"String1\"), ESYMBOLTYPE_STRING, Script::GetString( team_str ));\r\n\t\tpParams->AddInteger( \"team\", m_Team );\r\n\t\tScript::RunScript( \"retrieved_flag_other\", pParams );\r\n\t}\r\n\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t{\r\n\t\tif( player->HasWhichFlag() == m_Team )\r\n\t\t{\r\n\t\t\tplayer->ClearCTFState();\r\n\t\t\tbreak;\r\n\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::MarkAsKing( bool mark )\r\n{    \r\n\tManager * gamenet_man = Manager::Instance();\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n    \r\n\tif( mark )\r\n\t{   \r\n\t\tPlayerInfo* former_king;\r\n\r\n\t\t// There can only be one king, so dethrone the last\r\n\t\tformer_king = gamenet_man->GetKingOfTheHill();\r\n\t\tif( former_king )\r\n\t\t{\r\n\t\t\tformer_king->MarkAsKing( false );\r\n\t\t}\r\n\r\n\t\tif( !m_flags.TestMask( mKING_OF_THE_HILL ))\r\n\t\t{\r\n\t\t\tm_flags.SetMask( mKING_OF_THE_HILL );\r\n\r\n\t\t\tif( IsLocalPlayer())\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pParams;\r\n\r\n\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\tif( m_Skater->GetHeapIndex() == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tpParams->AddChecksum( \"player_1\", Script::GenerateCRC( \"player_1\"));\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpParams->AddChecksum( \"player_2\", Script::GenerateCRC( \"player_2\"));\r\n\t\t\t\t}\r\n\t\t\t\t// If we just picked up the crown, hide the arrow\r\n\t\t\t\tScript::RunScript( \"hide_crown_arrow\", pParams );\r\n\t\t\t\tdelete pParams;\r\n\t\t\t\t\r\n\t\t\t\t/*gamenet_man->CreateNetPanelMessage( false, Script::GenerateCRC(\"net_message_new_king_you\"),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tNULL, NULL, m_Skater );*/\r\n\t\t\t\tScript::RunScript( \"NewKingYou\" );\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pParams;\r\n\r\n\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\tpParams->AddChecksum( \"player_1\", Script::GenerateCRC( \"player_1\"));\r\n\t\t\t\t// If someone else just picked up the crown, show the arrow\r\n\t\t\t\tScript::RunScript( \"show_crown_arrow\", pParams );\r\n\t\t\t\t\r\n\t\t\t\tpParams->AddString( \"String0\", m_Name );\r\n\t\t\t\tScript::RunScript( \"NewKingOther\", pParams );\r\n\t\t\t\t/*gamenet_man->CreateNetPanelMessage( false, Script::GenerateCRC( \"net_message_new_king_other\"),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tm_Name, NULL );*/\r\n\t\t\t\tdelete pParams;\r\n\r\n\t\t\t\t\r\n\t\t\t}\r\n\r\n\t\t\tif( !gamenet_man->InNetGame())\r\n\t\t\t{\r\n\t\t\t\tint other_id;\r\n\t\t\t\tPlayerInfo* other_player;\r\n\r\n\t\t\t\t// NOTE: This code only works for 2-player splitscreen. If we ever go to four,\r\n\t\t\t\t// it needs to be more sophisticated\r\n\t\t\t\tif( m_Skater->GetID() == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tother_id = 1;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{ \r\n\t\t\t\t\tother_id = 0;\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tother_player = gamenet_man->GetPlayerByObjectID( other_id );\r\n\t\t\t\tif( other_player )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct* pParams;\r\n\r\n\t\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\t\tpParams->AddString( \"String0\", (char*)m_Skater->GetDisplayName());\r\n\t\t\t\t\tScript::RunScript( \"NewKingOther\", pParams );\r\n\t\t\t\t\t/*gamenet_man->CreateNetPanelMessage( false, Script::GenerateCRC(\"net_message_new_king_other\"),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(char*)m_Skater->GetDisplayName(), NULL, other_player->m_Skater );*/\r\n\t\t\t\t\tdelete pParams;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\r\n\t\t\tm_flags.SetMask( mKING_OF_THE_HILL );\r\n\t\t}\r\n        \r\n        Obj::CCrown* crown;\r\n\t\tcrown = gamenet_man->GetCrown();\r\n\t\tif( crown )\r\n\t\t{\r\n\t\t\tcrown->PlaceOnKing( m_Skater );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( m_flags.TestMask( mKING_OF_THE_HILL ))\r\n\t\t{\r\n\t\t\tif( IsLocalPlayer())\r\n\t\t\t{\r\n\t\t\t\t// If we lost the crown, show the arrow again, but only if we're still in koth mode\r\n\t\t\t\tif( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netking\" ) ||\r\n\t\t\t\t\tskate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"king\" ))\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct* pParams;\r\n\r\n\t\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\t\tpParams->AddChecksum( \"player_1\", Script::GenerateCRC( \"player_1\"));\r\n\t\t\t\t\tpParams->AddChecksum( \"player_2\", Script::GenerateCRC( \"player_2\"));\r\n\r\n\t\t\t\t\tScript::RunScript( \"show_crown_arrow\", pParams );\r\n\t\t\t\t\tdelete pParams;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tm_flags.ClearMask( mKING_OF_THE_HILL );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tPlayerInfo::IsKing( void )\r\n{\r\n\treturn m_flags.TestMask( mKING_OF_THE_HILL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::MarkAsNotReady( int time )\r\n{\r\n\tif( m_Conn && m_Conn->IsRemote())\r\n\t{\r\n\t\tif( time != 0 )\r\n\t\t{\r\n\t\t\tm_latest_ready_query = time;\r\n\t\t}\r\n\t\tm_Conn->ClearStatus( Net::Conn::mSTATUS_READY );\r\n\t\tm_Conn->SetStatus( Net::Conn::mSTATUS_BUSY );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::SetReadyQueryTime( int time )\r\n{\r\n\tm_latest_ready_query = time;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::MarkAsReady( int time )\r\n{\r\n\tif( m_latest_ready_query == time )\r\n\t{\r\n\t\tif( m_Conn )\r\n\t\t{   \r\n\t\t\tm_Conn->ClearStatus( Net::Conn::mSTATUS_BUSY );\r\n\t\t\tm_Conn->SetStatus( Net::Conn::mSTATUS_READY );\r\n\r\n\t\t\t// Now that they're ready, we need to keep track of how many times we're resending to\r\n\t\t\t// them so that we can detect bad connections\r\n\t\t\tm_Conn->ClearNumResends();\r\n\t\t}\r\n\t\tm_latest_ready_query = 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tPlayerInfo::IsVulnerable( void )\r\n{\r\n\treturn (( Tmr::GetTime() - m_last_hit_time ) > vPROJECTILE_INVULNERABILITY_INTERVAL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tPlayerInfo::ResetProjectileVulnerability( void )\r\n{\r\n\tm_last_hit_time = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tPlayerInfo::SetHitTime( Tmr::Time hit_time )\r\n{\r\n\tm_last_hit_time = hit_time;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tPlayerInfo::GetConnHandle( void )\r\n{\r\n\tif( m_Conn )\r\n\t{\r\n\t\treturn m_Conn->GetHandle();\r\n\t}\r\n\treturn Net::Conn::vHANDLE_INVALID;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tPlayerInfo::GetSkaterNumber( void )\r\n{\r\n\tDbg_Assert( m_Skater );\r\n\r\n\treturn m_Skater->GetSkaterNumber();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tPlayerInfo::GetLastObjectUpdateID( void )\r\n{\r\n\treturn m_last_object_update_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPlayerInfo::SetLastObjectUpdateID( int id )\r\n{\r\n\tm_last_object_update_id = id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tPlayerInfo::GetMaxObjectUpdates( void )\r\n{\r\n\tif( m_Conn->GetBandwidthType() == Net::Conn::vBROADBAND )\r\n\t{\r\n\t\treturn 2;\r\n\t}\r\n\t\r\n\treturn 1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tPlayerInfo::IsPendingPlayer( void )\r\n{\r\n\treturn m_flags.TestMask( mPENDING_PLAYER );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNewPlayerInfo::NewPlayerInfo(void)\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\tmpSkaterProfile = new Obj::CSkaterProfile;\r\n\tJumpInFrame = 0;\r\n\tProfile = 0;\r\n\tRating = 0;\r\n\tScore = 0;\r\n\tVehicleControlType = 0;\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNewPlayerInfo::~NewPlayerInfo(void)\r\n{\r\n\t\r\n\r\n\tDbg_Assert( mpSkaterProfile );\r\n\r\n\tdelete mpSkaterProfile;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/ServerList.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tServerList.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t06/131/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tServer List functionality\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/thread.h>\r\n\r\n#include <sys/mcman.h>\r\n\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/music/music.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#include <sk/modules/frontend/frontend.h>\r\n//#include <sk/modules/frontend/mainmenu.h>\r\n\r\n#ifdef __PLAT_NGPS__\r\n#include <gamenet/lobby.h>\r\n//#include <cengine/goaceng.h>\r\n#include <qr2/qr2.h>\r\n#include <ghttp/ghttp.h>\r\n#include <pt/pt.h>\r\n#include <sk/gamenet/ngps/p_buddy.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __PLAT_XBOX__\r\n#ifndef __PLAT_NGC__\r\n// Gamespy frame counter\r\n//extern unsigned long goa_frame_ct;\r\n\r\n//extern \"C\" \r\n//{\r\n//////////////////////////////////\r\n// Global IP addresses for gamespy\r\n//extern char\tqr_hostname[64];\r\n//extern char ServerListHostname[64];\r\n\r\n//}\r\n\r\nextern void GOASetUniqueID( const char* id );\r\n\r\n#endif\r\n#endif\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define vMOTD_WAIT_THRESHOLD\t\tTmr::Seconds( 7 )\r\n#define vTIME_BETWEEN_AUTO_REFRESH\tTmr::Seconds( 3 )\r\n#define vTIME_BETWEEN_MANUAL_REFRESH\tTmr::Seconds( 5 )\r\n\r\n#define\tvLAN_SERVER_LIST_TIMEOUT\t500\r\n#define\tvHTTP_TIMEOUT\t\t\t\tTmr::Seconds( 15 )\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n#ifdef __PLAT_NGPS__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic int\t\t\ts_motd_retry = 0;\r\n#endif // __PLAT_NGPS__\r\n\r\nstatic Tmr::Time \ts_last_refresh_time = 0;\r\nstatic bool \t\ts_refresh_pending = false;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool\tgEnteringFromMainMenu;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __PLAT_NGPS__\r\n//static bool s_no_servers_dialog_box_handler( Front::EDialogBoxResult result );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*SortKeyInfo* GetSortKey( int key_type )\r\n{\r\n\tint i;\r\n\r\n\tfor( i = 0; i < vNUM_SORT_KEYS; i++ )\r\n\t{\r\n\t\tif( s_sort_keys[i].KeyType == key_type )\r\n\t\t{\r\n\t\t\treturn &s_sort_keys[i];\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}*/\r\n#endif // __PLAT_NGPS__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#if 0\r\nstatic bool not_posted_dialog_box_handler( Front::EDialogBoxResult result )\r\n{\r\n    Mdl::FrontEnd* front = Mdl::FrontEnd::Instance();\r\n\r\n\tfront->SetActive( false );\r\n\r\n\treturn false;\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_server_list_state_code( const Tsk::Task< Manager >& task )\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\tManager& man = task.GetData();\r\n\r\n\tswitch( man.GetServerListState())\r\n\t{   \r\n\t\tcase vSERVER_LIST_STATE_WAIT:\r\n\t\t\t// A wait time of zero indicates we should wait for an outside force to change the state\r\n\t\t\tif( man.m_server_list_wait_time == 0 )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tif( Tmr::GetTime() > man.m_server_list_wait_time )\r\n\t\t\t{\r\n\t\t\t\tman.SetServerListState( man.GetNextServerListState());\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase vSERVER_LIST_STATE_RETRY_MOTD:\r\n\t\t{\r\n\t\t\t//Mdl::FrontEnd* front = Mdl::FrontEnd::Instance();\r\n\t\t\t//Front::DialogBox* dlg;\r\n\r\n\t\t\t//dlg = front->GetDialogBox();\r\n\t\t\t//dlg->GoBack();\r\n\r\n\t\t\t// fall-through intentional\r\n\t\t}\r\n\t\tcase vSERVER_LIST_STATE_STARTING_MOTD:\r\n\t\t{\r\n\t\t\tThread::PerThreadStruct\tnet_thread_data;\r\n\t\t\t\r\n\t\t\t//Dbg_Printf( \"Serverlist State: Starting MotD\\n\" );\r\n\r\n\t\t\t// Pause the music & streams before doing DNS lookup\r\n\t\t\tPcm::PauseStream( 1 );\r\n\t\t\t\r\n            \r\n\t\t\t// First, show the dialog box\r\n\t\t\tif( s_motd_retry == 0 )\r\n\t\t\t{\r\n\t\t\t\tScript::SpawnScript( \"launch_motd_wait_dialog\" );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tchar msg[256];\r\n\t\t\t\tScript::CScriptStructure* pStructure;\r\n\t\t\t\r\n\t\t\t\tpStructure = new Script::CScriptStructure;\r\n\t\t\t\tsprintf( msg, \"(%d) %s\", \ts_motd_retry,\r\n\t\t\t\t\t\t\t\t\t\t\tScript::GetLocalString( \"net_status_retry_motd\" ));\r\n\t\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"message\" ), ESYMBOLTYPE_STRING, msg );\r\n\t\t\t\tScript::SpawnScript( \"CreateMotdRetryDialog\", pStructure );\r\n\t\t\t\tdelete pStructure;\r\n\t\t\t}\r\n\r\n\t\t\tman.SetServerListState( vSERVER_LIST_STATE_WAIT );\r\n\t\t\tman.m_server_list_wait_time = 0;\r\n\r\n\t\t\t// Now spawn the thread that gets the message of the day\r\n\t\t\tnet_thread_data.m_pEntry = s_threaded_get_message_of_the_day;\r\n\t\t\tnet_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY;\r\n\t\t\tnet_thread_data.m_pStackBase = man.GetNetThreadStack();\r\n\t\t\tnet_thread_data.m_iStackSize = vNET_THREAD_STACK_SIZE;\r\n\t\t\tnet_thread_data.m_utid = 0x151;\r\n\t\t\tThread::CreateThread( &net_thread_data );\r\n\t\t\tman.SetNetThreadId( net_thread_data.m_osId );\r\n\t\t\tStartThread( man.GetNetThreadId(), &man );\r\n\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vSERVER_LIST_STATE_GETTING_MOTD:\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\t\t\tif(( Tmr::GetTime() - man.m_ghttp_start_time ) > vHTTP_TIMEOUT )\r\n\t\t\t{\r\n\t\t\t\tghttpCancelRequest( man.m_ghttp_request );\r\n\t\t\t\tman.SetServerListState( vSERVER_LIST_STATE_FAILED_MOTD );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tghttpThink(); \r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vSERVER_LIST_STATE_TRACK_USAGE:\r\n\t\t{\r\n\t\t\tThread::PerThreadStruct\tnet_thread_data;\r\n\t\t\t\r\n\t\t\tghttpCleanup();\r\n\r\n\t\t\t//Dbg_Printf( \"Serverlist State: Starting track usage\\n\" );\r\n\r\n\t\t\t// Pause the music & streams before doing DNS lookup\r\n\t\t\tPcm::PauseStream( 1 );\r\n            \r\n\t\t\t// Now spawn the thread that gets the message of the day\r\n\t\t\tnet_thread_data.m_pEntry = s_threaded_track_usage;\r\n\t\t\tnet_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY;\r\n\t\t\tnet_thread_data.m_pStackBase = man.GetNetThreadStack();\r\n\t\t\tnet_thread_data.m_iStackSize = vNET_THREAD_STACK_SIZE;\r\n\t\t\tnet_thread_data.m_utid = 0x151;\r\n\t\t\tThread::CreateThread( &net_thread_data );\r\n\t\t\tman.SetNetThreadId( net_thread_data.m_osId );\r\n\t\t\tStartThread( man.GetNetThreadId(), &man );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vSERVER_LIST_STATE_TRACKING_USAGE:\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\t\t\tif(( Tmr::GetTime() - man.m_ghttp_start_time ) > vHTTP_TIMEOUT )\r\n\t\t\t{\r\n\t\t\t\tghttpCancelRequest( man.m_ghttp_request );\r\n\t\t\t\tman.SetServerListState( vSERVER_LIST_STATE_SHOW_MOTD );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tghttpThink(); \r\n\t\t\t}\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vSERVER_LIST_STATE_SHOW_MOTD:\r\n\t\t{\r\n\t\t\tScript::CScriptStructure* pStructure;\r\n\t\t\t\r\n\t\t\t//Dbg_Printf( \"Serverlist State: Got MotD\\n\" );\r\n\r\n\t\t\tghttpCleanup();\r\n\r\n\t\t\tman.RemoveMessageOfTheDay();\r\n\r\n\t\t\tpStructure = new Script::CScriptStructure;\r\n\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"message\" ), ESYMBOLTYPE_STRING, man.m_motd );\r\n\t\t\t\r\n\t\t\tScript::RunScript( \"create_motd_menu\", pStructure );\r\n\t\t\t\r\n\t\t\tdelete pStructure;\r\n\t\t\t\r\n\t\t\tman.SetServerListState( vSERVER_LIST_STATE_WAIT );\r\n\t\t\tman.m_server_list_wait_time = 0;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vSERVER_LIST_STATE_FAILED_MOTD:\r\n\t\t{\r\n\t\t\tDbg_Printf( \"In vSERVER_LIST_STATE_FAILED_MOTD\\n\" );\r\n\t\t\tghttpCleanup();\r\n\t\t\tScript::RunScript( \"CreateMotdFailedDialog\" );\r\n\r\n\t\t\t// NOTE: USED TO CALL THIS FROM THE \"OK\" DIALOG BOX HANDLER\r\n\t\t\t// gamenet_man->SetServerListState( vSERVER_LIST_STATE_STARTING_LOBBY_LIST )\r\n\t\t\t\t\t\t\r\n\t\t\t//man.SetServerListState( vSERVER_LIST_STATE_WAIT );\r\n\t\t\tman.SetServerListState( vSERVER_LIST_STATE_SHUTDOWN );\r\n\t\t\tman.m_server_list_wait_time = 0;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vSERVER_LIST_STATE_STARTING_LOBBY_LIST:\r\n\t\t{\r\n\t\t\t// First, show the dialog box\r\n\t\t\tScript::RunScript( \"CreateGettingLobbyListDialog\" );\r\n\r\n\t\t\t// Free up the previous lobby list\r\n\t\t\tman.mpLobbyMan->StopLobbyList();\r\n\t\t\t\r\n\t\t\t// Now spawn the lobby list -- this function also changes the state\r\n\t\t\tman.mpLobbyMan->StartLobbyList();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vSERVER_LIST_STATE_GETTING_LOBBY_LIST:\r\n\t\t{\r\n\r\n\t\t\t//Dbg_Printf( \"Serverlist State: Getting Lobby List\\n\" );\r\n            \r\n            man.SetServerListState( vSERVER_LIST_STATE_WAIT );\r\n\t\t\tman.m_server_list_wait_time = 0;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vSERVER_LIST_STATE_FAILED_LOBBY_LIST:\r\n\t\t{\r\n\t\t\tScript::CScriptStructure* pStructure;\r\n\t\t\t\r\n\t\t\t//Dbg_Printf( \"Failed lobby list\\n\" );\r\n\t\t\tman.mpLobbyMan->StopLobbyList();\r\n\t\t\r\n\t\t\tpStructure = new Script::CScriptStructure;\r\n\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"message\" ), ESYMBOLTYPE_STRING, Script::GetLocalString( \"net_status_gamespy_no_connect\" ));\r\n\r\n\t\t\tScript::RunScript( \"CreateFailedLobbyListDialog\", pStructure );\r\n\r\n\t\t\tdelete pStructure;\r\n\t\t\t\t\t\r\n\t\t\tman.SetServerListState( vSERVER_LIST_STATE_SHUTDOWN );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vSERVER_LIST_STATE_GOT_LOBBY_LIST:\r\n\t\t{\r\n\t\t\t// If we didn't get any lobbies, that either means the matchmaker's down or their\r\n\t\t\t// connection isn't valid\r\n\t\t\tif( man.mpLobbyMan->GetLobbyInfo( 0 ) == NULL )\r\n\t\t\t{\r\n\t\t\t\tScript::CScriptStructure* pStructure = new Script::CScriptStructure;\r\n\t\t\t\t\r\n\t\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"message\" ), ESYMBOLTYPE_STRING, Script::GetLocalString( \"net_status_gamespy_no_connect\" ));\r\n\r\n\t\t\t\tScript::RunScript( \"CreateFailedLobbyListDialog\", pStructure );\r\n\r\n\t\t\t\tdelete pStructure;\r\n\t\t\t\t\r\n\t\t\t\tman.SetServerListState( vSERVER_LIST_STATE_SHUTDOWN );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tman.SetServerListState( vSERVER_LIST_STATE_FILL_LOBBY_LIST );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tPcm::PauseStream( 0 );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vSERVER_LIST_STATE_FILL_LOBBY_LIST:\r\n\t\t{\r\n\t\t\tman.mpLobbyMan->FillLobbyList();\r\n\t\t\tman.SetServerListState( vSERVER_LIST_STATE_SHUTDOWN );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n#endif\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::s_auto_refresh_code( const Tsk::Task< Manager >& task )\r\n{\r\n\tManager& man = task.GetData();\r\n\tstatic Tmr::Time s_refresh_time = 0;\r\n\r\n\tif(( Tmr::GetTime() - s_refresh_time ) > vTIME_BETWEEN_AUTO_REFRESH )\r\n\t{\r\n\t\ts_refresh_time = Tmr::GetTime();\r\n#ifdef __PLAT_XBOX__\r\n\t\tman.RefreshServerList( true );\r\n#endif\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( s_refresh_pending )\r\n\t\t{\r\n\t\t\tif(( Tmr::GetTime() - s_last_refresh_time ) > vLAN_SERVER_LIST_TIMEOUT )\r\n\t\t\t{\r\n\t\t\t\tLst::Search< ServerInfo > sh;\r\n\t\t\t\tServerInfo* server, *next;\r\n\r\n\t\t\t\tman.ClearServerList();\r\n\t\t\t\t\t\t\r\n\t\t\t\tfor( server = sh.FirstItem( man.m_temp_servers ); server; server = next )\r\n\t\t\t\t{\r\n\t\t\t\t\tnext = sh.NextItem();\r\n\t\t\t\t\tserver->Remove();\r\n\r\n\t\t\t\t\tman.AddServerToMenu( server, man.m_servers.CountItems());\r\n\t\t\t\t\tman.m_servers.AddToTail( server );\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\tScript::RunScript( \"update_lobby_server_list\" );\r\n\t\t\t\t\r\n\t\t\t\ts_refresh_pending = false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Handler Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/* Respond to a client who is looking for games to join on the LAN*/\r\n/* Tell them info about the game                                  */\r\n/******************************************************************/\r\n\r\nint Manager::s_handle_server_response( Net::MsgHandlerContext* context )\r\n{\r\n\tMsgServerDescription* msg;\r\n\tServerInfo *server_info;\r\n\tManager* manager = (Manager*) context->m_Data;\r\n\tint i;\r\n\r\n\t//Dbg_Printf( \"GOT SERVER RESPONSE!\\n\" );\r\n\r\n\tmsg = (MsgServerDescription*) context->m_Msg;\r\n\r\n\tif( context->m_MsgLength != sizeof( MsgServerDescription ))\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\t\r\n#ifdef\t__PLAT_XBOX__\r\n    if( manager->ServerAlreadyInList( msg->m_Name, &msg->m_XboxAddr ))\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n#else\r\n\tif( manager->ServerAlreadyInList( msg->m_Name, context->m_Conn->GetIP()))\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n#endif\r\n\r\n\t\r\n#ifdef\t__PLAT_XBOX__\r\n\tif( memcmp( msg->m_Nonce, context->m_App->m_Nonce, 8 ))\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n#endif\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\tserver_info = new ServerInfo;\r\n\t\r\n\tstrcpy( server_info->m_Name, msg->m_Name );\r\n\tserver_info->m_Ip = context->m_Conn->GetIP();\r\n\tserver_info->m_Latency = Tmr::GetTime() - msg->m_Timestamp;\r\n\tstrcpy( server_info->m_Level, msg->m_Level );\r\n\tstrcpy( server_info->m_Mode, msg->m_Mode );\r\n\tserver_info->m_MaxPlayers = msg->m_MaxPlayers;\r\n\tserver_info->m_NumPlayers = msg->m_NumPlayers;\r\n\tserver_info->m_MaxObservers = msg->m_MaxObservers;\r\n\tserver_info->m_NumObservers = msg->m_NumObservers;\r\n\tserver_info->m_Password = msg->m_Password;\r\n\tserver_info->m_GameStarted = msg->m_GameStarted;\r\n\tserver_info->m_HostMode = msg->m_HostMode;\r\n\tserver_info->m_Ranked = msg->m_Ranked;\r\n\tserver_info->m_SkillLevel = msg->m_SkillLevel;\r\n\tserver_info->m_Port = vHOST_PORT;\r\n#ifdef __PLAT_XBOX__\r\n\tmemcpy( &server_info->m_XboxKeyId, &msg->m_XboxKeyId, sizeof( XNKID ));\r\n\tmemcpy( &server_info->m_XboxKey, &msg->m_XboxKey, sizeof( XNKEY ));\t\r\n\tmemcpy( &server_info->m_XboxAddr, &msg->m_XboxAddr, sizeof( XNADDR ));\t\r\n#endif    \r\n    \r\n\tfor( i = 0; i < server_info->m_NumPlayers; i++ )\r\n\t{\r\n\t\tserver_info->AddPlayer( msg->m_PlayerNames[i] );\r\n\t}\r\n\r\n\t//manager->AddServerToMenu( server_info, manager->m_servers.CountItems());\r\n\r\n\t//manager->m_servers.AddToTail( server_info );\r\n\tmanager->m_temp_servers.AddToTail( server_info );\r\n    \r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#ifdef __PLAT_NGPS__\r\n\r\nvoid\tManager::s_create_game_callback( PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, \r\n\t\t\t\t\t\t\t\t\t\t\tvoid * param )\r\n{\r\n\tif( success )\r\n\t{\r\n\t\t//Dbg_Printf( \"Joined Created Room\\n\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tswitch( result )\r\n\t\t{\r\n\t\t\tcase PEERFullRoom:\r\n\t\t\t\t//Dbg_Printf( \"Couldnt join created room. Full\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase PEERInviteOnlyRoom:\r\n\t\t\t\t//Dbg_Printf( \"Couldnt join created room. Invite Only\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase PEERBannedFromRoom:\r\n\t\t\t\t//Dbg_Printf( \"Couldnt join created room. Banned\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase PEERBadPassword:\r\n\t\t\t\t//Dbg_Printf( \"Couldnt join created room. Bad Password\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase PEERAlreadyInRoom:\r\n\t\t\t\t//Dbg_Printf( \"Couldnt join created room. Already in room\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase PEERNoTitleSet:\r\n\t\t\t\t//Dbg_Printf( \"Couldnt join created room. No Title Set\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\t//Dbg_Printf( \"Couldnt join created room. General error\\n\" );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n#endif // __PLAT_NGPS__\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::PostGame( void )\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\tNet::Manager * net_man = Net::Manager::Instance();\r\n\t\r\n    Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\t\r\n\tmpLobbyMan->StartReportingGame();\r\n\tif( mpBuddyMan->IsLoggedIn())\r\n\t{\r\n\t\tchar location[1024];\r\n\t\tconst char *server_name;\r\n\t\tScript::CScriptStructure* pStructure;\r\n\t\tPrefs::Preferences* pPreferences;\r\n\r\n\t\tpPreferences = GetNetworkPreferences();\r\n\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"server_name\") );\r\n\t\tpStructure->GetText( \"ui_string\", &server_name, true );\r\n\r\n\t\tif( mpLobbyMan->GetPeer())\r\n\t\t{\r\n\t\t\tsprintf( location, \"%d:%d:%d:%s (%s)\", net_man->GetPublicIP(), peerGetPrivateIP( mpLobbyMan->GetPeer()), vHOST_PORT, server_name, mpLobbyMan->GetLobbyName());\r\n\t\t}\r\n\t\tmpBuddyMan->SetStatusAndLocation( GP_PLAYING, (char*) Script::GetString( \"homie_status_hosting\" ), location );\r\n\t}\r\n\tMem::Manager::sHandle().PopContext();\r\n#endif\r\n}\r\n\r\n\r\n/*void Manager::RequestMatchmakerConnect( void )\r\n{\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tint result;\r\n\r\n\tm_server->SetForeignPacketHandler( gamespy_data_handler );\r\n\ts_gamespy_parse_data[0] = '\\0';\r\n\r\n\t// Hardcode the IP of the master server until we get the message of the day squared away\r\n\tresult = qr_init_socket( NULL, m_server->GetSocket(), \"thps4ps2\", \"H2r8W1\", basic_callback,\r\n\t\t\t\t\t\t\t info_callback, rules_callback, players_callback, this );\r\n\t// Uncomment for media burns\r\n\t//result = qr_init_socket( NULL, m_server->GetSocket(), \"thps3media\", \"tRKg39\", basic_callback,\r\n\t\t\t\t\t\t\t //info_callback, rules_callback, players_callback, this );\r\n\t \r\n\tswitch( result )\r\n\t{\r\n\t\tcase 0:\r\n\t\t\t// success:\r\n\t\t\tbreak;\r\n\t\tcase E_GOA_WSOCKERROR:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Failed to initialize GameSpy query report toolkit due to Socket Error\\n\" ));\r\n\t\t\tbreak;\r\n\t\tcase E_GOA_BINDERROR:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Failed to initialize GameSpy query report toolkit due to Bind Error\\n\" ));\r\n\t\t\tbreak;\r\n\t\tcase E_GOA_CONNERROR:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Failed to initialize GameSpy query report toolkit due to Connection Error\\n\" ));\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Failed to initialize Gamespy query report toolkit\\n\" ));\r\n\t\t\tbreak;\r\n\t}\r\n\r\n#endif\r\n\t\r\n#ifdef __PLAT_NGPS__\r\n\ts_game_start_time = Tmr::GetTime();\r\n\ts_notified_user_not_connected = false;\r\n\ts_retried_game_post = false;\r\n\tgGotGamespyCallback = false;\r\n#endif\t\t// __PLAT_NGC__\r\n\tmlp_manager->AddLogicTask( *m_process_gamespy_queries_task );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetServerFocus( ServerInfo* server )\r\n{\r\n\tClearServerFocus();\r\n\tserver->m_InFocus = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::ClearServerFocus( void )\r\n{\r\n\tLst::Search< ServerInfo > sh;\r\n\tServerInfo* server;\r\n\r\n\tfor( server = sh.FirstItem( m_servers ); server; server = sh.NextItem())\r\n\t{\r\n\t\tserver->m_InFocus = false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nServerInfo*\t\tManager::GetServerFocus( void )\r\n{\r\n\tLst::Search< ServerInfo > sh;\r\n\tServerInfo* server;\r\n\r\n\tfor( server = sh.FirstItem( m_servers ); server; server = sh.NextItem())\r\n\t{\r\n\t\tif( server->m_InFocus )\r\n\t\t{\r\n\t\t\treturn server;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tManager::NumServersListed( void )\r\n{\r\n\tLst::Search< ServerInfo > sh;\r\n\tServerInfo* server;\r\n\tint num_listed;\r\n\r\n\tnum_listed = 0;\r\n\tfor( server = sh.FirstItem( m_servers ); server; server = sh.NextItem())\r\n\t{\r\n\t\tif( server->m_Listed )\r\n\t\t{\r\n\t\t\tnum_listed++;\r\n\t\t}\r\n\t}\r\n\r\n\treturn num_listed;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::AddServerToMenu( ServerInfo* server, int index )\r\n{   \r\n\tScript::CStruct* p_item_params;\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\tuint32 server_id;\r\n\t\t\r\n\t// If this is our first listed server, destroy the \"no servers found\" message\r\n\tif( NumServersListed() == 0 )\r\n\t{\r\n\t\tScript::RunScript( \"destroy_server_menu_children\" );\r\n\t}\r\n\r\n\tScript::RunScript( \"prepare_server_menu_for_new_children\" );\r\n\t\t\r\n\tp_item_params = new Script::CStruct;\t\r\n\tp_item_params->AddString( \"text\", server->m_Name );\r\n\tp_item_params->AddString( \"mode\", server->m_Mode );\r\n\tprintf(\"The game mode is: %s\\n\", server->m_Mode );\r\n#ifdef __PLAT_NGPS__\r\n\tif( InInternetMode())\r\n\t{\r\n\t\tserver_id = (uint32) server->m_GServer;\r\n\t\t\r\n\t}\r\n\telse\r\n#endif\r\n\t{\r\n\t\tserver_id = (uint32) server;\r\n\t}\r\n\t\r\n\tp_item_params->AddChecksum( \"id\", server_id );\r\n\tp_item_params->AddChecksum( \"parent\", Script::GenerateCRC( \"server_list_menu\" ));\r\n\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"choose_selected_server\"));\r\n\tp_item_params->AddChecksum( \"focus_script\",Script::GenerateCRC(\"describe_selected_server\"));\r\n\r\n\t// create the parameters that are passed to the X script\r\n\tScript::CStruct *p_script_params= new Script::CStruct;\r\n\tp_script_params->AddChecksum( \"id\", server_id );\t\r\n\tp_item_params->AddStructure(\"pad_choose_params\",p_script_params);\t\t\t\r\n\tp_item_params->AddStructure(\"focus_params\",p_script_params);\r\n\r\n\tScript::RunScript(\"server_list_menu_add_item\",p_item_params);\r\n\t\r\n\tserver->m_Listed = true;\r\n\r\n\tdelete p_item_params;\r\n\tdelete p_script_params;\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#ifdef __PLAT_NGPS__\r\n\r\nGHTTPBool\tManager::MotdComplete( GHTTPRequest request, GHTTPResult result, char* buffer, int buffer_len, \r\n\t\t\t\t\t\t  void* param )\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tbool succeeded;\r\n\r\n\t\r\n    \r\n\tsucceeded = false;\r\n\tif( result == GHTTPSuccess )\r\n\t{   \r\n\t\tchar* token;\r\n\t\tchar* message, *ip_ptr;\r\n\t\tchar temp_motd[4096];\r\n\t\tint server_ip;\r\n\r\n\t\tstrncpy( temp_motd, buffer, 4095 );\r\n\t\ttemp_motd[4095] = '\\0';\r\n\t\t//Dbg_Printf( \"Got Message of the day: %s\\n\", temp_motd );\r\n\t\t\r\n\t\t// Checksum comes first and is delimited by a space\r\n\t\ttoken = strtok( temp_motd, \" \" );\r\n\t\tif( token )\r\n\t\t{\r\n\t\t \tuint32 checksum;\r\n\r\n\t\t\tchecksum = atoi( token );\r\n\t\t\t//Dbg_Printf( \"checksum is %d\\n\", checksum );\r\n\t\t\tip_ptr = token + strlen( token ) + 1;\t// skip the checksum\r\n\t\t\tif( checksum == Script::GenerateCRC( ip_ptr ))\r\n\t\t\t{\r\n\t\t\t\t//Dbg_Printf( \"Matched!\\n\" );\r\n\t\t\t\t// Next token is the IP address for the gamespy servers\r\n\t\t\t\tip_ptr = strtok( NULL, \" \" );\r\n\t\t\t\tif( ip_ptr )\r\n\t\t\t\t{\r\n\t\t\t\t\t//Dbg_Printf( \"Got an IP Pointer of %s!\\n\", ip_ptr );\r\n\t\t\t\t\tmessage = strtok( NULL, \"\\n\" );\r\n\t\t\t\t\tif( message )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//Dbg_Printf( \"Got a message of %s\\n\", message );\r\n\t\t\t\t\t\tstrncpy( gamenet_man->m_motd, message, 1023 );\r\n\t\t\t\t\t\tgamenet_man->m_motd[1023] = '\\0';\r\n\r\n\t\t\t\t\t\tserver_ip = atoi( ip_ptr );\r\n\t\t\t\t\t\t\r\n                        //sprintf( ServerListHostname, \"%s\", inet_ntoa(*(struct in_addr*) &server_ip ));\r\n\t\t\t\t\t\t//sprintf( qr_hostname, \"%s\", inet_ntoa(*(struct in_addr*) &server_ip ));\r\n\r\n\t\t\t\t\t\t//Dbg_Printf( \"GameSpy Server is %s\\n\", ServerListHostname );\r\n\t\t\t\t\t\tsucceeded = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( succeeded )\r\n\t\t{   \r\n\t\t\tgamenet_man->m_got_motd = true;\r\n\t\t\tgamenet_man->SetServerListState( vSERVER_LIST_STATE_TRACK_USAGE );\r\n\t\t}\r\n\t}\r\n\r\n\tif( !succeeded )\r\n\t{\r\n\t\tDbg_Printf( \"Error Downloading motd: %d\\n\", result );\r\n\r\n\t\t// No retries in THPS4. We're just going to use our neversoft website and that's it\r\n\t\t/*s_motd_retry = s_motd_retry + 1;\r\n\t\tif( gamenet_man->m_master_servers[ s_motd_retry ][0] != '\\0' )\r\n\t\t{\r\n\t\t\tgamenet_man->SetServerListState( vSERVER_LIST_STATE_RETRY_MOTD );\r\n\t\t\treturn GHTTPTrue;\r\n\t\t}*/\r\n\r\n\t\tgamenet_man->SetServerListState( vSERVER_LIST_STATE_FAILED_MOTD );\r\n\t}\r\n\r\n\treturn GHTTPTrue;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid MotdProgress( GHTTPRequest request, GHTTPState state, const char * buffer, int bufferLen,\r\n\t\t\t\t\tint bytesReceived, int totalSize, void * param )\r\n{\r\n\t\r\n\r\n\tswitch( state )\r\n\t{\r\n\t\tcase GHTTPHostLookup:\r\n\t\t\tDbg_Printf( \"Lookin up HTTP host...\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GHTTPConnecting:\r\n\t\t\tDbg_Printf( \"Connecting to HTTP host...\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GHTTPSendingRequest:\r\n\t\t\tDbg_Printf( \"Sending Request to HTTP host...\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GHTTPPosting:\r\n\t\t\tbreak;\r\n\t\tcase GHTTPWaiting:\r\n\t\t\tDbg_Printf( \"Waiting for response from HTTP host...\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GHTTPReceivingStatus:\r\n\t\t\tDbg_Printf( \"Receiving status....\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GHTTPReceivingHeaders:\r\n\t\t\tDbg_Printf( \"Receiving headers....\\n\" );\r\n\t\t\tbreak;\r\n\t\tcase GHTTPReceivingFile:\r\n\t\t\tDbg_Printf( \"Receiving file: %d bytes....\\n\", bytesReceived );\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGHTTPBool\tManager::TrackUsageComplete( GHTTPRequest request, GHTTPResult result, char* buffer, int buffer_len, \r\n\t\t\t\t\t\t  void* param )\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\t//Dbg_Printf( \"Track usage complete!!!\\n\" );\r\n\r\n\tgamenet_man->SetServerListState( vSERVER_LIST_STATE_SHOW_MOTD );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::s_threaded_get_message_of_the_day( Manager* gamenet_man )\r\n{\r\n\tchar motd_path[256];\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\t// Register this thread with the sockets API\r\n\tsockAPIregthr();\r\n\r\n\t// Wait a bit before starting the http transfer \r\n\tmsleep( 100 );\r\n\r\n\tgamenet_man->SetServerListState( vSERVER_LIST_STATE_GETTING_MOTD );\r\n\t\r\n\tgamenet_man->m_ghttp_start_time = Tmr::GetTime();\r\n\tsprintf( motd_path, \"http://www.thugonline.com/motd.txt\" );\r\n\t//sprintf( motd_path, \"http://www.neversoft.com/thps5/motd.txt\" );\r\n\tgamenet_man->m_ghttp_request = ghttpGetEx( \tmotd_path,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNULL,\r\n\t\t\t\t\t\t\t\t\t\t\t\tgamenet_man->m_motd,\r\n\t\t\t\t\t\t\t\t\t\t\t\t1024,\r\n\t\t\t\t\t\t\t\t\t\t\t\tNULL,\r\n\t\t\t\t\t\t\t\t\t\t\t\tGHTTPFalse,\r\n\t\t\t\t\t\t\t\t\t\t\t\tGHTTPFalse,\r\n\t\t\t\t\t\t\t\t\t\t\t\tMotdProgress,\r\n\t\t\t\t\t\t\t\t\t\t\t\tMotdComplete,\r\n\t\t\t\t\t\t\t\t\t\t\t\tgamenet_man );\r\n\r\n\t// Deregister this thread with the sockets API\r\n\tsockAPIderegthr();\r\n\t\t\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::s_threaded_track_usage( Manager* gamenet_man )\r\n{\r\n\tPrefs::Preferences*\tprefs;\r\n\tScript::CStruct* pStructure;\r\n\tconst char* unique_id = \"123456789\";\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\r\n\t// Register this thread with the sockets API\r\n\tsockAPIregthr();\r\n        \r\n\tprefs = gamenet_man->GetNetworkPreferences();\r\n\tpStructure = prefs->GetPreference( Script::GenerateCRC(\"unique_id\"));\r\n\tpStructure->GetString( \"ui_string\", &unique_id );\r\n\t//GOASetUniqueID( unique_id );\r\n\r\n\tgamenet_man->m_ghttp_start_time = Tmr::GetTime();\r\n\tgamenet_man->m_ghttp_request = ptTrackUsage( \t0,\t// int userID ( if not using Presence & Messaging, send zero )\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tvGAMESPY_PRODUCT_ID,\t// int productID,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"1.0\",\t//const char * versionUniqueID,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t0,\t//int distributionID,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGHTTPFalse,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tTrackUsageComplete );\t//PTBool blocking\r\n\r\n\tgamenet_man->SetServerListState( vSERVER_LIST_STATE_TRACKING_USAGE );\r\n\r\n\t// Deregister this thread with the sockets API\r\n\tsockAPIderegthr();\r\n\t\t\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::RemoveMessageOfTheDay( void )\r\n{\r\n\t//ghttpCleanup();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::s_server_list_callback( PEER peer, PEERBool success, const char * name, SBServer server, PEERBool staging, \r\n\t\t\t\t\t\t\t\t\t  int msg, int progress, void * param )\r\n{\r\n\tManager* man = (Manager*) param;\r\n\tif( success )\r\n\t{\r\n\t\tswitch( msg )\r\n\t\t{\r\n\t\t\r\n\t\t\tcase PEER_ADD:\r\n\t\t\t{\r\n\t\t\t\tServerInfo* server_info;\r\n\t\t\t\tint i;\r\n\t\t\t\t\r\n\t\t\t\tDbg_Printf( \"****** ADDING SERVER %p : %s\\n\", server, name );\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\t\r\n\t\t\t\tserver_info = new ServerInfo;\r\n\t\t\t\tserver_info->m_GServer = server;\r\n\t\t\t\tstrncpy( server_info->m_Name, name, vMAX_SERVER_NAME_LEN );\r\n\t\t\t\tserver_info->m_Name[vMAX_SERVER_NAME_LEN] = '\\0';\r\n\t\t\t\tserver_info->m_Latency = SBServerGetPing( server );\r\n\r\n\t\t\t\t// Check if we're behind the same NAT\r\n                if( SBServerHasPrivateAddress( server ))\r\n\t\t\t\t{\r\n\t\t\t\t\t// If so, we'll have the same public IP\r\n                    if( SBServerGetPublicInetAddress( server ) == peerGetLocalIP( peer ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tserver_info->m_Ip = SBServerGetPrivateInetAddress( server );\t\t\t\t\t\t\r\n\t\t\t\t\t\tserver_info->m_Port = vHOST_PORT;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// If we're not behind the same NAT, check if they are behind\r\n\t\t\t\t\t\t// a promiscuous NAT or, perhaps, not behind a NAT at all.  If so\r\n\t\t\t\t\t\t// we can directly connect to their public IP\r\n\t\t\t\t\t\tif( SBServerDirectConnect( server ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tserver_info->m_Ip = SBServerGetPublicInetAddress( server );\r\n\t\t\t\t\t\t\tserver_info->m_Port = SBServerGetPublicQueryPort( server );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tserver_info->m_Ip = SBServerGetPublicInetAddress( server );\r\n\t\t\t\t\t\t\tserver_info->m_Port = SBServerGetPublicQueryPort( server );\r\n\t\t\t\t\t\t\tserver_info->m_CanDirectConnect = false;\r\n\t\t\t\t\t\t\tserver_info->m_Latency = 9999;\t// We can't get the ping of servers behind non-promiscuous NATs\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif( SBServerDirectConnect( server ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tserver_info->m_Ip = SBServerGetPublicInetAddress( server );\r\n\t\t\t\t\t\tserver_info->m_Port = SBServerGetPublicQueryPort( server );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tserver_info->m_Ip = SBServerGetPublicInetAddress( server );\r\n\t\t\t\t\t\tserver_info->m_Port = SBServerGetPublicQueryPort( server );\r\n\t\t\t\t\t\tserver_info->m_CanDirectConnect = false;\r\n\t\t\t\t\t\tserver_info->m_Latency = 9999;\t// We can't get the ping of servers behind non-promiscuous NATs\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tDbg_Printf( \"Percent Done: %d : Server %s ping (%d)\\n\", (int) progress, server_info->m_Name, server_info->m_Latency );\r\n\t\t\t\tstrcpy( server_info->m_Level, SBServerGetStringValue( server, \"mapname\",\"...\"));\r\n\t\t\t\tstrcpy( server_info->m_Mode, SBServerGetStringValue( server, \"gametype\",\"...\"));\r\n\t\t\t\tserver_info->m_NumPlayers = SBServerGetIntValue( server, \"numplayers\", 1 );\r\n\t\t\t\tserver_info->m_MaxPlayers = SBServerGetIntValue( server, \"maxplayers\", 8 );\r\n\t\t\t\tserver_info->m_NumObservers = SBServerGetIntValue( server, \"numobservers\", 0 );\r\n\t\t\t\tserver_info->m_MaxObservers = SBServerGetIntValue( server, \"maxobservers\", 1 );\r\n\t\t\t\tserver_info->m_Password = SBServerGetBoolValue( server, \"password\", false );\r\n\t\t\t\tserver_info->m_GameStarted = SBServerGetBoolValue( server, \"started\", false );\r\n\t\t\t\tserver_info->m_HostMode = SBServerGetIntValue( server, \"hostmode\", vHOST_MODE_SERVE );\r\n\t\t\t\tserver_info->m_Ranked = SBServerGetIntValue( server, \"ranked\", 0 );\r\n\t\t\t\tserver_info->m_SkillLevel = SBServerGetIntValue( server, \"skilllevel\", vSKILL_LEVEL_DEFAULT );\r\n\r\n\t\t\t\tDbg_Printf( \"Numplayers %d\\n\", server_info->m_NumPlayers )\r\n\t\t\t\tfor( i = 0; i < server_info->m_NumPlayers; i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tint rating;\r\n\r\n\t\t\t\t\trating = SBServerGetPlayerIntValue( server, i, \"rating\", 0 );\r\n\t\t\t\t\tDbg_Printf( \"Adding player %s with rating %d\\n\", (char*) SBServerGetPlayerStringValue( server, i, \"player\",\"...\" ), rating );\r\n\t\t\t\t\tserver_info->AddPlayer((char*) SBServerGetPlayerStringValue( server, i, \"player\",\"...\" ), rating );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tman->m_servers.AddToTail( server_info );\r\n\t\t\t\tif( SBServerHasBasicKeys( server ))\r\n\t\t\t\t{\r\n\t\t\t\t\tman->AddServerToMenu( server_info, man->m_servers.CountItems() - 1 );\r\n\t\t\t\t\tScript::RunScript( \"update_lobby_server_list\" );\r\n\t\t\t\t\tserver_info->m_HasBasicInfo = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\r\n\t\t\t//   Remove this server from the list.  The server object for this server\r\n\t\t\t//   should not be used again after this callback returns.\r\n\t\t\tcase PEER_REMOVE:\r\n\t\t\t{\r\n\t\t\t\tLst::Search< ServerInfo > sh;\r\n\t\t\t\tServerInfo* server_info, *next;\r\n\t\t\t\tScript::CStruct* pParams;\r\n\t\t\t\t\r\n\t\t\t\tDbg_Printf( \"****** REMOVING SERVER %p\\n\", server );\r\n\r\n\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\tpParams->AddChecksum( \"server_id\", (uint32) server );\r\n\t\t\t\tScript::RunScript( \"destroy_lobby_server\", pParams );\r\n\t\t\t\tdelete pParams;\r\n\t    \r\n\t\t\t\tfor( server_info = sh.FirstItem( man->m_servers ); server_info; server_info = next )\r\n\t\t\t\t{\r\n\t\t\t\t\tnext = sh.NextItem();\r\n\t\t\t\t\tif( server_info->m_GServer == server )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdelete server_info;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tScript::RunScript( \"update_lobby_server_list\" );\r\n                break;\r\n\t\t\t}\r\n\r\n\t\t\t//   Clear the list.  This has the same effect as if this was called\r\n\t\t\t//   with PEER_REMOVE for every server listed.\r\n\t\t\tcase PEER_CLEAR:\r\n\t\t\t{\r\n\t\t\t\tDbg_Printf( \"****** CLEAR SERVER LIST\\n\" );\r\n\r\n\t\t\t\tman->ClearServerList( false );\r\n\t\t\t\tman->FreeServerList();\r\n\r\n\t\t\t\tScript::RunScript( \"update_lobby_server_list\" );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t//   This server is already on the list, and its been updated.\r\n\t\t\tcase PEER_UPDATE:\r\n\t\t\t{\r\n\t\t\t\tLst::Search< ServerInfo > sh;\r\n\t\t\t\tServerInfo* server_info;\r\n\t\t\t\tint i;\r\n\t\t\t\t\r\n\t\t\t\tif( SBServerHasFullKeys( server ))\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Printf( \"****** FULLY UPDATING SERVER %p\\n\", server );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Printf( \"****** PARTIALLY UPDATING SERVER %p\\n\", server );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t    \r\n\t\t\t\tfor( server_info = sh.FirstItem( man->m_servers ); server_info; server_info = sh.NextItem())\r\n\t\t\t\t{\r\n\t\t\t\t\tif( server_info->m_GServer == server )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrncpy( server_info->m_Name, name, vMAX_SERVER_NAME_LEN );\r\n\t\t\t\t\t\tserver_info->m_Name[vMAX_SERVER_NAME_LEN] = '\\0';\r\n\t\t\t\t\t\t//server_info->m_Ip = SBServerGetPublicInetAddress( server );\r\n\t\t\t\t\t\tif( server_info->m_CanDirectConnect )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tserver_info->m_Latency = SBServerGetPing( server );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tDbg_Printf( \"Percent Done: %d : Server %s ping (%d)\\n\", (int) progress, server_info->m_Name, SBServerGetPing(server));\r\n\t\t\t\t\t\tstrcpy( server_info->m_Level, SBServerGetStringValue( server, \"mapname\",\"...\"));\r\n\t\t\t\t\t\tstrcpy( server_info->m_Mode, SBServerGetStringValue( server, \"gametype\",\"...\"));\r\n\t\t\t\t\t\tserver_info->m_NumPlayers = SBServerGetIntValue( server, \"numplayers\", 1 );\r\n\t\t\t\t\t\tserver_info->m_MaxPlayers = SBServerGetIntValue( server, \"maxplayers\", 8 );\r\n\t\t\t\t\t\tserver_info->m_NumObservers = SBServerGetIntValue( server, \"numobservers\", 0 );\r\n\t\t\t\t\t\tserver_info->m_MaxObservers = SBServerGetIntValue( server, \"maxobservers\", 1 );\r\n\t\t\t\t\t\tserver_info->m_Password = SBServerGetBoolValue( server, \"password\", false );\r\n\t\t\t\t\t\tserver_info->m_GameStarted = SBServerGetBoolValue( server, \"started\", false );\r\n\t\t\t\t\t\tserver_info->m_HostMode = SBServerGetIntValue( server, \"hostmode\", vHOST_MODE_SERVE );\r\n\t\t\t\t\t\tserver_info->m_Ranked = SBServerGetIntValue( server, \"ranked\", 0 );\r\n\t\t\t\t\t\tserver_info->m_SkillLevel = SBServerGetIntValue( server, \"skilllevel\", vSKILL_LEVEL_DEFAULT );\r\n\t\t\t\t\t\t//server_info->m_Port = SBServerGetPublicQueryPort( server );\r\n\t\t\t\t\t\tserver_info->ClearPlayerNames();\r\n\t\t\t\t\t\tDbg_Printf( \"Game Mode: %s\\n\", server_info->m_Mode );\r\n\t\t\t\t\t\tDbg_Printf( \"Numplayers %d\\n\", server_info->m_NumPlayers )\r\n\t\t\t\t\t\tfor( i = 0; i < server_info->m_NumPlayers; i++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tint rating;\r\n\r\n\t\t\t\t\t\t\trating = SBServerGetPlayerIntValue( server, i, \"rating\", 0 );\r\n\t\t\t\t\t\t\tDbg_Printf( \"Adding player %s with rating %d\\n\", (char*) SBServerGetPlayerStringValue( server, i, \"player\",\"...\" ), rating );\r\n\t\t\t\t\t\t\tserver_info->AddPlayer((char*) SBServerGetPlayerStringValue( server, i, \"player\",\"...\" ), rating );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif( server_info->m_HasBasicInfo == false )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif( SBServerHasBasicKeys( server ))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tman->AddServerToMenu( server_info, 0 );\r\n\t\t\t\t\t\t\t\tScript::RunScript( \"update_lobby_server_list\" );\r\n\t\t\t\t\t\t\t\tserver_info->m_HasBasicInfo = true;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif( server_info->m_HasFullInfo == false )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif( SBServerHasFullKeys( server ))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tserver_info->m_HasFullInfo = true;\r\n\t\t\t\t\t\t\t\tif( server_info->m_InFocus )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tScript::CStruct* params;\r\n\r\n\t\t\t\t\t\t\t\t\tparams = new Script::CStruct;\r\n\t\t\t\t\t\t\t\t\tparams->AddChecksum( \"id\", (uint32) server );\r\n\t\t\t\t\t\t\t\t\tScript::RunScript( \"describe_selected_server\", params );\r\n\t\t\t\t\t\t\t\t\tdelete params;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n                break;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n#endif \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::ScriptGetNumServersInLobby(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager * gamenet_man = Manager::Instance();\r\n\tScript::CStruct* p_return_params;\r\n\r\n\tp_return_params = pScript->GetParams();\r\n\tp_return_params->AddInteger( \"num_servers\", gamenet_man->m_servers.CountItems());\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tManager::StartServerList( void )\r\n{\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\r\n\tif( InLanMode())\r\n\t{\r\n\t\tNet::Client* client;\r\n\r\n\t\tMatchClientShutdown();\r\n\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\t\tclient = SpawnMatchClient();\r\n\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\tif( client == NULL )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n        if( !m_auto_refresh_task->InList())\r\n\t\t{\r\n\t\t\tmlp_man->AddLogicTask( *m_auto_refresh_task );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::StopServerList( void )\r\n{\r\n\t\r\n\r\n\tif( InInternetMode())\r\n\t{   \r\n#ifdef __PLAT_NGPS__\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\t\tDbg_Printf( \"******** STOP LISTING GAMES **********\\n\" );\r\n\t\tif( mpLobbyMan->GetPeer())\r\n\t\t{\r\n\t\t\tpeerStopListingGames( mpLobbyMan->GetPeer());\r\n\t\t}\r\n\t\tMem::Manager::sHandle().PopContext();\r\n#endif\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNet::Client* client;\r\n\r\n\t\tclient = GetMatchClient();\r\n\t\tif( client )\r\n\t\t{\r\n\t\t\tclient->m_Dispatcher.Deinit();\r\n\t\t}\r\n\r\n        m_auto_refresh_task->Remove();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::FreeServerList( void )\r\n{\r\n\tLst::Search< ServerInfo > sh;\r\n\tServerInfo* server, *next;\r\n\t    \r\n\tfor( server = sh.FirstItem( m_temp_servers ); server; server = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tdelete server;\r\n\t}\r\n\r\n\tfor( server = sh.FirstItem( m_servers ); server; server = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tdelete server;\r\n\t}\r\n\r\n\tif( InLanMode())\r\n\t{\r\n\t\tMatchClientShutdown();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::ClearServerList( bool refocus )\r\n{   \r\n\tScript::CStruct* pParams;\r\n\t\r\n\tpParams = new Script::CStruct;\r\n\tif( refocus )\r\n\t{\r\n\t\tpParams->AddChecksum( \"refocus\", Script::GenerateCRC( \"refocus\" ));\r\n\t}\r\n\tScript::RunScript( \"destroy_server_menu_children\", pParams );\r\n\tScript::RunScript( \"add_no_servers_found_message\", pParams );\r\n\tdelete pParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::RefreshServerList( bool force_refresh )\r\n{\r\n\t//Dbg_Printf( \"In Refresh server list\\n\" );\r\n\tif( force_refresh == false )\r\n\t{\r\n\t\t//Dbg_Printf( \"No force\\n\" );\r\n\t\t// Don't let people refresh like crazy\r\n\t\tif(( Tmr::GetTime() - s_last_refresh_time ) < vTIME_BETWEEN_MANUAL_REFRESH )\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"Not enough time\\n\" );\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\ts_last_refresh_time = Tmr::GetTime();\r\n\ts_refresh_pending = true;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\r\n\tStopServerList();\r\n\tFreeServerList();\r\n\tStartServerList();\r\n\r\n\tif( InInternetMode())\r\n\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\tunsigned char key_list[] = {NUMPLAYERS_KEY,\r\n\t\t\t\t\t\t\t\t\tMAXPLAYERS_KEY,\r\n\t\t\t\t\t\t\t\t\tHOSTPORT_KEY,\r\n\t\t\t\t\t\t\t\t\tGAMETYPE_KEY };\r\n\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\t\t\r\n\t\tDbg_Printf( \"******** START LISTING GAMES **********\\n\" );\r\n\t\tpeerStartListingGames( mpLobbyMan->GetPeer(), key_list, sizeof(key_list), NULL, \r\n\t\t\t\t\t\t\t\ts_server_list_callback, this );\r\n\t\tMem::Manager::sHandle().PopContext();\r\n#endif\r\n\t}\r\n\telse\r\n\t{   \r\n\t\tFindServersOnLAN();\r\n\t}\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef __PLAT_XBOX__\r\nbool\t\tManager::ServerAlreadyInList( char* name, XNADDR* xbox_addr )\r\n{\r\n\tLst::Search< ServerInfo > sh;\r\n\tServerInfo* server;\r\n\r\n\tfor( server = sh.FirstItem( m_temp_servers ); server; server = sh.NextItem())\r\n\t{\r\n\t\tif(\t( memcmp( &server->m_XboxAddr, xbox_addr, sizeof( XNADDR ) == 0 )) &&\r\n\t\t\t( stricmp( server->m_Name, name ) == 0 ))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n#else\r\n\r\nbool\t\tManager::ServerAlreadyInList( char* name, int ip )\r\n{\r\n\tLst::Search< ServerInfo > sh;\r\n\tServerInfo* server;\r\n\r\n\tfor( server = sh.FirstItem( m_servers ); server; server = sh.NextItem())\r\n\t{\r\n\t\tif(\t( server->m_Ip == ip ) &&\r\n\t\t\t( stricmp( server->m_Name, name ) == 0 ))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tfor( server = sh.FirstItem( m_temp_servers ); server; server = sh.NextItem())\r\n\t{\r\n\t\tif(\t( server->m_Ip == ip ) &&\r\n\t\t\t( stricmp( server->m_Name, name ) == 0 ))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t\r\n\treturn false;\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::SortPreviousKey( void )\r\n{\r\n\tif( m_sort_key == 0 )\r\n\t{\r\n\t\tm_sort_key = vNUM_SORT_KEYS - 1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_sort_key--;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::SortNextKey( void )\r\n{\r\n\tm_sort_key = ( m_sort_key + 1 ) % vNUM_SORT_KEYS;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tManager::SortServerList( void )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nServerInfo*\tManager::GetServerInfo( uint32 id )\r\n{\r\n\tLst::Search< ServerInfo > sh;\r\n\tServerInfo* server;\r\n\r\n\tfor( server = sh.FirstItem( m_servers ); server; server = sh.NextItem())\r\n\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\tif( InInternetMode())\r\n\t\t{\r\n\t\t\tif( id == (uint32) server->m_GServer )\r\n\t\t\t{\r\n\t\t\t\treturn server;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n#endif\r\n\t\t{\r\n\t\t\tif( id == (uint32) server )\r\n\t\t{\r\n\t\t\treturn server;\r\n\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nServerInfo::ServerInfo( void ) : Lst::Node< ServerInfo > ( this )\r\n{\r\n\tm_Listed = false;\r\n\tm_InFocus = false;\r\n\tm_Latency = 0;\r\n\tsprintf( m_Level, \"None\" );\r\n\tsprintf( m_Mode, \"None\" );\r\n\tm_MaxPlayers = 8;\r\n\tm_NumPlayers = 1;\r\n\tm_MaxObservers = 1;\r\n\tm_NumObservers = 0;\r\n\tm_SkillLevel = vSKILL_LEVEL_DEFAULT;\r\n\tm_HostMode = vHOST_MODE_SERVE;\r\n\tm_Ranked = false;\r\n\tm_GameStarted = false;\r\n\tm_CanDirectConnect = true;\r\n\tm_HasBasicInfo = false;\r\n\tm_HasFullInfo = false;\r\n#ifdef __PLAT_NGPS__\r\n\tm_GServer = NULL;\r\n#endif\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid ServerInfo::ClearPlayerNames( void )\r\n{\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo* player, *next;\r\n\tManager * gamenet_man = Manager::Instance();\r\n\r\n\tfor( player = sh.FirstItem( m_players ); player; player = next )\r\n\t{\r\n\t\tnext = sh.NextItem();\r\n\t\tgamenet_man->DestroyPlayer( player );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nServerInfo::~ServerInfo( void )\r\n{\r\n\tClearPlayerNames();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tServerInfo::AddPlayer( char* name, int rating )\r\n{   \r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tPlayerInfo* player;\r\n\r\n\tif( gamenet_man->InInternetMode())\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetBottomUpHeap());\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());\r\n\t}\r\n\t\r\n\tplayer = new PlayerInfo( 0 );\r\n\tplayer->m_Rating = rating;\r\n\tstrncpy( player->m_Name, name, vMAX_PLAYER_NAME_LEN );\r\n\tplayer->m_Name[ vMAX_PLAYER_NAME_LEN ] = '\\0';\r\n\tm_players.AddToTail( player );\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar*\tServerInfo::GetPlayerName( int index )\r\n{\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo* player;\r\n\r\n\tfor( player = sh.FirstItem( m_players ); player; player = sh.NextItem())\r\n\t{\r\n\t\tif( index == 0 )\r\n\t\t{\r\n\t\t\treturn player->m_Name;\r\n\t\t}\r\n\t\tindex--;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tServerInfo::GetPlayerRating( int index )\r\n{\r\n\tLst::Search< PlayerInfo > sh;\r\n\tPlayerInfo* player;\r\n\r\n\tfor( player = sh.FirstItem( m_players ); player; player = sh.NextItem())\r\n\t{\r\n\t\tif( index == 0 )\r\n\t\t{\r\n\t\t\treturn player->m_Rating;\r\n\t\t}\r\n\t\tindex--;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetServerListState( ServerListState state )\r\n{\r\n\t//Dbg_Printf( \"Setting server list state to %d from %d\\n\", state, m_server_list_state );\r\n\tm_server_list_state = state;\r\n\t\r\n\tswitch( m_server_list_state )\r\n\t{\r\n\t\tcase vSERVER_LIST_STATE_INITIALIZE:\r\n\t\t{\r\n\t\t\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\t\t\t\r\n\t\t\t//Dbg_Printf( \"Serverlist State: Initializing\\n\" );\r\n\r\n\t\t\tmlp_man->AddLogicTask( *m_server_list_state_task );\r\n\t\t\tSetServerListState( GetNextServerListState());\r\n#ifdef __PLAT_NGPS__\r\n\t\t\ts_motd_retry = 0;\r\n#endif // __PLAT_NGPS__\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase vSERVER_LIST_STATE_SHUTDOWN:\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"Serverlist State: Shutting down\\n\" );\r\n\r\n\t\t\tm_server_list_state_task->Remove();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tManager::SetNextServerListState( ServerListState state )\r\n{\r\n\tm_next_server_list_state = state;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nServerListState Manager::GetServerListState( void )\r\n{\r\n\treturn m_server_list_state;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nServerListState Manager::GetNextServerListState( void )\r\n{\r\n\treturn m_next_server_list_state;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tManager::ScriptRetrieveServerInfo(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tManager* gamenet_man = Manager::Instance();\r\n\r\n\tif( gamenet_man->InLanMode())\r\n\t{\r\n\t\t// We have the data and can display it immediately\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n#ifdef __PLAT_NGPS__\r\n\t\tuint32 id;\r\n\t\tServerInfo* p_server;\r\n\r\n\t\tpParams->GetChecksum( Script::GenerateCRC(\"id\"), &id );\r\n\r\n\t\tp_server = gamenet_man->GetServerInfo( id );\r\n\t\tDbg_Assert( p_server );\r\n\r\n\t\tgamenet_man->SetServerFocus( p_server );\r\n\t\tif( p_server->m_HasFullInfo )\r\n\t\t{\r\n\t\t\t// We have the data and can display it immediately\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().InternetTopDownHeap());\r\n\r\n\t\t\tpeerUpdateGame( gamenet_man->mpLobbyMan->GetPeer(), p_server->m_GServer, PEERTrue );\r\n\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t\t// We have to request it from the server\r\n\t\t\treturn false;\r\n\t\t}\r\n#else\r\n\t\treturn false;\r\n#endif\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tManager::ScriptDescribeServer(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tScript::CStruct* p_item_params;\r\n\tServerInfo* p_server;\r\n\tManager* gamenet_man = Manager::Instance();\r\n\tint i;\r\n\tchar p_string[128];\r\n\tScript::CArray* p_skill_array;\r\n\tScript::CScriptStructure* p_skill_struct;\r\n\tconst char* p_skill_string;\r\n\tuint32 id;\r\n\r\n\tpParams->GetChecksum( Script::GenerateCRC(\"id\"), &id );\r\n\t\t\t\t\r\n\tp_server = gamenet_man->GetServerInfo( id );\r\n\tDbg_Assert( p_server );\r\n\r\n\tScript::RunScript( \"destroy_server_desc_children\" );\r\n\r\n    Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\r\n\tif( p_server->m_GameStarted )\r\n\t{\r\n        // In Progress\r\n        p_item_params = new Script::CStruct;\r\n        sprintf( p_string, \"%s:\", Script::GetLocalString( \"netoptions_str_game_in_progress\" ) );\r\n        p_item_params->AddString( \"name\", p_string );\r\n        Script::RunScript(\"net_game_info_add_item\", p_item_params );\r\n    \tdelete p_item_params;\r\n\t}\r\n\r\n\tif( p_server->m_HostMode == vHOST_MODE_AUTO_SERVE )\r\n\t{\r\n\t\t// Auto Serve\r\n        p_item_params = new Script::CStruct;\r\n        sprintf( p_string, \"%s:\", Script::GetLocalString( \"netoptions_str_auto_serve\" ) );\r\n        p_item_params->AddString( \"name\", p_string );\r\n        Script::RunScript(\"net_game_info_add_item\", p_item_params );\r\n    \tdelete p_item_params;\r\n\t}\r\n\telse if( p_server->m_HostMode == vHOST_MODE_FCFS )\r\n\t{\r\n\t\t// FCFS\r\n        p_item_params = new Script::CStruct;\r\n        sprintf( p_string, \"%s:\", Script::GetLocalString( \"netoptions_str_fcfs\" ) );\r\n        p_item_params->AddString( \"name\", p_string );\r\n        Script::RunScript(\"net_game_info_add_item\", p_item_params );\r\n    \tdelete p_item_params;\r\n\t}\r\n\r\n#ifdef __PLAT_NGPS__\r\n\t// Ping\r\n    p_item_params = new Script::CStruct;\r\n    sprintf( p_string, \"%s:\", Script::GetLocalString( \"sort_title_ping\" ) );\r\n    p_item_params->AddString( \"name\", p_string );\r\n\tif( p_server->m_Latency == 9999 )\r\n\t{\r\n\t\tsprintf( p_string, \"...\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsprintf( p_string, \"%d\", p_server->m_Latency );\r\n\t}\r\n    \r\n    p_item_params->AddString( \"value\", p_string );\r\n    Script::RunScript(\"net_game_info_add_item\", p_item_params );\r\n\tdelete p_item_params;\r\n#endif\r\n\r\n\t// Mode\r\n    p_item_params = new Script::CStruct;\r\n    sprintf( p_string, \"%s:\", Script::GetLocalString( \"sort_title_mode\" ) );\r\n    p_item_params->AddString( \"name\", p_string );\r\n    sprintf( p_string, \"%s\", p_server->m_Mode );\r\n    p_item_params->AddString( \"value\", p_string );\r\n    Script::RunScript(\"net_game_info_add_item\", p_item_params );\r\n\tdelete p_item_params;\r\n    \r\n\t// Skill Level\r\n    p_skill_array = Script::GetArray( \"skill_level_info\" );\r\n\tp_skill_struct = p_skill_array->GetStructure( p_server->m_SkillLevel );\r\n\tp_skill_struct->GetText( \"name\", &p_skill_string );\r\n\tp_item_params = new Script::CStruct;\t\r\n    sprintf( p_string, \"%s:\", Script::GetLocalString( \"sort_title_skill\" ) );\r\n    p_item_params->AddString( \"name\", p_string );\r\n    sprintf( p_string, \"%s\", p_skill_string );\r\n    p_item_params->AddString( \"value\", p_string );\r\n\tScript::RunScript(\"net_game_info_add_item\", p_item_params );\r\n\tdelete p_item_params;\r\n\r\n\t// Level\r\n    p_item_params = new Script::CStruct;\r\n    sprintf( p_string, \"%s:\", Script::GetLocalString( \"sort_title_level\" ) );\r\n    p_item_params->AddString( \"name\", p_string );\r\n    sprintf( p_string, \"%s\", p_server->m_Level );\r\n    p_item_params->AddString( \"value\", p_string );\r\n    Script::RunScript(\"net_game_info_add_item\", p_item_params );\r\n\tdelete p_item_params;\r\n\r\n\t// Goals\r\n#ifndef __PLAT_XBOX__\r\n\tif( gamenet_man->InInternetMode())\r\n\t{\r\n\t\tp_item_params = new Script::CStruct;\r\n\t\tsprintf( p_string, \"%s:\", Script::GetLocalString( \"sort_title_ranked\" ) );\r\n\t\tp_item_params->AddString( \"name\", p_string );\r\n\t\tif( p_server->m_Ranked )\r\n\t\t{\r\n\t\t\tsprintf( p_string, \"%s\", Script::GetLocalString( \"netoptions_str_yes\" ));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsprintf( p_string, \"%s\", Script::GetLocalString( \"netoptions_str_no\" ));\r\n\t\t}\r\n\t\t\r\n\t\tp_item_params->AddString( \"value\", p_string );\r\n\t\tScript::RunScript(\"net_game_info_add_item\", p_item_params );\r\n\t\tdelete p_item_params;\r\n\t}\r\n#endif\r\n\r\n\t// Player Ratio\r\n    p_item_params = new Script::CStruct;\r\n    sprintf( p_string, \": %d/%d\", p_server->m_NumPlayers, p_server->m_MaxPlayers );\r\n    p_item_params->AddString( \"text\", p_string );\r\n    Script::RunScript(\"net_game_info_update_player_title\", p_item_params );\r\n\tdelete p_item_params;\r\n    \r\n    // List of Players\r\n    for( i = 0; i < p_server->m_NumPlayers; i++ )\r\n\t{\r\n\t\tint rank;\r\n\r\n\t\trank = (int) (((float) p_server->GetPlayerRating( i ) / (float) vMAX_RATING ) * (float) vMAX_RANK );\r\n\t\tp_item_params = new Script::CStruct;\r\n        sprintf( p_string, \"%d:\", i+1 );\r\n\t\tp_item_params->AddInteger( \"rank\", rank );\r\n        p_item_params->AddString( \"name\", p_string );\r\n        sprintf( p_string, \"%s\", p_server->GetPlayerName( i ) );\r\n        p_item_params->AddString( \"value\", p_string );\r\n\t\tScript::RunScript(\"net_game_info_add_player\", p_item_params );\r\n\t\tdelete p_item_params;\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\tManager::ScriptChooseServer(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tServerInfo* p_server;\r\n\tManager* gamenet_man = Manager::Instance();\r\n\tbool server_full;\r\n\tuint32 reason_checksum;\t\t\r\n\tuint32 id;\r\n\r\n\tpParams->GetChecksum( Script::GenerateCRC(\"id\"), &id );\r\n\t\t\t\t\r\n\tgamenet_man->ClearServerFocus();\r\n\r\n\tp_server = gamenet_man->GetServerInfo( id );\r\n\tDbg_Assert( p_server );\r\n\t\t\t\t\t\t\t\t\r\n\tserver_full = false;\r\n\treason_checksum = 0;\r\n\tif( gamenet_man->GetJoinMode() == vJOIN_MODE_PLAY )\r\n\t{\r\n\t\tif( p_server->m_NumPlayers >= p_server->m_MaxPlayers )\r\n\t\t{\r\n\t\t\tserver_full = true;\r\n\t\t\treason_checksum = Script::GenerateCRC(\"net_reason_full\");\r\n\t\t}\r\n\t}\r\n\telse if( gamenet_man->GetJoinMode() == vJOIN_MODE_OBSERVE )\r\n\t{\r\n\t\tif( p_server->m_NumObservers >= p_server->m_MaxObservers )\r\n\t\t{\r\n\t\t\tserver_full = true;\r\n\t\t\treason_checksum = Script::GenerateCRC(\"net_reason_full_observers\");\r\n\t\t}\r\n\t}\r\n\r\n\tif( server_full )\r\n\t{   \r\n\t\tScript::CStruct* p_structure = new Script::CStruct;\r\n\t\tp_structure->AddChecksum( \"reason\", reason_checksum );\r\n\t\tp_structure->AddChecksum( \"just_dialog\", 0 );\r\n\r\n\t\tgamenet_man->m_join_state_task->Remove();\r\n\t\tScript::RunScript( \"CreateJoinRefusedDialog\", p_structure );\r\n\t\tdelete p_structure;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tScript::CScriptStructure* p_structure = new Script::CScriptStructure;\r\n\r\n#ifdef __PLAT_NGPS__\t\t\t\t\t\t\t\r\n        if( gamenet_man->mpBuddyMan->IsLoggedIn())\r\n\t\t{\r\n\t\t\tgamenet_man->mpLobbyMan->SetServerName( p_server->m_Name );\r\n\t\t}\r\n#endif\r\n\r\n#ifdef __PLAT_XBOX__\t\t\t\t\t\t\t\r\n\t\tIN_ADDR host_addr;\t\t\r\n\t\t\r\n\t\t// Register the session key.\r\n\t\tif( XNetRegisterKey( &p_server->m_XboxKeyId, \r\n\t\t\t&p_server->m_XboxKey ) != NO_ERROR )\r\n\t\t{\r\n\t\t\tOutputDebugString( \"**** Failed to register key\\n\" );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\r\n\t\tgamenet_man->m_XboxKeyRegistered = true;\r\n\t\t// Translate the hosts XNADDR to an IN_ADDR.\t\t\t\r\n\t\tif( XNetXnAddrToInAddr( &p_server->m_XboxAddr, &p_server->m_XboxKeyId,\r\n\t\t\t\t&host_addr ) != NO_ERROR )\r\n\t\t{\r\n\t\t\tOutputDebugString( \"**** Failed to get inaddr from xnaddr\\n\" );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\r\n\t\tmemcpy( &gamenet_man->m_XboxKeyId, &p_server->m_XboxKeyId, sizeof( XNKID ));\r\n\t\t\r\n\t\tp_structure->AddComponent( Script::GenerateCRC( \"Address\" ), \r\n\t\t\t\t\t\t\t\tESYMBOLTYPE_INTEGER, (int) host_addr.s_addr );\r\n\t\tp_structure->AddComponent( Script::GenerateCRC( \"Port\" ), \r\n\t\t\t\t\t\t\t\tESYMBOLTYPE_INTEGER, p_server->m_Port );\r\n#else\r\n\t\tchar *ip_addr;\r\n\t\tstruct in_addr addr;\r\n\t\tuint32 cookie;\r\n\t\t\r\n\t\taddr.s_addr = p_server->m_Ip;\r\n\t\tip_addr = inet_ntoa( addr );\r\n\t\tif( p_server->m_CanDirectConnect == false )\r\n\t\t{\r\n\t\t\tcookie = Mth::Rnd( vINT32_MAX );\r\n\t\t\tp_structure->AddComponent( CRCD( 0x751f4599, \"cookie\" ), ESYMBOLTYPE_NAME, cookie );\r\n\t\t}\r\n        p_structure->AddComponent( NONAME, ESYMBOLTYPE_INTEGER, p_server->m_Port );\r\n\t\tp_structure->AddComponent( NONAME, ESYMBOLTYPE_STRING, ip_addr );\r\n#endif\r\n\r\n\t\tp_structure->AddInteger( \"MaxPlayers\", p_server->m_MaxPlayers );\r\n\t\tScript::RunScript( \"net_chosen_join_server\", p_structure );\r\n\t\tdelete p_structure;\r\n\r\n\t}\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#ifdef __PLAT_NGPS__\r\nbool \t\tManager::ScriptPostGame( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tManager* gamenet_man = Manager::Instance();\r\n\r\n\tif( gamenet_man->mpLobbyMan->ReportedGame() == false )\r\n\t{\r\n\t\tgamenet_man->PostGame();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n#endif //__PLAT_NGPS__\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nLobbyInfo::LobbyInfo( void ) : Lst::Node< LobbyInfo > ( this )\r\n{\r\n\tm_Full = false;\r\n\tm_Official = false;\r\n\tm_OffLimits = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n} // namespace GameNet\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/XBox/p_auth.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_auth.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/28/02\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXBox Online Authorization Code\t\t \t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <sys/McMan.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/scripting/script.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <GameNet/Xbox/p_auth.h>\r\n#include <GameNet/Xbox/p_buddy.h>\r\n#include <GameNet/Xbox/p_voice.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nconst DWORD vMAX_MEMORY_UNITS  = 2 * XGetPortCount();\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tAuthMan::s_logon_state_code( const Tsk::Task< AuthMan >& task )\r\n{\r\n#\tif 0\r\n\tAuthMan& man = task.GetData();\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tswitch( man.m_state )\r\n\t{\r\n\t\tcase vSTATE_FILL_ACCOUNT_LIST:\t\t\r\n\t\t\tif( man.gather_user_list() == 0 )\r\n\t\t\t{\r\n\t\t\t\tman.m_state = vSTATE_CREATE_ACCOUNT;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tman.fill_user_list();\r\n\t\t\t\tman.m_state = vSTATE_SELECT_ACCOUNT;\r\n\t\t\t}\r\n\t\t\tbreak;\t\t\t\t\r\n\t\tcase vSTATE_SELECT_ACCOUNT:\r\n\t\t\tbreak;\t\t\t\r\n\t\tcase vSTATE_CREATE_ACCOUNT:\t\t\r\n\t\t\tman.create_account();\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase vSTATE_GET_PIN:\r\n\t\t\tScript::RunScript( \"launch_pin_entry_menu\" );\r\n\t\t\tman.m_pin_entry.BeginInput( man.m_chosen_account );\r\n\t\t\tman.m_state = vSTATE_WAIT;\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_PIN_COMPLETE:\r\n\t\t\tman.PinAttempt( man.m_pin_entry.GetPin());\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_PIN_CANCELLED:\r\n\t\t\tman.m_pin_entry.EndInput();\r\n\t\t\tman.m_state = vSTATE_FILL_ACCOUNT_LIST;\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_PIN_CLEARED:\r\n\t\t\tman.m_state = vSTATE_GET_PIN;\r\n\t\t\tman.m_pin_entry.ClearInput();\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_LOG_ON:\r\n\t\t\tman.logon();\r\n\t\t\tman.m_state = vSTATE_LOGGING_ON;\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_LOGGING_ON:\t\t\r\n\t\t\tman.check_logon_progress();\t\t\t\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_SUCCESS:\r\n\t\t\tScript::RunScript( \"launch_xbox_online_menu\" );\r\n\t\t\tman.m_signed_in = true;\r\n\t\t\tman.m_state = vSTATE_LOGGED_IN;\r\n\t\t\tgamenet_man->mpVoiceMan->Startup();\r\n\t\t\tgamenet_man->mpBuddyMan->SpawnBuddyList( man.m_chosen_account );\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_LOGGED_IN:\r\n\t\t\tman.pump_logon_task();\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_CANCEL:\r\n\t\t{\r\n\t\t\tLst::DynamicTableDestroyer<XONLINE_USER> destroyer( &man.m_user_list );\r\n\t\t\tdestroyer.DeleteTableContents();\r\n\r\n\t\t\tdelete man.mp_logon_state_task;\r\n\t\t\tman.mp_logon_state_task = NULL;\r\n\t\t\tman.m_state = vSTATE_WAIT;\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase vSTATE_WAIT:\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_ERROR:\r\n\t\t\tman.m_state = man.m_next_state;\r\n\t\t\tswitch( man.m_error )\r\n\t\t\t{\r\n\t\t\t\tcase vERROR_WRONG_PIN:\r\n\t\t\t\t\tScript::RunScript( \"launch_wrong_pin_dialog_box\" );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vERROR_GENERAL_LOGIN:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vERROR_LOGIN_FAILED:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\t\t\t\r\n\t\t\tbreak;\r\n\t}\t\r\n#\tendif\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic DWORD\ts_get_mem_unit_slot( DWORD i )\r\n{\r\n\treturn( ( i % 2 ) ? XDEVICE_BOTTOM_SLOT : XDEVICE_TOP_SLOT );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic DWORD\ts_get_mem_unit_port( DWORD i )\r\n{\r\n\treturn( i / 2 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic DWORD\ts_get_mem_unit_mask( DWORD i )\r\n{\r\n\t// The XGetDevices bitmask is formatted as follows:\r\n    //\r\n    //      0x00000001      port 0 top slot         i = 0\r\n    //      0x00010000      port 0 bottom slot          1\r\n    //      0x00000002      port 1 top slot             2\r\n    //      0x00020000      port 1 bottom slot          3\r\n    //      0x00000004      port 2 top slot             4\r\n    //      0x00040000      port 2 bottom slot          5\r\n    //      0x00000008      port 3 top slot             6\r\n    //      0x00080000      port 3 bottom slot          7\r\n\r\n    DWORD dwMask = 1 << s_get_mem_unit_port( i );\r\n    if( s_get_mem_unit_slot( i ) == XDEVICE_BOTTOM_SLOT )\r\n        dwMask <<= 16;\r\n\r\n    return( dwMask );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tAuthMan::gather_user_list( void )\r\n{\r\n    // Get accounts stored on the hard disk\r\n    DWORD num_users = 0;\r\n\r\n#\tif 0\r\n\t// On input, the list must have room for XONLINE_MAX_STORED_ONLINE_USERS\r\n    // accounts\r\n    XONLINE_USER user_list[ XONLINE_MAX_STORED_ONLINE_USERS ];\r\n\r\n    HRESULT hr = XOnlineGetUsers( user_list, &num_users);\r\n    if( SUCCEEDED(hr) )\r\n    {\r\n        for( DWORD i = 0; i < num_users; ++i )\r\n\t\t{\r\n\t\t\tXONLINE_USER* new_user;\r\n\t\t\t\r\n\t\t\tnew_user = new XONLINE_USER;\r\n\t\t\t*new_user = user_list[i];\r\n            m_user_list.Add( new_user );\r\n\t\t}\r\n    }\r\n#\tendif\r\n\r\n\treturn num_users;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAuthMan::fill_user_list( void )\r\n{\r\n\tint i;\r\n\t\r\n\tScript::RunScript( \"create_account_list_menu\" );\t\r\n\r\n\tfor( i = 0; i < m_user_list.GetSize(); i++ )\r\n\t{\r\n\t\tScript::CStruct* p_item_params = new Script::CStruct;\r\n\t\tXONLINE_USER* user;\r\n\t\t\r\n\t\tuser = &m_user_list[i];\r\n\r\n\t\t//p_item_params->AddString( \"text\", user->gamertag );\r\n\t\tp_item_params->AddChecksum( \"id\", 123456 + i );\t\t\r\n\t\tp_item_params->AddChecksum( \"pad_choose_script\",Script::GenerateCRC(\"choose_selected_account\"));\r\n\r\n\t\t// create the parameters that are passed to the X script\r\n\t\tScript::CStruct *p_script_params= new Script::CStruct;\r\n\t\tp_script_params->AddInteger( \"index\", i );\t\r\n\t\tp_item_params->AddStructure(\"pad_choose_params\",p_script_params);\t\t\t\r\n\r\n\t\tScript::RunScript(\"make_text_sub_menu_item\",p_item_params);\r\n\t\tdelete p_item_params;\r\n\t\tdelete p_script_params;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAuthMan::create_account( void )\r\n{\r\n\tScript::RunScript( \"launch_no_accounts_dialog\" );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAuthMan::logon( void )\r\n{\t\r\n#\tif 0\r\n\tXONLINE_USER user_list[ XGetPortCount() ] = { 0 };\t\r\n\t\r\n\tCopyMemory( &user_list[ 0 ], &m_user_list[ m_chosen_account ], sizeof( XONLINE_USER ));\r\n\r\n    // Initiate the login process. XOnlineTaskContinue() is used to poll\r\n    // the status of the login.\r\n    HRESULT hr = XOnlineLogon( user_list, mp_services, vNUM_SERVICES, \r\n                               NULL, &mh_online_task );\r\n\r\n    if( FAILED(hr) || mh_online_task == NULL )\r\n    {\r\n\t\tif( mh_online_task != NULL )\r\n\t\t{\r\n\t\t\thr = XOnlineTaskClose( mh_online_task );\r\n\t\t\tmh_online_task = NULL;\r\n\t\t}        \r\n        m_state = vSTATE_ERROR;\r\n\t\tm_next_state = vSTATE_WAIT;\r\n\t\tm_error = vERROR_GENERAL_LOGIN;        \r\n    }\r\n#\tendif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tAuthMan::xbox_has_voice_device( void )\r\n{\r\n\treturn false;\r\n\t\r\n//\tDWORD dwConnectedMicrophones = XGetDevices( XDEVICE_TYPE_VOICE_MICROPHONE );\r\n//\tDWORD dwConnectedHeadphones = XGetDevices( XDEVICE_TYPE_VOICE_HEADPHONE );\r\n\r\n    // Voice is available if there's at least one mike and one headphone\r\n//\treturn( dwConnectedMicrophones >= 1 && dwConnectedHeadphones  >= 1 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAuthMan::pump_logon_task( void )\r\n{\r\n#\tif 0\r\n\t// Pump the task\r\n\tHRESULT hr;\r\n\thr = XOnlineTaskContinue( mh_online_task );\r\n\t\r\n\t// Check status\r\n\tif( FAILED( hr ))\r\n\t{\t\r\n\t\t//m_UI.SetErrorStr( L\"Connection was lost. Must relogin\" );\r\n\t}\r\n#\tendif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAuthMan::check_logon_progress( void )\r\n{\r\n#\tif 0\r\n\t// Pump the task\r\n\tHRESULT hr;\r\n\thr = XOnlineTaskContinue( mh_online_task );\r\n\t\r\n\t// Check status\r\n\tif ( hr != XONLINETASK_S_RUNNING )\r\n\t{\t\r\n\t\tif ( hr != XONLINE_S_LOGON_CONNECTION_ESTABLISHED  )\r\n        {\r\n            XOnlineTaskClose( mh_online_task );\r\n\r\n\t\t\tm_state = vSTATE_ERROR;\r\n\t\t\tm_error = vERROR_LOGIN_FAILED;\t\t\t\t\r\n            return;\r\n        }\t\t\r\n\t\r\n\t\t// Check login status; partial results indicate that login itself\r\n\t\t// has completed.\r\n\t\tBOOL success = TRUE;\r\n\t\tBOOL service_err = FALSE;\r\n\t\tHRESULT hrService = S_OK;\r\n\t\tDWORD i = 0;\r\n\t\t\r\n\t\t// Next, check if the user was actually logged on\r\n\t\tPXONLINE_USER pLoggedOnUsers = XOnlineGetLogonUsers();\r\n\t\tDbg_Assert( pLoggedOnUsers );\r\n\r\n\t\thr = pLoggedOnUsers[ m_chosen_account ].hr;\r\n\r\n\t\t// Check for general errors\r\n\t\tif( FAILED(hr) )\r\n\t\t{\r\n\t\t\tXOnlineTaskClose( mh_online_task );\r\n\r\n\t\t\tm_state = vSTATE_ERROR;\r\n\t\t\tm_error = vERROR_LOGIN_FAILED;\t\t\t\t\r\n            return;\r\n\t\t}\r\n\t\t\r\n\t\t// Check for service errors\r\n\t\tfor( i = 0; i < vNUM_SERVICES; ++i )\r\n\t\t{\r\n\t\t\tif( FAILED( hrService = XOnlineGetServiceInfo( mp_services[i], NULL) ))\r\n\t\t\t{\r\n\t\t\t\tsuccess = FALSE;\r\n\t\t\t\tservice_err = TRUE;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\t\r\n\t\t}\r\n\r\n\t\t// If no errors, login was successful\r\n\t\tm_state = success ? vSTATE_SUCCESS : vSTATE_ERROR;\r\n\r\n\t\tif( !success )\r\n\t\t{\r\n\t\t\tif( service_err )\r\n\t\t\t{\r\n\t\t\t\tm_error = vERROR_SERVICE_DOWN;\r\n\t\t\t\t/*m_UI.SetErrorStr( L\"Login failed.\\n\\n\"\r\n\t\t\t\t\t\t\t\t  L\"Error %x logging into service %d\",\r\n\t\t\t\t\t\t\t\t  mp_services[i].hr, mp_services[i].dwServiceID );*/\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_error = vERROR_LOGIN_FAILED;\r\n\t\t\t\t/*m_UI.SetErrorStr( L\"Login failed.\\n\\n\"\r\n\t\t\t\t\t\t\t\t  L\"Error %x returned by \"\r\n\t\t\t\t\t\t\t\t  L\"XOnlineTaskContinue\", hr );*/\t\t\t\t\t\r\n\t\t\t}\r\n\t\t\tXOnlineTaskClose( mh_online_task );\r\n\t\t\tm_state = vSTATE_ERROR;\r\n\t\t\tm_error = vERROR_LOGIN_FAILED;\t\t\t\t\r\n\t\t}\t\t\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tDWORD player_state;\r\n\r\n\t\t\tm_service_info_list.Reset();\r\n\t\t\tfor( i = 0; i < vNUM_SERVICES; ++i )\r\n\t\t\t{\r\n\t\t\t\t// Stored service information for UI\r\n\t\t\t\tXONLINE_SERVICE_INFO* service_info;\t\t\t\r\n\r\n\t\t\t\tservice_info = new XONLINE_SERVICE_INFO;                \r\n                XOnlineGetServiceInfo( mp_services[i], service_info );\r\n\t\t\t\tm_service_info_list.Add( service_info );\r\n\t\t\t}\r\n\r\n\t\t\t// Notify the world of our state change\r\n\t\t\tplayer_state = XONLINE_FRIENDSTATE_FLAG_ONLINE;\r\n\t\t\tif( xbox_has_voice_device())\r\n\t\t\t{\r\n\t\t\t\tplayer_state |= XONLINE_FRIENDSTATE_FLAG_VOICE;\r\n\t\t\t}\r\n\r\n\t\t\tXOnlineNotificationSetState( m_chosen_account, player_state,\r\n                                         XNKID(), 0, NULL );\t\t\t\r\n\t\t}\r\n\t}\r\n#\tendif\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nAuthMan::AuthMan( void )\r\n: m_user_list( 1 ), m_service_info_list( 1 ), m_signed_in( false )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAuthMan::UserLogon( void )\r\n{\t\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\r\n\tmp_logon_state_task = new Tsk::Task< AuthMan > ( s_logon_state_code, *this,\r\n\t\t\t\t\t\t\t\t\t\tTsk::BaseTask::Node::vNORMAL_PRIORITY );\r\n\tmlp_man->AddLogicTask( *mp_logon_state_task );\r\n\tm_state = vSTATE_FILL_ACCOUNT_LIST;\t\r\n\tm_chosen_account = 0;\r\n\tmp_services[0] = XONLINE_MATCHMAKING_SERVICE;\r\n    mp_services[1] = XONLINE_BILLING_OFFERING_SERVICE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAuthMan::CancelLogon( void )\r\n{\r\n\tm_state = vSTATE_CANCEL;\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAuthMan::SelectAccount( int index )\r\n{\r\n\tm_chosen_account = index;\r\n\r\n#\tif 0\r\n\tDWORD pin_required = m_user_list[ m_chosen_account ].dwUserOptions & XONLINE_USER_OPTION_REQUIRE_PIN;\r\n\tif( pin_required )\r\n\t{\r\n\t\tm_state = vSTATE_GET_PIN;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_state = vSTATE_LOG_ON;\r\n\t}\r\n#\tendif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAuthMan::PinAttempt( BYTE* pin )\r\n{\t\r\n#\tif 0\r\n\tif(( memcmp( pin, m_user_list[m_chosen_account].pin, XONLINE_PIN_LENGTH ) == 0 ))\r\n\t{\r\n\t\tm_state = vSTATE_LOG_ON;\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_state = vSTATE_ERROR;\r\n\t\tm_next_state = vSTATE_CANCEL;\r\n\t\tm_error = vERROR_WRONG_PIN;\r\n\t}\r\n#\tendif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAuthMan::SetState( LogonState state )\r\n{\r\n\tm_state = state;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tAuthMan::SignedIn( void )\r\n{\r\n\treturn m_signed_in;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAuthMan::SignOut( void )\r\n{\r\n#\tif 0\r\n\tXOnlineTaskClose( mh_online_task );\r\n\tmh_online_task = NULL;\r\n\tm_signed_in = false;\r\n#\tendif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPinEntry::s_pin_entry_input_logic_code ( const Inp::Handler < PinEntry >& handler )\r\n{\t\r\n\tPinEntry&\tentry = handler.GetData();\r\n\r\n\t// 'B' and 'Back' cancel the PIN entry\r\n\tif(\t( handler.m_Input->m_Buttons & Inp::Data::mD_SELECT ) ||\r\n\t\t( handler.m_Input->m_Buttons & Inp::Data::mD_CIRCLE ))\r\n\t{\r\n\t\tentry.m_cancelled = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// 'A' and 'Start' are ignored\r\n\tif(\t( handler.m_Input->m_Buttons & Inp::Data::mD_X ) ||\r\n\t\t( handler.m_Input->m_Buttons & Inp::Data::mD_START ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tXINPUT_GAMEPAD pad = {0};\t\r\n\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_L3 )\r\n\t{\r\n\t\tentry.m_cleared = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_LEFT )\r\n\t{\r\n\t\tpad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT;\r\n\t}\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_RIGHT )\r\n\t{\r\n\t\tpad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT;\r\n\t}\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_UP )\r\n\t{\r\n\t\tpad.wButtons |= XINPUT_GAMEPAD_DPAD_UP;\r\n\t}\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_DOWN )\r\n\t{\r\n\t\tpad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN;\r\n\t}\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_TRIANGLE )\r\n\t{\r\n\t\tpad.bAnalogButtons[XINPUT_GAMEPAD_Y] = 255;\t\t\r\n\t}\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_SQUARE )\r\n\t{\r\n\t\tpad.bAnalogButtons[XINPUT_GAMEPAD_X] = 255;\t\t\r\n\t}\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_L1 )\r\n\t{\r\n\t\tpad.bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER] = 255;\t\t\r\n\t}\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_R1 )\r\n\t{\r\n\t\tpad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] = 255;\t\t\r\n\t}\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_L2 )\r\n\t{\r\n\t\tpad.bAnalogButtons[XINPUT_GAMEPAD_WHITE] = 255;\t\t\r\n\t}\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_R2 )\r\n\t{\r\n\t\tpad.bAnalogButtons[XINPUT_GAMEPAD_BLACK] = 255;\t\t\r\n\t}\t\t\r\n\r\n\tXINPUT_STATE xis;\r\n    CopyMemory( &xis.Gamepad, &pad, sizeof( pad ));\r\n\r\n#\tif 0\r\n    HRESULT hr = XOnlinePINDecodeInput( entry.m_pin_input, &xis, &entry.m_frame_entry );\r\n    if( hr == S_OK )\r\n    {\r\n\t\tentry.m_got_entry = true;        \r\n    }\r\n#\tendif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPinEntry::s_pin_entry_logic_code( const Tsk::Task< PinEntry >& task )\r\n{\r\n#\tif 0\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tPinEntry& entry = task.GetData();\r\n\r\n\tif( entry.m_cleared )\r\n\t{\r\n\t\tgamenet_man->mp_AuthMan->SetState( AuthMan::vSTATE_PIN_CLEARED );\t\t\r\n\t}\r\n\telse if( entry.m_cancelled )\r\n\t{\t\t\r\n\t\tgamenet_man->mp_AuthMan->SetState( AuthMan::vSTATE_PIN_CANCELLED );\t\t\r\n\t}\r\n\telse if( entry.m_got_entry )\r\n\t{\r\n\t\tentry.m_pin[entry.m_pin_length++] = entry.m_frame_entry;\r\n\t\tentry.m_got_entry = false;\r\n\t\t// Here update the UI with the latest pin entry\r\n\r\n\t\tif( entry.Complete())\r\n\t\t{\r\n\t\t\tentry.EndInput();\r\n\t\t\t\r\n\t\t\t// Submit this entry as a our final pin\r\n\t\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\t\tgamenet_man->mp_AuthMan->SetState( AuthMan::vSTATE_PIN_COMPLETE );\r\n\t\t}\r\n\t}\r\n#\tendif\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPinEntry::ClearInput( void )\r\n{\r\n\tm_pin_length = 0;\r\n\tm_got_entry = false;\r\n\tm_cleared = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPinEntry::BeginInput( int controller )\r\n{\r\n#\tif 0\r\n\tint i;\r\n\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\tInp::Manager * inp_manager = Inp::Manager::Instance();\r\n\r\n\tmp_pin_entry_logic_task = new Tsk::Task< PinEntry > ( s_pin_entry_logic_code, *this,\r\n\t\t\t\t\t\t\t\t\t\tTsk::BaseTask::Node::vNORMAL_PRIORITY );\r\n\tmlp_man->AddLogicTask( *mp_pin_entry_logic_task );\r\n\tmp_pin_entry_input_handler = new Inp::Handler< PinEntry > ( controller,  \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ts_pin_entry_input_logic_code, *this, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tTsk::BaseTask::Node::vNORMAL_PRIORITY-1 );\r\n\tinp_manager->AddHandler( *mp_pin_entry_input_handler );\t\r\n\r\n\tfor( i = 0; i < XONLINE_PIN_LENGTH; i++ )\r\n\t{\r\n\t\tm_pin[i] = 0;\r\n\t}\r\n\r\n\tm_pin_length = 0;\r\n\tm_frame_entry = 0;\r\n\tm_cancelled = false;\r\n\tm_got_entry = false;\r\n\tm_cleared = false;\r\n\r\n\tXINPUT_STATE xis = {0};\r\n    m_pin_input = XOnlinePINStartInput( &xis );\t\r\n#\tendif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tPinEntry::Complete( void )\r\n{\r\n//\treturn( m_pin_length == XONLINE_PIN_LENGTH );\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPinEntry::EndInput( void )\r\n{\r\n\tdelete mp_pin_entry_logic_task;\r\n\tmp_pin_entry_logic_task = NULL;\r\n\tdelete mp_pin_entry_input_handler;\r\n\tmp_pin_entry_input_handler = NULL;\r\n\r\n//\tXOnlinePINEndInput( m_pin_input );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nBYTE*\tPinEntry::GetPin( void )\r\n{\r\n//\treturn m_pin;\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n\r\n\t\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/XBox/p_auth.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_auth.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/28/02\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXBox Online Authorization Code\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GAMENET_XBOX_P_AUTH_H\r\n#define __GAMENET_XBOX_P_AUTH_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/dynamictable.h>\r\n#include <sys/sioman.h>\r\n#include <Xbox.h>\r\n#include <XOnline.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace GameNet\r\n{\r\n\r\n// Number of services to authenticate\r\nconst DWORD vNUM_SERVICES = 2;\t\t\t\t\t\t\r\n//typedef std::vector< XONLINE_USER > XBUserList;\r\n//typedef std::vector< XONLINE_SERVICE_INFO > ServiceInfoList;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass PinEntry\r\n{\r\npublic:\r\n\tvoid\tBeginInput( int controller );    \r\n\tvoid\tEndInput( void );\r\n\tvoid\tClearInput( void );\r\n\tbool\tComplete( void );\r\n\tBYTE*\tGetPin( void );\r\n\r\nprivate:\r\n//\tXPININPUTHANDLE m_pin_input;                  // PIN input handle\r\n\tBYTE\t\tm_frame_entry;\t\t\t\t// PIN entry this frame\r\n//    BYTE\t\tm_pin[ XONLINE_PIN_LENGTH ];  // Current PIN\r\n    int\t\t\tm_pin_length;                // number of buttons entered\r\n\tbool\t\tm_got_entry;\r\n\tbool\t\tm_cancelled;\r\n\tbool\t\tm_cleared;\r\n\t\r\n\tstatic\tInp::Handler< PinEntry >::Code \ts_pin_entry_input_logic_code;      \r\n\tInp::Handler< PinEntry >*\tmp_pin_entry_input_handler;\r\n\r\n\tstatic\tTsk::Task< PinEntry >::Code  s_pin_entry_logic_code; \r\n\tTsk::Task< PinEntry >*\t\tmp_pin_entry_logic_task;\r\n\t\r\n};\r\n\r\nclass AuthMan\r\n{\r\npublic:\r\n\ttypedef enum\r\n\t{\r\n\t\tvSTATE_FILL_ACCOUNT_LIST,\r\n\t\tvSTATE_CREATE_ACCOUNT,\r\n\t\tvSTATE_SELECT_ACCOUNT,\r\n\t\tvSTATE_GET_PIN,\r\n\t\tvSTATE_PIN_COMPLETE,\r\n\t\tvSTATE_PIN_CLEARED,\r\n\t\tvSTATE_PIN_CANCELLED,\r\n\t\tvSTATE_LOG_ON,\r\n\t\tvSTATE_LOGGING_ON,\t\t\r\n\t\tvSTATE_LOGGED_IN,\r\n\t\tvSTATE_SUCCESS,\r\n\t\tvSTATE_CANCEL,\r\n\t\tvSTATE_ERROR,\r\n\t\tvSTATE_WAIT,\r\n\t} LogonState;\r\n\r\n\tenum\r\n\t{\r\n\t\tvERROR_WRONG_PIN,\r\n\t\tvERROR_GENERAL_LOGIN,\r\n\t\tvERROR_LOGIN_FAILED,\r\n\t\tvERROR_SERVICE_DOWN,\r\n\t};\r\n\r\n\tAuthMan( void );\r\n\r\n\tvoid\tUserLogon( void );\r\n\tvoid\tCancelLogon( void );\r\n\tvoid\tSelectAccount( int index );\r\n\tvoid\tPinAttempt( BYTE* pin );\r\n\tvoid\tSetState( LogonState state );\r\n\tvoid\tSignOut( void );\r\n\tbool\tSignedIn( void );\r\n\t\r\nprivate:\r\n\tint\t\tgather_user_list( void );\r\n\tvoid\tfill_user_list( void );\r\n\tvoid\tcreate_account( void );\r\n\tvoid\tlogon( void );\r\n\tvoid\tcheck_logon_progress( void );\r\n\tvoid\tpump_logon_task( void );\r\n\tbool\txbox_has_voice_device( void ); \r\n\r\n\tLst::DynamicTable< XONLINE_USER > m_user_list;\r\n\tLogonState\tm_state;\r\n\tLogonState\tm_next_state;\r\n\tint\t\t\tm_error;\r\n\tbool\t\tm_signed_in;\r\n\tint\t\t\tm_chosen_account;\r\n\tPinEntry\tm_pin_entry;\t\r\n\tXONLINETASK_HANDLE\tmh_online_task;\r\n\tDWORD\t\tmp_services[ vNUM_SERVICES ]; // List of desired services\r\n\tLst::DynamicTable< XONLINE_SERVICE_INFO > m_service_info_list;\r\n\r\n\tstatic\tTsk::Task< AuthMan >::Code  s_logon_state_code; \r\n\tTsk::Task< AuthMan >*\t\tmp_logon_state_task;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n#endif\t// __GAMENET_XBOX_P_AUTH_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/XBox/p_buddy.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_buddy.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/28/02\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXBox Buddy List Code \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <gel/mainloop.h>\r\n#include <GameNet/GameNet.h>\r\n#include <GameNet/Xbox/p_buddy.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tBuddyMan::s_buddy_state_code( const Tsk::Task< BuddyMan>& task )\r\n{\r\n\tBuddyMan& man = task.GetData();\r\n\r\n\tswitch( man.m_state )\r\n\t{\r\n\t\tcase vSTATE_UPDATE:\r\n\t\t\tman.update_buddy_list();\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_FILL_BUDDY_LIST:\r\n\t\t\tman.fill_buddy_list();\r\n\t\t\tman.m_state = vSTATE_WAIT;\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_SUCCESS:\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_CANCEL:\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_ERROR:\r\n\t\t\tbreak;\r\n\t\tcase vSTATE_WAIT:\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBuddyMan::fill_buddy_list( void )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tBuddyMan::update_buddy_list( void )\r\n{\r\n#\tif 0\r\n\tHRESULT hr = XOnlineTaskContinue( mh_friends_enum_task );\r\n    // Enumeration failed\r\n    if( FAILED( hr ) )\r\n    {\r\n        //m_UI.SetErrorStr( L\"Friend enumeration failed. Error %x\", hr );\r\n        //Reset( TRUE );\r\n        return;\r\n    }\r\n    \r\n    // Update generic status\r\n//    if( XOnlineNotificationIsPending( m_current_user, XONLINE_NOTIFICATION_TYPE_FRIENDREQUEST ))\r\n\t{\r\n        //SetStatus( L\"You have received a friend request\" );\r\n\t}\r\n//    else if( XOnlineNotificationIsPending( m_current_user, XONLINE_NOTIFICATION_TYPE_GAMEINVITE ))\r\n\t{\r\n        //SetStatus( L\"You have received a game invitation\" );\r\n\t}\r\n//    else\r\n\t{\r\n        //SetStatus( L\"Friend list refreshed\" );\r\n\t}\r\n    \r\n\tXONLINE_FRIEND\tfriend_list[MAX_FRIENDS];\r\n\tint\ti, num_friends;\r\n\r\n\tnum_friends = XOnlineFriendsGetLatest( m_current_user, MAX_FRIENDS, friend_list );\r\n\tif( num_friends != m_num_friends )\r\n\t{\r\n\t\tm_num_friends = num_friends;\r\n\t\tLst::DynamicTableDestroyer<XONLINE_FRIEND> destroyer( &m_friends_list );\r\n\t\tdestroyer.DeleteTableContents();\r\n\r\n\t\tfor( i = 0; i < num_friends; i++ )\r\n\t\t{\r\n\t\t\tXONLINE_FRIEND* new_friend;\r\n\r\n\t\t\tnew_friend = new XONLINE_FRIEND;\r\n\t\t\tmemcpy( new_friend, &friend_list[i], sizeof( XONLINE_FRIEND ));\r\n\t\t\tm_friends_list.Add( new_friend );\r\n\t\t}\r\n\t}    \r\n#\tendif\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\tBuddyMan::SpawnBuddyList( int user_index )\r\n{\r\n#\tif 0\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\r\n\tm_current_user = user_index;\r\n\r\n\t// Standard init\r\n    HRESULT hr = XOnlineFriendsStartup( NULL, &mh_friends_task );\r\n    if( FAILED(hr) )\r\n    {\r\n        //m_UI.SetErrorStr( L\"Friends failed to initialize. Error %x\", hr );\r\n        //Reset( TRUE );\r\n    }\r\n    \r\n    // Query server for latest list of friends\r\n    hr = XOnlineFriendsEnumerate( m_current_user, NULL, &mh_friends_enum_task );\r\n    if( FAILED(hr) )\r\n    {\r\n        //m_UI.SetErrorStr( L\"Friend enum failed to initialize. Error %x\", hr );\r\n        //Reset( TRUE );\r\n    }\r\n\r\n\tmp_buddy_state_task = new Tsk::Task< BuddyMan > ( s_buddy_state_code, *this,\r\n\t\t\t\t\t\t\t\t\t\tTsk::BaseTask::Node::vNORMAL_PRIORITY );\r\n\tmlp_man->AddLogicTask( *mp_buddy_state_task );\t\r\n\tm_state = vSTATE_UPDATE;\t\r\n#\tendif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nBuddyMan::BuddyMan( void )\r\n: m_potential_friends_list( 1 ), m_friends_list( MAX_FRIENDS ), m_num_friends( 1 )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/XBox/p_buddy.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_buddy.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/28/02\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXBox Buddy List Code \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GAMENET_XBOX_P_BUDDY_H\r\n#define __GAMENET_XBOX_P_BUDDY_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/dynamictable.h>\r\n#include <Xbox.h>\r\n#include <XOnline.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace GameNet\r\n{\r\n\r\nclass BuddyMan\r\n{\r\npublic:\r\n\ttypedef enum\r\n\t{\r\n\t\tvSTATE_FILL_BUDDY_LIST,\r\n\t\tvSTATE_UPDATE,\r\n\t\tvSTATE_SUCCESS,\r\n\t\tvSTATE_CANCEL,\r\n\t\tvSTATE_ERROR,\r\n\t\tvSTATE_WAIT,\r\n\t} BuddyState;\r\n\r\n\tBuddyMan( void );\r\n\r\n\tvoid\tSpawnBuddyList( int user_index );\r\n\r\nprivate:\r\n\r\n\tvoid\tupdate_buddy_list( void );\r\n\tvoid\tfill_buddy_list( void );\r\n\r\n\tint\t\tm_current_user;\r\n\tint\t\tm_num_friends;\r\n\tint\t\tm_state;\r\n\tint\t\tm_next_state;\r\n\tXONLINETASK_HANDLE\tmh_friends_task;\r\n\tXONLINETASK_HANDLE\tmh_friends_enum_task;\r\n\tLst::DynamicTable< XONLINE_USER > m_potential_friends_list;\r\n\tLst::DynamicTable< XONLINE_FRIEND > m_friends_list;\r\n\r\n\tstatic\tTsk::Task< BuddyMan >::Code  s_buddy_state_code; \r\n\tTsk::Task< BuddyMan >*\t\tmp_buddy_state_task;\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n#endif\t// __GAMENET_XBOX_P_BUDDY_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/XBox/p_match.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_match.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/28/02\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXBox Match-Making Code\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <GameNet/Xbox/p_match.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace GameNet\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/XBox/p_match.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_match.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/28/02\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXBox Matchmaking Code \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GAMENET_XBOX_P_MATCH_H\r\n#define __GAMENET_XBOX_P_MATCH_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n#endif\t// __GAMENET_XBOX_P_MATCH_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/XBox/p_voice.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_voice.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/12/02\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXBox Online Voice Chat Code\t\t \t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <sys/McMan.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/scripting/script.h>\r\n#include <GameNet/GameNet.h>\r\n#include <GameNet/Xbox/p_voice.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace GameNet\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nVoiceMan::VoiceMan( void )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tVoiceMan::Startup( void )\r\n{\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tVoiceMan::Shutdown( void )\r\n{\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n\r\n\t\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/XBox/p_voice.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tGameNet\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_voice.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/12/02\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXBox Online Voice Chat Code\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __GAMENET_XBOX_P_VOICE_H\r\n#define __GAMENET_XBOX_P_VOICE_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <sys/sioman.h>\r\n#include <Xbox.h>\r\n#include <XOnline.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace GameNet\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass VoiceMan\r\n{\r\npublic:\r\n\t\r\n\tVoiceMan( void );\r\n\r\n\tvoid\tStartup( void );\r\n\tvoid\tShutdown( void );\r\n\t\r\nprivate:\t\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace GameNet\r\n\r\n#endif\t// __GAMENET_XBOX_P_VOICE_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/GameNet/scriptdebugger.h",
    "content": "#ifndef __GAMENET_SCRIPTDEBUGGER_H__\r\n#define\t__GAMENET_SCRIPTDEBUGGER_H__\r\n\r\n#include <core/defines.h>\r\n\r\nnamespace GameNet\r\n{\r\n\r\n#define\tvSERVER_IP_VARIABLE\t\"VIEWER_IP\"\r\n\r\nenum\r\n{\r\n\tvSCRIPT_DEBUG_PORT = 10050, // Needs to be distinct from vEXPORT_COMM_PORT or any others\r\n};\t\r\n\r\nenum\r\n{\r\n\tvSCRIPT_DEBUG_GROUP = 10\r\n};\r\n\r\nenum\r\n{\t\r\n\t//\t32 is the first available user-defined message id\r\n\tvMSG_ID_DBG_PACKET\t\t\t\t\t\t\t= 32, // PC -> Game\r\n\t\r\n\tvMSG_ID_DBG_CHECKSUM_NAMES_BUFFER_SIZE\t\t= 33, // Game -> PC\r\n\tvMSG_ID_DBG_CHECKSUM_NAMES\t\t\t\t\t= 34, // Game -> PC\r\n\tvMSG_ID_DBG_CSCRIPT_LIST\t\t\t\t\t= 35, // Game -> PC\r\n\tvMSG_ID_DBG_WATCH_THIS\t\t\t\t\t\t= 36, // PC -> Game\r\n\tvMSG_ID_DBG_WATCH_SCRIPT\t\t\t\t\t= 37, // PC -> Game\r\n\tvMSG_ID_DBG_SCRIPT_CREATED\t\t\t\t\t= 38, // Game -> PC\r\n\tvMSG_ID_DBG_SCRIPT_DIED\t\t\t\t\t\t= 39, // Game -> PC\r\n\tvMSG_ID_DBG_CSCRIPT_INFO\t\t\t\t\t= 40, // Game -> PC\r\n\t\r\n\tvMSG_ID_DBG_COMPRESSION_LOOKUP_TABLE\t\t= 41, // Game -> PC\r\n\tvMSG_ID_DBG_BASIC_CSCRIPT_INFO\t\t\t\t= 42, // Game -> PC\r\n\tvMSG_ID_DBG_STOP\t\t\t\t\t\t\t= 43, // PC -> Game\r\n\tvMSG_ID_DBG_STEP_INTO\t\t\t\t\t\t= 44, // PC -> Game\r\n\tvMSG_ID_DBG_STEP_OVER\t\t\t\t\t\t= 45, // PC -> Game\r\n\tvMSG_ID_DBG_GO\t\t\t\t\t\t\t\t= 46, // PC -> Game\r\n\tvMSG_ID_DBG_SCRIPT_UPDATE_DELAY\t\t\t\t= 47, // PC -> Game\r\n\tvMSG_ID_DBG_CLEAR_SCRIPT_WATCHES\t\t\t= 48, // PC -> Game\r\n\tvMSG_ID_DBG_REFRESH\t\t\t\t\t\t\t= 49, // PC -> Game\r\n\tvMSG_ID_DBG_SEND_CSCRIPT_LIST\t\t\t\t= 50, // PC -> Game\r\n\t\r\n\tvMSG_ID_DBG_SEND_WATCH_LIST\t\t\t\t\t= 51, // PC -> Game\r\n\tvMSG_ID_DBG_WATCH_LIST\t\t\t\t\t\t= 52, // Game -> PC\r\n\tvMSG_ID_DBG_STOP_WATCHING_THIS_INDEX\t\t= 53, // PC -> Game\r\n\tvMSG_ID_DBG_STOP_WATCHING_THIS_CSCRIPT\t\t= 54, // PC -> Game\r\n\tvMSG_ID_DBG_SEND_COMPOSITE_OBJECT_INFO\t\t= 55, // PC -> Game\r\n\tvMSG_ID_DBG_COMPOSITE_OBJECT_INFO\t\t\t= 56, // Game -> PC\r\n\t\r\n\tvMSG_ID_DBG_MOUSE_POSITION\t\t\t\t\t= 57, // PC -> Game\r\n\tvMSG_ID_DBG_MOUSE_ON_SCREEN\t\t\t\t\t= 58, // PC -> Game\r\n\tvMSG_ID_DBG_MOUSE_OFF_SCREEN\t\t\t\t= 59, // PC -> Game\r\n\tvMSG_ID_DBG_MOUSE_LEFT_BUTTON_DOWN\t\t\t= 60, // PC -> Game\r\n\tvMSG_ID_DBG_MOUSE_LEFT_BUTTON_UP\t\t\t= 61, // PC -> Game\r\n\tvMSG_ID_DBG_MOUSE_RIGHT_BUTTON_DOWN\t\t\t= 62, // PC -> Game\r\n\tvMSG_ID_DBG_MOUSE_RIGHT_BUTTON_UP\t\t\t= 63, // PC -> Game\r\n\t\r\n\tvMSG_ID_DBG_COMPOSITE_OBJECT_LIST\t\t\t= 64, // Game -> PC\r\n\tvMSG_ID_DBG_SEND_COMPOSITE_OBJECT_LIST\t\t= 65, // PC -> Game\r\n\tvMSG_ID_DBG_SET_OBJECT_UPDATE_MODE\t\t\t= 66, // PC -> Game\r\n\tvMSG_ID_DBG_VIEW_OBJECT\t\t\t\t\t\t= 67, // PC -> Game\r\n\t\r\n\tvMSG_ID_DBG_SEND_SCRIPT_GLOBAL_INFO\t\t\t= 68, // PC -> Game\r\n\tvMSG_ID_DBG_SCRIPT_GLOBAL_INFO\t\t\t\t= 69, // Game -> PC\r\n\t\r\n\tvMSG_ID_DBG_EXCEPTION_INFO\t\t\t\t\t= 70, // Game -> PC\r\n\tvMSG_ID_DBG_RUNNING_SCRIPT\t\t\t\t\t= 71, // Game -> PC\r\n};\r\n\r\n}\r\n#endif\t// __GAMENET_SCRIPTDEBUGGER_H__"
  },
  {
    "path": "Code/Sk/Main.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMain\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmain.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\ta long long time ago\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMain entry code\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdio.h>\r\n#include <string.h>\r\n\r\n\r\nextern int maintest(int argc, char *argv[]);\r\nextern void test_init();\r\nextern void test_render();\r\n\r\n#ifdef __PLAT_NGC__\r\n#ifdef DVDETH\r\n#include <dolphin/dvdeth.h>\r\n#endif\r\n#include <libsn.h>\r\n#endif\r\n\r\n#include <core/defines.h>\t\r\n#include <core/thread.h>\r\n#include <core/singleton.h>\r\n\t\t \r\n#include <sys/profiler.h>\r\n#include <sys/timer.h>\r\n#include <sys/mem/memman.h>\r\n#include <sys/mem/memtest.h>\r\n#include <sys/sioman.h>\t\t\t\t\t\t\t\t\t\t   \r\n#include <sys/File/PRE.h>\r\n#include <sys/File/filesys.h>\r\n#include <sys/File/AsyncFilesys.h>\r\n#include <sys/mcman.h>\r\n#include <sys/config/config.h>\r\n\r\n\r\n#include <gfx/gfxman.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxloadscreen.h>\r\n#include <gfx/ngps/nx/nx_init.h>\r\n\r\n\r\n#include <gel/modman.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/objman.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/inpman.h>\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/music/music.h>\r\n#include <gel/net/net.h>\r\n#include <gel/assman/assman.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/FrontEnd/FrontEnd.h>\r\n#include <sk/objects/movingobject.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <gel/scripting/scriptcache.h> \r\n#include <gel/scripting/script.h> \r\n#include <gel/scripting/parse.h> \r\n#include <gel/scripting/symboltable.h> \r\n#include <sk/scripting/gs_init.h>\r\n#include <gfx/2D/ScreenElemMan.h>\r\n#include <sys/mem/PoolManager.h>\r\n#include <objects/pathman.h>\r\n#include <sys/replay/replay.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n\r\n#include <sk/ParkEditor2/ParkEd.h>\r\n#include <gel/scripting/Debugger.h>\r\n\r\n#include <gfx/ngps/nx/pcrtc.h>\r\n\r\n#ifdef __PLAT_NGPS__\r\n#include <libgraph.h>\r\n#endif\r\n\r\n#ifdef __PLAT_NGC__\r\n#include <sys/ngc/p_display.h>\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n#define MAINLOOP_MEMMARKER 16\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#include <eeregs.h>\r\n#include <libscedemo.h>\r\nextern char _code_start[];\r\nextern char _code_end[];\r\n\r\nextern char __floatdisf[];\r\nextern char dptofp[];\r\nextern char __fixunssfdi[];\r\nextern char __udivdi3[];\r\n#endif\r\n\r\n\r\n\r\n#ifdef\t__PLAT_NGPS__\r\nsceDemoEndReason\t\tdemo_exit_reason = SCE_DEMO_ENDREASON_PLAYABLE_QUIT;\t// default reason is that we quit (timeouts overrride this, and we can't \"complete\")\r\n#define\tDEBUG_FLASH(x)  //*GS_BGCOLOR = x  // 0xBBGGRR\r\n#else\r\n#define\tDEBUG_FLASH(x)\r\n#endif\r\n\r\nint\t\tinactive_time = 0;\r\nint\t\tinactive_countdown = 0;\r\nint\t\tgameplay_time = 0;\r\n\r\n\r\n\r\nbool\tskip_startup = false;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDbg_DefineProject( PS2, \"Test Project\" )\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern \"C\"\r\n{\r\n#ifdef __PLAT_XBOX__\r\nint pre_main( void );\r\n#endif\r\n#ifdef __PLAT_NGC__\r\nvoid __init_vm(void);\r\n#endif\r\n#ifdef __PLAT_NGPS__\r\nvoid pre_main( void );\r\n#endif\r\nvoid post_main( void );\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __PLAT_XBOX__\r\nint pre_main( void )\r\n#endif\r\n#ifdef __PLAT_NGC__\r\nvoid __init_vm( void )\r\n#endif\r\n#ifdef __PLAT_NGPS__\r\nvoid pre_main( void )\r\n#endif\r\n{\r\n\tDEBUG_FLASH(0x07f7f7f);\t\t// initial white\r\n\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tprintf (\"calling Mike test\\n\");\r\n//\tmaintest(0, NULL); // the Mike code.....\r\n\tprintf (\"DONE calling Mike test\\n\");\r\n#endif\t\t// __PLAT_NGPS__\r\n\r\n#ifdef __PLAT_NGC__\r\n\tOSInitFastCast();\r\n\tNsDisplay::init();\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\tDbg::SetUp();\r\n\tMem::Manager::sSetUp();\r\n\t\r\n\tDEBUG_FLASH(0x02050);\t\t// brown\r\n\r\n#ifdef __PLAT_XBOX__\r\n\t// Must return 0 here, as this is called from CRT initialization code.\r\n\treturn 0;\r\n}\r\n\r\n#pragma data_seg( \".CRT$RIX\" )\r\nstatic int (*_mypreinit)(void) = pre_main;\r\n#pragma data_seg()\r\n\r\n#else\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid post_main (void)\r\n{\r\n\tMem::Manager::sCloseDown();\r\n\tDbg::CloseDown();\r\n}\r\n\r\nvoid mat_test(Mth::Matrix A,Mth::Matrix B,Mth::Matrix C);\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nint main ( sint argc, char** argv )\r\n{ \t\r\n#ifdef __PLAT_NGC__\r\n#ifdef DVDETH\r\n\t// Defaults\r\n    u8   DvdServerAddr[4]    = { 192, 168,   0,   153 };// PC IP Address\r\n    u16  DvdServerPort       = 9001;                  // PC TCP PORT\r\n\r\n//    u8   ReportServerAddr[4] = { 192, 168,   0,   153 };// PC IP Address\r\n//    u16  ReportServerPort    = 9002;                  // PC TCP PORT\r\n\r\n    u8   GCClientAddr[4]     = { 192, 168,   5,   153 };// GC IP Adderss\r\n    u8   Netmask[4]          = { 255, 255,   0,   0 };// Netmask\r\n    u8   Gateway[4]          = { 192, 168,   0, 254 };// Gateway\r\n#endif\t\t// DVDETH\r\n\r\n\r\n\t// Add -a -pf to odemrun to enable printfs.\r\n\tbool kill = true;\r\n\tfor ( int arg = 1; arg < argc; arg++ )\r\n\t{\r\n\t\tif ( argv[arg][0] != '-' ) continue;\r\n\r\n\t\tswitch ( argv[arg][1] )\r\n\t\t{\r\n\t\t\tcase 'p':\r\n\t\t\t\t// Kill printfs.\r\n\t\t\t\tif ( argv[arg][2] == 'f' )\r\n\t\t\t\t{\r\n\t\t\t\t\tkill = false;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n#ifdef DVDETH\r\n\t\t\tcase 'i':\r\n\t\t\t\t// specify IP address.\r\n\t\t\t\tswitch ( argv[arg][2] )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase 'p':\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// PC IP address\r\n\t\t\t\t\t\t\tchar num0[8];\r\n\t\t\t\t\t\t\tchar num1[8];\r\n\t\t\t\t\t\t\tchar num2[8];\r\n\t\t\t\t\t\t\tchar num3[8];\r\n\t\t\t\t\t\t\tint c = 0;\r\n\t\t\t\t\t\t\tint d;\r\n\r\n\t\t\t\t\t\t\t// Get the numbers individually.\r\n\t\t\t\t\t\t\td = 0;      while ( argv[arg][3+c] != '.' ) { num0[d++] = argv[arg][3+c++]; } num0[d] = '\\0';\r\n\t\t\t\t\t\t\td = 0; c++; while ( argv[arg][3+c] != '.' ) { num1[d++] = argv[arg][3+c++]; } num1[d] = '\\0';\r\n\t\t\t\t\t\t\td = 0; c++; while ( argv[arg][3+c] != '.' ) { num2[d++] = argv[arg][3+c++]; } num2[d] = '\\0';\r\n\t\t\t\t\t\t\td = 0; c++; while ( argv[arg][3+c] != '\\0' ) { num3[d++] = argv[arg][3+c++]; } num3[d] = '\\0';\r\n\r\n\t\t\t\t\t\t\tDvdServerAddr[0] = atoi( num0 );\r\n\t\t\t\t\t\t\tDvdServerAddr[1] = atoi( num1 );\r\n\t\t\t\t\t\t\tDvdServerAddr[2] = atoi( num2 );\r\n\t\t\t\t\t\t\tDvdServerAddr[3] = atoi( num3 );\r\n\r\n//\t\t\t\t\t\t\tReportServerAddr[0] = atoi( num0 );\r\n//\t\t\t\t\t\t\tReportServerAddr[1] = atoi( num1 );\r\n//\t\t\t\t\t\t\tReportServerAddr[2] = atoi( num2 );\r\n//\t\t\t\t\t\t\tReportServerAddr[3] = atoi( num3 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 'g':\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// GameCube IP address\r\n\t\t\t\t\t\t\tchar num0[8];\r\n\t\t\t\t\t\t\tchar num1[8];\r\n\t\t\t\t\t\t\tchar num2[8];\r\n\t\t\t\t\t\t\tchar num3[8];\r\n\t\t\t\t\t\t\tint c = 0;\r\n\t\t\t\t\t\t\tint d;\r\n\r\n\t\t\t\t\t\t\t// Get the numbers individually.\r\n\t\t\t\t\t\t\td = 0;      while ( argv[arg][3+c] != '.' ) { num0[d++] = argv[arg][3+c++]; } num0[d] = '\\0';\r\n\t\t\t\t\t\t\td = 0; c++; while ( argv[arg][3+c] != '.' ) { num1[d++] = argv[arg][3+c++]; } num1[d] = '\\0';\r\n\t\t\t\t\t\t\td = 0; c++; while ( argv[arg][3+c] != '.' ) { num2[d++] = argv[arg][3+c++]; } num2[d] = '\\0';\r\n\t\t\t\t\t\t\td = 0; c++; while ( argv[arg][3+c] != '\\0' ) { num3[d++] = argv[arg][3+c++]; } num3[d] = '\\0';\r\n\r\n\t\t\t\t\t\t\tGCClientAddr[0] = atoi( num0 );\r\n\t\t\t\t\t\t\tGCClientAddr[1] = atoi( num1 );\r\n\t\t\t\t\t\t\tGCClientAddr[2] = atoi( num2 );\r\n\t\t\t\t\t\t\tGCClientAddr[3] = atoi( num3 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n#endif\t\t// DVDETH\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n#\tif !defined( __PLAT_NGC__ ) || ( defined( __PLAT_NGC__ ) && !defined( __NOPT_FINAL__ ) )\r\n\tif ( kill )\r\n\t{\r\n\t\t// Kill printfs\r\n\t\tuint32 * p;\r\n\t\tp = (uint32*)&OurPrintf;\r\n\t\t*p = 0x4e800020;\t\t// blr\r\n\t\tp = (uint32*)&OSReport;\r\n\t\t*p = 0x4e800020;        // blr\r\n\t}\r\n#endif\t// __NOPT_FINAL__\r\n\r\n#ifdef DVDETH\r\n\r\n    // Initialize Network\r\n    DVDEthInit(GCClientAddr, Netmask, Gateway);\r\n\r\n    // Initialize DVD\r\n    DVDLowInit(DvdServerAddr, DvdServerPort);\r\n\r\n//    // Initialize OSReport();\r\n//    OSReportInit(ReportServerAddr, ReportServerPort);\r\n#endif\r\n\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\t// Note: printf's will not work until after Config::Init() is called.\r\n\r\n\tDEBUG_FLASH(0x007F0000);\r\n\t\r\n\tMem::SetThreadSafe(false);\t\r\n\tConfig::Init(argc,argv);\r\n\r\n#ifdef __PLAT_NGPS__\r\n\t// a hack to disable the PS2 video output as early as poss\r\n\tNxPs2::SetupPCRTC(0, SCE_GS_FIELD);\r\n#endif\t\t// __PLAT_NGPS__\r\n\r\n\tDEBUG_FLASH(0x00007f00);\r\n\t\t\t\t\t  \r\n\tMem::Manager::sHandle().InitOtherHeaps();\t\t\t\t\t\t\t\r\n\r\n\tDEBUG_FLASH(0x0000007f);\r\n\r\n\t#ifdef\t__PLAT_NGPS__\r\n// Need to reconcile the Config::Init with the following code\r\n// so demo version can exist with regular version\r\n// just switched by examining command line\r\n\r\n\tif (Config::SonyBootstrap())\r\n\t{\r\n\t\t\t\t\t\t\t\t   \r\n\t\tunsigned short language;\r\n\t\tunsigned short aspect;\r\n\t\tunsigned short playmode;\r\n\t\tunsigned short to_inactive;\r\n\t\tunsigned short to_total;\r\n\t\tunsigned short mediaType;\r\n\t\tunsigned short masterVolumeScale = 10;\r\n\t\tunsigned short directorySectorNum;\r\n\t\t\t\r\n\t\tsceDemoStart(argc,argv,&language,&aspect,&playmode,&to_inactive,&to_total,&mediaType,&masterVolumeScale,&directorySectorNum);\r\n\t\t\r\n\t\tprintf(\"Tony Hawk's Pro Skater 4 - Demo Disk Version\\n\");\r\n\t\tprintf(\"l %d a %d pm %d toa %d tot %d\\n\",language,aspect,playmode,to_inactive,to_total);\r\n\t\tprintf(\"MEDIA TYPE %d\\n\",mediaType);\r\n\t\tprintf(\"MasterVol Scale %d\\n\",masterVolumeScale);\r\n\t\tprintf(\"My directory Sector is %d\\n\",directorySectorNum);\r\n\t\t\r\n\t\tinactive_time = to_inactive * 60;\r\n\t\tinactive_countdown = to_inactive * 60;\r\n\t\tgameplay_time = to_total * 60;\r\n\t\t\r\n\t\tif (Config::Bootstrap() && Config::CD())\r\n\t\t{\r\n\t\t\tConfig::SetMasterVolume(masterVolumeScale * 10.0f);\r\n\t\t}\r\n\t}\r\n\t#endif\t\t   \r\n\t\r\n\t\r\n//\tConfig::SetMasterVolume(0.0f);\r\n\t \t\t   \r\n\t\r\n\t\r\n\tprintf (\"\\n Start of main()\\n\");\r\n\tprintf (\"argc = %d\\n\",argc); \r\n\tfor (int arg = 0; arg < argc; arg++)\r\n\t{\r\n\t\tprintf (\"%2d: %s\\n\",arg,argv[arg]);\r\n\t}\r\n\tprintf (\"\\n\");\r\n\t\r\n\t//printf(\"Hardware=%s\\n\",Config::GetHardwareName());\r\n\t//printf(\"GotExtraMemory=%d\\n\",Config::GotExtraMemory());\r\n\t//printf(\"Language=%s\\n\",Config::GetLanguageName());\r\n\t//printf(\"CD=%d\\n\",Config::CD());\r\n\t\r\n\tif (Config::GotExtraMemory())\r\n\t{\r\n\t\tMem::Manager::sSetUpDebugHeap();\r\n\t}\t\r\n\r\n\tMem::PushMemProfile(\"Everything\");\r\n\tMem::PushMemProfile(\"Initialization\");\r\n\r\n\t\r\n//\tstatic char\tprofdata[8192];\r\n//\tsnDebugInit();\r\n//\tsnProfInit(_4KHZ, profdata, sizeof(profdata));\r\n\r\n\tif (argc == 2 && strcmp(argv[1],\"demo\") == 0)\r\n\t{\r\n\t\tskip_startup = true;\r\n\t}\r\n\t\r\n\t\r\n\tDEBUG_FLASH(0x007f007f);\t\t// magenta\r\n\t\r\n\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n#ifdef\t__PLAT_NGPS__\t\r\n\tstatic u_long128 profdata[2048]; // quadword aligned, can be 2K\r\n\t\t\t\t\t\t\t\t\t // to 64K bytes\r\n\r\n\t// we now always turn on profiling if running on a TOOL (unless we are on a CD)\t\t\t\t\t\t\t\t\t \r\n\tif (Config::GetHardware() == Config::HARDWARE_PS2_DEVSYSTEM && !Config::CD())\r\n\t{\r\n\t\tsnDebugInit();\r\n\t\tsceSifInitRpc(0);\r\n\t\t// Load the SNProfil module\r\n\t\tif(sceSifLoadModule(\"host0:/usr/local/sce/iop/modules/SNProfil.irx\", 0, NULL) < 0)\r\n\t\t{\r\n\t\t\tprintf(\"Can't load SNProfil module, but don't worry, that's just for programmers...\\n However, you could get the latest version of usr if you want it\\n\");\r\n\t//\t\texit(-1);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif(snProfInit(_4KHZ, profdata, sizeof(profdata)) != 0)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"Profiler init failed\\n\"); // see SN_PRF in LIBSN.H\r\n\t\t\t}\r\n\t\t}\t\r\n\t}\t\r\n\t// rest of user code follows on from here...\r\n#endif\r\n#endif\r\n\r\n\tDbg_Message ( \"Begin Application\" );\t\t\t\t\t\t \r\n\tMth::InitialRand(107482099);\r\n\r\n#if 0\r\n\t\tMth::InitSinLookupTable();\r\n#ifdef  __PLAT_NGPS__\r\n// (Mick)  THis might not be needed with the new libs\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\t\t// Run through all the code and replace all calls to sinf, cosf\r\n\t\t// with faster versions that use a lookup table.\r\n\t\t// Note: This must be done after the call to Mth::InitSinLookupTable(); above,\r\n\t\t// because that uses the original sinf to generate the lookup table.\r\n\t\tint *pc = (int*)_code_start;\r\n\t\twhile (pc < (int*)_code_end)\r\n\t\t{\r\n\r\n\t\t\tint instruction = *pc;\r\n\t\t\tif (instruction >> 24 == 0x0c)\r\n\t\t\t{\r\n\t\t\t\tint code = (instruction & 0xffffff)<<2;\r\n\t\t\t\tif (code == (int)sinf)\r\n\t\t\t\t{\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t*pc=(*pc&0xff000000)| ((((uint32)Mth::Kensinf)>>2)&0xffffff);\r\n\t\t\t\t}\r\n\t\t\t\telse if (code == (int)cosf)\r\n\t\t\t\t{\r\n\t\t\t\t\t*pc=(*pc&0xff000000)| ((((uint32)Mth::Kencosf)>>2)&0xffffff);\r\n\t\t\t\t}\r\n\t\t\t\telse if (code == (int)acosf)\r\n\t\t\t\t{\r\n\t\t\t\t\t*pc=(*pc&0xff000000)| ((((uint32)Mth::Kenacosf)>>2)&0xffffff);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t++pc;\r\n\t   }\r\n\t   \r\n#endif\t\t\t\t \r\n#endif\t\t\t\t \r\n\r\n\r\n#ifdef __NOPT_ASSERT__\r\n#ifdef  __PLAT_NGPS__\r\n\tMem::PushMemProfile(\"(debug only) Log::Init()\");\r\n\tLog::Init();\r\n\tMem::PopMemProfile();\r\n#endif\r\n#endif\r\n\r\n\t\r\n\twhile (  true )\r\n\t{\t\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PushContext();\r\n\t\tMem::Manager::sHandle().PushMemoryMarker(MAINLOOP_MEMMARKER);\r\n\t\t{\r\n\t\t\t/*\r\n\t\t\t\tImportant Notes:\r\n\t\t\t\t\r\n\t\t\t\tPlease put all module creation/registering/starting code in its proper section.\r\n\t\t\t\tThis helps prevents bugs caused by initialization code depending on objects\r\n\t\t\t\tthat have not been initialized.\r\n\t\t\t\t\r\n\t\t\t\tThere are two stages to initialization. First, object creation (create singleton\r\n\t\t\t\tsection). Second, running the object's v_start function (start modules section).\r\n\t\t\t\tNote that the latter doesn't happen when StartModule is called, but after the\r\n\t\t\t\tmain loop is entered.\r\n\t\t\t\r\n\t\t\t\tIt would be a bad idea to make code in any module's constructor depend on initialization \r\n\t\t\t\tdone in another's v_start function.\r\n\t\t\t*/\r\n\t\t\t\r\n\t\t\t// We create the symbol hash table early, as it's kind of used my Music::Init, which I think\r\n\t\t\t// is called both at startup (when the scripts are invalid), and later (when they are valid)\r\n\t\t\tScript::CreateSymbolHashTable();\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\r\n\t\t\t/***********************************************\r\n\t\t\tGeneral startup section\r\n\t\t\t************************************************/\r\n\t\t\t\r\n\t\t\tMem::PushMemProfile(\"Hash Item Pool Manager\");\r\n#\t\t\tif( defined( __PLAT_NGC__ ) || defined( __PLAT_XBOX__ ))\r\n\t\t\tMem::PoolManager::SSetupPool(Mem::PoolManager::vHASH_ITEM_POOL, 12500);\t// Mick: increased from 5600 to 10000\r\n#\t\t\telse\r\n\t\t\tMem::PoolManager::SSetupPool(Mem::PoolManager::vHASH_ITEM_POOL, 10000);\t// Mick: increased from 5600 to 10000\r\n#\t\t\tendif // __PLAT_NGC__ || __PLAT_XBOX__\r\n\t\t\tMem::PopMemProfile(/*\"Hash Item Pool Manager\"*/);\r\n\r\n\t\t\t\t\r\n\t\t\t// I'd prefer for this stuff to happen after the singleton section,\r\n\t\t\t// but it won't work that way\r\n\t\t\t\r\n\t\t\tSpt::SingletonPtr< File::PreMgr> pre_mgr(true);\t\t // Note, moved here so SkateScript::Init can use it\r\n\t\t\t   \t\r\n\t\t\t/***********************************************\r\n\t\t\tCreate singleton section\r\n\t\t\t************************************************/\r\n\t\t\t\r\n\t\t\t/*\r\n\t\t\t\tRJM:\r\n\t\t\t\t\r\n\t\t\t\t-SkateMod must come after panelMgr, because it references the panelMgr singleton\r\n\t\t\t*/\r\n\t\t\t\r\n\t\t\tTmr::Init();\r\n\t\t\t\r\n\t\t\tMem::PushMemProfile(\"File System\");\r\n\t\t\tFile::InstallFileSystem();               \r\n\t\t\tMem::PopMemProfile(/*\"File System\"*/);\r\n\r\n\t\t\t\t\t\t\t\t\r\n\t\t\tDEBUG_FLASH(0x007f7f00);\t\t// cyan\r\n\t\t\t\t\t\t\t\t\r\n\t\t\tMem::PushMemProfile(\"System Singletons\");\r\n\t\t\tSpt::SingletonPtr< Obj::CTracker >\tobj_tracker( true );\r\n\t\t\tSpt::SingletonPtr< Mlp::Manager >\tmlp_manager( true );\r\n\t\t\tSpt::SingletonPtr< Mdl::Manager >\tmdl_manager( true );\r\n\t\t\tSpt::SingletonPtr< SIO::Manager >\tsio_manager( true );\r\n\t\t\tSpt::SingletonPtr< Mc::Manager > \tmc_manager( true );\r\n\t\t\tSpt::SingletonPtr< Inp::Manager >\tinp_manager( true );\r\n\t\t\tSpt::SingletonPtr< Gfx::Manager >\tgfx_manager( true );\r\n\t\t\tSpt::SingletonPtr< File::CAsyncFilePoll>\tasync_poll( true );\r\n\t\t\tMem::PopMemProfile(/*\"System Singletons\"*/);\r\n\r\n\t\t\tDEBUG_FLASH(0x00007f7f);\t\t// yellow\r\n\r\n\r\n\t\t\t#ifdef\t__PLAT_NGPS__\r\n\t\t\tNxPs2::InitialiseEngine();\r\n\t\t\tNx::CLoadScreen::sDisplay( \"loadscrn\", false, false );\r\n\t\t\t//Nx::CLoadScreen::sStartLoadingBar(duration);\r\n\t\t\t#endif\r\n\r\n\t\t\t\r\n\t\t\t// NOTE:  I moved SkateScript::Init() down here, as\r\n\t\t\t// we want to display the loading screen before\r\n\t\t\t// we load any other files (so it loads as fast as possible)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\t\t// SO, NO SCRIPT FUNCTIONS MAY BE USED BEFORE THIS POINT\r\n\r\n\t\t\tMem::PushMemProfile(\"SkateScript::Init()\");\r\n\t\t\tSkateScript::Init();\t \t\t\t\r\n\r\n\t\t\tMem::PushMemProfile(\"Game Singletons\");\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tSpt::SingletonPtr< Dbg::CScriptDebugger> script_debugger(true);\r\n\t\t\t#endif\r\n\t\t\tMem::PopMemProfile();\r\n\r\n#ifdef __PLAT_NGC__\r\nextern uint8 * RES_gamecube;\r\n\t\t\tSpt::SingletonPtr< Script::CScriptCache>\t\t\tscript_cache( true );\r\n\t\t\tScript::ParseQB( \"scripts\\\\engine\\\\gamecube.qb\", RES_gamecube );\r\n\r\n\t\t\tif ( ( VIGetTvFormat() == VI_NTSC ) || ( VIGetTvFormat() == VI_MPAL ) )\r\n\t\t\t{\r\n\t\t\t\tNsDisplay::Check480P();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tNsDisplay::Check60Hz();\r\n\t\t\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\tSkateScript::Preload();\r\n\t\t\tMem::PopMemProfile();\r\n\t\t\t\r\n\t\t\tMem::PushMemProfile(\"Game Singletons\");\r\n\t\t\tObj::CPathMan::Instance(); // Force creation of CPathMan singleton\r\n\r\n#ifndef __PLAT_NGC__\r\n\t\t\tSpt::SingletonPtr< Script::CScriptCache>\t\t\tscript_cache( true );\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\tSpt::SingletonPtr< Ass::CAssMan > \t\t\t\t\tass_manager( true );\r\n\t\t\tSpt::SingletonPtr< Sfx::CSfxManager > \t\t\t\tsfx_manager( true );\t\t\t\r\n\t\t\tSpt::SingletonPtr< Net::Manager >\t\t\t\t\tnet_manager( true );\t\r\n\t\t\tSpt::SingletonPtr< Obj::CCompositeObjectManager >   composite_object_manager( true );\r\n\t\t\tSpt::SingletonPtr< Mdl::Skate >\t\t\t\t\t\tskate_mod( true );\r\n\t\t\tSpt::SingletonPtr< Mdl::FrontEnd > \t\t\t\t\tfront(true);\r\n\t\t\tSpt::SingletonPtr< GameNet::Manager > \t\t\t\tgamenet_man( true );\r\n\t\t\tSpt::SingletonPtr< Ed::CParkEditor>\t\t\t\t\tgrandpas_park_editor(true);\r\n\r\n\t\t\tSpt::SingletonPtr< Front::CScreenElementManager > \tscreen_elem_manager(true);\r\n#if __USE_REPLAYS__\r\n\t\t\tSpt::SingletonPtr< Replay::Manager > \t\t\t\treplay_manager( true );\r\n#endif\t\t\t\r\n\t\t\tMem::PopMemProfile(/*\"Game Singletons\"*/);\r\n\r\n\t\t\tDEBUG_FLASH(0x007f7f7f);\t\t// white\r\n\r\n\t\t\tMem::PushMemProfile(\"Resgistering and starting modules\");\r\n\r\n\t\t\t/***********************************************\r\n\t\t\tSetup main loop tasks section\r\n\t\t\t************************************************/\r\n\r\n\t\t\t// Note, some managers/modules add their tasks in their constructors\r\n\t\t\t// however, these three are hooked up in the main loop, for some reason\r\n\t\t\t// and have to provide a global function to get a pointer to\r\n\t\t\t// their appropiate tasks\r\n\t\t\r\n//\t\t\tmlp_manager->AddSystemTask ( tgt_manager->GetProcessBackGroundTasks() );\r\n\t\t\tmlp_manager->AddSystemTask ( mdl_manager->GetProcessModulesTask() );   // Note: this hooks up the code that starts the modules\r\n\t\t\tmlp_manager->AddSystemTask ( sio_manager->GetProcessDevicesTask() );\r\n\t\t\tmlp_manager->AddLogicTask  ( inp_manager->GetProcessHandlersTask() );\r\n\t\t\r\n\t\t\t/***********************************************\r\n\t\t\tRegister modules section\r\n\t\t\t************************************************/\r\n\t\t\t\r\n\t\t\t/* \r\n\t\t\t\tRJM: \r\n\t\t\t\t\r\n\t\t\t\tThe FrontEnd and Panel Managers must be initialized before the Skate Mod,\r\n\t\t\t\tso that the game can be launched from a startup script without problems\r\n\t\t\t\r\n\t\t\t*/\r\n\t\t\t\r\n\t\t\tmdl_manager->RegisterModule ( *script_cache );\r\n\t\t\tmdl_manager->RegisterModule ( *grandpas_park_editor );\r\n\t\t\tmdl_manager->RegisterModule ( *front );\r\n\t\t\tmdl_manager->RegisterModule ( *skate_mod );\r\n\t\t\tmdl_manager->RegisterModule ( *async_poll );\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tmdl_manager->RegisterModule ( *script_debugger );\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\t/***********************************************\r\n\t\t\tStart modules section\r\n\t\t\t************************************************/\r\n\t\t\t\r\n\t\t\tmdl_manager->StartModule( *script_cache );\r\n\t\t\tmdl_manager->StartModule( *front );\r\n\t\t\tmdl_manager->StartModule( *skate_mod );      \r\n\t\t\tmdl_manager->StartModule ( *grandpas_park_editor );\r\n\t\t\tmdl_manager->StartModule ( *async_poll );\r\n\t\t\t\r\n\t\t\tMem::PopMemProfile(/*\"Resgistering and starting modules\"*/);\r\n\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t/***********************************************\r\n\t\t\tMain loop section\r\n\t\t\t************************************************/\r\n\t\t\t\r\n#ifdef\t\t__USE_PROFILER__\r\n\t\t\tSys::Profiler::sSetUp(2);\r\n#endif\t\t\t\r\n\t\t\t\r\n\t\t\tMem::PushMemProfile(\"sStartEngine\");\r\n\t\t\tNx::CEngine::sStartEngine();\r\n\t\t\tMem::PopMemProfile(/*\"sStartEngine\"*/);\r\n\r\n\t\t\tDbg_Message ( \"Starting main loop\" );\r\n// Note to the adventurer:\r\n// Where does control go now? .... you may well ask\r\n// The above \"modules\" have simply been flagged as wanting to start, they have not\r\n// actually started yet.\r\n// The code that actually runs them is called ultimately from \"service_system\" in mainloop.cpp\r\n// \"service_system\" iterates over the \"system_task_list\", and calls all the tasks\r\n// in that list.  One of those tasks is the task returned by GetProcessModulesTask()\r\n// which is added to the task list by the line:\r\n// \t\t\tmlp_manager->AddSystemTask ( mdl_manager->GetProcessModulesTask() );\r\n// above.\r\n// The GetProcessModulesTask() returns (via some indirection), Mdl::Manager::process_modules\r\n// and this function iterates over the modules registered with the module manager\r\n// in part it checks if (current->command == Module::vSTART), and if so, then it calls\r\n// \t\t\t\t\tcurrent->v_start_cb();\r\n// which in the case of the skate module is Mdl::Skate::v_start_cb\r\n// which does some initialization of the skate module\r\n// and in the course of that, calls \r\n//\tScript::RunScript(\"default_system_startup\");\r\n//\tScript::RunScript(\"StartUp\");\t<<< but not on the CD version\r\n//\r\n// The \"Startup\" script differs per person during development, but will typically look like:\r\n//\r\n//\tscript startup\r\n//\t    autolaunch level=load_sch game=career\r\n//\tendscript\r\n//\r\n// which calls a bunch of commands to ultimately load the level geometry,\r\n// parse the triggers in the \"node array\" \r\n// and drop in the skater\r\n// and start skating.\r\n// phew\r\n\r\n\t\t\tMem::PopMemProfile(/*Initilization*/);\r\n\t\t\t\r\n\t\t\t\r\n\t\t\tMem::PushMemProfile(\"MainLoop\");\r\n\t\t\tmlp_manager->MainLoop();\r\n\t\t\tMem::PopMemProfile(/*\"MainLoop\"*/);\r\n\t\t\t\r\n// The following code is theoretical, as we actually never shut down the whole game\t\t\t\r\n// On the PS2, we use the script command \"LoadExecPS2\", which calls \"ScriptLoadExecPS2\" in cfuncs.cpp\r\n// which allows us to load another executable.  This would either be a demo or another game\r\n// or it would be returning to the bootstrap loader.\r\n\t\t\t\r\n\t\t\tDbg_Message ( \"Ending main loop\" );\r\n\t\t\t\r\n#ifdef\t\t__USE_PROFILER__\r\n\t\t\tSys::Profiler::sCloseDown();\r\n#endif\t\t\t\r\n\t\t\tmdl_manager->StopAllModules();\r\n\t\t\t\r\n\t\t\t/***********************************************\r\n\t\t\tUnregister section\r\n\t\t\t************************************************/\r\n\t\t\t\r\n\t\t\tmdl_manager->UnregisterModule ( *skate_mod );\r\n\t\t\tmdl_manager->UnregisterModule ( *front );\r\n\t\t\tmdl_manager->UnregisterModule ( *grandpas_park_editor );\r\n\t\t\tmdl_manager->UnregisterModule ( *async_poll );\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tmdl_manager->UnregisterModule ( *script_debugger );\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\t/***********************************************\r\n\t\t\tGeneral closedown\r\n\t\t\t************************************************/\r\n\t\t\t\r\n\t\t\tmlp_manager->RemoveAllDisplayTasks();\t\t\t\r\n\t\t\tmlp_manager->RemoveAllLogicTasks();\r\n\t\t\tmlp_manager->RemoveAllSystemTasks();\r\n\r\n\t\t\tDbg_Message ( \"End Application\" );\r\n\t\t}\r\n\t\tTmr::DeInit();\r\n\t\tMem::Manager::sHandle().PopMemoryMarker(MAINLOOP_MEMMARKER);\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PopContext();\r\n\tMth::Matrix A,B,C;\r\n\tmat_test(A,B,C);\t\t\t\t \r\n\t}\r\n\r\n\t\t\t\t \r\n\treturn 0;\r\n}\r\n\r\nvoid nob(Mth::Matrix A);\r\n\r\nvoid mat_test(const Mth::Matrix A,const Mth::Matrix B,Mth::Matrix C)\r\n{\r\n\r\n\tMth::Matrix D;\r\n\tD = A * B;\r\n}\r\n\r\nvoid nob(Mth::Matrix A)\r\n{\r\n\tprintf (\"%f\",A[X][X]);\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t                    \t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/FrontEnd/FrontEnd.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t \t\t\t                              \t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t\t\t\t\t\t\t\t\t\t                    **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t    rjm, 9/12/2000\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t\t\t\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// start autoduck documentation\r\n// @DOC frontend\r\n// @module frontend | None\r\n// @subindex Scripting Database\r\n// @index script | frontend\r\n                                    \r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/support.h>\r\n#include <core/task.h>\r\n\r\n#include <gfx/gfxman.h>\r\n#include <gfx/camera.h>\r\n\r\n#include <gel/inpman.h>\r\n#include <gel/module.h>\r\n#include <gel/music/music.h>\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/net/net.h>\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n\r\n#include <modules/FrontEnd/FrontEnd.h>\r\n#include <sk/modules/skate/skate.h>\r\n\r\n#include <objects/skaterprofile.h>\r\n\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <scripting/cfuncs.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sys/sio/keyboard.h>\r\n#include <sys/profiler.h>\r\n#include <sys/File/PRE.h>\r\n#include <sys/replay/replay.h>\r\n\r\n\r\n#include <gfx/2D/ScreenElemMan.h>\r\n\r\n#include <sk/objects/skater.h>\t\t   // just for pausing the skater, and for running the \"run me now\" script\r\n\r\n\t\t\t\t\t\t\t\t\t\t   \r\nextern bool run_runmenow;\r\n\r\nnamespace Mdl\r\n{\r\nDefineSingletonClass( FrontEnd, \"Frontend module\" );\r\n\r\n\r\nFrontEnd::FrontEnd()\r\n{\r\n\r\n\tm_logic_task = new Tsk::Task< FrontEnd > ( FrontEnd::s_logic_code, *this, Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_FRONTEND);\r\n\tm_handle_keyboard_task = new Tsk::Task< FrontEnd > ( FrontEnd::s_handle_keyboard_code, *this, Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_HANDLE_KEYBOARD);\r\n\t\r\n\tfor ( int i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n\t\tmp_input_handlers[i] = new Inp::Handler< FrontEnd > ( i, FrontEnd::s_input_logic_code, *this, Tsk::BaseTask::Node::vHANDLER_PRIORITY_FRONTEND_INPUT_LOGIC0);\t\t\r\n\t\tm_pad_info[i].mState =  NOT_DOWN;\r\n\t\tm_pad_info[i].mMode = ACTIVE;\r\n\t}\r\n\tm_paused = false;\r\n\r\n\tm_auto_repeat_time[0] = Tmr::vRESOLUTION * 3 / 10;\r\n\tm_auto_repeat_time[1] = Tmr::vRESOLUTION * 5 / 100;\r\n\t\r\n\t\r\n\t// m_pad_info[1].mState =  NOT_DOWN;\r\n\t\r\n\t// m_pad_info[1].mMode = INACTIVE;\r\n\r\n\tm_temp_block_pad_input = false;\r\n\r\n\tm_using_auto_input = false;\r\n\tm_check_for_auto_input = true;\r\n\tm_auto_input_script_id = 0;\r\n\r\n\tfor (int i = 0; i < MAX_BUTTON_EVENT_MAP_ENTRIES; i++)\r\n\t{\r\n\t\tm_digital_button_event_map[i].mEventType = DEAD_ENTRY;\r\n\t}\r\n\r\n\tfor ( int i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t\tm_device_server_map[i] = i;\r\n}\r\n\r\n\r\n\r\n\r\nFrontEnd::~FrontEnd()\r\n{\r\n\tdelete m_logic_task;\r\n\t\r\n\tfor ( int i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n\t\tdelete mp_input_handlers[i];\r\n\t\tmp_input_handlers[i] = NULL;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid FrontEnd::v_start_cb ( void )\r\n{\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\tMlp::Manager * mlp_manager = Mlp::Manager::Instance(); \r\n\t\tmlp_manager->AddLogicTask ( *m_logic_task );\r\n\t\tInp::Manager * inp_manager = Inp::Manager::Instance(); \r\n\t\t\r\n\t\tfor ( int i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t\t{\r\n\t\t\tInp::Handler< FrontEnd >* p_handler = GetInputHandler( i );\r\n\t\t\tinp_manager->AddHandler( *p_handler );\r\n\t\t}\r\n\tMem::Manager::sHandle().PopContext();\t\r\n}\r\n\r\n\r\n\r\n\r\nvoid FrontEnd::v_stop_cb ( void )\r\n{\r\n\tm_logic_task->Remove();\r\n\t\r\n\tfor ( int i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n\t\tInp::Handler< FrontEnd >* p_handler = GetInputHandler( i );\r\n\t\tp_handler->Remove();\r\n\t}\r\n}\r\n\r\n\r\nbool FrontEnd::PadsPluggedIn()\r\n{\r\n\tfor ( int i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n\t\tDbg_MsgAssert(mp_input_handlers[i],(\"NULL mp_input_handlers[%d]\",i));\r\n\t\tif (mp_input_handlers[i]->m_Device->IsPluggedIn())\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\t\t\r\n}\r\n\r\n\r\n\r\nvoid FrontEnd::AddKeyboardHandler( int max_string_length )\r\n{\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance(); \r\n\r\n\tm_max_kb_string_length = max_string_length;\r\n\tmlp_manager->AddLogicTask( *m_handle_keyboard_task );\r\n}\r\n\r\n\r\n\r\n\r\nvoid FrontEnd::RemoveKeyboardHandler( void )\r\n{\r\n\tm_handle_keyboard_task->Remove();\r\n}\r\n\r\n\r\n\r\n\r\nvoid FrontEnd::SetAnalogStickActiveForMenus( bool isActive )\r\n{\r\n\tSpt::SingletonPtr<Inp::Manager> p_manager;\r\n\tp_manager->SetAnalogStickOverride(isActive);\r\n}\r\n\r\n\r\n\r\n\r\n///////////////////////////////////////////\r\n// (Mick takes responsibility for this)\r\n// This function JUST pauses the game\r\n// this mainly consists of pausing all the tasks (for objects, cars, peds), but\r\n// first it pauses the skate module (for music), and the sio_manager (pad vibration)\r\n//\r\n// The pausing of stuff is fairly comvoluted, here we:\r\n//\r\n// Pause the PCM music\r\n// pause the pad vibration\r\n// pause all messages, but allow future messages to be launched\r\n// pause all spawned scripts, apart from the current one, and future spawned scritps \r\n//\r\n// pause the skater, but still allow the reading of the pad from script \r\n//\r\n// Overall, a rather mixed bag of things, which might be best refactored\r\n// but should do for now.....\r\n//\r\n// Note:  is_active == true ... implies the \"Front End\" is active, and the \"game\" paused\r\n\r\nvoid FrontEnd::PauseGame(bool paused)\r\n{\r\n\t\r\n\t// if already in the correct \"paused\" state, then just return\r\n\tif (paused == m_paused)\t\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\t\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tif (paused)\r\n\t{\r\n\t\t// make game be paused\r\n\t\tskate_mod->Pause( );\r\n\t\t\r\n\t\t// Ken: Pause the controller vibrations.\r\n\t\tSIO::Manager * sio_man = SIO::Manager::Instance();\r\n\t\tsio_man->Pause();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// make game be unpaused\r\n\t\t// Ken: Un-pause the controller vibrations.\r\n\t\tSIO::Manager * sio_man = SIO::Manager::Instance();\r\n\t\tsio_man->UnPause();\r\n\t}\r\n\t\r\n\t// Pause currently spawned scripts (any script with PauseGame in it will unpause itself)\t\t\r\n\tScript::PauseSpawnedScripts(paused);\t\t\r\n\t\r\n\t// Pause or unpause all the skaters\r\n\tuint32 NumSkaters = skate_mod->GetNumSkaters();\r\n\t\r\n\tfor (uint32 i = 0; i < NumSkaters; ++i)\r\n\t{\r\n\t\tObj::CSkater *pSkater = skate_mod->GetSkater(i);\r\n\t\tif (pSkater) // Hmm, assert instead?\r\n\t\t{\r\n\t\t\tif (paused)\r\n\t\t\t{\r\n\t\t\t\tpSkater->Pause();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpSkater->UnPause();\r\n\t\t\t}\r\n\t\t}\t\r\n\t}\t\r\n\t\r\n\t// Pause all composite objects\r\n\tObj::CCompositeObjectManager::Instance()->Pause(paused);\r\n\t\r\n\r\n\t// pause (or unpause) any screen elements in process of morphing\r\n\tFront::CScreenElementManager* p_screen_element_manager = Front::CScreenElementManager::Instance();\r\n\tp_screen_element_manager->SetPausedState(paused);\r\n\t\r\n\tm_paused = paused;\r\n\r\n\t\r\n\tif (m_paused)\r\n\t{\r\n\t\t// make game be paused\r\n\t\tMlp::Manager * mlp_manager = Mlp::Manager::Instance(); \r\n\t\tmlp_manager->SetLogicMask(Mlp::Manager::mGAME_OBJECTS | Mlp::Manager::mGFX_MANAGER);\r\n\t\tTmr::StoreTimerInfo( );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// make game be unpaused\r\n\t\tMlp::Manager * mlp_manager = Mlp::Manager::Instance(); \r\n\t\tmlp_manager->SetLogicMask(Mlp::Manager::mNONE);\t\t\r\n//\t\trw_viewer->DisableMainLogic(false);\r\n\t\t// unpause music and soundfx:\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tskate_mod->Pause( false );\r\n\t\tTmr::RecallTimerInfo( );\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid FrontEnd::AddEntriesToEventButtonMap(Script::CStruct *pParams)\r\n{\r\n\t#ifdef __PLAT_XBOX__\r\n\tconst char *p_array_name = \"xbox\";\r\n\t#else\r\n\t#ifdef __PLAT_NGC__\r\n\tconst char *p_array_name = \"gamecube\";\r\n\t#else\r\n\tconst char *p_array_name = \"ps2\";\r\n\t#endif\r\n\t#endif\r\n\t\r\n\t// This seems a very hacky way of doing things.\r\n\t// Black and white need to be in position 16 and 17, since they are button indices 16 and 17.\r\n\t#ifdef __PLAT_XBOX__\r\n\tconst char *p_button_names[] =\r\n\t{\r\n\t\t\"left_trigger_full\",\r\n\t\t\"right_trigger_full\",\r\n\t\t\"left_trigger_half\",\r\n\t\t\"right_trigger_half\",\r\n\t\t\"y\",\r\n\t\t\"b\",\r\n\t\t\"a\",\r\n\t\t\"x\",\r\n\t\t\"back\",\r\n\t\t\"left_stick_button\",\r\n\t\t\"right_stick_button\",\r\n\t\t\"null\",\r\n\t\t\"null\",\r\n\t\t\"null\",\r\n\t\t\"null\",\r\n\t\t\"null\",\r\n\t\t\"black\",\r\n\t\t\"white\"\r\n\t};\r\n\t#else\r\n\t#ifdef __PLAT_NGC__\r\n\tconst char *p_button_names[] =\r\n\t{\r\n\t\t\"left_trigger_full\",\r\n\t\t\"right_trigger_full\",\r\n\t\t\"left_trigger_half\",\r\n\t\t\"right_trigger_half\",\r\n\t\t\"y\",\r\n\t\t\"x\",\r\n\t\t\"a\",\r\n\t\t\"b\",\r\n\t\t\"null\",\r\n\t\t\"z_plus_left_trigger\",\r\n\t\t\"z_plus_right_trigger\",\r\n\t\t\"null\",\r\n\t\t\"null\",\r\n\t\t\"null\",\r\n\t\t\"null\",\r\n\t\t\"null\",\r\n\t\t\"null\",\r\n\t\t\"null\",\r\n\t\t\"z\"\r\n\t};\r\n\t#else\r\n\tconst char *p_button_names[] =\r\n\t{\r\n\t\t\"left_trigger2\",\r\n\t\t\"right_trigger2\",\r\n\t\t\"left_trigger1\",\r\n\t\t\"right_trigger1\",\r\n\t\t\"triangle\",\r\n\t\t\"circle\",\r\n\t\t\"x\",\r\n\t\t\"square\",\r\n\t\t\"select\",\r\n\t\t\"left_stick_button\",\r\n\t\t\"right_stick_button\"\r\n\t};\r\n\t#endif\r\n\t#endif\r\n\t\r\n\t// Cleaner way of allowing varying button names array per platform.\r\n\tint num_mapped_buttons = sizeof( p_button_names ) / sizeof( char* );\r\n\r\n\tuint32 null_crc = Script::GenerateCRC(\"null\");\r\n\t\r\n\t/*\r\n\t\tIndices:\r\n\t\t\r\n\t\ti: into script array\r\n\t\tj: into button name array\r\n\t\tx: into map array\r\n\t*/\r\n\t\r\n\tScript::CArray *p_map;\r\n\tif (!pParams->GetArray(p_array_name, &p_map))\r\n\t\treturn;\r\n\r\n\tfor (uint i = 0; i < p_map->GetSize(); i++)\r\n\t{\r\n\t\tScript::CArray *p_entry = p_map->GetArray(i);\r\n\r\n\t\tuint32 button_crc = p_entry->GetChecksum(0);\r\n\t\tuint32 event_crc = p_entry->GetChecksum(1);\r\n\r\n\t\tfor (uint j = 0; j < (uint) num_mapped_buttons; j++)\r\n\t\t{\r\n\t\t\tif (button_crc == Script::GenerateCRC(p_button_names[j]) || button_crc == null_crc)\r\n\t\t\t{\r\n\t\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\t\tbool removing_entries = (button_crc == null_crc || event_crc == null_crc);\r\n\t\t\t\t#endif\r\n\t\t\t\tint x = 0;\r\n\t\t\t\tfor (; x < MAX_BUTTON_EVENT_MAP_ENTRIES; x++)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (button_crc == null_crc && m_digital_button_event_map[x].mEventType == event_crc)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// in this case, I am removing existing entry (or entries)\r\n\t\t\t\t\t\tm_digital_button_event_map[x].mEventType = DEAD_ENTRY;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if (event_crc == null_crc && m_digital_button_event_map[x].mDigitalButtonIndex == j)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// in this case, I am removing existing entry (or entries)\r\n\t\t\t\t\t\tm_digital_button_event_map[x].mEventType = DEAD_ENTRY;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if (m_digital_button_event_map[x].mEventType == DEAD_ENTRY)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// in this case, I am adding a new entry, so need empty slot\r\n\t\t\t\t\t\tm_digital_button_event_map[x].mDigitalButtonIndex = j;\r\n\t\t\t\t\t\tm_digital_button_event_map[x].mEventType = event_crc;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tDbg_MsgAssert(x < MAX_BUTTON_EVENT_MAP_ENTRIES || removing_entries, (\"out of entries, increase size of MAX_BUTTON_EVENT_MAP_ENTRIES\"));\r\n\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t/*\r\n\t\tPaul:\r\n\t\r\n\t\t'Y' = PS2 'Triangle'. \r\n\t\t'X' = PS2 'Circle'.   \r\n\t\t'A' = PS2 'X'.        \r\n\t\t'B' = PS2 'Square'.   \r\n\t\t'Left Trigger pressed down > halfway' = PS2 'L1'. \r\n\t\t'Right Trigger pressed down > halfway' = PS2 'R1'.\r\n\t\t'Left Trigger' = PS2 'L2'.                        \r\n\t\t'Right Trigger' = PS2 'R2'.                       \r\n\t\t'Z' plus 'L' = PS2 'Left Stick Button'.  \r\n\t\t'Z' plus 'R' = PS2 'Right Stick Button'\r\n\t\tZ button without L & R is PS2 'Select'\r\n\t*/\r\n\r\n\t/*\r\n\t\tDave:\r\n\t\r\n\t\tXbox start = start\r\n\t\tXbox back = select\r\n\t\tThe 4 xbox color buttons map to the Ps2 buttons in the same location.\r\n\t\tBlack and white buttons aren't mapped at all.\r\n\t\tTriggers as per Ngc.\r\n\t\tLeft and right stick buttons map directly to Ps2 equivalents\r\n\t*/\r\n}\r\n\r\n\r\n\r\n\r\nvoid FrontEnd::s_input_logic_code ( const Inp::Handler < FrontEnd >& handler )\r\n{\t   \r\n\tDbg_AssertType ( &handler, Inp::Handler< FrontEnd > );\r\n    \r\n\tFrontEnd& mdl = handler.GetData();\r\n\r\n\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\tp_tracker->LogTick();\r\n\t\r\n\tfor (int count = 0;; count++)\r\n\t{\r\n\t\tuint32 event_type = 0; \r\n\t\t\r\n\t\tif (count == 0)\r\n\t\t{\r\n\t\t\tif (mdl.m_check_for_auto_input)\r\n\t\t\t{\r\n\t\t\t\tmdl.m_using_auto_input = (bool) Script::GetInteger(\"use_auto_menu_input\");\r\n\t\t\t\tif (mdl.m_using_auto_input)\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CScript *p_script = Script::SpawnScript(\"auto_menu_input\");\r\n\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\tp_script->SetCommentString(\"Spawned from FrontEnd::s_input_logic_code\");\r\n\t\t\t\t\t#endif\r\n\t\t\t\t\tmdl.m_auto_input_script_id = p_script->GetUniqueId();\r\n\t\t\t\t}\r\n\t\t\t\tmdl.m_check_for_auto_input = false;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tuint32 timed_event_type = mdl.grab_timed_event_type(handler.m_Input->m_Buttons, handler.m_Index);\r\n\t\t\tif (timed_event_type)\r\n\t\t\t\tevent_type = timed_event_type;\r\n\t\t}\r\n\t\t\r\n\t\tuint32 mapped_event_type = mdl.turn_mask_into_event_type(handler.m_Input->m_Makes, count, handler.m_Index,handler.m_Input->m_Buttons);\r\n\t\tif (mapped_event_type)\r\n\t\t\tevent_type = mapped_event_type;\r\n\t\t\r\n\t\tif (event_type && mdl.m_pad_info[handler.m_Index].mMode != INACTIVE && !mdl.m_temp_block_pad_input) \r\n\t\t{\r\n\t\t\tScript::CStruct event_data;\r\n\t\t\tint device_num = handler.m_Device->GetPort();\r\n\t\t\tevent_data.AddInteger(\"device_num\", device_num );\r\n\t\t\t// printf(\"device_num = %i\\n\", device_num);\r\n\r\n\t\t\tif (mdl.m_pad_info[handler.m_Index].mMode == ACTIVE)\r\n\t\t\t{\r\n\t\t\t\t// get the controller this came from\t\t\t\t\r\n\t\t\t\t// event_data.AddInteger(\"controller\", handler.m_Index);\r\n\t\t\t\tevent_data.AddInteger(\"controller\", 0);\r\n\t\t\t\t// event_data.AddInteger( \"controller\", Mdl::FrontEnd::Instance()->GetInputHandlerMapping( device_num ) );\r\n\t\t\t\t// printf( \"using controller %i\\n\", Mdl::FrontEnd::Instance()->GetInputHandlerMapping( device_num ) );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// printf(\"using 0\\n\");\r\n\t\t\t\tevent_data.AddInteger(\"controller\", 0);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t//if (handler.m_Index)\r\n\t\t\t// printf(\"firing pad event %s\\n\", Script::FindChecksumName(event_type));\r\n\t\r\n\t\t\tif (p_tracker->LaunchEvent(event_type, Obj::CEvent::vSYSTEM_EVENT, Obj::CEvent::vSYSTEM_EVENT, &event_data))\r\n\t\t\t{\r\n\t\t\t\t// will get here whenever menu systems responds to one of above occurences\r\n\t\r\n\t\t\t\t//handler.m_Input->MaskDigitalInput(Inp::Data::mD_ALL);\r\n\t\t\t\t//handler.m_Input->MaskAnalogInput(Inp::Data::mA_ALL);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (event_type == 0)\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid FrontEnd::s_logic_code ( const Tsk::Task< FrontEnd >& task )\r\n{\r\n\tDbg_AssertType ( &task, Tsk::Task< FrontEnd > );\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\r\n\tFrontEnd&\tmdl = task.GetData();\r\n\r\n\tmdl.update(mdl.m_paused);\r\n\t\r\n\t\r\n#\t\tifdef __USE_PROFILER__\r\n\t\tSys::CPUProfiler->PushContext( 0, 0, 128 ); \t// blue under green = screen element update\r\n#\t\tendif // __USE_PROFILER__\r\n\t\r\n\t\r\n\tFront::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();\r\n\tp_screen_elem_man->Update();\r\n\r\n\r\n\r\n#\t\tifdef __USE_PROFILER__\r\n\t\tSys::CPUProfiler->PopContext(  ); \t\r\n#\t\tendif // __USE_PROFILER__\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\t\t\r\n}\r\n\r\n\r\nvoid FrontEnd::s_handle_keyboard_code( const Tsk::Task< FrontEnd >& task )\r\n{\r\n\tint i, num_chars;\r\n\tchar makes[256];\r\n\tFrontEnd& mdl = task.GetData();\r\n\t\t\r\n\tnum_chars = SIO::KeyboardRead( makes );\r\n\r\n\tfor( i = 0; i < num_chars; i++ )\r\n\t{\r\n\t\tif((( makes[i] >= 32 ) && ( makes[i] <= 126 ) ) || ( makes[i] == SIO::vKB_ENTER ) || ( makes[i] == SIO::vKB_BACKSPACE ))\r\n\t\t{\r\n\t\t\tScript::CStruct* pParams;\r\n\t\t\t\r\n\t\t\tpParams = new Script::CStruct;\r\n\t\t\tif( makes[i] == SIO::vKB_ENTER )\r\n\t\t\t{\r\n\t\t\t\tpParams->AddChecksum( NONAME, Script::GenerateCRC( \"got_enter\" ));\r\n\t\t\t}\r\n\t\t\telse if( makes[i] == SIO::vKB_BACKSPACE )\r\n\t\t\t{\r\n\t\t\t\tpParams->AddChecksum( NONAME, Script::GenerateCRC( \"got_backspace\" ));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tchar text_string[2];\r\n\r\n\t\t\t\ttext_string[0] = makes[i];\r\n\t\t\t\ttext_string[1] = '\\0';\r\n\t\t\t\tpParams->AddString( \"text\", text_string );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tpParams->AddInteger( \"max_length\", mdl.m_max_kb_string_length );\r\n\t\t\tScript::RunScript( \"handle_keyboard_input\", pParams );\r\n\t\t\tdelete pParams;\r\n\t\t}\r\n\t}\r\n\r\n\t// Don't let anyone else handle the keypresses\r\n\tSIO::KeyboardClear();\r\n}\r\n\r\n\r\n/*****************************************************************\r\n*\tThis friendly little function gets called every frame. 'game_is_paused'\r\n*\tis true if the game is paused, or if the player is in the front end.\r\n*\r\n*\tI will probably move this function to MainMod.cpp or some other more\r\n*\tlogical place later on.                                                                \r\n*                                                               \r\n******************************************************************/\r\nvoid FrontEnd::update(bool game_is_paused)\r\n{\t\r\n\t/*\r\n\t\t===========================================\r\n\t\tNon-front end Stuff\r\n\t\t===========================================\r\n\t*/\r\n\r\n\t// Turn Keybard handler on and off\r\n\r\n\t#ifdef\t__PLAT_NGPS__\t\r\n\tif (\tgame_is_paused\t\t\t\t\t\t\t\t\t\t// paused\r\n\t\t|| \tGameNet::Manager::Instance()->InNetGame()\t\t\t// or a network game\r\n\t\t|| Mdl::Skate::Instance()->m_requested_level == 0x9f2bafb7        \t// (0x9f2bafb7 === Load_SkateShop) In skateshop\r\n\t\t|| m_handle_keyboard_task->InList() \t\t\t\t\t// if the keyboard is on-screen\r\n\t\t)\r\n\t{\r\n\t\tSIO::SetKeyboardActive(true);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSIO::SetKeyboardActive(false);\r\n\t}\r\n\t#endif\r\n\t\r\n\r\n\t\r\n\t// Call these functions every frame:\r\n\tPcm::Update( );\t\r\n\r\n\tSfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();\r\n\tsfx_manager->Update();\r\n\r\n\tif ( !game_is_paused )\r\n\t{\r\n\t\t// Mick: using the default heap here....\r\n\t\t// as spawned scripts can fill up the front end heap in an unpredictable manner\r\n\t\t// like with the LA earthquake\t\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\r\n\r\n#\t\tifdef __USE_PROFILER__\r\n\t\tSys::CPUProfiler->PushContext( 128, 0, 0 ); \t// red under green = Positional Sounds\r\n#\t\tendif // __USE_PROFILER__\r\n\r\n\t\tsfx_manager->UpdatePositionalSounds( );\r\n\r\n#\t\tifdef __USE_PROFILER__\r\n\t\tSys::CPUProfiler->PopContext( ); \t// \r\n#\t\tendif // __USE_PROFILER__\r\n\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\r\n#\tifdef __USE_PROFILER__\r\n\tSys::CPUProfiler->PushContext( 128, 128, 128 ); \t// gray under green = spawned scripts\r\n#\tendif // __USE_PROFILER__\r\n\r\n\t// And call these functions every game frame:\r\n\tScript::UpdateSpawnedScripts();\r\n\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tskate_mod->UpdateGameFlow();\r\n\r\n\t// mick: run the special script I use for command line scripting\t\r\n\tif (run_runmenow)\r\n\t{\r\n\t\trun_runmenow = false;\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tObj::CSkater *pSkater = skate_mod->GetLocalSkater();\t\t\t\t\t\t   \r\n\t\tScript::RunScript(\"RunMeNow\",NULL,pSkater);\r\n\t}\r\n\r\n\r\n#\tifdef __USE_PROFILER__\r\n\tSys::CPUProfiler->PopContext( ); \t// \r\n#\tendif // __USE_PROFILER__\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n\r\n\r\n\r\nuint32 FrontEnd::grab_timed_event_type(uint mask, int index)\r\n{\r\n    char makes[256];\r\n\tint i, num_chars;\r\n\tuint32 event_type = 0;\r\n\t\t\r\n\t/*\r\n\t\tWe check for these types of pad presses first, because of the timing element\r\n\t*/\r\n\tif (mask & Inp::Data::mD_LEFT)\r\n\t\tevent_type = Obj::CEvent::TYPE_PAD_LEFT;\r\n\telse if (mask & Inp::Data::mD_RIGHT)\r\n\t\tevent_type = Obj::CEvent::TYPE_PAD_RIGHT;\r\n\telse if (mask & Inp::Data::mD_UP)\r\n\t\tevent_type = Obj::CEvent::TYPE_PAD_UP;\r\n\telse if (mask & Inp::Data::mD_DOWN)\r\n\t\tevent_type = Obj::CEvent::TYPE_PAD_DOWN;\t\r\n\t\r\n\t// Let the pad take precedence over the keyboard\r\n\tif(( index == 0 ) && ( event_type == 0 ))\r\n\t{\r\n\t\t// First check for keyboard events, if there were any\r\n\t\tnum_chars = SIO::KeyboardRead( makes );\r\n\t\r\n\t\tif( num_chars > 0 )\r\n\t\t{\r\n\t\t\tfor( i = 0; i < num_chars; i++ )\r\n\t\t\t{\r\n\t\t\t\tif( makes[i] == SIO::vKB_LEFT )\r\n\t\t\t\t{\r\n\t\t\t\t\tevent_type = Obj::CEvent::TYPE_PAD_LEFT;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\telse if( makes[i] == SIO::vKB_RIGHT )\r\n\t\t\t\t{\r\n\t\t\t\t\tevent_type = Obj::CEvent::TYPE_PAD_RIGHT;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\telse if( makes[i] == SIO::vKB_UP )\r\n\t\t\t\t{\r\n\t\t\t\t\tevent_type = Obj::CEvent::TYPE_PAD_UP;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\telse if( makes[i] == SIO::vKB_DOWN )\r\n\t\t\t\t{\r\n\t\t\t\t\tevent_type = Obj::CEvent::TYPE_PAD_DOWN;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (m_pad_info[index].mState == NOT_DOWN)\r\n\t{\r\n\t\tif (event_type)\r\n\t\t{\r\n\t\t\t// The directional pad was freshly pressed, so we will send an event.\r\n\t\t\t// Begin next countdown until the pad input \"counts\" again.\r\n\t\t\tm_pad_info[index].mAutorepeatCountdown = m_auto_repeat_time[0];\r\n\t\t\tm_pad_info[index].mState = SLOW_REPEAT;\r\n\t\t}\r\n\t}\r\n\telse if (event_type)\r\n\t{ \t\t\r\n\t\t// The directional pad was held down last frame\t(and this one)\r\n\t\t\r\n\t\t// update countdown\ttime\r\n\t\tTmr::Time frame_time = (Tmr::Time) (Tmr::FrameLength() * Tmr::vRESOLUTION);\r\n\t\tif (frame_time < m_pad_info[index].mAutorepeatCountdown)\r\n\t\t\tm_pad_info[index].mAutorepeatCountdown -= frame_time;\r\n\t\telse\r\n\t\t\tm_pad_info[index].mAutorepeatCountdown = 0;\r\n\r\n\t\tif (m_pad_info[index].mAutorepeatCountdown == 0)\r\n\t\t{\r\n\t\t\t// countdown finished, time to fire event, reset countdown time\r\n\t\t\tif (m_pad_info[index].mState == SLOW_REPEAT)\r\n\t\t\t\tm_pad_info[index].mState = FAST_REPEAT;\r\n\t\t\tm_pad_info[index].mAutorepeatCountdown = m_auto_repeat_time[1];\r\n\t\t}\r\n\t\telse\r\n\t\t\t// don't fire pad event, countdown hasn't finished\r\n\t\t\tevent_type = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_pad_info[index].mState = NOT_DOWN;\r\n\t}\t\r\n\r\n\tif (m_using_auto_input && index == 0)\r\n\t{\r\n\t\tevent_type = 0;\r\n\r\n\t\tScript::CScript *p_script = Script::GetScriptWithUniqueId(m_auto_input_script_id);\r\n\t\tif (p_script)\r\n\t\t{\r\n\t\t\tScript::UnpauseSpawnedScript(p_script);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_using_auto_input = false;\r\n\t\t}\t\t\r\n\t}\r\n\t\r\n\treturn event_type;\r\n}\r\n\r\n\r\n\r\n\r\nuint32 FrontEnd::turn_mask_into_event_type(uint mask, int count, int index, uint buttons)\r\n{\r\n    for (int i = 0; i < MAX_BUTTON_EVENT_MAP_ENTRIES; i++)\r\n\t{\r\n\t\tif ((mask & (1<<m_digital_button_event_map[i].mDigitalButtonIndex)) && \r\n\t\t\tm_digital_button_event_map[i].mEventType != DEAD_ENTRY)\r\n\t\t{\r\n\t\t\tcount--;\r\n\t\t\tif (count < 0)\r\n\t\t\t\treturn m_digital_button_event_map[i].mEventType;\r\n\t\t}\r\n\t}\r\n\t\r\n\r\n\t// Mick:  Ignore start button as an event if select is pressed and select_shift is true\t\r\n\tif( ! (buttons & Inp::Data::mD_SELECT) || ! Script::GetInt(CRCD(0xf3e055e1,\"select_shift\")))\r\n\t{\r\n\t\tif( (mask & Inp::Data::mD_START) && count == 0 )\r\n\t\t\treturn Obj::CEvent::TYPE_PAD_START;\r\n\t}\r\n\t\r\n\tif( index == 0 )\r\n\t{\r\n\t\tchar makes[256];\r\n\t\tint i, num_chars;\r\n\t\tuint32 event_type = 0;\r\n\r\n\t\t// First check for keyboard events, if there were any\r\n\t\tnum_chars = SIO::KeyboardRead( makes );\r\n\r\n\t\tif( num_chars > 0 )\r\n\t\t{\r\n\t\t\tfor( i = 0; i < num_chars; i++ )\r\n\t\t\t{   \r\n\t\t\t\t// If the keyboard menu is showing, don't treat space and enter as X\r\n\t\t\t\tif( makes[i] == SIO::vKB_ESCAPE )\r\n\t\t\t\t{\r\n\t\t\t\t\t\r\n\t\t\t\t\tScript::CStruct* pParams;\r\n\r\n\t\t\t\t\tpParams= new Script::CStruct;\r\n\t\t\t\t\tpParams->AddChecksum( Script::GenerateCRC( \"id\" ), Script::GenerateCRC( \"current_menu_anchor\" ));\r\n\t\t\t\t\tif( Obj::ScriptObjectExists( pParams, NULL ) == false )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tevent_type = Obj::CEvent::TYPE_PAD_START;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tevent_type = Obj::CEvent::TYPE_PAD_BACK;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tSIO::KeyboardClear();\r\n\t\t\t\t\tdelete pParams;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\telse if(( makes[i] == SIO::vKB_ENTER ) || ( makes[i] == 32 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct* pParams;\r\n\t\t\t\t\tbool menu_up;\r\n\r\n\t\t\t\t\tmenu_up = false;\r\n\t\t\t\t\tpParams = new Script::CStruct;\r\n\t\t\t\t\tpParams->AddChecksum( Script::GenerateCRC( \"id\" ), Script::GenerateCRC( \"keyboard_anchor\" ));\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Enter and space act as \"choose\" only if you're not currently using the on-screen keyboard\r\n\t\t\t\t\tif( Obj::ScriptObjectExists( pParams, NULL ) == false )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpParams->Clear();\r\n    \t\t\t\t\tpParams->AddChecksum( Script::GenerateCRC( \"id\" ), Script::GenerateCRC( \"actions_menu\" ));\r\n                        \r\n                        // only allow enter in actions menu\r\n                        if( (Obj::ScriptObjectExists( pParams, NULL ) == true) && ( makes[i] == 32 ) )\r\n    \t\t\t\t\t{\r\n                            return 0;\r\n                        }\r\n                        else\r\n                        {\r\n                            pParams->Clear();\r\n    \t\t\t\t\t\tpParams->AddChecksum( Script::GenerateCRC( \"id\" ), Script::GenerateCRC( \"current_menu_anchor\" ));\r\n    \t\t\t\t\t\tif( Obj::ScriptObjectExists( pParams, NULL ))\r\n    \t\t\t\t\t\t{\r\n    \t\t\t\t\t\t\tmenu_up = true;\r\n    \t\t\t\t\t\t}\r\n    \t\t\t\t\t\telse\r\n    \t\t\t\t\t\t{\r\n    \t\t\t\t\t\t\tpParams->Clear();\r\n    \t\t\t\t\t\t\tpParams->AddChecksum( Script::GenerateCRC( \"id\" ), Script::GenerateCRC( \"dialog_box_anchor\" ));\r\n    \t\t\t\t\t\t\tif( Obj::ScriptObjectExists( pParams, NULL ))\r\n    \t\t\t\t\t\t\t{\r\n    \t\t\t\t\t\t\t\tmenu_up = true;\r\n    \t\t\t\t\t\t\t}\r\n    \t\t\t\t\t\t}\r\n    \r\n    \t\t\t\t\t\tif( menu_up )\r\n    \t\t\t\t\t\t{\r\n    \t\t\t\t\t\t\tevent_type = Obj::CEvent::TYPE_PAD_CHOOSE;\r\n    \t\t\t\t\t\t\tSIO::KeyboardClear();\r\n    \t\t\t\t\t\t}\r\n                        }\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdelete pParams;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn event_type;\r\n\t}\r\n\t\r\n    return 0;\r\n}\r\n\r\n\r\nvoid FrontEnd::UpdateInputHandlerMappings()\r\n{\r\n\tSpt::SingletonPtr< Inp::Manager > inp_man;\r\n\t\r\n\tfor ( int i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n\t\tprintf(\"m_device_server_map[%i] = %i\\n\", i, m_device_server_map[i]);\r\n\t\tInp::Handler< FrontEnd >* p_handler = GetInputHandler( i );\r\n\t\tif ( p_handler )\r\n\t\t{\r\n\t\t\tprintf(\"got a handler\\n\");\r\n\t\t\tinp_man->ReassignHandler( *p_handler, m_device_server_map[i] );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nint FrontEnd::GetInputHandlerMapping( int device_num )\r\n{\r\n\treturn m_device_server_map[device_num];\r\n}\r\n\r\n\r\nbool ScriptLaunchMenuScreen(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 which_menu;\r\n\tif (!pParams->GetChecksum(\"screen\", &which_menu))\r\n\t\tDbg_MsgAssert(0, (\"need screen=... with LaunchMenuScreen command\"));\r\n\r\n\t// XXX\r\n\tRyan(\"requesting game menu from LaunchMenuScreen\\n\");\r\n//\tFrontEnd* frontend = FrontEnd::Instance();\r\n//\tfrontend->RequestMenuScreen(which_menu);\r\n\r\n\tprintf (\"STUBBED: LaunchMenuScreen\\n\");\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptSetMenuAutoRepeatTimes(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tScript::CPair times;\r\n\tpParams->GetPair(NONAME, &times, Script::ASSERT);\r\n\r\n\tFrontEnd* p_front_end = FrontEnd::Instance();\r\n\tp_front_end->SetAutoRepeatTimes((Tmr::Time) (times.mX * (float) Tmr::vRESOLUTION),\r\n\t\t\t\t\t\t\t\t\t(Tmr::Time) (times.mY * (float) Tmr::vRESOLUTION));\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptSetMenuPadMappings(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tScript::CArray *p_map_array;\r\n\tpParams->GetArray(NONAME, &p_map_array, true);\r\n\r\n\tFrontEnd* p_front_end = FrontEnd::Instance();\r\n\tfor (int i = 0; i < 2; i++)\r\n\t{\r\n\t\tuint32 flag = p_map_array->GetChecksum(i);\r\n\t\tFrontEnd::EControllerMode mode = FrontEnd::INACTIVE;\r\n\t\tif (flag == Script::GenerateCRC(\"inactive\"))\r\n\t\t\tmode = FrontEnd::INACTIVE;\r\n\t\telse if (flag == Script::GenerateCRC(\"active\"))\r\n\t\t\tmode = FrontEnd::ACTIVE;\r\n\t\telse if (flag == Script::GenerateCRC(\"use_as_first\"))\r\n\t\t\tmode = FrontEnd::MAP_TO_FIRST;\r\n\t\telse\r\n\t\t\tDbg_MsgAssert(0, (\"unknown controller mode\"));\r\n\r\n\t\tp_front_end->SetControllerMode(i, mode);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptSetButtonEventMappings(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tFrontEnd* p_front_end = FrontEnd::Instance();\r\n\tp_front_end->AddEntriesToEventButtonMap(pParams);\r\n\t\r\n\tif (pParams->ContainsFlag(\"block_menu_input\"))\r\n\t\tp_front_end->SetControllerTempBlock(true);\r\n\telse if (pParams->ContainsFlag(\"unblock_menu_input\"))\r\n\t\tp_front_end->SetControllerTempBlock(false);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n// @script bool | SetAnalogStickActiveForMenus | Turn on/off analog simulation of digital buttons,\r\n// so you can turn them off during certain menus that use analog for other things. \r\n// @uparmopt 1 | on or off, 1 or 0\r\nbool ScriptSetAnalogStickActiveForMenus(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint\tactive = 1;\r\n\tpParams->GetInteger(NONAME,&active,false);\r\n\tFrontEnd::Instance()->SetAnalogStickActiveForMenus((bool)active);\r\n\treturn true;\r\n}\r\n\r\n} // namespace FrontEnd\r\n"
  },
  {
    "path": "Code/Sk/Modules/FrontEnd/FrontEnd.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t\t\t\t\t\t\t\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t09/12/2000\t-\trjm\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __FRONTEND_H\r\n#define __FRONTEND_H\r\n\r\n#include <core/support.h>\r\n#include <core/task.h>\r\n#include <core/string/cstring.h>\r\n\r\n#include <gel/module.h>\r\n#include <gel/inpman.h>\r\n\r\n#include <gfx/camera.h>\r\n#include <gfx/image/imagebasic.h>\r\n\r\n#include <sys/timer.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n}\r\n\r\nnamespace Mdl\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass FrontEnd;\r\n\r\nclass FrontEnd : public  Module\r\n{\r\n\t\r\n\tDeclareSingletonClass( FrontEnd );\r\n\r\npublic:\r\n\tenum\r\n\t{ \r\n\t\tvMAIN_MENU \t\t\t= 0x6249f70e, // \"main_menu\"\r\n\t\tvGAME_MENU\t\t\t= 0x69efa940, // \"game_menu\"\r\n\t\tvPARKED_MENU\t\t= 0xab42b78b, // \"parked_menu\"\r\n\t};\r\n\t\r\n\tenum EControllerMode\r\n\t{\r\n\t\tINACTIVE,\r\n\t\tACTIVE,\r\n\t\tMAP_TO_FIRST,\r\n\t};\r\n\r\n\t\r\n\tvoid \t\t\t\t\t\t\tPauseGame(bool pause);\r\n\tbool \t\t\t\t\t\t\tGamePaused() {return m_paused;}\r\n\t// This function is used to temporarily switch the paused task list on and off. You should reset it to its previous\r\n\t// state afterwards. Use SetActive() whenever you can.\r\n\tvoid \t\t\t\t\t\t\tSetPausedTasks(bool is_active);\r\n\r\n\tbool\t\t\t\t\t\t\tPadsPluggedIn();\r\n\tvoid \t\t\t\t\t\t\tUseFirstPadForPausedMenu() {m_use_second_pad_for_paused_menu=false; m_using_one_pad_for_paused_menu=true;}\r\n\tvoid \t\t\t\t\t\t\tUseSecondPadForPausedMenu() {m_use_second_pad_for_paused_menu=true; m_using_one_pad_for_paused_menu=true;}\r\n\r\n\tvoid \t\t\t\t\t\t\tSetAutoRepeatTimes(Tmr::Time kickoff, Tmr::Time repeat) {m_auto_repeat_time[0] = kickoff; m_auto_repeat_time[1] = repeat;}\r\n\tvoid\t\t\t\t\t\t\tGetAutoRepeatTimes(Tmr::Time &kickoff, Tmr::Time &repeat) {kickoff = m_auto_repeat_time[0]; repeat = m_auto_repeat_time[1];}\r\n\tvoid \t\t\t\t\t\t\tSetControllerMode(int controllerNum, EControllerMode mode) {m_pad_info[controllerNum].mMode = mode;}\r\n\tvoid \t\t\t\t\t\t\tSetControllerTempBlock(bool tempBlock) {m_temp_block_pad_input = tempBlock;}\r\n\r\n\tvoid\t\t\t\t\t\t\tAddEntriesToEventButtonMap(Script::CStruct *pParams);\r\n\r\n\tvoid \t\t\t\t\t\t\tAddKeyboardHandler( int max_string_length );\r\n\tvoid \t\t\t\t\t\t\tRemoveKeyboardHandler( void );\r\n\tvoid \t\t\t\t\t\t\tSetAnalogStickActiveForMenus( bool isActive );\r\n\r\nprivate:\r\n\r\n\tFrontEnd( void );\r\n\tvirtual\t\t\t\t\t\t\t~FrontEnd( void );\r\n\r\n\tvoid \t\t\t\t\t\t\tupdate(bool game_is_paused);\r\n\tuint32\t\t\t\t\t\t\tgrab_timed_event_type(uint mask, int index);\r\n\tuint32\t\t\t\t\t\t\tturn_mask_into_event_type(uint mask, int count, int index, uint buttons);\r\n\t\r\n\tenum Commands \r\n\t{\r\n        mSELECTUP   \t\t\t= nBit(0),\r\n        mSELECTDOWN \t\t\t= nBit(1),\r\n        mXDOWN \t\t\t\t\t= nBit(2),\r\n\t\tmTRIANGLEDOWN\t\t\t= nBit(3),\r\n\t\tmSTARTDOWN\t\t\t\t= nBit(4),\r\n\t\tmTOGGLE\t\t\t\t\t= nBit(5),\r\n\t\tmSELECTLEFT\t\t\t\t= nBit(6),\r\n\t\tmSELECTRIGHT\t\t\t= nBit(7),\r\n\t};\r\n\r\n\tstatic\tTsk::Task< FrontEnd >::Code\t\ts_logic_code;\r\n\tstatic\tTsk::Task< FrontEnd >::Code\t\ts_handle_keyboard_code;\r\n\tstatic\tTsk::Task< FrontEnd >::Code\t\ts_display_code;\r\n\tstatic\tInp::Handler< FrontEnd >::Code  s_input_logic_code;\r\n\r\n\tvoid\t\t\t\t\t\t\tv_start_cb( void );\r\n\tvoid\t\t\t\t\t\t\tv_stop_cb( void );\r\n    \t\r\n\tTsk::Task< FrontEnd >*\t\t\tm_logic_task;\t\r\n\tTsk::Task< FrontEnd >*\t\t\tm_handle_keyboard_task;\r\n\tbool\t\t\t\t\t\t\tm_use_second_pad_for_paused_menu;\r\n\tbool\t\t\t\t\t\t\tm_using_one_pad_for_paused_menu;\r\n\t\r\n   \tInp::Handler< FrontEnd >*\t\tmp_input_handlers[SIO::vMAX_DEVICES];\r\npublic:\r\n\t// Used by ScriptAnyControllerPressed in cfuncs.cpp\r\n\tInp::Handler< FrontEnd >*\t\tGetInputHandler( int index ) { return mp_input_handlers[index]; }\r\n\tvoid\t\t\t\t\t\t\tUpdateInputHandlerMappings();\r\n\tint\t\t\t\t\t\t\t\tGetInputHandlerMapping( int device_num );\r\n\r\n\tint\t\t\t\t\t\t\t\tm_device_server_map[SIO::vMAX_DEVICES];\r\n\r\nprivate:\r\n\r\n\tbool\t\t\t\t\t\t\tm_paused;\r\n\tbool\t\t\t\t\t\t\tm_allowDeactivate;\r\n\r\n\t// first is \"kickoff\" time, second is \"repeat\" time\r\n\tTmr::Time\t\t\t\t\t\tm_auto_repeat_time[2];\r\n\tint\t\t\t\t\t\t\t\tm_max_kb_string_length;\r\n\r\n\tenum EPadState\r\n\t{\r\n\t\tNOT_DOWN,\r\n\t\tSLOW_REPEAT,\r\n\t\tFAST_REPEAT,\r\n\t};\r\n\t\r\n\tstruct PadInfo\r\n\t{\r\n\t\tEPadState\t\t\t\t\tmState;\r\n\t\tTmr::Time\t\t\t\t\tmAutorepeatCountdown;\r\n\t\tEControllerMode\t\t\t\tmMode;\r\n\t};\r\n\t\r\n\tPadInfo\t\t\t\t\t\t\tm_pad_info[SIO::vMAX_DEVICES];\r\n\tbool\t\t\t\t\t\t\tm_temp_block_pad_input;\r\n\r\n\tenum \r\n\t{\r\n\t\tMAX_BUTTON_EVENT_MAP_ENTRIES\t= 32,\r\n\t\t// use in mEventType\r\n\t\tDEAD_ENTRY\t\t\t\t\t\t= 0,\r\n\t};\r\n\t\r\n\tstruct EventMapEntry\r\n\t{\r\n\t\tuint\t\t\t\t\t\tmDigitalButtonIndex;\r\n\t\tuint32\t\t\t\t\t\tmEventType;\r\n\t};\r\n\t\r\n\tEventMapEntry\t\t\t\t\tm_digital_button_event_map[32];\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_check_for_auto_input;\r\n\tbool\t\t\t\t\t\t\tm_using_auto_input;\r\n\tuint32\t\t\t\t\t\t\tm_auto_input_script_id;\r\n};\r\n\r\nbool ScriptLaunchMenuScreen(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetMenuAutoRepeatTimes(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetMenuPadMappings(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetButtonEventMappings(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetAnalogStickActiveForMenus(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\n} // namespace FrontEnd\r\n\r\n#endif\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/BettingGuy.cpp",
    "content": "// BettingGuy.cpp\r\n\r\n#include <sk/modules/skate/bettingguy.h>\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/modules/skate/skate.h>\r\n\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/restart.h>\r\n#include <sk/objects/movingobject.h>\r\n#include <sk/objects/ped.h>\r\n\r\n#include <gel/object.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <sk/scripting/nodearray.h>\r\n\r\n#include <core/math/math.h>\r\n\r\nnamespace Game\r\n{\r\n\r\nconst int vMINSQUAREDIST\t\t= 1000001;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBettingGuy::CBettingGuy( Script::CStruct* pParams ) \r\n\t: CGoal( pParams )\r\n{\r\n\tprintf(\"creating a CBettingGuy\\n\");\r\n\tReset();\r\n\tm_shouldMove = true;\r\n\tm_currentMinigame = 0;\r\n\tm_straightWins = 0;\r\n\tm_straightLosses = 0;\r\n\tm_currentDifficulty = 1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBettingGuy::~CBettingGuy()\r\n{\r\n\t// nothing yet\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBettingGuy::Activate()\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tCGoal* pGoal = pGoalManager->GetGoal( m_currentMinigame );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tScript::CStruct* pGoalParams = pGoal->GetParams();\r\n\r\n\t// get the bet amount\r\n\tint bet_amount;\r\n\tif ( pGoalParams->GetInteger( \"bet_amount\", &bet_amount, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tm_betAmount = bet_amount;\r\n\t}\r\n\r\n\tSetActive();\r\n\tprintf(\"activated!\\n\");\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBettingGuy::SetActive()\r\n{\r\n\t// necessary?\r\n\tm_active = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBettingGuy::BetIsActive( uint32 betId )\r\n{\r\n\t// printf(\"betid: %x, current: %x\\n\", betId, m_currentMinigame );\r\n\treturn ( betId == m_currentMinigame && IsActive() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBettingGuy::IsActive()\r\n{\r\n\treturn ( m_hasOffered && !m_shouldMove );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBettingGuy::Update()\r\n{\r\n\t// do we need to pick a new minigame?\r\n\tif ( m_shouldMove )\r\n\t{\r\n\t\t// printf(\"I need to move\\n\");\r\n\t\tMoveToNewNode();\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBettingGuy::IsExpired()\r\n{\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBettingGuy::Deactivate( bool force, bool affect_tree )\r\n{\r\n\t// no more minigame associated with this\r\n\tReset();\r\n\tm_straightWins = 0;\r\n\tm_straightLosses = 0;\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// win function that gets called from a trickscript\r\n// checks that the calling minigame is the current minigame\r\nbool CBettingGuy::Win( uint32 goalId )\r\n{\r\n\tif ( IsActive() && m_currentMinigame == goalId )\r\n\t{\r\n\t\t// this is the right minigame!\r\n\t\treturn Win();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n// win func that gets called automatically by update endbetattempt func\r\nbool CBettingGuy::Win()\r\n{\t\r\n\tprintf(\"CBettingGuy::Win\\n\");\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->AddCash( m_betAmount );\r\n\tReset();\r\n\r\n\tRunCallbackScript( vSUCCESS );\r\n\tm_numBetsWon++;\r\n\tm_straightWins++;\r\n\tif ( m_straightWins > 3 && m_currentDifficulty < 3 )\r\n\t{\r\n\t\tm_currentDifficulty++;\r\n\t\tm_straightWins = 0;\r\n\t}\r\n\r\n\tm_straightLosses = 0;\r\n\tm_shouldMove = true;\r\n\r\n\tSetInactive();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBettingGuy::Lose()\r\n{\r\n\tprintf(\"CbettingGuy::Lose\\n\");\r\n\tRunCallbackScript( vFAIL );\r\n\tReset();\r\n\tm_straightLosses++;\r\n\tif ( m_straightLosses > 3 && m_currentDifficulty > 1 )\r\n\t{\r\n\t\tm_currentDifficulty--;\r\n\t\tm_straightLosses = 0;\r\n\t}\r\n\r\n\tm_straightWins = 0;\r\n\tm_shouldMove = true;\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBettingGuy::Reset()\r\n{\r\n\tm_shouldMove = false;\r\n\t// m_currentMinigame = 0;\r\n\tm_numTries = 0;\r\n\t// m_currentDifficulty = 1;\r\n\tm_hasOffered = false;\r\n\tm_inAttempt = false;\r\n\tm_currentChallenge = 0;\r\n\tm_betAmount = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBettingGuy::MoveToNewNode( bool force )\r\n{\r\n\tCGoalManager* pGoalManager = Game::GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tuint32 minigameId = pGoalManager->GetRandomBettingMinigame();\r\n\tif ( minigameId == 0 || minigameId == m_currentMinigame )\r\n\t\treturn false;\t\r\n\t\t\t\r\n\tuint32 node_checksum;\r\n\tScript::CStruct* p_minigame_params = pGoalManager->GetGoal( minigameId )->GetParams();\r\n\tDbg_Assert( p_minigame_params );\r\n\tp_minigame_params->GetChecksum( \"betting_guy_node\", &node_checksum, Script::ASSERT );\r\n\r\n\tif ( force )\r\n\t{\r\n\t\t// move him!\r\n\t\t// printf(\"moving betting guy\\n\");\r\n\r\n\t\t// record his suspend state and turn off suspension\r\n\t\tReset();\r\n\t\tm_currentMinigame = minigameId;\r\n\t\tSetupParams();\r\n\r\n\t\tuint32 betting_guy_id;\r\n\t\tmp_params->GetChecksum( \"betting_guy_id\", &betting_guy_id, Script::ASSERT );\r\n\t\t\r\n//\t\tObj::CMovingObject* p_bet_guy = (Obj::CMovingObject*)(Obj::CMovingObject::m_hash_table.GetItem( betting_guy_id ));\r\n\t\tObj::CMovingObject* p_bet_guy = (Obj::CMovingObject*)(Obj::CCompositeObjectManager::Instance()->GetObjectByID( betting_guy_id ));\r\n\t\t\r\n\t\tDbg_Assert( p_bet_guy );\r\n\r\n// Mick:  removed this, as suspension handled differently under new components system\r\n//\t\tbool suspend_state = p_bet_guy->m_never_suspend;\r\n//\t\tp_bet_guy->m_never_suspend = true;\r\n\r\n\t\tScript::CStruct* p_temp_params = new Script::CStruct();\r\n\t\tp_temp_params->AddChecksum( \"goal_id\", GetGoalId() );\r\n\t\tp_temp_params->AddChecksum( \"new_node\", node_checksum );\r\n\t\tScript::RunScript( \"betting_guy_move_to_node\", p_temp_params );\r\n\t\tdelete p_temp_params;\r\n\r\n\t\t// make sure he's updated and restore his suspension state\r\n\t\tp_bet_guy->Update();\r\n\t\t\r\n\t\t\r\n//\t\tp_bet_guy->m_never_suspend = suspend_state;\r\n\t\r\n\t\tmp_params->AddChecksum( \"current_minigame\", minigameId );\r\n\r\n\t\tm_currentNode = node_checksum;\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// printf(\"got a minigameId of %x\\n\", minigameId);\r\n\t\r\n\t// get the local skater's position\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = skate_mod->GetLocalSkater();\r\n\tDbg_Assert( pSkater );\r\n\tMth::Vector skater_pos = pSkater->GetPos();\r\n\t\r\n\t// see if the skater is too close to the betting guy\r\n\tMth::Vector current_pos;\r\n\tif ( m_currentNode )\r\n\t{\r\n\t\tint current_node = SkateScript::FindNamedNode( m_currentNode );\r\n\t\tSkateScript::GetPosition( current_node, &current_pos );\r\n\t\r\n\t\tfloat d = ( skater_pos - current_pos ).LengthSqr();\r\n\t\t// printf(\"square distance from the skater to the betting guy: %f\\n\", d);\r\n\t\tif ( d < vMINSQUAREDIST )\r\n\t\t{\r\n\t\t\t// printf(\"the skater is too close to the betting guy\\n\");\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// try out the destination node\t\r\n\t// get the node's position\r\n\tint node = SkateScript::FindNamedNode( node_checksum );\r\n\tMth::Vector node_pos;\r\n\tSkateScript::GetPosition(node, &node_pos);\r\n\t\r\n\t// get the square of the distance between them\r\n\tfloat distSqr = ( skater_pos - node_pos ).LengthSqr();\r\n\t\r\n\t// make sure it isn't too close\r\n\t// printf(\"sqaure distance from skater to next node: %f\\n\", distSqr);\r\n\tif ( distSqr < vMINSQUAREDIST )\r\n\t{\r\n\t\t// printf(\"the skater is too close to the betting guy's destination node\\n\");\r\n\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\t\t\t\r\n\t\t// move him!\r\n\t\t// printf(\"moving betting guy\\n\");\r\n\t\tReset();\r\n\t\tm_currentMinigame = minigameId;\r\n\t\tSetupParams();\r\n\r\n\t\tScript::CStruct* p_temp_params = new Script::CStruct();\r\n\t\tp_temp_params->AddChecksum( \"goal_id\", GetGoalId() );\r\n\t\tp_temp_params->AddChecksum( \"new_node\", node_checksum );\r\n\t\tScript::RunScript( \"betting_guy_move_to_node\", p_temp_params );\r\n\t\tdelete p_temp_params;\r\n\t\r\n\t\tmp_params->AddChecksum( \"current_minigame\", minigameId );\r\n\r\n\t\tm_currentNode = node_checksum;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBettingGuy::StartBetAttempt( uint32 goalId )\r\n{\r\n\t// this acts like a secondary activate\r\n\tif ( IsActive() && m_currentMinigame == goalId && !m_inAttempt && !m_shouldMove )\r\n\t{\r\n\t\tprintf(\"starting bet attempt\\n\");\r\n\t\tm_inAttempt = true;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CBettingGuy::EndBetAttempt( uint32 goalId )\r\n{\r\n\t// this acts like a secondary deactivate\r\n\tif ( IsActive() && m_currentMinigame == goalId && m_inAttempt && !m_shouldMove )\r\n\t{\r\n\t\t//printf(\"CBettingGuy::EndBetAttempt\\n\");\r\n\t\t// printf(\"step 2\\n\");\r\n\t\tm_inAttempt = false;\r\n\t\t\r\n\t\tScript::CStruct* pBetParams = GetBetParams();\r\n\t\t\r\n\t\t// check that they haven't exceeded the number of tries\r\n\t\tint max_attempts;\r\n\t\tpBetParams->GetInteger( \"tries\", &max_attempts, Script::ASSERT );\r\n\r\n\t\t// we're challenging them to break a record\r\n\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\tDbg_Assert( pGoalManager );\r\n\t\tScript::CStruct* pMinigameParams = pGoalManager->GetGoal( m_currentMinigame )->GetParams();\r\n\t\tDbg_Assert( pMinigameParams );\r\n\t\tif ( m_currentChallenge )\r\n\t\t{\r\n\t\t\t// printf(\"step 3\\n\");\r\n\t\t\tint last_attempt;\r\n\t\t\tif ( pMinigameParams->GetInteger( \"last_attempt\", &last_attempt, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tprintf(\"got a last attempt of %i\\n\", last_attempt);\r\n\t\t\t\tprintf(\"m_currentChallenge is %i\\n\", m_currentChallenge);\r\n\t\t\t\tif ( last_attempt >= m_currentChallenge )\r\n\t\t\t\t{\t\t\t\t\t\t\r\n\t\t\t\t\t// printf(\"you won the bet!\\n\");\r\n\t\t\t\t\t// beat the bet and call the minigame's bet_success script\r\n\t\t\t\t\tthis->Win();\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t// check that this isn't their last try\r\n\t\tm_numTries++;\r\n\t\tif ( m_numTries >= max_attempts )\r\n\t\t{\r\n\t\t\tLose();\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\t// if it's not a challenge minigame, it's probably a trickspot\r\n\t\t// minigame.  In that case, we'll be told when the game is won\r\n\t\t// the the gap script.\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* CBettingGuy::GetBetParams()\r\n{\r\n\tScript::CStruct* p_params = NULL;\r\n\t\r\n\tif ( m_currentMinigame )\r\n\t{\t\t\r\n\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\tDbg_Assert( pGoalManager );\r\n\t\t\r\n\t\tCGoal* pGoal = pGoalManager->GetGoal( m_currentMinigame );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tScript::CStruct* p_temp = pGoal->GetParams();\r\n\t\t\r\n\t\tswitch ( m_currentDifficulty )\r\n\t\t{\r\n\t\tcase 1:\r\n\t\t\tp_temp->GetStructure( \"bet_easy\", &p_params, Script::NO_ASSERT );\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tp_temp->GetStructure( \"bet_medium\", &p_params, Script::NO_ASSERT );\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tp_temp->GetStructure( \"bet_hard\", &p_params, Script::NO_ASSERT );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Betting game had unknown difficulty level\" ) );\r\n\t\t}\r\n\t}\r\n\treturn p_params;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBettingGuy::OfferMade()\r\n{\r\n\tm_hasOffered = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBettingGuy::OfferRefused()\r\n{\r\n\tm_shouldMove = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CBettingGuy::OfferAccepted()\r\n{\r\n}\r\n\r\nvoid CBettingGuy::SetupParams()\r\n{\r\n\tScript::CStruct* pBetParams = GetBetParams();\r\n\tDbg_Assert( pBetParams );\r\n\t\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tScript::CStruct* p_minigameParams = pGoalManager->GetGoal( m_currentMinigame )->GetParams();\r\n\tDbg_Assert( p_minigameParams );\r\n\t\r\n\tpBetParams->GetInteger( CRCD(0x1d7750fa,\"bet_amount\"), &m_betAmount, Script::ASSERT );\r\n\t\r\n\tmp_params->RemoveComponent( CRCD(0x1d7750fa,\"bet_amount\") );\r\n\tmp_params->AddInteger( CRCD(0x1d7750fa,\"bet_amount\"), m_betAmount );\r\n\t\r\n\tmp_params->RemoveComponent( CRCD(0xf3d0c702,\"current_challenge\") );\r\n\tif ( pBetParams->GetInteger( CRCD(0x1931ac3b,\"bet_challenge\"), &m_currentChallenge, Script::NO_ASSERT ) )\r\n\t{\r\n\t\t// m_currentChallenge = current_challenge;\r\n\t\tprintf(\"got a challenge: %i\\n\", m_currentChallenge);\r\n\t\tmp_params->AddInteger( CRCD(0xf3d0c702,\"current_challenge\"), m_currentChallenge );\r\n\t}\r\n\r\n\tint max_attempts;\r\n\tpBetParams->GetInteger( CRCD(0x62396931,\"tries\"), &max_attempts, Script::ASSERT );\r\n\tmp_params->RemoveComponent( \"num_tries\" );\r\n\tmp_params->AddInteger( CRCD(0x25bad847,\"num_tries\"), max_attempts );\r\n\t\r\n\tmp_params->RemoveComponent( CRCD(0x6922090,\"bet_unit\") );\r\n\tmp_params->RemoveComponent( CRCD(0xd41aac2a,\"bet_action\") );\r\n\tmp_params->RemoveComponent( CRCD(0xa1617634,\"location\") );\r\n\t// get the trick string if necessary\r\n\tif ( p_minigameParams->ContainsFlag( CRCD(0xbc167894,\"trickspot\") ) )\r\n\t{\r\n\t\tScript::CArray* p_keyCombos;\r\n\t\tpBetParams->GetArray( CRCD(0x79704516,\"key_combos\"), &p_keyCombos, Script::ASSERT );\r\n\t\tDbg_MsgAssert( p_keyCombos->GetType() == ESYMBOLTYPE_NAME, ( \"Betting guy key_combos array has bad type\" ) );\r\n\t\tint key_combo_index = GetRandomIndexFromKeyCombos( p_keyCombos );\r\n\t\tuint32 key_combo = p_keyCombos->GetChecksum( key_combo_index );\r\n\t\r\n\t\tuint32 trick_name_checksum;\r\n\t\t// get the global trick mapping\r\n\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\tObj::CSkaterProfile* p_SkaterProfile = skate_mod->GetCurrentProfile();\r\n\t\tScript::CStruct* p_trickMappings = p_SkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") );\r\n\t\tp_trickMappings->GetChecksum( key_combo, &trick_name_checksum, Script::ASSERT );\r\n\t\r\n\t\tconst char* trick_text;\r\n\t\tif ( trick_name_checksum )\r\n\t\t{\r\n\t\t\tScript::CStruct* p_trick_structure = Script::GetStructure( trick_name_checksum, Script::ASSERT );\r\n\t\t\tScript::CStruct* p_trick_params;\r\n\t\t\tp_trick_structure->GetStructure( CRCD(0x7031f10c,\"Params\"), &p_trick_params, Script::ASSERT );\r\n\t\t\tp_trick_params->GetLocalText( CRCD(0xa1dc81f9,\"Name\"), &trick_text, Script::ASSERT );\r\n\t\t}\r\n\t\tmp_params->AddString( CRCD(0xd41aac2a,\"bet_action\"), trick_text );\r\n\t\r\n\t\tconst char* location;\r\n\t\tp_minigameParams->GetString( CRCD(0xa1617634,\"location\"), &location, Script::ASSERT );\r\n\t\tmp_params->AddString( CRCD(0xa1617634,\"location\"), location );\r\n\t}\r\n\telse \r\n\t{\r\n\t\tconst char* bet_action;\r\n\t\t// the bet action is global\r\n\t\tp_minigameParams->GetString( CRCD(0xd41aac2a,\"bet_action\"), &bet_action, Script::ASSERT );\r\n\t\tmp_params->AddString( CRCD(0xd41aac2a,\"bet_action\"), bet_action );\r\n\t\tconst char* bet_unit;\r\n\t\tp_minigameParams->GetString( CRCD(0x6922090,\"bet_unit\"), &bet_unit, Script::ASSERT );\r\n\t\tmp_params->AddString( CRCD(0x6922090,\"bet_unit\"), bet_unit );\r\n\t}\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/BettingGuy.h",
    "content": "// BettingGuy.h\r\n#ifndef _SK_MODULES_SKATE_BETTINGGUY_H_\r\n#define _SK_MODULES_SKATE_BETTINGGUY_H_\r\n\r\n#include <sk/modules/skate/goalmanager.h>\r\n\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Game\r\n{\r\n\r\nclass CBettingGuy : public CGoal\r\n{\r\npublic:\r\n\t\t\t\t\t\tCBettingGuy( Script::CStruct* pParams );\r\n\tvirtual\t\t\t\t~CBettingGuy();\r\n\r\n\tbool\t\t\t\tIsActive();\r\n\tbool\t\t\t\tShouldUseTimer() { return false; }\r\n\tbool\t\t\t\tCountAsActive() { return false; }\r\n\tbool\t\t\t\tActivate();\r\n\tvoid\t\t\t\tSetActive();\r\n\tbool\t\t\t\tUpdate();\r\n\tbool\t\t\t\tMoveToNewNode( bool force = false );\r\n\tbool\t\t\t\tIsExpired();\r\n\tbool\t\t\t\tDeactivate( bool force = false, bool affect_tree = true );\r\n\tbool\t\t\t\tWin();\r\n\tbool\t\t\t\tWin( uint32 goalId );\r\n\tbool\t\t\t\tLose();\r\n\tvoid\t\t\t\tReset();\r\n\r\n\tbool\t\t\t\tEndBetAttempt( uint32 goalId );\r\n\tbool\t\t\t\tStartBetAttempt( uint32 goalId );\r\n\tbool\t\t\t\tBetIsActive( uint32 goalId );\r\n\r\n\tvoid\t\t\t\tOfferMade();\r\n\tvoid\t\t\t\tOfferRefused();\r\n\tvoid\t\t\t\tOfferAccepted();\r\n\r\n\tScript::CStruct*\tGetBetParams();\r\n\tvoid\t\t\t\tSetupParams();\r\n\r\nprotected:\r\n\tbool\t\t\t\tm_shouldMove;\r\n\tint\t\t\t\t\tm_numBetsWon;\r\n\tuint32\t\t\t\tm_currentMinigame;\r\n\tuint32\t\t\t\tm_currentNode;\r\n\tint\t\t\t\t\tm_currentDifficulty;\r\n\tbool\t\t\t\tm_hasOffered;\r\n\tbool\t\t\t\tm_inAttempt;\r\n\tint\t\t\t\t\tm_numTries;\r\n\tint\t\t\t\t\tm_currentChallenge;\r\n\tint\t\t\t\t\tm_betAmount;\r\n\tint\t\t\t\t\tm_straightLosses;\r\n\tint \t\t\t\tm_straightWins;\r\n};\r\n\r\n}\t// namespace Game\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/CATGoal.cpp",
    "content": "// Create-A-Trick goal!\r\n\r\n#include <sk/modules/skate/catgoal.h>\r\n#include <sk/modules/skate/GoalManager.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCatGoal::CCatGoal( Script::CStruct* pParams ) : CGoal( pParams )\r\n{\r\n\t// uh...\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCatGoal::~CCatGoal()\r\n{\r\n\t// hmm...\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CCatGoal::Activate()\r\n{\r\n\treturn CGoal::Activate();\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCatGoal::Deactivate( bool force, bool affect_tree )\r\n{\r\n\treturn CGoal::Deactivate( force, affect_tree );\r\n}\r\n\r\n\r\n}\t// namespace game\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/CATGoal.h",
    "content": "// Create-A-Trick goal!\r\n\r\n#ifndef __SK_MODULES_SKATE_CATGOAL_H__\r\n#define __SK_MODULES_SKATE_CATGOAL_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <sk/modules/skate/GoalManager.h>\r\n\r\nnamespace Game\r\n{\r\n\r\nclass CCatGoal : public CGoal\r\n{\r\n\r\npublic:\r\n\t\t\t\t\t\tCCatGoal( Script::CStruct* pParams );\r\n\tvirtual\t\t\t\t~CCatGoal();\r\n\r\n\tbool\t\t\t\tActivate();\r\n\tbool\t\t\t\tDeactivate( bool force = false, bool affect_tree = true );\r\nprotected:\r\n};\r\n\r\n}\r\n\r\n#endif // #ifndef __SK_MODULES_SKATE_FINDGAPSGOAL_H__\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/CompetitionGoal.cpp",
    "content": "#include <sk/modules/skate/GoalManager.h>\r\n#include <sk/modules/skate/CompetitionGoal.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/competition.h>\r\n\r\n#include <sk/objects/skaterprofile.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCompetitionGoal::CCompetitionGoal( Script::CStruct* pParams )\r\n\t: CGoal( pParams )\r\n{\r\n\t// uhh...necessary?\r\n\tm_compPaused = false;\r\n\tm_gotGold = m_gotSilver = m_gotBronze = false;\r\n\tm_rewardGiven = 0;\r\n\r\n\tm_winScoreRecord = vINT_MAX;\r\n\r\n\tm_endRunType = vENDOFRUN;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCCompetitionGoal::~CCompetitionGoal()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompetitionGoal::Expire()\r\n{\r\n\t// don't deactivate the goal!\r\n\tRunCallbackScript( Game::vEXPIRED );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CCompetitionGoal::IsActive()\r\n{\r\n\treturn m_active;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompetitionGoal::SetActive()\r\n{\r\n\t// printf(\"setting to active\\n\");\r\n\tm_active = true;\r\n\tm_compPaused = false;\r\n\tm_paused = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompetitionGoal::SetInactive()\r\n{\r\n\tm_active = false;\r\n\tm_compPaused = false;\r\n\tm_paused = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CCompetitionGoal::HasWonGoal()\r\n{\r\n\treturn m_isbeat;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompetitionGoal::MarkBeaten()\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tMdl::CCompetition* pComp = skate_mod->GetCompetition();\r\n\t\r\n\tif ( pComp->PlaceIs( 1 ) )\r\n\t{\r\n\t\tm_gotGold = true;\r\n\t\tm_gotSilver = true;\r\n\t\tm_gotBronze = true;\r\n\t}\r\n\telse if ( pComp->PlaceIs( 2 ) )\r\n\t{\r\n\t\tm_gotSilver = true;\r\n\t\tm_gotBronze = true;\r\n\t}\r\n\telse if ( pComp->PlaceIs( 3 ) )\r\n\t{\r\n\t\tm_gotBronze = true;\r\n\t}\r\n\r\n\t// m_gotGold = true;\r\n\t// m_gotSilver = true;\r\n\t// m_gotBronze = true;\r\n\tm_isbeat = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CCompetitionGoal::UnBeatGoal()\r\n{\r\n\tm_isbeat = false;\r\n\tm_gotBronze = false;\r\n\tm_gotSilver = false;\r\n\tif ( HasWonGoal() )\r\n\t{\r\n\t\tm_gotGold = false;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CCompetitionGoal::Win()\r\n{\r\n\tmp_params->AddChecksum( NONAME, CRCD( 0xc309cad1, \"just_won_goal\" ) );\r\n\tRunCallbackScript( Game::vDEACTIVATE );\r\n\tmp_params->RemoveFlag( CRCD( 0xc309cad1, \"just_won_goal\" ) );\r\n\tSetInactive();\r\n\t\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\r\n\tif ( !gamenet_man->InNetGame() )\r\n\t{\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tMdl::CCompetition* pComp = skate_mod->GetCompetition();\r\n\t\t\r\n\t\tint place = 999;\r\n\t\tif ( pComp->PlaceIs( 1 ) )\r\n\t\t\tplace = 1;\r\n\t\telse if ( pComp->PlaceIs( 2 ) )\r\n\t\t\tplace = 2;\r\n\t\telse if ( pComp->PlaceIs( 3 ) )\r\n\t\t\tplace = 3;\r\n\r\n\t\tif ( place < m_winScoreRecord )\r\n\t\t{\r\n\t\t\tmp_params->AddInteger( \"win_record\", place );\r\n\t\t\tm_winScoreRecord = place;\r\n\t\t}\r\n\t}\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n#endif\t\t// __NOPT_ASSERT__\r\n\t\t\r\n\tScript::CStruct* p_reward_params = new Script::CStruct();\r\n\t\r\n\tif ( !HasWonGoal() )\r\n\t{\r\n\t\t// don't add cash\r\n\t\tScript::CStruct* pTempStruct = new Script::CStruct();\r\n\t\tGetRewardsStructure( pTempStruct, true );\r\n\t\tp_reward_params->AppendStructure( pTempStruct );\r\n\t\tdelete pTempStruct;\r\n\t\tUnlockRewardGoals();\r\n\t}\r\n\telse\r\n\t\tmp_params->RemoveComponent( \"reward_params\" );\r\n\r\n\t// award any cash\r\n\t// AwardCash( p_reward_params );\r\n\r\n\t// mp_params->RemoveComponent( \"reward_params\" );\r\n\tmp_params->AddStructure( \"reward_params\", p_reward_params );\r\n\tRunCallbackScript( Game::vSUCCESS );\r\n\t\r\n\tdelete p_reward_params;\r\n\r\n\t// now it's safe to mark as beaten\r\n\tif ( !HasWonGoal() )\r\n\t\tMarkBeaten();\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompetitionGoal::AwardCash( Script::CStruct* p_reward_params )\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n#endif\t\t// __NOPT_ASSERT__\r\n\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tMdl::CCompetition* pComp = skate_mod->GetCompetition();\r\n\t\r\n\t// figure any cash reward\r\n\tif ( pComp->PlaceIs( 1 ) || pComp->PlaceIs( 2 ) || pComp->PlaceIs( 3 ) )\r\n\t{\t\t\r\n\t\tint total_reward;\r\n\t\tint current_reward = 0;\r\n\t\tif ( mp_params->GetInteger( \"reward_cash\", &total_reward, Script::NO_ASSERT ) )\r\n\t\t{\t\t\t\r\n\t\t\tif ( pComp->PlaceIs( 1 ) && !m_gotGold )\r\n\t\t\t{\r\n\t\t\t\tcurrent_reward = total_reward - m_rewardGiven;\r\n\t\t\t\tm_gotGold = true;\r\n\t\t\t\tm_gotSilver = true;\r\n\t\t\t\tm_gotBronze = true;\r\n\t\t\t}\r\n\t\t\telse if ( pComp->PlaceIs( 2 ) && !m_gotSilver )\r\n\t\t\t{\r\n\t\t\t\tcurrent_reward = total_reward * 2 / 3;\r\n\t\t\t\tif ( m_gotBronze )\r\n\t\t\t\t\tcurrent_reward -= total_reward / 3;\r\n\r\n\t\t\t\tm_gotSilver = true;\r\n\t\t\t\tm_gotBronze = true;\t\t\t\t\r\n\r\n\t\t\t}\r\n\t\t\telse if ( pComp->PlaceIs( 3 ) && !m_gotBronze )\r\n\t\t\t{\r\n\t\t\t\tcurrent_reward = total_reward / 3;\r\n\t\t\t\tm_gotBronze = true;\r\n\t\t\t}\r\n\r\n\t\t\tif ( current_reward > 0 )\r\n\t\t\t{\r\n\t\t\t\t// pGoalManager->AddCash( current_reward );\r\n\t\t\t\t// Script::RunScript( \"goal_got_cash\" );\r\n\t\t\t\tp_reward_params->AddInteger( \"cash\", current_reward );\r\n\t\t\t\tm_rewardGiven += current_reward;\r\n\t\t\t}\r\n\t\t}\r\n\t}   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompetitionGoal::PauseCompetition()\r\n{\r\n\tm_compPaused = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompetitionGoal::UnPauseCompetition()\r\n{\r\n\tm_compPaused = false;\r\n\tm_endRunCalled = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CCompetitionGoal::IsPaused()\r\n{\r\n\treturn ( m_paused || m_compPaused );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompetitionGoal::LoadSaveData( Script::CStruct* pFlags )\r\n{\r\n\tint gotBronze;\r\n\tpFlags->GetInteger( \"gotBronze\", &gotBronze, Script::NO_ASSERT );\r\n\tif ( gotBronze != 0 )\r\n\t\tm_gotBronze = true;\r\n\r\n\tint gotSilver;\r\n\tpFlags->GetInteger( \"gotSilver\", &gotSilver, Script::NO_ASSERT );\r\n\tif ( gotSilver != 0 )\r\n\t\tm_gotBronze = true;\r\n\r\n\tint gotGold;\r\n\tpFlags->GetInteger( \"gotGold\", &gotGold, Script::NO_ASSERT );\r\n\tif ( gotGold != 0 )\r\n\t\tm_gotBronze = true;\r\n\r\n\tint reward_given;\r\n\tpFlags->GetInteger( \"reward_given\", &reward_given, Script::NO_ASSERT );\r\n\tm_rewardGiven = reward_given;\r\n\r\n\tint record;\r\n\tif ( pFlags->GetInteger( \"win_record\", &record, Script::NO_ASSERT ) )\r\n\t\tm_winScoreRecord = record;\r\n\t\r\n\tCGoal::LoadSaveData( pFlags );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CCompetitionGoal::GetSaveData( Script::CStruct* pFlags )\r\n{\r\n\tCGoal::GetSaveData( pFlags );\r\n\t\r\n\tif ( m_gotBronze )\r\n\t\tpFlags->AddInteger( \"gotBronze\", 1 );\r\n\telse\r\n\t\tpFlags->AddInteger( \"gotBronze\", 0 );\r\n\r\n\tif ( m_gotSilver )\r\n\t\tpFlags->AddChecksum( \"gotSilver\", 1 );\r\n\telse\r\n\t\tpFlags->AddChecksum( \"gotSilver\", 0 );\r\n\r\n\tif ( m_gotGold )\r\n\t\tpFlags->AddChecksum( \"gotGold\", 1 );\r\n\telse\r\n\t\tpFlags->AddChecksum( \"gotGold\", 0 );\r\n\r\n\tpFlags->AddInteger( \"win_record\", m_winScoreRecord );\r\n\tpFlags->AddInteger( \"reward_given\", m_rewardGiven );\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/CompetitionGoal.h",
    "content": "#ifndef __SK_MODULES_SKATE_COMPETITIONGOAL_H__\r\n#define __SK_MODULES_SKATE_COMPETITIONGOAL_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <sk/modules/skate/GoalManager.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n\r\nclass CCompetitionGoal : public CGoal\r\n{\r\n\r\npublic:\r\n\t\t\t\t\tCCompetitionGoal( Script::CStruct* pParams );\r\n\tvirtual\t\t\t~CCompetitionGoal();\r\n\r\n\tvoid\t\t\tExpire();\r\n\tbool\t\t\tIsActive();\r\n\tvoid\t\t\tSetActive();\r\n\tvoid \t\t\tSetInactive();\r\n\r\n\tvoid\t\t\tLoadSaveData( Script::CStruct* pFlags );\r\n\tvoid\t\t\tGetSaveData( Script::CStruct* pFlags );\r\n\r\n\tbool\t\t\tWin();\r\n\tbool\t\t\tHasWonGoal();\r\n\tvoid\t\t\tMarkBeaten();\r\n\tbool\t\t\tUnBeatGoal();\r\n\r\n\tvoid\t\t\tAwardCash( Script::CStruct* p_reward_params );\r\n\r\n\tvoid\t\t\tPauseCompetition();\r\n\tvoid\t\t\tUnPauseCompetition();\r\n\r\n\tbool\t\t\tIsPaused();\r\nprotected:\r\n\r\n\tbool\t\t\tm_compPaused;\r\n\tbool\t\t\tm_gotGold;\r\n\tbool\t\t\tm_gotSilver;\r\n\tbool\t\t\tm_gotBronze;\r\n\tint\t\t\t\tm_rewardGiven;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/CreateATrick.cpp",
    "content": "// CreateATrick.cpp\r\n\r\n#include <sk/modules/skate/createatrick.h>\r\n#include <sk/modules/skate/skate.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <core/math/math.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCreateATrick::CCreateATrick() \r\n\t\r\n{\r\n\tprintf(\"creating a CCreateATrick\\n\");\r\n\r\n    // Other Params\r\n    Script::CStruct* p_other_params = Script::GetStructure( \"Default_CAT_other_info\", Script::ASSERT );\r\n    mp_other_params = new Script::CStruct();\r\n    mp_other_params->AppendStructure( p_other_params );\r\n    \r\n    // Rotations\r\n    Script::CArray* p_rotations;\r\n    p_rotations = Script::GetArray( \"Default_CAT_rotation_info\", Script::ASSERT );\r\n\r\n    mp_rotations = new Script::CArray();\r\n    mp_rotations->SetSizeAndType( vMAX_ROTATIONS, ESYMBOLTYPE_STRUCTURE );\r\n    Script::CopyArray( mp_rotations, p_rotations );\r\n    \r\n\r\n    // Animations\r\n    Script::CArray* p_animations;\r\n    p_animations = Script::GetArray( \"Default_CAT_animation_info\", Script::ASSERT );\r\n\r\n    mp_animations = new Script::CArray();\r\n    mp_animations->SetSizeAndType( vMAX_ANIMATIONS, ESYMBOLTYPE_STRUCTURE );\r\n    Script::CopyArray( mp_animations, p_animations );\r\n    \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCreateATrick::~CCreateATrick()\r\n{\r\n\tif ( mp_other_params )\r\n    {\r\n        delete mp_other_params;\r\n    }\r\n    if ( mp_rotations )\r\n    {\r\n        Script::CleanUpArray( mp_rotations );\r\n        delete mp_rotations;\r\n    }\r\n    if ( mp_animations )\r\n    {\r\n        Script::CleanUpArray( mp_animations );\r\n        delete mp_animations;\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetCreateATrickParams | Gets the values for rotations and animations of a particular skater\r\nbool ScriptGetCreateATrickParams(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\r\n    int trick_index;\r\n\r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n\t\r\n        pParams->GetInteger( \"trick_index\", &trick_index, Script::ASSERT );\r\n        Game::CCreateATrick* pCreatedTrick = pSkater->m_created_trick[trick_index];\r\n    \tDbg_Assert( pCreatedTrick );\r\n    \r\n        //Other params\r\n        pScript->GetParams()->AddStructure( \"other_params\", pCreatedTrick->mp_other_params );\r\n        \r\n        //Rotation params\r\n        pScript->GetParams()->AddArray( \"rotation_info\", pCreatedTrick->mp_rotations );\r\n        \r\n        //Animation params\r\n        pScript->GetParams()->AddArray( \"animation_info\", pCreatedTrick->mp_animations );\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetCreateATrickOtherParams | Gets the values for trick name, score, etc.\r\nbool ScriptGetCreateATrickOtherParams(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\r\n    int trick_index;\r\n\r\n\tObj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetInteger( \"trick_index\", &trick_index, Script::ASSERT );\r\n        Game::CCreateATrick* pCreatedTrick = pSkater->m_created_trick[trick_index];\r\n    \tDbg_Assert( pCreatedTrick );\r\n        \r\n        //Other params\r\n        pScript->GetParams()->AddStructure( \"other_params\", pCreatedTrick->mp_other_params );\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetCreateATrickRotations | Gets the values for rotations\r\nbool ScriptGetCreateATrickRotations(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\r\n    int trick_index;\r\n\r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetInteger( \"trick_index\", &trick_index, Script::ASSERT );\r\n        Game::CCreateATrick* pCreatedTrick = pSkater->m_created_trick[trick_index];\r\n    \tDbg_Assert( pCreatedTrick );\r\n    \r\n        //Rotation params\r\n        pScript->GetParams()->AddArray( \"rotation_info\", pCreatedTrick->mp_rotations );\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetCreateATrickAnimations | Gets the values for animations\r\nbool ScriptGetCreateATrickAnimations(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\r\n    int trick_index;\r\n\r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetInteger( \"trick_index\", &trick_index, Script::ASSERT );\r\n        Game::CCreateATrick* pCreatedTrick = pSkater->m_created_trick[trick_index];\r\n    \tDbg_Assert( pCreatedTrick );\r\n    \r\n        //Animation params\r\n        pScript->GetParams()->AddArray( \"animation_info\", pCreatedTrick->mp_animations );\r\n    \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetCreateATrickParams | Sets the values for rotations and animations of a particular skater\r\nbool ScriptSetCreateATrickParams(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\r\n    int trick_index;\r\n    \r\n    Script::CStruct *p_other_params;\r\n    Script::CArray *p_rotation_info;\r\n    Script::CArray *p_animation_info;\r\n\r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n    \r\n        pParams->GetInteger( \"trick_index\", &trick_index, Script::ASSERT );\r\n        //Game::CCreateATrick* pCreatedTrick = pSkater->m_created_trick[trick_index];\r\n    \t//Dbg_Assert( pCreatedTrick );\r\n        \r\n        // make sure the skater actually has created tricks before we try to update them.\r\n        if ( !(pSkater->m_created_trick[1]) )\r\n        {\r\n            printf(\"Skater has no created tricks!!\\n\");\r\n            return false;\r\n        }\r\n        else\r\n        {\r\n            //Script::PrintContents( pSkater->m_created_trick[trick_index]->mp_other_params );\r\n        }\r\n        //Dbg_Assert( pSkater->m_created_trick[1] );\r\n    \r\n        //Params\r\n        if(pParams->GetStructure( \"other_params\", &p_other_params, Script::ASSERT ))\r\n        {\r\n            printf(\"Storing param info %i\\n\", trick_index);\r\n            pSkater->m_created_trick[trick_index]->mp_other_params->AppendStructure( p_other_params );\r\n        }\r\n        \r\n        //Rotations\r\n        if(pParams->GetArray( \"rotation_info\", &p_rotation_info, Script::ASSERT ))\r\n        {\r\n            printf(\"Storing rotation info %i\\n\", trick_index);\r\n            Script::CopyArray( pSkater->m_created_trick[trick_index]->mp_rotations, p_rotation_info );\r\n        }\r\n    \r\n        //Animations\r\n        if(pParams->GetArray( \"animation_info\", &p_animation_info, Script::ASSERT ))\r\n        {\r\n            printf(\"Storing animation info %i\\n\", trick_index);\r\n            Script::CopyArray( pSkater->m_created_trick[trick_index]->mp_animations, p_animation_info );\r\n        }\r\n        \r\n            \r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetCreateATrickOtherParams | Sets name, score, etc.\r\nbool ScriptSetCreateATrickOtherParams(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\r\n    \r\n    int trick_index;\r\n    \r\n    Script::CStruct *p_other_params;\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n\t\r\n        pParams->GetInteger( \"trick_index\", &trick_index, Script::ASSERT );\r\n    \r\n        Dbg_Assert( pSkater->m_created_trick[trick_index] );\r\n        \r\n        //Params\r\n        if(pParams->GetStructure( \"other_params\", &p_other_params, Script::ASSERT ))\r\n        {\r\n            printf(\"Storing param info %i\\n\", trick_index);\r\n            // pSkater->m_created_trick[trick_index]->mp_other_params->Clear();\r\n            pSkater->m_created_trick[trick_index]->mp_other_params->AppendStructure( p_other_params );\r\n            //Script::PrintContents(pSkater->m_created_trick[trick_index]->mp_other_params);\r\n        }\r\n    \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetCreateATrickRotations | Sets the values for rotations\r\nbool ScriptSetCreateATrickRotations(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\r\n    int trick_index;\r\n    \r\n    Script::CArray *p_rotation_info;\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetInteger( \"trick_index\", &trick_index, Script::ASSERT );\r\n    \r\n        Dbg_Assert( pSkater->m_created_trick[trick_index] );\r\n        \r\n        //Rotations\r\n        if(pParams->GetArray( \"rotation_info\", &p_rotation_info, Script::ASSERT ))\r\n        {\r\n            printf(\"Storing rotation info %i\\n\", trick_index);\r\n            Script::CopyArray( pSkater->m_created_trick[trick_index]->mp_rotations, p_rotation_info );\r\n        }\r\n    \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetCreateATrickAnimations | Sets the values for rotations\r\nbool ScriptSetCreateATrickAnimations(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\r\n    int trick_index;\r\n    \r\n    Script::CArray *p_animation_info;\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetInteger( \"trick_index\", &trick_index, Script::ASSERT );\r\n        \r\n        Dbg_Assert( pSkater->m_created_trick[trick_index] );\r\n        \r\n        //Animations\r\n        if(pParams->GetArray( \"animation_info\", &p_animation_info, Script::ASSERT ))\r\n        {\r\n            printf(\"Storing animation info %i\\n\", trick_index);\r\n            Script::CopyArray( pSkater->m_created_trick[trick_index]->mp_animations, p_animation_info );\r\n        }\r\n    \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_SetNumAnims | \r\nbool ScriptCAT_SetNumAnims(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    int value;\r\n\r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetInteger(NONAME, &value, Script::ASSERT );\r\n        pSkater->m_num_cat_animations_on = value;\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_GetNumAnims | \r\nbool ScriptCAT_GetNumAnims(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pScript->GetParams()->AddInteger( \"num_animations_on\", pSkater->m_num_cat_animations_on );\r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_SetAnimsDone | \r\nbool ScriptCAT_SetAnimsDone(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    int value;\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetInteger(NONAME, &value, Script::ASSERT );\r\n        if ( value == 0 )\r\n        {\r\n            pSkater->m_cat_animations_done = false;\r\n        }\r\n        else\r\n        {\r\n            pSkater->m_cat_animations_done = true;\r\n        }\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_GetAnimsDone | \r\nbool ScriptCAT_GetAnimsDone(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        if ( pSkater->m_cat_animations_done )\r\n        {\r\n            pScript->GetParams()->AddInteger( \"cat_animations_done\", 1 );\r\n        }\r\n        else\r\n        {\r\n            pScript->GetParams()->AddInteger( \"cat_animations_done\", 0 );\r\n        }\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_SetRotsDone | \r\nbool ScriptCAT_SetRotsDone(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    int value;\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetInteger(NONAME, &value, Script::ASSERT );\r\n        if ( value == 0 )\r\n        {\r\n            pSkater->m_cat_rotations_done = false;\r\n        }\r\n        else\r\n        {\r\n            pSkater->m_cat_rotations_done = true;\r\n        }\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_GetRotsDone | \r\nbool ScriptCAT_GetRotsDone(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        if ( pSkater->m_cat_rotations_done )\r\n        {\r\n            pScript->GetParams()->AddInteger( \"cat_rotations_done\", 1 );\r\n        }\r\n        else\r\n        {\r\n            pScript->GetParams()->AddInteger( \"cat_rotations_done\", 0 );\r\n        }\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_SetBailDone | \r\nbool ScriptCAT_SetBailDone(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    int value;\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetInteger(NONAME, &value, Script::ASSERT );\r\n        if ( value == 0 )\r\n        {\r\n            pSkater->m_cat_bail_done = false;\r\n        }\r\n        else\r\n        {\r\n            pSkater->m_cat_bail_done = true;\r\n        }\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_GetBailDone | \r\nbool ScriptCAT_GetBailDone(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        if ( pSkater->m_cat_bail_done )\r\n        {\r\n            pScript->GetParams()->AddInteger( \"bailtimescriptdone\", 1 );\r\n        }\r\n        else\r\n        {\r\n            pScript->GetParams()->AddInteger( \"bailtimescriptdone\", 0 );\r\n        }\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_SetFlipSkater | \r\nbool ScriptCAT_SetFlipSkater(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    int value;\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetInteger(NONAME, &value, Script::ASSERT );\r\n        if ( value == 0 )\r\n        {\r\n            pSkater->m_cat_flip_skater_180 = false;\r\n        }\r\n        else\r\n        {\r\n            pSkater->m_cat_flip_skater_180 = true;\r\n        }\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_GetFlipSkater | \r\nbool ScriptCAT_GetFlipSkater(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        if ( pSkater->m_cat_flip_skater_180 )\r\n        {\r\n            pScript->GetParams()->AddInteger( \"cat_flip_skater_180\", 1 );\r\n        }\r\n        else\r\n        {\r\n            pScript->GetParams()->AddInteger( \"cat_flip_skater_180\", 0 );\r\n        }\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_SetHoldTime | \r\nbool ScriptCAT_SetHoldTime(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    float value;\r\n\r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetFloat(NONAME, &value, Script::ASSERT );\r\n        pSkater->m_cat_hold_time = value;\r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_GetHoldTime | \r\nbool ScriptCAT_GetHoldTime(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pScript->GetParams()->AddFloat( \"cat_hold_time\", pSkater->m_cat_hold_time );\r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_SetTotalY | \r\nbool ScriptCAT_SetTotalY(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    int value;\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetInteger(NONAME, &value, Script::ASSERT );\r\n        pSkater->m_cat_total_y = value;\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_GetTotalY | \r\nbool ScriptCAT_GetTotalY(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pScript->GetParams()->AddInteger( \"total_Y_angle\", pSkater->m_cat_total_y );\r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_SetTotalX | \r\nbool ScriptCAT_SetTotalX(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    int value;\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetInteger(NONAME, &value, Script::ASSERT );\r\n        pSkater->m_cat_total_x = value;\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_GetTotalX | \r\nbool ScriptCAT_GetTotalX(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pScript->GetParams()->AddInteger( \"total_X_angle\", pSkater->m_cat_total_x );\r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_SetTotalZ | \r\nbool ScriptCAT_SetTotalZ(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    int value;\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pParams->GetInteger(NONAME, &value, Script::ASSERT );\r\n        pSkater->m_cat_total_z = value;\r\n        \r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptCAT_GetTotalZ | \r\nbool ScriptCAT_GetTotalZ(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    \r\n    Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n    if ( pSkater )\r\n    {\r\n        pScript->GetParams()->AddInteger( \"total_Z_angle\", pSkater->m_cat_total_z );\r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n \r\n}\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/CreateATrick.h",
    "content": "\r\n// CreateATrick.h\r\n#ifndef _SK_MODULES_SKATE_CREATEATRICK_H_\r\n#define _SK_MODULES_SKATE_CREATEATRICK_H_\r\n\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Script\r\n{\r\n    class CStruct;\r\n}\r\n\r\nnamespace Game\r\n{\r\n\r\nenum\r\n{\r\n    vMAX_CREATED_TRICKS=11,\r\n    vMAX_ROTATIONS=6,\r\n    vMAX_ANIMATIONS=6\r\n};\r\n\r\nclass CCreateATrick\r\n{\r\npublic:\r\n\t\t\t\t\t\tCCreateATrick();\r\n\tvirtual\t\t\t\t~CCreateATrick();\r\n\r\n    //char*   m_name;\r\n\t//int     m_score;\r\n    //bool    m_rotateafter;\r\n\r\n    Script::CStruct *mp_other_params;\r\n    Script::CArray *mp_rotations;\r\n    Script::CArray *mp_animations;\r\n\r\n};\r\n\r\n// Get\r\nbool ScriptGetCreateATrickParams(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptGetCreateATrickOtherParams(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptGetCreateATrickRotations(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptGetCreateATrickAnimations(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\n// Set\r\nbool ScriptSetCreateATrickParams(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptSetCreateATrickOtherParams(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptSetCreateATrickRotations(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptSetCreateATrickAnimations(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\n// other scripts\r\nbool ScriptCAT_SetNumAnims(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptCAT_GetNumAnims(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptCAT_SetAnimsDone(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptCAT_GetAnimsDone(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptCAT_SetRotsDone(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptCAT_GetRotsDone(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptCAT_SetBailDone(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptCAT_GetBailDone(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptCAT_SetFlipSkater(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptCAT_GetFlipSkater(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptCAT_SetHoldTime(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptCAT_GetHoldTime(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptCAT_SetTotalY(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptCAT_GetTotalY(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptCAT_SetTotalX(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptCAT_GetTotalX(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptCAT_SetTotalZ(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptCAT_GetTotalZ(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\n\r\n}\t// namespace Game\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/FilmGoal.cpp",
    "content": "// filming goal\r\n\r\n#include <sk/modules/skate/GoalManager.h>\r\n#include <sk/modules/skate/FilmGoal.h>\r\n#include <sk/modules/skate/skate.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n\r\n#include <gel/components/modelcomponent.h>\r\n\r\n#include <gel/scripting/checksum.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/NxModel.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCFilmGoal::CFilmGoal( Script::CStruct* pParams ) : CGoal( pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCFilmGoal::~CFilmGoal()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CFilmGoal::Activate()\r\n{\r\n\tm_timeOnCamera = 0;\r\n\tm_timeRequired = m_totalTime = 0;\r\n\tm_numShotsRequired = 0;\r\n\tm_filming = false;\r\n\r\n\t// script param for displaying time on camera...\r\n\tmp_params->AddInteger( CRCD( 0x9278ca8d, \"time_on_camera\" ), 0 );\r\n\t\r\n\tint time_required;\r\n\tif ( mp_params->GetInteger( CRCD(0x184e30fd,\"total_time_required\"), &time_required, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tm_timeRequired = (Tmr::Time)( time_required * 1000 );\r\n\t\tint total_time;\r\n\t\tmp_params->GetInteger( CRCD(0x906b67ba,\"time\"), &total_time, Script::ASSERT );\r\n\t\tm_totalTime *= (Tmr::Time)( total_time * 1000 );\r\n\t}\r\n\telse if ( !mp_params->GetInteger( CRCD(0xc808f9fb,\"total_shots_required\"), &m_numShotsRequired, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Film goal %s requires either total_time_required or total_shots_required\", Script::FindChecksumName( GetGoalId() ) ) );\r\n\t}\t\r\n\treturn CGoal::Activate();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CFilmGoal::Update()\r\n{\r\n\tmp_params->AddInteger( CRCD(0xfc7fc309,\"last_time_on_camera\"), (int)m_timeOnCamera );\r\n\r\n    if ( IsActive() && !IsPaused() )\r\n\t{\r\n\t\t// check if they're still looking at the target object\r\n\t\tbool should_win = false;\r\n\t\tif ( m_filming )\r\n\t\t{\r\n\t\t\tif ( target_object_visible() )\r\n\t\t\t{\r\n\t\t\t\tm_timeOnCamera += (Tmr::Time)( Tmr::FrameLength() * 1000 );\r\n\t\t\t\t\r\n\t\t\t\t// script param for displaying time on camera...\r\n\t\t\t\tmp_params->AddInteger( CRCD( 0x9278ca8d, \"time_on_camera\" ), (int)m_timeOnCamera );\r\n\t\t\t}\r\n\t\t\t// printf( \"on camera: %i, required: %i\\n\", (int)m_timeOnCamera, (int)m_timeRequired );\r\n\t\r\n\t\t\tif ( m_timeOnCamera >= m_timeRequired )\r\n\t\t\t{\r\n\t\t\t\tshould_win = true;\r\n\t\t\t}\r\n\t\t\telse if ( m_timeRequired - m_timeOnCamera > m_timeLeft )\r\n\t\t\t{\r\n\t\t\t\t// can't possibly win!\r\n\t\t\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\t\t\tDbg_Assert( pGoalManager );\r\n\t\t\t\treturn pGoalManager->LoseGoal( GetGoalId() );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( m_numShotsRequired && m_numShotsAchieved >= m_numShotsRequired )\r\n\t\t{\r\n\t\t\tshould_win = true;\r\n\t\t}\r\n\t\r\n\t\tif ( should_win )\r\n\t\t{\r\n\t\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\t\tDbg_Assert( pGoalManager );\r\n\t\t\treturn pGoalManager->WinGoal( GetGoalId() );\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t\treturn CGoal::Update();\r\n\t}\r\n\telse\r\n\t\treturn CGoal::Update();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CFilmGoal::Deactivate( bool force, bool affect_tree )\r\n{\r\n\treturn CGoal::Deactivate( force, affect_tree );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CFilmGoal::CheckpointHit()\r\n{\r\n\tDbg_MsgAssert( m_numShotsRequired, ( \"GoalManager_FilmCheckpoint called on a non-checkpoint goal.\" ) );\r\n\tif ( target_object_visible() )\r\n\t{\r\n\t\tm_numShotsAchieved++;\r\n\r\n\t\tif ( m_numShotsAchieved > m_numShotsRequired )\r\n\t\t{\r\n\t\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\t\tDbg_Assert( pGoalManager );\r\n\t\t\tpGoalManager->WinGoal( GetGoalId() );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// does a visibility check as well as a distance check - you can't just\r\n// look at him from a mile away\r\nbool CFilmGoal::target_object_visible()\r\n{\r\n\tuint32 target_obj_id;\r\n\tmp_params->GetChecksum( CRCD( 0xd262ed09, \"film_target\" ), &target_obj_id, Script::ASSERT );\r\n\tObj::CCompositeObject* pTargetObj = (Obj::CCompositeObject*)Obj::ResolveToObject( target_obj_id );\r\n\tDbg_Assert( pTargetObj );\r\n\r\n\tbool visible = false;\r\n\tif ( pTargetObj )\r\n\t{\r\n\t\tObj::CModelComponent* pTargetObjModelComponent = GetModelComponentFromObject( pTargetObj );\r\n\t\tMth::Vector sphere = pTargetObjModelComponent->GetModel()->GetBoundingSphere();\r\n\t\tMth::Vector position = sphere;\r\n\t\tposition[3] = 1.0f;\r\n\t\tposition *= pTargetObj->GetMatrix();\r\n\t\tposition += pTargetObj->GetPos();\r\n\t\t//if ( ( Nx::CEngine::sIsVisible( position, sphere[3] ) ) )\r\n\t\tif ( ( Nx::CEngine::sIsVisible( position, 6.0f ) ) ) // TT#2555 (Mick), use a 6 inch radius sphere te ensure we can really see him\r\n\t\t{\r\n\t\t\t// get the cam\r\n\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\tObj::CSkater* pSkater = skate_mod->GetLocalSkater();\r\n\t\t\tDbg_Assert( pSkater );\r\n\t\t\tGfx::Camera* pCurrentCamera = pSkater->GetActiveCamera();\r\n\r\n\t\t\tfloat distance_to_target = Mth::Distance( pCurrentCamera->GetPos(), pTargetObj->GetPos() );\r\n\t\t\tint max_distance;\r\n\t\t\tmp_params->GetInteger( CRCD(0x856fab92,\"max_distance_to_target\"), &max_distance, Script::ASSERT );\r\n\t\t\tif ( distance_to_target < (float)max_distance )\r\n\t\t\t{\r\n\t\t\t\tvisible = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn visible;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CFilmGoal::StartFilming()\r\n{\r\n\tDbg_MsgAssert( m_timeRequired, ( \"StartFilming called on a non-filming goal.\" ) );\r\n\tm_filming = true;\r\n}\r\n\r\n}\t// namespace Game\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/FilmGoal.h",
    "content": "// film goal.\r\n\r\n#ifndef __SK_MODULES_SKATE_FILMGOAL_H__\r\n#define __SK_MODULES_SKATE_FILMGOAL_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <sk/modules/skate/GoalManager.h>\r\n\r\nnamespace Game\r\n{\r\n\r\nclass CFilmGoal : public CGoal\r\n{\r\n\r\npublic:\r\n\t\t\t\t\t\tCFilmGoal( Script::CStruct* pParams );\r\n\tvirtual\t\t\t\t~CFilmGoal();\r\n\r\n\tbool\t\t\t\tActivate();\r\n\tbool\t\t\t\tDeactivate( bool force = false, bool affect_tree = true );\r\n\tbool\t\t\t\tUpdate();\r\n\r\n\tvoid\t\t\t\tCheckpointHit();\r\n\tvoid\t\t\t\tStartFilming();\r\nprotected:\r\n\tbool\t\t\t\ttarget_object_visible();\r\n\r\n\tbool\t\t\t\tm_filming;\r\n\t\r\n\tTmr::Time           m_timeOnCamera;\r\n\tTmr::Time\t\t\tm_timeRequired;\r\n\tTmr::Time\t\t\tm_totalTime;\r\n\r\n\tint\t\t\t\t\tm_numShotsRequired;\r\n\tint\t\t\t\t\tm_numShotsAchieved;\r\n\r\n};\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/FindGapsGoal.cpp",
    "content": "// find x gaps\r\n#include <sk/modules/skate/GoalManager.h>\r\n#include <sk/modules/skate/FindGapsGoal.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/score.h>\r\n\r\n// #include <gel/scripting/utils.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCFindGapsGoal::CFindGapsGoal( Script::CStruct* pParams ) : CGoal( pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCFindGapsGoal::~CFindGapsGoal()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CFindGapsGoal::Activate()\r\n{\r\n\tmp_params->RemoveComponent( CRCD(0x735af2dd,\"completedGaps\") );\r\n\tScript::CStruct* pCompletedGaps = new Script::CStruct();\r\n\tmp_params->AddStructure( CRCD(0x735af2dd,\"completedGaps\"), pCompletedGaps );\r\n\tdelete pCompletedGaps;\r\n\r\n\tmp_params->AddInteger( CRCD(0xf1e59083,\"num_gaps_found\"), 0 );\r\n\tmp_params->AddInteger( CRCD(0x129daa10,\"number_collected\"), 0 );\r\n\r\n\tint num_gaps_to_find;\r\n\tmp_params->GetInteger( CRCD(0xe75c4bbf,\"num_gaps_to_find\"), &num_gaps_to_find, Script::ASSERT );\r\n\tDbg_MsgAssert( num_gaps_to_find > 0, ( \"find gaps goal activated but num_gaps_to_find <= 0!\" ) );\r\n\r\n\treturn CGoal::Activate();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CFindGapsGoal::Deactivate( bool force, bool affect_tree )\r\n{\r\n\treturn CGoal::Deactivate();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CFindGapsGoal::CheckGaps()\r\n{\r\n\t// printf(\"CFindGapsGoal::CheckGaps\\n\");\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = skate_mod->GetLocalSkater();\r\n\r\n\tScript::CStruct* pCompletedGaps;\r\n\tmp_params->GetStructure( CRCD(0x735af2dd,\"completedGaps\"), &pCompletedGaps, Script::ASSERT );\r\n\r\n\tint num_gaps_found;\r\n\tmp_params->GetInteger( CRCD(0xf1e59083,\"num_gaps_found\"), &num_gaps_found, Script::ASSERT );\r\n\r\n\tMdl::Score* pScore = pSkater->GetScoreObject();\r\n\tint numTricks = pScore->GetCurrentTrickCount();\r\n\tbool found_gap = false;\r\n\tfor ( int i = 0; i < numTricks; i++ )\r\n\t{\r\n\t\tif ( pScore->TrickIsGap( i ) )\r\n\t\t{\r\n\t\t\tuint32 gap_name = pScore->GetTrickId( i );\r\n\t\t\tif ( !pCompletedGaps->ContainsComponentNamed( gap_name ) )\r\n\t\t\t{\r\n\t\t\t\tpCompletedGaps->AddInteger( gap_name, 1 );\r\n\t\t\t\tnum_gaps_found++;\r\n\t\t\t\tfound_gap = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tmp_params->AddInteger( CRCD(0xf1e59083,\"num_gaps_found\"), num_gaps_found );\r\n\tmp_params->AddInteger( CRCD(0x129daa10,\"number_collected\"), num_gaps_found );\r\n\r\n\tif ( found_gap )\r\n\t{\r\n\t\tScript::CStruct* pScriptParams = new Script::CStruct();\r\n\t\tpScriptParams->AddChecksum( CRCD(0x9982e501,\"goal_id\"), GetGoalId() );\r\n\t\tScript::RunScript( CRCD(0x851aa6b8,\"goal_find_gaps_found_gap\"), pScriptParams );\r\n\t\tdelete pScriptParams;\r\n\t}\r\n}\r\n\r\n\r\n}\t// namespace Game\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/FindGapsGoal.h",
    "content": "// find x gaps\r\n\r\n#ifndef __SK_MODULES_SKATE_FINDGAPSGOAL_H__\r\n#define __SK_MODULES_SKATE_FINDGAPSGOAL_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <sk/modules/skate/GoalManager.h>\r\n\r\nnamespace Game\r\n{\r\n\r\nclass CFindGapsGoal : public CGoal\r\n{\r\n\r\npublic:\r\n\t\t\t\t\t\tCFindGapsGoal( Script::CStruct* pParams );\r\n\tvirtual\t\t\t\t~CFindGapsGoal();\r\n\r\n\tbool\t\t\t\tActivate();\r\n\tbool\t\t\t\tDeactivate( bool force = false, bool affect_tree = true );\r\n\r\n\tvoid\t\t\t\tCheckGaps();\r\nprotected:\r\n\tint\t\t\t\t\tm_numGapsToFind;\r\n};\r\n\r\n}\t// namespace game\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/GameFlow.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSkate\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tSkate/GameFlow.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t04/27/01\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tDefines various game flows\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <sk/modules/skate/GameFlow.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mdl\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGameFlow::CGameFlow( void )\r\n{\r\n\tmp_gameFlowScript = NULL;\r\n\tmp_tester_script = NULL;\r\n\t\r\n\tm_requestedScript = 0;\r\n\tm_requestNewScript = false;\r\n\tm_paused = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGameFlow::~CGameFlow( void )\r\n{\r\n\tif ( mp_gameFlowScript )\r\n\t\tdelete mp_gameFlowScript;\r\n\t\t\r\n\tif (mp_tester_script)\r\n\t{\r\n\t\tdelete mp_tester_script;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGameFlow::Reset( uint32 scriptChecksum )\r\n{\r\n\tm_requestedScript = scriptChecksum;\r\n\tm_requestNewScript = true;\r\n\tm_paused = false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameFlow::Pause( bool paused )\r\n{\r\n\tbool old = m_paused;\r\n\tm_paused = paused;\r\n\treturn old;\r\n}\r\n\r\nvoid CGameFlow::SetTesterScript(uint32 testerScript, Script::CStruct *p_params)\r\n{\r\n\tif (!mp_tester_script)\r\n\t{\r\n\t\tmp_tester_script=new Script::CScript;\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tmp_tester_script->SetCommentString(\"Created in CGameFlow::SetTesterScript(...)\");\r\n\t\t#endif\r\n\t}\r\n\t\t\r\n\tmp_tester_script->SetScript(testerScript, p_params);\r\n}\r\n\r\n// Returns true if the tester script did exist.\r\n// This is so that the corresponding script command can return true/false, and hence\r\n// messages can say stuff like 'test script killed' or 'no tester script present' if they want.\r\nbool CGameFlow::KillTesterScript()\r\n{\r\n\tif (mp_tester_script)\r\n\t{\r\n\t\tdelete mp_tester_script;\r\n\t\tmp_tester_script=NULL;\r\n\t\treturn true;\r\n\t}\r\n\t\t\r\n\treturn false;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGameFlow::Update()\r\n{\r\n\tif (mp_tester_script)\r\n\t{\r\n\t\tmp_tester_script->Update();\r\n\t}\t\r\n\t\r\n\r\n\t// GJ:  This keeps us from loading a new script\r\n\t// while we're still in the middle of processing the old one\r\n\tif ( m_requestNewScript )\r\n\t{\r\n\t\tm_requestNewScript = false;\r\n\r\n\t\tif ( mp_gameFlowScript )\r\n\t\t\tdelete mp_gameFlowScript;\r\n\r\n\t\tmp_gameFlowScript = new Script::CScript;\r\n\t\tmp_gameFlowScript->SetScript( m_requestedScript );\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tmp_gameFlowScript->SetCommentString(\"Created in CGameFlow::Update()\");\r\n\t\t#endif\r\n\t\t\r\n#ifdef __USER_GARY__\r\n\t\tprintf(\"Resetting to script %s %08x!\\n\", Script::FindChecksumName( m_requestedScript ), (int)mp_gameFlowScript);\r\n#endif\r\n\t}\r\n\r\n\t// if paused, then don't continue the script\r\n\tif ( m_paused )\r\n\t\treturn;\r\n\r\n\tif ( mp_gameFlowScript )\r\n\t{\r\n\t\tif ( mp_gameFlowScript->Update() == Script::ESCRIPTRETURNVAL_FINISHED )\r\n\t\t{\r\n\t\t\tdelete mp_gameFlowScript;\r\n\t\t\tmp_gameFlowScript = NULL;\r\n\t\t}\r\n\r\n\t}\r\n}\r\n\r\n} // namespace Game\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/GameFlow.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSkate\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tSkate/GameFlow.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t04/27/01\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tDefines various game flows\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __MODULES_SKATE_GAMEFLOW_H\r\n#define __MODULES_SKATE_GAMEFLOW_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mdl\r\n{\r\n \r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  CGameFlow  : public Spt::Class\r\n{\r\n\t\r\n\r\n\tpublic:\r\n\t\tCGameFlow();\r\n\t\tvirtual\t\t\t\t\t\t~CGameFlow();\r\n\t\tvoid\t\t\t\t\t\tReset( uint32 script_checksum );\r\n\t\tvoid\t\t\t\t\t\tUpdate();\r\n\t\tbool\t\t\t\t\t\tPause( bool paused );\r\n\r\n\t\tvoid\t\t\t\t\t\tSetTesterScript(uint32 testerScript, Script::CStruct *p_params);\r\n\t\tbool\t\t\t\t\t\tKillTesterScript();\r\n\r\n\tprotected:\r\n\t\tbool\t\t\t\t\t\tm_paused;\r\n\t\tScript::CScript*\t\t\tmp_gameFlowScript;\r\n\t\tbool\t\t\t\t\t\tm_requestNewScript;\r\n\t\tuint32\t\t\t\t\t\tm_requestedScript;\r\n\t\t\r\n\t\tScript::CScript*\t\t\tmp_tester_script;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n} // namespace Mdl\r\n\r\n#endif // __MODULES_SKATE_GAMEFLOW_H"
  },
  {
    "path": "Code/Sk/Modules/Skate/GameMode.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSkate\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tSkate/GameMode.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/07/01\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tDefines various game modes\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// start autoduck documentation\r\n// @DOC gamemode\r\n// @module gamemode | None\r\n// @subindex Scripting Database\r\n// @index script | gamemode\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/modules/frontend/frontend.h>\r\n#include <sk/modules/skate/GameMode.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/GoalManager.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/scripting/skfuncs.h>\r\n#include <sk/objects/skater.h>\t\t   // get player id\r\n#include <sk/components/skaterscorecomponent.h>\r\n#include <sys/config/config.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Game\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGameMode::clear_victorycondition_list()\r\n{\r\n\t\r\n\r\n\tLst::Node<CVictoryCondition> *pNode = m_VictoryConditionList.GetNext();\r\n\twhile(pNode)\r\n\t{\r\n\t\tLst::Node<CVictoryCondition> *pNext = pNode->GetNext();\r\n\t\tpNode->Remove();\r\n\t\tdelete pNode->GetData();\r\n\t\tdelete pNode;\r\n\t\tpNode = pNext;\r\n\t}\r\n\r\n\tDbg_Assert( m_VictoryConditionList.IsEmpty() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGameMode::build_victorycondition_list()\r\n{\r\n\t\r\n\r\n\tclear_victorycondition_list();\r\n\r\n\tScript::CArray* pArray;\r\n\tif ( !m_ModeDefinition.GetArray( CRCD(0x94a24c5e,\"victory_conditions\"), &pArray ) )\r\n\t{\r\n\t\t// no victory conditions found\r\n\t\treturn;\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\t// loop through the victory conditions\r\n\tfor ( uint32 i = 0; i < pArray->GetSize(); i++ )\r\n\t{\r\n\t\tScript::CScriptStructure* pStructure = pArray->GetStructure( i );\r\n\t\tDbg_Assert( pStructure );\r\n\r\n\t\tCVictoryCondition* pVictoryCondition = CreateVictoryConditionInstance( pStructure );\r\n\t\tDbg_Assert( pVictoryCondition );\r\n\t\tm_VictoryConditionList.AddToTail( new Lst::Node<CVictoryCondition>( pVictoryCondition ) );\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\t// TODO: Scan for combinations that don't make sense\r\n\t// (i.e. highest score AND best combo)\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::remove_component_if_exists( const char* p_component_name, Script::CScriptStructure* p_params )\r\n{\r\n\tif ( p_params->ContainsComponentNamed( p_component_name ) )\r\n\t{\r\n\t\tm_ModeDefinition.RemoveComponent( Script::GenerateCRC( p_component_name ) );\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGameMode::CGameMode()\r\n{\r\n\t\r\n\r\n\tReset();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGameMode::~CGameMode()\r\n{\r\n\t\r\n\r\n\tclear_victorycondition_list();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nTmr::Time CGameMode::GetTimeLeft()\r\n{\r\n\r\n\tCGoalManager* pGoalManager = Game::GetGoalManager();\r\n\tuint32\tnameChecksum = ConvertNetNameChecksum(GetNameChecksum());\r\n\tCGoal* pGoal = pGoalManager->GetGoal(nameChecksum,false);\r\n\r\n\tif( !pGoal )\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\r\n\treturn pGoal->GetTimeLeft();\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCGameMode::SetTimeLeft( Tmr::Time time_left )\r\n{\r\n\tCGoalManager* pGoalManager = Game::GetGoalManager();\r\n\tuint32\tnameChecksum = ConvertNetNameChecksum(GetNameChecksum());\r\n\tCGoal* pGoal = pGoalManager->GetGoal(nameChecksum,false);\r\n\r\n\tif( pGoal )\r\n\t{\r\n\t\tpGoal->SetTimer( time_left );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCGameMode::EndConditionsMet()\r\n{\r\n\t// this checks whether time has run out\r\n\tif ( ShouldUseClock() )\r\n\t{\r\n\t\tCGoalManager* pGoalManager = Game::GetGoalManager();\r\n\r\n\t\tif( pGoalManager->GetNumActiveGoals( true ) > 0 && pGoalManager->GetGoalTime() <= 0 )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\r\n\tuint32 i;\r\n\tint num_terminals = 0;\r\n\tint num_completed_terminals = 0;\r\n\r\n\t// TODO:  Allow boolean conditions (&'s and |'s)\r\n\r\n\t// Look through the victory conditions also\r\n\tfor ( i = 0; i < m_VictoryConditionList.CountItems(); i++ )\r\n\t{\r\n\t\tLst::Node<CVictoryCondition> *pNode = m_VictoryConditionList.GetItem( i );\r\n\r\n\t\tif (pNode->GetData()->IsTerminal())\r\n\t\t{\r\n\t\t\tnum_terminals++;\r\n\t\t\t\r\n\t\t\tif ( pNode->GetData()->ConditionComplete() )\r\n\t\t\t{\r\n\t\t\t\tnum_completed_terminals++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// If all of the terminal ones have been met,\r\n\t// then we've also met our end conditions\r\n\tif ( num_terminals && ( num_completed_terminals == num_terminals ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::ShouldUseClock()\r\n{\r\n\tint time_limit;\r\n\t\r\n\tif(\t( GetNameChecksum() == CRCD(0x5d32129c,\"king\")) ||\r\n\t\t( GetNameChecksum() == CRCD(0x6ef8fda0,\"netking\")) ||\r\n\t\t( GetNameChecksum() == CRCD(0xf135ecb6,\"scorechallenge\")) ||\r\n\t\t( GetNameChecksum() == CRCD(0x1498240a,\"netscorechallenge\")) ||\r\n\t\t// K: Added check for creategoals to fix bug where end of run triggered straight away on\r\n\t\t// entering a level in creategoals mode.\r\n\t\t( GetNameChecksum() == CRCD(0xe45f0ca2,\"creategoals\")) ||\r\n\t\t( GetNameChecksum() == CRCD(0x3d6d444f,\"firefight\")) ||\r\n\t\t( GetNameChecksum() == CRCD(0xbff33600,\"netfirefight\")))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tm_ModeDefinition.GetInteger( CRCD(0x8d38a280,\"default_time_limit\"), &time_limit, true );\r\n\treturn ( time_limit != 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::ShouldStopAtZero()\r\n{\r\n\tMdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\r\n\tif( skate_mod->IsMultiplayerGame() == false )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif( ShouldUseClock())\r\n\t{\r\n\t\tint should_stop;\r\n\r\n\t\tm_ModeDefinition.GetInteger( CRCD(0x48e748b5,\"stop_at_zero\"), &should_stop, true );\r\n\t\treturn ( should_stop == 1 );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCGameMode::ShouldAccumulateScore()\r\n{\r\n\tint should_accumulate_score;\r\n\tm_ModeDefinition.GetInteger( CRCD(0xc1f5864b,\"accumulate_score\"), &should_accumulate_score, true );\r\n\treturn should_accumulate_score;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCGameMode::ShouldTrackBestCombo()\r\n{\r\n\tint should_track;\r\n\tif( m_ModeDefinition.GetInteger( CRCD(0xd57c16ba,\"track_best_combo\"), &should_track, false ) == false )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn should_track;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\r\nCGameMode::SetScoreAccumulation( bool should_accumulate )\r\n{\r\n\tm_ModeDefinition.AddInteger( CRCD(0xc1f5864b,\"accumulate_score\"), should_accumulate );\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGameMode::SetScoreFrozen( bool is_frozen )\r\n{\r\n\tm_ModeDefinition.AddInteger( CRCD(0x78fb9f04,\"score_frozen\"), is_frozen );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\r\nCGameMode::SetScoreDegradation( bool should_degrade )\r\n{\r\n\tm_ModeDefinition.AddInteger( CRCD(0xca37e639,\"degrade_score\"), should_degrade );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\r\nCGameMode::SetNumTeams( int num_teams )\r\n{\r\n\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tm_ModeDefinition.AddInteger( CRCD(0x2ebe6cd1,\"num_teams\"), num_teams );\r\n\tif( GetNameChecksum() == CRCD(0x1c471c60,\"netlobby\") )\r\n\t{\r\n\t\tgamenet_man->CreateTeamFlags( num_teams );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::ScoreFrozen()\r\n{\r\n\tint score_is_frozen;\r\n\tm_ModeDefinition.GetInteger( CRCD(0x78fb9f04,\"score_frozen\"), &score_is_frozen, true );\r\n\treturn ( score_is_frozen != 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCGameMode::ShouldTrackTrickScore()\r\n{\r\n\tint should_track_trick_score;\r\n\tm_ModeDefinition.GetInteger( CRCD(0x47f763ff,\"track_trick_score\"), &should_track_trick_score, true );\r\n\treturn should_track_trick_score;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCGameMode::ShouldDegradeScore()\r\n{\r\n\tint should_degrade_score;\r\n\tm_ModeDefinition.GetInteger( CRCD(0xca37e639,\"degrade_score\"), &should_degrade_score, true );\r\n\treturn should_degrade_score;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::ShouldRunIntroCamera()\r\n{\r\n\tint should_run_intro_camera;\r\n\tif (Config::CD())\r\n\t{\r\n\t\tm_ModeDefinition.GetInteger( CRCD(0xe2355b5e,\"should_run_intro_camera\"), &should_run_intro_camera, true );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_ModeDefinition.GetInteger( CRCD(0xea0d7454,\"should_run_intro_camera_noncd\"), &should_run_intro_camera, true );\r\n\t}\t\r\n\treturn should_run_intro_camera;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::ShouldShowRankingScreen()\r\n{\r\n\tint should_show_ranking_screen;\r\n\tm_ModeDefinition.GetInteger( CRCD(0xf18020f1,\"show_ranking_screen\"), &should_show_ranking_screen, true );\r\n\treturn should_show_ranking_screen;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCGameMode::IsTimeLimitConfigurable()\r\n{\r\n\t\r\n\t\r\n\tuint32 time_limit_type;\r\n\tm_ModeDefinition.GetChecksum( CRCD(0x7d5e4bc1,\"time_limit_type\"), &time_limit_type, true );\r\n\tDbg_MsgAssert( time_limit_type == CRCD(0x2b75d083,\"config\") || time_limit_type == CRCD(0x613631cd,\"fixed\"),( \"Unrecognized time limit type\" ));\r\n\treturn ( time_limit_type == CRCD(0x2b75d083,\"config\") );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCGameMode::IsTeamGame()\r\n{\r\n\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\treturn ( gamenet_man->InNetGame() && ( NumTeams() > 0 ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\r\nCGameMode::NumTeams()\r\n{\r\n\tint num_teams;\r\n\tm_ModeDefinition.GetInteger( CRCD( 0x2ebe6cd1, \"num_teams\" ), &num_teams, true );\r\n\treturn num_teams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCGameMode::ShouldTimerBeep()\r\n{\r\n\tint beeps;\r\n\tm_ModeDefinition.GetInteger( CRCD(0x35c8073,\"timer_beeps\"), &beeps, true );\r\n\treturn beeps;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\r\nCGameMode::GetTimeLimit()\r\n{\r\n\t\r\n\tint time_limit;\r\n\tm_ModeDefinition.GetInteger( CRCD(0x8d38a280,\"default_time_limit\"), &time_limit, true );\r\n\treturn (uint32)time_limit;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\t\tCGameMode::GetTargetScore( void )\r\n{\r\n\tuint32 i;\r\n\t// Look through the victory conditions also\r\n\tfor ( i = 0; i < m_VictoryConditionList.CountItems(); i++ )\r\n\t{\r\n\t\tLst::Node<CVictoryCondition> *pNode = m_VictoryConditionList.GetItem( i );\r\n\r\n\t\tCScoreReachedVictoryCondition* condition;\r\n\r\n\t\tcondition = static_cast <CScoreReachedVictoryCondition*> (pNode->GetData());\r\n\t\tif( condition )\r\n\t\t{\r\n\t\t\treturn condition->GetTargetScore();\r\n\t\t}\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CGameMode::GetInitialNumberOfPlayers()\r\n{\r\n\t\r\n\r\n\tint num_players;\r\n\tm_ModeDefinition.GetInteger( CRCD(0x6dc3d6f1,\"initial_players\"), &num_players, true );\r\n\treturn num_players;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCGameMode::SetMaximumNumberOfPlayers( uint32 num_players )\r\n{\r\n\tm_ModeDefinition.AddInteger( CRCD(0x4d42e61d,\"max_players\"), num_players );\r\n\tDbg_Printf( \"****** SETTING MAX PLAYERS TO %d\\n\", num_players );\r\n//\tDumpUnwindStack( 20, 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CGameMode::GetMaximumNumberOfPlayers()\r\n{\r\n\tint num_players;\r\n\tm_ModeDefinition.GetInteger( CRCD(0x4d42e61d,\"max_players\"), &num_players, true );\r\n\treturn num_players;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::ScreenMode CGameMode::GetScreenMode()\r\n{\r\n\t\r\n\r\n\tuint32 checksum;\r\n\r\n\tm_ModeDefinition.GetChecksum( CRCD(0x9bab2eae,\"screenmode\"), &checksum, true );\r\n\tswitch (checksum)\r\n\t{\r\n\t\tcase 0x3558d8e6: // single\r\n\t\t\treturn Nx::vONE_CAM;\r\n\t\t\tbreak;\r\n\t\tcase 0x9d65d0e7: // horse\r\n\t\t\treturn Nx::vHORSE1;\r\n\t\t\tbreak;\r\n\t\tcase 0x06ab02f2: // splitscreen\r\n\t\t{\r\n\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\tPrefs::Preferences* pPreferences;\r\n\r\n\t\t\tpPreferences = skate_mod->GetSplitScreenPreferences();\r\n\t\t\tDbg_Assert(pPreferences);\r\n\r\n\t\t\tScript::CScriptStructure* pStructure = pPreferences->GetPreference( CRCD(0x6f82c71e,\"viewport_type\") );\r\n\t\t\tDbg_Assert(pStructure);\r\n\r\n\t\t\tuint32 checksum;\r\n\t\t\tpStructure->GetChecksum( CRCD(0x21902065,\"checksum\"), &checksum, true );\r\n\t\t\tif ( checksum == CRCD(0x92f5b4cb,\"viewport_type_vertical\") )\r\n\t\t\t{\r\n\t\t\t\treturn Nx::vSPLIT_V;\r\n\t\t\t}\r\n\t\t\telse if ( checksum == CRCD(0x7c442511,\"viewport_type_horizontal\") )\r\n\t\t\t{\r\n\t\t\t\treturn Nx::vSPLIT_H;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\treturn Nx::vSPLIT_V;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t\treturn (Nx::ScreenMode) 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::IsFrontEnd()\r\n{\r\n\t\r\n\r\n\tint is_frontend;\r\n\tm_ModeDefinition.GetInteger( CRCD( 0xa6479767, \"is_frontend\" ), &is_frontend, true );\r\n\treturn is_frontend;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::IsParkEditor()\r\n{\r\n\t\r\n\r\n\tint is_parkeditor;\r\n\tm_ModeDefinition.GetInteger( CRCD(0x66d9ddb9,\"is_parkeditor\"), &is_parkeditor, true );\r\n\treturn is_parkeditor;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tCGameMode::GetFireballLevel()\r\n{\r\n\tint level;\r\n\r\n\tlevel = 3;\r\n\tm_ModeDefinition.GetInteger( CRCD(0xce87e4e3,\"fireball_level\"), &level );\r\n\t\r\n\treturn level;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::IsTrue( const char* pFieldName )\r\n{\r\n\t\r\n\r\n\tint field_value;\r\n\tm_ModeDefinition.GetInteger( pFieldName, &field_value, true );\r\n\treturn field_value;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::IsTrue( uint32 checksum )\r\n{\r\n\t\r\n\r\n\tint field_value;\r\n\tm_ModeDefinition.GetInteger( checksum, &field_value, true );\r\n\treturn field_value;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Returns the checksum of the name of the game mode definition structure\r\n// these structures are defined in gamemode.q, an example would be \"graffiti\"\r\n// however, you should NOT use these names to check for things to do\r\n// as there might be mutliple instance of similar modes (like, graffiti and netgraffiti)\r\n// so you should use the fields within the structure, \r\n// use the IsTrue methods above, like IsTrue(\"is_graffiti\");  \r\n\r\nuint32 CGameMode::GetNameChecksum()\r\n{\r\n\t\r\n\r\n\tuint32 checksum = 0;\r\n\tm_ModeDefinition.GetChecksum(CRCD(0xa1dc81f9,\"name\"), &checksum);\r\n\treturn checksum;\r\n}\r\n\r\n\t\t\t\t\t \r\n// if the checksum is the name of a net game, then return the name of the regular equivalent\t\t\t\t\t \r\n// used by the time functions, wehre we need to know what type of game it is\r\n// and not if it's net or not\r\nuint32 CGameMode::ConvertNetNameChecksum(uint32 nameChecksum)\r\n{\r\n\r\n\tuint32 checksum = nameChecksum;\r\n\t\r\n\tif( nameChecksum == CRCD(0x30c2ffa3,\"nettrickattack\"))\r\n\t{\r\n\t\tchecksum =  CRCD( 0xf9283ee7,\"trickattack\" );\r\n\t}\r\n\telse if( nameChecksum == CRCD( 0x5e2ea50c, \"netgraffiti\" ))\r\n\t{\r\n\t\tchecksum = CRCD(0xc8a82b5a, \"graffiti\");\r\n\t}\r\n\telse if( nameChecksum == CRCD( 0xc50affd0, \"netcombomambo\" ))\r\n\t{\r\n\t\tchecksum = CRCD(0x23eb3da3, \"combomambo\");\r\n\t}\r\n\telse if ( nameChecksum == CRCD( 0xf9d5d933, \"netslap\" ))\r\n\t{\r\n\t\tchecksum = CRCD( 0xca1f360f, \"slap\" );\r\n\t}\r\n\telse if ( nameChecksum == CRCD(0x6ef8fda0, \"netking\" ) )\r\n\t{\r\n\t\tchecksum = CRCD( 0x5d32129c,\"king\" );\r\n\t}\r\n\telse if( nameChecksum == CRCD(0xbff33600,\"netfirefight\") )\r\n\t{\r\n\t\tchecksum = CRCD(0x3d6d444f,\"firefight\");\r\n\t}\r\n\telse if( nameChecksum == CRCD(0x6c5ff266,\"netctf\") )\r\n\t{\r\n\t\tchecksum = CRCD(0xa5ad2b0b,\"ctf\");\r\n\t}\r\n\treturn checksum;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint compFunc( const void *arg1, const void *arg2 )\r\n{\r\n\tSRanking* pRanking1 = (SRanking*)arg1;\r\n\tSRanking* pRanking2 = (SRanking*)arg2;\r\n\r\n\tint score1 = pRanking1->pScore->GetTotalScore();\r\n\tint score2 = pRanking2->pScore->GetTotalScore();\r\n\r\n\tif ( score1 == score2 )\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\telse if ( score1 < score2 )\r\n\t{\r\n\t\treturn 1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn -1;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGameMode::CalculateRankings( SRanking* p_player_rankings )\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr( p_player_rankings );\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tfor ( uint32 skater_num = 0; skater_num < skate_mod->GetNumSkaters(); skater_num++ )\r\n\t{\r\n\t\tObj::CSkater* pSkater = skate_mod->GetSkater(skater_num);\r\n\t\tDbg_AssertPtr( pSkater );\r\n\t\t\r\n\t\tObj::CSkaterScoreComponent* pSkaterScoreComponent = GetSkaterScoreComponentFromObject(pSkater);\r\n\t\tDbg_Assert( pSkaterScoreComponent );\r\n\t\t\r\n\t\tp_player_rankings[skater_num].obj_id = pSkater->GetID();\r\n\t\tp_player_rankings[skater_num].pScore = pSkaterScoreComponent->GetScore();\r\n\t\tp_player_rankings[skater_num].ranking = 0;\r\n\t}\r\n\r\n\t// sort them by score\r\n\t// TODO:  make the sorting function variable depending on the game mode\r\n\tqsort( &p_player_rankings[0], skate_mod->GetNumSkaters(), sizeof(SRanking), compFunc );\r\n\r\n\tfor ( uint32 i = 0; i < skate_mod->GetNumSkaters(); i++ )\r\n\t{\r\n\t\tif ( (i != 0) && (p_player_rankings[i].pScore->GetTotalScore() == p_player_rankings[i-1].pScore->GetTotalScore()) )\r\n\t\t{\r\n\t\t\tp_player_rankings[i].ranking = p_player_rankings[i-1].ranking;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_player_rankings[i].ranking = i + 1;\r\n\t\t}\r\n\r\n\t\tprintf(\"ranking = skater=%d score=%d ranking=%d\\n\", p_player_rankings[i].obj_id, p_player_rankings[i].pScore->GetTotalScore(), p_player_rankings[i].ranking );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::IsWinner( uint32 skater_num )\r\n{\r\n\t\r\n\r\n\tint completed_count[Mdl::Skate::vMAX_SKATERS];\r\n\tuint32 j;\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tfor ( j = 0; j < skate_mod->GetNumSkaters(); j++ )\r\n\t{\r\n\t\tcompleted_count[j] = 0;\r\n\t\t\r\n\t\tfor ( uint32 i = 0; i < m_VictoryConditionList.CountItems(); i++ )\r\n\t\t{\r\n\t\t\tLst::Node<CVictoryCondition> *pNode = m_VictoryConditionList.GetItem( i );\r\n\t\t\t\r\n\t\t\tif ( pNode->GetData()->IsWinner( j ) )\r\n\t\t\t{\r\n\t\t\t\tcompleted_count[j]++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( j = 0; j < skate_mod->GetNumSkaters(); j++ )\r\n\t{\r\n\t\tif ( skater_num != j && completed_count[skater_num] < completed_count[j] )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::Reset()\r\n{\r\n\tclear_victorycondition_list();\r\n\t\r\n\treturn LoadGameType( CRCD(0x34861a16,\"freeskate\") );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::LoadGameType( uint32 gameTypeChecksum )\r\n{\r\n\tGameNet::Manager* gamenet_man;\r\n\tint max_players;\r\n\t\r\n\tmax_players = Mdl::Skate::vMAX_SKATERS;\r\n\tgamenet_man = GameNet::Manager::Instance();\r\n\tif( gamenet_man && gamenet_man->InNetGame())\r\n\t{\r\n\t\tmax_players = GetMaximumNumberOfPlayers();\r\n\t}\r\n\r\n\t// Reset the current game mode first\r\n\tm_ModeDefinition.Clear();\r\n\r\n\tScript::CArray* pArray = Script::GetArray( CRCD(0xca5f7ffb,\"mode_info\"), Script::ASSERT );\r\n\r\n\tfor ( uint32 i = 0; i < pArray->GetSize(); i++ )\r\n\t{\r\n\t\tScript::CScriptStructure* pStructure = pArray->GetStructure( i );\r\n\t\tDbg_Assert( pStructure );\r\n\r\n\t\tuint32 checksum;\r\n\t\tpStructure->GetChecksum( CRCD(0x21902065,\"checksum\"), &checksum, true );\r\n\t\t\r\n\t\tif ( checksum == gameTypeChecksum )\r\n\t\t{\r\n\r\n\t\t\tconst char* definition;\r\n\t\t\tpStructure->GetText( CRCD(0x97cfd027,\"definition\"), &definition, true );\r\n\r\n\t\t\tScript::CScriptStructure* pRefersToStructure = Script::GetStructure( definition, Script::ASSERT );\r\n\t\t\tm_ModeDefinition.AppendStructure( pRefersToStructure );\r\n\r\n\t\t\t// clears the existing lists, as we're about to rebuild them\r\n\t\t\tclear_victorycondition_list();\r\n\t\t\t\r\n\t\t\t// rebuilds the victory condition list based on the current game mode\r\n\t\t\tbuild_victorycondition_list();\r\n\r\n\t\t\tif( gamenet_man && gamenet_man->InNetGame())\r\n\t\t\t{\r\n\t\t\t\tSetMaximumNumberOfPlayers( max_players );\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert( 0,( \"Unrecognized game type %08x %s\", gameTypeChecksum, Script::FindChecksumName( gameTypeChecksum ) ));\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGameMode::OverrideOptions( Script::CScriptStructure *pParams )\r\n{\r\n\t// first we should get rid of any named components that are duplicates\r\n\t// the trick may be not to use any named components?\r\n\tremove_component_if_exists( \"time_limit_type\", pParams );\r\n\tremove_component_if_exists( \"victory_condition_type\", pParams );\r\n\tremove_component_if_exists( \"screenmode\", pParams );\r\n\t\r\n\tm_ModeDefinition.AppendStructure( pParams );\r\n\t\r\n\t// clears the existing lists, as we're about to rebuild them\r\n\tclear_victorycondition_list();\r\n\r\n\t// rebuilds the victory condition list based on the current game mode\r\n\tbuild_victorycondition_list();\r\n\r\n//#ifdef __USER_GARY__\r\n#if 1\r\n\tScript::PrintContents( &m_ModeDefinition );\r\n#endif\r\n\t\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | OverrideGameModeOptions | \r\nbool ScriptOverrideGameModeOptions( Script::CScriptStructure *pParams, Script::CScript *pScript )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tCGameMode* pGameMode = skate_mod->GetGameMode();\r\n\treturn pGameMode->OverrideOptions( pParams );\r\n}\r\n\r\n} // namespace Game\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/GameMode.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSkate\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tSkate/GameMode.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/07/01\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tDefines various game modes\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __MODULES_SKATE_GAMEMODE_H\r\n#define __MODULES_SKATE_GAMEMODE_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/list.h>\r\n#include <gel/scripting/struct.h>\r\n#include <sk/modules/skate/victorycond.h>\r\n#include <gfx/nxviewman.h>\r\n#include <sys/timer.h>\r\n\r\n#ifndef\t__SCRIPTING_UTILS_H\r\n#include <gel/scripting/utils.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mdl\r\n{\r\n\t// forward declaration\r\n\tclass Score;\r\n}\r\n\r\nnamespace Game\r\n{\r\n \r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstruct SRanking\r\n{\r\n\tint\t\t\t\tobj_id;\r\n\tint\t\t\t\tranking;\r\n\tMdl::Score*\t\tpScore;\r\n};\r\n\r\nclass  CGameMode  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvGAMEMODE_NETLOBBY = 0x1c471c60,\t\t// \"netlobby\"\r\n\t};\r\n\t\t\t\r\npublic:\r\n\tCGameMode();\r\n\tvirtual\t\t\t\t\t\t~CGameMode();\r\n\r\n\t// clears the game mode to default, which is effectively \"freeskate\"\r\n\tbool\t\t\t\t\t\tReset();\r\n\r\n\t// loads a game mode, as defined in a script\r\n\tbool\t\t\t\t\t\tLoadGameType( uint32 game_type );\r\n\tbool\t\t\t\t\t\tOverrideOptions( Script::CScriptStructure *pParams );\r\n\t\r\npublic:\r\n\tvoid\t\t\t\t\t\tCalculateRankings( SRanking* p_player_rankings );\r\n\tvoid\t\t\t\t\t\tSetScoreFrozen( bool is_frozen );\r\n\tbool\t\t\t\t\t\tScoreFrozen();\r\n\tvoid\t\t\t\t\t\tSetScoreAccumulation( bool should_accumulate );\r\n\tvoid\t\t\t\t\t\tSetScoreDegradation( bool should_degrade );\r\n\tvoid\t\t\t\t\t\tSetNumTeams( int num_teams );\r\n\tbool\t\t\t\t\t\tShouldAccumulateScore();\r\n\tbool\t\t\t\t\t\tShouldTrackBestCombo();\r\n\tbool\t\t\t\t\t\tShouldTrackTrickScore();\r\n\tbool\t\t\t\t\t\tShouldDegradeScore();\r\n\tbool\t\t\t\t\t\tShouldUseClock();\r\n\tbool\t\t\t\t\t\tShouldStopAtZero();\r\n\tbool\t\t\t\t\t\tShouldRunIntroCamera();\r\n\tbool\t\t\t\t\t\tShouldShowRankingScreen();\r\n\tbool\t\t\t\t\t\tIsTeamGame();\r\n\tint\t\t\t\t\t\t\tNumTeams();\r\n\tbool\t\t\t\t\t\tIsTimeLimitConfigurable();\r\n\tbool\t\t\t\t\t\tShouldTimerBeep();\r\n\tuint32\t\t\t\t\t\tGetTimeLimit();\r\n\tuint32\t\t\t\t\t\tGetTargetScore();\r\n\tuint32\t\t\t\t\t\tGetInitialNumberOfPlayers();\r\n\tuint32\t\t\t\t\t\tGetMaximumNumberOfPlayers();\r\n\tvoid\t\t\t\t\t\tSetMaximumNumberOfPlayers( uint32 num_players );\r\n\tbool\t\t\t\t\t\tEndConditionsMet();\r\n\tTmr::Time\t\t\t\t\tGetTimeLeft();\r\n\tvoid\t\t\t\t\t\tSetTimeLeft( Tmr::Time time_left );\r\n\tbool\t\t\t\t\t\tIsWinner( uint32 skater_num );\r\n\tNx::ScreenMode\t\t\t\tGetScreenMode();\r\n\tbool\t\t\t\t\t\tIsFrontEnd();\r\n\tbool\t\t\t\t\t\tIsParkEditor();\r\n\r\n\tuint32 \t\t\t\t\t\tGetNameChecksum();\r\n\tuint32 \t\t\t\t\t\tConvertNetNameChecksum(uint32 nameChecksum);\r\n\t\r\n\tint\t\t\t\t\t\t\tGetFireballLevel();\r\n\r\n\t// for generic tests, like \"is career mode\"\r\n\tbool\t\t\t\t\t\tIsTrue( const char* pFieldName );\r\n\tbool\t\t\t\t\t\tIsTrue( uint32 checksum );\r\n\t\r\n\tvoid\t\t\t\t\t\tPrintContents()\r\n\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\tScript::PrintContents(&m_ModeDefinition);\r\n#endif\t\r\n\t}\r\n\r\nprotected:\r\n\tvoid\t\t\t\t\t\tclear_victorycondition_list();\r\n\tvoid\t\t\t\t\t\tbuild_victorycondition_list();\r\n\tbool\t\t\t\t\t\tremove_component_if_exists( const char* p_component_name, Script::CScriptStructure* p_params );\r\n\t\r\nprotected:\r\n\tScript::CScriptStructure\tm_ModeDefinition;\r\n\t\r\n\t// for determining who is the winner, as well\r\n\t// as ending the game before time has run out\r\n\tLst::Head<CVictoryCondition>\tm_VictoryConditionList;\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool ScriptOverrideGameModeOptions( Script::CScriptStructure *pParams, Script::CScript *pScript );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n} // namespace Game\r\n\r\n#endif // __MODULES_SKATE_GAMEMODE_H"
  },
  {
    "path": "Code/Sk/Modules/Skate/Goal.cpp",
    "content": "// start autoduck documentation\r\n// @DOC goal\r\n// @module goal | None\r\n// @subindex Scripting Database\r\n// @index script | goal\r\n\t\t\t\t\t\t\t   \r\n#include <sk/modules/skate/goalmanager.h>\r\n\r\n#include <sk/modules/skate/gamemode.h>\r\n\r\n#include <core/string/stringutils.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/string.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n\t\t\t\t\t\t\t\t\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/trickobject.h>\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/objects/playerprofilemanager.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skaterendruncomponent.h>\r\n#include <sk/components/skaterscorecomponent.h>\r\n\t\t\t\t\t   \r\n#include <sk/modules/skate/score.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/scripting/skfuncs.h>\r\n\r\n\r\nnamespace Front\r\n{\r\n    extern void HideTimeTHPS4();\r\n}\r\n\r\nnamespace Game\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGoalLink::CGoalLink()\r\n{\r\n\tm_relative = 0;\r\n\tmp_next = NULL;\r\n\tm_beaten = false;\r\n}\r\n\r\nCGoalLink::~CGoalLink()\r\n{\r\n\t// nothing yet\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGoal::CGoal( Script::CStruct* pParams ) : Lst::Node<CGoal>( this )\r\n{\r\n\tmp_children = new Game::CGoalLink();\r\n\tmp_parents = new Game::CGoalLink();\r\n\t\r\n\tm_active = false;\r\n    m_hasSeen = false;\r\n    m_paused = false;\r\n    m_unlimitedTime = true;\r\n    m_isbeat = false;\r\n\tm_netIsBeat = false;\r\n\tm_beatenFlags = 0;\r\n\tm_teamBeatenFlags = 0;\r\n\tm_isselected = false;\r\n\tm_isInitialized = false;\r\n\r\n\tm_numTimesLost = 0;\r\n\tm_numTimesWon = 0;\r\n\tm_numTimesStarted = 0;\r\n\r\n\tm_deactivateOnExpire = true;\r\n\r\n    m_timeLeft  = 0;\r\n\r\n\tm_chapter = m_stage = -1;\r\n\r\n\tmp_params = new Script::CStruct;\r\n\tmp_params->AppendStructure( pParams );\r\n\r\n\tmp_goalPed = new Game::CGoalPed( mp_params );\r\n\r\n\tmp_goalFlags = new Script::CStruct;\r\n    \r\n\tm_numflags = 0;\r\n    m_flagsSet = 0;\r\n\r\n\tm_elapsedTime = 0;\r\n\tm_elapsedTimeRecord = vINT32_MAX;\r\n\tm_winScoreRecord = 0;\r\n\r\n\tm_endRunType = vGOALENDOFRUN;\r\n\r\n    // set the level number\r\n    Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n    Obj::CSkaterCareer* pCareer = skate_mod->GetCareer();\r\n    m_levelNum = pCareer->GetLevel();\r\n    \r\n\tCreateGoalFlags( pParams );\r\n\r\n\tif ( pParams->ContainsFlag( CRCD( 0x4ab5f14, \"single_timer\" ) ) )\r\n\t{\r\n\t\t// Dbg_MsgAssert( mp_children->m_relative, ( \"single_timer flag used on a goal without children\" ) );\r\n\t\tm_inherited_flags |= GOAL_INHERITED_FLAGS_ONE_TIMER;\r\n\t}\r\n\r\n\tif ( pParams->ContainsFlag( CRCD( 0xc6b4258f, \"retry_stage\" ) ) )\r\n\t{\r\n\t\tm_inherited_flags |= GOAL_INHERITED_FLAGS_RETRY_STAGE;\r\n\t}\r\n    \r\n    // TODO: make goal lock stuff work right\r\n\tif ( pParams->ContainsFlag( vUNLOCKED_BY_ANOTHER ) )\r\n    {\r\n        m_isLocked = true;\r\n    }\r\n    else if ( pParams->ContainsFlag( vPRO_GOAL ) )\r\n    {\r\n        m_isLocked = true;\r\n    }\r\n/*\telse if ( pParams->ContainsFlag( vPRO_CHALLENGE ) )\r\n\t{\r\n\t\tm_isLocked = true;\r\n\t}\r\n*/\r\n    else\r\n    {\r\n        m_isLocked = false;\r\n    }\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::Init()\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\r\n\t// overwrite any params with difficulty level params\r\n\tAppendDifficultyLevelParams();\r\n\r\n\t// make sure there's a goal description so that the intro cam anims can\r\n\t// be killed and Gary will be happy\r\n\tDbg_MsgAssert( mp_params->ContainsComponentNamed( CRCD(0xc5d7e6b,\"goal_description\") ), ( \"No goal description defined for %s\\n\", Script::FindChecksumName( GetGoalId() ) ) );\r\n\t\r\n\tRunCallbackScript( vINIT );\r\n\tReplaceTrickText();\r\n\tm_isInitialized = true;\r\n\t\r\n\t// Dan, TT12965.  If a server switched between time limit and capture limit ctf games, m_unlimitedTime was not being reset to true.  Thus, ShouldExpire\r\n\t// was returning true during the capture limit game, if the time on the previous time limit game had been allowed to run down.\r\n\tint unlimited_time = 0;\r\n\tmp_params->GetInteger( CRCD(0xf0e712d2,\"unlimited_time\"), &unlimited_time );\r\n\tif ( unlimited_time )\r\n\t{\r\n\t\tm_unlimitedTime = true;\r\n\t}\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::AddParent( uint32 id )\r\n{\r\n\t// printf(\"adding parents\\n\");\r\n\tif ( mp_parents->m_relative == 0 )\r\n\t{\r\n\t\tmp_parents->m_relative = id;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGame::CGoalLink* p_parent = new Game::CGoalLink();\r\n\t\tp_parent->m_relative = id;\r\n\t\tp_parent->mp_next = mp_parents;\r\n\t\tmp_parents = p_parent;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::CreateGoalFlags( Script::CStruct* pParams )\r\n{\r\n    // set any goal flags specified in the params\r\n    Script::CArray *pTempArray;\r\n    mp_goalFlags->Clear();\r\n\tm_numflags = 0;\r\n\tif ( pParams->GetArray( CRCD(0xcc3c4cc4,\"goal_flags\"), &pTempArray ) )\r\n    {\r\n        for ( uint32 c = 0; c < pTempArray->GetSize(); c++)\r\n        {\r\n            mp_goalFlags->AddInteger( pTempArray->GetNameChecksum( c ), 0 );\r\n            m_numflags++;\r\n        }\r\n    }\r\n\tmp_params->AddInteger( CRCD(0xb3790f33,\"num_flags\"), m_numflags );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::SetInheritableFlags( int recurse_level )\r\n{\r\n\t// printf(\"SetInheritableFlags called on %s\\n\", Script::FindChecksumName( GetGoalId() ) );\r\n\tDbg_MsgAssert( recurse_level < 100, ( \"SetInheritableFlags recursed too much\" ) );\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tCGoalLink* p_child = mp_children;\r\n\twhile ( p_child && p_child->m_relative != 0 )\r\n\t{\r\n\t\tCGoal *pGoal = pGoalManager->GetGoal( p_child->m_relative );\r\n\t\tif ( pGoal )\r\n\t\t{\r\n\t\t\tpGoal->m_inherited_flags |= m_inherited_flags;\r\n\t\t\tpGoal->SetInheritableFlags( recurse_level + 1 );\r\n\t\t}\r\n\t\tp_child = p_child->mp_next;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::AddChild( uint32 id )\r\n{\r\n\t// printf(\"adding child\\n\");\t\r\n\t// any current children?\r\n\tif ( mp_children->m_relative == 0 )\r\n\t{\r\n\t\tmp_children->m_relative = id;\r\n\t}\r\n\telse\r\n\t{\t\t\r\n\t\t// make sure this child isn't already in the list\r\n\t\tbool found = false;\r\n\t\tGame::CGoalLink* p_test = mp_children;\r\n\t\twhile ( p_test && p_test->m_relative != 0 )\r\n\t\t{\r\n\t\t\tif ( p_test->m_relative == id )\r\n\t\t\t{\r\n\t\t\t\tfound = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tp_test = p_test->mp_next;\r\n\t\t}\r\n\t\t\r\n\t\tif ( found )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"AddChild failed.  %s already a child of %s\\n\", Script::FindChecksumName( id ), Script::FindChecksumName( GetGoalId() ) ) );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// add new child to head of list\r\n\t\t\tGame::CGoalLink* p_child = new Game::CGoalLink();\r\n\t\t\tp_child->m_relative = id;\r\n\t\t\tp_child->mp_next = mp_children;\r\n\t\t\tmp_children = p_child;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::ResetGoalLinks()\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\t\r\n\tCGoalLink* p_link = mp_children;\r\n\twhile ( p_link && p_link->m_relative != 0 )\r\n\t{\r\n\t\tp_link->m_beaten = false;\r\n\t\tCGoal* pGoal = pGoalManager->GetGoal( p_link->m_relative );\r\n\t\tif ( pGoal )\r\n\t\t{\r\n\t\t\t// recurse!\r\n\t\t\tpGoal->ResetGoalLinks();\r\n\t\t}\r\n\t\t\r\n\t\tp_link = p_link->mp_next;\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::DeleteLinks( CGoalLink* p_list )\r\n{\r\n\tCGoalLink *p_a, *p_b;\r\n\tfor ( p_a = p_list; p_a; p_a = p_b )\r\n\t{\r\n\t\tp_b = p_a->mp_next;\r\n\t\tdelete p_a;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::Uninit( bool propogate, int recurse_level )\r\n{\r\n\tDbg_MsgAssert( recurse_level < 20, ( \"CGoal::Uninit recursed too deep\" ) );\r\n\t\r\n\t// uint32 trigger_obj_id = 0;\r\n\r\n\tif ( IsActive() )\r\n\t{\r\n\t\tDeactivate( true );\r\n\t}\r\n\r\n\tRunCallbackScript( vUNINIT );\r\n\t\r\n\tm_isInitialized = false;\r\n\t\r\n/*\t\r\n\tScript::RunScript( Script::GenerateCRC( \"goal_kill_proset_geom\" ), mp_params );\r\n\tmp_params->GetChecksum( CRCD( 0x2d7e03d, \"trigger_obj_id\" ), &trigger_obj_id );\r\n\tif ( trigger_obj_id )\r\n\t{\r\n\t\tObj::CMovingObject* p_pos_obj = NULL;\r\n\t\t// p_pos_obj = Obj::CMovingObject::m_hash_table.GetItem( trigger_obj_id );\r\n\t\tp_pos_obj = (Obj::CMovingObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID( trigger_obj_id );\r\n\t\tif ( p_pos_obj )\r\n\t\t{\r\n\t\t\tdelete p_pos_obj;\r\n\t\t}\r\n\t}\r\n*/\r\n\tif ( propogate )\r\n\t{\r\n\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\tDbg_Assert( pGoalManager );\r\n\r\n\t\tCGoalLink* pGoalLink = mp_children;\r\n\t\twhile ( pGoalLink && pGoalLink->m_relative != 0 )\r\n\t\t{\r\n\t\t\tCGoal* pChildGoal = pGoalManager->GetGoal( pGoalLink->m_relative );\r\n\t\t\tDbg_Assert( pChildGoal );\r\n\t\t\tpChildGoal->Uninit( propogate, recurse_level + 1 );\r\n\t\t\tpGoalLink = pGoalLink->mp_next;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCGoal::~CGoal()\r\n{\r\n\t// does this really need to be run?\r\n\t// (you may not necessarily want to go through the\r\n\t// same destructor logic if we're clearing out the\r\n\t// goals at the end of the level)\r\n    \r\n    RunCallbackScript( vDESTROY );\r\n\t\r\n\tdelete mp_goalPed;\r\n\r\n\tDbg_Assert( mp_params );\r\n\tdelete mp_params;    \r\n\tdelete mp_goalFlags;\r\n\r\n\t// delete all children and parent trees\r\n\tDeleteLinks( mp_children );\r\n\tDeleteLinks( mp_parents );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nScript::CStruct* CGoal::GetParams()\r\n{\r\n\treturn mp_params;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::SetTimer()\r\n{\r\n\tint unlimited_time = 0;\r\n\r\n\tmp_params->GetInteger( CRCD(0xf0e712d2,\"unlimited_time\"), &unlimited_time );\r\n\r\n\t// check for unlimited time\r\n\tif ( unlimited_time == 1 )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// don't set default time for minigames.\r\n\tif ( IsMinigame() )\r\n\t{\r\n\t\tif ( !mp_params->ContainsComponentNamed( CRCD(0x906b67ba,\"time\") ) )\r\n\t\t\treturn;\r\n\t}\r\n\r\n\t// default time limit of 2 minutes\r\n    m_timeLeft = 120;\r\n\tint time;\r\n\tif ( mp_params->GetInteger( CRCD(0x906b67ba,\"time\"), &time, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tm_timeLeft = (Tmr::Time)time;\r\n\t}\r\n/*\telse\r\n\t{\r\n\t\tScript::CArray* pTimeLimits;\r\n\t\tif ( mp_params->GetArray( CRCD(0x906b67ba,\"time\"), &pTimeLimits, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\t\tDbg_Assert( pGoalManager );\r\n\t\t\tuint32 difficulty_level = pGoalManager->GetDifficultyLevel();\r\n\t\t\tDbg_Assert( difficulty_level > 0 && difficulty_level < pTimeLimits->GetSize() );\r\n\t\t\tm_timeLeft = (Tmr::Time)( pTimeLimits->GetInteger( difficulty_level ) );\r\n\t\t}\r\n\t}\r\n*/\r\n\t// convert to milliseconds\r\n\tm_timeLeft *= 1000;\r\n    \r\n\t// bump up timer so clock starts with expected amount of time left\r\n\tm_timeLeft += 20;\r\n\t// printf(\"timer set to %i\\n\", (int)m_timeLeft);\r\n\r\n\tm_unlimitedTime = false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::SetTimer( int time )\r\n{\r\n\tm_timeLeft = (Tmr::Time)time * 1000;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tCGoal::GetTimeLeft( void )\r\n{\r\n\treturn m_timeLeft;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::AddTime( int time )\r\n{\r\n\t// bump up time by 20ms so that it displays right\r\n\tm_timeLeft += ( (Tmr::Time)time * 1000 ) + 20;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::Activate()\r\n{\r\n    if ( !IsActive() )\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t\t// Warning! Make sure there are no 'return's between the above pushcontext and the \r\n\t\t// popcontext below ...\r\n\t\t\r\n\t\tm_elapsedTime = 0;\r\n\t\t\r\n\t\tm_numTimesStarted++;\r\n\r\n\t\t// printf(\"goal is not active - now activating\\n\");\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tGameNet::PlayerInfo* player;\r\n\t\tLst::Search< GameNet::PlayerInfo > sh;\r\n\t\t\t\t\t\t\r\n\t\t// TODO: reset just this skater's score\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ) )\r\n\t\t{\r\n\t\t\tObj::CSkater *p_Skater = player->m_Skater;\r\n\t\t\tDbg_Assert( p_Skater );\r\n\t\t\t\r\n\t\t\tObj::CSkaterScoreComponent* p_SkaterScoreComponent = GetSkaterScoreComponentFromObject(p_Skater);\r\n\t\t\tDbg_Assert( p_SkaterScoreComponent );\r\n\t\t\t\r\n\t\t\tMdl::Score * p_Score = ( p_SkaterScoreComponent->GetScore() );\r\n\t\t\tDbg_Assert( p_Score );\r\n\t\r\n\t\t\t// don't reset the score when starting a minigame\r\n\t\t\tif ( !IsMinigame() )\r\n\t\t\t\tp_Score->Reset();\r\n\t\t}\r\n\r\n\t\t// Warning! Make sure there are no 'return's between the above pushcontext and the \r\n\t\t// popcontext below ...\r\n        \r\n\t\tif ( mp_parents->m_relative != 0 )\r\n\t\t{\r\n\t\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\t\tDbg_Assert( pGoalManager );\r\n\r\n\t\t\tCGoal* pParentGoal = NULL;\r\n\r\n\t\t\t// get the root node and check the timer\r\n\t\t\tCGoalLink* p_parent = mp_parents;\r\n\t\t\twhile ( p_parent && p_parent->m_relative != 0 )\r\n\t\t\t{\r\n\t\t\t\tpParentGoal = pGoalManager->GetGoal( p_parent->m_relative );\r\n\t\t\t\tp_parent = pParentGoal->GetParents();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif ( pParentGoal )\r\n\t\t\t{\r\n\t\t\t\tif ( m_inherited_flags & GOAL_INHERITED_FLAGS_ONE_TIMER )\r\n\t\t\t\t\tSetTimer( pParentGoal->GetTimeLeft() / 1000.0f );\r\n\t\t\t\telse\r\n\t\t\t\t\tSetTimer();\r\n\r\n\t\t\t\tif ( pParentGoal->IsInitialized() )\r\n\t\t\t\t{\r\n\t\t\t\t\tpParentGoal->Uninit();\r\n\t\t\t\t\t\r\n\t\t\t\t\t// reinitialize the goal in case uninitializing the parent\r\n\t\t\t\t\t// screwed anything up.\r\n\t\t\t\t\tif ( IsInitialized() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tUninit();\r\n\t\t\t\t\t\tInit();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Dbg_Message( \"Goal supposed to use a single timer but couldn't find parent\" );\r\n\t\t\t\tSetTimer();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tSetTimer();\r\n\t\t}\r\n\t\t\r\n\t\tif ( !IsInitialized() )\r\n\t\t{\r\n\t\t\tInit();\r\n\t\t}\r\n\t\t\r\n\t\tm_endRunCalled = false;\r\n\r\n\t\t// Warning! Make sure there are no 'return's between the above pushcontext and the \r\n\t\t// popcontext below ...\r\n\r\n\t\tmp_params->RemoveFlag( CRCD(0x7100155d,\"combo_started\") );\r\n\r\n        // activate script\r\n\t\tRunCallbackScript( vACTIVATE );\r\n        \r\n\t\tif( gamenet_man->InNetGame() == false )\r\n\t\t{\r\n\t\t\tm_hasSeen = true;\r\n\t\t}\r\n        \r\n\t\t//if ( !mp_params->ContainsFlag( \"quick_start\" ) )\r\n\t\t\t//PauseGoal();\r\n\t\tSetActive();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::SetActive()\r\n{\r\n\tm_active = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::Deactivate( bool force, bool affect_tree )\r\n{\r\n\tif ( IsActive() )\r\n\t{\r\n\t\t// special case for special trick goal...get rid of\r\n\t\t// the temp key_combos array\r\n\t\tif ( IsSpecialGoal() )\r\n\t\t\tmp_params->RemoveComponent( CRCD(0x79704516,\"key_combos\") );\r\n\r\n\t\tFront::HideTimeTHPS4();\r\n\t\t\r\n\t\tSetInactive();\r\n        \r\n        ResetGoalFlags();\r\n\r\n\t\tResetGoalLinks();\r\n\r\n        RunCallbackScript( vDEACTIVATE );\r\n\r\n\t\tif (!mp_params->ContainsFlag( CRCD( 0x38221df4, \"quick_start\" ) ))\r\n\t\t{\r\n\t\t\t// If not retrying, then remove the testing_goal flag\r\n\t\t\t// The presence of the testing_goal flag prevents the goal from being marked as\r\n\t\t\t// beaten when it is beaten during testing.\r\n\t\t\tmp_params->RemoveFlag(CRCD(0x54d3cac1,\"testing_goal\"));\r\n\t\t}\t\r\n\t\t\r\n\t\tif ( !mp_params->ContainsFlag( CRCD( 0xc309cad1, \"just_won_goal\" ) )\r\n\t\t\t && !mp_params->ContainsFlag( CRCD( 0x38221df4, \"quick_start\" ) ) )\r\n\t\t{\r\n\t\t\tScript::RunScript(CRCD(0x719ae783, \"ready_skater_for_early_end_current_goal\"), mp_params);\r\n\t\t\t\r\n\t\t\tif ( affect_tree && mp_parents && mp_parents->m_relative )\r\n\t\t\t{\r\n\t\t\t\tUninit();\r\n\t\r\n\t\t\t\t// find parent node and reinitialize\r\n\t\t\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\t\t\tDbg_Assert( pGoalManager );\r\n\t\t\t\tCGoalLink* p_link = mp_parents;\r\n\t\t\t\tCGoal* pParentGoal = NULL;\r\n\t\t\t\twhile ( p_link && p_link->m_relative )\r\n\t\t\t\t{\r\n\t\t\t\t\tpParentGoal = pGoalManager->GetGoal( p_link->m_relative );\r\n\t\t\t\t\tDbg_Assert( pParentGoal );\r\n\t\t\t\t\tp_link = pParentGoal->GetParents();\r\n\t\t\t\t}\r\n\t\t\t\tif ( pParentGoal && !pParentGoal->HasWonGoal() )\r\n\t\t\t\t{\r\n\t\t\t\t\t// printf(\"initializing goal: %s\\n\", Script::FindChecksumName( pParentGoal->GetGoalId() ) );\r\n\t\t\t\t\tpParentGoal->Init();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n        return true;\r\n    }\r\n\treturn false;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::SetInactive()\r\n{\r\n\tm_active = false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::Win( void )\r\n{\r\n\tmp_params->AddInteger( CRCD(0xc22a2b72,\"win_record\"), 0 );\r\n\t// see if it's a leaf node\r\n\tif ( mp_children->m_relative == 0 )\r\n\t{\r\n\t\tmp_params->AddChecksum( NONAME, CRCD( 0xc309cad1, \"just_won_goal\" ) );\t\t\t\r\n\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\t\r\n\t\tm_numTimesWon++;\r\n\t\t\r\n\t\t// look for a new record if we're not in a net game\r\n\t\tbool set_new_record = false;\r\n\t\tuint32 record_type;\r\n\t\tif ( !gamenet_man->InNetGame() && mp_params->GetChecksum( CRCD(0x96963902,\"record_type\"), &record_type, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\t// printf(\"record type is %s\\n\", Script::FindChecksumName( record_type ) );\r\n\t\t\tif ( record_type == CRCD(0xcd66c8ae,\"score\") )\r\n\t\t\t{\r\n\t\t\t\t// check for custom score record\r\n\t\t\t\tint custom_record;\r\n\t\t\t\tif ( mp_params->GetInteger( CRCD(0xfc9630ab,\"custom_score_record\"), &custom_record, Script::NO_ASSERT ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( custom_record > m_winScoreRecord )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_winScoreRecord = custom_record;\r\n\t\t\t\t\t\tmp_params->AddInteger( CRCD(0xc22a2b72,\"win_record\"), m_winScoreRecord );\r\n\t\t\t\t\t\tset_new_record = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// printf(\"found a score record type\\n\");\r\n\t\t\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\t\t\tObj::CSkater *pSkater = skate_mod->GetLocalSkater();\r\n\t\t\t\t\tDbg_Assert( pSkater );\r\n\t\t\t\t\t\r\n\t\t\t\t\tObj::CSkaterScoreComponent* pSkaterScoreComponent = GetSkaterScoreComponentFromObject(pSkater);\r\n\t\t\t\t\tDbg_Assert( pSkaterScoreComponent );\r\n\t\t\r\n\t\t\t\t\tMdl::Score * pScore = ( pSkaterScoreComponent->GetScore() );\r\n\t\t\t\t\tDbg_Assert( pScore );\r\n\t\t\r\n\t\t\t\t\tint total_score;\r\n\t\t\t\t\tif ( mp_params->ContainsFlag( CRCD(0xc63432a7,\"high_combo\") ) )\r\n\t\t\t\t\t\t total_score = pScore->GetLastScoreLanded();\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\t total_score = pScore->GetTotalScore();\r\n\r\n\t\t\t\t\t// printf(\"got a total_score of %i, had a previous record of %i\\n\", total_score, m_winScoreRecord );\r\n\t\t\t\t\tif ( total_score > m_winScoreRecord )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_winScoreRecord = total_score;\r\n\t\t\t\t\t\tmp_params->AddInteger( CRCD(0xc22a2b72,\"win_record\"), m_winScoreRecord );\r\n\t\t\t\t\t\tset_new_record = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( record_type == CRCD(0x906b67ba,\"time\") )\r\n\t\t\t{\r\n\t\t\t\t// printf(\"got a time of %i, previous record was %i\\n\", (int)m_elapsedTime, (int)m_elapsedTimeRecord);\r\n\t\t\t\tif ( m_elapsedTime < m_elapsedTimeRecord )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_elapsedTimeRecord = m_elapsedTime;\r\n\t\t\t\t\tmp_params->AddInteger( CRCD(0xc22a2b72,\"win_record\"), (int)m_elapsedTimeRecord );\r\n\t\t\t\t\tset_new_record = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t#ifdef __NOPT_ASSERT__\r\n\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\tDbg_Assert( pGoalManager );\r\n\t#endif\t\t// __NOPT_ASSERT__\r\n\t\t\r\n\t\tif ( !HasWonGoal() && !gamenet_man->InNetGame() )\r\n\t\t{\r\n\t\t\t// printf(\"getting rewards struct\\n\");\r\n\t\t\tScript::CStruct* p_reward_params = new Script::CStruct();\r\n\t\t\tGetRewardsStructure( p_reward_params, true );\r\n\t\t\tif ( set_new_record )\r\n\t\t\t\tp_reward_params->AddChecksum( NONAME, CRCD(0xe7b8254f,\"set_new_record\") );\r\n\t\r\n\t\t\tmp_params->AddStructurePointer( CRCD(0x128b3088,\"reward_params\"), p_reward_params );\r\n\t\r\n\t\t\tUnlockRewardGoals();\r\n\t\t}\r\n\t\telse\r\n\t\t\tmp_params->RemoveComponent( CRCD(0x128b3088,\"reward_params\") );\r\n\t\t\r\n\t\t// update set_new_record flag\r\n\t\tif ( set_new_record )\r\n\t\t\tmp_params->AddChecksum( NONAME, CRCD(0xe7b8254f,\"set_new_record\") );\r\n\t\telse\r\n\t\t\tmp_params->RemoveFlag( CRCD(0xe7b8254f,\"set_new_record\") );\r\n\t\t\r\n\t\tRunCallbackScript( vSUCCESS );\r\n\r\n\t\tbool testing_goal=mp_params->ContainsFlag(CRCD(0x54d3cac1,\"testing_goal\"));\r\n\t\t\r\n\t\tif ( IsActive() )\r\n\t\t{\r\n\t\t\t// add a flag so the deactivate script knows that we just beat the goal\r\n\t\t\tDeactivate();\r\n\t\t}\r\n\t\r\n\t\t// The testing_goal flag is set when a created goal is being test played.\r\n\t\t// Don't want it to be crossed off the view goals menu in that case. (TT3366)\r\n\t\tif (!testing_goal)\r\n\t\t{\r\n\t\t\tMarkBeaten();\r\n\t\t}\r\n\r\n\t\tif ( gamenet_man->InNetGame() )\r\n\t\t{\r\n\t\t\tUninit();\r\n\t\t}\r\n\t\t\t\t\r\n\t\tmp_params->RemoveFlag( CRCD( 0xc309cad1, \"just_won_goal\" ) );\r\n\t\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// it's a link to another goal\r\n\r\n\t\t// TODO: we need a way of deciding which child to pick\r\n\t\t// for now, we'll just take the first child\r\n\t\tGame::CGoalLink* p_link = mp_children;\r\n\r\n\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\tDbg_Assert( pGoalManager );\r\n\t\tDeactivate();\r\n\t\tUninit();\r\n\t\tCGoal* pChildGoal = pGoalManager->GetGoal( p_link->m_relative );\r\n\t\tpChildGoal->Init();\r\n\t\tpGoalManager->ActivateGoal( p_link->m_relative, false );\r\n\t\t\r\n\t\t// mark the link beaten\r\n\t\tp_link->m_beaten = true;\r\n\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::Lose( void )\r\n{\r\n\t// Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t// Obj::CSkater *p_Skater = skate_mod->GetLocalSkater();\r\n\t// Dbg_Assert( p_Skater );\r\n\r\n\t// p_Skater->ClearAllExceptions();\r\n\r\n\tif ( IsActive() )\r\n\t{\r\n\t\tm_numTimesLost++;\r\n\t\t\r\n\t\tRunCallbackScript( vFAIL );\r\n        \r\n\t\tDeactivate( true );\r\n\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::IsExpired()\r\n{\r\n\treturn IsExpired( false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::ShouldExpire()\r\n{\r\n\t// returns true if the goal would expire if the skater was not in a combo\r\n\t\r\n\t// Dan: this logic needs to mimic IsExpired()\r\n\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tObj::CSkater* p_skater;\r\n\t\r\n\tp_skater = skate_mod->GetLocalSkater();\r\n\tif ( p_skater == NULL )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n#ifdef __NOPT_ASSERT__\r\n\tObj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(p_skater);\r\n\tDbg_Assert(p_skater_endrun_component);\r\n#endif\t\t// __NOPT_ASSERT__\r\n\t\r\n\t// If no players are left, the goal should expire\r\n\tif ( gamenet_man->GetNumPlayers() == 0 )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\t// If it's an unlimited game, don't expire the goal\r\n\tif ( m_unlimitedTime )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tif ( (int)m_timeLeft <= 0 )\r\n\t{\r\n\t\t// Dbg_Printf( \"**** Already Expired\\n\" );\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::IsExpired( bool force_end )\r\n{\r\n    Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tObj::CSkater* p_skater;\r\n\r\n\tp_skater = skate_mod->GetLocalSkater();\r\n\tif ( p_skater == NULL )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tObj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(p_skater);\r\n\tDbg_Assert(p_skater_endrun_component);\r\n\r\n\t// If no players are left, the goal should expire\r\n\tif ( gamenet_man->GetNumPlayers() == 0 )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\t\t\t\t\r\n\t// If it's an unlimited game, don't expire the goal\r\n\tif ( m_unlimitedTime )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// check if the skaters have reached end of run BEFORE\r\n\t// setting the exception, or you'll never catch it!\r\n\tbool expired = false;\r\n\t \r\n\tswitch ( m_endRunType )\r\n\t{\r\n\tcase vENDOFRUN:\r\n\t\texpired = p_skater_endrun_component->RunHasEnded();\r\n\t\tbreak;\r\n\tcase vGOALENDOFRUN:\r\n\t\texpired = p_skater_endrun_component->GoalRunHasEnded();\r\n\t\tbreak;\r\n\tcase vNONE:\r\n\t\t// if we're not supposed to use end of run, we need only check\r\n\t\t// the time\r\n\t\treturn ( (int)m_timeLeft <= 0 );\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n\r\n\tif ( expired && (int)m_timeLeft <= 0 )\r\n\t{\r\n\t\t// Dbg_Printf( \"**** Already Expired\\n\" );\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// if time is up, set the end of run exception\r\n\tif ( (int)m_timeLeft <= 0 )\r\n\t{\r\n\t\t// Dbg_Printf( \"EXPIRING GOAL: %d\\n\", GetGoalId());\r\n\t\t// printf(\"&&&&&&&&&&&&&&&&& calling EndRun\\n\");\r\n\t\tswitch ( m_endRunType )\r\n\t\t{\r\n\t\tcase vENDOFRUN:\r\n\t\t\tm_endRunCalled = true;\r\n\t\t\t// Dbg_Printf( \"**** Calling End Run\\n\" );\r\n\t\t\tp_skater_endrun_component->EndRun( force_end );\r\n\t\t\tbreak;\r\n\t\tcase vGOALENDOFRUN:\r\n\t\t\t// printf(\"reached goalendofrun\\n\");\r\n\t\t\tm_endRunCalled = true;\r\n\t\t\tp_skater_endrun_component->EndGoalRun( force_end );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t}\r\n\t}\r\n\r\n    // printf(\"AtEndOfRun returned %i\\n\", all_expired);\r\n\t// return ( all_expired && ( (int)m_timeLeft <= 0 ) );\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::AllSkatersAtEndOfRun()\r\n{\r\n\t// check all the goals\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\r\n\tGameNet::PlayerInfo* player;\r\n\tLst::Search< GameNet::PlayerInfo > sh;\r\n\t\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t{\r\n\t\tObj::CSkater *p_Skater = player->m_Skater;\r\n\t\t// int skater_num = p_Skater->GetSkaterNumber();\r\n\t\tDbg_Assert( p_Skater );\r\n\t\t\r\n\t\tObj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(p_Skater);\r\n\t\tDbg_Assert( p_skater_endrun_component );\r\n\r\n\t\tif( skate_mod->GetGameMode()->GetNameChecksum() == CRCD( 0x9d65d0e7, \"horse\" ))\r\n\t\t{\r\n\t\t\tif( p_Skater->IsPaused() || p_Skater->IsHidden())\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\t\tswitch ( m_endRunType )\r\n\t\t{\r\n\t\tcase vENDOFRUN:\r\n\t\t\tif ( !p_skater_endrun_component->RunHasEnded() )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase vGOALENDOFRUN:\r\n\t\t\tif ( !p_skater_endrun_component->GoalRunHasEnded() )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t}\r\n\t}    \r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::EditParams( Script::CStruct* pParams )\r\n{\r\n\tmp_params->AppendStructure( pParams );\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::Update( void )\r\n{\r\n    if ( IsActive() && !IsPaused() )\r\n    {\r\n        RunCallbackScript( vACTIVE );\r\n    }\r\n    \r\n    // the active script may have deactivated the goal, so we check \r\n    // if it's active again...don't check mini games\r\n    if ( IsActive() && !IsPaused())\r\n\t{\r\n\t\tif( ShouldUseTimer()  )\r\n\t\t{\r\n\t\t\tif ( ( (int)m_timeLeft >= 1 ) )\r\n\t\t\t{\r\n\t\t\t\tint old_time_left = (int)m_timeLeft;\r\n\t\t\t\tm_timeLeft -= (Tmr::Time)( Tmr::FrameLength() * 1000 );\r\n\t\t\t\tm_elapsedTime += (Tmr::Time)( Tmr::FrameLength() * 1000 );\r\n\r\n\t\t\t\tif ( (int)m_timeLeft < 10000 && ( (int)( old_time_left / 1000 ) > (int)( (int)m_timeLeft / 1000 ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif (Mdl::Skate::Instance()->GetGameMode()->ShouldTimerBeep())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tScript::RunScript( CRCD(0xcfc7c3ad,\"timer_runout_beep\") );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( ShouldRequireCombo() )\r\n\t\t{\r\n\t\t\tif ( !mp_params->ContainsFlag( CRCD( 0x7100155d, \"combo_started\" ) ) )\r\n\t\t\t{\r\n\t\t\t\tMdl::Skate *skate_mod =  Mdl::Skate::Instance();\r\n\t\t\t\tObj::CSkater* pSkater = skate_mod->GetLocalSkater();\r\n\t\t\t\tif ( pSkater )\r\n\t\t\t\t{\r\n\t\t\t\t\tMdl::Score* pScore = pSkater->GetScoreObject();\r\n\t\t\t\t\tif ( pScore && pScore->GetScorePotValue() > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmp_params->AddChecksum( NONAME, CRCD(0x7100155d,\"combo_started\") );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// add the amount of time left\r\n\t\t// mp_params->AddInteger( \"time_left\", m_timeLeft );        \r\n\t\tif ( IsExpired() )\r\n\t\t{\r\n\t\t\tExpire();\r\n\t\t}\r\n\t}\r\n\t\r\n// haven't used the inactive yet\t\r\n/*\telse\r\n\t{\r\n\t\tif ( !IsLocked() )\r\n        {\r\n            // runs its inactive script (if any)\r\n    \t\tRunCallbackScript( vINACTIVE );\r\n        }\r\n\t}\t\r\n*/\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::Expire()\r\n{\r\n\tRunCallbackScript( vEXPIRED );\r\n\t\r\n\t// TODO: fix after e3\r\n\t// this was done to make the horse and combo letter goals work right\r\n\tif ( m_deactivateOnExpire )\r\n\t{\r\n\t\tDeactivate();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::IsActive( void )\r\n{\r\n\treturn ( m_active == true );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::HasSeenGoal( void )\r\n{\r\n\treturn m_hasSeen;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::PauseGoal( void )\r\n{\r\n\tm_paused = true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::UnPauseGoal( void )\r\n{\r\n\tm_paused = false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nTmr::Time CGoal::GetTime( void )\r\n{\r\n\treturn m_timeLeft;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/*void CGoal::CreateGoalFlag( uint32 flag )\r\n{\r\n    mp_goalFlags->AddInteger( flag, 0 );\r\n    m_numflags++;\r\n}*/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::SetGoalFlag( uint32 flag, int value )\r\n{\r\n    if ( !IsActive() )\r\n    {\r\n        return false;\r\n    }\r\n    \r\n\tif ( mp_goalFlags->ContainsComponentNamed( flag ) )\r\n\t{\r\n\t\t// remember the old value\r\n\t\tint old_value;\r\n\t\tmp_goalFlags->GetInteger( flag, &old_value, Script::ASSERT );\r\n\t\t\r\n\t\tmp_goalFlags->AddInteger( flag, value );\r\n\t\tif ( old_value != value )\r\n\t\t{\r\n\t\t\tif ( value == 0 )\r\n\t\t\t\tm_flagsSet--;\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_flagsSet++;\r\n\t\t\t\tif ( !mp_params->ContainsFlag( CRCD(0x524566e3,\"no_midgoal_sound\") ) )\r\n\t\t\t\t\tScript::RunScript( CRCD(0x5ed34deb,\"goal_got_flag_sound\") );\r\n\t\t\t}\r\n\t\t\tif ( mp_params->ContainsFlag( CRCD(0xfd7ae1f4,\"use_hud_counter\") ) )\r\n\t\t\t\tScript::RunScript( CRCD(0xf2e85a34,\"goal_update_counter\"), mp_params );\r\n\r\n\t\t\tmp_params->AddInteger( CRCD(0xcf6cd3c1,\"num_flags_set\"), m_flagsSet );\r\n\t\t}\t\t\r\n\t\t// printf(\"setting goal flag %s, %i of %i set\\n\", Script::FindChecksumName( flag ), m_flagsSet, m_numflags );\r\n\t\treturn true;\r\n\t}\r\n    \r\n    Dbg_MsgAssert( 0, (\"SetGoalFlag couldn't find flag\\n\" ) );\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::GetCreatedGoalGap(int gapIndex)\r\n{\r\n\tScript::CArray *p_required_gaps=NULL;\r\n\tif (!mp_params->GetArray(CRCD(0x52d4489e,\"required_gaps\"),&p_required_gaps))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tconst char *p_required_trick_name=\"\";\r\n\tmp_params->GetString(CRCD(0x730844a3,\"required_trick_name\"),&p_required_trick_name);\r\n\tif (p_required_trick_name[0])\r\n\t{\r\n\t\tMdl::Skate *p_skate_mod =  Mdl::Skate::Instance();\r\n\t\tObj::CSkater *p_skater = p_skate_mod->GetLocalSkater();\r\n\t\tif (!p_skater)\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\t\r\n\t\tMdl::Score *p_score = p_skater->GetScoreObject();\r\n\t\r\n\t\tuint32 trick_checksum=Script::GenerateCRC(p_required_trick_name);\r\n\t\t\r\n\t\t// Also check for fs and bs versions (TT9784)\r\n\t\tuint32 bs_trick_checksum=CRCD(0x7491335e,\"bs \");\r\n\t\tbs_trick_checksum=Crc::ExtendCRCWithString(bs_trick_checksum, p_required_trick_name);\r\n\t\tuint32 fs_trick_checksum=CRCD(0x73989b82,\"fs \");\r\n\t\tfs_trick_checksum=Crc::ExtendCRCWithString(fs_trick_checksum, p_required_trick_name);\r\n\t\t\r\n\t\tif (p_score->GetCurrentNumberOfOccurrencesByName(trick_checksum, 0, false) == 0 && \r\n\t\t\tp_score->GetCurrentNumberOfOccurrencesByName(bs_trick_checksum, 0, false) == 0 &&\r\n\t\t\tp_score->GetCurrentNumberOfOccurrencesByName(fs_trick_checksum, 0, false) == 0)\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\tfor (uint i=0; i<p_required_gaps->GetSize(); ++i)\r\n\t{\r\n\t\tif (gapIndex==p_required_gaps->GetInteger(i))\r\n\t\t{\r\n\t\t\tchar p_foo[20];\r\n\t\t\tsprintf(p_foo,\"got_%d\",i+1);\r\n\t\t\tSetGoalFlag(Script::GenerateCRC(p_foo),1);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::GoalFlagEquals( uint32 flag, int value )\r\n{\r\n\tif ( mp_goalFlags->ContainsComponentNamed( flag ) )\r\n\t{\r\n\t\tint f;\r\n\t\tmp_goalFlags->GetInteger( flag, &f, Script::ASSERT );\r\n\t\treturn ( value == f );\r\n\t}\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::ResetGoalFlags()\r\n{\r\n\t// reset the goal flags\r\n\tScript::CComponent* p_comp = mp_goalFlags->GetNextComponent( NULL );\r\n\twhile ( p_comp )\r\n\t{\r\n\t\tScript::CComponent* p_next = mp_goalFlags->GetNextComponent( p_comp );\r\n\t\tp_comp->mIntegerValue = 0;\r\n\t\t// SetGoalFlag( p_comp->mNameChecksum, 0 );\r\n\t\t\r\n\t\t// printf(\"resetting goal flag %s\\n\", Script::FindChecksumName( flag_name ) );\r\n\t\tp_comp = p_next;\r\n\t}\r\n\tm_flagsSet = 0;\r\n\tmp_params->AddInteger( CRCD( 0xcf6cd3c1, \"num_flags_set\" ), 0 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::AllFlagsSet()\r\n{\r\n//    printf(\"%i flags, %i set\\n\", m_numflags, m_flagsSet);\r\n\tint num_flags_to_win = m_numflags;\r\n\tmp_params->GetInteger( CRCD(0x1171a555,\"num_flags_to_win\"), &num_flags_to_win, Script::NO_ASSERT );\r\n\t\r\n\t// K: Fix to TT9785, where created gap goals would succeed straight away if no gaps were chosen,\r\n\t// causing an assert.\r\n\tif (num_flags_to_win == 0)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\treturn ( m_flagsSet >= num_flags_to_win );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::GoalFlagSet( uint32 flag )\r\n{\r\n\tint flag_value;\r\n\tmp_goalFlags->GetInteger( flag, &flag_value, Script::ASSERT );\r\n\treturn ( flag_value != 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::IsLocked()\r\n{\r\n    return false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::UnlockGoal()\r\n{\r\n    if ( m_isLocked )\r\n    {\r\n        m_isLocked = false;\r\n\r\n\t\t// don't initialize goals automatically in net games\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tif ( gamenet_man->InNetGame() )\r\n\t\t\treturn;\r\n\r\n\t\t// initialize goal\r\n        Init();\r\n        \r\n        // call the unlock script \r\n        RunCallbackScript( vUNLOCK );\r\n    }\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::NextTourSpot()\r\n{\r\n    Script::CArray* p_waypoints;\r\n    // backward compatible with the horse_spots array naming convention\r\n\tif ( !mp_params->GetArray( CRCD(0x160b3220,\"tour_spots\"), &p_waypoints, Script::NO_ASSERT ) )\r\n\t\tmp_params->GetArray( CRCD(0x92c6e839,\"horse_spots\"), &p_waypoints, Script::ASSERT );\r\n\r\n    Script::CStruct* p_waypoint;\r\n    for ( uint32 i = 0; i < p_waypoints->GetSize(); i++ )\r\n    {\r\n        p_waypoint = p_waypoints->GetStructure( i );\r\n\r\n        // is this waypoint done?\r\n        uint32 flagId;\r\n        p_waypoint->GetChecksum( CRCD(0x2e0b1465,\"flag\"), &flagId, Script::ASSERT );\r\n        if ( GoalFlagEquals( flagId, 1 ) )\r\n            continue;\r\n        \r\n        // pause the goal and set the time for this tour spot\r\n        PauseGoal();\r\n\t\tint time;\r\n\t\tp_waypoint->GetInteger( CRCD(0x906b67ba,\"time\"), &time, Script::ASSERT );\r\n        // add time if necessary\r\n\t\tif ( mp_params->ContainsFlag( CRCD(0xfb11cb01,\"cumulative_timer\") ) )\r\n\t\t{\r\n\t\t\tAddTime( time );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_params->AddInteger( CRCD(0x906b67ba,\"time\"), time );\r\n\t\t\tSetTimer();\r\n\t\t}\r\n            \r\n        // add the goalId and trigger id to the params\r\n        p_waypoint->AddChecksum( CRCD(0x9982e501,\"goal_id\"), GetGoalId() );\r\n\r\n\t\t// send a flag if this is the first spot\r\n\t\tif ( m_flagsSet == 0 )\r\n\t\t\tp_waypoint->AddChecksum( NONAME, CRCD( 0xb13f3ab8, \"first_spot\" ) );\r\n\r\n\t\t// send a flag if this is a restart\r\n\t\tif ( mp_params->ContainsFlag( CRCD(0x38221df4,\"quick_start\") ) )\r\n\t\t\tp_waypoint->AddChecksum( NONAME, CRCD(0x38221df4,\"quick_start\") );\r\n\t\telse\r\n\t\t\tp_waypoint->RemoveFlag( CRCD(0x38221df4,\"quick_start\") );\r\n\r\n        \r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\t// backward compatible with horse goal\r\n\t\tScript::CScript *p_script=NULL;\r\n\t\tif ( mp_params->ContainsFlag( CRCD(0x9d65d0e7,\"horse\") ) )\r\n\t\t\tp_script=Script::SpawnScript( CRCD(0x681bc776,\"goal_horse_next_spot\"), p_waypoint );\r\n\t\telse\r\n\t\t\tp_script=Script::SpawnScript( CRCD(0x4c938553,\"goal_tour_next_spot\"), p_waypoint );\r\n\t\tp_script->SetCommentString(\"Spawned from CGoal::NextTourSpot()\");\r\n\t\t#else\t\r\n\t\t// backward compatible with horse goal\r\n\t\tif ( mp_params->ContainsFlag( CRCD(0x9d65d0e7,\"horse\") ) )\r\n\t\t\tScript::SpawnScript( CRCD(0x681bc776,\"goal_horse_next_spot\"), p_waypoint );\r\n\t\telse\r\n\t\t\tScript::SpawnScript( CRCD(0x4c938553,\"goal_tour_next_spot\"), p_waypoint );\r\n\t\t#endif\t\t\t\r\n\r\n\r\n\t\t// remove restart flag\r\n\t\tp_waypoint->RemoveFlag( CRCD(0x38221df4,\"quick_start\") );\r\n\r\n\r\n/*        // move the skater to the node\r\n        uint32 reset_checksum;\r\n        p_waypoint->GetChecksum( \"id\", &reset_checksum, Script::ASSERT );\r\n        Mdl::Skate * p_skate = Mdl::Skate::Instance();\r\n        p_skate->ResetSkaters( SkateScript::FindNamedNode( reset_checksum ) );\r\n\r\n        uint32 waypoint_script;\r\n        if ( p_waypoint->GetChecksum( \"scr\", &waypoint_script, Script::NO_ASSERT ) )\r\n            Script::SpawnScript( waypoint_script );\r\n*/        \r\n        return true;\r\n\r\n    }\r\n    return true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::InitTrickObjects()\r\n{\r\n    // get the object id's\r\n    Script::CArray* p_trickObjectArray = NULL;\r\n    mp_params->GetArray( CRCD(0x2eb84a54,\"trick_objects\"), &p_trickObjectArray, Script::ASSERT );\r\n    \r\n    Mdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n    Obj::CTrickObjectManager* p_TrickObjectManager = skate_mod->GetTrickObjectManager();\r\n\r\n    for ( uint32 i = 0; i < p_trickObjectArray->GetSize(); i++ )\r\n    {\r\n        // add the trick object\r\n        uint32 goal_object;\r\n        Script::CStruct* p_trickObject = p_trickObjectArray[i].GetStructure( i );\r\n        p_trickObject->GetChecksum( CRCD(0x40c698af,\"id\"), &goal_object, Script::ASSERT );\r\n        \r\n        // p_TrickObjectManager->RequestLogTrick( 1, \r\n        p_TrickObjectManager->ModulateTrickObjectColor( goal_object, 0 );\r\n    }\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::GotTrickObject( uint32 clusterId )\r\n{\r\n\t// do we care?\r\n\tif ( mp_params->ContainsFlag( CRCD( 0xf268c278, \"SkateTheLine\" ) ) )\r\n\t{\r\n\t\t// we do\r\n\t\tuint32 current;\r\n\t\tmp_params->GetChecksum( CRCD(0xb03713ee,\"current_cluster\"), &current, Script::ASSERT );\r\n\t\tif ( current == clusterId )\r\n\t\t\tScript::RunScript( CRCD( 0x62b12a8e, \"Goal_SkateTheLine_got_node\" ), mp_params );\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::IsGraffitiGoal()\r\n{\r\n\treturn ( mp_params->ContainsFlag( CRCD(0xc8a82b5a,\"graffiti\") ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::ShouldLogTrickObject()\r\n{\r\n\tif ( mp_params->ContainsFlag( CRCD(0xc8a82b5a,\"graffiti\") ) || mp_params->ContainsFlag( CRCD(0xf268c278,\"SkateTheLine\") ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::GotGraffitiCluster( uint32 clusterId, int score )\r\n{\r\n    // find the cluster in our cluster array\r\n    Script::CArray* pClusterArray;\r\n    mp_params->GetArray( CRCD(0x191f66e9,\"kill_clusters\"), &pClusterArray, Script::ASSERT );\r\n\r\n    for ( uint32 i = 0; i < pClusterArray->GetSize(); i++ )\r\n    {\r\n        Script::CStruct* pCluster = pClusterArray->GetStructure( i );\r\n        Dbg_MsgAssert( pCluster, ( \"got null cluster from kill_cluster array\\n\" ) );\r\n\r\n        uint32 id;\r\n        pCluster->GetChecksum( \"id\", &id, Script::ASSERT );\r\n\t\t\r\n\t\tint minScore;\r\n\t\t// get the score for this cluster, or the default score\r\n\t\tif ( !pCluster->GetInteger( CRCD(0xcd66c8ae,\"score\"), &minScore, Script::NO_ASSERT ) )\r\n\t\t\tmp_params->GetInteger( CRCD(0xcd66c8ae,\"score\"), &minScore, Script::ASSERT );\r\n\t\t\r\n\t\t// printf(\"minScore: %i, score: %i\\n\", minScore, score);\r\n\r\n        if ( id == clusterId && score > minScore )\r\n        {\r\n\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\tObj::CTrickObjectManager* p_trickObjectMan = skate_mod->GetTrickObjectManager();\r\n\r\n\t\t\t// printf(\"modulating color\\n\");\r\n\t\t\tif ( !p_trickObjectMan->ModulateTrickObjectColor( clusterId, 0 ) )\r\n\t\t\t\tprintf(\"ModulateTrickObjectColor didn't work\\n\");\r\n\r\n\t\t\tuint32 flag;\r\n            pCluster->GetChecksum( CRCD(0x2e0b1465,\"flag\"), &flag, Script::ASSERT );\r\n\r\n            SetGoalFlag( flag, 1 );\r\n            return;\r\n        }\r\n    }\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::IsSpecialGoal()\r\n{\r\n    return ( mp_params->ContainsFlag( CRCD(0xb394c01c,\"special\") ) );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::CheckSpecialGoal()\r\n{\r\n    Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n    Obj::CSkater *p_Skater = skate_mod->GetLocalSkater();\r\n    Dbg_Assert( p_Skater );\r\n\t\r\n\tObj::CSkaterScoreComponent* p_SkaterScoreComponent = GetSkaterScoreComponentFromObject(p_Skater);\r\n\tDbg_Assert( p_SkaterScoreComponent );\r\n    \r\n    Mdl::Score * p_Score = ( p_SkaterScoreComponent->GetScore() );\r\n    Dbg_Assert( p_Score );\r\n\r\n    const char* trick_string;\r\n    mp_params->GetString( CRCD(0x3a54cc4b,\"trick_string\"), &trick_string, Script::ASSERT );\r\n\r\n\t// if it's a grind, we need to check for the FS and BS version too\r\n\tuint32 trick_type;\r\n\tmp_params->GetChecksum( CRCD(0x3d929b66,\"trick_type\"), &trick_type, Script::ASSERT );\r\n\tif ( trick_type == CRCD( 0x255ed86f, \"grind\" ) )\r\n\t{\r\n\t\tchar test_trick[128];\r\n\t\t// frontside\r\n\t\tstrcpy( test_trick, \"FS \" );\r\n\t\tstrcat( test_trick, trick_string );\r\n\t\t// printf(\"testing FS version - %s\\n\", test_trick);\r\n\t\tif ( p_Score->GetCurrentNumberOfOccurrencesByName( Script::GenerateCRC( test_trick ) ) )\r\n\t\t{\r\n\t\t\t// printf(\"got it\\n\");\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// backside\r\n\t\tstrcpy( test_trick, \"BS \" );\r\n\t\tstrcat( test_trick, trick_string );\r\n\t\t// printf(\"testing BS version - %s\\n\", test_trick);\r\n\t\tif ( p_Score->GetCurrentNumberOfOccurrencesByName( Script::GenerateCRC( test_trick ) ) )\r\n\t\t{\r\n\t\t\t// printf(\"got it\\n\");\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// check the bare trick string\r\n\tif ( mp_params->ContainsFlag( CRCD(0x8e6014f6,\"create_a_trick\") ) )\r\n\t{\r\n\t\t// printf(\"testing cat version %s\\n\", new_string );\r\n\t\tif ( p_Score->GetCurrentNumberOfOccurrencesByName( Script::GenerateCRC( trick_string ) ) > 0 )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// printf(\"testing normal version - %s\\n\", trick_string);\r\n\t\tif ( p_Score->GetCurrentNumberOfOccurrencesByName( Script::GenerateCRC( trick_string ) ) > 0 )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n    return false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::IsTetrisGoal()\r\n{\r\n    return ( mp_params->ContainsFlag( CRCD(0x4147922b,\"tetris\") ) );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoal::GetRandomIndexFromKeyCombos( Script::CArray* p_keyCombos )\r\n{\r\n\tDbg_MsgAssert( p_keyCombos->GetType() == ESYMBOLTYPE_NAME ||\r\n\t\t\t\t   p_keyCombos->GetType() == ESYMBOLTYPE_STRUCTURE,\r\n\t\t\t\t   ( \"GetRandomIndexFromKeyCombos got array of the wrong type\" ) );\r\n\r\n\t// get the global trick mapping\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* p_SkaterProfile = skate_mod->GetCurrentProfile();\r\n\tScript::CStruct* p_trickMappings = p_SkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") );\r\n\r\n\t// figure number of components in mapping\r\n\tuint32 size = p_keyCombos->GetSize();\r\n\r\n\t// safety first\r\n\tint max_tries = 100;\r\n\t\r\n\tuint32 trick_name_checksum = 0;\r\n\tuint32 key_combo;\r\n\twhile ( !trick_name_checksum )\r\n\t{        \r\n\t\tint i = Mth::Rnd( size );\r\n\t\tif ( p_keyCombos->GetType() == ESYMBOLTYPE_NAME )\r\n\t\t{\r\n\t\t\tkey_combo = p_keyCombos->GetChecksum( i );\r\n\t\t}\r\n\t\telse\r\n\t\t\tp_keyCombos->GetStructure( i )->GetChecksum( CRCD(0xacfdb27a,\"key_combo\"), &key_combo, Script::ASSERT );\r\n\r\n\t\t// see if this is a valid key_combo\r\n\t\tint cat_index;\r\n\t\tp_trickMappings->GetChecksum( key_combo, &trick_name_checksum, Script::NO_ASSERT );\r\n\t\tif ( trick_name_checksum )\r\n\t\t{\r\n\t\t\treturn i;\r\n\t\t}\r\n\t\telse if ( p_trickMappings->GetInteger( key_combo, &cat_index, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\treturn i;\r\n\t\t}\r\n\t\t// reset it to 0\r\n\t\ttrick_name_checksum = 0;\r\n\t\tmax_tries--;\r\n\t\tif ( max_tries == 0 )\r\n\t\t{\r\n\t\t\t// they've probably un-mapped all their keys.  check all the tricks in order\r\n\t\t\t// just to be safe\r\n\t\t\tfor ( uint32 j = 0; j < size; j++ )\r\n\t\t\t{\r\n\t\t\t\tif ( p_keyCombos->GetType() == ESYMBOLTYPE_NAME )\r\n\t\t\t\t\tkey_combo = p_keyCombos->GetChecksum( j );\r\n\t\t\t\telse\r\n\t\t\t\t\tp_keyCombos->GetStructure( j )->GetChecksum( CRCD(0xacfdb27a,\"key_combo\"), &key_combo, Script::ASSERT );\r\n\t\t\t\tp_trickMappings->GetChecksum( key_combo, &trick_name_checksum, Script::NO_ASSERT );\r\n\t\t\t\tif ( trick_name_checksum )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn i;\r\n\t\t\t\t}\r\n\t\t\t\ttrick_name_checksum = 0;\r\n\t\t\t}\r\n\t\t\t// they did un-map all their keys.  Fuck 'em\r\n\t\t\tNoValidKeyCombos();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::NoValidKeyCombos()\r\n{\r\n\tScript::CStruct* p_temp_params = new Script::CStruct();\r\n\tp_temp_params->AddChecksum( CRCD(0x9982e501,\"goal_id\"), GetGoalId() );\r\n\tScript::RunScript( CRCD( 0xf3c20af5, \"goal_no_valid_key_combos\" ), p_temp_params );\r\n\tdelete p_temp_params;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nuint32 CGoal::GetRootGoalId()\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tCGoal* pParentGoal = this;\t\r\n\tDbg_Assert( pGoalManager );\r\n\t\r\n\t// get the root node\r\n\tCGoalLink* p_parent = mp_parents;\r\n\twhile ( p_parent && p_parent->m_relative != 0 )\r\n\t{\r\n\t\tpParentGoal = pGoalManager->GetGoal( p_parent->m_relative );\r\n\t\tp_parent = pParentGoal->GetParents();\r\n\t}\r\n\r\n\treturn pParentGoal->GetGoalId();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nuint32 CGoal::GetGoalId()\r\n{\r\n    uint32 goalId = 0;\r\n    mp_params->GetChecksum( \"goal_id\", &goalId, Script::ASSERT );\r\n    return goalId;\r\n}\r\n\r\nbool CGoal::IsEditedGoal()\r\n{\r\n\tDbg_MsgAssert(mp_params,(\"NULL mp_params\"));\r\n\treturn mp_params->ContainsFlag(CRCD(0x981d3ad0,\"edited_goal\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::HasWonGoal()\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\t\r\n\tif ( gamenet_man->InNetGame() && \r\n\t\t ( skate_mod->GetGameMode()->GetNameChecksum() == CRCD( 0xec200eaa, \"netgoalattack\" )) ||\r\n\t\t ( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0x1c471c60,\"netlobby\")))\r\n\t{\r\n\t\treturn m_netIsBeat;\r\n\t}\r\n\treturn m_isbeat;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::HasWonStage()\r\n{\r\n\tif ( HasWonGoal() )\r\n\t\treturn true;\t\r\n\telse\r\n\t{\r\n\t\tCGoalLink* pLink = mp_children;\r\n\t\twhile ( pLink )\r\n\t\t{\r\n\t\t\tif ( pLink->m_beaten )\r\n\t\t\t\treturn true;\r\n\t\t\telse\r\n\t\t\t\tpLink = pLink->mp_next;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::IsSelected()\r\n{\r\n\treturn m_isselected;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::GotCounterObject()\r\n{\r\n\tint number_collected = 0;\r\n    mp_params->GetInteger( CRCD(0x129daa10,\"number_collected\"), &number_collected, Script::NO_ASSERT );\r\n    // printf(\"alredy collected %i\\n\", number_collected);\r\n    number_collected++;\r\n\r\n    mp_params->AddInteger( CRCD(0x129daa10,\"number_collected\"), number_collected );\r\n\r\n\tif ( mp_params->ContainsFlag( CRCD(0xfd7ae1f4,\"use_hud_counter\") ) )\r\n\t\tScript::RunScript( CRCD(0xf2e85a34,\"goal_update_counter\"), mp_params );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::CounterGoalDone()\r\n{\r\n    int number_collected = 0;\r\n    mp_params->GetInteger( CRCD(0x129daa10,\"number_collected\"), &number_collected, Script::NO_ASSERT );\r\n\r\n    int number;\r\n    mp_params->GetInteger( CRCD(0x696fe0ab,\"number\"), &number, Script::ASSERT );\r\n\r\n    return ( number_collected >= number );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::MarkInvalid()\r\n{\r\n    m_invalid = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::IsInvalid()\r\n{\r\n    return m_invalid;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::HasProset( const char* proset_prefix )\r\n{\r\n    const char* p_local_proset;\r\n    if ( mp_params->GetString( CRCD(0x955c6305,\"proset_prefix\"), &p_local_proset, Script::NO_ASSERT ) )\r\n    {\r\n        if ( stricmp( p_local_proset, proset_prefix ) == 0 )\r\n            return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::SetHasSeen()\r\n{\r\n    m_hasSeen = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::MarkBeaten()\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\r\n\tif( gamenet_man->InNetGame()  && skate_mod->GetGameMode()->GetNameChecksum() == CRCD( 0xec200eaa, \"netgoalattack\" ) )\r\n\t{\r\n\t\tm_netIsBeat = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_isbeat = true;\r\n\t}\r\n\t// mark all goals in the tree beaten\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tGame::CGoalLink* p_link = mp_parents;\r\n\twhile ( p_link && p_link->m_relative != 0 )\r\n\t{\r\n\t\tCGoal* pGoal = pGoalManager->GetGoal( p_link->m_relative );\r\n\t\tpGoal->MarkBeaten();\r\n\t\tp_link = p_link->mp_next;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::MarkBeatenBy( int id )\r\n{\r\n\tDbg_Printf( \"**** Marking goal 0x%x as beaten\\n\", GetGoalId());\r\n\tm_beatenFlags.Set( id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::MarkBeatenByTeam( int team_id )\r\n{\r\n\tm_teamBeatenFlags.Set( team_id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::HasWonGoal( int id )\r\n{\r\n\treturn m_beatenFlags.Test( id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::HasTeamWonGoal( int team_id )\r\n{\r\n\treturn m_teamBeatenFlags.Test( team_id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::Select()\r\n{\r\n\tm_isselected = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::Deselect()\r\n{\r\n\tm_isselected = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::SetUnlocked()\r\n{\r\n    m_isLocked = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::SetLevelNum( int levelNum )\r\n{\r\n    m_levelNum = levelNum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CGoal::GetLevelNum()\r\n{\r\n    return m_levelNum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::CheckMinigameRecord( int value )\r\n{\r\n\tint record = 0;\r\n\tmp_params->GetInteger( CRCD(0x78ffb85c,\"minigame_record\"), &record, Script::NO_ASSERT );\r\n\r\n\tmp_params->AddInteger( CRCD(0x819fc1d1,\"last_attempt\"), value );\r\n\tif ( value > record )\r\n\t{\r\n\t\tmp_params->AddInteger( CRCD(0x78ffb85c,\"minigame_record\"), value );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CGoal::GetMinigameRecord()\r\n{\r\n\tint minigame_record = -1;\r\n\tmp_params->GetInteger( CRCD(0x78ffb85c,\"minigame_record\"), &minigame_record, Script::NO_ASSERT );\r\n\treturn minigame_record;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::CanRetry()\r\n{\r\n\treturn ( !mp_params->ContainsFlag( CRCD(0xa612f12c,\"no_restart\") ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::IsMinigame()\r\n{\r\n\treturn ( mp_params->ContainsFlag( CRCD(0x6bae094c,\"minigame\") ) );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::SetStartTime()\r\n{\r\n\tmp_params->AddInteger( CRCD(0x5fd80edc,\"current_time\"), 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::UpdateComboTimer()\r\n{\r\n\tif ( !IsPaused() )\r\n\t{\r\n\t\tTmr::Time current_time = 0;\r\n\t\tint time;\r\n\t\tmp_params->GetInteger( CRCD(0x5fd80edc,\"current_time\"), &time, Script::NO_ASSERT );\r\n\t\tcurrent_time = (Tmr::Time)time;\r\n\t\r\n\t\tcurrent_time +=  (Tmr::Time)( Tmr::FrameLength() * 1000 );\r\n\t\r\n\t\tmp_params->AddInteger( CRCD(0x5fd80edc,\"current_time\"), (int)current_time );\r\n\r\n\t\t// add normal units for display\r\n\t\tmp_params->AddInteger( CRCD(0x7b1fe9a4,\"current_time_seconds\"), (int)( current_time / 1000 ) );\r\n\t\tmp_params->AddInteger( CRCD(0xb4db9cb7,\"current_time_fraction\"), (int)( ( current_time / 10 ) % 100 ) );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::SetStartHeight()\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater *p_skater = skate_mod->GetLocalSkater();\r\n\tDbg_Assert( p_skater );\r\n\r\n\tint start_height = static_cast< int >(GetSkaterStateComponentFromObject(p_skater)->GetHeight());\r\n\tmp_params->AddInteger( CRCD(0xc07d8d60,\"start_height\"), start_height );\r\n\r\n\t// printf(\"setting start height to %i\\n\", start_height);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::CheckHeightRecord()\r\n{\r\n\tif ( !IsPaused() )\r\n\t{\r\n\t\tint record = 0;\r\n\t\tmp_params->GetInteger( CRCD(0x78ffb85c,\"minigame_record\"), &record, Script::NO_ASSERT );\r\n\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tObj::CSkater *p_skater = skate_mod->GetLocalSkater();\r\n\t\tDbg_Assert( p_skater );\r\n\r\n\t\tint start_height = 10000;\r\n\t\tmp_params->GetInteger( CRCD(0xc07d8d60,\"start_height\"), &start_height, Script::NO_ASSERT );\r\n\t\t\r\n\t\tint current_height = static_cast< int >(GetSkaterStateComponentFromObject(p_skater)->GetHeight()) - start_height;\r\n\r\n\t\t//printf(\"current_height: %i\\n\", current_height);\r\n\r\n\t\tif ( current_height < 0 )\r\n\t\t\tcurrent_height = 0;\t\t\r\n\r\n\t\tint feet = (int)( current_height / 12 );\r\n\t\tint inches = current_height % 12;\r\n\r\n\t\tmp_params->AddInteger( CRCD(0x50815d42,\"current_height_feet\"), feet );\r\n\t\tmp_params->AddInteger( CRCD(0xb0c26927,\"current_height_inches\"), inches );\r\n\t\t\r\n\t\tif ( current_height > record )\r\n\t\t{\r\n\t\t\tmp_params->AddInteger( CRCD(0x78ffb85c,\"minigame_record\"), current_height );\r\n\t\t\t\r\n\t\t\tmp_params->AddInteger( CRCD(0x24bf3ae4,\"record_feet\"), feet );\r\n\t\t\tmp_params->AddInteger( CRCD(0x9b49f28d,\"record_inches\"), inches );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::CheckDistanceRecord()\r\n{\r\n\t// find the object in question\r\n\tuint32 objId;\r\n\tmp_params->GetChecksum( CRCD(0x8e18f3b3,\"distance_record_object\"), &objId, Script::ASSERT );\r\n\r\n\t// grab the object\r\n\tObj::CMovingObject* pObj = NULL;\r\n//\tpObj = Obj::CMovingObject::m_hash_table.GetItem( objId );\r\n\tpObj = (Obj::CMovingObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID( objId);\r\n\r\n\t// grab the skater\r\n\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetLocalSkater();\r\n\t\r\n\tif ( pSkater && pObj )\r\n\t{\r\n\t\tfloat distSquared = Mth::DistanceSqr( pObj->m_pos, pSkater->m_pos );\r\n\t\t\r\n\t\t// get the height of the two\r\n\t\tfloat objHeight = pObj->m_pos.GetY();\r\n\t\tfloat skaterHeight = pSkater->m_pos.GetY();\r\n\r\n\t\t// get the base of the right triangle formed by the three points\r\n\t\tfloat distance = sqrtf(\tdistSquared - ( Mth::Sqr( skaterHeight - objHeight ) ) );\r\n\t\t// printf(\"distance = %f\\n\", distance);\r\n\r\n\t\tint feet = (int)( distance / 12 );\r\n\t\tint inches = (int)distance % 12;\r\n\t\t\r\n\t\tmp_params->AddInteger( CRCD(0xcb48c8e8,\"current_distance_feet\"), feet );\r\n\t\tmp_params->AddInteger( CRCD(0x644fc146,\"current_distance_inches\"), inches );\r\n\t\t\r\n\t\tint record = 0;\r\n\t\tmp_params->GetInteger( CRCD(0x78ffb85c,\"minigame_record\"), &record, Script::NO_ASSERT );\t\t\r\n\t\tif ( distance > record )\r\n\t\t{\r\n\t\t\tmp_params->AddInteger( CRCD(0x78ffb85c,\"minigame_record\"), distance );\r\n\t\t\r\n\t\t\tmp_params->AddInteger( CRCD(0x24bf3ae4,\"record_feet\"), feet );\r\n\t\t\tmp_params->AddInteger( CRCD(0x9b49f28d,\"record_inches\"), inches );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::SetQuickStartFlag()\r\n{\r\n\tmp_params->AddChecksum( NONAME, CRCD( 0x38221df4, \"quick_start\" ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::UnsetQuickStartFlag()\r\n{\r\n\tmp_params->RemoveFlag( CRCD(0x38221df4,\"quick_start\") );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::IsProGoal()\r\n{\r\n\treturn ( mp_params->ContainsComponentNamed( CRCD(0xd303a1a3,\"pro_goal\") ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::IsNetGoal()\r\n{\r\n\treturn ( mp_params->ContainsComponentNamed( CRCD(0xd15ea00,\"net\") ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::IsCompetition()\r\n{\r\n\treturn ( mp_params->ContainsFlag( CRCD(0x4af5d34e,\"competition\") ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::IsPaused()\r\n{\r\n\treturn m_paused;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::UnBeatGoal()\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tif( gamenet_man->InNetGame() )\r\n\t{\r\n\t\tm_beatenFlags = 0;\r\n\t\tm_teamBeatenFlags = 0;\r\n\t\tif( m_netIsBeat )\r\n\t\t{\r\n\t\t\tm_netIsBeat = false;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( m_isbeat )\r\n\t\t{\r\n\t\t\tm_isbeat = false;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}    \r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::GetViewGoalsText( const char** p_view_goals_text )\r\n{\r\n\tmp_params->GetText( \"view_goals_text\", p_view_goals_text, Script::NO_ASSERT );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::IsBettingGame()\r\n{\r\n\treturn ( mp_params->ContainsFlag( CRCD(0x8add4306,\"betting_game\") ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::IsBettingGuy()\r\n{\r\n\treturn ( mp_params->ContainsFlag( CRCD(0x8cfee956,\"betting_guy\") ) );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::EndRunCalled()\r\n{\r\n\treturn m_endRunCalled;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::ClearEndRun( Script::CScript* pScript )\r\n{\r\n\t// printf(\"CGoal::ClearEndRun called\\n\");\r\n\tm_endRunCalled = false;\r\n\r\n\t// TODO: this should pick the right skater somehow\r\n\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* p_skater = skate_mod->GetLocalSkater();\r\n\r\n\tObj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(p_skater);\r\n\tDbg_Assert(p_skater_endrun_component);\r\n\r\n\tswitch ( m_endRunType )\r\n\t{\r\n\tcase vENDOFRUN:\r\n// Mick: the way these type of exception is handled has changed\r\n// I'm not sure if it still needs to be cleared here any more\r\n// as it should have been executed immediately\r\n// I'm removing this line for now, as the ExceptionComponent has gone  \r\n//\t\tGetExceptionComponentFromObject(p_skater)->ClearException( CRCD( 0x822e13a9, \"RunHasEnded\" ));\r\n\t\tp_skater->CallMemberFunction( CRCD( 0x4c58771e, \"EndOfRunDone\" ), NULL, pScript );\r\n\t\tp_skater_endrun_component->ClearStartedEndOfRunFlag();\r\n\t\tbreak;\r\n\tcase vGOALENDOFRUN:\r\n//\t\tGetExceptionComponentFromObject(p_skater)->ClearException( CRCD( 0xab676175, \"GoalHasEnded\" ) );\r\n\t\tp_skater->CallMemberFunction( CRCD( 0x69a9e37f, \"Goal_EndOfRunDone\" ), NULL, pScript );\r\n\t\tp_skater_endrun_component->ClearStartedGoalEndOfRunFlag();\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::FinishedEndOfRun()\r\n{\r\n\t// TODO: make this pick the right skater\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* p_skater = skate_mod->GetLocalSkater();\r\n\r\n\tObj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(p_skater);\r\n\tDbg_Assert(p_skater_endrun_component);\r\n\r\n\tswitch ( m_endRunType )\r\n\t{\r\n\tcase vENDOFRUN:\r\n\t\treturn p_skater_endrun_component->RunHasEnded();\r\n\t\tbreak;\r\n\tcase vGOALENDOFRUN:\r\n\t\treturn p_skater_endrun_component->GoalRunHasEnded();\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::StartedEndOfRun()\r\n{\r\n\t// TODO: make this choose the right skater\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* p_skater = skate_mod->GetLocalSkater();\r\n\r\n\tObj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(p_skater);\r\n\tDbg_Assert(p_skater_endrun_component);\r\n\r\n\tswitch ( m_endRunType )\r\n\t{\r\n\tcase vENDOFRUN:\r\n\t\treturn p_skater_endrun_component->StartedEndOfRun();\r\n\t\tbreak;\r\n\tcase vGOALENDOFRUN:\r\n\t\t// return p_skater->StartedGoalEndOfRun();\r\n\t\treturn m_endRunCalled;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// void CGoal::DisableEndOfRun()\r\n// {\r\n//\tm_shouldEndRun = false;\r\n// }\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::AddTempSpecialTrick()\r\n{\r\n\t// get the new special trick name and type\t\r\n\tuint32 trickType;\r\n\tbool is_cat = mp_params->ContainsFlag( CRCD(0x8e6014f6,\"create_a_trick\") );\r\n\t\r\n\tmp_params->GetChecksum( \"trick_type\", &trickType, Script::ASSERT );\r\n\tuint32 trickName;\t\r\n\tif ( is_cat )\r\n\t{\r\n\t\tint tempTrickName;\r\n\t\tmp_params->GetInteger( CRCD(0xb502200,\"premade_cat_index\"), &tempTrickName, Script::ASSERT );\r\n\t\ttrickName = (uint32)tempTrickName;\r\n\t}\r\n\telse\r\n\t\tmp_params->GetChecksum( \"trick_name\", &trickName, Script::ASSERT );\r\n\t\r\n\t// get the local string version of the trick and store it\r\n\tif ( is_cat )\r\n\t{\r\n\t\tScript::CArray* pPremadeCatArray = Script::GetArray( CRCD(0xffd7913f,\"Premade_CATS\"), Script::ASSERT );\r\n\t\tScript::CStruct* pPremadeCat = pPremadeCatArray->GetStructure( trickName );\r\n\t\tconst char* pPremadeCatName;\r\n\t\tpPremadeCat->GetString( CRCD(0xa1dc81f9,\"name\"), &pPremadeCatName, Script::ASSERT );\r\n\t\tmp_params->AddString( CRCD(0x3a54cc4b,\"trick_string\"), pPremadeCatName );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tconst char* trickName_string; \r\n\t\tScript::CStruct* p_trick = Script::GetStructure( trickName, Script::ASSERT );\r\n\t\tScript::CStruct* p_trick_params;\r\n\t\tp_trick->GetStructure( \"Params\", &p_trick_params, Script::ASSERT );\r\n\t\tp_trick_params->GetLocalString( \"Name\", &trickName_string, Script::ASSERT );\r\n\t\tmp_params->AddString( \"trick_string\", trickName_string );\r\n\t}\r\n\t\r\n\t// get the list of valid key bindings for this trick type\r\n\tScript::CStruct* p_keyBindings = NULL;\r\n\tswitch ( trickType )\r\n\t{\r\n\t\tcase CRCC( 0x61a1bc57, \"cat\" ):\r\n\t\tcase CRCC( 0x439f4704, \"air\" ):\r\n\t\t\tp_keyBindings = Script::GetStructure( CRCD( 0x4764231d, \"goal_special_tricks_air\" ), Script::ASSERT );\r\n\t\t\tbreak;\r\n\t\tcase CRCC( 0xa549b57b, \"lip\" ):\r\n\t\t\tp_keyBindings = Script::GetStructure( CRCD( 0xa1b2d162, \"goal_special_tricks_lip\" ), Script::ASSERT );\r\n\t\t\tbreak;\r\n\t\tcase CRCC( 0x255ed86f, \"grind\" ):\r\n\t\t\tp_keyBindings = Script::GetStructure( CRCD( 0xf481d0cd, \"goal_special_tricks_grind\" ), Script::ASSERT );\r\n\t\t\tbreak;\r\n\t\tcase CRCC( 0xef24413b, \"manual\" ):\r\n\t\t\tp_keyBindings = Script::GetStructure( CRCD( 0xd72d5cf7, \"goal_special_tricks_manual\" ), Script::ASSERT );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( p_keyBindings, ( \"AddTempSpecialTrick got weird trick type\\n\" ) );\r\n\t}\r\n\r\n\tObj::CPlayerProfileManager* pPlayerProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pSkaterProfile = pPlayerProfileManager->GetCurrentProfile();\r\n\t// Script::CStruct* p_trickMapping = p_SkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") );\r\n\r\n\tint numTricks = pSkaterProfile->GetNumSpecialTrickSlots();\r\n\t\r\n\t// we need to remember the key combo\r\n\tuint32 key_combo = 0;\r\n\r\n\t// search through current special tricks\r\n\tbool found_trick = false;\r\n\tfor ( int i = 0; i < numTricks; i++ )\r\n\t{\r\n\t\tObj::SSpecialTrickInfo trick_info = pSkaterProfile->GetSpecialTrickInfo( i );\r\n\t\t\r\n\t\tif ( !is_cat && trick_info.m_TrickName == trickName )\r\n\t\t{\r\n\t\t\t// printf(\"the special trick is already bound!\\n\");\r\n\t\t\tfound_trick = true;\r\n\t\t\tkey_combo = trick_info.m_TrickSlot;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tp_keyBindings->RemoveFlag( trick_info.m_TrickSlot );\r\n\t}\r\n\r\n\t// if we didn't find the trick, grab the first available, unused key combo\r\n\tif ( !found_trick )\r\n\t{\r\n\t\t// printf(\"binding special trick\\n\");\r\n\t\tScript::CComponent* p_comp = p_keyBindings->GetNextComponent();\r\n\t\tDbg_MsgAssert( p_comp, ( \"Could not find an open key binding\\n\" ) );\r\n\t\tuint32 trickSlot = p_comp->mChecksum;\r\n\t\tDbg_MsgAssert( trickSlot, ( \"Could not find key binding in structure\" ) );\r\n\t\t\r\n\t\t// give everyone a new slot\r\n\t\t/*int num_profiles = pPlayerProfileManager->GetNumProfileTemplates();\r\n\t\tfor ( int i = 0; i < num_profiles; i++ )\r\n\t\t{\r\n\t\t\tObj::CSkaterProfile* pTempProfile = pPlayerProfileManager->GetProfileTemplateByIndex( i );\r\n\t\t\tpTempProfile->AwardSpecialTrickSlot();\r\n\t\t}*/\r\n\t\tpSkaterProfile->AwardSpecialTrickSlot();\r\n\r\n\t\tkey_combo = trickSlot;\r\n\t\tif ( is_cat )\r\n\t\t{\r\n\t\t\t// assign cat to trickslot\r\n\t\t\tScript::CStruct* pScriptParams = new Script::CStruct();\r\n\t\t\tpScriptParams->AddChecksum( CRCD(0xa92a2280,\"trickSlot\"), trickSlot );\r\n\t\t\tpScriptParams->AddInteger( CRCD(0x7f8c98fe,\"index\"), trickName );\r\n\t\t\tpScriptParams->AddInteger( CRCD(0x7f264be9,\"special_trick_index\"), numTricks );\r\n\t\t\tScript::RunScript( CRCD(0x466576c8,\"load_premade_cat\"), pScriptParams );\r\n\t\t\tdelete pScriptParams;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// add new trick to new slot\r\n\t\t\tObj::SSpecialTrickInfo trickInfo;\r\n\t\t\ttrickInfo.m_TrickSlot = trickSlot;\r\n\t\t\ttrickInfo.m_TrickName = trickName;\r\n\t\t\tpSkaterProfile->SetSpecialTrickInfo( numTricks, trickInfo );\r\n\t\t}\r\n\r\n\t\t// make a note of this so we can remove it later\r\n\t\tmp_params->AddInteger( CRCD( 0xbc678826, \"should_remove_trick\" ), 1 );\r\n\t}\r\n\r\n\t// testing\r\n\t// Script::PrintContents( p_SkaterProfile->GetSpecialTricksStructure() );\r\n\r\n\t// replace the key combo array\r\n\tmp_params->RemoveComponent( \"key_combos\" );\r\n\tScript::CArray* p_key_combos = new Script::CArray();\r\n\tp_key_combos->SetSizeAndType( 1, ESYMBOLTYPE_NAME );\r\n\r\n\tp_key_combos->SetChecksum( 0, key_combo );\r\n\r\n\tmp_params->AddArrayPointer( \"key_combos\", p_key_combos );\r\n\t// printf(\"added special trick\\n\");\r\n\t// Script::PrintContents( mp_params );\r\n\tReplaceTrickText();\r\n\t\r\n\treturn !found_trick;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::RemoveTempSpecialTrick()\r\n{\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tObj::CPlayerProfileManager* pPlayerProfileManager = skate_mod->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pSkaterProfile = pPlayerProfileManager->GetCurrentProfile();\r\n\r\n\t// do we need to take out the trick we added?\r\n\tint should_remove;\r\n\tmp_params->GetInteger( \"should_remove_trick\", &should_remove, Script::ASSERT );\r\n\tif ( should_remove == 1 )\r\n\t{\r\n\t\t// printf(\"removing special trick\\n\");\r\n\t\t// find it and take it out\r\n\t\tuint32 trickName;\r\n\t\t\r\n\t\tif ( mp_params->ContainsFlag( CRCD(0x8e6014f6,\"create_a_trick\") ) )\r\n\t\t{\r\n\t\t\t// int premade_cat_index;\r\n\t\t\t// mp_params->GetInteger( CRCD(0xb502200,\"premade_cat_index\"), &premade_cat_index, Script::ASSERT );\r\n\t\t\t// trickName = (uint32)premade_cat_index;\r\n\t\t\t\r\n\t\t\t// temp cat tricks are always on 0\r\n\t\t\ttrickName = 0;\r\n\t\t}\r\n\t\telse\r\n\t\t\tmp_params->GetChecksum( CRCD( 0xef6fb249, \"trick_name\" ), &trickName, Script::ASSERT );\r\n\r\n\t\t// int numTricks = p_SkaterProfile->GetNumSpecialTrickSlots();\r\n\t\t// just look through all tricks\r\n\t\tfor ( int i = 0; i < Obj::CSkaterProfile::vMAXSPECIALTRICKSLOTS; i++ )\r\n\t\t{\r\n\t\t\tObj::SSpecialTrickInfo trick_info = pSkaterProfile->GetSpecialTrickInfo( i );\r\n\t\t\t// printf(\"m_TrickName: %x, trickName: %x\\n\", trick_info.m_TrickName, trickName );\r\n\t\t\tif ( trick_info.m_TrickName == trickName )\r\n\t\t\t{\r\n\t\t\t\t// printf(\"Removing special trick\\n\");\r\n\t\t\t\tObj::SSpecialTrickInfo new_info;\r\n\t\t\t\tnew_info.m_TrickName = CRCD( 0xf60c9090, \"unassigned\" );\r\n\t\t\t\tnew_info.m_TrickSlot = CRCD( 0xf60c9090, \"unassigned\" );\r\n\t\t\t\tpSkaterProfile->SetSpecialTrickInfo( i, new_info );\r\n\t\t\t\tmp_params->AddInteger( CRCD( 0xbc678826, \"should_remove_trick\" ), 0 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// take a slot away from everyone\r\n\t\t/*int num_profiles = pPlayerProfileManager->GetNumProfileTemplates();\r\n\t\tfor ( int i = 0; i < num_profiles; i++ )\r\n\t\t{\r\n\t\t\tObj::CSkaterProfile* pTempProfile = pPlayerProfileManager->GetProfileTemplateByIndex( i );\r\n\t\t\tpTempProfile->AwardSpecialTrickSlot( -1 );\r\n\t\t}*/\r\n\t\tpSkaterProfile->AwardSpecialTrickSlot( -1 );\r\n\t}\r\n\t\r\n\tmp_params->RemoveComponent( CRCD(0x79704516,\"key_combos\") );\r\n\r\n\tDbg_MsgAssert( (int)pSkaterProfile->GetNumSpecialTrickSlots() <= Script::GetInteger( CRCD(0x20297d6f,\"max_number_of_special_trickslots\") ), ( \"You have too many trickslots!\" ) );\r\n\t// Script::CStruct* pTest = pSkaterProfile->GetSpecialTricksStructure();\r\n\t// printf(\"done removing\\n\");\r\n\t// Script::PrintContents( pTest );\r\n\r\n\t// remove the display string just in case\r\n\tmp_params->RemoveComponent( \"key_combo_string\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::ShouldUseTimer()\r\n{\r\n\tint unlimited_time = 0;\r\n\r\n\tmp_params->GetInteger( CRCD(0xf0e712d2,\"unlimited_time\"), &unlimited_time );\r\n\r\n\treturn ( unlimited_time == 0 );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::CountAsActive()\r\n{\r\n\treturn IsActive();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::LoadSaveData( Script::CStruct *pFlags )\r\n{\r\n\tint hasBeaten = 0;\r\n\tpFlags->GetInteger( \"hasBeaten\", &hasBeaten, Script::ASSERT );\r\n\tif ( hasBeaten != 0 )\r\n\t\tMarkBeaten();\r\n\t\r\n\tint isLocked = 1;\r\n\tpFlags->GetInteger( \"isLocked\", &isLocked, Script::ASSERT );\r\n\tif ( isLocked == 0 )\r\n\t{\r\n\t\t// special case for pro challenges\r\n/*\t\tif ( mp_params->ContainsFlag( \"pro_specific_challenge\" ) && hasBeaten == 0 )\r\n\t\t{\r\n\t\t\tif ( mp_goalPed->ProIsCurrentSkater() )\r\n\t\t\t\tSetUnlocked();\r\n\t\t}\r\n\t\telse\r\n*/\r\n\t\tSetUnlocked();\r\n\t}\r\n\r\n\tint hasSeen = 0;\r\n\tpFlags->GetInteger( \"hasSeen\", &hasSeen, Script::ASSERT );\r\n\tif ( hasSeen != 0 )\r\n\t\tSetHasSeen();\r\n\t\r\n\t\r\n\t// check for a completion record\r\n\tint record = 0;\r\n\tpFlags->GetInteger( CRCD( 0xc22a2b72, \"win_record\" ), &record, Script::ASSERT );\r\n\tmp_params->AddInteger( \"win_record\", record );\r\n\tuint32 record_type;\r\n\tif ( mp_params->GetChecksum( \"record_type\", &record_type, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tif ( record_type == Script::GenerateCRC( \"time\" ) )\r\n\t\t\tm_elapsedTimeRecord = record;\r\n\t\telse if ( record_type == Script::GenerateCRC( \"score\" ) )\r\n\t\t\tm_winScoreRecord = record;\r\n\t}\r\n\r\n\tpFlags->GetInteger( \"timesLost\", &m_numTimesLost, Script::ASSERT );\r\n\tpFlags->GetInteger( \"timesWon\", &m_numTimesWon, Script::ASSERT );\r\n\tpFlags->GetInteger( \"timesStarted\", &m_numTimesStarted, Script::ASSERT );\r\n\r\n\tuint32 team_pro;\r\n\tpFlags->GetChecksum( CRCD(0xced8a3a4,\"team_pro\"), &team_pro, Script::ASSERT );\r\n\tif ( team_pro != 0 )\r\n\t{\r\n\t\tmp_params->AddChecksum( CRCD(0xced8a3a4,\"team_pro\"), team_pro );\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::GetSaveData( Script::CStruct* pFlags )\r\n{\r\n\tpFlags->AddInteger( \"levelNum\", GetLevelNum() );\r\n\r\n\tint isLocked = IsLocked();\r\n\tpFlags->AddInteger( \"isLocked\", isLocked );\r\n\r\n\tint hasSeen = HasSeenGoal();\r\n\tpFlags->AddInteger( \"hasSeen\", hasSeen );\r\n\r\n\tint hasBeaten = HasWonGoal();\r\n\tpFlags->AddInteger( \"hasBeaten\", hasBeaten );\r\n\t\r\n/*\tint isProSpecificChallenge = 0;\r\n\tif ( mp_params->ContainsFlag( \"pro_specific_challenge\" ) )\r\n\t\tisProSpecificChallenge = 1;\r\n\tpFlags->AddInteger( \"isProSpecificChallenge\", isProSpecificChallenge );\r\n*/\r\n\r\n\tint record = 0;\r\n\tuint32 record_type;\r\n\tif ( mp_params->GetChecksum( \"record_type\", &record_type, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tif ( record_type == Script::GenerateCRC( \"time\" ) )\r\n\t\t\trecord = (int)m_elapsedTimeRecord;\r\n\t\telse if ( record_type == Script::GenerateCRC( \"score\" ) )\r\n\t\t\trecord = m_winScoreRecord;\r\n\t}\r\n\tpFlags->AddInteger( \"win_record\", record );\r\n\r\n\t// TODO: should this be removed for the release?\r\n\tpFlags->AddInteger( \"timesLost\", m_numTimesLost );\r\n\tpFlags->AddInteger( \"timesWon\", m_numTimesWon );\r\n\tpFlags->AddInteger( \"timesStarted\", m_numTimesStarted );\r\n\r\n\tuint32 team_pro = 0;\r\n\tmp_params->GetChecksum( CRCD(0xced8a3a4,\"team_pro\"), &team_pro, Script::NO_ASSERT );\r\n\tpFlags->AddChecksum( CRCD(0xced8a3a4,\"team_pro\"), team_pro );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// utility used by ReplaceTrickText\r\nbool fill_trick_and_key_combo_arrays( Script::CArray* p_key_combos, Script::CArray* p_key_combo_strings, Script::CArray* p_trick_names, int premade_cat_index )\r\n{\t\r\n\t// make sure the arrays are the right size and type\r\n\tDbg_MsgAssert( p_key_combos->GetSize() == p_key_combo_strings->GetSize(), ( \"key combo string array wrong size\" ) );\r\n\tDbg_MsgAssert( p_key_combos->GetSize() == p_trick_names->GetSize(),\t( \"trick name array wrong size\" ) );\r\n\tDbg_MsgAssert( p_key_combo_strings->GetType() == ESYMBOLTYPE_STRING, ( \"array is the wrong type\" ) );\r\n\tDbg_MsgAssert( p_trick_names->GetType() == ESYMBOLTYPE_STRING, ( \"array is the wrong type\" ) );\r\n\t\r\n\tScript::CStruct* p_key_combo_map = Script::GetStructure( CRCD(0x8856c817,\"goal_tetris_trick_text\"), Script::ASSERT );\r\n\t\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile();\r\n\tScript::CStruct* pTricks = pSkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") );\r\n\r\n\t// Script::PrintContents( pTricks );\r\n\r\n\tint size = p_key_combos->GetSize();\r\n\t\r\n\tfor ( int i = 0; i < size; i++ )\r\n\t{\r\n\t\tuint32 key_combo = p_key_combos->GetChecksum( i );\r\n\t\t// printf(\"checking for key combo %s\\n\", Script::FindChecksumName( key_combo ) );\r\n\t\tuint32 trick_checksum = 0;\r\n\t\tbool found_a_match = false;\r\n\t\tint cat_trick_index = 0;\r\n\t\tbool found_cat = false;\r\n\t\tif ( pTricks->GetInteger( key_combo, &cat_trick_index, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\t// load cat info\r\n\t\t\tprintf(\"found a cat trick - cat_trick_index = %i\\n\", cat_trick_index);\r\n\t\t\tfound_cat = true;\r\n\t\t\tfound_a_match = true;\r\n\t\t}\r\n\t\telse if ( pTricks->GetChecksum( key_combo, &trick_checksum, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tfound_a_match = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// look for a special key combo\r\n\t\t\tint numSpecials = pSkaterProfile->GetNumSpecialTrickSlots();\r\n\t\t\t// printf(\"checking special trick slots\\n\");\r\n\t\t\tfor ( int j = 0; j < numSpecials; j++ )\r\n\t\t\t{\r\n\t\t\t\tObj::SSpecialTrickInfo trick_info = pSkaterProfile->GetSpecialTrickInfo( j );\r\n\t\t\t\t// printf(\"trickslot: %s\\n\", Script::FindChecksumName( trick_info.m_TrickSlot ) );\r\n\t\t\t\tif ( trick_info.m_TrickSlot == key_combo )\r\n\t\t\t\t{\r\n\t\t\t\t\t// printf(\"found a match\\n\");\r\n\t\t\t\t\ttrick_checksum = trick_info.m_TrickName;\r\n\t\t\t\t\tfound_a_match = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( !found_a_match )\r\n\t\t{\r\n\t\t\t// Script::PrintContents( pTricks );\r\n\t\t\t// this key combo isn't assigned!  bail out...\r\n\t\t\tDbg_MsgAssert( 0, ( \"key combo %s not assigned!\\n\", Script::FindChecksumName( key_combo ) ) );\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst char* p_key_combo_string;\r\n\t\tp_key_combo_map->GetString( key_combo, &p_key_combo_string, Script::ASSERT );\r\n\t\tconst char* p_trick_name;\r\n\t\tif ( found_cat )\r\n\t\t{            \r\n\t\t\t// printf(\"getting cat params\\n\");\r\n\t\t\tObj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n\t\t\tif ( pSkater )\r\n\t\t\t{\r\n\t\t\t\t// printf(\"got skater\\n\");\r\n\t\t\t\tGame::CCreateATrick* pCreatedTrick = pSkater->m_created_trick[cat_trick_index];\r\n\t\t\t\tDbg_Assert( pCreatedTrick );\r\n\t\t\t\t// Script::PrintContents( pCreatedTrick->mp_other_params );\r\n\t\t\t\tpCreatedTrick->mp_other_params->GetString( CRCD( 0xa1dc81f9, \"name\" ), &p_trick_name, Script::ASSERT );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( premade_cat_index > -1 )\r\n\t\t\t{\r\n\t\t\t\tScript::CArray* pPremadeCats = Script::GetArray( CRCD(0xffd7913f,\"Premade_CATS\"), Script::ASSERT );\r\n\t\t\t\tScript::CStruct* pPremadeCat = pPremadeCats->GetStructure( premade_cat_index );\r\n\t\t\t\tpPremadeCat->GetString( CRCD(0xa1dc81f9,\"name\"), &p_trick_name, Script::ASSERT );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* p_trick_struct = Script::GetStructure( trick_checksum, Script::ASSERT );\r\n\t\t\t\tScript::CStruct* p_trick_params;\r\n\t\t\t\tp_trick_struct->GetStructure( CRCD(0x7031f10c,\"Params\"), &p_trick_params, Script::ASSERT );\r\n\t\t\t\tp_trick_params->GetLocalString( CRCD(0xa1dc81f9,\"Name\"), &p_trick_name, Script::ASSERT );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// printf(\"setting strings: %s\\n%s\\n\", p_key_combo_string, p_trick_name );\r\n\t\t\r\n\t\tp_key_combo_strings->SetString( i, Script::CreateString( p_key_combo_string ) );\r\n\t\tp_trick_names->SetString( i, Script::CreateString( p_trick_name ) );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n// utility used by CGoal::ReplaceTrickText...finds and replaces \\t and \\k with\r\n// the trick name and key combo, respectively\r\nvoid find_and_replace_trick_string( const char* p_old, char* p_out, Script::CArray* p_key, Script::CArray* p_trick, uint out_buffer_size )\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tconst char *p_out_start = p_out;\r\n\t#endif\r\n\tconst char *p_in = p_old;\t\r\n\twhile( *p_in )\r\n\t{\r\n\t\tint tag_num;\r\n\t\tif ( *p_in == '\\\\' && *(p_in+1) == 't' && ( *(p_in+2) <= '9' && *(p_in+2) >= '0' ) )\r\n\t\t{\r\n\t\t\t// printf(\"found the trick tag\\n\");\r\n\t\t\t\r\n\t\t\t// get the index\r\n\t\t\ttag_num = *(p_in+2) - 48;\r\n\t\t\tif ( *(p_in+3) <= '9' && *(p_in+3) >= '0' )\r\n\t\t\t{\r\n\t\t\t\ttag_num *= 10;\r\n\t\t\t\ttag_num += *(p_in+3) - 48;\r\n\t\t\t\t\r\n\t\t\t\t// move ahead an extra char\r\n\t\t\t\tp_in++;\r\n\t\t\t}\r\n\t\t\t// printf( \"found a tag num of %i\\n\", tag_num );\r\n\t\t\tDbg_MsgAssert( ( tag_num > 0 ) && tag_num <= (int)p_trick->GetSize(), ( \"Tag value too large\" ) );\r\n\t\t\tconst char* p_trick_string = p_trick->GetString( tag_num - 1 );\r\n\r\n\t\t\tDbg_MsgAssert( p_trick_string, ( \"ReplaceTrickText found a \\\\t tag but no key combo.\" ) );\r\n\r\n\t\t\tsprintf( p_out, p_trick_string );\r\n\t\t\tint length = strlen( p_trick_string );\r\n\t\t\tfor ( int i = 0; i < length; i++ )\r\n\t\t\t\tp_out++;\r\n\t\t\t\r\n\t\t\t// move past the tag\r\n\t\t\tp_in++;\r\n\t\t\tp_in++;\r\n\t\t\tp_in++;\r\n\t\t}\r\n\t\telse if ( *p_in == '\\\\' && *(p_in+1) == 'k' && ( *(p_in+2) <= '9' && *(p_in+2) >= '0' ) )\r\n\t\t{\r\n\t\t\t// printf(\"found the key tag\\n\");\r\n\t\t\t\r\n\t\t\t// get the index\r\n\t\t\ttag_num = *(p_in+2) - 48;\r\n\t\t\tif ( *(p_in+3) <= '9' && *(p_in+3) >= '0' )\r\n\t\t\t{\r\n\t\t\t\ttag_num *= 10;\r\n\t\t\t\ttag_num += *(p_in+3) - 48;\r\n\t\t\t\t\r\n\t\t\t\t// move ahead an extra char\r\n\t\t\t\tp_in++;\r\n\t\t\t}\r\n\t\t\t// printf( \"found a tag num of %i\\n\", tag_num );\r\n\t\t\tDbg_MsgAssert( ( tag_num > 0 ) && tag_num <= (int)p_key->GetSize(), ( \"Tag value too large\" ) );\r\n\t\t\tconst char* p_key_string = p_key->GetString( tag_num - 1 );\r\n\r\n\t\t\tDbg_MsgAssert( p_key_string, ( \"ReplaceTrickText found a \\\\k tag but no key combo.\" ) );\r\n\r\n\t\t\tsprintf( p_out, p_key_string );\r\n\t\t\tint length = strlen( p_key_string );\r\n\t\t\tfor ( int i = 0; i < length; i++ )\r\n\t\t\t\tp_out++;\r\n\t\t\t\r\n\t\t\t// move past the tag\r\n\t\t\tp_in++;\r\n\t\t\tp_in++;\r\n\t\t\tp_in++;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t*p_out++ = *p_in++;\r\n\t\t}\r\n\t}\r\n\t*p_out++ = '\\0';\r\n\tDbg_MsgAssert(strlen(p_out_start) < out_buffer_size,(\"String overflow with\\n\\n%s\\n\\nMake it shorter than %d chars, or get a bigger buffer\",p_out_start, out_buffer_size));\r\n}\r\n\r\nbool CGoal::ReplaceTrickText()\r\n{\r\n\t// printf(\"ReplaceTrickText %s\\n\", Script::FindChecksumName( GetGoalId() ) );\r\n\t// see if there's a key_combo associated with this goal\r\n\tScript::CArray* p_key_combo = NULL;\r\n\tif ( !mp_params->GetArray( \"key_combos\", &p_key_combo, Script::NO_ASSERT ) )\r\n\t{\r\n\t\t// printf(\"no key combos\\n\");\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// Make sure we have copies of the original text.  We want\r\n\t// to update properly if they change their trick bindings.\r\n\tif ( !mp_params->ContainsComponentNamed( \"original_goal_description\" ) )\r\n\t{\r\n\t\tconst char* p_ogd;\r\n\t\tScript::CArray* p_ogd_array;\r\n\t\tif ( mp_params->GetString( \"goal_description\", &p_ogd, Script::NO_ASSERT ) )\r\n\t\t\tmp_params->AddString( \"original_goal_description\", p_ogd );\r\n\t\t\r\n\t\telse if ( mp_params->GetArray( \"goal_description\", &p_ogd_array, Script::ASSERT ) )\r\n\t\t\tmp_params->AddArray( \"original_goal_description\", p_ogd_array );\r\n\t}\r\n\tif ( !mp_params->ContainsComponentNamed( \"original_view_goals_text\" ) )\r\n\t{\r\n\t\tconst char* p_ovgt;\r\n\t\tif ( mp_params->GetString( \"view_goals_text\", &p_ovgt, Script::NO_ASSERT ) )\r\n\t\t\tmp_params->AddString( \"original_view_goals_text\", p_ovgt );\r\n\t}\r\n\tif ( !mp_params->ContainsComponentNamed( \"original_goal_text\" ) )\r\n\t{\r\n\t\tconst char* p_ogt;\r\n\t\tif ( mp_params->GetString( \"goal_text\", &p_ogt, Script::NO_ASSERT ) )\r\n\t\t\tmp_params->AddString( \"original_goal_text\", p_ogt );\r\n\t}\r\n\tif ( !mp_params->ContainsComponentNamed( \"original_key_combo_text\" ) )\r\n\t{\r\n\t\tconst char* p_okct;\r\n\t\tif ( mp_params->GetString( \"key_combo_text\", &p_okct, Script::NO_ASSERT ) )\r\n\t\t\tmp_params->AddString( \"original_key_combo_text\", p_okct );\r\n\t}\r\n\r\n\t// special case for cat goal\r\n\tint premade_cat_index = -1;\r\n\tif ( mp_params->ContainsFlag( CRCD(0x8e6014f6,\"create_a_trick\") ) )\r\n\t{\r\n\t\tmp_params->GetInteger( CRCD(0xb502200,\"premade_cat_index\"), &premade_cat_index, Script::ASSERT );\r\n\t}\r\n\r\n\t// get the new string arrays\r\n\tScript::CArray* p_key = new Script::CArray();\r\n\tScript::CArray* p_trick = new Script::CArray();\r\n\tint size = p_key_combo->GetSize();\r\n\tp_key->SetSizeAndType( size, ESYMBOLTYPE_STRING );\r\n\tp_trick->SetSizeAndType( size, ESYMBOLTYPE_STRING );\r\n\tif ( !fill_trick_and_key_combo_arrays( p_key_combo, p_key, p_trick, premade_cat_index ) )\r\n\t{\r\n\t\tScript::CleanUpArray( p_key );\r\n\t\tScript::CleanUpArray( p_trick );\r\n\t\tdelete p_key;\r\n\t\tdelete p_trick;\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tconst char* p_string;\r\n\tScript::CArray* p_string_array = NULL;\r\n\r\n\tchar new_string[Game::NEW_STRING_LENGTH];\r\n\t\r\n\t// replace the goal description\r\n\tif ( mp_params->GetString( \"original_goal_description\", &p_string, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tfind_and_replace_trick_string( p_string, new_string, p_key, p_trick, Game::NEW_STRING_LENGTH );\r\n\t\tmp_params->AddString( \"goal_description\", p_string );\r\n\t}\r\n\telse if ( mp_params->GetArray( \"original_goal_description\", &p_string_array, Script::ASSERT ) )\r\n\t{\r\n\t\tint size = p_string_array->GetSize();\r\n\t\tScript::CArray* p_new_string_array = new Script::CArray();\r\n\t\tp_new_string_array->SetSizeAndType( size, ESYMBOLTYPE_STRING );\r\n\t\tfor ( int i = 0; i < size; i++ )\r\n\t\t{\r\n\t\t\tp_string = p_string_array->GetString( i );\r\n\t\t\tfind_and_replace_trick_string( p_string, new_string, p_key, p_trick, Game::NEW_STRING_LENGTH );\r\n\t\t\tp_new_string_array->SetString( i, Script::CreateString( new_string ) );\r\n\t\t}\r\n\t\tmp_params->AddArray( \"goal_description\", p_new_string_array );\r\n\t\tScript::CleanUpArray( p_new_string_array );\r\n\t\tdelete p_new_string_array;\r\n\t}\r\n\r\n\t// replace the view goals text\r\n\tif ( mp_params->GetString( \"original_view_goals_text\", &p_string, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tfind_and_replace_trick_string( p_string, new_string, p_key, p_trick, Game::NEW_STRING_LENGTH );\r\n\t\tmp_params->AddString( \"view_goals_text\", new_string );\r\n\t}\r\n\t\r\n\t// replace the goal text\r\n\tif ( mp_params->GetString( \"original_goal_text\", &p_string, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tfind_and_replace_trick_string( p_string, new_string, p_key, p_trick, Game::NEW_STRING_LENGTH );\r\n\t\tmp_params->AddString( \"goal_text\", new_string );\r\n\t}\r\n\r\n\t// replace the key combo text\r\n\tif ( mp_params->GetString( \"original_key_combo_text\", &p_string, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tfind_and_replace_trick_string( p_string, new_string, p_key, p_trick, Game::NEW_STRING_LENGTH );\r\n\t\tmp_params->AddString( \"key_combo_text\", new_string );\r\n\t}\r\n\r\n\t// cleanup!\r\n\tScript::CleanUpArray( p_key );\r\n\tScript::CleanUpArray( p_trick );\r\n\tdelete p_key;\r\n\tdelete p_trick;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CGoal::GetNumberCollected()\r\n{\r\n\tint number_collected = 0;\r\n\t\r\n\t// check for special counter goal num\r\n\tif ( mp_params->GetInteger( CRCD(0x129daa10,\"number_collected\"), &number_collected, Script::NO_ASSERT ) )\r\n\t\treturn number_collected;\r\n\r\n\t// return the number of flags set\r\n\treturn m_flagsSet;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CGoal::GetNumberOfFlags()\r\n{\r\n\tint num_flags_to_win = m_numflags;\r\n\tmp_params->GetInteger( CRCD(0x1171a555,\"num_flags_to_win\"), &num_flags_to_win, Script::NO_ASSERT );\r\n\tif ( num_flags_to_win != 0 )\r\n\t\treturn num_flags_to_win;\r\n\treturn -1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::ColorTrickObjects( int seqIndex, bool clear )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CTrickObjectManager* p_trickObjMan = skate_mod->GetTrickObjectManager();\r\n\t\r\n\tScript::CArray* p_clusters = NULL;\r\n\tif ( !mp_params->GetArray( \"kill_clusters\", &p_clusters, Script::NO_ASSERT ) )\r\n\t\treturn;\r\n\r\n\tint numClusters = p_clusters->GetSize();\r\n\tfor ( int i = 0; i < numClusters; i++ )\r\n\t{\r\n\t\tScript::CStruct* p_temp = p_clusters->GetStructure( i );\r\n\t\tuint32 cluster_id;\r\n\t\tp_temp->GetChecksum( \"id\", &cluster_id, Script::ASSERT );\r\n\t\t\r\n\t\tObj::CTrickCluster* p_trickCluster = p_trickObjMan->GetTrickCluster( cluster_id );\r\n\t\tif ( p_trickCluster )\r\n\t\t{\r\n\t\t\tif ( clear )\r\n\t\t\t{\r\n\t\t\t\t// printf(\"clearing cluster %s\\n\", Script::FindChecksumName( cluster_id ) );\r\n\t\t\t\tObj::CTrickCluster* p_trickCluster = p_trickObjMan->GetTrickCluster( cluster_id );\r\n\t\t\t\tif ( p_trickCluster )\r\n\t\t\t\t\tp_trickCluster->ClearCluster( seqIndex );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t\tp_trickObjMan->GetTrickCluster( cluster_id )->ModulateTrickObjectColor( seqIndex );\r\n\t\t}\r\n\t\telse\r\n\t\t\tDbg_Message( \"WARNING: cluster %s not found\\n\", Script::FindChecksumName( cluster_id ) );\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CGoal::GetNumberOfTimesGoalStarted()\r\n{\r\n\treturn m_numTimesStarted;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::GetRewardsStructure( Script::CStruct *p_structure, bool give_cash )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\r\n\tif ( !mp_params->ContainsFlag( CRCD(0x981d3ad0,\"edited_goal\") ) )\r\n\t\tpGoalManager->AddGoalPoint();\r\n\r\n\tp_structure->AddChecksum( NONAME, CRCD( 0xc7fef529, \"awarded_goal_point\" ) );\r\n\r\n\t// No rewards in net games, only fanfare\r\n\tif( gamenet_man->InNetGame() == false )\r\n\t{\r\n\t\t// special case for special trick goal\r\n\t\tif ( mp_params->ContainsFlag( \"reward_trickslot\" ) && !mp_params->ContainsFlag( CRCD( 0x8e6014f6, \"create_a_trick\" ) ) )\r\n\t\t{\r\n\t\t\t// printf(\"found trickslot flag\\n\");\r\n\t\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\t\tObj::CSkaterProfile* p_SkaterProfile = skate_mod->GetCurrentProfile();\r\n\t\t\tint num_slots = p_SkaterProfile->GetNumSpecialTrickSlots();\r\n\t\t\tif ( num_slots <= Script::GetInteger( CRCD(0x20297d6f,\"max_number_of_special_trickslots\") ) )\r\n\t\t\t{\r\n\t\t\t\t// printf(\"has less than the max number of slots\\n\");\r\n\t\t\t\tint should_remove = 0;\r\n\t\t\t\tmp_params->GetInteger( \"should_remove_trick\", &should_remove, Script::NO_ASSERT );\r\n\t\t\t\tif ( should_remove == 1 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// printf(\"was going to remove the special trick, but don't!\\n\");\r\n\t\t\t\t\tmp_params->AddInteger( \"should_remove_trick\", 0 );\r\n\t\t\t\t\t// p_reward_params->AddChecksum( NONAME, CRCD( 0x65ca5ffc, \"already_added_trickslot\" ) );\r\n\t\t\t\t\tmp_params->AddChecksum( NONAME, CRCD( 0x65ca5ffc, \"already_added_trickslot\" ) );\r\n\t\t\t\t\tmp_params->AddInteger( CRCD(0xb45fd352,\"just_added_trickslot\"), 1 );\r\n\t\t\t\t}\t\t\t\t\t\r\n\t\t\t}\r\n\t\t}\t\t\r\n\t\t\r\n\t\t// ************************\r\n\t\t// new global reward stuff\r\n\t\t// ************************\r\n\t\t// grab the list of rewards\r\n\t\tScript::CStruct* p_all_rewards = Script::GetStructure( \"goal_rewards\", Script::ASSERT );\r\n\t\tScript::CStruct* p_rewards = NULL;\r\n\t\tp_all_rewards->GetStructure( GetGoalId(), &p_rewards, Script::NO_ASSERT );\r\n\t\tif ( p_rewards )\r\n\t\t{\r\n\t\t\t// map the reward_stat flag to an int\r\n\t\t\tif ( p_rewards->ContainsFlag( \"reward_stat\" ) )\r\n\t\t\t{\r\n\t\t\t\tp_rewards->RemoveComponent( \"reward_stat\" );\r\n\t\t\t\tp_rewards->AddInteger( \"reward_stat\", 1 );\r\n\t\t\t}\r\n\r\n\t\t\tp_structure->AppendStructure( p_rewards );\r\n\t\t\t\r\n\t\t\tif ( give_cash )\r\n\t\t\t{\r\n\t\t\t\tint reward_cash;\r\n\t\t\t\tif ( p_rewards->GetInteger( \"reward_cash\", &reward_cash, Script::NO_ASSERT ) )\r\n\t\t\t\t\tp_structure->AddInteger( \"cash\", reward_cash );\r\n\t\t\t}\r\n\t\t}\r\n\t\t// **************************\r\n\t\t// old reward stuff\r\n\t\t// **************************\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( give_cash )\r\n\t\t\t{\r\n\t\t\t\tint reward_cash;\r\n\t\t\t\t// give 'em cash\r\n\t\t\t\tif ( mp_params->GetInteger( \"reward_cash\", &reward_cash, Script::NO_ASSERT ) )\r\n\t\t\t\t\tp_structure->AddInteger( \"cash\", reward_cash );\r\n\t\t\t}\r\n\r\n\t\t\t// stat points\r\n\t\t\tint stat_points;\r\n\t\t\tif ( mp_params->ContainsFlag( \"reward_stat\" ) )\r\n\t\t\t\tp_structure->AddInteger( \"reward_stat\", 1 );\r\n\t\t\telse if ( mp_params->GetInteger( \"reward_stat\", &stat_points, Script::NO_ASSERT ) )\r\n\t\t\t\tp_structure->AddInteger( \"reward_stat\", stat_points );\r\n\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::UnlockRewardGoals()\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\r\n\t// unlock a new goal\r\n\tScript::CArray* p_new_goal_array = NULL;\r\n\tuint32 new_goal_checksum = 0;\r\n\r\n\tif ( mp_params->GetChecksum( \"reward_goal\", &new_goal_checksum, Script::NO_ASSERT ) )\r\n\t\tpGoalManager->UnlockGoal( new_goal_checksum );\r\n\r\n\t// check for an array of goals to unlock\r\n\telse if ( mp_params->GetArray( \"reward_goal\", &p_new_goal_array, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tint num_goals_to_unlock = p_new_goal_array->GetSize();\r\n\t\tfor ( int i = 0; i < num_goals_to_unlock; i++ )\r\n\t\t{\r\n\t\t\tnew_goal_checksum = p_new_goal_array->GetChecksum( i );\r\n\t\t\tif ( new_goal_checksum )\r\n\t\t\t\tpGoalManager->UnlockGoal( new_goal_checksum );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::SetEndRunType( EndRunType newEndRunType )\r\n{\r\n\tm_endRunType = newEndRunType;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoal::SetShouldDeactivateOnExpire( bool should_deactivate )\r\n{\r\n\tm_deactivateOnExpire = should_deactivate;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::IsHorseGoal()\r\n{\r\n\treturn mp_params->ContainsFlag( CRCD(0x9d65d0e7,\"horse\") );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::IsFindGapsGoal()\r\n{\r\n    return ( mp_params->ContainsFlag( CRCD( 0xc5ec08e6, \"findGaps\" ) ) );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoal::ShouldRequireCombo()\r\n{\r\n\treturn mp_params->ContainsFlag( CRCD(0xf8e31760,\"require_combo\") );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoal::AppendDifficultyLevelParams()\r\n{\r\n\tScript::CArray* pLevelParams;\r\n\tif ( mp_params->GetArray( CRCD( 0x85104ab3, \"difficulty_level_params\" ), &pLevelParams, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\tDbg_Assert( pGoalManager );\r\n\t\tGame::GOAL_MANAGER_DIFFICULTY_LEVEL difficulty_level = pGoalManager->GetDifficultyLevel();\r\n\t\tDbg_MsgAssert( difficulty_level < (int)pLevelParams->GetSize(), ( \"Difficulty params array has wrong size in goal %s\", Script::FindChecksumName( GetGoalId() ) ) );\r\n\t\tmp_params->AppendStructure( pLevelParams->GetStructure( difficulty_level ) );\r\n\t\tCreateGoalFlags( mp_params );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoal::RunCallbackScript( uint32 script_name )\r\n{\r\n#if 1\r\n\tuint32 checksum;\r\n\tif ( mp_params->GetChecksum( script_name, &checksum, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tScript::RunScript( checksum, mp_params );\r\n\t\treturn true;\r\n    }\r\n#else\r\n\tScript::CStruct* pStruct;\r\n\tif ( mp_params->GetStructure( script_name, &pStruct, Script::NO_ASSERT ) )\r\n\t{\r\n\t\t// target script name is required\r\n\t\tuint32 checksum;\r\n\t\tpStruct->GetChecksum( CRCD(0xb990d003,\"target\"), &checksum, Script::ASSERT );\r\n\r\n\t\t// but not the params...\r\n\t\tScript::CStruct* pSubStruct = NULL;\r\n\t\tpStruct->GetStructure( CRCD(0x7031f10c,\"params\"), &pSubStruct, Script::NO_ASSERT );\r\n\r\n\t\tif ( pParams )\r\n\t\t\tpSubStruct->AppendStructure( pParams );\r\n\t\t\r\n\t\tScript::RunScript( checksum, pSubStruct );\r\n\t\treturn true;\r\n\t}\r\n#endif\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n}\t// namespace Game\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/Goal.h",
    "content": "#ifndef\t__MODULES_SKATE_GOAL_H\r\n#define\t__MODULES_SKATE_GOAL_H\r\n\r\n                           \r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __SYS_TIMER_H\r\n    #include <sys/timer.h> // For Tmr::Time\r\n#endif\r\n\t\t\t\t\t\t\t  \r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/modules/skate/goalped.h>\r\n\r\n#include <core/list/node.h>\r\n#include <core/lookuptable.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n\r\nnamespace Game\r\n{\r\n\tenum EndRunType\r\n\t{\r\n\t\tvGOALENDOFRUN,\r\n\t\tvENDOFRUN,\r\n\t\tvNONE,\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n\t\tGOAL_INHERITED_FLAGS_ONE_TIMER\t\t= ( 1 << 1  ),\r\n\t\tGOAL_INHERITED_FLAGS_RETRY_STAGE\t= ( 1 << 2  ),\r\n\t};\r\n\t\r\n// *************************************************************\r\n//\t\t\tClass def\r\n// *************************************************************\r\n\r\nclass CGoalLink\r\n{\r\npublic:\r\n\tCGoalLink();\r\n\t~CGoalLink();\r\n\t\r\n\tuint32\t   \tm_relative;\r\n\tCGoalLink*\tmp_next;\r\n\tbool\t\tm_beaten;\r\n};\r\n\r\nclass CGoal : public  Lst::Node<CGoal>\r\n{\r\npublic:\r\n\tCGoal();\r\n\tCGoal(Script::CStruct* pParams);\r\n\t~CGoal();\r\n\r\npublic:\r\n\tvirtual bool\t\tIsExpired();\r\n\tbool\t\t\t\tIsExpired( bool force_end );\r\n\tvirtual bool\t\tShouldExpire();\r\n\t\r\n\tvirtual bool\t\tIsActive();\r\n\tvirtual bool\t\tCountAsActive(); // eg, minigames don't count\r\n    virtual void\t\tExpire();\r\n\r\n\tvirtual void\t\tLoadSaveData( Script::CStruct* pFlags );\r\n\tvirtual void\t\tGetSaveData( Script::CStruct* pFlags );\r\n\r\n\tvoid\t\t\t\tAddChild( uint32 id );\r\n\tvoid\t\t\t\tAddParent( uint32 id );\r\n\tvoid\t\t\t\tResetGoalLinks();\r\n\tvoid\t\t\t\tDeleteLinks( CGoalLink* p_list );\r\n\r\n\tvoid                MarkInvalid();\r\n    bool                IsInvalid(); \r\n\tvoid\t\t\t\tSetTimer();\r\n\tvoid\t\t\t\tAddTime( int time );\r\n\tvoid\t\t\t\tSetTimer( int time );\r\n\tint\t\t\t\t\tGetTimeLeft( void );\r\n\tvirtual bool\t\tShouldUseTimer();\r\n\tvirtual bool\t\tActivate();\r\n\tvirtual void\t\tSetActive();\r\n\tvirtual bool\t\tDeactivate( bool force = false, bool affect_tree = true );\r\n\tvirtual void\t\tSetInactive();\r\n\tvirtual bool\t\tWin();\r\n\tvirtual bool\t\tLose();\r\n\tbool\t\t\t\tIsProGoal();\r\n\tbool\t\t\t\tIsNetGoal();\r\n\r\n\tbool\t\t\t\tRunCallbackScript( uint32 script_name );\r\n\tScript::CStruct*\tGetParams();\r\n\tbool\t\t\t\tEditParams(Script::CStruct* pParams);\r\n\tvirtual bool\t\tUpdate();\r\n\r\n    bool                HasSeenGoal();\r\n    void                PauseGoal();\r\n    void                UnPauseGoal();\r\n\tvirtual bool\t\tIsPaused();\r\n    Tmr::Time           GetTime();\r\n    // void                CreateGoalFlag( uint32 flag );\r\n    bool                SetGoalFlag( uint32 flag, int value );\r\n\tbool\t\t\t\tGetCreatedGoalGap(int gapIndex);\r\n\t\r\n    void                ResetGoalFlags();\r\n\tvoid\t\t\t\tCreateGoalFlags( Script::CStruct* pParams );\r\n    bool                GoalFlagEquals( uint32 flag, int value );\r\n    bool                AllFlagsSet();\r\n\tbool\t\t\t\tGoalFlagSet( uint32 flag );\r\n    void                Init();\r\n\tvoid                Uninit( bool propogate = false, int recurse_level = 0 );\r\n    bool                IsLocked();\r\n    void                UnlockGoal();\r\n    uint32              GetGoalId();\r\n\tuint32              GetRootGoalId();\r\n\tbool\t\t\t\tIsEditedGoal();\r\n\tvoid\t\t\t\tGetViewGoalsText( const char** p_view_goals_text );\r\n    virtual bool        HasWonGoal();\r\n\tvirtual bool        HasWonGoal( int id );\r\n\tvirtual bool        HasTeamWonGoal( int team_id );\r\n\tvirtual bool\t\tHasWonStage();\r\n\tbool\t\t\t\tIsSelected();\r\n\tvirtual bool\t\tIsInitialized() { return m_isInitialized; }\r\n\r\n    bool                NextTourSpot();\r\n    void                InitTrickObjects();\r\n\r\n\tvoid\t\t\t\tGotTrickObject( uint32 clusterId );\r\n\tbool\t\t\t\tIsGraffitiGoal();\r\n\tbool\t\t\t\tShouldLogTrickObject();\r\n    void                GotGraffitiCluster( uint32 clusterId, int score );\r\n    bool                IsSpecialGoal();\r\n    bool                IsTetrisGoal();\r\n    bool                CheckSpecialGoal();\r\n    \r\n    void                GotCounterObject();\r\n    bool                CounterGoalDone();\r\n    bool                HasProset( const char* proset_prefix );\r\n\tbool\t\t\t\tCheckMinigameRecord( int value );\r\n\tint\t\t\t\t\tGetMinigameRecord();\r\n\tbool\t\t\t\tIsMinigame();\r\n\tbool\t\t\t\tIsBettingGame();\r\n\tbool\t\t\t\tIsBettingGuy();\r\n\tvirtual bool\t\tCanRetry();\r\n\tvoid\t\t\t\tSetStartTime();\r\n\tvoid\t\t\t\tUpdateComboTimer();\r\n\r\n    void                SetHasSeen();\r\n    virtual void        MarkBeaten();\r\n\tvirtual void\t\tMarkBeatenBy( int id );\r\n\tvirtual void\t\tMarkBeatenByTeam( int team_id );\r\n\tvoid\t\t\t\tSelect();\r\n\tvoid\t\t\t\tDeselect();\r\n    void                SetUnlocked();\r\n    void                SetLevelNum( int levelNum );\r\n    int                 GetLevelNum();\r\n\tvoid\t\t\t\tSetStartHeight();\r\n\tbool\t\t\t\tCheckHeightRecord();\r\n\tbool\t\t\t\tCheckDistanceRecord();\r\n\r\n\tvoid \t\t\t\tSetQuickStartFlag();\r\n\tvoid\t\t\t\tUnsetQuickStartFlag();\r\n\r\n\tbool\t\t\t\tIsCompetition();\r\n\r\n\tbool\t\t\t\tAllSkatersAtEndOfRun();\r\n\tbool\t\t\t\tEndRunCalled();\r\n\tvoid\t\t\t\tClearEndRun( Script::CScript* pScript );\r\n\tbool\t\t\t\tFinishedEndOfRun();\r\n\tbool\t\t\t\tStartedEndOfRun();\r\n\tvoid\t\t\t\tSetEndRunType( EndRunType newEndRunType );\r\n\r\n\tvirtual bool\t\tUnBeatGoal();\r\n\r\n\tvoid\t\t\t\tNoValidKeyCombos();\r\n\tint \t\t\t\tGetRandomIndexFromKeyCombos( Script::CArray* p_KeyCombos );\r\n\r\n\tbool\t\t\t\tAddTempSpecialTrick();\r\n\tvoid\t\t\t\tRemoveTempSpecialTrick();\r\n\r\n\tbool\t\t\t\tReplaceTrickText();\r\n\r\n\tint\t\t\t\t\tGetNumberCollected();\r\n\tint\t\t\t\t\tGetNumberOfFlags();\r\n\r\n\tvoid\t\t\t\tColorTrickObjects( int seqIndex, bool clear = false );\r\n\r\n\tint\t\t\t\t\tGetNumberOfTimesGoalStarted();\r\n\r\n\tvoid\t\t\t\tGetRewardsStructure( Script::CStruct *p_structure, bool give_cash = true );\r\n\tvoid\t\t\t\tUnlockRewardGoals();\r\n\r\n\tvoid\t\t\t\tSetShouldDeactivateOnExpire( bool should_deactivate );\r\n\r\n\tbool\t\t\t\tIsHorseGoal();\r\n\tbool\t\t\t\tIsFindGapsGoal();\r\n\r\n\t// family stuff\t\r\n\tGame::CGoalLink*\tGetChildren() { return mp_children; }\r\n\tGame::CGoalLink*\tGetParents() { return mp_parents; }\r\n\r\n\tvoid\t\t\t\tSetInheritableFlags( int recurse_level = 0 );\r\n\r\n\tGame::CGoalPed*\t\tmp_goalPed;\r\n\r\n\t// the inhereted flags of any root node\r\n\t// in a family branch will be set in the goals of all offspring\r\n\tuint32\t\t\t\tm_inherited_flags;\r\n\r\n\t// chatper/stage stuff\r\n\tvoid\t\t\t\tSetChapter( int chapter ) { m_chapter = chapter; }\r\n\tvoid\t\t\t\tSetStage( int stage ) { m_stage = stage; }\r\n\tint\t\t\t\t\tGetChapter() { return m_chapter; }\r\n\tint\t\t\t\t\tGetStage() { return m_stage; }\r\n\r\n\tbool\t\t\t\tShouldRequireCombo();\r\n\r\n\tvoid\t\t\t\tAppendDifficultyLevelParams();\r\nprotected:\t\r\n\tScript::CStruct*\tmp_params;\r\n    Script::CStruct*\tmp_goalFlags;\r\n\t\r\n\tEndRunType\t\t\tm_endRunType;\r\n\r\n\tGame::CGoalLink*\tmp_children;\r\n\tGame::CGoalLink*\tmp_parents;\r\n\t\r\n\t// members stored by goal manager on level unload\r\n    int                 m_levelNum;\r\n\tFlags< int >\t\tm_beatenFlags;\r\n\tFlags< int >\t\tm_teamBeatenFlags;\r\n\tint\t\t\t\t\tm_numTimesLost;\r\n\tint\t\t\t\t\tm_numTimesWon;\r\n\tint\t\t\t\t\tm_numTimesStarted;\r\n\tTmr::Time\t\t\tm_elapsedTimeRecord;\r\n\tint\t\t\t\t\tm_winScoreRecord;\r\n    Tmr::Time           m_timeLeft;\r\n\tint\t\t\t\t\tm_ownerId;\r\n    int                 m_numflags;\r\n    int                 m_flagsSet;\r\n\tTmr::Time\t\t\tm_elapsedTime;\r\n\tint\t\t\t\t\tm_chapter;\r\n\tint\t\t\t\t\tm_stage;\r\n    \r\n\tbool\t\t\t\tm_isInitialized;\r\n\tbool                m_hasSeen;\r\n    bool                m_isbeat;\r\n\tbool\t\t\t\tm_netIsBeat;\r\n\tbool\t\t\t\tm_isselected;\r\n    bool                m_isLocked;\r\n\tbool\t\t\t\tm_deactivateOnExpire;\r\n\tbool\t\t\t\tm_endRunCalled;\r\n\tbool\t\t\t\tm_active;\r\n    bool                m_invalid;\r\n    bool                m_paused;\r\n\tbool\t\t\t\tm_isOwned;\r\n    bool                m_unlimitedTime;\r\n};\r\n\r\n}\t// namespace Game\r\n\r\n#endif // __MODULES_SKATE_GOAL_H\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/GoalManager.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Modules/Skate\r\n//* FILENAME:       GoalManager.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  1/24/2001\r\n//****************************************************************************\r\n\r\n// start autoduck documentation\r\n// @DOC goalmanager\r\n// @module goalmanager | None\r\n// @subindex Scripting Database\r\n// @index script | goalmanager\r\n\t\t\t\t\t\t\t   \r\n#include <sk/modules/skate/goalmanager.h>\r\n\r\n#include <sk/modules/skate/Minigame.h>\r\n#include <sk/modules/skate/CompetitionGoal.h>\r\n#include <sk/modules/skate/NetGoal.h>\r\n#include <sk/modules/skate/RaceGoal.h>\r\n#include <sk/modules/skate/BettingGuy.h>\r\n#include <sk/modules/skate/SkatetrisGoal.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/modules/skate/HorseGoal.h>\r\n#include <sk/modules/skate/FindGapsGoal.h>\r\n#include <sk/modules/skate/FilmGoal.h>\r\n#include <sk/modules/skate/CatGoal.h>\r\n\r\n#include <core/string/stringutils.h>\r\n\r\n#include <gfx/2D/ScreenElemMan.h>       // for tetris tricks\r\n#include <gfx/2D/ScreenElement2.h>\r\n#include <gfx/2D/TextElement.h>\r\n#include <gfx/2D/SpriteElement.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/string.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gel/music/music.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/components/trickcomponent.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n\t\t\t\t\t\t\t\t\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/trickobject.h>\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/objects/playerprofilemanager.h>\r\n\r\n\r\n#include <sk/modules/skate/score.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/competition.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/scripting/skfuncs.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n\textern bool fill_trick_and_key_combo_arrays( Script::CArray* p_key_combos, Script::CArray* p_key_combo_strings, Script::CArray* p_trick_names, int premade_cat_index );\r\n\textern void find_and_replace_trick_string( const char* p_old, char* p_out, Script::CArray* p_key, Script::CArray* p_trick, uint out_buffer_size );\r\n\t\r\n// TODO:\r\n// Uber time limit should be its own goal?\r\n// Each of the skate letters can either be its own goal\r\n// or maybe we can grab the goal state in script somehow\r\n\r\n// maybe there's some kind of goal factory\r\n\r\n// TODO:  Maybe the script should be spawned so that it can wait a while...\r\n// or maybe it could run a script that spawns a script...\r\n// or maybe a combination of the two?\r\n\r\n// TODO:  Edit goal.  changes the state of the goal, maybe to track flags and such?\r\n// or maybe a thing can be made of 5 subgoals?\r\n\r\n// TODO:  Need a way of binding the goal to a specific player \r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCGoalManager::CGoalManager()\r\n{\r\n    m_lastGoal = 0;\r\n    m_graffitiMode = 0;\r\n    m_goalPoints = 0;\r\n\tm_totalGoalPointsEarned = 0;\r\n    m_cash = 0;\r\n\tm_numGoalsBeaten = 0;\r\n\tm_isPro = false;\r\n\t// m_proChallengesUnlocked = false;\r\n\tm_canStartGoal = true;\r\n\r\n\tm_currentChapter = 0;\r\n\tm_currentStage = 0;\r\n\tm_sponsor = 0;\r\n\tmp_team = new Script::CStruct();\r\n\r\n    mp_goalFlags = new Script::CStruct();\r\n\t// mp_proSpecificChallenges = new Script::CStruct();\r\n\t// mp_proSpecificChallenges->AppendStructure( Script::GetStructure( \"goal_pro_specific_challenges_beaten\", Script::ASSERT ) );\r\n\r\n\tmp_difficulty_levels = new Script::CStruct();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCGoalManager::~CGoalManager()\r\n{\r\n\t// delete all the goals in the list\r\n\tRemoveAllGoals();\r\n    delete mp_goalFlags;\r\n\t// delete mp_proSpecificChallenges;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::AddGoal( uint32 goalId, Script::CStruct* pParams )\r\n{\r\n\t// don't add non-minigames in free skate\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tbool free_skate = skate_mod->GetGameMode()->IsTrue( CRCD(0x337e7779,\"is_freeskate\") );\r\n\tif ( !CFuncs::ScriptInMultiplayerGame( NULL, NULL ) && free_skate && !pParams->ContainsFlag( CRCD(0x6bae094c,\"minigame\") ) )\r\n\t\treturn false;\r\n\r\n\tif ( skate_mod->GetGameMode()->IsTrue( CRCD( 0x353961d7, \"is_creategoals\" ) ) && !pParams->ContainsFlag( CRCD( 0x981d3ad0, \"edited_goal\" ) ) )\r\n\t\treturn false;\r\n\r\n\t// printf(\"addGoal called with goalId %x\\n\", goalId);\r\n\t\r\n\tDbg_MsgAssert( !m_goalList.GetItem( goalId ), ( \"duplicate goal id 0x%x (%s), please check your script\", goalId, Script::FindChecksumName( goalId ) ) );\r\n\tpParams->AddChecksum( CRCD(0x9982e501,\"goal_id\"), goalId );\r\n\t\r\n\t// figure the type\r\n\tCGoal* pGoal = NULL;\r\n\tif ( pParams->ContainsFlag( CRCD(0xc18fef36,\"career_only\") ) )\r\n\t{   \r\n\t\tif( CFuncs::ScriptInMultiplayerGame( NULL, NULL ))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\tif ( pParams->ContainsFlag( CRCD(0x4af5d34e,\"competition\") ) )\r\n\t{\r\n\t\t// printf(\"adding comp goal\\n\");\r\n\t\tpGoal = new CCompetitionGoal( pParams );\r\n\t}\r\n\telse if ( pParams->ContainsFlag( CRCD(0xd15ea00,\"net\") ) )\r\n\t{\r\n\t\t// printf(\"adding net goal\\n\");\r\n\t\tpGoal = new CNetGoal( pParams );\r\n\t}\r\n\telse if ( pParams->ContainsFlag( CRCD(0x25904450,\"race\") ) )\r\n\t{\r\n\t\t// printf(\"adding race goal\\n\");\r\n\t\tpGoal = new CRaceGoal( pParams );\r\n\t}\r\n\telse if ( pParams->ContainsFlag( CRCD(0x6bae094c,\"minigame\") ) )\r\n\t{\r\n\t\t// printf(\"adding minigame\\n\");\r\n\t\tpGoal = new CMinigame( pParams );\r\n\t}\r\n\telse if ( pParams->ContainsFlag( CRCD(0x8cfee956,\"betting_guy\") ) )\r\n\t{\r\n\t\t// printf(\"adding betting guy\\n\");\r\n\t\tpGoal = new CBettingGuy( pParams );\r\n\t}\r\n\telse if ( pParams->ContainsFlag( CRCD(0x4147922b,\"tetris\") ) )\r\n\t{\r\n\t\t// printf(\"adding skatetris goal\\n\");\r\n\t\tpGoal = new CSkatetrisGoal( pParams );\r\n\t}\r\n\telse if ( pParams->ContainsFlag( CRCD(0x9d65d0e7,\"horse\") ) )\r\n\t{\r\n\t\t// printf(\"adding horse goal\\n\");\r\n\t\tpGoal = new CHorseGoal( pParams );\r\n\t}\r\n\telse if ( pParams->ContainsFlag( CRCD( 0xc5ec08e6, \"findGaps\" ) ) )\r\n\t{\r\n\t\tpGoal = new CFindGapsGoal( pParams );\r\n\t}\r\n\telse if ( pParams->ContainsFlag( CRCD( 0x7dbb41dd, \"Film\" ) ) )\r\n\t{\r\n\t\tpGoal = new CFilmGoal( pParams );\r\n\t}\r\n\telse if ( pParams->ContainsFlag( CRCD( 0x8e6014f6, \"create_a_trick\" ) ) )\r\n\t{\r\n\t\tpGoal = new CCatGoal( pParams );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpGoal = new CGoal( pParams );\r\n\t}\r\n\tDbg_Assert( pGoal );\r\n\r\n\tm_goalList.PutItem( goalId, pGoal );\r\n\r\n\tpGoal->AppendDifficultyLevelParams();\r\n\tScript::CStruct* pGoalParams = pGoal->GetParams();\r\n\r\n\t// add children\r\n\tuint32 childId;\r\n\tScript::CArray* p_children;\r\n\tif ( pGoalParams->GetArray( CRCD( 0x5e684e45, \"children\" ), &p_children, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tint size = p_children->GetSize();\r\n\t\tDbg_MsgAssert( size > 0, ( \"0 size children array for goal %s\", Script::FindChecksumName( goalId ) ) );\r\n\t\tDbg_MsgAssert( p_children->GetType() == ESYMBOLTYPE_NAME, ( \"children array has wrong type for goal %s\", Script::FindChecksumName( goalId ) ) );\r\n\t\tfor ( int i = 0; i < size; i++ )\r\n\t\t{\r\n\t\t\tFindCircularLinks( goalId, p_children->GetChecksum( i ) );\r\n\t\t\tpGoal->AddChild( p_children->GetChecksum( i ) );\r\n\t\t}\r\n\t}\r\n\telse if ( pGoalParams->GetChecksum( CRCD( 0xdd4cabd6, \"child\" ), &childId, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tFindCircularLinks( goalId, childId );\r\n\t\tpGoal->AddChild( childId );\r\n\t}\r\n\t\r\n\tif ( CFuncs::ScriptInMultiplayerGame( NULL, NULL ))\r\n\t{\r\n\t\t// SKATE SPECIFIC\r\n\t\tpGoal->GetParams()->AddString( CRCD(0x944b2900,\"pro\"), \"NetJudge\" );\r\n\t\tpGoal->GetParams()->AddString( CRCD(0x243b9c3b,\"full_name\"), Script::GetString( CRCD(0xa500bc5f,\"judge_full_name\") ) );\r\n\t\t// END SKATE SPECIFIC\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// SKATE SPECIFIC\r\n\t\tconst char* pFirstName;\r\n\t\tuint32 pro_name;\r\n\t\tif ( pGoal->GetParams()->GetString( CRCD(0x944b2900,\"pro\"), &pFirstName, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\t// printf(\"pro string: %s\\n\", pFirstName );\r\n\t\t\tScript::CStruct* pLastNames = Script::GetStructure( CRCD(0x621d1828,\"goal_pro_last_name_checksums\") );\r\n\t\t\tif ( pLastNames->GetChecksum( Script::GenerateCRC( pFirstName ), &pro_name, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\t// printf(\"got a last name: %s\\n\", Script::FindChecksumName( pro_name ) );\r\n\t\t\t\t// get the current skater's name\r\n\t\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\t\tObj::CPlayerProfileManager* pPlayerProfileManager = skate_mod->GetPlayerProfileManager();\r\n\t\t\t\tObj::CSkaterProfile* pSkaterProfile = pPlayerProfileManager->GetCurrentProfile();\r\n\t\t\t\tuint32 current_skater = pSkaterProfile->GetSkaterNameChecksum();\r\n\t\t\t\t// printf(\"current_skater: %s\\n\", Script::FindChecksumName( current_skater ) );\r\n\t\t\t\tif ( current_skater == pro_name )\r\n\t\t\t\t{\r\n\t\t\t\t\tconst char* p_generic_pro_first_name = Script::GetString( CRCD(0x2245b93c,\"generic_pro_first_name\"), Script::ASSERT );\r\n\t\t\t\t\tpGoal->GetParams()->AddString( CRCD(0x944b2900,\"pro\"), p_generic_pro_first_name );\r\n\t\t\t\t\tconst char* p_generic_pro_full_name = Script::GetString( CRCD(0xfe6ef7b8,\"generic_pro_full_name\"), Script::ASSERT );\r\n\t\t\t\t\tpGoal->GetParams()->AddString( CRCD(0x243b9c3b,\"full_name\"), p_generic_pro_full_name );\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t// END SKATE SPECIFIC\r\n\t}\r\n\r\n\treturn ( pGoal != NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGoal* CGoalManager::GetGoal( uint32 goalId, bool assert )\r\n{\r\n\tCGoal* pGoal = m_goalList.GetItem( goalId );\r\n\tif ( assert )\r\n\t\tDbg_MsgAssert( pGoal, ( \"Could not find goal %s\\n\", Script::FindChecksumName( goalId ) ) );\r\n\t\r\n\treturn pGoal;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGoal* CGoalManager::GetGoal( Script::CStruct* pParams, bool assert )\r\n{\r\n\tuint32 goalId = GetGoalIdFromParams( pParams, assert );\r\n\tif ( goalId )\r\n\t\treturn GetGoal( goalId, assert );\r\n\treturn NULL;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGoal*\tCGoalManager::GetGoalByIndex( int index )\r\n{\r\n\treturn m_goalList.GetItemByIndex( index, NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::RemoveGoal( uint32 goalId )\r\n{\r\n\t// TODO:  Maybe add an \"AssertOnFail\" flag\r\n\r\n\tCGoal* pGoal = m_goalList.GetItem( goalId );\r\n\tDbg_Assert( pGoal );\r\n\t\t\r\n\tpGoal->mp_goalPed->DestroyGoalPed();\r\n\tm_goalList.FlushItem( goalId );\r\n\r\n\tif (m_lastGoal == goalId)\r\n\t{\r\n\t\tm_lastGoal=0;\r\n\t}\r\n\t\t\r\n\t// The FlushItem does not delete the CGoal* itself, it only deletes its own entry for\r\n\t// it (which is a LookupItem<CGoal>*) so we need to delete the pGoal here.\r\n\tdelete pGoal;\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::ActivateGoal( uint32 goalId, bool dontAssert )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\r\n    bool success = false;\r\n\r\n\tif ( !pGoal )\r\n\t{\r\n\t\tif ( dontAssert )\r\n\t\t\treturn false;\t\t\t\r\n\t\telse\r\n\t\t\tDbg_MsgAssert( 0, ( \"ActivateGoal could not find the goal\" ) );\r\n\t}\r\n\t\r\n    if ( pGoal )\r\n    {\r\n\t\tsuccess = pGoal->Activate();\r\n\t\t// set the last goal\r\n        if ( success && pGoal->CanRetry() )\r\n\t\t{\r\n\t\t\t// only set this for the root node\r\n\t\t\t// BB - changed!  the retry goal option now\r\n\t\t\t// always gives you the last stage.\r\n\t\t\t\r\n\t\t\t// Game::CGoalLink* p_parents = pGoal->GetParents();\r\n\t\t\t// if ( p_parents->m_relative == 0 )\r\n\t\t\tm_lastGoal = goalId;\r\n\t\t}\r\n    }\r\n\t\r\n    // move it back and forth from the inactive to the active list\r\n\t// TODO:  Maybe add an \"AssertOnFail\" flag\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::DeactivateGoal( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tif ( pGoal )\r\n\t{\r\n\t\tpGoal->Deactivate();\r\n\t}\r\n\r\n\t// move it back and forth from the inactive to the active list\r\n\t// would be an optimization?\r\n\r\n \t// TODO:  Maybe add an \"AssertOnFail\" flag\r\n\r\n\treturn ( pGoal != NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::ClearLastGoal( void )\r\n{\r\n\tm_lastGoal = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::WinGoal( uint32 goalId )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tif ( pGoal )\r\n\t{\r\n        // don't let them retry this goal\r\n\t\t// only if it's a leaf node\r\n        if ( pGoal->GetChildren()->m_relative == 0 )\r\n\t\t\tm_lastGoal = 0;\r\n\r\n\t\t// we always want to call win, but if they\r\n\t\t// already beat it, we don't want to give them \r\n\t\t// double credit\r\n\t\tif ( !pGoal->HasWonGoal() )\r\n\t\t{\r\n\t\t\t// Report winning leaf node goals\r\n\t\t\tif( ( pGoal->GetChildren()->m_relative == 0 ) &&\r\n\t\t\t\t( gamenet_man->InNetGame()))\r\n\t\t\t{\r\n\t\t\t\tNet::Client* client;\r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t\tDbg_Printf( \"*** Reporting won goal\\n\" );\r\n\t\t\t\t// TODO: This should use the appropriate client for the skater completing this trick.\r\n\t\t\t\t// Assuming client Zero will probably cause problems in split-screen games\r\n\t\t\t\tclient = gamenet_man->GetClient( 0 );\r\n\t\t\t\tDbg_Assert( client );\r\n\r\n\t\t\t\tGameNet::MsgBeatGoal msg;\r\n\r\n\t\t\t\tmsg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\t\t\t\tmsg.m_GoalId = pGoal->GetRootGoalId();\r\n\t\t\t\t\r\n\t\t\t\tDbg_Printf( \"**** Beat GOAL 0x%x  ROOT: 0x%x\\n\", pGoal->GetGoalId(), pGoal->GetRootGoalId());\r\n\r\n\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgBeatGoal );\r\n\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_BEAT_GOAL;\r\n\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// increase num goals beaten if this is a leaf node.\r\n\t\t\t\tif ( pGoal->GetChildren()->m_relative == 0 )\r\n\t\t\t\t\tif ( !pGoal->GetParams()->ContainsFlag( CRCD(0x981d3ad0,\"edited_goal\") ) )\r\n\t\t\t\t\t\tm_numGoalsBeaten++;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t}\r\n\t\t\r\n\t\t// In net games, \"won\" goals need to be approved by the server\r\n\t\t// Update: Win goals locally now to close the window where time can expire waiting for server's approval\r\n\t\tpGoal->Win();\r\n\t}\r\n\r\n\t/*\r\n\tif( gamenet_man->InNetGame() == false )\r\n\t{\r\n\t\tif ( !m_isPro && ( m_numGoalsBeaten >= m_numGoalsToPro ) )\r\n\t\t{\r\n\t\t\tTurnPro();\r\n\t\t}\r\n\t}\r\n\t*/\r\n\r\n\treturn ( pGoal != NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::LoseGoal( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\t// expire takes priority over fail\r\n\tif ( pGoal )\r\n\t{\r\n\t\tpGoal->Lose();\r\n\t}\r\n\r\n\treturn ( pGoal != NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::EditGoal( uint32 goalId, Script::CStruct* pParams )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\r\n\tif ( pGoal )\r\n\t{\r\n\t\tpGoal->EditParams( pParams );\r\n\t}\r\n\t\t\t \r\n\t// should edit the state of the goal here...\r\n\t\r\n\t// TODO:  Maybe add an \"AssertOnFail\" flag\r\n\r\n\treturn ( pGoal != NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::SetGoalTimer( uint32 goalId, int time )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tif ( pGoal )\r\n\t{\r\n\t\tif (time == -1)\r\n\t\t{\r\n\t\t\tpGoal->SetTimer();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpGoal->SetTimer(time);\r\n\t\t}\r\n\t}\r\n\t\t\t \r\n\t// should edit the state of the goal here...\r\n\t\r\n\t// TODO:  Maybe add an \"AssertOnFail\" flag\r\n\r\n\treturn ( pGoal != NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::GoalIsActive( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId, false );\r\n\r\n\tif ( pGoal )\r\n\t{\r\n\t\treturn pGoal->IsActive();\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoalManager::GetActiveGoal( bool ignore_net_goals )\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tif( ignore_net_goals && pGoal->IsNetGoal())\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif ( pGoal->IsActive() )\r\n\t\t{\r\n            return i;\r\n        }\r\n    }\r\n    return -1;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoalManager::GetNumGoals()\r\n{\r\n\treturn m_goalList.getSize();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoalManager::GetNumActiveGoals( bool count_all )\r\n{\r\n\tint numActiveGoals = 0;\r\n\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tif( pGoal->IsNetGoal() && !count_all )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif ( count_all && pGoal->IsActive() )\r\n\t\t\tnumActiveGoals++;\r\n\t\telse if ( pGoal->CountAsActive() )\r\n\t\t\tnumActiveGoals++;\r\n\t}\r\n\treturn numActiveGoals;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoalManager::GetNumSelectedGoals()\r\n{\r\n\tint num_selected = 0;\r\n\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\t// this is now primarily used for determining if the timer should be on-screen\r\n\t\tif ( pGoal->IsSelected() )\r\n\t\t{\r\n\t\t\tnum_selected++;\r\n\t\t}\r\n\t}\r\n\treturn num_selected;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::RemoveAllGoals()\r\n{\r\n\t// can't retry!\r\n    m_lastGoal = 0;\r\n    \r\n\t// kill the ped\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\t\r\n\t\tpGoal->mp_goalPed->DestroyGoalPed();\r\n\t}\r\n\r\n\t// delete all the goals in the list\r\n\tLst::LookupTableDestroyer<CGoal> destroyer( &m_goalList );\t\r\n\tdestroyer.DeleteTableContents();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::DeactivateAllGoals( bool include_net_goals )\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tif ( pGoal->IsActive() )\r\n\t\t{\r\n\t\t\tpGoal->Deactivate( include_net_goals );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::UninitializeGoal( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\tpGoal->Uninit();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::UninitializeGoalTree( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\tCGoalLink* pGoalLink = pGoal->GetParents();\r\n\twhile ( pGoalLink && pGoalLink->m_relative != 0 )\r\n\t{\r\n\t\tpGoal = GetGoal( pGoalLink->m_relative );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tpGoalLink = pGoal->GetParents();\r\n\t}\r\n\t\r\n\t// the resulting goal should be the root node of the family tree\r\n\tpGoal->Uninit( true );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::UninitializeAllGoals()\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tpGoal->Uninit();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::DeactivateAllMinigames()\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tif ( pGoal->IsMinigame() && pGoal->IsActive() )\r\n\t\t\tpGoal->Deactivate();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::InitializeAllMinigames()\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tif( pGoal->IsMinigame())\r\n\t\t{\r\n\t\t\tpGoal->RunCallbackScript( vINIT );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::InitializeAllGoals()\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\t\t\r\n\t\tif( gamenet_man->InNetGame() && !pGoal->IsNetGoal())\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif ( !pGoal->IsLocked() && !pGoal->HasWonGoal() )\r\n\t\t{\r\n\t\t\t// check if this is a child of another goal\r\n\t\t\tCGoalLink* pGoalParents = pGoal->GetParents();\r\n\r\n\t\t\t// support an always_initialize_goal flag, which\r\n\t\t\t// allows designers to have goals that aren't tied to\r\n\t\t\t// a chapter/stage\r\n\t\t\tScript::CStruct* pGoalParams = pGoal->GetParams();\r\n\t\t\t\r\n\t\t\tint goal_chapter = pGoal->GetChapter();\r\n\t\t\tint goal_stage = pGoal->GetStage();\r\n\t\t\t\r\n\t\t\t// printf(\"%s: %i.%i\\n\", Script::FindChecksumName( pGoal->GetGoalId() ), goal_chapter, goal_stage );\r\n\t\t\tif ( pGoalParents->m_relative == 0 )\r\n\t\t\t{\r\n\t\t\t\t// if the goal isn't listed in chapter_info.q at all,\r\n\t\t\t\t// the chapter and stage will default to -1.\r\n\t\t\t\t// Always create these goals\r\n\t\t\t\tif ( ( goal_chapter == m_currentChapter && goal_stage == m_currentStage ) \r\n\t\t\t\t\t || pGoalParams->ContainsFlag( CRCD( 0x4e863e93, \"always_initialize_goal\" ) )\r\n\t\t\t\t\t || pGoalParams->ContainsFlag( CRCD( 0x981d3ad0, \"edited_goal\" ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tpGoal->Init();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::InitializeAllSelectedGoals()\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\t\t\r\n\t\tif ( pGoal->IsSelected())\r\n\t\t{       \r\n\t\t\tScript::RunScript( Script::GenerateCRC( \"goal_create_proset_geom\" ), pGoal->GetParams());\r\n\t\t\tpGoal->Init();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::DeselectAllGoals()\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\t\t\r\n\t\tpGoal->Deselect();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// TODO: make this smarter...it just deactivates the first\r\n// non-minigame goal it finds\r\nvoid CGoalManager::DeactivateCurrentGoal()\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tif ( pGoal->IsActive() && !pGoal->IsNetGoal() && !pGoal->IsMinigame() )\r\n\t\t{\r\n\t\t\tpGoal->Deactivate();\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::Update()\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tif ( pGoal->IsActive() )\r\n\t\t{\r\n            pGoal->Update();\r\n        }\r\n    }\r\n\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n        if ( pGoal->IsInvalid() )\r\n        {\r\n            //Dbg_Printf(\"************** removing goal %p\\n\", pGoal->GetGoalId());\r\n            m_goalList.FlushItem( pGoal->GetGoalId() );\r\n            delete pGoal;\r\n        }\r\n/*        else \r\n            {\r\n                pGoal->Update();\r\n            }\r\n*/\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::HasSeenGoal( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\r\n\tif ( pGoal )\r\n\t{\r\n\t\treturn pGoal->HasSeenGoal();\r\n\t}\r\n\r\n\treturn false;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::PauseAllGoals()\r\n{\r\n    for ( int i = 0; i < GetNumGoals(); i++ )\r\n    {\r\n        uint32 key;\r\n        CGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n        Dbg_Assert( pGoal );\r\n    \r\n        pGoal->PauseGoal();\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::UnPauseAllGoals()\r\n{\r\n    for ( int i = 0; i < GetNumGoals(); i++ )\r\n    {\r\n        uint32 key;\r\n        CGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n        Dbg_Assert( pGoal );\r\n    \r\n        pGoal->UnPauseGoal();\r\n    }\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nTmr::Time CGoalManager::GetGoalTime()\r\n{\r\n    // TODO: allow some sort of goal priority \r\n    // right now this just finds the fist active goal\r\n    // and returns that timer\r\n    for (int i = 0; i < GetNumGoals(); i++) {\r\n        uint32 key;\r\n        CGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n        Dbg_Assert( pGoal );\r\n        \r\n        if ( pGoal->IsActive() && pGoal->ShouldUseTimer() && !pGoal->IsExpired() )\r\n        {\r\n            Tmr::Time timeLeft = pGoal->GetTime();\r\n            if ( (int)timeLeft < 0 )\r\n                return 0;\r\n            return timeLeft;\r\n        }\r\n    }\r\n    // there are no active goals.\r\n    return 0;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::CanRetryGoal()\r\n{\r\n    if ( m_lastGoal != 0 )\r\n\t{\r\n\t\tCGoal* pGoal = GetGoal( m_lastGoal );\r\n\t\treturn pGoal->CanRetry();\r\n\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::QuickStartGoal( uint32 goalId, bool dontAssert )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tif ( !pGoal )\r\n\t{\r\n\t\tif ( dontAssert )\r\n\t\t\treturn false;\r\n\t\telse\r\n\t\t\tDbg_MsgAssert( 0, ( \"QuickStartGoal unable to find goal\" ) );\r\n\t}\r\n\tpGoal->SetQuickStartFlag();\r\n\tbool success = pGoal->Activate();\r\n\t\r\n\t// set the last goal\r\n\tif ( success && pGoal->CanRetry() )\r\n\t\tm_lastGoal = goalId;\r\n\r\n\tpGoal->UnsetQuickStartFlag();\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::RestartLastGoal() \r\n{\r\n\tif ( m_lastGoal != 0 )\r\n    {\r\n\t\tCGoal* pGoal = GetGoal( m_lastGoal );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\t// set the restart flag so the (de)activate scripts knows not to show\r\n\t\t// cam anims, etc.\r\n\t\tpGoal->SetQuickStartFlag();\r\n\r\n\t\t// if ( pGoal->IsActive() )\r\n\t\t\t// pGoal->Deactivate();\r\n\t\tDeactivateAllGoals();\r\n\r\n\t\t// SKATE SPECIFIC\r\n\t\t// kill any sk3_killscripts, as they will screw up the reset skater call\r\n\t\tScript::KillSpawnedScriptsThatReferTo( ( CRCD(0xdea3057b,\"SK3_KillSkater\") ) );\r\n\t\tScript::KillSpawnedScriptsThatReferTo( ( CRCD(0xb38ed6b,\"SK3_Killskater_Finish\") ) );\r\n\t\t// END SKATE SPECIFIC\r\n\r\n\t\t// kill any blur effect\r\n\t\tScript::RunScript(( CRCD(0xbda66e7d,\"kill_blur\") ) );\r\n\t\t\r\n\t\t// uint32 reset_checksum = 0;\r\n        // pGoal->GetParams()->GetChecksum( \"restart_node\", &reset_checksum, Script::ASSERT );        \r\n        // Mdl::Skate * p_skate = Mdl::Skate::Instance();\r\n        // p_skate->ResetSkaters( SkateScript::FindNamedNode( reset_checksum ) );\r\n\r\n\t\t// clear the trigger exceptions\r\n\t\tif ( !pGoal->HasWonGoal() )\r\n\t\t{\r\n\t\t\tScript::CStruct* p_params = new Script::CStruct();\r\n\t\t\tp_params->AddChecksum( \"goal_id\", pGoal->GetGoalId() );\r\n\t\t\tScript::RunScript( CRCD( 0x17c2e09f, \"GoalManager_ResetGoalTrigger\" ), p_params );\r\n\t\t\tdelete p_params;\r\n\t\t}\r\n\t\t\r\n\t\tpGoal->Activate();\r\n\t\tpGoal->UnsetQuickStartFlag();\r\n    }\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::RestartStage()\r\n{\r\n    int activeGoal = GetActiveGoal();\r\n\tif ( activeGoal == -1 )\r\n\t\treturn;\r\n\r\n\tuint32 key;\r\n\tCGoal* pGoal = m_goalList.GetItemByIndex( activeGoal, (int*)&key );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->SetQuickStartFlag();\r\n\r\n\tif ( pGoal->IsActive() )\r\n\t{\r\n\t\tpGoal->Deactivate( false, false );\r\n\r\n\t\t// SKATE SPECIFIC\r\n\t\t// kill any sk3_killscripts, as they will screw up the reset skater call\r\n\t\tScript::KillSpawnedScriptsThatReferTo(  CRCD(0xdea3057b,\"SK3_KillSkater\")  );\r\n\t\tScript::KillSpawnedScriptsThatReferTo( ( CRCD(0xb38ed6b,\"SK3_Killskater_Finish\") ) );\r\n\t\t// END SKATE SPECIFIC\r\n\r\n\t\t// kill any blur effect\r\n\t\tScript::RunScript( ( CRCD(0xbda66e7d,\"kill_blur\") ) );\r\n\t\t\r\n\t\t// uint32 reset_checksum = 0;\r\n        // pGoal->GetParams()->GetChecksum( \"restart_node\", &reset_checksum, Script::ASSERT );        \r\n        // Mdl::Skate * p_skate = Mdl::Skate::Instance();\r\n        // p_skate->ResetSkaters( SkateScript::FindNamedNode( reset_checksum ) );\r\n\r\n\t\t// clear the trigger exceptions\r\n\t\tif ( !pGoal->HasWonGoal() )\r\n\t\t{\r\n\t\t\tScript::CStruct* p_params = new Script::CStruct();\r\n\t\t\tp_params->AddChecksum( \"goal_id\", pGoal->GetGoalId() );\r\n\t\t\tScript::RunScript( CRCD( 0x17c2e09f, \"GoalManager_ResetGoalTrigger\" ), p_params );\r\n\t\t\tdelete p_params;\r\n\t\t}\r\n\t\t\r\n\t\tpGoal->Activate();\r\n\t\tpGoal->UnsetQuickStartFlag();\r\n    }\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*void CGoalManager::CreateGoalFlag( uint32 goalId, uint32 flag )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n    Dbg_Assert( pGoal );\r\n    \r\n    pGoal->CreateGoalFlag( flag );\r\n}*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::SetGoalFlag( uint32 goalId, uint32 flag, int value )\r\n{\r\n    CGoal* pGoal = GetGoal( goalId );\r\n\r\n    if ( !pGoal )\r\n        return false;\r\n    if ( pGoal->SetGoalFlag( flag, value ) ) return true;\r\n    \r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::AllFlagsSet( uint32 goalId )\r\n{\r\n    CGoal* pGoal = GetGoal( goalId );\r\n\r\n    Dbg_Assert( pGoal );\r\n    return pGoal->AllFlagsSet();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::GoalFlagSet( uint32 goalId, uint32 flag )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\treturn pGoal->GoalFlagSet( flag );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CGoalManager::CreatedGapGoalIsActive()\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* p_goal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( p_goal );\r\n\t\t\r\n\t\tif (p_goal->IsActive())\r\n\t\t{\r\n\t\t\tScript::CStruct *p_params=p_goal->GetParams();\r\n\t\t\tScript::CArray *p_dummy=NULL;\r\n\t\t\tif (p_params->GetArray(CRCD(0x52d4489e,\"required_gaps\"),&p_dummy))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\t\r\n\t}\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::GetCreatedGoalGap(int gapIndex)\r\n{\r\n\tbool return_value=false;\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* p_goal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( p_goal );\r\n\t\t\r\n\t\treturn_value=p_goal->GetCreatedGoalGap(gapIndex);\r\n\t}\t\r\n\treturn return_value;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* CGoalManager::GetGoalParams( uint32 goalId )\r\n{\r\n\t// printf(\"trying to get params for goalId %x\\n\", goalId);\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n    Dbg_Assert( pGoal );\r\n\r\n    return pGoal->GetParams( );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::CanStartGoal()\r\n{\r\n    return m_canStartGoal;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::NextRaceWaypoint( uint32 goalId )\r\n{\r\n    CRaceGoal* pGoal = (CRaceGoal*)GetGoal( goalId );\r\n\tDbg_MsgAssert( pGoal, ( \"Couldn't find goal: %x\\n\", goalId ) );\r\n\r\n    return pGoal->NextRaceWaypoint( goalId );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::NextTourSpot( uint32 goalId )\r\n{\r\n    CGoal* pGoal = GetGoal( goalId );\r\n    Dbg_Assert( pGoal );\r\n\r\n    return pGoal->NextTourSpot();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::InitTrickObjects( uint32 goalId )\r\n{\r\n    CGoal* pGoal = GetGoal( goalId );\r\n    Dbg_Assert( pGoal );\r\n\r\n    pGoal->InitTrickObjects();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::SetGraffitiMode( int mode )\r\n{\r\n    m_graffitiMode = mode;\r\n\r\n/*    // do we need to reset the scores?\r\n    if ( mode == 0 )\r\n    {\r\n        Mdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n        Obj::CTrickObjectManager* p_TrickObjectManager = skate_mod->GetTrickObjectManager();\r\n        p_TrickObjectManager->ResetAllTrickObjects();\r\n    }\r\n*/\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::ShouldLogTrickObject()\r\n{\r\n    int activeGoal = GetActiveGoal( true );\r\n\tif ( activeGoal == -1 )\r\n\t\treturn false;\r\n\r\n\tuint32 key;\r\n\tCGoal* pGoal = m_goalList.GetItemByIndex( activeGoal, (int*)&key );\r\n\tDbg_Assert( pGoal );\r\n\treturn pGoal->ShouldLogTrickObject();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::GotTrickObject( uint32 clusterId, int score )\r\n{\r\n\tint activeGoal = GetActiveGoal( true );\r\n\tif ( activeGoal == -1 )\t// no active goal\r\n\t\treturn;\r\n\t\r\n\tuint32 key;\r\n\tCGoal* pGoal = m_goalList.GetItemByIndex( activeGoal, (int*)&key );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tif ( pGoal->IsGraffitiGoal() )\r\n\t\tpGoal->GotGraffitiCluster( clusterId, score );\r\n\telse\r\n\t\tpGoal->GotTrickObject( clusterId );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::CheckTrickText()\r\n{\r\n    int activeGoal = GetActiveGoal( true );\r\n    \r\n    if ( activeGoal == -1 )\r\n        return;\r\n\r\n    uint32 key;\r\n    CGoal* pGoal = m_goalList.GetItemByIndex( activeGoal, (int*)&key );\r\n\r\n    Dbg_Assert( pGoal );\r\n\r\n    Script::CStruct* p_goal_params = pGoal->GetParams();\r\n\tif ( pGoal->IsSpecialGoal() || p_goal_params->ContainsFlag( CRCD(0x8e6014f6,\"create_a_trick\") ) )\r\n    {\t\t\r\n\t\t// don't check special goals that are setup with gaps\r\n\t\tif ( !p_goal_params->ContainsFlag( \"special_gap\" ) )\r\n\t\t{\r\n\t\t\tif ( pGoal->CheckSpecialGoal() )\r\n\t\t\t{\r\n\t\t\t\tuint32 goalId = pGoal->GetGoalId();\r\n\t\t\t\tWinGoal( goalId );\r\n\t\t\t}\r\n\t\t}\r\n    }\r\n    else if ( pGoal->IsTetrisGoal() )\r\n    {\r\n        CSkatetrisGoal* p_temp = (CSkatetrisGoal*)pGoal;\r\n\t\tp_temp->CheckTetrisTricks();\r\n    }\r\n\telse if ( pGoal->IsFindGapsGoal() )\r\n\t{\r\n\t\tCFindGapsGoal *p_temp = (CFindGapsGoal*)pGoal;\r\n\t\tp_temp->CheckGaps();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::UnlockGoal( uint32 goalId )\r\n{\r\n    CGoal* pGoal = GetGoal( goalId );\r\n    Dbg_MsgAssert( pGoal, (\"Couldn't find goal to unlock\") );\r\n\r\n    pGoal->UnlockGoal();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::HasWonGoal( uint32 goalId )\r\n{\r\n    CGoal* pGoal = GetGoal( goalId, false );\r\n\r\n    if ( pGoal )\r\n\t\treturn pGoal->HasWonGoal();\r\n\telse\r\n\t{\r\n\t\t// check goal manager params struct in case the goal was in\r\n\t\t// another level\r\n\t\tint hasWonGoal = 0;\r\n\t\tScript::CStruct* pGoalParams;\r\n\t\tif ( mp_goalFlags->GetStructure( goalId, &pGoalParams, Script::NO_ASSERT ) )\r\n\t\t\tpGoalParams->GetInteger( CRCD(0x49807745,\"hasBeaten\"), &hasWonGoal, Script::ASSERT );\r\n\r\n\t\treturn ( hasWonGoal != 0 );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::GoalIsSelected( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n    Dbg_Assert( pGoal );\r\n\r\n    return pGoal->IsSelected();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::ToggleGoalSelection( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n    Dbg_Assert( pGoal );\r\n\r\n\tif( pGoal->IsSelected())\r\n\t{\r\n\t\tpGoal->Deselect();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpGoal->Select();\r\n\t}                   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::GotCounterObject( uint32 goalId )\r\n{\r\n    CGoal* pGoal = GetGoal( goalId );\r\n    Dbg_Assert( pGoal );\r\n\r\n    if ( pGoal->IsActive() )\r\n\t\tpGoal->GotCounterObject();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::CounterGoalDone( uint32 goalId )\r\n{\r\n    CGoal* pGoal = GetGoal( goalId );\r\n    Dbg_Assert( pGoal );\r\n\r\n    return pGoal->CounterGoalDone();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::SpendGoalPoints( int num )\r\n{\r\n    m_goalPoints -= num;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::AddGoalPoint()\r\n{\r\n    m_goalPoints++;\r\n\tm_totalGoalPointsEarned++;\r\n\tScript::RunScript( CRCD(0x888ef05e,\"GoalManager_ShowGoalPoints\") );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::HasGoalPoints( int num )\r\n{\r\n    return ( m_goalPoints >= num );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoalManager::GetNumberOfGoalPoints()\r\n{\r\n    return m_goalPoints;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoalManager::GetTotalNumberOfGoalPointsEarned()\r\n{\r\n    return m_totalGoalPointsEarned;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::ClearGoalPoints()\r\n{\r\n\tm_goalPoints = 0;\r\n\tm_totalGoalPointsEarned = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::AddCash( int amount )\r\n{\r\n    m_cash += amount;\r\n\tm_totalCash += amount;\r\n\tif ( GetNumActiveGoals() < 1 )\r\n\t{\r\n\t\tScript::RunScript( CRCD(0x888ef05e,\"GoalManager_ShowGoalPoints\") );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::SpendCash( int amount )\r\n{\r\n    if ( amount <= m_cash)\r\n    {\r\n        m_cash -= amount;\r\n        return true;\r\n    } \r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoalManager::GetCash( bool get_total )\r\n{\r\n    if ( get_total )\r\n\t\treturn m_totalCash;\r\n\treturn m_cash;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::HasBeatenGoalWithProset( const char* proset_prefix )\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n    {\r\n        uint32 key;\r\n        CGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n        Dbg_Assert( pGoal );\r\n\r\n        if ( pGoal->HasWonGoal() && pGoal->HasProset( proset_prefix ) )\r\n        {\r\n            return true;\r\n        }\r\n    }\r\n    return false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::LevelUnload()\r\n{\r\n\t// don't do this in net games!\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tif ( gamenet_man->InNetGame() )\r\n\t\treturn;\r\n\t\r\n\t// save goal manager params\r\n\tScript::CStruct *p_manager_params = new Script::CStruct();\r\n\r\n\tp_manager_params->AddInteger( CRCD(0x6abb6fcb,\"goalPoints\"), m_goalPoints );\r\n\tp_manager_params->AddInteger( CRCD(0x79ed60aa,\"totalGoalPointsEarned\"), m_totalGoalPointsEarned );\r\n\tp_manager_params->AddInteger( CRCD(0xf9461a46,\"cash\"), m_cash );\r\n\tp_manager_params->AddInteger( CRCD(0x875e89bb,\"total_cash\"), m_totalCash );\r\n\t// p_manager_params->AddInteger( \"numGoalsToPro\", m_numGoalsToPro );\r\n\tp_manager_params->AddInteger( CRCD(0x46f71d38,\"numGoalsBeaten\"), m_numGoalsBeaten );\r\n\r\n\tp_manager_params->AddInteger( CRCD(0xf884773c,\"currentChapter\"), m_currentChapter );\r\n\tp_manager_params->AddInteger( CRCD(0xaf1575eb,\"currentStage\"), m_currentStage );\r\n\tp_manager_params->AddChecksum( CRCD(0x7e73362b,\"sponsor\"), m_sponsor );\r\n\tp_manager_params->AddStructure( CRCD(0x3b1f59e0,\"team\"), mp_team );\r\n\tp_manager_params->AddStructure( CRCD(0xb13d98d3,\"difficulty_levels\"), mp_difficulty_levels );\r\n\t\r\n/*\tint proChallengesUnlocked = 0;\r\n\tif ( m_proChallengesUnlocked )\r\n\t\tproChallengesUnlocked = 1;\r\n\tp_manager_params->AddInteger( CRCD(0x24c226fa,\"proChallengesUnlocked\"), proChallengesUnlocked );\r\n*/\r\n\tint isPro = 0;\r\n\tif ( m_isPro )\r\n\t\tisPro = 1;\r\n\tp_manager_params->AddInteger( CRCD(0x40801d41,\"isPro\"), isPro );\r\n\r\n\t// p_manager_params->AddStructure( CRCD(0xf8478579,\"proSpecificChallenges\"), mp_proSpecificChallenges );\r\n\r\n\tmp_goalFlags->AddStructure( CRCD(0x23d4170a,\"GoalManager_Params\"), p_manager_params );\r\n\r\n\tdelete p_manager_params;\r\n\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n    {\r\n        uint32 key;\r\n        CGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n        Dbg_Assert( pGoal );\r\n\t\tScript::CStruct* pGoalParams = pGoal->GetParams();\r\n\t\t\r\n\t\tif ( !pGoalParams->ContainsFlag( CRCD(0x3d1cab0b,\"null_goal\") ) && !pGoal->IsEditedGoal() ) // K: Don't add edited goals\r\n\t\t{\r\n\t\t\tScript::CStruct* p_temp = new Script::CStruct();\r\n\t\t\tpGoal->GetSaveData( p_temp );\r\n\t\t\tmp_goalFlags->AddStructure( pGoal->GetGoalId(), p_temp );\r\n\t\t\tdelete p_temp;\r\n\t\t}\t\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::LevelLoad()\r\n{\r\n    Script::CComponent* p_comp = NULL;\r\n    p_comp = mp_goalFlags->GetNextComponent( p_comp );\r\n\r\n    while ( p_comp )\r\n    {\r\n        Script::CComponent* p_next = mp_goalFlags->GetNextComponent( p_comp );\r\n\r\n\t\t// special goal manager params structure\r\n\t\tif ( p_comp->mNameChecksum == CRCD( 0x23d4170a, \"GoalManager_Params\" ) )\r\n\t\t{\r\n\t\t\tp_comp->mpStructure->GetInteger( CRCD(0x6abb6fcb,\"goalPoints\"), &m_goalPoints, Script::NO_ASSERT );\r\n\t\t\tp_comp->mpStructure->GetInteger( CRCD(0x79ed60aa,\"totalGoalPointsEarned\"), &m_totalGoalPointsEarned, Script::NO_ASSERT );\r\n\t\t\tp_comp->mpStructure->GetInteger( CRCD(0xf9461a46,\"cash\"), &m_cash, Script::NO_ASSERT );\r\n\t\t\tp_comp->mpStructure->GetInteger( CRCD(0x875e89bb,\"total_cash\"), &m_totalCash, Script::NO_ASSERT );\r\n\t\t\t// p_comp->mpStructure->GetInteger( \"numGoalsToPro\", &m_numGoalsToPro, Script::NO_ASSERT );\r\n\t\t\tp_comp->mpStructure->GetInteger( CRCD(0x46f71d38,\"numGoalsBeaten\"), &m_numGoalsBeaten, Script::NO_ASSERT );\r\n\r\n\t\t\tint auto_change_chapter_and_stage = 0;\r\n\t\t\tauto_change_chapter_and_stage = Script::GetInteger( CRCD(0x5a1d8804,\"auto_change_chapter_and_stage\"), Script::NO_ASSERT );\r\n\t\t\tif ( auto_change_chapter_and_stage == 0 )\r\n\t\t\t{\r\n\t\t\t\tp_comp->mpStructure->GetInteger( CRCD(0xf884773c,\"currentChapter\"), &m_currentChapter, Script::NO_ASSERT );\r\n\t\t\t\tp_comp->mpStructure->GetInteger( CRCD(0xaf1575eb,\"currentStage\"), &m_currentStage, Script::NO_ASSERT );\t\t\t\t\r\n\t\t\t}\r\n\t\t\tp_comp->mpStructure->GetChecksum( CRCD(0x7e73362b,\"sponsor\"), &m_sponsor, Script::ASSERT );\r\n\t\t\t\r\n\t\t\tScript::CStruct* p_copy;\r\n\t\t\tp_comp->mpStructure->GetStructure( CRCD(0x3b1f59e0,\"team\"), &p_copy, Script::ASSERT );\r\n\t\t\tmp_team->Clear();\r\n\t\t\tmp_team->AppendStructure( p_copy );\r\n\r\n\t\t\tScript::CStruct* p_diff_copy;\r\n\t\t\tp_comp->mpStructure->GetStructure( CRCD(0xb13d98d3,\"difficulty_levels\"), &p_diff_copy, Script::ASSERT );\r\n\t\t\tmp_difficulty_levels->Clear();\r\n\t\t\tmp_difficulty_levels->AppendStructure( p_diff_copy );\r\n\t\t\t\r\n\t\t\tint isPro;\r\n\t\t\tp_comp->mpStructure->GetInteger( CRCD(0x40801d41,\"isPro\"), &isPro, Script::ASSERT );\r\n\t\t\tif ( isPro != 0 )\r\n\t\t\t\tTurnPro();\r\n\t\t\t\r\n/*\t\t\tint proChallengesUnlocked;\r\n\t\t\tp_comp->mpStructure->GetInteger( CRCD(0x24c226fa,\"proChallengesUnlocked\"), &proChallengesUnlocked, Script::ASSERT );\r\n\t\t\tif ( proChallengesUnlocked != 0 )\r\n\t\t\t\tm_proChallengesUnlocked = true;\r\n\r\n\t\t\tScript::CStruct* p_copy;\r\n\t\t\tp_comp->mpStructure->GetStructure( CRCD(0xf8478579,\"proSpecificChallenges\"), &p_copy, Script::ASSERT );\r\n\t\t\tmp_proSpecificChallenges->AppendStructure( p_copy );\r\n*/\r\n\t\t}\r\n\t\telse \r\n\t\t{\r\n\t\t\tCGoal* pGoal = GetGoal( p_comp->mNameChecksum, false );\r\n\t\t\tif ( pGoal )\r\n\t\t\t\tpGoal->LoadSaveData( p_comp->mpStructure );\r\n\t\t}\r\n        \r\n\t\tp_comp = p_next;\r\n    }\r\n\t\r\n\t// make sure to unlock any pro goals (they may have turned pro in another level)\r\n\tif ( m_isPro )\r\n\t\tTurnPro();\r\n\r\n\t// ...and unlock any pro challenges\r\n\t// if ( m_proChallengesUnlocked )\r\n\t\t// UnlockProSpecificChallenges();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoalManager::NumGoalsBeatenBy( int obj_id )\r\n{\r\n\tint i, num_beaten;\r\n\tCGoal* pGoal;\r\n\r\n\tnum_beaten = 0;\r\n\tfor ( i = 0; i < GetNumGoals(); i++ )\r\n    {\r\n        uint32 key;\r\n        pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n        Dbg_Assert( pGoal );\r\n\r\n\t\tif( pGoal->GetParents()->m_relative != 0 )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif( pGoal->HasWonGoal( obj_id ))\r\n\t\t{\r\n\t\t\tnum_beaten++;\r\n\t\t}\r\n\t}\r\n\r\n\treturn num_beaten;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoalManager::NumGoalsBeatenByTeam( int team_id )\r\n{\r\n\tint i, num_beaten;\r\n\tCGoal* pGoal;\r\n\r\n\tnum_beaten = 0;\r\n\tfor ( i = 0; i < GetNumGoals(); i++ )\r\n    {\r\n        uint32 key;\r\n        pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n        Dbg_Assert( pGoal );\r\n\r\n\t\tif( pGoal->GetParents()->m_relative != 0 )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif( pGoal->HasTeamWonGoal( team_id ))\r\n\t\t{\r\n\t\t\tnum_beaten++;\r\n\t\t}\r\n\t}\r\n\r\n\treturn num_beaten;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoalManager::NumGoalsBeaten()\r\n{\r\n\tint i, num_beaten;\r\n\tCGoal* pGoal;\r\n\r\n\tnum_beaten = 0;\r\n\tfor ( i = 0; i < GetNumGoals(); i++ )\r\n    {\r\n        uint32 key;\r\n        pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n        Dbg_Assert( pGoal );\r\n\r\n\t\tif( pGoal->GetParents()->m_relative != 0 )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif( pGoal->HasWonGoal())\r\n\t\t{\r\n\t\t\tnum_beaten++;\r\n\t\t}\r\n\t}\r\n\r\n\treturn num_beaten;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CGoalManager::NumGoalsBeatenInLevel( int levelNum, bool count_pro_specific_challenges )\r\n{\r\n    // store all the goal info in the goalmanager's struct\r\n    // so we can grab it all in one place\r\n    LevelUnload();\r\n    \r\n    int numbeat = 0;\r\n    Script::CComponent* p_comp = mp_goalFlags->GetNextComponent( NULL );\r\n    Script::CComponent* p_next = NULL;\r\n    while ( p_comp )\r\n    {\r\n        // printf(\"checking p_comp\\n\");\r\n        p_next = mp_goalFlags->GetNextComponent( p_comp );\r\n\r\n        int p_comp_levelNum = 0;\r\n        if ( p_comp->mpStructure->GetInteger( CRCD(0x1a4cde06,\"levelNum\"), &p_comp_levelNum, Script::NO_ASSERT ) )\r\n        {\r\n            // printf(\"found levelNum\\n\");\r\n/*\t\t\tif ( !count_pro_specific_challenges )\r\n\t\t\t{\r\n\t\t\t\tint isProSpecificChallenge;\r\n\t\t\t\tp_comp->mpStructure->GetInteger( CRCD(0x3dbe3121,\"isProSpecificChallenge\"), &isProSpecificChallenge, Script::ASSERT );\r\n\t\t\t\tif ( isProSpecificChallenge == 1 )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_comp = p_next;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n*/\r\n\t\t\tint hasBeaten = 0;\r\n\t\t\tp_comp->mpStructure->GetInteger( CRCD(0x49807745,\"hasBeaten\"), &hasBeaten, Script::NO_ASSERT );\r\n            if ( p_comp_levelNum == levelNum && hasBeaten )\r\n            {\r\n                numbeat++;\r\n            }\r\n        }\r\n        p_comp = p_next;\r\n    }\r\n    return numbeat;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoalManager::UnlockAllGoals()\r\n{\r\n    m_isPro = true;\r\n\t// m_proChallengesUnlocked = true;\r\n\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n    {\r\n        uint32 key;\r\n        CGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n        Dbg_Assert( pGoal );\r\n        // pGoal->UnlockGoal();\r\n\t\tpGoal->SetHasSeen();\r\n    }\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::TurnPro()\r\n{\r\n\tm_isPro = true;\r\n\t// m_proChallengesUnlocked = true;\r\n\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\t\r\n\t\tif ( pGoal->IsProGoal() && pGoal->IsLocked() )\r\n\t\t{\r\n\t\t\tpGoal->UnlockGoal();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoalManager::SetStartTime( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->SetStartTime();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoalManager::CheckMinigameRecord( uint32 goalId, int value )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\treturn pGoal->CheckMinigameRecord( value );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::UpdateComboTimer( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->UpdateComboTimer();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::SetStartHeight( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->SetStartHeight();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::CheckHeightRecord( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\treturn pGoal->CheckHeightRecord();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::CheckDistanceRecord( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\treturn pGoal->CheckDistanceRecord();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::PlayGoalStartStream( Script::CStruct* pParams )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->mp_goalPed->PlayGoalStartStream( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::PlayGoalWaitStream( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->mp_goalPed->PlayGoalWaitStream();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::PlayGoalStream( Script::CStruct* pParams )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\t// if we got a specific stream, just play it and quit\r\n\tuint32 stream_checksum = 0;\r\n\tpParams->GetChecksum( CRCD(0x1a4e4fb9,\"vo\"), &stream_checksum, Script::NO_ASSERT );\r\n\tif ( stream_checksum )\r\n\t{\r\n\t\tpGoal->mp_goalPed->PlayGoalStream( stream_checksum );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// check for type\r\n\tconst char* type = NULL;\r\n\tif ( pParams->GetString( CRCD(0x7321a8d6,\"type\"), &type, Script::NO_ASSERT ) )\r\n\t{\t\t\r\n\t\tpGoal->mp_goalPed->PlayGoalStream( type, pParams );\r\n\t\treturn;\r\n\t}\t\t\r\n\t\r\n\t// you gotta have one or the other\r\n\tif ( !type && !stream_checksum )\r\n\t\tDbg_MsgAssert( 0, (\"GoalManager_PlayGoalStream called without a type or vo checksum\") );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::StopCurrentStream( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->mp_goalPed->StopCurrentStream();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::PlayGoalWinStream( Script::CStruct* pParams )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->mp_goalPed->PlayGoalWinStream( pParams );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::PauseGoal( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->PauseGoal();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::UnPauseGoal( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->UnPauseGoal();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::PauseCompetition( uint32 goalId )\r\n{\r\n\tGame::CCompetitionGoal* pComp = (Game::CCompetitionGoal*)GetGoal( goalId );\r\n\tDbg_Assert( pComp );\r\n\r\n\tpComp->PauseCompetition();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::UnPauseCompetition( uint32 goalId )\r\n{\r\n\tGame::CCompetitionGoal* pComp = (Game::CCompetitionGoal*)GetGoal( goalId );\r\n\tDbg_Assert( pComp );\r\n\r\n\tpComp->UnPauseCompetition();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::UnBeatAllGoals()\r\n{\t\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tif ( pGoal->UnBeatGoal() && !gamenet_man->InNetGame() )\r\n\t\t{\r\n\t\t\t// m_numGoalsToPro++;\r\n\t\t\tm_numGoalsBeaten--;\r\n\t\t\tm_goalPoints--;\r\n\t\t\tm_totalGoalPointsEarned--;\r\n\t\t}\r\n\t}\r\n\t// clear the goal manager's memory of goals too\r\n\tif ( !gamenet_man->InNetGame() )\r\n\t\tmp_goalFlags->Clear();\r\n\r\n\tif ( GetNumActiveGoals() == 0 )\r\n\t{\r\n\t\tif( CFuncs::ScriptInMultiplayerGame( NULL, NULL ) == false )\r\n\t\t{\r\n\t\t\tScript::RunScript( CRCD(0x888ef05e,\"GoalManager_ShowGoalPoints\") );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::AddViewGoalsList()\r\n{\r\n\t\r\n\tint numGoals = GetNumGoals();\r\n\tScript::CArray* p_ordered_goals = new Script::CArray();\r\n\tScript::CArray* p_unordered_goals = new Script::CArray();\t\r\n\tp_ordered_goals->SetSizeAndType( numGoals, ESYMBOLTYPE_NAME );\r\n\tp_unordered_goals->SetSizeAndType( numGoals, ESYMBOLTYPE_NAME );\r\n\t\r\n\tint num_ordered_goals = 0;\r\n\tint num_unordered_goals = 0;\r\n\t\r\n\t// divide the list into goals with ordinals and goals without\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tif ( pGoal->GetParams()->ContainsComponentNamed( CRCD(0x9b048fc,\"ordinal\") ) )\r\n\t\t{\r\n\t\t\tp_ordered_goals->SetChecksum( num_ordered_goals, pGoal->GetGoalId() );\r\n\t\t\tnum_ordered_goals++;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_unordered_goals->SetChecksum( num_unordered_goals, pGoal->GetGoalId() );\r\n\t\t\tnum_unordered_goals++;\r\n\t\t}\t\t\t\r\n\t}\r\n\r\n\t// sort the list of goals with ordinals\r\n\t// printf(\"there are %i ordered goals\\n\", num_ordered_goals);\r\n\tfor ( int i = 0; i < num_ordered_goals; i++ )\r\n\t{\r\n\t\t// inefficient sorting, but there's only ~20 things - brad\r\n\t\tfor ( int j = i; j < num_ordered_goals; j++ )\r\n\t\t{\r\n\t\t\tuint32 temp = p_ordered_goals->GetChecksum( j );\r\n\t\t\tCGoal* p_temp_goal = GetGoal( temp );\r\n\t\t\tDbg_Assert( p_temp_goal );\r\n\t\t\tint ordinal_check;\r\n\t\t\tp_temp_goal->GetParams()->GetInteger( CRCD(0x9b048fc,\"ordinal\"), &ordinal_check, Script::ASSERT );\r\n\t\t\tDbg_MsgAssert( ordinal_check - 1 < num_ordered_goals, ( \"Ordinal value %i too big.\", ordinal_check ) );\r\n\t\t\tif ( ordinal_check - 1 == i )\r\n\t\t\t{\r\n\t\t\t\tif ( j == i )\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t// swap them\t\t\t\t\r\n\t\t\t\tuint32 temp2 = p_ordered_goals->GetChecksum( i );\r\n\t\t\t\tint double_check;\r\n\t\t\t\tGetGoal( temp2 )->GetParams()->GetInteger( CRCD(0x9b048fc,\"ordinal\"), &double_check, Script::ASSERT );\r\n\t\t\t\tDbg_MsgAssert( double_check != i, ( \"Found ordinal %i twice\", double_check ) );\r\n\r\n\t\t\t\tp_ordered_goals->SetChecksum( i, temp );\r\n\t\t\t\tp_ordered_goals->SetChecksum( j, temp2 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// tack on the list of unordered goals\r\n\tfor ( int i = 0; i < num_unordered_goals; i++ )\r\n\t\tp_ordered_goals->SetChecksum( i + num_ordered_goals, p_unordered_goals->GetChecksum( i ) );\r\n\t\r\n\t// populate the menu\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 goalId = p_ordered_goals->GetChecksum( i );\r\n\t\tCGoal* pGoal = GetGoal( goalId );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tScript::CStruct* pGoalParams = pGoal->GetParams();\r\n\r\n\t\tconst char* p_view_goals_text = NULL;\r\n\t\tpGoal->GetViewGoalsText( &p_view_goals_text );\r\n\t\t\r\n\t\t// skip goals without an associated text (eg, minigames)\r\n\t\tif ( !p_view_goals_text )\r\n\t\t\tcontinue;\r\n\r\n\t\t// skip pro goals if we're not pro\r\n\t\tif ( !IsPro() && pGoalParams->ContainsFlag( CRCD(0xd303a1a3,\"pro_goal\") ) )\r\n\t\t\tcontinue;\r\n\r\n\t\t// skip pro challenges if we haven't unlocked them.\r\n\t\t// if ( !ProSpecificChallengesUnlocked() && pGoalParams->ContainsFlag( CRCD(0xe0f96410,\"pro_specific_challenge\") ) )\r\n\t\t\t// continue;\r\n\t\t\r\n\t\t// skip pro specific challenges if we're not the right skater\r\n/*\t\tif ( !pGoal->HasWonGoal() && !IsPro() && pGoalParams->ContainsFlag( CRCD(0xe0f96410,\"pro_specific_challenge\") ) )\r\n\t\t{\r\n\t\t\t// check the current skater against the listed pro\r\n\t\t\tScript::CStruct* pLastNames = Script::GetStructure( CRCD(0x621d1828,\"goal_pro_last_name_checksums\"), Script::ASSERT );\r\n\t\t\tconst char* pProChallengeProName;\r\n\t\t\tpGoalParams->GetString( CRCD(0x4a91eceb,\"pro_challenge_pro_name\"), &pProChallengeProName, Script::ASSERT );\r\n\t\t\tuint32 last_name = 0;\r\n\t\t\tpLastNames->GetChecksum( Script::GenerateCRC( pProChallengeProName ), &last_name, Script::NO_ASSERT );\r\n\t\t\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\t\t\tObj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile();\r\n\t\t\tif ( last_name && last_name != pSkaterProfile->GetSkaterNameChecksum() )\r\n\t\t\t\tcontinue;\r\n\t\t}\r\n*/\r\n\t\tif( pGoal->IsNetGoal())\r\n\t\t\tcontinue;\r\n\t\t\r\n\t\t// create the screen element\r\n\t\tScript::CStruct* p_elem_params = new Script::CStruct();\r\n\t\tuint32 id = pGoal->GetGoalId();\r\n\t\t\r\n\t\t// add the id so we can use the same struct when calling the set_events script below\r\n\t\tp_elem_params->AddChecksum( CRCD(0x9982e501,\"goal_id\"), id );\r\n\t\tp_elem_params->AddString( CRCD(0xc4745838,\"text\"), p_view_goals_text );\r\n\r\n\t\t// check for a win record\r\n\t\tuint32 record_type;\r\n\t\tif ( pGoal->HasWonGoal() )\r\n\t\t{\r\n\t\t\tint record = 0;\r\n\t\t\tchar record_string[128];\r\n\r\n\t\t\t// special case for competition\r\n\t\t\tif ( pGoal->IsCompetition() )\r\n\t\t\t{\r\n\t\t\t\tpGoalParams->GetInteger( CRCD(0xc22a2b72,\"win_record\"), &record, Script::NO_ASSERT );\r\n\t\t\t\tsprintf( record_string, \"%i\", record );\r\n\t\t\t\tswitch ( record )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase 1:\r\n\t\t\t\t\t\tstrcat( record_string, \"st place\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 2:\r\n\t\t\t\t\t\tstrcat( record_string, \"nd place\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 3:\r\n\t\t\t\t\t\tstrcat( record_string, \"rd place\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tDbg_Message( \"WARNING: competition place is %i\", record );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\t\t\t\t\t\r\n\t\t\t\tp_elem_params->AddString( CRCD(0xbb48af8b,\"win_record_string\"), record_string );\r\n\t\t\t}\t\t\t\r\n\t\t\telse if ( pGoalParams->GetChecksum( CRCD(0x96963902,\"record_type\"), &record_type, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\t// For the purposes of supporting different record types in the future,\r\n\t\t\t\t// I've left some repeated code within each block.\r\n\t\t\t\tif ( record_type == ( CRCD(0xcd66c8ae,\"score\") ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tpGoalParams->GetInteger( CRCD(0xc22a2b72,\"win_record\"), &record, Script::NO_ASSERT );\r\n\t\t\t\t\tsprintf( record_string, \"%s\", Str::PrintThousands( record ) );\r\n\r\n\t\t\t\t\tp_elem_params->AddString( CRCD(0xbb48af8b,\"win_record_string\"), record_string );\r\n\t\t\t\t}\r\n\t\t\t\telse if ( record_type == ( CRCD(0x906b67ba,\"time\") ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tint record = 0;\r\n\t\t\t\t\tpGoalParams->GetInteger( CRCD(0xc22a2b72,\"win_record\"), &record, Script::NO_ASSERT );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// break down into minutes, seconds, fraction\r\n\t\t\t\t\tint min, sec, fraction;\r\n\t\t\t\t\tsec = record / 1000;\r\n\t\t\t\t\tmin = ( sec / 60 );\r\n\t\t\t\t\tsec -= ( min * 60 );\r\n\t\t\t\t\tfraction = ( ( record % 1000 ) / 10 );\r\n\t\t\t\t\tsprintf( record_string, \"%i:%02i.%02i\", min, sec, fraction );\r\n\r\n\t\t\t\t\tp_elem_params->AddString( CRCD(0xbb48af8b,\"win_record_string\"), record_string );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_elem_params->AddChecksum( NONAME,  CRCD(0xc80e196,\"no_record_type\")  );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// create the item\r\n\t\tScript::RunScript( CRCD(0x380aea65,\"view_goals_menu_add_item\"), p_elem_params );\r\n\r\n\t\tdelete p_elem_params;\r\n\t}\r\n\t\r\n\t// cleanup!\r\n\tScript::CleanUpArray( p_ordered_goals );\r\n\tScript::CleanUpArray( p_unordered_goals );\r\n\tdelete p_ordered_goals;\r\n\tdelete p_unordered_goals;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::AddGoalChoices( bool selected_only )\r\n{\r\n\t\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tconst char* p_view_goals_text = NULL;\r\n\t\tpGoal->ReplaceTrickText();\r\n\t\tpGoal->GetViewGoalsText( &p_view_goals_text );\r\n\t\t\r\n\t\t// skip goals without an associated text (eg, minigames)\r\n\t\tif ( !p_view_goals_text )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif( pGoal->IsNetGoal())\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif( pGoal->IsMinigame())\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n        if( pGoal->GetParents()->m_relative != 0 )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif( GameNet::Manager::ScriptIsHost( NULL, NULL ))\r\n\t\t{\r\n\t\t\t// if( pGoal->HasSeenGoal() == false )\r\n\t\t\t// {\r\n\t\t\t\t// continue;\r\n\t\t\t// }\r\n\t\r\n\t\t\t// if( pGoal->IsLocked())\r\n\t\t\t// {\r\n\t\t\t\t// continue;\r\n\t\t\t// }\r\n\t\t}\r\n\r\n\t\tif( selected_only )\r\n\t\t{\r\n\t\t\tif( !pGoal->IsSelected())\r\n\t\t\t{\r\n\t\t\t\t\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// create the screen element\r\n\t\tScript::CStruct* p_elem_params = new Script::CStruct();\r\n\t\tuint32 id = pGoal->GetGoalId();\r\n\t\t\r\n\r\n\t\t// add the id so we can use the same struct when calling the set_events script below\r\n\t\tp_elem_params->AddChecksum( CRCD(0x9982e501,\"goal_id\"), id );\r\n\t\tp_elem_params->AddChecksum( CRCD(0xc2719fb0,\"parent\"), CRCD( 0x4d49ac0a, \"current_menu\" ) );\r\n\t\tp_elem_params->AddString( CRCD(0xc4745838,\"text\"), p_view_goals_text );\r\n\t\tp_elem_params->AddChecksum( CRCD(0x2f6bf72d,\"font\"), CRCD( 0x8aba15ec, \"small\" ) );\t\t\r\n\t\tp_elem_params->AddInteger( CRCD(0x13b9da7b,\"scale\"), 0 );\r\n\t\t\r\n\t\t\r\n\t\t// set initial color and events for this item\r\n\t\tif( selected_only )\r\n\t\t{\r\n\t\t\tScript::RunScript( CRCD(0xe704c86c,\"view_selected_goals_menu_set_events\"), p_elem_params);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tScript::RunScript( CRCD(0x6790ac11,\"choose_goals_menu_set_events\"), p_elem_params);\r\n\t\t}\r\n\t\t// normally, script won't be updated until next frame -- we want it NOW\r\n\t\t// p_new_script->Update();\r\n\r\n\t\tdelete p_elem_params;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::GoalIsLocked( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId, false );\r\n\t\r\n\tif ( pGoal )\r\n\t{\r\n\t\treturn pGoal->IsLocked();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// check goal manager params struct in case the goal was in\r\n\t\t// another level\r\n\t\tint goalLocked = 0;\r\n\t\tScript::CStruct* pGoalParams;\r\n\t\tif ( mp_goalFlags->GetStructure( goalId, &pGoalParams, Script::NO_ASSERT ) )\r\n\t\t\tpGoalParams->GetInteger( CRCD(0xd3e93882,\"isLocked\"), &goalLocked, Script::ASSERT );\r\n\r\n\t\treturn ( goalLocked != 0 );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGoal* CGoalManager::IsInCompetition()\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tif ( pGoal->IsCompetition() && pGoal->IsActive() )\r\n\t\t{\r\n\t\t\treturn pGoal;\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::GetGoalAnimations( uint32 goalId, const char* type, Script::CScript* pScript )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tuint32 array_name = pGoal->mp_goalPed->GetGoalAnimations( type );\r\n\t// Dbg_Assert( p_anims_array );\r\n\r\n\t// never know\r\n\tpScript->GetParams()->RemoveComponent( CRCD(0x18653764,\"pro_stuff\") );\r\n\tif ( array_name )\r\n\t\tpScript->GetParams()->AddChecksum( CRCD(0x18653764,\"pro_stuff\"), array_name );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CGoalManager::GetRandomBettingMinigame()\r\n{\r\n\t// create an index array and randomize\r\n\tint numGoals = GetNumGoals();\r\n\tint* indexes = new int[numGoals];\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t\tindexes[i] = i;\r\n\tfor ( int i = 0; i < numGoals * 5; i++ )\r\n\t{\r\n\t\tint aIndex = Mth::Rnd( numGoals );\r\n\t\tint bIndex = Mth::Rnd( numGoals );\r\n\t\tint a = indexes[aIndex];\r\n\t\tindexes[aIndex] = indexes[bIndex];\r\n\t\tindexes[bIndex] = a;\r\n\t}\r\n\t\r\n\t// look through until we find one that's suitable\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( indexes[i], (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tif ( pGoal->IsBettingGame() )\r\n\t\t{\r\n\t\t\tdelete[] indexes;\r\n\t\t\treturn pGoal->GetGoalId();\r\n\t\t}\r\n\t}\r\n\tdelete[] indexes;\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::EndRunCalled( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\treturn pGoal->EndRunCalled();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CGoalManager::GetBettingGuyId()\r\n{\r\n\t// find the betting guy\r\n\tint numGoals = GetNumGoals();\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tif ( pGoal->IsBettingGuy() )\r\n\t\t{\t\t\t\r\n\t\t\treturn pGoal->GetGoalId();\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::DeactivateMinigamesWithTimer()\r\n{\r\n\tint numGoals = GetNumGoals();\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tif ( pGoal->IsMinigame() && pGoal->IsActive() && pGoal->ShouldUseTimer() )\r\n\t\t\tpGoal->Deactivate();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* CGoalManager::GetGoalManagerParams()\r\n{\r\n\treturn mp_goalFlags;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::ReplaceTrickText( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\treturn pGoal->ReplaceTrickText();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::ReplaceTrickText( uint32 goalId, const char* p_old_string, char* p_new_string, uint out_buffer_size )\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n#endif\t\t// __NOPT_ASSERT__\r\n\r\n\t// get the key combo array\r\n\tScript::CStruct* p_goal_params = GetGoalParams( goalId );\r\n\tScript::CArray* p_key_combo;\r\n\tp_goal_params->GetArray( CRCD(0x79704516,\"key_combos\"), &p_key_combo, Script::ASSERT );\r\n\r\n\t// build the string arrays\r\n\tScript::CArray* p_key = new Script::CArray();\r\n\tScript::CArray* p_trick = new Script::CArray();\r\n\tint size = p_key_combo->GetSize();\r\n\tp_key->SetSizeAndType( size, ESYMBOLTYPE_STRING );\r\n\tp_trick->SetSizeAndType( size, ESYMBOLTYPE_STRING );\r\n\r\n\tint premade_cat_index = -1;\r\n\tif ( p_goal_params->ContainsFlag( CRCD(0x8e6014f6,\"create_a_trick\") ) )\r\n\t{\r\n\t\tp_goal_params->GetInteger( CRCD(0x5b077ce1,\"trickName\"), &premade_cat_index, Script::ASSERT );\r\n\t}\r\n\t\r\n\tif ( !fill_trick_and_key_combo_arrays( p_key_combo, p_key, p_trick, premade_cat_index ) )\r\n\t{\r\n\t\tScript::CleanUpArray( p_key );\r\n\t\tScript::CleanUpArray( p_trick );\r\n\t\tdelete p_key;\r\n\t\tdelete p_trick;\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfind_and_replace_trick_string( p_old_string, p_new_string, p_key, p_trick, out_buffer_size );\r\n\t\r\n\t// cleanup!\r\n\tScript::CleanUpArray( p_key );\r\n\tScript::CleanUpArray( p_trick );\r\n\tdelete p_key;\r\n\tdelete p_trick;\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::ReplaceAllTrickText()\r\n{\r\n\tint numGoals = GetNumGoals();\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tif ( pGoal->IsInitialized() )\r\n\t\t\tpGoal->ReplaceTrickText();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nvoid CGoalManager::UnlockProSpecificChallenges()\r\n{\r\n\tm_proChallengesUnlocked = true;\r\n\tint numGoals = GetNumGoals();\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\t\r\n\t\tif ( pGoal->GetParams()->ContainsFlag( CRCD(0xe0f96410,\"pro_specific_challenge\") ) )\r\n\t\t{\r\n\t\t\t// only unlock it if it's beaten or we're using the right skater\r\n\t\t\tif ( pGoal->HasWonGoal() || pGoal->mp_goalPed->ProIsCurrentSkater() )\r\n\t\t\t\tpGoal->UnlockGoal();\r\n\t\t}\r\n\t}\r\n}\r\n*/\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nbool CGoalManager::ProSpecificChallengesUnlocked()\r\n{\r\n\treturn m_proChallengesUnlocked;\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoalManager::GetNumberCollected( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId, true );\r\n\r\n\treturn pGoal->GetNumberCollected();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoalManager::GetNumberOfFlags( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId, true );\r\n\r\n\treturn pGoal->GetNumberOfFlags();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::IsPro()\r\n{\r\n\treturn m_isPro;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::ResetGoalFlags( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\r\n\tpGoal->ResetGoalFlags();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::ColorTrickObjects( uint32 goalId, int seqIndex, bool clear )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\r\n\tpGoal->ColorTrickObjects( seqIndex, clear );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CGoalManager::GetNumberOfTimesGoalStarted( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\r\n\treturn pGoal->GetNumberOfTimesGoalStarted();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::GoalExists( uint32 goalId )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId, false );\r\n\tif ( pGoal )\r\n\t\treturn true;\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* CGoalManager::GetGoalAttemptInfo()\r\n{\r\n\tint numGoals = GetNumGoals();\r\n\tint totalStarts = 0;\r\n\tScript::CStruct* attemptInfo = new Script::CStruct();\r\n\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tif ( !pGoal->IsMinigame() && !pGoal->IsNetGoal() && pGoal->HasWonGoal() )\r\n\t\t\ttotalStarts += pGoal->GetNumberOfTimesGoalStarted();\r\n\t}\r\n\tattemptInfo->AddInteger( CRCD(0xd023adbe,\"totalStarts\"), totalStarts );\r\n\treturn attemptInfo;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::SetCanStartGoal( int value )\r\n{\r\n\tif ( value != 0 )\r\n\t\tm_canStartGoal = true;\r\n\telse\r\n\t\tm_canStartGoal = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::CheckTrickObjects()\r\n{\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = skate_mod->GetLocalSkater();\r\n\r\n\tMdl::Score* pScore = pSkater->GetScoreObject();\r\n\tint score = pScore->GetLastScoreLanded();\r\n\t\r\n\tObj::CTrickComponent* pTrickComponent = GetTrickComponentFromObject(pSkater);\r\n\tDbg_Assert(pTrickComponent);\r\n\r\n\tObj::CPendingTricks pendingTricks = pTrickComponent->m_pending_tricks;\r\n\r\n\tint max_tricks = pendingTricks.m_NumTrickItems;\r\n\tif ( max_tricks > pendingTricks.vMAX_PENDING_TRICKS )\r\n\t\tmax_tricks = pendingTricks.vMAX_PENDING_TRICKS;\r\n\r\n\tfor ( int i = 0; i < max_tricks; i++ )\r\n\t{\r\n\t\tGotTrickObject( pendingTricks.m_Checksum[i], score );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nvoid CGoalManager::MarkProSpecificChallengeBeaten( uint32 skater_name, int beaten )\r\n{\r\n\tDbg_MsgAssert( mp_proSpecificChallenges->ContainsComponentNamed( skater_name ), (\"MarkProSpecificChallengeBeaten called with unknown skater\") );\r\n\tmp_proSpecificChallenges->AddInteger( skater_name, beaten );\r\n}\r\n*/\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nbool CGoalManager::SkaterHasBeatenProSpecificChallenge( uint32 skater_name )\r\n{\r\n\t// Dbg_MsgAssert( mp_proSpecificChallenges->ContainsComponentNamed( skater_name ), (\"SkaterHasBeatenProSpecificChallenge called with unknown skater %s\", Script::FindChecksumName( skater_name ) ) );\r\n\tif ( mp_proSpecificChallenges->ContainsComponentNamed( skater_name ) )\r\n\t{\r\n\t\tint beaten;\r\n\t\tmp_proSpecificChallenges->GetInteger( skater_name, &beaten, Script::ASSERT );\r\n\t\treturn ( beaten != 0 );\r\n\t}\r\n\treturn false;\r\n}\r\n*/\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::SetEndRunType( uint32 goalId, Game::EndRunType newEndRunType )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->SetEndRunType( newEndRunType );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::ShouldUseTimer()\r\n{\r\n\tint numGoals = GetNumGoals();\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\t\r\n\t\tif ( pGoal->IsActive() && pGoal->ShouldUseTimer() )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::SetShouldDeactivateOnExpire( uint32 goalId, bool should_deactivate )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->SetShouldDeactivateOnExpire( should_deactivate );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoalManager::Land()\r\n{\r\n\tif ( ShouldLogTrickObject() )\r\n\t\tCheckTrickObjects();\r\n\telse \r\n\t{\r\n\t\tint numGoals = GetNumGoals();\r\n\t\tfor ( int i = 0; i < numGoals; i++ )\r\n\t\t{\r\n\t\t\tuint32 key;\r\n\t\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\t\tDbg_Assert( pGoal );\r\n\r\n\t\t\tif ( pGoal->IsActive() && pGoal->IsHorseGoal() )\r\n\t\t\t{\r\n\t\t\t\tGame::CHorseGoal* pHorseGoal = (Game::CHorseGoal*)pGoal;\r\n\t\t\t\tpHorseGoal->CheckScore();\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse if ( pGoal->IsActive() && pGoal->GetParams()->ContainsFlag( CRCD(0xc63432a7,\"high_combo\") ) )\r\n\t\t\t{\r\n\t\t\t\t// TODO: maybe the high combo goal should be a subclass rather than\r\n\t\t\t\t// having a special case here?\t\t\t\t\r\n\t\t\t\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetLocalSkater();\r\n\t\t\t\tif ( pSkater )\r\n\t\t\t\t{\r\n\t\t\t\t\tMdl::Score* pScore = pSkater->GetScoreObject();\r\n\t\t\t\t\tif ( pScore->GetLastScoreLanded() > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tScript::CStruct* pScriptParams = new Script::CStruct();\r\n\t\t\t\t\t\tpScriptParams->AddChecksum( CRCD(0x9982e501,\"goal_id\"), pGoal->GetGoalId() );\r\n\t\t\t\t\t\tpScriptParams->AddInteger( CRCD(0xb9072b65,\"last_score_landed\"), pScore->GetLastScoreLanded() );\r\n\t\t\t\t\t\tScript::RunScript( CRCD(0x6b755ed8,\"goal_highcombo_check_score\"), pScriptParams );\r\n\t\t\t\t\t\tdelete pScriptParams;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( pGoal->IsActive() && pGoal->ShouldRequireCombo() && pGoal->GetParams()->ContainsFlag( CRCD(0x7100155d,\"combo_started\") ) )\r\n\t\t\t{\r\n\t\t\t\t// lose the goal next frame\r\n\t\t\t\tScript::CStruct* pScriptParams = new Script::CStruct();\r\n\t\t\t\tpScriptParams->AddChecksum( CRCD(0x9982e501,\"goal_id\"), pGoal->GetGoalId() );\r\n\t\t\t\tScript::SpawnScript( CRCD(0xfefda11,\"goal_lose_next_frame\"), pScriptParams );\r\n\t\t\t\tdelete pScriptParams;\r\n\t\t\t}\r\n\t\t\telse if ( pGoal->IsActive() && pGoal->GetParams()->ContainsFlag( CRCD( 0x293b95a7, \"score_goal\" ) ) )\r\n\t\t\t{\r\n\t\t\t\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetLocalSkater();\r\n\t\t\t\tif ( pSkater )\r\n\t\t\t\t{\r\n\t\t\t\t\tMdl::Score* pScore = pSkater->GetScoreObject();\r\n\t\t\t\t\tint required_score;\r\n\t\t\t\t\tpGoal->GetParams()->GetInteger( CRCD(0xcd66c8ae,\"score\"), &required_score, Script::ASSERT );\r\n\t\t\t\t\tif ( pScore->GetTotalScore() + pScore->GetScorePotValue() >= required_score )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpGoal->GetParams()->AddInteger( CRCD(0x3da891b6,\"winning_score\"), pScore->GetTotalScore() + pScore->GetScorePotValue() );\r\n\t\t\t\t\t\tWinGoal( pGoal->GetGoalId() );\r\n\t\t\t\t\t\tpGoal->GetParams()->RemoveComponent( CRCD(0x3da891b6,\"winning_score\") );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoalManager::Bail()\r\n{\r\n\tint numGoals = GetNumGoals();\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\r\n\t\tif ( pGoal->IsActive() && pGoal->ShouldRequireCombo() && pGoal->GetParams()->ContainsFlag( CRCD(0x7100155d,\"combo_started\") ) )\r\n\t\t{\r\n\t\t\t// lose the goal next frame\r\n\t\t\tScript::CStruct* pScriptParams = new Script::CStruct();\r\n\t\t\tpScriptParams->AddChecksum( CRCD(0x9982e501,\"goal_id\"), pGoal->GetGoalId() );\r\n\t\t\tScript::SpawnScript( CRCD(0xfefda11,\"goal_lose_next_frame\"), pScriptParams );\r\n\t\t\tdelete pScriptParams;\r\n\t\t}\r\n\t\tif ( pGoal->IsActive() && pGoal->IsTetrisGoal() )\r\n\t\t{\r\n\t\t\tint trick_flag;\r\n\t\t\tif ( pGoal->GetParams()->GetInteger( CRCD( 0x60b827d5, \"trick_flag\" ), &trick_flag, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tif ( trick_flag != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tpGoal->GetParams()->AddInteger( CRCD(0x60b827d5,\"trick_flag\"), 0 );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::AwardMinigameCash( uint32 goalId, int amount )\r\n{\r\n\tCGoal* pGoal = GetGoal( goalId, true );\r\n\tif ( pGoal && pGoal->IsMinigame() )\r\n\t{\r\n\t\tCMinigame* pMinigame = (CMinigame*)pGoal;\r\n\t\treturn pMinigame->AwardCash( amount );\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::ResetCareer()\r\n{\r\n\t// reset all of the goal manager's memory\r\n\tmp_goalFlags->Clear();\r\n\r\n\tm_goalPoints = 0;\r\n\tm_totalGoalPointsEarned = 0;\r\n\tm_cash = 0;\r\n\tm_totalCash = 0;\r\n\tm_numGoalsBeaten = 0;\r\n\t// m_proChallengesUnlocked = false;\r\n\tm_isPro = false;\r\n\t\r\n\t// mp_proSpecificChallenges->AppendStructure( Script::GetStructure( CRCD(0xd8b84847,\"goal_pro_specific_challenges_beaten\"), Script::ASSERT ) );\r\n\tm_currentChapter = m_currentStage = 0;\r\n\r\n\tmp_difficulty_levels->Clear();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::AwardAllGoalCash()\r\n{\r\n\tint numGoals = GetNumGoals();\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\t\r\n\t\tif ( !pGoal->IsMinigame() && !pGoal->HasWonGoal() )\r\n\t\t{\r\n\t\t\t// printf(\"found an unbeaten goal\\n\");\r\n\t\t\tpGoal->MarkBeaten();\r\n\t\t\tScript::CStruct* pRewardParams = new Script::CStruct();\r\n\t\t\tpGoal->GetRewardsStructure( pRewardParams );\r\n\t\t\tint cash;\r\n\t\t\tif ( pRewardParams->GetInteger(\t \"cash\", &cash, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tconst char* p_goal_name;\r\n\t\t\t\tpGoal->GetParams()->GetString( CRCD(0xbfecc45b,\"goal_name\"), &p_goal_name, Script::ASSERT );\r\n\t\t\t\t// printf(\"adding $%i for goal %s\\n\", cash, p_goal_name);\r\n\t\t\t\tAddCash( cash );\r\n\t\t\t}\r\n\t\t\tdelete pRewardParams;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::UpdateFamilyTrees()\r\n{\r\n\tint numGoals = GetNumGoals();\r\n\t\r\n\t// update all the parent lists\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tuint32 parent_id = pGoal->GetGoalId();\r\n\t\tGame::CGoalLink* p_child = pGoal->GetChildren();\r\n\t\t\r\n\t\twhile ( p_child && p_child->m_relative != 0 )\r\n\t\t{\r\n\t\t\t// printf(\"goal has a child\\n\");\r\n\t\t\tuint32 child_id = p_child->m_relative;\r\n\t\t\t// get the child\r\n\t\t\tCGoal* pChildGoal = GetGoal( child_id, false );\r\n\t\t\tDbg_MsgAssert( pChildGoal, ( \"Failed to find goal %s when binding child to parent\\n\", Script::FindChecksumName( child_id ) ) );\r\n\r\n\t\t\t// search the parent list and add if necessary\r\n\t\t\tGame::CGoalLink* p_parentNode = pChildGoal->GetParents();\r\n\t\t\tbool found = false;\r\n\t\t\twhile ( p_parentNode && p_parentNode->m_relative != 0 )\r\n\t\t\t{\r\n\t\t\t\tif ( p_parentNode->m_relative == parent_id )\r\n\t\t\t\t{\r\n\t\t\t\t\tfound = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tp_parentNode = p_parentNode->mp_next;\r\n\t\t\t}\r\n\r\n\t\t\tif ( !found )\r\n\t\t\t\tpChildGoal->AddParent( parent_id );\r\n\t\t\t\r\n\t\t\tp_child = p_child->mp_next;\r\n\t\t}\r\n\t}\r\n\r\n\t// send inherited params down the tree from root parent\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\t\r\n\t\t// SetInheritableFlags will automatically traverse down the tree,\r\n\t\t// so we only need to call it on nodes without parents - ie, the root \r\n\t\t// node of the tree.\r\n\t\tif ( pGoal->GetParents()->m_relative == 0 )\r\n\t\t{\r\n\t\t\tpGoal->SetInheritableFlags();\r\n\t\t}\r\n\t}\r\n\t\r\n\t// debugging shit.\r\n\tfor ( int i = 0; i < numGoals; i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\r\n\t\t// print out children list\r\n\t\tGame::CGoalLink* p_test = pGoal->GetChildren();\r\n\t\tbool print_newline = false;\r\n\t\tif ( p_test->m_relative != 0 )\r\n\t\t\t// printf(\"children of %s\\n\", Script::FindChecksumName( pGoal->GetGoalId() ) );\r\n\t\twhile ( p_test && p_test->m_relative != 0 )\r\n\t\t{\r\n\t\t\tprint_newline = true;\r\n\t\t\t// printf(\"\\t%s\\n\", Script::FindChecksumName( p_test->m_relative ) );\r\n\t\t\tp_test = p_test->mp_next;\r\n\t\t}\r\n\t\t\r\n\t\t// print out the parent list\r\n\t\tp_test = pGoal->GetParents();\r\n\t\tif ( p_test->m_relative != 0 )\r\n\t\t\t// printf(\"parents of %s\\n\", Script::FindChecksumName( pGoal->GetGoalId() ) );\r\n\t\twhile ( p_test && p_test->m_relative != 0 )\r\n\t\t{\r\n\t\t\tprint_newline = true;\r\n\t\t\t// printf(\"\\t%s\\n\", Script::FindChecksumName( p_test->m_relative ) );\r\n\t\t\tp_test = p_test->mp_next;\r\n\t\t}\r\n\t\t// if ( print_newline )\r\n\t\t\t// printf(\"\\n\");\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::FindCircularLinks( uint32 parent, uint32 child )\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tCGoal* pGoal = GetGoal( child, false );\r\n\tif ( pGoal )\r\n\t{\r\n\t\tCGoalLink* p_link = pGoal->GetChildren();\r\n\t\twhile ( p_link && p_link->m_relative != 0 )\r\n\t\t{\r\n\t\t\tif ( p_link->m_relative == parent )\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"Circular goal link path found from %s to %s\\n\", Script::FindChecksumName( parent ), Script::FindChecksumName( child ) ) );\r\n\t\t\tif ( p_link->m_relative == child )\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"Goal (%s) has itself as a child\\n\", Script::FindChecksumName( child ) ) );\r\n\r\n\t\t\t// recurse!\r\n\t\t\tFindCircularLinks( parent, p_link->m_relative );\r\n\t\t\tp_link = p_link->mp_next;\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::CallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( checksum )\r\n\t{\r\n\t\tcase 0x3ae9211b: // IsRootNode\r\n\t\t{\r\n\t\t\tCGoal* pGoal = GetGoal( pParams );\r\n\t\t\tif ( pGoal )\r\n\t\t\t\treturn ( pGoal->GetParents()->m_relative == 0 );\r\n\t\t\treturn false;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\r\n\t\tcase 0xd782f8de: // IsLeafNode\r\n\t\t{\r\n\t\t\tCGoal* pGoal = GetGoal( pParams );\r\n\t\t\tif ( pGoal )\r\n\t\t\t\treturn ( pGoal->GetChildren()->m_relative == 0 );\r\n\t\t\treturn false;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CGoalManager::GetGoalIdFromParams( Script::CStruct* pParams, bool assert )\r\n{\r\n\tuint32 goalId = 0;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, assert );\r\n\treturn goalId;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::CreateGoalLevelObjects( void )\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tScript::CStruct* pParams;\r\n\t\tScript::CArray *pGeomArray;\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tpParams = pGoal->GetParams();\r\n\r\n\t\t// Create the associated pieces of geometry\r\n\t\tif ( pParams->GetArray( CRCD(0xf4eb5c60,\"create_geometry\"), &pGeomArray ) )\r\n\t\t{\r\n\t\t\tuint32 j, geometry;\r\n\t\t\tfor( j = 0; j < pGeomArray->GetSize(); j++ )\r\n\t\t\t{\r\n\t\t\t\tgeometry = pGeomArray->GetChecksum( j );\r\n\t\t\t\tCFuncs::ScriptCreateFromNodeIndex( SkateScript::FindNamedNode( geometry ));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::SetDifficultyLevel( int level )\r\n{\r\n\tDbg_MsgAssert( level >= 0 && level <= vMAXDIFFICULTYLEVEL, ( \"SetDifficultyLevel called with level %i\", level ) );\r\n\tMdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tuint32 gameMode = skate_mod->GetGameMode()->GetNameChecksum();\r\n\tmp_difficulty_levels->AddInteger( gameMode, level );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGOAL_MANAGER_DIFFICULTY_LEVEL CGoalManager::GetDifficultyLevel( bool career )\r\n{\r\n\tuint32 gameMode;\r\n    if ( career)\r\n    {\r\n        gameMode = CRCD(0x4da4937b,\"career\");\r\n    }\r\n    else\r\n    {\r\n        Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n    \tgameMode = skate_mod->GetGameMode()->GetNameChecksum();\r\n    }\r\n\t\r\n    int level;\r\n\t\r\n\t// if no diff level assigned for this game mode yet, assume normal\r\n\tif ( !mp_difficulty_levels->GetInteger( gameMode, &level, Script::NO_ASSERT ) )\r\n\t\tlevel = 1;\r\n\t\r\n\tGOAL_MANAGER_DIFFICULTY_LEVEL diff_level = GOAL_MANAGER_DIFFICULTY_MEDIUM;\r\n\t\r\n    switch ( level )\r\n\t{\r\n\t\tcase 0:\r\n\t\t\tdiff_level = GOAL_MANAGER_DIFFICULTY_LOW;\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tdiff_level = GOAL_MANAGER_DIFFICULTY_MEDIUM;\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tdiff_level = GOAL_MANAGER_DIFFICULTY_HIGH;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"bad difficulty level %i\", level ) );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\treturn diff_level;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::CanRestartStage()\r\n{\r\n\tprintf(\"STUBBED\\n\");\r\n\treturn false;\r\n/*\r\n\tint activeGoal = GetActiveGoal();\r\n\tif ( activeGoal != -1 )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( activeGoal, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\r\n\t\tif ( pGoal->m_inherited_flags & GOAL_INHERITED_FLAGS_RETRY_STAGE )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::SetGoalChaptersAndStages()\r\n{\r\n\t// grab the chapter info array\r\n\tScript::CArray* pChapterGoalsArray = Script::GetArray( CRCD( 0xb892776f, \"chapter_goals\" ), Script::ASSERT );\r\n\tDbg_Assert( pChapterGoalsArray->GetType() == ESYMBOLTYPE_ARRAY );\r\n\r\n\tint chapter_goals_array_size = pChapterGoalsArray->GetSize();\r\n\tfor ( int chapter_index = 0; chapter_index < chapter_goals_array_size; chapter_index++ )\r\n\t{\r\n\t\tScript::CArray* pStageArray = pChapterGoalsArray->GetArray( chapter_index );\r\n\t\tDbg_Assert( pStageArray->GetType() == ESYMBOLTYPE_ARRAY );\r\n\t\tint stage_array_size = pStageArray->GetSize();\r\n\t\tfor ( int stage_index = 0; stage_index < stage_array_size; stage_index++ )\r\n\t\t{\r\n\t\t\tScript::CArray* pStage = pStageArray->GetArray( stage_index );\r\n\t\t\tDbg_Assert( pStage->GetType() == ESYMBOLTYPE_STRUCTURE );\r\n\t\t\tint num_goals = pStage->GetSize();\r\n\t\t\tfor ( int goal_index = 0; goal_index < num_goals; goal_index++ )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pGoalStruct = pStage->GetStructure( goal_index );\r\n\t\t\t\tuint32 goal_id;\r\n\t\t\t\tif ( pGoalStruct->GetChecksum( CRCD( 0x9982e501, \"goal_id\" ), &goal_id, Script::NO_ASSERT ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tCGoal* pGoal = GetGoal( goal_id, false );\r\n\t\t\t\t\tif ( pGoal )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpGoal->SetChapter( chapter_index );\r\n\t\t\t\t\t\tpGoal->SetStage( stage_index );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGoalManager::AdvanceStage( bool force, uint32 just_won_goal_id )\r\n{\r\n\t// printf(\"CGoalManager::AdvanceStage\\n\");\r\n\t// DeactivateAllGoals();\r\n\t\r\n\t// K: This was to fix an assert when winning a created goal in the park editor.\r\n\t// Fixed by just not doing any advance-stage logic when in created goals mode.\r\n\tMdl::Skate *p_skate_mod = Mdl::Skate::Instance();\r\n\tif ( p_skate_mod->GetGameMode()->IsTrue( CRCD( 0x353961d7, \"is_creategoals\" ) ) )\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\t// grab the chapter info array\r\n\tScript::CArray* pChapterGoalsArray = Script::GetArray( CRCD( 0xb892776f, \"chapter_goals\" ), Script::ASSERT );\r\n\tDbg_Assert( pChapterGoalsArray->GetType() == ESYMBOLTYPE_ARRAY );\r\n\t\r\n\t// grab num goals to complete array\r\n\tScript::CArray* pChapterNumGoalsToComplete = Script::GetArray( CRCD( 0x846f65f5, \"CHAPTER_NUM_GOALS_TO_COMPLETE\" ), Script::ASSERT );\r\n\tDbg_Assert( pChapterNumGoalsToComplete->GetType() == ESYMBOLTYPE_ARRAY );\r\n\t\r\n\tif ( m_currentChapter >= (int)pChapterGoalsArray->GetSize() )\r\n\t{\r\n\t\t// they beat the game\r\n\t\treturn false;\r\n\t}\r\n\t// printf(\"m_currentChapter = %i, m_currentStage = %i\\n\", m_currentChapter, m_currentStage);\r\n\tDbg_MsgAssert( m_currentChapter < (int)pChapterGoalsArray->GetSize(), ( \"the current chapter is %i, but the chapter goals array has size %i.\", m_currentChapter, pChapterGoalsArray->GetSize() ) );\r\n\tScript::CArray* pCurrentChapter = pChapterGoalsArray->GetArray( m_currentChapter );\r\n\tDbg_MsgAssert( m_currentStage < (int)pCurrentChapter->GetSize(), ( \"The current stage is set to %i, but the chapter array only has %i stage(s).\", m_currentStage, pCurrentChapter->GetSize() ) );\r\n\tScript::CArray* pCurrentStage = pCurrentChapter->GetArray( m_currentStage );\r\n\r\n\tScript::CArray* pChapterTotals = pChapterNumGoalsToComplete->GetArray( m_currentChapter );\r\n\tint stage_total_target = pChapterTotals->GetInteger( m_currentStage );\r\n\tint num_stages = pChapterTotals->GetSize();\r\n\r\n\t// resolve just won goal to parent goal, which is what's listed\r\n\t// in the chapter info array\r\n\tif ( just_won_goal_id )\r\n\t{\r\n\t\t// printf(\"just won goal %s\\n\", Script::FindChecksumName( just_won_goal_id ) );\r\n\t\tCGoal* pJustWonGoal = GetGoal( just_won_goal_id );\r\n\t\tCGoalLink* pJustWonParents = pJustWonGoal->GetParents();\r\n\t\twhile ( pJustWonParents && pJustWonParents->m_relative != 0 )\r\n\t\t{\r\n\t\t\tjust_won_goal_id = pJustWonParents->m_relative;\r\n\t\t\tpJustWonGoal = GetGoal( pJustWonParents->m_relative );\r\n\t\t\tpJustWonParents = pJustWonGoal->GetParents();\r\n\t\t}\r\n\t}\r\n\t\r\n\t// check the required total\r\n\tint num_goals = pCurrentStage->GetSize();\r\n\tint stage_total = 0;\r\n\r\n\tfor ( int goal_index = 0; goal_index < num_goals; goal_index++ )\r\n\t{\r\n\t\tScript::CStruct* pGoalStruct = pCurrentStage->GetStructure( goal_index );\r\n\t\tuint32 goal_id;\r\n\t\tif ( pGoalStruct->GetChecksum( CRCD( 0x9982e501, \"goal_id\" ), &goal_id, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tCGoal* pGoal = GetGoal( goal_id, false );\r\n\t\t\t\r\n\t\t\tif ( pGoal )\r\n\t\t\t{\r\n\t\t\t\t// resolve to parent goal id\r\n\t\t\t\tCGoalLink* pParents = pGoal->GetParents();\r\n\t\t\t\twhile ( pParents && pParents->m_relative != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tgoal_id = pParents->m_relative;\r\n\t\t\t\t\tpGoal = GetGoal( pParents->m_relative );\r\n\t\t\t\t\tpParents = pGoal->GetParents();\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif ( pGoal )\r\n\t\t\t{\r\n\t\t\t\tif ( ( goal_id == just_won_goal_id && !pGoal->HasWonGoal() ) || ( pGoal->HasWonGoal() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tstage_total++;\r\n\t\t\t\t\t// printf( \"you've won %s, stage_total = %i\\n\", Script::FindChecksumName( goal_id ), stage_total );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// look for goal in other level\r\n\t\t\t\tScript::CStruct* pTempGoalParams;\r\n\t\t\t\tif ( mp_goalFlags->GetStructure( goal_id, &pTempGoalParams, Script::NO_ASSERT ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tint hasBeaten = 0;\r\n\t\t\t\t\tpTempGoalParams->GetInteger( \"hasBeaten\", &hasBeaten, Script::ASSERT );\r\n\t\t\t\t\tif ( hasBeaten != 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// printf(\"you've beaten %s in another level\\n\", Script::FindChecksumName( p_comp->mNameChecksum ) );\r\n\t\t\t\t\t\tstage_total++;\r\n\t\t\t\t\t}\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// printf(\"stage_total = %i, stage_total_target = %i\\n\", stage_total, stage_total_target );\r\n\tif ( stage_total >= stage_total_target || force )\r\n\t{\r\n\t\t// we've beaten the stage\r\n\t\tif ( m_currentStage + 1 == num_stages )\r\n\t\t{\r\n\t\t\t// we've finished the chapter\r\n\t\t\tm_currentChapter++;\r\n\t\t\tm_currentStage = 0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_currentStage++;\r\n\t\t}\r\n\r\n\t\t// printf(\"m_currentStage = %i\\n\", m_currentStage);\r\n\t\t// reinitialize the chapter and stage\r\n\t\tUninitializeAllGoals();\r\n\t\tInitializeAllGoals();\r\n\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::RunLastStageScript()\r\n{\r\n\t// DeactivateAllGoals();\r\n\t\r\n\t// don't do anything if they beat the game\r\n\tScript::CArray* pChapterGoalsArray = Script::GetArray( CRCD( 0xb892776f, \"chapter_goals\" ), Script::ASSERT );\r\n\tDbg_Assert( pChapterGoalsArray->GetType() == ESYMBOLTYPE_ARRAY );\r\n\tif ( m_currentChapter >= (int)pChapterGoalsArray->GetSize() )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// K: This was to fix an assert when winning a created goal in the park editor.\r\n\t// Fixed by just not doing any advance-stage logic when in created goals mode.\r\n\tMdl::Skate *p_skate_mod = Mdl::Skate::Instance();\r\n\tif ( p_skate_mod->GetGameMode()->IsTrue( CRCD( 0x353961d7, \"is_creategoals\" ) ) )\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\t// grab the chapter scripts arrray\r\n\tScript::CArray* pChapterScriptsArray = Script::GetArray( CRCD(0x9f00892d,\"CHAPTER_COMPLETION_SCRIPTS\"), Script::ASSERT );\r\n\tDbg_Assert( pChapterScriptsArray->GetType() == ESYMBOLTYPE_ARRAY );\r\n\t\r\n\tint last_stage_index = m_currentStage;\r\n\tint last_chapter_index = m_currentChapter;\r\n\r\n\tif ( last_stage_index == 0 )\r\n\t{\r\n\t\tif ( last_chapter_index == 0 )\r\n\t\t{\r\n\t\t\t// we're on the first chapter and stage - don't do anything\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tlast_chapter_index--;\r\n\r\n\t\tDbg_MsgAssert( last_chapter_index < (int)pChapterScriptsArray->GetSize(), ( \"last_chapter_index %i too big\", last_chapter_index ) );\r\n\r\n\t\t// figure the stage index\r\n\t\tScript::CArray* pChapterArray = pChapterScriptsArray->GetArray( last_chapter_index );\r\n\t\tDbg_Assert( pChapterArray );\r\n\t\tlast_stage_index = pChapterArray->GetSize() - 1;\r\n\t\t// [ { script_name=NJ_StageSwitch_0_to_1_1 }, { script_name=NJ_StageSwitch_1_1_to_1_2 }, { script_name=NJ_StageSwitch_1_2_to_2_1 } ]\r\n\t}\r\n\telse\r\n\t\tlast_stage_index--;\r\n\r\n\tuint32 script_name;\r\n\tScript::CArray* pChapterParamsArray = pChapterScriptsArray->GetArray( last_chapter_index );\r\n\tDbg_Assert( pChapterParamsArray );\r\n\tScript::CStruct* pStageScriptStruct = pChapterParamsArray->GetStructure( last_stage_index );\r\n\tDbg_Assert( pStageScriptStruct );\r\n\tif ( pStageScriptStruct->GetChecksum( CRCD(0x6166f3ad,\"script_name\"), &script_name, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tScript::SpawnScript( script_name );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::SetTeamMember( uint32 pro, bool remove, bool mark_used )\r\n{\r\n\tif ( remove )\r\n\t\tmp_team->RemoveComponent( pro );\r\n\telse\r\n\t{\r\n\t\tif ( mark_used )\r\n\t\t\tmp_team->AddInteger( pro, 1 );\t\r\n\t\telse\r\n\t\t\tmp_team->AddInteger( pro, 0 );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::KillTeamMembers( )\r\n{\r\n\tmp_team->Clear();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::SetTeamName( const char* pTeamName )\r\n{\r\n\tmp_team->AddString( CRCD(0x703d7582,\"team_name\"), pTeamName );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalManager::HideAllGoalPeds( bool hide )\r\n{\r\n\tfor ( int i = 0; i < GetNumGoals(); i++ )\r\n\t{\r\n\t\tuint32 key;\r\n\t\tCGoal* pGoal = m_goalList.GetItemByIndex( i, (int*)&key );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tpGoal->mp_goalPed->Hide( hide );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGoalManager* GetGoalManager()\r\n{\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\treturn skate_mod->GetGoalManager();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_AddGoal | \r\n// @parm name | name | the goal id\r\n// @parm structure | params | goal parameters\r\nbool ScriptAddGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\t\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tScript::CStruct* pSubParams;\r\n\tpParams->GetStructure( CRCD(0x7031f10c,\"params\"), &pSubParams, Script::ASSERT );\r\n\r\n\treturn pGoalManager->AddGoal( goalId, pSubParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_RemoveGoal | \r\n// @parm name | name | the goal id\r\nbool ScriptRemoveGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\tpGoalManager->RemoveGoal( goalId );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetGoal | currently does nothing at all!\r\n// @parm name | name | the goal id\r\nbool ScriptGetGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t#if 0\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\tCGoal* pGoal = pGoalManager->GetGoal( goalId );\r\n\tif ( pGoal )\r\n\t{\r\n\t}\r\n\t#endif\r\n\t\r\n\t// TODO: return it in the script components\r\n\r\n\t// flags are not allowed as params,\r\n\t// otherwise there will be a leak\r\n\t// as things get appended, and re-appended\r\n\r\n\t// activate goal->\r\n\t// should turn off the score degrader\r\n\t// and the score accumulation script \r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_EditGoal | this will append the given structure\r\n// onto the goal's existing params structure\r\n// @parm name | name | the goal id\r\n// @parm structure | params | structure to append\r\nbool ScriptEditGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\t\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tScript::CStruct* pSubParams;\r\n\tpParams->GetStructure( CRCD(0x7031f10c,\"params\"), &pSubParams, Script::ASSERT );\r\n\r\n\treturn pGoalManager->EditGoal( goalId, pSubParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_ActivateGoal |\r\n// @parm name | name | the goal id\r\n// @flag dontAssert | pass this in if you don't want the goal manager \r\n// to assert if it can't find the specified goal (not recommended)\r\nbool ScriptActivateGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n    // put in for testing\r\n    bool dontAssert = false;\r\n    if ( pParams->ContainsFlag( CRCD(0x9ac8d54f,\"dontAssert\") ) )\r\n        dontAssert = true;\r\n\t\r\n\treturn pGoalManager->ActivateGoal( goalId, dontAssert );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_DeactivateGoal | \r\n// @parm name | name | the goal id\r\nbool ScriptDeactivateGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\t\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\treturn pGoalManager->DeactivateGoal( goalId );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_DeactivateGoal | \r\nbool ScriptClearLastGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\t\r\n\tpGoalManager->ClearLastGoal();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_WinGoal | \r\n// @parm name | name | the goal id\r\nbool ScriptWinGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tbool had_object = false;\r\n\tuint32\told_id = 0;\r\n\tObj::CObjectPtr p_obj;\r\n\tif (pScript->mpObject)\r\n\t{\r\n\t\thad_object = true;\r\n\t\tp_obj = pScript->mpObject;\r\n\t\told_id = p_obj->GetID();\r\n\t}\r\n\t#endif\r\n\t\r\n\t\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\t\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\tbool result = pGoalManager->WinGoal( goalId );\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tif (had_object)\r\n\t{\r\n\t\tDbg_MsgAssert(p_obj,(\"%s\\nObject %s was deleted indirectly \\nWhen running a script via GoalManager_WinGoal\\n You probably use KILL PREFIX = ...., Maybe you could use DIE instead\",pScript->GetScriptInfo(),Script::FindChecksumName(old_id)));\r\n\t}\r\n\t#endif\r\n\t\t\r\n\treturn result;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_LoseGoal | \r\n// @parm name | name | the goal id\r\nbool ScriptLoseGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tbool had_object = false;\r\n\tuint32\told_id = 0;\r\n\tObj::CObjectPtr p_obj;\r\n\tif (pScript->mpObject)\r\n\t{\r\n\t\thad_object = true;\r\n\t\tp_obj = pScript->mpObject;\r\n\t\told_id = p_obj->GetID();\r\n\t}\r\n\t#endif\r\n\t\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\t\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\tbool result = pGoalManager->LoseGoal( goalId );\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tif (had_object)\r\n\t{\r\n\t\tDbg_MsgAssert(p_obj,(\"%s\\nObject %s was deleted indirectly when running a script via GoalManager_LoseGoal\\n You probaly use KILL PREFIX = ...., Maybe you could use DIE instead\",pScript->GetScriptInfo(),Script::FindChecksumName(old_id)));\r\n\t}\r\n\t#endif\r\n\t\r\n\t\r\n\treturn result;\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_RemoveAllGoals | this will completely destroy\r\n// all the goals currently in existence...make sure you call GoalManager_LevelUnload\r\n// first if you want to remember anything about the state of the goals before\r\n// destroying them.\r\nbool ScriptRemoveAllGoals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tpGoalManager->RemoveAllGoals();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_DeactivateAllGoals | \r\nbool ScriptDeactivateAllGoals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tbool including_net_goals;\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tincluding_net_goals = false;\r\n\tif( pParams->ContainsComponentNamed( CRCD(0xcc365298,\"force_all\")))\r\n\t{\r\n\t\tincluding_net_goals = true;\r\n\t}\r\n\r\n\tpGoalManager->DeactivateAllGoals( including_net_goals );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UninitializeAllGoals |\r\nbool ScriptUninitializeAllGoals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tpGoalManager->UninitializeAllGoals();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_UninitializeGoal |\r\n// @parm name | name | the goal id\r\nbool ScriptUninitializeGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\tif ( pParams->ContainsFlag( CRCD(0x687de558,\"affect_tree\") ) )\r\n\t{\r\n\t\tpGoalManager->UninitializeGoalTree( goalId );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpGoalManager->UninitializeGoal( goalId );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_InitializeAllGoals | \r\nbool ScriptInitializeAllGoals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tpGoalManager->InitializeAllGoals();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_InitializeAllSelectedGoals | \r\nbool ScriptInitializeAllSelectedGoals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tpGoalManager->InitializeAllSelectedGoals();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_UpdateAllGoals | This forces the goal manager to run\r\n// an update cycle.\r\nbool ScriptUpdateAllGoals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tpGoalManager->Update();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_HasActiveGoals | returns true if there is at least one\r\n// active goal (excluding minigames and other goals that don't count towards the total)\r\nbool ScriptHasActiveGoals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tbool count_all = pParams->ContainsFlag( CRCD(0xa21884b5,\"count_all\") );\r\n\r\n\treturn ( pGoalManager->GetNumActiveGoals( count_all ) > 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GoalIsActive | returns true if the specified goal\r\n// is currently active\r\n// @parm name | name | the goal id\r\nbool ScriptGoalIsActive(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\t\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\treturn pGoalManager->GoalIsActive( goalId );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SetGoalTimer | resets the goal timer to it's inital\r\n// value.\r\n// @parm name | name | the goal id\r\nbool ScriptSetGoalTimer(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\t\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\t\r\n\treturn pGoalManager->SetGoalTimer( goalId );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_ZeroGoalTimer | zeros the goal timer; added to allow a hack to fix split screen horse end runs to be minimally invasive\r\n// @parm name | name | the goal id\r\nbool ScriptZeroGoalTimer(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\t\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\t\r\n\treturn pGoalManager->SetGoalTimer( goalId, 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_PauseAllGoals | \r\nbool ScriptPauseAllGoals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    pGoalManager->PauseAllGoals();\r\n    return true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_UnPauseAllGoals | \r\nbool ScriptUnPauseAllGoals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    pGoalManager->UnPauseAllGoals();\r\n    return true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SetGoalFlag | for setting the special goal flags\r\n// @parm name | name | the goal id\r\n// @uparm name | the name of the flag to set\r\n// @uparm 1 | value to use \r\nbool ScriptSetGoalFlag(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\t\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\t\r\n\tuint32 flagChecksum;\r\n\tpParams->GetChecksum( NONAME, &flagChecksum, Script::ASSERT );\r\n\r\n\tint flagValue;\r\n\tpParams->GetInteger( NONAME, &flagValue, Script::ASSERT );\r\n\r\n    bool success = pGoalManager->SetGoalFlag( goalId, flagChecksum, flagValue );\r\n\r\n    return success;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_HasSeenGoal | returns true if the player has\r\n// activated the specified goal at least once\r\n// @parm name | name | the goal id\r\nbool ScriptHasSeenGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    uint32 goalId;\r\n    pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n    return ( pGoalManager->HasSeenGoal( goalId ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_RestartLastGoal | this will restart the last goal\r\n// It will fail silently if there is no goal to retry\r\nbool ScriptRestartLastGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    pGoalManager->RestartLastGoal();\r\n\r\n    return true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*// @script | GoalManager_CreateGoalFlag | \r\n// @parm name | name | the goal id\r\n// @parm name | flag | the name of the flag to create\r\nbool ScriptCreateGoalFlag(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    uint32 name;\r\n    pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &name, Script::ASSERT );\r\n\r\n    uint32 flag;\r\n    pParams->GetChecksum( CRCD(0x2e0b1465,\"flag\"), &flag, Script::ASSERT ); \r\n\r\n    pGoalManager->CreateGoalFlag( name, flag );\r\n    return true;\r\n}*/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_AllFlagsSet | \r\n// @parm name | name | the goal id\r\nbool ScriptAllFlagsSet(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    uint32 name;\r\n    pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &name, Script::ASSERT );\r\n\r\n    return pGoalManager->AllFlagsSet( name );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GoalFlagSet | true if a goal flag has been set\r\n// @parm name | name | the goal id\r\n// @parm name | flag | the name of the flag to check\r\nbool ScriptGoalFlagSet(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\t\r\n\tuint32 flag;\r\n\tpParams->GetChecksum( CRCD(0x2e0b1465,\"flag\"), &flag, Script::ASSERT );\r\n\r\n\treturn pGoalManager->GoalFlagSet( goalId, flag );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_CanRetryGoal | returns true if there is a goal\r\n// to retry\r\nbool ScriptCanRetryGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    return pGoalManager->CanRetryGoal();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetGoalParams | this will append the goal's \r\n// params onto the scripts params.  The goal manager scripts use this\r\n// extensively to avoid passing large structures back and forth.\r\n// @parm name | name | the goal id\r\nbool ScriptGetGoalParams(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    uint32 goalId;\r\n    pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n    \r\n    pScript->GetParams()->AppendStructure( pGoalManager->GetGoalParams( goalId ) );\r\n\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_CanStartGoal |\r\n// @parm name | name | the goal id\r\nbool ScriptCanStartGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    // uint32 goalId;\r\n    // pParams->GetChecksum( \"name\", &goalId, Script::ASSERT );\r\n\r\n    return pGoalManager->CanStartGoal();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_NextRaceWaypoint | \r\n// @parm name | name | the goal id\r\nbool ScriptNextRaceWaypoint(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    uint32 goalId;\r\n    pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n    return pGoalManager->NextRaceWaypoint( goalId );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_NextTourSpot | \r\n// @parm name | name | the goal id\r\nbool ScriptNextTourSpot(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    uint32 goalId;\r\n    pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n    return pGoalManager->NextTourSpot( goalId );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_InitTrickObjects |\r\n// @parm name | name | the goal id\r\nbool ScriptInitTrickObjects( Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n    \r\n    uint32 goalId;\r\n    pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n    pGoalManager->InitTrickObjects( goalId );\r\n\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_CreateGoalName | \r\n// @parm string | goal_type | the goal type\r\nbool ScriptCreateGoalName( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n    char goal_prefix[128];\r\n    const char* goal_type;\r\n\r\n    pParams->GetText( CRCD(0x6d11ed74,\"goal_type\"), &goal_type, Script::ASSERT );\r\n\r\n\t// Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t// Obj::CSkaterCareer* pCareer = skate_mod->GetCareer();\r\n\r\n\t// create the level prefix\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tScript::CStruct* p_level_structure = Script::GetStructure( pGoalManager->GetLevelStructureName(), Script::ASSERT );\r\n\tconst char* p_level_prefix;\r\n\tp_level_structure->GetString( CRCD(0x651533ec,\"level\"), &p_level_prefix, Script::ASSERT );\r\n\tstrcpy( goal_prefix, p_level_prefix );\r\n\tstrcat( goal_prefix, \"_goal_\" );\r\n\r\n/*\t// figure the level\r\n\tswitch ( level )\r\n\t{\r\n\tcase 1:                                 // school\r\n\t\tstrcpy( goal_prefix, \"Sch_goal_\" );\r\n\t\tbreak;\r\n\tcase 2:                                 // san francisco\r\n\t\tstrcpy( goal_prefix, \"Sf2_goal_\" );\r\n\t\tbreak;\r\n\tcase 3:                                 // alcatraz\r\n\t\tstrcpy( goal_prefix, \"Alc_goal_\" );\r\n\t\tbreak;\r\n\tcase 4:                                 // Kona park\r\n\t\tstrcpy( goal_prefix, \"Kon_goal_\" );\r\n\t\tbreak;\r\n\tcase 5:                                 // junkyard\r\n\t\tstrcpy( goal_prefix, \"Jnk_goal_\" );\r\n\t\tbreak;\r\n\tcase 6:                                 // london\r\n\t\tstrcpy( goal_prefix, \"Lon_goal_\" );\r\n\t\tbreak;\r\n\tcase 7:                                 // zoo\r\n\t\tstrcpy( goal_prefix, \"Zoo_goal_\" );\r\n\t\tbreak;\r\n\tcase 8:\t\t\t\t\t\t\t\t\t// carnival\r\n\t\tstrcpy( goal_prefix, \"Cnv_Goal_\" );\r\n\t\tbreak;\r\n\tcase 9:\t\t\t\t\t\t\t\t\t// chicago\r\n\t\tstrcpy( goal_prefix, \"Hof_goal_\" );\r\n\t\tbreak;\r\n\tcase 10:\t\t\t\t\t\t\t\t// default test level\r\n\t\tstrcpy( goal_prefix, \"Default_goal_\" );\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tDbg_MsgAssert( false, ( \"GetGoalName couldn't figure level number\" ) );\r\n\t}\r\n*/\r\n    \r\n    // create the goal name\r\n    strcat( goal_prefix, (char*)goal_type );\r\n\r\n    // add to pParams\r\n    pScript->GetParams()->AddChecksum( CRCD(0x9982e501,\"goal_id\"), Script::GenerateCRC( goal_prefix ) );\r\n\tpScript->GetParams()->AddString( CRCD(0xbfecc45b,\"goal_name\"), goal_prefix );\r\n\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetLevelPrefix | returns the current level's prefix in level_prefix\r\nbool ScriptGetLevelPrefix( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tScript::CStruct* p_level_structure = Script::GetStructure( pGoalManager->GetLevelStructureName(), Script::ASSERT );\r\n\tconst char* p_level_prefix;\r\n\tp_level_structure->GetString( CRCD(0x651533ec,\"level\"), &p_level_prefix, Script::ASSERT );\r\n\t\r\n\tpScript->GetParams()->AddString( CRCD(0x15f818d0,\"level_prefix\"), p_level_prefix);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SetGraffitiMode |\r\n// @uparmopt 1 | turn on or off with 1 or 0\r\nbool ScriptSetGraffitiMode( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n\r\n    int mode = 1;\r\n    pParams->GetInteger( NONAME, &mode, Script::NO_ASSERT ); \r\n\r\n    return pGoalManager->SetGraffitiMode( mode );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_HasWonGoal | true if you've beat this goal\r\n// @parm name | name | the goal id\r\nbool ScriptHasWonGoal( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    uint32 goalId;\r\n    pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n    return pGoalManager->HasWonGoal( goalId );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGoalIsSelected(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    uint32 goalId;\r\n    pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n    return pGoalManager->GoalIsSelected( goalId );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptToggleGoalSelection(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    uint32 goalId;\r\n    pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n    pGoalManager->ToggleGoalSelection( goalId );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGoalsAreSelected(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n\treturn ( pGoalManager->GetNumSelectedGoals() > 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GotCounterObject | \r\n// @parm name | name | the goal id\r\nbool ScriptGotCounterObject( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n    uint32 goalId;\r\n    if ( pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::NO_ASSERT ) )\r\n    {\r\n        CGoalManager* pGoalManager = GetGoalManager();\r\n        pGoalManager->GotCounterObject( goalId );\r\n        return true;\r\n    }\r\n    else \r\n    {\r\n        // printf(\"didn't get goalId\\n\");\r\n    }\r\n    return false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_CounterGoalDone | returns true if the counter goal\r\n// is complete\r\n// @parm name | name | the goal id\r\nbool ScriptCounterGoalDone(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    uint32 goalId;\r\n    pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n\r\n    return pGoalManager->CounterGoalDone( goalId );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_AddGoalPoint | adds one goal point\r\nbool ScriptAddGoalPoint(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tpGoalManager->AddGoalPoint();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SpendGoalPoints | \r\n// @uparm 1 | number to spend\r\nbool ScriptSpendGoalPoints(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    int num;\r\n    pParams->GetInteger( NONAME, &num, Script::ASSERT );\r\n\r\n    pGoalManager->SpendGoalPoints( num );\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_HasGoalPoints | \r\n// @uparm 1 | number to check for\r\nbool ScriptHasGoalPoints(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    int num;\r\n    pParams->GetInteger( NONAME, &num, Script::ASSERT );\r\n    \r\n    return pGoalManager->HasGoalPoints( num );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptClearGoalPoints(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    pGoalManager->ClearGoalPoints();\r\n    \r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetNumberOfGoalPoints | places the number of\r\n// goal points in a variable named \"goal_points\" in the script params\r\nbool ScriptGetNumberOfGoalPoints(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    int goal_points = 0;\r\n\tif ( pParams->ContainsFlag( CRCD(0x3dd01ea1,\"total\") ) )\r\n\t\tgoal_points = pGoalManager->GetTotalNumberOfGoalPointsEarned();\r\n\telse\r\n\t\tgoal_points = pGoalManager->GetNumberOfGoalPoints();\r\n\r\n    pScript->GetParams()->AddInteger( CRCD(0x42c20492,\"goal_points\"), goal_points );\r\n    return true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_AddCash | gives the player more cash\r\n// @uparm 1 | amount of cash to give\r\nbool ScriptAddCash(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    int amount;\r\n    pParams->GetInteger( NONAME, &amount, Script::ASSERT );\r\n\r\n    pGoalManager->AddCash( amount );\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SpendCash | spends some of the player's cash\r\n// @uparm 1 | amount to spend\r\nbool ScriptSpendCash(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    int amount;\r\n    pParams->GetInteger( NONAME, &amount, Script::ASSERT );\r\n\r\n    return pGoalManager->SpendCash( amount );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetCash | places the current player's cash amount\r\n// in a parameter called \"cash\" in the script params\r\nbool ScriptGetCash(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n\tbool get_total = pParams->ContainsFlag( CRCD(0x3dd01ea1,\"total\") );\r\n    \r\n    pScript->GetParams()->AddInteger( CRCD(0xf9461a46,\"cash\"), pGoalManager->GetCash( get_total ) );\r\n    return true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_HasWonGoalWithProset | \r\n// @uparm \"string\" | the proset_prefix you wanna check\r\nbool ScriptHasBeatenGoalWithProset(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    const char* p_proset_prefix;\r\n    pParams->GetString( NONAME, &p_proset_prefix, Script::ASSERT );\r\n\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    return pGoalManager->HasBeatenGoalWithProset( p_proset_prefix );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetProsetNotPrefix | \r\n// @uparm \"string\" | the proset_prefix you wanna check\r\nbool ScriptGetProsetNotPrefix(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    const char* p_proset_prefix;\r\n    pParams->GetString( NONAME, &p_proset_prefix, Script::ASSERT );\r\n\r\n    char temp_string[128];\r\n    strcpy( temp_string, \"\");\r\n\r\n    int size = 0;    \r\n    while ( p_proset_prefix[size + 1] )\r\n    {\r\n        temp_string[size] = p_proset_prefix[size];\r\n        size++;\r\n    }\r\n\ttemp_string[size] = '\\0';\r\n\r\n    // now we're at the last char\r\n    strcat( temp_string, \"NOT_\" );\r\n\r\n    pScript->GetParams()->AddString( CRCD(0xc60ce720,\"proset_not_prefix\"), temp_string );\r\n    return true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_LevelLoad | called when the player enters a level.\r\n// Loads data about goals seen, completed, etc. in a previous game\r\nbool ScriptLevelLoad(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    pGoalManager->LevelLoad();\r\n    return true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_LevelUnload | called when the player leaves a level.\r\n// Prompts the goal manager to save state data about all goals\r\nbool ScriptLevelUnload(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    pGoalManager->LevelUnload();\r\n    return true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_NumGoalsBeatenInLevel | This will return the number\r\n// of beaten goals in the scripts params as num_beaten\r\n// @uparm 1 | level number\r\n// @flag count_pro_specific_challenges | false by default\r\nbool ScriptNumGoalsBeatenInLevel(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    int levelNum;\r\n    pParams->GetInteger( NONAME, &levelNum, Script::ASSERT );\r\n\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    int numbeat = pGoalManager->NumGoalsBeatenInLevel( levelNum, pParams->ContainsFlag( CRCD(0x8690a9cf,\"count_pro_specific_challenges\") ) );\r\n    pScript->GetParams()->AddInteger( CRCD(0x8110dcdf,\"num_beaten\"), numbeat );\r\n    return true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_UnlockAllGoals | Unlocks all locked goals\r\nbool ScriptUnlockAllGoals(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    CGoalManager* pGoalManager = GetGoalManager();\r\n    Dbg_Assert( pGoalManager );\r\n\r\n    pGoalManager->UnlockAllGoals();\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_CheckMinigameRecord | checks the current minigame\r\n// value against the one stored in minigame_record in the goal params\r\n// @parm name | name | the goal id\r\n// @uparm 100 | the value you want to check against the current record\r\nbool ScriptCheckMinigameRecord(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tint value;\r\n\tpParams->GetInteger( NONAME, &value, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->CheckMinigameRecord( goalId, value );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_DeactivateCurrentGoal | Deactivates the currently\r\n// active goal (this function cannot always be trusted).\r\nbool ScriptDeactivateCurrentGoal(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->DeactivateCurrentGoal();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SetStartTime | Records the start time of a combo\r\n// (only used for the timedcombo miingame right now).\r\n// @parm name | name | the goal id\r\nbool ScriptSetStartTime(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\t\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->SetStartTime( goalId );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_UpdateComboTimer | Used for the timedcombo minigame\r\n// @parm name | name | the goal id\r\nbool ScriptUpdateComboTimer(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->UpdateComboTimer( goalId );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SetStartHeight | used for the height minigame\r\n// @parm name | name | the goal id\r\nbool ScriptSetStartHeight(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->SetStartHeight( goalId );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_CheckHeightRecord | used for height minigame\r\n// @parm name | name | the goal id\r\nbool ScriptCheckHeightRecord(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->CheckHeightRecord( goalId );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_CheckDistanceRecord | used for height minigame\r\n// @parm name | name | the goal id\r\nbool ScriptCheckDistanceRecord(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->CheckDistanceRecord( goalId );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_PlayGoalStartStream | plays the intro vo for the goal\r\n// @parm name | name | the goal id\r\nbool ScriptPlayGoalStartStream(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->PlayGoalStartStream( pParams );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_PlayGoalWaitStream | plays the wait vo for the goal\r\n// @parm name | name | the goal id\r\nbool ScriptPlayGoalWaitStream(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->PlayGoalWaitStream( goalId );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_PlayGoalWinStream | plays the success vo for the goal\r\n// @parm name | name | the goal ID\r\nbool ScriptPlayGoalWinStream(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->PlayGoalWinStream( pParams );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_StopCurrentStream | stops any vo being played by\r\n// the goal trigger\r\n// @parm name | name | the goal ID\r\nbool ScriptStopCurrentStream(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->StopCurrentStream( goalId );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_TurnPro | instantly turns you pro, unlocks all \r\n// the pro goals, and runs the \"you just turned pro\" script\r\nbool ScriptTurnPro(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->TurnPro();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_DeactivateAllMinigames | \r\nbool ScriptDeactivateAllMinigames(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->DeactivateAllMinigames();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_InitializeAllMinigames | \r\nbool ScriptInitializeAllMinigames(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->InitializeAllMinigames();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_PauseGoal | pauses an individual goal\r\n// @parm name | name | the goal id\r\nbool ScriptPauseGoal( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->PauseGoal( goalId );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_UnPauseGoal | unpauses an individual goal\r\n// @parm name | name | the goal id\r\nbool ScriptUnPauseGoal( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->UnPauseGoal( goalId );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_PauseCompetition | Pauses a competition\r\n// @parm name | name | the goal id\r\nbool ScriptPauseCompetition( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->PauseCompetition( goalId );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_UnPauseCompetition | The competition uses a secondary\r\n// pause mechanism...this is for unpausing the comp between rounds\r\n// @parm name | name | the goal id\r\nbool ScriptUnPauseCompetition( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->UnPauseCompetition( goalId );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_UnBeatAllGoals | marks all goals as unbeaten and \r\n// takes away any goal points you earned for beating them.  You have to \r\n// reload the level to re-initialize the goals, however\r\nbool ScriptUnBeatAllGoals( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_MsgAssert( pGoalManager, (\"couldn't get goal manager\") );\r\n\r\n\tpGoalManager->UnBeatAllGoals();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_AddViewGoalsList | adds the list of goals to the \r\n// view goals menu.  This is called from one place within the create_view_Goals_menu\r\n// script.\r\nbool ScriptAddViewGoalsList( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_MsgAssert( pGoalManager, (\"couldn't get goal manager\") );\r\n\r\n\tpGoalManager->AddViewGoalsList();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_AddGoalChoices | Adds the list of available goals to the \"Choose Goals\" menu\r\nbool ScriptAddGoalChoices( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tbool selected_only;\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_MsgAssert( pGoalManager, (\"couldn't get goal manager\") );\r\n\r\n\tselected_only = pParams->ContainsFlag( CRCD(0x5685c1b7,\"selected_only\") );\r\n\r\n\tpGoalManager->AddGoalChoices( selected_only );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GoalIsLocked | true if the goal is locked\r\n// @parm name | name | the goal id\r\nbool ScriptGoalIsLocked( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->GoalIsLocked( goalId );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_IsInCompetition | returns true if the player is\r\n// in a competition\r\nbool ScriptIsInCompetition( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tCGoal* pGoal = pGoalManager->IsInCompetition();\r\n\tif ( pGoal )\r\n\t{\r\n\t\tpScript->GetParams()->AddChecksum( CRCD(0x9982e501,\"goal_id\"), pGoal->GetGoalId() );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetGoalAnimations | Gets the appropriate animations\r\n// array from script.  It wil first search for an array specific to this goal and \r\n// type, then for an array specific to this pro, then for the generic array\r\n// @parm name | name | the goal id\r\n// @parmopt string | type | | the goal state - wait, start, midgoal, or success\r\nbool ScriptGetGoalAnimations( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tconst char* type = NULL;\r\n\tpParams->GetString( CRCD(0x7321a8d6,\"type\"), &type, Script::NO_ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->GetGoalAnimations( goalId, type, pScript );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_PlayGoalStream | plays the appropriate stream for this\r\n// goal/pro.  The appropriate anim arrays must be setup in script for this to work\r\n// @parm name | name | the goal id\r\nbool ScriptPlayGoalStream( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->PlayGoalStream( pParams );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_EndRunCalled | returns true if the goal manager\r\n// called endrun for this goal\r\n// @parm name | name | the goal id\r\nbool ScriptEndRunCalled(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->EndRunCalled( goalId );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_ClearEndRun | This will clear the skater's endrun exception\r\n// as well as any others.  It's used by the combo goal, which needs to clear\r\n// the exception if you bail.  In general, this function should not be used -\r\n// clearing the endrun exception is not usually a good idea.\r\n// @parm name | name | the goal id\r\nbool ScriptClearEndRun(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\t\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tpGoalManager->GetGoal( goalId )->ClearEndRun( pScript );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_FinishedEndOfRun | returns true if EndOfRun has\r\n// finished\r\n// @parm name | name | the goal id\r\nbool ScriptFinishedEndOfRun(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->GetGoal( goalId )->FinishedEndOfRun();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_StartedEndOfRun | this returns true if EndOfRun \r\n// has started\r\n// @parm name | name | the goal id\r\nbool ScriptStartedEndOfRun(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->GetGoal( goalId )->StartedEndOfRun();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_EndBetAttempt | call this to end a bet attempt. \r\n// If the goal id does not match the current bet, the call will be ignored.\r\n// @parm name | name | the goal id\r\nbool ScriptEndBetAttempt(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 id = pGoalManager->GetBettingGuyId();\r\n\tif ( id )\r\n\t{\r\n\t\tCBettingGuy* pGoal = (CBettingGuy*)pGoalManager->GetGoal( id );\r\n\t\tDbg_Assert( pGoal );\r\n\t\treturn pGoal->EndBetAttempt( goalId );\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_StartBetAttempt | called by any minigame that is\r\n// also used as a betting game\r\n// @parm name | name | the goal id\r\nbool ScriptStartBetAttempt(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 id = pGoalManager->GetBettingGuyId();\r\n\tif ( id )\r\n\t{\r\n\t\tCBettingGuy* pGoal = (CBettingGuy*)pGoalManager->GetGoal( id );\r\n\t\tDbg_Assert( pGoal );\r\n\t\treturn pGoal->StartBetAttempt( goalId );\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_WinBet | calling this will win the bet.\r\n// The goal id is used to verify that the specified bet is in fact\r\n// the active bet.  If it's not, the goal manager will ignore the call\r\n// @parm name | name | the goal id\r\nbool ScriptWinBet(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 id = pGoalManager->GetBettingGuyId();\r\n\tif ( id )\r\n\t{\r\n\t\tCBettingGuy* pGoal = (CBettingGuy*)pGoalManager->GetGoal( id );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tpGoal->Win( goalId );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_BetOffered | called once the betting guy makes \r\n// an offer\r\nbool ScriptBetOffered( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 id = pGoalManager->GetBettingGuyId();\r\n\tif ( id )\r\n\t{\t\r\n\t\tCBettingGuy* pGoal = (CBettingGuy*)pGoalManager->GetGoal( id );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tpGoal->OfferMade();\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_BetRefused | called when the player declines a betting\r\n// guy bet\r\nbool ScriptBetRefused( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 id = pGoalManager->GetBettingGuyId();\r\n\tif ( id )\r\n\t{\t\r\n\t\tCBettingGuy* pGoal = (CBettingGuy*)pGoalManager->GetGoal( id );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tpGoal->OfferRefused();\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_MoveBettingGuyNow | this will force the betting guy to\r\n// immediately move to a new, random betting game.  This is useful when the betting guy\r\n// is created and you don't care where the skater is (otherwise the betting guy will avoid\r\n// moving where the skater could see him).\r\nbool ScriptMoveBettingGuyNow( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 id = pGoalManager->GetBettingGuyId();\r\n\tif ( id )\r\n\t{\r\n\t\tCBettingGuy* pGoal = (CBettingGuy*)pGoalManager->GetGoal( id );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tpGoal->MoveToNewNode( true );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_BetAccepted | called when the player accepts a bet\r\nbool ScriptBetAccepted(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 id = pGoalManager->GetBettingGuyId();\r\n\tif ( id )\r\n\t{\r\n\t\tCBettingGuy* pGoal = (CBettingGuy*)pGoalManager->GetGoal( id );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tpGoal->OfferAccepted();\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_BetIsActive | returns true if the bet is currently\r\n// active - ie, the bet guy has offered the bet and the player accepted\r\n// @parm name | name | the goal id\r\nbool ScriptBetIsActive(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tuint32 betting_guy_id = pGoalManager->GetBettingGuyId();\r\n\tif ( betting_guy_id )\r\n\t{\r\n\t\tCBettingGuy* pBetGuy = (CBettingGuy*)pGoalManager->GetGoal( betting_guy_id );\r\n\t\tDbg_Assert( pBetGuy );\r\n\t\treturn pBetGuy->BetIsActive( goalId );\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_AddMinigameTime | adds the specified amount of time\r\n// to the minigame.  \r\n// @parm name | name | the minigame id (usually goal_id)\r\n// @uparm 1 | the amount of time to add in seconds\r\nbool ScriptAddMinigameTime(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\t\r\n\t\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tint amount;\r\n\tpParams->GetInteger( NONAME, &amount, Script::ASSERT );\r\n\r\n\tCGoal* pGoal = pGoalManager->GetGoal( goalId );\r\n\tDbg_MsgAssert( pGoal->IsMinigame(), (\"This is not a minigame\") );\r\n\tCMinigame* pMinigame = (CMinigame*)pGoal;\r\n\treturn pMinigame->AddTime( amount );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_AddTempSpecialTrick | This is used only by the \r\n// special goal.\r\n// @parm name | name | the goal id\r\nbool ScriptAddTempSpecialTrick(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tCGoal* pGoal = pGoalManager->GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\treturn pGoal->AddTempSpecialTrick();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_RemoveTempSpecialTrick | this is used only by the \r\n// special goal.\r\n// @parm name | name | the goal id\r\nbool ScriptRemoveTempSpecialTrick(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tCGoal* pGoal = pGoalManager->GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->RemoveTempSpecialTrick();\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetTrickFromKeyCombo | this will find the trick\r\n// currently bound to the given key combo.  the trick name (checksum value) will\r\n// be placed in the script params as trick_checksum.  The trick text\r\n// will be placed in the params as trick_string.  If no trick is bound to the \r\n// key combo, the function will return false\r\n// @parm name | key_combo | the key combo to search for\r\nbool ScriptGetTrickFromKeyCombo(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 key_combo;\r\n\tpParams->GetChecksum( CRCD(0xacfdb27a,\"key_combo\"), &key_combo, Script::ASSERT );\r\n\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile();\r\n\tScript::CStruct* pTricks = pSkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") );\r\n\t\r\n\tuint32 trick_checksum;\r\n    int cat_num;\r\n\tif ( !pParams->ContainsFlag( CRCD(0xb394c01c,\"special\") ) )\r\n    {\r\n        if( pTricks->GetInteger( key_combo, &cat_num, Script::NO_ASSERT ) )\r\n        {\r\n            // printf(\"it's a created trick! %i\\n\", cat_num );\r\n    \t\tpScript->GetParams()->AddInteger( CRCD(0xa75b8581,\"cat_num\"), cat_num );\r\n            return true;\r\n        }\r\n        \r\n        if( pTricks->GetChecksum( key_combo, &trick_checksum, Script::NO_ASSERT ) )\r\n    \t{\r\n    \t\tif ( trick_checksum == ( CRCD(0xf60c9090,\"Unassigned\") ) )\r\n               \treturn false;\r\n            \r\n    \t\t// return the name and checksum\r\n    \t\tconst char* p_trick_string;\r\n    \t\tScript::CStruct* p_trick = Script::GetStructure( trick_checksum, Script::ASSERT );\r\n    \t\tScript::CStruct* p_trick_params;\r\n    \t\tp_trick->GetStructure( CRCD(0x7031f10c,\"Params\"), &p_trick_params, Script::ASSERT );\r\n    \t\tp_trick_params->GetLocalString( CRCD(0xa1dc81f9,\"Name\"), &p_trick_string, Script::ASSERT );\r\n    \r\n    \t\tpScript->GetParams()->AddString( CRCD(0x3a54cc4b,\"trick_string\"), p_trick_string );\r\n    \t\tpScript->GetParams()->AddChecksum( CRCD(0x4443a4da,\"trick_checksum\"), trick_checksum );\r\n    \r\n    \t\t// look for any double tap tricks\r\n    \t\tuint32 extra_trick = 0;\r\n    \t\tif ( !p_trick_params->GetChecksum( CRCD(0x6e855102,\"ExtraTricks\"), &extra_trick, Script::NO_ASSERT ) )\r\n    \t\t{\r\n    \t\t\t// look for an array of extra tricks and grab the first one\r\n    \t\t\tScript::CArray* p_extra_tricks;\r\n    \t\t\tif ( p_trick_params->GetArray( CRCD(0x6e855102,\"ExtraTricks\"), &p_extra_tricks, Script::NO_ASSERT ) )\r\n    \t\t\t\textra_trick = p_extra_tricks->GetChecksum( 0 );\r\n    \t\t}\r\n    \r\n    \t\t// add any extra trick info\r\n    \t\tif ( extra_trick )\r\n    \t\t{\r\n    \t\t\t// grab this extra trick\r\n    \t\t\tScript::CArray* p_temp = Script::GetArray( extra_trick, Script::ASSERT );\r\n    \t\t\tScript::CStruct* p_extra_trick = p_temp->GetStructure( 0 );\r\n    \t\t\tDbg_Assert( p_extra_trick );\r\n    \t\t\tScript::CStruct* p_extra_trick_params;\r\n    \t\t\tp_extra_trick->GetStructure( CRCD(0x7031f10c,\"Params\"), &p_extra_trick_params, Script::ASSERT );\r\n    \t\t\tconst char* p_extra_trick_string;\r\n    \t\t\tp_extra_trick_params->GetString( CRCD(0xa1dc81f9,\"Name\"), &p_extra_trick_string, Script::ASSERT );\r\n    \t\t\tpScript->GetParams()->AddString( CRCD(0x3daaf58b,\"extra_trick_string\"), p_extra_trick_string );\r\n    \t\t\tpScript->GetParams()->AddChecksum( CRCD(0xd0bcfc62,\"extra_trick_checksum\"), extra_trick );\r\n    \t\t}\r\n    \t\treturn true;\r\n    \t}\r\n    }\r\n\telse if ( pParams->ContainsFlag( CRCD(0xb394c01c,\"special\") ) )\r\n\t{\t\t\r\n\t\t// check the special tricks\r\n\t\tint numTricks = pSkaterProfile->GetNumSpecialTrickSlots();\r\n\r\n\t\t// search through current special tricks\r\n\t\tfor ( int i = 0; i < numTricks; i++ )\r\n\t\t{\r\n            Obj::SSpecialTrickInfo trick_info = pSkaterProfile->GetSpecialTrickInfo( i );\r\n\t\t\r\n\t\t\tif ( trick_info.m_TrickSlot == key_combo )\r\n\t\t\t{\r\n\t\t\t\tif ( trick_info.m_TrickName == ( CRCD(0xf60c9090,\"Unassigned\") ) )\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t\r\n\t\t\t\t// printf(\"the special trick is already bound!\\n\");\r\n\t\t\t\tif ( Script::CStruct* p_trick = Script::GetStructure( trick_info.m_TrickName ) )\r\n                {\r\n                    const char* p_trick_string;\r\n                    Script::CStruct* p_trick_params;\r\n    \t\t\t\tp_trick->GetStructure( CRCD(0x7031f10c,\"Params\"), &p_trick_params, Script::ASSERT );\r\n    \t\t\t\tp_trick_params->GetLocalString( CRCD(0xa1dc81f9,\"Name\"), &p_trick_string, Script::ASSERT );\r\n                    pScript->GetParams()->AddString( CRCD(0x3a54cc4b,\"trick_string\"), p_trick_string );\r\n                }\r\n                \r\n                if ( trick_info.m_isCat )\r\n                {\r\n                    pScript->GetParams()->AddInteger( CRCD(0x4443a4da,\"trick_checksum\"), trick_info.m_TrickName );\r\n                }\r\n                else\r\n                {\r\n                    pScript->GetParams()->AddChecksum( CRCD(0x4443a4da,\"trick_checksum\"), trick_info.m_TrickName );\r\n                }\r\n                pScript->GetParams()->AddInteger( CRCD(0xdb92effa,\"current_index\"), i );\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_UnlockGoal | unlocks the specified goal\r\n// @parm name | name | the goal id\r\nbool ScriptUnlockGoal(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tCGoal* pGoal = pGoalManager->GetGoal( goalId );\r\n\r\n\tpGoal->UnlockGoal();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_QuickStartGoal | starts a goal without going\r\n// through the intro movie, etc.\r\n// @parm name | name | the goal id\r\n// @flag dontAssert | used by autotester\r\nbool ScriptQuickStartGoal(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tbool dontAssert = false;\r\n\tif ( pParams->ContainsFlag( CRCD(0x9ac8d54f,\"dontAssert\") ) )\r\n\t\tdontAssert = true;\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->QuickStartGoal( goalId, dontAssert );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_InitializeGoal | initialize the specified goal\r\n// @parm name | name | the goal id\r\nbool ScriptInitializeGoal( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tCGoal* pGoal = pGoalManager->GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->Init();\r\n\treturn true;\r\n}\r\n// TODO:  it would be nice to have the cfuncs call the goalmanager's\r\n// member functions directly...\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_AddTime | adds the specified amount of time to the goal\r\n// @parm name | name | the goal id\r\n// @uparm 10 | time to add, in seconds\r\nbool ScriptAddTime( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tint time;\r\n\tpParams->GetInteger( NONAME, &time, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tCGoal* pGoal = pGoalManager->GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->AddTime( time );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_ReplaceTrickText | replaces the trick name and \r\n// key combo with the appropriate text.  The key combo should be represented \r\n// in the string by \\k, and the text by \\t\r\n// @parmopt name | name | | the goal id\r\n// @flag all | in place of a goal id - update all goals\r\nbool ScriptReplaceTrickText( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 goalId;\r\n\tif ( pParams->ContainsFlag( CRCD(0xc4e78e22,\"all\") ) )\r\n\t{\r\n\t\tpGoalManager->ReplaceAllTrickText();\r\n\t\treturn true;\r\n\t}\r\n\telse if ( pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tconst char* p_old_string;\r\n\t\tif ( pParams->GetString( CRCD(0xc4745838,\"text\"), &p_old_string, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tchar new_string[NEW_STRING_LENGTH];\r\n\t\t\tif ( pGoalManager->ReplaceTrickText( goalId, p_old_string, new_string, NEW_STRING_LENGTH ) )\r\n\t\t\t{\r\n                pScript->GetParams()->RemoveComponent( CRCD(0x3eafa520,\"TrickText\") );\r\n\t\t\t\tpScript->GetParams()->AddString( CRCD(0x3eafa520,\"TrickText\"), new_string );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse \r\n\t\t\treturn pGoalManager->ReplaceTrickText( goalId );\r\n\t}\r\n\telse\r\n\t\tDbg_MsgAssert( 0, ( \"GoalManager_ReplaceTrickText requires a goal id or the 'all' flag.\" ) );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\n// @script | GoalManager_UnlockProSpecificChallenges | called once, when you \r\n// first get enough goals to unlock the pro challenge\r\nbool ScriptUnlockProSpecificChallenges( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->UnlockProSpecificChallenges();\r\n\treturn true;\r\n}\r\n*/\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\n// @script | GoalManager_ProSpecificChallengesUnlocked | true if the pro challenges \r\n// have been unlocked\r\nbool ScriptProSpecificChallengesUnlocked( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->ProSpecificChallengesUnlocked();\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetNumberCollected | returns the number of objects\r\n// collected so far in this goal.  If the goal is not a counter goal, it just returns\r\n// the number of flags set.  The value will be stored in the number_collected var.\r\n// @parm name | name | the goal id\r\nbool ScriptGetNumberCollected( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tint number_collected = pGoalManager->GetNumberCollected( goalId );\r\n\tpScript->GetParams()->AddInteger( CRCD(0x129daa10,\"number_collected\"), number_collected );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetNumberOfFlags | returns the number of flags in this\r\n// goal.  If there are no flags, it returns false\r\n// @parm name | name | the goal id\r\nbool ScriptGetNumberOfFlags( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\t\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tint number_of_flags = pGoalManager->GetNumberOfFlags( goalId );\r\n\tif ( number_of_flags != -1 )\r\n\t{\r\n\t\tpScript->GetParams()->AddInteger( CRCD(0xcb9d1224,\"number_of_flags\"), number_of_flags );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_IsPro | returns true if you're pro\r\nbool ScriptIsPro( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->IsPro();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_ResetGoalFlags | resets all of the goals flags\r\nbool ScriptResetGoalFlags( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->ResetGoalFlags( goalId );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_ColorTrickObjects | colors all trick objects \r\n// associated with this goal\r\n// @parm name | name | the goal id\r\n// @flag clear | pass this in if you want to clear the color\r\n// @parmopt int | skater | 0 | the skater num\r\nbool ScriptColorTrickObjects( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tbool clear = pParams->ContainsFlag( CRCD(0x1a4e0ef9,\"clear\") );\r\n\r\n\tint skaterId = 0;\r\n\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skaterId, Script::NO_ASSERT );\r\n\r\n\tint seqIndex = skaterId + 1;\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->ColorTrickObjects( goalId, seqIndex, clear );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetNumberOfTimesGoalStarted | gets the total number\r\n// of times the player has lost this goal.  The number will be stored in\r\n// the calling scripts params as times_lost\r\n// @parm name | name | the goal id\r\nbool ScriptGetNumberOfTimesGoalStarted( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tint numTimesLost = pGoalManager->GetNumberOfTimesGoalStarted( goalId );\r\n\tpScript->GetParams()->AddInteger( CRCD(0xff61ba23,\"times_started\"), numTimesLost );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GoalExists | returns true if the goal exists\r\n// @parm name | name | the goal id\r\nbool ScriptGoalExists( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->GoalExists( goalId );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetGoalAttemptInfo | grabs the number of times each\r\n// goal has been lost, and stores all the data in your times_lost_info\r\nbool ScriptGetGoalAttemptInfo( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tpScript->GetParams()->AddStructurePointer( CRCD(0xd23ad129,\"goal_attempt_info\"), pGoalManager->GetGoalAttemptInfo() );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SetCanStartGoal | tell the goal manager that it can\r\n// or cannot start any new goals\r\n// @parmopt int | | 1 | 0 to block new goals\r\nbool ScriptSetCanStartGoal( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tint value = 1;\r\n\tpParams->GetInteger( NONAME, &value, Script::NO_ASSERT );\r\n\tpGoalManager->SetCanStartGoal( value );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetLastGoalId | returns the last unbeaten goal\r\n// as a checksum param goal_id.  If the player hasn't played a goal yet\r\n// or beat the last goal, the function will return false.\r\nbool ScriptGetLastGoalId( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 goalId = pGoalManager->GetLastGoalId();\r\n\tif ( goalId )\r\n\t{\r\n\t\tpScript->GetParams()->AddChecksum( CRCD(0x9982e501,\"goal_id\"), goalId );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_ClearTetrisTricks | clears the entire stack of\r\n// tetris tricks.\r\nbool ScriptClearTetrisTricks( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoal* pGoal = pGoalManager->GetGoal( goalId );\r\n\tDbg_MsgAssert( pGoal->IsTetrisGoal(), ( \"ClearTetrisTricks called on a non-tetris goal\" ) );\r\n\r\n\tCSkatetrisGoal* pSkatetrisGoal = (CSkatetrisGoal*)pGoal;\r\n\tpSkatetrisGoal->ClearAllTricks();\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nbool ScriptMarkProSpecificChallengeBeaten( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 skater_name;\r\n\tpParams->GetChecksum( CRCD(0x5b8ab877,\"skater\"), &skater_name, Script::ASSERT );\r\n\r\n\tint beaten = 1;\r\n\tpParams->GetInteger( NONAME, &beaten, Script::NO_ASSERT );\r\n\t\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->MarkProSpecificChallengeBeaten( skater_name, beaten );\r\n\treturn true;\r\n}\r\n*/\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nbool ScriptSkaterHasBeatenProSpecificChallenge( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 skater_name;\r\n\tpParams->GetChecksum( CRCD(0x5b8ab877,\"skater\"), &skater_name, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->SkaterHasBeatenProSpecificChallenge( skater_name );\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptAnnounceGoalStarted( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tNet::Client* client;\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoal* pGoal = pGoalManager->GetGoal( goalId );\r\n\tDbg_Assert( pGoal != NULL );\r\n\r\n\tif( pGoal->IsNetGoal())\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\tif( pGoal->GetParents()->m_relative != 0 )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tclient = gamenet_man->GetClient( 0 );\r\n\tDbg_Assert( client );\r\n\tGameNet::MsgStartedGoal msg;\r\n\tGameNet::PlayerInfo* local_player;\r\n\tNet::MsgDesc msg_desc;\r\n\r\n\tlocal_player = gamenet_man->GetLocalPlayer();\r\n\tDbg_Assert( local_player );\r\n\t\r\n\tmsg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\tmsg.m_GoalId = pGoal->GetGoalId();\r\n\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof( GameNet::MsgStartedGoal );\r\n\tmsg_desc.m_Id = GameNet::MSG_ID_STARTED_GOAL;\r\n\tclient->EnqueueMessageToServer( &msg_desc );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SetEndRunType | one of the flags is required\r\n// @parm name | name | the goal id\r\n// @flag Goal_EndOfRun | use GoalEndOfRun\r\n// @flag EndOfRun | use EndOfRun\r\n// @flag none | don't use end of run\r\nbool ScriptSetEndRunType( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tGame::EndRunType newEndRunType = Game::vENDOFRUN;\r\n\tif ( pParams->ContainsFlag( CRCD(0x54585419,\"Goal_EndOfRun\") ) )\r\n\t\tnewEndRunType = Game::vGOALENDOFRUN;\r\n\telse if ( pParams->ContainsFlag( CRCD(0xe022c12c,\"EndOfRun\") ) )\r\n\t\tnewEndRunType = Game::vENDOFRUN;\r\n\telse if ( pParams->ContainsFlag( CRCD(0x806fff30,\"none\") ) )\r\n\t\tnewEndRunType = Game::vNONE;\r\n\telse\r\n\t\tDbg_MsgAssert( 0, ( \"GoalManager_SetEndRunType called without type\" ) );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->SetEndRunType( goalId, newEndRunType );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SetShouldDeactivateOnExpire | \r\n// @uparm 1 | 0 for no, anything else for yes\r\nbool ScriptSetShouldDeactivateOnExpire( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tint should_deactivate;\r\n\tpParams->GetInteger( NONAME, &should_deactivate, Script::ASSERT );\r\n\t\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->SetShouldDeactivateOnExpire( goalId, should_deactivate != 0 );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetActiveGoalId | returns the active goal's goal_id.\r\n// Returns false if there are no active goals\r\nbool ScriptGetActiveGoalId( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId = 0;\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tif ( pGoalManager )\r\n\t{\r\n\t\tint activeGoal = pGoalManager->GetActiveGoal( true );\r\n\t\tif ( activeGoal == -1 )\r\n\t\t\treturn false;\r\n\r\n\t\tCGoal* pGoal = pGoalManager->GetGoalByIndex( activeGoal );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tif ( pGoal )\r\n\t\t{\r\n\t\t\tgoalId = pGoal->GetGoalId();\r\n\t\t\tpScript->GetParams()->AddChecksum( \"goal_id\", goalId );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_AwardMinigameCash | \r\n// @parm name | name | the goal id\r\n// @uparm 25 | amount of cash to award\r\nbool ScriptAwardMinigameCash( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tint amount;\r\n\tpParams->GetInteger( NONAME, &amount, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tif ( pGoalManager )\r\n\t{\r\n\t\treturn pGoalManager->AwardMinigameCash( goalId, amount );\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_ResetCareer | \r\nbool ScriptResetCareer( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->ResetCareer();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptAwardAllGoalCash( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->AwardAllGoalCash();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_UpdateFamilyTrees |\r\nbool ScriptUpdateFamilyTrees( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpGoalManager->UpdateFamilyTrees();\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_IsLeafNode | returns true if the passed goal\r\n// is a leaf node in the goal tree\r\n// @parm name | name | the goal id\r\nbool ScriptIsLeafNode( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->CallMemberFunction( ( CRCD(0xd782f8de,\"IsLeafNode\") ), pParams, pScript );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_IsRootNode | returns true if the passed\r\n// goal is the root node of a family tree.  This is true if the goal\r\n// is the only goal in a tree.\r\n// @parm name | name | the goal id\r\nbool ScriptIsRootNode( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->CallMemberFunction( ( CRCD(0x3ae9211b,\"IsRootNode\") ), pParams, pScript );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptSuspendGoalPedLogic( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tint suspend = 1;\r\n\tpParams->GetInteger( CRCD(0xce0ca665,\"suspend\"), &suspend, Script::NO_ASSERT );\r\n\r\n\tpGoalManager->GetGoal( pParams )->mp_goalPed->SuspendGoalLogic( suspend != 0 );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptRememberLevelStructureName( Script::CStruct *pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 level;\r\n\tpParams->GetChecksum( CRCD(0x63b1214e,\"level_structure_name\"), &level, Script::ASSERT );\r\n\tpGoalManager->RememberLevelStructureName( level );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SetDifficultyLevel | sets the current level\r\n// @uparm 1 | difficulty level (starts at 0)\r\nbool ScriptSetDifficultyLevel( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tint level;\r\n\tpParams->GetInteger( NONAME, &level, Script::ASSERT );\r\n\tDbg_MsgAssert( level >= 0 && level <= vMAXDIFFICULTYLEVEL, ( \"GoalManager_SetDifficultyLevel called with level of %i\", level ) );\r\n\t\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tpGoalManager->SetDifficultyLevel( level );\r\n\treturn ( level != 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetDifficultyLevel | returns the current\r\n// difficulty level as an integer param called difficulty_level\r\nbool ScriptGetDifficultyLevel( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tint level = (int)pGoalManager->GetDifficultyLevel();\r\n\tpScript->GetParams()->AddInteger( CRCD(0x3671f748,\"difficulty_level\"), level );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n/*\r\nbool ScriptGetGoalParam( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\tCGoal* pGoal = pGoalManager->GetGoal( goalId );\r\n\r\n\tuint32 type_checksum;\r\n\tScript::ESymbolType type = ESYMBOLTYPE_NONE;\r\n\tpParams->GetChecksum( CRCD(0x7321a8d6,\"type\"), &type_checksum, Script::ASSERT );\r\n\r\n\t// convert type\r\n\tswitch ( type_checksum )\r\n\t{\r\n\t\tcase CRCC(0x21902065,\"checksum\"):\r\n\t\t\ttype=ESYMBOLTYPE_NAME;\r\n\t\t\tbreak;\r\n\t\tcase CRCC(0x365aa16a,\"float\"):\r\n\t\t\ttype=ESYMBOLTYPE_FLOAT;\r\n\t\t\tbreak;\r\n\t\tcase CRCC(0xa5f054f4,\"integer\"):\r\n\t\t\ttype=ESYMBOLTYPE_INTEGER;\r\n\t\t\tbreak;\r\n\t\tcase CRCC(0x90fec815,\"structure\"):\r\n\t\t\ttype=ESYMBOLTYPE_STRUCTURE;\r\n\t\t\tbreak;\r\n\t\tcase CRCC(0x5ef31148,\"array\"):\r\n\t\t\ttype=ESYMBOLTYPE_ARRAY;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Uknown type %x\", type ) );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tuint32 name;\r\n\tpParams->GetChecksum( NONAME, &name, Script::ASSERT );\r\n\r\n\t// printf(\"looking for %s with type %s\\n\", Script::FindChecksumName( name ), Script::FindChecksumName( type ) );\r\n\r\n\treturn pGoal->ExtractDifficultyLevelParam( type, name, pScript->GetParams() );\r\n}\r\n*/\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_RestartStage | restarts the current/last stage\r\nbool ScriptRestartStage( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tpGoalManager->RestartStage();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_CanRestartStage | returns true if the player\r\n// can retry a goal stage.\r\nbool ScriptCanRestartStage( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\treturn pGoalManager->CanRestartStage();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptSetGoalChaptersAndStages( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tpGoalManager->SetGoalChaptersAndStages();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_AdvanceStage | returns true if the stage/chapter\r\n// advances, false if you haven't reached an advancement point yet.\r\n// @flag force | force the stage to advance\r\n// @flag just_won_goal | this flag needs to be passed in if the function is called\r\n// from a success script, as the goal is not marked beaten until after the success\r\n// script finishes.  Therefore, the total number of goals beaten will be one more\r\n// than the number returned by searching through the goals.\r\nbool ScriptAdvanceStage( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tuint32 just_won_goal_id = 0;\r\n\tpParams->GetChecksum( CRCD(0x5d82c486,\"just_won_goal_id\"), &just_won_goal_id, Script::NO_ASSERT );\r\n\treturn pGoalManager->AdvanceStage( pParams->ContainsFlag( CRCD( 0x68977cd7, \"force\" ) ), just_won_goal_id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetCurrentChapterAndStage | returns the \r\n// current chapter and stage as currentChapter and currentStage\r\nbool ScriptGetCurrentChapterAndStage( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tint chapter = pGoalManager->GetCurrentChapter();\r\n\tint stage = pGoalManager->GetCurrentStage();\r\n\t\r\n\t// return the last chapter if they beat the game\r\n\tScript::CArray* pChapterGoalsArray = Script::GetArray( CRCD( 0xb892776f, \"chapter_goals\" ), Script::ASSERT );\r\n\tDbg_Assert( pChapterGoalsArray->GetType() == ESYMBOLTYPE_ARRAY );\r\n\tif ( chapter >= (int)pChapterGoalsArray->GetSize() )\r\n\t{\r\n\t\tchapter = pChapterGoalsArray->GetSize() - 1;\r\n\t}\r\n\tpScript->GetParams()->AddInteger( CRCD( 0xf884773c, \"CurrentChapter\" ), chapter );\r\n\tpScript->GetParams()->AddInteger( CRCD( 0xaf1575eb, \"CurrentStage\" ), stage );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SetCurrentChapterAndStage | \r\n// @parmopt int | chapter | current | \r\n// @parmopt int | stage | current |\r\nbool ScriptSetCurrentChapterAndStage( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tint chapter = pGoalManager->GetCurrentChapter();\r\n\tint stage = pGoalManager->GetCurrentStage();\r\n\tpParams->GetInteger( CRCD(0x67e4ad1,\"chapter\"), &chapter, Script::NO_ASSERT );\r\n\tpParams->GetInteger( CRCD(0x3d836c96,\"stage\"), &stage, Script::NO_ASSERT );\r\n\tpGoalManager->SetCurrentChapter( chapter );\r\n\tpGoalManager->SetCurrentStage( stage );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// @script | GoalManager_FilmGoalCheckpoint | Call this when the filming\r\n// target reaches a checkpoint.  This is only used for filming goals that\r\n// require the skater to catch X of Y checkpoints, not goals which requrie\r\n// the skater to film the target for X of Y seconds.\r\n// @parm name | name | the goal_id\r\nbool ScriptFilmGoalCheckpoint( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tCFilmGoal* pFilmGoal = (CFilmGoal*)pGoalManager->GetGoal( pParams, true );\r\n\r\n\tpFilmGoal->CheckpointHit();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// @script | GoalManager_StartFilming | Called when the start cam anims finish.\r\n// @parm name | name | the goal_id\r\nbool ScriptStartFilming( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tCFilmGoal* pFilmGoal = (CFilmGoal*)pGoalManager->GetGoal( pParams, true );\r\n\r\n\tpFilmGoal->StartFilming();\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// @script | GoalManager_GoalShouldExpire | setup for endrun exceptions\r\nbool ScriptGoalShouldExpire( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tif ( pGoalManager )\r\n\t{\r\n\t\tint activeGoal = pGoalManager->GetActiveGoal();\r\n\t\tif ( activeGoal == -1 )\r\n\t\t\treturn false;\r\n\r\n\t\tCGoal* pGoal = pGoalManager->GetGoalByIndex( activeGoal );\r\n\t\tDbg_Assert( pGoal );\r\n\t\tif ( pGoal )\r\n\t\t{\r\n\t\t\treturn pGoal->ShouldExpire();\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SetSponsor | \r\n// @uparm sponsor_name | the checksum of the sponsor name\r\nbool ScriptSetSponsor( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tuint32 sponsor;\r\n\tpParams->GetChecksum( NONAME, &sponsor, Script::ASSERT );\r\n\tpGoalManager->SetSponsor( sponsor );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetSponsor | returns sponsor as param \"sponsor\"\r\n// the sponsor will be 0 if not set\r\nbool ScriptGetSponsor( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tpScript->GetParams()->AddChecksum( CRCD(0x7e73362b,\"sponsor\"), pGoalManager->GetSponsor() );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GetTeam | returns team structure as param named\r\n// team.  It also returns the current number of team members, in a param \r\n// named num_team_members\r\nbool ScriptGetTeam( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tScript::CStruct* pTeam = pGoalManager->GetTeam();\r\n\tpScript->GetParams()->AddStructure( CRCD(0x3b1f59e0,\"team\"), pTeam );\r\n\t\r\n\t// throw in the number of team members\r\n    Script::CComponent* p_comp = NULL;\r\n    p_comp = pTeam->GetNextComponent( p_comp );\r\n\r\n    int total = 0;\r\n\twhile ( p_comp )\r\n    {\r\n        Script::CComponent* p_next = pTeam->GetNextComponent( p_comp );\r\n\t\ttotal++;\r\n\t\tp_comp = p_next;\r\n\t}\r\n\tpScript->GetParams()->AddInteger( CRCD(0xeb8dd330,\"num_team_members\"), total );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SetTeamMember | add or remove a team member\r\n// @parm name | pro | name of the pro to add or remove\r\n// @flag remove | use this flag to remove the pro - will add by default\r\nbool ScriptSetTeamMember( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tuint32 pro;\r\n\tpParams->GetChecksum( CRCD(0x944b2900,\"pro\"), &pro, Script::ASSERT );\r\n\tbool remove = pParams->ContainsFlag( CRCD(0x977fe2cf,\"remove\") );\r\n\tbool mark_used = pParams->ContainsFlag( CRCD(0x531ff702,\"mark_used\") );\r\n\tDbg_MsgAssert( !( remove && mark_used ), ( \"GoalManager_SetTeamMember called with remove and mark_used flags.\" ) );\r\n\tpGoalManager->SetTeamMember( pro, remove, mark_used );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_KillTeamMembers | removes all team members\r\nbool ScriptKillTeamMembers( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tpGoalManager->KillTeamMembers( );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_SetTeamName | set the team name\r\n// @uparm \"team name\" | team name\r\nbool ScriptSetTeamName( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tconst char* p_string;\r\n\tpParams->GetString( NONAME, &p_string, Script::ASSERT );\r\n\tpGoalManager->SetTeamName( p_string );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptRunLastStageScript( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tpGoalManager->RunLastStageScript();\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_GoalInitialized | returns true if the goal\r\n// is initialized\r\n// @parm name | name | goal id\r\nbool ScriptGoalInitialized( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tCGoal* pGoal = pGoalManager->GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\treturn pGoal->IsInitialized();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_UnloadLastFam | unloads the last fam file \r\n// loaded for the goal ped.  If the fam has already been unloaded, it\r\n// will return\r\nbool ScriptUnloadLastFam( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tCGoal* pGoal = pGoalManager->GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->mp_goalPed->UnloadLastFam();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_StopLastStream | stops the last stream played \r\n// for a cam anim\r\nbool ScriptStopLastSream( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 goalId;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &goalId, Script::ASSERT );\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tCGoal* pGoal = pGoalManager->GetGoal( goalId );\r\n\tDbg_Assert( pGoal );\r\n\r\n\tpGoal->mp_goalPed->StopLastStream();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalManager_HideAllGoalPeds | hide/unhide all goal peds\r\n// @uparm 0 | 0 to unhide, anything else to hide\r\nbool ScriptHideAllGoalPeds( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tint hide;\r\n\tpParams->GetInteger( NONAME, &hide, Script::ASSERT );\r\n\tpGoalManager->HideAllGoalPeds( ( hide != 0 ) );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n} // namespace Game\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/GoalManager.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Modules/Skate\r\n//* FILENAME:       GoalManager.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  1/24/2001\r\n//****************************************************************************\r\n\r\n#ifndef\t__MODULES_SKATE_GOALMANAGER_H\r\n#define\t__MODULES_SKATE_GOALMANAGER_H\r\n\r\n                           \r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __SYS_TIMER_H\r\n    #include <sys/timer.h> // For Tmr::Time\r\n#endif\r\n\t\t\t\t\t\t\t  \r\n#include <sk/modules/skate/goal.h>\r\n\r\n#include <core/list/node.h>\r\n#include <core/lookuptable.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Script\r\n{\r\n\tclass CScript;\r\n\tclass CStruct;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Game\r\n{\r\n\t// script names\r\n\tconst uint32 vINIT\t\t\t= 0x398b1b8b;\r\n\tconst uint32 vUNINIT\t\t= 0xd4e0306a;\r\n\tconst uint32 vDESTROY\t\t= 0x83b57984;\r\n\tconst uint32 vACTIVATE\t\t= 0x4999fb52;\r\n\tconst uint32 vDEACTIVATE\t= 0x01c92cac;\t\r\n\tconst uint32 vACTIVE\t\t= 0xb4e103fd;\r\n\tconst uint32 vINACTIVE\t\t= 0x742cf11f;\r\n\tconst uint32 vEXPIRED\t\t= 0xd34eb52b;\r\n\tconst uint32 vSUCCESS\t\t= 0x90ff204d;\r\n\tconst uint32 vFAIL\t\t\t= 0x79d8d4b6;\r\n    const uint32 vUNLOCK        = 0x951b4f10;\r\n\r\n\tconst uint32 vBET_SUCCESS\t= 0x782bdda1;\r\n\r\n    // flag array name - goal_flags\r\n    const uint32 vFLAGS         = 0xcc3c4cc4;\r\n\r\n\t// number of goal flags allowed\r\n\tconst uint32 vNUMGOALFLAGS = 10;\r\n\r\n    // number of completed goals required to unlock this goal\r\n    const int vUNLOCKED_BY_ANOTHER  = 0x8a3a324e;   // type - unlocked_by_another goal\r\n    const int vPRO_GOAL             = 0xd303a1a3;   // type - pro_goal\r\n\t// const int vPRO_CHALLENGE\t\t= 0xe0f96410;\t// type - pro_specific_challenge\r\n\r\n\t// number of streams to search through for goal wait vo\r\n\tconst int vMAXWAITSTREAMS\t\t= 10;\r\n\tconst int vMAXWINSTREAMS\t\t= 10;\r\n\tconst int vMAXMIDGOALSTREAMS\t= 10;\r\n\tconst int vMAXCALLSKATERBYNAMESTREAMS = 5;\r\n\r\n\t// Size of the local buffer used for replacing trick names in goals\r\n\tconst uint32\tNEW_STRING_LENGTH = 512;\r\n\r\n\tconst int vMAXDIFFICULTYLEVEL = 2;\t\r\n\tenum GOAL_MANAGER_DIFFICULTY_LEVEL\r\n\t{\r\n\t\tGOAL_MANAGER_DIFFICULTY_LOW = 0,\r\n\t\tGOAL_MANAGER_DIFFICULTY_MEDIUM,\r\n\t\tGOAL_MANAGER_DIFFICULTY_HIGH,\r\n\t};\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CGoalManager : public Spt::Class\r\n{\r\npublic:\r\n\tCGoalManager();\r\n\t~CGoalManager();\r\n\r\npublic:\r\n\tbool\t\t\t\tCallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\tuint32\t\t\t\tGetGoalIdFromParams( Script::CStruct* pParams, bool assert = true );\r\n\t\r\n\tbool\t\t\t\tAddGoal( uint32 goalId, Script::CStruct* pParams );\r\n\tCGoal*\t\t\t\tGetGoal( uint32 goalId, bool assert = true );\r\n\tCGoal*\t\t\t\tGetGoal( Script::CStruct* pParams, bool assert = true );\r\n\tCGoal*\t\t\t\tGetGoalByIndex( int index );\r\n\tbool\t\t\t\tActivateGoal( uint32 goalId, bool dontAssert );\r\n\tbool\t\t\t\tDeactivateGoal( uint32 goalId );\r\n\tbool\t\t\t\tWinGoal( uint32 goalId );\r\n\tbool\t\t\t\tLoseGoal( uint32 goalId );\r\n\tbool\t\t\t\tRemoveGoal( uint32 goalId );\r\n    void                UnlockGoal( uint32 goalId );\r\n    void                LevelUnload();\r\n    void                LevelLoad();\r\n\r\n\tvoid\t\t\t\tUpdateFamilyTrees();\r\n\tvoid\t\t\t\tFindCircularLinks( uint32 parent, uint32 child );\r\n\t\r\n    bool\t\t\t\tGoalIsActive( uint32 goalId );\r\n\tbool\t\t\t\tEditGoal( uint32 goalId, Script::CStruct* pParams );\r\n\tbool\t\t\t\tSetGoalTimer( uint32 goalId, int time = -1 );\r\n\tint\t\t\t\t\tGetNumGoals();\r\n\tint\t\t\t\t\tGetNumActiveGoals( bool count_all = false );\r\n\tint\t\t\t\t\tGetNumSelectedGoals();\r\n\tvoid\t\t\t\tDeactivateAllGoals( bool include_net_goals = false );\r\n\tvoid\t\t\t\tUninitializeGoal( uint32 goalId );\r\n\tvoid\t\t\t\tUninitializeGoalTree( uint32 start_goal );\r\n\tvoid\t\t\t\tUninitializeAllGoals();\r\n\tvoid\t\t\t\tDeactivateAllMinigames();\r\n\tvoid\t\t\t\tInitializeAllMinigames();\r\n\tvoid\t\t\t\tInitializeAllGoals();\r\n\tvoid\t\t\t\tInitializeAllSelectedGoals();\r\n\tvoid\t\t\t\tDeselectAllGoals();\r\n\tvoid\t\t\t\tRemoveAllGoals();\r\n\tvoid\t\t\t\tUpdate();\r\n    bool                HasSeenGoal( uint32 goalId );\r\n    void                PauseAllGoals();\r\n    void                UnPauseAllGoals();\r\n    Tmr::Time           GetGoalTime();\r\n    int                 GetActiveGoal( bool ignore_net_goals = false );\r\n    bool                QuickStartGoal( uint32 goalId, bool dontAssert = false );\r\n\tvoid                RestartLastGoal();\r\n\tbool\t\t\t\tCanRestartStage();\r\n\tvoid\t\t\t\tRestartStage();\r\n    bool                HasWonGoal( uint32 goalId );\r\n\tbool\t\t\t\tGoalIsSelected( uint32 goalId );\r\n\tvoid\t\t\t\tToggleGoalSelection( uint32 goalId );\r\n\tvoid\t\t\t\tCreateGoalLevelObjects( void );\r\n    \r\n    // void                CreateGoalFlag( uint32 goalId, uint32 flag );\r\n    bool                SetGoalFlag( uint32 goalId, uint32 flag, int value );\r\n\tbool\t\t\t\tGoalFlagSet( uint32 goalId, uint32 flag );\r\n    bool                AllFlagsSet( uint32 goalId );\r\n    \r\n\tbool\t\t\t\tCreatedGapGoalIsActive(); // Added by Ken\r\n\tbool\t\t\t\tGetCreatedGoalGap(int gapIndex); // Also added by Ken\r\n\r\n    bool                CanRetryGoal();\r\n    Script::CStruct*    GetGoalParams( uint32 goalId );\r\n    bool                CanStartGoal();\r\n    \r\n    bool                NextRaceWaypoint( uint32 goalId );\r\n    bool                NextTourSpot( uint32 goalId );\r\n    void                InitTrickObjects( uint32 goalId );\r\n\tbool\t\t\t\tShouldLogTrickObject();\r\n    bool                SetGraffitiMode( int mode );\r\n\r\n\tvoid\t\t\t\tGotTrickObject( uint32 clusterId, int score );\r\n    void                SetSpecialGoal( uint32 goalId, int set );\r\n\tvoid                CheckTrickText();\r\n//\tvoid                CheckTetrisTricks();\r\n    void                GotCounterObject( uint32 goalId );\r\n    bool                CounterGoalDone( uint32 goalId );\r\n    void                SpendGoalPoints( int num );\r\n    bool                HasGoalPoints( int num );\r\n    int                 GetNumberOfGoalPoints();\r\n\tint\t\t\t\t\tGetTotalNumberOfGoalPointsEarned();\r\n\tvoid\t\t\t\tClearGoalPoints();\r\n    void                AddGoalPoint();\r\n    void                AddCash( int amount );\r\n    int                 GetCash( bool get_total = false );\r\n    bool                SpendCash( int amount );\r\n    bool                HasBeatenGoalWithProset( const char* proset_prefix );\r\n\tint                 NumGoalsBeatenBy( int obj_id );\r\n\tint                 NumGoalsBeatenByTeam( int team_id );\r\n\tint                 NumGoalsBeaten();\r\n    int                 NumGoalsBeatenInLevel( int levelNum, bool count_pro_specific_challenges = false );\r\n    void                UnlockAllGoals();\r\n\tvoid\t\t\t\tTurnPro();\r\n\tbool\t\t\t\tCheckMinigameRecord( uint32 goalId, int value );\r\n\tvoid\t\t\t\tDeactivateMinigamesWithTimer();\r\n\tvoid\t\t\t\tDeactivateCurrentGoal();\r\n\tvoid\t\t\t\tSetStartTime( uint32 goalId );\r\n\tvoid\t\t\t\tUpdateComboTimer( uint32 goalId );\r\n\tvoid\t\t\t\tSetStartHeight( uint32 goalId );\r\n\tbool\t\t\t\tCheckHeightRecord( uint32 goalId );\r\n\tbool\t\t\t\tCheckDistanceRecord( uint32 goalId );\r\n\r\n\tvoid\t\t\t\tPlayGoalStartStream( Script::CStruct* pParams );\r\n\tvoid\t\t\t\tStopCurrentStream( uint32 goalId );\r\n\tvoid\t\t\t\tPlayGoalWinStream( Script::CStruct* pParams );\r\n\tvoid\t\t\t\tPlayGoalWaitStream( uint32 goalId );\r\n\tvoid\t\t\t\tPlayGoalStream( Script::CStruct* pParams );\r\n\r\n\tvoid\t\t\t\tGetGoalAnimations( uint32 goalId, const char* type, Script::CScript* pScript );\r\n\r\n\tvoid\t\t\t\tPauseGoal( uint32 goalId );\r\n\tvoid\t\t\t\tUnPauseGoal( uint32 goalId );\r\n\r\n\tvoid\t\t\t\tPauseCompetition( uint32 goalId );\r\n\tvoid\t\t\t\tUnPauseCompetition( uint32 goalId );\r\n\r\n\tvoid\t\t\t\tUnBeatAllGoals();\r\n\tvoid\t\t\t\tAddViewGoalsList();\r\n\tvoid\t\t\t\tAddGoalChoices( bool selected_only );\r\n\r\n\tbool\t\t\t\tGoalIsLocked( uint32 goalId );\r\n\r\n\tCGoal*\t\t\t\tIsInCompetition();\r\n\r\n\tuint32\t\t\t\tGetRandomBettingMinigame();\r\n\tbool\t\t\t\tEndRunCalled( uint32 goalId );\r\n\r\n\tuint32\t\t\t\tGetBettingGuyId();\r\n\r\n\tScript::CStruct*\tGetGoalManagerParams();\r\n\r\n\tbool\t\t\t\tReplaceTrickText( uint32 goalId );\r\n\tbool\t\t\t\tReplaceTrickText( uint32 goalId, const char* p_old_string, char* p_new_string, uint out_buffer_size );\r\n\tvoid\t\t\t\tReplaceAllTrickText();\r\n\r\n\t// void\t\t\t\tUnlockProSpecificChallenges();\r\n\t// bool\t\t\t\tProSpecificChallengesUnlocked();\r\n\r\n\tint\t\t\t\t\tGetNumberCollected( uint32 goalId );\r\n\tint\t\t\t\t\tGetNumberOfFlags( uint32 goalId );\r\n\r\n\tbool \t\t\t\tIsPro();\r\n\r\n\tvoid\t\t\t\tResetGoalFlags( uint32 goalId );\r\n\r\n\tvoid\t\t\t\tColorTrickObjects( uint32 goalId, int seqIndex, bool clear = false );\r\n\r\n\tint\t\t\t\t\tGetNumberOfTimesGoalStarted( uint32 goalId );\r\n\r\n\tbool\t\t\t\tGoalExists( uint32 goalId );\r\n\r\n\tScript::CStruct*\tGetGoalAttemptInfo();\r\n\r\n\tvoid\t\t\t\tSetCanStartGoal( int value );\r\n\tvoid\t\t\t\tCheckTrickObjects();\r\n\r\n\tuint32\t\t\t\tGetLastGoalId() { return m_lastGoal; }\r\n\tvoid\t\t\t\tClearLastGoal( void );\r\n\r\n\t// void\t\t\t\tMarkProSpecificChallengeBeaten( uint32 skater_name, int beaten = 1 );\r\n\t// bool\t\t\t\tSkaterHasBeatenProSpecificChallenge( uint32 skater_name );\r\n\r\n\tvoid\t\t\t\tSetEndRunType( uint32 goalId, EndRunType newEndRunType );\r\n\tbool\t\t\t\tShouldUseTimer();\r\n\tvoid\t\t\t\tSetShouldDeactivateOnExpire( uint32 goalId, bool should_deactivate );\r\n\tvoid\t\t\t\tLand();\r\n\tvoid\t\t\t\tBail();\r\n\tbool\t\t\t\tAwardMinigameCash( uint32 goalId, int amount );\r\n\tvoid\t\t\t\tResetCareer();\r\n\tvoid\t\t\t\tAwardAllGoalCash();\r\n\r\n\tvoid\t\t\t\tRememberLevelStructureName( uint32 level ) { m_levelStructureName = level; }\r\n\tuint32\t\t\t\tGetLevelStructureName() { return m_levelStructureName; }\r\n\r\n\tvoid\t\t\t\tSetDifficultyLevel( int level );\r\n\tGOAL_MANAGER_DIFFICULTY_LEVEL GetDifficultyLevel( bool career = false );\r\n\r\n\tvoid\t\t\t\tSetGoalChaptersAndStages();\r\n\tbool\t\t\t\tAdvanceStage( bool force = false, uint32 just_won_goal_id = 0 );\r\n\tint\t\t\t\t\tGetCurrentChapter() { return m_currentChapter; }\r\n\tint\t\t\t\t\tGetCurrentStage() { return m_currentStage; }\r\n\tvoid\t\t\t\tSetCurrentChapter( int chapter ) { m_currentChapter = chapter; }\r\n\tvoid\t\t\t\tSetCurrentStage( int stage ) { m_currentStage = stage; }\r\n\tvoid\t\t\t\tRunLastStageScript();\r\n\tvoid\t\t\t\tSetSponsor( uint32 sponsor ) { m_sponsor = sponsor; }\r\n\tuint32\t\t\t\tGetSponsor() { return m_sponsor; }\r\n\tvoid\t\t\t\tSetTeamMember( uint32 pro, bool remove = false, bool mark_used = false );\r\n\tvoid\t\t\t\tKillTeamMembers( );\r\n\tvoid\t\t\t\tSetTeamName( const char* pTeamName );\r\n\tScript::CStruct*\tGetTeam() { return mp_team; }\r\n\tvoid\t\t\t\tHideAllGoalPeds( bool hide );\r\nprotected:\r\n\tLst::LookupTable<CGoal>\t    m_goalList;\r\n\tScript::CStruct*            mp_goalFlags;\r\n    \r\n    uint32                      m_lastGoal;\r\n\tuint32\t\t\t\t\t\tm_lastStage;\r\n    int                         m_graffitiMode;\r\n    int                         m_goalPoints;\r\n\tint\t\t\t\t\t\t\tm_totalGoalPointsEarned;\r\n    int                         m_cash;\r\n\tint\t\t\t\t\t\t\tm_totalCash;\r\n    \r\n\tint\t\t\t\t\t\t\tm_numGoalsBeaten;\r\n\tbool \t\t\t\t\t\tm_isPro;\r\n\t// bool\t\t\t\t\t\tm_proChallengesUnlocked;\r\n\tbool\t\t\t\t\t\tm_canStartGoal;\r\n\r\n\tint\t\t\t\t\t\t\tm_currentChapter;\r\n\tint\t\t\t\t\t\t\tm_currentStage;\r\n\r\n\tuint32\t\t\t\t\t\tm_sponsor;\r\n\tScript::CStruct*\t\t\tmp_team;\r\n\r\n\t// Script::CStruct*\t\t\tmp_proSpecificChallenges;\r\n\r\n\tuint32\t\t\t\t\t\tm_levelStructureName;\r\n\r\n\tScript::CStruct* \t\t\tmp_difficulty_levels;\r\n};\r\n\r\nCGoalManager*           GetGoalManager();\r\n\r\nbool ScriptAddGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRemoveGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptEditGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptActivateGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptDeactivateGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptClearLastGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptWinGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptLoseGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRemoveAllGoals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptDeactivateAllGoals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUninitializeAllGoals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUninitializeGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUpdateAllGoals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptInitializeAllGoals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptInitializeAllSelectedGoals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptHasActiveGoals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGoalIsActive(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetGoalTimer(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptZeroGoalTimer(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetGoalFlag(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptHasSeenGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPauseAllGoals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUnPauseAllGoals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRestartLastGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\n// bool ScriptCreateGoalFlag(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGoalFlagSet(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAllFlagsSet(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCanRetryGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetGoalParams(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCanStartGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetCanStartGoal( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptNextRaceWaypoint(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptNextTourSpot(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptInitTrickObjects(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCreateGoalName(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptGetLevelPrefix( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetGraffitiMode(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptSetSpecialGoal(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptGetNumGoalsCompleted(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptGetNumGoalsNeeded(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptHasWonGoal(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptGoalIsSelected(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptToggleGoalSelection(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptGoalsAreSelected(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptGotCounterObject(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptCounterGoalDone(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptAddGoalPoint(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptSpendGoalPoints(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptHasGoalPoints(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptClearGoalPoints(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptGetNumberOfGoalPoints(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptAddCash(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptGetCash(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptSpendCash(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptHasBeatenGoalWithProset(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptGetProsetNotPrefix(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptLevelLoad(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptLevelUnload(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptNumGoalsBeatenInLevel(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptUnlockAllGoals(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptCheckMinigameRecord(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptDeactivateCurrentGoal(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptSetStartTime(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptUpdateComboTimer(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptSetStartHeight(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptCheckHeightRecord(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptCheckDistanceRecord(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptShowGoalPoints(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptHideGoalPoints(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptHidePoints(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptShowPoints(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptTurnPro(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptDeactivateAllMinigames(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptInitializeAllMinigames(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptPauseGoal(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptUnPauseGoal(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptPauseCompetition(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptUnPauseCompetition(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\nbool ScriptPlayGoalStartStream(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptPlayGoalWinStream(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptStopCurrentStream(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptPlayGoalWaitStream(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\nbool ScriptUnBeatAllGoals(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptAddViewGoalsList(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptGoalIsLocked(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\nbool ScriptIsInCompetition(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\nbool ScriptGetGoalAnimations(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptPlayGoalStream(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\nbool ScriptSetEndRunType(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptEndRunCalled(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptClearEndRun(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptFinishedEndOfRun(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptStartedEndOfRun(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\nbool ScriptEndBetAttempt(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptStartBetAttempt(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptBetOffered(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptBetRefused(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptWinBet(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptMoveBettingGuyNow(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptBetAccepted(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptBetIsActive(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\nbool ScriptAddMinigameTime(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\nbool ScriptAddTempSpecialTrick(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptRemoveTempSpecialTrick(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\nbool ScriptGetTrickFromKeyCombo(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptUnlockGoal(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\nbool ScriptQuickStartGoal( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptInitializeGoal( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGoalInitialized( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptAddGoalChoices( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptAddTime( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptReplaceTrickText( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\n// bool ScriptUnlockProSpecificChallenges( Script::CStruct* pParams, Script::CScript* pScript );\r\n// bool ScriptProSpecificChallengesUnlocked( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptGetNumberCollected( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetNumberOfFlags( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptIsPro( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptResetGoalFlags( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptColorTrickObjects( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptGetNumberOfTimesGoalStarted( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptGoalExists( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptGetGoalAttemptInfo( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptGetLastGoalId( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptClearTetrisTricks( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\n// bool ScriptMarkProSpecificChallengeBeaten( Script::CStruct* pParams, Script::CScript* pScript );\r\n// bool ScriptSkaterHasBeatenProSpecificChallenge( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptAnnounceGoalStarted( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptAnnounceGoalExited( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptSetShouldDeactivateOnExpire( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptGetActiveGoalId( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptAwardMinigameCash( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptResetCareer( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptAwardAllGoalCash( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptUpdateFamilyTrees( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptIsLeafNode( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptIsRootNode( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptSuspendGoalPedLogic( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptRememberLevelStructureName( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptSetDifficultyLevel( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetDifficultyLevel( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\n// bool ScriptGetGoalParam( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptRestartStage( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptCanRestartStage( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptSetGoalChaptersAndStages( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptAdvanceStage( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetCurrentChapterAndStage( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetCurrentChapterAndStage( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptRunLastStageScript( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptFilmGoalCheckpoint( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptStartFilming( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptGoalShouldExpire( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptSetSponsor( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetSponsor( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetTeam( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetTeamMember( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptKillTeamMembers( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetTeamName( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptUnloadLastFam( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptStopLastSream( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptHideAllGoalPeds( Script::CStruct* pParams, Script::CScript* pScript );\r\n}\r\n\r\n#endif // __MODULES_SKATE_GOALMANAGER_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/GoalPed.cpp",
    "content": "// goal ped!\r\n\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/modules/skate/goal.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/objects/playerprofilemanager.h>\r\n\r\n#include <gel/assman/assman.h>\r\n#include <gel/music/music.h>\r\n\r\n#include <gel/object/compositeobjectmanager.h>\r\n\r\n#include <gel/components/animationcomponent.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\nnamespace Game\r\n{\r\n\r\nCGoalPed::CGoalPed( Script::CStruct* pParams )\r\n{\r\n\tpParams->GetChecksum( CRCD(0x9982e501,\"goal_id\"), &m_goalId, Script::ASSERT );\r\n\tm_goalLogicSuspended = false;\r\n\tm_lastFam = 0;\r\n\tm_lastFamObj = 0;\r\n\tm_lastStreamId = 0;\r\n}\r\n\r\nCGoalPed::~CGoalPed()\r\n{\r\n\t// nothing yet.\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\t\r\n\r\ninline void parse_first_name( char* pFirstName, const char** ppDisplayName, int buffer_size )\r\n{\r\n\tif ( !strstr( *ppDisplayName, \" \" ) )\r\n\t{\t\t\r\n\t\tDbg_MsgAssert( strlen( *ppDisplayName ) < (uint32)buffer_size, ( \"buffer overflow\" ) );\r\n\t\tstrcpy( pFirstName, *ppDisplayName );\r\n\t\t// printf(\"first name has no spaces, using %s\\n\", pFirstName);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tchar *p_in = pFirstName;\r\n\t\tint length = 0;\r\n\t\twhile ( **ppDisplayName != ' ' )\r\n\t\t{\r\n\t\t\t*p_in++ = **ppDisplayName;\r\n\t\t\t(*ppDisplayName)++;\r\n\t\t\tlength++;\r\n\t\t}\r\n\t\t*p_in++ = '\\0';\r\n\t\tlength++;\r\n\t\tDbg_MsgAssert( length < buffer_size, ( \"buffer overflow\" ) );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\t\r\n\r\nconst char* CGoalPed::GetProFirstName()\r\n{\t\r\n\t// get params\r\n\tScript::CStruct* pParams = GetGoalParams();\r\n\t\r\n\t// grab the pro\r\n\tconst char* p_default_pro_name;\r\n\tconst char* p_alternate_pro_name;\r\n\tif ( !pParams->GetText( CRCD(0x944b2900,\"pro\"), &p_default_pro_name ) )\r\n\t{\r\n\t\t// printf(\"no pro associated with this goal\\n\");\r\n\t\treturn 0;\r\n\t}\r\n\r\n\t// check what pro the player is using\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile();\t\r\n\tconst char* p_current_pro_name;\r\n\tp_current_pro_name = pSkaterProfile->GetDisplayName();\r\n\t// printf(\"the current display name is %s\\n\", p_current_pro_name);\r\n\t\r\n\t// only check the display name if it's a pro\r\n\tbool use_alternate = false;\r\n\tif ( pSkaterProfile->IsPro() )\r\n\t{\t\r\n\t\t// chop off the first name\r\n\t\tchar current_pro_first_name[128];\r\n\t\tparse_first_name( current_pro_first_name, &p_current_pro_name, 128 );\r\n\r\n\t\tDbg_MsgAssert( strlen( current_pro_first_name ) > 0, ( \"No first name found for the current pro\" ) );\r\n\t\t// printf(\"the player's first name is %s\\n\", current_pro_first_name);\r\n\t\r\n\t\t// see if we should use the alternate pro\r\n\t\tif ( pSkaterProfile->IsPro() && ( Script::GenerateCRC( current_pro_first_name ) == Script::GenerateCRC( p_default_pro_name ) ) )\r\n\t\t{\r\n\t\t\tif ( pParams->GetText( CRCD(0x878ccc12,\"alternate_pro\"), &p_alternate_pro_name ) )\r\n\t\t\t{\r\n\t\t\t\tuse_alternate = true;\r\n\t\t\t\t// printf(\"found an alternate name of %s\\n\", p_alternate_pro_name);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// printf(\"no alternate pro found for this goal\\n\");\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// build the stream name\r\n\tif ( use_alternate )\r\n\t\treturn p_alternate_pro_name;\r\n\telse\r\n\t\treturn p_default_pro_name;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\t\r\n\r\ninline void possibly_add_success_suffix( bool success, char* buffer, int buffer_length )\r\n{\r\n\tif ( success )\r\n\t{\r\n\t\tDbg_MsgAssert( (int)strlen( buffer ) + 8 < buffer_length, ( \"buffer overflow\" ) );\r\n\t\tsprintf( buffer, \"%s_success\", buffer );\r\n\t}\r\n\t// printf(\"done creating stream %s\\n\", buffer );\r\n}\r\n\r\n// returns true if it found a lip version of the stream, signifying\r\n// that there exists a fam associated with the stream\r\nbool CGoalPed::GetStreamChecksum( uint32* p_streamChecksum, int cam_anim_index, bool success, const char* p_speaker_name, bool last_anim )\r\n{\r\n\tScript::CStruct* pGoalParams = GetGoalParams();\r\n\r\n\tconst char* p_first_name = GetProFirstName();\r\n\tif ( !p_first_name )\r\n\t\treturn 0;\r\n\r\n\tconst char* p_goal_name;\r\n\tpGoalParams->GetText( CRCD(0xbfecc45b,\"goal_name\"), &p_goal_name, Script::ASSERT );\r\n\t\r\n\t// build stream name\r\n\tchar p_stream_name[MAX_STREAM_NAME_LENGTH];\r\n\tDbg_MsgAssert( strlen( p_first_name ) + strlen( p_goal_name ) + 1 < MAX_STREAM_NAME_LENGTH, ( \"buffer overflow\" ) );\r\n\tsprintf( p_stream_name, \"%s_%s\", p_first_name, p_goal_name );\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tuint32 stream_name_length = (uint32)strlen( p_stream_name );\r\n\t#endif\r\n\t\r\n\t// get string representation of difficulty level\r\n\tconst char* p_difficulty_level_string;\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tGOAL_MANAGER_DIFFICULTY_LEVEL difficulty_level = pGoalManager->GetDifficultyLevel();\r\n\tswitch ( difficulty_level )\r\n\t{\r\n\t\tcase ( GOAL_MANAGER_DIFFICULTY_LOW ):\r\n\t\t\tp_difficulty_level_string = \"easy\";\r\n\t\t\tbreak;\r\n\t\tcase ( GOAL_MANAGER_DIFFICULTY_MEDIUM ):\r\n\t\t\tp_difficulty_level_string = \"medium\";\r\n\t\t\tbreak;\r\n\t\tcase ( GOAL_MANAGER_DIFFICULTY_HIGH ):\r\n\t\t\tp_difficulty_level_string = \"hard\";\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Unknown difficulty level\" ) );\r\n\t\t\treturn 0;\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\t// build different prefix possibilities\r\n\t// format is: <pro>_<goal_id>_<difficulty>_<camanimXX>_<speaker>_success_lip\r\n\t// where difficulty, camAnimXX, speaker, success, and lip are optional\r\n\r\n\t// figure out if we need to look for a female vo\r\n\tbool is_female_skater = false;\r\n\tif ( p_speaker_name && Script::GenerateCRC( p_speaker_name ) == CRCD(0x5b8ab877,\"skater\") )\r\n\t{\r\n\t\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\t\tObj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile();\t\r\n\t\tint male_test;\r\n\t\tpSkaterProfile->GetInfo()->GetInteger( CRCD(0x3f813177,\"is_male\"), &male_test, Script::ASSERT );\r\n\t\tif ( !male_test )\r\n\t\t{\r\n\t\t\tis_female_skater = true;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// diff level\r\n\tchar p_diff_stream_name[MAX_STREAM_NAME_LENGTH];\r\n\tDbg_MsgAssert( stream_name_length + strlen( p_difficulty_level_string ) + 1 < MAX_STREAM_NAME_LENGTH, ( \"buffer overflow\" ) );\r\n\tsprintf( p_diff_stream_name, \"%s_%s\", p_stream_name, p_difficulty_level_string );\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tuint32 diff_stream_name_length = (uint32)strlen( p_diff_stream_name );\r\n\t#endif\r\n\t\r\n\t// if we have a cam anim index...\r\n\tchar p_diff_cam_stream_name[MAX_STREAM_NAME_LENGTH];\r\n\tstrcpy( p_diff_cam_stream_name, \"\" );\r\n\tchar p_cam_stream_name[MAX_STREAM_NAME_LENGTH];\r\n\tstrcpy( p_cam_stream_name, \"\" );\r\n\tchar p_cam_speaker_stream_name[MAX_STREAM_NAME_LENGTH];\r\n\tstrcpy( p_cam_speaker_stream_name, \"\" );\r\n\tchar p_diff_cam_speaker_stream_name[MAX_STREAM_NAME_LENGTH];\r\n\tstrcpy( p_diff_cam_speaker_stream_name, \"\" );\r\n\tif ( cam_anim_index >= 0 && !last_anim )\r\n\t{\t\r\n\t\t// diff level and cam anim\r\n\t\tDbg_MsgAssert( diff_stream_name_length + 10 < MAX_STREAM_NAME_LENGTH, ( \"buffer overflow\" ) );\r\n\t\tsprintf( p_diff_cam_stream_name, \"%s_camAnim%02i\", p_diff_stream_name, cam_anim_index );\r\n\t\tpossibly_add_success_suffix( success, p_diff_cam_stream_name, MAX_STREAM_NAME_LENGTH );\r\n\t\t\r\n\t\t// cam anim\r\n\t\tDbg_MsgAssert( stream_name_length + 10 < MAX_STREAM_NAME_LENGTH, ( \"buffer overflow\" ) );\r\n\t\tsprintf( p_cam_stream_name, \"%s_camAnim%02i\", p_stream_name, cam_anim_index );\r\n\t\tpossibly_add_success_suffix( success, p_cam_stream_name, MAX_STREAM_NAME_LENGTH );\r\n\r\n\t\tif ( p_speaker_name )\r\n\t\t{\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tint speaker_name_length = strlen( p_speaker_name );\r\n\t\t\t// cam anim and speaker name\r\n\t\t\tDbg_MsgAssert( stream_name_length + 10 + speaker_name_length + 1 < MAX_STREAM_NAME_LENGTH, ( \"buffer overflow\" ) );\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tsprintf( p_cam_speaker_stream_name, \"%s_camAnim%02i_%s\", p_stream_name, cam_anim_index, p_speaker_name );\r\n\t\t\tif ( is_female_skater )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( strlen( p_cam_speaker_stream_name ) + 2 < MAX_STREAM_NAME_LENGTH, ( \"buffer overflow\" ) );\r\n\t\t\t\tsprintf( p_cam_speaker_stream_name, \"%s_f\", p_cam_speaker_stream_name );\r\n\t\t\t}\r\n\t\t\tpossibly_add_success_suffix( success, p_cam_speaker_stream_name, MAX_STREAM_NAME_LENGTH );\r\n\r\n\t\t\t\r\n\t\t\t// diff level, cam anim, and speaker name\r\n\t\t\tDbg_MsgAssert( diff_stream_name_length + 10 + speaker_name_length + 1 < MAX_STREAM_NAME_LENGTH, ( \"buffer overflow\" ) );\r\n\t\t\tsprintf( p_diff_cam_speaker_stream_name, \"%s_camAnim%02i_%s\", p_diff_stream_name, cam_anim_index, p_speaker_name );\r\n\t\t\tif ( is_female_skater )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( strlen( p_diff_cam_speaker_stream_name ) + 2 < MAX_STREAM_NAME_LENGTH, ( \"buffer overflow\" ) );\r\n\t\t\t\tsprintf( p_diff_cam_speaker_stream_name, \"%s_f\", p_diff_cam_speaker_stream_name );\r\n\t\t\t}\r\n\t\t\tpossibly_add_success_suffix( success, p_diff_cam_speaker_stream_name, MAX_STREAM_NAME_LENGTH );\r\n\t\t}\t\t\r\n\t}\r\n\r\n\tchar p_diff_speaker_stream_name[MAX_STREAM_NAME_LENGTH];\r\n\tstrcpy( p_diff_speaker_stream_name, \"\" );\r\n\tchar p_speaker_stream_name[MAX_STREAM_NAME_LENGTH];\r\n\tstrcpy( p_speaker_stream_name, \"\" );\r\n\tif ( p_speaker_name )\r\n\t{\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tint speaker_name_length = strlen( p_speaker_name );\r\n\t\t// diff level and speaker name\r\n\t\tDbg_MsgAssert( diff_stream_name_length + speaker_name_length + 1 < MAX_STREAM_NAME_LENGTH, ( \"buffer overflow\" ) );\r\n\t\t#endif\r\n\t\tsprintf( p_diff_speaker_stream_name, \"%s_%s\", p_diff_stream_name, p_speaker_name );\r\n\t\tif ( is_female_skater )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( strlen( p_diff_speaker_stream_name ) + 2 < MAX_STREAM_NAME_LENGTH, ( \"buffer overflow\" ) );\r\n\t\t\tsprintf( p_diff_speaker_stream_name, \"%s_f\", p_diff_speaker_stream_name );\r\n\t\t}\r\n\t\tpossibly_add_success_suffix( success, p_diff_speaker_stream_name, MAX_STREAM_NAME_LENGTH );\r\n\t\r\n\t\t// speaker name\r\n\t\tDbg_MsgAssert( stream_name_length + speaker_name_length + 1 < MAX_STREAM_NAME_LENGTH, ( \"buffer overflow\" ) );\r\n\t\tsprintf( p_speaker_stream_name, \"%s_%s\", p_stream_name, p_speaker_name );\r\n\t\tif ( is_female_skater )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( strlen( p_speaker_stream_name ) + 2 < MAX_STREAM_NAME_LENGTH, ( \"buffer overflow\" ) );\r\n\t\t\tsprintf( p_speaker_stream_name, \"%s_f\", p_speaker_stream_name );\r\n\t\t}\r\n\t\tpossibly_add_success_suffix( success, p_speaker_stream_name, MAX_STREAM_NAME_LENGTH );\r\n\t}\r\n\t\r\n\t// now that we're done using the diff stream  and stream name\r\n\t// as pieces, add the success suffix\r\n\tpossibly_add_success_suffix( success, p_diff_stream_name, MAX_STREAM_NAME_LENGTH );\r\n\tpossibly_add_success_suffix( success, p_stream_name, MAX_STREAM_NAME_LENGTH );\r\n\t\r\n\t// array of pointers to my streams to make the code more readable\r\n\t// 0 - p_stream_name\r\n\t// 1 - p_diff_stream_name\r\n\t// 2 - p_diff_cam_stream_name\r\n\t// 3 - p_cam_stream_name\r\n\t// 4 - p_cam_speaker_stream_name\r\n\t// 5 - p_diff_cam_speaker_stream_name\r\n\t// 6 - p_diff_speaker_stream_name\r\n\t// 7 - p_speaker_stream_name\r\n\tchar* pp_stream_names[8];\r\n\tpp_stream_names[0] = p_stream_name;\r\n\tpp_stream_names[1] = p_diff_stream_name;\r\n\tpp_stream_names[2] = p_speaker_stream_name;\r\n\tpp_stream_names[3] = p_diff_speaker_stream_name;\r\n\tpp_stream_names[4] = p_diff_cam_stream_name;\r\n\tpp_stream_names[5] = p_cam_stream_name;\r\n\tpp_stream_names[6] = p_cam_speaker_stream_name;\r\n\tpp_stream_names[7] = p_diff_cam_speaker_stream_name;\r\n\r\n\t// search!\r\n\t// if there's a cam anim index defined, don't search for \r\n\t// ones without cam anim index\r\n\tint start_index = 0;\r\n\tif ( cam_anim_index >= 0 )\r\n\t{\r\n\t\tstart_index = 4;\r\n\t}\r\n\r\n\t// search for regular or lip version of stream\r\n\tuint32 existing_stream = 0;\r\n\tbool found_lip = false;\r\n\tfor ( int i = start_index; i < 8; i++ )\r\n\t{\r\n\t\t// make sure there's something to check\r\n\t\tint stream_name_length = strlen( pp_stream_names[i] );\r\n\t\tif ( stream_name_length == 0 )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\t// test lip version first - it's more likely to happen\r\n\t\tchar p_lip_stream[MAX_STREAM_NAME_LENGTH];\r\n\t\tDbg_MsgAssert( (uint32)stream_name_length + 4 < MAX_STREAM_NAME_LENGTH, ( \"buffer overflow\" ) );\r\n\t\tsprintf( p_lip_stream, \"%s_lip\", pp_stream_names[i] );\r\n\t\t// printf(\"looking for %s\\n\", p_lip_stream );\r\n\t\tuint32 lip_stream_checksum = Script::GenerateCRC( p_lip_stream );\r\n\t\tif ( Pcm::StreamExists( lip_stream_checksum ) )\r\n\t\t{\r\n\t\t\t// printf(\"Existing stream: %s\\n\", p_lip_stream);\r\n\t\t\texisting_stream = lip_stream_checksum;\r\n\t\t\tfound_lip = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tuint32 stream_checksum = Script::GenerateCRC( pp_stream_names[i] );\r\n\t\t\t// printf(\"looking for %s\\n\", pp_stream_names[i]);\r\n\t\t\tif ( Pcm::StreamExists( stream_checksum ) )\r\n\t\t\t{\r\n\t\t\t\t// printf( \"Existing stream: %s\\n\", pp_stream_names[i] );\r\n\t\t\t\texisting_stream = stream_checksum;\r\n\t\t\t\tbreak;\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t*p_streamChecksum = existing_stream;\r\n\treturn found_lip;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\t\r\n\r\nvoid CGoalPed::GetPlayerFirstName( char* p_first_name, int buffer_size )\r\n{\r\n\t// check what pro the player is using\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile();\t\r\n\t\r\n\tconst char* p_current_pro_name;\r\n\tp_current_pro_name = pSkaterProfile->GetDisplayName();\r\n\t\r\n\tstrcpy( p_first_name, \"\" );\r\n\tparse_first_name( p_first_name, &p_current_pro_name, buffer_size );\r\n\tDbg_MsgAssert( strlen( p_first_name ) > 0, ( \"No current player name found\" ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoalPed::PlayGoalStream( uint32 stream_checksum, bool use_pos_info, uint32 speaker_obj_id, bool should_load_fam )\r\n{\r\n\tif ( m_goalLogicSuspended )\r\n\t\treturn;\r\n\r\n\tif ( !Pcm::StreamExists( stream_checksum ) )\r\n\t\treturn;\r\n\r\n\t// get params\r\n\tScript::CStruct* pParams = GetGoalParams();\r\n\r\n\t// printf(\"PlayGoalStream: %x\\n\", stream_checksum );\r\n\t\r\n\t// run script and associate with trigger\r\n\tuint32 trigger_obj_id = speaker_obj_id;\r\n\tif ( !trigger_obj_id )\r\n\t{\r\n\t\tpParams->GetChecksum( CRCD(0x02d7e03d,\"trigger_obj_id\"), &trigger_obj_id, Script::ASSERT );\r\n\t}\r\n\t\r\n\tObj::CCompositeObject* p_pos_obj = NULL;\r\n\tif ( trigger_obj_id == CRCD(0x5b8ab877,\"skater\") )\r\n\t{\t\t\r\n\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\tp_pos_obj = skate_mod->GetLocalSkater();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//p_pos_obj = Obj::CMovingObject::m_hash_table.GetItem( trigger_obj_id );\r\n\t\tp_pos_obj = (Obj::CCompositeObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID( trigger_obj_id);\r\n\t}\r\n\t\r\n\tif ( p_pos_obj )\r\n\t{\t\t\r\n\t\tScript::CStruct* p_tempParams = new Script::CStruct();\r\n\t\tp_tempParams->AddChecksum( CRCD(0x0572ea28,\"stream_checksum\"), stream_checksum );\r\n\r\n\t\tif ( !use_pos_info )\r\n\t\t{\r\n\t\t\tp_tempParams->AddInteger( CRCD(0xc9b0deb7,\"use_pos_info\"), 0 );\r\n\t\t\t\r\n\t\t\t// get the reference checksum, so that we can play anims on the correct skeleton\r\n\t\t\t// (either animload_thps5_human or animload_ped_female)\r\n\t\t\tObj::CAnimationComponent* pAnimComponent = GetAnimationComponentFromObject( p_pos_obj );\r\n\t\t\tDbg_Assert( pAnimComponent );\r\n\t\t\tuint32 reference_checksum = pAnimComponent->GetAnimScriptName();\r\n\t\r\n\t\t\tif ( should_load_fam )\r\n\t\t\t{\r\n\t\t\t\tLoadFam( stream_checksum, reference_checksum );\r\n\t\t\t}\r\n\t\t\r\n\t\t\t// preload the stream\r\n\t\t\tuint32 streamId = Pcm::PreLoadStream( stream_checksum, 100 );\r\n\t\t\tp_tempParams->AddChecksum( CRCD(0x8a68ab90,\"streamId\"), streamId );\r\n\t\t\tm_lastStreamId = streamId;\r\n\t\r\n\t\t\t// Script::KillSpawnedScriptsThatReferTo( CRCD(0x5376a011,\"goal_play_stream\") );\r\n\t\t\t\r\n\t\t\t// delete p_tempParams;\r\n\t\t\r\n\t\t\t// look for an FAM (frame amplitude) with that name\r\n\t\t\t// (needs an actual skeleton name, which we will\r\n\t\t\t// hardcode as \"animload_thps5_human\" for now)\r\n\t\t\tAss::CAssMan* ass_man = Ass::CAssMan::Instance();\r\n\t\t\tif ( ass_man->GetAsset( stream_checksum + reference_checksum, false ) )\r\n\t\t\t{\r\n\t\t\t\tp_tempParams->AddChecksum( NONAME, CRCD(0x93516575,\"play_anim\") );\r\n\t\t\t\tm_lastFamObj = trigger_obj_id;\r\n\t\t\t\t\r\n\t\t\t\t/*Script::CStruct* pTempStruct = new Script::CStruct;\r\n\t\t\t\tpTempStruct->AddChecksum( CRCD(0x7321a8d6,\"type\"), CRCD(0x659bf355,\"partialAnim\") );\r\n\t\t\t\tpTempStruct->AddChecksum( CRCD(0x40c698af,\"id\"), CRCD(0xc0ba0665,\"jawRotation\") );\r\n\t\t\t\t\r\n\t\t\t\t// first we want to kill off any old jaw rotation anims that might be playing...\r\n\t\t\t\t// pAnimComponent->CallMemberFunction( CRCD(0x986d274e,\"RemoveAnimController\"), pTempStruct, NULL );\r\n\t\t\t\t// Script::RunScript( CRCD(0x986d274e,\"RemoveAnimController\"), pTempStruct, p_pos_obj );\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\t\t\tpTempStruct->AddChecksum( CRCD(0x6c2bfb7f,\"animName\"), stream_checksum );\r\n\t\t\t\tpTempStruct->AddChecksum( CRCD(0x46e55e8f,\"from\"), CRCD(0x6086aa70,\"start\") );\r\n\t\t\t\tpTempStruct->AddChecksum( CRCD(0x28782d3b,\"to\"), CRCD(0xff03cc4e,\"end\") );\r\n\t\t\t\t//pTempStruct->AddChecksum( NONAME, CRCD(0x4f792e6c,\"cycle\") );\r\n\t\t\t\tpTempStruct->AddFloat( CRCD(0xf0d90109,\"speed\"), 1.0f );\r\n\t\t\t\t// printf(\"adding animcontroller to %s\\n\", Script::FindChecksumName( trigger_obj_id ) );\r\n\t\t\t\tpAnimComponent->CallMemberFunction( CRCD(0x83654874,\"AddAnimController\"), pTempStruct, NULL );\r\n\t\t\t\t// Script::RunScript( CRCD(0x83654874,\"AddAnimController\"), pTempStruct, p_pos_obj );\r\n\t\t\t\t\r\n\t\t\t\tdelete pTempStruct;*/\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"Couldn't find FAM file '%s'...  is it preloaded?.\\n\", Script::FindChecksumName(stream_checksum) );\r\n\t\t\t}\r\n\t\t}\r\n\t\tScript::CScript* pSpawnedScript = Script::SpawnScript( CRCD(0x5376a011,\"goal_play_stream\"), p_tempParams );\r\n\t\tpSpawnedScript->mpObject = p_pos_obj;\r\n\t\tdelete p_tempParams;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Message( \"WARNING: Could not find pro to associate with goal_play_stream\" );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoalPed::PlayGoalStream( const char* type, Script::CStruct* pParams )\r\n{\r\n\t// Garrett: This function can take over 1 ms to execute when searching for multiple streams.\r\n\t//uint64 start_time = Tmr::GetTimeInUSeconds();\t\r\n\r\n\tif ( m_goalLogicSuspended )\r\n\t\treturn;\r\n\r\n\t// check for any flags\r\n\tbool play_random = pParams->ContainsFlag( CRCD(0x2be2056a,\"play_random\") );\r\n\tbool call_player_by_name = pParams->ContainsFlag( CRCD(0x9f38b332,\"call_player_by_name\") );\r\n\r\n\tbool found_player_name_vo = false;\r\n\r\n\tif ( play_random && call_player_by_name )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, (\"GoalManager_PlayGoalStream called with play_random and call_player_by_name flags\") );\r\n\t}\r\n\r\n\tuint32 stream_checksum;\r\n\tif ( pParams->GetChecksum( CRCD(0x1a4e4fb9,\"vo\"), &stream_checksum, Script::NO_ASSERT ) )\r\n\t{\r\n\t\t// play it!\r\n\t\tPlayGoalStream( stream_checksum );\r\n\t\t//uint64 end_time = Tmr::GetTimeInUSeconds();\t\r\n\t\t//if ((end_time - start_time) > 250)\r\n\t\t//\tDbg_Message(\"PlayGoalStream String 1 Time %d\", (end_time - start_time));\r\n\t\treturn;\r\n\t}\r\n\t// else if ( call_player_by_name )\r\n\telse if ( play_random || call_player_by_name )\r\n\t{\r\n\t\t// check what pro the player is using\r\n\t\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\t\tObj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile();\t\r\n\r\n\t\t// don't play the special vo unless they're using a pro.\r\n\t\tif ( pSkaterProfile->IsPro() )\r\n\t\t{\r\n\t\t\t//uint64 mid_time = Tmr::GetTimeInUSeconds();\t\r\n\r\n\t\t\tconst char* p_speaker_name = GetProFirstName();\r\n\t\t\tchar p_player_name[128];\r\n\t\t\tGetPlayerFirstName( p_player_name, 128 );\r\n\t\t\tchar stream_name[128];\r\n\r\n\t\t\tScript::CArray* p_stream_numbers = new Script::CArray();\r\n\t\t\tp_stream_numbers->SetSizeAndType( vMAXCALLSKATERBYNAMESTREAMS, ESYMBOLTYPE_INTEGER );\r\n\t\t\tfor ( int num = 0; num < vMAXCALLSKATERBYNAMESTREAMS; num++ )\r\n\t\t\t{\r\n\t\t\t\tp_stream_numbers->SetInteger( num, num + 1 );   // stream numbers start at 1, not 0\r\n\t\t\t}\r\n\t\t\tfor ( int i = 0; i < vMAXCALLSKATERBYNAMESTREAMS; i++ )\r\n\t\t\t{\r\n\t\t\t\t// grab a random index and switch with the current index\r\n\t\t\t\tint random_index = Mth::Rnd( vMAXCALLSKATERBYNAMESTREAMS );\r\n\t\t\t\tint random_value = p_stream_numbers->GetInteger( random_index );\r\n\t\t\t\tp_stream_numbers->SetInteger( random_index, p_stream_numbers->GetInteger( i ) );\r\n\t\t\t\tp_stream_numbers->SetInteger( i, random_value );\r\n\t\t\t}\r\n\r\n\t\t\t//uint64 mid2_time = Tmr::GetTimeInUSeconds();\t\r\n\t\t\t// find one!\r\n\t\t\tfor ( int i = 0; i < vMAXCALLSKATERBYNAMESTREAMS; i++ )\r\n\t\t\t{\r\n\t\t\t\tsprintf( stream_name, \"%s_Far%s%02i\", p_speaker_name, p_player_name, i + 1 );\r\n\t\t\t\t\r\n\t\t\t\tif ( Pcm::StreamExists( Script::GenerateCRC( stream_name ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t// printf(\"playing targetpro vo directly: %s\\n\", stream_name);\r\n\t\t\t\t\tfound_player_name_vo = true;\r\n\t\t\t\t\tPlayGoalStream( Script::GenerateCRC( stream_name ) );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\t\t\t\r\n\t\t\t}\r\n\t\t\t//uint64 end_time = Tmr::GetTimeInUSeconds();\t\r\n\t\t\t//if ((end_time - start_time) > 250)\r\n\t\t\t//\tDbg_Message(\"******** PlayGoalStream String 2 Time %d Mid %d Mid2 %d\", (end_time - start_time), (mid2_time - mid_time), (end_time - mid2_time));\r\n\t\t\t\r\n\t\t\t// clean up the array\r\n\t\t\tScript::CleanUpArray( p_stream_numbers );\r\n\t\t\tdelete p_stream_numbers;\r\n\t\t}\r\n\t\t// else\r\n\t\tif ( !found_player_name_vo )\r\n\t\t{\r\n\t\t\t// go ahead and play a random one\r\n\t\t\tcall_player_by_name = false;\r\n\t\t\tplay_random = true;\r\n\t\t}\r\n\t}\r\n\t\r\n\t\r\n\tif ( ( call_player_by_name || play_random ) && !found_player_name_vo )\r\n\t{\r\n\t\tswitch ( Script::GenerateCRC( type ) )\r\n\t\t{\r\n\t\tcase ( CRCC(0x82117c1a,\"wait\") ):\r\n\t\t\tPlayGoalWaitStream();\r\n\t\t\tbreak;\r\n\t\t// case ( CRCC(0x90ff204d,\"Success\") ):\r\n\t\t\t// PlayGoalWinStream();\r\n\t\t\t// break;\r\n\t\tcase ( CRCC(0x1623b689,\"Midgoal\") ):\r\n\t\t\tPlayGoalMidStream();\r\n\t\t\tbreak;\r\n\t\t// case ( CRCC(0x6657a075,\"Talking\") ):\r\n\t\t\t// PlayGoalStartStream();\r\n\t\t\t// break;\r\n\t\tdefault:\r\n\t\t\t//Pcm::StopStreams();\r\n\t\t\tPlayGoalProStream( type, vMAXWAITSTREAMS, false );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t//uint64 end_time = Tmr::GetTimeInUSeconds();\t\r\n\t//if ((end_time - start_time) > 250)\r\n\t//\tDbg_Message(\"PlayGoalStream String 3 Time %d\", (end_time - start_time));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoalPed::PlayGoalStartStream( Script::CStruct* pParams )\r\n{\r\n\tif ( m_goalLogicSuspended )\r\n\t\treturn;\r\n\r\n\t// get goal params\r\n\tScript::CStruct* pGoalParams = GetGoalParams();\r\n\t\r\n\t// K: Added this to prevent an assert when created-goal peds try to play a non-existent stream.\r\n\tif ( pGoalParams->ContainsFlag( CRCD( 0x102a8591, \"no_stream\" ) ) )\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tint cam_anim_index = -1;\r\n\tpParams->GetInteger( CRCD(0x64eee2e6,\"cam_anim_index\"), &cam_anim_index, Script::NO_ASSERT );\r\n\r\n\tconst char* p_speaker_name = NULL;\r\n\tpParams->GetString( CRCD(0x82cbe8d1,\"speaker_name\"), &p_speaker_name, Script::NO_ASSERT );\r\n\r\n\tbool last_anim = pParams->ContainsFlag( CRCD(0xe7f5ff8,\"last_anim\") );\r\n\tbool should_load_fam = false;\r\n\tuint32 stream_checksum;\r\n\tif ( GetStreamChecksum( &stream_checksum, cam_anim_index, false, p_speaker_name, last_anim ) )\r\n\t{\r\n\t\t// load the fam as well.\r\n\t\tshould_load_fam = true;\r\n\t}\r\n\t\r\n\tif ( stream_checksum )\r\n\t{\t\t\r\n\t\t// stop any current vo's\r\n\t\tStopCurrentStream();\r\n\r\n\t\tuint32 speaker_obj_id = 0;\r\n\t\tpParams->GetChecksum( CRCD(0xf0c598fa,\"speaker_obj_id\"), &speaker_obj_id, Script::NO_ASSERT );\r\n\t\tPlayGoalStream( stream_checksum, false, speaker_obj_id, should_load_fam );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalPed::LoadFam( uint32 stream_checksum, uint32 reference_checksum )\r\n{\r\n\tUnloadLastFam();\r\n\tchar p_famName[32];\r\n\tsprintf( p_famName, \"fam\\\\%08x.fam\", stream_checksum );\r\n\t// printf(\"loading %s\\n\", p_famName);\r\n\tAss::CAssMan* ass_man =  Ass::CAssMan::Instance();\r\n\t\r\n\tuint32 old_ref_checksum = ass_man->GetReferenceChecksum();\r\n\tif ( ass_man->LoadAnim( p_famName, stream_checksum, reference_checksum, false, false ) )\r\n\t{\r\n\t\t// printf(\"loaded\\n\");\r\n\t\tm_lastFam = Script::GenerateCRC( p_famName );\r\n\t}\r\n\tass_man->SetReferenceChecksum( old_ref_checksum );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalPed::UnloadLastFam()\r\n{\r\n\tif ( m_lastFam )\r\n\t{\t\t\r\n\t\tif ( m_lastFamObj )\r\n\t\t{\t\t\t\r\n\t\t\tObj::CCompositeObject* p_pos_obj = NULL;\r\n\t\t\tif ( m_lastFamObj == CRCD(0x5b8ab877,\"skater\") )\r\n\t\t\t{\t\t\r\n\t\t\t\t// printf(\"getting skater\\n\");\r\n\t\t\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\t\t\tp_pos_obj = skate_mod->GetLocalSkater();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//p_pos_obj = Obj::CMovingObject::m_hash_table.GetItem( trigger_obj_id );\r\n\t\t\t\t// printf(\"getting ped\\n\");\r\n\t\t\t\tp_pos_obj = (Obj::CCompositeObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID( m_lastFamObj );\r\n\t\t\t}\r\n\r\n\t\t\tScript::StopScriptsUsingThisObject_Proper( p_pos_obj, CRCD(0x5376a011,\"goal_play_stream\") );\r\n\t\t\tScript::CStruct* pTempStruct = new Script::CStruct;\r\n\t\t\tpTempStruct->AddChecksum( CRCD(0x7321a8d6,\"type\"), CRCD(0x659bf355,\"partialAnim\") );\r\n\t\t\tpTempStruct->AddChecksum( CRCD(0x40c698af,\"id\"), CRCD(0xc0ba0665,\"jawRotation\") );\r\n\r\n\t\t\t// first we want to kill off any old jaw rotation anims that might be playing...\t\t\r\n\t\t\tif ( p_pos_obj )\r\n\t\t\t{\r\n\t\t\t\t// printf(\"removing animcontroller\\n\");\r\n\t\t\t\tObj::CAnimationComponent* pAnimComponent = GetAnimationComponentFromObject( p_pos_obj );\r\n\t\t\t\tDbg_Assert( pAnimComponent );\r\n\t\t\t\tpAnimComponent->CallMemberFunction( CRCD(0x986d274e,\"RemoveAnimController\"), pTempStruct, NULL );\t\t\t\t\r\n\t\t\t}\r\n\t\t\tdelete pTempStruct;\r\n\t\t\tm_lastFamObj = 0;\r\n\t\t}\r\n\r\n\t\t// get the assman\r\n\t\tAss::CAssMan * ass_man = Ass::CAssMan::Instance();\r\n\r\n\t\tAss::CAsset* pAsset = ass_man->GetAssetNode( m_lastFam, false );\r\n\r\n\t\tif ( pAsset )\r\n\t\t{\r\n\t\t\t// printf(\"unloading fam\\n\");\r\n\t\t\tass_man->DestroyReferences( pAsset );\r\n\t\t\tass_man->UnloadAsset( pAsset );\r\n\t\t\tScript::RunScript( CRCD( 0xb3dce47f, \"invalidate_anim_cache\" ) );\r\n\t\t}\r\n\t\tm_lastFam = 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalPed::StopLastStream()\r\n{\r\n\tif ( m_lastStreamId )\r\n\t{\r\n\t\tif ( m_lastFamObj )\r\n\t\t{\t\t\t\r\n\t\t\tObj::CCompositeObject* p_pos_obj = NULL;\r\n\t\t\tif ( m_lastFamObj == CRCD(0x5b8ab877,\"skater\") )\r\n\t\t\t{\t\t\r\n\t\t\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\t\t\tp_pos_obj = skate_mod->GetLocalSkater();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_pos_obj = (Obj::CCompositeObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID( m_lastFamObj );\r\n\t\t\t}\r\n\t\t\tScript::StopScriptsUsingThisObject_Proper( p_pos_obj, CRCD(0x5376a011,\"goal_play_stream\") );\r\n\t\t}\r\n\t\tPcm::StopStreamFromID( m_lastStreamId );\r\n\t\tm_lastStreamId = 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalPed::PlayGoalWaitStream()\r\n{\r\n\tif ( m_goalLogicSuspended )\r\n\t\treturn;\r\n\r\n\tPlayGoalProStream( \"Far\", vMAXWAITSTREAMS, true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalPed::PlayGoalWinStream( Script::CStruct* pParams )\r\n{\r\n\tif ( m_goalLogicSuspended )\r\n\t\treturn;\r\n\r\n\t// get params\r\n\tconst char* p_speaker_name = NULL;\r\n\tpParams->GetString( CRCD(0x82cbe8d1,\"speaker_name\"), &p_speaker_name, Script::NO_ASSERT );\r\n\t// int cam_anim_index = -1;\r\n\t// pParams->GetInteger( CRCD(0x64eee2e6,\"cam_anim_index\"), &cam_anim_index, Script:::NO_ASSERT );\r\n\t// bool last_anim = pParams->ContainsFlag( CRCD(0xe7f5ff8,\"last_anim\") );\r\n\r\n\tuint32 stream_checksum;\r\n\tbool should_load_fam = false;\r\n\r\n\tif ( GetStreamChecksum( &stream_checksum, -1, true, p_speaker_name, true ) )\r\n\t{\r\n\t\tshould_load_fam = true;\r\n\t}\r\n\r\n\tuint32 speaker_obj_id = 0;\r\n\tpParams->GetChecksum( CRCD(0xf0c598fa,\"speaker_obj_id\"), &speaker_obj_id, Script::NO_ASSERT );\r\n\t\r\n\tif ( stream_checksum )\r\n\t\tPlayGoalStream( stream_checksum, false, speaker_obj_id, should_load_fam );\r\n\t// else\r\n\t\t// PlayGoalProStream( \"Success\", vMAXWINSTREAMS, false, false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalPed::PlayGoalMidStream()\r\n{\r\n\tif ( m_goalLogicSuspended )\r\n\t\treturn;\r\n\tPlayGoalProStream( \"Midgoal\", vMAXMIDGOALSTREAMS, false );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalPed::PlayGoalProStream( const char* p_stream_type, int max_number_streams, bool use_player_name, bool use_pos_info )\r\n{\r\n\tDbg_MsgAssert( p_stream_type, (\"PlayGoalProStream called without stream type\") );\r\n\tDbg_MsgAssert( max_number_streams, (\"PlayGoalProStream called without stream type\") );\r\n\t\r\n\tif ( m_goalLogicSuspended )\r\n\t\treturn;\r\n\t\r\n\t// stop any current vo's\r\n\tStopCurrentStream();\r\n\t\r\n\t// get the first name of the speaker and the player\r\n\tconst char* p_speaker_name = GetProFirstName();\r\n\tif ( !p_speaker_name )\r\n\t\treturn;\r\n\t\r\n\t// check what pro the player is using\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile();\t\r\n\t\r\n\tconst char* p_current_pro_name;\r\n\tp_current_pro_name = pSkaterProfile->GetDisplayName();\r\n\t\r\n\tchar p_player_name[128];\r\n\tparse_first_name( p_player_name, &p_current_pro_name, 128 );\r\n\tDbg_MsgAssert( strlen( p_player_name ) > 0, ( \"No player name found\" ) );\r\n\t// printf(\"got a first name of %s\\n\", p_player_name);\r\n\t\r\n\t// create an array of all possible stream numbers\r\n\tint num_possible_streams = max_number_streams;\r\n\r\n\tif ( use_player_name )\r\n\t\t// there are x wait streams plus 20 possible streams directed specifically at the player (\"Hey, tony!\")\r\n\t\tnum_possible_streams += 20;\r\n\r\n\tScript::CArray* p_stream_numbers = new Script::CArray();\r\n\tp_stream_numbers->SetSizeAndType( num_possible_streams, ESYMBOLTYPE_INTEGER );\r\n\tfor ( int num = 0; num < num_possible_streams; num++ )\r\n\t{\r\n\t\tp_stream_numbers->SetInteger( num, num + 1 );   // stream numbers start at 1, not 0\r\n\t}\r\n\tfor ( int i = 0; i < num_possible_streams; i++ )\r\n\t{\r\n\t\t// grab a random index and switch with the current index\r\n\t\tint random_index = Mth::Rnd( num_possible_streams );\r\n\t\tint random_value = p_stream_numbers->GetInteger( random_index );\r\n\t\tp_stream_numbers->SetInteger( random_index, p_stream_numbers->GetInteger( i ) );\r\n\t\tp_stream_numbers->SetInteger( i, random_value );\r\n\t}\r\n\r\n\t// go through until we find the first valid stream\r\n\t// uint32 current_vo_stream = 0;\r\n\tfor ( int i = 0; i < num_possible_streams; i++ )\r\n\t{\r\n\t\tint stream_number = p_stream_numbers->GetInteger( i );\r\n\t\t// printf( \"got a stream number of %i\\n\", stream_number );\r\n\t\tchar stream_name[128];\r\n\r\n\t\t// check if this is the special \"hey tony\" type stream number\r\n\t\tif ( ( stream_number > max_number_streams ) )\r\n\t\t{\r\n\t\t\t// don't play the special vo unless they're using a pro.\r\n\t\t\tif ( pSkaterProfile->IsPro() )\r\n\t\t\t{\r\n\t\t\t\t// offset the stream number.\r\n\t\t\t\tstream_number -= max_number_streams;\r\n\t\t\t\tsprintf( stream_name, \"%s_%s%s%02i\", p_speaker_name, p_stream_type, p_player_name, stream_number );\r\n\t\t\t\t// printf(\"figured a special vo of %s\\n\", stream_name);\r\n\t\t\t\tif ( Pcm::StreamExists( Script::GenerateCRC( stream_name ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tPlayGoalStream( Script::GenerateCRC( stream_name ), use_pos_info );\r\n\t\t\t\t\t// current_vo_stream = Pcm::PlayStream( Script::GenerateCRC( stream_name ), 100, 100 );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsprintf( stream_name, \"%s_%s%02i\", p_speaker_name, p_stream_type, stream_number );\r\n\t\t\t// printf(\"figured vo: %s\\n\", stream_name);\r\n\t\t\tif ( Pcm::StreamExists( Script::GenerateCRC( stream_name ) ) )\r\n\t\t\t{\r\n\t\t\t\tPlayGoalStream( Script::GenerateCRC( stream_name ), use_pos_info );\r\n\t\t\t\t// current_vo_stream = Pcm::PlayStream( Script::GenerateCRC( stream_name ), 100, 100 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tScript::CleanUpArray( p_stream_numbers );\r\n\tdelete p_stream_numbers;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CGoalPed::StopCurrentStream()\r\n{\r\n\t// get params\r\n\tScript::CStruct* pParams = GetGoalParams();\r\n\r\n\tuint32 current_vo_stream = 0;\r\n\tif ( pParams->GetChecksum( CRCD(0xdc14d454,\"current_vo_stream\"), &current_vo_stream, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tpParams->RemoveComponent( CRCD(0xdc14d454,\"current_vo_stream\") );\r\n\t\tif ( current_vo_stream )\r\n\t\t\tPcm::StopStreamFromID( current_vo_stream );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CGoalPed::ProIsCurrentSkater()\r\n{\r\n\t// get params\r\n\tScript::CStruct* pParams = GetGoalParams();\r\n\t\r\n\t// are they using the right skater?\r\n\tScript::CStruct* p_last_names = Script::GetStructure( CRCD(0x621d1828,\"goal_pro_last_name_checksums\"), Script::ASSERT );\r\n\tconst char* first_name_string;\r\n\tpParams->GetString( CRCD(0x4a91eceb,\"pro_challenge_pro_name\"), &first_name_string, Script::ASSERT );\r\n\tuint32 last_name;\r\n\tp_last_names->GetChecksum( Script::GenerateCRC( first_name_string ), &last_name, Script::ASSERT );\r\n\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CPlayerProfileManager* pProfileManager = skate_mod->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pSkaterProfile = pProfileManager->GetCurrentProfile();\r\n\tuint32 current_skater = pSkaterProfile->GetSkaterNameChecksum();\r\n\r\n\treturn ( current_skater == last_name );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CGoalPed::GetGoalAnimations( const char* type )\r\n{\r\n\t// get params\r\n\tScript::CStruct* pParams = GetGoalParams();\r\n\t\r\n\tuint32 array_name = 0;\r\n\t\r\n\t// check for specific goal animation\r\n\tchar goal_specific_array_name[128];\r\n\tconst char* p_goal_name;\r\n\tpParams->GetString( CRCD(0xbfecc45b,\"goal_name\"), &p_goal_name, Script::ASSERT );\r\n\tsprintf( goal_specific_array_name, \"%s_%s\", p_goal_name, type );\r\n\tif ( ( Script::GetArray( goal_specific_array_name, Script::NO_ASSERT ) ) )\r\n\t{\r\n\t\t// printf(\"got a specific array name of %s\\n\", p_goal_specific_array_name );\r\n\t\tarray_name = Script::GenerateCRC( goal_specific_array_name );\r\n\t}\r\n\telse if ( type )\r\n\t{\r\n\t\t// build the name of the pro's generic anims array\r\n\t\tconst char* p_pro_name = GetProFirstName();\r\n\t\tchar pro_array_name[128];\r\n\t\tsprintf( pro_array_name, \"%s_goal_%s\", p_pro_name, type );\r\n\r\n\t\tif ( ( Script::GetArray( pro_array_name, Script::NO_ASSERT ) ) )\r\n\t\t{\r\n\t\t\t// pro's generic array\r\n\t\t\t// printf(\"got generic pro array: %s\\n\", pro_array_name );\r\n\t\t\tarray_name = Script::GenerateCRC( pro_array_name );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// get the generic anim array\r\n\t\t\tchar generic_array_name[128];\r\n\t\t\tsprintf( generic_array_name, \"generic_pro_anims_%s\", type );\r\n\t\t\t// printf(\"looking for array: %s\\n\", generic_array_name);\r\n\t\t\tif ( !Script::GetArray( generic_array_name, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\t Dbg_MsgAssert( 0, (\"Unable to find generic pro array '%s'\",generic_array_name) );\r\n\t\t\t}\r\n\t\t\tarray_name = Script::GenerateCRC( generic_array_name );\r\n\t\t}\r\n\t}\r\n\treturn array_name;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalPed::DestroyGoalPed()\r\n{\r\n\t// get params\r\n\tScript::CStruct* pParams = GetGoalParams();\r\n\t\r\n\tuint32 trigger_obj_id = 0;\r\n\r\n\tpParams->GetChecksum( CRCD(0x02d7e03d,\"trigger_obj_id\"), &trigger_obj_id );\r\n\tif( trigger_obj_id )\r\n\t{\r\n\t\tObj::CCompositeObject* p_pos_obj = NULL;\r\n\t\t//p_pos_obj = Obj::CMovingObject::m_hash_table.GetItem( trigger_obj_id );\r\n\t\tp_pos_obj = (Obj::CCompositeObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID( trigger_obj_id);\r\n\t\t\r\n\t\tif( p_pos_obj )\r\n\t\t{\r\n\t\t\tdelete p_pos_obj;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalPed::SuspendGoalLogic( bool suspend )\r\n{\r\n\tm_goalLogicSuspended = suspend;\r\n\r\n\tif ( suspend )\r\n\t{\r\n\t\tScript::RunScript( CRCD(0xbf67a3cf,\"goal_pro_stop_anim_scripts\"), GetGoalParams() );\r\n\t\tStopCurrentStream();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CGoalPed::Hide( bool hide )\r\n{\r\n\t// get params\r\n\tScript::CStruct* pParams = GetGoalParams();\r\n\t\r\n\tif ( pParams->ContainsFlag( CRCD( 0x3d1cab0b, \"null_goal\" ) ) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tuint32 trigger_obj_id = 0;\r\n\r\n\tpParams->GetChecksum( CRCD(0x02d7e03d,\"trigger_obj_id\"), &trigger_obj_id );\r\n\tif ( trigger_obj_id )\r\n\t{\r\n\t\tObj::CCompositeObject* p_pos_obj = NULL;\r\n\t\t//p_pos_obj = Obj::CMovingObject::m_hash_table.GetItem( trigger_obj_id );\r\n\t\tp_pos_obj = (Obj::CCompositeObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID( trigger_obj_id );\r\n\t\t\r\n\t\tif ( p_pos_obj )\r\n\t\t{\r\n\t\t\tp_pos_obj->Hide( hide );\r\n\t\t}\r\n\r\n\t\t// kill/create arrow\r\n\t\tScript::CStruct* pTempParams = new Script::CStruct();\r\n\t\tpTempParams->AddChecksum( CRCD(0x9982e501,\"goal_id\"), m_goalId );\r\n\t\tif ( hide )\r\n\t\t\tScript::RunScript( CRCD(0x6d39f2f3,\"goal_ped_kill_arrow\"), pTempParams );\r\n\t\telse\r\n\t\t{\r\n\t\t\t// check if this goal has been beaten...hack for mike v special goal\r\n\t\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\t\tDbg_Assert( pGoalManager );\r\n\t\t\tCGoal* pGoal = pGoalManager->GetGoal( m_goalId, false );\r\n\t\t\tbool should_add_arrow = true;\r\n\t\t\tif ( pGoal && pGoal->HasWonGoal() )\r\n\t\t\t\tshould_add_arrow = false;\r\n\t\t\t\r\n\t\t\tif ( should_add_arrow )\r\n\t\t\t\tScript::RunScript( CRCD(0x6ea4d309,\"goal_add_ped_arrow\"), pTempParams );\r\n\t\t}\r\n\t\tdelete pTempParams;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* CGoalPed::GetGoalParams()\r\n{\r\n\tCGoalManager* pGoalManager = Game::GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\treturn pGoalManager->GetGoalParams( m_goalId );\r\n}\r\n\r\n}\t// namespace Game\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/GoalPed.h",
    "content": "// goal ped!\r\n\r\n#ifndef __MODULES_SKATE_GOALPED_H\r\n#define __MODULES_SKATE_GOALPED_H\r\n\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/modules/skate/goal.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/struct.h>\r\n\r\nnamespace Game\r\n{\r\n\r\nconst uint32\tMAX_STREAM_NAME_LENGTH = 256;\r\n\t\r\nclass CGoalPed\r\n{\r\npublic:\r\n\tCGoalPed( Script::CStruct* pParams );\r\n\t~CGoalPed();\r\n\t\r\n\tvoid\t\t\t\tDestroyGoalPed();\r\n\t\r\n\tvoid\t\t \t\tGetPlayerFirstName( char* p_first_name, int buffer_size );\r\n\tconst char*\t\t\tGetProFirstName();\r\n\tbool\t\t\t\tGetStreamChecksum( uint32* p_streamChecksum, int cam_anim_index = -1, bool success = false, const char* p_speaker_name = NULL, bool last_anim = false);\r\n\tvoid\t\t\t\tLoadFam( uint32 stream_checksum, uint32 reference_checksum );\r\n\tvoid\t\t\t\tUnloadLastFam();\r\n\tvoid\t\t\t\tStopLastStream();\r\n\tvoid\t\t\t\tPlayGoalStream( uint32 stream_checksum, bool use_pos_info = true, uint32 speaker_obj_id = 0, bool should_load_fam = false );\r\n\tvoid\t\t\t\tPlayGoalStream( const char* type, Script::CStruct* pParams );\r\n\tvoid\t\t\t\tPlayGoalStartStream( Script::CStruct* pParams );\r\n\tvoid\t\t\t\tStopCurrentStream();\r\n\tvoid\t\t\t\tPlayGoalProStream( const char* p_stream_type, int max_number_streams, bool use_player_name, bool use_pos_info = true );\r\n\tvoid\t\t\t\tPlayGoalWinStream( Script::CStruct* pParams );\r\n\tvoid\t\t\t\tPlayGoalWaitStream();\r\n\tvoid\t\t\t\tPlayGoalMidStream();\r\n\r\n\tuint32\t\t\t\tGetGoalAnimations( const char* type );\r\n\r\n\tbool\t\t\t\tProIsCurrentSkater();\r\n\r\n\tvoid\t\t\t\tSuspendGoalLogic( bool suspend = true );\r\n\r\n\tScript::CStruct*\tGetGoalParams();\r\n\r\n\tvoid\t\t\t\tHide( bool hide );\r\nprotected:\r\n\tuint32\t\t\t\tm_goalId;\r\n\tbool\t\t\t\tm_goalLogicSuspended;\r\n\tuint32\t\t\t\tm_lastFam;\r\n\tuint32\t\t\t\tm_lastFamObj;\r\n\tuint32\t\t\t\tm_lastStreamId;\r\n};\r\n\r\n\r\n} // namespace Game\r\n\r\n#endif // __MODULES_SKATE_GOALPED_H\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/HorseGoal.cpp",
    "content": "// horse goal subclass\r\n\r\n#include <sk/modules/skate/GoalManager.h>\r\n#include <sk/modules/skate/HorseGoal.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/score.h>\r\n\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n\r\n#include <sk/objects/skater.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCHorseGoal::CHorseGoal( Script::CStruct* pParams ) : CGoal( pParams )\r\n{\r\n\t// nothing special\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCHorseGoal::~CHorseGoal()\r\n{\r\n\t// nothing yet\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CHorseGoal::CheckScore()\r\n{\r\n\t// get the right flag\r\n\tScript::CArray* pHorseSpots;\r\n\tmp_params->GetArray( \"horse_spots\", &pHorseSpots, Script::ASSERT );\r\n\r\n\tint size = pHorseSpots->GetSize();\r\n\tint i;\r\n\tint score;\r\n\tuint32 flag;\r\n\tfor ( i = 0; i < size; i++ )\r\n\t{\r\n\t\tScript::CStruct* pSpot = pHorseSpots->GetStructure( i );\r\n\t\tpSpot->GetChecksum( \"flag\", &flag, Script::ASSERT );\r\n\t\tint flag_value;\r\n\t\tmp_goalFlags->GetInteger( flag, &flag_value, Script::ASSERT );\r\n\t\t\r\n\t\t// find the first unset flag\r\n\t\tif ( flag_value == 0 )\r\n\t\t{\r\n\t\t\tif ( !pSpot->GetInteger( \"score\", &score, Script::NO_ASSERT ) )\r\n\t\t\t\tmp_params->GetInteger( \"score\", &score, Script::ASSERT );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// make sure they're not all set...\r\n\tif ( i == size )\r\n\t\treturn;\r\n\r\n\t// check the score\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = skate_mod->GetLocalSkater();\r\n\tMdl::Score* pScore = pSkater->GetScoreObject();\r\n\r\n\tint last_score_landed = pScore->GetLastScoreLanded();\r\n\tif ( last_score_landed > 0 )\r\n\t{\r\n\t\tuint32 goalId = GetGoalId();\r\n\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\tif ( last_score_landed > score )\r\n\t\t{\t\t\t\r\n\t\t\tpGoalManager->SetGoalFlag( goalId, flag, 1 );\r\n\t\t\tpGoalManager->NextTourSpot( goalId );\r\n\t\t}\r\n\t\telse\r\n\t\t\tpGoalManager->LoseGoal( goalId );\r\n\t}\r\n\tmp_params->AddInteger( \"should_check_trick\", 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CHorseGoal::ShouldExpire()\r\n{\r\n\tint should_check_trick = 0;\r\n\tmp_params->GetInteger( \"should_check_trick\", &should_check_trick, Script::ASSERT );\r\n\r\n\tif ( should_check_trick == 1 )\r\n\t\treturn false;\r\n\t\r\n\treturn CGoal::ShouldExpire();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CHorseGoal::IsExpired()\r\n{\r\n\tint should_check_trick = 0;\r\n\tmp_params->GetInteger( \"should_check_trick\", &should_check_trick, Script::ASSERT );\r\n\r\n\tif ( should_check_trick == 1 )\r\n\t\treturn false;\r\n\t\r\n\treturn CGoal::IsExpired();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid CHorseGoal::Expire()\r\n{\r\n\tCGoal::Expire();\r\n}\r\n\r\n}\t// namespace Game\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/HorseGoal.h",
    "content": "// horse goal subclass\r\n#ifndef __SK_MODULES_SKATE_HORSEGOAL_H__\r\n#define __SK_MODULES_SKATE_HORSEGOAL_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <sk/modules/skate/GoalManager.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n\r\nclass CHorseGoal : public CGoal\r\n{\r\n\r\npublic:\r\n\t\t\t\t\tCHorseGoal( Script::CStruct* pParams );\r\n\tvirtual\t\t\t~CHorseGoal();\r\n\t\r\n\tvoid\t\t\tCheckScore();\r\n\tbool\t\t\tShouldExpire();\r\n\tbool\t\t\tIsExpired();\r\n\tvoid\t\t\tExpire();\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/Minigame.cpp",
    "content": "#include <core/defines.h>\r\n\r\n#include <sk/modules/skate/Minigame.h>\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/scripting/skfuncs.h>\r\n#include <sk/scripting/Nodearray.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <gfx/2D/ScreenElemMan.h>       // for minigame timer\r\n#include <gfx/2D/ScreenElement2.h>\r\n#include <gfx/2D/TextElement.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCMinigame::CMinigame( Script::CStruct* pParams ) : CGoal( pParams )\r\n{\r\n\tScript::CArray *pGeomArray;\r\n\r\n\t// Create the associated pieces of geometry\r\n    if ( pParams->GetArray( \"create_geometry\", &pGeomArray ) )\r\n    {\r\n\t\tuint32 i, geometry;\r\n\r\n\t\tfor( i = 0; i < pGeomArray->GetSize(); i++ )\r\n        {\r\n            geometry = pGeomArray->GetChecksum( i );\r\n\t\t\tCFuncs::ScriptCreateFromNodeIndex( SkateScript::FindNamedNode( geometry ));\r\n        }\r\n\t}\r\n\t\r\n\tm_record = 0;\r\n\tm_cashLimit = 0;\r\n\tpParams->GetInteger( \"cash_limit\", &m_cashLimit, Script::NO_ASSERT );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nCMinigame::~CMinigame()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CMinigame::Activate()\r\n{\r\n\tif ( !IsActive() && ShouldUseTimer() )\r\n\t{\r\n\t\tCGoalManager* pGoalManager = Game::GetGoalManager();\r\n\t\tDbg_Assert( pGoalManager );\r\n\t\tpGoalManager->DeactivateMinigamesWithTimer();\r\n\t}\r\n\treturn CGoal::Activate();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CMinigame::Update()\r\n{\r\n\tif ( IsActive() && ShouldUseTimer() )\r\n\t{\r\n\t\tUpdateMinigameTimer();\r\n\t}\r\n\treturn CGoal::Update();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CMinigame::ShouldUseTimer()\r\n{\r\n\treturn ( mp_params->ContainsComponentNamed( \"time\" ) );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n// this is used for minigames that have their own timer.\r\nvoid CMinigame::UpdateMinigameTimer()\r\n{\r\n\treturn;\r\n/*\t\r\n\tFront::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();\r\n\r\n\tTmr::Time time_left = m_timeLeft / 1000;\t\t\r\n\tif( time_left < 1 )\r\n\t\ttime_left = 0;\r\n\t\r\n\tint seconds = time_left % 60;\r\n\tint minutes = time_left / 60;\r\n\t\t\r\n\tFront::CScreenElementPtr p_element = p_screen_elem_man->GetElement( CRCD( 0xcd9671b4, \"minigame_timer\") );\r\n\tif (p_element)\r\n\t{\r\n\t\tDbg_MsgAssert(p_element->GetType() == CRCD(0x5200dfb6, \"TextElement\"), (\"type is 0x%x\", p_element->GetType()));\r\n\t\tFront::CTextElement *p_time_element = (Front::CTextElement *) p_element.Convert();\r\n\t\r\n\t\tchar time_text[128];\r\n\t\tsprintf(time_text, \"%2d:%.2d\", minutes, seconds);\r\n\t\t\r\n\t\t// get the description if there is one\r\n\t\tconst char* timer_description;\r\n\t\tif ( mp_params->GetString( CRCD( 0xe1fc4f74, \"timer_description\" ), &timer_description, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tstrcat( time_text, \" \" );\r\n\t\t\tstrcat( time_text, timer_description );\r\n\t\t}\r\n\t\tp_time_element->SetText(time_text);\r\n\t}\r\n*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CMinigame::IsExpired()\r\n{\r\n\treturn ( ShouldUseTimer() && ( (int)m_timeLeft <= 0 ) );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CMinigame::CheckRecord( int value )\r\n{\r\n\tif ( value > m_record )\r\n\t{\r\n\t\tm_record = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CMinigame::AddTime( int amount )\r\n{\r\n\tif ( IsActive() )\r\n\t{\r\n\t\tm_timeLeft += (Tmr::Time)( amount * 1000 );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nint CMinigame::GetRecord()\r\n{\r\n\tmp_params->AddInteger( \"minigame_record\", m_record );\r\n\treturn m_record;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CMinigame::CanRetry()\r\n{\r\n\t// you cannot retry minigames - ie, they don't show up \r\n\t// on the pause menu as \"Retry last goal\"\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMinigame::LoadSaveData( Script::CStruct*  pFlags )\r\n{\r\n\t// minigame record\r\n\tint minigame_record;\r\n\tpFlags->GetInteger( \"minigame_record\", &minigame_record, Script::NO_ASSERT );\r\n\tif ( minigame_record != -1 )\r\n\t{\r\n\t\t// this will check and set the record\r\n\t\tCheckMinigameRecord( minigame_record );\r\n\t}\r\n\r\n\tint cash_limit;\r\n\tif ( pFlags->GetInteger( \"cash_limit\", &cash_limit, Script::NO_ASSERT ) )\r\n\t\tm_cashLimit = cash_limit;\r\n\tCGoal::LoadSaveData( pFlags );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMinigame::GetSaveData( Script::CStruct* pFlags )\r\n{\r\n\tint minigame_record = GetMinigameRecord();\r\n\tpFlags->AddInteger( \"minigame_record\", minigame_record );\r\n\tpFlags->AddInteger( \"cash_limit\", m_cashLimit );\r\n\tCGoal::GetSaveData( pFlags );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMinigame::AwardCash( int amount )\r\n{\r\n\tif ( m_cashLimit <= 0 )\r\n\t{\r\n\t\tScript::RunScript( \"minigame_cash_depleted\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// clamp it\r\n\tif ( amount > m_cashLimit )\r\n\t\tamount = m_cashLimit;\r\n\r\n\tCGoalManager* pGoalManager = GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tif ( pGoalManager )\r\n\t{\r\n\t\tpGoalManager->AddCash( amount );\r\n\t\tm_cashLimit -= amount;\r\n\t\tScript::CStruct* pScriptParams = new Script::CStruct();\r\n\t\tpScriptParams->AddInteger( \"amount\", amount );\r\n\t\tScript::RunScript( \"minigame_got_cash\", pScriptParams );\r\n\t\tdelete pScriptParams;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/Minigame.h",
    "content": "#ifndef __SK_MODULES_SKATE_MINIGAME_H__\r\n#define __SK_MODULES_SKATE_MINIGAME_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <sk/modules/skate/GoalManager.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n\r\nclass CMinigame : public CGoal\r\n{\r\n\r\npublic:\t\t\t\t\t\t\r\n\t\t\t\t\tCMinigame( Script::CStruct* pParams );\r\n\tvirtual\t\t\t~CMinigame();\r\n\r\n\tbool\t\t\tActivate();\r\n\r\n\tvoid\t\t\tLoadSaveData( Script::CStruct* pFlags );\r\n\tvoid\t\t\tGetSaveData( Script::CStruct* pFlags );\r\n\t\r\n\tbool\t\t\tShouldUseTimer();\r\n\tbool\t\t\tAddTime( int amount );\r\n\tbool\t\t\tCountAsActive() { return false; }\r\n\tbool\t\t\tIsExpired();\r\n\tbool\t\t\tCheckRecord( int value );\r\n\tint\t\t\t\tGetRecord();\r\n\tbool\t\t\tCanRetry();\r\n\tvoid\t\t\tSetStartTime();\r\n\tvoid\t\t\tUpdateTimer();\r\n\r\n\tbool\t\t\tUpdate();\r\n\tvoid\t\t\tUpdateMinigameTimer();\r\n\r\n\tbool\t\t\tAwardCash( int amount );\r\n\r\nprotected:\r\n\tint\t\t\t\tm_record;\r\n\tint\t\t\t\tm_cashLimit;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/NetGoal.cpp",
    "content": "#include <sk/objects/skater.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/victorycond.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/modules/skate/GoalManager.h>\r\n#include <sk/modules/skate/NetGoal.h>\r\n#include <sk/components/skaterendruncomponent.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n\r\nnamespace Game\r\n{\r\n\r\nCNetGoal::CNetGoal( Script::CStruct* pParams ) : CGoal( pParams )\r\n{\r\n\tm_endRunType = vENDOFRUN;\r\n\tm_initialized = false;\r\n}\r\n\r\nCNetGoal::~CNetGoal()\r\n{\r\n\t// nothing yet\r\n}\r\n\r\nbool CNetGoal::Update()\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tif ( !m_initialized )\r\n\t{\r\n\t\tInit();\r\n\t\tm_initialized = true;\r\n\t}\r\n\r\n\tif( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netgoalattack\" ))\r\n\t{\r\n\t\tif( GoalAttackComplete())\r\n\t\t{\r\n\t\t\tif( IsActive())\r\n\t\t\t{\r\n\t\t\t\tExpire();\r\n\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn CGoal::Update();\r\n}\r\n\r\nbool CNetGoal::Activate( void )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->ClearGameOver();\r\n\r\n\treturn CGoal::Activate();\r\n}\r\n\r\nbool CNetGoal::Deactivate( bool force, bool affect_tree )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tif( force == false )\r\n\t{\r\n\t\tif( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netgoalattack\" ))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn CGoal::Deactivate( force, affect_tree );\r\n}\r\n\r\nbool CNetGoal::IsExpired()\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tif( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netgoalattack\" ))\r\n\t{\r\n\t\treturn GoalAttackComplete() && AllSkatersAtEndOfRun();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tGameNet::PlayerInfo* player;\r\n\t\tLst::Search< GameNet::PlayerInfo > sh;\r\n\t\r\n\t\t// If no players are left, the goal should expire\r\n\t\tif( gamenet_man->GetNumPlayers() == 0 )\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"IsExpired: 1\\n\" );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\t\t\t\t\t\r\n\t\t// If it's an unlimited game, don't expire the goal\r\n\t\tif ( m_unlimitedTime )\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"IsExpired: 2\\n\" );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\r\n\t\tif( ( gamenet_man->HaveReceivedFinalScores() == false ) && \r\n\t\t\t( gamenet_man->InNetGame()))\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"IsExpired: 3\\n\" );\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// if we're not supposed to use end of run, we need only check\r\n\t\t// the time\r\n\t\tif ( m_endRunType == vNONE )\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"Timeleft: %d\\n\", (int) m_timeLeft );\r\n\t\t\treturn ( (int)m_timeLeft <= 0 );\r\n\t\t}\r\n\t\r\n\t\t// check if the skaters have reached end of run BEFORE\r\n\t\t// setting the exception, or you'll never catch it!\r\n\t\tif ( AllSkatersAtEndOfRun() && (int)m_timeLeft <= 0 )\r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"IsExpired: 4\\n\" );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\r\n\t\t// reset all players' scores\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tObj::CSkater *p_Skater = player->m_Skater;\r\n\t\t\tDbg_Assert( p_Skater );\r\n\r\n\t\t\tObj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(p_Skater);\r\n\t\t\tDbg_Assert( p_skater_endrun_component );\r\n\r\n\t\t\tif( p_skater_endrun_component->RunHasEnded() || p_Skater->IsPaused())\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t// if time is up, set the end of run exception\r\n\t\t\t// if ( m_shouldEndRun && !m_endRunCalled && (int)m_timeLeft <= 0 )\r\n\t\t\tif ( m_endRunType != vNONE && (int)m_timeLeft <= 0 )\r\n\t\t\t{\r\n\t\t\t\tm_endRunCalled = true;\r\n\t\t\t\t//Dbg_Printf( \"EXPIRING GOAL: %d\\n\", GetGoalId());\r\n\t\t\t\t// printf(\"calling EndRun\\n\");\r\n\t\t\t\tp_skater_endrun_component->EndRun();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t//Dbg_Printf( \"IsExpired: 6 : %d\\n\", gamenet_man->GameIsOver());\r\n\t\treturn gamenet_man->GameIsOver();\r\n\r\n\t}\r\n}\r\n\r\nvoid\tCNetGoal::Expire( void )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->MarkGameOver();\r\n\treturn CGoal::Expire();\r\n}\r\n\r\n}\t// namespace Game\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/NetGoal.h",
    "content": "#ifndef __SK_MODULES_SKATE_NETGOAL_H__\r\n#define __SK_MODULES_SKATE_NETGOAL_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <sk/modules/skate/GoalManager.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n\r\nclass CNetGoal : public CGoal\r\n{\r\n\r\npublic:\r\n\t\t\t\t\tCNetGoal( Script::CStruct* pParams );\r\n\tvirtual\t\t\t~CNetGoal();\r\n\t\r\n\tbool\t\t\tUpdate();\r\n\tbool\t\t\tDeactivate( bool force = false, bool affect_tree = true );\r\n\tbool\t\t\tActivate();\r\n\tbool\t\t\tIsExpired();\r\n\tvoid\t\t\tExpire();\r\n\r\nprotected:\r\n\tbool\t\t\tm_initialized;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/RaceGoal.cpp",
    "content": "#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/modules/skate/racegoal.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n\r\nCRaceGoal::CRaceGoal( Script::CStruct* pParams ) : CGoal( pParams )\r\n{\r\n\t// nothing yet\r\n}\r\n\r\nCRaceGoal::~CRaceGoal()\r\n{\r\n\t// nope\r\n}\r\n\r\nbool CRaceGoal::ShouldExpire()\r\n{\r\n\tif ( !m_unlimitedTime && (int)m_timeLeft <= 0)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool CRaceGoal::IsExpired()\r\n{\r\n\tif ( !m_unlimitedTime && (int)m_timeLeft <= 0)\r\n\t{\r\n\t\tCGoal::IsExpired();\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid CRaceGoal::Expire()\r\n{\r\n\tRunCallbackScript( vEXPIRED );\r\n\tDeactivate();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nbool CRaceGoal::NextRaceWaypoint( uint32 goalId )\r\n{\r\n    if ( IsExpired() )\r\n\t{\r\n\t\tprintf(\"expired!\\n\");\r\n\t\treturn false;\r\n\t}\r\n\tScript::CArray* p_waypoints;\r\n    mp_params->GetArray( \"race_waypoints\", &p_waypoints, Script::ASSERT );\r\n\r\n    Script::CStruct* p_waypoint;\r\n    for ( uint32 i = 0; i < p_waypoints->GetSize(); i++ )\r\n    {\r\n        p_waypoint = p_waypoints->GetStructure( i );\r\n\r\n        // is this waypoint done?\r\n        uint32 flagId;\r\n        p_waypoint->GetChecksum( \"flag\", &flagId, Script::ASSERT );\r\n        if ( GoalFlagEquals( flagId, 1 ) )\r\n        {\r\n            continue;\r\n        }\r\n        \r\n\t\tif ( m_flagsSet == 0)\r\n\t\t{\r\n\t\t\tm_timeLeft = 0;\r\n\t\t\tp_waypoint->AddInteger( \"first_waypoint\", 1 );\r\n\t\t}\r\n        \r\n\t\t// add the goalId to the params\r\n        p_waypoint->AddChecksum( \"goal_id\", goalId );\r\n\r\n\t\t// add quick start flag\r\n\t\tif ( mp_params->ContainsFlag( CRCD(0x38221df4,\"quick_start\") ) )\r\n\t\t\tp_waypoint->AddChecksum( NONAME, CRCD(0x38221df4,\"quick_start\") );\r\n\t\telse\r\n\t\t\tp_waypoint->RemoveFlag( CRCD(0x38221df4,\"quick_start\") );\r\n\r\n\t\t#ifdef __NOPT_ASSERT__\r\n        Script::CScript *p_script=Script::SpawnScript( \"goal_race_next_waypoint\", p_waypoint);\r\n\t\tp_script->SetCommentString(\"Spawned from CRaceGoal::NextRaceWaypoint\");\r\n\t\t#else\r\n        Script::SpawnScript( \"goal_race_next_waypoint\", p_waypoint);\r\n\t\t#endif\r\n\r\n\t\t// set the timer\r\n\t\tif ( !m_unlimitedTime )\r\n\t\t{\r\n\t\t\tint time;\r\n\t\t\tif ( !p_waypoint->GetInteger( \"time\", &time, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0, (\"Each race waypoint must have a 'time' param\") );\r\n\t\t\t}\r\n\t\t\tCGoal::AddTime( time );\r\n\t\t}\r\n\r\n/*        uint32 waypoint_script;\r\n        if ( p_waypoint->GetChecksum( \"scr\", &waypoint_script, Script::NO_ASSERT ) )\r\n            Script::SpawnScript( waypoint_script );\r\n*/\r\n        return true;\r\n    }\r\n    return true;\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/RaceGoal.h",
    "content": "#ifndef __SK_MODULES_SKATE_RACEGOAL_H__\r\n#define __SK_MODULES_SKATE_RACEGOAL_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <sk/modules/skate/GoalManager.h>\r\n\r\nnamespace Game\r\n{\r\n\r\nclass CRaceGoal : public CGoal\r\n{\r\n\tfriend class CGoalManager;\r\n\r\npublic:\r\n\t\t\t\t\tCRaceGoal( Script::CStruct* pParams );\r\n\tvirtual\t\t\t~CRaceGoal();\r\n\r\n\tbool\t\t\tShouldExpire();\r\n\tbool\t\t\tIsExpired();\r\n\tvoid\t\t\tExpire();\r\n\tbool\t\t\tNextRaceWaypoint( uint32 goalId );\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/SkatetrisGoal.cpp",
    "content": "// skatetris goal\r\n#include <sk/modules/skate/GoalManager.h>\r\n#include <sk/modules/skate/SkatetrisGoal.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/symboltype.h>\r\n\r\n#include <gfx/2D/ScreenElemMan.h>       // for tetris tricks\r\n#include <gfx/2D/ScreenElement2.h>\r\n#include <gfx/2D/TextElement.h>\r\n#include <gfx/2D/SpriteElement.h>\r\n\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/skaterprofile.h>\r\n\r\nnamespace Game\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkatetrisGoal::CSkatetrisGoal( Script::CStruct* pParams ) : CGoal( pParams )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkatetrisGoal::~CSkatetrisGoal()\r\n{\r\n//\tdelete[] m_tetrisTricks;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkatetrisGoal::Activate()\r\n{\r\n\tif ( !IsActive() )\r\n\t{\r\n\t\tStartTetrisGoal();\r\n\t\treturn CGoal::Activate();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkatetrisGoal::Deactivate( bool force, bool affect_tree )\r\n{\r\n\t// printf(\"CSkatetrisGoal::Deactivate\\n\");\r\n\tEndTetrisGoal();\r\n\treturn CGoal::Deactivate( force, affect_tree );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkatetrisGoal::Win()\r\n{\r\n\t// the win function is called after time runs out, \r\n\t// so deactivate must always be called\r\n\r\n\t// K: TT12058, Deactivate may remove the testing_goal flag, so store it and put it back in\r\n\t// afterwards if necessary. (The flag is required by the call to CGoal::Win below)\r\n\tbool testing_goal=mp_params->ContainsFlag(CRCD(0x54d3cac1,\"testing_goal\"));\r\n\t\r\n\tmp_params->AddChecksum( NONAME, CRCD( 0xc309cad1, \"just_won_goal\" ) );\r\n\tDeactivate();\r\n\tmp_params->RemoveFlag( CRCD( 0xc309cad1, \"just_won_goal\" ) );\r\n\t\r\n\tif (testing_goal)\r\n\t{\r\n\t\tmp_params->AddChecksum(NONAME,CRCD(0x54d3cac1,\"testing_goal\"));\r\n\t}\r\n\t\t\r\n\t/*if( gamenet_man->InNetGame())\r\n\t{\r\n\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n        Dbg_Assert( pGoalManager );\r\n        return pGoalManager->WinGoal( GetGoalId());\r\n\t}\r\n\telse*/\r\n\t{\r\n\t\tbool ret_val=CGoal::Win();\r\n\t\t// Make sure the testing_goal flag is definitely gone.\r\n\t\tmp_params->RemoveFlag(CRCD(0x54d3cac1,\"testing_goal\"));\r\n\t\treturn ret_val;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkatetrisGoal::Update()\r\n{\r\n\tint wait_to_add_tricks = 0;\r\n\tmp_params->GetInteger( CRCD(0x7824963c,\"wait_to_add_tricks\"), &wait_to_add_tricks, Script::NO_ASSERT );\r\n\tif ( wait_to_add_tricks )\r\n\t{\r\n\t\t// bail out...\r\n\t\treturn CGoal::Update();\r\n\t}\r\n\r\n\tint minTimeLeft = 1;\r\n\tif ( !IsSingleComboSkatetris() )\r\n\t{\r\n\t\tif ( mp_params->GetInteger( CRCD(0xa6d96603,\"time_to_stop_adding_tricks\"), &minTimeLeft, Script::NO_ASSERT ) )\r\n\t\t\tminTimeLeft *= 1000;\r\n\t}\r\n\t\r\n\t// check for win conditions\r\n\tif ( IsTricktris() )\r\n\t{\r\n\t\tif ( IsActive() && !IsPaused() )\r\n\t\t{\r\n\t\t\t// tricktris is won when you've completed the pre-determined number\r\n\t\t\t// of tricks\r\n\t\t\tint tricks_completed = 0;\r\n\t\t\tmp_params->GetInteger( CRCD(0x8d958f01,\"tricks_completed\"), &tricks_completed, Script::NO_ASSERT );\r\n\t\t\tint total_to_win;\r\n\t\t\tmp_params->GetInteger( CRCD(0xbfd3a831,\"tricktris_total_to_win\"), &total_to_win, Script::ASSERT );\r\n\t\t\t// printf(\"tricks_completed = %i, total_to_win = %i\\n\", tricks_completed, total_to_win);\r\n\t\t\tif ( tricks_completed >= total_to_win )\r\n\t\t\t{\r\n\t\t\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\t\t\tpGoalManager->WinGoal( GetGoalId() );\r\n\t\t\t\treturn true;\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if ( IsActive() && (int)m_timeLeft < minTimeLeft && !IsPaused() && AllTricksCleared() )\r\n\t{\r\n\t\t// win the goal if they've cleared all tricks and there's no time to add more\r\n\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\tpGoalManager->WinGoal( GetGoalId() );\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\t// update faded tricks if we're active - even if the time has run out\r\n\tif ( IsActive() && !IsPaused() )\r\n\t{\r\n\t\tUpdateFadedTricks();\r\n\t}\r\n\t\r\n\tif ( IsTricktris() )\r\n\t{\r\n\t\tif ( ( m_unlimitedTime || (int)m_timeLeft > 0.0f ) && !IsPaused() )\r\n\t\t{\r\n\t\t\tint tricks_completed = 0;\r\n\t\t\tmp_params->GetInteger( CRCD(0x8d958f01,\"tricks_completed\"), &tricks_completed, Script::NO_ASSERT );\r\n\t\t\tint total_to_win;\r\n\t\t\tmp_params->GetInteger( CRCD(0xbfd3a831,\"tricktris_total_to_win\"), &total_to_win, Script::ASSERT );\r\n\t\r\n\t\t\t// count number of valid entries and add if necessary\r\n\t\t\tint total_in_stack = 0;\r\n\t\t\tfor ( int i = 0; i < Game::vMAXTETRISTRICKS; i++ )\r\n\t\t\t{\r\n\t\t\t\tif ( m_tetrisTricks[i].invalid == false )\r\n\t\t\t\t\ttotal_in_stack++;\r\n\t\t\t}\r\n\t\t\tint desired_stack_size;\r\n\t\t\tmp_params->GetInteger( CRCD(0x45a375c9,\"tricktris_block_size\"), &desired_stack_size, Script::ASSERT );\r\n\t\t\tif ( total_in_stack < desired_stack_size && total_in_stack + tricks_completed < total_to_win )\r\n\t\t\t{\r\n\t\t\t\tint num_to_add = desired_stack_size - total_in_stack;\r\n\t\t\t\tif ( total_to_win - tricks_completed - total_in_stack < num_to_add )\r\n\t\t\t\t\tnum_to_add = total_to_win - tricks_completed - total_in_stack;\r\n\t\t\t\tAddTetrisTrick( num_to_add );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if ( IsActive() && ( m_unlimitedTime || (int)m_timeLeft >= minTimeLeft ) && !IsPaused() )\r\n\t{\r\n\t\tm_tetrisTime += (int)( Tmr::FrameLength() * 1000 );\r\n\r\n\t\tif ( IsSingleComboSkatetris() )\r\n\t\t{\r\n\t\t\t// throw in a delay so the single combo doesn't appear right away\r\n\t\t\t// during the goal intro movie\r\n\t\t\tif ( !mp_params->ContainsFlag( CRCD(0xc93da683,\"single_combo_added\") ) && m_tetrisTime > 50 )\r\n\t\t\t{\r\n\t\t\t\tint combo_size;\r\n\t\t\t\tmp_params->GetInteger( CRCD(0x67dd90ca,\"combo_size\"), &combo_size, Script::ASSERT );\r\n\t\t\t\tAddTetrisTrick( combo_size );\r\n\t\t\t\tmp_params->AddChecksum( NONAME, CRCD(0xc93da683,\"single_combo_added\") );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tint trickTime;\r\n\t\t\tmp_params->GetInteger( CRCD(0x648d8d2a,\"adjusted_trick_time\"), &trickTime, Script::ASSERT );\r\n\t\t\tif ( m_tetrisTime > trickTime )\r\n\t\t\t{\r\n\t\t\t\tm_tetrisTime = 0;\r\n\t\t\t\tif ( IsComboSkatetris() )\r\n\t\t\t\t{\r\n\t\t\t\t\tint combo_size;\r\n\t\t\t\t\tmp_params->GetInteger( CRCD(0x67dd90ca,\"combo_size\"), &combo_size, Script::ASSERT );\r\n\t\t\t\t\tAddTetrisTrick( combo_size );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t\tAddTetrisTrick();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn CGoal::Update();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkatetrisGoal::StartTetrisGoal()\r\n{\r\n    m_numTetrisTricks = 0;\r\n    m_tetrisTime = 0;\r\n    int original_time;\r\n    mp_params->GetInteger( CRCD( 0xded8540a, \"trick_time\" ), &original_time, Script::ASSERT );\r\n    mp_params->AddInteger( CRCD( 0x648d8d2a, \"adjusted_trick_time\" ), original_time );\r\n\tmp_params->AddInteger( CRCD( 0x8d958f01, \"tricks_completed\" ), 0 );\r\n\r\n\t// start almost out of time so a trick gets added right away\r\n\tif ( IsSingleComboSkatetris() )\r\n\t\tm_tetrisTime = 0;\r\n\telse\r\n\t\tm_tetrisTime = original_time - 200;\r\n    \r\n    for ( int i = 0; i < Game::vMAXTETRISTRICKS; i++ )\r\n    {\r\n        m_tetrisTricks[i].invalid = true;\r\n        m_tetrisTricks[i].trickNameChecksum = 0;\r\n\t\tm_tetrisTricks[i].altTrickNameChecksum = 0;\r\n\t\tm_tetrisTricks[i].keyCombo = 0;\r\n\t\tm_tetrisTricks[i].spin_mult = 0;\r\n\t\tm_tetrisTricks[i].num_taps = 1;\r\n\t\tm_tetrisTricks[i].require_perfect = false;\r\n\r\n\t\tm_validGroups[i] = false;\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkatetrisGoal::EndTetrisGoal()\r\n{\r\n    m_numTetrisTricks = 0;\r\n    m_tetrisTime = 0;\r\n    \r\n    for ( int i = 0; i < Game::vMAXTETRISTRICKS; i++ )\r\n    {\r\n        m_tetrisTricks[i].invalid = false;\r\n        m_tetrisTricks[i].trickNameChecksum = 0;\r\n\t\tm_tetrisTricks[i].altTrickNameChecksum = 0;\r\n\t\tm_tetrisTricks[i].keyCombo = 0;\r\n\t\tm_tetrisTricks[i].spin_mult = 0;\r\n\t\tm_tetrisTricks[i].num_taps = 1;\r\n\t\tm_tetrisTricks[i].require_perfect = false;\r\n\r\n\t\tm_validGroups[i] = false;\r\n    }\r\n\r\n\tmp_params->RemoveFlag( CRCD(0xc93da683,\"single_combo_added\") );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkatetrisGoal::AddTetrisTrick( int num_to_add )\r\n{\r\n    int max_tricks;\r\n\tmp_params->GetInteger( CRCD(0x89473db7,\"max_tricks\"), &max_tricks, Script::ASSERT );\r\n\t\r\n\tint tricks_in_group = num_to_add;\r\n\tint possible_num_tricks = m_numTetrisTricks + tricks_in_group;\r\n    \r\n\tbool add_combo = false;\r\n\tif ( IsComboSkatetris() || IsSingleComboSkatetris() )\r\n\t\tadd_combo = true;\r\n\t\r\n/*\tif ( add_combo )\r\n\t{\r\n\t\tmp_params->GetInteger( CRCD(0x67dd90ca,\"combo_size\"), &tricks_in_group, Script::ASSERT );\r\n\t\tpossible_num_tricks += tricks_in_group;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpossible_num_tricks++;\r\n\t}\r\n*/\r\n\t\r\n\t// check that they haven't lost\r\n\tif ( possible_num_tricks > max_tricks )\r\n    {\r\n        uint32 goalId = GetGoalId();\r\n        Dbg_Assert( goalId );\r\n        CGoalManager* pGoalManager = GetGoalManager();\r\n        Dbg_Assert( pGoalManager );\r\n        pGoalManager->LoseGoal( goalId );\r\n    }\r\n    else \r\n    {\r\n\t\t// set the group id and increment number of trick groups\r\n\t\tint group_id = 0;\r\n\t\tif ( add_combo )\r\n\t\t{\r\n\t\t\tfor ( int i = 0; i < Game::vMAXTETRISTRICKS; i++ )\r\n\t\t\t{\r\n\t\t\t\tif ( !m_validGroups[i] )\r\n\t\t\t\t{\r\n\t\t\t\t\tgroup_id = i;\r\n\t\t\t\t\tm_validGroups[group_id] = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tDbg_Assert( !( group_id == Game::vMAXTETRISTRICKS ) );\r\n\t\t}\t\t\r\n\t\t\r\n\t\t// add as many tricks as we need (1 by default)\r\n\t\twhile ( tricks_in_group > 0 )\r\n\t\t{\r\n\t\t\tFront::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();\r\n\t\t\t\r\n\t\t\t// grab list of valid key combos\r\n\t\t\tScript::CArray* p_keyCombos = NULL;\r\n\t\t\tmp_params->GetArray( CRCD(0x7be1e689,\"goal_tetris_key_combos\"), &p_keyCombos, Script::NO_ASSERT );\r\n\r\n\t\t\tuint32 key_combo = 0;\r\n\t\t\tuint32 trick_name_checksum = 0;\r\n\t\t\tchar trick_text[Game::NEW_STRING_LENGTH];\r\n\t\t\t\r\n\t\t\t// find the first empty trick\r\n\t\t\tint index = 0;\r\n\r\n\t\t\tfor ( int i = 0; i < Game::vMAXTETRISTRICKS; i++ )\r\n\t\t\t{\r\n\t\t\t\tif ( m_tetrisTricks[i].invalid == true )\r\n\t\t\t\t{\r\n\t\t\t\t\tindex = i;\r\n\t\t\t\t\tm_tetrisTricks[index].invalid = false;\r\n\t\t\t\t\tm_tetrisTricks[index].group_id = group_id;\r\n\t\t\t\t\tm_tetrisTricks[index].keyCombo = 0;\r\n\t\t\t\t\tm_tetrisTricks[index].trickNameChecksum = 0;\r\n\t\t\t\t\tm_tetrisTricks[index].altTrickNameChecksum = 0;\r\n\t\t\t\t\tm_tetrisTricks[index].spin_mult = 0;\r\n\t\t\t\t\tm_tetrisTricks[index].num_taps = 1;\r\n\t\t\t\t\tm_tetrisTricks[index].require_perfect = false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tDbg_Assert( !( index == Game::vMAXTETRISTRICKS ) );\r\n\t\t\t\r\n\t\t\t// check the type of the structure...this will tell us if this is a standard\r\n\t\t\t// skatetris goal (array of key combos), or a special one (array of structures\r\n\t\t\t// containing the name and text of the trick).\r\n\t\t\tconst char* p_key_combo_text = NULL;\r\n\t\t\tint num_taps = 1;\r\n\t\t\tif ( !p_keyCombos )\r\n\t\t\t{\r\n\t\t\t\t// check for a trick array\r\n\t\t\t\tScript::CArray* p_tetris_tricks = NULL;\r\n\t\t\t\tmp_params->GetArray( CRCD(0xeb79fb49,\"goal_tetris_tricks\"), &p_tetris_tricks, Script::ASSERT );\r\n\t\t\t\t\r\n\t\t\t\t// grab a random trick\r\n\t\t\t\t// no safety checks, since we don't care if the trick is mapped\r\n\t\t\t\tScript::CStruct* p_trick = p_tetris_tricks->GetStructure( Mth::Rnd( p_tetris_tricks->GetSize() ) );\r\n\t\t\t\tconst char* p_trick_display_text;\r\n\t\t\t\tp_trick->GetString( CRCD(0x270f56e1,\"trick\"), &p_trick_display_text, Script::ASSERT );\r\n\t\t\t\t\r\n\t\t\t\tif ( p_trick->ContainsFlag( CRCD( 0x255ed86f, \"grind\" ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t// store FS and BS versions of the trick\r\n\t\t\t\t\tchar grind_string[128];\r\n\t\t\t\t\tstrcpy( grind_string, \"FS \" );\r\n\t\t\t\t\tstrcat( grind_string, p_trick_display_text );\r\n\t\t\t\t\tm_tetrisTricks[index].trickNameChecksum = Script::GenerateCRC( grind_string );\r\n\r\n\t\t\t\t\tstrcpy( grind_string, \"BS \" );\r\n\t\t\t\t\tstrcat( grind_string, p_trick_display_text );\r\n\t\t\t\t\tm_tetrisTricks[index].altTrickNameChecksum = Script::GenerateCRC( grind_string );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_tetrisTricks[index].trickNameChecksum = Script::GenerateCRC( p_trick_display_text );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst char* p_text;\r\n\t\t\t\tp_trick->GetString( CRCD(0xc4745838,\"text\"), &p_text, Script::ASSERT );\r\n\t\t\t\tstrcpy( trick_text, p_text );\r\n\r\n\t\t\t\tif ( !p_trick->GetChecksum( CRCD(0xacfdb27a,\"key_combo\"), &key_combo, Script::NO_ASSERT ) )\r\n\t\t\t\t\tp_trick->GetString( CRCD(0xacfdb27a,\"key_combo\"), &p_key_combo_text, Script::NO_ASSERT );\r\n\r\n\t\t\t\t// printf(\"setting trick checksum: %s\\n\", Script::FindChecksumName( trick_name_checksum ) );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// see if this is a valid key_combo\r\n\t\t\t\tint key_combo_index = GetRandomIndexFromKeyCombos( p_keyCombos );\r\n\t\t\t\tif ( key_combo_index == -1 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// couldn't find one - the goal is going to be decativated.\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tif ( p_keyCombos->GetType() == ESYMBOLTYPE_NAME )\r\n\t\t\t\t{\r\n\t\t\t\t\tkey_combo = p_keyCombos->GetChecksum( key_combo_index );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( p_keyCombos->GetType() == ESYMBOLTYPE_STRUCTURE, ( \"goal_tetris_key_combos array has bad type\" ) );\r\n\t\t\t\t\tScript::CStruct* p_subStruct = p_keyCombos->GetStructure( key_combo_index );\r\n\t\t\t\t\tp_subStruct->GetChecksum( CRCD(0xacfdb27a,\"key_combo\"), &key_combo, Script::ASSERT );\r\n\t\t\t\t\t\r\n\t\t\t\t\tint spin_mult = 0;\r\n\t\t\t\t\tif ( p_subStruct->GetInteger( CRCD(0x8c8abd19,\"random_spin\"), &spin_mult, Script::NO_ASSERT ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// make sure it's a multiple of 180\r\n\t\t\t\t\t\tDbg_MsgAssert( spin_mult % 180 == 0, ( \"Skatetris goal %s has bad spin_mult value %i\", Script::FindChecksumName( GetGoalId() ), spin_mult ) );\r\n\t\t\t\t\t\tif (spin_mult < 360)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tspin_mult=360;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// K: Make it so that spins of 180 are excluded, since they are too hard to do on vert.\r\n\t\t\t\t\t\t// Ie:\r\n\t\t\t\t\t\t// spin_mult=360 gives spins of 0, or 360\r\n\t\t\t\t\t\t// spin_mult=540 gives spins of 0, 360 or 540\r\n\t\t\t\t\t\t// spin_mult=720 gives spins of 0, 360, 540 or 720\r\n\t\t\t\t\t\t// etc ...\r\n\t\t\t\t\t\tm_tetrisTricks[index].spin_mult = Mth::Rnd(spin_mult / 180) + 1;\r\n\t\t\t\t\t\tif (m_tetrisTricks[index].spin_mult == 1)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tm_tetrisTricks[index].spin_mult=0;\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( p_subStruct->GetInteger( CRCD(0xedf5db70,\"spin\"), &spin_mult, Script::NO_ASSERT ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// make sure it's a multiple of 180\r\n\t\t\t\t\t\tDbg_MsgAssert( spin_mult % 180 == 0, ( \"Skatetris goal %s has bad spin_mult value %i\", Script::FindChecksumName( GetGoalId() ), spin_mult ) );\r\n\t\t\t\t\t\tm_tetrisTricks[index].spin_mult = spin_mult / 180;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( p_subStruct->ContainsFlag( CRCD(0x1c39f1b9,\"perfect\") ) )\r\n\t\t\t\t\t\tm_tetrisTricks[index].require_perfect = true;\r\n\r\n\t\t\t\t\tif ( p_subStruct->GetInteger( CRCD(0xa4bee6a1,\"num_taps\"), &num_taps, Script::NO_ASSERT ) )\r\n\t\t\t\t\t\tm_tetrisTricks[index].num_taps = num_taps;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// get the global trick mapping\r\n\t\t\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\t\t\tObj::CSkaterProfile* p_SkaterProfile = skate_mod->GetCurrentProfile();\r\n\t\t\t\tScript::CStruct* p_trickMappings = p_SkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") );\r\n\t\t\r\n\t\t\t\tconst char* p_text = NULL;\r\n\t\t\t\t\r\n\t\t\t\t// if it's not a regular assignment, grab cat info\r\n\t\t\t\tif ( !p_trickMappings->GetChecksum( key_combo, &trick_name_checksum, Script::NO_ASSERT ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tint cat_index;\r\n\t\t\t\t\tp_trickMappings->GetInteger( key_combo, &cat_index, Script::ASSERT );\r\n\t\t\t\t\tDbg_Assert( cat_index >= 0 && cat_index < vMAX_CREATED_TRICKS );\r\n\t\t\t\t\tObj::CSkater* pSkater = skate_mod->GetLocalSkater();\r\n\t\t\t\t\tif ( pSkater )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tGame::CCreateATrick* pCreatedTrick = pSkater->m_created_trick[cat_index];\r\n\t\t\t\t\t\tpCreatedTrick->mp_other_params->GetString( CRCD( 0xa1dc81f9, \"name\" ), &p_text, Script::ASSERT );\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// mark it\r\n\t\t\t\t\t\t// no cat tricks have double versions!\r\n\t\t\t\t\t\tm_tetrisTricks[index].num_taps = 1;\r\n\t\t\t\t\t}\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tif ( !p_text )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct* p_trick_structure = NULL;\r\n\t\t\t\t\tp_trick_structure = Script::GetStructure( trick_name_checksum, Script::NO_ASSERT );\r\n\t\t\t\t\tif ( !p_trick_structure )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tScript::CArray* p_trick_array = Script::GetArray( trick_name_checksum, Script::ASSERT );\r\n\t\t\t\t\t\tp_trick_structure = p_trick_array->GetStructure( 0 );\r\n\t\t\r\n\t\t\t\t\t\tDbg_MsgAssert( p_trick_structure, ( \"Could not find trick structure\" ) );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tScript::CStruct* p_trick_params;\r\n\t\t\t\t\tp_trick_structure->GetStructure( CRCD(0x7031f10c,\"Params\"), &p_trick_params, Script::ASSERT );\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t// get any multiple tap info\r\n\t\t\t\t\twhile ( num_taps > 1 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnum_taps--;\r\n\t\r\n\t\t\t\t\t\tuint32 extra_trick;\r\n\t\t\t\t\t\tif ( p_trick_params->GetChecksum( CRCD(0x6e855102,\"ExtraTricks\"), &extra_trick, Script::NO_ASSERT ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tScript::CArray* p_extra_trick_array = Script::GetArray( extra_trick, Script::ASSERT );\r\n\t\t\t\t\t\t\tDbg_MsgAssert( p_extra_trick_array->GetType() == ESYMBOLTYPE_STRUCTURE, ( \"ExtraTricks array %s has wrong type\", Script::FindChecksumName( extra_trick ) ) );\r\n\t\t\t\t\t\t\tScript::CStruct* p_extra_trick_struct = p_extra_trick_array->GetStructure( 0 );\r\n\t\t\t\t\t\t\tp_extra_trick_struct->GetStructure( CRCD(0x7031f10c,\"Params\"), &p_trick_params, Script::ASSERT );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnum_taps = 1;\r\n\t\t\t\t\t\t\tm_tetrisTricks[index].num_taps = 1;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_trick_params->GetLocalText( CRCD(0xa1dc81f9,\"Name\"), &p_text, Script::ASSERT );\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// build the text string\r\n\t\t\t\tstrcpy( trick_text, \"\" );\r\n\r\n\t\t\t\t// spin value\r\n\t\t\t\tif ( m_tetrisTricks[index].spin_mult != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// perfect modifier\r\n\t\t\t\t\tif ( m_tetrisTricks[index].require_perfect )\r\n\t\t\t\t\t\tsprintf( trick_text, \"Perfect \" );\r\n\r\n\t\t\t\t\tsprintf( trick_text, \"\\\\c5%i\\\\c0 \", ( m_tetrisTricks[index].spin_mult * 180 ) );\r\n\t\t\t\t}\r\n\t\t\t\t// trick text\r\n\t\t\t\tstrcat( trick_text, p_text );\r\n\t\t\t\t\r\n\t\t\t\t// store key combo\r\n\t\t\t\tm_tetrisTricks[index].keyCombo = key_combo;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// create the container for this element\r\n\t\t\tScript::CStruct *p_container_params = new Script::CStruct();\r\n\t\t\tFront::CContainerElement *p_container = new Front::CContainerElement();\r\n\t\t\tuint32 container_id = Obj::CBaseManager::vNO_OBJECT_ID;\r\n\t\t\tp_container->SetID( container_id );\r\n\t\t\tp_screen_elem_man->RegisterObject( *p_container );\r\n\r\n\t\t\t// figure the dims\r\n\t\t\tint y_dim = 20;\r\n\t\t\tif ( add_combo && tricks_in_group == 1 )\r\n\t\t\t{\r\n\t\t\t\ty_dim *= 2;\r\n\t\t\t}\r\n\t\t\tp_container_params->AddPair( CRCD(0x34a68574,\"dims\"), 100, y_dim );\r\n\r\n\t\t\tp_container->SetProperties( p_container_params );\r\n\t\t\t\r\n\t\t\t// set the parent\r\n\t\t\tFront::CScreenElement* p_vmenu = p_screen_elem_man->GetElement(CRCD(0xe35ec715,\"tetris_tricks_menu\"), Front::CScreenElementManager::ASSERT );\r\n\t\t\tp_vmenu->SetChildLockState( Front::CScreenElement::UNLOCK );\r\n\t\t\tp_screen_elem_man->SetParent( p_vmenu, p_container );\r\n\r\n\t\t\tdelete p_container_params;\t\t\t\t\t\t\r\n\t\t\t\r\n\t\t\t// create text name element\r\n\t\t\tScript::CStruct *p_elem_params = new Script::CStruct();\r\n\t\t\tp_elem_params->AddString( CRCD(0xc4745838,\"text\"), trick_text );\r\n\t\t\tp_elem_params->AddChecksum( CRCD(0x2f6bf72d,\"font\"), CRCD( 0xbc19c379, \"newtrickfont\" ) );\r\n\t\t\tp_elem_params->AddChecksum( NONAME, CRCD( 0x1d944426, \"not_focusable\" ) );\r\n\t\t\tuint32 id = Obj::CBaseManager::vNO_OBJECT_ID;\r\n\t\r\n\t\t\tFront::CTextElement* p_new_element = new Front::CTextElement();\r\n\t\t\tp_new_element->SetID( id );\r\n\t\t\tp_screen_elem_man->RegisterObject( *p_new_element );\r\n\t\t\t\r\n\t\t\tp_new_element->SetProperties( p_elem_params );\r\n\t\r\n\t\t\t// set the parent\r\n\t\t\tp_screen_elem_man->SetParent( p_container, p_new_element );\r\n\t\t\t\r\n\t\t\tdelete p_elem_params;\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t// create button combo element\r\n\t\t\tif ( p_key_combo_text || key_combo )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* p_button_combos;\r\n\t\t\t\tif ( m_tetrisTricks[index].num_taps == 2 )\r\n\t\t\t\t\tp_button_combos = Script::GetStructure( CRCD(0xe7abfb95,\"goal_tetris_trick_text_double_tap\"), Script::ASSERT );\r\n\t\t\t\telse\r\n\t\t\t\t\tp_button_combos = Script::GetStructure( CRCD(0x8856c817,\"goal_tetris_trick_text\"), Script::ASSERT );\r\n\r\n\t\t\t\tif ( !p_key_combo_text && !p_button_combos->GetString( key_combo, &p_key_combo_text, Script::NO_ASSERT ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( 0, ( \"Could not find button text for skatetris trick\" ) );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tScript::CStruct *p_button_params = new Script::CStruct();\r\n\t\t\t\tp_button_params->AddString( CRCD(0xc4745838,\"text\"), p_key_combo_text );\r\n\t\t\t\tp_button_params->AddChecksum( CRCD(0x2f6bf72d,\"font\"), CRCD( 0x8aba15ec, \"small\" ) );\r\n\t\t\t\tp_button_params->AddChecksum( NONAME, CRCD( 0x1d944426, \"not_focusable\" ) );\r\n\t\t\t\tuint32 button_id = Obj::CBaseManager::vNO_OBJECT_ID;\r\n\t\t\r\n\t\t\t\tFront::CTextElement* p_button_element = new Front::CTextElement();\r\n\t\t\t\tp_button_element->SetID( button_id );\r\n\t\t\t\tp_screen_elem_man->RegisterObject( *p_button_element );\r\n\t\t\t\t\r\n\t\t\t\tp_button_element->SetProperties( p_button_params );\r\n\t\t\t\t\r\n\t\t\t\t// the button is a child of the container\r\n\t\t\t\tp_screen_elem_man->SetParent( p_container, p_button_element );\r\n\t\t\r\n\t\t\t\tdelete p_button_params;\r\n\t\t\t}\r\n\t\r\n\t\t\t// store the id\r\n\t\t\tm_tetrisTricks[index].screenElementId = p_container->GetID();\r\n\t\t\tm_numTetrisTricks++;\r\n\t\r\n\t\t\t// run entrance animation\r\n\t\t\tScript::CStruct* p_script_params = new Script::CStruct();\r\n\t\t\tif ( !p_key_combo_text )\r\n\t\t\t\tp_script_params->AddChecksum( NONAME, CRCD( 0x7b716096, \"no_key_combo\" ) );\r\n\t\t\tuint32 script = CRCD(0x668cc9e3,\"goal_tetris_add_trick\");\r\n\r\n\t\t\tif ( !IsTricktris() && !IsSingleComboSkatetris() && m_numTetrisTricks > ( .75 * (float)max_tricks ) )\r\n\t\t\t\tscript = CRCD(0x8e68afc2,\"goal_tetris_add_red_trick\");\r\n\t\r\n\t\t\tScript::CScript *p_new_script = Script::SpawnScript( script, p_script_params );\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tp_new_script->SetCommentString(\"Spawned from CSkatetrisGoal::AddTetrisTrick()\");\r\n\t\t\t#endif\r\n\t\t\tp_new_script->mpObject = p_container;\r\n\t\t\t// normally, script won't be updated until next frame -- we want it NOW, motherfucker\r\n\t\t\tp_new_script->Update();\r\n\t\t\tdelete p_script_params;\r\n\t\r\n\t\t\t// turn the elements red if you're over 75% of the way to the top,\r\n\t\t\t// but not if we're doing a single combo\r\n\t\t\tif ( !IsTricktris() && !IsSingleComboSkatetris() && m_numTetrisTricks > ( .75 * (float)max_tricks ) )\r\n\t\t\t{\r\n\t\t\t\tmp_params->AddInteger( CRCD(0xd02ac196,\"list_is_red\"), 1 );\r\n\t\t\t\t\r\n\t\t\t\tfor ( int j = 0; j < Game::vMAXTETRISTRICKS; j++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !m_tetrisTricks[j].invalid )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tFront::CScreenElement* p_trick = p_screen_elem_man->GetElement( m_tetrisTricks[j].screenElementId , Front::CScreenElementManager::ASSERT );\r\n\t\t\t\t\t\tscript = CRCD(0xeb016d1e,\"goal_tetris_turn_trick_red\");\r\n\t\t\t\t\t\tScript::CScript* p_trick_script = Script::SpawnScript( script, NULL );\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\tp_trick_script->SetCommentString(\"Spawned from CSkatetrisGoal::AddTetrisTrick()\");\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\tp_trick_script->mpObject = p_trick;\r\n\t\t\t\t\t\tp_trick_script->Update();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ttricks_in_group--;\r\n\t\t}\r\n    }\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkatetrisGoal::CheckTetrisTricks()\r\n{\r\n\t// special case trick flag...used for an additional condition that must be\r\n\t// met before any skatetris tricks can be cleared.\r\n\t// The flag is cleared each time the tricks are checked\r\n\tint trick_flag;\r\n\tif ( mp_params->GetInteger( CRCD(0x60b827d5,\"trick_flag\"), &trick_flag, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tif ( trick_flag == 0 )\r\n\t\t\treturn;\r\n\t\telse \r\n\t\t\tmp_params->AddInteger( CRCD(0x60b827d5,\"trick_flag\"), 0 );\r\n\t}\r\n\t\r\n\tbool check_combo = false;\r\n\tif ( IsSingleComboSkatetris() || IsComboSkatetris() )\r\n\t\tcheck_combo = true;\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n    Obj::CSkater *pSkater = skate_mod->GetLocalSkater();\r\n    Dbg_Assert( pSkater );\r\n  \r\n    Mdl::Score * p_score = ( pSkater->GetScoreObject() );\r\n    Dbg_Assert( p_score );\r\n    \r\n\t// check for combos!\r\n\tif ( check_combo )\r\n\t{\r\n\t\tCheckTetrisCombos();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// check for single tricks\r\n\t\tbool trick_removed = false;\r\n\t\tfor ( int i = 0; i < Game::vMAXTETRISTRICKS; i++ )\r\n\t\t{\r\n\t\t\tif ( !m_tetrisTricks[i].invalid )\r\n\t\t\t{\r\n\t\t\t\tif ( m_tetrisTricks[i].trickNameChecksum != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( p_score->GetCurrentNumberOfOccurrencesByName( m_tetrisTricks[i].trickNameChecksum, m_tetrisTricks[i].spin_mult, m_tetrisTricks[i].require_perfect ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( !trick_removed )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tScript::RunScript( \"goal_tetris_play_trick_removed_sound\" );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\ttrick_removed = true;\r\n\t\t\t\t\t\tRemoveTrick( i );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if ( m_tetrisTricks[i].altTrickNameChecksum != 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// check alternate trick name - usually BS version of grind trick\r\n\t\t\t\t\t\tif ( p_score->GetCurrentNumberOfOccurrencesByName( m_tetrisTricks[i].altTrickNameChecksum, m_tetrisTricks[i].spin_mult, m_tetrisTricks[i].require_perfect ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( !trick_removed )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tScript::RunScript( \"goal_tetris_play_trick_removed_sound\" );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\ttrick_removed = true;\r\n\t\t\t\t\t\t\tRemoveTrick( i );\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse if ( m_tetrisTricks[i].keyCombo != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// printf( \"checking for a key combo %s\\n\", Script::FindChecksumName( m_tetrisTricks[i].keyCombo ));\r\n\t\t\t\t\tif ( p_score->GetCurrentNumberOfOccurrences( m_tetrisTricks[i].keyCombo, m_tetrisTricks[i].spin_mult, m_tetrisTricks[i].require_perfect, m_tetrisTricks[i].num_taps ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( !trick_removed )\r\n\t\t\t\t\t\t\tScript::RunScript( \"goal_tetris_play_trick_removed_sound\" );\r\n\t\t\t\t\t\ttrick_removed = true;\r\n\t\t\t\t\t\tRemoveTrick( i );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkatetrisGoal::CheckTetrisCombos()\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n    Obj::CSkater *p_Skater = skate_mod->GetLocalSkater();\r\n    Dbg_Assert( p_Skater );\r\n  \r\n    Mdl::Score * p_Score = ( p_Skater->GetScoreObject() );\r\n    Dbg_Assert( p_Score );\r\n    \r\n\tint group_size;\r\n\tmp_params->GetInteger( CRCD(0x67dd90ca,\"combo_size\"), &group_size, Script::ASSERT );\r\n\t\r\n\tfor ( int group_id = 0; group_id < Game::vMAXTETRISTRICKS; group_id++ )\r\n\t{\r\n\t\tbool trick_removed = false;\r\n\r\n\t\t// skip invalid groups\r\n\t\tif ( !m_validGroups[group_id] )\r\n\t\t\tcontinue;\r\n\t\t\r\n\t\t// see how many tricks they got out of this group\r\n\t\tint group_total = 0;\r\n\t\tfor ( int i = 0; i < Game::vMAXTETRISTRICKS; i++ )\r\n\t\t{\r\n\t\t\tif ( m_tetrisTricks[i].keyCombo != 0 )\r\n\t\t\t{\r\n\t\t\t\tif ( !m_tetrisTricks[i].invalid &&\r\n\t\t\t\t\t m_tetrisTricks[i].group_id == group_id &&\r\n\t\t\t\t\t p_Score->GetCurrentNumberOfOccurrences( m_tetrisTricks[i].keyCombo, m_tetrisTricks[i].spin_mult, m_tetrisTricks[i].require_perfect, m_tetrisTricks[i].num_taps ) > 0\r\n\t\t\t\t   )\r\n\t\t\t\t\tgroup_total++;\r\n\t\t\t}\r\n\t\t\telse if ( m_tetrisTricks[i].trickNameChecksum != 0 )\r\n\t\t\t{\r\n\t\t\t\tif ( !m_tetrisTricks[i].invalid &&\r\n\t\t\t\t\t m_tetrisTricks[i].group_id == group_id &&\r\n\t\t\t\t\t p_Score->GetCurrentNumberOfOccurrencesByName( m_tetrisTricks[i].trickNameChecksum, m_tetrisTricks[i].spin_mult, m_tetrisTricks[i].require_perfect, m_tetrisTricks[i].num_taps ) > 0\r\n\t\t\t\t   )\r\n\t\t\t\t{\r\n\t\t\t\t\tgroup_total++;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( m_tetrisTricks[i].altTrickNameChecksum != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// check alternate version of trick - usually BS version of grind\r\n\t\t\t\t\tif ( !m_tetrisTricks[i].invalid &&\r\n\t\t\t\t\t\t m_tetrisTricks[i].group_id == group_id &&\r\n\t\t\t\t\t\t p_Score->GetCurrentNumberOfOccurrencesByName( m_tetrisTricks[i].altTrickNameChecksum, m_tetrisTricks[i].spin_mult, m_tetrisTricks[i].require_perfect, m_tetrisTricks[i].num_taps ) > 0\r\n\t\t\t\t\t   )\r\n\t\t\t\t\t\tgroup_total++;\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t\t// remove this group?\r\n\t\tif ( group_total >= group_size )\r\n\t\t{\r\n\t\t\t// kill all tricks in this group\r\n\t\t\tfor ( int j = 0; j < Game::vMAXTETRISTRICKS; j++ )\r\n\t\t\t{\r\n\t\t\t\tif ( !m_tetrisTricks[j].invalid && m_tetrisTricks[j].group_id == group_id )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !trick_removed )\r\n\t\t\t\t\t\tScript::RunScript( CRCD(0xe4ea743a,\"goal_tetris_play_trick_removed_sound\") );\r\n\t\t\t\t\ttrick_removed = true;\r\n\r\n\t\t\t\t\tRemoveTrick( j );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// this group id is dead\r\n\t\t\tm_validGroups[group_id] = false;\r\n\r\n\t\t\t// was this a single combo goal?\r\n\t\t\tif ( IsSingleComboSkatetris() )\r\n\t\t\t{\r\n\t\t\t\tGame::CGoalManager* pGoalManager = Game::GetGoalManager();\r\n\t\t\t\tpGoalManager->WinGoal( GetGoalId() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkatetrisGoal::RemoveTrick( int index )\r\n{\t\r\n\tint max_tricks;\r\n\tmp_params->GetInteger( CRCD(0x89473db7,\"max_tricks\"), &max_tricks, Script::ASSERT );\r\n\r\n\t// printf(\"found a completed trick at %i\\n\", i);\r\n\tFront::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();\r\n\tuint32 id = m_tetrisTricks[index].screenElementId;\r\n\tDbg_Assert( id );\r\n\tFront::CScreenElementPtr p_trick = p_screen_elem_man->GetElement( id, Front::CScreenElementManager::ASSERT );\r\n\r\n\t// kill any scripts running on this element so the animations don't conflict\r\n\tScript::CStruct* p_temp_params = new Script::CStruct();\r\n\tp_temp_params->AddChecksum( CRCD(0x40c698af,\"id\"), id );\r\n\tScript::RunScript( CRCD(0x235bde21,\"goal_tetris_reset_trick_container\"), p_temp_params );\r\n\tdelete p_temp_params;\r\n\t\r\n\tuint32 script;\r\n\t\r\n\t// turn the elements back to white if you fell to under 75% full\r\n\tint list_is_red = 0;\r\n\tmp_params->GetInteger( CRCD(0xd02ac196,\"list_is_red\"), &list_is_red, Script::NO_ASSERT );\r\n\tif ( ( list_is_red == 1 ) && ( ( m_numTetrisTricks - 1 ) < ( .75 * (float)max_tricks ) ) )\r\n\t{\r\n\t\tmp_params->AddInteger( CRCD(0xd02ac196,\"list_is_red\"), 0 );\r\n\t\tfor ( int j = 0; j < Game::vMAXTETRISTRICKS; j++ )\r\n\t\t{\r\n\t\t\tif ( !m_tetrisTricks[j].invalid )\r\n\t\t\t{\r\n\t\t\t\tFront::CScreenElement* p_trick = p_screen_elem_man->GetElement( m_tetrisTricks[j].screenElementId , Front::CScreenElementManager::ASSERT );\r\n\t\t\t\tscript = CRCD(0xa39b24e0,\"goal_tetris_turn_trick_white\");\r\n\t\t\t\tScript::CScript* p_trick_script = Script::SpawnScript( script, NULL );\r\n\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\tp_trick_script->SetCommentString(\"Spawned from CSkatetrisGoal::RemoveTrick()\");\r\n\t\t\t\t#endif\r\n\r\n\t\t\t\tp_trick_script->mpObject = p_trick;\r\n\t\t\t\tp_trick_script->Update();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// remove the trick\r\n\tscript = CRCD(0x23a6a456,\"goal_tetris_remove_trick\");\r\n\tScript::CStruct* pScriptParams = new Script::CStruct();\r\n\t\r\n\t// flag for removing tricktris tricks immediately\r\n\tif ( IsTricktris() )\r\n\t\tpScriptParams->AddChecksum( NONAME, CRCD(0xea7ba666,\"tricktris\") );\r\n\t\r\n\tScript::CScript *p_new_script = Script::SpawnScript( script, pScriptParams );\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tp_new_script->SetCommentString(\"Spawned from CSkatetrisGoal::RemoveTrick()\");\r\n\t#endif\r\n\tp_new_script->mpObject = p_trick;\r\n\tp_new_script->Update();\r\n\tdelete pScriptParams;\r\n\t\r\n\t// grab the number of tricks completed\r\n\tint tricks_completed = 0;\r\n\tmp_params->GetInteger( CRCD(0x8d958f01,\"tricks_completed\"), &tricks_completed, Script::NO_ASSERT );\r\n\ttricks_completed++;\r\n\t\r\n\t// accelerate if needed\r\n\tint acceleration_interval = 0;\r\n\tmp_params->GetInteger( CRCD(0x1181b29,\"acceleration_interval\"), &acceleration_interval, Script::NO_ASSERT );\r\n\t// printf(\"acceleration interval = %i, tricks completed = %i\\n\", acceleration_interval, tricks_completed );\r\n\tif ( acceleration_interval && ( tricks_completed % acceleration_interval == 0 ) )\r\n\t{\r\n\t\t// adjust the time between new tricks\r\n\t\tfloat acceleration_percent = 0;\r\n\t\tmp_params->GetFloat( CRCD(0x76f65c8,\"acceleration_percent\"), &acceleration_percent, Script::NO_ASSERT );\r\n\t\tint trick_time;\r\n\t\tmp_params->GetInteger( CRCD(0x648d8d2a,\"adjusted_trick_time\"), &trick_time, Script::ASSERT );\r\n\t\ttrick_time = (int)( ( 1 - acceleration_percent ) * trick_time );\r\n\t\tmp_params->AddInteger( CRCD(0x648d8d2a,\"adjusted_trick_time\"), trick_time );\r\n\t\t// printf(\"setting trick time to %i\\n\", trick_time);\r\n\t}\r\n\t// store the number of tricks completed\r\n\t// printf(\"%i tricks completed\\n\", tricks_completed );\r\n\tmp_params->AddInteger( CRCD(0x8d958f01,\"tricks_completed\"), tricks_completed );\r\n\t\r\n\t// update number of tricks in menu\r\n\tm_numTetrisTricks--;\r\n\t\r\n\t// printf(\"setting %s trick to invalid at index %i\\n\", m_tetrisTricks[i].trickText, i );\r\n\tm_tetrisTricks[index].invalid = true;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkatetrisGoal::UpdateFadedTricks()\r\n{\r\n\t// special case trick flag...used for an additional condition that must be\r\n\t// met before any skatetris tricks can be cleared.\r\n\t// The flag is cleared each time the tricks are checked\r\n\tbool found_trick_flag = false;\r\n\tint trick_flag;\r\n\tif ( mp_params->GetInteger( CRCD(0x60b827d5,\"trick_flag\"), &trick_flag, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tfound_trick_flag = true;\r\n\t}\r\n\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n    Obj::CSkater *pSkater = skate_mod->GetLocalSkater();\r\n    Dbg_Assert( pSkater );\r\n  \r\n    Mdl::Score * pScore = ( pSkater->GetScoreObject() );\r\n    Dbg_Assert( pScore );\r\n\r\n\tFront::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();\r\n\tDbg_Assert( p_screen_elem_man );\r\n\r\n\tfloat faded_trick_alpha = Script::GetFloat( CRCD( 0x855e6da4, \"goal_tetris_faded_trick_alpha\" ), Script::ASSERT );\r\n\tfloat unfaded_trick_alpha = Script::GetFloat( CRCD( 0xdbe5b19e, \"goal_tetris_unfaded_trick_alpha\" ), Script::ASSERT );\r\n\r\n\tfor ( int i = 0; i < vMAXTETRISTRICKS; i++ )\r\n\t{\r\n\t\tif ( !m_tetrisTricks[i].invalid )\r\n\t\t{\r\n\t\t\tFront::CScreenElement* p_trick = p_screen_elem_man->GetElement( m_tetrisTricks[i].screenElementId , Front::CScreenElementManager::ASSERT );\r\n\t\t\tbool should_be_faded = false;\r\n\t\t\tif ( found_trick_flag && !trick_flag )\r\n\t\t\t{\r\n\t\t\t\tshould_be_faded = false;\r\n\t\t\t}\r\n\t\t\telse if ( m_tetrisTricks[i].keyCombo != 0 )\r\n\t\t\t{\r\n\t\t\t\tint n = pScore->GetCurrentNumberOfOccurrences( m_tetrisTricks[i].keyCombo, m_tetrisTricks[i].spin_mult, m_tetrisTricks[i].require_perfect, m_tetrisTricks[i].num_taps );\r\n\t\t\t\tif ( n > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tshould_be_faded = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( m_tetrisTricks[i].trickNameChecksum != 0 )\r\n\t\t\t{\r\n\t\t\t\tint n = pScore->GetCurrentNumberOfOccurrencesByName( m_tetrisTricks[i].trickNameChecksum, m_tetrisTricks[i].spin_mult, m_tetrisTricks[i].require_perfect );\r\n\t\t\t\tif ( n > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tshould_be_faded = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( m_tetrisTricks[i].altTrickNameChecksum != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// check alternate version of trick - usually BS version of grind\r\n\t\t\t\t\tint n = pScore->GetCurrentNumberOfOccurrencesByName( m_tetrisTricks[i].altTrickNameChecksum, m_tetrisTricks[i].spin_mult, m_tetrisTricks[i].require_perfect );\r\n\t\t\t\t\tif ( n > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tshould_be_faded = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif ( should_be_faded )\r\n\t\t\t\tp_trick->SetAlpha( faded_trick_alpha, Front::CScreenElement::FORCE_INSTANT );\r\n\t\t\telse\r\n\t\t\t\tp_trick->SetAlpha( unfaded_trick_alpha, Front::CScreenElement::FORCE_INSTANT );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkatetrisGoal::Expire()\r\n{\r\n\t// expire during normal skatetris is winning...during single combo it's losing\r\n\tif ( IsSingleComboSkatetris() || IsTricktris() )\r\n\t\tCGoal::Lose();\r\n\telse\r\n\t{\r\n\t\tif ( AllTricksCleared() )\r\n\t\t{\r\n\t\t\tCGoalManager* pGoalManager = GetGoalManager();\r\n\t\t\tpGoalManager->WinGoal( GetGoalId() );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tRunCallbackScript( vEXPIRED );\r\n\t\r\n\t\t\t// TODO: fix after e3\r\n\t\t\t// this was done to make the horse and combo letter goals work right\r\n\t\t\tif ( m_endRunType != vNONE )\r\n\t\t\t\tDeactivate();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkatetrisGoal::AllTricksCleared()\r\n{\r\n    for ( int i = 0; i < Game::vMAXTETRISTRICKS; i++ )\r\n    {\r\n        if ( m_tetrisTricks[i].invalid == false )\r\n\t\t\treturn false;\r\n    }\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkatetrisGoal::ClearAllTricks()\r\n{\r\n    m_numTetrisTricks = 0;\r\n    m_tetrisTime = 0;\r\n    \r\n    for ( int i = 0; i < Game::vMAXTETRISTRICKS; i++ )\r\n    {\r\n        m_tetrisTricks[i].invalid = true;\r\n        m_tetrisTricks[i].trickNameChecksum = 0;\r\n\t\tm_tetrisTricks[i].altTrickNameChecksum = 0;\r\n\t\tm_tetrisTricks[i].keyCombo = 0;\r\n\r\n\t\tm_validGroups[i] = false;\r\n    }\r\n\r\n\tmp_params->RemoveFlag( CRCD(0xc93da683,\"single_combo_added\") );\r\n\r\n\t// clear all the screen elements\r\n\tFront::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();\r\n\tScript::CScript* pScript = NULL;\r\n\tp_screen_elem_man->DestroyElement( CRCD(0xe35ec715,\"tetris_tricks_menu\"), Front::CScreenElementManager::RECURSE, Front::CScreenElementManager::PRESERVE_PARENT, pScript);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkatetrisGoal::IsComboSkatetris()\r\n{\r\n\tint combo_test = 0;\r\n\tmp_params->GetInteger( CRCD(0x4ec3cfb5,\"combo\"), &combo_test, Script::NO_ASSERT );\r\n\treturn ( combo_test || mp_params->ContainsFlag( CRCD(0x4ec3cfb5,\"combo\") ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkatetrisGoal::IsSingleComboSkatetris()\r\n{\r\n\tint single_combo_test = 0;\r\n\tmp_params->GetInteger( CRCD(0xdf47b144,\"single_combo\"), &single_combo_test, Script::NO_ASSERT );\r\n\treturn ( single_combo_test || mp_params->ContainsFlag( CRCD(0xdf47b144,\"single_combo\") ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkatetrisGoal::IsTricktris()\r\n{\r\n\tint tricktris_test = 0;\r\n\tmp_params->GetInteger( CRCD(0xea7ba666,\"tricktris\"), &tricktris_test, Script::NO_ASSERT );\r\n\treturn ( tricktris_test || mp_params->ContainsFlag( CRCD(0xea7ba666,\"tricktris\") ) );\r\n}\r\n\r\n\r\n}\t\t// namespace Game\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/SkatetrisGoal.h",
    "content": "// skatetris subclass\r\n\r\n#ifndef __SK_MODULES_SKATE_SKATETRISGOAL_H__\r\n#define __SK_MODULES_SKATE_SKATETRISGOAL_H__\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <sk/modules/skate/GoalManager.h>\r\n\r\nnamespace Game\r\n{\r\n\r\nconst int vMAXTETRISTRICKS\t\t= 30;\r\n\r\nstruct tetrisTrick \r\n{\r\n\tuint32 \t\ttrickNameChecksum;\r\n\tuint32\t\taltTrickNameChecksum;\r\n    uint32 \t\tkeyCombo;\r\n    uint32 \t\tscreenElementId;\r\n    bool \t\tinvalid;\r\n\tbool\t\trequire_perfect;\r\n\tint \t\tgroup_id;\r\n\tint \t\tspin_mult;\r\n\tint \t\tnum_taps;\r\n};\r\n\r\nclass CSkatetrisGoal : public CGoal\r\n{\r\n\r\npublic:\r\n\t\t\t\t\t\tCSkatetrisGoal( Script::CStruct* pParams );\r\n\tvirtual\t\t\t\t~CSkatetrisGoal();\r\n\r\n\tbool\t\t\t\tActivate();\r\n\tbool\t\t\t\tDeactivate( bool force = false, bool affect_tree = true );\r\n\tbool\t\t\t\tWin();\r\n\tvoid\t\t\t\tExpire();\r\n\t\r\n\tbool\t\t\t\tUpdate();\r\n\r\n\tvoid                StartTetrisGoal();\r\n\tvoid                EndTetrisGoal();\r\n\tvoid                CheckTetrisTricks();\r\n\tvoid\t\t\t\tCheckTetrisCombos();\r\n\tvoid                AddTetrisTrick( int num_to_add = 1 );\r\n\tvoid\t\t\t\tUpdateFadedTricks();\r\n\r\n\tvoid\t\t\t\tRemoveTrick( int index );\r\n\r\n\tbool\t\t\t\tAllTricksCleared();\r\n\r\n\tvoid\t\t\t\tClearAllTricks();\r\n\r\n\tbool\t\t\t\tIsSingleComboSkatetris();\r\n\tbool\t\t\t\tIsComboSkatetris();\r\n\tbool\t\t\t\tIsTricktris();\r\nprotected:\r\n\r\n    tetrisTrick         m_tetrisTricks[vMAXTETRISTRICKS];\r\n    int                 m_numTetrisTricks;\r\n    int\t\t\t\t\tm_tetrisTime;\r\n\tbool\t\t\t\tm_validGroups[vMAXTETRISTRICKS];\r\n};\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/VictoryCond.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSkate\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tSkate/VictoryCond.cpp\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/07/01\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tDefines various victory conditions for a game\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <sk/modules/skate/score.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/modules/skate/victorycond.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Game\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   PrivateFunctions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCVictoryCondition::CVictoryCondition() //: Lst::Node< CVictoryCondition >( this )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCHighestScoreVictoryCondition::CHighestScoreVictoryCondition() : CVictoryCondition()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCHighestScoreVictoryCondition::ConditionComplete()\r\n{\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCHighestScoreVictoryCondition::PrintDebugInfo()\r\n{\r\n//\tprintf( \"Found CHighestScoreVictoryCondition\\n\" );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCHighestScoreVictoryCondition::IsTerminal()\r\n{\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCHighestScoreVictoryCondition::IsWinner( uint32 skater_num )\r\n{\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tfor ( uint32 i = 0; i < skate_mod->GetNumSkaters(); i++)\r\n\t{\r\n\t\tif ( i != skater_num )\r\n\t\t{\r\n\t\t\tMdl::Score* pTestThisScore = skate_mod->GetSkater(skater_num)->GetScoreObject();\r\n\r\n\t\t\t// score object\r\n\t\t\tMdl::Score* pScore = skate_mod->GetSkater(i)->GetScoreObject();\r\n\r\n\t\t\tif ( pTestThisScore->GetTotalScore() < pScore->GetTotalScore() )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCScoreReachedVictoryCondition::CScoreReachedVictoryCondition( uint32 target_score ) : CVictoryCondition()\r\n{\r\n\tm_TargetScore = target_score;\r\n\r\n//\tPrintDebugInfo();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCScoreReachedVictoryCondition::ConditionComplete()\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tif( skate_mod->GetGameMode()->IsTeamGame())\r\n\t{\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\tLst::Search< GameNet::PlayerInfo > sh;\r\n\t\tGameNet::PlayerInfo* player;\r\n\t\tint i;\r\n\t\tint total_score[GameNet::vMAX_TEAMS] = {0};\r\n\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tMdl::Score* pScore = player->m_Skater->GetScoreObject();\r\n\r\n\t\t\ttotal_score[player->m_Team] += pScore->GetTotalScore();\r\n\t\t}\r\n\r\n\t\tfor( i = 0; i < GameNet::vMAX_TEAMS; i++ )\r\n\t\t{\r\n\t\t\tif( total_score[i] >= (int32)m_TargetScore )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor ( uint32 i = 0; i < skate_mod->GetNumSkaters(); i++)\r\n\t\t{\r\n\t\t\t// score object\r\n\t\t\tMdl::Score* pScore = skate_mod->GetSkater(i)->GetScoreObject();\r\n\t\t\t\r\n\t\t\tif ( pScore->GetTotalScore() >= (int32)m_TargetScore )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCScoreReachedVictoryCondition::PrintDebugInfo()\r\n{\r\n\tprintf( \"Found CScoreReachedVictoryCondition %d\\n\", m_TargetScore );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tCScoreReachedVictoryCondition::GetTargetScore( void )\r\n{\r\n\treturn m_TargetScore;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCScoreReachedVictoryCondition::IsTerminal()\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCScoreReachedVictoryCondition::IsWinner( uint32 skater_num )\r\n{\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tfor ( uint32 i = 0; i < skate_mod->GetNumSkaters(); i++)\r\n\t{\r\n\t\tif ( i != skater_num )\r\n\t\t{\r\n\t\t\tMdl::Score* pTestThisScore = skate_mod->GetSkater(skater_num)->GetScoreObject();\r\n\r\n\t\t\t// score object\r\n\t\t\tMdl::Score* pScore = skate_mod->GetSkater(i)->GetScoreObject();\r\n\r\n\t\t\tif ( pTestThisScore->GetTotalScore() < pScore->GetTotalScore() )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCGoalsCompletedVictoryCondition::CGoalsCompletedVictoryCondition( void )\r\n: CVictoryCondition()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool GoalAttackComplete()\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tGame::CGoalManager* pGoalManager;\r\n\t\r\n\tpGoalManager = Game::GetGoalManager();\r\n\tif( skate_mod->GetGameMode()->IsTeamGame())\r\n\t{\r\n\t\tint i, num_selected_goals;\r\n\r\n\t\tnum_selected_goals = pGoalManager->GetNumSelectedGoals();\r\n\t\tfor( i = 0; i < skate_mod->GetGameMode()->NumTeams(); i++ )\r\n\t\t{\r\n\t\t\tif( gamenet_man->GetTeamScore( i ) >= num_selected_goals )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tuint32 i, j, num_goals;\r\n\t\tbool completed_all;\r\n\t\tGame::CGoal* pGoal;\r\n\t\t\r\n\t\tnum_goals = pGoalManager->GetNumGoals();\r\n\t\tfor( i = 0; i < skate_mod->GetNumSkaters(); i++ )\r\n\t\t{\r\n\t\t\tObj::CSkater* skater = skate_mod->GetSkater(i);\r\n\t\t\tcompleted_all = true;\r\n\t\t\tfor( j = 0; j < num_goals; j++ )\r\n\t\t\t{\r\n\t\t\t\tpGoal = pGoalManager->GetGoalByIndex( j );\r\n\r\n\t\t\t\tif( pGoal->GetParents()->m_relative != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tif( pGoal->IsSelected())\r\n\t\t\t\t{\r\n\t\t\t\t\tif( pGoal->HasWonGoal( skater->GetID()) == false )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcompleted_all = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}    \r\n\r\n\t\t\tif( completed_all )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCGoalsCompletedVictoryCondition::ConditionComplete()\r\n{\r\n\treturn GoalAttackComplete();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCGoalsCompletedVictoryCondition::IsWinner( uint32 skater_num )\r\n{\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCGoalsCompletedVictoryCondition::IsTerminal()\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCGoalsCompletedVictoryCondition::PrintDebugInfo()\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCBestComboVictoryCondition::CBestComboVictoryCondition( uint32 num_combos ) : CVictoryCondition()\r\n{\r\n\tm_NumCombos = num_combos;\r\n\r\n//\tPrintDebugInfo();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCBestComboVictoryCondition::ConditionComplete()\r\n{\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCBestComboVictoryCondition::PrintDebugInfo()\r\n{\r\n\tprintf( \"Found CBestComboVictoryCondition %d\\n\", m_NumCombos );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCBestComboVictoryCondition::IsTerminal()\r\n{\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\r\nCBestComboVictoryCondition::IsWinner( uint32 skater_num )\r\n{\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tfor ( uint32 i = 0; i < skate_mod->GetNumSkaters(); i++)\r\n\t{\r\n\t\tif ( i != skater_num )\r\n\t\t{\r\n\t\t\tMdl::Score* pTestThisScore = skate_mod->GetSkater(skater_num)->GetScoreObject();\r\n\r\n\t\t\t// score object\r\n\t\t\tMdl::Score* pScore = skate_mod->GetSkater(i)->GetScoreObject();\r\n\r\n\t\t\tif ( pTestThisScore->GetTotalScore() < pScore->GetTotalScore() )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCVictoryCondition*\tCreateVictoryConditionInstance( Script::CScriptStructure* p_structure )\r\n{\r\n\t\r\n\r\n\tDbg_Assert( p_structure );\r\n\r\n\tuint32 condition_type;\r\n\tp_structure->GetChecksum( \"type\", &condition_type, true );\r\n\r\n\tCVictoryCondition* pVictoryCondition = NULL;\r\n\t\r\n\tswitch ( condition_type )\r\n\t{\r\n\t\tcase vVICTORYCOND_HIGHESTSCORE:\r\n\t\t{\r\n\t\t\tpVictoryCondition = new CHighestScoreVictoryCondition( );\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase vVICTORYCOND_TARGETSCORE:\r\n\t\t{\r\n\t\t\tint target_score;\r\n\t\t\tp_structure->GetInteger( \"score\", &target_score, true );\r\n\t\t\tpVictoryCondition = new CScoreReachedVictoryCondition( (uint32)target_score );\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase vVICTORYCOND_BESTCOMBO:\r\n\t\t{\r\n\t\t\tint num_combos;\r\n\t\t\tp_structure->GetInteger( \"num_combos\", &num_combos, true );\r\n\t\t\tpVictoryCondition = new CBestComboVictoryCondition( (uint32)num_combos );\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase vVICTORYCOND_COMPLETEGOALS:\r\n\t\t{\r\n\t\t\tpVictoryCondition = new CGoalsCompletedVictoryCondition;\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase vVICTORYCOND_LASTMANSTANDING:\r\n\t\t{\r\n\t\t\tpVictoryCondition = new CLastManStandingVictoryCondition;\r\n\t\t}\r\n\t\tbreak;\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"Unrecognized victory condition type %08x %s\", condition_type, Script::FindChecksumName( condition_type ) ));\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\r\n\treturn pVictoryCondition;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCLastManStandingVictoryCondition::CLastManStandingVictoryCondition( void )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCLastManStandingVictoryCondition::ConditionComplete()\r\n{\r\n\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\tGameNet::PlayerInfo* player;\r\n\r\n\t// This logic may seem strange. Basically, when ConditionComplete() returns true,\r\n\t// the local skater ends his run and he can observe other players. So, it will return\r\n\t// true when his hit points have been depleted rather than when he has won.\r\n\r\n\tplayer = gamenet_man->GetLocalPlayer();\r\n\tif( player && player->m_Skater )\r\n\t{\r\n\t\tMdl::Score* pScore = player->m_Skater->GetScoreObject();\r\n\r\n\t\tif( pScore->GetTotalScore() <= 0 )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCLastManStandingVictoryCondition::PrintDebugInfo()\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCLastManStandingVictoryCondition::IsTerminal()\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCLastManStandingVictoryCondition::IsWinner( uint32 skater_num )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\t// score object\r\n\tMdl::Score* pScore = skate_mod->GetSkater(skater_num)->GetScoreObject();\r\n\tif( pScore && ( pScore->GetTotalScore() > 0 ))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Game\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/VictoryCond.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSkate\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tSkate/VictoryCond.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/07/01\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tDefines various victory conditions for a game\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __MODULES_SKATE_VICTORYCOND_H\r\n#define __MODULES_SKATE_VICTORYCOND_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Script\r\n{\r\n    class CStruct;\r\n}\r\n        \r\nnamespace Game\r\n{\r\n \r\nconst uint32 vVICTORYCOND_HIGHESTSCORE = 0x8f30fd26;\r\nconst uint32 vVICTORYCOND_TARGETSCORE = 0x71cd53a2;\r\nconst uint32 vVICTORYCOND_BESTCOMBO = 0x6fad9811;\r\nconst uint32 vVICTORYCOND_COMPLETEGOALS = 0x6fc19399;\t// complete_goals\r\nconst uint32 vVICTORYCOND_LASTMANSTANDING = 0xcc06880f;\t// last_man_standing\r\n   \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CVictoryCondition : public Spt::Class\r\n{\r\n\t\r\n\r\npublic:\r\n\tCVictoryCondition();\r\n\tvirtual\t\t\t\t\t~CVictoryCondition() {}\r\n\tvirtual bool\t\t\tIsWinner( uint32 skater_num ) { return false; }\r\n\tvirtual bool\t\t\tIsTerminal() = 0;\r\n\tvirtual bool\t\t\tConditionComplete() = 0;\r\n\tvirtual bool\t\t\tPrintDebugInfo() = 0;\r\n};\r\n\r\nclass CHighestScoreVictoryCondition : public  CVictoryCondition\r\n{\r\npublic:\r\n\tCHighestScoreVictoryCondition();\r\n\tbool\t\t\t\t\tConditionComplete();\r\n\tbool\t\t\t\t\tPrintDebugInfo();\r\n\tbool\t\t\t\t\tIsTerminal();\r\n\tbool\t\t\t\t\tIsWinner( uint32 skater_num );\r\n};\r\n\r\nclass CScoreReachedVictoryCondition : public  CVictoryCondition\r\n{\r\npublic:\r\n\tCScoreReachedVictoryCondition( uint32 target_score );\r\n\tbool\t\t\t\t\tConditionComplete();\r\n\tbool\t\t\t\t\tPrintDebugInfo();\r\n\tbool\t\t\t\t\tIsTerminal();\r\n\tbool\t\t\t\t\tIsWinner( uint32 skater_num );\r\n\tint\t\t\t\t\t\tGetTargetScore( void );\r\nprotected:\r\n\tuint32\t\t\t\tm_TargetScore;\r\n};\r\n\r\nbool GoalAttackComplete();\r\n\r\nclass CGoalsCompletedVictoryCondition : public  CVictoryCondition\r\n{\r\npublic:\r\n\tCGoalsCompletedVictoryCondition();\r\n\tbool\t\t\t\t\tConditionComplete();\r\n\tbool\t\t\t\t\tPrintDebugInfo();\r\n\tbool\t\t\t\t\tIsTerminal();\r\n\tbool\t\t\t\t\tIsWinner( uint32 skater_num );\r\n};\r\n\r\nclass CBestComboVictoryCondition : public  CVictoryCondition\r\n{\r\npublic:\r\n\tCBestComboVictoryCondition( uint32 num_combos );\r\n\tbool\t\t\t\t\tConditionComplete();\r\n\tbool\t\t\t\t\tPrintDebugInfo();\r\n\tbool\t\t\t\t\tIsTerminal();\r\n\tbool\t\t\t\t\tIsWinner( uint32 skater_num );\r\nprotected:\r\n\tuint32\t\t\t\tm_NumCombos;\r\n};\r\n\r\nclass CLastManStandingVictoryCondition : public CVictoryCondition\r\n{\r\npublic:\r\n\tCLastManStandingVictoryCondition( void );\r\n\tbool\t\t\t\t\tConditionComplete();\r\n\tbool\t\t\t\t\tPrintDebugInfo();\r\n\tbool\t\t\t\t\tIsTerminal();\r\n\tbool\t\t\t\t\tIsWinner( uint32 skater_num );\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCVictoryCondition*\tCreateVictoryConditionInstance( Script::CStruct* p_structure );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\r\n} // namespace Game\r\n\r\n#endif // __MODULES_SKATE_VICTORYCOND_H"
  },
  {
    "path": "Code/Sk/Modules/Skate/competition.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tskate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tskate\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcompetition.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t18/06/01\t-\tMick\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\thandles playing single player competitions\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/math/math.h>\t\t\t\t\t\t // for Mth::Rnd2()\r\n#include <modules/skate/competition.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/string.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/array.h>\r\n\r\n#include <sk/modules/skate/skate.h> \r\n#include <sk/modules/skate/goalmanager.h>\r\n\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/objects/playerprofilemanager.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mdl\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCCompetition::CCompetition( Script::CStruct* pParams )\r\n{\r\n\tmp_params = new Script::CStruct();\r\n}\r\n\r\nCCompetition::~CCompetition()\r\n{\r\n}\r\n\t\r\nvoid CCompetition::EditParams( Script::CStruct* pParams )\r\n{\r\n\tmp_params->AppendStructure( pParams );\r\n}\r\n\r\nvoid CCompetition::ResetJudgement()\r\n{\r\n\tm_total_score = 0.0f;\r\n\tm_bail_points = 0.0f;\r\n}\r\n\r\nint CLeaderBoardEntry::GetTotalScore(int round)\r\n{\r\n\tint score1 = 0;\r\n\tint score2 = 0;\r\n\t\r\n\tfor (int i=0;i<round+1;i++)\r\n\t{\r\n\t\tif (m_score[i] > score1)\r\n\t\t{\r\n\t\t\tscore2 = score1;\r\n\t\t\tscore1 = m_score[i];\r\n\t\t}\r\n\t\telse\r\n\t\tif (m_score[i] > score2)\r\n\t\t{\r\n\t\t\tscore2 = m_score[i];\r\n\t\t}\r\n\t}\r\n\treturn score1 + score2;\t\r\n}\r\n\r\n\r\n// start the competition, and pre-calculate all\r\n// the scores\r\nvoid\t   CCompetition::StartCompetition(float bronze, float silver, float gold, float bronze_score, float silver_score, float gold_score, float bail)\r\n{\r\n\t// store the defining parameters\r\n\r\n\tm_bronze = bronze;\r\n\tm_silver = silver;\r\n\tm_gold = gold;\r\n\tm_bronze_score = bronze_score;\r\n\tm_silver_score = silver_score;\r\n\tm_gold_score = gold_score;\r\n\tm_bail = bail;\r\n\t\r\n\t\r\n\tm_end_competition = false;\r\n\r\n\t// Get the current profile\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=pSkate->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pSkaterProfile=pPlayerProfileManager->GetCurrentProfile();\r\n\r\n\t// need to use GetDisplayName() wrapper function instead of GetUIString(), bec. ui string can now theoretically be empty\r\n\tm_leader_board[0].m_name = pSkaterProfile->GetDisplayName();\r\n\r\n\t// Let's count how many pros there are, so we can pcik from them at random\r\n\r\n\tint\tpossible_pros = pPlayerProfileManager->GetNumProfileTemplates();\t\r\n\r\n// get an array of pros, except the one that has the same name as me\r\n\tint\tpro_order[100];\r\n\tint num_pros = 0;\r\n\tfor (int i = 0;i<possible_pros;i++)\r\n\t{\r\n\t\r\n\t\tObj::CSkaterProfile* pProfile = pPlayerProfileManager->GetProfileTemplateByIndex(i);\r\n\t\t\r\n//\t\tprintf (\"Pro=%d, Secret = %d, name = %s\",pProfile->IsPro(), pProfile->IsSecret(), pProfile->GetDisplayName());\r\n\t\t\t\t\r\n\t\tif (!pProfile->IsPro() || pProfile->IsSecret() || Script::GenerateCRC(m_leader_board[0].m_name.getString()) == Script::GenerateCRC(pProfile->GetDisplayName()))\r\n\t\t{\r\n\t\t\t// skip over this one\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpro_order[num_pros++] = i;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// shuffle them\r\n\tfor (int i = 0;i<num_pros;i++)\r\n\t{\r\n\t\tint\tother = Mth::Rnd2(num_pros);\r\n\t\tint t = pro_order[i];\r\n\t\tpro_order[i] = pro_order[other];\r\n\t\tpro_order[other] = t;\r\n\t}\r\n\r\n\t// we initially populate the table with entries for each skater\r\n\t// other than skater 0, with random scores for 1st, 2nd and 3rd\r\n\t// that are close to the requied scores\r\n\t// and then populate the \"round\" scores with scores \r\n\t// that will eventually add up to the final score\r\n\t\r\n\t// first determine a random order for the 7 other skaters\r\n\t\r\n\tint\torder[vMAX_PLAYERS-1];\r\n\t\r\n\t// set up an initial linear order\r\n\tfor (int i = 0;i<vMAX_PLAYERS-1;i++)\r\n\t{\r\n\t\torder[i] = i+1;\r\n\t}\r\n\t\r\n\t// shuffle the list of players\r\n\tfor (int i = 0;i<vMAX_PLAYERS-1;i++)\r\n\t{\r\n\t\tint swap = Mth::Rnd2(vMAX_PLAYERS-1);\r\n\t\tint t = order[i];\r\n\t\torder[i] = order[swap];\r\n\t\torder[swap] = t;\r\n\t}\r\n\r\n\t// zero out the initial player\r\n//\tm_leader_board[0].mp_name = \"PLAYER 1\";\r\n\tm_leader_board[0].m_player_number = 0;\r\n\tfor (int round = 0; round < vNUM_ROUNDS; round++)\r\n\t{\r\n\t\tm_leader_board[0].m_score[round] = 0;\r\n\t}\r\n\r\n\t// add in the other players in the shuffled order\r\n\t// for the first three, we need to calculate the score they are going to get\r\n\t\r\n\tbronze += Mth::PlusOrMinus(2.0f);\t\r\n\tsilver += Mth::PlusOrMinus(2.0f);\t\r\n\tgold += Mth::PlusOrMinus(2.0f);\t\r\n\r\n\tif (silver >= gold)\r\n\t{\r\n\t\tsilver = gold - 0.1f;\r\n\t}\r\n\tif (bronze >= silver)\r\n\t{\r\n\t\tbronze = silver - 0.1f;\r\n\t}\r\n\t\r\n\t\r\n\t// go through all remaining players, and fill in the blanks\t\r\n\tfor (int i = 0;i<vMAX_PLAYERS-1;i++)\r\n\t{\r\n\t\tint player = i+1;\r\n\t\tm_leader_board[player].m_player_number = order[i];\t\t// say which player is in this position\t\t\r\n\t\t// ... note, need to get the name in here.\r\n\t\t// ...\r\n\t\t\r\n\t\tScript::CArray* pLeaderBoardNames;\r\n\t\tif ( mp_params->GetArray( CRCD(0x1cc6f48d,\"leader_board_names\"), &pLeaderBoardNames, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( pLeaderBoardNames->GetSize() == vMAX_PLAYERS - 1, ( \"leader_board_names has wrong size.  Needs to be %i\", vMAX_PLAYERS - 1 ) );\r\n\t\t\tm_leader_board[player].m_name = pLeaderBoardNames->GetString( i );\r\n\t\t}\r\n\t\telse\r\n\t\t\tm_leader_board[player].m_name = pPlayerProfileManager->GetProfileTemplate(pPlayerProfileManager->GetProfileTemplateChecksum(pro_order[i]))->GetDisplayName();\r\n\t\t\r\n\t\t\r\n\t\t// now calculate the score\r\n\t\tfloat score = 0.0f;\r\n\t\tif (i == 0) score = gold;\r\n\t\telse if (i == 1) score = silver;\r\n\t\telse if (i == 2) score = bronze;\r\n\t\telse\r\n\t\t{\r\n\t\t\t// scores for the player after bronze are essentially any random number less than bronze\r\n\t\t\tscore = bronze - (bronze/8) + Mth::PlusOrMinus(bronze/8);\r\n\t\t\tif (score >= bronze)\r\n\t\t\t{\r\n\t\t\t\tscore = bronze - 0.1f;\r\n\t\t\t}\t\t\t\r\n\t\t}\r\n\t\t// now we have the total score, we calculate the random components that\r\n\t\t// will add up to that score\r\n\t\t// the final sore is calculated as the average of the best of two scores\r\n\t\t// So... calculate two scores that add up to twice the total score\r\n\t\t// then add a third that is less than both of these\r\n\t\t// and put these in random order\r\n\t\t// \r\n\t\tfloat score1 = score + Mth::PlusOrMinus(2.0f);\r\n\t\tfloat score2 = score*2.0f - score1;\r\n\t\tfloat lower = score1;\r\n\t\tif (score2 <lower)\r\n\t\t{\r\n\t\t\tlower = score2;\r\n\t\t}\r\n\t\tint pos1 = Mth::Rnd2(vNUM_ROUNDS);\r\n\t\tint pos2 = pos1;\r\n\t\twhile (pos2 == pos1)\r\n\t\t{\r\n\t\t\tpos2 = Mth::Rnd2(vNUM_ROUNDS);\r\n\t\t}\r\n\t\t\r\n\t\tfor (int round = 0;round <vNUM_ROUNDS;round++)\r\n\t\t{\r\n\t\t\t// all other scores default to numbers just below the lower of the two scores\r\n\t\t\t// m_leader_board[player].m_score[round] = (int)(10.0f*(lower - 2.0f + Mth::PlusOrMinus(1.9f)));\r\n\t\t\tm_leader_board[player].m_score[round] = (int)Mth::Round((lower - 2.0f + Mth::PlusOrMinus(1.9f)));\r\n\t\t}\r\n\t\t// finally fill in the two higher scores\r\n\t\t// into the randomly chosen poistions\r\n\t\t// m_leader_board[player].m_score[pos1] = (int)(score1*10.0f);\r\n\t\t// m_leader_board[player].m_score[pos2] = (int)(score2*10.0f);\r\n\t\tm_leader_board[player].m_score[pos1] = (int)Mth::Round(score1);\r\n\t\tm_leader_board[player].m_score[pos2] = (int)Mth::Round(score2);\r\n\t}\r\n\r\n\tprintf (\"\\n\\n\");\t\r\n\t// let up now print out the fruits of our efforts\r\n\tfor (int i = 0;i<vMAX_PLAYERS;i++)\r\n\t{\r\n\t\tprintf (\"%d: pos %d, name %12s, %3d, %3d, %3d, %3d\\n\",\r\n\t\t\ti,\r\n\t\t\tm_leader_board[i].m_player_number,\r\n\t\t\tm_leader_board[i].m_name.getString(),\r\n\t\t\tm_leader_board[i].m_score[0],\r\n\t\t\tm_leader_board[i].m_score[1],\r\n\t\t\tm_leader_board[i].m_score[2],\r\n\t\t\tm_leader_board[i].GetTotalScore(3));\r\n\t\t\t\t\t\t\r\n\t}\r\n\tSort();\r\n\r\n\tconst char* p_first_place_name;\r\n\tif ( mp_params->GetString( CRCD(0xfaf19012,\"first_place_name\"), &p_first_place_name, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tm_leader_board[0].m_name = p_first_place_name;\r\n\t}\r\n\t\r\n\tprintf (\"\\nSorted\\n\");\t\r\n\t// let up now print out the fruits of our efforts\r\n\tfor (int i = 0;i<vMAX_PLAYERS;i++)\r\n\t{\r\n\t\tprintf (\"%d: pos %d, name %12s, %3d, %3d, %3d, %3d\\n\",\r\n\t\t\ti,\r\n\t\t\tm_leader_board[i].m_player_number,\r\n\t\t\tm_leader_board[i].m_name.getString(),\r\n\t\t\tm_leader_board[i].m_score[0],\r\n\t\t\tm_leader_board[i].m_score[1],\r\n\t\t\tm_leader_board[i].m_score[2],\r\n\t\t\tm_leader_board[i].GetTotalScore(3));\r\n\t\t\t\t\t\t\r\n\t}\r\n\r\n// Default names for judges (dunno if we'll ever change it though...).\t\r\n#if (ENGLISH == 0)\r\n\tm_judge_name[0] = (char*)Script::GetLocalString( \"comp_str_Judge1\");\r\n\tm_judge_name[1] = (char*)Script::GetLocalString( \"comp_str_Judge2\");\r\n\tm_judge_name[2] = (char*)Script::GetLocalString( \"comp_str_Judge3\");\r\n\tm_judge_name[3] = (char*)Script::GetLocalString( \"comp_str_Judge4\");\r\n\tm_judge_name[4] = (char*)Script::GetLocalString( \"comp_str_Judge5\");\r\n#else\t\r\n\tm_judge_name[0] = \"Judge 1\";\r\n\tm_judge_name[1] = \"Judge 2\";\r\n\tm_judge_name[2] = \"Judge 3\";\r\n\tm_judge_name[3] = \"Judge 4\";\r\n\tm_judge_name[4] = \"Judge 5\";\r\n#endif\t\r\n\tm_current_round = -1;\t\r\n}\r\n\r\nvoid\t   CCompetition::StartRun()\r\n{\r\n\tm_current_round++;\r\n\tResetJudgement();\r\n}\r\n\r\n\r\nvoid CCompetition::EndRun(int score)\r\n{\r\n\t// don't end a run if we're not in a comp\r\n\tif ( m_end_competition )\r\n\t\treturn;\r\n\r\n\tint i;\r\n\t\r\n\tprintf (\"Ending Competition with score of %d\\n\",score);\r\n\tprintf (\"Bronze %f, silver %f, gold %f\\n\",m_bronze_score,m_silver_score,m_gold_score);\r\n\t\r\n\tfloat points = 0.0f;\r\n\tif (score < m_bronze_score)\r\n\t{\r\n\t\tpoints = m_bronze * score / m_bronze_score;\t\t\r\n\t}\r\n\telse if (score < m_silver_score)\r\n\t{\r\n\t\tpoints = m_bronze + (m_silver - m_bronze) * (score - m_bronze_score) / (m_silver_score - m_bronze_score);\r\n\t}\r\n\telse if (score < m_gold_score)\r\n\t{\r\n\t\tpoints = m_silver + (m_gold - m_silver) * (score - m_silver_score) / (m_gold_score - m_silver_score);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// we have scored above the gold score\r\n\t\t// so interpolate up to perfect (100 for gold * 2)\r\n\t\tpoints = m_gold + (100.0f - m_gold) * (score - m_gold_score) / ( m_gold_score*2 - m_gold_score); \r\n\t}\r\n\r\n\tprintf (\"points calculated at %f\\n\",points);\r\n\r\n\t// Now we have the score, so decrement it by the bail points\t\r\n\tpoints -= m_bail_points;\r\n\t\r\n\tprintf (\"points decremented by %f bail points to %f\\n\",m_bail_points,points);\r\n\t\r\n\t\r\n\t// we've got the total score now (in points, for this round)\r\n\t// so store it\t\r\n\tm_total_score = points;\r\n\t\r\n\tif (m_total_score > 99.9f)\r\n\t\tm_total_score = 99.9f;\r\n\r\n\t// we calculate a \"varience\", which is the maximum amount\r\n\t// a score can be randomly varied\r\n\t// this ranges from 10 to 0 as the actual score goes from 0 to 99.9\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\tfloat variance = ( 99.9f - m_total_score ) / 10.0f;\r\n\r\n\t// perform some initial varying by half the variance\r\n\t// to make the score seen more random \r\n\tm_total_score += Mth::PlusOrMinus(variance/2);\r\n\r\n\t// clamp it, just to be safe\t\r\n\tif (m_total_score > 99.9f)\r\n\t\tm_total_score = 99.9f;\r\n\tif (m_total_score < 0.0f)\r\n\t\tm_total_score = 0.0f;\r\n\t\t\t\t\t\t\t\t\r\n\t// and find the n Judges scores\r\n\t// here the final score is the average of the top three scores.\r\n\t// so we need to generate three scores that add up to the \r\n\t// total score\r\n\t\r\n\t\r\n\tm_score[0] = m_total_score + Mth::PlusOrMinus(variance);\r\n\tif (m_score[0] > 99.85f)\r\n\t\tm_score[0] = 99.9f;\r\n\tif (m_score[0] < 0.0f)\r\n\t\tm_score[0] = 0.0f;\t\r\n\tm_score[1] = m_total_score + Mth::PlusOrMinus(variance);\r\n\tif (m_score[1] > 99.85f)\r\n\t\tm_score[1] = 99.9f;\r\n\tif (m_score[1] < 0.0f)\r\n\t\tm_score[1] = 0.0f;\r\n\tm_score[2] = (m_total_score * 3.0f) - (m_score[0] + m_score[1]);\r\n\tif (m_score[2] < 0.0f)\r\n\t\tm_score[2] = 0.0f;\r\n\tif (m_score[2] > 99.85f)\r\n\t\tm_score[2] = 99.9f;\r\n\t\t\r\n\t\t\r\n\tm_score[0] = (float)( (int) (m_score[0] * 10.0f)) /10.0f + 0.0001f;\r\n\tm_score[1] = (float)( (int) (m_score[1] * 10.0f)) /10.0f + 0.0001f;\r\n\tm_score[2] = (float)( (int) (m_score[2] * 10.0f)) /10.0f + 0.0001f;\r\n\t\r\n\tm_score[0] = (int)Mth::Round(m_score[0]);\r\n\tm_score[1] = (int)Mth::Round(m_score[1]);\r\n\tm_score[2] = (int)Mth::Round(m_score[2]);\r\n\r\n\tif ( m_score[0] > 99 )\r\n\t\tm_score[0] = 99;\r\n\tif ( m_score[1] > 99 )\r\n\t\tm_score[1] = 99;\r\n\tif ( m_score[2] > 99 )\r\n\t\tm_score[2] = 99;\r\n\t\r\n\t// recalculate the total score\r\n\tm_total_score = ((float)(m_score[0]) + (float)(m_score[1]) + (float)(m_score[2])) / 3;\r\n\tm_total_score = (int)Mth::Round( m_total_score );\r\n\tif ( m_total_score > 99 )\r\n\t\tm_total_score = 99;\r\n\t// m_judge_score[m_current_round] = (int)(10.0f * m_total_score + 0.5f);\r\n\tm_judge_score[m_current_round] = (int)m_total_score;\r\n\r\n\tprintf (\"3 scores are %f,%f,%f, total is %f\\n\",m_score[0],m_score[1],m_score[2],m_total_score);\r\n\r\n\t// Stick the total score in the correct place in the leaderboard\t\r\n\tfor (i = 0;i<vMAX_PLAYERS;i++)\r\n\t{\r\n\t\tif (m_leader_board[i].m_player_number == 0)\r\n\t\t{\r\n\t\t\tm_leader_board[i].m_score[m_current_round] = m_judge_score[m_current_round];\r\n\t\t}\r\n\t}\r\n\t\r\n\t// and re-sort it\t\r\n\tSort();\t\r\n\t\r\n\t// re-calculate our\tplacing\r\n\r\n\tfor (i = 0;i<vMAX_PLAYERS;i++)\r\n\t{\r\n\t\tif (m_leader_board[i].m_player_number == 0)\r\n\t\t{\r\n\t\t\tm_place = i+1;\t\t\r\n\t\t}\r\n\t}\t\r\n\r\n\t// then fill in the remaining judge scores with scores that are lower than the\r\n\t// lowest of these three scores\r\n\r\n\t// calculate lowest score\t\r\n\tfloat lowest = m_score[0];\r\n\tif (m_score[1] < lowest)\r\n\t\tlowest = m_score[1];\r\n\tif (m_score[2] < lowest)\r\n\t\tlowest = m_score[2];\r\n\t\t\r\n\tprintf(\"Lowest = %f\\n\",lowest);\r\n\t\t\r\n\t// add in remaining scores, in a range of (lowest - 2* variance) to (lowest)\r\n\tfor (i = 3; i< vNUM_JUDGES; i++)\r\n\t{\r\n\t\tm_score[i] = lowest - variance + Mth::PlusOrMinus(variance);\t\t\r\n\t\tprintf (\"Score %d is %f\\n\",i,m_score[i]);\r\n\t}\r\n\r\n\t// set any negative scores to 0.0f\t   \r\n\t// (this will not effect the three highest scores\r\n\tfor (i = 0; i< vNUM_JUDGES; i++)\r\n\t{\r\n\t\tif (m_score[i] < 0.0f)\r\n\t\t{\r\n\t\t\tm_score[i] = 0.0f;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Finally, shuffle the scores into random order\r\n\t// shuffle the list of players\r\n\tfor (i = 0;i<vNUM_JUDGES-1;i++)\r\n\t{\r\n\t\tint swap = Mth::Rnd2(vNUM_JUDGES);\r\n\t\tfloat t = m_score[i];\r\n\t\tm_score[i] = m_score[swap];\r\n\t\tm_score[swap] = t;\r\n\t}\r\n\t\r\n\tGame::CGoalManager* pGoalManager = Game::GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\tif ( pGoalManager->IsInCompetition() )\r\n\t{\r\n\t\t// and let us have a look at what we come up with;\r\n\t\tScript::CStruct* p_run_scores = new Script::CStruct();\r\n\t\t// pack the scores in a carray to make them easy to deal with in script\r\n\t\tScript::CArray* p_run_scores_array = new Script::CArray();\r\n\t\tp_run_scores_array->SetSizeAndType( vNUM_JUDGES, ESYMBOLTYPE_STRUCTURE );\r\n\t\tprintf( \"\\nJudgement Day\\n\\n\" );\r\n\t\tfor ( i = 0; i < vNUM_JUDGES; i++ )\r\n\t\t{\r\n\t\t\t// add an integer version of this score to the params, so it's \r\n\t\t\t// easy to deal with in script\r\n\t\t\tScript::CStruct* p_temp = new Script::CStruct();\r\n\t\t\tp_temp->AddInteger( \"score\", (int)Mth::Round( m_score[i] ) );\r\n\r\n\t\t\t// add a flag to the top judges\r\n\t\t\tif ( IsTopJudge( i ) )\r\n\t\t\t{\r\n\t\t\t\tp_temp->AddChecksum( NONAME, CRCD( 0x7b1b959f, \"top_judge\" ) );\r\n\t\t\t}\r\n\r\n\t\t\tp_run_scores_array->SetStructure( i, p_temp );\r\n\t\t\tprintf (\"%d: %f Top=%d\\n\",i,m_score[i],IsTopJudge(i));\r\n\t\t}\t\r\n\t\t\r\n\t\tp_run_scores->AddArray( \"scores\", p_run_scores_array );\r\n\r\n\t\t// add the total score\r\n\t\t// p_run_scores->AddInteger( \"total_score\", (int)Mth::Round( ( m_total_score * 10 ) ) );\r\n\t\tp_run_scores->AddInteger( \"total_score\", (int)Mth::Round( ( m_total_score ) ) );\r\n\r\n\t\tScript::CleanUpArray( p_run_scores_array );\r\n\t\tdelete p_run_scores_array;\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tScript::CScript *p_script=Script::SpawnScript( \"goal_comp_show_run_scores\", p_run_scores );\r\n\t\tp_script->SetCommentString(\"Spawned from CCompetition::EndRun(...)\");\r\n\t\t#else\r\n\t\tScript::SpawnScript( \"goal_comp_show_run_scores\", p_run_scores );\r\n\t\t#endif\r\n\t\tdelete p_run_scores;\r\n\t}\r\n}\r\n\r\n// This function should be called every time the skater bails\r\nvoid \t   CCompetition::Bail()\r\n{\r\n\t\tm_bail_points += m_bail + Mth::PlusOrMinus(m_bail/2);\r\n}\r\n\r\nvoid\t   CCompetition::Sort()\r\n{\r\n\t// sort the list, based on total score \r\n\r\n\tint round = m_current_round;\t\t\t\t\t\t\t\t\t  \r\n\t// if the competition has ended (maybe early), then total up for all the rounds\t\r\n\tif (CompetitionEnded())\r\n\t{\r\n\t\tround = 2;\r\n\t}\r\n\t\t\t\t\t\t\t \r\n\tfor (int i=0;i<vMAX_PLAYERS-1;i++)\r\n\t{\r\n\t\tint high = i;\r\n\t\tfor (int j=i+1; j<vMAX_PLAYERS;j++)\r\n\t\t{\r\n\t\t\tif (m_leader_board[j].GetTotalScore(round) > m_leader_board[high].GetTotalScore(round))\r\n\t\t\t{\r\n\t\t\t\thigh = j;\r\n\t\t\t}\r\n\t\t\t// give the player the higher position if there is a tie\r\n\t\t\telse if ( m_leader_board[j].m_player_number == 0 && m_leader_board[j].GetTotalScore(round) == m_leader_board[high].GetTotalScore(round) )\r\n\t\t\t{\r\n\t\t\t\thigh = j;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (high != i)\r\n\t\t{\r\n\t\t\tCLeaderBoardEntry t = m_leader_board[high];\r\n\t\t\tm_leader_board[high] = m_leader_board[i];\r\n\t\t\tm_leader_board[i] = t;\r\n\t\t}\r\n\t}\r\n}\r\n\t\r\nint \t   CCompetition::GetPosition(int player)\r\n{\r\n\treturn 0;\r\n}\r\n\r\n\t   \r\nchar *\t\tCCompetition::GetJudgeName(int judge)\r\n{\r\n\treturn m_judge_name[judge];\r\n}\r\n\r\nfloat\t\tCCompetition::GetJudgeScore(int judge)\r\n{\r\n\treturn m_score[judge];\r\n}\r\n\r\nvoid CCompetition::SetupJudgeText()\r\n{\r\n\tGame::CGoalManager* pGoalManager = Game::GetGoalManager();\r\n\tDbg_Assert( pGoalManager );\r\n\r\n\tif ( pGoalManager->IsInCompetition() )\r\n\t{\r\n\t\tScript::CStruct* p_score_params = new Script::CStruct();\r\n\r\n\t\tScript::CArray* p_score_array = new Script::CArray();\r\n\t\tp_score_array->SetSizeAndType( vNUM_JUDGES , ESYMBOLTYPE_STRUCTURE );\r\n\r\n\t\tprintf (\"\\nSetupJudgeText\\n\");\t\r\n\t\t// let up now print out the fruits of our efforts\r\n\t\tfor (int i = 0;i<vMAX_PLAYERS;i++)\r\n\t\t{\r\n\t\t\tprintf (\"%d: pos %d, name %12s, %3d, %3d, %3d, %3d\\n\",\r\n\t\t\t\ti,\r\n\t\t\t\tm_leader_board[i].m_player_number,\r\n\t\t\t\tm_leader_board[i].m_name.getString(),\r\n\t\t\t\tm_leader_board[i].m_score[0],\r\n\t\t\t\tm_leader_board[i].m_score[1],\r\n\t\t\t\tm_leader_board[i].m_score[2],\r\n\t\t\t\tm_leader_board[i].GetTotalScore(3));\r\n\t\t\r\n\t\t}\r\n\r\n\t\tfor ( int i = 0; i < vNUM_JUDGES; i++ )\r\n\t\t{\r\n\t\t\tScript::CStruct* p_leader_board_entry = new Script::CStruct();\r\n\t\t\tp_leader_board_entry->AddString( \"name\", m_leader_board[i].m_name.getString() );\r\n\t\t\tprintf(\"m_current_round: %i\\n\", m_current_round);\r\n\t\t\tp_leader_board_entry->AddInteger( \"score\", m_leader_board[i].GetTotalScore(m_current_round) );\r\n\r\n\t\t\tif ( m_leader_board[i].m_player_number == 0 )\r\n\t\t\t{\r\n\t\t\t\tp_leader_board_entry->AddChecksum( NONAME, CRCD( 0x67e6859a, \"player\" ) );\r\n\t\t\t}\r\n\r\n\t\t\tp_score_array->SetStructure( i, p_leader_board_entry );\r\n\t\t}\r\n\r\n\t\tp_score_params->AddArray( \"leader_board\", p_score_array );\r\n\t\tScript::CleanUpArray( p_score_array );\r\n\t\tdelete p_score_array;\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tScript::CScript *p_script=Script::SpawnScript( \"goal_comp_add_leader_board\", p_score_params );\r\n\t\tp_script->SetCommentString(\"Spawned from CCompetition::SetupJudgeText()\");\r\n\t\t#else\r\n\t\tScript::SpawnScript( \"goal_comp_add_leader_board\", p_score_params );\r\n\t\t#endif\r\n\t\tdelete p_score_params;\r\n\t}\r\n\r\n/*//\tint i_total = 0;\r\n\tfor (int i = 0;i<vNUM_JUDGES;i++)\r\n\t{\r\n\t\tsprintf(Script::GetScriptString(i*2),GetJudgeName(i));\r\n\t\tsprintf(Script::GetScriptString(i*2+1),\"%2.1f\",GetJudgeScore(i));\r\n//\t\tif (IsTopJudge(i))\r\n//\t\t{\r\n//\t\t\ti_total += (int) (GetJudgeScore(i) * 10.0f); \r\n//\t\t}\r\n\t}\t\r\n//\tm_total_score = (float)((int)(10.0f * (m_score[0] + m_score[1] + m_score[2])/3.0f))/10.0f;\t\r\n//\ttotal =         (float)((int)(total / 3.0f))/10.0f;\r\n\t\r\n\t\r\n\tsprintf(Script::GetScriptString(vNUM_JUDGES*2),\"%2.1f\",(float)(m_judge_score[m_current_round]/10.0f));\r\n\r\n\t// and let us set up the leaderboard text as well.....\r\n\tint line;\r\n\tfor (line = 0;line<vMAX_PLAYERS;line++)\r\n\t{\r\n\t\t\r\n\t\tconst char *pC;\t\t\t  // format for name\r\n\t\tconst char *pC21f;\t\t  // format for number\r\n\t\tconst char *xpC21f;\t\t  // format for dark number\r\n\t\r\n\t\tif (m_leader_board[line].m_player_number == 0)\r\n\t\t{\r\n\t\t\t// use yellow colors for skater\r\n\t\t\tpC = \"&C1%s\";\r\n\t\t\tpC21f = \"&C1%2.1f\";\r\n\t\t\txpC21f = \"&C3%2.1f\";\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// and white/grey for other skaters\r\n\t\t\tpC = \"%s\";\r\n\t\t\tpC21f = \"%2.1f\";\r\n\t\t\txpC21f = \"&C2%2.1f\";\r\n\t\t}\r\n\t\t\r\n\t\tsprintf(Script::GetScriptString(12 + line * 5), pC, m_leader_board[line].m_name.getString());\r\n\r\n\t\tint small = 0;\r\n\t\tif (m_leader_board[line].m_score[1] < m_leader_board[line].m_score[small]) small = 1;\r\n\t\tif (m_leader_board[line].m_score[2] < m_leader_board[line].m_score[small]) small = 2;\r\n\r\n\t\tint round = m_current_round;\t\t\t\t\t\t\t\t\t  \r\n\t\t// if the competition has ended (maybe early), then total up for all the rounds\t\r\n\t\tif (CompetitionEnded())\r\n\t\t{\r\n\t\t\tround = 2;\r\n\t\t}\r\n\t\t\t\t\r\n\t\t\r\n\t\tif (round == 2 && small == 0)\r\n\t\t\tsprintf(Script::GetScriptString(12 + line * 5 + 1),xpC21f, (float)(m_leader_board[line].m_score[0]/10.0f));\r\n\t\telse\r\n\t\t\tsprintf(Script::GetScriptString(12 + line * 5 + 1),pC21f, (float)(m_leader_board[line].m_score[0]/10.0f));\r\n\t\t\r\n\t\tif (round >=1)\r\n\t\t{\r\n\t\t\tif (round == 2 && small == 1)\r\n\t\t\t\tsprintf(Script::GetScriptString(12 + line * 5 + 2),xpC21f, (float)(m_leader_board[line].m_score[1]/10.0f));\r\n\t\t\telse\r\n\t\t\t\tsprintf(Script::GetScriptString(12 + line * 5 + 2),pC21f, (float)(m_leader_board[line].m_score[1]/10.0f));\r\n\t\t}\r\n\t\telse\r\n\t\t\tsprintf(Script::GetScriptString(12 + line * 5 + 2), pC,\"-\");\r\n\r\n\t\tif (round >=2)\r\n\t\t{\r\n\t\t\tif (round == 2 && small == 2)\r\n\t\t\t\tsprintf(Script::GetScriptString(12 + line * 5 + 3),xpC21f, (float)(m_leader_board[line].m_score[2]/10.0f));\r\n\t\t\telse\r\n\t\t\t\tsprintf(Script::GetScriptString(12 + line * 5 + 3),pC21f, (float)(m_leader_board[line].m_score[2]/10.0f));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsprintf(Script::GetScriptString(12 + line * 5 + 3),pC, \"-\");\t\t\t\t\r\n\t\t}\r\n\t\t\r\n\t\tsprintf(Script::GetScriptString(12 + line * 5 + 4),pC21f, (float)(m_leader_board[line].GetTotalScore(round)/10.0f));\r\n\t\t\r\n\t}\r\n\t\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=pSkate->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pSkaterProfile=pPlayerProfileManager->GetCurrentProfile();\r\n\tsprintf (Script::GetScriptString(12 + line *5),\tpSkaterProfile->GetDisplayName());\r\n*/\t\r\n}\r\n\r\n// Return true if this is a top 3 judge\r\n// note, has to handle cases where score is the same\r\n// works by sorting the judges, and then seeing if we are in the top three \r\nbool CCompetition::IsTopJudge(int judge)\r\n{\r\n\tint\tjudge_order[vNUM_JUDGES];\r\n\t\r\n\tfor (int i=0;i<vNUM_JUDGES;i++)\r\n\t{\r\n\t\tjudge_order[i] = i;\r\n\t}\r\n\tfor (int i=0;i<vNUM_JUDGES-1;i++)\r\n\t{\r\n\t\tfor (int j = i;j<vNUM_JUDGES;j++)\r\n\t\t{\r\n\t\t\tif (GetJudgeScore(judge_order[i]) < GetJudgeScore(judge_order[j]))\r\n\t\t\t{\r\n\t\t\t\tint\tt=judge_order[i];\r\n\t\t\t\tjudge_order[i]=judge_order[j];\r\n\t\t\t\tjudge_order[j]=t;  \r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// if it is in the top three, then return true\r\n\tif (judge_order[0] == judge || judge_order[1] == judge || judge_order[2] == judge)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n\r\nbool CCompetition::PlaceIs(int place)\r\n{\r\n\treturn \t(place == m_place);\r\n}\r\n\r\nbool CCompetition::RoundIs(int round)\r\n{\r\n\treturn \t(round == m_current_round+1);\t// ............... placign\r\n}\r\n\r\n\r\nvoid CCompetition::EndCompetition()\r\n{\r\n\tm_end_competition = true;\r\n}\r\n\r\nbool CCompetition::CompetitionEnded()\r\n{\r\n\treturn m_end_competition;\r\n}\r\n\r\n\t   \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mdl\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/competition.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tskate3  \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tsk\t\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcompetition.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t6/15/00 - Mick\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t<description>\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __SK_MODULES_COMPETITION_H\r\n#define __SK_MODULES_COMPETITION_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/string/cstring.h>\r\n\r\n#include <gel/scripting/struct.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Mdl\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\n\tenum \r\n\t{\r\n\t\tvMAX_PLAYERS = 8,\r\n\t\tvNUM_ROUNDS = 3,\r\n\t\tvNUM_JUDGES = 5,\r\n\t};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nclass\t\tCLeaderBoardEntry\r\n{\r\n\r\npublic:\r\n\tint \t\t\t\t\t\tGetTotalScore(int round);\t\r\n\r\n\tStr::String\t\t\t\t\tm_name;\r\n\tint\t\t\t\t\t\t\tm_player_number;\r\n\tint\t\t\t\t\t\t\tm_score[vNUM_ROUNDS]; \t// score now stored in hundreths\r\n\tbool\t\t\t\t\t\tvisible;\t\r\n};\r\n\r\n\r\nclass  CCompetition  : public Spt::Class\r\n{\r\n\t\r\n\t\r\npublic:\t\r\n\tCCompetition( Script::CStruct* pParams = NULL );\r\n\t~CCompetition();\r\n\t\r\n\tvoid\t\t\t\t\t\tStartCompetition(float bronze = 90.0f, float silver = 93.0f, float gold = 95.0f, float bonze_score=20000, float silver_score=40000,float gold_score = 60000,float bail = 1.0f);\r\n\tvoid\t\t\t\t\t\tStartRun();\r\n\tvoid \t\t\t\t\t\tEndRun(int score);\r\n\tvoid \t\t\t\t\t\tBail();\r\n\tvoid\t\t\t\t\t\tSort();\r\n\t\r\n\tint \t\t\t\t\t\tGetPosition(int player = 0);\r\n\tchar *\t\t\t\t\t\tGetJudgeName(int judge);\r\n\tfloat\t\t\t\t\t\tGetJudgeScore(int judge);\r\n\tvoid\t\t\t\t\t\tSetupJudgeText();\r\n\tbool \t\t\t\t\t\tIsTopJudge(int judge);\r\n\tbool \t\t\t\t\t\tPlaceIs(int place);\r\n\tbool \t\t\t\t\t\tRoundIs(int place);\r\n\tvoid \t\t\t\t\t\tEndCompetition();\r\n\tbool \t\t\t\t\t\tCompetitionEnded();\r\n\r\n\tvoid\t\t\t\t\t\tEditParams( Script::CStruct* pParams );\r\n\r\nprivate:\r\n\tvoid\t\t\t\t\t\tResetJudgement();\r\n\t\r\n\t// BB - i'm lazy, so I'm just adding a struct to hold various\r\n\t// params that i can use to change the behavior in the code\r\n\tScript::CStruct*\t\t\tmp_params;\r\n\t\r\n\tint\t\t\t\t\t\t\tm_current_round;\r\n\r\n\tCLeaderBoardEntry\t\t\tm_leader_board[vMAX_PLAYERS];\r\n\r\n\tfloat \t\t\t\t\t\tm_bronze;\t\t \t// score required to get bronze\r\n\tfloat\t\t\t\t\t\tm_silver;\r\n\tfloat \t\t\t\t\t\tm_gold;\r\n\tfloat \t\t\t\t\t\tm_bronze_score;\t\t// points required to get that score\r\n\tfloat \t\t\t\t\t\tm_silver_score;\r\n\tfloat \t\t\t\t\t\tm_gold_score;\r\n\tfloat \t\t\t\t\t\tm_bail;\t\t\t    // points deducted for bailing\t\r\n\r\n\tfloat\t\t\t\t\t\tm_bail_points;\t\t\t   \t\r\n\tfloat\t\t\t\t\t\tm_score[vNUM_JUDGES];  \t// m_score is generated from m_total_score\r\n\tchar *\t\t\t\t\t\tm_judge_name[vNUM_JUDGES];  \t//\r\n\tfloat\t\t\t\t\t\tm_total_score;\r\n\r\n\tint\t\t\t\t\t\t\tm_judge_score[vNUM_ROUNDS];\r\n\r\n\tbool\t\t\t\t\t\tm_end_competition;\r\n\t\r\n\tint\tm_place;\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace <module-name>\r\n\r\n#endif\t\t// __SK_MODULES_COMPETITION_H\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/horse.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tskate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tskate\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\thorse.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t07/17/01\t-\tGary\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t<description>\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/modules/skate/horse.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/math/math.h>\t\t\t\t\t\t // for Mth::Rnd()\r\n#include <core/string/stringutils.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <sk/objects/restart.h>\r\n#include <sk/objects/skater.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mdl\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic uint32 s_horse_status[] = {\r\n   0x0fd80eba,\t// GotLetter\r\n   0x006be86f,\t// TieScore\r\n   0xbaa12466,\t// BeatScore\r\n   0xae7d29b0,\t// Ended\r\n   0x23db4aea,\t// Idle\r\n   0xa71dd8eb,\t// NoScoreSet\r\n   0\t\t\t// Terminator\r\n};\r\n\r\n// should match the above\r\nenum\r\n{\r\n\tvGOTLETTER = 0,\r\n\tvTIESCORE,\r\n\tvBEATSCORE,\r\n\tvENDED,\r\n\tvIDLE,\r\n\tvNOSCORESET,\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic uint32 get_num_horse_restarts()\r\n{\r\n\tuint32 dummy_nodes[128];\r\n\treturn Obj::FindQualifyingNodes( Script::GenerateCRC(\"horse\"), &dummy_nodes[0] );\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCHorse::CHorse()\r\n{\r\n\tstrcpy( m_string, \"HORSE\" );\r\n\r\n\tm_currentRestartIndex = 0;\r\n}\r\n   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CHorse::Init()\r\n{\r\n\t// reset the score to beat\r\n\tm_scoreToBeat = 0;\r\n\r\n\t// setting the \"current horse player\"\r\n\tm_currentSkaterId = 0;\r\n\tm_nextSkaterId = 0;\r\n\tsprintf( m_nextHorseMessage, \"unknown\" );\r\n\r\n\t// resetting each of their accumulated horse words\r\n\tfor ( int i = 0; i < Skate::vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tm_numLetters[i] = 0;\r\n\t}\r\n\r\n\t// select a random restart point\r\n\tuint32 num_restarts = get_num_horse_restarts();\r\n\t//Dbg_MsgAssert ( num_restarts > 0, ( \"Couldn't find any horse restarts\" ) );\r\n\tDbg_Printf( \"-- COULDN'T FIND ANY HORSE RESTARTS --\\n\" );\r\n\tm_currentRestartIndex = Mth::Rnd( num_restarts );\r\n\r\n\t// maybe do some kind of handicapping?\r\n\t// or separate words for each player?\r\n\t\r\n\t// their panels need to be suspended, but that's\r\n\t// done in the panel manager code.\r\n\t// TODO:  move it to some accessor in the panel stuff\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CHorse::GetCurrentSkaterId()\r\n{\r\n\treturn m_currentSkaterId;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CHorse::StartRun()\r\n{\r\n\t\r\n\t\r\n\t//Front::MenuFactory* menu_factory = Front::MenuFactory::Instance();\r\n\r\n\t//m_currentSkaterId = m_nextSkaterId;\r\n\r\n\tm_status = s_horse_status[vIDLE];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CHorse::EndRun()\r\n{\r\n\t// calculate the score post-run\r\n\t// update the horse data structure so that we know that\r\n\t// the score to beat is\r\n\r\n\tsprintf( m_nextHorseMessage, \"unknown\" );\r\n\t\r\n\t// by default, don't change the skater\r\n\tm_nextSkaterId = m_currentSkaterId;\r\n\r\n\tint score = get_score( m_currentSkaterId );\r\n\r\n\tprintf( \"End run = %d\\n\", score );\r\n\r\n\tif ( score > m_scoreToBeat )\r\n\t{\r\n\t\t// current player wins the run\r\n\t\tm_scoreToBeat = score;\r\n\r\n\t\tsprintf( m_nextHorseMessage, \"%s %s\", Script::GetLocalString( \"horse_str_setscoreis\" ), Str::PrintThousands(m_scoreToBeat) );\r\n\t\tm_status = s_horse_status[vBEATSCORE];\r\n\t}\r\n\telse if ( score < m_scoreToBeat )\r\n\t{\r\n\t\t// current player loses the run\r\n\t\tm_scoreToBeat = 0;\r\n\t\t\r\n\t\tm_numLetters[ m_currentSkaterId ]++;\r\n\r\n\t\t// skip to next restart point\r\n\t\tSetNextRestartPoint();\r\n\t\t\r\n\t\tif ( Ended() )\r\n\t\t{\r\n\t\t\t// GJ:  this string is never used...  it says \"Player 1 is a horse\" somewhere else\r\n\t\t\tsprintf( m_nextHorseMessage, \"You are a %s!\", m_string );\r\n\r\n\t\t\tm_status = s_horse_status[vENDED];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tchar letter[2];\r\n\t\t\tletter[0] = *(m_string + m_numLetters[m_currentSkaterId] - 1);\r\n\t\t\t// make it uppercase\r\n\t\t\tif ( letter[0] >= 'a' && letter[0] <= 'z' )\r\n\t\t\t{\r\n\t\t\t\tletter[0] -= 'a';\r\n\t\t\t\tletter[0] += 'A';\r\n\t\t\t}\r\n\t\t\tletter[1] = 0;\r\n\t\t\tsprintf( m_nextHorseMessage, \"%s %s\", Script::GetLocalString( \"horse_str_getstheletter\" ), letter );\r\n\t\t\tm_status = s_horse_status[vGOTLETTER];\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// current player draws\r\n\t\tif ( score == 0 )\r\n\t\t{\r\n\t\t\tstrcpy( m_nextHorseMessage, Script::GetLocalString( \"horse_str_noscoreset\" ));\r\n\t\t\tm_status = s_horse_status[vNOSCORESET];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tstrcpy( m_nextHorseMessage, Script::GetLocalString( \"horse_str_youtiedthetargetscore\" ));\r\n\t\t\tm_status = s_horse_status[vTIESCORE];\r\n\t\t}\r\n\t}\r\n\r\n#ifdef __USER_GARY__\r\n\tprintf( \"Current Score:  %s - %s\\n\",\r\n\t\t\tGetWordForPlayer( 0 ).getString(),\r\n\t\t\tGetWordForPlayer( 1 ).getString() );\r\n#endif\r\n\t\r\n\t//SwitchPlayers();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CHorse::SwitchPlayers()\r\n{\r\n\tm_nextSkaterId = get_next_valid_skater_id();\r\n\tm_currentSkaterId = m_nextSkaterId;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CHorse::StatusEquals( Script::CStruct* pParams )\r\n{\r\n\tint i = 0;\r\n\twhile ( s_horse_status[i] )\r\n\t{\r\n\t\tif ( pParams->ContainsFlag( s_horse_status[i] ) )\r\n\t\t{\r\n\t\t\treturn ( m_status == s_horse_status[i] );\r\n\t\t}\r\n\t\t\r\n\t\ti++;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CHorse::Ended()\r\n{\r\n\tfor ( int i = 0; i < Skate::vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tif ( !skate_mod->GetSkaterById( i ) )\r\n\t\t\tcontinue;\r\n\r\n\t\t// if the skater exists...\r\n\t\tif ( m_numLetters[i] >= strlen( m_string ) )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CHorse::SetWord( Str::String word )\r\n{\r\n\t// validate string\r\n\t// make sure there's at least 1 letter\r\n\r\n\tDbg_Assert( word.getString() && strlen( word.getString() ) > 0 );\r\n\r\n\tstrcpy( m_string, word.getString());\r\n\r\n\tprintf( \"New word = %s\\n\", m_string );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStr::String CHorse::GetWordForPlayer( int skater_id )\r\n{\r\n\t\r\n\r\n\tDbg_Assert( skater_id >= 0 && skater_id < Skate::vMAX_SKATERS );\r\n\t\r\n\tchar msg[256];\r\n\t\r\n\tstrcpy( msg, m_string );\r\n\tfor ( uint32 i = 0; i < strlen(msg); i++ )\r\n\t{\r\n\t\tif ( i >= m_numLetters[ skater_id ] )\r\n\t\t\tmsg[i] = '-';\r\n\t}\r\n\r\n\treturn msg;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar* CHorse::GetWord()\r\n{\r\n\treturn m_string;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CHorse::get_next_valid_skater_id()\r\n{\r\n\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\tObj::CSkater *pSkater = NULL;\r\n\tint check_id = 0;\r\n\r\n\tfor ( int i = 0; i < Skate::vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tcheck_id = ( m_currentSkaterId + i + 1 ) % Skate::vMAX_SKATERS;\r\n\t\tpSkater = skate_mod->GetSkaterById( check_id );\r\n\t\tif ( pSkater )\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\tDbg_Assert( pSkater );\r\n\r\n\tprintf( \"new skater id = %d\\n\", check_id );\r\n\r\n\tif ( Script::GetInteger( \"debug_horse\" ) )\r\n\t{\r\n\t\t// DEBUGGING\r\n\t\tcheck_id = 0;\r\n\t}\r\n\t\r\n\treturn check_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CHorse::get_score( int skater_id )\r\n{\r\n\t\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater *pSkater = skate_mod->GetSkaterById( skater_id );\r\n\tDbg_Assert( pSkater );\r\n\r\n\tMdl::Score * pScore = ( pSkater->GetScoreObject() );\r\n\tDbg_Assert( pScore );\r\n\r\n\treturn pScore->GetTotalScore();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStr::String\tCHorse::GetString( uint32 checksum )\r\n{\r\n\t\r\n\t\r\n\tchar msg[256];\r\n\tstrcpy( msg, \"Unknown\" );\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater *pSkater = skate_mod->GetSkaterById( m_currentSkaterId );\r\n\tDbg_Assert( pSkater );\r\n\r\n\tswitch ( checksum )\r\n\t{\r\n\t\tcase 0x9196d920: // playerName\r\n\t\t{\r\n//\t\t\tint currentPlayerNumber = pSkater->GetID() + 1;\r\n//\t\t\tsprintf( msg, \"Player %d\", currentPlayerNumber );\r\n\t\t\tsprintf( msg, \"%s\", skate_mod->GetSkaterById( pSkater->GetID() )->GetDisplayName() );\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n\t\tcase 0x5078bc7c: // horsePreRun\r\n\t\t{\r\n\t\t\tif ( m_scoreToBeat > 0 )\r\n\t\t\t{\r\n\t\t\t\tsprintf( msg, \"%s %s\", Script::GetLocalString( \"horse_str_scoretobeat\" ), Str::PrintThousands(m_scoreToBeat) );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsprintf( msg, Script::GetLocalString( \"horse_str_setscore\" ) );\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n\t\tcase 0x2a13f850: // horsePostRun\r\n\t\t{\r\n\t\t\tstrcpy( msg, m_nextHorseMessage );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0xde802177: // panelString1\r\n\t\t{\r\n\t\t\tsprintf( msg, \"%s: %s\", skate_mod->GetSkaterById( 0 )->GetDisplayName(), GetWordForPlayer( 0 ).getString() );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0x478970cd: // panelString2\r\n\t\t{\r\n\t\t\tsprintf( msg, \"%s: %s\", skate_mod->GetSkaterById( 1 )->GetDisplayName(), GetWordForPlayer( 1 ).getString() );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0x2523853d: // youAreA\r\n\t\t{\r\n\t\t\tbool starts_with_vowel = false;\r\n\t\t\tchar first_letter = GetWord()[0];\r\n\t\t\tif ( first_letter >= 'a' && first_letter <= 'z' )\r\n\t\t\t{\r\n\t\t\t\t// make them upper case\r\n\t\t\t\tfirst_letter -= 'a';\r\n\t\t\t\tfirst_letter += 'A';\r\n\t\t\t}\r\n\t\t\tif ( first_letter == 'A' || first_letter == 'E' || first_letter == 'I'\r\n\t\t\t\t || first_letter == 'O' || first_letter == 'U' )\r\n\t\t\t{\r\n\t\t\t\tstarts_with_vowel = true;\r\n\t\t\t}\r\n\r\n\t\t\tsprintf( msg, \"%s %s\", GetString( Script::GenerateCRC(\"playerName\") ).getString(), starts_with_vowel ?  Script::GetLocalString( \"horse_str_isan\" ) :  Script::GetLocalString( \"horse_str_isa\" ) );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0x5f7d73e9: // finalWord\r\n\t\t{\r\n\t\t\tsprintf( msg, \"%s\", GetWord() );\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\t\r\n\treturn msg;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tCHorse::GetCurrentRestartIndex( void )\r\n{\r\n\t\r\n\r\n\tuint32 num_restarts = get_num_horse_restarts();\r\n\tif ( m_currentRestartIndex >= num_restarts )\r\n\t{\r\n\t\t//Dbg_MsgAssert( 0, ( \"Out of range horse restart index %d %d\", m_currentRestartIndex, num_restarts ) );\r\n\t}\r\n\r\n\treturn m_currentRestartIndex;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCHorse::SetNextRestartPoint( void )\r\n{\r\n\tm_currentRestartIndex++;\r\n\r\n\tif ( m_currentRestartIndex >= get_num_horse_restarts() )\r\n\t{\r\n\t\tm_currentRestartIndex = 0;\r\n\t}\r\n\r\n#ifdef __USER_GARY__\r\n\tprintf( \"\\n*** Setting next restart point %d ***\\n\", m_currentRestartIndex );\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mdl\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/horse.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tskate3  \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tsk\t\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\thorse.h\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t7/17/01 - Gary\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t<description>\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __SK_MODULES_HORSE_H\r\n#define __SK_MODULES_HORSE_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/string/cstring.h>\r\n#include <sk/modules/skate/skate.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Script\r\n{\r\n    class CStruct;\r\n};\r\n                                \r\nnamespace Mdl\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  CHorse  : public Spt::Class\r\n{\r\n\t\r\n\r\n\tenum\r\n\t{\r\n\t\tvMAX_RESTARTS = 32\r\n\t};\r\n\t\t\t\r\npublic:\r\n\tCHorse();\r\n\r\npublic:\r\n\tvoid\t\t\t\t\t\tInit();\r\n\tvoid\t\t\t\t\t\tSwitchPlayers();\r\n\tvoid\t\t\t\t\t\tStartRun();\r\n\tvoid \t\t\t\t\t\tEndRun();\r\n\tbool\t\t\t\t\t\tEnded();\r\n\tchar*\t\t\t\t\t\tGetWord();\r\n\tvoid\t\t\t\t\t\tSetWord( Str::String word );\r\n\tStr::String\t\t\t\t\tGetWordForPlayer( int skater_id );\r\n\tint\t\t\t\t\t\t\tGetCurrentSkaterId();\r\n\tStr::String\t\t\t\t\tGetString( uint32 checksum );\r\n\tuint32\t\t\t\t\t\tGetCurrentRestartIndex();\r\n\tvoid\t\t\t\t\t\tSetNextRestartPoint(void);\r\n\tbool\t\t\t\t\t\tStatusEquals( Script::CStruct* pParams );\r\n\r\nprotected:\r\n\tint\t\t\t\t\t\t\tget_next_valid_skater_id();\r\n\tint\t\t\t\t\t\t\tget_score( int id );\r\n\t\r\nprotected:\r\n\tint\t\t\t\t\t\t\tm_scoreToBeat;\r\n\tint\t\t\t\t\t\t\tm_currentSkaterId;\r\n\tint\t\t\t\t\t\t\tm_nextSkaterId;\r\n\tchar\t\t\t\t\t\tm_string[512];\r\n\tchar\t\t\t\t\t\tm_nextHorseMessage[512];\r\n\tuint32\t\t\t\t\t\tm_numLetters[Skate::vMAX_SKATERS];\r\n\tuint32\t\t\t\t\t\tm_numRestarts;\r\n\tuint32\t\t\t\t\t\tm_currentRestartIndex;\r\n\tuint32\t\t\t\t\t\tm_status;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mdl\r\n\r\n#endif\t\t// __SK_MODULES_HORSE_H\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/score.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tskate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\t\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\trjm\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/modules/skate/score.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/string/stringutils.h>\r\n\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/components/trickcomponent.h>\r\n#include <gel/components/statsmanagercomponent.h>\r\n#include <gel/components/animationcomponent.h>\r\n\r\n#include <gfx/nxviewman.h>\r\n#include <gfx/2d/screenelemman.h>\r\n#include <gfx/2d/textelement.h>\r\n#include <gfx/2d/spriteelement.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/gamenet/gamemsg.h>\r\n\r\n#include <sk/objects/skater.h>\t\t   // for control and trick stuff\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/objects/skatercareer.h>\r\n\r\n#include <sk/components/skaterruntimercomponent.h>\r\n#include <sk/components/skateradjustphysicscomponent.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/modules/skate/goalmanager.h>\r\n\r\n#include <sk/scripting/cfuncs.h>\r\n\r\n#include <sys/replay/replay.h>\r\n\r\nnamespace Front\r\n{\r\n\textern void SetScoreTHPS4(char* score_text, int skater_num);\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mdl\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define NO_SCORE_DURING_UBER_FRIG\r\n#define MAX_SCORE_DUE_TO_TWEAK (20000)\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic const int MAX_SPIN_VALUES\t\t\t\t\t= 6;\r\nstatic const int SPIN_MULT_VALUES[MAX_SPIN_VALUES]\t= {2, 3, 4, 5, 6, 7};\r\nstatic const int MAX_DEPREC\t\t\t\t\t\t\t= 5;\r\nstatic const int DEPREC_VALUES[MAX_DEPREC]\t\t\t= {100, 75, 50, 25, 10};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// given a score increment, return a value by which it should be decremented\r\n// basically return the closest multiple of 10 below score\r\nint\tscore_increment(int score)\r\n{\r\n\tif (score >1000000) return 1000000;\r\n\tif (score >100000) return 100000;\r\n\tif (score >10000) return 10000;\r\n\tif (score >10000) return 1000;\r\n\tif (score >1000) return 100;\r\n\tif (score >100) return 100;\r\n\tif (score >10) return 10;\r\n\treturn 1;\t\r\n}\r\n\r\n\r\n\r\n\r\nScore::Score() :\r\n\tm_historyTab(16),\r\n\tm_infoTab(8)\r\n{\r\n\tm_skaterId = 0;\r\n\tm_totalScore = 0;\r\n\tm_scorePot = 0;\r\n\tm_recentScorePot = 0;\r\n\tm_recentSpecialScorePot = 0;\r\n\tm_currentTrick = 0;\r\n\tm_currentMult = 0;\r\n\tm_currentBlockingTrick = -1;\r\n\tm_currentSpinTrick = -1;\r\n\r\n\tm_specialScore = 0;\r\n\tset_special_is_active(false);\r\n\r\n\tm_special_interpolator = 0.0f;\r\n\r\n\tm_longestCombo = 0;\r\n\tm_bestCombo = 0;\r\n\tm_bestGameCombo = 0;\r\n\t\r\n\t//mp_trickWindow = NULL;\r\n\r\n\tm_debug = (bool) Script::GetInteger(\"print_trick_info\");\r\n\r\n\tsetup_balance_meter_stuff();\r\n}\r\n\r\n\r\n\r\n\r\nScore::~Score()\r\n{\r\n\tReset();\r\n}\r\n\r\nint Score::get_packed_score( int start, int end )\r\n{\r\n\tint packed_score = 0;\r\n\tint current_spin_mult = 2;\t\t// n over 2\r\n\tfor (int i = start; i < end; i++)\r\n\t{\r\n\t\t// if a blocking trick, use default spin multiplier\r\n\t\tif (m_infoTab[i].flags & vBLOCKING)\r\n\t\t{\r\n\t\t\tcurrent_spin_mult = 2;\r\n\t\t}\r\n\t\t// if not a blocking trick, but the last trick was, then use the spin multiplier here\r\n\t\t// to apply to subsequent tricks up to next blocking one\r\n\t\telse if (i == 0 || (m_infoTab[i-1].flags & vBLOCKING))\r\n\t\t{\r\n\t\t\tcurrent_spin_mult = spinMult(m_infoTab[i].spin_mult_index);\r\n\t\t}\r\n\r\n\t\tint deprec_mult = deprecMult(m_infoTab[i].mult_index);\r\n\t\t\r\n//\t\tif (m_debug)\r\n//\t\t\tprintf(\"   base score %d, reduction mult %.2f, spin mult %.1f\\n\", \r\n//\t\t\t\t   m_infoTab[i].score, (float) deprec_mult / 100, (float) current_spin_mult / 2);\r\n\t\t\r\n\t\tint score = (m_infoTab[i].score * deprec_mult * current_spin_mult) / 200;\r\n\t\tif (m_infoTab[i].switch_mode)\r\n\t\t{\r\n\t\t\tscore\t= score * 120 / 100;\r\n\t\t}\r\n\t\t\r\n\t\tpacked_score += score;\r\n\t}\r\n\treturn packed_score;\r\n}\r\n\r\nvoid Score::pack_trick_info_table()\r\n{\r\n\tTrickInfo theTrickInfo;\r\n\tstrcpy( theTrickInfo.trickNameText, \"... + \" );\r\n\tstrcpy( theTrickInfo.trickTextFormatted, \"...\\\\_+\\\\_\" );\r\n\ttheTrickInfo.score = 0;\r\n\ttheTrickInfo.id = 0;\r\n\ttheTrickInfo.switch_mode = 0;\r\n\ttheTrickInfo.flags = 0;\r\n\ttheTrickInfo.mult_index = 0;\r\n\ttheTrickInfo.spin_mult_index = 0;\r\n\ttheTrickInfo.spin_degrees = 0;\r\n\r\n\tint firstBlockingTrick = m_infoTab.GetSize();\r\n\r\n\tfor ( int i = 0; i < m_infoTab.GetSize(); i++ )\r\n\t{\r\n//\t\tif ( ( i != 0 ) && ( m_infoTab[i].flags & vBLOCKING ) )\r\n\t\tif ( ( i != 0 ) && ( m_infoTab[i].trickNameText[0] == 0 ) )\r\n\t\t{\r\n\t\t\tfirstBlockingTrick = i;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// GJ:  see note below\r\n\tif ( ( firstBlockingTrick > m_currentSpinTrick )\r\n\t\t || ( firstBlockingTrick > m_currentBlockingTrick ) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\ttheTrickInfo.score = get_packed_score( 0, firstBlockingTrick );\r\n\r\n\t// shift them all...\r\n\tfor ( int i = 0; i < firstBlockingTrick; i++ )\r\n\t{\r\n\t\tm_infoTab.Remove( 1 );\r\n\r\n\t\tm_currentTrick--;\r\n\t\tm_currentSpinTrick--;\r\n\t\tm_currentBlockingTrick--;\r\n\r\n\t\t// GJ:  these asserts will fire off if the trick list is filled\r\n\t\t// with more non-blocking tricks than spin tricks...\t it rarely\r\n\t\t// happens, except for those glitches that lets the player do\r\n\t\t// infinite tricks.  The if-test above will abort early,\r\n\t\t// allowing the calling function ( Trigger() ) to gracefully\r\n\t\t// handle it\r\n\t\tDbg_MsgAssert( m_currentTrick > -1, ( \"m_currentTrick is negative (%d)\", m_currentTrick ) );\r\n\t\tDbg_MsgAssert( m_currentSpinTrick > -1, ( \"m_currentSpinTrick is negative (%d)\", m_currentSpinTrick ) );\r\n\t\tDbg_MsgAssert( m_currentBlockingTrick > -1, ( \"m_currentBlockingTrick is negative (%d)\", m_currentBlockingTrick ) );\r\n\t}\r\n\t\r\n\tm_infoTab[0] = theTrickInfo;\r\n\t\r\n\t// so that the packed score will be correct next time\r\n\tm_infoTab[0].flags |= vBLOCKING;\r\n\r\n#ifdef __USER_GARY__\r\n\tDbg_Message( \"Info table has %d elements.\", m_infoTab.GetSize() );\r\n#endif\r\n}\r\n\r\nvoid Score::print_trick_info_table()\r\n{\r\n\tfor ( int i = 0; i < m_infoTab.GetSize(); i++ )\r\n\t{\r\n\t\tprintf( \"info table %d\\n\", i );\r\n\t\tprintf( \"\\ttrickname = %s\\n\", m_infoTab[i].trickNameText); \r\n\t\tprintf( \"\\ttrickformatted = %s\\n\", m_infoTab[i].trickTextFormatted); \r\n\t\tprintf( \"\\tscore = %d\\n\", m_infoTab[i].score); \r\n\t\tprintf( \"\\tmult_index = %d\\n\", m_infoTab[i].mult_index); \r\n\t\tprintf( \"\\tspin_mult_index = %d\\n\", m_infoTab[i].spin_mult_index); \r\n\t\tprintf( \"\\tswitch_mode = %d\\n\", m_infoTab[i].switch_mode);\r\n/*\r\n\t\tm_infoTab[i].id,\r\n\t\tm_infoTab[i].switch_mode,\r\n\t\tm_infoTab[i].flags,\r\n*/\r\n\t\tprintf( \"-------------------------------------\\n\" );\r\n\t}\r\n}\r\n\r\nvoid Score::Update()\r\n{\r\n\tif (m_specialScore)\r\n\t{\r\n\t\t// shrink special bar\r\n\t\tif (m_specialIsActive)\r\n\t\t\tm_specialScore = (int) ((float) m_specialScore - (float) Tmr::FrameLength() * 200.0f / Tmr::vRESOLUTION);\t\t\t\r\n\t\telse\r\n\t\t\tm_specialScore = (int) ((float) m_specialScore - (float) Tmr::FrameLength() * 50.0f / Tmr::vRESOLUTION);\t\t\t\r\n\t\tif (m_specialScore <= 0)\r\n\t\t{\r\n\t\t\tset_special_is_active(false);\r\n\t\t\tm_specialScore = 0;\r\n\t\t}\r\n\t}\r\n\r\n\tif (m_scorePotState == WAITING_TO_COUNT_SCORE_POT)\r\n\t{\r\n\t\tm_scorePotCountdown--;\r\n\t\tif (!m_scorePotCountdown)\r\n\t\t{\r\n\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\tObj::CSkater* pSkater = skate_mod->GetSkaterById( m_skaterId );\r\n\t\t\tint index;\r\n\r\n\t\t\tindex = 0;\r\n\t\t\tif( pSkater )\r\n\t\t\t{\r\n\t\t\t\tindex = pSkater->GetHeapIndex();\r\n\t\t\t}\r\n\t\t\tTrickTextCountdown(index);\r\n\t\t\tReplay::WriteTrickTextCountdown();\r\n\r\n\t\t\tm_scorePotState = SHOW_COUNTED_SCORE_POT;\r\n\t\t}\r\n\t}\r\n\telse if (m_scorePotState == SHOW_COUNTED_SCORE_POT)\r\n\t{\r\n\t\tdispatch_score_pot_value_to_screen(m_countedScorePot, 0);\r\n\t\tm_countedScorePot -= score_increment(m_countedScorePot);\r\n\t\tif (m_countedScorePot < 0) \r\n\t\t{\r\n\t\t\tm_countedScorePot = 0;\r\n\t\t\tm_scorePotState = SHOW_ACTUAL_SCORE_POT;\r\n\t\t}\r\n\t}\r\n\t\r\n\t#if 0\r\n\tImage::RGBA\t\t\t\t\t\tm_special_rgba[3];\r\n\tfloat\t\t\t\t\t\t\tm_special_interpolator;\r\n\tfloat\t\t\t\t\t\t\tm_special_interpolator_rate;\r\n\t#endif\r\n\t\r\n\tFront::CScreenElementManager* p_manager = Front::CScreenElementManager::Instance();\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tFront::CScreenElementPtr p_special_bar;\r\n\t\r\n\tObj::CSkater* pSkater = skate_mod->GetSkaterById( m_skaterId );\r\n\tif( pSkater )\r\n\t{\r\n\t\tp_special_bar = p_manager->GetElement(CRCD(0xfe1dc544,\"the_special_bar_sprite\") + pSkater->GetHeapIndex());\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_special_bar = p_manager->GetElement(CRCD(0xfe1dc544,\"the_special_bar_sprite\"));\r\n\t}\r\n\t// clamp scale of bar, so that it doesn't get all crazy\r\n\tfloat special_mult = m_specialScore / 3000.0f;\r\n\tif (special_mult > 1.0f)\r\n\t\tspecial_mult = 1.0f;\r\n\telse if (special_mult < 0.0f)\r\n\t\tspecial_mult = 0.0f;\r\n\tp_special_bar->SetScale(special_mult, p_special_bar->GetScaleY());\r\n\tImage::RGBA special_rgba = m_special_rgba[REGULAR_SPECIAL];\r\n\tif (m_specialIsActive)\r\n\t{\r\n\t\tfloat interpolate_mult = (cosf(m_special_interpolator) + 1.0f) / 2.0f;\r\n\t\tm_special_interpolator += m_special_interpolator_rate;\r\n\t\t\r\n\t\tspecial_rgba.r = (uint8) ((float) m_special_rgba[1].r + ((float) (m_special_rgba[2].r - m_special_rgba[1].r)) * interpolate_mult);\r\n\t\tspecial_rgba.g = (uint8) ((float) m_special_rgba[1].g + ((float) (m_special_rgba[2].g - m_special_rgba[1].g)) * interpolate_mult);\r\n\t\tspecial_rgba.b = (uint8) ((float) m_special_rgba[1].b + ((float) (m_special_rgba[2].b - m_special_rgba[1].b)) * interpolate_mult);\r\n\t\tspecial_rgba.a = (uint8) ((float) m_special_rgba[1].a + ((float) (m_special_rgba[2].a - m_special_rgba[1].a)) * interpolate_mult);\r\n\t}\r\n\tp_special_bar->SetRGBA(special_rgba);\r\n\r\n\t/*\r\n\tHUD::PanelMgr* panel_mgr = HUD::PanelMgr::Instance();\r\n\tHUD::Panel* panel;\r\n\r\n\tif(( panel = panel_mgr->GetPanelBySkaterId(m_skaterId, false)))\r\n\t{\r\n\t\tpanel->SetSpecialPercent((float) m_specialScore / 3000.0f, m_specialIsActive);\r\n\t}\r\n\t*/\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCalled from CSkater constructor\r\n*/\r\nvoid Score::SetSkaterId(short skater_id) \r\n{\r\n\tm_skaterId = skater_id;\r\n\t//HUD::PanelMgr* panel_mgr = HUD::PanelMgr::Instance();\r\n\t//mp_trickWindow = panel_mgr->GetTrickWindow(m_skaterId);\r\n}\r\n\r\n\r\n\r\n\r\nvoid Score::copy_trick_name_with_special_spaces(char *pOut, const char *pIn)\r\n{\r\n\tint count = 0;\r\n\twhile(*pIn != '\\0')\r\n\t{\r\n\t\tDbg_Assert(count < TrickInfo::TEXT_BUFFER_SIZE);\r\n\t\tif (*pIn == ' ')\r\n\t\t{\r\n\t\t\t*pOut++ = '\\\\';\r\n\t\t\t*pOut++ = '_';\r\n\t\t\tcount += 2;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t*pOut++ = *pIn;\r\n\t\t\tcount++;\r\n\t\t}\r\n\t\tpIn++;\r\n\t}\r\n\t*pOut = '\\0';\r\n}\r\n\r\n/*\r\n\tAdded by Ken. Returns the Id of the last trick added, or 0 if there are none.\r\n\tAdded for use by the skater Display commmand when the AddSpin flag is specified.\r\n\tIn that case, if the skater's current trick is the same as the last one in the score object,\r\n\tthen instead of adding the same trick again it will add spin to the last one instead.\r\n\tUsed by some flatland tricks.\r\n\t(See skater.cpp for the above code, search for | Display |)\r\n*/\r\nuint32 Score::GetLastTrickId()\r\n{\r\n\tif (m_infoTab.GetSize())\r\n\t{\r\n\t\treturn m_infoTab.Last().id;\r\n\t}\r\n\treturn 0;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32 Score::GetTrickId( int trickIndex )\r\n{\r\n\tDbg_MsgAssert( trickIndex >= 0 && trickIndex < m_currentTrick, ( \"trickIndex out of range\" ) );\r\n\treturn m_infoTab[trickIndex].id;\r\n}\r\n\r\nvoid Score::TrickTextPulse(int index)\r\n{\r\n\tScript::CStruct* pParams=new Script::CStruct;\r\n\tpParams->AddChecksum( CRCD(0x33124d2e,\"trick_text_container_id\"), CRCD(0x1e55886e,\"trick_text_container\")  + index);\r\n\tpParams->AddChecksum( CRCD(0x6e7c7ba7,\"the_trick_text_id\"), CRCD(0x44727dae,\"the_trick_text\")  + index);\r\n\tpParams->AddChecksum( CRCD(0x6d02989c,\"the_score_pot_text_id\"), CRCD(0xf4d3a70e,\"the_score_pot_text\") + index);\r\n\tScript::RunScript(CRCD(0x3bd51fe5,\"trick_text_pulse\"), pParams);\r\n\tdelete pParams;\r\n}\r\n\r\nvoid Score::TrickTextCountdown(int index)\r\n{\r\n\tScript::CStruct* pParams=new Script::CStruct;\r\n\tpParams->AddChecksum( CRCD(0x33124d2e,\"trick_text_container_id\"), CRCD(0x1e55886e,\"trick_text_container\")  + index );\r\n\tpParams->AddChecksum( CRCD(0x6e7c7ba7,\"the_trick_text_id\"), ( CRCD(0x44727dae,\"the_trick_text\") ) + index );\r\n\tpParams->AddChecksum( CRCD(0x6d02989c,\"the_score_pot_text_id\"), ( CRCD(0xf4d3a70e,\"the_score_pot_text\") ) + index );\r\n\tScript::RunScript(CRCD(0xee9ce723,\"trick_text_countdown\"), pParams );\r\n\tdelete pParams;\r\n}\r\n\r\nvoid Score::TrickTextLanded(int index)\r\n{\r\n\tScript::CStruct* pParams=new Script::CStruct;\r\n\tpParams->AddChecksum( CRCD(0x33124d2e,\"trick_text_container_id\"), ( CRCD(0x1e55886e,\"trick_text_container\") ) + index );\r\n\tpParams->AddChecksum( CRCD(0x6e7c7ba7,\"the_trick_text_id\"), ( CRCD(0x44727dae,\"the_trick_text\") ) + index );\r\n\tpParams->AddChecksum( CRCD(0x6d02989c,\"the_score_pot_text_id\"), ( CRCD(0xf4d3a70e,\"the_score_pot_text\") ) + index );\r\n\tScript::RunScript(CRCD(0xc890e875,\"trick_text_landed\"), pParams);\r\n\tdelete pParams;\r\n}\r\n\r\nvoid Score::TrickTextBail(int index)\r\n{\r\n\tScript::CStruct* pParams=new Script::CStruct;\r\n\tpParams->AddChecksum( CRCD(0x33124d2e,\"trick_text_container_id\"), ( CRCD(0x1e55886e,\"trick_text_container\") ) + index );\r\n\tpParams->AddChecksum( CRCD(0x6e7c7ba7,\"the_trick_text_id\"), ( CRCD(0x44727dae,\"the_trick_text\") ) + index );\r\n\tpParams->AddChecksum( CRCD(0x6d02989c,\"the_score_pot_text_id\"), ( CRCD(0xf4d3a70e,\"the_score_pot_text\") ) + index );\r\n\tScript::RunScript(CRCD(0xaa7f404d,\"trick_text_bail\"), pParams );\r\n\tdelete pParams;\r\n}\r\n\r\n/*\r\n\tCalled when a trick is done, adding it to the trick sequence.\r\n*/\r\nconst int TRICK_LIMIT = 250;\r\nvoid Score::Trigger(char *trick_name, int base_score, Flags flags)\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\r\n\tbool null_trick=false;\r\n\tif (!trick_name[0])\r\n\t{\r\n\t\tnull_trick=true;\r\n\t}\r\n\t\t\r\n\t// once some trick/score has appeared on-screen\r\n\t// we know that the trick has started\r\n\tObj::CSkater* pSkater = skate_mod->GetSkaterById( m_skaterId );\r\n\tDbg_Assert( pSkater );\r\n\tObj::CTrickComponent* pTrickComponent = GetTrickComponentFromObject(pSkater);\r\n\tDbg_Assert( pTrickComponent );\r\n    Obj::CStatsManagerComponent* pStatsManagerComponent = GetStatsManagerComponentFromObject(pSkater);\r\n\tDbg_Assert( pStatsManagerComponent );\r\n\t\r\n\t// Only flag a trick as having started if a real trick is being triggered\r\n\tif( trick_name && trick_name[0] )\r\n\t{\r\n\t\tpTrickComponent->SetFirstTrickStarted( true );\r\n\t}\r\n\t\r\n    bool is_switch = false; // need to make this grab the switch flag eventually!!!\r\n    pStatsManagerComponent->SetTrick( trick_name, base_score, is_switch );\r\n\r\n\t// We place a high limit on tricks, so if they \r\n\t// cheat with perfect baclance, and keep tricking\r\n\t// then they will not run out of memory and crash\r\n\tif (m_currentTrick > TRICK_LIMIT-1)\r\n\t{\r\n\t\tpack_trick_info_table();\r\n\r\n\t\tif (m_currentTrick > TRICK_LIMIT-1)\r\n\t\t{\r\n\t\t\t// GJ:  You should never be able to hit the trick limit any more\r\n\r\n\t\t\tif ( !null_trick )\r\n\t\t\t{\r\n\t\t\t\tprintf (\"Trick Limit (%d) Reached\\n\",TRICK_LIMIT);\r\n\t\t\t\t//tweak_last_valid_trick(base_score);\r\n\t\t\t\tm_infoTab.Last().score \t+= base_score;  // give them the score, just stop recording tricks\r\n\t\t\t\tm_currentMult++;\t\t\t\t\t\t// but still keep up the multipler \r\n\t\t\t\tcaptureScore();\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\r\n\t// trick type is based on id + switch mode\r\n\tuint32 id = Script::GenerateCRC(trick_name);\r\n\tuint32 switch_mode = (flags & (vSWITCH | vNOLLIE)) >> 1;\r\n\t\t\r\n\tif (m_infoTab.GetSize() < TRICK_LIMIT)\r\n\t{\r\n\t\tm_infoTab.Add(new TrickInfo);\r\n\t\tm_infoTab.Last().score \t\t\t\t= 0;\r\n\t}\r\n\t// if we have filled up the trick limit, then we just use the last one we added\r\n\t\r\n\tm_infoTab.Last().score \t\t\t\t+= base_score;\r\n\t//printf(\"triggering trick with id %s\\n\",trick_name);\r\n\tm_infoTab.Last().id \t\t\t\t= id;\r\n\tm_infoTab.Last().switch_mode\t\t= switch_mode;\r\n\tm_infoTab.Last().flags \t\t\t\t= flags;\r\n\tm_infoTab.Last().spin_mult_index \t= 0;\r\n\tm_infoTab.Last().trickNameText[0]\t= 0;\r\n\tm_infoTab.Last().trickTextFormatted[0]\t= 0;\r\n\tm_infoTab.Last().spin_degrees\t\t= 0;\r\n\t\r\n\tif (!null_trick)\r\n\t{\r\n\t\tcopy_trick_name_with_special_spaces(m_infoTab.Last().trickNameText, trick_name);\r\n\t\t\r\n\t\tif ( flags & Score::vCAT )\r\n\t\t{\r\n\t\t\tsprintf(m_infoTab.Last().trickTextFormatted, \"\\\\c3%s\\\\c0 \", m_infoTab.Last().trickNameText);\r\n\t\t}\r\n\t\telse if ( flags & Score::vSPECIAL )\r\n\t\t{\r\n\t\t\t// K: If the 'special' flag is set, use color 2\r\n\t\t\tsprintf(m_infoTab.Last().trickTextFormatted, \"\\\\c2%s\\\\c0 \", m_infoTab.Last().trickNameText);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsprintf(m_infoTab.Last().trickTextFormatted, \"%s \", m_infoTab.Last().trickNameText);\r\n\t\t}\r\n\t\t\r\n\t\t// toss the \"+\" onto the end of the previous trick\r\n\t\t\r\n\t\t// K: This bit of code used to do a sprintf, but I changed it to use a strcat instead\r\n\t\t// to preserve any color formatting added previously, such as the special-trick color\r\n\t\t// added above.\r\n\t\t\r\n\t\t// This is a loop so that null tricks (tricks with no name) get skipped over.\r\n\t\tint index=m_infoTab.GetSize() - 2;\r\n\t\twhile (true)\r\n\t\t{\r\n\t\t\tif (index<0)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tchar *p_trick_text_formatted=m_infoTab[index].trickTextFormatted;\r\n\t\t\tDbg_MsgAssert(p_trick_text_formatted,(\"NULL p_trick_text_formatted\"));\r\n\t\t\t\r\n\t\t\tint len=strlen(p_trick_text_formatted);\r\n\t\t\tif (*p_trick_text_formatted == '.')\r\n\t\t\t{\r\n\t\t\t\t// skip items that begin with \"...\"\r\n\t\t\t\t// (or else you get things like\r\n\t\t\t\t// \"... +  + blah blah\")\r\n\t\t\t}\r\n\t\t\telse if (len)\r\n\t\t\t{\r\n\t\t\t\t// Remove any trailing space character\t\t\r\n\t\t\t\tif (p_trick_text_formatted[len-1]==' ')\r\n\t\t\t\t{\r\n\t\t\t\t\tp_trick_text_formatted[len-1]=0;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t// Wack on the +\r\n\t\t\t\tstrcat(p_trick_text_formatted,\"\\\\_+ \");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t// Keep searching backwards until a named trick is found.\r\n\t\t\t--index;\r\n\t\t}\r\n\t}\r\n\t\t\t\r\n\t// if the last trick was a blocking trick, make this trick the spin trick\r\n\t// (or if this is the first trick)\r\n\tif (m_currentBlockingTrick == m_currentTrick - 1)\r\n\t\tm_currentSpinTrick = m_currentTrick;\r\n\tif (flags & vBLOCKING)\r\n\t{\r\n\t\tm_currentBlockingTrick = m_currentTrick;\r\n\t}\r\n\r\n\t// set depreciation stuff\r\n\t//Game::CGameMode* pGameMode = skate_mod->GetGameMode();\r\n\tif (!(flags & vGAP) && !(flags & vNODEGRADE) /*&& pGameMode->ShouldDegradeScore()*/)\r\n\t{\r\n\t\t// trick is not a gap, so figure out what its depreciation index will be\r\n\t\tTrickHistory *pHistory = m_historyTab.GetItem(id);\r\n\t\tif (!pHistory)\r\n\t\t{\r\n\t\t\t// if no history for this trick, create one\r\n\t\t\tpHistory = new TrickHistory;\r\n\t\t\tm_historyTab.PutItem(id, pHistory);\r\n\t\t\tfor (int s = 0; s < 4; s++)\r\n\t\t\t{\r\n\t\t\t\tpHistory->total_count[s] = 0;\r\n\t\t\t\tpHistory->combo_count[s] = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_infoTab.Last().mult_index = pHistory->total_count[switch_mode] + (pHistory->combo_count[switch_mode]++);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// gaps don't depreciate\r\n\t\t// no depreciation used in free skate\r\n\t\tm_infoTab.Last().mult_index = 0;\r\n\t}\r\n\t\r\n\tm_currentTrick++;\r\n\tif (!null_trick)\r\n\t{\r\n\t\t#ifdef NO_SCORE_DURING_UBER_FRIG\r\n\t\tint previousMult = m_currentMult;\r\n\t\t#endif\r\n\t\t\r\n\t\tm_currentMult++;\r\n\t\tif (m_currentMult == 1)\r\n\t\t{\r\n\t\t\tObj::CSkaterRunTimerComponent* pSkaterRunTimerComponent = GetSkaterRunTimerComponentFromObject(pSkater);\r\n\t\t\tDbg_Assert(pSkaterRunTimerComponent);\r\n\t\t\tpSkaterRunTimerComponent->ComboStarted();\r\n\t\t\t\r\n\t\t\tpSkater->BroadcastEvent(CRCD(0x670fda8c, \"SkaterEnterCombo\"));\r\n\t\t}\r\n\r\n\t\t#if 1\t\r\n\t\t// (Mick) check if this is the last of a long line of non-blocking tricks \r\n\t\t// and if so, then decrement the multiplier (leaving it unchanged)\r\n\t\tint non_block_count = 0;   \r\n\t\tfor (int i = m_currentTrick-1; i >0; i--)\r\n\t\t{\r\n\t\t\t// if a blocking trick, use default spin multiplier\r\n\t\t\tif (m_infoTab[i].flags & vBLOCKING)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tnon_block_count++;\r\n\t\t}\t\r\n//\t\tprintf (\"%3d: \",non_block_count);\r\n\t\tif (non_block_count > 10)\r\n\t\t{\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tprintf (\"CHEAT PREVENTION:  Limiting non blocking combo to 10\\n\");\r\n\t\t\t#endif\r\n\t\t\tm_infoTab.Last().score = 0;\r\n\t\t\tm_currentMult--;\r\n\t\t}\r\n\t\t#endif\r\n\t\t\r\n\t\t#ifdef NO_SCORE_DURING_UBER_FRIG\r\n\t\tObj::CSkaterAdjustPhysicsComponent* pSkaterAdjustPhysicsComponent = GetSkaterAdjustPhysicsComponentFromObject(pSkater);\r\n\t\tif (pSkaterAdjustPhysicsComponent && pSkaterAdjustPhysicsComponent->UberFriggedThisFrame())\r\n\t\t{\r\n\t\t\tm_infoTab.Last().score = 0;\r\n\t\t\tm_currentMult = previousMult;\r\n\t\t}\r\n\t\t#endif\r\n\t}\r\n\t\r\n\tif (m_debug)\r\n\t{\r\n\t\tprintf(\"Adding trick %s\\n\", trick_name);\r\n\t}\r\n\t\r\n\tcaptureScore();\r\n\r\n\tdispatch_trick_sequence_to_screen();\r\n\r\n\tTrickTextPulse(pSkater->GetHeapIndex());\r\n\tReplay::WriteTrickTextPulse();\t\r\n\t\t\r\n\tm_scorePotState = SHOW_ACTUAL_SCORE_POT;\r\n\tdispatch_score_pot_value_to_screen(m_scorePot, m_currentMult);\r\n\t\r\n\t/*\r\n\tif (mp_trickWindow)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_trickWindow,( \"no trick window defined\"));\r\n\t\r\n\t\tHUD::TrickWindow::TrickType trick_type = HUD::TrickWindow::vREGULAR;\r\n\t\tif (flags & vGAP) trick_type = HUD::TrickWindow::vGAP;\t\r\n\t\tif (flags & vSPECIAL) trick_type = HUD::TrickWindow::vSPECIAL;\t\r\n\t\t\r\n\t\tmp_trickWindow->AddTrick(trick_name, m_currentTrick, trick_type);\r\n\t}\r\n\t*/\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n\r\n\r\n\r\n/* \r\n\tCalled when spin changes. (From CSkater::HandleAirRotation()). \r\n*/\r\nvoid Score::UpdateSpin(int spin_degrees)\r\n{   \r\n\t// if score pot was reset, m_currentSpinTrick is no longer valid\r\n\tif (m_currentTrick == 0 || m_currentSpinTrick < 0)\r\n\t\treturn;\r\n\t\r\n\t// If a trick is blocking, then we don't want to add any\r\n\t// more spin to it after the initial spin\t\t\r\n\tif (m_infoTab[m_currentSpinTrick].flags & vBLOCKING)\r\n\t{\r\n\t\t// printf (\"Trick %d is blocing, %d degs\\n\",m_currentSpinTrick,spin_degrees);\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tSetSpin(spin_degrees);\r\n}\r\n\r\n/* \r\n\tCalled right after call to Trigger(). Current spin trick might be trick just added. Also \r\n\tcalled by Update() (above).\r\n\t\r\n\tUpdates the spin multiplier on the current spin trick. If the skater has increased his\r\n\tspin over the highest spin last recorded (increments of 180), then save the new spin\r\n\tmultiplier.\r\n*/\r\nvoid Score::SetSpin(int spin_degrees)\r\n{\r\n\t// if score pot was reset, m_currentSpinTrick is no longer valid\r\n\tif (m_currentTrick == 0 || m_currentSpinTrick < 0)\r\n\t\treturn;\r\n\r\n\tint spin_position = spin_degrees;\r\n    const char *p_direction = \"\";\r\n\r\n    Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n    Obj::CSkater* pSkater = skate_mod->GetSkaterById( m_skaterId );\r\n    Dbg_Assert( pSkater );\r\n\r\n    Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( pSkater );\r\n\tbool is_flipped = pAnimationComponent->IsFlipped();\r\n\r\n    // frontside or backside?\r\n    if (spin_position < 0)\r\n    { \r\n        spin_position = -spin_position;\r\n        if ( is_flipped )\r\n        {\r\n            p_direction = \"BS\";\r\n        }\r\n        else\r\n        {\r\n            p_direction = \"FS\";\r\n        }\r\n    }\r\n    else\r\n    {\r\n        if ( is_flipped )\r\n        {\r\n            p_direction = \"FS\";\r\n        }\r\n        else\r\n        {\r\n            p_direction = \"BS\";\r\n        }\r\n    }\r\n\r\n    // add a little fudge factor: doesn't need to fully rotate 180 to earn 180\r\n\tspin_position += (int)Obj::GetPhysicsFloat(CRCD(0x50c5cc2f, \"spin_count_slop\"));\t\r\n\tint spin_index = spin_position / 180;\r\n\r\n\t// TT#3426 - Clamp spins if too high, to prevent cheaters getting stuck and doing a lot of tricks\t\r\n\t// Not needed as spins only give you extra multiplier up to 900 anyway\r\n\t#if 0\r\n\tif (spin_index > 11)\r\n\t{\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tprintf (\"CHEAT WARNING, clamping spins\\n\");\r\n\t\t#endif\r\n\t\tspin_index = 11;\r\n\t}\r\n\t#endif\r\n\t\r\n\t// update the rotation amount of this trick\r\n\tm_infoTab[m_currentSpinTrick].spin_degrees = spin_degrees;\r\n\r\n\t// don't bother updating text if spin index isn't big enough\r\n\tif (m_infoTab[m_currentSpinTrick].spin_mult_index < spin_index)\r\n\t{\r\n\t\tif (m_debug)\r\n\t\t{\r\n\t\t\tprintf(\"New spin value %d:\\n\", spin_index * 180);\r\n\t\t}\r\n\t\t\r\n        // Not sure why this is necessary, but Ollies w/o another trick\r\n        // have the wrong spin direction on half rotations. i.e. 180, 540, 900, etc.\r\n        if ( m_infoTab[m_currentSpinTrick].id == CRCD(0x9b65d7b8,\"Ollie\") )\r\n        {\r\n            if ( (spin_index%2) == 1 )\r\n            {\r\n                if ( p_direction == \"FS\")\r\n                {\r\n                    p_direction = \"BS\";\r\n                }\r\n                else\r\n                {\r\n                    p_direction = \"FS\";\r\n                }\r\n            }\r\n        }\r\n        \r\n\t\tint last_trick = m_infoTab.GetSize() - 1;\r\n\t\tDbg_Assert(last_trick >= 0);\r\n\t\tint shown_spin = spin_index * 180;\r\n\t\t\r\n\t\tconst char *p_format=\"%d\\\\_%s\";\r\n\t\tif (last_trick > m_currentSpinTrick)\r\n\t\t{\r\n\t\t\tif (m_infoTab[m_currentSpinTrick].flags & Score::vCAT)\r\n\t\t\t{\r\n\t\t\t\tp_format=\"\\\\c3%s\\\\_%d\\\\_%s\\\\c0\\\\_+ \";\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (m_infoTab[m_currentSpinTrick].flags & Score::vSPECIAL)\r\n    \t\t\t{\r\n    \t\t\t\tp_format=\"\\\\c2%s\\\\_%d\\\\_%s\\\\c0\\\\_+ \";\r\n    \t\t\t}\r\n                else\r\n                {\r\n                    p_format=\"%s\\\\_%d\\\\_%s\\\\_+ \";\r\n                }\r\n\t\t\t}\t\r\n\t\t}\t\t\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (m_infoTab[m_currentSpinTrick].flags & Score::vCAT)\r\n\t\t\t{\r\n\t\t\t\tp_format=\"\\\\c3%s\\\\_%d\\\\_%s\\\\c0\";\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (m_infoTab[m_currentSpinTrick].flags & Score::vSPECIAL)\r\n    \t\t\t{\r\n    \t\t\t\tp_format=\"\\\\c2%s\\\\_%d\\\\_%s\\\\c0\";\r\n    \t\t\t}\r\n                else\r\n                {\r\n                    p_format=\"%s\\\\_%d\\\\_%s\";\r\n                }\r\n\t\t\t}\t\r\n\t\t}\t\t\r\n\t\t\r\n        sprintf(m_infoTab[m_currentSpinTrick].trickTextFormatted, p_format, p_direction, shown_spin, m_infoTab[m_currentSpinTrick].trickNameText);\r\n\t\tdispatch_trick_sequence_to_screen();\r\n\t\t\r\n\t\t/*\r\n\t\tif (mp_trickWindow)\r\n\t\t{\r\n\t\t\tmp_trickWindow->ChangeSpin(spin_index * 180, m_currentSpinTrick);\r\n\t\t}\r\n\t\t*/\r\n\t\tm_infoTab[m_currentSpinTrick].spin_mult_index = spin_index;\r\n\t\tcaptureScore();\r\n\r\n        Obj::CStatsManagerComponent* pStatsManagerComponent = GetStatsManagerComponentFromObject( pSkater );\r\n        Dbg_Assert( pStatsManagerComponent );\r\n        pStatsManagerComponent->SetSpin( (spin_index*180) );\r\n\t\t\r\n\t\tm_scorePotState = SHOW_ACTUAL_SCORE_POT;\r\n\t\tdispatch_score_pot_value_to_screen(m_scorePot, m_currentMult);\r\n\t\t\r\n\t\tpSkater->BroadcastEvent(CRCD(0x68b887bb, \"SkaterSpinDisplayed\"));\r\n\t}\r\n}\r\n\r\nvoid Score::TweakTrick(int tweak_value )\r\n{\t\r\n\tif (m_currentTrick <= 0) return;\r\n\t// K: If the last trick was a 'Null' trick, then do not add the score.\r\n\t// This is to fix TT5718, where it was possible to do a manual, then jump out of it\r\n\t// really quickly whilst still getting some score appearing on screen, even though you\r\n\t// did not really get those points because the non-null trick name had not been displayed yet.\r\n\t// (At the start of the manual, a 'null' trick is done using SetTrickName \"\", simply in order\r\n\t// to do a BlockSpin, but we don't want that null trick to enable the score counter)\r\n\tif (m_infoTab[m_currentTrick-1].trickNameText[0]==0) return;\r\n\t\r\n\t#if 1\t\r\n\t// (Mick) check if this is the last of a long line of non-blocking tricks \r\n\t// and if so, then decrement the multiplier (leaving it unchanged)\r\n\tint non_block_count = 0;   \r\n\tfor (int i = m_currentTrick-1; i >0; i--)\r\n\t{\r\n\t\t// if a blocking trick, use default spin multiplier\r\n\t\tif (m_infoTab[i].flags & vBLOCKING)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tnon_block_count++;\r\n\t}\t\r\n//\t\tprintf (\"%3d: \",non_block_count);\r\n\tif (non_block_count > 10)\r\n\t{\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tprintf (\"CHEAT PREVENTION:  Limiting tweak after 10 nonblocking trick\\n\");\r\n\t\t#endif\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif (!(m_infoTab[m_currentTrick-1].flags & vBLOCKING) && m_infoTab[m_currentTrick-1].score > MAX_SCORE_DUE_TO_TWEAK) return;\r\n\t#endif\r\n\t\r\n\t#ifdef NO_SCORE_DURING_UBER_FRIG\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = skate_mod->GetSkaterById(m_skaterId);\r\n\tObj::CSkaterAdjustPhysicsComponent* pSkaterAdjustPhysicsComponent = GetSkaterAdjustPhysicsComponentFromObject(pSkater);\r\n\tif (pSkaterAdjustPhysicsComponent && pSkaterAdjustPhysicsComponent->UberFriggedThisFrame()) return;\r\n\t#endif\r\n\t\r\n\tm_infoTab[m_currentTrick-1].score += tweak_value;\r\n\tcaptureScore();\r\n\t\r\n\tdispatch_trick_sequence_to_screen();\r\n\tm_scorePotState = SHOW_ACTUAL_SCORE_POT;\r\n\tdispatch_score_pot_value_to_screen(m_scorePot, m_currentMult);\r\n}\r\n\r\nvoid Score::Land( void )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tNet::Client* client;\r\n    \r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tGame::CGameMode* pGameMode = skate_mod->GetGameMode();\r\n\t\r\n\tcaptureScore();\r\n\t\r\n\t/*\r\n\tif (mp_trickWindow)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_trickWindow,( \"no trick window defined\"));\r\n\t\tmp_trickWindow->Count(true);\r\n    }\r\n\t*/\r\n\t\r\n\t// GLOOBY\r\n\tint trick_score = m_scorePot * m_currentMult;\r\n\r\n\tObj::CSkater* pSkater = skate_mod->GetSkaterById( m_skaterId );\r\n\tDbg_Assert( pSkater );\r\n\tDbg_Assert( pSkater->IsLocalClient());\r\n\t// if playing graffiti, then update the colors as appropriate\r\n\tbool debug_graffiti = Script::GetInteger( \"debug_graffiti\" );\r\n    Game::CGoalManager* pGoalManager = Game::GetGoalManager();\r\n\tpGoalManager->Land();\r\n\tif ( debug_graffiti || ( pGameMode->IsTrue(\"should_modulate_color\") ) && ( trick_score > 0 ) )\r\n\t{\r\n\t\t// update the server\t\t\r\n\t\tLogTrickObjectRequest( trick_score );\r\n\t}\r\n\r\n\t// flushes the graffiti trick buffer\r\n\tGetTrickComponentFromObject(pSkater)->SetGraffitiTrickStarted( false );\r\n    \r\n    if (!Script::GetInteger(\"NewSpecial\"))\t\r\n\t{\r\n\t\t// update special meter (when we land)\r\n\t\tm_specialScore += m_scorePot * m_currentMult;\r\n\t\tif (m_specialScore >= 3000)\r\n\t\t{\r\n\t\t\tset_special_is_active(true);\r\n\t\t\tm_specialScore = 3000;\r\n\t\t}\r\n\t\tif (m_specialScore < 0)\r\n\t\t{\r\n\t\t\tm_specialScore = 0;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_recentSpecialScorePot = 0;\t\t// ensure next trick is not infuenced by this trick\r\n\t}\r\n\t\r\n\t// update combo records\r\n\tif ( m_currentMult > m_longestCombo )\r\n\t{\r\n\t\t// printf(\"length: old record - %i, new record - %i\\n\", m_longestCombo, m_currentMult);\r\n\t\tm_longestCombo = m_currentMult;\r\n\t}\r\n\tif ( GetLastScoreLanded() > m_bestCombo )\r\n\t{\r\n\t\tm_bestCombo = GetLastScoreLanded();\r\n\t\t// printf(\"points: old record - %i, new record - %i\\n\", m_bestCombo, GetLastScoreLanded());\r\n\t}\r\n\r\n\tif ( GetLastScoreLanded() > m_bestGameCombo )\r\n\t{\r\n\t\tif( gamenet_man->InNetGame() && ( pGameMode->GetNameChecksum() != CRCD(0x1c471c60,\"netlobby\")))\r\n\t\t{\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\tNet::Client* client;\r\n\t\t\tGameNet::MsgScoreLanded msg;\r\n\t\r\n\t\t\tmsg.m_Score = GetLastScoreLanded();\r\n\t\t\tmsg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\t\t\t\r\n\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_COMBO_REPORT;\r\n\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgScoreLanded );\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\r\n\t\t\tclient = gamenet_man->GetClient( pSkater->GetSkaterNumber());\r\n\t\t\tDbg_Assert( client );\r\n\t\t\t\t\t\r\n\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t}\r\n\t\tm_bestGameCombo = GetLastScoreLanded();\r\n\t}\r\n\r\n\r\n\t// if not degrading score, we need to clear our history\r\n\tif (!pGameMode->ShouldDegradeScore())  \r\n\t{\r\n\t\t// clear combo history, and total history as well, althought that really should never ahve been set.\r\n\t\tfor (int i = 0; i < m_historyTab.getSize(); i++)\r\n\t\t{\r\n\t\t\tTrickHistory *pHistory = m_historyTab.GetItemByIndex(i);\r\n\t\t\tfor (int s = 0; s < 4; s++)\r\n\t\t\t{\r\n\t\t\t\tpHistory->total_count[s] = 0;\r\n\t\t\t\tpHistory->combo_count[s] = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\t// and reset the rail counters between combos  \r\n\t\treset_robot_detection();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// update trick history -- all counts from trick sequence are added to counts from session\r\n\t\tfor (int i = 0; i < m_historyTab.getSize(); i++)\r\n\t\t{\r\n\t\t\tTrickHistory *pHistory = m_historyTab.GetItemByIndex(i);\r\n\t\t\tfor (int s = 0; s < 4; s++)\r\n\t\t\t{\r\n\t\t\t\tpHistory->total_count[s] += pHistory->combo_count[s];\r\n\t\t\t\tpHistory->combo_count[s] = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (m_currentTrick)\r\n\t{\r\n\t\tm_scorePotState = WAITING_TO_COUNT_SCORE_POT;\r\n\t\tm_countedScorePot = m_scorePot * m_currentMult;\r\n\t\tm_scorePotCountdown = 150; // about 3 seconds\t\t\r\n\t\tdispatch_score_pot_value_to_screen(m_scorePot * m_currentMult, 0);\r\n\r\n\t\tint index;\r\n\t\tindex = pSkater->GetHeapIndex();\r\n\t\tTrickTextLanded(index);\r\n\t\tReplay::WriteTrickTextLanded();\r\n\t}\r\n\t\r\n\tresetScorePot();\r\n\r\n\tint old_score = GetTotalScore(); \r\n\r\n\t// if we're not in graffiti mode, then update the total score\r\n\t// and panel (in graffiti mode, the client doesn't have the\r\n\t// authority to set its own scores)\r\n\tif ( !pGameMode->IsTrue(CRCD(0x11941568, \"should_modulate_color\")) )\r\n\t{\r\n\t\tif( pGameMode->ShouldTrackTrickScore())\r\n\t\t{\r\n\t\t\tif( ( pGameMode->ShouldAccumulateScore()) || \r\n\t\t\t\t( ( pGameMode->ShouldTrackBestCombo()) &&\r\n\t\t\t\t  ( GetTotalScore() < trick_score )))\r\n\t\t\t{\r\n\t\t\t\tif( !gamenet_man->OnServer())\r\n\t\t\t\t{\r\n\t\t\t\t\tGameNet::MsgScoreLanded msg;\r\n\t\t\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t\t\tmsg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\t\t\t\t\tmsg.m_Score = trick_score;\r\n\t\t\t\t\t\r\n\t\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgScoreLanded );\r\n\t\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_LANDED_TRICK;\r\n\t\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\r\n\t\t\t\t\tclient = gamenet_man->GetClient( pSkater->GetSkaterNumber());\r\n\t\t\t\t\tDbg_Assert( client );\r\n\t\t\t\t\t\r\n\t\t\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( pGameMode->ShouldTrackBestCombo())\r\n\t\t\t\t{\r\n\t\t\t\t\tSetTotalScore( trick_score );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tSetTotalScore( m_totalScore + trick_score );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if( !pGameMode->ShouldTrackBestCombo())\r\n\t\t\t{\r\n\t\t\t\t// don't reset if the score is frozen\r\n\t\t\t\tif ( !pGameMode->ScoreFrozen() )\r\n\t\t\t\t\tSetTotalScore( trick_score );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tint new_score = GetTotalScore();\r\n\tcheck_high_score(old_score, new_score);\r\n\r\n\t\r\n\tObj::CSkaterRunTimerComponent* pSkaterRunTimerComponent = GetSkaterRunTimerComponentFromObject(pSkater);\r\n\tDbg_Assert(pSkaterRunTimerComponent);\r\n\tpSkaterRunTimerComponent->ComboEnded();\r\n\r\n\t// XXX\r\n//\tprintf(\"TRICK SCORE = %d\\n\", new_score);\t\r\n}\r\n\r\n\r\nvoid Score::ForceSpecial( void )\r\n{\r\n\tset_special_is_active(true);\r\n\tm_specialScore = 3000;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCalled whenever skater bails. Clears combo history, resets score pot, stops special\r\n*/\r\nvoid Score::Bail( bool clearScoreText )\r\n{    \r\n\t// update trick history -- clear counts for this combo\r\n\tfor (int i = 0; i < m_historyTab.getSize(); i++)\r\n\t{\r\n\t\tTrickHistory *pHistory = m_historyTab.GetItemByIndex(i);\r\n\t\tfor (int s = 0; s < 4; s++)\r\n\t\t\tpHistory->combo_count[s] = 0;\r\n\t}\r\n\r\n\tif (m_currentTrick)\r\n\t{\r\n\t\tm_scorePotState = SHOW_ACTUAL_SCORE_POT;\r\n\t\t\r\n\t\tif (!clearScoreText)\r\n\t\t{\r\n\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\tObj::CSkater* pSkater = skate_mod->GetSkaterById( m_skaterId );\r\n\t\t\tDbg_Assert( pSkater );\r\n\t\r\n\t\t\tdispatch_score_pot_value_to_screen(m_scorePot * m_currentMult, 0);\r\n\t\t\t\r\n\t\t\tint index;\r\n\t\t\tindex = pSkater->GetHeapIndex();\r\n\t\t\tTrickTextBail(index);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tdispatch_trick_sequence_to_screen(true);\r\n\t\t\tdispatch_score_pot_value_to_screen( 0, 0 );\r\n\t\t}\r\n\t\t\r\n\t\t// Replay::WriteTrickTextBail();\r\n\t}\r\n\t\r\n\t/*\r\n\tif (mp_trickWindow)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_trickWindow,( \"no trick window defined\"));\r\n\t\tmp_trickWindow->Collapse();\r\n\t}\r\n\t*/\r\n\t\r\n\tresetScorePot();\r\n\r\n\tm_specialScore = 0;\r\n\tset_special_is_active(false);\r\n\t\r\n\tObj::CSkaterRunTimerComponent* pSkaterRunTimerComponent\r\n\t\t= GetSkaterRunTimerComponentFromObject(Mdl::Skate::Instance()->GetSkaterById( m_skaterId ));\r\n\tDbg_Assert(pSkaterRunTimerComponent);\r\n\tpSkaterRunTimerComponent->ComboEnded();\r\n\r\n    Game::CGoalManager* pGoalManager = Game::GetGoalManager();\r\n\tpGoalManager->Bail();\r\n}\r\n\r\n\r\n\r\n// completely resets score object\r\nvoid Score::Reset()\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = skate_mod->GetSkaterById( m_skaterId );\r\n\t//GameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t//Net::Server* server; \r\n\r\n\tprintf (\"Score::RESET ...............\\n\");\r\n\r\n\treset_robot_detection();\r\n\r\n\tresetScorePot();\r\n\r\n\tLst::LookupTableDestroyer<TrickHistory> destroyer(&m_historyTab);\t\r\n\tdestroyer.DeleteTableContents();\r\n\t\r\n\t/*\r\n\tif (mp_trickWindow)\r\n\t{\r\n\t\tmp_trickWindow->ResetWindow();\r\n\t\tmp_trickWindow->ResetRecords();\r\n\t}\r\n\t*/\r\n\r\n\tif( pSkater && pSkater->IsLocalClient())\r\n\t{\r\n\t\tdispatch_trick_sequence_to_screen();\r\n\t\tdispatch_score_pot_value_to_screen( 0, 0 );\r\n\t}\r\n\t\r\n\tif( ( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0xbff33600,\"netfirefight\")) ||\r\n\t\t( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0x3d6d444f,\"firefight\")))\r\n\t{\r\n\t\tm_totalScore = 100;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_totalScore = 0;\r\n\t}\r\n\t\r\n\tm_scorePot = 0;\r\n\tm_recentScorePot = 0;\r\n\tm_recentSpecialScorePot = 0;\r\n\tm_specialScore = 0;\r\n\tm_bestGameCombo = 0;\r\n\t\r\n\tset_special_is_active(false);\r\n\r\n\t// Mick:  The next two lines clear any pending \"countdown\" score that might show up again after\r\n\t// we switch levels (or return to the skateshop)\r\n\tm_countedScorePot = 0;\r\n\tm_scorePotState = SHOW_ACTUAL_SCORE_POT;\r\n\r\n\tsetSpecialBarColors(); // Split into seperate function so that special bar colors could be updated for themes\r\n\t\r\n\tObj::CSkater* p_skater = Mdl::Skate::Instance()->GetSkaterById( m_skaterId );\r\n\tif (p_skater && p_skater->IsLocalClient())\r\n\t{\r\n\t\tObj::CSkaterRunTimerComponent* pSkaterRunTimerComponent = GetSkaterRunTimerComponentFromObject(p_skater);\r\n\t\tDbg_Assert(pSkaterRunTimerComponent);\r\n\t\tpSkaterRunTimerComponent->ComboEnded();\r\n\t}\r\n\r\n\t/*\r\n\tHUD::PanelMgr* panel_mgr = HUD::PanelMgr::Instance();\r\n\tHUD::Panel* panel;\r\n\r\n\tif(( panel = panel_mgr->GetPanelBySkaterId(m_skaterId, false)))\r\n\t{\r\n\t\tpanel->SetScore(0, true);\r\n\t}\r\n\t*/\r\n}\r\n\r\nvoid Score::setSpecialBarColors()\r\n{\r\n    Script::CArray *p_special_bar_colors = Script::GetArray(\"special_bar_colors\", Script::ASSERT);\r\n\tfor (int i = 0; i < 3; i++)\r\n\t{\r\n\t\tScript::CArray *p_rgba = p_special_bar_colors->GetArray(i);\r\n\r\n\t\tm_special_rgba[i].r = p_rgba->GetInteger(0);\r\n\t\tm_special_rgba[i].g = p_rgba->GetInteger(1);\r\n\t\tm_special_rgba[i].b = p_rgba->GetInteger(2);\r\n\t\tm_special_rgba[i].a = p_rgba->GetInteger(3);\r\n\t}\r\n\tm_special_interpolator_rate = Script::GetFloat(\"special_bar_iterpolator_rate\", Script::ASSERT);\r\n\r\n}\r\n\r\n\r\n/*\r\n\tTotals up score pot of present trick sequence, sends number to trick text window\r\n*/\r\nvoid Score::captureScore()\r\n{\r\n\t// if no tricks in list, then no score to capture \r\n\tif (m_currentTrick == 0) \r\n\t{\r\n\t\tm_recentSpecialScorePot = 0;\r\n\t\tm_recentScorePot = 0;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (m_debug)\r\n\t\tprintf(\"Score pot:\\n\");\r\n\t\r\n\t// compute score pot\r\n\tm_scorePot = 0;\r\n\tint current_spin_mult = 2;\t\t// n over 2\r\n\tfor (int i = 0; i < m_currentTrick; i++)\r\n\t{\r\n\t\t// if a blocking trick, use default spin multiplier\r\n\t\tif (m_infoTab[i].flags & vBLOCKING)\r\n\t\t{\r\n\t\t\tcurrent_spin_mult = 2;\r\n\t\t}\r\n\t\t// if not a blocking trick, but the last trick was, then use the spin multiplier here\r\n\t\t// to apply to subsequent tricks up to next blocking one\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (i == 0 || (m_infoTab[i-1].flags & vBLOCKING))\r\n\t\t\t{\r\n\t\t\t\tcurrent_spin_mult = spinMult(m_infoTab[i].spin_mult_index);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tint deprec_mult = deprecMult(m_infoTab[i].mult_index);\r\n\t\t\r\n\t\tif (m_debug)\r\n\t\t\tprintf(\"   base score %d, reduction mult %.2f, spin mult %.1f\\n\", \r\n\t\t\t\t   m_infoTab[i].score, (float) deprec_mult / 100, (float) current_spin_mult / 2);\r\n\t\t\r\n\t\tint score = (m_infoTab[i].score * deprec_mult * current_spin_mult) / 200;\r\n\t\tif (m_infoTab[i].switch_mode)\r\n\t\t{\r\n\t\t\tscore\t= score * 120 / 100;\r\n\t\t}\r\n\t\t\r\n\t\tm_scorePot += score;\r\n\t}\r\n\tif (m_debug)\r\n\t\tprintf(\"   total %d\\n\", m_scorePot);\r\n\t\r\n\t/*\r\n\tif( mp_trickWindow )\r\n\t{\r\n\t\tmp_trickWindow->SetScore(m_scorePot);\r\n\t}\r\n\t*/\r\n\r\n\tif (Script::GetInteger(\"NewSpecial\"))\t\r\n\t{\r\n//\t\tprintf (\"Score = %d, Recent = %d\\n\",m_scorePot * m_currentTrick , m_recentScorePot);\r\n\t\tif (m_scorePot * m_currentMult > m_recentSpecialScorePot)\r\n\t\t{\r\n\t\t\t// update special meter (constantly, as we score)\r\n\t\t\tm_specialScore += m_scorePot * m_currentMult - m_recentSpecialScorePot;\r\n\t\t\tif (m_specialScore <0)\r\n\t\t\t{\r\n\t\t\t\tset_special_is_active(false);\r\n\t\t\t\tm_specialScore = 0;\r\n\t\t\t}\r\n\t\t\tif (m_specialScore >= 3000)\r\n\t\t\t{\r\n\t\t\t\tset_special_is_active(true);\r\n\t\t\t\tm_specialScore = 3000;\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n\tm_recentScorePot = m_scorePot * m_currentMult;\r\n\tm_recentSpecialScorePot = m_scorePot * m_currentMult;\r\n}\r\n\r\n\r\n\r\nvoid Score::resetScorePot()\r\n{\r\n\tm_scorePot = 0;\r\n\tLst::DynamicTableDestroyer<TrickInfo> destroyer(&m_infoTab);\t\r\n\tdestroyer.DeleteTableContents();\r\n\tm_currentTrick = 0;\r\n\tm_currentMult = 0;\r\n\tm_currentBlockingTrick = -1;\r\n\tm_currentSpinTrick = -1;\r\n\treset_robot_detection_combo();\r\n\t//m_recentScorePot = 0;\r\n}\r\n\r\n\r\n\r\n\r\nvoid Score::dispatch_trick_sequence_to_screen ( bool clear_text )\r\n{\r\n\tFront::CScreenElementManager* p_manager = Front::CScreenElementManager::Instance();\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = skate_mod->GetSkaterById( m_skaterId );\r\n\tint index = 0;\r\n\r\n\tif( pSkater )\r\n\t{\r\n\t\tindex = pSkater->GetHeapIndex();\r\n\t}\r\n\tFront::CTextBlockElement *p_text_block = (Front::CTextBlockElement *) p_manager->GetElement(Script::GenerateCRC(\"the_trick_text\") + index ).Convert();\r\n\tif (!p_text_block) return;\r\n\r\n\tconst char *pp_string_tab[TRICK_LIMIT];\r\n\r\n\tif (!clear_text)\r\n\t{\r\n\t\tDbg_Assert(m_infoTab.GetSize() <= TRICK_LIMIT);\r\n\t\tfor (int i = 0; i < m_infoTab.GetSize(); i++)\r\n\t\t{\r\n\t\t\tpp_string_tab[i] = m_infoTab[i].trickTextFormatted;\r\n\t\t}\r\n\r\n\t\tp_text_block->SetText(pp_string_tab, m_infoTab.GetSize());\r\n\t\t// Replay::WriteTrickText(pp_string_tab, m_infoTab.GetSize());\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_text_block->SetText(pp_string_tab, 0);\r\n\t}\r\n\r\n\tScript::RunScript(\"UpdateTrickText\");\r\n}\r\n\r\n\r\n\r\n\r\nint Score::spinMult(int x)\r\n{\r\n\t// defines how the multiplier for spins ramps up.  .5 and 1 for 180 and 360, then 2,3,4,5,... for 540,720,900,1080,... etc.\r\n\t//return (((x)<MAX_SPIN_VALUES) ? (SPIN_MULT_VALUES[x]) : SPIN_MULT_VALUES[MAX_SPIN_VALUES-1]+4+4*((x)-MAX_SPIN_VALUES));\r\n\t// Ken: Made spin multiplier have a max value so that it doesn't get huge for flatland tricks.\r\n\treturn (((x)<MAX_SPIN_VALUES) ? (SPIN_MULT_VALUES[x]) : SPIN_MULT_VALUES[MAX_SPIN_VALUES-1]);\r\n}\r\n\r\n\r\n\r\n\r\nint Score::deprecMult(int x)\r\n{\r\n\treturn ((x < MAX_DEPREC) ? DEPREC_VALUES[x] : DEPREC_VALUES[MAX_DEPREC-1]);\r\n}\r\n\r\n\r\n\r\n\r\nvoid Score::setup_balance_meter_stuff()\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tScript::CStruct *p_balance_meter_struct = Script::GetStructure(\"balance_meter_info\");\r\n\tDbg_Assert(p_balance_meter_struct);\r\n\t\r\n\t// fetch arrow position table\r\n\tScript::CArray *p_arrow_array = NULL;\r\n\tp_balance_meter_struct->GetArray(\"arrow_positions\", &p_arrow_array);\r\n\tDbg_Assert(p_arrow_array);\r\n\tm_numArrowPositions = p_arrow_array->GetSize();\r\n\tfor (int i = 0; i < m_numArrowPositions; i++)\r\n\t{\r\n\t\tm_arrowPosTab[i] = *p_arrow_array->GetPair(i);\r\n\t}\r\n\t// for good measure\r\n\tm_arrowPosTab[m_numArrowPositions] = m_arrowPosTab[m_numArrowPositions-1];\r\n\tm_arrowInterval = 1.0f / ((float) m_numArrowPositions);\r\n\r\n\tScript::CArray *p_bar_pos_array = NULL;\r\n\tif( ( CFuncs::ScriptInSplitScreenGame( NULL, NULL )) && \r\n\t\t( skate_mod->GetGameMode()->GetNameChecksum() != Script::GenerateCRC( \"horse\" )) &&\r\n\t\t( skate_mod->GetGameMode()->GetNameChecksum() != Script::GenerateCRC( \"nethorse\" )))\r\n\t{\r\n\t\tif( Nx::CViewportManager::sGetScreenMode() == Nx::vSPLIT_V )\r\n\t\t{\r\n\t\t\tp_balance_meter_struct->GetArray(\"bar_positions_mp_v\", &p_bar_pos_array);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_balance_meter_struct->GetArray(\"bar_positions_mp_h\", &p_bar_pos_array);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_balance_meter_struct->GetArray(\"bar_positions\", &p_bar_pos_array);\r\n\t}\r\n\r\n\tDbg_Assert(p_bar_pos_array);\r\n\tfor (int i = 0; i < 2; i++)\r\n\t{\r\n\t\tm_meterPos[i] = *p_bar_pos_array->GetPair(i);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid Score::position_balance_meter(bool state, float value, bool isVertical)\r\n{\r\n\tFront::CScreenElementManager* p_manager = Front::CScreenElementManager::Instance();\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = skate_mod->GetSkaterById( m_skaterId );\r\n\r\n\tFront::CSpriteElement *p_balance_meter = (Front::CSpriteElement *) p_manager->GetElement(0xa4db8a4b + pSkater->GetHeapIndex()).Convert(); // \"the_balance_meter\"\r\n\tDbg_Assert(p_balance_meter);\r\n\t\r\n\tint is_shown = 0;\r\n\tp_balance_meter->GetIntegerTag(0xc22eb9a0, &is_shown); // \"tag_turned_on\"\r\n\tif (state != (bool) is_shown)\r\n\t{\r\n\t\tScript::CStruct* pParams;\r\n\t\tpParams = new Script::CStruct;\r\n\t\tpParams->AddChecksum( \"id\", 0xa4db8a4b + pSkater->GetHeapIndex());\r\n\t\tif (state)\r\n\t\t{   \r\n\t\t\tScript::RunScript(CRCD(0xba95da16, \"show_balance_meter\"), pParams );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tScript::RunScript(CRCD(0x58783b40, \"hide_balance_meter\"), pParams );\r\n\t\t}\r\n\r\n\t\tdelete pParams;\r\n\t}\r\n\t\r\n\tif (isVertical)\r\n\t\tp_balance_meter->SetChecksumTag(0x863a07e2, 0xef24413b); // \"tag_mode\", \"manual\"\r\n\telse\r\n\t\tp_balance_meter->SetChecksumTag(0x863a07e2, 0x530be001); // \"tag_mode\", \"balance\"\r\n\t\r\n\t// figure out position of arrow\r\n\tfloat abs_value = Mth::Abs(value);\r\n\tint index = (int) ( abs_value / m_arrowInterval);\r\n\tfloat mix =  abs_value - ((float) index) * m_arrowInterval;\r\n\tm_arrowPos.mX = m_arrowPosTab[index].mX + (m_arrowPosTab[index+1].mX - m_arrowPosTab[index].mX) * mix / m_arrowInterval;\r\n\tm_arrowPos.mY = m_arrowPosTab[index].mY + (m_arrowPosTab[index+1].mY - m_arrowPosTab[index].mY) * mix / m_arrowInterval;\r\n\t//printf(\"arrow at %f, %f, index %d, mix %f\\n\", m_arrowPos.mX, m_arrowPos.mY, index, mix);\r\n\tm_arrowRot = -value * 45.0f;\r\n\t\r\n\tFront::CSpriteElement *p_balance_arrow = (Front::CSpriteElement *) p_balance_meter->GetFirstChild();//.Convert();\r\n\tDbg_Assert(p_balance_arrow);\r\n\t\r\n\tif (isVertical)\r\n\t{\r\n\t\tp_balance_meter->SetPos(m_meterPos[1].mX, m_meterPos[1].mY, Front::CScreenElement::FORCE_INSTANT);\r\n\t\tp_balance_meter->SetRotate(-90.0f);\r\n\t\tif (value >= 0.0f)\r\n\t\t\tp_balance_arrow->SetPos(p_balance_meter->GetBaseW() / 2.0f + m_arrowPos.mY, p_balance_meter->GetBaseH() / 2.0f - m_arrowPos.mX, Front::CScreenElement::FORCE_INSTANT);\r\n\t\telse\r\n\t\t\tp_balance_arrow->SetPos(p_balance_meter->GetBaseW() / 2.0f + m_arrowPos.mY, p_balance_meter->GetBaseH() / 2.0f + m_arrowPos.mX, Front::CScreenElement::FORCE_INSTANT);\r\n\t\tp_balance_arrow->SetRotate(-m_arrowRot - 90.0f);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_balance_meter->SetPos(m_meterPos[0].mX, m_meterPos[0].mY, Front::CScreenElement::FORCE_INSTANT);\r\n\t\tp_balance_meter->SetRotate(0);\r\n\t\tif (value >= 0.0f)\r\n\t\t\tp_balance_arrow->SetPos(p_balance_meter->GetBaseW() / 2.0f + m_arrowPos.mX, p_balance_meter->GetBaseH() / 2.0f + m_arrowPos.mY, Front::CScreenElement::FORCE_INSTANT);\r\n\t\telse\r\n\t\t\tp_balance_arrow->SetPos(p_balance_meter->GetBaseW() / 2.0f - m_arrowPos.mX, p_balance_meter->GetBaseH() / 2.0f + m_arrowPos.mY, Front::CScreenElement::FORCE_INSTANT);\r\n\t\tp_balance_arrow->SetRotate(-m_arrowRot);\r\n\t}\t\r\n}\r\n\r\n\r\n\r\n\r\nvoid Score::dispatch_score_pot_value_to_screen(int score, int multiplier)\r\n{\r\n\tFront::CScreenElementManager* p_manager = Front::CScreenElementManager::Instance();\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\r\n\tObj::CSkater* pSkater = skate_mod->GetSkaterById( m_skaterId );\r\n\tint index = 0;\r\n\r\n\tif( pSkater )\r\n\t{\r\n\t\tindex = pSkater->GetHeapIndex();\r\n\t}\r\n\tFront::CTextElement *p_score_pot_text = (Front::CTextElement *) p_manager->GetElement(0xf4d3a70e + index ).Convert(); // \"the_score_pot_text\"\r\n\tDbg_Assert(p_score_pot_text);\r\n\r\n\tchar p_string[128];\r\n\tif (!score)\r\n\t\tstrcpy(p_string, \" \");\r\n\telse if (multiplier)\r\n\t\tsprintf(p_string, \"%s X %d\", Str::PrintThousands(score), multiplier);\r\n\telse\r\n\t\tsprintf(p_string, \"%s\", Str::PrintThousands(score));\r\n\r\n\t\r\n\tp_score_pot_text->SetText(p_string);\r\n\t\r\n\tReplay::WriteScorePotText(p_string);\r\n\tScript::RunScript(\"UpdateScorepot\");\r\n}\r\n\r\n// Check for a high score goals being achieved\t   \r\n// for each goal that is actieved, then run the script\r\n// on the skater that got the score\r\nvoid Score::check_high_score(int old_score, int new_score)\r\n{\r\n\t#ifdef\tDEBUG_HIGH_SCORE_GOALS\r\n\tprintf(\"Checking High Scores, score changed from %d to %d\\n\",old_score, new_score); \r\n\t#endif\r\n\t\r\n\tMdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n\t// if we are not in career mode, then do not check for high score\t\t\t   \r\n\tif (!skate_mod->GetGameMode()->IsTrue( CRCD(0x1ded1ea4, \"is_career\") ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (int i=0;i < Mdl::Skate::vMAX_SCORE_GOALS;i++)\r\n\t{\r\n\t\tint score = skate_mod->GetScoreGoalScore(i);\r\n\t\tint goal = skate_mod->GetScoreGoalGoal(i);\r\n\t\tuint32 script = skate_mod->GetScoreGoalScript(i);\r\n\t\tif (score)\t\t\r\n\t\t{\r\n\t\t\t#ifdef\tDEBUG_HIGH_SCORE_GOALS\r\n\t\t\tprintf(\"For goal %2d, score %7d, script %x\\n\",goal,score,script); \r\n\t\t\t#endif\r\n\t\t\tif (old_score < score && new_score >= score)\r\n\t\t\t{\r\n\t\t\t\t#ifdef\tDEBUG_HIGH_SCORE_GOALS\r\n\t\t\t\tdodgy_test(); printf(\"Score change works\\n\"); \r\n\t\t\t\t#endif\r\n\t\t\t\tif( !skate_mod->GetCareer()->GetGoal(goal))\r\n\t\t\t\t{\r\n\t\t\t\t\t#ifdef\tDEBUG_HIGH_SCORE_GOALS\r\n\t\t\t\t\tprintf(\"awarding this goal, and running script\"); \r\n\t\t\t\t\t#endif\r\n\t\t\t\t\t// not got this goal yet, so give it\r\n\t\t\t\t\tskate_mod->GetCareer()->SetGoal(goal);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// and run the script\r\n\t\t\t\t\tskate_mod->GetSkaterById( m_skaterId )->SpawnAndRunScript(script);\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t#ifdef\tDEBUG_HIGH_SCORE_GOALS\r\n\t\t\t\t\tprintf(\"Already got this goal\\n\"); \r\n\t\t\t\t\t#endif\r\n\t\t\t\t}\r\n\t\t\t}  \r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t#ifdef\tDEBUG_HIGH_SCORE_GOALS\r\n\t\t\t\tprintf(\"Score change did not straddel this score\\n\"); \r\n\t\t\t\t#endif\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Score::SetBalanceMeter(bool state, float value)\r\n{\r\n\tReplay::WriteBalanceMeter(state,value);\r\n\t//Ryan(\"balance: %f\\n\", value);\r\n\tposition_balance_meter(state, value, false);\r\n}\r\n\r\n\r\n\r\n\r\nvoid Score::SetManualMeter(bool state, float value)\r\n{\r\n\tReplay::WriteManualMeter(state,value);\r\n\t\r\n\t//Ryan(\"balance: %f\\n\", value);\r\n\tposition_balance_meter(state, value, true);\r\n}\r\n\r\n\r\n\r\n\r\nvoid Score::SetTotalScore( int score )\r\n{\r\n\tm_totalScore = score;\r\n\r\n\t// update the panel\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\t/*Game::CGameMode* pGameMode = */skate_mod->GetGameMode();\r\n//\tbool can_zero_score = pGameMode->IsTrue(\"should_modulate_color\");\r\n\r\n\t//\tprintf(\"Setting total score for %d: %d %d %s\\n\", m_skaterId, score, GetTotalScore(), Script::FindChecksumName(pGameMode->GetNameChecksum()) );\r\n\t\r\n\tObj::CSkater* pSkater = skate_mod->GetSkaterById( m_skaterId );\r\n\tDbg_Assert( pSkater );\r\n\tif ( pSkater->IsLocalClient() )\r\n\t{\r\n\t\t//HUD::PanelMgr* panel_mgr = HUD::PanelMgr::Instance();\r\n\t\t//HUD::Panel* panel;\r\n\t\tchar score_text[64];\r\n\t\t\r\n\t\tif( ( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netking\" )) ||\r\n\t\t\t( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"king\" )))\r\n\t\t{\r\n\t\t\tsprintf( score_text, \"%d:%.2d\", Tmr::InSeconds( m_totalScore ) / 60, Tmr::InSeconds( m_totalScore ) % 60 );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsprintf( score_text, \"%d\", m_totalScore );\r\n\t\t}\r\n\r\n\t\tFront::SetScoreTHPS4( score_text, pSkater->GetHeapIndex());\r\n\r\n\t\t/*\r\n\t\tif(( panel = panel_mgr->GetPanelBySkaterId(m_skaterId, false)))\r\n\t\t{\r\n\t\t\tpanel->SetScore( m_totalScore, can_zero_score );\r\n\t\t}\r\n\t\t*/\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nint Score::GetTotalScore()\r\n{\t\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tGame::CGameMode* pGameMode = skate_mod->GetGameMode();\r\n\r\n\t\t// server is also responsible for calculating graffiti scores\r\n\t\tbool debug_graffiti = Script::GetInteger( \"debug_graffiti\" );\r\n\t\tif ( debug_graffiti || pGameMode->IsTrue(\"should_modulate_color\") )\r\n\t\t{\r\n\t\t\treturn skate_mod->GetTrickObjectManager()->GetScore( m_skaterId );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn m_totalScore;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// clients already knows their total scores\r\n\t\treturn m_totalScore;\r\n\t}\r\n\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tReturns the network connection.\r\n*/\r\nNet::Conn* Score::GetAssociatedNetworkConnection( void )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tObj::CSkater* skater;\r\n\tGameNet::PlayerInfo* player;\r\n\r\n\t\r\n\r\n\tskater = skate_mod->GetSkaterById( m_skaterId );\r\n\tif( skater )\r\n\t{\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( skater->GetID() );\r\n\t\tif( player )\r\n\t\t{\r\n\t\t\treturn player->m_Conn;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n\r\nvoid Score::LogTrickObjectRequest( int score )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tGameNet::PlayerInfo* player;\r\n\tGameNet::MsgScoreLogTrickObject msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tNet::Client* client;   \r\n\r\n\tplayer = gamenet_man->GetPlayerByObjectID( m_skaterId );\r\n\tDbg_Assert( player );\r\n    \r\n\tclient = gamenet_man->GetClient( player->m_Skater->GetSkaterNumber());\r\n\tDbg_MsgAssert( client, ( \"Couldn't find client for skater %d\", player->m_Skater->GetSkaterNumber() ) );\r\n\r\n\tmsg.m_SubMsgId = GameNet::SCORE_MSG_ID_LOG_TRICK_OBJECT;\r\n\tmsg.m_OwnerId = m_skaterId;\r\n\tmsg.m_Score = score;\r\n\tmsg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* skater = skate_mod->GetSkaterById( m_skaterId );\r\n\tDbg_Assert( skater );\r\n\t\r\n\tObj::CTrickComponent* p_trick_component = GetTrickComponentFromObject(skater);\r\n\tDbg_Assert(p_trick_component);\r\n\r\n\t// send out variable length data representing the trick chain\r\n\tuint32 max_pending_trick_buffer_size = GameNet::MsgScoreLogTrickObject::vMAX_PENDING_TRICKS * sizeof(uint32);\r\n\tuint32 actual_pending_trick_buffer_size = p_trick_component->WritePendingTricks( msg.m_PendingTrickBuffer, max_pending_trick_buffer_size );\r\n\tmsg.m_NumPendingTricks = actual_pending_trick_buffer_size / sizeof( uint32 );\r\n\r\n\tprintf( \"Client -> server %d tricks\\n\", msg.m_NumPendingTricks );\r\n\r\n\tmsg_desc.m_Data = &msg;\r\n\tmsg_desc.m_Length = sizeof( GameNet::MsgScoreLogTrickObject ) - max_pending_trick_buffer_size + actual_pending_trick_buffer_size;\r\n\tmsg_desc.m_Id = GameNet::MSG_ID_SCORE;\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t//client->EnqueueMessageToServer( &msg_desc );\r\n\t\r\n\tclient->StreamMessageToServer( msg_desc.m_Id, msg_desc.m_Length, \r\n\t\t\t\t\t\t   msg_desc.m_Data, \"TrickObj Buffer\", GameNet::vSEQ_GROUP_PLAYER_MSGS );\r\n\r\n}\r\n\r\n\r\n\r\n\r\nvoid Score::LogTrickObject( int skater_id, int score, uint32 num_pending_tricks, uint32* p_pending_tricks, bool propagate )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tGameNet::MsgScoreLogTrickObject msg;\r\n\tGameNet::MsgObsScoreLogTrickObject obs_msg;\r\n\tNet::Server* server;\r\n\tNet::Conn* conn;\r\n\tGameNet::PlayerInfo* player;\r\n\tLst::Search< GameNet::PlayerInfo > sh;\r\n\r\n\tif( propagate )\r\n\t{\r\n\t\tbool send_steal_message;\r\n\r\n\t\tserver = gamenet_man->GetServer();\r\n\t\tDbg_Assert( server );\r\n\r\n\t\tconn = GetAssociatedNetworkConnection();\r\n\r\n\t\t// keep track of whom we need to send the steal message to\r\n\t\tint i;\r\n\t\tchar previous_owner_flags[GameNet::vMAX_PLAYERS];\r\n\t\tfor ( i = 0; i < GameNet::vMAX_PLAYERS; i++ )\r\n\t\t{\r\n\t\t\tprevious_owner_flags[i] = 0;\r\n\t\t}\r\n\t\t\r\n\t\tnum_pending_tricks = skate_mod->GetTrickObjectManager()->RequestLogTrick( num_pending_tricks, p_pending_tricks, previous_owner_flags, skater_id, score );\r\n\t\t\r\n\t\tif ( !num_pending_tricks )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tfor ( i = 0; i < GameNet::vMAX_PLAYERS; i++ )\r\n\t\t{\r\n\t\t\tif ( previous_owner_flags[i] )\r\n\t\t\t{\r\n\t\t\t\t// GJ:  This only sends the stolen message to the two parties involved\r\n\r\n\t\t\t\tGameNet::PlayerInfo* new_owner, *old_owner;\r\n\t\t\t\tGameNet::MsgStealMessage steal_msg;\r\n\r\n\t\t\t\tsteal_msg.m_NewOwner = skater_id;\r\n\t\t\t\tsteal_msg.m_OldOwner = i;\r\n\t\t\t\tsteal_msg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\r\n\t\t\t\tnew_owner = gamenet_man->GetPlayerByObjectID(skater_id);\r\n\t\t\t\told_owner = gamenet_man->GetPlayerByObjectID( i );\r\n\t\t\t\tDbg_Assert( new_owner );\r\n\t\t\t\t\r\n\t\t\t\tsend_steal_message = true;\r\n\t\t\t\tif( skate_mod->GetGameMode()->IsTeamGame())\r\n\t\t\t\t{\r\n\t\t\t\t\tif( old_owner && new_owner && ( old_owner->m_Team == new_owner->m_Team ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsend_steal_message = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( send_steal_message )\r\n\t\t\t\t{\r\n\t\t\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t\t\tmsg_desc.m_Data = &steal_msg;\r\n\t\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgStealMessage );\r\n\t\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_STEAL_MESSAGE;\r\n\t\t\t\t\tserver->EnqueueMessage( new_owner->GetConnHandle(), &msg_desc );\r\n\t\r\n\t\t\t\t\tsteal_msg.m_NewOwner = skater_id;\r\n\t\t\t\t\tsteal_msg.m_OldOwner = i;\r\n\t\t\t\t\tsteal_msg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\t\r\n                    //Dbg_Assert( pPlayerInfo );\r\n\t\r\n\t\t\t\t\t// For now, don't assert if the player doesn't exist anymore. Just don't do anything.\r\n\t\t\t\t\t// Eventually, Gary will fix this so that pieces of exiting players are reset\r\n\t\t\t\t\tif( old_owner )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tserver->EnqueueMessage( old_owner->GetConnHandle(), &msg_desc );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n#ifdef __USER_GARY__\r\n\t\tprintf( \"Broadcasting %d tricks\\n\", num_pending_tricks );\r\n#endif\r\n\t\t\r\n\t\tmsg.m_SubMsgId = GameNet::SCORE_MSG_ID_LOG_TRICK_OBJECT;\r\n\t\tmsg.m_OwnerId = skater_id;\r\n\t\tmsg.m_Score = score;\r\n\t\tmsg.m_NumPendingTricks = num_pending_tricks;\r\n\t\tmsg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\r\n\t\tuint32 max_pending_trick_buffer_size = GameNet::MsgScoreLogTrickObject::vMAX_PENDING_TRICKS * sizeof(uint32);\r\n\t\tuint32 actual_pending_trick_buffer_size = msg.m_NumPendingTricks * sizeof(uint32);\r\n\t\tmemcpy( msg.m_PendingTrickBuffer, p_pending_tricks, actual_pending_trick_buffer_size );\r\n\r\n\t\tNet::MsgDesc score_msg_desc;\r\n\r\n\t\tscore_msg_desc.m_Data = &msg;\r\n\t\tscore_msg_desc.m_Length = sizeof( GameNet::MsgScoreLogTrickObject ) - max_pending_trick_buffer_size + actual_pending_trick_buffer_size;\r\n\t\tscore_msg_desc.m_Id = GameNet::MSG_ID_SCORE;\r\n\t\tscore_msg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tscore_msg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t// tell players to change their colors\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; \r\n\t\t\t\tplayer = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tserver->StreamMessage( player->GetConnHandle(), score_msg_desc.m_Id, score_msg_desc.m_Length, \r\n\t\t\t\t\t\t   score_msg_desc.m_Data, \"TrickObj Buffer\", GameNet::vSEQ_GROUP_PLAYER_MSGS );\r\n\t\t\t//server->EnqueueMessage( player->GetConnHandle(), &score_msg_desc );\r\n\t\t}\r\n\r\n\t\tobs_msg.m_OwnerId = skater_id;\r\n\t\tobs_msg.m_NumPendingTricks = num_pending_tricks;\r\n\t\tobs_msg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\t\tmax_pending_trick_buffer_size = GameNet::MsgScoreLogTrickObject::vMAX_PENDING_TRICKS * sizeof(uint32);\r\n\t\tactual_pending_trick_buffer_size = obs_msg.m_NumPendingTricks * sizeof(uint32);\r\n\t\tmemcpy( obs_msg.m_PendingTrickBuffer, p_pending_tricks, actual_pending_trick_buffer_size );\r\n\r\n\t\tscore_msg_desc.m_Data = &obs_msg;\r\n\t\tscore_msg_desc.m_Length = sizeof( GameNet::MsgObsScoreLogTrickObject ) - max_pending_trick_buffer_size + actual_pending_trick_buffer_size;\r\n\t\tscore_msg_desc.m_Id = GameNet::MSG_ID_OBSERVER_LOG_TRICK_OBJ;\r\n\t\t// tell observers to change their colors\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; \r\n\t\t\t\tplayer = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t{\r\n\t\t\tif( player->IsObserving())\r\n\t\t\t{\r\n\t\t\t\tserver->StreamMessage( player->GetConnHandle(), score_msg_desc.m_Id, score_msg_desc.m_Length, \r\n\t\t\t\t\t\t   score_msg_desc.m_Data, \"TrickObj Buffer\", GameNet::vSEQ_GROUP_PLAYER_MSGS );\r\n\t\t\t\t//server->EnqueueMessage( player->GetConnHandle(), &score_msg_desc );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// send score updates, as something has changed\r\n\t\tskate_mod->SendScoreUpdates( false );\r\n\t\t\r\n\t\t// Let the server's client do the rest of the work\r\n\t\tif( conn->IsLocal())\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n#ifdef __USER_GARY__\r\n\tprintf( \"Client is receiving %d tricks\\n\", num_pending_tricks );\r\n#endif\r\n\t\r\n\tint seq;\r\n\r\n\tif( skate_mod->GetGameMode()->IsTeamGame())\r\n\t{\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( skater_id );\r\n\t\tseq = player->m_Team;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tseq = skater_id;\r\n\t}\r\n\r\n\t// modulate the color here\r\n\tfor ( uint32 i = 0; i < num_pending_tricks; i++ )\r\n\t{\r\n\t\t\r\n\t\tskate_mod->GetTrickObjectManager()->ModulateTrickObjectColor( p_pending_tricks[i], seq );\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// utilities used by the trick counting functions to resolve a key_combo\r\n// or trick to its trick text checksum after taking into account the number\r\n// of taps.\r\ninline uint32 get_trickname_checksum_from_trick_and_taps( uint32 trick_checksum, int num_taps = 1 )\r\n{\r\n\t// get the trick text and associated checksum\r\n\tScript::CStruct* p_trick = Script::GetStructure( trick_checksum, Script::ASSERT );\r\n\tScript::CStruct* p_trick_params;\r\n\tp_trick->GetStructure( CRCD( 0x7031f10c, \"params\" ), &p_trick_params, Script::ASSERT );\r\n\r\n\tconst char* p_trick_name;\r\n\r\n\t// get any double or triple tap info\r\n\twhile ( num_taps > 1 )\r\n\t{\t\t\t\r\n\t\tnum_taps--;\r\n\r\n\t\tScript::CArray* p_extra_trick_array;\r\n\t\tuint32 extra_trick;\r\n\r\n\t\tif ( !p_trick_params->GetChecksum( CRCD( 0x6e855102, \"ExtraTricks\" ), &extra_trick, Script::NO_ASSERT ) )\r\n\t\t\tDbg_MsgAssert( 0, ( \"Couldn't find ExtraTricks to get multiple tap version of trick\" ) );\r\n\t\t\r\n\t\t// printf(\"got extra trick %s\\n\", Script::FindChecksumName( extra_trick ) );\r\n\t\t\r\n\t\tp_extra_trick_array = Script::GetArray( extra_trick, Script::ASSERT );\r\n\t\tDbg_MsgAssert( p_extra_trick_array->GetType() == ESYMBOLTYPE_STRUCTURE, ( \"Extra trick array %s had wrong type\", Script::FindChecksumName( extra_trick ) ) );\r\n\t\tScript::CStruct* p_sub_struct = p_extra_trick_array->GetStructure( 0 );\r\n\t\tp_sub_struct->GetStructure( CRCD( 0x7031f10c, \"params\" ), &p_trick_params, Script::ASSERT );\r\n\t}\r\n\t\r\n\tp_trick_params->GetLocalString( CRCD( 0xa1dc81f9, \"name\" ), &p_trick_name, Script::ASSERT );\r\n\t// printf(\"found name %s\\n\", p_trick_name);\r\n\treturn Script::GenerateCRC( p_trick_name );\r\n}\r\n\r\ninline uint32 get_trickname_checksum_from_key_combo( uint32 key_combo, int num_taps = 1 )\r\n{\r\n\t// printf(\"\\tget_trickname_checksum_from_key_combo( %s, %i )\\n\", Script::FindChecksumName( key_combo ), num_taps );\r\n\t\r\n\t// get the key mapping and trick name\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile();\r\n\tScript::CStruct* pTricks = pSkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") );\t\r\n\tuint32 trick_checksum = 0;\r\n\t\r\n\t// see if this is a normal or special trick\r\n\tif ( !pTricks->GetChecksum( key_combo, &trick_checksum, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tScript::CStruct* pSpecialTricks = pSkaterProfile->GetSpecialTricksStructure();\r\n\t\tScript::CArray* pSpecialTricksArray;\r\n\t\tpSpecialTricks->GetArray( NONAME, &pSpecialTricksArray, Script::ASSERT );\r\n\t\tint numSpecials = pSpecialTricksArray->GetSize();\r\n\t\tfor ( int i = 0; i < numSpecials; i++ )\r\n\t\t{\r\n\t\t\tScript::CStruct* pSpecial = pSpecialTricksArray->GetStructure( i );\r\n\t\t\tuint32 trickSlot;\r\n\t\t\tpSpecial->GetChecksum( CRCD( 0xa92a2280, \"TrickSlot\" ), &trickSlot, Script::ASSERT );\r\n\t\t\tif ( trickSlot == key_combo )\r\n\t\t\t{\r\n\t\t\t\tpSpecial->GetChecksum( CRCD( 0x5b077ce1, \"TrickName\" ), &trick_checksum, Script::ASSERT );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif ( trick_checksum == 0 )\r\n\t\treturn 0;\r\n\r\n\treturn get_trickname_checksum_from_trick_and_taps( trick_checksum, num_taps );\t\r\n}\r\n\r\n\r\ninline uint32 get_cat_index_from_key_combo( uint32 key_combo )\r\n{\r\n\t// printf(\"\\tget_trickname_checksum_from_key_combo( %s, %i )\\n\", Script::FindChecksumName( key_combo ), num_taps );\r\n\t\r\n\t// get the key mapping and trick name\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile();\r\n\tScript::CStruct* pTricks = pSkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") );\t\r\n\tint cat_trick = -1;\r\n\t\r\n\t// see if this is a normal or special trick\r\n\r\n\tif ( !pTricks->GetInteger( key_combo, &cat_trick, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tScript::CStruct* pSpecialTricks = pSkaterProfile->GetSpecialTricksStructure();\r\n\t\tScript::CArray* pSpecialTricksArray;\r\n\t\tpSpecialTricks->GetArray( NONAME, &pSpecialTricksArray, Script::ASSERT );\r\n\t\tint numSpecials = pSpecialTricksArray->GetSize();\r\n\t\tfor ( int i = 0; i < numSpecials; i++ )\r\n\t\t{\r\n\t\t\tScript::CStruct* pSpecial = pSpecialTricksArray->GetStructure( i );\r\n\t\t\tint is_cat = 0;\r\n\t\t\tpSpecial->GetInteger( CRCD(0xb56a8816,\"isCat\"), &is_cat, Script::NO_ASSERT );\r\n\t\t\tif ( is_cat != 0 )\r\n\t\t\t{\r\n\t\t\t\tuint32 trickslot;\r\n\t\t\t\tpSpecial->GetChecksum( CRCD(0xa92a2280,\"trickSlot\"), &trickslot, Script::ASSERT );\r\n\t\t\t\tif ( trickslot == key_combo )\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 cat_trick_checksum;\r\n\t\t\t\t\tpSpecial->GetChecksum( CRCD(0x5b077ce1,\"trickName\"), &cat_trick_checksum, Script::ASSERT );\r\n\t\t\t\t\tcat_trick = (int)cat_trick_checksum;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn cat_trick;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Score::VerifyTrickMatch( int info_tab_index, uint32 trick_checksum, int spin_mult, bool require_perfect )\r\n{\r\n\tif ( info_tab_index >= m_currentTrick )\r\n\t\treturn false;\r\n\t\r\n\t// printf(\"\\tVerifyTrickMatch( %i, %s, %i, %i )\\n\", info_tab_index, Script::FindChecksumName( trick_checksum ), spin_mult, require_perfect );\r\n\t// printf(\"m_infoTab[%i].id = %s\\n\", info_tab_index, Script::FindChecksumName( m_infoTab[info_tab_index].id ) );\r\n\tif ( m_infoTab[info_tab_index].id == trick_checksum )\r\n\t{\r\n\t\tif ( spin_mult == 0 )\r\n\t\t\treturn true;\r\n\t\telse \r\n\t\t{\r\n\t\t\t// printf(\"spin_degrees for this trick = %i\\n\", m_infoTab[i].spin_degrees);\r\n\t\t\tif ( spin_mult == m_infoTab[info_tab_index].spin_mult_index )\r\n\t\t\t{\r\n\t\t\t\tif ( !require_perfect )\r\n\t\t\t\t\treturn true;\r\n\t\t\t\telse if ( Mth::Abs( Mth::Abs(m_infoTab[info_tab_index].spin_degrees) - ( spin_mult * 180 ) ) < Script::GetInteger( CRCD( 0xfcfacab8, \"perfect_landing_slop\" ) ) )\r\n\t\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\t\t\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Score::CountTrickMatches( uint32 trick_checksum, int spin_mult, bool require_perfect )\r\n{\r\n\t// printf(\"CountTrickMatches( %s, %i, %i )\\n\", Script::FindChecksumName( trick_checksum ), spin_mult, require_perfect );\r\n\tint current_spin = 1;\r\n\t\r\n\tint total = 0;\r\n\r\n\tfor ( int i = 0; i < m_currentTrick; i++ )\r\n\t{\r\n\t\tif ( m_infoTab[i].flags & vBLOCKING )\r\n\t\t{\r\n\t\t\tcurrent_spin = 1;\r\n\t\t}\r\n\t\telse if ( i == 0 || ( i >= 1 && m_infoTab[i-1].flags & vBLOCKING ) )\r\n\t\t{\r\n\t\t\tcurrent_spin = m_infoTab[i].spin_mult_index;\r\n\t\t}\r\n\t\t// printf(\"current_spin = %i\\n\", current_spin );\r\n\t\t\r\n\t\tif ( m_infoTab[i].id == trick_checksum )\r\n\t\t{\r\n\t\t\tif ( spin_mult == 0 )\r\n\t\t\t\ttotal++;\r\n\t\t\telse \r\n\t\t\t{\r\n\t\t\t\t// printf(\"spin_degrees for this trick = %i\\n\", m_infoTab[i].spin_degrees);\r\n\t\t\t\tif ( spin_mult == current_spin )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !require_perfect )\r\n\t\t\t\t\t\ttotal++;\r\n\t\t\t\t\telse if ( Mth::Abs( Mth::Abs(m_infoTab[i].spin_degrees) - ( spin_mult * 180 ) ) < Script::GetInteger( CRCD( 0xfcfacab8, \"perfect_landing_slop\" ) ) )\r\n\t\t\t\t\t\ttotal++;\r\n\t\t\t\t}\r\n\t\t\t}\t\t\r\n\t\t}\r\n\t}\r\n\treturn total;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Score::CountStringMatches( const char* string )\r\n{\r\n\tint total = 0;\r\n    \r\n    for ( int i = 0; i < m_currentTrick; i++ )\r\n\t{\r\n        if ( Str::StrStr( m_infoTab[i].trickNameText, string ) )\r\n\t\t{\r\n            total++;\t\t\r\n\t\t}\r\n\t}\r\n\treturn total;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Score::IsLatestTrickByName( uint32 trick_text_checksum, int spin_mult, bool require_perfect, int num_taps )\r\n{\r\n\tint index = m_currentTrick;\r\n\tdo\r\n\t{\r\n\t\tif (index <= 0) return false;\r\n\t\tindex--;\r\n\t}\r\n\twhile (m_infoTab[index].trickNameText[0] == 0);\r\n\t\r\n\t// resolve multiple tap tricks\r\n\tif (num_taps > 1)\r\n\t{\r\n\t\ttrick_text_checksum = get_trickname_checksum_from_trick_and_taps(trick_text_checksum, num_taps);\r\n\t}\r\n\t\r\n\treturn VerifyTrickMatch(index, trick_text_checksum, spin_mult, require_perfect);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Score::IsLatestTrick( uint32 key_combo, int spin_mult, bool require_perfect, int num_taps )\r\n{\r\n\tint index = m_currentTrick;\r\n\tdo\r\n\t{\r\n\t\tif (index <= 0) return false;\r\n\t\tindex--;\r\n\t}\r\n\twhile (m_infoTab[index].trickNameText[0] == 0);\r\n\t\r\n\t// get the key mapping and trick name\r\n\tuint32 trick_name_checksum = get_trickname_checksum_from_key_combo( key_combo, num_taps );\r\n\tif ( trick_name_checksum == 0 )\r\n\t{\r\n\t\t// check for cat trick\t\t\r\n\t\tint cat_trick = get_cat_index_from_key_combo( key_combo );\r\n\t\tif ( cat_trick != -1 )\r\n\t\t{\r\n\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\tDbg_Assert( skate_mod );\r\n\t\t\tObj::CSkater* pSkater = skate_mod->GetLocalSkater();\r\n\t\t\tif ( pSkater )\r\n\t\t\t{\r\n\t\t\t\tGame::CCreateATrick* pCreatedTrick = pSkater->m_created_trick[cat_trick];\r\n\t\t\t\tDbg_Assert( pCreatedTrick );\r\n\t\t\t\tconst char* p_trick_name;\r\n\t\t\t\tpCreatedTrick->mp_other_params->GetString( CRCD( 0xa1dc81f9, \"name\" ), &p_trick_name, Script::ASSERT );\r\n\t\t\t\ttrick_name_checksum = Script::GenerateCRC( p_trick_name );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn VerifyTrickMatch(index, trick_name_checksum, spin_mult, require_perfect);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Score::GetNumberOfNonGapTricks()\r\n{\r\n\tint non_gap_trick_count = 0;\r\n\t\r\n\tfor ( int i = 0; i < m_currentTrick; i++ )\r\n\t{\r\n\t\tif (!TrickIsGap(i))\r\n\t\t{\r\n\t\t\tnon_gap_trick_count++;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn non_gap_trick_count;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// find a trick by name, rather than by key combo\r\nint Score::GetCurrentNumberOfOccurrencesByName( uint32 trickTextChecksum, int spin_mult, bool require_perfect, int num_taps )\r\n{\r\n\t// resolve multiple tap tricks\r\n\tif ( num_taps > 1 )\r\n\t{\r\n\t\ttrickTextChecksum = get_trickname_checksum_from_trick_and_taps( trickTextChecksum, num_taps );\r\n\t}\r\n\t\r\n\t// uint32 trick_name_checksum = Script::GenerateCRC( trick_string );\r\n\tint num = CountTrickMatches( trickTextChecksum, spin_mult, require_perfect );\r\n/*\tfor ( int i = 0; i < m_currentTrick; i++ )\r\n\t{\r\n\t\tif ( VerifyTrickMatch( i, trickTextChecksum, spin_mult, require_perfect ) )\r\n\t\t\tnum++;\r\n\t}*/\r\n\treturn num;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// searches by key combo\r\nint Score::GetCurrentNumberOfOccurrences( uint32 key_combo, int spin_mult, bool require_perfect, int num_taps )\r\n{\r\n\t// get the key mapping and trick name\r\n\tuint32 trick_name_checksum = get_trickname_checksum_from_key_combo( key_combo, num_taps );\r\n\tif ( trick_name_checksum == 0 )\r\n\t{\r\n\t\t// check for cat trick\t\t\r\n\t\tint cat_trick = get_cat_index_from_key_combo( key_combo );\r\n\t\tif ( cat_trick != -1 )\r\n\t\t{\r\n\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\tDbg_Assert( skate_mod );\r\n\t\t\tObj::CSkater* pSkater = skate_mod->GetLocalSkater();\r\n\t\t\tif ( pSkater )\r\n\t\t\t{\r\n\t\t\t\tGame::CCreateATrick* pCreatedTrick = pSkater->m_created_trick[cat_trick];\r\n\t\t\t\tDbg_Assert( pCreatedTrick );\r\n\t\t\t\tconst char* p_trick_name;\r\n\t\t\t\tpCreatedTrick->mp_other_params->GetString( CRCD( 0xa1dc81f9, \"name\" ), &p_trick_name, Script::ASSERT );\r\n\t\t\t\ttrick_name_checksum = Script::GenerateCRC( p_trick_name );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t}\r\n\r\n\tint num = this->CountTrickMatches( trick_name_checksum, spin_mult, require_perfect );\r\n/*    for ( int i = 0; i < m_currentTrick; i++ )\r\n    {\r\n        if ( this->VerifyTrickMatch( i, trick_name_checksum, spin_mult, require_perfect) )\r\n\t\t\tnum++;\r\n    }\r\n*/\r\n\treturn num;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Score::GetPreviousNumberOfOccurrencesByName( uint32 trickTextChecksum, int spin_mult, int num_taps )\r\n{\r\n\t// resolve multiple tap tricks\r\n\tif ( num_taps > 1 )\r\n\t{\r\n\t\ttrickTextChecksum = get_trickname_checksum_from_trick_and_taps( trickTextChecksum, num_taps );\r\n\t}\r\n\t\r\n\tint num = 0;\r\n    bool justSawTrick = false;\r\n    for ( int i = 0; i < m_currentTrick; i++ )\r\n    {\r\n        // printf(\"checking %s\\n\", m_infoTab[i].trickNameText );\r\n        if ( m_infoTab[i].id == trickTextChecksum )\r\n        {\r\n            // printf(\"found trick\\n\");\r\n            if ( spin_mult == 0 )\r\n\t\t\t{\r\n\t\t\t\tnum++;\r\n\t\t\t\tjustSawTrick = true;\r\n\t\t\t}\r\n\t\t\telse if ( spin_mult == m_infoTab[i].spin_mult_index )\r\n\t\t\t{\r\n\t\t\t\tnum++;\r\n\t\t\t\tjustSawTrick = true;\r\n\t\t\t}\r\n            \r\n        }\r\n        else \r\n        {\r\n            if ( ( m_infoTab[i].flags & vGAP ) && justSawTrick )\r\n            {\r\n                // printf(\"found gap after trick\\n\");\r\n            }\r\n            else\r\n            {\r\n                // if ( justSawTrick ) printf(\"found a non-gap trick after the trick\\n\");\r\n                justSawTrick = false;\r\n            }\r\n        }\r\n    }\r\n    if ( justSawTrick )\r\n    {\r\n        // printf(\"followed by gaps\\n\");\r\n        num--;\r\n    }\r\n    // printf(\"found %i previous occurences\\n\", num );\r\n    return num;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Score::GetPreviousNumberOfOccurrences( uint32 key_combo, int spin_mult, int num_taps )\r\n{\r\n\t// printf ( \"GetPreviousNumberOfOccurrences( %s, %i, %i )\\n\", Script::FindChecksumName( key_combo ), spin_mult, num_taps );\r\n\tuint32 trick_name_checksum = get_trickname_checksum_from_key_combo( key_combo, num_taps );\r\n\t\r\n\tif ( trick_name_checksum == 0 )\r\n\t{\r\n\t\t// check for cat trick\t\t\r\n\t\tint cat_trick = get_cat_index_from_key_combo( key_combo );\r\n\t\tif ( cat_trick != -1 )\r\n\t\t{\r\n\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\tDbg_Assert( skate_mod );\r\n\t\t\tObj::CSkater* pSkater = skate_mod->GetLocalSkater();\r\n\t\t\tif ( pSkater )\r\n\t\t\t{\r\n\t\t\t\tGame::CCreateATrick* pCreatedTrick = pSkater->m_created_trick[cat_trick];\r\n\t\t\t\tDbg_Assert( pCreatedTrick );\r\n\t\t\t\tconst char* p_trick_name;\r\n\t\t\t\tpCreatedTrick->mp_other_params->GetString( CRCD( 0xa1dc81f9, \"name\" ), &p_trick_name, Script::ASSERT );\r\n\t\t\t\ttrick_name_checksum = Script::GenerateCRC( p_trick_name );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t}\r\n\t\r\n\tint num = 0;\r\n    bool justSawTrick = false;\r\n    for ( int i = 0; i < m_currentTrick; i++ )\r\n    {\r\n        // printf(\"checking %s\\n\", m_infoTab[i].id );\r\n        if ( m_infoTab[i].id == trick_name_checksum )\r\n        {\r\n            // printf(\"found trick\\n\");\r\n            if ( spin_mult == 0 )\r\n\t\t\t{\r\n\t\t\t\tnum++;\r\n\t\t\t\tjustSawTrick = true;\r\n\t\t\t}\r\n\t\t\telse if ( spin_mult == m_infoTab[i].spin_mult_index )\r\n\t\t\t{\r\n\t\t\t\tnum++;\r\n\t\t\t\tjustSawTrick = true;\r\n\t\t\t}            \r\n        }\r\n        else \r\n        {\r\n            if ( ( m_infoTab[i].flags & vGAP ) && justSawTrick )\r\n            {\r\n                // printf(\"found gap after trick\\n\");\r\n            }\r\n            else\r\n            {\r\n                // if ( justSawTrick ) printf(\"found a non-gap trick after the trick\\n\");\r\n                justSawTrick = false;\r\n            }\r\n        }\r\n    }\r\n    if ( justSawTrick )\r\n    {\r\n        // printf(\"followed by gaps\\n\");\r\n        num--;\r\n    }\r\n    // printf(\"found %i previous occurences\\n\", num );\r\n    return num;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// utility used by GetCurrentNumberOfOccurrences( Script::CArray* )\r\ninline void GetTrickInfoFromTrickArray( Script::CArray* pTricks, int trick_array_index, uint32 *p_trick_name_checksum, int *p_spin, bool *p_require_perfect, int *p_num_taps )\r\n{\r\n\t// reset spin and perfect first\r\n\t*p_spin = 0;\r\n\t*p_require_perfect = false;\r\n\r\n\tint num_taps = 1;\r\n\tuint32 key_combo;\r\n\r\n\tif ( pTricks->GetType() == ESYMBOLTYPE_STRUCTURE )\r\n\t{\r\n\t\t// grab the key combo and any spin or perfect modifiers from the struct\r\n\t\tScript::CStruct* pSubStruct = pTricks->GetStructure( trick_array_index );\r\n\t\tpSubStruct->GetChecksum( CRCD( 0x95e16467, \"KeyCombo\" ), &key_combo, Script::ASSERT );\r\n\t\tpSubStruct->GetInteger( CRCD( 0xa4bee6a1, \"num_taps\" ), &num_taps, Script::NO_ASSERT );\r\n\t\tpSubStruct->GetInteger( CRCD(0xa4bee6a1,\"num_taps\"), &*p_num_taps, Script::NO_ASSERT );\r\n\t\t*p_trick_name_checksum = get_trickname_checksum_from_key_combo( key_combo, num_taps );\r\n\t\tif ( pSubStruct->GetInteger( CRCD( 0xedf5db70, \"spin\" ), &*p_spin, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( *p_spin % 180 == 0, ( \"Bad spin value %i in gap tricks structure\", *p_spin ) );\r\n\t\t\t*p_spin = *p_spin / 180;\r\n\t\t\t*p_require_perfect = pSubStruct->ContainsFlag( CRCD( 0x1c39f1b9, \"perfect\" ) );\r\n\t\t}\r\n\t\t// printf(\"\\tlooking for key_combo %s\\n\", Script::FindChecksumName( key_combo ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert( pTricks->GetType() == ESYMBOLTYPE_NAME, ( \"Tricks array has wrong type\" ) );\r\n\t\t*p_trick_name_checksum = get_trickname_checksum_from_key_combo( pTricks->GetChecksum( trick_array_index ) );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Score::GetCurrentNumberOfOccurrences( Script::CArray* pTricks, int start_trick_index )\r\n{\r\n\tDbg_Message(\"DEPRECATED! Tell Brad if you need this.\\n\");\r\n\treturn 0;\r\n\r\n\r\n/*\tDbg_MsgAssert( start_trick_index <= m_currentTrick, ( \"GetCurrentNumberOfOccurrences got bad start_trick_index of %i - m_currentTrick = %i\", start_trick_index, m_currentTrick ) );\r\n\t\r\n\tint trick_array_size = pTricks->GetSize();\r\n\tint total = 0;\r\n\t\r\n\t// parse through the current list of tricks\r\n\tfor ( int trick_array_index = 0; trick_array_index )\r\n\t{\r\n\t\t\r\n\t}\r\n\tfor ( int i = start_trick_index; i < m_currentTrick; i++ )\r\n\t{\r\n\t\t// printf(\"\\tcurrent trick = %s\\n\", Script::FindChecksumName( m_infoTab[i].id ) );\r\n\t\tint trick_array_index = 0;\r\n\t\tuint32 trick_name_checksum;\r\n\t\tint spin = 0;\r\n\t\tbool require_perfect = false;\r\n\t\tint num_taps = 0;\r\n\t\tGetTrickInfoFromTrickArray( pTricks, trick_array_index, &trick_name_checksum, &spin, &require_perfect, &num_taps );\r\n\r\n\t\twhile ( VerifyTrickMatch( i + trick_array_index, trick_name_checksum, spin, require_perfect ) )\r\n\t\t{\r\n\t\t\t// printf(\"\\tfound a match\\n\");\r\n\t\t\t// if we've matched as many tricks as are in the list, we know we've\r\n\t\t\t// found a complete match\r\n\t\t\tif ( trick_array_index == trick_array_size - 1 )\r\n\t\t\t{\r\n\t\t\t\ttotal++;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\ttrick_array_index++;\r\n\t\t\tGetTrickInfoFromTrickArray( pTricks, trick_array_index, &trick_name_checksum, &spin, &require_perfect, &num_taps );\r\n\t\t}\r\n\t}\r\n*/\r\n\t// printf(\"found %i occurrence(s)\\n\", total);\r\n\t// return total;\r\n}\r\n\r\nvoid\tScore::RepositionMeters( void )\r\n{\r\n\tsetup_balance_meter_stuff();\r\n}\r\n\r\nvoid Score::ResetComboRecords()\r\n{\r\n\tm_longestCombo = 0;\r\n\tm_bestCombo = 0;\r\n\tm_bestGameCombo = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/* Handle network scoring messages                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tScore::s_handle_score_message ( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::MsgEmbedded* p_msg = (GameNet::MsgEmbedded*) ( context->m_Msg );\r\n\tMdl::Score* pScore = ((Obj::CSkater*) ( context->m_Data ))->GetScoreObject();\r\n\t\r\n\tswitch ( p_msg->m_SubMsgId )\r\n\t{\r\n\t\tcase GameNet::SCORE_MSG_ID_LOG_TRICK_OBJECT:\r\n\t\t{\r\n\t\t\tGameNet::MsgScoreLogTrickObject* log_msg = (GameNet::MsgScoreLogTrickObject*) ( context->m_Msg );\r\n\t\t\tGameNet::Manager* gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\t\t\tif ( log_msg->m_GameId == gamenet_man->GetNetworkGameId())\r\n\t\t\t{\r\n\t\t\t\tpScore->LogTrickObject( log_msg->m_OwnerId, log_msg->m_Score, log_msg->m_NumPendingTricks, log_msg->m_PendingTrickBuffer, false );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Score::TrickIsGap( int trickIndex )\r\n{\r\n\tDbg_MsgAssert( trickIndex >= 0 && trickIndex < m_currentTrick, ( \"trickIndex out of range\" ) );\r\n\treturn ( m_infoTab[trickIndex].flags & vGAP );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Score::set_special_is_active ( bool is_active )\r\n{\r\n\tif (is_active != m_specialIsActive)\r\n\t{\r\n\t\tm_specialIsActive = is_active;\r\n\t\t\r\n\t\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetSkaterById(m_skaterId);\r\n\t\tif( pSkater )\r\n\t\t{\r\n\t\t\tpSkater->BroadcastEvent(m_specialIsActive ? CRCD(0xd0cd8081, \"SkaterEnterSpecial\") : CRCD(0x7ccf5ee2, \"SkaterExitSpecial\"));\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\nvoid Score::reset_robot_detection()\r\n{\r\n\tm_num_robot_landed = 0;\r\n\tm_num_robot_unique = 0;\r\n\tfor (int i=0;i<MAX_ROBOT_NODES;i++)\r\n\t{\r\n\t\tm_robot_detection_count[i] = 0;\r\n\t}\r\n\treset_robot_detection_combo();\r\n\r\n}\r\n\r\nvoid Score::reset_robot_detection_combo()\r\n{\r\n\tm_num_robot_landed_combo = 0;\r\n\tm_num_robot_unique_combo = 0;\r\n\tm_num_robot_first_combo = 0;\r\n\tfor (int i=0;i<MAX_ROBOT_NODES;i++)\r\n\t{\r\n\t\tm_robot_detection_count_combo[i] = 0;\r\n\t}\r\n\tm_robot_rail_mult = 1.0f;\r\n\r\n}\r\n\t\r\nvoid Score::UpdateRobotDetection(int node)\r\n{\r\n\r\n// Mick:  Most levels fit inside the curretn 2500 limit\r\n// so,rather than mess with memory, I'm just going to ignore those nodes that do not fit\r\n// this gives us a very small chance of there being some area that is slightly more\r\n// exploitable than others.   However, since the robot line detection does not have a very noticable effect\r\n// there will basically be no impact on the overall game experience.\r\n//\tDbg_MsgAssert(node < MAX_ROBOT_NODES,(\"robot node %d too big, tell Mick\",node));\r\n\tif (node >= MAX_ROBOT_NODES)\r\n\t{\r\n\t\tm_robot_rail_mult = 1.0f;\r\n\t\treturn;\r\n\t}\r\n\r\n\r\n\r\n\tm_num_robot_landed++;\r\n\tm_num_robot_landed_combo++;\r\n\tif (m_robot_detection_count[node] == 0)\r\n\t{\t\r\n\t\tm_num_robot_unique++;\r\n\t\tm_num_robot_first_combo++;\r\n\t}\r\n\tif (m_robot_detection_count[node] < 255)\r\n\t{\r\n\t\tm_robot_detection_count[node]++;\r\n\t}\r\n\t\r\n\tif (m_robot_detection_count_combo[node] == 0)\r\n\t{\t\r\n\t\tm_num_robot_unique_combo++;\r\n\t}\r\n\tif (m_robot_detection_count_combo[node] < 255)\r\n\t{\r\n\t\tm_robot_detection_count_combo[node]++;\r\n\t}\r\n\t\r\n//\tGetRobotMult();\r\n\r\n\t\t\t\t\t\t\t\t  \r\n\tint \tkick_in = Script::GetInteger(CRCD(0x6ee127b7,\"robot_kick_in_count\"));\t\t\t\t\t\t\t  \r\n\r\n\tif (m_robot_detection_count_combo[node] > kick_in)\r\n\t{\r\n\t\tint ramp = 20;\r\n\t\t// The first time you go over robot_kick_count, we want 1/2, everything before that will be 1.0f\r\n\t\tm_robot_rail_mult = 1.0f/(m_robot_detection_count_combo[node]-(kick_in)+1) * ( (float)(ramp + 1 - m_robot_detection_count[node])/(float)ramp);\r\n\t\t// Might go small or negative after a really long time, so clamp it\r\n\t\tm_robot_rail_mult = Mth::Max(0.1f, m_robot_rail_mult);\t\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tm_robot_rail_mult = 1.0f;\r\n\t}\r\n\t\r\n\r\n}\r\n\r\n\r\nfloat\tScore::GetRobotMult()\r\n{\r\n\t\r\n\tprintf (\"landed = %3d, unique = %3d .. \",m_num_robot_landed,m_num_robot_unique);\r\n\tprintf (\"combo landed = %3d, unique = %3d, first = %d\\n\",m_num_robot_landed_combo,m_num_robot_unique_combo,m_num_robot_first_combo);\r\n\t\r\n//\tfloat unique_ratio = (float)m_num_robot_unique_combo/(float)m_num_robot_landed_combo;\r\n//\tfloat first_ratio = (float)m_num_robot_first_combo/(float)m_num_robot_landed_combo;\r\n//\tfloat punish = 1.0f - 0.5f * logf(robot);\r\n//\tfloat reward = logf(m_num_robot_unique_combo) - logf(robot);\r\n//\tprintf (\"robot = %2.3f, punish = x%2.3f, reward = x%2.3f\\n\",robot, punish, reward);\t\r\n\r\n\tint\tmin_robot_effect = 3;  // number of repetitions at which \"robot\" adjustment begins\r\n\r\n\tfloat sub = 0.0f;\r\n\t// Scale any effect by the size of the combo, beyond the minimun needed to take effect\t\r\n//\tfloat robot_scale = 0.0f;\r\n\tif ((m_num_robot_landed_combo - m_num_robot_unique_combo) > min_robot_effect && m_num_robot_unique_combo < m_num_robot_landed_combo)\r\n\t{\r\n#\tif !defined( __PLAT_NGC__ ) || ( defined( __PLAT_NGC__ ) && !defined( __NOPT_FINAL__ ) )\r\n\t\tfloat landed = m_num_robot_landed_combo - min_robot_effect;\r\n\t\tfloat dupes = m_num_robot_landed_combo - m_num_robot_unique_combo - min_robot_effect;\r\n//\t\tfloat first =  m_num_robot_first_combo;\r\n\t\t\r\n//\t\trobot_scale = 0.1f * logf(landed);   // with min of 10, 10=0, 50 =1.6, 100 = 1.95 \r\n\t\t// find an amount to subtract from a 1.0f multiplier, based on how repeditive this line is\r\n//\t\tfloat dupe_sub = (dupes/landed); \r\n//\t\tfloat first_sub = 0.0f;\t//0.05f * logf(landed - first); \r\n//\t\tfloat sub = robot_scale * (dupe_sub + first_sub);\r\n\t\tfloat sub = dupes/landed;\r\n//\t\tprintf (\"(dupe = %2.3f + first = %2.3f) * scale %2.3f == sub %2.3f\\n\", dupe_sub, first_sub, robot_scale,  sub);\r\n\t\tprintf (\"sub = %2.3f\\n\",sub);\r\n#endif\t\t// __NOPT_FINAL__\r\n\t}\r\n\t\r\n\tfloat mult = 1.0f - sub;\r\n\tif (mult > 1.0f)\r\n\t{\r\n\t\tmult = 1.0f;\r\n\t}\r\n\tif (mult < 0.2f)\r\n\t{\r\n\t\tmult = 0.2f;\r\n\t}\r\n\tprintf (\"mult = %2.3f\\n\",mult);\r\n\treturn mult;\r\n}\t\r\n\r\n\r\n\r\n} // namespace HUD\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/score.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2001 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\t\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\trjm, 1/23/2001\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __MODULES_SKATE_SCORE_H\r\n#define __MODULES_SKATE_SCORE_H\r\n\r\n#include <core/defines.h>\r\n\r\n#include <core/lookuptable.h>\r\n#include <core/dynamictable.h>\r\n\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/array.h>\r\n#include <gfx/Image/ImageBasic.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Net\r\n{\r\n\tclass\tConn;\r\n\tclass\tMsgHandlerContext;\r\n}\r\n\r\nnamespace Mdl\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  Score  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic:\r\n\t\r\n\ttypedef uint32 Flags;\r\n\tenum\r\n\t{\r\n\t\tvBLOCKING \t\t= nBit(1),\r\n\t\tvSWITCH\t\t\t= nBit(2),\r\n\t\tvNOLLIE\t\t\t= nBit(3),\r\n\t\tvGAP\t\t\t= nBit(4),\r\n\t\tvSPECIAL\t\t= nBit(5),\r\n\t\tvNODEGRADE\t\t= nBit(6),\r\n\t\tvCAT\t\t\t= nBit(7),\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n\t\tMAX_ROBOT_NODES = 2500\r\n\t};\r\n\t\t\t\t\t\t\t\t\tScore();\r\n\t\t\t\t\t\t\t\t\t~Score();\r\n\r\n\tvoid \t\t\t\t\t\t\tUpdate();\r\n\tvoid \t\t\t\t\t\t\tSetSkaterId(short skater_id);\r\n\r\n\tvoid \t\t\t\t\t\t\tSetTotalScore( int score );\r\n\tint \t\t\t\t\t\t\tGetTotalScore();\r\n\tint \t\t\t\t\t\t\tGetLastScoreLanded() {return m_recentScorePot;}\r\n\tint \t\t\t\t\t\t\tGetScorePotValue() {return m_scorePot * m_currentMult;}  // current pot value\r\n\tbool \t\t\t\t\t\t\tGetSpecialState() {return m_specialIsActive;}\r\n\tvoid \t\t\t\t\t\t\tForceSpecial( void );\t\r\n\r\n\tuint32\t\t\t\t\t\t\tGetLastTrickId(); // Added by Ken\r\n\tuint32\t\t\t\t\t\t\tGetTrickId( int trickIndex );\r\n\r\n\tvoid\t\t\t\t\t\t\tTrickTextPulse(int index); // Added by Ken so that replay can use it\r\n\tvoid\t\t\t\t\t\t\tTrickTextCountdown(int index); // Added by Ken so that replay can use it\r\n\tvoid\t\t\t\t\t\t\tTrickTextLanded(int index); // Added by Ken so that replay can use it\r\n\tvoid\t\t\t\t\t\t\tTrickTextBail(int index); // Added by Ken so that replay can use it\r\n\tvoid \t\t\t\t\t\t\tTrigger(char *trick_name, int base_score, Flags flags = 0);\r\n\tvoid \t\t\t\t\t\t\tSetSpin(int spin_degrees );\r\n\tvoid \t\t\t\t\t\t\tUpdateSpin(int spin_degrees );\r\n\tvoid \t\t\t\t\t\t\tTweakTrick(int tweak_value );\r\n\tvoid \t\t\t\t\t\t\tLand( void );\r\n\tvoid \t\t\t\t\t\t\tBail( bool clearScoreText = false );\r\n\r\n\tvoid \t\t\t\t\t\t\tReset();\r\n\r\n\tNet::Conn* \t\t\t\t\t\tGetAssociatedNetworkConnection( void );\r\n\tvoid \t\t\t\t\t\t\tLogTrickObject( int skater_id, int score, uint32 num_pending_tricks, uint32* p_pending_tricks, bool propagate );\r\n\tvoid \t\t\t\t\t\t\tLogTrickObjectRequest( int score );\r\n\r\n\tvoid \t\t\t\t\t\t\tSetBalanceMeter(bool state, float value = 0.0f);\r\n\tvoid \t\t\t\t\t\t\tSetManualMeter(bool state, float value = 0.0f);\r\n\tvoid\t\t\t\t\t\t\tRepositionMeters( void );\r\n\r\n\tint\t\t\t\t\t\t\t\tGetNumberOfNonGapTricks();\r\n\t\r\n\tbool\t\t\t\t\t\t\tIsLatestTrickByName( uint32 trick_text_checksum, int spin_mult, bool require_perfect, int num_taps );\r\n\tbool\t\t\t\t\t\t\tIsLatestTrick( uint32 key_combo, int spin_mult, bool require_perfect, int num_taps );\r\n\r\n    // counting occurrences of trick\r\n    int                             GetPreviousNumberOfOccurrencesByName( uint32 trickTextChecksum, int spin_degrees = 0, int num_taps = 1 );\r\n    int                             GetPreviousNumberOfOccurrences( uint32 trick_checksum, int spin_degrees = 0, int num_taps = 1 );\r\n//\tint\t\t\t\t\t\t\t\tGetPreviousNumberOfOccurrences( Script::CArray* pTricks );\r\n    \r\n    int                             GetCurrentNumberOfOccurrencesByName( uint32 trickTextChecksum, int spin_degrees = 0, bool require_perfect = false, int num_taps = 1 );\r\n    int                             GetCurrentNumberOfOccurrences( uint32 trick_checksum, int spin_degrees = 0, bool require_perfect = false, int num_taps = 1 );\r\n\tint                             GetCurrentNumberOfOccurrences( Script::CArray* pTricks, int start_trick_index = 0 );\r\n\r\n\tbool\t\t\t\t\t\t\tVerifyTrickMatch( int info_tab_index, uint32 trick_checksum, int spin_degrees = 0, bool require_perfect = false );\r\n\tint\t\t\t\t\t\t\t\tCountTrickMatches( uint32 trick_checksum, int spin_degrees = 0, bool require_perfect = false );\r\n    int\t\t\t\t\t\t\t\tCountStringMatches( const char* string );\r\n\r\n\tint\t\t\t\t\t\t\t\tGetCurrentTrickCount() { return m_currentTrick; }\r\n    int\t\t\t\t\t\t\t\tGetCurrentMult() { return m_currentMult; }\r\n\r\n\t// track the best and longest combos\r\n\tint\t\t\t\t\t\t\t\tGetLongestCombo() { return m_longestCombo; }\r\n\tint\t\t\t\t\t\t\t\tGetBestCombo() { return m_bestCombo; }\r\n\tvoid\t\t\t\t\t\t\tSetBestCombo( int best_combo ) { m_bestCombo = best_combo; }\r\n\tvoid\t\t\t\t\t\t\tResetComboRecords();\r\n    void \t\t\t\t\t\t\tsetSpecialBarColors();\r\n\r\n\tbool\t\t\t\t\t\t\tTrickIsGap( int trickIndex );\r\n\t\r\n\tstatic int\t\t\t\t\t\ts_handle_score_message ( Net::MsgHandlerContext* context );\r\n\r\n\tvoid\t\t\t\t\t\t\tUpdateRobotDetection(int node);\r\n\tfloat\t\t\t\t\t\t\tGetRobotMult();\r\n\tfloat\t\t\t\t\t\t\tGetRobotRailMult() {return m_robot_rail_mult;}\r\n\t\r\n\r\nprivate:\r\n\r\n\tvoid\t\t\t\t\t\t\treset_robot_detection();\r\n\tvoid\t\t\t\t\t\t\treset_robot_detection_combo();\r\n\r\n\tint\t\t\t\t\t\t\t\tget_packed_score( int start, int end );\r\n\tvoid\t\t\t\t\t\t\tpack_trick_info_table();\r\n\tvoid\t\t\t\t\t\t\tprint_trick_info_table();\r\n\tvoid \t\t\t\t\t\t\tcopy_trick_name_with_special_spaces(char *pOut, const char *pIn);\r\n\t\r\n    void \t\t\t\t\t\t\tcaptureScore();\r\n\tvoid \t\t\t\t\t\t\tresetScorePot();\r\n\tvoid\t\t\t\t\t\t\tdispatch_trick_sequence_to_screen(bool clear_text=false);\r\n\tint \t\t\t\t\t\t\tspinMult(int x);\r\n\tint \t\t\t\t\t\t\tdeprecMult(int x);\r\n\r\n\tvoid\t\t\t\t\t\t\tsetup_balance_meter_stuff();\r\n\tvoid\t\t\t\t\t\t\tposition_balance_meter(bool state, float value, bool isVertical);\r\n\r\n\tvoid\t\t\t\t\t\t\tdispatch_score_pot_value_to_screen(int score, int multiplier);\r\n\t\r\n\tvoid\t\t\t\t\t\t\tcheck_high_score(int old_score, int new_score);\r\n\t\r\n\tvoid\t\t\t\t\t\t\tset_special_is_active ( bool is_active );\r\n\t\r\n\tshort\t\t\t\t\t\t\tm_skaterId;\r\n\r\n\tenum EScorePotState\r\n\t{\r\n\t\tSHOW_ACTUAL_SCORE_POT,\r\n\t\tWAITING_TO_COUNT_SCORE_POT,\r\n\t\tSHOW_COUNTED_SCORE_POT,\r\n\t};\r\n\t\r\n\tint\t\t\t\t\t\t\t\tm_totalScore;\r\n\tEScorePotState\t\t\t\t\tm_scorePotState;\r\n\tint \t\t\t\t\t\t\tm_scorePot;\r\n\tint \t\t\t\t\t\t\tm_countedScorePot;\r\n\tint\t\t\t\t\t\t\t\tm_scorePotCountdown;\r\n\tint    \t\t\t\t\t\t\tm_recentScorePot;\r\n\tint    \t\t\t\t\t\t\tm_recentSpecialScorePot;\r\n\r\n\tint\t\t\t\t\t\t\t\tm_longestCombo;\r\n\tint\t\t\t\t\t\t\t\tm_bestCombo;\r\n\tint\t\t\t\t\t\t\t\tm_bestGameCombo;\r\n\r\n\t//HUD::TrickWindow*\t\t\t\tmp_trickWindow;\r\n\r\n\tstruct TrickHistory\r\n\t{\r\n\t\tuint32\t\t\t\t\t\tid;\r\n\t\t// there are 4 switch modes, so 4 entries\r\n\t\tint\t\t\t\t\t\t\ttotal_count[4]; \t// done during session \r\n\t\tint\t \t\t\t\t\t\tcombo_count[4];\t\t// done\tduring combo\r\n\t};\r\n\tLst::LookupTable<TrickHistory>\tm_historyTab;\r\n\t\r\n\tstruct TrickInfo\r\n\t{\r\n\t\tenum\r\n\t\t{\r\n\t\t\tTEXT_BUFFER_SIZE\t\t= 64,\r\n\t\t};\r\n\t\t\r\n\t\tint\t\t\t\t\t\t\tscore;\r\n\t\tint \t\t\t\t\t\tmult_index;\r\n\t\tint \t\t\t\t\t\tspin_mult_index;\r\n\t\tint\t\t\t\t\t\t\tspin_degrees;\r\n\t\tuint32\t\t\t\t\t\tid;\r\n\t\tuint32\t\t\t\t\t\tswitch_mode;\r\n\t\tFlags\t\t\t\t\t\tflags;\r\n\t\tchar\t\t\t\t\t\ttrickNameText[TEXT_BUFFER_SIZE];\r\n\t\tchar\t\t\t\t\t\ttrickTextFormatted[TEXT_BUFFER_SIZE];\r\n\t};\r\n\t// keeps track of tricks done in current sequence\r\n\tLst::DynamicTable<TrickInfo>\tm_infoTab;\r\n\tint\t\t\t\t\t\t\t\tm_currentTrick;\t // Tricks cap out at 250\r\n\tint\t\t\t\t\t\t\t\tm_currentMult;\t // but multiplier will keep going\r\n\t// Indicates most recent blocking trick\r\n\tint\t\t\t\t\t\t\t\tm_currentBlockingTrick;\r\n\t// Most recent spin trick. Must come after a blocking trick.\r\n\t// Can be a blocking trick itself, but will be treated differently\r\n\t// if so.\r\n\tint\t\t\t\t\t\t\t\tm_currentSpinTrick;\r\n\r\n\tint\t\t\t\t\t\t\t\tm_specialScore;\r\n\tbool\t\t\t\t\t\t\tm_specialIsActive;\r\n\r\n\tenum\r\n\t{\r\n\t\tREGULAR_SPECIAL\t=\t\t\t0,\r\n\t\tSPECIAL_SPECIAL\r\n\t};\r\n\tImage::RGBA\t\t\t\t\t\tm_special_rgba[3];\r\n\tfloat\t\t\t\t\t\t\tm_special_interpolator;\r\n\tfloat\t\t\t\t\t\t\tm_special_interpolator_rate;\r\n\r\n\tbool \t\t\t\t\t\t\tm_debug;\r\n\r\n\t// Balance meter stuff -- here for now\r\n\tint\t\t\t\t\t\t\t\tm_numArrowPositions;\r\n\tScript::CPair \t\t\t\t\tm_arrowPosTab[20];\r\n\tfloat\t\t\t\t\t\t\tm_arrowInterval;\r\n\tScript::CPair\t\t\t\t\tm_arrowPos;\r\n\tfloat\t\t\t\t\t\t\tm_arrowRot;\r\n\tScript::CPair\t\t\t\t\tm_meterPos[2];\r\n\t\r\n\tuint8\t\t\t\t\t\t\tm_robot_detection_count[MAX_ROBOT_NODES];\r\n\tuint8\t\t\t\t\t\t\tm_robot_detection_count_combo[MAX_ROBOT_NODES];\r\n\tint\t\t\t\t\t\t\t\tm_num_robot_landed;\r\n\tint\t\t\t\t\t\t\t\tm_num_robot_landed_combo;\r\n\tint\t\t\t\t\t\t\t\tm_num_robot_unique;\r\n\tint\t\t\t\t\t\t\t\tm_num_robot_first_combo;\r\n\tint\t\t\t\t\t\t\t\tm_num_robot_unique_combo;\r\n\tfloat\t\t\t\t\t\t\tm_robot_rail_mult;\r\n\t\r\n};\r\n\r\n\r\n\r\n} // namespace Mdl\r\n\r\n#endif\t// __MODULES_SKATE_SCORE_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/skate.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSkate Module (SKATE) \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmodules/skate.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t06/07/2000\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSkate Module\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// start autoduck documentation\r\n// @DOC skate\r\n// @module skate | None\r\n// @subindex Scripting Database\r\n// @index script | skate\r\n\r\n// define this to call the movie updatign from the Skate::Mdl update, instead of the fronend up[date\r\n#define\t__MOVIES_FROM_SKATE_UPDATE__\t\r\n\r\n                           \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/modules/skate/skate.h>\r\n\r\n#ifndef __PLAT_XBOX__\r\n#ifndef __PLAT_NGC__\r\n    #include <sifdev.h>\r\n#endif\r\n#endif\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <core/singleton.h>\r\n#include <core/task.h>\r\n\r\n#include <core/string/stringutils.h>\r\n\r\n#include <gfx/gfxman.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxmiscfx.h>\r\n#include <gfx/nxparticlemgr.h>\r\n\r\n#include <gfx/2D/ScreenElement2.h>\r\n#include <gfx/2D/ScreenElemMan.h>\r\n\r\n#include <gel/objman.h>\r\n#include <gel/module.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/components/suspendcomponent.h>\r\n#include <gel/components/vibrationcomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/trickcomponent.h>\r\n#include <gel/components/shadowcomponent.h>\r\n#include <gel/components/railmanagercomponent.h>\r\n#include <gel/music/music.h>\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/prefs/prefs.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/string.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n#include <sk/engine/sounds.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\n#include <sk/modules/FrontEnd/FrontEnd.h>\r\n#include <sk/modules/skate/gameflow.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/modules/skate/competition.h>\r\n#include <sk/modules/skate/horse.h>\r\n#include <sk/modules/Viewer/Viewer.h>\r\n\r\n#include <sk/objects/crown.h>\r\n#include <sk/objects/moviecam.h>\r\n#include <sk/objects/playerprofilemanager.h>\r\n#include <sk/objects/emitter.h>\r\n#include <sk/objects/proxim.h>\r\n#include <sk/objects/rail.h>\r\n#include <sk/objects/records.h>\r\n#include <sk/objects/restart.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/objects/skatertricks.h>\r\n#include <sk/objects/trickObject.h>\r\n\r\n#ifdef TESTING_GUNSLINGER\r\n#include <sk/objects/navigation.h>\r\n#endif\r\n\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skaterstatehistorycomponent.h>\r\n#include <sk/components/skaterendruncomponent.h>\r\n#include <sk/components/skaterbalancetrickcomponent.h>\r\n#include <sk/components/RailEditorComponent.h>\r\n\r\n#include <sk/parkEditor2/edmap.h>\r\n\r\n#include <sys/sys.h>\r\n#include <sys/mem/memman.h>\r\n#include <sys/timer.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/pre.h>\r\n#include <sys/config/config.h>\r\n#include <sys/replay/replay.h>\r\n\r\nextern bool\tskip_startup;\r\n\r\n\r\nnamespace Front\r\n{\r\n\textern void SetTimeTHPS4(int minutes, int seconds);\r\n    extern void HideTimeTHPS4();\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mdl\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefineSingletonClass( Skate, \"Skate Module\" );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Classes\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// When going into observer mode the local skater gets destroyed, and is later\r\n// restored from his profile. The created tricks are not stored in the profile,\r\n// so we are storing them out seperately.\r\nstatic Script::CStruct *spCATData=NULL;\r\nstatic Script::CStruct *spStatData=NULL;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tSkate::s_logic_code ( const Tsk::Task< Skate >& task )\r\n{\r\n\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n    \r\n    Dbg_AssertType ( &task, Tsk::Task< Skate > );\r\n\r\n\tSkate&\tmdl = task.GetData();\r\n\r\n\tmdl.DoUpdate();\r\n\r\n\tif( gamenet_man->OnServer() && ( mdl.GetNumSkaters() > 0 ))\r\n\t{\r\n\t\tmdl.CheckSkaterCollisions();\r\n\t}\r\n\r\n\tif ( mdl.GetGameMode()->IsFrontEnd() )\r\n\t{\r\n\t}\r\n\telse if( ( mdl.GetGameMode()->GetNameChecksum() == CRCD(0x6ef8fda0,\"netking\") ) ||\r\n\t\t\t ( mdl.GetGameMode()->GetNameChecksum() ==  CRCD(0x5d32129c,\"king\") ))\r\n\t{\r\n        if( !mdl.GetGameMode()->EndConditionsMet())\r\n\t\t{\r\n\t\t\tGameNet::PlayerInfo* king;\r\n\t\t\t\r\n\t\t\tking = gamenet_man->GetKingOfTheHill();\r\n\t\t\tif( king && !king->m_Skater->IsPaused())\r\n\t\t\t{\r\n\t\t\t\tMdl::Score* score;\r\n\t\t\t\tint current_score, total_score, goal_score;\r\n\t\r\n\t\t\t\tscore = king->m_Skater->GetScoreObject();\r\n\t\t\t\tcurrent_score = score->GetTotalScore();\r\n\t\t\t\ttotal_score = current_score + (int) (\t( Tmr::FrameLength() * 60.0f ) * \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t( Tmr::vRESOLUTION / 60.0f ));\r\n\t\t\t\tscore->SetTotalScore( total_score );\r\n\r\n\t\t\t\tgoal_score = mdl.GetGameMode()->GetTargetScore();\r\n\r\n\t\t\t\tif( mdl.GetGameMode()->IsTeamGame())\r\n\t\t\t\t{\r\n\t\t\t\t\ttotal_score = gamenet_man->GetTeamScore( king->m_Team );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\ttotal_score = score->GetTotalScore();\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// When within 10 seconds of victory, play a timer sound periodically\r\n\t\t\t\tmdl.BeepTimer( (float) ( goal_score - total_score) / 1000.0f,\r\n\t\t\t\t\t\t\t   10.0f,\r\n\t\t\t\t\t\t\t   10.0f,\r\n\t\t\t\t\t\t\t   \"timer_runout_beep\");\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tSkate::v_start_cb ( void )\r\n{\r\n\t// TODO:  Should assert that the top-down heap is empty\r\n\t// before the permanent prefiles are loaded\r\n//\tScript::RunScript( \"DumpHeaps\" );\r\n\t\r\n\t// these prefiles will sit on the top-down heap permanently\r\n\t// this is done before other stuff gets put on the top-down\r\n\t// heap\r\n\tScript::RunScript( \"load_permanent_prefiles\" );\r\n\r\n\tm_stat_override = 0.0f;\r\n\t   \r\n\tMlp::Manager * mlp_manager =  Mlp::Manager::Instance(); \r\n                           \r\n\tObj::Proxim_Init();\t\t\t\t\t\t//\r\n\tObj::CEmitterManager::sInit();\r\n\r\n\tm_logic_task->SetMask(1<<1);\r\n\t\t\t\t\t\t\t\t\t\t\t\t   \r\n    // Initialise logic and display tasks\r\n\tmlp_manager->AddLogicTask ( *m_logic_task );\r\n    \r\n\tGetGameMode()->Reset();\r\n\r\n    Script::RunScript(\"init_loading_bar\");\r\n    Script::RunScript(\"startup_loading_screen\");\r\n\r\n\t// By default we are both client and server\r\n\t//gamenet_manager->m_Flags.SetMask( GameNet::mSERVER | GameNet::mCLIENT );\r\n    \r\n\t// Run the script for loading sounds that are permanently loaded into sound RAM...\r\n    Script::RunScript(\"LoadPermSounds\");\r\n\r\n\t// Run the script for loading the skater animations\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t\r\n\tMem::PushMemProfile(\"Permanent Assets\");\r\n\tScript::RunScript( \"load_permanent_assets\" );\r\n\tMem::PopMemProfile(/*\"Permanent Assets\"*/);\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// initialize the pro skater profiles here\r\n\tGetPlayerProfileManager()->Init();\r\n\r\n\t// add the trick checksums used to the lookup table\r\n\tmp_trickChecksumTable->Init();\r\n\r\n\tScript::RunScript(\"default_system_startup\");\r\n\r\n\tif ( !Config::CD() )\r\n\t{\r\n\t\tif ( !skip_startup )\r\n\t\t{\r\n\t\t\t// Run the personal startup script.\r\n\t\t\tScript::RunScript(\"Call_Personal_StartUp_Script\");\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::v_stop_cb ( void )\r\n{\r\n    m_logic_task->Remove();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::HideSkater( Obj::CSkater* skater, bool should_hide )\r\n{\r\n\tif( should_hide )\r\n\t{\r\n\t\tskater->Pause();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tskater->UnPause();\r\n\t}\r\n\r\n\tskater->Hide( should_hide );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\tSkate::GetNextUnusedSkaterHeapIndex( bool for_local_skater )\r\n{\r\n\tint start_index, heap_index, num_tested;\r\n\tbool taken;\r\n\r\n\t// Ok... kinda complicated, but it was the simplest solution I could come up with that solves the problem.\r\n\t// The issue is that we only have vMAX_SKATERS skater heaps.  And we always want to reserve skater heap 0 \r\n\t// for our local skater.  But we might be observing a game that has vMAX_SKATERS, in which case you will\r\n\t// not have a heap for the local skater at all.  But if we observe a server that has ( vMAX_SKATERS - 1 )\r\n\t// skaters and join late, we want to make sure that our skater (the last one to be loaded) gets skater \r\n\t// heap 0\r\n\tstart_index = 1;\r\n\tif( for_local_skater )\r\n\t{\r\n\t\tstart_index = 0;\r\n\t}\r\n\r\n\theap_index = start_index;\r\n\tfor( num_tested = 0; num_tested < (int) GetGameMode()->GetMaximumNumberOfPlayers(); num_tested ++ )\r\n\t{\r\n\t\ttaken = false;\r\n\t\tfor( uint i = 0; i < GetNumSkaters(); i++ )\r\n\t\t{\r\n\t\t\tif( m_skaters.GetItem(i) != NULL )\r\n\t\t\t{\r\n\t\t\t\tObj::CSkater *pSkater = m_skaters.GetItem(i)->GetData();\r\n\t\t\t\tif( pSkater->GetHeapIndex() == heap_index )\r\n\t\t\t\t{\r\n\t\t\t\t\ttaken = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif( taken == false )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\theap_index = ( heap_index + 1 ) % GetGameMode()->GetMaximumNumberOfPlayers();\r\n\t}\r\n\t\r\n\t// We assume that these skater heaps are totally empty\r\n\t// so if something is aleft on them, then assert\r\n\r\n#ifdef\t__NOPT_ASSERT__\t\r\n\tMem::Heap *skater_heap = Mem::Manager::sHandle().SkaterHeap(heap_index);\r\n\tDbg_MsgAssert( skater_heap != NULL, ( \"Invalid skater heap : %d\\n\", heap_index ));\r\n\tif (skater_heap->mUsedBlocks.m_count)\r\n\t{\r\n\t\tprintf (\"Skater heap has %d used blocks still on it, it should be empty\\n\",skater_heap->mUsedBlocks.m_count);\r\n#ifndef __PLAT_NGC__\r\n\t\tMemView_AnalyzeHeap(skater_heap);\r\n\t\tMemView_DumpHeap(skater_heap);\r\n#endif\t\t// __PLAT_NGC__\r\n\t\tDbg_MsgAssert(0,(\"Skater heap has %d used blocks still on it, it should be empty\\n\",skater_heap->mUsedBlocks.m_count));\r\n\t}\r\n\r\n\tMem::Heap *geom_heap = Mem::Manager::sHandle().SkaterGeomHeap(heap_index);\r\n\tif (geom_heap->mUsedBlocks.m_count)\r\n\t{\r\n\t\tprintf (\"SkaterGeom heap has %d used blocks still on it, it should be empty\\n\",geom_heap->mUsedBlocks.m_count);\r\n#ifndef __PLAT_NGC__\r\n\t\tMemView_AnalyzeHeap(geom_heap);\r\n\t\tMemView_DumpHeap(geom_heap);\r\n#endif\t\t// __PLAT_NGC__\r\n\t\tDbg_MsgAssert(0,(\"SkaterGeom heap has %d used blocks still on it, it should be empty\\n\",geom_heap->mUsedBlocks.m_count));\r\n\t}\r\n\t\r\n\t#endif\r\n\t\r\n\r\n\treturn heap_index;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CSkater*\tSkate::add_skater ( Obj::CSkaterProfile* pSkaterProfile, bool local_client, int obj_id, int player_num )\r\n{\r\n\tLst::Node< Obj::CSkater > *node;\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tint heap_index;\r\n    \r\n\t// GJ:  copy the face texture (if it has one) from the local client's skater profile\r\n\t// we need to do this because the code that sends the face texture data as a separate\r\n\t// network message hasn't been implemented yet.\r\n\t//Dbg_MsgAssert( local_client, ( \"Gary's kludge for face textures only works on local client\" ) );\r\n\tif ( local_client )\r\n\t{\r\n\t\tGfx::CModelAppearance* pModelAppearance = pSkaterProfile->GetAppearance();\r\n\t\tObj::CSkaterProfile* pOriginalProfile;\r\n\t\tif (CFuncs::ScriptInSplitScreenGame( NULL, NULL ))\r\n\t\t{\r\n\t\t\t// (Mick) Kluge modified for 2 players\r\n\t\t\t// get the correct profile\r\n\t\t\tpOriginalProfile = mp_PlayerProfileManager->GetProfile( player_num );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Otherwise, use the old kluge\r\n\t\t\tpOriginalProfile = mp_PlayerProfileManager->GetProfile( 0 );\r\n\t\t}\r\n\t\t\r\n\t\t\r\n\t\tGfx::CModelAppearance* pOriginalAppearance = pOriginalProfile->GetAppearance();\r\n\r\n\t\t*pModelAppearance = *pOriginalAppearance;\r\n\t}\r\n\t\r\n\t// Change our ID to what the server says it should be to avoid ID collision amongs clients\r\n\tif( local_client )\r\n\t{\r\n\t\tObj::CSkater* skater;\r\n\r\n\t\tScript::RunScript( \"show_panel_stuff\" );\r\n\t\tskater = GetLocalSkater();\r\n\t\tif( skater )\r\n\t\t{   \r\n\t\t\t// In Split-screen games, we'll have two local skaters\r\n\t\t\tif( CFuncs::ScriptInSplitScreenGame( NULL, NULL ))\r\n\t\t\t{\r\n\t\t\t\tif( skater->GetID() == (uint32) obj_id )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn skater;\r\n\t\t\t\t}\r\n#ifdef __PLAT_NGC__\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tFile::PreMgr* pre_mgr = File::PreMgr::Instance();\r\n\t\t\t\t\tpre_mgr->LoadPre( \"skaterparts.pre\", false);\r\n\t\t\t\t}\r\n#endif\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// In Net games, we'll only have one, but his ID can change in order to avoid\r\n\t\t\t\t// ID collision over the net.  So, if someone is trying to add another local skater with a different\r\n\t\t\t\t// ID, assume that they just want to assign a new ID to our already-existing local skater\r\n\t\t\t\tif( skater->GetID() != (uint32) obj_id )\r\n\t\t\t\t{   \r\n\t\t\t\t\tScore* score;\r\n\t\r\n\t\t\t\t\tnode = skater->GetLinkNode();\r\n\t\t\t\t\tnode->SetPri( obj_id );\r\n\t\t\t\t\tnode->Remove();\r\n\t\t\t\t\tm_skaters.AddUniqueSequence( node );\r\n\t\r\n////////////////////////////////////////////////////////////////////////////////////\t\t\t\t\t\r\n// Changing the id means we have to destroy and re-create the particle systems\r\n// as they are referenced by the id of the skater.\t\t\t\t\t\r\n\t\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterHeap(skater->GetHeapIndex()));\r\n\t\t\t\t\tScript::RunScript( \"DestroySkaterParticles\", NULL, skater );\r\n\r\n\t\t\t\t\tskater->SetID( obj_id );\r\n\t\t\t\t\t\r\n\t\t\t\t\tScript::RunScript( \"InitSkaterParticles\", NULL, skater );\r\n\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n////////////////////////////////////////////////////////////////////////////////////\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\tscore = skater->GetScoreObject();\r\n\t\t\t\t\tscore->SetSkaterId( obj_id );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\treturn skater;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tObj::CCompositeObject* cam_obj;\r\n\r\n\t\t\t// If we're about to re-create the skater, delete the skatercam as it is about to\r\n\t\t\t// be re-created.  This is to handle the case where someone goes into observer mode.\r\n\t\t\t// In this case, we destroy the skater, but leave the camera. So now we're going back\r\n\t\t\t// to the front end and it's re-creating the skater.\r\n\t\t\tcam_obj = (Obj::CCompositeObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0x967c138c,\"skatercam0\"));\r\n\t\t\tif( cam_obj )\r\n\t\t\t{\r\n\t\t\t\tcam_obj->SetLockOff();\r\n\t\t\t\tdelete cam_obj;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Stop vibration when loading client skaters in net games\r\n\t\tif ( gamenet_man->InNetGame() )\r\n\t\t{\r\n\t\t\tObj::CSkater* p_skater;\r\n\r\n\t\t\tp_skater = GetLocalSkater();\r\n\t\t\tif( p_skater )\r\n\t\t\t{\r\n\t\t\t\tObj::CVibrationComponent* p_vibration_component = GetVibrationComponentFromObject(p_skater);\r\n\t\t\t\tif (p_vibration_component)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_vibration_component->StopAllVibration();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif ( gamenet_man->InNetGame() )\r\n\t{\r\n\t\tDbg_MsgAssert( GetNumSkaters() < GetGameMode()->GetMaximumNumberOfPlayers(),( \"Trying to add too many players %d : %d\", GetNumSkaters(), GetGameMode()->GetMaximumNumberOfPlayers()));\r\n\t}\r\n\r\n    Mem::PushMemProfile(\"Skater\"); // Could possibly replace this with the name of the skater, when we have one, so can compare in multi player\r\n\r\n\t\t\r\n\tDbg_MsgAssert(( obj_id >= 0 ) && ( obj_id < vMAX_SKATERS ),( \"Invalid skater object id\\n\" ));\r\n\t\r\n\theap_index = GetNextUnusedSkaterHeapIndex( local_client );\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterHeap(heap_index));\r\n\r\n\tObj::CSkater* skater;\r\n\r\n\tDbg_MsgAssert( pSkaterProfile,( \"No profile specified\" ));\r\n\r\n\t// Garrett: We may need to pause the music here if we get glitches on the network server\r\n\t//Pcm::PauseMusic(1);\r\n\r\n\tskater = new Obj::CSkater ( player_num, GetObjectManager(),\r\n\t\t\t\t\t\t\t\tlocal_client, obj_id, heap_index, !GetGameMode()->IsFrontEnd() );\r\n\t//Pcm::PauseMusic(0);\r\n\tskater->Init(pSkaterProfile);\r\n\r\n\t// Initialize the skater's special items\r\n\tif( !skater->IsLocalClient())\r\n\t{\r\n\t\tScript::RunScript( \"ClientSkaterInit\", NULL, skater );\r\n\t}\r\n\r\n    // This bit of code will order our skaters in the linked list according to their object id\r\n\t// so the order will be consistent across all clients\r\n\tnode = skater->GetLinkNode();\r\n\tnode->SetPri( skater->GetID() );\r\n\tm_skaters.AddUniqueSequence( node );\r\n\r\n\tif ( GetGameMode()->IsFrontEnd() )\r\n\t{\r\n\t\t// front end doesn't have a server, so we need\r\n\t\t// to treat it as a special case.\r\n\t\tskip_to_restart_point( skater );\r\n\t\tScript::RunScript(\"reset_skateshop_skater\");\r\n\t}\r\n\t\r\n    // check if we should bind this skater to a different controller\r\n\t// printf(\"skaterIndex = %i, player_num = %i\\n\", mp_controller_preferences[player_num].skaterIndex, player_num);\r\n\tUpdateSkaterInputHandlers();\r\n\r\n    // restore CAT's\r\n    if( skater->IsLocalClient() && ( skater->GetSkaterNumber() == 0 ))\r\n    {\r\n        if (spCATData)\r\n        {\r\n            printf(\"CAT: Restoring Created Tricks\\n\");\r\n            skater->LoadCATInfo(spCATData);\r\n            delete spCATData;\r\n    \t\tspCATData=NULL;\r\n        }\r\n        \r\n        // restore stat goal data too!\r\n        if (spStatData)\r\n        {\r\n            printf(\"CAT: Restoring Stat Goal data\\n\");\r\n            skater->LoadStatGoalInfo(spStatData);\r\n            delete spStatData;\r\n    \t\tspStatData=NULL;\r\n        }\r\n    }\r\n\r\n    // update trick mappings if this is the second skater in a split screen game\r\n\tif ( skater->GetID() == 0x00000001 && CFuncs::ScriptInSplitScreenGame( NULL, NULL ) )\r\n\t{\r\n\t\t// Obj::CPlayerProfileManager* pProfileMan = GetPlayerProfileManager();\r\n\t\t// Obj::CSkaterProfile* pProfile = pProfileMan->GetProfile( 1 );\r\n\t\t\r\n\t\tObj::CTrickComponent* p_trick_component = GetTrickComponentFromObject(skater);\r\n\t\tDbg_Assert(p_trick_component);\r\n\t\tp_trick_component->UpdateTrickMappings( pSkaterProfile );\r\n\t}\r\n\r\n\tMem::PopMemProfile(/*\"Skater\"*/);\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n    return skater;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::GetNextStartingPointData( Mth::Vector* pos, Mth::Matrix* matrix, int obj_id )\r\n{   \r\n    int node;\r\n\r\n\tpos->Set( 0.0f, 0.0f, 0.0f, 0.0f );\r\n\tmatrix->Ident();\r\n\r\n\tnode = find_restart_node( obj_id );\r\n\r\n    // ...and jump to it\r\n\tif (node != -1)\r\n\t{\r\n\t\tMth::Vector rot;\r\n\r\n\t\tprintf (\"Got restart node %d\\n\",node);\r\n\t\t\r\n\t\tSkateScript::GetAngles( node, &rot );\r\n\t\tif ( rot[ X ] || rot[ Y ] || rot[ Z ] )\r\n\t\t{\r\n\t\t\t// 3DSMAX_ANGLES Mick: 3/19/03 - Changed all rotation orders to X,Y,Z\r\n\t\t\tmatrix->RotateX( rot[ X ] );\r\n\t\t\tmatrix->RotateY( rot[ Y ] );\r\n\t\t\tmatrix->RotateZ( rot[ Z ] );\r\n\t\t}\r\n\r\n\t\tSkateScript::GetPosition( node, pos );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Find the zero-based restart node. So index 0 is Player1\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Skate::find_restart_node( int index )\r\n{\r\n\tint node = -1;\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\t// get appropriate restart point...\r\n\tif( IsMultiplayerGame())\r\n\t{\r\n\t\tif( GetGameMode()->IsTeamGame())\r\n\t\t{\r\n\t\t\tif( GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netlobby\" ))\r\n\t\t\t{\r\n\t\t\t\tnode = Obj::GetRestartNode( Script::GenerateCRC( \"team\" ), 0 );\r\n\t\t\t}\r\n\t\t\telse if( GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netctf\" ))\r\n\t\t\t{\r\n\t\t\t\tGameNet::PlayerInfo* player;\r\n\t\t\t\t\r\n\t\t\t\tplayer = gamenet_man->GetLocalPlayer();\r\n\t\t\t\tif( player )\r\n\t\t\t\t{\r\n\t\t\t\t\tswitch( player->m_Team )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcase GameNet::vTEAM_RED:\r\n\t\t\t\t\t\t\tnode = SkateScript::FindNamedNode( \"TRG_CTF_Restart_Red\" );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase GameNet::vTEAM_BLUE:\r\n\t\t\t\t\t\t\tnode = SkateScript::FindNamedNode( \"TRG_CTF_Restart_Blue\" );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase GameNet::vTEAM_GREEN:\r\n\t\t\t\t\t\t\tnode = SkateScript::FindNamedNode( \"TRG_CTF_Restart_Green\" );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase GameNet::vTEAM_YELLOW:\r\n\t\t\t\t\t\t\tnode = SkateScript::FindNamedNode( \"TRG_CTF_Restart_Yellow\" );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tindex = gamenet_man->GetSkaterStartingPoint( index );\r\n\t\t\t\tnode = Obj::GetRestartNode( Script::GenerateCRC( \"Multiplayer\" ), index );\r\n\t\t\t\t// if we did not find one, then try the first generic restart\r\n\t\t\t\tif (node == -1)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf (\"\\n\\nWARNING - no multiplayer restart point, trying player1\\n\\n\");\r\n\t\t\t\t\t// If no Playern, then try player1\r\n\t\t\t\t\tnode = Obj::GetRestartNode( Script::GenerateCRC( \"Player1\" ), 0 );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t// In the skateshop, use the Player1, Player2 restart points\r\n\t\telse if( GetGameMode()->IsFrontEnd())\r\n\t\t{\r\n\t\t\tchar buff[32];\r\n\r\n\t\t\tsprintf( buff, \"Player%d\", index + 1 );\r\n\t\t\tnode = Obj::GetRestartNode( Script::GenerateCRC( buff ), 0 );\r\n\t\t}\r\n\t\telse if ( GetGameMode()->IsTrue( \"is_horse\" ) )\r\n\t\t{\r\n\t\t\t// grab the current horse node\r\n\t\t\tnode = Obj::GetRestartNode( Script::GenerateCRC( \"horse\" ), GetHorse()->GetCurrentRestartIndex() );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tindex = gamenet_man->GetSkaterStartingPoint( index );\r\n\t\t\tnode = Obj::GetRestartNode( Script::GenerateCRC( \"Multiplayer\" ), index );\r\n\t\t\t// if we did not find one, then try the first generic restart\r\n\t\t\tif (node == -1)\r\n\t\t\t{\r\n\t\t\t\tprintf (\"\\n\\nWARNING - no multiplayer restart point, trying player1\\n\\n\");\r\n\t\t\t\t// If no Playern, then try player1\r\n\t\t\t\tnode = Obj::GetRestartNode( Script::GenerateCRC( \"Player1\" ), 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tnode = Obj::GetRestartNode( Script::GenerateCRC( \"Player1\" ), index );\r\n\t}\r\n\t\t\r\n\t// If No player 1, then use generic\r\n\tif (node == -1)\r\n\t{\t\t\r\n\t\tprintf (\"\\n\\nWARNING - no Player1 restart point, trying Generic\\n\\n\");\r\n\t\tnode = Obj::GetRestartNode( 0, 0 );\r\n\t}\r\n\r\n\t// If No player 1, then use generic\r\n\tif( node == -1 )\r\n\t{\r\n\t\tprintf( \"\\n\\nWARNING - No restart points found\\n\\n\" );\r\n\t}\r\n\r\n\treturn node;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::skip_to_restart_point( Obj::CSkater* skater, int node, bool walk )\r\n{\r\n\tif (node == -1)\r\n\t{\r\n\t\tnode = find_restart_node( skater->GetID() );\r\n\t}\r\n\r\n\t// ...and jump to it\r\n\tif (node != -1)\r\n\t{\r\n\t\tskater->SkipToRestart( node, walk );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::move_to_restart_point( Obj::CSkater* skater )\r\n{\r\n\tskip_to_restart_point(skater, -1);\r\n\t\r\n/*  Dan: MoveToRestart is deprecated.  We'll use skip instead.\r\n\tint node;\r\n\t\r\n\tnode = find_restart_node( skater->GetID() );\r\n    \r\n\tif (node != -1)\r\n\t{\r\n\t\tskater->MoveToRestart(node);   \t\t\t\t\t   \r\n\t}\r\n*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tSkate::remove_skater( Obj::CSkater* skater )\r\n{   \t\r\n\tDbg_Assert( skater );\r\n\r\n    // (Mick) Now check for bailboard, and kill it\r\n\t// Bit of a patch really, but a fairly safe high level one.\r\n\t// (need a more general solution for killing model that has\r\n\t// instances...)\r\n\t\r\n\tObj::CCompositeObject*p_bailboard = (Obj::CCompositeObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0x884ef81b, \"bailboard\") + skater->GetID());\r\n\tif( p_bailboard )\r\n\t{\r\n\t\tp_bailboard->MarkAsDead();\r\n\t\tObj::CCompositeObjectManager::Instance()->FlushDeadObjects();\r\n\t}\r\n\t\r\n\t// destroy any car the non-local skater might have\r\n\tif( !skater->IsLocalClient() )\r\n\t{\r\n\t\tScript::CStruct* p_params = new Script::CStruct;\r\n\t\tp_params->AddChecksum(CRCD(0x5b24faaa, \"SkaterId\"), skater->GetID());\r\n\t\tScript::RunScript(CRCD(0x5b3fdccb, \"remove_car_from_non_local_skater\"), p_params);\r\n\t\tdelete p_params;\r\n\t}\r\n\r\n    // save off CAT params\r\n    if( skater->IsLocalClient() && ( skater->GetSkaterNumber() == 0 ))\r\n    {\r\n        if (spCATData)\r\n    \t{\r\n    \t\tDbg_Assert( 0 );\r\n            delete spCATData;\r\n    \t\tspCATData=NULL;\r\n    \t}\r\n        \r\n        printf(\"CAT: Storing Created Trick data\\n\");\r\n        spCATData=new Script::CStruct;\r\n        skater->AddCATInfo(spCATData);\r\n\r\n        // save stat goal info too...\r\n        if (spStatData)\r\n    \t{\r\n    \t\tDbg_Assert( 0 );\r\n            delete spStatData;\r\n    \t\tspStatData=NULL;\r\n    \t}\r\n        \r\n        printf(\"CAT: Storing Stat Goal data\\n\");\r\n        spStatData=new Script::CStruct;\r\n        skater->AddStatGoalInfo(spStatData);\r\n    }\r\n    \r\n\tskater->GetLinkNode()->Remove();\r\n\t//Obj::Unlock( skater );\r\n\t//Obj::Destroy( skater );\r\n\tdelete skater;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Skate::SkatersAreIdle()\r\n{\r\n\t //GameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\r\n#ifdef __USER_GARY__\r\n\t// GJ:  this assert was firing off for some reason.\r\n\t// it doesn't seem to have any negative impact, but i'd\r\n\t// like to look at it later, when i've got more time\r\n//\tDbg_Assert( GetGameMode()->EndConditionsMet() );\r\n#endif\r\n\r\n\tbool all_idle = true;\r\n\r\n\tfor ( uint32 i = 0; i < GetNumSkaters(); i++ )\r\n\t{\r\n\t\tObj::CSkater* pSkater = GetSkater( i );\r\n\t\tDbg_Assert( pSkater );\r\n\r\n\t\tif ( GetGameMode()->IsTrue( \"is_horse\" ) )\r\n\t\t{\r\n\t\t\t// only need to check the current horse skater\r\n\t\t\tif ( GetHorse()->GetCurrentSkaterId() != (int) pSkater->GetID() )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tObj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(pSkater);\r\n\t\tDbg_Assert(p_skater_endrun_component);\r\n\t\tif ( !p_skater_endrun_component->RunHasEnded() )\r\n\t\t{\r\n\t\t\tall_idle = false;\r\n\t\t\tif( pSkater->IsLocalClient())\r\n\t\t\t{\r\n\t\t\t\tp_skater_endrun_component->EndRun();\r\n\t\t\t}                     \r\n\t\t}\r\n\t}\r\n\t\r\n\t// In network games, don't base it on whether skater objects are idle as this is unreliable.\r\n\t// Instead, base it on \"GameIsOver()\" which uses reliable transport messages\r\n\t/*if( gamenet_man->InNetGame())\r\n\t{\r\n\t\treturn gamenet_man->GameIsOver();\r\n\t}*/\r\n\r\n\treturn all_idle;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Skate::FirstTrickStarted()\r\n{\r\n\t// you should only call this function in horse mode\r\n\tDbg_Assert( GetGameMode()->IsTrue(\"is_horse\") );\r\n\t\r\n\tObj::CSkater* pSkater = GetSkaterById( GetHorse()->GetCurrentSkaterId() );\r\n\tDbg_Assert( pSkater );\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\tObj::CTrickComponent* pTrickComponent = GetTrickComponentFromObject(pSkater);\r\n\tDbg_Assert( pTrickComponent );\r\n\r\n\tif ( pTrickComponent->FirstTrickStarted() )\r\n\t{\r\n\t\t// if the trick has started, then end the run, yo!\r\n\t\tObj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(pSkater);\r\n\t\tDbg_Assert(p_skater_endrun_component);\r\n\t\tp_skater_endrun_component->EndRun();\r\n\t}\r\n\r\n\treturn pTrickComponent->FirstTrickStarted();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Skate::FirstTrickCompleted()\r\n{\r\n\t// you should only call this function in horse mode\r\n\tDbg_Assert( GetGameMode()->IsTrue(\"is_horse\") );\r\n\t\r\n\tObj::CSkater* pSkater = GetSkaterById( GetHorse()->GetCurrentSkaterId() );\r\n\tDbg_Assert( pSkater );\r\n\t\r\n\tObj::CTrickComponent* pTrickComponent = GetTrickComponentFromObject(pSkater);\r\n\tDbg_Assert( pTrickComponent );\r\n\t\r\n\treturn pTrickComponent->FirstTrickCompleted();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::PauseGameFlow( bool paused )\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr( mp_gameFlow );\r\n\tmp_gameFlow->Pause( paused );\t\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////\r\n// void Skate::BeepTimer(float time, float beep_time, float beep_speed, const char *p_script_name)\r\n// given a time, run a script if that time is less than beep_time, and again, with increasing\r\n// frequency.  Note use of static vars, means this is a single use fn.  Intetended for a single timer\r\n// time = time remaining in seconds\r\n// beep_time = time at which to start beeping\r\n// beep_speed = relative speed at whcih beeps increase 10.0 is good\r\n// p_script_name = script to run for each beep\r\n//\r\n// example:\r\n//\r\n//\t\t\tBeepTimer(time,10.0f, 10.0f,\"timer_runout_beep\");\t\t\t\r\n//\r\n\r\nvoid Skate::BeepTimer(float time, float beep_time, float beep_speed, const char *p_script_name)\r\n{\r\n\tstatic float next_beep_time;\r\n\tif (time > 0.01f && time <= beep_time)\r\n\t{\r\n\t\tif (time<next_beep_time)\r\n\t\t{\r\n\t\t\tScript::RunScript( p_script_name, NULL, NULL );\t\t\t\t\r\n\t\t\tfloat sub = next_beep_time/beep_speed;\r\n\t\t\tif  (sub<0.2f)\t\t\t\t// limit the delay between beeps \r\n\t\t\t{\r\n\t\t\t\tsub=0.2f;\r\n\t\t\t}\r\n\t\t\tnext_beep_time -= sub;\t\t\t// Make Urgent smaller, but less so as time remain, so frequency rises\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tnext_beep_time = beep_time;\r\n\t}\r\n}\t\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void \tdo_CheckModelActive(Obj::CObject *pOb, void *pVoidData)\r\n{\t\r\n\tObj::CCompositeObject* pCompositeObject = (Obj::CCompositeObject*)pOb;\r\n\tObj::CSuspendComponent* pSuspendComponent = GetSuspendComponentFromObject( pCompositeObject );\r\n\tif ( pSuspendComponent )\r\n\t{\r\n\t\tpSuspendComponent->CheckModelActive();\r\n\t}\r\n}\r\n \r\n\r\nvoid Skate::DoUpdate()\r\n{\r\n\r\n#ifdef\t__MOVIES_FROM_SKATE_UPDATE__\t\r\n\tif ( !Mdl::FrontEnd::Instance()->GamePaused() && !Mdl::CViewer::sGetViewMode() )\r\n\t{\r\n\t\tif ( mp_movieManager->IsRolling() )\r\n\t\t{\r\n\t\t\tif ( mp_movieManager->GetActiveCamera() )\r\n\t\t\t{\r\n\t\t\t\t// hardcoded to viewport 0...  if we need the other\r\n\t\t\t\t// viewports to play movies then we can store it\r\n\t\t\t\t// in the details...\r\n\t\t\t\tNx::CViewportManager::sSetCamera( 0, mp_movieManager->GetActiveCamera() );\r\n\t\t\t}\r\n\r\n\t\t\t// hides the loading screen, if any\r\n\t\t\tif ( m_lastFrameWasMovieCamera )\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( CRCD(0xc5c9373a,\"hide_loading_screen\") );\r\n\t\t\t}\r\n\t\t\tmp_movieManager->Update();\r\n\t\t\tm_lastFrameWasMovieCamera = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// the camera just finished\r\n\t\t\tif ( m_lastFrameWasMovieCamera )\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( CRCD(0x15674315,\"restore_skater_camera\") );\r\n\t\t\t\tm_lastFrameWasMovieCamera = false;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// play any extra object anims that might be playing\r\n\t\t// (this might be phased out later)\r\n\t\tif ( mp_objectAnimManager->IsRolling() )\r\n\t\t{\r\n\t\t\tmp_objectAnimManager->Update();\r\n\t\t}\r\n\t}\r\n#endif\r\n\t\r\n\t\r\n\t\r\n\t// Fills in a little structure with some stuff so that SkipLogic is really fast.\r\n\tpre_calculate_object_update_info();\r\n\t\r\n\t// called once per frame\r\n\tScript::RunScript( CRCD(0x1aef674f,\"Game_Update\") );\r\n\r\n\t// Mick: PATCH\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t// if the game is paused, then manually update the visibility of the game object\r\n\t// as we might be moving the camera around (Like in the view-goals screen)\r\n\tif ( Mdl::FrontEnd::Instance()->GamePaused())\r\n\t{\r\n\t\tGetObjectManager()->ProcessAllObjects(do_CheckModelActive);\r\n\t}\r\n\r\n// \r\n\r\n\t#if 1\r\n\t\r\n\t// Temp hack, for each viewport, run proxim-update on it, hooking it up to the appropiate camera\r\n\t\r\n\t// Perhaps a better solution would be to have a non-suspendable component\r\n\t// that is attached to the skater, and grabs the viewport/camera itself\r\n\t// But what about when the game is paused?\t\r\n\tif( GetLocalSkater())\r\n\t{\r\n\t\tint viewports = Nx::CViewportManager::sGetNumActiveViewports();\r\n\t\tswitch (viewports)\r\n\t\t{\r\n\t\t\tcase 1:\r\n\t\t\t\tif (Nx::CViewportManager::sGetActiveCamera(0))\r\n\t\t\t\t{\r\n\t\t\t\t\tProxim_Update(1<<0, GetLocalSkater(), Nx::CViewportManager::sGetActiveCamera(0)->GetPos());\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\t\t\tprintf (\"WARNING: 1 viewport, but no active camera 0\\n\");\r\n\t\t\t\t\t#endif\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\tif (Nx::CViewportManager::sGetCamera(0))\r\n\t\t\t\t{\r\n\t\t\t\t\tProxim_Update(1<<0, Obj::CCompositeObjectManager::Instance()->GetObjectByID(0), Nx::CViewportManager::sGetCamera(0)->GetPos());\r\n\t\t\t\t}\r\n\t\t\t\t// Need to check that the second skater exists, as well as the viewport\r\n\t\t\t\tif (Nx::CViewportManager::sGetCamera(1) && Obj::CCompositeObjectManager::Instance()->GetObjectByID(1))\r\n\t\t\t\t{\r\n\t\t\t\t\tProxim_Update(1<<1, Obj::CCompositeObjectManager::Instance()->GetObjectByID(1), Nx::CViewportManager::sGetCamera(1)->GetPos());\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(0,(\"Don't handle %d viewport proxim updating\",viewports));\r\n\t\t}\r\n\t}\r\n\telse if (CFuncs::ScriptIsObserving(NULL, NULL))\t\t// TT12029: Run without object in observer mode\r\n\t{\r\n\t\tint viewports = Nx::CViewportManager::sGetNumActiveViewports();\r\n\t\tswitch (viewports)\r\n\t\t{\r\n\t\t\tcase 1:\r\n\t\t\t\tif (Nx::CViewportManager::sGetActiveCamera(0))\r\n\t\t\t\t{\r\n\t\t\t\t\tObj::Proxim_Update(1<<0, NULL, Nx::CViewportManager::sGetActiveCamera(0)->GetPos());\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\t\t\tprintf (\"WARNING: 1 viewport, but no active camera 0\\n\");\r\n\t\t\t\t\t#endif\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(0,(\"Don't handle %d viewport proxim updating in observer mode\",viewports));\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t// printf (\"WARNING: No local skater, so no Proxim updates\\n\");\r\n\t\t#endif\r\n\t}\r\n\t#endif\t\r\n\r\n\r\n\r\n\r\n\t\r\n\tif ( m_levelChanged )\r\n\t{\r\n#ifdef __DEFERRED_CLEANUP_TEST__\r\n\t\tCFuncs::ScriptPrintMemInfo( NULL, NULL );\r\n#endif\r\n\t\tm_levelChanged = false;\r\n\t}\r\n\r\n\t// don't think i need this anymore\r\n\tif (GetGameMode()->IsFrontEnd())\r\n\t{\r\n\t\t// if the front end is active, then don't update\r\n\t\treturn;\r\n\t}\r\n\r\n\t// =================== TIMER STUFF ===========================\r\n\t// display the appropriate time if necessary\r\n\t// (we don't use or show a clock in certain game modes)\r\n\tGame::CGoalManager* pGoalManager = Game::GetGoalManager();\r\n\tif ( !Replay::RunningReplay() && pGoalManager->ShouldUseTimer() )\r\n\t{\r\n\t\tTmr::Time time_left = (pGoalManager->GetGoalTime() + 999) / 1000;\r\n\r\n\t\t// int time_left = m_time_limit - Tmr::InSeconds( front_end->GetGameTime());\r\n\r\n\t\tif( time_left < 1 )\r\n\t\t{\r\n\t\t\ttime_left = 0;\r\n\t\t}\r\n\r\n\t\tint seconds = time_left % 60;\r\n\t\tint minutes = time_left / 60;\r\n\t\t\r\n\t\tFront::SetTimeTHPS4(minutes, seconds);\r\n\t\t\r\n\t\t//m_panelMgr->SetTime(minutes, seconds);\r\n\t\t\r\n/*\t\tif (GetGameMode()->ShouldTimerBeep())\r\n\t\t{\r\n\t\t\t//float time = (float)m_time_limit - front_end->GetGameTime()/1000.0f;\r\n\t\t\tfloat time = float(time_left);\r\n\t\t\tBeepTimer(time,10.0f, 10.0f,\"timer_runout_beep\");\t\t\t\r\n\t\t}\r\n*/\r\n\t}\r\n\telse\r\n\t{\r\n\t\tFront::HideTimeTHPS4();\r\n\t}\r\n\r\n\t// make sure everyone's controller is still plugged in\r\n#ifdef __PLAT_XBOX__\r\n\tint is_changing_levels = Script::GetInteger( CRCD(0xe997db9f,\"is_changing_levels\"), Script::ASSERT );\r\n\tint check_controllers = Script::GetInteger( CRCD(0x77a5662c,\"check_for_unplugged_controllers\"), Script::ASSERT );\r\n\tif ( check_controllers && !is_changing_levels )\r\n\t{\r\n\t\tif ( m_first_input_received )\r\n\t\t{\r\n\t\t\tFront::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();\r\n\t\t\tFront::CScreenElement* p_root_window = p_screen_elem_man->GetElement( CRCD(0x56a1eae3,\"root_window\")  , Front::CScreenElementManager::DONT_ASSERT );\r\n\t\t\tif ( p_root_window )\r\n\t\t\t{\r\n\t\t\t\t// check that the box isn't already up\r\n\t\t\t\tFront::CScreenElement* p_error_box = p_screen_elem_man->GetElement( CRCD(0x2edb780f,\"controller_unplugged_dialog_anchor\") , Front::CScreenElementManager::DONT_ASSERT );\r\n\t\t\t\tif ( !p_error_box )\r\n\t\t\t\t{\r\n\t\t\t\t\tbool controller_unplugged = false;\r\n\t\t\t\t\tfor ( int i = 0; i < vMAX_SKATERS; i++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tObj::CSkater* pSkater = GetSkater( i );\r\n\t\t\t\t\t\tif ( pSkater && pSkater->IsLocalClient() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tInp::Handler< Obj::CInputComponent >* pHandler = pSkater->mp_input_component->GetInputHandler();\r\n\t\t\t\t\t\t\tif ( !pHandler->m_Device->IsPluggedIn() )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// m_controller_unplugged_frame_count++;\r\n\t\t\t\t\t\t\t\tcontroller_unplugged = true;\r\n\t\t\t\t\t\t\t\tif ( m_controller_unplugged_frame_count > Script::GetInteger( CRCD(0xf7fabb50,\"controller_unplugged_frame_count\"), Script::ASSERT ) )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tm_controller_unplugged_frame_count = 0;\r\n\t\t\t\t\t\t\t\t\tScript::CStruct* pScriptParams = new Script::CStruct();\r\n\t\t\t\t\t\t\t\t\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\t\t\t\t\t\t\t\t\tif ( gamenet_man->InNetGame() )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\tGame::CGoalManager* pGoalManager = Game::GetGoalManager();\r\n\t\t\t\t\t\t\t\t\t\tDbg_Assert( pGoalManager );\r\n\t\t\t\t\t\t\t\t\t\tpGoalManager->DeactivateAllGoals();\r\n\t\t\t\t\t\t\t\t\t\tpGoalManager->UninitializeAllGoals();\r\n\r\n\t\t\t\t\t\t\t\t\t\tpScriptParams->AddChecksum( NONAME, CRCD(0xeaa48e14,\"leaving_net_game\") );\r\n\t\t\t\t\t\t\t\t\t\tSkate::LeaveServer();\r\n\t\t\t\t\t\t\t\t\t\tif ( gamenet_man->OnClient() )\r\n\t\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t\tgamenet_man->CleanupPlayers();\r\n\t\t\t\t\t\t\t\t\t\t\tgamenet_man->ClientShutdown();\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\r\n\t\t\t\t\t\t\t\t\t// get the device that's unplugged\r\n\t\t\t\t\t\t\t\t\tint device_num = pHandler->m_Device->GetPort();\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\tpScriptParams->AddInteger( CRCD(0xc9428a08,\"device_num\"), device_num );\r\n\t\t\t\t\t\t\t\t\tScript::RunScript( CRCD(0xf77aca62,\"controller_unplugged\"), pScriptParams );\r\n\t\t\t\t\t\t\t\t\tdelete pScriptParams;\r\n\t\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( controller_unplugged )\r\n\t\t\t\t\t\tm_controller_unplugged_frame_count++;\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tm_controller_unplugged_frame_count = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::SetTimeLimit( int seconds )\r\n{\r\n\tm_time_limit = seconds;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetTimeLimit | sets the time limit\r\n// @parmopt int | seconds | 120 | number of seconds for time limit\r\nbool ScriptSetTimeLimit(Script::CStruct *pParams, Script::CScript *pScript) {\r\n    int seconds = 120;\r\n\r\n    pParams->GetInteger( \"seconds\", &seconds );\r\n\r\n    Skate* skate = Skate::Instance();\r\n\r\n    skate->SetTimeLimit( seconds );\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Skate::GetTimeLimit( void )\r\n{\r\n\treturn m_time_limit;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::UpdateGameFlow()\r\n{\r\n\tDbg_Assert( mp_movieManager );\r\n\r\n#ifndef\t__MOVIES_FROM_SKATE_UPDATE__\t\r\n\tif ( !Mdl::FrontEnd::Instance()->GamePaused() && !Mdl::CViewer::sGetViewMode() )\r\n\t{\r\n\t\tif ( mp_movieManager->IsRolling() )\r\n\t\t{\r\n\t\t\tif ( mp_movieManager->GetActiveCamera() )\r\n\t\t\t{\r\n\t\t\t\t// hardcoded to viewport 0...  if we need the other\r\n\t\t\t\t// viewports to play movies then we can store it\r\n\t\t\t\t// in the details...\r\n\t\t\t\tNx::CViewportManager::sSetCamera( 0, mp_movieManager->GetActiveCamera() );\r\n\t\t\t}\r\n\r\n\t\t\t// hides the loading screen, if any\r\n\t\t\tif ( m_lastFrameWasMovieCamera )\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( CRCD(0xc5c9373a,\"hide_loading_screen\") );\r\n\t\t\t}\r\n\t\t\tmp_movieManager->Update();\r\n\t\t\tm_lastFrameWasMovieCamera = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// the camera just finished\r\n\t\t\tif ( m_lastFrameWasMovieCamera )\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( CRCD(0x15674315,\"restore_skater_camera\") );\r\n\t\t\t\tm_lastFrameWasMovieCamera = false;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// play any extra object anims that might be playing\r\n\t\t// (this might be phased out later)\r\n\t\tif ( mp_objectAnimManager->IsRolling() )\r\n\t\t{\r\n\t\t\tmp_objectAnimManager->Update();\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tDbg_AssertPtr( mp_gameFlow );\r\n\tmp_gameFlow->Update();\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSkate::Skate ( void )\r\n{   \r\n\tm_first_input_received = false;\r\n\tm_controller_unplugged_frame_count = 0;\r\n\t\r\n\tm_logic_task = new Tsk::Task< Skate > ( Skate::s_logic_code, *this );\r\n\r\n\tnet_setup();\r\n\r\n\tmp_PlayerProfileManager = new Obj::CPlayerProfileManager;\r\n\tmp_PlayerProfileManager->Reset();\r\n\r\n\tmp_gameFlow = new CGameFlow;\r\n\tmp_goalManager = new Game::CGoalManager;\r\n\r\n//    mp_obj_manager = new Obj::CGeneralManager;\r\n\t// Bit of a patch, but the engine now needs to be told what is managing the moving objects\t\t\r\n\t// When Skate.cpp is broken up, then the mp_obj_manager needs extracting into some more generic \"game object\" manager\r\n\t// which Nx can query, if it really needs to\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tNx::CEngine::sSetMovableObjectManager(GetObjectManager());\r\n\r\n    mp_gameMode = new Game::CGameMode;\r\n\tmp_career = new Obj::CSkaterCareer;\t\t\t\t// new local careeer\r\n\t\r\n\tmp_railManager = new Obj::CRailManager;\r\n\r\n#\tifdef TESTING_GUNSLINGER\r\n\tmp_navManager = new Obj::CNavManager;\r\n#\tendif\r\n\t\r\n\tmp_trickChecksumTable = new Obj::CTrickChecksumTable;\r\n\r\n\tmp_trickObjectManager = new Obj::CTrickObjectManager;\r\n\tmp_trickObjectManager->DeleteAllTrickObjects();\r\n\r\n\tm_recording = false;\r\n\tm_playing = false;\r\n\tm_fd = 0;\r\n\r\n\tm_gameInProgress = false;\r\n\tm_levelLoaded = false;\r\n\tSetGameType( Script::GenerateCRC(\"freeskate\") );\r\n\r\n\t// initialize the splitscreen preferences\r\n    mp_splitscreen_preferences = new Prefs::Preferences;\r\n\tmp_splitscreen_preferences->Load( Script::GenerateCRC(\"default_splitscreen_preferences\" ) );\r\n\r\n\tmp_competition = new CCompetition;\r\n\tmp_horse = new CHorse;\r\n\tmp_movieManager = new Obj::CMovieManager;\r\n\tmp_objectAnimManager = new Obj::CMovieManager;\r\n\r\n\tmp_gameRecords = new Records::CGameRecords(Obj::CSkaterCareer::vMAX_CAREER_LEVELS);\r\n\r\n\tm_shadow_mode = Gfx::vSIMPLE_SHADOW;\r\n\t\r\n\t// Initialise the controller preferences.\r\n\t// These might get changed by an autoload off the memory card.\r\n\tfor (int i=0; i<vMAX_SKATERS; ++i)\r\n\t{\r\n\t\tm_device_server_map[i] = -1;\r\n\t\t\r\n\t\tmp_controller_preferences[i].skaterIndex = i;\r\n\t\tmp_controller_preferences[i].VibrationOn=true;\r\n\t\tSetAutoKick(i,true);\r\n\t\tSetSpinTaps(i,false);\r\n\t}\t\r\n\t// so that autolaunch works\r\n\tm_device_server_map[0] = 0;\r\n\r\n\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSkate::~Skate ( void )\r\n{   \r\n\tdelete mp_gameRecords;\r\n\tdelete mp_competition;\r\n\tdelete mp_horse;\r\n\tdelete mp_movieManager;\r\n\tdelete mp_objectAnimManager;\r\n\tdelete mp_railManager;\r\n\tdelete mp_career;\r\n//    delete mp_obj_manager;\r\n\r\n\tnet_shutdown();\r\n\r\n\tDbg_Assert( mp_gameFlow );\r\n\tdelete mp_gameFlow;\r\n\r\n\tDbg_Assert( mp_gameMode );\r\n    delete mp_gameMode;\r\n\r\n\tDbg_Assert( mp_goalManager );\r\n\tdelete mp_goalManager;\r\n\t\r\n\tDbg_Assert( mp_PlayerProfileManager );\r\n\tdelete mp_PlayerProfileManager;\r\n\r\n    delete m_logic_task;\r\n    delete mp_splitscreen_preferences;\r\n\r\n    delete mp_trickChecksumTable;\r\n    delete mp_trickObjectManager;\r\n} \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::SetSpinTaps(int index, bool state)\r\n{\r\n\tDbg_MsgAssert(index>=0 && index<vMAX_SKATERS,(\"Bad index\"));\r\n\tmp_controller_preferences[index].SpinTapsOn=state;\r\n\tObj::CSkater *p_skater = GetSkater(index);\r\n\tif (p_skater)\r\n\t{\r\n\t\tGetSkaterCorePhysicsComponentFromObject(p_skater)->m_spin_taps=state;\r\n\t}\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::SetAutoKick(int index, bool state)\r\n{\r\n\tDbg_MsgAssert(index>=0 && index<vMAX_SKATERS,(\"Bad index\"));\r\n\tmp_controller_preferences[index].AutoKickOn=state;\r\n\tObj::CSkater *p_skater = GetSkater(index);\r\n\tif (p_skater)\r\n\t{\r\n\t\tGetSkaterCorePhysicsComponentFromObject(p_skater)->m_auto_kick=state;\r\n\t}\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::SetVibration(int index, bool state)\r\n{\r\n\tDbg_MsgAssert(index>=0 && index<vMAX_SKATERS,(\"Bad index\"));\r\n\tmp_controller_preferences[index].VibrationOn=state;\r\n\tObj::CSkater *p_skater = GetSkater(index);\r\n\tif (p_skater)\r\n\t{\r\n\t\tObj::CVibrationComponent* p_vibration_component = GetVibrationComponentFromObject(p_skater);\r\n\t\tif (p_vibration_component)\r\n\t\t{\r\n\t\t\tp_vibration_component->SetActiveState(state);\r\n\t\t}\r\n\t}\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CSkater* \tSkate::GetLocalSkater( void )\r\n{\r\n\tunsigned int i;\r\n\r\n\tfor( i = 0; i < GetNumSkaters(); i++ )\r\n\t{\r\n\t\tif( m_skaters.GetItem(i) != NULL )\r\n\t\t{\r\n\t\t\tObj::CSkater *pSkater = m_skaters.GetItem(i)->GetData();\r\n\t\t\tif( pSkater->IsLocalClient())\r\n\t\t\t{\r\n\t\t\t\treturn pSkater;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CSkater \t*Skate::GetSkater( uint num )\r\n{\r\n\t\r\n\tif( GetNumSkaters() <= num )\r\n\t{\r\n\t\treturn NULL;\r\n\t}   \r\n\telse \r\n\t{\r\n\t\tDbg_Assert( m_skaters.GetItem( num ) );\r\n        return m_skaters.GetItem( num )->GetData();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CSkater *Skate::GetSkaterById( uint32 id )\r\n{\r\n\tfor (uint i = 0; i < GetNumSkaters(); i++)\r\n\t{\r\n\t\tif( m_skaters.GetItem(i) != NULL )\r\n\t\t{\r\n\t\t\tObj::CSkater *pSkater = m_skaters.GetItem(i)->GetData();\r\n\t\t\tif (pSkater->GetID() == id)\r\n\t\t\t\treturn pSkater;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CGeneralManager*\tSkate::GetObjectManager( void )\r\n{\r\n//\treturn mp_obj_manager;\r\n\treturn\tObj::CCompositeObjectManager::Instance();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CTrickObjectManager*\tSkate::GetTrickObjectManager( void )\r\n{\r\n\treturn mp_trickObjectManager;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CPlayerProfileManager*\tSkate::GetPlayerProfileManager( void )\r\n{\r\n\treturn mp_PlayerProfileManager;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPrefs::Preferences* Skate::GetSplitScreenPreferences( void )\r\n{\r\n\treturn mp_splitscreen_preferences;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat Skate::GetHandicap( int id )\r\n{\r\n\tPrefs::Preferences* pPreferences = GetSplitScreenPreferences();\r\n\r\n\tScript::CStruct* pStructure = NULL;\r\n\t\r\n\tswitch ( id )\r\n\t{\r\n\t\tcase 0:\r\n\t\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"player1_handicap\") );\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"player2_handicap\") );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Out of range handicap id %d\", id ) );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tDbg_Assert( pStructure );\r\n\r\n\tint val = 0;\r\n\tpStructure->GetInteger( \"time\", &val );\t// stored in the time field...  ugly!\r\n\treturn val;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// The Skate::Cleanup function is essentially cleaning up\r\n// the \"Session\" objects.\r\n// It does not unload any assets, just deletes objects that were valid for the session \r\n\r\nvoid\tSkate::Cleanup()\r\n{\r\n\tuint32 i;\r\n\r\n\tprintf(\"Skate::Cleanup() - Deleting all session specific objects\\n\");\r\n\r\n// Resetting the skater is complicated\r\n// in that we have to lock him, to make sure he is not deleted\r\n// and then reset him manually, as we can't just delete and re-create him (yet)\t\r\n\tfor (i=0;i<GetNumSkaters();i++)\r\n\t{\r\n\t\tObj::CSkater* skater;\r\n\t\tskater = GetSkater(i);\r\n\t\tif (skater)\r\n\t\t{\r\n\t\t\tskater->SetLockOn();\t\t\t\t\t// Sets the \"lock\" flag, so he won't get deleted by DestroyAllObjects\r\n\t\t\tif( skater->IsLocalClient())\r\n\t\t\t{\r\n\t\t\t\tskater->ResetPhysics(false, true);\r\n\t\t\t\t// stop any movies associated with each skater\r\n\t\t\t\tthis->GetMovieManager()->ClearMovieQueue();\r\n\t\t\t}\r\n\t\t\tskater->DeleteResources();\t   // blood, gap checkslistm shodow\r\n\t\t\t//skater->SwitchOffShadow();\r\n\t\t\tskater->RemoveFromCurrentWorld();\r\n\t\t}\r\n\t}\r\n\r\n// Clear the movies used for moving object anims\t\r\n\tGetMovieManager()->ClearMovieQueue();\r\n\tGetObjectAnimManager()->ClearMovieQueue();\r\n\r\n\t// clear out the viewer object, if any\r\n\tMdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();\r\n\tif ( pViewer )\r\n\t{\r\n\t\tpViewer->RemoveViewerObject();   \t\r\n\t}\r\n\r\n// Destroy all level objects.  Basically anything created with the node array\r\n\tGetObjectManager()->DestroyAllObjects();\r\n\tGetObjectManager()->FlushDeadObjects();\r\n\r\n// For now we destory all the composite objects here as well\r\n//\tObj::CCompositeObjectManager::Instance()->UnlockAllObjects();\r\n//\tObj::CCompositeObjectManager::Instance()->DestroyAllObjects();\r\n//\tObj::CCompositeObjectManager::Instance()->FlushDeadObjects();\r\n\r\n\r\n\t// Now remove the lock on the skaters' objects\r\n\tfor (i=0;i<GetNumSkaters();i++)\r\n\t{\r\n\t\tObj::CSkater* skater;\r\n\t\tskater = GetSkater(i);\r\n\t\tif (skater)\r\n\t\t{\r\n\t\t\tskater->SetLockOff();\t\t\t\t\t// Clears the \"lock\" flag\r\n\t\t\tskater->AddToCurrentWorld();\r\n\t\t}\r\n\t}\r\n\r\n\t// The gamenet managers objects (crown, compass... )\r\n\t// have now been destroyed so Nullify references to them\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tgamenet_man->CleanupObjects();\r\n\r\n\t// Little sanity check, to make sure everyhting except the skater is gone\t\r\n//\tsint pTypes[]={SKATE_TYPE_SKATER,-1};\r\n//\tGetObjectManager()->AssertIfObjectsRemainApartFrom(pTypes);\r\n\r\n\t// unlock the skaters, as they will be the only remaining objects\t\r\n\t//GetObjectManager()->UnlockAllObjects();\r\n\r\n\t// Delete any leftover spawned scripts.\r\n\t// (NB, might not want to do this, if the gameflow has spawned scripts?\r\n\t// but we probably do, as most of it will be session specific scripts\t\r\n\tScript::DeleteSpawnedScripts();\r\n\r\n\t// Delete all the trick objects that were created for this session\r\n\tmp_trickObjectManager->DeleteAllTrickObjects();\r\n\t\r\n\t// destroy the list of gapchecks (checklist of all gaps in the level)\r\n\t// (maybe we would keep this from session to session?)\r\n//\tm_gapcheck_list.DestroyAllNodes();\r\n\t\t\r\n\t// Destroy the new style particle systems....\r\n    // or not, as they are now all destroyed by the controlling objects, or the object manager\r\n    // so, if we did destroy them here, then the blood splat would stop working.\r\n\tNx::destroy_all_temp_particles( );\r\n\r\n\t// Destroy rails, they get re-created from the node array\r\n\tGetRailManager()->Cleanup();\r\n\t\r\n\t// Destroy Proximity nodes, similar to rails\t\r\n\tObj::Proxim_Cleanup();\r\n\r\n\t// Destroy EmitterObjects   \r\n\tObj::CEmitterManager::sCleanup();\r\n\r\n\t// cleanup particles\r\n\tDbg_Printf( \"Destroying particle systems...\" );\r\n\tNx::CEngine::sGetParticleManager()->Cleanup();\r\n\r\n\t// This is a debugging function to see what's\r\n\t// currently in the anim cache (at this point,\r\n\t// only a handful of skater anims should be\r\n\t// in the cache)\r\n//\tNx::PrintAnimCache();\r\n}\r\n\r\n\r\n// Cleaup stuff that might have been created in the park editor test play\r\nvoid Skate::CleanupForParkEditor()\r\n{\r\n\tmp_trickObjectManager->DeleteAllTrickObjects();\r\n\tNx::KillAllTextureSplats();\r\n\tNx::destroy_all_temp_particles( );\r\n\tGetRailManager()->Cleanup();\r\n\tObj::Proxim_Cleanup();\r\n\tObj::CEmitterManager::sCleanup();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::Pause( bool pause )\r\n{\r\n\t\r\n\tif ( pause )\r\n\t{\r\n\t\t Sfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\t\tsfx_manager->PauseSounds( );\r\n//\t\tPcm::PauseMusic( 1 );\r\n//\t\tPcm::PauseStream( 1 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// unpause music if game is active:\r\n\t\tif ( IsGameInProgress( ) )\r\n\t\t{\r\n//\t\t\tPcm::PauseMusic( 0 );\r\n//\t\t\tPcm::PauseStream( 0 );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::RequestGameEnd()\r\n{\r\n\tm_gameInProgress = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGame::CGameMode *Skate::GetGameMode(void)\r\n{\r\n\treturn mp_gameMode;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGame::CGoalManager* Skate::GetGoalManager(void)\r\n{\r\n\treturn mp_goalManager;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CSkaterProfile* Skate::GetCurrentProfile( Script::CStruct *pParams )\r\n{\r\n\tDbg_MsgAssert( mp_PlayerProfileManager,( \"No skater profile manager\\n\" ));\r\n\r\n\tint skaterNum;\r\n\tif ( pParams && pParams->GetInteger( \"skater\", &skaterNum ) )\r\n\t{\r\n\t\treturn mp_PlayerProfileManager->GetProfile( skaterNum );\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn mp_PlayerProfileManager->GetCurrentProfile();\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CSkaterProfile* Skate::GetProfile( int skaterNum )\r\n{\r\n\tDbg_MsgAssert( mp_PlayerProfileManager,( \"No skater profile manager\\n\" ));\r\n\r\n\treturn mp_PlayerProfileManager->GetProfile( skaterNum );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::SetGameType(uint32 gameType)\r\n{\r\n// Don't set this right away...\t\r\n//\tGetGameMode()->LoadGameType( gameType );\r\n\tm_requested_game_type = gameType;\r\n\t\t\t\t \r\n// Instead, remember it, and\r\n// commit the change when we do the \"setgamestate on\"\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::SetCurrentGameType()\r\n{\r\n    printf(\"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<Changing Game Mode\\n\");\r\n\tGetGameMode()->LoadGameType( m_requested_game_type );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::OpenLevel(uint32 level_script)\r\n{\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n//\tCloseLevel();\r\n\r\n\tMem::PushMemProfile(\"LaunchLevel\");\r\n\r\n\r\n\tif( gamenet_man->InNetGame())\r\n\t{\r\n\t\tif( gamenet_man->OnServer())\r\n\t\t{\r\n\t\t\tLst::Search< GameNet::PlayerInfo > sh;\r\n\t\t\tGameNet::PlayerInfo* player;\r\n\r\n\t\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t\t{\r\n\t\t\t\tplayer->MarkAsNotReady( 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\r\n\tif (level_script == Script::GenerateCRC(\"custom_park\"))\r\n\t{\r\n        ;\r\n\t}\r\n\telse\r\n\t{\r\n#ifdef\t__NOPT_ASSERT__\r\n\t\t// Make sure it exists, otherwise we crash obscurely...\r\n\t\tScript::CSymbolTableEntry *p_entry=Script::Resolve(level_script);\r\n\t\tDbg_MsgAssert(p_entry,(\"Level script %x (%s) not found\",level_script,Script::FindChecksumName(level_script)));\r\n#endif\r\n\t\t\r\n\t\tScript::RunScript(level_script);\r\n\t}\r\n\r\n\tm_levelLoaded = true;\r\n\tm_cur_level = level_script;\r\n\r\n\tif( gamenet_man->InNetGame())\r\n\t{\r\n\t\tint i;\r\n\t\tfor( i = 0; i < GameNet::vMAX_LOCAL_CLIENTS; i++ )\r\n\t\t{\r\n\t\t\tLst::Search< Net::Conn > sh;\r\n\t\t\tNet::Conn* server_conn;\r\n\t\t\tNet::Client* client;\r\n\t\r\n\t\t\tclient = gamenet_man->GetClient( i );\r\n\t\t\tif( client )\r\n\t\t\t{\r\n\t\t\t\tserver_conn = client->FirstConnection( &sh );\r\n\t\t\t\tif( server_conn )\r\n\t\t\t\t{\r\n\t\t\t\t\tserver_conn->UpdateCommTime( Tmr::Seconds( 12 ));\t// update the current comm time so it doesn't time out after\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// loading the skater\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( gamenet_man->OnServer())\r\n\t\t{\r\n\t\t\tLst::Search< Net::Conn > sh;\r\n\t\t\tNet::Conn* conn;\r\n\t\t\tNet::Server* server;\r\n\r\n\t\t\tserver = gamenet_man->GetServer();\r\n\t\t\tif( server )\r\n\t\t\t{\r\n\t\t\t\tfor( conn = server->FirstConnection( &sh ); conn; \r\n\t\t\t\t\t\tconn = server->NextConnection( &sh ))\r\n\t\t\t\t{\r\n\t\t\t\t\tconn->UpdateCommTime( Tmr::Seconds( 8 ));\t// update the current comm time so it doesn't time out after\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// loading the skater\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// If we have some queued up new players, we'll respond to the ready query\r\n\t\t\t// after we finish loading them. Otherwise, if this is just a standard change level\r\n\t\t\t// call, tell the server we're finished loading it and ready to communicate\r\n\t\t\tLst::Search< GameNet::NewPlayerInfo > sh;\r\n\r\n\t\t\tif( gamenet_man->FirstNewPlayerInfo( sh ) == NULL )\r\n\t\t\t{\r\n\t\t\t\tgamenet_man->RespondToReadyQuery();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tMem::PopMemProfile(/*\"LaunchLevel\"*/);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// RestartLevel is just intended to be called when a level is restarted\r\n// it does not actually restart the level, it just sets a few flags\r\n// and does something with disabling the the viewer log that's only related to screenshot mode \r\n\r\nvoid Skate::RestartLevel()\r\n{\r\n\t// clear the end run flag\r\n\tClearEndRun();\r\n\t\r\n\t// GJ:  in a network lobby, the skater is loaded AFTER the\r\n\t// level so this return wouldn't work...  come to think\r\n\t// of it, what's it needed for?\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tif ( !GetNumSkaters() && !gamenet_man->InNetGame() )\r\n\t{\r\n\t\tRyan(\"BAD BAD BAD\\n\");\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!m_levelLoaded)\r\n\t{\r\n\t\tRyan(\"BAD BAD BAD\\n\");\r\n\t\treturn;\r\n\t}\r\n\r\n\t// the game is now on\r\n\tif ( GetGameMode()->IsFrontEnd() )\r\n\t{\r\n\t\t// don't let the career timer go until\r\n\t\t// we're actually in a real level,\r\n\t\t// otherwise, we'll get \"Requested MenuScreen\r\n\t\t// not active\" asserts\r\n\t\tm_gameInProgress = false;\r\n\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_gameInProgress = true;\r\n\r\n//\t\t Mdl::RwViewer * rwviewer_mod =  Mdl::RwViewer::Instance();\r\n//\t\trwviewer_mod->DisableMainLogic( false );\t\t// reset\r\n\t}\r\n\r\n\tif ( gamenet_man->InNetGame() )\r\n\t{\r\n\t\t#if 0\r\n\t\t// unpause the game if we're in the network lobby\r\n\t\tMdl::FrontEnd* frontend = Mdl::FrontEnd::Instance();\r\n\t\tfrontend->SetActive(false);\r\n\t\t#endif\r\n\t}\r\n\r\n\t// Mick:  tell the career mode that we are just starting this level\r\n\t// so it will remember what the flags were at the start of the level\t\r\n\tGetCareer()->StartLevel();\r\n\t\r\n\t// print debug info\r\n\tGetTrickObjectManager()->PrintContents();\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::ChangeLevel( uint32 level_id )\r\n{\r\n\t //GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\t// changes level while preserving the skaters\r\n\r\n// Mick - moved this in ScriptCleanup\r\n//    Game::CGoalManager* p_GoalManager = Game::GetGoalManager();\r\n//    Dbg_MsgAssert( p_GoalManager, ( \"couldn't get GoalManager\\n\" ) );\r\n//    p_GoalManager->LevelUnload();\r\n//    p_GoalManager->DeactivateAllGoals();\r\n//    p_GoalManager->RemoveAllGoals();\r\n\r\n\tprintf (\"-----------------------------------------Skate::ChangeLevel(%d)\\n\",level_id);\r\n\r\n\t//uint32 i;\r\n\tScript::CStruct* pTempStructure;\r\n\r\n\t// TODO:  is this necessary?   since we push individual heaps below\r\n\t// maybe, if there is anyhting else that might allocate stuff \r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\t// requests the new level...\r\n\tpTempStructure = new Script::CStruct;\r\n\tpTempStructure->Clear();\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"level\"), ESYMBOLTYPE_NAME, (int)level_id );\r\n\tScript::RunScript( \"request_level\", pTempStructure );\r\n\tdelete pTempStructure;\r\n\r\n\tm_prev_level = m_cur_level;\r\n\tm_cur_level=level_id;\r\n\t\r\n\t// removes the skaters from the existing world\r\n\t// (skate::cleanup func used to take care of this\r\n\t// but now it's in ScriptCleanup\r\n\t/*if( !gamenet_man->InNetGame())\r\n\t{\r\n\t\tfor ( i = 0; i < GetNumSkaters(); i++ )\r\n\t\t{\r\n\t\t\tObj::CSkater* pSkater = GetSkater( i );\r\n\t\t\tpSkater->RemoveFromCurrentWorld();\r\n\t\t}\r\n\t}*/\r\n\r\n\t\r\n\t// cleans up everything but the skaters\r\n\tpTempStructure = new Script::CStruct;\r\n\tpTempStructure->Clear();\r\n\t// If we're going back to the skateshop, clean up any extra skater heaps we may have allocated\r\n\tif( level_id != Script::GenerateCRC( \"load_skateshop\" ))\r\n\t{\r\n\t\tpTempStructure->AddComponent( NONAME, ESYMBOLTYPE_NAME, (int)Script::GenerateCRC(\"preserve_skaters\") );\r\n\t}\r\n\tCFuncs::ScriptCleanup( pTempStructure, NULL );\r\n\tdelete pTempStructure;\r\n\t\r\n\tm_levelChanged = true;\r\n\t\r\n\t//if( gamenet_man->InNetGame())\r\n\t//{\r\n\t\t//Script::RunScript( \"create_score_menu\" );\r\n\t//}\r\n\r\n\t// restarts the gameflow\r\n\tDbg_AssertPtr( mp_gameFlow );\r\n\tmp_gameFlow->Reset( Script::GenerateCRC( \"ChangeLevelGameFlow\" ) );\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n\r\nvoid Skate::ResetLevel()\r\n{\r\n\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\r\n\t// Cleanup existing level specific stuff\r\n\tCleanup();\r\n\r\n\t// Re-trigger all the objects in the level\t\t\t\t\t\t\t\t\t\t  \r\n\tCFuncs::ScriptParseNodeArray(NULL,NULL);\r\n\t\r\n\t// clear the end run flag\r\n\tClearEndRun();\r\n\r\n\t// now that the trick object database is set,\r\n\t// we can apply any graffiti state queued up in the trick\r\n\t// object manager\r\n\tGetTrickObjectManager()->ApplyObserverGraffitiState();\r\n\r\n\tGame::CGoalManager* pGoalManager = Game::GetGoalManager();\r\n\tif( gamenet_man->InNetGame())\r\n\t{                                                         \r\n\t\tpGoalManager->InitializeAllMinigames();\r\n\t\tpGoalManager->UnBeatAllGoals();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpGoalManager->InitializeAllGoals();\r\n\t}\r\n\r\n\tpGoalManager->CreateGoalLevelObjects();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nvoid Skate::ResetSkaters(int node, bool walk)\r\n{\r\n    // Skip skaters to restart points (will also reset their physics states)\r\n    for (uint32 i=0;i<GetNumSkaters();i++)\r\n    {\r\n        Obj::CSkater* pSkater = GetSkater( i );\r\n        Dbg_MsgAssert ( pSkater,( \"No skater\" ));\r\n        if ( pSkater->IsLocalClient() )\r\n        {\r\n             skip_to_restart_point( pSkater, node, walk );\t\t\t\r\n        }\r\n\r\n        // We Resync() the skater here, as he has just restarted\r\n        // he also moves on the client\r\n        // however, the client does not know he has to restart yet\r\n        // so will still be sending old positions\r\n        // we need to tell the clients all the restart\r\n        // and then not take any positions from them until they acknowledge \r\n        // that they have carried out this restart\r\n        // This would involved calling Resync each frame until they acknowledge having restarted\r\n        // or we could just resync every frame for a period of time\r\n        // however, that seems rather dodgy, as you have no way of knowing\r\n        // how long you should resync for \r\n\t\tpSkater->Resync();\r\n\r\n        // So... how do we do that then Steve?\r\n\r\n    }\r\n    ClearEndRun();\r\n}\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::LaunchGame()\r\n{\r\n\t Mdl::FrontEnd * front =  Mdl::FrontEnd::Instance();\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tfront->PauseGame(false);\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\r\n\tprintf (\"\\nLAUNCH GAME CALLED with %d skaters \\n\\n\",GetNumSkaters());\t\t\t   \r\n\t\t\t   \r\n\t//if (!GetNumSkaters())\r\n\tif( !gamenet_man->GetLocalPlayer())\r\n\t{\r\n\t\tDbg_Printf( \"*** NO LOCAL PLAYER\\n\" );\r\n\t\t// If we are starting a game with possibly more than two players\r\n\t\t// then we want to allocate \t\r\n\t\tDbg_Printf( \"*** Max players: %d\\n\", GetGameMode()->GetMaximumNumberOfPlayers());\r\n\t\tif (GetGameMode()->GetMaximumNumberOfPlayers() > NUM_PERM_SKATER_HEAPS)\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().InitSkaterHeaps(GetGameMode()->GetMaximumNumberOfPlayers());\r\n\t\t}\r\n\t\r\n\t\t// start the game flow\r\n\t\tDbg_AssertPtr( mp_gameFlow );\r\n\t\tmp_gameFlow->Reset( Script::GenerateCRC( \"InitializeGameFlow\" ) );\r\n\t\tmp_gameFlow->Update();\r\n\t\tprintf( \"\\nLeaving Update\\n\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Reset everything in the level to its initial state\r\n\t\tResetLevel();\r\n\r\n\t\t// GJ:  we are intentionally not rerunning the intro script here\r\n\t\tm_gameInProgress = true;\r\n\r\n\t\t// start the game flow\r\n\t\tDbg_AssertPtr( mp_gameFlow );\r\n\t\tmp_gameFlow->Reset( Script::GenerateCRC( \"StandardGameFlow\" ) );\r\n\t\tprintf(\"Restarting game flow\\n\");\r\n\t}\r\n\r\n\t// Clear the king of the hill\r\n\tGameNet::PlayerInfo* player;\r\n\tLst::Search< GameNet::PlayerInfo > sh;\r\n\tif(( player = gamenet_man->GetKingOfTheHill()))\r\n\t{\r\n\t\tplayer->MarkAsKing( false );\r\n\t}\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tplayer->ClearCTFState();\r\n\t}\r\n\r\n\tif( GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netlobby\" ))\r\n\t{\r\n\t\tgamenet_man->CreateTeamFlags( GetGameMode()->NumTeams());\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::CheckSkaterCollisions( void )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tObj::CSkater* subject;\r\n\tint i;\r\n\t\r\n\tif( gamenet_man->GameIsOver())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Only perform the collision logic if player collision is enabled\r\n\tif( ( gamenet_man->PlayerCollisionEnabled() == false ) &&\r\n\t\t( GetGameMode()->GetNameChecksum() != CRCD(0xbff33600,\"netfirefight\")) &&\r\n\t\t( GetGameMode()->GetNameChecksum() != CRCD(0x3d6d444f,\"firefight\")) &&\r\n\t\t( GetGameMode()->GetNameChecksum() != CRCD( 0x6ef8fda0, \"netking\" )) &&\r\n\t\t( GetGameMode()->GetNameChecksum() != CRCD( 0x5d32129c, \"king\" )) &&\r\n\t\t( GetGameMode()->GetNameChecksum() != CRCD( 0x6c5ff266, \"netctf\" )))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Loop through all other skaters and check for collisions\r\n\tfor( i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tsubject = GetSkater( i );\r\n\t\tif(\tsubject == NULL )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tsubject->mp_skater_state_history_component->CollideWithOtherSkaters( 0 );\r\n\t}\r\n\r\n\t// If we're in king of the hill mode and the crown is on the ground\r\n\t// perform collision checks to see if someone snags it\r\n\tif(\t( GetGameMode()->GetNameChecksum() == CRCD( 0x6ef8fda0, \"netking\" )) ||\r\n\t\t( GetGameMode()->GetNameChecksum() == CRCD( 0x5d32129c, \"king\" )))\r\n\t{   \r\n\t\tObj::CCrown* crown;\r\n\r\n\t\tcrown = gamenet_man->GetCrown();\r\n\t\tif( crown && !crown->OnKing())\r\n\t\t{\r\n\t\t\tfor( i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )\r\n\t\t\t{\r\n\t\t\t\tsubject = GetSkater( i );\r\n\t\t\t\tif(\tsubject == NULL )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif( subject->mp_skater_state_history_component->CheckForCrownCollision())\r\n\t\t\t\t{\r\n\t\t\t\t\tGameNet::PlayerInfo* player;\r\n\t\t\t\t\tLst::Search< GameNet::PlayerInfo > sh;\r\n\t\t\r\n\t\t\t\t\tplayer = gamenet_man->GetPlayerByObjectID( subject->GetID() );\r\n\t\t\t\t\tDbg_Assert( player );\r\n\r\n\t\t\t\t\t// It is important that we mark the king immediately (rather than through a\r\n\t\t\t\t\t// network message) since we do logic based on the \"current\" king\r\n\t\t\t\t\tplayer->MarkAsKing( true );\r\n\t\t\t\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player;\r\n\t\t\t\t\t\t\tplayer = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Already marked the king for the local player (above)\r\n\t\t\t\t\t\tif( player->IsLocalPlayer())\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tGameNet::MsgByteInfo msg;\r\n\t\t\t\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\t\t\t\tNet::Server* server;\r\n\r\n\t\t\t\t\t\tserver = gamenet_man->GetServer();\r\n\t\t\t\t\t\tDbg_Assert( server );\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tmsg.m_Data = subject->GetID();\r\n\r\n\t\t\t\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgByteInfo );\r\n\t\t\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_NEW_KING;\r\n\t\t\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\t\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\t   \r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::ObserveNextSkater( void )\r\n{\r\n\tGameNet::PlayerInfo* player;\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n    player = gamenet_man->GetNextPlayerToObserve();\r\n\tgamenet_man->ObservePlayer( player );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char* Skate::GetSkaterDisplayName( int id )\r\n{\t\r\n\tfor ( uint32 j = 0; j < GetNumSkaters(); j++ )\r\n\t{\r\n\t\tif ( (int) GetSkater(j)->GetID() == id )\r\n\t\t{\r\n\t\t\treturn GetSkater(j)->GetDisplayName();\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Skate::ShouldBeAbsentNode( Script::CStruct* pNode )\r\n{\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tDbg_Assert( pNode );\r\n\t\r\n\treturn ( pNode->ContainsFlag( 0x68910ac6 /*\"AbsentInNetGames\"*/ ) && \r\n\t\t\t ( IsMultiplayerGame() || gamenet_man->InNetMode()));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Skate::IsMultiplayerGame( void )\r\n{\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\treturn ( gamenet_man->InNetGame() || GetGameMode()->GetInitialNumberOfPlayers() > 1 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tSkate::SetShadowMode( Gfx::EShadowType shadowMode )\r\n{\r\n\tObj::CSkater* skater;\r\n\tLst::Search< Obj::CSkater > sh;\r\n\r\n\tm_shadow_mode = shadowMode;\r\n\r\n\tfor( skater = sh.FirstItem( m_skaters ); skater; skater = sh.NextItem())\r\n\t{\r\n\t\tObj::CShadowComponent* p_shadow_component = GetShadowComponentFromObject(skater);\r\n\t\tDbg_Assert(p_shadow_component);\r\n\t\tp_shadow_component->SwitchOnSkaterShadow();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGfx::EShadowType Skate::GetShadowMode( void ) const\r\n{\r\n\treturn m_shadow_mode;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetGameType | Sets the type of game to be played. Examples: <nl>\r\n// SetGameType FreeSkate <nl>\r\n// SetGameType SingleSession\r\n// @uparm name | Game type\r\nbool ScriptSetGameType(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tSkate* skate = Skate::Instance();\r\n\tuint32 game_type;\r\n\tpParams->GetChecksum(NONAME, &game_type, true);\r\n\tskate->SetGameType(game_type);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | TestGameType | Tests if current game type is equal to the \r\n// game type specified as the first parameter\r\n// @uparm name | Game type\r\nbool ScriptTestGameType(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 game_type;\r\n\tpParams->GetChecksum(NONAME, &game_type, true);\r\n\t\r\n\tSkate* skate = Skate::Instance();\r\n\treturn (game_type == skate->GetGameMode()->GetNameChecksum());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptInTeamGame(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tSkate* skate = Skate::Instance();\r\n\r\n\treturn skate->GetGameMode()->IsTeamGame();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | TestRequestedGameType |\r\n// This is so that I can tell what the last value sent to SetGameType\r\n// was, since SetGameType will not set the game type straight away,\r\n// so TestGameType will not work.\r\n// @uparm name | Game type\r\nbool ScriptTestRequestedGameType(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 game_type;\r\n\tpParams->GetChecksum(NONAME, &game_type, true);\r\n\t\r\n\tSkate* skate = Skate::Instance();\r\n\treturn (game_type == skate->GetGameType());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ChangeLevel | \r\n// @parm string | level | The level to change to\r\nbool ScriptChangeLevel(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tbool show_warning;\r\n\tuint32 level;\r\n\r\n\tpParams->GetChecksum(Script::GenerateCRC(\"level\"), &level, true);\r\n\tif( level == Script::GenerateCRC(\"use_preferences\") )\r\n\t{\r\n\t\tlevel = gamenet_man->GetLevelFromPreferences();\r\n\t}\r\n\t\t\r\n\tgamenet_man->SetLevel( level );\r\n\tshow_warning = pParams->ContainsComponentNamed( \"show_warning\" );\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tprintf(\"Send message to ChangeLevel level=%s here!\\n\", Script::FindChecksumName(level) );\r\n#endif\r\n\r\n\tPcm::StopMusic();\r\n\t\r\n\tNet::Server* server;\r\n\tGameNet::MsgChangeLevel msg;\r\n\tGameNet::PlayerInfo* player;\r\n\tLst::Search< GameNet::PlayerInfo > sh;\r\n\r\n\tserver = gamenet_man->GetServer();\r\n\tDbg_Assert( server );\r\n\r\n\tmsg.m_Level = level;\r\n\tmsg.m_ShowWarning = (char) show_warning;\r\n\t\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; \r\n\t\t\tplayer = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tGameNet::MsgReady ready_msg;\r\n\t\tNet::MsgDesc msg_desc;\r\n\t\t\r\n\t\tready_msg.m_Time = Tmr::GetTime();\r\n\r\n\t\tif( player->IsLocalPlayer() == false )\r\n\t\t{\r\n\t\t\tif( level == CRCD(0xb664035d,\"Load_Sk5Ed_gameplay\"))\r\n\t\t\t{\r\n\t\t\t\tserver->StreamMessage( player->GetConnHandle(), GameNet::MSG_ID_LEVEL_DATA, Ed::CParkManager::COMPRESSED_MAP_SIZE, \r\n\t\t\t\t\t\t\t\t\t   Ed::CParkManager::sInstance()->GetCompressedMapBuffer(), \"level data\", \r\n\t\t\t\t\t\t\t\t\t   GameNet::vSEQ_GROUP_PLAYER_MSGS, false, true );\r\n\t\t\t\t\t\t   \r\n\t\t\t\tserver->StreamMessage( player->GetConnHandle(), GameNet::MSG_ID_RAIL_DATA, Obj::GetRailEditor()->GetCompressedRailsBufferSize(), \r\n\t\t\t\t\t\t\t\t\t   Obj::GetRailEditor()->GetCompressedRailsBuffer(), \"rail data\", \r\n\t\t\t\t\t\t\t\t\t   GameNet::vSEQ_GROUP_PLAYER_MSGS, false, true );\r\n\t\t\t\t\t\t   \r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tmsg_desc.m_Data = &msg;\r\n\t\tmsg_desc.m_Length = sizeof(GameNet::MsgChangeLevel);\r\n\t\tmsg_desc.m_Id = GameNet::MSG_ID_CHANGE_LEVEL;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\r\n\t\tif( player->IsLocalPlayer() == false )\r\n\t\t{\r\n\t\t\tif( gamenet_man->UsingCreatedGoals())\r\n\t\t\t{\r\n\t\t\t\tgamenet_man->LoadGoals( level );\r\n\t\t\t\tserver->StreamMessage( player->GetConnHandle(), GameNet::MSG_ID_GOALS_DATA, gamenet_man->GetGoalsDataSize(),\r\n\t\t\t\t\t\t\t   gamenet_man->GetGoalsData(), \"goals data\", GameNet::vSEQ_GROUP_PLAYER_MSGS, false, true );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Don't send them any non-important messages until they're finished loading\r\n\t\tmsg_desc.m_Data = &ready_msg;\r\n\t\tmsg_desc.m_Length = sizeof( GameNet::MsgReady );\r\n\t\tmsg_desc.m_Id = GameNet::MSG_ID_READY_QUERY;\r\n\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t\t\r\n\t\tplayer->SetReadyQueryTime( ready_msg.m_Time );\r\n\t}\r\n\r\n\t// In net games, the changing of levels is deferred. No need to send immediately - we can\r\n\t// wait until the enqueued message is naturally added to the outgoing stream.  In 2p mode,\r\n\t// however, the scripts expect this message to be sent and handled in a one-frame window\r\n\t// so we need to send it immediately\r\n\tif ( ! gamenet_man->InNetGame())\r\n\t{\r\n\t\tserver->SendData();\t\t// Mick, (true) because we want to send it immediatly\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LaunchLevel | launches currently requested level\r\nbool ScriptLaunchLevel(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tSkate* skate_mod = Skate::Instance();\r\n\tuint32 level = skate_mod->m_requested_level;\r\n\tskate_mod->OpenLevel(level);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RequestLevel | \r\n// @uparm name | level to request\r\nbool ScriptRequestLevel(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tSkate* skate_mod = Skate::Instance();\r\n\tuint32 level;\r\n\r\n\t\r\n//\tprintf (\"\\n%s\\n\",pScript->GetScriptInfo());\r\n\t\r\n\t\r\n\tif( !pParams->GetChecksum(NONAME, &level, false))\r\n\t{\r\n\t\tconst char* level_name;\r\n\t\tchar checksum_name[128];\r\n\r\n\t\tif( pParams->GetString( NONAME, &level_name, Script::ASSERT ))\r\n\t\t{\r\n\t\t\tsprintf( checksum_name, \"load_%s\", level_name );\r\n\t\t\tDbg_Printf( \"Got checksum name of %s\\n\", checksum_name );\r\n\t\t\tlevel = Script::GenerateCRC( checksum_name );\r\n\t\t}\r\n\t}\r\n\r\n\tif( level == Script::GenerateCRC(\"use_preferences\") )\r\n\t{\r\n\t\tlevel = gamenet_man->GetLevelFromPreferences();\r\n\t\tgamenet_man->SetLevel( level );\r\n\t}\r\n\r\n\tskate_mod->m_requested_level = level;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Retry | retry current level\r\nbool ScriptRetry(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tSkate* skate_mod = Skate::Instance();\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\tskate_mod->LaunchGame();\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LaunchGame | \r\nbool ScriptLaunchGame(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\tSkate::Instance()->LaunchGame();\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptFillRankingScreen(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tLst::Search< GameNet::PlayerInfo > sh;\r\n\tGameNet::PlayerInfo* player;\r\n\tLst::Head< GameNet::ScoreRank > rank_list;\r\n\tLst::Search< GameNet::ScoreRank > rank_sh;\r\n\tGameNet::ScoreRank* rank, *next;\r\n\tbool in_goal_attack;\r\n\tint i;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\r\n\tin_goal_attack = skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netgoalattack\" );\r\n\r\n\tif( skate_mod->GetGameMode()->IsTeamGame())\r\n\t{\r\n\t\tfor( i = 0; i < skate_mod->GetGameMode()->NumTeams(); i++ )\r\n\t\t{\r\n\t\t\tif( gamenet_man->NumTeamMembers( i ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tchar team_name_str[64];\r\n\t\t\t\t\t\t\r\n\t\t\trank = new GameNet::ScoreRank;\r\n\t\t\trank->m_IsKing = false;\r\n\t\t\trank->m_ColorIndex = i + 2;\r\n\t\t\trank->m_TeamId = i;\r\n\t\t\trank->m_TotalScore = gamenet_man->GetTeamScore( i );\r\n\t\t\t\r\n\t\t\tsprintf( team_name_str, \"team_%d_name\", i + 1 );\r\n\t\t\tsprintf( rank->m_Name, \"\\\\c%d%s %s\", rank->m_ColorIndex, Script::GetString( team_name_str ), Script::GetString( \"total_str\" ));\r\n\t\t\t\t\t\t\r\n\t\t\trank->SetPri( gamenet_man->GetTeamScore( i ));\r\n\t\t\trank_list.AddNode( rank );\r\n\t\t}\r\n\r\n\t\t// Now loop through the sorted list in order of highest to lowest score and print them out\r\n\t\ti = 0;\r\n\t\tfor( rank = rank_sh.FirstItem( rank_list ); rank; rank = next )\r\n\t\t{   \r\n\t\t\tScript::CStruct* p_item_params;\r\n\t\t\tchar score_str[64];\r\n\t\r\n\t\t\tnext = rank_sh.NextItem();\r\n\t\r\n\t\t\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t\t{\r\n\t\t\t\tchar player_score_str[128];\r\n\t\t\t\tint player_score;\r\n                \r\n\t\t\t\tif( player->m_Team != rank->m_TeamId )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( in_goal_attack )\r\n\t\t\t\t{\r\n\t\t\t\t\tGame::CGoalManager* pGoalManager;\r\n\t\t\t \r\n\t\t\t\t\tpGoalManager = Game::GetGoalManager();\r\n\t\t\t\t\tplayer_score = pGoalManager->NumGoalsBeatenBy( player->m_Skater->GetID());\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tplayer_score = gamenet_man->GetPlayerScore( player->m_Skater->GetID());\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\r\n\t\t\t\tif( player->IsLocalPlayer())\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf( player_score_str, \"\\\\c%d> %s\", rank->m_ColorIndex, player->m_Name );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf( player_score_str, \"\\\\c%d%s\", rank->m_ColorIndex, player->m_Name );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tp_item_params = new Script::CStruct;\t\r\n\t\t\t\tp_item_params->AddString( \"text\", player_score_str );\r\n\t\t\t\t// p_item_params->AddChecksum( \"id\", 123456 + i );\r\n\t\t\t\tp_item_params->AddChecksum( \"parent\", Script::GenerateCRC( \"player_list_menu\" ));\r\n\r\n\t\t\t\tScript::RunScript(\"player_menu_add_item\", p_item_params);\r\n\t\t\t\tdelete p_item_params;\r\n\t\t\r\n\t\t\t\tp_item_params = new Script::CStruct;\t\r\n\t\t\t\tif(\tskate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netking\" ) ||\r\n\t\t\t\t\tskate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"king\" ))\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf( score_str, \"%.2d:%.2d\", Tmr::InSeconds( player_score ) / 60, Tmr::InSeconds( player_score ) % 60 );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf( score_str, \"%d\", player_score );\r\n\t\t\t\t}\r\n\t\t\t\tp_item_params->AddString( \"text\", score_str );\r\n\t\t\t\tp_item_params->AddChecksum( \"font\", Script::GenerateCRC( \"dialog\" ) );\r\n\t\t\t\tp_item_params->AddChecksum( \"id\", 234567 + i );\r\n\t\t\t\tp_item_params->AddChecksum( \"parent\", Script::GenerateCRC( \"rankings_list_menu\" ));\r\n\t\t\r\n\t\t\t\tScript::RunScript(\"score_menu_add_item\",p_item_params);\r\n\t\t\t\tdelete p_item_params;\r\n\r\n\t\t\t\ti++;\r\n\t\t\t}\r\n\t\t\tp_item_params = new Script::CStruct;\t\r\n\t\t\tp_item_params->AddString( \"text\", rank->m_Name );\r\n\t\t\t// p_item_params->AddChecksum( \"id\", 123456 + i );\r\n\t\t\tp_item_params->AddChecksum( NONAME, Script::GenerateCRC( \"team_score\" ) );\r\n\t\t\tp_item_params->AddChecksum( \"parent\", Script::GenerateCRC( \"player_list_menu\" ));\r\n\t\r\n\t\t\tScript::RunScript(\"player_menu_add_item\",p_item_params);\r\n\t\t\tdelete p_item_params;\r\n\t\r\n\t\t\tp_item_params = new Script::CStruct;\t\r\n\t\t\tif( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netking\" ) ||\r\n\t\t\t\tskate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"king\" ))\r\n\t\t\t{\r\n\t\t\t\tsprintf( score_str, \"\\\\c%d%.2d:%.2d\", rank->m_ColorIndex, Tmr::InSeconds( rank->GetPri()) / 60, Tmr::InSeconds( rank->GetPri()) % 60 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsprintf( score_str, \"\\\\c%d%d\", rank->m_ColorIndex, rank->GetPri());\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tp_item_params->AddString( \"text\", score_str );\r\n\t\t\tp_item_params->AddChecksum( \"id\", 234567 + i );\r\n\t\t\tp_item_params->AddChecksum( \"font\", Script::GenerateCRC( \"dialog\" ) );\r\n\t\t\tp_item_params->AddChecksum( NONAME, Script::GenerateCRC( \"team_score\" ) );\r\n\t\t\tp_item_params->AddChecksum( \"parent\", Script::GenerateCRC( \"rankings_list_menu\" ));\r\n\t\r\n\t\t\tScript::RunScript(\"score_menu_add_item\",p_item_params);\r\n\t\t\tdelete p_item_params;\r\n\t\r\n\t\t\tdelete rank;\r\n\t\t\ti++;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tint player_score;\r\n\r\n\t\t\tif( in_goal_attack )\r\n\t\t\t{\r\n\t\t\t\tGame::CGoalManager* pGoalManager;\r\n\t\t \r\n\t\t\t\tpGoalManager = Game::GetGoalManager();\r\n\t\t\t\tplayer_score = pGoalManager->NumGoalsBeatenBy( player->m_Skater->GetID());\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tplayer_score = gamenet_man->GetPlayerScore( player->m_Skater->GetID());\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\trank = new GameNet::ScoreRank;\r\n\t\t\tstrcpy( rank->m_Name, player->m_Skater->GetDisplayName() );\r\n\t\r\n\t\t\t// Lists sort based on node's priority so set the node's priority to that of\r\n\t\t\t// the player's score and add him to the list\r\n\t\t\trank->SetPri( player_score );\r\n\t\t\trank_list.AddNode( rank );\r\n\t\t}\r\n\t\r\n\t\t// Now loop through the sorted list in order of highest to lowest score and print them out\r\n\t\ti = 0;\r\n\t\tfor( rank = rank_sh.FirstItem( rank_list ); rank; rank = next )\r\n\t\t{   \r\n\t\t\tScript::CStruct* p_item_params;\r\n\t\t\tchar score_str[64];\r\n\t\r\n\t\t\tnext = rank_sh.NextItem();\r\n\t\r\n\t\t\t//Script::RunScript( \"prepare_server_menu_for_new_children\" );\r\n\t\t\t\r\n\t\t\tp_item_params = new Script::CStruct;\t\r\n\t\t\tp_item_params->AddString( \"text\", rank->m_Name );\r\n\t\t\t// p_item_params->AddChecksum( \"id\", 123456 + i );\r\n\t\t\tp_item_params->AddChecksum( \"parent\", Script::GenerateCRC( \"player_list_menu\" ));\r\n\t\r\n\t\t\tScript::RunScript(\"player_menu_add_item\",p_item_params);\r\n\t\t\tdelete p_item_params;\r\n\t\r\n\t\t\tp_item_params = new Script::CStruct;\t\r\n\t\t\tif( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netking\" ) ||\r\n\t\t\t\tskate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"king\" ))\r\n\t\t\t{\r\n\t\t\t\tsprintf( score_str, \"%.2d:%.2d\", Tmr::InSeconds( rank->GetPri()) / 60, Tmr::InSeconds( rank->GetPri()) % 60 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsprintf( score_str, \"%d\", rank->GetPri());\r\n\t\t\t}\r\n\r\n\t\t\tp_item_params->AddString( \"text\", score_str );\r\n\t\t\tp_item_params->AddChecksum( \"id\", 234567 + i );\r\n\t\t\tp_item_params->AddChecksum( \"font\", Script::GenerateCRC( \"dialog\" ) );\r\n\t\t\tp_item_params->AddChecksum( \"parent\", Script::GenerateCRC( \"rankings_list_menu\" ));\r\n\t\r\n\t\t\tScript::RunScript(\"score_menu_add_item\",p_item_params);\r\n\t\t\tdelete p_item_params;\r\n\t\r\n\t\t\tdelete rank;\r\n\t\t\ti++;\r\n\t\t}\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// K: This function used to use GetMaximumNumberOfPlayers,\r\n// but I changed it to use p_gamenet_man->GetMaxPlayers so that only\r\n// the required amount of memory is allocated, hence allowing bigger\r\n// parks that allow fewer players.\r\n// p_gamenet_man->GetMaxPlayers will return the num players as chosen from the Players menu\r\n// when starting a network game.\r\n\r\n// @script | InitSkaterHeaps | \r\nbool ScriptInitSkaterHeaps(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t\r\n\t\r\n\tint num_skater_heaps_required=1;\r\n\t\r\n    Skate *p_skate = Skate::Instance();\r\n\tif (p_skate->GetGameType()==CRCD(0x5c8f5d66,\"freeskate2p\"))\r\n\t{\r\n\t\tnum_skater_heaps_required=2;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGameNet::Manager * p_gamenet_man = GameNet::Manager::Instance();\r\n\t\tnum_skater_heaps_required=p_gamenet_man->GetMaxPlayers();\r\n\t}\r\n\t\t\r\n\tDbg_Printf( \"\\nInitializing %d Skater Heaps\\n\", num_skater_heaps_required);\r\n\t\t\t   \r\n\t// If we are startinga  game with possibly more than two players\r\n\t// then we want to allocate     \r\n\tif( num_skater_heaps_required > NUM_PERM_SKATER_HEAPS )\r\n\t{\r\n\t\tMem::Manager::sHandle().DeleteSkaterHeaps();\r\n\t\tMem::Manager::sHandle().InitSkaterHeaps(num_skater_heaps_required);\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetLevel | resets the level\r\nbool ScriptResetLevel(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tSkate* skate_mod = Skate::Instance();\r\n\r\n\t// A hacky way of preserving the running script, since skate's cleanup will destroy all\r\n\t// spawned scripts.\r\n\tbool was_spawned = false;\r\n\tif( pScript )\r\n\t{\r\n\t\twas_spawned = pScript->mIsSpawned;\r\n\t\tpScript->mIsSpawned = false;\r\n\t}\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\tskate_mod->ResetLevel();\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\tif( pScript )\r\n\t{\r\n\t\tpScript->mIsSpawned = was_spawned;\r\n\t}\r\n\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#if 0\r\n\r\nstatic char * maybe_new(int n, bool new_record)\r\n{\r\n\tchar *p = Script::GetScriptString(n);\r\n\tif (new_record)\r\n\t{\r\n\t\tsprintf (p,\"&c1\");\r\n\t\tp+=3;\r\n\t}\r\n\treturn p;\t\r\n}\r\n\r\n// insert a single line into the script strings\r\nvoid populate_line(int &index, Records::CRecord *pRecord)\r\n{\r\n\t\tsprintf(maybe_new(index++,pRecord->GetNewRecord()),\"%s\",Str::PrintThousands(pRecord->GetValue()));\r\n\t\tsprintf(maybe_new(index++,pRecord->GetNewRecord()),\"%d\",pRecord->GetNumber());\r\n\t\tsprintf(maybe_new(index++,pRecord->GetNewRecord()),pRecord->GetInitials());\r\n}\r\n\r\n#ifndef __PLAT_NGC__\r\n// insert a single line into the script strings\r\nstatic void populate_line_secs(int &index, Records::CRecord *pRecord)\r\n{\r\n\t\t#if (ENGLISH == 0)\t\t\r\n\t\tsprintf(maybe_new(index++,pRecord->GetNewRecord()),\"%3.2f %s\",(float)pRecord->GetValue()/100.0f,Script::GetLocalString( \"skate_str_secs\"));\r\n\t\t#else\t\t\r\n\t\tsprintf(maybe_new(index++,pRecord->GetNewRecord()),\"%3.2f secs\",(float)pRecord->GetValue()/100.0f);\r\n\t\t#endif\r\n\t\tsprintf(maybe_new(index++,pRecord->GetNewRecord()),\"%d\",pRecord->GetNumber());\r\n\t\tsprintf(maybe_new(index++,pRecord->GetNewRecord()),pRecord->GetInitials());\r\n}\r\n\r\n\r\nstatic void  populate_table(int &index, Records::CRecordTable *pRecordTable)\r\n{\r\n\r\n\tint entries = pRecordTable->GetSize();\r\n\tfor (int i = 0; i < entries; i++)\r\n\t{\r\n\t\tpopulate_line(index, pRecordTable->GetRecord(i));\t\t\r\n\t}\r\n}\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Update the records with whatever we just did this session \r\nvoid Skate::UpdateRecords()\r\n{\r\n\tm_new_record = false;\r\n\t\r\n\tint level = GetCareer()->GetLevel();\r\n\r\n\t// get the records for this level\t\r\n\tRecords::CLevelRecords *pRecords = GetGameRecords()->GetLevelRecords(level);\r\n\r\n   \t// find the skater, get the score landed:\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tObj::CSkater *pSkater = skate_mod->GetLocalSkater(); \r\n\tif( pSkater == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}          \r\n\r\n\tMdl::Score * pScore = ( pSkater->GetScoreObject() );\r\n\t/*\r\n\tHUD::PanelMgr* panel_mgr = HUD::PanelMgr::Instance();\r\n\tHUD::Panel* pPanel;\r\n\tpPanel = panel_mgr->GetPanelBySkaterId(pSkater->GetID(), false);\r\n\t*/\r\n\r\n\t// Insert the score into the high score table if it is high enough\t \r\n\tm_new_record |=  (-1 != pRecords->GetHighScores()->MaybeNewEntry(pScore->GetTotalScore(),0));\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\r\n\tm_new_record |=  (-1 != pRecords->GetBestCombos()->MaybeNewEntry(pScore->GetBestCombo(),0));\r\n\r\n\tObj::CSkaterBalanceTrickComponent* p_skater_balance_trick_component = GetSkaterBalanceTrickComponentFromObject(pSkater);\r\n\tDbg_Assert(p_skater_balance_trick_component);\r\n\t\r\n\tint this_grind = (int)(p_skater_balance_trick_component->mGrind.GetMaxTime()*100);\r\n\tint this_manual = (int)(p_skater_balance_trick_component->mManual.GetMaxTime()*100);\r\n\tint\tthis_lip = (int)(p_skater_balance_trick_component->mLip.GetMaxTime()*100);\r\n\t// int this_combo = 0;\r\n\tint this_combo = pScore->GetLongestCombo();\r\n\r\n\tm_new_record |= pRecords->GetLongestGrind()->MaybeNewRecord(this_grind,0);\t\r\n\tm_new_record |= pRecords->GetLongestManual()->MaybeNewRecord(this_manual,0);\t\r\n\tm_new_record |= pRecords->GetLongestLipTrick()->MaybeNewRecord(this_lip,0);\t\t\r\n\tm_new_record |= pRecords->GetLongestCombo()->MaybeNewRecord(this_combo,0);\t\t\r\n}\r\n\r\n#define\tMAX_COMBO_LINES  200\t\t\t// more that we need...\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifndef __PLAT_NGC__\r\n#if 0\r\nstatic float text_width(const char *p_string, const char *p_font)\r\n{\r\n\tFnt::Drawer drawer;\r\n\tdrawer.SetFont(p_font);\r\n\tdrawer.SetText(p_string);\r\n\treturn drawer.GetWidth();\r\n}\r\n#endif\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Utility function to get the info out of the level records\r\n// and into the script strings\r\nvoid Skate::GetRecordsText(int level)\r\n{\r\n#if 0\r\n#ifndef __PLAT_NGC__\r\n\t\r\n\r\n\t// get the records for this level\t\r\n\tRecords::CLevelRecords *pRecords = GetGameRecords()->GetLevelRecords(level);\r\n\r\n\tint index = 0;\r\n\t\r\n\t\t// find the skater, get the score landed:\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tObj::CSkater *pSkater = skate_mod->GetLocalSkater();\r\n\tMdl::Score * pScore = ( pSkater->GetScoreObject() );\r\n\t/*\r\n\tHUD::PanelMgr* panel_mgr = HUD::PanelMgr::Instance();\r\n\tHUD::Panel* pPanel;\r\n\tpPanel = panel_mgr->GetPanelBySkaterId(pSkater->GetID(), false);\r\n\tDbg_MsgAssert(pPanel,(\"Could not get panel for skater on records screen\"));\r\n\t*/\r\n\r\n\tint this_grind = (int)(pSkater->mGrind.GetMaxTime()*100);\r\n\tint this_manual = (int)(pSkater->mManual.GetMaxTime()*100);\r\n\tint\tthis_lip = (int)(pSkater->mLip.GetMaxTime()*100);\r\n\t\r\n\t// get total score for this level\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tsprintf(Script::GetScriptString(index++),\"%s\",Str::PrintThousands(pScore->GetTotalScore()));\t\t // 0\r\n\t// get highest score from high score table\r\n\tsprintf(Script::GetScriptString(index++),\"%s\",Str::PrintThousands(pRecords->GetHighScores()->GetRecord(0)->GetValue()));\t  // 1\r\n\t\r\n\t\r\n\t#if (ENGLISH == 0)\r\n\t\r\n\tsprintf(Script::GetScriptString(index++),\"%3.2f %s\",(float)this_grind/100.0f,Script::GetLocalString( \"skate_str_secs\"));\t\t\t\t\t  // 2\r\n\tsprintf(Script::GetScriptString(index++),\"%3.2f %s\",(float)this_manual/100.0f,Script::GetLocalString( \"skate_str_secs\"));\t\t\t\t\t  // 3\r\n\tsprintf(Script::GetScriptString(index++),\"%3.2f %s\",(float)this_lip/100.0f,Script::GetLocalString( \"skate_str_secs\"));\t\t\t\t\t\t  // 4\r\n\tsprintf(Script::GetScriptString(index++),\"%d %s\",pPanel->GetNumLongestCombo(),Script::GetLocalString( \"skate_str_tricks\"));\t\t\t// 5\r\n\tsprintf(Script::GetScriptString(index++),Script::GetLocalString( \"skate_str_points_tricks\"),Str::PrintThousands(pPanel->GetScoreBestCombo()),pPanel->GetNumBestCombo());\t// 6\r\n\r\n\t#else\r\n\t\r\n\tsprintf(Script::GetScriptString(index++),\"%3.2f secs\",(float)this_grind/100.0f);\t\t\t\t\t  // 2\r\n\tsprintf(Script::GetScriptString(index++),\"%3.2f secs\",(float)this_manual/100.0f);\t\t\t\t\t  // 3\r\n\tsprintf(Script::GetScriptString(index++),\"%3.2f secs\",(float)this_lip/100.0f);\t\t\t\t\t\t  // 4\r\n\tsprintf(Script::GetScriptString(index++),\"1 tricks\");\t\t\t// 5\r\n\tsprintf(Script::GetScriptString(index++),\"2 points in 2 tricks\");\t// 6\r\n\t//sprintf(Script::GetScriptString(index++),\"%d tricks\",pPanel->GetNumLongestCombo());\t\t\t// 5\r\n\t//sprintf(Script::GetScriptString(index++),\"%s points in %d tricks\",Str::PrintThousands(pPanel->GetScoreBestCombo()),pPanel->GetNumBestCombo());\t// 6\r\n\r\n\t#endif\r\n\r\n\t// What we want is to get the last N lines of combo text, word wrapped\r\n\t// to the correct size for the font we will use on the statistics screen\r\n\t//\r\n\t// What we have is the text for the individual tricks, and the number of tricks.\r\n\t//\r\n\t// - Set up a textdrawer with the correct size and font\r\n\t// - add text to it, and to a string, until full\r\n\t// - copy string into a ScriptString, and repeat\r\n\r\n\t// find font we will be using by looking in the appropiate property \r\n\tScript::CStruct * p_record_font_props = Script::GetStructure(\"statistics_font_props\");\r\n\tconst char *p_font;\r\n\tp_record_font_props->GetText(\"font\",&p_font);\t\r\n\tScript::CStruct * p_record_box3_props = Script::GetStructure(\"statistics_box_3_props\");\r\n\tint\tbox_width;\r\n\tp_record_box3_props->GetInteger(\"box_w\",&box_width);\r\n\t  \t\r\n\t\r\n\tStr::String line_table[MAX_COMBO_LINES];\r\n\tint line = 0;\r\n\tfloat current_w = 0;\r\n\tint num_combos = 0;\r\n\t//int num_combos = pPanel->GetNumBestCombo();\r\n\tfor (int trick =0; trick < num_combos; trick++)\r\n\t{\r\n\t\tconst char * trick_chars = \"blah\";\r\n\t\t//const char * trick_chars = pPanel->GetStringBestCombo(trick);\r\n\t\tfloat trick_w = text_width(trick_chars, p_font);\r\n\t\tfloat new_w = current_w + trick_w;\r\n\t\tif (current_w > 0.0f && new_w > box_width)\r\n\t\t{\r\n\t\t\tline++;\r\n\t\t\tDbg_MsgAssert(line < MAX_COMBO_LINES,(\"Far to many combo lines\"));\r\n\t\t\tcurrent_w = 0.0f;\r\n\t\t}\r\n\t\tif (current_w == 0.0f)\r\n\t\t{\r\n\t\t\tline_table[line] = trick_chars;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// combine the two strings into one string by sprintfing them into a temporary buffer\r\n\t\t\tchar temp[1024];\t  \t// good job we have a huge stack!!\r\n\t\t\tsprintf (temp,\"%s%s\",line_table[line].getString(),trick_chars);\r\n\t\t\tDbg_MsgAssert(strlen(temp) < 1024,(\"line insanely too long\"));  // not taking any chances\r\n\t\t\tline_table[line] = temp;\t // this will delete the old string contents\r\n\t\t}\r\n\t\tcurrent_w += trick_w;\r\n\t}\r\n//\tint num_lines = line+1;\r\n\r\n\tline = 0;\r\n\twhile (index < 20)\r\n\t{\r\n\t\tsprintf(Script::GetScriptString(index++),line_table[line++].getString());\t\t\r\n\t}\r\n\r\n/* functions we can use\r\n\tint  \tGetScoreBestCombo();\r\n\tint\t\tGetNumBestCombo();\r\n\tconst char\t* GetStringBestCombo(int trick);\r\n\tint  \tGetScoreLongestCombo();\r\n\tint\t\tGetNumLongestCombo();\r\n*/\r\n\r\n\tindex = 20;\r\n\r\n\tpopulate_table(index, pRecords->GetHighScores());\t\t\t\t\t\t\t\t  \t\t\t// 20-34\r\n\tpopulate_table(index, pRecords->GetBestCombos());\t\t\t\t\t\t\t\t\t\t\t// 35-49\r\n\tpopulate_line_secs(index,pRecords->GetLongestGrind());\t\t\t\t\t\t\t\t\t\t\t// 50-52\r\n\tpopulate_line_secs(index,pRecords->GetLongestManual());\t\t\t\t\t\t\t\t\t\t\t// 53-55\r\n\tpopulate_line_secs(index,pRecords->GetLongestLipTrick());\t\t\t\t\t\t\t\t\t\t// 56-58\r\n\tpopulate_line(index,pRecords->GetLongestCombo());\t\t\t\t\t\t\t\t\t\t\t// 59-61\r\n#endif\t\t// __PLAT_NGC__\r\n#endif\r\n}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::UpdateSkaterInputHandlers()\r\n{\t\r\n\tprintf(\"&&&&&&&&&&&&&&&&&&&&&&&&&& UpdateSkaterInputHandlers called\\n\");\r\n\t\r\n\tfor ( int i = 0; i < vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tObj::CSkater* pSkater = GetSkater( i );\r\n\t\tif ( pSkater && pSkater->IsLocalClient() )\r\n\t\t{\r\n\t\t\tprintf(\"found a local skater - binding controller\\n\");\r\n\t\t\tint heap_index = pSkater->GetHeapIndex();\r\n\t\t\tDbg_MsgAssert( heap_index >= 0 && heap_index < vMAX_SKATERS, ( \"heap index %i out of range\", heap_index ) );\r\n\t\t\t\r\n\t\t\tDbg_Assert(GetInputComponentFromObject(pSkater));\r\n\t\t\tGetInputComponentFromObject(pSkater)->BindToController(m_device_server_map[heap_index]);\r\n\t\t\t\r\n\t\t\t// Dan: Pretty sure this method is wrong.\r\n\t\t\t//char skatecam[16];\r\n\t\t\t//sprintf(skatecam,\"SkaterCam%d\",i);\r\n\t\t\t//if (Obj::CCompositeObject *p_obj\r\n\t\t\t\t//= static_cast< Obj::CCompositeObject* >(Obj::CCompositeObjectManager::Instance()->GetObjectByID(Script::GenerateCRC(skatecam))))\r\n\t\t\tif (Obj::CCompositeObject *p_obj = pSkater->GetCamera())\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert(GetInputComponentFromObject(p_obj));\r\n\t\t\t\tGetInputComponentFromObject(p_obj)->BindToController(m_device_server_map[heap_index]);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Fills in a little structure with some stuff so that SkipLogic is really fast.\r\nvoid Skate::pre_calculate_object_update_info()\r\n{\r\n\tif (Nx::CViewportManager::sGetNumActiveViewports() > 1 || ! Nx::CViewportManager::sGetActiveCamera(0))\r\n\t{\r\n\t\t// Nothing should be suspended if multiplayer, so leave the flag true.\r\n\t\tm_precalculated_object_update_info.mDoNotSuspendAnything=true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_precalculated_object_update_info.mDoNotSuspendAnything=false;\r\n\t\tm_precalculated_object_update_info.mActiveCameraPosition = Nx::CViewportManager::sGetActiveCamera(0)->GetPos();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPrefs::Preferences* GetPreferences( Script::CStruct* pParams, bool assert_on_fail )\r\n{   \r\n\tuint32 checksum;\r\n\tpParams->GetChecksum( \"prefs\", &checksum, true );\r\n\r\n\treturn GetPreferences( checksum, assert_on_fail );\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPrefs::Preferences* GetPreferences( uint32 checksum, bool assert_on_fail )\r\n{\t\r\n\tif ( checksum == Script::GenerateCRC(\"network\") )\r\n\t{\r\n\t\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\t\treturn gamenet_man->GetNetworkPreferences();\r\n\t}\r\n\telse if ( checksum == Script::GenerateCRC(\"taunt\") )\r\n\t{\r\n\t\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\t\treturn gamenet_man->GetTauntPreferences();\r\n\t}\r\n\telse if ( checksum == Script::GenerateCRC(\"splitscreen\") )\r\n\t{\r\n\t\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\treturn skate_mod->GetSplitScreenPreferences();\r\n\t}\r\n\r\n\tif ( assert_on_fail )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Couldn't find preferences for %s\", Script::FindChecksumName(checksum) ) );\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Just a simple debugging interface function to call the main rail \r\n// manager's DebugRender() function\r\nvoid\t\t\tRail_DebugRender()\r\n{\r\n\tMdl::Skate* skate_mod =  Mdl::Skate::Instance();\r\n\tif (!skate_mod->GetDrawRails())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tskate_mod->GetRailManager()->DebugRender();\r\n\r\n\tfor (Obj::CRailManagerComponent* p_rail_manager_component = static_cast< Obj::CRailManagerComponent* >(Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType(CRC_RAILMANAGER));\r\n\t\tp_rail_manager_component;\r\n\t\tp_rail_manager_component = static_cast< Obj::CRailManagerComponent* >(p_rail_manager_component->GetNextSameType()))\r\n\t{\r\n\t\tObj::CCompositeObject* p_movable_object = p_rail_manager_component->GetObject();\r\n\r\n\t\t// form a transformation matrix\r\n\t\tMth::Matrix total_mat = p_movable_object->GetMatrix();\r\n\t\ttotal_mat[X][W] = 0.0f;\r\n\t\ttotal_mat[Y][W] = 0.0f;\r\n\t\ttotal_mat[Z][W] = 0.0f;\r\n\t\ttotal_mat[W] = p_movable_object->GetPos();\r\n\t\ttotal_mat[W][W] = 1.0f;\r\n\r\n\t\t\r\n\t\tObj::CRailManager *p_railman = p_rail_manager_component->GetRailManager();\t\t\t\t\t\t\t\t   \r\n\t\tif (p_railman)\r\n\t\t{\r\n\t\t\tp_railman->DebugRender(&total_mat);\t\t\t\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// return the current gap checklist for the level that we are in\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\nObj::CGapChecklist* Skate::GetGapChecklist()\r\n{\r\n\tObj::CGapChecklist* p_gap_checklist = GetCareer()->GetGapChecklist(); \r\n\tDbg_Assert(p_gap_checklist);\r\n\treturn p_gap_checklist;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tSkate::ShouldAllocateNetMiscHeap( void )\r\n{\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\treturn ( gamenet_man->InNetGame() && ( m_cur_level != Script::GenerateCRC( \"Load_Skateshop\" ))) ;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tSkate::ShouldAllocateInternetHeap( void )\r\n{\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tif( gamenet_man->InNetMode())\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// GJ:  need to temporarily remove LOAD_CAS, because \r\n\t// the internet heap is coming in after the unloadable\r\n\t// anims, and the unloadable anims need to be the last\r\n\t// thing on the topdown heap\r\n\tif( ( m_requested_level == Script::GenerateCRC( \"load_skateshop\" ) ) \r\n\t\t|| ( m_requested_level == Script::GenerateCRC( \"load_CAS\" )))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::FirstInputReceived()\r\n{\r\n\tm_first_input_received = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mdl\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/skate.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSKATE\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmodules/skate/skate.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t06/07/2000\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __MODULES_SKATE_SKATE_H\r\n#define __MODULES_SKATE_SKATE_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#include <core/singleton.h>\r\n#include <core/task.h>\r\n\r\n#include <gel/module.h>\r\n#include <gel/net/net.h>\r\n\r\n#include <gfx/shadow.h> // For EShadowType\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nenum\r\n{\r\n\tSKATE_TYPE_UNDEFINED \t\t= 0,\r\n\tSKATE_TYPE_SKATER \t\t\t= 1,\r\n\tSKATE_TYPE_PED\t\t\t\t= 2,\r\n\tSKATE_TYPE_CAR\t\t\t\t= 3,\r\n\tSKATE_TYPE_GAME_OBJ\t\t\t= 4,\r\n\tSKATE_TYPE_BOUNCY_OBJ\t\t= 5,\r\n\tSKATE_TYPE_CASSETTE\t\t\t= 6,\r\n\tSKATE_TYPE_ANIMATING_OBJECT\t= 7,\r\n\tSKATE_TYPE_CROWN\t\t\t= 8,\r\n\tSKATE_TYPE_PARTICLE\t\t\t= 9,\r\n\tSKATE_TYPE_REPLAY_DUMMY\t\t= 10,\r\n\tSKATE_TYPE_COMPOSITE\t\t= 11,\t\t// just a temp type, to exclude it from certain checks\r\n\t\r\n\t// Note: If a new type is added here, please also add it to the switch statement in\r\n\t// the CCompositeObject::GetDebugInfo function in gel\\object\\compositeobject.cpp and also add\r\n\t// the name to data\\scripts\\debugger\\debugger_names.q\r\n\t// That way the m_type member will appear as a name in the script debugger rather than as\r\n\t// an integer.\r\n};\r\n\r\nnamespace Game\r\n{\r\n    class CGameMode;\r\n\tclass CGoalManager;\r\n}\r\n\r\nnamespace GameNet\r\n{\r\n\tclass PlayerInfo;\r\n}\r\n\r\nnamespace Obj\r\n{\r\n    class CGapChecklist;\r\n    class CGeneralManager;\r\n\tclass CMovieManager;\r\n    class CObject;\r\n\tclass CPlayerProfileManager;\r\n\tclass CProximManager;\r\n\tclass CRailManager;\r\n\tclass CSkater;\r\n\tclass CSkaterCareer;\r\n\tclass CSkaterProfile;\r\n    class CTrickChecksumTable;\r\n    class CTrickObjectManager;\r\n\r\n#\tifdef TESTING_GUNSLINGER\r\n\tclass CNavManager;\r\n#\tendif\r\n};\r\n\r\nnamespace Prefs\r\n{\r\n\tclass Preferences;\r\n};\r\n\r\nnamespace Records\r\n{\r\n\tclass CGameRecords;\r\n};\r\n\r\nnamespace Script\r\n{\r\n    class CScript;\r\n    class CStruct;\r\n};\r\n\r\nnamespace Mdl\r\n{\r\n    class CCompetition;\r\n    class CGameFlow;\r\n    class CHorse;\r\n\r\n// Little structure for storing information about a high score goal\r\n// currently there are just two, the \"high score\" and \"pro score\"\r\n// we did previously have an additional \"sick score\", which may return\r\n// hence, I'm trying to be flexible here, if not totally object oriented...   \r\nstruct\tSScoreGoal\r\n{\r\n\tint\t\t\t\tscore;\t\t\t\t\t// What score we try to get\r\n\tuint32\t\t\tscript;\t\t\t\t\t// what script it triggers\r\n\tint\t\t\t\tgoal;\t\t\t\t\t// what goal we get (can be -1 for none, if you want to do it in script)\r\n};\r\n   \r\n// There is an array of vMAX_SKATERS of these in the Skate class.\r\n// They get set from the controller config menu in the skateshop, and\r\n// get saved out to the memory card. (see ScriptSaveToMemoryCard in cfuncs.cpp)\r\n//\r\n// Brad - the skaterIndex is used to map a controller to a skater.\r\n// This is needed to meet an XBox requirement that whatever controller they\r\n// use to start the game can be used to play.\r\nstruct SControllerPreferences\r\n{\r\n\tint skaterIndex;\r\n\tbool VibrationOn;\r\n\tbool AutoKickOn;\r\n\tbool SpinTapsOn;\r\n};\r\n\r\n// Ken: A small structure for holding info needed by SkipLogic & MovingObj_Update\r\n// to save them having to calculate the same things for billions of objects every frame.\r\n// This structure gets filled in once per frame, and read by SkipLogic & MovingObj_Update\r\nstruct SPreCalculatedObjectUpdateInfo\r\n{\r\n\t// This is set if it is a multiplayer game or if a cutscene is playing\r\n\tbool mDoNotSuspendAnything;\r\n\t\r\n\t// SkipLogic calculates the distance of the object from this.\r\n\tMth::Vector mActiveCameraPosition;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Skate : public Module \r\n{\r\n\r\npublic:\r\n\t\r\n\tenum\r\n\t{\r\n\t\tvMAX_SKATERS \t\t= 8,\r\n\t\tvMAX_SCORE_GOALS    = 64,\t\t// Don't really need 32, but just to cover the maximun number of goals\r\n\t};\r\n\t\t\t\t\t\t\t\t\tSkate( void );\r\n\tvirtual\t\t\t\t\t\t\t~Skate( void );\r\n\t\t\r\n\t// Cleans up game objects and optionally skaters\r\n\tvoid\t\t\t\t\t\t\tCleanup();\r\n\tvoid \t\t\t\t\t\t\tCleanupForParkEditor();\r\n\r\n\t\r\n\tvoid\t\t\t\t\t\t\tPause( bool pause = true );\r\n\t\r\n\t/************************************\r\n\t* skater control functions\r\n\t*************************************/\r\n\tObj::CSkater* \t\t\t\t\tGetLocalSkater( void );\r\n\tObj::CSkater*\t\t\t\t\tGetSkater( uint num );\r\n\tObj::CSkater*\t\t\t\t\tGetSkaterById( uint32 id );\r\n\tuint32\t\t\t\t\t\t\tGetNumSkaters( void );\r\n\tint\t\t\t\t\t\t\t\tGetNextUnusedSkaterHeapIndex( bool for_local_skater );\r\n\tvoid\t\t \t\t\t\t\tGetNextStartingPointData( Mth::Vector* pos, Mth::Matrix* matrix, int obj_id );\r\n\tvoid\t\t\t\t\t\t\tHideSkater( Obj::CSkater* skater, bool should_hide = true );\r\n\tObj::CSkater*\t\t\t\t\tadd_skater( Obj::CSkaterProfile* pSkaterProfile, bool local_client, int obj_id, int player_num );\r\n\tvoid\t\t\t\t\t\t\tremove_skater( Obj::CSkater* skater );\t// Remove a specific skater\r\n\tint\t\t\t\t\t\t\t\tfind_restart_node( int index );\r\n\tvoid\t\t\t\t\t\t\tskip_to_restart_point( Obj::CSkater* skater, int node = -1, bool walk = false );\r\n\tvoid\t\t\t\t\t\t\tmove_to_restart_point( Obj::CSkater* skater );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tPauseGameFlow( bool paused );\r\n\tvoid\t\t\t\t\t\t\tSetTimeLimit( int seconds );\r\n\tint\t\t\t\t\t\t\t\tGetTimeLimit( void );\r\n\r\n\tvoid\t\t\t\t\t\t\tFirstInputReceived();\r\n\t\r\n\t/************************************\r\n\t* game control functions\r\n\t*************************************/\r\n\t\r\npublic:\r\n\t// game control\r\n\tvoid\t\t\t\t\t\t\tSetGameType(uint32 gameType);\r\n\t// Added by Ken, for use by the cassette menu so that it can tell whether it is to be\r\n\t// used for career, free skate or session.\r\n\tuint32\t\t\t\t\t\t\tGetGameType() {return m_requested_game_type;}\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetCurrentGameType();\r\n\r\n\t// returns checksum of level script name\r\n\tuint32\t\t\t\t\t\t\tGetGameLevel();\t\t  \r\n\r\n\t// informs the skate module that we want the game in progress to end\r\n\tvoid\t\t\t\t\t\t\tRequestGameEnd();\r\n\tbool\t\t\t\t\t\t\tIsGameInProgress() {return m_gameInProgress;}\r\n\r\n\tvoid\t\t\t\t\t\t\tSetLaunchingQueuedScripts( void );\r\n\tvoid\t\t\t\t\t\t\tClearLaunchingQueuedScripts( void );\r\n\tbool\t\t\t\t\t\t\tLaunchingQueuedScripts( void );\r\n\r\n\t// used to not load objects that were meant to be left\r\n\t// out for performance/bandwidth/gameplay reasons\r\n\tbool\t\t\t\t\t\t\tIsMultiplayerGame( void );\r\n\tbool\t\t\t\t\t\t\tShouldBeAbsentNode( Script::CStruct* pNode );\r\n\t\r\n\tvoid\t\t\t\t\t\t\tOpenLevel(uint32 level_script);\r\n\tvoid\t\t\t\t\t\t\tRestartLevel();\r\n\tvoid\t\t\t\t\t\t\tResetLevel();\r\n\tvoid\t\t\t\t\t\t\tResetSkaters(int node = -1, bool walk = false);\r\n\tvoid\t\t\t\t\t\t\tChangeLevel( uint32 level_id );\r\n\tvoid\t\t\t\t\t\t\tLaunchGame();\r\n\tvoid\t\t\t\t\t\t\tLaunchNetworkGame();\r\n\r\n\t/************************************\r\n\t* network functions\t\t\t\t\t*\r\n\t*************************************/\r\n\tvoid\t\t\t\t\t\t\tStartServer( void );\r\n\tvoid\t\t\t\t\t\t\tAddNetworkMsgHandlers( Net::Client* client, int index );\r\n\tvoid\t\t\t\t\t\t\tLeaveServer( void );\r\n\tvoid\t\t\t\t\t\t\tSendScoreUpdates( bool final = false );\r\n\tvoid \t\t\t\t\t\t\tObserveNextSkater( void );\r\n\tuint32\t\t\t\t\t\t\tGetCheatChecksum( void );\r\n\tvoid\t\t\t\t\t\t\tSendCheatList( GameNet::PlayerInfo* player );\r\n\r\n\t/************************************\r\n\t* other functions\r\n\t*************************************/\r\n\r\n\tconst char*\t\t\t\t\t\tGetSkaterDisplayName( int id );\r\n\tObj::CSkaterProfile*\t\t\tGetProfile( int i );\r\n\tObj::CSkaterProfile*\t\t\tGetCurrentProfile( Script::CStruct* pParams = NULL );\r\n\tObj::CSkaterCareer*\t\t\t\tGetCareer(){return mp_career;} \r\n\tGame::CGameMode*\t\t\t\tGetGameMode();\r\n\tGame::CGoalManager*\t\t\t\tGetGoalManager();\r\n\tObj::CGeneralManager*\t\t\tGetObjectManager( void );\r\n\tObj::CTrickObjectManager*\t\tGetTrickObjectManager( void );\r\n\tObj::CPlayerProfileManager*\t\tGetPlayerProfileManager( void );\r\n\tObj::CTrickChecksumTable*\t\tGetTrickChecksumTable() { return mp_trickChecksumTable; }\r\n\r\n\tPrefs::Preferences*\t\t\t\tGetSplitScreenPreferences( void );\r\n\tfloat\t\t\t\t\t\t\tGetHandicap( int id );\r\n\r\n\tvoid \t\t\t\t\t\t\tCheckSkaterCollisions( void );\r\n\t\r\n    static Tsk::Task< Skate >::Code   \ts_logic_code; \r\n\tstatic Tsk::Task< Skate >::Code   \ts_object_update_code; \r\n\tstatic Tsk::Task< Skate >::Code   \ts_score_update_code; \r\n\tstatic void\ts_object_update( Obj::CObject* object, void* data );\r\n\t\r\nprivate:\r\n\t\t\t\r\n\tvoid\t\t\t\t\t\t\tv_start_cb( void );\r\n\tvoid\t\t\t\t\t\t\tv_stop_cb( void );\r\n\t\r\n\tTsk::Task< Skate >*\t\t\t\tm_logic_task;\t\r\n\tTsk::Task< Skate >*\t\t\t\tm_object_update_task;\t\r\n\tTsk::Task< Skate >*\t\t\t\tm_score_update_task;    \r\n\r\n\r\n\tObj::CSkaterCareer*\t\t\t\tmp_career;\r\n\t\r\npublic:\r\n\tObj::CRailManager*\t            mp_railManager;    \r\n\tObj::CProximManager*\t        mpProximManager;\r\n\tvoid \t\t\t\t\t\t\tUpdateGameFlow();\r\n\tObj::CRailManager*\t            GetRailManager() { return mp_railManager; }\r\n\r\n#\tifdef TESTING_GUNSLINGER\r\n\tObj::CNavManager*\t\t\t\tmp_navManager;\r\n\tObj::CNavManager*\t            GetNavManager() { return mp_navManager; }\r\n#\tendif\r\n\r\n\tvoid\t\t\t                Rail_DebugRender();\r\n\r\nprivate:\r\n\tvoid \t\t\t\t\t\t\tDoUpdate();\t// called by s_logic\r\n\r\n\t\r\n//\tObj::CGeneralManager*\t\t\tmp_obj_manager;\r\n\tLst::Head< Obj::CSkater >\t\tm_skaters;\r\n\t    \r\n\tbool \t\t\t\t\t\t\tm_recording;\r\n\tbool \t\t\t\t\t\t\tm_playing;\r\n\tint \t\t\t\t\t\t\tm_fd; \r\n\r\n\tbool\t\t\t\t\t\t\tm_first_input_received;\r\n\tint\t\t\t\t\t\t\t\tm_controller_unplugged_frame_count;\r\n\r\n\t// Network msg handlers\r\n\tvoid\t\t\t\t\t\t\tnet_setup( void );\r\n\tvoid\t\t\t\t\t\t\tnet_shutdown( void );\r\n\tbool\t\t\t\t\t\t\tshould_send_update( GameNet::PlayerInfo* send_player, Obj::CObject* object );\r\n\r\n\tbool\t\t\t\t\t\t\tm_launching_queued_scripts;\r\n\t    \r\n\tstatic Net::MsgHandlerCode\t\thandle_cheats;\r\n\tstatic Net::MsgHandlerCode\t\thandle_cheat_list;\r\n\tstatic Net::MsgHandlerCode\t\thandle_projectile;\r\n\tstatic Net::MsgHandlerCode\t\thandle_enter_vehicle_client;\r\n\t\r\n\tstatic Net::MsgHandlerCode\t\thandle_anims;\r\n\tstatic Net::MsgHandlerCode\t\thandle_flip_anim;\r\n\tstatic Net::MsgHandlerCode\t\thandle_enter_vehicle_server;\r\n\t\r\n\tstatic Net::MsgHandlerCode\t\thandle_msg_relay;\r\n\tstatic Net::MsgHandlerCode\t\thandle_selective_msg_relay;\r\n\tstatic Net::MsgHandlerCode\t\thandle_script_relay;\r\n\tstatic Net::MsgHandlerCode\t\thandle_score_request;\r\n\tstatic Net::MsgHandlerCode\t\thandle_landed_trick;\r\n\tstatic Net::MsgHandlerCode\t\thandle_combo_report;\r\n\tstatic Net::MsgHandlerCode\t\thandle_object_update;\r\n\tstatic Net::MsgHandlerCode\t\thandle_object_update_relay;\r\n\tstatic Net::MsgHandlerCode\t\thandle_player_quit;\r\n\tstatic Net::MsgHandlerCode\t\thandle_disconn_accepted;\r\n\tstatic Net::MsgHandlerCode\t\thandle_kicked;\r\n\tstatic Net::MsgHandlerCode\t\thandle_play_sound;\r\n\tstatic Net::MsgHandlerCode\t\thandle_sparks;\r\n\tstatic Net::MsgHandlerCode\t\thandle_blood;\r\n\tstatic Net::MsgHandlerCode\t\thandle_score_update;\r\n\tstatic Net::MsgHandlerCode\t\thandle_bail_done;\r\n\tstatic Net::MsgHandlerCode\t\thandle_change_level;\r\n\tstatic Net::MsgHandlerCode\t\thandle_run_script;\r\n\tstatic Net::MsgHandlerCode\t\thandle_spawn_run_script;\r\n\tstatic Net::MsgHandlerCode\t\thandle_start_info;\r\n\tstatic Net::MsgHandlerCode\t\thandle_free_trick_objects;\r\n\tstatic Net::MsgHandlerCode\t\thandle_obs_log_trick_objects;\r\n\tstatic Net::MsgHandlerCode\t\thandle_obs_init_graffiti_state;\r\n\tstatic Net::MsgHandlerCode\t\thandle_face_data;\r\n\t\t\r\n\tfriend bool ScriptSetGameType(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tfriend bool ScriptInTeamGame(Script::CStruct *pParams, Script::CScript *pScript);\r\n\tfriend bool ScriptLaunchLevel(Script::CStruct *pParams, Script::CScript *pScript);\r\n    friend bool ScriptSetTimeLimit(Script::CStruct *pParams, Script::CScript *pScript);\r\n\t\r\n\t// Exactly what it says. This should be the master flag for determining if a game is in progress.\r\n\tbool\t\t\t\t\t\t\tm_gameInProgress;\r\n\tbool\t\t\t\t\t\t\tm_levelLoaded;\r\n\r\n\tbool\t\t\t\t\t\t\tm_endRun;\r\n\r\n\tuint32 \t\t\t\t\t\t\tm_gameType;\r\n\r\n\t// needed so that we can restore the skatercamera\r\n\t// after skatercams and cutscenes...\r\n\tbool\t\t\t\t\t\t\tm_lastFrameWasMovieCamera;\r\n\r\n\r\n\t// Keeps track of all the rules/options for this particular game mode\r\n\tGame::CGameMode*\t\t\t\tmp_gameMode;\r\n\r\n\t// Keeps track of all the trick objects in the scene\r\n\tObj::CTrickObjectManager*\t\tmp_trickObjectManager;\r\n\r\n\t// Keeps track of all the trick names in the game\r\n\tObj::CTrickChecksumTable*\t\tmp_trickChecksumTable;\r\n\r\n\t// Keeps track of skater appearance, stats, etc.\r\n\tObj::CPlayerProfileManager*\t\tmp_PlayerProfileManager;\r\n\r\n\t// Keeps track of all the high scores and suchlike\r\n\tRecords::CGameRecords*\t\t\tmp_gameRecords;\r\n\r\n\t// Keeps track of splitscreen preferences\r\n\tPrefs::Preferences*\t\t\t\tmp_splitscreen_preferences;\r\n\r\n\tuint32\t\t\t\t\t\t\tm_requested_game_type;\r\n\tbool\t\t\t\t\t\t\tm_levelChanged;\r\n\r\n\tSScoreGoal\t\t\t\t\t\tm_ScoreGoal[vMAX_SCORE_GOALS];\r\n\tCCompetition*\t\t\t\t\tmp_competition;\r\n\tCHorse*\t\t\t\t\t\t\tmp_horse;\r\n\tObj::CMovieManager*\t\t\t\tmp_movieManager;\r\n\tObj::CMovieManager*\t\t\t\tmp_objectAnimManager;\r\n\r\n\tGfx::EShadowType\t\t\t\tm_shadow_mode;\r\n\t\r\n\tint\t\t\t\t\t\t\t\tm_time_limit;\r\n\r\npublic:\r\n\tvoid \t\t\t\t\t\t\tBeepTimer(float time, float beep_time, float beep_speed, const char *p_script_name);\r\n\r\n\tbool\t\t\t\t\t\t\tShouldAllocateInternetHeap( void );\r\n\tbool\t\t\t\t\t\t\tShouldAllocateNetMiscHeap( void );\r\n\r\n\tuint32\t\t\t\t\t\t\tm_requested_level;\r\n\tuint32\t\t\t\t\t\t\tm_cur_level;\r\n\tuint32\t\t\t\t\t\t\tm_prev_level;\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_new_record;\r\n\t\t\r\n\tvoid\t\t\t\t\t\t\tGetRecordsText(int level);\r\n\tvoid \t\t\t\t\t\t\tUpdateRecords();\r\n\r\n\tvoid\t\t\t\t\t\t\tSetShadowMode( Gfx::EShadowType shadowMode );\r\n\tGfx::EShadowType\t\t\t\tGetShadowMode( void ) const;\r\n\t\r\n\tRecords::CGameRecords*\t\t\tGetGameRecords() {return mp_gameRecords;}\r\n\r\n\tObj::CGapChecklist\t\t*\t\tGetGapChecklist();\r\n\t\r\n// Some handy dandy functions for accessing the high score goals \t\r\n\tint\t\t\t\t\t\t\t\tGetScoreGoalScore(int n){return m_ScoreGoal[n].score;}\r\n\tvoid\t\t\t\t\t\t\tSetScoreGoalScore(int n, int score){m_ScoreGoal[n].score = score;}\r\n\tuint32\t\t\t\t\t\t\tGetScoreGoalScript(int n){return m_ScoreGoal[n].script;}\r\n\tvoid\t\t\t\t\t\t\tSetScoreGoalScript(int n, uint32 script){m_ScoreGoal[n].script = script;}\t\r\n\tint\t\t\t\t\t\t\t\tGetScoreGoalGoal(int n){return m_ScoreGoal[n].goal;}\r\n\tvoid\t\t\t\t\t\t\tSetScoreGoalGoal(int n, uint32 goal){m_ScoreGoal[n].goal = goal;}\r\n\tvoid\t\t\t\t\t\t\tClearScoreGoals() {for (int i =0;i<vMAX_SCORE_GOALS;i++) SetScoreGoalScore(i,0);}\r\n\r\n\t// for detecting end-of-run\r\n\tbool\t\t\t\t\t\t\tFirstTrickStarted();\r\n\tbool\t\t\t\t\t\t\tFirstTrickCompleted();\r\n\tbool\t\t\t\t\t\t\tSkatersAreIdle();\r\n\tbool\t\t\t\t\t\t\tEndRunSelected() {return m_endRun;}\r\n\tvoid \t\t\t\t\t\t\tEndRun() {m_endRun = true;}\r\n\tvoid\t\t\t\t\t\t\tClearEndRun() {m_endRun = false;}\r\n\r\n\tCCompetition*\t\t\t\t\tGetCompetition(){return mp_competition;}\r\n\tCHorse*\t\t\t\t\t\t\tGetHorse(){return mp_horse;}\r\n\tObj::CMovieManager*\t\t\t\tGetMovieManager(){return mp_movieManager;}\r\n\tObj::CMovieManager*\t\t\t\tGetObjectAnimManager(){return mp_objectAnimManager;}\r\n\r\n\tCGameFlow*\t\t\t\t\t\tmp_gameFlow;\r\n\tGame::CGoalManager*\t\t\t\tmp_goalManager;\r\n\t\r\n\tSControllerPreferences\t\t\tmp_controller_preferences[vMAX_SKATERS];\r\n\tint\t\t\t\t\t\t\t\tm_device_server_map[vMAX_SKATERS];\r\n\tvoid \t\t\t\t\t\t\tSetSpinTaps(int index, bool state);\r\n\tvoid\t\t\t\t\t\t\tSetAutoKick(int index, bool state);\r\n\tvoid\t\t\t\t\t\t\tSetVibration(int index, bool state);\r\n\t\r\n\t\r\n\tvoid\t\t\t\t\t\t\tSetStatOverride(float s) {m_stat_override = s;}\r\n\tfloat\t\t\t\t\t\t\tGetStatOverride() {return m_stat_override;}\t\t\t\t\t\t\t\t\t \r\n\r\n\tvoid\t\t\t\t\t\t\tSetDrawRails(bool x) {m_draw_rails = x;}\r\n\tbool\t\t\t\t\t\t\tGetDrawRails() {return m_draw_rails;}\r\n\r\n\tvoid\t\t\t\t\t\t\tUpdateSkaterInputHandlers();\r\nprivate:\r\n\r\n\tfloat\t\t\t\t\t\t\tm_stat_override;\r\n\tbool\t\t\t\t\t\t\tm_draw_rails;\r\n\r\n\t// Ken: A small structure for holding info needed by SkipLogic & MovingObj_Update\r\n\t// to save them having to calculate the same things for billions of objects every frame.\r\n\t// This structure gets filled in once per frame, and read by SkipLogic & MovingObj_Update\r\n\tSPreCalculatedObjectUpdateInfo\tm_precalculated_object_update_info;\r\n\tvoid\t\t\t\t\t\t\tpre_calculate_object_update_info();\r\npublic:\r\n\tSPreCalculatedObjectUpdateInfo\t*GetPreCalculatedObjectUpdateInfo() {return &m_precalculated_object_update_info;}\r\n\t\r\nprivate:\r\n\tDeclareSingletonClass( Skate );\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool ScriptSetGameType(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptTestGameType(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptTestRequestedGameType(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptRetry(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptLaunchGame(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptChangeLevel(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptResetLevel(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptLaunchLevel(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptRequestLevel(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptInitSkaterHeaps(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptFillRankingScreen(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\n// GJ:  These are some convenience functions that don't really\r\n// belong in any class, but are of general use to the skate code\r\n// If such a beast existed, it would\r\nPrefs::Preferences*\tGetPreferences( uint32 checksum, bool assert_on_fail = true );\r\nPrefs::Preferences*\tGetPreferences( Script::CStruct* pParams, bool assert_on_fail = true );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline uint32 Skate::GetNumSkaters()\r\n{\r\n\treturn m_skaters.CountItems();\r\n}\r\n\r\n} // namespace Mdl\r\n\r\n#endif\t// __MODULES_SKATE_SKATE_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Skate/skatenet.cpp",
    "content": "\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSkate Module (SKATE) \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmodules/skatenet.cpp\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t02/08/2001\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSkate Module's Network Handlers\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#include <string.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n\r\n#include <core/task.h>\r\n#include <core/math.h>\r\n\r\n#include <sys/sys.h>\r\n#include <sys/mem/memman.h>\r\n#include <sys/timer.h>\r\n\r\n#include <gfx/gfxman.h>\r\n#include <gfx/animcontroller.h>\r\n#include <gfx/facetexture.h>\r\n#include <gfx/skeleton.h>\r\n#include <gfx/nxmodel.h>\r\n\r\n//#include <gel/inpman.h>\r\n#include <gel/objman.h>\r\n#include <gel/object.h>\r\n#include <gel/net/net.h>\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/environment/terrain.h>\r\n\r\n#include <modules/skate/skate.h>\r\n#include <modules/skate/goalmanager.h>\r\n#include <modules/skate/gamemode.h>\r\n#include <modules/frontend/frontend.h>\r\n\r\n#include <objects/skater.h>\r\n#include <objects/skaterprofile.h>\r\n#include <sk/objects/skatercareer.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/components/skaterstatehistorycomponent.h>\r\n#include <sk/components/skaterlocalnetlogiccomponent.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <scripting/cfuncs.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mdl\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define\tvFORCE_UPDATE_INTERVAL\t60\r\n#define vOBJ_UPDATE_THRESHOLD\tFEET( 150 )\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass ObjUpdateInfo\r\n{\r\npublic:\r\n\tNet::BitStream\t\t\tm_BitStream;\r\n\tint \t\t\t\t\tm_Handle;\r\n\tGameNet::PlayerInfo* \tm_Player;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Classes\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/* Create all network-related tasks and handlers                  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tSkate::net_setup( void )\r\n{\r\n\t// Server net tasks\r\n\tm_object_update_task = new Tsk::Task< Skate > ( Skate::s_object_update_code, *this,\r\n\t\t\t\t\t\t\t\t\t\tTsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_OBJECT_UPDATE );\r\n\tm_score_update_task = new Tsk::Task< Skate > ( Skate::s_score_update_code, *this,\r\n \t\t\t\t\t\t\t\t\t\tTsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_SCORE_UPDATE );\r\n}\r\n\r\n/******************************************************************/\r\n/* delete all network-related tasks and handlers                  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tSkate::net_shutdown( void )\r\n{\r\n\t// Server net tasks\r\n\tdelete m_object_update_task;\r\n\tdelete m_score_update_task;\r\n}\r\n\r\n/******************************************************************/\r\n/* Determines whether we should send \"send_player\" an update \t  */\r\n/* concerning \"object\"                                            */\r\n/******************************************************************/\r\n\r\nbool\t\tSkate::should_send_update( GameNet::PlayerInfo* send_player, Obj::CObject* object )\r\n{\r\n\tObj::SPosEvent* latest_state;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tGameNet::PlayerInfo* skater_player;\r\n\tObj::CSkater* skater_obj;\r\n\tint id, index;\r\n\t\r\n\t// Dont send a client updates on his own skater. He is up to date.\r\n\tskater_player = gamenet_man->GetPlayerByObjectID( object->GetID() );\r\n\tif(\t( skater_player == NULL ) ||\r\n\t\t( skater_player == send_player ))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tskater_obj = skater_player->m_Skater;\r\n\t// Check if we have something to report\r\n\tif( skater_obj->GetStateHistory()->GetNumPosUpdates() == 0 )\r\n\t{\r\n\t\t//Dbg_Printf( \"Not enough pos updates\\n\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tid = skater_obj->GetID();\r\n\tindex = ( skater_obj->GetStateHistory()->GetNumPosUpdates() - 1 ) % Obj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\tlatest_state = &skater_obj->GetStateHistory()->GetPosHistory()[index];\r\n\r\n\t// Only send an update if there's something new to tell\r\n\tif( latest_state->LoTime == send_player->m_LastSentProps.m_LastSkaterUpdateTime[id] )\r\n\t{\r\n\t\t//Dbg_Printf( \"Nothing new to tell\\n\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/* Decide which fields need to be updated for this object\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic\tint\t\ts_get_update_flags( GameNet::PlayerInfo* player, \r\n\t\t\t\t\t\t\t\t\tObj::SPosEvent* latest_state,\r\n\t\t\t\t\t\t\t\t\tint skater_id ) \r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tint i, update_flags;\r\n\tshort pos[3];\r\n\tshort rot[3];\r\n\tFlags< int > skater_flags;\r\n\tFlags< int > end_run_flags;\r\n\tMth::Vector eulers;\r\n\tchar state, doing_trick, terrain, walking, driving;\r\n\tbool forced_send;\r\n\tunsigned char id;\r\n\tsint16 rail_node;\r\n\r\n\tupdate_flags = 0;\r\n\r\n\t// Force an object update every N frames\r\n\tforced_send = !( gamenet_man->GetServer()->m_FrameCounter % vFORCE_UPDATE_INTERVAL ); \r\n\tid = skater_id;\r\n\r\n\tfor( i = 0; i < 3; i++ )\r\n\t{\r\n\t\teulers[i] = latest_state->Eulers[i];\r\n\t}\r\n\r\n\t// Write out the object's position as three shorts (fixed-point)\r\n\tfor( i = 0; i < 3; i++ )\r\n\t{\r\n\t\tif( i == Y )\r\n\t\t{\r\n\t\t\tpos[i] = (short) ( latest_state->Position[i] * 4.0f );\r\n\t\t\t//pos[i] = latest_state->Position[i];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpos[i] = (short) ( latest_state->Position[i] * 2.0f );\r\n\t\t\t//pos[i] = latest_state->Position[i];\r\n\t\t}\r\n\t\tif(( pos[i] != player->m_LastSentProps.m_LastSkaterPosUpdate[id][i] ) || forced_send )\r\n\t\t{\r\n\t\t\tif( i == X )\r\n\t\t\t{\r\n\t\t\t\tupdate_flags |= GameNet::mUPDATE_FIELD_POS_X;\r\n\t\t\t}\r\n\t\t\telse if( i == Y )\r\n\t\t\t{\r\n\t\t\t\tupdate_flags |= GameNet::mUPDATE_FIELD_POS_Y;\r\n\t\t\t}\r\n\t\t\telse if( i == Z )\r\n\t\t\t{\r\n\t\t\t\tupdate_flags |= GameNet::mUPDATE_FIELD_POS_Z;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Write out the object's orientation as three short euler angles (fixed-point)\r\n\tfor( i = 0; i < 3; i++ )\r\n\t{\r\n\t\trot[i] = (short) ( eulers[i] * 4096.0f );\r\n\t\tif(( rot[i] != player->m_LastSentProps.m_LastSkaterRotUpdate[id][i] ) || forced_send )\r\n\t\t{   \r\n\t\t\tif( i == X )\r\n\t\t\t{\r\n\t\t\t\tupdate_flags |= GameNet::mUPDATE_FIELD_ROT_X;\r\n\t\t\t}\r\n\t\t\telse if( i == Y )\r\n\t\t\t{\r\n\t\t\t\tupdate_flags |= GameNet::mUPDATE_FIELD_ROT_Y;\r\n\t\t\t}\r\n\t\t\telse if( i == Z )\r\n\t\t\t{\r\n\t\t\t\tupdate_flags |= GameNet::mUPDATE_FIELD_ROT_Z;\r\n\t\t\t}\r\n\t\t}\r\n\t}                                          \r\n\r\n\tstate = (char) latest_state->State;\r\n\tdoing_trick = (char) latest_state->DoingTrick;\r\n\tterrain = (char) latest_state->Terrain;\r\n\twalking = (char) latest_state->Walking;\r\n\tdriving = (char) latest_state->Driving;\r\n\r\n\tif(( state != player->m_LastSentProps.m_LastSkaterStateUpdate[id] ) ||\r\n\t   ( doing_trick != player->m_LastSentProps.m_LastDoingTrickUpdate[id] ) ||\r\n\t   ( terrain != player->m_LastSentProps.m_LastSkaterTerrain[id] ) || \r\n\t   ( walking != player->m_LastSentProps.m_LastSkaterWalking[id] ) || \r\n\t   ( driving != player->m_LastSentProps.m_LastSkaterDriving[id] ) || \r\n\t   ( forced_send == true ))\r\n\t{\r\n\t\tupdate_flags |= GameNet::mUPDATE_FIELD_STATE;\r\n\t}\r\n\r\n\tskater_flags = latest_state->SkaterFlags;\r\n\tend_run_flags = latest_state->EndRunFlags;\r\n\r\n\tif(( skater_flags != player->m_LastSentProps.m_LastSkaterFlagsUpdate[id] ) || \r\n\t   ( end_run_flags != player->m_LastSentProps.m_LastEndRunFlagsUpdate[id] ) || \r\n\t   ( forced_send == true ))\r\n\t{\r\n\t\tupdate_flags |= GameNet::mUPDATE_FIELD_FLAGS;\r\n\t}\r\n\r\n\trail_node = latest_state->RailNode;\r\n\tif(( rail_node != player->m_LastSentProps.m_LastRailNodeUpdate[id] ) ||\r\n\t   ( forced_send == true ))\r\n\t{\r\n\t\tupdate_flags |= GameNet::mUPDATE_FIELD_RAIL_NODE;\r\n\t}\r\n\r\n\treturn update_flags;\r\n}\r\n\r\n/******************************************************************/\r\n/* Place positional/state update data in the outbound stream\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tSkate::s_object_update( Obj::CObject* object, void* data )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tGameNet::PlayerInfo* player, *skater_player;\r\n\tObjUpdateInfo* update_info;\r\n\tObj::CSkater* skater_obj;\r\n\tMth::Vector eulers;\r\n\tshort pos[3];\r\n\tshort rot[3];\r\n\tunsigned char id;\r\n\tchar state, doing_trick, terrain, walking, driving;\r\n\tFlags< int > skater_flags;\r\n\tFlags< int > end_run_flags;\r\n\tint update_flags;\r\n\tObj::SPosEvent* latest_state;\r\n\tint i, index;\r\n\tunsigned short time;\r\n\t\r\n\tDbg_Assert( data );\r\n\r\n\tupdate_info = (ObjUpdateInfo *) data;\r\n\r\n\tskater_player = gamenet_man->GetPlayerByObjectID( object->GetID() );\r\n\tskater_obj = skater_player->m_Skater;\r\n\tid = (char) skater_obj->GetID();\r\n\tplayer = update_info->m_Player;\r\n\tindex = ( skater_obj->GetStateHistory()->GetNumPosUpdates() - 1 ) % Obj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\tlatest_state = &skater_obj->GetStateHistory()->GetPosHistory()[index];\r\n\tplayer->m_LastSentProps.m_LastSkaterUpdateTime[id] = latest_state->GetTime();\r\n\r\n\tfor( i = 0; i < 3; i++ )\r\n\t{\r\n\t\teulers[i] = latest_state->Eulers[i];\r\n\t}\r\n\r\n\ttime = latest_state->LoTime;\r\n\tupdate_info->m_BitStream.WriteValue( time, sizeof( uint16 ) * 8 );\r\n\r\n\tupdate_flags = s_get_update_flags( player, latest_state, id );\r\n\tupdate_info->m_BitStream.WriteValue( update_flags, 9 );\r\n\r\n\t//Dbg_Printf( \"*** Sending Pos[%.2f %.2f %.2f]\\n\", latest_state->Position[X], latest_state->Position[Y], latest_state->Position[Z] );\r\n\t// Write out the object's position as three shorts (fixed-point)\r\n\tfor( i = 0; i < 3; i++ )\r\n\t{\r\n\t\tif( i == Y )\r\n\t\t{\r\n\t\t\tpos[i] = (short) ( latest_state->Position[i] * 4.0f );\r\n\t\t\t//pos[i] = latest_state->Position[i];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpos[i] = (short) ( latest_state->Position[i] * 2.0f );\r\n\t\t\t//pos[i] = latest_state->Position[i];\r\n\t\t}\r\n\t\t\r\n\t\tif( i == X )\r\n\t\t{\r\n\t\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_X )\r\n\t\t\t{\r\n\t\t\t\tupdate_info->m_BitStream.WriteValue( pos[i], sizeof( short ) * 8 );\r\n\t\t\t\t//update_info->m_BitStream.WriteFloatValue( pos[i] );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( i == Y )\r\n\t\t{\r\n\t\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_Y )\r\n\t\t\t{\r\n\t\t\t\tupdate_info->m_BitStream.WriteValue( pos[i], sizeof( short ) * 8 );\r\n\t\t\t\t//update_info->m_BitStream.WriteFloatValue( pos[i] );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( i == Z )\r\n\t\t{\r\n\t\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_Z )\r\n\t\t\t{\r\n\t\t\t\tupdate_info->m_BitStream.WriteValue( pos[i], sizeof( short ) * 8 );\r\n\t\t\t\t//update_info->m_BitStream.WriteFloatValue( pos[i] );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tplayer->m_LastSentProps.m_LastSkaterPosUpdate[id][i] = pos[i];\r\n\t}\r\n\t\r\n\t// Write out the object's orientation as three short euler angles (fixed-point)\r\n\tfor( i = 0; i < 3; i++ )\r\n\t{\r\n\t\trot[i] = (short) ( eulers[i] * 4096.0f );\r\n\t\tif( i == X )\r\n\t\t{\r\n\t\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_X )\r\n\t\t\t{\r\n\t\t\t\tupdate_info->m_BitStream.WriteValue( rot[i], sizeof( short ) * 8 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( i == Y )\r\n\t\t{\r\n\t\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_Y )\r\n\t\t\t{\r\n\t\t\t\tupdate_info->m_BitStream.WriteValue( rot[i], sizeof( short ) * 8 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( i == Z )\r\n\t\t{\r\n\t\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_Z )\r\n\t\t\t{\r\n\t\t\t\tupdate_info->m_BitStream.WriteValue( rot[i], sizeof( short ) * 8 );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tplayer->m_LastSentProps.m_LastSkaterRotUpdate[id][i] = rot[i];\r\n\t}                                          \r\n\r\n\tstate = (char) latest_state->State;\r\n\tdoing_trick = (char) latest_state->DoingTrick;\r\n\tterrain = (char) latest_state->Terrain;\r\n\twalking = (char) latest_state->Walking;\r\n\tdriving = (char) latest_state->Driving;\r\n\r\n\t// Write out the skaters' state\r\n\t// Write out the skater's \"doing trick\" flag\r\n\t// Write out the skater's terrain type\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_STATE )\r\n\t{\r\n\t\tchar mask;\r\n\r\n\t\tmask = state;\r\n\t\tif( doing_trick )\r\n\t\t{\r\n\t\t\tmask |= GameNet::mDOING_TRICK_MASK;\r\n\t\t}\r\n\r\n\t\tupdate_info->m_BitStream.WriteValue( mask, 4 );\r\n\t\tupdate_info->m_BitStream.WriteValue( terrain, 6 );\r\n\t\tupdate_info->m_BitStream.WriteValue( walking, 1 );\r\n\t\tupdate_info->m_BitStream.WriteValue( driving, 1 );\r\n\r\n\t\tplayer->m_LastSentProps.m_LastSkaterStateUpdate[id] = state;\r\n\t\tplayer->m_LastSentProps.m_LastDoingTrickUpdate[id] = doing_trick;\r\n\t\tplayer->m_LastSentProps.m_LastSkaterTerrain[id] = terrain;\r\n\t\tplayer->m_LastSentProps.m_LastSkaterWalking[id] = walking;\r\n\t\tplayer->m_LastSentProps.m_LastSkaterDriving[id] = driving;\r\n\t}\r\n\r\n\t// Write out the skaters' flags\r\n\tskater_flags = latest_state->SkaterFlags;\r\n\tend_run_flags = latest_state->EndRunFlags;\r\n\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_FLAGS )\r\n\t{\r\n\t\tplayer->m_LastSentProps.m_LastSkaterFlagsUpdate[id] = skater_flags;\r\n\t\tplayer->m_LastSentProps.m_LastEndRunFlagsUpdate[id] = end_run_flags;\r\n\t\tupdate_info->m_BitStream.WriteValue( skater_flags, 5 );\r\n\t\tupdate_info->m_BitStream.WriteValue( end_run_flags, 3 );\r\n\t}\r\n\r\n\t// Write out the skaters' rail node\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_RAIL_NODE )\r\n\t{\r\n\t\tplayer->m_LastSentProps.m_LastRailNodeUpdate[id] = latest_state->RailNode;\r\n\t\tupdate_info->m_BitStream.WriteValue( latest_state->RailNode, sizeof( sint16 ) * 8 );\r\n\t}\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/* Update Clients with objects' positional/rotational/anim data\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tSkate::s_object_update_code ( const Tsk::Task< Skate >& task )\r\n{   \r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tGameNet::PlayerInfo* player;\r\n\tLst::Search< GameNet::PlayerInfo > sh;\r\n\tNet::Server* server;\r\n    \r\n    Dbg_AssertType ( &task, Tsk::Task< Skate > );\r\n\tSkate& mdl = task.GetData();\r\n\t\r\n    server = gamenet_man->GetServer();\r\n\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = \r\n\t\t\t\tgamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tNet::MsgMax update_msg;\r\n\t\tunsigned int length;\r\n\t\tObjUpdateInfo update_info;\r\n\t\tGameNet::PlayerInfo* update_player;\r\n\t\tint i, start_id, obj_id, num_updates;\r\n        \r\n\t\t// Don't send updates to the local client. His stuff is already up-to-date\r\n\t\tif( player->m_Conn->IsRemote())\r\n\t\t{\r\n\t\t\tint obj_id_mask;\r\n\r\n\t\t\tupdate_info.m_BitStream.SetOutputData( update_msg.m_Data, 4096 );\t// skip Obj ID Mask\r\n\t\t\tupdate_info.m_Handle = player->m_Conn->GetHandle();\r\n\t\t\tupdate_info.m_Player = player;\r\n\t\t\t\t\t\r\n\t\t\tobj_id_mask = 0;\r\n\r\n\t\t\t// First decide which objects' updates we will send, then append them to the stream\r\n\t\t\t// in increasing id order \r\n\t\t\tnum_updates = 0;\r\n\t\t\tstart_id = ( player->GetLastObjectUpdateID() + 1 ) % vMAX_SKATERS;\r\n\t\t\tfor( i = 0; i < vMAX_SKATERS; i++ )\r\n\t\t\t{\r\n\t\t\t\tobj_id = ( start_id + i ) % vMAX_SKATERS;\r\n\t\t\t\tupdate_player = gamenet_man->GetPlayerByObjectID( obj_id );\r\n\t\t\t\tif( update_player )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( mdl.should_send_update( player, update_player->m_Skater ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tobj_id_mask |= ( 1 << obj_id );\r\n\t\t\t\t\t\tif( ++num_updates >= player->GetMaxObjectUpdates())\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif( num_updates == 0 )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tupdate_info.m_BitStream.WriteValue( obj_id_mask, sizeof( char ) * 8 );\r\n\t\t\tfor( i = 0; i < vMAX_SKATERS; i++ )\r\n\t\t\t{\r\n\t\t\t\tif( obj_id_mask & ( 1 << i ))\r\n\t\t\t\t{\r\n\t\t\t\t\tupdate_player = gamenet_man->GetPlayerByObjectID( i );\r\n\r\n\t\t\t\t\ts_object_update( update_player->m_Skater, &update_info );\r\n\t\t\t\t\tplayer->SetLastObjectUpdateID( i );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tupdate_info.m_BitStream.Flush();\r\n\t\t\tlength = update_info.m_BitStream.GetByteLength();\r\n\r\n\t\t\tif( length > 0 )\r\n\t\t\t{   \r\n\t\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\t\tmsg_desc.m_Data = &update_msg;\r\n\t\t\t\tmsg_desc.m_Length = length;\r\n\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_OBJ_UPDATE_STREAM;\r\n\t\t\t\tserver->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/* Update Clients with other players' scores\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tSkate::SendScoreUpdates( bool final )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tGameNet::PlayerInfo* player, *score_player;\r\n\tLst::Search< GameNet::PlayerInfo > sh, score_sh;\r\n\r\n    for( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = \r\n\t\t\t\tgamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tGameNet::MsgScoreUpdate score_msg;\r\n\t\tchar num_scores;\r\n\t\tint length;\r\n\t\tchar* data;\r\n        \r\n\t\tscore_msg.m_Final = (char) final;\r\n\t\tif( final )\r\n\t\t{\r\n\t\t\tscore_msg.m_TimeLeft = 0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tscore_msg.m_TimeLeft = Tmr::InSeconds( GetGameMode()->GetTimeLeft());\r\n\t\t}\r\n\t\tnum_scores = 0;\r\n\t\tdata = score_msg.m_ScoreData;\r\n\t\tfor( score_player = gamenet_man->FirstPlayerInfo( score_sh ); score_player; score_player = \r\n\t\t\tgamenet_man->NextPlayerInfo( score_sh ))\r\n\t\t{\r\n\t\t\tbool send_all_scores;\r\n\r\n\t\t\tsend_all_scores = \tfinal ||\r\n\t\t\t\t\t\t\t\t( GetGameMode()->IsTrue( \"should_modulate_color\" )) ||\r\n\t\t\t\t\t\t\t\t( GetGameMode()->ShouldTrackTrickScore() == false );\r\n\t\t\tif( ( score_player != player ) || ( send_all_scores ) )\r\n\t\t\t{\r\n\t\t\t\tchar id;\r\n\t\t\t\tint score;\r\n\t\t\t\tbool in_goal_attack;\r\n\t\t\t\t\r\n\t\t\t\tid = (char) score_player->m_Skater->GetID();\r\n\t\t\t\tin_goal_attack = GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netgoalattack\" );\r\n\r\n\t\t\t\tif( in_goal_attack )\r\n\t\t\t\t{\r\n\t\t\t\t\tGame::CGoalManager* pGoalManager;\r\n\t\t\t \r\n\t\t\t\t\tpGoalManager = Game::GetGoalManager();\r\n\t\t\t\t\tscore = pGoalManager->NumGoalsBeatenBy( score_player->m_Skater->GetID());\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tscore = gamenet_man->GetPlayerScore( score_player->m_Skater->GetID());\r\n\t\t\t\t}\r\n\r\n\t\t\t\t*data = id;\r\n\t\t\t\tdata++;\r\n\t\t\t\tmemcpy( data, &score, sizeof( int ));\r\n\t\t\t\tdata += sizeof( int );\r\n\r\n\t\t\t\tnum_scores++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( num_scores > 0 )\r\n\t\t{\r\n\t\t\tNet::MsgDesc msg_desc;\r\n            \r\n\t\t\tscore_msg.m_Cheats = GetCheatChecksum();\r\n\t\t\tscore_msg.m_NumScores = num_scores;\r\n\t\t\tlength = \tsizeof( int ) +\t\t// m_TimeLeft\r\n\t\t\t\t\t\tsizeof( int ) +\t\t// m_Cheats\r\n\t\t\t\t\t\tsizeof( char ) + \t// m_Final\r\n\t\t\t\t\t\tsizeof( char ) +\t// m_NumScores\r\n\t\t\t\t\t\t(( sizeof( char ) + sizeof( int )) * num_scores );\r\n\r\n\t\t\tmsg_desc.m_Data = &score_msg;\r\n\t\t\tmsg_desc.m_Length = length;\r\n\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_SCORE_UPDATE;\r\n\t\t\t// If it's the final tally or if it's reporting cheats, it HAS to get there\r\n\t\t\tif( final || ( score_msg.m_Cheats != 0 ))\r\n\t\t\t{\r\n\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t}\r\n\r\n\t\t\tgamenet_man->GetServer()->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\r\n\t\t\tif( !player->IsLocalPlayer() && player->IsFullyIn())\r\n\t\t\t{\r\n\t\t\t\tGameNet::MsgCheatChecksum cheat_msg;\r\n\r\n\t\t\t\tcheat_msg.m_ServerChecksum = GetCheatChecksum();\r\n\t\t\t\tcheat_msg.m_ServerChecksum ^= 0xDEADFACE;\r\n\t\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_CHEAT_CHECKSUM_REQUEST;\r\n\t\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t\tmsg_desc.m_Data = &cheat_msg;\r\n\t\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgCheatChecksum );\r\n\t\r\n\t\t\t\tgamenet_man->GetServer()->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tgamenet_man->SetLastScoreUpdateTime( gamenet_man->GetServer()->m_Timestamp );\r\n}\r\n\r\n/******************************************************************/\r\n/* Periodic task to update Clients with other players' scores\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tSkate::s_score_update_code ( const Tsk::Task< Skate >& task )\r\n{   \r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tSkate&\tmdl = task.GetData();\r\n\r\n\t\r\n\r\n\tDbg_AssertType ( &task, Tsk::Task< Skate > );\r\n\r\n\tif( gamenet_man->ShouldSendScoreUpdates() == false )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif(( gamenet_man->GetServer()->m_Timestamp - gamenet_man->GetLastScoreUpdateTime()) <\r\n\t\t\tGameNet::vSCORE_UPDATE_FREQUENCY )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tmdl.SendScoreUpdates();\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\tServer Handlers\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/* The client has requested a score event.  Decide whether or not */\r\n/* to allow it (don't allow it if time is up, for example), and   */\r\n/* relay the results back whenever we want to (which right now is */\r\n/* immediately, but it doesn't have to be)\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_score_request( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::MsgEmbedded* msg;\r\n\tGameNet::PlayerInfo* player;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n    \r\n\tmsg = (GameNet::MsgEmbedded* ) context->m_Msg;\r\n\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tif( player == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n    \r\n\tMdl::Score *pScore = player->m_Skater->GetScoreObject();\r\n\r\n\tswitch( msg->m_SubMsgId )\r\n\t{\r\n\t\tcase GameNet::SCORE_MSG_ID_LOG_TRICK_OBJECT:\r\n\t\t{\r\n\t\t\tGameNet::MsgScoreLogTrickObject* log_msg;\r\n\t\t\t\r\n\t\t\tlog_msg = (GameNet::MsgScoreLogTrickObject* ) context->m_Msg;\r\n\t\t\tif( log_msg->m_GameId == gamenet_man->GetNetworkGameId())\r\n\t\t\t{\r\n\t\t\t\tpScore->LogTrickObject( log_msg->m_OwnerId, log_msg->m_Score, log_msg->m_NumPendingTricks, log_msg->m_PendingTrickBuffer, true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Skater is reporting his high combo\t\t\t\t\t\t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Skate::handle_combo_report( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::PlayerInfo* player;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tSkate* skate_mod;\r\n\tGameNet::MsgScoreLanded* msg;\r\n    \r\n\tskate_mod = (Skate*) context->m_Data;\r\n\r\n\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tif( player == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\tmsg = (GameNet::MsgScoreLanded*) context->m_Msg;\r\n\r\n\t// Ignore combo messages in freeskate\r\n\tif( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0x1c471c60,\"netlobby\"))\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\t// Make sure this reported score is for this game (could be late -- could be a cheat replay packet)\r\n    if( gamenet_man->GetNetworkGameId() != msg->m_GameId )\r\n\t{\r\n\t\tDbg_Printf( \"Wrong game id! %d %d\\n\", gamenet_man->GetNetworkGameId(), msg->m_GameId );\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\t// We should never get a score that's less than or equal to our recorded best combo for this\r\n\t// player since they are only supposed to report combo scores if they eclipse their current\r\n\t// mark.  This is most-likely cheating\r\n\t/*if( msg->m_Score <= player->m_BestCombo )\r\n\t{\r\n\t\tDbg_Printf( \"**** COMBO CHEAT DETECTED: Combo reported: %d , previous best: %d\\n\", msg->m_Score, player->m_BestCombo );\r\n\t\tgamenet_man->CheatingOccured();\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}*/\r\n\r\n\t//Dbg_Printf( \"Player: %d  Combo: %d\\n\", player->m_Skater->GetID(), msg->m_Score );\r\n\tplayer->m_BestCombo = msg->m_Score;\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Skater landed a trick and is reporting his score\t\t  \t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Skate::handle_landed_trick( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::PlayerInfo* player;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tint trick_score;\r\n\tSkate* skate_mod;\r\n\tGameNet::MsgScoreLanded* msg;\r\n    \r\n\tskate_mod = (Skate*) context->m_Data;\r\n\r\n\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tif( player == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\tmsg = (GameNet::MsgScoreLanded*) context->m_Msg;\r\n\r\n\t// Make sure this reported score is for this game (could be late -- could be a cheat replay packet)\r\n    if( gamenet_man->GetNetworkGameId() != msg->m_GameId )\r\n\t{\r\n\t\tDbg_Printf( \"Wrong game id! %d %d\\n\", gamenet_man->GetNetworkGameId(), msg->m_GameId );\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\ttrick_score = msg->m_Score;\r\n\tMdl::Score *pScore = player->m_Skater->GetScoreObject();\r\n\r\n\tif( trick_score > pScore->GetBestCombo())\r\n\t{\r\n\t\tpScore->SetBestCombo( trick_score );\r\n\t}\r\n\tif ( !skate_mod->GetGameMode()->IsTrue(\"should_modulate_color\") )\r\n\t{\r\n\t\tif( skate_mod->GetGameMode()->ShouldTrackTrickScore())\r\n\t\t{\r\n\t\t\tif (skate_mod->GetGameMode()->ShouldAccumulateScore())\r\n\t\t\t{\r\n\t\t\t\tpScore->SetTotalScore( pScore->GetTotalScore() + trick_score );\r\n\t\t\t}\r\n\t\t\telse if( skate_mod->GetGameMode()->ShouldTrackBestCombo())\r\n\t\t\t{\r\n\t\t\t\tif( pScore->GetTotalScore() < trick_score )\r\n\t\t\t\t{\r\n\t\t\t\t\tpScore->SetTotalScore( trick_score );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Skater is entering a car\t\t\t\t\t\t\t\t  \t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Skate::handle_enter_vehicle_server( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::PlayerInfo* player;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tSkate* skate_mod;\r\n\tGameNet::MsgEnterVehicle* msg;\r\n    \r\n\tskate_mod = (Skate*) context->m_Data;\r\n\r\n\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tif( player == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\tmsg = (GameNet::MsgEnterVehicle*) context->m_Msg;\r\n\t\r\n\tplayer->m_VehicleControlType = msg->m_ControlType;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Relay non-important msgs to all other clients\t\t  \t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_msg_relay( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tLst::Search< GameNet::PlayerInfo > sh;\r\n\tGameNet::PlayerInfo* player, *orig_player;\r\n\r\n\torig_player = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\r\n\t// Make sure this is from a current player\r\n\tif( orig_player == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player;\r\n\t\t\tplayer = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t// Don't relay it back to the original client\r\n\t\tif( player == orig_player )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tmsg_desc.m_Data = context->m_Msg;\r\n\t\tmsg_desc.m_Length = context->m_MsgLength;\r\n\t\tmsg_desc.m_Id = context->m_MsgId;\r\n\t\tif( ( context->m_MsgId == GameNet::MSG_ID_BLOOD_OFF ) ||\r\n\t\t\t( context->m_MsgId == GameNet::MSG_ID_CHAT ) ||\r\n\t\t\t( context->m_MsgId == GameNet::MSG_ID_ENTER_VEHICLE ))\r\n\t\t{\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t}\r\n\t\telse if( context->m_MsgId == GameNet::MSG_ID_SPAWN_PROJECTILE )\r\n\t\t{\r\n\t\t\tSkate* mod = (Skate*) context->m_Data;\r\n\r\n\t\t\tif(\t( mod->GetGameMode()->GetNameChecksum() == CRCD(0x3d6d444f,\"firefight\") ) ||\r\n\t\t\t\t( mod->GetGameMode()->GetNameChecksum() == CRCD(0xbff33600,\"netfirefight\")))\r\n\t\t\t{\r\n\t\t\t\tGameNet::MsgProjectile* msg;\r\n\t\r\n\t\t\t\tmsg = (GameNet::MsgProjectile*) context->m_Msg;\r\n\t\t\t\tif( ( msg->m_Scale <= 10.0f ) &&\r\n\t\t\t\t\t( msg->m_Radius <= 240 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tmsg->m_Id = orig_player->m_Skater->GetID();\r\n\t\t\t\t\tmsg->m_Latency = context->m_Conn->GetAveLatency();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\t\r\n\t\tcontext->m_App->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t}\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Relay script msgs to nearby clients only\t\t  \t\t  \t  \t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_selective_msg_relay( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tLst::Search< GameNet::PlayerInfo > sh;\r\n\tGameNet::PlayerInfo* player, *orig_player;\r\n\tObj::CSkater* orig_skater, *skater;\r\n\r\n\torig_player = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\r\n\t// Make sure this is from a current player\r\n\tif( orig_player == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\torig_skater = orig_player->m_Skater;\r\n\tif( orig_skater == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player;\r\n\t\t\tplayer = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tbool send;\r\n\r\n\t\tsend = false;\r\n\t\t// Don't relay it back to the original client\r\n\t\tif( player != orig_player )\r\n\t\t{\r\n\t\t\tif( player->IsObserving())\r\n\t\t\t{\r\n\t\t\t\tsend = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tskater = player->m_Skater;\r\n\t\t\t\tif( skater )\r\n\t\t\t\t{\r\n\t\t\t\t\tMth::Vector diff;\r\n\r\n\t\t\t\t\tdiff = skater->GetPos() - orig_skater->GetPos();\r\n\t\t\t\t\tif( diff.Length() < vOBJ_UPDATE_THRESHOLD )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsend = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( send )\r\n\t\t{\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\tmsg_desc.m_Data = context->m_Msg;\r\n\t\t\tmsg_desc.m_Length = context->m_MsgLength;\r\n\t\t\tmsg_desc.m_Id = context->m_MsgId;\r\n\t\t\tcontext->m_App->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t}\r\n\t}\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Relay script msgs to all other clients\t\t  \t\t  \t  \t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_script_relay( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tLst::Search< GameNet::PlayerInfo > sh;\r\n\tGameNet::PlayerInfo* player, *orig_player;\r\n\r\n\torig_player = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\r\n\t// Make sure this is from a current player\r\n\tif( orig_player == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player;\r\n\t\t\tplayer = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t{\r\n\t\tNet::MsgDesc msg_desc;\r\n\t\t\r\n\t\t// Don't relay it back to the original client\r\n\t\tif( player == orig_player )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tmsg_desc.m_Data = context->m_Msg;\r\n\t\tmsg_desc.m_Length = context->m_MsgLength;\r\n\t\tmsg_desc.m_Id = context->m_MsgId;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\tcontext->m_App->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t}\r\n\r\n\tif( context->m_MsgId == GameNet::MSG_ID_SPAWN_AND_RUN_SCRIPT )\r\n\t{\r\n\t\tGameNet::MsgSpawnAndRunScript* msg;\r\n\r\n\t\tmsg = (GameNet::MsgSpawnAndRunScript *) context->m_Msg;\r\n\r\n\t\t// Only save the event if it changes the level in a permanent way\r\n\t\tif( msg->m_Permanent )\r\n\t\t{\r\n\t\t\tgamenet_man->AddSpawnedTriggerEvent( msg->m_Node, msg->m_ObjID, msg->m_ScriptName );\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Relay non-important msgs to all other clients\t\t  \t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_bail_done( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tGameNet::PlayerInfo* player;\r\n    \r\n\tplayer = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\tif( player )\r\n\t{\r\n\t\tplayer->ClearNonCollidable();\r\n\t}\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Change levels\t  \t\t\t\t\t\t\t\t\t\t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_change_level( Net::MsgHandlerContext* context )\r\n{\r\n\tSkate* skate;\r\n\tskate = (Skate*)context->m_Data;\r\n\r\n\tGameNet::MsgChangeLevel* pMsg;\r\n\tpMsg = (GameNet::MsgChangeLevel*) context->m_Msg;\r\n\t\r\n\tskate->ChangeLevel( pMsg->m_Level );\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Receive and store client skater states for relay later on\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Skate::handle_object_update( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tObj::CSkater* skater;\r\n\tGameNet::PlayerInfo* player;\r\n\tint i, index, last_index;\r\n\tunsigned int timestamp;\r\n\tchar state, doing_trick, terrain, walking, driving;\r\n\tFlags< int > skater_flags;\r\n\tFlags< int > end_run_flags;\r\n\tshort pos[3];\r\n\tMth::Vector eulers;\r\n\tsint16 rail_node;\r\n    short fixed;\r\n\tint update_flags;\r\n\tObj::SPosEvent* latest_state, *previous_state;\r\n\tNet::BitStream stream;\r\n\r\n    player = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\r\n\t// Ignore late/foreign updates and update from non-ready/non-existent clients\r\n\tif( ( player == NULL ) || \r\n\t\t( player->m_Conn->TestStatus( Net::Conn::mSTATUS_READY ) == false ) ||\r\n        ( context->m_PacketFlags & ( Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN )))\r\n\t{\r\n\t\tint size, value, bit_data;\r\n\r\n\t\tsize = 0;\r\n\t\tbit_data = 0;\r\n\t\t\r\n\t\t// Even though we don't process the data, we need to calculate the msg length\r\n\t\t// so that dispatcher knows how many bytes to skip\r\n\t\tstream.SetInputData( context->m_Msg, 1024 );\r\n\r\n\t\tbit_data += sizeof( int ) * 8;\t// Timestamp size\r\n\t\tvalue = stream.ReadSignedValue( sizeof( int ) * 8 );\r\n\t\tupdate_flags = stream.ReadUnsignedValue( 9 );\r\n\t\tbit_data += 9;\r\n\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_X )\r\n\t\t{\r\n\t\t\t//bit_data += sizeof( float ) * 8;\r\n\t\t\tbit_data += sizeof( short ) * 8;\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_Y )\r\n\t\t{\r\n\t\t\t//bit_data += sizeof( float ) * 8;\r\n\t\t\tbit_data += sizeof( short ) * 8;\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_Z )\r\n\t\t{\r\n\t\t\t//bit_data += sizeof( float ) * 8;\r\n\t\t\tbit_data += sizeof( short ) * 8;\r\n\t\t}   \r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_X )\r\n\t\t{\r\n\t\t\tbit_data += sizeof( short ) * 8;\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_Y )\r\n\t\t{\r\n\t\t\tbit_data += sizeof( short ) * 8;\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_Z )\r\n\t\t{\r\n\t\t\tbit_data += sizeof( short ) * 8;\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_STATE )\r\n\t\t{   \r\n\t\t\tbit_data += 12;\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_FLAGS )\r\n\t\t{\r\n\t\t\tbit_data += 5;\r\n\t\t\tbit_data += 3;\r\n\t\t}              \r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_RAIL_NODE )\r\n\t\t{\r\n\t\t\tbit_data += 16;\r\n\t\t}\r\n\r\n\t\tsize += (( bit_data + 7 ) >> 3 );\r\n\r\n\t\tcontext->m_MsgLength = size;\r\n\t\treturn Net::HANDLER_CONTINUE;\r\n\t}\r\n\r\n\tskater = player->m_Skater;\r\n\tif( skater == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\t\r\n\tindex = skater->GetStateHistory()->GetNumPosUpdates() % Obj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\tlatest_state = &skater->GetStateHistory()->GetPosHistory()[index];\r\n\tprevious_state = NULL;\r\n    \r\n\tif( skater->GetStateHistory()->GetNumPosUpdates() > 0 )\r\n\t{\r\n\t\tlast_index = ( skater->GetStateHistory()->GetNumPosUpdates() + ( Obj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS - 1 )) % \r\n\t\t\t\t\tObj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\t\tprevious_state = &skater->GetStateHistory()->GetPosHistory()[last_index];\r\n\r\n        doing_trick = previous_state->DoingTrick;\r\n\t\tstate = previous_state->State;\r\n\t\tskater_flags = previous_state->SkaterFlags;\r\n\t\tend_run_flags = previous_state->EndRunFlags;\r\n\t\tterrain = previous_state->Terrain;\r\n\t\twalking = previous_state->Walking;\r\n\t\tdriving = previous_state->Driving;\r\n\t\trail_node = previous_state->RailNode;\r\n\t\tfor( i = 0; i < 3; i++ )\r\n\t\t{\r\n\t\t\tpos[i] = previous_state->ShortPos[i];\r\n\t\t}\r\n\t\tfor( i = 0; i < 3; i++ )\r\n\t\t{\r\n\t\t\teulers[i] = previous_state->Eulers[i];\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tdoing_trick = 0;\r\n\t\tstate = 0;\r\n\t\tskater_flags = 0;\r\n\t\tend_run_flags = 0;\r\n\t\tterrain = 0;\r\n\t\twalking = 0;\r\n\t\tdriving = 0;\r\n\t\trail_node = -1;\r\n\t\tfor( i = 0; i < 3; i++ )\r\n\t\t{\r\n\t\t\tpos[i] = 0;\r\n\t\t}\r\n\t\tfor( i = 0; i < 3; i++ )\r\n\t\t{\r\n\t\t\teulers[i] = 0;\r\n\t\t}\r\n\t}\r\n\t\r\n\r\n\tstream.SetInputData( context->m_Msg, 1024 );\r\n\r\n\t// Read in timestamp\r\n\ttimestamp = stream.ReadUnsignedValue( sizeof( int ) * 8 );\r\n\tupdate_flags = stream.ReadUnsignedValue( 9 );\r\n\t\r\n\t// Read in fixed point position\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_POS_X )\r\n\t{\r\n\t\tpos[X] = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t//pos[X] = stream.ReadFloatValue();\r\n\t}\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_POS_Y )\r\n\t{\r\n\t\tpos[Y] = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t//pos[Y] = stream.ReadFloatValue();\r\n\t}\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_POS_Z )\r\n\t{\r\n\t\tpos[Z] = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t//pos[Z] = stream.ReadFloatValue();\r\n\t}   \r\n\t\t\t\r\n\t// Read in fixed point eulers\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_X )\r\n\t{\r\n\t\tfixed = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\teulers[X] = ((float) fixed ) / 4096.0f;\r\n\t}\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_Y )\r\n\t{\r\n\t\tfixed = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\teulers[Y] = ((float) fixed ) / 4096.0f;\r\n\t}\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_Z )\r\n\t{\r\n\t\tfixed = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\teulers[Z] = ((float) fixed ) / 4096.0f;\r\n\t}\r\n\r\n\t// Read in skater's 'state'\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_STATE )\r\n\t{   \r\n\t\tchar mask;\r\n\r\n\t\tmask = stream.ReadUnsignedValue( 4 );\r\n\r\n\t\tstate = mask & GameNet::mSTATE_MASK;\r\n\t\tdoing_trick = (( mask & GameNet::mDOING_TRICK_MASK ) != 0 );\r\n\t\t\r\n\t\tterrain = stream.ReadUnsignedValue( 6 );\r\n\t\t\r\n\t\twalking = stream.ReadUnsignedValue( 1 );\r\n\t\tdriving = stream.ReadUnsignedValue( 1 );\r\n\t}\r\n\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_FLAGS )\r\n\t{\r\n\t\tskater_flags = stream.ReadUnsignedValue( 5 );\r\n\t\tend_run_flags = stream.ReadUnsignedValue( 3 );\r\n\t}                           \r\n\r\n\tif( update_flags & GameNet::mUPDATE_FIELD_RAIL_NODE )\r\n\t{\r\n\t\trail_node = stream.ReadSignedValue( sizeof( sint16 ) * 8 );\r\n\t}                           \r\n\t\r\n\r\n\t// Tell the dispatcher the size of this message because it does not know (optimization)\r\n\tcontext->m_MsgLength = stream.GetByteLength();\r\n\r\n\tif( ( skater->GetStateHistory()->GetNumPosUpdates() > 0 ) &&\r\n\t\t( timestamp < previous_state->GetTime()))\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\t// Use those euler angles to compose a matrix\r\n\tMth::Matrix obj_matrix( eulers[X], eulers[Y], eulers[Z] );\r\n    \r\n\tlatest_state->Matrix = obj_matrix;\r\n\tlatest_state->Position.Set(\t((float) pos[X] ) / 2.0f,//pos[X],\r\n\t\t\t\t  \t\t\t\t((float) pos[Y] ) / 4.0f,//pos[Y],\r\n\t\t\t\t  \t\t\t\t((float) pos[Z] ) / 2.0f,//pos[Z],\r\n\t\t\t\t  \t\t\t\t0.0f );\r\n\r\n\tlatest_state->SetTime( timestamp );\r\n\r\n\t// Update short versions in the player history\r\n\tfor( i = 0; i < 3; i++ )\r\n\t{\r\n\t\tlatest_state->ShortPos[i] = pos[i];\r\n\t\tlatest_state->Eulers[i] = eulers[i];\r\n\t}\r\n\r\n\tlatest_state->DoingTrick = doing_trick;\r\n\tlatest_state->SkaterFlags = skater_flags;\r\n\tlatest_state->EndRunFlags = end_run_flags;\r\n\tlatest_state->State = state;\r\n\tlatest_state->Terrain = (ETerrainType) terrain;\r\n\tlatest_state->RailNode = rail_node;\r\n\tlatest_state->Walking = walking;\r\n\tlatest_state->Driving = driving;\r\n\r\n\tskater->GetStateHistory()->IncrementNumPosUpdates();\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\tClient Handlers\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/* Execute a script\t  \t\t\t\t\t\t\t\t\t  \t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Skate::handle_run_script( Net::MsgHandlerContext* context )\r\n{\r\n\tSkate* mod;\r\n\tGameNet::MsgRunScript* msg;\r\n    Script::CScriptStructure *pParams;\r\n\tObj::CMovingObject* obj;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\r\n\tmod = (Skate *) context->m_Data;\r\n\tmsg = (GameNet::MsgRunScript *) context->m_Msg;\r\n\r\n\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjID );\r\n\r\n    pParams = new Script::CScriptStructure;\r\n\tScript::ReadFromBuffer(pParams,(uint8 *) msg->m_Data );\r\n\r\n\tScript::RunScript( msg->m_ScriptName, pParams, obj );\r\n\r\n\tdelete pParams;\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Spawn and run a script \t\t\t\t\t\t\t\t\t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Skate::handle_spawn_run_script( Net::MsgHandlerContext* context )\r\n{\r\n\tSkate* mod;\r\n\tScript::CScript* pScript;\r\n\tObj::CMovingObject* obj;\r\n\tGameNet::MsgSpawnAndRunScript* msg;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tmod = (Skate *) context->m_Data;\r\n\tmsg = (GameNet::MsgSpawnAndRunScript *) context->m_Msg;\r\n\r\n    if( gamenet_man->ReadyToPlay())\r\n\t{\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjID );\r\n\t\r\n\t\tpScript = Script::SpawnScript( msg->m_ScriptName, NULL, 0, NULL, msg->m_Node ); // K: The 0,NULL bit means no callback script specified\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tpScript->SetCommentString(\"Spawned from Skate::handle_spawn_run_script\");\r\n\t\t#endif\r\n\t\tpScript->mpObject = obj; \r\n\r\n\t\tpScript->Update(); \r\n\t}\r\n\telse\r\n\t{\r\n\t\tgamenet_man->AddSpawnedTriggerEvent( msg->m_Node, msg->m_ObjID, msg->m_ScriptName );\r\n\t}\r\n\t\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Unpacks wobble details\t  \t\t\t\t\t\t\t\t  \t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nstatic float s_get_wobble_details_from_mask( char mask, int field )\r\n{\r\n\tfloat value;\r\n\r\n\tvalue = 0;\r\n\tswitch( field )\r\n\t{\r\n\t\tcase GameNet::MsgSetWobbleDetails::vWOBBLE_AMP_A:\r\n\t\t{\r\n\t\t\tint field_mask;\r\n\r\n\t\t\tfield_mask = mask & GameNet::MsgSetWobbleDetails::mWOBBLE_AMPA_MASK;\r\n            if( field_mask == 0 )\r\n\t\t\t{\r\n\t\t\t\tvalue = 0.05f;\r\n\t\t\t}\r\n\t\t\telse if( field_mask == 1 )\r\n\t\t\t{\r\n\t\t\t\tvalue = 0.1f;\r\n\t\t\t}\r\n\t\t\telse if( field_mask == 2 )\r\n\t\t\t{\r\n\t\t\t\tvalue = 10.1f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase GameNet::MsgSetWobbleDetails::vWOBBLE_AMP_B:\r\n\t\t{\r\n\t\t\tint field_mask;\r\n\r\n\t\t\tfield_mask = mask & GameNet::MsgSetWobbleDetails::mWOBBLE_AMPB_MASK;\r\n\t\t\tfield_mask >>= 2;\r\n            if( field_mask == 0 )\r\n\t\t\t{\r\n\t\t\t\tvalue = 0.04f;\r\n\t\t\t}\r\n\t\t\telse if( field_mask == 1 )\r\n\t\t\t{\r\n\t\t\t\tvalue = 10.1f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase GameNet::MsgSetWobbleDetails::vWOBBLE_K1:\r\n\t\t{\r\n\t\t\tint field_mask;\r\n\r\n\t\t\tfield_mask = mask & GameNet::MsgSetWobbleDetails::mWOBBLE_K1_MASK;\r\n\t\t\tfield_mask >>= 3;\r\n            if( field_mask == 0 )\r\n\t\t\t{\r\n\t\t\t\tvalue = 0.0022f;\r\n\t\t\t}\r\n\t\t\telse if( field_mask == 1 )\r\n\t\t\t{\r\n\t\t\t\tvalue = 20.0f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase GameNet::MsgSetWobbleDetails::vWOBBLE_K2:\r\n\t\t{\r\n\t\t\tint field_mask;\r\n\r\n\t\t\tfield_mask = mask & GameNet::MsgSetWobbleDetails::mWOBBLE_K2_MASK;\r\n\t\t\tfield_mask >>= 4;\r\n            if( field_mask == 0 )\r\n\t\t\t{\r\n\t\t\t\tvalue = 0.0017f;\r\n\t\t\t}\r\n\t\t\telse if( field_mask == 1 )\r\n\t\t\t{\r\n\t\t\t\tvalue = 10.0f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase GameNet::MsgSetWobbleDetails::vSPAZFACTOR:\r\n\t\t{\r\n\t\t\tint field_mask;\r\n\r\n\t\t\tfield_mask = mask & GameNet::MsgSetWobbleDetails::mSPAZFACTOR_MASK;\r\n\t\t\tfield_mask >>= 5;\r\n            if( field_mask == 0 )\r\n\t\t\t{\r\n\t\t\t\tvalue = 1.5f;\r\n\t\t\t}\r\n\t\t\telse if( field_mask == 1 )\r\n\t\t\t{\r\n\t\t\t\tvalue = 1.0f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\treturn value;\r\n}\r\n\r\n/******************************************************************/\r\n/* A client has launched a projectile\t\t\t\t\t\t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_projectile( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::MsgProjectile* msg;\r\n\tScript::CStruct* pParams;\r\n\tObj::CSkater* skater;\r\n\tSkate* mod;\r\n\tMth::Vector vel, dir, pos;\r\n\tTmr::Time lag;\r\n\tfloat time;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n    \r\n\tmod = (Skate *) context->m_Data;\r\n\r\n\tmsg = (GameNet::MsgProjectile*) context->m_Msg;\r\n\tskater = mod->GetSkaterById( msg->m_Id );\r\n\tif( skater == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\t\r\n\tvel = msg->m_Vel;\r\n\tpos = msg->m_Pos;\r\n\tdir = vel;\r\n\tdir.Normalize();\r\n\tlag = msg->m_Latency;\r\n\r\n\t// If not on the server, also add the average latency from server to us\r\n\tif( gamenet_man->OnServer() == false )\r\n\t{\r\n\t\tLst::Search< Net::Conn > sh;\r\n\t\tNet::Conn* server_conn;\r\n\r\n\t\tserver_conn = context->m_App->FirstConnection( &sh );\r\n\t\tlag += server_conn->GetAveLatency();\r\n\t}\r\n\r\n    time = (float) lag / 1000.0f;\r\n    pos += dir * time;\t// Time is in units of seconds. Velocity is in terms of feet/sec\r\n\r\n\tpParams = new Script::CStruct;\r\n\tpParams->AddChecksum( CRCD(0x81c39e06,\"owner_id\"), msg->m_Id );\r\n\tpParams->AddInteger( CRCD(0x7323e97c,\"x\"), pos[X] );\r\n\tpParams->AddInteger( CRCD(0x424d9ea,\"y\"), pos[Y] );\r\n\tpParams->AddInteger( CRCD(0x9d2d8850,\"z\"), pos[Z] );\r\n\tpParams->AddInteger( CRCD(0xbded7a76,\"scaled_x\"), msg->m_Vel[X] );\r\n\tpParams->AddInteger( CRCD(0xcaea4ae0,\"scaled_y\"), msg->m_Vel[Y] );\r\n\tpParams->AddInteger( CRCD(0x53e31b5a,\"scaled_z\"), msg->m_Vel[Z] );\r\n\tpParams->AddInteger( CRCD(0xc48391a5,\"radius\"), msg->m_Radius );\r\n\tpParams->AddFloat( CRCD(0x13b9da7b,\"scale\"), msg->m_Scale );\r\n\t\r\n\tScript::RunScript( CRCD(0xaa2b5552,\"ClientLaunchFireball\"), pParams, skater );\r\n\tdelete pParams;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* A client has entered a vehicle\t\t\t\t\t\t\t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_enter_vehicle_client( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::MsgEnterVehicle* msg;\r\n\tObj::CSkater* skater;\r\n\tSkate* mod;\r\n    \r\n\tmod = (Skate *) context->m_Data;\r\n\r\n\tmsg = (GameNet::MsgEnterVehicle*) context->m_Msg;\r\n\tskater = mod->GetSkaterById( msg->m_Id );\r\n\tif( skater == NULL )\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\t\r\n\tDbg_Assert(GetSkaterStateHistoryComponentFromObject(skater));\r\n\tGetSkaterStateHistoryComponentFromObject(skater)->SetCurrentVehicleControlType(msg->m_ControlType);\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* The server has sent a list of cheats that are enabled\t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_cheat_list( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::MsgEnabledCheats* msg;\r\n\tint i;\r\n\r\n\tDbg_Printf( \"**** HANDLING CHEAT LIST\\n\" );\r\n\tCFuncs::ScriptClearCheats( NULL, NULL );\r\n\r\n\tmsg = (GameNet::MsgEnabledCheats*) context->m_Msg;\r\n\tfor( i = 0; i < msg->m_NumCheats; i++ )\r\n\t{\r\n\t\tScript::CStruct* pParams;\r\n\r\n\t\tpParams = new Script::CStruct;\r\n\t\tpParams->AddChecksum( CRCD(0xf649d637,\"on\"), 0 );\r\n\t\tpParams->AddChecksum( CRCD(0xae94c183,\"cheat_flag\"), msg->m_Cheats[i] );\r\n\t\tScript::RunScript( CRCD(0x3cf9e86d,\"client_toggle_cheat\"), pParams );\r\n\r\n\t\tdelete pParams;\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* The server has toggled a cheat. Mimic behavior on this end\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Skate::handle_cheats( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::MsgToggleCheat* msg;\r\n\tScript::CStruct* pParams;\r\n\r\n\tpParams = new Script::CStruct;\r\n\tmsg = (GameNet::MsgToggleCheat*) context->m_Msg;\r\n\t\r\n\tif( msg->m_On )\r\n\t{\r\n\t\tpParams->AddChecksum( CRCD(0xf649d637,\"on\"), 0 );\r\n\t}\r\n\r\n\tpParams->AddChecksum( CRCD(0xae94c183,\"cheat_flag\"), msg->m_Cheat );\r\n\r\n\tScript::RunScript( CRCD(0x3cf9e86d,\"client_toggle_cheat\"), pParams );\r\n\r\n\tdelete pParams;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Get the number of times the 16-bit value was flipped since the */\r\n/* last time\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\ts_get_num_flips( uint32 new_time, uint32 old_time )\r\n{\r\n\tuint32 hi_new, hi_old;\r\n\r\n\thi_new = new_time >> 16;\r\n\thi_old = old_time >> 16;\r\n\r\n\treturn ( hi_new - hi_old );\r\n}\r\n\r\n/******************************************************************/\r\n/* Animate non-local clients\t  \t\t\t\t\t\t\t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Skate::handle_anims( Net::MsgHandlerContext* context )\r\n{\r\n\tObj::SAnimEvent* latest_event;\r\n\tObj::CMovingObject* obj;\r\n\tObj::CSkater* skater;\r\n\tSkate* mod;\r\n    \r\n\tmod = (Skate *) context->m_Data;\r\n    if( context->m_MsgId == GameNet::MSG_ID_PRIM_ANIM_START )\r\n\t{\r\n\t\tGameNet::MsgPlayPrimaryAnim anim_msg;\r\n\t\tchar* stream;\r\n        \r\n        stream = context->m_Msg;\r\n        \r\n\t\t//memcpy( &anim_msg.m_Time, stream, sizeof( unsigned short ));\r\n\t\t//Dbg_Printf( \"(%d) Got Primary %d\\n\", context->m_App->m_FrameCounter, anim_msg.m_Time );\r\n\t\t//stream += sizeof( int );\r\n\t\tmemcpy( &anim_msg.m_LoopingType, stream, sizeof( char ));\r\n\t\tstream++;\r\n\t\tmemcpy( &anim_msg.m_ObjId, stream, sizeof( char ));\r\n\t\tstream++;\r\n\t\tmemcpy( &anim_msg.m_Index, stream, sizeof( uint32 ));\r\n\t\tstream += sizeof( uint32 );\r\n\t\tmemcpy( &anim_msg.m_StartTime, stream, sizeof( unsigned short ));\r\n\t\tstream += sizeof( unsigned short );\r\n\t\tmemcpy( &anim_msg.m_EndTime, stream, sizeof( unsigned short ));\r\n\t\tstream += sizeof( unsigned short );\r\n\t\tmemcpy( &anim_msg.m_BlendPeriod, stream, sizeof( unsigned short ));\r\n\t\tstream += sizeof( unsigned short );\r\n\t\tmemcpy( &anim_msg.m_Speed, stream, sizeof( unsigned short ));\r\n\t\tstream += sizeof( unsigned short );\r\n\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( anim_msg.m_ObjId );\r\n\t\tif( obj )\r\n\t\t{\r\n\t\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\t\tfloat blend_period;\r\n\r\n\t\t\tskater = static_cast< Obj::CSkater *> ( obj );\r\n\t\t\tDbg_MsgAssert( skater != NULL,( \"Got anim for non-CSkater\" ));\r\n\t\t\t\r\n\t\t\tblend_period = (float) anim_msg.m_BlendPeriod / 4096.0f;\r\n\r\n\t\t\t// Only blend skaters that we are observing\r\n\t\t\tif ( gamenet_man->InNetGame() )\r\n\t\t\t{\r\n\t\t\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\t\t\tGameNet::PlayerInfo* observed_player, *anim_player;\r\n\r\n\t\t\t\tanim_player = gamenet_man->GetPlayerByObjectID( obj->GetID() );\r\n\t\t\t\tobserved_player = gamenet_man->GetCurrentlyObservedPlayer();\r\n\t\t\t\tif(( observed_player == NULL ) || ( anim_player != observed_player ))\r\n\t\t\t\t{\r\n\t\t\t\t\tblend_period = 0.0f;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif( skater )\r\n\t\t\t{\r\n\t\t\t\tlatest_event = skater->GetStateHistory()->GetLatestAnimEvent();\r\n\t\t\t\tlatest_event->m_MsgId = GameNet::MSG_ID_PRIM_ANIM_START;\r\n\t\t\t\tlatest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());\r\n\t\t\t\t//Dbg_Printf( \"(%d) Setting anm time: %d\\n\", context->m_App->m_FrameCounter, latest_event->GetTime());\r\n\r\n\t\t\t\tlatest_event->m_ObjId = anim_msg.m_ObjId;\r\n\t\t\t\tlatest_event->m_Asset = anim_msg.m_Index;\r\n\t\t\t\tlatest_event->m_StartTime = (float) anim_msg.m_StartTime / 4096.0f;\r\n\t\t\t\tlatest_event->m_EndTime = (float) anim_msg.m_EndTime / 4096.0f;\r\n\t\t\t\tlatest_event->m_BlendPeriod = blend_period;\r\n\t\t\t\tlatest_event->m_Speed = (float) anim_msg.m_Speed / 4096.0f;\r\n\t\t\t\tlatest_event->m_LoopingType = anim_msg.m_LoopingType;\r\n\r\n\t\t\t\tskater->GetStateHistory()->IncrementNumAnimUpdates();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( context->m_MsgId == GameNet::MSG_ID_SET_WOBBLE_TARGET )\r\n\t{\r\n\t\tGameNet::MsgSetWobbleTarget* msg;\r\n\r\n\t\tmsg = (GameNet::MsgSetWobbleTarget *) context->m_Msg;\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\t\tif( obj )\r\n\t\t{   \r\n\t\t\tskater = static_cast< Obj::CSkater *> ( obj );\r\n\t\t\tDbg_MsgAssert( skater != NULL,( \"Got anim for non-CSkater\" ));\r\n\r\n\t\t\tif( skater )\r\n\t\t\t{\r\n\t\t\t\tlatest_event = skater->GetStateHistory()->GetLatestAnimEvent();\r\n\t\t\t\tlatest_event->m_MsgId = GameNet::MSG_ID_SET_WOBBLE_TARGET;\r\n\t\t\t\tlatest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());\r\n\t\t\t\t//Dbg_Printf( \"(%d) Got Wobble %d\\n\", context->m_App->m_FrameCounter, msg->m_Time );\r\n\t\t\t\tlatest_event->m_ObjId = msg->m_ObjId;\r\n\t\t\t\tlatest_event->m_Alpha = (float) msg->m_Alpha / 255.0f;\r\n\t\t\t\tskater->GetStateHistory()->IncrementNumAnimUpdates();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( context->m_MsgId == GameNet::MSG_ID_ROTATE_SKATEBOARD )\r\n\t{\r\n\t\tGameNet::MsgRotateSkateboard* msg;\r\n\r\n\t\tmsg = (GameNet::MsgRotateSkateboard *) context->m_Msg;\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\t\tif( obj )\r\n\t\t{\r\n\t\t\tskater = static_cast< Obj::CSkater *> ( obj );\r\n\t\t\tDbg_MsgAssert( skater != NULL,( \"Got anim for non-CSkater\" ));\r\n\r\n\t\t\tif( skater )\r\n\t\t\t{\r\n\t\t\t\tlatest_event = skater->GetStateHistory()->GetLatestAnimEvent();\r\n\t\t\t\tlatest_event->m_MsgId = GameNet::MSG_ID_ROTATE_SKATEBOARD;\r\n\t\t\t\tlatest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());\r\n                //Dbg_Printf( \"(%d) Got Rotate %d\\n\", context->m_App->m_FrameCounter, msg->m_Time );\r\n\t\t\t\tlatest_event->m_ObjId = msg->m_ObjId;\r\n\t\t\t\tlatest_event->m_Rotate = msg->m_Rotate;\r\n\t\t\t\tskater->GetStateHistory()->IncrementNumAnimUpdates();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( context->m_MsgId == GameNet::MSG_ID_SET_WOBBLE_DETAILS )\r\n\t{\r\n\t\tGameNet::MsgSetWobbleDetails* msg;\r\n\r\n\t\tObj::CMovingObject* obj;\r\n\r\n\t\tmsg = (GameNet::MsgSetWobbleDetails *) context->m_Msg;\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\t\tif( obj )\r\n\t\t{\r\n\t\t\tskater = static_cast< Obj::CSkater *> ( obj );\r\n\t\t\tDbg_MsgAssert( skater != NULL,( \"Got anim for non-CSkater\" ));\r\n\r\n\t\t\tif( skater )\r\n\t\t\t{\r\n\t\t\t\tlatest_event = skater->GetStateHistory()->GetLatestAnimEvent();\r\n\t\t\t\tlatest_event->m_MsgId = GameNet::MSG_ID_SET_WOBBLE_DETAILS;\r\n\t\t\t\tlatest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());\r\n\t\t\t\t//Dbg_Printf( \"(%d) Got details %d\\n\", context->m_App->m_FrameCounter, msg->m_Time );\r\n\t\t\t\tlatest_event->m_ObjId = msg->m_ObjId;\r\n\t\t\t\tlatest_event->m_WobbleAmpA = s_get_wobble_details_from_mask( msg->m_WobbleDetails, GameNet::MsgSetWobbleDetails::vWOBBLE_AMP_A );\r\n\t\t\t\tlatest_event->m_WobbleAmpB = s_get_wobble_details_from_mask( msg->m_WobbleDetails, GameNet::MsgSetWobbleDetails::vWOBBLE_AMP_B );\r\n\t\t\t\tlatest_event->m_WobbleK1 = s_get_wobble_details_from_mask( msg->m_WobbleDetails, GameNet::MsgSetWobbleDetails::vWOBBLE_K1 );\r\n\t\t\t\tlatest_event->m_WobbleK2 = s_get_wobble_details_from_mask( msg->m_WobbleDetails, GameNet::MsgSetWobbleDetails::vWOBBLE_K2 );\r\n\t\t\t\tlatest_event->m_SpazFactor = s_get_wobble_details_from_mask( msg->m_WobbleDetails, GameNet::MsgSetWobbleDetails::vSPAZFACTOR );\r\n\r\n\t\t\t\tskater->GetStateHistory()->IncrementNumAnimUpdates();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( context->m_MsgId == GameNet::MSG_ID_SET_LOOPING_TYPE )\r\n\t{\r\n\t\tGameNet::MsgSetLoopingType* msg;\r\n\r\n\t\tObj::CMovingObject* obj;\r\n\r\n\t\tmsg = (GameNet::MsgSetLoopingType *) context->m_Msg;\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\t\tif( obj )\r\n\t\t{\r\n\t\t\tskater = static_cast< Obj::CSkater *> ( obj );\r\n\t\t\tDbg_MsgAssert( skater != NULL,( \"Got anim for non-CSkater\" ));\r\n\r\n\t\t\tif( skater )\r\n\t\t\t{\r\n\t\t\t\tlatest_event = skater->GetStateHistory()->GetLatestAnimEvent();\r\n                latest_event->m_MsgId = GameNet::MSG_ID_SET_LOOPING_TYPE;\r\n\t\t\t\tlatest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());\r\n\t\t\t\t//Dbg_Printf( \"(%d) Got looping %d\\n\", context->m_App->m_FrameCounter, msg->m_Time );\r\n\t\t\t\tlatest_event->m_ObjId = msg->m_ObjId;\r\n\t\t\t\tlatest_event->m_LoopingType = msg->m_LoopingType;\r\n\r\n\t\t\t\tskater->GetStateHistory()->IncrementNumAnimUpdates();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( context->m_MsgId == GameNet::MSG_ID_SET_HIDE_ATOMIC )\r\n\t{\r\n\t\tGameNet::MsgHideAtomic* msg;\r\n\r\n\t\tObj::CMovingObject* obj;\r\n\r\n\t\tmsg = (GameNet::MsgHideAtomic *) context->m_Msg;\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\t\tif( obj )\r\n\t\t{\r\n\t\t\tskater = static_cast< Obj::CSkater *> ( obj );\r\n\t\t\tDbg_MsgAssert( skater != NULL,( \"Got anim for non-CSkater\" ));\r\n\r\n\t\t\tif( skater )\r\n\t\t\t{\r\n\t\t\t\tlatest_event = skater->GetStateHistory()->GetLatestAnimEvent();\r\n                latest_event->m_MsgId = GameNet::MSG_ID_SET_HIDE_ATOMIC;\r\n\t\t\t\tlatest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());\r\n\t\t\t\tlatest_event->m_ObjId = msg->m_ObjId;\r\n\t\t\t\tlatest_event->m_Asset = msg->m_AtomicName;\r\n\t\t\t\tlatest_event->m_Hide = msg->m_Hide;\r\n\r\n\t\t\t\tskater->GetStateHistory()->IncrementNumAnimUpdates();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( context->m_MsgId == GameNet::MSG_ID_SET_ANIM_SPEED )\r\n\t{\r\n\t\tGameNet::MsgSetAnimSpeed* msg;\r\n\r\n\t\tObj::CMovingObject* obj;\r\n\r\n\t\tmsg = (GameNet::MsgSetAnimSpeed *) context->m_Msg;\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\t\tif( obj )\r\n\t\t{\r\n\t\t\tskater = static_cast< Obj::CSkater *> ( obj );\r\n\t\t\tDbg_MsgAssert( skater != NULL,( \"Got anim for non-CSkater\" ));\r\n\r\n\t\t\tif( skater )\r\n\t\t\t{\r\n\t\t\t\tlatest_event = skater->GetStateHistory()->GetLatestAnimEvent();\r\n                latest_event->m_MsgId = GameNet::MSG_ID_SET_ANIM_SPEED;\r\n\t\t\t\tlatest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());\r\n\t\t\t\t//Dbg_Printf( \"(%d) Got speed %d\\n\", context->m_App->m_FrameCounter, msg->m_Time );\r\n\t\t\t\tlatest_event->m_ObjId = msg->m_ObjId;\r\n\t\t\t\tlatest_event->m_Speed = msg->m_AnimSpeed;\r\n\r\n\t\t\t\tskater->GetStateHistory()->IncrementNumAnimUpdates();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( context->m_MsgId == GameNet::MSG_ID_FLIP_ANIM )\r\n\t{\r\n\t\tGameNet::MsgFlipAnim* msg;\r\n\r\n\t\tObj::CMovingObject* obj;\r\n\t\t\r\n\t\tmsg = (GameNet::MsgFlipAnim *) context->m_Msg;\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\t\tif( obj )\r\n\t\t{\r\n\t\t\tskater = mod->GetSkaterById( msg->m_ObjId );\r\n\t\t\tif( skater )\r\n\t\t\t{\r\n\t\t\t\tlatest_event = skater->GetStateHistory()->GetLatestAnimEvent();\r\n                latest_event->m_MsgId = GameNet::MSG_ID_FLIP_ANIM;\r\n\t\t\t\tlatest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());\r\n\t\t\t\t//Dbg_Printf( \"(%d) Got flip %d\\n\", context->m_App->m_FrameCounter, msg->m_Time );\r\n\t\t\t\tlatest_event->m_Flipped = msg->m_Flipped;\r\n\t\t\t\tlatest_event->m_ObjId = msg->m_ObjId;\r\n\r\n\t\t\t\tskater->GetStateHistory()->IncrementNumAnimUpdates();\r\n\r\n\t\t\t\t// If we got a flip message for a skater, we've now handled it. Otherwise,\r\n\t\t\t\t// let it fall through as it is for some other object in the game\r\n\t\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( context->m_MsgId == GameNet::MSG_ID_ROTATE_DISPLAY )\r\n\t{\r\n\t\tGameNet::MsgRotateDisplay* msg;\r\n\r\n\t\tObj::CMovingObject* obj;\r\n\t\t\r\n\t\tmsg = (GameNet::MsgRotateDisplay *) context->m_Msg;\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\t\tif( obj )\r\n\t\t{\r\n\t\t\tskater = mod->GetSkaterById( msg->m_ObjId );\r\n\t\t\tif( skater )\r\n\t\t\t{\r\n\t\t\t\tlatest_event = skater->GetStateHistory()->GetLatestAnimEvent();\r\n                latest_event->m_MsgId = GameNet::MSG_ID_ROTATE_DISPLAY;\r\n\t\t\t\tlatest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());\r\n\t\t\t\t//Dbg_Printf( \"(%d) Got rotate %d\\n\", context->m_App->m_FrameCounter, msg->m_Time );\r\n\t\t\t\tlatest_event->m_ObjId = msg->m_ObjId;\r\n\t\t\t\tlatest_event->m_Duration = msg->m_Duration;\r\n\t\t\t\tlatest_event->m_SinePower = msg->m_SinePower;\r\n\t\t\t\tlatest_event->m_StartAngle = msg->m_StartAngle;\r\n\t\t\t\tlatest_event->m_DeltaAngle = msg->m_DeltaAngle;\r\n\t\t\t\tlatest_event->m_HoldOnLastAngle = msg->m_HoldOnLastAngle;\r\n\t\t\t\tlatest_event->m_Flags = msg->m_Flags;\r\n\r\n\t\t\t\tskater->GetStateHistory()->IncrementNumAnimUpdates();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( context->m_MsgId == GameNet::MSG_ID_CLEAR_ROTATE_DISPLAY )\r\n\t{\r\n\t\tGameNet::MsgObjMessage* msg;\r\n\r\n\t\tObj::CMovingObject* obj;\r\n\t\t\r\n\t\tmsg = (GameNet::MsgObjMessage *) context->m_Msg;\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\t\tif( obj )\r\n\t\t{\r\n\t\t\tskater = mod->GetSkaterById( msg->m_ObjId );\r\n\t\t\tif( skater )\r\n\t\t\t{\r\n\t\t\t\tlatest_event = skater->GetStateHistory()->GetLatestAnimEvent();\r\n                latest_event->m_MsgId = GameNet::MSG_ID_CLEAR_ROTATE_DISPLAY;\r\n\t\t\t\tlatest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());\r\n\t\t\t\tlatest_event->m_ObjId = msg->m_ObjId;\r\n\r\n\t\t\t\tskater->GetStateHistory()->IncrementNumAnimUpdates();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( context->m_MsgId == GameNet::MSG_ID_CREATE_SPECIAL_ITEM )\r\n\t{    \r\n\t\tObj::CMovingObject* obj;\r\n\t\tGameNet::MsgSpecialItem* msg;\r\n\r\n\t\tmsg = (GameNet::MsgSpecialItem *) context->m_Msg;\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\t\tif( obj )\r\n\t\t{\r\n\t\t\tskater = mod->GetSkaterById( msg->m_ObjId );\r\n\t\t\tif( skater )\r\n\t\t\t{\r\n\t\t\t\tlatest_event = skater->GetStateHistory()->GetLatestAnimEvent();\r\n                latest_event->m_MsgId = GameNet::MSG_ID_CREATE_SPECIAL_ITEM;\r\n\t\t\t\tlatest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());\r\n\t\t\t\tlatest_event->m_ObjId = msg->m_ObjId;\r\n\t\t\t\tlatest_event->m_Bone = msg->m_Bone;\r\n\t\t\t\tlatest_event->m_Index = msg->m_Index;\r\n\t\t\t\tlatest_event->m_Asset = msg->m_Params;\r\n\r\n\t\t\t\tskater->GetStateHistory()->IncrementNumAnimUpdates();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if( context->m_MsgId == GameNet::MSG_ID_DESTROY_SPECIAL_ITEM )\r\n\t{\r\n\t\tObj::CMovingObject* obj;\r\n\t\tGameNet::MsgSpecialItem* msg;\r\n\r\n\t\tmsg = (GameNet::MsgSpecialItem *) context->m_Msg;\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\t\tif( obj )\r\n\t\t{\r\n\t\t\tskater = mod->GetSkaterById( msg->m_ObjId );\r\n\t\t\tif( skater )\r\n\t\t\t{\r\n\t\t\t\tlatest_event = skater->GetStateHistory()->GetLatestAnimEvent();\r\n                latest_event->m_MsgId = GameNet::MSG_ID_DESTROY_SPECIAL_ITEM;\r\n\t\t\t\tlatest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());\r\n\t\t\t\tlatest_event->m_ObjId = msg->m_ObjId;\r\n\t\t\t\tlatest_event->m_Index = msg->m_Index;\r\n\r\n\t\t\t\tskater->GetStateHistory()->IncrementNumAnimUpdates();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Skate::handle_flip_anim( Net::MsgHandlerContext* context ) \r\n{\r\n\tSkate* mod;\r\n\r\n\tmod = (Skate *) context->m_Data;\r\n\t\t\r\n\tGameNet::MsgFlipAnim* msg;\r\n\r\n\tObj::CMovingObject* obj;\r\n\tmsg = (GameNet::MsgFlipAnim *) context->m_Msg;\r\n\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\tif( obj )\r\n\t{\r\n\t\tObj::CMovingObject* moving_obj;\r\n\t \r\n\t\tmoving_obj = static_cast< Obj::CMovingObject *> ( obj );\r\n\t\tDbg_MsgAssert( moving_obj != NULL,( \"Got object update for non-CMovingObj\\n\" ));\r\n\t\t\r\n\t\tif( moving_obj )\r\n\t\t{\r\n\t\t\tObj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( moving_obj );\r\n\t\t\tif ( pAnimationComponent )\r\n\t\t\t{\r\n\t\t\t\tpAnimationComponent->FlipAnimation( msg->m_ObjId, msg->m_Flipped, context->m_App->m_Timestamp, false );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Skate::handle_player_quit( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::PlayerInfo* player;\r\n\tSkate* mod;\r\n\tGameNet::MsgPlayerQuit* msg;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tDbg_Printf( \"Got player quit message\" );\r\n\r\n\tmod = (Skate *) context->m_Data;\r\n\tmsg = (GameNet::MsgPlayerQuit *) context->m_Msg; \r\n\tplayer = gamenet_man->GetPlayerByObjectID( msg->m_ObjId );\r\n\tif( player )\r\n\t{   \r\n\t\tObj::CSkater* quitting_skater;\r\n\r\n\t\tquitting_skater = player->m_Skater;\r\n\t\t\r\n\t\tDbg_Printf( \"Got player quit message 2\" );\r\n\t\tgamenet_man->DropPlayer( player, (GameNet::DropReason) msg->m_Reason );\r\n\t\tmod->remove_skater( quitting_skater );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGameNet::NewPlayerInfo* pending_player;\r\n\r\n\t\tpending_player = gamenet_man->GetNewPlayerInfoByObjectID( msg->m_ObjId );\r\n\t\tif( pending_player )\r\n\t\t{\r\n\t\t\tgamenet_man->DestroyNewPlayer( pending_player );\r\n\t\t}\r\n\t}\r\n\r\n\t// The server may have been waiting for us to load this player.  If so, tell the server we're ready now.\r\n\tgamenet_man->RespondToReadyQuery();\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#if 0\r\nstatic bool HostQuitDialogHandler( Front::EDialogBoxResult result )\r\n{\r\n\t\r\n\r\n\tif( result == Front::DB_OK )\r\n\t{   \r\n\t\tMdl::FrontEnd* front = Mdl::FrontEnd::Instance();\r\n            \r\n\t\tScript::RunScript( \"chosen_leave_server\" );\r\n\t\tfront->PauseGame( false );\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Skate::handle_disconn_accepted( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tDbg_Message( \"Logging off of server\\n\" );\r\n\r\n\tScript::RunScript( \"CreateServerQuitDialog\" );\r\n\tgamenet_man->CleanupPlayers();\r\n\tgamenet_man->ClientShutdown();\r\n \r\n\treturn Net::HANDLER_HALT;\r\n}\r\n\r\n/******************************************************************/\r\n/* You've been kicked by the server\t\t\t\t\t\t\t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Skate::handle_kicked( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tSkate * skate_mod = Skate::Instance();\r\n\r\n\t\r\n\r\n\tDbg_Message( \"Logging off of server\\n\" );\r\n\r\n\tScript::DeleteSpawnedScripts();\r\n\r\n\tScript::CScriptStructure* pStructure = new Script::CScriptStructure;\r\n\t\r\n\tpStructure->AddComponent( Script::GenerateCRC( \"width\" ), ESYMBOLTYPE_INTEGER, 300 );\r\n\tpStructure->AddComponent( Script::GenerateCRC( \"title\" ), ESYMBOLTYPE_NAME, (int) Script::GenerateCRC(\"net_notice_msg\"));\r\n\tif( context->m_MsgId == GameNet::MSG_ID_KICKED )\r\n\t{\r\n\t\tScript::RunScript( \"CreateServerRemovedYouDialog\" );\r\n\t}\r\n\telse if( context->m_MsgId == GameNet::MSG_ID_LEFT_OUT )\r\n\t{\r\n\t\tScript::RunScript( \"CreateServerMovedOnDialog\" );\r\n\t}\r\n\t\r\n\tif( skate_mod->m_requested_level == Script::GenerateCRC( \"load_skateshop\" ))\r\n\t{\r\n\t\t// If we got partially in, cancel the join and remove partially-loaded players\r\n\t\t// Shut the client down so that it doesn't bombard the server ip with messages\r\n\t\tgamenet_man->CancelJoinServer();\r\n\t\tgamenet_man->SetJoinState( GameNet::vJOIN_STATE_FINISHED );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgamenet_man->CleanupPlayers();\r\n\t\tgamenet_man->ClientShutdown();\r\n\t}\r\n\r\n\tdelete pStructure;\t\r\n \r\n\treturn Net::HANDLER_HALT;\r\n}\r\n\r\n/******************************************************************/\r\n/* Observer-specific trick object handling\t\t\t\t\t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Skate::handle_obs_log_trick_objects( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tGameNet::MsgObsScoreLogTrickObject* msg;\r\n\tSkate* skate_mod;\r\n\r\n\tskate_mod = (Skate*) context->m_Data;\r\n\tmsg = (GameNet::MsgObsScoreLogTrickObject*) context->m_Msg;\r\n\r\n\tif( msg->m_GameId != gamenet_man->GetNetworkGameId())\r\n\t{\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\tint seq;\r\n\r\n\tif( skate_mod->GetGameMode()->IsTeamGame())\r\n\t{\r\n\t\tGameNet::PlayerInfo* player;\r\n\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( msg->m_OwnerId );\r\n\t\tseq = player->m_Team;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tseq = msg->m_OwnerId;\r\n\t}\r\n\r\n\t// modulate the color here\r\n\tfor( uint32 i = 0; i < msg->m_NumPendingTricks; i++ )\r\n\t{\r\n\t\tskate_mod->GetTrickObjectManager()->ModulateTrickObjectColor( msg->m_PendingTrickBuffer[i], seq );\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* handle custom face data\t\t\t\t\t\t  \t\t\t\t  */\r\n/* \t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Skate::handle_face_data( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tGameNet::PlayerInfo* sender;\r\n\tObj::CSkater* skater;\r\n\tuint8* face_data;\r\n\tint face_data_length;\r\n\tuint8 skater_id;\r\n\r\n\tDbg_Printf( \"**** HANDLING FACE DATA****\" );\r\n\r\n    // Create a new temporary CFaceTexture.  \r\n\tGfx::CFaceTexture* pFaceTexture = new Gfx::CFaceTexture;\r\n\r\n\tface_data = (uint8*) context->m_Msg;\r\n\tface_data_length = context->m_MsgLength;\r\n\tskater_id = 0;\r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\tsender = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\t\tif( sender == NULL )\r\n\t\t{\r\n\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t}\r\n\t\t\r\n\t\tskater = sender->m_Skater;\r\n\t\tif( skater == NULL ) \r\n\t\t{\r\n\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tskater_id = *face_data++;\r\n\t\tface_data_length -= sizeof( char );\r\n\r\n\t\tsender = gamenet_man->GetPlayerByObjectID( skater_id );\r\n\t\tif( sender == NULL )\r\n\t\t{\r\n\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t}\r\n\t\t\r\n\t\tskater = sender->m_Skater;\r\n\t\tif( skater == NULL ) \r\n\t\t{\r\n\t\t\treturn Net::HANDLER_MSG_DONE;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Read in data from network message\r\n\tpFaceTexture->ReadFromBuffer((uint8*) face_data, face_data_length );\r\n\tpFaceTexture->SetValid( true );\r\n\r\n\t// Get the skater's model\r\n\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( skater ); \r\n\tDbg_Assert( pModelComponent );\r\n\tNx::CModel* pModel = pModelComponent->GetModel();\r\n\tDbg_Assert( pModel );\r\n\t\r\n\t// Apply face texture to new model (eventually these parameters \r\n\t// might need to come through the same network message, \r\n\t// depending on the sex of the skater) \r\n\tconst char* pSrcTexture = \"CS_NSN_facemap.png\";\r\n\tpModel->ApplyFaceTexture( pFaceTexture, pSrcTexture, Nx::CModel::vREPLACE_GLOBALLY );\r\n\t\r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\tGameNet::PlayerInfo* face_player, *player;\r\n\t\tLst::Search< GameNet::PlayerInfo > sh;\r\n\t\tNet::Server* server;\r\n\r\n\t\tserver = (Net::Server*) context->m_App;\r\n\r\n\t\t// need to copy face texture data somewhere\r\n\t\t// so that future joining players can get \r\n\t\t// everyone else's face textures (unimplemented)\r\n\t\tface_player = gamenet_man->GetPlayerByConnection( context->m_Conn );\r\n\t\tface_player->SetFaceData((uint8*) context->m_Msg, context->m_MsgLength );\r\n\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t{\r\n\t\t\tif( player->IsLocalPlayer() || ( player == face_player ))\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tserver->StreamMessageToConn( player->m_Conn, GameNet::MSG_ID_FACE_DATA, Gfx::CFaceTexture::vTOTAL_CFACETEXTURE_SIZE + 1, face_player->GetFaceData(), \"Face Data\",\r\n\t\t\t\t\t\t\t\t\t   GameNet::vSEQ_GROUP_FACE_MSGS, false, true );\r\n\t\t}\r\n\t}\r\n\t\r\n\tdelete pFaceTexture;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Observer-specific trick object handling\t\t\t\t\t\t  */\r\n/* for when the level starts up (observer needs to \"catch up\"     */\r\n/* to everyone else's trick object state)   \t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Skate::handle_obs_init_graffiti_state( Net::MsgHandlerContext* context )\r\n{\r\n\t\r\n\t\r\n\tGameNet::MsgInitGraffitiState* msg;\r\n\tSkate* skate_mod;\r\n\tint i;\r\n\r\n\tskate_mod = (Skate*) context->m_Data;\r\n\tmsg = (GameNet::MsgInitGraffitiState*) context->m_Msg;\r\n\r\n\tif ( !skate_mod->GetGameMode()->IsTrue( \"should_modulate_color\" ) )\r\n\t{\r\n\t\tprintf( \"No need to continue cause we're not in graffiti mode\" );\r\n\t\t\r\n\t\t// no need to process the msg here unless it's graffiti mode\r\n\t\treturn Net::HANDLER_MSG_DONE;\r\n\t}\r\n\r\n\tuint8* pStartOfStream = &msg->m_TrickObjectStream[0];\r\n\r\n\tObj::CTrickObjectManager* pTrickObjectManager = skate_mod->GetTrickObjectManager();\r\n\tDbg_Assert( pTrickObjectManager );\r\n\r\n\t// push heap\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\r\n\tScript::CScriptStructure* pStructure = new Script::CScriptStructure;\r\n\r\n\t// modulate the color here\r\n\tfor( i = 0; i < vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tif ( msg->m_NumTrickObjects[i] )\r\n\t\t{\r\n\t\t\tScript::CArray* pArray = new Script::CArray;\r\n\t\t\t\r\n\t\t\tpArray->SetArrayType( msg->m_NumTrickObjects[i], ESYMBOLTYPE_NAME );\r\n\t\t\t\r\n\t\t\tfor ( int j = 0; j < msg->m_NumTrickObjects[i]; j++ )\r\n\t\t\t{\r\n\t\t\t\tuint32 trick_object_checksum = pTrickObjectManager->GetUncompressedTrickObjectChecksum( *pStartOfStream );\r\n\t\t\t\tpArray->SetChecksum( j, trick_object_checksum );\r\n//\t\t\t\tpTrickObjectManager->ModulateTrickObjectColor( trick_object_checksum, i );\r\n\t\t\t\tpStartOfStream++;\r\n\t\t\t}\r\n\r\n\t\t\tchar arrayName[32];\r\n\t\t\tsprintf( arrayName, \"Skater%d\", i );\t\t\t\r\n\t\t\tpStructure->AddComponent( Script::GenerateCRC( arrayName ), pArray );\r\n\t\t}\r\n\t}\r\n\r\n\tpTrickObjectManager->SetObserverGraffitiState( pStructure );\r\n\tpTrickObjectManager->ApplyObserverGraffitiState();\r\n\r\n\tdelete pStructure;\r\n\r\n\t// apply color modulation a few frames later...\r\n\t//\r\n\t//\r\n\t// This was never defined, so I commented it out. I just apply it immediately and this\r\n\t// seems to work for now\r\n\t//Script::SpawnScript( \"deferred_observer_trick_modulation\", pStructure, 0, NULL );\r\n\r\n\t// pop heap\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Set terrain type\t\t\t\t\t\t\t\t\t\t  \t\t  */\r\n/*                           \t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_score_update( Net::MsgHandlerContext* context )\r\n{\r\n    GameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\tMdl::FrontEnd* front_end = Mdl::FrontEnd::Instance();\r\n\tGameNet::MsgScoreUpdate* msg;\r\n\tObj::CMovingObject *obj;\r\n\tSkate* mod;\r\n\tint i, score;\r\n\tchar* data;\r\n\tchar id;\r\n    \r\n\tmsg = (GameNet::MsgScoreUpdate*) context->m_Msg;\r\n\tdata = msg->m_ScoreData;\r\n    mod = (Skate*) context->m_Data;\r\n\r\n\tif( !gamenet_man->OnServer())\r\n\t{\r\n\t\tmod->GetGameMode()->SetTimeLeft( msg->m_TimeLeft );\r\n\t}\r\n\r\n\tfor( i = 0; i < msg->m_NumScores; i++ )\r\n\t{           \r\n\t\tid = *data;\r\n\t\tdata++;\r\n\t\tmemcpy( &score, data, sizeof( int ));\r\n\t\tdata += sizeof( int );\r\n\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( id );\r\n\t\tif( obj )\r\n\t\t{\r\n\t\t\tObj::CSkater* skater_obj;\r\n\t\t\t\r\n\t\t\tskater_obj = static_cast< Obj::CSkater *> ( obj );\r\n\t\t\tDbg_MsgAssert( skater_obj != NULL,( \"Got score update for non-CSkater\\n\" ));\r\n\r\n\t\t\tif(\t( mod->GetGameMode()->IsTrue( \"should_modulate_color\" )) ||\r\n\t\t\t\t( mod->GetGameMode()->ShouldTrackTrickScore() == false ))\r\n\t\t\t{\r\n\t\t\t\tMdl::Score *pScore = skater_obj->GetScoreObject();\r\n\r\n\t\t\t\t// Check if a skater has just been eliminated in a firefight game\r\n\t\t\t\tif(\t( mod->GetGameMode()->GetNameChecksum() == CRCD(0xbff33600,\"netfirefight\" )) &&\r\n\t\t\t\t\t( skater_obj->IsLocalClient() == false ))\r\n\t\t\t\t{\r\n\t\t\t\t\t// If this is the positive edge then hide the skater\r\n\t\t\t\t\tif(( pScore->GetTotalScore() > 0 ) && ( score == 0 ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tScript::CStruct* params;\r\n\t\t\t\t\t\tparams = new Script::CStruct;\r\n\t\t\t\t\t\tparams->AddString( CRCD(0xa1dc81f9,\"name\"), skater_obj->GetDisplayName());\r\n\t\t\t\t\t\tScript::RunScript( CRCD(0x9b043179,\"announce_elimination\"), params );\r\n\t\t\t\t\t\tdelete params;\r\n\t\t\t\t\t\tmod->HideSkater( skater_obj, true );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tpScore->SetTotalScore( score );\r\n\t\t\t}\r\n\t\t\telse if( skater_obj && !skater_obj->IsLocalClient())\r\n\t\t\t{\r\n\t\t\t\tMdl::Score *pScore = skater_obj->GetScoreObject();\r\n\t\t\t\tpScore->SetTotalScore( score );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif( msg->m_Final )\r\n\t{          \r\n\t\tgamenet_man->MarkReceivedFinalScores( true );\r\n\t}\r\n\r\n\tif( msg->m_Cheats != mod->GetCheatChecksum())\r\n\t{\r\n\t\tif( gamenet_man->HasCheatingOccurred() == false )\r\n\t\t{\r\n\t\t\tScript::RunScript( CRCD(0x1cedb62c,\"notify_cheating\"));\r\n\t\t\tgamenet_man->CheatingOccured();\r\n\t\t}\r\n\t}\r\n    \r\n\tif( mod->GetGameMode()->IsTeamGame())\r\n\t{\r\n\t\tint num_teams, score, highest_score, leading_team;\r\n\t\tGameNet::PlayerInfo* my_player;\r\n\r\n\t\tnum_teams = mod->GetGameMode()->NumTeams();\r\n\t\tleading_team = GameNet::vNO_TEAM;\r\n\t\thighest_score = 0;\r\n\t\tfor( i = 0; i < num_teams; i++ )\r\n\t\t{\r\n\t\t\tscore = gamenet_man->GetTeamScore( i );\r\n\t\t\tif( score > highest_score )\r\n\t\t\t{\r\n\t\t\t\thighest_score = score;\r\n\t\t\t\tleading_team = i;\r\n\t\t\t}\r\n\t\t\telse if( score == highest_score )\r\n\t\t\t{\r\n\t\t\t\t// A tie doesn't result in the panel message\r\n\t\t\t\tleading_team = GameNet::vNO_TEAM;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( leading_team != GameNet::vNO_TEAM )\r\n\t\t{\r\n\t\t\tmy_player = gamenet_man->GetLocalPlayer();\r\n\t\t\tif( msg->m_Final )\r\n\t\t\t{\r\n\t\t\t\tif(( my_player->m_Skater ) && ( my_player->m_Team == leading_team ))\r\n\t\t\t\t{\r\n\t\t\t\t\tmy_player->m_Skater->SelfEvent(CRCD(0x96935417,\"WonGame\"));\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif( my_player->m_Skater )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmy_player->m_Skater->SelfEvent(CRCD(0xe3ec7e9e,\"LostGame\"));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if( ( gamenet_man->GetCurrentLeadingTeam() != leading_team ) &&\r\n\t\t\t\t\t ( mod->GetGameMode()->IsTrue( \"show_leader_messages\" ) ) &&\r\n                     ( !gamenet_man->GameIsOver()))\r\n\t\r\n\t\t\t{\r\n\t\t\t\t// only print the message if you're competing against someone\r\n\t\t\t\tif(( my_player->m_Skater ) && ( my_player->m_Team == leading_team ))\r\n\t\t\t\t{   \r\n\t\t\t\t\tScript::RunScript( \"NewScoreLeaderYourTeam\", NULL, my_player->m_Skater );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{   \r\n\t\t\t\t\tchar team_name[128];\r\n\r\n\t\t\t\t\tsprintf( team_name, \"team_%d_name\", leading_team + 1 );\r\n\t\t\t\t\tScript::CScriptStructure* pTempStructure = new Script::CScriptStructure;\r\n\t\t\t\t\tpTempStructure->Clear();\r\n\t\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"String0\"), ESYMBOLTYPE_STRING, Script::GetString( team_name ));\r\n\t\t\t\t\tScript::RunScript( \"NewScoreLeaderOtherTeam\", pTempStructure, my_player->m_Skater );\r\n\t\t\t\t\tdelete pTempStructure;\r\n\t\t\t\t}\r\n\t\t\t\tgamenet_man->SetCurrentLeadingTeam( leading_team );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGameNet::PlayerInfo* player, *leader, *my_player;\r\n\t\tLst::Search< GameNet::PlayerInfo > sh;\r\n\t\tint score, highest_score, num_players;\r\n\r\n\t\t// Do the logic that figures out if there's a new winner and provides feedback\r\n\t\tleader = NULL;\r\n\t\thighest_score = 0;\r\n\t\tnum_players = 0;\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player;\r\n\t\t\t\tplayer = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\t//if( player->IsLocalPlayer() && mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netgoalattack\" ))\r\n\t\t\t{\r\n\t\t\t\tscore = gamenet_man->GetPlayerScore( player->m_Skater->GetID());\r\n\t\t\t}\r\n\t\t\t//else\r\n\t\t\t//{\r\n\t\t\t\t//Mdl::Score *pScore = player->m_Skater->GetScoreObject();\r\n\t\t\t\t\r\n\t\t\t\t//score = pScore->GetTotalScore();\r\n\t\t\t//}\r\n\t\t\tif( score > highest_score )\r\n\t\t\t{\r\n\t\t\t\thighest_score = score;\r\n\t\t\t\tleader = player;\r\n\t\t\t}\r\n\t\t\telse if( score == highest_score )\r\n\t\t\t{\r\n\t\t\t\t// A tie doesn't result in the panel message\r\n\t\t\t\tleader = NULL;\r\n\t\t\t}\r\n\t\t\tnum_players++;\r\n\t\t}\r\n        \r\n\t\tif( leader )\r\n\t\t{   \r\n\t\t\tmy_player = gamenet_man->GetLocalPlayer();\r\n\t\t\tif( msg->m_Final )\r\n\t\t\t{\r\n\t\t\t\tif( leader->IsLocalPlayer())\r\n\t\t\t\t{\r\n\t\t\t\t\tleader->m_Skater->SelfEvent(CRCD(0x96935417,\"WonGame\"));\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif( my_player->m_Skater )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tleader->m_Skater->SelfEvent( CRCD(0xe3ec7e9e,\"LostGame\") );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if( ( gamenet_man->GetCurrentLeader() != leader ) &&\r\n\t\t\t\t\t ( num_players > 1 ) &&\r\n\t\t\t\t\t ( mod->GetGameMode()->IsTrue( CRCD(0xd63dfd0f,\"show_leader_messages\") ) ) &&\r\n                     ( !front_end->GamePaused()))\r\n\t\r\n\t\t\t{\r\n\t\t\t\t// only print the message if you're competing against someone\r\n\t\t\t\tif( leader->IsLocalPlayer())\r\n\t\t\t\t{   \r\n\t\t\t\t\tScript::RunScript( CRCD(0xa1d334d0,\"NewScoreLeaderYou\"), NULL, leader->m_Skater );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{   \r\n\t\t\t\t\tScript::CScriptStructure* pTempStructure = new Script::CScriptStructure;\r\n\t\t\t\t\tpTempStructure->Clear();\r\n\t\t\t\t\tpTempStructure->AddComponent( CRCD(0xa4b08520,\"String0\"), ESYMBOLTYPE_STRING, leader->m_Name );\r\n\t\t\t\t\tScript::RunScript( CRCD(0x7a4b9d14,\"NewScoreLeaderOther\"), pTempStructure, my_player->m_Skater );\r\n\t\t\t\t\tdelete pTempStructure;\r\n\t\t\t\t}\r\n\t\t\t\tgamenet_man->SetCurrentLeader( leader );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Start/Stop spark effect\t\t\t\t\t\t\t\t\t\t  */\r\n/*                           \t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_sparks( Net::MsgHandlerContext* context )\r\n{\r\n\tSkate* mod;\r\n\tGameNet::MsgObjMessage *msg;\r\n\tObj::CMovingObject *obj;\r\n\r\n\t\r\n\r\n\tmsg = (GameNet::MsgObjMessage *) context->m_Msg;\r\n\t\r\n\tmod = (Skate *) context->m_Data;\r\n\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\tif( obj )\r\n\t{\r\n\t\tObj::CSkater* skater_obj;\r\n\t\t\r\n\t\tskater_obj = static_cast< Obj::CSkater *> ( obj );\r\n\t\tDbg_MsgAssert( skater_obj != NULL,( \"Got sparks message for non-CSkater\\n\" ));\r\n\t\t\r\n\t\tif( skater_obj )\r\n\t\t{   \r\n\t\t\tswitch( context->m_MsgId )\r\n\t\t\t{\r\n\t\t\t\tcase GameNet::MSG_ID_SPARKS_ON:\r\n\t\t\t\t\tskater_obj->SparksOn();\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase GameNet::MSG_ID_SPARKS_OFF:\r\n\t\t\t\t\tskater_obj->SparksOff();\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Start/Stop blood effect\t\t\t\t\t\t\t\t\t\t  */\r\n/*                           \t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_blood( Net::MsgHandlerContext* context )\r\n{\r\n\tSkate* mod;\r\n\tObj::CMovingObject *obj;\r\n\tGameNet::MsgObjMessage* msg;\r\n\r\n\t\r\n\r\n\tmod = (Skate *) context->m_Data;\r\n\tmsg = (GameNet::MsgObjMessage* ) context->m_Msg;\r\n\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );\r\n\tif( obj )\r\n\t{\r\n\t\tObj::CSkater* skater_obj;\r\n\r\n\t\tskater_obj = static_cast< Obj::CSkater *> ( obj );\r\n\t\tDbg_MsgAssert( skater_obj != NULL,( \"Got blood message for non-CSkater\\n\" ));\r\n\t\tif( skater_obj )\r\n\t\t{   \r\n\t\t\tswitch( context->m_MsgId )\r\n\t\t\t{\r\n\t\t\t\tcase GameNet::MSG_ID_BLOOD_ON:\r\n\t\t\t\t{\r\n\t\t\t\t\tGameNet::MsgBlood *msg;\r\n\r\n\t\t\t\t\tmsg = (GameNet::MsgBlood *) context->m_Msg;\r\n//\t\t\t\t\tskater_obj->BloodOn( msg->m_BodyPart, msg->m_Size, msg->m_Frequency, msg->m_RandomRadius );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase GameNet::MSG_ID_BLOOD_OFF:\r\n\t\t\t\t{\r\n\t\t\t\t\tGameNet::MsgBloodOff *msg;\r\n\r\n\t\t\t\t\tmsg = (GameNet::MsgBloodOff *) context->m_Msg;\r\n//\t\t\t\t\tskater_obj->BloodOff( msg->m_BodyPart );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Play a one-off sound given a position  \t\t\t\t\t\t  */\r\n/*                           \t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_play_sound( Net::MsgHandlerContext* context )\r\n{\r\n\tGameNet::MsgPlaySound *msg;\r\n\tMth::Vector pos;\r\n\tfloat vol, pitch, choice;\r\n\r\n\tmsg = (GameNet::MsgPlaySound *) context->m_Msg;\r\n\t\r\n\tpos[X] = msg->m_Pos[0];\r\n\tpos[Y] = msg->m_Pos[1];\r\n\tpos[Z] = msg->m_Pos[2];\r\n\r\n\tvol = (float) msg->m_VolPercent;\r\n\tpitch = (float) msg->m_PitchPercent;\r\n\tchoice = (float) msg->m_SoundChoice;\r\n\r\n\tEnv::CTerrainManager::sPlaySound( (Env::ETerrainActionType) msg->m_WhichArray, (ETerrainType) msg->m_SurfaceFlag, pos, vol, pitch, choice, false );\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Get all the game options  \t\t\t\t\t\t  \t\t\t  */\r\n/*                           \t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint\tSkate::handle_start_info( Net::MsgHandlerContext* context )\r\n{   \r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tSkate* skate_mod;\r\n\tGameNet::MsgStartInfo* msg;\r\n\tScript::CArray* mode_array;\r\n\tint i;\r\n\r\n\tDbg_Printf( \"********************************* Got lobby info\\n\" );\r\n\r\n\tgamenet_man->SetJoinState( GameNet::vJOIN_STATE_CONNECTED );\r\n\tgamenet_man->FreeServerList();\r\n\r\n\tskate_mod = (Skate *) context->m_Data;\r\n\tmsg = (GameNet::MsgStartInfo*) context->m_Msg;\r\n\r\n\t// Note whether or not the server is narrowband/broadband\r\n\tif( msg->m_Broadband )\r\n\t{\r\n\t\tcontext->m_Conn->SetBandwidthType( Net::Conn::vBROADBAND );\r\n\t\tcontext->m_Conn->SetSendInterval( Tmr::VBlanks( 2 ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcontext->m_Conn->SetBandwidthType( Net::Conn::vNARROWBAND );\r\n\t\tcontext->m_Conn->SetSendInterval( Tmr::VBlanks( 2 ));\r\n\t}\r\n\r\n\tgamenet_man->SetNetworkGameId( msg->m_GameId );\r\n\tgamenet_man->SetLevel( msg->m_LevelId );\r\n\tgamenet_man->SetCrownSpawnPoint( msg->m_CrownSpawnPoint );\r\n\tgamenet_man->SetSkaterStartingPoints( msg->m_StartPoints );\r\n\t\r\n\t// set up the game mode for the client cause we're now in the lobby\r\n\t// anything that's lobby-dependent should go after this line\r\n\tScript::CScriptStructure* pTempStructure = new Script::CScriptStructure;\r\n\tpTempStructure->Clear();\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"level\"), ESYMBOLTYPE_NAME, (int)msg->m_LevelId );\t\t\t\t\t\r\n\tScript::RunScript( \"request_level\", pTempStructure, NULL );\r\n\tdelete pTempStructure;\r\n\r\n\tScript::RunScript( \"leave_front_end\" );\r\n\tScript::RunScript( \"cleanup_before_loading_level\" );\r\n\t\r\n\tcontext->m_Conn->UpdateCommTime();\t// update the current comm time so it doesn't time out after\r\n\t\t\t\t\t\t\t\t\t\t// laoding the level\r\n\r\n\tskate_mod->GetGameMode()->SetMaximumNumberOfPlayers( msg->m_MaxPlayers );\r\n\tskate_mod->GetGameMode()->LoadGameType( msg->m_GameMode );\r\n\t//skate_mod->GetGameMode()->SetMaximumNumberOfPlayers( msg->m_MaxPlayers );\r\n\tskate_mod->LaunchGame();\r\n\tskate_mod->GetGameMode()->LoadGameType( msg->m_GameMode );\r\n\tskate_mod->GetGameMode()->SetNumTeams( msg->m_TeamMode );\r\n\t\r\n\tgamenet_man->SetProSetFlags( msg->m_ProSetFlags );\r\n\tfor( i = 0; i < GameNet::vMAX_NUM_PROSETS; i++ )\r\n\t{\r\n\t\tif(( 1 << i ) & msg->m_ProSetFlags )\r\n\t\t{\r\n\t\t\tScript::CStruct* pSetParams;\r\n\t\t\tpSetParams = new Script::CStruct;\r\n\t\t\tpSetParams->AddInteger( \"flag\", Script::GetInt( \"FLAG_PROSET1_GEO_ON\" ) + i );\r\n\t\t\tScript::RunScript( \"SetFlag\", pSetParams );\r\n\t\t\tdelete pSetParams;\r\n\t\t}\r\n\t}\r\n\t\r\n    {\r\n\t\tScript::CScriptStructure* pTempStructure = new Script::CScriptStructure;\r\n\t\t\r\n\t\tif( msg->m_GameMode != Script::GenerateCRC(\"netlobby\" ))\r\n\t\t{\r\n\t\t\t// In king of the hill, interpret time limit as a target time\r\n\t\t\tif(\t( msg->m_TimeLimit == 0 ) &&\r\n\t\t\t\t( msg->m_GameMode != Script::GenerateCRC( \"netctf\" )) &&\r\n\t\t\t\t( msg->m_GameMode != Script::GenerateCRC( \"netgoalattack\" )))\r\n\t\t\t{\r\n\t\t\t\tif( ( msg->m_GameMode != CRCD(0x3d6d444f,\"firefight\")) &&\r\n\t\t\t\t\t( msg->m_GameMode != CRCD(0xbff33600,\"netfirefight\")))\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CArray* pArray = new Script::CArray;\r\n\t\t\t\t\tScript::CopyArray(pArray,Script::GetArray(\"targetScoreArray\"));\r\n\t\t\t\t\t\r\n\t\t\t\t\tScript::CScriptStructure* pSubStruct = pArray->GetStructure(0);\r\n\t\t\t\t\tDbg_Assert(pSubStruct);\r\n\t\t\t\t\tpSubStruct->AddComponent(Script::GenerateCRC(\"score\"),ESYMBOLTYPE_INTEGER, msg->m_TargetScore );\r\n\t\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"victory_conditions\"), pArray );\r\n\t\t\t\t}\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"default_time_limit\"), ESYMBOLTYPE_INTEGER, (int) 0 );\r\n\t\t\t\tskate_mod->SetTimeLimit( 0 );\r\n\t\t\t\tskate_mod->GetGameMode()->OverrideOptions( pTempStructure );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"default_time_limit\"), ESYMBOLTYPE_INTEGER, (int) msg->m_TimeLimit );\r\n\t\t\t\tif( msg->m_GameMode == Script::GenerateCRC( \"netctf\" ))\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CArray* pArray = new Script::CArray;\r\n\t\t\t\t\tScript::CopyArray(pArray,Script::GetArray(\"highestScoreArray\") );\r\n\t\t\t\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"victory_conditions\"), pArray );\r\n\t\t\t\t}\r\n\t\t\t\tskate_mod->SetTimeLimit( msg->m_TimeLimit );\r\n\t\t\t\tskate_mod->GetGameMode()->SetTimeLeft( msg->m_TimeLeft );\r\n\t\t\t\tskate_mod->GetGameMode()->OverrideOptions( pTempStructure );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tdelete pTempStructure;\r\n\t}\r\n\r\n\tif( gamenet_man->InNetGame())\r\n\t{\r\n\t\tmode_array = Script::GetArray( \"net_game_type_info\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmode_array = Script::GetArray( \"mp_game_type_info\" );\r\n\t}\r\n\tDbg_Assert( mode_array );\r\n\r\n\tfor( i = 0; i < (int)mode_array->GetSize(); i++ )\r\n\t{   \r\n\t\tuint32 value, script;\r\n\t\tScript::CStruct* mode_struct;\r\n\t\t \r\n\t\tmode_struct = mode_array->GetStructure( i );\r\n\t\tDbg_Assert( mode_struct );\r\n\t\t\r\n\t\tmode_struct->GetChecksum( \"checksum\", &value, true );\r\n\t\tif( value == msg->m_GameMode )\r\n\t\t{\r\n\t\t\tScript::CStruct* params;\r\n\t\t\t\t\t\t\r\n\t\t\tparams = new Script::CStruct;\r\n\t\t\tparams->AddInteger( \"time\", msg->m_TimeLimit );\r\n\t\t\tparams->AddInteger( \"score\", msg->m_TargetScore );\r\n\t\t\tif( msg->m_TimeLimit == 0 )\r\n\t\t\t{\r\n\t\t\t\tparams->AddInteger( CRCD(0xf0e712d2,\"unlimited_time\"), 1 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tparams->AddInteger( CRCD(0xf0e712d2,\"unlimited_time\"), 0 );\r\n\t\t\t}\r\n\t\t\t//Dbg_Printf( \"Target Score : %d\\n\", msg->m_TargetScore );\r\n\t\t\tmode_struct->GetChecksum( \"goal_script\", &script, true );\r\n\t\t\tScript::RunScript( script, params );\r\n\t\t\tdelete params;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif( ( gamenet_man->InNetGame()) &&\r\n\t\t( gamenet_man->GetJoinMode() == GameNet::vJOIN_MODE_PLAY ))\r\n\t{\r\n\t\tif( !CFuncs::ScriptIsObserving( NULL, NULL ))\r\n\t\t{\r\n\t\t\tgamenet_man->SendFaceDataToServer();\r\n\t\t}\r\n\t}\r\n\r\n    return Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/* Parse the object update stream from the server and update the  */\r\n/* appropriate objects                          \t\t\t\t  */\r\n/******************************************************************/\r\n\r\nint Skate::handle_object_update_relay( Net::MsgHandlerContext* context )\r\n{\r\n\tSkate* mod;\r\n\tint update_flags;\r\n\tunsigned char obj_id, obj_id_mask;\r\n\tNet::BitStream stream;\r\n    \r\n    Dbg_Assert( context );\r\n     \r\n\tmod = (Skate *) context->m_Data;\r\n\tstream.SetInputData( context->m_Msg, 1024 );\r\n\tobj_id_mask = stream.ReadUnsignedValue( sizeof( char ) * 8 );\r\n\t\r\n\tfor( obj_id = 0; obj_id < vMAX_SKATERS; obj_id++ )\r\n\t{\r\n\t\tGameNet::ObjectUpdate obj_update;\r\n\t\tObj::CMovingObject* obj;\r\n\t\tMth::Vector eulers;\r\n\t\tshort pos[3];\r\n\t\tshort fixed;\r\n\t\tchar doing_trick, state, terrain, walking, driving;\r\n\t\tFlags< int > skater_flags;\r\n\t\tFlags< int > end_run_flags;\r\n\t\tsint16 rail_node;\r\n\t\tint i;\r\n\t\tunsigned short timestamp;\r\n\t\t \r\n\t\t// If the bit for this player number is not set, that means there is no \r\n\t\t// object update for them. Continue\r\n\t\tif(( obj_id_mask & ( 1 << obj_id )) == 0 )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t//Dbg_Printf( \"================ Got update for player %d\\n\", obj_id );\r\n\r\n    \ttimestamp = stream.ReadUnsignedValue( sizeof( uint16 ) * 8 );\r\n\t\tupdate_flags = stream.ReadUnsignedValue( 9 );\r\n\t\t\r\n\t\t//Dbg_Printf( \"Got Object Update For %d, Time: %d Mask %d\\n\", obj_id, timestamp, obj_id_mask );\r\n\r\n\t\tdoing_trick = 0;\r\n\t\tstate = 0;\r\n\t\tskater_flags = 0;\r\n\t\tend_run_flags = 0;\r\n\t\tterrain = 0;\r\n\t\twalking = 0;\r\n\t\tdriving = 0;\r\n\t\trail_node = -1;\r\n        \r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_X )\r\n\t\t{   \r\n\t\t\tpos[X] = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t\t//pos[X] = stream.ReadFloatValue();\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_Y )\r\n\t\t{\r\n\t\t\tpos[Y] = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t\t//pos[Y] = stream.ReadFloatValue();\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_POS_Z )\r\n\t\t{\r\n\t\t\tpos[Z] = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t\t//pos[Z] = stream.ReadFloatValue();\r\n\t\t}   \r\n\t\t\t\t\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_X )\r\n\t\t{\r\n\t\t\tfixed = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t\teulers[X] = ((float) fixed ) / 4096.0f;\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_Y )\r\n\t\t{\r\n\t\t\tfixed = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t\teulers[Y] = ((float) fixed ) / 4096.0f;\r\n\t\t}\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_ROT_Z )\r\n\t\t{\r\n\t\t\tfixed = stream.ReadSignedValue( sizeof( short ) * 8 );\r\n\t\t\teulers[Z] = ((float) fixed ) / 4096.0f;\r\n\t\t}\r\n        \r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_STATE )\r\n\t\t{   \r\n\t\t\tchar mask;\r\n\r\n\t\t\tmask = stream.ReadUnsignedValue( 4 );\r\n\t\t\r\n\t\t\tstate = mask & GameNet::mSTATE_MASK;\r\n\t\t\tdoing_trick = (( mask & GameNet::mDOING_TRICK_MASK ) != 0 );\r\n\t\t\tterrain = stream.ReadUnsignedValue( 6 );\r\n\t\t\twalking = stream.ReadUnsignedValue( 1 );\r\n\t\t\tdriving = stream.ReadUnsignedValue( 1 );\r\n\t\t}\r\n\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_FLAGS )\r\n\t\t{\r\n\t\t\tskater_flags = stream.ReadUnsignedValue( 5 );\r\n\t\t\tend_run_flags = stream.ReadUnsignedValue( 3 );\r\n\t\t}\r\n\r\n\t\tif( update_flags & GameNet::mUPDATE_FIELD_RAIL_NODE )\r\n\t\t{\r\n\t\t\trail_node = stream.ReadSignedValue( sizeof( sint16 ) * 8 );\r\n\t\t\t//Dbg_Printf( \"Got rail node %d\\n\", rail_node );\r\n\t\t}\r\n\r\n\t\tobj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( obj_id );\r\n\t\t\r\n\t\t// Make sure that we actually have this object in our list of objects\r\n\t\t// Also, reject late/foreign object update messages. We still needed to do all the stream\r\n\t\t// parsing though because we need to return the length of the message to the dispatcher\r\n\t\tif( ( obj != NULL ) &&\r\n\t\t\t(( context->m_PacketFlags & ( Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN )) == 0 ))\r\n\t\t{\r\n\t\t\tObj::CSkater* skater_obj;\r\n\t\t\t \r\n\t\t\tskater_obj = static_cast< Obj::CSkater *> ( obj );\r\n\t\t\tDbg_MsgAssert( skater_obj != NULL,( \"Got object update for non-CSkater\\n\" ));\r\n\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\t\t\tif( skater_obj )\r\n\t\t\t{\r\n\t\t\t\tObj::SPosEvent* p_pos_history = skater_obj->GetStateHistory()->GetPosHistory();\r\n\t\t\t\t\r\n\t\t\t\tint index, last_index;\r\n\t\r\n\t\t\t\tif( skater_obj->GetStateHistory()->GetNumPosUpdates() > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tlast_index = ( skater_obj->GetStateHistory()->GetNumPosUpdates() - 1 ) % Obj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tMth::Matrix obj_matrix;\r\n\t\t\t\t\tMth::Vector eulers;\r\n\t\t\t\t\tlast_index = 0;\r\n\r\n\t\t\t\t\tobj_matrix = skater_obj->GetMatrix();\r\n\t\t\t\t\tobj_matrix.GetEulers( eulers );\r\n\t\t\t\t\tfor( i = 0; i < 3; i++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( i == Y )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_pos_history[0].ShortPos[i] = (short) ( skater_obj->m_pos[i] * 4.0f );\r\n\t\t\t\t\t\t\t//p_pos_history[0].ShortPos[i] = skater_obj->m_pos[i];\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_pos_history[0].ShortPos[i] = (short) ( skater_obj->m_pos[i] * 2.0f );\r\n\t\t\t\t\t\t\t//p_pos_history[0].ShortPos[i] = skater_obj->m_pos[i];\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tp_pos_history[0].Eulers[i] = eulers[i];\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tindex = skater_obj->GetStateHistory()->GetNumPosUpdates() % Obj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;\r\n\t\t\t\t\r\n                if( !(  update_flags & GameNet::mUPDATE_FIELD_POS_X ))\r\n\t\t\t\t{\r\n\t\t\t\t\tpos[X] = p_pos_history[last_index].ShortPos[X];\r\n\t\t\t\t}\r\n\t\t\t\tif( !(  update_flags & GameNet::mUPDATE_FIELD_POS_Y ))\r\n\t\t\t\t{\r\n\t\t\t\t\tpos[Y] = p_pos_history[last_index].ShortPos[Y];\r\n\t\t\t\t}\r\n\t\t\t\tif( !(  update_flags & GameNet::mUPDATE_FIELD_POS_Z ))\r\n\t\t\t\t{\r\n\t\t\t\t\tpos[Z] = p_pos_history[last_index].ShortPos[Z];\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tfor( i = 0; i < 3; i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_pos_history[index].ShortPos[i] = pos[i];\r\n\t\t\t\t}\r\n\r\n\t\t\t\tobj_update.m_Pos.Set(\t((float) pos[X] ) / 2.0f,//pos[X],\r\n\t\t\t\t\t\t\t\t\t\t((float) pos[Y] ) / 4.0f,//pos[Y],\r\n\t\t\t\t\t\t\t\t\t\t((float) pos[Z] ) / 2.0f,//pos[Z],\r\n\t\t\t\t\t\t\t\t\t\t0.0f );\r\n\t\t\t\t//Dbg_Printf( \"*** Got Pos[%.2f %.2f %.2f]\\n\", obj_update.m_Pos[X], obj_update.m_Pos[Y], obj_update.m_Pos[Z] );\r\n\r\n\t\t\t\tif( !(  update_flags & GameNet::mUPDATE_FIELD_ROT_X ))\r\n\t\t\t\t{\r\n\t\t\t\t\teulers[X] = p_pos_history[last_index].Eulers[X];\r\n\t\t\t\t}\r\n\t\t\t\tif( !(  update_flags & GameNet::mUPDATE_FIELD_ROT_Y ))\r\n\t\t\t\t{\r\n\t\t\t\t\teulers[Y] = p_pos_history[last_index].Eulers[Y];\r\n\t\t\t\t}\r\n\t\t\t\tif( !(  update_flags & GameNet::mUPDATE_FIELD_ROT_Z ))\r\n\t\t\t\t{\r\n\t\t\t\t\teulers[Z] = p_pos_history[last_index].Eulers[Z];\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Update history\r\n\t\t\t\tfor( i = 0; i < 3; i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_pos_history[index].Eulers[i] = eulers[i];\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Use those euler angles to compose a matrix\r\n\t\t\t\tMth::Matrix obj_matrix( eulers[X], eulers[Y], eulers[Z] );\r\n\t\t\t\tobj_update.m_Matrix = obj_matrix;\r\n\r\n                p_pos_history[index].Matrix = obj_update.m_Matrix;\r\n\t\t\t\tp_pos_history[index].Position = obj_update.m_Pos;\r\n                \r\n\t\t\t\tMth::Vector vel;\r\n\t\t\t\tvel = p_pos_history[index].Position - p_pos_history[last_index].Position;\r\n\t\t\t\t//Dbg_Printf( \"(%d) Vel: %f %f %f\\n\", timestamp, vel[X], vel[Y], vel[Z] );\r\n\r\n\t\t\t\tif( !( update_flags & GameNet::mUPDATE_FIELD_STATE ))\r\n\t\t\t\t{\r\n\t\t\t\t\tstate = p_pos_history[last_index].State;\r\n\t\t\t\t\tdoing_trick = p_pos_history[last_index].DoingTrick;\r\n\t\t\t\t\tterrain = p_pos_history[last_index].Terrain;\r\n\t\t\t\t\twalking = p_pos_history[last_index].Walking;\r\n\t\t\t\t\tdriving = p_pos_history[last_index].Driving;\r\n\t\t\t\t}\r\n\t\t\t\tif( !( update_flags & GameNet::mUPDATE_FIELD_FLAGS ))\r\n\t\t\t\t{\r\n\t\t\t\t\tskater_flags = p_pos_history[last_index].SkaterFlags;\r\n\t\t\t\t\tend_run_flags = p_pos_history[last_index].EndRunFlags;\r\n\t\t\t\t}\r\n\t\t\t\tif( !( update_flags & GameNet::mUPDATE_FIELD_RAIL_NODE ))\r\n\t\t\t\t{\r\n\t\t\t\t\trail_node = p_pos_history[last_index].RailNode;\r\n\t\t\t\t}\r\n                \r\n\t\t\t\tp_pos_history[index].SkaterFlags = skater_flags;\r\n\t\t\t\tp_pos_history[index].EndRunFlags = end_run_flags;\r\n\t\t\t\tp_pos_history[index].RailNode = rail_node;\r\n\t\t\t\tp_pos_history[index].State = state;\r\n\t\t\t\tp_pos_history[index].DoingTrick = doing_trick;\r\n\t\t\t\tp_pos_history[index].Terrain = (ETerrainType) terrain;\r\n\t\t\t\tp_pos_history[index].Walking = walking;\r\n\t\t\t\tp_pos_history[index].Driving = driving;\r\n\r\n\t\t\t\t// Update the lo and hi words of the timestamp\r\n\t\t\t\tp_pos_history[index].HiTime = p_pos_history[last_index].HiTime;\r\n\r\n\t\t\t\t// If the lo-word has flipped, increment the hi-word\r\n\t\t\t\tif( p_pos_history[last_index].LoTime > timestamp )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_pos_history[index].HiTime++;\r\n\t\t\t\t}\r\n\t\t\t\tp_pos_history[index].LoTime = timestamp;\r\n\t\t\t\t//Dbg_Printf( \"(%d) Got time: %d\\n\", context->m_App->m_FrameCounter, p_pos_history[index].GetTime());\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\tskater_obj->GetStateHistory()->IncrementNumPosUpdates();\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\t\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::StartServer( void )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance(); \r\n\tNet::Server* server;\r\n\tbool net_game;\r\n\r\n\tnet_game = false;\r\n\t// prevents fragmentation\r\n\t//CFuncs::ScriptCleanup( NULL, NULL );\r\n\tif( gamenet_man->InNetMode())\r\n\t{\t\r\n\t\tnet_game = true;\r\n\t\tgamenet_man->ClientShutdown();\r\n\t}\r\n\t\r\n\tserver = gamenet_man->SpawnServer( !net_game, true );\r\n\tif( server == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tmlp_manager->AddLogicTask ( *m_object_update_task );\r\n\tmlp_manager->AddLogicTask ( *m_score_update_task );\r\n\t\r\n\t// These handlers remaio active throughout the server's life\r\n\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_SCORE, handle_score_request );\r\n\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_LANDED_TRICK, handle_landed_trick, 0, this );\r\n\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_COMBO_REPORT, handle_combo_report, 0, this );\r\n    server->m_Dispatcher.AddHandler( GameNet::MSG_ID_CHAT, handle_msg_relay, Net::mHANDLE_LATE );\r\n\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_BAIL_DONE, handle_bail_done, Net::mHANDLE_LATE );\r\n\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_OBJ_UPDATE_STREAM, handle_object_update, \r\n\t\t\t\t\t\t\t\t\t Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN );\r\n\r\n\t// In Split Screen Games, Don't relay any messages\r\n\tif( !server->IsLocal())\r\n\t{\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_FACE_DATA, handle_face_data );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPAWN_PROJECTILE, handle_msg_relay, 0, this );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_ENTER_VEHICLE, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_ENTER_VEHICLE, handle_enter_vehicle_server );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_PRIM_ANIM_START, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_WOBBLE_TARGET, handle_selective_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_ROTATE_SKATEBOARD, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_ROTATE_DISPLAY, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_CLEAR_ROTATE_DISPLAY, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_CREATE_SPECIAL_ITEM, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_DESTROY_SPECIAL_ITEM, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_FLIP_ANIM, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_WOBBLE_DETAILS, handle_selective_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_LOOPING_TYPE, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_HIDE_ATOMIC, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_ANIM_SPEED, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_PLAY_SOUND, handle_selective_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_PLAY_LOOPING_SOUND, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_BLOOD_ON, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_BLOOD_OFF, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPARKS_ON, handle_msg_relay );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPARKS_OFF, handle_msg_relay, Net::mHANDLE_LATE );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_RUN_SCRIPT, handle_script_relay, Net::mHANDLE_LATE );\r\n\t\tserver->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPAWN_AND_RUN_SCRIPT, handle_script_relay, Net::mHANDLE_LATE );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Skate::LaunchNetworkGame( void )\r\n{\r\n\tRestartLevel();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tSkate::AddNetworkMsgHandlers( Net::Client* client, int index )\r\n{\r\n\tObj::CSkater* skater;\r\n\t\r\n\tDbg_Assert( client );\r\n    \r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_START_INFO, handle_start_info, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_OBJ_UPDATE_STREAM, handle_object_update_relay, \r\n\t\t\t\t\t\t\t\t\t Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_PRIM_ANIM_START, handle_anims, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_TOGGLE_CHEAT, handle_cheats, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_WOBBLE_TARGET, handle_anims, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_ROTATE_DISPLAY, handle_anims, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_CLEAR_ROTATE_DISPLAY, handle_anims, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_CREATE_SPECIAL_ITEM, handle_anims, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_DESTROY_SPECIAL_ITEM, handle_anims, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_ROTATE_SKATEBOARD, handle_anims, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_FLIP_ANIM, handle_anims, 0, this, Net::HIGHEST_PRIORITY );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_FLIP_ANIM, handle_flip_anim, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_WOBBLE_DETAILS, handle_anims, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_LOOPING_TYPE, handle_anims, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_HIDE_ATOMIC, handle_anims, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_ANIM_SPEED, handle_anims, 0, this );     \r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_PLAYER_QUIT, handle_player_quit, \r\n\t\t\t\t\t\t\t\t\t Net::mHANDLE_LATE, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_HOST_QUIT, handle_disconn_accepted, \r\n\t\t\t\t\t\t\t\t\t Net::mHANDLE_LATE, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_PLAY_SOUND, handle_play_sound, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_PLAY_LOOPING_SOUND, handle_play_sound, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPARKS_ON, handle_sparks, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPARKS_OFF, handle_sparks, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_BLOOD_ON, handle_blood, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_BLOOD_OFF, handle_blood, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SCORE_UPDATE, handle_score_update, \r\n\t\t\t\t\t\t\t\t\t Net::mHANDLE_LATE, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_CHANGE_LEVEL, handle_change_level, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_RUN_SCRIPT, handle_run_script, Net::mHANDLE_LATE, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPAWN_AND_RUN_SCRIPT, handle_spawn_run_script, Net::mHANDLE_LATE, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_KICKED, handle_kicked, Net::mHANDLE_LATE, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_LEFT_OUT, handle_kicked, Net::mHANDLE_LATE, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_OBSERVER_LOG_TRICK_OBJ, handle_obs_log_trick_objects, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_OBSERVER_INIT_GRAFFITI_STATE, handle_obs_init_graffiti_state, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_FACE_DATA, handle_face_data, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_CHEAT_LIST, handle_cheat_list, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPAWN_PROJECTILE, handle_projectile, 0, this );\r\n\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_ENTER_VEHICLE, handle_enter_vehicle_client, 0, this );\r\n\r\n\tfor( uint i = 0; i < vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tskater = GetSkater( i );\r\n\t\tif( skater && skater->IsLocalClient() && ( skater->GetHeapIndex() == index ))\r\n\t\t{\r\n\t\t\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SCORE, Mdl::Score::s_handle_score_message, 0, skater );\r\n\t\t\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SKATER_COLLIDE_WON, Obj::CSkaterStateHistoryComponent::sHandleCollision, 0, skater );\r\n\t\t\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SKATER_COLLIDE_LOST, Obj::CSkaterStateHistoryComponent::sHandleCollision, 0, skater );\r\n\t\t\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SKATER_PROJECTILE_HIT_TARGET, Obj::CSkaterStateHistoryComponent::sHandleProjectileHit, 0, skater );\r\n\t\t\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SKATER_HIT_BY_PROJECTILE, Obj::CSkaterStateHistoryComponent::sHandleProjectileHit, 0, skater );\r\n\t\t\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_STEAL_MESSAGE, Obj::CSkaterLocalNetLogicComponent::sHandleStealMessage, 0, skater );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tSkate::LeaveServer( void )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tNet::Client* client;\r\n    \r\n\t\r\n    \r\n\tif( gamenet_man->OnServer())\r\n\t{   \r\n\t\tNet::App* server;\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tserver = gamenet_man->GetServer();\r\n\t\tDbg_Assert( server );\r\n\r\n\t\t// If we were auto serving, shut that service down\r\n\t\tif( gamenet_man->GetHostMode() == GameNet::vHOST_MODE_AUTO_SERVE )\r\n\t\t{\r\n\t\t\tgamenet_man->AutoServerShutdown();\r\n\t\t}\r\n\r\n\t\t// First, wait for any pending network tasks to finish before sending out final disconn\r\n\t\t// message\r\n#ifdef __PLAT_NGPS__\r\n\t\t//server->WaitForAsyncCallsToFinish();\r\n#endif  \t\t\r\n\r\n\t\t// Send off last message, notifying clients that I'm about to quit\r\n\t\tDbg_Printf( \"Starting server shutdown\\n\" );\r\n\t\tmsg_desc.m_Id = GameNet::MSG_ID_HOST_QUIT;\r\n\t\tmsg_desc.m_Priority = Net::HIGHEST_PRIORITY;\r\n\t\tserver->EnqueueMessage( Net::HANDLE_ID_BROADCAST, &msg_desc );\r\n\t\t// Wake the network thread up to send the data\r\n\t\tserver->SendData();\r\n\t\t\r\n\t\t// Wait for that final send to complete\r\n#ifdef __PLAT_NGPS__\r\n\t\t//server->WaitForAsyncCallsToFinish();\r\n#endif  \r\n\t\tgamenet_man->ServerShutdown();\r\n\r\n\t\tm_object_update_task->Remove();\r\n\t\tm_score_update_task->Remove();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tclient = gamenet_man->GetClient( 0 );\r\n\t\tif( client )\r\n\t\t{\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\t// First, wait for any pending network tasks to finish before sending out final disconn\r\n\t\t\t// message\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t//client->WaitForAsyncCallsToFinish();\r\n#endif  \t\t\r\n\t\t\tDbg_Printf( \"Leaving server\\n\" );\r\n\t\t\t\r\n\t\t\tmsg_desc.m_Id = Net::MSG_ID_DISCONN_REQ;\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\t// Send off last message, notifying server that I'm about to quit\r\n\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t\t// Wake the network thread up to send the data\r\n\t\t\tclient->SendData();\r\n\t\t\r\n\t\t\t// Wait for that final send to complete\r\n#ifdef __PLAT_NGPS__\r\n\t\t\t//client->WaitForAsyncCallsToFinish();\r\n#endif  \r\n\r\n\t\t}\r\n\t}\r\n    \r\n\tgamenet_man->DisconnectFromServer();\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tSkate::SetLaunchingQueuedScripts( void )\r\n{\r\n\tm_launching_queued_scripts = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tSkate::ClearLaunchingQueuedScripts( void )\r\n{\r\n\tm_launching_queued_scripts = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tSkate::LaunchingQueuedScripts( void )\r\n{\r\n\treturn m_launching_queued_scripts;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tSkate::SendCheatList( GameNet::PlayerInfo* player )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tGameNet::MsgEnabledCheats cheat_msg;\r\n\tNet::MsgDesc msg_desc;\r\n\r\n\tcheat_msg.m_NumCheats = 0;\r\n\r\n\tif( mp_career->GetCheat( CRCD(0xeefecf1b, \"CHEAT_ALWAYS_SPECIAL\")))\r\n\t{\r\n\t\tcheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xeefecf1b, \"CHEAT_ALWAYS_SPECIAL\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0xb38341c9, \"CHEAT_PERFECT_MANUAL\")))\r\n\t{\r\n\t\tcheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xb38341c9, \"CHEAT_PERFECT_MANUAL\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0xcd09e062, \"CHEAT_PERFECT_RAIL\")))\r\n\t{\r\n\t\tcheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xcd09e062, \"CHEAT_PERFECT_RAIL\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0x69a1ce96, \"CHEAT_PERFECT_SKITCH\")))\r\n\t{\r\n\t\tcheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0x69a1ce96, \"CHEAT_PERFECT_SKITCH\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0xeefecf1b, \"CHEAT_ALWAYS_SPECIAL\")))\r\n\t{\r\n\t\tcheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xeefecf1b, \"CHEAT_ALWAYS_SPECIAL\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0x6b0f24bc, \"CHEAT_STATS_13\")))\r\n\t{\r\n\t\tcheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0x6b0f24bc, \"CHEAT_STATS_13\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0x520a66ef,\"FLAG_G_EXPERT_MODE_NO_REVERTS\")))\r\n\t{\r\n\t\tcheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0x520a66ef,\"FLAG_G_EXPERT_MODE_NO_REVERTS\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0xeba89179,\"FLAG_G_EXPERT_MODE_NO_WALKING\")))\r\n\t{\r\n\t\tcheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xeba89179,\"FLAG_G_EXPERT_MODE_NO_WALKING\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0xc4ffc672,\"FLAG_G_EXPERT_MODE_NO_MANUALS\")))\r\n\t{\r\n\t\tcheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xc4ffc672,\"FLAG_G_EXPERT_MODE_NO_MANUALS\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0xd5982173,\"NO_G_DISPLAY_BALANCE\")))\r\n\t{\r\n\t\tcheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xd5982173,\"NO_G_DISPLAY_BALANCE\");\r\n\t}\r\n\r\n\t// Send it, even if there are zero cheats. This triggers the clearing of all cheats on\r\n\t// the client side\r\n\tmsg_desc.m_Id = GameNet::MSG_ID_CHEAT_LIST;\r\n\tmsg_desc.m_Data = &cheat_msg;\r\n\tmsg_desc.m_Length = sizeof( int ) +( sizeof( uint32 ) * cheat_msg.m_NumCheats );\r\n\r\n\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\r\n\tgamenet_man->GetServer()->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tSkate::GetCheatChecksum( void )\r\n{\r\n\tuint32 checksum;\r\n\r\n\tchecksum = 0;\r\n\t\r\n\tif( mp_career->GetCheat( CRCD(0xeefecf1b, \"CHEAT_ALWAYS_SPECIAL\")))\r\n\t{\r\n\t\tchecksum |= CRCD(0xeefecf1b, \"CHEAT_ALWAYS_SPECIAL\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0xb38341c9, \"CHEAT_PERFECT_MANUAL\")))\r\n\t{\r\n\t\tchecksum |= CRCD(0xb38341c9, \"CHEAT_PERFECT_MANUAL\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0xcd09e062, \"CHEAT_PERFECT_RAIL\")))\r\n\t{\r\n\t\tchecksum |= CRCD(0xcd09e062, \"CHEAT_PERFECT_RAIL\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0x69a1ce96, \"CHEAT_PERFECT_SKITCH\")))\r\n\t{\r\n\t\tchecksum |= CRCD(0x69a1ce96, \"CHEAT_PERFECT_SKITCH\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0xeefecf1b, \"CHEAT_ALWAYS_SPECIAL\")))\r\n\t{\r\n\t\tchecksum |= CRCD(0xeefecf1b, \"CHEAT_ALWAYS_SPECIAL\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0x6b0f24bc, \"CHEAT_STATS_13\")))\r\n\t{\r\n\t\tchecksum |= CRCD(0x6b0f24bc, \"CHEAT_STATS_13\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0x520a66ef,\"FLAG_G_EXPERT_MODE_NO_REVERTS\")))\r\n\t{\r\n\t\tchecksum |= CRCD(0x520a66ef,\"FLAG_G_EXPERT_MODE_NO_REVERTS\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0xeba89179,\"FLAG_G_EXPERT_MODE_NO_WALKING\")))\r\n\t{\r\n\t\tchecksum |= CRCD(0xeba89179,\"FLAG_G_EXPERT_MODE_NO_WALKING\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0xc4ffc672,\"FLAG_G_EXPERT_MODE_NO_MANUALS\")))\r\n\t{\r\n\t\tchecksum |= CRCD(0xc4ffc672,\"FLAG_G_EXPERT_MODE_NO_MANUALS\");\r\n\t}\r\n\tif( mp_career->GetCheat( CRCD(0xd5982173,\"NO_G_DISPLAY_BALANCE\")))\r\n\t{\r\n\t\tchecksum |= CRCD(0xd5982173,\"NO_G_DISPLAY_BALANCE\");\r\n\t}\r\n\r\n\treturn checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mdl\r\n"
  },
  {
    "path": "Code/Sk/Modules/Viewer/Viewer.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2001 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tViewer\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tViewer.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t11/28/01\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tViewer module\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gel/inpman.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n\r\n\r\n#include <gfx/nxviewman.h>\r\n\r\n#include <modules/viewer/viewer.h>\r\n\r\n#include <sk/objects/viewerobj.h>\r\n#include <sk/objects/skater.h>\t\t\t// just to see if the select button is pressed!!!\r\n\r\n#include <gamenet/exportmsg.h>\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#include <scripting/gs_file.h>\r\n#include <gel/scripting/utils.h>\r\n\r\n#include <sys/config/config.h>\r\n#include <sys/profiler.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool\trun_runmenow = false;\t\t// patch for signalling that the runnow script should be run\r\n\r\nnamespace Mdl\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nfloat\tCViewer::s_movement_vel;\t// in inches per sec\r\nfloat\tCViewer::s_rotate_vel;\t// in degrees per sec\r\nint\t\tCViewer::s_view_mode=0;\r\n\r\n// GJ:  I'm assuming that there's only going to be one CViewer at a time.\r\n// I needed to be able to access this class from cfuncs.cpp, so I added\r\n// this pointer.  Perhaps when Steve gets back from his surgery, we can\r\n// decide a more appropriate interface between cfuncs.cpp and viewer.cpp.\r\nCViewer* CViewer::sp_viewer = NULL;\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid        CViewer::s_shift_input_logic_code ( const Inp::Handler < CViewer >& handler )\r\n{\r\n\tDbg_AssertType ( &handler, Inp::Handler< CViewer > );\r\n\r\n\tCViewer&   mdl = handler.GetData();\r\n\r\n\tmdl.m_shift_commands.ClearAll();\r\n\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_SELECT )\r\n\t{\r\n\t\tmdl.m_shift_commands.SetMask( handler.m_Input->m_Makes );\r\n\t\tif (Script::GetInt(CRCD(0xf3e055e1,\"select_shift\")))\r\n\t\t{\r\n\t\t\t// only mask the buttons if we are using select as a shift button \r\n\t\t\thandler.m_Input->MaskDigitalInput( Inp::Data::mD_ALL && ~Inp::Data::mD_LEFT && ~Inp::Data::mD_RIGHT && ~Inp::Data::mD_UP && ~Inp::Data::mD_DOWN);\r\n\t\t\thandler.m_Input->MaskAnalogInput( Inp::Data::mA_ALL && ~Inp::Data::mA_LEFT && ~Inp::Data::mA_RIGHT && ~Inp::Data::mA_UP && ~Inp::Data::mA_DOWN && ~Inp::Data::mA_LEFT_X && ~Inp::Data::mA_LEFT_Y && ~Inp::Data::mA_RIGHT_X && ~Inp::Data::mA_RIGHT_Y );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCViewer::s_input_logic_code ( const Inp::Handler < CViewer >& handler )\r\n{       \r\n\tCViewer&\tmdl = handler.GetData();\r\n\r\n//\tprintf (\"s_view_mode = %d   rightx = %d\\n\",s_view_mode,mdl.m_right[X]);\r\n\r\n// just return if we are not in viewer mode\r\n\tif (!s_view_mode)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\t\t\t\t\t  \r\n\t// GJ:  no longer clearing the last frame's data\r\n\t// at the beginning of the loop...  this allows\r\n\t// the viewer object to add additional m_commands\r\n\t// to the viewer (useful for customizing controller\r\n\t// configs in different viewer modes)\r\n//\tmdl.m_commands.ClearAll();\r\n\r\n\t// translate m_Input data to module-specific commands\r\n\tmdl.m_right[X] = handler.m_Input->m_Event[Inp::Data::vA_RIGHT_X_UNCLAMPED] - 128;\r\n\tmdl.m_right[Y] = handler.m_Input->m_Event[Inp::Data::vA_RIGHT_Y_UNCLAMPED] - 128;\r\n\tmdl.m_left[X] = handler.m_Input->m_Event[Inp::Data::vA_LEFT_X_UNCLAMPED] - 128;\r\n\tmdl.m_left[Y] = handler.m_Input->m_Event[Inp::Data::vA_LEFT_Y_UNCLAMPED] - 128;\r\n\r\n\r\n\tif (Script::GetInt(CRCD(0x89bef647,\"viewer_buttons_enabled\")))\r\n\t{\r\n\t\tif( ( handler.m_Input->m_Buttons & Inp::Data::mD_R1 ) &&\r\n\t\t\t( handler.m_Input->m_Makes & Inp::Data::mD_R2 ))\r\n\t\t{\r\n\t\t\tif (!Config::CD())\r\n\t\t\t{\r\n\t//  Mick - took out viewport changing for non-PS2, as it messes up X-Box artists, with only one shoulder button\r\n\t\t\t\t#ifdef\t__PLAT_NGPS__\r\n\t\t\t\tmdl.m_commands.SetMask( mCHANGE_SCREEN_MODE );\r\n\t\t\t\t#endif\r\n\t\t\t}\t\r\n\t\t}\r\n\t\telse if( handler.m_Input->m_Buttons & Inp::Data::mD_R1 )\r\n\t\t{\r\n\t\t\tif( !( handler.m_Input->m_Buttons & Inp::Data::mD_R2 ))\r\n\t\t\t{\r\n\t\t\t\tmdl.m_commands.SetMask( mSTRAFE_UP );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if( handler.m_Input->m_Buttons & Inp::Data::mD_R2 )\r\n\t\t{\r\n\t\t\tmdl.m_commands.SetMask( mSTRAFE_DOWN );\r\n\t\t}\r\n\t\t\r\n\t//\tif (!Config::CD())\r\n\t\t{\r\n\t\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_START )\r\n\t\t\t{\r\n\t\t\t\tmdl.m_commands.SetMask( mRESET );\r\n\t\t\t}\r\n\t\t\tif( mdl.m_rotation_mode == vROTATE_CAMERA )\r\n\t\t\t{   \r\n\t\t\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_TRIANGLE )\r\n\t\t\t\t{\r\n\t\t\t\t\tmdl.m_commands.SetMask( mVIEW_TOP );\r\n\t\t\t\t}\r\n\t\t\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_SQUARE )\r\n\t\t\t\t{\r\n\t\t\t\t\tmdl.m_commands.SetMask( mVIEW_LEFT );\r\n\t\t\t\t}\r\n\t\t\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_CIRCLE )\r\n\t\t\t\t{\r\n\t\t\t\t\tmdl.m_commands.SetMask( mVIEW_RIGHT );\r\n\t\t\t\t}\r\n\t\t\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_X )\r\n\t\t\t\t{\r\n\t\t\t\t\tmdl.m_commands.SetMask( mVIEW_FRONT );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if( mdl.m_rotation_mode == vROTATE_OBJECTS )\r\n\t\t\t{\r\n\t\t\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_X )\r\n\t\t\t\t{\r\n\t\t\t\t\tmdl.m_commands.SetMask( mRESET_ROTATIONS );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif( handler.m_Input->m_Buttons & Inp::Data::mD_UP )\r\n\t\t\t{\r\n\t\t\t\tif ( handler.m_Input->m_Makes & Inp::Data::mD_UP )\r\n\t\t\t\t{\r\n\t\t\t\t\tmdl.m_commands.SetMask( mLIGHT_FW );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif( handler.m_Input->m_Buttons & Inp::Data::mD_DOWN )\r\n\t\t\t{\r\n\t\t\t\tif ( handler.m_Input->m_Makes & Inp::Data::mD_DOWN )\r\n\t\t\t\t{\r\n\t\t\t\t\tmdl.m_commands.SetMask( mLIGHT_BK );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif( handler.m_Input->m_Buttons & Inp::Data::mD_RIGHT )\r\n\t\t\t{\r\n\t\t\t\tmdl.m_commands.SetMask( mLIGHT_RT );\r\n\t\t\t}\r\n\t\t\tif( handler.m_Input->m_Buttons & Inp::Data::mD_LEFT )\r\n\t\t\t{\r\n\t\t\t\tmdl.m_commands.SetMask( mLIGHT_LT );\r\n\t\t\t}\r\n\t\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_L3 )\r\n\t\t\t{\r\n\t\t\t\tmdl.m_commands.SetMask( mTOGGLE_ROTATE_MODE );\r\n\t\t\t}\r\n\t\t\tif ( handler.m_Input->m_Buttons & Inp::Data::mD_L1 )\r\n\t\t\t{\r\n\t\t\t\tif ( !( handler.m_Input->m_Buttons & Inp::Data::mD_L2 ))\r\n\t\t\t\t{\r\n\t\t\t\t\tmdl.m_commands.SetMask( mROLL_LEFT );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( handler.m_Input->m_Buttons & Inp::Data::mD_L2 )\r\n\t\t\t{\r\n\t\t\t\tmdl.m_commands.SetMask( mROLL_RIGHT );\r\n\t\t\t}\r\n\t\r\n\t\t\t\r\n\t\t\tif ( ! (handler.m_Input->m_Buttons & Inp::Data::mD_SELECT) )\r\n\t\t\t{\r\n\t\t\t\t// Patch on buttonscript calls to center the camera in various ways when in a view mode\r\n\t\t\t\tif ( handler.m_Input->m_Makes & Inp::Data::mD_SQUARE )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(\"UserViewerSquare\");\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif ( handler.m_Input->m_Makes & Inp::Data::mD_CIRCLE )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(\"UserViewerCIRCLE\");\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif ( handler.m_Input->m_Makes & Inp::Data::mD_TRIANGLE )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(\"UserViewerTRIANGLE\");\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif ( handler.m_Input->m_Makes & Inp::Data::mD_X )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(\"UserViewerX\");\r\n\t\t\t\t}\r\n\t\t\t}\t\t\r\n\t\t\t\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCViewer::s_logic_code ( const Tsk::Task< CViewer >& task )\r\n{\r\n\tCViewer&\tmdl = task.GetData();\r\n\r\n\tDbg_AssertType ( &task, Tsk::Task< CViewer > );\r\n\r\n\t//static const    float   ldelta = 1.0f;\r\n\t//static const    float   lcolordelta = .0125f;\r\n\tstatic const    float   scale = ( 1.0f / ( 128.0f - Inp::vANALOGUE_TOL ));\r\n\r\n//    Gfx::Camera* pCam = Nx::CViewportManager::sGetCamera( 0 );\r\n//\tif ( !pCam )\r\n//\t{\r\n//\t\treturn;\r\n//\t}\r\n\r\n\tfloat elapsed_seconds;\r\n\tTmr::Time elapsed_time;\r\n\tstatic Tmr::Time last_time = 0;\r\n\r\n\t// store the old camera pos before updating anything...\r\n//\tpCam->StoreOldPos( );\r\n\r\n\telapsed_time = Tmr::ElapsedTime( last_time );\r\n\telapsed_seconds = (int)elapsed_time / 1000.0f;\r\n\tlast_time = last_time + elapsed_time;   \r\n\r\n\tif ( mdl.m_commands.TestMask( mTOGGLE_ROTATE_MODE ))\r\n\t{\r\n\t\t// Mick: Don't switch to rotating the camera around the object unless there is an object\r\n\t\tif ( mdl.mp_viewerObject && mdl.m_rotation_mode == vROTATE_CAMERA )\r\n\t\t{\r\n\t\t\tmdl.m_rotation_mode = vROTATE_OBJECTS;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmdl.m_rotation_mode = vROTATE_CAMERA;\r\n\t\t}      \r\n\t}\r\n\r\n\tmdl.m_right[Y] =\r\n\t( mdl.m_right[Y] >  Inp::vANALOGUE_TOL ) ? ( mdl.m_right[Y] - Inp::vANALOGUE_TOL ) * scale :\r\n\t( mdl.m_right[Y] < -Inp::vANALOGUE_TOL ) ? ( mdl.m_right[Y] + Inp::vANALOGUE_TOL ) * scale : 0.0f;\r\n\tmdl.m_right[X] =\r\n\t( mdl.m_right[X] >  Inp::vANALOGUE_TOL ) ? ( mdl.m_right[X] - Inp::vANALOGUE_TOL ) * scale :\r\n\t( mdl.m_right[X] < -Inp::vANALOGUE_TOL ) ? ( mdl.m_right[X] + Inp::vANALOGUE_TOL ) * scale : 0.0f;\r\n\r\n\tmdl.m_left[Y] =\r\n\t( mdl.m_left[Y] >  Inp::vANALOGUE_TOL ) ? ( mdl.m_left[Y] - Inp::vANALOGUE_TOL ) * scale :\r\n\t( mdl.m_left[Y] < -Inp::vANALOGUE_TOL ) ? ( mdl.m_left[Y] + Inp::vANALOGUE_TOL ) * scale : 0.0f;\r\n\tmdl.m_left[X] =\r\n\t( mdl.m_left[X] >  Inp::vANALOGUE_TOL ) ? ( mdl.m_left[X] - Inp::vANALOGUE_TOL ) * scale :\r\n\t( mdl.m_left[X] < -Inp::vANALOGUE_TOL ) ? ( mdl.m_left[X] + Inp::vANALOGUE_TOL ) * scale : 0.0f;\r\n\r\n\tObj::CCompositeObject * p_obj = (Obj::CCompositeObject *) Obj::CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0xeb17151b,\"viewer_cam\"));\r\n\tif (p_obj)\r\n\t{\r\n\t\tif ( mdl.m_rotation_mode == vROTATE_CAMERA )\r\n\t\t{\r\n\t\t\tif (mdl.m_left[Y])\r\n\t\t\t{\r\n\t\t\t\tp_obj->GetMatrix().RotateLocal( Mth::Vector( 1, 0, 0 ),\r\n\t\t\t\t\t\t\tmdl.m_left[Y] * elapsed_seconds * mdl.s_rotate_vel * Mth::PI / 180.0f );\r\n\t\t\t}\r\n\t\t\tif (mdl.m_left[X])\r\n\t\t\t{\r\n\t\t\t\t// this rotation is *NOT* local, as the designers seem to prefer it this way.\r\n\t\t\t\tMth::Matrix mat = p_obj->GetMatrix();\r\n\t\t\t\tmat.RotateY( -mdl.m_left[X] * elapsed_seconds * mdl.s_rotate_vel * Mth::PI / 180.0f );\r\n\t\t\t\tp_obj->SetMatrix( mat );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( mdl.m_rotation_mode == vROTATE_OBJECTS )\r\n\t\t{\r\n\t\t\tDbg_Assert( mdl.mp_viewerObject );\r\n\t\t\tmdl.mp_viewerObject->SetRotation( mdl.m_left[X], mdl.m_left[Y] );\r\n\t\t}\r\n\r\n\r\n\t\r\n\t\t// Move with right analog stick:\r\n\t\tif (mdl.m_right[X] || mdl.m_right[Y])\r\n\t\t{\r\n\t\t\tMth::Vector transVec;\r\n\t\t\ttransVec[X] = mdl.m_right[X] * ( elapsed_seconds * mdl.s_movement_vel );\r\n\t\t\ttransVec[Y] = 0.0f;\r\n\t\t\ttransVec[Z] = mdl.m_right[Y] * ( elapsed_seconds * mdl.s_movement_vel );\r\n\t\t\ttransVec[W] = 1.0f;\r\n\t\t\ts_translate_local( p_obj, transVec );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( mdl.m_commands.TestMask( mSTRAFE_UP ))\r\n\t{\r\n\t\ts_translate_local( p_obj, Mth::Vector( 0, elapsed_seconds * mdl.s_movement_vel, 0 ) );\r\n\t}\r\n\tif ( mdl.m_commands.TestMask( mSTRAFE_DOWN ))\r\n\t{\r\n\t\ts_translate_local( p_obj, Mth::Vector( 0, -elapsed_seconds * mdl.s_movement_vel, 0 ) );\r\n\t}\r\n\r\n\tif ( !Script::GetInt( CRCD(0xd8c91578,\"DisableViewerRoll\"), false ) )\r\n\t{\r\n\t\tif ( mdl.m_commands.TestMask( mROLL_LEFT ))\r\n\t\t{\r\n\t\t\tp_obj->GetMatrix().RotateLocal( Mth::Vector( 0, 0, 1 ),\r\n\t\t\t\t\t\t\t\t\t  -0.5f * elapsed_seconds * mdl.s_rotate_vel * Mth::PI / 180.0f );\r\n\t\t}\r\n\t\tif ( mdl.m_commands.TestMask( mROLL_RIGHT ))\r\n\t\t{\r\n\t\t\tp_obj->GetMatrix().RotateLocal( Mth::Vector( 0, 0, 1 ),\r\n\t\t\t\t\t\t\t\t\t  0.5f * elapsed_seconds * mdl.s_rotate_vel * Mth::PI / 180.0f );\r\n\t\t}\r\n\t}\r\n\t\r\n\tp_obj->Pause(false);\t\t// dang, it's suspended due to game being paused, so need to update manually...\r\n\t\t\t\t\t\t\t// THIS IS A PATCH - needs to be more explicity handled.....\r\n\t\r\n\t\r\n\tif ( mdl.m_commands.TestMask( mCHANGE_SCREEN_MODE ))\r\n\t{\r\n\t\tNx::CViewportManager::sSetScreenMode ( (Nx::ScreenMode) (( (int) Nx::CViewportManager::sGetScreenMode() + 1 ) % Nx::vNUM_SCREEN_MODES) );\r\n\t}\r\n\r\n\t// GJ:  clear the frame's data, now that we're done with it\r\n\t// (this used to be done at the beginning of the loop)\r\n\tmdl.m_commands.ClearAll();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tCViewer::s_translate_local( Obj::CCompositeObject* p_obj, const Mth::Vector& vec )\r\n{\r\n\t// need to build a temporary matrix,\r\n\t// because the rotation and translation\r\n\t// are stored separately in the camera\r\n\tMth::Matrix mat = p_obj->GetMatrix();\r\n\tmat[Mth::POS] = p_obj->GetPos();\r\n\t\r\n\tmat.TranslateLocal( vec );\r\n\t\r\n\tp_obj->SetPos(mat[Mth::POS]);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CScript *spawn_if_exists(uint32 script)\r\n{\r\n\tif (Script::ScriptExists(script))\r\n\t{\r\n\t\treturn  Script::SpawnScript(script);\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\nvoid        CViewer::s_shift_logic_code ( const Tsk::Task< CViewer >& task )\r\n{\r\n\tDbg_AssertType ( &task, Tsk::Task< CViewer > );\r\n\r\n\tCViewer&   mdl = task.GetData();\r\n\r\n\tif (!Script::GetInt(CRCD(0xf3e055e1,\"select_shift\")))\r\n\t{\r\n//\t\tif ( mdl.m_shift_commands.TestMask( Inp::Data::mD_SELECT ))\r\n//\t\t{\r\n//\t\t\tScript::RunScript(CRCD(0x60871393,\"UserSelectSelect\"));\r\n//\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tScript::CScript *p_script=NULL;\r\n\t\tif ( mdl.m_shift_commands.TestMask( Inp::Data::mD_TRIANGLE ))\r\n\t\t{\r\n\t\t\tp_script=spawn_if_exists(CRCD(0xcbb91022,\"UserSelectTriangle\"));\r\n\t\t}\r\n\t\telse if ( mdl.m_shift_commands.TestMask( Inp::Data::mD_SQUARE ))\r\n\t\t{\r\n\t\t\tp_script=spawn_if_exists(CRCD(0xe69691fa,\"UserSelectSquare\"));\r\n\t\t}\r\n\t\telse if ( mdl.m_shift_commands.TestMask( Inp::Data::mD_CIRCLE ))\r\n\t\t{\r\n\t\t\t// (launches the game)\r\n\t\t\tp_script=spawn_if_exists(CRCD(0xffc29c2a,\"UserSelectCircle\"));\r\n\t\t}\r\n\t\telse if ( mdl.m_shift_commands.TestMask( Inp::Data::mD_START ))\r\n\t\t{\r\n\t\t\tp_script=spawn_if_exists(CRCD(0x51b0e413,\"UserSelectStart\"));\r\n\t\t}\r\n\t\telse if ( mdl.m_shift_commands.TestMask( Inp::Data::mD_X ))\r\n\t\t{\r\n\t\t\tp_script=spawn_if_exists(CRCD(0x746d2598,\"UserSelectX\"));\r\n\t\t}\r\n\t\telse if ( mdl.m_shift_commands.TestMask( Inp::Data::mD_L1 ))\r\n\t\t{\r\n\t\t\tp_script=spawn_if_exists(CRCD(0x81d0a13c,\"UserSelectL1\"));\r\n\t\t}\r\n\t\telse if ( mdl.m_shift_commands.TestMask( Inp::Data::mD_L2 ))\r\n\t\t{\r\n\t\t\tp_script=spawn_if_exists(CRCD(0x18d9f086,\"UserSelectL2\"));\r\n\t\t}\r\n\t\telse if ( mdl.m_shift_commands.TestMask( Inp::Data::mD_R1 ))\r\n\t\t{\r\n\t\t\tp_script=spawn_if_exists(CRCD(0x55919ee3,\"UserSelectR1\"));\r\n\t\t}\r\n\t\telse if ( mdl.m_shift_commands.TestMask( Inp::Data::mD_R2 ))\r\n\t\t{\r\n\t\t\tp_script=spawn_if_exists(CRCD(0xcc98cf59,\"UserSelectR2\"));\r\n\t\t}\r\n\t\telse if ( mdl.m_shift_commands.TestMask( Inp::Data::mD_UP ))\r\n\t\t{\r\n\t\t\tp_script=spawn_if_exists(CRCD(0x1b0b7922,\"UserSelectUp\"));\r\n\t\t}\r\n\t\telse if ( mdl.m_shift_commands.TestMask( Inp::Data::mD_DOWN ))\r\n\t\t{\r\n\t\t\tp_script=spawn_if_exists(CRCD(0xbbc0e36a,\"UserSelectDown\"));\r\n\t\t}\r\n\t\telse if ( mdl.m_shift_commands.TestMask( Inp::Data::mD_LEFT ))\r\n\t\t{\r\n\t\t\tp_script=spawn_if_exists(CRCD(0xdd589439,\"UserSelectLeft\"));\r\n\t\t}\r\n\t\telse if ( mdl.m_shift_commands.TestMask( Inp::Data::mD_RIGHT ))\r\n\t\t{\r\n\t\t\tp_script=spawn_if_exists(CRCD(0x7a03c488,\"UserSelectRight\"));\r\n\t\t}\r\n\t\t   \r\n\t\tif (p_script)\r\n\t\t{\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tp_script->SetCommentString(\"Spawned from CViewer::s_shift_logic_code()\");\r\n\t\t\t#endif\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CViewer::s_handle_quickview( Net::MsgHandlerContext* context )\r\n{\r\n\tNet::MsgQuickview* p_msg;\r\n\tScript::CStruct* pStructure;\r\n\r\n\tp_msg = (Net::MsgQuickview*) context->m_Msg;\r\n\r\n\tDbg_Printf( \"Got quickview request to load file %s....\\n\", p_msg->m_Filename );\r\n\r\n    pStructure = new Script::CStruct;\r\n\r\n\tpStructure->AddComponent( Script::GenerateCRC( \"scene\" ), ESYMBOLTYPE_STRING, p_msg->m_Filename );\r\n\r\n\tScript::RunScript( \"ReloadScene\", pStructure );\r\n\r\n\tdelete pStructure;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CViewer::s_handle_incremental_update( Net::MsgHandlerContext* context )\r\n{\r\n\tNet::MsgQuickview* p_msg;\r\n\tScript::CStruct* pStructure;\r\n\r\n\tp_msg = (Net::MsgQuickview*) context->m_Msg;\r\n\r\n\tDbg_Printf( \"Got quickview request to load file %s....\\n\", p_msg->m_Filename );\r\n\r\n    pStructure = new Script::CStruct;\r\n\r\n\tpStructure->AddComponent( Script::GenerateCRC( \"scene\" ), ESYMBOLTYPE_STRING, p_msg->m_Filename );\r\n\r\n\tpStructure->AddComponent( Script::GenerateCRC( \"add\" ), ESYMBOLTYPE_STRING, p_msg->m_UpdateFilename );\r\n\tScript::RunScript( \"AddToScene\", pStructure );\r\n\r\n\tdelete pStructure;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CViewer::s_handle_update_material( Net::MsgHandlerContext* context )\r\n{\r\n\tDbg_Printf( \"Got material update request....\\n\" );\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CViewer::s_handle_rq( Net::MsgHandlerContext* context )\r\n{\r\n\tchar* path = context->m_Msg;\r\n\r\n\tif ((strcmp(\"..\\\\runnow.qb\",path) == 0) || (strcmp(\"runnow.qb\",path) == 0))\r\n\t{\r\n\t\trun_runmenow = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Printf( \"******* GOT PATH %s ********\\n\", path );\r\n\t}\r\n\tSkateScript::LoadQB( path );\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CViewer::s_handle_load_model( Net::MsgHandlerContext* context )\r\n{        \r\n\tDbg_Message( \"Got request to load model/anim...\\n\" );\r\n\t\r\n\tMdl::CViewer* pViewer = (Mdl::CViewer*) context->m_Msg;\r\n\tDbg_Assert( pViewer );\r\n\t\r\n\tScript::CStruct* pStruct = new Script::CStruct;\r\n\r\n\tNet::MsgViewObjLoadModel* p_msg;\r\n\tp_msg = (Net::MsgViewObjLoadModel*) context->m_Msg;\r\n\tpStruct->AddString( CRCD(0xb974f2fc,\"modelName\"), p_msg->m_ModelName );\r\n\tpStruct->AddChecksum( CRCD(0x6c2bfb7f,\"animName\"), p_msg->m_AnimScriptName );\r\n\tpStruct->AddChecksum( CRCD(0x09794932,\"skeletonName\"), p_msg->m_SkeletonName );\r\n\tpViewer->AddViewerObject( pStruct );\r\n\t\r\n\tdelete pStruct;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t \r\nint CViewer::s_handle_unload_model( Net::MsgHandlerContext* context )\r\n{\r\n\tDbg_Message( \"Got request to unload model/anim...\\n\" );\r\n\r\n\tMdl::CViewer* pViewer = (Mdl::CViewer*) context->m_Msg;\r\n\tDbg_Assert( pViewer );\r\n\tpViewer->RemoveViewerObject();\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CViewer::s_handle_run_script_command( Net::MsgHandlerContext* context )\r\n{\r\n\tuint32 *p_data=(uint32*)context->m_Msg;\r\n\t\r\n\tuint32 command_name=*p_data++;\r\n\t\r\n\tScript::CStruct *p_params=new Script::CStruct;\r\n\tScript::ReadFromBuffer(p_params,(uint8*)p_data);\r\n//\tDbg_Printf( \"Running script command %p\\n\", command_name );\r\n\tScript::RunScript(command_name,p_params);\r\n\tdelete p_params;\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CViewer::AddViewerObject( Script::CStruct* pParams )\r\n{\r\n\tif (Config::GotExtraMemory())\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t}\r\n\t\t\r\n\t// if the viewer object exists already,\r\n\t// clear it out\r\n\tif ( mp_viewerObject )\r\n\t{\r\n\t\tRemoveViewerObject();\r\n\t}\r\n\r\n\tDbg_Assert( !mp_viewerObject );\r\n\tmp_viewerObject = new Obj::CViewerObject( mp_server );\r\n\tmp_viewerObject->LoadModel( pParams );\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CViewer::RemoveViewerObject()\r\n{\r\n\tif ( mp_viewerObject )\r\n\t{\r\n\t\tmp_viewerObject->UnloadModel();\r\n\t\tdelete mp_viewerObject;\r\n\t\tmp_viewerObject = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCViewer::v_start_cb ( void )\r\n{\r\n\tInp::Manager* inp_manager = Inp::Manager::Instance();\r\n\tMlp::Manager* mlp_manager = Mlp::Manager::Instance();\r\n\r\n\t#ifdef\t\t__USE_PROFILER__\t\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ProfilerHeap());\r\n\t#else\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t#endif\r\n\r\n\t// Sorry Steve, but we need the shift input handler on the CD, so I'm going\r\n\t// to have to start this module all the time.\r\n\t// but on the CD, we don't initialize any of the actual view stuff\r\n\tif (!Config::CD())\r\n\t{\r\n\t\t\r\n\t\t\r\n\t\r\n\t\tmp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_QUICKVIEW, \r\n\t\t\t\t\t\t\t\t\t\t\ts_handle_quickview, \r\n\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE | Net::mHANDLE_FOREIGN );\r\n\t\tmp_server->m_Dispatcher.AddHandler(\tNet::vMSG_ID_UPDATE_MATERIAL, \r\n\t\t\t\t\t\t\t\t\t\t\ts_handle_update_material, \r\n\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE | Net::mHANDLE_FOREIGN );\r\n\t\tmp_server->m_Dispatcher.AddHandler(\tNet::vMSG_ID_REMOTE_Q, \r\n\t\t\t\t\t\t\t\t\t\t\ts_handle_rq, \r\n\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE | Net::mHANDLE_FOREIGN );\r\n\t\tmp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_INCREMENTAL_UPDATE,\r\n\t\t\t\t\t\t\t\t\t\t\ts_handle_incremental_update,\r\n\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE | Net::mHANDLE_FOREIGN );\r\n\t\tmp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_LOAD_MODEL, \r\n\t\t\t\t\t\t\t\t\t\t\ts_handle_load_model,\r\n\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );\r\n\t\tmp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_UNLOAD_MODEL, \r\n\t\t\t\t\t\t\t\t\t\t\ts_handle_unload_model,\r\n\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );\r\n\t\tmp_server->m_Dispatcher.AddHandler(\tNet::vMSG_ID_RUN_SCRIPT_COMMAND, \r\n\t\t\t\t\t\t\t\t\t\t\ts_handle_run_script_command, \r\n\t\t\t\t\t\t\t\t\t\t\tNet::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );\r\n\t\r\n\t\r\n\t\r\n\t\tDbg_Printf( \"Starting Viewer Module....\\n\" );\r\n\t}\t\r\n\r\n\t// We also add the regular input handler and logic handler on CD\r\n\tmlp_manager->AddLogicTask( *mp_logic_task );\r\n\tinp_manager->AddHandler( *mp_input_handler );\r\n\t\r\n\t// The \"shift_input\" handler and logic are just for the user-select buttons\r\n\t// specifically the screenshot (Select+Square)\r\n\t// generally they are disabled. \r\n\t// see buttonscripts.q for the scripts that get run\r\n\r\n\tprintf(\"Adding shift input handlers\\n)\");\t\r\n\tinp_manager->AddHandler( *mp_shift_input_handler );\r\n\tmlp_manager->AddLogicTask( *mp_shift_logic_task );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCViewer::v_stop_cb ( void )\r\n{   \r\n\tif ( mp_viewerObject )\r\n\t{\r\n    \tdelete mp_viewerObject;\r\n\t\tmp_viewerObject = NULL;\r\n\t}\r\n    \r\n\tmp_input_handler->Remove();\r\n\tmp_logic_task->Remove();\r\n\tmp_shift_logic_task->Remove();\r\n\tmp_shift_input_handler->Remove();\r\n\r\n\tmp_server->m_Dispatcher.Deinit();\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCViewer::CViewer( void )\r\n{\r\n\tif (!Config::CD())\r\n\t{\r\n\t\tuint32 local_ip;\r\n\r\n\t\tNet::Manager * net_man = Net::Manager::Instance();\r\n\t\t\t\r\n#ifdef __PLAT_NGC__\r\n\t\tSOInAddr local_addr;\r\n\t\tSOInetAtoN( net_man->GetLocalIP(), &local_addr );\r\n\t\tlocal_ip = local_addr.addr;\r\n#else\r\n\t\tlocal_ip = inet_addr( net_man->GetLocalIP());\r\n#endif\r\n\t\tnet_man->NetworkEnvironmentSetup();\r\n\t\tmp_server = net_man->CreateNewAppServer( 0, \"Skate4 Viewer\", 4, Net::vEXPORT_COMM_PORT,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tinet_addr( net_man->GetLocalIP()), Net::App::mACCEPT_FOREIGN_CONN );\r\n\t\r\n\t\tDbg_Assert( mp_server );\r\n\t}\t\r\n\r\n\r\n\tint viewer_controller = Script::GetInt(CRCD(0x702247a5,\"Viewer_controller\"), false);\r\n\r\n\tmp_logic_task = new Tsk::Task< CViewer > ( CViewer::s_logic_code, *this );\r\n\tmp_input_handler = new Inp::Handler< CViewer > ( viewer_controller,  s_input_logic_code, *this, Tsk::BaseTask::Node::vNORMAL_PRIORITY );\r\n\t\r\n\ts_movement_vel = 400.0f;\t// default movement velocity in inches per second\r\n\ts_rotate_vel = 120.0f;\t\t// 120 degrees per second. In 3 seconds you should complete 1 revolution\r\n\r\n\tprintf(\"Creating shift input handlers\\n)\");\t\r\n\tmp_shift_logic_task = new Tsk::Task< CViewer > ( CViewer::s_shift_logic_code, *this );\r\n\tmp_shift_input_handler = new Inp::Handler< CViewer > ( viewer_controller,  CViewer::s_shift_input_logic_code, *this, Tsk::BaseTask::Node::vHANDLER_PRIORITY_VIEWER_SHIFT_INPUT_LOGIC );\r\n\r\n\tDbg_Assert( !sp_viewer );\r\n\tsp_viewer = this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCViewer::~CViewer( void )\r\n{\r\n\tDbg_Assert( mp_server );\r\n\r\n\tdelete mp_server;\r\n\tdelete mp_input_handler;\r\n\tdelete mp_logic_task;\r\n\tdelete mp_shift_logic_task;\r\n\tdelete mp_shift_input_handler;\r\n\r\n\tDbg_Assert( sp_viewer );\r\n\tsp_viewer = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CViewerObject* CViewer::GetViewerObject()\r\n{\r\n\treturn mp_viewerObject;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCViewer::sSetViewMode(int viewMode)\r\n{\r\n\ts_view_mode = viewMode;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid    CViewer::sSetMovementVelocity( float in_per_sec )\r\n{\r\n\ts_movement_vel = in_per_sec;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t \r\nvoid    CViewer::sSetRotateVelocity( float deg_per_sec )\r\n{\r\n\ts_rotate_vel = deg_per_sec;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t \r\nbool\tCViewer::ResetCameraToViewerObject()\r\n{\r\n\tif ( !Script::GetInteger( CRCD(0xc965e06f,\"ResetCameraToViewerObject\"), Script::NO_ASSERT ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n//\tGfx::Camera* pCamera = Nx::CViewportManager::sGetCamera(0);\r\n\tObj::CCompositeObject * p_obj = (Obj::CCompositeObject *) Obj::CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0xeb17151b,\"viewer_cam\"));\r\n\r\n\tif ( p_obj )\r\n\t{\r\n\t\t// ideally we would want to hide the level/sky when\r\n\t\t// switching to the object viewer, but for now,\r\n\t\t// just put the viewer object in the sky...\r\n\r\n\t\t// set the camera\r\n\t\tMth::Matrix ident;\r\n\t\tident.Ident();\r\n\t\tp_obj->SetMatrix( ident );\r\n\r\n\t\t// the viewer object gets placed at (0, 1000, 0),\r\n\t\t// so put the camera slightly offset from here\r\n\t\tp_obj->SetPos( Mth::Vector(0.0f, 35.0f, 100.0f) );\r\n\t}\r\n\r\n\treturn true;\r\n}\t\t\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t \r\nCViewer* CViewer::sGetViewer()\r\n{\r\n\treturn sp_viewer;\r\n}\r\n\t\t\t\t\t\t\t  \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t \r\nvoid CViewer::SetCommand( const uint32 command )\r\n{\r\n\tm_commands.SetMask( command );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t \r\n} // namespace Mdl\r\n\r\n"
  },
  {
    "path": "Code/Sk/Modules/Viewer/Viewer.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2001 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tViewer\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tViewer.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t11/28/01\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tViewer module\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __SK_MODULES_VIEWER_H__\r\n#define __SK_MODULES_VIEWER_H__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/math.h>\r\n\r\n#include <gel/module.h>\r\n#include <gel/inpman.h>\r\n#include <gel/net/net.h>\r\n#include <gel/net/server/netserv.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n    class CViewerObject;\r\n    class CCompositeObject;\r\n};\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n};\r\n\t\t\t  \r\nnamespace Mdl\r\n{\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CViewer : public Module\r\n{\r\npublic:\r\n\tCViewer( void );\r\n\t~CViewer( void );\r\n\r\n\tstatic int\tsGetViewMode() {return s_view_mode; }\r\n\tstatic void\tsSetViewMode(int viewMode);\r\n\tstatic void\tsSetMovementVelocity( float in_per_sec );\r\n\tstatic void\tsSetRotateVelocity( float deg_per_sec );\r\n\t\r\n\t// GJ:  viewer mode stuff...\r\n\t// there's probably a better way to do this...\r\n\tstatic CViewer*\t\tsGetViewer();\r\n\tbool\t\t\t\tResetCameraToViewerObject();\r\n\tvoid\t\t\t\tAddViewerObject( Script::CStruct* pParams );\r\n\tvoid\t\t\t\tRemoveViewerObject();\r\n\tObj::CViewerObject*\tGetViewerObject();\r\n\tstatic CViewer*\t\tsp_viewer;\r\n\tvoid\t\t\t\tSetCommand( const uint32 command );\r\n\r\n\tenum ECommands\r\n\t{\r\n\t\tmSTRAFE_UP          = nBit( 1 ),\r\n\t\tmSTRAFE_DOWN        = nBit( 2 ),\r\n\t\tmLIGHT_BK\t\t\t= nBit( 3 ),\r\n\t\tmLIGHT_FW\t\t\t= nBit( 4 ),\r\n\t\tmLIGHT_LT\t\t\t= nBit( 5 ),\r\n\t\tmLIGHT_RT\t\t\t= nBit( 6 ),\r\n\t\tmVIEW_FRONT         = nBit( 7 ),\r\n\t\tmVIEW_LEFT          = nBit( 8 ),\r\n\t\tmVIEW_RIGHT         = nBit( 9 ),\r\n\t\tmVIEW_TOP           = nBit( 10 ),\r\n\t\tmRESET              = nBit( 11 ),\r\n\t\tmCHANGE_SCREEN_MODE = nBit( 12 ),\r\n\t\tmTOGGLE_RENDER_MODE = nBit( 13 ),\r\n\t\tmTOGGLE_ROTATE_MODE\t= nBit( 14 ),\r\n\t\tmRESET_ROTATIONS\t= nBit( 15 ),\r\n\t\tmROLL_LEFT          = nBit( 16 ),\r\n\t\tmROLL_RIGHT         = nBit( 17 ),\r\n\t};\r\n\r\n\tenum ERotationMode\r\n\t{\r\n\t\tvROTATE_CAMERA,\r\n\t\tvROTATE_OBJECTS\r\n\t};\r\n\r\nprivate:\r\n\tvoid\t\t\tv_start_cb ( void );\r\n\tvoid\t\t\tv_stop_cb ( void );\r\n\t\r\n\tstatic \t\t\tNet::MsgHandlerCode\t\t\t\ts_handle_quickview;\r\n\tstatic \t\t\tNet::MsgHandlerCode\t\t\t\ts_handle_incremental_update;\r\n\tstatic \t\t\tNet::MsgHandlerCode\t\t\t\ts_handle_update_material;\r\n\tstatic \t\t\tNet::MsgHandlerCode\t\t\t\ts_handle_rq;\r\n\tstatic \t\t\tNet::MsgHandlerCode\t\t\t\ts_handle_load_model;\r\n\tstatic \t\t\tNet::MsgHandlerCode\t\t\t\ts_handle_unload_model;\r\n\tstatic \t\t\tNet::MsgHandlerCode\t\t\t\ts_handle_run_script_command;\r\n\t\r\n\tstatic\t\t\tTsk::Task< CViewer >::Code\t\ts_logic_code;       \r\n\tstatic\t\t\tTsk::Task< CViewer >::Code\t\ts_shift_logic_code;       \r\n\t\r\n\tstatic\t\t\tInp::Handler< CViewer >::Code\ts_input_logic_code;\r\n\tstatic\t\t\tInp::Handler< CViewer >::Code\ts_shift_input_logic_code;\r\n\tstatic\t\t\tInp::Handler< CViewer >::Code\ts_shift_input_logic_code2;\r\n\t\r\n\tstatic \t\t\tvoid\t\t\t\t\t\t\ts_translate_local( Obj::CCompositeObject* p_obj, const Mth::Vector& vec );\r\n\t\r\n\r\n\tInp::Handler< CViewer >*\tmp_input_handler;\r\n\tInp::Handler< CViewer >*\tmp_shift_input_handler;      \r\n\tTsk::Task< CViewer >*\t\tmp_logic_task;\r\n\tTsk::Task< CViewer >*\t\tmp_shift_logic_task;\t\r\n\r\n\t// Input\r\n    Mth::Vector\t\tm_right;\r\n    Mth::Vector\t\tm_left;\r\n    Flags<ECommands>m_commands;\r\n\tFlags<uint>     m_shift_commands;\r\n\tERotationMode\tm_rotation_mode;\r\n\tstatic float\ts_movement_vel;\t// in inches per sec\r\n\tstatic float\ts_rotate_vel;\t// in degrees per sec\r\n\tstatic int\t\ts_view_mode;\t// 0 if inactive\r\n\t\r\n\tNet::Server*\tmp_server;\r\n\r\n    Obj::CViewerObject*    mp_viewerObject;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCViewer* GetViewer();\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mdl\r\n\r\n#endif\t// __SK_MODULES_VIEWER_H__\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Ngps/crt0.s",
    "content": "\r\n/* SCEI CONFIDENTIAL\r\n \"PlayStation 2\" Programmer Tool Runtime Library Release 2.4\r\n */\r\n/*\r\n *                      Emotion Engine Library\r\n *                          Version 1.10\r\n *                           Shift-JIS\r\n *\r\n *      Copyright (C) 1998-1999 Sony Computer Entertainment Inc.\r\n *                        All Rights Reserved.\r\n *\r\n *                       libkernel - crt0.s\r\n *                        kernel libraly\r\n *\r\n *       Version        Date            Design      Log\r\n *  --------------------------------------------------------------------\r\n *       1.10           Oct.12.1999     horikawa    renewal\r\n *       1.50           May.16.2000     horikawa\r\n */\r\n\r\n/* Ken: Added so that I can use register names like a0 rather than $4\t*/\r\n#include \"C:\\usr\\local\\sce\\iop\\gcc\\mipsel-scei-elfl\\include\\cpureg.h\"\r\n\r\n#define DS_SOUND\r\n\r\n#ifdef __mips16\r\n\t.set nomips16\t/* This file contains 32 bit assembly code. */\r\n#endif\r\n\r\n#define\tARG_SIZ     256 + 16*4 + 1*4\r\n\r\n         _stack\t=\t\t_std_stack\r\n         \r\n\t.set noat\r\n    \t.set noreorder\r\n\t.global ENTRYPOINT\r\n\t.global _start\r\n\t.ent\t_start\r\n\t.text\t\t\t\t# 0x00200000\r\n\tnop\r\n\tnop\r\nENTRYPOINT:\r\n_start:\r\n#if defined(DS_SOUND)\r\n\t/* $4 =  1 ʥ쥸Ϥ*/\r\n   \tlui\t$2, %hi(_args_ptr)\r\n   \taddiu\t$2, $2, %lo(_args_ptr)\r\n    \tsw\t$4, ($2)\r\n#endif\r\n/*\r\n * clear .bss\r\n */\r\nzerobss:\r\n\tlui\t$2, %hi(_fbss)\r\n\tlui\t$3, %hi(_end)\r\n\taddiu\t$2, $2, %lo(_fbss)\r\n\taddiu\t$3, $3, %lo(_end)\r\n1:\r\n\tsq\t$0, ($2)\r\n\tnop\r\n\tsltu\t$1, $2, $3\r\n\tnop\r\n\tnop\r\n\tbne\t$1, $0, 1b\r\n\taddiu\t$2, $2, 16\r\n\r\n/*\r\n * initialize main thread\r\n */\r\n\tlui\t$4, %hi(_gp)\r\n\tlui\t$5, %hi(_stack)\r\n\tlui\t$6, %hi(_stack_size)\r\n\tlui\t$7, %hi(_args)\r\n\tlui\t$8, %hi(_root)\r\n\taddiu\t$4, $4, %lo(_gp)\r\n\taddiu\t$5, $5, %lo(_stack)\r\n\taddiu\t$6, $6, %lo(_stack_size)\r\n\taddiu\t$7, $7, %lo(_args)\r\n\taddiu\t$8, $8, %lo(_root)\r\n\tmove\t$28, $4\r\n\taddiu\t$3, $0, 60\r\n\tsyscall\r\n\tmove\t$29, $2\r\n\r\n/*\r\n * initialize heap area\r\n */\r\n\tlui\t$4, %hi(_end)\r\n\tlui\t$5, %hi(_heap_size)\r\n\taddiu\t$4, $4, %lo(_end)\r\n\taddiu\t$5, $5, %lo(_heap_size)\r\n\taddiu\t$3, $0, 61\r\n\tsyscall\r\n\r\n/*\r\n *\tKen addition.\r\n *\tDetect whether we are running on a ProView system by seeing whether \r\n *\tsnputs works.\r\n */\r\n\r\n\tjal sceScfGetLanguage\t\t# snputs will always fail until this is called, for some reason.\r\n\tnop\r\n\t\r\n\tla a0,TestStringForSnputs\r\n\tjal snputs\r\n\tnop\r\n\r\n\tbltz v0,notproview\t\t\t# If the return value is -1, it is not a proview.\r\n\tnop\r\n\r\n/*\r\n *\tNow we know we're running on a ProView, so run the startup code copied from\r\n *\tthe ProView crt0.s\r\n */\r\n\r\n\t\r\n/*\r\n * flush data cache\r\n */\r\n\tjal\tFlushCache\r\n\tmove\t$4, $0\r\n\r\n/*\r\n * call main program\r\n */\r\n\tei\r\n\r\n/*\r\n * This is a Neversoft addition, we need to call pre_main to set up the mem manager & debug stuff\r\n */ \r\n    jal pre_main\r\n\tnop\r\n\t\r\n#if defined(DS_SOUND)\t\r\n \tlui\t$2, %hi(_args_ptr)\r\n \taddiu\t$2, $2, %lo(_args_ptr)\r\n\r\n \tlw\t$3, ($2)\r\n\t\r\n \tbeq\t$3, $0, _skipArgV\r\n \tnop\r\n\r\n \taddiu\t$2, $3, 4\r\n\tb\t_run\t\r\n\tnop\r\n\r\n_skipArgV:\r\n\tlui\t$2, %hi(_args)\r\n\taddiu\t$2, $2, %lo(_args)\r\n\r\n#else\r\n\tlui\t$2, %hi(_args)\r\n\taddiu\t$2, $2, %lo(_args)\r\n#endif\r\n\r\n_run:\r\n\r\n\tlw\t$4, ($2)\r\n\tjal\tmain\r\n\taddiu\t$5, $2, 4\r\n\r\n/*\r\n * This is a Neversoft addition, we call post_main at the end\r\n */ \r\n    jal post_main\r\n\tnop\r\n\r\n#if defined(DS_SOUND)\r\n\tj\t_root\r\n\tnop\r\n#else\r\n\tj\tExit\r\n\tmove\t$4, $2\r\n#endif\r\n\r\n\t\t\r\nnotproview:\r\n\r\n/*\r\n * initialize System\r\n */\r\n\tjal\t_InitSys\r\n\tnop\r\n\r\n/*\r\n * flush data cache\r\n */\r\n\tjal\tFlushCache\r\n\tmove\t$4, $0\r\n\r\n/*\r\n * call main program\r\n */\r\n\tei\r\n\t\t\t\r\n/*\r\n * This is a Neversoft addition, we need to call pre_main to set up the mem manager & debug stuff\r\n */ \r\n    jal pre_main\r\n\tnop\r\n        \r\n\tlui\t$2, %hi(_args)\r\n\taddiu\t$2, $2, %lo(_args)\r\n\tlw\t$4, ($2)\r\n\tjal\tmain\r\n\taddiu\t$5, $2, 4\r\n\r\n/*\r\n * This is a Neversoft addition, we call post_main at the end\r\n */ \r\n    jal post_main\r\n\tnop\r\n        \r\n\tj\tExit\r\n\tmove\t$4, $2\r\n\t.end\t_start\r\n\r\n/**************************************/\r\n\t.align\t3\r\n\t.global\t_exit\r\n\t.ent\t_exit\r\n_exit:\r\n#if defined(DS_SOUND)\r\n\tj\t_root\r\n\tnop\r\n#else\r\n\tj\tExit\t\t\t# Exit(0);\r\n\tmove\t$4, $0\r\n#endif\r\n\t.end\t_exit\r\n    \r\n\t.align\t3\r\n\t.ent\t_root\r\n_root:\r\n#if defined(DS_SOUND)\r\n/*\r\n *\tK: If not ProView, don't do the next bit, or it will crash.\r\n */\r\n\tla a0,TestStringForSnputs\r\n\tjal snputs\r\n\tnop\r\n\tbltz v0,notproviewsogotoexitthread\t# If the return value is -1, it is not a proview.\r\n\tnop\r\n\r\n\tlui\t$2, %hi(_args_ptr)\r\n\taddiu\t$2, $2, %lo(_args_ptr)\r\n\tlw\t$3, ($2)\r\n\tjal\tSignalSema\r\n\tlw\t$4, ($3)\r\n\t\r\nnotproviewsogotoexitthread:\t\r\n#endif\r\n\taddiu\t$3, $0, 35\t\t# ExitThread();\r\n\tsyscall\r\n\t.end\t_root\r\n\r\n\t.bss\r\n\t.align\t6\r\n_args: .space\tARG_SIZ\r\n\r\n#if defined(DS_SOUND)\r\n\t.data\r\n_args_ptr:\r\n\t.space 4\r\n#endif\r\n\r\n\r\n\r\n/*\r\n * Ken: This is used by ProView detection code\r\n */\r\n\t.section\t.rodata\r\nTestStringForSnputs:   .string \"crt0.s detected ProView ...\\n\"\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/FollowOb.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObject (OBJ)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobjects/followob.h    \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t05/02/02\t-\tksh\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __OBJECTS_FOLLOWOB_H\r\n#define __OBJECTS_FOLLOWOB_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __CORE_MATH_VECTOR_H\r\n#include <core/math/vector.h>\r\n#endif\r\n\r\n//#include <sys/timer.h>\r\n\r\n//#include <gfx/gfxman.h>\r\n\r\n//#include <gfx/skin.h>\r\n\r\n//#include <gel/inpman.h>\r\n//#include <gel/object.h>\r\n\r\n//#include <servers/os_coll.h>\r\n\r\n//#include <core/math/matrix.h>\r\n//#include <core/math/vector.h>\r\n\r\n//#include <sk/objects/movingobject.h>\r\n\r\n//#include <gel/scripting/script.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define MAX_FOLLOWOB_PATH_POINTS 64\r\nclass  CFollowOb  : public Spt::Class\r\n{\r\n\tMth::Vector mp_path_points[MAX_FOLLOWOB_PATH_POINTS];\r\n\tint m_num_path_points;\r\n\tint m_most_recent_path_point;\r\n\t\r\n\tuint32 m_leader_name;\r\n\tMth::Vector m_leader_pos;\r\n\tfloat m_distance;\r\n\tbool m_orient_y;\r\n\t\r\npublic:\r\n\tCFollowOb();\r\n\t~CFollowOb();\r\n\t\r\n\tvoid\tReset();\r\n\tvoid\tSetLeaderName(uint32 name) {m_leader_name=name;}\r\n\tvoid\tSetDistance(float distance) {m_distance=distance;}\r\n\t\r\n\tvoid\tGetNewPathPointFromObjectBeingFollowed();\r\n\tvoid\tCalculatePositionAndOrientation(Mth::Vector *p_pos, Mth::Matrix *p_orientation);\r\n\tvoid\tOrientY() {m_orient_y=true;}\r\n\tvoid\tDoNotOrientY() {m_orient_y=false;}\r\n};\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_FOLLOWOB_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/GameObj.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       gameobj.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  11/02/2000\r\n//****************************************************************************\r\n\r\n#include <sk/objects/gameobj.h>\r\n\r\n#include <core/math.h>\r\n\r\n#include <gel/objman.h>\r\n#include <gel/components/modelcomponent.h>\r\n\r\n#include <gel/components/lockobjcomponent.h>  // needs some stupid special setup\r\n\r\n\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/nxparticle.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\t\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define\t\tOLD_GO_SYSTEM  0\r\n\r\nObj::CCompositeObject* create_game_obj( CGeneralManager* p_obj_man, Script::CStruct* pNodeData, bool is_level_obj )\r\n{\r\n\r\n\r\n\t#if OLD_GO_SYSTEM\t\r\n\tCMovingObject* pGameObj = new CMovingObject;\r\n\tpGameObj->MovingObjectCreateComponents();\r\n\t#else\r\n\r\n// Create a composite object from this node, but don't finalize it\r\n\t\tObj::CCompositeObject* pGameObj = Obj::CCompositeObjectManager::Instance()->CreateCompositeObjectFromNode(\r\n\t\t\tScript::GetArray(\"gameobj_composite_structure\"), pNodeData, false);\r\n\r\n//\r\n    CLockObjComponent* p_lockObjComponent = new CLockObjComponent;\r\n\tpGameObj->AddComponent(p_lockObjComponent);\r\n\r\n\t\r\n\t#endif\r\n\t\r\n\t#if OLD_GO_SYSTEM\t\t\r\n\tpGameObj->SetType( SKATE_TYPE_GAME_OBJ );\r\n\tDbg_MsgAssert(pGameObj, (\"Failed to create gameobj.\"));\r\n\tp_obj_man->RegisterObject(*pGameObj);\r\n\tSkateScript::GetPosition( pNodeData, &pGameObj->m_pos );\r\n\tpGameObj->MovingObjectInit( pNodeData, p_obj_man );\r\n\t#endif\r\n\r\n\tScript::RunScript( CRCD(0xf3b84da6,\"gameobj_add_components\"), pNodeData, pGameObj );\r\n\r\n\tpGameObj->Finalize();\r\n\r\n\t// need to synchronize rendered model's position to initial world position\r\n\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( pGameObj );\r\n\tif ( pModelComponent )\r\n\t{\r\n\t\tpModelComponent->FinalizeModelInitialization();\r\n\t}\r\n\r\n//\t#if !OLD_GO_SYSTEM\r\n\t// This used to be in MovingObjectInit\t\r\n\t// get any script associated with the object, and run it on the object\r\n\tuint32 AIScriptChecksum=0;\r\n\tif ( pNodeData->GetChecksum(CRCD(0x2ca8a299,\"TriggerScript\"),&AIScriptChecksum) )\r\n\t{\r\n\t\tScript::CScriptStructure *pScriptParams=NULL;\r\n\t\tpNodeData->GetStructure(CRCD(0x7031f10c,\"Params\"),&pScriptParams);\r\n\t\tpGameObj->SwitchScript( AIScriptChecksum, pScriptParams );\r\n\t}\r\n//\t#endif\r\n\r\n\treturn pGameObj;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CCompositeObject* CreateGameObj( CGeneralManager* p_obj_man, Script::CStruct* pNodeData )\r\n{   \r\n\treturn create_game_obj( p_obj_man, pNodeData, false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CreateLevelObj( CGeneralManager* p_obj_man, Script::CStruct* pNodeData )\r\n{\r\n\tif (pNodeData->ContainsFlag(\"Bouncy\"))\r\n\t{\r\n\t\tObj::CCompositeObjectManager::Instance()->CreateCompositeObjectFromNode(Script::GetArray(\"bouncy_composite_structure\"), pNodeData);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcreate_game_obj( p_obj_man, pNodeData, true );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CreateParticleObject( CGeneralManager* p_obj_man, Script::CStruct* pNodeData )\r\n{\r\n\tif( pNodeData->ContainsComponentNamed( \"HasMotion\" ))\r\n\t{\r\n\t\tObj::CCompositeObjectManager::Instance()->CreateCompositeObjectFromNode(\r\n\t\t\t\t\tScript::GetArray(\"moving_particle_composite_structure\"), pNodeData);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tObj::CCompositeObjectManager::Instance()->CreateCompositeObjectFromNode(\r\n\t\t\t\t\tScript::GetArray(\"particle_composite_structure\"), pNodeData);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CreateParticleEmitter( CGeneralManager* p_obj_man, Script::CStruct* pNodeData )\r\n{\r\n\tDbg_MsgAssert( pNodeData, ( \"Couldn't find node script.\" ) );\r\n\r\n\t// Run the trigger script, and this will create the game object\r\n\t// then need to find the game object\t\r\n\tuint32 AIScriptChecksum=0;\r\n\tpNodeData->GetChecksum( \"TriggerScript\", &AIScriptChecksum, true );\r\n\tuint32 NameChecksum=0;\r\n\tpNodeData->GetChecksum( \"Name\", &NameChecksum, true );\r\n\tif ( AIScriptChecksum )\r\n\t{\r\n\t\t// Make sure we don't have an unnamed particle system already\r\n\t\tconst uint32 PARTICLE_UNNAMED = 0x502335a1;   // Particle_UnNamed\t\t\t\r\n\t\tDbg_MsgAssert(!Nx::CEngine::sGetParticleTable()->GetItem(PARTICLE_UNNAMED),(\"Particle_UnNamed should not exist\"));\t\t\r\n\t\t\t\r\n\t\t// Get the parameters for the TriggerScript, and run it\r\n\t\t// this should create a particle system\r\n\t\tScript::CScriptStructure *pScriptParams=NULL;\r\n\t\tpNodeData->GetStructure(\"Params\",&pScriptParams);\r\n\t\tScript::RunScript(AIScriptChecksum,pScriptParams);\t\t// this will create the particle emitter\r\n\t\t\r\n\t\t// Get the newly created particle system\r\n\t\tNx::CParticle *p_system = Nx::CEngine::sGetParticleTable()->GetItem(PARTICLE_UNNAMED);\r\n\t\tDbg_MsgAssert(p_system,(\"Script did not create Particle_UnNamed!\"));\r\n\r\n\t\t// Remove the entry from the Hash table\t\t\t\r\n\t\tNx::CEngine::sGetParticleTable()->FlushItem(PARTICLE_UNNAMED);\r\n\r\n\t\t// Add it back with the name as specifed in this node\t\t\t\r\n\t\tNx::CEngine::sGetParticleTable()->PutItem(NameChecksum,p_system);\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\tp_system->set_checkum(NameChecksum);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \t\t\t\t\t   \r\n\t\tp_system->SetID(NameChecksum);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \t\t\t\t\t   \r\n\t\t   \r\n\t\tMth::Vector\tangles;\r\n\t\tMth::Vector dir (0.0f,1.0f,0.f);\r\n\t\tpNodeData->GetVector(\"Angles\",&angles);\r\n\t\tprintf(\"Angles(%f,%f,%f)\\n\",angles[X],angles[Y],angles[Z]);\r\n\t\t// 3DSMAX_ANGLES Mick: 3/19/03 - Changed all rotation orders to X,Y,Z\r\n\t\tdir.RotateX(angles[X]);\r\n\t\tdir.RotateY(angles[Y]);\r\n\t\tdir.RotateZ(angles[Z]);\r\n\t\t\r\n\t\tp_system->set_emit_target( dir[X], dir[Y], dir[Z] );\r\n\r\n\t\t// Register it with the object manager.....\r\n\t\t// This means that the system can be refered to like a regular moving object\r\n\t\tp_obj_man->RegisterObject(*p_system);\r\n\t\t\t   \r\n\t\tp_system->MovingObjectInit( pNodeData, p_obj_man ); \t// get LOD and suspend info\r\n\t\t\r\n\t\t// Bastard crap code.... Since I set them up to be objects\r\n\t\t// they now run their scripts with the new component system\r\n\t\t// meaning the scripts run twice, dammit...\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\tp_system->GetScript()->ClearScript();\r\n\t\tp_system->GetScript()->ClearEventHandlerTable();\r\n\t}\r\n}\r\n\r\n\r\n} // namespace Obj\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/GameObj.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       gameobj.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  11/02/2000\r\n//****************************************************************************\r\n\r\n#ifndef __OBJECTS_GAMEOBJ_H\r\n#define __OBJECTS_GAMEOBJ_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\tclass CCompositeObject;\r\n\tclass CGeneralManager;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid CreateParticleEmitter( CGeneralManager* p_obj_man, Script::CStruct* pNodeData );\r\nCCompositeObject* CreateGameObj( CGeneralManager* p_obj_man, Script::CStruct* pNodeData );\r\nvoid CreateLevelObj( CGeneralManager* p_obj_man, Script::CStruct* pNodeData );\r\nvoid CreateParticleObject( CGeneralManager* p_obj_man, Script::CStruct* pNodeData );\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_GAMEOBJ_H\r\n"
  },
  {
    "path": "Code/Sk/Objects/MovingObject.cpp",
    "content": "/*\r\n\tMovingObject.cpp\r\n\t\r\n\tSkaters, Peds, Cars are derived from CMovingObject.\r\n\r\n\tThese objects are controlled through scripts.  Script commands are\r\n\tsent through CallMemberFunction( ).  See all available commands by\r\n\tlooking at CMovingObject::CallMemberFunction().\r\n*/\r\n\r\n// start autoduck documentation\r\n// @DOC movingobject\r\n// @module movingobject | None\r\n// @subindex Scripting Database\r\n// @index script | movingobject\r\n\r\n#include <sk/objects/movingobject.h>\r\n\r\n#include <gel/mainloop.h>\r\n#include <gel/objman.h>\r\n#include <gel/objsearch.h>\r\n#include <gel/objtrack.h>\r\n\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/lockobjcomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/motioncomponent.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n#include <gel/components/suspendcomponent.h>\r\n#include <gel/components/soundcomponent.h>\r\n#include <gel/components/specialitemcomponent.h>\r\n#include <gel/components/streamcomponent.h>\r\n\r\n#include <sk/components/skaterproximitycomponent.h>\r\n\r\n#include <gel/object/compositeobjectmanager.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\n#include <gfx/debuggfx.h> // for AddDebugLine( )\r\n#include <gfx/bbox.h>\r\n#include <gfx/gfxutils.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/skeleton.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovingObject::DrawBoundingBox( SBBox *pBox, Mth::Vector *pOffset, int numFrames, Mth::Vector *pRot )\r\n{\r\n    Gfx::AddDebugBox( m_matrix, m_pos, pBox, pOffset, numFrames, pRot);\r\n} \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMovingObject::CMovingObject()\r\n{\r\n\t// set up default bounding box\r\n    m_bbox.m_max.Set(10.0f, 10.0f, 10.0f);\r\n    m_bbox.m_min.Set(-10.0f, -10.0f, -10.0f);    \r\n    m_bbox.centerOfGravity.Set();\t\t\t// zero center of gravity......    \r\n\r\n\t// suspend component should come first, because it\r\n\t// controls whether the rest of the components\r\n\t// should be updated\r\n\tCSuspendComponent* p_suspendComponent = new CSuspendComponent;\r\n\tAddComponent(p_suspendComponent);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMovingObject::~CMovingObject( void )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovingObject::MovingObjectCreateComponents()\r\n{\r\n\tCMotionComponent* p_motionComponent = new CMotionComponent;\r\n\tAddComponent(p_motionComponent);\r\n\r\n\tCSpecialItemComponent* p_specialItemComponent = new CSpecialItemComponent;\r\n\tAddComponent(p_specialItemComponent);\r\n\r\n\tCSkaterProximityComponent* p_skaterProximityComponent = new CSkaterProximityComponent;\r\n\tAddComponent( p_skaterProximityComponent );\r\n\r\n\tCSoundComponent* p_soundComponent = new CSoundComponent;\r\n\tAddComponent(p_soundComponent);\r\n\t\r\n\tCStreamComponent* p_streamComponent = new CStreamComponent;\r\n\tAddComponent(p_streamComponent);\r\n\t\r\n    CLockObjComponent* p_lockObjComponent = new CLockObjComponent;\r\n\tAddComponent(p_lockObjComponent);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovingObject::MovingObjectInit( Script::CStruct* pNodeData, CGeneralManager* p_obj_man )\r\n{\r\n\t// Dan: a hack for now to detect whether anyone has called CreateComponents() yet or not\r\n\t// once components are created in a consistent manner across object types, we can remove this sort of foolishness\r\n\tif (!GetMotionComponent())\r\n\t{\r\n\t\tMovingObjectCreateComponents();\r\n\t}\r\n\t\r\n\tDbg_MsgAssert( GetMotionComponent(), ( \"Motion component doesn't exist yet\" ) );\r\n\t\r\n\tGetMotionComponent()->OrientToNode( pNodeData );\r\n\t\r\n\t//----------------------------------------\r\n\t// MOVED FROM POSOBJECT.H\r\n\tDbg_MsgAssert( pNodeData, ( \"Couldn't find node structure.\" ));\r\n\t\r\n\t// Get the checksum ...\r\n\tuint32\tNodeNameChecksum = 0;\r\n\tpNodeData->GetChecksum(CRCD(0xa1dc81f9,\"Name\"),&NodeNameChecksum);\r\n\tif (NodeNameChecksum)\r\n\t{\r\n\t\tSetID(NodeNameChecksum);\r\n\t}\t\r\n\t\r\n\tuint32 AIScriptChecksum=0;\r\n\tif ( pNodeData->GetChecksum(CRCD(0x2ca8a299,\"TriggerScript\"),&AIScriptChecksum) )\r\n\t{\r\n\t\tScript::CScriptStructure *pScriptParams=NULL;\r\n\t\tpNodeData->GetStructure(CRCD(0x7031f10c,\"Params\"),&pScriptParams);\r\n\t\tSwitchScript( AIScriptChecksum, pScriptParams );\r\n\t}\r\n\t//----------------------------------------\r\n\t\r\n\tGetMotionComponent()->InitFromStructure( pNodeData );\r\n\tGetSuspendComponent()->InitFromStructure( pNodeData );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGfx::CSkeleton* CMovingObject::GetSkeleton()\r\n{\r\n\tObj::CSkeletonComponent* p_skeleton_component = GetSkeletonComponent();\r\n\tif ( p_skeleton_component )\r\n\t{\r\n\t\treturn p_skeleton_component->GetSkeleton();\r\n\t}\r\n\r\n    return NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nNx::CModel* CMovingObject::GetModel()\r\n{\r\n\tObj::CModelComponent* p_model_component = GetModelComponent();\r\n    if ( p_model_component )\r\n    {\r\n        return p_model_component->GetModel();\r\n    }\r\n    \r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovingObject::LookAtObject_Init( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 typeChecksum;\r\n\tif ( pParams->GetChecksum( 0x7321a8d6, &typeChecksum ) ) // \"type\"\r\n\t{\r\n\t\tint type;\r\n\t\tswitch ( typeChecksum )\r\n\t\t{\r\n\t\t\tcase 0x88c21962: // car\r\n\t\t\t\ttype = SKATE_TYPE_CAR;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x61a741e: // ped\r\n\t\t\t\ttype = SKATE_TYPE_PED;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x5b8ab877: // skater\r\n\t\t\t\ttype = SKATE_TYPE_SKATER;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x3b5737a6:  // gameobj\r\n\t\t\t\ttype = SKATE_TYPE_GAME_OBJ;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert( 0,( \"\\n%s\\nUnknown type %s\", pScript->GetScriptInfo( ), Script::FindChecksumName( typeChecksum ) ));\r\n\t\t\t\treturn false;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tCCompositeObject* pClosestObject = GetClosestObjectOfType( type );\r\n\t\tif ( !pClosestObject )\r\n\t\t{\r\n\t\t\tDbg_Message( \"\\n%s\\nWarning:  Looking at object that doesn't exist.\", pScript->GetScriptInfo( ) );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn GetMotionComponent()->LookAt_Init( pParams, pClosestObject->m_pos );\r\n\t}\r\n\t\r\n\t// find a named object:\r\n\tuint32 nameChecksum;\r\n\tif ( pParams->GetChecksum( 0xa1dc81f9, &nameChecksum ) ) // \"name\"\r\n\t{\r\n\t\tCCompositeObject* pNext;\r\n\t\tCCompositeObject* pObj;\r\n\t\tLst::Search< CObject >\tsh;\r\n\t\tDbg_MsgAssert(mp_manager,(\"NULL mp_Manager in MovingObject\"));\r\n\t\tpNext = (Obj::CCompositeObject*) sh.FirstItem( mp_manager->GetRefObjectList() );\r\n\t\twhile ( pNext )\r\n\t\t{\r\n\t\t\tDbg_AssertType( pNext, CCompositeObject );\r\n\t\t\tpObj = pNext;\r\n\t\t\tpNext = (Obj::CCompositeObject*) sh.NextItem();\r\n\t\t\t// find objects spawned from this node, return true if out of this radius...\r\n\t\t\tif ( ( pObj != this ) && ( pObj->GetID() == nameChecksum ) )\r\n\t\t\t{\r\n\t\t\t\treturn GetMotionComponent()->LookAt_Init( pParams, pObj->m_pos );\r\n\t\t\t}\r\n\t\t}\r\n\t\tDbg_Message( \"\\n%s\\nWarning:  Looking at object that doesn't exist.\", pScript->GetScriptInfo( ) );\r\n\t\treturn false;\r\n\t}\r\n\tDbg_Message( \"\\n%s\\nWarning: No object specified for Obj_LookAtObject\", pScript->GetScriptInfo( ) );\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovingObject::ObjectFromNodeWithinRange( int nodeIndex, int radiusSqr, SiteBox* pBox )\r\n{\r\n\tuint32\tnodeNameChecksum = SkateScript::GetNodeNameChecksum(nodeIndex);\r\n\r\n// TODO:  Since there can only be one object from a node, then should be able to get it directly\r\n\t\r\n\tbool retVal = false;\r\n\tCMovingObject* pNext;\r\n\tCMovingObject* pObj;\r\n\tLst::Search< CObject >\tsh;\r\n//\tDbg_MsgAssert(mp_manager,(\"NULL mp_Manager in MovingObject. Node Checksum = 0x%x (%s)\",GetID(),Script::FindChecksumName(GetID())));\r\n\tDbg_MsgAssert(mp_manager,(\"NULL mp_Manager in MovingObject. Node Checksum = 0x%x (%s)\",GetID(),Script::FindChecksumName(GetID())));\r\n\tpNext = (Obj::CMovingObject *) sh.FirstItem( mp_manager->GetRefObjectList() );\r\n\twhile ( pNext )\r\n\t{\r\n\t\tDbg_AssertType( pNext, CMovingObject );\r\n\t\tpObj = (Obj::CMovingObject *) pNext;\r\n\t\tpNext = (Obj::CMovingObject *) sh.NextItem();\r\n\t\t\r\n\t\tif ( ( pObj->GetID() == nodeNameChecksum ) && ( pObj != this ) )\r\n\t\t{\r\n\t\t\tif ( pBox )\r\n\t\t\t{\r\n\t\t\t\tif ( ObjInSiteBox( pObj, pBox ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tretVal = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( Mth::DistanceSqr( pObj->m_pos, m_pos ) < radiusSqr )\r\n\t\t\t{\r\n\t\t\t\tretVal = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn ( retVal );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CMovingObject::GetSiteBoxMaxRadiusSquared( SiteBox* pBox )\r\n{\r\n\tfloat maxBoxDist;\r\n\tif ( pBox->maxDistInitialized )\r\n\t{\r\n\t\treturn ( pBox->maxDistSquared );\r\n\t}\r\n\tmaxBoxDist = fabsf( pBox->dist );\r\n\tif ( fabsf( pBox->height ) > maxBoxDist )\r\n\t{\r\n\t\tmaxBoxDist = fabsf( pBox->height );\r\n\t}\r\n\tif ( fabsf( pBox->width ) > maxBoxDist )\r\n\t{\r\n\t\tmaxBoxDist = fabsf( pBox->width );\r\n\t}\r\n\r\n\tfloat maxOffset;\r\n\tMth::Vector* pOffset;\r\n\tpOffset = &pBox->bbox.centerOfGravity;\r\n\tmaxOffset = fabsf( pOffset->GetZ( ) );\r\n\tif ( fabsf( pOffset->GetY( ) ) > maxOffset )\r\n\t{\r\n\t\tmaxOffset = fabsf( pOffset->GetY( ) );\r\n\t}\r\n\tif ( fabsf( pOffset->GetX( ) ) > maxOffset )\r\n\t{\r\n\t\tmaxOffset = fabsf( pOffset->GetX( ) );\r\n\t}\r\n\r\n\tpBox->maxDistSquared = maxOffset + maxBoxDist;\r\n\tpBox->maxDistSquared *= pBox->maxDistSquared;\r\n\tpBox->maxDistInitialized = true;\r\n\treturn ( pBox->maxDistSquared );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovingObject::InitializeSiteBox( SiteBox* pBox )\r\n{\r\n\tif ( pBox->initialized )\r\n\t{\r\n\t\t// already initialized!\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tpBox->matrix = m_matrix;\r\n\tif ( pBox->angle )\r\n\t{\r\n\t\tpBox->matrix = pBox->matrix.RotateYLocal( pBox->angle );\r\n\t}\r\n\tpBox->matrix.Invert( );\r\n\t\r\n\tSBBox* pBBox = &pBox->bbox;\r\n\t// start by setting min/max to half the dimentions:\r\n\tpBBox->m_max.Set( pBox->width / 2.0f, pBox->height / 2.0f, pBox->dist );\r\n\tpBBox->m_min = -pBBox->m_max;\r\n\tpBBox->m_min[ Z ] = 0.0f;\r\n\r\n\t// using the vector in pBox->bbox.centerOfGravity to store offset\r\n\t// sent by the player! MISNOMER:\r\n\tpBBox->m_max += pBBox->centerOfGravity;\r\n\tpBBox->m_min += pBBox->centerOfGravity;\r\n\t\t\r\n\t// gots ta move the site box up so that it comes from the object's\r\n\t// center of gravity (as the object's position isn't usually the center\r\n\t// of gravity):\r\n/*\tif ( mp_model )\r\n\t{\r\n\t\t//Mth::Vector temp3;\r\n\t\t//temp3 = m_pos + centerOfGravity;\t\t\r\n\t\t//Gfx::AddDebugLine( m_pos, temp3 );\r\n\t\tpBBox->m_max += m_bbox.centerOfGravity;\r\n\t\tpBBox->m_min += m_bbox.centerOfGravity;\r\n\t}*/\r\n\r\n#ifndef __PLAT_NGC__\t\r\n#ifdef __NOPT_ASSERT__\t\r\n\tif ( pBox->debug )\r\n\t{\r\n\t\tpBBox->centerOfGravity.Set( ); // zero that out for the render...\r\n\t\tMth::Vector drawOffset;\r\n//\t\tdrawOffset.Set( 0, m_ground_offset, 0 );\r\n\t\tdrawOffset.Set( 0, 0, 0 );\r\n\t\tif ( pBox->angle )\r\n\t\t{\r\n\t\t\tMth::Vector angles;\r\n\t\t\tangles.Set( 0, pBox->angle, 0 );\r\n\t\t\tDrawBoundingBox( pBBox, &drawOffset, 10, &angles );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDrawBoundingBox( pBBox, &drawOffset, 10 );\r\n\t\t}\r\n\t}\r\n#endif\r\n#endif\r\n\t\r\n\t// Phew... now we can quickly check objects by rotating their position\r\n\t// into our world, and seeing if they're in the motherfuckin' box:\r\n\tpBox->initialized = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovingObject::ObjInSiteBox( CMovingObject* pObj, SiteBox* pBox )\r\n{\r\n\t// K: There was a bug whereby the initial distance check below was not taking\r\n\t// into account the offset of the box.\r\n\t// The offset is stored in centerOfGravity which may get zeroed in InitializeSiteBox,\r\n\t// so store it here.\r\n\tMth::Vector off=pBox->bbox.centerOfGravity;\r\n\t\r\n\t// initialize the site box and the BBox contained therein:\r\n\tInitializeSiteBox( pBox );\r\n\r\n\t// sorta trivial radius check and return...\r\n\tfloat distSquared;\r\n\tdistSquared = Mth::DistanceSqr( pObj->m_pos+off, m_pos );\r\n\tfloat boxRadiusSquared = GetSiteBoxMaxRadiusSquared( pBox );\r\n\tif ( distSquared > boxRadiusSquared )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tMth::Vector objPos;\r\n\tobjPos = pObj->m_pos;\r\n\t\r\n\t// center of the object...\r\n\tobjPos[ Y ] += ( pObj->m_bbox.m_max[ Y ] - pObj->m_bbox.m_min[ Y ] ) / 2.0f;\r\n\r\n#ifndef __PLAT_NGC__\t\r\n#ifdef __NOPT_ASSERT__\r\n\tMth::Vector preTransform = objPos;\r\n#endif\t\r\n#endif\t\r\n\r\n\tobjPos -= m_pos;\r\n\t// now we have the head and toes at the right distance from us and from each other...\r\n\t// rotate them into our world:\r\n\tobjPos = pBox->matrix.Transform( objPos );\r\n\t\r\n#ifndef __PLAT_NGC__\t\r\n#ifdef __NOPT_ASSERT__\r\n\tif ( pBox->debug )\r\n\t{\r\n\t\tif ( Gfx::PointInsideBox( objPos, pBox->bbox.m_max, pBox->bbox.m_min ) )\r\n\t\t{\r\n\t\t\tGfx::AddDebugLine( m_pos, preTransform, MAKE_RGB( 150, 50, 50 ), MAKE_RGB( 150, 50, 50 ), 10 );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tGfx::AddDebugLine( m_pos, preTransform, MAKE_RGB( 50, 50, 100 ), MAKE_RGB( 50, 50, 100 ), 10 );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n#endif\r\n#endif\r\n\treturn ( Gfx::PointInsideBox( objPos, pBox->bbox.m_max, pBox->bbox.m_min ) );\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovingObject::FillInSiteBox(SiteBox* p_siteBox, Script::CStruct* pParams)\r\n{\r\n\tDbg_MsgAssert(p_siteBox,(\"NULL p_siteBox\"));\r\n\tDbg_MsgAssert(pParams,(\"NULL pParams\"));\r\n\t\r\n\tp_siteBox->initialized = false;\r\n\tp_siteBox->angle = 0;\r\n\tp_siteBox->maxDistInitialized = false;\r\n\t\r\n\t// Misnomer: used for offsetting the site box...\r\n\t// But we will want it to default to the center of gravity:\r\n\tp_siteBox->bbox.centerOfGravity = m_bbox.centerOfGravity;\r\n\t\r\n    p_siteBox->height = p_siteBox->width = p_siteBox->dist = 0.0f;\r\n\t\r\n\tMth::Vector offset;\r\n\toffset[W]=0.0f; //\r\n\tif ( pParams->GetVector( 0xa6f5352f, &offset ) ) // offset\r\n\t{\r\n\t\toffset.FeetToInches( );\r\n\t\tp_siteBox->bbox.centerOfGravity += offset;\r\n\t}\r\n\r\n\tif ( pParams->GetFloat( 0xff7ebaf6, &p_siteBox->angle ) ) // angle\r\n\t{\r\n\t\tp_siteBox->angle = DEGREES_TO_RADIANS( p_siteBox->angle );\r\n\t}\r\n\r\n\tif ( pParams->GetFloat( 0xab21af0, &p_siteBox->height ) ) // height\r\n\t{\r\n\t\tp_siteBox->height = FEET_TO_INCHES( p_siteBox->height );\r\n\t}\r\n\tif ( pParams->GetFloat( 0x7e832f08, &p_siteBox->dist ) ) // dist\r\n\t{\r\n\t\tp_siteBox->dist = FEET_TO_INCHES( p_siteBox->dist  );\r\n\t}\r\n\tif ( pParams->GetFloat( 0x73e5bad0, &p_siteBox->width ) ) // width\r\n\t{\r\n\t\tp_siteBox->width = FEET_TO_INCHES( p_siteBox->width );\r\n\t}\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\t\r\n\tp_siteBox->debug = 0;\r\n\r\n\tp_siteBox->debug = pParams->ContainsFlag( 0x935ab858 ); // debug\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovingObject::ObjectWithinRect( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tSiteBox siteBox;\r\n\tFillInSiteBox(&siteBox,pParams);\r\n\t\r\n\treturn ( ObjectWithinRange( pParams, pScript, &siteBox ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovingObject::SkaterInRange( SiteBox* pBox, float radiusSqr )\r\n{\r\n\tint numSkaters = Mdl::Skate::Instance()->GetNumSkaters( );\r\n\t\r\n\tfor ( int i = 0; i < numSkaters; i++ )\r\n\t{\r\n\t\tCMovingObject* pObj = Mdl::Skate::Instance()->GetSkater( i );\r\n\t\tif ( pObj != this )\r\n\t\t{\r\n\t\t\tif ( pBox )\r\n\t\t\t{\r\n\t\t\t\tif ( ObjInSiteBox( pObj, pBox ) )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( Mth::DistanceSqr( pObj->m_pos, m_pos ) < radiusSqr )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovingObject::ObjTypeInRange( Script::CStruct* pParams, Script::CScript* pScript, float radiusSqr, SiteBox* pBox, uint32 typeChecksum )\r\n{\r\n\t\r\n\tint type;\r\n\tSearch objSearch;\t\t\r\n\tCMovingObject* pObj;\r\n\tswitch ( typeChecksum )\r\n\t{\r\n\t\tcase 0x88c21962: // car\r\n\t\t\ttype = SKATE_TYPE_CAR;\r\n\t\t\tbreak;\r\n\t\tcase 0x61a741e: // ped\r\n\t\t\ttype = SKATE_TYPE_PED;\r\n\t\t\tbreak;\r\n\t\tcase 0x5b8ab877: // skater\r\n\t\t\treturn ( SkaterInRange( pBox, radiusSqr ) );\r\n\t\t\tbreak;\r\n\t\tcase 0x3b5737a6: // gameobj\r\n\t\t\ttype = SKATE_TYPE_GAME_OBJ;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( \"\\n%s\\nUnknown type %s\",((char *)( pScript->GetScriptInfo( ), Script::FindChecksumName( typeChecksum ) )));\r\n\t\t\treturn false;\r\n\t\t\tbreak;\r\n\t}\r\n\tDbg_MsgAssert(mp_manager,(\"NULL mp_Manager in MovingObject\"));\r\n\tpObj = (Obj::CMovingObject *) objSearch.FindFirstObjectOfType( mp_manager->GetRefObjectList(), type );\r\n\twhile ( pObj )\r\n\t{\r\n\t\tif ( pObj != this )\r\n\t\t{\r\n\t\t\tif ( pBox )\r\n\t\t\t{\r\n\t\t\t\tif ( ObjInSiteBox( pObj, pBox ) )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( Mth::DistanceSqr( pObj->m_pos, m_pos ) < radiusSqr )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tpObj = (Obj::CMovingObject *) objSearch.FindNextObjectOfType( );\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovingObject::ObjectWithinRange( Script::CStruct* pParams, Script::CScript* pScript, SiteBox* pBox )\r\n{\r\n\tfloat radiusSqr = 0.0f;\r\n\t\r\n\tif ( !pBox )\r\n\t{\r\n\t\tif( !( pParams->GetFloat( 0xc48391a5, &radiusSqr ) ) )//\"radius\"\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"\\n%s\\nNo radius specified in Obj_*InRadius.\", pScript->GetScriptInfo( ) ));\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tradiusSqr = FEET_TO_INCHES( radiusSqr );\r\n\t\tradiusSqr *= radiusSqr;\r\n\t}\r\n\r\n\tScript::CArray* pArray=NULL;\r\n\tuint32 typeChecksum;\r\n\tif ( pParams->GetChecksum( 0x7321a8d6, &typeChecksum ) ) // \"type\"\r\n\t{\r\n\t\treturn ( ObjTypeInRange( pParams, pScript, radiusSqr, pBox, typeChecksum ) );\r\n\t}\r\n\telse if ( pParams->GetArray( 0x7321a8d6, &pArray, Script::ASSERT ) ) // \"type\"\r\n\t{\r\n\t\tDbg_MsgAssert( pArray->GetType( ) == ESYMBOLTYPE_NAME,( \"\\n%s\\nObjectWithinRange: Array must be of names\",pScript->GetScriptInfo()));\r\n\t\tuint32 i;\r\n\t\tfor ( i = 0; i < pArray->GetSize( ); ++i )\r\n\t\t{\r\n\t\t\tif ( ObjTypeInRange( pParams, pScript, radiusSqr, pBox, pArray->GetChecksum( i ) ) )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn false;\t\t\r\n\t}\r\n\r\n\t// find a named object:\r\n\tuint32 nameChecksum;\r\n\tif ( pParams->GetChecksum( 0xa1dc81f9, &nameChecksum ) ) // \"name\"\r\n\t{\r\n\t\tint nodeNum = SkateScript::FindNamedNode( nameChecksum );\r\n\t\treturn ( ObjectFromNodeWithinRange( nodeNum, radiusSqr, pBox ) );\r\n\t}\r\n    const char* pPrefix;\r\n\tif ( pParams->GetText( 0x6c4e7971, &pPrefix ) ) // checksum 'prefix'\r\n\t{\r\n\t\t// Create with a prefix specified:\r\n\t\tuint16 numNodes = 0;\r\n\t\tconst uint16* pMatchingNodes = SkateScript::GetPrefixedNodes( pPrefix, &numNodes );\r\n\t\tint i;\r\n\t\tfor ( i = 0; i < numNodes; i++ )\r\n\t\t{\r\n\t\t\tif ( ObjectFromNodeWithinRange( pMatchingNodes[ i ], radiusSqr, pBox ) )\r\n\t\t\t{\r\n\t\t\t\t//printf(\"Oof old\\n\");\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n\t\r\n//\tDbg_Message( \"\\n%s\\nWarning: Unprocessed radius ( or site box ) check... unrecognized syntax. needs 'type', 'name' or 'prefix'\", pScript->GetScriptInfo( ) );\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovingObject::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{   \r\n\tswitch (Checksum)\r\n\t{\t\t\t\t\r\n\t\t// @script | Obj_LookAtObject | \r\n\t\t// Returns true if the object will rotate itself to point in the required direction. Ie, if\r\n\t\t// the object is already pointing the right way, the command will return false.\r\n        // @parmopt name | lockAxis | | can lock any two axes (LOCK_X, LOCK_Y, LOCK_Z)\r\n        // @parmopt float | time | vel/acceleration | in seconds\r\n        // @parmopt float | speed | 360  | angular velocity in degrees per second\r\n        // @parmopt float | acceleration | 0 | angular acceleration in degrees per second\r\n        // per second\r\n        // @parmopt name | name | | name of object\r\n        // @parmopt name | type | | type of object to look at - will look at closest if \r\n        // there are several in the world\r\n        case 0x33e04032:  // Obj_LookAtObject\r\n\t\t\treturn LookAtObject_Init( pParams, pScript );\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0x37185d8a:  // Obj_AngleToNearestSkaterGreaterThan\r\n\t\t{\r\n\t\t\tint type = SKATE_TYPE_SKATER;\r\n\t\t\tObj::CCompositeObject* pClosestObject = GetClosestObjectOfType( type );\r\n\t\t\tif ( !pClosestObject )\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"\\n%s\\nWarning:  Checking angle to skater that doesn't exist.\", pScript->GetScriptInfo() );\r\n\t\t\t\treturn false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tfloat threshold;\r\n\t\t\tpParams->GetFloat( NONAME, &threshold, Script::ASSERT );\r\n\t\t\tDbg_MsgAssert( threshold >= 0, ( \"Negative angle passed to Obj_AngleToNearestSkaterGreaterThan\" ) );\r\n\t\t\tthreshold = DEGREES_TO_RADIANS( threshold );\r\n\r\n\t\t\tMth::Vector pathHeading = pClosestObject->m_pos - m_pos;\r\n\t\t\tfloat test = Mth::GetAngle( m_matrix, pathHeading, 2, 1 );\r\n\t\t\tif ( fabs( test ) > threshold )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\treturn false;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | Obj_ObjectInRadius | \r\n        // @parmopt name | name | | use one of: name, prefix, or type\r\n        // @parmopt name | prefix | | use one of: name, prefix, or type\r\n        // @parmopt name | type | | use one of: name, prefix, or type\r\n        // (type values are skater, ped, car)\r\n        // @parm float | radius | radius in feet\r\n\t\tcase 0x67660fe5:  // Obj_ObjectInRadius\r\n\t\t\treturn ( ObjectWithinRange( pParams, pScript ) );\r\n\t\t\tbreak;\r\n\r\n        // @script | Obj_ObjectInRect | \r\n        // @parmopt float | angle | 0 | in degrees - default is  \r\n        // along the direction the object is facing\r\n        // @parmopt float | height | (height of object) | \r\n        // @parmopt float | distance | (length of object) | in feet - \r\n        // offset by half of the object in the direction determined by the angle\r\n        // @parmopt float | width | (width of object) | in feet\r\n        // @parmopt vector | offset | | in feet - the rectangle by default will be located\r\n        // sticking out of the XZ plane (or XY plane in Max coords ),\r\n        // rotated by number of degrees in angle parameter\r\n\t\t// @flag debug | just a parameter to turn on debugging info, \r\n        // to quickly set up rectangles on an object.\r\n        // @parmopt name | name | | use one of: name, prefix, or type\r\n        // @parmopt name | prefix | | use one of: name, prefix, or type\r\n        // @parmopt name | type | | use one of: name, prefix, or type\r\n        // (type values are skater, ped, car)\r\n        case 0x6520b902: // Obj_ObjectInRect\r\n\t\t{\r\n\t\t\treturn ( ObjectWithinRect( pParams, pScript ) );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | Obj_ObjectNotInRect | \r\n        // @parmopt float | angle | 0 | in degrees - default is  \r\n        // along the direction the object is facing\r\n        // @parmopt float | height | (height of object) | \r\n        // @parmopt float | distance | (length of object) | in feet - \r\n        // offset by half of the object in the direction determined by the angle\r\n        // @parmopt float | width | (width of object) | in feet\r\n        // @parmopt vector | offset | | in feet - the rectangle by default will be located\r\n        // sticking out of the XZ plane (or XY plane in Max coords ),\r\n        // rotated by number of degrees in angle parameter\r\n        // @flag debug | just a parameter to turn on debugging info, \r\n        // to quickly set up rectangles on an object.\r\n        // @parmopt name | name | | use one of: name, prefix, or type\r\n        // @parmopt name | prefix | | use one of: name, prefix, or type\r\n        // @parmopt name | type | | use one of: name, prefix, or type\r\n        // (type values are skater, ped, car)\r\n\t\tcase 0x3b6b66c3: // Obj_ObjectNotInRect\r\n\t\t\treturn ( !ObjectWithinRect( pParams, pScript ) );\r\n\t\t\tbreak;\r\n\r\n\r\n\t\t// @script | Obj_SetBodyShape | Sets the body shape for this object\r\n        // @parm structure | body_shape | a list of per-bone scales (see scaling.q for format)\r\n\t\tcase 0x802a7600: // Obj_SetBodyShape\r\n\t\t{\r\n\t\t\tScript::CStruct* pBodyShapeStructure;\r\n\t\t\tpParams->GetStructure( CRCD(0x812684ef,\"body_shape\"), &pBodyShapeStructure, true );\r\n\r\n\t\t\tif ( GetModel() )\r\n\t\t\t{\r\n\t\t\t\tGfx::CSkeleton* pSkeleton = GetSkeleton();\r\n\t\t\t\tDbg_Assert( pSkeleton );\r\n\t\t\t\tpSkeleton->ApplyBoneScale( pBodyShapeStructure );\r\n\t\t\t\r\n\t\t\t\tMth::Vector theScale( 1.0f, 1.0f, 1.0f );\r\n\t\t\t\tif ( Gfx::GetScaleFromParams( &theScale, pBodyShapeStructure ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tGetModel()->SetScale( theScale );\r\n\t\t\t\t}\r\n\t\t\t}\t\t\t\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\treturn ( CCompositeObject::CallMemberFunction( Checksum, pParams, pScript ) );\r\n\t\t\tbreak;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCompositeObject* CMovingObject::GetClosestObjectOfType( int type )\r\n{\r\n\tSearch objSearch;\r\n\tCCompositeObject *pObj;\t\t\r\n\tpObj = (CCompositeObject *) objSearch.FindFirstObjectOfType( mp_manager->GetRefObjectList(), type );\r\n\tif ( pObj == this )\r\n\t{\r\n\t\tif ( !( pObj = (CCompositeObject*) objSearch.FindNextObjectOfType( ) ) )\r\n\t\t{\r\n\t\t\treturn ( NULL );\r\n\t\t}\r\n\t}\r\n\tif ( !( pObj ) )\r\n\t{\r\n\t\treturn ( NULL );\r\n\t}\r\n\tfloat closestDist = FEET_TO_INCHES( 666.0f * 666.0f );\r\n\tfloat dist;\r\n\tCCompositeObject* pClosestObj = pObj;\r\n\twhile ( pObj )\r\n\t{\r\n\t\tdist = Mth::Distance( pObj->m_pos, m_pos );\r\n\t\tif ( ( pObj != this ) && ( dist < closestDist ) )\r\n\t\t{\r\n\t\t\tclosestDist = dist;\r\n\t\t\tpClosestObj = pObj;\r\n\t\t}\r\n\t\tpObj = (CCompositeObject*) objSearch.FindNextObjectOfType( );\r\n\t}\r\n\treturn ( pClosestObj );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n"
  },
  {
    "path": "Code/Sk/Objects/MovingObject.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       MovingObject.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/25/2000\r\n//****************************************************************************\r\n\r\n#ifndef __OBJECTS_MOVINGOBJECT_H\r\n#define __OBJECTS_MOVINGOBJECT_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <core/math.h>\r\n#include <core/task.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\tclass \tCSkeleton;\r\n\tclass \tCModelAppearance;\r\n};\r\n\t\t\t\t\t\t\t\t\t\t\t  \r\nnamespace Nx\r\n{\r\n    class \tCModel;\r\n\tclass \tCCollObj;\r\n};\r\n\r\nnamespace Obj\r\n{\r\n    class \tCFollowOb;\r\n\tclass\tCRailManager;\r\n\tclass\tCObjectHookManager;\r\n    \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstruct SiteBox\r\n{\r\n\tMth::Matrix     matrix;\r\n\tfloat           height;\r\n\tfloat           dist;\r\n\tfloat           width;\r\n\tfloat           angle;\r\n\tSBBox           bbox;\r\n\tbool            initialized;\r\n\tbool            maxDistInitialized;\r\n\tfloat           maxDistSquared;\r\n\r\n#ifdef __NOPT_ASSERT__\t\r\n\tbool            debug;\r\n#endif\r\n};\r\n\r\nclass CMovingObject : public CCompositeObject \r\n{\r\npublic :\r\n\t\tCMovingObject();\r\n\t\tvirtual ~CMovingObject( void );\r\n\r\npublic:\r\n\t\tvoid\t\t\t\t\tMovingObjectCreateComponents();\r\n\t\tvoid \t\t\t\t\tMovingObjectInit( Script::CStruct* pNodeData, CGeneralManager* p_obj_man );\r\n\r\n\t\tvirtual bool\t\t\tCallMemberFunction( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\n\t\tGfx::CSkeleton*\t\t\tGetSkeleton( void );\r\n\t\tNx::CModel*\t\t\t\tGetModel( void );\r\n\t\t\t\t\r\nprotected:\r\n\t\tvoid\t\t\t\t\tFillInSiteBox(SiteBox *p_siteBox, Script::CStruct *pParams);\r\n\t\tbool\t\t\t\t\tObjInSiteBox( CMovingObject *pObj, SiteBox *pBox );\r\n\r\npublic:\r\n//\t\tbool\t\t\t\t\tIsFlipped( void );\r\n\t\tvoid\t\t\t\t\tGetHoverOrgPos( Mth::Vector *p_orgPos );\r\n\t\t\r\nprotected:\r\n\t\tbool\t\t\t\t\tObjectWithinRange( Script::CStruct *pParams, Script::CScript *pScript, SiteBox *pBox = NULL );\r\n\t\tbool \t\t\t\t\tObjectWithinRect( Script::CStruct *pParams, Script::CScript *pScript );\r\n\t\tbool\t\t\t\t\tObjectFromNodeWithinRange( int nodeIndex, int radiusSqr, SiteBox *pBox );\r\n\t\tvoid\t\t\t\t\tInitializeSiteBox( SiteBox *pBox );\r\n\t\tfloat\t\t\t\t\tGetSiteBoxMaxRadiusSquared( SiteBox *pBox );\r\n\t\tbool\t\t\t\t\tObjTypeInRange( Script::CStruct *pParams, Script::CScript *pScript, float radiusSqr, SiteBox *pBox, uint32 typeChecksum );\r\n\t\tbool\t\t\t\t\tSkaterInRange( SiteBox *pBox, float radiusSqr );\r\n\t\t\r\nprotected:\r\n\t\tvoid\t\t\t\t\tDrawBoundingBox( SBBox *pBox, Mth::Vector *pOffset = NULL, int numFrames = 1, Mth::Vector *pRot = NULL );\r\n\t\t\r\n\t\tvoid\t\t\t\t\tToggleFlipState( void );\r\n\r\nprotected:\r\n\t\t// float\t\t\t   \t\tm_time;\t\t\t\t\t// time since last frame\r\n  \r\n\t\t// the rest of the flags stay here...\r\n//\t    int\t\t\t\t\t\tm_general_flags;\r\n\t\t\r\n\t\t// will add rotation vector (or rotation class?) to this ASAP...\r\n\r\nprivate:\t\t\r\n\t\tbool\t\t\t\t\tLookAtObject_Init( Script::CStruct *pParams, Script::CScript *pScript );\r\n\t\tvoid\t\t\t\t\tFollowLeader_Init( Script::CStruct *pParams );\r\n\r\n\t\t// GJ:  MOVED THESE FROM POSOBJECT.H\r\npublic:\r\n\t\t// Currently used by the PauseSkaters script command, which is used to pause all the skaters whilst\r\n\t\t// a camera animation is running.\r\n\t\tvirtual void \t\t\tPause() {mPaused=true; CCompositeObject::Pause(true);}\r\n\t\tvirtual void \t\t\tUnPause() {mPaused=false; CCompositeObject::Pause(false);}\r\n\t\tbool\t\t \t\t\tIsPaused() {return mPaused;}\r\n\r\n\t\tSBBox\t\t\t\t\tm_bbox;\r\n\r\n\tprotected:\r\n\t\tCCompositeObject*\t\tGetClosestObjectOfType( int type );\r\n\r\n\tpublic :\r\n\t\t// Whether the object is paused.\r\n\t\tbool\t\t\t\t\tmPaused;\r\n};\r\n\t\t\t\t\t\t\t  \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_MOVINGOBJECT_H\r\n"
  },
  {
    "path": "Code/Sk/Objects/PathMan.cpp",
    "content": "#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <objects/pathman.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\nCPathObjectTracker *CPathMan::TrackObject(CCompositeObject *p_ob, int node_number)\r\n{\r\n\tScript::CStruct *p_node=SkateScript::GetNode(node_number);\r\n\t#ifdef __NOPT_ASSERT__\r\n\tDbg_MsgAssert(p_node,(\"NULL p_node for node %d\",node_number));\r\n\t#endif\r\n\t\r\n\tint path_number=0;\r\n\tif (!p_node->GetInteger(\"PathNum\",&path_number))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"Node %d does not contain a PathNum\",node_number));\r\n\t}\r\n\t\t\r\n\tDbg_MsgAssert(path_number>=0 && path_number<MAX_PATHS,(\"Bad PathNum of %d for node %d\",path_number,node_number));\r\n\tmp_path_object_trackers[path_number].AddObjectPointer(p_ob);\r\n\treturn &mp_path_object_trackers[path_number];\r\n}\r\n\r\nCPathObjectTracker *CPathMan::TrackPed(CCompositeObject *p_ob, int node_number)\r\n{\r\n\tScript::CStruct *p_node=SkateScript::GetNode(node_number);\r\n\tDbg_MsgAssert(p_node,(\"NULL p_node for node %d\",node_number));\r\n\t\r\n\tint path_number=0;\r\n\tif (!p_node->GetInteger(\"PathNum\",&path_number))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"Node %d does not contain a PathNum\",node_number));\r\n\t}\r\n\t\t\r\n\t// Dbg_MsgAssert(path_number>=0 && path_number<MAX_PATHS,(\"Bad PathNum of %d for node %d\",path_number,node_number));\r\n\t// mp_path_object_trackers[path_number].AddObjectPointer(p_ob);\r\n\tmp_ped_object_tracker.AddObjectPointer( p_ob );\r\n\treturn &mp_ped_object_tracker;\r\n}\r\n\r\nCPathObjectTracker::CPathObjectTracker()\r\n{\r\n\tClear();\r\n}\r\n\r\nCPathObjectTracker::~CPathObjectTracker()\r\n{\r\n}\r\n\r\nvoid CPathObjectTracker::Clear()\r\n{\r\n\tfor (int i=0; i<MAX_OBJECTS_PER_PATH; ++i)\r\n\t{\r\n\t\tmpp_objects[i]=NULL;\r\n\t}\r\n}\r\n\r\nvoid CPathObjectTracker::StopTrackingObject(CCompositeObject *p_ob)\r\n{\r\n\tDbg_MsgAssert(p_ob,(\"NULL p_ob\"));\r\n\tfor (int i=0; i<MAX_OBJECTS_PER_PATH; ++i)\r\n\t{\r\n\t\tif (mpp_objects[i]==p_ob)\r\n\t\t{\r\n\t\t\tmpp_objects[i]=NULL;\r\n\t\t}\r\n\t}\r\n}\t\t\t\r\n\r\nvoid CPathObjectTracker::AddObjectPointer(CCompositeObject *p_ob)\r\n{\r\n\tDbg_MsgAssert(p_ob,(\"NULL p_ob\"));\r\n\t//printf(\"Tracking %s\\n\",Script::FindChecksumName(p_ob->mNodeNameChecksum));\r\n\r\n\tfor (int i=0; i<MAX_OBJECTS_PER_PATH; ++i)\r\n\t{\r\n\t\tif (!mpp_objects[i])\r\n\t\t{\r\n\t\t\tmpp_objects[i]=p_ob;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\t\t\r\n\tDbg_MsgAssert(0,(\"Full CPathObjectTracker\"));\r\n}\r\n\r\n\r\nCPathMan *CPathMan::mp_instance=NULL;\r\n\r\nCPathMan *CPathMan::Instance()\r\n{\r\n\tif (!mp_instance)\r\n\t{\r\n\t\tmp_instance=new CPathMan;\r\n\t}\r\n\treturn mp_instance;\r\n}\r\n\r\nCPathMan::CPathMan()\r\n{\r\n\tm_num_paths=0;\r\n\tmp_path_object_trackers = NULL;\r\n}\r\n\r\nvoid CPathMan::ClearPathObjectTrackers()\r\n{\r\n\tfor (int i=0; i<MAX_PATHS; ++i)\r\n\t{\r\n\t\tmp_path_object_trackers[i].Clear();\r\n\t}\t\r\n}\r\n\r\n// Called just after a new NodeArray is loaded, in ScriptLoadNodeArray in cfuncs.cpp\r\n// Scans through the node array inserting PathNum members to all nodes that are on a path.\r\n// Enables quick look up of what path a car is on, & hence whether it is on the same path as\r\n// another car.\r\nvoid CPathMan::AddPathInfoToNodeArray()\r\n{\r\n//\tDbg_Assert( mp_path_object_trackers );\r\n\tif (!mp_path_object_trackers)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// printf(\"CPathMan::AddPathInfoToNodeArray\\n\");\r\n\tScript::CArray *p_node_array=Script::GetArray(CRCD(0xc472ecc5,\"NodeArray\"),Script::ASSERT);\r\n\t\r\n\tClearPathObjectTrackers();\r\n\t\r\n\t// The path number assigned to the nodes is just an integer, starting at 0   \r\n\tm_num_paths=0;\r\n\t\r\n\tint array_size=p_node_array->GetSize();\r\n\tfor ( uint16 i = 0; i < array_size; ++i )\r\n\t{\r\n\t\tScript::CStruct *p_start_node=p_node_array->GetStructure( i );\r\n\t\t\r\n\t\t// Rail nodes are linked into a path, but don't need path numbers, so don't bother\r\n\t\t// adding them to save memory.\r\n\t\tuint32 class_type=0;\r\n\t\tp_start_node->GetChecksum( CRCD(0x12b4e660,\"Class\"), &class_type );\r\n\t\tif ( class_type == CRCD( 0x8e6b02ad, \"RailNode\" ) ||\r\n\t\t\t class_type == CRCD(0x30c19600, \"ClimbingNode\") )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// make sure this isn't a pedai waypoint\r\n\t\tuint32 type;\r\n\t\tif ( class_type == CRCD( 0x4c23a77e, \"Waypoint\" )\r\n\t\t\t && p_start_node->GetChecksum( CRCD( 0x7321a8d6, \"type\" ), &type, Script::NO_ASSERT )\r\n\t\t\t && type == CRCD( 0xcba10ffa, \"PedAI\" ) )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tint num_links=SkateScript::GetNumLinks( p_start_node );\r\n\t\tint node_path_number = 0;\r\n\t\t// Check if the node is linked to something, and has not already had a PathNum\r\n\t\t// given to it.\r\n\t\tif ( ( num_links || class_type == CRCD( 0x4c23a77e, \"WayPoint\" ) ) && \r\n\t\t\t!p_start_node->ContainsComponentNamed( CRCD( 0x9c91c3ca, \"PathNum\" ) ) )\r\n\t\t{\r\n\t\t\t// printf(\"found a non PedAI waypoint\\n\");\r\n\t\t\t// The node and subsequent nodes that it is linked to require a PathNum\t\t\t\t\r\n\t\t\tScript::CStruct *p_node=p_start_node;\r\n\t\t\t\r\n\t\t\t// The path number that is going to be written in is m_num_paths to start with,\r\n\t\t\t// but that might change if we hit a node that already has a path number. In that\r\n\t\t\t// case we'll rewind and write that number in instead.\r\n\t\t\tint path_number_to_write=m_num_paths;\r\n\t\t\t\r\n\t\t\twhile (true)\r\n\t\t\t{\r\n\t\t\t\tif (p_node->GetInteger( CRCD( 0x9c91c3ca, \"PathNum\" ),&node_path_number))\r\n\t\t\t\t{\r\n\t\t\t\t\t// We've hit a node that has already had a PathNum written in.\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (node_path_number==path_number_to_write)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// The path num matches what we started with, so must have looped\r\n\t\t\t\t\t\t// back to the start, so finished.\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t// We've hit a node that has a different PathNum. So we need to rewind\r\n\t\t\t\t\t// back to where we started and write in that path number instead.\r\n\t\t\t\t\t// This happens due to the fact that the nodes could be in any order in\r\n\t\t\t\t\t// the node array, so paths can start being traversed from any point, not\r\n\t\t\t\t\t// necessarily the start.\r\n\t\t\t\t\tpath_number_to_write=node_path_number;\r\n\t\t\t\t\tp_node=p_start_node;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// Wack in the path number\r\n\t\t\t\tp_node->AddInteger(0x9c91c3ca/*PathNum*/,path_number_to_write);\r\n\t\t\t\t\r\n\t\t\t\t// Check if this is a terminating node of the path, and stop if so.\r\n\t\t\t\tint num_links=SkateScript::GetNumLinks(p_node);\r\n\t\t\t\tif (num_links==0)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\t// On to the next node. Note the if the path branches, it will only\r\n\t\t\t\t// follow the first branch. The other branches will end up getting\r\n\t\t\t\t// their own path numbers. Don't know if this will be a problem yet.\r\n\t\t\t\tp_node=p_node_array->GetStructure(SkateScript::GetLink( p_node, 0 ));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// If path_number got used, increment it ready for the next path.\r\n\t\t\tif (path_number_to_write==m_num_paths)\r\n\t\t\t{\r\n\t\t\t\t++m_num_paths;\r\n\t\t\t\tDbg_MsgAssert(m_num_paths<MAX_PATHS,(\"Too many paths, max=%d\",MAX_PATHS));\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPathMan::DeallocateObjectTrackerMemory()\r\n{\r\n\tif ( mp_path_object_trackers )\r\n\t{\r\n\t\tClearPathObjectTrackers();\r\n\t\tdelete[] mp_path_object_trackers;\r\n\t\tmp_path_object_trackers = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPathMan::AllocateObjectTrackerMemory()\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\tmp_path_object_trackers = new CPathObjectTracker[MAX_PATHS];\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptAllocatePathManMemory( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tObj::CPathMan* pPathMan = Obj::CPathMan::Instance();\r\n\tDbg_Assert( pPathMan );\r\n\tpPathMan->AllocateObjectTrackerMemory();\r\n\treturn true;\r\n}\r\n\r\n} // namespace Obj\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/PathMan.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObject (OBJ)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobjects/pathman.h    \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t5/08/02\t-\tksh\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __OBJECTS_PATHMAN_H\r\n#define __OBJECTS_PATHMAN_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __SYS_MEM_POOLABLE_H\r\n#include <sys/mem/poolable.h>\r\n#endif\r\n\r\n#ifndef __GEL_OBJPTR_H\r\n#include <gel/objptr.h>\r\n#endif\r\n\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/script.h>\r\n\r\nnamespace Obj\r\n{\r\nclass CCompositeObject;\r\n\r\nclass CPathObjectTracker\r\n{\r\npublic:\t\r\nenum\r\n{\r\n\tMAX_OBJECTS_PER_PATH=50\r\n};\t\r\nprivate:\r\n\tCSmtPtr<CCompositeObject> mpp_objects[MAX_OBJECTS_PER_PATH];\r\n\t\r\npublic:\t\r\n\tCPathObjectTracker();\r\n\t~CPathObjectTracker();\r\n\tvoid Clear();\r\n\tvoid AddObjectPointer(CCompositeObject *p_ob);\r\n\tvoid StopTrackingObject(CCompositeObject *p_ob);\r\n\r\n\tconst CSmtPtr<CCompositeObject> *GetObjectList() {return mpp_objects;}\r\n};\r\n\r\nclass CPathMan\r\n{\r\npublic:\r\n\tstatic CPathMan *Instance();\r\n\tvoid RecursivelyAddPathInfo( int path_number_to_write, int node_number, int start_node_number, int recursion_depth = 0 );\r\nprotected:\r\n\tCPathMan();\r\nprivate:\r\n\tstatic CPathMan *mp_instance;\t\t\r\n\t\r\n\t#define MAX_PATHS 300\r\n\tCPathObjectTracker* mp_path_object_trackers;\r\n\tCPathObjectTracker mp_ped_object_tracker;\r\n\tint m_num_paths;\r\n\t\r\npublic:\r\n\tvoid AddPathInfoToNodeArray();\r\n\tvoid ClearPathObjectTrackers();\r\n\r\n\tvoid DeallocateObjectTrackerMemory();\r\n\tvoid AllocateObjectTrackerMemory();\r\n\t\r\n\tCPathObjectTracker *TrackObject(CCompositeObject *p_ob, int node_number);\r\n\tCPathObjectTracker *TrackPed(CCompositeObject *p_ob, int node_number);\r\n};\r\n\r\n//char foo[sizeof(CPathMan)/0];\r\nbool ScriptAllocatePathManMemory( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\n} // namespace Obj\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/PathOb.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       PathOb.cpp\r\n//* OWNER:          Matt Duncan\r\n//* CREATION DATE:  11/2/2000\r\n//****************************************************************************\r\n\r\n/*\r\n\tPathob.cpp\r\n\t\r\n\tThis module contains path-navigation functionality.\r\n\r\n\tA moving object contains a pointer to this pathob.  When\r\n\tthe moving object wants to follow a path along waypoints, it\r\n\tjust initializes this pathob with the current position and tells\r\n\tthe pathob where it wants to go.  Each frame, the moving object\r\n\tcalls TraversePath() and sends in the distance travelled, and\r\n\tits own heading.  The pathob moves accordingly, but the point remains\r\n\ton the plane defined by the points of the path.\r\n\r\n\tThe pathob is its own entity: it's essentially a point in\r\n\tspace and an orientation.  When the moving object calls TraversePath(),\r\n\tthe pathob just does the math and figures out where along the path\r\n\tto move to.  The moving object takes the new path-ob position, finds\r\n\tthe ground above or below this position, and possibly sets its heading\r\n\tso that it's looking the correct direction down the path.\r\n\r\n   \tThe pathob logic handles a simple path between two points... it also\r\n\thandles the curves from one simple path to the next (so the path along\r\n\tthree waypoints, but instead of a sharp turn the pathob follows a curve\r\n\tbetween the two lines).\r\n\r\n\tAs the pathob hits waypoints, it communicates to the moving object (in\r\n\tcase the moving object needs to run a script at the waypoint).\r\n*/\r\n\r\n#include <objects/pathob.h>\r\n\r\n#include <core/debug.h>\r\n\r\n#include <gel/components/motioncomponent.h>\r\n#include <gel/inpman.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/scripting/script.h>\r\n\r\n#include <gfx/debuggfx.h>\r\n\r\n#include <sk/scripting/nodearray.h>\r\n\r\n#include <sys/timer.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// PATHOB flags:\r\n#define PATHOBFLAG_LINEAR_INTERP\t\t\t( 1 << 0 )\r\n#define PATHOBFLAG_END_OF_PATH\t\t\t\t( 1 << 1 )\r\n#define PATHOBFLAG_SEND_HIT_WAYPOINT_MSG\t( 1 << 2 )\r\n\r\n#define MAX_RATIO_OF_HYPOTENUSE_TO_OPPOSITE_FOR_TURN_CIRCLE    6\r\n\r\n// NOTE: if you change this enum, make sure to update the GetDebugInfo func\r\nenum\r\n{\r\n\tPATHOB_STATE_UNINITIALIZED,\r\n\tPATHOB_STATE_FOLLOW_LINE,\r\n\tPATHOB_STATE_FOLLOW_CURVE,\r\n\tPATHOB_STATE_LINEAR_INTERP,\r\n\tPATHOB_STATE_IDLE,\r\n};\r\n\r\nenum\r\n{\r\n\tTURN_METHOD_LINEAR_INTERP,\r\n\tTURN_METHOD_CURVE,\r\n\tTURN_METHOD_INSTANT_TURN,\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPathOb::CPathOb( CCompositeObject* pObj )\r\n{\r\n\tmp_object = pObj;\r\n\tm_turn_matrix.Ident();\r\n\t\r\n\tm_wp_pos_from.Set();\r\n\tm_wp_pos_next.Set();\r\n\tm_wp_pos_to.Set();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPathOb::~CPathOb( void )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPathOb::Busy( void )\r\n{\r\n\tswitch ( m_pathob_state )\r\n\t{\r\n\t\tcase PATHOB_STATE_UNINITIALIZED:\r\n\t\tcase PATHOB_STATE_IDLE:\r\n\t\t\treturn false;\r\n\t\tdefault:\r\n\t\t\treturn true;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPathOb::SetUpNavPointLineMotion( void )\r\n{\r\n\t// assumes we're already on the line.\r\n\t\r\n\t// pre-calculations for navigating between the waypoints...\r\n\t\r\n\tMth::Vector vect_first_to_pos = m_nav_pos - m_wp_pos_from;\r\n\tm_dist_traveled = vect_first_to_pos.Length();\r\n\t\t\t  \r\n\tMth::Vector vect_first_to_second = m_wp_pos_from - m_wp_pos_to;\r\n\tm_dist_to_wp = vect_first_to_second.Length();\r\n    \r\n    m_dist_traveled += m_extra_dist;\r\n\tm_extra_dist = 0;\r\n\t\r\n\t/* Shouldn't need this, now that curve code is independent of turn dist\r\n    if ( m_dist_to_wp < m_current_turn_dist )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Waypoints %d and %d too close or turn radius too large.\", m_node_from, m_node_to ));\r\n\t}*/\r\n\t\r\n\t// set up the heading:\r\n\tm_turn_matrix[ Z ] = m_wp_pos_to - m_wp_pos_from;\r\n\tm_turn_matrix[ Z ].Normalize();\r\n\t\r\n\tSetUpTurnDist();\r\n\t\r\n\treturn( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CPathOb::SetUpTurningCircle( void )\r\n{\r\n\tMth::Vector vectA, vectB;\r\n\t\r\n\t// m_nav_pos holds one point on the circle.\r\n\t// on the line from m_wp_pos_from to m_wp_pos_to\r\n\t// (at the distance of nav pos from m_wp_pos_from)\r\n\t// will be the other point on the circle.\r\n\tvectB = m_nav_pos - m_wp_pos_from;\r\n\r\n\tfloat actualTurnDist = vectB.Length();\r\n\t\t\t\t\t\t\r\n\tm_circle_arrival_pos = m_wp_pos_from;\r\n\tvectA = m_wp_pos_to - m_wp_pos_from;\r\n\tfloat distBetweenWps = vectA.Length();\r\n    vectA *= ( actualTurnDist / distBetweenWps );\r\n\tm_circle_arrival_pos += vectA;\r\n\r\n\t// That's all the info from the turning circle we need, if we're doing a linear interpolation:\r\n\tif ( m_pathob_flags & PATHOBFLAG_LINEAR_INTERP )\r\n\t{\r\n\t\treturn TURN_METHOD_LINEAR_INTERP;\r\n\t}\r\n\t\r\n//\tDbg_MsgAssert( actualTurnDist, \"Traveling too fast for turn dist... increase turn dist or decrease velocity.\" );\r\n\tif ( !actualTurnDist )\r\n\t{\r\n\t\treturn TURN_METHOD_INSTANT_TURN;\r\n\t}\r\n\t\r\n\t// find the radius of the turning circle\r\n\t// the angle between the line we're on and the line to\r\n\t// the arrival pos on the next line is the same as half\r\n\t// the angle that the two radii where the circle touches\r\n\t// the waypoint lines form...  use the similar triangles\r\n\t// to get the circle radius:\r\n\tvectA = m_circle_arrival_pos - m_nav_pos;\r\n\tvectA /= 2; // vector from current pos to midpoint along current pos to arrival pos...\r\n\tfloat lengthPosToMidpoint = vectA.Length();\r\n\r\n\tvectB = m_nav_pos + vectA;\r\n\tvectB -= m_wp_pos_from;\r\n\tfloat distWPtoMP = vectB.Length();\r\n\t\r\n\tif ( ( !distWPtoMP ) | ( ( distWPtoMP * MAX_RATIO_OF_HYPOTENUSE_TO_OPPOSITE_FOR_TURN_CIRCLE ) < lengthPosToMidpoint ) )\r\n\t{\r\n\t\t// almost a straight line... use linear interpolation method:\r\n\t\treturn TURN_METHOD_LINEAR_INTERP;\r\n\t}\r\n\t// to understand this, draw the triangles and derive circle radius\r\n\t// in terms of the known lengths of the similar triangles:\r\n\tm_circle_radius = lengthPosToMidpoint * actualTurnDist;\r\n\tm_circle_radius /= distWPtoMP;\r\n\r\n\tif ( !m_circle_radius )\r\n\t{\r\n\t\t// tiny turn radius... snap to the point and shit like that!\r\n\t\treturn TURN_METHOD_INSTANT_TURN;\r\n\t}\r\n\t\r\n\t// find the location of the center of the circle...\r\n\t// the triangle formed by the current pos, the waypoint pos,\r\n\t// and the midpoint between the current pos and the arrival pos\r\n\t// is a similar triangle to the current pos, the waypoint pos,\r\n\t// and the center of the circle...  therefore the distance from\r\n\t// the center of the circle to the waypoint pos can be found:\r\n\tfloat distFromWaypointToCircleCenter = actualTurnDist * actualTurnDist;\r\n\tdistFromWaypointToCircleCenter /= vectB.Length();\r\n\t// take the vector from the waypoint to the midpoint, make it this length,\r\n\t// and viola we have the circle center:\r\n\tm_circle_center = vectB;\r\n\tm_circle_center.Normalize( distFromWaypointToCircleCenter );\r\n\tm_circle_center += m_wp_pos_from;\r\n\r\n\t// test the distance from the current pos... should equal the frickin' radius:\r\n\t/*\r\n\t{\r\n\t\tMth::Vector temp = m_circle_center;\r\n\t\ttemp -= m_nav_pos;\r\n\t\tDbg_Message( \"dist %f radius %f\", temp.Length(), m_circle_radius );\r\n\t}*/\r\n\t\r\n\tif ( m_circle_radius < m_min_turn_circle_radius )\r\n\t{\r\n\t\tDbg_Message( \"angle too acute to path between nodes %d and %d\", m_node_from, m_node_to );\r\n\t\tDbg_MsgAssert( 0,( \"Turn is too tight for this object...  your waypoints are just too acute for me!\" ));\r\n\t}\r\n\r\n\t// find the \"rotation axis\" (the y axis if we're traveling along the xz plane)\r\n\t// and set up a rotation matrix where the axis along the 1st waypoint path [ r0 ]\r\n\t// sweeps along the circle as we rotate about the 'up'[ r1 ] axis in the direction if r2...\r\n\tm_turn_matrix[ X ] = m_circle_center - m_nav_pos;\r\n\tm_turn_matrix[ Z ] = m_circle_center - m_circle_arrival_pos;\r\n\tif ( !( m_turn_matrix[ X ].Length() && m_turn_matrix[ Z ].Length() ) )\r\n\t{\r\n\t\treturn TURN_METHOD_INSTANT_TURN;\r\n\t}\r\n\tm_turn_matrix[ X ].Normalize();\r\n\tm_turn_matrix[ Z ].Normalize();\r\n\r\n\t// while we have these two vectors, find the angle between them...\r\n\tfloat angCos = Mth::DotProduct( m_turn_matrix[ X ], m_turn_matrix[ Z ] );\r\n#ifdef __PLAT_NGC__\r\n\tfloat\tang = angCos;\r\n\tif ( ang > 1.0f ) ang = 1.0f;\r\n\tif ( ang < -1.0f ) ang = -1.0f;\r\n\tm_arc_ang = acosf( ang );  // angles given in radians!\r\n#else\r\n\tm_arc_ang = acosf( angCos );  // angles given in radians!\r\n#endif\t\t// __PLAT_NGC__\r\n\t\r\n\t// find the total circumference of the arc,\r\n\t// which is the circumference of the circle ( ang * radius )\r\n\t// multiplied by ang / ( 2 * pi ) [ the fraction of the circle we actually traverse... ]\r\n\tm_arc_dist = m_circle_radius * m_arc_ang;\r\n\t\r\n\t// continue setting up the matrix now...\r\n\tm_turn_matrix[ Y ] = Mth::CrossProduct( m_turn_matrix[ X ], m_turn_matrix[ Z ] );\r\n\tif ( !m_turn_matrix[ Y ].Length() )\r\n\t{\r\n\t\treturn TURN_METHOD_INSTANT_TURN;\r\n\t}\r\n\tm_turn_matrix[ Y ].Normalize();\r\n\tm_turn_matrix[ Z ] = Mth::CrossProduct( m_turn_matrix[ X ], m_turn_matrix[ Y ] );\r\n\tif ( !m_turn_matrix[ Z ].Length() )\r\n\t{\r\n\t\treturn TURN_METHOD_INSTANT_TURN;\r\n\t}\r\n\tm_turn_matrix[ Z ].Normalize();\r\n\t\r\n    // Phew!!!  Now we can rotate this matrix along r1 and get the position on\r\n\t// the circle by taking r0 multiplied by the circle radius and adding that to\r\n\t// the center of the circle... and r2 will be the direction the car is pointed!!\r\n\t   \r\n\t// now to find the position along the arc, just get the\r\n\t// current distance traveled along the arc, divide by\r\n\t// the total circumference of the arc, multiply by the\r\n\t// angle the arc traverses to get the angle currently\r\n\t// traversed...  by rotating our curve matrix along\r\n\t// y in this fashion, we can find the position on the\r\n\t// circle!\r\n\t\r\n\tm_dist_traveled = m_extra_dist;\r\n\tm_extra_dist = 0;\r\n\t\r\n//\tGfx::AddDebugLine( m_nav_pos, m_circle_center, MAKE_RGB( 255, 0, 0 ), MAKE_RGB( 255, 0, 0 ) );\r\n//\tGfx::AddDebugLine( m_circle_center, m_circle_arrival_pos, MAKE_RGB( 0, 0, 255 ), MAKE_RGB( 0, 255, 0 ) );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPathOb::UpdateNavPosAlongPath( void )\r\n{\t\r\n\tMth::Vector pointAlongPath;\r\n\t\r\n\tm_nav_pos = m_wp_pos_from;\r\n\tpointAlongPath = m_wp_pos_to - m_wp_pos_from;\r\n\tpointAlongPath *= ( m_dist_traveled / m_dist_to_wp );\r\n\tm_nav_pos += pointAlongPath;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPathOb::UpdateNavPosAlongCurve( float distTraveled )\r\n{\t\r\n\tfloat fractionOfTotal;\r\n\tfractionOfTotal = distTraveled / m_arc_dist;\r\n\r\n\tm_y_rot = m_arc_ang * fractionOfTotal;\r\n\tm_turn_matrix.RotateYLocal( m_y_rot );\r\n\r\n\tMth::Vector temp;\r\n\ttemp = m_turn_matrix[ Y ];\r\n\tif ( temp[ Y ] > 0.0f )\r\n\t{\r\n\t\tm_y_rot *= -1.0f;\r\n\t}\r\n\r\n\tm_nav_pos = m_turn_matrix[ X ] * -m_circle_radius;\r\n\tm_nav_pos += m_circle_center;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPathOb::AlignToPath( void )\r\n{   \r\n\tm_turn_matrix[ Z ] = m_wp_pos_to - m_nav_pos;\r\n\tm_turn_matrix[ Z ].Normalize();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// If the distance between the next two waypoints is less than\r\n// the turn dist, decrease the turn dist and shit (otherwise\r\n// the arrival pos will be on the line but PAST the two waypoints\r\n// rather than between them!\r\nbool CPathOb::SetUpTurnDist( void )\r\n{\t\r\n\tMth::Vector temp;\r\n\tfloat wpLength;\r\n\r\n\tif ( m_enter_turn_dist )\r\n\t{\r\n\t\tif ( !SkateScript::GetNumLinks( m_node_to ) )\r\n\t\t\treturn false;\r\n        SkateScript::GetPosition( SkateScript::GetLink( m_node_to, 0 ), &temp );\r\n\t\ttemp -= m_wp_pos_to;\r\n\t\t// Need to optimise?  Store this length instead of recalculating it\r\n\t\t// when getting next waypoint!\r\n\t\twpLength = temp.Length();\r\n\t\tif ( wpLength < m_enter_turn_dist )\r\n\t\t{\r\n\t\t\tm_current_turn_dist = wpLength / 2.0f;\r\n\t\t\ttemp = m_wp_pos_to - m_nav_pos;\r\n\t\t\tfloat distToCurrentWP = temp.Length();\r\n\t\t\tif ( m_current_turn_dist > distToCurrentWP )\r\n\t\t\t{\r\n\t\t\t\tm_current_turn_dist = distToCurrentWP;\r\n\t\t\t}\r\n\t\t\tm_pathob_flags |= PATHOBFLAG_LINEAR_INTERP;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tm_pathob_flags &= ~PATHOBFLAG_LINEAR_INTERP;\r\n\r\n\tm_current_turn_dist = m_enter_turn_dist;\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPathOb::NewPath( int nodeNum, const Mth::Vector &currentPos )\r\n{\r\n\tm_pathob_state = PATHOB_STATE_UNINITIALIZED;\r\n\tm_pathob_flags = 0;\r\n\tm_node_to = nodeNum;\r\n\tm_dist_traveled = m_extra_dist = 0;\r\n\tm_nav_pos = m_wp_pos_from = currentPos;\r\n\tSetUpPath();\r\n\t\r\n\twhile ( Mth::Distance( m_nav_pos, m_wp_pos_to ) < 1.0f )\r\n\t{\r\n\t\tif ( !GetNextWaypoint() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\r\n\tAlignToPath();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Set up the path according to m_node_from and m_node_to...\r\n// Do this after getting the next waypoint in a path, or when\r\n// beginning a new path.  m_node_from should indicate where we\r\n// are now, m_node_to should be the node index of where we're\r\n// going!\r\nvoid CPathOb::SetUpPath( void )\r\n{\t\r\n\t// get data out of waypoints...\r\n\tScript::CScriptStructure *pNode = SkateScript::GetNode( m_node_to );\r\n\tSkateScript::GetPosition( pNode, &m_wp_pos_to );\r\n\t\r\n\tif ( !SkateScript::GetNumLinks( m_node_to ) )\r\n\t{\r\n\t\t// the path will end on arrival to m_node_to:\r\n\t\tm_pathob_flags |= PATHOBFLAG_END_OF_PATH;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_pathob_flags &= ~PATHOBFLAG_END_OF_PATH;\r\n\t}\r\n\r\n//\tGfx::AddDebugLine( m_wp_pos_from, m_wp_pos_to, MAKE_RGB( 255, 0, 0 ), MAKE_RGB( 0, 0, 255 ) );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPathOb::DrawPath()\r\n{\r\n\tGfx::AddDebugLine( m_wp_pos_from, m_wp_pos_to, MAKE_RGB( 255, 0, 0 ), MAKE_RGB( 0, 0, 255 ) );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPathOb::GetNextWaypoint( void )\r\n{\r\n\t\r\n\tint numLinks;\r\n\tnumLinks = SkateScript::GetNumLinks( m_node_to );\r\n\tif ( !numLinks )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\tm_node_from = m_node_to;\r\n\tDbg_Assert( GetMotionComponentFromObject( mp_object ) );\r\n\tif ( GetMotionComponentFromObject(mp_object)->PickRandomWaypoint() )\r\n\t{\r\n\t\tm_node_to = SkateScript::GetLink( m_node_to, Mth::Rnd( numLinks ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_node_to = SkateScript::GetLink( m_node_to, 0 );\r\n\t}\r\n\tm_wp_pos_from = m_wp_pos_to;\r\n\t\r\n\tSetUpPath();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPathOb::SetHeading( Mth::Vector *p_heading )\r\n{\r\n\t// Gets the current heading:\t\r\n\t*p_heading = m_turn_matrix[ Z ];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nfloat CPathOb::GetDistToWaypoint( void )\r\n{\r\n\tswitch ( m_pathob_state )\r\n\t{\r\n\t\tcase PATHOB_STATE_UNINITIALIZED:\r\n\t\t\t//Dbg_Message( \"%f line %d\", HUGE_DISTANCE, __LINE__ );\t\t\r\n\t\t\treturn HUGE_DISTANCE;\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase PATHOB_STATE_FOLLOW_LINE:\r\n\t\t\t//Dbg_Message( \"%f line %d\", m_dist_to_wp - m_dist_traveled, __LINE__ );\t\t\r\n\t\t\treturn ( m_dist_to_wp - m_dist_traveled );\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase PATHOB_STATE_FOLLOW_CURVE:\r\n\t\t\tif ( m_dist_traveled < ( m_arc_dist / 2 ) )\r\n\t\t\t{\r\n\t\t\t\t//Dbg_Message( \"%f line %d\", ( m_arc_dist / 2 ) - m_dist_traveled, __LINE__ );\t\t\r\n\t\t\t\treturn ( ( m_arc_dist / 2 ) - m_dist_traveled );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMth::Vector temp = m_wp_pos_to - m_wp_pos_from;\r\n\t\t\t\t//Dbg_Message( \"%f line %d\", temp.Length(), __LINE__ );\t\t\r\n\t\t\t\treturn temp.Length();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase PATHOB_STATE_LINEAR_INTERP:\r\n\t\t\tif ( m_dist_traveled < m_dist_to_wp )\r\n\t\t\t{\r\n\t\t\t\t//Dbg_Message( \"%f line %d\", m_dist_to_wp - m_dist_traveled, __LINE__ );\t\t\r\n\t\t\t\treturn ( m_dist_to_wp - m_dist_traveled );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMth::Vector temp = m_wp_pos_to - m_wp_pos_from;\r\n\t\t\t\t//Dbg_Message( \"%f line %d\", temp.Length(), __LINE__ );\t\t\r\n\t\t\t\treturn temp.Length();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"unhandled pathob state\" ) );\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\treturn HUGE_DISTANCE;\r\n}\r\n\r\n#if FINDING_GLITCHES_IN_PATH_TRAVERSAL\r\n// this function tracks down glitches in the path traversal...\r\nvoid CPathOb::FindGlitch( void )\r\n{\t\r\n\tstatic float totalDist = 0;\r\n\tstatic int numEntries = 0;\r\n\tfloat thisDist = Distance( m_old_nav_pos, m_nav_pos );\r\n\ttotalDist += thisDist;\r\n\tnumEntries++;\r\n\tfloat averageDist = totalDist / numEntries;\r\n\tif ( numEntries == 100 )\r\n\t{\r\n\t\tnumEntries = 50;\r\n\t\ttotalDist /= 2;\r\n\t}\r\n\tif ( fabs( thisDist - averageDist ) > 4.0f )\r\n\t{\r\n\t\tGfx::AddDebugLine( m_nav_pos, m_old_nav_pos, MAKE_RGB( 255, 255, 255 ), MAKE_RGB( 255, 255, 255 ) );\r\n\t\tDbg_Message( \"off by %f dist %f state %d prev state %d\", thisDist - averageDist, thisDist, m_pathob_state, m_prev_pathob_state );\r\n\t}\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPathOb::PrepareTurn( void )\r\n{\t\r\n\tint retVal = SetUpTurningCircle();\r\n\tswitch ( retVal )\r\n\t{\r\n\t\tcase TURN_METHOD_LINEAR_INTERP:\r\n\t\t{\r\n\t\t\t// store the current pos in circle center:\r\n\t\t\t// the angle is too wide (too close to PI radians)...\r\n\t\t\t// just move along the two lines and gradually turn and shit like that...\r\n\t\t\t\r\n\t\t\tm_circle_center = m_nav_pos;\r\n\t\t\tMth::Vector temp = m_nav_pos - m_wp_pos_from;\r\n\t\t\tm_dist_to_wp = temp.Length();\r\n\t\t\tm_dist_traveled = m_extra_dist;\r\n\t\t\tm_pathob_state = PATHOB_STATE_LINEAR_INTERP;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase TURN_METHOD_CURVE:\r\n\t\t\tm_pathob_state = PATHOB_STATE_FOLLOW_CURVE;\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase TURN_METHOD_INSTANT_TURN:\r\n\t\t\t// just hit the waypoint, and set up the path for the next one:\r\n\t\t\tDbg_Assert( GetMotionComponentFromObject( mp_object ) );\r\n\t\t\tGetMotionComponentFromObject( mp_object )->HitWaypoint( m_node_from );\r\n\t\t\tm_pathob_flags &= ~PATHOBFLAG_SEND_HIT_WAYPOINT_MSG;\r\n\t\t\tm_dist_traveled = m_dist_to_wp - m_dist_traveled;\r\n\t\t\t// now move along the line...\r\n\t\t\tSetUpNavPointLineMotion();\r\n\t\t\tUpdateNavPosAlongPath();\r\n\t\t\tm_pathob_state = PATHOB_STATE_FOLLOW_LINE;\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0,( \"Unknown turn method %d\", retVal ));\r\n\t\t\tbreak;\r\n\t}   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Function TraversePath()\r\n// This function is called by the moving object each frame, and causes the\r\n// pathob to move a little further down the path (by the projection of the moving\r\n// object's forward vector along the line or curve in the path).\r\n// Returns 'TRUE' when the end of the path is reached...\r\n//bool CPathOb::TraversePath( bool is_being_skitched, const float dist, Mth::Vector *pHeading )\r\nbool CPathOb::TraversePath( const float dist, Mth::Vector *pHeading )\r\n{\r\n\t//if (is_being_skitched) printf(\"#\");\t\r\n\t\r\n\tif ( m_pathob_state == PATHOB_STATE_IDLE )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n#if FINDING_GLITCHES_IN_PATH_TRAVERSAL\r\n\tm_old_nav_pos = m_nav_pos;\r\n#endif\r\n\t\r\n\tfloat distTraveled;\r\n\tif ( pHeading )\r\n\t{\r\n\t\tfloat cosHeadingToNavPath = Mth::DotProduct( *pHeading, m_turn_matrix[ Z ] );\r\n\t\tif ( !cosHeadingToNavPath )\r\n\t\t{\r\n\t\t\t//if (is_being_skitched) printf(\"a\");\t\r\n\t\t\t// can't assert on this case... car could be pointing at the sky temporarily!\r\n\t\t\tdistTraveled = 1;\r\n\t\t}\r\n\t\telse\r\n\t\t{\t\t\r\n\t\t\t//if (is_being_skitched) printf(\"b\");\t\r\n\t\t\tdistTraveled = dist * cosHeadingToNavPath;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//if (is_being_skitched) printf(\"c\");\t\r\n\t\tdistTraveled = dist;\r\n\t}\t\r\n\t\r\n#if FINDING_GLITCHES_IN_PATH_TRAVERSAL\r\n\tm_prev_pathob_state = m_pathob_state;\r\n#endif\r\n\t\t\r\n\tswitch ( m_pathob_state )\r\n\t{\r\n\t\tcase PATHOB_STATE_UNINITIALIZED:\r\n\t\t\t//if (is_being_skitched) printf(\"d\");\t\r\n\t\t\tSetUpNavPointLineMotion();\r\n\t\t\tm_y_rot = 0;\r\n\t\t\tm_pathob_state = PATHOB_STATE_FOLLOW_LINE;\r\n\t\t\t// intentional fall thru...\r\n\t\tcase PATHOB_STATE_FOLLOW_LINE:\r\n\t\t\t//if (is_being_skitched) printf(\"e\");\t\r\n\t\t\t// will convert this to GetDistTraveled(), once the\r\n\t\t\t// nav point stuff is disconnected from the car stuff\r\n\t\t\tm_dist_traveled += distTraveled;\r\n\t\t\t\r\n            if ( m_pathob_flags & PATHOBFLAG_END_OF_PATH )\r\n\t\t\t{\r\n\t\t\t\t// see if we're at the end of the path:\r\n\t\t\t\tif ( m_dist_traveled >= m_dist_to_wp )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_node_from = m_node_to;\r\n\t\t\t\t\tm_nav_pos = m_wp_pos_from = m_wp_pos_to;\r\n\t\t\t\t\tm_pathob_state = PATHOB_STATE_IDLE;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( m_dist_traveled >= ( m_dist_to_wp - m_current_turn_dist ) )\r\n\t\t\t{\r\n\t\t\t\t// we've reached the waypoint... save the extra!\r\n\t\t\t\t//m_extra_dist = m_dist_traveled - ( m_dist_to_wp - m_current_turn_dist );\r\n\t\t\t\tif ( !m_current_turn_dist )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_nav_pos = m_wp_pos_to;\r\n\t\t\t\t\tDbg_Assert( GetMotionComponentFromObject( mp_object ) );\r\n\t\t\t\t\tGetMotionComponentFromObject( mp_object )->HitWaypoint( m_node_to );\r\n\t\t\t\t\tif ( !GetNextWaypoint() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_MsgAssert( 0,( \"Tell Matt that the code got here, and that he's an idiot but you still love him.\" ));\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_pathob_state = PATHOB_STATE_UNINITIALIZED;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n                // get the circle along the turn, using the turn radius...\r\n\t\t\t\t// first, set the nav pos equal to the first point on the circle\r\n\t\t\t\t// ( the current position... )\r\n\t\t\t\t//m_dist_traveled -= m_extra_dist;\r\n\t\t\t\tUpdateNavPosAlongPath();\r\n\t\t\t\t\r\n\t\t\t\t// then get the next waypoint, which will allow us to figure out\r\n\t\t\t\t// the second point along the circle...\r\n\t\t\t\tGetNextWaypoint();\r\n\t\t\t\tm_pathob_flags |= PATHOBFLAG_SEND_HIT_WAYPOINT_MSG;\r\n\t\t\t\tPrepareTurn();\r\n\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tUpdateNavPosAlongPath();\r\n            break;\r\n\r\n\t\tcase PATHOB_STATE_FOLLOW_CURVE:\r\n\t\t\t// moving around the circumference of the circle now!!\r\n\t\t\t{\r\n\t\t\t\t//if (is_being_skitched) printf(\"f\");\t\r\n\t\t\t\t//Mth::Vector oldpos=m_nav_pos;\r\n\t\t\t\t\r\n\t\t\t\t// will convert this to GetDistTraveled(), once the\r\n\t\t\t\t// nav point stuff is disconnected from the car stuff\r\n\t\t\t\tm_dist_traveled += distTraveled;\r\n\t\t\t\t//if (is_being_skitched) printf(\"[dt=%.2f, %.2f]\",distTraveled,m_dist_traveled);\r\n\t\t\t\t\r\n\t\t\t\tif ( ( m_pathob_flags & PATHOBFLAG_SEND_HIT_WAYPOINT_MSG ) &&\r\n\t\t\t\t\t( m_dist_traveled >= ( m_arc_dist / 2.0f ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_pathob_flags &= ~PATHOBFLAG_SEND_HIT_WAYPOINT_MSG;\r\n\t\t\t\t\tDbg_Assert( GetMotionComponentFromObject( mp_object ) );\r\n\t\t\t\t\tGetMotionComponentFromObject( mp_object )->HitWaypoint( m_node_from );\r\n\t\t\t\t}\r\n\t\t\t\tif ( m_dist_traveled > m_arc_dist )\r\n\t\t\t\t{\r\n\t\t\t\t\t\r\n\t\t\t\t\tm_extra_dist = m_dist_traveled - m_arc_dist;\r\n\t\t\t\t\t//if (is_being_skitched) printf(\"[mdt=%.2f][ad=%.2f][ed=%.2f]\",m_dist_traveled,m_arc_dist,m_extra_dist);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Calculates m_nav_pos. Ignores m_dist_traveled and m_extra_dist\r\n\t\t\t\t\tUpdateNavPosAlongCurve( distTraveled - m_extra_dist );\r\n\t\t\t\t\t//if (is_being_skitched) printf(\"[cpd=%.2f]\",Mth::Distance(m_nav_pos,oldpos));\r\n\t\t\t\t\t\r\n\t\t\t\t\t// now move along the line...\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Ken: Skitch Glitch fix\r\n\t\t\t\t\t// If this is not zeroed there is an increase in speed for one frame when\r\n\t\t\t\t\t// going from this state to PATHOB_STATE_FOLLOW_LINE\r\n\t\t\t\t\t// Ie, the car moves too far in this transition.\r\n\t\t\t\t\tm_extra_dist=0.0f;\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Recalculates m_dist_traveled using m_nav_pos, then adds m_extra_dist, \r\n\t\t\t\t\t// then zeros m_extra_dist\r\n\t\t\t\t\tSetUpNavPointLineMotion();\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Calculates m_nav_pos using m_dist_traveled\r\n\t\t\t\t\tUpdateNavPosAlongPath();\r\n\t\t\t\t\t\r\n\t\t\t\t\tm_y_rot = 0;\r\n\t\t\t\t\tm_pathob_state = PATHOB_STATE_FOLLOW_LINE;\r\n\t\t\t\t\t\r\n\t\t\t\t\t//if (is_being_skitched) printf(\"[%.2f]\",Mth::Distance(oldpos,m_nav_pos));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// find the angular rotation (angle changes relative to\r\n\t\t\t\t// total arc angle as the distance changes relative to\r\n\t\t\t\t// the total distance...\r\n\t\t\t\t//if (is_being_skitched) printf(\"{dt=%.2f r=%.2f ad=%.2f ang=%.2f}\",distTraveled,m_circle_radius,m_arc_dist,m_arc_ang);\r\n\t\t\t\tUpdateNavPosAlongCurve( distTraveled );\r\n\t\t\t\t//if (is_being_skitched) printf(\"[%.2f]\",Mth::Distance(oldpos,m_nav_pos));\r\n\t\t\t\t\r\n\t\t\t\t//temp debuggery:\r\n\t\t\t\t/*{\r\n\t\t\t\t\tMth::Vector tempVect;\r\n\t\t\t\t\ttempVect = m_turn_matrix[ 0 ] * 150;\r\n\t\t\t\t\ttempVect += m_circle_center;\r\n\t\t\t\t\tGfx::AddDebugLine( tempVect, m_circle_center, MAKE_RGB( 255, 0, 0 ), MAKE_RGB( 0, 0, 0 ) );\r\n\t\t\t\t\ttempVect = m_turn_matrix[ 1 ] * 150;\r\n\t\t\t\t\ttempVect += m_circle_center;\r\n\t\t\t\t\tGfx::AddDebugLine( tempVect, m_circle_center, MAKE_RGB( 0, 255, 0 ), MAKE_RGB( 0, 0, 0 ) );\r\n\t\t\t\t\ttempVect = m_turn_matrix[ 2 ] * 150;\r\n\t\t\t\t\ttempVect += m_circle_center;\r\n\t\t\t\t\tGfx::AddDebugLine( tempVect, m_circle_center, MAKE_RGB( 0, 0, 255 ), MAKE_RGB( 0, 0, 0 ) );\r\n\t\t\t\t}*/\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase PATHOB_STATE_LINEAR_INTERP:\r\n\t\t{\r\n\t\t\t//if (is_being_skitched) printf(\"g\");\t\r\n\t\t\t// very minimal turn...\r\n\t\t\t// move along the current line until we get to the next line...\r\n\t\t\t// gradually change the heading.\r\n\t\t\tm_dist_traveled += distTraveled;\r\n\t\t\tfloat fracTraveled = m_dist_traveled / m_dist_to_wp;\r\n\t\t\t\r\n\t\t\tif ( m_dist_traveled < m_dist_to_wp )\r\n\t\t\t{\r\n\t\t\t\tm_nav_pos = m_circle_center;\r\n\t\t\t\tMth::Vector alongPath = m_wp_pos_from - m_circle_center;\r\n\t\t\t\talongPath *= fracTraveled;\r\n\t\t\t\tm_nav_pos += alongPath;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_nav_pos = m_wp_pos_from;\r\n\t\t\t\tMth::Vector alongPath = m_circle_arrival_pos - m_wp_pos_from;\r\n\t\t\t\talongPath *= ( fracTraveled - 1 ) / 1;\r\n\t\t\t\tm_nav_pos += alongPath;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// set the heading, just a weighted average of the two headings...\r\n\t\t\tMth::Vector heading1, heading2;\r\n\t\t\theading1 = m_wp_pos_from - m_circle_center;\r\n\t\t\theading2 = m_circle_arrival_pos - m_wp_pos_from;\r\n\t\t\t// fraction traveled over both lines...\r\n\t\t\tfracTraveled /= 2.0f;\r\n\t\t\tif ( ( fracTraveled ) >= 0.5f && ( m_pathob_flags & PATHOBFLAG_SEND_HIT_WAYPOINT_MSG ) )\r\n\t\t\t{\r\n\t\t\t\tm_pathob_flags &= ~PATHOBFLAG_SEND_HIT_WAYPOINT_MSG;\r\n\t\t\t\tDbg_Assert( GetMotionComponentFromObject( mp_object ) );\r\n\t\t\t\tGetMotionComponentFromObject( mp_object )->HitWaypoint( m_node_from );\r\n\t\t\t}\r\n\t\t\tif ( fracTraveled >= 1.0f )\r\n\t\t\t{\r\n\t\t\t\t// set all the variables back so we can traverse the next path:\r\n\t\t\t\tfracTraveled = 1;\r\n\t\t\t\t\r\n\t\t\t\t// Ken: Skitch Glitch fix\r\n\t\t\t\t//m_extra_dist = m_dist_traveled - ( 2 * m_dist_to_wp );\r\n\t\t\t\tm_extra_dist=0.0f;\r\n\t\t\t\t\r\n\t\t\t\tSetUpNavPointLineMotion();\r\n\t\t\t\t//Dbg_Message( \"hmm %f\\n\", m_dist_traveled );\r\n\t\t\t\tm_pathob_state = PATHOB_STATE_FOLLOW_LINE;\r\n\t\t\t\t//if (is_being_skitched)\r\n\t\t\t\t//{\r\n\t\t\t\t//\tprintf(\"Going from interp back to line\\n\");\t\r\n\t\t\t\t//}\t\r\n\t\t\t}\r\n\t\t\tm_turn_matrix[ Z ] = ( heading1 * ( 1 - fracTraveled ) );\r\n\t\t\t// by the time we get to the arrival pos, the heading will be along the next line!\r\n\t\t\tm_turn_matrix[ Z ] += ( heading2 * ( fracTraveled ) );\r\n\t\t\tm_turn_matrix[ Z ].Normalize();\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase PATHOB_STATE_IDLE:\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0,( \"Unknown substate!\" ));\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n#if FINDING_GLITCHES_IN_PATH_TRAVERSAL\r\n\tFindGlitch();\r\n#endif\r\n\t\r\n#if DRAW_COLOR_CODED_NAV_PATH\r\n\tint rgb;\r\n\tswitch ( m_pathob_state )\r\n\t{\r\n\t\tcase PATHOB_STATE_LINEAR_INTERP:\r\n\t\t\trgb = MAKE_RGB( 255, 0, 0 );\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase PATHOB_STATE_FOLLOW_CURVE:\r\n\t\t\trgb = MAKE_RGB( 0, 255, 0 );\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase PATHOB_STATE_FOLLOW_LINE:\r\n\t\t\trgb = MAKE_RGB( 0, 0, 255 );\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tcase PATHOB_STATE_UNINITIALIZED:\r\n\t\t\trgb = 255;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\trgb = MAKE_RGB( 255, 255, 255 );\t\t\t\t\t  \r\n\t}\r\n\tm_old_nav_pos[ Y ] += 200;\r\n\tm_nav_pos[ Y ] += 200;\r\n\tGfx::AddDebugLine( m_old_nav_pos, m_nav_pos, rgb, rgb );\r\n\tm_old_nav_pos[ Y ] -= 200;\r\n\tm_nav_pos[ Y ] -= 200;\r\n#endif\r\n\r\n\t//if (is_being_skitched) printf(\"#\");\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPathOb::GetDebugInfo( Script::CStruct* p_info )\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\tDbg_MsgAssert( p_info, ( \"NULL p_info passed to CPathOb::GetDebugInfo\" ) );\r\n\r\n\tp_info->AddVector( \"m_nav_pos\", m_nav_pos );\r\n\t\r\n\t// nodes\r\n\tp_info->AddInteger( \"m_node_from\", m_node_from );\r\n\tp_info->AddInteger( \"m_node_to\", m_node_to );\r\n\tp_info->AddInteger( \"m_node_next\", m_node_next );\r\n\tp_info->AddStructure( \"m_node_from\", SkateScript::GetNode( m_node_from ) );\r\n\tp_info->AddStructure( \"m_node_to\", SkateScript::GetNode( m_node_to ) );\r\n\tp_info->AddStructure( \"m_node_next\", SkateScript::GetNode( m_node_next ) );\r\n\t\r\n\t// waypoint positions:\r\n\tp_info->AddVector( \"m_wp_pos_from\", m_wp_pos_from );\r\n\tp_info->AddVector( \"m_wp_pos_to\", m_wp_pos_to );\r\n\tp_info->AddVector( \"m_wp_pos_next\", m_wp_pos_next );\r\n\r\n    // DESIGNER SETTABLE, through script file:\r\n    p_info->AddFloat( \"m_enter_turn_dist\", m_enter_turn_dist );\r\n\tp_info->AddFloat( \"m_min_turn_circle_radius\", m_min_turn_circle_radius );\r\n\t\r\n\t// float\t\t\t\tm_current_turn_dist;\r\n\t\r\n\t// navigational info (save runtime calculations...)\r\n\t// float\t\t\t\tm_dist_to_wp;\r\n\t// float\t\t\t\tm_dist_traveled;\r\n\t\r\n\t// could be private:\r\n\t// int\t\t\t\t\tm_pathob_flags;\r\n\r\n\t// float\t\t\t\tm_extra_dist;\r\n\r\n\t// for navigating around corners:\r\n\t// Mth::Vector\t\t\tm_circle_center;\r\n\t// Mth::Vector\t\t\tm_circle_arrival_pos; // do we really need this? no.  so fuck you!\r\n\t// use member m_turn_matrix from object structure...\r\n//\tMth::Matrix\t\t\tm_arc_matrix;\t// Y axis is rotation axis, X is along radius\r\n\t// float\t\t\t\tm_arc_ang;\t\t// total sweep along the radius....\r\n\t// float\t\t\t\tm_arc_dist;\t\t// total distance along the arc...\r\n\t// float\t\t\t\tm_circle_radius;\r\n\r\n\tuint32 pathob_state_checksum = 0;\r\n\tswitch ( m_pathob_state )\r\n\t{\r\n\tcase 0:\r\n\t\tpathob_state_checksum = CRCD( 0x16d6676f, \"PATHOB_STATE_UNINITIALIZED\" );\r\n\t\tbreak;\r\n\tcase 1:\r\n\t\tpathob_state_checksum = CRCD( 0x55b5bee1, \"PATHOB_STATE_FOLLOW_LINE\" );\r\n\t\tbreak;\r\n\tcase 2:\r\n\t\tpathob_state_checksum = CRCD( 0x6cc96f7, \"PATHOB_STATE_FOLLOW_CURVE\" );\r\n\t\tbreak;\r\n\tcase 3:\r\n\t\tpathob_state_checksum = CRCD( 0xac01db8, \"PATHOB_STATE_LINEAR_INTERP\" );\r\n\t\tbreak;\r\n\tcase 4:\r\n\t\tpathob_state_checksum = CRCD( 0x5bc8724c, \"PATHOB_STATE_IDLE\" );\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tDbg_MsgAssert( 0, ( \"CPathOb::GetDebugInfo got bad m_pathob_state.  Was the enum changed?\" ) );\r\n\t\tbreak;\r\n\t}\r\n\tp_info->AddChecksum( \"m_pathob_state\", pathob_state_checksum );\r\n#endif\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/PathOb.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       PathOb.h\r\n//* OWNER:          Matt Duncan\r\n//* CREATION DATE:  11/2/2000\r\n//****************************************************************************\r\n\r\n#ifndef __OBJECTS_PATHOB_H\r\n#define __OBJECTS_PATHOB_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/math.h>\r\n\r\n#include <gel/scripting/struct.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// debugging options:\r\n#define FINDING_GLITCHES_IN_PATH_TRAVERSAL\t0\r\n#define DRAW_COLOR_CODED_NAV_PATH\t\t\t0\r\n\r\n#define HUGE_DISTANCE\t\tFEET_TO_INCHES( 666 * 666 )\r\n\r\nnamespace Obj\r\n{\r\n\r\nclass CCompositeObject;\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t\t\t\t\t\t \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Manager;\r\n\r\nclass CPathOb : public Spt::Class\r\n{\r\n\t\r\npublic:\r\n\tCPathOb( CCompositeObject* pObj );\r\n\tvirtual ~CPathOb();\r\n\r\n\tvirtual\tvoid\t\tGetDebugInfo( Script::CStruct* p_info );\r\n\r\n\tMth::Vector\t\t\tm_nav_pos;\t\t//car pos is set by finding the ground under the nav pos\r\n\tCCompositeObject* \tmp_object;\t\t// owner\r\n\r\n\t// for the curve from one path to the next...\r\n\tMth::Matrix\t\t\tm_turn_matrix;\t// Y axis is rotation axis, X is along radius\r\n\t\r\n\t// waypoint indices:\r\n\tint\t\t\t\t\tm_node_from;\r\n\tint\t\t\t\t\tm_node_to;\r\n\tint\t\t\t\t\tm_node_next;\r\n\t\r\n\t// waypoint positions:\r\n\tMth::Vector\t\t\tm_wp_pos_from;\r\n\tMth::Vector\t\t\tm_wp_pos_to;\r\n\tMth::Vector\t\t\tm_wp_pos_next;\r\n\r\n    // DESIGNER SETTABLE, through script file:\r\n    float\t\t\t\tm_enter_turn_dist;\t\t\t\t// in inches...\r\n\tfloat\t\t\t\tm_min_turn_circle_radius;\t// in inches\r\n    // end DESIGNER SETTABLE variables...\r\n\t\r\n\t// varies depending on the distance between waypoints:\r\n\tfloat\t\t\t\tm_current_turn_dist;\r\n\t\r\n\t// navigational info (save runtime calculations...)\r\n\tfloat\t\t\t\tm_dist_to_wp;\r\n\tfloat\t\t\t\tm_dist_traveled;\r\n\t\r\n\t// could be private:\r\n\tint\t\t\t\t\tm_pathob_flags;\r\n\r\n\tfloat\t\t\t\tm_extra_dist;\r\n\r\n\t// for navigating around corners:\r\n\tMth::Vector\t\t\tm_circle_center;\r\n\tMth::Vector\t\t\tm_circle_arrival_pos; // do we really need this? no.  so fuck you!\r\n\t// use member m_turn_matrix from object structure...\r\n//\tMth::Matrix\t\t\tm_arc_matrix;\t// Y axis is rotation axis, X is along radius\r\n\tfloat\t\t\t\tm_arc_ang;\t\t// total sweep along the radius....\r\n\tfloat\t\t\t\tm_arc_dist;\t\t// total distance along the arc...\r\n\tfloat\t\t\t\tm_circle_radius;\r\n\r\n\tint\t\t\t\t\tm_pathob_state;\r\n \r\n\tbool\t\t\t\tBusy( void );\r\n\tfloat\t\t\t\tGetDistToWaypoint( void );\r\n\t\t\t   \r\n\t// Returns 'true' when path has been traversed (end of path!)\r\n    bool\t\t\t\tTraversePath( const float deltaDist, Mth::Vector *pHeading = NULL );\r\n\t\r\n\tvoid\t\t\t\tSetHeading( Mth::Vector *p_heading );\r\n\r\n\tbool\t\t\t\tGetNextWaypoint( void );\r\n\r\n\t// call when beginning a new path:\r\n\tvoid \t\t\t\tInitPath( int nodeNum );\r\n\tvoid\t\t\t\tNewPath( int nodeNum, const Mth::Vector &currentPos );\r\n\r\n\tfloat\t\t\t\tm_y_rot;\r\n\tvoid\t\t\t\tDrawPath( void );\r\n\r\nprivate:\r\n\r\n\t// Set up the path according to m_node_from and m_node_to...\r\n\t// Do this after getting the next waypoint in a path, or when\r\n\t// beginning a new path.  m_node_from should indicate where we\r\n\t// are now, m_node_to should be the node index of where we're\r\n\t// going!\r\n\tvoid\t\t\t\tSetUpPath( void );\r\n\r\n\t// set heading vector to correspond to new path...\r\n\tvoid\t\t\t\tAlignToPath( void );\r\n\r\n\tbool \t\t\t\tSetUpNavPointLineMotion( );\r\n\tint \t\t\t\tSetUpTurningCircle( void );\r\n\tvoid\t\t\t\tPrepareTurn( void );\r\n\tbool\t\t\t\tSetUpTurnDist( void );\r\n\r\n\tvoid\t\t\t\tUpdateNavPosAlongPath( void );\r\n\tvoid\t\t\t\tUpdateNavPosAlongCurve( float distTraveled );\r\n\r\n#if FINDING_GLITCHES_IN_PATH_TRAVERSAL\r\n\t// can remove if no longer debugging:\r\n\tint\t\t\t\t\tm_prev_pathob_state;\r\n\t// nav pos moves smoothly between the waypoints or along the curve connecting paths...\r\n\tMth::Vector \t\tm_old_nav_pos;\t//for debuggery...\r\n\t// debugging function:\r\n\tvoid\t\t\t\tFindGlitch( void );\r\n#endif\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_PATHOB_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/PlayerProfileManager.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       PlayerProfileManager.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  4/29/2002\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/objects/playerprofilemanager.h>\r\n\r\n#include <sk/objects/skaterprofile.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\n#include <gfx/facetexture.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n// Selects which one is the current player profile\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPlayerProfileManager::CPlayerProfileManager() : m_Profiles(vMAX_PROFILES)\r\n{\r\n\tm_CurrentProfileIndex = 0;\r\n\r\n\tfor ( int i = 0; i < vMAX_PLAYERS; i++ )\r\n\t{\r\n\t\tmp_CurrentProfile[i] = NULL;\r\n\t}\r\n\r\n\tm_LockCurrentSkaterProfileIndex = false;\r\n\r\n\tm_TemporaryProfileCount = 0;\r\n\r\n#if 0\r\n\r\n/*\r\nappearance_custom_skater_worst_case_net_packet = \r\n{\r\n    body = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    board = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    skater_m_head = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    skater_m_torso = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    skater_m_legs = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    skater_m_hair = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    skater_m_backpack = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    skater_m_jaw = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    skater_m_socks = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    sleeves = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    kneepads = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    elbowpads = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    shoes = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    sleeves = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    front_logo = { desc_id=#\"Wrist Bands\" uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n    back_logo = { desc_id=#\"Wrist Bands\" uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n    hat = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    helmet = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n    accessories = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n\that_logo = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n\thelmet_logo = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 use_default_hsv = 1}\r\n\r\n\t// pos items...\r\n\tgriptape = { desc_id=#\"Wrist Bands\" }\r\n\tdeck_graphic = { desc_id=#\"Wrist Bands\" }\r\n\tcad_graphic = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\tdeck_layer1 = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\tdeck_layer2 = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\tdeck_layer3 = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\tdeck_layer4 = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\tdeck_layer5 = { desc_id=#\"Wrist Bands\" h=350 s=99 v=98 uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\t\t\r\n\thead_tattoo = { desc_id=#\"Wrist Bands\" uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\tleft_bicep_tattoo = { desc_id=#\"Wrist Bands\" uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\tleft_forearm_tattoo = { desc_id=#\"Wrist Bands\" uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\tright_bicep_tattoo = { desc_id=#\"Wrist Bands\" uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\tright_forearm_tattoo = { desc_id=#\"Wrist Bands\" uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\tchest_tattoo = { desc_id=#\"Wrist Bands\" uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\tback_tattoo = { desc_id=#\"Wrist Bands\" uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\tleft_leg_tattoo = { desc_id=#\"Wrist Bands\" uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\tright_leg_tattoo = { desc_id=#\"Wrist Bands\" uv_u=199.999999 uv_v=199.999999 uv_scale=199.999999 uv_rot=355.000000 use_default_uv = 1}\r\n\r\n\theadtop_bone_group = { x=160 y=160 z=160 use_default_scale = 1}\r\n\tJaw_bone_group = { x=160 y=160 z=160 use_default_scale = 1}\r\n\tnose_bone_group = { x=160 y=160 z=160 use_default_scale = 1}\r\n\thead_bone_group = { x=160 y=160 z=160 use_default_scale = 1}\r\n\ttorso_bone_group = { x=160 y=160 z=160 use_default_scale = 1}\r\n\tstomach_bone_group = { x=160 y=160 z=160 use_default_scale = 1}\r\n\tupper_arm_bone_group = { x=160 y=160 z=160 use_default_scale = 1}\r\n\tlower_arm_bone_group = { x=160 y=160 z=160 use_default_scale = 1}\r\n\thands_bone_group = { x=160 y=160 z=160 use_default_scale = 1}\r\n\tupper_leg_bone_group = { x=160 y=160 z=160 use_default_scale = 1}\r\n\tlower_leg_bone_group = { x=160 y=160 z=160 use_default_scale = 1}\r\n\tfeet_bone_group = { x=160 y=160 z=160 use_default_scale = 1}\r\n\tboard_bone_group = { x=160 y=160 z=160 use_default_scale = 1}\r\n\tobject_scaling = { x=160 y=160 z=160 use_default_scale = 1}\r\n}\r\n*/\r\n\r\n\tuint8 tBuf[vMAX_APPEARANCE_BUFFER_SIZE];\r\n\tScript::CStruct* pTempStructure = Script::GetStructure(\"appearance_custom_skater_worst_case_net_packet\",Script::ASSERT);\r\n\tObj::CSkaterProfile* pPlayerProfile = new Obj::CSkaterProfile;\r\n\tpPlayerProfile->GetAppearance()->Load( pTempStructure, false );\t\r\n\tuint32 size = pPlayerProfile->WriteToBuffer(tBuf, vMAX_APPEARANCE_BUFFER_SIZE);\r\n\tDbg_Assert( size < vMAX_PRACTICAL_APPEARANCE_DATA_SIZE );\r\n\tDbg_Message(\"*********** Worst case model appearance data size = %d bytes\\n\", size);\r\n\tdelete pTempStructure;\r\n\tdelete pPlayerProfile;\r\n\tDbg_Assert( 0 );\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPlayerProfileManager::Init()\r\n{\r\n\tint dummy;\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\t// TODO:  this is an optimization to go down from 4-byte\r\n\t// checksums to a 1- or 2-byte index into a checksum table.\r\n\t// This is probably not a very good system, because it's not\r\n\t// scalable to downloadable content\r\n//\tCas::InitDescChecksumTable();\r\n\t\r\n\t// initialize the pro skater profiles here\r\n\tScript::RunScript( \"init_pro_skaters\" );\r\n\r\n\t// the number of profiles must exceed the number of players\r\n\tDbg_MsgAssert( m_Profiles.getSize() >= vMAX_PLAYERS, ( \"Not enough profiles (must be greater than maxplayers)\" ) );\r\n\r\n\t// profile #0 points to an actual profile\r\n\tmp_CurrentProfile[0] = m_Profiles.GetItemByIndex( 0, &dummy );\r\n\r\n\t// the others point to temp copies...  this is so that player\r\n\t// #1 through N can edit their appearances without affecting\r\n\t// the source profile\r\n\tfor ( int i = 1; i < vMAX_PLAYERS; i++ )\r\n\t{\r\n\t\tmp_CurrentProfile[i] = new CSkaterProfile;\r\n\t\t*mp_CurrentProfile[i] = *m_Profiles.GetItemByIndex( i, &dummy );\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPlayerProfileManager::~CPlayerProfileManager()\r\n{\r\n\tuint32 tableSize = m_Profiles.getSize( );\r\n\tfor ( uint32 i = 0; i < tableSize; i++ )\r\n\t{\r\n\t\tint key;\r\n\t\tCSkaterProfile* pProfile = m_Profiles.GetItemByIndex( 0, &key );\r\n\t\tdelete pProfile;\r\n\t\tm_Profiles.FlushItem( key );\r\n\t}\r\n\r\n\tfor ( int i = 1; i < vMAX_PLAYERS; i++ )\r\n\t{\r\n\t\tDbg_Assert( mp_CurrentProfile[i] );\r\n\t\tdelete mp_CurrentProfile[i];\r\n\t\tmp_CurrentProfile[i] = NULL;\r\n\t}\r\n\r\n\tfor ( int i = 0; i < m_TemporaryProfileCount; i++ )\r\n\t{\r\n\t\tDbg_Assert( mp_TemporaryProfiles[i] );\r\n\t\tdelete mp_TemporaryProfiles[i];\r\n\t\tmp_TemporaryProfiles[i] = NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CPlayerProfileManager::GetNumProfileTemplates( void )\r\n{\r\n\treturn m_Profiles.getSize();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CPlayerProfileManager::GetProfileTemplateChecksum( int i )\r\n{\r\n\tDbg_MsgAssert( i >= 0 && i < m_Profiles.getSize(),( \"Profile %d out of range (0-%d)\", i, m_Profiles.getSize()-1 ));\r\n\r\n\tint key;\r\n\tm_Profiles.GetItemByIndex( i, &key );\r\n\treturn (uint32)key;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterProfile*\t\tCPlayerProfileManager::GetProfileTemplateByIndex( int i)\r\n{\r\n\tDbg_MsgAssert( i >= 0 && i < m_Profiles.getSize(),( \"Profile %d out of range (0-%d)\", i, m_Profiles.getSize()-1 ));\r\n\r\n\treturn m_Profiles.GetItemByIndex( i );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPlayerProfileManager::SyncPlayer2()\r\n{\r\n\t// GJ:  need to push the skaterinfoheap or else the custom skater's face\r\n\t// texture may end up on the bottom up heap (you'd only notice that\r\n\t// if you went into 2 player mode and both characters were already\r\n\t// custom skaters, because pressing LEFT to switch from a pro skater\r\n\t// to a custom skater would automatically push the skater info heap)\r\n\t// this whole process is probably worth looking at next time because\r\n\t// it's kind of kludgy, but it's too risky to fix in any other\r\n\t// way right now...\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\tint profile_index = 1;\r\n\r\n\t// get the currently selected skater for player #1\r\n\tuint32 checksum = mp_CurrentProfile[profile_index]->GetSkaterNameChecksum();\r\n\r\n\t// sync up the profile from the root profile\r\n\t*mp_CurrentProfile[profile_index] = *m_Profiles.GetItem( checksum );\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPlayerProfileManager::SetCurrentProfileIndex(int i)\r\n{\r\n\tif ( m_LockCurrentSkaterProfileIndex )\r\n\t{\r\n\t\t// we lock it so that we make sure no one accesses\r\n\t\t// this during network games or splitscreen games,\r\n\t\t// which aren't guaranteed to return the correct\r\n\t\t// value\r\n\t\tDbg_MsgAssert( 0, ( \"Can't access current profile index! Are you playing a network game? (See Gary)\" ) );\r\n\t}\r\n\r\n\tDbg_MsgAssert( i >= 0 && i < vMAX_PLAYERS,( \"Profile %d out of range (0-%d)\", i, vMAX_PLAYERS-1 ));\r\n\t\r\n\tm_CurrentProfileIndex = i;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CPlayerProfileManager::GetCurrentProfileIndex()\r\n{\r\n\tif ( m_LockCurrentSkaterProfileIndex )\r\n\t{\r\n\t\t// we lock it so that we make sure no one accesses\r\n\t\t// this during network games or splitscreen games,\r\n\t\t// which aren't guaranteed to return the correct\r\n\t\t// value\r\n\t\tDbg_MsgAssert( 0, ( \"Can't access current profile index! Are you playing a network game? (See Gary)\" ) );\r\n\t}\r\n\r\n\treturn m_CurrentProfileIndex;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPlayerProfileManager::ApplyTemplateToCurrentProfile( uint32 checksum )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\tif ( m_CurrentProfileIndex == 0 )\r\n\t{\r\n\t\tmp_CurrentProfile[m_CurrentProfileIndex] = GetProfileTemplate( checksum );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t*mp_CurrentProfile[m_CurrentProfileIndex] = *GetProfileTemplate( checksum );\r\n\t}\r\n\tMem::Manager::sHandle().PopContext();\t//Mem::Manager::sHandle().SkaterInfoHeap());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterProfile* CPlayerProfileManager::GetCurrentProfile()\r\n{\r\n\treturn mp_CurrentProfile[m_CurrentProfileIndex];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterProfile* CPlayerProfileManager::GetProfile( int i )\r\n{\r\n\tDbg_MsgAssert( i >= 0 && i < vMAX_PLAYERS,( \"Profile %d out of range (0-%d)\", i, vMAX_PLAYERS-1 ));\r\n\r\n\treturn mp_CurrentProfile[i];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                \r\n\tIf any of the skater careers have this flag set, it returns true.\r\n\tUsed by the cassette menu when used for free skate, session etc,\r\n\tto find out what levels need to be selectable.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\n\r\n/*\r\nbool CPlayerProfileManager::GetGlobalFlag(int flag)\r\n{\r\n\tDbg_MsgAssert(0,(\"CPlayerProfileManager has been deprecated - careers no longer in profiles\\n\"));\r\n\tuint32 tableSize = m_Profiles.getSize( );\r\n\tfor ( uint32 i = 0; i < tableSize; i++ )\r\n\t{\r\n\t\tint key;\r\n\t\tCSkaterProfile* pProfile = m_Profiles.GetItemByIndex( i, &key );\r\n\t\tDbg_MsgAssert(pProfile,(\"NULL pProfile\"));\r\n\r\n\t\tCSkaterCareer *pCareer=pProfile->GetCareer();\r\n\t\tDbg_MsgAssert(pCareer,(\"NULL pCareer\"));\r\n\r\n\t\tif (pCareer->GetGlobalFlag(flag))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterProfile* CPlayerProfileManager::GetProfileTemplate( uint32 checksum )\r\n{\r\n\tDbg_MsgAssert( m_Profiles.GetItem( checksum ), ( \"Couldn't find profile %s\", Script::FindChecksumName(checksum) ) );\r\n\r\n\treturn m_Profiles.GetItem( checksum );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPlayerProfileManager::Reset()\r\n{\r\n\tuint32 tableSize = m_Profiles.getSize( );\r\n\tfor ( uint32 i = 0; i < tableSize; i++ )\r\n\t{\r\n\t\tint key;\r\n\t\tCSkaterProfile* pProfile = m_Profiles.GetItemByIndex( i, &key );\r\n\t\tpProfile->Reset();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPlayerProfileManager::AddAllProProfileInfo(Script::CStruct *pStuff)\r\n{\r\n\tDbg_MsgAssert(pStuff,(\"NULL pStuff\"));\r\n\t\r\n\tuint32 tableSize = m_Profiles.getSize( );\r\n\tfor ( uint32 i = 0; i < tableSize; i++ )\r\n\t{\r\n\t\tint key;\r\n\t\tCSkaterProfile* pProfile = m_Profiles.GetItemByIndex( i, &key );\r\n\r\n\t\t// Only add the pro's, not the create-a-skater.\r\n\t\tif (pProfile->IsPro())\r\n\t\t{\r\n\t\t\tpProfile->WriteIntoStructure(pStuff);\r\n\t\t}\r\n\t}\r\n\t\r\n\t\r\n\tDbg_MsgAssert(mp_CurrentProfile[m_CurrentProfileIndex],(\"NULL mp_CurrentProfile[%d]\",m_CurrentProfileIndex));\r\n\t\r\n\tuint32 CurrentSkaterNameChecksum = mp_CurrentProfile[m_CurrentProfileIndex]->GetSkaterNameChecksum();\r\n\tpStuff->AddComponent(Script::GenerateCRC(\"CurrentSkater\"),ESYMBOLTYPE_NAME,(int)CurrentSkaterNameChecksum);\r\n\t\r\n\tStr::String DisplayName=mp_CurrentProfile[m_CurrentProfileIndex]->GetUIString(\"display_name\");\r\n\tconst char *pDisplayName=DisplayName.getString();\r\n\tpStuff->AddComponent(Script::GenerateCRC(\"DisplayName\"),ESYMBOLTYPE_STRING,pDisplayName);\r\n\t\r\n\t/* The CAS file name is no longer needed since the cas info is now in the unified save file.\r\n\t\r\n\tconst char *pFileName=mp_CurrentProfile[m_CurrentProfileIndex]->GetCASFileName();\r\n\tpStuff->AddString(\"CASFileName\",pFileName);\r\n\t\r\n\t// The s_insert_game_save_info function in mcfuncs.cpp is also used to determine ahead of time\r\n\t// how much space a particular type of save will use, so that we can check that there is enough\r\n\t// space on the memcard.\r\n\t// However, at that point the file name for the cas save is not known, because the user has not\r\n\t// chosen it yet.\r\n\t// So add a pad string, so that whatever the current filename happens to be, the amount of\r\n\t// space used will be the same once the user has chosen a filename.\r\n\tint pad=Script::GetInteger(\"MAX_MEMCARD_FILENAME_LENGTH\",Script::ASSERT)-strlen(pFileName);\r\n\tDbg_MsgAssert(pad>=0 && pad<100,(\"Oops! '%s'\",pFileName));\r\n\tchar p_foo[100];\r\n\tfor (int i=0; i<pad; ++i)\r\n\t{\r\n\t\tp_foo[i]='*';\r\n\t}\r\n\tp_foo[pad]=0;\t\r\n\tpStuff->AddString(\"FileNamePad\",p_foo);\r\n\t*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPlayerProfileManager::LoadAllProProfileInfo(Script::CStruct *pStuff)\r\n{\r\n\tDbg_MsgAssert(pStuff,(\"NULL pStuff\"));\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\t\r\n\tuint32 tableSize = m_Profiles.getSize( );\r\n\tfor ( uint32 i = 0; i < tableSize; i++ )\r\n\t{\r\n\t\tint key;\r\n\t\tCSkaterProfile* pProfile = m_Profiles.GetItemByIndex( i, &key );\r\n\r\n\t\tif (pProfile->IsPro())\r\n\t\t{\r\n\t\t\tuint32 Name=pProfile->GetSkaterNameChecksum();\r\n\t\t\tpProfile->ReadFromStructure(Name,pStuff);\r\n\t\t}\t\r\n\t}\r\n\t\r\n\tuint32 CurrentSkaterNameChecksum=0;\r\n\tpStuff->GetChecksum(\"CurrentSkater\",&CurrentSkaterNameChecksum);\r\n\tApplyTemplateToCurrentProfile(CurrentSkaterNameChecksum);\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPlayerProfileManager::AddCASProfileInfo(Script::CStruct *pStuff)\r\n{\r\n\tDbg_MsgAssert(pStuff,(\"NULL pStuff\"));\r\n\t\r\n\tuint32 tableSize = m_Profiles.getSize( );\r\n\tfor ( uint32 i = 0; i < tableSize; i++ )\r\n\t{\r\n\t\tint key;\r\n\t\tCSkaterProfile* pProfile = m_Profiles.GetItemByIndex( i, &key );\r\n\r\n\t\tif (!pProfile->IsPro())\r\n\t\t{\r\n\t\t\tpProfile->WriteIntoStructure(pStuff);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPlayerProfileManager::LoadCASProfileInfo( Script::CStruct *pStuff, bool load_info )\r\n{\r\n\tDbg_MsgAssert(pStuff,(\"NULL pStuff\"));\r\n\r\n\tApplyTemplateToCurrentProfile(0xa7be964/*custom*/);\r\n\tCSkaterProfile* pProfile=GetCurrentProfile();\r\n\r\n\tuint32 Name = Script::GenerateCRC(\"custom\");\r\n\tScript::CStruct *pSkaterInfo=NULL;\r\n\tpStuff->GetStructure(Name,&pSkaterInfo);\r\n   \r\n\tDbg_MsgAssert(pSkaterInfo,(\"Memory card data is missing info for skater '%s'\",Script::FindChecksumName(Name)));\r\n\t\r\n\t// load only if there is a version number and it is current.\r\n\tint Version=0;\r\n\tif (pSkaterInfo->GetInteger(\"version_number\",&Version))\r\n\t{\r\n\t\tif (Version==CSkaterProfile::vVERSION_NUMBER)\r\n\t\t{\r\n\t\t\tScript::CStruct *pTemp=NULL;\r\n\t\r\n\t\t\tpSkaterInfo->GetStructure(\"Appearance\",&pTemp);\r\n\t\t\tGfx::CModelAppearance* pAppearance=pProfile->GetAppearance();\r\n\t\t\tDbg_MsgAssert(pAppearance,(\"NULL pAppearance\"));\r\n\t\t\tpAppearance->Load(pTemp);\r\n\t\r\n//\t\t\tCSkaterCareer* pCareer=pProfile->GetCareer();\r\n//\t\t\tDbg_MsgAssert(pCareer,(\"NULL pCareer\"));\r\n//\t\t\tpCareer->ReadFromStructure(pSkaterInfo);\r\n\t\r\n\t\t\t// GJ:  maybe this function could be refactored to use\r\n\t\t\t// CSkaterProfile's ReadFromStructure() function?\r\n\t\t\t// i'm not sure why there's one set of code for the pros\r\n\t\t\t// and one for the custom skater\r\n\t\t\tGfx::CFaceTexture* pFaceTexture = pAppearance->GetFaceTexture();\r\n\t\t\tDbg_MsgAssert( (!pProfile->IsPro()) == (pFaceTexture!=NULL), ( \"Only custom skaters should have face textures (Pro=%d, FaceTexture=%p)\", pProfile->IsPro(), pFaceTexture ) )\r\n\t\t\tif ( pFaceTexture )\r\n\t\t\t{\r\n\t\t\t\tbool faceTextureFound = pSkaterInfo->GetStructure( CRCD(0xf0d3bc94,\"FaceTexture\"), &pTemp );\r\n\t\t\t\tif ( faceTextureFound )\r\n\t\t\t\t{\r\n\t\t\t\t\t// load the face texture, if it exists\r\n\t\t\t\t\tpFaceTexture->ReadFromStructure( pTemp );\r\n\t\t\t\t\tprintf( \"Face texture found\\n\" );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf( \"Face texture not found\\n\" );\r\n\t\t\t\t}\r\n\t\t\t\tpFaceTexture->SetValid( faceTextureFound );\r\n\t\t\t}\r\n            \r\n            // store current stats\r\n            int air_value;\r\n            int run_value;\r\n            int ollie_value;\r\n            int speed_value;\r\n            int spin_value;\r\n            int flip_speed_value;\r\n            int switch_value;\r\n            int rail_balance_value;\r\n            int lip_balance_value;\r\n            int manual_balance_value;\r\n            air_value = pProfile->GetStatValue(CRCD(0x439f4704,\"air\"));\r\n            run_value = pProfile->GetStatValue(CRCD(0xaf895b3f,\"run\"));\r\n            ollie_value = pProfile->GetStatValue(CRCD(0x9b65d7b8,\"ollie\"));\r\n            speed_value = pProfile->GetStatValue(CRCD(0xf0d90109,\"speed\"));\r\n            spin_value = pProfile->GetStatValue(CRCD(0xedf5db70,\"spin\"));\r\n            flip_speed_value = pProfile->GetStatValue(CRCD(0x6dcb497c,\"flip_speed\"));\r\n            switch_value = pProfile->GetStatValue(CRCD(0x9016b4e7,\"switch\"));\r\n            rail_balance_value = pProfile->GetStatValue(CRCD(0xf73a13e3,\"rail_balance\"));\r\n            lip_balance_value = pProfile->GetStatValue(CRCD(0xae798769,\"lip_balance\"));\r\n            manual_balance_value = pProfile->GetStatValue(CRCD(0xb1fc0722,\"manual_balance\"));\r\n\r\n\t\t\tint num_trickslots;\r\n\t\t\tnum_trickslots = pProfile->GetNumSpecialTrickSlots();\r\n\t\t\tScript::CStruct* pSpecialTricks = new Script::CStruct();\r\n\t\t\tpSpecialTricks->AppendStructure( pProfile->GetSpecialTricksStructure() );\r\n            \r\n            \r\n            pTemp=NULL;\r\n            pSkaterInfo->GetStructure(\"Info\",&pTemp);\r\n            Script::CStruct* pInfo = pProfile->GetInfo();\r\n            Dbg_Assert(pInfo);\r\n            pInfo->Clear();\r\n            pInfo->AppendStructure(pTemp);\r\n            \r\n            if ( !load_info )\r\n            {\r\n                // restore stats\r\n                pProfile->SetPropertyValue(CRCD(0x439f4704,\"air\"), air_value);\r\n                pProfile->SetPropertyValue(CRCD(0xaf895b3f,\"run\"), run_value);\r\n                pProfile->SetPropertyValue(CRCD(0x9b65d7b8,\"ollie\"), ollie_value);\r\n                pProfile->SetPropertyValue(CRCD(0xf0d90109,\"speed\"), speed_value);\r\n                pProfile->SetPropertyValue(CRCD(0xedf5db70,\"spin\"), spin_value);\r\n                pProfile->SetPropertyValue(CRCD(0x6dcb497c,\"flip_speed\"), flip_speed_value);\r\n                pProfile->SetPropertyValue(CRCD(0x9016b4e7,\"switch\"), switch_value);\r\n                pProfile->SetPropertyValue(CRCD(0xf73a13e3,\"rail_balance\"), rail_balance_value);\r\n                pProfile->SetPropertyValue(CRCD(0xae798769,\"lip_balance\"), lip_balance_value);\r\n                pProfile->SetPropertyValue(CRCD(0xb1fc0722,\"manual_balance\"), manual_balance_value);\r\n\r\n\t\t\t\t// restore trickslot number\r\n\t\t\t\tpProfile->SetPropertyValue( CRCD(0xac9b9eda,\"max_specials\"), num_trickslots );\r\n\t\t\t\tpProfile->GetSpecialTricksStructure()->Clear();\r\n\t\t\t\tpProfile->GetSpecialTricksStructure()->AppendStructure( pSpecialTricks );\r\n            }\r\n\t\t\tdelete pSpecialTricks;\r\n            \r\n\r\n            // First deck is always unlocked, so make sure this is the default just in case DeckFlags is not found.\r\n\t\t\tint DeckFlags=1;\r\n\t\t\tpSkaterInfo->GetInteger(\"DeckFlags\",&DeckFlags);\r\n\t\t\t//Front::SetDeckFlags(Name,(uint32)DeckFlags);\r\n\t\t\t\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tDbg_Warning(\"\\n\\nBad version number of %d in saved custom skater. Required version = %d\\n\\n\",Version,CSkaterProfile::vVERSION_NUMBER);\r\n\t\treturn;\r\n\t}\t\t\r\n\tDbg_Warning(\"\\n\\nNo version number in saved custom skater. Required version = %d\\n\\n\",CSkaterProfile::vVERSION_NUMBER);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPlayerProfileManager::AddTemporaryProfile( uint32 profileName )\r\n{\r\n\tDbg_MsgAssert( m_TemporaryProfileCount < vMAX_TEMPORARY_PROFILES, ( \"Too many temporary profiles (max=%d)\", vMAX_TEMPORARY_PROFILES ) );\r\n\r\n\tfor ( int i = 0; i < m_TemporaryProfileCount; i++ )\r\n\t{\r\n\t\tif ( m_TemporaryProfileChecksums[i] == profileName )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Temporary profile checksum %s was already used\\n\", Script::FindChecksumName(profileName) ) );\r\n\t\t}\r\n\t}\r\n\r\n\tmp_TemporaryProfiles[m_TemporaryProfileCount] = new Obj::CSkaterProfile;\r\n\tm_TemporaryProfileChecksums[m_TemporaryProfileCount] = profileName;\r\n\r\n\tm_TemporaryProfileCount++;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterProfile* CPlayerProfileManager::GetTemporaryProfile(uint32 profileName)\r\n{\r\n\tfor ( int i = 0; i < m_TemporaryProfileCount; i++ )\r\n\t{\r\n\t\tif ( m_TemporaryProfileChecksums[i] == profileName )\r\n\t\t{\r\n\t\t\treturn mp_TemporaryProfiles[i];\r\n\t\t}\r\n\t}\r\n\t\r\n\tDbg_MsgAssert( 0, ( \"Couldn't find temporary profile with checksum %s\\n\", Script::FindChecksumName(profileName) ) );\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPlayerProfileManager::AddNewProfile( Script::CStruct* pParams )\r\n{\r\n\tDbg_Assert( pParams );\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\t// profileChecksum = hawk, thomas, custom, etc.\r\n\tuint32 profileChecksum;\r\n\tpParams->GetChecksum( \"name\", &profileChecksum, true );\r\n\t\r\n\t// add to the lookup table\r\n\tCSkaterProfile* pPlayerProfile = new CSkaterProfile;\r\n\tpPlayerProfile->Reset( pParams );\r\n\tm_Profiles.PutItem( profileChecksum, pPlayerProfile );\r\n\r\n#ifdef __USER_GARY__\r\n//\tuint8 tBuf[vMAX_APPEARANCE_BUFFER_SIZE];\r\n//\tuint32 size = pPlayerProfile->WriteToBuffer(tBuf, vMAX_APPEARANCE_BUFFER_SIZE);\r\n//\tDbg_Assert( size < vMAX_PRACTICAL_APPEARANCE_DATA_SIZE );\r\n//\tDbg_Message(\"*********** AddNewProfile %s appearance data size = %d bytes\\n\", Script::FindChecksumName(profileChecksum), size);\r\n#endif\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CPlayerProfileManager::LockCurrentSkaterProfileIndex( bool locked )\r\n{\r\n\t// GJ:  This is purely for debugging purposes,\r\n\t// to catch any accesses to the current skater profile index.\r\n\t// When using the CModelBuilder class, we NEVER want to use\r\n\t// the current skater profile index, because it may or may\r\n\t// not be valid in a network or splitscreen game.\r\n\t// So, the CModelBuilder class will turn this lock on\r\n\t// at the beginning of the model creation process, and\r\n\t// turn it off at the end.  Any calls to GetCurrentSkaterProfileIndex\r\n\t// will assert while locked.\r\n\r\n\tm_LockCurrentSkaterProfileIndex = locked;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/PlayerProfileManager.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       PlayerProfileManager.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  4/29/2002\r\n//****************************************************************************\r\n\r\n#ifndef __OBJECTS_PLAYERPROFILEMANAGER_H\r\n#define __OBJECTS_PLAYERPROFILEMANAGER_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/lookuptable.h>\r\n                               \r\n#include <sk/gamenet/gamenet.h>\r\n                                              \r\n#include <sk/objects/skaterprofile.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CPlayerProfileManager : public Spt::Class\r\n{\r\n\tenum\r\n\t{\r\n\t\tvMAX_PROFILES = 32,\r\n\t\tvMAX_PLAYERS = GameNet::vMAX_LOCAL_CLIENTS,\r\n\r\n\t\t// this is the biggest packet we can reasonably send\r\n\t\t// over a network packet (it's not really based on \r\n\t\t// the max packet size, but rather the biggest packet\r\n\t\t// that we've seen work so far...  the max packet size\r\n\t\t// specified in net.h seems to be too aggressive)\r\n\t\tvMAX_PRACTICAL_APPEARANCE_DATA_SIZE = 1150,\r\n\r\n\t\t// this is just the size of a temp buffer\r\n\t\tvMAX_APPEARANCE_BUFFER_SIZE = 4096,\r\n\r\n\t\t// temporary profiles, used for remembering/restoring\r\n\t\t// skater profiles (like for credits)\r\n\t\tvMAX_TEMPORARY_PROFILES = 3,\r\n\t};\r\n\t\r\n\tpublic:\r\n\t\tCPlayerProfileManager();\r\n\t\t~CPlayerProfileManager();\r\n\r\n\tpublic:\r\n\t\tvoid\t\t\t\t\tInit();\r\n\r\n\t\t// these deal with players (0 to numLocalClients)\r\n\t\tvoid\t\t\t\t\tSetCurrentProfileIndex(int i);\r\n\t\tint\t\t\t\t\t\tGetCurrentProfileIndex();\r\n\t\tvoid\t\t\t\t\tApplyTemplateToCurrentProfile(uint32 checksum);\r\n\t\tCSkaterProfile*\t\t\tGetCurrentProfile();\r\n\t\tCSkaterProfile*\t\t\tGetProfile(int i);\r\n//\t\tbool\t\t\t\t\tGetGlobalFlag(int flag);\r\n\t\tvoid\t\t\t\t\tSyncPlayer2();\r\n\r\n\t\t// these deal with templates (0 to numPros)\r\n\t\tCSkaterProfile*\t\t\tGetProfileTemplate(uint32 checksum);\r\n\t\tCSkaterProfile*\t\t\tGetProfileTemplateByIndex(int i);\r\n\r\n\t\t// for populating front end menus\r\n\t\tuint32\t\t\t\t\tGetNumProfileTemplates();\r\n\t\tuint32\t\t\t\t\tGetProfileTemplateChecksum(int i);\r\n\t\t\r\n\t\tvoid\t\t\t\t\tAddAllProProfileInfo(Script::CStruct *pStuff);\r\n\t\tvoid\t\t\t\t\tLoadAllProProfileInfo(Script::CStruct *pStuff);\r\n\t\tvoid\t\t\t\t\tAddCASProfileInfo(Script::CStruct *pStuff);\r\n\t\tvoid\t\t\t\t\tLoadCASProfileInfo(Script::CStruct *pStuff, bool load_info);\r\n\t\t\r\n\t\tvoid\t\t\t\t\tReset();\r\n\t\tbool\t\t\t\t\tAddNewProfile(Script::CStruct* pParams);\r\n\t\tvoid\t\t\t\t\tLockCurrentSkaterProfileIndex( bool locked );\r\n\t\t\r\n\t\tbool\t\t\t\t\tAddTemporaryProfile(uint32 checksum);\r\n\t\tCSkaterProfile*\t\t\tGetTemporaryProfile(uint32 checksum);\r\n\r\n\tprotected:\r\n\t\tLst::LookupTable<CSkaterProfile>\tm_Profiles;\r\n\t\tCSkaterProfile*\t\t\tmp_CurrentProfile[GameNet::vMAX_LOCAL_CLIENTS];\r\n\t\tint\t\t\t\t\t\tm_CurrentProfileIndex;\r\n\t\tbool\t\t\t\t\tm_LockCurrentSkaterProfileIndex;\r\n\t\t\r\n\t\tint\t\t\t\t\t\tm_TemporaryProfileCount;\r\n\t\tuint32\t\t\t\t\tm_TemporaryProfileChecksums[vMAX_TEMPORARY_PROFILES];\r\n\t\tCSkaterProfile*\t\t\tmp_TemporaryProfiles[vMAX_TEMPORARY_PROFILES];\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_PLAYERPROFILEMANAGER_H\r\n"
  },
  {
    "path": "Code/Sk/Objects/SkaterButton.cpp",
    "content": "// skaterbutton.cpp\r\n\r\n#include\t<sk\\objects\\skaterbutton.h>\r\n\r\n#include\t<gel\\scripting\\checksum.h>\r\n\r\nconst\tint\tpressure_threshold = 64;\r\n\r\n#ifdef __NOPT_ASSERT__\r\nvoid\t\tCSkaterButton::Update(int current_pressure, bool debug) \t\t// Update the pad based on teh current pressure\r\n#else\r\nvoid\t\tCSkaterButton::Update(int current_pressure) \t\t// Update the pad based on teh current pressure\r\n#endif\r\n{\r\n\t// if were are debouncing the button then update the debounce state\r\n\t// based on time and release, and ignore the button if still debouncing\r\n\tif (m_debounce_time)\r\n\t{\r\n\t\t// if not pressed, or debounce time expired\r\n\t\tif (current_pressure <= pressure_threshold)\r\n\t\t{\r\n//\t\t\tdodgy_test(); printf(\"Ending Debouncing as not pressed\\n\");\r\n\t\t\tm_debounce_time = 0;\r\n\t\t}\r\n\t\telse if ((float)Tmr::GetTime() > m_debounce_time)\r\n\t\t{\r\n//\t\t\tdodgy_test(); printf(\"Ending Debouncing as time expired\\n\");\r\n\t\t\tm_debounce_time = 0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n//\t\t\tdodgy_test(); printf(\"Debouncing button\\n\");\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tm_pressure = current_pressure;\r\n\tif (m_pressure > pressure_threshold)\r\n\t{\r\n\t\t// button is currently pressed\r\n\t\tif (!m_pressed)\r\n\t\t{\r\n\t\t\tm_pressed_time = Tmr::ElapsedTime(0);\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tif (debug)\t\t\t\r\n\t\t\t{\r\n\t\t\t\tprintf(\"%d: +++ Triggered %s +++\\n\",(int)Tmr::GetRenderFrame(),Script::FindChecksumName(m_name_checksum));\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t\t// but not previously pressed, so set the \"triggered\" flag\r\n\t\t\tm_triggered = true;\r\n\t\t}\r\n\t\tm_pressed = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// button is currently NOT pressed\r\n\t\tif (m_pressed)\r\n\t\t{\r\n\t\t\t// but WAS previously pressed, so set the \"released\" flag\r\n\t\t\tm_released_time = Tmr::ElapsedTime(0);\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tif (debug)\t\t\t\r\n\t\t\t{\r\n\t\t\t\tprintf(\"%d: --- Released  %s ----\\n\",(int)Tmr::GetRenderFrame(),Script::FindChecksumName(m_name_checksum));\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t\tm_released = true;\r\n\t\t}\r\n\t\tm_pressed = false;\r\n\t}\r\n\r\n}\r\n\r\nvoid\t\tCSkaterButton::SetPressed( bool pressed )\t\t// Set the button's \"Pressed\" state\r\n{\r\n\tif( pressed )\r\n\t{\r\n\t\t// button is currently pressed\r\n\t\tif( !m_pressed )\r\n\t\t{\r\n\t\t\tm_pressed_time = Tmr::ElapsedTime(0);\r\n\t\t\t// but not previously pressed, so set the \"triggered\" flag\r\n\t\t\tm_triggered = true;\r\n\t\t}\r\n\t\tm_pressed = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// button is currently NOT pressed\r\n\t\tif (m_pressed)\r\n\t\t{\r\n\t\t\t// but WAS previously pressed, so set the \"released\" flag\r\n\t\t\tm_released = true;\r\n\t\t}\r\n\t\tm_pressed = false;\r\n\t}\r\n\tm_pressed = pressed;\r\n}\r\n\r\nuint32\t\tCSkaterButton::GetReleasedTime()\t\t\t\t\t// Get time elapsed since m_released_time\r\n{\r\n\treturn\tTmr::ElapsedTime(m_released_time);\r\n}\r\n\r\nuint32\t\tCSkaterButton::GetPressedTime()\t\t\t\t\t// Get time elapsed since m_presssed_time\r\n{\r\n\treturn\tTmr::ElapsedTime(m_pressed_time);\r\n}\r\n\r\nvoid\t\tCSkaterButton::ClearTrigger()\t\t\t\t\t\t// Clear the trigger\r\n{\r\n\tm_triggered = false;\r\n}\r\n\r\nvoid\t\tCSkaterButton::ClearRelease()\t\t\t\t\t\t// Clear the trigger\r\n{\r\n\tm_released = false;\r\n}\r\n\r\n\r\nvoid \t\tCSkaterButton::SetName(const char *p_name)\r\n{\r\n\tm_name_checksum = Crc::GenerateCRCFromString(p_name);\r\n}\r\n\r\n\r\nvoid\t\tCSkaterButton::SetDebounce(float time)\r\n{\r\n\t// Mick:  When debouncing, we ignore furthur input until the time has elapsed\r\n\t// or the button \"pressed\" state changes from what it was at the start of the debounce \r\n\r\n//\tprintf (\"SetDebounce #########################################################\\n\");\r\n//\t\r\n//\tprintf (\"GetTime = %d, m_pressed = %d, m_pressed_time = %d, m_triggered = %d\\n\",\r\n//\t\t\tTmr::ElapsedTime(0), m_pressed  , m_pressed_time , m_triggered );\r\n\t\r\n\t\r\n\tm_debounce_time = time;\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/SkaterButton.h",
    "content": "// SkaterButton.h\r\n\r\n#ifndef\t__SK_OBJECTS_SKATERBUTTON_H__\r\n#define\t__SK_OBJECTS_SKATERBUTTON_H__\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <sys\\timer.h>\r\n\r\n\r\n// A SkaterButton contains the state of a single pad button\r\n// in a way that is specific to control issues\r\n// initially this is similar to the old SPad structure in THPS-PSX\r\n// but will probably be extended to handle analog buttons\r\n// and storing, inspecting and flagging the history of button events \r\n\r\nclass CSkaterButton : public Spt::Class\r\n{\r\n\r\n\r\npublic:\r\n#ifdef __NOPT_ASSERT__\r\n\tvoid\t\tUpdate(int current_pressure, bool debug = false); \t\t// Update the button based on the current pressure\r\n#else\r\n\tvoid\t\tUpdate(int current_pressure); \t\t// Update the button based on the current pressure\r\n#endif\r\n\tbool\t\tGetPressed() {return m_pressed;}\t// Get current \"Pressed\" state\r\n\tbool\t\tGetTriggered();\t\t\t\t\t\t// Get current \"Triggered\" state\r\n\tvoid\t\tSetPressed( bool pressed );\t\t\t// Set the button's \"Pressed\" state\r\n\tint\t\t\tGetPressure();\t\t\t\t\t\t// Get current pressure\r\n\tvoid\t\tClearTrigger();\t\t\t\t\t\t// Clear the trigger\r\n\tvoid \t\tSetName(const char *p_name);\t\t// Set name of button (mostly for dubugging)\r\n\r\n\tvoid\t\tSetDebounce(float time);\t\t\t// set time to debounce\r\n\tTmr::Time\tGetDebounceTime() { return static_cast< Tmr::Time >(m_debounce_time); }\r\n\r\n\tbool\t\tGetReleased();\r\n\tvoid\t\tClearRelease();\t\t\t\t\r\n\t\r\n\tuint32\t\tGetPressedTime();  \t\t\t\t\t// Get m_pressed_time\r\n\tuint32\t\tGetReleasedTime();\t\t\t\t\t// Get m_released_time\r\n\r\nprivate:\t\t\r\n\t\r\n\t\r\n\tbool\t\tm_pressed;  \t\t\t\t\t\t// true if pressed now, indicates the current state of the button\r\n\tuint32\t\tm_pressed_time;\t\t\t\t\t\t// time when button was last pressed\r\n\tuint32\t\tm_released_time;\t\t\t\t\t// time when button was last released\r\n\tint\t\t\tm_pressure;\t\t\t\t\t\t\t// current button presure;\r\n\tbool\t\tm_triggered;\t  \t\t\t\t\t// true if was triggered, can be cleared\r\n\tint \t\tm_released;\t\t\t\t\t\t\t// true if we released, can be cleared (for debouncing)\r\n\tuint32\t\tm_name_checksum;\t\t\t\t\t// Checksum of button name\r\n\tfloat\t\tm_debounce_time;\t\t\t\t\t// time until we we remain debounced\r\n\t//bool\t\tm_debounce_pressed;\t\t\t\t\t// state when \"debounce\" called\r\n\t//const char\t*\tmp_name;\t\t\t  \t \t// Pointer to name, used for debugging;\r\n\t\r\npublic:\r\n\tuint32 GetName() {return m_name_checksum;}\r\n};\r\n\r\ninline bool\t\tCSkaterButton::GetTriggered()\t\t// Get current \"Triggered\" state\r\n{\r\n\treturn m_triggered;\r\n}\r\n\r\ninline bool\t\tCSkaterButton::GetReleased()\t\t\r\n{\r\n\treturn m_released;\r\n}\r\n\r\ninline int\t\t\tCSkaterButton::GetPressure()\t// Get current pressure\r\n{\r\n\treturn\tm_pressure;\r\n}\r\n\r\n\r\n\r\n#endif\t__SK_OBJECTS_SKATERBUTTON_H__\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/SkaterPad.h",
    "content": "// SkaterPad.h\r\n\r\n#ifndef\t__SK_OBJ_SKATERPAD_H__\r\n#define\t__SK_OBJ_SKATERPAD_H__\r\n\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <core/math.h>\r\n#include <sk\\objects\\skaterbutton.h>\r\n\r\nnamespace Inp\r\n{\r\n\tclass Data;\r\n}\r\n\r\n// A CSkaterPad class contains the state of the pad controlling the skater \r\nclass  CSkaterPad  : public Spt::Class\r\n{\r\n\t\r\npublic:\r\n\tCSkaterPad();\r\n\r\n\tuint32\t\t\tGetPressedMask( void );\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tvoid\t\t\tUpdate ( Inp::Data* input, bool debug = false );\r\n\t#else\r\n\tvoid\t\t\tUpdate ( Inp::Data* input );\r\n\t#endif\r\n\t\r\n\tvoid\t\t\tZero (   );\r\n\tvoid\t\t\tReset (   );\r\n\t\r\n\tfloat\t\t\tGetScaledAnalogStickMagnitude ( float analog_x, float analog_y, float analog_angle  );\r\n\tfloat\t\t\tGetScaledLeftAnalogStickMagnitude (   ) { return GetScaledAnalogStickMagnitude(m_leftX, m_leftY, m_leftAngle); }\r\n\tfloat\t\t\tGetScaledRightAnalogStickMagnitude (   ) { return GetScaledAnalogStickMagnitude(m_rightX, m_rightY, m_rightAngle); }\r\n\t\r\n\tbool\t\t\tIsLeftAnalogUpPressed();\r\n\tbool\t\t\tIsLeftAnalogDownPressed();\r\n\tvoid\t\t\tDebounceLeftAnalogUp ( float duration );\r\n\tvoid\t\t\tDebounceLeftAnalogDown( float duration );\r\n\r\n\tCSkaterButton \tm_up;\r\n\tCSkaterButton \tm_down;\r\n\tCSkaterButton \tm_left;\r\n\tCSkaterButton \tm_right;\r\n\tCSkaterButton \tm_L1;\r\n\tCSkaterButton \tm_L2;\r\n\tCSkaterButton \tm_L3;\r\n\tCSkaterButton \tm_R1;\r\n\tCSkaterButton \tm_R2;\r\n\tCSkaterButton \tm_R3;\r\n\tCSkaterButton \tm_circle;\r\n\tCSkaterButton \tm_square;\r\n\tCSkaterButton \tm_triangle;\r\n\tCSkaterButton \tm_x;\r\n\tCSkaterButton \tm_start;\r\n\tCSkaterButton \tm_select;\r\n\r\n\tfloat\t\t\tm_rightX;\r\n\tfloat\t\t\tm_rightY;\r\n\tfloat\t\t\tm_leftX;\r\n\tfloat\t\t\tm_leftY;\r\n\r\n\tfloat\t\t\tm_scaled_rightX;\r\n\tfloat\t\t\tm_scaled_rightY;\r\n\tfloat\t\t\tm_scaled_leftX;\r\n\tfloat\t\t\tm_scaled_leftY;\r\n\r\n\t// angle and amount we are push the direction stick\r\n\tfloat\t\t\tm_rightAngle;\r\n\tfloat\t\t\tm_rightLength;\r\n\tfloat\t\t\tm_leftAngle;\r\n\tfloat\t\t\tm_leftLength;\r\n\t\r\n\tTmr::Time\t\tm_leftAnalogUpDebounceTime;\r\n\tTmr::Time\t\tm_leftAnalogDownDebounceTime;\r\n\t\r\n\t// Given the checksum of a button name, this will return that button.\r\n\tCSkaterButton*\tGetButton(uint32 NameChecksum);\r\n\r\n\t// related utility functions\r\n\t\r\n\tstatic uint32\tsGetDirection(bool Up, bool Down, bool Left, bool Right);\r\n\tstatic float\tsGetAngleFromDPad(bool Up, bool Down, bool Left, bool Right);\r\n};\r\n\r\ninline bool CSkaterPad::IsLeftAnalogUpPressed (   )\r\n{\r\n\treturn m_leftAnalogUpDebounceTime == 0 && m_leftLength != 0.0f && Mth::Abs(m_leftAngle) < Mth::DegToRad(45.0f);\r\n}\r\n\r\ninline bool CSkaterPad::IsLeftAnalogDownPressed (   )\r\n{\r\n\treturn m_leftAnalogDownDebounceTime == 0 && m_leftLength != 0.0f && (Mth::PI - Mth::Abs(m_leftAngle)) < Mth::DegToRad(45.0f);\r\n}\r\n\r\ninline void CSkaterPad::DebounceLeftAnalogUp ( float duration )\r\n{\r\n\tm_leftAnalogUpDebounceTime = Tmr::GetTime() + static_cast< Tmr::Time >(1000.0f * duration);\r\n}\r\n\r\ninline void CSkaterPad::DebounceLeftAnalogDown ( float duration )\r\n{\r\n\tm_leftAnalogDownDebounceTime = Tmr::GetTime() + static_cast< Tmr::Time >(1000.0f * duration);\r\n}\r\n\r\ntypedef CSkaterPad CControlPad;\r\n\r\n#endif\t//\t__SK_OBJ_SKATERPAD_H__\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/SkaterProfile.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       SkaterProfile.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  11/29/2000\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/objects/skaterprofile.h>\r\n\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/components/trickcomponent.h>\r\n\r\n#include <gfx/casutils.h>\r\n#include <gfx/facetexture.h>\r\n\r\n// If possible, try to remove the dependency on these include files...\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/skater.h>                         // for updatetrickmapping\r\n#include <sk/objects/playerprofilemanager.h>           // for updatetrickmapping\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n// TODO:  Add trick-config and special-trick-config classes.\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterProfile::CSkaterProfile(void)\r\n{\r\n\tReset();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterProfile::CSkaterProfile(const CSkaterProfile& skaterProfile)\r\n{\r\n\t// use the overridden assignment operator\r\n\t*this = skaterProfile;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterProfile& CSkaterProfile::operator=(const CSkaterProfile& skaterProfile)\r\n{\r\n\tif ( &skaterProfile == this )\r\n\t{\r\n\t\treturn *this;\r\n\t}\r\n\r\n\t// use the overridden assignment operator\r\n\tm_Appearance = skaterProfile.m_Appearance;\r\n\r\n\t// info assignment is okay, bec. structs have an overridden assignment operator\r\n\tm_Info = skaterProfile.m_Info;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterProfile::Reset(Script::CStruct* pParams)\r\n{\r\n\t// this should get called once at the beginning of the game,\r\n\t// and then whenever you want to clear it out to its initial state\r\n\t// (like creating a new pro)\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\t// destroy the face texture, if one exists\r\n\tm_Appearance.DestroyFaceTexture();\r\n\t\r\n\tm_Appearance.Init();\r\n\t\r\n\tm_Info.Clear();\r\n\r\n\tScript::CStruct* pTemp;\r\n\t\r\n\t// TODO:  The trick mapping and the specials\r\n\t// should be in their own structures, not within the\r\n\t// info...\r\n\r\n\t// at a minimum, the info structure must contain the trick_mapping structure\r\n\tpTemp = new Script::CStruct;\r\n\tm_Info.AddComponent( CRCD(0xd544aa2d,\"trick_mapping\"), ESYMBOLTYPE_STRUCTUREPOINTER, (int)pTemp );\r\n\r\n\t// as well as a special tricks array\r\n\tpTemp = new Script::CStruct;\r\n\tm_Info.AddComponent( CRCD(0xddbee809,\"specials\"), ESYMBOLTYPE_STRUCTUREPOINTER, (int)pTemp );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tif ( pParams )\r\n\t{\r\n\t\t//\tDbg_Message( \"Alternate constructor for skater profile called\\n\");\r\n\r\n\t\tuint32 appearanceStructure;\r\n\t\tpParams->GetChecksum( CRCD(0x1d6f290c,\"default_appearance\"), &appearanceStructure, true );\r\n\t\tm_Appearance.Load( appearanceStructure );\r\n\r\n\t\t// set the trick style, whether he's a pro, etc.\r\n\t\tm_Info.Clear();\r\n\t\tm_Info.AppendStructure( pParams );\r\n\r\n\t\tif ( !IsPro() )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\t\t\t// create a face texture, only if it's a custom skater\r\n\t\t\tm_Appearance.CreateFaceTexture();\r\n\t\t\t\r\n\t\t\t// for debugging purposes, set up a test face\r\n\t\t\t// Gfx::CFaceTexture* pFaceTexture = m_Appearance.GetFaceTexture();\r\n\t\t\t// pFaceTexture->LoadFace( \"faces\\\\CS_NSN_head_test_kurt\" );\r\n\t\t\t\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t}\t\t\r\n\r\n\t\t// initialize the trick mappings to the default values, defined in protricks.q\r\n\t\tuint32 trickMappingChecksum;\r\n\t\tpParams->GetChecksum( CRCD(0xe365363e,\"default_trick_mapping\"), &trickMappingChecksum, Script::ASSERT );\r\n\r\n\t\tScript::CStruct* pGlobalTrickMappingStructure;\r\n\t\tpGlobalTrickMappingStructure = Script::GetStructure(trickMappingChecksum, Script::ASSERT);\r\n\r\n\t\tScript::CStruct* pLocalTrickMappingStructure;\r\n\t\tm_Info.GetStructure( CRCD(0xd544aa2d,\"trick_mapping\"), &pLocalTrickMappingStructure, Script::ASSERT );\r\n\t\tpLocalTrickMappingStructure->Clear();\r\n\t\tpLocalTrickMappingStructure->AppendStructure( pGlobalTrickMappingStructure );\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tDbg_Message( \"Warning: profile was created without valid data\" );\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterProfile::PartialReset(Script::CStruct* pParams)\r\n{\r\n    Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\t// destroy the face texture, if one exists\r\n\tm_Appearance.DestroyFaceTexture();\r\n\t\r\n\tm_Appearance.Init();\r\n\t\r\n    Script::CStruct* pTemp;\r\n\t\r\n    // at a minimum, the info structure must contain the trick_mapping structure\r\n\tpTemp = new Script::CStruct;\r\n\tm_Info.AddComponent( CRCD(0xd544aa2d,\"trick_mapping\"), ESYMBOLTYPE_STRUCTUREPOINTER, (int)pTemp );\r\n\r\n\t// as well as a special tricks array\r\n\tpTemp = new Script::CStruct;\r\n\tm_Info.AddComponent( CRCD(0xddbee809,\"specials\"), ESYMBOLTYPE_STRUCTUREPOINTER, (int)pTemp );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tif ( pParams )\r\n\t{\r\n        uint32 appearanceStructure;\r\n\t\tpParams->GetChecksum( CRCD(0x1d6f290c,\"default_appearance\"), &appearanceStructure, true );\r\n\t\tm_Appearance.Load( appearanceStructure );\r\n\r\n        // copy just the info I want into it\r\n        const char* name;\r\n        int num;\r\n        uint32 checksum;\r\n\r\n        pParams->GetString( CRCD(0x2ab66cb8,\"display_name\"), &name, Script::ASSERT );\r\n        m_Info.AddString(\"display_name\", name );\r\n        pParams->GetString( CRCD(0x562e3ecd,\"first_name\"), &name, Script::ASSERT );\r\n        m_Info.AddString(\"first_name\", name );\r\n        pParams->GetString( CRCD(0x2820e997,\"file_name\"), &name, Script::ASSERT );\r\n        m_Info.AddString(\"file_name\", name );\r\n        pParams->GetString( CRCD(0x6c375b95,\"hometown\"), &name, Script::ASSERT );\r\n        m_Info.AddString(\"hometown\", name );\r\n\r\n        pParams->GetInteger( CRCD(0x6f14c39c,\"skater_index\"), &num, Script::ASSERT );\r\n        m_Info.AddInteger(\"skater_index\", num );\r\n        pParams->GetInteger( CRCD(0xd82f8ac8,\"is_pro\"), &num, Script::ASSERT );\r\n        m_Info.AddInteger(\"is_pro\", num );\r\n        pParams->GetInteger( CRCD(0x3f813177,\"is_male\"), &num, Script::ASSERT );\r\n        m_Info.AddInteger(\"is_male\", num );\r\n        pParams->GetInteger( CRCD(0x9f350e5,\"is_head_locked\"), &num, Script::ASSERT );\r\n        m_Info.AddInteger(\"is_head_locked\", num );\r\n        pParams->GetInteger( CRCD(0x4564bab1,\"is_locked\"), &num, Script::ASSERT );\r\n        m_Info.AddInteger(\"is_locked\", num );\r\n        pParams->GetInteger( CRCD(0x27eb9b9d,\"is_hidden\"), &num, Script::NO_ASSERT );\r\n        m_Info.AddInteger(\"is_hidden\", num );\r\n        pParams->GetInteger( CRCD(0x5ecfef4d,\"age\"), &num, Script::ASSERT );\r\n        m_Info.AddInteger(\"age\", num );\r\n        \r\n        pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &checksum, Script::ASSERT );\r\n        m_Info.AddChecksum(\"name\", checksum );\r\n        pParams->GetChecksum( CRCD(0x7d02bcc3,\"stance\"), &checksum, Script::ASSERT );\r\n        m_Info.AddChecksum(\"stance\", checksum );\r\n        pParams->GetChecksum( CRCD(0xc15dbf86,\"pushstyle\"), &checksum, Script::ASSERT );\r\n        m_Info.AddChecksum(\"pushstyle\", checksum );\r\n        pParams->GetChecksum( CRCD(0xdfd4043e,\"trickstyle\"), &checksum, Script::ASSERT );\r\n        m_Info.AddChecksum(\"trickstyle\", checksum );\r\n\r\n        Script::CStruct* p_special;\r\n        pParams->GetStructure( CRCD(0xddbee809,\"specials\"), &p_special, Script::ASSERT );\r\n        m_Info.AddStructure(\"specials\", p_special );\r\n        \r\n#ifdef __PLAT_NGPS__\r\n        if ( !IsPro() )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\t\t\t// create a face texture, only if it's a custom skater\r\n\t\t\tm_Appearance.CreateFaceTexture();\r\n\t\t\t\r\n\t\t\t// for debugging purposes, set up a test face\r\n\t\t\t// Gfx::CFaceTexture* pFaceTexture = m_Appearance.GetFaceTexture();\r\n\t\t\t// pFaceTexture->LoadFace( \"faces\\\\CS_NSN_head_test_kurt\" );\r\n\t\t\t\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t}\r\n#endif\r\n\r\n\t\t// initialize the trick mappings to the default values, defined in protricks.q\r\n\t\tuint32 trickMappingChecksum;\r\n\t\tpParams->GetChecksum( CRCD(0xe365363e,\"default_trick_mapping\"), &trickMappingChecksum, Script::ASSERT );\r\n\r\n\t\tScript::CStruct* pGlobalTrickMappingStructure;\r\n\t\tpGlobalTrickMappingStructure = Script::GetStructure(trickMappingChecksum, Script::ASSERT);\r\n\r\n\t\tScript::CStruct* pLocalTrickMappingStructure;\r\n\t\tm_Info.GetStructure( CRCD(0xd544aa2d,\"trick_mapping\"), &pLocalTrickMappingStructure, Script::ASSERT );\r\n\t\tpLocalTrickMappingStructure->Clear();\r\n\t\tpLocalTrickMappingStructure->AppendStructure( pGlobalTrickMappingStructure );\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tDbg_Message( \"Warning: profile was created without valid data\" );\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CSkaterProfile::WriteToBuffer(uint8 *pBuffer, uint32 BufferSize, bool ignoreFaceData )\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\r\n\tuint32 totalSize = 0;\r\n\tuint32 chunkSize = 0;\r\n\r\n\tchunkSize = m_Appearance.WriteToBuffer(pBuffer, BufferSize, ignoreFaceData);\r\n\ttotalSize += chunkSize;\r\n\r\n\t// write out trick mappings\r\n\tBufferSize -= chunkSize;\r\n\tpBuffer += chunkSize;\r\n//\tcompress_trick_mappings( \"trick_mapping\" );\r\n\tchunkSize = Script::WriteToBuffer(GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") ), pBuffer, BufferSize );\r\n\ttotalSize += chunkSize;\r\n//\tdecompress_trick_mappings( \"trick_mapping\" );\r\n\r\n\t// write out special tricks...  these could\r\n\t// theoretically be compressed, but not using\r\n\t// the same method as the regular tricks\r\n\t// (because they're in a different format)\r\n\tBufferSize -= chunkSize;\r\n\tpBuffer += chunkSize;\r\n\tScript::CStruct* pSpecialsStructure = GetSpecialTricksStructure();\r\n\tchunkSize = Script::WriteToBuffer(pSpecialsStructure, pBuffer, BufferSize);\r\n\ttotalSize += chunkSize;\r\n\r\n\t// write out any extra info that needs to go across\r\n\t// (i.e. stats, name, etc.)\r\n\t// (some data, such as your default specials\r\n\t// and your default appearance, aren't needed)\r\n\tBufferSize -= chunkSize;\r\n\tpBuffer += chunkSize;\r\n\tchunkSize = write_extra_info_to_buffer(pBuffer, BufferSize);\r\n\ttotalSize += chunkSize;\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn totalSize;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8* CSkaterProfile::ReadFromBuffer(uint8 *pBuffer)\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\r\n\tpBuffer = m_Appearance.ReadFromBuffer(pBuffer);\r\n\r\n\tGetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") )->Clear();\r\n\tpBuffer = Script::ReadFromBuffer(GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") ), pBuffer);\r\n\t\r\n//\tdecompress_trick_mappings( \"trick_mapping\" );\r\n\r\n\tScript::CStruct* pStructure = GetSpecialTricksStructure();\r\n\tDbg_Assert( pStructure );\r\n\tpStructure->Clear();\r\n\tpBuffer = Script::ReadFromBuffer(pStructure, pBuffer);\r\n\r\n\t// read any extra info that is needed in-game\r\n\t// (some data, such as your default specials\r\n\t// and your default appearance, aren't needed)\r\n\tpBuffer = read_extra_info_from_buffer(pBuffer);\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn pBuffer;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CSkaterProfile::write_extra_info_to_buffer(uint8 *pBuffer, uint32 BufferSize)\r\n{\t\r\n\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\r\n\tDbg_Assert( pTempStructure );\r\n\t\r\n\t// for each component in info, see if it's needed in-game...\r\n\t// such as the stats, trick style, etc.\r\n\t// (most of the other information is only needed in the front end)\r\n\tScript::CComponent *pComp = m_Info.GetNextComponent();\r\n\twhile ( pComp )\r\n\t{\r\n\t\tScript::CComponent* pNextComp = m_Info.GetNextComponent( pComp );\r\n\r\n\t\tswitch ( pComp->mNameChecksum )\r\n\t\t{\r\n\t\t\tcase 0xa1dc81f9:\t// name\r\n\t\t\tcase 0x7d02bcc3:\t// stance\r\n\t\t\tcase 0xc15dbf86:\t// pushstyle\r\n\t\t\t\tpTempStructure->AddComponent( pComp->mNameChecksum, ESYMBOLTYPE_NAME, (int)pComp->mChecksum );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 0x2ab66cb8:\t// display_name\r\n\t\t\tcase 0x2820e997:\t// file_name\r\n\t\t\tcase 0x562e3ecd:\t// first_name\r\n\t\t\t\tpTempStructure->AddComponent( pComp->mNameChecksum, ESYMBOLTYPE_STRING, pComp->mpString );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 0x439f4704:\t// air\r\n\t\t\tcase 0xaf895b3f:\t// run\r\n\t\t\tcase 0x9b65d7b8:\t// ollie\r\n\t\t\tcase 0xf0d90109:\t// speed\r\n\t\t\tcase 0xedf5db70:\t// spin\r\n\t\t\tcase 0x9016b4e7:\t// switch\r\n\t\t\tcase 0xf73a13e3:\t// rail_balance\r\n\t\t\tcase 0xae798769:\t// lip_balance\r\n\t\t\tcase 0xb1fc0722:\t// manual_balance\r\n\t\t\tcase 0xd82f8ac8:\t// is_pro\r\n\t\t\tcase 0x6dcb497c:\t// flip_speed\r\n\t\t\tcase 0x3f813177:\t// is_male\r\n\t\t\t\tpTempStructure->AddComponent( pComp->mNameChecksum, ESYMBOLTYPE_INTEGER, (int)pComp->mIntegerValue );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tdefault:\r\n\t\t\t\t// doesn't need to go across\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tpComp = pNextComp;\r\n\t}\r\n\r\n\tuint32 totalSize = Script::WriteToBuffer(pTempStructure, pBuffer, BufferSize);\r\n\t\r\n\tdelete pTempStructure;\r\n\t\r\n\treturn totalSize;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8* CSkaterProfile::read_extra_info_from_buffer(uint8 *pBuffer)\r\n{\r\n\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\r\n\tpBuffer = Script::ReadFromBuffer(pTempStructure, pBuffer);\r\n\r\n\tm_Info.AppendStructure( pTempStructure );\r\n\t\r\n\tdelete pTempStructure;\r\n\t\r\n\treturn pBuffer;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterProfile::compress_trick_mappings( const char* pTrickMappingName )\r\n{\r\n\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tCTrickChecksumTable* pTrickChecksumTable = skate_mod->GetTrickChecksumTable();\r\n\r\n\tScript::CStruct* pTempStructure;\r\n\tif ( !m_Info.GetStructure( pTrickMappingName, &pTempStructure ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Trick mapping %s not found...  already compressed?\", pTrickMappingName ) );\r\n\t}\r\n\r\n\tint compressed = 0;\r\n\tpTempStructure->GetInteger( CRCD(0x68a9b4e1,\"compressed\"), &compressed );\r\n\tif ( compressed )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"This structure is already compressed\" ) );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// take all the integers, and convert them to checksums\r\n\tScript::CComponent *pComp = pTempStructure->GetNextComponent();\r\n\twhile ( pComp )\r\n\t{\r\n\t\tScript::CComponent* pNextComp = pTempStructure->GetNextComponent( pComp );\r\n\r\n\r\n\t\tif (pComp && pComp->mType==ESYMBOLTYPE_NAME && pComp->mNameChecksum != CRCD(0x68a9b4e1,\"compressed\") )\r\n\t\t{\r\n\t\t\tint compressedIndex = pTrickChecksumTable->GetIndexFromChecksum( pComp->mChecksum );\r\n\t\t\tif ( compressedIndex != -1 )\r\n\t\t\t{\t\t\t\r\n\t\t\t\tuint32\tnameChecksum = pComp->mNameChecksum; // Mick, need to store this now, as we are about to remove pComp\r\n\t\t\t\tpTempStructure->RemoveComponent( nameChecksum );\r\n\t\t\t\tpTempStructure->AddComponent( nameChecksum, ESYMBOLTYPE_INTEGER, compressedIndex );\r\n\t\t\t}\r\n\t\t}\r\n\t\tpComp = pNextComp;\r\n\t}\r\n\r\n\t// add the compressed flag\r\n\tpTempStructure->AddComponent( CRCD(0x68a9b4e1,\"compressed\"), ESYMBOLTYPE_INTEGER, 1 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterProfile::decompress_trick_mappings( const char* pTrickMappingName )\r\n{\r\n\t\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tCTrickChecksumTable* pTrickChecksumTable = skate_mod->GetTrickChecksumTable();\r\n\t\r\n\tScript::CStruct* pTempStructure;\r\n\tif ( !m_Info.GetStructure( pTrickMappingName, &pTempStructure ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Trick mapping %s not found...  already compressed?\", pTrickMappingName ) );\r\n\t}\r\n\r\n\tint compressed = 0;\r\n\tpTempStructure->GetInteger( CRCD(0x68a9b4e1,\"compressed\"), &compressed );\r\n\tif ( !compressed )\r\n\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\tScript::PrintContents(&m_Info);\r\n\t\tScript::PrintContents(pTempStructure);\r\n#endif\t\t\r\n\t\tDbg_MsgAssert( 0, ( \"This structure is not compressed\" ) );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// take all the integers, and convert them to checksums\r\n\tScript::CComponent *pComp = pTempStructure->GetNextComponent();\r\n\twhile ( pComp )\r\n\t{\r\n\t\tScript::CComponent* pNextComp = pTempStructure->GetNextComponent( pComp );\r\n\r\n\t\tif (pComp && pComp->mType==ESYMBOLTYPE_INTEGER && pComp->mNameChecksum != CRCD(0x68a9b4e1,\"compressed\") )\r\n\t\t{\r\n\t\t\tint uncompressedChecksum = pTrickChecksumTable->GetChecksumFromIndex( pComp->mIntegerValue );\r\n\t\t\tuint32\tnameChecksum = pComp->mNameChecksum; // Mick, need to store this now, as we are about to remove pComp\r\n\t\t\tpTempStructure->RemoveComponent( nameChecksum );\r\n\t\t\tpTempStructure->AddComponent( nameChecksum, ESYMBOLTYPE_NAME, uncompressedChecksum );\r\n\t\t}\r\n\r\n\t\tpComp = pNextComp;\r\n\t}\r\n\r\n\t// reset the compressed flag\r\n\tpTempStructure->AddComponent( CRCD(0x68a9b4e1,\"compressed\"), ESYMBOLTYPE_INTEGER, 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterProfile::WriteIntoStructure( Script::CStruct* pStuff )\r\n{\t\r\n\tDbg_MsgAssert(pStuff,(\"NULL pStuff\"));\r\n\t\r\n\tScript::CStruct *pSkaterInfo=new Script::CStruct;\r\n\r\n\tpSkaterInfo->AddComponent( CRCD(0x1902c8f0,\"version_number\"), ESYMBOLTYPE_INTEGER, CSkaterProfile::vVERSION_NUMBER );\r\n\t\r\n\tScript::CStruct *pTemp=NULL;\r\n\t\r\n\tif (!IsPro())\r\n\t{\r\n\t\tpTemp=new Script::CStruct;\r\n\t\tpTemp->AppendStructure( m_Appearance.GetStructure() );\r\n\t\tpSkaterInfo->AddComponent( CRCD(0x554c7d6f,\"Appearance\"), ESYMBOLTYPE_STRUCTUREPOINTER, (int)pTemp );\r\n\t}\r\n\t\t\r\n\tGfx::CFaceTexture* pFaceTexture = m_Appearance.GetFaceTexture();\r\n\tif ( pFaceTexture && pFaceTexture->IsValid() )\r\n\t{\r\n\t\tpTemp=new Script::CStruct;\r\n\t\tpFaceTexture->WriteIntoStructure( pTemp );\r\n\t\tpSkaterInfo->AddComponent( CRCD(0xf0d3bc94,\"FaceTexture\"), ESYMBOLTYPE_STRUCTUREPOINTER, (int)pTemp );\r\n\t}\r\n\r\n\tpTemp=new Script::CStruct;\r\n\tpTemp->AppendStructure(&m_Info);\r\n\tpSkaterInfo->AddComponent( CRCD(0x3476cea8,\"Info\"), ESYMBOLTYPE_STRUCTUREPOINTER, (int)pTemp );\r\n\r\n\tuint32 Name=GetSkaterNameChecksum();\r\n\t//pSkaterInfo->AddComponent(CRCD(0x95388a60,\"DeckFlags\"),ESYMBOLTYPE_INTEGER,(int)Front::GetDeckFlags(Name));\r\n\tpSkaterInfo->AddComponent( CRCD(0x95388a60,\"DeckFlags\"), ESYMBOLTYPE_INTEGER, 0 );\r\n\t\r\n\tpStuff->AddComponent(Name,ESYMBOLTYPE_STRUCTUREPOINTER,(int)pSkaterInfo);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterProfile::ReadFromStructure( uint32 SkaterName, Script::CStruct* pStuff )\r\n{\r\n\t// should only get called for pros,\r\n\t// otherwise we need to implement face texture loading\r\n\r\n\tDbg_MsgAssert(pStuff,(\"NULL pStuff\"));\r\n\t\r\n\tScript::CStruct *pSkaterInfo=NULL;\r\n\tpStuff->GetStructure(SkaterName,&pSkaterInfo);\r\n\t// If no skater, just return. Could be no skater if a new skater name has been added, but autoloading off\r\n\t// a memory card with no info for that skater, so no assert.\r\n\tif (!pSkaterInfo)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\t\r\n\tScript::CStruct *pTemp=NULL;\r\n\t\r\n\t// There may not be an Appearance member, eg for the Pros.\t\r\n\tif (pSkaterInfo->GetStructure( CRCD(0x554c7d6f,\"Appearance\"), &pTemp ))\r\n\t{\r\n\t\tm_Appearance.Load(pTemp);\r\n\t}\t\r\n\t\t\r\n\tpTemp=NULL;\r\n\tpSkaterInfo->GetStructure( CRCD(0x3476cea8,\"Info\"), &pTemp );\r\n\tm_Info.Clear();\r\n\tm_Info.AppendStructure( pTemp);\r\n\t\r\n\t// First deck is always unlocked, so make sure this is the default just in case DeckFlags is not found.\r\n\tint DeckFlags=1;\r\n\tpSkaterInfo->GetInteger( CRCD(0x95388a60,\"DeckFlags\"), &DeckFlags );\r\n\t\r\n\t//Front::SetDeckFlags(SkaterName,(uint32)DeckFlags);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CSkaterProfile::GetStatValue( uint32 property )\r\n{\r\n\tint value;\r\n\tm_Info.GetInteger( property, &value, true );\r\n\treturn value;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterProfile::SetPropertyValue( uint32 property, int value )\r\n{\r\n\tif ( value >= 0 && value <= 10 )\r\n\t{\r\n\t\tm_Info.AddInteger( property, value );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterProfile::AwardStatPoint( int inc_val )\r\n{\r\n\tint value;\r\n\tm_Info.GetInteger( CRCD(0x471fc4dd,\"points_available\"), &value, true );\r\n\tvalue+=inc_val;\r\n\tm_Info.AddComponent( CRCD(0x471fc4dd,\"points_available\"), ESYMBOLTYPE_INTEGER, value );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CSkaterProfile::GetNumStatPointsAvailable()\r\n{\r\n\tint value;\r\n\tm_Info.GetInteger( CRCD(0x471fc4dd,\"points_available\"), &value, true );\r\n\treturn value;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterProfile::AwardSpecialTrickSlot( int inc_val )\r\n{\r\n\tint value;\r\n\tm_Info.GetInteger( CRCD(0xac9b9eda,\"max_specials\"), &value, true );\r\n\tvalue+=inc_val;\r\n\tm_Info.AddComponent( CRCD(0xac9b9eda,\"max_specials\"), ESYMBOLTYPE_INTEGER, value );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CSkaterProfile::GetNumSpecialTrickSlots( void )\r\n{\r\n\tint value;\r\n\tm_Info.GetInteger( CRCD(0xac9b9eda,\"max_specials\"), &value, true );\r\n\treturn value;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSSpecialTrickInfo CSkaterProfile::GetSpecialTrickInfo( int slot_num )\r\n{\t\r\n\tSSpecialTrickInfo theInfo;\r\n\t\r\n\tScript::CStruct* pStructure = GetSpecialTricksStructure();\r\n\tDbg_Assert( pStructure );\r\n\r\n\tScript::CArray* pArray;\r\n\tpStructure->GetArray( NONAME, &pArray, true );\r\n\tDbg_MsgAssert( pArray->GetSize() == vMAXSPECIALTRICKSLOTS, ( \"Expected %i elements in specials array instead of %d\", vMAXSPECIALTRICKSLOTS, pArray->GetSize() ) );\r\n\r\n\tif ( !(slot_num >= 0 && slot_num < (int)pArray->GetSize()) )\r\n\t{\r\n\t\tScript::PrintContents( &m_Info );\r\n\t\tScript::PrintContents( pStructure );\r\n\t\tDbg_MsgAssert( 0, ( \"Slot index %d is out of range (must be between 0 and %d\", slot_num, vMAXSPECIALTRICKSLOTS ) );\r\n\t}\r\n\t\r\n\tScript::CStruct* pSubStructure = pArray->GetStructure( slot_num );\r\n\tpSubStructure->GetChecksum( CRCD(0x5b077ce1,\"trickname\"), &theInfo.m_TrickName, true );\r\n\tpSubStructure->GetChecksum( CRCD(0xa92a2280,\"trickslot\"), &theInfo.m_TrickSlot, true );\r\n\tint is_cat = 0;\r\n\tpSubStructure->GetInteger( CRCD(0xb56a8816,\"isCat\"), &is_cat, false );\r\n\tif ( is_cat != 0 )\r\n\t{\r\n\t\ttheInfo.m_isCat = true;\r\n\t}\r\n\t\r\n\treturn theInfo;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterProfile::SetSpecialTrickInfo( int slot_num, const SSpecialTrickInfo& theInfo, bool update_mappings )\r\n{\r\n\tScript::CStruct* pStructure = GetSpecialTricksStructure();\r\n\tDbg_Assert( pStructure );\r\n\r\n\tScript::CArray* pArray;\r\n\tpStructure->GetArray( NONAME, &pArray, true );\r\n\tDbg_MsgAssert( pArray->GetSize() == vMAXSPECIALTRICKSLOTS, ( \"Expected %i elements in specials array instead of %d\", vMAXSPECIALTRICKSLOTS, pArray->GetSize() ) );\r\n\r\n\tif ( !(slot_num >= 0 && slot_num < (int)pArray->GetSize()) )\r\n\t{\r\n\t\t// out of range index...\r\n\t\t// this is possible if you press the square button while on the \"Done\" element\r\n\t\t// this isn't the best place to screen this out, but it's the safest...\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tuint32 trickName = theInfo.m_TrickName;\r\n\tuint32 trickSlot = theInfo.m_TrickSlot;\r\n\r\n\tif ( theInfo.IsUnassigned() )\r\n\t{\r\n\t\t// if the incoming trick is \"unassigned\"\r\n\t\t// then clear that slot\r\n\t\ttrickName = CRCD(0xf60c9090,\"unassigned\");\r\n\t\ttrickSlot = CRCD(0xf60c9090,\"unassigned\");\r\n\t}\r\n\t\r\n\tScript::CStruct* pSubStructure = pArray->GetStructure( slot_num );\r\n\tpSubStructure->AddComponent( CRCD(0x5b077ce1,\"trickname\"), ESYMBOLTYPE_NAME, (int)trickName );\r\n\tpSubStructure->AddComponent( CRCD(0xa92a2280,\"trickslot\"), ESYMBOLTYPE_NAME, (int)trickSlot );\r\n\r\n\tif ( theInfo.m_isCat )\r\n\t{\r\n\t\tpSubStructure->AddInteger( CRCD(0xb56a8816,\"isCat\"), 1 );\r\n\t}\r\n\telse\r\n\t\tpSubStructure->RemoveComponent( CRCD(0xb56a8816,\"isCat\") );\r\n\r\n\t// now that a trick config has changed,\r\n\t// update the trick mappings on any existing skaters\r\n\tif ( update_mappings )\r\n\t{\r\n        Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n        Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n        if ( pSkater )\r\n         {\r\n            Obj::CTrickComponent* pTrickComponent = GetTrickComponentFromObject(pSkater);\r\n    \t\tDbg_Assert( pTrickComponent );\r\n    \t\tpTrickComponent->UpdateTrickMappings( this );\r\n        }\r\n\t}\r\n\tScript::RunScript( CRCD(0xfab5c6eb,\"disable_replays\") );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tCSkaterProfile::GetChecksumValue( uint32 field_id )\r\n{\r\n\tuint32 value = 0;\r\n\r\n\tswitch ( field_id )\r\n\t{\r\n\t\tcase 0xc15dbf86:\t// pushstyle\r\n\t\t{\r\n\t\t\tm_Info.GetChecksum( CRCD(0xc15dbf86,\"pushstyle\"), &value, true );\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase 0x7d02bcc3:\t// stance\r\n\t\t{\r\n\t\t\tm_Info.GetChecksum( CRCD(0x7d02bcc3,\"stance\"), &value, true );\r\n\t\t}\r\n\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, (\"Unrecognized property %s\", Script::FindChecksumName(field_id) ) );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\treturn value;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterProfile::SetSkaterProperty( uint32 field_id, const char* pPropertyString )\r\n{\r\n\tDbg_Message(\"Stub:  setting skater property %s: %s\", Script::FindChecksumName(field_id), pPropertyString);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStr::String\tCSkaterProfile::GetUIString( const char* pFieldName )\r\n{\r\n\treturn GetUIString( Script::GenerateCRC( pFieldName ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStr::String\tCSkaterProfile::GetUIString( uint32 fieldID )\r\n{\r\n\treturn \"Unimplemented\";\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* CSkaterProfile::GetTrickMapping( uint32 TrickMappingName )\r\n{\r\n\t// pTrickMapping must be \"trick_mapping\"...  specials are accessed through special trick slots\r\n\tDbg_Assert( TrickMappingName==CRCD(0xd544aa2d,\"trick_mapping\") );\r\n\t\r\n\tScript::CStruct* pTrickMappingStructure;\r\n\tm_Info.GetStructure(TrickMappingName,&pTrickMappingStructure,Script::ASSERT);\r\n\treturn pTrickMappingStructure;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* CSkaterProfile::GetSpecialTricksStructure()\r\n{\r\n\tScript::CStruct* pTrickMappingStructure;\r\n\tm_Info.GetStructure( CRCD(0xddbee809,\"specials\"), &pTrickMappingStructure, Script::ASSERT);\r\n\treturn pTrickMappingStructure;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CSkaterProfile::GetSkaterNameChecksum( void )\r\n{\r\n\tuint32 checksum;\r\n\tm_Info.GetChecksum( CRCD(0xa1dc81f9,\"name\"), &checksum, true );\r\n\treturn checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterProfile::IsPro()\r\n{\r\n\tint is_pro;\r\n\tm_Info.GetInteger( CRCD(0xd82f8ac8,\"is_pro\"), &is_pro, true );\r\n\treturn is_pro;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterProfile::HeadIsLocked()\r\n{\r\n\tint is_locked;\r\n\tm_Info.GetInteger( CRCD(0x09f350e5,\"is_head_locked\"), &is_locked, true );\r\n\treturn is_locked;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterProfile::IsLocked()\r\n{\r\n\tint is_locked;\r\n\tm_Info.GetInteger( CRCD(0x4564bab1,\"is_locked\"), &is_locked, true );\r\n\treturn is_locked;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterProfile::IsSecret()\r\n{\r\n\treturn m_Info.ContainsFlag( CRCD(0xf3149ac5,\"is_secret\") );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterProfile::SetHeadIsLocked( bool is_locked )\r\n{\r\n\tm_Info.AddComponent( CRCD(0x09f350e5,\"is_head_locked\"), ESYMBOLTYPE_INTEGER, (int)is_locked );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char *CSkaterProfile::GetCASFileName()\r\n{\r\n\tconst char *p_file_name=\"Unimplemented\";\r\n\tm_Info.GetString( CRCD(0xf36c1878,\"CASFileName\"), &p_file_name);\r\n\treturn p_file_name;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterProfile::SetCASFileName(const char *pFileName)\r\n{\r\n\tm_Info.AddString( CRCD(0xf36c1878,\"CASFileName\"), pFileName );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char* CSkaterProfile::GetDisplayName()\r\n{\r\n\tconst char* pDisplayName;\r\n\tm_Info.GetText( CRCD(0x2ab66cb8,\"display_name\"), &pDisplayName, Script::ASSERT );\r\n\treturn pDisplayName;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterProfile::ResetDefaultAppearance()\r\n{\r\n\tDbg_Message( \"Stub:  Reset appearance here\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterProfile::ResetDefaultStats()\r\n{\r\n\tDbg_Message( \"Stub:  Reset stats here\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterProfile::ResetDefaultTricks()\r\n{\r\n\tDbg_Message( \"Stub:  Reset tricks here\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n"
  },
  {
    "path": "Code/Sk/Objects/SkaterProfile.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       SkaterProfile.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  11/29/2000\r\n//****************************************************************************\r\n\r\n#ifndef __OBJECTS_SKATERPROFILE_H\r\n#define __OBJECTS_SKATERPROFILE_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <gfx/modelappearance.h>\r\n#include <sk/objects/skatertricks.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// TODO:  Eventually, rename this CPlayerProfile,\r\n// and subclass to get the CSkaterProfile\r\n\r\n\r\nclass CSkaterProfile : public Spt::Class\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvVERSION_NUMBER = 2,\r\n\t\tvMAXSPECIALTRICKSLOTS = 12,\r\n\t};\r\n\r\npublic:\r\n\t// slowly phase this first constructor out\r\n\tCSkaterProfile();\t\t\t\t\t\t\t// set up default profile\r\n\tCSkaterProfile( Script::CStruct* pParams );\r\n\tCSkaterProfile( const CSkaterProfile& rhs );\r\n\tCSkaterProfile&\toperator=( const CSkaterProfile& rhs );\r\n\r\npublic:\r\n\tuint32\t\t\t\t\t\tWriteToBuffer(uint8 *pBuffer, uint32 BufferSize, \r\n\t\t\t\t\t\t\t\t\t\t\tbool ignoreFaceData = false );\r\n\tuint8*\t\t\t\t\t\tReadFromBuffer(uint8 *pBuffer);\r\n\tvoid \t\t\t\t\t\tWriteIntoStructure( Script::CStruct* pStuff );\r\n\tvoid \t\t\t\t\t\tReadFromStructure( uint32 SkaterName, Script::CStruct* pStuff );\r\n\r\n\tbool\t\t\t\t\t\tReset( Script::CStruct* pParams = NULL );\t\t\t\t\t\t// reset to initial conditions\r\n    bool\t\t\t\t\t\tPartialReset( Script::CStruct* pParams = NULL );\t\t\t\t// reset non story stuff\r\n\t\r\n\t// for querying whether the profile meets certain criteria (i.e. is vert skater?  is rodney mullen?)\r\n\tbool\t\t\t\t\t\tProfileEquals( Script::CStruct* pStructure );\r\n\t\r\n\tvoid\t\t\t\t\t\tResetDefaultAppearance();\t\t\t\t\t\t\t\t\t\t   \t\r\n\tvoid\t\t\t\t\t\tResetDefaultTricks();\r\n\tvoid\t\t\t\t\t\tResetDefaultStats();\r\n\t\r\npublic:\r\n\t// general accessors\r\n\tGfx::CModelAppearance*\t\tGetAppearance() {return &m_Appearance;}\r\n\tScript::CStruct*\t\t\tGetInfo() {return &m_Info;}\r\n\t\r\n\t// query functions\r\n\tuint32\t\t\t\t\t\tGetSkaterNameChecksum();\r\n\tScript::CStruct*\t\t\tGetTrickMapping( uint32 TrickMappingName );\r\n\tScript::CStruct*\t\t\tGetSpecialTricksStructure();\r\n\tvoid\t\t\t\t\t\tSetHeadIsLocked( bool is_locked );\r\n\tbool\t\t\t\t\t\tIsPro();\r\n\tbool\t\t\t\t\t\tIsSecret();\r\n\tbool\t\t\t\t\t\tHeadIsLocked();\r\n\tbool\t\t\t\t\t\tIsLocked();\r\n\tconst char*\t\t\t\t\tGetCASFileName();\r\n\tvoid\t\t\t\t\t\tSetCASFileName(const char *pFileName);\r\n\t\r\n\t// UI\r\n\tvoid\t\t\t\t\t\tSetSkaterProperty( uint32 fieldId, const char* pPropertyName );\r\n\tconst char*\t\t\t\t\tGetDisplayName();\r\n\tuint32\t\t\t\t\t\tGetChecksumValue( uint32 field_id );\r\n\tStr::String\t\t\t\t\tGetUIString( uint32 field_id );\r\n\tStr::String\t\t\t\t\tGetUIString( const char* field_name );\r\n\t\r\n\t// stats\r\n\tint\t\t\t\t\t\t\tGetStatValue( uint32 property );\r\n\tbool\t\t\t\t\t\tSetPropertyValue( uint32 property, int value );\r\n\tbool\t\t\t\t\t\tAwardStatPoint( int inc_val = 1 );\r\n\tint\t\t\t\t\t\t\tGetNumStatPointsAvailable();\r\n\t\r\n\t// tricks\r\n\tbool\t\t\t\t\t\tAwardSpecialTrickSlot( int inc_val = 1 );\r\n\tuint32\t\t\t\t\t\tGetNumSpecialTrickSlots();\r\n\tSSpecialTrickInfo\t\t\tGetSpecialTrickInfo( int slot_num );\r\n\tbool\t\t\t\t\t\tSetSpecialTrickInfo( int slot_num, const SSpecialTrickInfo& theInfo, bool update_mappings = true );\r\n\r\nprotected:\r\n\tvoid\t\t\t\t\t\tcompress_trick_mappings( const char* pTrickMappingName );\r\n\tvoid\t\t\t\t\t\tdecompress_trick_mappings( const char* pTrickMappingName );\r\n\t\r\nprotected:\r\n\t// net packet compression\r\n\tuint32\t\t\t\t\t\twrite_extra_info_to_buffer(uint8* pBuffer, uint32 BufferSize);\r\n\tuint8*\t\t\t\t\t\tread_extra_info_from_buffer(uint8* pBuffer);\r\n\r\nprivate:\r\n\tGfx::CModelAppearance\t\tm_Appearance;\r\n\tScript::CStruct\t\t\t\tm_Info;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_SKATERPROFILE_H\r\n\r\n#if 0\r\n\t// UI\r\n\tvoid\t\t\t\t\t\tSetSkaterProperty( uint32 fieldId, int value );\r\n\tint\t\t\t\t\t\t\tGetUIValue( uint32 checksum );\r\n\tStr::String\t\t\t\t\tGetUIString( uint32 checksum );\r\n#endif\r\n\r\n#if 0\r\n\t// temp functions\r\n\tbool\t\t\t\t\t\tpart_matches( uint32 list_name, uint32 desc_name, Script::CStruct* pIfStructure );\r\n\tbool\t\t\t\t\t\tsponsor_is_disqualified( uint32 partChecksum, uint32 descChecksum, Script::CArray* pSponsorArray );\r\n\tbool\t\t\t\t\t\tpart_is_disqualified( uint32 list_name, uint32 desc_id );\r\n\tbool\t\t\t\t\t\tappearance_currently_contains( Script::CStruct* pIfStructure );\r\n#endif\r\n\r\n#if 0\r\n\t// for setting up the skater model\r\n\tbool\t\t\t\t\t\tPartIsDisqualified( uint32 list_name, uint32 desc_id );\r\n\tbool\t\t\t\t\t\tColorModulationAllowed( uint32 list_name );\r\n\t\r\n\tbool\t\t\t\t\t\tSetCASOption(uint32 setName, const char* pDesiredName);\r\n\tbool\t\t\t\t\t\tSetOption(uint32 setName, uint32 descId);\r\n\r\n\tvoid\t\t\t\t\t\tSetHue( uint32 setName, int value );\r\n\tvoid\t\t\t\t\t\tSetSaturation( uint32 setName, int value );\r\n\tvoid\t\t\t\t\t\tSetValue( uint32 setName, int value );\r\n\t\r\n\tint\t\t\t\t\t\t\tGetNumOptions( uint32 list_name );\r\n\tStr::String\t\t\t\t\tOptionName( uint32 list_name, int i );\r\n\tuint32\t\t\t\t\t\tOptionId( uint32 list_name, int i );\r\n\tbool\t\t\t\t\t\tOptionSelected( uint32 list_name, int i );\r\n\tbool\t\t\t\t\t\tOptionDisqualified( uint32 list_name, int i );\r\n\tuint32\t\t\t\t\t\tCurrentOption( uint32 list_name );\r\n\tStr::String\t\t\t\t\tGetOptionNameFromDescId( uint32 list_name, uint32 desc_id );\r\n\tvoid\t\t\t\t\t\tRandomizeAppearance();\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/SkaterTricks.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObjects (OBJ) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobjects/SkaterTricks.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t10/29/01\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSkater tricks code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/objects/skatertricks.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/struct.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSSpecialTrickInfo::SSpecialTrickInfo()\r\n{\r\n\tm_isCat = false;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool SSpecialTrickInfo::IsUnassigned ( void ) const\r\n{\r\n\treturn m_TrickName == Script::GenerateCRC( \"Unassigned\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStr::String SSpecialTrickInfo::GetTrickNameString ( void ) const\r\n{\r\n\tif ( IsUnassigned() )\r\n\t{\r\n\t\treturn Script::GetLocalString( \"sp_str_unassigned\" );\r\n\t}\r\n\r\n\tScript::CScriptStructure* pTrickStructure;\r\n\tif ( ( Script::GetStructure( m_TrickName, Script::ASSERT ) )->GetStructure( \"params\", &pTrickStructure ) )\r\n\t{\r\n\t\t// get the trick name\r\n\t\tconst char* pTrickName;\r\n\t\tpTrickStructure->GetLocalText( \"name\", &pTrickName, true );\r\n\t\treturn pTrickName;\r\n\t}\r\n\r\n\treturn \"Unknown\";\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStr::String SSpecialTrickInfo::GetTrickSlotString ( void ) const\r\n{\r\n\tif ( IsUnassigned() )\r\n\t{\r\n\t\treturn Script::GetLocalString( \"sp_str_unassigned\" );\r\n\t}\r\n\r\n\tScript::CArray* pButtonArray = Script::GetArray( \"SpecialCombos\" );\r\n\tDbg_Assert( pButtonArray );\r\n\r\n\tfor ( int i = 0; i < (int)pButtonArray->GetSize(); i++ )\r\n\t{\r\n\t\tScript::CScriptStructure* pStructure = pButtonArray->GetStructure( i );\r\n\t\tDbg_Assert( pStructure );\r\n\r\n\t\tuint32 currTrickSlot;\r\n\t\tpStructure->GetChecksum( \"trickslot\", &currTrickSlot, true );\r\n\r\n\t\tif ( currTrickSlot == m_TrickSlot )\r\n\t\t{\r\n\t\t\tconst char* pTrickSlotString;\r\n\t\t\tpStructure->GetText( \"desc\", &pTrickSlotString, true );\r\n\t\t\treturn pTrickSlotString;\r\n\t\t}\t\r\n\t}\r\n\r\n\treturn \"Unknown\";\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nStr::String SSpecialTrickInfo::GetSlotMenuProperty ( void ) const\r\n{\r\n\tif ( IsUnassigned() )\r\n\t{\r\n\t\treturn \"trick_menu_property\";\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn \"trickslot_menu_property\";\r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTrickChecksumTable::CTrickChecksumTable( void )\r\n{\r\n\tm_NumChecksums = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTrickChecksumTable::Init( void )\r\n{\r\n\tm_NumChecksums = 0;\r\n\r\n\tScript::CArray* pArray = Script::GetArray( \"ConfigurableTricks\" );\r\n\r\n\tfor ( int i = 0; i < (int)pArray->GetSize(); i++ )\r\n\t{\r\n\t\tuint32 trickChecksum = pArray->GetNameChecksum( i );\r\n\r\n\t\t// not found\r\n\t\tif ( GetIndexFromChecksum( trickChecksum ) == -1 )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( m_NumChecksums < vMAX_TRICK_CHECKSUMS, (\"Too many trick checksums (limit = %d)\", vMAX_TRICK_CHECKSUMS) );\r\n\t\t\tm_Checksum[m_NumChecksums] = trickChecksum;\r\n\t\t\tm_NumChecksums++;\r\n\t\t}\r\n\t}\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CTrickChecksumTable::GetChecksumFromIndex( int index )\r\n{\r\n\t\t\r\n\tDbg_Assert( index >= 0 && index < m_NumChecksums );\r\n\r\n\treturn m_Checksum[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CTrickChecksumTable::GetIndexFromChecksum( uint32 checksum )\r\n{\r\n\tfor ( int i = 0; i < m_NumChecksums; i++ )\r\n\t{\r\n\t\tif ( checksum == m_Checksum[i] )\r\n\t\t{\r\n\t\t\t// found index\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\r\n\t// not found\r\n\treturn -1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n"
  },
  {
    "path": "Code/Sk/Objects/SkaterTricks.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObject (OBJ)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobjects/SkaterTricks.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t10/29/01\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __OBJECTS_SKATERTRICKS_H\r\n#define __OBJECTS_SKATERTRICKS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/string/cstring.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  SSpecialTrickInfo : public Spt::Class\r\n{\r\n\tpublic:\r\n\t\tuint32\tm_TrickName;\r\n\t\tuint32\tm_TrickSlot;\r\n\t\tbool\tm_isCat;\r\n\r\n\tpublic:\r\n\t\tSSpecialTrickInfo();\r\n\t\tbool\t\t\tIsUnassigned() const;\r\n\t\tStr::String\t\tGetTrickNameString() const;\r\n\t\tStr::String\t\tGetTrickSlotString() const;\r\n\t\tStr::String\t\tGetSlotMenuProperty() const;\r\n};\r\n\r\nclass CTrickChecksumTable : public Spt::Class\r\n{\r\n\tenum\r\n\t{\r\n\t\t// must be 256 or less, otherwise\r\n\t\t// the trick mapping database might\r\n\t\t// not compress to an acceptable size\r\n\t\tvMAX_TRICK_CHECKSUMS = 256\r\n\t};\r\n\r\n\tpublic:\r\n\t\tCTrickChecksumTable();\r\n\r\n\tpublic:\r\n\t\tvoid\t\t\tInit( void );\r\n\t\tuint32\t\t\tGetChecksumFromIndex( int index );\r\n\t\tint\t\t\t\tGetIndexFromChecksum( uint32 checksum );\r\n\r\n\tprotected:\r\n\t\tuint32\t\t\tm_Checksum[vMAX_TRICK_CHECKSUMS];\r\n\t\tint\t\t\t\tm_NumChecksums;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_SKATERTRICKS_H\r\n"
  },
  {
    "path": "Code/Sk/Objects/TrickObject.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTrickObject (OBJ)\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tTrickObject.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/05/01\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\ttrick object code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/objects/trickobject.h>\r\n\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n\r\n#include <gfx/gfxutils.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxsector.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/modules/skate/goalmanager.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/skater.h>\t\t   // just needed in mygetassociatednetworkconnection\r\n\r\n#include <sys/config/config.h>\r\n\r\n#include <sk/components/RailEditorComponent.h>\r\n\r\n#ifdef __NOPT_ASSERT__\t\r\n//#include <sk/ParkEditor/ParkEd.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefinePoolableClass(Lst::HashItem<Obj::CTrickCluster>);\r\n\r\n\r\nenum\r\n{\r\n\tvMAX_TRICKS_TO_FREE = 128\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n   \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTrickObject::CTrickObject( void ) : Lst::Node< CTrickObject >(this)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTrickObject::CTrickObject( uint32 name_checksum ) : Lst::Node< CTrickObject >(this)\r\n{\r\n\tm_NameChecksum = name_checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickObject::InitializeTrickObjectColor( int seqIndex )\r\n{\r\n\t// Garrett: shouldn't need to do anything except clear color here\r\n\t// checks for the wibbling data, and creates\r\n\t// it if it doesn't already exist\r\n\r\n\t// TODO:  Should also screen out if it doesn't have any geometry\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(m_NameChecksum);\t\t\t\t\r\n\tDbg_MsgAssert(p_sector,(\"sGetSector(0x%x) returned NULL (%s)\",m_NameChecksum,Script::FindChecksumName(m_NameChecksum)));\r\n\tp_sector->ClearColor();\r\n\tif (!Config::CD())\r\n\t{\r\n\t\tif ( Script::GetInt( \"show_all_trick_objects\", false ) )\r\n\t\t{\r\n\t\t\t// quick way to see all the trick objects in the scene\r\n\t\t\tModulateTrickObjectColor( 2 );\r\n\t\t}\r\n\t}\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickObject::ModulateTrickObjectColor( int seqIndex )\r\n{\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(m_NameChecksum);\t\t\t\t\r\n\tDbg_MsgAssert(p_sector,(\"sGetSector(0x%x) returned NULL (%s)\",m_NameChecksum,Script::FindChecksumName(m_NameChecksum)));\r\n\r\n\tScript::CArray* p_graffiti_col_tab = Script::GetArray( \"graffitiColors\" );\r\n\tDbg_MsgAssert( (uint) seqIndex < p_graffiti_col_tab->GetSize(), ( \"graffitiColors array too small\" ) );\r\n\r\n\tScript::CArray *p_entry = p_graffiti_col_tab->GetArray(seqIndex);\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tint size = p_entry->GetSize();\r\n\tDbg_MsgAssert(size >= 3 && size <= 4, (\"wrong size %d for color array\", size));\r\n\t#endif\r\n\t\r\n\tImage::RGBA color;\r\n\r\n\tcolor.r = p_entry->GetInteger( 0 );\r\n\tcolor.g = p_entry->GetInteger( 1 );\r\n\tcolor.b = p_entry->GetInteger( 2 );\r\n\tcolor.a = 128;\r\n\r\n\tp_sector->SetColor(color);\r\n\treturn true;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickObject::ClearTrickObjectColor( int seqIndex )\r\n{\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(m_NameChecksum);\t\t\t\t\r\n\tDbg_MsgAssert(p_sector,(\"sGetSector(0x%x) returned NULL (%s)\",m_NameChecksum,Script::FindChecksumName(m_NameChecksum)));\r\n\r\n\tScript::CArray* p_graffiti_col_tab = Script::GetArray( \"graffitiColors\" );\r\n\tDbg_MsgAssert( (uint) seqIndex < p_graffiti_col_tab->GetSize(), ( \"graffitiColors array too small\" ) );\r\n\r\n\tScript::CArray *p_entry = p_graffiti_col_tab->GetArray(seqIndex);\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tint size = p_entry->GetSize();\r\n\tDbg_MsgAssert(size >= 3 && size <= 4, (\"wrong size %d for color array\", size));\r\n\t#endif\r\n\r\n\tImage::RGBA color;\r\n\r\n\tcolor.r = p_entry->GetInteger( 0 );\r\n\tcolor.g = p_entry->GetInteger( 1 );\r\n\tcolor.b = p_entry->GetInteger( 2 );\r\n\tcolor.a = 128;\r\n\r\n\tImage::RGBA orig_color = p_sector->GetColor();\r\n\tif ((orig_color.r == color.r) &&\r\n\t\t(orig_color.g == color.g) &&\r\n\t\t(orig_color.b == color.b))\r\n\t{\r\n\t\tp_sector->ClearColor();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTrickCluster::CTrickCluster( void ) : Lst::Node< CTrickCluster >(this)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTrickCluster::CTrickCluster( uint32 name_checksum ) : Lst::Node< CTrickCluster >(this)\r\n{\r\n\t\r\n\r\n\tm_NameChecksum = name_checksum;\r\n\r\n\tReset();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTrickCluster::~CTrickCluster( void )\r\n{\r\n\t\r\n\r\n\tuint32 count = m_TrickObjectList.CountItems();\r\n\r\n\t// first iterate through all the items,\r\n\t// and destroy the associated objects\r\n\tfor ( uint32 i = 0; i < count; i++ )\r\n\t{\r\n\t\tLst::Node< CTrickObject >* pNode = m_TrickObjectList.GetItem( 0 );\r\n\t\tDbg_Assert( pNode );\r\n\t\tCTrickObject* pObject = pNode->GetData();\r\n\t\tDbg_Assert( pObject );\r\n\t\tdelete pObject;\r\n\t}\r\n\r\n\t// now remove all the nodes from the list\r\n\tm_TrickObjectList.RemoveAllNodes();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CTrickCluster::GetScore( uint32 skater_id )\r\n{\r\n\treturn ( m_IsOwned && (skater_id == m_OwnerId) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickCluster::Reset( void )\r\n{\r\n\t\r\n\r\n\tm_Score = 0;\r\n\tm_OwnerId = 0;\r\n\tm_IsOwned = false;\t// no owner\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCTrickCluster::ModulateTrickObjectColor( int seqIndex )\r\n{\r\n\t\r\n\r\n\tuint32 count = m_TrickObjectList.CountItems();\r\n\r\n\tfor ( uint32 i = 0; i < count; i++ )\r\n\t{\r\n\t\tLst::Node< CTrickObject >* pNode = m_TrickObjectList.GetItem( i );\r\n\t\tDbg_Assert( pNode );\r\n\t\tCTrickObject* pObject = pNode->GetData();\r\n\t\tDbg_Assert( pObject );\r\n\t\tpObject->ModulateTrickObjectColor( seqIndex );\r\n\t}\r\n\r\n\t// If playing a created park, update any created rails for this cluster.\r\n\tMdl::Skate * p_skate_mod =  Mdl::Skate::Instance();\r\n\tif (p_skate_mod->m_cur_level == CRCD(0xb664035d,\"load_sk5ed_gameplay\"))\r\n\t{\r\n\t\tObj::GetRailEditor()->ModulateRailColor(m_NameChecksum, seqIndex);\r\n\t}\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTrickObject* CTrickCluster::find_trick_object( uint32 name_checksum )\r\n{\r\n\t\r\n\r\n\tuint32 count = m_TrickObjectList.CountItems();\r\n\r\n\t// find the appropriate trick object\r\n\tfor ( uint32 i = 0; i < count; i++ )\r\n\t{\r\n\t\tLst::Node< CTrickObject >* pNode = m_TrickObjectList.GetItem( i );\r\n\t\tDbg_Assert( pNode );\r\n\t\tCTrickObject* pObject = pNode->GetData();\r\n\t\tDbg_Assert( pObject );\r\n\r\n\t\tif ( pObject->m_NameChecksum == name_checksum )\r\n\t\t{\r\n\t\t\treturn pObject;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickCluster::AddTrickObject( uint32 name_checksum )\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert( !find_trick_object( name_checksum ),( \"Trick object %s is already in list\", Script::FindChecksumName(name_checksum) ));\r\n\t\r\n\tCTrickObject* pObject = new CTrickObject( name_checksum );\r\n\r\n\tif ( !pObject )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif ( pObject->InitializeTrickObjectColor( name_checksum ) )\r\n\t{\r\n//\t\tprintf( \"Adding %s to trick object list\\n\", Script::FindChecksumName( name_checksum ) );\r\n\t\tm_TrickObjectList.AddToTail( pObject );\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// if not valid\r\n\t\tdelete pObject;\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTrickObjectManager::CTrickObjectManager( void ) : m_TrickClusterList(8), m_TrickAliasList(8)\r\n{\r\n//\tm_TrickAliasCount = 0;\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\r\n\tmp_ObserverState = new Script::CScriptStructure;\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTrickObjectManager::~CTrickObjectManager( void )\r\n{\r\n\tthis->DeleteAllTrickObjects();\r\n}\r\n\r\nstruct STrickObjectFreeInfo\r\n{\r\n\tuint32\tskater_id;\t\t\t// which objects to free\r\n\tuint32\tnum_tricks;\t\t\t// num tricks to free\r\n\tuint32\ttrick_buffer[vMAX_TRICKS_TO_FREE];\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickCluster::FreeCluster( uint32 skater_id )\r\n{\r\n\tif ( this->m_IsOwned && ( this->m_OwnerId == skater_id ) )\r\n\t{\r\n\t\tthis->m_IsOwned = false;\r\n\t\tthis->m_Score = 0;\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickCluster::ClearCluster( int seqIndex )\r\n{\r\n\r\n\tuint32 count = m_TrickObjectList.CountItems();\r\n\r\n\t// find the appropriate trick object\r\n\tfor ( uint32 i = 0; i < count; i++ )\r\n\t{\r\n\t\tLst::Node< CTrickObject >* pNode = m_TrickObjectList.GetItem( i );\r\n\t\tDbg_Assert( pNode );\r\n\t\tCTrickObject* p_object = pNode->GetData();\r\n\t\tDbg_Assert( p_object );\r\n\r\n\t\tif (!p_object->ClearTrickObjectColor(seqIndex))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// If playing a created park, clear any created rail colors for this cluster.\r\n\tMdl::Skate * p_skate_mod =  Mdl::Skate::Instance();\r\n\tif (p_skate_mod->m_cur_level == CRCD(0xb664035d,\"load_sk5ed_gameplay\"))\r\n\t{\r\n\t\tObj::GetRailEditor()->ClearRailColor(m_NameChecksum);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid free_trick_cluster(CTrickCluster* pCluster, void* pData)\r\n{\t\r\n\tDbg_AssertPtr(pCluster);\r\n\tDbg_AssertPtr(pData);\r\n\r\n\tSTrickObjectFreeInfo* pFreeInfo = (STrickObjectFreeInfo*)pData;\r\n\r\n\tif ( pCluster->FreeCluster( pFreeInfo->skater_id ) )\r\n\t{\r\n\t\tDbg_MsgAssert( pFreeInfo->num_tricks < vMAX_TRICKS_TO_FREE, ( \"Too many trick objects to free\" ) );\r\n\t\tpFreeInfo->trick_buffer[pFreeInfo->num_tricks] = pCluster->GetNameChecksum();\t\t\r\n\t\tpFreeInfo->num_tricks++;\r\n\r\n#ifdef __USER_GARY__\r\n\t\tDbg_Message( \"Freeing up %s\\n\", Script::FindChecksumName(pCluster->GetNameChecksum()) );\r\n#endif\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickObjectManager::FreeTrickObjects( uint32 skater_id )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n    \r\n\t// clear the observer state when you exit the game\r\n\tprintf( \"Clearing observer state\\n\" );\r\n\tmp_ObserverState->Clear();\r\n\t\r\n    if( gamenet_man->OnServer())\r\n\t{\r\n\t\tSTrickObjectFreeInfo theFreeInfo;\r\n\t\ttheFreeInfo.skater_id = skater_id;\r\n\t\ttheFreeInfo.num_tricks = 0;\r\n\r\n\t\tm_TrickClusterList.HandleCallback(free_trick_cluster, (void*)&theFreeInfo);\r\n\r\n\t\tif ( theFreeInfo.num_tricks <= 0 )\r\n\t\t{\r\n\t\t\t// no tricks to free\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// send score updates, as something has changed\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tskate_mod->SendScoreUpdates( false );\r\n\t}\r\n    \r\n\tclear_trick_clusters(skater_id + 1);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CTrickObjectManager::TrickObjectExists( uint32 name_checksum ){\r\n\t// gets cluster checksum\r\n\tCTrickCluster* pCluster = get_aliased_cluster( name_checksum );\r\n\tif ( pCluster )\r\n\t{\r\n\t\treturn pCluster->m_NameChecksum;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CTrickObjectManager::RequestLogTrick( uint32 num_pending_tricks, uint32* p_pending_tricks, char* p_inform_prev_owner, int skater_id, uint32 score )\r\n{\r\n    printf(\"RequestLogTrick called\\n\");\r\n\r\n// GJ:  Note that this function only logs the trick;  a message\r\n// will be sent out to the clients to actually modify the color\r\n\r\n\tuint32 i;\r\n\r\n\tDbg_Assert( p_pending_tricks );\r\n\tDbg_Assert( p_inform_prev_owner );\r\n\r\n\tDbg_Assert( num_pending_tricks < 128 );\r\n\tstatic char s_change_mask[128];\r\n\tfor ( i = 0; i < num_pending_tricks; i++ )\r\n\t{\r\n\t\ts_change_mask[i] = 0;\r\n\t}\r\n\r\n\tfor ( i = 0; i < num_pending_tricks; i++ )\r\n\t{\r\n\t\tCTrickCluster* pCluster = get_aliased_cluster( p_pending_tricks[i] );\r\n\r\n\t\t// change only objects marked as trick objects\r\n\t\tif ( !pCluster )\r\n\t\t\tcontinue;\r\n\r\n\t\t// tell the goal manager\r\n\t\tGame::CGoalManager* pGoalManager = Game::GetGoalManager();\r\n\t\tDbg_Assert( pGoalManager );\r\n\t\tpGoalManager->GotTrickObject( pCluster->GetNameChecksum(), score );\r\n\r\n\t\t// if the score beats the score\r\n\t\tif ( score > pCluster->m_Score )\r\n\t\t{\r\n            bool owner_changed = ( pCluster->m_OwnerId != (uint32)skater_id );\r\n\t\t\t\r\n\t\t\tif ( !pCluster->m_IsOwned || owner_changed )\r\n\t\t\t{\r\n\t\t\t\t// that the trick object has changed states\r\n\t\t\t\ts_change_mask[i] = 1;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif ( pCluster->m_IsOwned && owner_changed )\r\n\t\t\t{\r\n\t\t\t\t// for tracking steal messages\r\n\t\t\t\tDbg_Assert( pCluster->m_OwnerId >= 0 && pCluster->m_OwnerId < GameNet::vMAX_PLAYERS );\r\n\t\t\t\tp_inform_prev_owner[pCluster->m_OwnerId] = 1;\r\n\t\t\t}\r\n\r\n\t\t\tpCluster->m_OwnerId = skater_id;\r\n\t\t\tpCluster->m_Score = score;\r\n\t\t\tpCluster->m_IsOwned = true;\r\n\r\n/*            Game::CGoalManager* p_GoalManager = Game::GetGoalManager();\r\n            if ( p_GoalManager->IsInGraffitiGoal() )\r\n            {\r\n                p_GoalManager->GotGraffitiCluster( pCluster->GetNameChecksum() );\r\n                // printf(\"tricked in %s\\n\", Script::FindChecksumName( pCluster->GetNameChecksum() ) );\r\n            }\r\n*/\r\n\t\t}\r\n\t}\r\n\r\n\tuint32 num_changed = 0;\r\n\t\r\n\t// shift them so that the changed ones are at the beginning\r\n\tfor ( i = 0; i < num_pending_tricks; i++ )\r\n\t{\r\n\t\tif ( s_change_mask[i] )\r\n\t\t{\r\n\t\t\tp_pending_tricks[num_changed] = p_pending_tricks[i];\r\n\t\t\tnum_changed++;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn num_changed;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTrickCluster* CTrickObjectManager::GetTrickCluster( uint32 name_checksum )\r\n{\r\n\treturn find_trick_cluster( name_checksum );\r\n}\r\n\r\nstruct SAutoTrick\r\n{\r\n\tuint32\tpPendingTricks[32];\r\n\tuint32\tnumPendingTricks;\r\n};\r\n\r\nNet::Conn* MyGetAssociatedNetworkConnection( uint32 skater_id )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tObj::CSkater* skater;\r\n\tGameNet::PlayerInfo* player;\r\n\r\n\tskater = skate_mod->GetSkaterById( skater_id );\r\n\tif( skater )\r\n\t{\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( skater->GetID() );\r\n\t\tif( player )\r\n\t\t{\r\n\t\t\treturn player->m_Conn;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\nvoid MyLogTrickObject( int skater_id, int score, uint32 num_pending_tricks, uint32* p_pending_tricks, bool propagate )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tGameNet::MsgScoreLogTrickObject msg;\r\n\tGameNet::MsgObsScoreLogTrickObject obs_msg;\r\n\tNet::MsgDesc msg_desc;\r\n\tNet::Server* server;\r\n\tNet::Conn* conn;\r\n\tGameNet::PlayerInfo* player;\r\n\tLst::Search< GameNet::PlayerInfo > sh;\r\n\r\n\tif( propagate )\r\n\t{\r\n\t\tserver = gamenet_man->GetServer();\r\n\t\tDbg_Assert( server );\r\n\r\n\t\tconn = MyGetAssociatedNetworkConnection( skater_id );\r\n\r\n\t\t// keep track of whom we need to send the steal message to\r\n\t\tint i;\r\n\t\tchar previous_owner_flags[GameNet::vMAX_PLAYERS];\r\n\t\tfor ( i = 0; i < GameNet::vMAX_PLAYERS; i++ )\r\n\t\t{\r\n\t\t\tprevious_owner_flags[i] = 0;\r\n\t\t}\r\n\r\n\t\tnum_pending_tricks = skate_mod->GetTrickObjectManager()->RequestLogTrick( num_pending_tricks, p_pending_tricks, previous_owner_flags, skater_id, score );\r\n\r\n\t\tif ( !num_pending_tricks )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tfor ( i = 0; i < GameNet::vMAX_PLAYERS; i++ )\r\n\t\t{\r\n\t\t\tif ( previous_owner_flags[i] )\r\n\t\t\t{\r\n\t\t\t\t// GJ:  This only sends the stolen message to the two parties involved\r\n\r\n\t\t\t\tGameNet::PlayerInfo* pPlayerInfo;\r\n\t\t\t\tGameNet::MsgStealMessage steal_msg;\r\n\t\t\t\tNet::MsgDesc steal_msg_desc;\r\n\r\n\t\t\t\tsteal_msg.m_NewOwner = skater_id;\r\n\t\t\t\tsteal_msg.m_OldOwner = i;\r\n\t\t\t\tsteal_msg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\r\n\t\t\t\tpPlayerInfo = gamenet_man->GetPlayerByObjectID(skater_id);\r\n\t\t\t\tDbg_Assert( pPlayerInfo );\r\n\r\n\t\t\t\tsteal_msg_desc.m_Data = &steal_msg;\r\n\t\t\t\tsteal_msg_desc.m_Length = sizeof( GameNet::MsgStealMessage );\r\n\t\t\t\tsteal_msg_desc.m_Id = GameNet::MSG_ID_STEAL_MESSAGE;\r\n\t\t\t\tserver->EnqueueMessage( pPlayerInfo->GetConnHandle(), &steal_msg_desc );\r\n\r\n\t\t\t\tsteal_msg.m_NewOwner = skater_id;\r\n\t\t\t\tsteal_msg.m_OldOwner = i;\r\n\t\t\t\tsteal_msg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\r\n\t\t\t\tpPlayerInfo = gamenet_man->GetPlayerByObjectID(i);\r\n\t\t\t\t//Dbg_Assert( pPlayerInfo );\r\n\r\n\t\t\t\t// For now, don't assert if the player doesn't exist anymore. Just don't do anything.\r\n\t\t\t\t// Eventually, Gary will fix this so that pieces of exiting players are reset\r\n\t\t\t\tif( pPlayerInfo )\r\n\t\t\t\t{\r\n\t\t\t\t\tserver->EnqueueMessage( pPlayerInfo->GetConnHandle(), &msg_desc );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n#ifdef __USER_GARY__\r\n\t\tprintf( \"Broadcasting %d tricks\\n\", num_pending_tricks );\r\n#endif\r\n\r\n\t\tmsg.m_SubMsgId = GameNet::SCORE_MSG_ID_LOG_TRICK_OBJECT;\r\n\t\tmsg.m_OwnerId = skater_id;\r\n\t\tmsg.m_Score = score;\r\n\t\tmsg.m_NumPendingTricks = num_pending_tricks;\r\n\t\tmsg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\r\n\t\tuint32 max_pending_trick_buffer_size = GameNet::MsgScoreLogTrickObject::vMAX_PENDING_TRICKS * sizeof(uint32);\r\n\t\tuint32 actual_pending_trick_buffer_size = msg.m_NumPendingTricks * sizeof(uint32);\r\n\t\tmemcpy( msg.m_PendingTrickBuffer, p_pending_tricks, actual_pending_trick_buffer_size );\r\n\r\n\t\tmsg_desc.m_Data = &msg;\r\n\t\tmsg_desc.m_Length = sizeof( GameNet::MsgScoreLogTrickObject ) - max_pending_trick_buffer_size + actual_pending_trick_buffer_size;\r\n\t\tmsg_desc.m_Id = GameNet::MSG_ID_SCORE;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t// tell players to change their colors\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; \r\n\t\t\t player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\t//server->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\tserver->StreamMessage( player->GetConnHandle(), msg_desc.m_Id, msg_desc.m_Length, \r\n\t\t\t\t\t\t   msg_desc.m_Data, \"TrickObj Buffer\", GameNet::vSEQ_GROUP_PLAYER_MSGS );\r\n\t\t}\r\n\r\n\t\tobs_msg.m_OwnerId = skater_id;\r\n\t\tobs_msg.m_NumPendingTricks = num_pending_tricks;\r\n\t\tobs_msg.m_GameId = gamenet_man->GetNetworkGameId();\r\n\t\tmax_pending_trick_buffer_size = GameNet::MsgScoreLogTrickObject::vMAX_PENDING_TRICKS * sizeof(uint32);\r\n\t\tactual_pending_trick_buffer_size = obs_msg.m_NumPendingTricks * sizeof(uint32);\r\n\t\tmemcpy( obs_msg.m_PendingTrickBuffer, p_pending_tricks, actual_pending_trick_buffer_size );\r\n\r\n\t\tmsg_desc.m_Data = &obs_msg;\r\n\t\tmsg_desc.m_Length = sizeof( GameNet::MsgObsScoreLogTrickObject ) - max_pending_trick_buffer_size + actual_pending_trick_buffer_size;\r\n\t\tmsg_desc.m_Id = GameNet::MSG_ID_OBSERVER_LOG_TRICK_OBJ;\r\n\t\t// tell observers to change their colors\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh, true ); player; \r\n\t\t\t player = gamenet_man->NextPlayerInfo( sh, true ))\r\n\t\t{\r\n\t\t\tif( player->IsObserving())\r\n\t\t\t{\r\n\t\t\t\t//server->EnqueueMessage( player->GetConnHandle(), &msg_desc );\r\n\t\t\t\tserver->StreamMessage( player->GetConnHandle(), msg_desc.m_Id, msg_desc.m_Length, \r\n\t\t\t\t\t\t   msg_desc.m_Data, \"TrickObj Buffer\", GameNet::vSEQ_GROUP_PLAYER_MSGS );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// send score updates, as something has changed\r\n\t\tskate_mod->SendScoreUpdates( false );\r\n\r\n\t\t// Let the server's client do the rest of the work\r\n\t\tif( conn->IsLocal())\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n#ifdef __USER_GARY__\r\n\tprintf( \"Client is receiving %d tricks\\n\", num_pending_tricks );\r\n#endif\r\n\r\n\t// modulate the color here\r\n\tfor ( uint32 i = 0; i < num_pending_tricks; i++ )\r\n\t{\r\n\t\tskate_mod->GetTrickObjectManager()->ModulateTrickObjectColor( p_pending_tricks[i], skater_id );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid trick_off_object(CTrickCluster* pCluster, void* pData)\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr(pCluster);\r\n\r\n\tSAutoTrick* pAutoTrick = (SAutoTrick*)pData;\r\n\r\n\tif ( pAutoTrick->numPendingTricks >= 32 )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( !pCluster->m_IsOwned )\r\n\t{\r\n\t\tpAutoTrick->pPendingTricks[pAutoTrick->numPendingTricks] = pCluster->GetNameChecksum();\r\n\t\tpAutoTrick->numPendingTricks++;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTrickObjectManager::TrickOffAllObjects( uint32 skater_id )\r\n{\r\n\tSAutoTrick theAutoTrick;\r\n\ttheAutoTrick.numPendingTricks = 0;\r\n\t\r\n\tm_TrickClusterList.HandleCallback(trick_off_object, &theAutoTrick);\r\n\r\n\tif ( theAutoTrick.numPendingTricks > 0 )\r\n\t{\r\n\t\tMyLogTrickObject( skater_id, 1000, theAutoTrick.numPendingTricks, theAutoTrick.pPendingTricks, true );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickObjectManager::ModulateTrickObjectColor( uint32 name_checksum, int skater_id )\r\n{\r\n\t\r\n\r\n\tCTrickCluster* pCluster = get_aliased_cluster( name_checksum );\r\n\t\r\n\t// change only objects marked as trick objects\r\n\tif ( !pCluster )\r\n\t{\r\n\t\t// not a trick object\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// convert skater_id ->seqIndex, as it's 1-based,\r\n\t// or -1 to reset\r\n\tint seqIndex = -1;\r\n\tif ( skater_id != -1 )\r\n\t{\r\n\t\tseqIndex = skater_id + 1;\r\n\t}\r\n\t\r\n\tDbg_MsgAssert( seqIndex == -1 || ( seqIndex >= 1 && seqIndex <= 8 ) ,( \"Out of range seq index %d\", seqIndex ));\r\n\r\n\tpCluster->ModulateTrickObjectColor( seqIndex );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTrickCluster* CTrickObjectManager::get_aliased_cluster( uint32 alias_checksum )\r\n{\r\n#if 0\r\n\tfor ( uint32 i = 0; i < m_TrickAliasCount; i++ )\r\n\t{\r\n\t\tif ( m_TrickAliasList[i].m_AliasChecksum == alias_checksum )\r\n\t\t{\r\n\t\t\treturn m_TrickAliasList[i].mp_TrickCluster;\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n#endif\r\n\treturn m_TrickAliasList.GetItem(alias_checksum, false);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCTrickCluster* CTrickObjectManager::find_trick_cluster( uint32 cluster_checksum )\r\n{\r\n\t\r\n\r\n#if 0\r\n\tuint32 count = m_TrickClusterList.CountItems();\r\n\r\n\t// find the appropriate trick object\r\n\tfor ( uint32 i = 0; i < count; i++ )\r\n\t{\r\n\t\tLst::Node< CTrickCluster >* pNode = m_TrickClusterList.GetItem( i );\r\n\t\tDbg_Assert( pNode );\r\n\t\tCTrickCluster* pCluster = pNode->GetData();\r\n\t\tDbg_Assert( pCluster );\r\n\r\n\t\tif ( pCluster->m_NameChecksum == cluster_checksum )\r\n\t\t{\r\n\t\t\treturn pCluster;\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n#endif\r\n\treturn m_TrickClusterList.GetItem( cluster_checksum, false );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickObjectManager::clear_trick_clusters( int seqIndex )\r\n{\r\n\r\n\tm_TrickClusterList.IterateStart();\r\n\tCTrickCluster *p_cluster;\r\n\twhile ((p_cluster = m_TrickClusterList.IterateNext()))\r\n\t{\r\n\t\tif (!p_cluster->ClearCluster(seqIndex))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// this is useful if you want to examine the functionality\r\n// of a single trick object without sorting through hundreds of\r\n// other trick objects...  it represents one single piece in\r\n// the foundry\r\n//#define __TESTSINGLETRICKOBJECT__\r\n\r\n#ifdef __TESTSINGLETRICKOBJECT__\r\n\tconst char* p_single_cluster_name = \"ParkingLotBulldozer\";\r\n\tconst char* p_single_object_name = \"Parking_Lot_Bulldozer0\";\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickObjectManager::AddTrickCluster( uint32 name_checksum )\r\n{\r\n\t\r\n\r\n\r\n#ifdef __TESTSINGLETRICKOBJECT__\r\n\tif ( name_checksum != Script::GenerateCRC(p_single_cluster_name) )\r\n\t\treturn false;\r\n#endif\r\n\r\n#ifdef __USER_GARY__\r\n//\tprintf( \"+++  Adding trick object %s (%x)\\n\", Script::FindChecksumName(name_checksum), name_checksum );\r\n#endif\r\n\r\n\tif ( find_trick_cluster( name_checksum ) )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// If playing a created park, clear any created rail colors for this cluster.\r\n\tMdl::Skate * p_skate_mod =  Mdl::Skate::Instance();\r\n\tif (p_skate_mod->m_cur_level == CRCD(0xb664035d,\"load_sk5ed_gameplay\"))\r\n\t{\r\n\t\tObj::GetRailEditor()->ClearRailColor(name_checksum);\r\n\t}\r\n\t\r\n\t// add the cluster since it doesn't already exist\r\n\tCTrickCluster* pCluster = new CTrickCluster( name_checksum );\r\n\tDbg_Assert( pCluster );\r\n//\tm_TrickClusterList.AddToTail( pCluster );\r\n\tm_TrickClusterList.PutItem( name_checksum, pCluster );\r\n\tm_NumTrickClusters++;\r\n\t\r\n#if 0\t\r\n\tEd::ParkEditor* park_ed_mod = Ed::ParkEditor::Instance();\r\n\tif (!park_ed_mod->IsInitialized())\r\n\t{\r\n\t\tDbg_Assert( m_NumTrickClusters <= 256 );\r\n\t}\r\n#endif\r\n\t\r\n\t// alias the cluster to itself\r\n\tAddTrickAlias( name_checksum, name_checksum );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickObjectManager::AddTrickObjectToCluster( uint32 name_checksum, uint32 cluster_checksum )\r\n{\r\n\t\r\n\t\r\n#ifdef __TESTSINGLETRICKOBJECT__\r\n\tif ( name_checksum != Script::GenerateCRC(p_single_object_name) )\r\n\t\treturn false;\r\n#endif\r\n\r\n\tCTrickCluster* pCluster = find_trick_cluster( cluster_checksum );\r\n\tDbg_MsgAssert( pCluster,( \"cluster %s not found\", Script::FindChecksumName( cluster_checksum ) ));\r\n\r\n\tbool success = pCluster->AddTrickObject( name_checksum );\r\n\r\n\t// only if not clustering to self\r\n\tif ( success && ( name_checksum != cluster_checksum ) )\r\n\t{\r\n\t\t// bind the environment object to the cluster\r\n\t\tAddTrickAlias( name_checksum, cluster_checksum );\r\n\t}\r\n\t\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickObjectManager::AddTrickAlias( uint32 alias_checksum, uint32 cluster_checksum )\r\n{\r\n\t\r\n\t\r\n#ifdef __TESTSINGLETRICKOBJECT__\r\n\tif ( cluster_checksum != Script::GenerateCRC(p_single_cluster_name) )\r\n\t\treturn false;\r\n#endif\r\n\t\r\n\tCTrickCluster* pCluster = get_aliased_cluster( alias_checksum );\r\n\r\n\tif( pCluster )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"%s has already been aliased to %s cluster\", Script::FindChecksumName(alias_checksum), Script::FindChecksumName(pCluster->m_NameChecksum) ));\r\n\t}\r\n\r\n\tpCluster = find_trick_cluster( cluster_checksum );\r\n\r\n\tif( pCluster == NULL )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"cluster %s not found\", Script::FindChecksumName(cluster_checksum) ));\r\n\t}\r\n\r\n\tm_TrickAliasList.PutItem(alias_checksum, pCluster);\r\n\t\r\n#if 0\r\n\tDbg_MsgAssert( m_TrickAliasCount < vMAX_ALIASES,( \"Too many aliases.  Couldn't alias %s to cluster %s\", Script::FindChecksumName(alias_checksum), Script::FindChecksumName(cluster_checksum) ));\r\n\tm_TrickAliasList[m_TrickAliasCount].m_AliasChecksum = alias_checksum;\r\n\tpCluster = find_trick_cluster( cluster_checksum );\r\n\tm_TrickAliasList[m_TrickAliasCount].mp_TrickCluster = pCluster;\r\n\tDbg_MsgAssert( pCluster,( \"cluster %s not found\", Script::FindChecksumName(cluster_checksum) ));\r\n\tm_TrickAliasCount++;\r\n#endif\r\n\r\n//\tprintf(\"Adding trick alias %s\\n\", Script::FindChecksumName(alias_checksum));\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid delete_trick_cluster(CTrickCluster* pCluster, void* pData)\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr(pCluster);\r\n\r\n\tdelete pCluster;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickObjectManager::DeleteAllTrickObjects( void )\r\n{\r\n\t\r\n\r\n#if 0\r\n\tuint32 count = m_TrickClusterList.CountItems();\r\n\tfor ( uint32 i = 0; i < count; i++ )\r\n\t{\r\n\t\tLst::Node< CTrickCluster >* pNode = m_TrickClusterList.GetItem( 0 );\r\n\t\tDbg_Assert( pNode );\r\n\t\tCTrickCluster* pCluster = pNode->GetData();\r\n\t\tDbg_Assert( pCluster );\r\n\t\tdelete pCluster;\r\n\t}\r\n\r\n\t// now remove all the nodes from the list\r\n\tm_TrickClusterList.RemoveAllNodes();\r\n#endif\r\n\r\n\tm_TrickClusterList.HandleCallback(delete_trick_cluster, NULL);\r\n\tm_TrickClusterList.FlushAllItems();\r\n\tm_NumTrickClusters = 0;\r\n\t\r\n//\tm_TrickAliasCount = 0;\r\n\tm_TrickAliasList.FlushAllItems();\r\n\t\r\n\treturn true;\r\n}\r\n\r\nstruct STrickObjectScore\r\n{\r\n\tint\t\trunning_score;\r\n\tuint32\tskater_id;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid count_score(CTrickCluster* pCluster, void* pData)\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr(pCluster);\r\n\tDbg_AssertPtr(pData);\r\n\t\r\n\tSTrickObjectScore* pScore = (STrickObjectScore*)pData;\r\n\tpScore->running_score += pCluster->GetScore( pScore->skater_id );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CTrickObjectManager::GetScore( uint32 skater_id )\r\n{\r\n\tSTrickObjectScore theScore;\r\n\ttheScore.running_score = 0;\r\n\ttheScore.skater_id = skater_id;\r\n\r\n\tm_TrickClusterList.HandleCallback(count_score, (void*)&theScore);\r\n\r\n\treturn theScore.running_score;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstruct SSearchInfo\r\n{\r\n\tuint32 checksum;\r\n\tuint8 index;\r\n\tbool found;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid find_compressed_index(CTrickCluster* pCluster, void* pData)\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr(pCluster);\r\n\tDbg_AssertPtr(pData);\r\n\r\n\tSSearchInfo* pInfo = (SSearchInfo*)pData;\r\n\t\r\n\tif ( pInfo->found )\r\n\t{\r\n\t\t// already found...\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif ( pInfo->checksum == pCluster->GetNameChecksum() )\r\n\t{\r\n\t\tpInfo->found = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// make sure it's less than 256\r\n\tDbg_MsgAssert( pInfo->index < 256, ( \"Too many trick aliases\" ) );\r\n\t\r\n\tpInfo->index++;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid find_uncompressed_checksum(CTrickCluster* pCluster, void* pData)\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr(pCluster);\r\n\tDbg_AssertPtr(pData);\r\n\r\n\tSSearchInfo* pInfo = (SSearchInfo*)pData;\r\n\r\n\tif ( pInfo->found )\r\n\t{\r\n\t\t// already found...\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( pInfo->index == 0 )\r\n\t{\r\n\t\tpInfo->found = true;\r\n\t\tpInfo->checksum = pCluster->GetNameChecksum();\r\n\t\treturn;\r\n\t}\r\n\r\n\tpInfo->index--;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8 CTrickObjectManager::GetCompressedTrickObjectIndex( uint32 name_checksum )\r\n{\r\n\t\r\n\t\r\n\tSSearchInfo theInfo;\r\n\ttheInfo.index = 0;\r\n\ttheInfo.checksum = name_checksum;\r\n\ttheInfo.found = false;\r\n\t\r\n\tm_TrickClusterList.HandleCallback( find_compressed_index, (void*)&theInfo );\r\n\r\n\tDbg_Assert( theInfo.found );\r\n\r\n\treturn theInfo.index;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CTrickObjectManager::GetUncompressedTrickObjectChecksum( uint8 compressed_index )\r\n{\r\n\t\r\n\t\r\n\tSSearchInfo theInfo;\r\n\ttheInfo.index = compressed_index;\r\n\ttheInfo.checksum = 0;\r\n\ttheInfo.found = false;\r\n\r\n\tm_TrickClusterList.HandleCallback( find_uncompressed_checksum, (void*)&theInfo );\r\n\r\n\tDbg_Assert( theInfo.found );\r\n\t\r\n\treturn theInfo.checksum;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstruct SInitGraffitiStateInfo\r\n{\r\n\tuint32 skater_id;\r\n\tint num_trick_objects;\r\n\tGameNet::MsgInitGraffitiState* pMsg;\r\n\tObj::CTrickObjectManager* pManager;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid init_graffiti_state(CTrickCluster* pCluster, void* pData)\r\n{\r\n\t\r\n\t\r\n\tSInitGraffitiStateInfo* pInfo = (SInitGraffitiStateInfo*)pData;\r\n\r\n\tif ( pCluster->m_IsOwned && pCluster->m_OwnerId == pInfo->skater_id )\r\n\t{\r\n\t\t// TODO:  check whether it's already in the list?\r\n\t\t\r\n\t\tDbg_MsgAssert( pInfo->num_trick_objects < GameNet::vMAX_TRICK_OBJECTS_IN_LEVEL, ( \"Too many trick objects in level\" ) );\r\n\t\t\r\n\t\tObj::CTrickObjectManager* pManager = pInfo->pManager;\r\n\t\tpInfo->pMsg->m_TrickObjectStream[pInfo->num_trick_objects] = pManager->GetCompressedTrickObjectIndex( pCluster->GetNameChecksum() );\r\n\t\tpInfo->num_trick_objects++;\r\n\t\tpInfo->pMsg->m_NumTrickObjects[pInfo->skater_id]++;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTrickObjectManager::SetObserverGraffitiState( Script::CScriptStructure* pScriptStructure )\r\n{\r\n\tmp_ObserverState->Clear();\r\n\tif (pScriptStructure)\r\n\t{\r\n\t\t*mp_ObserverState+=*pScriptStructure;\r\n\t}\t\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tScript::PrintContents(mp_ObserverState);\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTrickObjectManager::ApplyObserverGraffitiState( void )\r\n{\r\n\tfor( int i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tScript::CArray* pArray;\r\n\r\n\t\tchar arrayName[32];\r\n\t\tsprintf( arrayName, \"Skater%d\", i );\r\n\r\n\t\tif ( mp_ObserverState->GetArray( arrayName, &pArray ) )\r\n\t\t{\r\n\t\t\tfor ( int j = 0; j < (int)pArray->GetSize(); j++ )\r\n\t\t\t{\t\t\t\r\n\t\t\t\tuint32 checksum = pArray->GetNameChecksum( j );\r\n#ifdef __NOPT_ASSERT__\t\t\t\t\r\n\t\t\t\tprintf( \"Modulating array %s\\n\", Script::FindChecksumName(checksum) );\r\n#endif\r\n\t\t\t\tModulateTrickObjectColor( checksum, i );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// now that we've done it, we can clear the observer state.\r\n\tmp_ObserverState->Clear();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CTrickObjectManager::SetInitGraffitiStateMessage( void* pData )\r\n{\r\n\t\r\n\r\n\tSInitGraffitiStateInfo theInfo;\r\n\ttheInfo.pMsg = (GameNet::MsgInitGraffitiState*)pData;\r\n\ttheInfo.pManager = this;\r\n\ttheInfo.num_trick_objects = 0;\r\n\r\n\tfor ( uint32 i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )\r\n\t{\r\n\t\ttheInfo.pMsg->m_NumTrickObjects[i] = 0;\r\n\t\ttheInfo.skater_id = i;\r\n\t\tm_TrickClusterList.HandleCallback( init_graffiti_state, (void*)&theInfo );\r\n        \r\n\t\tprintf( \"Building graffiti state message %d\\n\", theInfo.pMsg->m_NumTrickObjects[i] );\r\n\t}\r\n\t\r\n\treturn ( sizeof(uint8) * Mdl::Skate::vMAX_SKATERS ) + ( sizeof(uint8) * theInfo.num_trick_objects );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CTrickObjectManager::ResetAllTrickObjects( void )\r\n{\r\n\t\r\n\r\n\t// TODO:\r\n\tprintf(\"Resetting all trick objects\\n\");\r\n\treturn false;\r\n\r\n#if 0\r\n\tuint32 count = m_TrickClusterList.CountItems();\r\n\r\n\t// call the reset function on each trick object in the scene\r\n\tfor ( uint32 i = 0; i < count; i++ )\r\n\t{\r\n\t\tLst::Node< CTrickCluster >* pNode = m_TrickClusterList.GetItem( i );\r\n\t\tDbg_Assert( pNode );\r\n\t\tCTrickCluster* pCluster = pNode->GetData();\r\n\t\tDbg_Assert( pCluster );\r\n\t\tpCluster->Reset();\r\n\t}\r\n#endif\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CTrickObjectManager::PrintContents( void )\r\n{\r\n\t\r\n\r\n\t// Remove this line if you need to see the contents\r\n\treturn;\r\n\r\n\tprintf(\"**********************\\n\");\r\n\tprintf(\"* TRICK CLUSTER LIST:\\n\");\r\n\tprintf(\"**********************\\n\");\r\n\r\n#if 0\r\n\tuint32 i;\r\n\r\n\t// call the reset function on each trick object in the scene\r\n\tfor ( i = 0; i < m_TrickClusterList.CountItems(); i++ )\r\n\t{\r\n\t\tLst::Node< CTrickCluster >* pNode = m_TrickClusterList.GetItem( i );\r\n\t\tDbg_Assert( pNode );\r\n\t\tCTrickCluster* pCluster = pNode->GetData();\r\n\t\tDbg_Assert( pCluster );\r\n\t\tprintf( \"Trick cluster %d of %d: %s\\n\", i, m_TrickClusterList.CountItems(), Script::FindChecksumName( pCluster->m_NameChecksum ) );\r\n\t}\r\n#endif\r\n\t\r\n#if 0\r\n\tprintf(\"**********************\\n\");\r\n\tprintf(\"* TRICK ALIAS LIST:\\n\");\r\n\tprintf(\"**********************\\n\");\r\n\r\n\tfor ( i = 0; i < m_TrickAliasCount; i++ )\r\n\t{\r\n//\t\tprintf( \"%d: %s is aliased to %s\\n\", i, Script::FindChecksumName(m_TrickAliasList[i].m_AliasChecksum), Script::FindChecksumName(m_TrickAliasList[i].mp_TrickCluster->m_NameChecksum) );\r\n\t}\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPendingTricks::CPendingTricks( void )\r\n{\r\n\tm_NumTrickItems = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPendingTricks::TrickOffObject( uint32 checksum )\r\n{\r\n\t\r\n\t\r\n\tuint32 num_trick_items = m_NumTrickItems;\r\n\tif ( num_trick_items > vMAX_PENDING_TRICKS )\r\n\t\tnum_trick_items = vMAX_PENDING_TRICKS;\r\n\r\n\t// not a valid trick item\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tCTrickObjectManager* pTrickObjectManager = skate_mod->GetTrickObjectManager();\r\n\tDbg_Assert( pTrickObjectManager );\r\n\tchecksum = pTrickObjectManager->TrickObjectExists( checksum );\r\n\tif ( !checksum )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tfor ( uint32 i = 0; i < num_trick_items; i++ )\r\n\t{\r\n\t\tif ( m_Checksum[i] == checksum )\r\n\t\t\treturn false;\r\n\t}\r\n\r\n//\tprintf( \"Adding object %s to pending tricks:\\n\", Script::FindChecksumName(checksum) );\r\n\t\r\n\t// circular buffer\r\n\tm_Checksum[(m_NumTrickItems++)%vMAX_PENDING_TRICKS] = checksum;\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CPendingTricks::WriteToBuffer( uint32* p_buffer, uint32 max_size )\r\n{\r\n\t\r\n\r\n\t// TODO:  Account for the circular buffer so that the buffer\r\n\t// size can be bigger than the pending trick size\r\n\tDbg_Assert( ( vMAX_PENDING_TRICKS * sizeof(uint32) ) <= max_size );\r\n\t\r\n\tuint32 num_trick_items = m_NumTrickItems;\r\n\tif ( num_trick_items > vMAX_PENDING_TRICKS )\r\n\t\tnum_trick_items = vMAX_PENDING_TRICKS;\r\n\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tCTrickObjectManager* pTrickObjectManager = skate_mod->GetTrickObjectManager();\r\n\tDbg_Assert( pTrickObjectManager );\r\n\r\n\tuint32 size = 0;\r\n\tfor ( uint32 i = 0; i < num_trick_items; i++ )\r\n\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\tprintf( \"Looking for %s\\n\", Script::FindChecksumName( m_Checksum[i] ) );\r\n#endif\t\t\r\n\t\tif ( pTrickObjectManager->TrickObjectExists( m_Checksum[i] ) )\r\n\t\t{\r\n\t\t\t*p_buffer = m_Checksum[i];\r\n\t\t\tp_buffer++ ;\r\n\r\n\t\t\t// increment the size\r\n\t\t\tsize += sizeof(uint32);\r\n\t\t}\r\n\t\t\r\n\t\tif ( size >= max_size )\r\n\t\t\tbreak;\r\n\t}\r\n\treturn size;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CPendingTricks::FlushTricks( void )\r\n{\r\n\t// player has bailed\r\n\tm_NumTrickItems = 0;\r\n\r\n\treturn true;\r\n}\r\n\r\n} // namespace Obj\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/TrickObject.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTrickObject (OBJ)\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tTrickObject.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/05/01\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\ttrick object code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __TRICK_OBJECT_H\r\n#define __TRICK_OBJECT_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <core/list/node.h>\r\n#include <core/hashtable.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n}\r\n\t\r\nnamespace Obj\r\n{\r\n\r\n    class CTrickObjectManager;\r\n    class CTrickCluster;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// this is the interface through which we will\r\n// modify a specific world sector's colors\r\nclass  CTrickObject : public  Lst::Node< CTrickObject > \r\n{\r\n\t\r\n\r\n\tpublic:\r\n\t\tfriend class\tCTrickCluster;\r\n\r\n\tpublic:\r\n\t\tCTrickObject( uint32 name_checksum );\r\n\t\tbool\t\tInitializeTrickObjectColor( int seqIndex );\r\n\t\tbool\t\tModulateTrickObjectColor( int seqIndex );\r\n\t\tbool\t\tClearTrickObjectColor( int seqIndex );\r\n\r\n\tprotected:\r\n\t\tuint32\t\tm_NameChecksum;\r\n\r\n\tprivate:\r\n\t\tCTrickObject( void );\r\n};\r\n\r\n// this represents a group of linked trick objects\r\n// when the score contained in the cluster is beaten\r\n// all of the trick objects will change color\r\nclass  CTrickCluster : public  Lst::Node< CTrickCluster > \r\n{\r\n\t\r\n\r\n\tpublic:\r\n\t\tfriend class\tCTrickObjectManager;\r\n\t\tfriend void trick_off_object( CTrickCluster*, void* );\r\n\t\tfriend void init_graffiti_state( CTrickCluster*, void* );\r\n\r\n\tpublic:\r\n\t\tCTrickCluster( uint32 name_checksum );\r\n\t\tvirtual\t\t\t~CTrickCluster();\r\n\t\tint\t\t\t\tGetScore( uint32 skater_id );\r\n\t\tuint32\t\t\tGetNameChecksum() { return m_NameChecksum; }\r\n\t\tbool\t\t\tAddTrickObject( uint32 name_checksum );\r\n\t\tbool\t\t\tReset();\r\n\t\tbool\t\t\tModulateTrickObjectColor( int seqIndex );\r\n\t\tbool\t\t\tFreeCluster( uint32 skater_id );\r\n\t\tbool\t\t\tClearCluster( int seqIndex );\r\n\r\n\tprotected:\r\n\t\tCTrickObject*\tfind_trick_object( uint32 name_checksum );\r\n\r\n\tprotected:\r\n\t\tuint32\t\t\tm_NameChecksum;\r\n\t\tuint32\t\t\tm_Score;\r\n\t\tuint32\t\t\tm_OwnerId;\r\n\t\tbool\t\t\tm_IsOwned;\r\n\r\n\t// list of objects that get colored when one of the cluster get triggered\r\n\t\tLst::Head< CTrickObject >\t\tm_TrickObjectList;\r\n\r\n\tprivate:\r\n\t\tCTrickCluster( void );\r\n};\r\n\r\nclass  CTrickObjectManager  : public Spt::Class\r\n{\r\n\t\r\n\r\n\tpublic :\r\n\t\tCTrickObjectManager( void );\r\n\t\tvirtual\t\t\t~CTrickObjectManager( void );\r\n\r\n\tpublic:\r\n\t\tint\t\t\t\tGetScore( uint32 skater_id );\r\n\t\tbool\t\t\tAddTrickCluster( uint32 name_checksum );\r\n\t\tbool\t\t\tAddTrickObjectToCluster( uint32 name_checksum, uint32 cluster_checksum );\r\n\t\tbool\t\t\tAddTrickAlias( uint32 alias_checksum, uint32 cluster_checksum );\r\n\t\tbool\t\t\tDeleteAllTrickObjects();\t// wipes out all the trick objects\r\n\t\tbool\t\t\tResetAllTrickObjects();\t\t// resets all points to 0\r\n\t\tvoid\t\t\tPrintContents();\r\n\t\tbool\t\t\tModulateTrickObjectColor( uint32 name_checksum, int skater_id );\r\n\t\tuint32\t\t\tRequestLogTrick( uint32 num_pending_tricks, uint32* p_pending_tricks, char* p_inform_prev_owner, int skater_id, uint32 score );\r\n\t\tuint32\t\t\tTrickObjectExists( uint32 name_checksum );\r\n\t\tbool\t\t\tFreeTrickObjects( uint32 skater_id );\r\n\t\tvoid\t\t\tTrickOffAllObjects( uint32 skater_id );\r\n\t\tuint8\t\t\tGetCompressedTrickObjectIndex( uint32 name_checksum );\r\n\t\tuint32\t\t\tGetUncompressedTrickObjectChecksum( uint8 compressed_index );\r\n\t\tuint32\t\t\tSetInitGraffitiStateMessage( void* pMsg );\r\n\t\tvoid\t\t\tSetObserverGraffitiState( Script::CStruct* pScriptStructure );\r\n\t\tvoid\t\t\tApplyObserverGraffitiState( void );\r\n\t\tCTrickCluster*\tGetTrickCluster( uint32 name_checksum );\r\n\r\n\t\tint \t\t\tm_NumTrickClusters;\r\n\tprotected:\r\n\t\tCTrickCluster*\tget_aliased_cluster( uint32 alias_checksum );\r\n\t\tCTrickCluster*\tfind_trick_cluster( uint32 name_checksum );\r\n\t\tbool\t\t\tclear_trick_clusters( int seqIndex );\t\t\r\n\t\t\r\n\tprotected:\r\n\t\t// full list of clusters\r\n\t\tLst::HashTable< CTrickCluster >\tm_TrickClusterList;\r\n\r\n\t\t// list of checksums that will fire off this cluster\r\n\t\tLst::HashTable< CTrickCluster >\tm_TrickAliasList;\r\n\r\n\t\tScript::CStruct* mp_ObserverState;\r\n};\r\n\r\n// per-skater\r\nclass  CPendingTricks  : public Spt::Class\r\n{\r\n\tpublic:\r\n\t\tenum\r\n\t\t{\r\n\t\t\tvMAX_PENDING_TRICKS = 512,\t\t// max number of items we can trick off in a combo\r\n\t\t\t// for now this number must be less or equal to the buffer size in gamemsg.h\r\n\t\t};\r\n\r\n\t\tCPendingTricks( void );\r\n\t\tbool\t\tTrickOffObject( uint32 checksum );\r\n\t\tuint32\t\tWriteToBuffer( uint32* p_buffer, uint32 max_size );\r\n\t\tbool\t\tFlushTricks( void );\r\n\t\tuint32\t\tm_Checksum[vMAX_PENDING_TRICKS];\r\n\t\tuint32\t\tm_NumTrickItems;\r\n\r\n\tprotected:\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __TRICK_OBJECT_H\r\n"
  },
  {
    "path": "Code/Sk/Objects/ViewerObj.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       ViewerObj.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  1/21/2002\r\n//****************************************************************************\r\n\r\n#include <sk/objects/viewerobj.h>\r\n\t\t\t\t\t\t\t\t \r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n\r\n#include <gel/mainloop.h>\r\n#include <gel/objman.h>\r\n#include <gel/assman/assman.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/net/server/netserv.h>\r\n\r\n#include <gfx/bonedanim.h>\r\n#include <gfx/gfxutils.h>\r\n#include <gfx/modelappearance.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/nxhierarchy.h>\r\n#include <gfx/skeleton.h>\r\n\r\n#include <sk/gamenet/exportmsg.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/viewer/viewer.h>\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/scripting/gs_file.h>\r\n#include <sk/scripting/skfuncs.h>\r\n\r\n#include <sys/config/config.h>\r\n\r\n// TODO:  Remove the rest of the level when the viewer is active\t\t\t\t\t\t\t\t   \r\n// TODO:  Launch a primary sequence by name, pointer, or index\r\n// TODO:  The shoulder buttons should increment the current anim (next/prev anim)\r\n// TODO:  Don't crash if can't find the animation...\r\n// TODO:  Add handlers so that it can launch new anims and such\r\n// TODO:  Camera controls\r\n// TODO:  Be able to go back to the game\r\n// TODO:  Wireframe\tmode\r\n// TODO:  Change skater profile, in real time\r\n// TODO:  Take LODs into account\r\n\t\t\t\t\t\t\t\t   \r\nnamespace Obj\r\n{\r\n\r\n\tconst float vSPEED_INCREMENT_AMOUNT = 0.25;\r\n\tconst Mth::Vector vPOS_VIEWEROBJECT( 0.0f, 0.0f, 0.0f );\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CViewerObject::s_handle_set_anim( Net::MsgHandlerContext* context )\r\n{\r\n\tCViewerObject* pViewerObject;\r\n\tpViewerObject = (CViewerObject*) context->m_Data;\r\n\tDbg_Assert( pViewerObject );\r\n\t\r\n\tNet::MsgViewObjSetAnim* p_msg;\r\n\tp_msg = (Net::MsgViewObjSetAnim*) context->m_Msg;\r\n\tpViewerObject->SetAnim( p_msg->m_AnimName );\r\n\t\r\n\tDbg_Message( \"Got request to set anim %s...\", Script::FindChecksumName(p_msg->m_AnimName) );\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CViewerObject::s_handle_set_anim_speed( Net::MsgHandlerContext* context )\r\n{\r\n\tDbg_Message( \"Got request to set anim speed...\" );\r\n\t\r\n\tCViewerObject* pViewerObject;\r\n\tpViewerObject = (CViewerObject*) context->m_Data;\r\n\tDbg_Assert( pViewerObject );\r\n\r\n\tNet::MsgViewObjSetAnimSpeed* p_msg;\r\n\tp_msg = (Net::MsgViewObjSetAnimSpeed*) context->m_Msg;\r\n\tpViewerObject->ChangeAnimSpeed( p_msg->m_AnimSpeed );\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CViewerObject::s_handle_increment_frame( Net::MsgHandlerContext* context )\r\n{\r\n\tDbg_Message( \"Got request to increment frame...\" );\r\n\r\n\tCViewerObject* pViewerObject;\r\n\tpViewerObject = (CViewerObject*) context->m_Data;\r\n\tDbg_Assert( pViewerObject );\r\n\t\t\t\t\t\r\n\tNet::MsgViewObjIncrementFrame* p_msg;\r\n\tp_msg = (Net::MsgViewObjIncrementFrame*) context->m_Msg;\r\n\tpViewerObject->IncrementFrame( p_msg->m_Forwards );\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CViewerObject::s_handle_reload_anim( Net::MsgHandlerContext* context )\r\n{\r\n\tDbg_Message( \"Got request to reload anim...\" );\r\n\r\n\tCViewerObject* pViewerObject;\r\n\tpViewerObject = (CViewerObject*) context->m_Data;\r\n\tDbg_Assert( pViewerObject );\r\n\t\t\t\t\t\r\n\tNet::MsgViewObjSetAnimFile* p_msg;\r\n\tp_msg = (Net::MsgViewObjSetAnimFile*) context->m_Msg;\r\n\tpViewerObject->ReloadAnim( p_msg->m_Filename, p_msg->m_checksum );\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CViewerObject::s_handle_sequence_preview( Net::MsgHandlerContext* context )\r\n{\r\n\tchar path[256];\r\n\tchar* script_name;\r\n\tCViewerObject* pViewerObject;\r\n\tpViewerObject = (CViewerObject*) context->m_Data;\r\n\tDbg_Assert( pViewerObject );\r\n\r\n\tscript_name = context->m_Msg;\r\n\tsprintf( path, \"scripts\\\\animview\\\\%s.qb\", script_name );\r\n\tSkateScript::LoadQB( path );\r\n\t//Script::RunScriptOnObject(\"RunMeNow\",NULL,pViewerObject);\r\n\tScript::CScript *pNewScript=Script::SpawnScript(script_name,NULL,0,NULL);\r\n\tpNewScript->mpObject = pViewerObject;\r\n\t\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CViewerObject::s_handle_reload_cam_anim( Net::MsgHandlerContext* context )\r\n{\r\n\tDbg_Message( \"Got request to reload cam anim...\" );\r\n\r\n\tNet::MsgViewObjSetAnimFile* p_msg;\r\n\tp_msg = (Net::MsgViewObjSetAnimFile*) context->m_Msg;\r\n\t\r\n\tScript::CStruct* pTempStruct = new Script::CStruct;\r\n\t\t\t\t\t\t\t\t  \r\n\tpTempStruct->AddString( NONAME, p_msg->m_Filename );\r\n\tpTempStruct->AddChecksum( NONAME, p_msg->m_checksum );\r\n\r\n\tCFuncs::ScriptReloadSkaterCamAnim( pTempStruct, NULL );\r\n\r\n\tdelete pTempStruct;\r\n\r\n\treturn Net::HANDLER_CONTINUE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCViewerObject::CViewerObject( Net::Server* pServer )\r\n{\r\n\tInp::Manager * inp_manager = Inp::Manager::Instance();\r\n    mp_input_handler = new Inp::Handler< CViewerObject > ( 0,  s_input_logic_code, *this, Tsk::BaseTask::Node::vNORMAL_PRIORITY );\r\n\tinp_manager->AddHandler( *mp_input_handler );\r\n\r\n    m_animSpeed = 1.0f;\r\n\tm_showPanel = true;\r\n\r\n\tm_matrix.Ident();\r\n\r\n\tm_paused = false;\r\n\t\r\n\tmp_server = pServer;\r\n\r\n\tDbg_Assert( mp_server );\r\n\r\n\tmp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_SET_ANIM, \r\n\t\t\t\t\t\t\t\t\t  s_handle_set_anim,\r\n\t\t\t\t\t\t\t\t\t  Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );\r\n\tmp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_SET_ANIM_SPEED, \r\n\t\t\t\t\t\t\t\t\t  s_handle_set_anim_speed,\r\n\t\t\t\t\t\t\t\t\t  Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );\r\n\tmp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_INCREMENT_FRAME, \r\n\t\t\t\t\t\t\t\t\t  s_handle_increment_frame,\r\n\t\t\t\t\t\t\t\t\t  Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );\r\n\tmp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_SET_ANIM_FILE, \r\n\t\t\t\t\t\t\t\t\t  s_handle_reload_anim,\r\n\t\t\t\t\t\t\t\t\t  Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );\r\n\tmp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_SET_CAMANIM_FILE, \r\n\t\t\t\t\t\t\t\t\t  s_handle_reload_cam_anim,\r\n\t\t\t\t\t\t\t\t\t  Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );\r\n\tmp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_PREVIEW_SEQUENCE, \r\n\t\t\t\t\t\t\t\t\t  s_handle_sequence_preview,\r\n\t\t\t\t\t\t\t\t\t  Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCViewerObject::~CViewerObject()\r\n{\r\n\tmp_input_handler->Remove();\r\n\r\n    delete mp_input_handler;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void s_remove_asset( const char* pFileName )\r\n{\r\n\t// if the file is in the asset manager, unload it so\r\n\t// that the artists can display the latest version\r\n\t// (\"cas_artist\" must be set to 1, or else it'll just\r\n\t// reload it from the PRE file)\r\n\t\r\n\tif ( !Script::GetInt( \"cas_artist\", false ) )\r\n\t{\r\n\t\tDbg_Message( \"Warning:  Can't reload asset %s from disk (need to define cas_artist=1)\", pFileName );\r\n\t\treturn;\r\n\t}\r\n\r\n\t// get the assman\r\n\tAss::CAssMan * ass_man = Ass::CAssMan::Instance();\r\n\r\n\t// kills the original asset\r\n\tAss::CAsset* pAsset = ass_man->GetAssetNode( Script::GenerateCRC( pFileName ), false );\r\n\r\n\tif ( pAsset )\r\n\t{\t\t\r\n\t\tDbg_Message( \"Unloading asset %s\", pFileName );\r\n\t\tass_man->DestroyReferences( pAsset );\r\n\t\tass_man->UnloadAsset( pAsset );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Message( \"Couldn't find asset %s to unload\", pFileName );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CViewerObject::LoadModel( Script::CStruct* pNodeData )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tskate_mod->GetObjectManager()->RegisterObject( *this );\r\n\tMovingObjectCreateComponents();\r\n\tMovingObjectInit( pNodeData, skate_mod->GetObjectManager() );\r\n\r\n\tNx::CEngine::sFinishRendering();\r\n\r\n\tif (Config::GotExtraMemory())\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t}\r\n\t\t\r\n\tDbg_Assert( pNodeData );\r\n\t\r\n\t// get rid of old model, if\r\n\t// it was stored in the assman\r\n\tint skaterProfileNumber;\r\n\tconst char* pModelName;\r\n\tuint32 profileName;\r\n\r\n\tfor ( int i = 0; i < Obj::CModelComponent::vNUM_LODS; i++ )\r\n\t{\r\n\t\tchar paramName[256];\r\n\t\tsprintf( paramName, \"model%d\", i ); \r\n\r\n\t\tif ( pNodeData->GetText( paramName, &pModelName, false ) )\r\n\t\t{\r\n\t\t\tDbg_Message( \"Removing model LOD data from asset manager, in order to replace it with new data\" );\r\n\r\n\t\t\tStr::String fullModelName;\r\n\t\t\tfullModelName = Gfx::GetModelFileName(pModelName, \".skin\");\t\t\r\n\t\t\ts_remove_asset( fullModelName.getString() );\r\n\r\n\t\t\tfullModelName = Gfx::GetModelFileName(pModelName, \".mdl\");\t\t\r\n\t\t\ts_remove_asset( fullModelName.getString() );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( pNodeData->GetText( \"modelName\", &pModelName, false ) \r\n\t\t || pNodeData->GetText( \"model\", &pModelName, false ) )\r\n\t{\r\n\t\tDbg_Message( \"Removing model data from asset manager, in order to replace it with new data\" );\r\n\r\n\t\tStr::String fullModelName;\r\n\t\tfullModelName = Gfx::GetModelFileName(pModelName, \".skin\");\t\t\r\n\t\ts_remove_asset( fullModelName.getString() );\r\n\t\t\r\n\t\tfullModelName = Gfx::GetModelFileName(pModelName, \".mdl\");\t\t\r\n\t\ts_remove_asset( fullModelName.getString() );\r\n\t}\r\n\telse if ( pNodeData->GetChecksum( \"profile\", &profileName, false ) )\r\n\t{\r\n\t\tDbg_Message( \"Warning:  can't remove old model data from asset manager...  asset not reloaded from disk.\" );\r\n\t}\r\n\telse if ( pNodeData->GetInteger( \"skater_profile_index\", &skaterProfileNumber, false ) )\r\n\t{\r\n\t\tDbg_Message( \"Warning:  can't remove old model data from asset manager...  asset not reloaded from disk.\" );\r\n\r\n\t\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( skaterProfileNumber );\r\n\t\tScript::CStruct* pAppearanceStruct = pSkaterProfile->GetAppearance()->GetStructure();\r\n\t\tScript::CStruct* pNewStruct = new Script::CStruct;\r\n\t\tpNewStruct->AppendStructure( pAppearanceStruct );\r\n\t\tpNodeData->AddStructurePointer( \"profile\", pNewStruct );\r\n\t\t// don't need to delete the structure, \r\n\t\t// because it gets added permanently to the struct\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Unrecognized parameters for model loading\" ) );\r\n\t}\r\n\r\n\tm_pos = vPOS_VIEWEROBJECT;\r\n\tm_matrix.Ident();\r\n\t\r\n\tScript::RunScript( CRCD(0x24c71bc7,\"viewerobj_add_components\"), pNodeData, this );\r\n\r\n\tFinalize();\r\n\r\n\tScript::RunScript( CRCD(0xbbab79de,\"viewerobj_init_model\"), pNodeData, this );\r\n\r\n\t// loop the idle anim, if it exists\r\n\tCViewerObject::SetAnim( CRCD(0x23db4aea,\"idle\") );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CViewerObject::UnloadModel()\r\n{\r\n\tScript::RunScript( \"kill_viewer_object_panel\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CViewerObject::SetAnim( uint32 animName )\r\n{\r\n    if ( GetAnimationComponent() )\r\n    {\r\n        if ( GetAnimationComponent()->AnimExists( animName ) )\r\n        {\r\n            GetAnimationComponent()->PlayPrimarySequence( animName, false, 0.0f, GetAnimationComponent()->AnimDuration( animName ), Gfx::LOOPING_CYCLE);\r\n        \r\n/*\r\n\t\t\tScript::CStruct* pTempStruct = new Script::CStruct;\r\n\t\t\tpTempStruct->AddChecksum( \"type\", Script::GenerateCRC(\"partialAnim\" ) );\r\n\t\t\tpTempStruct->AddChecksum( \"AnimName\", Script::GetChecksum(\"TestPartialAnim\" ) );\r\n\t\t\tpTempStruct->AddChecksum( \"from\", Script::GenerateCRC(\"start\") );\r\n\t\t\tpTempStruct->AddChecksum( \"to\", Script::GenerateCRC(\"end\") );\r\n\t\t\tpTempStruct->AddChecksum( NONAME, Script::GenerateCRC(\"cycle\") );\r\n\t\t\tpTempStruct->AddFloat( \"speed\", 1.0f );\r\n\t\t\tScript::RunScript( \"AddAnimController\", pTempStruct, this );\r\n\t\t\tdelete pTempStruct;\r\n*/\r\n\t\t}\r\n        else\r\n        {\r\n#ifdef\t__NOPT_ASSERT__\r\n            Dbg_Message( \"Unrecognized anim %s\", Script::FindChecksumName(animName) );\r\n#endif\r\n        }\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CViewerObject::SetRotation( float rotZ, float rotX )\r\n{\r\n\tm_matrix.Ident();\r\n\tm_matrix.RotateZ( rotZ );\r\n\tm_matrix.RotateX( rotX );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CViewerObject::ChangeAnimSpeed( float animSpeed )\r\n{\r\n\tm_animSpeed = animSpeed;\r\n\r\n\tif ( m_animSpeed > 1.0f )\r\n\t{\r\n\t\tm_animSpeed = 1.0f;\r\n\t}\r\n\r\n\tif ( m_animSpeed < 0.0f )\r\n\t{\r\n\t\tm_animSpeed = 0.0f;\r\n\t}\r\n\r\n    if ( GetAnimationComponent() )\r\n    {\r\n        GetAnimationComponent()->SetAnimSpeed( m_animSpeed, false );\r\n\t\t\r\n\t\t// update partial anims\r\n\t\tScript::CStruct* pTempStruct = new Script::CStruct;\r\n\t\tpTempStruct->AddFloat( CRCD(0xf0d90109,\"speed\"), m_animSpeed );\r\n\t\tGetAnimationComponent()->CallMemberFunction( CRCD(0xbd4edd44,\"SetPartialAnimSpeed\"), pTempStruct, NULL );\r\n\t\tdelete pTempStruct;\r\n    }\r\n\r\n\tif ( GetAnimationComponent() )\r\n\t{\r\n\t\t// reset the paused state...\r\n\t\tGetAnimationComponent()->Suspend( false );\r\n\t}\r\n\r\n\tm_paused = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CViewerObject::IncrementFrame( bool forwards )\r\n{\r\n    if ( GetAnimationComponent() )\r\n    {\r\n\t\tif ( forwards )\r\n        {\r\n            // frame-rate independent\r\n            GetAnimationComponent()->AddTime( 1.0f / 60.0f );\r\n\t\t\tGetAnimationComponent()->PrintStatus();\r\n        \r\n\t\t\tScript::CStruct* pTempStruct = new Script::CStruct;\r\n\t\t\tpTempStruct->AddFloat( CRCD(0x06c9f278,\"incVal\"), 1.0f / 60.0f );\r\n\t\t\tGetAnimationComponent()->CallMemberFunction( CRCD(0x6aaeb76f,\"IncrementPartialAnimTime\"), pTempStruct, NULL );\r\n\t\t\tdelete pTempStruct;\r\n\t\t}\r\n        else\r\n        {\r\n\t\t\t// reverse direction so that it loops properly\r\n\t\t\tGetAnimationComponent()->ReverseDirection( false );\r\n\r\n\t\t\t// frame-rate independent\r\n            GetAnimationComponent()->AddTime( -1.0f / 60.0f );\r\n            GetAnimationComponent()->PrintStatus();\r\n\r\n\t\t\tGetAnimationComponent()->ReverseDirection( false );\r\n    \t\t\r\n\t\t\tGetAnimationComponent()->CallMemberFunction( CRCD(0xf5e2b871,\"ReversePartialAnimDirection\"), NULL, NULL );\r\n\t\t\t\r\n\t\t\tScript::CStruct* pTempStruct = new Script::CStruct;\r\n\t\t\tpTempStruct->AddFloat( CRCD(0x06c9f278,\"incVal\"), -1.0f / 60.0f );\r\n\t\t\tGetAnimationComponent()->CallMemberFunction( CRCD(0x6aaeb76f,\"IncrementPartialAnimTime\"), pTempStruct, NULL );\r\n\t\t\tdelete pTempStruct;\r\n\t\t\t\r\n\t\t\tGetAnimationComponent()->CallMemberFunction( CRCD(0xf5e2b871,\"ReversePartialAnimDirection\"), NULL, NULL );\r\n\t\t}\r\n\t\t\r\n\t\t// don't want to call the animation component's\r\n\t\t// Update() function, because that changes the\r\n\t\t// time...  instead, call UpdateSkeleton()\r\n\t\t// which syncs the skeleton to the current time\r\n\t\tGetAnimationComponent()->UpdateSkeleton();\r\n\r\n\t\t// reset the paused state...\r\n\t\tGetAnimationComponent()->Suspend( true );\r\n\t}\r\n\r\n\tm_paused = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CViewerObject::ReloadAnim( const char* pFileName, uint32 animName )\r\n{\r\n    if ( GetAnimationComponent() )\r\n    {\r\n        Dbg_Message( \"Reloading anim...\" );\r\n        Dbg_Message( \"Warning!  This function fragments memory.  Use it at your own risk!\" );\r\n\r\n        // get the assman\r\n        Ass::CAssMan * ass_man = Ass::CAssMan::Instance();\r\n\r\n        // kills the original asset\r\n        Ass::CAsset* pAsset = ass_man->GetAssetNode( Script::GenerateCRC( pFileName ), false );\r\n        if ( pAsset )\r\n        {\r\n            ass_man->DestroyReferences( pAsset );\r\n            ass_man->UnloadAsset( pAsset );\r\n        }\r\n        else\r\n        {\r\n#ifdef __NOPT_ASSERT__\r\n            Dbg_Message( \"Couldn't find asset %s to unload\", Script::FindChecksumName( animName ) );\r\n#endif\r\n        }\r\n\r\n        // load anim asset here!!!!\r\n        ass_man->LoadAnim( pFileName, animName, GetAnimationComponent()->GetAnimScriptName(), false, false );\r\n\r\n        this->SetAnim( animName );\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CViewerObject::UpdateWheels()\r\n{\r\n\tNx::CHierarchyObject* pHierarchyObjects = GetModel()->GetHierarchy();\r\n\tDbg_Assert( pHierarchyObjects );\r\n\r\n\tGfx::CSkeleton* pCarSkeleton = GetSkeletonComponent()->GetSkeleton();\r\n\tDbg_Assert( pCarSkeleton );\r\n\r\n\tDbg_MsgAssert( GetModel()->GetNumObjectsInHierarchy()==pCarSkeleton->GetNumBones(),\r\n\t\t\t\t   ( \"Skeleton and hierarchy doesn't match (%d hierarchy objs vs %d bones)\", \r\n\t\t\t\t    GetModel()->GetNumObjectsInHierarchy(), pCarSkeleton->GetNumBones() ) );\r\n\r\n\tstatic float s_wheelRotationX = 0.0f;\r\n\t\r\n\t// not frame rate independent (doesn't have valid m_time)\r\n\ts_wheelRotationX += ( Script::GetFloat(\"max_wheel_speed\", Script::ASSERT) * m_animSpeed );\r\n\r\n\t// make sure it's within bounds\r\n\twhile ( s_wheelRotationX > 360.0f )\r\n\t{\r\n\t\ts_wheelRotationX -= 360.0f;\r\n\t}\r\n\r\n\twhile ( s_wheelRotationX < 0.0f )\r\n\t{\r\n\t\ts_wheelRotationX += 360.0f;\r\n\t}\r\n\r\n\tif ( GetModel()->GetNumObjectsInHierarchy() > 5 )\r\n\t{\r\n\t\tMth::Matrix* pMatrices = pCarSkeleton->GetMatrices();\r\n\t\tDbg_Assert( pMatrices );\r\n\r\n\t\t// initialize the setup matrix once per frame\r\n\t\tfor ( int i = 0; i < GetModel()->GetNumObjectsInHierarchy(); i++ )\r\n\t\t{\t\t\t\t\t\t\r\n\t\t\t*(pMatrices + i) = ( pHierarchyObjects + i )->GetSetupMatrix();\r\n\t\t}\r\n\r\n\t\t// apply the appropriate rotations to the wheels\r\n\t\tfor ( int i = 2; i < 6; i++ )\r\n\t\t{\r\n\t\t\t(pMatrices + i)->RotateXLocal( s_wheelRotationX * 2.0f * Mth::PI / 360.0f );\r\n\t\t}\r\n\r\n\t\t// get children into object space\r\n\t\tfor ( int i = 1; i < 6; i++ )\r\n\t\t{\r\n\t\t\t*(pMatrices + i) *= *(pMatrices + 0); \r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CViewerObject::Update()\r\n{\r\n\tif ( GetAnimationComponent() )\r\n    {\r\n\t\tif ( m_showPanel )\r\n\t\t{\r\n\t\t\tif ( GetAnimationComponent()->AnimExists(GetAnimationComponent()->GetCurrentSequence()) )\r\n\t\t\t{\r\n\t\t\t\t// pass the pertinent info to the panel:\r\n\t\t\t\tScript::CStruct* pTempStruct = new Script::CStruct;\r\n\r\n\t\t\t\tchar line1[128];\r\n\t\t\t\tsprintf( line1, \"name %s\",\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\t\t\t\t Script::FindChecksumName( GetAnimationComponent()->GetCurrentSequence() )\r\n\t\t#else\r\n\t\t\t\t\t\t \"Unknown\"\r\n\t\t#endif\t\t\t\t  \r\n\t\t\t\t  );\r\n\r\n\t\t\t\tpTempStruct->AddString( \"line1\", (const char*)&line1 );\r\n\r\n\t\t\t\tchar line2[128];\r\n\t\t\t\tsprintf( line2, \"speed %f\", m_paused ? 0.0f : m_animSpeed );\r\n\t\t\t\tpTempStruct->AddString( \"line2\", (const char*)&line2 );\r\n\r\n\t\t\t\tchar line3[128];\r\n\t\t\t\tsprintf( line3, \"time %f of %f\", \r\n\t\t\t\t\t\t GetAnimationComponent()->GetCurrentAnimTime(), \r\n\t\t\t\t\t\t GetAnimationComponent()->AnimDuration( GetAnimationComponent()->GetCurrentSequence() ) );\r\n\t\t\t\tpTempStruct->AddString( \"line3\", (const char*)&line3 );\r\n\r\n\t\t\t\tchar line4[128];\r\n\t\t\t\tsprintf( line4, \"frame %d of %d\", (int)(GetAnimationComponent()->GetCurrentAnimTime() * 60.0f),\r\n\t\t\t\t\t\t (int)(GetAnimationComponent()->AnimDuration( GetAnimationComponent()->GetCurrentSequence() ) * 60.0f) );\r\n\t\t\t\tpTempStruct->AddString( \"line4\", (const char*)&line4 );\r\n\r\n\t\t\t\t// TODO:  Print out anim size\r\n\r\n\t\t\t\tScript::RunScript( \"draw_viewer_object_panel\", pTempStruct );\r\n\t\t\t\tdelete pTempStruct;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif ( GetModel()->GetNumObjectsInHierarchy() )\r\n\t{\r\n\t\tUpdateWheels();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CViewerObject::s_input_logic_code ( const Inp::Handler < CViewerObject >& handler )\r\n{       \r\n\tCViewerObject& obj = handler.GetData();\r\n \r\n\t// this is the minimum amount of time\r\n\t// you need to hold down the left/right keys\r\n\t// before it will auto repeat\r\n\tint vAUTO_REPEAT_TIME = Script::GetInteger( CRCD(0xe60442d5,\"ViewerAutoRepeatTime\"), Script::NO_ASSERT );\r\n\r\n\t// this is how fast it auto repeats\r\n\tint vAUTO_REPEAT_SPEED = Script::GetInteger( CRCD(0x2da212e5,\"ViewerAutoRepeatSpeed\"), Script::NO_ASSERT );\r\n\r\n\tstatic int s_auto_repeat_delay = vAUTO_REPEAT_TIME;\r\n\r\n\t// GJ:  no longer clearing the last frame's data\r\n\t// at the beginning of the loop...  this allows\r\n\t// us to override the m_commands from an external\r\n\t// class (useful for doing custom controller\r\n\t// configs for different viewer modes)\r\n//\tobj.m_commands.ClearAll();\r\n\r\n    if( handler.m_Input->m_Makes & Inp::Data::mD_TRIANGLE )\r\n\t{\r\n        obj.m_commands.SetMask( mTOGGLE_PANEL );\r\n\t}\r\n\r\n\tif ( handler.m_Input->m_Makes & Inp::Data::mD_LEFT )\r\n\t{\r\n\t\tobj.m_commands.SetMask( mDECREMENT_FRAME );\r\n\t\ts_auto_repeat_delay = vAUTO_REPEAT_TIME;\r\n\t}\r\n\telse if ( handler.m_Input->m_Makes & Inp::Data::mD_RIGHT )\r\n\t{\r\n\t\tobj.m_commands.SetMask( mINCREMENT_FRAME );\r\n\t\ts_auto_repeat_delay = vAUTO_REPEAT_TIME;\r\n\t}\r\n\telse if ( handler.m_Input->m_Buttons & Inp::Data::mD_LEFT )\r\n\t{\r\n\t\ts_auto_repeat_delay--;\r\n\t\tif ( s_auto_repeat_delay <= 0 )\r\n\t\t{\r\n\t\t\tobj.m_commands.SetMask( mDECREMENT_FRAME );\r\n\t\t\ts_auto_repeat_delay = vAUTO_REPEAT_SPEED;\r\n\t\t}\r\n\t}\r\n\telse if ( handler.m_Input->m_Buttons & Inp::Data::mD_RIGHT )\r\n\t{\r\n\t\ts_auto_repeat_delay--;\r\n\t\tif ( s_auto_repeat_delay <= 0 )\r\n\t\t{\r\n\t\t\tobj.m_commands.SetMask( mINCREMENT_FRAME );\r\n\t\t\ts_auto_repeat_delay = vAUTO_REPEAT_SPEED;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\ts_auto_repeat_delay = vAUTO_REPEAT_TIME;\r\n\t}\r\n\t\r\n\t// the viewer uses the global var \"viewer_controls_enabled\"\r\n\t// to decide whether certain viewer controls should be\r\n\t// active while in the regular viewer/light viewer.\r\n\t// rather than adding a new global var to distinguish\r\n\t// between the model viewer/light viewer, i've decided\r\n\t// to just have the viewer object handle those viewer\r\n\t// controls here\r\n\tif( handler.m_Input->m_Makes & Inp::Data::mD_L3 )\r\n\t{\r\n\t\tobj.m_commands.SetMask( mTOGGLE_ROTATE_MODE );\r\n\t}\r\n\t\r\n\tif ( handler.m_Input->m_Buttons & Inp::Data::mD_R1 )\r\n\t{\r\n\t\tif( !( handler.m_Input->m_Buttons & Inp::Data::mD_R2 ))\r\n\t\t{\r\n\t\t\tobj.m_commands.SetMask( mSTRAFE_UP );\r\n\t\t}\r\n\t}\r\n\telse if ( handler.m_Input->m_Buttons & Inp::Data::mD_R2 )\r\n\t{\r\n\t\tobj.m_commands.SetMask( mSTRAFE_DOWN );\r\n\t}\r\n\t\r\n\tif ( handler.m_Input->m_Makes & Inp::Data::mD_L1 )\r\n\t{\r\n\t\tobj.m_commands.SetMask( mINCREASE_SPEED );\r\n\t}\r\n\telse if ( handler.m_Input->m_Makes & Inp::Data::mD_L2 )\r\n\t{\r\n\t\tobj.m_commands.SetMask( mDECREASE_SPEED );\r\n\t}\r\n\t\r\n\tif ( !GetAnimationComponentFromObject( &obj ) )\r\n\t{\r\n\t\tif ( handler.m_Input->m_Buttons & Inp::Data::mD_CIRCLE )\r\n\t\t{\r\n\t\t\tobj.m_commands.SetMask( mROLL_LEFT );\r\n\t\t}\r\n\t\telse if ( handler.m_Input->m_Buttons & Inp::Data::mD_SQUARE )\r\n\t\t{\r\n\t\t\tobj.m_commands.SetMask( mROLL_RIGHT );\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CViewerObject::DoGameLogic()\r\n{\r\n\tif ( m_commands.TestMask( mTOGGLE_PANEL )\t)\r\n\t{\r\n\t\tm_showPanel = !m_showPanel;\r\n\t\t\r\n\t\tScript::RunScript( \"kill_viewer_object_panel\" );\r\n\t}\r\n\r\n\tif ( m_commands.TestMask( mINCREASE_SPEED ) )\r\n\t{\r\n\t\tChangeAnimSpeed( m_animSpeed + vSPEED_INCREMENT_AMOUNT );\r\n\t}\r\n\r\n\tif ( m_commands.TestMask( mDECREASE_SPEED ) )\r\n\t{\r\n\t\tChangeAnimSpeed( m_animSpeed - vSPEED_INCREMENT_AMOUNT );\r\n\t}\r\n\t\t\t\t\t\t\t\t\t\t\r\n\tif ( m_commands.TestMask( mINCREMENT_FRAME ) )\r\n\t{\r\n\t\tIncrementFrame( true );\r\n\t}\r\n\r\n\tif ( m_commands.TestMask( mDECREMENT_FRAME ) )\r\n\t{\r\n\t\tIncrementFrame( false );\r\n\t}\r\n\r\n\t// yuck:  the following creates a cyclic dependency\r\n\t// on viewer...  should get rid of this later.\r\n\tif ( m_commands.TestMask( mTOGGLE_ROTATE_MODE ) )\r\n\t{\r\n\t\tMdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();\r\n\t\tif ( pViewer )\r\n\t\t{\r\n\t\t\tpViewer->SetCommand( Mdl::CViewer::mTOGGLE_ROTATE_MODE );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( m_commands.TestMask( mSTRAFE_UP ) )\r\n\t{\r\n\t\tMdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();\r\n\t\tif ( pViewer )\r\n\t\t{\r\n\t\t\tpViewer->SetCommand( Mdl::CViewer::mSTRAFE_UP );\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( m_commands.TestMask( mSTRAFE_DOWN ) )\r\n\t{\r\n\t\tMdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();\r\n\t\tif ( pViewer )\r\n\t\t{\r\n\t\t\tpViewer->SetCommand( Mdl::CViewer::mSTRAFE_DOWN );\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( m_commands.TestMask( mROLL_LEFT ) )\r\n\t{\r\n\t\tMdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();\r\n\t\tif ( pViewer )\r\n\t\t{\r\n\t\t\tpViewer->SetCommand( Mdl::CViewer::mROLL_LEFT );\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( m_commands.TestMask( mROLL_RIGHT ) )\r\n\t{\r\n\t\tMdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();\r\n\t\tif ( pViewer )\r\n\t\t{\r\n\t\t\tpViewer->SetCommand( Mdl::CViewer::mROLL_RIGHT );\r\n\t\t}\r\n\t}\r\n\r\n\tUpdate();\r\n\t\r\n\t// GJ:  clear the frame's data, now that we're done with it\r\n\t// (this used to be done at the beginning of the loop)\r\n\tm_commands.ClearAll();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n"
  },
  {
    "path": "Code/Sk/Objects/ViewerObj.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       ViewerObj.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  1/21/2002\r\n//****************************************************************************\r\n\r\n#ifndef __VIEWER_OBJ_H\r\n#define __VIEWER_OBJ_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/support.h>\r\n\r\n#include <gel/inpman.h>\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n\r\n#include <gel/net/net.h>\r\n\r\n#include <sk/objects/movingobject.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Net\r\n{\r\n\tclass Server;\r\n};\r\n\r\nnamespace Nx\r\n{\r\n    class CModel;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\tclass CSkeletonComponent;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// a viewer object is similar to a moving object,\r\n// but without the physics.  a viewer object always\r\n// exists in the viewer, although it doesn't necessarily\r\n// have renderable model data associated with it\r\n\r\nclass CViewerObject : public CMovingObject\r\n{\r\npublic:\r\n\r\nenum ECommands\r\n{\r\n    mLOAD_SKATER        = nBit( 1 ),\r\n\tmLOAD_PEDESTRIAN\t= nBit( 2 ),\r\n    mGOTO_NEXT_ANIM\t\t= nBit( 3 ),\r\n    mGOTO_PREV_ANIM\t\t= nBit( 4 ),\r\n    mGOTO_FIRST_ANIM\t= nBit( 5 ),\r\n    mINCREASE_SPEED \t= nBit( 6 ),\r\n    mDECREASE_SPEED     = nBit( 7 ),\r\n    mINCREMENT_FRAME \t= nBit( 8 ),\r\n    mDECREMENT_FRAME    = nBit( 9 ),\r\n    mSHOW_PANEL    \t\t= nBit( 10 ),\r\n    mHIDE_PANEL    \t\t= nBit( 11 ),\r\n    mTOGGLE_PANEL    \t= nBit( 12 ),\r\n\tmSTRAFE_UP   \t    = nBit( 13 ),\r\n\tmSTRAFE_DOWN        = nBit( 14 ),\r\n\tmROLL_LEFT          = nBit( 15 ),\r\n\tmROLL_RIGHT         = nBit( 16 ),\r\n\tmTOGGLE_ROTATE_MODE = nBit( 17 ),\r\n};\r\n\r\npublic:\r\n    CViewerObject( Net::Server* pServer );\r\n    virtual     ~CViewerObject();\r\n\tvoid\t\tSetRotation( float rotZ, float rotX );\r\n\tvoid        LoadModel( Script::CStruct* pParams );\r\n\tvoid\t\tUnloadModel();\r\n\tvoid\t\tSetAnim( uint32 animName );\r\n\tvoid\t\tReloadAnim( const char* pAnim, uint32 animName );\r\n    \r\nprotected:\r\n\tvoid\t\tDoGameLogic();\r\n    void        Update();\r\n\tvoid\t\tUpdateWheels();\r\n    \r\nprotected:\r\n\tvoid\t\tChangeAnimSpeed( float animSpeed );\r\n\tvoid\t\tIncrementFrame( bool forwards );\r\n\r\nprotected:\r\n\tstatic \t\tNet::MsgHandlerCode\t\ts_handle_set_anim;\r\n\tstatic \t\tNet::MsgHandlerCode\t\ts_handle_set_anim_speed;\r\n\tstatic \t\tNet::MsgHandlerCode\t\ts_handle_increment_frame;\r\n\tstatic\t\tNet::MsgHandlerCode\t\ts_handle_reload_anim;\r\n\tstatic\t\tNet::MsgHandlerCode\t\ts_handle_reload_cam_anim;\r\n\tstatic\t\tNet::MsgHandlerCode\t\ts_handle_sequence_preview;\r\n\r\n    static\t\tInp::Handler< CViewerObject >::Code \ts_input_logic_code;\r\n\r\n    Inp::Handler< CViewerObject >*\tmp_input_handler;\r\n    Tsk::Task< CViewerObject >*     mp_logic_task;\r\n\r\n\tFlags<ECommands>\t\t\t\tm_commands;\r\n\r\nprotected:\r\n\tNet::Server*\t\t\t\t\tmp_server;\r\n    float       \t\t\t\t\tm_animSpeed;\r\n\tbool\t\t\t\t\t\t\tm_paused;\r\n\tbool\t\t\t\t\t\t\tm_showPanel;\r\n};\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __VIEWER_OBJ_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/car.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       car.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/24/2000\r\n//****************************************************************************\r\n\r\n/*\r\n\tMD:  The car is just a moving object with a special ground collision \r\n\tfunction, and the functionality to rotate wheels based on the car's \r\n\tvelocity and turn the wheels based on the change in the car's direction. \r\n*/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/objects/car.h>\r\n\r\n#include <gel/mainloop.h>\r\n#include <gel/objman.h>\t\t\t\t\r\n#include <gel/objsearch.h>\t\t\t\t\r\n                         \r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\t \r\n#include <gel/scripting/struct.h>\t \r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gel/components/carphysicscomponent.h>\r\n#include <gel/components/collisioncomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/motioncomponent.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n#include <gel/components/suspendcomponent.h>\r\n#include <gel/components/nodearraycomponent.h>\r\n#include <gel/components/railmanagercomponent.h>\r\n#include <gel/components/objecthookmanagercomponent.h>\r\n#include <gel/components/skitchcomponent.h>\r\n\r\n#include <gfx/debuggfx.h>\r\n#include <gfx/gfxutils.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxgeom.h>\r\n#include <gfx/nxhierarchy.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/skeleton.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/pathob.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/scripting/nodearray.h>\t \r\n\r\n#include <sys/profiler.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define DEFAULT_CAR_TURN_DIST\t\t\t\t20.0f\r\n#define DEFAULT_CAR_MAX_VEL \t\t\t\t30.0f\r\n#define\tDEFAULT_CAR_ACCELERATION\t\t\t18.0f\r\n#define DEFAULT_CAR_HEIGHT_OFFSET  \t\t\t0.0f\r\n#define DEFAULT_CAR_DECELERATION\t\t\t32.0f\r\n#define DEFAULT_EMERGENCY_DECELERATION\t\t20.0f\r\n#define DEFAULT_CAR_MIN_STOP_VEL\t\t\t4.0f\t\t//mph at which the brakes overpower momentum.\r\n#define DEFAULT_CAR_STOP_DIST_SPEED_MULT\t1.0f\t\t//stopping distance required depends on speed*this\r\n\r\n#define MAX_CAR_SPEED 85\r\n\t\r\n#define MAX_WHEEL_Y_ROT ( 70.0f )\r\n#define MAX_CAR_X_ROT ( 5.0f )\r\n#define MIN_CAR_X_ROT ( -5.0f )\r\n#define STEP_CAR_X_ROT ( 0.125f )\r\n#define ACCEL_TO_CAR_ROT_FACTOR ( 3.0f )\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCar::update_wheels()\r\n{\r\n#if 1\r\n\t// rotate based on forward speed\r\n\tGetCarPhysicsComponent()->m_wheelRotationX += ( ( Tmr::FrameRatio() ) * ( GetMotionComponent()->m_vel_z * 90.0f ) / ( MPH_TO_IPS( MAX_CAR_SPEED ) ) );\r\n#else\r\n\t// rotate at constant rate\r\n\tGetCarPhysicsComponent()->m_wheelRotationX += ( 2.0f * Tmr::FrameRatio() );\r\n#endif\r\n\t\r\n\t// make sure it's within bounds\r\n\twhile ( GetCarPhysicsComponent()->m_wheelRotationX > 360.0f )\r\n\t{\r\n\t\tGetCarPhysicsComponent()->m_wheelRotationX -= 360.0f;\r\n\t}\r\n\r\n\twhile ( GetCarPhysicsComponent()->m_wheelRotationX < 0.0f )\r\n\t{\r\n\t\tGetCarPhysicsComponent()->m_wheelRotationX += 360.0f;\r\n\t}\r\n\r\n\tif ( GetMotionComponent()->GetPathOb() )\r\n\t{\r\n\t\tif ( GetMotionComponent()->GetPathOb()->m_y_rot )\r\n\t\t{\r\n\t\t\tMth::Vector radiusVec = GetMotionComponent()->GetPathOb()->m_nav_pos - GetMotionComponent()->GetPathOb()->m_circle_center;\r\n\t\t\tfloat turningRadius = radiusVec.Length();\r\n\r\n#ifdef __PLAT_NGPS__\r\n\t\t\tfloat ang = asinf( GetCarPhysicsComponent()->m_distanceBetweenTires / turningRadius );\r\n#else\r\n\t\t\tfloat a_ang = GetCarPhysicsComponent()->m_distanceBetweenTires / turningRadius;\r\n\t\t\tif ( a_ang > 1.0f ) a_ang = 1.0f;\r\n\t\t\tif ( a_ang < -1.0f ) a_ang = -1.0f;\r\n\t\t\tfloat ang = asinf( a_ang );\r\n#endif\t\t// __PLAT_NGPS__\r\n\t\t\tGetCarPhysicsComponent()->m_targetWheelRotationY = Mth::RadToDeg(-ang);\r\n\t\t\tif ( GetMotionComponent()->GetPathOb()->m_y_rot < 0.0f )\r\n\t\t\t{\r\n\t\t\t\tGetCarPhysicsComponent()->m_targetWheelRotationY = -GetCarPhysicsComponent()->m_targetWheelRotationY;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tGetCarPhysicsComponent()->m_targetWheelRotationY = 0.0f;\r\n\t\t}\r\n\t\t\r\n\t    GetCarPhysicsComponent()->m_wheelRotationY = Mth::FRunFilter( GetCarPhysicsComponent()->m_targetWheelRotationY, GetCarPhysicsComponent()->m_wheelRotationY, Tmr::FrameRatio() );\r\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\telse\r\n\t{\r\n\t\tGetCarPhysicsComponent()->m_wheelRotationY = 0.0f;\r\n\t}\r\n\r\n\tfloat deltaZ = GetMotionComponent()->m_vel_z - GetCarPhysicsComponent()->m_old_vel_z;\r\n\r\n\tGetCarPhysicsComponent()->m_old_vel_z = GetMotionComponent()->m_vel_z;\r\n\r\n\tif ( Script::GetInt( CRCD(0x4cf13d8f,\"car_debug\"), Script::NO_ASSERT ) )\r\n\t{\r\n\t\tGetCarPhysicsComponent()->m_minCarRot = Script::GetFloat( CRCD(0x877db8da,\"accelCarRot\"), Script::ASSERT );\r\n\t\tGetCarPhysicsComponent()->m_maxCarRot = Script::GetFloat( CRCD(0xfb3464df,\"decelCarRot\"), Script::ASSERT );\r\n\t\tGetCarPhysicsComponent()->m_stepCarRot = Script::GetFloat( CRCD(0xfd8bc8d6,\"speedCarRot\"), Script::ASSERT );\r\n\t\tGetCarPhysicsComponent()->m_accelToCarRotFactor = Script::GetFloat( CRCD(0xb2c7447b,\"accelCarRotFactor\"), Script::ASSERT );\r\n//\t\tGetCarPhysicsComponent()->m_enter_turn_dist = Script::GetFloat( \"turnDist\", Script::ASSERT );\r\n\t}\r\n\r\n\t// vACCELERATION_TO_ROTATION_CONSTANT = magic number \r\n\t// that happens to look good, but it can be tweaked \r\n\t// later if necessary (or moved into script on a \r\n\t// per-car basis).\r\n\tGetCarPhysicsComponent()->m_targetCarRotationX = -deltaZ / GetCarPhysicsComponent()->m_accelToCarRotFactor;\r\n\r\n\tif ( GetCarPhysicsComponent()->m_targetCarRotationX > GetCarPhysicsComponent()->m_maxCarRot )\r\n\t{\r\n\t\tGetCarPhysicsComponent()->m_targetCarRotationX = GetCarPhysicsComponent()->m_maxCarRot;\r\n\t}\r\n\tif ( GetCarPhysicsComponent()->m_targetCarRotationX < GetCarPhysicsComponent()->m_minCarRot )\r\n\t{\r\n\t\tGetCarPhysicsComponent()->m_targetCarRotationX = GetCarPhysicsComponent()->m_minCarRot;\r\n\t}\r\n\r\n    GetCarPhysicsComponent()->m_carRotationX = Mth::FRunFilter( GetCarPhysicsComponent()->m_targetCarRotationX, GetCarPhysicsComponent()->m_carRotationX, GetCarPhysicsComponent()->m_stepCarRot * Tmr::FrameRatio() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CalculateCarHierarchyMatrices( Gfx::CSkeleton* pSkeleton,\r\n                                    Nx::CModel *p_renderedModel, \r\n\t\t\t\t\t\t\t\t\tfloat carRotationX, \r\n\t\t\t\t\t\t\t\t\tfloat wheelRotationX, \r\n\t\t\t\t\t\t\t\t\tfloat wheelRotationY)\r\n{\r\n\tDbg_Assert( p_renderedModel );\r\n\tGfx::CSkeleton* pCarSkeleton = pSkeleton;\r\n\tDbg_Assert( pCarSkeleton );\r\n\r\n\t// TODO:  Possibly set up the setup matrix only once,\r\n\t// and then prerotate the rotation?\r\n\t\r\n\tNx::CHierarchyObject* pHierarchyObjects = p_renderedModel->GetHierarchy();\r\n\tMth::Matrix* pMatrices = pCarSkeleton->GetMatrices();\r\n\r\n\tfloat carRotationXInRadians = Mth::DegToRad( carRotationX );\r\n\tfloat wheelRotationYInRadians = Mth::DegToRad( wheelRotationY );\r\n\tfloat wheelRotationXInRadians = Mth::DegToRad( wheelRotationX );\r\n\r\n\tNx::CHierarchyObject* pCurrentHierarchyObject = pHierarchyObjects;\r\n\tfor ( int i = 0; i < pCarSkeleton->GetNumBones(); i++ )\r\n\t{\r\n\t\tMth::Matrix* pMatrix = pMatrices + pCurrentHierarchyObject->GetBoneIndex();\r\n\t\t\r\n\t\t// initialize the setup matrix once per frame\r\n\t\t*pMatrix = pCurrentHierarchyObject->GetSetupMatrix();\t\r\n\r\n\t\tswitch ( pCurrentHierarchyObject->GetChecksum() )\r\n\t\t{\r\n\t\t\t// front wheels\r\n\t\t\tcase 0x6e2f434e:\t// car_wheel01\r\n\t\t\tcase 0xf72612f4:\t// car_wheel02\r\n\t\t\t\t\r\n\t\t\t\t// apply steering to the front tires\r\n\t\t\t\tpMatrix->RotateZLocal( wheelRotationYInRadians );\r\n\r\n\t\t\t\t// spin wheels\r\n\t\t\t\tpMatrix->RotateXLocal( wheelRotationXInRadians );\r\n\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t// back wheels\r\n\t\t\tcase 0x80212262:\t// car_wheel03\r\n\t\t\tcase 0x1e45b7c1:\t// car_wheel04\r\n\t\t\t\t\r\n\t\t\t\t// spin wheels\r\n\t\t\t\tpMatrix->RotateXLocal( wheelRotationXInRadians );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t// middle wheels\r\n\t\t\tcase 0x69428757:\t// car_wheel05\r\n\t\t\tcase 0xf04bd6ed:\t// car_wheel06\r\n\t\t\t\t\r\n\t\t\t\t// spin wheels\r\n\t\t\t\tpMatrix->RotateXLocal( wheelRotationXInRadians );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 0x88c21962:\t// car\r\n\r\n\t\t\t\t// rock the car back and forth\r\n\t\t\t\tpMatrix->RotateXLocal( carRotationXInRadians );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 0x92e19120:\t// car_shadow\r\n\t\t\t\t// do nothing\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"Unrecognized bone name %s while animating car parts (bone %d)\\nCar parts MUST be named be car_wheel01, car_wheel02, car_wheel03, car_wheel04, car_wheel05, car_wheel06, car, or car_shadow\", Script::FindChecksumName(pCurrentHierarchyObject->GetChecksum() ), i) );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// get children into object space\r\n\t\tif ( i != 0 )\r\n\t\t{\r\n\t\t\t*pMatrix *= *( pMatrices + pCurrentHierarchyObject->GetParentIndex() );\r\n\t\t}\r\n\r\n\t\tpCurrentHierarchyObject++;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCar::display_wheels()\r\n{\r\n\tCalculateCarHierarchyMatrices(this->GetSkeleton(),GetModel(),GetCarPhysicsComponent()->m_carRotationX,GetCarPhysicsComponent()->m_wheelRotationX,GetCarPhysicsComponent()->m_wheelRotationY);\r\n\t\r\n\t// scale down the shadow to nothing...  must be done after all the \r\n\t// children's matrices have been calculated...  this also assumes\r\n\t// the shadow is the first matrix...  if it's not, we'd have to\r\n\t// search for the correct matrix by name\r\n\tif ( !GetCarPhysicsComponent()->m_shadowEnabled )\r\n\t{\r\n\t\tMth::Matrix mat;\r\n\t\tmat.Ident();\r\n\t\tmat.Scale(Mth::Vector(0.0f,0.0f,0.0f,1.0f));\r\n\t\t\r\n\t\tMth::Matrix* pMatrices = GetSkeleton()->GetMatrices();\r\n\t\t*pMatrices = mat;\r\n\t}\r\n}\r\n\r\n#if 0\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCar::debug_wheels()\r\n{\r\n\tDbg_Assert( GetModel() );\r\n\tGfx::CSkeleton* pCarSkeleton = this->GetSkeleton();\r\n\tDbg_Assert( pCarSkeleton );\r\n\r\n\t// draw skeleton\r\n\tfor ( int i = 0; i < 6; i++ )\r\n\t{\r\n\t\tMth::Matrix objMatrix = m_matrix;\r\n\t\tobjMatrix[Mth::POS] = m_pos;\r\n\r\n\t\tMth::Matrix wsMatrix = *(pCarSkeleton->GetMatrices() + i) * objMatrix;\r\n\r\n\t\tMth::Vector pos = wsMatrix[Mth::POS];\r\n\t\tpos[Y] += 48.0f;\r\n\t\twsMatrix[Mth::POS] = Mth::Vector( 0.0f, 0.0f, 0.0f, 1.0f );\r\n        \r\n\t\t// set up bounding box\r\n\t\tSBBox theBox;\r\n\t\ttheBox.m_max.Set(10.0f, 10.0f, 10.0f);\r\n\t\ttheBox.m_min.Set(-10.0f, -10.0f, -10.0f);    \r\n\r\n\t\t// For now, draw a bounding box\r\n\t\tGfx::AddDebugBox( wsMatrix, pos, &theBox, NULL, 1, NULL ); \r\n\t}\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCar::InitCar( CGeneralManager* p_obj_man, Script::CStruct* pNodeData )\r\n{\r\n\tp_obj_man->RegisterObject(*this);\r\n\r\n\tMovingObjectCreateComponents();\r\n\r\n\tuint32 skeletonName = CRCD(0x88c21962,\"car\");\r\n\tbool use_skeletal_cars = false;\r\n\r\n\tif ( pNodeData->GetChecksum( CRCD(0x09794932,\"skeletonName\"), &skeletonName, false ) )\r\n\t{\r\n\t\tuse_skeletal_cars = true;\r\n\t}\r\n\r\n\tif ( use_skeletal_cars )\r\n\t{\r\n//\t\tm_model_restoration_info.mSkeletonName=skeletonName;\r\n\t\t// component-based\r\n\t\tDbg_MsgAssert( GetSkeletonComponent() == NULL, ( \"Skeleton component already exists\" ) );\r\n\t\tScript::CStruct* pSkeletonStruct = new Script::CStruct;\r\n\t\tpSkeletonStruct->AddChecksum( CRCD(0xb6015ea8,\"component\"), CRC_SKELETON );\r\n\t\tpSkeletonStruct->AddChecksum( CRCD(0x222756d5,\"skeleton\"), skeletonName );\r\n\t\tthis->CreateComponentFromStructure(pSkeletonStruct, NULL);\r\n\t\tdelete pSkeletonStruct;\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\t\tGfx::CSkeleton* pSkeleton = GetSkeletonComponent()->GetSkeleton();\r\n\t\tDbg_Assert( pSkeleton );\r\n\t\tDbg_Assert( pSkeleton->GetNumBones() > 0 );\r\n#endif\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tm_model_restoration_info.mSkeletonName=0;\r\n\t}\t\r\n\t\r\n\tMovingObjectInit( pNodeData, p_obj_man );\r\n\t\r\n\tObj::CModelComponent* pModelComponent = new Obj::CModelComponent;\r\n\tthis->AddComponent( pModelComponent );\r\n\tpModelComponent->InitFromStructure( pNodeData );\r\n\t\r\n\tDbg_Assert( GetModel() );\r\n\r\n\t// set up the skeleton for this car model, if any\r\n\t// needs to come after the geom is loaded (because\r\n\t// that's where the hierarchy info is)\r\n\tif ( use_skeletal_cars )\r\n\t{\t\t\r\n\t\tconst char* p_model_name;\r\n\t\tpNodeData->GetText( CRCD(0x286a8d26,\"model\"), &p_model_name, true );\r\n\r\n\t\t// sanity check on number of bones in skeleton\r\n\t\tDbg_MsgAssert( GetModel()->GetNumObjectsInHierarchy()==GetSkeleton()->GetNumBones(), \r\n\t\t\t\t\t   ( \"Expected to find %d bones in the %s skeleton (found %d in %s - %s)\",\r\n\t\t\t\t\t\t GetSkeleton()->GetNumBones(),\r\n\t\t\t\t\t\t Script::FindChecksumName( skeletonName ),\r\n\t\t\t\t\t\t GetModel()->GetNumObjectsInHierarchy(),\r\n\t\t\t\t\t\t Script::FindChecksumName( GetID() ),\r\n\t\t\t\t\t\t p_model_name ) );\r\n\t\t\r\n\t\tGetCarPhysicsComponent()->init_car_skeleton();\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( GetModel()->GetNumObjectsInHierarchy()!=0 )\r\n\t\t{\r\n\t\t\tuint32 name = 0;\r\n\t\t\tpNodeData->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &name, Script::ASSERT );\r\n\t\t\tDbg_MsgAssert( 0, ( \"Skeletal model requires a skeleton %s\", Script::FindChecksumName(name) ) );\r\n\t\t}\r\n\t}\r\n\r\n\tGetCarPhysicsComponent()->InitFromStructure( pNodeData );\r\n\r\n\tif ( !pNodeData->ContainsFlag( CRCD(0x0bf29bc0,\"NoCollision\") ) )\r\n\t{\r\n\t\t// GJ:  collision component should be added after the model component,\r\n\t\t// because we want the same m_pos/m_matrix that is used for displaying\r\n\t\t// the model\r\n\t\tDbg_MsgAssert( GetCollisionComponent() == NULL, ( \"Collision component already exists\" ) );\r\n\t\tScript::CStruct* pCollisionStruct = new Script::CStruct;\r\n\t\tpCollisionStruct->AddChecksum( CRCD(0xb6015ea8,\"component\"), CRC_COLLISION );\r\n\t\tpCollisionStruct->AddChecksum( CRCD(0x2d7e583b,\"collisionMode\"), CRCD(0x6aadf154,\"geometry\") );\r\n\t\tthis->CreateComponentFromStructure(pCollisionStruct, NULL);\r\n\t\tdelete pCollisionStruct;\r\n\t}\r\n\r\n\t// designer controlled variables:\r\n\t// set defaults, to be overridden by script values if they exist:\r\n\tGetMotionComponent()->m_max_vel = ( MPH_TO_INCHES_PER_SECOND ( DEFAULT_CAR_MAX_VEL ) );\r\n\tGetMotionComponent()->m_acceleration = FEET_TO_INCHES( DEFAULT_CAR_ACCELERATION );\r\n\tGetMotionComponent()->m_deceleration = FEET_TO_INCHES( DEFAULT_CAR_DECELERATION );\r\n\t\r\n\t// stick to ground tests against wheels, rather than origin\r\n\t// (eventually, we'll move this functionality into a custom\r\n\t// sticktoground component)\r\n\tGetMotionComponent()->m_point_stick_to_ground = false;\r\n\r\n\tGetMotionComponent()->EnsurePathobExists( this );\r\n\tGetMotionComponent()->GetPathOb()->m_enter_turn_dist = FEET_TO_INCHES( DEFAULT_CAR_TURN_DIST );\r\n\t\r\n\t// Add a NodeArrayComponent to the Car, so it will request loading of the associated node array.\r\n\tObj::CNodeArrayComponent *p_node_array_component = new Obj::CNodeArrayComponent;\r\n\tthis->AddComponent( p_node_array_component );\r\n\tp_node_array_component->InitFromStructure( pNodeData );\r\n\r\n\tif ( !pNodeData->ContainsFlag( CRCD(0x1fb9e477,\"NoRail\") ) )\r\n\t{\r\n\t\t// Add a RailManagerComponent to the Car, so it can be used for grinding etc.\r\n\t\tObj::CRailManagerComponent *p_rail_manager_component = new Obj::CRailManagerComponent;\r\n\t\tthis->AddComponent( p_rail_manager_component );\r\n\t\tp_rail_manager_component->InitFromStructure( pNodeData );\r\n\t}\r\n\r\n\tif ( !pNodeData->ContainsFlag( CRCD(0x59793e2b,\"NoSkitch\") ) )\r\n\t{\r\n\t\t// Add an ObjectHookManagerComponent to the Car, for use by the SkitchComponent.\r\n\t\tObj::CObjectHookManagerComponent *p_object_hook_manager_component = new Obj::CObjectHookManagerComponent;\r\n\t\tthis->AddComponent( p_object_hook_manager_component );\r\n\t\tp_object_hook_manager_component->InitFromStructure( pNodeData );\r\n\r\n\t\t// Add a SkitchComponent to the Car, so it can be used for skitching etc.\r\n\t\tObj::CSkitchComponent *p_skitch_component = new Obj::CSkitchComponent;\r\n\t\tthis->AddComponent( p_skitch_component );\r\n\t\tp_skitch_component->InitFromStructure( pNodeData );\r\n\t}\r\n\r\n\t// Finalize the object, saying we've added all the components\r\n\tFinalize();\r\n\t\r\n\t// need to synchronize rendered model's position to initial world position\r\n\tGetModelComponent()->FinalizeModelInitialization();\r\n\r\n\tSetProfileColor(0xc0c000);\t\t\t\t// cyan = car\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCar::DoGameLogic()\r\n{\r\n\tDbg_MsgLog((\"DoGameLogic for car '%s'\",Script::FindChecksumName(GetID())));\r\n\t\r\n\tif ( GetSuspendComponent()->SkipLogic( ) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tif ( IsDead() )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Don't update the wheels if we should not animate\r\n\t// (and this cunningly lets the SuspendComponment actually work, by clearing the initial_animations\t\r\n\tif (GetSuspendComponent()->should_animate( ))\r\n\t{\r\n\t\t// check to see if it's got a hierarchy\r\n\t\t// if it does, then update the wheels\r\n\t\tGfx::CSkeleton* pCarSkeleton = this->GetSkeleton();\r\n\t\tif ( pCarSkeleton )\r\n\t\t{\r\n\t\t\tupdate_wheels();\r\n\t\r\n\t\t\tdisplay_wheels();\r\n\t\t\t\r\n//\t\t\tdebug_wheels();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCar::CallMemberFunction( uint32 Checksum, Script::CScriptStructure *pParams, Script::CScript *pScript )\r\n{   \r\n\treturn CMovingObject::CallMemberFunction( Checksum, pParams, pScript );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCar::CCar ( void )\r\n{\r\n\tm_type = SKATE_TYPE_CAR;\r\n\r\n\tObj::CCarPhysicsComponent* pCarPhysicsComponent = new Obj::CCarPhysicsComponent;\r\n\tAddComponent( pCarPhysicsComponent );\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCar::~CCar ( void )\r\n{   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CreateCar(CGeneralManager* p_obj_man, Script::CStruct* pNodeData)\r\n{\r\n\tCCar* pCar = new CCar;\r\n    Dbg_MsgAssert(pCar, (\"Failed to create car.\"));\r\n\t\r\n\t// get position, from the node that created us:\r\n\tSkateScript::GetPosition( pNodeData, &pCar->m_pos );\r\n    \r\n\tpCar->InitCar(p_obj_man, pNodeData);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CreateCar(CGeneralManager* p_obj_man, int nodeNumber)\r\n{\r\n\tScript::CStruct* pNodeData = SkateScript::GetNode(nodeNumber);\r\n\tCreateCar(p_obj_man, pNodeData);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n"
  },
  {
    "path": "Code/Sk/Objects/car.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObject (OBJ)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobjects/car.h\t    \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t10/15/00\t-\tmjd\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __OBJECTS_CAR_H\r\n#define __OBJECTS_CAR_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <sk/objects/movingobject.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Script\r\n{\r\n\tclass CScript;\r\n\tclass CStruct;\r\n}\r\n\t\t\t\t \r\nnamespace Obj\r\n{\r\n\r\n\tclass CGeneralManager;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid CreateCar( CGeneralManager *p_obj_man, int nodeNum );\r\nvoid CreateCar( CGeneralManager* p_obj_man, Script::CStruct* pNodeData);\r\n\r\nclass CCar : public CMovingObject \r\n{\t\t\r\n\r\npublic:\r\n\t\t\t\t\tCCar ( void );\r\n\tvirtual\t\t\t~CCar ( void );\r\n\tvoid\t\t\tInitCar( CGeneralManager* p_obj_man, Script::CStruct* pNodeData );\r\n\tbool\t\t\tCallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript );\r\n\t\r\nprotected:\r\n\tvoid\t\t\tupdate_wheels();\r\n\tvoid\t\t\tdisplay_wheels();\r\n\tvoid\t\t\tdebug_wheels();\r\n\tvoid\t\t\tDoGameLogic();\t\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid CalculateCarHierarchyMatrices( Gfx::CSkeleton* pSkeleton,\r\n                                    Nx::CModel *p_renderedModel, \r\n\t\t\t\t\t\t\t\t\tfloat carRotationX, \r\n\t\t\t\t\t\t\t\t\tfloat m_wheelRotationX, \r\n\t\t\t\t\t\t\t\t\tfloat m_wheelRotationY);\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_CAR_H\r\n"
  },
  {
    "path": "Code/Sk/Objects/crown.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tskate4\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tCCrown\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCrown.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t08/06/01\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tKing of the Hill Crown Object\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/objects/crown.h>\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gel/objman.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/motioncomponent.h>\r\n#include <gel/components/suspendcomponent.h>\r\n\t\t\t\t\t \r\n#include <gfx/gfxutils.h>\r\n#include <gfx/debuggfx.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/skeleton.h>\r\n\r\n#include <sk/objects/skater.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nconst float CCrown::vCROWN_RADIUS = FEET( 8.0f );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCrown::DoGameLogic()\r\n{\r\n\tif ( m_on_king )\r\n\t{\r\n\t\tGfx::CSkeleton* pSkeleton;\r\n\t\tpSkeleton = mp_king->GetSkeleton();\r\n\t\tDbg_Assert( pSkeleton );\r\n\r\n\t\tpSkeleton->GetBoneMatrix( CRCD(0xddec28af,\"Bone_Head\"), &m_matrix );\r\n\r\n\t\tm_matrix.RotateXLocal( 90.0f );\r\n\r\n\t\t// raise the crown by 1 foot\r\n\t\t//m_matrix.TranslateLocal( Mth::Vector( 0.0f, FEET(1.0f), 0.0f, 0.0f ) );\r\n\t\tm_matrix.TranslateLocal( Mth::Vector( 0.0f, 0.0f, -FEET(1.5f), 0.0f ) );\r\n\r\n\t\tMth::Vector crownOffset = m_matrix[Mth::POS];\r\n\t\tm_matrix[Mth::POS] = Mth::Vector( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\t\t\r\n// for some reason, the below doesn't work as expected.\r\n// so instead, use the skater's root matrix for the orientation\r\n\r\n\t\tm_matrix = m_matrix * mp_king->GetMatrix();\r\n\r\n//\t\tm_matrix = mp_king->GetMatrix();\r\n\r\n\t\tm_pos = mp_king->GetMatrix().Transform( crownOffset );\r\n\t\tm_pos += mp_king->m_pos;\r\n\t\t\r\n//\t\tGfx::AddDebugStar( m_pos, 10, 0x0000ffff, 1 );\r\n\t}\r\n\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCCrown::CCrown( void )\r\n{\r\n\tSetID( Script::GenerateCRC( \"crown_object\" ));\r\n\r\n#if 0\t\r\n\t// GJ:  Why is the crown not registered here, instead of in InitCrown?\r\n\tp_obj_man->RegisterObject( *this );\r\n#endif\r\n\t\r\n    m_on_king = false;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCrown::~CCrown( void )\r\n{\t\r\n\tRemoveFromWorld();\r\n\r\n\tm_on_king = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCrown::PlaceOnKing( CSkater* king )\r\n{   \r\n\tmp_king = king;\r\n    \r\n    m_on_king = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCrown::RemoveFromWorld( void )\r\n{\r\n\tm_on_king = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCCrown::RemoveFromKing( void )\r\n{\r\n\tm_on_king = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCCrown::OnKing( void )\r\n{\r\n\treturn m_on_king;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCrown::InitCrown( CGeneralManager* p_obj_man, Script::CStruct* pNodeData )\r\n{   \r\n\tp_obj_man->RegisterObject( *this );\r\n\t\r\n\tMovingObjectCreateComponents();\r\n\r\n\t// Create an empty model \r\n\tDbg_MsgAssert( GetModelComponent() == NULL, ( \"Model component already exists\" ) );\r\n\tScript::CStruct* pModelStruct = new Script::CStruct;\r\n\tpModelStruct->AddChecksum( CRCD(0xb6015ea8,\"component\"), CRC_MODEL );\r\n\tthis->CreateComponentFromStructure(pModelStruct, NULL);\r\n\tdelete pModelStruct;\r\n\t\r\n\tMovingObjectInit( pNodeData, p_obj_man );\r\n\tSetID( Script::GenerateCRC( \"crown_object\" ));\r\n\t\r\n\tObj::CSuspendComponent* pSuspendComponent = GetSuspendComponent();\r\n\tDbg_MsgAssert( pSuspendComponent, ( \"No suspend component?\" ) );\r\n\tpSuspendComponent->m_lod_dist[0] = 1000000;\r\n\tpSuspendComponent->m_lod_dist[1] = 1000001;\r\n\tpSuspendComponent->m_lod_dist[2] = 1000002;  // Note, this is used as a magic number to turn off the high level culling\r\n\tpSuspendComponent->m_lod_dist[3] = 1000003;\r\n\r\n\tStr::String fullModelName;\r\n//\tfullModelName = Gfx::GetModelFileName(\"gameobjects/skate/letter_a/letter_a.mdl\", \".mdl\");\r\n\tfullModelName = Gfx::GetModelFileName(\"crown\", \".mdl\");\r\n\t// Model file name should look like this:  \"models/testcar/testcar.mdl\"\r\n\tDbg_Printf( \"Initializing Crown using file %s\\n\", fullModelName.getString() );\r\n\tGetModel()->AddGeom( fullModelName.getString(), 0, true );\r\n\t\r\n\tGetModel()->SetActive( true );\r\n\tSkateScript::GetPosition( pNodeData, &m_pos );\r\n\tDbg_Printf( \"Placing crown at %f %f %f\\n\", m_pos[X], m_pos[Y], m_pos[Z] );\r\n\r\n\tFinalize();\r\n\r\n\tGetModelComponent()->FinalizeModelInitialization();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n} // namespace Obj\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/crown.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tskate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tCrown\t\t\t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tCrown.h\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t08/06/01\t-\tSPG\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tKing of the Hill crown object\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __OBJECTS_CROWN_H\r\n#define __OBJECTS_CROWN_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/macros.h>\r\n#include <core/math.h>\r\n\r\n#include <sk/objects/movingobject.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\nclass CSkater;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  CCrown : public CMovingObject \r\n{\t\t\r\npublic:\r\n\tstatic const float vCROWN_RADIUS;\r\n\r\npublic:\r\n\tCCrown ( void );\r\n\tvirtual\t~CCrown ( void );\r\n\t\r\n\tvoid\t\t\tInitCrown( CGeneralManager* p_obj_man, Script::CStruct* pNodeData );\r\n\tvoid\t\t\tPlaceOnKing( CSkater* king );\r\n\tvoid\t\t\tRemoveFromWorld( void );\r\n\tvoid\t\t\tRemoveFromKing( void );\r\n\tMth::Vector& \tGetPosition( void ) {return m_pos;}\r\n\tvoid\t\t\tSetPosition( Mth::Vector& pos ) { m_pos = pos; }\r\n\tbool\t\t\tOnKing( void );\r\n\tvoid\t\t\tDoGameLogic();\r\n\r\nprotected:\t\r\n\tCSkater* \t\tmp_king;\r\n\tuint32\t\t\tm_head_bone_index;\r\n\tbool\t\t\tm_on_king;\r\n\t\t\r\n//\tstatic\tTsk::Task< CCrown >::Code s_logic_code;\r\n//\tTsk::Task< CCrown >*\tmp_logic_task;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_CROWN_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/cutscenedetails.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       cutscenedetails.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  01/13/2003\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/objects/cutscenedetails.h>\r\n\r\n#include <core/math.h>\r\n\r\n#include <gel/assman/assman.h>\r\n#include <gel/assman/assettypes.h>\r\n#include <gel/assman/skeletonasset.h>\r\n#include <gel/assman/skinasset.h>\r\n\r\n#include <gfx/bonedanim.h>\r\n#include <gfx/camera.h>\r\n\r\n#include <gel/music/music.h>\r\n\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/file.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n\r\n#include <gfx/skeleton.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n\r\n#include <sys/file/AsyncFilesys.h>\r\n#include <sys/file/FileLibrary.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/movingobject.h>\r\n#include <gel/objman.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/components/animationcomponent.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/debuggfx.h>\r\n#include <gfx/facetexture.h>\r\n#include <gfx/nxanimcache.h>\r\n#include <gfx/nxquickanim.h>\r\n#include <gfx/nxlightman.h>\r\n#include <gfx/nxlight.h>\r\n\r\n#include <sk/objects/skaterprofile.h>\r\n#include <gfx/modelappearance.h>\r\n#include <sys/mem/memman.h>\r\n#include <sys/timer.h>\r\n#include <sys/config/config.h>\r\n#include <sk/modules/FrontEnd/FrontEnd.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/vecpair.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// make sure the texture dictionary offsets don't\r\n// clash with skater's texture dictionaries\r\n// in case we're using actual skater assets\r\n// (such as the board) \r\nconst int vCUTSCENE_TEXDICT_RANGE = 200;\r\n \r\n// flags that are set during cifconv\r\n#define vCUTSCENEOBJECTFLAGS_ISSKATER\t\t(1<<31)\r\n#define vCUTSCENEOBJECTFLAGS_ISHEAD\t\t\t(1<<30)\r\n\r\n#ifdef __PLAT_NGC__\r\nextern bool g_in_cutscene;\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*\r\nchar testWeightIndices[] = {\r\n\t30, -1, -1, // vertex 0\r\n\t30, -1, -1, // vertex 1\r\n\t30, -1, -1, // vertex 2\r\n\t30, -1, -1, // vertex 3\r\n\t30, -1, -1, // vertex 4\r\n\t30, -1, -1, // vertex 5\r\n\t30, -1, -1, // vertex 6\r\n\t30, -1, -1, // vertex 7\r\n\t30, -1, -1, // vertex 8\r\n\t30, 32, -1, // vertex 9\r\n\t30, 32, -1, // vertex 10\r\n\t30, 32, -1, // vertex 11\r\n\t30, 32, -1, // vertex 12\r\n\t30, 32, -1, // vertex 13\r\n\t30, 32, -1, // vertex 14\r\n\t30, 32, -1, // vertex 15\r\n\t30, 32, -1, // vertex 16\r\n\t30, 32, -1, // vertex 17\r\n\t30, 32, -1, // vertex 18\r\n\t30, 32, -1, // vertex 19\r\n\t30, 32, -1, // vertex 20\r\n\t30, 32, -1, // vertex 21\r\n\t30, -1, -1, // vertex 22\r\n\t30, -1, -1, // vertex 23\r\n\t30, -1, -1, // vertex 24\r\n\t30, -1, -1, // vertex 25\r\n\t30, -1, -1, // vertex 26\r\n\t30, -1, -1, // vertex 27\r\n\t30, 31, -1, // vertex 28\r\n\t30, -1, -1, // vertex 29\r\n\t30, 32, -1, // vertex 30\r\n\t30, -1, -1, // vertex 31\r\n\t30, 32, -1, // vertex 32\r\n\t30, -1, -1, // vertex 33\r\n\t30, 32, -1, // vertex 34\r\n\t30, 32, -1, // vertex 35\r\n\t30, 32, -1, // vertex 36\r\n\t30, 32, -1, // vertex 37\r\n\t30, 32, -1, // vertex 38\r\n\t30, 32, -1, // vertex 39\r\n\t30, 32, -1, // vertex 40\r\n\t30, 32, -1, // vertex 41\r\n\t30, 32, -1, // vertex 42\r\n\t30, -1, -1, // vertex 43\r\n\t30, -1, -1, // vertex 44\r\n\t30, -1, -1, // vertex 45\r\n\t30, -1, -1, // vertex 46\r\n\t30, -1, -1, // vertex 47\r\n\t30, -1, -1, // vertex 48\r\n\t30, -1, -1, // vertex 49\r\n\t30, -1, -1, // vertex 50\r\n\t30, 32, -1, // vertex 51\r\n\t30, 32, -1, // vertex 52\r\n\t30, 32, -1, // vertex 53\r\n\t30, 32, -1, // vertex 54\r\n\t30, 32, -1, // vertex 55\r\n\t30, 32, -1, // vertex 56\r\n\t30, 32, -1, // vertex 57\r\n\t30, 32, -1, // vertex 58\r\n\t30, 32, -1, // vertex 59\r\n\t30, 32, -1, // vertex 60\r\n\t30, 32, -1, // vertex 61\r\n\t30, 32, -1, // vertex 62\r\n\t30, 32, -1, // vertex 63\r\n\t30, 32, -1, // vertex 64\r\n\t30, 32, -1, // vertex 65\r\n\t30, 32, -1, // vertex 66\r\n\t30, 32, -1, // vertex 67\r\n\t30, 32, -1, // vertex 68\r\n\t30, 32, -1, // vertex 69\r\n\t30, 32, -1, // vertex 70\r\n\t30, 32, -1, // vertex 71\r\n\t30, 32, -1, // vertex 72\r\n\t30, -1, -1, // vertex 73\r\n\t30, 32, -1, // vertex 74\r\n\t30, -1, -1, // vertex 75\r\n\t30, 32, -1, // vertex 76\r\n\t30, -1, -1, // vertex 77\r\n\t30, -1, -1, // vertex 78\r\n\t30, -1, -1, // vertex 79\r\n\t30, -1, -1, // vertex 80\r\n\t30, -1, -1, // vertex 81\r\n\t30, -1, -1, // vertex 82\r\n\t30, -1, -1, // vertex 83\r\n\t30, -1, -1, // vertex 84\r\n\t30, -1, -1, // vertex 85\r\n\t30, -1, -1, // vertex 86\r\n\t30, -1, -1, // vertex 87\r\n\t30, -1, -1, // vertex 88\r\n\t30, -1, -1, // vertex 89\r\n\t30, -1, -1, // vertex 90\r\n\t30, -1, -1, // vertex 91\r\n\t30, -1, -1, // vertex 92\r\n\t30, -1, -1, // vertex 93\r\n\t30, -1, -1, // vertex 94\r\n\t30, 31, -1, // vertex 95\r\n\t30, 31, -1, // vertex 96\r\n\t30, -1, -1, // vertex 97\r\n\t30, -1, -1, // vertex 98\r\n\t30, -1, -1, // vertex 99\r\n\t30, 29, -1, // vertex 100\r\n\t30, 29, -1, // vertex 101\r\n\t30, -1, -1, // vertex 102\r\n\t30, -1, -1, // vertex 103\r\n\t30, 31, -1, // vertex 104\r\n\t30, -1, -1, // vertex 105\r\n\t30, -1, -1, // vertex 106\r\n\t30, -1, -1, // vertex 107\r\n\t30, -1, -1, // vertex 108\r\n\t30, -1, -1, // vertex 109\r\n\t30, -1, -1, // vertex 110\r\n\t30, -1, -1, // vertex 111\r\n\t30, -1, -1, // vertex 112\r\n\t30, -1, -1, // vertex 113\r\n\t30, -1, -1, // vertex 114\r\n\t29, 30, -1, // vertex 115\r\n\t30, -1, -1, // vertex 116\r\n\t29, 30, -1, // vertex 117\r\n\t29, 30, -1, // vertex 118\r\n\t30, 29, -1, // vertex 119\r\n\t30, 29, -1, // vertex 120\r\n\t30, 33, -1, // vertex 121\r\n\t30, 33, -1, // vertex 122\r\n\t33, 30, -1, // vertex 123\r\n\t33, 30, -1, // vertex 124\r\n\t33, 30, -1, // vertex 125\r\n\t33, 30, -1, // vertex 126\r\n\t33, 30, -1, // vertex 127\r\n\t33, 30, -1, // vertex 128\r\n\t33, 30, -1, // vertex 129\r\n\t33, 30, -1, // vertex 130\r\n\t33, 30, -1, // vertex 131\r\n\t33, 30, -1, // vertex 132\r\n\t33, 30, -1, // vertex 133\r\n\t33, 30, -1, // vertex 134\r\n\t30, 33, -1, // vertex 135\r\n\t33, 30, -1, // vertex 136\r\n\t33, 30, -1, // vertex 137\r\n\t33, 30, -1, // vertex 138\r\n\t33, 30, -1, // vertex 139\r\n\t33, 30, -1, // vertex 140\r\n\t30, 33, -1, // vertex 141\r\n\t33, 30, -1, // vertex 142\r\n\t30, 33, -1, // vertex 143\r\n\t33, 30, -1, // vertex 144\r\n\t30, 33, -1, // vertex 145\r\n\t30, 33, -1, // vertex 146\r\n\t30, -1, -1, // vertex 147\r\n\t30, -1, -1, // vertex 148\r\n\t30, -1, -1, // vertex 149\r\n\t30, -1, -1, // vertex 150\r\n\t30, -1, -1, // vertex 151\r\n\t30, -1, -1, // vertex 152\r\n\t30, -1, -1, // vertex 153\r\n\t30, 32, -1, // vertex 154\r\n\t30, -1, -1, // vertex 155\r\n\t30, 32, -1, // vertex 156\r\n\t30, 32, -1, // vertex 157\r\n\t30, 32, -1, // vertex 158\r\n\t30, 32, -1, // vertex 159\r\n\t30, 32, -1, // vertex 160\r\n\t30, 32, -1, // vertex 161\r\n\t30, 32, -1, // vertex 162\r\n\t30, 32, -1, // vertex 163\r\n\t30, 32, -1, // vertex 164\r\n\t30, 32, -1, // vertex 165\r\n\t30, 32, -1, // vertex 166\r\n\t30, 32, -1, // vertex 167\r\n\t30, 32, -1, // vertex 168\r\n\t30, 32, -1, // vertex 169\r\n\t30, 32, -1, // vertex 170\r\n\t30, 32, -1, // vertex 171\r\n\t30, 32, -1, // vertex 172\r\n\t30, 32, -1, // vertex 173\r\n\t30, 32, -1, // vertex 174\r\n\t30, 32, -1, // vertex 175\r\n\t30, -1, -1, // vertex 176\r\n\t30, 32, -1, // vertex 177\r\n\t30, -1, -1, // vertex 178\r\n\t30, -1, -1, // vertex 179\r\n\t30, -1, -1, // vertex 180\r\n\t30, -1, -1, // vertex 181\r\n\t30, -1, -1, // vertex 182\r\n\t30, -1, -1, // vertex 183\r\n\t30, -1, -1, // vertex 184\r\n\t30, 33, -1, // vertex 185\r\n\t30, 33, -1, // vertex 186\r\n\t33, 30, -1, // vertex 187\r\n\t30, 33, -1, // vertex 188\r\n\t33, 30, -1, // vertex 189\r\n\t30, 33, -1, // vertex 190\r\n\t33, 30, -1, // vertex 191\r\n\t33, 30, -1, // vertex 192\r\n\t33, 30, -1, // vertex 193\r\n\t33, 30, -1, // vertex 194\r\n\t33, 30, -1, // vertex 195\r\n\t30, 33, -1, // vertex 196\r\n\t33, 30, -1, // vertex 197\r\n\t30, 31, -1, // vertex 198\r\n\t30, 31, -1, // vertex 199\r\n\t30, 31, -1, // vertex 200\r\n\t30, 31, -1, // vertex 201\r\n\t30, 31, -1, // vertex 202\r\n\t30, 31, -1, // vertex 203\r\n\t30, 31, -1, // vertex 204\r\n\t30, 31, -1, // vertex 205\r\n\t30, 31, -1, // vertex 206\r\n\t30, 31, -1, // vertex 207\r\n\t30, 31, -1, // vertex 208\r\n\t30, 31, -1, // vertex 209\r\n\t30, 31, -1, // vertex 210\r\n\t30, 31, -1, // vertex 211\r\n\t31, 30, -1, // vertex 212\r\n\t31, 30, -1, // vertex 213\r\n\t31, 30, -1, // vertex 214\r\n\t31, 30, -1, // vertex 215\r\n\t30, 31, -1, // vertex 216\r\n\t30, 31, -1, // vertex 217\r\n\t30, 31, -1, // vertex 218\r\n\t30, 31, -1, // vertex 219\r\n\t30, 31, -1, // vertex 220\r\n\t30, 31, -1, // vertex 221\r\n\t30, 31, -1, // vertex 222\r\n\t30, -1, -1, // vertex 223\r\n\t30, 31, -1, // vertex 224\r\n\t30, -1, -1, // vertex 225\r\n\t30, 31, -1, // vertex 226\r\n\t30, 29, -1, // vertex 227\r\n\t30, -1, -1, // vertex 228\r\n\t30, -1, -1, // vertex 229\r\n\t30, -1, -1, // vertex 230\r\n\t30, 31, -1, // vertex 231\r\n\t30, -1, -1, // vertex 232\r\n\t30, -1, -1, // vertex 233\r\n\t30, -1, -1, // vertex 234\r\n\t30, -1, -1, // vertex 235\r\n\t30, -1, -1, // vertex 236\r\n\t30, -1, -1, // vertex 237\r\n\t30, -1, -1, // vertex 238\r\n\t30, 31, -1, // vertex 239\r\n\t30, 31, -1, // vertex 240\r\n\t30, -1, -1, // vertex 241\r\n\t30, -1, -1, // vertex 242\r\n\t30, -1, -1, // vertex 243\r\n\t30, -1, -1, // vertex 244\r\n\t30, -1, -1, // vertex 245\r\n\t30, -1, -1, // vertex 246\r\n\t30, -1, -1, // vertex 247\r\n\t30, -1, -1, // vertex 248\r\n\t30, -1, -1, // vertex 249\r\n\t30, -1, -1, // vertex 250\r\n\t30, -1, -1, // vertex 251\r\n\t30, -1, -1, // vertex 252\r\n\t30, 33, -1, // vertex 253\r\n\t30, -1, -1, // vertex 254\r\n\t30, 33, -1, // vertex 255\r\n\t30, -1, -1, // vertex 256\r\n\t30, 33, -1, // vertex 257\r\n\t30, -1, -1, // vertex 258\r\n\t33, 30, -1, // vertex 259\r\n\t30, -1, -1, // vertex 260\r\n\t33, 30, -1, // vertex 261\r\n\t30, 31, -1, // vertex 262\r\n\t30, 31, -1, // vertex 263\r\n\t30, 31, -1, // vertex 264\r\n\t30, -1, -1, // vertex 265\r\n\t30, -1, -1, // vertex 266\r\n\t30, -1, -1, // vertex 267\r\n\t30, -1, -1, // vertex 268\r\n\t30, -1, -1, // vertex 269\r\n\t30, -1, -1, // vertex 270\r\n\t30, -1, -1, // vertex 271\r\n\t30, -1, -1, // vertex 272\r\n\t30, -1, -1, // vertex 273\r\n\t30, -1, -1, // vertex 274\r\n\t30, -1, -1, // vertex 275\r\n\t30, -1, -1, // vertex 276\r\n\t30, -1, -1, // vertex 277\r\n\t30, 33, -1, // vertex 278\r\n\t30, -1, -1, // vertex 279\r\n\t30, 32, -1, // vertex 280\r\n\t30, -1, -1, // vertex 281\r\n\t30, -1, -1, // vertex 282\r\n\t30, -1, -1, // vertex 283\r\n\t30, -1, -1, // vertex 284\r\n\t30, -1, -1, // vertex 285\r\n\t30, -1, -1, // vertex 286\r\n\t30, -1, -1, // vertex 287\r\n\t30, -1, -1, // vertex 288\r\n\t30, -1, -1, // vertex 289\r\n\t30, 32, -1, // vertex 290\r\n\t30, 32, -1, // vertex 291\r\n\t30, 32, -1, // vertex 292\r\n\t30, 32, -1, // vertex 293\r\n\t30, -1, -1, // vertex 294\r\n\t30, -1, -1, // vertex 295\r\n\t30, -1, -1, // vertex 296\r\n\t30, 32, -1, // vertex 297\r\n\t30, -1, -1, // vertex 298\r\n\t30, 32, -1, // vertex 299\r\n\t30, -1, -1, // vertex 300\r\n\t30, 32, -1, // vertex 301\r\n\t30, -1, -1, // vertex 302\r\n\t30, 32, -1, // vertex 303\r\n\t30, 32, -1, // vertex 304\r\n\t30, -1, -1, // vertex 305\r\n\t30, 33, -1, // vertex 306\r\n\t30, -1, -1, // vertex 307\r\n\t30, 33, -1, // vertex 308\r\n\t30, 32, -1, // vertex 309\r\n\t30, 32, -1, // vertex 310\r\n\t30, 32, -1, // vertex 311\r\n\t30, 32, -1, // vertex 312\r\n\t30, 32, -1, // vertex 313\r\n\t30, 32, -1, // vertex 314\r\n\t30, 32, -1, // vertex 315\r\n\t30, 32, -1, // vertex 316\r\n\t30, 32, -1, // vertex 317\r\n\t30, 32, -1, // vertex 318\r\n\t30, 32, -1, // vertex 319\r\n\t30, 32, -1, // vertex 320\r\n\t30, 32, -1, // vertex 321\r\n\t30, 32, -1, // vertex 322\r\n\t30, 32, -1, // vertex 323\r\n\t30, 32, -1, // vertex 324\r\n\t30, 32, -1, // vertex 325\r\n\t30, 32, -1, // vertex 326\r\n\t30, 32, -1, // vertex 327\r\n\t30, 32, -1, // vertex 328\r\n\t30, 32, -1, // vertex 329\r\n\t30, 32, -1, // vertex 330\r\n\t30, 32, -1, // vertex 331\r\n\t30, 32, -1, // vertex 332\r\n\t30, 32, -1, // vertex 333\r\n\t30, 32, -1, // vertex 334\r\n\t30, -1, -1, // vertex 335\r\n\t30, -1, -1, // vertex 336\r\n\t30, -1, -1, // vertex 337\r\n\t30, -1, -1, // vertex 338\r\n\t30, -1, -1, // vertex 339\r\n\t30, -1, -1, // vertex 340\r\n\t30, -1, -1, // vertex 341\r\n\t30, -1, -1, // vertex 342\r\n\t30, -1, -1, // vertex 343\r\n\t30, -1, -1, // vertex 344\r\n\t30, -1, -1, // vertex 345\r\n\t30, 31, -1, // vertex 346\r\n\t30, 31, -1, // vertex 347\r\n\t30, -1, -1, // vertex 348\r\n\t30, -1, -1, // vertex 349\r\n\t30, -1, -1, // vertex 350\r\n\t30, -1, -1, // vertex 351\r\n\t30, -1, -1, // vertex 352\r\n\t30, -1, -1, // vertex 353\r\n\t30, -1, -1, // vertex 354\r\n\t30, -1, -1, // vertex 355\r\n\t30, -1, -1, // vertex 356\r\n\t30, -1, -1, // vertex 357\r\n\t30, -1, -1, // vertex 358\r\n\t30, -1, -1, // vertex 359\r\n\t30, -1, -1, // vertex 360\r\n\t30, -1, -1, // vertex 361\r\n\t30, 33, -1, // vertex 362\r\n\t30, 33, -1, // vertex 363\r\n\t33, 30, -1, // vertex 364\r\n\t30, 31, -1, // vertex 365\r\n\t30, 31, -1, // vertex 366\r\n\t30, 31, -1, // vertex 367\r\n\t30, 31, -1, // vertex 368\r\n\t30, 31, -1, // vertex 369\r\n\t31, 30, -1, // vertex 370\r\n\t30, 31, -1, // vertex 371\r\n\t30, 31, -1, // vertex 372\r\n\t30, 31, -1, // vertex 373\r\n\t30, 31, -1, // vertex 374\r\n\t30, 31, -1, // vertex 375\r\n\t30, 31, -1, // vertex 376\r\n\t30, 31, -1, // vertex 377\r\n\t30, 31, -1, // vertex 378\r\n\t30, 31, -1, // vertex 379\r\n\t30, 31, -1, // vertex 380\r\n\t30, 31, -1, // vertex 381\r\n\t30, -1, -1, // vertex 382\r\n\t30, -1, -1, // vertex 383\r\n\t30, -1, -1, // vertex 384\r\n\t30, -1, -1, // vertex 385\r\n\t30, -1, -1, // vertex 386\r\n\t30, -1, -1, // vertex 387\r\n\t30, -1, -1, // vertex 388\r\n\t30, -1, -1, // vertex 389\r\n\t30, -1, -1, // vertex 390\r\n\t29, 30, -1, // vertex 391\r\n\t30, -1, -1, // vertex 392\r\n\t30, 29, -1, // vertex 393\r\n\t30, 31, -1, // vertex 394\r\n\t30, -1, -1, // vertex 395\r\n\t30, 31, -1, // vertex 396\r\n\t30, -1, -1, // vertex 397\r\n\t30, -1, -1, // vertex 398\r\n\t30, -1, -1, // vertex 399\r\n\t30, -1, -1, // vertex 400\r\n\t30, -1, -1, // vertex 401\r\n\t30, -1, -1, // vertex 402\r\n\t30, -1, -1, // vertex 403\r\n\t30, -1, -1, // vertex 404\r\n\t30, -1, -1, // vertex 405\r\n\t30, 31, -1, // vertex 406\r\n\t30, 31, -1, // vertex 407\r\n\t30, 31, -1, // vertex 408\r\n\t33, 30, -1, // vertex 409\r\n\t30, -1, -1, // vertex 410\r\n\t33, 30, -1, // vertex 411\r\n\t30, -1, -1, // vertex 412\r\n\t30, 33, -1, // vertex 413\r\n\t30, -1, -1, // vertex 414\r\n\t30, 33, -1, // vertex 415\r\n\t30, -1, -1, // vertex 416\r\n\t30, 33, -1, // vertex 417\r\n\t30, -1, -1, // vertex 418\r\n\t30, -1, -1, // vertex 419\r\n\t30, -1, -1, // vertex 420\r\n\t30, -1, -1, // vertex 421\r\n\t30, 33, -1, // vertex 422\r\n\t30, -1, -1, // vertex 423\r\n\t30, -1, -1, // vertex 424\r\n\t30, -1, -1, // vertex 425\r\n\t30, -1, -1, // vertex 426\r\n\t30, -1, -1, // vertex 427\r\n\t30, -1, -1, // vertex 428\r\n\t30, -1, -1, // vertex 429\r\n\t30, -1, -1, // vertex 430\r\n\t30, -1, -1, // vertex 431\r\n\t30, -1, -1, // vertex 432\r\n\t30, -1, -1, // vertex 433\r\n\t30, -1, -1, // vertex 434\r\n\t30, -1, -1, // vertex 435\r\n\t30, 31, -1, // vertex 436\r\n\t30, 31, -1, // vertex 437\r\n\t30, -1, -1, // vertex 438\r\n\t30, -1, -1, // vertex 439\r\n\t30, -1, -1, // vertex 440\r\n\t30, 32, -1, // vertex 441\r\n\t30, -1, -1, // vertex 442\r\n\t30, -1, -1, // vertex 443\r\n\t30, -1, -1, // vertex 444\r\n\t30, -1, -1, // vertex 445\r\n\t30, -1, -1, // vertex 446\r\n\t30, -1, -1, // vertex 447\r\n\t30, -1, -1, // vertex 448\r\n\t30, -1, -1, // vertex 449\r\n\t30, -1, -1, // vertex 450\r\n\t30, 32, -1, // vertex 451\r\n\t30, 32, -1, // vertex 452\r\n\t30, 32, -1, // vertex 453\r\n\t30, 32, -1, // vertex 454\r\n\t30, -1, -1, // vertex 455\r\n\t30, 32, -1, // vertex 456\r\n\t30, -1, -1, // vertex 457\r\n\t30, 32, -1, // vertex 458\r\n\t30, -1, -1, // vertex 459\r\n\t30, 32, -1, // vertex 460\r\n\t30, -1, -1, // vertex 461\r\n\t30, -1, -1, // vertex 462\r\n\t30, 32, -1, // vertex 463\r\n\t30, 32, -1, // vertex 464\r\n\t30, 32, -1, // vertex 465\r\n\t30, 32, -1, // vertex 466\r\n\t30, 32, -1, // vertex 467\r\n\t30, 32, -1, // vertex 468\r\n\t30, 32, -1, // vertex 469\r\n\t30, 32, -1, // vertex 470\r\n\t30, 32, -1, // vertex 471\r\n\t30, 32, -1, // vertex 472\r\n\t30, 32, -1, // vertex 473\r\n\t30, 32, -1, // vertex 474\r\n\t30, 32, -1, // vertex 475\r\n\t30, 32, -1, // vertex 476\r\n\t30, 32, -1, // vertex 477\r\n\t30, 32, -1, // vertex 478\r\n\t30, 32, -1, // vertex 479\r\n\t30, 32, -1, // vertex 480\r\n\t30, 32, -1, // vertex 481\r\n\t30, 32, -1, // vertex 482\r\n\t30, 32, -1, // vertex 483\r\n\t30, 32, -1, // vertex 484\r\n\t30, 32, -1, // vertex 485\r\n\t30, -1, -1, // vertex 486\r\n\t30, -1, -1, // vertex 487\r\n\t30, -1, -1, // vertex 488\r\n\t30, -1, -1, // vertex 489\r\n\t30, -1, -1, // vertex 490\r\n\t30, -1, -1, // vertex 491\r\n\t30, -1, -1, // vertex 492\r\n\t30, -1, -1, // vertex 493\r\n\t30, -1, -1, // vertex 494\r\n\t30, -1, -1, // vertex 495\r\n\t30, -1, -1, // vertex 496\r\n\t30, -1, -1, // vertex 497\r\n\t30, -1, -1, // vertex 498\r\n\t30, -1, -1, // vertex 499\r\n\t30, -1, -1, // vertex 500\r\n\t29, 30, -1, // vertex 501\r\n\t30, -1, -1, // vertex 502\r\n\t30, -1, -1, // vertex 503\r\n\t30, -1, -1, // vertex 504\r\n\t30, -1, -1, // vertex 505\r\n\t30, -1, -1, // vertex 506\r\n\t30, -1, -1, // vertex 507\r\n\t30, -1, -1, // vertex 508\r\n\t30, -1, -1, // vertex 509\r\n\t30, -1, -1, // vertex 510\r\n\t30, -1, -1, // vertex 511\r\n\t30, -1, -1, // vertex 512\r\n\t30, -1, -1, // vertex 513\r\n\t30, -1, -1, // vertex 514\r\n\t30, -1, -1, // vertex 515\r\n\t30, 32, -1, // vertex 516\r\n\t30, 32, -1, // vertex 517\r\n\t30, 32, -1, // vertex 518\r\n\t30, -1, -1, // vertex 519\r\n\t30, -1, -1, // vertex 520\r\n\t30, -1, -1, // vertex 521\r\n\t30, 31, -1, // vertex 522\r\n\t30, 31, -1, // vertex 523\r\n\t30, 31, -1, // vertex 524\r\n\t30, 31, -1, // vertex 525\r\n\t30, 31, -1, // vertex 526\r\n\t30, 31, -1, // vertex 527\r\n\t30, 31, -1, // vertex 528\r\n\t30, 31, -1, // vertex 529\r\n\t30, 31, -1, // vertex 530\r\n\t30, 31, -1, // vertex 531\r\n\t30, 31, -1, // vertex 532\r\n\t30, 31, -1, // vertex 533\r\n\t30, 31, -1, // vertex 534\r\n\t30, 31, -1, // vertex 535\r\n\t30, 31, -1, // vertex 536\r\n\t30, 31, -1, // vertex 537\r\n\t30, 31, -1, // vertex 538\r\n\t30, 31, -1, // vertex 539\r\n\t30, 31, -1, // vertex 540\r\n\t30, 31, -1, // vertex 541\r\n\t30, 31, -1, // vertex 542\r\n\t30, 31, -1, // vertex 543\r\n\t30, 31, -1, // vertex 544\r\n\t30, 31, -1, // vertex 545\r\n\t30, 31, -1, // vertex 546\r\n\t30, 31, -1, // vertex 547\r\n\t30, 31, -1, // vertex 548\r\n\t30, 31, -1, // vertex 549\r\n\t30, 31, -1, // vertex 550\r\n\t30, 31, -1, // vertex 551\r\n\t30, 31, -1, // vertex 552\r\n\t31, 30, -1, // vertex 553\r\n\t30, 31, -1, // vertex 554\r\n\t31, 30, -1, // vertex 555\r\n\t31, 30, -1, // vertex 556\r\n\t30, 31, -1, // vertex 557\r\n\t30, 31, -1, // vertex 558\r\n\t30, 31, -1, // vertex 559\r\n\t30, 31, -1, // vertex 560\r\n\t30, 31, -1, // vertex 561\r\n\t31, 30, -1, // vertex 562\r\n\t30, 31, -1, // vertex 563\r\n\t30, 31, -1, // vertex 564\r\n\t30, 31, -1, // vertex 565\r\n\t30, 31, -1, // vertex 566\r\n\t30, 31, -1, // vertex 567\r\n\t30, 31, -1, // vertex 568\r\n\t31, 30, -1, // vertex 569\r\n\t31, 30, -1, // vertex 570\r\n\t30, -1, -1, // vertex 571\r\n\t30, -1, -1, // vertex 572\r\n\t30, -1, -1, // vertex 573\r\n\t30, -1, -1, // vertex 574\r\n\t30, -1, -1, // vertex 575\r\n\t30, -1, -1, // vertex 576\r\n\t30, -1, -1, // vertex 577\r\n\t30, -1, -1, // vertex 578\r\n\t30, -1, -1, // vertex 579\r\n\t30, -1, -1, // vertex 580\r\n\t30, -1, -1, // vertex 581\r\n\t30, -1, -1, // vertex 582\r\n\t30, -1, -1, // vertex 583\r\n\t30, -1, -1, // vertex 584\r\n\t30, -1, -1, // vertex 585\r\n\t30, -1, -1, // vertex 586\r\n\t30, -1, -1, // vertex 587\r\n\t30, -1, -1, // vertex 588\r\n\t30, -1, -1, // vertex 589\r\n\t30, -1, -1, // vertex 590\r\n\t30, -1, -1, // vertex 591\r\n\t30, 31, -1, // vertex 592\r\n\t30, -1, -1, // vertex 593\r\n\t30, 31, -1, // vertex 594\r\n\t30, 29, -1, // vertex 595\r\n\t30, 29, -1, // vertex 596\r\n\t30, -1, -1, // vertex 597\r\n\t29, 30, -1, // vertex 598\r\n\t30, 29, -1, // vertex 599\r\n\t30, 29, -1, // vertex 600\r\n\t30, 31, -1, // vertex 601\r\n\t30, -1, -1, // vertex 602\r\n\t30, 31, -1, // vertex 603\r\n\t33, 30, -1, // vertex 604\r\n\t33, 30, -1, // vertex 605\r\n\t33, 30, -1, // vertex 606\r\n\t33, 30, -1, // vertex 607\r\n\t33, 30, -1, // vertex 608\r\n\t30, 33, -1, // vertex 609\r\n\t30, 33, -1, // vertex 610\r\n\t30, 33, -1, // vertex 611\r\n\t30, 32, -1, // vertex 612\r\n\t30, 33, -1, // vertex 613\r\n\t30, 33, -1, // vertex 614\r\n\t33, 30, -1, // vertex 615\r\n\t33, 30, -1, // vertex 616\r\n\t33, 30, -1, // vertex 617\r\n\t33, 30, -1, // vertex 618\r\n\t33, 30, -1, // vertex 619\r\n\t33, 30, -1, // vertex 620\r\n\t33, 30, -1, // vertex 621\r\n\t33, 30, -1, // vertex 622\r\n\t33, 30, -1, // vertex 623\r\n\t33, 30, -1, // vertex 624\r\n\t33, 30, -1, // vertex 625\r\n\t30, 33, -1, // vertex 626\r\n\t30, 33, -1, // vertex 627\r\n\t30, 33, -1, // vertex 628\r\n\t30, 32, -1, // vertex 629\r\n\t30, 32, -1, // vertex 630\r\n\t30, -1, -1, // vertex 631\r\n\t30, -1, -1, // vertex 632\r\n\t30, -1, -1, // vertex 633\r\n\t30, -1, -1, // vertex 634\r\n\t30, -1, -1, // vertex 635\r\n\t30, -1, -1, // vertex 636\r\n\t30, 33, -1, // vertex 637\r\n\t30, 33, -1, // vertex 638\r\n\t30, -1, -1, // vertex 639\r\n\t30, 32, -1, // vertex 640\r\n\t30, -1, -1, // vertex 641\r\n\t30, 32, -1, // vertex 642\r\n\t30, -1, -1, // vertex 643\r\n\t30, 32, -1, // vertex 644\r\n\t30, -1, -1, // vertex 645\r\n\t30, -1, -1, // vertex 646\r\n\t30, -1, -1, // vertex 647\r\n\t30, 32, -1, // vertex 648\r\n\t30, 32, -1, // vertex 649\r\n\t30, 32, -1, // vertex 650\r\n\t30, 32, -1, // vertex 651\r\n\t30, 32, -1, // vertex 652\r\n\t30, 32, -1, // vertex 653\r\n\t30, 32, -1, // vertex 654\r\n\t30, 32, -1, // vertex 655\r\n\t30, 32, -1, // vertex 656\r\n\t30, 32, -1, // vertex 657\r\n\t30, 32, -1, // vertex 658\r\n\t30, -1, -1, // vertex 659\r\n\t30, -1, -1, // vertex 660\r\n\t30, -1, -1, // vertex 661\r\n\t33, 30, -1, // vertex 662\r\n\t33, 30, -1, // vertex 663\r\n\t33, 30, -1, // vertex 664\r\n\t33, 30, -1, // vertex 665\r\n\t33, 30, -1, // vertex 666\r\n\t33, 30, -1, // vertex 667\r\n\t33, 30, -1, // vertex 668\r\n\t33, 30, -1, // vertex 669\r\n\t33, 30, -1, // vertex 670\r\n\t33, 30, -1, // vertex 671\r\n\t33, 30, -1, // vertex 672\r\n\t33, 30, -1, // vertex 673\r\n\t33, 30, -1, // vertex 674\r\n\t33, 30, -1, // vertex 675\r\n\t30, 33, -1, // vertex 676\r\n\t30, 33, -1, // vertex 677\r\n\t33, 30, -1, // vertex 678\r\n\t33, 30, -1, // vertex 679\r\n\t33, 30, -1, // vertex 680\r\n\t33, 30, -1, // vertex 681\r\n\t33, 30, -1, // vertex 682\r\n\t30, -1, -1, // vertex 683\r\n\t30, -1, -1, // vertex 684\r\n\t30, -1, -1, // vertex 685\r\n\t30, -1, -1, // vertex 686\r\n\t30, -1, -1, // vertex 687\r\n\t30, -1, -1, // vertex 688\r\n\t30, 32, -1, // vertex 689\r\n\t30, -1, -1, // vertex 690\r\n\t30, 32, -1, // vertex 691\r\n\t30, -1, -1, // vertex 692\r\n\t30, 32, -1, // vertex 693\r\n\t30, -1, -1, // vertex 694\r\n\t33, 30, -1, // vertex 695\r\n\t30, 33, -1, // vertex 696\r\n\t30, 33, -1, // vertex 697\r\n\t30, -1, -1, // vertex 698\r\n\t30, -1, -1, // vertex 699\r\n\t30, -1, -1, // vertex 700\r\n\t30, 32, -1, // vertex 701\r\n\t30, 32, -1, // vertex 702\r\n\t30, 32, -1, // vertex 703\r\n\t30, 32, -1, // vertex 704\r\n\t30, 32, -1, // vertex 705\r\n\t30, 32, -1, // vertex 706\r\n\t30, 32, -1, // vertex 707\r\n\t30, 32, -1, // vertex 708\r\n\t30, 32, -1, // vertex 709\r\n\t30, 32, -1, // vertex 710\r\n\t30, 32, -1, // vertex 711\r\n\t30, -1, -1, // vertex 712\r\n\t30, -1, -1, // vertex 713\r\n\t30, -1, -1, // vertex 714\r\n\t30, 31, -1, // vertex 715\r\n\t30, 31, -1, // vertex 716\r\n\t30, 31, -1, // vertex 717\r\n\t30, 31, -1, // vertex 718\r\n\t30, 31, -1, // vertex 719\r\n\t30, 31, -1, // vertex 720\r\n\t30, 31, -1, // vertex 721\r\n\t30, 31, -1, // vertex 722\r\n\t30, 31, -1, // vertex 723\r\n\t30, 31, -1, // vertex 724\r\n\t30, 31, -1, // vertex 725\r\n\t30, 31, -1, // vertex 726\r\n\t30, 31, -1, // vertex 727\r\n\t30, 31, -1, // vertex 728\r\n\t30, 31, -1, // vertex 729\r\n\t30, 31, -1, // vertex 730\r\n\t30, 31, -1, // vertex 731\r\n\t30, 31, -1, // vertex 732\r\n\t30, 31, -1, // vertex 733\r\n\t30, 31, -1, // vertex 734\r\n\t30, 31, -1, // vertex 735\r\n\t30, 31, -1, // vertex 736\r\n\t30, 31, -1, // vertex 737\r\n\t30, 31, -1, // vertex 738\r\n\t30, 31, -1, // vertex 739\r\n\t30, 31, -1, // vertex 740\r\n\t30, 31, -1, // vertex 741\r\n\t30, 31, -1, // vertex 742\r\n\t30, 31, -1, // vertex 743\r\n\t30, 31, -1, // vertex 744\r\n\t30, 31, -1, // vertex 745\r\n\t30, 31, -1, // vertex 746\r\n\t30, 31, -1, // vertex 747\r\n\t30, 31, -1, // vertex 748\r\n\t30, 31, -1, // vertex 749\r\n\t30, -1, -1, // vertex 750\r\n\t30, -1, -1, // vertex 751\r\n\t30, 31, -1, // vertex 752\r\n\t30, -1, -1, // vertex 753\r\n\t30, -1, -1, // vertex 754\r\n\t30, 32, -1, // vertex 755\r\n\t30, 32, -1, // vertex 756\r\n\t30, 32, -1, // vertex 757\r\n\t30, 32, -1, // vertex 758\r\n\t30, 32, -1, // vertex 759\r\n\t30, 32, -1, // vertex 760\r\n\t30, 32, -1, // vertex 761\r\n\t30, 32, -1, // vertex 762\r\n\t30, -1, -1, // vertex 763\r\n\t30, -1, -1, // vertex 764\r\n\t30, 31, -1, // vertex 765\r\n\t30, -1, -1, // vertex 766\r\n\t30, -1, -1, // vertex 767\r\n\t30, -1, -1, // vertex 768\r\n\t30, -1, -1, // vertex 769\r\n\t30, 31, -1, // vertex 770\r\n\t30, 31, -1, // vertex 771\r\n\t30, 31, -1, // vertex 772\r\n\t30, 31, -1, // vertex 773\r\n\t30, 31, -1, // vertex 774\r\n\t30, 31, -1, // vertex 775\r\n\t30, 31, -1, // vertex 776\r\n\t30, 33, 31, // vertex 777\r\n\t30, 31, -1, // vertex 778\r\n\t30, 33, 31, // vertex 779\r\n\t30, 31, -1, // vertex 780\r\n\t30, 33, 31, // vertex 781\r\n\t30, 33, 31, // vertex 782\r\n\t30, 33, -1, // vertex 783\r\n\t30, 33, -1, // vertex 784\r\n\t30, 33, 31, // vertex 785\r\n\t30, 33, -1, // vertex 786\r\n\t30, 33, 31, // vertex 787\r\n\t30, 33, -1, // vertex 788\r\n\t30, 33, 31, // vertex 789\r\n\t33, 30, -1, // vertex 790\r\n\t30, 31, -1, // vertex 791\r\n\t30, 31, -1, // vertex 792\r\n\t30, 31, -1, // vertex 793\r\n\t30, 31, -1, // vertex 794\r\n\t30, 31, -1, // vertex 795\r\n\t30, -1, -1, // vertex 796\r\n\t30, 31, -1, // vertex 797\r\n\t30, 31, -1, // vertex 798\r\n\t30, 31, -1, // vertex 799\r\n\t30, 31, -1, // vertex 800\r\n\t30, 31, -1, // vertex 801\r\n\t30, 31, -1, // vertex 802\r\n\t30, 31, -1, // vertex 803\r\n\t30, 31, -1, // vertex 804\r\n\t30, 31, -1, // vertex 805\r\n\t30, 31, -1, // vertex 806\r\n\t30, 31, -1, // vertex 807\r\n\t30, 31, -1, // vertex 808\r\n\t30, 31, -1, // vertex 809\r\n\t30, 31, -1, // vertex 810\r\n\t30, 31, -1, // vertex 811\r\n\t30, 31, -1, // vertex 812\r\n\t30, 31, -1, // vertex 813\r\n\t30, 31, -1, // vertex 814\r\n\t30, 31, -1, // vertex 815\r\n\t30, 31, -1, // vertex 816\r\n\t30, 31, -1, // vertex 817\r\n\t30, -1, -1, // vertex 818\r\n\t30, 31, -1, // vertex 819\r\n\t30, 31, -1, // vertex 820\r\n\t30, 31, -1, // vertex 821\r\n\t30, 31, -1, // vertex 822\r\n\t30, 31, -1, // vertex 823\r\n\t30, 31, -1, // vertex 824\r\n\t30, 31, -1, // vertex 825\r\n\t30, 31, -1, // vertex 826\r\n\t30, 31, -1, // vertex 827\r\n\t30, 31, -1, // vertex 828\r\n\t30, 31, -1, // vertex 829\r\n\t30, 31, -1, // vertex 830\r\n\t30, 33, 31, // vertex 831\r\n\t30, 31, -1, // vertex 832\r\n\t30, 31, -1, // vertex 833\r\n\t30, 31, -1, // vertex 834\r\n\t30, 31, -1, // vertex 835\r\n\t30, 31, -1, // vertex 836\r\n\t30, 31, -1, // vertex 837\r\n\t30, 31, -1, // vertex 838\r\n\t30, 31, -1, // vertex 839\r\n\t30, 31, -1, // vertex 840\r\n\t30, -1, -1, // vertex 841\r\n\t30, -1, -1, // vertex 842\r\n\t30, 31, -1, // vertex 843\r\n\t30, 31, -1, // vertex 844\r\n\t30, 31, -1, // vertex 845\r\n\t30, 31, -1, // vertex 846\r\n\t30, 31, -1, // vertex 847\r\n\t33, 30, -1, // vertex 848\r\n\t30, 31, -1, // vertex 849\r\n\t30, 33, -1, // vertex 850\r\n\t30, 33, 31, // vertex 851\r\n\t30, 31, -1, // vertex 852\r\n\t30, 31, -1, // vertex 853\r\n\t30, 31, -1, // vertex 854\r\n\t30, 31, -1, // vertex 855\r\n\t30, 31, -1, // vertex 856\r\n\t30, 31, -1, // vertex 857\r\n\t30, 31, -1, // vertex 858\r\n\t30, 31, -1, // vertex 859\r\n\t30, 31, -1, // vertex 860\r\n\t30, 31, -1, // vertex 861\r\n\t30, 31, -1, // vertex 862\r\n\t30, 31, -1, // vertex 863\r\n\t30, 31, -1, // vertex 864\r\n\t30, 31, -1, // vertex 865\r\n\t30, 31, -1, // vertex 866\r\n\t30, 31, -1, // vertex 867\r\n\t30, 31, -1, // vertex 868\r\n\t30, 31, -1, // vertex 869\r\n\t30, 31, -1, // vertex 870\r\n\t30, 31, -1, // vertex 871\r\n\t30, 31, -1, // vertex 872\r\n\t30, 31, -1, // vertex 873\r\n\t30, 31, -1, // vertex 874\r\n\t30, 31, -1, // vertex 875\r\n\t30, 31, -1, // vertex 876\r\n\t30, 31, -1, // vertex 877\r\n\t30, 31, -1, // vertex 878\r\n\t30, 31, -1, // vertex 879\r\n\t30, 31, -1, // vertex 880\r\n\t30, 31, -1, // vertex 881\r\n\t30, 31, -1, // vertex 882\r\n\t30, 31, -1, // vertex 883\r\n\t30, 31, -1, // vertex 884\r\n\t30, -1, -1, // vertex 885\r\n\t30, 31, -1, // vertex 886\r\n\t30, 31, -1, // vertex 887\r\n\t30, 31, -1, // vertex 888\r\n\t30, 31, -1, // vertex 889\r\n\t30, 31, -1, // vertex 890\r\n\t30, 31, -1, // vertex 891\r\n\t30, 31, -1, // vertex 892\r\n\t30, 31, -1, // vertex 893\r\n\t30, -1, -1, // vertex 894\r\n\t30, 31, -1, // vertex 895\r\n\t30, 31, -1, // vertex 896\r\n\t30, 31, -1, // vertex 897\r\n\t30, 32, -1, // vertex 898\r\n\t30, 32, -1, // vertex 899\r\n\t30, 32, -1, // vertex 900\r\n\t30, 32, -1, // vertex 901\r\n\t30, 32, -1, // vertex 902\r\n\t30, 32, -1, // vertex 903\r\n\t30, 32, -1, // vertex 904\r\n\t30, 32, -1, // vertex 905\r\n\t30, 32, -1, // vertex 906\r\n\t30, 32, -1, // vertex 907\r\n\t30, 32, -1, // vertex 908\r\n\t30, 32, -1, // vertex 909\r\n\t30, 32, -1, // vertex 910\r\n\t30, 32, -1, // vertex 911\r\n\t30, 32, -1, // vertex 912\r\n\t30, 32, -1, // vertex 913\r\n\t30, 32, -1, // vertex 914\r\n\t30, 32, -1, // vertex 915\r\n\t30, 32, -1, // vertex 916\r\n\t30, 32, -1, // vertex 917\r\n\t30, 32, -1, // vertex 918\r\n\t30, 32, -1, // vertex 919\r\n\t30, 32, -1, // vertex 920\r\n\t30, 32, -1, // vertex 921\r\n\t30, 32, -1, // vertex 922\r\n\t30, 32, -1, // vertex 923\r\n\t30, 32, -1, // vertex 924\r\n\t30, 32, -1, // vertex 925\r\n\t30, 32, -1, // vertex 926\r\n\t30, 32, -1, // vertex 927\r\n\t30, 32, -1, // vertex 928\r\n\t30, 32, -1, // vertex 929\r\n\t30, 32, -1, // vertex 930\r\n\t30, 32, -1, // vertex 931\r\n\t30, 32, -1, // vertex 932\r\n\t30, 32, -1, // vertex 933\r\n\t30, 32, -1, // vertex 934\r\n\t30, 32, -1, // vertex 935\r\n\t30, 32, -1, // vertex 936\r\n\t30, 32, -1, // vertex 937\r\n\t30, 32, -1, // vertex 938\r\n\t30, 32, -1, // vertex 939\r\n\t30, 32, -1, // vertex 940\r\n\t30, 32, -1, // vertex 941\r\n\t30, 32, -1, // vertex 942\r\n\t30, 32, -1, // vertex 943\r\n\t30, 32, -1, // vertex 944\r\n\t30, 32, -1, // vertex 945\r\n\t30, 32, -1, // vertex 946\r\n\t30, 32, -1, // vertex 947\r\n\t30, 32, -1, // vertex 948\r\n\t30, 32, -1, // vertex 949\r\n\t30, 32, -1, // vertex 950\r\n\t30, 32, -1, // vertex 951\r\n\t30, 32, -1, // vertex 952\r\n\t30, 32, -1, // vertex 953\r\n\t30, 32, -1, // vertex 954\r\n\t30, 32, -1, // vertex 955\r\n\t30, 32, -1, // vertex 956\r\n\t30, 32, -1, // vertex 957\r\n\t30, 32, -1, // vertex 958\r\n\t30, 32, -1, // vertex 959\r\n\t30, 32, -1, // vertex 960\r\n\t30, 32, -1, // vertex 961\r\n\t30, 32, -1, // vertex 962\r\n\t30, 32, -1, // vertex 963\r\n\t30, 32, -1, // vertex 964\r\n\t30, 32, -1, // vertex 965\r\n\t30, 32, -1, // vertex 966\r\n\t30, 32, -1, // vertex 967\r\n\t30, 32, -1, // vertex 968\r\n\t30, 32, -1, // vertex 969\r\n\t30, 32, -1, // vertex 970\r\n\t30, 32, -1, // vertex 971\r\n\t30, 32, -1, // vertex 972\r\n\t30, 32, -1, // vertex 973\r\n\t30, 32, -1, // vertex 974\r\n\t30, 32, -1, // vertex 975\r\n\t30, -1, -1, // vertex 976\r\n\t30, -1, -1, // vertex 977\r\n\t30, -1, -1, // vertex 978\r\n\t30, -1, -1, // vertex 979\r\n\t30, -1, -1, // vertex 980\r\n\t30, -1, -1, // vertex 981\r\n\t30, -1, -1, // vertex 982\r\n\t30, -1, -1, // vertex 983\r\n\t30, -1, -1, // vertex 984\r\n\t30, -1, -1, // vertex 985\r\n\t30, -1, -1, // vertex 986\r\n\t30, -1, -1, // vertex 987\r\n\t30, -1, -1, // vertex 988\r\n\t30, -1, -1, // vertex 989\r\n\t30, -1, -1, // vertex 990\r\n\t30, -1, -1, // vertex 991\r\n\t30, -1, -1, // vertex 992\r\n\t30, -1, -1, // vertex 993\r\n\t30, -1, -1, // vertex 994\r\n\t30, -1, -1, // vertex 995\r\n\t30, -1, -1, // vertex 996\r\n\t30, -1, -1, // vertex 997\r\n\t30, -1, -1, // vertex 998\r\n\t30, -1, -1, // vertex 999\r\n\t30, -1, -1, // vertex 1000\r\n\t30, -1, -1, // vertex 1001\r\n\t30, -1, -1, // vertex 1002\r\n\t30, -1, -1, // vertex 1003\r\n\t30, -1, -1, // vertex 1004\r\n\t30, -1, -1, // vertex 1005\r\n\t30, -1, -1, // vertex 1006\r\n\t30, -1, -1, // vertex 1007\r\n\t30, -1, -1, // vertex 1008\r\n\t30, -1, -1, // vertex 1009\r\n\t30, -1, -1, // vertex 1010\r\n\t30, -1, -1, // vertex 1011\r\n\t30, -1, -1, // vertex 1012\r\n\t30, -1, -1, // vertex 1013\r\n\t30, -1, -1, // vertex 1014\r\n\t30, -1, -1, // vertex 1015\r\n\t30, -1, -1, // vertex 1016\r\n\t30, -1, -1, // vertex 1017\r\n\t30, -1, -1, // vertex 1018\r\n\t30, -1, -1, // vertex 1019\r\n\t30, -1, -1, // vertex 1020\r\n\t30, -1, -1, // vertex 1021\r\n\t30, -1, -1, // vertex 1022\r\n\t30, -1, -1, // vertex 1023\r\n\t30, -1, -1, // vertex 1024\r\n\t30, -1, -1, // vertex 1025\r\n\t30, -1, -1, // vertex 1026\r\n\t30, -1, -1, // vertex 1027\r\n\t30, -1, -1, // vertex 1028\r\n\t30, -1, -1, // vertex 1029\r\n\t30, -1, -1, // vertex 1030\r\n\t30, -1, -1, // vertex 1031\r\n\t30, -1, -1, // vertex 1032\r\n\t30, -1, -1, // vertex 1033\r\n\t30, -1, -1, // vertex 1034\r\n\t30, -1, -1, // vertex 1035\r\n\t30, -1, -1, // vertex 1036\r\n\t30, -1, -1, // vertex 1037\r\n\t30, -1, -1, // vertex 1038\r\n\t30, -1, -1, // vertex 1039\r\n\t30, -1, -1, // vertex 1040\r\n\t30, -1, -1, // vertex 1041\r\n\t30, -1, -1, // vertex 1042\r\n\t30, -1, -1, // vertex 1043\r\n\t30, -1, -1, // vertex 1044\r\n\t30, -1, -1, // vertex 1045\r\n\t31, -1, -1, // vertex 1046\r\n\t31, -1, -1, // vertex 1047\r\n\t31, -1, -1, // vertex 1048\r\n\t31, -1, -1, // vertex 1049\r\n\t31, -1, -1, // vertex 1050\r\n\t31, -1, -1, // vertex 1051\r\n\t31, -1, -1, // vertex 1052\r\n\t31, -1, -1, // vertex 1053\r\n\t31, -1, -1, // vertex 1054\r\n\t31, -1, -1, // vertex 1055\r\n\t31, -1, -1, // vertex 1056\r\n\t31, -1, -1, // vertex 1057\r\n\t31, -1, -1, // vertex 1058\r\n\t31, -1, -1, // vertex 1059\r\n\t31, -1, -1, // vertex 1060\r\n\t31, -1, -1, // vertex 1061\r\n\t31, -1, -1, // vertex 1062\r\n\t31, -1, -1, // vertex 1063\r\n\t31, -1, -1, // vertex 1064\r\n\t31, -1, -1, // vertex 1065\r\n\t31, -1, -1, // vertex 1066\r\n\t31, -1, -1, // vertex 1067\r\n\t31, -1, -1, // vertex 1068\r\n\t31, -1, -1, // vertex 1069\r\n\t31, -1, -1, // vertex 1070\r\n\t31, -1, -1, // vertex 1071\r\n\t31, -1, -1, // vertex 1072\r\n\t31, -1, -1, // vertex 1073\r\n\t31, -1, -1, // vertex 1074\r\n\t31, -1, -1, // vertex 1075\r\n\t31, -1, -1, // vertex 1076\r\n\t31, -1, -1, // vertex 1077\r\n\t31, -1, -1, // vertex 1078\r\n\t31, -1, -1, // vertex 1079\r\n\t31, -1, -1, // vertex 1080\r\n\t30, -1, -1, // vertex 1081\r\n\t30, -1, -1, // vertex 1082\r\n\t30, -1, -1, // vertex 1083\r\n\t30, -1, -1, // vertex 1084\r\n\t30, -1, -1, // vertex 1085\r\n\t30, -1, -1, // vertex 1086\r\n\t30, -1, -1, // vertex 1087\r\n\t30, -1, -1, // vertex 1088\r\n\t30, -1, -1, // vertex 1089\r\n\t30, -1, -1, // vertex 1090\r\n\t30, -1, -1, // vertex 1091\r\n\t30, -1, -1, // vertex 1092\r\n\t30, -1, -1, // vertex 1093\r\n\t30, -1, -1, // vertex 1094\r\n\t30, -1, -1, // vertex 1095\r\n\t30, -1, -1, // vertex 1096\r\n\t30, -1, -1, // vertex 1097\r\n\t30, -1, -1, // vertex 1098\r\n\t30, -1, -1, // vertex 1099\r\n\t30, -1, -1, // vertex 1100\r\n\t30, -1, -1, // vertex 1101\r\n\t30, -1, -1, // vertex 1102\r\n\t30, -1, -1, // vertex 1103\r\n\t31, -1, -1, // vertex 1104\r\n\t31, -1, -1, // vertex 1105\r\n\t31, -1, -1, // vertex 1106\r\n\t31, -1, -1, // vertex 1107\r\n\t31, -1, -1, // vertex 1108\r\n\t31, -1, -1, // vertex 1109\r\n\t31, -1, -1, // vertex 1110\r\n\t31, -1, -1, // vertex 1111\r\n\t31, -1, -1, // vertex 1112\r\n\t31, -1, -1, // vertex 1113\r\n\t31, -1, -1, // vertex 1114\r\n\t31, -1, -1, // vertex 1115\r\n\t31, -1, -1, // vertex 1116\r\n\t31, -1, -1, // vertex 1117\r\n\t31, -1, -1, // vertex 1118\r\n\t31, -1, -1, // vertex 1119\r\n\t31, -1, -1, // vertex 1120\r\n\t31, -1, -1, // vertex 1121\r\n\t31, -1, -1, // vertex 1122\r\n\t31, -1, -1, // vertex 1123\r\n\t31, -1, -1, // vertex 1124\r\n\t31, -1, -1, // vertex 1125\r\n\t31, -1, -1, // vertex 1126\r\n\t31, -1, -1, // vertex 1127\r\n\t31, -1, -1, // vertex 1128\r\n\t31, -1, -1, // vertex 1129\r\n\t31, -1, -1, // vertex 1130\r\n\t31, -1, -1, // vertex 1131\r\n\t31, -1, -1, // vertex 1132\r\n\t31, -1, -1, // vertex 1133\r\n\t31, -1, -1, // vertex 1134\r\n\t30, -1, -1, // vertex 1135\r\n\t30, -1, -1, // vertex 1136\r\n\t30, -1, -1, // vertex 1137\r\n\t30, -1, -1, // vertex 1138\r\n\t30, -1, -1, // vertex 1139\r\n\t30, -1, -1, // vertex 1140\r\n\t30, -1, -1, // vertex 1141\r\n\t30, -1, -1, // vertex 1142\r\n\t30, -1, -1, // vertex 1143\r\n\t30, -1, -1, // vertex 1144\r\n\t30, -1, -1, // vertex 1145\r\n\t30, -1, -1, // vertex 1146\r\n\t30, -1, -1, // vertex 1147\r\n\t30, -1, -1, // vertex 1148\r\n\t30, -1, -1, // vertex 1149\r\n\t30, -1, -1, // vertex 1150\r\n\t30, -1, -1, // vertex 1151\r\n\t30, -1, -1, // vertex 1152\r\n\t30, -1, -1, // vertex 1153\r\n\t30, -1, -1, // vertex 1154\r\n\t30, -1, -1, // vertex 1155\r\n\t30, -1, -1, // vertex 1156\r\n\t30, -1, -1, // vertex 1157\r\n\t30, -1, -1, // vertex 1158\r\n\t30, -1, -1, // vertex 1159\r\n\t30, -1, -1, // vertex 1160\r\n\t30, -1, -1, // vertex 1161\r\n\t30, -1, -1, // vertex 1162\r\n\t30, -1, -1, // vertex 1163\r\n\t30, -1, -1, // vertex 1164\r\n\t30, -1, -1, // vertex 1165\r\n\t30, -1, -1, // vertex 1166\r\n\t30, -1, -1, // vertex 1167\r\n\t30, -1, -1, // vertex 1168\r\n\t30, -1, -1, // vertex 1169\r\n\t30, -1, -1, // vertex 1170\r\n\t30, -1, -1, // vertex 1171\r\n\t30, -1, -1, // vertex 1172\r\n\t30, -1, -1, // vertex 1173\r\n\t30, -1, -1, // vertex 1174\r\n\t30, -1, -1, // vertex 1175\r\n\t30, -1, -1, // vertex 1176\r\n\t30, -1, -1, // vertex 1177\r\n\t30, -1, -1, // vertex 1178\r\n\t30, -1, -1, // vertex 1179\r\n\t30, 31, -1, // vertex 1180\r\n\t30, -1, -1, // vertex 1181\r\n\t30, -1, -1, // vertex 1182\r\n\t30, 32, -1, // vertex 1183\r\n\t30, 32, -1, // vertex 1184\r\n\t30, 32, -1, // vertex 1185\r\n\t30, 32, -1, // vertex 1186\r\n\t30, 32, -1, // vertex 1187\r\n\t30, 32, -1, // vertex 1188\r\n\t30, 32, -1, // vertex 1189\r\n\t30, 32, -1, // vertex 1190\r\n\t30, -1, -1, // vertex 1191\r\n\t30, -1, -1, // vertex 1192\r\n\t30, 31, -1, // vertex 1193\r\n\t30, -1, -1, // vertex 1194\r\n\t30, -1, -1, // vertex 1195\r\n\t30, -1, -1, // vertex 1196\r\n\t30, -1, -1, // vertex 1197\r\n\t30, 31, -1, // vertex 1198\r\n\t30, 31, -1, // vertex 1199\r\n\t30, 31, -1, // vertex 1200\r\n\t30, 31, -1, // vertex 1201\r\n\t30, 31, -1, // vertex 1202\r\n\t30, 31, -1, // vertex 1203\r\n\t30, 31, -1, // vertex 1204\r\n\t30, 33, 31, // vertex 1205\r\n\t30, 31, -1, // vertex 1206\r\n\t30, 33, 31, // vertex 1207\r\n\t30, 31, -1, // vertex 1208\r\n\t30, 33, 31, // vertex 1209\r\n\t30, 33, 31, // vertex 1210\r\n\t30, 33, -1, // vertex 1211\r\n\t30, 33, -1, // vertex 1212\r\n\t30, 33, 31, // vertex 1213\r\n\t30, 33, -1, // vertex 1214\r\n\t30, 33, 31, // vertex 1215\r\n\t30, 33, -1, // vertex 1216\r\n\t30, 33, 31, // vertex 1217\r\n\t33, 30, -1, // vertex 1218\r\n\t30, 31, -1, // vertex 1219\r\n\t30, 31, -1, // vertex 1220\r\n\t30, 31, -1, // vertex 1221\r\n\t30, 31, -1, // vertex 1222\r\n\t30, 31, -1, // vertex 1223\r\n\t30, -1, -1, // vertex 1224\r\n\t30, 31, -1, // vertex 1225\r\n\t30, 31, -1, // vertex 1226\r\n\t30, 31, -1, // vertex 1227\r\n\t30, 31, -1, // vertex 1228\r\n\t30, 31, -1, // vertex 1229\r\n\t30, 31, -1, // vertex 1230\r\n\t30, 31, -1, // vertex 1231\r\n\t30, 31, -1, // vertex 1232\r\n\t30, 31, -1, // vertex 1233\r\n\t30, 31, -1, // vertex 1234\r\n\t30, 31, -1, // vertex 1235\r\n\t30, 31, -1, // vertex 1236\r\n\t30, 31, -1, // vertex 1237\r\n\t30, 31, -1, // vertex 1238\r\n\t30, 31, -1, // vertex 1239\r\n\t30, 31, -1, // vertex 1240\r\n\t30, 31, -1, // vertex 1241\r\n\t30, 31, -1, // vertex 1242\r\n\t30, 31, -1, // vertex 1243\r\n\t30, 31, -1, // vertex 1244\r\n\t30, 31, -1, // vertex 1245\r\n\t30, -1, -1, // vertex 1246\r\n\t30, 31, -1, // vertex 1247\r\n\t30, 31, -1, // vertex 1248\r\n\t30, 31, -1, // vertex 1249\r\n\t30, 31, -1, // vertex 1250\r\n\t30, 31, -1, // vertex 1251\r\n\t30, 31, -1, // vertex 1252\r\n\t30, 31, -1, // vertex 1253\r\n\t30, 31, -1, // vertex 1254\r\n\t30, 31, -1, // vertex 1255\r\n\t30, 31, -1, // vertex 1256\r\n\t30, 31, -1, // vertex 1257\r\n\t30, 31, -1, // vertex 1258\r\n\t30, 33, 31, // vertex 1259\r\n\t30, 31, -1, // vertex 1260\r\n\t30, 31, -1, // vertex 1261\r\n\t30, 31, -1, // vertex 1262\r\n\t30, 31, -1, // vertex 1263\r\n\t30, 31, -1, // vertex 1264\r\n\t30, 31, -1, // vertex 1265\r\n\t30, 31, -1, // vertex 1266\r\n\t30, 31, -1, // vertex 1267\r\n\t30, 31, -1, // vertex 1268\r\n\t30, -1, -1, // vertex 1269\r\n\t30, -1, -1, // vertex 1270\r\n\t30, 31, -1, // vertex 1271\r\n\t30, 31, -1, // vertex 1272\r\n\t30, 31, -1, // vertex 1273\r\n\t30, 31, -1, // vertex 1274\r\n\t30, 31, -1, // vertex 1275\r\n\t33, 30, -1, // vertex 1276\r\n\t30, 31, -1, // vertex 1277\r\n\t30, 33, -1, // vertex 1278\r\n\t30, 33, 31, // vertex 1279\r\n\t30, 31, -1, // vertex 1280\r\n\t30, 31, -1, // vertex 1281\r\n\t30, 31, -1, // vertex 1282\r\n\t30, 31, -1, // vertex 1283\r\n\t30, 31, -1, // vertex 1284\r\n\t30, 31, -1, // vertex 1285\r\n\t30, 31, -1, // vertex 1286\r\n\t30, 31, -1, // vertex 1287\r\n\t30, 31, -1, // vertex 1288\r\n\t30, 31, -1, // vertex 1289\r\n\t30, 31, -1, // vertex 1290\r\n\t30, 31, -1, // vertex 1291\r\n\t30, 31, -1, // vertex 1292\r\n\t30, 31, -1, // vertex 1293\r\n\t30, 31, -1, // vertex 1294\r\n\t30, 31, -1, // vertex 1295\r\n\t30, 31, -1, // vertex 1296\r\n\t30, 31, -1, // vertex 1297\r\n\t30, 31, -1, // vertex 1298\r\n\t30, 31, -1, // vertex 1299\r\n\t30, 31, -1, // vertex 1300\r\n\t30, 31, -1, // vertex 1301\r\n\t30, 31, -1, // vertex 1302\r\n\t30, 31, -1, // vertex 1303\r\n\t30, 31, -1, // vertex 1304\r\n\t30, 31, -1, // vertex 1305\r\n\t30, 31, -1, // vertex 1306\r\n\t30, 31, -1, // vertex 1307\r\n\t30, 31, -1, // vertex 1308\r\n\t30, 31, -1, // vertex 1309\r\n\t30, 31, -1, // vertex 1310\r\n\t30, 31, -1, // vertex 1311\r\n\t30, 31, -1, // vertex 1312\r\n\t30, -1, -1, // vertex 1313\r\n\t30, 31, -1, // vertex 1314\r\n\t30, 31, -1, // vertex 1315\r\n\t30, 31, -1, // vertex 1316\r\n\t30, 31, -1, // vertex 1317\r\n\t30, 31, -1, // vertex 1318\r\n\t30, 31, -1, // vertex 1319\r\n\t30, 31, -1, // vertex 1320\r\n\t30, 31, -1, // vertex 1321\r\n\t30, -1, -1, // vertex 1322\r\n\t30, 31, -1, // vertex 1323\r\n\t30, 31, -1, // vertex 1324\r\n\t30, 31, -1, // vertex 1325\r\n\t30, 32, -1, // vertex 1326\r\n\t30, 32, -1, // vertex 1327\r\n\t30, 32, -1, // vertex 1328\r\n\t30, 32, -1, // vertex 1329\r\n\t30, 32, -1, // vertex 1330\r\n\t30, 32, -1, // vertex 1331\r\n\t30, 32, -1, // vertex 1332\r\n\t30, 32, -1, // vertex 1333\r\n\t30, 32, -1, // vertex 1334\r\n\t30, 32, -1, // vertex 1335\r\n\t30, 32, -1, // vertex 1336\r\n\t30, 32, -1, // vertex 1337\r\n\t30, 32, -1, // vertex 1338\r\n\t30, 32, -1, // vertex 1339\r\n\t30, 32, -1, // vertex 1340\r\n\t30, 32, -1, // vertex 1341\r\n\t30, 32, -1, // vertex 1342\r\n\t30, 32, -1, // vertex 1343\r\n\t30, 32, -1, // vertex 1344\r\n\t30, 32, -1, // vertex 1345\r\n\t30, 32, -1, // vertex 1346\r\n\t30, 32, -1, // vertex 1347\r\n\t30, 32, -1, // vertex 1348\r\n\t30, 32, -1, // vertex 1349\r\n\t30, 32, -1, // vertex 1350\r\n\t30, 32, -1, // vertex 1351\r\n\t30, 32, -1, // vertex 1352\r\n\t30, 32, -1, // vertex 1353\r\n\t30, 32, -1, // vertex 1354\r\n\t30, 32, -1, // vertex 1355\r\n\t30, 32, -1, // vertex 1356\r\n\t30, 32, -1, // vertex 1357\r\n\t30, 32, -1, // vertex 1358\r\n\t30, 32, -1, // vertex 1359\r\n\t30, 32, -1, // vertex 1360\r\n\t30, 32, -1, // vertex 1361\r\n\t30, 32, -1, // vertex 1362\r\n\t30, 32, -1, // vertex 1363\r\n\t30, 32, -1, // vertex 1364\r\n\t30, 32, -1, // vertex 1365\r\n\t30, 32, -1, // vertex 1366\r\n\t30, 32, -1, // vertex 1367\r\n\t30, 32, -1, // vertex 1368\r\n\t30, 32, -1, // vertex 1369\r\n\t30, 32, -1, // vertex 1370\r\n\t30, 32, -1, // vertex 1371\r\n\t30, 32, -1, // vertex 1372\r\n\t30, 32, -1, // vertex 1373\r\n\t30, 32, -1, // vertex 1374\r\n\t30, 32, -1, // vertex 1375\r\n\t30, 32, -1, // vertex 1376\r\n\t30, 32, -1, // vertex 1377\r\n\t30, 32, -1, // vertex 1378\r\n\t30, 32, -1, // vertex 1379\r\n\t30, 32, -1, // vertex 1380\r\n\t30, 32, -1, // vertex 1381\r\n\t30, 32, -1, // vertex 1382\r\n\t30, 32, -1, // vertex 1383\r\n\t30, 32, -1, // vertex 1384\r\n\t30, 32, -1, // vertex 1385\r\n\t30, 32, -1, // vertex 1386\r\n\t30, 32, -1, // vertex 1387\r\n\t30, 32, -1, // vertex 1388\r\n\t30, 32, -1, // vertex 1389\r\n\t30, 32, -1, // vertex 1390\r\n\t30, 32, -1, // vertex 1391\r\n\t30, 32, -1, // vertex 1392\r\n\t30, 32, -1, // vertex 1393\r\n\t30, 32, -1, // vertex 1394\r\n\t30, 32, -1, // vertex 1395\r\n\t30, 32, -1, // vertex 1396\r\n\t30, 32, -1, // vertex 1397\r\n\t30, 32, -1, // vertex 1398\r\n\t30, 32, -1, // vertex 1399\r\n\t30, 32, -1, // vertex 1400\r\n\t30, 32, -1, // vertex 1401\r\n\t30, 32, -1, // vertex 1402\r\n\t30, 32, -1, // vertex 1403\r\n};\r\n\r\nfloat testWeights[] = {\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 0\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 2\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 3\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 4\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 5\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 6\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 7\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 8\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 9\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 10\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 11\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 12\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 13\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 14\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 15\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 16\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 17\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 18\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 19\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 20\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 21\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 22\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 23\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 24\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 25\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 26\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 27\r\n\t0.926651f, 0.073349f, 0.000000f, // vertex 28\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 29\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 30\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 31\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 32\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 33\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 34\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 35\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 36\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 37\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 38\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 39\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 40\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 41\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 42\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 43\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 44\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 45\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 46\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 47\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 48\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 49\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 50\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 51\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 52\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 53\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 54\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 55\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 56\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 57\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 58\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 59\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 60\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 61\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 62\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 63\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 64\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 65\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 66\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 67\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 68\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 69\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 70\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 71\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 72\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 73\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 74\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 75\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 76\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 77\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 78\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 79\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 80\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 81\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 82\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 83\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 84\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 85\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 86\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 87\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 88\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 89\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 90\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 91\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 92\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 93\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 94\r\n\t0.926651f, 0.073349f, 0.000000f, // vertex 95\r\n\t0.926651f, 0.073349f, 0.000000f, // vertex 96\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 97\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 98\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 99\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 100\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 101\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 102\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 103\r\n\t0.926651f, 0.073349f, 0.000000f, // vertex 104\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 105\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 106\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 107\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 108\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 109\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 110\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 111\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 112\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 113\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 114\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 115\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 116\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 117\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 118\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 119\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 120\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 121\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 122\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 123\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 124\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 125\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 126\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 127\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 128\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 129\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 130\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 131\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 132\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 133\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 134\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 135\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 136\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 137\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 138\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 139\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 140\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 141\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 142\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 143\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 144\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 145\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 146\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 147\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 148\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 149\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 150\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 151\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 152\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 153\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 154\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 155\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 156\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 157\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 158\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 159\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 160\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 161\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 162\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 163\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 164\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 165\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 166\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 167\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 168\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 169\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 170\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 171\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 172\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 173\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 174\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 175\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 176\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 177\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 178\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 179\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 180\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 181\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 182\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 183\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 184\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 185\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 186\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 187\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 188\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 189\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 190\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 191\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 192\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 193\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 194\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 195\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 196\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 197\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 198\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 199\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 200\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 201\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 202\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 203\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 204\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 205\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 206\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 207\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 208\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 209\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 210\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 211\r\n\t0.512195f, 0.487805f, 0.000000f, // vertex 212\r\n\t0.512195f, 0.487805f, 0.000000f, // vertex 213\r\n\t0.512195f, 0.487805f, 0.000000f, // vertex 214\r\n\t0.512195f, 0.487805f, 0.000000f, // vertex 215\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 216\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 217\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 218\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 219\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 220\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 221\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 222\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 223\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 224\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 225\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 226\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 227\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 228\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 229\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 230\r\n\t0.833941f, 0.166059f, 0.000000f, // vertex 231\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 232\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 233\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 234\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 235\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 236\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 237\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 238\r\n\t0.952381f, 0.047619f, 0.000000f, // vertex 239\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 240\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 241\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 242\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 243\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 244\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 245\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 246\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 247\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 248\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 249\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 250\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 251\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 252\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 253\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 254\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 255\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 256\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 257\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 258\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 259\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 260\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 261\r\n\t0.952381f, 0.047619f, 0.000000f, // vertex 262\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 263\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 264\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 265\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 266\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 267\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 268\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 269\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 270\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 271\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 272\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 273\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 274\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 275\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 276\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 277\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 278\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 279\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 280\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 281\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 282\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 283\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 284\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 285\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 286\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 287\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 288\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 289\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 290\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 291\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 292\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 293\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 294\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 295\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 296\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 297\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 298\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 299\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 300\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 301\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 302\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 303\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 304\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 305\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 306\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 307\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 308\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 309\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 310\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 311\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 312\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 313\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 314\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 315\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 316\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 317\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 318\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 319\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 320\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 321\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 322\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 323\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 324\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 325\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 326\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 327\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 328\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 329\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 330\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 331\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 332\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 333\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 334\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 335\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 336\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 337\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 338\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 339\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 340\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 341\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 342\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 343\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 344\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 345\r\n\t0.926651f, 0.073349f, 0.000000f, // vertex 346\r\n\t0.833941f, 0.166059f, 0.000000f, // vertex 347\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 348\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 349\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 350\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 351\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 352\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 353\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 354\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 355\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 356\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 357\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 358\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 359\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 360\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 361\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 362\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 363\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 364\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 365\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 366\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 367\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 368\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 369\r\n\t0.512195f, 0.487805f, 0.000000f, // vertex 370\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 371\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 372\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 373\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 374\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 375\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 376\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 377\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 378\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 379\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 380\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 381\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 382\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 383\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 384\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 385\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 386\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 387\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 388\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 389\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 390\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 391\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 392\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 393\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 394\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 395\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 396\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 397\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 398\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 399\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 400\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 401\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 402\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 403\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 404\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 405\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 406\r\n\t0.952381f, 0.047619f, 0.000000f, // vertex 407\r\n\t0.952381f, 0.047619f, 0.000000f, // vertex 408\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 409\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 410\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 411\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 412\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 413\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 414\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 415\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 416\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 417\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 418\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 419\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 420\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 421\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 422\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 423\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 424\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 425\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 426\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 427\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 428\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 429\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 430\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 431\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 432\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 433\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 434\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 435\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 436\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 437\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 438\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 439\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 440\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 441\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 442\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 443\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 444\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 445\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 446\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 447\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 448\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 449\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 450\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 451\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 452\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 453\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 454\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 455\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 456\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 457\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 458\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 459\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 460\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 461\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 462\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 463\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 464\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 465\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 466\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 467\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 468\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 469\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 470\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 471\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 472\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 473\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 474\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 475\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 476\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 477\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 478\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 479\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 480\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 481\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 482\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 483\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 484\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 485\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 486\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 487\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 488\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 489\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 490\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 491\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 492\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 493\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 494\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 495\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 496\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 497\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 498\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 499\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 500\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 501\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 502\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 503\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 504\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 505\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 506\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 507\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 508\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 509\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 510\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 511\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 512\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 513\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 514\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 515\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 516\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 517\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 518\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 519\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 520\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 521\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 522\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 523\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 524\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 525\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 526\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 527\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 528\r\n\t0.769231f, 0.230769f, 0.000000f, // vertex 529\r\n\t0.769231f, 0.230769f, 0.000000f, // vertex 530\r\n\t0.769231f, 0.230769f, 0.000000f, // vertex 531\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 532\r\n\t0.769231f, 0.230769f, 0.000000f, // vertex 533\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 534\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 535\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 536\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 537\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 538\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 539\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 540\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 541\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 542\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 543\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 544\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 545\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 546\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 547\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 548\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 549\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 550\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 551\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 552\r\n\t0.512195f, 0.487805f, 0.000000f, // vertex 553\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 554\r\n\t0.512195f, 0.487805f, 0.000000f, // vertex 555\r\n\t0.512195f, 0.487805f, 0.000000f, // vertex 556\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 557\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 558\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 559\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 560\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 561\r\n\t0.512195f, 0.487805f, 0.000000f, // vertex 562\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 563\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 564\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 565\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 566\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 567\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 568\r\n\t0.512195f, 0.487805f, 0.000000f, // vertex 569\r\n\t0.512195f, 0.487805f, 0.000000f, // vertex 570\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 571\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 572\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 573\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 574\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 575\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 576\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 577\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 578\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 579\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 580\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 581\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 582\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 583\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 584\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 585\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 586\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 587\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 588\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 589\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 590\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 591\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 592\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 593\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 594\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 595\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 596\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 597\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 598\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 599\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 600\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 601\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 602\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 603\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 604\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 605\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 606\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 607\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 608\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 609\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 610\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 611\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 612\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 613\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 614\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 615\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 616\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 617\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 618\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 619\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 620\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 621\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 622\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 623\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 624\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 625\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 626\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 627\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 628\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 629\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 630\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 631\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 632\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 633\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 634\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 635\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 636\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 637\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 638\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 639\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 640\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 641\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 642\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 643\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 644\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 645\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 646\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 647\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 648\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 649\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 650\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 651\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 652\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 653\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 654\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 655\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 656\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 657\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 658\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 659\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 660\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 661\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 662\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 663\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 664\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 665\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 666\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 667\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 668\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 669\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 670\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 671\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 672\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 673\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 674\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 675\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 676\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 677\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 678\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 679\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 680\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 681\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 682\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 683\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 684\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 685\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 686\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 687\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 688\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 689\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 690\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 691\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 692\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 693\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 694\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 695\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 696\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 697\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 698\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 699\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 700\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 701\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 702\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 703\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 704\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 705\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 706\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 707\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 708\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 709\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 710\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 711\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 712\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 713\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 714\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 715\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 716\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 717\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 718\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 719\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 720\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 721\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 722\r\n\t0.769231f, 0.230769f, 0.000000f, // vertex 723\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 724\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 725\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 726\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 727\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 728\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 729\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 730\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 731\r\n\t0.769231f, 0.230769f, 0.000000f, // vertex 732\r\n\t0.769231f, 0.230769f, 0.000000f, // vertex 733\r\n\t0.769231f, 0.230769f, 0.000000f, // vertex 734\r\n\t0.769231f, 0.230769f, 0.000000f, // vertex 735\r\n\t0.769231f, 0.230769f, 0.000000f, // vertex 736\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 737\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 738\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 739\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 740\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 741\r\n\t0.769231f, 0.230769f, 0.000000f, // vertex 742\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 743\r\n\t0.769231f, 0.230769f, 0.000000f, // vertex 744\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 745\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 746\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 747\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 748\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 749\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 750\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 751\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 752\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 753\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 754\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 755\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 756\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 757\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 758\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 759\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 760\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 761\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 762\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 763\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 764\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 765\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 766\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 767\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 768\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 769\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 770\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 771\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 772\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 773\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 774\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 775\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 776\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 777\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 778\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 779\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 780\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 781\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 782\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 783\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 784\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 785\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 786\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 787\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 788\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 789\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 790\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 791\r\n\t0.952381f, 0.047619f, 0.000000f, // vertex 792\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 793\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 794\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 795\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 796\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 797\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 798\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 799\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 800\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 801\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 802\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 803\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 804\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 805\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 806\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 807\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 808\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 809\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 810\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 811\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 812\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 813\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 814\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 815\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 816\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 817\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 818\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 819\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 820\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 821\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 822\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 823\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 824\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 825\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 826\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 827\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 828\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 829\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 830\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 831\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 832\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 833\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 834\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 835\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 836\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 837\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 838\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 839\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 840\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 841\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 842\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 843\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 844\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 845\r\n\t0.952381f, 0.047619f, 0.000000f, // vertex 846\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 847\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 848\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 849\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 850\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 851\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 852\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 853\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 854\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 855\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 856\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 857\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 858\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 859\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 860\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 861\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 862\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 863\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 864\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 865\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 866\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 867\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 868\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 869\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 870\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 871\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 872\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 873\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 874\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 875\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 876\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 877\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 878\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 879\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 880\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 881\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 882\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 883\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 884\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 885\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 886\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 887\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 888\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 889\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 890\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 891\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 892\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 893\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 894\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 895\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 896\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 897\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 898\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 899\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 900\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 901\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 902\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 903\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 904\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 905\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 906\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 907\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 908\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 909\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 910\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 911\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 912\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 913\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 914\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 915\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 916\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 917\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 918\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 919\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 920\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 921\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 922\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 923\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 924\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 925\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 926\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 927\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 928\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 929\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 930\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 931\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 932\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 933\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 934\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 935\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 936\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 937\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 938\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 939\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 940\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 941\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 942\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 943\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 944\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 945\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 946\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 947\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 948\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 949\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 950\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 951\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 952\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 953\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 954\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 955\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 956\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 957\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 958\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 959\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 960\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 961\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 962\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 963\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 964\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 965\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 966\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 967\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 968\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 969\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 970\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 971\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 972\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 973\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 974\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 975\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 976\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 977\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 978\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 979\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 980\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 981\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 982\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 983\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 984\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 985\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 986\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 987\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 988\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 989\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 990\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 991\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 992\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 993\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 994\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 995\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 996\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 997\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 998\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 999\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1000\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1001\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1002\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1003\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1004\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1005\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1006\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1007\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1008\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1009\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1010\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1011\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1012\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1013\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1014\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1015\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1016\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1017\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1018\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1019\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1020\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1021\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1022\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1023\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1024\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1025\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1026\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1027\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1028\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1029\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1030\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1031\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1032\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1033\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1034\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1035\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1036\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1037\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1038\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1039\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1040\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1041\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1042\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1043\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1044\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1045\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1046\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1047\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1048\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1049\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1050\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1051\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1052\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1053\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1054\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1055\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1056\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1057\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1058\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1059\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1060\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1061\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1062\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1063\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1064\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1065\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1066\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1067\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1068\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1069\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1070\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1071\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1072\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1073\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1074\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1075\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1076\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1077\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1078\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1079\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1080\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1081\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1082\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1083\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1084\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1085\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1086\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1087\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1088\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1089\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1090\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1091\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1092\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1093\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1094\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1095\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1096\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1097\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1098\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1099\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1100\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1101\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1102\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1103\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1104\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1105\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1106\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1107\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1108\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1109\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1110\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1111\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1112\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1113\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1114\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1115\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1116\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1117\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1118\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1119\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1120\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1121\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1122\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1123\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1124\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1125\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1126\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1127\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1128\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1129\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1130\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1131\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1132\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1133\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1134\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1135\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1136\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1137\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1138\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1139\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1140\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1141\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1142\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1143\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1144\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1145\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1146\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1147\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1148\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1149\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1150\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1151\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1152\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1153\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1154\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1155\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1156\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1157\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1158\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1159\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1160\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1161\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1162\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1163\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1164\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1165\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1166\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1167\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1168\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1169\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1170\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1171\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1172\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1173\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1174\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1175\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1176\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1177\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1178\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1179\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 1180\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1181\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1182\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1183\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1184\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1185\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1186\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1187\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1188\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1189\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1190\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1191\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1192\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 1193\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1194\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1195\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1196\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1197\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1198\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1199\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1200\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1201\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 1202\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 1203\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 1204\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 1205\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 1206\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 1207\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 1208\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 1209\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 1210\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 1211\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 1212\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 1213\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 1214\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 1215\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 1216\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 1217\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1218\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 1219\r\n\t0.952381f, 0.047619f, 0.000000f, // vertex 1220\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1221\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 1222\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 1223\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1224\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1225\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1226\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1227\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1228\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1229\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1230\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1231\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1232\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1233\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1234\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1235\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1236\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1237\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 1238\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 1239\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1240\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1241\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1242\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1243\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1244\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1245\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1246\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1247\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1248\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1249\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1250\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1251\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1252\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1253\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1254\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1255\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1256\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1257\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 1258\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 1259\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 1260\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 1261\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 1262\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 1263\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 1264\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1265\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1266\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1267\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1268\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1269\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1270\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 1271\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 1272\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1273\r\n\t0.952381f, 0.047619f, 0.000000f, // vertex 1274\r\n\t0.900901f, 0.099099f, 0.000000f, // vertex 1275\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1276\r\n\t0.819001f, 0.180999f, 0.000000f, // vertex 1277\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 1278\r\n\t0.772187f, 0.154437f, 0.073375f, // vertex 1279\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1280\r\n\t0.655738f, 0.344262f, 0.000000f, // vertex 1281\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1282\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 1283\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1284\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1285\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1286\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1287\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1288\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1289\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1290\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1291\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1292\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1293\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1294\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1295\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1296\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1297\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1298\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1299\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1300\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1301\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1302\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1303\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1304\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1305\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1306\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1307\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1308\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1309\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1310\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 1311\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1312\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1313\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 1314\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1315\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1316\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1317\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1318\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1319\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1320\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1321\r\n\t1.000000f, 0.000000f, 0.000000f, // vertex 1322\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1323\r\n\t0.909091f, 0.090909f, 0.000000f, // vertex 1324\r\n\t0.833333f, 0.166667f, 0.000000f, // vertex 1325\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1326\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 1327\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1328\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 1329\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1330\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 1331\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1332\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 1333\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 1334\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1335\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 1336\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1337\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 1338\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1339\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 1340\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1341\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1342\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 1343\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 1344\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 1345\r\n\t0.714286f, 0.285714f, 0.000000f, // vertex 1346\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1347\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1348\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 1349\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 1350\r\n\t0.800000f, 0.200000f, 0.000000f, // vertex 1351\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1352\r\n\t0.666667f, 0.333333f, 0.000000f, // vertex 1353\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 1354\r\n\t0.555556f, 0.444444f, 0.000000f, // vertex 1355\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1356\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1357\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1358\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1359\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1360\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1361\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1362\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1363\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1364\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1365\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1366\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1367\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1368\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1369\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1370\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1371\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1372\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1373\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1374\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1375\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1376\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1377\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1378\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1379\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1380\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1381\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1382\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1383\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1384\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1385\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1386\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1387\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1388\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1389\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1390\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1391\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1392\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1393\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1394\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1395\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1396\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1397\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1398\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1399\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1400\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1401\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1402\r\n\t0.500000f, 0.500000f, 0.000000f, // vertex 1403                                                          \r\n};\r\n*/\r\n\r\nMth::Vector testBonePositions[] = {\r\n\tMth::Vector( 0.000000f, 0.000000f, 0.000000f, 1.000000f ),\r\n\tMth::Vector( 0.003876f, 3.697956f, 1.117333f, 1.000000f ),\r\n\tMth::Vector( 0.003872f, 4.297436f, 2.893996f, 1.000000f ),\r\n\tMth::Vector( 0.003868f, 9.568745f, 1.807596f, 1.000000f ),\r\n\tMth::Vector( 0.003863f, 7.351619f, 5.444900f, 1.000000f ),\r\n};\t\t\t\t\t\t\t\t\t\t\t    \r\n\r\nMth::Vector testBoneScales[] = {\r\n\tMth::Vector( 1.000000f, 1.000000f, 1.000000f, 1.000000f ),\r\n\tMth::Vector( 1.000000f, 1.000000f, 1.000000f, 1.000000f ),\r\n\tMth::Vector( 1.000000f, 1.000000f, 1.000000f, 1.000000f ),\r\n\tMth::Vector( 1.000000f, 1.000000f, 1.000000f, 1.000000f ),\r\n\tMth::Vector( 1.000000f, 1.000000f, 1.000000f, 1.000000f ),\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCutsceneData::CCutsceneData()\r\n{\r\n\tmp_fileLibrary = NULL;\r\n\r\n\tmp_cameraQuickAnim = NULL;\r\n\tmp_objectQuickAnim = NULL;\r\n\r\n\tm_numObjects = 0;\r\n\tm_numAssets = 0;\r\n\r\n\tm_audioStarted = false;\r\n\tm_currentTime = 0.0f;\r\n\r\n\tm_original_params_set = false;\r\n\r\n\tPcm::StopMusic();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCutsceneData::~CCutsceneData()\r\n{\r\n\tif ( mp_fileLibrary )\r\n\t{\r\n\t\tdelete mp_fileLibrary;\r\n\t\tmp_fileLibrary = NULL;\r\n\t}\r\n\r\n\tif ( mp_cameraQuickAnim )\r\n\t{\r\n\t\tdelete mp_cameraQuickAnim;\r\n\t\tmp_cameraQuickAnim = NULL;\r\n\t}\r\n\r\n\tif ( mp_objectQuickAnim )\r\n\t{\r\n\t\tdelete mp_objectQuickAnim;\r\n\t\tmp_objectQuickAnim = NULL;\r\n\t}\r\n\t\r\n\tfor ( int i = 0; i < m_numBonedAnims; i++ )\r\n\t{\t\t\t\t\t\t\t\t\t\t\t \r\n\t\tSCutsceneAnimInfo* pAnimInfo = &m_bonedAnims[i];\r\n\t\r\n\t\tDbg_MsgAssert( pAnimInfo->mp_bonedQuickAnim, ( \"No quick anim to delete\" ) );\r\n\t\tdelete pAnimInfo->mp_bonedQuickAnim;\r\n\t\tpAnimInfo->mp_bonedQuickAnim = NULL;\r\n\t}\r\n\r\n\tfor ( int i = 0; i < m_numObjects; i++ )\r\n\t{\r\n// \t\tDon't want to mark 'em as dead, because the assets\r\n//\t\tcontained in these dummy objects will be obliterated\r\n//\t\tvery soon...  we don't want any dummy objects hanging\r\n//\t\taround without valid assets...\r\n//\t\tmp_object[i]->MarkAsDead();\r\n\t\t\r\n\t\tSCutsceneObjectInfo* pObjectInfo = &m_objects[i];\r\n\t\t\r\n\t\tDbg_MsgAssert( pObjectInfo->mp_object, ( \"No object to delete\" ) );\r\n\t\t\r\n\t\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( pObjectInfo->mp_object );\r\n\t\tDbg_Assert( pModelComponent );\r\n\t\t\r\n\t\tif ( pObjectInfo->m_doPlayerSubstitution )\r\n\t\t{\r\n\t\t\tDbg_Assert( pModelComponent->HasRefObject() );\r\n\t\t\t// put back the skater's model component,\r\n\t\t\t// if we changed the bounding sphere...\r\n\t\t\tuint32 refObjectName = pModelComponent->GetRefObjectName();\r\n\t\t\tObj::CCompositeObject* pRefObject = (Obj::CCompositeObject*)Obj::ResolveToObject( refObjectName );\r\n\t\t\tDbg_Assert( pRefObject );\r\n\t\t\tObj::CModelComponent* pRefModelComponent = GetModelComponentFromObject( pRefObject );\r\n\t\t\tDbg_Assert( pRefModelComponent );\r\n\t\t\tNx::CModel* pRefModel = pRefModelComponent->GetModel();\r\n\t\t\tpRefModel->SetBoundingSphere( m_original_player_bounding_sphere );\r\n\t\t\tpRefModel->Hide( m_original_hidden );\r\n\t\t\tpRefModel->EnableScaling( m_original_scale_enabled );\r\n\t\t\t\r\n\t\t\t// send the object back to where it came from...\r\n\t\t\t// (we had to change it for the duration of the cutscene\r\n\t\t\t// in case the object was affected by a FakeLight)\r\n\t\t\tpRefObject->SetPos( m_original_pos );\r\n\t\t}\r\n\r\n\t\tdelete pObjectInfo->mp_object;\r\n\t\tpObjectInfo->mp_object = NULL;\r\n\t}\r\n\t\r\n\tfor ( int i = 0; i < m_numAssets; i++ )\r\n\t{\r\n\t\t// remove them from the assman\r\n\t\t// (do i need to make sure the objects are completely dead first?)\r\n\t\tAss::CAssMan* pAssMan = Ass::CAssMan::Instance();\r\n\t\tAss::CAsset* pAsset = pAssMan->GetAssetNode( m_assetName[i], true );\r\n\t\tpAssMan->UnloadAsset( pAsset );\r\n\t\tm_assetName[i] = NULL;\r\n\t\t\r\n\t\t// TODO:  Need to handle anims slightly\r\n\t\t// if we use references...  fortunately,\r\n\t\t// we're not using references right now\r\n\t}\r\n\r\n\t// stop the stream (may not need this, unless we abort)\r\n\tPcm::StopMusic();\r\n\t\r\n\tScript::RunScript( CRCD(0x7216d8da,\"CutsceneKillObjects\") );\r\n\r\n\tScript::UnloadQB( CRCD(0xa1408e6e,\"cutscenefrommemory.qb\") );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCutsceneData::OverridesCamera()\r\n{\r\n\treturn LoadFinished() && m_audioStarted;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector get_scale( Script::CStruct* pAppearance, uint32 bone_group_name )\r\n{\r\n\tScript::CStruct* pVirtualDescStruct = NULL;\r\n\r\n\tif ( pAppearance->GetStructure( bone_group_name, &pVirtualDescStruct, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tint use_default_scale = 1;\r\n\t\tpVirtualDescStruct->GetInteger( CRCD(0x5a96985d,\"use_default_scale\"), &use_default_scale, Script::NO_ASSERT );\r\n\t\t\r\n\t\tif ( !use_default_scale )\r\n\t\t{\r\n\t\t\tint x, y, z;\r\n\t\t\tpVirtualDescStruct->GetInteger( CRCD(0x7323e97c,\"x\"), &x, Script::ASSERT );\r\n\t\t\tpVirtualDescStruct->GetInteger( CRCD(0x0424d9ea,\"y\"), &y, Script::ASSERT );\r\n\t\t\tpVirtualDescStruct->GetInteger( CRCD(0x9d2d8850,\"z\"), &z, Script::ASSERT );\r\n\t\t\treturn Mth::Vector( ((float)x)/100.0f, ((float)y)/100.0f, ((float)z)/100.0f, 1.0f ); \r\n\t\t}\r\n\t\telse \r\n\t\t{\r\n\t\t\t// use_default_scale parameter\r\n\t\t\treturn Mth::Vector( 1.0f, 1.0f, 1.0f, 1.0f );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// part not found\r\n\t\treturn Mth::Vector( 1.0f, 1.0f, 1.0f, 1.0f );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneData::load_models()\r\n{\r\n\tDbg_MsgAssert( mp_fileLibrary, ( \"No file library?!?\" ) );\r\n\r\n\tint numFiles = mp_fileLibrary->GetNumFiles();\r\n\tfor ( int i = 0; i < numFiles; i++ )\r\n\t{\r\n\t\tconst File::SFileInfo* pFileInfo = mp_fileLibrary->GetFileInfo( i );\r\n\r\n#ifdef __PLAT_NGC__\r\n\t\tuint32* pData = NULL;\r\n\t\tswitch ( pFileInfo->fileExtensionChecksum )\r\n\t\t{\r\n\t\t\tcase 0x5ac14717:\t// CIF\r\n\t\t\tcase 0x1512808d:\t// TEX\r\n\t\t\tcase 0xffc529f4:\t// CAS\r\n\t\t\tcase 0x2cd4107d:\t// WGT\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tpData = mp_fileLibrary->GetFileData( i );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n#else\r\n\t\tuint32* pData = mp_fileLibrary->GetFileData( i );\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\t\r\n\t\t// read each file one by one, and do something different based on the file type\r\n\t\tswitch ( pFileInfo->fileExtensionChecksum )\r\n\t\t{\r\n\t\t\tcase 0xeab51346:\t// SKA\r\n\t\t\t\tadd_boned_anim( pFileInfo->fileNameChecksum, pData, pFileInfo->fileSize );\r\n\t\t\t\tmp_fileLibrary->ClearFile( pFileInfo->fileNameChecksum, pFileInfo->fileExtensionChecksum );\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\r\n\t\t\tcase 0x2e4bf21b:\t// OBA\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( !mp_objectQuickAnim, ( \"Cutscene file should have exactly 1 object anim\\n\" ) );\r\n\t\t\t\tadd_anim( CRCD(0x3b423a24,\"cutscene_oba\"), pData, pFileInfo->fileSize );\r\n\t\t\t\tmp_objectQuickAnim = new Nx::CQuickAnim;\r\n\t\t\t\tmp_objectQuickAnim->SetAnimAssetName( CRCD(0x3b423a24,\"cutscene_oba\") );\r\n\t\t\t\tmp_objectQuickAnim->ResetCustomKeys();\r\n//\t\t\t\tm_objectAnimController.PlaySequence( 0, 0.0f, mp_objectAnimData->GetDuration(), Gfx::LOOPING_HOLD, 0.0f, 1.0f );\r\n\t\t\t\tmp_fileLibrary->ClearFile( pFileInfo->fileNameChecksum, pFileInfo->fileExtensionChecksum );\t\t\t\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\r\n\t\t\tcase 0x05ca1497:\t// CAM\r\n\t\t\t{\r\n\t\t\t\t// this presumes that there's only one cutscene_cam asset at a time,\r\n\t\t\t\t// which may not be true if we're queueing up multiple cutscenes\r\n\t\t\t\t// in this case, we'd need to run an init function before each\r\n\t\t\t\t// cutscene is played, not in the cutscene's InitFromStructure,\r\n\t\t\t\t// which gets called at the time the cutscene gets added to the list...\r\n\t\t\t\tadd_anim( CRCD(0x10c3dca8,\"cutscene_cam\"), pData, pFileInfo->fileSize );\r\n\t\t\t\tDbg_MsgAssert( !mp_cameraQuickAnim, ( \"Cutscene file should have exactly 1 Camera\\n\" ) );\r\n\t\t\t\tmp_cameraQuickAnim = new Nx::CQuickAnim;\r\n\t\t\t\tmp_cameraQuickAnim->SetAnimAssetName( CRCD(0x10c3dca8,\"cutscene_cam\") );\r\n\t\t\t\tmp_cameraQuickAnim->ResetCustomKeys();\r\n//\t\t\t\tm_cameraController.PlaySequence( 0, 0.0f, mp_cameraData->GetDuration(), Gfx::LOOPING_HOLD, 0.0f, 1.0f );\r\n\t\t\t\tmp_fileLibrary->ClearFile( pFileInfo->fileNameChecksum, pFileInfo->fileExtensionChecksum );\t\t\t\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\t\tcase 0x2bbea5c3:\t// QB\r\n\t\t\t{\r\n\t\t\t\tScript::LoadQBFromMemory( \"cutscenefrommemory.qb\", (uint8*)pData, Script::ASSERT_IF_DUPLICATE_SYMBOLS );\r\n\t\t\t\tmp_fileLibrary->ClearFile( pFileInfo->fileNameChecksum, pFileInfo->fileExtensionChecksum );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\t\tcase 0xe7308c1f:\t// GEOM\r\n\t\t\tcase 0xfd8697e1:\t// SKIN\r\n\t\t\tcase 0x0524fd4e:\t// MDL\r\n\t\t\t{\r\n\t\t\t\tchar model_asset_filename[512];\r\n\t\t\t\tsprintf( model_asset_filename, \"%08x\", pFileInfo->fileNameChecksum + pFileInfo->fileExtensionChecksum );\r\n\t\t\t\tuint32 model_asset_name = pFileInfo->fileNameChecksum + CRCD(0xfd8697e1,\"SKIN\");// pFileInfo->fileExtensionChecksum;\r\n//\t\t\t\tDbg_Message( \"Adding model asset %08x\", model_asset_name );\r\n\t\t\t\t\t\t\r\n\t\t\t\tAss::SCutsceneModelDataInfo theInfo;\r\n\t\t\t\ttheInfo.modelChecksum = model_asset_name;\r\n\t\t\t\ttheInfo.pModelData = pData;\r\n\t\t\t\ttheInfo.modelDataSize = pFileInfo->fileSize;\r\n\t\t\t\ttheInfo.pTextureData = mp_fileLibrary->GetFileData( pFileInfo->fileNameChecksum, CRCD(0x1512808d,\"TEX\"), true );\r\n\t\t\t\tconst File::SFileInfo* pTextureFileInfo;\r\n\t\t\t\tpTextureFileInfo = mp_fileLibrary->GetFileInfo( pFileInfo->fileNameChecksum, CRCD(0x1512808d,\"TEX\"), true );\r\n\t\t\t\tDbg_Assert( pTextureFileInfo );\r\n\t\t\t\ttheInfo.textureDataSize = pTextureFileInfo->fileSize;\r\n\t\t\t\t\t\r\n\t\t\t\t// CAS data isn't always required;  only for certain SKIN files\r\n\t\t\t\ttheInfo.pCASData = (uint8*)mp_fileLibrary->GetFileData( pFileInfo->fileNameChecksum, CRCD(0xffc529f4,\"CAS\"), false );;\r\n\r\n\t\t\t\ttheInfo.isSkin = pFileInfo->fileExtensionChecksum == CRCD(0xfd8697e1,\"SKIN\");\t\t\r\n\t\t\t\ttheInfo.texDictChecksum = pTextureFileInfo->fileNameChecksum + pTextureFileInfo->fileExtensionChecksum;\r\n\t\t\t\t\r\n\t\t\t\t// TODO:  Should be true if this is the skater model...\r\n\t\t\t\ttheInfo.doShadowVolume = false;\t\r\n\r\n\t\t\t\t// GJ:  make sure the texture dictionary offset doesn't clash with skaters\r\n\t\t\t\t// there must be a cleaner way to do this...  there must!\r\n\t\t\t\tif ( pFileInfo->fileExtensionChecksum == CRCD(0xe7308c1f,\"GEOM\") )\r\n\t\t\t\t{\r\n\t\t\t\t\t// geoms shouldn't specify tex dict offset, because\r\n\t\t\t\t\t// non-zero tex dict offsets will try to load themselves\r\n\t\t\t\t\t// up as a MDL, rather than as a GEOM\r\n\t\t\t\t\ttheInfo.texDictOffset = 0;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\ttheInfo.texDictOffset = vCUTSCENE_TEXDICT_RANGE + i;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// set up some default parameters\r\n\t\t\t\tbool permanent = false;\r\n\t\t\t\tint group = 0;\r\n\r\n\t\t\t\t// these file types get added to the asset manager\r\n\t\t\t\t// (if they don't already exist)...  remember to remove\r\n\t\t\t\t// them when the cutscene is done!\r\n\t\t\t\tAss::CAssMan* pAssMan = Ass::CAssMan::Instance();\r\n\r\n\t\t\t\t// by default, load the asset...  the cutscene heads\r\n\t\t\t\t// go through an additional piece of code to figure out\r\n\t\t\t\t// whether they will actually be needed during the cutscene\r\n\t\t\t\tbool should_load_asset = true;\r\n\r\n\t\t\t\t// used for cutscene head scaling\r\n\t\t\t\tuint8* pWeightMapData = (uint8*)mp_fileLibrary->GetFileData( pFileInfo->fileNameChecksum, CRCD(0x2cd4107d,\"WGT\"), false );\r\n\t\t\t\tif ( pWeightMapData )\r\n\t\t\t\t{\r\n\t\t\t\t\tNx::SMeshScalingParameters theParams;\r\n\t\t\t\t\t\r\n#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\tif ( Script::GetInteger( CRCD(0xf28e1301,\"CutsceneScaleTest\"), Script::NO_ASSERT ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tScript::CVector* pVec = NULL;\r\n\t\t\t\t\t\tpVec = Script::GetVector( CRCD(0x513a55f6,\"CutsceneScaleTestNeck\") );\r\n\t\t\t\t\t\ttestBoneScales[0] = Mth::Vector( pVec->mX, pVec->mY, pVec->mZ, 1.0f );\r\n\t\t\t\t\t\tpVec = Script::GetVector( CRCD(0xd6d87539,\"CutsceneScaleTestHead\") );\r\n\t\t\t\t\t\ttestBoneScales[1] = Mth::Vector( pVec->mX, pVec->mY, pVec->mZ, 1.0f );\r\n\t\t\t\t\t\tpVec = Script::GetVector( CRCD(0x9dea75ff,\"CutsceneScaleTestJaw\") );\r\n\t\t\t\t\t\ttestBoneScales[2] = Mth::Vector( pVec->mX, pVec->mY, pVec->mZ, 1.0f );\r\n\t\t\t\t\t\tpVec = Script::GetVector( CRCD(0x0767f02b,\"CutsceneScaleTestHat\") );\r\n\t\t\t\t\t\ttestBoneScales[3] = Mth::Vector( pVec->mX, pVec->mY, pVec->mZ, 1.0f );\r\n\t\t\t\t\t\tpVec = Script::GetVector( CRCD(0xba314cf8,\"CutsceneScaleTestBrow\") );\r\n\t\t\t\t\t\ttestBoneScales[4] = Mth::Vector( pVec->mX, pVec->mY, pVec->mZ, 1.0f );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n#endif\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// get it from the profile\r\n\t\t\t\t\t\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( 0 );\r\n\t\t\t\t\t\tGfx::CModelAppearance* pCASModelAppearance = pSkaterProfile->GetAppearance();\r\n\t\t\t\t\t\tScript::CStruct* pCASModelStruct = pCASModelAppearance->GetStructure();\r\n\r\n\t\t\t\t\t\ttestBoneScales[0] = get_scale( pCASModelStruct, CRCD(0xa28fab7f,\"head_bone_group\") );\r\n\t\t\t\t\t\ttestBoneScales[1] = get_scale( pCASModelStruct, CRCD(0xa28fab7f,\"head_bone_group\") );\r\n\t\t\t\t\t\ttestBoneScales[2] = get_scale( pCASModelStruct, CRCD(0x0442d3c1,\"jaw_bone_group\") );\r\n\t\t\t\t\t\ttestBoneScales[3] = get_scale( pCASModelStruct, CRCD(0xb90f08d0,\"headtop_bone_group\") );\r\n\t\t\t\t\t\ttestBoneScales[4] = get_scale( pCASModelStruct, CRCD(0x1dbcfae8,\"nose_bone_group\") );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// skip past version number\r\n\t\t\t\t\tpWeightMapData += sizeof(int); \r\n\r\n\t\t\t\t\tint numVerts = *(int*)pWeightMapData;\r\n\t\t\t\t\tpWeightMapData += sizeof(int);\r\n\r\n\t    \t\t\ttheParams.pWeights = (float*)pWeightMapData;\r\n\t\t\t\t\ttheParams.pWeightIndices = (char*)(pWeightMapData + (numVerts * 3 * sizeof(float)));\r\n\t\t\t\t\t\r\n\t\t\t\t\t//theParams.pWeights = &testWeights[0];\r\n\t\t\t\t\t//theParams.pWeightIndices = &testWeightIndices[0];\r\n\t\t\t\t\ttheParams.pBonePositions = &testBonePositions[0];\r\n\t\t\t\t\ttheParams.pBoneScales = &testBoneScales[0];\r\n\r\n\t\t\t\t\t// it's a cutscene head, so only load the model if it's the head that \r\n\t\t\t\t\t// we're going to need in the cutscene...  the 4 cutscene heads are always\r\n\t\t\t\t\t// ordered male/nonfacemapped, male/facemapped, female/nonfacemapped, \r\n\t\t\t\t\t// female/facemapped, so we should be able to figure out which head\r\n\t\t\t\t\t// is which depending on what other files exist...\r\n\t\t\t\t\tint is_male_head = ( mp_fileLibrary->GetFileInfo( pFileInfo->fileNameChecksum + 2, CRCD(0xfd8697e1,\"SKIN\"), false ) != NULL );\r\n\t\t\t\t\tint is_facemapped_head;\r\n\t\t\t\t\tif ( is_male_head )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tis_facemapped_head = ( mp_fileLibrary->GetFileInfo( pFileInfo->fileNameChecksum - 1, CRCD(0xfd8697e1,\"SKIN\"), false ) != NULL );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tis_facemapped_head = ( mp_fileLibrary->GetFileInfo( pFileInfo->fileNameChecksum + 1, CRCD(0xfd8697e1,\"SKIN\"), false ) == NULL );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tint is_male_skater;\r\n\t\t\t\t\tint is_facemapped_skater;\r\n\t\t\t\t\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( 0 );\r\n\t\t\t\t\tGfx::CModelAppearance* pCASModelAppearance = pSkaterProfile->GetAppearance();\r\n\t\t\t\t\tGfx::CFaceTexture* pCASFaceTexture = pCASModelAppearance->GetFaceTexture();\r\n\t\t\t\t\tis_facemapped_skater = ( pCASFaceTexture && pCASFaceTexture->IsValid() );\t\t\t\t\t\r\n\t\t\t\t\tScript::CStruct* pInfo = pSkaterProfile->GetInfo();\r\n\t\t\t\t\tpInfo->GetInteger( CRCD(0x3f813177,\"is_male\"), &is_male_skater, Script::ASSERT );\r\n\r\n\t\t\t\t\t// only load the correct head from the 4 cutscene heads\r\n\t\t\t\t\tshould_load_asset = ( ( is_facemapped_head == is_facemapped_skater ) && ( is_male_head == is_male_skater) );\r\n\t\t\t\t\r\n\t\t\t\t\tif ( should_load_asset )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// only want to set the parameters if we're sure we're going to be loading the asset...\r\n\t\t\t\t\t\tNx::CEngine::sSetMeshScalingParameters( &theParams );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( should_load_asset )\r\n\t\t\t\t{\r\n\t\t\t\t\tpAssMan->LoadAssetFromStream( model_asset_name, \r\n\t\t\t\t\t\t\t\t\t\t\t\t  Ass::ASSET_SKIN, \r\n\t\t\t\t\t\t\t\t\t\t\t\t  (uint32*)&theInfo, \r\n\t\t\t\t\t\t\t\t\t\t\t\t  sizeof(Ass::SCutsceneModelDataInfo), \r\n\t\t\t\t\t\t\t\t\t\t\t\t  permanent,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  group);\r\n\r\n\t\t\t\t\t// keep track of which assets are loaded, \r\n\t\t\t\t\t// so that we know to remove it in the destructor...\r\n\t\t\t\t\tDbg_MsgAssert( m_numAssets < vMAX_CUTSCENE_ASSETS, ( \"Too many assets (increase vMAX_CUTSCENE_ASSETS > %d)\", vMAX_CUTSCENE_ASSETS ) );\r\n\t\t\t\t\tm_assetName[m_numAssets] = model_asset_name;\r\n\t\t\t\t\tm_numAssets++;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tmp_fileLibrary->ClearFile( pFileInfo->fileNameChecksum, pFileInfo->fileExtensionChecksum );\r\n\t\t\t\tmp_fileLibrary->ClearFile( pFileInfo->fileNameChecksum, CRCD(0x1512808d,\"TEX\") );\r\n\t\t\t\tmp_fileLibrary->ClearFile( pFileInfo->fileNameChecksum, CRCD(0xffc529f4,\"CAS\") );\r\n\t\t\t\tmp_fileLibrary->ClearFile( pFileInfo->fileNameChecksum, CRCD(0x2cd4107d,\"WGT\") );\r\n\t\t  }\r\n\t\t\tbreak;\r\n/*\r\n\t\t\tcase 0xedd8d75f:\t// SKE\r\n\t\t\t\t{\r\n\t\t\t\t\tchar skeleton_asset_filename[512];\r\n\t\t\t\t\tsprintf( skeleton_asset_filename, \"%08x\", pFileInfo->fileNameChecksum + pFileInfo->fileExtensionChecksum );\r\n\t\t\t\t\tuint32 skeleton_asset_name = pFileInfo->fileNameChecksum + pFileInfo->fileExtensionChecksum;\r\n\t\t\t\t\tDbg_Message( \"Adding asset %08x\", skeleton_asset_name );\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t// set up some default parameters\r\n\t\t\t\t\tbool permanent = false;\r\n\t\t\t\t\tint group = 0;\r\n\t\t\t\t\t \r\n\t\t\t\t\t// these file types get added to the asset manager\r\n\t\t\t\t\t// (if they don't already exist)...  remember to remove\r\n\t\t\t\t\t// them when the cutscene is done!\r\n\t\t\t\t\tAss::CAssMan* pAssMan = Ass::CAssMan::Instance();\r\n\t\t\t\t\tpAssMan->LoadAssetFromStream( skeleton_asset_name, \r\n\t\t\t\t\t\t\t\t\t\t\t\t  Ass::ASSET_SKELETON, \r\n\t\t\t\t\t\t\t\t\t\t\t\t  (uint32*)pData, \r\n\t\t\t\t\t\t\t\t\t\t\t\t  pFileInfo->fileSize, \r\n\t\t\t\t\t\t\t\t\t\t\t\t  permanent,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  group);\r\n\r\n\t\t\t\t\t// keep track of which assets are loaded, \r\n\t\t\t\t\t// so that we know to remove it in the destructor...\r\n\t\t\t\t\tDbg_MsgAssert( m_numAssets < vMAX_CUTSCENE_ASSETS, ( \"Too many assets (increase vMAX_CUTSCENE_ASSETS > %d)\", vMAX_CUTSCENE_ASSETS ) );\r\n\t\t\t\t\tm_assetName[m_numAssets] = skeleton_asset_name;\r\n\t\t\t\t\tm_numAssets++;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n*/\r\n\r\n\t\t\tcase 0x5ac14717:\t// CIF\r\n\t\t\t\t// do nothing;  cif packet is handled during a separate step\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 0x1512808d:\t// TEX\r\n\t\t\t\t// do nothing;  loading of texture dictionaries is handled\r\n\t\t\t\t// automatically by the loading of models/skins\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 0xffc529f4:\t// CAS\r\n\t\t\t\t// do nothing;  loading of CAS flags are handled\r\n\t\t\t\t// automatically by the loading of models/skins\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 0x2cd4107d:\t// WGT\r\n\t\t\t\t// do nothing;  loading of mesh scaling weight maps are handled\r\n\t\t\t\t// automatically by the loading of models/skins\r\n\t\t\t\tbreak;\r\n\t\t\t\r\n\t\t\tdefault:\r\n\t\t\t\t// file type ignored on this pass\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneData::init_objects()\r\n{\r\n\t// now create the objects once the assets have been loaded\r\n\tuint32* pCIFData = mp_fileLibrary->GetFileData( 0, CRCD(0x5ac14717,\"CIF\"), true );\r\n\tDbg_Assert( pCIFData );\r\n\tcreate_objects( pCIFData );\r\n\tmp_fileLibrary->ClearFile( 0, CRCD(0x5ac14717,\"CIF\") );\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\t/*\r\n\tcan't do this test any more, because we're clearing out unused data\r\n\t\r\n\t// check for valid skeleton, should be moved to the exporter\r\n\tfor ( int i = 0; i < m_numObjects; i++ )\r\n\t{\r\n\t\tSCutsceneObjectInfo* pObjectInfo = &m_objects[i];\r\n\t\t\r\n\t\tif ( pObjectInfo->m_doPlayerSubstitution )\r\n\t\t{\r\n\t\t\t// no checks\r\n\t\t}\r\n\t\telse if ( pObjectInfo->m_skeletonName == 0 )\r\n\t\t{\r\n\t\t\t// if the object has no skeleton, make sure that this is an MDL, and not a SKIN\r\n\t\t\tif ( mp_fileLibrary->GetFileData( pObjectInfo->m_objectName, Crc::GenerateCRCFromString(\"SKIN\"), false ) )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"No skeleton specified for object %08x, even though it was listed as a SKIN file\", pObjectInfo->m_objectName ) );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( !mp_fileLibrary->GetFileData( pObjectInfo->m_objectName, Crc::GenerateCRCFromString(\"SKIN\"), false ) )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"Skeleton specified for object %08x, even though it was not listed as a SKIN file\", pObjectInfo->m_objectName ) );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t*/\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCutsceneData::PostLoad( bool assertOnFail )\r\n{\r\n\tDbg_MsgAssert( mp_fileLibrary, ( \"No file library?!?\" ) );\r\n\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().CutsceneBottomUpHeap() );\r\n\r\n\tload_models();\r\n\tinit_objects();\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tdelete mp_fileLibrary;\r\n\tmp_fileLibrary = NULL;\r\n\r\n\t//-------------------------------------------------------------\r\n\t// There's a blue glitch that appears for a few frames while\r\n\t// the cutscene manager waits for the stream to be preloaded.\r\n\t// The following loop will ensure that the stream is ready\r\n\t// to go before the video starts...\r\n\r\n#ifndef __PLAT_NGC__\r\n\twhile ( !m_audioStarted )\r\n\t{\r\n\t\tPcm::Update();\r\n\t\t\r\n\t\tif ( Pcm::PreLoadMusicStreamDone() )\r\n\t\t{\r\n\t\t\t// TODO:  Fill in with appropriate music volume parameter?\r\n\t\t\tPcm::StartPreLoadedMusicStream();\r\n\r\n\t\t\tm_audioStarted = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tTmr::VSync();\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\t//-------------------------------------------------------------\r\n\t\r\n\treturn true;\r\n}\r\n\t\t\t   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneData::add_anim( uint32 animAssetName, uint32* pData, int fileSize )\r\n{\r\n\t// set up some default parameters\r\n\tbool permanent = false;\r\n\tint group = 0;\r\n\tuint32 anim_asset_name = animAssetName;\r\n\t\t\t\t\t \r\n\t// these file types get added to the asset manager\r\n\t// (if they don't already exist)...  remember to remove\r\n\t// them when the cutscene is done!\r\n\tAss::CAssMan* pAssMan = Ass::CAssMan::Instance();\r\n\tpAssMan->LoadAssetFromStream( anim_asset_name, \r\n\t\t\t\t\t\t\t\t  Ass::ASSET_ANIM, \r\n\t\t\t\t\t\t\t\t  pData,\r\n\t\t\t\t\t\t\t\t  fileSize,\r\n\t\t\t\t\t\t\t\t  permanent,\r\n\t\t\t\t\t\t\t\t  group);\r\n\r\n\t// keep track of which assets are loaded, \r\n\t// so that we know to remove it in the destructor...\r\n\tDbg_MsgAssert( m_numAssets < vMAX_CUTSCENE_ASSETS, ( \"Too many assets (increase vMAX_CUTSCENE_ASSETS > %d)\", vMAX_CUTSCENE_ASSETS ) );\r\n\tm_assetName[m_numAssets] = anim_asset_name;\r\n\tm_numAssets++;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneData::add_boned_anim( uint32 animName, uint32* pData, int fileSize )\r\n{\r\n\tDbg_MsgAssert( m_numBonedAnims < vMAX_CUTSCENE_ANIMS, ( \"Too many anims in cutscene (increase vMAX_CUTSCENE_ANIMS > %d).\", vMAX_CUTSCENE_ANIMS ) );\r\n\r\n\tSCutsceneAnimInfo* pAnimInfo = &m_bonedAnims[m_numBonedAnims];\r\n\r\n\tDbg_MsgAssert( !get_anim_info( animName ), ( \"Anim already exists %s\", Script::FindChecksumName(animName) ) );\r\n\r\n\tadd_anim( animName, pData, fileSize );\r\n\r\n#ifdef __PLAT_NGC__\r\n\tint size = sizeof( Nx::CQuickAnim );\r\n\tint mem_available;\r\n\tbool need_to_pop = false;\r\n\tif ( g_in_cutscene )\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().FrontEndHeap() );\r\n\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\tif ( size < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t{\r\n\t\t\tneed_to_pop = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ThemeHeap() );\r\n\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\tif ( size < ( mem_available - ( 5 * 1024 ) ) )\r\n\t\t\t{\r\n\t\t\t\tneed_to_pop = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ScriptHeap() );\r\n\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\tif ( size < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\t// __PLAT_NGC__\r\n\r\n\tNx::CQuickAnim* pBonedQuickAnim = new Nx::CQuickAnim;\r\n\r\n#ifdef __PLAT_NGC__\r\n\tif ( need_to_pop )\r\n\t{\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n#endif\t// __PLAT_NGC__\r\n\r\n\tpBonedQuickAnim->SetAnimAssetName( animName );\r\n\tpAnimInfo->mp_bonedQuickAnim = pBonedQuickAnim;\r\n\t\r\n\tpAnimInfo->m_animName = animName;\r\n\r\n//\tDbg_Message( \"Boned anim 0x%08x has %d bones\", animName, pBonedQuickAnim->GetNumBones() );\r\n\r\n\tm_numBonedAnims++;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSCutsceneObjectInfo* CCutsceneData::get_object_info( uint32 objectName )\r\n{\r\n\tfor ( int i = 0; i < m_numObjects; i++ )\r\n\t{\r\n\t\tif ( m_objects[i].m_objectName == objectName )\r\n\t\t{\r\n\t\t\treturn &m_objects[i];\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nSCutsceneAnimInfo* CCutsceneData::get_anim_info( uint32 animName )\r\n{\r\n\tfor ( int i = 0; i < m_numBonedAnims; i++ )\r\n\t{\r\n\t\tif ( m_bonedAnims[i].m_animName == animName )\r\n\t\t{\r\n\t\t\treturn &m_bonedAnims[i];\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nObj::CCompositeObject* create_cutscene_dummy_object( Script::CStruct* pNodeData )\r\n{  \r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tCGeneralManager* p_obj_man = skate_mod->GetObjectManager();\r\n\r\n\tObj::CCompositeObject* pDummyObject = new CCompositeObject;\r\n\t\r\n\tpDummyObject->SetType( SKATE_TYPE_COMPOSITE );\r\n\t\r\n\tp_obj_man->RegisterObject(*pDummyObject);\r\n\t\r\n\tScript::RunScript( CRCD(0x1f29c5a5,\"cutsceneobj_add_components\"), pNodeData, pDummyObject );\r\n\t\r\n\tpDummyObject->Finalize();\r\n\r\n\tpDummyObject->m_pos = Mth::Vector( 0.0f, 0.0f, 0.0f, 1.0f );\r\n\r\n\treturn pDummyObject;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid apply_cas_scaling( Obj::CCompositeObject* pObject, Gfx::CSkeleton* pSourceSkeleton )\r\n{\r\n\tObj::CSkeletonComponent* pSkeletonComponent = GetSkeletonComponentFromObject( pObject );\r\n\r\n\tif ( pSkeletonComponent )\r\n\t{\r\n\t\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( pObject );\r\n\t\tif ( pModelComponent->HasRefObject() )\r\n\t\t{\r\n\t\t\tGfx::CSkeleton* pSkeleton = pSkeletonComponent->GetSkeleton();\r\n\t\t\tDbg_Assert( pSkeleton );\r\n\r\n\t\t\tpSkeleton->CopyBoneScale( pSourceSkeleton );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCutsceneData::create_objects( uint32* pData )\r\n{\r\n\t// skip the version number\r\n\tpData++;\r\n\r\n\t// get the number of objects\r\n\tint numObjects = *pData;\r\n\tpData++;\r\n\r\n\tDbg_Message(\"Found %d objects in the CIF file\", numObjects);\r\n\r\n\tfor ( int i = 0; i < numObjects; i++ )\r\n\t{\r\n//\t\tDbg_Message( \"Adding cutscene object #%d:\", i );\r\n\t\t\r\n\t\t// remember the objectName\r\n\t\tuint32 objectName = *pData;\r\n//\t\tDbg_Message( \"objectName = %08x\", *pData );\r\n\t\tpData++;\r\n\r\n\t\t// get the model name\r\n\t\tuint32 modelName = *pData;\r\n\t\tuint32 modelAssetName;\r\n//\t\tDbg_Message( \"modelName = %08x\", *pData );\r\n\t\tmodelAssetName = *pData + Script::GenerateCRC(\"SKIN\");\r\n//\t\tDbg_Message( \"munged modelAssetName = %08x\", modelAssetName );\r\n\t\tpData++;\r\n\r\n\t\t// get the skeleton name\r\n\t\tuint32 skeletonName;\r\n\t\tskeletonName = *pData;\r\n\t\tpData++;\r\n\r\n\t\t// get the anim name (the associated SKA file\r\n\t\t// which should be found somewhere in this CUT file)\r\n\t\tuint32 animName;\r\n\t\tanimName = *pData;\r\n\t\tpData++;\r\n\r\n\t\t// get any extra flags\r\n\t\tuint32 flags;\r\n\t\tflags = *pData;\r\n\t\tpData++;\r\n\r\n\t\tScript::CStruct* pNodeData = new Script::CStruct;\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\t// This substitutes the\tgiven model with the current player model\r\n\t\t// TODO:  Eventually phase out the name \"skater\"\r\n\t\tbool do_player_substitution = ( modelName == CRCD(0x5b8ab877,\"skater\") || modelName == CRCD(0x67e6859a,\"player\") );\r\n\t\tif ( do_player_substitution )\r\n\t\t{\r\n\t\t\tuint32 refObjectName = 0;\r\n\t\t\tpNodeData->AddChecksum( CRCD(0x153a84de,\"refObjectName\"), refObjectName );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// if it's not a skater model, then check for correct skeleton/anims\r\n\t\t\tif ( !mp_fileLibrary->FileExists( modelName, CRCD(0xfd8697e1,\"SKIN\") ) )\r\n\t\t\t{\r\n//\t\t\t\tDbg_MsgAssert( skeletonName == 0, ( \"Non-skinned model %08x has skeleton name\", objectName ) );\r\n\t\t\t\tskeletonName = 0;\r\n//\t\t\t\tDbg_MsgAssert( animName == 0, ( \"Non-skinned model %08x has anim name\", objectName ) );\r\n\t\t\t\tanimName = 0;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( skeletonName != 0, ( \"Skinned model %08x has no skeleton name\", objectName ) );\r\n\t\t\t\tDbg_MsgAssert( animName != 0, ( \"Skinned model %08x has no anim name\", objectName ) );\r\n\t\t\t}\r\n\r\n\t\t\t// if it's the skater's head model and the player has a face texture,\r\n\t\t\t// then we need to swap in the eyeball-less head model...\r\n\t\t\tbool is_head_model = flags & vCUTSCENEOBJECTFLAGS_ISHEAD;\r\n\t\t\tbool is_skater_model = flags & vCUTSCENEOBJECTFLAGS_ISSKATER;\r\n\t\t\tif ( is_head_model && is_skater_model )\r\n\t\t\t{\r\n\t\t\t\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( 0 );\r\n\t\t\t\tGfx::CModelAppearance* pCASModelAppearance = pSkaterProfile->GetAppearance();\r\n\t\t\t\tGfx::CFaceTexture* pCASFaceTexture = pCASModelAppearance->GetFaceTexture();\r\n\t\t\t\tif ( pCASFaceTexture && pCASFaceTexture->IsValid() )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( mp_fileLibrary->FileExists( modelName + 1, CRCD(0xfd8697e1,\"SKIN\") ), ( \"Couldn't find eyeball-less head model\" ) );\r\n\r\n\t\t\t\t\t// eyeball-less head model checksum = regular head model checksum + 1\r\n\t\t\t\t\tmodelAssetName += 1;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Load up the correct head, based on the skater's sex\r\n\t\t\t\tScript::CStruct* pInfo = pSkaterProfile->GetInfo();\r\n\t\t\t\tint is_male = 0;\r\n\t\t\t\tpInfo->GetInteger( CRCD(0x3f813177,\"is_male\"), &is_male, Script::ASSERT );\r\n\t\t\t\tif ( !is_male )\r\n\t\t\t\t{\r\n\t\t\t\t\t// female eyeball = male eyeball + 2\r\n\t\t\t\t\t// female eyeball-less = male eyeball-less + 2\r\n\t\t\t\t\tmodelAssetName += 2;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// this will allow changing facial hair color (needed only for males)\r\n\t\t\t\tpNodeData->AddInteger( CRCD(0x92b43e79,\"multicolor\"), is_male );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tpNodeData->AddChecksum( CRCD(0x86bd5b8f,\"assetName\"), modelAssetName );\r\n\t\t}\r\n\r\n\t\t// if you've got the special-case skull head,\r\n\t\t// then we don't want to subsitute the hi-res skeleton\r\n\t\t{\r\n\t\t\tbool is_head_model = flags & vCUTSCENEOBJECTFLAGS_ISHEAD;\r\n\t\t\tbool is_skater_model = flags & vCUTSCENEOBJECTFLAGS_ISSKATER;\r\n\t\t\tif ( is_head_model && is_skater_model )\r\n\t\t\t{\r\n\t\t\t\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( 0 );\r\n\t\t\t\tGfx::CModelAppearance* pCASModelAppearance = pSkaterProfile->GetAppearance();\r\n\r\n\t\t\t\tScript::CStruct* pHeadStruct = NULL;\r\n\t\t\t\tpHeadStruct = pCASModelAppearance->GetActualDescStructure( CRCD(0x650fab6d,\"skater_m_head\") );\r\n\t\t\t\tif ( !pHeadStruct )\r\n\t\t\t\t{\r\n\t\t\t\t\tpHeadStruct = pCASModelAppearance->GetActualDescStructure( CRCD(0x0fc85bae,\"skater_f_head\") );\r\n\t\t\t\t}\r\n\t\t\t\tif ( pHeadStruct && pHeadStruct->ContainsFlag( CRCD(0xc4c5b2cc,\"NoCutsceneHead\") ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript( CRCD(0xf37d9f53,\"UnhideLoResHeads\") );\r\n\t\t\t\t\tdelete pNodeData;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// another special case for the paper bag...\r\n\t\t\t\tScript::CStruct* pHatStruct = NULL;\r\n\t\t\t\tpHatStruct = pCASModelAppearance->GetActualDescStructure( CRCD(0x6df453b6,\"hat\") );\r\n\t\t\t\tif ( pHatStruct && pHatStruct->ContainsFlag( CRCD(0xc4c5b2cc,\"NoCutsceneHead\") ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript( CRCD(0xf37d9f53,\"UnhideLoResHeads\") );\r\n\t\t\t\t\tdelete pNodeData;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n#if 0\t\t\t\t\r\n\t\t\t\tScript::RunScript( CRCD(0xf37d9f53,\"UnhideLoResHeads\") );\r\n\t\t\t\tdelete pNodeData;\r\n\t\t\t\tcontinue;\r\n#endif\r\n\t\t\t}\r\n\t\t}\r\n\r\n//\t\tDbg_Message( \"skeletonName = %08x\", skeletonName );\r\n//\t\tDbg_Message( \"animName = %08x\", animName );\r\n\t\t\r\n\t\t// TODO:  if the skeleton asset were included\r\n\t\t// in the CUT file, then we wouldn't need the\r\n\t\t// artists to fill in this field manually:\t\r\n\t\tif ( skeletonName )\r\n\t\t{\r\n\t\t\tpNodeData->AddChecksum( CRCD(0x09794932,\"skeletonName\"), skeletonName );\r\n\r\n\t\t\t// this disables the \"bone skip list\" optimization,\r\n\t\t\t// which would otherwise make the cutscene object's\r\n\t\t\t// hands disappear\r\n\t\t\tpNodeData->AddInteger( CRCD(0xd3982061,\"max_bone_skip_lod\"), 0 );\r\n\t\t}\r\n\r\n\t\t// shouldn't have an animation component, because\r\n\t\t// we want the cutscene details to fill up the skeleton\r\n\t\t// with the appropriate data (we don't want the\r\n\t\t// animation component's update() function to get\r\n\t\t// called once per frame and wipe out the cutscene\r\n\t\t// details' changes\r\n\t\t//pNodeData->AddChecksum( CRCD(0x6c2bfb7f,\"animName\"), anim_name );\r\n\r\n\t\tSCutsceneObjectInfo* pObjectInfo = &m_objects[m_numObjects];\r\n\r\n\t\tDbg_MsgAssert( m_numObjects < vMAX_CUTSCENE_OBJECTS, ( \"Too many objects in cutscene (increase vMAX_CUTSCENE_OBJECTS > %d).\", vMAX_CUTSCENE_OBJECTS ) );\r\n\t\tpObjectInfo->mp_object = create_cutscene_dummy_object( pNodeData ); \r\n\r\n\t\t// this\tprevents the skateboard from clipping out\r\n\t\t// when it gets far enough away from the skater\r\n\t\t// (like in the NJ pool cutscene) \r\n\t\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( pObjectInfo->mp_object );\r\n\t\tif ( pModelComponent )\r\n\t\t{\r\n\t\t\tNx::CModel* pModel = pModelComponent->GetModel();\r\n\t\t\tDbg_Assert( pModel );\r\n\t\t\tpModel->SetBoundingSphere( Mth::Vector(0.0f,0.0f,0.0f,50000.0f) );\r\n\r\n\t//\t\tprintf( \"pModel has %d bones, transforms = %p\\n\", pModel->GetNumBones(), pModel->GetBoneTransforms() );\r\n\r\n\t\t\tif ( pModelComponent->HasRefObject() )\r\n\t\t\t{\r\n\t\t\t\tuint32 refObjectName = pModelComponent->GetRefObjectName();\r\n\t\t\t\tObj::CCompositeObject* pRefObject = (Obj::CCompositeObject*)Obj::ResolveToObject( refObjectName );\r\n\t\t\t\tDbg_Assert( pRefObject );\r\n\t\t\t\tObj::CModelComponent* pRefModelComponent = GetModelComponentFromObject( pRefObject );\r\n\t\t\t\tDbg_Assert( pRefModelComponent );\r\n\t\t\t\tNx::CModel* pRefModel = pRefModelComponent->GetModel();\r\n\t\t\t\t\r\n\t\t\t\t// \"m_original_params_set\" ensures that we don't try\r\n\t\t\t\t// to write the same data out multiple times if there\r\n\t\t\t\t// are multiple create-a-skaters (which happens in the\r\n\t\t\t\t// final.cut cutscene)\r\n\t\t\t\tif ( !m_original_params_set )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_original_player_bounding_sphere = pRefModel->GetBoundingSphere();\r\n\t\t\t\t\tm_original_hidden = pRefModel->IsHidden();\r\n\t\t\t\t\tm_original_scale_enabled = pRefModel->IsScalingEnabled();\r\n\t\t\t\t\tm_original_pos = pRefObject->GetPos();\r\n\t\t\t\t\tm_original_params_set = true;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tpRefModel->SetBoundingSphere( Mth::Vector(0.0f,0.0f,0.0f,50000.0f) );\r\n\t\t\t\tpRefModel->Hide( false );\r\n\t\t\t\tpRefModel->EnableScaling( false );\r\n\r\n\t\t\t\tpRefModelComponent->UpdateBrightness();\r\n\t\t\t}\r\n\r\n\t\t\t// don't run the normal update() function,\r\n\t\t\t// or else it will screw up the double-buffer\r\n\t\t\tpModelComponent->Suspend(true);\r\n\t\t}\r\n\r\n\t\tpObjectInfo->m_objectName = objectName;\r\n\r\n\t\t// set the id, so that we can run scripts on it\r\n\t\tDbg_MsgAssert( !Obj::ResolveToObject(objectName), ( \"Object with name %s already exists\", Script::FindChecksumName(objectName) ) );\r\n\t\tpObjectInfo->mp_object->SetID( objectName );\r\n\r\n\t\t// for debugging...\r\n\t\tpObjectInfo->m_skeletonName = skeletonName;\r\n\t\tpObjectInfo->m_doPlayerSubstitution = do_player_substitution;\r\n\t\tpObjectInfo->m_flags = flags;\r\n\r\n\t\tpObjectInfo->mp_animInfo = NULL;\r\n\t\tpObjectInfo->mp_parentObject = NULL;\r\n\t\tpObjectInfo->m_obaIndex = -1;\r\n\r\n\t\t// the animation doesn't necessarily exist for all the objects\r\n\t\tif ( animName )\r\n\t\t{\r\n\t\t\t// enforce that the anim with that name exists,\r\n\t\t\tpObjectInfo->mp_animInfo = get_anim_info( animName );\r\n\t\t\tDbg_MsgAssert( pObjectInfo->mp_animInfo, ( \"Couldn't find SKA with id 0x%08x in LIB file\", animName ) );\r\n\t\t}\r\n\t\t\r\n//\t\tDbg_Message( \"---------------\" );\r\n\r\n\t\tm_numObjects++;\r\n\r\n\t\t// done with temp struct\r\n\t\tdelete pNodeData;\r\n\t}\r\n\r\n\t// apply cas scaling to the appropriate parts\r\n\tfor ( int i = 0; i < m_numObjects; i++ )\r\n\t{\r\n\t\tSCutsceneObjectInfo* pObjectInfo = &m_objects[i];\r\n\r\n\t\tif ( pObjectInfo->m_doPlayerSubstitution )\r\n\t\t{\r\n\t\t\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject(pObjectInfo->mp_object);\r\n\t\t\tDbg_Assert( pModelComponent );\r\n\t\t\t\r\n\t\t\tuint32 refObjectName = pModelComponent->GetRefObjectName();\r\n\t\t\tObj::CCompositeObject* pRefObject = (Obj::CCompositeObject*)Obj::ResolveToObject( refObjectName );\r\n\t\t\tDbg_Assert( pRefObject );\r\n\t\t\t\r\n\t\t\t// body\r\n\t\t\tObj::CSkeletonComponent* pRefSkeletonComponent = GetSkeletonComponentFromObject(pRefObject);\r\n\t\t\tDbg_Assert( pRefSkeletonComponent );\r\n\t\t\tapply_cas_scaling( pObjectInfo->mp_object, pRefSkeletonComponent->GetSkeleton() );\r\n\t\t}\r\n\t\t\r\n\t\tSCutsceneObjectInfo* pParentObjectInfo = get_object_info( pObjectInfo->m_objectName - 1 );\r\n\t\tif ( pParentObjectInfo && pParentObjectInfo->m_doPlayerSubstitution )\r\n\t\t{\r\n\t\t\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject(pParentObjectInfo->mp_object);\r\n\t\t\tDbg_Assert( pModelComponent );\r\n\t\t\t\r\n\t\t\tuint32 refObjectName = pModelComponent->GetRefObjectName();\r\n\t\t\tObj::CCompositeObject* pRefObject = (Obj::CCompositeObject*)Obj::ResolveToObject( refObjectName );\r\n\t\t\tDbg_Assert( pRefObject );\r\n\t\t\t\r\n\t\t\t// head\r\n\t\t\tObj::CSkeletonComponent* pRefSkeletonComponent = GetSkeletonComponentFromObject(pRefObject);\r\n\t\t\tDbg_Assert( pRefSkeletonComponent );\r\n\t\t\tapply_cas_scaling( pObjectInfo->mp_object, pRefSkeletonComponent->GetSkeleton() );\r\n\t\t}\r\n\t}\r\n\r\n\t// do basic poly removal on all objects\r\n\t// w/ some extra poly removal on the player's head\r\n\tfor ( int i = 0; i < m_numObjects; i++ )\r\n\t{\r\n\t\tSCutsceneObjectInfo* pObjectInfo = &m_objects[i];\r\n\r\n\t\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject(pObjectInfo->mp_object);\r\n\t\tif ( pModelComponent )\r\n\t\t{\r\n\t\t\tNx::CModel* pModel = pModelComponent->GetModel();\r\n\r\n\t\t\tuint32 polyRemovalMask = pModel->GetPolyRemovalMask();\r\n\r\n\t\t\tSCutsceneObjectInfo* pParentObjectInfo = get_object_info( pObjectInfo->m_objectName - 1 );\r\n\t\t\tif ( pParentObjectInfo && pParentObjectInfo->m_doPlayerSubstitution )\r\n\t\t\t{\r\n\t\t\t\t// treat the player's head as a special case\r\n\t\t\t\t// because we need to grab the poly removal\r\n\t\t\t\t// mask from the player's body\r\n\r\n\t\t\t\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject(pParentObjectInfo->mp_object);\r\n\t\t\t\tDbg_Assert( pModelComponent );\r\n\r\n\t\t\t\tuint32 refObjectName = pModelComponent->GetRefObjectName();\r\n\t\t\t\tObj::CCompositeObject* pRefObject = (Obj::CCompositeObject*)Obj::ResolveToObject( refObjectName );\r\n\t\t\t\tDbg_Assert( pRefObject );\r\n\r\n\t\t\t\tObj::CModelComponent* pRefModelComponent = GetModelComponentFromObject(pRefObject);\r\n\t\t\t\tDbg_Assert( pRefModelComponent );\r\n\r\n\t\t\t\tNx::CModel* pRefModel = pRefModelComponent->GetModel();\r\n\t\t\t\tDbg_Assert( pRefModel );\r\n\r\n\t\t\t\t// head\r\n\t\t\t\tpolyRemovalMask |= pRefModel->GetPolyRemovalMask();\r\n\t\t\t}\r\n\r\n\t\t\tpModel->HidePolys( polyRemovalMask );\r\n\t\t}\r\n\t}\r\n\r\n\t// relink parents if necessary\r\n\tfor ( int i = 0; i < m_numObjects; i++ )\r\n\t{\r\n\t\tSCutsceneObjectInfo* pObjectInfo = &m_objects[i];\r\n\r\n\t\t// checks for parents, if any...  based on naming convention\r\n\t\tSCutsceneObjectInfo* pParentObjectInfo = get_object_info( pObjectInfo->m_objectName - 1 );\r\n\t\tif ( pParentObjectInfo )\r\n\t\t{\r\n\t\t\tpObjectInfo->mp_parentObject = pParentObjectInfo->mp_object;\r\n\r\n\t\t\tif ( pParentObjectInfo->m_doPlayerSubstitution )\r\n\t\t\t{\r\n\t\t\t\t// it's the hires create-a-skater head,\r\n\t\t\t\t// so need to do some extra texture\treplacement on it\r\n\t\t\t\tObj::CModelComponent* pCASModelComponent = GetModelComponentFromObject(pObjectInfo->mp_object);\r\n\t\t\t\tDbg_Assert( pCASModelComponent );\r\n\t\t\t\t\r\n\t\t\t\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( 0 );\r\n\t\t\t\tGfx::CModelAppearance* pCASModelAppearance = pSkaterProfile->GetAppearance();\r\n\r\n\t\t\t\tpCASModelComponent->InitModelFromProfile(pCASModelAppearance,false,0,CRCD(0x8fb01036,\"replace_cutscene_skater_from_appearance\"));\r\n\t\t\t\r\n\t\t\t\t// apply color from the skater appearance\r\n\t\t\t\t// (we can't do this in replace_cutscene_skater_from_appearance\r\n\t\t\t\t// because it might have an object color to set, which you can\r\n\t\t\t\t// only do if you have the correct geom name)\r\n\t\t\t\tScript::CStruct* pHeadStruct = NULL;\r\n\r\n\t\t\t\tpCASModelAppearance->PrintContents();\r\n\r\n\t\t\t\tpHeadStruct = pCASModelAppearance->GetVirtualDescStructure( CRCD(0x650fab6d,\"skater_m_head\") );\r\n\t\t\t\t\r\n\t\t\t\tif ( !pHeadStruct )\r\n\t\t\t\t{\r\n\t\t\t\t\tpHeadStruct = pCASModelAppearance->GetVirtualDescStructure( CRCD(0x0fc85bae,\"skater_f_head\") );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif ( pHeadStruct )\r\n\t\t\t\t{\r\n\t\t\t\t\tNx::CModel* pCASModel = pCASModelComponent->GetModel();\r\n\t\t\t\t\tDbg_Assert( pCASModel );\r\n\r\n\t\t\t\t\tint use_default_hsv = 1;\r\n\t\t\t\t\tpHeadStruct->GetInteger( CRCD(0x97dbdde6,\"use_default_hsv\"), &use_default_hsv );\r\n\t\t\t\t\tif ( !use_default_hsv )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint h, s, v;\r\n\t\t\t\t\t\tif ( pHeadStruct->GetInteger( CRCD(0x6e94f918,\"h\"), &h, false )\r\n\t\t\t\t\t\t\t && pHeadStruct->GetInteger( CRCD(0xe4f130f4,\"s\"), &s, false )\r\n\t\t\t\t\t\t\t && pHeadStruct->GetInteger( CRCD(0x949bc47b,\"v\"), &v, false ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tScript::CStruct* pTempStruct = new Script::CStruct;\r\n\t\t\t\t\t\t\tpTempStruct->AddChecksum( CRCD(0xb6f08f39,\"part\"), 0 );\r\n\t\t\t\t\t\t\tpTempStruct->AddChecksum( CRCD(0x83418a6a,\"material\"), CRCD(0xaa2206ef,\"cashead_head\") );\r\n\t\t\t\t\t\t\tpTempStruct->AddInteger( CRCD(0x318f2bdb,\"pass\"), 0 );\r\n\t\t\t\t\t\t\tpCASModel->SetColor( pTempStruct, (float)h, (float)s / 100.0f, (float)v / 100.0f );\r\n\t\t\t\t\t\t\tdelete pTempStruct;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tDbg_Assert( mp_objectQuickAnim );\r\n\t\tfor ( int j = 0; j < mp_objectQuickAnim->GetNumBones(); j++ )\r\n\t\t{\r\n\t\t\tuint32 obaObjectName = mp_objectQuickAnim->GetBoneName(j);\r\n\t\t\tif ( pObjectInfo->m_objectName == obaObjectName )\r\n\t\t\t{\r\n\t\t\t\tpObjectInfo->m_obaIndex\t= j;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nchar* get_cut_name( const char* p_fileName )\r\n{\r\n\tstatic char cutsceneName[256];\r\n\r\n\tfor ( int i = strlen(p_fileName); i >= 0; i-- )\r\n\t{\r\n\t\tif ( p_fileName[i] == '\\\\' || p_fileName[i] == '/' )\r\n\t\t{\r\n\t\t\tstrcpy( cutsceneName, &p_fileName[i+1] );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// strip off extension, if one exists\r\n\tchar* pExt = strstr( cutsceneName, \".\" );\r\n\tif ( pExt )\r\n\t{\r\n\t\t*pExt = NULL;\r\n\t}\r\n\r\n\treturn cutsceneName;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCutsceneData::Load( const char* p_fileName, bool assertOnFail, bool async_load )\r\n{   \r\n\t// now that the async code is working, \r\n\t// there's no reason to load it synchronously\r\n\tasync_load = true;\r\n\r\n\t// GJ:  Disabled async load to remove\r\n\t// the glitch when starting cutscenes\r\n\tasync_load = false;\r\n\t\r\n\t// ...  but turn off async for platforms that\r\n\t// don't support it\tanyway\r\n\tif ( !File::CAsyncFileLoader::sAsyncSupported() )\r\n\t{\r\n\t\tasync_load = false;\r\n\t}\r\n\t\r\n\t// based on the name of the CUT file, \r\n\t// we can build the name of the stream associated with it\r\n\tchar* pCutsceneName = get_cut_name( p_fileName );\r\n\r\n\t//-------------------------------------------------------------\r\n\t// Load up the correct stream, based on the skater's sex\r\n\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( 0 );\r\n\tScript::CStruct* pInfo = pSkaterProfile->GetInfo();\r\n\tint is_male = 0;\r\n\tpInfo->GetInteger( CRCD(0x3f813177,\"is_male\"), &is_male, Script::ASSERT );\r\n\t\r\n\tchar streamName[256];\r\n\tif ( is_male )\r\n\t{\r\n\t\tsprintf( streamName, \"%s_Male\", pCutsceneName );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsprintf( streamName, \"%s_Female\", pCutsceneName );\r\n\t}\r\n\t\r\n\tuint32 streamNameChecksum;\r\n\tstreamNameChecksum = Crc::GenerateCRCFromString(streamName);\r\n\r\n#ifndef __PLAT_NGC__\r\n\tif ( !Pcm::PreLoadMusicStream( streamNameChecksum ) )\r\n\t{\r\n\t\tDbg_Message( \"Couldn't start stream...  stream %s not found?\", streamName );\r\n\t\tm_audioStarted = true;\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\t//-------------------------------------------------------------\r\n\r\n\t//-------------------------------------------------------------\r\n\t// Create a cutscene heap here...  it will only be used for the \r\n\t// cutscene, and will prevent fragmentation on the bottom up heap\r\n\t// by things that might get allocated during the cutscene,\r\n\t// such as proxim nodes.\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().TopDownHeap() );\r\n\t\t\r\n\t// reserve about 100K for any allocations that need to go on the \r\n\t// bottom up heap (such as proxim nodes).  Also need to reserve\r\n\t// some room on the topdown heap for texture dictionary loading\r\n\t// on the PS2\r\n\tint mem_available = Mem::Manager::sHandle().Available();\r\n#\tif defined( __PLAT_NGC__ )\r\n#ifdef DVDETH\r\n\tmem_available -= 6 * 1024 * 1024;\r\n#else\r\n#ifdef __NOPT_ASSERT__\r\n\tmem_available = 3 * 1024 * 1024;\r\n#else\r\n\r\n# define toupper(c) ( ( (c) >= 'a' ) && ( (c) <= 'z' ) ) ? (c) += ( 'A' - 'a' ) : (c)\r\n\tchar name[64];\r\n\tchar * ps = (char *)p_fileName;\r\n\tchar * pd = name;\r\n\twhile ( *ps != '\\0' )\r\n\t{\r\n\t\t*pd = toupper( *ps );\r\n\t\tps++;\r\n\t\tpd++;\r\n\t}\r\n\r\n\tif ( strstr( name, \"FL_03\" ) )\r\n\t{\r\n\t\tmem_available -= 200 * 1024;\r\n\t\tOSReport( \"******* Reducing by 200k\\n\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( strstr( name, \"NY_01V\" ) )\r\n\t\t{\r\n\t\t\tmem_available -= 100 * 1024;\r\n\t\t\tOSReport( \"******* Reducing by 80k\\n\" );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( strstr( name, \"NY_02\" ) )\r\n\t\t\t{\r\n\t\t\t\tmem_available -= 80 * 1024;\r\n\t\t\t\tOSReport( \"******* Reducing by 80k\\n\" );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmem_available -= 120 * 1024;\r\n\t\t\t\tOSReport( \"******* Reducing by 120k\\n\" );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\t\t// __NOPT_ASSERT__ \r\n#endif\t\t// DVDETH\r\n#\telif defined( __PLAT_XBOX__ )\r\n\t// Reserve more for Xbox since audio streams will be allocated from bottom up heap.\r\n\tmem_available -= 512 * 1024;\r\n#\telse\r\n\tmem_available -= 200 * 1024;\r\n#\tendif\t\t// __PLAT_NGC__\r\n\r\n#ifdef __PLAT_NGC__\r\n\t\tif ( mem_available < ( 150 * 1024 ) )\r\n\t\t{\r\n\t\t\t// If heap is too small, allocate a 200k heap from the theme region.\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ThemeHeap() );\r\n\t\t\tmem_available = 150 * 1024;\r\n\t\t}\r\n#endif\r\n\r\n\tMem::Manager::sHandle().InitCutsceneHeap( mem_available );\r\n\tMem::Manager::sHandle().PopContext(); \r\n\t//-------------------------------------------------------------\r\n#\tif defined( __PLAT_NGC__ )\r\n\tg_in_cutscene = true;\r\n#\tendif\t\t// __PLAT_NGC__\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().CutsceneBottomUpHeap());\t\r\n\tDbg_MsgAssert( !mp_fileLibrary, ( \"File library already exists\" ) );\r\n\tmp_fileLibrary = new File::CFileLibrary;\r\n\tDbg_MsgAssert( mp_fileLibrary, ( \"Couldn't create file library %s\", p_fileName ) );\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().CutsceneTopDownHeap());\t\r\n\r\n\tbool success = mp_fileLibrary->Load( p_fileName, assertOnFail, async_load );\r\n\t\r\n\tif ( !success )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Couldn't load file library %s\", p_fileName ) );\r\n\t}\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tif ( !async_load )\r\n\t{\r\n\t\tPostLoad( assertOnFail );\r\n\t\tm_dataLoaded = true;\r\n\t}\r\n\r\n#ifdef __PLAT_NGC__\r\n\tif ( !Pcm::PreLoadMusicStream( streamNameChecksum ) )\r\n\t{\r\n\t\tDbg_Message( \"Couldn't start stream...  stream %s not found?\", streamName );\r\n\t\tm_audioStarted = true;\r\n\t}\r\n\r\n\twhile ( !m_audioStarted )\r\n\t{\r\n\t\tPcm::Update();\r\n\t\t\r\n\t\tif ( Pcm::PreLoadMusicStreamDone() )\r\n\t\t{\r\n\t\t\t// TODO:  Fill in with appropriate music volume parameter?\r\n\t\t\tPcm::StartPreLoadedMusicStream();\r\n\r\n\t\t\tm_audioStarted = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tTmr::VSync();\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCutsceneData::LoadFinished()\r\n{\r\n\tif ( m_dataLoaded )\r\n\t{\r\n\t\t// already finished before this...\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// check to see whether the file has finished loading\r\n\tif ( !mp_fileLibrary->LoadFinished() )\r\n\t{\r\n\t\tDbg_Message( \"Waiting for async load to finish...\" );\r\n\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tPostLoad( true );\r\n\t\tm_dataLoaded = true;\r\n\t\treturn true;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t\t\t\t\t\t    \r\nvoid CCutsceneData::update_video_playback( Gfx::Camera* pCamera, Script::CStruct* pStruct )\r\n{\r\n\tif ( !m_videoStarted )\r\n\t{\r\n\t\t// need to pass in the fadeintime\r\n//\t\tScript::SpawnScript( CRCD(0x55665639,\"FadeInCutscene\"), pStruct );\r\n\t\tm_videoStarted = true;\r\n\t\t\r\n\t\tScript::RunScript( CRCD(0xe794a164,\"CutsceneStartVideo\") );\r\n\r\n\t\t// initialize the camera (don't really need to do this,\r\n\t\t// since the camera animation will override it)\r\n\t\tDbg_Assert( pCamera );\r\n//\t\tMth::Vector& camPos = pCamera->GetPos();\r\n//\t\tMth::Matrix& camMatrix = pCamera->GetMatrix();\r\n//\t\tcamPos = Mth::Vector(0.0f,0.0f,0.0f,1.0f);\r\n//\t\tcamMatrix.Ident();\r\n\t\r\n\t\t// reset the camera to some default FOV,\r\n\t\t// or else it will use the last FOV used\r\n\t\tfloat fov_in_degrees = Script::GetFloat( CRCD(0x99529205, \"camera_fov\") );\r\n\t\tpCamera->SetHFOV(fov_in_degrees);\r\n\r\n\t\tm_oldTime = 0.0f;\r\n\t\tm_initialVBlanks = Tmr::GetVblanks();\r\n\t}\r\n\r\n\t// update universal cutscene time\r\n\t// (shouldn't use the animcontroller's update function\r\n\t// because it caps the frame length...  although\r\n\t// there's no real reason that it needs to... \r\n\t// maybe we can have the animcontroller use the\r\n\t// uncapped version as well...  it's only capped\r\n\t// for things like the physics so that objects\r\n\t// don't travel too far in a single frame...)\r\n\tm_oldTime = m_currentTime;\r\n\t\r\n#if 0\r\n\t// here's some debug code for debugging cutscene glitches...\r\n\t// this will loop through 1 second's worth of cutscene data\r\n\t// at half speed.  it was handy for tracking down \r\n\t// SK5:TT10351 - \"pop\" in camera animation when going to\r\n\t// a moving camera cut\r\n\tstatic float cutscene_test_time_offset = 0.0f;\r\n\tcutscene_test_time_offset += ( 1/120.0f );\r\n\tif (cutscene_test_time_offset >= 1.0f )\r\n\t{\r\n\t\tcutscene_test_time_offset -= 1.0f;\r\n\t}\r\n\r\n\tm_currentTime = Script::GetFloat( \"cutscene_test_time\" ) + cutscene_test_time_offset;//(float)( Tmr::GetVblanks() - m_initialVBlanks ) / Config::FPS();\r\n#else\r\n\tm_currentTime = (float)( Tmr::GetVblanks() - m_initialVBlanks ) / Config::FPS();\r\n#endif\r\n\r\n\t// if the CUT file is really small, then chances are\r\n\t// the Makes will still be set from choosing the\r\n\t// item on the menu...  so, the following makes\r\n\t// sure that you don't try to skip it before the\r\n\t// cutscene has played for at least 1 frame...\r\n\tif ( m_videoStarted && ( m_currentTime != 0.0f ) )\r\n\t{\r\n\t\tMdl::FrontEnd* pFront = Mdl::FrontEnd::Instance();\r\n\t\t\r\n\t\tfor ( int i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t\t{\r\n\t\t\tInp::Handler< Mdl::FrontEnd >* pHandler = pFront->GetInputHandler( i );\r\n\t\t\tif ( pHandler->m_Device->IsPluggedIn() && pHandler->m_Device->HasValidControlData() && pHandler->m_Input->m_Makes & Inp::Data::mD_X )\r\n\t\t\t{\r\n\t\t\t\t// GJ FIX FOR TT12703:  \"If the player disconnects the \r\n\t\t\t\t// controller during any cut scene in the game, the player\r\n\t\t\t\t// can reconnect the controller into any of the other 3\r\n\t\t\t\t// controller ports and bypass the cut scene by pressing\r\n\t\t\t\t// the A button. Since story mode is a one player game, the\r\n\t\t\t\t// player should not be able to use multiple ports at the\r\n\t\t\t\t// same time.\"\r\n\t\t\t\tif ( i == Mdl::Skate::Instance()->m_device_server_map[0] )\r\n\t\t\t\t{\r\n\t\t\t\t\t// skip to the end of the movie...\r\n\t\t\t\t\tm_currentTime = mp_cameraQuickAnim->GetDuration();\r\n\t\t\t\t\tm_videoAborted = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_Message( \"Can only abort cutscenes from first controller\" );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tupdate_camera( pCamera );\r\n\r\n\t// boned anims should come before moving objects,\r\n\t// because some moving objects depend on the \r\n\t// current position of the neck bone\r\n\tupdate_boned_anims();\t\r\n\r\n\tupdate_moving_objects();\r\n\r\n\tupdate_extra_cutscene_objects();\r\n\r\n/*\r\n\t// display moving objects here\r\n\t// (need to do it after the object anims AND\r\n\t// the skeletal anims have been updated for\r\n\t// this frame)\r\n\tfor ( int i = 0; i < m_numObjects; i++ )\r\n\t{\r\n\t\tif ( m_objects[i].mp_animInfo )\r\n\t\t{\r\n\t\t\tObj::CCompositeObject* pCompositeObject = m_objects[i].mp_object;\t\r\n\t\t\tDbg_Assert( pCompositeObject );\r\n\r\n\t\t\tObj::CSkeletonComponent* pSkeletonComponent = GetSkeletonComponentFromObject( pCompositeObject );\r\n\t\t\tif ( pSkeletonComponent )\r\n\t\t\t{\r\n\t\t\t\tGfx::CSkeleton* pSkeleton = pSkeletonComponent->GetSkeleton();\r\n\t\t\t\tDbg_Assert( pSkeleton );\r\n\t\r\n\t\t\t\t// if we're going to grab the display matrix, need to grab it\r\n\t\t\t\t// *after* the object anims have been updated\r\n\t\t\t\tMth::Matrix theMat = pCompositeObject->GetDisplayMatrix();\r\n\t\t\t\ttheMat[Mth::POS] = pCompositeObject->GetPos();\r\n\t\t\t\tpSkeleton->Display( &theMat, 1.0f, 0.0f, 0.0f );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n*/\r\n\tif ( Script::GetInteger( CRCD(0x5ecc0073,\"debug_cutscenes\") ) )\r\n\t{\r\n\t\t// pass the pertinent info to the panel:\r\n\t\tScript::CStruct* pTempStruct = new Script::CStruct;\r\n\r\n//\t\t\tchar line1[128];\r\n//\t\t\tsprintf( line1, \"camera = %f\", m_cameraController.GetCurrentAnimTime() );\r\n//\t\t\tpTempStruct->AddString( \"line1\", (const char*)&line1 );\r\n\r\n\t\tchar line1[128];\r\n\t\tsprintf( line1, \"time = %f\", m_currentTime );\r\n\t\tpTempStruct->AddString( \"line1\", (const char*)&line1 );\r\n\r\n\t\tScript::RunScript( CRCD(0xd9157174,\"draw_cutscene_panel\"), pTempStruct );\r\n\r\n\t\tdelete pTempStruct;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneData::update_extra_cutscene_objects()\r\n{\r\n\t// GJ:  the cutscene manager updates the camera position after\r\n\t// the object manager updates the extra peds in the scene,\r\n\t// meaning that the extra peds will still be using the\r\n\t// previous frame's camera position to calculate whether it\r\n\t// should be visible.  effectively, this causes a 1-frame glitch\r\n\t// whenever there's a new camera cut and a ped appears for the\r\n\t// first time on-screen.  to patch this, i will loop through\r\n\t// the list of all the extra peds for the cutscene and re-apply\r\n\t// their model positions.\r\n\t\r\n\tScript::CArray* pArray = Script::GetArray( CRCD(0x67f08671,\"CutsceneObjectNames\"), Script::NO_ASSERT );\r\n\tif ( pArray )\r\n\t{\r\n\t\tfor ( uint32 i = 0; i < pArray->GetSize(); i++ )\r\n\t\t{\r\n\t\t\tuint32 objectName = pArray->GetChecksum( i );\r\n\t\t\tObj::CCompositeObject* pObject = (Obj::CCompositeObject*)Obj::ResolveToObject( objectName );\r\n\t\t\tif ( pObject )\r\n\t\t\t{\r\n\t\t\t\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( pObject );\r\n\t\t\t\tif ( pModelComponent && pModelComponent->GetModel() )\r\n\t\t\t\t{\r\n\t\t\t\t\tpModelComponent->GetModel()->SetActive( true );\r\n\t\t\t\t\tpModelComponent->Update();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/*\r\n\t// repeat for the skater\r\n\tObj::CCompositeObject* pObject = (Obj::CCompositeObject*)Obj::ResolveToObject( 0 );\r\n\tif ( pObject )\r\n\t{\r\n\t\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( pObject );\r\n\t\tif ( pModelComponent && pModelComponent->GetModel() )\r\n\t\t{\r\n\t\t\tpModelComponent->GetModel()->SetActive( true );\r\n//\t\t\tpModelComponent->Update();\r\n\t\t}\r\n\t}\r\n\t*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneData::Update( Gfx::Camera* pCamera, Script::CStruct* pStruct )\r\n{\r\n\tif ( !m_audioStarted )\r\n\t{\r\n\t\t// TODO:  Maybe have some timeout, so that if it \r\n\t\t// can't find the stream, it won't wait forever...\r\n\r\n\t\tif ( Pcm::PreLoadMusicStreamDone() )\r\n\t\t{\r\n\t\t\t// TODO:  Fill in with appropriate music volume parameter\r\n\t\t\tPcm::StartPreLoadedMusicStream();\r\n\r\n\t\t\tm_audioStarted = true;\r\n\t\t\t\r\n\t\t\t// GJ:  This seemed to cause sync problems\r\n\t\t\t// when the CUT file is really small (quick\r\n\t\t\t// to load), and the streams aren't ready\r\n\t\t\t// to go yet...  need to look into it more\r\n\r\n\t\t\t// now that the music stream has started,\r\n\t\t\t// we should start updating the video\r\n\t\t\t// on this frame\r\n\t\t\tupdate_video_playback( pCamera, pStruct );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Message( \"Waiting for streams to preload to finish...\" );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tupdate_video_playback( pCamera, pStruct );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCutsceneData::IsAnimComplete()\r\n{\r\n\t// we don't call the Update() function any more\r\n\t// (because Update() uses the capped frame rate)\r\n\t//return m_cameraController.IsAnimComplete();\r\n\r\n\treturn m_currentTime >= mp_cameraQuickAnim->GetDuration(); \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneData::update_camera( Gfx::Camera* pCamera )\r\n{\r\n\tDbg_Assert( pCamera );\r\n\r\n\t// Not sure if this is still needed for the Doppler effect code\r\n\t// Maybe we can add the functionality automatically to the Gfx::Camera?\r\n\tpCamera->StoreOldPos();\r\n\r\n\tMth::Vector& camPos = pCamera->GetPos();\r\n\tMth::Matrix& camMatrix = pCamera->GetMatrix();\r\n\t\r\n\tMth::Quat theQuat;\r\n\tMth::Vector theTrans;\r\n\r\n\tget_current_frame( &theQuat, &theTrans );\r\n\t\t\r\n\t// update the camera position\r\n\tcamPos = theTrans;\r\n\r\n\t// update the camera orientation\r\n\tMth::Vector nullTrans;\r\n\tnullTrans.Set(0.0f,0.0f,0.0f,1.0f);\t\t// Mick: added separate initialization\r\n\tMth::QuatVecToMatrix( &theQuat, &nullTrans, &camMatrix );\r\n\r\n\tif ( !m_videoAborted )\r\n\t{\r\n\t\t// any allocations during the cutscene should go on the\r\n\t\t// cutscene heap (such as pedestrians).  at the end\r\n\t\t// of the cutscene, we require that the cutscene heap\r\n\t\t// is empty before it is deleted...\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().CutsceneBottomUpHeap());\t\r\n\r\n\t\t// process any new keys since last frame...\r\n\t\t// do this AFTER the camera is updated for\r\n\t\t// the frame, because a custom key might\r\n\t\t// override the normal value (this is a fix\r\n\t\t// for the double-cut problem, which\r\n\t\t// tries to interpolate between the end\r\n\t\t// of one camera and the beginning of the\r\n\t\t// next...  what we really want is to \r\n\t\t// keep on the end of the previous camera)\r\n\t\tmp_cameraQuickAnim->ProcessCustomKeys( m_oldTime, m_currentTime, pCamera );\r\n\t\t\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\r\n//\tprintf( \"Done for frame\\n\" );\r\n\r\n//\tcamPos.PrintContents();\r\n//\tcamMatrix.PrintContents();\r\n}\r\n\r\n// TODO:  Check for overflow of temp arrays\r\nstatic Mth::Quat s_temp_quats[96];\r\nstatic Mth::Vector s_temp_vectors[96];\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneData::update_boned_anims()\r\n{\r\n\tfor ( int i = 0; i < m_numObjects; i++ )\r\n\t{\r\n\t\tif ( m_objects[i].mp_animInfo )\r\n\t\t{\r\n\t\t\tObj::CCompositeObject* pCompositeObject = m_objects[i].mp_object;\t\r\n\t\t\tDbg_Assert( pCompositeObject );\r\n\r\n\t\t\tObj::CSkeletonComponent* pSkeletonComponent = GetSkeletonComponentFromObject( pCompositeObject );\r\n\t\t\tif ( pSkeletonComponent )\r\n\t\t\t{\r\n\t\t\t\tGfx::CSkeleton* pSkeleton = pSkeletonComponent->GetSkeleton();\r\n\t\t\t\tDbg_Assert( pSkeleton );\r\n\r\n\t\t\t\tNx::CQuickAnim* pBonedQuickAnim = m_objects[i].mp_animInfo->mp_bonedQuickAnim;\r\n\r\n\t\t\t\t// turn off the bone skipping, because we're\r\n\t\t\t\t// not going through the normal animation code\r\n\t\t\t\tpSkeleton->SetBoneSkipDistance( 0.0f );\r\n\r\n\t\t\t\tpBonedQuickAnim->GetInterpolatedFrames( &s_temp_quats[0], &s_temp_vectors[0], pSkeleton->GetBoneSkipList(), pSkeleton->GetBoneSkipIndex(), m_currentTime );\r\n\r\n\t\t\t\tif ( m_objects[i].m_doPlayerSubstitution && pSkeleton->GetNumBones() == 55 )\r\n\t\t\t\t{\t\t\t\t\t\r\n\t\t\t\t\tint bone_index = pSkeleton->GetBoneIndexById( CRCD(0x7268c230,\"bone_jaw\") );\r\n\t\t\t\t\t\r\n\t\t\t\t\t// GJ:  the hi-res jaw bone and the low-res jaw bone aren't in the\r\n\t\t\t\t\t// exact same position, which is required for the skinning to\r\n\t\t\t\t\t// work properly (otherwise, it would create a gap between the\r\n\t\t\t\t\t// head and body models.)  ideally on the next project, we will\r\n\t\t\t\t\t// change the exporter so that it puts the correct low-res jaw\r\n\t\t\t\t\t// position into the body's SKA, and the correct hi-res jaw into\r\n\t\t\t\t\t// the head's SKA.  For now, since we only have access to the\r\n\t\t\t\t\t// correct hi-res jaw bone position, we need to explicitly\r\n\t\t\t\t\t// offset the position of the low-res jaw bone here.  the offset\r\n\t\t\t\t\t// was derived by subtracting the low-res jaw bone bone-space \r\n\t\t\t\t\t// translation (-0.000004, -1.776663, 0.599479) from the hi-res\r\n\t\t\t\t\t// jaw's bone-space translation (0, -1.57249, 0.08276)\r\n\t\t\t\t\ts_temp_vectors[bone_index] += Mth::Vector(0.000000f, -1.776663f-(-1.57249f), 0.599479f-0.08276f, 1.000000f);\r\n\r\n//\t\t\t\t\ts_temp_vectors[bone_index] = Mth::Vector(0.000000f, -2.531250f, 1.406250f, 1.000000f);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tpSkeleton->Update( &s_temp_quats[0], &s_temp_vectors[0] );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid update_model_component( Obj::CCompositeObject* pCompositeObject )\r\n{\r\n\tCModelComponent* pModelComponent = GetModelComponentFromObject( pCompositeObject );\r\n\tif ( pModelComponent )\r\n\t{\r\n\t\t// if it's hidden, there's no reason to update it...\r\n\t\t// (as a side benefit, this also allows us to have multiple\r\n\t\t// objects referencing the same skater, such as in final.cut...\r\n\t\t// otherwise, each object would try to update the same model's \r\n\t\t// position, and only the last object processed would actually\r\n\t\t// look correct)\r\n\t\tNx::CModel* pModel = pModelComponent->GetModel();\r\n\t\tDbg_Assert( pModel );\r\n\t\tif ( pModel->IsHidden() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( pModelComponent->HasRefObject() )\r\n\t\t{\r\n\t\t\tuint32 refObjectName = pModelComponent->GetRefObjectName();\r\n\t\t\tObj::CCompositeObject* pRefObject = (Obj::CCompositeObject*)Obj::ResolveToObject( refObjectName );\r\n\t\t\tDbg_Assert( pRefObject );\r\n\t\t\tObj::CModelComponent* pRefModelComponent = GetModelComponentFromObject( pRefObject );\r\n\t\t\tDbg_Assert( pRefModelComponent );\r\n\t\t\tNx::CModel* pRefModel = pRefModelComponent->GetModel();\r\n\t\t\t   \r\n\t\t\t// turn off skater brightness, so that it matches the other objects...\r\n\t\t\tpRefModelComponent->GetModel()->GetModelLights()->SetBrightness( 0.0f );\r\n\r\n\t\t\t// update brightness in case there's any time of day changes\r\n\t\t\tpRefModelComponent->UpdateBrightness();\r\n\t\t\t\r\n\t\t\tbool should_animate = true;\r\n\t\t\tObj::CSkeletonComponent* pSkeletonComponent = GetSkeletonComponentFromObject( pCompositeObject );\r\n\t\t\tDbg_Assert( pSkeletonComponent );\r\n\t\t\tMth::Matrix theMatrix = pCompositeObject->GetDisplayMatrix();\r\n\t\t\ttheMatrix[Mth::POS] = pCompositeObject->GetPos();\r\n\t\t\tpRefModel->Render( &theMatrix, !should_animate, pSkeletonComponent->GetSkeleton() );\r\n\t\t\tpRefModel->SetBoneMatrixData( pSkeletonComponent->GetSkeleton() );\r\n\r\n\t\t\t// TODO:  Should do some check that the object's skeleton matches up with the ref object's models.\r\n\t\t\r\n\t\t\t// Need to update the fake skater's position with the\r\n\t\t\t// real skater's position, or else the FakeLights will\r\n\t\t\t// be set incorrectly (FakeLights works by taking the \r\n\t\t\t// closest light to the m_pos that is pointed to by the\r\n\t\t\t// model lights)\r\n\t\t\tpRefObject->SetPos( pCompositeObject->GetPos() );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// update brightness in case there's any time of day changes\r\n\t\t\tpModelComponent->UpdateBrightness();\r\n\t\t\t\r\n\t\t\t// remember:\r\n\t\t\t// if there's no model specified, then it will draw\r\n\t\t\t// a red box.  the compositeobject's update() loop\r\n\t\t\t// will draw a red box with identity parameters, and then\r\n\t\t\t// this will draw a second one.  so don't freak out\r\n\t\t\t// when you see more boxes than you are expecting\r\n\t\t\tpModelComponent->Update();\r\n\r\n\t\t\t// GJ:  If you call the Update() function explicitly,\r\n\t\t\t// the model's double-buffer will be messed up...\r\n\t\t\t// in this case, however, we have suspended the model\r\n\t\t\t// component upon creation, so it doesn't get wonky\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneData::update_moving_objects()\r\n{\r\n\tif ( !mp_objectQuickAnim )\r\n\t{\r\n\t\t// No OBA data found in CUT file\r\n\t\treturn;\r\n\t}\r\n\r\n\tmp_objectQuickAnim->GetInterpolatedHiResFrames( &s_temp_quats[0], &s_temp_vectors[0], m_currentTime );\r\n\r\n\t// update all the OBA bones that don't have an object associated with it\r\n\tfor ( int i = 0; i < mp_objectQuickAnim->GetNumBones(); i++ )\r\n\t{\r\n\t\tuint32 boneName = mp_objectQuickAnim->GetBoneName(i);\r\n\t\t\r\n\t\tbool objectExists = false;\r\n\r\n\t\tfor ( int j = m_numObjects - 1; j >= 0; j-- )\r\n\t\t{\r\n\t\t\tSCutsceneObjectInfo* pInfo = &m_objects[j];\r\n\t\t\tif ( pInfo->m_objectName == boneName )\r\n\t\t\t{\r\n\t\t\t\tobjectExists = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( !objectExists )\r\n\t\t{\r\n\t\t\tObj::CCompositeObject* pCompositeObject = (Obj::CCompositeObject*)Obj::ResolveToObject( boneName );\r\n\t\t\tif ( pCompositeObject )\r\n\t\t\t{\r\n\t\t\t\t// update the object's orientation\r\n\t\t\t\tMth::Matrix theMatrix;\r\n\r\n\t\t\t\tMth::Vector nullTrans;\r\n\t\t\t\tnullTrans.Set(0.0f,0.0f,0.0f,1.0f);\t\t// Mick: added separate initialization\r\n\t\t\t\tMth::QuatVecToMatrix( &s_temp_quats[i], &nullTrans, &theMatrix );\r\n\r\n\t\t\t\t//theMatrix.Ident();\r\n\t\t\t\tpCompositeObject->SetMatrix( theMatrix );\r\n\t\t\t\tpCompositeObject->SetDisplayMatrix( theMatrix );\r\n\r\n\t\t\t\t// update the object's position\r\n\t\t\t\tpCompositeObject->m_pos = s_temp_vectors[i];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t// need to go backwards because the head is dependent\r\n\t// on the body's matrices being set up correctly\r\n\t// for that frame...\r\n\tfor ( int i = m_numObjects - 1; i >= 0; i-- )\r\n\t{\r\n\t\tSCutsceneObjectInfo* pInfo = &m_objects[i];\r\n\r\n\t\tObj::CCompositeObject* pCompositeObject = pInfo->mp_object;\r\n\r\n\t\tif ( pInfo->mp_parentObject )\r\n\t\t{\r\n\t\t\t// we handle the hi-res heads specially...  if we\r\n\t\t\t// were to use the OBA data, the hi-res head wouldn't\r\n\t\t\t// match up exactly with the body, possibly due to\r\n\t\t\t// accumulated round-off error as we move down the\r\n\t\t\t// parent-child hierarchy\r\n\r\n\t\t\tObj::CCompositeObject* pParentObject = pInfo->mp_parentObject;\r\n\t\t\tDbg_Assert( pParentObject );\r\n\r\n\t\t\t// if it's a neck bone, then use the previous item to link it\r\n\t\t\tObj::CSkeletonComponent* pSkeletonComponent = GetSkeletonComponentFromObject( pParentObject );\r\n\t\t\tDbg_Assert( pSkeletonComponent );\r\n\t\t\tGfx::CSkeleton* pSkeleton = pSkeletonComponent->GetSkeleton();\r\n\t\t\tDbg_Assert( pSkeleton );\r\n\t\t\tMth::Vector neckPos;\r\n\t\t\tbool success = pSkeleton->GetBonePosition( CRCD(0x5a0e0860,\"bone_neck\"), &neckPos );\r\n\t\t\tif ( !success )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"Couldn't find the neck bone\" ) );\r\n\t\t\t}\r\n\r\n\t\t\tpCompositeObject->m_pos = pParentObject->m_pos + ( neckPos * pParentObject->GetDisplayMatrix() );\r\n\t\t\tpCompositeObject->m_pos[W] = 1.0f;\r\n\r\n\t\t\tMth::Matrix bone_matrix;\r\n\t\t\tsuccess = pSkeleton->GetBoneMatrix( CRCD(0x5a0e0860,\"bone_neck\"), &bone_matrix );\r\n\t\t\tif ( !success )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"Couldn't find the neck bone\" ) );\r\n\t\t\t}\r\n\r\n\t\t\t// build the object's matrix\r\n\t\t\tMth::Matrix object_matrix = pParentObject->GetDisplayMatrix();\r\n\t\t\tobject_matrix[W] = pParentObject->GetPos();\r\n\t\t\tobject_matrix[X][W] = 0.0f;\r\n\t\t\tobject_matrix[Y][W] = 0.0f;\r\n\t\t\tobject_matrix[Z][W] = 0.0f;\r\n\t\t\t\r\n\t\t\t// rotate by 90:  doesn't seem to be needed\r\n\t\t\t// any more, perhaps due to an exporter bug\r\n\t\t\t// being fixed\r\n\t\t\t//Mth::Vector temp;\r\n\t\t\t//temp = bone_matrix[Y];\r\n\t\t\t//bone_matrix[Y] = bone_matrix[Z];\r\n\t\t\t//bone_matrix[Z] = -temp;\r\n\r\n\t\t\t// map the bone to world space\r\n\t\t\tbone_matrix *= object_matrix; \r\n\t\t\tbone_matrix[W] = Mth::Vector(0.0f,0.0f,0.0f,1.0f);\r\n\r\n\t\t\tpCompositeObject->SetMatrix( bone_matrix );\r\n\t\t\tpCompositeObject->SetDisplayMatrix( bone_matrix );\r\n\r\n\t\t\t// need to update the component manually,\r\n\t\t\t// because it is probably out of range for\r\n\t\t\t// the suspension logic\r\n\t\t\tupdate_model_component( pCompositeObject );\r\n\t\t}\r\n\t\telse if ( pInfo->m_obaIndex != -1 )\r\n\t\t{\r\n\t\t\t// if the object is directly referenced in the OBA file,\r\n\t\t\t// then use the position and rotation specified in the OBA.\r\n\r\n\t\t\t// update the object's orientation\r\n\t\t\tMth::Matrix theMatrix;\r\n\r\n\t\t\tMth::Vector nullTrans;\r\n\t\t\tnullTrans.Set(0.0f,0.0f,0.0f,1.0f);\t\t// Mick: added separate initialization\r\n\t\t\tMth::QuatVecToMatrix( &s_temp_quats[pInfo->m_obaIndex], &nullTrans, &theMatrix );\r\n\r\n\t\t\t// GJ:  this used to be a kludge to fix objects\r\n\t\t\t// being rotated incorrectly by 90 degrees.  it\r\n\t\t\t// was probably due to an exporter bug, which\r\n\t\t\t// seems to have been fixed.  in any case,\r\n\t\t\t// it doesn't make sense why we would need\r\n\t\t\t// to rotate it in code, so i will comment\r\n\t\t\t// this out permanently and we can fix the\r\n\t\t\t// bug in the exporter if it ever arises again.\r\n\t\t\tif ( pInfo->m_skeletonName == 0 )\r\n\t\t\t{\r\n\t\t\t\t// but we still need to do it for MDL files\r\n\t\t\t\t// because it doesn't have SKA data that\r\n\t\t\t\t// automatically rotates it\r\n\t\t\t\t// theMatrix.RotateXLocal( Mth::DegToRad(90.0f) );\r\n\t\t\t}\r\n\r\n\t\t\t//theMatrix.Ident();\r\n\t\t\tpCompositeObject->SetMatrix( theMatrix );\r\n\t\t\tpCompositeObject->SetDisplayMatrix( theMatrix );\r\n\r\n\t\t\t// update the object's position\r\n\t\t\tpCompositeObject->m_pos = s_temp_vectors[pInfo->m_obaIndex];\r\n\r\n//\t\t\tDbg_Message( \"Object %d:   \", i );\r\n//\t \t\tpCompositeObject->m_pos.PrintContents();\r\n//\t\t\tpCompositeObject->GetDisplayMatrix().PrintContents();\r\n\r\n\t\t\t// need to update the component manually,\r\n\t\t\t// because it is probably out of range for\r\n\t\t\t// the suspension logic\r\n\t\t\tupdate_model_component( pCompositeObject );\r\n\t\t}\r\n\r\n//\t\tif ( pCompositeObject->GetID() == Script::GenerateCRC( \"Skin_CAS2\" ) )\r\n//\t\t{\r\n//\t\t\tprintf( \"Setting %s at time %d\"\\n, Script::FindChecksumName(pCompositeObject->GetID()), (int)(m_currentTime/60.0f+0.5f) );\r\n//\t\t\tpCompositeObject->GetPos().PrintContents();\r\n//\t\t}\r\n\r\n#if 0\r\n\t\t// print out world-space position of board for adam:\r\n\t\t{\r\n\t\t\tObj::CSkeletonComponent* pSkeletonComponent = GetSkeletonComponentFromObject( pCompositeObject );\r\n\t\t\tif ( pSkeletonComponent )\r\n\t\t\t{\r\n\t\t\t\tGfx::CSkeleton* pSkeleton = pSkeletonComponent->GetSkeleton();\r\n\t\t\t\tMth::Vector theVec;\r\n\t\t\t\tif ( pSkeleton->GetBonePosition( Script::GenerateCRC(\"bone_board_root\"), &theVec ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf( \"Position of %s at time %f:\\n\\t\", Script::FindChecksumName(pCompositeObject->GetID()), m_currentTime );\r\n\t\t\t\t\tpCompositeObject->GetPos().PrintContents();\r\n\t\t\t\t\t\r\n\t\t\t\t\tprintf( \"Position of %s's board at time %f:\\n\\t\", Script::FindChecksumName(pCompositeObject->GetID()), m_currentTime );\r\n\t\t\t\t\ttheVec = pCompositeObject->GetPos() + ( theVec * pCompositeObject->GetDisplayMatrix() );\r\n\t\t\t\t\ttheVec.PrintContents();\r\n             \t\t\t\t\t\r\n\t\t\t\t\tprintf( \"--------------------------------\\n\" );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n#endif\t  \r\n\r\n\t\tif ( Script::GetInteger( CRCD(0x5ecc0073,\"debug_cutscenes\"), Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\t// set up bounding box\r\n\t\t\tSBBox theBox;\r\n\t\t\ttheBox.m_max.Set(1.0f, 10.0f, 1.0f);\r\n\t\t\ttheBox.m_min.Set(-1.0f, -1.0f, -1.0f);    \r\n\r\n\t\t\t// For now, draw a bounding box\r\n\t\t\tGfx::AddDebugBox( pCompositeObject->GetDisplayMatrix(), pCompositeObject->GetPos(), &theBox, NULL, 1, NULL ); \r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneData::get_current_frame(Mth::Quat* pQuat, Mth::Vector* pTrans)\r\n{\r\n\tDbg_Assert( pQuat );\r\n\tDbg_Assert( pTrans );\r\n\r\n\t// with cutscenes, i don't actually want to get \r\n\t// the interpolated frames, i actually want the closest frame\r\n\t// this is for camera positions that are held on a certain\r\n\t// frame for a period of time, and then jumps somewhere else\r\n\t// in this case we would want either the old pose or the new pose,\r\n\t// not something in the middle\r\n\r\n\t// this means we will not want compression on it\r\n\r\n\t// grab the frame from the animation controller\r\n\tDbg_MsgAssert( mp_cameraQuickAnim, ( \"Camera data has not been initialized for this cutscene\" ) );\r\n\tDbg_Assert( mp_cameraQuickAnim->GetNumBones() == 1 );\r\n\tmp_cameraQuickAnim->GetInterpolatedHiResFrames( pQuat, pTrans, m_currentTime );\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCutsceneDetails::CCutsceneDetails()\r\n{\t\t\t\t  \r\n\tmp_cutsceneAsset = NULL;\r\n\tm_cutsceneAssetName = 0;\r\n\r\n\tmp_cutsceneStruct = new Script::CStruct;\r\n\r\n\tm_numHiddenObjects = 0;\r\n\tmp_hiddenObjects = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCCutsceneDetails::~CCutsceneDetails()\r\n{\r\n\tif ( mp_cutsceneStruct )\r\n\t{\r\n\t\tdelete mp_cutsceneStruct;\r\n\t}\r\n\r\n\tif ( mp_cutsceneAsset )\r\n\t{\r\n\t\tAss::CAssMan* pAssMan = Ass::CAssMan::Instance();\r\n\t\tAss::CAsset* pAsset = pAssMan->GetAssetNode( m_cutsceneAssetName, true );\r\n\t\tpAssMan->UnloadAsset( pAsset );\r\n\t\tmp_cutsceneAsset = NULL;\r\n\t}\r\n\r\n\tif ( mp_hiddenObjects )\r\n\t{\r\n\t\tdelete[] mp_hiddenObjects;\r\n\t\tmp_hiddenObjects = NULL;\r\n\t}\r\n\t\r\n\t// restore the dynamic light modulation factor\r\n\tNx::CLightManager::sSetAmbientLightModulationFactor( m_oldAmbientLightModulationFactor );\r\n\tNx::CLightManager::sSetDiffuseLightModulationFactor( 0, m_oldDiffuseLightModulationFactor[0] );\r\n\tNx::CLightManager::sSetDiffuseLightModulationFactor( 1, m_oldDiffuseLightModulationFactor[1] );\r\n\r\n\t// don't need to refresh the skater, because\r\n\t// it will be applied on the next frame anyway\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCutsceneDetails::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tbool success = false;\r\n\r\n\t/// need to create a temp copy of the params...  this is because\r\n\t// the PreCutscene script destroys the screen element that launched\r\n\t// the cutscene, meaning that afterwards the data inside pParams \r\n\t// will become corrupt...\r\n\tScript::CStruct* pTempParams = new Script::CStruct;\r\n\tpTempParams->AppendStructure( pParams );\r\n\r\n\tthis->SetParams( pTempParams );\r\n\r\n\t// TODO:  Handle async loads of cutscene\r\n\tbool async = false;\r\n//\tbool dont_assert = false;\r\n\r\n\t// TODO:  Need to account for the possibility that the same\r\n\t// cutscene will be loaded twice\r\n\r\n\t// TODO:  Push the correct heap\r\n\r\n\t// turn off the modulation for the duration of the cutscene\r\n\tm_oldAmbientLightModulationFactor = Nx::CLightManager::sGetAmbientLightModulationFactor();\r\n\tm_oldDiffuseLightModulationFactor[0] = Nx::CLightManager::sGetDiffuseLightModulationFactor(0);\r\n\tm_oldDiffuseLightModulationFactor[1] = Nx::CLightManager::sGetDiffuseLightModulationFactor(1);\r\n\r\n\tNx::CLightManager::sSetAmbientLightModulationFactor( 0.0f );\r\n\tNx::CLightManager::sSetDiffuseLightModulationFactor( 0, 0.0f );\r\n\tNx::CLightManager::sSetDiffuseLightModulationFactor( 1, 0.0f );\r\n\r\n\t// force the fake lights to allocate its memory now\r\n\t// (otherwise, the next call to RenderWorld() would\r\n\t// alloc it which would end up fragmenting memory)\r\n\tNx::CLightManager::sUpdateVCLights();\r\n\r\n\t// also need to turn it off on the skater to refresh it\r\n\t// (but that will be done if there's a ref model)\r\n\r\n\tconst char* pCutsceneFileName;\r\n\tpTempParams->GetText( CRCD(0xa1dc81f9,\"name\"), &pCutsceneFileName, Script::ASSERT );\r\n\t\r\n\tAss::CAssMan* pAssMan = Ass::CAssMan::Instance();\r\n\tif ( pAssMan->GetAsset( pCutsceneFileName, false ) )\r\n\t{\r\n\t\tDbg_Message( \"Cutscene %s is already playing!\", pCutsceneFileName );\r\n\t\tgoto init_failed;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tchar* pCutName = get_cut_name( pCutsceneFileName );\r\n\t\tchar structName[256];\r\n\t\tstrcpy( structName, pCutName );\r\n\t\tstrcat( structName, \"_params\" );\r\n\r\n\t\tScript::CStruct* pCutParams = Script::GetStructure(structName, Script::NO_ASSERT);\r\n\t\tif ( pCutParams )\r\n\t\t{\r\n\t\t\tmp_cutsceneStruct->AppendStructure( pCutParams );\r\n\t\t}\r\n\r\n\t\t// first look at \"dont_unload_anims\" flag in cutscene struct\r\n\t\tint should_unload_anims = !mp_cutsceneStruct->ContainsFlag( CRCD(0xbafa9f1c,\"dont_unload_anims\") );\r\n\t\tint should_reload_anims = !mp_cutsceneStruct->ContainsFlag( CRCD(0xbafa9f1c,\"dont_unload_anims\") );\r\n\r\n\t\tif ( pParams->ContainsFlag( CRCD(0x7ddde00e,\"from_cutscene_menu\") ) )\r\n\t\t{\r\n\t\t\t// if we're coming from the cutscene menu, we never want to unload anims\r\n\t\t\tshould_unload_anims = true;\r\n\t\t\tshould_reload_anims = true;\r\n\t\t}\r\n\r\n\t\tmp_cutsceneStruct->AddInteger( CRCD(0xcdf2b13e,\"unload_anims\"), should_unload_anims );\r\n\t\tmp_cutsceneStruct->AddInteger( CRCD(0x9a4bdff5,\"reload_anims\"), should_reload_anims );\r\n\r\n\t\t// by default, unload the goals\r\n\t\tmp_cutsceneStruct->AddInteger( CRCD(0xed064302,\"unload_goals\"), 1 );\r\n\t\tmp_cutsceneStruct->AddInteger( CRCD(0xbabf2dc9,\"reload_goals\"), 1 );\r\n\r\n\t\t// \"unload_anims\" and \"reload_anims\" can be overridden from playcutscene line\r\n\t\tmp_cutsceneStruct->AppendStructure( pTempParams );\r\n\r\n\t\t// hide all moving objects here...\r\n\t\t// (do it before normal hide/unhide scripts happen)\r\n\t\thide_moving_objects();\r\n\r\n\t\tScript::RunScript( CRCD(0xe1ce826a,\"PreCutscene\"), mp_cutsceneStruct );\r\n\r\n\t\t// run the script after the cutscene, so\r\n\t\t// that we can unpause the objects and such...\r\n\t\tchar startScriptName[256];\r\n\t\tstrcpy( startScriptName, pCutName );\r\n\t\tstrcat( startScriptName, \"_begin\" );\r\n\t\tchar endScriptName[256];\r\n\t\tstrcpy( endScriptName, pCutName );\r\n\t\tstrcat( endScriptName, \"_end\" );\r\n\t\tm_startScriptName = Crc::GenerateCRCFromString( startScriptName );\r\n\t\tm_endScriptName = Crc::GenerateCRCFromString( endScriptName );\r\n\r\n\t\t// GJ:  \"use_pip\" flag would be handy here!\r\n\r\n\t\tmp_cutsceneAsset = (CCutsceneData*)pAssMan->LoadAsset( pCutsceneFileName, async, false, false, 0 );\r\n\r\n\t\t// couldn't get cutscene\r\n\t\tDbg_MsgAssert( mp_cutsceneAsset, ( \"Couldn't create cutscene data %s\", pCutsceneFileName ) );\r\n\r\n\t\tm_cutsceneAssetName = Script::GenerateCRC( pCutsceneFileName );\r\n    }\r\n\r\n\tsuccess = true;\r\n\r\ninit_failed:\r\n\tdelete pTempParams;\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneDetails::Cleanup()\r\n{\r\n#ifdef __PLAT_NGC__\r\n\tg_in_cutscene = false;\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\t// kill the cutscene panel, if it exists\r\n\tScript::RunScript( CRCD(0xe7bc7efd,\"kill_cutscene_panel\") );\r\n\r\n\t// need to delete the cutscene asset,\r\n\t// so that there will be enough room for all\r\n\t// the anims reloaded in \"PostCutscene\"\r\n\tif ( mp_cutsceneAsset )\r\n\t{\r\n\t\tAss::CAssMan* pAssMan = Ass::CAssMan::Instance();\r\n\t\tAss::CAsset* pAsset = pAssMan->GetAssetNode( m_cutsceneAssetName, true );\r\n\t\tpAssMan->UnloadAsset( pAsset );\r\n\t\tmp_cutsceneAsset = NULL;\r\n\t}\r\n\r\n\tif ( m_endScriptName )\r\n\t{\r\n\t\tScript::RunScript( m_endScriptName );\r\n\t}\r\n\t\t\r\n\t// kill special effects, in case the artist forgot to do it \r\n\t// in the individual cutscene end scripts... (need to do this\r\n\t// before the cutscene heap is destroyed)\r\n\tScript::RunScript( CRCD(0xf49a8c9c,\"kill_cutscene_camera_hud\") );\r\n\r\n\t// Clear any currently running FakeLights commands, in case the player\r\n\t// aborted while they were still taking effect during the cutscene\r\n\t// (in which case the fake lights would have gone on the cutscene heap)\r\n\tNx::CLightManager::sClearCurrentFakeLightsCommand();\r\n\r\n\t// destroy the cutscene heap (at this point, any allocations made during \r\n\t// the cutscene should have been freed up)\r\n\tMem::Manager::sHandle().DeleteCutsceneHeap();\r\n\r\n\tScript::RunScript( CRCD(0xbca1791c,\"PostCutscene\"), mp_cutsceneStruct );\r\n\r\n\t// unhide moving objects, based on whether they were hidden...\r\n\tunhide_moving_objects();\r\n\r\n\tCMovieDetails::Cleanup();\r\n\r\n\tScript::RunScript( CRCD(0x15674315,\"restore_skater_camera\") );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneDetails::Update()\r\n{\r\n\tif ( !mp_cutsceneAsset )\r\n\t{\r\n\t\tDbg_Message( \"No cutscene asset!\" );\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( mp_cutsceneAsset->LoadFinished() )\r\n\t{\r\n\t\tif ( !m_startScriptAlreadyRun && m_startScriptName )\r\n\t\t{\r\n\t\t\tScript::RunScript( m_startScriptName );\r\n\t\t\tm_startScriptAlreadyRun = true;\r\n\t\t}\r\n\r\n\t\tmp_cutsceneAsset->Update( mp_camera, mp_cutsceneStruct );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCutsceneDetails::HasMovieStarted()\r\n{\r\n\tif ( !mp_cutsceneAsset )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"No cutscene asset!\" ) );\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn mp_cutsceneAsset->HasMovieStarted();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCutsceneDetails::ResetCustomKeys()\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCutsceneDetails::IsComplete()\r\n{\r\n\tif ( m_aborted )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif ( m_holdOnLastFrame )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif ( mp_cutsceneAsset )\r\n\t{\r\n\t\treturn mp_cutsceneAsset->LoadFinished() && mp_cutsceneAsset->IsAnimComplete();\r\n\t}\r\n\t\t\r\n\treturn false;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCutsceneDetails::IsHeld()\r\n{\r\n\treturn false;\r\n}\r\n\t\t\t\t\t\t\t\t\t  \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CCutsceneDetails::OverridesCamera()\r\n{\r\n\tif ( mp_cutsceneAsset )\r\n\t{\r\n\t\treturn mp_cutsceneAsset->OverridesCamera();\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneDetails::hide_moving_objects()\r\n{\r\n\t// hides the goal peds\r\n\tScript::RunScript( CRCD(0x722d9ca7,\"cutscene_hide_objects\") );\r\n\r\n\t// first count the number of objects, so we can allocate the proper number of hide flags\r\n\tint numObjects = 0;\r\n\tObj::CBaseComponent *p_component = Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType( CRCD(0x286a8d26,\"model\") );\r\n\twhile( p_component )\r\n\t{\r\n\t\tObj::CModelComponent* pModelComponent = ((Obj::CModelComponent*)p_component);\r\n\t\tNx::CModel* pModel = pModelComponent->GetModel();\r\n\t\tif ( p_component->GetObject()->GetID() == 0 )\r\n\t\t{\r\n\t\t\t// skip the skater...\r\n\t\t}\r\n\t\telse if ( !pModel->IsHidden() )\r\n\t\t{\r\n\t\t\tnumObjects++;\r\n\t\t}\r\n\t\tp_component = p_component->GetNextSameType();\t\t\r\n\t}\r\n\tDbg_MsgAssert( mp_hiddenObjects\t== NULL, ( \"hidden objects array already exists?\" ) );\r\n\r\n\tif ( !numObjects)\r\n\t\treturn;\r\n\r\n\r\n\tmp_hiddenObjects = new uint32[numObjects];\r\n\tm_numHiddenObjects = 0;\r\n\t\r\n\t// now actually go through and hide them\r\n\tp_component = Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType( CRCD(0x286a8d26,\"model\") );\r\n\twhile( p_component )\r\n\t{\r\n\t\tObj::CModelComponent* pModelComponent = ((Obj::CModelComponent*)p_component);\r\n\t\tNx::CModel* pModel = pModelComponent->GetModel();\r\n\t\tif ( p_component->GetObject()->GetID() == 0 )\r\n\t\t{\r\n\t\t\t// skip the skater...\r\n\t\t}\r\n\t\telse if ( !pModel->IsHidden() )\r\n\t\t{\r\n\t\t\t// if this fires off, that would be really weird because we just counted the exact\r\n\t\t\t// number we need a few moments ago...\r\n\t\t\tDbg_MsgAssert( m_numHiddenObjects < numObjects, ( \"Too many objects in scene to hide?\" ) );\r\n\r\n//\t\t\tprintf( \"Found model to hide (%s)\\n\", Script::FindChecksumName(p_component->GetObject()->GetID()) );\r\n\t\t\tmp_hiddenObjects[m_numHiddenObjects] = p_component->GetObject()->GetID();\r\n\t\t\tpModel->Hide( true );\r\n\t\t\tm_numHiddenObjects++;\r\n\t\t}\r\n\r\n\t\tp_component = p_component->GetNextSameType();\t\t\r\n\t}\r\n\r\n\tprintf( \"Hid %d objects\\n\", m_numHiddenObjects );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CCutsceneDetails::unhide_moving_objects()\r\n{\r\n\tif ( mp_hiddenObjects )\r\n\t{\r\n\t\tfor ( int i = 0; i < m_numHiddenObjects; i++ )\r\n\t\t{\r\n\t\t\tObj::CCompositeObject* pObject = (Obj::CCompositeObject*)Obj::ResolveToObject( mp_hiddenObjects[i] );\r\n\t\t\tif ( pObject )\r\n\t\t\t{\r\n\t\t\t\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( pObject );\r\n\t\t\t\tNx::CModel* pModel = pModelComponent->GetModel();\r\n\t\t\t\tpModel->Hide( false );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// it's possible that they won't exist anymore\r\n\t\t\t\t// because of the call to uninitialize all goals...\r\n\t\t\t\t//Dbg_MsgAssert( pObject, ( \"Couldn't find object %s to unhide?\", Script::FindChecksumName(mp_hiddenObjects[i]) ) );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tdelete[] mp_hiddenObjects;\r\n\t\tmp_hiddenObjects = NULL;\r\n\t}\r\n\r\n\tm_numHiddenObjects = 0;\r\n\t\r\n\t// unhides the goal peds\r\n\tScript::RunScript( CRCD(0x94d0d528,\"cutscene_unhide_objects\") );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n"
  },
  {
    "path": "Code/Sk/Objects/cutscenedetails.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       cutscenedetails.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  01/13/2003\r\n//****************************************************************************\r\n\r\n#ifndef __OBJECTS_CUTSCENEDETAILS_H\r\n#define __OBJECTS_CUTSCENEDETAILS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <sk/objects/moviedetails.h>\t\t\t\t\t\t\t   \r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace File\r\n{\r\n\tclass CFileLibrary;\r\n}\r\n\t\t \r\nnamespace Nx\r\n{\r\n\tclass CQuickAnim;\r\n}\r\n\r\nnamespace Mth\r\n{\r\n\tclass Matrix;\r\n\tclass Quat;\r\n\tclass Vector;\r\n}\r\n\t\t\t\t   \r\nnamespace Script\r\n{\r\n\tclass CScript;\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\r\n\tclass CCutsceneData;\r\n\tclass CCompositeObject;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstruct SCutsceneAnimInfo\r\n{\r\n\tuint32\t\t\t\t\t\tm_animName;\r\n\tNx::CQuickAnim*\t\t\t\tmp_bonedQuickAnim;\r\n};\r\n\r\nstruct SCutsceneObjectInfo\r\n{\r\n\tuint32\t\t\t\t\t\tm_objectName;\r\n\tuint32\t\t\t\t\t\tm_flags;\r\n\tuint32\t\t\t\t\t\tm_skeletonName;\r\n\tbool\t\t\t\t\t\tm_doPlayerSubstitution;\r\n\tSCutsceneAnimInfo*\t\t\tmp_animInfo;\r\n\tObj::CCompositeObject*\t\tmp_object;\r\n\tObj::CCompositeObject*\t\tmp_parentObject;\r\n\tint\t\t\t\t\t\t\tm_obaIndex;\t\t\t// -1 if not valid\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CCutsceneData\t: public Spt::Class\r\n{\r\nprotected:\r\n\tenum\r\n\t{\r\n\t\tvMAX_CUTSCENE_ANIMS = 64,\r\n\t\tvMAX_CUTSCENE_OBJECTS = 64,\r\n\t\tvMAX_CUTSCENE_ASSETS = 64\r\n\t};\r\n\r\npublic:\r\n\tCCutsceneData();\r\n\tvirtual ~CCutsceneData();\r\n\r\npublic:\r\n    bool    \t\t\t   \t\tLoad(const char* p_fileName, bool assertOnFail, bool async);\r\n    bool    \t\t\t   \t\tPostLoad(bool assertOnFail);\r\n\tbool\t\t\t\t\t\tLoadFinished();\r\n\tvoid\t\t\t\t\t\tUpdate( Gfx::Camera* pCamera, Script::CStruct* pStruct );\r\n\tbool\t\t\t\t\t\tIsAnimComplete();\r\n\tbool\t\t\t\t\t\tOverridesCamera();\r\n\tbool\t\t\t\t\t\tHasMovieStarted()\r\n\t{\r\n\t\treturn m_videoStarted;\r\n\t}\r\n\r\nprotected:\r\n\tvoid\t\t\t\t\t\tget_current_frame( Mth::Quat* pQuat, Mth::Vector* pTrans );\r\n\tvoid\t\t\t\t\t\tupdate_camera( Gfx::Camera* pCamera );\r\n\tvoid\t\t\t\t\t\tupdate_moving_objects();\r\n\tvoid\t\t\t\t\t\tupdate_extra_cutscene_objects();\r\n\tvoid\t\t\t\t\t\tupdate_boned_anims();\t\r\n\tvoid \t\t\t\t\t\tadd_boned_anim( uint32 objectName, uint32* pData, int fileSize );\r\n\tvoid\t\t\t\t\t\tadd_anim( uint32 animName, uint32* pData, int fileSize );\r\n\tvoid \t\t\t\t\t\tadd_object( Script::CStruct* pParams );\r\n\tbool\t\t\t\t\t\tcreate_objects( uint32* pData );\r\n\tSCutsceneObjectInfo*\t\tget_object_info( uint32 objectName );\r\n\tSCutsceneAnimInfo*\t\t\tget_anim_info( uint32 animName );\r\n\tvoid\t\t\t\t\t\tupdate_video_playback( Gfx::Camera* pCamera, Script::CStruct* pStruct );\r\n\r\nprotected:\r\n\tvoid\t\t\t\t\t\tinit_objects();\r\n\tvoid\t\t\t\t\t\tload_models();\r\n\r\nprotected:\r\n\t// need this pointer only during async loads\r\n\tFile::CFileLibrary* \t\tmp_fileLibrary;\r\n\tbool\t\t\t\t\t\tm_dataLoaded;\r\n\t\r\n\tNx::CQuickAnim*\t\t\t\tmp_cameraQuickAnim;\r\n\tNx::CQuickAnim*\t\t\t\tmp_objectQuickAnim;\r\n\t\r\n\tMth::Vector\t\t\t\t\tm_original_player_bounding_sphere;\r\n\tbool\t\t\t\t\t\tm_original_hidden;\r\n\tbool\t\t\t\t\t\tm_original_scale_enabled;\r\n\tMth::Vector\t\t\t\t\tm_original_pos;\r\n\r\n\t// this is used so that if there are multiple create-a-skaters,\r\n\t// they don't all try to overwrite the same m_original_*\r\n\t// fields...\r\n\tbool\t\t\t\t\t\tm_original_params_set;\r\n\r\n\tSCutsceneObjectInfo\t\t\tm_objects[vMAX_CUTSCENE_OBJECTS];\r\n\tint\t\t\t\t\t\t\tm_numObjects;\r\n\r\n\tSCutsceneAnimInfo\t\t\tm_bonedAnims[vMAX_CUTSCENE_ANIMS];\r\n\tint\t\t\t\t\t\t\tm_numBonedAnims;\r\n\r\n\tuint32\t\t\t\t\t\tm_assetName[vMAX_CUTSCENE_ASSETS];\r\n\tint\t\t\t\t\t\t\tm_numAssets;\r\n\t\r\n\tbool\t\t\t\t\t\tm_audioStarted;\r\n\tbool\t\t\t\t\t\tm_videoStarted;\r\n\tbool\t\t\t\t\t\tm_videoAborted;\r\n\r\n\tfloat\t\t\t\t\t\tm_oldTime;\r\n\tfloat\t\t\t\t\t\tm_currentTime;\r\n\tuint64\t\t\t\t\t\tm_initialVBlanks;\r\n};\r\n\r\nclass CCutsceneDetails : public CMovieDetails\r\n{\r\npublic:\r\n\tCCutsceneDetails();\r\n\tvirtual\t\t\t~CCutsceneDetails();\r\n\r\npublic:\r\n\tvirtual bool \t\t\t\tInitFromStructure(Script::CStruct *pParams);\r\n\tvirtual void \t\t\t\tUpdate();\r\n\tvirtual bool \t\t\t\tResetCustomKeys();\r\n\tvirtual bool \t\t\t\tIsComplete();\r\n\tvirtual bool\t\t\t\tIsHeld();\r\n\tvirtual bool\t\t\t\tOverridesCamera();\r\n\tvirtual void\t\t\t\tCleanup();\r\n\tvirtual bool\t\t\t\tHasMovieStarted();\r\n\t\r\nprotected:\r\n\tvoid\t\t\t\t\t\thide_moving_objects();\r\n\tvoid\t\t\t\t\t\tunhide_moving_objects();\r\n\r\nprotected:\r\n\tCCutsceneData*\t\t\t\tmp_cutsceneAsset;\r\n\tuint32\t\t\t\t\t\tm_cutsceneAssetName;\r\n\tuint32\t\t\t\t\t\tm_startScriptName;\r\n\tbool\t\t\t\t\t\tm_startScriptAlreadyRun;\r\n\tuint32\t\t\t\t\t\tm_endScriptName;\r\n\tScript::CStruct*\t\t\tmp_cutsceneStruct;\r\n\r\n\tfloat\t\t\t\t\t\tm_oldAmbientLightModulationFactor;\r\n\tfloat\t\t\t\t\t\tm_oldDiffuseLightModulationFactor[2];\r\n\t\r\n\tuint32*\t\t\t\t\t\tmp_hiddenObjects;\r\n\tint\t\t\t\t\t\t\tm_numHiddenObjects;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_CUTSCENEDETAILS_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/emitter.cpp",
    "content": "///////////////////////////////////////////////////////\r\n// Emitter.cpp\r\n\r\n\t\t  \r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/math.h>\r\n#include <gfx/camera.h>\r\n#include <gfx/nx.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <sk/objects/Emitter.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/objects/skater.h>\t\t   // used to get position of the skater's camera\r\n\r\n//#define\tDEBUG_EMITTER\r\n\r\nnamespace Obj\r\n{\r\n\r\nLst::HashTable<CEmitterObject> *\tCEmitterManager::sp_emitter_lookup = NULL;\r\n\r\nvoid CEmitterManager::sInit()\r\n{\r\n\tif (sp_emitter_lookup)\r\n\t{\r\n\t\tsCleanup();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsp_emitter_lookup = new Lst::HashTable<CEmitterObject>(4);\t\r\n\t}\r\n}\r\n\r\nvoid CEmitterManager::sCleanup()\r\n{\r\n\tif (sp_emitter_lookup)\r\n\t{\r\n\t\tsp_emitter_lookup->IterateStart();\r\n\t\tCEmitterObject *pNode = sp_emitter_lookup->IterateNext();\r\n\t\twhile (pNode)\r\n\t\t{\r\n\t\t\tCEmitterObject *pNext = sp_emitter_lookup->IterateNext();\r\n\t\t\tuint32 checksum = pNode->m_name;   \r\n\t\t\tdelete pNode;\r\n\t\t\tsp_emitter_lookup->FlushItem(checksum);\t\t\t\r\n\t\t\tpNode = pNext;\r\n\t   \t}\r\n\r\n//\t\tdelete sp_emitter_lookup;\r\n//\t\tsp_emitter_lookup = NULL;\r\n\t}\r\n}\r\n\r\nvoid CEmitterManager::sAddEmitter(int node,bool active)\r\n{\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n//\tprintf (\"It's a Emitter (%d)\\n\",node);\r\n\t\r\n\t// create a new EmitterObject\r\n\tCEmitterObject *pEmitterObject = new CEmitterObject();\r\n\r\n\tpEmitterObject->m_node = node;\r\n\r\n\tpEmitterObject->m_active = active;  // created at start or not?\r\n\t\r\n\tpEmitterObject->mp_sector = NULL;\r\n\tpEmitterObject->m_shape_type = CEmitterObject::vSHAPE_SPHERE;  \r\n\r\n\t// Get pointer to the Emitter data\t\r\n\tScript::CScriptStructure *pNode = SkateScript::GetNode(node);\r\n\t\r\n\t// Get name\r\n\tif (pNode->GetChecksum(\"name\",&pEmitterObject->m_name))\r\n\t{\r\n#ifdef\tDEBUG_EMITTER\r\n\t\tprintf (\"Emitter: Got Name %s\\n\",Script::FindChecksumName(pEmitterObject->m_name));\r\n#endif\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"No name in proxim node %d\\n\",node));\r\n\t}\r\n\r\n\t// Add to hash table\r\n\tsp_emitter_lookup->PutItem(pEmitterObject->m_name, pEmitterObject);\r\n\r\n\t// Get shape type\r\n\tuint32 shape_checksum;\r\n\tif (pNode->GetChecksum(\"type\", &shape_checksum))\r\n\t{\r\n\t\tpEmitterObject->m_shape_type = CEmitterObject::sGetShapeFromChecksum(shape_checksum);\r\n\t}\r\n\r\n\t// Try to find geometry\r\n\tpEmitterObject->InitGeometry(Nx::CEngine::sGetMainScene()->GetSector(pEmitterObject->m_name));\r\n\r\n\tSkateScript::GetPosition(pNode,&pEmitterObject->m_pos);\r\n#ifdef\tDEBUG_EMITTER\t\t\t\t\r\n\t\tDbg_Message(\"Emitter: Pos = (%f, %f, %f)\", pEmitterObject->m_pos[X], pEmitterObject->m_pos[Y], pEmitterObject->m_pos[Z]);\r\n#endif\t\r\n\r\n\tpNode->GetFloat (0xc48391a5 /*radius*/, &pEmitterObject->m_radius);  \r\n\tDbg_MsgAssert(pEmitterObject->mp_sector || pEmitterObject->m_radius > 0.0f,( \"Radius %f too small in proxim node %d\\n\",pEmitterObject->m_radius,node));\t\r\n#ifdef\tDEBUG_EMITTER\r\n\tprintf (\"Emitter:  Radius = %f\\n\",pEmitterObject->m_radius);\r\n#endif\t\r\n\tpEmitterObject->m_radius_squared = pEmitterObject->m_radius * pEmitterObject->m_radius;\t\r\n\r\n\tif (pNode->GetChecksum(0x2ca8a299,&pEmitterObject->m_script))\t\t// Checksum of TriggerScript\r\n\t{\r\n#ifdef\tDEBUG_EMITTER\r\n\t\tprintf (\"Emitter: Got Script %s\\n\",Script::FindChecksumName(pEmitterObject->m_script));\r\n#endif\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//Dbg_MsgAssert(0,(\"No triggerscript in proxim node %d\\n\",node));\r\n\t}\r\n\r\n\t\r\n\t//pEmitterObject->m_outside_flags = 0;\t\t\t// say all inside for now....\r\n}\r\n\r\nvoid CEmitterManager::sAddedAll()\r\n{\r\n\t\r\n//\tprintf(\"Added all Emitters\\n\");\t\t \r\n\t\t \r\n\tDbg_Assert(sp_emitter_lookup);\r\n\r\n\tsp_emitter_lookup->IterateStart();\r\n\tCEmitterObject *pEmitterObject = sp_emitter_lookup->IterateNext();\r\n\r\n\twhile (pEmitterObject)\r\n\t{\r\n\t\t// do any final per-node processing here\r\n\t\tpEmitterObject = sp_emitter_lookup->IterateNext();\r\n\t}\t\t\t\t \r\n\t\t\t\t \t\r\n}\t\t\t   \r\n\r\nCEmitterObject * CEmitterManager::sGetEmitter(uint32 checksum)\r\n{\r\n\tDbg_Assert(sp_emitter_lookup);\r\n\r\n\tCEmitterObject *pEmitter = sp_emitter_lookup->GetItem(checksum);\r\n\r\n\tif (!pEmitter)\r\n\t{\r\n\t\tDbg_Message(\"Warning: Can't find emitter %s\", Script::FindChecksumName(checksum));\r\n\t}\r\n\r\n\treturn pEmitter;\r\n}\r\n\r\nvoid CEmitterManager::sSetEmitterActive( int node, int active )\r\n{\r\n\tDbg_Assert(sp_emitter_lookup);\r\n\r\n\tsp_emitter_lookup->IterateStart();\r\n\tCEmitterObject *pEmitterObject = sp_emitter_lookup->IterateNext();\r\n\twhile (pEmitterObject)\r\n\t{\r\n\t\tif (pEmitterObject->m_node == node)\r\n\t\t{\r\n\t\t\tpEmitterObject->m_active = active;\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tpEmitterObject = sp_emitter_lookup->IterateNext();\r\n\t}\t\t\t\t \r\n}\r\n\r\n#if 0\r\n// Update all the proximity nodes\t\t\t\t\r\n// for a certain skater\r\n// checking for proximity either with the skater or the camera\t\t\t\t\t\r\nvoid CEmitterManager::sUpdateEmitters(CSkater *pSkater, Gfx::Camera* camera)\r\n{\r\n\tDbg_Assert(sp_emitter_lookup);\r\n\r\n\tsp_emitter_lookup->IterateStart();\r\n\tCEmitterObject *pEmitterObject = sp_emitter_lookup->IterateNext();\r\n\r\n    Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tif( skate_mod->mpProximManager == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tint\tskater_num = 0;\t\t\t\t\t\t// 0 for now, should be viewport index\r\n\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tif (!gamenet_man->InNetGame())\r\n\t{\r\n\t\tif (skate_mod->GetSkater(1) == pSkater)\r\n\t\t{\r\n\t\t\tskater_num = 1;\r\n\t\t}\r\n\t}\r\n\r\n\tint\tskater_mask = 1 << skater_num;\t\t// the bitmask for this skater\r\n\r\n//\tMth::Vector\tskater_pos = pSkater->m_pos;\t\r\n//\tMth::Vector\tskater_old_pos = pSkater->m_old_pos;\t\r\n\r\n\t// Aieeeeee!!!\r\n\t// to get the camera's position, we have to dig down to a low level\r\n\t// the CSkater::GetSkaterCam returns a *CSkaterCam\r\n\t// CSkaterCam::GetCamera returns a \treference to Gfx::Camera\r\n\t// Gfx::Camera::GetCamera returns a *NsCamera (pointer)\r\n\t// so we pass that to RwCameraGetFrame, so we can get the position of the camera...\r\n\t// Matt added m_pos to CSkaterCam and removed the code below to find the camera:\r\n\t\r\n//\tGfx::Camera* \tp_camera = pSkater->GetSkaterCam()->mpCamera ;\r\n\tMth::Vector\tcamera_pos;\r\n\t// Local clients can get the camera's position directly from the skater cam\r\n\t// but observers need to get it from the camera that was passed in since\r\n\t// the skater they're following doesn't have a skatercam\r\n\r\n// Mick - camera passed in is the active camera\r\n//\tif( pSkater->IsLocalClient())\r\n//\t{\r\n//\t\tcamera_pos = pSkater->GetSkaterCam()->GetPos();\r\n//\t}\r\n//\telse\r\n//\t{\r\n\t\tcamera_pos = camera->GetPos();\r\n//\t}\r\n\t\r\n\twhile (pEmitterObject)\r\n\t{\r\n\t\r\n\t//Mth::Vector to_skater = skater_pos - pEmitterObject->m_pos;\r\n\t// Bitfield per viewport....\r\n\t\t\t\r\n//\t\tprintf (\"Proxim: Update,  Script %s\\n\",Script::FindChecksumName(pEmitterObject->m_script));\t\r\n\r\n\t\t// find the squared dist from this node:\r\n\t\t\r\n\t\t// This code would crash with observers since the skater they were following had no cam\r\n\t\t//Mth::Vector\t\tnode_to_camera = pSkater->GetSkaterCam( )->m_pos - pEmitterObject->m_pos;\r\n        \r\n\t\tbool now_inside = pEmitterObject->CheckInside(camera_pos);\r\n\r\n\t\tif ( skater_mask & pEmitterObject->m_outside_flags)\r\n\t\t{\r\n\t\t\t// skater is currently outside, check if moved to inside\r\n\t\t\tif (now_inside)\r\n\t\t\t{\r\n\t\t\t\r\n\t\t\t\tpEmitterObject->m_outside_flags &= ~skater_mask;\r\n\t\t\t\tpSkater->m_inside = true;\r\n\t\t\t\t\r\n#ifdef\tDEBUG_EMITTER\t\t\t\t\r\n\t\t\t\tprintf (\"+++++ NOW INSIDE, running script %s \\n\",Script::FindChecksumName(pEmitterObject->m_script));\r\n#endif\t\t\t\t\r\n\t\t\t\tpSkater->SpawnAndRunScript(pEmitterObject->m_script,pEmitterObject->m_node );\r\n\t\t\t}\t\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// skater is currently inside, check if moved outside\r\n\t\t\tif (!now_inside)\r\n\t\t\t{\r\n\t\t\t\tpEmitterObject->m_outside_flags |= skater_mask;\t\t\t\t\r\n\t\t\t\tpSkater->m_inside = false;\r\n\t#ifdef\tDEBUG_EMITTER\t\t\t\t\r\n\t\t\t\tprintf (\"----- NOW OUTSIDE, running script %s \\n\",Script::FindChecksumName(pEmitterObject->m_script));\r\n\t#endif\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\tpSkater->SpawnAndRunScript(pEmitterObject->m_script,pEmitterObject->m_node );\r\n\t\t\t}\t\t\t\r\n\t\t}\t\t\r\n\t\tpEmitterObject = sp_emitter_lookup->IterateNext();\r\n\t}\t\t\t\t \r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCEmitterObject::EShape CEmitterObject::sGetShapeFromChecksum(uint32 checksum)\r\n{\r\n\tswitch (checksum)\r\n\t{\r\n\tcase 0xaa069978: // Sphere\r\n\t\treturn vSHAPE_SPHERE;\r\n\r\n\tcase 0xe460abde: // BoundingBox\r\n\t\treturn vSHAPE_BBOX;\r\n\r\n\tcase 0x3f1e5a7: // NonAxisAlignedBoundingBox\r\n\t\treturn vSHAPE_NON_AA_BBOX;\r\n\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0, (\"Unknown shape checksum %x\\n\", checksum));\r\n\t\treturn vSHAPE_SPHERE;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCEmitterObject::InitGeometry(Nx::CSector *p_sector)\r\n{\r\n\tmp_sector = p_sector;\r\n\r\n\tif (!mp_sector)\r\n\t{\r\n\t\t// No Geometry\r\n\t\tDbg_MsgAssert(m_shape_type == CEmitterObject::vSHAPE_SPHERE, (\"EmitterObject with shape %d has no geometry.\", m_shape_type));\r\n\t\treturn;\r\n\t}\r\n\r\n#ifdef\tDEBUG_EMITTER\t\t\t\t\r\n\tDbg_Message(\"Found Geometry for EmitterObject %s at address %x\", Script::FindChecksumName(m_name), mp_sector);\r\n#endif\r\n\r\n\tswitch (m_shape_type)\r\n\t{\r\n\tcase CEmitterObject::vSHAPE_SPHERE:\r\n\t\tDbg_MsgAssert(0, (\"EmitterObject with sphere shape has geometry.\"));\r\n\t\tbreak;\r\n\r\n\tcase CEmitterObject::vSHAPE_BBOX:\r\n\t\tm_bbox = mp_sector->GetBoundingBox();\r\n#ifdef\tDEBUG_EMITTER\t\t\t\t\r\n\t\tDbg_Message(\"Bounding box of geometry (%f, %f, %f) - (%f, %f, %f)\",\r\n\t\t\t\t\tm_bbox.GetMin()[X], m_bbox.GetMin()[Y], m_bbox.GetMin()[Z],\r\n\t\t\t\t\tm_bbox.GetMax()[X], m_bbox.GetMax()[Y], m_bbox.GetMax()[Z]);\r\n#endif\t\r\n\t\tbreak;\r\n\r\n\tcase CEmitterObject::vSHAPE_NON_AA_BBOX:\r\n\t\tDbg_MsgAssert(0, (\"EmitterObject with non axis aligned bounding box shape not supported yet.\"));\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCEmitterObject::CheckInside(const Mth::Vector &object_pos) const\r\n{\r\n\tMth::Vector\t\tnode_to_object = object_pos - m_pos;\r\n\tfloat\t\t\tdist_squared = node_to_object.LengthSqr();\t   \r\n\r\n\tbool inside = false;\r\n\r\n\tswitch (m_shape_type)\r\n\t{\r\n\tcase vSHAPE_SPHERE:\r\n\t\tinside = (dist_squared <= m_radius_squared);\r\n\t\tbreak;\r\n\r\n\tcase vSHAPE_BBOX:\r\n\t\tinside = m_bbox.Within(object_pos);\r\n#ifdef\tDEBUG_EMITTER\r\n\t\tm_bbox.DebugRender(0xff0000ff);\r\n#endif //\tDEBUG_EMITTER\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0, (\"Can't handle EmitterObject type %d\", m_shape_type));\r\n\t\tbreak;\r\n\t}\r\n\r\n\treturn inside;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector \t\tCEmitterObject::GetClosestPoint(const Mth::Vector &object_pos) const\r\n{\r\n\t// Return original position if within the object\r\n\tif (CheckInside(object_pos))\r\n\t{\r\n\t\treturn object_pos;\r\n\t}\r\n\r\n\tMth::Vector intersect_point;\r\n\r\n\tswitch (m_shape_type)\r\n\t{\r\n\tcase vSHAPE_SPHERE:\r\n\t\t{\r\n\t\t\t// Same for either within or outside sphere\r\n\t\t\tMth::Vector direction = object_pos - m_pos;\r\n\t\t\tdirection.Normalize();\r\n\t\t\tdirection *= m_radius;\r\n\r\n\t\t\tintersect_point = m_pos + direction;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\tcase vSHAPE_BBOX:\r\n\t\tm_bbox.GetClosestIntersectPoint(object_pos, intersect_point);\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0, (\"Can't handle EmitterObject type %d\", m_shape_type));\r\n\t\tbreak;\r\n\t}\r\n\r\n#ifdef\tDEBUG_EMITTER\r\n\tGfx::AddDebugStar(intersect_point);\r\n#endif //\tDEBUG_EMITTER\r\n\r\n\treturn intersect_point;\r\n}\r\n\r\n/*\r\n{\r\n\t// Node 572 (Mick Test)\r\n\tPosition = (-4060.666992,131.999329,-4604.379395)\r\n\tAngles = (0.000000,-3.141593,0.000000)\r\n\tName = TRG_Micks_test\r\n\tClass = ProximNode\r\n\tType = skater\r\n    radius = 1200\r\n\tTriggerScript = xxx_test\r\n}\r\n*/\r\n\r\n\r\n}\r\n\t\t\t   \r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/emitter.h",
    "content": "//////////////////////////////////////////\r\n// Emitter.h\r\n\r\n#ifndef __OBJECTS_Emitter_H\r\n#define __OBJECTS_Emitter_H\r\n\r\n#include <core\\hashtable.h>\r\n#include <core\\math\\geometry.h>\r\n\r\nnamespace Nx\r\n{\r\n\tclass\tCSector;\r\n}\r\n\r\nnamespace Gfx\r\n{\r\n\tclass\tCamera;\r\n}\r\n\r\nnamespace Script\r\n{\r\n\tclass\tCScript;\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\r\n\tclass\tCSkater;\r\n\tclass CEmitterManager;\r\n\r\nclass CEmitterObject : public Spt::Class\r\n{\r\npublic:\r\n\tenum EShape\r\n\t{\r\n\t\tvSHAPE_BBOX = 0,\t\t// Axis-aligned bounding box\r\n\t\tvSHAPE_NON_AA_BBOX,\t\t// Non-axis-aligned bounding box\r\n\t\tvSHAPE_SPHERE,\r\n\t};\r\n\r\n\t///////////\r\n\t// Functions\r\n\tvoid\t\t\t\tInitGeometry(Nx::CSector *p_sector);\r\n\tbool\t\t\t\tCheckInside(const Mth::Vector &object_pos) const;\r\n\tMth::Vector \t\tGetClosestPoint(const Mth::Vector &object_pos) const;\r\n\r\n\t// Checksum conversion functions\r\n\tstatic EShape\t\tsGetShapeFromChecksum(uint32 checksum);\r\n\r\nprotected:\r\n\t///////////\r\n\t// Variables\r\n\tint\t\t\tm_node;\t\t\t\t// Number of the node in the trigger array\r\n\tint \t\tm_link;\t\t\t\t// link number\r\n\tuint32\t\tm_name;\t\t\t\t// checksum of name of the node in the trigger array\r\n\tMth::Vector m_pos;\t\t\t\t// position of the node\r\n\tMth::Vector m_angles;\t\t\t// angles of the node\r\n\tbool \t\tm_active;\t\t\t// Emitter segment starting at this node: active or not?\r\n\r\n\t//int\t\t\tm_outside_flags;\t// bitmask of flags, 0 = inside the radius, 1 = outside\r\n\r\n\tEShape \t\tm_shape_type;\r\n\r\n\t// Sphere data\r\n\tfloat\t\tm_radius;\r\n\tfloat\t\tm_radius_squared;\r\n\r\n\t// Geometry Data\r\n\tNx::CSector *mp_sector;\r\n\r\n\t// BBox data\r\n\tMth::CBBox\tm_bbox;\r\n\t\r\n\tfloat\t\tm_last_distance_squared;\r\n\t\r\n\tuint32 \t\tm_script;\r\n\r\n\t//CEmitterObject *m_pNext;\r\n\r\n\r\n\t// friends\r\n\tfriend CEmitterManager;\r\n};\r\n\r\n \r\n\r\nclass CEmitterManager\r\n{\r\npublic:\r\n\tstatic void\t\t\t\tsInit();\r\n\tstatic void\t\t\t\tsCleanup();\r\n\tstatic void\t\t\t\tsAddEmitter(int node, bool active);\r\n\tstatic void\t\t\t\tsAddedAll();\r\n\tstatic CEmitterObject * sGetEmitter(uint32 checksum);\r\n\r\n\t// activate/deactivate Emitter:\r\n\tstatic void\t\t\t\tsSetEmitterActive(int node, int active);\r\n\r\n\t//static void\t\t\t\tsUpdateEmitters(CSkater *pSkater, Gfx::Camera* camera);\r\n\r\nprotected:\r\n\tstatic Lst::HashTable<CEmitterObject> *\tsp_emitter_lookup;\t\r\n};\r\n\r\n\r\n\r\n} \r\n\r\n\t\t\t\r\n#endif\t\t\t// #ifndef __OBJECTS_Emitter_H\r\n\t\t\t\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/followob.cpp",
    "content": "#include <sk/objects/followob.h>\r\n#include <gel/object.h>\r\n#include <sk/objects/movingobject.h>\r\n#include <core/math.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\nCFollowOb::CFollowOb()\r\n{\r\n\tReset();\r\n}\r\n\r\nCFollowOb::~CFollowOb()\r\n{\r\n}\r\n\r\nvoid CFollowOb::Reset()\r\n{\r\n\tm_num_path_points=0;\r\n\tm_most_recent_path_point=0;\r\n\tm_leader_name=0;\r\n\tm_leader_pos.Set();\r\n\tm_distance=0.0f;\r\n\tm_orient_y=false;\r\n}\r\n\r\n// Adds a new position taken from the leader object, if that position is suitably interesting.\r\n// (Ie, it is not too close to the last position)\r\n// FOLLOW_RESOLUTION should be kept as big as possible. That way, the array of positions does\r\n// not need to be so big, and calculating the position will be faster because it won't have to\r\n// step over so many segments.\r\n// If it is too big though the object won't follow the leader's path so accurately and \r\n// will start cutting corners noticeably.\r\n#define FOLLOW_RESOLUTION 40.0f\r\nvoid CFollowOb::GetNewPathPointFromObjectBeingFollowed()\r\n{\r\n\t//CMovingObject *p_obj=CMovingObject::m_hash_table.GetItem(m_leader_name);\r\n\tCMovingObject *p_obj=(CMovingObject*)Obj::ResolveToObject(m_leader_name);\r\n\t\r\n\tif (!p_obj)\r\n\t{\r\n\t\t// Can't find the object, oh well.\r\n\t\treturn;\r\n\t}\t\r\n\r\n\tm_leader_pos=p_obj->m_pos;\r\n\t\r\n\tif (m_num_path_points==0)\r\n\t{\r\n\t\t// Insert the first point.\r\n\t\tm_most_recent_path_point=0;\r\n\t\tmp_path_points[0]=m_leader_pos;\r\n\t\t++m_num_path_points;\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tif (Mth::DistanceSqr(mp_path_points[m_most_recent_path_point],m_leader_pos) > \r\n\t\tFOLLOW_RESOLUTION*FOLLOW_RESOLUTION)\r\n\t{\r\n\t\t// The new point is sufficiently far from the last, so insert it into the cyclic buffer.\r\n\t\t++m_most_recent_path_point;\r\n\t\tif (m_most_recent_path_point>=MAX_FOLLOWOB_PATH_POINTS)\r\n\t\t{\r\n\t\t\tm_most_recent_path_point=0;\r\n\t\t}\r\n\t\t\r\n\t\tmp_path_points[m_most_recent_path_point]=m_leader_pos;\r\n\t\t\r\n\t\t// m_num_path_points increases till it hits MAX_FOLLOWOB_PATH_POINTS then stays there.\r\n\t\tif (m_num_path_points<MAX_FOLLOWOB_PATH_POINTS)\r\n\t\t{\r\n\t\t\t++m_num_path_points;\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\nvoid CFollowOb::CalculatePositionAndOrientation(Mth::Vector *p_pos, Mth::Matrix *p_orientation)\r\n{\r\n\tDbg_MsgAssert(p_pos,(\"NULL p_pos\"));\r\n\tDbg_MsgAssert(p_orientation,(\"NULL p_orientation\"));\r\n\t\r\n\tif (m_num_path_points<1)\r\n\t{\r\n\t\t// Need at least 1 path point before the interpolated position can be calculated.\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tMth::Vector seg_start;\r\n\tMth::Vector seg_end;\r\n\tMth::Vector seg_vec;\r\n\tfloat seg_length;\r\n\r\n\tint num_points_left=m_num_path_points;\r\n\tfloat dist_remaining=m_distance;\r\n\r\n\tseg_start=m_leader_pos;\r\n\tint i=m_most_recent_path_point;\r\n\tseg_end=mp_path_points[i];\t\r\n\tnum_points_left-=1;\r\n\t\r\n\t\r\n\twhile (true)\r\n\t{\r\n\t\tseg_vec=seg_end-seg_start;\r\n\t\tseg_length=seg_vec.Length();\r\n\t\tif (dist_remaining > seg_length)\r\n\t\t{\r\n\t\t\tdist_remaining-=seg_length;\r\n\t\t\tseg_start=seg_end;\r\n\t\t\tif (!num_points_left)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t--i;\r\n\t\t\tif (i < 0)\r\n\t\t\t{\r\n\t\t\t\ti=MAX_FOLLOWOB_PATH_POINTS-1;\r\n\t\t\t}\r\n\t\t\tseg_end=mp_path_points[i];\t\r\n\t\t\t--num_points_left;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (seg_length>0.0f)\r\n\t{\r\n\t\tMth::Vector seg_dir=seg_vec/-seg_length;\r\n\t\t\r\n\t\t*p_pos=seg_start-seg_dir*dist_remaining;\r\n\t\t\r\n\t\tif (m_orient_y)\r\n\t\t{\r\n\t\t\t// Instead of setting z to seg_dir directly, use some of the previous value\r\n\t\t\t// so that the orientation gradually moves towards the new dir rather than snapping.\r\n\t\t\t(*p_orientation)[Z]=10.0f*(*p_orientation)[Z]+seg_dir;\r\n\t\t\t(*p_orientation)[Z].Normalize();\r\n\t\t\t\r\n\t\t\tMth::Vector Up(0.0f,1.0f,0.0f);\r\n\t\t\t(*p_orientation)[X]=Mth::CrossProduct(Up,(*p_orientation)[Z]);\r\n\t\t\t(*p_orientation)[X].Normalize();\r\n\t\t\t(*p_orientation)[Y]=Mth::CrossProduct((*p_orientation)[Z],(*p_orientation)[X]);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t(*p_orientation)[Z]=10.0f*(*p_orientation)[Z]+seg_dir;\r\n\t\t\t(*p_orientation)[Z][Y]=0;\r\n\t\t\t(*p_orientation)[Z].Normalize();\r\n\t\t\t(*p_orientation)[Y].Set(0.0f,1.0f,0.0f);\r\n\t\t\t(*p_orientation)[X]=Mth::CrossProduct((*p_orientation)[Y],(*p_orientation)[Z]);\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/gap.cpp",
    "content": "//////////////////////////////////////////////////////////\r\n// Gap.cpp\r\n//\r\n// Functions for CGap and CGapMan\r\n//\r\n// A \"Gap\" in the game is a pair of events that cause something to happen\r\n// Typically this is jumping across something, such as a gap between two buildings\r\n// but might also be grinding a rail for a certain distance\r\n// or doing something specific, like doing a kickflip over a barrel.\r\n//\r\n// The aim of the gap system is to provide lots of flexibility in setting up\r\n// these pairs of events, and also to allow the user to set gaps quickly and simply\r\n//\r\n// Gaps are set up via script commands\r\n// so they can easily be inserted in trigger scripts\r\n// the simplest might look like:\r\n/*\r\n\r\nscript TRG_Obj010\r\n\tStartGap GapId = JumpOverLog Cancel = [CANCEL_GROUND CANCEL_RAIL CANCEL_WALLRIDE] Expire = 20\r\nendscript\r\n\r\n\r\nscript TRG_Obj012\r\n\tEndGap GapId = JumpOverLog Score = 100 Text = \"You jumped over a log\" Script = ScreenFlash01\r\nendscript\r\n\r\nUsing the \"StartGap\" command, you can set up as many gaps as you like, starting from\r\na particular event.\r\n\r\nFor that gap, you specify what cancels the gap, if nothing is specified, then this should default\r\nto CANCEL_GROUND.  These conditions are checked every frame\r\n\r\nAll gaps are cancelled by a bail (perhaps unless we have CANCEL_BAIL_NOT set????)\r\n\r\nWe can also have a specific \"CancelGap\"  command, for fuller control.\r\n\r\nThe optional \"Expire\" parameter says when the gap expires.  By default gaps do not expire\t\t\t\t   \r\n\r\nThe \"EndGap\" command will check to see if the gap with the specified GapID had been started\r\n(and not cancelled, or expired), and will then Execute the gap, having an optional Score,\r\ntext (defaults to \"Gap\") and an optional script, which is executed.\r\n\r\nIf there is no score, then it will not count as a trick, and you just get the script executing.\r\n\r\n\r\n\r\n\r\n\r\n*/\r\n\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/math.h>\r\n#include <sk/objects/gap.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <gfx/debuggfx.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <gel/modman.h>\r\n#include <core/string/stringutils.h>\r\n\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/modules/skate/goalmanager.h>\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*\r\n\ta CGapCheck is a single entry representing a gap with a unique name\r\n\tthese are stored in a list: Mdl::Skate::Instance()->m_gapcheck_list\r\n\twhich is re-created individually for each level whan the level is loaded\r\n\t\r\n\tThis list is used to create the \"View Gaps\" menu (from gamemenu.q, script launch_gap_menu)\r\n\t\r\n\tThe gap list is updated in game with CGapCheck::GetGap() whena  gap is got\r\n\t\r\n\tTODO -> add LandPendingGaps to \"solidlfy\" gaps.  The gap should be flagged\r\n\tas \"pending\" when you \"get\" it (with an EndGap).  But it should only\r\n\tbe really flagged when you sucessfully land the combo\r\n\tand it should be cleared if you bail while doing the gap \r\n\r\n\r\n*/\t\r\n\r\n// Constructors are needed for types derived from the list node class\r\n// so the \"this\" pointer can be passed down, so it ends up\r\n// in the data member\r\n\r\nCGapCheck::CGapCheck(): Lst::Node< CGapCheck > ( this )\r\n{\t\r\n\tm_got = 0;\r\n\tm_got_pending = 0;\r\n\tm_valid = true;\t\t\t// newly created gaps are always valid\r\n}\r\n\r\nint\t\t\t\tCGapCheck::Got()\r\n{\r\n\treturn m_got;\r\n}\r\n\r\nvoid\t\t\t\tCGapCheck::GetGap()\r\n{\r\n\tm_got+= m_got_pending;\r\n\tm_got_pending = 0;\r\n}\r\n\r\nvoid\t\t\t\tCGapCheck::GetGapPending()\r\n{\r\n\tm_got_pending += 1;\r\n}\r\n\r\nvoid\t\t\t\tCGapCheck::UnGetGapPending()\r\n{\r\n\tm_got_pending = 0;\r\n}\r\n\r\nint\t\t\t\tCGapCheck::GotGapPending()\r\n{\r\n\t return m_got_pending;\r\n}\r\n\r\n\r\nvoid\t\t\t\tCGapCheck::UnGetGap()\r\n{\r\n\tm_got = false;\r\n}\r\n\r\nconst char\t*\t\t\tCGapCheck::GetText()\r\n{\r\n\treturn m_name.getString();\r\n}\r\n\r\nvoid\t\t\t\tCGapCheck::SetText(const char *p)\r\n{\r\n\tm_name = p;\r\n}\r\n\r\nvoid CGapCheck::SetInfoForCamera(Mth::Vector pos, Mth::Vector dir)\r\n{\r\n\tm_skater_start_pos=pos;\r\n\tm_skater_start_dir=dir;\r\n}\r\n\r\nvoid\t\t\t\tCGapCheck::SetCount(int count)\r\n{\r\n\tm_got = count;\r\n}\r\n\r\nvoid \t\t\t\tCGapCheck::SetValid(bool valid)\r\n{\r\n\tm_valid = valid;\r\n}\r\n\r\nvoid\t\t\t\tCGapCheck::Reset()\r\n{\r\n\tm_got = 0;\r\n\tm_got_pending = 0;\r\n\tm_valid = true;\t\t\t// newly created gaps are always valid\r\n}\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////\r\n\r\nCGap::CGap(): Lst::Node< CGap > ( this )\r\n{\r\n    m_trickChecksum = 0;\r\n    m_numTrickOccurrences = 0;\r\n\tm_spinMult = 0;\r\n\tm_requirePerfect = false;\r\n\tmp_tricks = new Script::CArray();\r\n\tm_startGapTrickCount = 0;\r\n\tm_numTaps = 0;\r\n}\r\n\r\nCGap::~CGap()\r\n{\r\n\tif ( mp_tricks )\r\n\t\tScript::CleanUpArray( mp_tricks );\r\n\tdelete mp_tricks;\r\n}\r\n\r\nCGapTrick::CGapTrick(): Lst::Node< CGapTrick > ( this )\r\n{\r\n}\r\n\r\nvoid CGapTrick::GetGapTrick()\r\n{\r\n    m_got = true;\r\n}\r\n\r\n\r\n// delete all gapchecks\r\n// used when we load a level\t\t\t\t\t\t  \r\n// K: Also used when choosing test play in the park editor, just before adding all the park editor\r\n// gaps.\r\nvoid\tCGapChecklist::FlushGapChecks()\r\n{\r\n\tCGapCheck *pOther = (CGapCheck*)m_gapcheck_list.FirstItem();\r\n\twhile (pOther != NULL)\r\n\t{\r\n\t\tdelete pOther;\r\n\t\tpOther = (CGapCheck*)m_gapcheck_list.FirstItem();\r\n\t}\r\n\tm_valid = false;\r\n}\r\n\r\n// Given a name and a count, then add a GapCheck to the list\r\n// if it is already in the list, then just set it valid (leaving the count)\t\t\t\t\t\t   \r\n// (that is so when we re-scan the level's gaps after loading a level, we can remove any\r\n// that do not exist in the level any more)\r\nvoid\tCGapChecklist::AddGapCheck(const char *p_name, int count, int score)\r\n{\r\n\t\r\n\tm_valid = true;\t \t\t\t\t\t\t\t// the list becomes valid when at least one gapcheck is in it\r\n\t\r\n\tCGapCheck *pOther = (CGapCheck*)m_gapcheck_list.FirstItem();\r\n\tCGapCheck *pAppend = NULL;\t\t\t\t// last item we find that is lower than this\r\n\twhile (pOther)\t\t\t\t\t\t \t\t\r\n\t{\r\n\t\tif (!strcmp(pOther->GetText(),p_name) && pOther->GetScore() == score)   // if it matches an existing gap in both text and score\r\n\t\t{\r\n\t\t\tpOther->SetValid(true);\t\t\t\t// then set that one valid (as we might be pruning later)\r\n\t\t\treturn;\t\t\t\t\t\t\t\t// then break out\r\n\t\t}\t\t  \r\n\t\t\r\n\t\tif (pOther->GetScore() < score)\r\n\t\t{\r\n\t\t\tpAppend = pOther;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (pOther->GetScore() == score && Str::Compare(pOther->GetText(),p_name)<0)\r\n\t\t\t{\r\n\t\t\t\tpAppend = pOther;\r\n\t\t\t}\r\n\t\t}\r\n\t\t  \t\t\r\n\t\tpOther = (CGapCheck*)pOther->GetNext();\r\n\t}\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap()); \r\n\t\r\n\tCGapCheck* pGapCheck = new CGapCheck;\t\t// create new gap\t\t\r\n\tpGapCheck->UnGetGap();\t\t\t\t\t\t// say not got it yet\r\n\r\n\tpGapCheck->SetText(p_name);\t\t\t   \t\t// set the text for it\r\n\tpGapCheck->SetCount(count);\t\t\t   \t\t// and the count\r\n\tpGapCheck->SetScore(score);\t\t\t   \t\t// and the count\r\n\tif (pAppend)\r\n\t{\r\n\t\t// Append after the last node that is smaller or equal to than this\r\n\t\tpAppend->Append( pGapCheck );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// add to the ehad of the list if it's smaller than everything\r\n\t\tm_gapcheck_list.AddToHead( pGapCheck );\t \r\n\t}\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\nvoid CGapChecklist::got_gap(Script::CStruct *pScriptStruct, const uint8 *pPC)\r\n{\r\n\tint score=0;\r\n\tpScriptStruct->GetInteger(CRCD(0xcd66c8ae,\"score\"),&score);\r\n\t\r\n\tconst char *p_name=\"\";\r\n\tpScriptStruct->GetText(CRCD(0xc4745838,\"text\"),&p_name);\r\n\r\n\t// only add gaps with some text, and a score\r\n\tif (score && p_name[0])\r\n\t{\r\n\t\tAddGapCheck(p_name,0,score);\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tif (Script::GetInteger(\"PrintGaps\"))\r\n\t\t{\r\n\t\t\tprintf (\"(Name '%s' Score %d - not in checklist)\\n\",p_name,score); // we don't add gaps with no name or score\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\nstatic CGapChecklist * p_current;\r\n\r\n// slightly dodgy callback needed to call memmber function\r\nstatic void Gap_GotGap(Script::CStruct *pScriptStruct, const uint8 *pPC)\r\n{\r\n\tp_current->got_gap(pScriptStruct,pPC);\t\t   \r\n}\r\n\r\n\r\nCGapChecklist::CGapChecklist()\r\n{\r\n\tm_valid = false;\r\n}\r\n\r\n\r\n//  Find all the gaps in the level\r\n// note, we scan regardless, so during development, we \r\n// can add gaps to an already saved game\r\n// (might want to also remove gaps if they have been deleted)\r\nvoid CGapChecklist::FindGaps()\r\n{\t\r\n\tDbg_Message(\"Looking for gaps ...\\n\");\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap()); \r\n\t\r\n\tp_current = this;\t  \t\t\t// store curent 'this' pointer for the callback\r\n\tm_valid = true;\t\t\t\t\t// say that we have looked for gaps in this level\r\n\t\r\n\t// Maybe - scan all gaps, and flag them as not found\r\n\t\r\n\t\r\n\tif (Script::GetInteger(\"PrintGaps\"))\r\n\t{\r\n\t\tprintf(\"\\nGAP LIST\\n--------------------------------------\\n\");\r\n\t}\r\n\r\n\tSkateScript::ScanNodeScripts(CRCD(0x2ca8a299,\"TriggerScript\"), CRCD(0xe5399fb2,\"EndGap\"), Gap_GotGap);\t\r\n\t\r\n\t// Maybe - and then re-scan them here, and delete them if not flagged by got_gap\r\n\t\r\n\tMem::Manager::sHandle().PopContext(); \r\n\tDbg_Message(\"Finished looking for gaps.\\n\");\r\n}\r\n\r\n// K: Given a gap name, this will return its index withing the gap checklist, or -1 if not found.\r\n// Used by the end_gap function in skatergapcomponent when a created gap goal is active.\r\nint CGapChecklist::GetGapChecklistIndex(const char *p_name)\r\n{\r\n\tint index=0;\r\n\tCGapCheck *p_search =  (CGapCheck*) m_gapcheck_list.FirstItem();\r\n\twhile (p_search)\t\t\t\t\t\t \t\t\r\n\t{\r\n\t\tif (!strcmp(p_search->GetText(),p_name))\r\n\t\t{\r\n\t\t\treturn index;\r\n\t\t}\t\r\n\t\tp_search = (CGapCheck*)p_search->GetNext();\r\n\t\t++index;\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\nvoid CGapChecklist::SetInfoForCamera(const char *p_name, Mth::Vector pos, Mth::Vector dir)\r\n{\r\n\tCGapCheck *p_search =  (CGapCheck*) m_gapcheck_list.FirstItem();\r\n\twhile (p_search)\t\t\t\t\t\t \t\t\r\n\t{\r\n\t\tif (!strcmp(p_search->GetText(),p_name))\r\n\t\t{\r\n\t\t\tp_search->SetInfoForCamera(pos,dir);\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tp_search = (CGapCheck*)p_search->GetNext();\r\n\t}\r\n}\r\n\r\nvoid CGapChecklist::GetGapByText(const char *p_text)\r\n{\r\n\tCGapCheck *pOther =  (CGapCheck*) m_gapcheck_list.FirstItem();\r\n\twhile (pOther)\t\t\t\t\t\t \t\t\r\n\t{\r\n\t\tif (!strcmp(pOther->GetText(),p_text))   // if it matches and existing gap \r\n\t\t{\r\n\t\t\tpOther->GetGapPending();\t// flag it as pending\r\n\t\t\r\n\t\t\tbreak;\t\t\t\t\t\t\t\t// then break out\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t}\r\n\t\tpOther = (CGapCheck*)pOther->GetNext();\r\n\t}\r\n}\r\n\r\nvoid CGapChecklist::AwardPendingGaps()\r\n{\r\n\tint gap_index=0;\r\n\tCGapCheck *pOther =  (CGapCheck*) m_gapcheck_list.FirstItem();\r\n\tchar ran_got_gap_for_first_time = 0;\r\n\r\n\twhile (pOther)\t\t\t\t\t\t \t\t\r\n\t{\r\n\t\tif(pOther->GotGapPending())\r\n\t\t{\r\n\t\t\t// K: The gap is being awarded, so let the goal manager know that the gap has\r\n\t\t\t// just been got in case a create-gap-goal is active.\r\n\t\t\tGame::CGoalManager* p_goal_manager = Game::GetGoalManager();\r\n\t\t\tDbg_MsgAssert(p_goal_manager,(\"NULL p_goal_manager ?\"));\r\n\t\t\tif (p_goal_manager->CreatedGapGoalIsActive())\r\n\t\t\t{\r\n\t\t\t\t// Let the goal manager know that this gap has just been gone through so that\r\n\t\t\t\t// it can tick it off it's list of required gaps, if it is one of them.\r\n\t\t\t\tp_goal_manager->GetCreatedGoalGap(gap_index);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// The code below is commented out so multiple new gap messages can be displayed\r\n\t\t\tif ( pOther->Got() == 0 )//&& !ran_got_gap_for_first_time )\r\n\t\t\t{\r\n\t\t\t\t++ran_got_gap_for_first_time;\r\n\t\t\t\t\r\n\t\t\t\t// this is the first time we've gotten the gap, so give them a message\r\n\t\t\t\tScript::CStruct* pScriptParams = new Script::CStruct();\r\n\r\n\t\t\t\tif( ran_got_gap_for_first_time > 1)\r\n\t\t\t\t\tpScriptParams->AddInteger( Script::GenerateCRC(\"multiple_new_gaps\"), ( int ) ran_got_gap_for_first_time  );\r\n\r\n\t\t\t\tpScriptParams->AddString( CRCD(0xc69ce365,\"gap_text\"), pOther->GetText() );\r\n\t\t\t\tScript::RunScript( CRCD(0x318eaf64,\"got_gap_for_first_time\"), pScriptParams );\r\n\t\t\t\tdelete pScriptParams;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tpOther->GetGap();\r\n\t\t}\r\n\t\tpOther->UnGetGapPending();\t\t\t\r\n\t\tpOther = (CGapCheck*)pOther->GetNext();\r\n\t\t++gap_index;\r\n\t}\r\n}\r\n\r\nvoid CGapChecklist::AwardAllGaps()\r\n{\r\n\r\n\tCGapCheck *pOther =  (CGapCheck*) m_gapcheck_list.FirstItem();\r\n\r\n\twhile (pOther)\t\t\t\t\t\t \t\t\r\n\t{  \t\r\n\t\tpOther->SetCount( pOther->Got() + 1 );\t\t\t\r\n\t\tpOther = (CGapCheck*)pOther->GetNext();\r\n\t}\r\n}\r\n\r\nvoid CGapChecklist::ClearPendingGaps()\r\n{\r\n\tCGapCheck *pOther =  (CGapCheck*) m_gapcheck_list.FirstItem();\r\n\twhile (pOther)\t\t\t\t\t\t \t\t\r\n\t{\r\n\t\tpOther->UnGetGapPending();\t\t\t\r\n\t\tpOther = (CGapCheck*)pOther->GetNext();\r\n\t}\r\n}\r\n\r\nint\tCGapChecklist::NumGaps()\r\n{\r\n\treturn m_gapcheck_list.CountItems();\r\n}\r\n\r\n\r\nbool CGapChecklist::GotAllGaps()\r\n{\r\n\tCGapCheck *pOther =  (CGapCheck*) m_gapcheck_list.FirstItem();\r\n\twhile (pOther)\t\t\t\t\t\t \t\t\r\n\t{\r\n\t\tif ( pOther->Got() == 0 )\r\n\t\t\treturn false;\r\n\t\tpOther = (CGapCheck*)pOther->GetNext();\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nvoid CGapChecklist::Reset()\r\n{\r\n\tCGapCheck *pOther =  (CGapCheck*) m_gapcheck_list.FirstItem();\r\n\twhile (pOther)\t\t\t\t\t\t \t\t\r\n\t{\r\n\t\tpOther->Reset();\r\n\t\tpOther = (CGapCheck*)pOther->GetNext();\r\n\t}\r\n}\r\n\r\nbool CGapChecklist::ScriptGetLevelGapTotals( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGapCheck *pGap =  (CGapCheck*) m_gapcheck_list.FirstItem();\r\n\t\r\n\tint total_gaps = 0;\r\n\tint total_got = 0;\r\n\twhile (pGap)\t\t\t\t\t\t \t\t\r\n\t{\r\n\t\tCGapCheck* pNext = (CGapCheck*)pGap->GetNext();\r\n\t\ttotal_gaps++;\r\n\t\r\n\t\tif ( pGap->Got() )\r\n\t\t\ttotal_got++;\r\n\r\n\t\tpGap = (CGapCheck*)pNext;\r\n\t}\r\n\tpScript->GetParams()->AddInteger( \"num_gaps\", total_gaps );\r\n\tpScript->GetParams()->AddInteger( \"num_collected_gaps\", total_got );\r\n\treturn true;\r\n}\r\n\r\n\r\nbool CGapChecklist::ScriptAddGapsToMenu( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 choose_script=CRCD(0xf7e902c,\"nullscript\");\r\n\tpParams->GetChecksum(CRCD(0xa7d7c610,\"choose_script\"),&choose_script);\r\n\r\n\r\n\tCGapCheck *pGap =  (CGapCheck*) m_gapcheck_list.FirstItem();\r\n\t\r\n\tScript::CStruct* p_gap_params;\r\n\tint entry = 0;\r\n\twhile (pGap)\t\t\t\t\t\t \t\t\r\n\t{\r\n\t\tp_gap_params = new Script::CStruct;\r\n\r\n\t\t// check if this is the first or last gap\r\n\t\tCGapCheck* pNext = (CGapCheck*)pGap->GetNext();\r\n\t\tif ( entry == 0 )\r\n\t\t\tp_gap_params->AddChecksum( NONAME, CRCD( 0x171665d5, \"first_item\" ) );\r\n\t\telse if ( !pNext )\r\n\t\t\tp_gap_params->AddChecksum( NONAME, CRCD( 0x76cf1ebd, \"last_item\" ) );\r\n\r\n\t\tp_gap_params->AddInteger( \"gap_score\", pGap->GetScore() );\r\n\t\tp_gap_params->AddString( \"gap_name\", pGap->GetText() );\r\n\t\tp_gap_params->AddInteger( \"times\", pGap->Got() );\r\n\r\n\t\tp_gap_params->AddInteger( \"gap_number\", entry );\r\n\t\t\r\n\t\tMth::Vector v=pGap->GetSkaterStartPos();\r\n\t\tp_gap_params->AddVector(CRCD(0x26a4e85a,\"skater_start_pos\"),v[X],v[Y],v[Z]);\r\n\t\tv=pGap->GetSkaterStartDir();\r\n\t\tp_gap_params->AddVector(CRCD(0x1cd674e6,\"skater_start_dir\"),v[X],v[Y],v[Z]);\r\n\t\t\r\n\t\tp_gap_params->AddChecksum(CRCD(0xa7d7c610,\"choose_script\"),choose_script);\r\n\t\t\r\n\t\tScript::RunScript( \"gap_menu_add_item\", p_gap_params );\r\n\t\tdelete p_gap_params;\r\n\r\n\t\tpGap = (CGapCheck*)pNext;\r\n\t\tentry++;\r\n\t}\r\n\r\n\tif (entry == 0)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool CGapChecklist::ScriptCreateGapList( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCGapCheck *p_gap =  (CGapCheck*) m_gapcheck_list.FirstItem();\r\n\r\n\tint num_gaps=0;\r\n\twhile (p_gap)\t\t\t\t\t\t \t\t\r\n\t{\r\n\t\tp_gap = (CGapCheck*)p_gap->GetNext();\r\n\t\t++num_gaps;\r\n\t}\t\r\n\tpScript->GetParams()->AddInteger(CRCD(0x7f5b3d4d,\"array_size\"),num_gaps);\r\n\t\r\n\tif (!num_gaps)\r\n\t{\r\n\t\tpScript->GetParams()->AddInteger(CRCD(0x6a8a0061,\"num_gaps_got\"),0);\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\tScript::CArray *p_gap_list=new Script::CArray;\r\n\tp_gap_list->SetSizeAndType(num_gaps,ESYMBOLTYPE_STRUCTURE);\r\n\t\r\n\tp_gap =  (CGapCheck*) m_gapcheck_list.FirstItem();\r\n\t\r\n\tint gap_number = 0;\r\n\tint num_gaps_got=0;\r\n\twhile (p_gap)\t\t\t\t\t\t \t\t\r\n\t{\r\n\t\tif (p_gap->Got())\r\n\t\t{\r\n\t\t\t++num_gaps_got;\r\n\t\t}\r\n\t\t\t\r\n\t\tScript::CStruct* p_gap_params = new Script::CStruct;\r\n\r\n\t\tp_gap_params->AddInteger( \"gap_score\", p_gap->GetScore() );\r\n\t\tp_gap_params->AddString( \"gap_name\", p_gap->GetText() );\r\n\t\tp_gap_params->AddInteger( \"times\", p_gap->Got() );\r\n\r\n\t\tp_gap_params->AddInteger( \"gap_number\", gap_number );\r\n\t\t\r\n\t\tMth::Vector v=p_gap->GetSkaterStartPos();\r\n\t\tp_gap_params->AddVector(CRCD(0x26a4e85a,\"skater_start_pos\"),v[X],v[Y],v[Z]);\r\n\t\tv=p_gap->GetSkaterStartDir();\r\n\t\tp_gap_params->AddVector(CRCD(0x1cd674e6,\"skater_start_dir\"),v[X],v[Y],v[Z]);\r\n\t\t\r\n\t\tp_gap_list->SetStructure(gap_number,p_gap_params);\r\n\t\tp_gap = (CGapCheck*)p_gap->GetNext();\r\n\t\t++gap_number;\r\n\t}\r\n\r\n\tpScript->GetParams()->AddArrayPointer(CRCD(0x737449de,\"GapList\"),p_gap_list);\r\n\tpScript->GetParams()->AddInteger(CRCD(0x6a8a0061,\"num_gaps_got\"),num_gaps_got);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AddgapsToMenu | adds all gaps to the menu\r\nbool ScriptAddGapsToMenu( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t\r\n\tbool result = \tMdl::Skate::Instance()->GetGapChecklist()->ScriptAddGapsToMenu(pParams,pScript); \r\n\t\r\n\t\r\n\treturn result;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CreateGapList | Similar to AddGapsToMenu, but instead creates an array of structures called GapList\r\n// and adds it to the calling script's parameters.\r\nbool ScriptCreateGapList( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\treturn Mdl::Skate::Instance()->GetGapChecklist()->ScriptCreateGapList(pParams,pScript); \r\n}\r\n\r\n// @script | GetLevelGapTotals | returns the total number of gaps and the number\r\n// of gaps that have been completed in the level (num_gaps, num_completed_gaps)\r\n// @parm int | level | the level number\r\nbool ScriptGetLevelGapTotals( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tint level;\r\n\tpParams->GetInteger( \"level\", &level, Script::ASSERT );\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkaterCareer* pCareer = skate_mod->GetCareer();\r\n\t\r\n\tbool result = pCareer->GetGapChecklist( level )->ScriptGetLevelGapTotals( pParams, pScript );\r\n\treturn result;\r\n}\r\n\r\n// @script | GiveAllGaps | \"Gets\" all the gaps in level or current level if none is specified\r\n// @parm int | level | the level number | optional\r\nbool ScriptGiveAllGaps( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkaterCareer* pCareer = skate_mod->GetCareer();\r\n\r\n\tint level;\r\n\tif(!pParams->GetInteger( \"level\", &level, Script::NO_ASSERT ))\r\n\t\tlevel = pCareer->GetLevel();\r\n\t\r\n\tpCareer->GetGapChecklist( level )->AwardAllGaps();\r\n\treturn true;\r\n}\r\n\r\n\r\nCGapCheck *CGapChecklist::get_indexed_gapcheck(int gap_index)\r\n{\r\n\r\n\tCGapCheck *pGap =  (CGapCheck*) m_gapcheck_list.FirstItem();\r\n\tint \tentry = 0;\r\n\twhile (pGap)\t\t\t\t\t\t \t\t\r\n\t{\r\n\t\tif (entry == gap_index)\r\n\t\t{\r\n\t\t\treturn pGap;\t\t\r\n\t\t}\r\n\t\tpGap = (CGapCheck*)pGap->GetNext();\r\n\t\tentry++;\r\n\t}\r\n\tDbg_MsgAssert(0,(\"Gap index %ds invalid\\n\",gap_index));\t\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CGapChecklist::ScriptGotGap( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tint\tgap_index = 0;\r\n\tpParams->GetInteger(NONAME,&gap_index,true);\t\t \r\n\treturn get_indexed_gapcheck(gap_index)->Got();\r\n}\r\n\r\nconst char *\tCGapChecklist::GetGapText(int gap)\r\n{\r\n\treturn get_indexed_gapcheck(gap)->GetText();\r\n}\r\n\r\nint\tCGapChecklist::GetGapCount(int gap)\r\n{\r\n\treturn get_indexed_gapcheck(gap)->Got();\r\n}\r\n\r\nint\tCGapChecklist::GetGapScore(int gap)\r\n{\r\n\treturn get_indexed_gapcheck(gap)->GetScore();\r\n}\r\n\r\nvoid CGapChecklist::GetSkaterStartPosAndDir(int gap, Mth::Vector *p_skaterStartPos, Mth::Vector *p_skaterStartDir)\r\n{\r\n\tCGapCheck *p_gap_check=get_indexed_gapcheck(gap);\r\n\t\r\n\t*p_skaterStartPos=p_gap_check->GetSkaterStartPos();\r\n\t*p_skaterStartDir=p_gap_check->GetSkaterStartDir();\r\n}\r\n\r\n// @script | GotGap | returns true if we have got the indicated gap\r\n// this really only makes sense in the context of the gap menu (see AddGapsToMenu)\r\nbool ScriptGotGap( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\treturn Mdl::Skate::Instance()->GetGapChecklist()->ScriptGotGap(pParams,pScript); \r\n}\r\n\r\n\r\n \r\n}\t// end of Ojb namespace\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/gap.h",
    "content": "////////////////////////////////////////////////////////////\r\n// gap.h\r\n\r\n#ifndef\t__GAP_H__\r\n#define\t__GAP_H__\r\n\r\n#define\t__USE_MJB_LIST__\r\n\t  \r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __CORE_MATH_H\r\n#include <core/math.h>\r\n#endif\r\n\r\n#include <core/list.h>\r\n#include <core/string/cstring.h>\r\n\r\n#include <gel/scripting/array.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\r\n#define\tCANCEL_GROUND\t\t\t\t0x00000001\r\n#define\tCANCEL_AIR              \t0x00000002\r\n#define\tCANCEL_RAIL             \t0x00000004\r\n#define\tCANCEL_WALL             \t0x00000008\r\n#define\tCANCEL_LIP              \t0x00000010\r\n#define\tCANCEL_WALLPLANT\t\t\t0x00000020\r\n#define\tCANCEL_MANUAL\t\t\t\t0x00000040\r\n#define CANCEL_HANG     \t    \t0x00000080\r\n#define CANCEL_LADDER\t         \t0x00000100\r\n#define CANCEL_SKATE\t\t\t\t0x00000200\r\n#define CANCEL_WALK\t\t\t\t\t0x00000400\r\n#define CANCEL_DRIVE\t\t\t\t0x00000800\r\n\r\n#define\tCANCEL_MASK\t\t\t\t\t0x0000FFFF\r\n\r\n#define\tREQUIRE_GROUND\t\t\t\t0x00010000\r\n#define\tREQUIRE_AIR             \t0x00020000\r\n#define\tREQUIRE_RAIL            \t0x00040000\r\n#define\tREQUIRE_WALL            \t0x00080000\r\n#define\tREQUIRE_LIP             \t0x00100000\r\n#define\tREQUIRE_WALLPLANT\t\t\t0x00200000\r\n#define\tREQUIRE_MANUAL\t\t\t\t0x00400000\r\n#define REQUIRE_HANG\t        \t0x00800000\r\n#define REQUIRE_LADDER\t        \t0x01000000\r\n#define REQUIRE_SKATE\t\t\t\t0x02000000\r\n#define REQUIRE_WALK\t\t\t\t0x04000000\r\n#define REQUIRE_DRIVE\t\t\t\t0x08000000\r\n                                \r\n#define\tREQUIRE_MASK\t\t\t\t0xFFFF0000\r\n\r\n\r\nclass CGapCheck : public Lst::Node< CGapCheck >\r\n{\r\npublic:\r\n\t\t\t\t\t\tCGapCheck();\r\n\tint\t\t\t\t\tGot();\r\n\tvoid\t\t\t\tGetGap();\r\n\t\r\n\tvoid\t\t\t\tGetGapPending();\r\n\tvoid\t\t\t\tUnGetGapPending();\r\n\tint\t\t\t\t\tGotGapPending();\r\n\t\r\n\tvoid\t\t\t\tSetInfoForCamera(Mth::Vector pos, Mth::Vector dir);\r\n\tMth::Vector&\t\tGetSkaterStartPos() {return m_skater_start_pos;}\r\n\tMth::Vector&\t\tGetSkaterStartDir() {return m_skater_start_dir;}\r\n\t\r\n\t\r\n\tvoid\t\t\t\tUnGetGap();\r\n\tconst char\t*\t\tGetText();\r\n\tvoid\t\t\t\tSetText(const char *p);\r\n\tvoid\t\t\t\tSetCount(int count);\r\n\tvoid\t\t\t\tSetScore(int score) {m_score = score;}\r\n\tint\t\t\t\t\tGetScore() {return m_score;};\r\n\tvoid \t\t\t\tSetValid(bool valid);\r\n\r\n\tvoid\t\t\t\tReset();\r\nprivate:\r\n\tMth::Vector\t\t\tm_skater_start_pos;\r\n\tMth::Vector\t\t\tm_skater_start_dir;\r\n\t\r\n\tint\t\t\t\t\tm_got_pending;\t\t\t// number of times we have got this gap, but the landing of the combo is still pending\r\n\tint\t\t\t\t\tm_got;\t\t\t\t\t// number of times we have got this gap\r\n\tint\t\t\t\t\tm_score;\t\t\t\t// score for this gap\r\n\tbool\t\t\t\tm_valid;\t\t\t\t// flag used when parsing gaps to remove any that no longer exist (from an old save)\r\n\tStr::String\t\t\tm_name;\r\n};\r\n\r\n\r\n\r\n// CGapChecklist contains a list of gaps for the level\r\n// these gaps (CGap) count how many times they have been got,\r\n// and so this list is used to display the in-game gap checklist\r\n// there is one of these for each level in an array in CSkaterCareer\r\n// \r\nclass CGapChecklist \r\n{\r\n\r\npublic:\r\n\t\t\t\t\t\t\t\t\t\tCGapChecklist();\r\n\tvoid \t\t\t\t\t\t\t\tFindGaps();\r\n\tvoid \t\t\t\t\t\t\t\tGetGapByText(const char *p_text);\r\n\tint\t\t\t\t\t\t\t\t\tGetGapChecklistIndex(const char *p_name);\r\n\tvoid\t\t\t\t\t\t\t\tSetInfoForCamera(const char *p_name, Mth::Vector pos, Mth::Vector dir);\r\n\tvoid \t\t\t\t\t\t\t\tAwardPendingGaps(); \r\n\tvoid \t\t\t\t\t\t\t\tAwardAllGaps();\r\n\tvoid \t\t\t\t\t\t\t\tClearPendingGaps();\r\n\tbool \t\t\t\t\t\t\t\tScriptAddGapsToMenu( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\t\t\t\tScriptCreateGapList( Script::CStruct* pParams, Script::CScript* pScript );\r\n\t\r\n\tbool\t\t\t\t\t\t\t\tScriptGotGap( Script::CStruct* pParams, Script::CScript* pScript );\r\n\tbool\t\t\t\t\t\t\t\tScriptGetLevelGapTotals( Script::CStruct* pParams, Script::CScript* pScript );\r\n\t\r\n\tbool\t\t\t\t\t\t\t\tIsValid() {return m_valid;}\r\n\tint\t\t\t\t\t\t\t\t\tNumGaps();\r\n\r\n\tconst char *\t\t\t\t\t\tGetGapText(int gap);\r\n\tint\t\t\t\t\t\t\t\t\tGetGapCount(int gap);\r\n\tint\t\t\t\t\t\t\t\t\tGetGapScore(int gap);\r\n\tvoid\t\t\t\t\t\t\t\tGetSkaterStartPosAndDir(int gap, Mth::Vector *p_skaterStartPos, Mth::Vector *p_skaterStartDir);\r\n\r\n\tvoid\t\t\t\t\t\t\t\tAddGapCheck(const char *p_name, int count, int score);\r\n\tvoid\t\t\t\t\t\t\t\tFlushGapChecks();\r\n\r\n\tbool\t\t\t\t\t\t\t\tGotAllGaps();\r\n\tvoid\t\t\t\t\t\t\t\tReset();\r\n\r\n// semi-private, dammit...\t\r\n\tvoid \t\t\t\t\t\t\t\tgot_gap(Script::CStruct *pScriptStruct, const uint8 *pPC);\r\nprivate:\r\n\r\n\tObj::CGapCheck *\t\t\t\t\tget_indexed_gapcheck(int gap_index);\r\n\tbool\t\t\t\t\t\t\t\tm_valid;\t\t\t// true if we'd parsed the scripts for this level\r\n\tLst::Head< Obj::CGapCheck >\t\t\tm_gapcheck_list;\t// list of unique gaps in level, or NULL if none\r\n};\r\n\r\n// CGap is a gap we are in the middle of\r\nclass CGap : public Lst::Node< CGap >\r\n{\r\n\tpublic:\t\r\n\t\tCGap();\r\n\t\t~CGap();\r\n\tpublic:\r\n\t\tuint32\t\t\tm_id;\t\t\t\t\t// checksum of the gap's ID\r\n\t\tuint32\t\t\tm_flags;\t\t\t\t// bit fields saying what cancles it\r\n\t\tuint32\t\t\tm_node;\t\t\t\t\t// source node\r\n        uint32          m_trickChecksum;\r\n        int             m_numTrickOccurrences;\r\n        uint32          m_trickscript;\r\n\t\tuint32\t\t\tm_trickTextChecksum;\r\n\t\tint\t\t\t\tm_spinMult;\r\n\t\tbool\t\t\tm_requirePerfect;\r\n\t\tint\t\t\t\tm_startGapTrickCount;\r\n\t\tint\t\t\t\tm_numTaps;\r\n\r\n\t\t// K: The position & direction the skater is facing when the StartGap command was executed.\r\n\t\t// Used to determine a good camera position when showing the gap in the view-gaps menu.\r\n\t\tMth::Vector\t\tm_skater_start_pos;\r\n\t\tMth::Vector\t\tm_skater_start_dir;\r\n\t\t\t\t\r\n\t\t// these arrays are used for arrays of tricks that must\r\n\t\t// be completed in order to get the gap.\r\n\t\tScript::CArray* mp_tricks;\r\n};\r\n\r\n// CGaptrick contains list if gaps we are in the middle of, that contain tricks\r\nclass CGapTrick : public Lst::Node< CGapTrick >\r\n{\r\npublic:\r\n\tCGapTrick();\r\n    void                GetGapTrick();\r\npublic:\r\n    Str::String         m_trickString;\r\n    uint32  \t\t\tm_id;                   // matches the gap's ID\r\n\tuint32\t \t\t\tm_node;\t\t\t\t\t// node this came from\r\n\tuint32\t \t\t\tm_script;\t\t\t\t// script to run when sucessful\r\n    bool                m_got;\r\n\tuint32\t\t\t\tm_frame;\t\t\t\t// Logic frame number on which this was triggered\r\n};\r\n\r\n// Some gap utility functions\r\nbool ScriptAddGapsToMenu( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptCreateGapList( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetLevelGapTotals( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGiveAllGaps( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\n}  // end namespace obj\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/Objects/manual.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObjects (OBJ) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmanual.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/31/01\t-\tksh\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSkater object code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#define\t\t__DEBUG_CHEESE__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n\r\n#include <core/math.h>\r\n\r\n#include <gel/inpman.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/components/statsmanagercomponent.h>\r\n\r\n#include <objects/manual.h>\r\n#include <objects/rail.h>\r\n#include <objects/skaterprofile.h>\r\n\r\n#include <sys/timer.h>\r\n\r\n\r\n#include <engine/sounds.h>\r\n\r\n#include <gfx/camera.h>\r\n#include <gfx/shadow.h>\r\n\r\n#include <gfx/debuggfx.h>\r\n\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n#include <sk/modules/skate/skate.h> \r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skaterbalancetrickcomponent.h>\r\n#include <sk/components/skaterscorecomponent.h>\r\n\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCManual::CManual()\r\n{\r\n\tReset();\r\n}\r\n\r\nCManual::~CManual()\r\n{\r\n\t\r\n}\r\n\r\nvoid CManual::Init ( CCompositeObject *pSkater )\r\n{\r\n\tmpSkater = pSkater;\r\n\tDbg_Assert(mpSkater);\r\n\t\r\n\tmpSkaterBalanceTrickComponent = GetSkaterBalanceTrickComponentFromObject(mpSkater);\r\n\tDbg_Assert(mpSkaterBalanceTrickComponent);\r\n\t\r\n\tmpSkaterScoreComponent = GetSkaterScoreComponentFromObject(mpSkater);\r\n\tDbg_Assert(mpSkaterScoreComponent);\r\n\t\r\n\tmpInputComponent = GetInputComponentFromObject(mpSkater);\r\n\tDbg_Assert(mpInputComponent);\r\n}\r\n\r\nvoid CManual::Reset()\r\n{\r\n\r\n#ifdef\t\t__DEBUG_CHEESE__\r\n\tprintf (\"%d:   Resetting cheese to 0 in CManual::Reset\\n\",__LINE__);\r\n#endif\t\r\n\tmManualCheese=0.0f;\r\n\tmActualManualTime=0.0f;\r\n\tmManualTime=0.0f;\r\n\tmManualLean=0.0f;\r\n\tmManualLeanDir=0.0f;\r\n\tmManualReleased=false;\r\n\tmOldRailNode=-1;\r\n\tmWobbleEnabled=false;\r\n}\r\n\r\n// a utility function to scale a linear value based on \r\n// the framerate\r\n// m_time will be 1/60 when running at 60fps\r\n// and 1/50 when running at 50fps (for pal)\r\n// So, this 60.0f is correct for PAL\r\n// as the adjustment is done to m_time\t\t\t\t\t\r\nfloat CManual::scale_with_frame_length ( float frame_length, float f )\r\n{\r\n\treturn f * frame_length * 60.0f;\t  // Do NOT change this in PAL mode, leave it at 60\r\n}\r\n\r\n// clear the record time for this level, only call this at start of a session\r\nvoid CManual::ClearMaxTime()\r\n{\r\n\t\r\n\tmMaxTime=0.0f;\r\n}\r\n\r\n\r\nvoid CManual::SwitchOffMeters()\r\n{\r\n\t\r\n\tmNeverShowMeters=true;\r\n}\r\n\r\nvoid CManual::SwitchOnMeters()\r\n{\r\n\t\r\n\tmNeverShowMeters=false;\r\n}\r\n\r\n// Switched off the meters and sets the buttons to zero so that calling DoManualPhysics will\r\n// have no effect.\r\nvoid CManual::Stop()\r\n{\r\n\t\r\n\t// Switch off the meters.\r\n\tif (mpSkaterScoreComponent->GetScore())\r\n\t{\r\n\t\tmpSkaterScoreComponent->GetScore()->SetBalanceMeter(false);\r\n\t\tmpSkaterScoreComponent->GetScore()->SetManualMeter(false);\r\n\t} \r\n\tmButtonAChecksum=0;\r\n\tmButtonBChecksum=0;\r\n}\r\n\r\n\r\n// Check to see if this is a new record\t\t\t\t \r\nvoid CManual::UpdateRecord()\r\n{\r\n    // Update the longest grind/manual/lip\r\n\tif (mActualManualTime>mMaxTime)\r\n\t{\r\n\t\tmMaxTime=mActualManualTime;\r\n\t}\r\n\tmActualManualTime = 0.0f;\r\n}\r\n\r\n\r\n\r\nvoid CManual::SetUp(uint32 ButtonAChecksum, uint32 ButtonBChecksum, int Tweak, bool DoFlipCheck, bool PlayRangeAnimBackwards)\r\n{\r\n\t\r\n\tmActualManualTime = 0.0f;\r\n\tmManualReleased=false;\r\n\tmButtonAChecksum=ButtonAChecksum;\r\n\tmButtonBChecksum=ButtonBChecksum;\r\n\tmTweak=Tweak;\r\n\tmDoFlipCheck=DoFlipCheck;\r\n\tmPlayRangeAnimBackwards=PlayRangeAnimBackwards;\r\n\r\n\tDbg_MsgAssert(mpSkater,(\"NULL mpSkater\"));\r\n\r\n\t// Check for whether the skater has re-railed onto the same rail\r\n\t// or a different one.\r\n\tif (mpSkaterBalanceTrickComponent->mBalanceTrickType==0x255ed86f || // Grind\r\n\t\tmpSkaterBalanceTrickComponent->mBalanceTrickType==0x8d10119d) // Slide\r\n\t{\r\n\t\tconst CRailNode* p_rail_node = GetSkaterCorePhysicsComponentFromObject(mpSkater)->mp_rail_node;\r\n\t\t\r\n\t\tDbg_MsgAssert(p_rail_node,(\"What, NULL mp_rail_node ??\"));\r\n\t\t\r\n\t\tif (mOldRailNode==-1)\r\n\t\t{\r\n\t\t\t// This is a fresh rail.\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\r\n\t\t\tif (p_rail_node->ProbablyOnSameRailAs(mOldRailNode))\r\n\t\t\t{\r\n\t\t\t\t// Jumped and landed on the same rail without ending\r\n\t\t\t\t// the combo.\r\n\t\t\t\t// Add some time to make this more difficult.\r\n\t\t\t\tmManualTime+=mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0xfbec5b6c, \"Same_Grind_Add_Time\"));\r\n\t\t\t\t#ifdef\t\t__DEBUG_CHEESE__\r\n\t\t\t\t\tprintf (\"%d:  %.2f:  leaving cheese, probably on same rail\\n\",__LINE__,mManualCheese);\r\n\t\t\t\t#endif\t\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// It's a different rail from the last one, ie jumped from a rail to\r\n\t\t\t\t// another rail without ending the combo.\r\n\t\t\t\t// Reward the player by subtracting a bit of time to make it easier.\r\n\t\t\t\tmManualTime-=mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0xc5e1c8eb,\"New_Grind_Sub_Time\"));\r\n\t\t\t\tif (mManualTime<0.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\tmManualTime=0.0f;\r\n\t\t\t\t}\t\r\n\t\t\t\t// And clear the cheese\r\n\t\t\t\t// as it's not cheesey to change rails\r\n\t\t\t\t// so we don't to penalize the player for doing so\r\n\t\t\t\t#ifdef\t\t__DEBUG_CHEESE__\r\n\t\t\t\t\tprintf (\"%d:   Resetting cheese to 0 as it's a new grind\\n\",__LINE__);\r\n\t\t\t\t#endif\t\r\n\r\n\t\t\t\tmManualCheese = 0.0f;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\tmOldRailNode=p_rail_node->GetNode();\r\n\t\t\r\n\t\tMdl::Score *pScore=mpSkaterScoreComponent->GetScore();\r\n\t\tfloat robot = pScore->GetRobotRailMult();\r\n\t\tif ( robot < 0.5f)\t   // <0.5 means any time you are on the same rail twice in a combo\r\n\t\t{\r\n//\t\t\tprintf (\"SHOULD ADJUST BALANCE HERE, AS ON A ROBOT LINE\\n\");\r\n\t\t\t// Need to add something to the Manual Time\r\n\t\t\tmManualTime += Script::GetFloat(CRCD(0xf54ca12f,\"robot_rail_add_time\") )* 0.5f / robot;\r\n\t\t\t\r\n\t\t\t// And give him  percentage nudge away from 0\r\n\t\t\t// (actually, an absolute value would be better, more consistent\r\n\t\t\t// perhaps not even based on the amount, just trigger 20% whenever  \r\n\t\t\t// you land on something robotesque\r\n\t\t\tmManualLean += Script::GetFloat(CRCD(0x30990680,\"robot_rail_nudge\")) * Mth::Sgn(mManualLeanDir) * 0.5f / robot;\r\n//\t\t\tprintf (\"Time = %.2f,  Lean = %.2f, dir = %.2f\\n\",mManualTime, mManualLean, mManualLeanDir);\r\n\t\t}\r\n\t\t\r\n\t\t\r\n\t}\r\n\r\n\tfloat repeat_min = mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0x8f4db5d3,\"Repeat_Min\"));\r\n\tif ( Mth::Abs(mManualLeanDir) != 0.0f)\r\n\t{\r\n\t\t// first multiplied by the reat multipler\r\n\t\tmManualLeanDir = mManualLeanDir * mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0x93dd6a10,\"Repeat_Multiplier\"));\t\t\r\n\t\t\t\t\r\n\t\t// use the sign of previous balance\r\n\t\tif ( Mth::Abs(mManualLeanDir) < repeat_min)\r\n\t\t{\r\n\t\t\t//  if too small, then set to minimum\r\n\t\t\tmManualLeanDir = repeat_min * Mth::Sgn(mManualLeanDir);\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// No previous balance\r\n\t\t// so just set to default minimum\r\n\t\tmManualLeanDir = repeat_min;\r\n\t\t// Adjust the sign of the lean to point in the direction of a bail.\r\n\t\tswitch (mpSkaterBalanceTrickComponent->mBalanceTrickType)\r\n\t\t{\r\n\t\t\tcase 0xef24413b: // Manual\r\n\t\t\t\t// Manuals keep positive sign.\r\n\t\t\t\tbreak;\r\n\t\t\tcase 0x0ac90769: // NoseManual\t\r\n\t\t\t\t// Nosemanuals fall the other way.\r\n\t\t\t\tmManualLeanDir=-mManualLeanDir;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\t// If in a grind, choose a random side to fall towards.\r\n\t\t\t\t// Hmm, should choose differently for a lip?\r\n\t\t\t\tif (Mth::Rnd(2))\r\n\t\t\t\t{\r\n\t\t\t\t\tmManualLeanDir=-mManualLeanDir;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t}\t\t\r\n\r\n\t}\r\n\t\r\n\t\r\n\t// multiply this initial direction by some value based on the time\r\n//\tmManualLean = Mth::Abs(mManualLean) * Mth::Sgn(mManualLeanDir);\t\t// possibly alter lean to face the bail direction\r\n\r\n\tmManualLean *= mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0x6ce10ea4,\"Lean_Repeat_Multiplier\"));\r\n\r\n\t// add cheese after lean multiply (otherwise, it can be ineffective)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t#ifdef\t\t__DEBUG_CHEESE__\r\n\t\tprintf (\"%d:  %.2f + %.2f = %.2f:  Adding cheese to lean \\n\",__LINE__,mManualLean, mManualCheese * Mth::Sgn(mManualLean),mManualLean += mManualCheese * Mth::Sgn(mManualLean));\r\n\t#endif\t\t\t\t\t\r\n\r\n\tmManualLean += mManualCheese * Mth::Sgn(mManualLean);\t\t\t\t// add in the cheese\tto the lean\r\n\t\r\n\tfloat BailAngle=mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0xf81ab0e9,\"Lean_Bail_Angle\"));\r\n\tif (Mth::Abs(mManualLean) > BailAngle)\r\n\t{\r\n\t\t#ifdef\t\t__DEBUG_CHEESE__\r\n\t\t\tprintf (\"%d:  %.2f:  Cheese caused an instant bail!!! \\n\",__LINE__,mManualCheese);\r\n\t\t#endif\t\t\t\t\t\r\n\t\t// The cheese has caused an instant bail, so in order that the meter does become\r\n\t\t// visible, make the lean a wee bit less that the bail angle.\r\n\t\tmManualLean=BailAngle*0.9f;\r\n\t\tmManualLean = Mth::Abs(mManualLean) * Mth::Sgn(mManualLeanDir);\r\n\t\tmManualLeanDir = Mth::Sgn(mManualLeanDir) * BailAngle;  // ensure a bail next frame\r\n\t}\r\n\r\n\t\r\n\t// Reset the cheese.\r\n\tmManualCheese=mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0x1231ae3c,\"Cheese\"));\r\n\r\n\t#ifdef\t\t__DEBUG_CHEESE__\r\n\t\tprintf (\"%d:  %.2f:  Cheese reset to initial scripted value \\n\",__LINE__,mManualCheese);\r\n\t#endif\t\t\t\t\t\r\n\r\n\t\r\n\t// The programmatic wobble applied to the animation is off initially, so that it does not get applied\r\n\t// to the init anim.\r\n\tmWobbleEnabled=false;\r\n\t\r\n\tmStartTime=Tmr::ElapsedTime(0);\r\n}\r\n\r\n// Gets called by the EnableWobble skater script command.\r\nvoid CManual::EnableWobble()\r\n{\r\n\t\r\n\tmWobbleEnabled=true;\r\n}\r\n\r\n//static float MaxTime=0;\r\nvoid CManual::DoManualPhysics()\r\n{\r\n\tfloat frame_length = Tmr::FrameLength();\r\n\t\r\n\t// Do nothing if no buttons are specified.\r\n\tif (!mButtonAChecksum || !mButtonBChecksum)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tNet::Server* server;\r\n\tGameNet::PlayerInfo* player;\r\n\tNet::Conn* skater_conn;\r\n\t\r\n\tDbg_MsgAssert(mpSkater,(\"NULL mpSkater\"));\r\n\t\r\n\tskater_conn = NULL;\r\n\tif(( server = gamenet_man->GetServer()))\r\n\t{\r\n\t\tif(( player = gamenet_man->GetPlayerByObjectID( mpSkater->GetID() )))\r\n\t\t{\r\n\t\t\tskater_conn = player->m_Conn;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// decrement the cheese value, which is added to the lean angle when we do the next manual\r\n\t// this is to prevent \"cheesing\" the manuals (by rapidly doing several manuals that only\r\n\t// last a frame or two, and don't give the balancing physics any time to take effect).\r\n\r\n\tif (mManualCheese>0.01f)\r\n\t{\r\n\t\tmManualCheese -= scale_with_frame_length(frame_length, mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0x1231ae3c,\"Cheese\"))/mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0xa4362662,\"CheeseFrames\")));\r\n\t\tif (mManualCheese < 0.0f)\r\n\t\t\tmManualCheese = 0.0f;\r\n\t\t#ifdef\t\t__DEBUG_CHEESE__\r\n\t\t\tprintf (\"%d:  %.2f:  Cheese decremented\\n\",__LINE__,mManualCheese);\r\n\t\t#endif\t\t\t\t\t\r\n\r\n\t}\r\n//\tprintf(Cheese=%f\\n\",mManualCheese);\r\n\r\n\t// Add in the tweak to the score.\r\n\tMdl::Score *pScore=mpSkaterScoreComponent->GetScore();\r\n\t//pScore->TweakTrickRequest(mTweak);\r\n\tpScore->TweakTrick(mTweak);\r\n\r\n\tmActualManualTime+=frame_length;\r\n\tmManualTime+=frame_length;\r\n\r\n    Obj::CStatsManagerComponent* pStatsManagerComponent = GetStatsManagerComponentFromObject(mpSkater);\r\n\tDbg_Assert( pStatsManagerComponent );\r\n    \r\n    pStatsManagerComponent->CheckTimedRecord( mpSkaterBalanceTrickComponent->mBalanceTrickType, mActualManualTime, false );\r\n\t\r\n\tfloat ManualLeanGravity=mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0x6851748,\"Lean_Gravity_Stat\"));\r\n\tfloat ManualInstableRate=mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0xa9fef5ab,\"Instable_Rate\"));\r\n\tfloat ManualBase = mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0xb6a634f3,\"Instable_base\")); \r\n\tfloat ManualInstability = ManualBase + (mManualTime * ManualInstableRate);\r\n\r\n\t\r\n\t// the more you lean, the more you lean\r\n//\tmManualLean += scale_with_frame_length(mManualLean/ManualLeanGravity * (0.5f + mManualTime/2)/ManualInstableRate);\r\n//\tmManualLean += scale_with_frame_length(mManualLeanDir * (0.5f + mManualTime/2)/ManualInstableRate);\t // speed of turn\r\n\t\r\n\tmManualLean += scale_with_frame_length(frame_length, mManualLean * ManualLeanGravity * ManualInstability);\r\n\tmManualLean += scale_with_frame_length(frame_length, mManualLeanDir * ManualInstability);\t \t\r\n\r\n\r\n\tCSkaterButton *pButt=mpInputComponent->GetControlPad().GetButton(mButtonAChecksum);\r\n\tbool APressed=pButt->GetPressed();\r\n\t\r\n\tpButt=mpInputComponent->GetControlPad().GetButton(mButtonBChecksum);\r\n\tbool BPressed=pButt->GetPressed();\r\n\r\n\t// The released flag stays false until they let go of the buttons. This is so that if the player\r\n\t// was holding one of the control buttons at the instant the balance trick started, as they probably\r\n\t// will be if doing a manual, then the button won't have any effect on the balance, so as not to\r\n\t// unbalance them straight away.\r\n\tif (!APressed && !BPressed)\r\n\t{\r\n\t\tmManualReleased = true;\r\n\t}\r\n\t\r\n\t\r\n\tuint32   safe_period = (uint32)Script::GetInt(CRCD(0x8cc8f176,\"BalanceSafeButtonPeriod\"));\r\n\tuint32\t elapsed_time = Tmr::ElapsedTime(mStartTime);\r\n\r\n\t// If the buttons have not technically been released, but have been held for longer than a certain\r\n\t// amount of time, then assume that the player does want the button to have an effect after all.\r\n\tif (!mManualReleased && elapsed_time>(uint32)Script::GetInt(CRCD(0x7da1621,\"BalanceIgnoreButtonPeriod\")))\r\n\t{\r\n\t\tmManualReleased = true;\r\n\t}\r\n\t\r\n\t\r\n\tif (APressed && mManualReleased)\r\n\t{\r\n\t\t// this ramping up of the accleration for a few hundred miliseconds\r\n\t\t// will prevent us from overcompensating\r\n\t\t// due to the button being held down\r\n\t\t// and will actually make it easier to \"Stick\" the mManualLeanDir\r\n\t\t// the ramping is only in effect if you press in the direction opposite \r\n\t\t// from what you need to get more upright\r\n\t\t// so it prevents you from becoming more unbalanced\r\n\t\tfloat mult = 1.0f;\r\n\t\tif (mManualLean < 0.0f && elapsed_time < safe_period)\r\n\t\t{\r\n\t\t\tmult =  elapsed_time / safe_period; \r\n\t\t}\r\n\t\t\r\n\t\tmManualLeanDir -= scale_with_frame_length(frame_length, mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0x61ad5596,\"Lean_Acc\"))) * mult;\r\n\t}\r\n\telse if (BPressed && mManualReleased)\r\n\t{\r\n\t\tfloat mult = 1.0f;\r\n\t\tif (mManualLean > 0.0f && elapsed_time < safe_period)\r\n\t\t{\r\n\t\t\tmult =  elapsed_time / safe_period; \r\n\t\t}\r\n\t\tmManualLeanDir += scale_with_frame_length(frame_length, mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0x61ad5596,\"Lean_Acc\"))) * mult;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (Mth::Abs(mManualLeanDir) < mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0xef27e8ff,\"Lean_Min_Speed\")))\r\n\t\t{\r\n\t\t\tint r=(int)mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0x32eb3308,\"Lean_Rnd_Speed\"));\r\n\t\t\tr|=1;\r\n//\t\t\tmManualLeanDir = Mth::Rnd(r)-r/2;\r\n\t\t\tmManualLeanDir = Mth::Rnd(r)*Mth::Sgn(mManualLeanDir);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// always add some randomness to it, to make sure we don't ever get stuck\r\n\t\t\tmManualLeanDir += (Mth::Rnd(50))/100.0f * Mth::Sgn(mManualLeanDir);\r\n\t\t}\r\n\t}\r\n\r\n\t\r\n\t/*\r\n\tHUD::PanelMgr* panelMgr = HUD::PanelMgr::Instance();\r\n\tHUD::Panel *pPanel=panelMgr->GetPanelBySkaterId(mpSkater->GetID());\r\n\t\r\n\tchar pBuf[100];\r\n\tsprintf(pBuf,\"Record %.2f\",mMaxTime);\r\n\tpanelMgr->SendConsoleMessage(pBuf, 2);\r\n\tsprintf(pBuf,\"Time %.2f\",mActualManualTime);\r\n\tpanelMgr->SendConsoleMessage(pBuf, 3);\r\n\t*/\r\n\r\n\tif (!mpSkater->GetScript())\r\n\t{\r\n\t\tmpSkater->SetScript(new Script::CScript);\r\n\t}\r\n\r\n\tif (Mth::Abs(mManualLean)>mpSkaterBalanceTrickComponent->GetBalanceStat(CRCD(0xf81ab0e9,\"Lean_Bail_Angle\")))\r\n\t{\r\n\t\tif (mManualLean>0)\r\n\t\t{\r\n\t\t\tmpSkater->SelfEvent(CRCD(0xd77b6ff9,\"OffMeterTop\"));\r\n\t\t}\r\n\t\telse\t\r\n\t\t{\r\n\t\t\tmpSkater->SelfEvent(CRCD(0x47d44b84,\"OffMeterBottom\"));\r\n\t\t}\r\n\r\n\t\tmManualLean=0;\r\n\t\tmpSkaterBalanceTrickComponent->mBalanceTrickType=0;\r\n\t}\t\r\n\r\n\tif (mWobbleEnabled)\r\n\t{\r\n\t\tbool flip=mPlayRangeAnimBackwards;\r\n\t\tif (mDoFlipCheck && GetSkaterCorePhysicsComponentFromObject(mpSkater)->GetFlag(FLIPPED))\r\n\t\t{\r\n\t\t\tflip=!flip;\r\n\t\t}\t\r\n\t\t// Update the anim frame.\r\n\t\tObj::CAnimationComponent* pAnimComponent = GetAnimationComponentFromObject(mpSkater);\r\n        if ( pAnimComponent )\r\n        {\r\n            if (flip)\r\n            {\r\n                pAnimComponent->SetWobbleTarget((-mManualLean+4096)/8192, true);\r\n            }\r\n            else\r\n            {\r\n                pAnimComponent->SetWobbleTarget((mManualLean+4096)/8192, true);\r\n            }\t\t\r\n        }\r\n\t}\t\r\n\r\n\r\n\t// Update the balance meter.\r\n\tGameNet::MsgByteInfo msg;\r\n\tfloat final_val = -mManualLean/4096;\r\n\t\r\n\tif( server && skater_conn )\r\n\t{\r\n\t\tmsg.m_Data = (char) ( final_val * 127.0f );\r\n\t\t/*server->EnqueueMessage( skater_conn->GetHandle(), GameNet::MSG_ID_SET_MANUAL_METER, \r\n\t\t\t\t\t\t\t\tsizeof(GameNet::MsgByteInfo), &msg );*/\r\n\t}\r\n\t\r\n\t// Need to also check we are still doing a balance trick, since exceptions\r\n\t// that we fired above (offmetertop/bottom) might have canceled it\r\n\tif (!mNeverShowMeters && mpSkaterBalanceTrickComponent->mBalanceTrickType)\r\n\t{\r\n\t\tif ((mButtonAChecksum==0xbc6b118f/*Up*/ || mButtonAChecksum==0xe3006fc4/*Down*/) &&\r\n\t\t\t(mButtonBChecksum==0xbc6b118f/*Up*/ || mButtonBChecksum==0xe3006fc4/*Down*/))\r\n\t\t{\r\n\t\t\tif (mpSkaterScoreComponent->GetScore())\r\n\t\t\t{\r\n\t\t\t\tmpSkaterScoreComponent->GetScore()->SetManualMeter( true, final_val );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (mpSkaterScoreComponent->GetScore())\r\n\t\t\t{\r\n\t\t\t\tmpSkaterScoreComponent->GetScore()->SetBalanceMeter( true, final_val );\r\n\t\t\t}\r\n\t\t}\r\n\t}\t \r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/manual.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObject (OBJ)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobjects/manual.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t01/31/01\t-\tksh\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __OBJECTS_MANUAL_H\r\n#define __OBJECTS_MANUAL_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <sys/timer.h>\r\n\r\n#include <gfx/gfxman.h>\r\n\r\n#include <gel/inpman.h>\r\n#include <gel/object.h>\r\n#include <gel/object/compositeobject.h>\r\n\r\n#include <core/math/matrix.h>\r\n#include <core/math/vector.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\nnamespace Obj\r\n{\r\n\tclass CSkaterBalanceTrickComponent;\r\n\tclass CSkaterScoreComponent;\r\n\tclass CInputComponent;\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  CManual  : public Spt::Class\r\n{\r\n\t\r\npublic:\t\t\t\t\t\t\t\t// for debugging\r\n\r\n\tCCompositeObject *mpSkater;\r\n\tCSkaterBalanceTrickComponent* mpSkaterBalanceTrickComponent;\r\n\tCSkaterScoreComponent* mpSkaterScoreComponent;\r\n\tCInputComponent* mpInputComponent;\r\n\t\r\n\tMth::Vector mManualPos;\r\n\tfloat mActualManualTime;\r\n\tfloat mManualTime;\r\n\tfloat mMaxTime;\r\n\t\r\n\tfloat mManualLean;\r\n\tfloat mManualLeanDir;\r\n\tfloat mManualCheese;\r\n\tbool mManualReleased;\r\n\t\r\n\tuint32 mStartTime;\r\n\tuint32 mButtonAChecksum;\r\n\tuint32 mButtonBChecksum;\r\n\t\r\n\tint mTweak;\r\n\t\r\n\tint mOldRailNode;\r\n\t\r\n\tbool mWobbleEnabled;\r\n\tbool mNeverShowMeters;\r\n\r\n\t// If true, then the animation will be moved in the opposite direction\r\n\t// when the skater is flipped.\r\n\t// This is required when the animation moves from side to side as in\r\n\t// the case of most grinds, but not for anims that move forward and\r\n\t// back, such as manuals.\r\n\tbool mDoFlipCheck;\r\n\t\r\n\t// If set, the range anim will be played backwards. Can be used in conjunction with\r\n\t// mDoFlipCheck.\r\n\tbool mPlayRangeAnimBackwards;\r\n\t\t\r\npublic:\r\n\tCManual();\r\n\tvirtual ~CManual();\r\n\t\r\n\tvoid Init ( CCompositeObject *pSkater );\r\n\r\n\tvoid ResetCheese() {mManualCheese=0.0f;}\t\r\n\tvoid Reset();\r\n\tvoid ClearMaxTime();\r\n\tvoid SwitchOffMeters();\r\n\tvoid SwitchOnMeters();\r\n\tvoid Stop();\r\n\tvoid UpdateRecord();\r\n\r\n\tfloat\tGetMaxTime() {return mMaxTime;}\r\n\t\r\n\tvoid SetUp(uint32 ButtonAChecksum, uint32 ButtonBChecksum, int Tweak, bool DoFlipCheck, bool PlayRangeAnimBackwards);\r\n\tvoid EnableWobble();\r\n\tvoid DoManualPhysics();\r\n\t\r\nprivate:\r\n\tinline float scale_with_frame_length ( float frame_length, float f );\r\n\t\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_MANUAL_H\r\n"
  },
  {
    "path": "Code/Sk/Objects/moviecam.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       moviemanager.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  02/07/2002\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/objects/moviecam.h>\r\n\r\n#include <gel/assman/assman.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <gfx/bonedanim.h>\r\n#include <gfx/nxloadscreen.h>\r\n#include <gfx/nxviewman.h>\r\n\r\n#include <sk/modules/frontend/frontend.h>\r\n#include <sk/modules/skate/skate.h>\r\n\r\n#include <sk/objects/cutscenedetails.h>\r\n\r\n// TODO:  Remove dependency on CSkater class...\r\n#include <sk/objects/skater.h>\r\n#include <sk/modules/viewer/viewer.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CMovieManager::get_movie_count()\r\n{\r\n\treturn m_movieDetailsList.CountItems();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMovieDetails* CMovieManager::get_movie_details( int index )\r\n{\r\n\tif ( get_movie_count() == 0 )\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\treturn (CMovieDetails*)m_movieDetailsList.GetItem( index );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMovieDetails* CMovieManager::get_movie_details_by_name( uint32 name )\r\n{\r\n\tfor ( int i = 0; i < get_movie_count(); i++ )\r\n\t{\r\n\t\tCMovieDetails* pDetails = get_movie_details( i );\r\n\t\tDbg_Assert( pDetails );\r\n\t\tif ( pDetails->GetName() == name )\r\n\t\t{\r\n\t\t\treturn pDetails;\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovieManager::setup_last_movie_camera( CMovieDetails* pDetails )\r\n{\r\n\t// Check if this is an overridding camera\r\n\tif ( !( pDetails && pDetails->OverridesCamera() ) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Don't set up if the game is paused or in the skateshop\r\n\tif ( pDetails->NeedsCameraTransition() &&\r\n\t\t !Mdl::FrontEnd::Instance()->GamePaused() &&\r\n\t\t (Mdl::Skate::Instance()->m_cur_level != CRCD(0x9f2bafb7,\"Load_Skateshop\") ) )\r\n\t{\r\n\t\tm_last_movie_camera = *(pDetails->GetCamera());\r\n\t\tm_last_movie_frame = Tmr::GetRenderFrame() + 1;\t\t// End it one frame later so there aren't any glitches\r\n\t\tm_use_last_movie_camera = true;\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tScript::RunScript( CRCD( 0x15674315, \"Restore_skater_camera\" ) );  // Temp patch to get the skater camera back at end of cutscenes\r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMovieManager::CMovieManager()\r\n{\r\n\tm_use_last_movie_camera = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMovieManager::~CMovieManager()\r\n{\r\n\tClearMovieQueue();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGfx::Camera* CMovieManager::GetActiveCamera()\r\n{\r\n\tCMovieDetails* pDetails = get_movie_details( 0 );\r\n\tif ( pDetails && pDetails->OverridesCamera() )\r\n\t{\r\n\t\treturn pDetails->GetCamera();\r\n\t}\r\n\telse if ( m_use_last_movie_camera )\r\n\t{\r\n\t\treturn &m_last_movie_camera;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovieManager::ClearMovieQueue( void )\r\n{\r\n\tif ( !m_movieDetailsList.IsEmpty() )\r\n\t{\r\n\t\tsetup_last_movie_camera( get_movie_details( 0 ) );\r\n\t\t//Script::RunScript( CRCD( 0x15674315, \"Restore_skater_camera\" ) );  // Temp patch to get the skater camera back at end of cutscenes\r\n\t}\r\n\tm_movieDetailsList.DestroyAllNodes();\r\n\t//Dbg_Message(\"Removing all movies\\n\");\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovieManager::CleanupMovie( CMovieDetails* pDetails )\r\n{\r\n\tDbg_MsgAssert( pDetails, ( \"No details?\" ) );\r\n\r\n\t// remember the exit script, for use\r\n\t// after the movie has been removed\r\n\t// from the list\r\n\tuint32 exitScriptName = pDetails->GetExitScriptName();\r\n\tScript::CStruct* pTempExitParams = new Script::CStruct;\r\n\tpTempExitParams->AppendStructure( pDetails->GetExitParams() );\r\n\t\t\t\t\t\t\t\t\t\t  \r\n\t// Check if last movie\r\n\tif (get_movie_count() == 1)\r\n\t{\r\n\t\tsetup_last_movie_camera(pDetails);\r\n\t}\r\n\r\n\tpDetails->Cleanup();\r\n\tpDetails->Remove();\r\n\tdelete pDetails;\r\n\tprintf( \"Details have been removed %ld\\n\", Tmr::GetRenderFrame() );\r\n\t\r\n\t// GJ:  run the exit script AFTER we delete it\r\n\t// need to do it after the details are deleted\r\n\t// in case the exit script affects the camera\r\n\t// somehow (would cause a glitch otherwise)\r\n\tif ( exitScriptName != 0 )\r\n\t{\r\n\t\tScript::RunScript( exitScriptName, pTempExitParams, NULL );\r\n\t}\r\n\r\n\tdelete pTempExitParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieManager::AbortCurrentMovie( bool only_if_skippable )\r\n{\r\n\tbool aborted = false;\r\n\t\r\n\tif ( !only_if_skippable )\r\n\t{\r\n\t\tCMovieDetails* pDetails = get_movie_details( 0 );\r\n\t\tif ( pDetails )\r\n\t\t{\r\n\t\t\tCleanupMovie( pDetails );\r\n\t\t\t\r\n\t\t\taborted = true;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// delete as many skippable movies as there are...\r\n\t\tCMovieDetails* pDetails = get_movie_details( 0 );\r\n\t\twhile ( pDetails && pDetails->IsSkippable() )\r\n\t\t{\r\n\t\t\tCleanupMovie( pDetails );\r\n\t\t\t\r\n\t\t\tpDetails = get_movie_details( 0 );\r\n\t\t\taborted = true;\r\n\t\t}\r\n\t}\r\n\r\n\t// now that a new movie is about to begin,\r\n\t// reset its custom keys\r\n\tCMovieDetails* pDetails = get_movie_details( 0 );\r\n\tif ( pDetails )\r\n\t{\r\n\t\tpDetails->ResetCustomKeys();\r\n\t}\r\n\r\n\t// restore skater cam\r\n\t// Nx::CViewportManager::sSetCamera( 0, Mdl::Skate::Instance()->GetSkater(0)->GetCamera() );\r\n\r\n\t// if there are no more movies, then restore the camera\r\n//\tif (aborted)  <-- causes one frame glitch with queued up cameras\r\n\tif ( !aborted && (get_movie_count() == 0) )\r\n\t{\r\n//\t\tScript::RunScript(CRCD(0x15674315, \"Restore_skater_camera\"));\t\t// Temp pathc to get the skater camera back at end of cutscenes\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieManager::SetMovieSkippable( uint32 name, bool skippable )\r\n{\r\n\tif ( m_movieDetailsList.CountItems() == 0 )\r\n\t{\r\n\t\t// no movies in the queue\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif ( name == 0 )\r\n\t{\r\n\t\t// no name specified, so set the current movie\r\n\t\tCMovieDetails* pDetails = get_movie_details( 0 );\r\n\t\tDbg_Assert( pDetails );\r\n\t\tpDetails->SetSkippable( skippable );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// a name was specified, so only do this movie\r\n\t\tCMovieDetails* pDetails = get_movie_details_by_name( name );\r\n\t\tif ( pDetails )\r\n\t\t{\r\n\t\t\tpDetails->SetSkippable( skippable );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Movie to skip (%s) not found\\n\", Script::FindChecksumName(name) ) );\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieManager::SetMoviePauseMode( uint32 name, bool pause_mode )\r\n{\r\n\tif ( m_movieDetailsList.CountItems() == 0 )\r\n\t{\r\n\t\t// no movies in the queue\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif ( name == 0 )\r\n\t{\r\n\t\t// no name specified, so set the current movie\r\n\t\tCMovieDetails* pDetails = get_movie_details( 0 );\r\n\t\tDbg_Assert( pDetails );\r\n\t\tpDetails->SetPauseMode( pause_mode );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// a name was specified, so only do this movie\r\n\t\tCMovieDetails* pDetails = get_movie_details_by_name( name );\r\n\t\tif ( pDetails )\r\n\t\t{\r\n\t\t\tpDetails->SetPauseMode( pause_mode );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Movie to set pause mode (%s) not found\\n\", Script::FindChecksumName(name) ) );\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieManager::IsMovieComplete( uint32 name )\r\n{\r\n\tif ( get_movie_count() == 0 )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif ( name != 0 )\r\n\t{\r\n\t\tif ( get_movie_details_by_name( name ) )\r\n\t\t{\r\n\t\t\t// the movie still exists in the queue,\r\n\t\t\t// so it's obviously not done yet\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieManager::IsMovieHeld( uint32 name )\r\n{\r\n\tif ( m_movieDetailsList.CountItems() == 0 )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif ( name != 0 )\r\n\t{\r\n\t\tCMovieDetails* pDetails = get_movie_details_by_name( name );\r\n\t\t\r\n\t\tif ( pDetails )\r\n\t\t{\r\n\t\t\treturn pDetails->IsHeld();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// movie not found in list!\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCMovieDetails* pDetails = get_movie_details( 0 );\r\n\t\tDbg_Assert( pDetails );\r\n\t\treturn pDetails->IsHeld();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieManager::RemoveMovieFromQueue( uint32 name )\r\n{\r\n\tCMovieDetails* pDetails = get_movie_details_by_name( name );\r\n\r\n\tif ( pDetails )\r\n\t{\r\n\t\tif ( pDetails == get_movie_details( 0 ) )\r\n\t\t{\r\n\t\t\t// first movie?  then just abort current\r\n\t\t\tAbortCurrentMovie( false );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Message( \"Removing %s from movie queue\", Script::FindChecksumName(name) );\r\n\t\t\tpDetails->Remove();\r\n\t\t\tdelete pDetails;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\r\n\t//Dbg_Message( \"RemoveMovieFromQueue:  Movie %s not found.\", Script::FindChecksumName(name) );\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieManager::AddMovieToQueue( uint32 name, Script::CStruct* pParams, uint32 movieType )\r\n{\r\n\tCMovieDetails* pDetails = NULL;\r\n\r\n    bool old_last_movie_camera = m_use_last_movie_camera;\r\n\r\n\t// GJ:  a new camera has been queued up, so don't need\r\n\t// to do anything special to fix the 1-frame glitch\r\n\t// (otherwise, some of the cutscenes will have the\r\n\t// wrong camera for the first frame...)  must be done before\r\n\t// the cutscenedetails constructor, which updates the model component,\r\n\t// which contains a check for \"IsRolling\"\r\n\tm_use_last_movie_camera = false;\r\n\r\n\tswitch ( movieType )\r\n\t{\r\n\t\tcase 0xf5012f52: // cutscene\r\n\t\t\t\r\n\t\t\t// check for multiple movies in the queue\r\n\t\t\tif ( get_movie_count() != 0 )\r\n\t\t\t{\r\n\t\t\t\tfor ( int i = 0; i < get_movie_count(); i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tCMovieDetails* pDetails = get_movie_details( i );\r\n\t\t\t\t\tif ( pDetails->GetName() == CRCD(0xf5012f52,\"cutscene\") )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// GJ:  theoretically, we should be able to just clear the movie queue\r\n\t\t\t\t\t\t// to get rid of the extra cutscene, but i suspect that there will be\r\n\t\t\t\t\t\t// problems with cleanup, and that it would be too risky to do\r\n\t\t\t\t\t\t// that so close to the end of the project...\r\n\t\t\t\t\t\tDbg_MsgAssert( 0, ( \"Cutscenes should not be queued (only 1 cutscene at a time, please)\" ) );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t// if we've currently got skatercamanims in the queue,\r\n\t\t\t\t// then trash them...  (due to the convoluted level\r\n\t\t\t\t// loading process, it's possible for a skatercamanim\r\n\t\t\t\t// to be launched on the same frame as a cutscene;\r\n\t\t\t\t// in this case, we want the cutscene to take\r\n\t\t\t\t// precedence)\r\n\t\t\t\tClearMovieQueue();\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t// we should set this to false, since\r\n\t\t\t\t// we know we're about to add a new movie\r\n\t\t\t\t// in a moment anyway.  (otherwise, modelcomponent\r\n\t\t\t\t// will assert because it doesn't expect the\r\n\t\t\t\t// cutscene camera to be active...\r\n\t\t\t\tm_use_last_movie_camera = false;\r\n\t\t\t}\r\n\r\n\t\t\t{\r\n\t\t\t\t// fix 1-frame glitch with a loading screen here...\r\n\t\t\t\tchar* pFileName = NULL;\r\n\t\t\t\tbool freeze = true;\r\n\t\t\t\tbool blank = false;\r\n\t\t\t\tNx::CLoadScreen::sDisplay( pFileName, freeze, blank );\r\n\t\t\t}\t\t\t\t\t\t\t\t\t\t  \r\n\r\n\t\t\tpDetails = new CCutsceneDetails;\r\n\t\t\tDbg_Message( \"Trying to create new cutscene\" );\r\n\t\t\tbreak;\r\n\t\tcase 0x12743edb: // objectanim\r\n\t\t\tpDetails = new CObjectAnimDetails;\r\n\t\t\tDbg_Message( \"Trying to create new object anim\" );\r\n\t\t\tbreak;\r\n\t\tcase 0x66b7dd11: // skatercamanim\r\n\t\t\tpDetails = new CSkaterCamDetails;\r\n\t\t\tDbg_Message( \"Trying to create new skater cam anim\" );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Unrecognized movie type %s\", Script::FindChecksumName(movieType) ) );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tDbg_Assert( pDetails );\r\n\r\n\tpDetails->SetName( name );\r\n\r\n\tif ( !pDetails->InitFromStructure( pParams ) )\r\n\t{\r\n\t\t// failed\r\n\t\tdelete pDetails;\r\n\r\n\t\t// restore the old \"last movie camera\" flag\r\n\t\tm_use_last_movie_camera = old_last_movie_camera;\r\n\t\t\r\n\t\treturn false;\r\n\t}\r\n\r\n\tm_movieDetailsList.AddToTail( pDetails );\r\n\t//Dbg_Message(\"Adding a movie on frame %ld.  Count now %d\\n\", Tmr::GetRenderFrame(), get_movie_count());\r\n\r\n\t// GJ:  if it's the first movie in the queue,\r\n\t// then set the correct camera (to prevent\r\n\t// one frame glitch between movies)\r\n\tif ( get_movie_count() == 1 )\r\n\t{\r\n\t\tNx::CViewportManager::sSetCamera( 0, this->GetActiveCamera() );\r\n\t}\r\n\r\n\t// TODO:  Support the following parameters\r\n//\tpDetails->SetTarget( Obj::MovingObject* pObject );\t\r\n//\tpDetails->SetFocusSkater( pParams->ContainsFlag(\"focus_skater\") );\r\n//\tpDetails->SetFocusTarget( pParams->ContainsFlag(\"focus_target\") );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovieManager::ApplyLastCamera()\r\n{\r\n   \tNx::CViewportManager::sSetCamera( 0, &m_last_movie_camera );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieManager::Update()\r\n{\r\n\t// Clear out old camera if we advanced a frame\r\n\tif (m_use_last_movie_camera && (m_last_movie_frame <= Tmr::GetRenderFrame()))\r\n\t{\r\n\t\t//Dbg_Message(\"Turning off camera on frame %d\", Tmr::GetRenderFrame());\r\n\t\tm_use_last_movie_camera = false;\r\n\r\n\t\tif ( get_movie_count() == 0 )\r\n\t\t{\r\n//\t\t\tScript::RunScript(CRCD(0x15674315, \"Restore_skater_camera\"));\t\t// Temp pathc to get the skater camera back at end of cutscenes\r\n\t\t}\r\n\t}\r\n\r\n\tCMovieDetails* pDetails = get_movie_details( 0 );\r\n\r\n\t// there are no movies in the queue,\r\n\t// so return \"no movies\" code\r\n\t// (the camera manager should then immediately\r\n\t// pass control back to the skater cam)\r\n\tif ( !pDetails )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n#if 0\r\n\tprintf( \"Movie manager update %d:\\n\", get_movie_count() );\r\n\tfor ( int i = 0; i < get_movie_count(); i++ )\r\n\t{\r\n\t\tprintf( \"\\tmovie name = %s\\n\", Script::FindChecksumName(get_movie_details(i)->GetName()) );\r\n\t}\r\n#endif\r\n\t\r\n\tif ( Mdl::FrontEnd::Instance()->GamePaused() && ( Mdl::CViewer::sGetViewMode() == 0 ) )\r\n\t{\r\n\t\t// printf(\"game is paused in normal view mode\\n\");\r\n\t\tif ( !pDetails->ShouldPauseMovie() )\r\n\t\t{\r\n\t\t\tpDetails->Update();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// printf(\"view mode is not normal\\n\");\r\n\t\tpDetails->Update();\r\n\t}\r\n\t\t\r\n\t// if the animation is done,\r\n\t// the remove it from the list\r\n\tif ( pDetails->IsComplete() )\r\n\t{\r\n\t\t// TODO:  run callback function if necessary?\r\n\r\n\t\tAbortCurrentMovie( false );\r\n\t}\r\n\r\n\treturn ( get_movie_count() != 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* CMovieManager::GetMovieParams( uint32 name )\r\n{\r\n\tif ( m_movieDetailsList.CountItems() == 0 )\r\n\t{\r\n\t\t// no movies in the queue\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tif ( name == 0 )\r\n\t{\r\n\t\t// no name specified, so set the current movie\r\n\t\tCMovieDetails* pDetails = get_movie_details( 0 );\r\n\t\tDbg_Assert( pDetails );\r\n\t\tif ( pDetails )\r\n\t\t\treturn pDetails->GetParams();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// a name was specified, so only do this movie\r\n\t\tCMovieDetails* pDetails = get_movie_details_by_name( name );\r\n\t\tif ( pDetails )\r\n\t\t\treturn pDetails->GetParams();\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieManager::CallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tCMovieDetails* pDetails = get_movie_details( 0 );\r\n\tDbg_MsgAssert( pDetails, (\"No current movie?\") );\r\n\tbool success = pDetails->CallMemberFunction( checksum, pParams, pScript );\r\n\tif ( success )\r\n\t{\r\n\t\treturn success;\r\n\t}\r\n\r\n\treturn Obj::CObject::CallMemberFunction( checksum, pParams, pScript );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieManager::OverridesCamera()\r\n{\r\n\tCMovieDetails* pDetails = get_movie_details( 0 );\r\n\r\n\tif ( pDetails )\r\n\t{\r\n\t\treturn pDetails->OverridesCamera();\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CMovieManager::GetCurrentMovieName()\r\n{\r\n\tCMovieDetails* pDetails = get_movie_details( 0 );\r\n\r\n\tif ( pDetails )\r\n\t{\r\n\t\treturn pDetails->GetName();\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieManager::HasMovieStarted()\r\n{\r\n\tCMovieDetails* pDetails = get_movie_details( 0 );\r\n\r\n\tif ( pDetails )\r\n\t{\r\n\t\treturn pDetails->HasMovieStarted();\r\n\t}\r\n\r\n\tDbg_MsgAssert( 0, ( \"Shouldn't call this without knowing there's a movie queued %d\", get_movie_count() ) );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieManager::IsMovieQueued()\r\n{\r\n\treturn ( get_movie_count() != 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n"
  },
  {
    "path": "Code/Sk/Objects/moviecam.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       moviemanager.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  02/07/2002\r\n//****************************************************************************\r\n\r\n#ifndef __OBJECTS_MOVIEMANAGER_H\r\n#define __OBJECTS_MOVIEMANAGER_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <core/list.h>\r\n\r\n#include <gel/object.h>\r\n\r\n#include <gfx/camera.h>\r\n\r\n#include <sk/objects/moviedetails.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Script\r\n{\r\n\tclass CScript;\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// CMovieManager\r\nclass CMovieManager : public Obj::CObject\r\n{\r\n\tpublic:\r\n\tCMovieManager();\r\n\tvirtual\t\t\t~CMovieManager();\r\n\r\npublic:\r\n\tvirtual bool\t\t\t\tUpdate();\r\n\tvoid\t\t\t\t\t\tClearMovieQueue();\r\n\tbool\t\t\t\t\t\tAddMovieToQueue( uint32 name, Script::CStruct* pParams, uint32 movieType );\r\n\tbool\t\t\t\t\t\tRemoveMovieFromQueue( uint32 name );\r\n\tvoid\t\t\t\t\t\tApplyLastCamera();\r\n\tbool\t\t\t\t\t\tSetMovieSkippable( uint32 name, bool skippable );\r\n\tbool\t\t\t\t\t\tSetMoviePauseMode( uint32 name, bool pause_mode );\r\n\tScript::CStruct*\t\t\tGetMovieParams( uint32 name );\r\n\tbool\t\t\t\t\t\tAbortCurrentMovie( bool only_if_skippable );\r\n\tbool\t\t\t\t\t\tIsMovieComplete( uint32 name );\r\n\tbool\t\t\t\t\t\tIsMovieHeld( uint32 name );\r\n\tbool\t\t\t\t\t\tIsRolling() { return ( get_movie_count() != 0 ); }// || m_use_last_movie_camera;}\r\n\tbool\t\t\t\t\t\tOverridesCamera();\r\n\tGfx::Camera*\t\t\t\tGetActiveCamera();\r\n\tuint32\t\t\t\t\t\tGetCurrentMovieName();\r\n\tvoid\t\t\t\t\t\tCleanupMovie( CMovieDetails* pMovieDetails );\r\n\tbool\t\t\t\t\t\tHasMovieStarted();\r\n\tbool\t\t\t\t\t\tIsMovieQueued();\r\n\r\npublic:\r\n\tbool\t\t\t\t\t\tCallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript ); \r\n\r\nprotected:\r\n\tint\t\t\t\t\t\t\tget_movie_count();\r\n\tCMovieDetails*\t\t\t\tget_movie_details( int index );\r\n\tCMovieDetails*\t\t\t\tget_movie_details_by_name( uint32 name );\r\n\tvoid\t\t\t\t\t\tupdate_movie_frame();\r\n\tvoid\t\t\t\t\t\tsetup_last_movie_camera( CMovieDetails* pDetails );\r\n\r\nprotected:\r\n\tLst::Head<CMovieDetails>\tm_movieDetailsList;\r\n\r\n\t// Currently, when we switch movie cameras, we delete the old one before adding\r\n\t// a new one.  Because the new one isn't added until a frame later, we need the\r\n\t// ability to have a smooth transition.  So we keep the old camera around for\r\n\t// an extra frame.\r\n\t// In the future, this code should go away and the cameras should be switched\r\n\t// at the same time.\r\n\tGfx::Camera\t\t\t\t\tm_last_movie_camera;\r\n\tuint32\t\t\t\t\t\tm_last_movie_frame;\r\n\tbool\t\t\t\t\t\tm_use_last_movie_camera;\r\n};\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_MOVIEMANAGER_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/moviedetails.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       moviedetails.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  06/17/2002\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/objects/moviedetails.h>\r\n\r\n#include <gel/components/modelcomponent.h>\r\n\t\t\t\t\t\t\t\t\r\n#include <gfx/bonedanim.h>\r\n#include <gfx/camera.h>\r\n#include <gfx/nxviewman.h>\r\n\r\n#include <gel/assman/assman.h>\r\n#include <gel/objman.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <gel/object/compositeobject.h>\r\n\r\n#include <gfx/skeleton.h>\r\n\r\n#include <sk/modules/FrontEnd/FrontEnd.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMovieDetails::CMovieDetails() : Lst::Node<CMovieDetails>( this )\r\n{\r\n\tmp_exitParams = NULL;\r\n\r\n\t// defaults to not skippable\r\n\tm_skippable = false;\r\n\tm_holdOnLastFrame = false;\r\n\r\n\tm_allowPause = false;\r\n\r\n\tmp_camera = new Gfx::Camera;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCMovieDetails::~CMovieDetails()\r\n{\r\n\tif ( mp_exitParams )\r\n\t{\r\n\t\tdelete mp_exitParams;\r\n\t}\r\n   \r\n\tif ( mp_camera )\r\n\t{\r\n\t\tif (!Nx::CViewportManager::sMarkCameraForDeletion(mp_camera))\r\n\t\t{\r\n\t\t\tdelete mp_camera;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovieDetails::SetParams( Script::CStruct* pParams )\r\n{\r\n\tDbg_Assert( pParams );\r\n\r\n\tDbg_MsgAssert( m_exitScript == 0, ( \"exit script was already assigned to %s\", Script::FindChecksumName( m_name ) ) );\r\n\r\n\tif ( !mp_exitParams )\r\n\t{\r\n\t\tmp_exitParams = new Script::CStruct;\r\n\t}\r\n\r\n\tmp_exitParams->Clear();\r\n\r\n\tif ( pParams->GetChecksum( CRCD(0x1a005041,\"exitScript\"), &m_exitScript, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tScript::CStruct* pSubParams = NULL;\r\n\t\tif ( pParams->GetStructure( CRCD(0x894fd988,\"exitParams\"), &pSubParams, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tmp_exitParams->AppendStructure( pSubParams );\r\n\t\t}\r\n\t}\r\n\r\n\tint skippable = 0;\r\n\tpParams->GetInteger( CRCD(0x8dde72c0,\"skippable\"), &skippable, Script::NO_ASSERT );\r\n\tm_skippable = skippable;\r\n\r\n\t// if we want the movie to continue to hold on the last frame (i.e. don't go on to the next anim)\r\n\tm_holdOnLastFrame = pParams->ContainsFlag( CRCD(0xeb300c29,\"play_hold\") );\r\n\r\n\tint allow_pause = 0;\r\n\tpParams->GetInteger( CRCD(0xb8ca12c5,\"allow_pause\"), &allow_pause, Script::NO_ASSERT );\r\n\tm_allowPause = ( allow_pause != 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* CMovieDetails::GetParams()\r\n{\r\n\tScript::CStruct* pReturnParams = new Script::CStruct();\r\n\tpReturnParams->AddInteger( CRCD(0x8dde72c0,\"skippable\"), m_skippable );\r\n\tpReturnParams->AddInteger( CRCD(0xb8ca12c5,\"allow_pause\"), m_allowPause );\r\n\treturn pReturnParams;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CMovieDetails::Cleanup()\r\n{\r\n\t// run the exit script\r\n\r\n//\tif ( m_exitScript != 0 )\r\n\t{\r\n//\t\tDbg_Message( \"Running exit script (%s)\\n\", Script::FindChecksumName(m_exitScript) );\r\n\r\n//\t\tScript::RunScript( m_exitScript, mp_exitParams, NULL );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieDetails::Abort( bool only_if_skippable )\r\n{\r\n\tif ( !only_if_skippable )\r\n\t{\r\n\t\tm_aborted = true;\r\n\t}\r\n\tif ( m_skippable )\r\n\t{\r\n\t\tm_aborted = true;\r\n\t}\r\n\r\n\treturn m_aborted;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieDetails::SetSkippable( bool skippable )\r\n{\r\n\tm_skippable = skippable;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieDetails::SetPauseMode( bool pause_mode )\r\n{\r\n\tm_shouldPause = pause_mode;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieDetails::SetName( uint32 name )\r\n{\r\n\tm_name = name;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32 CMovieDetails::GetName()\r\n{\r\n\treturn m_name;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CMovieDetails::CallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCObjectAnimDetails::CObjectAnimDetails() : CMovieDetails()\r\n{\r\n//\tGfx::CBonedAnimFrameData*\tmp_frameData;\r\n\t\r\n\tmp_frameData = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCObjectAnimDetails::~CObjectAnimDetails()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CObjectAnimDetails::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tthis->SetParams( pParams );\r\n\r\n\tif ( !pParams->ContainsFlag( CRCD(0xee721991,\"virtual_cam\") ) )\r\n\t{\r\n\t\tAss::CAssMan* ass_man = Ass::CAssMan::Instance();\r\n\t\tGfx::CBonedAnimFrameData* pData = (Gfx::CBonedAnimFrameData*)ass_man->GetAsset( this->GetName(), false );\r\n\t\tif ( !pData )\r\n\t\t{\r\n\t\t\tDbg_Message( \"Warning: couldn't find movie with name %s\", Script::FindChecksumName( this->GetName() ) );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\r\n\t\tthis->set_frame_data( pData, \r\n\t\t\t\t\t\t\tpParams->ContainsFlag( CRCD(0x5ea0e211,\"loop\") ) ? Gfx::LOOPING_CYCLE : Gfx::LOOPING_HOLD,\r\n\t\t\t\t\t\t\tpParams->ContainsFlag( CRCD(0xf8cfd515,\"backwards\") ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint numFrames = 0;\r\n\t\tpParams->GetInteger( CRCD(0x019176c5,\"frames\"), &numFrames, Script::ASSERT );\r\n\t\tthis->set_movie_length( numFrames / 60.0f );\r\n\t}\r\n\r\n\t// by default, pause movie when game is paused \r\n\tthis->SetPauseMode( true );\r\n\t   \r\n\t// now that the new movie is about to start,\r\n\t// reset all of its custom keys\r\n\tthis->ResetCustomKeys();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CObjectAnimDetails::Update()\r\n{\r\n\tupdate_moving_objects();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CObjectAnimDetails::set_frame_data( Gfx::CBonedAnimFrameData* pFrameData, Gfx::EAnimLoopingType loopingType, bool reverse )\r\n{\r\n\tDbg_Assert( pFrameData );\r\n\r\n\tmp_frameData = pFrameData;\r\n\r\n\tif ( !reverse )\r\n\t{\r\n\t\tm_animController.PlaySequence( 0, 0.0f, pFrameData->GetDuration(), loopingType, 0.0f, 1.0f );\r\n\t}\r\n\telse\r\n\t{\r\n// 26Mar03 JCB - When playing backwards, start on the final frame, not beyond the end of the anim.\r\n//\r\n//\t\tm_animController.PlaySequence( 0, pFrameData->GetDuration(), 0.0f, loopingType, 0.0f, 1.0f );\r\n\t\tm_animController.PlaySequence( 0, pFrameData->GetDuration() - (1.0f/60.0f), 0.0f, loopingType, 0.0f, 1.0f );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CObjectAnimDetails::set_movie_length( float duration )\r\n{\r\n\tmp_frameData = NULL;\r\n\r\n\tm_animController.PlaySequence( 0, 0.0f, duration, Gfx::LOOPING_HOLD, 0.0f, 1.0f );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CObjectAnimDetails::ResetCustomKeys()\r\n{\r\n\t// eventually, this will go in the decompressed version of the\r\n\t// frame data, rather than the frame data itself...\r\n\tif ( mp_frameData )\r\n\t{\r\n\t\tmp_frameData->ResetCustomKeys();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CObjectAnimDetails::process_custom_keys(float startTime, float endTime, bool end_time_inclusive)\r\n{\r\n\t// This code currently assumes that you're not going to pause the\r\n\t// camera.  If so, then you run the risk of calling these user keys\r\n\t// more than once...\r\n\r\n\t// TODO:  Handle this gracefully!\r\n\r\n\tif ( mp_frameData )\r\n\t{\r\n\t\tDbg_Assert( mp_camera );\r\n\r\n\t\t// It depends on the direction also...\r\n\t\tmp_frameData->ProcessCustomKeys( startTime, endTime, mp_camera, end_time_inclusive );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CObjectAnimDetails::update_moving_objects()\r\n{\r\n\tfloat oldTime = m_animController.GetCurrentAnimTime();\r\n\r\n\tm_animController.Update();\r\n\t\r\n\t// Print out some useful information...\r\n\t//if ( Script::GetInt( CRCD(0x2f510f45,\"moviecam_debug\"), false ) )\r\n\t{\r\n\t\t//Dbg_Message( \"Moving object anim %s @ %f seconds (%d frames)\", Script::FindChecksumName(m_name), m_animController.GetCurrentAnimTime(), (int)(m_animController.GetCurrentAnimTime() * 60.0f) );\r\n\t}\r\n\r\n\t// process associated keys since last frame\r\n\tprocess_custom_keys( oldTime, m_animController.GetCurrentAnimTime(), false );\r\n\r\n\tMth::Quat* pQuat = new Mth::Quat[mp_frameData->GetNumBones()];\r\n\tMth::Vector* pVector = new Mth::Vector[mp_frameData->GetNumBones()];\r\n\tmp_frameData->GetInterpolatedCameraFrames( pQuat, pVector, m_animController.GetCurrentAnimTime() );\r\n\r\n\t// get the position of each bone\r\n\tfor ( int i = 0; i < mp_frameData->GetNumBones(); i++ )\r\n\t{\r\n\t\t// grab the frame from the animation controller\r\n\t\tDbg_Assert( mp_frameData );\r\n\t\t\r\n\t\tuint32 objName;\r\n\t\tobjName = mp_frameData->GetBoneName( i );\r\n\r\n\t\tObj::CObject* pObject = Obj::ResolveToObject( objName );\r\n\t\tDbg_MsgAssert( pObject, ( \"Can't find lookup target %s\", Script::FindChecksumName( objName ) ) );\r\n\t\tif ( pObject )\r\n\t\t{\r\n\t\t\tObj::CCompositeObject* pCompositeObject = (Obj::CCompositeObject*)pObject;\r\n\r\n\t\t\t// update the object's orientation\r\n\t\t\tMth::Matrix theMatrix;\r\n\t\t\t\r\n\t\t\tMth::Vector nullTrans;\r\n\t\t\tnullTrans.Set(0.0f,0.0f,0.0f,1.0f);\t\t// Mick: added separate initialization\r\n\t\t\tMth::QuatVecToMatrix( pQuat + i, &nullTrans, &theMatrix );\r\n\t\t\t\r\n\t\t\tpCompositeObject->SetMatrix( theMatrix );\r\n\t\t\tpCompositeObject->SetDisplayMatrix( theMatrix );\r\n\r\n\t\t\t// update the object's position\r\n\t\t\tpCompositeObject->m_pos = pVector[i];\r\n\r\n\t\t\tif ( Script::GetInt( CRCD(0x2f510f45,\"moviecam_debug\") ) )\r\n\t\t\t{\r\n\t\t\t\tprintf( \"Object %s @ time %f:  \", Script::FindChecksumName(objName), m_animController.GetCurrentAnimTime() );\r\n\t\t\t\tpCompositeObject->m_pos.PrintContents();\r\n\t\t\t\tpCompositeObject->m_matrix.PrintContents();\r\n\t\t\t}\r\n\t\t\r\n\t\t\t// if we want to change the position/rotation,\r\n\t\t\t// then we also need to update the model component\r\n\t\t\tCModelComponent* pModelComponent = GetModelComponentFromObject( pCompositeObject );\r\n\t\t\tif ( pModelComponent )\r\n\t\t\t{\r\n\t\t\t\tpModelComponent->Update();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tprintf( \"object animation:  couldn't find object %s\\n\", Script::FindChecksumName(objName) );\r\n\t\t}\r\n\t}\r\n\t\r\n\tdelete[] pQuat;\r\n\tdelete[] pVector;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CObjectAnimDetails::IsComplete()\r\n{\r\n\tif ( m_aborted )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif ( m_holdOnLastFrame )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn m_animController.IsAnimComplete();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CObjectAnimDetails::IsHeld()\r\n{\r\n\t/* Added by Ken. Used to determine when camera anims used in\t  */\r\n\t/* the skate shop front-end have got to their last frame, so that */\r\n\t/* scripts can trigger things to happen such as the video menu    */\r\n\t/* making the video cassettes pan out to the foreground.          */\r\n\t\r\n\treturn ( m_holdOnLastFrame && m_animController.IsAnimComplete() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CObjectAnimDetails::OverridesCamera()\r\n{\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterCamDetails::CSkaterCamDetails() : CMovieDetails()\r\n{\r\n\tmp_frameData = NULL;\r\n\t\r\n\t// defaults to no target\r\n\tm_hasTarget = false;\r\n\tm_targetID = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterCamDetails::~CSkaterCamDetails()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCamDetails::InitFromStructure( Script::CStruct* pParams )\r\n{\r\n\tthis->SetParams( pParams );\r\n\r\n\tif ( !pParams->ContainsFlag( CRCD(0xee721991,\"virtual_cam\") ) )\r\n\t{\r\n\t\tAss::CAssMan* ass_man = Ass::CAssMan::Instance();\r\n\t\tGfx::CBonedAnimFrameData* pData = (Gfx::CBonedAnimFrameData*)ass_man->GetAsset( this->GetName(), false );\r\n\t\tif ( !pData )\r\n\t\t{\r\n\t\t\tDbg_Message( \"Warning: couldn't find movie with name %s\", Script::FindChecksumName( this->GetName() ) );\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\r\n\t\tthis->set_frame_data( pData, \r\n\t\t\t\t\t\t\tpParams->ContainsFlag( CRCD(0x5ea0e211,\"loop\") ) ? Gfx::LOOPING_CYCLE : Gfx::LOOPING_HOLD,\r\n\t\t\t\t\t\t\tpParams->ContainsFlag( CRCD(0xf8cfd515,\"backwards\") ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint numFrames = 0;\r\n\t\tpParams->GetInteger( CRCD(0x019176c5,\"frames\"), &numFrames, Script::ASSERT );\r\n\t\tthis->set_movie_length( numFrames / 60.0f );\r\n\t}\r\n\r\n\t// by default, pause movie when game is paused \r\n\tthis->SetPauseMode( true );\r\n\t   \r\n\t// look for target parameters\r\n\tthis->set_target_params( pParams );\r\n\t\r\n\t// now that the new movie is about to start,\r\n\t// reset all of its custom keys\r\n\tthis->ResetCustomKeys();\r\n\r\n\tupdate_camera();\r\n\r\n\t// process initial keys, end time inclusive...\r\n\t// this to fix an FOV glitch on the first frame\r\n\tprocess_custom_keys( m_animController.GetCurrentAnimTime(), m_animController.GetCurrentAnimTime(), true );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCamDetails::Update()\r\n{\r\n\tupdate_camera_time();\r\n\r\n\tupdate_camera();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCamDetails::set_target_params( Script::CStruct* pParams )\r\n{\r\n\tDbg_Assert( pParams );\r\n\r\n\tm_hasTarget = pParams->GetChecksum( CRCD(0x531e4d28,\"targetID\"), &m_targetID, Script::NO_ASSERT );\r\n\t\r\n\tif ( m_hasTarget )\r\n\t{\r\n\t\t// target offset, if any\r\n\t\tm_targetOffset.Set(0.0f,0.0f,0.0f);\r\n\t\tpParams->GetVector( CRCD(0x906642bf,\"targetOffset\"), &m_targetOffset, Script::NO_ASSERT );\r\n\t\tm_hasTargetOffset = ( m_targetOffset[X] != 0.0f || m_targetOffset[Y] != 0.0f || m_targetOffset[Z] != 0.0f );\r\n\r\n\t\t// position offset, if any\r\n\t\tm_positionOffset.Set(0.0f,0.0f,0.0f);\r\n\t\tm_hasPositionOffset = pParams->GetVector( CRCD(0xa00d3d6e,\"positionOffset\"), &m_positionOffset, Script::NO_ASSERT );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCamDetails::clear_target_params()\r\n{\r\n\tm_hasTarget = false;\r\n\tm_targetID = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCamDetails::set_frame_data( Gfx::CBonedAnimFrameData* pFrameData, Gfx::EAnimLoopingType loopingType, bool reverse )\r\n{\r\n\tDbg_Assert( pFrameData );\r\n\r\n\tmp_frameData = pFrameData;\r\n\r\n\tif ( !reverse )\r\n\t{\r\n\t\tm_animController.PlaySequence( 0, 0.0f, pFrameData->GetDuration(), loopingType, 0.0f, 1.0f );\r\n\t}\r\n\telse\r\n\t{\r\n// 26Mar03 JCB - When playing backwards, start on the final frame, not beyond the end of the anim.\r\n//\r\n//\t\tm_animController.PlaySequence( 0, pFrameData->GetDuration(), 0.0f, loopingType, 0.0f, 1.0f );\r\n\t\tm_animController.PlaySequence( 0, pFrameData->GetDuration() - (1.0f/60.0f), 0.0f, loopingType, 0.0f, 1.0f );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCamDetails::set_movie_length( float duration )\r\n{\r\n\tmp_frameData = NULL;\r\n\r\n\tm_animController.PlaySequence( 0, 0.0f, duration, Gfx::LOOPING_HOLD, 0.0f, 1.0f );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCamDetails::ResetCustomKeys()\r\n{\r\n\t// eventually, this will go in the decompressed version of the\r\n\t// frame data, rather than the frame data itself...\r\n\tif ( mp_frameData )\r\n\t{\r\n\t\tmp_frameData->ResetCustomKeys();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCamDetails::get_current_frame(Mth::Quat* pQuat, Mth::Vector* pTrans)\r\n{\r\n\tDbg_Assert( pQuat );\r\n\tDbg_Assert( pTrans );\r\n\r\n\t// grab the frame from the animation controller\r\n\tDbg_Assert( mp_frameData );\r\n\tDbg_Assert( mp_frameData->GetNumBones() == 1 );\r\n\tmp_frameData->GetInterpolatedCameraFrames( pQuat, pTrans, m_animController.GetCurrentAnimTime() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCamDetails::process_custom_keys(float startTime, float endTime, bool end_time_inclusive)\r\n{\r\n\t// This code currently assumes that you're not going to pause the\r\n\t// camera.  If so, then you run the risk of calling these user keys\r\n\t// more than once...\r\n\r\n\t// TODO:  Handle this gracefully!\r\n\r\n\tif ( mp_frameData )\r\n\t{\r\n\t\tDbg_Assert( mp_camera );\r\n\r\n\t\t// It depends on the direction also...\r\n\t\tmp_frameData->ProcessCustomKeys( startTime, endTime, mp_camera, end_time_inclusive );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCamDetails::update_camera_time()\r\n{\r\n\tfloat oldTime = m_animController.GetCurrentAnimTime();\r\n\r\n\tm_animController.Update();\r\n\r\n\t// Not sure if this is still needed for the sound code\r\n\t// Maybe we can add the functionality automatically to the Gfx::Camera?\r\n\tmp_camera->StoreOldPos();\r\n\t\r\n\t// process associated keys since last frame\r\n\tprocess_custom_keys( oldTime, m_animController.GetCurrentAnimTime(), false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCamDetails::update_camera()\r\n{\r\n\tDbg_Assert( mp_camera );\r\n\r\n\tMth::Vector& camPos = mp_camera->GetPos();\r\n\tMth::Matrix& camMatrix = mp_camera->GetMatrix();\r\n\t\r\n\tMdl::FrontEnd* pFront = Mdl::FrontEnd::Instance();\r\n\r\n\tfor ( int i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n\t\tif ( pFront->GetInputHandler( i )->m_Input->m_Makes & Inp::Data::mD_X )\r\n\t\t{\r\n\t\t\t// abort if skippable\r\n\t\t\tAbort( true );\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( mp_frameData )\r\n\t{\r\n\t\tMth::Quat theQuat;\r\n\t\tMth::Vector theTrans;\r\n\r\n\t\tget_current_frame( &theQuat, &theTrans );\r\n\t\t\r\n\t\t// update the camera position\r\n\t\tcamPos = theTrans;\r\n\r\n\t\t// update the camera orientation\r\n\t\tMth::Vector nullTrans;\r\n\t\tnullTrans.Set(0.0f,0.0f,0.0f,1.0f);\t\t// Mick: added separate initialization\r\n\t\tMth::QuatVecToMatrix( &theQuat, &nullTrans, &camMatrix );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// clear out the cam matrix to the identity\r\n\t\t// if there's no associated animation.\r\n\t\t// the assumption is that the following m_hasTarget\r\n\t\t// code block will overrride it with the correct data...\r\n\t\tcamPos = Mth::Vector( 0.0f, 0.0f, 0.0f );\r\n\t\tcamMatrix.Ident();\r\n\t\t\r\n\t\t// if there's no frame data, then we should\r\n\t\t// reset the camera to some default FOV,\r\n\t\t// or else it will use the last FOV used\r\n\t\tfloat fov_in_degrees = Script::GetFloat( CRCD(0x99529205, \"camera_fov\") );\r\n\t\tmp_camera->SetHFOV(fov_in_degrees);\r\n\t}\r\n\t\r\n\tif ( m_hasTarget )\r\n\t{\r\n\t\tif ( m_targetID != CRCD(0xc588eebc,\"world\") )\r\n\t\t{\r\n\t\t\t// calculate the orientation from the target\r\n\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\tObj::CGeneralManager* pObjectManager = skate_mod->GetObjectManager();\r\n\t\t\tDbg_Assert( pObjectManager );\r\n\t\t\tObj::CObject* pObject = pObjectManager->GetObjectByID( m_targetID );\r\n\t\t\tDbg_MsgAssert( pObject, ( \"Can't find lookup target %s\", Script::FindChecksumName(m_targetID) ) );\r\n\t\t\tif ( pObject )\r\n\t\t\t{\r\n\t\t\t\t//Dbg_MsgAssert( static_cast<Obj::CCompositeObject*>( pObject ), ( \"This function only works on moving objects.\" ) ); \r\n\t\t\t\tObj::CCompositeObject* pCompositeObject = (Obj::CCompositeObject*)pObject;\r\n\t\r\n\t\t\t\t// override it with the moving object's position\r\n\t\t\t\tMth::Vector pos = pCompositeObject->GetPos();\r\n\t\t\t\t\r\n\t\t\t\t// patch for positions that don't have 1.0 in the final column...\r\n\t\t\t\t// not sure why this would be the case, but it seems to happen\r\n\t\t\t\t// with the skater...  (possibly a result of skater's mp_physics\r\n\t\t\t\t// disappearing)\r\n\t\t\t\tpos[W] = 1.0f;\r\n\t\r\n\t\t\t\t// not properly working yet...\r\n\t\t\t\tif ( m_hasTargetOffset )\r\n\t\t\t\t{    \r\n\t\t\t\t\tMth::Matrix mat = pCompositeObject->GetMatrix();\r\n\t\t\t\t\tmat[Mth::POS] = pos;\t\t\t\t                                                         \r\n\t\t\t\t\tmat.TranslateLocal( m_targetOffset );\r\n\t\t\t\t\tpos = mat[Mth::POS];\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tif ( m_hasPositionOffset )\r\n\t\t\t\t{\r\n\t\t\t\t\tcamPos = pos;\r\n\t\r\n\t\t\t\t\tMth::Matrix mat = pCompositeObject->GetMatrix();\r\n\t\t\t\t\tmat[Mth::POS] = pos;\r\n\t\t\t\t\tmat.TranslateLocal( m_positionOffset );\r\n\t\t\t\t\tcamPos = mat[Mth::POS];\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\t// set rotation from the camera's position (always up)\r\n\t\t\t\tMth::Vector atVec = camPos - pos;\r\n\t\t\t\tatVec.Normalize();\r\n\t\t\t\t\r\n\t\t\t\tcamMatrix.Ident();\r\n\t\t\t\tcamMatrix[Mth::AT]\t\t= atVec;\r\n\t\t\t\tcamMatrix[Mth::RIGHT]\t= Mth::CrossProduct( camMatrix[Mth::UP], camMatrix[Mth::AT] );\r\n\t\t\t\tcamMatrix[Mth::RIGHT].Normalize();\r\n\t\t\t\tcamMatrix[Mth::UP]\t\t= Mth::CrossProduct( camMatrix[Mth::AT], camMatrix[Mth::RIGHT] );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// World coordinates are a lot simpler\r\n\t\t\tMth::Vector pos = m_targetOffset;\r\n\t\t\tcamPos = m_positionOffset;\r\n\t\t\tMth::Vector atVec = camPos - pos;\r\n\t\t\tatVec[W] = 1.0f;\r\n\t\t\tatVec.Normalize();\r\n\t\t\tcamMatrix.Ident();\r\n\t\t\tcamMatrix[Mth::AT]\t\t= atVec;\r\n\t\t\tcamMatrix[Mth::RIGHT]\t= Mth::CrossProduct( camMatrix[Mth::UP], camMatrix[Mth::AT] );\r\n\t\t\tcamMatrix[Mth::RIGHT].Normalize();\r\n\t\t\tcamMatrix[Mth::UP]\t\t= Mth::CrossProduct( camMatrix[Mth::AT], camMatrix[Mth::RIGHT] );\r\n\t\t}\t\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCamDetails::CallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tswitch ( checksum )\r\n\t{\r\n\t\tcase 0xa8d5a188:\t\t// SetTargetObject\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"*** Calling SetTargetObject\" );\r\n\t\t\t\t\r\n\t\t\t\tset_target_params( pParams );\r\n\t\t\t\t\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\tcase 0xd7241a6c:\t\t// ClearTargetObject\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"*** Calling ClearTargetObject\" );\r\n\t\t\t\t\r\n\t\t\t\tclear_target_params();\r\n\t\t\t\t\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\treturn CMovieDetails::CallMemberFunction( checksum, pParams, pScript );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCamDetails::IsComplete()\r\n{\r\n\tif ( m_aborted )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif ( m_holdOnLastFrame )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn m_animController.IsAnimComplete();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCamDetails::IsHeld()\r\n{\r\n\t/* Added by Ken. Used to determine when camera anims used in\t  */\r\n\t/* the skate shop front-end have got to their last frame, so that */\r\n\t/* scripts can trigger things to happen such as the video menu    */\r\n\t/* making the video cassettes pan out to the foreground.          */\r\n\t\r\n\treturn ( m_holdOnLastFrame && m_animController.IsAnimComplete() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCamDetails::OverridesCamera()\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n"
  },
  {
    "path": "Code/Sk/Objects/moviedetails.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       moviedetails.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  06/17/2002\r\n//****************************************************************************\r\n\r\n#ifndef __OBJECTS_MOVIEDETAILS_H\r\n#define __OBJECTS_MOVIEDETAILS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <core/list.h>\r\n#include <core/math.h>\r\n\r\n#include <gfx/animcontroller.h>\t\t\t\t\t\t \r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Gfx\r\n{\r\n\tclass Camera;\r\n\tclass CBonedAnimFrameData;\r\n}\r\n\r\nnamespace Mth\r\n{\r\n\tclass Matrix;\r\n\tclass Quat;\r\n\tclass Vector;\r\n}\r\n\t\t\t\t   \r\nnamespace Script\r\n{\r\n\tclass CScript;\r\n\tclass CStruct;\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// CMovieDetails\r\nclass CMovieDetails : public Lst::Node<CMovieDetails>\r\n{\r\npublic:\r\n\tCMovieDetails();\r\n\tvirtual \t\t\t\t~CMovieDetails();\r\n\r\npublic:\r\n\tvirtual bool\t\t\tInitFromStructure( Script::CStruct* pParams ) = 0;\r\n\tvirtual void\t\t\tUpdate() = 0;\r\n\tvirtual\tbool\t\t\tResetCustomKeys() = 0;\r\n\tvirtual bool\t\t\tCallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript ); \r\n\tvirtual bool\t\t\tIsComplete() = 0;\r\n\tvirtual bool\t\t\tIsHeld() = 0;\r\n\tvirtual bool\t\t\tOverridesCamera() = 0;\r\n\tvirtual void\t\t\tCleanup();\r\n\tvirtual bool\t\t\tHasMovieStarted() = 0;\r\n\tvirtual bool\t\t\tNeedsCameraTransition() { return false; }\t\t// Only set to true on classes that need the\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// old camera to stay around an extra frame\r\n\t\t\t\t\t\t\t\t\t\t\t\t  \r\npublic:\r\n\tvoid\t\t\t    \tSetParams( Script::CStruct* pParams );\r\n\tScript::CStruct* \t\tGetParams();\r\n\tbool\t\t\t\t\tSetSkippable( bool skippable );\r\n\tbool\t\t\t\t\tIsSkippable() { return m_skippable; }\r\n\tbool\t\t\t\t\tSetName( uint32 name );\r\n\tuint32\t\t\t\t\tGetName();\r\n\tbool\t\t\t\t\tAbort( bool only_if_skippable );\r\n\r\n\tbool\t\t\t\t\tShouldPauseMovie() { return m_shouldPause; }\r\n\tbool\t\t\t\t\tSetPauseMode( bool pause_mode );\r\n\r\n\tGfx::Camera*\t\t\tGetCamera() { return mp_camera; }\r\n\t\r\n\tuint32\t\t\t\t\tGetExitScriptName() const\r\n\t{\r\n\t\treturn m_exitScript;\r\n\t}\r\n\tScript::CStruct*\t\tGetExitParams()\r\n\t{\r\n\t\treturn mp_exitParams;\r\n\t}\r\n\r\nprotected:\r\n\tGfx::Camera*\t\t\tmp_camera;\r\n\tbool\t\t\t\t\tm_holdOnLastFrame;\r\n\tbool\t\t\t\t\tm_skippable;\r\n\tbool\t\t\t\t\tm_aborted;\r\n\tbool\t\t\t\t\tm_shouldPause;\r\n\tbool\t\t\t\t\tm_allowPause;\r\n\tuint32\t\t\t\t\tm_name;\r\n\r\n\t// exit parameters\r\n\tuint32\t\t\t\t\tm_exitScript;\r\n\tScript::CStruct*\t\tmp_exitParams;\r\n};\r\n\r\n// this can probably be split up into\r\n// a target version and a non-target version\r\nclass CSkaterCamDetails : public CMovieDetails\r\n{\r\npublic:\r\n\tCSkaterCamDetails();\r\n\t~CSkaterCamDetails();\r\n\r\npublic:\r\n\tvirtual bool \tInitFromStructure(Script::CStruct *pParams);\r\n\tvirtual void \tUpdate();\r\n\tvirtual bool \tResetCustomKeys();\r\n\tvirtual bool\tCallMemberFunction( uint32 checksum, Script::CStruct* pParams, Script::CScript* pScript ); \r\n\tvirtual bool \tIsComplete();\r\n\tvirtual bool\tIsHeld();\r\n\tvirtual bool\tOverridesCamera();\r\n\tvirtual bool\tHasMovieStarted()\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\tvirtual bool\tNeedsCameraTransition() { return true; }\t\t// Uses hack to work around glitches where there isn't a camera\r\n\r\nprotected:\r\n\tvoid\t\t\tset_target_params( Script::CStruct* pParams );\r\n\tvoid\t\t\tclear_target_params();\r\n\tvoid\t\t\tset_frame_data( Gfx::CBonedAnimFrameData* pFrameData, Gfx::EAnimLoopingType loopingType, bool reverse );\r\n\tvoid\t\t\tset_movie_length( float duration );\r\n\tvoid\t\t\tget_current_frame( Mth::Quat* pQuat, Mth::Vector* pTrans );\r\n\tbool\t\t\tprocess_custom_keys( float startTime, float endTime, bool end_time_inclusive );\r\n\tvoid\t\t\tupdate_camera();\r\n\tvoid\t\t\tupdate_camera_time();\r\n\r\nprotected:\r\n\t// target parameters\r\n\tbool\t\t\tm_hasTarget;\r\n\tuint32\t\t\tm_targetID;\r\n\tMth::Vector\t\tm_targetOffset;\r\n\tMth::Vector\t\tm_positionOffset;\r\n\tbool\t\t\tm_hasTargetOffset;\r\n\tbool\t\t\tm_hasPositionOffset;\r\n\t\r\n\tGfx::CBonedAnimFrameData*\tmp_frameData;\r\n\t\r\n\t// time-keeper\r\n\tGfx::CAnimChannel\t\tm_animController;\r\n};\t\t\t\t\t\r\n\r\nclass CObjectAnimDetails : public CMovieDetails\r\n{\r\npublic:\r\n\tCObjectAnimDetails();\r\n\tvirtual \t\t~CObjectAnimDetails();\r\n\r\npublic:\r\n\tvirtual bool\tInitFromStructure( Script::CStruct* pParams );\r\n\tvirtual void\tUpdate();\r\n\tvirtual bool\tResetCustomKeys();\r\n\tvirtual bool\tIsComplete();\r\n\tvirtual bool\tIsHeld();\r\n\tvirtual bool\tOverridesCamera();\r\n\tvirtual bool\tHasMovieStarted()\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\nprotected:\r\n\tvoid\t\t\tset_frame_data( Gfx::CBonedAnimFrameData* pFrameData, Gfx::EAnimLoopingType loopingType, bool reverse );\r\n\tvoid\t\t\tset_movie_length( float duration );\r\n\tbool\t\t\tprocess_custom_keys( float startTime, float endTime, bool end_time_inclusive );\r\n\tvoid\t\t\tupdate_moving_objects();\r\n\r\nprotected:\r\n\tGfx::CBonedAnimFrameData*\tmp_frameData;\r\n\t\r\n\t// time-keeper\r\n\tGfx::CAnimChannel\t\tm_animController;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_MOVIEDETAILS_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/navigation.cpp",
    "content": "///////////////////////////////////////////////////////\r\n// rail.cpp\r\n\r\n#include <sk/objects/navigation.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n\r\n#include <gel/modman.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/environment/terrain.h>\r\n#include <gel/collision/collision.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/debuggfx.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/scripting/nodearray.h>\r\n\t\t  \r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sAStarOpenList\r\n{\r\n\tCNavNode*\tm_open_list[512];\r\n\tint\t\t\tm_num_open;\r\n\r\n\t\t\t\tsAStarOpenList( void );\r\n\t\t\t\t~sAStarOpenList( void );\r\n\r\n\tbool\t\tIsEmpty( void )\t\t\t\t{ return m_num_open == 0; }\r\n\tvoid\t\tClear();\r\n\tvoid\t\tEmpty();\r\n\tvoid\t\tPush( CNavNode* p_node );\r\n\tCNavNode*\tPop( void );\r\n\tvoid\t\tSortOnTotalCost();\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sAStarClosedList\r\n{\r\n\tCNavNode*\tm_closed_list[512];\r\n\tint\t\t\tm_num_closed;\r\n\r\n\t\t\t\tsAStarClosedList( void );\r\n\t\t\t\t~sAStarClosedList( void );\r\n\r\n\tbool\t\tIsEmpty( void )\t\t\t\t{ return m_num_closed == 0; }\r\n\tvoid\t\tClear();\r\n\tvoid\t\tEmpty( void );\r\n\tvoid\t\tAdd( CNavNode* p_node );\r\n\tvoid\t\tRemove( CNavNode* p_node );\r\n};\r\n\r\n\r\n\r\nstatic sAStarOpenList\topenList;\r\nstatic sAStarClosedList\tclosedList;\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sAStarNode::Reset( void )\r\n{\r\n\tm_flags\t= 0;\r\n\tm_cost_from_start\t= 0.0f;\r\n\tm_cost_to_goal\t\t= 0.0f;\r\n\tm_total_cost\t\t= 0.0f;\r\n\tmp_parent\t\t\t= NULL;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool normal_sensitive_collision( CFeeler& feeler, float normal_y_sensitivity )\r\n{\r\n\t// Safety check.\r\n\tint iteration = 0;\r\n\r\n\t// The feeler should already have been set up with the start and end points.\r\n\twhile( feeler.GetCollision())\r\n\t{\r\n\t\t// If this collision is with a normal that passes ouyr sensitivity test, consider it valid.\r\n\t\tif( Mth::Abs( feeler.GetNormal()[Y] ) < normal_y_sensitivity )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Otherwise move the start location on by 0.1 inch and continue.\r\n\t\tfeeler.m_start += ( feeler.m_end - feeler.m_start ).Normalize( 0.1f );\r\n\r\n\t\t++iteration;\r\n\t\tif( iteration > 8 )\r\n\t\t{\r\n\t\t\tDbg_Message( \"Multiple iterations in normal_sensitive_collision()\" );\r\n\r\n\t\t\t// Err on the side of caution.\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nfloat path_cost_estimate( Mth::Vector& pos_a, Mth::Vector& pos_b )\r\n{\r\n\t// Currently just use the distance between them. No consideration of terrain type.\r\n\treturn Mth::Distance( pos_a, pos_b );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nfloat traverse_cost( CNavNode* p_node_a, CNavNode* p_node_b )\r\n{\r\n\t// Currently just use the distance between them. No consideration of terrain type.\r\n\treturn Mth::Distance( p_node_a->GetPos(), p_node_b->GetPos());\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint sort_on_total_cost( const void *p1, const void *p2 )\r\n{\r\n\tCNavNode*\tp_node1\t= *((CNavNode**)p1 );\r\n\tCNavNode*\tp_node2\t= *((CNavNode**)p2 );\r\n\t\r\n\treturn ( p_node1->GetAStarNode()->m_total_cost < p_node2->GetAStarNode()->m_total_cost ) ? 1 : (( p_node1->GetAStarNode()->m_total_cost > p_node2->GetAStarNode()->m_total_cost ) ? -1 : 0 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNavNode* get_nearest_visible_node( Mth::Vector& pos, Mth::Vector& heading )\r\n{\r\n\tMdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tObj::CNavManager* p_nav_man = skate_mod->GetNavManager();\r\n\r\n\tfloat\t\tbest_dp\t\t= -0.707106f;\t// cosine of 135 degrees\r\n\tCNavNode*\tp_best_node\t= NULL;\r\n\r\n\tint num_nodes = p_nav_man->GetNumNodes();\r\n\tfor( int i = 0; i < num_nodes; ++i )\r\n\t{\r\n\t\tCNavNode*\tp_node = p_nav_man->GetNavNodeByIndex( i );\r\n\r\n\t\t// Discard nodes that are not in the required direction.\r\n\t\tMth::Vector node_pos\t= p_node->GetPos() + Mth::Vector( 0.0f, 60.0f, 0.0f, 0.0f );\r\n\t\tMth::Vector pos_to_node\t= node_pos - pos;\r\n\t\tpos_to_node[Y]\t\t\t= 0.0f;\r\n\t\tpos_to_node[W]\t\t\t= 0.0f;\r\n\t\tpos_to_node.Normalize();\r\n\t\tfloat dp\t\t\t\t= Mth::DotProduct( pos_to_node, heading );\r\n\r\n\t\t// Do we already have a better node.\r\n\t\tif( dp < best_dp )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Discard nodes that are not visible.\r\n\t\tCFeeler feeler;\r\n\t\tfeeler.m_start\t= pos;\r\n\t\tfeeler.m_end\t= node_pos;\r\n\t\tif( normal_sensitive_collision( feeler, 0.2f ))\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tbest_dp\t\t= dp;\r\n\t\tp_best_node\t= p_node;\r\n\t}\r\n\treturn p_best_node;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNavNode* CalculateNodePath( Mth::Vector pos, Mth::Vector target_pos )\r\n{\r\n\t// Clear open and closed nodes.\r\n\topenList.Clear();\r\n\tclosedList.Clear();\r\n\r\n\t// Find nearest visible node from current location, preferably in direction currently facing.\r\n\tMth::Vector heading = target_pos - pos;\r\n\theading[Y] = 0.0f;\r\n\theading[W] = 0.0f;\r\n\theading.Normalize();\r\n\tCNavNode* p_nearest_visible = get_nearest_visible_node( pos, heading );\r\n\tif( p_nearest_visible == NULL )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Initialise the A* section of the node.\r\n\tp_nearest_visible->GetAStarNode()->m_cost_from_start\t= path_cost_estimate( pos, p_nearest_visible->GetPos());\r\n\tp_nearest_visible->GetAStarNode()->m_cost_to_goal\t\t= path_cost_estimate( p_nearest_visible->GetPos(), target_pos );\r\n\tp_nearest_visible->GetAStarNode()->m_total_cost\t\t\t= p_nearest_visible->GetAStarNode()->m_cost_from_start + p_nearest_visible->GetAStarNode()->m_cost_to_goal;\r\n\tp_nearest_visible->GetAStarNode()->mp_parent\t\t\t= NULL;\r\n\r\n\t// Push this node on to the open list.\r\n\topenList.Push( p_nearest_visible );\r\n\r\n\twhile( !openList.IsEmpty())\r\n\t{\r\n\t\t// Pop lowest total cost node from open list.\r\n\t\tCNavNode* p_this_node = openList.Pop();\r\n\r\n\t\t// If goal visible from this node, we're done.\r\n\t\tMth::Vector raised_node_pos = p_this_node->GetPos() + Mth::Vector( 0.0f, 60.0f, 0.0f, 0.0f );\r\n\t\tCFeeler feeler;\r\n\t\tfeeler.m_start\t= raised_node_pos;\r\n\t\tfeeler.m_end\t= target_pos;\r\n\t\tif( !normal_sensitive_collision( feeler, 0.2f ))\r\n\t\t{\r\n\t\t\t// Build list of nodes.\r\n\r\n\t\t\t// Empty lists.\r\n\t\t\topenList.Empty();\r\n\t\t\tclosedList.Empty();\r\n\r\n\t\t\treturn p_this_node;\r\n\t\t}\r\n\r\n\t\t// For each node linked to this node...\r\n\t\tfor( int l = 0; l < p_this_node->GetNumLinks(); ++l )\r\n\t\t{\r\n\t\t\tCNavNode*\tp_new_node\t= p_this_node->GetLink( l );\r\n\t\t\tfloat\t\tnew_cost\t= p_this_node->GetAStarNode()->m_cost_from_start + traverse_cost( p_this_node, p_new_node );\r\n\r\n\t\t\t// Ignore this node if it is already in a list and provides no improvement.\r\n\t\t\tif(( p_new_node->GetAStarNode()->InOpen() || p_new_node->GetAStarNode()->InClosed()) &&\r\n\t\t\t\t p_new_node->GetAStarNode()->m_cost_from_start <= new_cost )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// Store the new or improved information.\r\n\t\t\tp_new_node->GetAStarNode()->mp_parent\t\t\t= p_this_node;\r\n\t\t\tp_new_node->GetAStarNode()->m_cost_from_start\t= new_cost;\r\n\t\t\tp_new_node->GetAStarNode()->m_cost_to_goal\t\t= path_cost_estimate( p_new_node->GetPos(), target_pos );\r\n\t\t\tp_new_node->GetAStarNode()->m_total_cost\t\t= p_new_node->GetAStarNode()->m_cost_from_start + p_new_node->GetAStarNode()->m_cost_to_goal;\r\n\r\n\t\t\t// Remove new node from closed list if it's in there.\r\n\t\t\tif( p_new_node->GetAStarNode()->InClosed())\r\n\t\t\t{\r\n\t\t\t\tclosedList.Remove( p_new_node );\r\n\t\t\t}\r\n\r\n\t\t\t// Push new node onto open list (if it's not already in there).\r\n\t\t\t// This will re-sort the open list.\r\n\t\t\tif( !p_new_node->GetAStarNode()->InOpen())\r\n\t\t\t{\r\n\t\t\t\topenList.Push( p_new_node );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Add node onto the closed list.\r\n\t\tclosedList.Add( p_this_node );\r\n\t}\r\n\r\n\t// Empty lists.\r\n\topenList.Empty();\r\n\tclosedList.Empty();\r\n\r\n\t// If we get here we have failed to find any valid path.\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsAStarOpenList::sAStarOpenList( void )\r\n{\r\n\tClear();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsAStarOpenList::~sAStarOpenList( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sAStarOpenList::Clear( void )\r\n{\r\n\tmemset( m_open_list, 0, sizeof( m_open_list ));\r\n\tm_num_open = 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sAStarOpenList::Empty( void )\r\n{\r\n\twhile( !IsEmpty())\r\n\t{\r\n\t\tPop();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sAStarOpenList::Push( CNavNode* p_node )\r\n{\r\n\tDbg_Assert( m_num_open < 512 );\r\n\r\n\tm_open_list[m_num_open++] = p_node;\r\n\r\n\t// Flag this node as now being in the open list.\r\n\tp_node->GetAStarNode()->m_flags |= sAStarNode::IN_OPEN;\r\n\r\n\tSortOnTotalCost();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNavNode* sAStarOpenList::Pop( void )\r\n{\r\n\tDbg_Assert( m_num_open > 0 );\r\n\r\n\t// Assumes always sorted, so just return lowest cost node.\r\n\t--m_num_open;\r\n\tCNavNode* p_return\t\t= m_open_list[m_num_open];\r\n\tm_open_list[m_num_open]\t= NULL;\r\n\r\n\t// Flag this node as no longer being in the open list.\r\n\tp_return->GetAStarNode()->m_flags &= ~sAStarNode::IN_OPEN;\r\n\r\n\treturn p_return;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sAStarOpenList::SortOnTotalCost( void )\r\n{\r\n\tif( m_num_open > 1 )\r\n\t{\r\n\t\tqsort( m_open_list, m_num_open, sizeof( CNavNode* ), sort_on_total_cost );\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsAStarClosedList::sAStarClosedList( void )\r\n{\r\n\tClear();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsAStarClosedList::~sAStarClosedList( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sAStarClosedList::Clear( void )\r\n{\r\n\tmemset( m_closed_list, 0, sizeof( m_closed_list ));\r\n\tm_num_closed = 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sAStarClosedList::Empty( void )\r\n{\r\n\tif( !IsEmpty())\r\n\t{\r\n\t\tfor( int i = 0; i < 512; ++i )\r\n\t\t{\r\n\t\t\tif( m_closed_list[i] )\r\n\t\t\t{\r\n\t\t\t\tRemove( m_closed_list[i] );\r\n\t\t\t}\r\n\t\t}\r\n\t\tDbg_Assert( IsEmpty());\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sAStarClosedList::Add( CNavNode* p_node )\r\n{\r\n\tfor( int i = 0; i < 512; ++i )\r\n\t{\r\n\t\tif( m_closed_list[i] == NULL )\r\n\t\t{\r\n\t\t\tm_closed_list[i] = p_node;\r\n\t\t\t++m_num_closed;\r\n\t\t\tp_node->GetAStarNode()->m_flags |= sAStarNode::IN_CLOSED;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tDbg_Assert( 0 );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid sAStarClosedList::Remove( CNavNode* p_node )\r\n{\r\n\tfor( int i = 0; i < 512; ++i )\r\n\t{\r\n\t\tif( m_closed_list[i] == p_node )\r\n\t\t{\r\n\t\t\tm_closed_list[i] = NULL;\r\n\t\t\t--m_num_closed;\r\n\t\t\tp_node->GetAStarNode()->m_flags &= ~sAStarNode::IN_CLOSED;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tDbg_Assert( 0 );\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNavManager::CNavManager()\r\n{\r\n\tmp_nodes\t\t= NULL;\r\n\tm_num_nodes\t\t= 0;\r\n\tmp_node_array\t= NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCNavManager::~CNavManager()\r\n{\t \r\n\tCleanup();  \r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNavManager::Cleanup()\r\n{\r\n\tm_num_nodes = 0;\r\n\t\r\n\tMem::Free( mp_nodes );\r\n\tmp_nodes\t\t= NULL;\r\n\tmp_node_array\t= NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNavManager::AddNavNode( int node_number, Script::CStruct* p_node_struct )\r\n{\r\n\tCNavNode* pNavNode = &mp_nodes[m_current_node];\r\n\t\r\n\tuint32 class_checksum;\r\n\tp_node_struct->GetChecksum( CRCD( 0x12b4e660, \"class\" ), &class_checksum );\r\n\t\r\n\tuint32 type_checksum;\r\n\tp_node_struct->GetChecksum( CRCD( 0x7321a8d6, \"type\" ), &type_checksum );\r\n\r\n\t// No links as yet.\r\n\tpNavNode->m_num_links = 0;\r\n\tfor( int i = 0;i < MAX_NAV_LINKS; ++i )\r\n\t{\r\n\t\tpNavNode->mp_links[i] = NULL;\r\n\t}\r\n\r\n\t// The node_number is use primarily for calculating links.\r\n\tpNavNode->m_node\t\t= node_number;\r\n\t\r\n\t// Reset the A* node.\r\n\tpNavNode->m_astar_node.Reset();\r\n\t\r\n//\tpNavNode->m_flags\t= 0;\r\n//\tpNavNode->SetActive( p_node_struct->ContainsFlag( 0x7c2552b9 /*\"CreatedAtStart\"*/ ));\t// Created at start or not?\r\n\r\n\t// Set the position from the node structure.\r\n\tSkateScript::GetPosition( p_node_struct, &pNavNode->m_pos );\r\n\r\n\tint links = SkateScript::GetNumLinks( p_node_struct );\r\n\tif( links )\r\n\t{\r\n\t\tDbg_MsgAssert( links <= MAX_NAV_LINKS, ( \"Nav node %d has %d linkes, max is %d\", node_number, links, MAX_NAV_LINKS ));\r\n\r\n\t\tpNavNode->m_num_links = links;\r\n\t\tfor( int i = 0; i < links; ++i )\r\n\t\t{\r\n\t\t\t// For now we just set the link to be the node number in the node array.\r\n\t\t\tpNavNode->mp_links[i] = (CNavNode*)SkateScript::GetLink( p_node_struct, i );\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CNavManager::AddNavsFromNodeArray( Script::CArray *p_nodearray )\r\n{\r\n\tDbg_MsgAssert( !mp_node_array, ( \"Setting two node arrays in rail manager\" ));\r\n\tmp_node_array = p_nodearray;\r\n\t\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\r\n\tuint32 i;\t\r\n\r\n\tDbg_MsgAssert( m_num_nodes == 0, (\"Can only addd nodes once, already %d there\\n\", m_num_nodes ));\r\n\r\n\t// First iterate over the node array, and count the number of nodes needed.\r\n\tm_num_nodes = 0;\t\t\t\t\t\t\t\t\t\t  \r\n\tfor( i = 0; i < p_nodearray->GetSize(); ++i )\r\n\t{\r\n\t\tScript::CStruct* p_node_struct = p_nodearray->GetStructure( i );\r\n\t\tDbg_MsgAssert( p_node_struct, ( \"Error getting node from node array for navigation\" ));\r\n\t\tif( !skate_mod->ShouldBeAbsentNode( p_node_struct ))\r\n\t\t{\r\n\t\t\tuint32 class_checksum = 0;\t\t\r\n\t\t\tp_node_struct->GetChecksum( CRCD( 0x12b4e660, \"Class\" ), &class_checksum );\r\n\t\t\tif( class_checksum == CRCD( 0x4c23a77e, \"Waypoint\" ))\r\n\t\t\t{\r\n\t\t\t\tuint32 type_checksum = 0;\t\t\r\n\t\t\t\tp_node_struct->GetChecksum( CRCD( 0x7321a8d6, \"Type\" ), &type_checksum );\r\n\t\t\t\tif( type_checksum == CRCD( 0x9784feb5, \"HorseNav\" ))\r\n\t\t\t\t{\r\n\t\t\t\t\t++m_num_nodes;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// No nodes found, so just return\r\n\tif( m_num_nodes == 0 )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tmp_nodes = (CNavNode*)Mem::Malloc( m_num_nodes * sizeof( CNavNode ));\r\n\r\n\t// Iterate over the nodes and add them to the array.\r\n\tm_current_node = 0;\t\r\n\t\r\n\tfor( i = 0; i < p_nodearray->GetSize(); ++i )\r\n\t{\r\n\t\tScript::CStruct *p_node_struct = p_nodearray->GetStructure( i );\r\n\t\tDbg_MsgAssert( p_node_struct, (\"Error getting node from node array for navigation\" ));\r\n\r\n\t\tif( !skate_mod->ShouldBeAbsentNode( p_node_struct ))\r\n\t\t{\r\n\t\t\tuint32 class_checksum = 0;\t\t\r\n\t\t\tp_node_struct->GetChecksum( CRCD( 0x12b4e660, \"Class\" ), &class_checksum );\r\n\t\t\tif( class_checksum == CRCD( 0x4c23a77e, \"Waypoint\" ))\r\n\t\t\t{\r\n\t\t\t\tuint32 type_checksum = 0;\t\t\r\n\t\t\t\tp_node_struct->GetChecksum( CRCD( 0x7321a8d6, \"Type\" ), &type_checksum );\r\n\t\t\t\tif( type_checksum == CRCD( 0x9784feb5, \"HorseNav\" ))\r\n\t\t\t\t{\r\n\t\t\t\t\tAddNavNode( i, p_node_struct );\r\n\t\t\t\t\t++m_current_node;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// We are creating a table of all nodes, and the pointer to the CNavNode for that node, so we can do a reverse lookup.\r\n\tint num_nodes = p_nodearray->GetSize();\r\n\tCNavNode **pp_navnodes = (CNavNode**)Mem::Malloc( num_nodes * sizeof( CNavNode* ));\r\n\tfor( int i = 0; i < num_nodes; ++i )\r\n\t{\r\n\t\tpp_navnodes[i] = NULL;\r\n\t}\r\n\r\n\t// Now fill it in.\r\n\tCNavNode* p_node;\r\n\tfor( int node = 0; node < m_num_nodes; ++node )\r\n\t{\r\n\t\tp_node = &mp_nodes[node];\r\n\t\tpp_navnodes[p_node->GetNode()] = p_node;\r\n\t}\r\n\r\n\t// Now go through all the nodes.\r\n\tfor( int node = 0; node < m_num_nodes; ++node )\r\n\t{\r\n\t\tp_node = &mp_nodes[node];\r\n\t\tfor( int i = 0; i < p_node->m_num_links; ++i )\r\n\t\t{\r\n\t\t\tint index = (int)p_node->mp_links[i];\r\n\r\n\t\t\tDbg_MsgAssert( index < num_nodes, ( \"Node %d, Nav link node (%d) out of range (0 .. %d). Bad Node array?\", p_node->m_node, index, num_nodes ));\r\n\t\t\tDbg_MsgAssert( pp_navnodes[index], ( \"NavNode %d linked to something (node %d) that is not a NavNode\", p_node->m_node, index ));\r\n\r\n\t\t\tp_node->mp_links[i] = pp_navnodes[index];\r\n\t\t}\r\n\t}\r\n\r\n\t// Don't need the temporary array anymore.\r\n\tMem::Free( pp_navnodes );\r\n}\r\n\r\n\r\n\r\nMth::Vector\tCNavManager::GetPos( const CNavNode* p_node ) const\r\n{\r\n\tDbg_Assert( p_node );\r\n\treturn p_node->GetPos();\r\n}\r\n\r\n\r\n}\r\n\t\t\t   \r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/navigation.h",
    "content": "//////////////////////////////////////////\r\n// navigation.h\r\n\r\n#ifndef __OBJECTS_NAVIGATION_H\r\n#define __OBJECTS_NAVIGATION_H\r\n                        \r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <gfx/nxflags.h>\r\n                           \r\nnamespace Script\r\n{\r\n\tclass\tCArray;\r\n\tclass\tCStruct;\r\n}\r\n\r\n#define\tMAX_NAV_LINKS 12\r\n\r\nnamespace Obj\r\n{\r\n\r\nclass\tCNavManager;\r\n//class\tCWalkComponent;\r\n//struct\tSHangNavData;\r\n//struct\tSLadderNavData;\r\n\r\n//enum ENavNodeFlag\r\n//{\t\r\n//\tLIP_OVERRIDE,\t\t// always do a lip trick on this\r\n//\tDEFAULT_LINE,\r\n//\tACTIVE,\r\n//\tCLIMBING,\r\n//\tLADDER\r\n//};\r\n\r\n\r\n\r\n// Forward declaration.\r\nclass CNavNode;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstruct sAStarNode\r\n{\r\n\tenum EAStarNodeFlag\r\n\t{\r\n\t\tIN_OPEN\t\t= 0x01,\r\n\t\tIN_CLOSED\t= 0x02\r\n\t};\r\n\r\n\tuint32\t\t\tm_flags;\r\n\tfloat\t\t\tm_cost_from_start;\r\n\tfloat\t\t\tm_cost_to_goal; \r\n\tfloat\t\t\tm_total_cost; \r\n\tCNavNode*\t\tmp_parent;\r\n\r\n\r\n\tbool\t\t\tInOpen( void )\t\t{ return m_flags & IN_OPEN; }\r\n\tbool\t\t\tInClosed( void )\t{ return m_flags & IN_CLOSED; }\r\n\tvoid\t\t\tReset();\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CNavNode : public Spt::Class\r\n{\r\n\tfriend class\t\tCNavManager;\r\n\r\npublic:\t\t\t\t\t\t  \r\n\t\r\n\tconst sint16\t\tGetNode() const\t\t\t\t{ return m_node; }\r\n\tsAStarNode*\t\t\tGetAStarNode( void )\t\t{ return &m_astar_node; }\r\n\tMth::Vector&\t\tGetPos( void )\t\t\t\t{ return m_pos; }\r\n\tint\t\t\t\t\tGetNumLinks( void )\t\t\t{ return m_num_links; }\r\n\tCNavNode*\t\t\tGetLink( int l )\t\t\t{ return mp_links[l]; }\r\n\r\nprotected:\r\n\r\n\tMth::Vector\t\t\tm_pos;\t\t\t\t\t\t// Position of the node.\r\n\tCNavNode*\t\t\tmp_links[MAX_NAV_LINKS];\r\n\tsint16\t\t\t\tm_num_links;\r\n\tsint16\t\t\t\tm_node;\t\t\t\t\t\t// Number of the node in the trigger array.\r\n\tsAStarNode\t\t\tm_astar_node;\t\t\t\t// Used during the A* pathfinding routine.\r\n\r\nprivate:\r\n\tconst Mth::Vector&\tGetPos() const;\r\n};\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nclass CNavManager : public Spt::Class\r\n{\r\n\r\npublic:\r\n\t\t\t\t\t\tCNavManager();\r\n\t\t\t\t\t\t~CNavManager();\t\r\n\t\r\n\tvoid \t\t\t\tCleanup();\r\n\t\t\t\t\t\t\t\t\t \r\n\tvoid\t\t\t\tAddNavsFromNodeArray( Script::CArray * p_node_array );\r\n\tvoid \t\t\t\tAddNavNode( int node_number, Script::CStruct *p_node_struct );\r\n\t\r\n\tint\t\t\t\t\tGetNumNodes()\t\t\t\t\t\t\t\t\t{ return m_num_nodes; }\r\n\tScript::CArray*\t\tGetNodeArray()\t\t\t\t\t\t\t\t\t{ return mp_node_array; }\r\n\tvoid\t\t\t\tSetNodeArray( Script::CArray* p_nodeArray )\t\t{ mp_node_array = p_nodeArray; }\r\n\r\n\tCNavNode*\t\t\tGetNavNodeByIndex( int index )\t\t\t\t\t{ return mp_nodes + index; }\r\n\tCNavNode*\t\t\tGetNavNodeByNodeNumber( int node_num );\r\n\t\r\n\tMth::Vector\t\t\tGetPos( const CNavNode *p_node ) const;\t \r\n\r\nprivate:\r\n\r\n\tCNavNode*\t  \t\tmp_nodes;\t\t\t\t// pointer to array of nodes\r\n\tScript::CArray*\t\tmp_node_array;\r\n\tint\t\t\t\t\tm_num_nodes;\r\n\tint\t\t\t\t\tm_current_node;\r\n};\r\n \r\n\r\n\r\nCNavNode* CalculateNodePath( Mth::Vector pos, Mth::Vector target_pos );\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ninline const Mth::Vector& CNavNode::GetPos() const\r\n{\r\n\treturn m_pos;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n} \r\n\r\n\t\t\t\r\n#endif\t\t\t// #ifndef __OBJECTS_RAIL_H\r\n\t\t\t\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/objecthook.cpp",
    "content": "///////////////////////////////////////////////////////\r\n// ObjectHook.cpp\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/math.h>\r\n#include <sk/objects/ObjectHook.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <gfx/debuggfx.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <gel/modman.h>\r\n\r\n#include <core/math/geometry.h>\r\n#include <engine/feeler.h>\r\n\r\n#ifdef\t__PLAT_NGPS__\t\r\n#include <gfx/ngps/nx/line.h>\r\n#endif\r\n\r\n\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\nCObjectHookManager::CObjectHookManager()\r\n{\r\n\tmp_first_node = NULL;\r\n\tm_is_transformed = false;\r\n\tmp_node_array = NULL;\r\n\t\r\n}\r\n\r\nCObjectHookManager::~CObjectHookManager()\r\n{\t \r\n\tCleanup();  \r\n}\r\n\r\nvoid CObjectHookManager::Cleanup()\r\n{\r\n\twhile (mp_first_node)\r\n\t{\r\n\t\tCObjectHookNode *pNext = mp_first_node->m_pNext;\r\n\t\tdelete mp_first_node;\r\n\t\tmp_first_node = pNext;\t\t\t\r\n\t}    \r\n\tm_is_transformed = false;\t\r\n\t// Unhook from node array\r\n\tmp_node_array = NULL;\r\n}\r\n\r\n\r\nvoid CObjectHookManager::AddObjectHookNode(int node_number, Script::CStruct *p_node_struct)\r\n{\r\n\r\n\t// create a new ObjectHook node\t\t\t\t\t\t\t\t\t\t   \r\n\tCObjectHookNode *pObjectHookNode = new CObjectHookNode();\r\n\t// Link into the head of the ObjectHook manager\t\r\n\t// Note, this must be done before we attempt to link up with other nodes\t\t\t\t\t\t\t\t   \r\n\tpObjectHookNode->m_pNext = mp_first_node; \t\t\t\t\t\t\t  \r\n\tmp_first_node = pObjectHookNode;\r\n\r\n\tpObjectHookNode->m_node = node_number;\t\t\t// The node_number is use primarily for calculating links\r\n\tpObjectHookNode->m_active = p_node_struct->ContainsFlag( 0x7c2552b9 /*\"CreatedAtStart\"*/ );\t// created at start or not?\r\n\tpObjectHookNode->m_flags = 0;\t\t\t\t\t\t// all flags off by default\r\n\r\n\tSkateScript::GetPosition(p_node_struct,&pObjectHookNode->m_pos);\r\n\r\n}\r\n\r\nvoid CObjectHookManager::UpdateTransform(Mth::Matrix& transform)\r\n{\r\n\r\n\tm_is_transformed = true;\r\n\tm_transform = transform;\r\n}\r\n\r\n\r\n\r\nvoid\tCObjectHookManager::DebugRender(Mth::Matrix *p_transform)\r\n{\r\n\t#ifdef\t__PLAT_NGPS__\r\n\r\n\tMth::Vector up(0.0f,1.0f,0.0f);\t\r\n\r\n\tuint32\trgb = 0x0000ff;\r\n\t\r\n\tuint32 current = 12345678;\r\n\r\n\t\r\n\t\r\n\tCObjectHookNode *pObjectHookNode;\r\n\tpObjectHookNode = mp_first_node;\r\n\tint count = 0;\r\n\t// then draw the node positions as litle red lines\t\r\n\tpObjectHookNode = mp_first_node;\r\n\twhile (pObjectHookNode)\r\n\t{\r\n\t\tcount++;\r\n\t\tif (pObjectHookNode->m_active)\r\n\t\t{\r\n\t\t\trgb = 0xff0000;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\trgb = 0x00ff00;\r\n\t\t}\r\n\t\r\n\t\t// check for context changes\r\n\t\tif (current != rgb)\r\n\t\t{\r\n\t\t\tif ( current != 12345678)\r\n\t\t\t{\r\n\t\t\t\tNxPs2::EndLines3D();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcurrent = rgb;\r\n\t\t\tNxPs2::BeginLines3D(0x80000000 + (0x00ffffff & rgb));\r\n\t\t}\r\n\t\r\n\t\tMth::Vector v0, v1;\r\n\t\tv0 = pObjectHookNode->m_pos;\r\n\t\tv1 = v0 + up * 24.0f;\r\n\t\tv0[W] = 1.0f;\t\t// Make homgeneous\r\n\t\tv1[W] = 1.0f;\r\n\r\n\t\tif (p_transform)\r\n\t\t{\r\n\t\t\tv0 = p_transform->Transform(v0);\r\n\t\t\tv1 = p_transform->Transform(v1);\r\n\t\t}\r\n\r\n\t\tNxPs2::DrawLine3D(v0[X],v0[Y],v0[Z],v1[X],v1[Y],v1[Z]);\r\n\t\t\r\n\t\tpObjectHookNode = pObjectHookNode->m_pNext;\r\n\t\t\r\n\t}\r\n\r\n\t\r\n\t\r\n\t// only if we actually drew some\r\n\tif ( current != 12345678)\r\n\t{\r\n\t\tNxPs2::EndLines3D();\r\n\t}\r\n\r\n\r\n\t#endif\r\n\r\n}\r\n\r\n\r\n\r\n\r\nvoid\tCObjectHookManager::AddObjectHooksFromNodeArray(Script::CArray * p_nodearray)\r\n{\r\n\tDbg_MsgAssert(!mp_node_array,(\"Setting two node arrays in ObjectHook manager\"));\r\n\tmp_node_array = p_nodearray;\r\n\t\r\n\t\r\n\tuint32 i;\t \r\n\tfor (i=0; i<p_nodearray->GetSize(); ++i)\r\n\t{\r\n\t\tScript::CStruct *p_node_struct=p_nodearray->GetStructure(i);\r\n\t\tDbg_MsgAssert(p_node_struct,(\"Error getting node from node array for ObjectHook generation\"));\r\n\r\n\t\tuint32 class_checksum = 0;\t\t\r\n\t\tp_node_struct->GetChecksum( 0x12b4e660 /*\"Class\"*/, &class_checksum );\r\n\t\tif (class_checksum == 0xd18719d5)\t\t  // checksum 'ObjectHook'\r\n\t\t{\r\n\t\t\tAddObjectHookNode( i, p_node_struct);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\nconst Mth::Vector&\tCObjectHookNode::GetPos() const\r\n{\r\n\treturn m_pos;\r\n}\r\n\r\n\r\nMth::Vector\tCObjectHookManager::GetPos(const CObjectHookNode *p_node) \tconst\r\n{\r\n\tif (!m_is_transformed)\r\n\t{\r\n\t\treturn p_node->GetPos();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMth::Vector v = m_transform.Transform(p_node->GetPos());\r\n\t\treturn v;\r\n\t}\r\n}\r\n\r\n\r\n}\r\n\t\t\t   \r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/objecthook.h",
    "content": "//////////////////////////////////////////\r\n// ObjectHook.h\r\n\r\n#ifndef __OBJECTS_OBJECTHOOK_H\r\n#define __OBJECTS_OBJECTHOOK_H\r\n\r\nnamespace Script\r\n{\r\n\tclass\tCArray;\r\n\tclass\tCStruct;\r\n}\r\n\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\nclass\tCObjectHookManager;\r\n\r\nenum EObjectHookNodeFlag\r\n{\r\n\tGRAB_OVERRIDE = 0x01,\r\n};\r\n\r\nclass CObjectHookNode : public Spt::Class\r\n{\r\n\tfriend class  CObjectHookManager;\r\n\r\npublic:\t\t\t\t\t\t  \r\n\tconst sint16\t\t\tGetNode() const \t  \t\t{return m_node;}\r\n\tvoid\t\t\t\t\tSetActive(bool active)\t\t{m_active = active;}\r\n\tconst bool\t\t\t\tIsActive() const\t\t\t\t{return m_active;}\r\n\r\n\tvoid\t\t\t\t\tSetFlag(EObjectHookNodeFlag flag) {m_flags |= flag;}\r\n\tvoid\t\t\t\t\tClearFlag(EObjectHookNodeFlag flag) {m_flags &= ~flag;}\r\n\tbool\t\t\t\t\tGetFlag(EObjectHookNodeFlag flag) const {return m_flags & flag;}\r\n\r\n\tCObjectHookNode *\t\tGetNext(){return m_pNext;}\r\n\r\nprotected:\r\n\r\n\tMth::Vector m_pos;\t\t\t// position of the node\r\n\tCObjectHookNode *m_pNext;\t\t\t// Pointer to next node in master list\t \t(or NULL if none)\r\n\tsint16 m_node;\t\t\t\t\t// Number of the node in the trigger array\r\n\tchar m_active;\t\t\t\t// ObjectHook segment starting at this node: active or not?\r\n\tchar m_flags;\t\t\t\t// flags for ObjectHook segment\r\n\r\n// the position getting functions are private\r\n// so you can only access them through the ObjectHook manager\r\n// (as you need to know if it's transformed or not)\r\nprivate:\r\n\tconst Mth::Vector&\tGetPos() const;\t \r\n\t\t\t\t\t\t  \r\n};\r\n\r\n\r\n\r\nclass CObjectHookManager : public Spt::Class\r\n{\r\n\r\npublic:\r\n\t\t\t\t\tCObjectHookManager();\r\n\t\t\t\t   ~CObjectHookManager();\t\r\n\r\n\tvoid \t\t\tCleanup();\r\n\t\t\t\t\t\t\t\t \r\n\tvoid\t\t\tAddObjectHooksFromNodeArray(Script::CArray * p_node_array);\r\n\tvoid \t\t\tAddObjectHookNode(int node_number, Script::CStruct *p_node_struct);\r\n\tvoid \t\t\tAddedAll();\r\n\tvoid\t\t\tUpdateTransform(Mth::Matrix& transform);\r\n\t\r\n\tvoid \t\t\tSetActive( int node, int active, bool wholeObjectHook );\r\n\tbool \t\t\tIsActive( int node );\r\n\tbool\t\t\tIsMoving(){return m_is_transformed;}\r\n\t\r\n\tvoid\t\t\tDebugRender(Mth::Matrix *p_transform = NULL);\r\n\tvoid\t\t\tRemoveOverlapping();\r\n\t\r\n\tCObjectHookNode*\t\tGetFirstNode(){return mp_first_node;}\r\n\t\r\n\tScript::CArray *\tGetNodeArray(){return mp_node_array;}\r\n\tvoid\t\t\t\tSetNodeArray(Script::CArray *p_nodeArray){mp_node_array = p_nodeArray;}\r\n\r\n// accessor functions for the ObjectHook node\r\n// we only access their positions via the ObjectHook manager\r\n// as only the ObjectHook manager knows the transform of the object to\r\n// which they are attached\r\n// These nodes are \"instances\", in that the same node might be used in\r\n// more than one place\r\n// so these functions only make sense in conjunction with the ObjectHook_manager\r\n\tMth::Vector\tGetPos(const CObjectHookNode *p_node) \tconst;\t \r\n\r\nprivate:\r\n\tCObjectHookNode*  \t\t\tmp_first_node;\t\r\n\tbool\t\t\t\t\t\tm_is_transformed;\r\n\tMth::Matrix\t\t\t\t\tm_transform;\r\n\tScript::CArray *\t\t\tmp_node_array;\r\n\r\n};\r\n\r\n\r\n} \r\n\r\n\t\t\t\r\n#endif\t\t\t// #ifndef __OBJECTS_OBJECTHOOK_H\r\n\t\t\t\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/ped.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       ped.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/15/2000\r\n//****************************************************************************\r\n\r\n/*\r\n\tMD:  Derived from CMovingObject, the ped just adds some functionality\r\n\tfor jumping out of the way of the skater.  That's all!  Other than\r\n\tthat, the ped inherits all the abilities of the moving object class,\r\n\tsuch as having an animating model, that can follow paths, or play\r\n\tsounds, etc...\r\n*/\r\n\r\n/*\r\n\tGJ:  The above comment used to be true, but now peds are defined as\r\n\thaving skinned models and animations, running extra scripts to shut\r\n\toff extra bones, etc.  Some of this stuff should be moved up to\r\n\tthe CMovingObject level (in particular, the skinned model/anim stuff)\r\n*/\r\n\r\n// start autoduck documentation\r\n// @DOC ped\r\n// @module ped | None\r\n// @subindex Scripting Database\r\n// @index script | ped\r\n    \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/objects/ped.h>\r\n\r\n#include <gel/objman.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <sk/components/skaterproximitycomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/motioncomponent.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/movingobject.h>\r\n#include <sk/objects/pathob.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nconst float DEFAULT_PED_TURN_DIST = 2.0f;\r\nconst float DEFAULT_PED_MAX_VEL = 2.5f;\r\nconst float DEFAULT_PED_ACCELERATION = 4.0f;\r\nconst float DEFAULT_PED_DECELERATION = 1.0f;\r\nconst float DEFAULT_PED_STOP_DIST = 2.0f;\t\t// stopping distance from wp\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CreatePed(CGeneralManager* p_obj_man, Script::CStruct* pNodeData)\r\n{\r\n\tCMovingObject* pPed = new CMovingObject;\r\n\t\r\n\tpPed->MovingObjectCreateComponents();\r\n\r\n\tpPed->SetType( SKATE_TYPE_PED );\r\n\r\n\tDbg_MsgAssert(pPed, (\"Failed to create pedestrian.\"));\r\n\tp_obj_man->RegisterObject(*pPed);\r\n\t\r\n\t// GJ:  This should come before the model gets initialized\r\n\t// get position, from the node that created us:\r\n\tSkateScript::GetPosition( pNodeData, &pPed->m_pos );\r\n\t\t\r\n\tpPed->MovingObjectInit( pNodeData, p_obj_man );\r\n\r\n\tScript::RunScript( CRCD(0xf3eec45e,\"ped_add_components\"), pNodeData, pPed );\r\n\t// Finalize the components, after everything has been added\t\r\n\tpPed->Finalize();\r\n\tScript::RunScript( CRCD(0x955a2767,\"ped_init_model\"), pNodeData, pPed );\r\n\r\n\t// designer controlled variables:\r\n\t// set defaults, to be overridden by script values if they exist:\r\n\tObj::CMotionComponent* pMotionComponent = GetMotionComponentFromObject( pPed );\r\n\t\r\n\tpMotionComponent->m_max_vel = ( MPH_TO_INCHES_PER_SECOND ( DEFAULT_PED_MAX_VEL ) );\r\n\tpMotionComponent->m_acceleration = FEET_TO_INCHES( DEFAULT_PED_ACCELERATION );\r\n\tpMotionComponent->m_deceleration = FEET_TO_INCHES( DEFAULT_PED_DECELERATION );\r\n\tpMotionComponent->m_stop_dist = FEET_TO_INCHES( DEFAULT_PED_STOP_DIST );\r\n\tpMotionComponent->EnsurePathobExists( pPed );\r\n\tpMotionComponent->GetPathOb()->m_enter_turn_dist = FEET_TO_INCHES( DEFAULT_PED_TURN_DIST );\r\n\r\n\t// don't let his pitch get messed up when going up hills...\r\n\tpMotionComponent->m_movingobj_flags |= MOVINGOBJ_FLAG_NO_PITCH_PLEASE;\r\n\r\n\t// need to synchronize rendered model's position to initial world position\r\n\tGetModelComponentFromObject( pPed )->FinalizeModelInitialization();\r\n\r\n\t// now that the skeleton has been updated at least once,\r\n\t// we can turn off the extra bones that don't animate:\t\r\n\tScript::RunScript( CRCD(0x48ca2d26,\"ped_disable_bones\"), NULL, pPed );\r\n\tpPed->SetProfileColor(0xc000c0);\t\t\t\t// magenta = ped\r\n\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/ped.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Objects\r\n//* FILENAME:       ped.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/15/2000\r\n//****************************************************************************\r\n\r\n#ifndef __OBJECTS_PED_H\r\n#define __OBJECTS_PED_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n}\r\n\t\t\t\t   \r\nnamespace Obj\r\n{\r\n\r\n\tclass CGeneralManager;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\tvoid CreatePed(CGeneralManager* p_obj_man, Script::CStruct* pNodeData);\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_PED_H\r\n"
  },
  {
    "path": "Code/Sk/Objects/proxim.cpp",
    "content": "///////////////////////////////////////////////////////\r\n// Proxim.cpp\r\n\r\n\t\t  \r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/math.h>\r\n#include <gfx/camera.h>\r\n#include <gfx/nx.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <modules/FrontEnd/FrontEnd.h>\r\n#include <sk/objects/Proxim.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/objects/skater.h>\t\t   // used to get position of the skater's camera\r\n#include <sk/objects/moviecam.h>\r\n\r\n//#define\tDEBUG_PROXIM\r\n\r\nnamespace Obj\r\n{\r\n\r\nvoid Proxim_Init()\r\n{\r\n    Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\r\n\tif (skate_mod->mpProximManager)\r\n\t{\r\n\t\tProxim_Cleanup();\r\n\t}\r\n\tskate_mod->mpProximManager = new CProximManager();\r\n\tskate_mod->mpProximManager->m_pFirstNode = NULL;\r\n}\r\n\r\nvoid Proxim_Cleanup()\r\n{\r\n    Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tif (skate_mod->mpProximManager)\r\n\t{\r\n\t\tCProximNode *pNode = skate_mod->mpProximManager->m_pFirstNode;\t   \r\n\t\twhile (pNode)\r\n\t\t{\r\n\t\t\tCProximNode *pNext = pNode->m_pNext;\r\n\t\t\tdelete pNode;\r\n\t\t\tpNode = pNext;\t\t\t\r\n\t\t}\r\n\r\n\t\tdelete skate_mod->mpProximManager;\r\n\t\tskate_mod->mpProximManager = NULL;\r\n\t}\r\n}\r\n\r\n#define CHECKSUM_TERRAIN_TYPE\t0x54cf8532  // \"terrainType\"\r\n\r\nvoid Proxim_AddNode(int node,bool active)\r\n{\r\n//\tprintf (\"It's a Proxim (%d)\\n\",node);\r\n    Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tDbg_Assert(skate_mod->mpProximManager);\r\n\t\r\n\t// create a new Proxim node\t\t\t\t\t\t\t\t\t\t   \r\n\tCProximNode *pProximNode = new CProximNode();\r\n\r\n\t// Link into the head of the Proxim manager\t\t\t\t\t\t\t\t\t   \r\n\tpProximNode->m_pNext = skate_mod->mpProximManager->m_pFirstNode; \t\t\t\t\t\t\t  \r\n\tskate_mod->mpProximManager->m_pFirstNode = pProximNode;\r\n\r\n\tpProximNode->m_node = node;\r\n\r\n\tpProximNode->m_active = active;  // created at start or not?\r\n\t\r\n\tpProximNode->mp_sector = NULL;\r\n\tpProximNode->m_shape = CProximNode::vSHAPE_SPHERE;  \r\n\r\n\t// Get pointer to the Proxim data\t\r\n\tScript::CScriptStructure *pNode = SkateScript::GetNode(node);\r\n\t\r\n\t// Get name\r\n\tif (pNode->GetChecksum(\"name\",&pProximNode->m_name))\r\n\t{\r\n#ifdef\tDEBUG_PROXIM\r\n\t\tprintf (\"Proxim: Got Name %s\\n\",Script::FindChecksumName(pProximNode->m_name));\r\n#endif\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"No name in proxim node %d\\n\",node));\r\n\t}\r\n\r\n\t// Get shape\r\n\tuint32 shape_checksum;\r\n\tif (pNode->GetChecksum(\"shape\", &shape_checksum))\r\n\t{\r\n\t\tpProximNode->m_shape = CProximNode::sGetShapeFromChecksum(shape_checksum);\r\n\t}\r\n\r\n\t// Try to find geometry\r\n\tpProximNode->InitGeometry(Nx::CEngine::sGetMainScene()->GetSector(pProximNode->m_name));\r\n\r\n\tSkateScript::GetPosition(pNode,&pProximNode->m_pos);\r\n#ifdef\tDEBUG_PROXIM\t\t\t\t\r\n\t\tDbg_Message(\"Proxim: Pos = (%f, %f, %f)\", pProximNode->m_pos[X], pProximNode->m_pos[Y], pProximNode->m_pos[Z]);\r\n#endif\t\r\n\r\n\tpProximNode->m_type = 0;  \r\n\tpNode->GetInteger( 0x7321a8d6 /* type */, &pProximNode->m_type );\r\n#ifdef\tDEBUG_PROXIM\r\n\tprintf (\"Proxim:  Type = %d\\n\",pProximNode->m_type);\r\n#endif\r\n\tpNode->GetFloat (0xc48391a5 /*radius*/, &pProximNode->m_radius);  \r\n\tDbg_MsgAssert(pProximNode->mp_sector || pProximNode->m_radius > 0.0f,( \"Radius %f too small in proxim node %d\\n\",pProximNode->m_radius,node));\t\r\n#ifdef\tDEBUG_PROXIM\r\n\tprintf (\"Proxim:  Radius = %f\\n\",pProximNode->m_radius);\r\n#endif\t\r\n\tpProximNode->m_radius_squared = pProximNode->m_radius * pProximNode->m_radius;\t\r\n\r\n\tif (pNode->GetChecksum(0x2ca8a299,&pProximNode->m_script))\t\t// Checksum of TriggerScript\r\n\t{\r\n#ifdef\tDEBUG_PROXIM\r\n\t\tprintf (\"Proxim: Got Script %s\\n\",Script::FindChecksumName(pProximNode->m_script));\r\n#endif\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"No triggerscript in proxim node %d\\n\",node));\r\n\t}\r\n\r\n\t\r\n\tpProximNode->m_proxim_object = 0;\t\r\n\tpProximNode->m_active_objects = 0;\t\r\n\tpProximNode->m_active_scripts = 0;\t\r\n\tif (pNode->ContainsFlag(CRCD(0x5113f19c,\"ProximObject\")))\r\n\t{\r\n\t\t// for proxim objects, it's best if we start \"outside\" the objects\r\n\t\t// so if we are actually inside, then the event will trigger\r\n\t\tpProximNode->m_outside_flags = 0xffffffff;\t\t\t// say all outside\r\n\t\tpNode->GetChecksum(\"Name\",&pProximNode->m_proxim_object);\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// for non-proxim objects, it's best if we start \"inside\" the node\r\n\t\t// in case something is depending on the outside script being called first\r\n\t\t// to keep things shut off.  We'll do this by starting with it active\r\n\t\t// and then setting it to inactive.\r\n\t\tpProximNode->m_outside_flags = 0;\t\t\t// say all inside for now....\r\n\t\tpProximNode->m_active = true;\r\n\r\n\t\t// Set the script active flag for each skater that exists\r\n\t\tObj::CObject *p_obj;\r\n\t\tint object_id = 0;\r\n\t\twhile ((p_obj  = Obj::CCompositeObjectManager::Instance()->GetObjectByID(object_id)) && (object_id < 32))\r\n\t\t{\r\n\t\t\tObj::CSkater *p_skater = (Obj::CSkater *) p_obj;\r\n\t\t\tif (p_skater->IsLocalClient())\r\n\t\t\t{\r\n\t\t\t\tpProximNode->m_active_scripts |= 1 << object_id;\r\n\t\t\t}\r\n\t\t\tobject_id++;\r\n\t\t}\r\n\r\n\t\tpProximNode->SetActive(false);\r\n\t\tpProximNode->SetActive(active);\r\n\t}\r\n\t\t\t\t\r\n}\r\n\r\nvoid Proxim_AddedAll()\r\n{\r\n\t\r\n//\tprintf(\"Added all Proxims\\n\");\t\t \r\n\t\t \r\n    Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tDbg_Assert(skate_mod->mpProximManager);\r\n\tCProximNode *pProximNode = skate_mod->mpProximManager->m_pFirstNode;\r\n\twhile (pProximNode)\r\n\t{\r\n\t\t// do any final per-node processing here\r\n\t\tpProximNode = pProximNode->m_pNext;\r\n\t}\t\t\t\t \r\n\t\t\t\t \t\r\n}\t\t\t   \r\n\r\nvoid Proxim_SetActive( int node, int active )\r\n{\r\n    Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\r\n\tif (!skate_mod->mpProximManager) return;\r\n\t\r\n\tCProximNode *pProximNode = skate_mod->mpProximManager->m_pFirstNode;\r\n\twhile (pProximNode)\r\n\t{\r\n\t\tif (pProximNode->m_node == node)\r\n\t\t{\r\n\t\t\tpProximNode->SetActive(active);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tpProximNode = pProximNode->m_pNext;\r\n\t}\t\t\t\t \r\n}\r\n\r\nCProximNode * CProximManager::sGetNode(uint32 checksum)\r\n{\r\n    Mdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tDbg_Assert(skate_mod->mpProximManager);\r\n\tCProximNode *pProximNode = skate_mod->mpProximManager->m_pFirstNode;\r\n\twhile (pProximNode)\r\n\t{\r\n\t\tif (pProximNode->m_name == checksum)\r\n\t\t{\r\n\t\t\treturn pProximNode;\r\n\t\t}\r\n\t\tpProximNode = pProximNode->m_pNext;\r\n\t}\t\t\t\t \r\n\r\n\treturn NULL;\r\n}\r\n\r\n// Update all the proximity nodes\t\t\t\t\r\n// for a certain skater\r\n// checking for proximity either with the skater or the camera\t\t\t\t\t\r\nvoid Proxim_Update ( uint32 trigger_mask, CObject* p_script_target, const Mth::Vector& pos )\r\n{\r\n#if 0\t\t// TT9254: Too many things were having problems with this.  The proxim node scripts themselves\r\n\t\t\t// will have to do this.\r\n\t// Don't update if the game is paused\r\n\tif( Mdl::FrontEnd::Instance()->GamePaused() && !(Script::GetInteger(CRCD(0x45e46afd,\"goal_editor_placement_mode\"))) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n#if 0\r\n\t// Don't update if the game is playing a CamAnim\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tif ( skate_mod->GetMovieManager()->IsRolling() )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n#endif\r\n#endif\r\n\r\n\tCProximManager* proxim_manager = Mdl::Skate::Instance()->mpProximManager;\r\n\t\r\n\tif (!proxim_manager) return;\r\n\t\r\n\tCProximNode *pProximNode = proxim_manager->m_pFirstNode;\r\n\r\n\twhile (pProximNode)\r\n\t{\r\n\t\tif (!pProximNode->m_active)\r\n\t\t{\r\n\t\t\tpProximNode = pProximNode->m_pNext;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\t\r\n\t\tbool now_inside = pProximNode->CheckInside(pos);\r\n\r\n\t\tif ( trigger_mask & pProximNode->m_outside_flags)\r\n\t\t{\r\n\t\t\t// trigger is currently outside, check if moved to inside\r\n\t\t\tif (now_inside)\r\n\t\t\t{\r\n\t\t\t\r\n\t\t\t\tpProximNode->m_outside_flags &= ~trigger_mask;\r\n\t\t\t\t\r\n\t\t\t\tif ( ! pProximNode->m_proxim_object )\r\n\t\t\t\t{\r\n#ifdef\tDEBUG_PROXIM\t\t\t\t\r\n\t\t\t\tprintf (\"+++++ NOW INSIDE, mask = %d running script %s \\n\",trigger_mask, Script::FindChecksumName(pProximNode->m_script));\r\n#endif\t\t\t\t\r\n\t\t\t\t\tproxim_manager->m_inside_flag = true;\r\n\t\t\t\t\tproxim_manager->m_inside_flag_valid = true;\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (p_script_target)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_script_target->SpawnAndRunScript(pProximNode->m_script,pProximNode->m_node );\r\n\t\t\t\t\t\tDbg_MsgAssert(p_script_target->GetID() < 32, (\"Object ID %d is greater than 31\", pProximNode->m_proxim_object));\r\n\t\t\t\t\t\tpProximNode->m_active_scripts |= 1 << p_script_target->GetID();\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//Script::SpawnScript(pProximNode->m_script, NULL, NO_NAME, NULL, pProximNode->m_node );\r\n\t\t\t\t\t\tScript::RunScript(pProximNode->m_script);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tproxim_manager->m_inside_flag_valid = false;\r\n\t\t\t\t}\r\n\t\t\t\telse if (p_script_target)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Need to create an object with the id pProximNode->m_proxim_object\r\n\r\n#ifdef\tDEBUG_PROXIM\t\t\t\t\r\n\t\t\t\tprintf (\"+++++ NOW INSIDE, creating object %s running script %s \\n\",Script::FindChecksumName(pProximNode->m_proxim_object),Script::FindChecksumName(pProximNode->m_script));\r\n#endif\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\tObj::CCompositeObject* pObj = Obj::CCompositeObjectManager::Instance()->CreateCompositeObject();\r\n\t\t\t\t\tpObj->SetID(pProximNode->m_proxim_object + p_script_target->GetID());  // Mick mangle the proxim object ID with the player's ID\r\n\t\t\t\t\tpObj->m_pos = pProximNode->m_pos  ;\r\n\r\n\t\t\t\t\tDbg_MsgAssert(p_script_target->GetID() < 32, (\"Object ID %d is greater than 31\", pProximNode->m_proxim_object));\r\n\t\t\t\t\tpProximNode->m_active_objects |= 1 << p_script_target->GetID();\r\n\r\n\t\t\t\t\tScript::CStruct component_params;\t// ProximNode params\r\n\t\t\t\t\tif (pProximNode->HasGeometry())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Only add if we want the geometry used\r\n\t\t\t\t\t\tcomponent_params.AddChecksum(\"ProximNode\", pProximNode->m_name);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tpObj->CreateComponentsFromArray(Script::GetArray(\"proximobj_composite_structure\"), &component_params);   \r\n\t\t\t\t \tpObj->Finalize();\r\n   \r\n\t\t\t\t\tScript::CStruct params;\t// dummy empty params\r\n\t\t\t\t\tpObj->SwitchScript(pProximNode->m_script,&params);\r\n\t\t\t\t}\r\n\t\t\t}\t\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// skater is currently inside, check if moved outside\r\n\t\t\tif (!now_inside)\r\n\t\t\t{\r\n\t\t\t\tpProximNode->m_outside_flags |= trigger_mask;\t\t\t\t\r\n\t\t\t\tif ( ! pProximNode->m_proxim_object )\r\n\t\t\t\t{\r\n\t#ifdef\tDEBUG_PROXIM\t\t\t\t\r\n\t\t\t\t\tprintf (\"----- NOW OUTSIDE, mask = %d running script %s \\n\",trigger_mask,Script::FindChecksumName(pProximNode->m_script));\r\n\t#endif\t\t\t\t\r\n\t\t\t\t\tproxim_manager->m_inside_flag = false;\r\n\t\t\t\t\tproxim_manager->m_inside_flag_valid = true;\r\n\r\n\t\t\t\t\tif (p_script_target)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_script_target->SpawnAndRunScript(pProximNode->m_script,pProximNode->m_node );\r\n\t\t\t\t\t\tpProximNode->m_active_scripts &= ~(1 << p_script_target->GetID());\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//Script::SpawnScript(pProximNode->m_script, NULL, NO_NAME, NULL, pProximNode->m_node );\r\n\t\t\t\t\t\tScript::RunScript(pProximNode->m_script);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tproxim_manager->m_inside_flag_valid = false;\r\n\t\t\t\t}\t\t\t\t\t\t\t\t\t\r\n\t\t\t\telse if (p_script_target)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Need to create an object with the id pProximNode->m_proxim_object\r\n\r\n#ifdef\tDEBUG_PROXIM\t\t\t\t\r\n\t\t\t\t\tprintf (\"+++++ NOW OUTSIDE, killing %s running script %s \\n\",Script::FindChecksumName(pProximNode->m_proxim_object),Script::FindChecksumName(pProximNode->m_script));\r\n#endif\t\t\t\t\r\n\t\t\t\t\tObj::CObject *p_obj  = Obj::CCompositeObjectManager::Instance()->GetObjectByID(pProximNode->m_proxim_object  + p_script_target->GetID());\r\n\t\t\t\t\tif (p_obj)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_obj->MarkAsDead();\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\tpProximNode->m_active_objects &= ~(1 << p_script_target->GetID());\r\n\t\t\t\t}\r\n\t\t\t}\t\t\t\r\n\t\t}\t\t\r\n\t\tpProximNode = pProximNode->m_pNext;\r\n\t}\t\t\t\t \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCProximNode::EShape CProximNode::sGetShapeFromChecksum(uint32 checksum)\r\n{\r\n\tswitch (checksum)\r\n\t{\r\n\tcase 0xaa069978: // Sphere\r\n\t\treturn vSHAPE_SPHERE;\r\n\r\n\tcase 0xe460abde: // BoundingBox\r\n\t\treturn vSHAPE_BBOX;\r\n\r\n\tcase 0x3f1e5a7: // NonAxisAlignedBoundingBox\r\n\t\treturn vSHAPE_NON_AA_BBOX;\r\n\r\n\tcase 0x64fba415: // Cylinder\r\n\t\treturn vSHAPE_CYLINDER;\r\n\r\n\tcase 0x6aadf154: // Geometry\r\n\t\treturn vSHAPE_GEOMETRY;\r\n\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0, (\"Unknown shape checksum %x\\n\", checksum));\r\n\t\treturn vSHAPE_SPHERE;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCProximNode::SetActive(bool active)\r\n{\r\n\t// Check for changes\r\n\tif (m_active != active)\r\n\t{\r\n\t\tif (m_active)\r\n\t\t{\r\n\t\t\t// Turning off node, so treat like were going outside\r\n\t\t\tif ( m_proxim_object )\r\n\t\t\t{\r\n\t\t\t\t// Delete all created objects\r\n#ifdef\tDEBUG_PROXIM\t\t\t    \r\n\t\t\t\tprintf (\"----- SETTING ProximNode INACTIVE, killing %s running script %s \\n\",Script::FindChecksumName(m_proxim_object),Script::FindChecksumName(m_script));\r\n#endif\t\t\t\t\r\n\t\t\t\tint object_id = 0;\r\n\t\t\t\twhile (m_active_objects)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (m_active_objects & 0x1)\t// Check if this ID is turned on\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tObj::CObject *p_obj  = Obj::CCompositeObjectManager::Instance()->GetObjectByID(m_proxim_object + object_id);\r\n\t\t\t\t\t\tif (p_obj)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_obj->MarkAsDead();\t\t\t\t\t\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Advance ID\r\n\t\t\t\t\tm_active_objects = m_active_objects >> 1;\r\n\t\t\t\t\tobject_id++;\r\n\t\t\t\t}\r\n\t\t\t}\t\t\t\t\t\t\t\t\t\r\n\t\t\telse\r\n\t\t\t{\r\n#ifdef\tDEBUG_PROXIM\t\t\t\t\r\n\t\t\t\tprintf (\"----- SETTING ProximNode INACTIVE, running script %s \\n\",Script::FindChecksumName(m_script));\r\n#endif\t\t\t\t\r\n\t\t\t\tCProximManager* proxim_manager = Mdl::Skate::Instance()->mpProximManager;\r\n\r\n\t\t\t\tif (proxim_manager)\r\n\t\t\t\t{\r\n\t\t\t\t\tint object_id = 0;\r\n\t\t\t\t\twhile (m_active_scripts)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (m_active_scripts & 0x1)\t// Check if this ID is turned on\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tObj::CObject *p_obj  = Obj::CCompositeObjectManager::Instance()->GetObjectByID(object_id);\r\n\t\t\t\t\t\t\tDbg_MsgAssert(p_obj, (\"Can't find object to play script on\"));\r\n\t\t\t\t\t\t\tproxim_manager->m_inside_flag = false;\r\n\r\n\t\t\t\t\t\t\tproxim_manager->m_inside_flag_valid = true;\r\n\t\t\t\t\t\t\tp_obj->SpawnAndRunScript( m_script, m_node );\r\n\t\t\t\t\t\t\tproxim_manager->m_inside_flag_valid = false;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Advance ID\r\n\t\t\t\t\t\tm_active_scripts = m_active_scripts >> 1;\r\n\t\t\t\t\t\tobject_id++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Make everything outside\r\n\t\tm_outside_flags = 0xffffffff;\r\n\r\n\t\tm_active = active;\r\n\t}\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCProximNode::InitGeometry(Nx::CSector *p_sector)\r\n{\r\n\tmp_sector = p_sector;\r\n\r\n\tif (!mp_sector)\r\n\t{\r\n\t\t// No Geometry\r\n\t\tDbg_MsgAssert(m_shape == CProximNode::vSHAPE_SPHERE, (\"ProximNode %s with shape %d has no geometry.\", Script::FindChecksumName(m_name), m_shape));\r\n\t\treturn;\r\n\t}\r\n\r\n#ifdef\tDEBUG_PROXIM\t\t\t\t\r\n\tDbg_Message(\"Found Geometry for Proxim node %s at address %x\", Script::FindChecksumName(m_name), mp_sector);\r\n#endif\r\n\r\n\tswitch (m_shape)\r\n\t{\r\n\tcase CProximNode::vSHAPE_SPHERE:\r\n\t\tDbg_MsgAssert(0, (\"ProximNode with sphere shape has geometry.\"));\r\n\t\tbreak;\r\n\r\n\tcase CProximNode::vSHAPE_BBOX:\r\n\t\tm_bbox = mp_sector->GetBoundingBox();\r\n#ifdef\tDEBUG_PROXIM\t\t\t\t\r\n\t\tDbg_Message(\"Bounding box of geometry (%f, %f, %f) - (%f, %f, %f)\",\r\n\t\t\t\t\tm_bbox.GetMin()[X], m_bbox.GetMin()[Y], m_bbox.GetMin()[Z],\r\n\t\t\t\t\tm_bbox.GetMax()[X], m_bbox.GetMax()[Y], m_bbox.GetMax()[Z]);\r\n#endif\t\r\n\t\tbreak;\r\n\r\n\tcase CProximNode::vSHAPE_NON_AA_BBOX:\r\n\t\tDbg_MsgAssert(0, (\"ProximNode with non axis aligned bounding box shape not supported yet.\"));\r\n\t\tbreak;\r\n\r\n\tcase CProximNode::vSHAPE_CYLINDER:\r\n\t\tDbg_MsgAssert(0, (\"ProximNode with cylinder shape not supported yet.\"));\r\n\t\tbreak;\r\n\tcase CProximNode::vSHAPE_GEOMETRY:\r\n\t\tDbg_MsgAssert(0, (\"ProximNode with geometry shape not supported yet.\"));\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool\t\t\t\tCProximNode::HasGeometry() const\r\n{\r\n\treturn mp_sector != NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCProximNode::CheckInside(const Mth::Vector &object_pos) const\r\n{\r\n\tMth::Vector\t\tnode_to_object = object_pos - m_pos;\r\n\tfloat\t\t\tdist_squared = node_to_object.LengthSqr();\t   \r\n\r\n\tbool inside = false;\r\n\r\n\tswitch (m_shape)\r\n\t{\r\n\tcase vSHAPE_SPHERE:\r\n\t\tinside = (dist_squared <= m_radius_squared);\r\n\t\tbreak;\r\n\r\n\tcase vSHAPE_BBOX:\r\n\t\tinside = m_bbox.Within(object_pos);\r\n#ifdef\tDEBUG_PROXIM\r\n\t\tm_bbox.DebugRender(0xff0000ff);\r\n\t\t{\r\n\t\t\tMth::Vector closest_point;\r\n\t\t\tm_bbox.GetClosestIntersectPoint(object_pos, closest_point);\r\n//\t\t\tGfx::AddDebugStar(closest_point);\r\n\t\t}\r\n#endif //\tDEBUG_PROXIM\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0, (\"Can't handle ProximNode type %d\", m_shape));\r\n\t}\r\n\r\n\treturn inside;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector \t\tCProximNode::GetClosestIntersectionPoint(const Mth::Vector &object_pos) const\r\n{\r\n\tMth::Vector intersect_point;\r\n\r\n\tswitch (m_shape)\r\n\t{\r\n\tcase vSHAPE_SPHERE:\r\n\t\t{\r\n\t\t\t// Same for either within or outside sphere\r\n\t\t\tMth::Vector direction = object_pos - m_pos;\r\n\t\t\tdirection.Normalize();\r\n\t\t\tdirection *= m_radius;\r\n\r\n\t\t\tintersect_point = m_pos + direction;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\tcase vSHAPE_BBOX:\r\n\t\tm_bbox.GetClosestIntersectPoint(object_pos, intersect_point);\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0, (\"Can't handle ProximNode type %d\", m_shape));\r\n\t\tbreak;\r\n\t}\r\n\r\n#ifdef\tDEBUG_PROXIM\r\n//\tGfx::AddDebugStar(intersect_point);\r\n#endif //\tDEBUG_PROXIM\r\n\r\n\treturn intersect_point;\r\n}\r\n\r\n/*\r\n{\r\n\t// Node 572 (Mick Test)\r\n\tPosition = (-4060.666992,131.999329,-4604.379395)\r\n\tAngles = (0.000000,-3.141593,0.000000)\r\n\tName = TRG_Micks_test\r\n\tClass = ProximNode\r\n\tType = skater\r\n    radius = 1200\r\n\tTriggerScript = xxx_test\r\n}\r\n*/\r\n\r\n\r\n}\r\n\t\t\t   \r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/proxim.h",
    "content": "//////////////////////////////////////////\r\n// Proxim.h\r\n\r\n#ifndef __OBJECTS_Proxim_H\r\n#define __OBJECTS_Proxim_H\r\n\r\n#include <core\\math\\geometry.h>\r\n\r\n#include <gfx/camera.h>\r\n\r\nnamespace Nx\r\n{\r\n\tclass\tCSector;\r\n}\r\n\r\nnamespace Script\r\n{\r\n\tclass\tCScript;\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\r\n\tclass\tCSkater;\r\n\r\nclass CProximNode : public Spt::Class\r\n{\r\npublic:\r\n\tenum EShape\r\n\t{\r\n\t\tvSHAPE_SPHERE = 0,\r\n\t\tvSHAPE_BBOX,\t\t\t// Axis-aligned bounding box\r\n\t\tvSHAPE_NON_AA_BBOX,\t\t// Non-axis-aligned bounding box\r\n\t\tvSHAPE_CYLINDER,\t\t// Cylinder\r\n\t\tvSHAPE_GEOMETRY,\t\t// Geometry data\r\n\t};\r\n\r\n\t///////////\r\n\t// Functions\r\n\tvoid\t\tSetActive(bool active);\r\n\tvoid\t\tInitGeometry(Nx::CSector *p_sector);\r\n\tbool\t\tHasGeometry() const;\r\n\tbool\t\tCheckInside(const Mth::Vector &object_pos) const;\r\n\tMth::Vector GetClosestIntersectionPoint(const Mth::Vector &object_pos) const;\r\n\r\n\t// Checksum conversion functions\r\n\tstatic EShape sGetShapeFromChecksum(uint32 checksum);\r\n\r\n\t///////////\r\n\t// Variables\r\n\tint\t\t\tm_node;\t\t\t\t// Number of the node in the trigger array\r\n\tint \t\tm_link;\t\t\t\t// link number\r\n\tuint32\t\tm_name;\t\t\t\t// checksum of name of the node in the trigger array\r\n\tMth::Vector m_pos;\t\t\t\t// position of the node\r\n\tMth::Vector m_angles;\t\t\t// angles of the node\r\n\tbool \t\tm_active;\t\t\t// Proxim segment starting at this node: active or not?\r\n\r\n\tuint32 \t\tm_proxim_object;\t// checksum of name, if this is a ProximObject\r\n\tuint32\t\tm_active_objects;\t// bit number corresponds to originating object ID\r\n\tuint32\t\tm_active_scripts;\t// bit number corresponds to originating object ID\r\n\r\n\tint\t\t\tm_outside_flags;\t// bitmask of flags, 0 = inside the radius, 1 = outside\r\n\r\n\tint \t\tm_type;\r\n\tEShape \t\tm_shape;\r\n\r\n\t// Sphere data\r\n\tfloat\t\tm_radius;\r\n\tfloat\t\tm_radius_squared;\r\n\r\n\t// Geometry Data\r\n\tNx::CSector *mp_sector;\r\n\r\n\t// BBox data\r\n\tMth::CBBox\tm_bbox;\r\n\t\r\n\tfloat\t\tm_last_distance_squared;\r\n\t\r\n\tuint32 \t\tm_script;\r\n\r\n\tCProximNode *m_pNext;\r\n\r\n};\r\n\r\n \r\n\r\nvoid Proxim_AddNode(int node, bool active);\r\nvoid Proxim_Init();\r\nvoid Proxim_Cleanup();\r\nvoid Proxim_AddedAll();\r\n// activate/deactivate Proxim:\r\nvoid Proxim_SetActive( int node, int active);\r\nvoid Proxim_Update ( uint32 trigger_mask, CObject* p_script_target, const Mth::Vector& pos );\r\n\r\nclass CProximManager : public Spt::Class\r\n{\r\nprivate:\r\n\tstatic const int vMAX_NUM_PROXIM_TRIGGERS = 8 * sizeof(uint32);\r\n\t\r\npublic:\r\n\tCProximManager() { m_inside_flag_valid = false; }\r\n\r\n\tstatic CProximNode * sGetNode(uint32 checksum);\r\n\r\n\tCProximNode*  m_pFirstNode;\t\r\n\t\t\r\n\tuint32 GetProximTriggerMask ( int viewport );\r\n\t\r\n\tbool IsInsideFlagValid (   ) { return m_inside_flag_valid; }\r\n\tbool IsInside (   ) { return m_inside_flag; }\r\n\t\r\nprivate:\r\n\tbool m_inside_flag;\r\n\tbool m_inside_flag_valid;\r\n\t\r\n\tfriend void Proxim_Update ( uint32 trigger_mask, CObject* p_script_target, const Mth::Vector& pos );\r\n\tfriend CProximNode;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline uint32 CProximManager::GetProximTriggerMask ( int viewport )\r\n{\r\n\treturn 1 << viewport;\r\n}\r\n\r\n} \r\n\t\t\t\r\n#endif // #ifndef __OBJECTS_Proxim_H\r\n\t\t\t\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/rail.cpp",
    "content": "///////////////////////////////////////////////////////\r\n// rail.cpp\r\n\r\n#include <sk/objects/rail.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/math.h>\r\n#include <core/math/geometry.h>\r\n\r\n#include <gel/modman.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/environment/terrain.h>\r\n#include <gel/collision/collision.h>\r\n#include <gel/components/walkcomponent.h>\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/debuggfx.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <sk/objects/trickobject.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/ParkEditor2/ParkEd.h>\r\n#include <sk/scripting/nodearray.h>\r\n\t\t  \r\n// REMOVE\r\n#include <sk/objects/skater.h>\r\n\t\t  \r\n#ifdef\t__PLAT_NGPS__\t\r\n#include <gfx/nxviewman.h>\t\t\t// for camera\r\n#include <gfx/ngps/nx/line.h>\r\n#include <gfx/ngps/nx/render.h>\r\n#endif\r\n\r\n//#define\t\tDEBUG_EDITOR_RAILS\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\nvoid Rail_ComputeBB(Mth::Vector &pos1, Mth::Vector &pos2, Mth::Vector &bb_min, Mth::Vector &bb_max)\r\n{\r\n\tfloat x0 = pos1.GetX();\r\n\tfloat x1 = pos2.GetX();\r\n\tfloat min_x, max_x;\r\n\tif (x0 < x1)\r\n\t{\r\n\t\tmin_x = x0; max_x = x1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmin_x = x1; max_x = x0;\r\n\t}\r\n\r\n\tfloat y0 = pos1.GetY();\r\n\tfloat y1 = pos2.GetY();\r\n\tfloat min_y, max_y;\r\n\tif (y0 < y1)\r\n\t{\r\n\t\tmin_y = y0; max_y = y1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmin_y = y1; max_y = y0;\r\n\t}\r\n\r\n\tfloat z0 = pos1.GetZ();\r\n\tfloat z1 = pos2.GetZ();\r\n\tfloat min_z, max_z;\r\n\tif (z0 < z1)\r\n\t{\r\n\t\tmin_z = z0; max_z = z1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmin_z = z1; max_z = z0;\r\n\t}\r\n\r\n\tbb_min.Set(min_x, min_y, min_z);\r\n\tbb_max.Set(max_x, max_y, max_z);\r\n}\r\n\r\nCRailManager::CRailManager()\r\n{\r\n//\tmp_first_node = NULL;\r\n\tmp_nodes = NULL;\r\n\tmp_links = NULL;\r\n\tm_num_nodes = 0;\r\n\tm_is_transformed = false;\r\n\tmp_node_array = NULL;\r\n\t\r\n}\r\n\r\nCRailManager::~CRailManager()\r\n{\t \r\n\tCleanup();  \r\n}\r\n\r\nvoid CRailManager::Cleanup()\r\n{\r\n//\twhile (mp_first_node)\r\n//\t{\r\n//\t\tCRailNode *pNext = mp_first_node->m_pNext;\r\n//\t\tdelete mp_first_node;\r\n//\t\tmp_first_node = pNext;\t\t\t\r\n//\t}    \r\n\t\r\n\tm_num_nodes = 0;\r\n\t\r\n\tMem::Free(mp_nodes);\r\n\tmp_nodes = NULL;\r\n\t\r\n\t\r\n\tm_is_transformed = false;\t\r\n\t// Unhook from node array\r\n\tmp_node_array = NULL;\r\n}\r\n\r\n\r\n#define CHECKSUM_TERRAIN_TYPE\t0x54cf8532  // \"terrainType\"\r\n\r\n// Given two rail nodes that should be linked in a rail segment\r\n// then link them up as well as we are able\r\n// given that we only have a NEXT and a PREV pointer\r\n// so we give precedence to links to nodes that\r\n// are flagged \"DefaultLine\"\r\n\r\nvoid CRailManager::NewLink(CRailNode *p_from, CRailNode *p_to)\r\n{\r\n\t// one of our links links to this node\r\n\t// so we need to establish next and prev links\r\n\t// or if they are established, then possibly override them\t\t\t\r\n\tif (!p_from->m_pNextLink)\r\n\t{\r\n\t\t// this is the first time we are linking to something\r\n\t\tp_from->m_pNextLink = p_to;\r\n\t\tRail_ComputeBB(p_from->m_pos, p_to->m_pos, p_from->m_BBMin, p_from->m_BBMax);\r\n\t}\r\n\telse\r\n\t{\r\n\t\r\n\t\t// already linked to something, so only override it\r\n\t\t// if the new node is not DEFAULT_LINE\r\n\t\tif (p_to->GetFlag(DEFAULT_LINE))\r\n\t\t{\r\n\t\t\t// This new link is DEFAULT_LINE\r\n\t\t\t// so, as long as the previous link was not, we can override it\r\n\t\t\tDbg_MsgAssert(!p_from->m_pNextLink->GetFlag(DEFAULT_LINE),\r\n\t\t\t\t\t\t  (\"Node %d links to both %d and %d and both are DEFAULT_LINE\",\r\n\t\t\t\t\t\t   p_from->m_node,p_from->m_pNextLink->m_node,p_to->m_node));\r\n\t\t\t// Overriding an existing NEXT link\r\n\t\t\tp_from->m_pNextLink = p_to;\r\n\t\t\tRail_ComputeBB(p_from->m_pos, p_to->m_pos, p_from->m_BBMin, p_from->m_BBMax);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// The new link is not DEFAULT_LINE\r\n\t\t\t// if the old one was, then leave it\r\n\t\t\t// if neither is, then leave it, and maybe print a warning?\r\n\t\t\t\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Now handle the PREV link back from p_to to p_from\r\n\t\r\n\tif (!p_to->m_pPrevLink)\r\n\t{\r\n\t\tp_to->m_pPrevLink = p_from;\r\n\t}\r\n\telse\r\n\t{\r\n\r\n\t\t// something already linked to p_from via prev from p_to\r\n\t\tif (p_from->GetFlag(DEFAULT_LINE))\r\n\t\t{\r\n\t\t\t// this is the default line, so make sure the old PREV node was not\r\n\t\t\tDbg_MsgAssert(!p_to->m_pPrevLink->GetFlag(DEFAULT_LINE),\r\n\t\t\t\t\t\t  (\"Node %d linked from both %d and %d and both are DEFAULT_LINE\",\r\n\t\t\t\t\t\t   p_to->m_node,p_to->m_pPrevLink->m_node,p_from->m_node));\r\n\t\t\t\r\n\t\t\tp_to->m_pPrevLink = p_from;\r\n\t\t\t// Note, we don't re-calculate the bounding box here\r\n\t\t\t// as that only applies to NEXT links\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\nvoid CRailManager::AddRailNode(int node_number, Script::CStruct *p_node_struct)\r\n{\r\n\r\n\t\t\t\t\t\t\t\r\n\t// create a new rail node\t\t\t\t\t\t\t\t\t\t   \r\n//\tCRailNode *pRailNode = new CRailNode();\r\n\t// Link into the head of the rail manager\t\r\n\t// Note, this must be done before we attempt to link up with other nodes\t\t\t\t\t\t\t\t   \r\n//\tpRailNode->m_pNext = mp_first_node; \t\t\t\t\t\t\t  \r\n//\tmp_first_node = pRailNode;\r\n\t\r\n\tCRailNode *pRailNode = &mp_nodes[m_current_node];\r\n\tCRailLinks *pLinkNode = &mp_links[m_current_node++];\r\n\t\r\n\tuint32 class_checksum;\r\n\tp_node_struct->GetChecksum(CRCD(0x12b4e660, \"class\"), &class_checksum);\r\n\tbool climbing = class_checksum == CRCD(0x30c19600, \"ClimbingNode\");\r\n\t\r\n\tuint32 type_checksum;\r\n\tp_node_struct->GetChecksum(CRCD(0x7321a8d6, \"type\"), &type_checksum);\r\n\r\n\tpRailNode->m_pNextLink = NULL;\r\n\tpRailNode->m_pPrevLink = NULL;\r\n\tfor (int i=0;i<MAX_RAIL_LINKS;i++)\r\n\t{\r\n\t\tpLinkNode->m_link[i] = -1;\t\t\t\t\t\t// say it's not linked to anything, initially\r\n\t}\r\n\tpRailNode->m_node = node_number;\t\t\t// The node_number is use primarily for calculating links\r\n\tpRailNode->m_flags = 0;\t\t\t\t\t\t// all flags off by default\r\n\tpRailNode->SetActive(p_node_struct->ContainsFlag( 0x7c2552b9 /*\"CreatedAtStart\"*/ ));\t// created at start or not?\r\n\t\r\n    // set the position from the node structure\r\n\tSkateScript::GetPosition(p_node_struct,&pRailNode->m_pos);\r\n\r\n\tif (p_node_struct->ContainsFlag( 0xf4c67f0f /*\"LipOverride\"*/))\r\n\t{\r\n\t\tpRailNode->m_flags.Set(LIP_OVERRIDE);\r\n\t}\r\n\r\n\tif (p_node_struct->ContainsFlag(  0x4de721de/*\"DefaultLine\"*/))\r\n\t{\r\n\t\tpRailNode->m_flags.Set(DEFAULT_LINE);\r\n\t}\r\n\t\r\n\tif (climbing)\r\n\t{\r\n\t\tpRailNode->m_flags.Set(ONLY_CLIMBING);\r\n\t\tpRailNode->m_flags.Set(LADDER, type_checksum == CRCD(0xc84243da, \"Ladder\"));\r\n\t}\r\n\t\r\n\tpRailNode->m_flags.Set(NO_HANG_WITH_RIGHT_ALONG_RAIL, p_node_struct->ContainsFlag(CRCD(0xf6dd21ca, \"HangLeft\")));\r\n\tpRailNode->m_flags.Set(NO_HANG_WITH_LEFT_ALONG_RAIL, p_node_struct->ContainsFlag(CRCD(0x5e9ce29b, \"HangRight\")));\r\n\tpRailNode->m_flags.Set(NO_CLIMBING, p_node_struct->ContainsFlag(CRCD(0xf22bfc6d, \"NoClimbing\")));\r\n    \r\n\tif (climbing)\r\n\t{\r\n\t\t// set the orientation from the node structure\r\n\t\tMth::Vector angles;\r\n\t\tSkateScript::GetAngles(p_node_struct, &angles);\r\n\t\tMth::Matrix matrix;\r\n\t\tpRailNode->m_orientation = matrix.SetFromAngles(angles);\r\n\t}\r\n\r\n\t// no terrain types for climbing nodes\r\n\tif (!climbing)\r\n\t{\r\n\t\tpRailNode->m_terrain_type = 0;  // default terrain type...\r\n\t\tuint32 terrain_checksum;\r\n\t\tint terrain = 0;\r\n\t\tp_node_struct->GetChecksum( CHECKSUM_TERRAIN_TYPE, &terrain_checksum, Script::ASSERT );\r\n\t\tterrain = Env::CTerrainManager::sGetTerrainFromChecksum(terrain_checksum);\r\n\t\tDbg_MsgAssert(terrain >= 0 && terrain < 256,(\"Rail node %d, terrain type %d too big\\n\",node_number,terrain));\r\n\t\tpRailNode->m_terrain_type = (uint8) terrain ;\r\n\t}\r\n\r\n\r\n\tint links = SkateScript::GetNumLinks(p_node_struct);\r\n\tif (links)\r\n\t{\r\n\t\tDbg_MsgAssert(links <= MAX_RAIL_LINKS,(\"Rail node %d has %d linkes, max is %d\",node_number,links,MAX_RAIL_LINKS));\r\n\t\tfor (int i=0;i<links;i++)\r\n\t\t{\r\n\t\t\tpLinkNode->m_link[i] = SkateScript::GetLink(p_node_struct,i);\r\n\t\t}\r\n\t}\t\r\n\t\r\n\tRail_ComputeBB(pRailNode->m_pos, pRailNode->m_pos, pRailNode->m_BBMin, pRailNode->m_BBMax);\r\n\r\n// Linking is now donw after they are all loaded\r\n// Making it O(n) rather than O(n^2)\r\n/*\t\r\n\t// try going through all the nodes to find one linked to this one\r\n\t// and to find the target node, if it exists\r\n\tCRailNode *p_link_node = pRailNode->m_pNext;\r\n\twhile (p_link_node)\r\n\t{\r\n\t\t// Check links from the new node to all the existing nodes\r\n\t\tfor (int i=0;i<MAX_RAIL_LINKS;i++)\r\n\t\t{\r\n\t\t\tif (pRailNode->m_link[i] == p_link_node->m_node)\r\n\t\t\t{\r\n\t\t\t\tNewLink(pRailNode,p_link_node);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// check links from the existing nodes to the new node\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\tfor (int i=0;i<MAX_RAIL_LINKS;i++)\r\n\t\t{\r\n\t\t\tif (p_link_node->m_link[i] == pRailNode->m_node)\r\n\t\t\t{\r\n\t\t\t\tNewLink(p_link_node,pRailNode);\r\n\t\t\t}\r\n\t\t}\r\n\t   \tp_link_node = p_link_node->m_pNext;\t\t\r\n\t}\r\n*/\t\r\n}\r\n\r\n// returns a positive number that is the amount of an axis\r\n// required to totally encompass the 1D line segments a-b and c-d\r\nstatic inline float span_4(float a, float b, float c, float d)\r\n{\r\n\tfloat min = a;\r\n\tif (b < min) min = b;\r\n\tif (c < min) min = c;\r\n\tif (d < min) min = d;\r\n\tfloat max = a;\r\n\tif (b > max) max = b;\r\n\tif (c > max) max = c;\r\n\tif (d > max) max = d;\r\n\treturn max-min;\t\r\n}\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n// returns the amount two 1D line segments overlap\r\n// works by adding together the length of both lines\r\n// and then subtracting the \"span\" of the the min and max points of the lines\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\nstatic inline float overlap(float a, float b, float c, float d)\r\n{\r\n\treturn  Mth::Abs(b-a) + Mth::Abs(d-c) - span_4(a,b,c,d);\r\n}\r\n\r\nstatic inline bool nearly_the_same(float a, float b, float c, float d, float nearly = 1.0f)\r\n{\r\n\treturn ( Mth::Abs(a-b) < nearly\r\n\t\t && Mth::Abs(b-c) < nearly\r\n\t\t && Mth::Abs(c-d) < nearly);\r\n}\t\r\n\r\nvoid\tCRailManager::RemoveOverlapping()\r\n{\r\n\tprintf (\"Starting overlapping rail removal\\n\");\r\n\t\r\n\tint\tremoved =0;\r\n//\tCRailNode *pRailNode = mp_first_node;\r\n//\twhile (pRailNode)\r\n//\t{\r\n\tfor (int node=0;node<m_num_nodes;node++)\r\n\t{\r\n\t\tCRailNode *pRailNode = &mp_nodes[node];\r\n\t\tif (pRailNode->m_pNextLink)\t   \t// it's a segment\r\n\t\t{\r\n\r\n\t\t\tMth::Vector\tstart = pRailNode->m_pos;\r\n\t\t\tMth::Vector\tend = pRailNode->m_pNextLink->m_pos;\r\n\r\n\t\t\tMth::Vector dir = end-start;\r\n\t\t\tdir.Normalize();\r\n\r\n\t\t\t// we expand the bounding box, as they might not really be that close\t\t\t\r\n\t\t\tMth::Vector bb_min = pRailNode->m_BBMin;\r\n\t\t\tbb_min[X] -= 16.0f;\r\n\t\t\tbb_min[Y] -= 16.0f;\r\n\t\t\tbb_min[Z] -= 16.0f;\r\n\t\t\tMth::Vector bb_max = pRailNode->m_BBMax;\r\n\t\t\tbb_max[X] += 16.0f;\r\n\t\t\tbb_max[Y] += 16.0f;\r\n\t\t\tbb_max[Z] += 16.0f;\r\n\t\t\t\r\n\t\t\t\r\n\t\t\tint check_node = node+1;\r\n//\t\t\tCRailNode *pCheckNode = pRailNode->m_pNext;\r\n\t\t\twhile (check_node<m_num_nodes && pRailNode->IsActive())\r\n\t\t\t{\r\n\t\t\t\tCRailNode *pCheckNode = &mp_nodes[check_node];\r\n\t\t\t\tif (pCheckNode->m_pNextLink)\t   \t// it's a segment\r\n\t\t\t\t{\r\n\t\t\t\t   \t// first check to see if bounding boxes overlap\r\n\t\t\t\t\t  \r\n\t\t\t\t\tif (!(pCheckNode->m_BBMin.GetX() > bb_max.GetX()))\r\n\t\t\t\t\tif (!(pCheckNode->m_BBMax.GetX() < bb_min.GetX()))\r\n\t\t\t\t\tif (!(pCheckNode->m_BBMin.GetZ() > bb_max.GetZ()))\r\n\t\t\t\t\tif (!(pCheckNode->m_BBMax.GetZ() < bb_min.GetZ()))\r\n\t\t\t\t\tif (!(pCheckNode->m_BBMin.GetY() > bb_max.GetY()))\r\n\t\t\t\t\tif (!(pCheckNode->m_BBMax.GetY() < bb_min.GetY()))\r\n\t\t\t\t\t{\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t// bounding boxes overlap \t\t\t\t\t\t\r\n\t\t\t\t\t\t// check to see if rails are roughly parallel\r\n\t\t\t\t\t\tMth::Vector check_start = pCheckNode->m_pos;\r\n\t\t\t\t\t\tMth::Vector check_end = pCheckNode->m_pNextLink->m_pos;\r\n\t\t\t\t\t\tMth::Vector check_dir = check_end - check_start;\r\n\r\n\t\t\t\t\t\tcheck_dir.Normalize();\t\t\t\t\t\t\r\n\t\t\t\t\t\tfloat dot = Mth::DotProduct(dir, check_dir);\r\n//\t\t\t\t\t\tprintf (\"Bounding Box Overlap, dot = %f\\n\",dot);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif (dot < -0.99f || dot > 0.99f)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// lines are roughly parallel\r\n\t\t\t\t\t\t\t// so check if they overlap significantly in at least one axis\r\n\t\t\t\t\t\t\t// and/or are very close in one other axis\r\n\t\t\t\t\t\t\t// we only check X and Z\r\n\t\t\t\t\t\t\t// as we don't have any vertical rails in the park\r\n\t\t\t\t\t\t\t// editor\r\n\t\t\t\t\t\t\t// (note, I'm prematurely optimizing here...)\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tint overlaps = 0;\r\n\t\t\t\t\t\t\tint close =  0;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t// now check the distance between the lines\r\n\t\t\t\t\t\t\t// which is the components of start -> check_start\r\n\t\t\t\t\t\t\t// that is perpendicular to start -> end\r\n\t\t\t\t\t\t\tconst float significant = 6.0f;\t// six inches is significant, I feel...\r\n\t\t\t\t\t\t\tMth::Vector\ts_cs = check_start - start;\r\n\t\t\t\t\t\t\tMth::Vector\ts_e = end - start;\r\n\t\t\t\t\t\t\ts_e.Normalize();\r\n\t\t\t\t\t\t\tMth::Vector perp = s_cs;\r\n\t\t\t\t\t\t\tperp.ProjectToPlane(s_e); \r\n\t\t\t\t\t\t\tif ( perp.Length()<significant)\r\n\t\t\t\t\t\t\t{\r\n\t\r\n//\t\t\t\t\t\t\t\tprintf (\"(%.2f,%.2f),(%.2f,%.2f),(%.2f,%.2f),(%.2f,%.2f)\\n\",\r\n//\t\t\t\t\t\t\t\tstart[X],start[Z],end[X],end[Z],\r\n//\t\t\t\t\t\t\t\tcheck_start[X],check_start[Z],check_end[X],check_end[Z]);\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tif (overlap(start[X],end[X],check_start[X],check_end[X]) > significant)\r\n\t\t\t\t\t\t\t\t\toverlaps++;\r\n\t\t\t\t\t\t\t\tif (overlap(start[Z],end[Z],check_start[Z],check_end[Z]) > significant)\r\n\t\t\t\t\t\t\t\t\toverlaps++;\r\n\t\t\t\t\t\t\t\tif (nearly_the_same(start[X],end[X],check_start[X],check_end[X],6.0f))\r\n\t\t\t\t\t\t\t\t\tclose++;\r\n\t\t\t\t\t\t\t\tif (nearly_the_same(start[Z],end[Z],check_start[Z],check_end[Z],6.0f))\r\n\t\t\t\t\t\t\t\t\tclose++;\r\n//\t\t\t\t\t\t\t\tprintf (\"dot close, overlaps = %d, close = %d\\n\",overlaps,close);\r\n\t\t\t\t\t\t\t\tif (overlaps + close >= 2)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// it's a duplicate\r\n//\t\t\t\t\t\t\t\t\tprintf(\"Removing duplicate rail !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\\n\");\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t// add a magenta line for rails that have been removed\r\n\t\t\t\t\t\t\t\t\t#ifdef\t\tDEBUG_EDITOR_RAILS\r\n\t\t\t\t\t\t\t\t\tpRailNode->m_pos += Mth::Vector(0.0f,2.0f,0.0f);\r\n\t\t\t\t\t\t\t\t\tpRailNode->m_pNextLink->m_pos += Mth::Vector(0.0f,2.0f,0.0f);\r\n\t\t\t\t\t\t\t\t\tGfx::AddDebugLine( pRailNode->m_pos, pRailNode->m_pNextLink->m_pos, MAKE_RGB( 255, 0, 255 ),MAKE_RGB( 255,0, 255 ) );\r\n\t\t\t\t\t\t\t\t\tpRailNode->m_pos -= Mth::Vector(0.0f,2.0f,0.0f);\r\n\t\t\t\t\t\t\t\t\tpRailNode->m_pNextLink->m_pos -= Mth::Vector(0.0f,2.0f,0.0f);\r\n\t\t\t\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\tremoved ++;\r\n\t\t\t\t\t\t\t\t\t// Remove the one that is lower\r\n\t\t\t\t\t\t\t\t\tif (pRailNode->m_pos[Y] < pCheckNode->m_pos[Y])\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\tpRailNode->SetActive(false);\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\tpCheckNode->SetActive(false);\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tcheck_node++;\r\n//\t\t\t\tpCheckNode = pCheckNode->m_pNext;\r\n\t\t\t}\t\t\t\t\r\n\t\t}\r\n//\t\tpRailNode = pRailNode->m_pNext;\r\n\t}\t\t \r\n\tprintf (\"Done overlapping rail removal, removed %d\\n\", removed);\r\n}\r\n\r\n\r\nvoid CRailManager::AddedAll()\r\n{\r\n\t\r\n//\tprintf(\"Added all rails\\n\");\t\t \r\n\r\n\t#if 1\r\n\tif (Ed::CParkEditor::Instance()->UsingCustomPark()) \t\t// is it a custom park???\r\n\t{\r\n\t\t// yes, so remove overlapping rails\r\n\t\tRemoveOverlapping();\t\r\n\t}\t \r\n\t#endif\r\n\r\n\t\r\n}\t\t\t   \r\n\r\nvoid CRailManager::SetActive( int node, int active, bool wholeRail )\r\n{\r\n\t\r\n//\tCRailNode *pRailNode = mp_first_node;\r\n//\twhile (pRailNode)\r\n\tfor (int check_node = 0;check_node<m_num_nodes;check_node++)\r\n\t{\r\n\t\tCRailNode *pRailNode = &mp_nodes[check_node];\r\n\t\t\r\n\t\tif (pRailNode->m_node == node)\r\n\t\t{\r\n\t\t\tif ( wholeRail )\r\n\t\t\t{\r\n\t\t\t\twhile ( pRailNode )\r\n\t\t\t\t{\r\n\t\t\t\t\tpRailNode->SetActive(active);\r\n\t\t\t\t\tpRailNode = pRailNode->m_pNextLink;\r\n\t\t\t\t}\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tpRailNode->SetActive(active);\r\n\t\t\treturn;\r\n\t\t}\r\n//\t\tpRailNode = pRailNode->m_pNext;\r\n\t}\t\t\t\t \r\n}\r\n\r\nbool CRailManager::IsActive( int node )\r\n{\r\n//\tCRailNode *pRailNode = mp_first_node;\r\n//\twhile (pRailNode)\r\n\tfor (int check_node = 0;check_node<m_num_nodes;check_node++)\r\n\t{\r\n\t\tCRailNode *pRailNode = &mp_nodes[check_node];\r\n\t\tif (pRailNode->m_node == node)\r\n\t\t{\r\n\t\t\treturn ( pRailNode->GetActive() );\r\n\t\t}\r\n//\t\tpRailNode = pRailNode->m_pNext;\r\n\t}\r\n\treturn ( false );\r\n}\r\n\r\n\r\n// A node in the node array has moved (due to realtime editing)\r\n// so find that node here, and update the position\r\n// and update bounding boxes as needed \r\n//\r\n\r\nvoid CRailManager::MoveNode( int node, Mth::Vector &pos )\r\n{\r\n\tfor (int check_node = 0;check_node<m_num_nodes;check_node++)\r\n\t{\r\n\t\tCRailNode *pRailNode = &mp_nodes[check_node];\r\n\t\t\r\n\t\tif (pRailNode->m_node == node)\r\n\t\t{\r\n\t\t\t// Set The position\r\n\t\t\tpRailNode->m_pos = pos;\r\n\t\t\t\r\n\t\t\t// calculate the bounding box of any segment this node starts\r\n\t\t\t// (there can be only one)\r\n\t\t\tif (pRailNode->GetNextLink())\r\n\t\t\t{\r\n\t\t\t\tMth::Vector from_pos = pRailNode->m_pos; \r\n\t\t\t\tMth::Vector to_pos = pRailNode->GetNextLink()->m_pos;\r\n\t\t\t\tRail_ComputeBB(from_pos ,to_pos , pRailNode->m_BBMin, pRailNode->m_BBMax);\t\t\t\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Check to see if there are any nodes leading to this one\r\n\t\t\t// (this initial check is only for speed)\r\n\t\t\tif (pRailNode->GetPrevLink())\r\n\t\t\t{\r\n\t\t\t\t// There is one, but there might be more that one\r\n\t\t\t\t// the only way to know, is to go through all the nodes and see if any points to this one\r\n\t\t\t\t// \r\n\t\t\t\tfor (int from_node = 0;from_node<m_num_nodes;from_node++)\r\n\t\t\t\t{\r\n\t\t\t\t\tCRailNode *p_from = &mp_nodes[check_node];\r\n\t\t\t\t\tif (p_from->GetNextLink() == pRailNode)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tRail_ComputeBB(p_from->m_pos, pRailNode->m_pos, p_from->m_BBMin, p_from->m_BBMax);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// There is only going to be one mathcing node, so we can now return\t\t\r\n\t\t\treturn;\r\n\t\t} // end if (pRailNode->m_node == node)\r\n\t}\t\t\t\t \r\n}\r\n\r\n\r\n\r\n\r\n// Given a velocity, and a rail node\r\n// then see which side of the rail (left or right)\r\n// has no collision\r\n// returns -1 if left, 0 if neither or both, and +1 if right\r\n// Used in the park editor to give preference to those\r\n// rails that keep the same sideness as the prior rail we were on\r\nint\tCRailNode::Side(const Mth::Vector &vel) const\r\n{\r\n\tMth::Vector Start = m_pos;\r\n\tMth::Vector End = \tm_pNextLink->m_pos;\r\n\r\n\tCFeeler\tfeeler;\r\n\r\n // Find a point \"Mid\", which is 1/4 of the way along the rail   \r\n // and lowered six inches\r\n\tMth::Vector\tMid = (Start + End) / 2.0f;\t\t\t// Half way along\r\n\tMid = Start + ((Mid - Start) / 2.0f);\t\t    // quarter of the way along\t\r\n\tMid[Y] -= 6.0f;\t\t\t\t\t\t\t\t\t// lowered a bit\r\n\r\n// Find a vector \"Side\" which is horizontal, perpendicular to the rail, and 4 inches long\t\r\n\tMth::Vector\tSide = End - Start;\t   \t\t\t// vector along the rail\r\n\tSide[Y] = 0.0f;\t\t\t\t\t\t\t\t// horizontal\r\n\tSide.Normalize(4.0f);\t\t\t\t\t\t// this is half the width of the thickest rail.  Was 4.0, changed for Tokyo mega funbox\r\n\tfloat temp = Side[X];\t\t\t \t\t\t\t// make perpendicular to rail\r\n\tSide[X] = Side[Z];\r\n\tSide[Z] = -temp;\r\n\r\n\r\n\tbool\tleft = false;\r\n\tbool\tright = false;\r\n\t\r\n// if collision above me, left to right\r\n\tfeeler.SetLine(Mid + Side, Mid-Side);\t\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tleft = true;\r\n\t}\r\n\r\n// if collision above me, right to left\r\n\tfeeler.FlipDirection();\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tright = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t}\r\n\t\r\n\tint side = 0;\r\n\tif (left && !right)\r\n\t{\r\n\t\tside = -1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (right && ! left)\r\n\t\t{\r\n\t\t\tside = 1;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// flip is we are going the opposite direction on the rail\r\n\tif ( side && (Mth::DotProduct(vel,End-Start) < 0.0f) )\r\n\t{\r\n\t\tside = -side;\r\n\t}\r\n\t\r\n\treturn side;\t\r\n}\r\n\r\n\r\nvoid CRailManager::UpdateTransform(Mth::Matrix& transform)\r\n{\r\n\r\n\tm_is_transformed = true;\r\n\tm_transform = transform;\r\n}\r\n\r\n\r\nbool CRailManager::CheckForLadderRail ( const Mth::Vector& pos, float max_horizontal_snap_distance, float max_vertical_snap_distance, bool up, CWalkComponent* p_walk_component, SLadderRailData& rail_data, const CRailNode** pp_rail_node )\r\n{\r\n    float max_horizontal_snap_distance_sqr = Mth::Sqr(max_horizontal_snap_distance);\r\n    \r\n    for (int check_node_idx = m_num_nodes; check_node_idx--; )\r\n    {\r\n        CRailNode* p_node = &mp_nodes[check_node_idx];\r\n        \r\n\t\tif (!p_node->GetFlag(LADDER) || !p_node->GetActive()) continue;\r\n        \r\n        // quick oriented bounding box check\r\n        if (Mth::Abs(p_node->m_pos[X] - pos[X]) > max_horizontal_snap_distance) continue;\r\n        if (Mth::Abs(p_node->m_pos[Z] - pos[Z]) > max_horizontal_snap_distance) continue;\r\n        if (Mth::Abs(p_node->m_pos[Y] - pos[Y]) > max_vertical_snap_distance) continue;\r\n        \r\n        // actual distance check\r\n        Mth::Vector offset = p_node->m_pos - pos;\r\n        if (offset[X] * offset[X] + offset[Z] * offset[Z] > max_horizontal_snap_distance_sqr) continue;\r\n        \r\n        // find the ladder's partiner node\r\n        const CRailNode* p_partiner_node = p_node->GetNextLink() ? p_node->GetNextLink() : p_node->GetPrevLink();\r\n        Dbg_Assert(p_partiner_node);\r\n        \r\n\t\tif (up)\r\n\t\t{\r\n\t\t\tif (!p_walk_component->FilterLadderUpRail(p_node->m_pos, p_partiner_node->m_pos, GetMatrix(p_node), rail_data)) continue;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (!p_walk_component->FilterLadderDownRail(p_partiner_node->m_pos, p_node->m_pos, GetMatrix(p_partiner_node), rail_data)) continue;\r\n\t\t}\r\n        \r\n        // for now we do no comparison between ladders; they should be sparce enough that we can just take the first ladder rail we find\r\n\t\t\r\n\t\t// return the bottom node of the ladder\r\n\t\tif (up)\r\n\t\t{\r\n\t\t\t*pp_rail_node = p_node;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t*pp_rail_node = p_partiner_node;\r\n\t\t}\r\n        return true;\r\n    }\r\n    \r\n    return false;\r\n}\r\n\r\nbool CRailManager::CheckForAirGrabLadderRail ( const Mth::Vector& start_pos, const Mth::Vector& end_pos, CWalkComponent* p_walk_component, SLadderRailData& rail_data, const CRailNode** pp_rail_node )\r\n{\r\n\t*pp_rail_node = NULL;\r\n\t\r\n\tMth::Line movement;\r\n\tmovement.m_start = start_pos;\r\n\tmovement.m_end = end_pos;\r\n\t\r\n\t// find bounding box for movement\r\n\tMth::Vector bb_min, bb_max;\r\n\tRail_ComputeBB(movement.m_start, movement.m_end, bb_min, bb_max);\r\n\tfloat snap_dist_sqr = Script::GetFloat(CRCD(0x30ce7f2c, \"Climb_Max_Snap\"));\r\n\tbb_min.Set(bb_min.GetX() - snap_dist_sqr, bb_min.GetY() - snap_dist_sqr, bb_min.GetZ() - snap_dist_sqr);\t\r\n\tbb_max.Set(bb_max.GetX() + snap_dist_sqr, bb_max.GetY() + snap_dist_sqr, bb_max.GetZ() + snap_dist_sqr);\t\r\n\tsnap_dist_sqr *= snap_dist_sqr;\r\n\t\r\n\tfloat closest_dist_sqr = 10000000.0f * 10000000.0f;\r\n\r\n\tfor (int check_node = 0; check_node < m_num_nodes; check_node++)\r\n\t{\r\n\t\tCRailNode* pRailNode = &mp_nodes[check_node];\r\n\t\tif (!pRailNode->GetFlag(LADDER) || !pRailNode->GetActive() || !pRailNode->m_pNextLink) continue;\r\n\t\t\r\n\t\t// First do bounding box test, before time-intensive LineLineIntersect test \r\n\t\tif (bb_min.GetX() > pRailNode->m_BBMax.GetX()) continue;\r\n\t\tif (bb_max.GetX() < pRailNode->m_BBMin.GetX()) continue;\r\n\t\tif (bb_min.GetZ() > pRailNode->m_BBMax.GetZ()) continue;\r\n\t\tif (bb_max.GetZ() < pRailNode->m_BBMin.GetZ()) continue;\r\n\t\tif (bb_min.GetY() > pRailNode->m_BBMax.GetY()) continue;\r\n\t\tif (bb_max.GetY() < pRailNode->m_BBMin.GetY()) continue;\r\n\t\t\r\n\t\t// we have a rail segment with a BB match\r\n\t\t// so see if we are close to it \r\n\t\tMth::Line segment;\r\n\t\tsegment.m_start = pRailNode->m_pos;\r\n\t\tsegment.m_end = pRailNode->m_pNextLink->m_pos;\r\n\t\tMth::Vector p1, p2;\r\n\t\tfloat f1,f2;\r\n\t\tif (!Mth::LineLineIntersect(movement, segment, &p1, &p2, &f1, &f2)) continue;\r\n\t\t\r\n\t\tMth::Vector\tto_rail = p2 - p1;\r\n\t\tfloat dist_sqr = to_rail.LengthSqr();\r\n\t\t\r\n\t\tif (dist_sqr > snap_dist_sqr || dist_sqr > closest_dist_sqr) continue;\r\n\t\t\r\n\t\tSLadderRailData this_data;\r\n\t\tif (pRailNode->m_pos[Y] < pRailNode->m_pNextLink->m_pos[Y])\r\n\t\t{\r\n\t\t\tif (!p_walk_component->FilterLadderAirGrabRail(pRailNode->m_pos, pRailNode->m_pNextLink->m_pos, GetMatrix(pRailNode), p2, f2, this_data)) continue;\r\n\t\t\t*pp_rail_node = pRailNode;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (!p_walk_component->FilterLadderAirGrabRail(pRailNode->m_pNextLink->m_pos, pRailNode->m_pos, GetMatrix(pRailNode->m_pNextLink), p2, 1.0f - f2, this_data)) continue;\r\n\t\t\t*pp_rail_node = pRailNode->m_pNextLink;\r\n\t\t}\r\n\t\t\r\n\t\tclosest_dist_sqr = dist_sqr;\r\n\t\trail_data = this_data;\r\n\t}\r\n\r\n\treturn *pp_rail_node;\r\n}\r\n\r\n/*\r\n// check for rails near but perpendicular to check_line\r\nbool CRailManager::CheckForHopToHangRail ( const Mth::Vector& check_line_start, float check_line_height, const Mth::Vector& facing, float max_forward_reach, float max_backward_reach, CWalkComponent* p_walk_component, SHangRailData& rail_data, const CRailNode** pp_rail_node )\r\n{\r\n\t// this logic assumes Y is up, which might not be true if we're checking a movable rail manager\r\n\t// for now, no hopping to hang from movable rail managers which are not nicely oriented\r\n\tif (Mth::Abs(facing[Y]) > 0.1f) return false;\r\n\t\r\n\t// The check box is aligned with the Y axis and the facing, is check_line_height tall,\r\n\t// and has a max_foward_reach + max_backward_reach by vCHECK_BOX_WIDTH foot print in the horizontal plane.\r\n\t\r\n\t*pp_rail_node = NULL;\r\n\tfloat best_facing_distance = 0.0f;\r\n\tfloat best_height = 0.0f;\r\n\t\r\n\tfloat check_line_X_start = check_line_start[X] - max_backward_reach * facing[X];\r\n\tfloat check_line_X_delta = (max_backward_reach + max_forward_reach) * facing[X];\r\n\tfloat check_line_Z_start = check_line_start[Z] - max_backward_reach * facing[Z];\r\n\tfloat check_line_Z_delta = (max_backward_reach + max_forward_reach) * facing[Z];\r\n\t\r\n\tfor (int check_node_idx = m_num_nodes; check_node_idx--; )\r\n\t{\r\n\t\tCRailNode* p_node = &mp_nodes[check_node_idx];\r\n\t\t\r\n\t\tif (p_node->GetFlag(LADDER) || p_node->GetFlag(NO_CLIMBING) || !p_node->GetActive() || !p_node->m_pNextLink) continue;\r\n\t\t\r\n\t\t// determine the clostest point on the rail in the horizontal plane\r\n\t\tfloat s;\r\n\t\tif (!Nx::CCollObj::s2DLineLineCollision(\r\n\t\t\tp_node->m_pos[X],\r\n\t\t\tp_node->m_pos[Z],\r\n\t\t\tp_node->m_pNextLink->m_pos[X] - p_node->m_pos[X],\r\n\t\t\tp_node->m_pNextLink->m_pos[Z] - p_node->m_pos[Z],\r\n\t\t\tcheck_line_X_start,\r\n\t\t\tcheck_line_Z_start,\r\n\t\t\tcheck_line_X_delta,\r\n\t\t\tcheck_line_Z_delta,\r\n\t\t\t&s\r\n\t\t)) continue;\r\n\t\tMth::Vector closest_point = p_node->m_pos + s * (p_node->m_pNextLink->m_pos - p_node->m_pos);\r\n\t\t\r\n\t\t// calculate the offset vector from the bottom of the check line to the closest point\r\n\t\tMth::Vector offset_to_rail = closest_point - check_line_start;\r\n\t\t\r\n\t\t// calculate distance along our facing to the closest point\r\n\t\tfloat facing_distance = offset_to_rail[X] * facing[X] + offset_to_rail[Z] * facing[Z];\r\n\t\t\r\n\t\t// check if the closest point is within reach\r\n\t\tif (facing_distance > max_forward_reach) continue;\r\n\t\tif (facing_distance < -max_backward_reach) continue;\r\n\t\t\r\n\t\t// check to see if the closest point is within the allowed height range\r\n\t\tif (closest_point[Y] < check_line_start[Y]) continue;\r\n\t\tif (closest_point[Y] > check_line_start[Y] + check_line_height) continue;\r\n\t\t\r\n\t\tSHangRailData this_data;\r\n\t\tif (!p_walk_component->FilterHangRail(GetPos(p_node), GetPos(p_node->m_pNextLink), LocalToWorldTransform(closest_point), s, this_data, false)) continue;\r\n\t\t\r\n\t\tif (*pp_rail_node)\r\n\t\t{\r\n\t\t\t// logic determining if this rail is better\r\n\t\t\t\r\n\t\t\t// take rail in front over rail behind\r\n\t\t\tif (best_facing_distance >= 0.0f && facing_distance < 0.0f) continue;\r\n\t\t\tif (!(facing_distance >= 0.0f && best_facing_distance < 0.0f))\r\n\t\t\t{\r\n\t\t\t\t// otherwise, take lowest rail\r\n\t\t\t\tif (offset_to_rail[Y] > best_height) continue;\r\n\t\t\t\tif (offset_to_rail[Y] == best_height)\r\n\t\t\t\t{\r\n\t\t\t\t\t// otherwise, take the closest rail horizontally\r\n\t\t\t\t\tif (Mth::Abs(facing_distance) > Mth::Abs(best_facing_distance)) continue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// this is the best (or first) rail so far\r\n\t\t*pp_rail_node = p_node;\r\n\t\tbest_facing_distance = facing_distance;\r\n\t\tbest_height = offset_to_rail[Y];\r\n\t\trail_data = this_data;\r\n\t\t\r\n\t\tGfx::AddDebugStar(closest_point,  36.0f,  MAKE_RGB(255, 0, 0), 1);\r\n\t}\r\n\t\r\n\treturn *pp_rail_node;\r\n}\r\n*/\r\n\r\nbool CRailManager::CheckForHangRail ( const Mth::Vector& start_pos, const Mth::Vector& end_pos, const Mth::Vector& facing, CWalkComponent* p_walk_component, SHangRailData& rail_data, float snap_distance )\r\n{\r\n\tbool rail_found = false;\r\n\t\r\n\tMth::Line movement;\r\n\tmovement.m_start = start_pos;\r\n\tmovement.m_end = end_pos;\r\n\t\r\n\t// find bounding box for movement\r\n\tMth::Vector bb_min, bb_max;\r\n\tRail_ComputeBB(movement.m_start, movement.m_end, bb_min, bb_max);\r\n\tfloat snap_dist_sqr = snap_distance;\r\n\tbb_min.Set(bb_min.GetX() - snap_dist_sqr, bb_min.GetY() - snap_dist_sqr, bb_min.GetZ() - snap_dist_sqr);\t\r\n\tbb_max.Set(bb_max.GetX() + snap_dist_sqr, bb_max.GetY() + snap_dist_sqr, bb_max.GetZ() + snap_dist_sqr);\t\r\n\tsnap_dist_sqr *= snap_dist_sqr;\r\n\t\r\n\tfloat closest_dist_sqr = 10000000.0f * 10000000.0f;\r\n\r\n\tfor (int check_node = 0; check_node < m_num_nodes; check_node++)\r\n\t{\r\n\t\tCRailNode* pRailNode = &mp_nodes[check_node];\r\n\t\tif (pRailNode->GetFlag(LADDER) || pRailNode->GetFlag(NO_CLIMBING) || !pRailNode->GetActive() || !pRailNode->m_pNextLink) continue;\r\n\t\t\r\n\t\t// First do bounding box test, before time-intensive LineLineIntersect test \r\n\t\tif (bb_min.GetX() > pRailNode->m_BBMax.GetX()) continue;\r\n\t\tif (bb_max.GetX() < pRailNode->m_BBMin.GetX()) continue;\r\n\t\tif (bb_min.GetZ() > pRailNode->m_BBMax.GetZ()) continue;\r\n\t\tif (bb_max.GetZ() < pRailNode->m_BBMin.GetZ()) continue;\r\n\t\tif (bb_min.GetY() > pRailNode->m_BBMax.GetY()) continue;\r\n\t\tif (bb_max.GetY() < pRailNode->m_BBMin.GetY()) continue;\r\n\t\t\r\n\t\t// we have a rail segment with a BB match\r\n\t\t// so see if we are close to it \r\n\t\tMth::Line segment;\r\n\t\tsegment.m_start = pRailNode->m_pos;\r\n\t\tsegment.m_end = pRailNode->m_pNextLink->m_pos;\r\n\t\tMth::Vector p1, p2;\r\n\t\tfloat f1,f2;\r\n\t\tif (!Mth::LineLineIntersect(movement, segment, &p1, &p2, &f1, &f2)) continue;\r\n\t\t\r\n\t\tMth::Vector\tto_rail = p2 - p1;\r\n\t\tif (to_rail.LengthSqr() > snap_dist_sqr) continue;\r\n\t\t\r\n\t\t// count rails in front of us as three times closer\r\n\t\tfloat dot = Mth::DotProduct(facing, to_rail);\r\n\t\tif (dot > 0.0f)\r\n\t\t{\r\n\t\t\tto_rail -= (2.0f / 3.0f * dot) * facing;\r\n\t\t}\r\n\t\tfloat dist_sqr = to_rail.LengthSqr();\r\n\t\t\r\n\t\tif (dist_sqr > closest_dist_sqr) continue;\r\n\t\t\r\n\t\tif (!Rail_ValidInEditor(GetPos(pRailNode), GetPos(pRailNode->m_pNextLink))) continue;\r\n\t\t\r\n\t\tSHangRailData this_data;\r\n\t\tthis_data.p_rail_node = pRailNode;\r\n\t\tif (!p_walk_component->FilterHangRail(GetPos(pRailNode), GetPos(pRailNode->m_pNextLink), LocalToWorldTransform(p2), LocalToWorldTransform(p1), f2, this_data, false)) continue;\r\n\t\t\r\n\t\tclosest_dist_sqr = dist_sqr;\r\n\t\trail_data = this_data;\r\n\t\trail_found = true;\r\n\t}\r\n\t\r\n\treturn rail_found;\r\n}\r\n\r\nbool CRailManager::RailNodesAreCoincident ( const CRailNode* p_node_a, const CRailNode* p_node_b )\r\n{\r\n\tconst float epsilon = 1.0f;\r\n\t\r\n\tif (Mth::Abs(p_node_a->m_pos[X] - p_node_b->m_pos[X]) > epsilon) return false;\r\n\tif (Mth::Abs(p_node_a->m_pos[Y] - p_node_b->m_pos[Y]) > epsilon) return false;\r\n\tif (Mth::Abs(p_node_a->m_pos[Z] - p_node_b->m_pos[Z]) > epsilon) return false;\r\n\treturn true;\r\n}\r\n\r\n// look for another rail node within a few inches of the given node's position\r\nbool CRailManager::CheckForCoincidentRailNode ( const CRailNode* p_node, uint32 ignore_mask, const CRailNode** pp_next_node )\r\n{\r\n\tfor (int check_node = 0; check_node<m_num_nodes; check_node++)\r\n\t{\r\n\t\tCRailNode *pRailNode = &mp_nodes[check_node];\r\n\t\t\r\n\t\tif (!RailNodesAreCoincident(pRailNode, p_node)) continue;\r\n\t\t\r\n\t\tif (!pRailNode->m_pNextLink && !pRailNode->m_pPrevLink) continue;\r\n\t\t\r\n\t\tif (pRailNode == p_node) continue;\r\n\t\t\r\n\t\tif (pRailNode->m_pNextLink && pRailNode->IsActive() && !pRailNode->m_flags.TestMask(ignore_mask))\r\n\t\t{\r\n\t\t\t// MESSAGE(\"found potential coincident\");\r\n\t\t\tif (Rail_ValidInEditor(GetPos(pRailNode), GetPos(pRailNode->m_pNextLink)))\r\n\t\t\t{\r\n\t\t\t\t*pp_next_node = pRailNode;\r\n\t\t\t\t// MESSAGE(\"found good coincident\");\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// MESSAGE(\"not valid coincident\");\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif (pRailNode->m_pPrevLink && pRailNode->m_pPrevLink->IsActive() && !pRailNode->m_pPrevLink->m_flags.TestMask(ignore_mask))\r\n\t\t{\r\n\t\t\t// MESSAGE(\"found potential coincident\");\r\n\t\t\tif (Rail_ValidInEditor(GetPos(pRailNode->m_pPrevLink), GetPos(pRailNode)))\r\n\t\t\t{\r\n\t\t\t\t*pp_next_node = pRailNode->m_pPrevLink;\r\n\t\t\t\t// MESSAGE(\"found good coincident\");\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// MESSAGE(\"not valid coincident\");\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n// see if we can stick to a rail\t\r\nbool CRailManager::StickToRail(const Mth::Vector &pos1, const Mth::Vector &pos2, Mth::Vector *p_point, CRailNode **pp_rail_node, const CRailNode *p_ignore_node, float min_dot, int side)\r\n{\r\n\t\r\n\t// Go through all the rail segments, and find the shortest distance to line\r\n\t// and there is your rail\r\n\t\r\n\tMth::Line  movement;\r\n\tmovement.m_start = pos1;\r\n\tmovement.m_end = pos2;\r\n\t\r\n\t// find bounding box for skater\r\n\tMth::Vector bb_min, bb_max;\r\n\tRail_ComputeBB(movement.m_start, movement.m_end, bb_min, bb_max);\r\n\tfloat snap_dist = Script::GetFloat(CRCD(0xf840753e, \"Rail_Max_Snap\"));\r\n\tbb_min.Set(bb_min.GetX() - snap_dist, bb_min.GetY() - snap_dist, bb_min.GetZ() - snap_dist);\t\r\n\tbb_max.Set(bb_max.GetX() + snap_dist, bb_max.GetY() + snap_dist, bb_max.GetZ() + snap_dist);\t\r\n\t\r\n\tfloat\t\tclosest_dist = 10000000.0f;\r\n\tCRailNode   * p_closest_rail = NULL;\r\n\tMth::Vector\t\tclosest_point; \r\n\r\n\tbool\tfound = false;\r\n\t\t\t\t\t\t\r\n\r\n//\tCRailNode *pRailNode = mp_first_node;\r\n//\twhile (pRailNode)\r\n\tfor (int check_node = 0;check_node<m_num_nodes;check_node++)\r\n\t{\r\n\t\tCRailNode *pRailNode = &mp_nodes[check_node];\r\n\t\tif (!pRailNode->GetFlag(ONLY_CLIMBING) && pRailNode != p_ignore_node && pRailNode->GetActive())\r\n\t\t{\r\n\t\t\tif (pRailNode->m_pNextLink)\r\n\t\t\t{\r\n\t\t\t\t// First do bounding box test, before time-intensive LineLineIntersect test \r\n\t\t\t\t\r\n\t\t\t\t// *** IMPORTANT ***\r\n\t\t\t\t// There should be indentations for each 'if', but I left them out for readability\r\n\t\t\t\tif (!(bb_min.GetX() > pRailNode->m_BBMax.GetX()))\r\n\t\t\t\tif (!(bb_max.GetX() < pRailNode->m_BBMin.GetX()))\r\n\t\t\t\tif (!(bb_min.GetZ() > pRailNode->m_BBMax.GetZ()))\r\n\t\t\t\tif (!(bb_max.GetZ() < pRailNode->m_BBMin.GetZ()))\r\n\t\t\t\tif (!(bb_min.GetY() > pRailNode->m_BBMax.GetY()))\r\n\t\t\t\tif (!(bb_max.GetY() < pRailNode->m_BBMin.GetY()))\r\n\t\t\t\t{\r\n\t\t\t\t\t// we have a rail segment with a BB match\r\n\t\t\t\t\t// so see if we are close to it \r\n\t\t\t\t\tMth::Line segment;\r\n\t\t\t\t\tsegment.m_start = pRailNode->m_pos;\r\n\t\t\t\t\tsegment.m_end = pRailNode->m_pNextLink->m_pos;\r\n\t\r\n\t\t\t\t\tif (Rail_ValidInEditor(pRailNode->m_pos,pRailNode->m_pNextLink->m_pos))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMth::Vector p1,p2;\r\n\t\t\t\t\t\tfloat  f1,f2;\r\n\t\t\t\t\t\tif (Mth::LineLineIntersect(movement, segment, &p1, &p2, &f1, &f2))\r\n\t\t\t\t\t\t{\r\n\t\t\r\n\t\t\t\t\t\t\tMth::Vector\tto_rail = p2-p1;\r\n\t\t\t\t\t\t\tfloat \tdist = to_rail.Length();\r\n\t\t\t\t\t\t\tfloat\told_dist = dist; \r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t// calculate the dot product of the\r\n\t\t\t\t\t\t\t// the movement and the rail in the XZ plane\r\n\t\t\t\t\t\t\tMth::Vector  v1,v2;\r\n\t\t\t\t\t\t\tv1 = segment.m_end - segment.m_start;\r\n\t\t\t\t\t\t\tv2 = pos2 - pos1;\r\n\t\t\t\t\t\t\tv1[Y] = 0.0f;\r\n\t\t\t\t\t\t\tv2[Y] = 0.0f;\r\n\t\t\t\t\t\t\tv1.Normalize();\r\n\t\t\t\t\t\t\tv2.Normalize();\r\n\t\t\t\t\t\t\tfloat dot = Mth::Abs(Mth::DotProduct(v1,v2));\r\n\t\r\n\t\t\t\t\t\t\t// if now v2 (the skater's movement vector) is all zero\r\n\t\t\t\t\t\t\t// and the dot is 0.0f\r\n\t\t\t\t\t\t\t// then that means we were going precisely straght up\r\n\t\t\t\t\t\t\t// so we set the dot to 1,\r\n\t\t\t\t\t\t\t// as normally (if we we slightly left or right)\r\n\t\t\t\t\t\t\t// we would be going along the rail at the top of the pipe\r\n\t\t\t\t\t\t\t// in the XZ plane (albeit slowly)\r\n\t\t\t\t\t\t\tif (v2[X] == 0.0f && v2[Z] == 0.0f && dot == 0.0f)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tdot = 1.0f;\r\n\t\t\t\t\t\t\t}\r\n\t\r\n\t\r\n\t\t\t\t\t\t\tdist = dist * (0.122f + 1.0f-dot);\t\t// was (50 + (4096-dist)) on PS1\t\t\t\t\t\t\r\n\t\t\t\t\t\t\told_dist = old_dist * (2.0f - dot);\t\t// was (8192-dot) on PS1 \r\n\t\t\t\t\t\t\t\r\n\t//\t\t\t\t\t\tprintf (\"dot=%.2f, dist=%.2f, old_dist=%.2f, min_dot=%.2f\\n\",dot,dist,old_dist,min_dot);\r\n\t\r\n\t\t\t\t\t\t\tif (side)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tMth::Vector vel = pos2-pos1;\r\n\t\t\t\t\t\t\t\tif (pRailNode->Side(vel) != side)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tdist *= 2.0f;\r\n\t//\t\t\t\t\t\t\t\tprintf (\"side change, dist doubled to %.2f\\n\",dist);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\r\n\t\t\r\n\t\t\t\t\t\t\tif (dist < closest_dist)\r\n\t\t\t\t\t\t\t{\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tbool close = true;\r\n\t\t\t\t\t\t\t\t// if we have a maximum dot, then check we don't go over it\r\n\t\t\t\t\t\t\t\tif (min_dot != 1.0f)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tif (Mth::Abs(dot) < min_dot)\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\tclose = false; \t \r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t}\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tif (close)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tif (old_dist > snap_dist)\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t// there is a good rail, but too far away\r\n\t\t\t\t\t\t\t\t\t\t// so kill any rail we've found so far\r\n\t\t\t\t\t\t\t\t\t\t// and make this the new target\r\n\t\t\t\t\t\t\t\t\t\tclosest_dist = dist;\r\n\t\t\t\t\t\t\t\t\t\tfound = false; \r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t// good rail, and close enough\r\n\t\t\t\t\t\t\t\t\t\tclosest_dist = dist;\r\n\t\t\t\t\t\t\t\t\t\tclosest_point = p2;\r\n\t\t\t\t\t\t\t\t\t\tp_closest_rail = pRailNode;\t  \r\n\t\t\t\t\t\t\t\t\t\tfound = true; \r\n\t\t\t\t\t\t\t\t\t}\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\t\t\t\t\t\t  \t\r\n\t\t\t\t\t\t} // end if (bb_test && Mth::LineLineIntersect(movement, segment, &p1, &p2, &f1, &f2))\r\n\t\t\t\t\t} // end if (Rail_ValidInEditor(pRailNode->m_pos,pRailNode->m_pNextLink->m_pos))\r\n\t\t\t\t} // end whole big bounding box test\r\n\t\t\t} // end if (pRailNode->m_pNextLink)\r\n\t\t\telse if (!pRailNode->m_pPrevLink && !pRailNode->m_pNextLink)\r\n\t\t\t{\r\n\t\t\t\t// special logic for a single node rail\r\n\t\t\t\tif (!(bb_min.GetX() > pRailNode->m_BBMax.GetX()))\r\n\t\t\t\tif (!(bb_max.GetX() < pRailNode->m_BBMin.GetX()))\r\n\t\t\t\tif (!(bb_min.GetZ() > pRailNode->m_BBMax.GetZ()))\r\n\t\t\t\tif (!(bb_max.GetZ() < pRailNode->m_BBMin.GetZ()))\r\n\t\t\t\tif (!(bb_min.GetY() > pRailNode->m_BBMax.GetY()))\r\n\t\t\t\tif (!(bb_max.GetY() < pRailNode->m_BBMin.GetY()))\r\n\t\t\t\t{\r\n\t\t\t\t\t// calculate the distance from the movement to the rail point \r\n\t\t\t\t\tMth::Vector offset = pRailNode->m_pos - pos1;\r\n\t\t\t\t\tMth::Vector movement_direction = (pos2 - pos1).Normalize();\r\n\t\t\t\t\toffset -= Mth::DotProduct(offset, movement_direction) * movement_direction;\r\n\t\t\t\t\tfloat distance = offset.Length();\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (distance > snap_dist) continue;\r\n\t\t\t\t\t\r\n\t\t\t\t\t// single node rails count as twice the distance when looking for the closest rail\r\n\t\t\t\t\tif (closest_dist < 2.0f * distance) continue;\r\n\t\t\t\t\t\r\n\t\t\t\t\tclosest_dist = 2.0f * distance;\r\n\t\t\t\t\tclosest_point = pRailNode->m_pos;\r\n\t\t\t\t\tp_closest_rail = pRailNode;\r\n\t\t\t\t\tfound = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} // end if (active && etc)\r\n\t\t\r\n\t\t//pRailNode = pRailNode->m_pNext;\r\n\t}\t\t\t\t \r\n\r\n\tif (found)\r\n\t{\r\n\t\t// note, the line from pos1 to closest_point will not reflect the line segment found above\r\n\t\t// as the line segment will actually start somewhere between pos1 and pos2, and not always on pos1\r\n//\t\tif ( closest_dist > Script::GetFloat(\"Rail_Max_Snap\"))\r\n//\t\t{\r\n//\t\t\tfound = false;\r\n//\t\t}\r\n//\t\telse\r\n\t\t{\r\n\t\t\t*p_point = closest_point;\r\n\t\t\t*pp_rail_node = p_closest_rail;\r\n\t\t}\r\n\t}\r\n\treturn found;\t\r\n}\r\n\r\n// Added by Ken.\r\n// Returns true if the passed Node is on the same rail as the rail node.\r\n// Note, with the \"merging\" rails, where two nodes can link to\r\n// a new node, then this is not guarenteed to work\r\n//  \r\n// Given that the rails can now form a \"loop with a tail\"\r\n// we now detect loops by traversign the list with two pointers\r\n// one moving at half the speed of the other\r\n\r\nbool CRailNode::ProbablyOnSameRailAs(int SearchNode) const\r\n{\t\t\r\n\t\r\n\r\n\t// First check if this node is the required node.\r\n\tif (m_node==SearchNode)\r\n\t{\r\n\t\t// Well that was easy.\r\n\t\treturn true;\r\n\t}\t\r\n\t\r\n\t\r\n\t// MICK:  Modified to return true only if on the same rail segment\r\n\t\r\n\treturn false;\r\n\r\n\r\n\t\r\n\r\n\tconst CRailNode *p_trailing = this;\r\n\tbool\t\tadvance_trailing = false;\r\n\t\r\n\t// Scan forwards.\r\n\tCRailNode *pNode=m_pNextLink;\r\n\twhile (pNode)\r\n\t{\r\n\t\tif (pNode->m_node==SearchNode)\r\n\t\t{\r\n\t\t\t// Found it.\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t\tif (pNode == p_trailing)\r\n\t\t{\r\n\t\t\t// We've got back where we started without finding\r\n\t\t\t// the node, so return false.\r\n\t\t\treturn false;\r\n\t\t}\t\r\n\t\tpNode=pNode->m_pNextLink;\r\n\t\t\r\n\t\t// Advance the trailing node every other time\r\n\t\t// we advance the search node\r\n\t\tif (advance_trailing)\r\n\t\t{\r\n\t\t\tp_trailing = p_trailing->m_pNextLink;\r\n\t\t}\r\n\t\tadvance_trailing = !advance_trailing;\r\n\t}\r\n\r\n\tp_trailing = this;\r\n\tadvance_trailing = false;\r\n\t\t\r\n\t// Didn't find anything that way, so now scan backwards.\r\n\tpNode=m_pPrevLink;\r\n\twhile (pNode)\r\n\t{\r\n\t\tif (pNode->m_node==SearchNode)\r\n\t\t{\r\n\t\t\t// Found it.\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t\tif (pNode == p_trailing)\r\n\t\t{\r\n\t\t\t// We've got back where we started without finding\r\n\t\t\t// the node, so return false.\r\n\t\t\treturn false;\r\n\t\t}\t\r\n\t\tpNode=pNode->m_pPrevLink;\r\n\t\t// Advance the trailing node every other time\r\n\t\t// we advance the search node\r\n\t\tif (advance_trailing)\r\n\t\t{\r\n\t\t\tp_trailing = p_trailing->m_pPrevLink;\r\n\t\t}\r\n\t\tadvance_trailing = !advance_trailing;\r\n\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n\r\n// use in-game collision checks to determine if a rail is valid\r\nbool  Rail_ValidInEditor(Mth::Vector Start, Mth::Vector End)\r\n{\r\n\r\n// MAYBE TODO:  a rail should only need disqualifying if it is along the edge of a cell\r\n// (or even more accurately, a meta-piece\r\n// so could maybe check for that before we try to disqualify it. \r\n\t\r\n\r\n\tif (!Ed::CParkEditor::Instance()->UsingCustomPark()) \t\t// is it a custom park???\r\n\t{\r\n\t\t#ifdef\t\tDEBUG_EDITOR_RAILS\r\n\t\tprintf (\"not in editor\\n\");\r\n\t\t#endif\r\n\t\t// if not a custom park, then everything is valid.\r\n\t\treturn true;\r\n\t}\r\n\r\n\tCFeeler\t\tfeeler;\r\n\r\n// Find a point \"Mid\", which is 1/4 of the way along the rail   \r\n\tMth::Vector\tMid = (Start + End) / 2.0f;\t\t\t// Half way along\r\n\tMid = Start + ((Mid - Start) / 2.0f);\t\t    // quarter of the way along\t\r\n\tMid[Y] += 6.0f;\t\t\t\t\t\t\t\t\t// raised up a bit\r\n\r\n// Find a vector \"Side\" which is horizontal, perpendicular to the rail, and 4 inches long\t\r\n\tMth::Vector\tSide = End - Start;\t   \t\t\t// vector along the rail\r\n\tSide[Y] = 0.0f;\t\t\t\t\t\t\t\t// horizontal\r\n\tSide.Normalize(7.0f);\t\t\t\t\t\t// this is half the width of the thickest rail.  Was 4.0, changed for Tokyo mega funbox\r\n\tfloat temp = Side[X];\t\t\t \t\t\t\t// make perpendicular to rail\r\n\tSide[X] = Side[Z];\r\n\tSide[Z] = -temp;\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\t\r\n// if collision above me, left to right, then invalid\r\n\tfeeler.SetLine(Mid + Side, Mid-Side);\t\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t#ifdef\t\tDEBUG_EDITOR_RAILS\r\n\t\tprintf (\"l-r above collision, invalid\\n\");\r\n\t\tfeeler.DebugLine(255,0,0);\r\n\t\t#endif\r\n\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t#ifdef\t\tDEBUG_EDITOR_RAILS\r\n\t\tfeeler.DebugLine();\r\n\t\t#endif\r\n\t}\r\n\r\n// if collision above me, right to left, then invalid \t\r\n\tfeeler.FlipDirection();\r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t#ifdef\t\tDEBUG_EDITOR_RAILS\r\n\t\tprintf (\"r-l above collision, invalid\\n\");\r\n\t\tfeeler.DebugLine(255,0,0);\r\n\t\t#endif\r\n\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t#ifdef\t\tDEBUG_EDITOR_RAILS\r\n\t\tfeeler.DebugLine();\r\n\t\t#endif\r\n\t}\r\n\r\n#if 1\r\n\r\n// Get a vector \"Down\", which is a line straight down 7 inches\r\n\tMth::Vector\tDeepBelow(0.0f,-12.0f,0.0f);\t \t\t// six inches below the rail\r\n\t\r\n\tfloat\tleft_height \t\t= 0.0f;\r\n\tfloat \tright_height \t\t= 0.0f;\r\n\r\n// find reltive height of slope (to rail) on left side\r\n\tfeeler.SetLine(Mid + Side, Mid + Side + DeepBelow);\t\t\t\t  \r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t#ifdef\t\tDEBUG_EDITOR_RAILS\r\n\t\tfeeler.DebugLine(0,255,0);\t   \t// green = possible bad one side\r\n\t\t#endif\r\n\t\tleft_height = feeler.GetPoint().GetY() - (Mid[Y] -6.0f);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tfeeler.SetLine(Mid - Side, Mid - Side + DeepBelow);\t\t\t\t  \r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\t#ifdef\t\tDEBUG_EDITOR_RAILS\r\n\t\tfeeler.DebugLine(0,255,0);\t   \t// green = possible bad one side\r\n\t\t#endif\r\n\t\tright_height = feeler.GetPoint().GetY() - (Mid[Y]-6.0f);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\t\r\n//\tprintf(\"Left = %f, Right = %f\\n\",left_height, right_height);\r\n\t\r\n\tif (left_height > -1.0f && right_height > -1.0f)\r\n\t{\r\n\t\t// both faces tilt upwards, or are roughtly horizontal\r\n\t\t// so return false\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Make it so left is higher than right for subsequent tests\t\r\n\tif (left_height < right_height)\r\n\t{\r\n\t\tfloat t = left_height;\r\n\t\tleft_height = right_height;\r\n\t\tright_height = t;\r\n\t}\r\n\t\r\n\t// check for steep left side\r\n\tif (left_height > 1.0f)\r\n\t{\r\n\t\t// sloped down right side, so return\r\n\t\tif (right_height > -2.0f)\r\n\t\t{\r\n//\t\t\tprintf (\"Sloped, false\\n\");\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\r\n#else\r\n\r\n// Get a vector \"Down\", which is a line straight down 7 inches\r\n\tMth::Vector\tDownBelow(0.0f,-7.0f,0.0f);\t \t\t// inch below the rail\r\n\tMth::Vector\tDownAbove(0.0f,-4.0f,0.0f);\t\t\t// 2 inch above the rail\r\n\r\n\r\n\t// we do fource collision checks, two on each side of the rail\r\n\t// one to a height that goes below the rail\r\n\t// and the other that goes to a height above it\r\n\t// if two or more of these return a collision\r\n\t// then the rail is invalid\r\n\t// the majority of bad rails will be eliminated with two checks\r\n\r\n\tint cols = 0;\r\n\tfeeler.SetLine(Mid + Side, Mid + Side + DownBelow);\t\t\t\t  \r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tcols++;\r\n\t\t#ifdef\t\tDEBUG_EDITOR_RAILS\r\n\t\tfeeler.DebugLine(0,255,0);\t   \t// green = possible bad one side\r\n\t\tprintf (\"first side collision (greeen), checking other side.....\\n\");\r\n\t\t#endif\r\n\t}\r\n\t\r\n\tfeeler.SetLine(Mid-Side, Mid-Side+DownBelow);\t\t\t\t  \r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tcols++;\r\n\t\t#ifdef\t\tDEBUG_EDITOR_RAILS\r\n\t\tfeeler.DebugLine(0,255,0);\t   \t// green = possible bad one side\r\n\t\tprintf (\"second side collision (greeen), checking other side.....\\n\");\r\n\t\t#endif\r\n\t\tif (cols > 1)\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\tfeeler.SetLine(Mid+Side, Mid+Side+DownAbove);\t\t\t\t  \r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tcols++;\r\n\t\t#ifdef\t\tDEBUG_EDITOR_RAILS\r\n\t\tfeeler.DebugLine(0,255,0);\t   \t// green = possible bad one side\r\n\t\tprintf (\"third side collision (greeen), checking other side.....\\n\");\r\n\t\t#endif\r\n\t\tif (cols > 1)\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\tfeeler.SetLine(Mid-Side, Mid-Side+DownAbove);\t\t\t\t  \r\n\tif (feeler.GetCollision())\r\n\t{\r\n\t\tcols++;\r\n\t\t#ifdef\t\tDEBUG_EDITOR_RAILS\r\n\t\tfeeler.DebugLine(0,255,0);\t   \t// green = possible bad one side\r\n\t\tprintf (\"forth side collision (greeen)\\n\");\r\n\t\t#endif\r\n\t\tif (cols > 1)\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\t\r\n\t}\r\n#endif\t\t\t\r\n\t\t\r\n// Not found two collisions\r\n// so we can return true, indicating this rail is valid in the park editor\r\n//\tprintf (\"everything ok, valid\\n\");\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\nvoid\tCRailManager::DebugRender(Mth::Matrix *p_transform)\r\n{\r\n#ifdef\t__DEBUG_CODE__\r\n\t\r\n\t#ifdef\t__PLAT_NGPS__\t\r\n\t\r\n\tNxPs2::DMAOverflowOK = 2;\r\n\t\t\t\t\t\t   \r\n\t\r\n\tMth::Vector\tcam_fwd;\r\n\t\r\n\tif (Nx::CViewportManager::sGetActiveCamera())\r\n\t{\r\n\t\tcam_fwd = Nx::CViewportManager::sGetActiveCamera()->GetMatrix()[Z];\r\n\t}\r\n\telse\r\n\t{\r\n\t\tprintf(\"WARNING: called CRailManager::DebugRender without a camera\\n\");\r\n\t\treturn;\r\n\t}\r\n\r\n\t\r\n\t\r\n\tbool\tdraw_arrows = Script::GetInt( CRCD(0xc57f95d7,\"rail_arrows\"), false );\r\n\r\n\tMth::Vector up(0.0f,1.0f,0.0f);\t\r\n\r\n\tuint32\trgb = 0x0000ff;\r\n\t\r\n\tuint32 current = 12345678;\r\n\r\n\t\r\n\t\r\n//\tCRailNode *pRailNode;\r\n//\tpRailNode = mp_first_node;\r\n\tint count = 0;\r\n\tfor (int check_node = 0;check_node<m_num_nodes;check_node++)\r\n\t{\r\n\t\tCRailNode *pRailNode = &mp_nodes[check_node];\r\n\t\tcount++;\r\n\t\tCRailNode *pNext = pRailNode->m_pNextLink;\r\n\t\t\r\n\t\tint terrain = pRailNode->GetTerrain();\r\n\t\t\t\r\n\t\tif (pNext)\r\n\t\t{\r\n\t\t\r\n\t\t\tswitch (terrain)\r\n\t\t\t{\r\n\t\t\t\r\n\t\t\t\tcase vTERRAIN_CONCSMOOTH:\r\n\t\t\t\tcase vTERRAIN_CONCROUGH:\t\r\n\t\t\t\t\trgb = 0x0000ff;\t\t\t// red = concrete\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vTERRAIN_METALSMOOTH:\r\n\t\t\t\tcase vTERRAIN_METALROUGH:\t\r\n\t\t\t\tcase vTERRAIN_METALCORRUGATED:\t\r\n\t\t\t\tcase vTERRAIN_METALGRATING:\r\n\t\t\t\tcase vTERRAIN_METALTIN: \r\n\t\t\t\t\trgb = 0xff0000;\t\t\t// blue = metal\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t \r\n\t\t\t\tcase vTERRAIN_WOOD:\t\t\r\n\t\t\t\tcase vTERRAIN_WOODMASONITE:\r\n\t\t\t\tcase vTERRAIN_WOODPLYWOOD:\r\n\t\t\t\tcase vTERRAIN_WOODFLIMSY:\t\r\n\t\t\t\tcase vTERRAIN_WOODSHINGLE:\r\n\t\t\t\tcase vTERRAIN_WOODPIER:\t\r\n\t\t\t\t\trgb = 0x00ff00;\t\t\t// green = wood\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\trgb = 0xffffff;\t\t\t// white = everything else \r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (pRailNode->m_flags.Test(LADDER))\r\n\t\t\t{\r\n\t\t\t\trgb = 0xffff00;\r\n\t\t\t}\r\n\t\t\r\n\r\n\t\t\t// check for context changes\r\n\t\t\tif (current != rgb)\r\n\t\t\t{\r\n\t\t\t\tif ( current != 12345678)\r\n\t\t\t\t{\r\n\t\t\t\t\tNxPs2::EndLines3D();\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tcurrent = rgb;\r\n\t\t\t\tNxPs2::BeginLines3D(0x80000000 + (0x00ffffff & rgb));\r\n\t\t\t}\r\n\t\t\r\n\t\t\tMth::Vector v0, v1;\r\n\t\t\tv0 = pRailNode->m_pos/* + up*/;\t  \t// the +up is the lift them off the surface, so they render better\r\n\t\t\tv1 = pNext->m_pos/* + up*/;\r\n\t\t\tv0[W] = 1.0f;\t\t// Make homgeneous\r\n\t\t\tv1[W] = 1.0f;\r\n\r\n\t\t\tif (p_transform)\r\n\t\t\t{\r\n\t\t\t\tv0 = p_transform->Transform(v0);\r\n\t\t\t\tv1 = p_transform->Transform(v1);\r\n\t\t\t}\r\n\r\n\t\t\tif (pRailNode->GetTerrain() || ((Tmr::GetTime() % 100) > 50))\r\n\t\t\t{\r\n\t\t\t\tNxPs2::DrawLine3D(v0[X],v0[Y],v0[Z],v1[X],v1[Y],v1[Z]);\r\n\t\t\t\tNxPs2::DrawLine3D(v0[X],v0[Y],v0[Z],v1[X],v1[Y],v1[Z]);\r\n\t\t\t\r\n\t\t\t\tif (draw_arrows)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Calculate and draw an arrowhead \r\n\t\t\t\t\t// 1/4th the length, at ~30 degrees\t\t\t\t\t   \r\n\t\t\t\t\tMth::Vector\ta = v0;\r\n\t\t\t\t\tMth::Vector b = v1;\r\n\t\t\t\t\tMth::Vector\tab = (b-a);\r\n\t\t\t\t\tab /= 4.0f;\r\n\t\t\t\t\tMth::Vector out;\r\n\t\t\t\t\tout = ab;\r\n\t\t\t\t\tout.Normalize();\r\n\t\t\t\t\tout = Mth::CrossProduct(out, cam_fwd);\r\n\t\t\t\t\tout *= ab.Length()/3.0f;\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\tMth::Vector left =  b - ab + out;\r\n\t\t\t\t\tMth::Vector right = b - ab - out;\r\n\t\t\r\n\t\t\t\t\tNxPs2::DrawLine3D(left[X],left[Y],left[Z],b[X],b[Y],b[Z]);\r\n\t\t\t\t\tNxPs2::DrawLine3D(right[X],right[Y],right[Z],b[X],b[Y],b[Z]);\r\n\t\t\t\t\tNxPs2::DrawLine3D(right[X],right[Y],right[Z],left[X],left[Y],left[Z]);\t // crossbar\r\n\t\t\t\t\t// have to draw it twice for some stupid reason\t(final segment of a particular color is not rendered)\r\n\t\t\t\t\tNxPs2::DrawLine3D(left[X],left[Y],left[Z],b[X],b[Y],b[Z]);\r\n\t\t\t\t\tNxPs2::DrawLine3D(right[X],right[Y],right[Z],b[X],b[Y],b[Z]);\r\n\t\t\t\t\tNxPs2::DrawLine3D(right[X],right[Y],right[Z],left[X],left[Y],left[Z]);\r\n\t\t\t\t}\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n//\t\tpRailNode = pRailNode->m_pNext;\r\n\t\t\r\n\t}\r\n\t\r\n\r\n\t// then draw the node positions as litle red lines\t\r\n//\tpRailNode = mp_first_node;\r\n\tcount = 0;\r\n\tfor (int check_node = 0;check_node<m_num_nodes;check_node++)\r\n\t{\r\n\t\tCRailNode *pRailNode = &mp_nodes[check_node];\r\n\t\tcount++;\r\n\t\tif (pRailNode->GetActive())\r\n\t\t{\r\n\t\t\trgb = 0xff0000;\t\t \t\t// blue for active\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\trgb = 0x00ff00;\t\t\t\t// green for inactive\r\n\t\t}\r\n\t\t\r\n\t\tif (!pRailNode->GetPrevLink())\r\n\t\t{\r\n\t\t\trgb |= 0x0000ff;\t\t\t// blue+red = cyan = no prev node (or green+red = yellow for no prev inactive)\r\n\t\t}\r\n\t\r\n\t\t// check for context changes\r\n\t\tif (current != rgb)\r\n\t\t{\r\n\t\t\tif ( current != 12345678)\r\n\t\t\t{\r\n\t\t\t\tNxPs2::EndLines3D();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcurrent = rgb;\r\n\t\t\tNxPs2::BeginLines3D(0x80000000 + (0x00ffffff & rgb));\r\n\t\t}\r\n\t\r\n\t\tMth::Vector v0, v1;\r\n\t\tv0 = pRailNode->m_pos;\r\n\t\tv1 = v0 + up * 24.0f;\r\n\t\tv0[W] = 1.0f;\t\t// Make homgeneous\r\n\t\tv1[W] = 1.0f;\r\n\r\n\t\tif (p_transform)\r\n\t\t{\r\n\t\t\tv0 = p_transform->Transform(v0);\r\n\t\t\tv1 = p_transform->Transform(v1);\r\n\t\t}\r\n\r\n\t\tif (pRailNode->GetTerrain() || ((Tmr::GetTime() % 100) > 50))\r\n\t\t{\r\n\t\t\tNxPs2::DrawLine3D(v0[X],v0[Y],v0[Z],v1[X],v1[Y],v1[Z]);\r\n\t\t\tNxPs2::DrawLine3D(v0[X],v0[Y],v0[Z],v1[X],v1[Y],v1[Z]);\r\n\t\t}\r\n//\t\tpRailNode = pRailNode->m_pNext;\r\n\t\t\r\n\t}\r\n\r\n\t\r\n\t\r\n\t// only if we actually drew some\r\n\tif ( current != 12345678)\r\n\t{\r\n\t\tNxPs2::EndLines3D();\r\n\t}\r\n\r\n\r\n\t#endif\r\n\t#endif\r\n\r\n}\r\n\r\n\r\n\r\n\r\nvoid\tCRailManager::AddRailsFromNodeArray(Script::CArray * p_nodearray)\r\n{\r\n\tDbg_MsgAssert(!mp_node_array,(\"Setting two node arrays in rail manager\"));\r\n\tmp_node_array = p_nodearray;\r\n\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\r\n\t\r\n\tuint32 i;\t\r\n\t\r\n\r\n\tDbg_MsgAssert(m_num_nodes == 0,(\"Can only addd nodes once, already %d there\\n\",m_num_nodes));\t\t\t\t\t\t\t\t\t\t  \r\n\tm_num_nodes = 0;\t\t\t\t\t\t\t\t\t\t  \r\n\t\t\t\t\t\t\t\t\t\t  \r\n\t// First iterate over the node array, and count the number of nodes needed\r\n\r\n\r\n\tfor (i=0; i<p_nodearray->GetSize(); ++i)\r\n\t{\r\n\t\tScript::CStruct *p_node_struct=p_nodearray->GetStructure(i);\r\n\t\tDbg_MsgAssert(p_node_struct,(\"Error getting node from node array for rail generation\"));\r\n\t\tif ( !skate_mod->ShouldBeAbsentNode( p_node_struct ) )\r\n\t\t{\r\n\t\t\tuint32 class_checksum = 0;\t\t\r\n\t\t\tp_node_struct->GetChecksum( 0x12b4e660 /*\"Class\"*/, &class_checksum );\r\n\t\t\tif (class_checksum == CRCD(0x8e6b02ad, \"railnode\") || class_checksum == CRCD(0x30c19600, \"ClimbingNode\"))\r\n\t\t\t{\r\n\t\t\t\tm_num_nodes++;\t\t\t\t\t\t\t\t\t\t  \r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// if (class_checksum == CRCD(0x16d1e502, \"climbnode\"))\r\n\t\t\t// {\r\n\t\t\t\t// printf(\"Found climb node!\\n\");\r\n\t\t\t// }\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t// No nodes found, so just return\r\n\tif (!m_num_nodes)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tmp_nodes = (CRailNode*)Mem::Malloc(m_num_nodes * sizeof(CRailNode));\r\n\tmp_links = (CRailLinks*)Mem::Malloc(m_num_nodes * sizeof(CRailLinks));\r\n\r\n\t// iterate over the nodes and add them to the array\t\r\n\tm_current_node = 0;\t\r\n\t\r\n\t \r\n\tfor (i=0; i<p_nodearray->GetSize(); ++i)\r\n\t{\r\n\t\tScript::CStruct *p_node_struct=p_nodearray->GetStructure(i);\r\n\t\tDbg_MsgAssert(p_node_struct,(\"Error getting node from node array for rail generation\"));\r\n\r\n\t\tif ( !skate_mod->ShouldBeAbsentNode( p_node_struct ) )\r\n\t\t{\r\n\t\r\n\t\r\n\t\t\tuint32 class_checksum = 0;\t\t\r\n\t\t\tp_node_struct->GetChecksum( 0x12b4e660 /*\"Class\"*/, &class_checksum );\r\n\t\t\tif (class_checksum == CRCD(0x8e6b02ad, \"railnode\") || class_checksum == CRCD(0x30c19600, \"ClimbingNode\"))\r\n\t\t\t{\r\n\t\t\t\t\r\n\t\r\n\t\t\t\tAddRailNode( i, p_node_struct);\r\n\t\r\n\t\t\t\tbool is_trick_object = p_node_struct->ContainsComponentNamed( \"TrickObject\" );\r\n\t\r\n\t#if 1\r\n\t\t\t\tbool debug_graffiti = Script::GetInt( \"create_all_trick_objects\", false );\r\n\t\t\t\tif ( debug_graffiti )\r\n\t\t\t\t\tis_trick_object = true;\r\n\t#endif\r\n\t\r\n\t\t\t\tif ( is_trick_object )\r\n\t\t\t\t{\r\n\t\t\t\t\t// get the node name\r\n\t\t\t\t\tuint32 checksumName;\r\n\t\t\t\t\tp_node_struct->GetChecksum( \"name\", &checksumName, true );\r\n\t\r\n\t\t\t\t\t// must have a cluster associated with it\r\n\t\t\t\t\tuint32 clusterName = checksumName;\r\n\t#if 0\r\n\t\t\t\t\t// automatically link all rail nodes to the TestCluster for now\r\n\t\t\t\t\tclusterName = Script::GenerateCRC(\"TestCluster\");\r\n\t#else\r\n\t\t\t\t\tp_node_struct->GetChecksum( \"Cluster\", &clusterName, true );\r\n\t#endif\r\n\t\t\t\t\tskate_mod->GetTrickObjectManager()->AddTrickCluster( clusterName );\r\n\t\r\n\t\t\t\t\t// bind the name of the rail node to the cluster name\r\n\t\t\t\t\tskate_mod->GetTrickObjectManager()->AddTrickAlias( checksumName, clusterName );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t\r\n\tint num_nodes  = p_nodearray->GetSize();   \r\n\t\r\n\t// we are creating a table of all nodes, and the pointer to the CRailNode\r\n\t// for that node, so we can do a reverse lookup\r\n\t\r\n\tCRailNode **pp_railnodes = (CRailNode **) Mem::Malloc(num_nodes * sizeof(CRailNode*));\r\n\tfor (int i=0;i<num_nodes;i++)\r\n\t{\r\n\t\tpp_railnodes[i] = NULL;\r\n\t}\r\n\r\n\t// now fill it in\t\r\n\tCRailNode *p_node; // = mp_first_node;\r\n//\twhile (p_node)\r\n\tfor (int node=0;node<m_num_nodes;node++)\r\n\t{\r\n\t\tp_node = &mp_nodes[node];\r\n\t\tpp_railnodes[p_node->GetNode()] = p_node;\r\n//\t\tp_node = p_node->m_pNext;\r\n\t}\r\n\r\n\t// now go through all the node\t\r\n//\tp_node = mp_first_node;\r\n\tfor (int node=0;node<m_num_nodes;node++)\r\n\t{\r\n\t\tp_node = &mp_nodes[node];\r\n\t\tfor (int i=0;i<MAX_RAIL_LINKS;i++)\r\n\t\t{\r\n\t\t\tif (mp_links[node].m_link[i] != - 1)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(mp_links[node].m_link[i] < num_nodes, (\"Node %d,Rail link node (%d) out of range (0 .. %d). Bad Node array?\",\r\n\t\t\t\t\t\t\t\t\t\t\t\tp_node->m_node, mp_links[node].m_link[i], num_nodes));\r\n\t\t\t\tDbg_MsgAssert(pp_railnodes[mp_links[node].m_link[i]], (\"RailNode %d linked to something (node %d) that is not a RailNode\",\r\n\t\t\t\t\t\t\t\t\t\t\t\tp_node->m_node, mp_links[node].m_link[i]));\r\n\t\t\t\tNewLink(p_node,pp_railnodes[mp_links[node].m_link[i]]);\r\n\t\t\t}\r\n\t\t}\r\n//\t\tp_node = p_node->m_pNext;\r\n\t}\r\n\tMem::Free(pp_railnodes);\r\n\t\r\n\tMem::Free(mp_links);\r\n\tmp_links = NULL;\r\n\t\r\n\t//printf (\"THERE ARE %d rails\\n\",m_num_nodes);\r\n\t\r\n}\r\n\r\nMth::Vector CRailManager::LocalToWorldTransform ( const Mth::Vector& vector ) const\r\n{\r\n\tif (!m_is_transformed)\r\n\t{\r\n\t\treturn vector;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn m_transform.Transform(vector);\r\n\t}\r\n}\r\n\r\nMth::Vector\tCRailManager::GetPos(const CRailNode *p_node) \tconst\r\n{\r\n\tDbg_Assert(p_node);\r\n\t\r\n\tif (!m_is_transformed)\r\n\t{\r\n\t\treturn p_node->GetPos();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMth::Vector v = m_transform.Transform(p_node->GetPos());\r\n\t\treturn v;\r\n\t}\r\n}\r\n\r\nMth::Matrix\tCRailManager::GetMatrix(const CRailNode *p_node) \tconst\r\n{\r\n\tDbg_Assert(p_node);\r\n\t\r\n\tif (!m_is_transformed)\r\n\t{\r\n\t\treturn Mth::Matrix(p_node->GetOrientation());\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMth::Matrix m = m_transform * Mth::Matrix(p_node->GetOrientation());\r\n\t\treturn m;\r\n\t}\r\n}\r\n\r\n\r\nMth::Vector\tCRailManager::GetBBMin(const CRailNode *p_node) const\r\n{\r\n\tif (!m_is_transformed)\r\n\t{\r\n\t\treturn p_node->GetBBMin();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMth::Vector v = m_transform.Transform(p_node->GetBBMin());\r\n\t\treturn v;\r\n\t}\r\n}\r\n\r\nMth::Vector\tCRailManager::GetBBMax(const CRailNode *p_node) const\r\n{\r\n\tif (!m_is_transformed)\r\n\t{\r\n\t\treturn p_node->GetBBMax();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMth::Vector v = m_transform.Transform(p_node->GetBBMax());\r\n\t\treturn v;\r\n\t}\r\n}\r\n\r\n// Auto-generation of rails\r\n\r\n// a binning data structure similar to a hashtable which will allow us to quickly find nearby rail endpoints\r\n// differs from the standard hashtable in that we will be able to add an element multiple times\r\n// its algorithm is just as inefficient as the standard hashtable\r\n\r\nstruct SAutoRail;\r\nclass BinTable;\r\n\r\nclass BinItem\r\n{\r\n\tfriend class BinTable;\r\n\r\nprivate:\r\n\tBinItem (   )\r\n\t\t: mp_value(NULL), mp_next(NULL)\r\n\t\t{   }\r\n\r\n\tSAutoRail* mp_value;\r\n\tBinItem* mp_next;\r\n};\r\n\r\nclass BinTable\r\n{\r\npublic:\r\n\tBinTable ( uint32 numBits );\r\n\t~BinTable (   );\r\n\r\n\tbool PutItem ( const uint32 key, SAutoRail* item );\r\n\tbool PutItemTwice ( const uint32 first_key, const uint32 second_key, SAutoRail* item );\r\n\tSAutoRail* GetFirstItem ( const uint32 key );\r\n\tSAutoRail* GetNextItem ( const uint32 key, SAutoRail* item );\r\n\tvoid FlushAllItems (   );\r\n\r\n\tint GetSize (   ) { return m_size; }\r\n\r\nprotected:\r\n\tuint32 m_numBits;\r\n\tBinItem* mp_table;\r\n\tint m_size;\r\n\r\nprivate:\r\n\tuint32 key_to_bin ( const uint32 key )\r\n\t\t{ return key & ((1 << m_numBits) - 1); }\r\n};\r\n\r\nBinTable::BinTable ( uint32 numBits )\r\n\t: m_numBits(numBits), mp_table(new BinItem[1 << numBits]), m_size(0)\r\n\t{   }\r\n\r\nBinTable::~BinTable (   )\r\n{\r\n\tDbg_AssertPtr(mp_table);\r\n\r\n\tFlushAllItems();\r\n\r\n\tdelete [] mp_table;\r\n\tmp_table = NULL;\r\n}\r\n\r\nbool BinTable::PutItem ( const uint32 key, SAutoRail* item )\r\n{    \r\n    Dbg_AssertPtr(item);\r\n\r\n\tDbg_AssertPtr(mp_table);\r\n\r\n\tDbg_MsgAssert(key || item, (\"Both key and item are 0 (NULL) in bin table\"));\r\n\t\r\n\tDbg_MsgAssert(item, (\"NULL item added to bin table\"));\r\n\r\n\tBinItem *pEntry = &mp_table[key_to_bin(key)];\r\n\tif (pEntry->mp_value)\r\n\t{\r\n#ifndef __PLAT_WN32__\r\n\t\tBinItem *pNew = new (Mem::PoolManager::SCreateItem(Mem::PoolManager::vHASH_ITEM_POOL)) BinItem();\r\n#else\r\n\t\tBinItem *pNew = new BinItem;\r\n#endif\r\n\t\tpNew->mp_value = item;\r\n\t\tpNew->mp_next = pEntry->mp_next;\r\n\t\tpEntry->mp_next = pNew;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpEntry->mp_value = item;\r\n\t}\r\n\r\n\tm_size++;\t\r\n\treturn true;\r\n}\r\n\r\n// this feature is needed to insure a rail is never added twice to the same bin; if it were, it would become\r\n// impossible to traverse the bin\r\nbool BinTable::PutItemTwice ( const uint32 first_key, const uint32 second_key, SAutoRail* item )\r\n{\r\n\tPutItem(first_key, item);\r\n\tif (key_to_bin(first_key) != key_to_bin(second_key))\r\n\t\tPutItem(second_key, item);\r\n\treturn true;\r\n}\r\n\r\nSAutoRail* BinTable::GetFirstItem ( const uint32 key )\r\n{\r\n    Dbg_AssertPtr(mp_table);\r\n\r\n\tBinItem* pEntry = &mp_table[key_to_bin(key)];\r\n\r\n\twhile (pEntry)\r\n\t{\r\n\t\tif (pEntry->mp_value)\r\n\t\t{\r\n\t\t\treturn pEntry->mp_value;\r\n\t\t}\t\r\n\t\tpEntry = pEntry->mp_next;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\nSAutoRail* BinTable::GetNextItem ( const uint32 key, SAutoRail* p_item )\r\n{\r\n    Dbg_AssertPtr(mp_table);\r\n\r\n\tBinItem* pEntry = &mp_table[key_to_bin(key)];\r\n\r\n\twhile (pEntry)\r\n\t{\r\n\t\tif (pEntry->mp_value == p_item)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tpEntry = pEntry->mp_next;\r\n\t}\r\n\tif (!pEntry)\r\n\t{\r\n\t\treturn NULL;\r\n\t}\t\r\n\r\n\tpEntry = pEntry->mp_next;\r\n\twhile (pEntry)\r\n\t{\r\n\t\tif (pEntry->mp_value)\r\n\t\t{\r\n\t\t\treturn pEntry->mp_value;\r\n\t\t}\t\r\n\t\tpEntry = pEntry->mp_next;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\nvoid BinTable::FlushAllItems (   )\r\n{\r\n\tDbg_AssertPtr(mp_table);\r\n\tif (!mp_table)\r\n\t\treturn;\r\n\r\n\tBinItem* pMainEntry = mp_table;\r\n\tuint32 hashTableSize = 1 << m_numBits;\r\n\tfor (uint32 i = 0; i < hashTableSize; ++i)\r\n\t{\r\n\t\tBinItem* pLinkedEntry = pMainEntry->mp_next;\r\n\t\twhile (pLinkedEntry)\r\n\t\t{\r\n\t\t\tBinItem* pNext = pLinkedEntry->mp_next;\r\n#ifndef __PLAT_WN32__\r\n\t\t\tMem::PoolManager::SFreeItem(Mem::PoolManager::vHASH_ITEM_POOL, pLinkedEntry);\r\n#else\r\n\t\t\tdelete pLinkedEntry;\r\n#endif\r\n\t\t\tpLinkedEntry = pNext;\r\n\t\t}\r\n\t\t++pMainEntry;\r\n\t}\t\r\n\tm_size = 0;\r\n}\r\n\r\n// memory managment defines; control temporary memory usage\r\n\r\n// maximum number of edges in a sector\r\n#define MAX_NUM_EDGES\t\t\t\t\t(5000)\r\n// maximum number of rails\r\n#define\tMAX_NUM_RAILS\t\t\t\t\t(30000)\r\n// maximum number of railsets\r\n#define MAX_NUM_RAILSETS \t\t\t\t(6000)\r\n// size of the rail endpoint bintable\r\n#define ENDPOINT_BINTABLE_SIZE_BITS\t\t(12) // 4096 entries\r\n\r\n// default rail generation parameter values\r\n// when changing these, don't forget to CHANGE THE DOCUMENTATION of the default script parameter values in cfuncs.cpp\r\n\r\n// angle below which edges do not generate rails\r\n#define MIN_RAIL_EDGE_ANGLE\t\t\t\t(30.0f)\r\n// maximum rail assent\r\n// NOTE: can't sync with max skate slop because not a explicitly defined physics value (I think)\r\n#define MAX_RAIL_ANGLE_OF_ASSENT\t\t(45.0f)\r\n// minimum length of a independent rail or a railset\r\n#define MIN_RAILSET_LENGTH\t\t\t\t(36.0f)\r\n// minimum length of a rail, whether in a railset or not\r\n#define MIN_EDGE_LENGTH\t\t\t\t\t(0.0f)\r\n// distance increment along rails at which collision detection is done\r\n#define FEELER_INCREMENT\t\t\t\t(36.0f)\r\n// maximum heigh of a curb before it will get a rail \r\n// NOTE: sync with low-curb skate height from physics engine? i think that's 8.0f but I don't really know what I'm talking about\r\n#define MAX_LOW_CURB_HEIGHT\t\t\t\t(8.0f)\r\n// angle of assent above face of low-curb feelers\r\n#define LOW_CURB_FEELER_ANGLE_OF_ASSENT\t(30.0f)\r\n// maximum angle between two connected rails in a railset\r\n#define MAX_CORNER_IN_RAILSET\t\t\t(50.0f)\r\n// height of vertical feeler\r\n#define VERTICAL_FEELER_LENGTH\t\t\t(5.0f * 12.0f)\r\n// distance above rail at which crossbar feeler is used\r\n#define CROSSBAR_FEELER_ELEVATION\t\t(12.0f)\r\n// half length of crossbar feeler\r\n#define CROSSBAR_FEELER_LENGTH\t\t\t(1.0f * 12.0f)\r\n// farthest distance between an auto-generated rail and an old rail for which the auto-generated rail will be culled\r\n#define FARTHEST_DEGENERATE_RAIL\t\t(12.0f)\r\n// angle between an old and and auto-generated rail below which they may be considered degenerate\r\n#define MAX_DEGENERATE_RAIL_ANGLE\t\t(20.0f)\r\n// distance below which verticies are concidered equal\r\n#define CONNECTION_SLOP\t\t\t\t\t(0.1f)\r\n\r\n\r\n// feeler usage bits\r\n#define VERTICAL_FEELER_BIT\t\t\t\t(1 << 0)\r\n#define CROSSBAR_FEELER_BIT\t\t\t\t(1 << 1)\r\n#define LOW_CURB_FEELER_BIT\t\t\t\t(1 << 2)\r\n#define ALL_FEELERS_ON\t\t\t\t\t(-1)\r\n\r\nstruct SEdge {\r\n\t// has a match for this edge been found?\r\n\tbool matched;\r\n\r\n\t// edge is from a vert poly; maybe I should just save all the face flag bits\r\n\tbool vert;\r\n\r\n\t// edge endpoints\r\n\tMth::Vector p0, p1;\r\n\r\n\t// edge's face's unit normal\r\n\tMth::Vector\tnormal;\r\n\r\n\t// edge's unit perp vector along face\r\n\tMth::Vector perp;\r\n};\r\n\r\nstruct SAutoRailEndpoint {\r\n\t// endpoint position\r\n\tMth::Vector p;\r\n\r\n\t// connection at this end; -1 is no connection\r\n\tint connection;\r\n};\r\n\r\nstruct SAutoRail {\r\n\t// rail endpoints\r\n\tSAutoRailEndpoint endpoints[2];\r\n\r\n\t// unit vector along rail\r\n\tMth::Vector\tpara;\r\n\r\n\t// railset id; -1 for solo rail\r\n\tint railset;\r\n\r\n\t// rail length\r\n\tfloat length;\r\n\r\n\t// if found to be too sort or once added to the rail nodes, a rail is disabled\r\n\tbool disabled;\r\n};\r\n\r\n// dereference endpoints\r\nenum { START = 0, END };\r\n\r\nstruct SRailSet {\r\n\t// length of rail set\r\n\tfloat length;\r\n};\r\n\r\n// collect the autorail state into a single structure to ease transportation\r\nstruct SAutoRailGeneratorState {\r\n\tSEdge* p_edges;\r\n\tSAutoRail* p_rails;\r\n\tSRailSet* p_railsets;\r\n\r\n\t// hash of rail endpoints; most rails are in hash twice, keyed off endpoint's X*Y rounded to nearest inch\r\n\tBinTable* p_rail_endpoint_list;\r\n\r\n\tint\tnum_rails;\t\r\n\tint num_active_rails;\r\n\tint num_railsets;\r\n};\r\n\r\n// collect all the algorithm's input parameters into a structure\r\n// see default values for explaination of meanings\r\nstruct SAutoRailGeneratorParameters {\r\n\t// input parameters\r\n\tfloat min_rail_edge_angle;\r\n\tfloat max_rail_angle_of_assent;\r\n\tfloat min_railset_length;\r\n\tfloat min_edge_length;\r\n\tfloat feeler_increment;\r\n\tfloat max_low_curb_height;\r\n\tfloat curb_feeler_angle_of_assent;\r\n\tfloat max_corner_in_railset;\r\n\tfloat vertical_feeler_length;\r\n\tfloat crossbar_feeler_elevation;\r\n\tfloat half_crossbar_feeler_length;\r\n\tfloat farthest_degenerate_rail;\r\n\tfloat max_degenerate_rail_angle;\r\n\tfloat connection_slop;\r\n\tint feeler_usage;\r\n\r\n\t// dependent parameters\r\n\tfloat sin_max_rail_angle_of_assent;\r\n\tfloat low_curb_feeler_length;\r\n\tfloat cos_min_rail_edge_angle;\r\n\tfloat cos_max_corner_in_railset;\r\n\tfloat sin_curb_feeler_angle_of_assent;\r\n\tfloat cos_curb_feeler_angle_of_assent;\r\n\tfloat cos_max_degenerate_rail_angle;\r\n\r\n\t// additional flags\r\n\tbool remove_old_rails;\r\n};\r\n\r\ninline bool very_close ( Mth::Vector a, Mth::Vector b, const SAutoRailGeneratorParameters& arp )\r\n{\r\n\treturn(Mth::Abs(a[X]-b[X]) < arp.connection_slop\t\r\n\t\t&& Mth::Abs(a[Y]-b[Y]) < arp.connection_slop\r\n\t\t&& Mth::Abs(a[Z]-b[Z]) < arp.connection_slop\r\n\t);\r\n}\r\n\r\ninline int generate_endpoint_key ( Mth::Vector& end_point )\r\n{\r\n\treturn static_cast<int>((end_point[X] * end_point[Z]) * (1.0f / 6.0f));\r\n}\r\n\r\n// checks for duplicate rails and then adds rails to rail array and endpoint bintable\r\ninline bool add_rail ( const Mth::Vector& pa, const Mth::Vector& pb, SAutoRailGeneratorState& arg, const SAutoRailGeneratorParameters& arp )\r\n{\r\n\t// cull out duplicate rails\r\n\t// NOTE: what is causing these? some levels do not have them; perhaps sloppy geometry\r\n\tfor (int n = arg.num_rails; n--; )\r\n\t{\r\n\t\t// if this is a duplicate, bail\r\n\t\tif (very_close(arg.p_rails[n].endpoints[START].p, pa, arp) && very_close(arg.p_rails[n].endpoints[END].p, pb, arp)\r\n\t\t\t|| very_close(arg.p_rails[n].endpoints[START].p, pb, arp) && very_close(arg.p_rails[n].endpoints[END].p, pa, arp))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// if we get to here, we've decided this is a valid rail\r\n\t\r\n\tif (arg.num_rails + 1 == MAX_NUM_RAILS) return false;\r\n\r\n\t// add rail to rail array\r\n\r\n\targ.p_rails[arg.num_rails].endpoints[START].p = pa;\r\n\targ.p_rails[arg.num_rails].endpoints[END].p = pb;\r\n\targ.p_rails[arg.num_rails].endpoints[START].connection = -1;\r\n\targ.p_rails[arg.num_rails].endpoints[END].connection = -1;\r\n\targ.p_rails[arg.num_rails].railset = -1;\r\n\targ.p_rails[arg.num_rails].disabled = false;\r\n\r\n\targ.p_rails[arg.num_rails].para = pb - pa;\r\n\targ.p_rails[arg.num_rails].length = arg.p_rails[arg.num_rails].para.Length();\r\n\targ.p_rails[arg.num_rails].para.Normalize();\r\n\r\n\t// add rail to endpoint bintable\r\n\targ.p_rail_endpoint_list->PutItemTwice(\r\n\t\tgenerate_endpoint_key(arg.p_rails[arg.num_rails].endpoints[START].p),\r\n\t\tgenerate_endpoint_key(arg.p_rails[arg.num_rails].endpoints[END].p),\r\n\t\t&arg.p_rails[arg.num_rails]\r\n\t);\r\n\r\n\targ.num_rails++;\r\n\t\r\n\treturn true;\r\n}\r\n\r\n// handles nearby collision detection\r\n// use feelers to insure that this is a good rail; if the full rail doesn't work, attempt to snip it up into smaller\r\n// valid rails\r\ninline bool consider_rail ( const Mth::Vector& pa, const Mth::Vector& pb, int matched_edge, const Mth::Vector& para, const Mth::Vector& normal,\r\n\tconst Mth::Vector& perp, float edge_length, SAutoRailGeneratorState& arg, SAutoRailGeneratorParameters& arp )\r\n{\r\n\t// four feelers are used at each step along the edge\r\n\t// 1, 2) short feelers up from the edge's two faces\r\n\t// 3) longer feeler straight up from the edge\r\n\t// 4) medium feeler crossbar on feeler 3\r\n\r\n\t// there are full_step_length + 2 feeler points along an edge\r\n\t// 0 corresponds the the edge's start point\r\n\t// n corresponds to a points n steps in from the start point\r\n\t// full_step_length + 1 corresponds to the edge's end point\r\n\tint full_step_length = static_cast<int>(edge_length / arp.feeler_increment);\r\n\r\n\tint start_step = 0;\r\n\tMth::Vector r0 = pa;\r\n\t// attempt to create rail snippets until we've used up the rail\r\n\tdo\r\n\t{\r\n\t\t// start a new rail snippet\r\n\t\tint end_step = start_step;\r\n\t\tMth::Vector r1 = r0;\r\n\r\n\t\t// attempt to extent the rail snippet along the edge\r\n\t\tdo\r\n\t\t{\r\n\t\t\tbool fail = false;\r\n\r\n\t\t\t// check for nearby collidables\r\n\r\n\t\t\tCFeeler feeler;\r\n            \r\n\t\t\t// first side feeler\r\n\t\t\t// angled up from face in perp-normal plane starting a fraction of an inch from edge\r\n\t\t\tif ((arp.feeler_usage & LOW_CURB_FEELER_BIT))\r\n\t\t\t{\r\n\t\t\t\tMth::Vector feeler_direction = arp.sin_curb_feeler_angle_of_assent * normal + arp.cos_curb_feeler_angle_of_assent * perp;\r\n\r\n\t\t\t\tfeeler.m_start = r1 + 0.1f * feeler_direction;\r\n\t\t\t\tfeeler.m_end = r1 + arp.low_curb_feeler_length * feeler_direction;\r\n\r\n\t\t\t\tfail = feeler.GetCollision(false);\r\n\t\t\t}\r\n\r\n\t\t\t// second side feeler\r\n\t\t\t// angled up from face in perp-normal plane starting a fraction of an inch from edge\r\n\t\t\tif (!fail && (arp.feeler_usage & LOW_CURB_FEELER_BIT))\r\n\t\t\t{\r\n\t\t\t\tMth::Vector feeler_direction = arp.sin_curb_feeler_angle_of_assent * arg.p_edges[matched_edge].normal\r\n\t\t\t\t\t+ arp.cos_curb_feeler_angle_of_assent * arg.p_edges[matched_edge].perp;\r\n\r\n\t\t\t\tfeeler.m_start = r1 + 0.2f * feeler_direction;\r\n\t\t\t\tfeeler.m_end = r1 + arp.low_curb_feeler_length * feeler_direction;\r\n\r\n\t\t\t\tfail = feeler.GetCollision(false);\r\n\t\t\t}\r\n\r\n\t\t\t// vertical feeler\r\n\t\t\t// straight up starting a fraction of an inch above the edge\r\n\t\t\tif (!fail && (arp.feeler_usage & VERTICAL_FEELER_BIT))\r\n\t\t\t{\r\n\t\t\t\tfeeler.m_start = r1;\r\n\t\t\t\tfeeler.m_start[Y] += 0.2f;\r\n\r\n\t\t\t\tfeeler.m_end = r1;\r\n\t\t\t\tfeeler.m_end[Y] += arp.vertical_feeler_length;\r\n\t\t\t}\r\n\r\n\t\t\t// crossbar feeler\r\n\t\t\t// some height above rail, flush with XZ plane, perp to edge\r\n\t\t\tif (!fail && (arp.feeler_usage & CROSSBAR_FEELER_BIT))\r\n\t\t\t{\r\n\t\t\t\tMth::Vector bar;\r\n\r\n\t\t\t\tbar[X] = para[Z];\r\n\t\t\t\tbar[Y] = 0.0f;\r\n\t\t\t\tbar[Z] = -para[X];\r\n\t\t\t\tbar.Normalize();\r\n\r\n\t\t\t\tfeeler.m_start = r1;\r\n\t\t\t\tfeeler.m_start[Y] += arp.crossbar_feeler_elevation;\r\n\t\t\t\tfeeler.m_start += arp.half_crossbar_feeler_length * bar;\r\n\r\n\t\t\t\tfeeler.m_end = r1;\r\n\t\t\t\tfeeler.m_end[Y] += arp.crossbar_feeler_elevation;\r\n\t\t\t\tfeeler.m_end += -arp.half_crossbar_feeler_length * bar;\r\n\r\n\t\t\t\tfail = feeler.GetCollision(false);\r\n\t\t\t}\r\n\r\n\t\t\t// if there is collidables, the extention attempt failed\r\n\t\t\tif (fail) break;\r\n\r\n\t\t\t// there are no nearby collidables\r\n\t\t\t// so we'll attempt to stretch the snippet one step or to the end of the edge\r\n\t\t\tend_step++;\r\n\r\n\t\t\t// if we're beyond the end of the edge, we're done\r\n\t\t\tif (end_step == full_step_length + 2) break;\r\n\r\n\t\t\tif (end_step == full_step_length + 1)\r\n\t\t\t{\r\n\t\t\t\tr1 = pb;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tr1 = pa + end_step * arp.feeler_increment * para;\r\n\t\t\t}\r\n\t\t} while (true);\r\n\r\n\t\t// restore r1 to the last value it had before the failed extention\r\n\t\tend_step--;\r\n\t\tif (end_step == full_step_length + 1)\r\n\t\t\tr1 = pb;\r\n\t\telse\r\n\t\t\tr1 = pa + end_step * arp.feeler_increment * para;\r\n\r\n\t\t// the snippet is now as long as it can be\r\n\r\n\t\t// if the snippet is long enough\r\n\t\tif (end_step - start_step > 0 && (r0 - r1).LengthSqr() >= (arp.min_edge_length * arp.min_edge_length))\r\n\t\t{\r\n\t\t\t// use it\r\n\t\t\tif (!add_rail(r0, r1, arg, arp)) return false;\r\n\t\t}\r\n\r\n\t\t// jump to next start point\r\n\t\tstart_step = end_step + 2;\r\n\t\tr0 = pa + start_step * arp.feeler_increment * para;\r\n\r\n\t} while (start_step < full_step_length + 1);\r\n\r\n\treturn true;\r\n}\r\n\r\nCRailNode* CRailManager::GetRailNodeByNodeNumber( int node_num )\r\n{\r\n\tint i;\r\n\r\n\tif( mp_nodes )\r\n\t{\r\n\t\tfor( i = 0; i < m_num_nodes; i++ )\r\n\t\t{\r\n\t\t\tif( mp_nodes[i].GetNode() == node_num )\r\n\t\t\t{\r\n\t\t\t\treturn &mp_nodes[i];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n// knowns issues or ideas:\r\n// snap rail endpoints - do we want to snap the endpoints of railset together; if so, definitely make the slop parameter adjustable\r\n// vertical feeler - the vertical feeler is causing random snipping up of rails in odd places\r\n// don't destory old rails - instead, when considering a rail, check for nearly parallel rails and don't add a new rail if you find one; bin old rails first\r\n// cross-section edges finding - look for potential rails by joining up across sectors; time consuming; edge endpoints won't match, so we have to look for overlapping edges instead of just looking for matching endpoints\r\nvoid CRailManager::AutoGenerateRails ( Script::CStruct* pParams )\r\n{\r\n// 27K\r\n#ifdef\t__DEBUG_CODE__\r\n\tprintf(\"-----------------------\\n\");\r\n\r\n\t// let's use the Debug heap, since we might need a lot of memory\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\r\n\t// auto-generator's state\r\n\tSAutoRailGeneratorState arg;\r\n\r\n\targ.num_rails = 0;\t\r\n\targ.num_railsets = 0;\r\n\targ.num_active_rails = 0;\r\n\r\n\targ.p_edges = new SEdge[MAX_NUM_EDGES];\r\n\targ.p_rails = new SAutoRail[MAX_NUM_RAILS];\r\n\targ.p_railsets = new SRailSet[MAX_NUM_RAILSETS];\r\n\r\n\targ.p_rail_endpoint_list = new BinTable(ENDPOINT_BINTABLE_SIZE_BITS);\r\n\r\n\t// auto-generator's modifiable parameters\r\n\tSAutoRailGeneratorParameters arp;\r\n\r\n\t// set parameters to defaults\r\n\tarp.min_rail_edge_angle = MIN_RAIL_EDGE_ANGLE;\r\n\tarp.max_rail_angle_of_assent = MAX_RAIL_ANGLE_OF_ASSENT;\r\n\tarp.min_railset_length = MIN_RAILSET_LENGTH;\r\n\tarp.min_edge_length = MIN_EDGE_LENGTH;\r\n\tarp.feeler_increment = FEELER_INCREMENT;\r\n\tarp.max_low_curb_height = MAX_LOW_CURB_HEIGHT;\r\n\tarp.curb_feeler_angle_of_assent = LOW_CURB_FEELER_ANGLE_OF_ASSENT;\r\n\tarp.max_corner_in_railset = MAX_CORNER_IN_RAILSET;\r\n\tarp.vertical_feeler_length = VERTICAL_FEELER_LENGTH;\r\n\tarp.crossbar_feeler_elevation = CROSSBAR_FEELER_ELEVATION;\r\n\tarp.half_crossbar_feeler_length = CROSSBAR_FEELER_LENGTH;\r\n\tarp.farthest_degenerate_rail = FARTHEST_DEGENERATE_RAIL;\r\n\tarp.max_degenerate_rail_angle = MAX_DEGENERATE_RAIL_ANGLE;\r\n\tarp.connection_slop = CONNECTION_SLOP;\r\n\r\n\t// look for overrides in script parameters\r\n\tpParams->GetFloat(\"min_rail_edge_angle\", &arp.min_rail_edge_angle, Script::NO_ASSERT);\r\n\tpParams->GetFloat(\"max_rail_angle_of_assent\", &arp.max_rail_angle_of_assent, Script::NO_ASSERT);\r\n\tpParams->GetFloat(\"min_railset_length\", &arp.min_railset_length, Script::NO_ASSERT);\r\n\tpParams->GetFloat(\"min_edge_length\", &arp.min_edge_length, Script::NO_ASSERT);\r\n\tpParams->GetFloat(\"feeler_increment\", &arp.feeler_increment, Script::NO_ASSERT);\r\n\tpParams->GetFloat(\"max_low_curb_height\", &arp.max_low_curb_height, Script::NO_ASSERT);\r\n\tpParams->GetFloat(\"curb_feeler_angle_of_assent\", &arp.curb_feeler_angle_of_assent, Script::NO_ASSERT);\r\n\tpParams->GetFloat(\"max_corner_in_railset\", &arp.max_corner_in_railset, Script::NO_ASSERT);\r\n\tpParams->GetFloat(\"vertical_feeler_length\", &arp.vertical_feeler_length, Script::NO_ASSERT);\r\n\tpParams->GetFloat(\"crossbar_feeler_elevation\", &arp.crossbar_feeler_elevation, Script::NO_ASSERT);\r\n\tpParams->GetFloat(\"crossbar_feeler_length\", &arp.half_crossbar_feeler_length, Script::NO_ASSERT);\r\n\tpParams->GetFloat(\"farthest_degenerate_rail\", &arp.farthest_degenerate_rail, Script::NO_ASSERT);\r\n\tpParams->GetFloat(\"max_degenerate_rail_angle\", &arp.max_degenerate_rail_angle, Script::NO_ASSERT);\r\n\tpParams->GetFloat(\"connection_slop\", &arp.connection_slop, Script::NO_ASSERT);\r\n\r\n\tarp.half_crossbar_feeler_length /= 2.0f;\r\n\tarp.low_curb_feeler_length = arp.max_low_curb_height / cosf(DEGREES_TO_RADIANS(arp.curb_feeler_angle_of_assent));\r\n\tarp.sin_max_rail_angle_of_assent = sinf(DEGREES_TO_RADIANS(arp.max_rail_angle_of_assent));\r\n\tarp.cos_min_rail_edge_angle = cosf(DEGREES_TO_RADIANS(arp.min_rail_edge_angle));\r\n\tarp.cos_max_corner_in_railset = cosf(DEGREES_TO_RADIANS(arp.max_corner_in_railset));\r\n\tarp.sin_curb_feeler_angle_of_assent = sinf(DEGREES_TO_RADIANS(arp.curb_feeler_angle_of_assent));\r\n\tarp.cos_curb_feeler_angle_of_assent = cosf(DEGREES_TO_RADIANS(arp.curb_feeler_angle_of_assent));\r\n\tarp.cos_max_degenerate_rail_angle = cosf(DEGREES_TO_RADIANS(arp.max_degenerate_rail_angle));\r\n\r\n\t// turn on all feelers by default\r\n\tarp.feeler_usage = ALL_FEELERS_ON;\r\n\r\n\t// check for overrides in script parameters\r\n\tif (pParams->ContainsFlag(\"no_vertical_feeler\"))\r\n\t\tarp.feeler_usage &= ~VERTICAL_FEELER_BIT;\r\n\tif (pParams->ContainsFlag(\"no_crossbar_feeler\"))\r\n\t\tarp.feeler_usage &= ~CROSSBAR_FEELER_BIT;\r\n\tif (pParams->ContainsFlag(\"no_low_curb_feeler\"))\r\n\t\tarp.feeler_usage &= ~LOW_CURB_FEELER_BIT;\r\n\tif (pParams->ContainsFlag(\"no_feelers\"))\r\n\t\tarp.feeler_usage = 0;\r\n\r\n\t// check additional flags\r\n\tarp.remove_old_rails = false;\r\n\tif (pParams->ContainsFlag(\"overwrite\"))\r\n\t{\r\n\t\tarp.remove_old_rails = true;\r\n\t}\r\n\r\n\t// dump parameter state\r\n\r\n\tprintf(\"min_rail_edge_angle = %f\\n\", arp.min_rail_edge_angle);\r\n\tprintf(\"max_rail_angle_of_assent = %f\\n\", arp.max_rail_angle_of_assent);\r\n\tprintf(\"min_railset_length = %f\\n\", arp.min_railset_length);\r\n\tprintf(\"min_edge_length = %f\\n\", arp.min_edge_length);\r\n\tprintf(\"connection_slop = %f\\n\", arp.connection_slop);\r\n\tprintf(\"feeler_increment = %f\\n\", arp.feeler_increment);\r\n\tprintf(\"max_low_curb_height = %f\\n\", arp.max_low_curb_height);\r\n\tprintf(\"curb_feeler_angle_of_assent = %f\\n\", arp.curb_feeler_angle_of_assent);\r\n\tprintf(\"max_corner_in_railset = %f\\n\", arp.max_corner_in_railset);\r\n\tprintf(\"vertical_feeler_length = %f\\n\", arp.vertical_feeler_length);\r\n\tprintf(\"crossbar_feeler_length = %f\\n\", 2.0f * arp.half_crossbar_feeler_length);\r\n\tprintf(\"crossbar_feeler_elevation = %f\\n\", arp.crossbar_feeler_elevation);\r\n\r\n\tif (!arp.remove_old_rails)\r\n\t{\r\n\t\tprintf(\"farthest_degenerate_rail = %f\\n\", arp.farthest_degenerate_rail);\r\n\t\tprintf(\"max_degenerate_rail_angle = %f\\n\", arp.max_degenerate_rail_angle);\r\n\t}\r\n\r\n\tif (!(arp.feeler_usage & VERTICAL_FEELER_BIT))\r\n\t\tprintf(\"vertical feeler deactivated\\n\");\r\n\tif (!(arp.feeler_usage & CROSSBAR_FEELER_BIT))\r\n\t\tprintf(\"crossbar feeler deactivated\\n\");\r\n\tif (!(arp.feeler_usage & LOW_CURB_FEELER_BIT))\r\n\t\tprintf(\"low-curb feeler deactivated\\n\");\r\n\tif (arp.feeler_usage == ALL_FEELERS_ON)\r\n\t\tprintf(\"all feelers active\\n\");\r\n\r\n\tif (arp.remove_old_rails)\r\n\t{\r\n\t\tprintf(\"removing existing rails\\n\");\r\n\t}\r\n\telse\r\n\t{\r\n\t\tprintf(\"retaining existing rails\\n\");\r\n\t}\r\n\r\n\tprintf(\"generating rails...\\n\");\r\n\r\n\tNx::CScene *p_scene = Nx::CEngine::sGetMainScene();\r\n\tLst::HashTable<Nx::CSector>* p_sector_list = p_scene->GetSectorList();\r\n\tif (!p_sector_list)\r\n\t\treturn;\r\n\r\n\t// loop through every sector in the scene\r\n\t// NOTE: to do a better job, we may need to attempt to match edges between sectors\r\n\t// if so, we'd have to deal with the issue of not being able to expect edge vertices to match up\r\n\tp_sector_list->IterateStart();\t\r\n\tNx::CSector *p_sector = p_sector_list->IterateNext();\t\t\r\n\twhile(p_sector)\r\n\t{\r\n\t\tNx::CCollObjTriData *p_coll_obj = p_sector->GetCollSector()->GetGeometry();\r\n\t\tif (!p_coll_obj || !p_sector->IsActive() || !p_sector->IsCollidable())\r\n\t\t{\r\n\t\t\tp_sector = p_sector_list->IterateNext();\t\t\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// we have the collision data, now build a list of edges\r\n\t\t// based solely on positions of verts\r\n\r\n\t\tint\tnum_edges = 0;\r\n\r\n\t\tMth::Vector p[3];\r\n\t\t\r\n\t\t// loop though the faces of the sector\r\n\t\tint num_faces = p_coll_obj->GetNumFaces();\r\n\t\tfor (int face = 0; face < num_faces; face++)\r\n\t\t{\r\n\t\t\t// get the normal\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\tMth::Vector normal = p_coll_obj->GetFaceNormal(face);\r\n\t\t\t\r\n\t\t\t// Get the three vertex indicies for this face\r\n\t\t\t// and the vertex position into the above arrays\r\n\t\t\tint v[3];\r\n            for (int i = 0; i < 3; i++)\t\t\t\r\n\t\t\t{\r\n\t\t\t\tv[i] = p_coll_obj->GetFaceVertIndex(face,i);\r\n\t\t\t\tp[i] = p_coll_obj->GetRawVertexPos(v[i]);\r\n\t\t\t\t\t\r\n\t\t\t}\r\n\t\t\t// iterate over the edges (0->1, 1->2, 2->0)\r\n\t\t\tfor (int a = 0; a < 3; a++)\t   \t\t// 'a' is the first point on the edge\r\n\t\t\t{\t\t\t\t\r\n\t\t\t\tint b = (a + 1) % 3;\t\t\t// 'b' is the second point on the edge\r\n\t\t\t\tint c = (b + 1) % 3;\t\t\t// 'c' is the opposite point on the triangle\r\n\t\t\t\t// we are considering the edge a->b\r\n\r\n\t\t\t\t// generate a unit vector along the edge from a to b, from start to end\r\n\t\t\t\tMth::Vector\tpara = (p[b] - p[a]);\r\n\t\t\t\tfloat edge_length = para.Length();\r\n\t\t\t\tif (edge_length != 0.0f) para /= edge_length; // normalize by hand since we have the length\r\n\r\n\t\t\t\t// cull certain edges at this point; we don't cull faces at this point in\r\n\t\t\t\t// order to better match edges\r\n\r\n\t\t\t\t// cull very short edges\r\n\t\t\t\tif (edge_length < arp.min_edge_length) continue;\r\n\r\n\t\t\t\t// use edges only if less than some angle from horizontal\r\n\t\t\t\tif (Mth::Abs(para[Y]) > arp.sin_max_rail_angle_of_assent) continue;\r\n\r\n\t\t\t\t// generate a unit vector along the triangle face perpendicular to the edge\r\n\t\t\t\tMth::Vector perp = (p[c] - p[a]);\r\n\t\t\t\tperp -= Mth::DotProduct(perp, para) * para;\r\n\t\t\t\tperp.Normalize();\r\n\r\n\t\t\t\t// check to see if we already have this edge's match; bail if we find a match\r\n\t\t\t\tbool new_edge = true;\r\n\t\t\t\tfor (int edge = 0; edge < num_edges && new_edge; edge++)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (arg.p_edges[edge].matched) continue;\r\n\t\t\t\t\r\n\t\t\t\t\t// check for matched edge \r\n\t\t\t\t\tif (very_close(arg.p_edges[edge].p0, p[a], arp) && very_close(arg.p_edges[edge].p1, p[b], arp)\r\n\t\t\t\t\t\t|| \tvery_close(arg.p_edges[edge].p0, p[b], arp) && very_close(arg.p_edges[edge].p1, p[a], arp))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnew_edge = false;\r\n\t\t\t\t\t\targ.p_edges[edge].matched = true;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// we've found a match, let's see if the edge is a good rail\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// ignore upside down faces\t\t\t\r\n\t\t\t\t\t\t\t// NOTE: we could probably come up with a better heuristic using both edges' normals\r\n\t\t\t\t\t\t\tif (normal[Y] < -0.707 || arg.p_edges[edge].normal[Y] < -0.707) break;\r\n\r\n\t\t\t\t\t\t\t// ignore face if non-collidable\r\n\t\t\t\t\t\t\tif (p_coll_obj->GetFaceFlags(face) & mFD_NON_COLLIDABLE) break;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t// exclude roughly coplanar polygons\r\n\t\t\t\t\t\t\tif (Mth::DotProduct(normal, arg.p_edges[edge].normal) > arp.cos_min_rail_edge_angle) break;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t// cull out interior edges; that is, if sum of the normals points along the sum of the perps\r\n\t\t\t\t\t\t\tif (Mth::DotProduct(perp + arg.p_edges[edge].perp, normal + arg.p_edges[edge].normal) > 0.0f) break;\r\n\r\n\t\t\t\t\t\t\t// we don't want the edges of verts to generate rails, only the tops; so cull non-horizontal vert rails\r\n\t\t\t\t\t\t\tif ((arg.p_edges[edge].vert || (p_coll_obj->GetFaceFlags(face) & mFD_VERT)) && Mth::Abs(para[Y]) > 0.1f) break;\r\n\r\n\t\t\t\t\t\t\t// if we haven't removed the old rails\r\n\t\t\t\t\t\t\tif (!arp.remove_old_rails)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// loop over all old rails and check for degeneracy\r\n\t\t\t\t\t\t\t\tint check_node = 0;\r\n\t\t\t\t\t\t\t\tfor (check_node = 0; check_node < m_num_nodes; check_node++)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tCRailNode *pRailNode = &mp_nodes[check_node];\r\n\t\r\n\t\t\t\t\t\t\t\t\tif (!pRailNode->m_pNextLink) continue;\r\n\t\r\n\t\t\t\t\t\t\t\t\t// is the new rail within a loose bounding box of the old rail\r\n\t\t\t\t\t\t\t\t\tif (p[a][X] < pRailNode->m_BBMin[X] - arp.farthest_degenerate_rail) continue;\r\n\t\t\t\t\t\t\t\t\tif (p[a][Y] < pRailNode->m_BBMin[Y] - arp.farthest_degenerate_rail) continue;\r\n\t\t\t\t\t\t\t\t\tif (p[a][Z] < pRailNode->m_BBMin[Z] - arp.farthest_degenerate_rail) continue;\r\n\t\t\t\t\t\t\t\t\tif (p[a][X] > pRailNode->m_BBMax[X] + arp.farthest_degenerate_rail) continue;\r\n\t\t\t\t\t\t\t\t\tif (p[a][Y] > pRailNode->m_BBMax[Y] + arp.farthest_degenerate_rail) continue;\r\n\t\t\t\t\t\t\t\t\tif (p[a][Z] > pRailNode->m_BBMax[Z] + arp.farthest_degenerate_rail) continue;\r\n\t\t\t\t\t\t\t\t\tif (p[b][X] < pRailNode->m_BBMin[X] - arp.farthest_degenerate_rail) continue;\r\n\t\t\t\t\t\t\t\t\tif (p[b][Y] < pRailNode->m_BBMin[Y] - arp.farthest_degenerate_rail) continue;\r\n\t\t\t\t\t\t\t\t\tif (p[b][Z] < pRailNode->m_BBMin[Z] - arp.farthest_degenerate_rail) continue;\r\n\t\t\t\t\t\t\t\t\tif (p[b][X] > pRailNode->m_BBMax[X] + arp.farthest_degenerate_rail) continue;\r\n\t\t\t\t\t\t\t\t\tif (p[b][Y] > pRailNode->m_BBMax[Y] + arp.farthest_degenerate_rail) continue;\r\n\t\t\t\t\t\t\t\t\tif (p[b][Z] > pRailNode->m_BBMax[Z] + arp.farthest_degenerate_rail) continue;\r\n\t\r\n\t\t\t\t\t\t\t\t\t// is the new rail parallel to the old rail\r\n\t\t\t\t\t\t\t\t\tMth::Vector old_para = pRailNode->m_pNextLink->m_pos - pRailNode->m_pos;\r\n\t\t\t\t\t\t\t\t\told_para.Normalize();\r\n\t\t\t\t\t\t\t\t\tif (Mth::Abs(Mth::DotProduct(para, old_para)) < arp.cos_max_degenerate_rail_angle) continue;\r\n\t\r\n\t\t\t\t\t\t\t\t\t// if the perpendicular distance from the start of the new rail to the start of the old rail is small, it's degenerate\r\n\t\t\t\t\t\t\t\t\tperp = p[a] - pRailNode->m_pos;\r\n\t\t\t\t\t\t\t\t\tperp -= Mth::DotProduct(para, perp) * para;\r\n\t\t\t\t\t\t\t\t\tif (perp.LengthSqr() < (arp.farthest_degenerate_rail * arp.farthest_degenerate_rail)) break;\r\n\t\r\n\t\t\t\t\t\t\t\t\t// if the perpendicular distance from the end of the new rail to the start of the old rail is small, it's degenerate\r\n\t\t\t\t\t\t\t\t\tperp = p[b] - pRailNode->m_pos;\r\n\t\t\t\t\t\t\t\t\tperp -= Mth::DotProduct(para, perp) * para;\r\n\t\t\t\t\t\t\t\t\tif (perp.LengthSqr() < (arp.farthest_degenerate_rail * arp.farthest_degenerate_rail)) break;\r\n\t\r\n\t\t\t\t\t\t\t\t\t// if the perpendicular distance from the start of the new rail to the end of the old rail is small, it's degenerate\r\n\t\t\t\t\t\t\t\t\tperp = p[a] - pRailNode->m_pNextLink->m_pos;\r\n\t\t\t\t\t\t\t\t\tperp -= Mth::DotProduct(para, perp) * para;\r\n\t\t\t\t\t\t\t\t\tif (perp.LengthSqr() < (arp.farthest_degenerate_rail * arp.farthest_degenerate_rail)) break;\r\n\t\r\n\t\t\t\t\t\t\t\t\t// if the perpendicular distance from the end of the new rail to the end of the old rail is small, it's degenerate\r\n\t\t\t\t\t\t\t\t\tperp = p[b] - pRailNode->m_pNextLink->m_pos;\r\n\t\t\t\t\t\t\t\t\tperp -= Mth::DotProduct(para, perp) * para;\r\n\t\t\t\t\t\t\t\t\tif (perp.LengthSqr() < (arp.farthest_degenerate_rail * arp.farthest_degenerate_rail)) break;\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\t// if we broke from the loop, cull the rail due to degeneracy\r\n\t\t\t\t\t\t\t\tif (check_node != m_num_nodes) break;\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// use feelers to test for good rails within this edge\r\n\t\t\t\t\t\t\tif (!consider_rail(p[a], p[b], edge, para, normal, perp, edge_length, arg, arp))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tprintf(\"failed: more than %d rails\\n\", MAX_NUM_RAILS);\r\n\t\t\t\t\t\t\t\tgoto ABORT;\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t} // END valid rail test block\r\n\t\t\t\t\t} // END if (this edge matches)\r\n\t\t\t\t} // END loop over previous edges looking for match\r\n\t\t\t\t\r\n\t\t\t\t// if we didn't find a match\r\n\t\t\t\tif (new_edge)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (num_edges + 1 < MAX_NUM_EDGES)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// save the new edge\r\n\t\t\t\t\t\targ.p_edges[num_edges].p0 = p[a];\r\n\t\t\t\t\t\targ.p_edges[num_edges].p1 = p[b];\r\n\t\t\t\t\t\targ.p_edges[num_edges].normal = normal;\r\n\t\t\t\t\t\targ.p_edges[num_edges].perp = perp;\r\n\t\t\t\t\t\targ.p_edges[num_edges].matched = false;\r\n\t\t\t\t\t\targ.p_edges[num_edges].vert = p_coll_obj->GetFaceFlags(face) & mFD_VERT;\r\n\r\n\t\t\t\t\t\tnum_edges++;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tprintf(\"failed: more that %d edges in an object\\n\", MAX_NUM_EDGES);\r\n\t\t\t\t\t\tgoto ABORT;\t// sorry dijkstra ...\r\n\t\t\t\t\t}\r\n\t\t\t\t} // END if (new_edge)\r\n\t\t\t} // END for (int a=0;a<3;a++) (iterating over 3 edges in a face)\r\n\t\t} // END for (int face = 0; face < num_faces; face++) (iterate over faces in a collision sector)\r\n\r\n\t\tp_sector = p_sector_list->IterateNext();\r\n\t} // END loop over sectors\r\n\r\n\tprintf(\"building railsets...\\n\");\r\n\r\n\t// we need to group in the individual rails into continuous rail sets, so we can cull short solo rails and short railsets\r\n\t// note that the connectivity is not perfect in the sense that it can make loops but not loops with tails\r\n\r\n\t// loop through rail set\r\n\tfor (int r = 0; r < arg.num_rails; r++)\r\n\t{\r\n\t\tSAutoRail& rail = arg.p_rails[r];\r\n\r\n\t\t// loop over rail's endpoints\r\n\t\tfor (int endpoint = START; endpoint <= END; endpoint++)\r\n\t\t{\r\n\t\t\t// if the endpoint is connected\r\n\t\t\tif (rail.endpoints[endpoint].connection != -1) continue;\r\n\r\n\t\t\t// now we'll check for connections\r\n\r\n\t\t\tint rail_key = generate_endpoint_key(rail.endpoints[endpoint].p);\r\n\t\r\n\t\t\t// loop over all rails in same endpoint bin as rail's endpoint's bin\r\n\t\t\t// we will check only these rails for connections\r\n\t\t\tfor (SAutoRail* next_rail = arg.p_rail_endpoint_list->GetFirstItem(rail_key);\r\n\t\t\t\tnext_rail;\r\n\t\t\t\tnext_rail = arg.p_rail_endpoint_list->GetNextItem(rail_key, next_rail))\r\n\t\t\t{\r\n\t\t\t\tSAutoRail& match_rail = *next_rail;\r\n\r\n\t\t\t\t// we'll always find ourself\r\n\t\t\t\tif (&match_rail == &rail) continue;\r\n\t\r\n\t\t\t\t// check only rails with unconnected endpoints\r\n\t\t\t\tif (match_rail.endpoints[START].connection != -1 && match_rail.endpoints[END].connection != -1) continue;\r\n\r\n\t\t\t\t// rails connect only if the angle between them is small; this should be adjusted or adjustable\r\n\t\t\t\tfloat dot = Mth::DotProduct(rail.para, match_rail.para);\r\n\t\t\t\tif (Mth::Abs(dot) < arp.cos_max_corner_in_railset) continue;\r\n\r\n\t\t\t\tbool reverse_connection = false;\r\n\r\n\t\t\t\t// see if the start of the match rail is connected to our endpoint\r\n\t\t\t\tif (match_rail.endpoints[START].connection == -1\r\n\t\t\t\t\t&& very_close(rail.endpoints[endpoint].p, match_rail.endpoints[START].p, arp))\r\n\t\t\t\t{\r\n\t\t\t\t\t// rails connect only for obtuse angles\r\n\t\t\t\t\tif (endpoint == START)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treverse_connection = true;\r\n\t\t\t\t\t\tif (dot > 0.0f) continue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (dot < 0.0f) continue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\trail.endpoints[endpoint].connection = &match_rail - arg.p_rails;\r\n\t\t\t\t\tmatch_rail.endpoints[START].connection = r;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// else see if the end of the match rail is connected to our endpoint\r\n\t\t\t\telse if (match_rail.endpoints[END].connection == -1\r\n\t\t\t\t\t&& very_close(rail.endpoints[endpoint].p, match_rail.endpoints[END].p, arp))\r\n\t\t\t\t{\r\n\t\t\t\t\t// rails connect only for obtuse angles\r\n\t\t\t\t\tif (endpoint == END)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treverse_connection = true;\r\n\t\t\t\t\t\tif (dot > 0.0f) continue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (dot < 0.0f) continue;\r\n\t\t\t\t\t}\r\n                    \r\n\t\t\t\t\trail.endpoints[endpoint].connection = &match_rail - arg.p_rails;\r\n\t\t\t\t\tmatch_rail.endpoints[END].connection = r;\r\n\t\t\t\t} // END ifelse determining connectivity\r\n\r\n\t\t\t\t// if this endpoint of the rail is not found to be connected, continue\r\n\t\t\t\tif (rail.endpoints[endpoint].connection == -1) continue;\r\n\r\n\t\t\t\t// otherwise, we'll add the rail to a railset\r\n\r\n\t\t\t\t// if both rails are not in railset\r\n\t\t\t\tif (match_rail.railset == -1 && rail.railset == -1)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (arg.num_railsets == MAX_NUM_RAILSETS)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tprintf(\"failed: more that %d railsets\\n\", MAX_NUM_RAILSETS);\r\n\t\t\t\t\t\tgoto ABORT;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// setup a new railset\r\n\t\t\t\t\trail.railset = arg.num_railsets;\r\n\t\t\t\t\targ.p_railsets[arg.num_railsets].length = rail.length;\r\n\t\t\t\t\targ.num_railsets++;\r\n\r\n\t\t\t\t\t// add match_rail to rail's new railset\r\n\t\t\t\t\tmatch_rail.railset = rail.railset;\r\n\t\t\t\t\targ.p_railsets[match_rail.railset].length += match_rail.length;\r\n\r\n\t\t\t\t\t// swap the rail's endpoints if the connection is reverse\r\n\t\t\t\t\tif (reverse_connection)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSAutoRailEndpoint temp = rail.endpoints[START];\r\n\t\t\t\t\t\trail.endpoints[START] = rail.endpoints[END];\r\n\t\t\t\t\t\trail.endpoints[END] = temp;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t// if only match_rail has a railset\r\n\t\t\t\t}\r\n\t\t\t\telse if (match_rail.railset != -1 && rail.railset == -1)\r\n\t\t\t\t{\r\n\t\t\t\t\t// add rail to match_rail's railset\r\n\t\t\t\t\trail.railset = match_rail.railset;\r\n\t\t\t\t\targ.p_railsets[rail.railset].length += rail.length;\r\n\r\n\t\t\t\t\t// swap the rail's endpoints if the connection is reverse\r\n\t\t\t\t\tif (reverse_connection)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSAutoRailEndpoint temp = rail.endpoints[START];\r\n\t\t\t\t\t\trail.endpoints[START] = rail.endpoints[END];\r\n\t\t\t\t\t\trail.endpoints[END] = temp;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t// if only rail has a railset\r\n\t\t\t\t}\r\n\t\t\t\telse if (match_rail.railset == -1 && rail.railset != -1)\r\n\t\t\t\t{\r\n\t\t\t\t\t// add match_rail to rail's railset\r\n\t\t\t\t\tmatch_rail.railset = rail.railset;\r\n\t\t\t\t\targ.p_railsets[match_rail.railset].length += rail.length;\r\n\r\n\t\t\t\t\t// swap the match rail's endpoints if the connection is reverse\r\n\t\t\t\t\tif (reverse_connection)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tSAutoRailEndpoint temp = match_rail.endpoints[START];\r\n\t\t\t\t\t\tmatch_rail.endpoints[START] = match_rail.endpoints[END];\r\n\t\t\t\t\t\tmatch_rail.endpoints[END] = temp;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t// if both rails have multrails\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// join railsets\r\n\t\t\t\t\t// NOTE: this currently waists a railset; more flexible railset data structure would fix this;\r\n\t\t\t\t\t// can i use STL? if geometry is ordered in any reasonable fashion, waist should be minimal\r\n\r\n\t\t\t\t\t// match_rail's railset survives\r\n\t\t\t\t\tif (match_rail.railset != rail.railset)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmatch_rail.length += arg.p_railsets[rail.railset].length;\r\n\t\t\t\t\t\tfor (int n = arg.num_rails; n--; )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif (arg.p_rails[n].railset == rail.railset) {\r\n\t\t\t\t\t\t\t\targ.p_rails[n].railset = match_rail.railset;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\trail.railset = match_rail.railset;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// swap all of the rail's railset's endpoints if the connection is reverse\r\n\t\t\t\t\t// if we're closing a ring, the connection should never be reversed; so that shouldn't be a worry\r\n\t\t\t\t\tif (reverse_connection)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// traverse in the opposite direction of the connection\r\n\t\t\t\t\t\tint traversal_direction = endpoint ^ 1;\r\n\r\n\t\t\t\t\t\t// traverse the rail's railset\r\n\t\t\t\t\t\tfor (int s = r; s != -1; s = arg.p_rails[s].endpoints[traversal_direction].connection)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tSAutoRailEndpoint temp = arg.p_rails[s].endpoints[START];\r\n\t\t\t\t\t\t\targ.p_rails[s].endpoints[START] = arg.p_rails[s].endpoints[END];\r\n\t\t\t\t\t\t\targ.p_rails[s].endpoints[END] = temp;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t} // END ifelse block determining rail and match_rail's previous connectivity\r\n\t\t\t} // END loop over potential match rails\r\n\r\n\t\t} // END loop over endpoints\r\n\t} // END loop over all rails\r\n\r\n\tprintf(\"culling short rails...\\n\");\r\n\r\n\t// now we have rails grouped into railsets; we can cull rails based on their length or the length of their railset\r\n\tfor (int r = 0; r < arg.num_rails; r++)\r\n\t{\r\n\t\tSAutoRail& rail = arg.p_rails[r];\r\n\r\n\t\t// solo rails\r\n\t\tif (rail.railset == -1)\r\n\t\t{\r\n\t\t\t// cull short solo rails\r\n\t\t\tif (rail.length < arp.min_railset_length)\r\n\t\t\t{\r\n\t\t\t\trail.disabled = true;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\t\t// railsets\r\n\t\telse\r\n\t\t{\r\n\t\t\t// cull short railsets\r\n\t\t\tif (arg.p_railsets[rail.railset].length < arp.min_railset_length)\r\n\t\t\t{\r\n\t\t\t\trail.disabled = true;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\targ.num_active_rails++;\r\n\t} // END loop over rails\r\n\r\n\tif (!arp.remove_old_rails && arg.num_rails == 0)\r\n\t{\r\n\t\tprintf(\"failed: no rails found\\n\");\r\n\t\tgoto ABORT;\r\n\t}\r\n\r\n\tprintf(\"creating rail nodes...\\n\");\r\n\r\n\t// block to scope the final-rail-list generation variables\r\n\t{\r\n\t\t// we need to count the number of nodes required for the new rails\r\n\t\t// new_num_nodes = (num rails) + (num rails with no end connection)\t+ (num old nodes)\r\n\t\tint new_num_nodes = arg.num_active_rails;\r\n\t\tfor (int r = arg.num_rails; r--; )\r\n\t\t{\r\n\t\t\tif (!arg.p_rails[r].disabled && arg.p_rails[r].endpoints[END].connection == -1)\r\n\t\t\t{\r\n\t\t\t\tnew_num_nodes++;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!arp.remove_old_rails)\r\n\t\t{\r\n\t\t\tnew_num_nodes += m_num_nodes;\r\n\t\t}\r\n\t\r\n\t\t// and create the array for the rails\t\r\n\t\tCRailNode* p_new_nodes = (CRailNode*)Mem::Malloc(new_num_nodes * sizeof(CRailNode));\r\n\t\r\n\t\t// add the old rails to the new data structure\r\n\t\tint next_node = 0;\r\n\t\tif (!arp.remove_old_rails)\r\n\t\t{\r\n\t\t\t// loop over the old nodes\r\n\t\t\tfor (; next_node < m_num_nodes; next_node++)\r\n\t\t\t{\r\n\t\t\t\tCRailNode* pOldRailNode = &mp_nodes[next_node];\r\n\t\t\t\tCRailNode* pRailNode = &p_new_nodes[next_node];\r\n\r\n\t\t\t\tpRailNode->m_node = next_node;\r\n\r\n\t\t\t\t// calculate connectivity using pointer offsets\r\n\t\t\t\tpRailNode->m_pNextLink = (pOldRailNode->m_pNextLink\r\n\t\t\t\t\t\t\t\t\t\t  ? pOldRailNode->m_pNextLink - mp_nodes + p_new_nodes\r\n\t\t\t\t\t\t\t\t\t\t  : NULL);\r\n\t\t\t\tpRailNode->m_pPrevLink = (pOldRailNode->m_pPrevLink\r\n\t\t\t\t\t\t\t\t\t\t  ? pOldRailNode->m_pPrevLink - mp_nodes + p_new_nodes\r\n\t\t\t\t\t\t\t\t\t\t  : NULL);\r\n\r\n\t\t\t\t// copy in their state\r\n\t\t\t\tpRailNode->m_flags = pOldRailNode->m_flags;\r\n\t\t\t\tpRailNode->m_pos = pOldRailNode->m_pos;\r\n\t\t\t\tpRailNode->m_terrain_type = pOldRailNode->m_terrain_type; // debug colors for now pOldRailNode->m_terrain_type;\r\n\t\t\t\tpRailNode->m_BBMin = pOldRailNode->m_BBMin;\r\n\t\t\t\tpRailNode->m_BBMax = pOldRailNode->m_BBMax;\r\n\t\t\t} // END loop over old nodes\r\n\t\t} // END if retaining old rails\r\n\t\r\n\t\t// iterate over the nodes and add the new rails to the array; each time we hit a railset, we move to the head, then traverse the set, adding the\r\n\t\t// rails; not the most optimal algorithm but simple; we skip previously added rails and we move through the array\r\n\t\tfor (int r = 0; r < arg.num_rails; r++)\r\n\t\t{\r\n\t\t\t// because we add whole railsets at once, we may already have added any given rail\r\n\t\t\tif (arg.p_rails[r].disabled) continue;\r\n\r\n\t\t\t// traverse to start of this rail's railset watching for a loop\r\n\t\t\tint s = r;\r\n\t\t\twhile (arg.p_rails[s].endpoints[START].connection != -1)\r\n\t\t\t{\r\n\t\t\t\ts = arg.p_rails[s].endpoints[START].connection;\r\n\t\t\t\tif (s == r) break;\r\n\t\t\t}\r\n\r\n\t\t\t// traverse the railset, adding nodes as we go\r\n\t\t\tint starting_rail = s;\r\n\t\t\tCRailNode* p_starting_node = &p_new_nodes[next_node];\r\n\t\t\tint last_s;\r\n\t\t\tdo {\r\n\t\t\t\tCRailNode* pRailNode = &p_new_nodes[next_node];\r\n\t\t\t\tpRailNode->m_node = next_node;\r\n\r\n\t\t\t\tif (arg.p_rails[s].endpoints[START].connection != -1)\r\n\t\t\t\t{\r\n\t\t\t\t\tpRailNode->m_pPrevLink = &p_new_nodes[next_node - 1];\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpRailNode->m_pPrevLink = NULL;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// check for a loop\r\n\t\t\t\tif (arg.p_rails[s].endpoints[END].connection != starting_rail)\r\n\t\t\t\t{\r\n\t\t\t\t\tpRailNode->m_pNextLink = &p_new_nodes[next_node + 1];\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpRailNode->m_pNextLink = p_starting_node;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tpRailNode->m_flags = 0;\r\n\t\t\t\tpRailNode->SetActive(true);\r\n\t\t\t\tpRailNode->m_pos = arg.p_rails[s].endpoints[START].p;\r\n\t\t\t\tif (arg.p_rails[s].railset == -1)\r\n\t\t\t\t\tpRailNode->m_terrain_type = vTERRAIN_CONCSMOOTH; // red\r\n\t\t\t\telse\r\n\t\t\t\t\tpRailNode->m_terrain_type = vTERRAIN_METALSMOOTH; // blue\r\n\t\t\t\tRail_ComputeBB(arg.p_rails[s].endpoints[START].p, arg.p_rails[s].endpoints[END].p, pRailNode->m_BBMin, pRailNode->m_BBMax);\r\n\r\n\t\t\t\t// mark as having been added\r\n\t\t\t\targ.p_rails[s].disabled = true;\r\n\t\t\t\tnext_node++;\r\n\r\n\t\t\t\tlast_s = s;\r\n\t\t\t\ts = arg.p_rails[s].endpoints[END].connection;\r\n\t\t\t} while (s != -1 && s != starting_rail);\r\n\r\n\t\t\t// if not a loop\r\n\t\t\tif (s != starting_rail)\r\n\t\t\t{\r\n\t\t\t\t// add extra ending node of railset\r\n\r\n\t\t\t\tCRailNode* pRailNode = &p_new_nodes[next_node];\r\n\t\t\t\tpRailNode->m_node = next_node;\r\n\t\r\n\t\t\t\tpRailNode->m_pPrevLink = &p_new_nodes[next_node - 1];\r\n\t\t\t\tpRailNode->m_pNextLink = NULL;\r\n\r\n\t\t\t\tpRailNode->m_pos = arg.p_rails[last_s].endpoints[END].p;\r\n\t\r\n\t\t\t\tnext_node++;\r\n\t\t\t}\r\n\t\t} // END final-rail-list generation scope\r\n\t\r\n\t\t// first reset the manager (this)\r\n\t\t// Note this invalidates mp_node_array (setting it to NULL)\r\n\t\t// so I had to patch up a couple of placed in skater.cpp\r\n\t\t// that were using the rail manager's node array\r\n\t\tCleanup();\r\n\t\r\n\t\tmp_nodes = p_new_nodes;\r\n \t\tm_num_nodes = new_num_nodes;\r\n\t\r\n\t\tprintf(\"complete.\\n\");\r\n\r\n\t}\r\n\r\nABORT:\r\n\r\n\tdelete\targ.p_rail_endpoint_list;\r\n\r\n\tdelete\t[] arg.p_railsets;\t\r\n\tdelete\t[] arg.p_edges;\r\n\tdelete  [] arg.p_rails;\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\tprintf(\"-----------------------\\n\");\r\n#endif\t\r\n}\r\n\r\n}\r\n\t\t\t   \r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/rail.h",
    "content": "//////////////////////////////////////////\r\n// rail.h\r\n\r\n#ifndef __OBJECTS_RAIL_H\r\n#define __OBJECTS_RAIL_H\r\n                        \r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <gfx/nxflags.h>\r\n                           \r\nnamespace Script\r\n{\r\n\tclass\tCArray;\r\n\tclass\tCStruct;\r\n}\r\n\r\n#define\tMAX_RAIL_LINKS 4\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\nclass\tCRailManager;\r\nclass\tCWalkComponent;\r\nstruct\tSHangRailData;\r\nstruct\tSLadderRailData;\r\n\r\nenum ERailNodeFlag\r\n{\t\r\n\tLIP_OVERRIDE,\t\t// always do a lip trick on this\r\n\tDEFAULT_LINE,\r\n\tACTIVE,\r\n\tNO_CLIMBING,\r\n\tONLY_CLIMBING,\r\n\tLADDER,\r\n\tNO_HANG_WITH_RIGHT_ALONG_RAIL,\r\n\tNO_HANG_WITH_LEFT_ALONG_RAIL\r\n};\r\n\r\n\r\n// seperating out a parallel structure of CRailLinks, as only used \r\n// when rails are first parsed\r\nclass\tCRailLinks\r\n{\r\n\tfriend class CRailManager;\r\n\tsint16 m_link[MAX_RAIL_LINKS];\t// link numbers\t\r\n};\r\n\r\nclass CRailNode : public Spt::Class\r\n{\r\n\tfriend class  CRailManager;\r\n\r\npublic:\t\t\t\t\t\t  \r\n\tbool \t\t\tProbablyOnSameRailAs(int SearchNode) const;\r\n\tint\t\t\t\tSide(const Mth::Vector &vel) const;\r\n\t\r\n\tconst CRailNode\t*\tGetNextLink() const\t\t\t\t{return m_pNextLink;}\t\r\n\tconst CRailNode\t*\tGetPrevLink() const\t\t\t\t{return m_pPrevLink;}\t\r\n\tconst sint16\t\t\tGetNode() const \t  \t\t\t\t{return m_node;}\r\n//\tconst sint16\t\t\tGetLink() const\t  \t\t\t\t{return m_link;}\r\n\tconst ETerrainType\tGetTerrain() const\t  \t\t\t{return (ETerrainType) m_terrain_type;}\r\n\t\r\n\tvoid\t\t\t\tSetActive(bool active)\t\t{if (active) SetFlag(ACTIVE); else ClearFlag(ACTIVE);}\r\n\tconst bool\t\t\tGetActive() const\t\t\t\t\t{return GetFlag(ACTIVE);}\r\n\tconst bool\t\t\tIsActive() const\t\t\t\t\t{return GetActive();}\r\n\r\n\tvoid\t\t\tSetFlag(ERailNodeFlag flag) {m_flags.Set(flag);}\r\n\tvoid\t\t\tClearFlag(ERailNodeFlag flag) {m_flags.Clear(flag);}\r\n\tbool\t\t\tGetFlag(ERailNodeFlag flag) const {return m_flags.Test(flag);}\r\n\r\nprotected:\r\n\r\n// MEMOPT:  In theory this could all fit in 3x16 = 48 bytes, instead it is 64, becaute the Mth::Vectors are 16 byte aligned\r\n// possibly could define a Mth::Vector3 that uses 12 bytes, with appropiate copy operators.\r\n\r\n\tMth::Vector m_BBMin;\t\t// bounding box for this node and the subsequent one\r\n\tMth::Vector m_BBMax;\t\t// (or just a zero-sized box, if not applicable)\r\n\tMth::Vector m_pos;\t\t\t// position of the node\r\n\r\n    Mth::Quat m_orientation;    // orientation of the rail node; only set for climbing nodes\r\n\t\r\n\tCRailNode *m_pNextLink;\t\t// Pointer to next Node\tin rail(or NULL if none)\r\n\tCRailNode *m_pPrevLink;\t\t// Pointer to previous Node\t(or NULL if none)\r\n\r\n\tFlags< ERailNodeFlag > m_flags; // flags for rail segment\r\n\t\r\n\tsint16 m_node;\t\t\t\t// Number of the node in the trigger array\t\r\n\tuint8 m_terrain_type;\t\t// play the correct grind sound on the rail...\r\n\t\r\n    \r\n\r\n// the position getting functions are private\r\n// so you can only access them through the rail manager\r\n// (as you need to know if it's transformed or not)\r\nprivate:\r\n\tconst Mth::Vector&\tGetPos() const;\t \r\n\tconst Mth::Quat&\tGetOrientation() const;\t \r\n\tconst Mth::Vector&\tGetBBMin() const;\r\n\tconst Mth::Vector&\tGetBBMax() const;\r\n\t\t\t\t\t\t  \r\n};\r\n\r\n\r\n\r\nclass CRailManager : public Spt::Class\r\n{\r\n\r\npublic:\r\n\t\t\t\t\tCRailManager();\r\n\t\t\t\t   ~CRailManager();\t\r\n\r\n\t\r\n\tvoid \t\t\tCleanup();\r\n\t\t\t\t\t\t\t\t \r\n\tvoid\t\t\tAddRailsFromNodeArray(Script::CArray * p_node_array);\r\n\tvoid \t\t\tAddRailNode(int node_number, Script::CStruct *p_node_struct);\r\n\tvoid \t\t\tAddedAll();\r\n\t\r\n\tvoid\t\t\tUpdateTransform(Mth::Matrix& transform);\r\n    bool\t\t\tCheckForLadderRail ( const Mth::Vector& pos, float max_horizontal_snap_distance, float max_vertical_snap_distance, bool up, CWalkComponent* p_walk_component, SLadderRailData& rail_data, const CRailNode** pp_rail_node );\r\n\tbool\t\t\tCheckForAirGrabLadderRail ( const Mth::Vector& start_pos, const Mth::Vector& end_pos, CWalkComponent* p_walk_component, SLadderRailData& rail_data, const CRailNode** pp_rail_node );\r\n\t// bool\t\t\tCheckForHopToHangRail ( const Mth::Vector& check_line_start, float check_line_height, const Mth::Vector& facing, float max_forward_reach, float max_backward_reach, CWalkComponent* p_walk_component, SHangRailData& rail_data, const CRailNode** pp_rail_node );\r\n\tbool\t\t\tCheckForHangRail ( const Mth::Vector& start_pos, const Mth::Vector& end_pos, const Mth::Vector& facing, CWalkComponent* p_walk_component, SHangRailData& rail_data, float snap_distance );\r\n\tbool\t\t\tRailNodesAreCoincident ( const CRailNode* p_node_a, const CRailNode* p_node_b );\r\n\tbool\t\t\tCheckForCoincidentRailNode ( const CRailNode* p_node, uint32 ignore_mask, const CRailNode** pp_next_node );\r\n    bool \t\t\tStickToRail(const Mth::Vector &pos1, const Mth::Vector &pos2, Mth::Vector *p_point, Obj::CRailNode **pp_rail_node, const Obj::CRailNode *p_ignore_node = NULL, float min_dot = 1.0f, int side = 0);\r\n\t\r\n\tvoid \t\t\tSetActive( int node, int active, bool wholeRail );\r\n\tbool \t\t\tIsActive( int node );\r\n\tbool\t\t\tIsMoving(){return m_is_transformed;}\r\n\r\n\tvoid \t\t\tMoveNode( int node, Mth::Vector &pos );\r\n\r\n\t\r\n\tvoid\t\t\tDebugRender(Mth::Matrix *p_transform = NULL);\r\n\tvoid\t\t\tRemoveOverlapping();\r\n\t\r\n\tint\t\t\t\tGetNumNodes(){return m_num_nodes;}\r\n\t\r\n\tScript::CArray *\tGetNodeArray(){return mp_node_array;}\r\n\tvoid\t\t\t\tSetNodeArray(Script::CArray *p_nodeArray){mp_node_array = p_nodeArray;}\r\n\r\n\tvoid\t\t\tNewLink(CRailNode *p_from, CRailNode *p_to);\r\n\r\n\tvoid\t\t\tAutoGenerateRails(Script::CStruct* pParams);\r\n\r\n\tCRailNode*\t\tGetRailNodeByNodeNumber( int node_num );\r\n\t\r\n\tint\t\t\t\tGetNodeIndex(const CRailNode *p_node) {return (((int)(p_node)-(int(mp_nodes)))/sizeof(CRailNode));}\r\n\t\r\n// accessor functions for the rail node\r\n// we only access their positions via the rail manager\r\n// as only the rail manager knows the transform of the object to\r\n// which they are attached\r\n// These nodes are \"instances\", in that the same node might be used in\r\n// more than one place\r\n// so these functions only make sense in conjunction with the rail_manager\r\n\tMth::Vector LocalToWorldTransform ( const Mth::Vector& vector ) const;\r\n\tMth::Vector\tGetPos(const CRailNode *p_node) \tconst;\t \r\n    Mth::Matrix GetMatrix(const CRailNode *p_node) \tconst;\r\n\tMth::Vector\tGetBBMin(const CRailNode *p_node)   const;\r\n\tMth::Vector\tGetBBMax(const CRailNode *p_node)   const;\r\n\r\n\r\nprivate:\r\n//\tCRailNode*  \t\tmp_first_node;\t\t\t// was a pointer to a list of nodes\r\n\tMth::Matrix\t\t\tm_transform;\r\n\tCRailNode*  \t\tmp_nodes;\t\t\t\t// pointer to array of nodes\r\n\tCRailLinks*\t\t\tmp_links;\t\t\t\t// pointer to temp array of links\r\n\tScript::CArray *\tmp_node_array;\r\n\tint\t\t\t\t\tm_num_nodes;\r\n\tint\t\t\t\t\tm_current_node;\r\n\tbool\t\t\t\tm_is_transformed;\r\n\t\r\n};\r\n\r\n\r\n\r\n// Global rail type functions that don't need a manager\r\n\r\nbool  \t\t\tRail_ValidInEditor(Mth::Vector Start, Mth::Vector End);\r\n \r\ninline const Mth::Vector&\tCRailNode::GetPos() const\r\n{\r\n\treturn m_pos;\r\n}\r\n\r\ninline const Mth::Quat&\tCRailNode::GetOrientation() const\r\n{\r\n\treturn m_orientation;\r\n}\r\n\r\ninline const Mth::Vector&\tCRailNode::GetBBMin() const\r\n{\r\n\treturn m_BBMin;\r\n}\r\n\r\ninline const Mth::Vector&\tCRailNode::GetBBMax()  const\r\n{\r\n\treturn m_BBMax;\r\n}\r\n\r\n} \r\n\r\n\t\t\t\r\n#endif\t\t\t// #ifndef __OBJECTS_RAIL_H\r\n\t\t\t\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/records.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObjects\t(Record)\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobjects/Record.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t7/11/01\t- Mick\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tRecord Handling, high score tables and suchlike\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <objects/records.h>\r\n#include <gel/scripting/script.h> \r\n#include <gel/scripting/struct.h> \r\n#include <gel/scripting/array.h> \r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Records\r\n{\r\n\t\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\t\tenum {\r\n\t\t\t\t\tvNumHighScores = 5,\r\n\t\t\t\t\tvNumBestCombos = 5,\r\n\t\t\t };\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CInitials::Set(const char *initials) // K: Had to add a const so I could pass it a const got from GetText\r\n{\r\n\t\r\n\r\n\tm_initials[0] = initials[0];\r\n\tm_initials[1] = initials[1];\r\n\tm_initials[2] = initials[2];\r\n\tm_initials[3] = 0;\r\n\r\n}\r\n\r\nchar * CInitials::Get(void)\r\n{\r\n\t\r\n\r\n\treturn m_initials;\t\t\t// note, returning a pointer\r\n\r\n}\r\n\r\n\r\n\r\nCRecord::CRecord()\r\n{\r\n\t\r\n\t\r\n\tmp_initials = new CInitials();\r\n\t\r\n\tSet(\"XXX\",1000,0); \t\t\t// set a default.  Will not hurt anything\r\n\t\r\n}\r\n\r\nCRecord::~CRecord()\r\n{\r\n\t\r\n\t\r\n\tdelete mp_initials;\r\n}\r\n\r\n\r\n// SetInitials will copy in the first three digits of the string   \r\nvoid\tCRecord::SetInitials(char *initials)\r\n{\r\n\t\r\n\tmp_initials->Set(initials);\r\n\r\n}\r\n\r\nvoid\tCRecord::SetValue(int value)\r\n{\r\n\t\r\n\tm_value = value;\r\n\r\n}\r\n\r\nvoid\tCRecord::SetNumber(int number)\r\n{\r\n\t\r\n\tm_number = number;\r\n\r\n}\r\n\r\nvoid\tCRecord::SetNewRecord(bool new_record)\r\n{\r\n\t\r\n\tm_new_record = new_record;\r\n\r\n}\r\n\r\n\r\nvoid\tCRecord::Set(char *initials, int value, int number)\r\n{\r\n\t\r\n\t\r\n\tSetInitials(initials);\r\n\tSetValue(value);\r\n\tSetNumber(number);\r\n}\r\n\r\nvoid\tCRecord::Set(CRecord *pRecord)\r\n{\r\n\t\r\n\t\r\n\tSetInitials(pRecord->GetInitials());\r\n\tSetValue(pRecord->GetValue());\r\n\tSetNumber(pRecord->GetNumber());\r\n}\r\n\r\n\r\nchar *\tCRecord::GetInitials(void)\t// note, returns a pointer to the initials, not the initials itself\r\n{\r\n\t\r\n\treturn mp_initials->Get();\r\n}\r\n\r\nint\t   CRecord::GetValue(void)\r\n{\r\n\t\r\n\t\r\n\treturn m_value;\r\n}\r\n\r\nint\t   CRecord::GetNumber(void)\r\n{\r\n\t\r\n\t\r\n\treturn m_number;\r\n\r\n}\r\n\r\nbool\t   CRecord::GetNewRecord(void)\r\n{\r\n\t\r\n\t\r\n\treturn m_new_record;\r\n\r\n}\r\n\r\n\r\nbool  CRecord::BeatRecord(int value)\t\t\r\n{\r\n\t\r\n\t\r\n\treturn value > GetValue();\r\n}\r\n\r\nbool  CRecord::MaybeNewRecord(int value, int number)\t\t\r\n{\r\n\t\r\n\t\r\n\tif (BeatRecord(value))\r\n\t{\r\n\t\tSetValue(value);\r\n\t\tSetNumber(number);\r\n\t\tSetNewRecord(true);\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSetNewRecord(false);\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n\r\n// if this was flagged as a new record, then set it to these initials\r\nvoid \tCRecord::UpdateInitials(CInitials* pInitials)\r\n{\r\n\tif (GetNewRecord())\r\n\t{\r\n//\t\tSetNewRecord(false);\r\n\t\tmp_initials->Set(pInitials->Get());\r\n\t}\r\n}\r\n\r\n\r\n\r\nvoid CRecord::WriteIntoStructure(Script::CStruct *pIn)\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert(pIn,(\"NULL pIn sent to CRecord::WriteIntoStructure\"));\r\n\r\n\tpIn->AddComponent(Script::GenerateCRC(\"Value\"),ESYMBOLTYPE_INTEGER,m_value);\r\n\tpIn->AddComponent(Script::GenerateCRC(\"Number\"),ESYMBOLTYPE_INTEGER,m_number);\r\n\tDbg_MsgAssert(mp_initials,(\"NULL mp_initials\"));\r\n\tpIn->AddComponent(Script::GenerateCRC(\"Initials\"),ESYMBOLTYPE_STRING,mp_initials->Get());\r\n}\r\n\r\nvoid CRecord::ReadFromStructure(Script::CStruct *pIn)\r\n{\r\n\t\r\n\tDbg_MsgAssert(pIn,(\"NULL pIn sent to CRecord::ReadFromStructure\"));\r\n\t\r\n\tif (!pIn->GetInteger(\"Value\",&m_value))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"Structure is missing Value parameter\"));\r\n\t}\t\r\n\tif (!pIn->GetInteger(\"Number\",&m_number))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"Structure is missing Number parameter\"));\r\n\t}\t\r\n\t\r\n\tconst char *pInitials=\"XXX\";\r\n\tif (!pIn->GetText(\"Initials\",&pInitials))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"Structure is missing Initials parameter\"));\r\n\t}\r\n\tDbg_MsgAssert(mp_initials,(\"NULL mp_initials\"));\r\n\tmp_initials->Set(pInitials);\r\n}\r\n\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// CRecordTable, a table of records, like a high score table\r\nCRecordTable::CRecordTable(int num_records)\r\n{\r\n\t\r\n\t\r\n\tm_numRecords = num_records;\r\n\tmp_records = new CRecord[m_numRecords];\r\n}\r\n\t\t\t\r\nCRecordTable::~CRecordTable()\r\n{\r\n\t\r\n\r\n\tdelete [] mp_records;\r\n\t\r\n}\r\n\r\nCRecord*   CRecordTable::GetRecord(int line)\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert(line < m_numRecords,(\"Bad Line %d in recordtable\",line));\r\n\treturn &mp_records[line];\r\n}\r\n\r\nint\t\t\tCRecordTable::GetSize(void)\r\n{\r\n\t\r\n\t\r\n\treturn m_numRecords;\t\r\n}\r\n\r\n\r\nvoid \tCRecordTable::UpdateInitials(CInitials* pInitials)\r\n{\r\n\tfor (int line= 0; line < m_numRecords; line++)\r\n\t{\r\n\t\tmp_records[line].UpdateInitials(pInitials);\r\n\t}\t\r\n}\r\n\r\n// given a new \"value\", then insert it into the table in the position\r\n// that matches this value, and move other entries down (losing the final entry)\r\n// returns the entery number (fisr tline is 0)\r\n// or -1 if it does not make the cut.\r\nint\t\t\tCRecordTable::MaybeNewEntry(int value, int number)\r\n{\r\n\t\r\n\r\n\tint line;\r\n\t\r\n\tfor (line= 0; line < m_numRecords; line++)\r\n\t{\r\n\t\tmp_records[line].SetNewRecord(false);\r\n\t}\r\n\r\n\tfor (line= 0; line < m_numRecords; line++)\r\n\t{\r\n\t\tif (value > mp_records[line].GetValue())\r\n\t\t{\r\n\t\t\t// alright! this value belongs at \"line\"\r\n\t\t\t// so maove down any that are below this line\r\n\t\t\t// and insert this one\r\n\t\t\tfor (int dest = m_numRecords - 1; dest > line; dest--)\r\n\t\t\t{\r\n\t\t\t\tmp_records[dest].Set(&mp_records[dest-1]);\r\n\t\t\t}\r\n\t\t\tmp_records[line].SetValue(value);\t\r\n\t\t\tmp_records[line].SetNumber(number);\t\r\n\t\t\tmp_records[line].SetInitials(\"XXX\");\t\r\n\t\t\tmp_records[line].SetNewRecord(true);\r\n\t\t\treturn line;\t\t\r\n\t\t}\r\n\t}\r\n\r\n\treturn -1;\r\n}\r\n\r\n\r\n\t\t\t\r\nvoid \t\tCRecordTable::ReadFromStructure(Script::CStruct *pIn)\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert(pIn, (\"NULL pIn sent to CRecordTable::ReadFromStructure\"));\r\n\tScript::CArray *pArray=NULL;\r\n\tpIn->GetArray(\"RecordTable\",&pArray);\r\n\tDbg_MsgAssert(pArray,(\"Structure is missing RecordTable parameter\"));\r\n\t\r\n\tif (m_numRecords!=(int)pArray->GetSize())\r\n\t{\r\n\t\tDbg_Warning(\"m_numRecords mismatch: m_numRecords=%d, but num records in structure=%d\",m_numRecords,pArray->GetSize());\r\n\t\treturn;\r\n\t}\r\n\tDbg_MsgAssert(mp_records,(\"NULL mp_records\"));\r\n\t\t\r\n\tfor (int i=0; i<m_numRecords; ++i)\r\n\t{\r\n\t\tmp_records[i].ReadFromStructure(pArray->GetStructure(i));\r\n\t}\t\r\n}\r\n\t\t\t\r\nvoid \t\tCRecordTable::WriteIntoStructure(Script::CStruct *pIn)\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert(pIn, (\"NULL pIn sent to CRecordTable::WriteIntoStructure\"));\r\n\t\r\n\tScript::CArray *pArray=new Script::CArray;\r\n\tpArray->SetArrayType(m_numRecords,ESYMBOLTYPE_STRUCTURE);\r\n\r\n\tDbg_MsgAssert(mp_records,(\"NULL mp_records\"));\r\n\tfor (int i=0; i<m_numRecords; ++i)\r\n\t{\r\n\t\tScript::CStruct *pStruct=new Script::CStruct;\r\n\t\tmp_records[i].WriteIntoStructure(pStruct);\r\n\t\tpArray->SetStructure(i,pStruct);\r\n\t}\r\n\r\n\tpIn->AddComponent(Script::GenerateCRC(\"RecordTable\"),ESYMBOLTYPE_ARRAY,(int)pArray);\r\n}\r\n\t\t\t\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// CLevelRecords - Records for a particualr level (Skate3 specific)\r\nCLevelRecords::CLevelRecords(/*int numHighScores, int numBestCombos*/)\r\n{\r\n\t\r\n\t\r\n\t\r\n   \tmp_highScores = new CRecordTable(vNumHighScores);\r\n\t\r\n   \tmp_bestCombos = new CRecordTable(vNumBestCombos);\r\n   \tmp_longestCombo = new CRecord;\r\n\tmp_longestCombo->SetValue(0);\r\n   \tmp_longestGrind = new CRecord;\r\n\tmp_longestGrind->SetValue(0);\r\n   \tmp_longestLipTrick = new CRecord;\r\n\tmp_longestLipTrick->SetValue(0);\r\n   \tmp_longestManual = new CRecord;\r\n\tmp_longestManual->SetValue(0);\r\n\t\r\n\t\r\n}\r\n\t\t\t\r\nCLevelRecords::~CLevelRecords()\r\n{\r\n\t\r\n\tdelete mp_longestManual;\r\n\tdelete mp_longestLipTrick;\r\n\tdelete mp_longestGrind;\r\n\tdelete mp_longestCombo;\r\n\tdelete mp_bestCombos;\r\n\tdelete mp_highScores;\r\n}\r\n\r\n\r\nvoid\t\tCLevelRecords::UpdateInitials(CInitials* pInitials)\r\n{\r\n\tmp_longestManual->UpdateInitials(pInitials);\r\n\tmp_longestLipTrick->UpdateInitials(pInitials);\r\n\tmp_longestGrind->UpdateInitials(pInitials);\r\n\tmp_longestCombo->UpdateInitials(pInitials);\r\n\tmp_bestCombos->UpdateInitials(pInitials);\r\n\tmp_highScores->UpdateInitials(pInitials);\r\n\t\r\n}\r\n \r\n\r\n\r\n\t\t\t\r\nvoid\t\tCLevelRecords::ReadFromStructure(Script::CStruct *pIn)\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert(pIn,(\"NULL pIn sent to CLevelRecords::ReadFromStructure\"));\r\n\r\n\tScript::CStruct *pStruct=NULL;\r\n\t\r\n\tpIn->GetStructure(\"HighScores\",&pStruct);\r\n\tDbg_MsgAssert(pStruct,(\"Structure is missing HighScores\"));\r\n   \tDbg_MsgAssert(mp_highScores,(\"NULL mp_highScores\"));\r\n\tmp_highScores->ReadFromStructure(pStruct);\r\n\r\n\tpIn->GetStructure(\"BestCombos\",&pStruct);\r\n\tDbg_MsgAssert(pStruct,(\"Structure is missing BestCombos\"));\r\n   \tDbg_MsgAssert(mp_bestCombos,(\"NULL mp_bestCombos\"));\r\n\tmp_bestCombos->ReadFromStructure(pStruct);\r\n\r\n\tpIn->GetStructure(\"LongestCombo\",&pStruct);\r\n\tDbg_MsgAssert(pStruct,(\"Structure is missing LongestCombo\"));\r\n   \tDbg_MsgAssert(mp_longestCombo,(\"NULL mp_longestCombo\"));\r\n\tmp_longestCombo->ReadFromStructure(pStruct);\r\n\r\n\tpIn->GetStructure(\"LongestGrind\",&pStruct);\r\n\tDbg_MsgAssert(pStruct,(\"Structure is missing LongestGrind\"));\r\n   \tDbg_MsgAssert(mp_longestGrind,(\"NULL mp_longestGrind\"));\r\n\tmp_longestGrind->ReadFromStructure(pStruct);\r\n\r\n\tpIn->GetStructure(\"LongestLipTrick\",&pStruct);\r\n\tDbg_MsgAssert(pStruct,(\"Structure is missing LongestLipTrick\"));\r\n   \tDbg_MsgAssert(mp_longestLipTrick,(\"NULL mp_longestLipTrick\"));\r\n\tmp_longestLipTrick->ReadFromStructure(pStruct);\r\n\r\n\tpIn->GetStructure(\"LongestManual\",&pStruct);\r\n\tDbg_MsgAssert(pStruct,(\"Structure is missing LongestManual\"));\r\n   \tDbg_MsgAssert(mp_longestManual,(\"NULL mp_longestManual\"));\r\n\tmp_longestManual->ReadFromStructure(pStruct);\r\n}\r\n\t\t\t\r\nvoid\t\tCLevelRecords::WriteIntoStructure(Script::CStruct *pIn)\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert(pIn,(\"NULL pIn sent to CLevelRecords::WriteIntoStructure\"));\r\n\t\r\n\r\n\tScript::CStruct *pStruct=new Script::CStruct;\r\n   \tDbg_MsgAssert(mp_highScores,(\"NULL mp_highScores\"));\r\n\tmp_highScores->WriteIntoStructure(pStruct);\r\n\tpIn->AddComponent(Script::GenerateCRC(\"HighScores\"),ESYMBOLTYPE_STRUCTUREPOINTER,(int)pStruct);\r\n\t\r\n\tpStruct=new Script::CStruct;\r\n   \tDbg_MsgAssert(mp_bestCombos,(\"NULL mp_bestCombos\"));\r\n\tmp_bestCombos->WriteIntoStructure(pStruct);\r\n\tpIn->AddComponent(Script::GenerateCRC(\"BestCombos\"),ESYMBOLTYPE_STRUCTUREPOINTER,(int)pStruct);\r\n\t\r\n\tpStruct=new Script::CStruct;\r\n   \tDbg_MsgAssert(mp_longestCombo,(\"NULL mp_longestCombo\"));\r\n\tmp_longestCombo->WriteIntoStructure(pStruct);\r\n\tpIn->AddComponent(Script::GenerateCRC(\"LongestCombo\"),ESYMBOLTYPE_STRUCTUREPOINTER,(int)pStruct);\r\n\t\r\n\tpStruct=new Script::CStruct;\r\n   \tDbg_MsgAssert(mp_longestGrind,(\"NULL mp_longestGrind\"));\r\n\tmp_longestGrind->WriteIntoStructure(pStruct);\r\n\tpIn->AddComponent(Script::GenerateCRC(\"LongestGrind\"),ESYMBOLTYPE_STRUCTUREPOINTER,(int)pStruct);\r\n\t\r\n\tpStruct=new Script::CStruct;\r\n   \tDbg_MsgAssert(mp_longestLipTrick,(\"NULL mp_longestLipTrick\"));\r\n\tmp_longestLipTrick->WriteIntoStructure(pStruct);\r\n\tpIn->AddComponent(Script::GenerateCRC(\"LongestLipTrick\"),ESYMBOLTYPE_STRUCTUREPOINTER,(int)pStruct);\r\n   \t\r\n\tpStruct=new Script::CStruct;\r\n\tDbg_MsgAssert(mp_longestManual,(\"NULL mp_longestManual\"));\r\n\tmp_longestManual->WriteIntoStructure(pStruct);\r\n\tpIn->AddComponent(Script::GenerateCRC(\"LongestManual\"),ESYMBOLTYPE_STRUCTUREPOINTER,(int)pStruct);\r\n}\r\n\t\t\t\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// CGameRecords - Records for the whole game\r\n\r\nCGameRecords::CGameRecords(int numLevels /*, int numHighScores, int numBestCombos*/)\r\n{\r\n\t\r\n\tm_numLevels = numLevels;\r\n\r\n\t// VC++ complains about constructing an array with parameters\r\n\t// so I (Mick) changed it to use and enum for those values,\r\n\t// as they are not likely to change anyway  \r\n\tmp_levelRecords = new CLevelRecords[numLevels]; /*(numHighScores,numBestCombos)*/\r\n\tmp_defaultInitials = new CInitials;\r\n\tmp_defaultInitials->Set(\"ABC\");\r\n}\r\n\t\t\t\r\nCGameRecords::~CGameRecords()\r\n{\r\n\t\r\n\tdelete [] mp_levelRecords;\r\n\tdelete mp_defaultInitials;\r\n\t\r\n}\r\n\r\n\r\nCInitials * CGameRecords::GetDefaultInitials(void)\r\n{\r\n\t\r\n\r\n\treturn mp_defaultInitials;\r\n}\r\n\r\nvoid CGameRecords::SetDefaultInitials(const char *p_initials)\r\n{\r\n\t\r\n\r\n\tmp_defaultInitials->Set( p_initials );\r\n}\r\n\r\n\r\n\r\nCLevelRecords * CGameRecords::GetLevelRecords(int level)\r\n{\r\n\t\r\n\tDbg_MsgAssert(level>=0 && level <= m_numLevels,(\"bad level number %d (max %d)\\n\",level,m_numLevels));\r\n\t\r\n\treturn &mp_levelRecords[level];\r\n}\r\n\r\n\t\t\t\r\nvoid \t\tCGameRecords::ReadFromStructure(Script::CStruct *pIn)\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert(pIn, (\"NULL pIn sent to CGameRecords::ReadFromStructure\"));\t\r\n\r\n\tScript::CArray *pArray=NULL;\r\n\tpIn->GetArray(\"GameRecords\",&pArray);\r\n\tDbg_MsgAssert(pArray,(\"Structure is missing GameRecords parameter\"));\r\n\t\r\n\tif (m_numLevels!=(int)pArray->GetSize())\r\n\t{\r\n\t\tDbg_Warning(\"m_numLevels mismatch: m_numLevels=%d, but num levels in structure=%d\",m_numLevels,pArray->GetSize());\r\n\t\treturn;\r\n\t}\r\n\tDbg_MsgAssert(mp_levelRecords,(\"NULL mp_levelRecords\"));\r\n\t\t\r\n\tfor (int i=0; i<m_numLevels; ++i)\r\n\t{\r\n\t\tmp_levelRecords[i].ReadFromStructure(pArray->GetStructure(i));\r\n\t}\t\r\n\t\r\n\tconst char *pDefaultInitials=\"ABC\";\r\n\tpIn->GetText(\"DefaultInitials\",&pDefaultInitials);\r\n\tDbg_MsgAssert(mp_defaultInitials,(\"NULL mp_defaultInitials\"));\r\n\tmp_defaultInitials->Set(pDefaultInitials);\r\n\t\r\n}\r\n\t\t\t\r\nvoid \t\tCGameRecords::WriteIntoStructure(Script::CStruct *pIn)\r\n{\r\n\t\r\n\tDbg_MsgAssert(pIn, (\"NULL pIn sent to CGameRecords::WriteIntoStructure\"));\t\r\n\t\r\n\tScript::CArray *pArray=new Script::CArray;\r\n\tpArray->SetArrayType(m_numLevels,ESYMBOLTYPE_STRUCTURE);\r\n\r\n\tDbg_MsgAssert(mp_levelRecords,(\"NULL mp_levelRecords\"));\r\n\tfor (int i=0; i<m_numLevels; ++i)\r\n\t{\r\n\t\tScript::CStruct *pStruct=new Script::CStruct;\r\n\t\tmp_levelRecords[i].WriteIntoStructure(pStruct);\r\n\t\tpArray->SetStructure(i,pStruct);\r\n\t}\r\n\r\n\tpIn->AddComponent(Script::GenerateCRC(\"GameRecords\"),ESYMBOLTYPE_ARRAY,(int)pArray);\r\n\tpIn->AddComponent(Script::GenerateCRC(\"DefaultInitials\"),ESYMBOLTYPE_STRING,mp_defaultInitials->Get());\r\n}\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n} // namespace Records\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/records.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObject (OBJ)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobjects/records.h\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t11/7/01 - Mick \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n// Notes:\r\n// as a bit of an experiment, I'm writing the whole structure using \r\n// dynamic containers,\r\n// so each data type is more independent of the others\r\n// but the constructor (and destructor) of the higher level types\r\n// will have to create (and destroy) the dynamic instances of the others\r\n//\r\n// this gives us benefits, namely:\r\n//   No cross includes needed between header files if we split into seperate classes\r\n//   Number of elements in arrays (for high score tables) can be decided at run time.\r\n//\r\n// But has drawback:\r\n//   Uses more memory, as each element is allocated individually\r\n//   might be slower?\r\n//   more code?  Dunno, that's why I'm experimenting....\r\n\r\n\r\n#ifndef __OBJECTS_RECORDS_H\r\n#define __OBJECTS_RECORDS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Records\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  CInitials : public Spt::Class\r\n{\r\n\t\r\n\r\n\tpublic:\r\n\t\tchar *\tGet(void);\r\n\t\tvoid\tSet(const char *initials);\t\t\t\t\r\n\t\r\n\tprivate:\r\n\t\tchar \tm_initials[4];\r\n\t\t\r\n};\r\n\t\t\t\t\r\nclass  CRecord  : public Spt::Class\r\n{\r\n\t\r\n\r\n\r\n\tpublic:\r\n\t\t\t\t\t\t\t\tCRecord();\r\n\t\t\t\t\t\t\t\t~CRecord();\r\n\t\t\r\n\t\t// for memory card loading/saving\r\n\t\tvoid \t\t\t\t\t\tReadFromStructure(Script::CStruct *pIn);\r\n\t\tvoid \t\t\t\t\t\tWriteIntoStructure(Script::CStruct *pIn);\r\n\r\n\t\tvoid\t\t\t\t\t\tSet(char *initials, int value, int number);\r\n\t\tvoid\t\t\t\t\t\tSet(CRecord *pRecord);\r\n\t\t\r\n\t\tvoid\t\t\t\t\t\tSetInitials(char *initials);\r\n\t\tvoid\t\t\t\t\t\tSetValue(int value);\r\n\t\tvoid\t\t\t\t\t\tSetNumber(int number);\r\n\t\tvoid\t\t\t\t\t\tSetNewRecord(bool new_record);\r\n\t\t\r\n\t\tchar \t*\t\t\t\t\tGetInitials(void);\t// note, returns a pointer to the initials, not the initials itself\r\n\t\tint\t\t\t\t\t\t\tGetValue(void);\r\n\t\tint\t\t\t\t\t\t\tGetNumber(void);\r\n\t\tbool\t\t\t\t\t\tGetNewRecord(void);\t\r\n\r\n\t\t// Return true if we beat the record\t\t\r\n\t\tbool\t\t\t\t\t\tBeatRecord(int value);\t\t\r\n\r\n\t\t// set the record and return true if we beat it\r\n\t\tbool\t\t\t\t\t\tMaybeNewRecord(int value, int number);\r\n\t\tvoid \t\t\t\t\t\tUpdateInitials(CInitials* pInitials);\r\n\t\t\r\n\r\n\r\n\tprivate:\r\n\t\tCInitials\t\t*\t\t\tmp_initials;\t\t// Initials\r\n\t\tint\t\t\t\t\t\t\tm_value;\t\t \t// \r\n\t\tint\t\t\t\t\t\t\tm_number;\t\t\t// pro skater number (or could be used for anything)\r\n\t\tbool\t\t\t\t\t\tm_new_record;\t\t// set if it's a new record\r\n};\r\n\r\n\r\nclass  CRecordTable  : public Spt::Class\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\t\t\tCRecordTable(int num_records);\r\n\t\t\t\t\t\t\t\t\t~CRecordTable();\r\n\t\tCRecord*   \t\t\t\t\tGetRecord(int line);\r\n\t\tint\t\t   \t\t\t\t\tGetSize(void);\r\n\t\tint\t\t\t\t\t\t\tMaybeNewEntry(int value, int number);\r\n\t\t// for memory card loading/saving\r\n\t\tvoid \t\t\t\t\t\tReadFromStructure(Script::CStruct *pIn);\r\n\t\tvoid \t\t\t\t\t\tWriteIntoStructure(Script::CStruct *pIn);\r\n\t\tvoid \t\t\t\t\t\tUpdateInitials(CInitials* pInitials);\r\n\r\n\tprivate:\t\t\r\n\t\tint\t\t\t\t\t\t\tm_numRecords;\t\t// Number of records\r\n\t\tCRecord\t\t*\t\t\t\tmp_records;\t\t\t// pointer to records\t\t\t\t\t\r\n};\r\n\r\n\r\n// CLevelRecords - Records for a particualr level\r\n// Include table of high scores, and combo scores\r\n// and individual records for other things like longest grind \r\nclass  CLevelRecords  : public Spt::Class\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\t\t\tCLevelRecords(/*int numHighScores, int numBestCombos*/);\r\n\t\t\t\t\t\t\t\t\t~CLevelRecords();\r\n\t\t\r\n\t\tvoid \t\t\t\t\t\tUpdateInitials(CInitials* pInitials);\r\n\t\t\r\n\t\t// for memory card loading/saving\r\n\t\tvoid \t\t\t\t\t\tReadFromStructure(Script::CStruct *pIn);\r\n\t\tvoid \t\t\t\t\t\tWriteIntoStructure(Script::CStruct *pIn);\r\n\t\r\n\tprivate:\r\n\t\tCRecordTable\t\t*\t\tmp_highScores;\r\n\t\tCRecordTable\t\t*\t\tmp_bestCombos;\r\n\t\tCRecord\t\t\t\t*\t\tmp_longestGrind;\r\n\t\tCRecord\t\t\t\t*\t\tmp_longestManual;\r\n\t\tCRecord\t\t\t\t*\t\tmp_longestLipTrick;\r\n\t\tCRecord\t\t\t\t*\t\tmp_longestCombo;\t\r\n\tpublic:\r\n\t\tCRecordTable\t\t*\t\tGetHighScores()      {return mp_highScores;}        \r\n\t\tCRecordTable\t\t*\t\tGetBestCombos()      {return mp_bestCombos;}        \r\n\t\tCRecord\t\t\t\t*\t\tGetLongestGrind()    {return mp_longestGrind;}      \r\n\t\tCRecord\t\t\t\t*\t\tGetLongestManual()   {return mp_longestManual;}     \r\n\t\tCRecord\t\t\t\t*\t\tGetLongestLipTrick() {return mp_longestLipTrick;}   \r\n\t\tCRecord\t\t\t\t*\t\tGetLongestCombo()\t {return mp_longestCombo;}      \r\n\t\t\t\t\r\n\t\t\t\r\n};\r\n\r\n// Records for the whole game\r\n// stores a single CLevelRecords for each level, in an array\r\n// also stores the default initials used by the game records\r\n\t\t\t\t\t\t\t\t  \r\nclass CGameRecords : public Spt::Class\r\n{\r\n\tpublic:\r\n\t\t\t\t\t\t\t\t\tCGameRecords(int numLevels /*, int numHighScores, int numBestCombos*/);\r\n\t\t\t\t\t\t\t\t\t~CGameRecords();\r\n\t\t\t\t\t\t\t\t\t\r\n\t\tCInitials \t\t\t* \t\tGetDefaultInitials(void);\r\n\t\tvoid\t\t\t\t \t\tSetDefaultInitials(const char *p_initials);\r\n\t\t\r\n\t\tCLevelRecords \t\t*\t \tGetLevelRecords(int level);\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t// for memory card loading/saving\r\n\t\tvoid \t\t\t\t\t\tReadFromStructure(Script::CStruct *pIn);\r\n\t\tvoid \t\t\t\t\t\tWriteIntoStructure(Script::CStruct *pIn);\r\n\t\r\n\tprivate:\r\n\t\tint\t\t\t\t\t\t\tm_numLevels;\r\n\t\tCInitials\t\t\t*\t\tmp_defaultInitials;\r\n\t\tCLevelRecords\t\t*\t\tmp_levelRecords;\r\n};\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Records\r\n\r\n#endif\t// __OBJECTS_RECORDS_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/restart.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t<skate3>\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t<object>\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\trestart.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t00/00/00\t-\tinitials\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t<description>\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Return tru is this node is a restart node\r\nbool IsRestart(Script::CScriptStructure *pNode)\r\n{\r\n\tuint32\tClassChecksum;\r\n\tpNode->GetChecksum(\"Class\",&ClassChecksum);\r\n\tif (ClassChecksum == 0x1806ddf8)\t\t\t\t\t// checksum of \"Restart\"\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nbool IsRestart(int node)\r\n{\r\n\t// get the node array\t\r\n\tScript::CArray *pNodeArray=Script::GetArray(CRCD(0xc472ecc5,\"NodeArray\"));\r\n\tScript::CScriptStructure *pNode=pNodeArray->GetStructure(node);\r\n\treturn\tIsRestart(pNode);\r\n}\r\n\r\nint FindQualifyingNodes( uint32 type, uint32 *node_buffer, int first = -1 )\r\n{\r\n\tint num_qualifiers;\r\n\tint i;\r\n\r\n\tnum_qualifiers = 0;\r\n\ti = 0;\r\n\t\r\n\t// get the node array\t\r\n\tScript::CArray *pNodeArray=Script::GetArray(CRCD(0xc472ecc5,\"NodeArray\"));\r\n\r\n\t// if there is no node array, then there are no restart points\r\n\tif (!pNodeArray)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\t\t\t\t\t\t \r\n\tif( first >= 0 )\r\n\t{\r\n\t\ti = first + 1;\r\n\t}\r\n\t// scan through it from the start point\r\n\twhile( i < (int)pNodeArray->GetSize() )\r\n\t{\r\n\t\tScript::CScriptStructure *pNode=pNodeArray->GetStructure(i);\r\n\t\tif (IsRestart(pNode))\t\t\t\t\t// checksum of \"Restart\"\r\n\t\t{   \r\n\t\t\tScript::CArray *pArray;\r\n\t\t\tint j;\r\n\r\n\t\t\t// The caller wants all restart points\r\n\t\t\tif (type == 0)\r\n\t\t\t{\r\n\t\t\t\tnode_buffer[num_qualifiers++] = i;\r\n\t\t\t\ti++;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// Loop through supported game types, gathering matches\r\n\t\t\tif (pNode->GetArray(\"restart_types\", &pArray))\r\n\t\t\t{\r\n\t\t\t\tfor (j = 0; j < (int)pArray->GetSize(); j++)\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 game_type;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\tgame_type = pArray->GetNameChecksum( j );\r\n\t\t\t\t\tif( game_type == type )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnode_buffer[num_qualifiers++] = i;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\t\t\r\n\t\ti++;\t\r\n\t}\t\r\n\r\n\treturn num_qualifiers;\r\n}\r\n\r\n\r\n// given the checksum of a type of restart\r\n// then get the node index  \r\n// if \"first\" is specified then resturn the first on after this\t\t\t\t\t\t\t\t  \r\n// if \"type\"  is zero, then it will be ignored, and will return restarts of any type.\r\n// returns -1 if no restarts matching \"type\" are found.\r\nint GetRestartNode(uint32 type, int index, int first = -1)\r\n{\r\n\t// decide where to start, based on the \"first\" parameter\r\n\tint num_qualifiers;\r\n\tuint32 qualifying_nodes[256];\r\n\t\r\n\tnum_qualifiers = FindQualifyingNodes( type, qualifying_nodes, first );\r\n\tif( num_qualifiers == 0 )\r\n\t{\r\n\t\treturn -1;\r\n\t}\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tif (num_qualifiers > 1 && (type == CRCD(0xbae0e4da,\"multiplayer\") || type == CRCD(0x9d65d0e7,\"horse\")))\r\n\t{\r\n\t\t// Scan through the nodes we've found, and check that there are not any\r\n\t\t// that are too close to each other (< 6 feet)\r\n\t\tbool ok = true;\r\n\t\tfor (int i=0;i<num_qualifiers-1;i++)\r\n\t\t{\r\n\t\t\tfor (int j=i+1;j<num_qualifiers;j++)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(qualifying_nodes[i] != qualifying_nodes[j],(\"Restart node %d qualifies more than once!\\n\",qualifying_nodes[i]));\r\n\t\t\t\tMth::Vector i_pos, j_pos;\r\n\t\t\t\tSkateScript::GetPosition( qualifying_nodes[i], &i_pos );\r\n\t\t\t\tSkateScript::GetPosition( qualifying_nodes[j], &j_pos );\r\n\t\t\t\tfloat dist = (i_pos-j_pos).Length();\r\n\t\t\t\tif (dist < 12.0f*6.0f)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (ok) printf (\"\\n\\n\\n\");\r\n\t\t\t\t\tok = false;\r\n\t\t\t\t\tuint32\ti_name_checksum;\r\n\t\t\t\t\tSkateScript::GetNode(qualifying_nodes[i])->GetChecksum(\"Name\",&i_name_checksum);\r\n\t\t\t\t\tuint32\tj_name_checksum;\r\n\t\t\t\t\tSkateScript::GetNode(qualifying_nodes[j])->GetChecksum(\"Name\",&j_name_checksum);\r\n\t\t\t\t\tprintf (\"%2.2f\"\" %s to %s \\n\",\r\n\t\t\t\t\t dist,\r\n\t\t\t\t\t Script::FindChecksumName(i_name_checksum),\r\n\t\t\t\t\t Script::FindChecksumName(j_name_checksum)\r\n\t\t\t\t\t );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!ok) printf (\"\\n\\n\\n\");\r\n\t\tDbg_MsgAssert(ok, (\"Restart nodes of type %s too close, see above for list\\n\",Script::FindChecksumName(type)));\r\n\t}\r\n\t#endif\t\r\n\t\r\n\t//Ryan(\"index is %d, num_qualifiers %d\\n\", index, num_qualifiers);\r\n\t\r\n\t// If we've found matches, return the \r\n\tif( num_qualifiers > 0 )\r\n\t{\r\n\t\tif( index >= num_qualifiers )\r\n\t\t{\r\n\t\t\treturn qualifying_nodes[index % num_qualifiers];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn qualifying_nodes[index];\r\n\t\t}\r\n\t}\r\n\treturn -1;\r\n}\r\n\t\t\t\t\r\n\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/restart.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tskate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tobj\t\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\ttmeplate.h  \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t00/00/00\t-\tmick\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __SK_OBJECTS_RESTART_H\r\n#define __SK_OBJECTS_RESTART_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Obj\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool IsRestart(Script::CScriptStructure pNode);\r\nbool IsRestart(int node);\r\nint GetRestartNode(uint32 type, int index, int first = -1);\r\nint FindQualifyingNodes( uint32 type, uint32 *node_buffer, int first = -1 );\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __DIR_SUBDIR_FILE_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/skater.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t    \t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObjects (OBJ) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tskater.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/25/00\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSkater\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n****************************************************************************/\r\n  \t\t\t\t\t\t\t\t \t\t\t\t\t\t\t\t\t  \r\n// start autoduck documentation\r\n// @DOC skater        \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n// @module skater | None\r\n// @subindex Scripting Database\r\n// @index script | skater\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n#include <core/math.h>\r\n#include <core/math/slerp.h>\r\n\r\n#include <sys/timer.h>\r\n#include <sys/sioman.h>\r\n\r\n#include <gel/objtrack.h>\r\n#include <gel/assman/assman.h>\r\n#include <gel/collision/collcache.h>\r\n#include <gel/inpman.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/environment/terrain.h>\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/lockobjcomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/motioncomponent.h>\r\n#include <gel/components/shadowcomponent.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n#include <gel/components/specialitemcomponent.h>\r\n#include <gel/components/suspendcomponent.h>\r\n#include <gel/components/trickcomponent.h>\r\n#include <gel/components/nodearraycomponent.h>\r\n#include <gel/components/railmanagercomponent.h>\r\n#include <gel/components/skitchcomponent.h>\r\n#include <gel/components/cameracomponent.h>\r\n#include <gel/components/skatercameracomponent.h>\r\n#include <gel/components/vibrationcomponent.h>\r\n#include <gel/components/proximtriggercomponent.h>\r\n#include <gel/components/triggercomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/collisioncomponent.h>\r\n#include <gel/components/walkcomponent.h>\r\n#include <gel/components/movablecontactcomponent.h>\r\n#include <gel/components/ribboncomponent.h>\r\n#include <gel/components/statsmanagercomponent.h>\r\n#include <gel/components/walkcameracomponent.h>\r\n#ifdef TESTING_GUNSLINGER\r\n#include <gel/components/ridercomponent.h>\r\n#include <gel/components/weaponcomponent.h>\r\n#endif\r\n\r\n\r\n#include <gfx/camera.h>\r\n#include <gfx/shadow.h>\r\n#include <gfx/debuggfx.h>\t\t\t\t// for debug lines\r\n#include <gfx/gfxutils.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/nxlight.h>\r\n#include <gfx/nxlightman.h>\r\n#include <gfx/2D/ScreenElemMan.h>\r\n#include <gfx/2D/SpriteElement.h>\r\n#include <gfx/2D/ScreenElement2.h>\r\n#include <gfx/skeleton.h>\r\n#include <gfx/nx.h>\t\t\t\t\t\t// for sGetMovableObjects\r\n#include <gfx/NxMiscFX.h>\r\n\r\n                                   \r\n#include <sk/modules/skate/skate.h> // for SKATE_TYPE_*\r\n#include <sk/modules/FrontEnd/FrontEnd.h>\r\n#include <sk/modules/skate/competition.h>\t  \t// for CCompetition\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/modules/skate/goalmanager.h>   // for special goal\r\n#include <sk/modules/skate/CreateATrick.h>\r\n\r\n#include <sk/ParkEditor2/ParkEd.h>\r\n\r\n#include <sk/objects/crown.h>\r\n#include <sk/objects/moviecam.h>\r\n#include <sk/objects/proxim.h>\r\n#include <sk/objects/rail.h>\r\n#include <sk/objects/objecthook.h>\r\n#include <sk/objects/restart.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/objects/playerprofilemanager.h>\r\n#include <sk/components/skaterstancepanelcomponent.h>\r\n#include <sk/components/skaterloopingsoundcomponent.h>\r\n#include <sk/components/skatersoundcomponent.h>\r\n#include <sk/components/skatergapcomponent.h>\r\n#include <sk/components/skaterrotatecomponent.h>\r\n#include <sk/components/skaterphysicscontrolcomponent.h>\r\n#include <sk/components/skaterlocalnetlogiccomponent.h>\r\n#include <sk/components/skaternonlocalnetlogiccomponent.h>\r\n#include <sk/components/skaterscorecomponent.h>\r\n#include <sk/components/skatermatrixqueriescomponent.h>\r\n#include <sk/components/skaterfloatingnamecomponent.h>\r\n#include <sk/components/skaterstatehistorycomponent.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/components/skateradjustphysicscomponent.h>\r\n#include <sk/components/skaterfinalizephysicscomponent.h>\r\n#include <sk/components/skatercleanupstatecomponent.h>\r\n#include <sk/components/skaterendruncomponent.h>\r\n#include <sk/components/skaterbalancetrickcomponent.h>\r\n#include <sk/components/skaterflipandrotatecomponent.h>\r\n#include <sk/components/skaterstatecomponent.h>\r\n#include <sk/components/skaterruntimercomponent.h>\r\n\r\n#include <sk/engine/feeler.h>\r\n#include <sk/engine/contact.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#include <sk/scripting/cfuncs.h>\r\n\r\n#include <sys/profiler.h>\r\n#include <sys/replay/replay.h>\r\n\r\n#include <core/math/geometry.h>\r\n\r\n#include <gel/music/music.h>\r\n\r\n#include <gel/collision/collision.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\n#ifdef __PLAT_NGC__\r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\r\n#define\tFLAGEXCEPTION(X)\tSelfEvent(X)\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////\r\n\r\ninline void\tdodgy_test()\r\n{\r\n//\t\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n//\t\tif (skate_mod->GetSkater(0))\r\n//\t\t{\r\n//\t\t\tskate_mod->GetSkater(0)->DodgyTest();\r\n//\t\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern uint64\tGfx_LastVBlank;\r\n\r\nnamespace Gfx\r\n{\r\n\tvoid DebuggeryLines_CleanUp( void );\t\t// just for debugging\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// All the CSkater code sits in the Obj namespace, along with other objects,\r\n// like peds and cars\r\nnamespace Obj\r\n{\r\n\r\nbool DebugSkaterScripts=false;\t\t\t// Set to true to dump out a lot of info about the skater's script\r\n\t\t\t\t\t\t\t\t\t\t// generally you would set it with the script command SkaterDebugOn/Off\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// Physics patching, so physics vars can come from different structs\r\n// or globals, in a nice relaxed manner\r\n\r\nScript::CStruct * get_physics_struct()\r\n{\r\n\t// if (Script::GetInteger(CRCD(0x9e86d1c1,\"use_bike_physics\")))\r\n\t// {\r\n\t\t// return Script::GetStructure(CRCD(0x9d728121,\"bike_physics\"));\r\n\t// }\r\n\t// else if (Script::GetInteger(CRCD(0x9ae06a83,\"use_walk_physics\")))\r\n\t// {\r\n\t\t// return Script::GetStructure(CRCD(0x8cbc89dd,\"skater_physics\"));\r\n\t// }\r\n\t// else\r\n\t// {\r\n\t\treturn Script::GetStructure(CRCD(0x8cbc89dd,\"skater_physics\"));\r\n\t// }\r\n}\r\n\t\t\t  \r\nfloat GetPhysicsFloat(uint32 id, Script::EAssertType assert)\r\n{\r\n\r\n\tScript::CStruct\t*p_struct = get_physics_struct();\t\r\n\tfloat x;\r\n\tif (p_struct->GetFloat(id,&x))\r\n\t{\r\n\t\treturn x;\r\n\t}\r\n\r\n\treturn Script::GetFloat(id,assert);\r\n}\r\n\r\nint GetPhysicsInt(uint32 id, Script::EAssertType assert)\r\n{\r\n\t\r\n\tScript::CStruct\t*p_struct = get_physics_struct();\t\r\n\tint x;\r\n\tif (p_struct->GetInteger(id,&x))\r\n\t{\r\n\t\treturn x;\r\n\t}\r\n\r\n\treturn Script::GetInteger(id,assert);\r\n}\r\n\r\n// End of physics patching\r\n/////////////////////////////////////////////////////////////////////////////\r\n\r\n\r\n// This Test generally not called\r\n// can stick code in here that will be called from dodgy_test\r\n// whcih gets called from every printf\r\n// generaly you'd have printfs enabled via something like DEBUG_POSITION\r\nvoid \tCSkater::DodgyTest()\r\n{\r\n\t\tCFeeler feeler;\r\n\t\tfeeler.SetEnd(m_pos);\r\n\t\tfeeler.SetStart(m_pos + Mth::Vector(0.0f,100.0f,0.0f,0.0f));\r\n\t\tif (feeler.GetCollision())\r\n\t\t{\r\n#\tif !defined( __PLAT_NGC__ ) || ( defined( __PLAT_NGC__ ) && !defined( __NOPT_FINAL__ ) )\r\n\t\t\tfloat above = feeler.GetPoint()[Y] - m_pos[Y];\r\n\t\t\tprintf(\" collision %.2f above me, normal = (%.2f,%.2f,%.2f)\\n\",above,feeler.GetNormal()[X],feeler.GetNormal()[Y],feeler.GetNormal()[Z]);\r\n#endif\t\t// __NOPT_FINAL__\r\n\t\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// K: This is a factored out code snippet that is used quite a bit.\r\n// It get's a pointer to this skater's score object and asserts if it's NULL.\r\nMdl::Score *CSkater::GetScoreObject()\r\n{\r\n\tDbg_Assert(mp_skater_score_component);\r\n\treturn mp_skater_score_component->GetScore();\r\n}\t\r\n\r\n// Just move the skater to the correct position and orientation for\r\n// this restart point\r\n// used to set intial position of other skaters on clients\r\nvoid CSkater::MoveToRestart(int node)\r\n{\r\n\tDbg_Assert(mp_skater_core_physics_component);\r\n\t\r\n\tm_matrix.Ident();\r\n\tScript::CStruct *pNode = NULL;\r\n\tif (node >= 0)\r\n\t{\r\n\t\tScript::CArray *pNodeArray=Script::GetArray(CRCD(0xc472ecc5,\"NodeArray\"));\r\n\t\tpNode=pNodeArray->GetStructure(node);\r\n\t\tDbg_MsgAssert(pNode,( \"null restart\"));\r\n\t\tSkateScript::GetPosition( node, &m_pos );\r\n\t\t#ifdef\tCHEAT_RUBBER\r\n\t\tm_rubber_pos = m_pos;\r\n\t\tm_rubber_vel.Set();\r\n\t\t#endif\r\n\t\t\r\n\t\tm_old_pos = m_pos;\r\n\t\tmp_skater_core_physics_component->m_safe_pos = m_pos;\r\n\t\t\r\n\t\tSetTeleported();\r\n\r\n\t\tMth::Vector angles;\r\n\t\tSkateScript::GetAngles(pNode, &angles);\r\n\t\tm_matrix.SetFromAngles(angles);\r\n\t\t\r\n\t\tmp_skater_core_physics_component->ResetLerpingMatrix();\r\n\t\tmp_skater_core_physics_component->m_display_normal = mp_skater_core_physics_component->m_last_display_normal = mp_skater_core_physics_component->m_current_normal = m_matrix[Y];\r\n\t\t\r\n\t\t#ifdef\t\tDEBUG_DISPLAY_MATRIX\r\n\t\tdodgy_test(); printf(\"%d: Setting display_matrix[Y][Y] to %f, [X][X] to %f\\n\",__LINE__,mp_skater_core_physics_component->m_lerping_display_matrix[Y][Y],mp_skater_core_physics_component->m_lerping_display_matrix[X][X]);\r\n\t\t#endif\r\n\t\r\n\t\t// set the shadow to stick to his feet, assuming we are on the ground\r\n\t\t// Note: These are used by the simple shadow, not the detailed one.\r\n\t\tDbg_Assert(mp_shadow_component)\r\n\t\tmp_shadow_component->SetShadowPos( m_pos );\r\n\t\tmp_shadow_component->SetShadowNormal( m_matrix[Y] );\r\n\t\r\n\t\t// update for the camera\r\n\t\tm_display_matrix = mp_skater_core_physics_component->m_lerping_display_matrix;\r\n\t}\r\n}\r\n\r\nvoid CSkater::SkipToRestart(int node, bool walk)\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n#\tifdef\tDEBUG_TRIGGERS\t\t\t\r\n\tdodgy_test(); printf(\"SkipToRestart(%d)\\n\",node);\r\n#\tendif\r\n\r\n    GetSkaterPhysicsControlComponent()->NotifyReset();\r\n\t\r\n\tif( m_local_client )\r\n\t{\r\n\t\t// The Skater might have been in the middle of a move that disabled his input, so re-enable it\r\n\t\t// and also enable the camera control\r\n\t\tmp_input_component->EnableInput();\r\n\t\t// Also player should ot be paused\r\n\t\tUnPause();\r\n\r\n        if (mp_stats_manager_component)\r\n        {\r\n            mp_stats_manager_component->m_restarted_this_frame = true;\r\n        }\r\n\r\n        /*\t\t\r\n        // If the player had locked the camera in lookaround, clear it back.\r\n\t\tif ( mp_skaterCamera )\r\n\t\t{\r\n\t\t\tmp_skaterCamera->ClearLookaroundLock();\r\n\t\t}\r\n\t\t*/\r\n\t\t//printf (\"STUBBED: Skater.cpp line %d - not clearing lookaroundlock\\n\",__LINE__);\r\n\r\n\t\t// Reset the skater back to a collidable state\r\n\t\tif( gamenet_man->InNetGame())\r\n\t\t{   \r\n\t\t\tCFuncs::ScriptNotifyBailDone( NULL, NULL );\r\n\t\t\tmp_skater_core_physics_component->SetFlagFalse( IS_BAILING );\r\n\t\t}\r\n\t}\r\n\r\n    if (mp_vibration_component)\r\n\t{\r\n\t\tmp_vibration_component->Reset();\r\n\t}\r\n\r\n\tif (node != -1)\r\n\t{\r\n\t\tMoveToRestart(node);\r\n\t}\r\n\t       \r\n\tResetPhysics(walk);\r\n\r\n\tdodgy_test(); //printf(\"Setting animation flipped to %d in SkipToRestart\\n\",mp_skater_core_physics_component->GetFlag(FLIPPED));\r\n\t\r\n\tif (IsLocalClient())\r\n\t{\r\n\t\t// reset any flippedness of animation\r\n\t\tGetSkaterFlipAndRotateComponent()->ApplyFlipState();\r\n\t}\r\n\r\n\t// Only local skaters should run the script\r\n\tif( m_local_client )\r\n\t{\r\n\t\tif (!m_viewing_mode)\r\n\t\t{\r\n\t\t\tUpdateCameras( true );\r\n\t\t\t\r\n\t\t\tObj::CCompositeObject *p_obj = GetCamera();\r\n\t\t\tif (p_obj)\r\n\t\t\t{\r\n\t\t\t\tp_obj->Update();\t // Not the best way of doing it...\r\n\t\t\t}\r\n\r\n\t\t\t\r\n\t\t}\r\n\t\tif (node != -1)\r\n\t\t{\r\n\t\t\tScript::CStruct *pNode = NULL;\t\r\n\t\t\tScript::CArray *pNodeArray=Script::GetArray(CRCD(0xc472ecc5,\"NodeArray\"));\r\n\t\t\tpNode=pNodeArray->GetStructure(node);\r\n\t\t\t// Now run any TriggerScript associated with this node\r\n\t\t\tuint32 script;\r\n\t\t\tif (pNode->GetChecksum(0x2ca8a299,&script))\r\n\t\t\t{\r\n\t#\t\t\tifdef\tDEBUG_TRIGGERS\t\t\t\r\n\t\t\t\tdodgy_test(); printf(\"%d: Restart Node Script triggered, script name %s, node %d\\n\",(int)Tmr::GetVblanks(),(char*)Script::FindChecksumName(script),node);\r\n\t#\t\t\tendif\t\t\t\r\n\t\t\t\tSpawnAndRunScript(script,node);\r\n\t\t\t}\r\n\t\t}\t  \t\r\n\t}\r\n\t\t\t\r\n\tSetTeleported();\r\n\r\n\tif(\t( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0x6c5ff266,\"netctf\") ) ||\r\n\t\t( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0x6ef8fda0,\"netking\") ) ||\r\n\t\t( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0x5d32129c,\"king\") ))\r\n\t{\r\n\t\tNet::Client* client;\r\n\t\tGameNet::PlayerInfo* player;\r\n\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\tclient = gamenet_man->GetClient( m_skater_number );\r\n\t\tDbg_Assert( client );\r\n\t\tplayer = gamenet_man->GetPlayerByObjectID( GetID());\r\n\t\tDbg_Assert( player );\r\n\t\tplayer->MarkAsRestarting();\r\n\r\n\t\tmsg_desc.m_Id = GameNet::MSG_ID_MOVED_TO_RESTART;\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t}\r\n\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////\r\n// START of \"Stat\" code\r\n\r\n\r\nfloat\tCSkater::GetStat(EStat stat)\r\n{\r\n\t\r\n\r\n\tfloat value;\t\t\t   \r\n\r\n\tfloat\toverride;\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\toverride = skate_mod->GetStatOverride();\r\n\t\r\n\tif (override != 0.0f)\r\n\t{\r\n\t\tvalue = override;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (m_stat[stat] == -1.0f)\r\n\t\t{\r\n\t\t\tvalue =  GetPhysicsFloat(CRCD(0x6357d57c,\"Skater_Default_Stats\"));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tvalue =  m_stat[stat];\r\n\t\t}\r\n\t}\r\n\r\n\t// In a network game, always set stats to 10\t\r\n//\tif( GameNet::Manager::Instance()->InNetGame() )\r\n//\t{\r\n//\t\tvalue = 10.0f;\r\n//\t}\r\n\r\n\tif( GameNet::Manager::Instance()->InNetGame())\r\n\t{\r\n\t\tGameNet::PlayerInfo* player;\r\n\r\n\t\tplayer = GameNet::Manager::Instance()->GetPlayerByObjectID( GetID());\r\n\t\tif( player )\r\n\t\t{\r\n\t\t\tif( player->IsKing())\r\n\t\t\t{\r\n\t\t\t\tvalue = 1.0f;\r\n\t\t\t}\r\n\t\t\telse if( player->HasCTFFlag())\r\n\t\t\t{\r\n\t\t\t\tvalue = 6.0f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tvalue = 10.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tvalue = 10.0f;\r\n\t\t}\r\n\t}\r\n\telse if( CFuncs::ScriptInSplitScreenGame( NULL, NULL ))\r\n\t{\r\n\t\tGameNet::PlayerInfo* player;\r\n\r\n\t\tplayer = GameNet::Manager::Instance()->GetPlayerByObjectID( GetID());\r\n\t\tif( player )\r\n\t\t{\r\n\t\t\tif( player->IsKing())\r\n\t\t\t{\r\n\t\t\t\tvalue = 1.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif( GameNet::Manager::Instance()->InNetGame())\r\n\t{\r\n\t\tGameNet::PlayerInfo* player;\r\n\r\n\t\tplayer = GameNet::Manager::Instance()->GetPlayerByObjectID( GetID());\r\n\t\tif( player )\r\n\t\t{\r\n\t\t\tif( player->IsKing())\r\n\t\t\t{\r\n\t\t\t\tvalue = 1.0f;\r\n\t\t\t}\r\n\t\t\telse if( player->HasCTFFlag())\r\n\t\t\t{\r\n\t\t\t\tvalue = 6.0f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tvalue = 10.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tvalue = 10.0f;\r\n\t\t}\r\n\t}\r\n\telse if( CFuncs::ScriptInSplitScreenGame( NULL, NULL ))\r\n\t{\r\n\t\tGameNet::PlayerInfo* player;\r\n\r\n\t\tplayer = GameNet::Manager::Instance()->GetPlayerByObjectID( GetID());\r\n\t\tif( player )\r\n\t\t{\r\n\t\t\tif( player->IsKing())\r\n\t\t\t{\r\n\t\t\t\tvalue = 1.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (CHEAT_STATS_13)\r\n\t{\r\n\t\tvalue = 15.0f;\r\n\t}\r\n\r\n\tDbg_Assert(mp_skater_score_component);\r\n\tif (mp_skater_score_component->GetScore()->GetSpecialState())\r\n\t{\r\n\t\tvalue += 3.0f;\r\n\t}\r\n\r\n\treturn value;\r\n\t\r\n}\r\n\r\n\r\nvoid\tCSkater::SetStat(EStat stat, float value)\r\n{\r\n\r\n\t// factor in the handicap if any...\r\n\tif ( CFuncs::ScriptInSplitScreenGame( NULL, NULL ) )\r\n\t{\r\n\t\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\tvalue += skate_mod->GetHandicap( m_id );\r\n\r\n\t\t// clamp it to the min, max values\r\n\t\tif ( value > 10.0f ) value = 10.0f;\r\n\t\tif ( value < 0.0f ) value = 0.0f;\r\n\t}\r\n\t\r\n\tm_stat[stat] = value;\r\n}\r\n\r\n\r\n// Gets a stat value given a pointer to the stat structure.\r\nfloat\tCSkater::GetScriptedStat(Script::CStruct *pSS)\r\n{\r\n\t\r\n\tScript::CPair range;\r\n\tScript::CPair switch_range;\r\n\tint stat;\r\n\tfloat limit;\r\n\r\n    Dbg_MsgAssert(pSS,(\"NULL pSS sent to GetScriptedStat\"));\r\n\t\r\n\tif (!pSS->GetPair(NONAME,&range))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"range pair not found in structure.\"));\t\t\r\n\t}\r\n\r\n\tfloat stat_value;\r\n\tif (!pSS->GetInteger(NONAME,&stat))\r\n\t{\r\n\t\tstat_value = 10.0f;\t   \t\t// default to 10 if no stats\r\n\t}\r\n\telse\r\n\t{\r\n\t\tstat_value = GetStat((CSkater::EStat)stat);\r\n\t}\r\n\t\r\n\tfloat lower = range.mX;\r\n\tfloat upper = range.mY;  \r\n\tfloat len = upper - lower;\r\n\tfloat value = lower + (len * stat_value / 10);\r\n\r\n\r\n\tif (mp_skater_core_physics_component->IsSwitched())\t\t// if skating in switch stance\r\n\t{\r\n\t\tif (pSS->GetPair(0x9016b4e7,&switch_range))\t   \t\t// switch\r\n\t\t{\r\n\t\t\tfloat\tswitch_stat = GetStat(STATS_SWITCH);   \t// returns 0..13\r\n\t\t\tfloat \tmult = switch_range.mX + (switch_range.mY - switch_range.mX) * switch_stat/10.0f;\r\n\t\t\t\r\n\t\t\tif (mult <0.0f) mult = 0.0f;\r\n\t\t\tif (mult >1.0f) mult = 1.0f;\t\t// this ensures we are never Better in switch\r\n\r\n\t\t\tvalue *= mult;\t\t\t\r\n\t\t\t\r\n\t\t}\r\n\t}\r\n\t\r\n\tGame::GOAL_MANAGER_DIFFICULTY_LEVEL level = Mdl::Skate::Instance()->GetGoalManager()->GetDifficultyLevel();\r\n\tif (level != Game::GOAL_MANAGER_DIFFICULTY_MEDIUM)\r\n\t{\r\n\t\tScript::CPair diff;\t\r\n\t\tif (pSS->GetPair(CRCD(0xba8fb854,\"diff\"),&diff))\r\n\t\t{\r\n\t\t\tif (level == Game::GOAL_MANAGER_DIFFICULTY_LOW)\r\n\t\t\t{\r\n\t\t\t\tvalue *= diff.mX;\r\n\t\t\t}\r\n\t\t\telse if (level == Game::GOAL_MANAGER_DIFFICULTY_HIGH)\r\n\t\t\t{\r\n\t\t\t\tvalue *= diff.mY;\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n\t\r\n\t// if there is a limit, then clamp the value to it\r\n\t// accounting for the direction of the range, this may be a high limit\r\n\t// or a low limit, but applies to the value for higher values of stat_value.\r\n\t// so if lower > upper, then it's a low limit\r\n\tif (pSS->GetFloat(0x8069179f/*\"limit\"*/,&limit))\r\n\t{\r\n\t\tif (lower < upper)\r\n\t\t{\r\n\t\t\tif (value > limit)\r\n\t\t\t{\r\n\t\t\t\tvalue = limit;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (value < limit)\r\n\t\t\t{\r\n\t\t\t\tvalue = limit;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// there is no limit, so we do nothing.\r\n\t}\r\n\t\r\n\treturn value;\r\n}\r\n\r\n// Gets a stat value given the name of the stat, where the stat is defined as a global structure.\r\nfloat\tCSkater::GetScriptedStat(const uint32 checksum)\r\n{\r\n\t\r\n   // Get the structure that contains the range, stat and limit\r\n\tScript::CStruct *pSS = NULL; \r\n\tScript::CStruct *pPhysics; \r\n\t// Try to get it from the skater/biker physics structure first\r\n\tpPhysics = get_physics_struct();\r\n\tif (! pPhysics->GetStructure(checksum,&pSS))\r\n\t{\r\n\t\tpSS= Script::GetStructure(checksum);\r\n\t}\r\n\t\r\n\tDbg_MsgAssert(pSS, (\"State %s not found\", Script::FindChecksumName(checksum)));\r\n\r\n\t// These asserts are also in the other GetScriptedStat,\r\n\t// but included here too so that it can print the name of the structure.\r\n\t#ifdef __NOPT_ASSERT__\r\n\tScript::CPair range;\r\n\tif (!pSS->GetPair(NONAME,&range))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"range pair not found in %s.\",Script::FindChecksumName(checksum)));\t\t\r\n\t}\r\n\r\n\tint stat;\r\n\tif (!pSS->GetInteger(NONAME,&stat))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"stat not found in %s.\",Script::FindChecksumName(checksum)));\t\t\r\n\t}\r\n\t#endif\r\n\t\t\r\n\treturn GetScriptedStat(pSS);\r\n}\r\n\r\n// Gets a stat value given the name of the stat, where the stat is defined as a global structure.\r\n\r\n\r\n// Gets a stat value given the name of the stat within a structure pSetOfStats.\r\n// This is used in manual.cpp.\r\n// Different sets of control & wobble stats are stored in structures in physics.q\r\nfloat CSkater::GetScriptedStat(uint32 Checksum, Script::CStruct *pSetOfStats)\r\n{\r\n\tDbg_MsgAssert(pSetOfStats,(\"NULL pSetOfStats.\"));\r\n\tScript::CStruct *pSS=NULL;\r\n\t\tpSetOfStats->GetStructure(Checksum,&pSS);\r\n\tDbg_MsgAssert(pSS,(\"Could not find stat called %s in pSetOfStats\",Script::FindChecksumName(Checksum)));\r\n\t\r\n\treturn GetScriptedStat(pSS);\r\n}\r\n\r\n\r\n// END of \"Stat\" code\r\n/////////////////////////////////////////////////////////////////////////////\r\n\r\nvoid CSkater::MoveToRandomRestart( void )\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tint node, retry;\r\n\t\r\n\t\r\n\r\n\t// Try to go to a different restart point than last time.  But still, limit\r\n\t// the number of retries just in case there is only one restart node in the level\r\n\tretry = 0;\r\n\tdo\r\n\t{\r\n\t\tnode = skate_mod->find_restart_node( Mth::Rnd( Mdl::Skate::vMAX_SKATERS ));\r\n\t\tretry++;\r\n\t} while(( node == m_last_restart_node ) && ( retry < 20 ));\r\n\r\n\tm_last_restart_node = node;\r\n\r\n\tDbg_Printf( \"In MoveToRandomRestart: Node %d\\n\", node );\r\n    \r\n\tif (node != -1)\r\n\t{\r\n\t\tSkipToRestart(node);   \t\t\t\t\t   \r\n\t}\r\n}\r\n\r\nvoid CSkater::UpdateCameras( bool instantly )\r\n{\r\n//\tprintf (\"%d: SUTUBBBEDDDDDDDDDDDDDDDDDDDDDDDD  UpdateCameras(%d)\\n\",__LINE__,instantly);\t\r\n\tif (instantly)\r\n\t{\r\n\t\tSetTeleported( false );\r\n\t}\r\n}\r\n\r\nvoid CSkater::UpdateCamera( bool instantly )\r\n{\r\n//\tprintf (\"%d: SUTUBBBEDDDDDDDDDDDDDDDDDDDDDDDD  UpdateCamera(%d)\\n\",__LINE__,instantly);\t\r\n\tif (instantly)\r\n\t{\r\n\t\tSetTeleported( false );\r\n\t}\r\n}\r\n\r\nGfx::Camera* CSkater::GetActiveCamera( void )\r\n{\r\n\r\n\treturn Nx::CViewportManager::sGetActiveCamera(m_skater_number);\r\n}\r\n\t\r\nCCompositeObject* CSkater::GetCamera()\r\n{\r\n\tuint32 camera_name = CRCD(0x967c138c,\"SkaterCam0\");\r\n\tif (m_skater_number == 1)\r\n\t{\r\n\t\tcamera_name = CRCD(0xe17b231a,\"SkaterCam1\");\r\n\t}\r\n\treturn static_cast< CCompositeObject* >(CCompositeObjectManager::Instance()->GetObjectByID(camera_name));\r\n}\r\n\r\nvoid CSkater::SetViewMode( EViewMode view_mode )\r\n{\r\n\t\r\n\t Mdl::FrontEnd* front = Mdl::FrontEnd::Instance();\r\n\t//HUD::PanelMgr* panel_mgr = HUD::PanelMgr::Instance();\r\n\r\n\tif( m_viewing_mode == view_mode )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\r\n\t// don't want to do it to skaters that don't have this component\r\n\t// (which would be the nonlocal skaters)\t\r\n\tif (!GetSkaterPhysicsControlComponent())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tm_viewing_mode = view_mode;\r\n\t\t\t  \r\n\tswitch ( m_viewing_mode )\r\n\t{\r\n\t\t// Normal skaing around with camera\r\n\t\tcase GAMEPLAY_SKATER_ACTIVE:\r\n\t\t{\r\n\t\t\t// Regular gameplay, panel and console on\r\n\t\t\tif (GetPhysicsInt(CRCD(0x9816e1e3,\"ScreenShotMode\")))\r\n\t\t\t{\r\n\t\t\t\tdodgy_test(); printf(\"UnPausing game\\n\");\r\n\t\t\t\tfront->PauseGame(false);\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\t// select+X pressed once, skater is frozen\t\t\t\t\t\t\t\t\t\t  \r\n\t\tcase VIEWER_SKATER_PAUSED:\r\n\t\t{\r\n\t\t\tif (GetPhysicsInt(CRCD(0x9816e1e3,\"ScreenShotMode\")))\r\n\t\t\t{\r\n\t\t\t\tdodgy_test(); printf(\"Freezing game\\n\");\r\n\t\t\t\tfront->PauseGame(true);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tGetSkaterPhysicsControlComponent()->SuspendPhysics(true);\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n\t\t// select+X pressed again, skater skates around\t\t\t\t\t \r\n\t\tcase VIEWER_SKATER_ACTIVE:\r\n\t\t{\r\n\t\t\t// pause the  game, turn off console\r\n\t\t\tif (GetPhysicsInt(CRCD(0x9816e1e3,\"ScreenShotMode\")))\r\n\t\t\t{\r\n\t\t\t\t// Dan: should we skip VIEWER_SKATER_ACTIVE then ScreenShotMode is true?\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tGetSkaterPhysicsControlComponent()->SuspendPhysics(false);\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n\t\t\r\n\t\tdefault:\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n}\r\n\r\nvoid CSkater::Pause()\r\n{\r\n\tif (!mPaused && m_local_client )\r\n\t{\r\n\t\tMARK;\r\n\t\t\r\n\t\t// Pause the base object\r\n\t\tCMovingObject::Pause();\r\n\r\n\t\t// Switch off the meters. They will come back on by themselves when the skater is unpaused\r\n\t\t// and his logic is called again.\r\n\t\tDbg_Assert(mp_skater_score_component)\t   // Might not have a panel in the front end\r\n\t\t\r\n\t\t// NOTE:  These two lines make the balance meter vanish in \"Screenshot\" mode\r\n\t\t// But are needed for regular game pausing\r\n\t\tmp_skater_score_component->GetScore()->SetBalanceMeter(false);\r\n\t\tmp_skater_score_component->GetScore()->SetManualMeter(false);\r\n\t\t\r\n\t\tScript::RunScript(CRCD(0x1277e3fd,\"pause_run_timer\"), NULL);\r\n\t\t\r\n\t\t// Pause the input device (such as vibrations)\r\n\t\tif (mp_input_component)\r\n\t\t{\r\n\t\t\tmp_input_component->PauseDevice();\r\n\t\t}\r\n        \r\n\t\t// Pause the game sounds\r\n\t\tSfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\t\tsfx_manager->PauseSounds();\r\n\t}\r\n}\r\n\r\nvoid CSkater::UnPause()\r\n{\r\n\tif (mPaused && m_local_client)\r\n\t{\r\n\t\tMARK;\r\n\t\t\r\n\t\tCMovingObject::UnPause();\r\n\t\t\r\n\t\tif (mp_input_component)\r\n\t\t{\r\n\t\t\tmp_input_component->UnPauseDevice();\r\n\t\t}\r\n\r\n\t\tCSkaterLoopingSoundComponent *p_sound_loop_component = GetSkaterLoopingSoundComponent();\r\n\t\tif (p_sound_loop_component)\r\n\t\t{\r\n\t\t\tp_sound_loop_component->UnPause();\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\n// Ken: Factored this out so that the replay code can call it too.\r\nvoid CSkater::UpdateShadow(const Mth::Vector& pos, const Mth::Matrix& matrix)\r\n{\r\n#ifndef __PLAT_NGPS__\r\n\tstatic Mth::Vector ground_dir( 0.8f, -0.8f, 0.3f );\r\n\tstatic Mth::Vector air_dir( 0.0f, -1.0f, 0.0f );\r\n\t\r\n\t// If lights are active, set the ground direction to be that of the primary light.\r\n\tif( GetModel())\r\n\t{\r\n\t\tNx::CModelLights *p_lights = GetModel()->GetModelLights();\r\n\t\tif( p_lights )\r\n\t\t{\r\n\t\t\tground_dir = p_lights->GetLightDirection( 0 ) * -1.0f;\r\n\r\n\t\t\tif( ground_dir[Y] > -0.65f )\r\n\t\t\t{\r\n\t\t\t\t// Lighting direction is too shallow, leading to overly extended shadows. Limit direction.\r\n\t\t\t\t// In the new vector, we know we want the [Y] component to be -0.65, so it follows that we\r\n\t\t\t\t// want ( [X]^2 + [Z]^2 ) to be ( 1.0 - ( -0.65 ^2 )), or 0.5775. First, figure out the\r\n\t\t\t\t// current value of ( [X]^2 + [Z]^2 ).\r\n\t\t\t\tfloat xz_squared\t= ( ground_dir[X] * ground_dir[X] ) + ( ground_dir[Z] * ground_dir[Z] );\r\n\t\t\t\tfloat multiple\t\t= sqrtf( 0.5775f / xz_squared );\r\n\t\t\t\tground_dir[X]\t\t= ground_dir[X] * multiple;\r\n\t\t\t\tground_dir[Y]\t\t= -0.65f;\r\n\t\t\t\tground_dir[Z]\t\t= ground_dir[Z] * multiple;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tbool ground = true;\r\n\tif( mp_skater_physics_control_component && ( mp_skater_physics_control_component->IsSkating()))\r\n\t{\r\n\t\tground = mp_skater_core_physics_component->GetState() == GROUND;\r\n\t}\r\n\telse if( mp_walk_component )\r\n\t{\r\n\t\tground = mp_walk_component->GetState() != CWalkComponent::WALKING_AIR;\r\n\t}\r\n\t\r\n\t// Interpolate between the two shadow directions based on Skater state.\r\n\tif( ground )\r\n\t{\r\n\t\tm_air_timer = ( m_air_timer > 0 ) ? ( m_air_timer - 1 ) : 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_air_timer = ( m_air_timer < 16 ) ? ( m_air_timer + 1 ) : 16;\r\n\t}\r\n\r\n\tMth::Vector dir = Mth::Lerp(ground_dir, air_dir, m_air_timer * (1.0f / 16.0f));\r\n\t// Mth::Vector dir = ground_dir + (( air_dir - ground_dir ) * ((float)m_air_timer / 16.0f ));\r\n\tmp_shadow_component->SetShadowDirection( dir );\r\n#ifdef __PLAT_NGC__\r\n\tNxNgc::EngineGlobals.skater_shadow_dir.x = dir[X];\r\n\tNxNgc::EngineGlobals.skater_shadow_dir.y = dir[Y];\r\n\tNxNgc::EngineGlobals.skater_shadow_dir.z = dir[Z];\r\n\tNxNgc::EngineGlobals.skater_height = GetSkaterStateComponent()->GetHeight();\r\n\r\n#endif\t\t// __PLAT_NGC__ \r\n\r\n#endif\r\n\r\n\t/*\r\n\tGJ:  The following has been moved to CShadowComponent::Update()\r\n\t\r\n\tMth::Vector shadow_target_pos = pos + ( matrix.GetUp() * 36.0f );\r\n\r\n\tif ( pShadowComponent->mp_shadow )\r\n\t{\r\n\t\tif (pShadowComponent->mp_shadow->GetShadowType()==Gfx::vSIMPLE_SHADOW)\r\n\t\t{\r\n\t\t\tpShadowComponent->mp_shadow->UpdatePosition(m_shadow_pos,m_matrix,pShadowComponent->m_shadow_normal);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpShadowComponent->mp_shadow->UpdatePosition(shadow_target_pos); // at this point m_pos is the same as m_pos\r\n\t\t}\r\n\t}\r\n\t*/\r\n}\r\n\r\n// K: Added for use by replay code so that it can playback pad vibrations\r\nSIO::Device *CSkater::GetDevice()\r\n{\r\n\t// Stubbed for now\r\n\t// Dbg_MsgAssert(m_input_handler,(\"NULL m_input_handler\"));\r\n\t// Dbg_MsgAssert(m_input_handler->m_Device,(\"NULL m_input_handler->m_Device ?\"));\r\n\t// return m_input_handler->m_Device;\r\n\treturn NULL;\r\n}\r\n\r\nint\t\t\tCSkater::GetHeapIndex( void )\r\n{\r\n\treturn m_heap_index;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nCSkater::CSkater ( int player_num, CBaseManager* p_obj_manager, bool local_client, int obj_id,\r\n\t\t\t\t\t\tint heap_num, bool should_tristrip ) : m_link_node( this ), m_local_client( local_client )\r\n{\r\n\tm_type = SKATE_TYPE_SKATER;\r\n\t\r\n\tm_in_world = false;\r\n\tm_heap_index = heap_num;\r\n\tm_id = obj_id;\r\n\r\n\t// Mick:  Set up the Skater and Skater2 aliases\t\r\n\t// Note we use heap_num rather than player_num, as player_num is unreliable in network games\r\n\tif (heap_num == 0)\r\n\t{\r\n\t\tObj::CTracker::Instance()->AddAlias(CRCD(0x5b8ab877,\"Skater\"),this);\t\t\r\n\t}\r\n\tif (heap_num == 1)\r\n\t{\r\n\t\tObj::CTracker::Instance()->AddAlias(CRCD(0x6ed3fa7,\"Skater2\"),this);\t\t\t\t\r\n\t}\r\n\t\r\n\t// low priority (but not lower than cameras) ensures that moving objects we may skate on or\r\n\t// cars we may drive will be updated before the skater each frame\r\n\tm_node.SetPri(-500);\r\n\tp_obj_manager->RegisterObject(*this);\r\n\t\r\n\tm_skater_number = player_num;\r\n\t\r\n\tDUMPI(m_skater_number);\r\n\tDUMPI(m_id);\r\n\r\n\tSetProfileColor(0x00c0c0);\t\t\t\t// yellow = skater\r\n\t\r\n\tmp_animation_component=NULL;\r\n\tmp_model_component=NULL;\r\n\tmp_shadow_component=NULL;\r\n\tmp_trick_component=NULL;\r\n\tmp_vibration_component=NULL;\r\n\tmp_input_component=NULL;\r\n\tmp_skater_sound_component=NULL;\r\n\tmp_skater_gap_component=NULL;\r\n\tmp_skater_score_component=NULL;\r\n\tmp_skater_core_physics_component=NULL;\r\n    mp_stats_manager_component=NULL;\r\n\tmp_walk_component=NULL;\r\n\tmp_skater_physics_control_component=NULL;\r\n\r\n\t// create the following components before CMovingObject creates components\r\n\t\r\n\tScript::CStruct* component_struct = new Script::CStruct;\r\n\t\r\n\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERSTATE);\r\n\tCreateComponentFromStructure(component_struct);\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\tif (m_local_client)\r\n\t{\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_INPUT);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\tmp_input_component = GetInputComponent();\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERSCORE);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\tmp_skater_score_component = GetSkaterScoreComponent();\r\n\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERMATRIXQUERIES);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_TRICK);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\tmp_trick_component = GetTrickComponent();\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERPHYSICSCONTROL);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\tmp_skater_physics_control_component=GetSkaterPhysicsControlComponent();\r\n\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERCOREPHYSICS);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\tmp_skater_core_physics_component = GetSkaterCorePhysicsComponent();\r\n\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERROTATE);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERGAP);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\tmp_skater_gap_component = GetSkaterGapComponent();\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERADJUSTPHYSICS);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_TRIGGER);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERFINALIZEPHYSICS);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERCLEANUPSTATE);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_WALK);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\tmp_walk_component = GetWalkComponent();\r\n\t\t\r\n#\t\tifdef TESTING_GUNSLINGER\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_RIDER);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_WEAPON);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n#\t\tendif\r\n\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERLOCALNETLOGIC);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERENDRUN);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERBALANCETRICK);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERLOOPINGSOUND);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\r\n        component_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_STATSMANAGER);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n        mp_stats_manager_component = GetStatsManagerComponent();\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_MOVABLECONTACT);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERRUNTIMER);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERSCORE);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\tmp_skater_score_component = GetSkaterScoreComponent();\r\n\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERNONLOCALNETLOGIC);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERCLEANUPSTATE);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERFLOATINGNAME);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERENDRUN);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t\t\r\n\t\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERLOOPINGSOUND);\r\n\t\tCreateComponentFromStructure(component_struct);\r\n\t}\r\n\t\r\n\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERSTATEHISTORY);\r\n\tCreateComponentFromStructure(component_struct);\r\n\tmp_skater_state_history_component = GetSkaterStateHistoryComponent();\r\n\t\r\n\tcomponent_struct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_SKATERFLIPANDROTATE);\r\n\tCreateComponentFromStructure(component_struct);\r\n\t\t\t\t\t\t\t\t\t\r\n    delete component_struct;\r\n}\r\n\r\nvoid CSkater::Construct ( Obj::CSkaterProfile* pSkaterProfile)\r\n{\r\n\t// only skater 0 should update the camera in the\r\n\t// skateshop (otherwise, reloading skater 1 would\r\n\t// cause a momentary flicker)\r\n\tMdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tbool should_create_cam = ( !skate_mod->GetGameMode()->IsFrontEnd() ) || ( m_skater_number == 0 );\r\n\r\n\tif( m_local_client && should_create_cam )\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\r\n\t\tuint32\tname = CRCD(0x967c138c,\"SkaterCam0\");\r\n\t\tif (m_skater_number == 1)\r\n\t\t{\r\n\t\t\tname = CRCD(0xe17b231a,\"SkaterCam1\");\r\n\t\t}\r\n\t\t\r\n\t\t\t   \r\n\t\tCCompositeObject *p_cam_object = (CCompositeObject*)CCompositeObjectManager::Instance()->GetObjectByID(name);\r\n\t\tif (p_cam_object)\r\n\t\t{\r\n\t\t\t// Camera already exists, was being used as an observer camera,\r\n\t\t\t// so just attache it back to this skater\r\n\t\t\tGetSkaterCameraComponentFromObject(p_cam_object)->SetSkater( this );\r\n\t\t\tGetWalkCameraComponentFromObject(p_cam_object)->SetSkater( this );\r\n\t\t}\r\n\t\telse\r\n\t\t\r\n\t\t{\r\n\t\t\t// Add the parameters for the skater camera component\t\t\r\n\t\t\t// so it can get me as the target\r\n\t\t\tScript::CStruct * p_component_params = new Script::CStruct;\r\n\t\t\tp_component_params->AddChecksum(CRCD(0x4c48da58,\"CameraTarget\"), GetID());\r\n\t\t\t// p_component_params->AddChecksum(CRCD(0x1313e3c,\"ProximTriggerTarget\"), GetID());\r\n\t\t\tp_component_params->AddChecksum(CRCD(0xa1dc81f9,\"name\"),name);\r\n\t\r\n\t\t\tp_cam_object = CCompositeObjectManager::Instance()->CreateCompositeObjectFromNode(\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tScript::GetArray(\"skatercam_composite_structure\"),p_component_params);\r\n\t\t\tdelete\tp_component_params;\r\n\t\t}\t\t\r\n\t\t\r\n\t\tGetWalkComponent()->SetAssociatedCamera(p_cam_object);\r\n\t\tCFuncs::SetActiveCamera(name, m_skater_number, false);\r\n\t\t\r\n#if 0 \r\n// proximtrigger components are deprecated  \t\r\n\t\t// point the viewer camera's proximity trigger at the skater\r\n\t\t// if it exists, which it might not, if the viewer is not active (Like for the XBox)\r\n\t\tCObject* p_viewer_cam = CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0xeb17151b,\"viewer_cam\"));\r\n\t\tif (p_viewer_cam)\r\n\t\t{\r\n\t\t\tGetProximTriggerComponentFromObject(static_cast< CCompositeObject* >(p_viewer_cam))->SetScriptTarget(this);\r\n\t\t}\r\n#endif\t\t\r\n\t\t\r\n\t\t// Lock the object so it won't get deleted.\r\n\t\tp_cam_object->SetLockOn();\r\n\t\t\r\n\t\t\t// Set default mode, so \"behind\" etc, is set tosomething sensible \r\n\t\tGetSkaterCameraComponentFromObject(p_cam_object)->SetMode(CSkaterCameraComponent::SKATERCAM_MODE_NORMAL_MEDIUM, 0.0f);\r\n\r\n\t\t/*\r\n\t\tCCameraComponent *p_cam_component\t\t\t\t= new CCameraComponent();\r\n\t\tCSkaterCameraComponent *p_skatercam_component\t= new CSkaterCameraComponent();\r\n\r\n\t\t// We want the CameraComponent processed *after* the SkaterCameraComponent.\r\n\t\tp_cam_object->AddComponent( p_skatercam_component );\r\n\t\tp_cam_object->AddComponent( p_cam_component );\r\n\r\n\t\tp_skatercam_component->InitFromStructure( NULL );\r\n\t\tp_cam_component->InitFromStructure( NULL );\r\n\r\n\t\tp_skatercam_component->SetSkater( this );\r\n\t\t*/\r\n\t\t\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\r\n\t// Set up the AI script.\r\n\tDbg_MsgAssert(mp_script==NULL,(\"mp_script not NULL?\"));\r\n\r\n\tmp_script=new Script::CScript;\r\n\r\n\r\n// SkaterInit used to be run there --------------> *\t\r\n\t\r\n\tScript::CStruct* pSkaterInfoParams = Script::GetStructure(CRCD(0x962e5cf7,\"skater_asset_info\"));\r\n\r\n\tuint32 skeleton_name = CRCD(0x5a9d2a0a,\"human\");\r\n\tif (pSkaterInfoParams)\r\n\t{\r\n\t\tpSkaterInfoParams->GetChecksum(\"skater_skeleton\",&skeleton_name,Script::NO_ASSERT);\r\n\t}\r\n    \r\n//--------------------------------------------------------\r\n\t// components need to be created in a specific\r\n\t// order...  the model needs to come as late as\r\n\t// possible, so that all the other components can\r\n\t// play around with its display matrix.  (maybe \r\n\t// should have some kind of priority system for \r\n\t// components)?\r\n\t\r\n\tMovingObjectCreateComponents();\r\n\r\n\tDbg_MsgAssert( !GetAnimationComponent(), ( \"Animation component already exists\" ) );\r\n\tScript::CStruct* pAnimationStruct = new Script::CStruct;\r\n\tpAnimationStruct->AddChecksum( CRCD(0xb6015ea8,\"component\"), CRC_ANIMATION );\r\n\tpAnimationStruct->AddChecksum( CRCD(0x5b8c6dc2,\"AnimEventTableName\"), CRCD(0x3fec31a6,\"SkaterAnimEventTable\") );\r\n\tCreateComponentFromStructure(pAnimationStruct, NULL);\r\n    delete pAnimationStruct;\r\n\tmp_animation_component = GetAnimationComponent();\r\n\t\t\r\n\tDbg_MsgAssert( !GetSkeletonComponent(), ( \"Skeleton component already exists\" ) );\r\n\tScript::CStruct* pSkeletonStruct = new Script::CStruct;\r\n\tpSkeletonStruct->AddChecksum( CRCD(0xb6015ea8,\"component\"), CRC_SKELETON );\r\n    pSkeletonStruct->AddChecksum( CRCD(0x222756d5,\"skeleton\"), skeleton_name );\r\n    pSkeletonStruct->AddInteger( CRCD(0xd3982061,\"max_bone_skip_lod\"), 0 );\r\n\tCreateComponentFromStructure(pSkeletonStruct, NULL);\r\n    delete pSkeletonStruct;\r\n\t\r\n\t#if 0\r\n\t// Dan: testing\r\n\tScript::CStruct* pStruct = new Script::CStruct;\r\n\tpStruct->AddChecksum(CRCD(0xb6015ea8,\"component\"), CRC_RIBBON);\r\n    pStruct->AddChecksum(CRCD(0xcab94088,\"bone\"), CRCD(0x7ee14cfe,\"Bone_Wrist_L\"));\r\n    pStruct->AddInteger(CRCD(0x69feef91,\"num_links\"), 15);\r\n    pStruct->AddFloat(CRCD(0x9f4625c2,\"link_length\"), 5.0f);\r\n    pStruct->AddChecksum(CRCD(0x99a9b716,\"color\"), MAKE_RGB(0, 0, 255));\r\n\tCreateComponentFromStructure(pStruct, NULL);\r\n    delete pStruct;\r\n\t#endif\r\n\t\r\n//--------------------------------------------------------\r\n \t\r\n\tuint32 anim_script_name = CRCD(0x501949bd,\"animload_human\");\r\n\tif (pSkaterInfoParams)\r\n\t{\r\n\t\tpSkaterInfoParams->GetChecksum(CRCD(0x8b7488e,\"skater_anims\"),&anim_script_name,Script::NO_ASSERT);\r\n\t}\r\n\tmp_animation_component->SetAnims( anim_script_name );\r\n\tmp_animation_component->EnableBlending( true );\r\n\t\r\n\t// Create an empty model \r\n\tDbg_MsgAssert( !GetModelComponent(), ( \"Model component already exists\" ) );\r\n\tScript::CStruct* pModelStruct = new Script::CStruct;\r\n\tpModelStruct->AddChecksum( NONAME, CRCD(0x10079f2d,\"UseModelLights\") );\r\n\t\r\n\t// Enables the shadow volume on any meshes that get added in the future\r\n\tint shadowVolumeEnabled = 0;\r\n\tif ( m_local_client )\r\n\t{\r\n\t\tshadowVolumeEnabled = true;\r\n\t}\r\n\tpModelStruct->AddInteger( CRCD(0x2a1f92c0,\"ShadowVolume\"), shadowVolumeEnabled ); \r\n\t\r\n\tpModelStruct->AddChecksum( CRCD(0xb6015ea8,\"component\"), CRC_MODEL );\r\n\tCreateComponentFromStructure(pModelStruct, NULL);\r\n\tdelete pModelStruct;\r\n\tmp_model_component = GetModelComponent();\r\n\t\r\n\t// create the model\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterGeomHeap(m_heap_index));\r\n\t\r\n\tAss::CAssMan * ass_man =  Ass::CAssMan::Instance();\r\n\tbool defaultPermanent = ass_man->GetDefaultPermanent();\r\n\tass_man->SetDefaultPermanent( false );\r\n\t\r\n\t// load up the model from a profile\r\n\tmp_model_component->InitModelFromProfile( pSkaterProfile->GetAppearance(), false, m_heap_index );\r\n\t\r\n\tass_man->SetDefaultPermanent( defaultPermanent );\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Create Model lights\r\n\t// (This has been moved to the CModelComponent)\r\n//\tGetModel()->CreateModelLights();\r\n//\tNx::CModelLights *p_lights = GetModel()->GetModelLights();\r\n//\tp_lights->SetPositionPointer(&m_pos);\r\n\r\n\t// now that the model has been created,\r\n\t// create a shadow component for the skater\r\n\tDbg_MsgAssert( !GetShadowComponent(), ( \"Shadow component already exists\" ) );\r\n\tScript::CStruct* pShadowStruct = new Script::CStruct;\r\n\tpShadowStruct->AddChecksum( CRCD(0xb6015ea8,\"component\"), CRC_SHADOW );\r\n    pShadowStruct->AddChecksum( CRCD(0x9ac24b18,\"shadowType\"), (CRCD(0x76a54cd1,\"detailed\")) );\r\n\tCreateComponentFromStructure(pShadowStruct, NULL);\r\n    delete pShadowStruct;\r\n\tmp_shadow_component = GetShadowComponent();\r\n\r\n\tif ( m_local_client )\r\n\t{\r\n\t\tDbg_MsgAssert( !GetVibrationComponent(), ( \"Vibration component already exists\" ) );\r\n\t\tScript::CStruct* p_vibration_struct = new Script::CStruct;\r\n\t\tp_vibration_struct->AddChecksum( CRCD(0xb6015ea8,\"component\"), CRC_VIBRATION );\r\n\t\tCreateComponentFromStructure(p_vibration_struct, NULL);\r\n\t\tdelete p_vibration_struct;\r\n\t\tmp_vibration_component = GetVibrationComponent();\r\n\r\n\t\tDbg_MsgAssert( !GetSkaterStancePanelComponent(), ( \"StancePanel component already exists\" ) );\r\n\t\tScript::CStruct* p_stancepanel_struct = new Script::CStruct;\r\n\t\tp_stancepanel_struct->AddChecksum( CRCD(0xb6015ea8,\"component\"), CRC_SKATERSTANCEPANEL );\r\n\t\tCreateComponentFromStructure(p_stancepanel_struct, NULL);\r\n\t\tdelete p_stancepanel_struct;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_vibration_component = NULL;\r\n\t}\r\n\t\r\n\tif ( m_local_client )\r\n\t{\r\n\t\tDbg_MsgAssert( !GetSkaterSoundComponent(), ( \"SkaterSound component already exists\" ) );\r\n\t\tScript::CStruct* p_skater_sound_struct = new Script::CStruct;\r\n\t\tp_skater_sound_struct->AddChecksum( CRCD(0xb6015ea8,\"component\"), CRC_SKATERSOUND );\r\n\t\tCreateComponentFromStructure(p_skater_sound_struct, NULL);\r\n\t\tdelete p_skater_sound_struct;\r\n\t\tmp_skater_sound_component = GetSkaterSoundComponent();\r\n\t}\r\n\t\r\n\t// Finalize Components\r\n\tFinalize();\t\t\t\t\t\t\t\t\t\r\n\t\r\n\t// Set up the controller preferences.\r\n\tDbg_MsgAssert(m_skater_number>=0 && m_skater_number<Mdl::Skate::vMAX_SKATERS,(\"Eh? Bad m_skater_number\"));\r\n\t\r\n\tif (IsLocalClient())\r\n\t{\r\n\t\tmp_skater_core_physics_component->m_auto_kick = skate_mod->mp_controller_preferences[m_skater_number].AutoKickOn;\r\n\t\tmp_skater_core_physics_component->m_spin_taps = skate_mod->mp_controller_preferences[m_skater_number].SpinTapsOn;\r\n\t\tmp_vibration_component->SetActiveState(skate_mod->mp_controller_preferences[m_skater_number].VibrationOn);\r\n\t}\r\n\r\n\r\n\t// Mick:  Run the SkaterInit Script\r\n\t// this used to be done before all the components are created, but it makes more sense to do it after\r\n\t// and the old way boke after I moved the \"SetSkaterCamOverride\" into SkaterCameraComponent\r\n\tif ( m_local_client )\r\n\t{\r\n\t\t// Start running the ground AI.\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tmp_script->SetCommentString(\"Created in CSkater constructor, assigned to CSkater::mp_script\");\r\n\t\t#endif\r\n\t\tmp_script->SetScript(\"SkaterInit\",NULL,this);\r\n\t}\r\n\r\n\t\r\n\tUpdateSkaterInfo( pSkaterProfile );\r\n\r\n\tUpdateStats( pSkaterProfile );\r\n\t\r\n\tif ( m_local_client )\r\n\t{\r\n\t\tGetSkaterSoundComponent()->SetMaxSpeed(GetScriptedStat(CRCD(0xcc5f87aa,\"Skater_Max_Max_Speed_Stat\")));\r\n\t}\r\n\t\r\n\r\n\t/*\r\n\t// K: For the debug info above the skater.\r\n\tmp_drawer=new Fnt::Drawer();\r\n\tmp_drawer->SetRenderState(Image::Drawer::vRS_ZBUFFER | Image::Drawer::vRS_ALPHABLENDING);\r\n\tmp_drawer->SetFont(\"small.fnt\");\r\n\tmp_drawer->SetJust(Image::vJUST_CENTER_X,Image::vJUST_CENTER_Y);\r\n\tmp_drawer->SetShadowState(true,0,0);\r\n\t*/\r\n\r\n\tif (mp_trick_component)\r\n\t{\r\n\t\t// K: Create and fill in the trick mappings structure.\r\n\t\tmp_trick_component->UpdateTrickMappings( pSkaterProfile );\r\n\r\n\t\t// Initialise the event buffer.\r\n\t\tmp_trick_component->ClearEventBuffer();\r\n\t\t\r\n\t\t// Initialise the trick queue\r\n\t\tmp_trick_component->ClearTrickQueue();\r\n\t\tmp_trick_component->ClearManualTrick();\r\n\t\tmp_trick_component->ClearExtraGrindTrick();\r\n\r\n\t\tmp_trick_component->SetAssociatedScore(mp_skater_score_component->GetScore());\r\n\t}\r\n\tif (mp_skater_gap_component)\r\n\t{\r\n\t\tmp_skater_gap_component->SetAssociatedScore(mp_skater_score_component->GetScore());\r\n\t}\r\n\t\r\n\tmSparksRequireRail=true;\r\n\r\n\r\n\tObj::CCollisionComponent* p_collision_component = GetCollisionComponent();\r\n\tif ( p_collision_component )\r\n\t{\r\n\t\tif (p_collision_component->GetCollision())\r\n\t\t{\r\n\t\t\t// Garrett: Make skater non-collidable for now\r\n\t\t\tp_collision_component->GetCollision()->SetObjectFlags(mSD_NON_COLLIDABLE);\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Init collision cache for CFeelers\r\n\tif (m_local_client)\r\n\t{\r\n\t\t// mp_collision_cache = Nx::CCollCacheManager::sCreateCollCache();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// mp_collision_cache = NULL;\r\n\t}\r\n\r\n\t// make sure it doesn't flash at the origin for a brief moment,\r\n\tmp_model_component->FinalizeModelInitialization();\r\n\r\n\t// this needs to happen after the m_id has been assigned\r\n\tScript::RunScript( CRCD(0xae5438af,\"InitSkaterParticles\"), NULL, this );\r\n\r\n\t// safety-check to make sure he doesn't start out in the blair witch position\r\n\t// (because of our animation LOD-ing system)\r\n\t// (must be done before the models get initialized)\r\n    mp_animation_component->PlaySequence(CRCD(0x1ca1ff20,\"default\"));\r\n    \r\n    if (m_local_client)\r\n\t{\r\n\t\t// add created tricks\r\n\t\tfor (int i=0; i < Game::vMAX_CREATED_TRICKS; i++)\r\n\t\t{\r\n\t\t\tm_created_trick[i] = new Game::CCreateATrick;\r\n\t\t}\r\n        Script::RunScript( CRCD(0xbdc1c89,\"spawn_add_premade_cats_to_skater\"), NULL, this );\r\n        \r\n\t\t// setup the correct physics state\r\n\t\tCCompositeObject::CallMemberFunction(CRCD(0x5c038f9b,\"SkaterPhysicsControl_SwitchWalkingToSkating\"), NULL, NULL);\r\n\t}\r\n}\r\n\r\nvoid CSkater::Init(Obj::CSkaterProfile* pSkaterProfile)\r\n{\r\n\tConstruct(pSkaterProfile);\r\n\r\n\tGameNet::Manager * gamenet_manager =  GameNet::Manager::Instance();\r\n\r\n// Note, both tasks are registered as LOW_PRIORITY, so they come after everything else\r\n// this ensures the movement of the skater is in sync with objects the skater stands on\r\n\t\r\n\tif( m_local_client && CFuncs::ScriptInMultiplayerGame( NULL, NULL ))\r\n\t{\r\n\t\tNet::App* client;\r\n\t\r\n\t\tclient = gamenet_manager->GetClient( m_skater_number );\r\n\t\tDbg_Assert( client );\r\n\t\t   \r\n\t\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SCORE, Mdl::Score::s_handle_score_message, 0, this );\r\n\t\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SKATER_COLLIDE_WON, CSkaterStateHistoryComponent::sHandleCollision, 0, this );\r\n\t\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SKATER_COLLIDE_LOST, CSkaterStateHistoryComponent::sHandleCollision, 0, this );\r\n\t\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SKATER_PROJECTILE_HIT_TARGET, CSkaterStateHistoryComponent::sHandleProjectileHit, 0, this );\r\n\t\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_SKATER_HIT_BY_PROJECTILE, CSkaterStateHistoryComponent::sHandleProjectileHit, 0, this );\r\n\t\tclient->m_Dispatcher.AddHandler( GameNet::MSG_ID_STEAL_MESSAGE, CSkaterLocalNetLogicComponent::sHandleStealMessage, 0, this );\r\n\t}\r\n\t\t\r\n\t// moved to CSkaterLocalNetLogicComponent\r\n\t// m_last_update_time = 0;\r\n    \r\n\tObj::CSuspendComponent* pSuspendComponent = GetSuspendComponent();\r\n\tif ( pSuspendComponent )\r\n\t{\r\n\t\tpSuspendComponent->m_lod_dist[0] = 3000;\t// was 500, but in multi-player, we generally want to see subtle animations animating\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t// and in single player, you should always be close to the camera anyway\r\n\t\tpSuspendComponent->m_lod_dist[1] = 5000; \t// we pretty much always want to see the other player, even at a great distance\r\n\t\tpSuspendComponent->m_lod_dist[2] = 10000000;\r\n\t\tpSuspendComponent->m_lod_dist[3] = 10000000;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkater::UpdateStats( CSkaterProfile* pSkaterProfile )\r\n{\t\t\r\n\t// GJ:  apply the stats contained in the skater profile;  we'll need\r\n\t// need to override them after this function, if we're applying cheats\r\n\t\r\n\tthis->SetStat( STATS_AIR, pSkaterProfile->GetStatValue((CRCD(0x439f4704,\"air\"))) );\r\n\tthis->SetStat( STATS_RUN, pSkaterProfile->GetStatValue((CRCD(0xaf895b3f,\"run\"))) );\r\n\tthis->SetStat( STATS_OLLIE, pSkaterProfile->GetStatValue((CRCD(0x9b65d7b8,\"ollie\"))) );\r\n\tthis->SetStat( STATS_SPEED, pSkaterProfile->GetStatValue((CRCD(0xf0d90109,\"speed\"))) );\r\n\tthis->SetStat( STATS_SPIN, pSkaterProfile->GetStatValue((CRCD(0xedf5db70,\"spin\"))) );\r\n\tthis->SetStat( STATS_FLIPSPEED, pSkaterProfile->GetStatValue((CRCD(0x6dcb497c,\"flip_speed\"))) );\r\n\tthis->SetStat( STATS_SWITCH, pSkaterProfile->GetStatValue((CRCD(0x9016b4e7,\"switch\"))) );\r\n\tthis->SetStat( STATS_RAILBALANCE, pSkaterProfile->GetStatValue((CRCD(0xf73a13e3,\"rail_balance\"))) );\r\n\tthis->SetStat( STATS_LIPBALANCE, pSkaterProfile->GetStatValue((CRCD(0xae798769,\"lip_balance\"))) );\r\n\tthis->SetStat( STATS_MANUAL, pSkaterProfile->GetStatValue((CRCD(0xb1fc0722,\"manual_balance\"))) );\r\n\r\n#ifdef __USER_GARY__\r\n\tdodgy_test(); printf(\"Air    %2.2f\\n\",GetStat(STATS_AIR));\t\t\r\n\tdodgy_test(); printf(\"Run    %2.2f\\n\",GetStat(STATS_RUN));\t\t\r\n\tdodgy_test(); printf(\"Ollie  %2.2f\\n\",GetStat(STATS_OLLIE));\t\t\r\n\tdodgy_test(); printf(\"Speed  %2.2f\\n\",GetStat(STATS_SPEED));\t\t\r\n\tdodgy_test(); printf(\"Spin   %2.2f\\n\",GetStat(STATS_SPIN));\t\t\r\n\tdodgy_test(); printf(\"Flip   %2.2f\\n\",GetStat(STATS_FLIPSPEED));\t\t\r\n\tdodgy_test(); printf(\"Switch %2.2f\\n\",GetStat(STATS_SWITCH));\t\t\r\n\tdodgy_test(); printf(\"Rail   %2.2f\\n\",GetStat(STATS_RAILBALANCE));\t\t\r\n\tdodgy_test(); printf(\"Lip    %2.2f\\n\",GetStat(STATS_LIPBALANCE));\t\t\r\n\tdodgy_test(); printf(\"Manual %2.2f\\n\",GetStat(STATS_MANUAL));\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkater::UpdateSkaterInfo( Obj::CSkaterProfile* pSkaterProfile )\r\n{\r\n\t// get some info from the skater profile\r\n\t// while we still have access to it...\r\n\tDbg_MsgAssert( pSkaterProfile,( \"No profile supplied\" ));\r\n\r\n\tm_pushStyle = pSkaterProfile->GetChecksumValue( (CRCD(0xc15dbf86,\"pushstyle\")) );\r\n\tm_isGoofy = pSkaterProfile->GetChecksumValue( (CRCD(0x7d02bcc3,\"stance\")) ) == ( CRCD(0x287fcd4e,\"goofy\") );\r\n\tm_isPro = pSkaterProfile->IsPro();\r\n\tm_displayName = pSkaterProfile->GetDisplayName();\r\n\t\r\n\t// needed for playing correct streams\r\n\tpSkaterProfile->GetInfo()->GetInteger( CRCD(0x3f813177,\"is_male\"), &m_isMale, Script::ASSERT );\r\n\r\n\tconst char* pFirstName;\r\n\tpSkaterProfile->GetInfo()->GetText( CRCD(0x562e3ecd,\"first_name\"), &pFirstName, Script::ASSERT );\r\n\tDbg_MsgAssert( strlen( pFirstName) < MAX_LEN_FIRST_NAME,\r\n\t\t\t\t   ( \"First name %s is too long (max = %d chars)\", m_firstName, MAX_LEN_FIRST_NAME ) );\r\n\tstrcpy( m_firstName, pFirstName );\r\n\t\r\n\tm_skaterNameChecksum = pSkaterProfile->GetSkaterNameChecksum();\r\n\t\r\n\tif (IsLocalClient())\r\n\t{\r\n\t\tmp_skater_core_physics_component->SetFlag(FLIPPED, !m_isGoofy);\r\n\t\tGetSkaterFlipAndRotateComponent()->ApplyFlipState();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkater::~CSkater ( void )\r\n{ \r\n// Taken care of by the shadow component's destructor\r\n//\tObj::CShadowComponent* pShadowComponent = GetShadowComponent();\r\n//\tif ( pShadowComponent )\r\n//\t{\r\n//\t\tpShadowComponent->SwitchOffShadow();\r\n//\t}\r\n\r\n\t// if (mp_collision_cache)\r\n\t// {\r\n\t\t// Nx::CCollCacheManager::sDestroyCollCache(mp_collision_cache);\r\n\t// }\r\n\t\r\n\t// We must unpause the controller before we destruct ourselves.  Otherwise, the\r\n\t// paused/unpaused toggle will become out of sync with any future skater which\r\n\t// uses this controller.\r\n\tif (mPaused && m_local_client && mp_input_component)\r\n\t{\r\n\t\tmp_input_component->GetDevice()->UnPause();\r\n\t\tmp_input_component->GetDevice()->StopAllVibrationIncludingSaved();\r\n\t}\r\n\r\n\tDeleteResources();\t   \r\n\r\n\tScript::RunScript( CRCD(0xf429e0ac,\"DestroySkaterParticles\"), NULL, this );\r\n\r\n\tfor (int i=0; i < Game::vMAX_CREATED_TRICKS; i++)\r\n    {\r\n        delete m_created_trick[i];\r\n    }\r\n\r\n\t// (Mick) If there is a camera still associated with this skater, then delete it\r\n\t// this will be either SkaterCam0 or SkaterCam1, and only on local clients \t\r\n\t// (Steve) only delete player 2's camera. For now, at least, player 1's camera\r\n\t// is persistent because it is used in observer mode\r\n\tif (IsLocalClient() && ( m_skater_number == 1 ))\r\n\t{\r\n\t\tCCompositeObject *p_cam = GetCamera();\r\n\t\tif (p_cam)\r\n\t\t{\r\n\t\t\t//delete p_cam;\r\n\t\t\tp_cam->MarkAsDead();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Reset skater state (physics, score, et al.), such as when you're retrying\r\nvoid CSkater::Reset()\r\n{\r\n\t// MARK;\r\n\t\r\n\tDbg_Assert(mp_skater_score_component);\r\n\tmp_skater_score_component->Reset();\r\n\t\r\n\t// clear max times (records) for the various balance tricks\r\n\tDbg_Assert(GetSkaterBalanceTrickComponent());\r\n\tGetSkaterBalanceTrickComponent()->ClearMaxTimes();\t\r\n\t\r\n\tResetAnimation();\r\n\t\r\n\tDbg_Assert(mp_skater_core_physics_component);\r\n\tint i;\r\n\tfor ( i = 0; i < NUM_ESKATERFLAGS; i++ )\r\n\t{\r\n\t\tmp_skater_core_physics_component->SetFlag( ( ESkaterFlag )i, true );\r\n\t\tmp_skater_core_physics_component->SetFlag( ( ESkaterFlag )i, false );\r\n\t}\r\n\r\n\t// Reset the pad:\r\n\tDbg_Assert(mp_input_component);\r\n\tmp_input_component->GetControlPad().Reset();\r\n}\r\n\r\n\r\n// DeleteResources will delete things the skater has allocated that\r\n// we do not want to stick around when we do a cleanup of everything else\r\n// we should really split the skater into temporary and permanent parts\r\nvoid CSkater::DeleteResources(void)\r\n{\r\n\tif (IsLocalClient())\r\n\t{\r\n\t\tmp_skater_gap_component->ClearActiveGaps();\r\n\t\t\r\n\t\tGetSkaterBalanceTrickComponent()->ClearBalanceParameters();\r\n\t}\r\n\t\r\n\t// we don't want to carry over special items\r\n\t// from one level to another (they would\r\n\t// fragment memory anyway)\r\n\t\r\n\tObj::CSpecialItemComponent* pSpecialItemComponent = GetSpecialItemComponent();\r\n\tDbg_Assert(pSpecialItemComponent);\r\n\tpSpecialItemComponent->DestroyAllSpecialItems();\r\n\r\n\t// need to get rid of any animations\r\n\t// that the skater is currently playing,\r\n\t// or else there will be CBlendChannels\r\n\t// fragmenting the bottom-up heap.\r\n\tmp_animation_component->Reset();\r\n\t\r\n\t\r\n#ifdef\t__SCRIPT_EVENT_TABLE__\t\t\r\n\tif (mp_script)\r\n\t{\r\n\t\tdelete mp_script;\r\n\t\tmp_script = NULL;\r\n\t\t\r\n\t}\r\n#else\r\n\t// Clear the event receiver associated with this objects\r\n\t// They will get set up again next time we add or remove one\r\n\tmp_event_handler_table->unregister_all(this);\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nvoid CSkater::ResetStates()\r\n{\r\n\tDbg_Assert( IsLocalClient());\r\n\r\n\tGetSkaterPhysicsControlComponent()->SuspendPhysics(false);\r\n\t\r\n\tGetSkaterFlipAndRotateComponent()->Reset();\r\n\t\r\n//\t#ifdef __PLAT_NGC__\r\n//\tmDoDeferredRotateAfter=false;\r\n//\tmDeferredFlipAndRotate=false;\r\n//\t#endif\r\n\r\n\t// Ken stuff, reset other misc stuff such as the event buffer, trick queue, blaa blaa\r\n\t\r\n//\tGetExceptionComponent()->ClearExceptions();\r\n\r\n\tDbg_Assert( mp_trick_component );\r\n\tmp_trick_component->ClearQueueTricksArrays();\r\n\tmp_trick_component->ClearManualTrick();\r\n\tmp_trick_component->ClearExtraGrindTrick();\r\n\tmp_trick_component->ClearEventBuffer();\r\n\tmp_trick_component->ClearTrickQueue();\r\n\tmp_trick_component->ClearMiscellaneous();\r\n\t\r\n\tGetSkaterStateComponent()->Reset();\r\n\r\n\t// If set this will make the call to UpdateModel() use the display matrix flipped.\r\n\t// Used when running the lip-trick out-anim, to stop it appearing flipped until\r\n\t// the anim has finished.\r\n\tmp_model_component->mFlipDisplayMatrix=false;\r\n\t\r\n\t// Make sure the meters are off.\r\n\tDbg_Assert( mp_skater_score_component )\r\n\tmp_skater_score_component->GetScore()->SetBalanceMeter(false);\r\n\tmp_skater_score_component->GetScore()->SetManualMeter(false);\r\n\t\r\n\t// Reset the panel\r\n//\tMdl::Score *pScore=GetScoreObject();\r\n//\tpScore->BailRequest();\t// effectively cancels the current score pot\r\n\r\n\t// Reset doing-trick flag so that he doesn't bail on the drop-in if he died whilst\r\n\t// doing a trick.\r\n\t\r\n\tif (mp_vibration_component)\r\n\t{\r\n\t\tmp_vibration_component->StopAllVibration();\r\n\t}\t\r\n\r\n\t// set the shadow to stick to his feet, assuming we are on the ground\r\n\t// Note: These are used by the simple shadow, not the detailed one.\r\n\tmp_shadow_component->SetShadowPos( m_pos );\r\n\tmp_shadow_component->SetShadowNormal( m_matrix[Y] );\r\n\r\n\tmSparksRequireRail=true;\r\n\t\r\n\tGetSkaterStancePanelComponent()->Reset();\r\n}\r\n\r\nvoid CSkater::ResetAnimation()\r\n{\r\n\tDbg_Assert( IsLocalClient());\r\n    \r\n\t// Put the board orientation back to normal\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tNet::Client* client;\r\n\r\n\tclient = gamenet_man->GetClient( GetHeapIndex());\r\n\tDbg_Assert( client );\r\n\r\n\tCSkaterFlipAndRotateComponent* p_flip_and_rotate_component = GetSkaterFlipAndRotateComponent();\r\n\tp_flip_and_rotate_component->RotateSkateboard(GetID(), false, client->m_Timestamp, IsLocalClient());\r\n\tp_flip_and_rotate_component->ApplyFlipState();\r\n\t\r\n\t// Make sure the board is visible\r\n\tmp_model_component->HideGeom( CRCD(0xa7a9d4b8,\"board\"), false, IsLocalClient() );\r\n\t\r\n\t/*\r\n\t// Make sure all atomics are visible\r\n\t// (GJ:  Not really sure why the previous board unhiding is still necessary)\r\n\tpModelComponent->HideGeom((CRCD(0xc4e78e22,\"all\")), false, IsLocalClient());\r\n\t\r\n\t// unhiding all the atomics will conflict with the \"invisible\" cheat\t\r\n\t*/\r\n\t  \r\n\t// getting into certain physics states\r\n\t// will reset the animation, so we want to \r\n\t// make sure we've always got some animation\r\n\t// to be playing...\r\n\tmp_animation_component->Reset();\r\n\r\n//\tGJ:  don't start playing a new animation, because\r\n//  it's possible that the animations have been unloaded\r\n//\tmp_animation_component->PlaySequence( CRCD(0x1ca1ff20,\"default\") );\r\n//\tmp_animation_component->SetLoopingType( Gfx::LOOPING_CYCLE, true );\r\n}\r\n\r\nvoid CSkater::ResetInitScript(bool walk, bool in_cleanup)\r\n{\r\n// Mick: Finally update the \"SkaterInit\" script, so it does any flag clearing that \r\n// is needed by the game\r\n// we do this now, otherwise some other script could issue a MakeSkaterGoto, and clear this script\r\n// so it would never get run.\r\n\tif ( !mp_script )\r\n\t{\r\n\t\tmp_script = new Script::CScript;\r\n\t}\r\n\t\r\n\tScript::CStruct* p_params = NULL;\r\n\tif (walk || in_cleanup)\r\n\t{\r\n\t\tp_params = new Script::CStruct;\r\n\t\tif (walk)\r\n\t\t{\r\n\t\t\tp_params->AddChecksum(NO_NAME, CRCD(0x726e85aa,\"Walk\"));\r\n\t\t}\r\n\t\tif (in_cleanup)\r\n\t\t{\r\n\t\t\tp_params->AddChecksum(NO_NAME, CRCD(0x7b738580,\"InCleanup\"));\r\n\t\t}\r\n\t}\r\n\t\r\n\tmp_script->SetScript(CRCD(0xe740f458,\"SkaterInit\"), p_params, this);\r\n\tif( IsLocalClient())\r\n\t{\r\n\t\tmp_script->Update();\r\n\t}\r\n\tif (p_params)\r\n\t{\r\n\t\tdelete p_params;\r\n\t}\r\n}\r\n\r\n// Reset physics flags, position, velocity, etc...\r\nvoid CSkater::ResetPhysics(bool walk, bool in_cleanup)\r\n{\r\n\t// MARK;\r\n\tDbg_Assert( IsLocalClient());\r\n\r\n\t// Massive function to reset all skater's members so that\r\n\t// replay becomes deterministicalistic\r\n\t// ResetEverything( );\r\n\t\r\n\t// switch back to walking\r\n\tif (mp_skater_physics_control_component->IsWalking())\r\n\t{\r\n\t\tScript::CStruct* p_params = new Script::CStruct;\r\n\t\tp_params->AddChecksum(CRCD(0x91d0d784, \"NewScript\"), CRCD(0x1dde4804, \"OnGroundAi\"));\r\n\t\tJumpToScript(CRCD(0x93a4e402, \"Switch_OnGroundAI\"), p_params);\r\n\t\tdelete p_params;\r\n\t}\r\n\t\r\n\t// make sure the OnExitRun script gets run before DeleteResources clears the script\r\n\tif (mp_script && mp_script->GetOnExitScriptChecksum())\r\n\t{\r\n\t\tuint32 on_exit_script_name_checksum = mp_script->GetOnExitScriptChecksum();\r\n\t\tmp_script->SetOnExitScriptChecksum(0);\r\n\t\tmp_script->Interrupt(on_exit_script_name_checksum);\r\n\t}\r\n\t\r\n\tmp_skater_core_physics_component->Reset();\r\n\r\n\tGetSkaterCameraComponentFromObject(GetCamera())->ResetMode();\r\n\r\n\tResetStates();\r\n\tDeleteResources();\r\n\tResetAnimation();\t\t  \r\n\tResetInitScript(walk, in_cleanup);\r\n\t\r\n\tGetSkaterEndRunComponent()->ClearIsEndingRun();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkater::SkaterEquals( Script::CStruct* pStructure )\r\n{\r\n\t// TODO:  Maybe stick this data inside the skater's tags,\r\n\t// so that we can create new fields without having to\r\n\t// update this function?\r\n\r\n\tDbg_MsgAssert( pStructure,( \"No structure supplied\" ));\r\n\r\n\tif ( pStructure->ContainsFlag( CRCD(0xd82f8ac8,\"is_pro\") ) )\r\n\t{\r\n\t\tif ( !m_isPro )\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\tif ( pStructure->ContainsFlag( CRCD(0x5a3264bb,\"is_custom\") ) )\r\n\t{\r\n\t\tif ( m_isPro )\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\tif ( pStructure->ContainsFlag( CRCD(0x3f813177,\"is_male\") ) )\r\n\t{\r\n\t\tif ( !m_isMale )\r\n\t\t\treturn false;\r\n\t}\r\n\t\r\n\tif ( pStructure->ContainsFlag( CRCD(0xe5c2f84c,\"is_female\") ) )\r\n\t{\r\n\t\tif ( m_isMale )\r\n\t\t\treturn false;\r\n\t}\r\n\t\r\n\tuint32 is_named;\r\n\tif ( pStructure->GetChecksum( CRCD(0xc2e3d008,\"is_named\"), &is_named ) )\r\n\t{\r\n\t\tif ( is_named != m_skaterNameChecksum )\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\tuint32 stance;\r\n\tif ( pStructure->GetChecksum( CRCD(0x7d02bcc3,\"stance\"), &stance ) )\r\n\t{\r\n\t\tuint32 myStance = ( m_isGoofy ? CRCD(0x287fcd4e,\"goofy\") : CRCD(0xb58efc2b,\"regular\") );\r\n\t\tif ( stance != myStance )\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\t// if we've gotten to the end of the function,\r\n\t// that means that all of the criteria matched\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkater::CallMemberFunction( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tDbg_MsgAssert(pScript,(\"NULL pScript\"));\r\n\t\r\n\treturn _function0( Checksum, pParams, pScript );\r\n}\r\n\r\nbool CSkater::_function0( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tswitch (Checksum)\r\n\t{\r\n        // @script | InLocalSkater | returns true if the skater is a local client\r\n\t\tcase 0x7015bc33: // IsLocalSkater\r\n\t\t{\r\n\t\t\treturn IsLocalClient();\r\n\t\t}\r\n\t\t\r\n        // @script | MoveToRandomRestart | moves the skater to a random\r\n        // restart node\r\n\t\tcase 0xbf450bab: // MoveToRandomRestart\r\n\t\t{\r\n\t\t\tMoveToRandomRestart();\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | SkaterIsNamed | true if skater name matches specified name\r\n        // @uparm name | skater name\r\n\t\tcase 0x1c5612ee: // SkaterIsNamed\r\n\t\t{\r\n\t\t\tuint32 checksum;\r\n\t\t\tpParams->GetChecksum( NONAME, &checksum, Script::ASSERT );\r\n\t\t\treturn ( checksum == m_skaterNameChecksum );\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n\t\t// @script | GetCameraId | sets the skater's camera id to CameraId\r\n\t\tcase CRCC(0x97c8285a,\"GetCameraId\"):\r\n\t\t{\r\n\t\t\tuint32 camera_name = CRCD(0x967c138c,\"SkaterCam0\");\r\n\t\t\tif (m_skater_number == 1)\r\n\t\t\t{\r\n\t\t\t\tcamera_name = CRCD(0xe17b231a,\"SkaterCam1\");\r\n\t\t\t}\r\n\t\t\tpScript->GetParams()->AddChecksum(CRCD(0x7a039889,\"CameraId\"), camera_name);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | RemoveSkaterFromWorld | \r\n\t\tcase 0xbce85494:\t// RemoveSkaterFromWorld\r\n\t\t{\r\n\t\t\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n\t\t\tskate_mod->HideSkater( this, true );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n        // @script | AddSkaterToWorld | \r\n\t\tcase 0x0c09c1b7:\t// AddSkaterToWorld\r\n\t\t{\r\n\t\t\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n\t\t\tskate_mod->HideSkater( this, false );\r\n\t\t\t//AddToCurrentWorld();\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\t#if 0\r\n\t\tcase 0x7fa39d17:\t// ResetLookAround\r\n\t\t{\r\n\t\t\tDbg_Message(\"Skater:ResetLookAround does not work\");\r\n\t\t\tif (GetSkaterCameraComponent())\r\n\t\t\t{\r\n\t\t\t\tGetSkaterCameraComponent()->ResetLookAround();\t\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tbreak;\r\n\t\t#endif\r\n\t\t\r\n\t\tcase 0x72aecfc0:\t// ResetRigidBodyCollisionRadiusBoost\r\n\t\t\tResetRigidBodyCollisionRadiusBoost();\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\treturn _function1( Checksum, pParams, pScript );\r\n\t\t\tbreak;\r\n\t}\r\n\treturn true;\r\n}\r\n\t\t\t\r\nbool CSkater::_function1( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\t\r\n\tswitch (Checksum)\r\n\t{\r\n\t\t/////////////////////////////////////////////////////////////////////////////////////////////\r\n        // @script | KillSkater | Killskater will reset the skater\r\n        // to a node, and set his speed to 0. If this command is\r\n        // run from a node, and that node is linked to a restart\r\n        // node, then the skater will skip to that restart node,\r\n        // and the script in that restart node will be executed\r\n\t\t// @parmopt name | Node | | name of node to jump to\r\n\t\t// @parmopt name | prefix | | restart at nearest node matching this prefix\r\n\t\t// @flag RestartWalking | restart the skater in walk physics mode\r\n\t\tcase 0x1b572abf: // KillSkater \r\n\t\t{\r\n\t\t\t// default just clear skater skater\r\n\t\t\t// and reset to origin\t\t\r\n\t\t\t\r\n\t\t\tbool walk = pParams->ContainsComponentNamed(CRCD(0xd6f06bf6,\"RestartWalking\"));\r\n\t\t\t\r\n\t\t\t// If there is a \"node\" parameter, then skip to that \r\n\t\t\t// Mick, optionally add a \"prefix\" parameter, and skip to the nearest node that matches\r\n\t\t\t// this prefix (will need a new node funtion:\r\n\t\t\t//  int\tGetNearestNodeByPrefix(const char *p_prefix, const Mth::Vector &pos)\r\n\r\n\t\t\tconst char *p_prefix = NULL;\r\n\t\t\tuint32\tprefix_name = 0;\r\n\t\t\tif (!pParams->GetChecksum(CRCD(0x6c4e7971,\"prefix\"),&prefix_name))\r\n\t\t\t{\r\n\t\t\t\tif (pParams->GetString(CRCD(0x6c4e7971,\"prefix\"),&p_prefix))\r\n\t\t\t\t{\r\n\t\t\t\t\tprefix_name = Crc::GenerateCRCFromString(p_prefix);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (prefix_name)\r\n\t\t\t{\r\n\t\t\t\tint\ttarget_node = SkateScript::GetNearestNodeByPrefix(prefix_name,m_pos);\r\n\t\t\t\tDbg_MsgAssert(target_node != -1,(\"%s\\nNo restart node found with prefix 0x%x, %s\",pScript->GetScriptInfo(),prefix_name, p_prefix));\r\n\t\t\t\tSkipToRestart(target_node, walk);  \r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\r\n\t\t\tuint32 node_name=0;\r\n\t\t\tif (pParams->GetChecksum(CRCD(0x7a8017ba,\"Node\"),&node_name))\r\n\t\t\t{\r\n\t\t\t\tint target_node = SkateScript::FindNamedNode(node_name);\r\n\t\t\t\tDbg_MsgAssert(target_node != -1,(\"%\\n Tried to kill skater to non-existant node\",pScript->GetScriptInfo()));\r\n\t\t\t\tSkipToRestart(target_node, walk); \r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t\r\n\t\t\t\tint node = pScript->mNode;\r\n\t\t\t\tDbg_MsgAssert(node !=  -1,( \"%s\\nKillSkater called from non node script with no 'node' parameter\",pScript->GetScriptInfo()));\t\t\t\r\n\t\t\t\t{\r\n\t\t\t\t\t// Otherwise, check the links to see if we are linked to a restart point\r\n\t\t\t\t\r\n\t\t\t\t\tint links = SkateScript::GetNumLinks(node);\r\n\t\t\t\t\tint link;\r\n\t\t\t\t\tfor (link = 0;link<links;link++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint linked_node = SkateScript::GetLink(node,link);\r\n\t\t\t\t\t\tif (IsRestart(linked_node))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// if the node is linked to a restart point\r\n\t\t\t\t\t\t\t// then we just skip to that restart point\r\n\t\t\t\t\t\t\tSkipToRestart(linked_node, walk); \r\n\t\t\t\t\t\t\tbreak;   \r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (link == links)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t#if 1\r\n\t\t\t\t\t\tif (Ed::CParkEditor::Instance()->UsingCustomPark()) \t\t// is it a custom park???\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\t\t\t\t\t\t\tskate_mod->skip_to_restart_point( this, -1, walk );\t// just skip to standard restart node\t\t\t\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tDbg_MsgAssert(0,( \"%s\\nKillSkater called, but node %d not linked to restart\",pScript->GetScriptInfo(),node));\t\t\t\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        // @script | SparksOn | turn sparks on\r\n        // @flag RailNotRequired | \r\n\t\tcase 0xe62f94a2: // SparksOn\r\n\t\t\tReplay::WriteSparksOn();\r\n\t\t\tScript::RunScript( CRCD(0xaf4475de,\"sparks_on\"), pParams, this );\r\n\t\t\tmSparksRequireRail=true;\r\n\t\t\tmSparksOn=true;\r\n\t\t\tif (pParams->ContainsFlag(\"RailNotRequired\"))\r\n\t\t\t{\r\n\t\t\t\tmSparksRequireRail=false;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\r\n        // @script | SparksOff | turn sparks off\r\n\t\tcase 0x5436a335: // SparksOff\r\n\t\t\tReplay::WriteSparksOff();\r\n\t\t\tScript::RunScript( CRCD(0x0dccf5c3,\"sparks_off\"), pParams, this );\r\n\t\t\tmSparksOn=false;\r\n\t\t\tmSparksRequireRail=true;\r\n\t\t\tbreak;\r\n\r\n        // @script | BloodOff | turn blood off\r\n        // @parm string | bone | bone name\r\n\t\tcase 0xc67c18d7: // BloodOff\r\n\t\t{\r\n\t\t\tconst char* p_bone_name;\r\n\t\t\tif (!pParams->GetText( CRCD(0xcab94088,\"bone\"), &p_bone_name ))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0,(\"%s\\nBloodOff requires a bone name\"));\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// nothing doing......\r\n\r\n            break;\r\n\t\t}\r\n   \r\n        // @script | Die | can't be called on the player\r\n\t\tcase 0xc6870028:// \"Die\"\r\n\t\t\tDbg_MsgAssert( 0,( \"\\n%s\\nDie can't be called on the player.\\nIs somebody putting 'Die' in a trigger script?\", pScript->GetScriptInfo( ) ));\r\n\t\t\tbreak;\r\n\r\n        // @script | ShouldMongo | true if should mongo\r\n\t\tcase 0x3e8eb713:\t// ShouldMongo\r\n\t\t{\r\n\t\t\tif( !IsLocalClient())\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tswitch ( m_pushStyle )\r\n\t\t\t{\r\n\t\t\t\tcase vALWAYS_MONGO:\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vMONGO_WHEN_SWITCH:\r\n\t\t\t\t\treturn ( mp_skater_core_physics_component->IsSwitched() );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vNEVER_MONGO:\r\n\t\t\t\tdefault:\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\tbreak;\r\n\r\n        // @script | SetCustomRestart |  Skater command to set the current position as the \"custom restart point\" \r\n\t\t// and also to query or clear the status of this restart, based on:\r\n        // @flag set | set the restart\r\n\t\t// @flag clear | clear the restart\r\n\t\t// if no flags are passed, then it will return true if restart point is valid \r\n\t\tcase 0x42832375:\t\t\t// SetCustomRestart\r\n\t\t{\r\n\t\t\tif (pParams->ContainsFlag(CRCD(0x19ebda23,\"set\")))\r\n\t\t\t{\r\n\t\t\t\tm_restart_valid = true;\r\n\t\t\t\tm_restart_pos = m_pos;\r\n\t\t\t\tm_restart_matrix = m_matrix;\t\t\t\r\n\t\t\t\tm_restart_walking = mp_skater_physics_control_component->IsWalking();\r\n\t\t\t}\r\n\t\t\telse if (pParams->ContainsFlag(CRCD(0x1a4e0ef9,\"clear\")))\r\n\t\t\t{\r\n\t\t\t\tm_restart_valid = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn m_restart_valid;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t//break;\r\n\t\t}\r\n\t\t// Note: Intentional fallthrough!  We want setting the point to have the same effect as skipping to it\r\n\t\t\r\n        // @script | SkipToCustomRestart |  Skater command to jump to previously set custom restart \t\t\r\n\t\tcase 0x5a3c19e9:\t\t// SkipToCustomRestart\r\n\t\t{\r\n\t\t\tSkipToRestart(-1, m_restart_walking);\r\n\t\t\tm_pos = m_restart_pos;\r\n\t\t\tDUMP_SPOSITION\r\n\t\t\t#ifdef\tDEBUG_POSITION\r\n\t\t\tdodgy_test(); printf(\"%d: Position = (%.2f,%.2f,%.2f)\\n\",__LINE__,m_pos[X],m_pos[Y],m_pos[Z]);\r\n\t\t\t#endif\r\n\t\t\tm_matrix = m_restart_matrix;\r\n\t\t\tmp_skater_core_physics_component->m_safe_pos = m_pos;\t\t\t\t// for uberfrig\r\n\t\t\tm_old_pos = m_pos;\t\t\t\t// ensure we don't get any nasty triggerings....\r\n\t\t\tSetTeleported();\r\n\t\t\t\r\n\t\t\tmp_skater_core_physics_component->ResetLerpingMatrix();\r\n\t\t\t#ifdef\t\tDEBUG_DISPLAY_MATRIX\r\n\t\t\tdodgy_test(); printf(\"%d: Setting display_matrix[Y][Y] to %f, [X][X] to %f\\n\",__LINE__,mp_skater_core_physics_component->m_lerping_display_matrix[Y][Y],mp_skater_core_physics_component->m_lerping_display_matrix[X][X]);\r\n\t\t\t#endif\r\n\t\t\tmp_skater_core_physics_component->m_display_normal = mp_skater_core_physics_component->m_last_display_normal = mp_skater_core_physics_component->m_current_normal = m_matrix[Y];\r\n\t\t\t// set the shadow to stick to his feet, assuming we are on the ground\r\n\t\t\t// Note: These are used by the simple shadow, not the detailed one.\r\n\t\t\tmp_shadow_component->SetShadowPos( m_pos );\r\n\t\t\tmp_shadow_component->SetShadowNormal( m_matrix[Y] );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | GetStat |  Get a stat value in the float stat_value, so it can be used in a script expression\r\n\t\t// @parm int | Stat | index of stat in stat array, see \r\n\t\tcase 0x7915aa31:\t\t\t// GetStat\r\n\t\t{\r\n\t\t\tint stat;\r\n\t\t\tpParams->GetInteger(CRCD(0xdf4700de,\"Stat\"),&stat,true);\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x8eaf7add,\"stat_value\"),GetStat((EStat)stat));\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        // @script | GetScriptedStat |  Get a stat value in the float stat_value\r\n\t\t// parameters are as used in physics.q\r\n\t\t// and you would generally pass in a structure, like Skater_Max_Speed_Stat\r\n\t\t// rather than the individual values\r\n\t\tcase 0x9abe8a21:\t\t\t// GetScriptedStat\r\n\t\t{\r\n//\t\t\tScript::PrintContents(pParams);\r\n\t\t\tScript::CStruct *p_struct = NULL;\r\n\t\t\tpParams->GetStructure(NONAME,&p_struct,true);\r\n\t\t\tpScript->GetParams()->AddFloat(CRCD(0x8eaf7add,\"stat_value\"),GetScriptedStat(p_struct));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// @script | GetSkaterNumber | Gets the skater number, and puts it into a parameter called\r\n\t\t// SkaterNumber\r\n\t\tcase 0xf4c52f72: // GetSkaterNumber \r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddInteger(CRCD(0xf3cf5755,\"SkaterNumber\"),m_skater_number);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0xd38e8b6c: // PlaceBeforeCamera\r\n\t\t\t{\r\n\t\t\t\tif ( GetActiveCamera() )\r\n\t\t\t\t{\r\n\t\t\t\t\tMth::Vector\t&cam_pos = GetActiveCamera()->GetPos();\r\n\t\t\t\t\tMth::Matrix\t&cam_mat = GetActiveCamera()->GetMatrix();\r\n\r\n\r\n\t\t\t\t\tm_matrix.Ident();\r\n\t\t\t\t\tm_pos = cam_pos;\r\n\t\t\t\t\tm_pos[Y] += FEET( 0 );\r\n\t\t\t\t\tm_pos -= cam_mat[Z] * FEET( 12 );\r\n\t\t\t\t\tDUMP_SPOSITION\r\n\t\t\t\t\tm_old_pos = m_pos;\t\t\t// MoveToRestart \r\n\t\t\t\t\tmp_skater_core_physics_component->m_safe_pos = m_pos;\t\t\t// MoveToRestart  \r\n\t\t\t\t\tm_matrix = cam_mat;\r\n\t\t\t\t\tm_matrix[Z] = -m_matrix[Z];\r\n\t\t\t\t\tm_matrix[X] = -m_matrix[X];\r\n\t\t\t\t\tmp_skater_core_physics_component->ResetLerpingMatrix();\r\n\t\t\t\t\t#ifdef\t\tDEBUG_DISPLAY_MATRIX\r\n\t\t\t\t\tdodgy_test(); printf(\"%d: Setting display_matrix[Y][Y] to %f, [X][X] to %f\\n\",__LINE__,mp_skater_core_physics_component->m_lerping_display_matrix[Y][Y],mp_skater_core_physics_component->m_lerping_display_matrix[X][X]);\r\n\t\t\t\t\t#endif\r\n\t\t\t\t\tmp_skater_core_physics_component->m_display_normal = mp_skater_core_physics_component->m_last_display_normal = mp_skater_core_physics_component->m_current_normal = m_matrix[Y];\r\n\t\t\t\t\t// set the shadow to stick to his feet, assuming we are on the ground\r\n\t\t\t\t\t// Note: These are used by the simple shadow, not the detailed one.\r\n\t\t\t\t\tmp_shadow_component->SetShadowPos( m_pos );\r\n\t\t\t\t\tmp_shadow_component->SetShadowNormal( m_matrix[Y] );\r\n\t\t\t\t\t// update these for the camera\r\n\t\t\t\t\tm_vel = -cam_mat[Z];  \r\n\t\t\t\t\tm_vel[Y] = 0;  \r\n\t\t\t\t\tm_vel.Normalize(10);  \r\n\t\t\t\t\tUpdateCamera(true);\t  \t// re-snap the camera to the correct position\r\n\t\t\t\t\t\r\n\t\t\t\t\t#ifdef\tDEBUG_VELOCITY\r\n\t\t\t\t\tdodgy_test(); printf(\"%d: Velocity = (%.2f,%.2f,%.2f) (%f)\\n\",__LINE__,m_vel[X],m_vel[Y],m_vel[Z],m_vel.Length());\r\n\t\t\t\t\t#endif\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n  \t\t\tDbg_MsgAssert(0,(\"Forgot a break?\"));\t\t\r\n\t\t\r\n\t\tdefault:\r\n\t\t\treturn CMovingObject::CallMemberFunction( Checksum, pParams, pScript );\r\n\t\t\tbreak;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n// End of CallMemberFunction\r\n\r\nvoid CSkater::SparksOn()\r\n{\r\n\tDbg_Assert( 0 );\r\n\r\n\t// GJ:  It would be nice to keep all the spark logic in\r\n\t// script, but it requires some skater state info in C\r\n\t// (like the mSparksRequireRail).  Eventually, we should\r\n\t// move this all to script, instead of calling the following\r\n\t// script from C code.\r\n\r\n\tScript::RunScript( CRCD(0xaf4475de,\"sparks_on\"), NULL, this );\r\n\tmSparksOn = true;\r\n}\r\n\r\nvoid CSkater::SparksOff()\r\n{\r\n\t// GJ:  It would be nice to keep all the spark logic in\r\n\t// script, but it requires some skater state info in C\r\n\t// (like the mSparksRequireRail).  Eventually, we should\r\n\t// move this all to script, instead of calling the following\r\n\t// script from C code.\r\n\tif ( mSparksOn )\r\n\t{\r\n\t\tReplay::WriteSparksOff();\r\n\t\tScript::RunScript( CRCD(0x430efc31,\"TurnOffSkaterSparks\"), NULL, this );\r\n\t\tmSparksOn=false;\r\n\t}\r\n}\r\n\t\r\n// Used by the MakeSkaterGoto script function in cfuncs.cpp\r\n// Causes the skater to jump to the specified script straight away.\r\nvoid CSkater::JumpToScript(uint32 ScriptChecksum, Script::CStruct *pParams)\r\n{\r\n\tDbg_Assert(IsLocalClient());\r\n\t\t\r\n//\tDbg_MsgAssert(mp_script,(\"NULL mp_script\"));\r\n\tif ( !mp_script )\r\n\t{\r\n\t\tmp_script = new Script::CScript;\r\n\t}\r\n\r\n\tGetSkaterFlipAndRotateComponent()->DoAnyFlipRotateOrBoardRotateAfters(); // <- See huge comment above definition of this function.\r\n\tmp_script->SetScript(ScriptChecksum,pParams,this);\r\n\tmp_script->Update();\r\n}\r\n\t\r\nvoid CSkater::JumpToScript(const char *pScriptName, Script::CStruct *pParams)\r\n{\r\n\t\r\n\tJumpToScript(Script::GenerateCRC(pScriptName),pParams);\r\n}\r\n\r\nMth::Matrix&\t\t\t\tCSkater::GetDisplayMatrix( void )\r\n{\r\n\treturn mp_skater_core_physics_component->m_lerping_display_matrix;\r\n}\r\n\r\nvoid\t\t\t\t\t\tCSkater::SetDisplayMatrix( Mth::Matrix& matrix )\r\n{\r\n\tmp_skater_core_physics_component->m_lerping_display_matrix = matrix;\r\n}\r\n\r\nLst::Node< CSkater >*\t\tCSkater::GetLinkNode( void )\r\n{\r\n\treturn &m_link_node;\r\n}\r\n\r\nvoid CSkater::Resync( void )\r\n{\r\n\tif (!m_local_client)\r\n\t{\r\n\t\tGetSkaterNonLocalNetLogicComponent()->Resync();\r\n\t}\r\n\t\r\n\tmp_skater_state_history_component->ResetPosHistory();\r\n\t//mp_skater_state_history_component->ResetAnimHistory();\r\n\t//mp_skater_state_history_component->SetLatestAnimTimestamp( 0 );\r\n\t\r\n}\r\n\r\nvoid CSkater::RemoveFromCurrentWorld( void )\r\n{\r\n\tif (IsLocalClient())\r\n\t{\r\n\t\tGetSkaterLoopingSoundComponent()->StopLoopingSound();\r\n\t}\r\n\t\r\n\tmp_shadow_component->SwitchOffShadow();\r\n    \r\n\tHide( true );\r\n\tm_in_world = false;\r\n}\r\n\r\nvoid\tCSkater::AddToCurrentWorld ( void )\r\n{\r\n\tmp_shadow_component->SwitchOnSkaterShadow();\r\n\tHide( false );\r\n\tm_in_world = true;\r\n}\r\n\r\nbool\tCSkater::IsInWorld( void )\r\n{\r\n\treturn m_in_world;\r\n}\r\n\r\nconst char* CSkater::GetDisplayName()\r\n{\r\n\t// set the player's display name for rankings screen,\r\n\t// \"You got bitch-slapped by X\" messages, etc.\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tif( gamenet_man->InNetGame() )\r\n\t{\r\n\t\tGameNet::PlayerInfo* pInfo = gamenet_man->GetPlayerByObjectID( m_id );\r\n\t\tDbg_Assert( pInfo );\r\n\t\t// (Mick) don't assign it to m_displayName, as that can cause memory allocations\r\n\t\t// and fragments the heap\r\n\t\t// ensure you set the appropiate context if you want to do this.\r\n\t\t//m_displayName =  pInfo->m_Name;\r\n\t\treturn pInfo->m_Name;\r\n\t}\r\n\t\r\n\treturn m_displayName.getString();\r\n}\r\n\r\nvoid CSkater::AddCATInfo(Script::CStruct *pStuff)\r\n{\r\n\tDbg_MsgAssert(pStuff,(\"NULL pStuff\"));\r\n\t\r\n    Script::CArray *p_tricks=new Script::CArray;\r\n    p_tricks->SetSizeAndType(Game::vMAX_CREATED_TRICKS,ESYMBOLTYPE_STRUCTURE);\r\n    for (int i=0; i<Game::vMAX_CREATED_TRICKS; ++i)\r\n    {\r\n        Script::CStruct *p_new_trick_struct=new Script::CStruct;\r\n        p_new_trick_struct->AddStructure(CRCD(0x26a7cadf,\"other\"),m_created_trick[i]->mp_other_params);\r\n        p_new_trick_struct->AddArray(CRCD(0x6b19fc8f,\"animations\"),m_created_trick[i]->mp_animations);\r\n        p_new_trick_struct->AddArray(CRCD(0x2e628ee6,\"rotations\"),m_created_trick[i]->mp_rotations);\r\n\r\n        //Script::PrintContents( p_new_trick_struct );\r\n\r\n        p_tricks->SetStructure(i,p_new_trick_struct);\r\n    }\r\n    pStuff->AddArrayPointer(CRCD(0x1e26fd3e,\"Tricks\"),p_tricks);\r\n}\r\n\r\nvoid CSkater::LoadCATInfo(Script::CStruct *pStuff)\r\n{\r\n    printf(\"LoadCATInfo was called\\n\");\r\n\tDbg_MsgAssert(pStuff,(\"NULL pStuff\"));\r\n\r\n    Script::CArray *pCATInfo=NULL;\r\n    pStuff->GetArray(CRCD(0x1e26fd3e,\"tricks\"),&pCATInfo);\r\n\r\n    Dbg_Assert( m_created_trick[1] );\r\n\r\n    for (int i=0; i<Game::vMAX_CREATED_TRICKS; ++i)\r\n    {\r\n        Script::CStruct *pTemp=NULL;\r\n        pTemp = pCATInfo->GetStructure(i);\r\n        \r\n        // other params\r\n        Script::CStruct *p_other_params=NULL;\r\n        pTemp->GetStructure(CRCD(0x26a7cadf,\"other\"),&p_other_params,Script::ASSERT);\r\n        m_created_trick[i]->mp_other_params->AppendStructure( p_other_params );\r\n\r\n        // animations\r\n        Script::CArray *p_animation_info=NULL;\r\n        pTemp->GetArray(CRCD(0x6b19fc8f,\"animations\"),&p_animation_info,Script::ASSERT);\r\n        Script::CopyArray( m_created_trick[i]->mp_animations, p_animation_info );\r\n        \r\n        // rotations\r\n        Script::CArray *p_rotation_info=NULL;\r\n        pTemp->GetArray(CRCD(0x2e628ee6,\"rotations\"),&p_rotation_info,Script::ASSERT);\r\n        Script::CopyArray( m_created_trick[i]->mp_rotations, p_rotation_info );\r\n\r\n        //Script::PrintContents( m_created_trick[i]->mp_other_params );\r\n        //Script::PrintContents( m_created_trick[i]->mp_rotations );\r\n    }\r\n\r\n    Script::RunScript(CRCD(0x33fe5817,\"kill_load_premade_cats\"), NULL);\r\n}\r\n\r\nvoid CSkater::AddStatGoalInfo(Script::CStruct *pStuff)\r\n{\r\n    Dbg_MsgAssert(pStuff,(\"NULL pStuff\"));\r\n\t\r\n    Script::CArray *p_stat_goals=new Script::CArray;\r\n    p_stat_goals->SetSizeAndType(Obj::NUM_STATS_GOALS,ESYMBOLTYPE_INTEGER);\r\n    \r\n    for (int i=0; i<Obj::NUM_STATS_GOALS; ++i)\r\n    {\r\n        p_stat_goals->SetInteger(i,mp_stats_manager_component->StatGoalGetStatus(i));\r\n    }\r\n    pStuff->AddArrayPointer(CRCD(0x44b66a9f,\"StatGoals\"),p_stat_goals);\r\n}\r\n\r\nvoid CSkater::LoadStatGoalInfo(Script::CStruct *pStuff)\r\n{\r\n    Dbg_MsgAssert(pStuff,(\"NULL pStuff\"));\r\n\r\n    // Reset Stats Goals and set to proper difficulty\r\n    Script::CStruct* p_params = NULL;\r\n    mp_stats_manager_component->RefreshFromStructure(p_params);\r\n\r\n    Script::CArray *pStatGoalInfo=NULL;\r\n    pStuff->GetArray(CRCD(0x44b66a9f,\"StatGoals\"),&pStatGoalInfo);\r\n\r\n    for (int i=0; i<Obj::NUM_STATS_GOALS; ++i)\r\n    {\r\n        mp_stats_manager_component->StatGoalSetStatus(i,pStatGoalInfo->GetInteger(i));\r\n    }\r\n}\r\n\r\nvoid CSkater::AddChapterStatusInfo(Script::CStruct *pStuff)\r\n{\r\n    Dbg_MsgAssert(pStuff,(\"NULL pStuff\"));\r\n\t\r\n    pStuff->AddArray(CRCD(0x8e8ee0c0,\"ChapterStatus\"),Script::GetArray( CRCD(0xdfa17d68,\"CHAPTER_STATUS\"), Script::ASSERT ));\r\n}\r\n\r\nvoid CSkater::LoadChapterStatusInfo(Script::CStruct *pStuff)\r\n{\r\n    Dbg_MsgAssert(pStuff,(\"NULL pStuff\"));\r\n\r\n\tuint32 Name = Script::GenerateCRC(\"ChapterStatus\");\r\n    Script::CArray *pChapterStatusInfo=NULL;\r\n    pStuff->GetArray(Name,&pChapterStatusInfo);\r\n\r\n    Script::CopyArray(Script::GetArray( CRCD(0xdfa17d68,\"CHAPTER_STATUS\"), Script::ASSERT ), pChapterStatusInfo);\r\n}\r\n\r\n} // namespace Obj\r\n"
  },
  {
    "path": "Code/Sk/Objects/skater.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObject (OBJ)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobjects/skater.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t01/25/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __OBJECTS_SKATER_H\r\n#define __OBJECTS_SKATER_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\n#include <core/math/vector.h>\r\n#include <core/math/matrix.h>\r\n#include <core/string/cstring.h>\r\n// #include <core/timestampedflag.h>\r\n\r\n// #include <sk/objects/skaterflags.h>\r\n\r\n// #include <sk/objects/gap.h>\r\n// #include <sk/objects/manual.h>\r\n#include <sk/objects/movingobject.h>\r\n#include <sk/objects/trickobject.h>\r\n// #include <sk/objects/skaterpad.h>\r\n\r\n// #include <sys/timer.h>\r\n\r\n#include <gel/inpman.h>\r\n// #include <gel/net/net.h>\r\n\r\n#include <sk/modules/skate/score.h>\r\n#include <sk/modules/skate/createatrick.h>\r\n\r\n#include <gel/objptr.h>\r\n\r\n#define\t\tSNAP_OVER_THIN_WALLS  \t// snap over thin walls (like rails)\r\n#define\t\tSTICKY_WALLRIDES\t\t // attempt to snap sideways to wallrides\r\n\r\n// temp debug macros\r\n#define MESSAGE(a) { printf(\"M:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPI(a) { printf(\"D:%s:%i: \" #a \" = %i\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPB(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, a ? \"true\" : \"false\"); }\r\n#define DUMPF(a) { printf(\"D:%s:%i: \" #a \" = %g\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPE(a) { printf(\"D:%s:%i: \" #a \" = %e\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPS(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPP(a) { printf(\"D:%s:%i: \" #a \" = %p\\n\", __FILE__ + 15, __LINE__, a); }\r\n#define DUMPC(a) { printf(\"D:%s:%i: \" #a \" = %s\\n\", __FILE__ + 15, __LINE__, Script::FindChecksumName(a)); }\r\n#define DUMPV(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z]); }\r\n#define DUMP4(a) { printf(\"D:%s:%i: \" #a \" = %g, %g, %g, %g\\n\", __FILE__ + 15, __LINE__, (a)[X], (a)[Y], (a)[Z], (a)[W]); }\r\n#define DUMPM(a) { DUMP4(a[X]); DUMP4(a[Y]); DUMP4(a[Z]); DUMP4(a[W]); }\r\n#define MARK { printf(\"K:%s:%i: %s\\n\", __FILE__ + 15, __LINE__, __PRETTY_FUNCTION__); }\r\n#define PERIODIC(n) for (static int p__ = 0; (p__ = ++p__ % (n)) == 0; )\r\n\r\n#define RED MAKE_RGB(255, 0, 0)\r\n#define GREEN MAKE_RGB(0, 255, 0)\r\n#define BLUE MAKE_RGB(0, 0, 255)\r\n#define YELLOW MAKE_RGB(200, 200, 0)\r\n#define PURPLE MAKE_RGB(200, 0, 200)\r\n#define CYAN MAKE_RGB(0, 200, 200)\r\n\r\n// skater specific debug defines\r\n#ifdef __NOPT_ASSERT__\r\n#define HEADER { printf(\"%i:%s:%i: \", Tmr::GetRenderFrame(), __FILE__ + 15, __LINE__); }\r\n#define DUMP_VELOCITY { if (Script::GetInteger(CRCD(0x71f0478a, \"debug_skater_vel\"))) { HEADER; printf(\"m_vel = %g, %g, %g (%g)\\n\", GetObject()->m_vel[X], GetObject()->m_vel[Y], GetObject()->m_vel[Z], GetObject()->m_vel.Length()); } }\r\n#define DUMP_POSITION { if (Script::GetInteger(CRCD(0x029ade47, \"debug_skater_pos\"))) { HEADER; printf(\"m_pos = %g, %g, %g\\n\", GetObject()->m_pos[X], GetObject()->m_pos[Y], GetObject()->m_pos[Z]); } }\r\n#define DUMP_SPOSITION { if (Script::GetInteger(CRCD(0x029ade47, \"debug_skater_pos\"))) { HEADER; printf(\"m_pos = %g, %g, %g\\n\", m_pos[X], m_pos[Y], m_pos[Z]); } }\r\n#else\r\n#define DUMP_VELOCITY {   }\r\n#define DUMP_POSITION {   }\r\n#define DUMP_SPOSITION {   }\r\n#endif\r\n\r\n// if uncommented here, uncomment in skaterpad.cpp too\t\t\t\t\t\t\t\t   \r\n//#define\t\tPS2_SIMULATING_XBOX\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n\t#ifdef\tPS2_SIMULATING_XBOX\r\n\t\t#define\tBREAK_SPINE_BUTTONS (control_pad.m_L2.GetPressed() && control_pad.m_R2.GetPressed())\r\n\t\t#define\tWALK_SPINE_BUTTONS (control_pad.m_L2.GetPressed() && control_pad.m_R2.GetPressed())\r\n\t#else\t\r\n\t\t#define\tBREAK_SPINE_BUTTONS (control_pad.m_L2.GetPressed() || control_pad.m_R2.GetPressed())\r\n\t\t#define\tWALK_SPINE_BUTTONS (control_pad.m_R2.GetPressed())\r\n\t#endif\r\n#endif\r\n\r\n#ifdef\t__PLAT_XBOX__\r\n#define\tBREAK_SPINE_BUTTONS (control_pad.m_L2.GetPressed() && control_pad.m_R2.GetPressed())\r\n#define\tWALK_SPINE_BUTTONS (control_pad.m_L2.GetPressed() && control_pad.m_R2.GetPressed())\r\n#endif\r\n\r\n#ifdef\t__PLAT_NGC__\r\n#define\tBREAK_SPINE_BUTTONS (control_pad.m_L1.GetPressed() && control_pad.m_R1.GetPressed())\r\n#define\tWALK_SPINE_BUTTONS (control_pad.m_L1.GetPressed() && control_pad.m_R1.GetPressed())\r\n#endif\r\n\r\n\r\n#define\tVERT_RECOVERY_BUTTONS (BREAK_SPINE_BUTTONS)\r\n\r\n// #define\tUSE_BIKE_PHYSICS (Script::GetInteger(CRCD(0x9e86d1c1,\"use_bike_physics\")))\r\n// #define\tUSE_WALK_PHYSICS (Script::GetInteger(CRCD(0x9ae06a83,\"use_walk_physics\")))\r\n// #define\tCESS_SLIDE_BUTTONS (control_pad.m_R1.GetPressed() && USE_BIKE_PHYSICS)\r\n\r\n#define\tSKITCH_BUTTON (control_pad.m_up.GetPressed() && control_pad.m_up.GetPressedTime()>(uint32)GetPhysicsInt(CRCD(0x19b2c752,\"Skitch_Hold_Time\")))\r\n\r\n// These are defined here, so they can easily be switched from\t\r\n// script flags to some more general cheat flags\r\n//#define\t\tCHEAT_SNOWBOARD\t\t(control_pad.m_R1.GetPressed()) //   (GetPhysicsInt(\"CheatSnowBoard\",false) || GetCheat(GetPhysicsInt(0x9bc667b5)))  //CHEAT_SNOWBOARD\r\n#define\t\tCHEAT_SNOWBOARD\t\t0\t//(GetPhysicsInt(\"CheatSnowBoard\",false) || GetCheat(GetPhysicsInt(0x9bc667b5)))  //CHEAT_SNOWBOARD\r\n#define\t\tCHEAT_MATRIX\t\t(Mdl::Skate::Instance()->GetCareer()->GetPhysicsInt(CRCD(0xc41d8a34,\"CheatMatrix\"),false)  || GetCheat(GetPhysicsInt(0xf9514c9e)))\t  // CHEAT_MATRIX\r\n#define\t\tCHEAT_FIRST_PERSON\t0//(GetPhysicsInt(\"CheatFirstPerson\",false)  || GetCheat(GetPhysicsInt(0xca459091))) // CHEAT_FIRST_PERSON\r\n#define\t\tCHEAT_PERFECT_RAIL\t (Mdl::Skate::Instance()->GetCareer()->GetCheat(GetPhysicsInt(0xcd09e062)))\t  // CHEAT_PERFECT_RAIL\r\n#define\t\tCHEAT_PERFECT_MANUAL (Mdl::Skate::Instance()->GetCareer()->GetCheat(GetPhysicsInt(0xb38341c9)))\t  // CHEAT_PERFECT_MANUAL\r\n#define\t\tCHEAT_PERFECT_SKITCH (Mdl::Skate::Instance()->GetCareer()->GetCheat(GetPhysicsInt(0x69a1ce96)))\t  // CHEAT_PERFECT_SKITCH\r\n\r\n#define\t\tCHEAT_STATS_13   (Mdl::Skate::Instance()->GetCareer()->GetCheat(GetPhysicsInt(0x6b0f24bc)))  \r\n#define\t\tCHEAT_KID        0//(GetCheat(GetPhysicsInt(0x406e5a16))) \r\n#define\t\tCHEAT_SIM        (Mdl::Skate::Instance()->GetCareer()->GetCheat(GetPhysicsInt(0x2b87107a)))  \r\n#define\t\tCHEAT_MOON       (Mdl::Skate::Instance()->GetCareer()->GetCheat(GetPhysicsInt(0x9c8c6df1)))  \r\n\r\n#define\t\tCHEAT_SLOMO\t\t(Mdl::Skate::Instance()->GetCareer()->GetCheat(GetPhysicsInt(0xf163e7e0)))\t\t// CHEAT_SLOMO\r\n#define\t\tCHEAT_DISCO\t\t(Mdl::Skate::Instance()->GetCareer()->GetCheat(GetPhysicsInt(0x9fc22bda)))\t\t// CHEAT_DISCO\r\n\r\n////////////////////////////////////////////////////////////////////////\r\n// The following #defines generally enable a bunch of prints\r\n// that track the changes in value or state of a particular \r\n// aspect of the physics.\r\n// Some of them will also display debugging lines\r\n//\r\n\r\n\r\n//#define\tDEBUG_WALKING\r\n//#define\tDEBUG_ACC_LINES\r\n//#define\tDEBUG_INSIDE_OBJECT\r\n//#define\tDEBUG_SKITCHING\r\n//#define\tDEBUG_BOUNCE_OFF_WALL\r\n//#define\tDEBUG_WALLRIDE\r\n//#define\tDEBUG_VELOCITY\r\n//#define\tDEBUG_POSITION\r\n//#define\tDEBUG_SPINE\r\n//#define\tSHOW_MOVEMENT_LINES\r\n//#define\tDEBUG_UBERFRIG\r\n//#define\tDEBUG_DISPLAY_MATRIX\r\n//#define\tDEBUG_MATRIX\r\n//#define\tDEBUG_COL_FLAGS \r\n//#define\tDEBUG_RAILS\r\n//#define\tDEBUG_TERRAIN\r\n//#define\tDEBUG_AIR_SNAP_UP\r\n//#define\tDEBUG_SHOW_ALL_COLLISION_LINES\r\n//#define\tDEBUG_SHOW_SIDE_PUSH_LINES\r\n//#define\tDEBUG_TRIGGERS\r\n//#define\tDEBUG_GAPS\r\n//#define\tDEBUG_STATES\r\n//#define\tDEBUG_VERT\r\n//#define\tDEBUG_RECOVER\r\n//#define\tDEBUG_BRAKE\r\n//#define\tDEBUG_FRICTION\r\n//#define\tDEBUG_HIGH_SCORE_GOALS\r\n\t\t\t\t\t   \r\n#define\t\tSTOPPED_TURN_RAMP_TIME\t\t600\t\t// ms ramp time for turning when stopped\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t   Forward Declarations\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n// These are for network games\r\n#define vNUM_LAG_FRAMES\t1.0f\r\n#define vFORCE_SEND_INTERVAL\t15\t// every 15 frames, send a full network object update\r\n\r\nclass\tCContact;\r\n\r\nnamespace Script\r\n{\r\n\tclass CComponent;\r\n}\r\n\t\r\nnamespace Mdl\r\n{\r\n\tclass Skate;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\tclass CCollCache;\r\n}\r\n\r\nnamespace Gfx\r\n{\r\n\tclass\tCamera;\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\tclass \tCRailNode;\t\t\t\t\t\t\t   \r\n\tclass \tCSkaterProfile;\r\n\tclass\tCMovieManager;\r\n\r\n\tclass\tCTrickBufferComponent;\r\n\t\r\n\tclass\tCAnimationComponent;\r\n\tclass\tCModelComponent;\r\n\tclass\tCShadowComponent;\r\n\tclass\tCTrickComponent;\r\n\tclass\tCTriggerComponent;\r\n\tclass\tCInputComponent;\r\n\tclass\tCSkaterCameraComponent;\r\n\tclass\tCVibrationComponent;\r\n\tclass\tCSkaterSoundComponent;\r\n\tclass\tCSkaterGapComponent;\r\n\tclass\tCSkaterRotateComponent;\r\n\tclass\tCSkaterScoreComponent;\r\n\tclass\tCSkaterStateHistoryComponent;\r\n\tclass\tCSkaterCorePhysicsComponent;\r\n\tclass\tCSkaterPhysicsControlComponent;\r\n\tclass\tCWalkComponent;\r\n    class\tCStatsManagerComponent;\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nenum EViewMode\r\n{\r\n\tGAMEPLAY_SKATER_ACTIVE,\r\n\tVIEWER_SKATER_PAUSED,\r\n\tVIEWER_SKATER_ACTIVE,\r\n\tNUM_VIEW_MODES\r\n};\r\n\r\n#define MAX_TRICK_NAME_CHARS 50\r\n\r\n// Used for storing any info needed to restore the skater after it is\r\n// hidden during a replay.\r\n// Doesn't contain much at the moment.\r\nclass CSkaterModelRestorationInfo\r\n{\r\npublic:\r\n\t//bool mShadowOn;\r\n\tMth::Vector mPreReplayPos;\r\n\tMth::Matrix mPreReplayDisplayMatrix;\r\n\tuint32 mAtomicStates;\r\n};\r\n\r\nclass  CSkater : public  CMovingObject \r\n{\r\n\tfriend class Mdl::Skate;\r\n\r\npublic:\r\n\r\n\tvoid DodgyTest();\r\n\r\n\tenum\tEPushStyle\r\n\t{\r\n\t\tvNEVER_MONGO = 0x8b966093,\t\t\t// \"never_mongo\"\r\n\t\tvALWAYS_MONGO = 0x16c6df0b,\t\t\t// \"always_mongo\"\r\n\t\tvMONGO_WHEN_SWITCH = 0x0cdba4f9\t\t// \"mongo_when_switch\"\r\n\t};\r\n\r\n\tenum\tEStat\r\n\t{\r\n\t\tSTATS_AIR = 0,\r\n\t\tSTATS_RUN,\r\n\t\tSTATS_OLLIE,\r\n\t\tSTATS_SPEED,\r\n\t\tSTATS_SPIN,\r\n\t\tSTATS_FLIPSPEED,\r\n\t\tSTATS_SWITCH,\r\n\t\tSTATS_RAILBALANCE,\r\n\t\tSTATS_LIPBALANCE,\r\n\t\tSTATS_MANUAL,\t\r\n\t\t\t   \r\n\t\tNUM_ESTATS\r\n\t};\r\n\r\n///////////////////////////////////////////////////////////////////////////////////////////////\t\r\n// Player specific\t\r\npublic:\r\n\tvoid\t\t\t\t\t\tUpdateStats( Obj::CSkaterProfile* pSkaterProfile );\r\n\tvoid \t\t\t\t\t\tUpdateSkaterInfo( Obj::CSkaterProfile* pSkaterProfile );\r\n\tfloat\t\t\t\t\t\tGetStat(EStat stat);\r\n\tvoid\t\t\t\t\t\tSetStat(EStat stat, float value);\r\n\tfloat \t\t\t\t\t\tGetStattedValue(const char *pName, EStat stat);\r\n\tfloat \t\t\t\t  \t  \tGetScriptedStat(Script::CStruct *pSS);\r\n\tfloat\t\t\t\t\t\tGetScriptedStat(const uint32 checksum);\r\n\tfloat \t\t\t\t\t\tGetScriptedStat(uint32 Checksum, Script::CStruct *pSetOfStats);\r\n\t// float\t\t\t\t\t\tGetHeight();\r\n\t\t\t\t\t\t\t   \r\n\t// Here's some data that needs to be stored\r\n\t// from the skater profile, in case various\r\n\t// scripts ask for it\r\n\tuint32\tm_pushStyle;\r\n\tbool\tm_isGoofy;\r\n\tbool\tm_isPro;\r\n\tint\t\tm_isMale;\r\n\r\n\tenum\r\n\t{\r\n\t\tMAX_LEN_FIRST_NAME = 64\r\n\t};\r\n\r\n\tchar\tm_firstName[MAX_LEN_FIRST_NAME];\r\n\r\n\t// Name of the skater, eg Hawk, Caballero, etc.\r\n\t// Grabbed from the skater profile.\r\n\tuint32\tm_skaterNameChecksum;\r\n\tStr::String\tm_displayName;\r\n\r\nprotected:\r\n\t\r\n\tCSkaterModelRestorationInfo m_model_restoration_info;\r\n\t\r\npublic :\r\n\tCSkater ( int player_num, CBaseManager* p_obj_man, bool local_client, int obj_id, int heap_num, bool should_tristrip);\r\n\tvirtual\t\t\t\t\t\t~CSkater ( void );\r\n\r\n\t// void HideForReplayPlayback();\r\n\t// void RestoreAfterReplayPlayback();\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n// Sub Games\r\n\t\r\npublic:\r\n\tbool\t\t\t\t\t\tm_always_special;\r\n\r\n///////////////////////////////////////////////////////////////////////////////////////////////\r\n// Kind of redundant\t\r\npublic:\r\n\tvoid\t\t\t\t\t\tRemoveFromCurrentWorld( void );\r\n\tvoid\t\t\t\t\t\tAddToCurrentWorld ( void );\r\n\tbool\t\t\t\t\t\tIsInWorld( void );\r\n\t\r\n///////////////////////////////////////////////////////////////////////////////////////////\r\n// fundamental  to both skater and physics\t\r\npublic:\r\n\tvirtual void \t\t\t\tPause();\r\n\tvirtual void \t\t\t\tUnPause();\r\n\tvirtual bool\t\t\t\tCallMemberFunction( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript ); \r\n\tvirtual void \t\t\t\tInit(Obj::CSkaterProfile* pSkaterProfile);\r\n\r\nprotected :\r\n\tvoid \t\t\t\t\t\tConstruct(Obj::CSkaterProfile* pSkaterProfile);\r\n\tbool _function0( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript );\r\n\tbool _function1( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\n///////////////////////////////////////////////////////////////////////////////////\r\n// Network\r\n\r\npublic:\r\n\tvoid\tResync( void );\r\nprotected:\r\n\r\n\tint\t\t\t\t\t\t\tm_last_restart_node;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////\r\n// Rendering related\r\npublic:\r\n\tMth::Matrix&\t\t\t\tGetDisplayMatrix( void );\r\n\tvoid\t\t\t\t\t\tSetDisplayMatrix( Mth::Matrix& matrix );\r\n\t\r\nprotected:\r\n\t// True if sparks will be automatically switched off when\r\n\t// the skater comes off a rail.\r\n\tbool mSparksRequireRail;\r\n\tbool mSparksOn;\r\n\tvoid SparksOff();\r\n\tvoid SparksOn();\r\n\r\n\t// The skater's shadow will move beneath him (if directional) when he is in the air.\r\n\tint\t\t\tm_air_timer;\r\n\t\r\n//////////////////////////////////////////////////////////////////////////////////////////////\r\n// high level accessors\t\r\npublic:\r\n\tint\t\t\t\t\t\t\tGetHeapIndex( void );\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Level gameplay related\r\npublic:\r\n\tvoid\t\t\t\t\t\tMoveToRandomRestart( void );\r\n\tvirtual void\t\t\t\tReset();\r\n\tvirtual void\t\t\t\tSkipToRestart(int node, bool walk=false);\r\n\tvirtual void\t\t\t\tMoveToRestart(int node);\r\n\r\n// should be private:\t\r\n\t// Dan: I'd like to remove this, but it's still used by CEmiter, which is skater specific and does not\r\n\t// currently use ProximTriggerComponents\r\n\tbool\t\t\t\t\t\tm_inside;\t\t// flag set up by proxim node triggering\r\n\r\n\r\nprotected:\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Misc\r\npublic:\r\n\tLst::Node< CSkater >*\t\tGetLinkNode( void );\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n// Tricks \r\npublic:\t\r\n    // CreateATrick \r\n    Game::CCreateATrick* m_created_trick[Game::vMAX_CREATED_TRICKS];\r\n    void\t\t\t\t\tAddCATInfo(Script::CStruct *pStuff);\r\n    void\t\t\t\t\tLoadCATInfo(Script::CStruct *pStuff);\r\n    int                     m_num_cat_animations_on;\r\n    bool                    m_cat_bail_done;\r\n    bool                    m_cat_flip_skater_180;\r\n    bool                    m_cat_animations_done;\r\n    bool                    m_cat_rotations_done;\r\n    float                   m_cat_hold_time;\r\n    int                     m_cat_total_x;\r\n    int                     m_cat_total_y;\r\n    int                     m_cat_total_z;\r\n    // Stat Goals\r\n    void\t\t\t\t\tAddStatGoalInfo(Script::CStruct *pStuff);\r\n    void\t\t\t\t\tLoadStatGoalInfo(Script::CStruct *pStuff);\r\n    // Chapter Status\r\n    void\t\t\t\t\tAddChapterStatusInfo(Script::CStruct *pStuff);\r\n    void\t\t\t\t\tLoadChapterStatusInfo(Script::CStruct *pStuff);\r\n\t\r\npublic:\r\n////////////////////////////////////////////////////////////////////////////////\r\n// script\r\n\r\n\tvoid\tJumpToScript(uint32 ScriptChecksum, Script::CStruct *pParams=NULL);\r\n\tvoid\tJumpToScript(const char *pScriptName, Script::CStruct *pParams=NULL);\r\n\r\nprotected :\r\n\t\r\n\tvoid UpdateCamera(bool instantly = false);\r\n\tvoid UpdateCameras( bool instantly );\r\n\t\r\npublic:\r\n\t\r\n\tvoid DeleteResources(void);\r\n\tvoid ResetPhysics(bool walk=false,bool in_cleanup=false);\r\n\tvirtual void ResetStates();\r\n\tvirtual void ResetAnimation();\t\t  \r\n\tvirtual void ResetInitScript(bool walk, bool in_cleanup);\r\n\r\nprotected:\r\n\t// Moved this from the CMovingObject class\r\n\t// since we're trying to remove functionality\r\n\t// from the moving object class, and because\r\n\t// the skater was the only thing that was\r\n\t// calling it...\r\n\tvoid MovingObj_Reset( void );\r\n\r\npublic:\t\r\n\tvoid UpdateShadow(const Mth::Vector& pos, const Mth::Matrix& matrix);\r\n\t// K: Added for use by replay code so that it can playback pad vibrations\r\n\tSIO::Device *GetDevice();\r\n\r\nprotected:\r\n\r\n\tLst::Node< CSkater >\t\tm_link_node;\t\t\t// linked list node for list of skaters\r\n\r\n\t// pointers to oft used components of the skater\r\n\tCAnimationComponent*\t\t\tmp_animation_component;\r\n\tCModelComponent*\t\t\t\tmp_model_component;\r\n\tCShadowComponent*\t\t\t\tmp_shadow_component;\r\n\tCTrickComponent*\t\t\t\tmp_trick_component;\r\n\tCVibrationComponent*\t\t\tmp_vibration_component;\r\n\tCTriggerComponent*\t\t\t\tmp_trigger_component;\r\n\tCInputComponent*\t\t\t\tmp_input_component;\r\n\tCSkaterSoundComponent*\t\t\tmp_skater_sound_component;\r\n\tCSkaterGapComponent*\t\t\tmp_skater_gap_component;\r\n\tCSkaterRotateComponent*\t\t\tmp_skater_rotate_component;\r\n\tCSkaterScoreComponent*\t\t\tmp_skater_score_component;\r\n\tCSkaterStateHistoryComponent*\tmp_skater_state_history_component;\r\n\tCSkaterCorePhysicsComponent*\tmp_skater_core_physics_component;\r\n\tCSkaterPhysicsControlComponent* mp_skater_physics_control_component;\r\n\tCWalkComponent*\t\t\t\t\tmp_walk_component;\r\n    CStatsManagerComponent*\t\t\tmp_stats_manager_component;\r\n\t\r\npublic:\r\n\t// allow external code rapid access to these components\r\n\tCSkaterStateHistoryComponent*\tGetStateHistory (   )\r\n\t{\r\n\t\tDbg_Assert(mp_skater_state_history_component);\r\n\t\treturn mp_skater_state_history_component;\r\n\t}\r\n\t\r\nprotected:\r\n\t\r\n\tfloat\t\t\t\t\t\tm_stat[NUM_ESTATS];\t \t// all the stats\r\n\r\n\tint\t\t\t\t\t\t\tm_heap_index;\t\t\t// Which skater heap is this skater using\r\n\t\t\t\t\t\t\t\t\t\t\t \r\n\tbool\t\t\t\t\t\tm_local_client;\t\t\t// Is this cient being controlled by my PS2\r\n\r\n\t\r\n\tint\t\t\t\t\t\t\tm_skater_number;\t\t// 0 or 1 (maybe 2 or 3) \t  \r\n\r\n\tint\t\t\t\t\t\t\tm_viewing_mode;\t\t\t\t\t// 0 = normal, 1 = frozen, move cam, 2 = move, freeze cam\r\n\t\r\npublic:\t\r\n\tint\t\t\t\t\t\t\tGetViewingMode (   ) { return m_viewing_mode; }\r\n\t\r\nprotected:\t\r\n\t// is the skater in the world?\r\n\tbool\t\t\t\t\t\tm_in_world;\r\n\t\r\n\t// For custom restart point\r\n\t\r\n\tMth::Vector\t\t\t\t\tm_restart_pos;\r\n\tMth::Matrix\t\t\t\t\tm_restart_matrix;\r\n\tbool\t\t\t\t\t\tm_restart_walking;\r\n\tbool\t\t\t\t\t\tm_restart_valid;\r\n\t\r\npublic:\t\r\n\r\n\tconst char*\tGetDisplayName();\r\n\tvoid\t\tSetAlwaysSpecial(bool on) {m_always_special = on;}\r\n\tvoid\t\tToggleAlwaysSpecial() {m_always_special = !m_always_special;}\r\n\r\n\t// this used to be in the skater profile, but I changed it\r\n\t// because it was confusing when called from multiplayer games.\r\n\tbool\t\tSkaterEquals( Script::CStruct* pParams );\r\n\r\npublic:\r\n\t// Returns a pointer to this skater's score object.\r\n\tMdl::Score *GetScoreObject();\r\n\tbool\tIsLocalClient() {return m_local_client;}\r\n\r\n\tint\t\tGetSkaterNumber() {return m_skater_number;}\r\n\t\r\n\tGfx::Camera *GetActiveCamera( void );\r\n\t\r\n\tCCompositeObject* CSkater::GetCamera (    );\r\n\r\n\tvoid    SetViewMode( EViewMode view_mode );\r\n\tint\t\tGetViewMode() { return m_viewing_mode; }\r\n\t\r\n\t// hack to allow the collision radius to be adjusted while in a car\r\n\tfloat\tm_rigid_body_collision_radius_boost;\r\n\tvoid\tSetRigidBodyCollisionRadiusBoost ( float rigid_body_collision_radius_boost ) { m_rigid_body_collision_radius_boost = rigid_body_collision_radius_boost; }\r\n\tvoid\tResetRigidBodyCollisionRadiusBoost (   ) { m_rigid_body_collision_radius_boost = 0.0f; }\r\n\tfloat\tGetRigidBodyCollisionRadiusBoost (   ) { return m_rigid_body_collision_radius_boost; }\r\n\r\n\tfriend class CSkaterCam;\r\n\t\r\n\tfriend class CSkaterCameraComponent;\r\n\tfriend class CTrickComponent;\r\n\tfriend class CSkaterLoopingSoundComponent;\r\n\tfriend class CSkaterSoundComponent;\r\n\tfriend class CSkaterGapComponent;\r\n\tfriend class CSkaterRotateComponent;\r\n\tfriend class CSkaterLocalNetLogicComponent;\r\n\tfriend class CSkaterNonLocalNetLogicComponent;\r\n\tfriend class CSkaterScoreComponent;\r\n\tfriend class CSkaterMatrixQueriesComponent;\r\n\tfriend class CSkaterStateHistoryComponent;\r\n\tfriend class CSkaterPhysicsControlComponent;\r\n\tfriend class CSkaterCorePhysicsComponent;\r\n\tfriend class CSkaterAdjustPhysicsComponent;\r\n\tfriend class CSkaterFinalizePhysicsComponent;\r\n\tfriend class CSkaterCleanupStateComponent;\r\n\tfriend class CSkaterFlipAndRotateComponent;\r\n\t\r\nprivate:\r\n\t// skater physics variables beyond those inherited from CCompositeObject\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\nextern bool DebugSkaterScripts;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint GetPhysicsInt(const char *p_name, Script::EAssertType assert = Script::NO_ASSERT);\r\nint GetPhysicsInt(uint32 id, Script::EAssertType assert = Script::NO_ASSERT);\r\nfloat GetPhysicsFloat(const char *p_name, Script::EAssertType assert = Script::NO_ASSERT);\r\nfloat GetPhysicsFloat(uint32 id, Script::EAssertType assert = Script::NO_ASSERT);\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_SKATER_H\r\n"
  },
  {
    "path": "Code/Sk/Objects/skatercam.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       skatercam.cpp\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/05/2001\r\n//****************************************************************************\r\n\r\n/*\r\n\r\n(Mick) \r\nProblem:\r\n\r\nIf you stop, and then jump in place while holding \"down\", you will lean backwards while \r\nyou jump.  This will not really be noticable, but when you land, the camera will seem to \r\nsnap backwards for a single frame\r\n\r\nthe problem was m_display_matrix is lagging behind\r\nso I have patched it by setting skater_up to mpSkate->m_display_normal when on the ground\r\nthis fixes it for the skater glitching, however the world around him is still glitching\r\nas the angle still changes abruptly\r\n\r\none fix might be to somehow smoothly interpolate this angle , which might also help \r\nwith any fix we do for skating off ledges\r\n\r\nI need to clean up and comment this code, so it can be modified without fear.....\r\n\r\n\r\n*/\r\n\r\n\r\n//#define\tDEBUG_CAMERA\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <gel/mainloop.h>\r\n\r\n#include <core/math/slerp.h>\r\n\r\n#include <objects/skater.h>\r\n#include <objects/skaterflags.h>\r\n#include <objects/skatercam.h>\r\n#include <components/skatercorephysicscomponent.h>\r\n#include <components/skaterbalancetrickcomponent.h>\r\n#include <components/skaterstatecomponent.h>\r\n#include <gfx/nxviewman.h>\r\n#include <gfx/debuggfx.h>\r\n\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/components/movablecontactcomponent.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\r\n\t\t\r\nstatic void _xrotlocal ( Mth::Matrix& m, float a )\r\n{\r\n\tm.RotateXLocal( a );\r\n}\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\tconst float LEAN_TO_SKATERCAM_LEAN\t= (( Mth::PI / 6.0f ) / -4096.0f );\r\n\tconst float\tSKATERCAM_INTERPOLATOR_TIMESTEP = ( 1.0f / 60.0f );\r\n\r\n\tconst float VERT_AIR_LANDED_TIME\t= 10.0f / 60.0f;\r\n\tconst float TILT_MAX\t\t\t\t= 0.34907f;\t\t\t\t\t\t// 20 degees.\r\n\tconst float TILT_MIN\t\t\t\t= -0.34907f;\t\t\t\t\t// -20 degees.\r\n\tconst float TILT_INCREMENT\t\t\t= 2.0f * ( TILT_MAX / 60.0f );\t// 40 degrees/second.\r\n\tconst float TILT_DECREMENT\t\t\t= 2.0f * ( TILT_MAX / 60.0f );\t// 40 degrees/second.\r\n\tconst float TILT_RESTORE\t\t\t= 8.0f * ( TILT_MAX / 60.0f );\t// 160 degrees/second.\r\n\r\n\t// This is the value that mAbove should tend to when the behind value is closer than mBehind.\r\n\tconst float PERFECT_ABOVE = 3.0f;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCam::s_input_logic_code( const Inp::Handler < CSkaterCam >& handler )\r\n{    \r\n    Dbg_AssertType( &handler, Inp::Handler< CSkaterCam > );\r\n\t\r\n\tbool skip_button;\r\n\tbool right_button;\r\n\tint right_x;\r\n\tint right_y;\r\n\r\n    CSkaterCam&\tobj = handler.GetData();\r\n\t\r\n\tif ( obj.mpSkater && !obj.mpSkater->IsLocalClient( ) )\r\n\t{\r\n\t\tobj.mSkipButton = handler.m_Input->m_Makes & ( Inp::Data::mD_X );\r\n\t\tobj.mRightButton = handler.m_Input->m_Makes & ( Inp::Data::mD_R3 );\r\n\t\tobj.mRightX = handler.m_Input->m_Event[Inp::Data::vA_RIGHT_X] - 128;\r\n\t\tobj.mRightY = handler.m_Input->m_Event[Inp::Data::vA_RIGHT_Y] - 128;\r\n\t}\r\n\tskip_button = obj.mSkipButton;\r\n\tright_button = obj.mRightButton;\r\n\tright_x = obj.mRightX;\r\n\tright_y = obj.mRightY;\r\n\r\n\tif (obj.m_input_enabled)\r\n\t{\r\n\t\tif( right_button )\r\n\t\t{\r\n\t\t\tobj.mLookaroundLock = !obj.mLookaroundLock;\r\n\t\t}\r\n\t\r\n\t\tif( !obj.mLookaroundLock && !obj.mLookaroundOverride )\r\n\t\t{\r\n\t\t\t// We want this to map to (PI/2, ~-2PI/10). Switched this 7/10/01 to be opposite up/down to previously.\r\n\t\t\tfloat target = ((float)(( right_y < 0 ) ? right_y : ( 0.4f * right_y ))) * ( -1.4f / 128.0f );\r\n\t\t\tobj.mLookaroundTilt += ( target - obj.mLookaroundTilt ) * 0.0625f;\r\n\t\r\n\t\t\t// We want this to map to (-~PI, ~PI).\r\n\t\t\ttarget = ((float)right_x ) * ( 3.0f / 128.0f );\r\n\t\t\tobj.mLookaroundHeading\t+= ( target - obj.mLookaroundHeading ) * 0.0625f;\r\n\t\t}\r\n\t\r\n/*\t\tHey -- Let's not mask these since I need to read them in the player's s_input_logic function\r\n\t\tfor replay stuff.  Thanks.  If it breaks something please tell me.  Love Matt\r\n\t\t// Mask off analog right stick input.\r\n\t\thandler.m_Input->MaskDigitalInput( Inp::Data::mD_R3 );\r\n\t\thandler.m_Input->MaskAnalogInput( Inp::Data::mA_RIGHT_X );\r\n\t\thandler.m_Input->MaskAnalogInput( Inp::Data::mA_RIGHT_Y );\r\n*/\r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPublic Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterCam::CSkaterCam( int player )\r\n{\r\n\tmMode\t= SKATERCAM_MODE_UNDEFINED;\r\n\r\n#ifdef\tDEBUG_CAMERA\r\n\tprintf (\"+++ SkaterCam Created ..........................\\n\");\t\t\t\t  \r\n#endif\r\n\t\t\t\t  \r\n\t// Create the SLERP interpolator here.\r\n\tmpSlerp = new Mth::SlerpInterpolator;\r\n\r\n\t// Set current zoom and LERP rates.\r\n\tmCurrentZoom\t\t= 1.0f;\r\n\tmZoomLerp\t\t\t= 0.0625f;\r\n\tmLastDot\t\t\t= 1.0f;\r\n\r\n\tmLerpXZ\t\t\t= 0.25f;\r\n\tmLerpY\t\t\t= 0.5f;\r\n\tmVertAirLerpXZ\t= 1.0f;\r\n\tmVertAirLerpY\t= 1.0f;\r\n\tmGrindLerp\t\t= 0.1f;\r\n\r\n\tmLookaroundTilt\t\t= 0.0f;\r\n\tmLookaroundHeading\t= 0.0f;\r\n\tmLookaroundZoom\t\t= 1.0f;\r\n\r\n\tInp::Manager * inp_manager = Inp::Manager::Instance();\r\n\r\n\t// Register input task.\r\n\tm_input_handler\t\t\t= new Inp::Handler< CSkaterCam >( player, s_input_logic_code, *this, Tsk::BaseTask::Node::vNORMAL_PRIORITY + 1 );\r\n//\tm_input_handler_special\t= new Inp::Handler< CSkaterCam >( player, s_input_logic_code_special, *this, Tsk::BaseTask::Node::vNORMAL_PRIORITY + 1 );\r\n\r\n\tm_input_enabled = true;\r\n\tinp_manager->AddHandler( *m_input_handler );\r\n\r\n    // clear the frame matrix\r\n    // so that future slerps make sense\r\n    Mth::Matrix& frame_matrix = Gfx::Camera::GetMatrix();\r\n    frame_matrix.Ident();\r\n\r\n\tmLastActualRight \t= frame_matrix[X];\r\n\tmLastActualUp \t\t= frame_matrix[Y];\r\n\tmLastActualAt \t\t= frame_matrix[Z];\r\n\t\r\n\tDbg_MsgAssert(false, (\"CSkaterCam is not supported.\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterCam::~CSkaterCam( void )\r\n{\r\n#ifdef\tDEBUG_CAMERA\r\n\tprintf (\"--- SkaterCam Destroyed ..........................\\n\");\t\t\t\t  \r\n#endif\r\n\r\n\tif( mpSlerp )\r\n\t{\r\n\t\tdelete mpSlerp;\r\n\t}\r\n\r\n\t#if 0\r\n\t// for cutscene camera\r\n\r\n\tif( mpCopy )\r\n\t{\r\n\t\tMem::Free( mpCopy );\r\n\t\tmpCopy = NULL;\r\n\t}\r\n\t#endif\r\n\r\n\t// Unregister input task.\r\n\tif( m_input_handler )\r\n\t{\r\n\t\tif( m_input_handler->InList() )\r\n\t\t{\r\n\t\t\tm_input_handler->Remove();\r\n\t\t}\r\n\t\tdelete m_input_handler;\r\n\t}\r\n/*\t\r\n\tif( m_input_handler_special )\r\n\t{\r\n\t\tif( m_input_handler_special->InList() )\r\n\t\t{\r\n\t\t\tm_input_handler_special->Remove();\r\n\t\t}\r\n\t\tdelete m_input_handler_special;\r\n\t}\r\n*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCam::EnableInputHandler( bool enable )\r\n{\r\n\tm_input_enabled = enable;\r\n\r\n/*\r\n\tif( enable )\r\n\t{\r\n\t\t// Remove the special handler and add the standard handler.\r\n\t\tif( m_input_handler_special->InList() )\r\n\t\t{\r\n\t\t\tm_input_handler_special->Remove();\r\n\t\t}\r\n\t\tif( !m_input_handler->InList() )\r\n\t\t{\r\n\t\t\tInp::Manager * inp_manager = Inp::Manager::Instance();\r\n\t\t\tinp_manager->AddHandler( *m_input_handler );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Remove the standard handler and add the special handler.\r\n\t\tif( m_input_handler->InList() )\r\n\t\t{\r\n\t\t\tm_input_handler->Remove();\r\n\t\t}\r\n\t\tif( !m_input_handler_special->InList() )\r\n\t\t{\r\n\t\t\tInp::Manager * inp_manager = Inp::Manager::Instance();\r\n\t\t\tinp_manager->AddHandler( *m_input_handler_special );\r\n\t\t}\r\n\r\n\t}\r\n*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCam::ResetLookAround( void )\r\n{\r\n\tmLookaroundTilt\t\t= 0.0f;\r\n\tmLookaroundHeading\t= 0.0f;\r\n\r\n\tUpdate( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// toggle between replay modes:\r\nvoid CSkaterCam::SwitchReplayMode( bool increment )  // true to increment, false to decrement\r\n{\r\n\t\r\n\tint mode = ( int )mMode;\r\n\tif ( increment )\r\n\t{\r\n\t\tmode++;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmode--;\r\n\t}\r\n\tif ( mode < SKATERCAM_FIRST_REPLAY_MODE )\r\n\t{\r\n\t\tmode = SKATERCAM_LAST_REPLAY_MODE;\r\n\t}\r\n\telse if ( mode > SKATERCAM_LAST_REPLAY_MODE )\r\n\t{\r\n\t\tmode = SKATERCAM_FIRST_REPLAY_MODE;\r\n\t}\r\n\tSetMode( ( ESkaterCamMode )mode, 0.0f );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCam::SetMode( ESkaterCamMode mode, float time )\r\n{\r\n\t\r\n\r\n#if 0\t// Garrett: This doesn't work because it doesn't check to see if the screen mode has changed\r\n\tif( mode == mMode )\r\n\t{\r\n\t\t// Nothing to do here.\r\n\t\treturn;\r\n\t}\r\n#endif\r\n\r\n\tDbg_MsgAssert( mode < SKATERCAM_NUM_MODES,( \"Bad mode\" ));\r\n\r\n\t// Obtain details for this mode.\r\n\tfloat h_fov, behind, above, tilt, origin_offset, zoom_lerp;\r\n\tconst char* p_name;\r\n\r\n\t// Obtain a pointer to the array entry for the desired mode. The array is now dependent\r\n\t// on which game mode is currently being played, 1 player, 2 player vert, or 2 player horiz.\r\n\tNx::ScreenMode screen_mode = Nx::CViewportManager::sGetScreenMode();\r\n\r\n\tScript::CArray* p_array;\r\n\r\n\tswitch( screen_mode )\r\n\t{\r\n\t\tcase Nx::vSPLIT_V:\r\n\t\t{\r\n\t\t\tp_array = Script::GetArray( \"Skater_Camera_2P_Vert_Array\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase Nx::vSPLIT_H:\r\n\t\t{\r\n\t\t\tp_array = Script::GetArray( \"Skater_Camera_2P_Horiz_Array\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t{\t\t\t\r\n\t\t\tp_array = Script::GetArray( \"Skater_Camera_Array\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t// Extra check here, since the array in physics.q may change.\r\n\tDbg_MsgAssert( mode < (int)p_array->GetSize(), ( \"Bad mode\" ));\r\n\r\n\tuint32 cs = p_array->GetNameChecksum( mode );\r\n\tScript::CScriptStructure* p_struct = Script::GetStructure( cs );\r\n\r\n\tmMode = mode;\r\n\r\n\tmLipTrickTilt = 0.0f;\r\n\r\n\t// Read the values from the array.\r\n\tp_struct->GetFloat( \"horiz_fov\",\t\t\t\t&h_fov );\r\n\tp_struct->GetFloat( \"behind\",\t\t\t\t\t&behind );\r\n\tp_struct->GetFloat( \"above\",\t\t\t\t\t&above );\r\n\tp_struct->GetFloat( \"tilt\",\t\t\t\t\t\t&tilt );\r\n\tp_struct->GetFloat( \"origin_offset\",\t\t\t&origin_offset );\r\n\tp_struct->GetFloat( \"lip_trick_tilt\",\t\t\t&mLipTrickTilt );\r\n\tp_struct->GetFloat( \"lip_trick_above\",\t\t\t&mLipTrickAbove );\r\n\r\n\t// Get SLERP values.\r\n\tp_struct->GetFloat( \"slerp\",\t\t\t\t\t&mSlerp );\r\n\tp_struct->GetFloat( \"vert_air_slerp\",\t\t\t&mVertAirSlerp );\r\n\tp_struct->GetFloat( \"vert_air_landed_slerp\",\t&mVertAirLandedSlerp );\r\n\r\n\t// Get LERP values.\r\n\tp_struct->GetFloat( \"lerp_xz\",\t\t\t\t\t&mLerpXZ );\r\n\tp_struct->GetFloat( \"lerp_y\",\t\t\t\t\t&mLerpY );\r\n\tp_struct->GetFloat( \"vert_air_lerp_xz\",\t\t\t&mVertAirLerpXZ );\r\n\tp_struct->GetFloat( \"vert_air_lerp_y\",\t\t\t&mVertAirLerpY );\r\n\tp_struct->GetFloat( \"grind_lerp\",\t\t\t\t&mGrindLerp );\r\n\r\n\t// Get zoom values.\r\n\tmGrindZoom\t\t\t= 1.0f;\r\n\tmLipTrickZoom\t\t= 1.0f;\r\n\tmBigAirTrickZoom\t= 1.0f;\r\n\r\n\tp_struct->GetFloat( \"zoom_lerp\",\t\t\t&zoom_lerp );\r\n\tp_struct->GetFloat( \"grind_zoom\",\t\t\t&mGrindZoom );\r\n\tp_struct->GetFloat( \"big_air_trick_zoom\",\t&mBigAirTrickZoom );\r\n\tp_struct->GetFloat( \"lip_trick_zoom\",\t\t&mLipTrickZoom );\r\n\tmZoomLerp\t\t\t= zoom_lerp;\r\n\r\n\t// Get camera style name.\r\n\tp_struct->GetText( \"name\", &p_name );\r\n\r\n\t// Send the new camera mode to console line 1.\r\n\t//HUD::PanelMgr* panelMgr = HUD::PanelMgr::Instance();\r\n\t//panelMgr->SendConsoleMessage( p_name, 1 );\r\n\r\n\t// Need to calculate interpolate timers here.\r\n\tmHorizFOV\t\t= h_fov;\r\n\tmTilt\t\t\t= tilt;\r\n\tmOriginOffset\t= FEET( origin_offset );\t\t// Convert to inches.\r\n\r\n\t// Set up interpolators for those values that require it.\r\n\tif( time > 0.0f )\r\n\t{\r\n\t\tbehind\t\t\t\t\t\t= FEET( behind );\t\t\t\t// Convert to inches.\r\n\t\tabove\t\t\t\t\t\t= FEET( above );\t\t\t\t// Convert to inches.\r\n\t\tmBehindInterpolatorTime\t\t= time;\r\n\t\tmBehindInterpolatorDelta\t= (( behind - mBehind ) * ( SKATERCAM_INTERPOLATOR_TIMESTEP / time ));\r\n\t\tmAboveInterpolatorTime\t\t= time;\r\n\t\tmAboveInterpolatorDelta\t\t= (( above - mAbove ) * ( SKATERCAM_INTERPOLATOR_TIMESTEP / time ));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmBehind\t\t\t\t\t\t= FEET( behind );\r\n\t\tmAbove\t\t\t\t\t\t= FEET( above );\r\n\t\tmBehindInterpolatorTime\t\t= 0.0f;\r\n\t\tmAboveInterpolatorTime\t\t= 0.0f;\r\n\t}\r\n\r\n\t// Set focal length immediately.\r\n\tif( this )\r\n\t{\r\n\t\tNx::ScreenMode\tmode = Nx::CViewportManager::sGetScreenMode();\r\n\r\n\t\tswitch( mode )\r\n\t\t{\r\n\t\t\tcase Nx::vSPLIT_V:\r\n\t\t\t{\r\n#ifdef __PLAT_NGC__\r\n\t\t\t\t//Gfx::Camera::SetFocalLength( Script::GetFloat(\"Skater_Cam_Horiz_FOV\"), Nx::vBASE_ASPECT_RATIO );\r\n\t\t\t\tGfx::Camera::SetHFOV(Script::GetFloat(\"Skater_Cam_Horiz_FOV\") / 2.0f);\r\n#else\r\n\t\t\t\t//Gfx::Camera::SetFocalLength( mFocalLength, Nx::vBASE_ASPECT_RATIO * 0.5f );\r\n\t\t\t\tGfx::Camera::SetHFOV(mHorizFOV / 2.0f);\r\n#endif // __PLAT_NGC__\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tcase Nx::vSPLIT_H:\r\n\t\t\t{\r\n\t\t\t\t//Gfx::Camera::SetFocalLength( mFocalLength * 2.0f, Nx::vBASE_ASPECT_RATIO * 2.0f );\r\n\t\t\t\tGfx::Camera::SetHFOV(mHorizFOV);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tdefault:\r\n\t\t\t{\t\t\t\r\n\t\t\t\t//Gfx::Camera::SetFocalLength( mFocalLength, Nx::vBASE_ASPECT_RATIO );\r\n\t\t\t\tGfx::Camera::SetHFOV(mHorizFOV);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tswitch ( mode )\r\n\t{\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_FRONT ):\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_FRONT_ZOOM ):\r\n\t\t\tmLookaroundHeadingStartingPoint = Mth::PI;\r\n\t\t\tbreak;\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_LEFT ):\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_LEFT_ZOOM ):\r\n\t\t\tmLookaroundHeadingStartingPoint = Mth::PI / 2.0f;\r\n\t\t\tbreak;\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_BEHIND ):\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_BEHIND_ZOOM ):\r\n\t\t\tmLookaroundHeadingStartingPoint = 0;\r\n\t\t\tbreak;\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_RIGHT ):\r\n\t\tcase ( SKATERCAM_MODE_REPLAY_RIGHT_ZOOM ):\r\n\t\t\tmLookaroundHeadingStartingPoint = -( Mth::PI / 2.0f );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tmLookaroundHeadingStartingPoint = 0;\r\n\t\t\tbreak;\r\n\t}   \r\n}\r\n\r\n/*******************************************************************************************************\r\nlogic for getTimeAdjustedSlerp()\r\n\r\nIf the camera is lagging a distance D behind the target, and the target is moving with velocity V, and the lerp is set to L.\r\n\r\nThen when the camera is stable, it will be moving at the same rate as the target (V), and since the distance it will move is equal to the lerp multiplied by the distance from the target (which will be the old distance plus the new movement of the target V)\r\n\r\nThen:\r\n\r\nL*(D+V) = V \r\n\r\nL*D + L*V = V\r\nD = V * (1 - L) / L\r\n\r\nAssuming in the above T = 1, then if we have a variable T, the speed of the skater will be T*V, yet we want the distance (Dt) moved to remain unchanged (D), so for a time adjusted lerp Lt\r\n\r\nDt = T * V * (1-Lt)/Lt\r\n\r\nSince D = Dt\r\n\r\nV * (1 - L) / L = T * V * (1-Lt)/Lt\r\n\r\nV cancels out, and we get\r\n\r\nLt = TL / (1 - L + TL)\r\n\r\nSanity check,  \r\n\r\nif L is 0.25, and T is 1, then Lt = 1*0.25 / (1 - 0.25 + 1*0.25)  = 0.25\r\nif L is 0.25, and T is 2, then Lt = 2*0.25 / (1 - 0.25 + 2*0.25)  = 0.5 / 1.25 = 0.40\r\nif L is 0.25, and T is 5, then Lt = 5*0.25 / (1 - 0.25 + 5*0.25)  = 1.25 / 2 = 0.625\r\n\r\nSounds about right.\r\n\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic float getTimeAdjustedSlerp( float slerp, float delta )\r\n{\r\n#if\t1\r\n\t// Mick's method, tries to guarantee that the distance from the target point\r\n\t// will never alter at constant velocity, with changing frame rate\r\n\t// Lt = TL / (1 - L + TL)\r\n\t\r\n\tfloat t = delta * 60.0f;\r\n\tfloat Lt =  t * slerp / (1.0f - slerp + t * slerp);\r\n\treturn Lt;\t\r\n\t\r\n#else\r\n\t// Dave's method. simulates the effect of lerp over multiple frames\r\n\t// curiously seems to be within 2% of the above method.  \r\n\r\n\tfloat result\t= 0.0f;\r\n\tfloat remainder\t= 1.0f;\r\n\r\n\twhile( true )\r\n\t{\r\n\t\tif( delta >= ( 1.0f / 60.0f ))\r\n\t\t{\r\n\t\t\tdelta -= ( 1.0f / 60.0f );\r\n\r\n\t\t\tfloat extra = slerp * remainder;\r\n\t\t\tremainder -= extra;\r\n\t\t\tresult += extra;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Partial fragment, or nothing at all?\r\n\t\t\tif( delta > 0.0f )\r\n\t\t\t{\r\n\t\t\t\t// The slerp this time will be reduced.\r\n\t\t\t\tslerp *= delta / ( 1.0f / 60.0f );\r\n\r\n\t\t\t\tfloat extra = slerp * remainder;\r\n\t\t\t\tremainder -= extra;\r\n\t\t\t\tresult += extra;\r\n\t\t\t}\r\n//\t\t\tprintf (\"Result %f, Lt %f, diff = %f\\n\",result,Lt,result-Lt);\r\n\t\t\treturn result;\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCam::SetLookaround( float heading, float tilt, float time, float zoom )\r\n{\r\n\tmLookaroundOverride\t\t\t= true;\r\n\r\n\tmLookaroundHeadingTarget\t= heading;\r\n\tmLookaroundTiltTarget\t\t= tilt;\r\n\r\n\t// Calculate delta - the amount to move in 1 second.\r\n\tif( time > 0.0f )\r\n\t{\r\n\t\tmLookaroundHeadingDelta\t\t= ( heading - mLookaroundHeading ) / time;\r\n\t\tmLookaroundTiltDelta\t\t= ( tilt - mLookaroundTilt ) / time;\r\n\t}\r\n\r\n\tmLookaroundDeltaTimer\t\t= time;\r\n\tmLookaroundZoom\t\t\t\t= zoom;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCam::ClearLookaround( void )\r\n{\r\n\tmLookaroundOverride = false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CSkaterCam::SetShake( float duration, float vert_amp, float horiz_amp, float vert_vel, float horiz_vel )\r\n{\r\n\tmShakeDuration\t\t\t= duration;\r\n\tmShakeInitialDuration\t= duration;\r\n\tmShakeMaxVertAmp\t\t= vert_amp;\r\n\tmShakeMaxHorizAmp\t\t= horiz_amp;\r\n\tmShakeVertVel\t\t\t= vert_vel;\r\n\tmShakeHorizVel\t\t\t= horiz_vel;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Added by Ken. \r\nbool CSkaterCam::UseVertCam( void )\r\n{   \r\n\t// Use vert cam when in the lip state.\r\n\tif( mpSkaterStateComponent->GetState() == LIP )\r\n\t{\r\n#ifdef\tDEBUG_CAMERA\r\n\t\tprintf (\"SkaterCam Using Vert Cam as LIP\\n\");\r\n#endif\r\n\t\treturn true;\r\n\t}\t\r\n\t\t\r\n\tif( mpSkaterStateComponent->GetFlag( VERT_AIR ) && !mpSkaterStateComponent->GetFlag( CAN_BREAK_VERT )  && !mpSkaterStateComponent->GetFlag(SPINE_PHYSICS))\r\n\t{\r\n#ifdef\tDEBUG_CAMERA\r\n\t\tprintf (\"SkaterCam Using Vert Cam as VERT_AIR\\n\");\r\n#endif\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tif( mpSkaterStateComponent->GetJumpedOutOfLipTrick())\r\n\t{\r\n#ifdef\tDEBUG_CAMERA\r\n\t\tprintf (\"SkaterCam Using Vert Cam as Jumped out of lip trick\\n\");\r\n#endif\r\n\t\treturn true;\r\n\t}\r\n\r\n#ifdef\tDEBUG_CAMERA\r\n\t\tprintf (\"Skatecam NOT using vert cam\\n\");\r\n#endif\r\n\r\n\r\n\treturn false;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t \r\nvoid CSkaterCam::addShake( Mth::Vector& cam, Mth::Matrix& frame )\r\n{\r\n\tfloat damping\t\t= mShakeDuration / mShakeInitialDuration;\r\n\tfloat vert_angle\t= mShakeDuration * mShakeVertVel * Mth::PI * 2.0f;\r\n\tfloat horiz_angle\t= mShakeDuration * mShakeHorizVel * Mth::PI * 2.0f;\r\n\tfloat vert_offset\t= mShakeMaxVertAmp * sinf( vert_angle ) * damping;\r\n\tfloat horiz_offset\t= mShakeMaxHorizAmp * sinf( horiz_angle ) * damping;\r\n\r\n\tcam += frame[X] * horiz_offset;\r\n\tcam += frame[Y] * vert_offset;\r\n\r\n\tmShakeDuration\t\t-= Tmr::FrameLength();\r\n\tif( mShakeDuration < 0.0f )\r\n\t\tmShakeDuration = 0.0f;\r\n}\r\n\r\n// updates the camera position\r\n// returns the dist from the camera to the focus point \t\t\t\t\t \r\nfloat CSkaterCam::Update( bool instantly )\r\n{\r\n\t\r\n\tif( instantly )\r\n\t{\r\n\t\tmInstantCount = 3;\r\n\t}\r\n\r\n\tif( mInstantCount > 0 )\r\n\t{\r\n\t\t--mInstantCount;\r\n\t\tinstantly = true;\r\n\t}\r\n\r\n\t// Length of last frame in seconds.\r\n\tfloat delta_time = Tmr::FrameLength();\r\n\r\n\tif (mpSkater && mpSkater->mPaused)\t  \t// Mick: early out of ithe skater is paused, just allow scripted cameras\r\n\t{\r\n\t\t//return 100000.0f;\r\n\t}\r\n\r\n\t// Update any values we are currently interpolating.\r\n\tUpdateInterpolators();\r\n\r\n\t\t// Would have used a SetPos() function, but the camera update in rwviewer.cpp is spread out all over the place,\r\n\t\t// so it's not easy to do. We'll just store the old position before updating anything...\r\n\t\tGfx::Camera::StoreOldPos();\r\n\r\n\t\tMth::Matrix& frame_matrix\t= Gfx::Camera::GetMatrix();\r\n\r\n\t\tframe_matrix[X]   \t\t= mLastActualRight;\r\n\t\tframe_matrix[Y]\t\t\t= mLastActualUp;\r\n\t\tframe_matrix[Z]\t\t\t= mLastActualAt;\r\n\r\n\t\tMth::Vector\tcurrent_at_vector( frame_matrix[Z][X], frame_matrix[Z][Y], frame_matrix[Z][Z] ); \r\n\r\n\t\t// Obtain skater state.\r\n\t\tEStateType\tstate\t\t\t= mpSkaterStateComponent->GetState();\r\n\t\tMth::Matrix target;\r\n\t\tif( state == WALL )\r\n\t\t{\r\n#ifdef\tDEBUG_CAMERA\r\n\t\tprintf (\"SkaterCam Using mLastPreWallSkaterMatrix, as wallriding\\n\");\r\n#endif\r\n\t\t\ttarget\t\t\t\t\t\t= mLastPreWallSkaterMatrix;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n#ifdef\tDEBUG_CAMERA\r\n\t\tprintf (\"SkaterCam Using GetCameraDisplayMatrix\\n\");\r\n#endif\r\n\t\t\ttarget\t\t\t\t\t\t= mpSkater->GetDisplayMatrix();\r\n\t\t\tmLastPreWallSkaterMatrix\t= target;\r\n\t\t}\r\n\r\n\t\t// Lerp towards the required lean.\r\n\t\tfloat cam_lean = 0.0f;\r\n\t\tif( state == RAIL )\r\n\t\t{\t\t\r\n\t\t\t// Need to translate the lean value [-4096, 4096] into a reasonable camera lean angle.\r\n\t\t\tcam_lean = GetSkaterBalanceTrickComponentFromObject(mpSkater)->mGrind.mManualLean * LEAN_TO_SKATERCAM_LEAN;\r\n\t\t}\r\n\r\n\t\tif( cam_lean != mLean )\r\n\t\t{\r\n\t\t\tif( instantly )\r\n\t\t\t{\r\n\t\t\t\tmLean = cam_lean;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmLean += (( cam_lean - mLean ) * mGrindLerp );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\r\n\t\tMth::Vector skater_up;\r\n\t\t\t\t\t\r\n\t\tif (state != GROUND)\r\n\t\t{\r\n\t\t\tskater_up\t= target[Y];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tskater_up\t= mpSkaterPhysicsComponent->m_display_normal;\r\n\t\t}\r\n\r\n//\t\tGfx::AddDebugLine( p_skater->m_pos, ( target[X] * 72.0f ) + p_skater->m_pos, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 4 );\r\n//\t\tGfx::AddDebugLine( p_skater->m_pos, ( target[Y] * 72.0f ) + p_skater->m_pos, MAKE_RGB( 0, 128, 0 ), MAKE_RGB( 0, 128, 0 ), 4 );\r\n//\t\tGfx::AddDebugLine( p_skater->m_pos, ( target[Z] * 72.0f ) + p_skater->m_pos, MAKE_RGB( 0, 0, 128 ), MAKE_RGB( 0, 0, 128 ), 4 );\r\n\t\t\r\n\r\n\t\t// Use vel for forward facing, if moving in xz plane.\r\n\t\tMth::Vector vel_xz( mpSkater->GetVel().GetX(), 0.0f, mpSkater->GetVel().GetZ());\r\n\r\n\t\tbool use_vert_cam = UseVertCam();\r\n\r\n\t\t// use velocity if physics not paused, and if we are moving fast enough, or if we are doing vert cam\r\n\t\t// or if we are doing spine physics\r\n\t\tif( /* !mpSkater->m_physics_paused && */ (vel_xz.Length() > 0.1f || use_vert_cam  || mpSkaterStateComponent->GetFlag( SPINE_PHYSICS )))\r\n\t\t{\r\n\t\t\tif( use_vert_cam )\r\n\t\t\t{\r\n\t\t\t\t// If it's vert, then set target direction to near straight down.\r\n\t\t\t\ttarget[Z].Set( 0.0f, -1.0f, 0.0f );\r\n\r\n\t\t\t\t// Zero lookaround when in vert air (and not in lookaround locked or override mode, or doing a lip trick).\r\n\t\t\t\tif( !mLookaroundLock && !mLookaroundOverride && ( state != LIP ))\r\n\t\t\t\t{\r\n\t\t\t\t\tmLookaroundTilt\t\t= 0.0f;\r\n\t\t\t\t\tmLookaroundHeading\t= 0.0f;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\ttarget[Z]\t\t= mpSkater->GetVel();\r\n\t\t\t\t#if 1\t// for use with non-straight spine transfer physics\r\n\t\t\t\tif (mpSkaterStateComponent->GetFlag( SPINE_PHYSICS ))\r\n\t\t\t\t{\r\n\t\t\t\t\t// just use the up velocity, plus the velocity over the spine\r\n\t\t\t\t\t// will be straight down when coing down the other side\r\n\t\t\t\t\ttarget[Z][X] = 0.0f;\r\n\t\t\t\t\ttarget[Z][Z] = 0.0f;\r\n\t\t\t\t\ttarget[Z] += mpSkaterStateComponent->GetSpineVel();\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\t#endif\r\n\t\t\t\ttarget[Z].Normalize();\r\n\r\n//\t\t\t\tprintf (\"Using Velocity (%f, %f, %f)\\n\", target[Z][X],target[Z][Y], target[Z][Z]);\r\n\r\n//\t\t\t\tGfx::AddDebugLine( mpSkater->m_pos, ( target[Z] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 128, 128, 128 ), MAKE_RGB( 128, 128, 128 ), 4 );\r\n\r\n\t\t\t\t// Flatten out the velocity component perpendicular to the ground. However, if the skater is in the air, the\r\n\t\t\t\t// m_last_normal will contain the last ground normal, which we don't want, so set it to be 'up'.\r\n\t\t\t\tfloat\t\t\tdot;\r\n\t\t\t\tMth::Vector\t\tnormal;\r\n\r\n\t\t\t\tif( state == LIP )\r\n\t\t\t\t{\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t// Patch for spine physics\r\n\t\t\t\t\t// only reduce component perpendicular to plane by 60%\r\n\t\t\t\t\t// so we still get some up/down camera movmeent \r\n\t\t\t\t\t// only do this when moving down though, otherwise it looks poo\r\n\t\t\t\t\tif (mpSkaterStateComponent->GetFlag(SPINE_PHYSICS) && target[Z][Y] < 0.0f)\r\n\t\t\t\t\t{\r\n//\t\t\t\t\t\tnormal\t= mpSkaterPhysicsComponent->m_current_normal;\r\n\t\t\t\t\t\tnormal.Set( 0.0f, 1.0f, 0.0f );\r\n\t\t\t\t\t\t//dot\t\t= (( target[Z].GetX() * normal.GetX() ) + ( target[Z].GetY() * normal.GetY() ) + ( target[Z].GetZ() * normal.GetZ() ));\r\n\t\t\t\t\t\t//dot\t\t= dot * 0.8f;\r\n\t\t\t\t\t\tdot =  0.7f * Mth::DotProduct(target[Z],normal);\t// change this to 0.8 to look down when coming down other side of a spine\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnormal.Set( 0.0f, 1.0f, 0.0f );\r\n\t\t\t\t\t\tdot\t\t= target[Z].GetY();\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// Set world up as the target vector.\r\n\t\t\t\t\ttarget[Y].Set( 0.0f, 1.0f, 0.0f );\r\n\t\t\t\t}\r\n\t\t\t\telse if( state == WALL )\r\n\t\t\t\t{\r\n\t\t\t\t\tnormal.Set( 0.0f, 1.0f, 0.0f );\r\n\t\t\t\t\tdot\t\t= target[Z].GetY();\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tnormal\t= mpSkaterPhysicsComponent->m_current_normal;\r\n\t\t\t\t\t//dot\t\t= (( target[Z].GetX() * normal.GetX() ) + ( target[Z].GetY() * normal.GetY() ) + ( target[Z].GetZ() * normal.GetZ() ));\r\n\t\t\t\t\t//dot\t\t= dot * 0.8f;\r\n\t\t\t\t\tdot =  0.8f * Mth::DotProduct(target[Z],normal);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t//target[Z].Set(\ttarget[Z].GetX() - ( dot * normal.GetX() ), target[Z].GetY() - ( dot * normal.GetY() ), target[Z].GetZ() - ( dot * normal.GetZ() ));\r\n\t\t\t\ttarget[Z] -= normal * dot;\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\ttarget[Z].Normalize();\r\n\r\n//\t\t\t\tGfx::AddDebugLine( mpSkater->m_pos, ( target[Z] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 256, 256, 256 ), MAKE_RGB( 256, 256, 256 ), 4 );\r\n\t\t\t}\r\n\r\n\t\t\t// We need to orthonormalize in a specific order, as when the velocity is going backwards, then \r\n\t\t\t// the X orient will be wrong, and so plonk the skater upside down.\r\n\t\t\ttarget[X]\t\t\t= Mth::CrossProduct( target[Y], target[Z] );\r\n\t\t\ttarget[X].Normalize();\r\n\t\t\ttarget[Y]\t\t\t= Mth::CrossProduct( target[Z], target[X] );\r\n\t\t\ttarget[Y].Normalize();\r\n\r\n//\t\t\tGfx::AddDebugLine( mpSkater->m_pos, ( target[X] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 4 );\r\n//\t\t\tGfx::AddDebugLine( mpSkater->m_pos, ( target[Y] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 0, 128, 0 ), MAKE_RGB( 0, 128, 0 ), 4 );\r\n//\t\t\tGfx::AddDebugLine( mpSkater->m_pos, ( target[Z] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 0, 0, 128 ), MAKE_RGB( 0, 0, 128 ), 4 );\r\n\t\t}    \t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t// Tilt further if in regular air (going off a big jump, for example), or doing a lip trick.\r\n\t\tif( state == LIP )\r\n\t\t{\r\n\t\t\tmTiltAddition += TILT_INCREMENT * Tmr::FrameRatio();\r\n\t\t\tif( mTiltAddition > TILT_MAX )\r\n\t\t\t{\r\n\t\t\t\tmTiltAddition = TILT_MAX;\r\n\t\t\t}\t\t\t\t\r\n\t\t}\r\n\t\telse if( mTiltAddition > 0.0f )\r\n\t\t{\r\n\t\t\tmTiltAddition -= TILT_RESTORE * Tmr::FrameRatio();\r\n\t\t\tif( mTiltAddition < 0.0f )\r\n\t\t\t{\r\n\t\t\t\tmTiltAddition = 0.0f;\r\n\t\t\t}\t\t\t\t\r\n\t\t}\r\n\t\telse if( mTiltAddition < 0.0f )\r\n\t\t{\r\n\t\t\tmTiltAddition += TILT_RESTORE * Tmr::FrameRatio();\r\n\t\t\tif( mTiltAddition > 0.0f )\r\n\t\t\t{\r\n\t\t\t\tmTiltAddition = 0.0f;\r\n\t\t\t}\t\t\t\t\r\n\t\t}\r\n\r\n\t\t// PJR: Needed to do this to fix a compiler crash on NGC. Hopefully SN will\r\n\t\t// fix this & I can revert this hack...\r\n\t\ttarget.RotateYLocal( mLookaroundHeading + mLookaroundHeadingStartingPoint );\r\n\r\n\t\t// Now tilt the matrix down a bit.\r\n\t\tif( state == LIP )\r\n\t\t{\r\n//\t\t\ttarget.RotateYLocal( 0.8f );\r\n//\t\t\ttarget.RotateXLocal( mLipTrickTilt + mTiltAddition );\r\n\t\t\t_xrotlocal ( target, mLipTrickTilt + mTiltAddition );\r\n\t\t}\t\t\t\t\t\r\n\t\telse if( !(mpSkaterStateComponent->GetFlag( VERT_AIR ) && !mpSkaterStateComponent->GetFlag( CAN_BREAK_VERT )  && !mpSkaterStateComponent->GetFlag(SPINE_PHYSICS) ))\r\n\t\t{\r\n//\t\t\ttarget.RotateXLocal( mTilt + mTiltAddition );\r\n\t\t\t_xrotlocal ( target, mTilt + mTiltAddition );\r\n\t\t}\t\t\t\t\t\r\n\r\n\t\t// Now adjust for 'lookaround'.\r\n//\t\ttarget.RotateXLocal( mLookaroundTilt );\r\n\t\t_xrotlocal ( target, mLookaroundTilt );\r\n\r\n\t\tstatic float lip_rotate = 0.0f;\r\n\r\n\t\tif( state == LIP )\r\n\t\t{\r\n\t\t\tlip_rotate = 1.5707963f;\r\n\r\n\t\t\tif( mLipSideDecided == 0 )\r\n\t\t\t{\r\n\t\t\t\ttarget.RotateY( lip_rotate );\r\n\r\n\t\t\t\t// Do collision check.\r\n\t\t\t\tCFeeler feeler;\r\n\r\n\t\t\t\tMth::Vector horiz_z( target[Z][X], 0.0f, target[Z][Z] );\r\n\t\t\t\thoriz_z.Normalize();\r\n\t\t\t\tMth::Vector a = mpSkater->m_pos - ( target[Z] * 3.0f );\r\n\t\t\t\tMth::Vector b = a - ( horiz_z * 72.0f );\r\n\r\n\t\t\t\tfeeler.SetIgnore(0, mFD_CAMERA_COLLIDABLE);\r\n\t\t\t\tbool collision = feeler.GetCollision(a, b, true);\r\n\t\t\t\tif( !collision )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Side 1 is fine.\r\n\t\t\t\t\tmLipSideDecided = 1;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tfloat dist = feeler.GetDist();\r\n\t\t\t\t\ttarget.RotateY( -lip_rotate * 2.0f );\r\n\t\t\t\t\thoriz_z.Set( target[Z][X], 0.0f, target[Z][Z] );\r\n\t\t\t\t\thoriz_z.Normalize();\r\n\t\t\t\t\ta = mpSkater->m_pos - ( target[Z] * 3.0f );\r\n\t\t\t\t\tb = a - ( horiz_z * 72.0f );\r\n\r\n\t\t\t\t\tcollision = feeler.GetCollision(a, b, true);\r\n\t\t\t\t\tif( !collision )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Side 2 is fine.\r\n\t\t\t\t\t\tmLipSideDecided = 2;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( feeler.GetDist() < dist )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Side 2 is better than side 1.\r\n\t\t\t\t\t\t\tmLipSideDecided = 2;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Side 1 is better than side 2.\r\n\t\t\t\t\t\t\ttarget.RotateY( lip_rotate * 2.0f );\r\n\t\t\t\t\t\t\tmLipSideDecided = 1;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( mLipSideDecided == 1 )\r\n\t\t\t\t{\r\n\t\t\t\t\ttarget.RotateY( lip_rotate );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\ttarget.RotateY( -lip_rotate );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmLipSideDecided = 0;\r\n\t\t}\t\t\t\t\t\r\n\r\n\t\t// Set skater flag to indicate when the liptrick camera has spun to the opposite side.\r\n\t\tif( mpSkater && ( mLipSideDecided == 2 ))\r\n\t\t{\r\n\t\t\tmpSkater->mScriptFlags |= ( 1 << Script::GetInteger( 0x16b8e4cb /* \"FLAG_SKATER_LIPTRICK_CAM_REVERSED\" */ ));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmpSkater->mScriptFlags &= ~( 1 << Script::GetInteger( 0x16b8e4cb /* \"FLAG_SKATER_LIPTRICK_CAM_REVERSED\" */ ));\r\n\t\t}\r\n\t\t\r\n//\t\tGfx::AddDebugLine( mpSkater->m_pos, ( target[X] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 4 );\r\n//\t\tGfx::AddDebugLine( mpSkater->m_pos, ( target[Y] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 0, 128, 0 ), MAKE_RGB( 0, 128, 0 ), 4 );\r\n//\t\tGfx::AddDebugLine( mpSkater->m_pos, ( target[Z] * 72.0f ) + mpSkater->m_pos, MAKE_RGB( 0, 0, 128 ), MAKE_RGB( 0, 0, 128 ), 4 );\r\n\r\n\t\t// Why doing this, when setting below?\r\n\t\tMth::Matrix t_matrix(0.0f, 0.0f, 0.0f);\r\n\t\t\r\n\t\t// Since camera points in -Z, but player in +Z, we must negate the X and Z axes\r\n        t_matrix[X][X]\t\t= -target[0][0];\r\n\t\tt_matrix[X][Y]\t\t= -target[0][1];\r\n\t\tt_matrix[X][Z]\t\t= -target[0][2];\r\n\t\tt_matrix[X][W]\t\t= 0.0f;\r\n\t\r\n\t\tt_matrix[Y][X]\t\t= target[1][0];\r\n\t\tt_matrix[Y][Y]\t\t= target[1][1];\r\n\t\tt_matrix[Y][Z]\t\t= target[1][2];\r\n\t\tt_matrix[Y][W]\t\t= 0.0f;\r\n\t\r\n\t\tt_matrix[Z][X]\t\t= -target[2][0];\r\n\t\tt_matrix[Z][Y]\t\t= -target[2][1];\r\n\t\tt_matrix[Z][Z]\t\t= -target[2][2];\r\n\t\tt_matrix[Z][W]\t\t= 0.0f;\r\n\t\t\t\r\n        t_matrix[W][X]\t\t= 0.0f;\r\n\t\tt_matrix[W][Y]\t\t= 0.0f;\r\n\t\tt_matrix[W][Z]\t\t= 0.0f;\r\n\t\tt_matrix[W][W]\t\t= 1.0f;\r\n        \r\n\t\tframe_matrix[W][X]\t= 0.0f;\r\n\t\tframe_matrix[W][Y]\t= 0.0f;\r\n\t\tframe_matrix[W][Z]\t= 0.0f;\r\n\t\tframe_matrix[W][W]\t= 1.0f;\r\n\r\n\r\n\t\t// if we want an instant update, then just move it\r\n\t\tif (instantly)\r\n\t\t{\r\n\t\t\tframe_matrix = t_matrix;\r\n\t\t}\r\n\r\n\r\n\t\tfloat dotx = Mth::DotProduct( t_matrix[X], frame_matrix[X] );\r\n\t\tfloat doty = Mth::DotProduct( t_matrix[Y], frame_matrix[Y] );\r\n\t\tfloat dotz = Mth::DotProduct( t_matrix[Z], frame_matrix[Z] );\r\n\r\n#define CAMERA_SLERP_STOP 0.9999f\r\n\t\t\r\n\t\tif( dotx > CAMERA_SLERP_STOP && doty > CAMERA_SLERP_STOP && dotz > CAMERA_SLERP_STOP )\r\n\t\t{\r\n\t\t\t// Do nothing, camera has reached the target so we just leave the frame matrix exactly where it is.\r\n//\t\t    frame_matrix = t_matrix;\r\n        }\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Initialise the SLERP interpolator, with the current matrix as the start, and the ideal\r\n\t\t\t// matrix as the end (target).\r\n\r\n            // GARY:  is this right?  i assume p_matrix = &t_matrix\r\n\t\t\tmpSlerp->setMatrices( &frame_matrix, &t_matrix );\r\n\r\n\t\t\t// Copy flags and shit (why copying all this when most of the values will be overwritten?)\r\n\t\t\tMth::Matrix stored_frame;\r\n            stored_frame = frame_matrix;\r\n            frame_matrix = t_matrix;\t\t\t\r\n\r\n\t\t\t// Continue to slerp towards the target, updating frame_matrix with the slerped values.\r\n\t\t\tif( !(mpSkaterStateComponent->GetFlag( VERT_AIR ) && !mpSkaterStateComponent->GetFlag( CAN_BREAK_VERT ) && !mpSkaterStateComponent->GetFlag(SPINE_PHYSICS)))\r\n\t\t\t{\r\n\t\t\t\t// If the skater has just landed from big air, use the big air land slerp value.\r\n\t\t\t\tif(( mpSkaterStateComponent->GetState() == GROUND ) && ( mVertAirLandedTimer >= delta_time ))\r\n\t\t\t\t{\r\n\t\t\t\t\tmVertAirLandedTimer -= delta_time;\r\n\t\t\t\t\tmpSlerp->getMatrix( &frame_matrix, getTimeAdjustedSlerp( mVertAirLandedSlerp, delta_time ));\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Clear the vert air landed timer.\r\n\t\t\t\t\tmVertAirLandedTimer = 0.0f;\r\n\r\n\t\t\t\t\tmpSlerp->getMatrix( &frame_matrix, getTimeAdjustedSlerp( mSlerp, delta_time ));\r\n\r\n\t\t\t\t\t// At this point we can check to see the angle that the camera's 'at' vector moved through this frame.\r\n\t\t\t\t\t// If this angle is too large, we need to limit it, regardless of the slerp. (This is primarily to avoid\r\n\t\t\t\t\t// the nasty jerk when transitioning rails etc.\r\n\t\t\t\t\tfloat this_dot = ( current_at_vector.GetX() * frame_matrix[Mth::AT][X] ) \r\n                        + ( current_at_vector.GetY() * frame_matrix[Mth::AT][Y] ) \r\n                        + ( current_at_vector.GetZ() * frame_matrix[Mth::AT][Z] ); \r\n\r\n\t\t\t\t\t// Dot values will be in the range [0,1], with 1 being no change.\r\n\t\t\t\t\tif( this_dot < ( mLastDot * 0.9998f ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// The angular change this frame is too big. Need to recalculate with an adjusted slerp value.\r\n\t\t\t\t\t\tfloat new_slerp = mSlerp * ( this_dot / ( mLastDot * 0.9998f ));\r\n\t\t\t\t\t\tmpSlerp->setMatrices( &stored_frame, &t_matrix );\r\n\t\t\t\t\t\tmpSlerp->getMatrix( &frame_matrix, getTimeAdjustedSlerp( new_slerp, delta_time ));\r\n\r\n\t\t\t\t\t\tthis_dot = mLastDot * 0.9998f;\r\n\t\t\t\t\t}\r\n                    \r\n\t\t\t\t\tmLastDot = this_dot;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmpSlerp->getMatrix( &frame_matrix, getTimeAdjustedSlerp( mVertAirSlerp, delta_time ));\r\n\r\n\t\t\t\t// Set the vert air landed timer to the max, since the skater is in vert air.\r\n\t\t\t\tmVertAirLandedTimer = VERT_AIR_LANDED_TIME;\r\n\t\t\t}\t\t\t\t\t\t\r\n\t\t}\t\t\r\n\r\n\t\t// At this point, frame_matrix is valid to store.\r\n\t\tmLastActualRight\t= frame_matrix[X];\r\n\t\tmLastActualUp\t\t= frame_matrix[Y];\r\n\t\tmLastActualAt\t\t= frame_matrix[Z];\r\n\r\n\t\t// Set camera position to be the same as the skater.\r\n\t\tMth::Vector\tcam_pos = GetTripodPos( instantly );\r\n\r\n\t\t// If in the air doing a trick, we slowly reduce the behind value to 'zoom' in on the skater.\r\n\t\tfloat above, behind;\r\n\t\tif (instantly)\r\n\t\t{\r\n\t\t\tfloat temp = mZoomLerp;\r\n\t\t\tmZoomLerp = 1.0f;\t\t\t\t\t// fully lerp instantly\r\n\t\t\tCalculateZoom( &above, &behind );\r\n\t\t\tmZoomLerp = temp;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tCalculateZoom( &above, &behind );\r\n\t\t}\r\n\r\n\r\n\r\n\t\t\r\n\r\n//        printf( \"above = %f, behind %f\\n\", above, behind );\r\n\t\t\r\n\t\t//Dbg_Message(\"Camera before: pos (%5.1f,%5.1f,%5.1f)\", cam_pos[X], cam_pos[Y], cam_pos[Z]);\r\n\r\n\t\t// Note we use the camera's at vector, as this will keep the skater in the middle of the frame.\r\n\t\t//cam_pos -= frame_matrix[Z] * behind;\r\n\t\tcam_pos += frame_matrix[Z] * behind;\r\n\t\t\r\n\t\t// Move camera along the Skater's up vector.\r\n//\t\tcam_pos += mpSkater->GetMatrix()[Y] * above;\r\n\t\tcam_pos += skater_up * above;\r\n\r\n\t\tMth::Vector\tactual_focus_pos = mpSkater->m_pos + ( skater_up * above );\r\n\r\n\r\n//\t\tGfx::AddDebugLine( mpSkater->m_pos, actual_focus_pos, MAKE_RGB( 0, 0, 128 ), MAKE_RGB( 0, 0, 128 ), 4 );\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n//\t\tDbg_Message(\"Matrix Z  (%5.4f,%5.4f,%5.4f)\", frame_matrix[Z][X], frame_matrix[Z][Y], frame_matrix[Z][Z]);\r\n//\t\tDbg_Message(\"Matrix UP (%5.4f,%5.4f,%5.4f)\", skater_up[X], skater_up[Y], skater_up[Z]);\r\n//\t\tDbg_Message(\"Above %f Behind %f\", above, behind);\r\n//\t\tDbg_Message(\"focus pos (%5.1f,%5.1f,%5.1f)\", actual_focus_pos[X], actual_focus_pos[Y], actual_focus_pos[Z]);\r\n//\t\tDbg_Message(\"Camera after: pos (%5.1f,%5.1f,%5.1f)\", cam_pos[X], cam_pos[Y], cam_pos[Z]);\r\n\r\n\t\t// Reorient the camera to look directly at the skater. We don't want to look at the interpolated position,\r\n\t\t// since this can lead to nasty jerkiness, especially on rails etc.\r\n\t\t\r\n\r\n\t\ttarget[Z].Set( actual_focus_pos.GetX() - cam_pos.GetX(), actual_focus_pos.GetY() - cam_pos.GetY(), actual_focus_pos.GetZ() - cam_pos.GetZ());\r\n\t\ttarget[Z].Normalize();\r\n\r\n\t\t// Read back the Y from the current matrix.\r\n\t\ttarget[Y][0]\t= frame_matrix[Y][X];\r\n\t\ttarget[Y][1]\t= frame_matrix[Y][Y];\r\n\t\ttarget[Y][2]\t= frame_matrix[Y][Z];\r\n\r\n\t\t// Generate new orthonormal X and Y axes.\r\n\t\ttarget[X]\t\t= Mth::CrossProduct( target[Y], target[Z] );\r\n\t\ttarget[X].Normalize();\r\n\t\ttarget[Y]\t\t= Mth::CrossProduct( target[Z], target[X] );\r\n\t\ttarget[Y].Normalize();\r\n\r\n\t\t// Here is where lean may safely be applied without moving the focus position on screen.\r\n\t\tif( mLean != 0.0f )\r\n\t\t{\r\n\t\t\ttarget[Y].Rotate( target[Z], mLean );\r\n\t\t\ttarget[X].Rotate( target[Z], mLean );\r\n\t\t}\r\n\r\n\t\t// Write back into camera matrix.\r\n\t\t// Since camera points in -Z, but player in +Z, we must negate the X and Z axes\r\n        frame_matrix[X][X]\t\t= -target[0][0];\r\n        frame_matrix[X][Y]\t\t= -target[0][1];\r\n        frame_matrix[X][Z]\t\t= -target[0][2];\r\n        frame_matrix[X][W]\t\t= 0.0f;\r\n\r\n        frame_matrix[Y][X]\t\t= target[1][0];\r\n        frame_matrix[Y][Y]\t\t= target[1][1];\r\n        frame_matrix[Y][Z]\t\t= target[1][2];\r\n        frame_matrix[Y][W]\t\t= 0.0f;\r\n\r\n        frame_matrix[Z][X]\t\t= -target[2][0];\r\n        frame_matrix[Z][Y]\t\t= -target[2][1];\r\n        frame_matrix[Z][Z]\t\t= -target[2][2];\r\n        frame_matrix[Z][W]\t\t= 0.0f;\r\n\r\n\t\t// Update the position if there is a shake active.\r\n\t\tif(\tmShakeDuration > 0.0f )\r\n\t\t{\r\n\t\t\taddShake( cam_pos, frame_matrix );\r\n\t\t}\r\n\t\t\r\n\t\t// Now do collision detection.\r\n\t\tMth::Vector at_pos = cam_pos - ((Mth::Vector)( frame_matrix[Z] )) * behind;\r\n\r\n\t\t// camera collision detection\r\n\t\t\r\n\t\tif (mpSkaterPhysicsComponent->mp_movable_contact_component->GetContact() && state == LIP)\r\n\t\t{\r\n\t\t\t// no camera collision if doing a lipt trick on a moving object\r\n\t\t\t//printf (\"Lip trick on moving object\\n\");\r\n\t\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tCFeeler feeler;\r\n\t\t\t// Ignore faces with mFD_NON_COLLIDABLE set, and ignore faces with mFD_CAMERA_COLLIDABLE not set.\r\n\t\t\tfeeler.SetIgnore(0, mFD_CAMERA_COLLIDABLE);\r\n\t\t\tbool collision = feeler.GetCollision(at_pos, cam_pos, true);\r\n\t\t\tif( collision )\r\n\t\t\t{\r\n\t\t\t\t\r\n\t\t\t\t//Gfx::AddDebugLine( at_pos, cam_pos, MAKE_RGB( 128, 0, 0 ), MAKE_RGB( 128, 0, 0 ), 2000 );\r\n\t\r\n\t\t\t\t// Limits the camera to getting nearer than 11.9 inches to the focus point.\r\n\t\t\t\tfloat distance = feeler.GetDist();\r\n\t\t\t\tif(( behind * distance * 0.9f ) < 11.9f )\r\n\t\t\t\t{\r\n\t\t\t\t\tdistance = 11.9f / ( behind * 0.9f );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\r\n\t\t\t\tcam_pos = at_pos + (( cam_pos - at_pos ) * ( distance * 0.9f ));\r\n\t\t\t}\r\n\t\r\n#\t\t\tifdef __PLAT_NGPS__\r\n\t\t\t// Now do two additional checks 1 foot to either side of the camera.\r\n\t\t\tMth::Vector\tleft( frame_matrix[X][X], 0.0f, frame_matrix[X][Z], 0.0f );\r\n\t\t\tleft.Normalize( 8.0f );\r\n\t\t\tleft += cam_pos;\r\n\t\r\n\t\t\tcollision = feeler.GetCollision(cam_pos, left, true);\r\n\t\t\tif( collision )\r\n\t\t\t{\r\n\t\t\t\tleft\t\t   -= feeler.GetPoint();\r\n\t\t\t\tcam_pos\t\t   -= left;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMth::Vector\tright( -frame_matrix[X][X], 0.0f, -frame_matrix[X][Z], 0.0f );\r\n\t\t\t\tright.Normalize( 8.0f );\r\n\t\t\t\tright += cam_pos;\r\n\t\r\n\t\t\t\tcollision = feeler.GetCollision(cam_pos, right, true);\r\n\t\t\t\tif( collision )\r\n\t\t\t\t{\r\n\t\t\t\t\tright\t\t   -= feeler.GetPoint();\r\n\t\t\t\t\tcam_pos\t\t   -= right;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\r\n\t\t\tif(collision )\r\n\t\t\t{\r\n\t\t\t\t// Re-orient the camera again.\r\n\t\t\t\ttarget[Z].Set( actual_focus_pos.GetX() - cam_pos.GetX(), actual_focus_pos.GetY() - cam_pos.GetY(), actual_focus_pos.GetZ() - cam_pos.GetZ());\r\n\t\t\t\ttarget[Z].Normalize();\r\n\t\r\n\t\t\t\t// Read back the Y from the current matrix.\r\n\t//\t\t\ttarget[Y][0]\t= p_frame_matrix->up.x;\r\n\t//\t\t\ttarget[Y][1]\t= p_frame_matrix->up.y;\r\n\t//\t\t\ttarget[Y][2]\t= p_frame_matrix->up.z;\r\n\t\r\n\t\t\t\t// Generate new orthonormal X and Y axes.\r\n\t\t\t\ttarget[X]\t\t= Mth::CrossProduct( target[Y], target[Z] );\r\n\t\t\t\ttarget[X].Normalize();\r\n\t\t\t\ttarget[Y]\t\t= Mth::CrossProduct( target[Z], target[X] );\r\n\t\t\t\ttarget[Y].Normalize();\r\n\t\r\n\t\t\t\t// Write back into camera matrix.\r\n\t\t\t\tframe_matrix[X][X]\t= -target[0][0];\r\n\t\t\t\tframe_matrix[X][Y]\t= -target[0][1];\r\n\t\t\t\tframe_matrix[X][Z]\t= -target[0][2];\r\n\t\t\t\tframe_matrix[Y][X]\t= target[1][0];\r\n\t\t\t\tframe_matrix[Y][Y]\t= target[1][1];\r\n\t\t\t\tframe_matrix[Y][Z]\t= target[1][2];\r\n\t\t\t\tframe_matrix[Z][X]\t= -target[2][0];\r\n\t\t\t\tframe_matrix[Z][Y]  = -target[2][1];\r\n\t\t\t\tframe_matrix[Z][Z]\t= -target[2][2];\r\n\t\t\t}\r\n#\t\t\tendif\r\n\t\t}\r\n\r\n\t\tcam_pos[W] = 1.0f;\r\n\t\t//Dbg_MsgAssert(cam_pos[W] == 1.0f, (\"cam_pos W is %f, not 1.0\", cam_pos[W]));\r\n\t\tGfx::Camera::SetPos(cam_pos);\r\n\r\n\t\t// store the position of the camera in CSkaterCam also (used for proximity nodes)\r\n\t\tm_pos = cam_pos;\r\n\t\tMth::Vector\t\tto_target = at_pos - cam_pos;\r\n\t\t\t\t\r\n\t\t\t\t\r\n//\t\tDbg_Message(\"Camera Final: pos (%5.1f,%5.1f,%5.1f)\", cam_pos[X], cam_pos[Y], cam_pos[Z]);\r\n\r\n\t\t\r\n\t\t\r\n\t\treturn to_target.Length();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nMth::Vector CSkaterCam::GetTripodPos( bool instantly )\r\n{\r\n\tfloat\t\tlerp_xz;\r\n\tfloat\t\tlerp_y;\r\n\tfloat\t\tdelta\t\t= Tmr::FrameLength();\r\n\tMth::Vector now\t\t\t= mpSkater->m_pos;\r\n\r\n\t// The tripod pos is always *tending* towards the skater position, but the rate at which it does so is\r\n\t// definable, to allow for some lag, which improves the feeling of speed.\r\n\tif( mLerpReductionTimer > 0.0f )\r\n\t{\r\n\t\tmLerpReductionTimer -= delta;\r\n\t\tif( mLerpReductionTimer > 0.0f )\r\n\t\t{\r\n\t\t\tmLerpReductionMult += ( mLerpReductionDelta * delta );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmLerpReductionMult\t= 1.0f;\r\n\t\t\tmLerpReductionTimer\t= 0.0f;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmLerpReductionMult\t= 1.0f;\r\n\t}\r\n\r\n\tif(( mpSkaterStateComponent->GetFlag( VERT_AIR ) && !mpSkaterStateComponent->GetFlag( CAN_BREAK_VERT ) && !mpSkaterStateComponent->GetFlag(SPINE_PHYSICS)))\r\n\t{\r\n\t\t#ifdef\tDEBUG_CAMERA\r\n\t\tprintf (\"Skatercam using mVertAirLerp\\n\");\r\n\t\t#endif\r\n\r\n\t\tlerp_xz\t= getTimeAdjustedSlerp( mVertAirLerpXZ * mLerpReductionMult, delta );\r\n\t\tlerp_y\t= getTimeAdjustedSlerp( mVertAirLerpY * mLerpReductionMult, delta );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tlerp_xz\t= getTimeAdjustedSlerp( mLerpXZ * mLerpReductionMult, delta );\r\n\t\tlerp_y\t= getTimeAdjustedSlerp( mLerpY * mLerpReductionMult, delta );\r\n\r\n\t\t// Added the following check (Dave 7/16/02) to help eliminate the camera rattle when snapping on/off a curb.\r\n\t\t// The flag is set for one frame only.\r\n\t\tif( mpSkaterStateComponent->GetFlag( SNAPPED_OVER_CURB ))\r\n\t\t{\r\n\t\t\tlerp_y = 1.0f;\r\n\t\t}\r\n\t}\r\n\r\n\tif( instantly )\r\n\t{\r\n\t\tmLastTripodPos = now;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmLastTripodPos.Set( mLastTripodPos.GetX() + (( now.GetX() - mLastTripodPos.GetX() ) * lerp_xz ),\r\n\t\t\t\t\t\t\tmLastTripodPos.GetY() + (( now.GetY() - mLastTripodPos.GetY() ) * lerp_y ),\r\n\t\t\t\t\t\t\tmLastTripodPos.GetZ() + (( now.GetZ() - mLastTripodPos.GetZ() ) * lerp_xz ));\r\n\t}\r\n\r\n\treturn mLastTripodPos;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCam::CalculateZoom( float* p_above, float* p_behind )\r\n{\r\n\tmTargetZoom = 1.0f;\r\n\r\n\t// Deal with zoom for Big Air. Set the flag only when a trick is started.\r\n\tif( !mBigAirTrickZoomActive && (mpSkaterStateComponent->GetFlag( VERT_AIR ) && !mpSkaterStateComponent->GetFlag( CAN_BREAK_VERT ) && !mpSkaterStateComponent->GetFlag(SPINE_PHYSICS)) && mpSkaterStateComponent->DoingTrick() )\r\n\t{\r\n\t\tmBigAirTrickZoomActive = true;\r\n\t}\r\n\telse if( !(mpSkaterStateComponent->GetFlag( VERT_AIR ) && !mpSkaterStateComponent->GetFlag( CAN_BREAK_VERT ) && !mpSkaterStateComponent->GetFlag(SPINE_PHYSICS)))\r\n\t{\r\n\t\t// Must have landed.\r\n\t\tmBigAirTrickZoomActive = false;\r\n\t}\r\n\r\n\tif( mBigAirTrickZoomActive )\r\n\t{\r\n\t\tmTargetZoom = mBigAirTrickZoom;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tEStateType state = mpSkaterStateComponent->GetState();\r\n\r\n\t\t// If the skater is grinding, zoom also.\r\n\t\tif( state == RAIL )\r\n\t\t{\r\n\t\t\tmTargetZoom = mGrindZoom;\r\n\t\t}\r\n\t\telse if( state == LIP )\r\n\t\t{\r\n\t\t\tmTargetZoom = mLipTrickZoom;\r\n\t\t}\r\n\t\telse if( state == LIP )\r\n\t\t{\r\n\t\t\tmTargetZoom = mLipTrickZoom;\r\n\t\t}\r\n\t}\r\n\r\n\t\r\n\t// If lookaround override is set, factor in the lookaround override zoom.\r\n\tif( mLookaroundOverride && ( mLookaroundZoom != 1.0f ))\r\n\t{\r\n\t\tmCurrentZoom = mTargetZoom;\r\n\t\tmCurrentZoom *= mLookaroundZoom;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmCurrentZoom += (( mTargetZoom - mCurrentZoom ) * mZoomLerp );\r\n\t}\r\n\t\r\n\t*p_behind = mBehind * mCurrentZoom;\r\n\r\n\r\n\t// Behind is also shortened when the lookaround camera is tilting upwards.\r\n\tif( mLookaroundTilt < 0.0f )\r\n\t{\r\n\t\tfloat max_tilt = 3.14f * 0.2f;\r\n\t\t*p_behind = *p_behind * ( 0.4f + ( 0.6f * (( max_tilt + mLookaroundTilt ) / max_tilt )));\r\n\t}\r\n\r\n\r\n\t// Use lip_trick_above when doing a lip trick.\r\n\tfloat above_val = mAbove;\r\n\tif( mpSkaterStateComponent->GetState() == LIP )\r\n\t{\r\n\t\tabove_val = mLipTrickAbove;\r\n\t}\r\n\t\r\n\r\n\t// Figure above tending towards the perfect above, if zoom is < 1.0.\r\n\tif( mCurrentZoom < 1.0f )\r\n\t{\r\n\t\t*p_above = PERFECT_ABOVE + (( above_val - PERFECT_ABOVE ) * mCurrentZoom );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t*p_above = above_val;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCam::UpdateInterpolators( void )\r\n{\r\n\tfloat delta_time = Tmr::FrameLength();\r\n\r\n\tif( mLookaroundOverride )\r\n\t{\r\n\t\tif( mLookaroundDeltaTimer > 0.0f )\r\n\t\t{\r\n\t\t\tif( mLookaroundDeltaTimer > delta_time )\r\n\t\t\t{\r\n\t\t\t\tmLookaroundHeading\t\t+= mLookaroundHeadingDelta * delta_time;\r\n\t\t\t\tmLookaroundTilt\t\t\t+= mLookaroundTiltDelta * delta_time;\r\n\t\t\t\tmLookaroundDeltaTimer\t-= delta_time;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmLookaroundHeading\t\t= mLookaroundHeadingTarget;\r\n\t\t\t\tmLookaroundTilt\t\t\t= mLookaroundTiltTarget;\r\n\t\t\t\tmLookaroundDeltaTimer\t= 0.0f;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif( mBehindInterpolatorTime > 0.0f )\r\n\t{\r\n\t\tmBehindInterpolatorTime -= SKATERCAM_INTERPOLATOR_TIMESTEP;\r\n\t\tmBehind += mBehindInterpolatorDelta;\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmBehindInterpolatorTime = 0.0f;\r\n\t}\r\n\r\n\tif( mAboveInterpolatorTime > 0.0f )\r\n\t{\r\n\t\tmAboveInterpolatorTime -= SKATERCAM_INTERPOLATOR_TIMESTEP;\r\n\t\tmAbove += mAboveInterpolatorDelta;\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmAboveInterpolatorTime = 0.0f;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCam::SetLerpReductionTimer( float time )\r\n{\r\n\tif( time > 0.0f )\r\n\t{\r\n\t\tmLerpReductionTimer\t= time;\r\n\t\tmLerpReductionDelta\t= 1.0f / time;\r\n\t\tmLerpReductionMult\t= 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmLerpReductionTimer\t= 0.0f;\r\n\t\tmLerpReductionDelta\t= 0.0f;\r\n\t\tmLerpReductionMult\t= 1.0f;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCam::SetSkater( CSkater* skater )\r\n{\r\n\tmpSkater = skater;\r\n\tDbg_Assert(mpSkater);\r\n\t\r\n\tmpSkaterPhysicsComponent = GetSkaterCorePhysicsComponentFromObject(skater);\r\n\tDbg_Assert(mpSkaterPhysicsComponent);\r\n\t\r\n\tmpSkaterStateComponent = GetSkaterStateComponentFromObject(skater);\r\n\tDbg_Assert(mpSkaterStateComponent);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkater* CSkaterCam::GetSkater( void )\r\n{\r\n\treturn mpSkater;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCam::BindToController( int controller )\r\n{\r\n\t// swap\r\n\tSpt::SingletonPtr< Inp::Manager > inp_manager;\r\n\tinp_manager->ReassignHandler( *m_input_handler, controller );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Obj\r\n"
  },
  {
    "path": "Code/Sk/Objects/skatercam.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Gfx\r\n//* FILENAME:       skatercam.cpp\r\n//* OWNER:          Dave Cowling\r\n//* CREATION DATE:  02/05/2001\r\n//****************************************************************************\r\n\r\n#ifndef __OBJECTS_SKATERCAM_H\r\n#define __OBJECTS_SKATERCAM_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\n#include <core/math/math.h>\r\n#include <core/math/matrix.h>\r\n#include <core/math/vector.h>\r\n\r\n#include <gfx/camera.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mth\r\n{\r\n    class SlerpInterpolator;\r\n};\r\n\r\n#if 0\r\nnamespace NxPlugin\r\n{\r\n\tclass CameraHeader;\r\n};\r\n#endif\r\n                   \r\nnamespace Obj\r\n{\r\n    class CSkater;\r\n    class CSkaterCorePhysicsComponent;\r\n    class CSkaterStateComponent;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CSkaterCam : public Gfx::Camera\r\n{\r\npublic:\r\n\tenum ESkaterCamMode\r\n\t{\r\n\t\tSKATERCAM_MODE_UNDEFINED\t\t= 0,\r\n\t\tSKATERCAM_MODE_FIRST_VALID\t\t= 1,\r\n\t\tSKATERCAM_MODE_NORMAL_NEAR\t\t= 1,\r\n\t\tSKATERCAM_MODE_NORMAL_MEDIUM,\r\n\t\tSKATERCAM_MODE_NORMAL_FAR,\r\n\t\tSKATERCAM_MODE_NORMAL_MEDIUM_LTG,\r\n        SKATERCAM_NUM_NORMAL_MODES,\r\n\t\tSKATERCAM_FIRST_REPLAY_MODE = SKATERCAM_NUM_NORMAL_MODES,\r\n\t\tSKATERCAM_MODE_REPLAY_FRONT = SKATERCAM_NUM_NORMAL_MODES,\r\n\t\tSKATERCAM_MODE_REPLAY_FRONT_ZOOM,\r\n        SKATERCAM_MODE_REPLAY_LEFT,\r\n\t\tSKATERCAM_MODE_REPLAY_LEFT_ZOOM,\r\n\t\tSKATERCAM_MODE_REPLAY_BEHIND,\r\n\t\tSKATERCAM_MODE_REPLAY_BEHIND_ZOOM,\r\n\t\tSKATERCAM_MODE_REPLAY_RIGHT,\r\n\t\tSKATERCAM_MODE_REPLAY_RIGHT_ZOOM,\r\n\t\tSKATERCAM_LAST_REPLAY_MODE = SKATERCAM_MODE_REPLAY_RIGHT_ZOOM,\r\n\t\tSKATERCAM_NUM_MODES,\r\n\t};\r\n\r\npublic:\r\n\r\n\t\t\t\t\tCSkaterCam( int player );\r\n\t\t\t\t\t~CSkaterCam( void );\r\n\tbool\t\t\tUseVertCam();\r\n\tfloat\t\t\tUpdate( bool instantly = false );\r\n\tbool\t\t\tIsAnimFinished( void );\r\n\tbool\t\t\tIsAnimHeld( void );\r\n\tvoid\t\t\tSetAnimSkippable( bool skippable );\r\n\tvoid\t\t\tSwitchReplayMode( bool increment );\r\n\tvoid\t\t\tSetMode( ESkaterCamMode mode, float time = 1.0f );\r\n\tint\t\t\t\tGetMode( void )\t\t\t\t\t\t\t\t{ return (int)mMode; }\r\n\tvoid\t\t\tSetLookaround( float heading, float tilt, float time, float zoom = 1.0f );\r\n\tvoid\t\t\tClearLookaround( void );\r\n\tvoid\t\t\tClearLookaroundLock( void )\t\t\t\t\t\t\t{ mLookaroundLock = false; }\r\n\tvoid\t\t\tSetShake( float duration, float vert_amp, float horiz_amp, float vert_vel, float horiz_vel );\r\n\tvoid\t\t\tEnableInputHandler( bool enable );\r\n\tvoid\t\t\tSetSkater( CSkater* skater );\r\n\tvoid\t\t\tSetLerpReductionTimer( float time );\r\n\tCSkater*\t\tGetSkater( void );\r\n\tvoid \t\t\tResetLookAround( void );\r\n\r\n\tvoid\t\t\tBindToController( int controller );\r\n\r\n\t// needed for proxim.cpp (each camera stores its position \r\n\t// after writing that position to render camera)\r\n//\tMth::Vector\t\tm_pos;\r\n\r\n\tbool\t\t\tmSkipButton;\r\n\tbool\t\t\tmRightButton;\r\n\tint\t\t\t\tmRightX;\r\n\tint\t\t\t\tmRightY;\r\n\tESkaterCamMode\tmMode;\r\n\t\r\nprivate:\r\n\r\n\tMth::Vector\t\tGetTripodPos( bool instantly = false );\r\n\tvoid\t\t\tUpdateInterpolators( void );\r\n\tvoid\t\t\tCalculateZoom( float* p_above, float* p_behind );\r\n\tvoid\t\t\taddShake( Mth::Vector& cam, Mth::Matrix& frame );\r\n\r\n\tMth::SlerpInterpolator*\tmpSlerp;\r\n\r\n\tCSkater*\t\tmpSkater;\r\n\tCSkaterCorePhysicsComponent*\tmpSkaterPhysicsComponent;\r\n\tCSkaterStateComponent*\tmpSkaterStateComponent;\r\n\r\n\tfloat\t\t\tmLastDot;\r\n\tMth::Vector\t\tmLastTripodPos;\r\n\r\n\tstatic\t\t\t\t\t\tInp::Handler< CSkaterCam >::Code s_input_logic_code;\r\n\tInp::Handler< CSkaterCam >*\tm_input_handler;\r\n//\tstatic\t\t\t\t\t\tInp::Handler< CSkaterCam >::Code s_input_logic_code_special;\r\n//\tInp::Handler< CSkaterCam >*\tm_input_handler_special;\r\n\r\n\tbool\t\t\tm_input_enabled;\r\n\t\r\n\tint\t\t\t\tmInstantCount;\t\t\t\t// Used to maintain the 'instantly' flag during update for several frames.\r\n\r\n\tfloat\t\t\tmHorizFOV;\r\n\r\n\tMth::Vector\t\tmLastActualRight;\t\t\t// Used because the frame is adjusted after focus LERPING.\r\n\tMth::Vector\t\tmLastActualUp;\r\n\tMth::Vector\t\tmLastActualAt;\r\n\r\n\tMth::Matrix\t\tmLastPreWallSkaterMatrix;\t// Used because we don't want to use the skater's matrix during wall rides.\r\n\r\n\tfloat\t\t\tmBehind;\r\n\tfloat\t\t\tmBehindInterpolatorTime;\r\n\tfloat\t\t\tmBehindInterpolatorDelta;\r\n\r\n\tfloat\t\t\tmAbove;\r\n\tfloat\t\t\tmAboveInterpolatorTime;\r\n\tfloat\t\t\tmAboveInterpolatorDelta;\r\n\r\n\tbool\t\t\tmBigAirTrickZoomActive;\r\n\tfloat\t\t\tmCurrentZoom;\r\n\tfloat\t\t\tmTargetZoom;\r\n\tfloat\t\t\tmZoomLerp;\t\t\t\t// LERP rate for zoom.\r\n\tfloat\t\t\tmBigAirTrickZoom;\t\t// Target zoom for big air trick.\r\n\tfloat\t\t\tmGrindZoom;\t\t\t\t// Target zoom for grind.\r\n\tfloat\t\t\tmLipTrickZoom;\t\t\t// Target zoom for lip trick.\r\n\tint\t\t\t\tmLipSideDecided;\r\n\r\n\tfloat\t\t\tmVertAirLandedTimer;\t// Defines how long the vert air landed slerp gets applied.\r\n\r\n\tfloat\t\t\tmLerpReductionTimer;\r\n\tfloat\t\t\tmLerpReductionDelta;\r\n\tfloat\t\t\tmLerpReductionMult;\r\n\r\n\tbool\t\t\tmLookaroundLock;\r\n\tbool\t\t\tmLookaroundOverride;\t// For when the designer is scripting the lookaround values.\r\n\tfloat\t\t\tmLookaroundZoom;\t\t// Allows designers to adjust the zoom when overrideing the lookaround values.\r\n\tfloat\t\t\tmLookaroundTilt;\r\n\tfloat\t\t\tmLookaroundHeading;\r\n\tfloat\t\t\tmLookaroundHeadingStartingPoint;\r\n\tfloat\t\t\tmLookaroundTiltTarget;\r\n\tfloat\t\t\tmLookaroundHeadingTarget;\r\n\tfloat\t\t\tmLookaroundTiltDelta;\r\n\tfloat\t\t\tmLookaroundHeadingDelta;\r\n\tfloat\t\t\tmLookaroundDeltaTimer;\r\n\r\n\tfloat\t\t\tmTilt;\r\n\tfloat\t\t\tmTiltAddition;\r\n\tfloat\t\t\tmLipTrickTilt;\r\n\tfloat\t\t\tmLipTrickAbove;\r\n\tfloat\t\t\tmSlerp;\r\n\tfloat\t\t\tmVertAirSlerp;\r\n\tfloat\t\t\tmVertAirLandedSlerp;\r\n\tfloat\t\t\tmOriginOffset;\r\n\r\n\tfloat\t\t\tmShakeDuration;\t\t\t// Shake duration in seconds (0.0 means no shake).\r\n\tfloat\t\t\tmShakeInitialDuration;\r\n\tfloat\t\t\tmShakeMaxVertAmp;\r\n\tfloat\t\t\tmShakeMaxHorizAmp;\r\n\tfloat\t\t\tmShakeVertVel;\r\n\tfloat\t\t\tmShakeHorizVel;\r\n\t\r\n\tfloat\t\t\tmLean;\t\t\t\t\t// For lean during grind imbalance.\r\n\r\n\tfloat\t\t\tmLerpXZ;\r\n\tfloat\t\t\tmLerpY;\r\n\tfloat\t\t\tmVertAirLerpXZ;\r\n\tfloat\t\t\tmVertAirLerpY;\r\n\tfloat\t\t\tmGrindLerp;\r\n};\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_SKATERCAM_H\r\n"
  },
  {
    "path": "Code/Sk/Objects/skatercareer.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObjects (OBJ) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobjects/SkaterCareer.cpp\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t21/5/01 - Mick (Based on SkaterApperance.cpp by gj)\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSkater career code \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <objects/skatercareer.h>\r\n#include <objects/gap.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/string.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n\r\nbool g_CheatsEnabled = false;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n\r\nstatic bool\t\t\t\t\t\ts_is_competition[CSkaterCareer::vMAX_CAREER_LEVELS];\r\n\t\r\n\t\r\n\t\r\n\r\nint CountOnes(uint32 v)\r\n{\r\n\t\r\n\r\n\tint NumOnes=0;\r\n\tfor (int i=0; i<32; ++i)\r\n\t{\r\n\t\tif (v&1)\r\n\t\t{\r\n\t\t\t++NumOnes;\r\n\t\t}\r\n\t\tv>>=1;\r\n\t}\t\t\r\n\treturn NumOnes;\r\n}\r\n\r\nint CountOnes(uint64 v)\r\n{\r\n\t\r\n\r\n\tint NumOnes=0;\r\n\tfor (int i=0; i<64; ++i)\r\n\t{\r\n\t\tif (v&1)\r\n\t\t{\r\n\t\t\t++NumOnes;\r\n\t\t}\r\n\t\tv>>=1;\r\n\t}\t\t\r\n\treturn NumOnes;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterCareer::CSkaterCareer()\r\n{\r\n   \r\n\tfor (unsigned int i = 0; i<vMAX_CAREER_LEVELS; i++)\r\n\t{\r\n\t\tmp_gap_checklist[i] = new Obj::CGapChecklist;\r\n\t\tm_level_visited[i] = false;\r\n\t} \r\n\r\n\tInit();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCSkaterCareer::~CSkaterCareer()\r\n{\r\n\tfor (unsigned int i = 0; i<vMAX_CAREER_LEVELS; i++)\r\n\t{\r\n\t\tdelete mp_gap_checklist[i];\r\n\t} \t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCareer::Init( bool init_gaps /*= true*/ )\r\n{\t\r\n\t// Reset everything to \"Not Done Yet\"\r\n\t// Note: we do not currently reset the gap checklist here\r\n\t// I'm not sure at what point we would want to do that \r\n\t\r\n\tfor (unsigned int i = 0; i<vMAX_CAREER_LEVELS; i++)\r\n\t{\r\n\t\tm_goal_flags[i][0] = 0;\r\n\t\tm_level_flags[i][0] = 0;\r\n\t\tm_goal_flags[i][1] = 0;\r\n\t\tm_level_flags[i][1] = 0;\r\n\t\ts_is_competition[i] = false;\r\n\t}\r\n\t\r\n\tm_start_goal_flags[0] = 0;\r\n\tm_start_level_flags[0] = 0;\r\n\tm_start_goal_flags[1] = 0;\r\n\tm_start_level_flags[1] = 0;\r\n\r\n\tm_current_level = 0;\r\n\t\r\n\tif ( init_gaps )\r\n\t{\r\n\t\tfor ( uint32 i = 0; i < vMAX_CAREER_LEVELS; i++ )\r\n\t\t{\r\n\t\t\tObj::CGapChecklist* pGapChecklist = GetGapChecklist( i );\r\n\t\t\tpGapChecklist->Reset();\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCareer::Reset()\r\n{\r\n\t\r\n\t\r\n\tInit(false);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n// Return the gap checklist, either for the current level\r\n// of for the level specified\r\n\t\t\t\t\t \r\n\t\t\t\t\t \r\nObj::CGapChecklist\t*\t\tCSkaterCareer::GetGapChecklist(int level)\r\n{\r\n\tif (level == -1)\r\n\t{\r\n\t\tlevel = m_current_level;\r\n\t}\r\n\r\n\tDbg_MsgAssert(level >= 0 && level < (int)vMAX_CAREER_LEVELS,(\"bad level number (%d) in  GetGapChecklist\",level));\r\n\treturn mp_gap_checklist[level];\r\n}\r\n\r\nbool CSkaterCareer::GotAllGaps()\r\n{\r\n\t//Rulon: Made this function more robust to handle the changing level arrangement.\r\n\tScript::CArray *p_array = Script::GetArray(CRCD(0xeb1a4bc9,\"levels_with_gaps\"),Script::ASSERT);\r\n\tuint32 array_size = p_array->GetSize();\r\n\r\n\tfor ( uint32 i = 0; i < vMAX_CAREER_LEVELS; ++i )\r\n\t{\r\n\t\t// Skip up levels we dont care about\r\n\t\tuint32 j = 0;\r\n\t\tfor ( j = 0; j < array_size; ++j) \r\n\t\t{\r\n\t\t\tuint32 check = p_array->GetChecksum(j);\r\n\t\t\tuint32 level_num = Script::GetInt(check ,Script::ASSERT);\r\n\t\t\tif( i == level_num )\r\n\t\t\t{\r\n\t\t\t\t//printf(\"level %i\\n\", i);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif (j == array_size)\r\n\t\t\tcontinue;\r\n\r\n\t\tObj::CGapChecklist* pGapChecklist = GetGapChecklist( i );\r\n\t\t\r\n\t\t// If this level should be taken into account but is unvisited\r\n\t\tif ( !this->HasVisitedLevel( i ) )\r\n\t\t{\r\n\t\t\t //printf(\"haven't been to level %i\\n\", i);\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tif ( !pGapChecklist->GotAllGaps() )\r\n\t\t{\r\n\t\t\t//printf(\"didn't get all the gaps in level %i\\n\", i);\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t //printf(\"got all gaps in level %i\\n\", i);\r\n\t}\r\n\t  return true;\r\n\t\r\n}\r\n\t\t\t\t\t \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSkaterCareer::StartLevel(int level)\r\n{\r\n\t\r\n\r\n\tif (level == -1)\r\n\t{\r\n\t\tlevel = m_current_level;\r\n\t}\r\n\telse\r\n\t{\t\r\n\t\tm_current_level = level;\r\n\t}\r\n\r\n\tthis->MarkLevelVisited( m_current_level );\r\n\r\n\tDbg_MsgAssert(m_current_level < (int)vMAX_CAREER_LEVELS,( \"level number %d too big\",m_current_level)); \r\n\tm_start_goal_flags[0]\t= m_goal_flags[level][0];\r\n\tm_start_goal_flags[1]\t= m_goal_flags[level][1];\r\n\tm_start_level_flags[0]\t= m_level_flags[level][0];\r\n\tm_start_level_flags[1]\t= m_level_flags[level][1];\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint CSkaterCareer::GetLevel()\r\n{\r\n\t\r\n\treturn m_current_level;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterCareer::MarkLevelVisited( int level_num )\r\n{\r\n\tDbg_MsgAssert( level_num >= 0 && level_num < (int)vMAX_CAREER_LEVELS, ( \"MarkLevelVisited called with bad level num %i\", level_num ) );\r\n\tm_level_visited[level_num] = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CSkaterCareer::HasVisitedLevel( int level_num )\r\n{\r\n\tDbg_MsgAssert( level_num >= 0 && level_num < (int)vMAX_CAREER_LEVELS, ( \"MarkLevelVisited called with bad level num %i\", level_num ) );\r\n\treturn m_level_visited[level_num];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSkaterCareer::SetGoal(int goal, int level)\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert(goal >= 0 && goal <256, (\"goal %d out of range\"));\r\n\t\r\n\tif (level == -1)\r\n\t{\r\n\t\tlevel = m_current_level;\r\n\t}\r\n\t\r\n\tm_goal_flags[level][goal>>5] |= (1<<(goal&31));\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSkaterCareer::UnSetGoal(int goal, int level)\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert(goal >= 0 && goal <256, (\"goal %d out of range\"));\r\n\t\r\n\t\r\n\tif (level == -1)\r\n\t{\r\n\t\tlevel = m_current_level;\r\n\t}\r\n\t\r\n\tm_goal_flags[level][goal>>5] &= ~(1<<(goal&31));\r\n\tm_start_goal_flags[goal>>5]  &= ~(1<<(goal&31));\r\n\t\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCSkaterCareer::GetGoal(int goal, int level)\r\n{\r\n\t\r\n\tDbg_MsgAssert(goal >= 0 && goal <256, (\"goal %d out of range\"));\r\n\tif (level == -1)\r\n\t{\r\n\t\tlevel = m_current_level;\r\n\t}\r\n\t\r\n\tif (m_goal_flags[level][goal>>5] & (1<<(goal&31)))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCSkaterCareer::JustGotGoal(int goal)\r\n{\r\n\t\r\n\tDbg_MsgAssert(goal >= 0 && goal <256, (\"goal %d out of range\"));\r\n\r\n\t// if start goal flag is different from the current one, then we must\r\n\t// have just got the goal\t\r\n\tif ((m_goal_flags[m_current_level][goal>>5] ^ m_start_goal_flags[goal>>5]) & (1<<(goal&31)) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n\r\n}\r\n\r\nint\tCSkaterCareer::CountGoalsCompleted(int level)\r\n{\r\n\t\r\n\tif (level == -1)\r\n\t{\r\n\t\tlevel = m_current_level;\r\n\t}\r\n\treturn CountOnes(m_goal_flags[level][0]) +  CountOnes(m_goal_flags[level][1]);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tCSkaterCareer::CountTotalGoalsCompleted()\r\n{\r\n\t\r\n\tint Goals=0;\r\n\tfor (uint i=0; i<vMAX_CAREER_LEVELS; ++i)\r\n\t{\r\n\t\tif (!s_is_competition[i])\r\n\t\t{\r\n\t\t\tGoals+=CountGoalsCompleted(i);\r\n\t\t}\r\n\t}\r\n\treturn Goals;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tCSkaterCareer::CountMedals()\r\n{\r\n\t\r\n\r\n\tint Medals=0;\r\n\tfor (uint i=0; i<vMAX_CAREER_LEVELS; ++i)\r\n\t{\r\n\t\tif (s_is_competition[i])\r\n\t\t{\r\n\t\t\tMedals += (CountGoalsCompleted(i) > 0) ? 1:0;\t\t// count one per level\r\n\t\t}\r\n\t}\r\n\treturn Medals;\r\n}\r\n\r\n// Returns 0 if no medal was won.\r\n// If a medal was won, it returns 1+the best-medal number, where the medal number is whatever it is defined to be\r\n// in goal_scripts.q\r\nint CSkaterCareer::GetBestMedal(int Level)\r\n{\r\n\t\r\n\t\r\n\tDbg_MsgAssert(Level>=0 && Level<(int)vMAX_CAREER_LEVELS,(\"Bad Level of %d sent to GetBestMedal\",Level));\r\n\t\r\n\tint Gold=Script::GetInteger(\"GOAL_GOLD\");\r\n\tint Silver=Script::GetInteger(\"GOAL_SILVER\");\r\n\tint Bronze=Script::GetInteger(\"GOAL_BRONZE\");\r\n\t\r\n\tDbg_MsgAssert(s_is_competition[Level],(\"Level %d is not a competition level\",Level));\r\n\t\r\n\tif (m_goal_flags[Level][Gold>>5] & (1<<Gold))\r\n\t{\r\n\t\treturn Gold+1;\r\n\t}\r\n\telse if (m_goal_flags[Level][Silver>>5] & (1<<Silver))\r\n\t{\r\n\t\treturn Silver+1;\r\n\t}\r\n\telse if (m_goal_flags[Level][Bronze>>5] & (1<<Bronze))\r\n\t{\r\n\t\treturn Bronze+1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 0;\r\n\t}\t\r\n\t\r\n\treturn 0;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCSkaterCareer::GetCheat(uint32 cheat_checksum)\r\n{\r\n\tg_CheatsEnabled = GetGlobalFlag(Script::GetInteger(cheat_checksum));\r\n\t// This should be the ONLY way we access the cheat flags, so we can override them in network games\r\n\t//if (GameNet::Manager::Instance()->InNetGame()) return false;\r\n\treturn g_CheatsEnabled;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSkaterCareer::SetGlobalFlag(int flag)\r\n{\r\n\t\r\n\tDbg_MsgAssert(flag<512,(\"Flag %d is over 255\",flag));\r\n\tm_global_flags[flag>>5] |= (1<<(flag&31));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSkaterCareer::UnSetGlobalFlag(int flag)\r\n{\r\n\t\r\n\tDbg_MsgAssert(flag<512,(\"Flag %d is over 255\",flag));\r\n\tm_global_flags[flag>>5] &= ~(1<<(flag&31));\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCSkaterCareer::GetGlobalFlag(int flag)\r\n{\r\n\t\r\n\tDbg_MsgAssert(flag<512,(\"Flag %d is over 255\",flag));\r\n\tif (m_global_flags[flag>>5] & (1<<(flag&31)))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSkaterCareer::SetFlag(int flag, int level)\r\n{\r\n\t\r\n\tDbg_MsgAssert(flag<256,(\"Flag %d is over 255\",flag));\r\n\tif (level == -1)\r\n\t{\r\n\t\tlevel = m_current_level;\r\n\t}\r\n\tm_level_flags[level][flag>>5] |= (1<<(flag&31));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCSkaterCareer::UnSetFlag(int flag, int level)\r\n{\r\n\t\r\n\tDbg_MsgAssert(flag<256,(\"Flag %d is over 255\",flag));\r\n\tif (level == -1)\r\n\t{\r\n\t\tlevel = m_current_level;\r\n\t}\r\n\tm_level_flags[level][flag>>5] &= ~(1<<(flag&31));\r\n\tm_start_level_flags[flag>>5]  &= ~(1<<(flag&31));\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCSkaterCareer::GetFlag(int flag, int level)\r\n{\r\n\t\r\n\tDbg_MsgAssert(flag<256,(\"Flag %d is over 255\",flag));\r\n\tif (level == -1)\r\n\t{\r\n\t\tlevel = m_current_level;\r\n\t}\r\n\t\r\n\tif (m_level_flags[level][flag>>5] & (1<<(flag&31)))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCSkaterCareer::JustGotFlag(int flag)\r\n{\r\n\t\r\n\tDbg_MsgAssert(flag<256,(\"Flag %d is over 255\",flag));\r\n\t// if start goal flag is different from the current one, then we must\r\n\t// have just got the goal\t\r\n\tif ((m_level_flags[m_current_level][flag>>5] ^ m_start_level_flags[flag>>5]) & (1<<(flag&31)) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n\r\nvoid CSkaterCareer::WriteIntoStructure(Script::CScriptStructure *pIn)\r\n{\r\n\t\r\n\t// Create an array for holding the goal flags\r\n\tScript::CArray *pGoalFlags=new Script::CArray;\r\n\tpGoalFlags->SetSizeAndType(8*vMAX_CAREER_LEVELS, ESYMBOLTYPE_INTEGER);\r\n\r\n\t// Wack 'em all in\r\n\tfor (unsigned int i = 0; i<vMAX_CAREER_LEVELS; ++i)\r\n\t{\r\n\t\tuint32 j;\r\n\t\tfor (j = 0;j<8;j++)\r\n\t\t{\r\n\t\t\tpGoalFlags->SetInteger(i*8+j,m_goal_flags[i][j]);\r\n\t\t}\r\n\t}\t\r\n\t\r\n\t// Create an array for holding the level flags\r\n\tScript::CArray *pLevelFlags=new Script::CArray;\r\n\tpLevelFlags->SetSizeAndType(8*vMAX_CAREER_LEVELS, ESYMBOLTYPE_INTEGER);\r\n\t\r\n\t// Wack 'em all in\r\n\tfor (unsigned int i = 0; i<vMAX_CAREER_LEVELS; ++i)\r\n\t{\r\n\t\tuint32 j;\r\n\t\tfor (j = 0;j<8;j++)\r\n\t\t{\r\n\t\t\tpLevelFlags->SetInteger(i*8+j,m_level_flags[i][j]);\r\n\t\t}\r\n\t}\t\r\n\r\n\t// Create an array for holding the global flags\r\n\tScript::CArray *pGlobalFlags=new Script::CArray;\r\n\tpGlobalFlags->SetSizeAndType(vMAX_GLOBAL_FLAGS, ESYMBOLTYPE_INTEGER);\r\n\t\r\n\t// Wack 'em all in\r\n\tfor (unsigned int i = 0; i<vMAX_GLOBAL_FLAGS; ++i)\r\n\t{\r\n\t\tpGlobalFlags->SetInteger(i,m_global_flags[i]);\r\n\t}\r\n\r\n#if 1\r\n\t// Create an array for holding the gap checklists\r\n\t\r\n\tScript::CArray *pGapChecklists=new Script::CArray;\r\n\tpGapChecklists->SetSizeAndType(vMAX_CAREER_LEVELS, ESYMBOLTYPE_STRUCTURE);\r\n\t\r\n\tfor (unsigned int i = 0; i<vMAX_CAREER_LEVELS; ++i)\r\n\t{\r\n\t\tCGapChecklist * p_checklist = GetGapChecklist(i);\r\n\t\tScript::CStruct *p_gap_struct = new Script::CScriptStructure; \r\n\t\tp_gap_struct->AddInteger(CRCD(0x651533ec,\"level\"),i);\r\n\t\tif (!p_checklist->IsValid())\r\n\t\t{\r\n\t\t\tp_gap_struct->AddInteger(CRCD(0x73f8ca00,\"valid\"),0);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_gap_struct->AddInteger(CRCD(0x73f8ca00,\"valid\"),1);\r\n\t\t\tint num_gaps = p_checklist->NumGaps();\r\n\t\t\t\r\n\t\t\tScript::CArray *p_gaps_array=new Script::CArray;\r\n\t\t\tp_gaps_array->SetSizeAndType(num_gaps, ESYMBOLTYPE_STRUCTURE);\r\n\r\n\t\t\tfor (int gap=0; gap<num_gaps; ++gap)\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct *p_struct = new Script::CStruct; \r\n\t\t\t\t\r\n\t\t\t\tp_struct->AddString(CRCD(0x699fcfc0,\"GapName\"),p_checklist->GetGapText(gap));\r\n\t\t\t\tp_struct->AddInteger(CRCD(0x25eb70db,\"GapCount\"),p_checklist->GetGapCount(gap));\r\n\t\t\t\tp_struct->AddInteger(CRCD(0x92ab03e8,\"GapScore\"),p_checklist->GetGapScore(gap));\r\n\t\t\t\t\r\n\t\t\t\tMth::Vector skater_start_pos;\r\n\t\t\t\tMth::Vector skater_start_dir;\r\n\t\t\t\tskater_start_pos.Set();\r\n\t\t\t\tskater_start_dir.Set();\r\n\t\t\t\tif (p_checklist->GetGapCount(gap))\r\n\t\t\t\t{\r\n\t\t\t\t\tp_checklist->GetSkaterStartPosAndDir(gap,&skater_start_pos,&skater_start_dir);\r\n\t\t\t\t}\t\t\t\t\r\n\t\t\t\t// The vectors are always added to keep the save structure size as constant as possible.\r\n\t\t\t\tp_struct->AddVector(CRCD(0xa4605544,\"SkaterStartPos\"),skater_start_pos[X],skater_start_pos[Y],skater_start_pos[Z]);\r\n\t\t\t\tp_struct->AddVector(CRCD(0x9e12c9f8,\"SkaterStartDir\"),skater_start_dir[X],skater_start_dir[Y],skater_start_dir[Z]);\r\n\t\t\t\t\r\n\t\t\t\tp_gaps_array->SetStructure(gap,p_struct);\r\n\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\tp_gap_struct->AddArrayPointer(CRCD(0xd76c173e,\"Gaps\"),p_gaps_array);\r\n\t\t}\r\n\t\tpGapChecklists->SetStructure(i,p_gap_struct);\r\n\t}\r\n#endif\r\n\r\n\tScript::CArray* pVisitedLevels = new Script::CArray();\r\n\tpVisitedLevels->SetSizeAndType( vMAX_CAREER_LEVELS, ESYMBOLTYPE_INTEGER );\r\n\tfor ( unsigned int i = 0; i < vMAX_CAREER_LEVELS; ++i )\r\n\t\tpVisitedLevels->SetInteger( i, m_level_visited[i] );\r\n\r\n\t// Insert the above arrays into a new structure.\r\n\tScript::CScriptStructure *pTemp=new Script::CScriptStructure;\r\n\tpTemp->AddComponent(Script::GenerateCRC(\"GoalFlags\"),ESYMBOLTYPE_ARRAY,(int)pGoalFlags);\r\n\tpTemp->AddComponent(Script::GenerateCRC(\"LevelFlags\"),ESYMBOLTYPE_ARRAY,(int)pLevelFlags);\r\n\tpTemp->AddComponent(Script::GenerateCRC(\"GlobalFlags\"),ESYMBOLTYPE_ARRAY,(int)pGlobalFlags);\r\n\t\r\n#if 1\t\r\n\tpTemp->AddComponent(Script::GenerateCRC(\"GapChecklists\"),ESYMBOLTYPE_ARRAY,(int)pGapChecklists);\r\n#endif\r\n\t\r\n\tpTemp->AddArrayPointer( \"VisitedLevels\", pVisitedLevels );\r\n\r\n\t// K: Added these for Zac so that when autoloading on startup it can automatically go\r\n\t// straight to the last level played\r\n\tMdl::Skate * p_skate_mod =  Mdl::Skate::Instance();\r\n\tpTemp->AddChecksum(CRCD(0xe3335d2f,\"LastLevelLoadScript\"),p_skate_mod->m_cur_level);\r\n\tpTemp->AddChecksum(CRCD(0x2cc06f5e,\"LastGameMode\"),p_skate_mod->GetGameMode()->GetNameChecksum());\r\n    pTemp->AddInteger(\"current_theme\",Script::GetInteger(\"stored_theme_prefix\"));\r\n\t\t\t\t\t \r\n\r\n\t// Thrust the new structure into the passed structure.\r\n\tDbg_MsgAssert(pIn,(\"NULL pIn\"));\r\n\tpIn->AddComponent(Script::GenerateCRC(\"Career\"),ESYMBOLTYPE_STRUCTUREPOINTER,(int)pTemp);\r\n\t\r\n\t// Note: The above arrays and structure are not deleted here, because pointers to them have\r\n\t// been given to the passed structure, so it will delete them when it gets deleted.\r\n\r\n//\tScript::PrintContents(pTemp);\r\n}\r\n\r\nvoid CSkaterCareer::ReadFromStructure(Script::CScriptStructure *pIn)\r\n{\r\n\t\r\n\tDbg_MsgAssert(pIn,(\"NULL pIn\"));\r\n\r\n\tScript::CScriptStructure *pCareer=NULL;\r\n\tpIn->GetStructure(\"Career\",&pCareer);\r\n\tDbg_MsgAssert(pCareer,(\"Missing Career structure in structure passed to CSkaterCareer::ReadFromStructure\"));\r\n\t\r\n\tScript::CArray *pGoalFlags=NULL;\r\n\tpCareer->GetArray(\"GoalFlags\",&pGoalFlags);\r\n\tDbg_MsgAssert(pGoalFlags,(\"Missing GoalFlags array in Career structure\"));\r\n\tDbg_MsgAssert(pGoalFlags->GetSize()==8*vMAX_CAREER_LEVELS,(\"Bad size of %d for goal flags array, expected %d\",pGoalFlags->GetSize(),vMAX_CAREER_LEVELS));\r\n\r\n\tScript::CArray *pLevelFlags=NULL;\r\n\tpCareer->GetArray(\"LevelFlags\",&pLevelFlags);\r\n\tDbg_MsgAssert(pLevelFlags,(\"Missing LevelFlags array in Career structure\"));\r\n\tDbg_MsgAssert(pLevelFlags->GetSize()==8*vMAX_CAREER_LEVELS,(\"Bad size of %d for level flags array, expected %d\",pGoalFlags->GetSize(),vMAX_CAREER_LEVELS));\r\n\r\n\tfor (unsigned int i = 0; i<vMAX_CAREER_LEVELS; ++i)\r\n\t{\r\n\t\tuint32 j;\r\n\t\tfor (j = 0;j<8;j++)\r\n\t\t{\r\n\t\t\tm_goal_flags[i][j]=pGoalFlags->GetInteger(i*8+j);\r\n\t\t}\r\n\t\t\r\n\t\tfor (j = 0;j<8;j++)\r\n\t\t{\r\n\t\t\tm_level_flags[i][j]=pLevelFlags->GetInteger(i*8+j);\r\n\t\t}\r\n\t}\t\r\n\t\r\n\tScript::CArray *pGlobalFlags=NULL;\r\n\tpCareer->GetArray(\"GlobalFlags\",&pGlobalFlags);\r\n\tDbg_MsgAssert(pGlobalFlags,(\"Missing GlobalFlags array in Career structure\"));\r\n\tDbg_MsgAssert(pGlobalFlags->GetSize()==vMAX_GLOBAL_FLAGS,(\"Bad size of %d for global flags array, expected %d\",pGlobalFlags->GetSize(),vMAX_GLOBAL_FLAGS));\r\n\tfor (unsigned int i = 0; i<vMAX_GLOBAL_FLAGS; ++i)\r\n\t{\r\n\t\tm_global_flags[i]=pGlobalFlags->GetInteger(i);\r\n\t}\r\n\t\r\n\tScript::CArray *pGapChecklists = NULL;\r\n\tpCareer->GetArray(\"GapChecklists\",&pGapChecklists);\t\r\n\t//Dbg_MsgAssert(pGapChecklists,(\"Missing Gap checklist in Career structure\"));\r\n\tDbg_MsgAssert(pGapChecklists->GetSize()==vMAX_CAREER_LEVELS,(\"Bad size of %d for gap checklist array, expected %d\",pGapChecklists->GetSize()==vMAX_CAREER_LEVELS));\r\n\tif (pGapChecklists)\r\n\t{\r\n\t\tfor (unsigned int i = 0; i<vMAX_CAREER_LEVELS; ++i)\r\n\t\t{\r\n\t\t\tCGapChecklist * p_checklist = GetGapChecklist(i);\r\n\t\t\tp_checklist->FlushGapChecks();\r\n\t\t\tScript::CStruct *p_gap_struct = pGapChecklists->GetStructure(i);\r\n\t\t\tint level = 0;\r\n\t\t\tint valid = 0;\r\n\t\t\tp_gap_struct->GetInteger(\"level\",&level,true);\r\n\t\t\tp_gap_struct->GetInteger(\"valid\",&valid,true);\r\n\t\t\tif (valid)\r\n\t\t\t{\r\n\t\t\t\tScript::CArray *p_gaps=NULL;\r\n\t\t\t\tp_gap_struct->GetArray(CRCD(0xd76c173e,\"Gaps\"),&p_gaps);\r\n\t\t\t\tDbg_MsgAssert(p_gaps,(\"Missing gaps array\"));\r\n\t\t\t\t\r\n\t\t\t\tint num_gaps = p_gaps->GetSize();\r\n\t\t\t\tfor (int gap = 0; gap<num_gaps; gap++)\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct *p_struct=p_gaps->GetStructure(gap);\r\n\t\t\t\t\t\r\n\t\t\t\t\tconst char *p_name = NULL;\r\n\t\t\t\t\tint count = 0;\r\n\t\t\t\t\tint score = 0;\r\n\t\t\t\t\tp_struct->GetString(CRCD(0x699fcfc0,\"GapName\"),&p_name);\r\n\t\t\t\t\tp_struct->GetInteger(CRCD(0x25eb70db,\"GapCount\"),&count);\r\n\t\t\t\t\tp_struct->GetInteger(CRCD(0x92ab03e8,\"GapScore\"),&score);\r\n\t\t\t\t\tp_checklist->AddGapCheck(p_name,count,score);  \r\n\t\t\t\t\t\r\n\t\t\t\t\tif (count)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMth::Vector skater_start_pos;\r\n\t\t\t\t\t\tMth::Vector skater_start_dir;\r\n\t\t\t\t\t\tp_struct->GetVector(CRCD(0xa4605544,\"SkaterStartPos\"),&skater_start_pos);\r\n\t\t\t\t\t\tp_struct->GetVector(CRCD(0x9e12c9f8,\"SkaterStartDir\"),&skater_start_dir);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tp_checklist->SetInfoForCamera(p_name,skater_start_pos,skater_start_dir);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t//printf (\"%d: %s (%d)\\n\",level,p_name,count);\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tScript::CArray* pVisitedLevels = NULL;\r\n\tpCareer->GetArray( \"VisitedLevels\", &pVisitedLevels, Script::NO_ASSERT );\r\n\tif ( pVisitedLevels )\r\n\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\tint size = pVisitedLevels->GetSize();\r\n\t\tDbg_MsgAssert( size <= (int)vMAX_CAREER_LEVELS, ( \"wrong array size\" ) );\r\n#endif\t\t// __NOPT_ASSERT__\r\n\t\tfor ( int i = 0; i < (int)vMAX_CAREER_LEVELS; i++ )\r\n\t\t\tm_level_visited[i] = pVisitedLevels->GetInteger( i );\r\n\t}\r\n}\r\n\r\n} // namespace Obj\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/skatercareer.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tObject (OBJ)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tobjects/SkaterCareer.h\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t21/5/01 - Mick (Based on SkaterApperance.h by gj)\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __OBJECTS_SKATERCAREER_H\r\n#define __OBJECTS_SKATERCAREER_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n    #include <core/defines.h>\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n}\t\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tForward Declarations\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass\tCGapChecklist;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Class Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  CSkaterCareer  : public Spt::Class\r\n{\r\n\t\r\n\r\n\tpublic:\r\n\t\tenum\r\n\t\t{\r\n\t\t\tvVERSION_NUMBER = 0x00000001,\r\n\t\t\tvMAX_CAREER_LEVELS = 21, \t\t// changes in this are handled automatically, so don't change the version number\r\n\t\t\tvMAX_GLOBAL_FLAGS = 16,\r\n\t\t\tvMAGIC_NUMBER = 0x84751129,\t\t// magic terminator, for integrity check\r\n\t\t\tvNUM_FLAG_BITS = 64,\t\t\t// used for assertions\r\n\t\t};\r\n\t\r\n\t\tCSkaterCareer();\r\n\t\tvirtual\t\t\t\t\t\t~CSkaterCareer();\r\n\r\n\tpublic:\r\n\t\t// for memory card loading/saving\r\n\t\tuint32\t\t\t\t\t\tWriteToBuffer(uint8* pBuffer, uint32 bufferSize);\r\n\t\tuint8*\t\t\t\t\t\tReadFromBuffer(uint8* pBuffer);\r\n\t\tvoid \t\t\t\t\t\tReadFromStructure(Script::CStruct *pIn);\r\n\t\tvoid \t\t\t\t\t\tWriteIntoStructure(Script::CStruct *pIn);\r\n\r\n\t\t// Initialize the career to \"Nothing Done Yet\" \r\n\t\tbool\t\t\t\t\t\tInit( bool init_gaps = true );\r\n\r\n\t\t// Reset's the career to \"Nothing Done Yet\"\r\n\t\tbool\t\t\t\t\t\tReset( void );\r\n\r\n\r\n\t\t// Start the level, setting the default level number\r\n\t\t// and remembering which goals and flags were set at the start of this level\r\n\t\tvoid\t\t\t\t\t\tStartLevel(int level = -1);\r\n\t\t\r\n\t\t// Access function for Level. Added by Ken, used by CareerLevelIs script command.\r\n\t\tint\t\t\t\t\t\t\tGetLevel();\r\n\r\n\t\t// marks a level visited\r\n\t\tvoid\t\t\t\t\t\tMarkLevelVisited( int level_num );\r\n\t\tbool\t\t\t\t\t\tHasVisitedLevel( int level_num );\r\n\r\n\t\t// Access functions for goals and flags\r\n\t\tvoid\t\t\t\t\t\tSetGoal(int goal, int level = -1);\r\n\t\tvoid\t\t\t\t\t\tUnSetGoal(int goal, int level = -1);\r\n\t\tbool\t\t\t\t\t\tGetGoal(int goal, int level = -1);\r\n\t\tint\t\t\t\t\t\t\tCountGoalsCompleted(int level = -1);\r\n\t\tbool\t\t\t\t\t\tJustGotGoal(int goal);\r\n\t\t\r\n\t\tvoid\t\t\t\t\t\tSetFlag(int flag, int level = -1);\r\n\t\tvoid\t\t\t\t\t\tUnSetFlag(int flag, int level = -1);\r\n\t\tbool\t\t\t\t\t\tGetFlag(int flag, int level = -1);\r\n\t\t\r\n\t\tbool\t\t\t\t\t\tGetCheat(uint32 cheat_checksum);\r\n\t\t\r\n\t\tvoid\t\t\t\t\t\tSetGlobalFlag(int flag);\r\n\t\tvoid\t\t\t\t\t\tUnSetGlobalFlag(int flag);\r\n\t\tbool\t\t\t\t\t\tGetGlobalFlag(int flag);\r\n\r\n\t\tbool\t\t\t\t\t\tJustGotFlag(int flag);\r\n\t\t\r\n\t\t\r\n\t\tint\t\t\t\t\t\t\tCountTotalGoalsCompleted();\r\n\t\tint\t\t\t\t\t\t\tCountMedals();\r\n\t\tint \t\t\t\t\t\tGetBestMedal(int Level);\r\n\t\t\r\n\t\tObj::CGapChecklist\t*\t\tGetGapChecklist(int level = -1);\r\n\t\tbool\t\t\t\t\t\tGotAllGaps();\r\n\r\n\r\n\tpublic:\r\n\t\t\r\n\tprotected:\r\n\t\tuint32\t\t\t\t\t\tm_goal_flags[vMAX_CAREER_LEVELS][8];\r\n\t\tuint32\t\t\t\t\t\tm_level_flags[vMAX_CAREER_LEVELS][8];\r\n\t\tuint32\t\t\t\t\t\tm_start_goal_flags[8];\r\n\t\tuint32\t\t\t\t\t\tm_start_level_flags[8];\r\n\t\t\r\n\t\tuint32\t\t\t\t\t\tm_global_flags[vMAX_GLOBAL_FLAGS];\t\t// 8x32 = 256 global flags\r\n\t\t\r\n\t\tint\t\t\t\t\t\t\tm_current_level;\r\n\t\t\r\n\t\tObj::CGapChecklist\t\t*   mp_gap_checklist[vMAX_CAREER_LEVELS];\r\n\t\tbool\t\t\t\t\t\tm_level_visited[vMAX_CAREER_LEVELS];\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Obj\r\n\r\n#endif\t// __OBJECTS_SKATERCAREER_H\r\n"
  },
  {
    "path": "Code/Sk/Objects/skaterflags.h",
    "content": "// Skaterflags.h\r\n\r\n#ifndef\t__SK_OBJECTS_SKATERFLAGS_H__\t\r\n#define\t__SK_OBJECTS_SKATERFLAGS_H__\t\r\n\r\nnamespace Obj\r\n{\r\n\t// Flags that can be toggled on and off, and also store how long since last toggle\r\n\t// This is used as an index into CSkater::m_flags\r\n\tenum\tESkaterFlag\r\n\t{\r\n\t\tTENSE = 0, \t\t\t\t\t// tensing for a jump, usually X pressed\t\t\t\t\t\t\t\t\t\t\t 0\r\n\t\t// SWITCH,\t\t\t\t\t// skating switch\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t 1\t\tNOTE: unused?\r\n\t\t// LEAN,\t\t\t\t\t// leaning L/R (might prohibit us doing other things\t\t\t\t\t\t\t\t 2\t\tNOTE: unused?\r\n\t\t// TENSE_ON_GROUND,\t\t\t// we were on the ground, and the tense flag was set\t\t\t\t\t\t\t\t 3\t\tNOTE: unused?\r\n\t\tFLIPPED,\t\t\t\t\t// animation is flipped\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t 4\r\n\t\tVERT_AIR,\t\t\t\t\t// True if we are going to vert air\t\t\t\t\t\t\t\t\t\t\t\t\t 5\r\n\t\tTRACKING_VERT,\t\t\t\t// True if we are tracking a vert surface below us \t\t\t\t\t\t\t\t\t 6\r\n\t\tLAST_POLY_WAS_VERT,\t\t\t// True if the last polygon we skated on was vert\t\t\t\t\t\t\t\t\t 7\r\n\t\tCAN_BREAK_VERT,\t\t\t\t// True if we can break the vert poly we are on\t\t\t\t\t\t\t\t\t\t 8\r\n\t\tCAN_RERAIL,\t\t\t\t\t// can get back on the rail again, ahead of rerail time\t\t\t\t\t\t\t\t 9\r\n\t\t// STARTED_END_OF_RUN,\t\t// true if the skater has started the \"end of run\" script\t\t\t\t\t\t\t 10\r\n\t\t// FINISHED_END_OF_RUN,\t\t// True if the skater has returned to his idle state after the \"end of run\" script\t 11\r\n\t\t// STARTED_GOAL_END_OF_RUN,\t// True if the goal_endofrun script has started\r\n\t\t// FINISHED_GOAL_END_OF_RUN,\r\n\t\tRAIL_SLIDING,\t\t\t\t// True if skater is railsliding\t\t\t\t\t\t\t\t\t\t\t\t\t 12\r\n\t\tCAN_HIT_CAR,\t\t\t\t// True is we can hit a car.  Set when on ground, or have negative y vel\t\t\t 13\r\n\t\tAUTOTURN,\t\t\t\t\t// True if we can autoturn\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t 14\r\n\t\tIS_BAILING,\t\t\t\t\t// True if skater is bailing...\t\t\t\t\t\t\t\t\t\t\t\t\t\t 15\r\n\t\t// IS_ENDING_RUN,\t\t\t// True is skater is in the process of ending his run\t\t\t\t\t\t\t\t 16\r\n\t\t// IS_ENDING_GOAL,\t\t\t// True if we're ending a goal\r\n\t\tSPINE_PHYSICS,\t\t\t\t// True is skater is going over a spine\t\t\t\t\t\t\t\t\t\t\t\t 17\r\n\t\tIN_RECOVERY,\t\t\t\t// True if recovering from going off vert\t\t\t\t\t\t\t\t\t\t\t 18\r\n\t\tSKITCHING,\t\t\t\t\t// True if we are being towed by a car\t\t\t\t\t\t\t\t\t\t\t\t 19\r\n\t\tOVERRIDE_CANCEL_GROUND,\t\t// True if we want to ignore the \"CANCEL_GROUND\" flag for gaps\t\t\t\t\t\t 20\r\n\t\tSNAPPED_OVER_CURB,\t\t\t// True if we snapped up or down a curb this frame (for use by camera)\t\t\t\t 21\r\n\t\tSNAPPED,\t\t\t\t\t// True if we snapped slightly this frame (for use by camera)\r\n\t\tIN_ACID_DROP,\t\t\t\t// True if we are in an acid drop\r\n\t\tAIR_ACID_DROP_DISALLOWED,\t// True if in-air acid drops are not currently allowed\r\n\t\tCANCEL_WALL_PUSH,\t\t\t// True if the current wallpush event is canceled via script\r\n\t\tNO_ORIENTATION_CONTROL,\t\t// True if spins and leans are turned off due to switching from walking\r\n\t\tNEW_RAIL,\t\t\t\t\t// True if the rail we land on is a \"new\" rail\r\n\t\tOLLIED_FROM_RAIL,\t\t\t// True if entered current air via an ollie out of a rail\r\n\t\t// NOTE: If anyone adds any more flags so that NUM_ESKATERFLAGS > 32, let Steve G know\r\n\r\n\t\tNUM_ESKATERFLAGS\r\n\t};\r\n\t\r\n\tenum EStateType\r\n\t{\r\n\t\tGROUND,\r\n\t\tAIR,\r\n\t\tWALL,\r\n\t\tLIP,\r\n\t\tRAIL,\r\n\t\tWALLPLANT\r\n\t};\r\n}\r\n\t\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Sk/Objects/skaterpad.cpp",
    "content": "// SkaterPad.cpp\r\n\r\n#include <sk\\objects\\skaterpad.h>\r\n#include <gel\\inpman.h>\r\n#include <core\\math.h>\r\n\r\n//#define\t\tPS2_SIMULATING_XBOX\r\n\r\n// The constructor of a skater pad just sets all the names\r\nCSkaterPad::CSkaterPad()\r\n{\r\n\t// Note: These names must match those used when defining event queries in .q files.\r\n\t// (Otherwise the queries won't work)\r\n\tm_up.SetName(\"UP\");\r\n\tm_down.SetName(\"DOWN\");\r\n\tm_left.SetName(\"LEFT\");\r\n\tm_right.SetName(\"RIGHT\");\r\n\tm_square.SetName(\"SQUARE\");\r\n\tm_circle.SetName(\"CIRCLE\");\r\n\tm_triangle.SetName(\"TRIANGLE\");\r\n\tm_x.SetName(\"X\");\r\n\tm_L1.SetName(\"L1\");\r\n\tm_L2.SetName(\"L2\");\r\n\tm_L3.SetName(\"L3\");\r\n\tm_R1.SetName(\"R1\");\r\n\tm_R2.SetName(\"R2\");\r\n\tm_R3.SetName(\"R3\");\r\n\tm_start.SetName(\"START\");\r\n\tm_select.SetName(\"SELECT\");\r\n\t\r\n\tm_leftAnalogUpDebounceTime = 0;\r\n\tm_leftAnalogDownDebounceTime = 0;\r\n}\r\n\r\n#ifdef __NOPT_ASSERT__\r\nvoid CSkaterPad::Update ( Inp::Data* input, bool debug )\r\n#else\r\nvoid CSkaterPad::Update ( Inp::Data* input )\r\n#endif\r\n{\r\n\t#ifdef __NOPT_ASSERT__\r\n\t\r\n\tm_up.Update(input->m_Event[Inp::Data::vA_UP] ? 255 : 0, debug);\r\n\tm_down.Update(input->m_Event[Inp::Data::vA_DOWN] ? 255 : 0, debug);\r\n\tm_left.Update(input->m_Event[Inp::Data::vA_LEFT] ? 255 : 0, debug);\r\n\tm_right.Update(input->m_Event[Inp::Data::vA_RIGHT] ? 255 : 0, debug);\r\n\r\n\tm_square.Update(input->m_Event[Inp::Data::vA_SQUARE] ? 255 : 0, debug);\r\n\tm_circle.Update(input->m_Event[Inp::Data::vA_CIRCLE] ? 255 : 0, debug);\r\n\tm_x.Update(input->m_Event[Inp::Data::vA_X] ? 255 : 0, debug);\r\n\tm_triangle.Update(input->m_Event[Inp::Data::vA_TRIANGLE] ? 255 : 0, debug);\r\n\r\n\tm_L1.Update(input->m_Event[Inp::Data::vA_L1] ? 255 : 0, debug);\r\n\tm_R1.Update(input->m_Event[Inp::Data::vA_R1] ? 255 : 0, debug);\r\n\r\n\t#ifndef\tPS2_SIMULATING_XBOX\r\n\tm_L2.Update(input->m_Event[Inp::Data::vA_L2] ? 255 : 0, debug);\r\n\tm_R2.Update(input->m_Event[Inp::Data::vA_R2] ? 255 : 0, debug);\r\n\t#else\t// update both 1 and 2 from L1/R1, to simulate the X-Box\r\n\tm_L2.Update(input->m_Event[Inp::Data::vA_L1] ? 255 : 0, debug);\r\n\tm_R2.Update(input->m_Event[Inp::Data::vA_R1] ? 255 : 0, debug);\r\n\t#endif\r\n\t\r\n\tm_L3.Update(input->m_Buttons & Inp::Data::mD_L3 ? 255 : 0, debug);\r\n\tm_R3.Update(input->m_Buttons & Inp::Data::mD_R3 ? 255 : 0, debug);\r\n\t\r\n\t\r\n\tm_select.Update(input->m_Buttons & Inp::Data::mD_SELECT ? 255 : 0, debug);\r\n\t\r\n\t#else\r\n\t\r\n\tm_up.Update(input->m_Event[Inp::Data::vA_UP] ? 255 : 0);\r\n\tm_down.Update(input->m_Event[Inp::Data::vA_DOWN] ? 255 : 0);\r\n\tm_left.Update(input->m_Event[Inp::Data::vA_LEFT] ? 255 : 0);\r\n\tm_right.Update(input->m_Event[Inp::Data::vA_RIGHT] ? 255 : 0);\r\n\r\n\tm_square.Update(input->m_Event[Inp::Data::vA_SQUARE] ? 255 : 0);\r\n\tm_circle.Update(input->m_Event[Inp::Data::vA_CIRCLE] ? 255 : 0);\r\n\tm_x.Update(input->m_Event[Inp::Data::vA_X] ? 255 : 0);\r\n\tm_triangle.Update(input->m_Event[Inp::Data::vA_TRIANGLE] ? 255 : 0);\r\n\r\n\tm_L1.Update(input->m_Event[Inp::Data::vA_L1] ? 255 : 0);\r\n\tm_R1.Update(input->m_Event[Inp::Data::vA_R1] ? 255 : 0);\r\n\r\n\t#ifndef\tPS2_SIMULATING_XBOX\r\n\tm_L2.Update(input->m_Event[Inp::Data::vA_L2] ? 255 : 0);\r\n\tm_R2.Update(input->m_Event[Inp::Data::vA_R2] ? 255 : 0);\r\n\t#else\t// update both 1 and 2 from L1/R1, to simulate the X-Box\r\n\tm_L2.Update(input->m_Event[Inp::Data::vA_L1] ? 255 : 0);\r\n\tm_R2.Update(input->m_Event[Inp::Data::vA_R1] ? 255 : 0);\r\n\t#endif\r\n\t\r\n\tm_L3.Update(input->m_Buttons & Inp::Data::mD_L3 ? 255 : 0);\r\n\tm_R3.Update(input->m_Buttons & Inp::Data::mD_R3 ? 255 : 0);\r\n\r\n\tm_select.Update(input->m_Buttons & Inp::Data::mD_SELECT ? 255 : 0);\r\n\t\r\n\t#endif\r\n\t\r\n\tint in;\r\n\t\r\n\tin = input->m_Event[Inp::Data::vA_RIGHT_X] - 128;\r\n\tif (in == 0)\r\n\t{\r\n\t\tm_scaled_rightX = 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (in == -128)\r\n\t\t{\r\n\t\t\tin = -127;\r\n\t\t}\r\n\t\tm_scaled_rightX = (in + (in > 0 ? -Inp::vANALOGUE_TOL : Inp::vANALOGUE_TOL)) / (127.0f - Inp::vANALOGUE_TOL);\r\n\t}\r\n\t\r\n\tin = input->m_Event[Inp::Data::vA_RIGHT_Y] - 128;\r\n\tif (in == 0)\r\n\t{\r\n\t\tm_scaled_rightY = 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (in == -128)\r\n\t\t{\r\n\t\t\tin = -127;\r\n\t\t}\r\n\t\tm_scaled_rightY = (in + (in > 0 ? -Inp::vANALOGUE_TOL : Inp::vANALOGUE_TOL)) / (127.0f - Inp::vANALOGUE_TOL);\r\n\t}\r\n\t\r\n\tin = input->m_Event[Inp::Data::vA_LEFT_X] - 128;\r\n\tif (in == 0)\r\n\t{\r\n\t\tm_scaled_leftX = 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (in == -128)\r\n\t\t{\r\n\t\t\tin = -127;\r\n\t\t}\r\n\t\tm_scaled_leftX = (in + (in > 0 ? -Inp::vANALOGUE_TOL : Inp::vANALOGUE_TOL)) / (127.0f - Inp::vANALOGUE_TOL);\r\n\t}\r\n\r\n\tin = input->m_Event[Inp::Data::vA_LEFT_Y] - 128;\r\n\tif (in == 0)\r\n\t{\r\n\t\tm_scaled_leftY = 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (in == -128)\r\n\t\t{\r\n\t\t\tin = -127;\r\n\t\t}\r\n\t\tm_scaled_leftY = (in + (in > 0 ? -Inp::vANALOGUE_TOL : Inp::vANALOGUE_TOL)) / (127.0f - Inp::vANALOGUE_TOL);\r\n\t}\r\n\t\r\n\tm_rightX = input->m_Event[Inp::Data::vA_RIGHT_X_UNCLAMPED] - 128;\r\n\tm_rightY = input->m_Event[Inp::Data::vA_RIGHT_Y_UNCLAMPED] - 128;\r\n\tm_leftX = input->m_Event[Inp::Data::vA_LEFT_X_UNCLAMPED] - 128;\r\n\tm_leftY = input->m_Event[Inp::Data::vA_LEFT_Y_UNCLAMPED] - 128;\r\n\t\r\n\t// Calculate the direction, and the amount\r\n\r\n\tm_rightLength = sqrtf(m_rightX * m_rightX + m_rightY * m_rightY);\r\n\tm_rightAngle = atan2f(m_rightX, -m_rightY);\r\n\r\n\tm_leftLength = sqrtf(m_leftX * m_leftX + m_leftY * m_leftY);\r\n\tif (m_leftLength > 0.001f)\r\n\t{\r\n\t\tm_leftAngle = atan2f(m_leftX, -m_leftY);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// if left analog stick not pressed, then get it from the D-Pad\r\n\t\tbool Up;\r\n\t\tbool Down;\r\n\t\tbool Left;\r\n\t\tbool Right;\r\n\t\tUp = input->m_Event[Inp::Data::vA_UP];\r\n\t\tDown = input->m_Event[Inp::Data::vA_DOWN];\r\n\t\tLeft = input->m_Event[Inp::Data::vA_LEFT];\r\n\t\tRight = input->m_Event[Inp::Data::vA_RIGHT];\r\n\r\n\t\tif (Up || Down || Left || Right)\r\n\t\t{\r\n\t\t\tm_leftAngle = sGetAngleFromDPad(Up, Down, Left, Right);\r\n\t\t\tm_leftLength = 127.0f;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_leftAngle = 0.0f;\r\n\t\t\tm_leftLength = 0.0f;\t\t\t\t\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (m_leftAnalogUpDebounceTime)\r\n\t{\r\n\t\t// if not pressed, or debounce time expired\r\n\t\tif (m_leftLength == 0.0f || !(Mth::Abs(m_leftAngle) < Mth::DegToRad(45.0f)))\r\n\t\t{\r\n\t\t\tm_leftAnalogUpDebounceTime = 0;\r\n\t\t}\r\n\t\telse if ((float)Tmr::GetTime() > m_leftAnalogUpDebounceTime)\r\n\t\t{\r\n\t\t\tm_leftAnalogUpDebounceTime = 0;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (m_leftAnalogDownDebounceTime)\r\n\t{\r\n\t\t// if not pressed, or debounce time expired\r\n\t\tif (m_leftLength == 0.0f || !((Mth::PI - Mth::Abs(m_leftAngle)) < Mth::DegToRad(45.0f)))\r\n\t\t{\r\n\t\t\tm_leftAnalogDownDebounceTime = 0;\r\n\t\t}\r\n\t\telse if ((float)Tmr::GetTime() > m_leftAnalogDownDebounceTime)\r\n\t\t{\r\n\t\t\tm_leftAnalogDownDebounceTime = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nCSkaterButton *CSkaterPad::GetButton(uint32 NameChecksum)\r\n{\r\n\t\r\n\t// Maybe optimize using a hash table later for speed.\r\n\tif (m_up.GetName()==NameChecksum) return &m_up;\r\n\telse if (m_down.GetName()==NameChecksum) return &m_down;\r\n\telse if (m_left.GetName()==NameChecksum) return &m_left;\r\n\telse if (m_right.GetName()==NameChecksum) return &m_right;\r\n\telse if (m_square.GetName()==NameChecksum) return &m_square;\r\n\telse if (m_circle.GetName()==NameChecksum) return &m_circle;\r\n\telse if (m_triangle.GetName()==NameChecksum) return &m_triangle;\r\n\telse if (m_x.GetName()==NameChecksum) return &m_x;\r\n\telse if (m_L1.GetName()==NameChecksum) return &m_L1;\r\n\telse if (m_L2.GetName()==NameChecksum) return &m_L2;\r\n\telse if (m_L3.GetName()==NameChecksum) return &m_L3;\r\n\telse if (m_R1.GetName()==NameChecksum) return &m_R1;\r\n\telse if (m_R2.GetName()==NameChecksum) return &m_R2;\r\n\telse if (m_R3.GetName()==NameChecksum) return &m_R3;\r\n\telse if (m_start.GetName()==NameChecksum) return &m_start;\r\n\telse if (m_select.GetName()==NameChecksum) return &m_select;\r\n\telse \r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"Bad checksum '%x' sent to GetButton\",NameChecksum));\r\n\t}\r\n\treturn NULL;\r\n}\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\nfloat\tCSkaterPad::GetScaledAnalogStickMagnitude ( float analog_x, float analog_y, float analog_angle )\r\n{\r\n\tfloat x = analog_x / (analog_x > 0.0f ? 127.0f : 128.0f);\r\n\tfloat y = analog_y / (analog_y > 0.0f ? 127.0f : 128.0f);\r\n\t\r\n\t#ifndef __PLAT_NGC__\r\n\t\r\n\tfloat angle;\r\n\tif (analog_angle > (-Mth::PI / 4.0f) && analog_angle < (Mth::PI / 4.0f))\r\n\t{\r\n\t\t// top quadrant\r\n\t\tangle = analog_angle;\r\n\t}\r\n\telse if (analog_angle > (Mth::PI / 4.0f) && analog_angle < (3.0f * Mth::PI / 4.0f))\r\n\t{\r\n\t\t// right quadrant\r\n\t\tangle = analog_angle - (Mth::PI / 2.0f);\r\n\t}\r\n\telse if (Mth::Abs(analog_angle) > (3.0f * Mth::PI / 4.0f))\r\n\t{\r\n\t\t// bottom quadrant\r\n\t\tangle = Mth::Abs(analog_angle) - Mth::PI;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// left quadrant\r\n\t\tangle = analog_angle + (Mth::PI / 2.0f);\r\n\t}\r\n\t\r\n\treturn sqrtf(x * x + y * y) * Mth::Abs(cosf(angle));\r\n\t\r\n\t#else\r\n\t\r\n\treturn sqrtf(x * x + y * y);\r\n\t\r\n\t#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint32\tCSkaterPad::GetPressedMask( void )\r\n{\r\n\tuint32 mask;\r\n\r\n\tmask = 0;\r\n\r\n\tif( m_up.GetPressed())\r\n\t{\r\n\t\tmask |= Inp::Data::mA_UP;\r\n\t}\r\n\tif( m_down.GetPressed())\r\n\t{\r\n\t\tmask |= Inp::Data::mA_DOWN;\r\n\t}\r\n\tif( m_left.GetPressed())\r\n\t{\r\n\t\tmask |= Inp::Data::mA_LEFT;\r\n\t}\r\n\tif( m_right.GetPressed())\r\n\t{\r\n\t\tmask |= Inp::Data::mA_RIGHT;\r\n\t}\r\n\tif( m_L1.GetPressed())\r\n\t{\r\n\t\tmask |= Inp::Data::mA_L1;\r\n\t}\r\n\tif( m_L2.GetPressed())\r\n\t{\r\n\t\tmask |= Inp::Data::mA_L2;\r\n\t}\r\n\tif( m_R1.GetPressed())\r\n\t{\r\n\t\tmask |= Inp::Data::mA_R1;\r\n\t}\r\n\tif( m_R2.GetPressed())\r\n\t{\r\n\t\tmask |= Inp::Data::mA_R2;\r\n\t}\r\n\tif( m_circle.GetPressed())\r\n\t{\r\n\t\tmask |= Inp::Data::mA_CIRCLE;\r\n\t}\r\n\tif( m_square.GetPressed())\r\n\t{\r\n\t\tmask |= Inp::Data::mA_SQUARE;\r\n\t}\r\n\tif( m_triangle.GetPressed())\r\n\t{\r\n\t\tmask |= Inp::Data::mA_TRIANGLE;\r\n\t}\r\n\tif( m_x.GetPressed())\r\n\t{\r\n\t\tmask |= Inp::Data::mA_X;\r\n\t}\r\n\t\t\r\n\treturn mask;\r\n}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the pressed state of the four cardinal directions\r\n// then return a sensible value including diagonals\r\n// given that we might be pressing opposing directions (Up+Down)\r\n// and we still want to get some sensible response\r\n// Here Up+Down is mapped to PAD_D\r\n// all mapping where there is some conflict needing resolution are\r\n// marked with an asterix\r\nuint32 CSkaterPad::sGetDirection(bool Up, bool Down, bool Left, bool Right)\r\n{\r\n\tint Dir = Up + (Down << 1) + (Left << 2) + (Right << 3);\r\n\r\n\tstatic uint DirectionMap[16] =\r\n\t{\r\n\t\t// RLDU\r\n\t\t0,\t\t\t\t// 0000\r\n\t\tPAD_U,\t\t// 0001\r\n\t\tPAD_D,\t\t// 0010\r\n\t\tPAD_D,\t\t// 0011\t *\r\n\t\tPAD_L,\t\t// 0100\r\n\t\tPAD_UL,\t\t// 0101\r\n\t\tPAD_DL,\t\t// 0110\r\n\t\tPAD_DL,\t\t// 0111\t *\r\n\t\tPAD_R,\t\t// 1000\r\n\t\tPAD_UR,\t\t// 1001\r\n\t\tPAD_DR,\t\t// 1010\r\n\t\tPAD_DR,\t\t// 1011\t *\r\n\t\tPAD_R,\t\t// 1100\t *\r\n\t\tPAD_UR,\t\t// 1101\t *\r\n\t\tPAD_DR,\t\t// 1110\t *\r\n\t\tPAD_DR,\t\t// 1111\t *\r\n\t};\r\n\r\n\treturn DirectionMap[Dir];\r\n}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#define\t\tPAD_ANGLE_U\t\t( 0.0f )\r\n#define\t\tPAD_ANGLE_UR\t( Mth::PI / 4.0f)\r\n#define\t\tPAD_ANGLE_R     ( Mth::PI / 2.0f) \r\n#define\t\tPAD_ANGLE_DR    ( Mth::PI * 3.0f / 4.0f)\r\n#define\t\tPAD_ANGLE_D\t\t( Mth::PI )\r\n#define\t\tPAD_ANGLE_DL\t( - Mth::PI * 3.0f / 4.0f) \r\n#define\t\tPAD_ANGLE_L\t\t( - Mth::PI / 2.0f ) \r\n#define\t\tPAD_ANGLE_UL\t( - Mth::PI / 4.0f) \r\n\r\nfloat CSkaterPad::sGetAngleFromDPad(bool Up, bool Down, bool Left, bool Right)\r\n{\r\n\tint Dir = Up + (Down << 1) + (Left << 2) + (Right << 3);\r\n\r\n\tstatic float DirectionMap[16] =\r\n\t{\r\n\t\t// RLDU\r\n\t\t0.0f,\t\t\t\t// 0000\r\n\t\tPAD_ANGLE_U,\t\t// 0001\r\n\t\tPAD_ANGLE_D,\t\t// 0010\r\n\t\tPAD_ANGLE_D,\t\t// 0011\t *\r\n\t\tPAD_ANGLE_L,\t\t// 0100\r\n\t\tPAD_ANGLE_UL,\t\t// 0101\r\n\t\tPAD_ANGLE_DL,\t\t// 0110\r\n\t\tPAD_ANGLE_DL,\t\t// 0111\t *\r\n\t\tPAD_ANGLE_R,\t\t// 1000\r\n\t\tPAD_ANGLE_UR,\t\t// 1001\r\n\t\tPAD_ANGLE_DR,\t\t// 1010\r\n\t\tPAD_ANGLE_DR,\t\t// 1011\t *\r\n\t\tPAD_ANGLE_R,\t\t// 1100\t *\r\n\t\tPAD_ANGLE_UR,\t\t// 1101\t *\r\n\t\tPAD_ANGLE_DR,\t\t// 1110\t *\r\n\t\tPAD_ANGLE_DR,\t\t// 1111\t *\r\n\t};\r\n\r\n\treturn DirectionMap[Dir];\r\n}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\nvoid CSkaterPad::Zero (   )\r\n{\r\n\tm_up.Update( 0 );\r\n\tm_down.Update( 0 );\r\n\tm_left.Update( 0 );\r\n\tm_right.Update( 0 );\r\n\tm_L1.Update( 0 );\r\n\tm_L2.Update( 0 );\r\n\tm_L3.Update( 0 );\r\n\tm_R1.Update( 0 );\r\n\tm_R2.Update( 0 );\r\n\tm_R3.Update( 0 );\r\n\tm_square.Update( 0 );\r\n\tm_circle.Update( 0 );\r\n\tm_x.Update( 0 );\r\n\tm_triangle.Update( 0 );\r\n\tm_start.Update( 0 );\r\n\tm_select.Update( 0 );\r\n\t\r\n\tm_rightX = 0.0f;\r\n\tm_rightY = 0.0f;\r\n\tm_leftX = 0.0f;\r\n\tm_leftY = 0.0f;\r\n\r\n\tm_scaled_rightX = 0.0f;\r\n\tm_scaled_rightY = 0.0f;\r\n\tm_scaled_leftX = 0.0f;\r\n\tm_scaled_leftY = 0.0f;\r\n\r\n\tm_rightAngle = 0.0f;\r\n\tm_rightLength = 0.0f;\r\n\tm_leftAngle = 0.0f;\r\n\tm_leftLength = 0.0f;\r\n}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CSkaterPad::Reset (   )\r\n{\r\n\tZero();\r\n\t\r\n\tm_up.ClearTrigger( );\r\n\tm_up.ClearRelease( );\r\n\tm_down.ClearTrigger( );\r\n\tm_down.ClearRelease( );\r\n\tm_left.ClearTrigger( );\r\n\tm_left.ClearRelease( );\r\n\tm_right.ClearTrigger( );\r\n\tm_right.ClearRelease( );\r\n\tm_L1.ClearTrigger( );\r\n\tm_L1.ClearRelease( );\r\n\tm_L2.ClearTrigger( );\r\n\tm_L2.ClearRelease( );\r\n\tm_L3.ClearTrigger( );\r\n\tm_L3.ClearRelease( );\r\n\tm_R1.ClearTrigger( );\r\n\tm_R1.ClearRelease( );\r\n\tm_R2.ClearTrigger( );\r\n\tm_R2.ClearTrigger( );\r\n\tm_R3.ClearRelease( );\r\n\tm_R3.ClearRelease( );\r\n\tm_square.ClearTrigger( );\r\n\tm_square.ClearRelease( );\r\n\tm_circle.ClearTrigger( );\r\n\tm_circle.ClearRelease( );\r\n\tm_x.ClearTrigger( );\r\n\tm_x.ClearRelease( );\r\n\tm_triangle.ClearTrigger( );\r\n\tm_triangle.ClearRelease( );\r\n\tm_start.ClearTrigger( );\r\n\tm_start.ClearRelease( );\r\n\tm_select.ClearTrigger( );\r\n\tm_select.ClearRelease( );\r\n}\r\n"
  },
  {
    "path": "Code/Sk/ParkEditor/EdRail.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\t\t      \t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\trjm\t\t\t\t\t\t\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <sk/ParkEditor/EdRail.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefinePoolableClass(Ed::RailPoint)\r\nDefinePoolableClass(Ed::RailString)\r\n\r\nnamespace Ed\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nRailPoint::RailPoint() :\r\n\tm_pos(0.0f, 0.0f, 0.0f, 0.0f)\r\n{\r\n\tmp_next = NULL;\r\n}\r\n\r\n\r\n\r\n\r\nRailPoint::~RailPoint() \r\n{\r\n}\r\n\r\n\r\n\r\n\r\nRailString::RailString()\r\n{\r\n\tmp_pointList = NULL;\r\n\tm_numPoints = 0;\r\n\tmp_next = NULL;\r\n\r\n\tm_isLoop = false;\r\n}\r\n\r\n\r\n\r\n\r\nRailString::~RailString()\r\n{\r\n}\r\n\r\n\r\n\r\n\r\nvoid RailString::AddPoint(RailPoint *pPoint)\r\n{\r\n\tif (!mp_pointList)\r\n\t\tmp_pointList = pPoint;\r\n\telse\r\n\t\tmp_lastPoint->mp_next = pPoint;\r\n\tmp_lastPoint = pPoint;\r\n\tm_numPoints++;\r\n}\r\n\r\n\r\n\r\n\r\nvoid RailString::Destroy()\r\n{\r\n\tRailPoint *pPoint = mp_pointList;\r\n\twhile(pPoint)\r\n\t{\r\n\t\tRailPoint *pNext = pPoint->mp_next;\r\n\t\tmp_parentSet->DestroyRailPoint(pPoint);\r\n\t\tpPoint = pNext;\r\n\t}\r\n\tmp_pointList = NULL;\r\n\tmp_lastPoint = NULL;\r\n\tm_numPoints = 0;\r\n}\r\n\r\n\r\n\r\n\r\nint\tRailString::CountLinkedPoints()\r\n{\r\n\t\r\n\r\n\tif (m_isLoop)\r\n\t\treturn Count();\r\n\r\n\tint count = 0;\r\n\tfor (RailPoint *pPoint = mp_pointList; pPoint != NULL; pPoint = pPoint->mp_next)\r\n\t\tcount++;\r\n\r\n\tDbg_MsgAssert(count > 1, (\"invalid number of linked rail points in a rail (%d) need 2 or more\",count));\r\n\treturn count - 1;\r\n}\r\n\r\n\r\n\r\n\r\nvoid RailString::CopyOffsetAndRot(RailString *pSource, Mth::Vector &pos, int rot, uint32 piece_id)\r\n{\r\n\tRailPoint *pSourcePt = pSource->GetList();\r\n\r\n\twhile(pSourcePt)\r\n\t{\r\n\t\tRailPoint *pOut = mp_parentSet->CreateRailPoint();\r\n\t\tfloat x = 0.0f, z = 0.0f;\r\n\t\tswitch(rot)\r\n\t\t{\r\n\t\t\tcase 0:\r\n\t\t\t\tx =  pSourcePt->m_pos.GetX();\r\n\t\t\t\tz = pSourcePt->m_pos.GetZ();\r\n// GJ:  No longer need to negate the Z component, now that we're using new-style \"Pos\" vectors!\r\n//\t\t\t\tz = -pSourcePt->m_pos.GetZ();\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1:\r\n\t\t\t\tx = pSourcePt->m_pos.GetZ();\r\n\t\t\t\tz = -pSourcePt->m_pos.GetX();\r\n// GJ:  No longer need to negate the Z component, now that we're using new-style \"Pos\" vectors!\r\n//\t\t\t\tz = pSourcePt->m_pos.GetX();\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\tx = -pSourcePt->m_pos.GetX();\r\n\t\t\t\tz = -pSourcePt->m_pos.GetZ();\r\n// GJ:  No longer need to negate the Z component, now that we're using new-style \"Pos\" vectors!\r\n//\t\t\t\tz = pSourcePt->m_pos.GetZ();\r\n\t\t\t\tbreak;\r\n\t\t\tcase 3:\r\n\t\t\t\tx =  -pSourcePt->m_pos.GetZ();\r\n\t\t\t\tz =  pSourcePt->m_pos.GetX();\r\n// GJ:  No longer need to negate the Z component, now that we're using new-style \"Pos\" vectors!\r\n//\t\t\t\tz =  -pSourcePt->m_pos.GetX();\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tfloat y = pSourcePt->m_pos.GetY() +\tpos.GetY();\r\n\t\tx += pos.GetX();\r\n\t\tz += pos.GetZ();\r\n// GJ:  No longer need to negate the Z component, now that we're using new-style \"Pos\" vectors!\r\n\t\tpOut->m_pos.Set(x, y, z);\r\n//\t\tpOut->m_pos.Set(x, y, -z);\r\n\t\tpOut->m_type = pSourcePt->m_type;\r\n\t\tpOut->m_objectId = piece_id;\r\n\r\n\t\tAddPoint(pOut);\r\n\r\n\t\tpSourcePt = pSourcePt->GetNext();\r\n\t}\r\n\r\n\tm_id = pSource->m_id;\r\n\tm_isLoop = pSource->m_isLoop;\r\n}\r\n\r\n\r\n\r\n\r\nRailSet::RailSet()\r\n{\r\n\tmp_stringList = NULL;\r\n\tm_numStrings = 0;\r\n\r\n\tmp_pointAllocator = NULL;\r\n\tmp_stringAllocator = NULL;\r\n}\r\n\r\n\r\n\r\n\r\nRailSet::~RailSet()\r\n{\r\n}\r\n\r\n\r\n\r\n\r\nvoid RailSet::AddString(RailString *pString)\r\n{\r\n\tif (!mp_stringList)\r\n\t\tmp_stringList = pString;\r\n\telse\r\n\t\tmp_lastString->mp_next = pString;\r\n\tmp_lastString = pString;\r\n\tm_numStrings++;\r\n}\r\n\r\n\r\n\r\n\r\nvoid RailSet::Destroy()\r\n{\r\n\tRailString *pString = mp_stringList;\r\n\twhile(pString)\r\n\t{\r\n\t\tRailString *pNext = pString->mp_next;\r\n\t\tpString->Destroy();\r\n\t\tDestroyRailString(pString);\r\n\t\tpString = pNext;\r\n\t}\r\n\tmp_stringList = NULL;\r\n\tmp_lastString = NULL;\r\n\tm_numStrings = 0;\r\n}\r\n\r\n\r\n\r\n\r\nint RailSet::CountPoints()\r\n{\r\n\tint num_points = 0;\r\n\tRailString *pString = mp_stringList;\r\n\twhile (pString)\r\n\t{\r\n\t\tnum_points += pString->Count();\r\n\t\tpString = pString->GetNext();\r\n\t}\r\n\r\n\treturn num_points;\r\n}\r\n\r\n\r\n\r\n\r\nRailString *RailSet::GetString(uint32 id, int requested_num)\r\n{\r\n\tRailString *pString = mp_stringList;\r\n\tint num = 0;\r\n\twhile(pString)\r\n\t{\r\n\t\tif (pString->m_id == id)\r\n\t\t{\r\n\t\t\tif (num == requested_num)\r\n\t\t\t\treturn pString;\r\n\t\t\telse\r\n\t\t\t\tnum++;\r\n\t\t}\r\n\t\tpString = pString->GetNext();\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n\r\nvoid RailSet::SetupAllocators(int num_points, int num_strings, bool in_set)\r\n{\r\n\tif (in_set)\r\n\t\tstrcpy(m_setName, \"In set\");\r\n\telse\r\n\t\tstrcpy(m_setName, \"Out set\");\r\n\tchar point_name[64];\r\n\tsprintf(point_name, \"%s RailPoint\", m_setName);\r\n\tchar string_name[64];\r\n\tsprintf(string_name, \"%s RailString\", m_setName);\r\n\t\r\n\tDbg_MsgAssert(mp_pointAllocator==NULL,(\"mp_pointAllocator not NULL\"));\r\n\tmp_pointAllocator = new Mem::CCompactPool(sizeof(RailPoint), num_points, point_name);\r\n\tDbg_MsgAssert(mp_stringAllocator==NULL,(\"mp_stringAllocator not NULL\"));\r\n\tmp_stringAllocator = new Mem::CCompactPool(sizeof(RailString), num_strings, string_name);\r\n}\r\n\r\n\r\n\r\n\r\nvoid RailSet::FreeAllocators()\r\n{\r\n\tif (mp_stringAllocator)\r\n\t{\r\n\t\tdelete mp_stringAllocator;\r\n\t\tmp_stringAllocator=NULL;\r\n\t}\r\n\tif (mp_pointAllocator)\r\n\t{\r\n\t\tdelete mp_pointAllocator;\r\n\t\tmp_pointAllocator=NULL;\r\n\t}\t\r\n}\r\n\r\n\r\n\r\n\r\nRailPoint *RailSet::CreateRailPoint()\r\n{\r\n\t\r\n\tDbg_Assert(mp_pointAllocator);\r\n\r\n\tRailPoint::SAttachPool(mp_pointAllocator);\r\n\tRailPoint *pNew = new RailPoint;\r\n\tRailPoint::SRemovePool();\r\n\treturn pNew;\r\n}\r\n\r\n\r\n\r\n\r\nRailString *RailSet::CreateRailString()\r\n{\r\n\t\r\n\tDbg_Assert(mp_stringAllocator);\r\n\r\n\tRailString::SAttachPool(mp_stringAllocator);\r\n\tRailString *pString = new RailString;\r\n\tRailString::SRemovePool();\r\n\tpString->mp_parentSet = this;\r\n\treturn pString;\r\n}\r\n\r\n\r\n\r\n\r\nvoid RailSet::DestroyRailPoint(RailPoint *pPoint)\r\n{\r\n\t\r\n\tDbg_Assert(mp_pointAllocator);\r\n\r\n\tRailPoint::SAttachPool(mp_pointAllocator);\r\n\tdelete pPoint;\r\n\tRailPoint::SRemovePool();\r\n}\r\n\r\n\r\n\r\n\r\nvoid RailSet::DestroyRailString(RailString *pString)\r\n{\r\n\t\r\n\tDbg_Assert(mp_stringAllocator);\r\n\r\n\tRailString::SAttachPool(mp_stringAllocator);\r\n\tdelete pString;\r\n\tRailString::SRemovePool();\r\n}\r\n\r\n\r\n\r\n\r\n} // namespace Ed\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/ParkEditor/EdRail.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t            \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t              \t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t                    \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:     rjm        \t\t\t\t    \t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t                                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __SK_PARKEDITOR_EDRAIL_H\r\n#define __SK_PARKEDITOR_EDRAIL_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/math.h>\r\n#include <sys/mem/CompactPool.h>\r\n#include <sys/mem/Poolable.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Ed\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  RailPoint  : public Mem::CPoolable<RailPoint>\r\n{\r\n\t\r\n\r\npublic:\r\n//\tenum RailType\r\n//\t{\r\n//\t\tvMETAL,\r\n//\t\tvWOOD,\r\n//\t};\r\n\r\n\ttypedef\t\tuint32\t\tRailType;\r\n\t\r\n\tRailPoint();\r\n\t~RailPoint();\r\n\r\n\tRailPoint *\t\t\t\t\t\t\t\tGetNext() {return mp_next;}\r\n\r\n\tMth::Vector\t\t\t\t\t\t\t\tm_pos;\r\n\tRailType\t\t\t\t\t\t\t\tm_type;\r\n\t// id of associated Piece (and therefore trick object)\r\n\tuint32\t\t\t\t\t\t\t\t\tm_objectId;\r\n\tRailPoint *\t\t\t\t\t\t\t\tmp_next;\r\n};\r\n\r\n\r\n\r\n\r\nclass RailSet;\r\nclass  RailString  : public Mem::CPoolable<RailString>\r\n{\r\n\t\r\n\r\npublic:\r\n\tRailString();\r\n\t~RailString();\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\tAddPoint(RailPoint *pPoint);\r\n\tvoid\t\t\t\t\t\t\t\t\tDestroy();\r\n\tRailPoint *\t\t\t\t\t\t\t\tGetList() {return mp_pointList;}\r\n\tRailString *\t\t\t\t\t\t\tGetNext() {return mp_next;}\r\n\tint\t\t\t\t\t\t\t\t\t\tCount() {return m_numPoints;}\r\n\tint\t\t\t\t\t\t\t\t\t\tCountLinkedPoints();\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\tCopyOffsetAndRot(RailString *pString, Mth::Vector &pos, int rot, uint32 piece_id);\r\n\t\r\n\tuint8\t\t\t\t\t\t\t\t\tm_isLoop;\r\n\tuint32\t\t\t\t\t\t\t\t\tm_id; // of associated piece\r\n\t\r\n\tRailPoint *\t\t\t\t\t\t\t\tmp_pointList;\r\n\tRailPoint *\t\t\t\t\t\t\t\tmp_lastPoint;\r\n\tuint16\t\t\t\t\t\t\t\t\tm_numPoints;\r\n\tRailString *\t\t\t\t\t\t\tmp_next;\r\n\r\n\tRailSet *\t\t\t\t\t\t\t\tmp_parentSet;\r\n};\r\n\r\n\r\n\r\n\r\nclass  RailSet  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic:\r\n\tRailSet();\r\n\t~RailSet();\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\tAddString(RailString *pString);\r\n\tvoid\t\t\t\t\t\t\t\t\tDestroy();\r\n\tRailString *\t\t\t\t\t\t\tGetList() {return mp_stringList;}\r\n\tint\t\t\t\t\t\t\t\t\t\tCount() {return m_numStrings;}\r\n\tint\t\t\t\t\t\t\t\t\t\tCountPoints();\r\n\r\n\tRailString *\t\t\t\t\t\t\tGetString(uint32 id, int num);\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\t\tSetupAllocators(int num_points, int num_strings, bool in_set);\r\n\tvoid\t\t\t\t\t\t\t\t\tFreeAllocators();\r\n\tRailPoint *\t\t\t\t\t\t\t\tCreateRailPoint();\r\n\tRailString *\t\t\t\t\t\t\tCreateRailString();\r\n\tvoid\t\t\t\t\t\t\t\t\tDestroyRailPoint(RailPoint *pPoint);\r\n\tvoid\t\t\t\t\t\t\t\t\tDestroyRailString(RailString *pString);\r\n\r\nprotected:\t\r\n\tRailString *\t\t\t\t\t\t\tmp_stringList;\r\n\tRailString *\t\t\t\t\t\t\tmp_lastString;\r\n\tuint16\t\t\t\t\t\t\t\t\tm_numStrings;\r\n\r\n\tMem::CCompactPool *\t\t\t\t\t\tmp_pointAllocator;\r\n\tMem::CCompactPool *\t\t\t\t\t\tmp_stringAllocator;\r\n\r\n\tchar\t\t\t\t\t\t\t\t\tm_setName[32];\r\n};\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n} // namespace Ed\r\n\r\n#endif\t// __SK_PARKEDITOR_EDRAIL_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/ParkEditor/LoadPath.txt",
    "content": "**************************************************\r\nLevel Loading Pathway for THPS3\r\nUpdated 7/17/2001\r\n**************************************************\r\n\r\n=========================================================\r\n*** REGULAR LEVEL ***\r\nchange_level level=Load_LevelName (script)\r\n-setgametype freeskate\r\n-request_level <...>\r\n\t-RequestLevel <level> -- sets skate_mod->m_requested_level\r\n-ScriptChangeLevel()\r\n\t-does some network stuff, or might apply to single player\r\n-Return to regular game flow, update function (below) does more later\r\n\r\n\r\n=========================================================\r\n*** CUSTOM PARK, PLAYED AS REGULAR ***\r\nchange_level level=custom_park (script, launched from menu)\r\n-setgametype freeskate\r\n-request_level <...>\r\n\t-RequestLevel <level> -- sets skate_mod->m_requested_level\r\n-ScriptChangeLevel()\r\n\t-does some network stuff, or might apply to single player\r\n-Return to regular game flow, update function (below) does more later\r\n\r\n\r\n=========================================================\r\n*** GOING INTO PARK EDITOR ***\r\nAutoLaunch level=custom_park game=parkeditor\r\n-SetServerMode on (command)\r\n-request_level level=<level>\r\n\t-RequestLevel <level> -- sets skate_mod->m_requested_level\r\n-SetGameType <game>\r\n-launchmenuscreen screen=parked_menu\r\n-Return to regular game flow, update function (below) does more later\r\n\r\n\r\n=========================================================\r\n*** UPDATE FUNCTION, ALL ***\r\n-CallMemberFunction, request==GameFlow_RequestLevel\r\n\t-*** REGULAR LEVEL ***\r\n\t\t-LoadLevel (script, see details below)\r\n\t-*** PARK EDITOR ***\r\n\t\t-DoParkGeneration (script, see below)\r\n\r\n\r\n=========================================================\r\n*** REGULAR LEVEL ***\r\nLoadLevel (script)\r\n-SetServerMode (command)\r\n-PreLevelLoad (script, see details below)\r\n-LaunchLevel (command, see details below)\r\n-PostLevelLoad\r\n-ResetCamera\r\n\r\n\r\n=========================================================\r\n*** PARK EDITOR ***\r\nDoParkGeneration (script)\r\n-PreLevelLoad (script, see details below)\r\n-LaunchLevel (command, see details below)\r\n-PostLevelLoad\r\n-ResetCamera\r\n-Do color, velocity, fogging stuff normally found in Load_LevName script\r\n\r\n\r\n=========================================================\r\n-PreLevelLoad (script)\r\n\t-Cleanup\r\n\t-Stopping, pausing music\r\n\t-SetArenaSize 1\r\n\t\t-call to RwResourcesSetArenaSize()\r\n\t-Sounds\r\n\t-SetLevelExists\r\n\t\t-rwviewer::SetLevelExists()\r\n\t-SetupBasicLights\r\n\t-DisplayLoadingScreen\r\n\r\n\r\n=========================================================\r\nLaunchLevel (command)\r\n-Skate::OpenLevel() \r\n\t-**** REGULAR LEVEL ***\r\n\t\t-runs level script, e.g. Load_Can\r\n\t\t\t-loadlevelgeometry (command)\r\n\t\t\t\t-rwviewer::RequestLoad() (see details below)\r\n\t\t\t-loadnodearray (command)\r\n\t\t\t\t-Script::RemoveOldTriggerScripts(), DeleteSpawnedScripts()\r\n\t\t\t\t-Script::LoadQB()\r\n\t\t\t\t-ScriptParseNodeArray()\r\n\t\t\t-LoadTerrain (loads sounds)\r\n\t\t\t-SetRenderModeVU\r\n\t\t\t-Set colors, velocity, fog and other level attributes\r\n\t\t\t-Call level startup, e.g. Can_startup\r\n\t-*** PARK EDITOR ***\r\n\t\t-ParkEditor::commandGeneratePark()\r\n\t\t\t-ParkEditor::Initialize() [need ParkEditor::mp_compressedMap to be set up at this point]\r\n\t\t\t\t-Map::InitializeWorld()\r\n\t\t\t\t\t-World::CreateParkHeap()\r\n\t\t\t\t\t\t-rwviewer::RequestLoad(\"sk3ed.bsp\") (see details below)\r\n\t\t\t\t\t\t-Create new heap for generated pieces\r\n\t\t\t\t\t-World::PreparePieceSet()\r\n\t\t\t\t\t\t-disconnect world sectors (source piece set) from just-loaded RpWorld\r\n\t\t\t\t\t\t-Script::RemoveOldTriggerScripts(), DeleteSpawnedScripts()\r\n\t\t\t\t\t\t-Script::LoadQB()\r\n\t\t\t\t\t\t-Sk3Ed_Startup (script)\r\n\t\t\t\t-Map::Initialize()\r\n\t\t\t\t\t-Map::readMapFromBuf()\r\n\t\t\t\t\t\t-Clone world sectors and link to them from the RpWorld\r\n\t\t\t\t-Map::GenerateWorld()\r\n\t\t\t\t\t-Generate super sectors\r\n\t\t\t\t\t-Obj::Proxim_Init()\r\n\t\t\t\t\t-Obj::Rail_Init()\r\n\r\n\r\n=========================================================\r\n// Probably safe for going into editor\r\n\r\nrwviewer::RequestLoad() \r\n\t-world_deinit()\r\n\t-sky_deinit()\r\n\t-world_init()\r\n\t\t-set m_level_exists\r\n\t\t-set m_dff_light_active\r\n\t\t-scene_load()\r\n\t\t\t-load bits texture dictionary\r\n\t\t\t-Gfx::SetImageDirectoryFromFileName()\r\n\t\t\t-Gfx::TexDictionaryLoad(), set it up\r\n\t\t\t-RwStreamOpen(), stream in world\r\n\t\t\t-GenerateSuperSectors()\r\n\t\t\t-load models from DFF file, gather textures from clumps, add clumps to AssMan\r\n\t\t\t-Pipeline::Chooser::FinishLoadingWorld()\r\n\t\t\t-Upload texture dictionary\r\n\t\t-Add cameras to world\r\n\t\t-run SetupViewerLights?\r\n\t\t-Mip K value stuff (NGPS)\r\n\t\t-Add lights\r\n\t\t-Get world sector render callback function\r\n\t\t-Set up particle system\r\n\r\n\r\n\r\n\r\n\r\n=========================================================\r\n*** LEAVING CUSTOM PARK ***\r\n\r\nchosen_leave_server\r\n-ParkEditor::Cleanup()\r\n\t-Map::Destroy()\r\n\t-Map::DestroyWorld()\r\n-ScriptLeaveServer()\r\n\t-Skate::LeaveServer()\r\n-SetNetworkMode\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/ParkEditor2/EdMap.cpp",
    "content": "#include <core/defines.h>\r\n#include <sk/ParkEditor/EdRail.h>\r\n#include <sk/ParkEditor2/EdMap.h>\r\n#include <sk/ParkEditor2/ParkEd.h>\r\n#include <sk/ParkEditor2/clipboard.h>\r\n#include <core/math.h>\r\n#include <core/crc.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/symboltype.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/vecpair.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/music/music.h>\r\n#include <sys/file/filesys.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/components/raileditorcomponent.h>\r\n#include <sk/components/goaleditorcomponent.h>\r\n#include <sk/engine/feeler.h>\r\n\r\nDefinePoolableClass(Ed::CMapListNode);\r\n\r\n#ifdef __PLAT_NGC__\r\n#define _16(a) (((a>>8)&0x00ff)|((a<<8)&0xff00))\r\n#define _32(a) (((a>>24)&0x000000ff)|((a>>8)&0x0000ff00)|((a<<8)&0x00ff0000)|((a<<24)&0xff000000)) \r\n#else\r\n#define _16(a) a\r\n#define _32(a) a\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n#if 1\r\n#ifdef\t__PLAT_NGPS__\r\n#define\t__USE_EXTERNAL_BUFFER__\r\n#include <gfx/nx.h>\r\n#include <gfx/ngps/nx/dma.h>\r\n#define\t__EXTERNAL_BUFFER__ NxPs2::dma::pRuntimeBuffer\r\n#define\t ACQUIRE_BUFFER Nx::CEngine::sFinishRendering();\r\n#endif\r\n#endif\r\n\r\nnamespace Ed\r\n{\r\n\r\n\r\n\r\n\r\nDefineSingletonClass(CParkManager, \"Park Manager\");\r\n\r\n\r\n\r\nCParkManager *CParkManager::sp_instance = NULL;\r\n\r\nGridDims::GridDims(uint8 x, sint8 y, uint8 z, uint8 w, uint8 h, uint8 l)\r\n{\r\n\tm_dims[0] = x;\r\n\tm_dims[1] = (uint8) y;\r\n\tm_dims[2] = z;\r\n\tm_dims[3] = w;\r\n\tm_dims[4] = h;\r\n\tm_dims[5] = l;\r\n}\r\n\r\n\r\n\r\n\r\nuint8 &GridDims::operator [](sint i)\r\n{\r\n\tDbg_Assert(i < 6);\r\n\treturn m_dims[i];\r\n}\r\n\r\n\r\n\r\n\r\n// Effectively gives the area an H of infinity\r\nvoid GridDims::MakeInfinitelyHigh()\r\n{\r\n\tm_dims[4] = 127 - (sint8) m_dims[1];\r\n}\r\n\r\n\r\n\r\n\r\n// Effectively gives the area an H of infinity\r\nvoid GridDims::MakeInfiniteOnY()\r\n{\r\n\tm_dims[1] = (uint8) -100;\r\n\tm_dims[4] = 200;\r\n}\r\n\r\n\r\n\r\n\r\nvoid GridDims::PrintContents() const\r\n{\r\n\tprintf(\"pos=(%d,%d,%d) dims=(%d,%d,%d)\\n\", \r\n\t\t   m_dims[0], (sint8) m_dims[1], m_dims[2],\r\n\t\t   m_dims[3], m_dims[4], m_dims[5]);\r\n}\r\n\r\n\r\n\r\n\r\nCMetaPiece::CMetaPiece()\r\n{\r\n\tm_flags = EFlags(0);\r\n\tmp_additional_desc_tab = NULL;\r\n\tm_total_entries = 0;\r\n\tm_num_used_entries = 0;\r\n}\r\n\r\n\r\n\r\n\r\nCMetaPiece::~CMetaPiece()\r\n{\r\n\tif (mp_additional_desc_tab)\r\n\t\tdelete mp_additional_desc_tab;\r\n}\r\n\r\n\r\n\r\n\r\nCConcreteMetaPiece *CMetaPiece::CastToConcreteMeta()\r\n{\r\n\tDbg_MsgAssert(this == NULL || (m_flags & mCONCRETE_META), (\"not a concrete metapiece\"));\r\n\treturn (CConcreteMetaPiece *) this;\r\n}\r\n\r\n\r\n\r\n\r\nCAbstractMetaPiece *CMetaPiece::CastToAbstractMeta()\r\n{\r\n\tDbg_MsgAssert(this == NULL || (m_flags & mABSTRACT_META), (\"not an abstract metapiece\"));\r\n\treturn (CAbstractMetaPiece *) this;\r\n}\r\n\r\nbool CMetaPiece::IsRestartOrFlag()\r\n{\r\n\tswitch (m_name_checksum)\r\n\t{\r\n\t\tcase CRCC(0xdc09a6a4,\"Sk3Ed_RS_1p\"):\r\n\t\tcase CRCC(0xca07b4fc,\"Sk3Ed_RS_Mp\"):\r\n\t\tcase CRCC(0x3a784d4c,\"Sk3Ed_Rs_Ho\"):\r\n\t\tcase CRCC(0x4e2efd2a,\"Sk3Ed_Rs_KOTH\"):\r\n\t\tcase CRCC(0x613c7766,\"Sk4Ed_Team_Yellow\"):\r\n\t\tcase CRCC(0xec82433c,\"Sk4Ed_Team_Green\"):\r\n\t\tcase CRCC(0xd7eb62b5,\"Sk4Ed_Team_Red\"):\r\n\t\tcase CRCC(0x8a1576b6,\"Sk4Ed_Team_Blue\"):\r\n\t\t\treturn true;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\t\r\n\treturn false;\r\n}\r\n\r\nbool CMetaPiece::IsCompletelyWithinArea(const GridDims &area)\r\n{\r\n\tif (m_cell_area.GetX() >= area.GetX() && m_cell_area.GetX()+m_cell_area.GetW() <= area.GetX()+area.GetW() &&\r\n\t\tm_cell_area.GetZ() >= area.GetZ() && m_cell_area.GetZ()+m_cell_area.GetL() <= area.GetZ()+area.GetL())\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\t\r\n}\r\n\r\n/*\r\n\tUse to set rotation of abstract metapiece for testing purposes (in GetMetaPiecesAt()), or\r\n\tto set rotation of concrete metapiece before adding to park.\r\n*/\r\nvoid CMetaPiece::SetRot(Mth::ERot90 newRot)\r\n{\r\n\tDbg_MsgAssert(!(m_flags & CMetaPiece::mIN_PARK), (\"metapiece already in park -- can't change rotation\"));\r\n\t\r\n\t// just want to change relative to current rotation\r\n\tMth::ERot90 rot = Mth::ERot90((newRot + 4 - m_rot) & 3);\r\n\tm_rot = newRot;\r\n\tif (rot & 1)\r\n\t{\r\n\t\t// switch W and L\r\n\t\tm_cell_area.SetWHL(m_cell_area.GetL(), m_cell_area.GetH(), m_cell_area.GetW());\r\n\t}\r\n\t\r\n\tSMetaDescriptor temp_new_first[USUAL_NUM_DESCRIPTORS];\r\n\t\r\n\t// Create a new table, which will soon replace the old one\r\n\tSMetaDescriptor *p_meta_tab = NULL;\r\n\tif (mp_additional_desc_tab)\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(CParkManager::sInstance()->GetGenerator()->GetParkEditorHeap());\r\n\t\tp_meta_tab = new SMetaDescriptor[m_total_entries-USUAL_NUM_DESCRIPTORS];\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\tfor (uint i = 0; i < m_num_used_entries; i++)\r\n\t{\r\n\t\t// \"dims\" contains position of upper-left, after rotation\r\n\t\tSMetaDescriptor &out = (i < USUAL_NUM_DESCRIPTORS) ? temp_new_first[i] : p_meta_tab[i-USUAL_NUM_DESCRIPTORS];\r\n\t\tSMetaDescriptor &in = (i < USUAL_NUM_DESCRIPTORS) ? m_first_desc_tab[i] : mp_additional_desc_tab[i-USUAL_NUM_DESCRIPTORS];\r\n\t\tout = in;\r\n\r\n\t\t// dimensions with current rotation (not new)\r\n\t\t// OOG!\r\n\t\tGridDims in_dims(0, 0, 0);\r\n\t\tif (m_flags & mABSTRACT_META)\r\n\t\t{\r\n\t\t\tCAbstractMetaPiece *p_meta = CParkManager::sInstance()->GetAbstractMeta(in.mPieceName);\r\n\t\t\tin_dims = p_meta->GetArea();\r\n\t\t\tif ((in.mRot & 1))\r\n\t\t\t{\r\n\t\t\t\t// for a concrete metapiece, the retrieved cell dimensions will already reflect\r\n\t\t\t\t// the current rotation, so no need to enter this block\r\n\t\t\t\tin_dims.SetWHL(in_dims.GetL(), in_dims.GetH(), in_dims.GetW()); // switch W & L\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tin.mpPiece->GetCellDims(&in_dims);\r\n\t\t}\r\n\r\n\t\tswitch(rot)\r\n\t\t{\r\n\t\t\tcase Mth::ROT_0:\r\n\t\t\t\tout.mX = in.mX;\r\n\t\t\t\tout.mZ = in.mZ;\r\n\t\t\t\tbreak;\r\n\t\t\tcase Mth::ROT_90:\r\n\t\t\t\tout.mX = in.mZ;\r\n\t\t\t\tout.mZ = m_cell_area.GetL() - in.mX - in_dims.GetW();\r\n\t\t\t\tbreak;\r\n\t\t\tcase Mth::ROT_180:\r\n\t\t\t\tout.mX = m_cell_area.GetW() - in.mX - in_dims.GetW();\r\n\t\t\t\tout.mZ = m_cell_area.GetL() - in.mZ - in_dims.GetL();\r\n\t\t\t\tbreak;\r\n\t\t\tcase Mth::ROT_270:\r\n\t\t\t\tout.mX = m_cell_area.GetW() - in.mZ - in_dims.GetL();\r\n\t\t\t\tout.mZ = in.mX;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(0, (\"ahhh-oooop?\"));\r\n\t\t\t\tbreak;\r\n\t\t}\t\t\r\n\t\t\r\n\t\tout.mY = in.mY;\r\n\t\tout.mRot = Mth::ERot90((in.mRot + rot) & 3);\r\n\t\t\r\n\t\t// this will also copy in.mPieceName, if this is an abstract metapiece\r\n\t\tout.mpPiece = in.mpPiece;\r\n\t} // end for\r\n\r\n\tif (mp_additional_desc_tab)\r\n\t\tdelete mp_additional_desc_tab;\r\n\tmp_additional_desc_tab = p_meta_tab;\r\n\tfor (int i = 0; i < USUAL_NUM_DESCRIPTORS; i++)\r\n\t{\r\n\t\tm_first_desc_tab[i] = temp_new_first[i];\r\n\t\t//printf(\"desc at (%d,%d,%d)\\n\", m_first_desc_tab[i].mX, m_first_desc_tab[i].mY, m_first_desc_tab[i].mZ);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n// returns postion of piece's center, relative to center of metapiece\r\nMth::Vector CMetaPiece::GetRelativePosOfContainedPiece(int index)\r\n{\r\n\t// center_pos in world coordinates\r\n\tMth::Vector center_pos;\r\n\tcenter_pos[X] = (float) m_cell_area.GetW() * CParkGenerator::CELL_WIDTH / 2.0f;\r\n\tcenter_pos[Y] = 0;\r\n\tcenter_pos[Z] = (float) m_cell_area.GetL() * CParkGenerator::CELL_LENGTH / 2.0f;\r\n\r\n\tSMetaDescriptor &desc = get_desc_at_index(index);\t\r\n\tCPiece *p_piece = GetContainedPiece(index);\r\n\tMth::Vector piece_pos(desc.mX * CParkGenerator::CELL_WIDTH + p_piece->GetDimsWithRot(Mth::ERot90(desc.mRot)).GetX() / 2.0f,\r\n\t\t\t\t\t\t  desc.mY * CParkGenerator::CELL_HEIGHT,\r\n\t\t\t\t\t\t  desc.mZ * CParkGenerator::CELL_LENGTH + p_piece->GetDimsWithRot(Mth::ERot90(desc.mRot)).GetZ() / 2.0f);\r\n\treturn piece_pos - center_pos;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CMetaPiece::BuildElement3dSectorsArray(Script::CArray *pArray)\r\n{\r\n\tpArray->SetSizeAndType(m_num_used_entries, ESYMBOLTYPE_STRUCTURE);\r\n\tfor (uint i = 0; i < m_num_used_entries; i++)\r\n\t{\r\n\t\tSMetaDescriptor &desc = get_desc_at_index(i);\t\r\n\t\t\r\n\t\tScript::CStruct *p_struct = new Script::CStruct();\r\n\t\tp_struct->AddChecksum(NONAME, desc.mPieceName);\r\n\t\tMth::Vector pos = GetRelativePosOfContainedPiece(i);\r\n\t\tp_struct->AddVector(NONAME, pos.GetX(), pos.GetY(), pos.GetZ());\r\n\t\t\r\n\t\tpArray->SetStructure(i, p_struct);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCreates\tnew table of SMetaDescriptors. Might copy old one.\r\n*/\r\nvoid CMetaPiece::initialize_desc_table(int numEntries)\r\n{\r\n\tSMetaDescriptor *p_new_tab = NULL;\r\n\tif (numEntries > USUAL_NUM_DESCRIPTORS) \r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(CParkManager::sInstance()->GetGenerator()->GetParkEditorHeap());\r\n\t\tp_new_tab = new SMetaDescriptor[numEntries-USUAL_NUM_DESCRIPTORS];\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\r\n\t// Copy old table, if any. Only copied if there are to be at least as many entries as\r\n\t// there were before.\r\n\tif (p_new_tab && mp_additional_desc_tab && m_total_entries <= (uint) numEntries)\r\n\t{\r\n\t\tfor (uint i = USUAL_NUM_DESCRIPTORS; i < m_total_entries; i++)\r\n\t\t\tp_new_tab[i-USUAL_NUM_DESCRIPTORS] = mp_additional_desc_tab[i-USUAL_NUM_DESCRIPTORS];\r\n\t}\r\n\t\r\n\tif (mp_additional_desc_tab)\r\n\t\tdelete mp_additional_desc_tab;\r\n\tmp_additional_desc_tab = p_new_tab; \r\n\tm_total_entries = numEntries;\r\n}\r\n\t\t\t\t\t\t\t\t\r\n\r\n\r\n\r\n/*\r\n\tReturns specified descriptor.\r\n*/\r\nSMetaDescriptor &CMetaPiece::get_desc_at_index(int i)\r\n{\r\n\tif (i < USUAL_NUM_DESCRIPTORS) return m_first_desc_tab[i];\r\n\r\n\tDbg_MsgAssert(mp_additional_desc_tab && (uint) i < m_num_used_entries, (\"descriptor entry doesn't exist\"));\r\n\treturn mp_additional_desc_tab[i-USUAL_NUM_DESCRIPTORS];\r\n}\r\n\r\n\r\n\r\n\r\nCConcreteMetaPiece::CConcreteMetaPiece()\r\n{\r\n\tm_flags = EFlags(m_flags | mCONCRETE_META);\r\n\tm_rot = 0;\r\n}\r\n\r\n\r\n\r\n\r\nint\tCConcreteMetaPiece::CountContainedPieces()\r\n{\r\n\treturn m_num_used_entries;\r\n}\r\n\r\n\r\n\r\n\r\nCPiece *CConcreteMetaPiece::GetContainedPiece(int index)\r\n{\r\n\tif ((uint) index >= m_num_used_entries || index < 0)\r\n\t\treturn NULL;\r\n\r\n\treturn get_desc_at_index(index).mpPiece;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tUsed for the cursor piece, allowing any position and rotation, not just cell-aligned with 90 degree\r\n\tincrements. Doesn't affect \"hard\" position, rotation.\r\n*/\r\nvoid CConcreteMetaPiece::SetSoftRot(Mth::Vector pos, float rot)\r\n{\r\n\t//Ryan(\"moving metapiece to (%.2f,%.2f,%.2f)\\n\", pos[X], pos[Y], pos[Z]);\r\n\t\r\n\tMth::Vector center(m_cell_area.GetW() * CParkGenerator::CELL_WIDTH / 2.0f,\r\n\t\t\t\t\t   0.0f,\r\n\t\t\t\t\t   m_cell_area.GetL() * CParkGenerator::CELL_LENGTH / 2.0f);\r\n\t\r\n\tfor (uint i = 0; i < m_num_used_entries; i++)\r\n\t{\r\n\t\tSMetaDescriptor &desc = get_desc_at_index(i);\r\n\t\t\r\n\t\t// BAKU\r\n\t\tMth::Vector piece_dims = desc.mpPiece->GetDims();\r\n\t\tMth::Vector piece_pos(desc.mX * CParkGenerator::CELL_WIDTH + piece_dims[X] / 2.0f - center[X],\r\n\t\t\t\t\t\t\t  desc.mY * CParkGenerator::CELL_HEIGHT - center[Y],\r\n\t\t\t\t\t\t\t  desc.mZ * CParkGenerator::CELL_LENGTH + piece_dims[Z] / 2.0f - center[Z]);\r\n\r\n\t\tMth::Matrix rot_mat;\r\n\t\trot_mat.Ident();\r\n\t\trot_mat.SetPos(piece_pos);\r\n\t\trot_mat.RotateY(Mth::DegToRad(rot));\r\n\t\trot_mat.Translate(pos);\r\n\r\n\t\t//Ryan(\"    sub-piece position (%d) (%.2f,%.2f,%.2f)\\n\", desc.mY, rot_mat[Mth::POS][X], rot_mat[Mth::POS][Y], rot_mat[Mth::POS][Z]);\r\n\t\t\r\n\t\tdesc.mpPiece->CastToCClonedPiece()->SetDesiredPos(rot_mat[Mth::POS], CClonedPiece::CHANGE_SECTOR);\t\t\r\n\t\t//desc.mpPiece->CastToCClonedPiece()->SetDesiredRot(Mth::ROT_0, CClonedPiece::CHANGE_SECTOR);\r\n\t\t\r\n\t\tfloat soft_rot = 90.0f * (float) desc.mRot + rot;\r\n\t\tdesc.mpPiece->CastToCClonedPiece()->SetSoftRot(soft_rot);\r\n\t}\r\n}\r\n\r\n\r\n// Turn on or off the highlight effect for this concrete meta piece\r\n// which just turns the effect on or off for the cloned pieces that make it up \r\nvoid CConcreteMetaPiece::Highlight(bool on, bool gapHighlight)\r\n{\r\n\tfor (uint i = 0; i < m_num_used_entries; i++)\r\n\t{\r\n\t\tSMetaDescriptor &desc = get_desc_at_index(i);\r\n\t\tif (desc.mpPiece->GetFlags() & CPiece::mCLONED_PIECE)\r\n\t\t{\r\n\t\t\tdesc.mpPiece->CastToCClonedPiece()->Highlight(on, gapHighlight);\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n\r\n\r\nvoid CConcreteMetaPiece::SetVisibility(bool visible)\r\n{\r\n\tfor (uint i = 0; i < m_num_used_entries; i++)\r\n\t{\r\n\t\tSMetaDescriptor &desc = get_desc_at_index(i);\r\n\t\tdesc.mpPiece->CastToCClonedPiece()->SetActive(visible);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tUse after calls to add_piece() have been made. Once metapiece has been locked, it can be added to \r\n\tthe world or used as a cursor\r\n*/\r\nvoid CConcreteMetaPiece::lock()\r\n{\r\n\t// work out dimensions of metapiece from contained pieces\r\n\tMth::Vector min_pos, max_pos;\r\n\tget_max_min_world_coords(max_pos, min_pos);\r\n\t\r\n\tMth::Vector my_dims;\r\n\tmy_dims.Set(max_pos.GetX() - min_pos.GetX(), max_pos.GetY() - min_pos.GetY(), max_pos.GetZ() - min_pos.GetZ());\r\n\r\n\tm_cell_area.SetWHL((uint8) ((my_dims.GetX() + 2.0f) / CParkGenerator::CELL_WIDTH),\r\n\t\t\t\t\t   (uint8) ((my_dims.GetY() + 2.0f) / CParkGenerator::CELL_HEIGHT),\r\n\t\t\t\t\t   (uint8) ((my_dims.GetZ() + 2.0f) / CParkGenerator::CELL_LENGTH));\r\n\r\n\tif (m_cell_area[H] < 1) m_cell_area[H] = 1;\r\n\t\r\n\t//Dbg_Assert(m_cell_area.mW > 0 && m_cell_area.mL > 0);\r\n\r\n\t// reposition all contained pieces relative to center bottom\r\n\tfor (uint i = 0; i < m_num_used_entries; i++)\r\n\t{\r\n\t\tCClonedPiece *p_piece = get_desc_at_index(i).mpPiece->CastToCClonedPiece();\r\n\t\t\r\n\t\t//Mth::Vector piece_dims = p_piece->GetDims();\r\n\t\tp_piece->m_pos[X] = p_piece->m_pos.GetX() - min_pos.GetX() - my_dims.GetX() / 2.0f;\r\n\t\tp_piece->m_pos[Z] = p_piece->m_pos.GetZ() - min_pos.GetZ() - my_dims.GetZ() / 2.0f;\r\n\t\tp_piece->m_pos[Y] = p_piece->m_pos.GetY(); // - min_pos.GetY();\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCalled by lock()\r\n*/\r\nvoid CConcreteMetaPiece::get_max_min_world_coords(Mth::Vector &max, Mth::Vector &min)\r\n{\r\n\tmin.Set(100000.0f, 100000.0f, 100000.0f, 0.0f);\r\n\tmax.Set(-100000.0f, -100000.0f, -100000.0f, 0.0f);\r\n\r\n\tfor (uint i = 0; i < m_num_used_entries; i++)\r\n\t{\r\n\t\tCClonedPiece *p_piece = get_desc_at_index(i).mpPiece->CastToCClonedPiece();\r\n\t\t\r\n\t\tMth::Vector piece_dims = p_piece->GetDims();\r\n\t\tMth::Vector piece_pos = p_piece->GetPos();\r\n\r\n\t\tif (piece_pos.GetX() - piece_dims.GetX() / 2.0f < min.GetX())\r\n\t\t\tmin[X] = piece_pos.GetX() - piece_dims.GetX() / 2.0f;\r\n\t\tif (piece_pos.GetX() + piece_dims.GetX() / 2.0f > max.GetX())\r\n\t\t\tmax[X] = piece_pos.GetX() + piece_dims.GetX() / 2.0f;\r\n\t\t\r\n\t\tif (piece_pos.GetZ() - piece_dims.GetZ() / 2.0f < min.GetZ())\r\n\t\t\tmin[Z] = piece_pos.GetZ() - piece_dims.GetZ() / 2.0f;\r\n\t\tif (piece_pos.GetZ() + piece_dims.GetZ() / 2.0f > max.GetZ())\r\n\t\t\tmax[Z] = piece_pos.GetZ() + piece_dims.GetZ() / 2.0f;\r\n\t\t\r\n\t\tif (piece_pos.GetY() < min.GetY())\r\n\t\t\tmin[Y] = piece_pos.GetY();\r\n\t\tif (piece_pos.GetY() + piece_dims.GetY() > max.GetY())\r\n\t\t\tmax[Y] = piece_pos.GetY() + piece_dims.GetY();\r\n\t}\r\n\r\n\t//Dbg_Assert(max[X] - min[X] > 1.0f && max[Z] - min[Z] > 1.0f);\r\n}\r\n\r\n\r\n\r\n\r\n/* \r\n\tDetermines if overlap between specified area of park and this metapiece.\r\n\t\r\n\tIf excludeRisers set, then we ignore overlaps with contained CPieces that are risers.\r\n*/\r\nbool CConcreteMetaPiece::test_for_conflict(GridDims area, bool excludeRisers)\r\n{\r\n\t// for now, we simply see if this metapiece overlaps with the area\r\n\t// later, we may add code that tests against contained pieces\r\n\r\n\tDbg_Assert(m_cell_area.GetW() > 0 && m_cell_area.GetL() > 0 && m_cell_area.GetH() > 0);\r\n\tDbg_MsgAssert(area.GetW() > 0 && area.GetL() > 0 && area.GetH() > 0, (\"invalid dimensions (%d,%d,%d)\", \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  area.GetW(), area.GetW(), area.GetL()));\r\n\r\n\t// do quick test\r\n\t\r\n\tif (m_cell_area.GetX() + m_cell_area.GetW() <= area.GetX())\r\n\t\treturn false;\r\n\tif (m_cell_area.GetX() >= area.GetX() + area.GetW())\r\n\t\treturn false;\r\n\tif (m_cell_area.GetY() + m_cell_area.GetH() <= area.GetY())\r\n\t\treturn false;\r\n\tif (m_cell_area.GetY() >= area.GetY() + area.GetH())\r\n\t\treturn false;\r\n\tif (m_cell_area.GetZ() + m_cell_area.GetL() <= area.GetZ())\r\n\t\treturn false;\r\n\tif (m_cell_area.GetZ() >= area.GetZ() + area.GetL())\r\n\t\treturn false;\r\n\r\n\tbool contains_risers = false;\r\n   \tif (excludeRisers)\r\n\t{\r\n\t\tfor (uint i = 0; i < m_num_used_entries; i++)\r\n\t\t{\r\n\t\t\tSMetaDescriptor &desc = get_desc_at_index(i);\r\n\t\t\tif (desc.mRiser) contains_risers = true;\r\n\t\t}\r\n\t}\r\n\t// '|| if !excludeRisers' is implicit\r\n\tif (!contains_risers) return true;\r\n\t\r\n\tfor (uint i = 0; i < m_num_used_entries; i++)\r\n\t{\r\n\t\tSMetaDescriptor &desc = get_desc_at_index(i);\r\n\t\tCClonedPiece *p_piece = GetContainedPiece(i)->CastToCClonedPiece();\r\n\t\tGridDims piece_area;\r\n\t\tp_piece->GetCellDims(&piece_area);\r\n\t\tpiece_area[X] = m_cell_area.GetX() + desc.mX;\r\n\t\tpiece_area[Y] = m_cell_area.GetY() + desc.mY;\r\n\t\tpiece_area[Z] = m_cell_area.GetZ() + desc.mZ;\r\n\t\r\n\t\tif (!desc.mRiser &&\r\n\t\t\tpiece_area.GetX() + piece_area.GetW() > area.GetX() &&\r\n\t\t\tpiece_area.GetY() + piece_area.GetH() > area.GetY()\t&&\r\n\t\t\tpiece_area.GetZ() + piece_area.GetL() > area.GetZ() &&\r\n\t\t\tpiece_area.GetX() < area.GetX() + area.GetW() &&\r\n\t\t\tpiece_area.GetY() < area.GetY() + area.GetH() &&\r\n\t\t\tpiece_area.GetZ() < area.GetZ() + area.GetL())\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\t\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tSee comments with original declaration.\r\n\t\r\n\tIt is fine if pPiece has been rotated already.\r\n*/\r\nvoid CConcreteMetaPiece::add_piece(CPiece *pPiece, GridDims *pPos, Mth::ERot90 rot, bool isRiser)\r\n{\r\n\tDbg_Assert(pPiece);\r\n\tDbg_MsgAssert(!(pPiece->GetFlags() & CPiece::mIN_WORLD), (\"piece already in world\"));\r\n\t\r\n\tCClonedPiece *p_cloned = pPiece->CastToCClonedPiece();\r\n\t#ifdef __NOPT_ASSERT__\r\n\tif (m_num_used_entries > 0)\r\n\t{\r\n\t\tif (get_desc_at_index(0).mpPiece->GetFlags() & CPiece::mSOFT_PIECE)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(pPiece->GetFlags() & CPiece::mSOFT_PIECE, (\"must be a soft piece\"));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(!(pPiece->GetFlags() & CPiece::mSOFT_PIECE), (\"must be a hard piece\"));\r\n\t\t}\r\n\t}\r\n\t#endif\r\n\r\n\tDbg_MsgAssert(m_num_used_entries < m_total_entries, (\"out of entries\"));\r\n\tSMetaDescriptor &desc = get_desc_at_index(m_num_used_entries++);\r\n\r\n\t// Set position relative to northwest bottom of piece. For now.\r\n\tMth::Vector piece_dims = p_cloned->GetDims();\r\n\tMth::Vector desired_pos;\r\n\tdesired_pos.Set(pPos->GetX() * CParkGenerator::CELL_WIDTH + piece_dims.GetX() / 2.0f,\r\n\t\t\t\t\t\t  pPos->GetY() * CParkGenerator::CELL_HEIGHT, // + piece_dims.GetY() / 2.0f,\r\n\t\t\t\t\t\t  pPos->GetZ() * CParkGenerator::CELL_LENGTH + piece_dims.GetZ() / 2.0f);\r\n\tp_cloned->SetDesiredPos(desired_pos, CClonedPiece::MARKER_ONLY);\r\n\r\n\tdesc.mpPiece = p_cloned;\r\n\tdesc.mX = pPos->GetX();\r\n\tdesc.mY = pPos->GetY();\r\n\tdesc.mZ = pPos->GetZ();\r\n\tdesc.mRot = rot;\r\n\tdesc.mRiser = isRiser ? 1 : 0;\r\n\r\n\t/*\r\n\tif (isRiser)\r\n\t{\r\n\t\tprintf(\"hoogaboog 2 (%d,%d,%d), desc.mRiser is %d, desc.mRiser at 0x%x, index %d\\n\", \r\n\t\t\t   desc.mX, desc.mY, desc.mZ, desc.mRiser, &desc.mRiser, m_num_used_entries-1);\r\n\t}\r\n\t*/\r\n}\r\n\r\n\r\n\r\n\r\nCAbstractMetaPiece::CAbstractMetaPiece()\r\n{\r\n\tm_flags = EFlags(m_flags | mABSTRACT_META);\r\n}\r\n\r\n\r\n\r\n\r\nCPiece *CAbstractMetaPiece::GetContainedPiece(int index)\r\n{\r\n\tif ((uint) index >= m_num_used_entries || index < 0)\r\n\t\treturn NULL;\r\n\r\n\tCPiece *p_piece = CParkManager::sInstance()->GetGenerator()->GetMasterPiece(get_desc_at_index(index).mPieceName);\r\n\tDbg_Assert(p_piece);\r\n\treturn p_piece;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tSee comments with original declaration. It is fine if pPiece has been rotated already.\r\n\t\r\n\tAutomatically changes stored cell WHL dimensions of metapiece to include new addition.\r\n*/\r\nvoid CAbstractMetaPiece::add_piece(CPiece *pPiece, GridDims *pPos, Mth::ERot90 rot, bool isRiser)\r\n{\r\n\tDbg_Assert(pPiece);\r\n\tCSourcePiece *p_source = NULL;\r\n\tif (pPiece->GetFlags() & CPiece::mSOURCE_PIECE)\r\n\t\tp_source = pPiece->CastToCSourcePiece();\r\n\tif (!p_source)\r\n\t\tDbg_MsgAssert(0, (\"not supported yet\"));\r\n\r\n\tDbg_MsgAssert(m_num_used_entries < m_total_entries, (\"out of entries\"));\r\n\tSMetaDescriptor &desc = get_desc_at_index(m_num_used_entries++);\r\n\r\n\tif (p_source)\r\n\t{\r\n\t\tdesc.mX = pPos->GetX();\r\n\t\tdesc.mY = pPos->GetY();\r\n\t\tdesc.mZ = pPos->GetZ();\r\n\t\tdesc.mRot = rot;\r\n\t\tdesc.mRiser = (uint8) isRiser;\r\n\t\tdesc.mPieceName = p_source->GetType();\r\n\r\n\t\tint highest_x = pPos->GetX() + pPos->GetW();\r\n\t\tint highest_y = pPos->GetY() + pPos->GetH();\r\n\t\tint highest_z = pPos->GetZ() + pPos->GetL();\r\n\r\n\t\tuint8 current_w = m_cell_area.GetW();\r\n\t\tuint8 current_h = m_cell_area.GetH();\r\n\t\tuint8 current_l = m_cell_area.GetL();\r\n\t\t\r\n\t\tif (highest_x > current_w)\r\n\t\t\tcurrent_w = highest_x;\r\n\t\tif (highest_y > current_h)\r\n\t\t\tcurrent_h = highest_y;\r\n\t\tif (highest_z > current_l)\r\n\t\t\tcurrent_l = highest_z;\r\n\r\n\t\tm_cell_area.SetWHL(current_w, current_h, current_l);\r\n\t\tif (m_cell_area[H] < 1) m_cell_area[H] = 1;\r\n\t}\r\n\t\r\n\t/*\r\n\tif (isRiser)\r\n\t{\r\n\t\tprintf(\"hoogaboog 1 (%d,%d,%d), index %d\\n\", desc.mX, desc.mY, desc.mZ, m_num_used_entries-1);\r\n\t}\r\n\t*/\r\n}\r\n\r\n\r\n\r\n\r\nvoid CAbstractMetaPiece::add_piece_dumb(CAbstractMetaPiece *pMeta, GridDims *pPos, Mth::ERot90 rot, bool isRiser)\r\n{\r\n\tDbg_MsgAssert(m_num_used_entries < m_total_entries, (\"out of entries\"));\r\n\tSMetaDescriptor &desc = get_desc_at_index(m_num_used_entries++);\r\n\r\n\tif (pMeta)\r\n\t{\r\n\t\tdesc.mX = pPos->GetX();\r\n\t\tdesc.mY = pPos->GetY();\r\n\t\tdesc.mZ = pPos->GetZ();\r\n\t\tdesc.mRot = rot;\r\n\t\tdesc.mRiser = (uint8) isRiser;\r\n\t\tdesc.mPieceName = pMeta->GetNameChecksum();\r\n\r\n\t\tint highest_x = pPos->GetX() + pPos->GetW();\r\n\t\tint highest_y = pPos->GetY() + pPos->GetH();\r\n\t\tint highest_z = pPos->GetZ() + pPos->GetL();\r\n\r\n\t\tuint8 current_w = m_cell_area.GetW();\r\n\t\tuint8 current_h = m_cell_area.GetH();\r\n\t\tuint8 current_l = m_cell_area.GetL();\r\n\t\t\r\n\t\tif (highest_x > current_w)\r\n\t\t\tcurrent_w = highest_x;\r\n\t\tif (highest_y > current_h)\r\n\t\t\tcurrent_h = highest_y;\r\n\t\tif (highest_z > current_l)\r\n\t\t\tcurrent_l = highest_z;\r\n\r\n\t\tm_cell_area.SetWHL(current_w, current_h, current_l);\r\n\t}\r\n\t\r\n\t/*\r\n\tif (isRiser)\r\n\t{\r\n\t\tprintf(\"hoogaboog 1 (%d,%d,%d), index %d\\n\", desc.mX, desc.mY, desc.mZ, m_num_used_entries-1);\r\n\t}\r\n\t*/\r\n}\r\n\r\n\r\n\r\n\r\nSMetaDescriptor CAbstractMetaPiece::get_desc_with_expansion(int index)\r\n{\r\n\t#if 1\r\n\tint count = 0;\r\n\tfor (uint j = 0; j < m_num_used_entries; j++)\r\n\t{\r\n\t\tSMetaDescriptor &outer_desc = get_desc_at_index(j);\r\n\r\n\t\tCAbstractMetaPiece *p_contained_meta = CParkManager::sInstance()->GetAbstractMeta(outer_desc.mPieceName);\r\n\t\tif (p_contained_meta->m_flags & CMetaPiece::mSINGULAR)\r\n\t\t{\r\n\t\t\tif (count == index)\r\n\t\t\t\treturn outer_desc;\r\n\t\t\tcount++;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfor (uint i = 0; i < p_contained_meta->m_num_used_entries; i++)\r\n\t\t\t{\r\n\t\t\t\tSMetaDescriptor &inner_desc = p_contained_meta->get_desc_at_index(i);\r\n\t\t\t\tif (count == index)\r\n\t\t\t\t{\r\n\t\t\t\t\tSMetaDescriptor ret_desc = inner_desc;\r\n\t\t\t\t\tret_desc.mPieceName = inner_desc.mPieceName;\r\n\t\t\t\t\tret_desc.mRot = inner_desc.mRot + outer_desc.mRot;\r\n\t\t\t\t\t\r\n\t\t\t\t\tGridDims outer_dims = GetArea();\r\n\r\n\t\t\t\t\tGridDims inner_dims = p_contained_meta->GetArea();\r\n\t\t\t\t\t\r\n\t\t\t\t\tret_desc.mX = outer_desc.mX;\r\n\t\t\t\t\tret_desc.mZ = outer_desc.mZ;\r\n\t\t\t\t\tret_desc.mY = outer_desc.mY + inner_desc.mY;\r\n\t\t\t\t\t\r\n\t\t\t\t\tswitch(outer_desc.mRot)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcase Mth::ROT_0:\r\n\t\t\t\t\t\t\tret_desc.mX += inner_desc.mX;\r\n\t\t\t\t\t\t\tret_desc.mZ += inner_desc.mZ;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase Mth::ROT_90:\r\n\t\t\t\t\t\t\tret_desc.mX += inner_desc.mZ;\r\n\t\t\t\t\t\t\tret_desc.mZ += outer_dims.GetW() - inner_desc.mX - inner_dims.GetW();\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase Mth::ROT_180:\r\n\t\t\t\t\t\t\tret_desc.mX += outer_dims.GetW() - inner_desc.mX - inner_dims.GetW();\r\n\t\t\t\t\t\t\tret_desc.mZ += outer_dims.GetL() - inner_desc.mZ - inner_dims.GetL();\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase Mth::ROT_270:\r\n\t\t\t\t\t\t\tret_desc.mX += outer_dims.GetL() - inner_desc.mZ - inner_dims.GetL();\r\n\t\t\t\t\t\t\tret_desc.mZ += inner_desc.mX;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\treturn ret_desc;\r\n\t\t\t\t}\r\n\t\t\t\tcount++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tDbg_MsgAssert(0, (\"what the bloody 'ell?\"));\r\n\tSMetaDescriptor dumb;\r\n\treturn dumb;\r\n\t#else\r\n\treturn get_desc_at_index(index);\r\n\t#endif\r\n}\r\n\r\n\r\n\r\n\r\nint CAbstractMetaPiece::count_descriptors_expanded()\r\n{\r\n\t#if 1\r\n\tint count = 0;\r\n\tfor (uint j = 0; j < m_num_used_entries; j++)\r\n\t{\r\n\t\tSMetaDescriptor &outer_desc = get_desc_at_index(j);\r\n\r\n\t\tCAbstractMetaPiece *p_contained_meta = CParkManager::sInstance()->GetAbstractMeta(outer_desc.mPieceName);\r\n\t\tDbg_MsgAssert(p_contained_meta, (\"couldn't find metapiece %s\", Script::FindChecksumName(outer_desc.mPieceName)));\r\n\t\tif (p_contained_meta->m_flags & CMetaPiece::mSINGULAR)\r\n\t\t{\r\n\t\t\tcount++;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfor (uint i = 0; i < p_contained_meta->m_num_used_entries; i++)\r\n\t\t\t{\r\n\t\t\t\tcount++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn count;\r\n\t#else\r\n\treturn m_num_used_entries;\r\n\t#endif\r\n}\r\n\r\n\r\n\r\n\r\nCMetaPiece *CMapListNode::GetMeta()\r\n{\r\n\tDbg_Assert(this);\r\n\tDbg_MsgAssert(((uint32)this) != 0x03030303,(\"Bad CMapListNode pointer ! (0x03030303)\"));\r\n\tDbg_MsgAssert(((uint32)this) != 0x55555555,(\"Bad CMapListNode pointer ! (0x55555555)\"));\r\n\tDbg_Assert(mp_meta);\r\n\treturn mp_meta;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CMapListNode::DestroyList()\r\n{\r\n\tCMapListNode *p_node = this;\r\n\twhile (p_node)\r\n\t{\r\n\t\tCMapListNode *p_next_node = p_node->mp_next;\r\n\t\tdelete p_node;\r\n\t\tp_node = p_next_node;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CMapListNode::VerifyIntegrity()\r\n{\r\n\tCMapListNode *p_outer_node = this;\r\n\twhile (p_outer_node)\r\n\t{\r\n\t\tCMapListNode *p_inner_node = p_outer_node->mp_next;\r\n\t\twhile (p_inner_node)\r\n\t\t{\r\n\t\t\tDbg_Assert(p_inner_node->GetMeta() != p_outer_node->GetMeta());\r\n\t\t\tp_inner_node = p_inner_node->mp_next;\r\n\t\t}\r\n\t\tp_outer_node = p_outer_node->mp_next;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nCMapListTemp::CMapListTemp(CMapListNode *p_list)\r\n{\r\n\tmp_list = p_list;\r\n}\r\n\r\n\r\n\r\n\r\nCMapListTemp::~CMapListTemp()\r\n{\r\n\tif (mp_list)\r\n\t\tmp_list->DestroyList();\r\n}\r\n\r\n\r\n\r\n\r\nCMapListNode *CMapListTemp::GetList()\r\n{\r\n\treturn mp_list;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CMapListTemp::PrintContents()\r\n{\r\n\tprintf(\"contents of map list:\\n\");\r\n\tCMapListNode *p_node = mp_list;\r\n\twhile(p_node)\r\n\t{\r\n\t\tprintf(\"   address=%p area=\", p_node->GetMeta());\r\n\t\tp_node->GetMeta()->GetArea().PrintContents();\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nCParkManager::CParkManager()\r\n{\r\n\tmp_generator = new CParkGenerator();\r\n\t\r\n\tmp_concrete_metapiece_list = NULL;\r\n\tmp_abstract_metapiece_list = NULL;\r\n\tm_num_concrete_metapieces = 0;\r\n\tm_num_general_concrete_metapieces = 0;\r\n\tm_dma_piece_count = 0;\r\n\tm_num_abstract_metapieces = 0;\r\n\r\n\tm_floor_height_map = NULL;\r\n\t\r\n\tfor (int i = 0; i < FLOOR_MAX_WIDTH; i++)\r\n\t\tfor (int j = 0; j < FLOOR_MAX_LENGTH; j++)\r\n\t\t\tmp_bucket_list[i][j] = NULL;\r\n\r\n\tm_state_on = false;\r\n\r\n\tsp_instance = this;\r\n\r\n\tmp_compressed_map_buffer = new uint8[COMPRESSED_MAP_SIZE];\r\n\tm_compressed_map_flags = mNO_FLAGS;\r\n\tm_park_is_valid = false;\r\n\r\n\tmp_gap_manager = NULL;\r\n\t\r\n\tfor (int i = 0; i < NUM_RISER_INFO_SLOTS; i++)\r\n\t{\r\n\t\tchar name0[128];\r\n\t\tsprintf(name0, \"floor_wall_block%d\", i+1);\r\n\t\tm_riser_piece_checksum[i][0] = Script::GenerateCRC(name0);\r\n\t\t\r\n\t\tchar name1[128];\r\n\t\tsprintf(name1, \"wall_block%d\", i+1);\r\n\t\tm_riser_piece_checksum[i][1] = Script::GenerateCRC(name1);\r\n\t\t\r\n\t\tchar name2[128];\r\n\t\tsprintf(name2, \"floor_block%d\", i+1);\r\n\t\tm_riser_piece_checksum[i][2] = Script::GenerateCRC(name2);\r\n\t}\r\n\r\n\tm_theme = 0;\r\n\t\r\n\t// Mick: Create a compressed map buffer, equivalent to an empty park\t\t\t\t\t\t\t\t\r\n\tfake_compressed_map_buffer();\r\n\r\n\tmp_column_slide_list = NULL;\t\r\n\t\r\n\tmp_park_name[0]=0;\r\n\t\r\n\t#ifdef USE_BUILD_LIST\r\n\tm_build_list_size=0;\r\n\tmp_build_list_entry=NULL;\r\n\t#endif\r\n}\r\n\r\n\r\n\r\n\r\nCParkManager::~CParkManager()\r\n{\r\n\t#ifdef USE_BUILD_LIST\r\n\tif (mp_build_list_entry)\r\n\t{\r\n\t\t#ifndef\t__USE_EXTERNAL_BUFFER__\r\n\t\tMem::Free(mp_build_list_entry);\r\n\t\t#endif\r\n\t\tmp_build_list_entry=NULL;\r\n\t}\t\r\n\t#endif\r\n\t\r\n\tdelete mp_generator;\r\n\tdelete mp_compressed_map_buffer;\r\n\r\n\tsp_instance = NULL;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tBoots up park editor.\r\n\t\r\n\t-Loads up files needed\r\n\t-Initializes buffers\r\n\t-Initializes CParkGenerator module\r\n\t-Calls Rebuild(), which:\r\n\t\t-Clears map\r\n\t\t-Generates riser geometry\r\n\t-Creates piece set database\r\n*/\r\nvoid CParkManager::Initialize()\r\n{\r\n\tParkEd(\"CParkManager::Initialize()\");\r\n\t\r\n\tif (m_state_on)\r\n\t\treturn;\r\n\tm_state_on = true;\r\n\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tMem::CPoolable<CMapListNode>::SCreatePool(16000, \"CMapListNode\");\r\n\tMem::CPoolable<CMapListNode>::SPrintInfo();\r\n\r\n\tMem::CPoolable<CClipboardEntry>::SCreatePool(MAX_CLIPBOARD_METAS, \"CClipboardEntry\");\r\n\tMem::CPoolable<CClipboard>::SCreatePool(MAX_CLIPBOARDS, \"CClipboard\");\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tmp_generator->InitializeMasterPieces(MAX_WIDTH, 16, MAX_LENGTH, GetTheme());\r\n\tmp_generator->ReadInRailInfo();\r\n\r\n\tcreate_abstract_metapieces();\r\n\r\n\tsetup_road_mask();\r\n\t\r\n\tDbg_MsgAssert(!m_floor_height_map, (\"bad monkey!!!\"));\r\n\tm_floor_height_map = new FloorHeightEntry*[FLOOR_MAX_WIDTH];\r\n\tfor (int i = 0; i < FLOOR_MAX_WIDTH; i++)\r\n\t{\r\n\t\tm_floor_height_map[i] = new FloorHeightEntry[FLOOR_MAX_LENGTH];\t\t\r\n\t\tfor (int j = 0; j < FLOOR_MAX_LENGTH; j++)\r\n\t\t{\r\n\t\t\tm_floor_height_map[i][j].mMarkAsSlid = false;\r\n\t\t\tm_floor_height_map[i][j].mSlideAmount = 0;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\tsetup_default_dimensions();\r\n\t\t\r\n\tmp_gap_manager = new CGapManager(this);\r\n\t\r\n\tRebuildWholePark(false);\r\n\r\n\tScript::CArray *p_set_array = Script::GetArray(\"Ed_piece_sets\", Script::ASSERT);\r\n\tm_total_sets = p_set_array->GetSize();\r\n\tDbg_Assert(m_total_sets <= MAX_SETS);\r\n\r\n\tScript::CArray *p_piece_array = Script::GetArray(\"Ed_standard_metapieces\", Script::ASSERT);\r\n\tint last_piece_index=p_piece_array->GetSize();\r\n\tint last_set_index=-1;\r\n\t\r\n\tfor (int s = m_total_sets-1; s >=0 ; --s)\r\n\t{\r\n\t\tScript::CStruct *p_set = p_set_array->GetStructure(s);\r\n\t\t\r\n\t\tm_palette_set[s].mpName = NULL;\r\n\t\tp_set->GetText(\"name\", &m_palette_set[s].mpName, Script::ASSERT);\r\n\t\tm_palette_set[s].mNameCrc = Script::GenerateCRC(m_palette_set[s].mpName);\r\n\t\tm_palette_set[s].mSelectedEntry = 0;\r\n\t\t\r\n\t\tm_palette_set[s].mTotalEntries=0;\r\n\r\n\t\tuint32 first_checksum;\r\n\t\tif (p_set->GetChecksum(\"first\", &first_checksum))\r\n\t\t{\r\n\t\t\tint first_index=0;\r\n\t\t\tif (!GetAbstractMeta(first_checksum, &first_index))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0, (\"couldn't find first-in-set entry\"));\r\n\t\t\t}\r\n\r\n\t\t\t// make sure index in previous first-in_set_entry is less than this one\r\n\t\t\tif (last_set_index>=0)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(first_index <\r\n\t\t\t\t\t\t\t  last_piece_index,\r\n\t\t\t\t\t\t\t  (\"sets %s and %s are out of order in EdPieces2.q\", \r\n\t\t\t\t\t\t\t   m_palette_set[s].mpName,\r\n\t\t\t\t\t\t\t   m_palette_set[last_set_index].mpName));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(first_index <\r\n\t\t\t\t\t\t\t  last_piece_index,\r\n\t\t\t\t\t\t\t  (\"set %s has a bad first piece in EdPieces2.q\", \r\n\t\t\t\t\t\t\t   m_palette_set[s].mpName));\r\n\t\t\t}\r\n\t\t\tm_palette_set[s].mTotalEntries=last_piece_index-first_index;\r\n\t\t\tlast_piece_index=first_index;\r\n\t\t\tlast_set_index=s;\r\n\t\t\t\r\n\t\t\t// Now that we know the number of entries, create the set.\r\n\t\t\tint entry=first_index;\r\n\t\t\tfor (int i=0; i<m_palette_set[s].mTotalEntries; ++i)\r\n\t\t\t{\r\n\t\t\t\tCAbstractMetaPiece *p_abstract = GetAbstractMetaByIndex(entry);\r\n\t\t\t\t\r\n\t\t\t\tDbg_Assert(i < CPieceSet::MAX_ENTRIES);\r\n\t\t\t\tm_palette_set[s].mEntryTab[i].mNameCrc = p_abstract->GetNameChecksum();\r\n\t\t\t\t\r\n\t\t\t\tScript::CStruct *p_piece_entry = p_piece_array->GetStructure(entry);\r\n\t\t\t\tif (!p_piece_entry->GetLocalString(\"text_name\", &m_palette_set[s].mEntryTab[i].mpName))\r\n\t\t\t\t{\r\n\t\t\t\t\tm_palette_set[s].mEntryTab[i].mpName = NULL;\r\n\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\t++entry;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tm_palette_set[s].mIsClipboardSet=false;\r\n\t\tif (p_set->ContainsFlag(CRCD(0x45c6c158,\"clipboard_set\")))\r\n\t\t{\r\n\t\t\tm_palette_set[s].mIsClipboardSet=true;\r\n\t\t\tm_palette_set[s].mTotalEntries=MAX_CLIPBOARDS;\r\n\t\t\t\r\n\t\t\tconst char *p_clipboard_title=Script::GetString(CRCD(0x4e677220,\"ClipboardTitle\"));\r\n\t\t\t\r\n\t\t\tfor (int i=0; i<MAX_CLIPBOARDS; ++i)\r\n\t\t\t{\r\n\t\t\t\tchar p_name[100];\r\n\t\t\t\tsprintf(p_name,\"Clipboard%d\",i);\r\n\t\t\t\t\r\n\t\t\t\tm_palette_set[s].mEntryTab[i].mpName=p_clipboard_title;\r\n\t\t\t\tm_palette_set[s].mEntryTab[i].mNameCrc=Script::GenerateCRC(p_name);\r\n\t\t\t}\t\r\n\t\t}\r\n\t\t\r\n\t\tm_palette_set[s].mVisible = !p_set->ContainsFlag(\"hidden\");\r\n\t\t#ifdef __PLAT_NGC__\r\n\t\tif (p_set->ContainsFlag(\"no_gamecube\"))\r\n\t\t\tm_palette_set[s].mVisible = false;\r\n\t\t#endif\r\n\t}\r\n}\r\n\r\nfloat CParkManager::GetClipboardProportionUsed()\r\n{\r\n\tfloat proportion_clipboard_entries=((float)Mem::CPoolable<CClipboardEntry>::SGetNumUsedItems())/Mem::CPoolable<CClipboardEntry>::SGetTotalItems();\r\n\tfloat proportion_clipboard_slots=((float)Mem::CPoolable<CClipboard>::SGetNumUsedItems())/Mem::CPoolable<CClipboard>::SGetTotalItems();\r\n\r\n\tif (proportion_clipboard_entries > proportion_clipboard_slots)\r\n\t{\r\n\t\treturn proportion_clipboard_entries;\r\n\t}\r\n\treturn proportion_clipboard_slots;\r\n}\r\n\t\r\n// This is just a public version of the private function\r\n// needed so the parks can be saved from within the park editor\r\n// This just updates the contents of the map buffer that will be used\r\n// by the enxt two public functions\r\nvoid CParkManager::WriteCompressedMapBuffer()\r\n{\r\n\tif (m_state_on)\r\n\t\twrite_compressed_map_buffer();\t\r\n}\r\n\r\nuint8* CParkManager::GetCompressedMapBuffer(bool markSaved)\r\n{\r\n\t/*\r\n\t\tThe compressed map buffer is valid if:\r\n\t\t\r\n\t\t-The park manager is active AND (in sync with built park OR newer than built park) OR\r\n\t\t-The park manager is not active\r\n\t*/\r\n\t\r\n\tDbg_MsgAssert((m_compressed_map_flags & mIS_VALID), (\"compressed map buffer not valid\")); \r\n\tif (m_state_on)\r\n\t{\r\n\t\tDbg_MsgAssert((m_compressed_map_flags & mIN_SYNC_WITH_PARK) || (m_compressed_map_flags & mIS_NEWER_THAN_PARK),\r\n\t\t\t\t\t  (\"park has changed, compressed map buffer out of sync\"));\r\n\t}\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tCompressedMapHeader *p_header = (CompressedMapHeader *) mp_compressed_map_buffer;\r\n\tDbg_Printf( \"************ NUM METAS: %d\\n\", p_header->mNumMetas );\r\n#endif\t\t// __NOPT_ASSERT__\r\n\r\n\tif (markSaved)\r\n\t\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags & ~mNOT_SAVED_LOCAL);\r\n\t\r\n\treturn mp_compressed_map_buffer;\r\n}\r\n\r\n\r\n\r\n\r\nvoid\tCParkManager::SetCompressedMapBuffer( uint8* src_buffer, bool markNotSaved )\r\n{\r\n\tParkEd(\"SetCompressedMapBuffer()\");\r\n\t\r\n\t\r\n\tmemcpy( mp_compressed_map_buffer, src_buffer, COMPRESSED_MAP_SIZE );\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags | mIS_VALID);\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags | mIS_NEWER_THAN_PARK);\r\n\r\n\tif (markNotSaved)\r\n\t\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags | mNOT_SAVED_LOCAL);\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tCompressedMapHeader *p_header = (CompressedMapHeader *) mp_compressed_map_buffer;\r\n\t//uint32 checksum=Crc::GenerateCRCCaseSensitive((const char*)mp_compressed_map_buffer+4,COMPRESSED_MAP_SIZE-4);\r\n\t//Dbg_MsgAssert(checksum==p_header->mChecksum,(\"Park editor buffer checksum mismatch !\"));\r\n\t\r\n\tDbg_Printf( \"************ NUM METAS: %d\\n\", p_header->mNumMetas );\r\n#endif\t\t// __NOPT_ASSERT__\r\n}\r\n\r\n\r\n\r\n\r\nbool CParkManager::IsMapSavedLocally()\r\n{\r\n\tif ((!(m_compressed_map_flags & mIN_SYNC_WITH_PARK) && !(m_compressed_map_flags & mIS_NEWER_THAN_PARK)) || \r\n\t\t(m_compressed_map_flags & mNOT_SAVED_LOCAL))\r\n\t\treturn false;\r\n\treturn true;\r\n}\r\n\r\n\r\nvoid CParkManager::WriteIntoStructure(Script::CStruct *p_struct)\r\n{\r\n\tWriteCompressedMapBuffer();\t\t// Ensure map buffer is correct\r\n\tuint32\t*p_map_buffer = (uint32*) GetCompressedMapBuffer(true);\r\n\tint\t\tsize = COMPRESSED_MAP_SIZE ;\r\n\r\n\t// create the array\r\n\tScript::CArray *p_map=new Script::CArray;\r\n\tp_map->SetArrayType(size/4,ESYMBOLTYPE_INTEGER);\r\n\t// copy the park editor into it\r\n\tfor (int i=0;i<size/4;i++)\r\n\t{\r\n\t\tp_map->SetInteger(i,p_map_buffer[i]);\r\n\t}\r\n\t\r\n\t// append it to p_struct\r\n\tp_struct->AddArrayPointer(CRCD(0x337c5289,\"Park_editor_map\"),p_map);\r\n\r\n\t// Now also add in any created goals, so that the goals do not have to saved out to a separate file.\r\n\tScript::CStruct *p_goals_struct=new Script::CStruct;\r\n\t\r\n\tObj::CGoalEditorComponent *p_goal_editor=Obj::GetGoalEditor();\r\n\tDbg_MsgAssert(p_goal_editor,(\"No goal editor component ???\"));\r\n\tp_goal_editor->WriteIntoStructure(CRCD(0xe8b4b836,\"Load_Sk5Ed\"),p_goals_struct);\r\n\t\r\n\t\r\n\tp_struct->AddStructurePointer(CRCD(0xd8eb825e,\"Park_editor_goals\"),p_goals_struct);\r\n\r\n\t// Add in the created rails.\t\t\t\r\n\tObj::GetRailEditor()->WriteIntoStructure(p_struct);\r\n\r\n\tp_struct->AddInteger(CRCD(0xb7e39b53,\"MaxPlayers\"),GetGenerator()->GetMaxPlayers());\r\n}\r\n\r\n#ifdef __PLAT_NGC__\r\nvoid CParkManager::ReadFromStructure(Script::CStruct *p_struct, bool do_post_mem_card_load, bool preMadePark)\r\n#else\r\nvoid CParkManager::ReadFromStructure(Script::CStruct *p_struct, bool do_post_mem_card_load)\r\n#endif\r\n{\r\n\tObj::CGoalEditorComponent *p_goal_editor=Obj::GetGoalEditor();\r\n\tDbg_MsgAssert(p_goal_editor,(\"No goal editor component ???\"));\r\n\t\r\n\tp_goal_editor->ClearOnlyParkGoals();\r\n\t\r\n\t// Read in any created goals.\r\n\tScript::CStruct *p_goals_struct=NULL;\r\n\tif (p_struct->GetStructure(CRCD(0xd8eb825e,\"Park_editor_goals\"),&p_goals_struct))\r\n\t{\r\n\t\tp_goal_editor->ReadFromStructure(p_goals_struct,Obj::CGoalEditorComponent::LOADING_PARK_GOALS);\r\n\t}\r\n\r\n\t// Read in the created rails\r\n\tSpt::SingletonPtr<Ed::CParkEditor> p_park_ed;\r\n\tif (!p_park_ed->EditingCustomPark())\r\n\t{\r\n\t\t// Do not call UpdateSuperSectors after deleting any existing rails if playing a park,\r\n\t\t// otherwise the entire park will disappear from under the skater due to all the sectors\r\n\t\t// having been flagged for deletion.\r\n\t\tObj::CRailEditorComponent::sUpdateSuperSectorsAfterDeletingRailSectors=false;\r\n\t}\t\r\n\tObj::GetRailEditor()->ReadFromStructure(p_struct);\r\n\tObj::CRailEditorComponent::sUpdateSuperSectorsAfterDeletingRailSectors=true;\r\n\t\r\n\tint max_players=2;\r\n\tp_struct->GetInteger(CRCD(0xb7e39b53,\"MaxPlayers\"),&max_players);\r\n\tEd::CParkManager::Instance()->GetGenerator()->SetMaxPlayers(max_players);\r\n\t\t\t\t\r\n\tint old_theme = GetTheme();\r\n\tWriteCompressedMapBuffer();\r\n\tuint32\t*p_map_buffer = (uint32*) GetCompressedMapBuffer();\r\n\tint\t\tsize = Ed::CParkManager::COMPRESSED_MAP_SIZE ;\r\n\t// get the array\r\n\tScript::CArray *p_map=NULL;\r\n\tif (p_struct->GetArray(\"Park_editor_map\",&p_map,true))\r\n\t{\r\n\t\t// copy the park editor map from structure to buffer\r\n\t\tfor (int i=0;i<size/4;i++)\r\n\t\t{\r\n\t\t\t#ifdef __PLAT_NGC__\r\n\t\t\tif (preMadePark)\r\n\t\t\t{\r\n\t\t\t\tuint32 v=p_map->GetInteger(i);\r\n\t\t\t\tp_map_buffer[i] = ((v>>24) | (((v>>16)&0xff)<<8) | (((v>>8)&0xff)<<16) | ((v&0xff)<<24));\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_map_buffer[i] = p_map->GetInteger(i);\r\n\t\t\t}\t\t\r\n\t\t\t#else\r\n\t\t\tp_map_buffer[i] = p_map->GetInteger(i);\r\n\t\t\t#endif\r\n\t\t}\r\n\r\n\t\t#ifdef __PLAT_NGC__\r\n\t\tif (preMadePark)\r\n\t\t{\r\n\t\t\t// If loading a pre-made park, it will need the map buffer endianness swapped since\r\n\t\t\t// it was saved from the PS2.\r\n\t\t\tSwapMapBufferEndianness();\r\n\t\t}\t\r\n\t\t#endif\r\n\t\t\r\n\t\tif (do_post_mem_card_load)\r\n\t\t{\r\n\t\t\tSpt::SingletonPtr<Ed::CParkEditor> p_park_ed;\r\n\t\t\tp_park_ed->PostMemoryCardLoad((uint8*) p_map_buffer, old_theme);\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\nint CParkManager::GetTheme()\r\n{\r\n\tif (m_compressed_map_flags & mIS_VALID)\r\n\t{\r\n\t\tint theme = (((CompressedMapHeader *) mp_compressed_map_buffer)->mTheme);\r\n\t\tDbg_MsgAssert(theme >= 0 && theme <= MAX_THEMES, (\"nonsense theme %d\", theme));\r\n\t\treturn theme;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkManager::SetTheme(int theme)\r\n{\r\n\tDbg_MsgAssert(theme >= 0 && theme < MAX_THEMES , (\"nonsense theme %d\", theme));\r\n\tm_theme = theme;\r\n\twrite_compressed_map_buffer();\r\n}\r\n\r\n\r\n\r\n\r\nconst char *CParkManager::GetParkName()\r\n{\r\n\tif (mp_compressed_map_buffer && ((CompressedMapHeader *) mp_compressed_map_buffer)->mVersion == (VERSION))\r\n\t\treturn ((CompressedMapHeader *) mp_compressed_map_buffer)->mParkName;\r\n\telse\r\n\t\treturn NULL;\r\n}\r\n\r\nuint32 CParkManager::GetParkChecksum()\r\n{\r\n\tif (mp_compressed_map_buffer && ((CompressedMapHeader *) mp_compressed_map_buffer)->mVersion == (VERSION))\r\n\t\treturn ((CompressedMapHeader *) mp_compressed_map_buffer)->mChecksum;\r\n\telse\r\n\t\treturn 0;\r\n}\r\n\r\nint\tCParkManager::GetCompressedParkWidth()\r\n{\r\n\tif (mp_compressed_map_buffer && ((CompressedMapHeader *) mp_compressed_map_buffer)->mVersion == (VERSION))\r\n\t\treturn ((CompressedMapHeader *) mp_compressed_map_buffer)->mW;\r\n\telse\r\n\t\treturn 0;\r\n}\r\n\r\nint\tCParkManager::GetCompressedParkLength()\r\n{\r\n\tif (mp_compressed_map_buffer && ((CompressedMapHeader *) mp_compressed_map_buffer)->mVersion == (VERSION))\r\n\t\treturn ((CompressedMapHeader *) mp_compressed_map_buffer)->mL;\r\n\telse\r\n\t\treturn 0;\r\n}\r\n\r\n\r\nvoid CParkManager::SetParkName(const char *pName)\r\n{\r\n\tif (!mp_compressed_map_buffer || ((CompressedMapHeader *) mp_compressed_map_buffer)->mVersion != (VERSION)) return;\r\n\tDbg_Assert(pName);\r\n\tDbg_MsgAssert(strlen(pName) < 64, (\"park name too long\"));\r\n\tstrcpy(((CompressedMapHeader *) mp_compressed_map_buffer)->mParkName, pName);\r\n\tstrcpy(mp_park_name, pName);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkManager::AccessDisk(bool save, int fileSlot)\r\n{\r\n\tchar fullname[64];\r\n\tsprintf(fullname, \"CustomParks\\\\custom%d.prk\", fileSlot);\r\n\r\n\tif (save)\r\n\t{\r\n//\t\tRyan(\"I am saving park %s\\n\", fullname);\r\n//\t\tprintf(\"I am saving park %s\\n\", fullname);\r\n\t\t\r\n\t\tScript::CStruct *p_struct=new Script::CStruct;\r\n\t\tWriteIntoStructure(p_struct);\r\n\t\tuint32 size=Script::CalculateBufferSize(p_struct);\r\n\t\tuint8 *p_buffer=(uint8*)Mem::Malloc(size);\r\n\t\tScript::WriteToBuffer(p_struct,p_buffer,size);\r\n\t\t\r\n\t\tvoid *fp = File::Open(fullname, \"wb\");\r\n\t\tDbg_MsgAssert(fp, (\"failed to open file %s for write\", fullname));\r\n\t\tFile::Write(p_buffer, size, 1, fp);\r\n\t\tFile::Close(fp);\r\n\t\t\r\n\t\tMem::Free(p_buffer);\r\n\t\tdelete p_struct;\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tRyan(\"I am loading park %s\\n\", fullname);\r\n//\t\tprintf(\"I am loading park %s\\n\", fullname);\r\n\t\tvoid *fp = File::Open(fullname, \"rb\");\r\n\t\tDbg_MsgAssert(fp, (\"failed to open file %s for read\", fullname));\r\n\t\t\r\n\t\tint size=File::GetFileSize(fp);\r\n\r\n\t\tuint8 *p_buffer=(uint8*)Mem::Malloc(size);\r\n\t\t\r\n\t\tFile::Read(p_buffer, size, 1, fp);\r\n\t\tFile::Close(fp);\r\n\t\t\r\n\t\tScript::CStruct *p_struct=new Script::CStruct;\r\n\t\tScript::ReadFromBuffer(p_struct,p_buffer);\r\n\t\tMem::Free(p_buffer);\r\n\r\n\t\t#ifdef __PLAT_NGC__\r\n\t\tReadFromStructure(p_struct,false,true);\r\n\t\t#else\r\n\t\tReadFromStructure(p_struct,false);\r\n\t\t#endif\r\n\t\t\r\n\t\tdelete p_struct;\r\n\t\t\t\t\r\n\t\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags | (mIS_NEWER_THAN_PARK + mIS_VALID));\r\n\t\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags & ~mIN_SYNC_WITH_PARK);\r\n\t\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags & ~mNOT_SAVED_LOCAL);\r\n\t}\t\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tDestroys everything, concrete metas, abstract metas, floor map.\r\n*/\r\n// K: Added type so that DESTROY_ONLY_PIECES can be passed when this function is used to clean\r\n// up the park editor heap for deletion when playing a park.\r\nvoid CParkManager::Destroy(CParkGenerator::EDestroyType type)\r\n{\r\n\tParkEd(\"CParkManager::Destroy(), m_compressed_map_flags=%08x\", m_compressed_map_flags);\r\n\t\r\n\tif (!m_state_on)\r\n\t\treturn;\r\n\t\r\n\tif (!(m_compressed_map_flags & mIN_SYNC_WITH_PARK) && !(m_compressed_map_flags & mIS_NEWER_THAN_PARK))\r\n\t{\r\n\t\twrite_compressed_map_buffer();\r\n\t}\r\n\t\r\n\tDbg_Assert(mp_gap_manager);\r\n\tmp_gap_manager->RemoveAllGaps();\r\n\t\r\n\t// remove all abstract metapieces\r\n\tCMapListNode *p_node = NULL;\r\n\twhile((p_node = mp_abstract_metapiece_list))\r\n\t{\r\n\t\tCMetaPiece *p_meta = p_node->GetMeta();\r\n\t\tremove_metapiece_from_node_list(p_meta, &mp_abstract_metapiece_list);\r\n\t\tdelete p_meta;\r\n\t}\r\n\tm_num_abstract_metapieces = 0;\r\n\t\r\n\tdestroy_concrete_metapieces(type);\r\n\t\r\n\tmp_generator->UnloadMasterPieces();\r\n\tmp_generator->DestroyRailInfo();   \t\t// info from node array (mostly rails)\r\n\t\r\n\tDbg_MsgAssert(m_floor_height_map, (\"bad bad monkey!!!\"));\r\n\tfor (int i = 0; i < FLOOR_MAX_WIDTH; i++)\r\n\t\tdelete [] m_floor_height_map[i];\r\n\tdelete [] m_floor_height_map;\r\n\tm_floor_height_map = NULL;\r\n\t\r\n\tm_state_on = false;\r\n\t// since park is destroyed, buffer is out of sync and newer than park\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags & ~mIN_SYNC_WITH_PARK);\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags | mIS_NEWER_THAN_PARK);\r\n\tm_park_is_valid = false;\r\n\t\r\n\tDbg_Assert(mp_gap_manager);\r\n\tdelete mp_gap_manager;\r\n\tmp_gap_manager = NULL;\r\n\t\r\n\tif (mp_column_slide_list)\r\n\t\tmp_column_slide_list->DestroyList();\r\n\tmp_column_slide_list = NULL;\r\n\t\r\n\tMem::CPoolable<CClipboard>::SRemovePool();\t\r\n\tMem::CPoolable<CClipboardEntry>::SRemovePool();\t\r\n\tMem::CPoolable<CMapListNode>::SRemovePool();\r\n}\r\n\r\n\r\nvoid CParkManager::RebuildWholePark(bool clearPark)\r\n{\r\n\tParkEd(\"CParkManager::RebuildWholePark() 0x%x\", m_compressed_map_flags);\r\n\r\n\tsetup_lighting();  // ensure light arrays are correct for current theme\r\n\t\r\n\tDbg_Assert(m_state_on);\r\n\t\r\n\tif (!(m_compressed_map_flags & mIN_SYNC_WITH_PARK) && \r\n\t\t!(m_compressed_map_flags & mIS_NEWER_THAN_PARK) && \r\n\t\tm_park_is_valid)\r\n\t{\r\n\t\t//Ryan(\"writing compressed map buffer\\n\");\r\n\t\twrite_compressed_map_buffer();\r\n\t}\r\n\t\r\n\tDbg_Printf( \"************* Rebuilding whole park : %d\\n\", (int) clearPark );\r\n\tdestroy_concrete_metapieces(CParkGenerator::DESTROY_PIECES_AND_SECTORS);\r\n\tmp_generator->GenerateCollisionInfo(false);\r\n\r\n\tif (clearPark || !(m_compressed_map_flags & mIS_VALID))\r\n\t{\r\n\t\t//Ryan(\"clearing park\\n\");\r\n\t\tDbg_MsgAssert(m_floor_height_map, (\"bad bad monkey!!!\"));\r\n\t\t\r\n\t\tfor (int j = 0; j < FLOOR_MAX_LENGTH; j++)\r\n\t\t{\r\n\t\t\tfor (int i = 0; i < FLOOR_MAX_WIDTH; i++)\r\n\t\t\t{\r\n\t\t\t\tint x = i;\r\n\t\t\t\tint z = j;\r\n\t\t\t\tm_floor_height_map[x][z].mHeight = 0; //Mth::Rnd(4);\r\n\t\t\t\tm_floor_height_map[x][z].mEnclosedFloor = 0;\r\n\t\t\t\tm_floor_height_map[x][z].mMarkAsSlid = false;\r\n\t\t\t\tm_floor_height_map[i][j].mSlideAmount = 0; \r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\twrite_compressed_map_buffer();\r\n\t\tSetParkName(\"unnamed park\");\r\n\t\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags & ~mNOT_SAVED_LOCAL);\r\n\t\tclearPark = true;\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\t// use compressed map\r\n\t\tread_from_compressed_map_buffer();\r\n\t}\r\n\t\r\n\tRebuildInnerShell(m_park_near_bounds);\r\n\tgenerate_floor_pieces_from_height_map(clearPark, false);\t\r\n\t\r\n\tmp_generator->GenerateCollisionInfo();\r\n//\tmp_generator->GenerateNodeInfo(mp_concrete_metapiece_list);\r\n\r\n\tm_park_is_valid = true;\r\n\r\n\tif (clearPark)\r\n\t{\r\n\t\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags | mIN_SYNC_WITH_PARK);\r\n\t}\r\n\t\r\n\t// K: Now that the park geometry has been built and collision info generated, \r\n\t// update the created rails.\r\n\tObj::GetRailEditor()->RefreshGeometry();\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\t-Might clear map\r\n\t-Generates riser geometry (from height map)\r\n\r\n\tThe only place we call this function with firstTestMemory true is from CCursor::ChangeFloorHeight()\r\n*/\r\nbool CParkManager::RebuildFloor(bool firstTestMemory)\r\n{\r\n\tParkEd(\"CParkManager::RebuildFloor()\");\r\n\t\r\n\tDbg_Assert(m_state_on);\r\n\t\r\n\t//Dbg_Printf( \"************* Rebuilding floor\\n\" );\r\n\r\n\tif (firstTestMemory)\r\n\t{\r\n\t\tif (!generate_floor_pieces_from_height_map(false, true))\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\tgenerate_floor_pieces_from_height_map(false, false);\r\n\t\r\n\t//CConcreteMetaPiece *p_out = CreateConcreteMeta(GetAbstractMeta(Script::GenerateCRC(\"gloopy\")));\r\n\t//GridDims dims(m_park_near_bounds.GetX(), 0, m_park_near_bounds.GetZ());\r\n\t//AddMetaPieceToPark(dims, p_out);\r\n\t\r\n\tmp_generator->GenerateCollisionInfo();\r\n\r\n\treturn true;\r\n\t\r\n}\r\n\r\n\r\nvoid CParkManager::RebuildNodeArray()\r\n{\r\n\tParkEd(\"CParkManager::RebuildNodeArray()\");\r\n\r\n\r\n\t// clear any pre-exisiting automatic restarts\r\n\t// so we have slots free to add new ones\t\r\n\tmp_generator->ClearAutomaticRestarts();\r\n\r\n \r\n\t// add default restarts\r\n\t// (they won't be added if player-placed ones already exist)\r\n\t// there are 18 points\r\n\t// 1p, 2p, 4 flags, 6 horse, 6 KOTH\r\n\tfor (int p = 0; p < 18; p++)\r\n\t{\r\n\t\tCParkGenerator::RestartType restart_type = CParkGenerator::vONE_PLAYER;\r\n\t\t\r\n\t\tGridDims restart_area;\r\n\t\trestart_area = GetParkNearBounds();\t\t // returns the rectangle enclosed by the fence\r\n\t\trestart_area.SetXYZ(restart_area.GetX()+restart_area.GetW()/2, 0, restart_area.GetZ()+restart_area.GetL()/2);\t// sets xyz to the midpoint\r\n\t\trestart_area.SetWHL(1,1,1);\t\t// needed for when we get the floor height\r\n\t\t\t\t\t\t\r\n\r\n\t\tbool\tfind_ground = true;\t\t\t// most restarts need to find the ground, except copied horse points\r\n\t\t\t\t\t\t\r\n\t\tint need = 1;\t\t// Most restarts only need one.  Horse/Multi being the current exception\t\t\t\t\t\t\r\n\t\tif (p == 1)\r\n\t\t{\r\n\t\t\trestart_type = CParkGenerator::vMULTIPLAYER;\r\n\t\t\trestart_area.SetXYZ(restart_area.GetX()+1, 0, restart_area.GetZ());\t\r\n\t\t}\r\n\r\n\t\tif (p == 2)\r\n\t\t{\r\n\t\t\trestart_type = CParkGenerator::vRED_FLAG;\r\n\t\t\trestart_area.SetXYZ(restart_area.GetX()-2, 0, restart_area.GetZ()+2);\t\r\n\t\t}\r\n\r\n\t\tif (p == 3)\r\n\t\t{\r\n\t\t\trestart_type = CParkGenerator::vGREEN_FLAG;\r\n\t\t\trestart_area.SetXYZ(restart_area.GetX()+0, 0, restart_area.GetZ()+2);\t\r\n\t\t}\r\n\r\n\t\tif (p == 4)\r\n\t\t{\r\n\t\t\trestart_type = CParkGenerator::vBLUE_FLAG;\r\n\t\t\trestart_area.SetXYZ(restart_area.GetX()+2, 0, restart_area.GetZ()+2);\t\r\n\t\t}\r\n\r\n\t\tif (p == 5)\r\n\t\t{\r\n\t\t\trestart_type = CParkGenerator::vYELLOW_FLAG;\r\n\t\t\trestart_area.SetXYZ(restart_area.GetX()+4, 0, restart_area.GetZ()+2);\t\r\n\t\t}\r\n\r\n\t\t// all the dummy horse/multi restart points go in a line at Z-2\t\t\r\n\t\tif (p >= 6 && p <=11)\t\t\t\t \t// 6,7,8,9,10,11\r\n\t\t{\r\n\t\t\tneed = 6;\t\t\t\r\n\t\t\trestart_type = CParkGenerator::vHORSE;\r\n\t\t\t\r\n\t\t\t#if 0\r\n\t\t\t// Code to make horse points be evenly distributed between 1p/2p nodes\r\n\t\t\t// but it's not usable, as the players will start at the same point\r\n\t\t\t// either all multi points need to be different, of the code needs\r\n\t\t\t// to check in 2P (and multi) for same node positions\r\n\t\t\t// either are too risky to implement right now \t\t\t\r\n\t\t\tstatic GridDims horse_points[6];    // needs to be static, so I can include it in this conditional\r\n\t\t\tGridDims  dims;\r\n\t\t\tif (p==6)\r\n\t\t\t{\r\n\t\t\t\t// about to try the first horse point\r\n\t\t\t\t// so fill the array with appropriate values\r\n\t\t\t\tint num_actual_horse = mp_generator->NumRestartsOfType(restart_type);\r\n//\t\t\t\tprintf (\"There are %d actual horse points\\n\",num_actual_horse);\r\n\t\t\t\tif (num_actual_horse == 0)\r\n\t\t\t\t{\r\n//\t\t\t\t\tprintf (\"No horse points, using 1p/2p\\n\");\r\n\t\t\t\t\t// not even got one, so fill the array with 1p,2p,1p,2p,1p,2p\r\n\t\t\t\t\tfor (int i = 0;i<6;i+=2)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdims = mp_generator->GetRestartDims(CParkGenerator::vONE_PLAYER,0);\r\n\t\t\t\t\t\thorse_points[i] = restart_area;\r\n\t\t\t\t\t\thorse_points[i].SetXYZ(dims.GetX(),0,dims.GetZ());\r\n\t\t\t\t\t\tdims = mp_generator->GetRestartDims(CParkGenerator::vMULTIPLAYER,0);\r\n\t\t\t\t\t\thorse_points[i+1] = restart_area;\r\n\t\t\t\t\t\thorse_points[i+1].SetXYZ(dims.GetX(),0,dims.GetZ());\r\n\t\t\t\t\t}\t\t\t\t\t \r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// we have one or more real horse points, so find out where they are\r\n\t\t\t\t\t// and copy those values for any automatic horse points, if needed\r\n\t\t\t\t\tfor (int i = 0;i<6;i++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (i < num_actual_horse)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// copy the n initial values into the array\r\n\t\t\t\t\t\t\thorse_points[i] = mp_generator->GetRestartDims(CParkGenerator::vHORSE,i);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// and duplicate these through the rest of the array\r\n\t\t\t\t\t\t\t//  so we will get an even distribution\r\n\t\t\t\t\t\t\t//  n = 1  gives [ 1 1 1 1 1 1 ]\r\n\t\t\t\t\t\t\t//  n = 2  gives [ 1 2 1 2 1 2 ]\r\n\t\t\t\t\t\t\t//  n = 3  gives [ 1 2 3 1 2 3 ]\r\n\t\t\t\t\t\t\t//  n = 4  gives [ 1 2 3 4 1 2 ]\r\n\t\t\t\t\t\t\t//  n = 5  gives [ 1 2 3 4 5 1 ]\r\n\t\t\t\t\t\t\t//  n = 6  gives [ 1 2 3 4 5 6 ]\r\n\t\t\t\t\t\t\thorse_points[i] = horse_points[i % num_actual_horse];\r\n\t\t\t\t\t\t}\r\n//\t\t\t\t\t\tprintf (\"Horse %d: (%d,%d,%d)\\n\",horse_points[i].GetX(),horse_points[i].GetY(),horse_points[i].GetX());\r\n\t\t\t\t\t}\t\t\t\t\t \t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// copy the appropiate value from the array\r\n\t\t\trestart_area = horse_points[p-6];\r\n\t\t\tfind_ground = false;\t\t\t// Don't find the ground when copying existing restarts, as we will be raised up by 1p/2p/horse pieces\r\n\t\t\t//printf (\"Using Restart Area(%d,%d,%d)\\n\",restart_area.GetX(), restart_area.GetY(), restart_area.GetZ());\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t#else\t\t\t\r\n\t\t\trestart_area.SetXYZ(restart_area.GetX()-3 + (p-6), 0, restart_area.GetZ()-2);\t\r\n\t\t\t//printf (\"Using Restart Area(%d,%d,%d)\\n\",restart_area.GetX(), restart_area.GetY(), restart_area.GetZ());\r\n\t\t\t#endif\r\n\t\t\r\n\t\t}\r\n\t\t\r\n\t\tbool\tauto_copy = false;\r\n\t\t\r\n\t\tif ( p >= 12 && p <= 17 )  \t\t\t\t\t// 12,13,14,15,16,17\r\n\t\t{\r\n\t\t\tauto_copy = true;\t\t\t\t\t\t// copy any existing restart point position, if there is one\r\n\t\t\tneed = 6;\r\n\t\t\trestart_type = CParkGenerator::vKING_OF_HILL;\r\n\t\t\trestart_area.SetXYZ(restart_area.GetX()-3 + (p-12), 0, restart_area.GetZ()-3);\t \r\n\t\t}\r\n\r\n\t\tif (mp_generator->NotEnoughRestartsOfType(restart_type, need))\r\n\t\t{\r\n\t\t\tif (find_ground)\r\n\t\t\t{\r\n\t\t\t\trestart_area.SetXYZ(restart_area.GetX(),GetFloorHeight(restart_area),restart_area.GetZ());\r\n\t\t\t\tCMapListTemp meta_list = GetMetaPiecesAt(restart_area);\r\n\t\t\t\tif (!meta_list.IsEmpty())\r\n\t\t\t\t{\r\n\t\t\t\t\trestart_area[Y] = restart_area.GetY() + meta_list.GetList()->GetConcreteMeta()->GetArea().GetH();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tMth::Vector restart_pos = GridCoordinatesToWorld(restart_area);\r\n\t\t\trestart_pos[X] = restart_pos[X] + CParkGenerator::CELL_WIDTH / 2.0f;\r\n\t\t\trestart_pos[Z] = restart_pos[Z] + CParkGenerator::CELL_LENGTH / 2.0f;\r\n\t\t\t\r\n\t\t\t// Fix to TT12221, where the flags would be floating if over a pool.\r\n\t\t\tCFeeler feeler;\r\n\t\t\tfeeler.SetStart(restart_pos+Mth::Vector(0.0f, 10000.0f, 0.0f));\r\n\t\t\tfeeler.SetEnd(restart_pos+Mth::Vector(0.0f, -1000.0f, 0.0f));\r\n\t\t\tif (feeler.GetCollision())\r\n\t\t\t{\r\n\t\t\t\trestart_pos[Y]=feeler.GetPoint().GetY();\r\n\t\t\t}\t\r\n\r\n//\t\t\tprintf(\"restart point %d at: cell=(%d,%d,%d) world=(%.4f,%.4f,%.4f)\\n\", p, \r\n//\t\t\t\t restart_area.GetX(), restart_area.GetY(), restart_area.GetZ(),\r\n//\t\t\t\t restart_pos[X], restart_pos[Y], restart_pos[Z]);\r\n\r\n\t\t\tmp_generator->AddRestart(restart_pos, 0, restart_area, restart_type, true, auto_copy);\r\n\t\t}\r\n\t} // end for p\r\n\r\n\tmp_generator->GenerateNodeInfo(mp_concrete_metapiece_list);\t\r\n}\r\n\r\n\r\nuint32 CParkManager::GetShellSceneID()\r\n{\r\n\tchar p_shell_name[40];\r\n\tif (GetTheme())\r\n\t{\r\n\t\tsprintf(p_shell_name,\"sk5ed%d_shell\",GetTheme()+1);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tstrcpy(p_shell_name,\"sk5ed_shell\");\r\n\t}\r\n\treturn Script::GenerateCRC(p_shell_name);\r\n}\r\n\r\nvoid CParkManager::RebuildInnerShell(GridDims newNearBounds)\r\n{\r\n\tParkEd(\"CParkManager::RebuildInnerShell()\");\r\n\t\r\n\tDbg_Printf( \"************* Rebuilding inner shell\\n\" );\r\n\r\n\t#if 1\r\n\tParkEd(\"old shell bounds: (%d,%d,%d)-(%d,%d,%d)\\n\", \r\n\t\t m_park_near_bounds.GetX(), m_park_near_bounds.GetY(), m_park_near_bounds.GetZ(),\r\n\t\t m_park_near_bounds.GetW(), m_park_near_bounds.GetH(), m_park_near_bounds.GetL());\r\n\t#endif\r\n\tm_park_near_bounds = newNearBounds;\r\n\t#if 1\r\n\tParkEd(\"new shell bounds: (%d,%d,%d)-(%d,%d,%d)\\n\", \r\n\t\t newNearBounds.GetX(), newNearBounds.GetY(), newNearBounds.GetZ(),\r\n\t\t newNearBounds.GetW(), newNearBounds.GetH(), newNearBounds.GetL());\r\n\t#endif\r\n\t\r\n\t// west\r\n\tm_road_mask_tab[0][X] = m_park_near_bounds.GetX() - 1;\r\n\tm_road_mask_tab[0][Z] = m_park_near_bounds.GetZ() - 1;\r\n\tm_road_mask_tab[0][W] = 1;\r\n\tm_road_mask_tab[0][L] = m_park_near_bounds.GetL() + 2;\r\n\t\r\n\t// east\r\n\tm_road_mask_tab[1][X] = m_park_near_bounds.GetX() + m_park_near_bounds.GetW();\r\n\tm_road_mask_tab[1][Z] = m_park_near_bounds.GetZ() - 1;\r\n\tm_road_mask_tab[1][W] = 1;\r\n\tm_road_mask_tab[1][L] = m_park_near_bounds.GetL() + 2;\r\n\t\r\n\t// north\r\n\tm_road_mask_tab[2][X] = m_park_near_bounds.GetX() - 1;\r\n\tm_road_mask_tab[2][Z] = m_park_near_bounds.GetZ() - 1;\r\n\tm_road_mask_tab[2][W] = m_park_near_bounds.GetW() + 2;\r\n\tm_road_mask_tab[2][L] = 1;\r\n\t\r\n\t// south\r\n\tm_road_mask_tab[3][X] = m_park_near_bounds.GetX() - 1;\r\n\tm_road_mask_tab[3][Z] = m_park_near_bounds.GetZ() + m_park_near_bounds.GetL();\r\n\tm_road_mask_tab[3][W] = m_park_near_bounds.GetW() + 2;\r\n\tm_road_mask_tab[3][L] = 1;\r\n\t\r\n\t//#if DEBUG_THIS_DAMN_THING\r\n\t//int destroy_type2_count = 0;\r\n\t//#endif\r\n\t\t\r\n\t// destroy all existing inner shell pieces\r\n\t// also: kill everything that's outside the near bounds\r\n\tCMapListNode *p_node = mp_concrete_metapiece_list;\r\n\twhile(p_node)\r\n\t{\r\n\t\tCMapListNode *p_next_node = p_node->GetNext();\r\n\t\tGridDims meta_area = p_node->GetConcreteMeta()->GetArea();\r\n\t\t\r\n\t\tif (p_node->GetConcreteMeta()->IsInnerShell())\r\n\t\t{\r\n\t\t\tDestroyConcreteMeta(p_node->GetConcreteMeta(), mDONT_DESTROY_PIECES_ABOVE);\r\n\t\t}\r\n\t\t#if 1\r\n\t\telse if ( !p_node->GetConcreteMeta()->IsRiser() &&  \r\n\t\t\tp_node->GetConcreteMeta()->IsInPark() &&\r\n\t\t\t(meta_area.GetX() < m_park_near_bounds.GetX() ||\r\n\t\t\tmeta_area.GetZ() < m_park_near_bounds.GetZ() ||\r\n\t\t\tmeta_area.GetX() + meta_area.GetW() > m_park_near_bounds.GetX() + m_park_near_bounds.GetW() ||\r\n\t\t\tmeta_area.GetZ() + meta_area.GetL() > m_park_near_bounds.GetZ() + m_park_near_bounds.GetL()))\r\n\t\t{\r\n\t\t\tDestroyConcreteMeta(p_node->GetConcreteMeta(), mDONT_DESTROY_PIECES_ABOVE);\r\n\t\t\t//#if DEBUG_THIS_DAMN_THING\r\n\t\t\t//destroy_type2_count++;\r\n\t\t\t//#endif\r\n\t\t}\r\n\t\t#endif\r\n\r\n\t\tp_node = p_next_node;\r\n\t}\r\n\t\r\n\tuint32 fence_meta_name_crc = Script::GenerateCRC(\"Sk4Ed_Fence_20x20\");\r\n\tCAbstractMetaPiece *p_abstract_fence_meta = GetAbstractMeta(fence_meta_name_crc);\r\n\t\r\n\tfor (int x = m_park_near_bounds.GetX(); x < m_park_near_bounds.GetX() + m_park_near_bounds.GetW(); x += 2)\r\n\t{\r\n\t\tGridDims road_test_area;\r\n\t\troad_test_area.SetWHL(2, 1, 1);\r\n\r\n\t\t// north\r\n\t\tGridDims pos(x, 0, m_park_near_bounds.GetZ() - 1);\r\n\t\troad_test_area.SetXYZ(pos.GetX(), 0, pos.GetZ() + 1);\r\n\t\tif (!IsOccupiedByRoad(road_test_area))\r\n\t\t{\r\n\t\t\tCConcreteMetaPiece *p_meta = CreateConcreteMeta(p_abstract_fence_meta);\r\n\t\t\tp_meta->SetRot(Mth::ROT_0);\r\n\t\t\tp_meta->MarkAsInnerShell();\r\n\t\t\tAddMetaPieceToPark(pos, p_meta);\r\n\t\t}\r\n\t\r\n\t\t// south\r\n\t\tpos.SetXYZ(x, 0, m_park_near_bounds.GetZ() + m_park_near_bounds.GetL());\r\n\t\troad_test_area.SetXYZ(pos.GetX(), 0, pos.GetZ() - 1);\r\n\t\tif (!IsOccupiedByRoad(road_test_area))\r\n\t\t{\r\n\t\t\tCConcreteMetaPiece *p_meta = CreateConcreteMeta(p_abstract_fence_meta);\r\n\t\t\tp_meta->SetRot(Mth::ROT_180);\r\n\t\t\tp_meta->MarkAsInnerShell();\r\n\t\t\tAddMetaPieceToPark(pos, p_meta);\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int z = m_park_near_bounds.GetZ(); z < m_park_near_bounds.GetZ() + m_park_near_bounds.GetL(); z += 2)\r\n\t{\r\n\t\tGridDims road_test_area;\r\n\t\troad_test_area.SetWHL(1, 1, 2);\r\n\r\n\t\t// west\r\n\t\tGridDims pos(m_park_near_bounds.GetX() - 1, 0, z);\r\n\t\troad_test_area.SetXYZ(pos.GetX() + 1, 0, pos.GetZ());\r\n\t\tif (!IsOccupiedByRoad(road_test_area))\r\n\t\t{\r\n\t\t\tCConcreteMetaPiece *p_meta = CreateConcreteMeta(p_abstract_fence_meta);\r\n\t\t\tp_meta->SetRot(Mth::ROT_90);\r\n\t\t\tp_meta->MarkAsInnerShell();\r\n\t\t\tAddMetaPieceToPark(pos, p_meta);\r\n\t\t}\r\n\t\r\n\t\t// east\r\n\t\tpos.SetXYZ(m_park_near_bounds.GetX() + m_park_near_bounds.GetW(), 0, z);\r\n\t\troad_test_area.SetXYZ(pos.GetX() - 1, 0, pos.GetZ());\r\n\t\tif (!IsOccupiedByRoad(road_test_area))\r\n\t\t{\r\n\t\t\tCConcreteMetaPiece *p_meta = CreateConcreteMeta(p_abstract_fence_meta);\r\n\t\t\tp_meta->SetRot(Mth::ROT_270);\r\n\t\t\tp_meta->MarkAsInnerShell();\r\n\t\t\tAddMetaPieceToPark(pos, p_meta);\r\n\t\t}\r\n\t}\r\n\r\n\t//ParkEd(\"destroyed %d non-riser pieces\\n\", destroy_type2_count); \r\n\r\n\tfor (int x = 0; x < MAX_WIDTH; x++)\r\n\t{\r\n\t\tfor (int z = 0; z < MAX_LENGTH; z++)\r\n\t\t{\r\n\t\t\tif (x < m_park_near_bounds.GetX() ||\r\n\t\t\t\tz < m_park_near_bounds.GetZ() ||\r\n\t\t\t\tx >= m_park_near_bounds.GetX() + m_park_near_bounds.GetW() ||\r\n\t\t\t\tz >= m_park_near_bounds.GetZ() + m_park_near_bounds.GetL())\r\n\t\t\t{\r\n\t\t\t\tm_floor_height_map[x][z].mHeight = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tmp_generator->RemoveOuterShellPieces(GetTheme());\r\n\tmp_generator->GenerateCollisionInfo();\r\n\r\n//\tmp_generator->GenerateNodeInfo(mp_concrete_metapiece_list);\r\n\tParkEd(\"end RebuildInnerShell()\\n\");\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tRetrieves the abstract meta with the specified name checksum. Returns its index.\r\n*/\r\nCAbstractMetaPiece *CParkManager::GetAbstractMeta(uint32 type, int *pRetIndex)\r\n{\r\n\tDbg_Assert(m_state_on);\r\n\t\r\n\tCMapListNode *p_node = mp_abstract_metapiece_list;\r\n\tint index = m_num_abstract_metapieces-1;\r\n\twhile(p_node)\r\n\t{\r\n\t\tCAbstractMetaPiece *p_meta = p_node->GetAbstractMeta();\r\n\t\tDbg_Assert(p_meta);\r\n\t\tif (p_meta->m_name_checksum == type)\r\n\t\t{\r\n\t\t\tif (pRetIndex)\r\n\t\t\t\t*pRetIndex = index;\r\n\t\t\treturn p_meta;\r\n\t\t}\r\n\r\n\t\tindex--;\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tRetrieves the abstract meta with the specified index.\r\n*/\r\nCAbstractMetaPiece *CParkManager::GetAbstractMetaByIndex(int index)\r\n{\r\n\tDbg_Assert(m_state_on);\r\n\t\r\n\tCMapListNode *p_node = mp_abstract_metapiece_list;\r\n\tint i = m_num_abstract_metapieces-1;\r\n\twhile(p_node)\r\n\t{\r\n\t\tCAbstractMetaPiece *p_meta = p_node->GetAbstractMeta();\r\n\t\tDbg_Assert(p_meta);\r\n\t\tif (i == index)\r\n\t\t\treturn p_meta;\r\n\r\n\t\ti--;\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n\r\n\tDbg_MsgAssert(0, (\"index %d out of range\", i));\r\n\treturn NULL;\t\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCreates a concrete copy of the specified abstract meta.\r\n*/\r\nCConcreteMetaPiece *CParkManager::CreateConcreteMeta(CAbstractMetaPiece *pSource, bool isSoft)\r\n{\r\n\tDbg_Assert(m_state_on);\r\n\tDbg_Assert(pSource);\r\n\t\r\n\tMem::Manager::sHandle().PushContext(mp_generator->GetParkEditorHeap());\r\n\tCConcreteMetaPiece *p_meta = new CConcreteMetaPiece();\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\tint num_entries = pSource->count_descriptors_expanded();\r\n\tp_meta->initialize_desc_table(num_entries);\r\n\tp_meta->m_name_checksum = pSource->m_name_checksum;\r\n\t\r\n\tCPiece::EFlags clone_flags = (isSoft) ? CPiece::mSOFT_PIECE : CPiece::mNO_FLAGS;\r\n\t\r\n\tif (pSource->IsRiser())\r\n\t{\r\n\t\tp_meta->set_flag(CMetaPiece::mIS_RISER);\r\n\t\tclone_flags\t= CPiece::EFlags(clone_flags | CPiece::mFLOOR);\r\n\t}\r\n\tif (pSource->NoRails())\r\n\t{\r\n\t\tp_meta->set_flag(CMetaPiece::mNO_RAILS);\r\n\t\tclone_flags\t= CPiece::EFlags(clone_flags | CPiece::mNO_RAILS);\r\n\t}\r\n\tif (pSource->m_flags & CMetaPiece::mCONTAINS_RISERS)\r\n\t{\r\n\t\tp_meta->set_flag(CMetaPiece::mCONTAINS_RISERS);\r\n\t}\r\n\r\n\t// pick through source piece, for each descriptor entry, make new cloned piece\r\n\tfor (int i = 0; i < num_entries; i++)\r\n\t{\r\n\t\tSMetaDescriptor desc = pSource->get_desc_with_expansion(i);\r\n\t\t\r\n\t\tCClonedPiece *p_piece = \r\n\t\t\tmp_generator->ClonePiece(CParkManager::sInstance()->GetGenerator()->GetMasterPiece(desc.mPieceName), clone_flags);\r\n\t\tp_piece->SetDesiredRot(Mth::ERot90(desc.mRot), CClonedPiece::MARKER_ONLY);\r\n\t\tGridDims dims(desc.mX, desc.mY, desc.mZ);\r\n\t\tp_meta->add_piece(p_piece, &dims, Mth::ERot90(desc.mRot), (desc.mRiser != 0));\r\n\r\n\t\t#if 0\r\n\t\t// Ryan: this call is unnecessary\r\n\t\tif (!isSoft)\r\n\t\t{\r\n\t\t\tmp_generator->CalculateLighting(p_piece);\r\n\t\t}\r\n\t\t#endif\r\n\r\n\t\t#if 0\r\n\t\tif (pSource->GetNameChecksum() == Script::GenerateCRC(\"Low_Short_Deck\"))\r\n\t\t{\r\n\t\t\tprintf(\"   rotation: %d\\n\", desc.mRot);\r\n\t\t}\r\n\t\t#endif\r\n\t}\r\n\r\n\tp_meta->lock();\r\n\t   \r\n\t#if 1\r\n\t#ifdef __NOPT_ASSERT__\r\n\tGridDims test_area = p_meta->GetArea();\r\n\tDbg_MsgAssert(test_area.GetW() > 0 && test_area.GetH() > 0 && test_area.GetL() > 0, \r\n\t\t\t\t  (\"metapiece %s has invalid dimensions (%d,%d,%d)\", Script::FindChecksumName(p_meta->GetNameChecksum()),\r\n\t\t\t\t   test_area.GetW(), test_area.GetH(), test_area.GetL()));\r\n\t\r\n\t#if 0\r\n\tif (1 || p_meta->GetNameChecksum() == Script::GenerateCRC(\"Sk4Ed_Fence_10x10\"))\r\n\t\tprintf(\"OY! metapiece %s has dimensions (%d,%d,%d)\\n\", Script::FindChecksumName(p_meta->GetNameChecksum()),\r\n\t\t\t\t   test_area.GetW(), test_area.GetH(), test_area.GetL());\r\n\t#endif\r\n\r\n\t#endif\r\n\t#endif\r\n\t\r\n\tMem::Manager::sHandle().PushContext(mp_generator->GetParkEditorHeap());\r\n\tCMapListNode *p_node = new CMapListNode();\r\n\tMem::Manager::sHandle().PopContext();\r\n\tp_node->mp_meta = p_meta;\r\n\r\n\t#if 0\t\r\n\tp_node->mp_next = mp_concrete_metapiece_list;\r\n\tmp_concrete_metapiece_list = p_node;\r\n\t#else\r\n\tp_node->mp_next = NULL;\t\t\r\n\tif (!mp_concrete_metapiece_list)\r\n\t{\r\n\t\tmp_concrete_metapiece_list = p_node;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCMapListNode *p_add = mp_concrete_metapiece_list;\r\n\t\twhile( p_add->mp_next)\r\n\t\t{\r\n\t\t\tp_add = p_add->mp_next;\r\n\t\t}\r\n\t\tp_add->mp_next = p_node;\r\n\t}\r\n\t#endif\r\n\t\r\n\tm_num_concrete_metapieces++;\r\n\r\n\treturn p_meta;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkManager::DestroyConcreteMeta(CConcreteMetaPiece *pMeta, EDestroyFlags flags)\r\n{\r\n\tDbg_Assert(m_state_on);\r\n\tif (pMeta->m_flags & CMetaPiece::mLOCK_AGAINST_DELETE) return;\r\n\tDbg_MsgAssert(!(pMeta->m_flags & CMetaPiece::mLOCK_AGAINST_DELETE), (\"Metapiece is locked, can't deleted\"));\r\n\r\n\tif (CCursor::sInstance(false))\r\n\t\tCCursor::sInstance()->InformOfMetapieceDeletion(pMeta);\r\n\t\r\n\t// remove any gaps attached to this piece\r\n\tRemoveGap(pMeta);\r\n\r\n\tif (!pMeta->IsInnerShell() && pMeta->IsInPark())\r\n\t{\r\n\t\tdecrement_meta_count(pMeta->GetNameChecksum());\r\n\t\tif (!pMeta->IsRiser())\r\n\t\t{\r\n\t\t\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags & ~(mIN_SYNC_WITH_PARK | mIS_NEWER_THAN_PARK));\r\n\t\t}\t\r\n\t}\r\n\t\r\n\t// destroy all metas that are ABOVE this one\r\n\tif (!pMeta->IsRiser() && (flags & mDESTROY_PIECES_ABOVE))\r\n\t{\r\n\t\tGridDims test_area = pMeta->GetArea();\r\n\t\ttest_area[Y] = test_area.GetY() + test_area.GetH();\r\n\t\ttest_area.MakeInfinitelyHigh();\r\n\t\t// XXX\r\n\t\tRyan(\"die now: \");\r\n\t\t//test_area.PrintContents();\r\n\t\tDestroyMetasInArea(test_area, EDestroyFlags(mEXCLUDE_RISERS\t| mDESTROY_PIECES_ABOVE));\r\n\t}\r\n\t\r\n\tapply_meta_contained_risers_to_floor(pMeta, false);\r\n\t\r\n\tdebucketify_metapiece(pMeta);\r\n\tremove_metapiece_from_node_list(pMeta, &mp_concrete_metapiece_list);\r\n\t\r\n\t#if 0\r\n\tprintf(\"concrete metapiece %s destroyed: cell dims (%d,%d,%d)-(%d,%d,%d), flags=0x%x\\n\",\r\n\t\t   Script::FindChecksumName(pMeta->GetNameChecksum()),\r\n\t\t   pMeta->m_cell_area.GetX(), pMeta->m_cell_area.GetY(), pMeta->m_cell_area.GetZ(), \r\n\t\t   pMeta->m_cell_area.GetW(), pMeta->m_cell_area.GetH(), pMeta->m_cell_area.GetL(),\r\n\t\t   pMeta->m_flags);\r\n\t#endif\r\n\r\n\t\t\t\t\t\t\t\t\t\t \r\n\tCParkGenerator::RestartType restart_type = IsRestartPiece(pMeta->GetNameChecksum());\t\t\r\n\tif (restart_type != CParkGenerator::vEMPTY)\r\n\t{\r\n\t\tmp_generator->RemoveRestart(pMeta->GetArea(),restart_type);\r\n\t}\r\n\t\r\n\t// take out metapiece\r\n\tfor (uint i = 0; i < pMeta->m_num_used_entries; i++)\r\n\t{\r\n\t\tCClonedPiece *p_piece = pMeta->get_desc_at_index(i).mpPiece->CastToCClonedPiece();\r\n\t\tDbg_Assert(p_piece);\r\n\t\tmp_generator->DestroyClonedPiece(p_piece);\r\n\t}\r\n\t\r\n\tdelete pMeta;\r\n\tm_num_concrete_metapieces--;\r\n}\r\n\r\n\r\nvoid CParkManager::HighlightMetasInArea(GridDims area, bool on)\r\n{\r\n\tCMapListTemp list = GetAreaMetaPieces(area);\r\n\tCMapListNode *p_entry = list.GetList();\r\n\r\n\twhile(p_entry)\r\n\t{\r\n\t\tCMetaPiece *p_meta=p_entry->GetMeta();\r\n\t\tif (p_meta)\r\n\t\t{\r\n\t\t\tif (p_meta->IsConcrete() && p_meta->IsCompletelyWithinArea(area))\r\n\t\t\t{\r\n\t\t\t\tp_entry->GetConcreteMeta()->Highlight(on);\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\tp_entry = p_entry->GetNext();\r\n\t}\r\n}\r\n\r\n/*\r\nGridDims CParkManager::FindBoundingArea(GridDims area)\r\n{\r\n\tint min_x=1000000;\t\r\n\tint min_z=1000000;\t\r\n\tint max_x=-1000000;\r\n\tint max_z=-1000000;\r\n\t\r\n\tCMapListTemp list = GetAreaMetaPieces(area);\r\n\tCMapListNode *p_entry = list.GetList();\r\n\r\n\twhile(p_entry)\r\n\t{\r\n\t\tCMetaPiece *p_meta=p_entry->GetMeta();\r\n\t\tif (p_meta && p_meta->IsConcrete())\r\n\t\t{\r\n\t\t\tGridDims meta_area = p_entry->GetConcreteMeta()->GetArea();\r\n\t\t\tint x1=meta_area.GetX();\r\n\t\t\tint z1=meta_area.GetZ();\r\n\t\t\tint x2=x1+meta_area.GetW()-1;\r\n\t\t\tint z2=z1+meta_area.GetL()-1;\r\n\t\t\t\r\n\t\t\tif (x1 < min_x) min_x=x1;\r\n\t\t\tif (x2 > max_x) max_x=x2;\r\n\t\t\tif (z1 < min_z) min_z=z1;\r\n\t\t\tif (z2 > max_z) max_z=z2;\r\n\t\t}\t\r\n\t\tp_entry = p_entry->GetNext();\r\n\t}\r\n\t\r\n\tGridDims bounding_area=area;\r\n\tif (min_x <= max_x && min_z <= max_z)\r\n\t{\r\n\t\tbounding_area.SetXYZ(min_x, 0, min_z);\r\n\t\tbounding_area.SetWHL(max_x-min_x+1, 1, max_z-min_z+1);\r\n\t}\r\n\treturn bounding_area;\r\n}\r\n*/\r\n\r\n// K: Does the same as CCursor::AttemptRemove() but for any area\r\nbool CParkManager::DestroyMetasInArea(GridDims area, bool doNotDestroyRestartsOrFlags, bool onlyIfWithinArea)\r\n{\r\n\tbool destroyed_something=false;\r\n\tCMapListTemp metas_at_pos = GetAreaMetaPieces(area);\r\n\tCMapListNode *p_entry = metas_at_pos.GetList();\r\n\twhile (p_entry)\r\n\t{\r\n\t\tCConcreteMetaPiece *p_meta = p_entry->GetConcreteMeta();\r\n\t\tif (p_meta->IsRiser() || \r\n\t\t\t(doNotDestroyRestartsOrFlags && p_meta->IsRestartOrFlag()) ||\r\n\t\t\t(onlyIfWithinArea && !p_meta->IsCompletelyWithinArea(area)))\r\n\t\t{\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDestroyConcreteMeta(p_meta, CParkManager::mDESTROY_PIECES_ABOVE);\r\n\t\t\tdestroyed_something=true;\r\n\t\t}\t\r\n\t\t\r\n\t\tp_entry = p_entry->GetNext();\r\n\t}\r\n\r\n\t// Also destroy any rail points in the area.\r\n\tMth::Vector corner_pos;\r\n\tMth::Vector area_dims;\r\n\tcorner_pos=Ed::CParkManager::Instance()->GridCoordinatesToWorld(area,&area_dims);\r\n\tObj::GetRailEditor()->ClipRails(corner_pos[X], corner_pos[Z],\r\n\t\t\t\t\t\t\t\t\tcorner_pos[X]+area_dims[X], corner_pos[Z]+area_dims[Z],\r\n\t\t\t\t\t\t\t\t\tObj::CRailEditorComponent::DELETE_POINTS_INSIDE);\r\n\t\r\n\tif (destroyed_something)\r\n\t{\r\n\t\tRebuildFloor();\r\n\t\treturn true;\r\n\t}\r\n\t\t\r\n\treturn false;\r\n}\r\n\r\n\r\n/*\r\n\tDestroys concrete metapieces in specified area, according to flags.\r\n\t\r\n\tFlags:\r\n\t-mDESTROY_PIECES_ABOVE: if set, whenever a meta is destroyed, recursively\r\n\t\tdestroy all metas above it\r\n\t\t\r\n\tReturn value:\r\n\tupper 16 bits: number metas killed\r\n\tlower 16 bits: number pieces killed\r\n*/\r\nuint32 CParkManager::DestroyMetasInArea(GridDims area, EDestroyFlags flags)\r\n{\r\n\tuint16 metas_killed = 0;\r\n\tuint16 pieces_killed = 0;\r\n\tCMapListNode *p_list = GetMetaPiecesAt(area, Mth::ROT_0, NULL, (flags & mEXCLUDE_RISERS));\r\n\tCMapListNode *p_node = p_list;\r\n\twhile (p_node)\r\n\t{\r\n\t\tif (!(flags & mEXCLUDE_PIECES_MARKED_AS_SLID) || !(p_node->GetConcreteMeta()->m_flags & CMetaPiece::mMARK_AS_SLID))\r\n\t\t{\r\n\t\t\tmetas_killed++;\r\n\t\t\tpieces_killed += p_node->GetConcreteMeta()->m_num_used_entries;\r\n\t\t\tDestroyConcreteMeta(p_node->GetConcreteMeta(), flags);\r\n\t\t}\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n\tp_list->DestroyList();\r\n\r\n\treturn ((metas_killed<<16) | pieces_killed);\r\n}\r\n\r\nint CParkManager::get_dma_usage(uint32 pieceChecksum)\r\n{\r\n\tScript::CStruct *p_dma_usage=Script::GetStructure(CRCD(0x9547da8d,\"DMA_Usage\"),Script::ASSERT);\r\n\tint usage=1;\r\n\tp_dma_usage->GetInteger(pieceChecksum, &usage);\r\n\treturn usage;\r\n}\t\r\n\r\nvoid CParkManager::increment_meta_count(uint32 pieceChecksum)\r\n{\r\n\t++m_num_general_concrete_metapieces;\r\n\tm_dma_piece_count += get_dma_usage(pieceChecksum);\r\n\t\r\n\t//printf(\"IncrementMetaCount '%s', %d   DMA=%d\\n\",Script::FindChecksumName(pieceChecksum),m_num_general_concrete_metapieces,m_dma_piece_count);\r\n}\r\n\r\nvoid CParkManager::decrement_meta_count(uint32 pieceChecksum)\r\n{\r\n\t--m_num_general_concrete_metapieces;\r\n\tm_dma_piece_count -= get_dma_usage(pieceChecksum);\r\n\t\r\n\t//printf(\"DecrementMetaCount '%s' %d   DMA=%d\\n\",Script::FindChecksumName(pieceChecksum),m_num_general_concrete_metapieces,m_dma_piece_count);\r\n\tDbg_MsgAssert(m_dma_piece_count >= 0,(\"Negative m_dma_piece_count of %d\\n\",m_dma_piece_count));\r\n}\r\n\r\n/*\r\n\tPosition is in cell coordinates, relative to northwest corner of 256X256 grid.\r\n\tY coordinate is relative to \"ground level\", can be + or -.\r\n\r\n\tRotation is 0-3.\r\n*/\r\nvoid CParkManager::AddMetaPieceToPark(GridDims pos, CConcreteMetaPiece *pMetaPiece)\r\n{\r\n\tDbg_Assert(m_state_on);\r\n\t\r\n\tDbg_MsgAssert(!(pMetaPiece->m_flags & CMetaPiece::mIN_PARK), (\"metapiece already in park\"));\r\n\tpMetaPiece->set_flag(CMetaPiece::mIN_PARK);\r\n\r\n\tpMetaPiece->m_cell_area.SetXYZ(pos.GetX(), pos.GetY(), pos.GetZ());\r\n\r\n\t// center_pos in world coordinates\r\n\tMth::Vector center_pos;\r\n\tcenter_pos[X] = ((float) pos.GetX() + (float) pMetaPiece->m_cell_area.GetW() / 2.0f) * CParkGenerator::CELL_WIDTH;\r\n\tcenter_pos[X] -= (CParkGenerator::CELL_WIDTH * (float) CParkManager::FLOOR_MAX_WIDTH) / 2.0f;\r\n\tcenter_pos[Z] = ((float) pos.GetZ() + (float) pMetaPiece->m_cell_area.GetL() / 2.0f) * CParkGenerator::CELL_LENGTH;\r\n\tcenter_pos[Z] -= (CParkGenerator::CELL_LENGTH * (float) CParkManager::FLOOR_MAX_LENGTH) / 2.0f;\r\n\tcenter_pos[Y] = pos.GetY() * CParkGenerator::CELL_HEIGHT;\r\n\r\n\t// XXX\r\n\t#if 0\r\n\tDbg_Printf(\"adding piece to park: (%d,%d,%d), (%.2f,%.2f,%.2f)\\n\", \r\n\t\t pos.GetX(), pos.GetY(), pos.GetZ(), \r\n\t\t center_pos[X], center_pos[Y], center_pos[Z]);\r\n\t#endif\r\n\t\r\n\tfor (uint i = 0; i < pMetaPiece->m_num_used_entries; i++)\r\n\t{\r\n\t\tMth::Vector rel_pos = pMetaPiece->GetRelativePosOfContainedPiece(i);\r\n\t\tCClonedPiece *p_piece = pMetaPiece->GetContainedPiece(i)->CastToCClonedPiece();\r\n\t\t\r\n\t\t// reposition piece from metapiece-relative coordinates to world-relative\r\n\t\tMth::Vector abs_pos;\r\n\t\tabs_pos[X] = center_pos[X] + rel_pos[X]; \r\n\t\tabs_pos[Z] = center_pos[Z] + rel_pos[Z]; \r\n\t\tabs_pos[Y] = center_pos[Y] + rel_pos[Y];\r\n\t\t\r\n\t\tp_piece->SetDesiredPos(abs_pos, CClonedPiece::CHANGE_SECTOR);\r\n\t\tp_piece->SetDesiredRot(Mth::ERot90((p_piece->GetRot() + pMetaPiece->m_rot) & 3), CClonedPiece::CHANGE_SECTOR);\r\n\t\tmp_generator->AddClonedPieceToWorld(p_piece);\r\n\t\tmp_generator->CalculateLighting(p_piece);\r\n\t}\r\n\r\n\tapply_meta_contained_risers_to_floor(pMetaPiece, true);\t\t\r\n\tbucketify_metapiece(pMetaPiece);\r\n\r\n\t// If it's a restart point, then add that to the list of restart points\r\n\tCParkGenerator::RestartType restart_type = IsRestartPiece(pMetaPiece->GetNameChecksum());\t\t\r\n\tif (restart_type != CParkGenerator::vEMPTY)\r\n\t{\r\n\t\tmp_generator->AddRestart(center_pos,pMetaPiece->m_rot,pos,restart_type,false);\r\n\t}\r\n\r\n\tif (!pMetaPiece->IsInnerShell())\r\n\t{\r\n\t\tif (!pMetaPiece->IsRiser())\r\n\t\t{\r\n\t\t\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags & ~(mIN_SYNC_WITH_PARK | mIS_NEWER_THAN_PARK));\r\n\t\t}\r\n\t\tincrement_meta_count(pMetaPiece->GetNameChecksum());\r\n\t}\r\n\t\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\t\"Moves\" a metapiece from one position to another. Really, the old metapiece is destroyed, and a new copy created,\r\n\tso be careful to replace any pointers to old one.\r\n*/\r\nCConcreteMetaPiece *CParkManager::RelocateMetaPiece(CConcreteMetaPiece *pMeta, int changeX, int changeY, int changeZ)\r\n{\r\n\tGridDims area = pMeta->GetArea();\r\n\tuint32 name = pMeta->GetNameChecksum();\r\n\tMth::ERot90 rot = pMeta->GetRot();\r\n\tCMetaPiece::EFlags old_flags = pMeta->m_flags;\r\n\r\n\t// get gap associated with metapiece\r\n\tint gap_half;\r\n\tbool gap_exists = false;\r\n\tCGapManager::GapDescriptor *p_gap_desc = GetGapDescriptor(area, &gap_half);\r\n\tCGapManager::GapDescriptor new_gap_desc;\r\n\tif (p_gap_desc)\r\n\t{\r\n\t\tgap_exists = true;\r\n\t\tnew_gap_desc = *p_gap_desc;\r\n\t\t\r\n\t\t// remove it\r\n\t\tRemoveGap(*p_gap_desc);\r\n\r\n\t\t// shift gap descriptor to new position\r\n\t\tnew_gap_desc.loc[gap_half][X] = new_gap_desc.loc[gap_half].GetX() + changeX;\r\n\t\tnew_gap_desc.loc[gap_half][Y] = new_gap_desc.loc[gap_half].GetY() + changeY;\r\n\t\tnew_gap_desc.loc[gap_half][Z] = new_gap_desc.loc[gap_half].GetZ() + changeZ;\r\n\t}\r\n\t\r\n\tDestroyConcreteMeta(pMeta, mDONT_DESTROY_PIECES_ABOVE);\r\n\t\r\n\tarea[X] += changeX;\r\n\tarea[Y] = area.GetY() + changeY;\r\n\tarea[Z] += changeZ;\r\n\r\n\tCConcreteMetaPiece *p_new_meta = CreateConcreteMeta(GetAbstractMeta(name), false);\r\n\tp_new_meta->SetRot(rot);\r\n\tp_new_meta->m_flags = old_flags;\r\n\tp_new_meta->clear_flag(CMetaPiece::mIN_PARK);\r\n\tAddMetaPieceToPark(area, p_new_meta);\r\n\r\n\tif (gap_exists)\r\n\t{\r\n\t\tAddGap(new_gap_desc);\r\n\t}\r\n\r\n\treturn p_new_meta;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tReturns list of concrete metapieces in specified area.\r\n\t\r\n\tModes:\r\n\tpPiece == NULL, grab all pieces in area specified by 'dims', excluding risers and riser-containing metas if desired.\r\n\t\r\n\tpPiece != NULL, does pretty much the same thing right now.\r\n*/\r\n\r\nCMapListNode *CParkManager::GetMetaPiecesAt(GridDims dims, Mth::ERot90 rot, CAbstractMetaPiece *pPiece, bool excludeRisers)\r\n{\r\n\tDbg_Assert(m_state_on);\r\n\t\r\n\tif (!pPiece)\r\n\t{\r\n\t\tCMapListNode *p_out_list = NULL;\r\n\t\t\r\n\t\t// need to be scanning an area bigger than 0\r\n\t\t//if (dims.mW == 0) dims.mW++;\r\n\t\t//if (dims.mL == 0) dims.mL++;\r\n\t\t\r\n\t\t// no piece supplied, just scan through and grab all metapieces\r\n\t\tint end_x = dims.GetX() + dims.GetW();\r\n\t\tfor (int x = dims.GetX(); x < end_x; x++)\r\n\t\t{\r\n\t\t\tint end_z = dims.GetZ() + dims.GetL();\r\n\t\t\tfor (int z = dims.GetZ(); z < end_z; z++)\r\n\t\t\t{\r\n\t\t\t\tCMapListNode *p_node = mp_bucket_list[x][z];\r\n\t\t\t\t\r\n\t\t\t\twhile(p_node)\r\n\t\t\t\t{\r\n\t\t\t\t\t//Ryan(\"boogah %d\\n\", x);\r\n\t\t\t\t\tif ((!excludeRisers || !(p_node->GetMeta()->IsRiser())) &&\r\n\t\t\t\t\t\tp_node->GetConcreteMeta()->test_for_conflict(dims, excludeRisers))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tadd_metapiece_to_node_list(p_node->GetMeta(), &p_out_list);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_node = p_node->GetNext();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tp_out_list->VerifyIntegrity();\r\n\t\treturn p_out_list;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(pPiece->GetRot() == Mth::ROT_0, (\"abstract metapiece needs 0 rotation\"));\r\n\t\t\r\n\t\t// build a descriptor table rotated and shifted to correct world coordinates\r\n\t\t\r\n\t\t// rotate the abstract meta piece to the desired rotation\r\n\t\tpPiece->SetRot(rot);\r\n\t\tdims[W] = pPiece->m_cell_area.GetW();\r\n\t\tdims[H] = pPiece->m_cell_area.GetH();\r\n\t\tdims[L] = pPiece->m_cell_area.GetL();\r\n\r\n\t\tCMapListNode *p_out_list = NULL;\r\n\t\t\r\n\t\t// grab list of all concrete metas\r\n\t\tCMapListTemp metas_in_park = GetMetaPiecesAt(dims);\r\n\r\n\t\t// for each contained piece\r\n\t\tfor (uint i = 0; i < pPiece->m_num_used_entries; i++)\r\n\t\t{\r\n\t\t\tSMetaDescriptor &desc = pPiece->get_desc_at_index(i);\r\n\t\t\tGridDims test_area(desc.mX, desc.mY, desc.mZ);\r\n\t\t\ttest_area[X] += dims.GetX();\r\n\t\t\ttest_area[Y] += dims.GetY();\r\n\t\t\ttest_area[Z] += dims.GetZ();\r\n\r\n\t\t\tCMapListNode *p_in_park_entry = metas_in_park.GetList();\r\n\t\t\twhile (p_in_park_entry)\r\n\t\t\t{\r\n\t\t\t\tif (p_in_park_entry->GetConcreteMeta()->test_for_conflict(test_area, false))\r\n\t\t\t\t\tadd_metapiece_to_node_list(p_in_park_entry->GetMeta(), &p_out_list);\r\n\r\n\t\t\t\tp_in_park_entry = p_in_park_entry->GetNext();\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// return abstract meta to a zero rotation\r\n\t\tpPiece->SetRot(Mth::ROT_0);\r\n\t\tp_out_list->VerifyIntegrity();\r\n\t\treturn p_out_list;\r\n\t}\r\n\t\r\n\treturn NULL;\r\n}\r\n\r\n// This is just a slightly faster version of GetMetaPiecesAt, which gets all\r\nCMapListNode *CParkManager::GetAreaMetaPieces(GridDims dims)\r\n{\r\n\tDbg_Assert(m_state_on);\r\n\r\n\tCMapListNode *p_out_list = NULL;\r\n\t\r\n\tint end_x = dims.GetX() + dims.GetW();\r\n\tfor (int x = dims.GetX(); x < end_x; x++)\r\n\t{\r\n\t\tint end_z = dims.GetZ() + dims.GetL();\r\n\t\tfor (int z = dims.GetZ(); z < end_z; z++)\r\n\t\t{\r\n\t\t\tCMapListNode *p_node = mp_bucket_list[x][z];\r\n\t\t\twhile(p_node)\r\n\t\t\t{\r\n\t\t\t\tadd_metapiece_to_node_list(p_node->GetMeta(), &p_out_list);\r\n\t\t\t\tp_node = p_node->GetNext();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\t\r\n\treturn p_out_list;\r\n}\r\n\r\n// K: These two functions used by CClipboard::CopySelectionToClipboard\r\nCMapListNode *CParkManager::GetMapListNode(int x, int z)\r\n{\r\n\treturn mp_bucket_list[x][z];\r\n}\r\n\r\nint CParkManager::GetFloorHeight(int x, int z)\r\n{\r\n\treturn m_floor_height_map[x][z].mHeight;\r\n}\r\n\t\r\n/*\r\n\tUsed to determine if resizing park will destroy existing metas.\r\n*/\r\nbool CParkManager::AreMetasOutsideBounds(GridDims new_dims)\r\n{\r\n\t//Ryan(\"New Park Bounds are: (%d,%d,%d)-(%d,%d,%d)\\n\", \r\n\t//\t new_dims.GetX(), new_dims.GetY(), new_dims.GetZ(),\r\n\t//\t new_dims.GetW(), new_dims.GetH(), new_dims.GetL());\r\n\tCMapListNode *p_node = mp_concrete_metapiece_list;\r\n\twhile(p_node)\r\n\t{\r\n\t\tCConcreteMetaPiece *p_meta = p_node->GetConcreteMeta();\r\n\t\tGridDims meta_area = p_meta->GetArea();\r\n\t\t//Ryan(\"Checking if meta in bounds: is_riser=%d, inner_shell=%d (%d,%d,%d)-(%d,%d,%d)\\n\", \r\n\t\t//\t p_meta->IsRiser(), p_meta->IsInnerShell(), \r\n\t\t//\t meta_area.GetX(), meta_area.GetY(), meta_area.GetZ(),\r\n\t\t//\t meta_area.GetW(), meta_area.GetH(), meta_area.GetL());\r\n\t\tif ((meta_area.GetX() < new_dims.GetX() ||\r\n\t\t\tmeta_area.GetZ() < new_dims.GetZ() ||\r\n\t\t\tmeta_area.GetX() + meta_area.GetW() > new_dims.GetX() + new_dims.GetW() ||\r\n\t\t\tmeta_area.GetZ() + meta_area.GetL() > new_dims.GetZ() + new_dims.GetL()) &&\r\n\t\t\t!p_meta->IsRiser() &&\r\n\t\t\t!p_meta->IsInnerShell() &&\r\n\t\t\t(p_meta->m_flags & CMetaPiece::mIN_PARK))\r\n\t\t\treturn true;\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tUsed to determine if resizing park will destroy existing metas.\r\n*/\r\nbool CParkManager::EnoughMemoryToResize(GridDims new_dims)\r\n{\r\n\tint current_num_tiles = m_park_near_bounds.GetW() * m_park_near_bounds.GetL();\r\n\tint new_num_tiles = new_dims.GetW() * new_dims.GetL();\r\n\r\n\tif (new_num_tiles - current_num_tiles > GetGenerator()->GetResourceSize(\"max_dma_pieces\") - GetDMAPieceCount())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\tint park_add_amount = (new_num_tiles - current_num_tiles) * mp_generator->GetResourceSize(\"floor_piece_size_park\");\r\n\tint main_add_amount = (new_num_tiles - current_num_tiles) * mp_generator->GetResourceSize(\"floor_piece_size_main\");\r\n\r\n\tCParkGenerator::MemUsageInfo usage_info = mp_generator->GetResourceUsageInfo();\r\n\tif (usage_info.mParkHeapFree < park_add_amount) \r\n\t{\r\n\t\tRyan(\"not enough memory for resize on park heap, need %d, have %d\\n\", park_add_amount, usage_info.mParkHeapFree);\r\n\t\treturn false;\r\n\t}\r\n\tif (usage_info.mMainHeapFree < main_add_amount) \r\n\t{\r\n\t\tRyan(\"not enough memory for resize on main heap, need %d, have %d\\n\", main_add_amount, usage_info.mMainHeapFree);\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t#ifdef __PLAT_NGC__\r\n\t// NGC has problems resizing if the top down heap is low due to UpdateSuperSectors requiring some temporary space.\r\n\tint required_top_down_heap=TOP_DOWN_REQUIRED_MARGIN;\r\n\t\r\n\t// If increasing the size of the park, then in the worse case the TD heap may reduce by main_add_amount,\r\n\t// if none of the fragments got used.\r\n\t// We want there to be more than TOP_DOWN_REQUIRED_MARGIN after increasing the size, so that the user\r\n\t// will be able to reduce the size afterwards, so add in main_add_amount to the requirement.\r\n\tif (main_add_amount > 0)\r\n\t{\r\n\t\trequired_top_down_heap += main_add_amount;\r\n\t}\t\r\n\t\r\n\tMem::Heap *p_top_down_heap = Mem::Manager::sHandle().TopDownHeap();\r\n\t// Check if there is enough TD heap at the moment\r\n\tif (p_top_down_heap->mp_region->MemAvailable() < required_top_down_heap)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t#endif\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tReturns max floor height within specified\r\n*/\r\nint\tCParkManager::GetFloorHeight(GridDims dims, bool *pRetUniformHeight)\r\n{\r\n\tDbg_Assert(m_state_on);\r\n\tDbg_MsgAssert(m_floor_height_map, (\"bad bad monkey!!!\"));\r\n\t\r\n\tint max_height = -10000;\r\n\t\r\n\tif (pRetUniformHeight)\r\n\t\t*pRetUniformHeight = true;\r\n\tint corner_height = m_floor_height_map[dims.GetX()][dims.GetZ()].mHeight;\r\n\t\r\n\tfor (int x = dims.GetX(); x < dims.GetX() + dims.GetW(); x++)\r\n\t{\r\n\t\tfor (int z = dims.GetZ(); z < dims.GetZ() + dims.GetL(); z++)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(x >= 0 && z >= 0 && x < FLOOR_MAX_WIDTH && z < FLOOR_MAX_LENGTH,\r\n\t\t\t\t\t\t  (\"out of bounds (%d,%d)\", x, z));\r\n\t\t\tif (pRetUniformHeight && m_floor_height_map[x][z].mHeight != corner_height)\r\n\t\t\t\t*pRetUniformHeight = false;\r\n\t\t\tif (m_floor_height_map[x][z].mHeight > max_height)\r\n\t\t\t\tmax_height = m_floor_height_map[x][z].mHeight;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn max_height;\r\n}\r\n\r\n\r\n\r\n\r\n#if 0\r\n/*\r\n\tChanges the floor height stored in the height map, A subsequent call to\r\n\tgenerate_floor_pieces_from_height_map() will make the geometry.\r\n*/\r\nvoid CParkManager::SetFloorHeight(GridDims area, int newHeight, bool justDropHighest)\r\n{\r\n\tfor (int x = area.GetX(); x < area.GetX() + area.GetW(); x++)\r\n\t{\r\n\t\tfor (int z = area.GetZ(); z < area.GetZ() + area.GetL(); z++)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(x >= 0 && z >= 0 && x < FLOOR_MAX_WIDTH && z < FLOOR_MAX_LENGTH,\r\n\t\t\t\t\t\t  (\"out of bounds (%d,%d)\", x, z));\r\n\t\t\t\r\n\t\t\tGridDims test_area(x, 0, z, 1, 1, 1);\r\n\t\t\tif (IsOccupiedByRoad(test_area))\r\n\t\t\t{\r\n\t\t\t\tm_floor_height_map[x][z].mHeight = 0;\r\n\t\t\t}\r\n\t\t\tif (justDropHighest)\r\n\t\t\t{\r\n\t\t\t\tif (m_floor_height_map[x][z].mHeight > newHeight)\r\n\t\t\t\t\tm_floor_height_map[x][z].mHeight = newHeight;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t\tm_floor_height_map[x][z].mHeight = newHeight;\r\n\t\t}\r\n\t}\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags & ~(mIN_SYNC_WITH_PARK | mIS_NEWER_THAN_PARK));\r\n}\r\n#endif\r\n\r\n\r\nvoid CParkManager::ResetFloorHeights(GridDims area)\r\n{\r\n\t// First move all the pieces in the area such that their y's are zero.\r\n\tCMapListTemp metas_at_pos = GetAreaMetaPieces(area);\r\n\tCMapListNode *p_entry = metas_at_pos.GetList();\r\n\twhile (p_entry)\r\n\t{\r\n\t\tCConcreteMetaPiece *p_meta = p_entry->GetConcreteMeta();\r\n\t\tif (!p_meta->IsRiser())\r\n\t\t{\r\n\t\t\tGridDims meta_area=p_meta->GetArea();\r\n\t\t\tRelocateMetaPiece(p_meta,0,-meta_area.GetY(),0);\r\n\t\t\t\r\n\t\t\t// Set the floor heights under the piece to zero. Need to do this as well\r\n\t\t\t// as zeroing the heights for the whole area, in case the piece sticks out\r\n\t\t\t// of the area.\r\n\t\t\tfor (int x = meta_area.GetX(); x < meta_area.GetX() + meta_area.GetW(); x++)\r\n\t\t\t{\r\n\t\t\t\tfor (int z = meta_area.GetZ(); z < meta_area.GetZ() + meta_area.GetL(); z++)\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(x >= 0 && z >= 0 && x < FLOOR_MAX_WIDTH && z < FLOOR_MAX_LENGTH,\r\n\t\t\t\t\t\t\t\t  (\"out of bounds (%d,%d)\", x, z));\r\n\t\t\t\t\tm_floor_height_map[x][z].mHeight=0;\r\n\t\t\t\t}\r\n\t\t\t}\t\t\r\n\t\t}\r\n\t\t\r\n\t\tp_entry = p_entry->GetNext();\r\n\t}\r\n\r\n\t// Then set all the floor heights to zero\r\n\tfor (int x = area.GetX(); x < area.GetX() + area.GetW(); x++)\r\n\t{\r\n\t\tfor (int z = area.GetZ(); z < area.GetZ() + area.GetL(); z++)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(x >= 0 && z >= 0 && x < FLOOR_MAX_WIDTH && z < FLOOR_MAX_LENGTH,\r\n\t\t\t\t\t\t  (\"out of bounds (%d,%d)\", x, z));\r\n\t\t\tm_floor_height_map[x][z].mHeight=0;\r\n\t\t}\r\n\t}\t\t\r\n\r\n\t// K: Do I need this?\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags & ~(mIN_SYNC_WITH_PARK | mIS_NEWER_THAN_PARK));\r\n\t\r\n\t// Then rebuild the floor so that the above changes take effect.\r\n\tRebuildFloor();\r\n}\t\r\n\r\n\r\n/*\r\n\tA \"column\" is a 3D region defined by the XZ rectangle of 'area'. Its bottom is at height 'y'. All the \r\n\tmetapieces within the column will change y position by the amount specified. Floor heights within the\r\n\tcolumn will change as well.\r\n\t\r\n\tReturns true if success.\r\n*/\r\nbool CParkManager::SlideColumn(GridDims area, int bottom, int top, bool up, bool uneven)\r\n{\r\n\tESlideColumnFlags flags = ESlideColumnFlags(mFIRST_RECURSE);\r\n\tif (up) flags = ESlideColumnFlags(flags | mUP);\r\n\tif (uneven) flags = ESlideColumnFlags(flags | mUNEVEN);\r\n\t\r\n\t/* Remove bookkeeping left from last SlideColumn */\r\n\tfinish_slide_column();\r\n\tif (mp_column_slide_list)\r\n\t\tmp_column_slide_list->DestroyList();\r\n\tmp_column_slide_list = NULL;\r\n\tm_num_metas_killed_in_slide = 0;\r\n\tm_num_pieces_killed_in_slide = 0;\r\n\t\r\n\t#if 1\r\n\tif (uneven && intersection_with_riser_containing_metas(area))\r\n\t\treturn false;\r\n\t#endif\r\n\t\r\n\tif (!slide_column_part_one(area, bottom, top, flags, &mp_column_slide_list))\r\n\t{\r\n\t\tfix_slide_column_part_one_failure();\r\n\t\treturn false;\r\n\t}\r\n\tslide_column_part_two(mp_column_slide_list);\r\n\t\r\n\tif (!up)\r\n\t\tkill_pieces_in_layer_under_area(area);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/*\r\n\tUndoes the results of a successful SlideColumn()\r\n*/\r\nvoid CParkManager::UndoSlideColumn()\r\n{\r\n\tfix_slide_column_part_one_failure();\r\n\t\r\n\tCMapListNode *p_node = mp_column_slide_list;\r\n\twhile(p_node)\r\n\t{\r\n\t\tp_node->mp_meta = RelocateMetaPiece(p_node->GetConcreteMeta(), 0, -p_node->mSlideAmount, 0);\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n}\r\n\r\n// K: This is copied from CCursor::ChangeFloorHeight\r\n// Modified to take a GridDims parameter so that it can be used by the clipboard pasting code.\r\nbool CParkManager::ChangeFloorHeight(GridDims dims, int dir)\r\n{\r\n\t/*\r\n\t\tUneven floor:\r\n\t\t\tIf going up, raise to height of topmost\r\n\t\t\tIf going down, only lower ones on same level\r\n\t*/\r\n\r\n\tbool uniform_height;\r\n\tint height = GetFloorHeight(dims, &uniform_height);\r\n\r\n\t/*\r\n\t\tNow, \r\n\t*/\r\n\r\n\tbool success = true;\r\n\tif (SlideColumn(dims, dims.GetY(), height, (dir > 0), !uniform_height))\r\n\t{\r\n\t\t//Ryan(\"Slide column, dir = %d, dims=\", dir);\r\n\t\t//dims.PrintContents();\r\n\r\n\t\t// K: This was required in the CCursor version of ChangeFloorHeight, can't\r\n\t\t// call it here though cos it is a member function of CCursor ...\r\n\t\t//change_cell_pos(0, 0);\r\n\t\t\r\n\t\tSpt::SingletonPtr<CParkEditor> p_editor;\r\n\t\tif (RebuildFloor(p_editor->IsParkFull()))\r\n\t\t{\r\n\t\t\tHighlightMetasWithGaps(false, NULL);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// out of memory, so reverse slide\r\n\t\t\tUndoSlideColumn();\r\n\t\t\tRebuildFloor();\r\n\t\t\tsuccess = false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t\tsuccess = false;\r\n\r\n\treturn success;\r\n}\r\n\r\n\r\n\r\n/*\r\n\tConverts a cell based XYZ coordinate to its world coordinate equivalent.\r\n*/\r\nMth::Vector\tCParkManager::GridCoordinatesToWorld(const GridDims &cellDims, Mth::Vector *pRetDims)\r\n{\r\n\tMth::Vector world_pos(((int) cellDims.GetX() - (int) CParkManager::FLOOR_MAX_WIDTH / 2) * CParkGenerator::CELL_WIDTH,\r\n\t\t(int) cellDims.GetY() * CParkGenerator::CELL_HEIGHT,\r\n\t\t((int) cellDims.GetZ() - (int) CParkManager::FLOOR_MAX_LENGTH / 2) * CParkGenerator::CELL_LENGTH);\r\n\r\n\tif (pRetDims)\r\n\t{\r\n\t\t(*pRetDims)[X] = cellDims.GetW() * CParkGenerator::CELL_WIDTH;\r\n\t\t(*pRetDims)[Y] = cellDims.GetH() * CParkGenerator::CELL_HEIGHT;\r\n\t\t(*pRetDims)[Z] = cellDims.GetL() * CParkGenerator::CELL_LENGTH;\r\n\t\t#if 0\r\n\t\tprintf(\"dims: (%d,%d,%d)-(%d,%d,%d)\\n\", \r\n\t\t\t   cellDims.GetW(), cellDims.GetH(), cellDims.GetL(),\r\n\t\t\t   (int) cellDims.GetX() - (int) CParkManager::FLOOR_MAX_WIDTH / 2,\r\n\t\t\t   (int) cellDims.GetY(),\r\n\t\t\t   (int) cellDims.GetZ() - (int) CParkManager::FLOOR_MAX_LENGTH / 2);\r\n\t\t#endif\r\n\t}\r\n\t\r\n\treturn world_pos;\r\n}\r\n\r\n\r\n\r\n\r\nCParkManager *CParkManager::sInstance()\r\n{\r\n\tDbg_Assert(sp_instance);\r\n\treturn sp_instance;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tThe manager keeps track of a piece database that matches the selection set the user sees at the top of the screen.\r\n*/\r\nCParkManager::CPieceSet &CParkManager::GetPieceSet(int setNumber, int *pMenuSetNumber)\r\n{\r\n\tDbg_Assert(setNumber >= 0 && setNumber < MAX_SETS);\r\n\t\r\n\tint menu_set_number = 0;\r\n\tfor (int s = 0; s < setNumber; s++)\r\n\t{\r\n\t\tif (m_palette_set[s].mVisible)\r\n\t\t\tmenu_set_number++;\r\n\t}\r\n\t\r\n\tif (pMenuSetNumber)\r\n\t\t*pMenuSetNumber = menu_set_number;\r\n\r\n\treturn m_palette_set[setNumber];\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\ty coordinates, dimensions of 'area' not used.\r\n*/\r\nbool CParkManager::IsOccupiedByRoad(GridDims area)\r\n{\r\n\tfor (uint i = 0; i < m_road_mask_tab_size; i++)\r\n\t{\r\n\t\tbool overlap = true;\r\n\t\tif (area.GetX() + area.GetW() <= m_road_mask_tab[i].GetX()) overlap = false;\r\n\t\telse if (area.GetX() >= m_road_mask_tab[i].GetX() + m_road_mask_tab[i].GetW()) overlap = false;\r\n\t\telse if (area.GetZ() + area.GetL() <= m_road_mask_tab[i].GetZ()) overlap = false;\r\n\t\telse if (area.GetZ() >= m_road_mask_tab[i].GetZ() + m_road_mask_tab[i].GetL()) overlap = false;\r\n\r\n\t\tif (overlap) return true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool CParkManager::CanPlacePiecesIn(GridDims cellDims, bool ignoreFloorHeight)\r\n{\r\n\tSpt::SingletonPtr<CParkEditor> p_editor;\r\n\tif (p_editor->IsParkFull())\r\n\t{\r\n\t\tParkEd(\"p_editor->IsParkFull()\");\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\t// Check if there are any pieces in the area already.\r\n\t// Not using GetMetaPiecesAt because it does not detect pieces in lowered cells for some reason.\r\n\tCMapListTemp metas_at_pos = GetAreaMetaPieces(cellDims);\r\n\tCMapListNode *p_entry = metas_at_pos.GetList();\r\n\twhile (p_entry)\r\n\t{\r\n\t\tCConcreteMetaPiece *p_meta=p_entry->GetConcreteMeta();\r\n\t\tif (!p_meta->IsRiser())\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\t\r\n\t\tp_entry = p_entry->GetNext();\r\n\t}\r\n\t\r\n\tif (!ignoreFloorHeight)\r\n\t{\r\n\t\tbool uniform_floor;\r\n\t\tint floor_height = GetFloorHeight(cellDims, &uniform_floor);\r\n\t\tif (floor_height != cellDims.GetY() || !uniform_floor)\r\n\t\t{\r\n\t\t\tParkEd(\"floor_height != cellDims.GetY() || !uniform_floor\");\r\n\t\t\treturn false;\r\n\t\t}\t\r\n\t}\r\n\t\t\r\n\tif (IsOccupiedByRoad(cellDims))\r\n\t{\r\n\t\tParkEd(\"IsOccupiedByRoad(cellDims)\");\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n// pHalf returns the half number associated with the piece, if any gap found\r\nCGapManager::GapDescriptor *CParkManager::GetGapDescriptor(GridDims &area, int *pHalf)\r\n{\r\n\tarea.SetWHL(1,1,1);\r\n\tCMapListTemp meta_list = GetMetaPiecesAt(area);\r\n\tif (meta_list.IsEmpty())\r\n\t\treturn NULL;\r\n\tCConcreteMetaPiece *p_meta = meta_list.GetList()->GetConcreteMeta();\r\n\r\n\tint tab_index;\r\n\tDbg_Assert(mp_gap_manager);\r\n\tif (!mp_gap_manager->IsGapAttached(p_meta, &tab_index))\r\n\t\treturn NULL;\r\n\t\r\n\tCGapManager::GapDescriptor *pDesc = mp_gap_manager->GetGapDescriptor(tab_index, pHalf);\r\n\tDbg_MsgAssert(pDesc, (\"couldn't find gap descriptor\"));\r\n\treturn pDesc;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCall from:\r\n\t\r\n\tread_from_compressed_map_buffer(), CParkEditor, gap adjustment code, gap name changer\r\n\t\r\n\t-see if meta at cursor loc\r\n\t-if user working on gap already, fail\r\n\t-if no prexisiting, remove gap-in-progress\r\n\t-build descriptor\r\n\t-add gap\r\n*/\r\nbool CParkManager::AddGap(CGapManager::GapDescriptor &descriptor)\r\n{\r\n\tDbg_Assert(mp_gap_manager);\r\n\tint gap_tab_index = mp_gap_manager->GetFreeGapIndex();\r\n\tif (gap_tab_index == -1) return false;\r\n\r\n\tfor (int i = 0; i < descriptor.numCompleteHalves; i++)\r\n\t{\r\n\t\t// fetch piece associated with this gap half\r\n\t\tdescriptor.loc[i].SetWHL(1,1,1);\r\n\t\tCMapListTemp meta_list = GetMetaPiecesAt(descriptor.loc[i]);\r\n\t\tif (meta_list.IsEmpty())\r\n\t\t\treturn false;\r\n\t\tDbg_MsgAssert(!meta_list.IsEmpty(), (\"am expecting a metapiece here\"));\r\n\t\tCConcreteMetaPiece *p_meta = meta_list.GetList()->GetConcreteMeta();\r\n\t\tDbg_MsgAssert(p_meta, (\"no pieces found at (%d,%d,%d)\", descriptor.loc[i].GetX(), descriptor.loc[i].GetY(), descriptor.loc[i].GetZ()));\r\n\t\tDbg_MsgAssert(!mp_gap_manager->IsGapAttached(p_meta, NULL), (\"gap is already attached\"));\r\n\t\tp_meta->set_flag(CMetaPiece::mGAP_ATTACHED);\r\n\t\t\r\n\t\tdescriptor.loc[i] = p_meta->GetArea();\r\n\t\t\r\n\t\t#if 0\r\n\t\tRyan(\"  Placing gap half %d, loc=(%d,%d,%d-%d,%d,%d), rot=%d, left=%d, right=%d\\n\", i,\r\n\t\t\t descriptor.loc[i].GetX(), descriptor.loc[i].GetY(), descriptor.loc[i].GetZ(), \r\n\t\t\t descriptor.loc[i].GetW(), descriptor.loc[i].GetH(), descriptor.loc[i].GetL(),\r\n\t\t\t descriptor.rot[i], descriptor.leftExtent[i], descriptor.rightExtent[i]);\r\n\t\t#endif\r\n\t\t\r\n\t\tGridDims area = p_meta->GetArea();\r\n\t\t\r\n\t\t#if 1\r\n\t\t// work out gap positioning\r\n\t\tMth::Vector gap_pos;\r\n\t\tfloat gap_length = 0.0f;\r\n\t\tint gap_rot = 0;\r\n\t\tswitch(descriptor.rot[i])\r\n\t\t{\r\n\t\t\tcase 0:\t// east\r\n\t\t\t\tgap_length = (area.GetL() + descriptor.leftExtent[i] + descriptor.rightExtent[i]) * CParkGenerator::CELL_LENGTH;\r\n\t\t\t\tgap_pos[X] = (area.GetX() + area.GetW()) * CParkGenerator::CELL_WIDTH - CParkGenerator::CELL_WIDTH / 2.0f - 1.0f;\r\n\t\t\t\tgap_pos[Z] = (area.GetZ() - descriptor.rightExtent[i]) * CParkGenerator::CELL_LENGTH + gap_length / 2.0f - CParkGenerator::CELL_LENGTH;\r\n\t\t\t\tgap_pos[Y] = area.GetY() * CParkGenerator::CELL_HEIGHT;\r\n\t\t\t\tgap_rot = 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1:\t// north\r\n\t\t\t\tgap_length = (area.GetW() + descriptor.leftExtent[i] + descriptor.rightExtent[i]) * CParkGenerator::CELL_WIDTH;\r\n\t\t\t\tgap_pos[X] = (area.GetX() - descriptor.rightExtent[i]) * CParkGenerator::CELL_WIDTH + gap_length / 2.0f - CParkGenerator::CELL_WIDTH;\r\n\t\t\t\tgap_pos[Z] = area.GetZ() * CParkGenerator::CELL_LENGTH - CParkGenerator::CELL_LENGTH / 2.0f + 1.0f;\r\n\t\t\t\tgap_pos[Y] = area.GetY() * CParkGenerator::CELL_HEIGHT;\r\n\t\t\t\tgap_rot = 0;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\t// west\r\n\t\t\t\tgap_length = (area.GetL() + descriptor.leftExtent[i] + descriptor.rightExtent[i]) * CParkGenerator::CELL_LENGTH;\r\n\t\t\t\tgap_pos[X] = area.GetX() * CParkGenerator::CELL_WIDTH - CParkGenerator::CELL_WIDTH / 2.0f + 1.0f;\r\n\t\t\t\tgap_pos[Z] = (area.GetZ() - descriptor.leftExtent[i]) * CParkGenerator::CELL_LENGTH + gap_length / 2.0f - CParkGenerator::CELL_LENGTH;\r\n\t\t\t\tgap_pos[Y] = area.GetY() * CParkGenerator::CELL_HEIGHT;\r\n\t\t\t\tgap_rot = 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 3:\t// south\r\n\t\t\t\tgap_length = (area.GetW() + descriptor.leftExtent[i] + descriptor.rightExtent[i]) * CParkGenerator::CELL_WIDTH;\r\n\t\t\t\tgap_pos[X] = (area.GetX() - descriptor.leftExtent[i]) * CParkGenerator::CELL_WIDTH + gap_length / 2.0f - CParkGenerator::CELL_WIDTH;\r\n\t\t\t\tgap_pos[Z] = (area.GetZ() + area.GetL()) * CParkGenerator::CELL_LENGTH - CParkGenerator::CELL_LENGTH / 2.0f - 1.0f;\r\n\t\t\t\tgap_pos[Y] = area.GetY() * CParkGenerator::CELL_HEIGHT;\r\n\t\t\t\tgap_rot = 0;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(0, (\"not a valid gap rotation\"));\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\t#endif\r\n\t\t\r\n\t\tgap_pos[X] -= MAX_WIDTH * CParkGenerator::CELL_WIDTH / 2.0f;\r\n\t\tgap_pos[Z] -= MAX_LENGTH * CParkGenerator::CELL_LENGTH / 2.0f;\r\n\r\n\t\tCClonedPiece *p_gap_piece = mp_generator->CreateGapPiece(gap_pos, gap_length, gap_rot);\r\n\t\tp_gap_piece->SetScaleX(gap_length / CParkGenerator::CELL_WIDTH);\r\n\t\t\r\n\t\t// create gap\r\n\t\tif (i == 0)\r\n\t\t\tmp_gap_manager->StartGap(p_gap_piece, p_meta, gap_tab_index);\r\n\t\telse\t\r\n\t\t\tmp_gap_manager->EndGap(p_gap_piece, p_meta, gap_tab_index);\r\n\t}\t\r\n\r\n\tdescriptor.tabIndex = gap_tab_index;\r\n\tmp_gap_manager->SetGapInfo(gap_tab_index, descriptor);\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/*\r\n\tCalled from: change cursor, cleanup, gap placement, gap adjustment, name change\r\n*/\r\nvoid CParkManager::RemoveGap(CGapManager::GapDescriptor &descriptor)\r\n{\r\n\t#if 1\r\n\t// XXX\r\n\tfor (int half = 0; half < 2; half++)\r\n\t\tRyan(\"   removing gap half %d (%d,%d,%d),(%d,%d,%d) left=%d right=%d, index=%d\\n\", half,\r\n\t\t\t descriptor.loc[half].GetX(), descriptor.loc[half].GetY(), descriptor.loc[half].GetZ(),\r\n\t\t\t descriptor.loc[half].GetW(), descriptor.loc[half].GetH(), descriptor.loc[half].GetL(),\r\n\t\t\t descriptor.leftExtent[half], descriptor.rightExtent[half],\r\n\t\t\t\tdescriptor.tabIndex);\r\n\t#endif\r\n\t\r\n\tCConcreteMetaPiece *p_meta[2];\r\n\tfor (int half = 0; half < descriptor.numCompleteHalves; half++)\r\n\t{\r\n\t\tCMapListTemp meta_list = GetMetaPiecesAt(descriptor.loc[half]);\r\n\t\tDbg_MsgAssert(!meta_list.IsEmpty(), (\"no pieces found at (%d,%d,%d)\", descriptor.loc[half].GetX(), descriptor.loc[half].GetY(), descriptor.loc[half].GetZ()));\r\n\t\t\r\n\t\t#if 1\r\n\t\tif (!meta_list.IsSingular())\r\n\t\t{\r\n//\t\t\tprintf(\"failed singularity, half %d\\n\", half);\r\n\t\t\tmeta_list.PrintContents();\r\n\t\t}\r\n\t\t#endif\r\n\t\t\r\n\t\t// go through list, find metapiece matching location above\r\n\t\t// there is only SUPPOSED to be one metapiece in list, but sometimes there are more\r\n\t\t// and I have no idea why, so fuck it\r\n\t\tCMapListNode *p_node = meta_list.GetList();\r\n\t\twhile(p_node)\r\n\t\t{\r\n\t\t\tp_meta[half] = p_node->GetConcreteMeta();\r\n\t\t\tGridDims area = p_meta[half]->GetArea();\r\n\r\n\t\t\tif (area.GetX() == descriptor.loc[half].GetX() &&\r\n\t\t\t\tarea.GetY() == descriptor.loc[half].GetY() &&\r\n\t\t\t\tarea.GetZ() == descriptor.loc[half].GetZ())\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tp_node = p_node->GetNext();\r\n\t\t}\r\n\r\n\t\t//p_meta[half] = meta_list.GetList()->GetConcreteMeta();\r\n\t\tp_meta[half]->Highlight(false);\r\n\t\tp_meta[half]->clear_flag(CMetaPiece::mGAP_ATTACHED);\r\n\t}\r\n\r\n\tint tab_index;\r\n\tDbg_Assert(mp_gap_manager);\r\n\tif (mp_gap_manager->IsGapAttached(p_meta[0], &tab_index))\r\n\t{\r\n\t\tmp_gap_manager->RemoveGap(tab_index);\r\n\t}\r\n\r\n\tdescriptor.tabIndex = -1;\r\n\t// Reset the cancel flags to the default, to fix TT9493\r\n\tdescriptor.mCancelFlags=Script::GetInteger(CRCD(0x9a27e74d,\"Cancel_Ground\"));\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkManager::RemoveGap(CConcreteMetaPiece *pMeta)\r\n{\r\n\tint tab_index;\r\n\tDbg_Assert(mp_gap_manager);\r\n\tif (!mp_gap_manager->IsGapAttached(pMeta, &tab_index))\r\n\t\treturn;\r\n\t\r\n\tint half;\r\n\tCGapManager::GapDescriptor *pDesc = mp_gap_manager->GetGapDescriptor(tab_index, &half);\r\n\tDbg_MsgAssert(pDesc, (\"couldn't find gap descriptor\"));\r\n\tRemoveGap(*pDesc);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkManager::HighlightMetasWithGaps(bool highlightOn, CGapManager::GapDescriptor *pDesc)\r\n{\r\n\tCMapListNode *p_node = mp_concrete_metapiece_list;\r\n\twhile (p_node)\r\n\t{\r\n\t\tif (p_node->GetConcreteMeta()->m_flags & CMetaPiece::mGAP_ATTACHED)\r\n\t\t\tp_node->GetConcreteMeta()->Highlight(highlightOn, true);\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n\r\n\tmp_generator->SetGapPiecesVisible(false);\r\n\t\r\n\tif (highlightOn && pDesc && pDesc->tabIndex >= 0)\r\n\t{\r\n\t\tmp_gap_manager->MakeGapWireframe(pDesc->tabIndex);\r\n\t}\r\n\telse if (!highlightOn)\r\n\t{\r\n\t\tmp_generator->SetGapPiecesVisible(false);\r\n\t}\r\n}\r\n\r\n// Added for use by s_generate_summary_info in mcfunc.cpp\r\nvoid CParkManager::GetSummaryInfoFromBuffer(uint8 *p_buffer, int *p_numGaps, int *p_numMetas, uint16 *p_theme, uint32 *p_todScript, int *p_width, int *p_length)\r\n{\r\n\tCompressedMapHeader *p_header=(CompressedMapHeader*)p_buffer;\r\n\t*p_width=p_header->mW;\r\n\t*p_length=p_header->mL;\r\n\t*p_numGaps=p_header->mNumGaps;\r\n\t*p_numMetas=p_header->mNumMetas;\r\n\t*p_theme=p_header->mTheme;\r\n\tif (p_header->mTODScript)\r\n\t{\r\n\t\t*p_todScript=p_header->mTODScript;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t*p_todScript=CRCD(0x1ca1ff20,\"default\");\r\n\t}\t\r\n}\r\n\r\n\r\n/*\r\n\tCreates a \"stack\" of risers within the specified vertical column. If !simpleBuild, will keep exisiting\r\n\triser metapieces if they do the job.\r\n\t\r\n\t'top' refers to cell position of top of topmost riser\r\n*/\r\nvoid CParkManager::output_riser_stack(BuildFloorParams &params)\r\n{\r\n\tDbg_MsgAssert(m_floor_height_map, (\"bad bad monkey!!!\"));\r\n\t\r\n\tDbg_MsgAssert(params.top >= -16 && params.top <= 15, (\"faulty floor height %d, at (%d,%d)\", params.top, params.x, params.z));\r\n\t\r\n\tint lowest_neighbor = 10000;\r\n\t\r\n\t// work out lowest neighbor\r\n\tif (params.x > m_park_far_bounds.GetX())\r\n\t{\r\n\t\tif (m_floor_height_map[params.x-1][params.z].mHeight < lowest_neighbor)\r\n\t\t\tlowest_neighbor = m_floor_height_map[params.x-1][params.z].mHeight;\r\n\t}\r\n\telse\r\n\t\tlowest_neighbor = (lowest_neighbor > 0) ? 0 : lowest_neighbor;\r\n\r\n\tif (params.x < m_park_far_bounds.GetX() + m_park_far_bounds.GetW() - 1)\r\n\t{\r\n\t\tif (m_floor_height_map[params.x+1][params.z].mHeight < lowest_neighbor)\r\n\t\t\tlowest_neighbor = m_floor_height_map[params.x+1][params.z].mHeight;\r\n\t}\r\n\telse\r\n\t\tlowest_neighbor = (lowest_neighbor > 0) ? 0 : lowest_neighbor;\r\n\r\n\tif (params.z > m_park_far_bounds.GetZ())\r\n\t{\r\n\t\tif (m_floor_height_map[params.x][params.z-1].mHeight < lowest_neighbor)\r\n\t\t\tlowest_neighbor = m_floor_height_map[params.x][params.z-1].mHeight;\r\n\t}\r\n\telse\r\n\t\tlowest_neighbor = (lowest_neighbor > 0) ? 0 : lowest_neighbor;\r\n\r\n\tif (params.z < m_park_far_bounds.GetZ() + m_park_far_bounds.GetL() - 1)\r\n\t{\r\n\t\tif (m_floor_height_map[params.x][params.z+1].mHeight < lowest_neighbor)\r\n\t\t\tlowest_neighbor = m_floor_height_map[params.x][params.z+1].mHeight;\r\n\t}\r\n\telse\r\n\t\tlowest_neighbor = (lowest_neighbor > 0) ? 0 : lowest_neighbor;\r\n\r\n\tEFloorFlags flags = mHAS_BOTTOM;\r\n\tGridDims road_test_area(params.x, 0, params.z, 1, 1, 1);\r\n\tif (IsOccupiedByRoad(road_test_area))\r\n\t{\r\n\t\tflags = EFloorFlags(flags | mNO_COVER);\r\n\t\tparams.top = 0;\r\n\t}\r\n\t\r\n\tif (lowest_neighbor < params.top)\r\n\t{\r\n\t\tparams.bottom = lowest_neighbor;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tparams.bottom = params.top-1;\r\n\t\tflags = EFloorFlags(flags & ~mHAS_BOTTOM);\r\n\t}\r\n\r\n\tparams.flags = flags;\r\n\tfor (int y = params.bottom; y < params.top; y++)\r\n\t{\r\n\t\tif (y == params.top-1 && !(flags & mNO_COVER))\r\n\t\t\tparams.flags = EFloorFlags(params.flags | mHAS_TOP);\r\n\t\t\r\n\t\tif (y == -1)\r\n\t\t{\r\n\t\t\tif (y <= lowest_neighbor)\r\n\t\t\t\tparams.heightSlotOffset = 3; // group 4 -- bottom level, just below surface\r\n\t\t\telse\r\n\t\t\t\tparams.heightSlotOffset = 2; // group 3 -- not bottom level, just below surface\r\n\t\t}\r\n\t\telse if (y < -1)\r\n\t\t{\r\n\t\t\tif (y <= lowest_neighbor)\r\n\t\t\t\tparams.heightSlotOffset = 0; // group 1 -- bottom level, not touching surface\r\n\t\t\telse\r\n\t\t\t\tparams.heightSlotOffset = 1; // group 2 -- not bottom level, not touching surface\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (y == params.top-1)\r\n\t\t\t{\r\n\t\t\t\tif (y == 0)\r\n\t\t\t\t\tparams.heightSlotOffset = 4; // group 5 -- top level risers sitting on surface\r\n\t\t\t\telse\r\n\t\t\t\t\tparams.heightSlotOffset = 7; // group 8 -- risers sitting above surface, top level\r\n\t\t\t}\r\n\t\t\telse if (y == 0)\r\n\t\t\t\tparams.heightSlotOffset = 5; // group 6 -- risers sitting on surface, but not top level\r\n\t\t\telse\r\n\t\t\t\tparams.heightSlotOffset = 6; // group 7 -- risers sitting above surface, not top level\r\n\t\t}\t\t\r\n\t\t\r\n\t\tparams.y = y;\r\n\t\tif (params.simpleBuild)\r\n\t\t\tbuild_add_floor_piece_simple(params); \r\n\t\telse\r\n\t\t\tbuild_add_floor_piece(params); \r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCreates a riser metapiece, if one is needed.\r\n*/\r\nvoid CParkManager::build_add_floor_piece(BuildFloorParams &params)\r\n{\r\n\tuint32 type = TYPE_EMPTY_BLOCK;\r\n\tif (params.flags & mHAS_BOTTOM)\r\n\t{\r\n\t\tif (params.flags & mHAS_TOP)\r\n\t\t\ttype = m_riser_piece_checksum[params.heightSlotOffset][0];\r\n\t\telse\r\n\t\t\ttype = m_riser_piece_checksum[params.heightSlotOffset][1];\r\n\t}\r\n\telse if (params.flags & mHAS_TOP)\r\n\t{\r\n\t\ttype = m_riser_piece_checksum[params.heightSlotOffset][2];\r\n\t}\r\n\telse\r\n\t\treturn;\r\n\t\r\n\t// see if floor already included in metapiece at this position\r\n\tint floor_height = params.y + 1;\r\n\tDbg_MsgAssert(floor_height >= -16 && floor_height <= 15, (\"faulty floor height %d, at (%d,%d,%d)\", \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  floor_height, params.x, params.y, params.z));\r\n\tuint32 floor_bit = (1<<(floor_height+16));\r\n\tif (m_floor_height_map[params.x][params.z].mEnclosedFloor & floor_bit)\r\n\t{\r\n\t\t#if 0\r\n\t\tprintf(\"preexisting riser at %d (%d,%d)!\\n\", floor_height, params.x, params.z);\r\n\t\t#endif\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// see if floor piece is already there and if it has desired type\r\n\tGridDims test_dims(params.x, params.y, params.z, 1, 1, 1);\r\n\tCMapListNode *p_node = GetMetaPiecesAt(test_dims);\r\n\tif (p_node)\r\n\t{\r\n\t\tif (p_node->GetMeta()->m_name_checksum == type)\r\n\t\t{\r\n\t\t\t/*\r\n\t\t\tif (type == TYPE_FLOOR_BLOCK && 0)\r\n\t\t\t\tprintf(\"preserving floor block at %d,%d,%d\\n\", \r\n\t\t\t\t\t   p_node->GetMeta()->GetArea().GetX(),\r\n\t\t\t\t\t   p_node->GetMeta()->GetArea().GetY(),\r\n\t\t\t\t\t   p_node->GetMeta()->GetArea().GetZ());\r\n\t\t\t*/\r\n\t\t\t\r\n\t\t\t// undo mark for kill\r\n\t\t\tp_node->GetMeta()->clear_flag(CMetaPiece::mMARK_FOR_KILL);\r\n\t\t\tp_node->DestroyList();\r\n\t\t\treturn;\r\n\t\t}\r\n\t\telse\r\n\t\t\tp_node->DestroyList();\r\n\t}\r\n\t\r\n\tif (!params.dryRun)\r\n\t{\r\n\t\t#ifdef USE_BUILD_LIST\r\n\t\tenum\r\n\t\t{\r\n\t\t\tMAX_BUILD_LIST_SIZE=10000,\r\n\t\t};\r\n\t\tDbg_MsgAssert(m_build_list_size<MAX_BUILD_LIST_SIZE-1,(\"Build list overflow\"));\r\n\r\n\t\tif (!mp_build_list_entry)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(m_build_list_size==0,(\"Expected m_build_list_size to be 0\"));\r\n\t\t\t#ifndef\t__USE_EXTERNAL_BUFFER__\t\t\t\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t\t\tmp_build_list_entry=(SBuildListEntry*)Mem::Malloc(MAX_BUILD_LIST_SIZE * sizeof(SBuildListEntry));\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t#else\r\n\t\t\tACQUIRE_BUFFER\r\n\t\t\tmp_build_list_entry = (SBuildListEntry*)__EXTERNAL_BUFFER__;\r\n\t\t\t#endif\r\n\t\t}\t\t\r\n\t\tmp_build_list_entry[m_build_list_size].mType=type;\r\n\t\tGridDims pos(params.x, params.y, params.z);\r\n\t\tmp_build_list_entry[m_build_list_size].mPos=pos;\r\n\t\t++m_build_list_size;\r\n\t\t#else\r\n\t\tCConcreteMetaPiece *p_out = CreateConcreteMeta(GetAbstractMeta(type));\r\n\t\tGridDims pos(params.x, params.y, params.z);\r\n\t\tAddMetaPieceToPark(pos, p_out);\r\n\t\t#endif\r\n\r\n\t\t\r\n\t\t#if 0\r\n\t\tif (type == TYPE_FLOOR_BLOCK)\r\n\t\t\tprintf(\"adding floor block at %d,%d,%d\\n\", \r\n\t\t\t\t   params.x,\r\n\t\t\t\t   params.y,\r\n\t\t\t\t   params.z);\r\n\t\r\n\t\tif (type == TYPE_FLOOR_WALL_BLOCK)\r\n\t\t\tprintf(\"adding floor wall block at %d,%d,%d\\n\", \r\n\t\t\t\t   params.x,\r\n\t\t\t\t   params.y,\r\n\t\t\t\t   params.z);\r\n\t\t#endif\r\n\t}\r\n\telse\r\n\t{\r\n\t\tparams.addCount2 += GetAbstractMeta(type)->m_num_used_entries;\r\n\t}\r\n\tparams.addCount++;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCreates a riser metapiece, period.\r\n*/\r\nvoid CParkManager::build_add_floor_piece_simple(BuildFloorParams &params)\r\n{\r\n\tuint32 type = TYPE_EMPTY_BLOCK;\r\n\tif (params.flags & mHAS_BOTTOM)\r\n\t{\r\n\t\tif (params.flags & mHAS_TOP)\r\n\t\t\ttype = m_riser_piece_checksum[params.heightSlotOffset][0];\r\n\t\telse\r\n\t\t\ttype = m_riser_piece_checksum[params.heightSlotOffset][1];\r\n\t}\r\n\telse if (params.flags & mHAS_TOP)\r\n\t{\r\n\t\ttype = m_riser_piece_checksum[params.heightSlotOffset][2];\r\n\t}\r\n\telse\r\n\t\treturn;\r\n\t\r\n\t\r\n\tCConcreteMetaPiece *p_out = CreateConcreteMeta(GetAbstractMeta(type));\r\n\tGridDims pos(params.x, params.y, params.z);\r\n\tAddMetaPieceToPark(pos, p_out);\r\n\tparams.addCount++;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tSome metapieces contain risers.\r\n*/\r\nvoid CParkManager::apply_meta_contained_risers_to_floor(CConcreteMetaPiece *pMetaPiece, bool add)\r\n{\r\n\tfor (uint i = 0; i < pMetaPiece->m_num_used_entries; i++)\r\n\t{\r\n\t\tCClonedPiece *p_piece = pMetaPiece->GetContainedPiece(i)->CastToCClonedPiece();\r\n\t\t\r\n\t\t// see if this piece affects floor height\r\n\t\tSMetaDescriptor &desc = pMetaPiece->get_desc_at_index(i);\r\n\t\tif (desc.mRiser)\r\n\t\t{\r\n\t\t\tGridDims riser_area;\r\n\t\t\tp_piece->GetCellDims(&riser_area);\r\n\t\t\triser_area[X] = pMetaPiece->m_cell_area.GetX() + desc.mX;\r\n\t\t\triser_area[Y] = pMetaPiece->m_cell_area.GetY() + desc.mY;\r\n\t\t\triser_area[Z] = pMetaPiece->m_cell_area.GetZ() + desc.mZ;\r\n\t\r\n\t\t\tint start_x = riser_area.GetX();\r\n\t\t\tint end_x = start_x + riser_area.GetW();\r\n\t\t\tint start_z = riser_area.GetZ();\r\n\t\t\tint end_z = start_z + riser_area.GetL();\r\n\t\t\t#if 0\r\n\t\t\tprintf(\"raising floor at: (%d,%d,%d)+(%d,%d,%d), desc.mRiser is %d at 0x%x, index %d\\n\",\r\n\t\t\t\t   pMetaPiece->m_cell_area.GetX(), pMetaPiece->m_cell_area.GetY(), pMetaPiece->m_cell_area.GetZ(),\r\n\t\t\t\t   desc.mX, desc.mY, desc.mZ, desc.mRiser, &desc.mRiser, i);\r\n\t\t\t#endif\r\n\t\t\tfor (int x = start_x; x < end_x; x++)\r\n\t\t\t{\r\n\t\t\t\tfor (int z = start_z; z < end_z; z++)\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(x >= 0 && z >= 0 && x < FLOOR_MAX_WIDTH && z < FLOOR_MAX_LENGTH,\r\n\t\t\t\t\t\t\t\t  (\"out of bounds (%d,%d)\", x, z));\r\n\t\t\t\t\tif (add)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (m_floor_height_map[x][z].mHeight < riser_area.GetY() + riser_area.GetH())\r\n\t\t\t\t\t\t\tm_floor_height_map[x][z].mHeight = riser_area.GetY() + riser_area.GetH();\r\n\t\t\t\t\t\tif (m_floor_height_map[x][z].mHeight > 15)\r\n\t\t\t\t\t\t\tm_floor_height_map[x][z].mHeight = 15;\r\n\t\t\t\t\t\tif (m_floor_height_map[x][z].mHeight < -16)\r\n\t\t\t\t\t\t\tm_floor_height_map[x][z].mHeight = -16;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Are there non-riser metapieces above this one?\r\n\t\t\t\t\t\tGridDims area_above = riser_area;\r\n\t\t\t\t\t\tarea_above[Y] = riser_area.GetY() + riser_area.GetH();\r\n\t\t\t\t\t\tarea_above.MakeInfinitelyHigh();\r\n\t\t\t\t\t\tCMapListTemp meta_list = GetMetaPiecesAt(area_above, Mth::ROT_0, NULL, true);\r\n\t\t\t\t\t\tif (meta_list.IsEmpty())\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif (m_floor_height_map[x][z].mHeight > riser_area.GetY())\r\n\t\t\t\t\t\t\t\tm_floor_height_map[x][z].mHeight = riser_area.GetY();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tfor (int y = riser_area.GetY(); y < riser_area.GetY() + riser_area.GetH(); y++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (add)\r\n\t\t\t\t\t\t\tm_floor_height_map[x][z].mEnclosedFloor |= (1<<(y+16+1));\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\tm_floor_height_map[x][z].mEnclosedFloor &= ~(1<<(y+16+1));\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t#if 0\r\n\t\t\t\t\tprintf(\"  floor change: (%d,%d) to %d, flags 0x%x, bottom %d, top %d\\n\", \r\n\t\t\t\t\t\t   x, z, m_floor_height_map[x][z].mHeight, m_floor_height_map[x][z].mEnclosedFloor,\r\n\t\t\t\t\t\t   riser_area.GetY(), riser_area.GetY() + riser_area.GetH());\r\n\t\t\t\t\t#endif\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nbool CParkManager::intersection_with_riser_containing_metas(GridDims area)\r\n{\r\n\tarea.MakeInfiniteOnY();\r\n\t\r\n\tCMapListTemp list = GetMetaPiecesAt(area, Mth::ROT_0, NULL, true);\r\n\tCMapListNode *p_node = list.GetList();\r\n\twhile (p_node)\r\n\t{\r\n\t\tif (p_node->GetConcreteMeta()->m_flags & CMetaPiece::mCONTAINS_RISERS)\r\n\t\t\treturn true;\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tChange map height. Add metapieces in column to move list. Repeat this for every metapiece in move list. No\r\n\tmetapiece will end up in move list twice, though.\r\n\t\r\n\tGood LUCK figuring this out. :)\r\n*/\r\nbool CParkManager::slide_column_part_one(GridDims area, int bottom, int top, ESlideColumnFlags flags, CMapListNode **ppMoveList)\r\n{\r\n\tGridDims test_area = area;\r\n\ttest_area[Y] = (uint8) bottom;\r\n\tif (flags & mFIRST_RECURSE)\r\n\t\ttest_area.MakeInfiniteOnY();\r\n\telse\r\n\t\ttest_area.MakeInfinitelyHigh();\r\n\r\n\tfor (int x = test_area.GetX(); x < test_area.GetX() + test_area.GetW(); x++)\r\n\t{\r\n\t\tfor (int z = test_area.GetZ(); z < test_area.GetZ() + test_area.GetL(); z++)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(x >= 0 && z >= 0 && x < FLOOR_MAX_WIDTH && z < FLOOR_MAX_LENGTH,\r\n\t\t\t\t\t\t  (\"out of bounds (%d,%d)\", x, z));\r\n\t\t\tif (!m_floor_height_map[x][z].mMarkAsSlid)\r\n\t\t\t{\r\n\t\t\t\tint change_amount = 0;\r\n\t\t\t\tif (flags & mUNEVEN)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (flags & mUP)\r\n\t\t\t\t\t\tchange_amount = top - m_floor_height_map[x][z].mHeight;\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tchange_amount = (m_floor_height_map[x][z].mHeight == top) ? -1 : 0;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif (flags & mUP)\r\n\t\t\t\t\t\tchange_amount = 1;\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tchange_amount = -1;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tm_floor_height_map[x][z].mHeight += change_amount;\r\n\t\t\t\tm_floor_height_map[x][z].mSlideAmount = change_amount;\r\n\r\n\t\t\t\tif (m_floor_height_map[x][z].mHeight < -16 || m_floor_height_map[x][z].mHeight > 15)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tm_floor_height_map[x][z].mMarkAsSlid = true;\r\n\t\t}\r\n\t}\r\n\r\n\tCMapListTemp list = GetMetaPiecesAt(test_area, Mth::ROT_0, NULL, true);\r\n\tCMapListNode *p_node = list.GetList();\r\n\twhile (p_node)\r\n\t{\r\n\t\tCConcreteMetaPiece *p_meta = p_node->GetConcreteMeta();\r\n\t\tGridDims meta_area = p_meta->GetArea();\r\n\t\t\r\n\t\tif (!p_meta->IsRiser() && !(p_meta->m_flags & CMetaPiece::mMARK_AS_SLID))\r\n\t\t{\r\n\t\t\t/*\r\n\t\t\t\tAre we actually going to move this meta?\r\n\t\t\t\t\r\n\t\t\t\tEven surface:\r\n\t\t\t\t-yes\r\n\t\t\t\t\r\n\t\t\t\tUneven\r\n\t\t\t\t-up: only if lower than top\r\n\t\t\t\t-down\r\n\t\t\t*/\r\n\t\t\t\r\n\t\t\tp_meta->set_flag(CMetaPiece::mMARK_AS_SLID);\r\n\t\t\tMem::Manager::sHandle().PushContext(mp_generator->GetParkEditorHeap());\r\n\t\t\tCMapListNode *p_new_node = new CMapListNode();\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\tp_new_node->mp_next = *ppMoveList;\r\n\t\t\tp_new_node->mp_meta = p_meta;\t\t\t\r\n\t\t\t*ppMoveList = p_new_node;\r\n\r\n\t\t\t#if 0\r\n\t\t\tRyan(\"rising meta at: \");\r\n\t\t\tp_meta->GetArea().PrintContents();\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tp_new_node->mSlideAmount = 0;\r\n\t\t\tif (flags & mUNEVEN)\r\n\t\t\t{\r\n\t\t\t\tif (flags & mUP)\r\n\t\t\t\t\tp_new_node->mSlideAmount = top - meta_area.GetY();\r\n\t\t\t\telse\r\n\t\t\t\t\tp_new_node->mSlideAmount = (meta_area.GetY() == top) ? -1 : 0;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (flags & mUP)\r\n\t\t\t\t\tp_new_node->mSlideAmount = 1;\r\n\t\t\t\telse\r\n\t\t\t\t\tp_new_node->mSlideAmount = -1;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tESlideColumnFlags recurse_flags = ESlideColumnFlags(flags & ~mFIRST_RECURSE);\r\n\t\t\tif (!slide_column_part_one(meta_area, meta_area.GetY(), top, recurse_flags, ppMoveList))\r\n\t\t\t\treturn false;\r\n\t\t}\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkManager::fix_slide_column_part_one_failure()\r\n{\r\n\tfor (int x = 0; x < FLOOR_MAX_WIDTH; x++)\r\n\t{\r\n\t\tfor (int z = 0; z < FLOOR_MAX_LENGTH; z++)\r\n\t\t{\r\n\t\t\tif (m_floor_height_map[x][z].mMarkAsSlid)\r\n\t\t\t{\r\n\t\t\t\tm_floor_height_map[x][z].mMarkAsSlid = false;\r\n\t\t\t\tm_floor_height_map[x][z].mHeight -= m_floor_height_map[x][z].mSlideAmount;\r\n\t\t\t}\r\n\t\t\tif (m_floor_height_map[x][z].mHeight > 15)\r\n\t\t\t\tm_floor_height_map[x][z].mHeight = 15;\r\n\t\t\tif (m_floor_height_map[x][z].mHeight < -16)\r\n\t\t\t\tm_floor_height_map[x][z].mHeight = -16;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tGo through move list, relocate each metapiece\r\n*/\r\nvoid CParkManager::slide_column_part_two(CMapListNode *pMoveList)\r\n{\r\n\t//Mem::Heap *p_top_down_heap = Mem::Manager::sHandle().TopDownHeap();\r\n\t\r\n\tCMapListNode *p_node = pMoveList;\r\n\twhile (p_node)\r\n\t{\r\n\t\tCConcreteMetaPiece *p_meta = p_node->GetConcreteMeta();\r\n\t\t\r\n\t\tif (p_node->mSlideAmount < 0)\r\n\t\t{\r\n\t\t\tkill_pieces_in_layer_under_area(p_meta->GetArea());\r\n\t\t}\r\n\r\n\t\tp_node->mp_meta = RelocateMetaPiece(p_meta, 0, p_node->mSlideAmount, 0);\r\n\r\n\t\t//if (p_top_down_heap->mp_region->MemAvailable() < 200000)\r\n\t\t//{\r\n\t\t//\tGetGenerator()->GetClonedScene()->UpdateSuperSectors();\r\n\t\t//}\t\r\n\t\t\r\n\t\tp_node = p_node->GetNext();\r\n\t}\t\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkManager::kill_pieces_in_layer_under_area(GridDims area)\r\n{\r\n\tGridDims kill_area = area;\r\n\tkill_area[Y] = area.GetY() - 1;\r\n\tkill_area[H] = 1;\r\n\r\n\t#if 0\r\n\tprintf(\"killing metas in area: (%d,%d,%d)-(%d,%d,%d)\\n\",\r\n\t\t   kill_area.GetX(), kill_area.GetY(), kill_area.GetZ(),\r\n\t\t   kill_area.GetW(), kill_area.GetH(), kill_area.GetL());\r\n\t#endif\r\n\r\n\tuint32 killed_result = DestroyMetasInArea(kill_area, mEXCLUDE_PIECES_MARKED_AS_SLID);\r\n\tm_num_metas_killed_in_slide += killed_result>>16;\r\n\tm_num_pieces_killed_in_slide += killed_result & 0xFFFF;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tUndo 'slid' markers in floor map array. Turn off MARK_AS_SLID flags on metapieces.\r\n*/\r\nvoid CParkManager::finish_slide_column()\r\n{\r\n\tfor (int x = m_park_far_bounds.GetX(); x < m_park_far_bounds.GetX() + m_park_far_bounds.GetW(); x++)\r\n\t{\r\n\t\tfor (int z = m_park_far_bounds.GetZ(); z < m_park_far_bounds.GetZ() + m_park_far_bounds.GetL(); z++)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(x >= 0 && z >= 0 && x < FLOOR_MAX_WIDTH && z < FLOOR_MAX_LENGTH,\r\n\t\t\t\t\t\t  (\"out of bounds (%d,%d)\", x, z));\r\n\t\t\tm_floor_height_map[x][z].mMarkAsSlid = false;\r\n\t\t\tm_floor_height_map[x][z].mSlideAmount = 0;\r\n\t\t}\r\n\t}\r\n\r\n\tCMapListNode *p_node = mp_concrete_metapiece_list;\r\n\twhile(p_node)\r\n\t{\r\n\t\tp_node->GetConcreteMeta()->clear_flag(CMetaPiece::mMARK_AS_SLID);\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n}\r\n\r\n#ifdef USE_BUILD_LIST\r\nvoid CParkManager::create_metas_in_build_list()\r\n{\r\n\tfor (int i=0; i<m_build_list_size; ++i)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_build_list_entry,(\"NULL mp_build_list_entry\"));\r\n\t\tCConcreteMetaPiece *p_out = CreateConcreteMeta(GetAbstractMeta(mp_build_list_entry[i].mType));\r\n\t\tAddMetaPieceToPark(mp_build_list_entry[i].mPos, p_out);\r\n\t}\t\r\n\tm_build_list_size=0;\r\n\tif (mp_build_list_entry)\r\n\t{\r\n\t\t#ifndef\t__USE_EXTERNAL_BUFFER__\r\n\t\tMem::Free(mp_build_list_entry);\r\n\t\t#endif\r\n\t\tmp_build_list_entry=NULL;\r\n\t}\t\r\n}\r\n#endif\r\n\r\n/*\r\n\tTurns the height map into actual riser geometry. Creates all the CConcreteMetaPieces that are needed, destroys \r\n\tthe ones that aren't. If an existing CConcreteMetaPiece matches the height map, it is preserved.\r\n\t\r\n\tThe simpleBuild parameter causes all riser metapieces to be destroyed and rebuilt. Use this parameter\r\n\twhen you know you'll be doing this anyway.\r\n\t\r\n\tdryRun means don't actually create or destroy pieces, just make a count\r\n*/\r\nbool CParkManager::generate_floor_pieces_from_height_map(bool simpleBuild, bool dryRun)\r\n{\r\n\tParkEd(\"CParkManager::generate_floor_pieces_from_height_map(simpleBuild = %d)\", simpleBuild);\r\n\t\r\n\tDbg_Assert(m_state_on);\r\n\t\r\n\t//printf(\"=============== generate_floor_pieces_from_height_map() ========================\\n\");\r\n\r\n\t// mark all existing floor pieces for destruction (some will be unmarked later)\r\n\tint mark_count = 0;\t// counts all risers existing upon entering this function\r\n\tCMapListNode *p_node = mp_concrete_metapiece_list;\r\n\twhile(p_node)\r\n\t{\r\n\t\tCMetaPiece *p_meta = p_node->GetMeta();\r\n\t\tif (p_meta->IsRiser())\r\n\t\t{\r\n\t\t\tp_meta->set_flag(CMetaPiece::mMARK_FOR_KILL);\r\n\t\t\tmark_count++;\r\n\t\t}\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n\tmark_count += m_num_metas_killed_in_slide;\r\n\r\n\t#ifdef USE_BUILD_LIST\r\n\tm_build_list_size=0;\r\n\tDbg_MsgAssert(mp_build_list_entry==NULL,(\"Non-NULL mp_build_list_entry\"));\r\n\t#endif\r\n\r\n\t\r\n\tDbg_MsgAssert(m_floor_height_map, (\"bad bad monkey!!!\"));\r\n\tBuildFloorParams riser_build_params;\r\n\triser_build_params.simpleBuild = simpleBuild;\r\n\triser_build_params.dryRun = dryRun;\r\n\triser_build_params.addCount = 0; // counts all risers added by the output_riser_stack() calls\r\n\triser_build_params.addCount2 = 0;\r\n\tfor (int x = m_park_near_bounds.GetX() - 1; x < m_park_near_bounds.GetX() + m_park_near_bounds.GetW() + 1; x++)\r\n\t{\r\n\t\tfor (int z = m_park_near_bounds.GetZ() - 1; z < m_park_near_bounds.GetZ() + m_park_near_bounds.GetL() + 1; z++)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(x >= 0 && z >= 0 && x < FLOOR_MAX_WIDTH && z < FLOOR_MAX_LENGTH,\r\n\t\t\t\t\t\t  (\"out of bounds (%d,%d)\", x, z));\r\n\t\t\triser_build_params.x = x;\r\n\t\t\triser_build_params.z = z;\r\n\t\t\triser_build_params.top = m_floor_height_map[x][z].mHeight;\r\n\t\t\triser_build_params.bottom = m_park_far_bounds.GetY();\r\n\t\t\toutput_riser_stack(riser_build_params);\r\n\t\t}\r\n\r\n\t\t#ifdef __PLAT_XBOX__\r\n\t\t// On the XBox the large amount of CPU time taken up by rebuilding the park causes a glitch when\r\n\t\t// wma music is playing. So make sure Pcm::Update gets called often whilst in this inner loop.\r\n\t\tDirectSoundDoWork();\r\n\t\tPcm::Update();\r\n\t\t#endif // __PLAT_XBOX__\r\n\t\t#ifdef __PLAT_NGC__\r\n\t\t// Same for the NGC ...\r\n\t\tPcm::Update();\r\n\t\t#endif // __PLAT_NGC__\r\n\t}\r\n\r\n\t// remove all marked floor piece\r\n\tint kill_count = 0; // counts risers killed\r\n\tint kill_count2 = 0; // counts contained pieces\r\n\tint left_count = 0;\t// counts risers not killed plus those added\r\n\tp_node = mp_concrete_metapiece_list;\r\n\twhile(p_node)\r\n\t{\r\n\t\tCMapListNode *p_nextNode = p_node->GetNext();\t\t// get next node now, as DestroyConcretMeta, below, can delete current node\r\n\t\tCMetaPiece *p_meta = p_node->GetMeta();\r\n\t\tif (p_meta->m_flags & CMetaPiece::mMARK_FOR_KILL)\r\n\t\t{\r\n\t\t\tkill_count++;\r\n\t\t\tkill_count2 += p_meta->m_num_used_entries;\r\n\t\t\tif (!dryRun)\r\n\t\t\t{\r\n\t\t\t\t//p_node->GetConcreteMeta()->GetArea().PrintContents();\r\n\t\t\t\tDestroyConcreteMeta(p_node->GetConcreteMeta(), mDONT_DESTROY_PIECES_ABOVE);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if (p_meta->IsRiser())\r\n\t\t\tleft_count++;\r\n\t\tp_node = p_nextNode;\r\n\t}\r\n\tkill_count += m_num_metas_killed_in_slide;\r\n\tkill_count2 += m_num_pieces_killed_in_slide;\r\n\t\r\n\r\n\t#ifdef USE_BUILD_LIST\r\n\tmp_generator->GetClonedScene()->UpdateSuperSectors();\t\r\n\tif (!dryRun)\r\n\t{\r\n\t\tleft_count+=m_build_list_size;\r\n\t\tcreate_metas_in_build_list();\r\n\t}\r\n\tDbg_MsgAssert(mp_build_list_entry==NULL,(\"Non-NULL mp_build_list_entry\"));\r\n\t#endif\r\n\t\t\r\n\t// risers preexisting + risers added - risers killed == risers left\r\n\tDbg_Assert(dryRun || riser_build_params.addCount == left_count + kill_count - mark_count);\r\n\t\r\n\t//printf(\"riser_build_params.addCount = %d kill_count = %d, kill_count2 = %d\\n\",riser_build_params.addCount,kill_count,kill_count2);\r\n\t\r\n\t//if (dryRun)\r\n\t//\tprintf(\"DRYRUN: \");\r\n\t//printf(\"marked %d pieces, killed %d, not killed %d, left %d, added %d\\n\", \r\n\t//\t   mark_count, kill_count, mark_count - kill_count, left_count, riser_build_params.addCount);\r\n\t//printf(\"addCount2 = %d, killCount2 = %d\\n\", riser_build_params.addCount2, kill_count2);\r\n\r\n\tif (dryRun && (riser_build_params.addCount > kill_count || riser_build_params.addCount2 > kill_count2))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t//if (dryRun && (riser_build_params.addCount - kill_count > 200))\r\n\t//{\r\n\t//\t// Don't allow height changes that will result in too many pieces being created, to prevent\r\n\t//\t// running out of memory.\r\n\t//\treturn false;\r\n\t//}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCreate new list if none\r\n*/\r\nvoid CParkManager::add_metapiece_to_node_list(CMetaPiece *pMetaToAdd, CMapListNode **ppList)\r\n{\r\n\tCMapListNode *p_test_node = *ppList;\r\n\twhile(p_test_node)\r\n\t{\r\n\t\tif (p_test_node->GetMeta() == pMetaToAdd) return; // it's in there\r\n\t\tp_test_node = p_test_node->GetNext();\r\n\t}\r\n\r\n\t// not in list already, so add it\r\n\tMem::Manager::sHandle().PushContext(mp_generator->GetParkEditorHeap());\r\n\tCMapListNode *p_new_node = new CMapListNode();\r\n\tMem::Manager::sHandle().PopContext();\r\n\tp_new_node->mp_meta = pMetaToAdd;\r\n\tp_new_node->mp_next = *ppList;\r\n\t*ppList = p_new_node;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tOpposite of above\r\n*/\r\nvoid CParkManager::remove_metapiece_from_node_list(CMetaPiece *pMetaToRemove, CMapListNode **ppList)\r\n{\r\n\tCMapListNode *p_node = *ppList;\r\n\tCMapListNode *p_prev = NULL;\r\n\twhile(p_node)\r\n\t{\r\n\t\tif (p_node->GetMeta() == pMetaToRemove)\r\n\t\t{\r\n\t\t\tif (p_prev)\r\n\t\t\t\tp_prev->mp_next = p_node->GetNext();\r\n\t\t\telse\r\n\t\t\t\t*ppList = p_node->GetNext();\r\n\r\n\t\t\tdelete p_node;\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t\r\n\t\tp_prev = p_node;\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkManager::bucketify_metapiece(CConcreteMetaPiece *pMeta)\r\n{\r\n\tfor (int x = 0; x < pMeta->m_cell_area.GetW(); x++)\r\n\t{\r\n\t\tfor (int z = 0; z < pMeta->m_cell_area.GetL(); z++)\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PushContext(mp_generator->GetParkEditorHeap());\r\n\t\t\tCMapListNode *p_new_entry = new CMapListNode();\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\tp_new_entry->mp_meta = pMeta;\r\n\t\t\t\r\n\t\t\tp_new_entry->mp_next = mp_bucket_list[x + pMeta->m_cell_area.GetX()][z + pMeta->m_cell_area.GetZ()];\r\n\t\t\tmp_bucket_list[x + pMeta->m_cell_area.GetX()][z + pMeta->m_cell_area.GetZ()] = p_new_entry;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkManager::debucketify_metapiece(CConcreteMetaPiece *pMeta)\r\n{\r\n\tfor (int x = 0; x < pMeta->m_cell_area.GetW(); x++)\r\n\t{\r\n\t\tfor (int z = 0; z < pMeta->m_cell_area.GetL(); z++)\r\n\t\t{\r\n\t\t\tCMapListNode *p_prev = NULL;\r\n\t\t\tCMapListNode *p_entry = mp_bucket_list[x + pMeta->m_cell_area.GetX()][z + pMeta->m_cell_area.GetZ()];\r\n\t\t\twhile(p_entry)\r\n\t\t\t{\r\n\t\t\t\t// piece should occur only once per list\r\n\t\t\t\t\r\n\t\t\t\tif (p_entry->mp_meta == pMeta)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (p_prev)\r\n\t\t\t\t\t\tp_prev->mp_next = p_entry->mp_next;\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tmp_bucket_list[x + pMeta->m_cell_area.GetX()][z + pMeta->m_cell_area.GetZ()] = p_entry->mp_next;\r\n\t\t\t\t\tdelete p_entry;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tp_prev = p_entry;\r\n\t\t\t\tp_entry = p_entry->mp_next;\r\n\t\t\t}\r\n\t\t} // end for z\r\n\t} // end for x\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkManager::create_abstract_metapieces()\r\n{\r\n\tParkEd(\"CParkManager::create_abstract_metapieces()\");\r\n\t\r\n\t/*\r\n\t\tThis add_later stuff is so we can create singular metapieces that weren't defined in \r\n\t\tEd_standard_metapieces. Every CPiece that exists must have a corresponding singular\r\n\t\tmetapiece, at least an abstract one.\r\n\t*/\r\n\tuint32 add_later_tab[1000];\r\n\tuint add_later_count = 0;\r\n\t\r\n\tScript::CArray *p_metapiece_array = Script::GetArray(\"Ed_standard_metapieces\", Script::ASSERT);\r\n\t\r\n\t// this first loop makes sure that metapieces named in EdPieces2.q actually exist\r\n\tfor (uint i = 0; i < p_metapiece_array->GetSize(); i++)\r\n\t{\r\n\t\tScript::CStruct *p_entry = p_metapiece_array->GetStructure(i);\r\n\t\t\r\n\t\t// see if singular or multiple metapiece\r\n\t\tuint32 single_crc = 0;\r\n\t\tif (p_entry->GetChecksum(\"single\", &single_crc))\r\n\t\t{\r\n\t\t\tmp_generator->GetMasterPiece(single_crc, false);\r\n\t\t}\t\t\r\n\t} // end for\r\n\r\n\r\n\t// now, build abstract metapieces from Ed_standard_metapieces array\r\n\tfor (uint i = 0; i < p_metapiece_array->GetSize(); i++)\r\n\t{\r\n\t\tScript::CStruct *p_entry = p_metapiece_array->GetStructure(i);\r\n\t\t\r\n\t\tMem::Manager::sHandle().PushContext(mp_generator->GetParkEditorHeap());\r\n\t\tCAbstractMetaPiece *p_meta = new CAbstractMetaPiece();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\t// see if singular or multiple metapiece\r\n\t\tuint32 single_crc = 0;\r\n\t\tScript::CArray *p_multiple_array = NULL;\r\n\t\tif (p_entry->GetChecksum(\"single\", &single_crc))\r\n\t\t{\r\n\t\t\tp_meta->initialize_desc_table(1);\r\n\t\t\t\r\n\t\t\tCSourcePiece *p_source_piece = mp_generator->GetMasterPiece(single_crc, true);\r\n\t\t\t\r\n\t\t\tGridDims area(0, 0, 0);\r\n\t\t\tp_source_piece->GetCellDims(&area);\r\n\t\t\tScript::CArray *p_pos_array = NULL;\r\n\t\t\tif (p_entry->GetArray(\"pos\", &p_pos_array))\r\n\t\t\t{\r\n\t\t\t\tarea.SetXYZ(p_pos_array->GetInteger(0), p_pos_array->GetInteger(1), p_pos_array->GetInteger(2));\r\n\t\t\t}\r\n\r\n\t\t\tp_meta->add_piece(p_source_piece, &area);\r\n\r\n\t\t\t// if just a singular meta, use the name checksum already associated with single piece\r\n\t\t\tp_meta->m_name_checksum = p_source_piece->GetType();\r\n\t\t\tDbg_Assert(add_later_count < 1000);\r\n\t\t\tadd_later_tab[add_later_count++] = p_meta->m_name_checksum;\t\t\t\r\n\t\t\tp_meta->set_flag(CMetaPiece::mSINGULAR);\r\n\t\t\t\r\n\t\t\t// Finally, Check to see if it is a special type\r\n\t\t\t// and add it to the table of special types: \r\n\t\t\t\r\n\t\t\tuint32 special_type;\r\n\t\t\tif (p_entry->GetChecksum(CRCD(0xf176a9fd,\"special_type\"), &special_type))\r\n\t\t\t{\r\n\r\n\t\t\t\t// gap piece detection here ----- need to reinstate this when we do gaps\t\t\t\t\r\n\t\t\t\tif (special_type == CRCD(0x2813ab8a,\"gap_placement\"))\r\n\t\t\t\t\tp_meta->set_flag(CMetaPiece::mGAP_PLACEMENT);\r\n\t\t\t\tif (special_type == CRCD(0xfc26b6f4,\"area_selection\"))\r\n\t\t\t\t\tp_meta->set_flag(CMetaPiece::mAREA_SELECTION);\r\n\t\t\t\tif (special_type == CRCD(0xffd81c08,\"rail_placement\"))\r\n\t\t\t\t\tp_meta->set_flag(CMetaPiece::mRAIL_PLACEMENT);\r\n\t\t\t\t\r\n\t\t\t\tif (special_type == CRCD(0x48fa9c7b,\"restart_1\"))\r\n\t\t\t\t\tSetRestartTypeId(CParkGenerator::vONE_PLAYER, single_crc);\r\n\t\t\t\tif (special_type == CRCD(0x419183b2,\"restart_multi\"))\r\n\t\t\t\t\tSetRestartTypeId(CParkGenerator::vMULTIPLAYER, single_crc);\r\n\t\t\t\tif (special_type == CRCD(0xe69aefaf,\"restart_horse\"))\r\n\t\t\t\t\tSetRestartTypeId(CParkGenerator::vHORSE, single_crc);\r\n\t\t\t\tif (special_type == CRCD(0xa091ce25,\"king_of_hill\"))\r\n\t\t\t\t\tSetRestartTypeId(CParkGenerator::vKING_OF_HILL, single_crc);\r\n\t\t\t\t\r\n\t\t\t\tif (special_type == CRCD(0x74b0f4e9,\"red_flag\"))\r\n\t\t\t\t{\r\n\t\t\t\t\tSetRestartTypeId(CParkGenerator::vRED_FLAG, single_crc);\r\n\t\t\t\t\tp_meta->set_flag(CMetaPiece::mNOT_ON_GC);\r\n\t\t\t\t}\r\n\t\t\t\tif (special_type == CRCD(0xc893acf8,\"green_flag\"))\r\n\t\t\t\t{\r\n\t\t\t\t\tSetRestartTypeId(CParkGenerator::vGREEN_FLAG, single_crc);\r\n\t\t\t\t\tp_meta->set_flag(CMetaPiece::mNOT_ON_GC);\r\n\t\t\t\t}\r\n\t\t\t\tif (special_type == CRCD(0x40bdfa7e,\"blue_flag\"))\r\n\t\t\t\t{\r\n\t\t\t\t\tSetRestartTypeId(CParkGenerator::vBLUE_FLAG, single_crc);\r\n\t\t\t\t\tp_meta->set_flag(CMetaPiece::mNOT_ON_GC);\r\n\t\t\t\t}\r\n\t\t\t\tif (special_type == CRCD(0x3ae047fc,\"yellow_flag\"))\r\n\t\t\t\t{\r\n\t\t\t\t\tSetRestartTypeId(CParkGenerator::vYELLOW_FLAG, single_crc);\r\n\t\t\t\t\tp_meta->set_flag(CMetaPiece::mNOT_ON_GC);\r\n\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if (p_entry->GetArray(\"multiple\", &p_multiple_array))\r\n\t\t{\r\n\t\t\tbool contains_risers = false;\r\n\t\t\tp_meta->initialize_desc_table(p_multiple_array->GetSize());\r\n\t\t\t\r\n\t\t\tfor (uint j = 0; j < p_multiple_array->GetSize(); j++)\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct *p_name_pos = p_multiple_array->GetStructure(j);\r\n\t\t\t\t\r\n\t\t\t\tScript::CComponent *p_name_crc_comp = p_name_pos->GetNextComponent(NULL);\r\n\t\t\t\tDbg_Assert(p_name_crc_comp->mType == ESYMBOLTYPE_NAME);\t\t\t\t\r\n\t\t\t\tuint32 name_crc = p_name_crc_comp->mChecksum;\r\n\r\n\t\t\t\tScript::CArray *p_pos_array = NULL;\r\n\t\t\t\tp_name_pos->GetArray(NONAME, &p_pos_array, Script::ASSERT);\r\n\t\t\t\t\r\n\t\t\t\tCSourcePiece *p_source_piece = mp_generator->GetMasterPiece(name_crc, true);\r\n\t\t\t\tDbg_Assert(add_later_count < 1000);\r\n\t\t\t\tadd_later_tab[add_later_count++] = name_crc;\r\n\t\t\t\t\r\n\t\t\t\tGridDims area;\r\n\t\t\t\tp_source_piece->GetCellDims(&area);\r\n\t\t\t\tarea.SetXYZ(p_pos_array->GetInteger(0), p_pos_array->GetInteger(1), p_pos_array->GetInteger(2));\r\n\t\r\n\t\t\t\tMth::ERot90 rot = Mth::ROT_0;\r\n\t\t\t\tif (p_pos_array->GetSize() > 3)\r\n\t\t\t\t\trot = (Mth::ERot90) p_pos_array->GetInteger(3);\r\n\t\t\t\t\r\n\t\t\t\tif (p_name_pos->ContainsFlag(CRCD(0xcd75a3f,\"riser\")))\r\n\t\t\t\t\tcontains_risers = true;\r\n\t\t\t\tp_meta->add_piece(p_source_piece, &area, rot, p_name_pos->ContainsFlag(CRCD(0xcd75a3f,\"riser\")));\r\n\t\t\t} // end for\r\n\r\n\t\t\tif (contains_risers)\r\n\t\t\t\tp_meta->set_flag(CMetaPiece::mCONTAINS_RISERS);\r\n\t\t}\r\n\t\telse if (p_entry->GetArray(\"ack\", &p_multiple_array))\r\n\t\t{\r\n\t\t\tp_meta->initialize_desc_table(p_multiple_array->GetSize());\r\n\t\t\t\r\n\t\t\tfor (uint j = 0; j < p_multiple_array->GetSize(); j++)\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct *p_name_pos = p_multiple_array->GetStructure(j);\r\n\t\t\t\t\r\n\t\t\t\tScript::CComponent *p_name_crc_comp = p_name_pos->GetNextComponent(NULL);\r\n\t\t\t\tDbg_Assert(p_name_crc_comp->mType == ESYMBOLTYPE_NAME);\t\t\t\t\r\n\t\t\t\tuint32 name_crc = p_name_crc_comp->mChecksum;\r\n\r\n\t\t\t\tScript::CArray *p_pos_array = NULL;\r\n\t\t\t\tp_name_pos->GetArray(NONAME, &p_pos_array, Script::ASSERT);\r\n\t\t\t\t\r\n\t\t\t\tCAbstractMetaPiece *p_source_meta = GetAbstractMeta(name_crc);\r\n\t\t\t\t\r\n\t\t\t\tGridDims area = p_source_meta->GetArea();\r\n\t\t\t\tarea.SetXYZ(p_pos_array->GetInteger(0), p_pos_array->GetInteger(1), p_pos_array->GetInteger(2));\r\n\t\r\n\t\t\t\tMth::ERot90 rot = Mth::ROT_0;\r\n\t\t\t\tif (p_pos_array->GetSize() > 3)\r\n\t\t\t\t\trot = (Mth::ERot90) p_pos_array->GetInteger(3);\r\n\t\t\t\t\r\n\t\t\t\tp_meta->add_piece_dumb(p_source_meta, &area, rot, p_name_pos->ContainsFlag(CRCD(0xcd75a3f,\"riser\")));\r\n\t\t\t} // end for\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"screwy entry %d in Ed_standard_metapieces\", i));\r\n\t\t}\r\n\t\t\r\n\t\t#if 1\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tGridDims test_area = p_meta->GetArea();\r\n\t\tDbg_MsgAssert(test_area.GetW() > 0 && test_area.GetH() > 0 && test_area.GetL() > 0, \r\n\t\t\t\t\t  (\"metapiece %s has invalid dimensions (%d,%d,%d)\", Script::FindChecksumName(p_meta->GetNameChecksum()),\r\n\t\t\t\t\t   test_area.GetW(), test_area.GetH(), test_area.GetL()));\r\n\t\t#if 0\r\n\t\tif (p_meta->GetNameChecksum() == Script::GenerateCRC(\"Sk4Ed_Fence_10x10\"))\r\n\t\t\tprintf(\"OY! metapiece %s has dimensions (%d,%d,%d)\\n\", Script::FindChecksumName(p_meta->GetNameChecksum()),\r\n\t\t\t\t\t   test_area.GetW(), test_area.GetH(), test_area.GetL());\r\n\t\t#endif\r\n\r\n\t\t#endif\t\t\r\n\t\t#endif\r\n\t\t\r\n\t\t// the name provided in EdPieces.q, if any, takes precedence\r\n\t\tif (p_entry->GetChecksum(\"name\", &p_meta->m_name_checksum))\r\n\t\t{\r\n\t\t\t// this metapiece has been renamed, so we must treat it as a non-singular piece\r\n\t\t\tp_meta->clear_flag(CMetaPiece::mSINGULAR);\r\n\t\t}\r\n\t\t// make sure no piece with checksum currently exists\r\n\t\tDbg_MsgAssert(!GetAbstractMeta(p_meta->m_name_checksum), (\"name checksum already used for metapiece\"));\r\n\r\n\t\tif (p_entry->ContainsFlag(\"is_riser\"))\r\n\t\t\tp_meta->set_flag(CMetaPiece::mIS_RISER);\r\n\t\tif (p_entry->ContainsFlag(\"no_rails\"))\r\n\t\t{\r\n#\t\t\tifdef __NOPT_ASSERT__\r\n\t\t\tRyan(\"No rails for %s\\n\", Script::FindChecksumName(p_meta->m_name_checksum));\r\n#\t\t\tendif\r\n\t\t\tp_meta->set_flag(CMetaPiece::mNO_RAILS);\r\n\t\t}\r\n\t\t\r\n\t\tMem::Manager::sHandle().PushContext(mp_generator->GetParkEditorHeap());\r\n\t\tCMapListNode *p_node = new CMapListNode();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\tp_node->mp_meta = p_meta;\r\n\t\tp_node->mp_next = mp_abstract_metapiece_list;\r\n\t\tmp_abstract_metapiece_list = p_node;\r\n\t\tm_num_abstract_metapieces++;\r\n\t} // end for\r\n\r\n\t\r\n\tfor (uint i = 0; i < add_later_count; i++)\r\n\t{\r\n\t\tif (GetAbstractMeta(add_later_tab[i]))\r\n\t\t\tcontinue;\r\n\t\t\r\n\t\tMem::Manager::sHandle().PushContext(mp_generator->GetParkEditorHeap());\r\n\t\tCAbstractMetaPiece *p_meta = new CAbstractMetaPiece();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\tp_meta->initialize_desc_table(1);\r\n\t\tCSourcePiece *p_source_piece = mp_generator->GetMasterPiece(add_later_tab[i], true);\r\n\r\n\t\tGridDims area(0, 0, 0);\r\n\t\tp_source_piece->GetCellDims(&area);\r\n\t\tp_meta->add_piece(p_source_piece, &area);\r\n\r\n\t\tp_meta->m_name_checksum = add_later_tab[i];\r\n\t\tp_meta->set_flag(CMetaPiece::mSINGULAR);\r\n\r\n\t\tMem::Manager::sHandle().PushContext(mp_generator->GetParkEditorHeap());\r\n\t\tCMapListNode *p_node = new CMapListNode();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\tp_node->mp_meta = p_meta;\r\n\t\tp_node->mp_next = mp_abstract_metapiece_list;\r\n\t\tmp_abstract_metapiece_list = p_node;\r\n\t\tm_num_abstract_metapieces++;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkManager::SetRestartTypeId(CParkGenerator::RestartType type, uint32 id)\r\n{\r\n\r\n\t// Mick\t\r\n//\tprintf (\"SetRestartTypeId(%d,%x)\\n\",type,id);\t\r\n\tif (type > CParkGenerator::vEMPTY && type < CParkGenerator::vNUM_RESTART_TYPES)\r\n\t{\r\n\t\tm_restartPieceIdTab[type] = id;\t\t\r\n\t}\r\n\r\n/*\t\r\n\tswitch(type)\r\n\t{\r\n\t\tcase CParkGenerator::vONE_PLAYER:\r\n//\t\t\tprintf (\"Found vONE_PLAYER\\n\");\r\n\t\t\tm_restartPieceIdTab[0] = id;\r\n\t\t\tbreak;\r\n\t\tcase CParkGenerator::vMULTIPLAYER:\r\n//\t\t\tprintf (\"Found vMULTIPLAYER\\n\");\r\n\t\t\tm_restartPieceIdTab[1] = id;\r\n\t\t\tbreak;\r\n\t\tcase CParkGenerator::vHORSE:\r\n//\t\t\tprintf (\"Found vHORSE\\n\");\r\n\t\t\tm_restartPieceIdTab[2] = id;\r\n\t\t\tbreak;\r\n\t\tcase CParkGenerator::vKING_OF_HILL:\r\n//\t\t\tprintf (\"Found vKING_OF_HILL\\n\");\r\n\t\t\tm_restartPieceIdTab[3] = id;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\r\n\t}\r\n*/\r\n}\r\n\r\n\r\n\r\n\r\n// returns the type of restart piece this is, or vEMPTY is it is not a restart piece\r\n// (vEMPTY is 0, so the return value can be treated as true/false)\r\nCParkGenerator::RestartType CParkManager::IsRestartPiece(uint32 id)\r\n{\r\n\tfor (int type = CParkGenerator::vONE_PLAYER; type < CParkGenerator::vNUM_RESTART_TYPES; type++)\r\n\t{\r\n\t\tif (id == m_restartPieceIdTab[type])\r\n\t\t{\r\n\t\t\treturn (CParkGenerator::RestartType) type;\r\n\t\t}\r\n\t}\r\n\treturn CParkGenerator::vEMPTY;\r\n\r\n/*\r\n\tif (id == m_restartPieceIdTab[0])\r\n\t\treturn CParkGenerator::vONE_PLAYER;\r\n\tif (id == m_restartPieceIdTab[1])\r\n\t\treturn CParkGenerator::vMULTIPLAYER;\r\n\tif (id == m_restartPieceIdTab[2])\r\n\t\treturn CParkGenerator::vHORSE;\r\n\tif (id == m_restartPieceIdTab[3])\r\n\t\treturn CParkGenerator::vKING_OF_HILL;\r\n\treturn CParkGenerator::vEMPTY;\r\n*/\r\n}\r\n\r\n/*\r\nCommented out cos I just discovered Destroy() does pretty much the same thing!\r\n\r\n// K: This is for freeing up as much memory as possible when playing a park, so that\r\n// the number of players can be increased. Each player requires 830K.\r\nvoid CParkManager::FreeUpMemoryForPlayingPark()\r\n{\r\n\t// Delete everything in the park editor heap, so that it can be removed, freeing\r\n\t// up 900K.\r\n\t\r\n\t// First delete the cursor.\r\n\tEd::CParkEditor::Instance()->DeleteCursor();\r\n\t\r\n\tprintf(\"After deleting cursor ...\\n\");\t\r\n\tprintf(\"Num CMapListNode's = %d\\n\",Ed::CMapListNode::SGetNumUsedItems());\r\n\tMemView_AnalyzeHeap(mp_generator->GetParkEditorHeap());\r\n\r\n\tmp_generator->DeleteSourceAndClonedPieces();\r\n\t\r\n\t// Delete the concrete metapieces\r\n\tCMapListNode *p_node = mp_concrete_metapiece_list;\r\n\twhile(p_node)\r\n\t{\r\n\t\tCMapListNode *p_next_node = p_node->GetNext();\r\n\t\tdelete p_node->GetConcreteMeta();\r\n\t\tdelete p_node;\r\n\t\tp_node = p_next_node;\r\n\t}\r\n\tm_num_concrete_metapieces=0;\r\n\tmp_concrete_metapiece_list=NULL;\r\n\r\n\tprintf(\"After deleting CParkManager::mp_concrete_metapiece_list ...\\n\");\t\r\n\tprintf(\"Num CMapListNode's = %d\\n\",Ed::CMapListNode::SGetNumUsedItems());\r\n\tMemView_AnalyzeHeap(Ed::CParkManager::sInstance()->GetGenerator()->GetParkEditorHeap());\r\n\r\n\t// Free up the abstract metapieces.\t\r\n\tp_node = mp_abstract_metapiece_list;\r\n\twhile(p_node)\r\n\t{\r\n\t\tCMapListNode *p_next_node = p_node->GetNext();\r\n\t\tdelete p_node->GetAbstractMeta();\r\n\t\tdelete p_node;\r\n\t\tp_node = p_next_node;\r\n\t}\r\n\tm_num_abstract_metapieces=0;\r\n\tmp_abstract_metapiece_list=NULL;\r\n\r\n\r\n\tprintf(\"After deleting CParkManager::mp_abstract_metapiece_list ...\\n\");\t\r\n\tprintf(\"Num CMapListNode's = %d\\n\",Ed::CMapListNode::SGetNumUsedItems());\r\n\tMemView_AnalyzeHeap(Ed::CParkManager::sInstance()->GetGenerator()->GetParkEditorHeap());\r\n\r\n\r\n\t// The park editor heap is now totally empty!\r\n\t// So delete it.\r\n\tmp_generator->DeleteParkEditorHeap();\r\n\t\r\n\t\r\n\t\r\n\tprintf(\"After deleting stuff ...\\n\");\t\r\n\tprintf(\"Num CMapListNode's = %d\\n\",Ed::CMapListNode::SGetNumUsedItems());\r\n\tMemView_AnalyzeHeap(Ed::CParkManager::sInstance()->GetGenerator()->GetParkEditorHeap());\r\n}\r\n*/\r\n\r\n// K: Added type so that DESTROY_ONLY_PIECES can be passed when this function is used to clean\r\n// up the park editor heap for deletion when playing a park.\r\nvoid CParkManager::destroy_concrete_metapieces(CParkGenerator::EDestroyType type)\r\n{\r\n\tParkEd(\"CParkManager::destroy_concrete_metapieces()\");\r\n\r\n\tDbg_Assert(mp_gap_manager);\r\n\tmp_gap_manager->RemoveAllGaps();\r\n\t\r\n\t// Commented these out because destroy_concrete_metapieces gets called via \r\n\t// ScriptFreeUpMemoryForPlayingPark, which must not delete the edited rails.\r\n\t// (Fix to TT2125)\r\n\t//Obj::GetRailEditor()->DestroyRailGeometry();\r\n\t//Obj::GetRailEditor()->DestroyPostGeometry();\r\n\t\r\n\t// remove all concrete metapieces, except locked ones\r\n\tCMapListNode *p_node = mp_concrete_metapiece_list;\r\n\twhile(p_node)\r\n\t{\r\n\t\tCMapListNode *p_next_node = p_node->GetNext();\r\n\t\tDestroyConcreteMeta(p_node->GetConcreteMeta(), mDONT_DESTROY_PIECES_ABOVE);\r\n\t\tp_node = p_next_node;\r\n\t}\r\n\t\r\n\tmp_generator->DestroyAllClonedPieces(type); // if any are left\r\n\t\r\n\tmp_generator->KillRestarts();\t\t// This should have been taken care of by destrying the actual concrete metas, but just to be safe....\r\n}\r\n\r\n\r\n#ifdef __PLAT_NGC__\r\nvoid CParkManager::SwapMapBufferEndianness()\r\n{\r\n\tCompressedMapHeader *p_header = (CompressedMapHeader *)mp_compressed_map_buffer;\r\n\t\r\n\tp_header->mChecksum=_32(p_header->mChecksum);\r\n\tp_header->mSizeInBytes=_16(p_header->mSizeInBytes);\r\n\tp_header->mVersion=_16(p_header->mVersion);\r\n\tp_header->mTheme=_16(p_header->mTheme);\r\n\tp_header->mParkSize=_16(p_header->mParkSize);\r\n\tp_header->mNumMetas=_16(p_header->mNumMetas);\r\n\tp_header->mNumGaps=_16(p_header->mNumGaps);\r\n\tp_header->mTODScript=_32(p_header->mTODScript);\r\n\t\r\n\tuint32 *p_metas=(uint32*)((uint8*)(p_header+1) + FLOOR_MAX_WIDTH * FLOOR_MAX_LENGTH);\r\n\tfor (int i=0; i<p_header->mNumMetas; ++i)\r\n\t{\r\n\t\tp_metas[0]=_32(p_metas[0]);\r\n\t\tp_metas[1]=_32(p_metas[1]);\r\n\t\tp_metas+=2;\r\n\t}\r\n\t\r\n\tCompressedGap *p_gap=(CompressedGap*)p_metas;\r\n\tfor (int i=0; i<p_header->mNumGaps; ++i)\r\n\t{\r\n\t\tp_gap->score=_16(p_gap->score);\r\n\t\tp_gap->mCancelFlags=_32(p_gap->mCancelFlags);\r\n\t\t++p_gap;\r\n\t}\r\n}\r\n#endif\r\n\r\n/*\r\nPark editor map file format:\r\n\r\nHeader\r\n-size\r\n-version\r\n-theme\r\n-X, Z, W, L\r\n-number of metas\r\n\r\nFloor height array, each entry:\r\n-height\r\n-texture\r\n(included risers taken care of by placed metapieces)\r\n\r\nMeta entries:\r\n-10 bits: index\r\n-8 bits: X\r\n-8 bits: Z\r\n-6 bits: padding\r\n-2 bits: rot\r\n-5 bits: Y\r\n-1 bit: padding\r\n(total: 40)\r\n\r\nGap info\r\n\r\nUser-defined stamps\r\n-number contained\r\n\t-source meta\r\n\t-8 bits: X\r\n\t-8 bits: Z\r\n\t-6 bits: Y\r\n\t-2 bits: rot\r\n*/\r\n\r\nvoid CParkManager::write_compressed_map_buffer()\r\n{\r\n\tDbg_Assert(m_state_on);\r\n\tParkEd(\"CParkManager::write_compressed_map_buffer()\");\t\r\n\t//DumpUnwindStack( 20, 0 );\r\n\t\r\n\tif (m_compressed_map_flags & mIS_NEWER_THAN_PARK)\r\n\t\t// we just loaded this park, so don't touch it\r\n\t\treturn;\r\n\t\r\n\tfor (int i=0; i<COMPRESSED_MAP_SIZE; ++i)\r\n\t{\r\n\t\tmp_compressed_map_buffer[i]=0;\r\n\t}\r\n\t\r\n\tScript::CArray *p_save_map_array = Script::GetArray(\"Ed_Save_Map\", Script::ASSERT);\r\n\tuint save_map_array_size = p_save_map_array->GetSize();\r\n\t\r\n\tCompressedMapHeader *p_header = (CompressedMapHeader *) mp_compressed_map_buffer;\r\n\tp_header->mVersion = (VERSION);\r\n\tp_header->mTheme = (m_theme);\r\n\tp_header->mParkSize = (0);\r\n\tp_header->mX = m_park_near_bounds.GetX();\r\n\tp_header->mZ = m_park_near_bounds.GetZ();\r\n\tp_header->mW = m_park_near_bounds.GetW();\r\n\tp_header->mL = m_park_near_bounds.GetL();\r\n\tp_header->mTODScript = Ed::CParkEditor::Instance()->GetTimeOfDayScript();\r\n\tp_header->mMaxPlayers=GetGenerator()->GetMaxPlayers();\r\n\tDbg_MsgAssert(strlen(mp_park_name) < 64,(\"Park name '%s' too long\",mp_park_name));\r\n\tstrcpy(p_header->mParkName,mp_park_name);\r\n\r\n\tCompressedFloorEntry *p_floor_entry = (CompressedFloorEntry *) (p_header + 1);\t\t\r\n\tfor (int i = 0; i < FLOOR_MAX_WIDTH; i++)\r\n\t{\r\n\t\tfor (int j = 0; j < FLOOR_MAX_LENGTH; j++)\r\n\t\t{\r\n\t\t\tp_floor_entry->mHeight = (sint8) m_floor_height_map[i][j].mHeight;\r\n\t\t\tp_floor_entry++;\r\n\t\t}\r\n\t}\r\n\r\n\tuint8 *p_meta_entry = (uint8 *) p_floor_entry;\r\n\r\n\tint num_metas_outputted = 0;\r\n\tCMapListNode *p_meta_node = mp_concrete_metapiece_list;\r\n\twhile(p_meta_node)\r\n\t{\r\n\t\tCConcreteMetaPiece *p_meta = p_meta_node->GetConcreteMeta();\r\n\t\tif (!p_meta->IsRiser() && !p_meta->IsInnerShell() && p_meta->IsInPark())\r\n\t\t{\r\n\t\t\tuint32 *p_meta_entry_first = (uint32 *) p_meta_entry;\r\n\t\t\tuint32 *p_meta_entry_second = (uint32 *) (p_meta_entry + 4);\r\n\r\n\t\t\tGridDims meta_area = p_meta->GetArea();\r\n\t\t\t\r\n\t\t\tuint32 metapiece_index = 0;\r\n\t\t\tuint32 metapiece_name_checksum = p_meta->GetNameChecksum();\r\n\t\t\tfor (; metapiece_index < save_map_array_size; metapiece_index++)\r\n\t\t\t{\t\r\n\t\t\t\tif (p_save_map_array->GetChecksum(metapiece_index) == metapiece_name_checksum)\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (metapiece_index < save_map_array_size)\r\n\t\t\t{\t\t\t\r\n\t\t\t\t*p_meta_entry_first = metapiece_index & 1023;\r\n\t\t\t\t*p_meta_entry_first |= meta_area.GetX()\t<< 10;\r\n\t\t\t\t*p_meta_entry_first |= meta_area.GetZ()\t<< 18;\r\n\t\r\n\t\t\t\t*p_meta_entry_second = p_meta->GetRot() & 3;\r\n\t\t\t\t*p_meta_entry_second |= ((meta_area.GetY() + 16) & 31) << 2;\r\n\t\t\t\t\r\n\t\t\t\t*p_meta_entry_first = (*p_meta_entry_first);\r\n\t\t\t\t*p_meta_entry_second = (*p_meta_entry_second);\r\n\t\t\t\t//Ryan(\"compressed piece: 0x%x 0x%x\\n\", *p_meta_entry_first, *p_meta_entry_second);\r\n\t\t\t\t\r\n\t\t\t\tp_meta_entry += 8;\r\n\t\t\t\tnum_metas_outputted++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_meta_node = p_meta_node->GetNext();\r\n\t}\r\n\r\n\tint buffer_used_size = (uint32) p_meta_entry - (uint32) p_header;\r\n\tDbg_MsgAssert(buffer_used_size <= COMPRESSED_MAP_SIZE, (\"compressed map buffer (%d) needs to be bigger than (%d)\",COMPRESSED_MAP_SIZE,buffer_used_size));\r\n\tp_header->mNumMetas = (num_metas_outputted);\t\r\n\t\r\n\t/* Gap Section */\r\n\r\n\t// count number of gaps\r\n\tCGapManager::GapDescriptor *p_desc_tab[CGapManager::vMAX_GAPS];\r\n\tint num_gaps = 0;\r\n\tint gap;\r\n\tfor (gap = 0; gap < CGapManager::vMAX_GAPS; gap++)\r\n\t{\r\n\t\tint half = 0;\r\n\t\tCGapManager::GapDescriptor *pDesc = mp_gap_manager->GetGapDescriptor(gap, &half);\r\n\t\tif (pDesc && half == 0 && pDesc->numCompleteHalves == 2)\r\n\t\t\tp_desc_tab[num_gaps++] = pDesc;\r\n\t}\r\n\tp_header->mNumGaps = (num_gaps);\r\n\t\r\n\t// write gaps\r\n\tCompressedGap *p_out_gap = (CompressedGap *) p_meta_entry;\r\n\tfor (gap = 0; gap < num_gaps; gap++)\r\n\t{\r\n\t\tp_out_gap->rot = 0;\r\n\t\tfor (int half = 0; half < 2; half++)\r\n\t\t{\r\n\t\t\tp_out_gap->x[half] = p_desc_tab[gap]->loc[half].GetX(); \r\n\t\t\tp_out_gap->y[half] = p_desc_tab[gap]->loc[half].GetY() + (MAX_HEIGHT>>1); \r\n\t\t\tp_out_gap->z[half] = p_desc_tab[gap]->loc[half].GetZ(); \r\n\t\t\tp_out_gap->rot |= p_desc_tab[gap]->rot[half]<<(half*4);\r\n\t\t\t\r\n\t\t\tp_out_gap->extent[half] = (uint8) ((p_desc_tab[gap]->leftExtent[half] & 15) << 4);\r\n\t\t\tp_out_gap->extent[half] |= (uint8) (p_desc_tab[gap]->rightExtent[half] & 15);\r\n\t\t\t//Ryan(\"adding gap at (%d,%d,%d)\\n\", p_out_gap->x[half], p_out_gap->y[half], p_out_gap->z[half]);\r\n\t\t}\r\n\t\tDbg_MsgAssert(strlen(p_desc_tab[gap]->text) <= 31, (\"too many characters in gap name %s\", p_desc_tab[gap]->text));\r\n\t\tstrcpy(p_out_gap->text, p_desc_tab[gap]->text);\r\n\t\tp_out_gap->score = ((uint16) p_desc_tab[gap]->score);\r\n\t\t\r\n\t\tp_out_gap->mCancelFlags=p_desc_tab[gap]->mCancelFlags;\r\n\t\t\r\n\t\tp_out_gap++;\r\n\t}\r\n  \r\n\tbuffer_used_size = (uint32) p_out_gap - (uint32) p_header;\r\n\tDbg_MsgAssert(buffer_used_size <= COMPRESSED_MAP_SIZE, (\"compressed map buffer (%d) needs to be bigger than (%d)\",COMPRESSED_MAP_SIZE,buffer_used_size));\r\n\tp_header->mSizeInBytes = buffer_used_size;\r\n\t\r\n\t/* Flag section */\r\n\r\n\tif (!(m_compressed_map_flags & mIN_SYNC_WITH_PARK) && !(m_compressed_map_flags & mIS_NEWER_THAN_PARK))\r\n\t\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags | mNOT_SAVED_LOCAL);\r\n\t\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags | (mIN_SYNC_WITH_PARK + mIS_VALID));\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags & ~mIS_NEWER_THAN_PARK);\r\n\r\n\r\n\tp_header->mChecksum = (Crc::GenerateCRCCaseSensitive((const char *) mp_compressed_map_buffer + 4, COMPRESSED_MAP_SIZE-4));\r\n\t\r\n\t// XXX\r\n\tParkEd(\"end CParkManager::write_compressed_map_buffer()\");\t\r\n}\r\n\r\n\r\n// Create a minimal compressed map buffer\r\nvoid CParkManager::fake_compressed_map_buffer()\r\n{\r\n\tParkEd(\"CParkManager::fake_compressed_map_buffer()\");\t\r\n\t\r\n//\tScript::CArray *p_save_map_array = Script::GetArray(\"Ed_Save_Map\", Script::ASSERT);\r\n//\tuint save_map_array_size = p_save_map_array->GetSize();\r\n\t\r\n\tsetup_default_dimensions();\r\n\t\r\n\tCompressedMapHeader *p_header = (CompressedMapHeader *) mp_compressed_map_buffer;\r\n\tp_header->mVersion = (VERSION);\r\n\tp_header->mTheme = (m_theme);\r\n\tp_header->mParkSize = (0);\r\n\tp_header->mX = m_park_near_bounds.GetX();\r\n\tp_header->mZ = m_park_near_bounds.GetZ();\r\n\tp_header->mW = m_park_near_bounds.GetW();\r\n\tp_header->mL = m_park_near_bounds.GetL();\r\n\t\r\n\tEd::CParkEditor *p_editor=Ed::CParkEditor::Instance();\r\n\tif (p_editor)\r\n\t{\r\n\t\tp_header->mTODScript = p_editor->GetTimeOfDayScript();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_header->mTODScript=0;\r\n\t}\t\r\n\t\r\n\tp_header->mMaxPlayers=2;\r\n\tstrcpy(p_header->mParkName, \"unnamed park\");\r\n\r\n\tCompressedFloorEntry *p_floor_entry = (CompressedFloorEntry *) (p_header + 1);\t\t\r\n\tfor (int i = 0; i < FLOOR_MAX_WIDTH; i++)\r\n\t{\r\n\t\tfor (int j = 0; j < FLOOR_MAX_LENGTH; j++)\r\n\t\t{\r\n\t\t\tp_floor_entry->mHeight = 0;\t\t// (sint8) m_floor_height_map[i][j].mHeight;\r\n\t\t\tp_floor_entry++;\r\n\t\t}\r\n\t}\r\n\r\n\tuint8 *p_meta_entry = (uint8 *) p_floor_entry;\r\n\tint num_metas_outputted = 0;\r\n\tint buffer_used_size = (uint32) p_meta_entry - (uint32) p_header;\r\n\tp_header->mNumMetas = num_metas_outputted;\t\r\n\tp_header->mChecksum = Crc::GenerateCRCCaseSensitive((const char *) mp_compressed_map_buffer + 4, buffer_used_size - 4);\r\n\tint num_gaps = 0;\r\n\tp_header->mNumGaps = num_gaps;\r\n\t\r\n\t// write gaps\r\n\tCompressedGap *p_out_gap = (CompressedGap *) p_meta_entry;\r\n\tbuffer_used_size = (uint32) p_out_gap - (uint32) p_header;\r\n\tDbg_MsgAssert(buffer_used_size <= COMPRESSED_MAP_SIZE, (\"compressed map buffer (%d) needs to be bigger than (%d)\",COMPRESSED_MAP_SIZE,buffer_used_size));\r\n\tp_header->mSizeInBytes = buffer_used_size;\r\n\t\r\n\t/* Flag section */\r\n\r\n\tif (!(m_compressed_map_flags & mIN_SYNC_WITH_PARK) && !(m_compressed_map_flags & mIS_NEWER_THAN_PARK))\r\n\t\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags | mNOT_SAVED_LOCAL);\r\n\t\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags | (mIN_SYNC_WITH_PARK + mIS_VALID));\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags & ~mIS_NEWER_THAN_PARK);\r\n\t\r\n\t// XXX\r\n\tParkEd(\"end CParkManager::fake_compressed_map_buffer()\");\t\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkManager::read_from_compressed_map_buffer()\r\n{\r\n\tDbg_Assert(m_state_on);\r\n\t// XXX\r\n\tParkEd(\"CParkManager::read_from_compressed_map_buffer()\");\t\r\n\t\r\n\tScript::CArray *p_save_map_array = Script::GetArray(\"Ed_Save_Map\", Script::ASSERT);\r\n\tuint32 dead_piece_checksum = Script::GenerateCRC(\"Sk4Ed_Dead\");\r\n\t\r\n\tDbg_MsgAssert(m_compressed_map_flags & mIS_VALID, (\"compressed map is invalid\"));\r\n\t\r\n\tCompressedMapHeader *p_header = (CompressedMapHeader *) mp_compressed_map_buffer;\r\n\t// make sure latest version\r\n\tif (p_header->mVersion != VERSION)\r\n\t{\r\n\t\tread_from_compressed_map_buffer_old();\r\n\t\tGetGenerator()->SetMaxPlayers(1);\r\n\t\treturn;\r\n\t}\r\n\r\n\tm_park_near_bounds[X] = p_header->mX;\r\n\tm_park_near_bounds[Z] = p_header->mZ;\r\n\tm_park_near_bounds[W] = p_header->mW;\r\n\tm_park_near_bounds[L] = p_header->mL;\r\n\tm_theme = p_header->mTheme;\r\n\tEd::CParkEditor::Instance()->SetTimeOfDayScript(p_header->mTODScript);\r\n\t#ifdef __PLAT_NGC__\r\n\tp_header->mMaxPlayers=2;\r\n\t#endif\r\n\tGetGenerator()->SetMaxPlayers(p_header->mMaxPlayers);\r\n\t// SG: Was setting to the incorrect number (8 when it should have been 2). I think\r\n\t// it is redundant anyway as max players is set elsewhere already\r\n\t//GameNet::Manager::Instance()->SetMaxPlayers(p_header->mMaxPlayers);\r\n\t\r\n\tCompressedFloorEntry *p_floor_entry = (CompressedFloorEntry *) (p_header + 1);\t\t\r\n\tfor (int i = 0; i < FLOOR_MAX_WIDTH; i++)\r\n\t{\r\n\t\tfor (int j = 0; j < FLOOR_MAX_LENGTH; j++)\r\n\t\t{\r\n\t\t\tm_floor_height_map[i][j].mHeight = (int) p_floor_entry->mHeight;\r\n\t\t\tm_floor_height_map[i][j].mEnclosedFloor = 0;\r\n\t\t\tp_floor_entry++;\r\n\t\t}\r\n\t}\r\n\r\n\tuint8 *p_meta_entry = (uint8 *) p_floor_entry;\r\n\tDbg_Printf( \"****** NUM METAS WHILE READING FROM BUFFER : %d\\n\", p_header->mNumMetas );\r\n\tfor (int i = 0; i < p_header->mNumMetas; i++)\r\n\t{\r\n\t\tuint32 *p_meta_entry_first = (uint32 *) p_meta_entry;\r\n\t\tuint32 *p_meta_entry_second = (uint32 *) (p_meta_entry + 4);\r\n\t\tuint32 meta1 = *p_meta_entry_first;\r\n\t\tuint32 meta2 = *p_meta_entry_second;\r\n\t\t\r\n\t\t//Ryan(\"compressed piece: 0x%x 0x%x\\n\", *p_meta_entry_first, *p_meta_entry_second);\r\n\t\t\r\n\t\tuint32 metapiece_index = meta1 & 1023;\r\n\t\tuint32 metapiece_checksum = p_save_map_array->GetChecksum(metapiece_index);\r\n\r\n\t\tif (metapiece_checksum != dead_piece_checksum)\r\n\t\t{\r\n\t\t\tCAbstractMetaPiece *p_source_meta = GetAbstractMeta(metapiece_checksum);\r\n\t\t\tDbg_MsgAssert(p_source_meta, (\"couldn't find abstract meta %s\", Script::FindChecksumName(metapiece_checksum)));\r\n\t\t\t#ifdef __PLAT_NGC__\r\n\t\t\tif (!(p_source_meta->m_flags & CMetaPiece::mNOT_ON_GC))\t\t\t\r\n\t\t\t#endif\r\n\t\t\t{\t\t\t\r\n\t\t\t\tCConcreteMetaPiece *p_meta = CreateConcreteMeta(p_source_meta);\r\n\t\t\t\tGridDims pos;\r\n\t\t\t\tpos[X] = (meta1 >> 10) & 255;\r\n\t\t\t\tpos[Z] = (meta1 >> 18) & 255;\r\n\t\t\t\tpos[Y] = ((meta2 >> 2) & 31) - 16;\r\n\t\t\t\tint rot = meta2 & 3;\r\n\t\t\t\tp_meta->SetRot(Mth::ERot90(rot));\r\n\t\t\t\tAddMetaPieceToPark(pos, p_meta);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tp_meta_entry += 8;\r\n\t}\t\r\n\t\r\n\t/* Gap section */\r\n\t\r\n\tCompressedGap *p_in_gap = (CompressedGap *) p_meta_entry;\r\n\tfor (int g = 0; g < p_header->mNumGaps; g++)\r\n\t{\r\n\t\tCGapManager::GapDescriptor desc;\r\n\t\t\r\n\t\tfor (int half = 0; half < 2; half++)\r\n\t\t{\r\n\t\t\tdesc.loc[half][X] = p_in_gap->x[half]; \r\n\t\t\tdesc.loc[half][Y] = p_in_gap->y[half] - (MAX_HEIGHT>>1); \r\n\t\t\tdesc.loc[half][Z] = p_in_gap->z[half]; \r\n\t\t\tdesc.rot[half] = (p_in_gap->rot>>(half*4)) & 15;\r\n\t\t\t\r\n\t\t\tdesc.leftExtent[half] = (p_in_gap->extent[half]>>4) & 15;\r\n\t\t\tdesc.rightExtent[half] = (p_in_gap->extent[half]) & 15;\r\n\t\t\t//Ryan(\"adding gap at (%d,%d,%d)\\n\", p_in_gap->x[half], p_in_gap->y[half], p_in_gap->z[half]);\r\n\t\t}\r\n\t\tDbg_Assert(strlen(p_in_gap->text) < 32);\r\n\t\tstrcpy(desc.text, p_in_gap->text);\r\n\t\tdesc.score = (int) p_in_gap->score;\r\n\t\tdesc.numCompleteHalves = 2;\r\n\t\tdesc.mCancelFlags=p_in_gap->mCancelFlags;\r\n\t\t\r\n\t\tAddGap(desc);\r\n\t\t\r\n\t\tp_in_gap++;\r\n\t}\r\n\t\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags | mIN_SYNC_WITH_PARK);\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags & ~mIS_NEWER_THAN_PARK);\r\n\t\r\n\t// XXX\r\n\tParkEd(\"end CParkManager::read_from_compressed_map_buffer()\");\t\r\n}\r\n\r\n\r\n\r\nvoid CParkManager::read_from_compressed_map_buffer_old()\r\n{\r\n\tDbg_Assert(m_state_on);\r\n\t// XXX\r\n\tParkEd(\"CParkManager::read_from_compressed_map_buffer()\");\t\r\n\t\r\n\tScript::CArray *p_save_map_array = Script::GetArray(\"Ed_Save_Map\", Script::ASSERT);\r\n\tuint32 dead_piece_checksum = Script::GenerateCRC(\"Sk4Ed_Dead\");\r\n\t\r\n\tDbg_MsgAssert(m_compressed_map_flags & mIS_VALID, (\"compressed map is invalid\"));\r\n\t\r\n\tCompressedMapHeader *p_header = (CompressedMapHeader *) mp_compressed_map_buffer;\r\n\r\n\t// make sure proper version\r\n\tDbg_MsgAssert((p_header->mVersion) == VERSION-1, (\"can't read park with this version #: %d\", (p_header->mVersion)));\r\n\t\r\n\t// XXX\r\n//\tfor (int zzz = 0; zzz < 16; zzz++)\r\n//\t\tprintf(\"OUT OF DATE PARK FORMAT -- SAVE NOW. OUT OF DATE PARK FORMAT -- SAVE NOW. OUT OF DATE PARK FORMAT -- SAVE NOW.\\n\");\r\n\r\n\tm_park_near_bounds[X] = p_header->mX;\r\n\tm_park_near_bounds[Z] = p_header->mZ;\r\n\tm_park_near_bounds[W] = p_header->mW;\r\n\tm_park_near_bounds[L] = p_header->mL;\r\n\tm_theme = (p_header->mTheme);\r\n\tEd::CParkEditor::Instance()->SetTimeOfDayScript(p_header->mTODScript);\r\n\t\r\n\tGetGenerator()->SetMaxPlayers(p_header->mMaxPlayers);\r\n\t// SG: Was setting to the incorrect number (8 when it should have been 2). I think\r\n\t// it is redundant anyway as max players is set elsewhere already\r\n\t//GameNet::Manager::Instance()->SetMaxPlayers(p_header->mMaxPlayers);\r\n\t\r\n\tCompressedFloorEntry *p_floor_entry = (CompressedFloorEntry *) (p_header + 1);\t\t\r\n\tfor (int i = 0; i < FLOOR_MAX_WIDTH; i++)\r\n\t{\r\n\t\tfor (int j = 0; j < FLOOR_MAX_LENGTH; j++)\r\n\t\t{\r\n\t\t\tm_floor_height_map[i][j].mHeight = (int) p_floor_entry->mHeight;\r\n\t\t\tm_floor_height_map[i][j].mEnclosedFloor = 0;\r\n\t\t\tp_floor_entry++;\r\n\t\t}\r\n\t}\r\n\r\n\tuint8 *p_meta_entry = (uint8 *) p_floor_entry;\r\n\tDbg_Printf( \"****** NUM METAS WHILE READING FROM BUFFER : %d\\n\", p_header->mNumMetas );\r\n\tfor (int i = 0; i < (p_header->mNumMetas); i++)\r\n\t{\r\n\t\tuint32 *p_meta_entry_first = (uint32 *) p_meta_entry;\r\n\t\tuint32 *p_meta_entry_second = (uint32 *) (p_meta_entry + 4);\r\n\t\tuint32 meta1 = (*p_meta_entry_first);\r\n\t\tuint32 meta2 = (*p_meta_entry_second);\r\n\t\t\r\n\t\t//Ryan(\"compressed piece: 0x%x 0x%x\\n\", *p_meta_entry_first, *p_meta_entry_second);\r\n\t\t\r\n\t\tuint32 metapiece_index = meta1 & 1023;\r\n\t\tuint32 metapiece_checksum = p_save_map_array->GetChecksum(metapiece_index);\r\n\r\n\t\tif (metapiece_checksum != dead_piece_checksum)\r\n\t\t{\r\n\t\t\tCAbstractMetaPiece *p_source_meta = GetAbstractMeta(metapiece_checksum);\r\n\t\t\tDbg_MsgAssert(p_source_meta, (\"couldn't find abstract meta %s\", Script::FindChecksumName(metapiece_checksum)));\r\n\t\t\t#ifdef __PLAT_NGC__\r\n\t\t\tif (!(p_source_meta->m_flags & CMetaPiece::mNOT_ON_GC))\t\t\t\r\n\t\t\t#endif\r\n\t\t\t{\t\t\t\r\n\t\t\t\tCConcreteMetaPiece *p_meta = CreateConcreteMeta(p_source_meta);\r\n\t\t\t\tGridDims pos;\r\n\t\t\t\tpos[X] = (meta1 >> 10) & 255;\r\n\t\t\t\tpos[Z] = (meta1 >> 18) & 255;\r\n\t\t\t\tpos[Y] = ((meta2 >> 2) & 31) - 16;\r\n\t\t\t\tint rot = meta2 & 3;\r\n\t\t\t\tp_meta->SetRot(Mth::ERot90(rot));\r\n\t\t\t\tAddMetaPieceToPark(pos, p_meta);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tp_meta_entry += 8;\r\n\t}\t\r\n\t\r\n\t// Gap section\r\n\t\r\n\tCompressedGapOld *p_in_gap = (CompressedGapOld *) p_meta_entry;\r\n\tfor (int g = 0; g < (p_header->mNumGaps); g++)\r\n\t{\r\n\t\tCGapManager::GapDescriptor desc;\r\n\t\t\r\n\t\tfor (int half = 0; half < 2; half++)\r\n\t\t{\r\n\t\t\tdesc.loc[half][X] = p_in_gap->x[half]; \r\n\t\t\tdesc.loc[half][Y] = p_in_gap->y[half] - (MAX_HEIGHT>>1); \r\n\t\t\tdesc.loc[half][Z] = p_in_gap->z[half]; \r\n\t\t\tdesc.rot[half] = (p_in_gap->rot>>(half*4)) & 15;\r\n\t\t\t\r\n\t\t\tdesc.leftExtent[half] = (p_in_gap->extent[half]>>4) & 15;\r\n\t\t\tdesc.rightExtent[half] = (p_in_gap->extent[half]) & 15;\r\n\t\t\t//Ryan(\"adding gap at (%d,%d,%d)\\n\", p_in_gap->x[half], p_in_gap->y[half], p_in_gap->z[half]);\r\n\t\t}\r\n\t\tDbg_Assert(strlen(p_in_gap->text) < 32);\r\n\t\tstrcpy(desc.text, p_in_gap->text);\r\n\t\tdesc.score = (int) (p_in_gap->score);\r\n\t\tdesc.numCompleteHalves = 2;\r\n\t\t\r\n\t\tAddGap(desc);\r\n\t\t\r\n\t\tp_in_gap++;\r\n\t}\r\n\t\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags | mIN_SYNC_WITH_PARK);\r\n\tm_compressed_map_flags = ECompressedMapFlags(m_compressed_map_flags & ~mIS_NEWER_THAN_PARK);\r\n\t\r\n\t// XXX\r\n\tParkEd(\"end CParkManager::read_from_compressed_map_buffer_old()\");\t\r\n}\r\n\r\nvoid\tCParkManager::setup_default_dimensions()\r\n{\r\n\tint default_inner_dim = Script::GetInt(\"ed_default_inner_dim\", Script::ASSERT);\r\n\tDbg_Assert(default_inner_dim <= MAX_WIDTH && default_inner_dim <= MAX_LENGTH);\r\n\r\n\tm_park_far_bounds.SetXYZ(1, -4, 1);\r\n\tm_park_far_bounds.SetWHL(MAX_WIDTH, 8, MAX_LENGTH);\r\n\tm_park_near_bounds.SetXYZ(1 + (MAX_WIDTH - default_inner_dim) / 2, -4, 1 + (MAX_LENGTH - default_inner_dim) / 2);\r\n\tm_park_near_bounds.SetWHL(default_inner_dim, 8, default_inner_dim);\r\n}\r\n\r\n\r\n\r\nvoid CParkManager::setup_road_mask()\r\n{\r\n\t/*\r\n\t\tThe first four entries in m_road_mask_tab will be set up in RebuildInnerShell()\r\n\t*/\r\n\t\r\n\tScript::CArray *p_road_mask_array = Script::GetArray(\"Ed_Roadmask\", Script::ASSERT);\r\n\tm_road_mask_tab_size = p_road_mask_array->GetSize();\r\n\tfor (uint i = 4; i < 4 + m_road_mask_tab_size; i++)\r\n\t{\r\n\t\tDbg_Assert(i < NUM_ROAD_PIECES);\r\n\t\tScript::CArray *p_entry = p_road_mask_array->GetArray(i);\r\n\r\n\t\tm_road_mask_tab[i][X] = p_entry->GetInt(0);\r\n\t\tm_road_mask_tab[i][Z] = p_entry->GetInt(1);\r\n\t\tm_road_mask_tab[i][W] = p_entry->GetInt(2);\r\n\t\tm_road_mask_tab[i][L] = p_entry->GetInt(3);\r\n\t\tm_road_mask_tab[i][Y] = 0;\r\n\t\tm_road_mask_tab[i].MakeInfinitelyHigh();\r\n\t}\r\n\r\n\tm_road_mask_tab_size += 4;\r\n}\r\n\r\n\r\nvoid CParkManager::setup_lighting()\r\n{\r\n\t\r\n\t\r\n\tScript::CArray *pThemeArray = Script::GetArray(\"Editor_Light_Info\");\r\n//\tScript::CArray *pSizeArray = pThemeArray->GetArray(m_currentThemeIndex);\r\n//\tScript::CScriptStructure *pLightInfo = pSizeArray->GetStructure(m_currentShellSizeIndex);\r\n\tScript::CArray *pSizeArray = pThemeArray->GetArray(0);\r\n\tScript::CScriptStructure *pLightInfo = pSizeArray->GetStructure(0);\r\n\r\n\tfloat amb_const;\r\n\tpLightInfo->GetFloat(\"ambient_const\", &amb_const, true);\r\n\tMth::Vector ambient_rgb;\r\n\tpLightInfo->GetVector(\"ambient_rgb\", &ambient_rgb, true);\r\n\tfloat falloff_const;\r\n\tpLightInfo->GetFloat(\"falloff_const\", &falloff_const, true);\r\n\tMth::Vector falloff_rgb;\r\n\tpLightInfo->GetVector(\"falloff_rgb\", &falloff_rgb, true);\r\n\tfloat cursor_ambience;\r\n\tpLightInfo->GetFloat(\"cursor_ambience\", &cursor_ambience, true);\r\n\t\r\n\t\r\n\tScript::CArray *pLightArray;\r\n\tpLightInfo->GetArray(\"pos\", &pLightArray, true);\r\n\r\n\tmp_generator->SetLightProps(pLightArray->GetSize(), \r\n\t\t\t\t\t\t\tamb_const * ambient_rgb.GetX(), amb_const * ambient_rgb.GetY(), amb_const * ambient_rgb.GetZ(), \r\n\t\t\t\t\t\t\tfalloff_const * falloff_rgb.GetX(), falloff_const * falloff_rgb.GetY(), falloff_const * falloff_rgb.GetZ(),\r\n\t\t\t\t\t\t\tcursor_ambience);\r\n\r\n\tfor (int i = 0; i < (int)pLightArray->GetSize(); i++)\r\n\t{\r\n\t\tScript::CVector *pInPos = pLightArray->GetVector(i);\r\n\t\tMth::Vector outPos;\r\n\t\toutPos.Set(pInPos->mX * CParkGenerator::CELL_WIDTH,\r\n\t\t\t\t   pInPos->mY * CParkGenerator::CELL_HEIGHT,\r\n\t\t\t\t   pInPos->mZ * CParkGenerator::CELL_LENGTH);\r\n\t\tmp_generator->SetLight(outPos, i);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/ParkEditor2/EdMap.h",
    "content": "#ifndef __SK_PARKEDITOR2_EDMAP_H\r\n#define __SK_PARKEDITOR2_EDMAP_H\r\n\r\n#include <sk/ParkEditor2/ParkGen.h>\r\n#include <sk/ParkEditor2/GapManager.h>\r\n\r\n#ifndef __SYS_MEM_POOLABLE_H\r\n#include <sys/mem/poolable.h>\r\n#endif\r\n\r\n//#ifdef\t__PLAT_NGPS__\r\n#define USE_BUILD_LIST\r\n//#endif\r\n\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n}\r\n\r\n\r\nnamespace Ed\r\n{\r\n\r\nclass CPiece;\r\nclass CSourcePiece;\r\nclass CClonedPiece;\r\nclass CParkGenerator;\r\nclass CConcreteMetaPiece;\r\nclass CAbstractMetaPiece;\r\n\r\n/*\r\n\tDescribes how to incorporate a CPiece or hardcoded metapiece into a CMetaPiece.\r\n\t\r\n\tThe position is relative to the NW corner of the piece, in its current rotation.\r\n\t\r\n\tLikewise, the rotation value includes the rotation of the whole metapiece.\r\n*/\r\nstruct SMetaDescriptor\r\n{\r\n\tuint8\t\t\t\t\t\tmX;\r\n\tuint8\t\t\t\t\t\tmY;\r\n\tuint8\t\t\t\t\t\tmZ;\r\n\tuint8\t\t\t\t\t\tmRot;\r\n\tuint8\t\t\t\t\t\tmRiser; // true if a riser\r\n\t\r\n\t/* \r\n\t\tThe piece pointer is active within a concrete metapiece, the name in an abstract one.\r\n\t\tIn the latter case, the name refers to a metapiece.\r\n\t*/\r\n\tunion\r\n\t{\r\n\t\tuint32\t\t\t\t\tmPieceName;\r\n\t\tCPiece *\t\t\t\tmpPiece;\r\n\t};\r\n};\r\n\r\n\r\n\r\n\r\n/*\r\n\tWhat is a metapiece?\r\n\t\r\n\t-Wraps a group of cloned pieces that are in the park (or about to be)\r\n\t\r\n\t-Wraps a group of cloned pieces that make up the cursor. Contains extra position,\r\n\t\trotation info.\r\n\t\r\n\t-Wraps a group of cloned pieces that make up a menu item. Refers to a 3D element.\r\n\t\t\r\n\t-Wraps a descriptor table that tells how to build a full metapiece.\r\n\t\r\n\tRules:\r\n\t-If metapiece is in world, positions of contained pieces are in world\r\n\t-Otherwise, positions are relative to center bottom of metapiece\r\n\t\r\n\tOther notes:\r\n\t-An abstract user-created metapiece can contain hard-coded metapieces\r\n\t-A concrete metapiece cannot\r\n*/\r\nclass CMetaPiece\r\n{\r\n\tfriend class CParkManager;\r\n\r\npublic:\r\n\r\n\tenum EFlags\r\n\t{\r\n\t\tmCONCRETE_META\t\t\t= (1<<0),\r\n\t\tmABSTRACT_META\t\t\t= (1<<1),\r\n\r\n\t\tmIN_PARK\t\t\t\t= (1<<2),\r\n\r\n\t\tmIS_RISER\t\t\t\t= (1<<3),\r\n\t\tmMARK_FOR_KILL\t\t\t= (1<<4),\r\n\t\tmMARK_AS_SLID\t\t\t= (1<<5),\r\n\r\n\t\tmUSER_CREATED\t\t\t= (1<<6),\r\n\t\tmSINGULAR\t\t\t\t= (1<<7),\r\n\r\n\t\tmINNER_SHELL\t\t\t= (1<<8),\r\n\r\n\t\tmLOCK_AGAINST_DELETE\t= (1<<9),\r\n\t\tmNO_RAILS\t\t\t\t= (1<<10),\r\n\r\n\t\tmGAP_PLACEMENT\t\t\t= (1<<11),\r\n\t\tmGAP_ATTACHED\t\t\t= (1<<12),\r\n\r\n\t\tmNOT_ON_GC\t\t\t\t= (1<<13), // this metapiece does not appear on Gamecube\r\n\r\n\t\tmCONTAINS_RISERS\t\t= (1<<14),\r\n\t\tmAREA_SELECTION\t\t\t= (1<<15),\r\n\t\t\r\n\t\tmRAIL_PLACEMENT\t\t\t= (1<<16),\r\n\t};\r\n\r\n\tCConcreteMetaPiece *\t\tCastToConcreteMeta();\r\n\tCAbstractMetaPiece *\t\tCastToAbstractMeta();\r\n\r\n\tbool\t\t\t\t\t\tIsRestartOrFlag();\r\n\tbool\t\t\t\t\t\tIsCompletelyWithinArea(const GridDims &area);\r\n\t\r\n\t\r\n\tvirtual CPiece *\t\t\tGetContainedPiece(int index) = 0;\r\n\r\n\tvoid\t\t\t\t\t\tSetRot(Mth::ERot90 rot);\r\n\tMth::Vector \t\t\t\tGetRelativePosOfContainedPiece(int index);\r\n\tvoid \t\t\t\t\t\tBuildElement3dSectorsArray(Script::CArray *pArray);\r\n\r\n\t/*\r\n\t\tReturns cell dimensions occupied by metapiece (post-rotation). Coordinates in GridDims structure\r\n\t\tare not valid in an abstract metapiece, only in a concrete one that's in the park.\r\n\t*/\r\n\tconst GridDims &\t\t\tGetArea() {return m_cell_area;}\r\n\tuint32\t\t\t\t\t\tGetNameChecksum() {return m_name_checksum;}\r\n\t// Returns rotation of whole metapiece\r\n\tMth::ERot90\t\t\t\t\tGetRot() {return Mth::ERot90(m_rot);}\r\n\r\n\tbool\t\t\t\t\t\tIsInPark() {return m_flags & mIN_PARK;}\r\n\t// Returns true if the WHOLE metapiece is a riser\r\n\tbool \t\t\t\t\t\tIsRiser() {return m_flags & mIS_RISER;}\r\n\tbool\t\t\t\t\t\tIsInnerShell() {return m_flags & mINNER_SHELL;}\r\n\tbool\t\t\t\t\t\tIsSingular() {return m_flags & mSINGULAR;}\r\n\tbool \t\t\t\t\t\tNoRails() {return m_flags & mNO_RAILS;}\r\n\tbool\t\t\t\t\t\tIsGapPlacement() {return m_flags & mGAP_PLACEMENT;}\r\n\tbool\t\t\t\t\t\tIsAreaSelection() {return m_flags & mAREA_SELECTION;}\r\n\tbool\t\t\t\t\t\tIsRailPlacement() {return m_flags & mRAIL_PLACEMENT;}\r\n\tbool \t\t\t\t\t\tIsConcrete() {return m_flags & mCONCRETE_META;}\r\n\r\n\tvoid\t\t\t\t\t\tMarkAsInnerShell() {m_flags = EFlags(m_flags | mINNER_SHELL);}\r\n\tvoid\t\t\t\t\t\tMarkLocked() {m_flags = EFlags(m_flags | mLOCK_AGAINST_DELETE);}\r\n\tvoid\t\t\t\t\t\tMarkUnlocked() {m_flags = EFlags(m_flags & ~mLOCK_AGAINST_DELETE);}\r\n\t\r\n\r\nprotected:\r\n\t\t\t\t\t\t\t\tCMetaPiece();\r\n\tvirtual\t\t\t\t\t\t~CMetaPiece();\r\n\r\n\tvoid\t\t\t\t\t\tinitialize_desc_table(int numEntries);\r\n\tSMetaDescriptor &\t\t\tget_desc_at_index(int i);\r\n\r\n\t/*\r\n\t\tAdds a CPiece to the metapiece. If the metapiece is abstract, the CPiece must be a CSourcePiece. If the metapiece is\r\n\t\tconcrete, the CPiece must be a CClonedPiece. \r\n\t\t\r\n\t\tpPos specifies the position of the pPiece relative to the northwest corner of the metapiece.\r\n\t\t\r\n\t\tisRiser set if pPiece is meant to act as a riser.\r\n\t*/\r\n\tvirtual\tvoid\t\t\t\tadd_piece(CPiece *pPiece, GridDims *pPos, Mth::ERot90 rot = Mth::ROT_0, bool isRiser = false) = 0;\r\n\t\r\n\tvoid\t\t\t\t\t\tset_flag(EFlags flag) {m_flags = EFlags(m_flags | flag);}\r\n\tvoid\t\t\t\t\t\tclear_flag(EFlags flag) {m_flags = EFlags(m_flags & ~flag);}\r\n\t\r\n\t// takes into account current rotation\r\n\tGridDims\t\t\t\t\tm_cell_area;\t\t\t//  6 ( 8) + 2\r\n\t\t\t\t\t\t\t\t\t\r\n\tEFlags \t\t\t\t\t\tm_flags;   \t\t\t\t// \t4 (only uses 17 bits, grr)\r\n\tint\t\t\t\t\t\t\tm_rot;\t\t\t\t\t//  4 (only uses  2 bits, grr)   +4 (if combined)\r\n\t\r\n\t/* \r\n\t\t-See comment above SMetaDescriptor declaration for details on what descriptors are\r\n\t\t-Most metapieces will only contain one piece, so mp_additional_desc_tab is only used if there are more\r\n\t*/\r\n\r\n\tenum\r\n\t{\r\n\t\tUSUAL_NUM_DESCRIPTORS =\t2\r\n\t};\r\n\t\r\n\tSMetaDescriptor \t\t\tm_first_desc_tab[USUAL_NUM_DESCRIPTORS];  //  9 (12), + 9 (12)\t  + 6\r\n\tSMetaDescriptor *\t\t\tmp_additional_desc_tab;\t  \t\t\t\t  //  4\t\r\n\tuint\t\t\t\t\t\tm_total_entries;\t\t\t\t\t\t  //  2 (4) \t\t\t  + 2\r\n\tuint \t\t\t\t\t\tm_num_used_entries;\t\t\t\t\t\t  //  2 (4) \t\t\t  +2\r\n\t\r\n\tuint32\t\t\t\t\t\tm_name_checksum; \t\t\t\t\t\t  //  4\r\n};\r\n\r\n// Total \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\r\n\r\n\r\nclass CConcreteMetaPiece : public CMetaPiece\r\n{\r\n\tfriend class CParkManager;\r\n\r\npublic:\r\n\t\r\n\tint\t\t\t\t\t\t\tCountContainedPieces();\r\n\tCPiece *\t\t\t\t\tGetContainedPiece(int index);\r\n\r\n\tvoid\t\t\t\t\t\tSetSoftRot(Mth::Vector pos, float rot);\r\n\r\n\tvoid\t\t\t\t\t\tHighlight(bool on, bool gapHighlight = false);\r\n\tvoid\t\t\t\t\t\tSetVisibility(bool visible);\r\n\r\nprotected:\r\n\t\r\n\t\t\t\t\t\t\t\tCConcreteMetaPiece();\r\n\t\r\n\tvoid\t\t\t\t\t\tlock();\r\n\tvoid\t\t\t\t\t\tget_max_min_world_coords(Mth::Vector &max, Mth::Vector &min);\r\n\t\r\n\tbool \t\t\t\t\t\ttest_for_conflict(GridDims area, bool excludeRisers);\r\n\t\r\n\t// see comments with original declaration\r\n\tvirtual void\t\t\t\tadd_piece(CPiece *pPiece, GridDims *pPos, Mth::ERot90 rot = Mth::ROT_0, bool isRiser = false);\r\n};\r\n\r\n\r\n\r\n\r\nclass CAbstractMetaPiece : public CMetaPiece\r\n{\r\n\tfriend class CParkManager;\r\n\r\npublic:\r\nprotected:\r\n\t\t\t\t\t\t\t\tCAbstractMetaPiece();\r\n\r\n\tCPiece *\t\t\t\t\tGetContainedPiece(int index);\r\n\t\r\n\t// see comments with original declaration\r\n\tvirtual void\t\t\t\tadd_piece(CPiece *pPiece, GridDims *pPos, Mth::ERot90 rot = Mth::ROT_0, bool isRiser = false);\r\n\tvoid \t\t\t\t\t\tadd_piece_dumb(CAbstractMetaPiece *pMeta, GridDims *pPos, Mth::ERot90 rot, bool isRiser);\r\n\r\n\tSMetaDescriptor \t\t\tget_desc_with_expansion(int index);\r\n\tint \t\t\t\t\t\tcount_descriptors_expanded();\r\n};\r\n\r\n\r\n\r\n\r\nclass CMapListNode : public Mem::CPoolable<CMapListNode>\r\n{\r\n\tfriend class CParkManager;\r\n\tfriend class CCursor;\r\n\r\npublic:\r\n\tCMetaPiece *\t\t\t\tGetMeta();\r\n\tCConcreteMetaPiece *\t\tGetConcreteMeta() {return GetMeta()->CastToConcreteMeta();}\r\n\tCAbstractMetaPiece *\t\tGetAbstractMeta() {return GetMeta()->CastToAbstractMeta();}\r\n\tCMapListNode *\t\t\t\tGetNext() {return mp_next;}\r\n\tvoid\t\t\t\t\t\tDestroyList();\r\n\tvoid\t\t\t\t\t\tVerifyIntegrity();\r\n\r\n\tint\t\t\t\t\t\t\tmSlideAmount;\r\n\r\nprivate:\r\n\tCMetaPiece *\t\t\t\tmp_meta;\r\n\tCMapListNode *\t\t\t\tmp_next;\r\n};\r\n\r\n\r\n\r\n\r\nclass CMapListTemp\r\n{\r\npublic:\r\n\tCMapListTemp(CMapListNode *p_list);\r\n\t~CMapListTemp();\r\n\t\r\n\tbool\t\t\t\t\t\tIsEmpty() {return (mp_list == NULL);}\r\n\tbool\t\t\t\t\t\tIsSingular() {return (mp_list->GetNext() == NULL);}\r\n\tCMapListNode *\t\t\t\tGetList();\r\n\tvoid\t\t\t\t\t\tPrintContents();\r\n\r\nprivate:\r\n\r\n\tCMapListNode *\t\t\t\tmp_list;\r\n};\r\n\r\n\r\n\r\n\r\nclass CParkManager\r\n{\r\n\tDeclareSingletonClass( CParkManager );\r\n\r\npublic:\r\n\r\n\tenum\r\n\t{\r\n\t\tMAX_WIDTH =\t\t\t\t56,\r\n\t\tMAX_LENGTH =\t\t\t56,\r\n\t\tMAX_HEIGHT =\t\t\t16,\r\n\t\t/* \r\n\t\t\tThese next two account for the border around the whole park. Riser pieces must be added when the user\r\n\t\t\tdigs a hole at the edge of the park.\r\n\t\t*/\r\n\t\tFLOOR_MAX_WIDTH =\t\tMAX_WIDTH + 2,\r\n\t\tFLOOR_MAX_LENGTH =\t\tMAX_LENGTH + 2,\r\n\r\n\t\tCOMPRESSED_MAP_SIZE\t\t= 15000,\t\t// (Mick) it can acutally be bigger than this, but I've made it this size so network code won't crash\r\n\t};\r\n\r\n\t\t\t\t\t\t\t\tCParkManager();\r\n\t\t\t\t\t\t\t\t~CParkManager();\r\n\r\n\t/* ======== General Functions ======== */\r\n\r\n\tCParkGenerator *\t\t\tGetGenerator() {return mp_generator;}\t\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\t\t\tInitialize();\r\n\tbool\t\t\t\t\t\tIsInitialized() {return m_state_on;}\r\n\tvoid\t\t\t\t\t\tAccessDisk(bool save, int fileSlot);\r\n\tvoid\t\t\t\t\t\tDestroy(CParkGenerator::EDestroyType type);\r\n\r\n\tfloat\t\t\t\t\t\tGetClipboardProportionUsed();\r\n\tvoid\t\t\t\t\t\tWriteCompressedMapBuffer();\r\n\tuint8*\t\t\t\t\t\tGetCompressedMapBuffer(bool markSaved = false);\r\n\tvoid\t\t\t\t\t\tSetCompressedMapBuffer(uint8* src_buffer, bool markNotSaved = false);\r\n\tbool\t\t\t\t\t\tIsMapSavedLocally();\r\n\tvoid\t\t\t\t\t\tWriteIntoStructure(Script::CStruct *p_struct);\r\n\t#ifdef __PLAT_NGC__\r\n\tvoid \t\t\t\t\t\tReadFromStructure(Script::CStruct *p_struct, bool do_post_mem_card_load=true, bool preMadePark=false);\r\n\t#else\r\n\tvoid\t\t\t\t\t\tReadFromStructure(Script::CStruct *p_struct, bool do_post_mem_card_load=true);\r\n\t#endif\r\n\t\r\n\tint\t\t\t\t\t\t\tGetTheme();\r\n\tvoid\t\t\t\t\t\tSetTheme(int theme);\r\n\tuint32\t\t\t\t\t\tGetShellSceneID();\r\n\tconst char *\t\t\t\tGetParkName();\r\n\tvoid\t\t\t\t\t\tSetParkName(const char *pName);\r\n\tuint32\t\t\t\t\t\tGetParkChecksum();\r\n\tint\t\t\t\t\t\t\tGetCompressedParkWidth();\r\n\tint\t\t\t\t\t\t\tGetCompressedParkLength();\r\n\r\n\t/* ======== Rebuild functions ======== */\r\n\r\n\tvoid\t\t\t\t\t\tRebuildWholePark(bool clearPark);\t\r\n\tbool\t\t\t\t\t\tRebuildFloor(bool firstTestMemory = false);\r\n\tvoid\t\t\t\t\t\tRebuildNodeArray();\r\n\tvoid\t\t\t\t\t\tRebuildInnerShell(GridDims newNearBounds);\r\n\t\r\n\t/* ======== Abstract metapiece functions ======== */\r\n\t\r\n\tCAbstractMetaPiece *\t\tGetAbstractMeta(uint32 type, int *pRetIndex = NULL);\r\n\tCAbstractMetaPiece *\t\tGetAbstractMetaByIndex(int index);\r\n\t\r\n\t/* ======== Concrete metapiece functions ======== */\r\n\t\r\n\tenum EDestroyFlags\r\n\t{\r\n\t\tmDONT_DESTROY_PIECES_ABOVE\t\t= 0,\r\n\t\tmDESTROY_PIECES_ABOVE\t\t\t= (1<<0),\r\n\t\tmEXCLUDE_RISERS\t\t\t\t\t= (1<<1),\r\n\t\tmEXCLUDE_PIECES_MARKED_AS_SLID\t= (1<<2),\r\n\t};\r\n\t\r\n\tCConcreteMetaPiece *\t\tCreateConcreteMeta(CAbstractMetaPiece *pSource, bool isSoft = false);\r\n\tvoid\t\t\t\t\t\tDestroyConcreteMeta(CConcreteMetaPiece *pMeta, EDestroyFlags flags);\r\n\tuint32\t\t\t\t\t\tDestroyMetasInArea(GridDims area, EDestroyFlags flags);\r\n\tbool\t\t\t\t\t\tDestroyMetasInArea(GridDims area, bool doNotDestroyRestartsOrFlags=false, bool onlyIfWithinArea=false);\r\n\tvoid\t\t\t\t\t\tHighlightMetasInArea(GridDims area, bool on);\r\n\t//GridDims\t\t\t\t\tFindBoundingArea(GridDims area);\r\n\tvoid\t\t\t\t\t\tAddMetaPieceToPark(GridDims pos, CConcreteMetaPiece *pPiece);\r\n\tCConcreteMetaPiece *\t\tRelocateMetaPiece(CConcreteMetaPiece *pMeta, int changeX, int changeY, int changeZ);\r\n\tCMapListNode *\t\t\t\tGetMetaPiecesAt(GridDims dims, Mth::ERot90 rot = Mth::ROT_0, CAbstractMetaPiece *pPiece = NULL, bool excludeRisers = false);\r\n\tCMapListNode *\t\t\t\tGetAreaMetaPieces(GridDims dims);\r\n\tCMapListNode *\t\t\t\tGetMapListNode(int x, int z);\r\n\tCMapListNode *\t\t\t\tGetConcreteMetaList() {return mp_concrete_metapiece_list;}\r\n\tint \t\t\t\t\t\tGetFloorHeight(int x, int z);\r\n\t\r\n\t\r\n\tbool \t\t\t\t\t\tAreMetasOutsideBounds(GridDims new_dims);\r\n\tbool \t\t\t\t\t\tEnoughMemoryToResize(GridDims new_dims);\r\n\r\n\tint \t\t\t\t\t\tCountGeneralMetas() {return m_num_general_concrete_metapieces;}\r\n\tint\t\t\t\t\t\t\tGetDMAPieceCount() {return m_dma_piece_count;}\r\n\t\r\n\t\r\n\t/* ======== Floor height functions ======== */\r\n\t\r\n\tint\t\t\t\t\t\t\tGetFloorHeight(GridDims dims, bool *pRetUniformHeight = NULL);\r\n\t#if 0\r\n\tvoid\t\t\t\t\t\tSetFloorHeight(GridDims area, int newHeight, bool justDropHighest);\r\n\t#endif\r\n\tvoid\t\t\t\t\t\tResetFloorHeights(GridDims area);\r\n\t\r\n\tbool\t\t\t\t\t\tSlideColumn(GridDims area, int bottom, int top, bool up, bool uneven);\r\n\tvoid\t\t\t\t\t\tUndoSlideColumn();\r\n\tbool\t\t\t\t\t\tChangeFloorHeight(GridDims dims, int dir);\r\n\r\n\t/* ======== Coordinate info functions ======== */\r\n\t\r\n\tconst GridDims &\t\t\tGetParkNearBounds() {return m_park_near_bounds;}\r\n\tconst GridDims &\t\t\tGetParkFarBounds() {return m_park_far_bounds;}\r\n\tMth::Vector\t\t\t\t\tGridCoordinatesToWorld(const GridDims &cellDims, Mth::Vector *pRetDims = NULL);\r\n\r\n\tstatic CParkManager *\t\tsInstance();\r\n\t\r\n\t/* ======== Piece set (group, category) functions ======== */\r\n\t\r\n\tclass CPieceEntry\r\n\t{\r\n\tpublic:\r\n\t\tuint32\t\t\t\t\t\t\t\t\tmNameCrc;\r\n\t\tconst char *\t\t\t\t\t\t\tmpName;\r\n\t};\r\n\t\r\n\tclass CPieceSet\r\n\t{\r\n\tpublic:\r\n\t\tenum \r\n\t\t{\r\n\t\t\tMAX_ENTRIES =\t\t\t\t\t\t40,\r\n\t\t};\r\n\t\t\r\n\t\tuint32\t\t\t\t\t\t\t\t\tmNameCrc;\r\n\t\tconst char *\t\t\t\t\t\t\tmpName;\r\n\t\tCPieceEntry \t\t\t\t\t\t\tmEntryTab[MAX_ENTRIES];\r\n\t\tint\t\t\t\t\t\t\t\t\t\tmTotalEntries;\r\n\t\tint\t\t\t\t\t\t\t\t\t\tmSelectedEntry;\r\n\t\tchar\t\t\t\t\t\t\t\t\tmVisible;\r\n\t\tchar\t\t\t\t\t\t\t\t\tmIsClipboardSet;\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n\t\tMAX_SETS =\t\t\t\t\t\t\t\t40,\r\n\t};\r\n\r\n\tCPieceSet &\t\t\t\t\tGetPieceSet(int setNumber, int *pMenuSetNumber = NULL);\r\n\tint\t\t\t\t\t\t\tGetTotalNumPieceSets() {return m_total_sets;}\r\n\r\n\t/* ======== Road mask functions ======== */\r\n\t\r\n\tbool\t\t\t\t\t\tIsOccupiedByRoad(GridDims area);\r\n\tbool\t\t\t\t\t\tCanPlacePiecesIn(GridDims cellDims, bool ignoreFloorHeight=false);\r\n\r\n\r\n\t/* ======== Restart node functions ===== */\r\n\r\n\tvoid\t\t\t\t\t\tSetRestartTypeId(CParkGenerator::RestartType type, uint32 id);\r\n\tCParkGenerator::RestartType\tIsRestartPiece(uint32 id);\r\n\r\n\t/* ======== Gap functions ===== */\r\n\t\r\n\tCGapManager::GapDescriptor *GetGapDescriptor(GridDims &area, int *pHalf);\r\n\tbool \t\t\t\t\t\tAddGap(CGapManager::GapDescriptor &descriptor);\r\n\tvoid \t\t\t\t\t\tRemoveGap(CGapManager::GapDescriptor &descriptor);\r\n\tvoid\t\t\t\t\t\tRemoveGap(CConcreteMetaPiece *pMeta);\r\n\tvoid\t\t\t\t\t\tHighlightMetasWithGaps(bool highlightOn, CGapManager::GapDescriptor *pDesc);\r\n\r\n\t//void\t\t\t\t\t\tFreeUpMemoryForPlayingPark();\r\n\t\r\n\tvoid\t\t\t\t\t\tGetSummaryInfoFromBuffer(uint8 *p_buffer, int *p_numGaps, int *p_numMetas, uint16 *p_theme, uint32 *p_todScript, int *p_width, int *p_length);\r\n\t\r\n\t#ifdef __PLAT_NGC__\r\n\tvoid\t\t\t\t\t\tSwapMapBufferEndianness();\r\n\t#endif\r\n\t\r\nprotected:\r\n\r\n\t/* ======== Key members ======== */\r\n\t\r\n\tCParkGenerator *\t\t\tmp_generator;\r\n\tbool\t\t\t\t\t\tm_state_on;\r\n\tbool\t\t\t\t\t\tm_park_is_valid;\r\n\r\n\t/* ======== Riser/floor related functions ======== */\r\n\t\r\n\tenum EFloorFlags\r\n\t{\r\n\t\tNONE =\t\t\t\t\t0,\r\n\t\tmHAS_BOTTOM =\t\t\t(1<<0),\r\n\t\tmHAS_TOP =\t\t\t\t(1<<1),\r\n\t\tmNO_COVER =\t\t\t\t(1<<2),\r\n\t};\r\n\t\r\n\tstruct BuildFloorParams\r\n\t{\r\n\t\t/* for build_add_floor_piece() */\r\n\t\tint \t\t\t\t\tx, y, z;\r\n\t\tEFloorFlags \t\t\tflags;\r\n\t\tint \t\t\t\t\theightSlotOffset;\r\n\t\t/* for output_riser_stack() */\r\n\t\tint\t\t\t\t\t\tbottom;\r\n\t\tint\t\t\t\t\t\ttop;\r\n\t\tbool\t\t\t\t\tsimpleBuild;\r\n\t\tbool\t\t\t\t\tdryRun;\r\n\t\tint\t\t\t\t\t\taddCount; \t// counts metapieces\r\n\t\tint\t\t\t\t\t\taddCount2;\t// counts contained pieces\r\n\t};\r\n\r\n\tvoid\t\t\t\t\t\toutput_riser_stack(BuildFloorParams &params);\r\n\tvoid\t\t\t\t\t\tbuild_add_floor_piece(BuildFloorParams &params);\r\n\tvoid\t\t\t\t\t\tbuild_add_floor_piece_simple(BuildFloorParams &params);\r\n\tvoid\t\t\t\t\t\tapply_meta_contained_risers_to_floor(CConcreteMetaPiece *pMetaPiece, bool add);\r\n\t\r\n\tCMapListNode *\t\t\t\tmp_column_slide_list;\r\n\tint\t\t\t\t\t\t\tm_num_metas_killed_in_slide;\r\n\tint\t\t\t\t\t\t\tm_num_pieces_killed_in_slide;\r\n\t\t\r\n\tenum ESlideColumnFlags\r\n\t{\r\n\t\tmUNEVEN =\t\t\t\t(1<<0),\r\n\t\tmUP\t=\t\t\t\t\t(1<<1),\r\n\t\tmFIRST_RECURSE =\t\t(1<<2),\r\n\t};\r\n\tbool \t\t\t\t\t\tintersection_with_riser_containing_metas(GridDims area);\r\n\tbool\t\t\t\t\t\tslide_column_part_one(GridDims area, int bottom, int top, ESlideColumnFlags flags, CMapListNode **ppMoveList);\r\n\tvoid\t\t\t\t\t\tfix_slide_column_part_one_failure();\r\n\tvoid\t\t\t\t\t\tslide_column_part_two(CMapListNode *pMoveList);\r\n\tvoid\t\t\t\t\t\tkill_pieces_in_layer_under_area(GridDims area);\r\n\tvoid\t\t\t\t\t\tfinish_slide_column();\r\n\tbool\t\t\t\t\t\tgenerate_floor_pieces_from_height_map(bool simpleBuild, bool dryRun);\r\n\r\n\tvoid\t\t\t\t\t\tincrement_meta_count(uint32 pieceChecksum);\r\n\tvoid\t\t\t\t\t\tdecrement_meta_count(uint32 pieceChecksum);\r\n\tint\t\t\t\t\t\t\tget_dma_usage(uint32 pieceChecksum);\r\n\r\n\tenum\r\n\t{\r\n\t\tNUM_RISER_INFO_SLOTS = \t8,\r\n\t};\r\n\t\r\n\tuint32\t\t\t\t\t\tm_riser_piece_checksum[NUM_RISER_INFO_SLOTS][3];\r\n\r\n\t#ifdef USE_BUILD_LIST\r\n\tstruct SBuildListEntry\r\n\t{\r\n\t\tuint32 mType;\r\n\t\tGridDims mPos;\r\n\t};\t\r\n\tint\t\t\t\t\t\t\tm_build_list_size;\r\n\tSBuildListEntry\t\t\t\t*mp_build_list_entry;\r\n\tvoid\t\t\t\t\t\tcreate_metas_in_build_list();\r\n\t#endif\r\n\t\r\n\t/* ======== metapiece management stuff ======== */\r\n\t\r\n\tCMapListNode *\t\t\t\tmp_concrete_metapiece_list;\r\n\tCMapListNode *\t\t\t\tmp_abstract_metapiece_list;\r\n\tint \t\t\t\t\t\tm_num_concrete_metapieces;\r\n\tint\t\t\t\t\t\t\tm_num_general_concrete_metapieces; // concrete metapieces not including riser, shell metapieces. Must be in park.\r\n\tint \t\t\t\t\t\tm_num_abstract_metapieces;\r\n\t// The DMA piece count counts pieces weighted according to their contribution to DMA usage.\r\n\t// Some pieces contribute more than 1, eg the lava piece, and any piece that has wibbling.\r\n\t// Needed so that the gauge can take into account DMA usage and not allow DMA overflow.\r\n\tint\t\t\t\t\t\t\tm_dma_piece_count;\r\n\tCMapListNode * \t\t\t\tmp_bucket_list[FLOOR_MAX_WIDTH][FLOOR_MAX_LENGTH];\r\n\r\n\tvoid \t\t\t\t\t\tadd_metapiece_to_node_list(CMetaPiece *pPieceToAdd, CMapListNode **ppList);\r\n\tvoid \t\t\t\t\t\tremove_metapiece_from_node_list(CMetaPiece *pPieceToRemove, CMapListNode **ppList);\r\n\tvoid\t\t\t\t\t\tbucketify_metapiece(CConcreteMetaPiece *pPiece);\r\n\tvoid\t\t\t\t\t\tdebucketify_metapiece(CConcreteMetaPiece *pPiece);\r\n\t\t\r\n\tvoid\t\t\t\t\t\tcreate_abstract_metapieces();\r\n\tvoid\t\t\t\t\t\tdestroy_concrete_metapieces(CParkGenerator::EDestroyType type);\r\n\r\n\t/* ======== Floor map/park bounds stuff ======== */\r\n\t\r\n\tint\t\t\t\t\t\t\tm_theme;\r\n\t\r\n\t/*\r\n\t\tWithin the 256X256 \"super map\"\r\n\t\t\r\n\t\tX and Z are positive -- must subtract 128 to get true world cell coordinates\r\n\t*/\r\n\tGridDims\t\t\t\t\tm_park_near_bounds;\r\n\tGridDims\t\t\t\t\tm_park_far_bounds;\r\n\r\n\tenum\r\n\t{\r\n\t\tTYPE_EMPTY_BLOCK\t\t= 0,\r\n\t\tTYPE_FLOOR_BLOCK\t\t= 0xaec511eb,\r\n\t\tTYPE_FLOOR_WALL_BLOCK\t= 0x829cfc8d,\r\n\t\tTYPE_WALL_BLOCK\t\t\t= 0x304bd5f7,\r\n\t};\r\n\t\r\n\tstruct FloorHeightEntry\r\n\t{\r\n\t\tint\t\t\t\t\t\tmHeight;\r\n\t\t/*\r\n\t\t\tBit 0 = -16Y, 31 = 15Y\r\n\t\t\t\r\n\t\t\tEach bit set true of corresponding riser is part of metapiece at that position.\r\n\t\t*/\r\n\t\tuint32\t\t\t\t\tmEnclosedFloor;\r\n\t\tbool\t\t\t\t\tmMarkAsSlid;\r\n\t\tint\t\t\t\t\t\tmSlideAmount;\r\n\t};\r\n\r\n\tFloorHeightEntry **\t\t\tm_floor_height_map;\r\n\r\n\t/* ======== piece set stuff ======== */\r\n\t\r\n\tCPieceSet\t\t\t\t\tm_palette_set[MAX_SETS];\r\n\tint\t\t\t\t\t\t\tm_total_sets;\r\n\r\n\t/* ======== map buffer access stuff ======== */\r\n\t\r\n\tstruct CompressedMapHeader\r\n\t{\r\n\t\tuint32\t\t\t\t\tmChecksum; // CRC of every byte in file except these 4\r\n\t\tuint16\t\t\t\t\tmSizeInBytes;\r\n\t\tuint16\t\t\t\t\tmVersion;\r\n\t\tuint16\t\t\t\t\tmTheme;\r\n\t\tuint16\t\t\t\t\tmParkSize;\r\n\t\tuint8 \t\t\t\t\tmX;\r\n\t\tuint8\t\t\t\t\tmZ;\r\n\t\tuint8\t\t\t\t\tmW;\r\n\t\tuint8\t\t\t\t\tmL;\r\n\t\tuint16\t\t\t\t\tmNumMetas;\r\n\t\tuint16\t\t\t\t\tmNumGaps;\r\n\t\tuint8\t\t\t\t\tmMaxPlayers;\r\n\t\tuint32\t\t\t\t\tmTODScript;\r\n\t\tchar\t\t\t\t\tmParkName[64];\r\n\t};\r\n\r\n\tstruct CompressedMapHeaderOld\r\n\t{\r\n\t\tuint32\t\t\t\t\tmChecksum; // CRC of every byte in file except these 4\r\n\t\tuint16\t\t\t\t\tmSizeInBytes;\r\n\t\tuint16\t\t\t\t\tmVersion;\r\n\t\tuint16\t\t\t\t\tmTheme;\r\n\t\tuint16\t\t\t\t\tmParkSize;\r\n\t\tuint8 \t\t\t\t\tmX;\r\n\t\tuint8\t\t\t\t\tmZ;\r\n\t\tuint8\t\t\t\t\tmW;\r\n\t\tuint8\t\t\t\t\tmL;\r\n\t\tuint16\t\t\t\t\tmNumMetas;\r\n\t\tuint16\t\t\t\t\tmNumGaps;\r\n\t\tchar\t\t\t\t\tmParkName[64];\r\n\t};\r\n\r\n\tstruct CompressedFloorEntry\r\n\t{\r\n\t\tsint8\t\t\t\t\tmHeight;\r\n\t};\r\n\r\n\t// K: To allow loading of older parks that do not have gap cancel-flag info \r\n\tstruct CompressedGapOld\r\n\t{\r\n\t\tuint8\t\t\t\t\tx[2];\r\n\t\tuint8\t\t\t\t\ty[2];\r\n\t\tuint8\t\t\t\t\tz[2];\r\n\t\t// bits 0-3 left extent, 4-7 right\r\n\t\tuint8\t\t\t\t\textent[2];\r\n\t\t// bits 0-3 first rot, 4-7 second\r\n\t\tuint8\t\t\t\t\trot;\r\n\t\tuint8\t\t\t\t\tflags;\r\n\t\tchar\t\t\t\t\ttext[32];\r\n\t\tuint16\t\t\t\t\tscore;\r\n\t};\r\n\t\r\n\tstruct CompressedGap\r\n\t{\r\n\t\tuint8\t\t\t\t\tx[2];\r\n\t\tuint8\t\t\t\t\ty[2];\r\n\t\tuint8\t\t\t\t\tz[2];\r\n\t\t// bits 0-3 left extent, 4-7 right\r\n\t\tuint8\t\t\t\t\textent[2];\r\n\t\t// bits 0-3 first rot, 4-7 second\r\n\t\tuint8\t\t\t\t\trot;\r\n\t\tuint8\t\t\t\t\tflags;\r\n\t\tchar\t\t\t\t\ttext[32];\r\n\t\tuint16\t\t\t\t\tscore;\r\n\t\t\r\n\t\tuint32\t\t\t\t\tmCancelFlags;\r\n\t};\r\n\t\r\n\tenum\r\n\t{   \r\n\t\tVERSION\t\t\t\t\t= 20004,\r\n\t};\r\n\tuint8 *\t\t\t\t\t\tmp_compressed_map_buffer;\r\n\t\r\n\tenum ECompressedMapFlags\r\n\t{\r\n\t\tmNO_FLAGS\t\t\t\t= 0,\r\n\t\tmIN_SYNC_WITH_PARK\t\t= (1<<0),\t// cleared if park hasn't been built yet\r\n\t\tmIS_VALID\t\t\t\t= (1<<1),\r\n\t\tmIS_NEWER_THAN_PARK\t\t= (1<<2),\t// also set if park hasn't been built yet\r\n\r\n\t\tmNOT_SAVED_LOCAL\t\t= (1<<3),\r\n\t};\r\n\tECompressedMapFlags\t\t\tm_compressed_map_flags;\r\n\r\n\tvoid\t\t\t\t\t\tfake_compressed_map_buffer();\r\n\tvoid\t\t\t\t\t\twrite_compressed_map_buffer();\r\n\tvoid\t\t\t\t\t\tread_from_compressed_map_buffer();\r\n\tvoid \t\t\t\t\t\tread_from_compressed_map_buffer_old();\r\n\r\n\tvoid\t\t\t\t\t\tsetup_default_dimensions();\r\n\t\r\n\tchar\t\t\t\t\t\tmp_park_name[64];\r\n\t\r\n\t/* ======== Road mask section ======== */\r\n\r\n\tenum\r\n\t{\r\n\t\tNUM_ROAD_PIECES\t\t\t= 8,\r\n\t};\r\n\tGridDims\t\t\t\t\tm_road_mask_tab[NUM_ROAD_PIECES];\r\n\tuint\t\t\t\t\t\tm_road_mask_tab_size;\r\n\r\n\tvoid\t\t\t\t\t\tsetup_road_mask();\r\n\r\n\t/* ======== Restart Node section ======= */\r\n\r\n\tuint32\t\t\t\t\t\tm_restartPieceIdTab[CParkGenerator::vNUM_RESTART_TYPES];\t // Table of checksums of the names of restart pieces\r\n\r\n\r\n\t/* ======== Lights Section ============= */\r\n\tvoid\t\t\t\t\t\tsetup_lighting();\r\n\r\n\r\n\t/* ======== Gap Section ============= */\r\n\t\r\n\tCGapManager\t*\t\t\t\tmp_gap_manager;\r\n\t\r\n\tstatic CParkManager *\t\tsp_instance;\r\n};\r\n\r\n\r\n\r\n\r\n}\r\n\r\n#endif // __SK_PARKEDITOR2_EDMAP_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/ParkEditor2/GapManager.cpp",
    "content": "#include <core/defines.h>\r\n#include <sk/ParkEditor2/EdMap.h>\r\n#include <sk/ParkEditor2/GapManager.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/objects/gap.h>\r\n#include <sk/components/GoalEditorComponent.h>\r\n\r\n\r\nnamespace Ed\r\n{\r\n\r\n\r\n\r\n\r\nCGapManager *CGapManager::sp_instance = NULL;\r\n\r\n\r\nGapInfo::GapInfo()\r\n{\r\n\tmp_gapPiece[0] \t\t= NULL;\r\n\tmp_gapPiece[1] \t\t= NULL;\r\n\tmp_regularMeta[0] \t= NULL;\r\n\tmp_regularMeta[1] \t= NULL;\r\n\t\r\n\tm_descriptor.mCancelFlags=0;\r\n}\r\n\r\n\r\n\r\n\r\nCGapManager::CGapManager(CParkManager *pManager)\r\n{\r\n\tm_currentId = 2000;\r\n\r\n\tfor (int i = 0; i < vMAX_GAPS; i++)\r\n\t\tmp_gapInfoTab[i] = NULL;\r\n\r\n\tmp_manager = pManager;\r\n\tSetInstance();\r\n}\r\n\r\n\r\n\r\n\r\nCGapManager::~CGapManager()\r\n{\r\n\t// XXX\r\n\tRyan(\"in ~CGapManager()\\n\");\r\n\tRemoveAllGaps();\r\n\t// XXX\r\n\tRyan(\"leaving ~CGapManager()\\n\");\r\n\tsp_instance = NULL;\r\n}\r\n\r\nCGapManager& CGapManager::operator=( const CGapManager& rhs )\r\n{\r\n\tm_currentId = rhs.m_currentId;\r\n\t\r\n\tfor (int i = 0; i < vMAX_GAPS; i++)\r\n\t{\r\n\t\tif (rhs.mp_gapInfoTab[i])\r\n\t\t{\r\n\t\t\tGapInfo *p_new = new GapInfo;\r\n\t\t\t\r\n\t\t\tp_new->m_id[0] = rhs.mp_gapInfoTab[i]->m_id[0];\r\n\t\t\tp_new->m_id[1] = rhs.mp_gapInfoTab[i]->m_id[1];\r\n\t\t\tp_new->mp_gapPiece[0] = NULL;\r\n\t\t\tp_new->mp_gapPiece[1] = NULL;\r\n\t\t\tp_new->mp_regularMeta[0] = NULL;\r\n\t\t\tp_new->mp_regularMeta[1] = NULL;\r\n\t\t\tDbg_MsgAssert(strlen(rhs.mp_gapInfoTab[i]->mp_text) < 128,(\"Bad source gap text\"));\r\n\t\t\tstrcpy(p_new->mp_text, rhs.mp_gapInfoTab[i]->mp_text);\r\n\t\t\tp_new->m_descriptor = rhs.mp_gapInfoTab[i]->m_descriptor;\r\n\t\t\t\r\n\t\t\tmp_gapInfoTab[i] = p_new;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_gapInfoTab[i]=NULL;\r\n\t\t}\t\r\n\t\t\r\n\t\tm_startOfGap[i] = rhs.m_startOfGap[i];\r\n\t}\r\n\t\r\n\tmp_manager=NULL;\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n\r\n\r\nint CGapManager::GetFreeGapIndex()\r\n{\r\n\tfor (int i = 0; i < vMAX_GAPS; i++)\r\n\t\tif (!mp_gapInfoTab[i])\r\n\t\t\treturn i;\r\n\treturn -1;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CGapManager::StartGap(CClonedPiece *pGapPiece, CConcreteMetaPiece *pRegularMeta, int tab_index)\r\n{\r\n\t\r\n\tDbg_Assert(pGapPiece);\r\n\tDbg_Assert(pRegularMeta);\r\n\r\n\t//Ryan(\"Starting gap 0x%x\\n\", m_currentId);\r\n\t\r\n\t// find empty slot\r\n\t// BAD MEM\r\n\tmp_gapInfoTab[tab_index] = new GapInfo();\r\n\tmp_gapInfoTab[tab_index]->m_id[0] = m_currentId++;\r\n\tmp_gapInfoTab[tab_index]->mp_gapPiece[0] = pGapPiece;\r\n\t//mp_gapInfoTab[tab_index]->mp_gapPiece[0]->MarkAsGapInProgress();\r\n\tmp_gapInfoTab[tab_index]->mp_regularMeta[0] = pRegularMeta;\r\n\tmp_gapInfoTab[tab_index]->m_descriptor.tabIndex = tab_index;\r\n\tm_startOfGap[tab_index] = true;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CGapManager::EndGap(CClonedPiece *pGapPiece, CConcreteMetaPiece *pRegularMeta, int tab_index)\r\n{\r\n\t\r\n\tDbg_Assert(pGapPiece);\r\n\tDbg_Assert(pRegularMeta);\r\n\tDbg_MsgAssert(tab_index >= 0 && tab_index < vMAX_GAPS, (\"invalid tab_index\"));\r\n\r\n\tGapInfo *pStartInfo = mp_gapInfoTab[tab_index];\r\n\tDbg_Assert(pStartInfo);\r\n\t\r\n\t//Ryan(\"Ending gap 0x%x\\n\", m_currentId);\r\n\t\r\n\t// find empty slot\r\n\tfor (int i = 0; i < vMAX_GAPS; i++)\r\n\t\tif (!mp_gapInfoTab[i])\r\n\t\t{\r\n\t\t\tmp_gapInfoTab[i] = pStartInfo;\r\n\t\t\tmp_gapInfoTab[i]->m_id[1] = m_currentId++;\r\n\t\t\tmp_gapInfoTab[i]->mp_gapPiece[1] = pGapPiece;\r\n\t\t\t//mp_gapInfoTab[i]->mp_gapPiece[0]->UnmarkAsGapInProgress();\r\n\t\t\t//mp_gapInfoTab[i]->mp_gapPiece[1]->UnmarkAsGapInProgress();\r\n\t\t\tmp_gapInfoTab[i]->mp_regularMeta[1] = pRegularMeta;\r\n\t\t\tmp_gapInfoTab[i]->m_descriptor.tabIndex = tab_index;\r\n\t\t\tm_startOfGap[i] = false;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\tDbg_MsgAssert(0, (\"out of gap slots\"));\r\n\treturn;\r\n}\r\n\r\n// K: Called when CParkEditor::SetState switches to test play or regular play.\r\n// This is necessary to make the gaps appear in the view-gaps menu, which lists those\r\n// in the skater career.\r\nvoid CGapManager::RegisterGapsWithSkaterCareer()\r\n{\r\n\tObj::CGapChecklist\t*p_gap_checklist=Mdl::Skate::Instance()->GetCareer()->GetGapChecklist();\r\n\tif (!p_gap_checklist)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tp_gap_checklist->FlushGapChecks();\r\n\r\n\tfor (int i = 0; i < vMAX_GAPS; i++)\r\n\t{\r\n\t\tif (mp_gapInfoTab[i])\r\n\t\t{\r\n\t\t\tp_gap_checklist->AddGapCheck(mp_gapInfoTab[i]->m_descriptor.text, 0,\r\n\t\t\t\t\t\t\t\t\t\t mp_gapInfoTab[i]->m_descriptor.score);\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\nvoid CGapManager::SetGapInfo(int tab_index, GapDescriptor &descriptor)\r\n{\r\n\t\r\n\tDbg_MsgAssert(tab_index >= 0 && tab_index < vMAX_GAPS, (\"invalid tab_index\"));\r\n\tDbg_Assert(mp_gapInfoTab[tab_index]);\r\n\tDbg_Assert(descriptor.tabIndex >= 0 && descriptor.tabIndex < vMAX_GAPS);\r\n\r\n\tsprintf(mp_gapInfoTab[tab_index]->mp_text, \"%s\", descriptor.text);\r\n\tmp_gapInfoTab[tab_index]->m_descriptor = descriptor;\r\n\r\n\tRegisterGapsWithSkaterCareer();\r\n\t//mp_gapInfoTab[tab_index]->mp_gapPiece[0]->MakeTriggerable(true);\r\n\t//mp_gapInfoTab[tab_index]->mp_gapPiece[1]->MakeTriggerable(true);\r\n}\r\n\r\n\r\n\r\n\r\nbool CGapManager::IsGapAttached(const CConcreteMetaPiece *pRegularMeta, int *pTabIndex)\r\n{\r\n\tfor (int i = 0; i < vMAX_GAPS; i++)\r\n\t\tif (mp_gapInfoTab[i])\r\n\t\t{\r\n\t\t\tint half_num = (m_startOfGap[i]) ? 0 : 1;\r\n\t\t\t#if 0\r\n\t\t\tif (i == 16 || i == 17)\r\n\t\t\t\tRyan(\"           testing gap index %d, pMeta[0]=%x, pMeta[1]=%x, half=%d, test_meta=%p\\n\", \r\n\t\t\t\t\t i,\r\n\t\t\t\t\t mp_gapInfoTab[i]->mp_regularMeta[0],\r\n\t\t\t\t\t mp_gapInfoTab[i]->mp_regularMeta[1], \r\n\t\t\t\t\t half_num, pRegularMeta);  \r\n\t\t\t#endif\r\n\t\t\tif (mp_gapInfoTab[i]->mp_regularMeta[half_num] == pRegularMeta)\r\n\t\t\t{\r\n\t\t\t\t#if 0\r\n\t\t\t\tRyan(\"     found gap at table index %d, position=(%d,%d,%d), half=%d, pMeta=%p\\n\", \r\n\t\t\t\t\t i, \r\n\t\t\t\t\t mp_gapInfoTab[i]->m_descriptor.loc[half_num].GetX(), \r\n\t\t\t\t\t mp_gapInfoTab[i]->m_descriptor.loc[half_num].GetY(),\r\n\t\t\t\t\t mp_gapInfoTab[i]->m_descriptor.loc[half_num].GetZ(),\r\n\t\t\t\t\t half_num,\r\n\t\t\t\t\t pRegularMeta);\r\n\t\t\t\t#endif\r\n\t\t\t\tif (pTabIndex)\r\n\t\t\t\t\t*pTabIndex = i;\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CGapManager::RemoveGap(int tab_index, bool unregisterGapFromGoalEditor)\r\n{\r\n\t\r\n\tDbg_MsgAssert(tab_index >= 0 && tab_index < vMAX_GAPS, (\"invalid tab_index\"));\r\n\r\n\tGapInfo *pRemoveInfo = mp_gapInfoTab[tab_index];\r\n\tDbg_Assert(pRemoveInfo);\r\n\t\r\n\t\r\n\tfor (int gp = 0; gp < 2; gp++)\r\n\t{\r\n\t\tif (pRemoveInfo->mp_gapPiece[gp])\r\n\t\t\tmp_manager->GetGenerator()->DestroyClonedPiece(pRemoveInfo->mp_gapPiece[gp]);\r\n\t}\r\n\r\n\t// Note: Need to check mp_manager cos it could be NULL in the case of this being\r\n\t// the CParkEditor's mp_play_mode_gap_manager. (Fixes TT12087)\r\n\tif (unregisterGapFromGoalEditor)\r\n\t{\r\n\t\t// Determine the gap number of the gap as stored in the career gap check list\t\r\n\t\tint gap_number=Mdl::Skate::Instance()->GetGapChecklist()->GetGapChecklistIndex(pRemoveInfo->m_descriptor.text);\r\n\t\tif (gap_number >= 0)\r\n\t\t{\r\n\t\t\tObj::GetGoalEditor()->RefreshGapGoalsAfterGapRemovedFromPark(gap_number);\r\n\t\t}\t\r\n\t}\r\n\t\t\r\n\tfor (int i = 0; i < vMAX_GAPS; i++)\r\n\t{\r\n\t\tif (mp_gapInfoTab[i] == pRemoveInfo)\r\n\t\t{\r\n\t\t\tmp_gapInfoTab[i] = NULL;\r\n\t\t}\r\n\t}\r\n\tdelete pRemoveInfo;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CGapManager::RemoveAllGaps()\r\n{\r\n\tfor (int i = 0; i < vMAX_GAPS; i++)\r\n\t{\r\n\t\tif (mp_gapInfoTab[i])\r\n\t\t{\r\n\t\t\t// Normally, when a gap piece is deleted such as when editing a park, it gets unregistered\r\n\t\t\t// from the goal editor.\r\n\t\t\t// However, when cleaning up the park, we don't want to do this.\r\n\t\t\t// The false means do not unregister the gap from the goal editor.\r\n\t\t\tRemoveGap(i, false);\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\n\r\n\r\n\r\nuint32 CGapManager::GetGapTriggerScript(CClonedPiece *pGapPiece)\r\n{\r\n\tfor (int i = 0; i < vMAX_GAPS; i++)\r\n\t\tif (mp_gapInfoTab[i])\r\n\t\t{\r\n\t\t\tint half_num = (m_startOfGap[i]) ? 0 : 1;\r\n\t\t\tif (mp_gapInfoTab[i]->mp_gapPiece[half_num] == pGapPiece)\r\n\t\t\t{\r\n\t\t\t\tif (i&1  && Script::GetInt(\"PrintGaps\",false))\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf (\"Editor Gap %d points: %s\\n\",mp_gapInfoTab[i]->m_descriptor.score, mp_gapInfoTab[i]->m_descriptor.text);  \r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tchar gap_trigger_script[48];\r\n\t\t\t\tsprintf(gap_trigger_script, \"EditorTrgGap%d\", i);\r\n\t\t\t\treturn Script::GenerateCRC(gap_trigger_script);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\tDbg_MsgAssert(0, (\"no gap trigger script\"));\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n\t\r\nCGapManager::GapDescriptor *CGapManager::GetGapDescriptor(int tab_index, int *pHalfNum)\r\n{\r\n\t\r\n\tif (!mp_gapInfoTab[tab_index])\r\n\t\treturn NULL;\r\n\t\r\n\t*pHalfNum = (m_startOfGap[tab_index]) ? 0 : 1;\r\n\tstrcpy(mp_gapInfoTab[tab_index]->m_descriptor.text, mp_gapInfoTab[tab_index]->mp_text);\r\n\treturn &mp_gapInfoTab[tab_index]->m_descriptor;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CGapManager::MakeGapWireframe(int tab_index)\r\n{\r\n\t\r\n\tDbg_MsgAssert(tab_index >= 0 && tab_index < vMAX_GAPS, (\"invalid tab_index %d\", tab_index));\r\n\r\n\tif (!mp_gapInfoTab[tab_index])\r\n\t\treturn;\r\n\r\n\tif (mp_gapInfoTab[tab_index]->mp_gapPiece[0])\r\n\t\tmp_gapInfoTab[tab_index]->mp_gapPiece[0]->SetVisibility(true);\r\n\tif (mp_gapInfoTab[tab_index]->mp_gapPiece[1])\r\n\t\tmp_gapInfoTab[tab_index]->mp_gapPiece[1]->SetVisibility(true);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CGapManager::LaunchGap(int tab_index, Script::CScript *pScript)\r\n{\r\n#if 1\t\r\n\tDbg_MsgAssert(tab_index >= 0 && tab_index < vMAX_GAPS, (\"invalid tab_index\"));\r\n\tDbg_Assert(mp_gapInfoTab[tab_index]);\r\n\tDbg_Assert(pScript);\r\n\tDbg_Assert(pScript->mpObject);\r\n\t\t\r\n\tfor (int i = 0; i < 2; i++)\r\n\t{\r\n\t\tint half_num = (m_startOfGap[tab_index]) ? i : 1 - i;\r\n\r\n\t\tScript::CStruct *pGapParms = new Script::CStruct();\r\n\t\tpGapParms->AddChecksum(CRCD(0x3b442e26,\"GapID\"), mp_gapInfoTab[tab_index]->m_id[half_num]);\r\n\t\tpGapParms->AddInteger(CRCD(0xcd66c8ae,\"score\"), mp_gapInfoTab[tab_index]->m_descriptor.score);\r\n\t\tpGapParms->AddString(CRCD(0xc4745838,\"text\"), mp_gapInfoTab[tab_index]->mp_text);\r\n\t\t//pGapParms->AddComponent(Script::GenerateCRC(\"text\"), ESYMBOLTYPE_STRING, \"boogah\");\r\n\t\t\r\n\t\tif (i == 0)\r\n\t\t{\r\n\t\t\tuint32 cancel_flags=mp_gapInfoTab[tab_index]->m_descriptor.mCancelFlags;\r\n\t\t\tif (!cancel_flags)\r\n\t\t\t{\r\n\t\t\t\t// If no flags are set for some reason, use the default of just CANCEL_GROUND\r\n\t\t\t\tcancel_flags=Script::GetInteger(CRCD(0x9a27e74d,\"CANCEL_GROUND\"));\r\n\t\t\t}\r\n\t\t\tpGapParms->AddChecksum(CRCD(0x2760de9e,\"combined_flags\"),cancel_flags);\r\n\t\t\r\n\t\t\tpScript->mpObject->CallMemberFunction(Script::GenerateCRC(\"StartGap\"), pGapParms, pScript);\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tpScript->mpObject->CallMemberFunction(Script::GenerateCRC(\"EndGap\"), pGapParms, pScript);\r\n\t\t}\r\n\t\t\r\n\t\tdelete pGapParms;\t\r\n\t}\r\n#endif\r\n}\r\n\r\n\r\n\r\n\r\nCGapManager *CGapManager::sInstance()\r\n{\r\n\tDbg_Assert(sp_instance);\r\n\treturn sp_instance;\r\n}\r\n\r\n\r\n\r\n\r\n}\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/ParkEditor2/GapManager.h",
    "content": "#ifndef __SK_PARKEDITOR2_GAPMANAGER_H\r\n#define __SK_PARKEDITOR2_GAPMANAGER_H\r\n\r\n#include <sk/ParkEditor2/ParkGen.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n}\r\n\r\n\r\nnamespace Ed\r\n{\r\n\r\nclass CGapManager;\r\nclass GapInfo;\r\nclass CParkManager;\r\n\r\nclass  CGapManager\r\n{\r\n\t\r\n\t\r\npublic:\r\n\r\n\tstruct GapDescriptor\r\n\t{\r\n\t\tGridDims\t\t\t\tloc[2];\r\n\t\tint\t\t\t\t\t\trot[2];\r\n\t\tint \t\t\t\t\tleftExtent[2];\r\n\t\tint\t\t\t\t\t\trightExtent[2];\r\n\t\tchar \t\t\t\t\ttext[32];\r\n\t\tint\t\t\t\t\t\tscore;\r\n\t\tint\t\t\t\t\t\tnumCompleteHalves; // will be 0, 1, or 2\r\n\t\tint\t\t\t\t\t\ttabIndex; // set to -1 if not in table\r\n\t\t\r\n\t\t// An 'or' of the CANCEL_ values as defined in skutils.q, eg CANCEL_GROUND\r\n\t\tuint32\t\t\t\t\tmCancelFlags;\r\n\t};\r\n\t\r\n\t// actually max gap HALVES, divide by two to get gaps\r\n\tstatic const int\t\t\tvMAX_GAPS = 32;\r\n\r\n\t\t\t\t\t\t\t\tCGapManager(CParkManager *pManager);\r\n\t\t\t\t\t\t\t\t~CGapManager();\r\n\r\n\tint \t\t\t\t\t\tGetFreeGapIndex();\r\n\tvoid\t\t\t\t\t\tStartGap(CClonedPiece *pGapPiece, CConcreteMetaPiece *pRegularMeta, int tab_index);\r\n\tvoid\t\t\t\t\t\tEndGap(CClonedPiece *pGapPiece, CConcreteMetaPiece *pRegularMeta, int tab_index);\r\n\tvoid\t\t\t\t\t\tSetGapInfo(int tab_index, GapDescriptor &descriptor);\r\n\tbool\t\t\t\t\t\tIsGapAttached(const CConcreteMetaPiece *pRegularMeta, int *pTabIndex);\r\n\tvoid\t\t\t\t\t\tRemoveGap(int tab_index, bool unregisterGapFromGoalEditor=true);\r\n\tvoid\t\t\t\t\t\tRemoveAllGaps();\r\n\tvoid\t\t\t\t\t\tRegisterGapsWithSkaterCareer();\r\n\r\n\tuint32\t\t\t\t\t\tGetGapTriggerScript(CClonedPiece *pGapPiece);\r\n\tGapDescriptor *\t\t\t\tGetGapDescriptor(int tab_index, int *pHalfNum);\r\n\tvoid\t\t\t\t\t\tMakeGapWireframe(int tab_index);\r\n\t\r\n\tvoid\t\t\t\t\t\tLaunchGap(int tab_index, Script::CScript *pScript);\r\n\r\n\tstatic CGapManager *\t\tsInstance();\r\n\tvoid\t\t\t\t\t\tSetInstance() {sp_instance=this;}\r\n\r\n\tstatic CGapManager *\t\tsInstanceNoAssert() {return sp_instance;}\r\n\r\n\tCGapManager& operator=( const CGapManager& rhs );\r\n\t\r\nprivate:\r\n\r\n\tuint32\t\t\t\t\t\tm_currentId;\r\n\r\n\tGapInfo *\t\t\t\t\tmp_gapInfoTab[vMAX_GAPS];\r\n\tbool\t\t\t\t\t\tm_startOfGap[vMAX_GAPS];\r\n\r\n\tCParkManager\t\t\t\t*mp_manager;\r\n\t\r\n\tstatic CGapManager *\t\tsp_instance;\r\n};\r\n\r\n\r\n\r\n\r\nclass  GapInfo  : public Spt::Class\r\n{\r\n\t\r\n\tfriend class CGapManager;\r\n\r\nprivate:\r\n\r\n\tGapInfo();\r\n\r\n\tuint32\t\t\t\t\t\tm_id[2];\r\n\tCClonedPiece *\t\t\t\tmp_gapPiece[2];\r\n\tCConcreteMetaPiece *\t\tmp_regularMeta[2];\r\n\tchar\t\t\t\t\t\tmp_text[128];\r\n\r\n\tCGapManager::GapDescriptor\tm_descriptor;\r\n};\r\n\r\n\r\n\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Sk/ParkEditor2/ParkEd.cpp",
    "content": "#include <core/defines.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/event.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/scripting/component.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <sk/ParkEditor2/ParkEd.h>\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/modules/FrontEnd/FrontEnd.h>\r\n#include <gfx/nxviewman.h>\r\n#include <gfx/2D/ScreenElemMan.h>\r\n#include <gfx/2D/TextElement.h>\r\n#include <gel/components/cameracomponent.h>\r\n#include <sk/components/raileditorcomponent.h>\r\n#include <sk/components/goaleditorcomponent.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n\r\n#include <sk/ParkEditor2/clipboard.h>\r\n#include <core/string/stringutils.h>\r\n\r\n//#define DONT_USE_CURSOR_META\r\n\r\nnamespace Ed\r\n{\r\n\r\n\r\n\r\n\r\nconst float CParkEditor::vMAX_CAM_DIST\t\t\t\t= 1500.0f;\r\nconst float CParkEditor::vMIN_CAM_DIST\t\t\t\t= 500.0f;\r\nconst float CParkEditor::vCAM_DIST_INC\t\t\t\t= 16.0f;\r\nconst float CParkEditor::vCAM_TARGET_ELEVATION\t\t= 300.0f;\r\n\r\nDefineSingletonClass( CParkEditor, \"Park editor module\" );\r\n\r\n\r\n\r\n\r\nCParkEditor::CParkEditor() :\r\n\tmp_park_manager(true)\r\n{\r\n\tm_logic_task \t= new Tsk::Task< CParkEditor > ( CParkEditor::s_logic_code, *this );\r\n\tm_display_task \t= new Tsk::Task< CParkEditor > ( CParkEditor::s_display_code, *this, Tsk::BaseTask::Node::vDISPLAY_TASK_PRIORITY_CPARKEDITOR_DISPLAY );\r\n\tm_input_handler = new Inp::Handler< CParkEditor > ( 0,  CParkEditor::s_input_logic_code, *this);\r\n\r\n\tm_movement_vel = 480.0f; //8.0f;\t\t// default movement velocity in inches per second\r\n\tm_rotate_vel = 120.0f;\t\t// 120 degrees per second. In 3 seconds you should complete 1 revolution\r\n\r\n\tmp_camera = NULL;\r\n\tm_camDist = 1400.0f;\r\n\tm_camAngle = 0.0f; //225.0f;\r\n\tm_camAngleVert = 10.0f;\r\n\r\n\tm_cursor_state = vMOVEMENT;\r\n\tm_state = vINACTIVE;\r\n\tm_paused = false;\r\n\r\n\tmp_cursor = NULL;\r\n\tmp_menu_manager = NULL;\r\n\t\r\n\tm_pct_resources_used = 1.0f;\r\n\tm_last_main_heap_free=0;\r\n\t\r\n\tm_tod_script=0;\r\n\r\n\tmp_play_mode_gap_manager=NULL;\r\n\r\n\tm_allow_defrag=false;\r\n\t\t\r\n\tRegisterWithTracker(NULL);\r\n}\r\n\r\n\r\n\r\n\r\nCParkEditor::~CParkEditor()\r\n{\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::Initialize(bool editMode)\r\n{\r\n\tParkEd(\"CParkEditor::Initialize()\");\r\n\t//printf(\"CParkEditor::Initialize\\n\");\r\n\t\r\n\tmp_park_manager->Initialize();\r\n\t\r\n\tif (editMode && !mp_cursor)\r\n\t{\r\n\t\tmp_cursor = new CCursor();\r\n\t\tmp_menu_manager = new CUpperMenuManager();\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::Rebuild(bool justRebuildFloor, bool clearMap, bool makeCursor)\r\n{\r\n\tParkEd(\"CParkEditor::Rebuild(justRebuildFloor = %d, clearMap = %d)\", justRebuildFloor, clearMap);\r\n\t\r\n\tif (justRebuildFloor)\r\n\t{\r\n\t\tmp_park_manager->RebuildFloor();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (mp_cursor)\r\n\t\t\tdelete mp_cursor;\r\n\t\tmp_cursor = NULL;\r\n\t\tmp_park_manager->RebuildWholePark(clearMap);\r\n\t}\t   \r\n\t\r\n\tif (makeCursor && !mp_cursor)\r\n\t{\r\n\t\tmp_cursor = new CCursor();\r\n\t}\r\n\t\r\n\t// Fix to TT1437, where the 1P restart piece was able to be placed outside the map if X pressed really quickly\r\n\t// just after nuking a park.\r\n\tif (mp_cursor)\r\n\t{\r\n\t\tmp_cursor->ForceInBounds();\r\n\t}\r\n\t\t\r\n\t// Regenerate the node array when the park is rebuilt (usually only happens when we are going to play the level)\r\n\tmp_park_manager->RebuildNodeArray();\r\n\t\r\n\t// and re register the gaps so that any old gaps are removed from the career.\r\n\tCGapManager::sInstance()->RegisterGapsWithSkaterCareer();\t\t\t\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::SetState(EEditorState desiredState)\r\n{\r\n\tParkEd(\"CParkEditor::SetState(desiredState = %d)\", desiredState);\r\n\t\r\n\tif (desiredState != vKEEP_SAME_STATE)\r\n\t{\r\n\t\tm_state = desiredState;\r\n\t}\t\r\n\t\r\n\t// this prevents menu input from placing a piece\r\n\tm_commands.ClearAll();\r\n\tif (mp_cursor)\r\n\t\tmp_cursor->SetVisibility(m_state == vEDITING);\r\n\r\n\tif (desiredState == vTEST_PLAY || desiredState == vREGULAR_PLAY)\r\n\t{\r\n\t   \t// XXX\r\n\t\tRyan(\"$$$MakeEditorStuffVisible(false)\\n\");\r\n\t\tMakeEditorStuffVisible(false); \r\n\t\t\r\n\t\tCGapManager::sInstance()->RegisterGapsWithSkaterCareer();\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// XXX\r\n\t\tRyan(\"$$$MakeEditorStuffVisible(true)\\n\");\r\n\t\tMakeEditorStuffVisible(true); \t\r\n\t}\r\n\r\n\tSpt::SingletonPtr<Mdl::FrontEnd> p_front_end;\t\r\n\tif (desiredState == vEDITING)\r\n\t{\r\n\t\tMdl::Skate::Instance()->CleanupForParkEditor();\r\n\t\r\n\t\tp_front_end->SetAutoRepeatTimes(320, 100);\r\n\t\tmp_park_manager->HighlightMetasWithGaps(false, NULL);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// same as above, but what the hell\r\n\t\tp_front_end->SetAutoRepeatTimes(320, 50);\r\n\t}\r\n\tupdate_analog_stick_menu_control_state();\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::MakeEditorStuffVisible(bool visible)\r\n{\r\n\tParkEd(\"MakeEditorStuffVisible(visible = %d)\", visible);\r\n\t\r\n\t// it would be nice to sort out the encapsulation sometime...\t\r\n\tEd::CParkManager::Instance()->GetGenerator()->HighlightAllPieces(false);\r\n\tEd::CParkManager::Instance()->GetGenerator()->SetGapPiecesVisible(visible);\r\n\tEd::CParkManager::Instance()->GetGenerator()->SetRestartPiecesVisible(visible);\r\n\t\r\n\tif (visible)\r\n\t{\r\n\t\tScript::RunScript(\"pause_trick_text\");\r\n\t\tScript::RunScript(\"GoalManager_HidePoints\");\r\n\t\tScript::RunScript(\"GoalManager_HideGoalPoints\");\r\n\t\tScript::RunScript(\"SK4_Hide_Death_Message\");\r\n\t}\r\n\telse\r\n\t{\r\n\t\tScript::RunScript(\"unpause_trick_text\");\r\n\t\tScript::RunScript(\"GoalManager_ShowPoints\");\r\n\t\tScript::RunScript(\"GoalManager_ShowGoalPoints\");\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::AccessDisk(bool save, int fileSlot, bool blockRebuild)\r\n{\r\n\tParkEd(\"CParkEditor::AccessDisk()\");\r\n\t\r\n\tif (save)\r\n\t{\r\n\t\tCParkManager::sInstance()->AccessDisk(true, fileSlot);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint old_theme = CParkManager::sInstance()->GetTheme();\r\n\t\t\r\n\t\tif (m_state != vINACTIVE && !blockRebuild)\r\n\t\t{\r\n\t\t\t// need to destroy cursor geometry now, otherwise code will think park has changed\r\n\t\t\tDbg_Assert(mp_cursor);\r\n\t\t\tmp_cursor->DestroyGeometry();\r\n\t\t}\r\n\t\tif (mp_cursor)\r\n\t\t{\r\n\t\t\tmp_cursor->DestroyAnyClipboardCursors();\r\n\t\t}\t\r\n\t\t\r\n\t\tCParkManager::sInstance()->AccessDisk(false, fileSlot);\r\n\t\tif (m_state != vINACTIVE && !blockRebuild)\r\n\t\t{\r\n\t\t\tif (CParkManager::sInstance()->GetTheme() != old_theme)\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct params;\r\n\t\t\t\tparams.AddChecksum(\"level\", CRCD(0xe8b4b836,\"Load_Sk5Ed\"));\r\n\t\t\t\t\r\n\t\t\t\tScript::RunScript(\"change_level\", &params);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tCParkManager::sInstance()->RebuildWholePark(false);\r\n\t\t\t\tmp_cursor->ChangePieceInSet(0);\r\n\t\t\t\tmp_park_manager->HighlightMetasWithGaps(false, NULL);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::PostMemoryCardLoad(uint8 * p_map_buffer, int oldTheme)\r\n{\r\n\tbool needs_rebuild = (m_state == vEDITING || m_state == vTEST_PLAY);\r\n\t\r\n\tif (needs_rebuild)\r\n\t{\r\n\t\t// need to destroy cursor geometry now, otherwise code will think park has changed\r\n\t\tDbg_Assert(mp_cursor);\r\n\t\tmp_cursor->DestroyGeometry();\r\n\t}\r\n\t// PATCH:  Copy buffer back over itself to set the flags\r\n\tEd::CParkManager::Instance()->SetCompressedMapBuffer(p_map_buffer);\r\n\tif (needs_rebuild)\r\n\t{\r\n\t\t// XXX\r\n\t\tRyan(\"old theme %d, new theme %d\\n\", oldTheme, CParkManager::sInstance()->GetTheme());\r\n\t\tif (CParkManager::sInstance()->GetTheme() != oldTheme)\r\n\t\t{\r\n\t\t\tScript::CStruct params;\r\n\t\t\tparams.AddChecksum(\"level\", CRCD(0xe8b4b836,\"Load_Sk5Ed\"));\r\n\r\n\t\t\tScript::RunScript(\"change_level\", &params);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tCParkManager::sInstance()->RebuildWholePark(false);\r\n\t\t\tmp_cursor->ChangePieceInSet(0);\r\n\t\t\tmp_park_manager->HighlightMetasWithGaps(false, NULL);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n// K: Added to allow cleanup of the park editor heap during play\r\nvoid CParkEditor::DeleteCursor()\r\n{\r\n\tif (mp_cursor)\r\n\t{\r\n\t\tdelete mp_cursor;\r\n\t\tmp_cursor=NULL;\r\n\t}\r\n}\r\n\r\n// Creates a copy of the gap manager on the script heap.\r\n// CGapManager::sInstance() will still return the original gap manager afterwards however.\r\n// This function is needed because to free up memory before playing a park, everything on the\r\n// park editor heap is deleted and then the heap is deleted, and the original gap manager is on that heap.\r\n// So a copy is made for play mode, since the gap manager is needed when a gap fires.\r\nvoid CParkEditor::CreatePlayModeGapManager()\r\n{\r\n\tDbg_MsgAssert(mp_play_mode_gap_manager==NULL,(\"Expected mp_play_mode_gap_manager to be NULL\"));\r\n\tEd::CGapManager *p_original_gap_manager = CGapManager::sInstance();\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\tmp_play_mode_gap_manager=new Ed::CGapManager(NULL);\r\n\t\r\n\t// Use the overloaded assignement operator to make the copy.\r\n\t*mp_play_mode_gap_manager = *p_original_gap_manager;\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\t\r\n\t// The constructor of CGapManager sets the sp_instance pointer, so set it back to the original so that\r\n\t// things don't get confused.\r\n\tp_original_gap_manager->SetInstance();\r\n}\r\n\r\nvoid CParkEditor::SwitchToPlayModeGapManager()\r\n{\r\n\tDbg_MsgAssert(CGapManager::sInstanceNoAssert() == NULL,(\"Expected CGapManager::sInstance() to be NULL\"));\r\n\tDbg_MsgAssert(mp_play_mode_gap_manager,(\"NULL mp_play_mode_gap_manager\"));\r\n\tmp_play_mode_gap_manager->SetInstance();\r\n}\t\r\n\r\nvoid CParkEditor::DeletePlayModeGapManager()\r\n{\r\n\tif (mp_play_mode_gap_manager)\r\n\t{\r\n\t\tdelete mp_play_mode_gap_manager;\r\n\t\tmp_play_mode_gap_manager=NULL;\r\n\t}\r\n\tDbg_MsgAssert(CGapManager::sInstanceNoAssert() == NULL,(\"Expected CGapManager::sInstance() to be NULL\"));\r\n}\r\n\r\nvoid CParkEditor::PlayModeGapManagerChecks()\r\n{\r\n\t//printf(\"CGapManager::sInstance = 0x%08x\\n\",CGapManager::sInstanceNoAssert());\r\n\t//printf(\"mp_play_mode_gap_manager = 0x%08x\\n\",mp_play_mode_gap_manager);\r\n}\r\n\r\nvoid CParkEditor::Cleanup()\r\n{\r\n\tParkEd(\"CParkEditor::Cleanup()\");\r\n\r\n\tm_state = vINACTIVE;\r\n\tif (mp_cursor)\r\n\t{\r\n\t\tdelete mp_cursor;\r\n\t\tmp_cursor = NULL;\r\n\t}\r\n\tif (mp_menu_manager)\r\n\t{\r\n\t\tdelete mp_menu_manager;\r\n\t\tmp_menu_manager = NULL;\r\n\t}\r\n\t\r\n\tmp_park_manager->Destroy(CParkGenerator::DESTROY_PIECES_AND_SECTORS);\r\n\t\r\n\tObj::CRailEditorComponent::sUpdateSuperSectorsAfterDeletingRailSectors = false;\r\n\tObj::GetRailEditor()->DestroyRailGeometry();\r\n\tObj::GetRailEditor()->DestroyPostGeometry();\r\n\tObj::CRailEditorComponent::sUpdateSuperSectorsAfterDeletingRailSectors = true;\r\n\r\n\tprintf(\"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ DEATH OR GLORY 2 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\\n\");\r\n}\r\n\r\nvoid CParkEditor::SetAppropriateCamera()\r\n{\r\n\tif (mp_cursor && mp_cursor->InRailPlacementMode())\r\n\t{\r\n\t\tCFuncs::SetActiveCamera(CRCD(0x5b509ad3,\"raileditor\"), 0, false);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCFuncs::SetActiveCamera(CRCD(0x64716bee,\"parked_cam\"), 0, false);\r\n\t}\t\r\n}\r\n\r\nvoid CParkEditor::do_piece_select_commands()\r\n{\r\n\tif (m_commands.TestMask(mPREV_SET))\r\n\t{\r\n\t\tmp_cursor->ChangeSet(-1); \r\n\t\tturn_on_or_update_piece_menu();\r\n\t\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\t\tp_tracker->LaunchEvent(Script::GenerateCRC(\"parked_menu_up\"), Script::GenerateCRC(\"set_menu_container\"));\r\n\t\t//mp_menu_manager->SetSourceMeta(mp_cursor->GetChecksum());\r\n\t}\r\n\tif (m_commands.TestMask(mNEXT_SET))\r\n\t{\r\n\t\tmp_cursor->ChangeSet(1); \r\n\t\tturn_on_or_update_piece_menu();\r\n\t\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\t\tp_tracker->LaunchEvent(Script::GenerateCRC(\"parked_menu_down\"), Script::GenerateCRC(\"set_menu_container\"));\r\n\t\t//mp_menu_manager->SetSourceMeta(mp_cursor->GetChecksum());\r\n\t}\r\n\tif (m_commands.TestMask(mPREV_PIECE))\r\n\t{\r\n\t\tmp_cursor->ChangePieceInSet(-1); \r\n\t\tturn_on_or_update_piece_menu();\r\n\t\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\t\tp_tracker->LaunchEvent(Script::GenerateCRC(\"parked_menu_left\"), Script::GenerateCRC(\"piece_menu_container\"));\r\n\t\t//mp_menu_manager->SetSourceMeta(mp_cursor->GetChecksum());\r\n\t}\r\n\tif (m_commands.TestMask(mNEXT_PIECE))\r\n\t{\r\n\t\tmp_cursor->ChangePieceInSet(1); \r\n\t\tturn_on_or_update_piece_menu();\r\n\t\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\t\tp_tracker->LaunchEvent(Script::GenerateCRC(\"parked_menu_right\"), Script::GenerateCRC(\"piece_menu_container\"));\r\n\t\t//mp_menu_manager->SetSourceMeta(mp_cursor->GetChecksum());\r\n\t}\r\n}\r\n\r\nvoid CParkEditor::regular_command_logic()\r\n{\r\n\tDbg_MsgAssert(mp_cursor,(\"NULL mp_cursor\"));\r\n\r\n\tMth::Matrix cam_matrix;\r\n\tcam_matrix.Ident();\r\n\tcam_matrix.SetPos(Mth::Vector(0.0f, 0.0f, m_camDist, 1.0f));\r\n\tcam_matrix.RotateX(Mth::DegToRad(-m_camAngleVert));\r\n\tcam_matrix.RotateY(Mth::DegToRad(m_camAngle));\r\n\tcam_matrix.Translate(Mth::Vector(mp_cursor->m_pos[X], vCAM_TARGET_ELEVATION, mp_cursor->m_pos[Z], 0.0f));\r\n\t\r\n\tObj::CCompositeObject * p_obj = (Obj::CCompositeObject *) Obj::CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0x64716bee,\"parked_cam\"));\r\n\tif (p_obj)\r\n\t{\r\n\t\t//printf(\"Setting cam pos\\n\");\r\n\t\t//CFuncs::SetActiveCamera(CRCD(0x64716bee,\"parked_cam\"), 0, false);\r\n\t\t\r\n\t\t//Obj::CCameraComponent * p_cam_comp = GetCameraComponentFromObject(p_obj); \t\t\t\r\n\t\tp_obj->SetPos(cam_matrix[Mth::POS]);\r\n\t\tp_obj->SetMatrix(cam_matrix);\r\n\t}\r\n\r\n\r\n\tif (!m_paused)\r\n\t{\r\n\t\t// XXX\r\n\t\t//Ryan(\"enraged monkey\\n\");\r\n\r\n\t\t// We unhighlight the meta-pieces intersecting the cursor before\r\n\t\t// we change or move it.\r\n\t\tif (!mp_cursor->InAreaSelectMode())\r\n\t\t{\r\n\t\t\tmp_cursor->HighlightIntersectingMetas(false); \r\n\t\t}\t\r\n\t\t\r\n\t\tTmr::Time current_time = Tmr::GetTime();\r\n\t\tfloat elapsed_seconds = (int) (current_time - m_last_time) / 1000.0f;\t\r\n\t\tm_last_time = current_time;\r\n\t\t\r\n\t\tstatic const\tfloat\tscale = ( 1.0f / ( 128.0f - Inp::vANALOGUE_TOL ));\r\n\t\t\r\n\t\tm_leftStick.m_Y =\r\n\t\t\t( m_leftStick.m_Y >  Inp::vANALOGUE_TOL ) ? ( m_leftStick.m_Y - Inp::vANALOGUE_TOL ) * scale :\r\n\t\t\t( m_leftStick.m_Y < -Inp::vANALOGUE_TOL ) ? ( m_leftStick.m_Y + Inp::vANALOGUE_TOL ) * scale : 0.0f;\r\n\t\tm_leftStick.m_X =\r\n\t\t\t( m_leftStick.m_X >  Inp::vANALOGUE_TOL ) ? ( m_leftStick.m_X - Inp::vANALOGUE_TOL ) * scale :\r\n\t\t\t( m_leftStick.m_X < -Inp::vANALOGUE_TOL ) ? ( m_leftStick.m_X + Inp::vANALOGUE_TOL ) * scale : 0.0f;\r\n\t\t\t\r\n\t\tfloat rel_shift_x = m_leftStick.m_X * elapsed_seconds * m_movement_vel;\r\n\t\tfloat rel_shift_z = m_leftStick.m_Y * elapsed_seconds * m_movement_vel;\r\n\t\tfloat angle_rad = m_camAngle * Mth::PI / 180.0f;\r\n\t\tfloat shift_x = cosf(angle_rad) * rel_shift_x + sinf(angle_rad) * rel_shift_z;\r\n\t\tfloat shift_z = cosf(angle_rad) * rel_shift_z - sinf(angle_rad) * rel_shift_x;\r\n\t\r\n\t\tm_rightStick.m_Y =\r\n\t\t\t( m_rightStick.m_Y >  Inp::vANALOGUE_TOL ) ? ( m_rightStick.m_Y - Inp::vANALOGUE_TOL ) * scale :\r\n\t\t\t( m_rightStick.m_Y < -Inp::vANALOGUE_TOL ) ? ( m_rightStick.m_Y + Inp::vANALOGUE_TOL ) * scale : 0.0f;\r\n\t\tm_rightStick.m_X =\r\n\t\t\t( m_rightStick.m_X >  Inp::vANALOGUE_TOL ) ? ( m_rightStick.m_X - Inp::vANALOGUE_TOL ) * scale :\r\n\t\t\t( m_rightStick.m_X < -Inp::vANALOGUE_TOL ) ? ( m_rightStick.m_X + Inp::vANALOGUE_TOL ) * scale : 0.0f;\r\n\t\r\n#ifdef __PLAT_NGC__DAN\r\n\t\tif ( !( m_commands.TestMask(mZOOM_CAMERA_IN) ) )\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t{\r\n\t\t\tm_camAngle += m_rightStick.m_X * elapsed_seconds * m_rotate_vel;\t\r\n\t\t}\r\n\t\tif (m_camAngle < 0) m_camAngle += 360.0f;\r\n\t\telse if (m_camAngle >= 360.0) m_camAngle -= 360.0f;\r\n#ifdef __PLAT_NGC__DAN\r\n\t\tif ( !( m_commands.TestMask(mZOOM_CAMERA_IN) ) )\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t{\r\n\t\t\tm_camAngleVert -= m_rightStick.m_Y * elapsed_seconds * m_rotate_vel;\t\r\n\t\t}\r\n\t\tif (m_camAngleVert < 10.0f) m_camAngleVert = 10.0f;\r\n\t\telse if (m_camAngleVert > 90.0) m_camAngleVert = 90.0f;\r\n\r\n\t\t/*\r\n\t\t\tPlayEdPlaceSound for placing items (might have wrong sound hooked up right now)\r\n\t\t\tPlayEdEraseSound  for removing items\r\n\t\t\tPlayRaiseGroundSound for raising\r\n\t\t\tPlayLowerGroundSound for lowering\r\n\t\t\tPlayRotatePieceSound for rotating both directions\r\n\t\t*/\r\n\t\t\r\n\t\tint rot_inc = 0;\r\n\t\tif (m_commands.TestMask(mROTATE_CW))\r\n\t\t{\r\n\t\t\tScript::RunScript(\"PlayRotatePieceSound\");\r\n\t\t\tif (mp_cursor->InGapMode())\r\n\t\t\t\tmp_cursor->AdjustGap(-1, 0, 0);\r\n\t\t\telse\r\n\t\t\t\trot_inc = -1;\r\n\t\t}\r\n\t\tif (m_commands.TestMask(mROTATE_CCW))\r\n\t\t{\r\n\t\t\tScript::RunScript(\"PlayRotatePieceSound\");\r\n\t\t\tif (mp_cursor->InGapMode())\r\n\t\t\t\tmp_cursor->AdjustGap(-1, 0, 0);\r\n\t\t\telse\r\n\t\t\t\trot_inc = 1;\r\n\t\t}\r\n\t\tif (m_commands.TestMask(mPLACE_PIECE))\r\n\t\t{\r\n\t\t\tif (mp_cursor->InGapMode())\r\n\t\t\t{\r\n\t\t\t\tbool success = mp_cursor->AttemptGap();\r\n\t\t\t\tif ((success || mp_cursor->IsSittingOnGap()) && !mp_cursor->HalfFinishedGap())\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(\"PlayEdPlaceSound\");\r\n\t\t\t\t\t// XXX\r\n\t\t\t\t\tRyan(\"the hell, you say\\n\");\r\n\t\t\t\t\tScript::RunScript(\"parked_setup_gap_menu\");\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t\tScript::RunScript(\"PlayEdBuzzSound\");\r\n\t\t\t\t\t\r\n\t\t\t\tm_allow_defrag=true;\r\n\t\t\t}\r\n\t\t\telse if (mp_cursor->InAreaSelectMode())\r\n\t\t\t{\r\n\t\t\t\tswitch (mp_cursor->AttemptAreaSelect())\r\n\t\t\t\t{\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\t// Maybe have a different sound for the first corner ?\r\n\t\t\t\t\tScript::RunScript(\"PlayEdPlaceSound\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tScript::RunScript(\"PlayEdPlaceSound\");\r\n\t\t\t\t\tScript::RunScript(\"parked_setup_area_select_menu\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tScript::RunScript(\"PlayEdBuzzSound\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// Note: Not setting m_allow_defrag here, because otherwise it may defrag\r\n\t\t\t\t// as soon as the user places one of the area corners, which becomes a pain\r\n\t\t\t\t// especially if trying to select a set of pieces to delete to free up memory.\r\n\t\t\t}\r\n\t\t\telse if (mp_cursor->InPasteMode())\r\n\t\t\t{\r\n\t\t\t\tmp_cursor->PasteCurrentClipboard();\r\n\t\t\t\tm_allow_defrag=true;\r\n\t\t\t}\r\n\t\t\telse\t\r\n\t\t\t{\r\n\t\t\t\tif (mp_cursor->AttemptStamp())\r\n\t\t\t\t\tScript::RunScript(\"PlayEdPlaceSound\");\r\n\t\t\t\telse\r\n\t\t\t\t\tScript::RunScript(\"PlayEdBuzzSound\");\r\n\t\t\t\tm_allow_defrag=true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (m_commands.TestMask(mREMOVE_PIECE))\r\n\t\t{\r\n\t\t\tif (mp_cursor->InGapMode())\r\n\t\t\t{\r\n\t\t\t\tif (mp_cursor->AttemptRemoveGap())\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(\"PlayEdEraseSound\");\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t\tScript::RunScript(\"PlayEdBuzzSound\");\r\n\t\t\t}\r\n\t\t\telse if (mp_cursor->InAreaSelectMode())\r\n\t\t\t{\r\n\t\t\t\tmp_cursor->ClearAreaSelection();\r\n\t\t\t\tm_allow_defrag=true;\r\n\t\t\t}\r\n\t\t\telse\t\r\n\t\t\t{\r\n\t\t\t\tif (mp_cursor->AttemptRemove())\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(\"PlayEdEraseSound\");\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(\"PlayEdBuzzSound\");\r\n\t\t\t\t}\r\n\t\t\t\tm_allow_defrag=true;\r\n\t\t\t}\r\n\t\t\t// and re register the gaps so that any old gaps are removed from the career.\r\n\t\t\tCGapManager::sInstance()->RegisterGapsWithSkaterCareer();\t\t\t\r\n\t\t}\r\n\t\t\r\n\t\tdo_piece_select_commands();\r\n\t\t\r\n\t\tif (m_commands.TestMask(mRAISE_FLOOR))\r\n\t\t{\r\n\t\t\tif (!mp_cursor->InGapMode())\r\n\t\t\t{\r\n\t\t\t\tif (mp_cursor->ChangeFloorHeight(1))\r\n\t\t\t\t\tScript::RunScript(\"PlayRaiseGroundSound\");\r\n\t\t\t\telse\r\n\t\t\t\t\tScript::RunScript(\"PlayEdBuzzSound\");\r\n\t\t\t}\r\n\t\t\tm_allow_defrag=true;\r\n\t\t}\r\n\t\tif (m_commands.TestMask(mLOWER_FLOOR))\r\n\t\t{\r\n\t\t\tif (!mp_cursor->InGapMode())\r\n\t\t\t{\r\n\t\t\t\tif (mp_cursor->ChangeFloorHeight(-1))\r\n\t\t\t\t\tScript::RunScript(\"PlayLowerGroundSound\");\r\n\t\t\t\telse\r\n\t\t\t\t\tScript::RunScript(\"PlayEdBuzzSound\");\r\n\t\t\t}\r\n\t\t\tm_allow_defrag=true;\r\n\t\t}\r\n\r\n#ifdef __PLAT_NGC__DAN\r\n\t\tif ( m_commands.TestMask(mZOOM_CAMERA_IN) )\r\n\t\t{\r\n\t\t\t// Use y component of stick to zoom camera in or out.\r\n\t\t\tm_camDist += vCAM_DIST_INC * m_rightStick.m_Y;\r\n\t\t\tif (m_camDist > vMAX_CAM_DIST)\r\n\t\t\t\tm_camDist = vMAX_CAM_DIST;\r\n\t\t\tif (m_camDist < vMIN_CAM_DIST)\r\n\t\t\t\tm_camDist = vMIN_CAM_DIST;\r\n\t\t}\r\n#else\r\n\t\tif (m_commands.TestMask(mZOOM_CAMERA_OUT) && !mp_cursor->InGapMode())\r\n\t\t{\r\n\t\t\tm_camDist += vCAM_DIST_INC;\r\n\t\t\tif (m_camDist > vMAX_CAM_DIST)\r\n\t\t\t\tm_camDist = vMAX_CAM_DIST;\r\n\t\t}\r\n\t\tif (m_commands.TestMask(mZOOM_CAMERA_IN) && !mp_cursor->InGapMode())\r\n\t\t{\r\n\t\t\tm_camDist -= vCAM_DIST_INC;\r\n\t\t\tif (m_camDist < vMIN_CAM_DIST)\r\n\t\t\t\tm_camDist = vMIN_CAM_DIST;\r\n\t\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\r\n\t\tif (m_commands.TestMask(mINCREASE_GAP_LEFT))\r\n\t\t{\r\n\t\t\tif (mp_cursor->InGapMode())\r\n\t\t\t\tmp_cursor->AdjustGap(0, 1, 0);\r\n\t\t}\r\n\t\tif (m_commands.TestMask(mINCREASE_GAP_RIGHT))\r\n\t\t{\r\n\t\t\tif (mp_cursor->InGapMode())\r\n\t\t\t\tmp_cursor->AdjustGap(0, 0, 1);\r\n\t\t}\r\n\t\tif (m_commands.TestMask(mDECREASE_GAP_LEFT))\r\n\t\t{\r\n\t\t\tif (mp_cursor->InGapMode())\r\n\t\t\t\tmp_cursor->AdjustGap(0, -1, 0);\r\n\t\t}\r\n\t\tif (m_commands.TestMask(mDECREASE_GAP_RIGHT))\r\n\t\t{\r\n\t\t\tif (mp_cursor->InGapMode())\r\n\t\t\t\tmp_cursor->AdjustGap(0, 0, -1);\r\n\t\t}\r\n\r\n\r\n\t\t// If an operation has occurred that has modified collidable geometry,\r\n\t\t// run through all the existing created-rails and update their posts so that they\r\n\t\t// maintain ground contact.\r\n\t\tif (m_commands.TestMask(mPLACE_PIECE) ||\r\n\t\t\tm_commands.TestMask(mREMOVE_PIECE) ||\r\n\t\t\tm_commands.TestMask(mRAISE_FLOOR) ||\r\n\t\t\tm_commands.TestMask(mLOWER_FLOOR))\r\n\t\t{\r\n\t\t\tObj::CRailEditorComponent *p_rail_editor=Obj::GetRailEditor();\r\n\t\t\tp_rail_editor->AdjustYs();\r\n\t\t\tp_rail_editor->UpdateRailGeometry();\r\n\t\t\tp_rail_editor->UpdatePostGeometry();\r\n\t\t\t\r\n\t\t\tObj::GetGoalEditor()->RefreshGoalPositionsUsingCollisionCheck();\r\n\t\t}\r\n\t\t\r\n\t\tmp_cursor->Update(shift_x, shift_z, rot_inc);\r\n\t\t//printf(\"cursor position: (%.2f,%.2f)\\n\", mp_cursor->m_target_pos[X], mp_cursor->m_target_pos[Z]);\t\t\r\n\t\t\r\n\t\tif (mp_cursor->InAreaSelectMode())\r\n\t\t{\r\n\t\t\tmp_cursor->RefreshSelectionArea();\r\n\t\t}\r\n\t\telse if (mp_cursor->InRailPlacementMode())\r\n\t\t{\r\n\t\t\tmp_cursor->DestroyGeometry();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Highlight the pieces intersecting the cursor after it has changed or moved\r\n\t\t\tmp_cursor->HighlightIntersectingMetas(true); \r\n\t\t}\t\r\n\t}\t\r\n}\r\n\r\nvoid CParkEditor::rail_placement_logic()\r\n{\r\n\tDbg_MsgAssert(mp_cursor,(\"NULL mp_cursor\"));\r\n\r\n\tif (!m_paused)\r\n\t{\r\n\t\tdo_piece_select_commands();\r\n\t}\r\n}\r\n\t\r\nvoid CParkEditor::Update()\r\n{\r\n\tif (!m_paused)\r\n\t{\r\n\t\tif (m_state == vEDITING)\r\n\t\t{\r\n\t\t\tScript::CStruct params;\r\n\t\t\tparams.AddChecksum(NONAME, Script::GenerateCRC(\"hide\"));\r\n\t\t\tCFuncs::ScriptPauseSkaters(&params, NULL);\r\n\t\t}\r\n\t\telse if (m_state == vTEST_PLAY)\r\n\t\t{\r\n\t\t\tCFuncs::ScriptUnPauseSkaters(NULL, NULL);\r\n\t\t}\r\n\t}\r\n\r\n\tif (m_state == vEDITING && mp_cursor)\r\n\t{\r\n\t\tif (!m_paused)\r\n\t\t{\r\n\t\t\tif (mp_cursor->InRailPlacementMode())\r\n\t\t\t{\r\n\t\t\t\tif (Obj::GetRailEditor()->IsSuspended())\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(CRCD(0x2c3b17ea,\"SwitchOnRailEditor\"));\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\trail_placement_logic();\r\n\t\t\t\t\r\n\t\t\t\tif (!mp_cursor->InRailPlacementMode())\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(CRCD(0x32428a49,\"SwitchOffRailEditor\"));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (!Obj::GetRailEditor()->IsSuspended())\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(CRCD(0x32428a49,\"SwitchOffRailEditor\"));\r\n\t\t\t\t}\r\n\t\t\t\tregular_command_logic();\r\n\t\t\t\tif (mp_cursor->InRailPlacementMode())\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(CRCD(0x2c3b17ea,\"SwitchOnRailEditor\"));\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t}\r\n\r\n\t\tif (!m_paused)\t\t\r\n\t\t{\r\n\t\t\tCParkGenerator *p_generator = mp_park_manager->GetGenerator();\r\n\t\t\tCParkGenerator::MemUsageInfo usage_info = p_generator->GetResourceUsageInfo();\r\n\t\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tif (Script::GetInteger(CRCD(0xcc55a87b,\"show_parked_main_heap_free\")))\r\n\t\t\t{\r\n\t\t\t\tprintf(\"usage_info.mMainHeapFree = %d   usage_info.mParkHeapFree=%d\\n\",usage_info.mMainHeapFree,usage_info.mParkHeapFree);\r\n\t\t\t}\t\r\n\t\t\t#endif\r\n\t\t\t\r\n\r\n\t\t\tif (usage_info.mMainHeapFree >= 0)\r\n\t\t\t{\r\n\t\t\t\tm_pct_resources_used=1.0f-((float)usage_info.mMainHeapFree)/((float)p_generator->GetResourceSize(\"main_heap_base\"));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\t\tprintf(\"Memory overflow! Gone over the end of the gauge by %d bytes\\n\",-usage_info.mMainHeapFree);\r\n\t\t\t\t#endif\r\n\t\t\t\tm_pct_resources_used=1.0f;\r\n\t\t\t}\t\r\n\r\n\t\t\tMem::Heap *p_bottom_up_heap = Mem::Manager::sHandle().BottomUpHeap();\r\n\t\t\tMem::Heap *p_top_down_heap = Mem::Manager::sHandle().TopDownHeap();\r\n\t\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t\tif (Script::GetInteger(CRCD(0xe2ca7dfc,\"show_actual_heap_status\")))\r\n\t\t\t{\r\n\t\t\t\tprintf(\"Bottom up = %d  Top down = %d\\n\",p_bottom_up_heap->mFreeMem.m_count,p_top_down_heap->mp_region->MemAvailable());\r\n\t\t\t}\t\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\t// top_down_pct is a metric based on the amount of top down heap available. The reason for the 2.0 is to\r\n\t\t\t// make the top_down_pct be >= 1.0 if there is less than TOP_DOWN_REQUIRED_MARGIN available, and < 1.0\r\n\t\t\t// if there is more than that available.\r\n\t\t\tfloat top_down_pct=2.0f-(((float)p_top_down_heap->mp_region->MemAvailable()) / ((float)TOP_DOWN_REQUIRED_MARGIN));\r\n\t\t\tif (top_down_pct > m_pct_resources_used)\r\n\t\t\t{\r\n\t\t\t\tm_pct_resources_used = top_down_pct;\r\n\t\t\t}\t\r\n\r\n\r\n\t\t\tfloat park_heap_pct=1.0f-((float)usage_info.mParkHeapFree)/((float)p_generator->GetResourceSize(\"park_heap_base\"));\r\n\t\t\tif (park_heap_pct > m_pct_resources_used)\r\n\t\t\t{\r\n\t\t\t\tm_pct_resources_used=park_heap_pct;\r\n\t\t\t}\t\r\n\r\n\t\t\tm_last_main_heap_free=usage_info.mMainHeapFree;\r\n\r\n\t\t\t//printf(\"2: m_pct_resources_used = %f\\n\",m_pct_resources_used);\r\n\t\t\t\r\n\t\t\t//float rail_point_pct = (float) usage_info.mTotalRailPoints / (float) (p_generator->GetResourceSize(\"out_railpoint_pool\") - 25);\r\n\t\t\tint component_use_est = usage_info.mTotalClonedPieces * 7 + usage_info.mTotalRailPoints * 9 + usage_info.mTotalLinkedRailPoints;\r\n\t\t\tint base_component_use = p_generator->GetResourceSize(\"component_use_base\");\r\n\t\t\tfloat component_pct = (float) (component_use_est - base_component_use) / (float) (p_generator->GetResourceSize(\"max_components\") - base_component_use);\r\n\t\t\tif (m_pct_resources_used < component_pct)\r\n\t\t\t\tm_pct_resources_used = component_pct;\r\n\t\t\t//printf(\"component_use_est=%d\\n\",component_use_est);\r\n\t\t\t//ParkEd(\"3: m_pct_resources_used=%f\",m_pct_resources_used);\r\n\t\t\t\r\n\t\t\tint vector_use_est = usage_info.mTotalClonedPieces * 2 + usage_info.mTotalRailPoints * 2;\r\n\t\t\tint base_vector_use = p_generator->GetResourceSize(\"vector_use_base\");\r\n\t\t\tfloat vector_pct = (float) (vector_use_est - base_vector_use) / (float) (p_generator->GetResourceSize(\"max_vectors\") - base_vector_use);\r\n\t\t\tif (m_pct_resources_used < vector_pct)\r\n\t\t\t\tm_pct_resources_used = vector_pct;\r\n\t\t\t//printf(\"vector_use_est=%d\\n\",vector_use_est);\t\r\n\t\t\t//ParkEd(\"4: m_pct_resources_used=%f\",m_pct_resources_used);\r\n\t\t\t//printf(\"3: m_pct_resources_used = %f\\n\",m_pct_resources_used);\r\n\r\n\t\t\tfloat pieces_pct=(float)mp_park_manager->GetDMAPieceCount() / (float)p_generator->GetResourceSize(\"max_dma_pieces\");\r\n\t\t\tif (pieces_pct > m_pct_resources_used)\r\n\t\t\t{\r\n\t\t\t\tm_pct_resources_used = pieces_pct;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t//printf(\"4: m_pct_resources_used = %f IsParkFull=%d\\n\",m_pct_resources_used,IsParkFull());\r\n\t\t\t\r\n\t\t\tfloat shown_pct_resources_used = m_pct_resources_used;\r\n\t\t\tif (shown_pct_resources_used < 0.0f) shown_pct_resources_used = 0.0f;\r\n\t\t\telse if (shown_pct_resources_used > 1.0f) shown_pct_resources_used = 1.0f;\r\n\r\n\r\n\r\n\t\t\tbool do_defragment=false;\r\n\t\t\t\r\n\t\t\t// Don't defrag if in rail placement mode, cos the resulting mode switch causes an assert.\r\n\t\t\tif (mp_cursor->InRailPlacementMode())\r\n\t\t\t{\r\n\t\t\t\tm_allow_defrag=false;\r\n\t\t\t}\r\n\t\t\t// m_allow_defrag is a flag that gets set by any operation that may have increased\r\n\t\t\t// memory usage, such as placing a piece, or raising the ground.\r\n\t\t\t// It is required to prevent an infinite loop of defrags which could occur if defrags\r\n\t\t\t// were allowed every frame.\r\n\t\t\t\r\n\t\t\tif (shown_pct_resources_used >= 1.0f && p_top_down_heap->mp_region->MemAvailable() < TOP_DOWN_REQUIRED_MARGIN)\r\n\t\t\t{\r\n\t\t\t\t// We're in trouble, there may not be enough top down heap for UpdateSuperSectors\r\n\t\t\t\t// to execute. This can happen if trying to raise a large chunk of ground.\r\n\t\t\t\tif (p_bottom_up_heap->mFreeMem.m_count + p_top_down_heap->mp_region->MemAvailable() > (TOP_DOWN_REQUIRED_MARGIN + TOP_DOWN_REQUIRED_MARGIN_LEEWAY))\r\n\t\t\t\t{\r\n\t\t\t\t\t// ... but there would be more than enough if all the fragments could be utilised,\r\n\t\t\t\t\t// so do a defragment to see if that helps.\r\n\t\t\t\t\tif (m_allow_defrag)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdo_defragment=true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\r\n\t\t\t\r\n\t\t\t// The old logic from THPS4, which would only defrag if this flag was set.\r\n\t\t\t/*\r\n\t\t\tif (usage_info.mIsFragmented)\r\n\t\t\t{\r\n\t\t\t\tif (m_allow_defrag)\r\n\t\t\t\t{\r\n\t\t\t\t\tdo_defragment=true;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\t*/\r\n\r\n\t\t\tm_allow_defrag=false;\r\n\t\t\t\r\n\t\t\tif (do_defragment)\r\n\t\t\t{\r\n\t\t\t\t#ifdef __PLAT_NGC__\r\n\t\t\t\t// The regular defragment script often does not fully cure the fragmentation, which\r\n\t\t\t\t// is a problem on the NGC because of its lower memory. So do a full reload instead.\r\n\t\t\t\tScript::SpawnScript(CRCD(0x57c05a9a,\"reload_park\"));\r\n\t\t\t\t#else\r\n\t\t\t\t\t// XXX\r\n\t\t\t\t\tRyan(\"defragging, memory free (largest block) is %d\\n\", usage_info.mMainHeapFree);\r\n\t\t\t\t\tSetPaused(true);\r\n\t\t\t\t\t// run a script to defragment memory\r\n\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\tScript::CScript *p_script=Script::SpawnScript(\"parked_defragment_memory\");\r\n\t\t\t\t\tp_script->SetCommentString(\"Spawned by CParkEditor::Update()\");\r\n\t\t\t\t\t#else\r\n\t\t\t\t\tScript::SpawnScript(\"parked_defragment_memory\");\r\n\t\t\t\t\t#endif\r\n\t\t\t\t#endif\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\r\n\r\n\t\t\t// percent_bar_colored_part\r\n\t\t\tFront::CScreenElementManager* p_elem_man = Front::CScreenElementManager::Instance();\r\n\t\t\tFront::CScreenElement *p_pct_bar = p_elem_man->GetElement(CRCD(0xcd9c729a, \"percent_bar_colored_part\"), Front::CScreenElementManager::DONT_ASSERT).Convert();\r\n\t\t\tif (p_pct_bar)\r\n\t\t\t\tp_pct_bar->SetScale(shown_pct_resources_used, 1.0f, false, Front::CScreenElement::FORCE_INSTANT);\r\n\r\n\t\t\tif (Script::GetInteger(CRCD(0x7a9c1acd,\"parked_show_memory_stats\")))\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript(CRCD(0xb935948d,\"CreateMemStatsScreenElements\"));\r\n\t\t\t\t\r\n\t\t\t\tFront::CScreenElementManager* p_elem_man = Front::CScreenElementManager::Instance();\r\n\t\t\t\tFront::CTextElement *p_park_free_elem = (Front::CTextElement *) p_elem_man->GetElement(CRCD(0xa5a33eb9, \"parked_mem_stats_park_free\"), Front::CScreenElementManager::ASSERT).Convert();\r\n\t\t\t\tchar park_free_text[128];\r\n\t\t\t\tsprintf(park_free_text, \"park heap free:\\\\c2 %s\", Str::PrintThousands(usage_info.mParkHeapFree));\r\n\t\t\t\tp_park_free_elem->SetText(park_free_text);\r\n\t\r\n\t\t\t\tFront::CTextElement *p_main_free_elem = (Front::CTextElement *) p_elem_man->GetElement(CRCD(0xcd38c218, \"parked_mem_stats_main_free\"), Front::CScreenElementManager::ASSERT).Convert();\r\n\t\t\t\tchar main_free_text[128];\r\n\t\t\t\tif (usage_info.mIsFragmented)\r\n\t\t\t\t\tsprintf(main_free_text, \"main heap free:\\\\c2 %s \\\\c1FRAG\", Str::PrintThousands(usage_info.mMainHeapFree));\r\n\t\t\t\telse\r\n\t\t\t\t\tsprintf(main_free_text, \"main heap free:\\\\c2 %s\", Str::PrintThousands(usage_info.mMainHeapFree));\r\n\t\t\t\tp_main_free_elem->SetText(main_free_text);\r\n\t\r\n\t\t\t\tFront::CTextElement *p_last_op_elem = (Front::CTextElement *) p_elem_man->GetElement(CRCD(0x9dd4532f, \"parked_mem_stats_last_op\"), Front::CScreenElementManager::ASSERT).Convert();\r\n\t\t\t\tchar last_op_text[128];\r\n\t\t\t\tsprintf(last_op_text, \"last op size:\\\\c2 %d\", usage_info.mMainHeapUsed - usage_info.mLastMainUsed);\r\n\t\t\t\tp_last_op_elem->SetText(last_op_text);\r\n\t\r\n\t\t\t\tFront::CTextElement *p_other_elem = (Front::CTextElement *) p_elem_man->GetElement(CRCD(0xb42704a3, \"parked_mem_stats_other\"), Front::CScreenElementManager::ASSERT).Convert();\r\n\t\t\t\tchar other_text[128];\r\n\t\t\t\tsprintf(other_text, \"components free:\\\\c2 %d %d\", \r\n\t\t\t\t\t\tp_generator->GetResourceSize(\"max_components\") - component_use_est - base_component_use,\r\n\t\t\t\t\t\tp_generator->GetResourceSize(\"max_vectors\") - vector_use_est - base_vector_use);\r\n\t\t\t\tp_other_elem->SetText(other_text);\r\n\t\r\n\t\t\t\tFront::CTextElement *p_pct_elem = (Front::CTextElement *) p_elem_man->GetElement(CRCD(0x65f2394f, \"parked_mem_stats_pct\"), Front::CScreenElementManager::ASSERT).Convert();\r\n\t\t\t\tchar pct_text[128];\r\n\t\t\t\tsprintf(pct_text, \"pct:\\\\c3 %.2f\", m_pct_resources_used * 100.0f);\r\n\t\t\t\tp_pct_elem->SetText(pct_text);\r\n\t\r\n\t\t\t\tFront::CTextElement *p_pieces_remaining_elem = (Front::CTextElement *) p_elem_man->GetElement(CRCD(0x3da56dac, \"parked_mem_pieces_remaining\"), Front::CScreenElementManager::ASSERT).Convert();\r\n\t\t\t\tchar pieces_remaining_text[128];\r\n\t\t\t\tsprintf(pieces_remaining_text, \"pieces remaining:\\\\c2 %d\", p_generator->GetResourceSize(\"max_dma_pieces\") - mp_park_manager->GetDMAPieceCount());\r\n\t\t\t\tp_pieces_remaining_elem->SetText(pieces_remaining_text);\r\n\r\n\t\t\t\tFront::CTextElement *p_main_used_elem = (Front::CTextElement *) p_elem_man->GetElement(CRCD(0xf95160c8, \"parked_mem_stats_main_used\"), Front::CScreenElementManager::ASSERT).Convert();\r\n\t\t\t\tchar main_used_text[128];\r\n\t\t\t\tsprintf(main_used_text, \"main heap used:\\\\c2 %s\", Str::PrintThousands(usage_info.mMainHeapUsed));\r\n\t\t\t\tp_main_used_elem->SetText(main_used_text);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript(CRCD(0x7a449180,\"DestroyMemStatsScreenElements\"));\r\n\t\t\t}\t\r\n\r\n\t\t\t// Update the clipboard usage bar.\t\t\t\r\n\t\t\t/*\r\n\t\t\tFront::CScreenElement *p_clipboard_percent_bar = p_elem_man->GetElement(CRCD(0xf07100ce,\"clipboard_percent_bar_colored_part\"), Front::CScreenElementManager::DONT_ASSERT).Convert();\r\n\t\t\tif (p_clipboard_percent_bar)\r\n\t\t\t{\r\n\t\t\t\tp_clipboard_percent_bar->SetScale(mp_park_manager->GetClipboardProportionUsed(), 1.0f, false, Front::CScreenElement::FORCE_INSTANT);\r\n\t\t\t}\r\n\t\t\t*/\r\n\t\t} // end if (!m_paused)\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_commands.ClearAll();\r\n\t}  \r\n}\r\n\r\nvoid CParkEditor::SwitchMenuPieceToMostRecentClipboard()\r\n{\r\n\tCCursor::sInstance()->SwitchMenuPieceToMostRecentClipboard();\r\n\t\r\n\tturn_on_or_update_piece_menu();\r\n\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\tp_tracker->LaunchEvent(Script::GenerateCRC(\"parked_menu_up\"), Script::GenerateCRC(\"set_menu_container\"));\r\n}\r\n\r\n// Returns true if there is enough memory to copy or paste an area of the given size.\r\nbool CParkEditor::RoomToCopyOrPaste(int w, int l)\r\n{\r\n\t#ifdef __PLAT_NGC__\r\n\tMem::Heap *p_top_down_heap = Mem::Manager::sHandle().TopDownHeap();\r\n\tif (p_top_down_heap->mp_region->MemAvailable() < TOP_DOWN_REQUIRED_MARGIN)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\t#endif\r\n\t\r\n\t// Assumes that in the worst case 1 cell uses up 40K, for example when a bunch of fountain pieces are raised\r\n\t// to the maximum height.\r\n\treturn w * l * 40000 < m_last_main_heap_free;\r\n}\r\n\r\nvoid CParkEditor::SetPaused(bool paused)\r\n{\r\n\t// XXX\r\n\tRyan(\"some fucker has made my pause state = %d\\n\", paused);\r\n\tm_paused = paused;\r\n\r\n\tif (mp_menu_manager)\r\n\t{\r\n\t\tif (paused)\r\n\t\t{\r\n\t\t\tScript::RunScript(\"parked_kill_wait_message\");\r\n\t\t\tmp_menu_manager->Disable();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_menu_manager->Enable();\r\n\t\t\tturn_on_or_update_piece_menu();\r\n\t\t}\r\n\t}\r\n\r\n\tif (mp_cursor)\r\n\t{\r\n\t\tif (mp_cursor->InRailPlacementMode())\r\n\t\t{\r\n\t\t\tmp_cursor->SetVisibility(false);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (paused)\r\n\t\t\t{\r\n\t\t\t\tmp_cursor->SetVisibility(false);\r\n\t\t\t}\t\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmp_cursor->SetVisibility(true);\r\n\t\t\t}\t\t\r\n\t\t}\t\r\n\t\tmp_cursor->RefreshHelperText();\r\n\t}\t\r\n\r\n\tupdate_analog_stick_menu_control_state();\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::turn_on_or_update_piece_menu()\r\n{\r\n\tint menu_set_number;\r\n\tint set_num = mp_cursor->GetSelectedSet(&menu_set_number);\r\n\t// XXX\r\n\tRyan(\"piece set number is %d\\n\", set_num);\r\n\tDbg_Assert(mp_menu_manager);\r\n\tmp_menu_manager->SetPieceSet(&mp_park_manager->GetPieceSet(set_num), set_num, menu_set_number);\r\n\t\r\n\tif (mp_cursor)\r\n\t{\r\n\t\tmp_cursor->RefreshHelperText();\r\n\t}\t\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::update_analog_stick_menu_control_state()\r\n{\r\n\tSpt::SingletonPtr<Mdl::FrontEnd> p_front_end;\t\r\n\tif (m_state == vEDITING && !m_paused)\r\n\t{\r\n\t\tp_front_end->SetAnalogStickActiveForMenus(false);\r\n\t}\r\n\telse\r\n\t\tp_front_end->SetAnalogStickActiveForMenus(true);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::pass_event_to_listener(Obj::CEvent *pEvent)\r\n{\r\n\tif (m_state != vEDITING || !mp_cursor || m_paused)\r\n\t\treturn;\r\n\t\r\n\tuint32 type = pEvent->GetType();\r\n\tuint32 target = pEvent->GetTarget();\r\n\r\n\tif (target != CRCD(0x56a1eae3, \"root_window\"))\r\n\t\treturn;\r\n\r\n#ifdef __PLAT_NGC__\r\n\tif ( m_commands.TestMask( mINCREASE_GAP_RIGHT ) ) return;\r\n\tif ( m_commands.TestMask( mDECREASE_GAP_RIGHT ) ) return;\r\n\tif ( m_commands.TestMask( mINCREASE_GAP_LEFT ) ) return;\r\n\tif ( m_commands.TestMask( mDECREASE_GAP_LEFT ) ) return;\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\tswitch(type)\r\n\t{\r\n\t\tcase Obj::CEvent::TYPE_PAD_UP:\r\n\t\t\tm_commands.SetMask( mPREV_SET );\r\n\t\t\tbreak;\r\n\t\tcase Obj::CEvent::TYPE_PAD_DOWN:\r\n\t\t\tm_commands.SetMask( mNEXT_SET );\r\n\t\t\tbreak;\r\n\t\tcase Obj::CEvent::TYPE_PAD_LEFT:\r\n\t\t\tm_commands.SetMask( mPREV_PIECE );\r\n\t\t\tbreak;\r\n\t\tcase Obj::CEvent::TYPE_PAD_RIGHT:\r\n\t\t\tm_commands.SetMask( mNEXT_PIECE );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\t//Ryan(\"I got an event!!\\n\");\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::v_start_cb()\r\n{\r\n\t\r\n\tRyan(\"CParkEditor2::v_start_cb\\n\");\r\n\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance(); \r\n\tmlp_manager->AddLogicTask ( *m_logic_task );\r\n\tInp::Manager * inp_manager = Inp::Manager::Instance(); \r\n\tinp_manager->AddHandler( *m_input_handler );\r\n\tmlp_manager->AddDisplayTask ( *m_display_task );\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::v_stop_cb()\r\n{\r\n\tRyan(\"CParkEditor2::v_stop_cb\\n\");\r\n\r\n\tm_logic_task->Remove();\r\n\tm_input_handler->Remove();\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::s_input_logic_code ( const Inp::Handler < CParkEditor >& handler )\r\n{\r\n\tCParkEditor &mdl = handler.GetData();\r\n\t// first clear last frame's data\r\n\tmdl.m_commands.ClearAll();\r\n\r\n\t//if (!mdl.mp_map || mdl.GameGoingOrOutsideEditor() || mdl.InMenu() || !mdl.m_initialized) return;\r\n\t\r\n\t// translate m_Input data to module-specific commands\r\n\tmdl.m_rightStick.m_X = handler.m_Input->m_Event[Inp::Data::vA_RIGHT_X] - 128;\r\n\tmdl.m_rightStick.m_Y = handler.m_Input->m_Event[Inp::Data::vA_RIGHT_Y] - 128;\r\n\tmdl.m_leftStick.m_X = handler.m_Input->m_Event[Inp::Data::vA_LEFT_X] - 128;\r\n\tmdl.m_leftStick.m_Y = handler.m_Input->m_Event[Inp::Data::vA_LEFT_Y] - 128;\r\n\r\n#ifdef __PLAT_NGC__\r\n\tif( handler.m_Input->m_Makes & Inp::Data::mD_TRIANGLE )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mROTATE_CCW );\r\n\t}\r\n#else\r\n\tif( handler.m_Input->m_Makes & Inp::Data::mD_SQUARE )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mROTATE_CCW );\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\tif( handler.m_Input->m_Makes & Inp::Data::mD_CIRCLE )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mROTATE_CW );\r\n\t}\r\n\tif( handler.m_Input->m_Makes & Inp::Data::mD_X )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mPLACE_PIECE );\r\n\t}\r\n#ifdef __PLAT_NGC__\r\n\tif( handler.m_Input->m_Makes & Inp::Data::mD_SQUARE )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mREMOVE_PIECE );\r\n\t}\r\n#else\r\n\tif( handler.m_Input->m_Makes & Inp::Data::mD_TRIANGLE )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mREMOVE_PIECE );\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n#ifdef __PLAT_NGC__\r\n\tif( !(handler.m_Input->m_Buttons & Inp::Data::mD_Z) )\r\n\t{\r\n\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_L1 )\r\n\t\t{\r\n\t\t\tmdl.m_commands.SetMask( mRAISE_FLOOR );\r\n\t\t}\r\n\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_R1 )\r\n\t\t{\r\n\t\t\tmdl.m_commands.SetMask( mLOWER_FLOOR );\r\n\t\t}\r\n\t}\r\n#else\r\n\tif( handler.m_Input->m_Makes & Inp::Data::mD_L1 )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mRAISE_FLOOR );\r\n\t}\r\n\tif( handler.m_Input->m_Makes & Inp::Data::mD_L2 )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mLOWER_FLOOR );\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n#ifdef __PLAT_NGC__\r\n\tif( ( handler.m_Input->m_Makes & Inp::Data::mD_UP ) && ( handler.m_Input->m_Buttons & Inp::Data::mD_R1 ) )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mINCREASE_GAP_RIGHT );\r\n\t}\r\n\tif( ( handler.m_Input->m_Makes & Inp::Data::mD_DOWN ) && ( handler.m_Input->m_Buttons & Inp::Data::mD_R1 ) )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mDECREASE_GAP_RIGHT );\r\n\t}\r\n\tif( ( handler.m_Input->m_Makes & Inp::Data::mD_UP ) && ( handler.m_Input->m_Buttons & Inp::Data::mD_L1 ) )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mINCREASE_GAP_LEFT );\r\n\t}\r\n\tif( ( handler.m_Input->m_Makes & Inp::Data::mD_DOWN ) && ( handler.m_Input->m_Buttons & Inp::Data::mD_L1 ) )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mDECREASE_GAP_LEFT );\r\n\t}\r\n#else\r\n\t#ifdef __PLAT_XBOX__\r\n\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_L1 )\r\n\t\t{\r\n\t\t\tmdl.m_commands.SetMask( mINCREASE_GAP_RIGHT );\r\n\t\t}\r\n\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_L2 )\r\n\t\t{\r\n\t\t\tmdl.m_commands.SetMask( mDECREASE_GAP_RIGHT );\r\n\t\t}\r\n\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_BLACK )\r\n\t\t{\r\n\t\t\tmdl.m_commands.SetMask( mINCREASE_GAP_LEFT );\r\n\t\t}\r\n\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_WHITE )\r\n\t\t{\r\n\t\t\tmdl.m_commands.SetMask( mDECREASE_GAP_LEFT );\r\n\t\t}\r\n\t#else\r\n\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_R1 )\r\n\t\t{\r\n\t\t\tmdl.m_commands.SetMask( mINCREASE_GAP_RIGHT );\r\n\t\t}\r\n\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_R2 )\r\n\t\t{\r\n\t\t\tmdl.m_commands.SetMask( mDECREASE_GAP_RIGHT );\r\n\t\t}\r\n\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_L1 )\r\n\t\t{\r\n\t\t\tmdl.m_commands.SetMask( mINCREASE_GAP_LEFT );\r\n\t\t}\r\n\t\tif( handler.m_Input->m_Makes & Inp::Data::mD_L2 )\r\n\t\t{\r\n\t\t\tmdl.m_commands.SetMask( mDECREASE_GAP_LEFT );\r\n\t\t}\r\n\t#endif\r\n\t\r\n#endif\t\t// __PLAT_NGC__\r\n#ifdef __PLAT_NGC__\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_Z )\r\n\t{\r\n\t\tif( handler.m_Input->m_Buttons & Inp::Data::mD_L1 )\r\n\t\t{\r\n\t\t\tmdl.m_commands.SetMask( mZOOM_CAMERA_IN );\r\n\t\t}\r\n\t\tif( handler.m_Input->m_Buttons & Inp::Data::mD_R1 )\r\n\t\t{\r\n\t\t\tmdl.m_commands.SetMask( mZOOM_CAMERA_OUT );\r\n\t\t}\r\n\t}\r\n#else\r\n#ifdef __PLAT_XBOX__\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_BLACK )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mZOOM_CAMERA_OUT );\r\n\t}\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_WHITE )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mZOOM_CAMERA_IN );\r\n\t}\r\n#else\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_R1 )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mZOOM_CAMERA_OUT );\r\n\t}\r\n\tif( handler.m_Input->m_Buttons & Inp::Data::mD_R2 )\r\n\t{\r\n\t\tmdl.m_commands.SetMask( mZOOM_CAMERA_IN );\r\n\t}\r\n#endif\t\t// __PLAT_XBOX__\t\r\n#endif\t\t// __PLAT_NGC__\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::s_logic_code ( const Tsk::Task< CParkEditor >& task )\r\n{\r\n\t\r\n\r\n\tCParkEditor &mdl = task.GetData();\r\n\t//if (mdl.mp_commandParams)\r\n\t//\tmdl.runCommand();\t\r\n\t//if (!mdl.mp_map || mdl.GameGoingOrOutsideEditor() || !mdl.m_initialized) return;\r\n\r\n\t/*\r\n\t// put skater up in air HACK\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater *pSkater = skate_mod->GetLocalSkater();\r\n\tif (pSkater)\r\n\t\tpSkater->m_pos.Set(4000.0f, 4000.0f, 0.0f);\r\n\t*/\r\n\t\r\n\tTmr::Time elapsed_time;\r\n\tstatic Tmr::Time last_time = 0;\r\n\t\r\n\telapsed_time = Tmr::ElapsedTime( last_time );\r\n\tlast_time = last_time + elapsed_time;   \r\n\t\r\n\tmdl.Update();\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkEditor::s_display_code ( const Tsk::Task< CParkEditor >& task )\r\n{\r\n\t//CParkEditor &mdl = task.GetData();\r\n\t//if (!mdl.mp_map || mdl.GameGoingOrOutsideEditor() || !mdl.m_initialized) return;\r\n\t\r\n\t//mdl.Draw();\r\n}\r\n\r\nvoid CParkEditor::BindParkEditorToController( int controller )\r\n{\r\n\tSpt::SingletonPtr< Inp::Manager > inp_manager;\r\n\tinp_manager->ReassignHandler( *m_input_handler, controller );\r\n}\r\n\r\nMth::Vector& CParkEditor::GetCursorPos()\r\n{\r\n\tDbg_MsgAssert(mp_cursor,(\"NULL mp_cursor\"));\r\n\treturn mp_cursor->m_pos;\r\n}\r\n\r\nvoid CParkEditor::DestroyClipboardsWhichAreTooBigToFit()\r\n{\r\n\tif (mp_cursor)\r\n\t{\r\n\t\tmp_cursor->DestroyClipboardsWhichAreTooBigToFit();\r\n\t}\t\r\n}\r\n\r\nvoid CParkEditor::SetTimeOfDayScript(uint32 tod_script)\r\n{\r\n\tm_tod_script=tod_script;\r\n}\t\r\n\r\nCCursor *CCursor::sp_instance = NULL;\r\nconst float CCursor::MOTION_PCT_INC = .15f;\r\nconst float CCursor::ROT_DEG_INC = 15.0f;\r\n\r\n\r\n\r\n\r\nCCursor::CCursor() :\r\n\tm_cell_dims(0, 0, 0),\r\n\tm_target_pos(0.0f, 0.0f, 0.0f),\r\n\tm_pos(0.0f, 0.0f, 0.0f),\r\n\tm_hard_rot(Mth::ROT_0),\r\n\tm_target_rot(0.0f),\r\n\tm_rot(0.0f),\r\n\tmp_meta(NULL)\r\n{\r\n\tm_num_corners_selected=0;\r\n\tm_initialised_highlight=false;\r\n\t\r\n\tmp_clipboards=NULL;\r\n\tmp_current_clipboard=NULL;\r\n\t\r\n\tm_hard_rot = Mth::ROT_0;\r\n\r\n\tm_motion_pct = 1.0f;\r\n\r\n\tm_selected_set = 0;\r\n\tm_menu_set_number = 0;\r\n\t\r\n\tm_current_gap.numCompleteHalves = 0;\r\n\tm_current_gap.mCancelFlags=0;\r\n\t\r\n\tm_mode = NONE;\r\n\t\r\n\tCParkManager::CPieceSet &piece_set = m_manager->GetPieceSet(m_selected_set, &m_menu_set_number);\r\n\tset_source_meta(piece_set.mEntryTab[piece_set.mSelectedEntry].mNameCrc);\r\n\r\n\tm_gap_suffix_counter=1;\r\n\t\r\n\tsp_instance = this;\r\n}\r\n\r\nCCursor::~CCursor()\r\n{\r\n\t#ifndef DONT_USE_CURSOR_META\r\n\tif (mp_meta)\r\n\t{\r\n\t\tmp_meta->MarkUnlocked();\r\n\t\tm_manager->DestroyConcreteMeta(mp_meta, CParkManager::mDONT_DESTROY_PIECES_ABOVE);\r\n\t}\r\n\t\r\n\t#endif\r\n\r\n\tdestroy_clipboards();\r\n\t\r\n\tsp_instance = NULL;\r\n}\r\n\r\n// K: Added to test something\r\nvoid CCursor::DeleteMeta()\r\n{\r\n\tif (mp_meta)\r\n\t{\r\n\t\tdelete mp_meta;\r\n\t\tmp_meta=NULL;\r\n\t}\r\n}\r\n\t\t\r\nvoid CCursor::destroy_clipboards()\r\n{\r\n\tCClipboard *p_clipboard=mp_clipboards;\r\n\twhile (p_clipboard)\r\n\t{\r\n\t\tCClipboard *p_next=p_clipboard->mpNext;\r\n\t\tdelete p_clipboard;\r\n\t\tp_clipboard=p_next;\r\n\t}\t\r\n\tmp_current_clipboard=NULL;\r\n}\r\n\r\n// Called when the park is resized.\r\nvoid CCursor::DestroyClipboardsWhichAreTooBigToFit()\r\n{\r\n\tCClipboard *p_last=NULL;\r\n\tCClipboard *p_clipboard=mp_clipboards;\r\n\twhile (p_clipboard)\r\n\t{\r\n\t\tCClipboard *p_next=p_clipboard->mpNext;\r\n\t\t\r\n\t\tGridDims area;\r\n\t\tp_clipboard->GetArea(this,&area);\r\n\r\n\t\tif (area.GetW() > m_manager->GetParkNearBounds().GetW() ||\r\n\t\t\tarea.GetW() > m_manager->GetParkNearBounds().GetL() ||\r\n\t\t\tarea.GetL() > m_manager->GetParkNearBounds().GetW() ||\r\n\t\t\tarea.GetL() > m_manager->GetParkNearBounds().GetL())\r\n\t\t{\r\n\t\t\tif (p_last)\r\n\t\t\t{\r\n\t\t\t\tp_last->mpNext=p_next;\r\n\t\t\t}\t\r\n\t\t\tif (p_clipboard==mp_clipboards)\r\n\t\t\t{\r\n\t\t\t\tmp_clipboards=p_next;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tdelete p_clipboard;\r\n\t\t\tp_clipboard=p_next;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_last=p_clipboard;\r\n\t\t\tp_clipboard=p_next;\r\n\t\t}\t\r\n\t}\t\r\n\t\r\n\tmp_current_clipboard=mp_clipboards;\r\n\r\n\t// Refresh since mp_current_clipboard has changed.\r\n\tChangePieceInSet(0);\r\n}\r\n\r\nvoid CCursor::DestroyGeometry()\r\n{\r\n\tif (mp_meta)\r\n\t{\r\n\t\tmp_meta->MarkUnlocked();\r\n\t\tm_manager->DestroyConcreteMeta(mp_meta, CParkManager::mDONT_DESTROY_PIECES_ABOVE);\r\n\t\tmp_meta = NULL;\r\n\t}\r\n}\r\n\r\nvoid CCursor::DestroyAnyClipboardCursors()\r\n{\r\n\tCClipboard *p_clipboard=mp_clipboards;\r\n\twhile (p_clipboard)\r\n\t{\r\n\t\tp_clipboard->DestroyMetas();\r\n\t\tp_clipboard=p_clipboard->mpNext;\r\n\t}\t\r\n}\r\n\r\nvoid CCursor::Update(float shiftX, float shiftZ, int rotInc)\r\n{\r\n\t/*\r\n\t\t==================================================\r\n\t\tROTATION SECTION\r\n\t\t==================================================\r\n\t*/\r\n\t\r\n\tif (rotInc > 0)\r\n\t{\r\n\t\tm_hard_rot = Mth::ERot90((m_hard_rot + 1) & 3);\r\n\t\tm_target_rot += 90.0f;\r\n\t\tif (m_target_rot > 360.0f)\r\n\t\t{\r\n\t\t\tm_target_rot -= 360.0f;\r\n\t\t\tm_rot -= 360.0f;\r\n\t\t}\r\n\t\tm_cell_dims.SetWHL(m_cell_dims.GetL(), m_cell_dims.GetH(), m_cell_dims.GetW());\r\n\t}\r\n\telse if (rotInc < 0)\r\n\t{\r\n\t\tm_hard_rot = Mth::ERot90((m_hard_rot - 1) & 3);\r\n\t\tm_target_rot -= 90.0f;\r\n\t\tif (m_target_rot < 0.0f)\r\n\t\t{\r\n\t\t\tm_target_rot += 360.0f;\r\n\t\t\tm_rot += 360.0f;\r\n\t\t}\r\n\t\tm_cell_dims.SetWHL(m_cell_dims.GetL(), m_cell_dims.GetH(), m_cell_dims.GetW());\r\n\t}\r\n\r\n\t/*\r\n\t\t==================================================\r\n\t\tCELL POSITIONING SECTION\r\n\t\t==================================================\r\n\t*/\r\n\t\r\n\tconst float near_zero = .0001f;\r\n\t//const float tolerance = .5f;\r\n\t\r\n\tfloat shift_x_squared = shiftX * shiftX;\r\n\tfloat shift_z_squared = shiftZ * shiftZ;\r\n\r\n\tbool actual_shift = (shift_x_squared > near_zero * near_zero || shift_z_squared > near_zero * near_zero);\r\n\t\r\n\t// can't shift to new cell if cursor currently in motion\r\n\tif (actual_shift && m_motion_pct <= 0.0f)\r\n\t{\r\n\t\tif (shift_z_squared > 5.8284f * shift_x_squared)\r\n\t\t{\r\n\t\t\tif (shiftZ < 0.0f)\r\n\t\t\t\tchange_cell_pos(0, -1);\r\n\t\t\telse\r\n\t\t\t\tchange_cell_pos(0, 1);\r\n\t\t\tm_motion_pct = 1.0f;\r\n\t\t}\r\n\t\telse if (shift_x_squared > 5.8284f * shift_z_squared)\r\n\t\t{\r\n\t\t\tif (shiftX < 0.0f)\r\n\t\t\t\tchange_cell_pos(-1, 0);\r\n\t\t\telse\r\n\t\t\t\tchange_cell_pos(1, 0);\r\n\t\t\tm_motion_pct = 1.0f;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (shiftZ < 0.0f)\r\n\t\t\t\tchange_cell_pos(0, -1);\r\n\t\t\telse\r\n\t\t\t\tchange_cell_pos(0, 1);\r\n\t\r\n\t\t\tif (shiftX < 0.0f)\r\n\t\t\t\tchange_cell_pos(-1, 0);\r\n\t\t\telse\r\n\t\t\t\tchange_cell_pos(1, 0);\r\n\t\t\tm_motion_pct = 1.0f;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tchange_cell_pos(0, 0);\r\n\t}\r\n\t\r\n\t#if 0\r\n\tprintf(\"cell (%d,%d), shown (%.2f,%.2f)\\n\", \r\n\t\t   m_cell_dims.GetX(), m_cell_dims.GetZ(), \r\n\t\t   m_pos[X], m_pos[Z]);\r\n\t#endif\r\n\t\r\n\t/*\r\n\t\t==================================================\r\n\t\tANIMATION SECTION\r\n\t\t==================================================\r\n\t*/\r\n\r\n\t//m_cell_dims.PrintContents();\r\n\t\r\n\t// derive m_target_pos from m_cell_dims\r\n\t\r\n\tMth::Vector world_dims;\r\n\tm_target_pos = m_manager->GridCoordinatesToWorld(m_cell_dims, &world_dims);\r\n\tm_target_pos[X] += world_dims[X] / 2.0f;\r\n\tm_target_pos[Z] += world_dims[Z] / 2.0f;\r\n\r\n\tif (m_motion_pct > 0.0f)\r\n\t{\r\n\t\tm_pos[X] += (m_target_pos[X] - m_pos[X]) * MOTION_PCT_INC / m_motion_pct;\r\n\t\tm_pos[Z] += (m_target_pos[Z] - m_pos[Z]) * MOTION_PCT_INC / m_motion_pct;\r\n\t\tm_pos[Y] = m_target_pos[Y];\r\n\t\tm_motion_pct -= MOTION_PCT_INC;\r\n\t\tif (m_motion_pct < 0.0f) m_motion_pct = 0.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_pos = m_target_pos;\r\n\t\tm_motion_pct = 0.0f;\r\n\t}\r\n\t\r\n\tif (m_rot < m_target_rot)\r\n\t{\r\n\t\tm_rot += ROT_DEG_INC;\r\n\t\tif (m_rot > m_target_rot)\r\n\t\t\tm_rot = m_target_rot;\r\n\t}\r\n\telse if (m_rot > m_target_rot)\r\n\t{\r\n\t\tm_rot -= ROT_DEG_INC;\r\n\t\tif (m_rot < m_target_rot)\r\n\t\t\tm_rot = m_target_rot;\r\n\t}\r\n\r\n\t/*\t\r\n\tScript::CStruct *p_params=new Script::CStruct;\r\n\tp_params->AddVector(CRCD(0x7f261953,\"pos\"),m_pos[X],m_pos[Y],m_pos[Z]);\r\n\tScript::RunScript(CRCD(0x9796fc9f,\"ParkEdCursorPos\"),p_params);\r\n\tdelete p_params;\r\n\t*/\r\n\t\r\n\t#ifndef DONT_USE_CURSOR_META\r\n\t// Mick:  TT#3804\r\n\t// Adding the vector fixes Z-Fighting between cursor and identical piece\r\n\tif (m_mode==PASTE)\r\n\t{\r\n\t\tif (mp_current_clipboard)\r\n\t\t{\r\n\t\t\t//printf(\"m_clipboard_y=%d\\n\",m_clipboard_y);\r\n\t\t\tmp_current_clipboard->ShowMetas(m_pos + Mth::Vector(-1.5f,+1.5f,-1.5f), m_rot, m_clipboard_y);\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDestroyAnyClipboardCursors();\r\n\t\tif (m_mode != RAIL_PLACEMENT)\r\n\t\t{\r\n\t\t\tDbg_Assert(mp_meta);\r\n\t\t\tmp_meta->SetSoftRot(m_pos + Mth::Vector(-1.5f,+1.5f,-1.5f), m_rot);\t\t  // Mick: Changed to move up, so water does not vanish on GC\r\n\t\t}\t\r\n\t}\t\r\n\t#endif\r\n}\r\n\r\n\r\n\r\nbool CCursor::AttemptStamp()\r\n{\r\n\tDbg_Assert(mp_meta);\r\n\tParkEd(\"CCursor::AttemptStamp()\");\r\n\t\r\n\tif (!m_manager->CanPlacePiecesIn(m_cell_dims))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t// If we are trying to put down a restart point then we need to see if there are \r\n\t// any free slots avaiable\t\r\n\tCParkGenerator::RestartType restart_type = m_manager->IsRestartPiece(mp_meta->GetNameChecksum());\r\n\tif (restart_type != CParkGenerator::vEMPTY)\r\n\t{\r\n\t\t//printf(\"Attempting to stamp a restart piece type %d\\n\", restart_type);\t\t\t\r\n\t\tif (! m_manager->GetGenerator()->FreeRestartExists(restart_type))\r\n\t\t{\r\n\t\t\t// no free slots for this restart point\r\n\t\t\tprintf (\"No free slots exist for this type of restart point\\n\");\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\t\r\n\t#ifndef DONT_USE_CURSOR_META\r\n\tCAbstractMetaPiece *p_abstract = m_manager->GetAbstractMeta(mp_meta->GetNameChecksum());\r\n\tDbg_MsgAssert(p_abstract, (\"couldn't find abstract piece %s\", Script::FindChecksumName(mp_meta->GetNameChecksum())));\r\n\tCConcreteMetaPiece *p_concrete = m_manager->CreateConcreteMeta(p_abstract);\r\n\tp_concrete->SetRot(m_hard_rot);\r\n\tm_manager->AddMetaPieceToPark(m_cell_dims, p_concrete);\r\n\t#endif\r\n\t\r\n\tm_manager->RebuildFloor();\r\n\t\r\n\treturn true;\r\n}\r\n\r\nbool CCursor::AttemptRemove()\r\n{\r\n\tParkEd(\"CCursor::AttemptRemove()\");\r\n\t\r\n\tGridDims area;\r\n\tif (m_mode==PASTE)\r\n\t{\r\n\t\tif (mp_current_clipboard)\r\n\t\t{\r\n\t\t\tmp_current_clipboard->GetArea(this,&area);\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tarea=m_cell_dims;\r\n\t}\t\r\n\t\r\n\treturn m_manager->DestroyMetasInArea(area);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tA callback called by CParkManager::DestroyConcreteMeta()\r\n*/\r\nvoid CCursor::InformOfMetapieceDeletion(CConcreteMetaPiece *pMeta)\r\n{\r\n\tint gap_half;\r\n\tGridDims meta_area = pMeta->GetArea();\r\n\tCGapManager::GapDescriptor *p_gap_desc = m_manager->GetGapDescriptor(meta_area, &gap_half);\r\n\tif (p_gap_desc && is_gap_descriptor_same_as_current(p_gap_desc))\r\n\t\tm_current_gap.numCompleteHalves = 0;\r\n}\r\n\r\n\r\n\r\n\r\nbool CCursor::AttemptGap()\r\n{\r\n\tSpt::SingletonPtr<CParkEditor> p_editor;\r\n\tif (p_editor->IsParkFull())\r\n\t\treturn false;\r\n\t\r\n\tCMapListTemp meta_list = m_manager->GetMetaPiecesAt(m_cell_dims);\r\n\tif (meta_list.IsEmpty()) \r\n\t{\r\n\t\t// XXX\r\n\t\tRyan(\"no gap for you!!!!\\n\");\r\n\t\treturn false;\r\n\t}\r\n\tCConcreteMetaPiece *p_meta = meta_list.GetList()->GetConcreteMeta();\r\n\t// XXX\r\n\tRyan(\"attempting gap at: \");\r\n\tm_cell_dims.PrintContents();\r\n\t\r\n\tint half;\r\n\tCGapManager::GapDescriptor *pDesc = m_manager->GetGapDescriptor(m_cell_dims, &half);\r\n\tif (pDesc)\r\n\t{\r\n\t\t// gap already attached at this location\r\n\t\tif (m_current_gap.numCompleteHalves == 1)\r\n\t\t{\r\n\t\t\t// user already working on gap, so fail\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\telse if (p_meta)\r\n\t{\r\n\t\t// metapiece found at this location without gap attached\r\n\t\tif (m_current_gap.numCompleteHalves == 1)\r\n\t\t\t// remove gap half placed so far. It'll get rebuilt later.\r\n\t\t\tm_manager->RemoveGap(m_current_gap);\r\n\t\telse\r\n\t\t\t// make sure not 2\r\n\t\t\tm_current_gap.numCompleteHalves = 0;\r\n\r\n\t\tint active_gap_half = m_current_gap.numCompleteHalves;\r\n\t\t\r\n\t\tGridDims gap_area = p_meta->GetArea();\r\n\t\t\r\n\t\t// start gap \r\n\t\tm_current_gap.loc[active_gap_half] = gap_area;\r\n\t\tm_current_gap.rot[active_gap_half] = 0;\r\n\t\tm_current_gap.leftExtent[active_gap_half] = 0;\r\n\t\tm_current_gap.rightExtent[active_gap_half] = 0;\r\n\t\tm_current_gap.score = 100;\r\n\t\tm_current_gap.numCompleteHalves = active_gap_half + 1;\r\n\t\tm_current_gap.tabIndex = -1;\r\n\t\r\n\t\tif (active_gap_half == 0)\r\n\t\t{\r\n\t\t\t// new gap, so give default name\r\n\t\t\tif (m_gap_suffix_counter > 1)\r\n\t\t\t{\r\n\t\t\t\t// K: Make sure the default names are different otherwise when registered in the \r\n\t\t\t\t// CSkaterCareer it will not get added cos it will think it is the same gap\r\n\t\t\t\t// as the last.\r\n\t\t\t\tsprintf(m_current_gap.text, \"gap%d\",m_gap_suffix_counter);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tstrcpy(m_current_gap.text, \"gap\");\r\n\t\t\t}\r\n\t\t\t++m_gap_suffix_counter;\r\n\t\t}\r\n\t\t\r\n\t\tif (!m_manager->AddGap(m_current_gap))\r\n\t\t{\r\n\t\t\tm_current_gap.numCompleteHalves = 0;\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tm_manager->RebuildFloor();\r\n\t\tif (m_current_gap.numCompleteHalves > 0)\r\n\t\t\tm_manager->HighlightMetasWithGaps(true, &m_current_gap);\r\n\r\n\t\treturn true;\r\n\t}\t\r\n\t\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\nbool CCursor::AttemptRemoveGap()\r\n{\r\n\tif (m_current_gap.numCompleteHalves == 1)\r\n\t{\r\n\t\t// remove gap being worked on\r\n\t\tm_manager->RemoveGap(m_current_gap);\r\n\t\tm_current_gap.numCompleteHalves = 0;\r\n\t\tm_manager->RebuildFloor();\r\n\t\treturn true;\r\n\t}\r\n\r\n\tint half;\r\n\tCGapManager::GapDescriptor *pDesc = m_manager->GetGapDescriptor(m_cell_dims, &half);\r\n\tif (pDesc)\r\n\t{\r\n\t\t// remove gap at this position\r\n\t\tm_manager->RemoveGap(*pDesc);\r\n\t\tm_manager->RebuildFloor();\r\n\t\tm_manager->HighlightMetasWithGaps(true, NULL);\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\nbool CCursor::AdjustGap(int rot, int leftChange, int rightChange)\r\n{\r\n\t// grab gap at this location\r\n\tint half;\r\n\tCGapManager::GapDescriptor *p_desc = m_manager->GetGapDescriptor(m_cell_dims, &half);\r\n\tif (!p_desc)\r\n\t{\r\n\t\t// no gap, so leave\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (!is_gap_descriptor_same_as_current(p_desc))\r\n\t\t// we are currently working on a gap and it's not the same as the one at this location, so fail\r\n\t\treturn false;\r\n\t\r\n\tCGapManager::GapDescriptor desc_temp = *p_desc;\r\n\tbool needs_change = false;\r\n\r\n\tif (rot != 0)\r\n\t{\r\n\t\tdesc_temp.rot[half] -= rot;\r\n\t\tdesc_temp.leftExtent[half] = 0;\r\n\t\tdesc_temp.rightExtent[half] = 0;\r\n\t\tneeds_change = true;\r\n\t}\r\n\r\n\tif (leftChange != 0)\r\n\t{\r\n\t\tdesc_temp.leftExtent[half] += leftChange;\r\n\t\tif (desc_temp.leftExtent[half] < 0)\r\n\t\t\tdesc_temp.leftExtent[half] = 0;\r\n\t\telse if (desc_temp.leftExtent[half] > 6)\r\n\t\t\tdesc_temp.leftExtent[half] = 6;\r\n\t\tneeds_change = true;\r\n\t}\r\n\t\r\n\tif (rightChange != 0)\r\n\t{\r\n\t\tdesc_temp.rightExtent[half] += rightChange;\r\n\t\tif (desc_temp.rightExtent[half] < 0)\r\n\t\t\tdesc_temp.rightExtent[half] = 0;\r\n\t\tif (desc_temp.rightExtent[half] > 6)\r\n\t\t\tdesc_temp.rightExtent[half] = 6;\r\n\t\tneeds_change = true;\r\n\t}\r\n\r\n\tif (needs_change)\r\n\t{\r\n\t\tm_manager->RemoveGap(*p_desc);\r\n\t\tdesc_temp.rot[half] &= 3;\r\n\r\n\t\tGridDims park_bounds = m_manager->GetParkNearBounds();\r\n\t\t\r\n\t\t// make sure gap boundaries are within map\r\n\t\tif (desc_temp.rot[half] == 0)\r\n\t\t{\r\n\t\t\tif (desc_temp.loc[half].GetZ() - desc_temp.rightExtent[half] < park_bounds.GetZ())\r\n\t\t\t\tdesc_temp.rightExtent[half]--;\r\n\t\t\tif (desc_temp.loc[half].GetZ() + desc_temp.loc[half].GetL() + desc_temp.leftExtent[half] > park_bounds.GetZ() + park_bounds.GetL())\r\n\t\t\t\tdesc_temp.leftExtent[half]--;\r\n\t\t}\r\n\t\telse if (desc_temp.rot[half] == 2)\r\n\t\t{\r\n\t\t\tif (desc_temp.loc[half].GetZ() - desc_temp.leftExtent[half] < park_bounds.GetZ())\r\n\t\t\t\tdesc_temp.leftExtent[half]--;\r\n\t\t\tif (desc_temp.loc[half].GetZ() + desc_temp.loc[half].GetL() + desc_temp.rightExtent[half] > park_bounds.GetZ() + park_bounds.GetL())\r\n\t\t\t\tdesc_temp.rightExtent[half]--;\r\n\t\t}\r\n\t\telse if (desc_temp.rot[half] == 1)\r\n\t\t{\r\n\t\t\tif (desc_temp.loc[half].GetX() - desc_temp.rightExtent[half] < park_bounds.GetX())\r\n\t\t\t\tdesc_temp.rightExtent[half]--;\r\n\t\t\tif (desc_temp.loc[half].GetX() + desc_temp.loc[half].GetW() + desc_temp.leftExtent[half] > park_bounds.GetX() + park_bounds.GetW())\r\n\t\t\t\tdesc_temp.leftExtent[half]--;\r\n\t\t}\r\n\t\telse if (desc_temp.rot[half] == 3)\r\n\t\t{\r\n\t\t\tif (desc_temp.loc[half].GetX() - desc_temp.leftExtent[half] < park_bounds.GetX())\r\n\t\t\t\tdesc_temp.leftExtent[half]--;\r\n\t\t\tif (desc_temp.loc[half].GetX() + desc_temp.loc[half].GetW() + desc_temp.rightExtent[half] > park_bounds.GetX() + park_bounds.GetW())\r\n\t\t\t\tdesc_temp.rightExtent[half]--;\r\n\t\t}\r\n\r\n\t\t// XXX\r\n\t\tfor (half = 0; half < 2; half++)\r\n\t\t\tRyan(\"gap details for half %d (%d,%d,%d),(%d,%d,%d) left=%d right=%d\\n\", half,\r\n\t\t\t\t desc_temp.loc[half].GetX(), desc_temp.loc[half].GetY(), desc_temp.loc[half].GetZ(),\r\n\t\t\t\t desc_temp.loc[half].GetW(), desc_temp.loc[half].GetH(), desc_temp.loc[half].GetL(),\r\n\t\t\t\t desc_temp.leftExtent[half], desc_temp.rightExtent[half]);\r\n\r\n\t\tm_manager->AddGap(desc_temp);\r\n\t\tm_manager->RebuildFloor();\r\n\t\t\r\n\t\tif (m_current_gap.numCompleteHalves == 1)\r\n\t\t{\r\n\t\t\tm_current_gap = desc_temp;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CCursor::SetGapNameAndScore(const char *pGapName, int score)\r\n{\r\n\tif (pGapName)\r\n\t{\r\n\t\tDbg_MsgAssert(strlen(pGapName) <= 31, (\"too many characters in gap name\"));\r\n\t\tif (*pGapName == '\\0')\r\n\t\t\tstrcpy(m_current_gap.text, \"x\");\r\n\t\telse\r\n\t\t\tstrcpy(m_current_gap.text, pGapName);\r\n\t}\r\n\tif (score >= 0)\r\n\t{\r\n\t\tm_current_gap.score = score;\r\n\t}\r\n\tDbg_Assert(m_current_gap.tabIndex >= 0);\r\n\tCGapManager::sInstance()->SetGapInfo(m_current_gap.tabIndex, m_current_gap);\r\n}\r\n\r\nvoid CCursor::SetGapCancelFlags(Script::CStruct *p_cancelFlags)\r\n{\r\n\tif (!p_cancelFlags)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tuint32 cancel_flags=0;\r\n\tScript::CComponent *p_comp=p_cancelFlags->GetNextComponent();\r\n\twhile (p_comp)\r\n\t{\r\n\t\tDbg_MsgAssert(p_comp->mNameChecksum==0 && p_comp->mType==ESYMBOLTYPE_NAME,(\"Gap cancel flag structure must contain only names\"));\r\n\t\tcancel_flags |= Script::GetInteger(p_comp->mChecksum);\r\n\t\tp_comp=p_cancelFlags->GetNextComponent(p_comp);\r\n\t}\t\r\n\t\r\n\tm_current_gap.mCancelFlags=cancel_flags;\r\n\t\r\n\tDbg_Assert(m_current_gap.tabIndex >= 0);\r\n\tCGapManager::sInstance()->SetGapInfo(m_current_gap.tabIndex, m_current_gap);\r\n}\r\n\r\n\r\nconst char *CCursor::GetGapName()\r\n{\r\n\treturn m_current_gap.text;\r\n}\r\n\r\n\r\nint CCursor::AttemptAreaSelect()\r\n{\r\n\tDbg_MsgAssert(m_mode==AREA_SELECT,(\"Called AttemptAreaSelect() with m_mode!=AREA_SELECT\"));\r\n\tDbg_MsgAssert(m_num_corners_selected<=2,(\"Bad m_num_corners_selected of %d\",m_num_corners_selected));\r\n\r\n\tif (m_num_corners_selected==0)\r\n\t{\r\n\t\tmp_area_corners[0]=m_cell_dims;\r\n\t\tmp_area_corners[1]=m_cell_dims;\r\n\t\tm_num_corners_selected=1;\r\n\t\tForceSelectionAreaHighlightRefresh();\r\n\t}\r\n\telse if (m_num_corners_selected==1)\r\n\t{\r\n\t\tGridDims area;\r\n\t\tGetAreaSelectDims(&area);\r\n\t\tif (area.GetW() <= CLIPBOARD_MAX_W && area.GetL() <= CLIPBOARD_MAX_L)\r\n\t\t{\r\n\t\t\tm_num_corners_selected=2;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\treturn m_num_corners_selected;\r\n}\r\n\r\nvoid CCursor::ClearAreaSelection()\r\n{\r\n\tGridDims area;\r\n\tGetAreaSelectDims(&area);\r\n\t\r\n\tm_manager->HighlightMetasInArea(area,false);\r\n\t\r\n\tm_num_corners_selected=0;\r\n\tm_initialised_highlight=false;\r\n}\r\n\r\nvoid CCursor::ContinueAreaSelection()\r\n{\r\n\tm_num_corners_selected=1;\r\n\t// Need to force it to re-highlight the selection area next time around\r\n\t// because when quitting the paused menu something resets all the highlights.\r\n\tForceSelectionAreaHighlightRefresh();\r\n}\r\n\r\nvoid CCursor::DeleteSelectedPieces()\r\n{\r\n\tif (!m_num_corners_selected)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tGridDims dims;\r\n\tGetAreaSelectDims(&dims);\r\n\r\n\t// First true means do not destroy any flags or restarts\r\n\t// Second true means only destroy if completely within the area.\r\n\tm_manager->DestroyMetasInArea(dims, true, true);\r\n\r\n\tContinueAreaSelection();\r\n}\r\n\r\nvoid CCursor::ResetSelectedHeights()\r\n{\r\n\tif (!m_num_corners_selected)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tGridDims dims;\r\n\tGetAreaSelectDims(&dims);\r\n\r\n\tm_manager->ResetFloorHeights(dims);\r\n\t\r\n\tContinueAreaSelection();\r\n}\r\n\t\r\nvoid CCursor::get_selected_area_coords(uint8 *p_x1, uint8 *p_z1, uint8 *p_x2, uint8 *p_z2)\r\n{\r\n\tuint8 x1=mp_area_corners[0].GetX();\r\n\tuint8 z1=mp_area_corners[0].GetZ();\r\n\tuint8 x2=mp_area_corners[1].GetX();\r\n\tuint8 z2=mp_area_corners[1].GetZ();\r\n\t\r\n\tif (x2 < x1)\r\n\t{\r\n\t\tuint8 temp=x1;\r\n\t\tx1=x2;\r\n\t\tx2=temp;\r\n\t}\r\n\r\n\tif (z2 < z1)\r\n\t{\r\n\t\tuint8 temp=z1;\r\n\t\tz1=z2;\r\n\t\tz2=temp;\r\n\t}\r\n\t\r\n\t*p_x1=x1;\r\n\t*p_z1=z1;\r\n\t*p_x2=x2;\r\n\t*p_z2=z2;\r\n}\r\n\r\nvoid CCursor::GetAreaSelectDims(GridDims *p_dims)\r\n{\r\n\tif (m_num_corners_selected==0)\r\n\t{\r\n\t\tp_dims->SetXYZ(0,0,0);\r\n\t\tp_dims->SetWHL(0,0,0);\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tuint8 x1,z1,x2,z2;\r\n\tget_selected_area_coords(&x1,&z1,&x2,&z2);\r\n\t\r\n\tp_dims->SetXYZ(x1,0,z1);\r\n\tp_dims->SetWHL(x2-x1+1,1,z2-z1+1);\r\n}\r\n\r\nbool CCursor::DestroyMetasInCurrentArea()\r\n{\r\n\tGridDims area;\r\n\tGetAreaSelectDims(&area);\r\n\r\n\treturn CParkManager::sInstance()->DestroyMetasInArea(area);\r\n}\r\n\r\nvoid CCursor::DeleteOldestClipboard()\r\n{\r\n\t// Find p_last, the last clipboard in the list.\r\n\tCClipboard *p_clip=mp_clipboards;\r\n\tCClipboard *p_last=NULL;\r\n\tCClipboard *p_next_to_last=NULL;\r\n\twhile (p_clip)\r\n\t{\r\n\t\tp_next_to_last=p_last;\r\n\t\tp_last=p_clip;\r\n\t\t\r\n\t\tp_clip=p_clip->mpNext;\r\n\t}\r\n\tif (!p_last)\r\n\t{\r\n\t\t// Cannot do anything because there are no clipboards to delete\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tdelete p_last;\r\n\t\r\n\tif (p_next_to_last)\r\n\t{\r\n\t\tp_next_to_last->mpNext=NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_clipboards=NULL;\r\n\t}\r\n}\r\n\r\nbool CCursor::SelectionAreaTooBigToCopy()\r\n{\r\n\tGridDims area;\r\n\tGetAreaSelectDims(&area);\r\n\r\n\tif (area.GetW() > CLIPBOARD_MAX_W || area.GetL() > CLIPBOARD_MAX_L)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tSpt::SingletonPtr<CParkEditor> p_editor;\r\n\tif (!p_editor->RoomToCopyOrPaste(area.GetW(), area.GetL()))\r\n\t{\r\n\t\treturn true;\r\n\t}\t\r\n\t\r\n\treturn false;\r\n}\r\n\t\t\r\nbool CCursor::CopySelectionToClipboard()\r\n{\r\n\tif (SelectionAreaTooBigToCopy())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\tGridDims area;\r\n\tGetAreaSelectDims(&area);\r\n\t\r\n\t// TODO TODO TODO\r\n\t// If not enough rail points to copy the rails, check to see if any of the existing clipboards contain\r\n\t// rails. If so, delete enough of them to free up enough points. If still not enough points, bail out.\r\n\t// If enough, carry on with the next loop.\r\n\tMth::Vector corner_pos;\r\n\tMth::Vector area_dims;\r\n\tcorner_pos=Ed::CParkManager::Instance()->GridCoordinatesToWorld(area,&area_dims);\r\n\tint num_rail_points_needed=Obj::GetRailEditor()->CountPointsInArea(corner_pos[X], corner_pos[Z], \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   corner_pos[X]+area_dims[X], corner_pos[Z]+area_dims[Z]);\r\n\tif (num_rail_points_needed > Obj::GetRailEditor()->GetNumFreePoints())\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\r\n\r\n\tif (GetNumClipboards()==MAX_CLIPBOARDS)\r\n\t{\r\n\t\t// All the CClipboard's in the pool have already been allocated.\r\n\t\t\r\n\t\t// Find the oldest clipboard and delete it.\r\n\t\tDeleteOldestClipboard();\r\n\t\t\r\n\t\t// That will have freed up space for one more CClipboard\r\n\t\t// so the new CClipboard below should not assert.\r\n\t\t// If it does then something strange is going on, like MAX_CLIPBOARDS is 0 or something.\r\n\t}\r\n\t\t\r\n\tCClipboard *p_clipboard=new CClipboard;\r\n\r\n\t\r\n\t\r\n\t// CopySelectionToClipboard will use up CClipboardEntry's, of which there are only\r\n\t// a certain number allocated in a pool.\r\n\t// So CopySelectionToClipboard may fail, even though the CClipboard pool may not be full.\r\n\t\r\n\t// Keep deleting old clipboards until CopySelectionToClipboard succeeds.\r\n\t// Note that the above newly allocated p_clipboard has not been put in the list\r\n\t// yet so it will not get deleted by accident here.\r\n\twhile (!p_clipboard->CopySelectionToClipboard(area))\r\n\t{\r\n\t\tif (!mp_clipboards)\r\n\t\t{\r\n\t\t\t// Run out of clipboards to delete! If this happens then CopySelectionToClipboard\r\n\t\t\t// must be failing because the total number of pieces the user wants to copy \r\n\t\t\t// exceeds the total number of CClipboardEntry's available in the pool, which\r\n\t\t\t// is defined by MAX_CLIPBOARD_METAS in clipboard.h\r\n\t\t\tbreak;\r\n\t\t}\t\t\t\r\n\t\tDeleteOldestClipboard();\r\n\t}\t\r\n\t\r\n\tif (p_clipboard->IsEmpty())\r\n\t{\r\n\t\t// Nothing got copied into the clipboard, which means either the user tried to copy a \r\n\t\t// blank area or the above attempts at copying failed due to lack of memory.\r\n\t\t\r\n\t\tdelete p_clipboard;\r\n\t\tp_clipboard=NULL;\r\n\t\t\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\t// Add the new clipboard to the list.\r\n\tp_clipboard->mpNext=mp_clipboards;\r\n\tmp_clipboards=p_clipboard;\r\n\treturn true;\r\n}\t\r\n\r\nint CCursor::GetNumClipboards()\r\n{\r\n\tint n=0;\r\n\tCClipboard *p_clipboard=mp_clipboards;\r\n\twhile (p_clipboard)\r\n\t{\r\n\t\t++n;\r\n\t\tp_clipboard=p_clipboard->mpNext;\r\n\t}\r\n\treturn n;\t\r\n}\r\n\r\nvoid CCursor::PasteCurrentClipboard()\r\n{\r\n\tif (mp_current_clipboard)\r\n\t{\r\n\t\tmp_current_clipboard->Paste(this);\r\n\t}\r\n}\r\n\r\nCClipboard *CCursor::get_clipboard(int index)\r\n{\r\n\tCClipboard *p_clipboard=mp_clipboards;\r\n\t\r\n\tfor (int i=0; i<index; ++i)\r\n\t{\r\n\t\tif (p_clipboard)\r\n\t\t{\r\n\t\t\tp_clipboard=p_clipboard->mpNext;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\treturn p_clipboard;\r\n}\r\n\r\nvoid CCursor::set_current_clipboard(int index)\r\n{\r\n\tDestroyAnyClipboardCursors();\t\t\r\n\tmp_current_clipboard=get_clipboard(index);\r\n\t\r\n\t/*\r\n\tif (mp_current_clipboard)\r\n\t{\r\n\t\tm_cell_dims.SetWHL(mp_current_clipboard->GetWidth(),1,mp_current_clipboard->GetLength());\r\n\t\tif (m_hard_rot & 1)\r\n\t\t{\r\n\t\t\tm_cell_dims.SetWHL(m_cell_dims.GetL(), m_cell_dims.GetH(), m_cell_dims.GetW());\r\n\t\t}\r\n\t}\t\r\n\t*/\r\n}\r\n\r\nvoid CCursor::remove_clipboard(int index)\r\n{\r\n\tCClipboard *p_remove=get_clipboard(index);\r\n\tif (!p_remove)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tCClipboard *p_search=mp_clipboards;\r\n\tCClipboard *p_last=NULL;\r\n\twhile (p_search)\r\n\t{\r\n\t\tif (p_search==p_remove)\r\n\t\t{\r\n\t\t\tif (p_last)\r\n\t\t\t{\r\n\t\t\t\tp_last->mpNext=p_remove->mpNext;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmp_clipboards=p_remove->mpNext;\r\n\t\t\t}\r\n\t\t\tdelete p_remove;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\t\r\n\t\tp_last=p_search;\r\n\t\tp_search=p_search->mpNext;\r\n\t}\t\r\n}\r\n\r\nvoid CCursor::RefreshSelectionArea()\r\n{\r\n\tswitch (m_num_corners_selected)\r\n\t{\r\n\tcase 0:\r\n\t\tbreak;\r\n\tcase 1:\r\n\t\tif (!m_initialised_highlight)\r\n\t\t{\r\n\t\t\tGridDims area;\r\n\t\t\tGetAreaSelectDims(&area);\r\n\t\t\t\r\n\t\t\tm_manager->HighlightMetasInArea(area,true);\r\n\t\t\t\r\n\t\t\tm_initialised_highlight=true;\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (m_cell_dims.GetX() != mp_area_corners[1].GetX() ||\r\n\t\t\t\tm_cell_dims.GetZ() != mp_area_corners[1].GetZ())\r\n\t\t\t{\r\n\t\t\t\tGridDims area;\r\n\t\t\t\tGetAreaSelectDims(&area);\r\n\r\n\t\t\t\tm_manager->HighlightMetasInArea(area,false);\r\n\r\n\t\t\t\tmp_area_corners[1]=m_cell_dims;\r\n\r\n\t\t\t\tGetAreaSelectDims(&area);\r\n\r\n\t\t\t\tm_manager->HighlightMetasInArea(area,true);\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\t\t\r\n\t}\r\n}\r\n\r\n// Find all the pieces intersecting the cursor\r\n// and turn the highlight effect on or off\r\n// (In THPS3, the highlight was a wireframe.  Here I think we are going to try coloring it red)\r\nvoid CCursor::HighlightIntersectingMetas(bool on)\r\n{\r\n\tif (m_mode==PASTE)\r\n\t{\r\n\t\tif (mp_current_clipboard)\r\n\t\t{\r\n\t\t\tmp_current_clipboard->HighlightIntersectingMetas(this,on);\r\n\t\t\treturn;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\t// Get the list of (concrete) meta pieces that intersect the\r\n\t// dimension of the cursor's m_cell_dims\r\n\tCMapListTemp metas_at_pos = m_manager->GetMetaPiecesAt(m_cell_dims);\r\n\tif (metas_at_pos.IsEmpty())\r\n\t{\r\n\t\t// Nothing intersecting, so do nothing and return\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Iterate over the list of metapieces we just found, and highlight each one\r\n\t// (Whcih will actually highlight the pieces\r\n\tCMapListNode *p_entry = metas_at_pos.GetList();\r\n\twhile(p_entry)\r\n\t{\r\n\t\tp_entry->GetConcreteMeta()->Highlight(on);\t\t\r\n\t\tp_entry = p_entry->GetNext();\r\n\t}\r\n}\r\n\r\nvoid CCursor::SetVisibility(bool visible)\r\n{\r\n\t//Dbg_Assert(mp_meta);\r\n\tif (mp_meta)\r\n\t{\r\n\t\tmp_meta->SetVisibility(visible);\r\n\t}\t\r\n\t\r\n\tif (!visible)\r\n\t{\r\n\t\tif (mp_current_clipboard)\r\n\t\t{\r\n\t\t\tmp_current_clipboard->DestroyMetas();\r\n\t\t}\r\n\t}\t\t\r\n\t\r\n\tm_initialised_highlight=false;\r\n}\r\n\r\n\r\n\r\nvoid CCursor::ChangePieceInSet(int dir)\r\n{\r\n\tCParkManager::CPieceSet &piece_set = m_manager->GetPieceSet(m_selected_set, &m_menu_set_number);\r\n\tint selected_entry = piece_set.mSelectedEntry;\r\n\tselected_entry += dir;\r\n\tif (selected_entry < 0)\r\n\t\tselected_entry = piece_set.mTotalEntries - 1;\r\n\telse if (selected_entry >= piece_set.mTotalEntries)\r\n\t\tselected_entry = 0;\r\n\tpiece_set.mSelectedEntry = selected_entry;\r\n\r\n\tif (piece_set.mIsClipboardSet)\r\n\t{\r\n\t\tset_current_clipboard(piece_set.mSelectedEntry);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tset_source_meta(piece_set.mEntryTab[selected_entry].mNameCrc);\r\n\t}\t\r\n}\r\n\r\nvoid CCursor::ChangeSet(int dir)\r\n{\r\n\tfor (int count = m_manager->GetTotalNumPieceSets(); count > 0; count--)\r\n\t{\r\n\t\tm_selected_set += dir;\r\n\t\tif (m_selected_set < 0)\r\n\t\t\tm_selected_set = m_manager->GetTotalNumPieceSets() - 1;\r\n\t\tif (m_selected_set >= m_manager->GetTotalNumPieceSets())\r\n\t\t\tm_selected_set = 0;\r\n\t\t//printf(\"set is: %s\\n\", m_palette_set[m_selected_set].mpName);\r\n\t\tif (m_manager->GetPieceSet(m_selected_set, &m_menu_set_number).mVisible) break;\r\n\t}\r\n\tCParkManager::CPieceSet &piece_set = m_manager->GetPieceSet(m_selected_set, &m_menu_set_number);\r\n\tif (piece_set.mIsClipboardSet)\r\n\t{\r\n\t\tset_current_clipboard(piece_set.mSelectedEntry);\r\n\t\t// Destroy the regular cursor meta\r\n\t\tDestroyGeometry();\r\n\t\t\r\n\t\t\r\n\t\tchange_mode(PASTE);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tset_source_meta(piece_set.mEntryTab[piece_set.mSelectedEntry].mNameCrc);\r\n\t}\t\r\n}\r\n\r\nvoid CCursor::SwitchMenuPieceToMostRecentClipboard()\r\n{\r\n\tif (!GetNumClipboards())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tint num_sets=m_manager->GetTotalNumPieceSets();\r\n\tCParkManager::CPieceSet *p_piece_set=NULL;\r\n\t\r\n\tfor (int i=0; i<num_sets; ++i)\r\n\t{\r\n\t\tCParkManager::CPieceSet &piece_set = m_manager->GetPieceSet(i, &m_menu_set_number);\r\n\t\tif (piece_set.mIsClipboardSet)\r\n\t\t{\r\n\t\t\tm_selected_set=i;\r\n\t\t\tp_piece_set=&piece_set;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tDbg_MsgAssert(p_piece_set,(\"Clipboard piece set not found?\"));\r\n\t\r\n\tp_piece_set->mSelectedEntry=0;\r\n\tset_current_clipboard(p_piece_set->mSelectedEntry);\r\n\t// Destroy the regular cursor meta\r\n\tDestroyGeometry();\r\n\tchange_mode(PASTE);\r\n\t\r\n\t// Fix to TT14349: Crash bug if copying tree pieces at the edge of the largest map by highlighting starting at the \r\n\t// lower right corner of the set of trees.\r\n\t// Caused by the cursor being out of bounds for a frame, hence causing it to read outside the map array.\r\n\tForceInBounds();\r\n}\r\n\r\nbool CCursor::ChangeFloorHeight(GridDims dims, int height, int dir, bool uniformHeight)\r\n{\r\n\t//printf(\"CCursor::ChangeFloorHeight: \");\r\n\t\r\n\t/*\r\n\t\tUneven floor:\r\n\t\t\tIf going up, raise to height of topmost\r\n\t\t\tIf going down, only lower ones on same level\r\n\t*/\r\n\r\n\t//printf(\"height=%d uniform_height=%d\\n\",height,uniformHeight);\r\n\t/*\r\n\t\tNow, \r\n\t*/\r\n\r\n\tif (dims.GetW() > CLIPBOARD_MAX_W || dims.GetL() > CLIPBOARD_MAX_L)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\t//Spt::SingletonPtr<CParkEditor> p_editor;\r\n\t//if (p_editor->IsParkFull())\r\n\t//{\r\n\t//\treturn false;\r\n\t//}\r\n\t\t\r\n\tbool success = true;\r\n\t\r\n\t\t\r\n\tif (m_manager->SlideColumn(dims, dims.GetY(), height, (dir > 0), !uniformHeight))\r\n\t{\r\n\t\t//Ryan(\"Slide column, dir = %d, dims=\", dir);\r\n\t\t//dims.PrintContents();\r\n\t\t\r\n\t\tchange_cell_pos(0, 0);\r\n\t\tSpt::SingletonPtr<CParkEditor> p_editor;\r\n\t\tif (m_manager->RebuildFloor(p_editor->IsParkFull()))\r\n\t\t{\r\n\t\t\tm_manager->HighlightMetasWithGaps(false, NULL);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// out of memory, so reverse slide\r\n\t\t\tm_manager->UndoSlideColumn();\r\n\t\t\tm_manager->RebuildFloor();\r\n\t\t\tsuccess = false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t\tsuccess = false;\r\n\r\n\treturn success;\r\n}\r\n\r\nbool CCursor::ChangeFloorHeight(int dir)\r\n{\r\n\tGridDims dims;\r\n\tswitch (m_mode)\r\n\t{\r\n\tcase AREA_SELECT:\r\n\t\tif (m_num_corners_selected)\r\n\t\t{\r\n\t\t\tGetAreaSelectDims(&dims);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tdims=m_cell_dims;\r\n\t\t}\t\r\n\t\tbreak;\r\n\tcase PASTE:\r\n\t\tif (mp_current_clipboard)\r\n\t\t{\r\n\t\t\tmp_current_clipboard->GetArea(this,&dims);\r\n\t\t}\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tdims=m_cell_dims;\r\n\t\tbreak;\r\n\t}\t\r\n\r\n\t// If the dims exceeds the area of the park, then do not raise or lower.\r\n\t// This can happen if the park is been resized to its smallest possible size and then a big pool\r\n\t// piece selected. If the raise was allowed to go ahead, it would result in the fence raising too. (TT11825)\r\n\tGridDims park_bounds = CParkManager::sInstance()->GetParkNearBounds();\t\r\n\tif (dims.GetW() > park_bounds.GetW() || dims.GetL() > park_bounds.GetL())\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\t\r\n\tbool uniform_height;\r\n\tint height = m_manager->GetFloorHeight(dims, &uniform_height);\r\n\r\n\t// If pasting, destroy the clipboard metas, otherwise the dry run that ChangeFloorHeight\r\n\t// does to determine whether it is safe to raise or lower will incorrectly think it\r\n\t// is safe when it is not. I think the function generate_floor_pieces_from_height_map\r\n\t// gets confused by the presence of the clipboard metas. (TT7495 & TT6152)\r\n\tif (m_mode==PASTE)\r\n\t{\r\n\t\tif (mp_current_clipboard)\r\n\t\t{\r\n\t\t\tmp_current_clipboard->DestroyMetas();\r\n\t\t}\r\n\t}\t\t\r\n\tbool ret_val=ChangeFloorHeight(dims,height,dir,uniform_height);\r\n\t\r\n\tif (m_mode==AREA_SELECT)\r\n\t{\r\n\t\tForceSelectionAreaHighlightRefresh();\r\n\t}\r\n\treturn ret_val;\t\r\n}\r\n\r\n\r\n\r\n\r\nbool CCursor::IsSittingOnGap()\r\n{\r\n\tint half;\r\n\tCGapManager::GapDescriptor *pDesc = m_manager->GetGapDescriptor(m_cell_dims, &half);\r\n\tif (pDesc)\r\n\t\treturn true;\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\nCCursor *CCursor::sInstance(bool assert)\r\n{\r\n\tDbg_Assert(!assert || sp_instance);\r\n\treturn sp_instance;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CCursor::ForceInBounds()\r\n{\r\n\tif (m_cell_dims[X] < m_manager->GetParkNearBounds().GetX())\r\n\t{\r\n\t\tm_cell_dims[X] = m_manager->GetParkNearBounds().GetX();\r\n\t}\r\n\tif (m_cell_dims[X] + m_cell_dims[W] > m_manager->GetParkNearBounds().GetX() + m_manager->GetParkNearBounds().GetW())\r\n\t{\r\n\t\tm_cell_dims[X] = m_manager->GetParkNearBounds().GetX() + m_manager->GetParkNearBounds().GetW() - m_cell_dims[W];\r\n\t}\r\n\tif (m_cell_dims[Z] < m_manager->GetParkNearBounds().GetZ())\r\n\t{\r\n\t\tm_cell_dims[Z] = m_manager->GetParkNearBounds().GetZ();\r\n\t}\r\n\tif (m_cell_dims[Z] + m_cell_dims[L] > m_manager->GetParkNearBounds().GetZ() + m_manager->GetParkNearBounds().GetL())\r\n\t{\r\n\t\tm_cell_dims[Z] = m_manager->GetParkNearBounds().GetZ() + m_manager->GetParkNearBounds().GetL() - m_cell_dims[L];\r\n\t}\r\n\t\r\n\tif (m_mode==PASTE)\r\n\t{\r\n\t\tif (mp_current_clipboard)\r\n\t\t{\r\n\t\t\tGridDims area;\r\n\t\t\tmp_current_clipboard->GetArea(this,&area);\r\n\t\t\t\t\t\t\r\n\t\t\tint dx=0;\r\n\t\t\tint park_x_left=m_manager->GetParkNearBounds().GetX();\r\n\t\t\tint park_x_right=m_manager->GetParkNearBounds().GetX()+m_manager->GetParkNearBounds().GetW()-1;\r\n\t\t\tsint8 x_left=area.GetX();\r\n\t\t\tif (x_left < park_x_left)\r\n\t\t\t{\r\n\t\t\t\tdx=park_x_left-x_left;\r\n\t\t\t}\r\n\t\t\tsint8 x_right=area.GetX();\r\n\t\t\tx_right+=area.GetW()-1;\t\r\n\t\t\tif (x_right > park_x_right)\r\n\t\t\t{\r\n\t\t\t\tdx=park_x_right-x_right;\r\n\t\t\t}\t\r\n\t\t\tm_cell_dims[X]+=dx;\r\n\t\t\t\r\n\t\t\tint dz=0;\r\n\t\t\tint park_z_top=m_manager->GetParkNearBounds().GetZ();\r\n\t\t\tint park_z_bottom=m_manager->GetParkNearBounds().GetZ()+m_manager->GetParkNearBounds().GetL()-1;\r\n\t\t\t\r\n\t\t\tsint8 z_top=area.GetZ();\r\n\t\t\tif (z_top < park_z_top)\r\n\t\t\t{\r\n\t\t\t\tdz=park_z_top-z_top;\r\n\t\t\t}\r\n\t\t\tsint8 z_bottom=area.GetZ();\r\n\t\t\tz_bottom+=area.GetL()-1;\t\r\n\t\t\tif (z_bottom > park_z_bottom)\r\n\t\t\t{\r\n\t\t\t\tdz=park_z_bottom-z_bottom;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tm_cell_dims[Z]+=dz;\r\n\t\t}\t\r\n\t}\r\n\t\r\n}\r\n\r\n\r\n\r\n\r\nvoid CCursor::change_cell_pos(int incX, int incZ)\r\n{\r\n\t//printf(\"change_cell_pos:\\n\");\r\n\t//printf(\"Before:\");\r\n\t//m_cell_dims.PrintContents();\r\n\t\r\n\tForceInBounds();\r\n\tGridDims old_pos = m_cell_dims;\r\n\t\r\n\tm_cell_dims[X] += incX;\r\n\tm_cell_dims[Z] += incZ;\r\n\r\n\tForceInBounds();\r\n\r\n\tif (m_mode==PASTE)\r\n\t{\r\n\t\tif (mp_current_clipboard)\r\n\t\t{\r\n\t\t\tm_clipboard_y=mp_current_clipboard->FindMaxFloorHeight(this);\r\n\t\t\tm_cell_dims[Y]=m_clipboard_y;\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_cell_dims[Y]=0;\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint current_floor_height = m_manager->GetFloorHeight(m_cell_dims);\r\n\t\tint floor_height_old_pos = m_manager->GetFloorHeight(old_pos);\r\n\t\tm_cell_dims[Y] = (current_floor_height > floor_height_old_pos) ? current_floor_height : floor_height_old_pos;\r\n\t}\r\n\t\t\r\n\t//Ryan(\"cursor at %d,%d\\n\", m_cell_dims[X], m_cell_dims[Z]);\t \r\n\r\n\t//printf(\"After:\");\r\n\t//m_cell_dims.PrintContents();\r\n\t\r\n\t#if 0\r\n\tprintf(\"park bounds: %d,%d,%d,%d, cell_dims: %d,%d\\n\", \r\n\t\t   m_manager->GetParkNearBounds().GetX(), m_manager->GetParkNearBounds().GetZ(),\r\n\t\t   m_manager->GetParkNearBounds().GetW(), m_manager->GetParkNearBounds().GetL(),\r\n\t\t   m_cell_dims[W], m_cell_dims[L]);\r\n\t#endif\r\n\t\r\n\tif (m_mode == GAP || m_mode == GAP_ADJUST)\r\n\t{\r\n\t\tECursorMode new_mode = GAP;\r\n\t\t\r\n\t\t// see if cursor is over a metapiece with attached gap\r\n\t\tCMapListTemp meta_list = m_manager->GetMetaPiecesAt(m_cell_dims);\r\n\t\tif (!meta_list.IsEmpty())\r\n\t\t{\r\n\t\t\tint half;\r\n\t\t\tGridDims area = meta_list.GetList()->GetConcreteMeta()->GetArea();\r\n\t\t\tCGapManager::GapDescriptor *p_desc = m_manager->GetGapDescriptor(area, &half);\r\n\t\t\tif (p_desc)\r\n\t\t\t{\r\n\t\t\t\tif (m_current_gap.numCompleteHalves != 1)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_current_gap = *p_desc;\r\n\t\t\t\t}\r\n\t\t\t\tnew_mode = GAP_ADJUST;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tchange_mode(new_mode);\r\n\t\t\r\n\t\tif (m_current_gap.numCompleteHalves > 0)\r\n\t\t\tm_manager->HighlightMetasWithGaps(true, &m_current_gap);\r\n\t\telse\r\n\t\t\tm_manager->HighlightMetasWithGaps(true, NULL);\r\n\t}\r\n}\r\n\t\r\n\r\n\r\n\r\nvoid CCursor::set_source_meta(uint32 nameChecksum)\r\n{\r\n\t#ifndef DONT_USE_CURSOR_META\r\n\tif (mp_meta)\r\n\t{\r\n\t\tmp_meta->MarkUnlocked();\r\n\t\tm_manager->DestroyConcreteMeta(mp_meta, CParkManager::mDONT_DESTROY_PIECES_ABOVE);\r\n\t\tmp_meta = NULL;\r\n\t}\r\n\t\r\n\tCAbstractMetaPiece *p_source_meta = m_manager->GetAbstractMeta(nameChecksum);\r\n\tDbg_MsgAssert(p_source_meta, (\"couldn't find metapiece named %s\", Script::FindChecksumName(nameChecksum)));\r\n\t\r\n\tif (p_source_meta->IsRailPlacement())\r\n\t{\r\n\t\tm_cell_dims.SetWHL(1, 1, 1);\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_meta = m_manager->CreateConcreteMeta(p_source_meta, true);\r\n\t\tmp_meta->MarkLocked();\r\n\t\tm_cell_dims.SetWHL(mp_meta->GetArea().GetW(), mp_meta->GetArea().GetH(), mp_meta->GetArea().GetL());\r\n\t\tif (m_hard_rot & 1)\r\n\t\t\tm_cell_dims.SetWHL(m_cell_dims.GetL(), m_cell_dims.GetH(), m_cell_dims.GetW());\r\n\t}\r\n\t#else\r\n\tm_cell_dims.SetWHL(1, 1, 1);\t\r\n\t#endif\r\n\r\n\tClearAreaSelection();\r\n\r\n\tif (p_source_meta->IsGapPlacement())\r\n\t{\r\n\t\tchange_mode(GAP);\r\n\t\t//m_manager->HighlightMetasWithGaps(true, NULL);\r\n\t}\r\n\telse if (p_source_meta->IsAreaSelection())\r\n\t{\r\n\t\tchange_mode(AREA_SELECT);\r\n\t\tm_manager->HighlightMetasWithGaps(false, NULL);\r\n\t}\r\n\telse if (p_source_meta->IsRailPlacement())\r\n\t{\r\n\t\tchange_mode(RAIL_PLACEMENT);\r\n\t\tm_manager->HighlightMetasWithGaps(false, NULL);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tchange_mode(REGULAR);\r\n\t\tm_manager->HighlightMetasWithGaps(false, NULL);\r\n\t}\r\n\t\t\r\n\t//m_manager->AddMetaPieceToPark(GridDims(0, 8, 0), mp_meta);\r\n\r\n\t//printf(\"selected set %d, entry %d/%d\\n\", m_selected_set, m_palette_set[m_selected_set].mSelectedEntry, m_palette_set[m_selected_set].mTotalEntries);\r\n}\r\n\r\nvoid CCursor::change_mode(ECursorMode newMode)\r\n{\r\n\tif (m_mode != newMode)\r\n\t{\r\n\t\tm_mode = newMode;\r\n\t\tRefreshHelperText();\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CCursor::RefreshHelperText()\r\n{\r\n\tScript::CStruct params;\r\n\tif (m_mode == GAP_ADJUST)\r\n\t\tparams.AddChecksum(CRCD(0x6835b854,\"mode\"), CRCD(0xe75a3a17,\"gap_adjust\"));\r\n\telse if (m_mode == GAP)\r\n\t\tparams.AddChecksum(CRCD(0x6835b854,\"mode\"), CRCD(0x780a5cf3,\"gap_regular\"));\r\n\telse if (m_mode == RAIL_PLACEMENT)\r\n\t\tparams.AddChecksum(CRCD(0x6835b854,\"mode\"), CRCD(0xffd81c08,\"rail_placement\"));\r\n\telse\r\n\t\tparams.AddChecksum(CRCD(0x6835b854,\"mode\"), CRCD(0xb58efc2b,\"regular\"));\r\n\tScript::RunScript(\"parked_set_helper_text_mode\", &params);\r\n}\r\n\r\n\r\n\r\n\r\nbool CCursor::is_gap_descriptor_same_as_current(CGapManager::GapDescriptor *pDesc)\r\n{\r\n\tif (m_current_gap.numCompleteHalves == 1 && \r\n\t\t(pDesc->loc[0].GetX() != m_current_gap.loc[0].GetX() ||\r\n\t\t pDesc->loc[0].GetY() != m_current_gap.loc[0].GetY() ||\r\n\t\t pDesc->loc[0].GetZ() != m_current_gap.loc[0].GetZ()))\r\n\t{\r\n\t\t// we are currently working on a gap and it's not the same as the one at this location, so fail\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\t\r\n\r\n\r\n\r\nCUpperMenuManager::CUpperMenuManager()\r\n{\r\n\t//Rulon: Commented this out to prevent menu set items from being added twice\r\n\t//Enable();\r\n\r\n\tmp_current_set = NULL;\r\n\tm_current_entry_in_set = 0;\r\n\tm_current_set_index = 0;\r\n}\r\n\r\n\r\n\r\n\r\nCUpperMenuManager::~CUpperMenuManager()\r\n{\r\n\tDisable();\r\n}\r\n\r\n\r\n\r\n\r\nvoid CUpperMenuManager::SetSourceMeta(uint32 nameChecksum)\r\n{\r\n\t//Script::RunScript(\"parked_make_piece_menu\");\r\n\t\r\n\tCAbstractMetaPiece *p_source_meta = m_manager->GetAbstractMeta(nameChecksum);\r\n\tDbg_MsgAssert(p_source_meta, (\"couldn't find metapiece named %s\", Script::FindChecksumName(nameChecksum)));\r\n\t\r\n\tScript::CStruct params;\r\n\tparams.AddChecksum(\"metapiece_id\", nameChecksum);\r\n\tif (p_source_meta->IsSingular())\r\n\t{\r\n\t\tparams.AddChecksum(\"sector\", nameChecksum);\r\n\t\tScript::RunScript(\"parked_make_piece_menu_item\", &params);\t\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tScript::CArray sectors_array;\r\n\t\tp_source_meta->BuildElement3dSectorsArray(&sectors_array);\t\t\t\r\n\t\tparams.AddArray(\"sectors\", &sectors_array);\r\n\t\tScript::RunScript(\"parked_make_piece_menu_item\", &params);\t\t\t\r\n\t\tScript::CleanUpArray(&sectors_array);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CUpperMenuManager::SetPieceSet(CParkManager::CPieceSet *pSet, int set_number, int menuSetNumber)\r\n{\r\n\tParkEd(\"CUpperMenuManager::SetPieceSet(pSet = %p, set_number = %d)\", pSet, set_number);\r\n\t\r\n\tDbg_Assert(pSet);\r\n\t\r\n\tbool is_clipboard_set=false;\r\n\tint num_clipboards=0;\r\n\tif (pSet->mIsClipboardSet)\r\n\t{\r\n\t\tis_clipboard_set=true;\r\n\t\tnum_clipboards=CCursor::sInstance()->GetNumClipboards();\r\n\t\tCCursor::sInstance()->ClearAreaSelection();\r\n\t}\r\n\r\n\tObj::CTracker* p_tracker = Obj::CTracker::Instance();\r\n\tif (mp_current_set)\r\n\t{\r\n\t\t//uint32 name_crc = pSet->mEntryTab[m_current_entry_in_set].mNameCrc;\r\n\t\tuint32 name_crc = mp_current_set->mEntryTab[m_current_entry_in_set].mNameCrc;\r\n\t\t\r\n\t\tParkEd(\"unfocusing item in piece menu %s\", Script::FindChecksumName(name_crc));\r\n\t\tif (p_tracker->GetObject(name_crc))\r\n\t\t\tp_tracker->LaunchEvent(Obj::CEvent::TYPE_UNFOCUS, name_crc);\r\n\t}\r\n\t\r\n\tParkEd(\"current set is %p\\n\", mp_current_set);\r\n\tif (pSet != mp_current_set)\r\n\t{\r\n\t\t//printf(\"Script::RunScript(\\\"parked_make_piece_menu\\\");\");\r\n\t\tScript::RunScript(\"parked_make_piece_menu\");\r\n\t\t\r\n\t\tfor (int i = 0; i < pSet->mTotalEntries; i++)\r\n\t\t{\r\n\t\t\tuint32 name_checksum = pSet->mEntryTab[i].mNameCrc;\r\n\t\t\t\r\n\t\t\tif (is_clipboard_set)\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct params;\r\n\t\t\t\tparams.AddChecksum(\"metapiece_id\", name_checksum);\r\n\t\t\t\tif (i<num_clipboards)\r\n\t\t\t\t{\r\n\t\t\t\t\tparams.AddInteger(\"ClipBoardIndex\",i+1);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tparams.AddChecksum(NONAME,CRCD(0x66da03b3,\"EmptyClipBoard\"));\r\n\t\t\t\t}\t\r\n\t\t\t\tScript::RunScript(\"parked_make_piece_menu_item\", &params);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tCAbstractMetaPiece *p_source_meta = m_manager->GetAbstractMeta(name_checksum);\r\n\t\t\t\tDbg_MsgAssert(p_source_meta, (\"couldn't find metapiece named %s\", Script::FindChecksumName(name_checksum)));\r\n\t\t\t\t\r\n\t\t\t\tScript::CStruct params;\r\n\t\t\t\tparams.AddChecksum(\"metapiece_id\", name_checksum);\r\n\t\t\t\tif (p_source_meta->IsSingular())\r\n\t\t\t\t{\r\n\t\t\t\t\tparams.AddChecksum(\"sector\", name_checksum);\r\n\t\t\t\t\tScript::RunScript(\"parked_make_piece_menu_item\", &params);\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CArray sectors_array;\r\n\t\t\t\t\tp_source_meta->BuildElement3dSectorsArray(&sectors_array);\t\t\t\r\n\t\t\t\t\tparams.AddArray(\"sectors\", &sectors_array);\r\n\t\t\t\t\tScript::RunScript(\"parked_make_piece_menu_item\", &params);\t\t\t\r\n\t\t\t\t\tScript::CleanUpArray(&sectors_array);\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t}\r\n\r\n\t\tScript::RunScript(\"parked_make_set_menu\");\r\n\t\t\r\n\t\tScript::CStruct params;\r\n\t\tparams.AddInteger(\"set_number\", menuSetNumber);\r\n\t\tparams.AddInteger(\"last_set_number\", m_current_set_index);\r\n\t\tScript::RunScript(\"parked_lock_piece_and_set_menus\", &params);\r\n\t\t\r\n\t\tmp_current_set = pSet;\r\n\t\tm_current_set_index = menuSetNumber;\r\n\t}\r\n\r\n\t// m_current_entry_in_set\r\n\t\r\n\t//Dbg_Assert(m_current_entry_in_set >= 0 && m_current_entry_in_set < \r\n\t\r\n\tParkEd(\"focusing item in piece menu %s\", Script::FindChecksumName(pSet->mEntryTab[pSet->mSelectedEntry].mNameCrc));\r\n\tif (p_tracker->GetObject(pSet->mEntryTab[pSet->mSelectedEntry].mNameCrc))\r\n\t\tp_tracker->LaunchEvent(Obj::CEvent::TYPE_FOCUS, pSet->mEntryTab[pSet->mSelectedEntry].mNameCrc);\r\n\tm_current_entry_in_set = pSet->mSelectedEntry;\r\n\r\n\t/* Make the slider reflect the selection window */\r\n\t\r\n\tint first_in_window = m_current_entry_in_set - 3;\r\n\tint last_in_window = m_current_entry_in_set + 3;\r\n\tif (pSet->mTotalEntries <= 7)\r\n\t{\r\n\t\tfirst_in_window = 0;\r\n\t\tlast_in_window = pSet->mTotalEntries - 1;\r\n\t}\r\n\telse if (first_in_window < 0)\r\n\t{\r\n\t\tlast_in_window += -first_in_window;\r\n\t\tfirst_in_window = 0;\r\n\t}\r\n\telse if (last_in_window >= pSet->mTotalEntries)\r\n\t{\r\n\t\tfirst_in_window += pSet->mTotalEntries - last_in_window - 1;\r\n\t\tlast_in_window = pSet->mTotalEntries - 1;\r\n\t}\r\n\t\r\n\tFront::CScreenElementManager* p_element_manager = Front::CScreenElementManager::Instance();\r\n\tFront::CScreenElementPtr p_slider = p_element_manager->GetElement(Script::GenerateCRC(\"piece_slider_orange\"), Front::CScreenElementManager::ASSERT);\r\n\tfloat slider_x, slider_y;\r\n\tp_slider->GetLocalPos(&slider_x, &slider_y);\r\n\tfloat slider_start = 375.0f * first_in_window / pSet->mTotalEntries;\r\n\tfloat slider_end = 375.0f * (last_in_window + 1) / pSet->mTotalEntries;\r\n\tp_slider->SetPos(slider_start, slider_y, Front::CScreenElement::FORCE_INSTANT);\r\n\tp_slider->SetScale((slider_end - slider_start) / 4.0f, 1.0f, false, Front::CScreenElement::FORCE_INSTANT);\r\n\r\n\tFront::CScreenElementPtr p_name_text = p_element_manager->GetElement(Script::GenerateCRC(\"piece_menu_name_text\"), Front::CScreenElementManager::ASSERT);\r\n\tif (pSet->mEntryTab[m_current_entry_in_set].mpName)\r\n\t\t((Front::CTextElement *) p_name_text.Convert())->SetText(pSet->mEntryTab[m_current_entry_in_set].mpName);\r\n\telse\r\n\t\t((Front::CTextElement *) p_name_text.Convert())->SetText(\"---\");\r\n}\r\n\r\n\r\n\r\n\r\nvoid CUpperMenuManager::Enable()\r\n{\r\n\tParkEd(\"CUpperMenuManager::Enable()\");\r\n\t//printf(\"CUpperMenuManager::Enable()\");\r\n\t\r\n\tScript::RunScript(\"parked_make_piece_menu\");\t\t\t\r\n\tScript::RunScript(\"parked_make_set_menu\");\t\t\t\r\n\t\r\n\tfor (int i = 0; i < m_manager->GetTotalNumPieceSets(); i++)\r\n\t{\r\n\t\tCParkManager::CPieceSet &set = m_manager->GetPieceSet(i);\r\n\t\tif (set.mVisible)\r\n\t\t{\r\n\t\t\tScript::CStruct params;\r\n\t\t\tparams.AddString(\"set_name\", set.mpName);\r\n\t\t\tScript::RunScript(\"parked_make_set_menu_item\", &params);\r\n\t\t}\r\n\t}\r\n\r\n\t// will force menu to be rebuilt in SetPieceSet()\r\n\tmp_current_set = NULL;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CUpperMenuManager::Disable()\r\n{\r\n\tParkEd(\"CUpperMenuManager::Disable()\");\r\n\t\r\n\tScript::RunScript(\"parked_destroy_piece_menu\");\r\n\tScript::RunScript(\"parked_destroy_set_menu\");\r\n\tmp_current_set= NULL;\r\n}\r\n\r\nbool ScriptSetParkEditorTimeOfDay(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 tod_script=0;\r\n\tpParams->GetChecksum(CRCD(0x4c72ed98,\"tod_script\"),&tod_script);\r\n\tEd::CParkEditor::Instance()->SetTimeOfDayScript(tod_script);\r\n\treturn true;\r\n}\r\n\r\nbool ScriptGetParkEditorTimeOfDayScript(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 tod_script=Ed::CParkEditor::Instance()->GetTimeOfDayScript();\r\n\tif (tod_script)\r\n\t{\r\n\t\tpScript->GetParams()->AddChecksum(CRCD(0x4c72ed98,\"tod_script\"),tod_script);\r\n\t\treturn true;\r\n\t}\t\r\n\treturn false;\r\n}\r\n\r\n// Added so that when choosing to create a goal, the node array can be initialised, otherwise the\r\n// cursor will not be able to detect kill polys (unless a test play had been done)\r\nbool ScriptRebuildParkNodeArray(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tEd::CParkManager::sInstance()->RebuildNodeArray();\t\r\n\treturn true;\r\n}\r\n\t\r\nbool ScriptFreeUpMemoryForPlayingPark(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// The following will free up everything on the park editor heap, then delete the\r\n\t// heap itself.\r\n\r\n\tEd::CParkEditor::Instance()->CreatePlayModeGapManager();\r\n\t\r\n\tEd::CParkEditor::Instance()->DeleteCursor();\r\n\t// Note: Only destroying pieces, not the cloned sectors, otherwise the whole park\r\n\t// will disappear from beneath the skater.\r\n\tEd::CParkManager::sInstance()->Destroy(Ed::CParkGenerator::DESTROY_ONLY_PIECES);\r\n\t\r\n\tEd::CParkEditor::Instance()->SwitchToPlayModeGapManager();\r\n\t\r\n\treturn true;\r\n}\r\n\r\nbool ScriptCalibrateMemoryGauge(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// Old\r\n\treturn true;\r\n}\r\n\r\nbool ScriptGetParkEditorCursorPos(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCParkEditor* p_editor = CParkEditor::Instance();\r\n\tMth::Vector pos=p_editor->GetCursorPos();\r\n\tpScript->GetParams()->AddVector(CRCD(0x7f261953,\"pos\"),pos[X],pos[Y],pos[Z]);\r\n\treturn true;\r\n}\r\n\r\nbool ScriptSwitchToParkEditorCamera(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// Create the park editor camera if it does not exist, then switch to it.\r\n\tObj::CCompositeObject * p_obj = (Obj::CCompositeObject *) Obj::CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0x64716bee,\"parked_cam\"));\r\n\tif (!p_obj)\r\n\t{\r\n\t\tScript::CStruct * p_cam_params = new Script::CStruct;\r\n\t\tp_cam_params->AddChecksum(\"name\",CRCD(0x64716bee,\"parked_cam\"));\r\n\t\t\r\n\t\tObj::CCompositeObjectManager::Instance()->CreateCompositeObjectFromNode(\r\n\t\t\t\t\t\t\t\t\t\t\tScript::GetArray(\"parkedcam_composite_structure\"),p_cam_params);\r\n\t\t\r\n\t\tdelete\tp_cam_params;\r\n\t}\r\n\t\r\n\tCParkEditor::Instance()->SetAppropriateCamera();\t\r\n\r\n\treturn true;\r\n}\r\n\t\r\n/*\r\n\tParameters:\r\n\t\r\n\tstate\r\n\tcommand\r\n\t\r\n\tStates:\r\n\t-edit\r\n\t\tCommand:\r\n\t\t-initialize\r\n\t\t-clear whole park\r\n\t\t-regenerate from compressed map\r\n\t\t-build floor\r\n\t-test_play\r\n\t-off\r\n\t\r\n\tWill\r\n*/\r\nbool ScriptSetParkEditorState(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tParkEd(\"CCursor::ScriptSetParkEditorState()\");\r\n\t#if DEBUG_THIS_DAMN_THING\r\n\tScript::PrintContents(pParams, 4);\r\n\t#endif\r\n\t\r\n\tCParkEditor* p_editor = CParkEditor::Instance();\r\n\t\r\n\tCParkEditor::EEditorState new_state = CParkEditor::vKEEP_SAME_STATE;\r\n\tpParams->GetChecksum(\"state\", (uint32 *) &new_state);\r\n\tDbg_MsgAssert(new_state == CParkEditor::vEDITING ||\r\n\t\t\t\t  new_state == CParkEditor::vINACTIVE ||\r\n\t\t\t\t  new_state == CParkEditor::vREGULAR_PLAY ||\r\n\t\t\t\t  new_state == CParkEditor::vTEST_PLAY, \r\n\t\t\t\t  (\"invalid park editor state\"));\r\n\r\n\tCParkEditor::EEditorCommand command = CParkEditor::vNO_COMMAND;\r\n\tpParams->GetChecksum(\"command\", (uint32 *) &command);\r\n\tDbg_MsgAssert(command == CParkEditor::vINITIALIZE ||\r\n\t\t\t\t  command == CParkEditor::vCLEAR ||\r\n\t\t\t\t  command == CParkEditor::vREGENERATE_FROM_MAP ||\r\n\t\t\t\t  command == CParkEditor::vBUILD_FLOOR ||\r\n\t\t\t\t  command == CParkEditor::vNO_COMMAND,\r\n\t\t\t\t  (\"invalid park editor command\"));\r\n\t\r\n\tif (new_state == CParkEditor::vINACTIVE)\r\n\t{\r\n\t\tp_editor->SetState(new_state);\t\t\t\t\t\r\n\t\tp_editor->Cleanup();\r\n\t\tp_editor->SetPaused(false);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (command == CParkEditor::vINITIALIZE)\r\n\t\t{\r\n\t\t\tp_editor->Initialize((new_state == CParkEditor::vEDITING));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (command == CParkEditor::vCLEAR)\r\n\t\t\t\tp_editor->Rebuild(false, true, (new_state == CParkEditor::vEDITING));\r\n\t\t\telse if (command == CParkEditor::vREGENERATE_FROM_MAP)\r\n\t\t\t\tp_editor->Rebuild(false, false, (new_state == CParkEditor::vEDITING));\r\n\t\t\telse if (command == CParkEditor::vBUILD_FLOOR)\r\n\t\t\t\tp_editor->Rebuild(true, false, (new_state == CParkEditor::vEDITING));\t\t\t\r\n\t\t}\r\n\t\tp_editor->SetState(new_state);\t\t\t\t\t\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptSetParkEditorPauseMode(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tParkEd(\"CCursor::ScriptSetParkEditorPauseMode()\");\r\n\t#if DEBUG_THIS_DAMN_THING\r\n\tScript::PrintContents(pParams, 4);\r\n\t#endif\r\n\t\r\n\tCParkEditor* p_editor = CParkEditor::Instance();\r\n\t\r\n\tif (pParams->ContainsFlag(\"pause\"))\r\n\t\tp_editor->SetPaused(true);\r\n\telse if (pParams->ContainsFlag(\"unpause\"))\r\n\t\tp_editor->SetPaused(false);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptCustomParkMode(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCParkEditor* p_editor = CParkEditor::Instance();\r\n\tif (pParams->ContainsFlag(\"editing\"))\r\n\t{\r\n\t\treturn p_editor->EditingCustomPark();\r\n\t}\r\n\telse if (pParams->ContainsFlag(\"testing\"))\r\n\t{\r\n\t\treturn p_editor->TestingCustomPark();\r\n\t}\r\n\telse if (pParams->ContainsFlag(\"just_using\"))\r\n\t{\r\n\t\treturn p_editor->UsingCustomPark();\r\n\t}\r\n\t\r\n\tDbg_MsgAssert(0, (\"need a parameter -- 'editing' or 'just_using'\"));\r\n\treturn false;\r\n}\r\n\r\nbool ScriptSetParkEditorMaxPlayers(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint max_players=1;\r\n\tpParams->GetInteger(NONAME,&max_players);\r\n\tDbg_MsgAssert(max_players>=1 && max_players<=8,(\"\\n%s\\nBad value of %d sent to SetParkEditorMaxPlayers\",pScript->GetScriptInfo(),max_players));\r\n\t\r\n\tCParkManager::Instance()->GetGenerator()->SetMaxPlayers(max_players);\r\n\r\n\treturn true;\r\n}\t\r\n\r\nbool ScriptGetParkEditorMaxPlayers(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->AddInteger(\"MaxPlayers\",CParkManager::Instance()->GetGenerator()->GetMaxPlayers());\r\n\treturn true;\r\n}\t\r\n\r\nbool ScriptGetParkEditorMaxPlayersPossible(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->AddInteger(\"MaxPlayersPossible\",CParkManager::Instance()->GetGenerator()->GetMaxPlayersPossible());\r\n\treturn true;\r\n}\t\r\n\r\n\r\n// a helper function used by ScriptCanCleanlyResizePark(), ScriptResizePark()\r\nGridDims ComputeResizedDims(Script::CStruct *pParams)\r\n{\r\n\t// these are the current bounds, may be replaced with new info\r\n\tGridDims new_bounds = CParkManager::sInstance()->GetParkNearBounds();\t\r\n\t\r\n\t// assume current w,l unless new parms passed in\r\n\tint w = new_bounds.GetW();\r\n\tint l = new_bounds.GetL();\r\n\tpParams->GetInteger(\"w\", &w);\r\n\tpParams->GetInteger(\"l\", &l);\r\n\r\n\t// these diffs may be replaced below\r\n\tint w_diff = w - (int) new_bounds.GetW();\r\n\tint l_diff = l - (int) new_bounds.GetL();\r\n\r\n\tif (pParams->GetInteger(\"inc_w\", &w_diff))\r\n\t\tw = new_bounds.GetW() + w_diff;\r\n\tif (pParams->GetInteger(\"inc_l\", &l_diff))\r\n\t\tl = new_bounds.GetL() + l_diff;\r\n\t\r\n\tnew_bounds[X] = new_bounds[X] - w_diff / 2;\r\n\tnew_bounds[Z] = new_bounds[Z] - l_diff / 2;\r\n\tnew_bounds[W] = w;\r\n\tnew_bounds[L] = l;\r\n\r\n\t\r\n\treturn new_bounds;\r\n}\r\n\r\n// Prevents rail points or goal peds being placed too close to the edge of the park.\r\nbool IsWithinParkBoundaries(Mth::Vector pos, float margin)\r\n{\r\n\tGridDims park_bounds = CParkManager::sInstance()->GetParkNearBounds();\t\r\n\tMth::Vector corner_pos;\r\n\tMth::Vector area_dims;\r\n\tcorner_pos=Ed::CParkManager::Instance()->GridCoordinatesToWorld(park_bounds,&area_dims);\r\n\r\n\tif (pos[X] > corner_pos[X]+margin && pos[X] < corner_pos[X]+area_dims[X]-margin &&\r\n\t\tpos[Z] > corner_pos[Z]+margin && pos[Z] < corner_pos[Z]+area_dims[Z]-margin)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\t\t\r\n\r\n\r\nbool ScriptCanCleanlyResizePark(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGridDims new_bounds;\r\n\t\r\n\tScript::CStruct *p_new_bounds=NULL;\r\n\tif (pParams->GetStructure(CRCD(0xb4f88771,\"NewBounds\"),&p_new_bounds))\r\n\t{\r\n\t\tint x,z,w,l;\r\n\t\tp_new_bounds->GetInteger(CRCD(0x7323e97c,\"x\"),&x);\r\n\t\tp_new_bounds->GetInteger(CRCD(0x9d2d8850,\"z\"),&z);\r\n\t\tp_new_bounds->GetInteger(CRCD(0xe39cf4ed,\"w\"),&w);\r\n\t\tp_new_bounds->GetInteger(CRCD(0x69f93d01,\"l\"),&l);\r\n\t\tnew_bounds.SetXYZ(x,0,z);\r\n\t\tnew_bounds.SetWHL(w,1,l);\r\n\t\t\r\n\t\tbool can_resize=true;\r\n\t\tif (CParkManager::sInstance()->AreMetasOutsideBounds(new_bounds))\r\n\t\t{\r\n\t\t\tcan_resize=false;\r\n\t\t}\r\n\t\t\r\n\t\tMth::Vector corner_pos;\r\n\t\tMth::Vector area_dims;\r\n\t\tcorner_pos=Ed::CParkManager::Instance()->GridCoordinatesToWorld(new_bounds,&area_dims);\r\n\t\tif (Obj::GetRailEditor()->ThereAreRailPointsOutsideArea(corner_pos[X]+PARK_BOUNDARY_MARGIN, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcorner_pos[Z]+PARK_BOUNDARY_MARGIN,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcorner_pos[X]+area_dims[X]-PARK_BOUNDARY_MARGIN, \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcorner_pos[Z]+area_dims[Z]-PARK_BOUNDARY_MARGIN))\r\n\t\t{\r\n\t\t\tcan_resize=false;\r\n\t\t}\r\n\r\n\t\tif (Obj::GetGoalEditor()->ThereAreGoalsOutsideArea(corner_pos[X], corner_pos[Z], corner_pos[X]+area_dims[X], corner_pos[Z]+area_dims[Z]))\r\n\t\t{\r\n\t\t\tcan_resize=false;\r\n\t\t}\r\n\t\t\r\n\t\treturn can_resize;\t\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\nvoid ResizePark(GridDims newBounds)\r\n{\r\n\tCParkManager::sInstance()->RebuildInnerShell(newBounds);\r\n\tCParkManager::sInstance()->RebuildFloor();\r\n\r\n\tMth::Vector corner_pos;\r\n\tMth::Vector area_dims;\r\n\tcorner_pos=Ed::CParkManager::Instance()->GridCoordinatesToWorld(newBounds,&area_dims);\r\n\tObj::GetRailEditor()->ClipRails(corner_pos[X]+PARK_BOUNDARY_MARGIN, corner_pos[Z]+PARK_BOUNDARY_MARGIN,\r\n\t\t\t\t\t\t\t\t\tcorner_pos[X]+area_dims[X]-PARK_BOUNDARY_MARGIN, corner_pos[Z]+area_dims[Z]-PARK_BOUNDARY_MARGIN,\r\n\t\t\t\t\t\t\t\t\tObj::CRailEditorComponent::DELETE_POINTS_OUTSIDE);\r\n\tObj::GetGoalEditor()->DeleteGoalsOutsideArea(corner_pos[X], corner_pos[Z], corner_pos[X]+area_dims[X], corner_pos[Z]+area_dims[Z]);\r\n\t\r\n\tCParkEditor::Instance()->DestroyClipboardsWhichAreTooBigToFit();\r\n}\r\n\r\nbool ScriptResizePark(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tstatic GridDims stored_dims;\r\n\t\r\n\tGridDims new_bounds;\r\n\t\r\n\tScript::CStruct *p_new_bounds=NULL;\r\n\tif (pParams->GetStructure(CRCD(0xb4f88771,\"NewBounds\"),&p_new_bounds))\r\n\t{\r\n\t\tint x,z,w,l;\r\n\t\tp_new_bounds->GetInteger(CRCD(0x7323e97c,\"x\"),&x);\r\n\t\tp_new_bounds->GetInteger(CRCD(0x9d2d8850,\"z\"),&z);\r\n\t\tp_new_bounds->GetInteger(CRCD(0xe39cf4ed,\"w\"),&w);\r\n\t\tp_new_bounds->GetInteger(CRCD(0x69f93d01,\"l\"),&l);\r\n\t\tnew_bounds.SetXYZ(x,0,z);\r\n\t\tnew_bounds.SetWHL(w,1,l);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tnew_bounds = ComputeResizedDims(pParams);\r\n\t}\r\n\t\r\n\t\r\n\tif (pParams->ContainsFlag(\"delayed\"))\r\n\t{\r\n\t\tstored_dims = new_bounds;\r\n\t}\r\n\telse \r\n\t{\r\n\t\tif (pParams->ContainsFlag(\"use_stored\"))\r\n\t\t{\r\n\t\t\tnew_bounds = stored_dims;\r\n\t\t}\r\n\t\tif (!CParkManager::sInstance()->EnoughMemoryToResize(new_bounds))\r\n\t\t{\r\n\t\t\tScript::RunScript(\"parked_show_out_of_memory_message\");\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t\t\t\r\n\t\tResizePark(new_bounds);\r\n\t\t// Refresh the rail geometry so that UpdateSuperSectors gets called on them.\r\n\t\t//Obj::GetRailEditor()->RefreshGeometry();\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\nbool ScriptGetCurrentParkBounds(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGridDims bounds = CParkManager::sInstance()->GetParkNearBounds();\t\r\n\tpScript->GetParams()->AddInteger(CRCD(0x7323e97c,\"x\"),bounds.GetX());\r\n\tpScript->GetParams()->AddInteger(CRCD(0x9d2d8850,\"z\"),bounds.GetZ());\r\n\tpScript->GetParams()->AddInteger(CRCD(0xe39cf4ed,\"w\"),bounds.GetW());\r\n\tpScript->GetParams()->AddInteger(CRCD(0x69f93d01,\"l\"),bounds.GetL());\r\n\treturn true;\r\n}\t\r\n\r\nbool ScriptCanChangeParkDimension(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGridDims current_bounds = CParkManager::sInstance()->GetParkNearBounds();\r\n\tGridDims max_bounds = CParkManager::sInstance()->GetParkFarBounds();\r\n\t\r\n\tScript::CArray *p_dim_array = NULL;\r\n\tif (pParams->GetArray(NONAME, &p_dim_array))\r\n\t{\r\n\t\tint w = p_dim_array->GetInt(0);\r\n\t\tint l = p_dim_array->GetInt(1);\r\n\t\tif (w != current_bounds.GetW() || l != current_bounds.GetL())\r\n\t\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// otherwise, decrease\r\n\t\tbool test_for_increase = pParams->ContainsFlag(\"up\");\r\n\t\r\n\t\tif (pParams->ContainsFlag(\"width\"))\r\n\t\t{\r\n\t\t\tif (test_for_increase && current_bounds.GetW() < max_bounds.GetW()) return true;\r\n\t\t\telse if (!test_for_increase && current_bounds.GetW() > 16) return true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (test_for_increase && current_bounds.GetL() < max_bounds.GetL()) return true;\r\n\t\t\telse if (!test_for_increase && current_bounds.GetL() > 16) return true;\r\n\t\t}\r\n\t}\r\n\t\t\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptSaveParkToDisk(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint slot = 0;\r\n\tpParams->GetInteger(\"slot\", &slot, Script::ASSERT);\r\n\t// XXX\r\n\tRyan(\"saving park at slot %d\\n\", slot);\r\n\tCParkEditor* p_editor = CParkEditor::Instance();\r\n\tp_editor->AccessDisk(true, slot, false);\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptLoadParkFromDisk(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint slot = 0;\r\n\tpParams->GetInteger(\"slot\", &slot, Script::ASSERT);\r\n\r\n\tbool block_rebuild = pParams->ContainsFlag(\"block_rebuild\");\r\n\r\n\t// XXX\r\n\tRyan(\"loading park in slot %d\\n\", slot);\r\n\tCParkEditor* p_editor = CParkEditor::Instance();\r\n\tp_editor->AccessDisk(false, slot, block_rebuild);\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptIsParkUnsaved(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn !CParkManager::sInstance()->IsMapSavedLocally();\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptFireCustomParkGap(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint gap_index;\r\n\tpParams->GetInteger(\"gap_index\", &gap_index, true);\r\n\r\n\t// XXX\r\n\tRyan(\"ScriptFireCustomParkGap() %d\\n\", gap_index);\r\n\t\r\n\tCGapManager::sInstance()->LaunchGap(gap_index, pScript);\r\n\treturn true;\r\n}\r\n\r\nbool ScriptSetEditedParkGapInfo(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_name = NULL;\r\n\tpParams->GetString(\"name\", &p_name);\r\n\tint score = -1;\r\n\tpParams->GetInteger(\"score\", &score);\r\n\t\r\n\tCCursor::sInstance()->SetGapNameAndScore(p_name, score);\r\n\r\n\tScript::CStruct *p_cancel_flags=NULL;\r\n\tpParams->GetStructure(CRCD(0x49ec3f9,\"cancel_flags\"),&p_cancel_flags);\r\n\tCCursor::sInstance()->SetGapCancelFlags(p_cancel_flags);\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptGetEditedParkGapName(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->AddString(\"name\", CCursor::sInstance()->GetGapName());\r\n\r\n\treturn true;\r\n}\r\n\r\nbool ScriptParkEditorSelectionAreaTooBigToCopy(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn CCursor::sInstance()->SelectionAreaTooBigToCopy();\r\n}\r\n\r\nbool ScriptCopyParkEditorSelectionToClipboard(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tbool success=CCursor::sInstance()->CopySelectionToClipboard();\r\n\tCCursor::sInstance()->ClearAreaSelection();\t\r\n\treturn success;\r\n}\r\n\r\nbool ScriptSwitchParkEditorMenuPieceToMostRecentClipboard(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCParkEditor::Instance()->SwitchMenuPieceToMostRecentClipboard();\r\n\treturn true;\r\n}\r\n\r\nbool ScriptCutParkEditorAreaSelection(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tbool success=CCursor::sInstance()->CopySelectionToClipboard();\r\n\tif (success)\r\n\t{\r\n\t\tCCursor::sInstance()->DeleteSelectedPieces();\r\n\t\tCCursor::sInstance()->ResetSelectedHeights();\r\n\t}\r\n\tCCursor::sInstance()->ClearAreaSelection();\t\r\n\treturn success;\r\n}\r\n\r\nbool ScriptParkEditorAreaSelectionDeletePieces(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCCursor::sInstance()->DeleteSelectedPieces();\r\n\treturn true;\r\n}\r\n\r\nbool ScriptContinueParkEditorAreaSelection(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCCursor::sInstance()->ContinueAreaSelection();\r\n\treturn true;\r\n}\r\n\t\r\nbool ScriptGetEditorTheme(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->AddInteger(CRCD(0x688a18f7,\"theme\"), CParkManager::sInstance()->GetTheme());\r\n\treturn true;\r\n}\r\n\r\nbool ScriptSetEditorTheme(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint theme=0;\r\n\tpParams->GetInteger(CRCD(0x688a18f7,\"theme\"),&theme);\r\n\tCParkManager::sInstance()->SetTheme(theme);\r\n\treturn true;\r\n}\r\n\r\nbool ScriptGetEditorMaxThemes(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->AddInteger(CRCD(0x7ddc0da8,\"max_themes\"), MAX_THEMES);\r\n\treturn true;\r\n}\r\n\r\nbool ScriptGetCustomParkName(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint truncate_char_num = -1;\r\n\tpParams->GetInteger(NONAME, &truncate_char_num);\r\n\t\r\n\tconst char *p_name = CParkManager::sInstance()->GetParkName();\r\n\t\r\n\tif (truncate_char_num == -1)\r\n\t{\r\n\t\tif (p_name)\r\n\t\t\tpScript->GetParams()->AddString(\"name\", p_name);\r\n\t\telse\r\n\t\t\tpScript->GetParams()->AddString(\"name\", \"unnamed park\");\r\n\t}\r\n\telse\r\n\t{\r\n\t\tchar out_name[64];\r\n\t\tfor (int i = 0; i < truncate_char_num; i++)\r\n\t\t\tout_name[i] = p_name[i];\r\n\t\tout_name[truncate_char_num] = '\\0';\r\n\t\tpScript->GetParams()->AddString(\"name\", out_name);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptSetCustomParkName(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_name = NULL;\r\n\tpParams->GetString(\"name\", &p_name, Script::ASSERT);\r\n\tCParkManager::sInstance()->SetParkName(p_name);\r\n\treturn true;\r\n}\r\n\r\n\r\n// @script | IsCustomPark | returns true if this is a custom park\r\nbool ScriptIsCustomPark(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\treturn Ed::CParkEditor::Instance()->UsingCustomPark();\r\n}\r\n\r\n\r\n\r\nbool ScriptBindParkEditorToController( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tint controller;\r\n\tpParams->GetInteger( NONAME, &controller, Script::ASSERT );\r\n\tCParkEditor* p_editor = CParkEditor::Instance();\r\n\tp_editor->BindParkEditorToController( controller );\r\n\treturn true;\r\n}\r\n\r\n#ifdef __PLAT_NGC__\r\n// Required in order that the park rebuild when defragmenting during resizing does not\r\n// reset the map heights.\r\n// (Used in the script parked_defragment_memory_for_resize in sk5ed_scripts)\r\nbool ScriptWriteCompressedMapBuffer(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tCParkManager::sInstance()->WriteCompressedMapBuffer();\r\n\treturn true;\r\n}\r\n\r\nbool ScriptRequiresDefragment(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMem::Heap *p_top_down_heap = Mem::Manager::sHandle().TopDownHeap();\r\n\tif (p_top_down_heap->mp_region->MemAvailable() < TOP_DOWN_REQUIRED_MARGIN)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n        Mem::Heap *p_main_heap = Mem::Manager::sHandle().BottomUpHeap();\r\n        if (p_main_heap->mFreeMem.m_count > 200000)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool ScriptTopDownHeapTooLow(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMem::Heap *p_top_down_heap = Mem::Manager::sHandle().TopDownHeap();\r\n\tif (p_top_down_heap->mp_region->MemAvailable() < TOP_DOWN_REQUIRED_MARGIN)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\t\r\n\r\n#endif\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sk/ParkEditor2/ParkEd.h",
    "content": "#ifndef __SK_PARKEDITOR2_PARKED_H\r\n#define __SK_PARKEDITOR2_PARKED_H\r\n\r\n#include <core/task.h>\r\n#include <core/math/vector.h>\r\n#include <gel/inpman.h>\r\n#include <gel/Event.h>\r\n#include <gel/modman.h>\r\n#include <gfx/camera.h>\r\n#include <sk/ParkEditor2/EdMap.h>\r\n\r\n// At least this much is required on the top down heap during editing to ensure that\r\n// UpdateSuperSectors will have enough space to execute when raising large areas of ground.\r\n#ifdef __PLAT_NGC__\r\n#define TOP_DOWN_REQUIRED_MARGIN 1000000\r\n#define TOP_DOWN_REQUIRED_MARGIN_LEEWAY 100000\r\n#else\r\n#define TOP_DOWN_REQUIRED_MARGIN 1000000\r\n// A defrag will only occur if freeing up the fragments will make the top down heap have this much\r\n// more than the above margin. Could probably make this zero, just included to make sure it doesn't\r\n// try to defrag too much.\r\n#define TOP_DOWN_REQUIRED_MARGIN_LEEWAY 2000\r\n#endif\r\n\r\n\r\nclass Coord\r\n{\r\npublic:\r\n\tfloat m_X;\r\n\tfloat m_Y;\r\n};\r\n\r\n\r\nnamespace Ed\r\n{\r\n\r\nenum\r\n{\r\n\tMAX_THEMES=5\r\n};\r\n\r\nclass CCursor;\r\nclass CUpperMenuManager;\r\nclass CClipboard;\r\n\r\n\r\n\r\nclass CParkEditor : public Mdl::Module, public Obj::CEventListener \r\n{\r\n\t\r\n\tDeclareSingletonClass( CParkEditor );\r\n\t\r\n\tCParkEditor();\r\n\t~CParkEditor();\r\n\r\npublic:\r\n\r\n\tenum EEditorState\r\n\t{\r\n\t\tvINACTIVE\t\t\t\t\t\t\t\t= 0xd443a2bc,\t// \"off\"\r\n\t\tvEDITING\t\t\t\t\t\t\t\t= 0x7eca21e5,\t// \"edit\"\r\n\t\tvTEST_PLAY\t\t\t\t\t\t\t\t= 0xa40f0b8a,\t// \"test_play\"\r\n\t\tvREGULAR_PLAY\t\t\t\t\t\t\t= 0xcd3682c1,\t// \"regular_play\"\r\n\t\t\r\n\t\t// use this as parameter only\r\n\t\tvKEEP_SAME_STATE\t\t\t\t\t\t= 0,\r\n\t};\r\n\r\n\tenum EEditorCommand\r\n\t{\r\n\t\tvINITIALIZE\t\t\t\t\t\t\t\t= 0x27f2117d,\t// \"initialize\"\r\n\t\tvCLEAR\t\t\t\t\t\t\t\t\t= 0x1a4e0ef9,\t// \"clear\"\r\n\t\tvREGENERATE_FROM_MAP\t\t\t\t\t= 0x2a907cbc,\t// \"regenerate_from_map\"\r\n\t\tvBUILD_FLOOR\t\t\t\t\t\t\t= 0x1625eda,\t// \"build_floor\"\r\n\r\n\t\tvNO_COMMAND\t\t\t\t\t\t\t\t= 0,\r\n\t};\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\t\tInitialize(bool edit_mode);\r\n\tvoid \t\t\t\t\t\t\t\t\t\tRebuild(bool justRebuildFloor, bool clearMap, bool makeCursor);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tSetState(EEditorState desiredState);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tAccessDisk(bool save, int slot, bool blockRebuild);\r\n\tvoid \t\t\t\t\t\t\t\t\t\tPostMemoryCardLoad(uint8 * p_map_buffer, int oldTheme);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tCleanup();\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\t\t\tSetAppropriateCamera();\r\n\t\r\n\t// K: Added to allow cleanup of the park editor heap during play\r\n\tvoid\t\t\t\t\t\t\t\t\t\tDeleteCursor();\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\t\tUpdate();\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\t\tSwitchMenuPieceToMostRecentClipboard();\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\t\t\tSetPaused(bool paused);\r\n\tvoid \t\t\t\t\t\t\t\t\t\tMakeEditorStuffVisible( bool visible);\r\n\t\r\n\tbool\t\t\t\t\t\t\t\t\t\tUsingCustomPark() {return m_state != vINACTIVE;}\r\n\t// returns true if actually editing right now\r\n\tbool\t\t\t\t\t\t\t\t\t\tEditingCustomPark() {return m_state == vEDITING;}\r\n\tbool\t\t\t\t\t\t\t\t\t\tTestingCustomPark() {return m_state == vTEST_PLAY;}\r\n\r\n\t// returns true if park is full\r\n\tbool\t   \t\t\t\t\t\t\t\t\tIsParkFull() {return m_pct_resources_used >= 1.0f;} \t\t\t\t\t\t\t\t\r\n\tbool\t\t\t\t\t\t\t\t\t\tRoomToCopyOrPaste(int w, int l);\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\t\tBindParkEditorToController( int controller );\r\n\tMth::Vector&\t\t\t\t\t\t\t\tGetCursorPos();\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\t\t\tDestroyClipboardsWhichAreTooBigToFit();\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\t\t\tSetTimeOfDayScript(uint32 tod_script);\r\n\tuint32\t\t\t\t\t\t\t\t\t\tGetTimeOfDayScript() {return m_tod_script;}\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\t\t\tCreatePlayModeGapManager();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tSwitchToPlayModeGapManager();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tDeletePlayModeGapManager();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tPlayModeGapManagerChecks();\r\n\t\r\nprivate:\t\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\t\tdo_piece_select_commands();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tregular_command_logic();\r\n\tvoid\t\t\t\t\t\t\t\t\t\trail_placement_logic();\r\n\t\r\n\tint\t\t\t\t\t\t\t\t\t\t\tm_last_main_heap_free;\r\n\t\r\n\t// A flag which is set whenever an operation is done that could increase memory usage.\r\n\t// This permits a defrag to be done if required. The flag is reset every frame.\r\n\t// The flag is required to prevent an infinite loop of defrags.\r\n\tbool \t\t\t\t\t\t\t\t\t\tm_allow_defrag;\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\t\t\tturn_on_or_update_piece_menu();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tupdate_analog_stick_menu_control_state();\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\t\t\tpass_event_to_listener(Obj::CEvent *pEvent);\r\n\r\n\tenum Commands\r\n\t{\r\n\t\t// some are aliases\r\n\t\t\r\n\t\tmROTATE_CW         \t= nBit( 1 ),\r\n\t\tmROTATE_CCW        \t= nBit( 2 ),\r\n\t\tmPREV_PIECE        \t= nBit( 3 ),\r\n\t\tmNEXT_PIECE        \t= nBit( 4 ),\r\n\t\tmPLACE_PIECE       \t= nBit( 5 ),\r\n\t\tmREMOVE_PIECE      \t= nBit( 6 ),\r\n\t\tmRAISE_FLOOR      \t= nBit( 7 ),\r\n\t\tmLOWER_FLOOR      \t= nBit( 8 ),\r\n\t\tmPREV_SET        \t= nBit( 9 ),\r\n\t\tmNEXT_SET        \t= nBit( 10 ),\r\n\t\tmZOOM_CAMERA_OUT\t= nBit( 13 ),\r\n\t\tmZOOM_CAMERA_IN\t\t= nBit( 14 ),\r\n\r\n\t\tmROTATE_GAP_CW\t\t= nBit( 1 ),\r\n\t\tmROTATE_GAP_CCW\t\t= nBit( 2 ),\r\n\t\tmPLACE_GAP       \t= nBit( 5 ),\r\n\t\tmREMOVE_GAP       \t= nBit( 6 ),\r\n#ifdef __PLAT_NGC__\r\n\t\tmINCREASE_GAP_LEFT\t= nBit( 0 ),\r\n\t\tmDECREASE_GAP_LEFT\t= nBit( 15 ),\r\n\t\tmINCREASE_GAP_RIGHT\t= nBit( 11 ),\r\n\t\tmDECREASE_GAP_RIGHT\t= nBit( 12 ),\r\n#else\r\n\t\tmINCREASE_GAP_LEFT\t= nBit( 15 ),\r\n\t\tmDECREASE_GAP_LEFT\t= nBit( 16 ),\r\n\t\tmINCREASE_GAP_RIGHT\t= nBit( 11 ),\r\n\t\tmDECREASE_GAP_RIGHT\t= nBit( 12 ),\r\n#endif\t\t// __PLAT_NGC__\r\n\t};\r\n\r\n\tstatic const float\t\t\t\tvMAX_CAM_DIST;\r\n\tstatic const float\t\t\t\tvMIN_CAM_DIST;\r\n\tstatic const float\t\t\t\tvCAM_DIST_INC;\r\n\tstatic const float\t\t\t\tvCAM_TARGET_ELEVATION;\r\n\t\r\n\tstatic\tTsk::Task< CParkEditor >::Code\t\ts_logic_code;\r\n\tstatic\tTsk::Task< CParkEditor >::Code\t\ts_display_code;\r\n\tstatic\tInp::Handler< CParkEditor >::Code  \ts_input_logic_code;\r\n\r\n\tTsk::Task< CParkEditor >*\t\t\t\t\tm_logic_task;\t\r\n    Tsk::Task< CParkEditor >*\t\t\t\t\tm_display_task;\r\n    Inp::Handler< CParkEditor >*\t\t\t\tm_input_handler;\r\n\t\r\n\tfloat\t\t\t\t\t\t\t\t\t\tm_movement_vel;\t// in inches per sec\r\n\tfloat\t\t\t\t\t\t\t\t\t\tm_rotate_vel;\t// in degrees per sec\r\n    \r\n\tCoord                      \t\t\tm_rightStick;\r\n    Coord                      \t\t\tm_leftStick;\r\n    Flags<Commands>                 \t\t\tm_commands;\r\n\t\r\n\tGfx::Camera*\t\t\t\t\t\t\t\tmp_camera;\r\n\tfloat\t\t\t\t\t\t\t\t\t\tm_camAngle;\r\n\tfloat\t\t\t\t\t\t\t\t\t\tm_camAngleVert;\r\n\tfloat\t\t\t\t\t\t\t\t\t\tm_camDist;\r\n\t\r\n\tenum CursorState\r\n\t{\r\n\t\t\t\t\t\t\t\t\t\t\t\tvMOVEMENT,\r\n\t\t\t\t\t\t\t\t\t\t\t\tvGAP_MOVE,\r\n\t\t\t\t\t\t\t\t\t\t\t\tvGAP_ADJUST,\r\n\t};\r\n\t\r\n\tCursorState\t\t\t\t\t\t\t\t\tm_cursor_state;\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\t\t\tv_start_cb( void );\r\n\tvoid\t\t\t\t\t\t\t\t\t\tv_stop_cb( void );\r\n    \t\r\n\tSpt::SingletonPtr<CParkManager>\t\t\t\tmp_park_manager;\r\n\r\n\tMth::Vector\t\t\t\t\t\t\t\t\tm_cursor_pos;\r\n\tCCursor *\t\t\t\t\t\t\t\t\tmp_cursor;\r\n\tCUpperMenuManager *\t\t\t\t\t\t\tmp_menu_manager;\r\n\r\n\tTmr::Time\t\t\t\t\t\t\t\t\tm_last_time;\r\n\r\n\tEEditorState\t\t\t\t\t\t\t\tm_state;\r\n\tbool\t\t\t\t\t\t\t\t\t\tm_paused;\r\n\t\r\n\tfloat\t\t\t\t\t\t\t\t\t\tm_pct_resources_used;\r\n\t\r\n\t// This is the name of the time-of-day script which gets passed to the\r\n\t// script_change_tod script in the parameter tod_action.\r\n\t// (see timeofday.q for the above scripts)\r\n\t// The time of day gets set in Sk5Ed_Startup and in parked_test_play (both in sk5ed_scripts.q)\r\n\t// and in GameFlow_StartRun\r\n\tuint32\t\t\t\t\t\t\t\t\t\tm_tod_script;\r\n\t\r\n\tCGapManager *\t\t\t\t\t\t\t\tmp_play_mode_gap_manager;\r\n\t/* Debugging */\r\n};\r\n\r\n\r\n\r\n\r\nclass CCursor\r\n{\r\n\tfriend class CParkEditor;\r\n\r\npublic:\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\tCCursor();\r\n\t\t\t\t\t\t\t\t\t\t\t\t~CCursor();\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\t\tDeleteMeta();\r\n\tvoid \t\t\t\t\t\t\t\t\t\tDestroyGeometry();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tDestroyAnyClipboardCursors();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tUpdate(float shiftX, float shiftZ, int rotInc);\r\n\tbool\t\t\t\t\t\t\t\t\t\tAttemptStamp();\r\n\tbool\t\t\t\t\t\t\t\t\t\tAttemptRemove();\r\n\tvoid \t\t\t\t\t\t\t\t\t\tInformOfMetapieceDeletion(CConcreteMetaPiece *pMeta);\r\n\tbool\t\t\t\t\t\t\t\t\t\tAttemptGap();\r\n\tbool\t\t\t\t\t\t\t\t\t\tAttemptRemoveGap();\r\n\tbool \t\t\t\t\t\t\t\t\t\tAdjustGap(int rot, int leftChange, int rightChange);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tSetGapNameAndScore(const char *pGapName, int score);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tSetGapCancelFlags(Script::CStruct *p_cancelFlags);\r\n\t\r\n\tconst char *\t\t\t\t\t\t\t\tGetGapName();\r\n\r\n\tint\t\t\t\t\t\t\t\t\t\t\tAttemptAreaSelect();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tClearAreaSelection();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tDeleteSelectedPieces();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tResetSelectedHeights();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tContinueAreaSelection();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tGetAreaSelectDims(GridDims *p_dims);\r\n\tbool\t\t\t\t\t\t\t\t\t\tDestroyMetasInCurrentArea();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tRefreshSelectionArea();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tForceSelectionAreaHighlightRefresh() {m_initialised_highlight=false;}\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\t\t\tChangePieceInSet(int dir);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tChangeSet(int dir);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tSwitchMenuPieceToMostRecentClipboard();\r\n\t\r\n\tbool\t\t\t\t\t\t\t\t\t\tChangeFloorHeight(GridDims dims, int height, int dir, bool uniformHeight);\r\n\tbool\t\t\t\t\t\t\t\t\t\tChangeFloorHeight(int dir);\r\n\tvoid \t\t\t\t\t\t\t\t\t\tHighlightIntersectingMetas(bool on);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tSetVisibility(bool visible);\r\n\r\n\tint\t\t\t\t\t\t\t\t\t\t\tGetSelectedSet(int *pMenuSetNumber) {*pMenuSetNumber = m_menu_set_number; return m_selected_set;}\r\n\tuint32\t\t\t\t\t\t\t\t\t\tGetChecksum() {return mp_meta->GetNameChecksum();}\r\n\r\n\tenum ECursorMode\r\n\t{\r\n\t\tNONE,\r\n\t\tREGULAR,\r\n\t\tGAP,\r\n\t\tGAP_ADJUST,\r\n\t\tAREA_SELECT,\r\n\t\tPASTE,\r\n\t\tRAIL_PLACEMENT,\r\n\t};\r\n\r\n\tECursorMode\t\t\t\t\t\t\t\t\tGetCursorMode() {return m_mode;}\r\n\tbool\t\t\t\t\t\t\t\t\t\tInGapMode() {return (m_mode == GAP || m_mode == GAP_ADJUST);}\r\n\tbool\t\t\t\t\t\t\t\t\t\tInAreaSelectMode() {return m_mode==AREA_SELECT;}\r\n\tbool\t\t\t\t\t\t\t\t\t\tInRailPlacementMode() {return m_mode==RAIL_PLACEMENT;}\r\n\tbool\t\t\t\t\t\t\t\t\t\tInPasteMode() {return m_mode==PASTE;}\r\n\tMth::ERot90\t\t\t\t\t\t\t\t\tGetRotation() {return m_hard_rot;}\r\n\tconst GridDims &\t\t\t\t\t\t\tGetPosition() {return m_cell_dims;}\r\n\tbool\t\t\t\t\t\t\t\t\t\tSelectionAreaTooBigToCopy();\r\n\tbool\t\t\t\t\t\t\t\t\t\tCopySelectionToClipboard();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tDeleteOldestClipboard();\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\t\t\tPasteCurrentClipboard();\r\n\tint\t\t\t\t\t\t\t\t\t\t\tGetNumClipboards();\r\n\tint\t\t\t\t\t\t\t\t\t\t\tGetClipboardY() {return m_clipboard_y;}\r\n\t\t\r\n\tbool\t\t\t\t\t\t\t\t\t\tIsSittingOnGap();\r\n\tbool\t\t\t\t\t\t\t\t\t\tHalfFinishedGap() {return m_current_gap.numCompleteHalves == 1;}\r\n\r\n\t// K: Made this public so that it can be called from CParkEditor::Rebuild\r\n\tvoid\t\t\t\t\t\t\t\t\t\tForceInBounds();\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\t\tDestroyClipboardsWhichAreTooBigToFit();\r\n\r\n\tstatic\tCCursor *\t\t\t\t\t\t\tsInstance(bool assert = true);\r\n\r\nprotected:\r\n\r\n\tvoid\t\t\t\t\t\t\t\t\t\tdestroy_clipboards();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tget_selected_area_coords(uint8 *p_x1, uint8 *p_z1, uint8 *p_x2, uint8 *p_z2);\r\n\t\r\n\tvoid\t\t\t\t\t\t\t\t\t\tchange_cell_pos(int incX, int incZ);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tset_source_meta(uint32 nameChecksum);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tchange_mode(ECursorMode newMode);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tRefreshHelperText();\r\n\r\n\tbool\t\t\t\t\t\t\t\t\t\tis_gap_descriptor_same_as_current(CGapManager::GapDescriptor *pDesc);\r\n\t\r\n\tstatic const float\t\t\t\t\t\t\tMOTION_PCT_INC;\r\n\tstatic const float\t\t\t\t\t\t\tROT_DEG_INC;\r\n\t\r\n\tSpt::SingletonPtr<CParkManager>\t\t\t\tm_manager;\r\n\r\n\tGridDims\t\t\t\t\t\t\t\t\tm_cell_dims;\r\n\t\r\n\tfloat\t\t\t\t\t\t\t\t\t\tm_motion_pct;\r\n\tfloat\t\t\t\t\t\t\t\t\t\tm_motion_pct_inc;\r\n\t\r\n\tMth::Vector\t\t\t\t\t\t\t\t\tm_target_pos;\r\n\tMth::Vector\t\t\t\t\t\t\t\t\tm_pos;\r\n\tbool\t\t\t\t\t\t\t\t\t\tm_am_moving;\r\n\r\n\tMth::ERot90\t\t\t\t\t\t\t\t\tm_hard_rot;\r\n\tfloat\t\t\t\t\t\t\t\t\t\tm_target_rot;\r\n\tfloat\t\t\t\t\t\t\t\t\t\tm_rot; // rotation on y, in degrees\r\n\r\n\r\n\tCConcreteMetaPiece *\t\t\t\t\t\tmp_meta;\r\n\t\r\n\t// Clipboard stuff\r\n\tuint8\t\t\t\t\t\t\t\t\t\tm_num_corners_selected; // 0,1 or 2\r\n\tGridDims\t\t\t\t\t\t\t\t\tmp_area_corners[2];\r\n\tbool\t\t\t\t\t\t\t\t\t\tm_initialised_highlight;\r\n\t\r\n\t// List of clipboards\r\n\tCClipboard *\t\t\t\t\t\t\t\tmp_clipboards;\r\n\t// This is the clip that will get placed when in paste mode.\r\n\tCClipboard *\t\t\t\t\t\t\t\tmp_current_clipboard;\r\n\tCClipboard *\t\t\t\t\t\t\t\tget_clipboard(int index);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tset_current_clipboard(int index);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tremove_clipboard(int index);\r\n\t// The y that must be added to the y of each clipboard entry such that\r\n\t// they align with the ground as best as possible.\r\n\tint\t\t\t\t\t\t\t\t\t\t\tm_clipboard_y;\r\n\t\r\n\r\n\t\r\n\t\r\n\tint\t\t\t\t\t\t\t\t\t\t\tm_selected_set;\r\n\tint\t\t\t\t\t\t\t\t\t\t\tm_menu_set_number;\r\n\r\n\tECursorMode\t\t\t\t\t\t\t\t\tm_mode;\r\n\r\n\t/* Gap Stuff */\r\n\r\n\tCGapManager::GapDescriptor\t\t\t\t\tm_current_gap;\r\n\tuint32\t\t\t\t\t\t\t\t\t\tm_gap_suffix_counter;\r\n\t\r\n\tstatic CCursor *\t\t\t\t\t\t\tsp_instance;\r\n};\r\n\r\n\r\n\r\n\r\nclass CUpperMenuManager\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\t\t\t\t\tCUpperMenuManager();\r\n\t\t\t\t\t\t\t\t\t\t\t\t~CUpperMenuManager();\r\n\r\n\tvoid \t\t\t\t\t\t\t\t\t\tSetSourceMeta(uint32 nameChecksum);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tSetPieceSet(CParkManager::CPieceSet *pSet, int set_number, int menuSetNumber);\r\n\tvoid\t\t\t\t\t\t\t\t\t\tEnable();\r\n\tvoid\t\t\t\t\t\t\t\t\t\tDisable();\r\n\r\nprotected:\r\n\r\n\tSpt::SingletonPtr<CParkManager>\t\t\t\tm_manager;\r\n\tCParkManager::CPieceSet *\t\t\t\t\tmp_current_set;\r\n\tint\t\t\t\t\t\t\t\t\t\t\tm_current_set_index;\r\n\tint\t\t\t\t\t\t\t\t\t\t\tm_current_entry_in_set;\r\n};\r\n\r\n\r\n#define PARK_BOUNDARY_MARGIN 10.0f\r\nbool IsWithinParkBoundaries(Mth::Vector pos, float margin);\r\n\r\n\r\nbool ScriptSetParkEditorTimeOfDay(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetParkEditorTimeOfDayScript(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRebuildParkNodeArray(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptFreeUpMemoryForPlayingPark(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCalibrateMemoryGauge(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetParkEditorCursorPos(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSwitchToParkEditorCamera(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetParkEditorState(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetParkEditorPauseMode(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCustomParkMode(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetParkEditorMaxPlayers(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetParkEditorMaxPlayers(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetParkEditorMaxPlayersPossible(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCanCleanlyResizePark(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptResizePark(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetCurrentParkBounds(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCanChangeParkDimension(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSaveParkToDisk(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptLoadParkFromDisk(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptIsParkUnsaved(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptFireCustomParkGap(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetEditedParkGapInfo(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetEditedParkGapName(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptParkEditorSelectionAreaTooBigToCopy(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCopyParkEditorSelectionToClipboard(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSwitchParkEditorMenuPieceToMostRecentClipboard(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCutParkEditorAreaSelection(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptParkEditorAreaSelectionDeletePieces(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptContinueParkEditorAreaSelection(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetEditorTheme(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetEditorTheme(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetEditorMaxThemes(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptGetCustomParkName(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetCustomParkName(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptBindParkEditorToController(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptIsCustomPark(Script::CStruct *pParams, Script::CScript *pScript);\r\n#ifdef __PLAT_NGC__\r\nbool ScriptWriteCompressedMapBuffer(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRequiresDefragment(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptTopDownHeapTooLow(Script::CStruct *pParams, Script::CScript *pScript);\r\n#endif\r\n\r\n\r\n}\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/ParkEditor2/ParkGen.cpp",
    "content": "#include <core/defines.h>\r\n#include <sk/ParkEditor2/ParkGen.h>\r\n#include <sk/ParkEditor2/EdMap.h>\t\t\t// Mick:  Added as we need to iterate over the ConcreteMetaPieces\r\n#include <core/math.h>\r\n\r\n#include <gel/collision/collision.h>\r\n#include <gel/collision/colltridata.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/scripting/gs_file.h>\r\n#include <sk/gamenet/gamenet.h>\r\n\r\n#include <sys/replay/replay.h>\t   // Needed to get the size of the replay buffer, for adjusting available memory\r\n\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <sk/components/raileditorcomponent.h>\r\n\r\n\r\n#include <gfx/nx.h>\r\n#include <gfx/NxSector.h>\r\n#include <gfx/NxGeom.h>\r\n#include <gfx/NxScene.h>\r\n#include <sk/heap_sizes.h>\r\n\r\n//#define\tDEBUG_RESTARTS\r\n\r\n#ifdef __PLAT_NGC__\r\n#include <gfx/ngc/p_nxscene.h>\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n#ifdef __PLAT_NGPS__\r\n#define PRINT_RAW_RESULTS 0\r\n\r\n#if PRINT_RAW_RESULTS\r\n#include <core/crc.h>\r\n#include <gfx/ngps/p_nxgeom.h>\r\n#include <gfx/ngps/nx/geomnode.h>\r\n#include <gfx/ngps/nx/dma.h>\r\n\r\n\r\nnamespace Nx\r\n{\r\n\textern void find_geom_leaves( NxPs2::CGeomNode *p_node, NxPs2::CGeomNode **leaf_array, int & num_nodes);\r\n}\r\n#endif // PRINT_RAW_RESULTS\r\n\r\n#endif\r\n\r\n\r\nnamespace Ed\r\n{\r\n\r\n\r\n\r\nconst float CParkGenerator::CELL_WIDTH = 120.0f;\r\nconst float CParkGenerator::CELL_HEIGHT = 48.0f;\r\nconst float CParkGenerator::CELL_LENGTH = 120.0f;\r\n\r\n\r\n// the first range of ids are used for regular objects and object nodes\r\n// the second for rail nodes\r\nconst uint32 CParkGenerator::vFIRST_ID_FOR_OBJECTS \t\t\t= 2000;\r\nconst uint32 CParkGenerator::vMAX_ID_FOR_OBJECTS \t\t\t= 2000000;\r\nconst uint32 CParkGenerator::vFIRST_ID_FOR_RAILS \t\t\t= 2000001;\r\nconst uint32 CParkGenerator::vMAX_ID_FOR_RAILS \t\t\t\t= 4000000;\r\nconst uint32 CParkGenerator::vFIRST_ID_FOR_CREATED_RAILS\t= 4000001;\r\nconst uint32 CParkGenerator::vMAX_ID_FOR_CREATED_RAILS\t\t= 6000000;\r\nconst uint32 CParkGenerator::vFIRST_ID_FOR_RESTARTS \t\t= 6000001;\r\n\r\n\r\n\r\nCPiece::CPiece()\r\n{\r\n\tm_flags = EFlags(0);\r\n\r\n\t//mp_sector = NULL;\r\n\tm_sector_checksum = 0;\r\n\t\r\n\tmp_next_in_list = NULL;\r\n}\r\n\r\n\r\n\r\n\r\nCPiece::~CPiece()\r\n{\r\n}\r\n\r\n\r\n\r\n\r\nvoid CPiece::GetCellDims(GridDims *pDims)\r\n{\r\n\tMth::Vector dims = GetDims();\r\n\tpDims->SetWHL((uint8) ((dims.GetX() + 2.0f) / CParkGenerator::CELL_WIDTH),\r\n\t\t\t\t  (uint8) ((dims.GetY() + 2.0f) / CParkGenerator::CELL_HEIGHT),\r\n\t\t\t\t  (uint8) ((dims.GetZ() + 2.0f) / CParkGenerator::CELL_LENGTH));\r\n\t\r\n\t/*\r\n\tif (m_sector_checksum == Script::GenerateCRC(\"Sk3Ed_MTra_02\"))\r\n\t{\r\n\t\tRyan(\"Sk3Ed_MTra_02 cells dims are (%d,%d,%d), world (%.4f,%.4f,%.4f)\\n\", \r\n\t\t\t pDims->GetW(), pDims->GetH(), pDims->GetL(),\r\n\t\t\t dims.GetX(), dims.GetY(), dims.GetZ());\r\n\t}\r\n\t*/\r\n}\r\n\r\n\r\n\r\n\r\nCSourcePiece *CPiece::CastToCSourcePiece()\r\n{\r\n\tDbg_MsgAssert(this == NULL || (m_flags & mSOURCE_PIECE), (\"not a source piece!\"));\r\n\treturn (CSourcePiece *) this;\r\n}\r\n\r\n\r\n\r\n\r\nCClonedPiece *CPiece::CastToCClonedPiece()\r\n{\r\n\tDbg_MsgAssert(this == NULL || (m_flags & mCLONED_PIECE), (\"not a cloned piece!\"));\r\n\treturn (CClonedPiece *) this;\r\n}\r\n\r\n\r\n\r\n\r\nMth::Vector\tCPiece::GetDimsWithRot(Mth::ERot90 rot)\r\n{\r\n\tCSourcePiece *p_source_piece;\r\n\tif (m_flags & mSOURCE_PIECE)\r\n\t\tp_source_piece = CastToCSourcePiece();\r\n\telse\r\n\t\tp_source_piece = CastToCClonedPiece()->GetSourcePiece();\r\n\r\n\tDbg_Assert(p_source_piece);\r\n\r\n\tMth::Vector result;\r\n\tif (rot & 1)\r\n\t{\r\n\t\tresult[X] = p_source_piece->GetDims().GetZ();\r\n\t\tresult[Z] = p_source_piece->GetDims().GetX();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tresult[X] = p_source_piece->GetDims().GetX();\r\n\t\tresult[Z] = p_source_piece->GetDims().GetZ();\r\n\t}\r\n\tresult[Y] = p_source_piece->GetDims().GetY();\r\n\r\n\treturn result;\r\n}\r\n\r\n\r\n\r\n\r\nCSourcePiece::CSourcePiece()\r\n{\r\n\tset_flag(CPiece::mSOURCE_PIECE);\r\n\tm_domain = mREGULAR;\r\n\tm_triggerScriptId = 0;\r\n}\r\n\r\n\r\n\r\n\r\nCSourcePiece::~CSourcePiece()\r\n{\r\n\t//printf(\"killed CSourcePiece\\n\");\r\n}\r\n\r\n\r\n\r\n\r\nuint32 CSourcePiece::GetType()\r\n{\r\n\treturn m_sector_checksum;\r\n}\r\n\r\n\r\n\r\n\r\nCClonedPiece::CClonedPiece()\r\n{\r\n\tm_id = 0;\r\n\tset_flag(CPiece::mCLONED_PIECE);\r\n\tmp_source_piece = NULL;\r\n}\r\n\r\n\r\n\r\n\r\nuint32 CClonedPiece::GetID()\r\n{\r\n\treturn m_id;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tInstant function. Piece arrives at new location right away.\r\n*/\r\nvoid CClonedPiece::SetDesiredPos(const Mth::Vector & pos, ESectorEffect sectorEffect)\r\n{\r\n\t//Dbg_MsgAssert(!(m_flags & CPiece::mIN_WORLD), (\"can't change position, piece already in world\"));\r\n\tm_pos = pos;\r\n\r\n\tif (sectorEffect == CHANGE_SECTOR)\r\n\t{\r\n\t\t#if 0\r\n\t\t//printf(\"cloned piece at (%.2f,%.2f,%.2f), dims=(%.2f,%.2f,%.2f)\\n\", \r\n\t\t//if (mp_source_piece->GetType() == Script::GenerateCRC(\"Sk3Ed_Rd1b_10x10x4\"))\r\n//\t\t\tprintf(\"   cloned piece at (%.3f,%.3f,%.3f), dims=(%.3f,%.3f,%.3f)\\n\", \r\n//\t\t\t\t   pos.GetX(), pos.GetY(), pos.GetZ(),\r\n//\t\t\t\t   mp_source_piece->m_dims.GetX(), mp_source_piece->m_dims.GetY(), mp_source_piece->m_dims.GetZ());\r\n\t\t#endif\r\n\r\n\t\t/*\r\n\t\tif (pos.GetX() == -1140.0f && pos.GetZ() == -1140.0f)\r\n\t\t\tprintf(\"    add (%f,%f,%f), sector 0x%x\\n\", \r\n\t\t\t\t   pos.GetX(), pos.GetY(), pos.GetZ(), m_sector_checksum);\r\n\t\t*/\r\n\t\t\r\n\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(m_sector_checksum);\r\n\t\tDbg_Assert(p_sector);\r\n\t\r\n\t\tp_sector->SetWorldPosition(pos);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tInstant function. Piece arrives at new rotation right away.\r\n*/\r\nvoid CClonedPiece::SetDesiredRot(Mth::ERot90 rot, ESectorEffect sectorEffect)\r\n{\r\n\t//Dbg_MsgAssert(!(m_flags & CPiece::mIN_WORLD), (\"can't change rotation, piece already in world\"));\r\n\tm_rot = rot;\r\n\r\n\tif (sectorEffect == CHANGE_SECTOR)\r\n\t{\r\n\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(m_sector_checksum);\r\n\t\tDbg_Assert(p_sector);\r\n\r\n\t\t//Dbg_Message(\"Rotating piece with to %d\", (int) rot * 90);\r\n\t\tp_sector->SetYRotation(rot);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CClonedPiece::SetSoftRot(float rot)\r\n{\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(m_sector_checksum);\r\n\tDbg_Assert(p_sector);\r\n\r\n\tNx::CGeom *p_geom = p_sector->GetGeom();\r\n\tif (p_geom)\r\n\t{\r\n\t\tMth::Matrix rot_mat;\r\n\t\trot_mat.Ident();\r\n\t\trot_mat.RotateY(Mth::DegToRad(rot));\r\n\t\tp_geom->SetOrientation(rot_mat);\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CClonedPiece::SetScaleX(float scaleX)\r\n{\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(m_sector_checksum);\r\n\tDbg_Assert(p_sector);\r\n\tMth::Vector scale_vect;\r\n\tif (m_rot & 1)\r\n\t{\r\n\t\tscale_vect[X] = 1.0f;\r\n\t\tscale_vect[Z] = scaleX;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tscale_vect[X] = scaleX;\r\n\t\tscale_vect[Z] = 1.0f;\r\n\t}\r\n\tscale_vect[Y] = 1.0f;\r\n\tp_sector->SetScale(scale_vect);\r\n}\r\n\r\n\r\n\r\n\r\n// Turn on or off the highlight effect for the geometry that makes up a cloned piece\r\nvoid CClonedPiece::Highlight(bool on, bool makePurple)\r\n{\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(m_sector_checksum);\r\n\tif (!p_sector)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t//Dbg_Assert(p_sector);\r\n\r\n\tNx::CGeom *p_geom = p_sector->GetGeom();\r\n\tif (p_geom)\r\n\t{\r\n\t\t// This effect is somewhat arbitary.   I just want to get SOME effect\r\n\t\tif (on)\r\n\t\t{\r\n\t\t\tif (makePurple)\r\n\t\t\t\tp_geom->SetColor(Image::RGBA(160,100,160,0));\r\n\t\t\telse\r\n\t\t\t\tp_geom->SetColor(Image::RGBA(160,100,100,0));\r\n\t\t\t//Ryan(\"set color for sector=%p\\n\", p_sector);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// ClearColor flags the geom as being NOT COLORED, rather than setting the color to neutral.\r\n\t\t\tp_geom->ClearColor();\t\t\r\n\t\t\t//Ryan(\"clear color for sector=%p\\n\", p_sector);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CClonedPiece::SetActive(bool active)\r\n{\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(m_sector_checksum);\r\n\tDbg_Assert(p_sector);\r\n\tp_sector->SetActive(active);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CClonedPiece::SetVisibility(bool visible)\r\n{\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(m_sector_checksum);\r\n\tDbg_Assert(p_sector);\r\n\tuint32 mask = visible ? 0xFF : 0;\r\n\tp_sector->SetVisibility(mask);\r\n}\r\n\r\n\r\n\r\n\r\nMth::Vector\tCClonedPiece::GetDims()\r\n{\r\n\tDbg_Assert(mp_source_piece);\r\n\r\n\tMth::Vector result;\r\n\tif (m_rot & 1)\r\n\t{\r\n\t\tresult[X] = mp_source_piece->m_dims.GetZ();\r\n\t\tresult[Z] = mp_source_piece->m_dims.GetX();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tresult[X] = mp_source_piece->m_dims.GetX();\r\n\t\tresult[Z] = mp_source_piece->m_dims.GetZ();\r\n\t}\r\n\tresult[Y] = mp_source_piece->m_dims.GetY();\r\n\r\n\treturn result;\r\n}\r\n\r\n\r\n\r\n\r\nCParkGenerator::CParkGenerator()\r\n{\r\n\tm_flags = EFlags(0);\r\n\tmp_cloned_piece_list = NULL;\r\n\tmp_source_piece_list = NULL;\r\n\r\n\tmp_cloned_scene = NULL;\r\n\tmp_source_scene = NULL;\r\n\tm_num_cloned_pieces = 0;\r\n\tm_num_source_pieces = 0;\r\n\r\n\tm_next_id = 32;\r\n\r\n\tmp_mem_region = NULL;\r\n\tmp_mem_heap = NULL;\r\n\r\n\tm_mem_usage_info.mMainHeapFree = 0;\r\n\tm_mem_usage_info.mMainHeapUsed = 0;\r\n\tm_mem_usage_info.mParkHeapFree = 0;\r\n\tm_mem_usage_info.mParkHeapUsed = 0;\r\n\tm_mem_usage_info.mLastMainUsed = 0;\r\n\t\r\n\tm_total_rail_points = 0;\r\n\tm_total_rail_linked_points = 0;\r\n\t\r\n\tm_max_players=2;\r\n}\r\n\r\n\r\n\r\n\r\nCParkGenerator::~CParkGenerator()\r\n{\r\n\t// Clean up scenes (do this last)\r\n\tif (mp_cloned_scene)\r\n\t{\r\n\t\tdelete mp_cloned_scene;\r\n\t}\r\n\tif (mp_source_scene)\r\n\t{\r\n\t\tdelete mp_source_scene;\r\n\t}\r\n}\r\n\r\nint\tCParkGenerator::GetResourceSize(char *name)\r\n{\r\n\tScript::CStruct *p_resource_struct = Script::GetStructure(\"Ed_Resources_Info\");\r\n\tint size;\r\n\r\n\tif (strcmp(name, \"main_heap_base\") == 0)\r\n\t{\r\n\t\tScript::CArray *p_values;\r\n\t\tp_resource_struct->GetArray(name, &p_values);\r\n\t\t#ifdef __PLAT_NGPS__\r\n\t\tsize = p_values->GetInteger(0);\r\n\t\t#else\r\n\t\t\t#ifdef __PLAT_NGC__\r\n\t\t\tsize = 4654800+((2 * 1024 * 1024)-900000);\t//p_values->GetInteger(1);\r\n\t\t\t#else\r\n\t\t\tsize = p_values->GetInteger(2);\r\n\t\t\t#endif\r\n\t\t#endif\r\n\t}\r\n\telse if(strcmp(name, \"main_heap_pad\") == 0)\r\n\t{\r\n\t\tScript::CArray *p_values;\r\n\t\tp_resource_struct->GetArray(name, &p_values);\r\n#\t\tif defined( __PLAT_NGPS__ )\r\n\t\tsize = p_values->GetInteger(0);\r\n#\t\telif defined( __PLAT_NGC__ )\r\n\t\tsize = -2294188;\t//p_values->GetInteger(1);\r\n#\t\telse\r\n\t\tsize = p_values->GetInteger(2);\r\n#\t\tendif\r\n\r\n\t}\r\n\telse if (strcmp(name, \"theme_pad\") == 0)\r\n\t{\r\n\t\tint theme=CParkManager::sInstance()->GetTheme();\r\n\t\t#ifdef __PLAT_NGC__\r\n\t\tint theme_size[5] =\r\n\t\t{\r\n\t\t\t0,\r\n\t\t\t179296,\r\n\t\t\t822784,\r\n\t\t\t482944,\r\n\t\t\t444544\r\n\t\t};\r\n\t\tsize = theme_size[theme];\r\n\t\t#else\r\n\t\t\t#ifdef __PLAT_XBOX__\r\n\t\t\t\tint theme_size[5] =\r\n\t\t\t\t{\r\n\t\t\t\t\t0,\r\n\t\t\t\t\t253728,\r\n\t\t\t\t\t564688,\r\n\t\t\t\t\t161344,\r\n\t\t\t\t\t441856\r\n\t\t\t\t};\r\n\t\t\t\tsize = theme_size[theme];\r\n\t\t\t#else\t\t\r\n\t\t\t\tScript::CArray *p_values;\r\n\t\t\t\tp_resource_struct->GetArray(name, &p_values);\r\n\t\t\t\tsize = p_values->GetInteger(theme);\r\n\t\t\t#endif\r\n\t\t#endif\t\t// __PLAT_NGC__\r\n\t}\r\n\t#ifdef __PLAT_NGC__\r\n\telse if(strcmp(name, \"floor_piece_size_main\") == 0)\r\n\t{\r\n\t\tsize = 1000;\r\n\t}\r\n\t#endif\r\n\telse\r\n\t{\r\n\t\tif (!p_resource_struct->GetInteger(name, &size))\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"couldn't get resource size '%s'\", name));\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t}\r\n\r\n\treturn size;\r\n}\r\n\r\n\r\n\r\n\r\nMem::Heap *CParkGenerator::GetParkEditorHeap()\r\n{\r\n\tDbg_MsgAssert(mp_mem_heap, (\"no park editor heap\"));\r\n\treturn mp_mem_heap;\r\n}\r\n\r\n\r\n\r\nvoid CParkGenerator::SetMaxPlayers(int maxPlayers)\r\n{\r\n\tDbg_MsgAssert(maxPlayers>1 && maxPlayers<=GameNet::vMAX_PLAYERS,(\"Bad maxPlayers of %d\",maxPlayers));\r\n\tm_max_players=maxPlayers;\r\n}\t\r\n\r\nCParkGenerator::MemUsageInfo CParkGenerator::GetResourceUsageInfo(bool printInfo)\r\n{\r\n\tDbg_Assert(mp_mem_heap);\r\n\tDbg_Assert(this);\r\n\t\r\n\t//int base_park_heap = 0;\r\n\t//int max_base_park_heap = 0;\r\n\t\r\n\t//int padding_size = GetResourceSize(\"park_heap_pad\");\r\n\t//int used_park_heap = mp_mem_heap->mUsedMem.m_count;\r\n\t//int free_park_heap = mp_mem_heap->mFreeMem.m_count + mp_mem_region->MemAvailable();\r\n\r\n\r\n\t// allowed to be used, that is\r\n\t//int allowed_park_heap_mem = free_park_heap + used_park_heap - padding_size;\r\n\t//float park_heap_pct = (float) (used_park_heap - base_park_heap) / (float) (allowed_park_heap_mem - max_base_park_heap);\r\n\t//float actual_park_heap_pct = (float) (used_park_heap) / (float) (allowed_park_heap_mem);\r\n\t/*\r\n\tif (largest_free_block < padding_size)\r\n\t{\r\n\t\t// there is no guarantee we can safetly fit the next piece\r\n\t\t// placed, so make the memory meter full\r\n\t\tpark_heap_pct = actual_park_heap_pct = 1.0001f;\r\n\t}\r\n\t*/\r\n\r\n\tMem::Heap *p_main_heap = Mem::Manager::sHandle().BottomUpHeap();\r\n\tMem::Region *p_main_region = p_main_heap->mp_region;\r\n\tDbg_Assert(p_main_region);\r\n\tif (m_mem_usage_info.mMainHeapUsed != p_main_heap->mUsedMem.m_count)\r\n\t{\r\n\t\tm_mem_usage_info.mLastMainUsed = m_mem_usage_info.mMainHeapUsed;\r\n\t}\r\n\t\r\n\t// Mick, the replay buffer is allocated in the park editor\r\n\t// but we want to ignore it in our calculations\r\n\t// so we just subtract it from the main_heap_pad\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n#ifdef __PLAT_NGC__\r\n\tint main_padding_size = GetResourceSize(\"main_heap_pad\");\r\n#else\r\n#if __USE_REPLAYS__\r\n\tint main_padding_size = GetResourceSize(\"main_heap_pad\") - Replay::GetBufferSize();\r\n#else\t\r\n\tint main_padding_size = GetResourceSize(\"main_heap_pad\");\r\n#endif\r\n#endif\r\n\t\r\n\tmain_padding_size+=(m_max_players-1)*(SKATER_HEAP_SIZE+SKATER_GEOM_HEAP_SIZE);\r\n\t\r\n\tint total_mem_available=p_main_heap->mFreeMem.m_count + p_main_region->MemAvailable();\r\n\tif (main_padding_size > total_mem_available)\r\n\t{\r\n\t\t//Dbg_MsgAssert(0,(\"main_padding_size > total_mem_available !! (%d > %d)\",main_padding_size,total_mem_available));\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t//printf(\"main_padding_size > total_mem_available !! (%d > %d)\\n\",main_padding_size,total_mem_available);\r\n\t\t#endif\r\n\t\t//ParkEd(\"main_padding_size > total_mem_available !! (%d > %d)\\n\",main_padding_size,total_mem_available);\r\n\t}\r\n\t\t\r\n\tm_mem_usage_info.mMainHeapUsed = p_main_heap->mUsedMem.m_count;\r\n\tm_mem_usage_info.mMainHeapFree = p_main_heap->mFreeMem.m_count + p_main_region->MemAvailable() - main_padding_size;\r\n\t\r\n\t\r\n\t//printf(\"p_main_heap->mFreeMem.m_count=%d\\np_main_region->MemAvailable()=%d\\nmain_padding_size=%d\\n\",p_main_heap->mFreeMem.m_count,p_main_region->MemAvailable(),main_padding_size);\r\n\tint park_padding_size = GetResourceSize(\"park_heap_pad\");\r\n\tm_mem_usage_info.mParkHeapUsed = mp_mem_heap->mUsedMem.m_count;\r\n\tm_mem_usage_info.mParkHeapFree = mp_mem_heap->mFreeMem.m_count + mp_mem_region->MemAvailable() - park_padding_size;\r\n\r\n\tif (p_main_heap->LargestFreeBlock() < m_mem_usage_info.mMainHeapFree && \t// heap definitely fragmented\r\n\t\tp_main_heap->LargestFreeBlock() < main_padding_size && \t\t\t\t\t// no block big enough for single piece\r\n\t\tm_mem_usage_info.mMainHeapFree >= main_padding_size) \t\t\t\t\t// there is enough memory for single piece\r\n\t{\r\n\t\t// XXX\r\n\t\tRyan(\"===================== DEFRAG ===========================\\n\");\r\n\t\tRyan(\"largest: %d, free: %d, padding %d\\n\", \r\n\t\t\t p_main_heap->LargestFreeBlock(), m_mem_usage_info.mMainHeapFree, main_padding_size);\r\n\t\tRyan(\"========================================================\\n\");\r\n\t\tm_mem_usage_info.mIsFragmented = true;\r\n\t\tint false_free_amt = m_mem_usage_info.mMainHeapFree - p_main_heap->LargestFreeBlock();\r\n\t\tm_mem_usage_info.mMainHeapFree -= false_free_amt;\r\n\t\tm_mem_usage_info.mMainHeapUsed += false_free_amt;\r\n\t}\r\n\telse\r\n\t\tm_mem_usage_info.mIsFragmented = false;\r\n\t\t\r\n\t\t\r\n\t#if 0\r\n\tif ( p_main_heap->mFreeMem.m_count > 200000)\r\n\t{\r\n\t\tm_mem_usage_info.mIsFragmented = true;\t\r\n\t}\r\n\t#endif\r\n\r\n\tm_mem_usage_info.mTotalClonedPieces = m_num_cloned_pieces;\r\n\tm_mem_usage_info.mTotalRailPoints = m_total_rail_points;\r\n\tm_mem_usage_info.mTotalLinkedRailPoints = m_total_rail_linked_points;\r\n\r\n\r\n\t// subtract theme specific padding\r\n\tif (CParkManager::sInstance()->GetTheme() > 0)\r\n\t{\r\n\t\tm_mem_usage_info.mMainHeapFree -= GetResourceSize(\"theme_pad\");\r\n\t}\r\n\r\n\t\r\n\tif (printInfo)\r\n\t{\r\n\t\tRyan(\"=====================================================\\nParkGen Usage Stats:\\n\\n\");\r\n\t\tRyan(\"largest free block: %d\\n\", mp_mem_heap->LargestFreeBlock());\r\n\t\tRyan(\"used park heap: %d\\n\", m_mem_usage_info.mParkHeapUsed);\r\n\t\tRyan(\"free park heap: %d\\n\", m_mem_usage_info.mParkHeapFree);\r\n\t\tRyan(\"main heap used: %d\\n\", m_mem_usage_info.mMainHeapUsed);\r\n\t\tRyan(\"main heap available: %d\\n\", m_mem_usage_info.mMainHeapFree);\r\n\t}\r\n\t\r\n\treturn m_mem_usage_info;\r\n\t\r\n}\r\n\r\nint\tCParkGenerator::GetMaxPlayersPossible()\r\n{\r\n\tCParkGenerator::MemUsageInfo usage_info = GetResourceUsageInfo();\r\n\t// GetResourceUsageInfo has already subtracted the memory used by the currently set max players,\r\n\t// so add that back in so that the max max can be calculated.\r\n\tusage_info.mMainHeapFree += (m_max_players-1)*(SKATER_HEAP_SIZE+SKATER_GEOM_HEAP_SIZE);\r\n\t\r\n\t// The +1 is because at least 1 skater is assumed.\r\n\treturn \tusage_info.mMainHeapFree/(SKATER_HEAP_SIZE+SKATER_GEOM_HEAP_SIZE)+1;\r\n}\r\n\r\n\r\n\r\n/*\r\n\tGiven checksum of piece name, returns pointer to source piece.\r\n*/\r\nCSourcePiece *CParkGenerator::GetMasterPiece(uint32 pieceType, bool assert)\r\n{\r\n\tCPiece *p_piece = mp_source_piece_list;\r\n\twhile(p_piece)\r\n\t{\r\n\t\tif (p_piece->CastToCSourcePiece()->m_sector_checksum == pieceType)\r\n\t\t\treturn p_piece->CastToCSourcePiece();\r\n\t\tp_piece = p_piece->mp_next_in_list;\r\n\t}\r\n\t\r\n\tif (assert)\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"couldn't not find master piece %s\", Script::FindChecksumName(pieceType)));\r\n\t}\r\n\telse\r\n\t\tprintf(\"couldn't not find master piece %s\\n\", Script::FindChecksumName(pieceType));\r\n\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n\r\nCSourcePiece *CParkGenerator::GetNextMasterPiece(CSourcePiece *pLast)\r\n{\t\r\n\tif (!pLast)\r\n\t\treturn mp_source_piece_list->CastToCSourcePiece();\r\n\telse\r\n\t\treturn pLast->mp_next_in_list->CastToCSourcePiece();\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tMakes a copy of a source piece. The copy can then be added to a metapiece, or to the world.\r\n\r\n\tA soft piece can be smoothly rotated, like a piece used in a cursor.\r\n*/\r\nCClonedPiece *CParkGenerator::ClonePiece(CPiece *pMasterPiece, CPiece::EFlags flags)\r\n{\r\n\t// make sure flags make sense\r\n\tflags = CPiece::EFlags(flags & (CPiece::mSOFT_PIECE | CPiece::mFLOOR | CPiece::mNO_RAILS));\r\n\t\r\n\tDbg_Assert(pMasterPiece);\r\n\r\n\tCSourcePiece *pSource;\r\n\tif (pMasterPiece->m_flags & CPiece::mSOURCE_PIECE)\r\n\t\tpSource = pMasterPiece->CastToCSourcePiece();\r\n\telse\r\n\t\tpSource = pMasterPiece->CastToCClonedPiece()->mp_source_piece;\r\n\r\n\tDbg_Assert(pSource);\r\n\tDbg_Assert(mp_source_scene);\r\n\tDbg_Assert(mp_cloned_scene);\r\n\r\n\t// putting cloned sectors on main heap seems best right now\r\n\t//Mem::Manager::sHandle().PushContext(mp_mem_heap);\r\n\tuint32 new_sector_checksum;\r\n\tif (flags & CPiece::mSOFT_PIECE)\r\n\t{\r\n\t\t// create fresh soft piece (hmm, that sounds kind of disgusting)\r\n\t\tnew_sector_checksum = mp_source_scene->CloneSector(pSource->m_sector_checksum, mp_cloned_scene, true, false); // no instance for now (should be instance)\r\n\t\t//Dbg_Message(\"************************* New soft checksum %x\", new_sector_checksum);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// create fresh hard piece (no, this sounds worse!)\r\n\t\tnew_sector_checksum = mp_source_scene->CloneSector(pSource->m_sector_checksum, mp_cloned_scene, false, true); // no instance\r\n\t\t\r\n\t\tif (!(flags & CPiece::mNO_RAILS))\r\n\t\t{\r\n\t\t\tm_total_rail_points += pSource->m_num_rail_points;\r\n\t\t\tm_total_rail_linked_points += pSource->m_num_linked_rail_points;\r\n\t\t}\r\n\t}\r\n\t//Mem::Manager::sHandle().PopContext();\r\n\r\n\t// Create cloned piece, will soon live in world or as animated piece\r\n\tMem::Manager::sHandle().PushContext(mp_mem_heap);\r\n\tCClonedPiece *p_cloned_piece = new CClonedPiece();\r\n\tMem::Manager::sHandle().PopContext();\r\n\tp_cloned_piece->m_sector_checksum = new_sector_checksum;\r\n\tp_cloned_piece->m_id = m_next_id++;\r\n\tp_cloned_piece->mp_source_piece = pSource;\r\n\tp_cloned_piece->SetDesiredRot(Mth::ERot90(0), CClonedPiece::MARKER_ONLY);\r\n\t\r\n\tm_num_cloned_pieces++;\r\n\r\n\tp_cloned_piece->set_flag(flags);\r\n\r\n\tset_flag(mSECTORS_GENERATED);\r\n\t\r\n\treturn p_cloned_piece;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tMust be called to finalized cloned piece's presence in world.\r\n*/\r\nvoid CParkGenerator::AddClonedPieceToWorld(CClonedPiece *pPiece)\r\n{\r\n\tDbg_MsgAssert(!(pPiece->GetFlags() & CPiece::mIN_WORLD), (\"piece already in world\"));\r\n\tpPiece->set_flag(CPiece::mIN_WORLD);\r\n\r\n\tpPiece->mp_next_in_list = mp_cloned_piece_list;\r\n\tmp_cloned_piece_list = pPiece;\r\n\t\r\n\tset_flag(mPIECES_IN_WORLD);\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkGenerator::DestroyClonedPiece(CClonedPiece *pPiece)\r\n{\r\n\tdestroy_piece_impl(pPiece, DESTROY_PIECES_AND_SECTORS);\r\n}\r\n\r\n\r\n#ifdef __PLAT_NGPS__\r\n#if PRINT_RAW_RESULTS\r\nvoid print_ps2_data(NxPs2::CGeomNode *p_node)\r\n{\r\n\tuint8 *p_dma = p_node->GetDma();\r\n\r\n\tint num_verts = NxPs2::dma::GetNumVertices(p_dma);\r\n\tif( num_verts >= 3 )\r\n\t{\r\n\t\tbool short_xyz = (NxPs2::dma::GetBitLengthXYZ(p_dma) == 16);\r\n\t\tMth::Vector mesh_center = p_node->GetBoundingSphere();\r\n\r\n\t\t// Get DMA arrays\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\tsint32 *p_vert_array = new sint32[4 * num_verts];\r\n\t\tsint32 *p_uv_array = new sint32[2 * num_verts];\r\n\t\tuint32 *p_rgb_array = new uint32[num_verts];\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t// Copy DMA data\r\n\t\tNxPs2::dma::ExtractXYZs(p_dma, (uint8 *) p_vert_array);\r\n\t\tNxPs2::dma::ExtractSTs(p_dma, (uint8 *) p_uv_array);\r\n\t\tNxPs2::dma::ExtractRGBAs(p_dma, (uint8 *) p_rgb_array);\r\n\r\n\t\tMth::Vector v0;\r\n\t\tfloat u, v;\r\n\t\tImage::RGBA col;\r\n\r\n\t\tDbg_Message(\"Number of verts: %d\", num_verts);\r\n\r\n\t\tfor (int idx = 0; idx < num_verts; idx++)\r\n\t\t{\r\n\t\t\tif (short_xyz)\r\n\t\t\t{\r\n\t\t\t\tNxPs2::dma::ConvertXYZToFloat(v0, &(p_vert_array[idx * 4]), mesh_center);\r\n\t\t\t} else {\r\n\t\t\t\tNxPs2::dma::ConvertXYZToFloat(v0, &(p_vert_array[idx * 4]));\r\n\t\t\t}\r\n\t\t\tNxPs2::dma::ConvertSTToFloat(u, v, &(p_uv_array[idx * 2]));\r\n\t\t\tcol = *((Image::RGBA *) &(p_rgb_array[idx]));\r\n\r\n\t\t\tDbg_Message(\"Vert %d\", idx);\r\n\t\t\tDbg_Message(\"Raw Pos (%x, %x, %x, %x)\", p_vert_array[idx * 4 + 0], p_vert_array[idx * 4 + 1], p_vert_array[idx * 4 + 2], p_vert_array[idx * 4 + 3]);\r\n\t\t\tDbg_Message(\"Pos (%f, %f, %f, %f)\", v0[X], v0[Y], v0[Z], v0[W]);\r\n\t\t\tDbg_Message(\"UV (%f, %f)\", u, v);\r\n\t\t\tDbg_Message(\"Color (%d, %d, %d, %d)\", col.r, col.g, col.b, col.a);\r\n\r\n\t\t}\r\n\r\n\t\t// Free DMA buffers\r\n\t\tdelete [] p_vert_array;\r\n\t\tdelete [] p_uv_array;\r\n\t\tdelete [] p_rgb_array;\r\n\t}\r\n}\r\n#endif // PRINT_RAW_RESULTS\r\n#endif\r\n\r\n\r\n/*\r\n\tCreates the set of source pieces. The data will have been loaded by this point.\r\n*/\r\nvoid CParkGenerator::InitializeMasterPieces(int parkW, int parkH, int parkL, int theme)\r\n{\r\n\tif (flag_on(mMASTER_STUFF_LOADED))\r\n\t\tUnloadMasterPieces();\r\n\t\r\n\tset_flag(mMASTER_STUFF_LOADED);\r\n\r\n\t// When we reload the master piece, we reset the id of the generate pieces\r\n\t// so that net games will be syncronized\r\n\tm_next_id = 32;\r\n\r\n\t// set up park editor heap\r\n\tDbg_MsgAssert(!mp_mem_region && !mp_mem_heap,(\t\"park editor heap already exists\"));\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t#ifdef __PLAT_NGC__\r\n\t// Added 200K to the TOP_DOWN_REQUIRED_MARGIN for safety, and cancelled that by removing\r\n\t// 200K from the park editor heap. (Normally 900K)\r\n\tmp_mem_region = new Mem::AllocRegion(700000);\t\r\n\t#else\r\n\tmp_mem_region = new Mem::AllocRegion(GetResourceSize(\"heap\"));\t\r\n\t#endif\r\n\tMem::Manager::sHandle().PopContext();\r\n\tRyan(\"  allocated park editor region at %p\\n\", mp_mem_region);\r\n\tmp_mem_heap = Mem::Manager::sHandle().CreateHeap( mp_mem_region, Mem::Allocator::vBOTTOM_UP, \"Park Editor\" );\r\n\r\n\t// fetch scene\r\n\tconst char *p_scene_name=\"sk5ed\";\r\n\t\t\r\n\tmp_source_scene = Nx::CEngine::sGetScene(p_scene_name);\r\n\t\r\n\t// set up all the source pieces\r\n\tDbg_MsgAssert(mp_source_scene, (\"couldn't get scene %s\", p_scene_name));\r\n\tLst::HashTable<Nx::CSector> *p_sector_list = mp_source_scene->GetSectorList();\r\n\tNx::CSector *p_sector;\r\n\r\n//\tprintf(\"Setting up park editor source pieces:\\n\");\r\n\tp_sector_list->IterateStart();\r\n\twhile ((p_sector = p_sector_list->IterateNext()))\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(mp_mem_heap);\r\n\t\tCSourcePiece *p_new_piece = new CSourcePiece();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\tp_new_piece->mp_next_in_list = mp_source_piece_list;\r\n\t\tmp_source_piece_list = p_new_piece;\r\n\r\n\t\t//printf (\"Piece with checksum 0x%x\\n\",p_sector->GetChecksum());\r\n#ifdef __PLAT_NGPS__\r\n#if PRINT_RAW_RESULTS\r\n\t\tif (p_sector->GetChecksum() == Crc::GenerateCRCFromString(\"Sk3Ed_F_10x10\"))\r\n\t\t{\r\n\t\t\tDbg_Message(\"******* Found the target piece\");\r\n\t\t\tMth::CBBox piece_bbox(p_sector->GetBoundingBox());\r\n\t\t\tDbg_Message(\"Bounding Box (%.8f, %.8f, %.8f) - (%.8f, %.8f, %.8f)\",\r\n\t\t\t\t\t\tpiece_bbox.GetMin()[X], piece_bbox.GetMin()[Y], piece_bbox.GetMin()[Z],\r\n\t\t\t\t\t\tpiece_bbox.GetMax()[X], piece_bbox.GetMax()[Y], piece_bbox.GetMax()[Z]);\r\n\r\n\t\t\tNx::CPs2Geom *p_geom = static_cast<Nx::CPs2Geom *>(p_sector->GetGeom());\r\n\t\t\tNxPs2::CGeomNode *p_geom_node = p_geom->GetEngineObject();\r\n\t\t\tDbg_Assert(p_geom_node);\r\n\r\n\t\t\t// Put all the meshes in an array\r\n\t\t\tint num_meshes = 0;\r\n\t\t\tNxPs2::CGeomNode *mesh_array[10];\r\n\t\t\tNx::find_geom_leaves(p_geom_node, mesh_array, num_meshes);\r\n\t\t\tDbg_Assert(num_meshes == 1);\r\n\t\t\tp_geom_node = mesh_array[0];\r\n\r\n\t\t\tprint_ps2_data(p_geom_node);\r\n\t\t}\r\n#endif\r\n#endif\r\n\t\tp_new_piece->m_sector_checksum = p_sector->GetChecksum();\r\n\r\n\t\t// Init dimensions\r\n\t\tMth::CBBox piece_bbox(p_sector->GetBoundingBox());\r\n\t\t\r\n\t\tint cell_w = (int) ((piece_bbox.GetMax()[X] - piece_bbox.GetMin()[X] + 2.0f) / CELL_WIDTH);\r\n\t\tif (cell_w < 1) cell_w = 1;\r\n\t\tp_new_piece->m_dims[X] = cell_w * CELL_WIDTH;\r\n\t\t\r\n\t\tint cell_l = (int) ((piece_bbox.GetMax()[Z] - piece_bbox.GetMin()[Z] + 2.0f) / CELL_LENGTH);\r\n\t\tif (cell_l < 1) cell_l = 1;\r\n\t\tp_new_piece->m_dims[Z] = cell_l * CELL_LENGTH;\r\n\t\t\r\n\t\tp_new_piece->m_dims[Y] = (piece_bbox.GetMax()[Y] - piece_bbox.GetMin()[Y]);\r\n\r\n\t\t// piece cannot have any dimension less the that of a park editor cell\r\n\t\tif (p_new_piece->m_dims[Y] < CParkGenerator::CELL_HEIGHT && p_new_piece->m_dims[Y] > 0.0f)\r\n\t\t\tp_new_piece->m_dims[Y] = CParkGenerator::CELL_HEIGHT;\r\n\t\t\r\n\t\tm_num_source_pieces++;\r\n\t\t\r\n\t\t#if 0\r\n\t\t//printf(\"   %s\\n      [%f,%f,%f]-[%f,%f,%f]\\n\", Script::FindChecksumName(p_new_piece->m_sector_checksum),\r\n\t\t//\t   piece_bbox.GetMin()[X], piece_bbox.GetMin()[Y], piece_bbox.GetMin()[Z],\r\n\t\t//\t   piece_bbox.GetMax()[X], piece_bbox.GetMax()[Y], piece_bbox.GetMax()[Z]);\r\n\t\tprintf(\"      %s [%.2f,%.2f,%.2f]\\n\", Script::FindChecksumName(p_new_piece->m_sector_checksum),\r\n\t\t\t   p_new_piece->m_dims[X], p_new_piece->m_dims[Y], p_new_piece->m_dims[Z]);\r\n\t\t#endif\r\n\t}\r\n\r\n\tmp_cloned_scene = Nx::CEngine::sCreateScene(\"cloned\", mp_source_scene->GetTexDict(), true);\r\n\r\n#ifdef __PLAT_NGC__\r\n\t// Need to copy scene data here, so stuff added to the cloned scene has geometry pools.\r\n\tNx::CNgcScene *p_Ngc_scene = static_cast<Nx::CNgcScene*>( mp_cloned_scene );\r\n\tNx::CNgcScene *p_source_scene = static_cast<Nx::CNgcScene*>( mp_source_scene );\r\n\tNxNgc::sScene *p_scene = p_Ngc_scene->GetEngineScene();\r\n\tmemcpy( p_scene, p_source_scene->GetEngineScene(), sizeof( NxNgc::sScene ) );\r\n\tp_scene->m_num_meshes\t\t\t= 0;\t\t// No meshes as yet.\r\n\tp_scene->m_num_filled_meshes\t= 0;\r\n\tp_scene->mpp_mesh_list\t\t\t= NULL;\r\n\r\n\tp_scene->mp_hierarchyObjects\t= NULL;\r\n\tp_scene->m_numHierarchyObjects\t= 0;\r\n\r\n\tp_scene->mp_hierarchyObjects\t= NULL;\r\n\tp_scene->m_numHierarchyObjects\t= 0;\r\n\r\n\t// Make it renderable, and make sure it doesn't try to double-delete the scene data.\r\n\tp_scene->m_is_dictionary\t\t= false;\r\n\tp_scene->m_flags\t\t\t\t= SCENE_FLAG_CLONED_GEOM;\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\tMth::CBBox b_box;\r\n\tMth::Vector vmin(-((float) parkW * CELL_WIDTH) / 2.0f, -((float) parkH * CELL_HEIGHT) / 2.0f, -((float) parkL * CELL_LENGTH) / 2.0f);\r\n\tb_box.AddPoint(vmin);\r\n\tMth::Vector vmax(((float) parkW * CELL_WIDTH) / 2.0f, ((float) parkH * CELL_HEIGHT) / 2.0f, ((float) parkL * CELL_LENGTH) / 2.0f);\r\n\tb_box.AddPoint(vmax);\r\n\tmp_cloned_scene->CreateCollision(b_box);\r\n\r\n\tKillRestarts();\r\n}\r\n\r\n/*\r\n// K: Added to allow cleanup of the park editor heap during play\r\nvoid CParkGenerator::DeleteSourceAndClonedPieces()\r\n{\r\n\tCPiece *p_piece = mp_source_piece_list;\r\n\twhile (p_piece)\r\n\t{\r\n\t\tCPiece *p_next = p_piece->mp_next_in_list;\r\n\t\tdelete p_piece;\r\n\t\tp_piece = p_next;\r\n\t}\r\n\tmp_source_piece_list = NULL;\r\n\tm_num_source_pieces=0;\r\n\r\n\tprintf(\"After deleting CParkGenerator::mp_source_piece_list ...\\n\");\t\r\n\tprintf(\"Num CMapListNode's = %d\\n\",Ed::CMapListNode::SGetNumUsedItems());\r\n\tMemView_AnalyzeHeap(Ed::CParkManager::sInstance()->GetGenerator()->GetParkEditorHeap());\r\n\t\r\n\tp_piece = mp_cloned_piece_list;\r\n\twhile(p_piece)\r\n\t{\r\n\t\tCPiece *p_next = p_piece->mp_next_in_list;\r\n\t\tdelete p_piece;\r\n\t\tp_piece = p_next;\r\n\t}\r\n\tm_num_cloned_pieces=0;\r\n\tmp_cloned_piece_list=NULL;\r\n\t\r\n\tprintf(\"After deleting CParkGenerator::mp_cloned_piece_list ...\\n\");\t\r\n\tprintf(\"Num CMapListNode's = %d\\n\",Ed::CMapListNode::SGetNumUsedItems());\r\n\tMemView_AnalyzeHeap(Ed::CParkManager::sInstance()->GetGenerator()->GetParkEditorHeap());\r\n}\r\n*/\r\n\r\n/*\r\n\tDestroys the set of source pieces.\r\n*/\r\nvoid CParkGenerator::UnloadMasterPieces()\r\n{\r\n\tif (flag_on(mPIECES_IN_WORLD))\r\n\t\tDestroyAllClonedPieces(DESTROY_PIECES_AND_SECTORS);\r\n\r\n\t// GARRETT: not sure if you need to do anything here\r\n\t\r\n\tCPiece *p_piece = mp_source_piece_list;\r\n\twhile (p_piece)\r\n\t{\r\n\t\tCPiece *p_next = p_piece->mp_next_in_list;\r\n\t\tdelete p_piece;\r\n\t\tp_piece = p_next;\r\n\t}\r\n\tmp_source_piece_list = NULL;\r\n\tm_num_source_pieces--;\r\n\t//m_num_source_pieces=0;\r\n\t\r\n\tclear_flag(mMASTER_STUFF_LOADED);\r\n\t\r\n\tMem::Manager::sHandle().RemoveHeap(mp_mem_heap);\r\n\tdelete mp_mem_region;\r\n\tmp_mem_heap = NULL;\r\n\tmp_mem_region = NULL;\r\n}\r\n\r\n/*\r\nvoid CParkGenerator::DeleteParkEditorHeap()\r\n{\r\n\tif (mp_mem_heap)\r\n\t{\r\n\t\tMem::Manager::sHandle().RemoveHeap(mp_mem_heap);\r\n\t\tdelete mp_mem_region;\r\n\t\tmp_mem_heap = NULL;\r\n\t\tmp_mem_region = NULL;\r\n\t}\t\r\n}\r\n*/\r\n\r\n/* \r\n\tShould be called after adding/removing sectors\r\n*/\r\nvoid CParkGenerator::PostGenerate()\r\n{\r\n\tDbg_MsgAssert(flag_on(mPIECES_IN_WORLD) && flag_on(mSECTORS_GENERATED), (\"no pieces or sectors available\"));\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tShould be called after adding a group of cloned pieces to world.\r\n*/\r\nvoid CParkGenerator::GenerateCollisionInfo(bool assert)\r\n{\r\n\t// if this flag IS on, then we need to call UpdateSuperSectors() to free the memory\r\n\tif (flag_on(mSECTOR_MEMORY_NEEDS_FREE))\r\n\t{\r\n\t}\r\n\telse if (!assert)\r\n\t{\r\n\t\tif (!flag_on(mPIECES_IN_WORLD) || !flag_on(mSECTORS_GENERATED))\r\n\t\t\treturn;\r\n\t}\r\n\telse\r\n\t\tDbg_MsgAssert(flag_on(mPIECES_IN_WORLD) && flag_on(mSECTORS_GENERATED), (\"no pieces or sectors available\"));\r\n\t\r\n\t// GARRETT\r\n\tDbg_Assert(mp_cloned_scene);\r\n\tmp_cloned_scene->UpdateSuperSectors();\r\n\t//Dbg_Message(\"Adding collision to scene %x\", mp_cloned_scene->GetID());\r\n\t\r\n\t// XXX\r\n\t//printf(\"there are %d source pieces, %d cloned pieces\\n\", m_num_source_pieces, m_num_cloned_pieces);\r\n\t\r\n\tset_flag(mCOLLISION_INFO_GENERATED);\r\n\tclear_flag(mSECTOR_MEMORY_NEEDS_FREE);\r\n}\r\n\r\n\r\nvoid CParkGenerator::RemoveOuterShellPieces(int theme)\r\n{\r\n\tuint32 shell_id=CParkManager::Instance()->GetShellSceneID();\r\n\t\r\n\tNx::CScene *p_scene = Nx::CEngine::sGetScene(shell_id);\r\n\tif (p_scene)\r\n\t{\r\n\t\t// Turn everything on simply by using a huge bounding box\r\n\t\tMth::CBBox a(Mth::Vector(-200000,-200000,-200000),Mth::Vector(200000,200000,200000));\r\n\t\tp_scene->SetActiveInBox(a,true,0.0f);\r\n\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t// Calculate the bounding box of the park up to the edges \r\n \t\tGridDims  fence;\r\n\t\tfence = CParkManager::Instance()->GetParkNearBounds();\t\t \t\t\t\t\t// returns the rectangle enclosed by the fence\r\n\t\tMth::Vector start = CParkManager::Instance()->GridCoordinatesToWorld(fence);\t\t// top left cornder\r\n\t\t\r\n\t\tfence.SetXYZ(fence.GetX()+fence.GetW()-1,fence.GetY(),fence.GetZ()+fence.GetL()-1);\r\n\t\tMth::Vector end = CParkManager::Instance()->GridCoordinatesToWorld(fence);\t\t// bot right corner, in one square\r\n\r\n\t\t// offset into the park by half a piece\t\t\r\n\t\tstart[X] += CParkGenerator::CELL_WIDTH/2;\r\n\t\tstart[Z] += CParkGenerator::CELL_LENGTH/2;\r\n\t\tend[X] += CParkGenerator::CELL_WIDTH/2;\r\n\t\tend[Z] += CParkGenerator::CELL_LENGTH/2;\r\n\t\t\r\n\t\t// The Y of the world box calculated above is not correct.... so just make it bigh enough to encompass everything\r\n\t\tstart[Y] = -100000;\r\n\t\tend[Y]   =  100000;\r\n\t\tMth::CBBox b(start,end);\r\n\t\t// Note: the above bounding box is based on the centers of cells\r\n\t\t// so it misses a half cell boundry around the inside of the fence\r\n\t\t// however, this is actually close to what I want than the true bounding box\r\n\t\t// as I want to provide a little slack so we don't accidentally kill \r\n\t\t// things that just come inside the fence by an inch or two.\r\n\t\t// (remember the shell collision is not active) \r\n\t\t\r\n\t\t\r\n\t\t// and turn off everything that intersects the bounding box we just calculated\r\n\t\tp_scene->SetActiveInBox(b,false,0.0f);\r\n\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Where is my scene?! %s\", Script::FindChecksumName(shell_id)));\r\n\t}\r\n}\r\n\r\nvoid CParkGenerator::CleanUpOutRailSet()\r\n{\r\n\tm_out_rail_set.Destroy();\r\n\tm_out_rail_set.FreeAllocators();\r\n}\r\n\r\n// K: Factored this code out of GenerateNodeInfo because it is required by FindNearestRailPoint\r\nvoid CParkGenerator::GenerateOutRailSet(CMapListNode * p_concrete_metapiece_list)\r\n{\r\n\tCleanUpOutRailSet();\r\n\t\r\n\tMdl::Skate * p_skate_mod =  Mdl::Skate::Instance();\r\n\tif (p_skate_mod->m_cur_level == CRCD(0xe8b4b836,\"load_sk5ed\"))\r\n\t{\r\n\t\t// K: Not using the top down heap whilst in the editor to avoid running out of memory, \r\n\t\t// since this causes a 192K spike in memory usage when doing a test play.\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());\r\n\t}\r\n\telse\t\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t}\r\n\tm_out_rail_set.SetupAllocators(GetResourceSize(\"out_railpoint_pool\"), GetResourceSize(\"out_railstring_pool\"), false);\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Need to iterate over the pieces here, meaning we'd iterate over the meta pieces\r\n\t// and then find the pieces they are composed of.....\r\n\t// should be similar to rebuilding the park (in terms of iterating over the pieces)\r\n\t\r\n\t// We have been passed in the list of concrete metapiece\r\n\t// (the pieces that have actually been placed in the level\r\n\tCMapListNode *p_node = p_concrete_metapiece_list;\r\n\twhile(p_node)\r\n\t{\r\n\t\tCConcreteMetaPiece *p_meta = p_node->GetConcreteMeta();\r\n\r\n\t\tif (p_meta->IsInPark() && !p_meta->NoRails())\r\n\t\t{\r\n\t\t\t// Iterate over the pieces in the metapiece\r\n\t\t\tint pieces = p_meta->CountContainedPieces();\r\n\t\t\tfor (int i=0;i<pieces;i++)\r\n\t\t\t{\r\n\t\t\t\tCPiece * p_base_piece = p_meta->GetContainedPiece(i);\r\n\t\t\t\tCClonedPiece *pPiece = p_base_piece->CastToCClonedPiece();\t    \r\n\t\r\n\t//\t\t\tif (!(pPiece->m_type & CPiece::vNO_RAILS))\r\n\t\t\t\t{\r\n\t\t\t\t\t// go through all rail strings associated with source object\r\n\t\t\t\t\tfor (int n = 0; ;n++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tuint32 piece_checksum = pPiece->mp_source_piece->m_sector_checksum;\r\n\t\t\t\t\t\tRailString *pSrcString = m_in_rail_set.GetString(piece_checksum, n);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif (pSrcString)\r\n\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\tprintf(\"creating rail string %d for %s, meta=%s\\n\", \r\n//\t\t\t\t\t\t\t\t   n, Script::FindChecksumName(piece_checksum), Script::FindChecksumName(p_meta->GetNameChecksum()));\r\n\t\t\t\t\t\t\tRailString *pOutString = m_out_rail_set.CreateRailString();\r\n\t\t\t\t\t\t\tuint32\ttrickob_id = pPiece->GetID();\r\n\t\t\t\t\t\t\tif (p_meta->IsRiser())\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// objects that are JUST risers cannot be trickobs\r\n\t\t\t\t\t\t\t\ttrickob_id = 0;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tpOutString->CopyOffsetAndRot(pSrcString, pPiece->m_pos, pPiece->m_rot, trickob_id);\r\n\t\t\t\t\t\t\tm_out_rail_set.AddString(pOutString);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t//printf (\"No rails here for %x: %s\\n\", piece_checksum, Script::FindChecksumName(piece_checksum));\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\t\t\r\n\t\t\t\t} // end if (!(pPiece->m_type & Piece::vNO_RAILS))\r\n\t\t\t}\r\n\t\t}\r\n\t\tp_node = p_node->GetNext();\r\n\t}\r\n}\r\n\r\n/*\r\n\tFor rail generation, etc.\r\n*/\r\nvoid CParkGenerator::GenerateNodeInfo(CMapListNode * p_concrete_metapiece_list)\r\n{\r\n\tDbg_MsgAssert(flag_on(mPIECES_IN_WORLD) && flag_on(mSECTORS_GENERATED), (\"no pieces or sectors available\"));\r\n\t\r\n\tint\t\ttotal_nodes = 0;\r\n\t\r\n\t\r\n\t/*\r\n\t========================================================\r\n\tBegin Rail Generation\r\n\t========================================================\r\n\t*/\r\n\r\n\tprintf(\"Making rail objects\\n\");\r\n\r\n\tGenerateOutRailSet(p_concrete_metapiece_list);\t\r\n\t\r\n\ttotal_nodes\t+= m_out_rail_set.CountPoints();\r\n\t\r\n\t\r\n\t\r\n\t/*\r\n\t========================================================\r\n\tEnd Rail Generation\r\n\t========================================================\r\n\t*/\r\n\r\n\r\n\t#if 1\t\r\n\r\n\r\n\tprintf(\"Generating node array\\n\");\r\n\t\r\n\t// count up regular object nodes\r\n\tint object_nodes = 0;\r\n\tCPiece *p_piece = mp_cloned_piece_list;\r\n\twhile (p_piece)\r\n\t{\r\n\t\tif (!(p_piece->m_flags & CPiece::mFLOOR))\r\n\t\t\tobject_nodes++;\r\n\t\tp_piece = p_piece->mp_next_in_list;\r\n\t}\r\n\t// count up object nodes\r\n\ttotal_nodes += object_nodes;\r\n\t\r\n\t#endif\r\n\t\r\n\r\n\t#if 1\r\n\t/*\r\n\t========================================================\r\n\tDo Some Restart Stuff\r\n\t========================================================\r\n\t*/\r\n\t\r\n\t// count up restart nodes\r\n\tfor (int res = 0; res < vNUM_RESTARTS; res++)\r\n\t{\r\n\t\tif (m_restart_tab[res].type != vEMPTY)\r\n\t\t\ttotal_nodes++;\r\n\t\t// one player restarts are repeated as multiplayer\r\n\t\tif (m_restart_tab[res].type == vONE_PLAYER)\r\n\t\t\ttotal_nodes++;\r\n\t\t// HORSE restarts are repeated as multiplayer\r\n\t\tif (m_restart_tab[res].type == vHORSE)\r\n\t\t\ttotal_nodes++;\r\n\t\t// flag restart nodes will generate 3 extra nodes in addition to a restart\r\n\t\tif (\r\n\t\t\tm_restart_tab[res].type == vRED_FLAG\r\n\t\t\t|| m_restart_tab[res].type == vGREEN_FLAG\r\n\t\t\t|| m_restart_tab[res].type == vBLUE_FLAG\r\n\t\t\t|| m_restart_tab[res].type == vYELLOW_FLAG\r\n\t\t)\r\n\t\t{\r\n\t\t    total_nodes += 3; \r\n\t\t}\r\n\t\t\t\r\n\t}\r\n\r\n\t#endif\r\n\t\r\n\t// Add in the number of nodes needed for the created rails.\t\r\n\tint num_nodes_required=Obj::GetRailEditor()->GetTotalRailNodesRequired();\r\n\tDbg_MsgAssert((uint32)num_nodes_required <= vMAX_ID_FOR_CREATED_RAILS-vFIRST_ID_FOR_CREATED_RAILS+1,(\"Too many created-rail nodes\"));\r\n\ttotal_nodes+=num_nodes_required;\r\n\t\r\n\t\r\n\t/*\r\n\t========================================================\r\n\tActually Create Node Array\r\n\t========================================================\r\n\t*/\r\n\r\n\r\n\tSkateScript::CreateNodeArray(total_nodes, false);\r\n\r\n\tScript::CArray *pNodeArray = Script::GetArray(CRCD(0xc472ecc5,\"NodeArray\"));\r\n\tint current_node_num = 0;\r\n\t#if 1\r\n\tset_up_object_nodes(pNodeArray, &current_node_num);\r\n\t#endif\r\n\t\r\n\tset_up_rail_nodes(pNodeArray, &current_node_num);\r\n\t\r\n\tObj::GetRailEditor()->SetUpRailNodes(pNodeArray, &current_node_num, vFIRST_ID_FOR_CREATED_RAILS);\r\n\t\r\n\t#if 1\r\n\tset_up_restart_nodes(pNodeArray, &current_node_num);\r\n\t#endif\r\n\t\r\n\tCleanUpOutRailSet();\r\n\r\n\t\r\n\tprintf(\"Calling CreateNodeNameHashTable()\\n\");\r\n\tSkateScript::CreateNodeNameHashTable();\r\n\tprintf(\"Calling ScriptParseNodeArray()\\n\");\r\n\tCFuncs::ScriptParseNodeArray(NULL, NULL);\r\n\r\n//\tm_node_array_is_set_up = true;\r\n\r\n\t\r\n\tset_flag(mNODE_INFO_GENERATED);\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tCan use 'type' parameter only to remove only CPieces, but not underlying sector. This is useful\r\n\tfor freeing up memory no longer needed once park is generated.\r\n*/\r\nvoid CParkGenerator::DestroyAllClonedPieces(EDestroyType type)\r\n{\r\n\tif (type == DESTROY_PIECES_AND_SECTORS)\r\n\t{\r\n\t\tObj::GetRailEditor()->DestroyRailGeometry();\r\n\t\tObj::GetRailEditor()->DestroyPostGeometry();\r\n\t}\t\r\n\t\r\n\tCPiece *p_entry = mp_cloned_piece_list;\r\n\twhile(p_entry)\r\n\t{\r\n\t\tCPiece *p_next_entry = p_entry->mp_next_in_list;\r\n\t\tdestroy_piece_impl(p_entry->CastToCClonedPiece(), type);\r\n\t\tp_entry = p_next_entry;\r\n\t}\r\n\t\r\n\tif (type == DESTROY_PIECES_AND_SECTORS)\r\n\t\tclear_flag(mSECTORS_GENERATED);\r\n\tclear_flag(mPIECES_IN_WORLD);\r\n\r\n\tif (type == DESTROY_PIECES_AND_SECTORS)\r\n\t{\r\n\t\t// CHUNKY\r\n\t\tDbg_Assert(mp_cloned_scene);\r\n\t\tmp_cloned_scene->ClearSuperSectors();\r\n\t}\t\r\n}\r\n\r\n\r\n\r\n\r\nvoid\tCParkGenerator::HighlightAllPieces(bool highlight)\r\n{\r\n\tCPiece *p_entry = mp_cloned_piece_list;\r\n\twhile(p_entry)\r\n\t{\r\n\t\tCPiece *p_next_entry = p_entry->mp_next_in_list;\r\n\t\tp_entry->CastToCClonedPiece()->Highlight(highlight);\r\n\t\tp_entry = p_next_entry;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid\tCParkGenerator::SetGapPiecesVisible(bool visible)\r\n{\r\n#if 1\t\r\n\t// Nothing doing here yet, eventually will turn off the wireframe pieces\r\n\tCPiece *p_entry = mp_cloned_piece_list;\r\n\twhile(p_entry)\r\n\t{\r\n\t\tCPiece *p_next_entry = p_entry->mp_next_in_list;\r\n\t\tif (p_entry->CastToCClonedPiece()->GetFlags() & CPiece::mGAP)\r\n\t\t{\r\n\t\t\t//Dbg_Assert(0);\r\n\t\t\tp_entry->CastToCClonedPiece()->SetVisibility(visible);\r\n\t\t}\r\n\t\tp_entry = p_next_entry;\r\n\t}\r\n#endif\r\n}\r\n\r\n\r\n\r\n\r\nvoid\tCParkGenerator::SetRestartPiecesVisible(bool visible)\r\n{\r\n\tRyan(\"the stars go in and the stars go out %d\\n\", visible);\r\n\tCPiece *p_entry = mp_cloned_piece_list;\r\n\twhile(p_entry)\r\n\t{\r\n\t\tCPiece *p_next_entry = p_entry->mp_next_in_list;\r\n\t\tuint32 id = p_entry->CastToCClonedPiece()->mp_source_piece->GetType();\r\n\t\tif (CParkManager::Instance()->IsRestartPiece(id))\r\n\t\t{\r\n\t\t\tp_entry->CastToCClonedPiece()->SetActive(visible);\t\r\n\t\t}\r\n\t\tp_entry = p_next_entry;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkGenerator::SetLightProps(int num_lights, \r\n\t\t\t\t\t\t  float amb_const_r, float amb_const_g, float amb_const_b, \r\n\t\t\t\t\t\t  float falloff_const_r, float falloff_const_g, float falloff_const_b,\r\n\t\t\t\t\t\t  float cursor_ambience)\r\n{\r\n\t\r\n\tDbg_MsgAssert(num_lights <= vMAX_LIGHTS, (\"too many lights\"));\r\n\tm_numLights = num_lights;\r\n\t\r\n\tm_ambientLightIntensity.r = amb_const_r;\r\n\tm_ambientLightIntensity.g = amb_const_g;\r\n\tm_ambientLightIntensity.b = amb_const_b;\r\n\tm_falloffLightIntensity.r = falloff_const_r;\r\n\tm_falloffLightIntensity.g = falloff_const_g;\r\n\tm_falloffLightIntensity.b = falloff_const_b;\r\n\r\n\tm_cursorAmbience = cursor_ambience;\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkGenerator::SetLight(Mth::Vector &light_pos, int light_num)\r\n{\r\n\t\r\n\tDbg_MsgAssert(light_num < m_numLights, (\"out of light slots\"));\r\n\r\n\tm_lightTab[light_num] = light_pos;\r\n}\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t   \r\n// Given the id of a piece in the world, apply the lights to it\t\t\t\t\t\t\t\t\t\t\t   \r\nvoid CParkGenerator::CalculateLighting(CClonedPiece *p_piece)\r\n{\t\r\n\tNx::CSector *p_sector= Nx::CEngine::sGetSector(p_piece->m_sector_checksum);\r\n\tDbg_MsgAssert(p_sector,(\"Trying to Calculate lighting on non-existant sector\"))\r\n\tNx::CGeom \t*p_geom = p_sector->GetGeom();\r\n\tDbg_MsgAssert(p_geom,(\"sector does not have geometry\"))\r\n\t\r\n\tNx::CSector *p_source_sector= Nx::CEngine::sGetSector(p_piece->GetSourcePiece()->GetType());\r\n\tDbg_MsgAssert(p_source_sector,(\"Trying to Calculate lighting on sector with no source sector\"))\r\n\tNx::CGeom \t*p_source_geom = p_source_sector->GetGeom();\r\n\tDbg_MsgAssert(p_source_geom,(\"source sector does not have geometry\"))\r\n\r\n\t//\r\n\t// Do renderable geometry\r\n\tint verts = p_geom->GetNumRenderVerts();\r\n\tDbg_MsgAssert(verts == p_source_geom->GetNumRenderVerts(),(\"source and clone have differing no of verts (%d, %d)\\n\",verts,p_source_geom->GetNumRenderVerts()));\r\n\r\n\tif (verts)\r\n\t{\r\n\t\tMth::Vector\t*p_verts = new Mth::Vector[verts];\r\n\t\tImage::RGBA\t*p_colors = new Image::RGBA[verts];\r\n\t\tp_geom->GetRenderVerts(p_verts);\r\n\t\tp_source_geom->GetRenderColors(p_colors);\r\n\t\r\n\t\tImage::RGBA *p_color = p_colors;\r\n\t\tMth::Vector *p_vert = p_verts;\r\n\t\tfor (int i = 0; i < verts; i++)\r\n\t\t{\r\n\t\t\tCalculateVertexLighting(*p_vert, *p_color);\r\n\r\n\t\t\tp_color++;\r\n\t\t\tp_vert++;\r\n\t\t} // end for\r\n\r\n\t\t// Set the colors on the actual new geom, not on the source...\t\t\r\n\t\tp_geom->SetRenderColors(p_colors);\r\n\t\t\r\n\t\tdelete [] p_verts;\r\n\t\tdelete [] p_colors;\r\n\t} // end if\r\n\telse\r\n\t{\r\n\t\t// debuggery\r\n\t\t//p_geom->SetColor(Image::RGBA(0,0,100,0));\r\n\t}\r\n\r\n\r\n\t//\r\n\t// Do collision geometry\r\n\tNx::CCollObjTriData *p_coll_tri_data = p_geom->GetCollTriData();\r\n\tNx::CCollObjTriData *p_source_coll_tri_data = p_source_geom->GetCollTriData();\r\n\r\n\tDbg_MsgAssert(p_coll_tri_data, (\"sector does not have collision\"));\r\n\tDbg_MsgAssert(p_source_coll_tri_data, (\"source sector does not have collision\"));\r\n\r\n#ifdef __PLAT_NGC__\r\n\tint faces = p_coll_tri_data->GetNumFaces();\r\n\tDbg_MsgAssert(faces == p_source_coll_tri_data->GetNumFaces(), (\"source and clone have differing no of collision faces (%d, %d)\\n\",verts,p_source_coll_tri_data->GetNumFaces()));\r\n\r\n\tImage::RGBA color;\r\n\tunsigned char intensity;\r\n\tunsigned int avg_color;\r\n\tfor (int f = 0; f < faces; f++)\r\n\t{\r\n\t\tfor ( int c = 0; c < 3; c++ )\r\n\t\t{\r\n\t\t\tintensity = p_source_coll_tri_data->GetVertexIntensity(f, c);\r\n\r\n\t\t\tcolor.r = intensity;\r\n\t\t\tcolor.g = intensity;\r\n\t\t\tcolor.b = intensity;\r\n\t\t\tcolor.a = 255;\r\n\r\n\t\t\tCalculateVertexLighting(p_coll_tri_data->GetRawVertexPos(p_coll_tri_data->GetFaceVertIndex(f, c)), color);\r\n\t\t\tavg_color = (color.r + color.g + color.b) / 3;\r\n\t\t\tp_coll_tri_data->SetVertexIntensity(f, c, avg_color);\r\n\t\t}\r\n\t}\r\n#else\r\n\tverts = p_coll_tri_data->GetNumVerts();\r\n\tDbg_MsgAssert(verts == p_source_coll_tri_data->GetNumVerts(), (\"source and clone have differing no of collision verts (%d, %d)\\n\",verts,p_source_coll_tri_data->GetNumVerts()));\r\n\r\n\tImage::RGBA color;\r\n\tunsigned char intensity;\r\n\tunsigned int avg_color;\r\n\tfor (int i = 0; i < verts; i++)\r\n\t{\r\n\t\tintensity = p_source_coll_tri_data->GetVertexIntensity(i);\r\n\r\n\t\tcolor.r = intensity;\r\n\t\tcolor.g = intensity;\r\n\t\tcolor.b = intensity;\r\n\t\tcolor.a = 255;\r\n\r\n\t\tCalculateVertexLighting(p_coll_tri_data->GetRawVertexPos(i), color);\r\n\r\n\t\tavg_color = (color.r + color.g + color.b) / 3;\r\n\t\tp_coll_tri_data->SetVertexIntensity(i, avg_color);\r\n\r\n\t}\r\n#endif // __PLAT_NGC__\r\n}\r\n\r\n\r\n// apply lights to a vert\t\t\t\t\t\t\t\t\t\t\t   \r\nvoid CParkGenerator::CalculateVertexLighting(const Mth::Vector & vert, Image::RGBA & color)\r\n{\r\n\tLightIntensity i_amb;\r\n\r\n\ti_amb.r = (float) color.r \t* m_ambientLightIntensity.r;\r\n\ti_amb.g = (float) color.g \t* m_ambientLightIntensity.g;\r\n\ti_amb.b = (float) color.b \t* m_ambientLightIntensity.b;\r\n\r\n\tfloat i_spot_light = 0.0f;\r\n\tMth::Vector *pLightTabEntry = m_lightTab;\r\n\tfor (int l = 0; l < m_numLights; l++)\r\n\t{\r\n\t\tfloat dist_x = vert.GetX() - pLightTabEntry->GetX();\r\n\t\t//float dist_y = vert.GetY() - pLightTabEntry->GetY();\r\n\t\tfloat dist_y = 400;\t// Mick:  Patched to ignore height, otherwise we have burningly bright spots on high walls\r\n\t\t\t\t\t\t\t// you can decrease this number make the lighhing more intense\r\n\t\t\t\t\t\t\t// (note, this means no verticle variation in brightness in the park editor\r\n\t\tfloat dist_z = vert.GetZ() - pLightTabEntry->GetZ();\r\n\r\n\t\tfloat dist_squared = dist_x * dist_x + dist_y * dist_y + dist_z * dist_z;\r\n\t\ti_spot_light += 1.0f / dist_squared;\r\n\r\n\t\tpLightTabEntry++;\r\n\t}\r\n\ti_spot_light *= 255.0f;\r\n\r\n\ti_amb.r += i_spot_light * m_falloffLightIntensity.r;\r\n\tif (i_amb.r > 255.0)\r\n\t\tcolor.r = 255;\r\n\telse\r\n\t\tcolor.r = (uint8) (i_amb.r);\r\n\r\n\ti_amb.g += i_spot_light * m_falloffLightIntensity.g;\r\n\tif (i_amb.g > 255.0)\r\n\t\tcolor.g = 255;\r\n\telse \r\n\t\tcolor.g = (uint8) (i_amb.g);\r\n\r\n\ti_amb.b += i_spot_light * m_falloffLightIntensity.b;\r\n\tif (i_amb.b > 255.0)\r\n\t\tcolor.b = 255;\r\n\telse\r\n\t\tcolor.b\t= (uint8) (i_amb.b);\r\n}\r\n\r\n\r\n/*\r\n\tSee comments in DestroyAllClonedPieces() for 'destroyType'\r\n*/\r\nvoid CParkGenerator::destroy_piece_impl(CClonedPiece *pPiece, EDestroyType destroyType)\r\n{\r\n\t// XXX\r\n\tif (pPiece->m_flags & CPiece::mGAP)\r\n\t\tRyan(\"@@@ destroying gap piece 0x%x\\n\", pPiece);\r\n\r\n\tif (!(pPiece->m_flags & CClonedPiece::mSOFT_PIECE))\r\n\t{\r\n\t\t// remove from list\tfirst\r\n\t\tCPiece *p_entry = mp_cloned_piece_list;\r\n\t\tCPiece *p_prev = NULL;\r\n\t\twhile(p_entry)\r\n\t\t{\r\n\t\t\tif (p_entry == pPiece)\r\n\t\t\t{\r\n\t\t\t\tif (p_prev)\r\n\t\t\t\t\tp_prev->mp_next_in_list = p_entry->mp_next_in_list;\r\n\t\t\t\telse\r\n\t\t\t\t\tmp_cloned_piece_list = p_entry->mp_next_in_list;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tp_prev = p_entry;\r\n\t\t\tp_entry = p_entry->mp_next_in_list;\r\n\t\t}\r\n\t\tDbg_MsgAssert(p_entry, (\"piece not found\"));\r\n\t\t\r\n\t\tif (!(pPiece->m_flags & CPiece::mNO_RAILS))\r\n\t\t{\r\n\t\t\tm_total_rail_points -= pPiece->mp_source_piece->m_num_rail_points;\r\n\t\t\tm_total_rail_linked_points -= pPiece->mp_source_piece->m_num_linked_rail_points;\r\n\t\t}\r\n\t}\r\n\r\n\t// now actually destroy piece\r\n\tif (destroyType == DESTROY_PIECES_AND_SECTORS)\r\n\t{\r\n\t\t#if 0\r\n\t\tprintf(\"    Gott mit uns (%f,%f,%f)\\n\", \r\n\t\t\t   pPiece->GetPos().GetX(), pPiece->GetPos().GetY(), pPiece->GetPos().GetZ());\r\n\t\t#endif\r\n\t\t// destroy underlying sector\r\n\t\tmp_cloned_scene->DeleteSector(pPiece->m_sector_checksum);\r\n\t\t\r\n\t\t#ifdef __PLAT_NGC__\r\n\t\t//printf(\"Called DeleteSector\\n\");\r\n\t\tNx::CEngine::sFinishRendering();\r\n\t\t#endif\r\n\t}\r\n\t\r\n\tm_num_cloned_pieces--;\r\n\t\r\n\tdelete pPiece;\r\n\r\n\tif (!mp_cloned_piece_list)\r\n\t\tclear_flag(mPIECES_IN_WORLD);\r\n\tset_flag(mSECTOR_MEMORY_NEEDS_FREE);\r\n}\r\n\r\n\r\n\r\n// Read in the node array containing the rail information\r\n// and parse this into the park editor format....\r\n\r\n// called from CParkManager::Initialize()\r\nvoid CParkGenerator::ReadInRailInfo()\r\n{\r\n\tconst uint32 crc_cluster \t\t= 0x1a3a966b;\r\n    const uint32 crc_class \t\t\t= 0x12b4e660;\r\n\tconst uint32 crc_links \t\t\t= 0x2e7d5ee7;\r\n\r\n\tprintf (\"Starting ReadInRailInfo()\\n\");\r\n\r\n// Mick - Not sure where this should be set up\r\n\tm_in_rail_set.SetupAllocators(GetResourceSize(\"in_railpoint_pool\"), GetResourceSize(\"in_railstring_pool\"), true);\r\n\r\n\t\r\n\t// Ken: This function has gone now, since the new ability to unload a qb has made it redundant.\r\n\t//Script::RemoveOldTriggerScripts();\r\n\t\r\n\t// Remove any spawned scripts that might have been left over from the previous level.\r\n\tScript::DeleteSpawnedScripts();\t\r\n\t\t\r\n\t// Load the QB\r\n//\tSkateScript::LoadQB(PIECE_SET_QB[m_currentThemeNumber]);\r\n//\tSkateScript::LoadQB(\"levels\\\\sk4ed\\\\sk4ed.qb\");\t\t\t  // assume it has already been loaded (NOTE: If not, then you will have problems with PRE files, as the .QBs do not go in the pre file)\r\n\t// Ensure it has a node array in it\r\n\tScript::CArray *pNodeArray=Script::GetArray(CRCD(0xc472ecc5,\"NodeArray\"));\r\n\tDbg_MsgAssert(pNodeArray,(\"Park editor node array not found\"));\r\n\t\t\r\n\t// this will load up sounds\r\n\tScript::RunScript(\"LoadTerrain\");\r\n\t\r\n\tRyan(\"\\n*** Reading in rail info ***\\n\");\r\n\tm_in_rail_set.Destroy();\r\n\t// BAD MEM\r\n\tm_processed_node_tab = new int[256];\r\n\tm_processed_node_tab_entries = 0;\r\n\tm_temp_node_tab = new TempNodeInfo[2048];\r\n\r\n\t\r\n\tint index = 0;\r\n\tfor ( ; index < (int)pNodeArray->GetSize(); index++)\r\n\t{\r\n\t\tScript::CScriptStructure *pStruct = pNodeArray->GetStructure(index);\r\n\t\r\n\t\tm_temp_node_tab[index].classCrc = 0;\r\n\t\tpStruct->GetChecksum(crc_class, &m_temp_node_tab[index].classCrc);\r\n\t\tm_temp_node_tab[index].cluster = 0;\r\n\t\tpStruct->GetChecksum(crc_cluster, &m_temp_node_tab[index].cluster);\r\n\t\tm_temp_node_tab[index].pLinkArray = NULL;\r\n\t\tpStruct->GetArray(crc_links, &m_temp_node_tab[index].pLinkArray);\r\n\t}\r\n\r\n\t\r\n\tconst bool debug_rail_read = true;\r\n\t\r\n\t// XXX\r\n\tRyan(\"number of node entries is %d\\n\", pNodeArray->GetSize());\r\n\t\r\n\tindex = 0;\r\n\t// loop through all LevelGeometry objects in node array.\r\n\t// for each one, locate associated rail nodes (if any) and create RailString.\r\n\twhile(1)\r\n\t{\r\n\t\t// get cluster checksum of LevelGeometry object, will be used to\r\n\t\t// look up rail nodes\r\n\t\tuint32 cluster_crc = scan_for_cluster(pNodeArray, index);\r\n\t\tif (index >= (int)pNodeArray->GetSize())\r\n\t\t{\r\n\t\t\tprintf (\"No more clusters, exiting\\n\"); \r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n//\t\tprintf(\"source piece %s for cluster \\n\", Script::FindChecksumName(cluster_crc));\t\t\r\n\t\t\r\n\t\t//debug_rail_read = (cluster_crc == 0x21997899);\r\n#ifdef __NOPT_ASSERT__\r\n\t\tCPiece *pMasterPiece = GetMasterPiece(cluster_crc);\r\n\t\t\r\n\t\tCSourcePiece *pSourcePiece = pMasterPiece->CastToCSourcePiece();\r\n\t\t\r\n\t\tDbg_MsgAssert(pSourcePiece, (\"no source piece %s found\", Script::FindChecksumName(cluster_crc)));\t\t\r\n#endif\t\t// __NOPT_ASSERT__\r\n\t\tif (debug_rail_read)\r\n\t\t\tRyan(\"found cluster %s at index %d\\n\", Script::FindChecksumName(cluster_crc), index-1);\r\n\r\n\t\tMth::Vector v;\r\n\t\tRailPoint::RailType type;\r\n\t\t\t   \r\n\t\t// find all rail strings associated with current LevelGeometry object\r\n\t\t// m_processed_node_tab[] keeps track of strings already processed\r\n\t\tm_processed_node_tab_entries = 0;\r\n\t\twhile (1)\r\n\t\t{\r\n\t\t\tbool string_is_loop = false;\r\n\t\t\t\r\n\t\t\t// try to locate a rail node that matches the cluster and has no links\r\n\t\t\t// if it fails to find one, it will try to return one that matches the cluster and does have links\r\n\t\t\tint last_node_in_set = scan_for_rail_node(pNodeArray, cluster_crc, -1, &v, &string_is_loop, &type);\r\n\t\t\tif (last_node_in_set == -1)\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tint current_node = last_node_in_set;\r\n\t\t\t\r\n\t\t\tRailString *pCurrentString = m_in_rail_set.CreateRailString();\r\n\t\t\tpCurrentString->m_id = cluster_crc;\r\n\t\t\tpCurrentString->m_isLoop = string_is_loop;\r\n\r\n\t\t\tRailPoint *pPoint = m_in_rail_set.CreateRailPoint();\r\n\t\t\t//pPoint->m_pos.Set(v.GetX() - pSourcePiece->m_pos.GetX(), v.GetY() - pSourcePiece->m_pos.GetY(), v.GetZ() + pSourcePiece->m_pos.GetZ());\r\n\t\t\tpPoint->m_pos.Set(v.GetX(), v.GetY(), v.GetZ());\r\n\t\t\tpPoint->m_type = type;\r\n\t\t\tif (debug_rail_read)\r\n\t\t\t\tRyan(\"* [%.1f,%.1f,%.1f]\", pPoint->m_pos.GetX(), pPoint->m_pos.GetY(), pPoint->m_pos.GetZ());\r\n\t\t\tpCurrentString->AddPoint(pPoint);\r\n\t\t\t\r\n\t\t\t// go through all points in the string (after the first)\r\n\t\t\twhile (1)\r\n\t\t\t{\r\n\t\t\t\tcurrent_node = scan_for_rail_node(pNodeArray, cluster_crc, current_node, &v, &string_is_loop, &type);\r\n\t\t\t\tif (current_node == -1)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (debug_rail_read && pCurrentString->m_isLoop)\r\n\t\t\t\t\t\tRyan(\" (loop)\");\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t\r\n\t\t\t\tpPoint = m_in_rail_set.CreateRailPoint();\r\n\t\t\t\t//pPoint->m_pos.Set(v.GetX() - pSourcePiece->m_pos.GetX(), v.GetY() - pSourcePiece->m_pos.GetY(), v.GetZ() + pSourcePiece->m_pos.GetZ());\r\n\t\t\t\tpPoint->m_pos.Set(v.GetX(), v.GetY(), v.GetZ());\r\n\t\t\t\tpPoint->m_type = type;\r\n\t\t\t\tif (debug_rail_read)\r\n\t\t\t\t\tRyan(\"-[%.1f,%.1f,%.1f]\", pPoint->m_pos.GetX(), pPoint->m_pos.GetY(), pPoint->m_pos.GetZ());\r\n\t\t\t\tpCurrentString->AddPoint(pPoint);\r\n\t\t\t}\r\n\r\n\t\t\tif (debug_rail_read)\r\n\t\t\t\tRyan(\"\\n\");\r\n\t\t\tm_in_rail_set.AddString(pCurrentString);\r\n\t\t} // end while\r\n\t} // end while\r\n\r\n\tdelete m_processed_node_tab;\r\n\tdelete m_temp_node_tab;\r\n\r\n\tscan_in_trigger_info(pNodeArray);\r\n//\r\n//\tm_nodeArrayIsSetup = true;\r\n//\tDestroyCollisionDataAndNodeArray();\r\n\r\n\t// now that rail info is set up, it's safe to do this next block of code\r\n\tCPiece *p_piece = mp_source_piece_list;\r\n\twhile(p_piece)\r\n\t{\r\n\t\tCSourcePiece *p_source_piece = p_piece->CastToCSourcePiece();\r\n\r\n\t\tp_source_piece->m_num_rail_points = 0;\r\n\t\tp_source_piece->m_num_linked_rail_points = 0;\r\n\t\tint string_num = 0;\r\n\t\twhile(1)\r\n\t\t{\r\n\t\t\tRailString *p_rail_string = m_in_rail_set.GetString(p_source_piece->GetType(), string_num++);\r\n\t\t\tif (!p_rail_string)\r\n\t\t\t\tbreak;\r\n\t\t\tp_source_piece->m_num_rail_points += p_rail_string->Count();\r\n\t\t\tp_source_piece->m_num_linked_rail_points += p_rail_string->CountLinkedPoints();\r\n\t\t}\r\n\r\n\t\tp_piece = p_piece->mp_next_in_list;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n// called from CParkManager::Destroy()\r\nvoid CParkGenerator::DestroyRailInfo()\r\n{\r\n\tm_in_rail_set.Destroy();\r\n\tm_in_rail_set.FreeAllocators();\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n// returns checksum of first found cluster, increases index appropriately\r\n// called from ReadInRailInfo()\r\nuint32 CParkGenerator::scan_for_cluster(Script::CArray *pNodeArray, int &index)\r\n{\r\n    const uint32 crc_class \t\t\t= 0x12b4e660;\r\n    const uint32 crc_levelgeometry = 0xbf4d3536;\t\t//0xdabd3086;\r\n\tconst uint32 crc_name \t\t\t= 0xa1dc81f9;\r\n\r\n\tint total_entries = pNodeArray->GetSize();\r\n\r\n\t/*\r\n\t\tGiven a node like...\r\n\t\t\r\n\t\t{\r\n\t\t\t// Node 471\r\n\t\t\tPosition = (-0.002991,1200.000000,0.000854)\r\n\t\t\tAngles = (0.000000,0.000000,0.000000)\r\n\t\t\tName = Sk3Ed_Shell_Col_16x16_01\r\n\t\t\tClass = levelgeometry\r\n\t\t\tCreatedAtStart\r\n\t\t}\r\n\t\t\r\n\t\t... make sure it's level geometry, then find the value\r\n\t\tof 'Name'\r\n\t*/\r\n\twhile (index < total_entries)\r\n\t{\r\n\t\tScript::CStruct *pStruct = pNodeArray->GetStructure(index);\r\n\t\t\r\n\t\tuint32 node_class = 0;\r\n\t\tpStruct->GetChecksum(crc_class, &node_class);\r\n\t\t\r\n\t\tif (node_class == crc_levelgeometry)\r\n\t\t{\r\n\t\t\tuint32 name;\r\n\t\t\tif (pStruct->GetChecksum(crc_name, &name))\r\n\t\t\t{\r\n\t\t\t\tindex++;\r\n\t\t\t\treturn name;\r\n\t\t\t}\t\t\t\r\n\t\t}\r\n\r\n\t\tindex++;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n\r\n/* \r\n\treturns number of node\r\n\t3 ways of calling:\r\n\t\t-link set: find rail node with that link\r\n\t\t-cluster set, link -1: find rail node with that cluster, but no link\r\n\t\t-cluster set, link -2: find rail node with that cluster, can have a link\r\n\t\r\n\tCalled from ReadInRailInfo()\r\n*/\r\nint CParkGenerator::scan_for_rail_node(Script::CArray *pNodeArray, uint32 cluster, int link, Mth::Vector *pVector, bool *pHasLinks, RailPoint::RailType *pType)\r\n{\r\n\t\r\n\t\r\n//\tconst uint32 crc_position \t\t= 0xb9d31b0a;\r\n\t//const uint32 crc_links \t\t\t= 0x2e7d5ee7;\r\n\t//const uint32 crc_cluster \t\t= 0x1a3a966b;\r\n\tconst uint32 crc_terraintype\t= 0x54cf8532;\r\n//\tconst uint32 crc_terrain_wood\t= 0x39075ea5;\r\n\t\r\n    //const uint32 crc_class \t\t\t= 0x12b4e660;\r\n    const uint32 crc_railnode \t\t= 0x8e6b02ad;\r\n\r\n\tint found_node_with_link_index = -1;\r\n\tint found_node_without_link_index = -1;\r\n\t\r\n\t/*\r\n\t\tA little optimization:\r\n\t\r\n\t\tWe first call this function with link<0, so at that time\r\n\t\tstore the index of the first node belonging to the requested\r\n\t\tcluster.\r\n\t\t\r\n\t\tSeveral following calls to this function will start the node\r\n\t\tsearch from this point\r\n\t*/\r\n\t\r\n\tstatic int first_node_in_cluster;\r\n\tif (link < 0)\r\n\t\tfirst_node_in_cluster = 0;\r\n\r\n\tint total_entries = pNodeArray->GetSize();\r\n\tfor (int n = first_node_in_cluster; n < total_entries; n++)\r\n\t{\r\n\t\t//Script::CScriptStructure *pStruct = pNodeArray->GetStructure(n);\r\n\t\r\n\t\tuint32 node_class = m_temp_node_tab[n].classCrc;\r\n\t\tif (node_class == crc_railnode)\r\n\t\t{\r\n\t\t\t// find link\r\n\t\t\tint found_link = -1;\r\n\t\t\tScript::CArray *pLinkArray = m_temp_node_tab[n].pLinkArray;\r\n\t\t\tif (pLinkArray)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(pLinkArray->GetSize() == 1, (\"Rail node %d has more than one link (%d)\",n,pLinkArray->GetSize()));\r\n\t\t\t\tfound_link = pLinkArray->GetInt(0);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tuint32 found_cluster = m_temp_node_tab[n].cluster;\r\n\t\t\t//Ryan(\"   cluster is %s, link is %d\\n\", Script::FindChecksumName(found_cluster), found_link);\r\n\r\n\t\t\tif (link >= 0)\r\n\t\t\t{\r\n\t\t\t\tif (found_link == link)\r\n\t\t\t\t{\r\n\t\t\t\t\tfound_node_with_link_index = n;\r\n\t\t\t\t\tfor (int i = 0; i < m_processed_node_tab_entries; i++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (m_processed_node_tab[i] == found_node_with_link_index)\r\n\t\t\t\t\t\t\t// we've already processed this node\r\n\t\t\t\t\t\t\tfound_node_with_link_index = -1;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (found_node_with_link_index != -1)\r\n\t\t\t\t\t\t// in this case, we have all the info we need, so exit loop\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (cluster == found_cluster)\r\n\t\t\t{\r\n\t\t\t\tif (!first_node_in_cluster)\r\n\t\t\t\t\tfirst_node_in_cluster = n;\r\n\t\t\t\t\r\n\t\t\t\tif (found_link == -1)\r\n\t\t\t\t{\r\n\t\t\t\t\tfound_node_without_link_index = n;\r\n\t\t\t\t\tfor (int i = 0; i < m_processed_node_tab_entries; i++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (m_processed_node_tab[i] == found_node_without_link_index)\r\n\t\t\t\t\t\t\t// we've already processed this node\r\n\t\t\t\t\t\t\tfound_node_without_link_index = -1;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (found_node_without_link_index != -1)\r\n\t\t\t\t\t\t// this is the node we're looking for, so exit loop\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\telse if (found_node_with_link_index == -1) // && found_link >= 0\r\n\t\t\t\t{\r\n\t\t\t\t\tfound_node_with_link_index = n;\r\n\t\t\t\t\tfor (int i = 0; i < m_processed_node_tab_entries; i++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (m_processed_node_tab[i] == found_node_with_link_index)\r\n\t\t\t\t\t\t\t// we've already processed this node\r\n\t\t\t\t\t\t\tfound_node_with_link_index = -1;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// even if not already processed, this node is secondary priority, \r\n\t\t\t\t\t// so we will not be exiting the loop\r\n\t\t\t\t}\r\n\t\t\t} // end else if\r\n\t\t} // if (node_class == crc_railnode)\r\n\t}\r\n\t\t\r\n\t// the node without a link has greater priority\r\n\tint match_index = -1;\r\n\tif (found_node_with_link_index != -1)\r\n\t{\r\n\t\tmatch_index = found_node_with_link_index;\r\n\t\t*pHasLinks = true;\r\n\t}\r\n\tif (found_node_without_link_index != -1)\r\n\t{\r\n\t\tmatch_index = found_node_without_link_index;\t\r\n\t\t*pHasLinks = false;\r\n\t}\r\n\tif (match_index == -1) return -1;\r\n\r\n\t// store this node so we won't use it twice\r\n\tm_processed_node_tab[m_processed_node_tab_entries++] = match_index;\r\n\t// fetch position info (will be returned to caller)\r\n\tScript::CScriptStructure *pFound = pNodeArray->GetStructure(match_index);\r\n\t\r\n\tpFound->GetVector(CRCD(0x7f261953,\"Pos\"), pVector, true);\r\n\r\n// GJ:  The following was incorrect, because the Z component should have been negated,\r\n// however, the function that was supposed to use this data should have negated it again,\r\n// but didn't, meaning that the 2 bugs ended up cancelling each other out.\r\n// The new-style 'pos' vector is already correct and needs no negation.\r\n//\tpFound->GetVector(CRCD(0xb9d31b0a,\"Position\"), pVector, false);\r\n\t\r\n\tuint32 terrain_type; // terrain_wood\r\n\tpFound->GetChecksum(crc_terraintype, &terrain_type, true);\r\n\t\r\n//\tif (terrain_type == crc_terrain_wood)\r\n//\t\t*pType = RailPoint::vWOOD;\r\n//\telse\r\n//\t\t*pType = RailPoint::vMETAL;\r\n\r\n\t*pType =  terrain_type; \r\n\r\n\treturn match_index;\r\n}\r\n\r\n\r\n\r\n\r\n// \tShould be called from ReadInRailInfo(), but isn't\r\nvoid CParkGenerator::scan_in_trigger_info(Script::CArray *pNodeArray)\r\n{\r\n\t//const uint32 crc_position \t\t= 0xb9d31b0a;\r\n    const uint32 crc_class \t\t\t= 0x12b4e660;\r\n    const uint32 crc_levelgeometry = 0xbf4d3536;\t\t//0xdabd3086;\r\n\tconst uint32 crc_name \t\t\t= 0xa1dc81f9;\r\n    const uint32 crc_triggerscript \t= 0x2ca8a299;\r\n\r\n\tfor (uint32 n = 0; n < pNodeArray->GetSize(); n++)\r\n\t{\r\n\t\tScript::CScriptStructure *pStruct = pNodeArray->GetStructure(n);\r\n\t\t\r\n\t\tuint32 node_class = 0;\r\n\t\tpStruct->GetChecksum(crc_class, &node_class);\r\n\t\t\r\n\t\tif (node_class == crc_levelgeometry)\r\n\t\t{\r\n\t\t\tuint32 piece_name = 0;\r\n\t\t\tpStruct->GetChecksum(crc_name, &piece_name);\r\n\t\t\tuint32 trigger_name = 0;\r\n\t\t\tpStruct->GetChecksum(crc_triggerscript, &trigger_name);\r\n\t\t\t\r\n\t\t\tif (piece_name && trigger_name)\r\n\t\t\t{\r\n\t\t\t\t// XXX\r\n\t\t\t\tRyan(\"Setting up trigger script: piece=%s script=%s\\n\", Script::FindChecksumName(piece_name), Script::FindChecksumName(trigger_name));\r\n\t\t\t\tCPiece *pPiece = GetMasterPiece(piece_name, true);\r\n\t\t\t\tCSourcePiece *pSourcePiece = pPiece->CastToCSourcePiece();\r\n\t\t\t\tpSourcePiece->m_triggerScriptId = trigger_name;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tRyan(\"done with all rail reading\\n\");\r\n}\r\n\r\n\r\n\r\n\r\nvoid CParkGenerator::set_up_object_nodes(Script::CArray *pNodeArray, int *pNodeNum)\r\n{\r\n\t\r\n\r\n\tRyan(\"set_up_object_nodes: %d/%d\\n\", Mem::CPoolable<Script::CComponent>::SGetNumUsedItems(), Mem::CPoolable<Script::CComponent>::SGetTotalItems());\r\n\tRyan(\"CVector use: %d/%d\\n\", Mem::CPoolable<Script::CVector>::SGetNumUsedItems(), Mem::CPoolable<Script::CVector>::SGetTotalItems());\r\n\r\n#if 1\r\n//\tuint32 crc_position \t\t\t= Script::GenerateCRC(\"position\");\r\n\tuint32 crc_angles \t\t\t\t= Script::GenerateCRC(\"angles\");\r\n\tuint32 crc_name \t\t\t\t= Script::GenerateCRC(\"name\");\r\n\tuint32 crc_class \t\t\t\t= Script::GenerateCRC(\"class\");\r\n\tuint32 crc_levelgeometry \t\t= Script::GenerateCRC(\"LevelGeometry\");\r\n\tuint32 crc_createdatstart \t\t= Script::GenerateCRC(\"CreatedAtStart\");\r\n\tuint32 crc_triggerscript \t\t= Script::GenerateCRC(\"TriggerScript\");\r\n\tuint32 crc_trickobject \t\t\t= Script::GenerateCRC(\"TrickObject\");\r\n\tuint32 crc_cluster \t\t\t\t= Script::GenerateCRC(\"Cluster\");\r\n\t\r\n\t// 7\r\n\tCPiece *p_piece = mp_cloned_piece_list;\r\n\twhile (p_piece)\r\n\t{\r\n\t\tCClonedPiece *p_cloned = p_piece->CastToCClonedPiece();\r\n\t\tif (!(p_cloned->GetFlags() & CPiece::mFLOOR) && \r\n\t\t\t!(p_cloned->GetFlags() & CPiece::mRESTART))\r\n\t\t{\r\n\t\t\t\r\n\t\t\tScript::CScriptStructure *pNode = pNodeArray->GetStructure(*pNodeNum);\r\n\t\t\tMth::Vector pos = p_cloned->GetPos();\r\n\t\t\tpNode->AddComponent(CRCD(0x7f261953,\"pos\"), pos.GetX(), pos.GetY(), pos.GetZ());\r\n// GJ:  The following was incorrect, and the Z component should have been negated,\r\n// but no one ever really used it, so we never noticed that it was a problem...\r\n// The new-style 'pos' vector is already correct and needs no negation.\r\n//\t\t\tpNode->AddComponent(CRCD(0xb9d31b0a,\"position\"), pos.GetX(), pos.GetY(), pos.GetZ());\r\n\t\t\tpNode->AddComponent(crc_angles, 0.0f, 0.0f, 0.0f);\r\n\t\t\t// hopefully safe\r\n\t\t\t// XXX\r\n\t\t\tRyan(\"id is 0x%x\\n\", p_cloned->m_id);\r\n\t\t\tpNode->AddComponent(crc_name, ESYMBOLTYPE_NAME, (int) p_cloned->m_sector_checksum);\r\n\t\t\tpNode->AddComponent(crc_class, ESYMBOLTYPE_NAME, (int) crc_levelgeometry);\r\n\t\t\tpNode->AddComponent(NONAME, ESYMBOLTYPE_NAME, (int) crc_createdatstart);\r\n\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\t\tpNode->AddComponent(NONAME, ESYMBOLTYPE_NAME, (int) crc_trickobject);\r\n// Mick:  use the cloned pieces ID, but EOR with with 0xffffffff so it's different to the original name\r\n\t\t\tpNode->AddComponent(crc_cluster, ESYMBOLTYPE_NAME, (int) p_cloned->GetID() ^ 0xffffffff);\r\n\r\n\t\t\t\r\n\t\t\t// trigger script\r\n\t\t\tif (p_cloned->GetFlags() & CPiece::mGAP)\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert(CGapManager::sInstance());\r\n\t\t\t\tpNode->AddComponent(crc_triggerscript, ESYMBOLTYPE_NAME, (int) CGapManager::sInstance()->GetGapTriggerScript(p_cloned));\r\n\t\t\t}\r\n\t\t\telse if (p_cloned->GetSourcePiece()->m_triggerScriptId)\r\n\t\t\t\tpNode->AddComponent(crc_triggerscript, ESYMBOLTYPE_NAME, (int) p_cloned->GetSourcePiece()->m_triggerScriptId);\r\n\t\t\t\r\n\t\t\t(*pNodeNum)++;\r\n\t\t}\r\n\t\tp_piece = p_piece->mp_next_in_list;\r\n\t}\r\n#endif\r\n}\r\n\r\n// Used by the rail editor for snapping to the nearest rail point.\r\nbool CParkGenerator::FindNearestRailPoint(Mth::Vector &pos, Mth::Vector *p_nearest_pos, float *p_dist_squared)\r\n{\r\n\tfloat min_dist_squared=100000000.0f;\r\n\tbool found_point=false;\r\n\tRailString *p_string = m_out_rail_set.GetList();\r\n\t\r\n\twhile (p_string)\r\n\t{\r\n\t\tRailPoint *p_point = p_string->GetList();\r\n\t\t\r\n\t\twhile (p_point)\r\n\t\t{\r\n\t\t\tMth::Vector diff=p_point->m_pos-pos;\r\n\t\t\tfloat dd=diff.LengthSqr();\r\n\t\t\t\r\n\t\t\tif (dd < min_dist_squared)\r\n\t\t\t{\r\n\t\t\t\tmin_dist_squared=dd;\r\n\t\t\t\t\r\n\t\t\t\t*p_nearest_pos=p_point->m_pos;\r\n\t\t\t\t*p_dist_squared=min_dist_squared;\r\n\t\t\t\tfound_point=true;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tp_point = p_point->GetNext();\r\n\t\t}\r\n\t\t\t\r\n\t\tp_string = p_string->GetNext();\r\n\t}\r\n\r\n\treturn found_point;\r\n}\r\n\r\n// called from GenerateNodeInfo()\r\nvoid CParkGenerator::set_up_rail_nodes(Script::CArray *pNodeArray, int *pNodeNum)\r\n{\r\n\r\n\tRyan(\"set_up_rail_nodes: %d/%d\\n\", Mem::CPoolable<Script::CComponent>::SGetNumUsedItems(), Mem::CPoolable<Script::CComponent>::SGetTotalItems());\r\n\r\n#if 1\t\r\n\t\r\n\tconst bool debug_rail_out = false;\r\n\t\r\n\tuint32 crc_angles \t\t\t= Script::GenerateCRC(\"angles\");\r\n\tuint32 crc_name \t\t\t= Script::GenerateCRC(\"name\");\r\n\tuint32 crc_class \t\t\t= Script::GenerateCRC(\"class\");\r\n\tuint32 crc_railnode \t\t= Script::GenerateCRC(\"railnode\");\r\n\tuint32 crc_createdatstart \t= Script::GenerateCRC(\"CreatedAtStart\");\r\n\tuint32 crc_links \t\t\t= Script::GenerateCRC(\"links\");\r\n\t\r\n//\tuint32 crc_type\t\t\t\t= Script::GenerateCRC(\"type\");\r\n//\tuint32 crc_metal\t\t\t= Script::GenerateCRC(\"metal\");\r\n//\tuint32 crc_wood\t\t\t\t= Script::GenerateCRC(\"wood\");\r\n\tuint32 crc_terraintype\t\t= Script::GenerateCRC(\"terraintype\");\r\n//\tuint32 crc_terrain_wood\t\t= Script::GenerateCRC(\"terrain_wood\");\r\n//\tuint32 crc_terrain_metal\t= Script::GenerateCRC(\"terrain_metal\");\r\n\t\r\n\tuint32 crc_trickobject \t\t= Script::GenerateCRC(\"TrickObject\");\r\n\tuint32 crc_cluster \t\t\t= Script::GenerateCRC(\"Cluster\");\r\n\t\r\n\t/*\r\n\tPosition = (-1619.978027,-336.000031,-6870.965332)\r\n\tAngles = (0.000000,-3.141589,0.000000)\r\n\tName = TRG_Conc_Park_Rail0\r\n\tClass = RailNode\r\n\tType = Concrete\r\n\tCreatedAtStart\r\n\tTerrainType = TERRAIN_CONCSMOOTH\r\n\tTrickObject Cluster = ParkingLotSpine1\r\n\tTriggerScript = CanTRG_Conc_Park_Rail0Script\r\n\tLinks=[1]\r\n\t*/\r\n\t\r\n\tint num_points = m_out_rail_set.CountPoints();\r\n\tif (!num_points) return;\r\n\r\n\tRailString *pString = m_out_rail_set.GetList();\r\n\tRailPoint *pPoint = pString->GetList();\r\n\t\r\n\tif (debug_rail_out)\r\n\t\tRyan(\"String %s: \", Script::FindChecksumName(pString->m_id));\t\r\n\tint first_node_in_loop = *pNodeNum;\r\n\t\r\n\t// 10\r\n\tuint32 rail_point_id = vFIRST_ID_FOR_RAILS;\r\n\tint stop_node_num = *pNodeNum + num_points;\r\n\tfor (; *pNodeNum < stop_node_num; (*pNodeNum)++)\r\n\t{\r\n\t\tDbg_Assert(pPoint);\r\n\t\t\r\n\t\tScript::CStruct *pNode = pNodeArray->GetStructure(*pNodeNum);\r\n\t\tpNode->AddComponent(CRCD(0x7f261953,\"pos\"), pPoint->m_pos.GetX(), pPoint->m_pos.GetY(), pPoint->m_pos.GetZ());\r\n//\t\tpNode->AddComponent(CRCD(0xb9d31b0a,\"Position\"), pPoint->m_pos.GetX(), pPoint->m_pos.GetY(), pPoint->m_pos.GetZ());\r\n\t\tif (debug_rail_out)\r\n\t\t\tRyan(\"[%.1f,%.1f,%.1f]\", pPoint->m_pos.GetX(), pPoint->m_pos.GetY(), pPoint->m_pos.GetZ());\r\n\t\tpNode->AddComponent(crc_angles, 0.0f, 0.0f, 0.0f);\r\n\t\tDbg_MsgAssert(rail_point_id < vMAX_ID_FOR_RAILS, (\"out of rail ids\"));\r\n\t\tpNode->AddComponent(crc_name, ESYMBOLTYPE_NAME, (int) rail_point_id++);\r\n\t\tpNode->AddComponent(crc_class, ESYMBOLTYPE_NAME, (int) crc_railnode);\r\n\t\tpNode->AddComponent(NONAME, ESYMBOLTYPE_NAME, (int) crc_createdatstart);\r\n\r\n/*\t\r\n\t\tuint32 type, terrain_type;\r\n\r\n\t\t\r\n\t\tif (pPoint->m_type == RailPoint::vWOOD)\r\n\t\t{\r\n\t\t\ttype = crc_wood;\r\n\t\t\tterrain_type = crc_terrain_wood;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttype = crc_metal;\r\n\t\t\tterrain_type = crc_terrain_metal;\r\n\t\t}\r\n*/\t\t\r\n\r\n// Don't need type?\t\t\r\n//\t\tpNode->AddComponent(crc_type, ESYMBOLTYPE_NAME, (int) type);\r\n\t\t\r\n\t\tpNode->AddComponent(crc_terraintype, ESYMBOLTYPE_NAME, (int) pPoint->m_type);\r\n\t\t\r\n\t\t// Mick: m_objectId will be zero if this rail is not part of a trickob\r\n\t\tif (pPoint->m_objectId)\r\n\t\t{\r\n\t\t\tpNode->AddComponent(NONAME, ESYMBOLTYPE_NAME, (int) crc_trickobject);\r\n\t\t\tpNode->AddComponent(crc_cluster, ESYMBOLTYPE_NAME, (int) pPoint->m_objectId ^ 0xffffffff);\r\n\t\t}\r\n\t\t\r\n\t\tif (pPoint->GetNext() != NULL || pString->m_isLoop)\r\n\t\t{\r\n\t\t\tint link_num = *pNodeNum + 1;\r\n\t\t\tif (pPoint->GetNext() == NULL && pString->m_isLoop)\r\n\t\t\t\tlink_num = first_node_in_loop;\r\n\t\t\t\r\n\t\t\tScript::CArray *pLinks = new Script::CArray();\r\n\t\t\tpLinks->SetSizeAndType(1,ESYMBOLTYPE_INTEGER);\r\n\t\t\tpLinks->SetInteger(0, link_num);\r\n\t\t\tpNode->AddComponent(crc_links, pLinks);\r\n\t\t\tdelete pLinks;\r\n\t\t}\r\n\r\n\t\tpPoint = pPoint->GetNext();\r\n\t\tif (pPoint)\r\n\t\t{\r\n\t\t\tif (debug_rail_out)\r\n\t\t\t\tRyan(\"-\");\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (debug_rail_out)\r\n\t\t\t{\r\n\t\t\t\tif (pString->m_isLoop) Ryan(\" (loop)\");\r\n\t\t\t\tRyan(\"\\n\");\r\n\t\t\t}\r\n\t\t\tpString = pString->GetNext();\r\n\t\t\tif (pString)\r\n\t\t\t{\r\n\t\t\t\tif (debug_rail_out)\r\n\t\t\t\t\tRyan(\"String %s: \", Script::FindChecksumName(pString->m_id));\r\n\t\t\t\tpPoint = pString->GetList();\r\n\t\t\t\tfirst_node_in_loop = *pNodeNum + 1;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n#endif\t\r\n}\r\n\r\n\r\n\r\n\r\n// called from GenerateNodeInfo()\r\nvoid CParkGenerator::set_up_restart_nodes(Script::CArray *pNodeArray, int *pNodeNum)\r\n{\r\n\tuint32 crc_angles \t\t\t= Script::GenerateCRC(\"angles\");\r\n\tuint32 crc_name \t\t\t= Script::GenerateCRC(\"name\");\r\n\tuint32 crc_class \t\t\t= Script::GenerateCRC(\"class\");\r\n\tuint32 crc_type \t\t\t= Script::GenerateCRC(\"type\");\r\n\tuint32 crc_restart \t\t\t= Script::GenerateCRC(\"restart\");\r\n\tuint32 crc_genericnode\t\t= Script::GenerateCRC(\"GenericNode\");\r\n\tuint32 crc_createdatstart \t= Script::GenerateCRC(\"CreatedAtStart\");\r\n\tuint32 crc_restartname \t\t= Script::GenerateCRC(\"RestartName\");\r\n\tuint32 crc_restart_types \t= Script::GenerateCRC(\"restart_types\");\r\n\tuint32 crc_model\t\t \t= Script::GenerateCRC(\"model\");\r\n\tuint32 crc_triggerscript \t= Script::GenerateCRC(\"TriggerScript\");\r\n\t\r\n\tuint32 restart_id = vFIRST_ID_FOR_RESTARTS;\r\n\t\r\n\tfor (int i = 0; i < vNUM_RESTARTS; i++)\r\n\t{\r\n\t\tif (m_restart_tab[i].type != vEMPTY)\r\n\t\t{\r\n\t\t\t//Ryan(\"yo, restart at (%.2f,%.2f,%.2f)\\n\", m_restart_tab[i].pos.GetX(), m_restart_tab[i].pos.GetY(), m_restart_tab[i].pos.GetZ());\r\n\t\t\t\r\n\t\t\t// if restart is ONE_PLAYER or HORSE type, it will also be repeated \r\n\t\t\t// as a multiplayer\r\n\t\t\tint repeat_num = 1;\r\n\t\t\tif (m_restart_tab[i].type == vHORSE)\r\n\t\t\t\trepeat_num = 2;\r\n\t\t\tif (m_restart_tab[i].type == vONE_PLAYER)\r\n\t\t\t\trepeat_num = 2;\t\t\t\t\r\n\r\n\t\t\tfor (int n = 0; n < repeat_num; n++)\r\n\t\t\t{\r\n\t\t\t\t/*\r\n\t\t\t\t{\r\n\t\t\t\t\t// Node 1965\r\n\t\t\t\t\tPosition = (-476.991364,-70.263161,-5703.516602)\r\n\t\t\t\t\tAngles = (0.000000,0.000000,0.000000)\r\n\t\t\t\t\tName = TRG_Crown01\r\n\t\t\t\t\tClass = GenericNode\r\n\t\t\t\t\tType = Crown\r\n\t\t\t\t\tCreatedAtStart\r\n\t\t\t\t}\r\n\t\t\t\t{\r\n\t\t\t\t\t// Node 2912\r\n\t\t\t\t\tPosition = (2940.254639,-1368.771729,-753.127625)\r\n\t\t\t\t\tAngles = (0.000000,2.687807,0.000000)\r\n\t\t\t\t\tName = TRG_CTF_Restart_Red\r\n\t\t\t\t\tClass = Restart\r\n\t\t\t\t\tType = CTF\r\n\t\t\t\t\tCreatedAtStart\r\n\t\t\t\t\tCollisionMode = BoundingBox\r\n\t\t\t\t\tRestartName = \"Team: CTF\"\r\n\t\t\t\t\trestart_types = [ CTF ]\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t*/\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\tint restart_name = restart_id++;\t\t// use generic name for most restarts\r\n\t\t\t\tuint32 type_checksum = 0;\r\n\t\t\t\tif (m_restart_tab[i].type == vONE_PLAYER)\r\n\t\t\t\t{\r\n\t\t\t\t\ttype_checksum = Script::GenerateCRC(\"Player1\");\r\n\t\t\t\t}\r\n\t\t\t\tif (m_restart_tab[i].type == vHORSE)\r\n\t\t\t\t{\r\n\t\t\t\t\ttype_checksum = Script::GenerateCRC(\"Horse\");\r\n\t\t\t\t}\r\n\t\t\t\tif (m_restart_tab[i].type == vMULTIPLAYER || n == 1)\r\n\t\t\t\t{\t\r\n\t\t\t\t\ttype_checksum = Script::GenerateCRC(\"Multiplayer\");\r\n\t\t\t\t}\r\n\t\t\t\tif (m_restart_tab[i].type == vKING_OF_HILL)\r\n\t\t\t\t{\r\n\t\t\t\t\ttype_checksum = Script::GenerateCRC(\"Crown\");\r\n\t\t\t\t}\r\n\t\t\t\tif (\r\n\t\t\t\t\tm_restart_tab[i].type == vRED_FLAG\r\n\t\t\t\t\t|| m_restart_tab[i].type == vGREEN_FLAG\r\n\t\t\t\t\t|| m_restart_tab[i].type == vBLUE_FLAG\r\n\t\t\t\t\t|| m_restart_tab[i].type == vYELLOW_FLAG\r\n\t\t\t\t\t)\r\n\t\t\t\t{\r\n\t\t\t\t\ttype_checksum = Script::GenerateCRC(\"CTF\");\r\n\t\t\t\t\tswitch (m_restart_tab[i].type)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcase vRED_FLAG:\r\n\t\t\t\t\t\t\trestart_name = Script::GenerateCRC(\"TRG_CTF_Restart_Red\");\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase vGREEN_FLAG:\r\n\t\t\t\t\t\t\trestart_name = Script::GenerateCRC(\"TRG_CTF_Restart_Green\");\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase vBLUE_FLAG:\r\n\t\t\t\t\t\t\trestart_name = Script::GenerateCRC(\"TRG_CTF_Restart_Blue\");\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase vYELLOW_FLAG:\r\n\t\t\t\t\t\t\trestart_name = Script::GenerateCRC(\"TRG_CTF_Restart_Yellow\");\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tDbg_MsgAssert(0,(\"Impossible!\"));\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (type_checksum != 0)\r\n\t\t\t\t{\r\n\t\r\n\t\t\t\t\tScript::CScriptStructure *pNode = pNodeArray->GetStructure(*pNodeNum);\r\n\t\t\t\t\tif (m_restart_tab[i].type == vKING_OF_HILL)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpNode->AddComponent(CRCD(0x7f261953,\"pos\"), m_restart_tab[i].pos.GetX(), m_restart_tab[i].pos.GetY() + 50.0f, m_restart_tab[i].pos.GetZ());\r\n//\t\t\t\t\t\tpNode->AddComponent(CRCD(0xb9d31b0a,\"Position\"), m_restart_tab[i].pos.GetX(), m_restart_tab[i].pos.GetY() + 50.0f, -m_restart_tab[i].pos.GetZ());\r\n\t\t\t\t\t\tpNode->AddComponent(crc_class, ESYMBOLTYPE_NAME, (int) crc_genericnode);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpNode->AddComponent(CRCD(0x7f261953,\"pos\"), m_restart_tab[i].pos.GetX(), m_restart_tab[i].pos.GetY() + 50.0f, m_restart_tab[i].pos.GetZ());\r\n//\t\t\t\t\t\tpNode->AddComponent(CRCD(0xb9d31b0a,\"Position\"), m_restart_tab[i].pos.GetX(), m_restart_tab[i].pos.GetY(), -m_restart_tab[i].pos.GetZ());\r\n\t\t\t\t\t\tpNode->AddComponent(crc_class, ESYMBOLTYPE_NAME, (int) crc_restart);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tpNode->AddComponent(crc_angles, 0.0f, Mth::PI * 0.5f * ((float) m_restart_tab[i].dir + 2), 0.0f);\r\n\t\t\t\t\tpNode->AddComponent(crc_name, ESYMBOLTYPE_NAME, (int) restart_name);\r\n\t\t\t\t\tpNode->AddComponent(crc_type, ESYMBOLTYPE_NAME, (int) type_checksum);\r\n\t\t\t\t\tpNode->AddComponent(NONAME, ESYMBOLTYPE_NAME, (int) crc_createdatstart);\r\n\t\t\t\t\tif (m_restart_tab[i].type != vKING_OF_HILL)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tchar *p_name = \"Multi Restart\";\r\n\t\t\t\t\t\tif (n == 0)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tswitch (m_restart_tab[i].type)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tcase vONE_PLAYER:\r\n\t\t\t\t\t\t\t\t\tp_name = \"Player 1 Restart\";\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\tcase vMULTIPLAYER:\r\n\t\t\t\t\t\t\t\t\tp_name = \"Player 2 Restart\";\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\tcase vHORSE:\r\n\t\t\t\t\t\t\t\t\tp_name = \"Horse Restart\";\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\tcase vRED_FLAG:\r\n\t\t\t\t\t\t\t\tcase vGREEN_FLAG:\r\n\t\t\t\t\t\t\t\tcase vBLUE_FLAG:\r\n\t\t\t\t\t\t\t\tcase vYELLOW_FLAG:\r\n\t\t\t\t\t\t\t\t\tp_name = \"Team: CTF\";\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\t\t\t\t\t\t\r\n\t\t\t\t\t\tpNode->AddComponent(crc_restartname, ESYMBOLTYPE_STRING, p_name);\r\n\t\t\t\t\t\r\n\t\t\t\t\t\tScript::CArray *pRestartTypes = new Script::CArray();\r\n\t\t\t\t\t\tpRestartTypes->SetSizeAndType(1, ESYMBOLTYPE_NAME);\r\n\t\t\t\t\t\tpRestartTypes->SetChecksum(0, type_checksum);\r\n\t\t\t\t\t\tpNode->AddComponent(crc_restart_types, pRestartTypes);\r\n\t\t\t\t\t\tdelete pRestartTypes;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t//Script::PrintContents(pNode);\t\t\t\t\t\t\t\t   \r\n\t\t\t\t\t(*pNodeNum)++;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// Flags have the 3 additional nodes for the team flags, bases, CTF flag\r\n\t\t\t\t\r\n\t\t\t\tif (\r\n\t\t\t\t\tm_restart_tab[i].type == vRED_FLAG\r\n\t\t\t\t\t|| m_restart_tab[i].type == vGREEN_FLAG\r\n\t\t\t\t\t|| m_restart_tab[i].type == vBLUE_FLAG\r\n\t\t\t\t\t|| m_restart_tab[i].type == vYELLOW_FLAG\r\n\t\t\t\t\t)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Not a normal restart point, so must be a flag\r\n\t\t\t\t\t// so need to generate the flag, the CTF base and the CTF restart all in the same place\r\n\r\n\t\t\t\t/*\t\t\t\t\t\r\n\t\t\t\t// team flag is like:\r\n\t\t\t\t{\r\n\t\t\t\t\t// Node 2678\r\n\t\t\t\t\tPosition = (864.618835,-408.157806,-3771.989014)\r\n\t\t\t\t\tAngles = (0.000000,2.268928,0.000000)\r\n\t\t\t\t\tName = TRG_Flag_Red\r\n\t\t\t\t\tClass = GameObject\r\n\t\t\t\t\tType = Flag_Red\r\n\t\t\t\t\tModel = \"gameobjects\\flags\\flag_red\\flag_red.mdl\"\r\n\t\t\t\t\tSuspendDistance = 0\r\n\t\t\t\t\tlod_dist1 = 800\r\n\t\t\t\t\tlod_dist2 = 801\r\n\t\t\t\t\tTriggerScript = TRG_Flag_RedScript\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tthen pretty much the same for CTF flags, just a different name\r\n\t\t\t\t\r\n\t\t\t\t{\r\n\t\t\t\t\t// Node 3360\r\n\t\t\t\t\tPosition = (4060.947998,408.885132,1926.812012)\r\n\t\t\t\t\tAngles = (0.000000,0.000000,0.000000)\r\n\t\t\t\t\tName = TRG_CTF_Blue\t\t\t\t\t\t<<<<<<<<<<<<<<   Different name\r\n\t\t\t\t\tClass = GameObject\r\n\t\t\t\t\tType = Flag_Blue\r\n\t\t\t\t\tModel = \"gameobjects\\flags\\flag_blue\\flag_blue.mdl\"\r\n\t\t\t\t\tSuspendDistance = 0\r\n\t\t\t\t\tlod_dist1 = 800\r\n\t\t\t\t\tlod_dist2 = 801\r\n\t\t\t\t\tTriggerScript = TRG_CTF_BlueScript\t\t<<<<<<<<<<<<<<  script can actually stay the same\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tand then the base\r\n\t\t\t\t{\r\n\t\t\t\t\t// Node 3252\r\n\t\t\t\t\tPosition = (-2448.872314,-373.527405,5749.742188)\r\n\t\t\t\t\tAngles = (0.000000,-2.792527,0.000000)\r\n\t\t\t\t\tName = TRG_CTF_Yellow_Base\t\t <<<<<<<<<<<<<<<<<<<<<<<<<<<<  different name\r\n\t\t\t\t\tClass = GameObject\r\n\t\t\t\t\tType = Flag_Yellow_Base\t\t\t   <<<<<<<<<<<<<<<<<<<<<<<<<<<  different type\r\n\t\t\t\t\tModel = \"gameobjects\\flags\\flag_yellow_base\\flag_yellow_base.mdl\"   <<<<<< differnt model\r\n\t\t\t\t\tSuspendDistance = 0\r\n\t\t\t\t\tlod_dist1 = 800\r\n\t\t\t\t\tlod_dist2 = 801\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t<<<<<<<<<<<<<<<  no script\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t\t*/\t\r\n\t\t\t\t\r\n\t\r\n\t\t\t\t\tScript::CScriptStructure *pNode = pNodeArray->GetStructure(*pNodeNum);\r\n\r\n\t\t\t\t\tconst\tchar *color = NULL;\t\t\t\t\t\r\n\t\t\t\t\tif (m_restart_tab[i].type == vRED_FLAG) color = \"red\";\r\n\t\t\t\t\tif (m_restart_tab[i].type == vGREEN_FLAG) color = \"green\";\r\n\t\t\t\t\tif (m_restart_tab[i].type == vBLUE_FLAG) color = \"blue\";\r\n\t\t\t\t\tif (m_restart_tab[i].type == vYELLOW_FLAG) color = \"yellow\";\r\n\r\n\t\t\t\t\tchar name_string[256];\r\n\t\t\t\t\tchar type_string[256];\r\n\t\t\t\t\tchar model_string[256];\r\n\t\t\t\t\tchar triggerscript_string[256];\r\n\t\t\t\t\tsprintf(type_string,\"Flag_%s\",color);\r\n\t\t\t\t\tsprintf(model_string,\"gameobjects\\\\flags\\\\flag_%s\\\\flag_%s.mdl\",color,color);\r\n\t\t\t\t\tsprintf(triggerscript_string,\"TRG_Flag_%sScript_Parked\",color);\r\n\t\t\t\t\t\r\n\t\t\t\t\tsprintf(name_string,\"TRG_Flag_%s\",color);\r\n\t\t\t\t\tpNode->AddComponent(CRCD(0x7f261953,\"pos\"), m_restart_tab[i].pos.GetX(), m_restart_tab[i].pos.GetY(), m_restart_tab[i].pos.GetZ());\r\n//\t\t\t\t\tpNode->AddComponent(CRCD(0xb9d31b0a,\"Position\"), m_restart_tab[i].pos.GetX(), m_restart_tab[i].pos.GetY(), -m_restart_tab[i].pos.GetZ());\r\n\t\t\t\t\tpNode->AddComponent(crc_angles, 0.0f, Mth::PI * 0.5f * ((float) m_restart_tab[i].dir + 2), 0.0f);\r\n\t\t\t\t\tpNode->AddComponent(crc_name, ESYMBOLTYPE_NAME, Script::GenerateCRC(name_string));\r\n\t\t\t\t\tpNode->AddComponent(crc_class, ESYMBOLTYPE_NAME, Script::GenerateCRC(\"GameObject\"));\r\n\t\t\t\t\tpNode->AddComponent(crc_type, ESYMBOLTYPE_NAME, Script::GenerateCRC(type_string));\r\n\t\t\t\t\tpNode->AddComponent(crc_model, ESYMBOLTYPE_STRING, model_string);\r\n\t\t\t\t\tpNode->AddComponent(crc_triggerscript, ESYMBOLTYPE_NAME, Script::GenerateCRC(triggerscript_string));\r\n\r\n\t\t\t\t\tpNode->AddInteger(\"nodeIndex\", *pNodeNum);\r\n\t\t\t\t\tpNode->AddInteger(\"SuspendDistance\", 0);\r\n\t\t\t\t\tpNode->AddInteger(\"lod_dist1\", 800);\r\n\t\t\t\t\tpNode->AddInteger(\"lod_dist2\", 801);\r\n//\t\t\t\t\tScript::PrintContents(pNode);\t\t\t\t\t\t\t\t   \r\n\t\t\t\t\t(*pNodeNum)++;\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t// then repeat exactly for the CTF node, with different name\r\n\t\t\t\t\t\r\n\t\t\t\t\tpNode = pNodeArray->GetStructure(*pNodeNum);\r\n\t\t\t\t\tsprintf(name_string,\"TRG_CTF_%s\",color);\r\n\t\t\t\t\tpNode->AddComponent(CRCD(0x7f261953,\"pos\"), m_restart_tab[i].pos.GetX(), m_restart_tab[i].pos.GetY(), m_restart_tab[i].pos.GetZ());\r\n//\t\t\t\t\tpNode->AddComponent(CRCD(0xb9d31b0a,\"Position\"), m_restart_tab[i].pos.GetX(), m_restart_tab[i].pos.GetY(), -m_restart_tab[i].pos.GetZ());\r\n\t\t\t\t\tpNode->AddComponent(crc_angles, 0.0f, Mth::PI * 0.5f * ((float) m_restart_tab[i].dir + 2), 0.0f);\r\n\t\t\t\t\tpNode->AddComponent(crc_name, ESYMBOLTYPE_NAME, Script::GenerateCRC(name_string));\r\n\t\t\t\t\tpNode->AddComponent(crc_class, ESYMBOLTYPE_NAME, Script::GenerateCRC(\"GameObject\"));\r\n\t\t\t\t\tpNode->AddComponent(crc_type, ESYMBOLTYPE_NAME, Script::GenerateCRC(type_string));\r\n\t\t\t\t\tpNode->AddComponent(crc_model, ESYMBOLTYPE_STRING, model_string);\r\n\t\t\t\t\tpNode->AddComponent(crc_triggerscript, ESYMBOLTYPE_NAME, Script::GenerateCRC(triggerscript_string));\r\n\r\n\t\t\t\t\tpNode->AddInteger(\"nodeIndex\", *pNodeNum);\r\n\t\t\t\t\tpNode->AddInteger(\"SuspendDistance\", 0);\r\n\t\t\t\t\tpNode->AddInteger(\"lod_dist1\", 800);\r\n\t\t\t\t\tpNode->AddInteger(\"lod_dist2\", 801);\r\n//\t\t\t\t\tScript::PrintContents(pNode);\t\t\t\t\t\t\t\t   \r\n\t\t\t\t\t(*pNodeNum)++;\t\t\t\t\r\n\r\n\t\t\t\t\t// different for base (note, no triggerscript)\r\n\t\t\t\t\tpNode = pNodeArray->GetStructure(*pNodeNum);\r\n\t\t\t\t\tsprintf(name_string,\"TRG_CTF_%s_Base\",color);\r\n\t\t\t\t\tsprintf(type_string,\"Flag_%s_Base\",color);\r\n\t\t\t\t\tsprintf(model_string,\"gameobjects\\\\flags\\\\flag_%s_base\\\\flag_%s_base.mdl\",color,color);\r\n\t\t\t\t\t\r\n\t\t\t\t\tpNode->AddComponent(CRCD(0x7f261953,\"pos\"), m_restart_tab[i].pos.GetX(), m_restart_tab[i].pos.GetY(), m_restart_tab[i].pos.GetZ());\r\n//\t\t\t\t\tpNode->AddComponent(CRCD(0xb9d31b0a,\"Position\"), m_restart_tab[i].pos.GetX(), m_restart_tab[i].pos.GetY(), -m_restart_tab[i].pos.GetZ());\r\n\t\t\t\t\tpNode->AddComponent(crc_angles, 0.0f, Mth::PI * 0.5f * ((float) m_restart_tab[i].dir + 2), 0.0f);\r\n\t\t\t\t\tpNode->AddComponent(crc_name, ESYMBOLTYPE_NAME, Script::GenerateCRC(name_string));\r\n\t\t\t\t\tpNode->AddComponent(crc_class, ESYMBOLTYPE_NAME, Script::GenerateCRC(\"GameObject\"));\r\n\t\t\t\t\tpNode->AddComponent(crc_type, ESYMBOLTYPE_NAME, Script::GenerateCRC(type_string));\r\n\t\t\t\t\tpNode->AddComponent(crc_model, ESYMBOLTYPE_STRING, model_string);\r\n\r\n\t\t\t\t\tpNode->AddInteger(\"nodeIndex\", *pNodeNum);\r\n\t\t\t\t\tpNode->AddInteger(\"SuspendDistance\", 0);\r\n\t\t\t\t\tpNode->AddInteger(\"lod_dist1\", 800);\r\n\t\t\t\t\tpNode->AddInteger(\"lod_dist2\", 801);\r\n//\t\t\t\t\tScript::PrintContents(pNode);\t\t\t\t\t\t\t\t   \r\n\t\t\t\t\t(*pNodeNum)++;\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t} // end for n\r\n\t\t} // end if\r\n\t}\r\n\r\n/*\t\r\n\tPosition = (2456.617188,-218.955109,-6663.688477)\r\n\tAngles = (0.741766,-1.570794,-0.000002)\r\n\tName = TRG_Restart_Parking_Lot04\r\n\tClass = Restart\r\n\tType = Player1\r\n\tCreatedAtStart\r\n\tRestartName = \"P1: Restart\"\r\n\trestart_types =\r\n\t[\r\n\tPlayer1\r\n\t]\r\n*/\r\n}\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////\r\n// Restart stuff\r\n\r\n/* \r\n\tShould be called from \r\n\t-CParkManager::RebuildNodeArray() (was in Map::GenerateWorld())\r\n\t-AddMetaPieceToPark::AddMetaPieceToPark() (was in Map::AddPiece())\r\n*/\r\n// Add a restart point if space\r\n// Non-automatic restart points will overwrite automatic restart points\r\n// (but not if they find an empty slot first)\r\nbool CParkGenerator::AddRestart(Mth::Vector &pos, int dir, GridDims &dims, RestartType type, bool automatic, bool auto_copy)\r\n{\r\n\tint first_slot = 0, last_slot = 0;\r\n\tget_restart_slots(type, &first_slot, &last_slot);\r\n\r\n\tMth::Vector\tuse_pos = pos;\r\n\tGridDims use_dims = dims;\r\n\r\n\t// When \"auto_copy\" is set\r\n\t// If this is an automatic point, then copy the position\r\n\t// from the last non-automatic point we find\r\n\tif (automatic && auto_copy)\r\n\t{\r\n\t\tfor (int i = first_slot; i <= last_slot; i++)\r\n\t\t{\r\n\t\t\tif (m_restart_tab[i].type == type && !m_restart_tab[i].automatic)\r\n\t\t\t{\r\n\t\t\t\tuse_pos = m_restart_tab[i].pos;\t\t\t\t\r\n\t\t\t\tuse_dims = m_restart_tab[i].dims;\t\t\t\t\r\n\t\t\t\t#ifdef\tDEBUG_RESTARTS\r\n\t\t\t\tprintf (\"%d: restart copying position from slot %d\",__LINE__,i);\r\n\t\t\t\t#endif\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t\r\n\t\r\n\tfor (int i = first_slot; i <= last_slot; i++)\r\n\t{\r\n\t\t\r\n\t\t// add the restart to any empty slot, or overwrite an \"automatic\" slot if this is not automatic \r\n\t\tif (m_restart_tab[i].type == vEMPTY || (m_restart_tab[i].automatic && !automatic))\t\t\r\n\t\t{\r\n\t\t\tm_restart_tab[i].pos = use_pos;\r\n\t\t\tm_restart_tab[i].dir = dir;\r\n\t\t\tm_restart_tab[i].dims = use_dims;\r\n\t\t\tm_restart_tab[i].type = type;\r\n\t\t\tm_restart_tab[i].automatic = automatic;\r\n\t\t\t#ifdef\tDEBUG_RESTARTS\r\n\t\t\tprintf (\"%d: restart (%.2f,%.2f,%.2f) set in slot %d  (type = %d, auto = %d\\n)\",__LINE__,use_pos[X],use_pos[Y],use_pos[Z],i,type,automatic);\r\n\t\t\t#endif\r\n\t\t\treturn true;\r\n\t\t}\t\t\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n\r\nint CParkGenerator::NumRestartsOfType(RestartType type)\r\n{\r\n\tint first_slot = 0, last_slot = 0;\r\n\tget_restart_slots(type, &first_slot, &last_slot);\r\n\r\n\tint got = 0;\t\t\t\t\t\t\t\t\t// count of number of actual restarts\r\n\tfor (int i = first_slot; i <= last_slot; i++)\r\n\t{\r\n\t\tif (m_restart_tab[i].type != vEMPTY)\t\t// got some kind of restart\r\n\t\t{\r\n\t\t\t\tgot++; \t\t\t\t\t\t\t\t// counting an actual restart\r\n\t\t}\r\n\t}\r\n\treturn got;\r\n}\r\n\r\n\r\n// should be called from CParkManager::RebuildNodeArray() (was in Map::GenerateWorld())\r\n// returns true if there are not enough restart points (ie, true if we need more)\r\n// Note:  we include \"automatic\" restart points now.\r\nbool CParkGenerator::NotEnoughRestartsOfType(RestartType type, int need)\r\n{\r\n\treturn NumRestartsOfType(type) < need;\t\t  // if got less than we need, return true, (we need more)\r\n}\r\n\r\n\r\nMth::Vector\t CParkGenerator::GetRestartPos(RestartType type, int index)\r\n{\r\n\r\n\tint first_slot = 0, last_slot = 0;\r\n\tget_restart_slots(type, &first_slot, &last_slot);\r\n\r\n\tfor (int i = first_slot; i <= last_slot; i++)\r\n\t{\r\n\t\tif (m_restart_tab[i].type != vEMPTY)\t\t// got some kind of restart\r\n\t\t{\r\n\t\t\tindex--;\t\t\t\t\t\t\t\t\r\n\t\t\tif (index < 0)\r\n\t\t\t{\r\n\t\t\t\treturn m_restart_tab[i].pos;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tDbg_MsgAssert(0,(\"could not find restart pos\"));\t\r\n\treturn Mth::Vector(0,0,0);\r\n\r\n}\r\n\r\nGridDims\t CParkGenerator::GetRestartDims(RestartType type, int index)\r\n{\r\n\r\n\tint first_slot = 0, last_slot = 0;\r\n\tget_restart_slots(type, &first_slot, &last_slot);\r\n\r\n\tfor (int i = first_slot; i <= last_slot; i++)\r\n\t{\r\n\t\tif (m_restart_tab[i].type != vEMPTY)\t\t// got some kind of restart\r\n\t\t{\r\n\t\t\tindex--;\t\t\t\t\t\t\t\t\r\n\t\t\tif (index < 0)\r\n\t\t\t{\r\n\t\t\t\treturn m_restart_tab[i].dims;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tDbg_MsgAssert(0,(\"could not find restart dims\"));\t\r\n\treturn\tGridDims();\r\n\r\n}\r\n\r\n\r\n\r\n// called by various restart functions in this class\r\nvoid CParkGenerator::get_restart_slots(RestartType type, int *pFirstSlot, int *pLastSlot)\r\n{\r\n\tswitch (type)\r\n\t{\r\n\t\tcase vONE_PLAYER:\r\n\t\t\t*pFirstSlot = 1;\r\n\t\t\t*pLastSlot = 1;\r\n\t\t\tbreak;\r\n\t\tcase vMULTIPLAYER:\r\n\t\t\t*pFirstSlot = 0;\r\n\t\t\t*pLastSlot = 0;\r\n\t\t\tbreak;\r\n\t\tcase vHORSE:\r\n\t\t\t*pFirstSlot = 2;\r\n\t\t\t*pLastSlot = 7;\r\n\t\t\tbreak;\r\n\t\tcase vKING_OF_HILL:\r\n\t\t\t*pFirstSlot = 8;\r\n\t\t\t*pLastSlot = 13;\r\n\t\t\tbreak;\r\n\t\tcase vRED_FLAG:\t\r\n\t\t\t*pFirstSlot = 14;\r\n\t\t\t*pLastSlot = 14;\r\n\t\t\tbreak;\r\n\t\tcase vGREEN_FLAG:\t\r\n\t\t\t*pFirstSlot = 15;\r\n\t\t\t*pLastSlot = 15;\r\n\t\t\tbreak;\r\n\t\tcase vBLUE_FLAG:\t\r\n\t\t\t*pFirstSlot = 16;\r\n\t\t\t*pLastSlot = 16;\r\n\t\t\tbreak;\r\n\t\tcase vYELLOW_FLAG:\t\r\n\t\t\t*pFirstSlot = 17;\r\n\t\t\t*pLastSlot = 17;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Unhandled restart type %d\",type));\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n// should be called by CParkManager::DestroyConcreteMeta() (was Map::RemovePiece())\r\nvoid CParkGenerator::RemoveRestart(const GridDims &dims, RestartType type)\r\n{\r\n\tint first_slot = 0, last_slot = 0;\r\n\tget_restart_slots(type, &first_slot, &last_slot);\r\n\t\r\n\tfor (int i = first_slot; i <= last_slot; i++)\r\n\t{\r\n//\t\tif (m_restart_tab[i].area.x == area.x &&\r\n//\t\t\tm_restart_tab[i].area.y == area.y &&\r\n//\t\t\tm_restart_tab[i].area.z == area.z)\r\n\t\tif (\r\n\t\t\tm_restart_tab[i].dims.GetX() == dims.GetX()\r\n\t\t\t&& m_restart_tab[i].dims.GetY() == dims.GetY()\r\n\t\t\t&& m_restart_tab[i].dims.GetZ() == dims.GetZ()\r\n\t\t\t)\r\n\t\t{\r\n\t\t\tm_restart_tab[i].type = vEMPTY;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n// should be called from CCursor::AttemptStamp() (was Cursor::AttemptPlacePiece())\r\nbool CParkGenerator::FreeRestartExists(RestartType type)\r\n{\r\n\tint first_slot = 0, last_slot = 0;\r\n\tget_restart_slots(type, &first_slot, &last_slot);\r\n\t\r\n\tfor (int i = first_slot; i <= last_slot; i++)\r\n\t\tif (m_restart_tab[i].type == vEMPTY || m_restart_tab[i].automatic)\r\n\t\t{\r\n//\t\t\tm_restart_tab[i].type = vEMPTY;\r\n\t\t\treturn true;\r\n\t\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n\r\n/* \r\n\tshould be called from:\r\n\t-CParkGenerator::InitializeMasterPieces() (was World::CreateParkHeap())\r\n\t-CParkGenerator::DestroyAllPieces() or CParkManager::destroy_concrete_metapieces() (was World::DestroyAllPieces())\r\n*/\r\nvoid CParkGenerator::KillRestarts()\r\n{\r\n\t#ifdef\tDEBUG_RESTARTS\r\n\tprintf (\"%d: KillRestarts called, all restarts set to vEMPTY\",__LINE__);\r\n\t#endif\r\n\r\n\tfor (int i = 0; i < vNUM_RESTARTS; i++)\r\n\t\tm_restart_tab[i].type = vEMPTY;\r\n}\r\n\r\n\r\nvoid CParkGenerator::ClearAutomaticRestarts()\r\n{\r\n\r\n\t#ifdef\tDEBUG_RESTARTS\r\n\tprintf (\"%d: ClearAutomaticRestarts called, all automatic restarts set to vEMPTY\",__LINE__);\r\n\t#endif\r\n\t\r\n\tfor (int i = 0; i < vNUM_RESTARTS; i++)\r\n\t{\r\n\t\tif (m_restart_tab[i].automatic)\r\n\t\t{\r\n\t\t\tm_restart_tab[i].type = vEMPTY;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n\tLeft edge of gap is at position pos. Bottom edge sticks out in direction\r\n\tindicated by rot, for length units.\r\n*/\r\nCClonedPiece *CParkGenerator::CreateGapPiece(Mth::Vector &pos, float length, int rot)\r\n{\r\n\t// maken der gapen piece\r\n\tCClonedPiece *p_gap_piece = ClonePiece(GetMasterPiece(Script::GenerateCRC(\"Sk4Ed_Gap_10x10\"), true), CPiece::mNO_FLAGS);\r\n\tp_gap_piece->SetDesiredPos(pos, CClonedPiece::CHANGE_SECTOR);\r\n\tp_gap_piece->SetDesiredRot(Mth::ERot90(rot), CClonedPiece::CHANGE_SECTOR);\r\n\tp_gap_piece->set_flag(CPiece::mGAP);\r\n\tAddClonedPieceToWorld(p_gap_piece);\r\n\t// XXX\r\n\tRyan(\"@@@ made gap piece 0x%x\\n\", p_gap_piece);\r\n\treturn p_gap_piece;\r\n}\r\n\r\n\r\n\r\n\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/ParkEditor2/ParkGen.h",
    "content": "#ifndef __SK_PARKEDITOR2_PARKGEN_H\r\n#define __SK_PARKEDITOR2_PARKGEN_H\r\n\r\n#include <core/math/vector.h>\r\n#include <sk/parkeditor/edrail.h>\r\n\r\n#define DEBUG_THIS_DAMN_THING 0\r\n\r\n#if defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ )\r\n\tinline void ParkEd(const char* A ...) {};\r\n#else\r\n\r\n\t#if DEBUG_THIS_DAMN_THING\r\n\t\t#define ParkEd(A...)  printf(\"PARKED: \"); printf(##A); printf(\"\\n\") \t\t\r\n\t#else\r\n\t\t#define ParkEd(A...)\r\n\t#endif\r\n#endif\r\n\r\nnamespace Image\r\n{\r\n\tstruct RGBA;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\tclass CScene;\r\n\tclass CSector;\r\n}\r\n\r\nnamespace Script\r\n{\r\n\tclass\tCArray;\r\n}\r\n\r\nnamespace Ed\r\n{\r\n\r\n\tclass CSourcePiece;\r\n\tclass CClonedPiece;\r\n\tclass CMapListNode;\r\n\r\nstruct MapArea\t\t \t// Mick - OLD\r\n{\r\n\tint x, y, z;\r\n\tint w, h, l;\r\n};\r\n\r\n\r\nenum\r\n{\r\n\tH = 4,\r\n\tL = 5\r\n};\r\n\r\n\r\n\r\n\r\n/*\r\n\tDescribes a 3D box in cell coordinates. Sometimes only the position part or only the area part is used.\r\n*/\r\nclass GridDims\r\n{\r\npublic:\r\n\t\t\t\t\t\t\t\tGridDims(uint8 x = 0, sint8 y = 0, uint8 z = 0, uint8 w = 0, uint8 h = 0, uint8 l = 0);\r\n\r\n\tvoid\t\t\t\t\t\tSetXYZ(uint8 x, sint8 y, uint8 z) {m_dims[0] = x; m_dims[1] = (uint8) y; m_dims[2] = z;}\r\n\tvoid\t\t\t\t\t\tSetWHL(uint8 w, uint8 h, uint8 l) {m_dims[3] = w; m_dims[4] = h; m_dims[5] = l;}\r\n\r\n\tuint8 &\t\t\t\t\t\toperator[](sint i);\r\n\t\r\n\tuint8\t\t\t\t\t\tGetX() const {return m_dims[0];}\r\n\tsint8\t\t\t\t\t\tGetY() const {return (sint8) m_dims[1];}\r\n\tuint8\t\t\t\t\t\tGetZ() const {return m_dims[2];}\r\n\tuint8\t\t\t\t\t\tGetW() const {return m_dims[3];}\r\n\tuint8\t\t\t\t\t\tGetH() const {return m_dims[4];}\r\n\tuint8\t\t\t\t\t\tGetL() const {return m_dims[5];}\r\n\r\n\tvoid\t\t\t\t\t\tMakeInfinitelyHigh();\r\n\tvoid\t\t\t\t\t\tMakeInfiniteOnY();\r\n\r\n\tvoid\t\t\t\t\t\tPrintContents() const;\r\n\r\nprivate:\r\n\r\n\tuint8\t\t\t\t\t\tm_dims[6];\r\n};\r\n\r\n\r\n/*\r\n\tRoles of CPiece:\r\n\t-wraps object placed in park\r\n\t-wraps fluid object contained in world (cursor)\r\n\t\r\n\tClass hierarchy:\r\n\t-CPiece\r\n\t\t-CSourcePiece (dims)\r\n\t\t-CClonedPiece (pos, rot, pointer to master)\r\n\t\t\r\n\tRotations:\t\t\t\t  \r\n\t-Hard: underlying verts are flipped around directly, stored dims changed to match\r\n\t-Soft: matrix sent down directly, not stored with piece\r\n\t\r\n\tRelationship with metapiece:\r\n\t-pieces contained by metapiece must be of the same type, all hard pieces or all soft pieces\r\n*/\r\nclass CPiece\r\n{\r\n\tfriend class CParkGenerator;\r\n\tfriend class CMetaPiece;\r\n\tfriend class CConcreteMetaPiece;\r\n\r\npublic:\r\n\r\n\tenum EFlags\r\n\t{\r\n\t\tmNO_FLAGS =\t\t\t\t\t0,\r\n\r\n\t\t// only one of following can be set\r\n\t\tmSOURCE_PIECE =\t\t\t\t(1<<0),\r\n\t\tmCLONED_PIECE =\t\t\t\t(1<<1),\r\n\t\t\r\n\t\t// Applied to a cloned piece. Set if an animated piece, like part of cursor\r\n\t\tmSOFT_PIECE =\t\t\t\t(1<<2),\r\n\t\t\r\n\t\t// set if piece is being displayed\r\n\t\tmIN_WORLD =\t\t\t\t\t(1<<3),\r\n\r\n\t\tmSHELL = \t\t\t\t\t(1<<4),\r\n\t\tmFLOOR = \t\t\t\t\t(1<<5),\r\n\t\tmGAP = \t\t\t\t\t\t(1<<6),\r\n\t\tmRESTART =\t\t\t\t\t(1<<7),\r\n\t\tmNO_RAILS =\t\t\t\t\t(1<<8),\r\n\t};\r\n\r\n\tEFlags\t\t\t\t\t\t\tGetFlags() {return m_flags;}\r\n\tvirtual Mth::Vector\t\t\t\tGetDims() = 0;\r\n\tvoid\t\t\t\t\t\t\tGetCellDims(GridDims *pDims);\r\n\r\n\tCSourcePiece *\t\t\t\t\tCastToCSourcePiece();\r\n\tCClonedPiece *\t\t\t\t\tCastToCClonedPiece();\r\n\r\n\tMth::Vector\t\t\t\t\t\tGetDimsWithRot(Mth::ERot90 rot);\r\n\r\nprotected:\r\n\r\n\t/*\r\n\t\tHard rotation: flipping of verts\r\n\t\t\r\n\t\tSoft: rotation of underlying piece, matrix is set for CSector directly.\r\n\t*/\t\t\t\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\t\t\tCPiece();\r\n\tvirtual\t\t\t\t\t\t\t~CPiece();\r\n\r\n\tvoid\t\t\t\t\t\t\tset_flag(EFlags flag) {m_flags = EFlags(m_flags | flag);}\r\n\tvoid\t\t\t\t\t\t\tclear_flag(EFlags flag) {m_flags = EFlags(m_flags & ~flag);}\r\n\r\n\tunion\r\n\t{\r\n\t\tuint32\t\t\t\t\t\tm_sector_checksum;\t\t// probably will refer to CSectors this way\r\n\t\t// \t\t\t\t\t\t\tmp_other_thing // for soft pieces\r\n\t};\r\n\r\n\tEFlags\t\t\t\t\t\t\tm_flags;\r\n\r\n\tCPiece *\t\t\t\t\t\tmp_next_in_list;\r\n\t//CPiece *\t\t\t\t\t\tmp_next_in_metapiece;\r\n};\r\n\r\n\r\n\r\n\r\nclass CSourcePiece : public CPiece\r\n{\r\n\tfriend class CParkGenerator;\r\n\tfriend class CMetaPiece;\r\n\tfriend class CClonedPiece;\r\n\r\npublic:\r\n\t/*\r\n\t\tpieces in different domains can coexist at same GRID coordinates\r\n\t*/\r\n\tenum EDomain\r\n\t{\r\n\t\tmREGULAR\t\t\t\t= (1<<0),\r\n\t\tmOFFSET_RAIL\t\t\t= (1<<1),\r\n\t\tmGAP\t\t\t\t\t= (1<<2),\r\n\t};\r\n\r\n\tuint32\t\t\t\t\t\t\tGetType();\r\n\tMth::Vector\t\t\t\t\t\tGetDims() {return m_dims;}\r\n\r\nprotected:\r\n\t\t\t\t\t\t\t\t\tCSourcePiece();\r\n\t\t\t\t\t\t\t\t\t~CSourcePiece();\r\n\r\n\tMth::Vector\t\t\t\t\t\tm_dims;\r\n\tEDomain\t\t\t\t\t\t\tm_domain;\t\r\n\tuint32\t\t\t\t\t\t\tm_triggerScriptId;  // Checksum of trigger script associated with this node (for stuff like chainlink fence SFX)\r\n\r\n\tint\t\t\t\t\t\t\t\tm_num_rail_points;\r\n\tint\t\t\t\t\t\t\t\tm_num_linked_rail_points;\r\n};\r\n\r\n\r\n\r\n\r\nclass CClonedPiece : public CPiece\r\n{\r\n\tfriend class CParkGenerator;\r\n\tfriend class CMetaPiece;\r\n\tfriend class CConcreteMetaPiece;\r\n\r\npublic:\r\n\tuint32\t\t\t\t\t\t\tGetID();\r\n\t\r\n\tenum ESectorEffect\r\n\t{\r\n\t\tMARKER_ONLY,\r\n\t\tCHANGE_SECTOR,\r\n\t};\r\n\tvoid\t\t\t\t\t\t\tSetDesiredPos(const Mth::Vector& pos, ESectorEffect sectorEffect);\r\n\tvoid\t\t\t\t\t\t\tSetDesiredRot(Mth::ERot90 rot, ESectorEffect sectorEffect);\r\n\tvoid\t\t\t\t\t\t\tSetSoftRot(float rot); // in degrees\r\n\tvoid\t\t\t\t\t\t\tSetScaleX(float scaleX);\r\n\tvoid\t\t\t\t\t\t\tHighlight(bool on, bool makePurple = false);\r\n\tvoid\t\t\t\t\t\t\tSetActive(bool active);\r\n\tvoid\t\t\t\t\t\t\tSetVisibility(bool visible);\r\n\tCSourcePiece *\t\t\t\t\tGetSourcePiece() {return mp_source_piece;}\r\n\tMth::Vector\t\t\t\t\t\tGetPos() {return m_pos;}\r\n\tMth::ERot90\t\t\t\t\t\tGetRot() {return m_rot;}\r\n\tMth::Vector\t\t\t\t\t\tGetDims();\r\n\tuint32\t\t\t\t\t\t\tGetType() {return mp_source_piece->GetType();}\r\n\r\nprotected:\r\n\t\t\t\t\t\t\t\t\tCClonedPiece();\r\n\r\n\tuint32\t\t\t\t\t\t\tm_id;\r\n\tCSourcePiece *\t\t\t\t\tmp_source_piece;\r\n\r\n\tMth::Vector\t\t\t\t\t\tm_pos; // center, bottom\r\n\tMth::ERot90\t\t\t\t\t\tm_rot; // in units of 90 degrees, CCW\r\n};\r\n\r\n\r\n\r\n\r\nclass CParkGenerator\r\n{\r\n\r\npublic:\r\n\r\n\tstatic const float \t\t\tCELL_WIDTH;\r\n\tstatic const float \t\t\tCELL_HEIGHT;\r\n\tstatic const float \t\t\tCELL_LENGTH;\r\n\r\n\r\n\tstatic const uint32\t\t\t\tvFIRST_ID_FOR_OBJECTS;\r\n\tstatic const uint32\t\t\t\tvMAX_ID_FOR_OBJECTS;\r\n\tstatic const uint32\t\t\t\tvFIRST_ID_FOR_RAILS;\r\n\tstatic const uint32\t\t\t\tvMAX_ID_FOR_RAILS;\r\n\tstatic const uint32\t\t\t\tvFIRST_ID_FOR_CREATED_RAILS;\r\n\tstatic const uint32\t\t\t\tvMAX_ID_FOR_CREATED_RAILS;\r\n\tstatic const uint32\t\t\t\tvFIRST_ID_FOR_RESTARTS;\r\n\r\n\t\r\n\tenum EDestroyType\r\n\t{\r\n\t\tDESTROY_PIECES_AND_SECTORS,\r\n\t\tDESTROY_ONLY_PIECES,\r\n\t};\r\n\r\n\tenum RestartType\r\n\t{\r\n\t\tvEMPTY,\r\n\t\tvONE_PLAYER,\r\n\t\tvMULTIPLAYER,\r\n\t\tvHORSE,\r\n\t\tvKING_OF_HILL,\r\n\t\tvRED_FLAG,\r\n\t\tvGREEN_FLAG,\r\n\t\tvBLUE_FLAG,\r\n\t\tvYELLOW_FLAG,\r\n\t\t\r\n\t\t\r\n\t\tvNUM_RESTART_TYPES,\r\n\t};\r\n\r\n\r\n\t\t\t\t\t\t\t\t\tCParkGenerator();\r\n\t\t\t\t\t\t\t\t\t~CParkGenerator();\r\n\r\n\tint\t\t\t\t\t\t\t\tGetResourceSize(char *name);\r\n\tMem::Heap *\t\t\t\t\t\tGetParkEditorHeap();\r\n\t\r\n\tstruct MemUsageInfo\r\n\t{\r\n\t\tint\t\t\t\t\t\t\tmParkHeapUsed;\r\n\t\tint\t\t\t\t\t\t\tmParkHeapFree; // after padding is deducted\r\n\t\tint\t\t\t\t\t\t\tmMainHeapUsed;\r\n\t\tint\t\t\t\t\t\t\tmMainHeapFree; // after padding is deducted\r\n\t\t\r\n\t\tint\t\t\t\t\t\t\tmLastMainUsed;\r\n\t\tbool\t\t\t\t\t\tmIsFragmented;\r\n\r\n\t\tint\t\t\t\t\t\t\tmTotalRailPoints;\r\n\t\tint\t\t\t\t\t\t\tmTotalLinkedRailPoints;\r\n\t\tint\t\t\t\t\t\t\tmTotalClonedPieces;\r\n\t};\r\n\tMemUsageInfo\t\t\t\t\tGetResourceUsageInfo(bool printInfo = false);\r\n\tvoid\t\t\t\t\t\t\tSetMaxPlayers(int maxPlayers);\r\n\tint \t\t\t\t\t\t\tGetMaxPlayers() {return m_max_players;}\r\n\tint \t\t\t\t\t\t\tGetMaxPlayersPossible();\r\n\t\t\r\n\tCSourcePiece *\t\t\t\t\tGetMasterPiece(uint32 pieceType, bool assert = false);\r\n\tCSourcePiece *\t\t\t\t\tGetNextMasterPiece(CSourcePiece *pLast);\r\n\tCClonedPiece *\t\t\t\t\tClonePiece(CPiece *pMasterPiece, CPiece::EFlags flags);\r\n\tvoid\t\t\t\t\t\t\tAddClonedPieceToWorld(CClonedPiece *pPiece);\r\n\tvoid\t\t\t\t\t\t\tDestroyClonedPiece(CClonedPiece *pPiece);\r\n\r\n\r\n\tvoid\t\t\t\t\t\t\tInitializeMasterPieces(int parkW, int parkH, int parkL, int theme);\r\n\t\r\n\t// K: Added to allow cleanup of the park editor heap during play\r\n\t//void\t\t\t\t\t\t\tDeleteSourceAndClonedPieces();\r\n\t//void\t\t\t\t\t\t\tDeleteParkEditorHeap();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tUnloadMasterPieces();\r\n\t\r\n\tvoid\t\t\t\t\t\t\tPostGenerate();\r\n\tvoid\t\t\t\t\t\t\tGenerateCollisionInfo(bool assert = true);\r\n\tvoid \t\t\t\t\t\t\tRemoveOuterShellPieces(int theme);\r\n\tvoid\t\t\t\t\t\t\tGenerateNodeInfo(CMapListNode * p_concrete_metapiece_list);\r\n\tvoid \t\t\t\t\t\t\tReadInRailInfo();\r\n\tvoid\t\t\t\t\t\t\tDestroyRailInfo();\r\n\r\n\tvoid\t\t\t\t\t\t\tHighlightAllPieces(bool highlight);\r\n\tvoid\t\t\t\t\t\t\tSetGapPiecesVisible(bool visible);\r\n\tvoid\t\t\t\t\t\t\tSetRestartPiecesVisible(bool visible);\r\n\r\n\r\n\tvoid \t\t\t\t\t\t\tSetLightProps(int num_lights, \r\n\t\t\t\t\t\t\t\t\t\t\t\t  float amb_const_r, float amb_const_g, float amb_const_b, \r\n\t\t\t\t\t\t\t\t\t\t\t\t  float falloff_const_r, float falloff_const_g, float falloff_const_b,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  float cursor_ambience);\r\n\tvoid \t\t\t\t\t\t\tSetLight(Mth::Vector &light_pos, int light_num);\r\n\tvoid \t\t\t\t\t\t\tCalculateLighting(CClonedPiece *p_piece);\r\n\tvoid \t\t\t\t\t\t\tCalculateVertexLighting(const Mth::Vector & vert, Image::RGBA & color);\r\n\t\r\n\t\r\n\tvoid\t\t\t\t\t\t\tDestroyAllClonedPieces(EDestroyType type);\r\n\r\n\r\n\tint\t\t\t\t\t\t\t\tNumRestartsOfType(RestartType type);\r\n\tbool\t\t\t\t\t\t\tNotEnoughRestartsOfType(RestartType type, int need);\r\n\tMth::Vector\t \t\t\t\t\tGetRestartPos(RestartType type, int index);\r\n\tGridDims\t \t\t\t\t\tGetRestartDims(RestartType type, int index);\r\n\tbool\t\t\t\t\t\t\tAddRestart(Mth::Vector &pos, int dir, GridDims &dims, RestartType type, bool automatic, bool auto_copy=false);\r\n\tvoid\t\t\t\t\t\t\tRemoveRestart(const GridDims &dims, RestartType type);\r\n\tbool \t\t\t\t\t\t\tFreeRestartExists(RestartType type);\r\n\tvoid\t\t\t\t\t\t\tKillRestarts();\t\r\n\tvoid\t\t\t\t\t\t\tClearAutomaticRestarts();\r\n\r\n\t\r\n\tCClonedPiece *\t\t\t\t\tCreateGapPiece(Mth::Vector &pos, float length, int rot);\r\n\r\n\tNx::CScene *\t\t\t\t\tGetClonedScene() {return mp_cloned_scene;}\r\n\r\n\tvoid\t\t\t\t\t\t\tCleanUpOutRailSet();\r\n\tvoid\t\t\t\t\t\t\tGenerateOutRailSet(CMapListNode * p_concrete_metapiece_list);\r\n\tbool\t\t\t\t\t\t\tFindNearestRailPoint(Mth::Vector &pos, Mth::Vector *p_nearest_pos, float *p_dist_squared);\r\n\t\r\nprivate:\r\n\r\n\tenum EFlags\r\n\t{\r\n\t\tmMASTER_STUFF_LOADED\t\t= (1<<1),\r\n\t\tmSECTORS_GENERATED\t\t\t= (1<<2),\r\n\t\tmPIECES_IN_WORLD\t\t\t= (1<<3),\r\n\t\tmCOLLISION_INFO_GENERATED\t= (1<<4),\r\n\t\tmNODE_INFO_GENERATED\t\t= (1<<5),\r\n\t\t// set when we destroy a piece\r\n\t\tmSECTOR_MEMORY_NEEDS_FREE\t= (1<<6),\r\n\t};\r\n\r\n\tvoid \t\t\t\t\t\t\tdestroy_piece_impl(CClonedPiece *pPiece, EDestroyType destroyType);\r\n\tbool\t\t\t\t\t\t\tflag_on(EFlags flag) {return ((m_flags & flag) != 0);}\r\n\tvoid\t\t\t\t\t\t\tset_flag(EFlags flag) {m_flags = EFlags(m_flags | flag);}\r\n\tvoid\t\t\t\t\t\t\tclear_flag(EFlags flag) {m_flags = EFlags(m_flags & ~flag);}\r\n\t\r\n\tuint32 \t\t\t\t\t\t\tscan_for_cluster(Script::CArray *pNodeArray, int &index);\r\n\tint \t\t\t\t\t\t\tscan_for_rail_node(Script::CArray *pNodeArray, uint32 cluster, int link, Mth::Vector *pVector, bool *pHasLinks, RailPoint::RailType *pType);\r\n\tvoid\t\t\t\t\t\t\tscan_in_trigger_info(Script::CArray *pNodeArray);\r\n\tvoid \t\t\t\t\t\t\tset_up_object_nodes(Script::CArray *pNodeArray, int *pNodeNum);\r\n\tvoid\t\t\t\t\t\t\tset_up_rail_nodes(Script::CArray *pNodeArray, int *pNodeNum);\r\n\tvoid\t\t\t\t\t\t\tset_up_restart_nodes(Script::CArray *pNodeArray, int *pNodeNum);\r\n\r\n\t\r\n\t/*\r\n\tThings\r\n\t\r\n\t\t-loading master geometry, loading master rails (one operation)\r\n\t\t-generating world from compressed map\r\n\t\t-collision setup\r\n\t\t-rail setup\r\n\t\t-cleanup world (maybe just destroys pieces)\r\n\t*/\r\n\t\r\n\tEFlags\t\t\t\t\t\t\tm_flags;\r\n\r\n\tCPiece *\t\t\t\t\t\tmp_cloned_piece_list;\r\n\tCPiece *\t\t\t\t\t\tmp_source_piece_list;\r\n\tint\t\t\t\t\t\t\t\tm_num_cloned_pieces;\r\n\tint\t\t\t\t\t\t\t\tm_num_source_pieces;\r\n\r\n\tNx::CScene *\t\t\t\t\tmp_source_scene;\t\t\t\t// Scene used as a manager of pieces\r\n\tNx::CScene *\t\t\t\t\tmp_cloned_scene;\r\n\r\n\tuint32\t\t\t\t\t\t\tm_next_id;\r\n\t\r\n\tMem::Region*\t\t\t\t\tmp_mem_region;\r\n\tMem::Heap*\t\t\t\t\t\tmp_mem_heap;\r\n\r\n\tint\t\t\t\t\t\t\t\tm_max_players;\r\n\t\t\r\n//////////////////////////////////////////////////////////////////////////\r\n// rail and node stuff patched in by Mick\r\n\r\n\tRailSet\t\t\t\t\t\t\tm_in_rail_set;\r\n\tRailSet\t\t\t\t\t\t\tm_out_rail_set;\r\n\t// in world, at editing time\r\n\tint\t\t\t\t\t\t\t\tm_total_rail_points;\r\n\tint\t\t\t\t\t\t\t\tm_total_rail_linked_points;\r\n\r\n\tstruct TempNodeInfo\r\n\t{\r\n\t\tuint32\t\t\t\t\t\tclassCrc;\r\n\t\tuint32\t\t\t\t\t\tcluster;\r\n\t\tScript::CArray *\t\t\tpLinkArray;\r\n\t};\r\n\r\n\tTempNodeInfo *\t\t\t\t\tm_temp_node_tab;\r\n\tint\t*\t\t\t\t\t\t\tm_processed_node_tab;\r\n\tint\t\t\t\t\t\t\t\tm_processed_node_tab_entries;\r\n\r\n\t/*\r\n\t\tRestart stuff\r\n\t*/\r\n\r\n\r\n\r\n\tvoid \t\t\t\tget_restart_slots(RestartType type, int *pFirstSlot, int *pLastSlot);\r\n\r\n\r\n\tstruct RestartInfo\r\n\t{\r\n\t\tMth::Vector\t\t\t\t\tpos;\r\n\t\tint\t\t\t\t\t\t\tdir;\r\n\t\tGridDims\t\t\t\t\tdims;\r\n\t\tRestartType\t\t\t\t\ttype;\r\n\t\tbool\t\t\t\t\t\tautomatic;\r\n\t};\r\n\tstatic const int\t\t\t\tvNUM_RESTARTS = 18;\r\n\t\r\n\tRestartInfo\t\t\t\t\t\tm_restart_tab[vNUM_RESTARTS];\r\n\r\n\t/*\r\n\t\tLight info\r\n\t*/\r\n\t\r\n\tstruct LightIntensity\r\n\t{\r\n\t\tfloat r;\r\n\t\tfloat g;\r\n\t\tfloat b;\r\n\t};\r\n\t\r\n\tstatic const int\t\t\t\tvMAX_LIGHTS = 16;\r\n\t\r\n\tint\t\t\t\t\t\t\t\tm_numLights;\r\n\tLightIntensity\t\t\t\t\tm_ambientLightIntensity;\r\n\tLightIntensity\t\t\t\t\tm_falloffLightIntensity;\r\n\tMth::Vector\t\t\t\t\t\tm_lightTab[vMAX_LIGHTS];\r\n\tfloat\t\t\t\t\t\t\tm_cursorAmbience;\r\n\r\n\t\r\n\tMemUsageInfo\t\t\t\t\tm_mem_usage_info;\r\n};\r\n\r\n\r\n\r\n\r\n} // end namespace\r\n\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sk/ParkEditor2/clipboard.cpp",
    "content": "#include <core/defines.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/event.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/utils.h>\r\n#include <sk/ParkEditor2/ParkEd.h>\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/modules/FrontEnd/FrontEnd.h>\r\n#include <gfx/nxviewman.h>\r\n#include <gfx/2D/ScreenElemMan.h>\r\n#include <gfx/2D/TextElement.h>\r\n\r\n#include <sk/ParkEditor2/clipboard.h>\r\n\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/components/RailEditorComponent.h>\r\n#include <gfx/nx.h>\r\n\r\nDefinePoolableClass(Ed::CClipboardEntry)\r\nDefinePoolableClass(Ed::CClipboard)\r\n\r\nnamespace Ed\r\n{\r\n\r\nstatic void s_rotate_map_vector(int *p_x, int *p_z, Mth::ERot90 rotation)\r\n{\r\n\tint in_x=*p_x;\r\n\tint in_z=*p_z;\r\n\tswitch (rotation)\r\n\t{\r\n\t\tcase Mth::ROT_0:\r\n\t\t\tbreak;\r\n\t\tcase Mth::ROT_90:\r\n\t\t\t*p_x=in_z;\r\n\t\t\t*p_z=-in_x;\r\n\t\t\tbreak;\r\n\t\tcase Mth::ROT_180:\r\n\t\t\t*p_x=-in_x;\r\n\t\t\t*p_z=-in_z;\r\n\t\t\tbreak;\r\n\t\tcase Mth::ROT_270:\r\n\t\t\t*p_x=-in_z;\r\n\t\t\t*p_z=in_x;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0, (\"Wacky rotation\"));\r\n\t\t\tbreak;\r\n\t}\t\t\r\n}\r\n\r\nCClipboardEntry::CClipboardEntry()\r\n{\r\n\tmpMeta=NULL;\r\n\tmpConcreteMeta=NULL;\r\n\tmX=mY=mZ=0;\r\n\tmWidth=0;\r\n\tmLength=0;\r\n\tm_rot=Mth::ROT_0;\r\n\tmpNext=NULL;\r\n}\r\n\r\nCClipboardEntry::~CClipboardEntry()\r\n{\r\n\tDestroyMeta();\r\n}\r\n\r\nvoid CClipboardEntry::DestroyMeta()\r\n{\r\n\tif (mpConcreteMeta)\r\n\t{\r\n\t\tmpConcreteMeta->MarkUnlocked();\r\n\t\tCParkManager::sInstance()->DestroyConcreteMeta(mpConcreteMeta, CParkManager::mDONT_DESTROY_PIECES_ABOVE);\r\n\t\tmpConcreteMeta=NULL;\r\n\t}\r\n}\r\n\r\n// This function takes the vector from the centre to the piece, rotates it according to \r\n// the cursor's current rotation, then adds that vector to the cursor's position and places the result in\r\n// p_mapCoords\r\nvoid CClipboardEntry::CalculateMapCoords(GridDims *p_mapCoords, uint8 centre_x, uint8 centre_z, CCursor *p_cursor)\r\n{\r\n\tGridDims meta_area;\r\n\tif (mpMeta)\r\n\t{\r\n\t\tmeta_area=mpMeta->GetArea();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// If there is no meta then the clipboard entry is defining a height for one cell, so\r\n\t\t// just set the w and l to 1.\r\n\t\tmeta_area.SetWHL(1,1,1);\r\n\t}\r\n\t\t\r\n\tMth::ERot90 total_rotation=Mth::ERot90((p_cursor->GetRotation()+m_rot)&3);\r\n\tswitch ( total_rotation )\r\n\t{\r\n\t\tcase Mth::ROT_0:\r\n\t\tcase Mth::ROT_180:\r\n\t\t\tp_mapCoords->SetWHL(meta_area.GetW(),1,meta_area.GetL());\r\n\t\t\tbreak;\r\n\t\tcase Mth::ROT_90:\r\n\t\tcase Mth::ROT_270:\r\n\t\t\tp_mapCoords->SetWHL(meta_area.GetL(),1,meta_area.GetW());\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0, (\"Wacky rotation\"));\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\t\r\n\t// Get the vector from the centre of the selection area to the piece.\r\n\tint vector_x=mX-centre_x;\r\n\tint vector_z=mZ-centre_z;\r\n\t\r\n\t// Rotate the vector according to the cursor's current rotation\r\n\ts_rotate_map_vector(&vector_x, &vector_z, p_cursor->GetRotation());\r\n\r\n\t// A frig is needed after rotation because the piece always appears to be\r\n\t// displayed with the coords referring to the top-left corner, even when the\r\n\t// piece is rotated.\r\n\tswitch ( p_cursor->GetRotation() )\r\n\t{\r\n\t\tcase Mth::ROT_0:\r\n\t\t\tbreak;\r\n\t\tcase Mth::ROT_90:\r\n\t\t\tvector_z-=mWidth-1;\r\n\t\t\tbreak;\r\n\t\tcase Mth::ROT_180:\r\n\t\t\tvector_x-=mWidth-1;\r\n\t\t\tvector_z-=mLength-1;\r\n\t\t\tbreak;\t\r\n\t\tcase Mth::ROT_270:\r\n\t\t\tvector_x-=mLength-1;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0, (\"Wacky rotation\"));\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\r\n\t// Get the new map coords of the meta such that it is positioned relative to the cursor.\r\n\tGridDims cursor_position=p_cursor->GetPosition();\r\n\tp_mapCoords->SetXYZ(cursor_position.GetX()+vector_x, mY, cursor_position.GetZ()+vector_z);\r\n}\r\n\r\nbool CClipboardEntry::CanPaste(uint8 centre_x, uint8 centre_z, CCursor *p_cursor)\r\n{\r\n\tGridDims map_coords;\r\n\tCalculateMapCoords(&map_coords,centre_x,centre_z,p_cursor);\r\n\t// Make sure the y is set to zero because the GetMetaPiecesAt function that gets called in\r\n\t// CanPlacePiecesIn will think there is something in the cell if the y is -1\r\n\tmap_coords.SetXYZ(map_coords.GetX(),0,map_coords.GetZ());\r\n\t\r\n\tCParkManager *p_manager=CParkManager::sInstance();\r\n\treturn p_manager->CanPlacePiecesIn(map_coords, true); // The true means ignore floor height problems\r\n}\r\n\r\n// centre_x,centre_z are the map coords of the centre of the original selection area.\r\n// The coords of the entry (mX,mZ) are also in map coords.\r\nvoid CClipboardEntry::Paste(uint8 centre_x, int raiseAmount, uint8 centre_z, CCursor *p_cursor)\r\n{\r\n\tif (mpMeta && mpMeta->IsRiser())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tGridDims map_coords;\r\n\tCalculateMapCoords(&map_coords,centre_x,centre_z,p_cursor);\r\n\t\r\n\tint new_y=mY+raiseAmount;\r\n\tif (new_y >= CParkManager::MAX_HEIGHT)\r\n\t{\r\n\t\tnew_y=CParkManager::MAX_HEIGHT-1;\r\n\t}\r\n\r\n\tmap_coords.SetXYZ(map_coords.GetX(),new_y,map_coords.GetZ());\r\n\t\t\r\n\tCParkManager *p_manager=CParkManager::sInstance();\r\n\t\r\n\t// Adjust the floor height to match that of the piece\r\n\tint count=0;\t\r\n\twhile (true)\r\n\t{\r\n\t\tbool uniform_height=false;\r\n\t\tint current_height = p_manager->GetFloorHeight(map_coords, &uniform_height);\r\n\t\t\r\n\t\tif (current_height > new_y)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\tif (count>40)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"Too many recursions of ChangeFloorHeight in CClipboardEntry::Paste\"));\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\t\r\n\t\tif (uniform_height && current_height==new_y)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tp_manager->ChangeFloorHeight(map_coords,1); // 1 is the step amount, 1 upwards\r\n\t\t++count;\r\n\t}\t\t\r\n\r\n\tif (mpMeta)\r\n\t{\r\n\t\t// Place the piece\t\r\n\t\tCConcreteMetaPiece *p_concrete = p_manager->CreateConcreteMeta(mpMeta);\r\n\t\tp_concrete->SetRot(Mth::ERot90((m_rot+p_cursor->GetRotation())&3));\r\n\t\tp_manager->AddMetaPieceToPark(map_coords, p_concrete);\r\n\t}\t\r\n}\r\n\r\nint CClipboardEntry::GetFloorHeight(uint8 centre_x, uint8 centre_z, CCursor *p_cursor)\r\n{\r\n\tGridDims map_coords;\r\n\tCalculateMapCoords(&map_coords,centre_x,centre_z,p_cursor);\r\n\t\r\n\tbool uniform_height;\r\n\treturn CParkManager::sInstance()->GetFloorHeight(map_coords, &uniform_height);\r\n}\r\n\r\nvoid CClipboardEntry::HighlightIntersectingMetas(uint8 centre_x, uint8 centre_z, CCursor *p_cursor, bool on)\r\n{\r\n\tGridDims map_coords;\r\n\tCalculateMapCoords(&map_coords,centre_x,centre_z,p_cursor);\r\n\t// Make sure the y is set to zero because the GetMetaPiecesAt function that gets called in\r\n\t// CanPlacePiecesIn will think there is something in the cell if the y is -1\r\n\tmap_coords.SetXYZ(map_coords.GetX(),0,map_coords.GetZ());\r\n\t\r\n\tCParkManager *p_manager=CParkManager::sInstance();\r\n\t\r\n\tCMapListTemp metas_at_pos = p_manager->GetAreaMetaPieces(map_coords);\r\n\tif (metas_at_pos.IsEmpty())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t// Iterate over the list of metapieces we just found, and highlight each one\r\n\tCMapListNode *p_entry = metas_at_pos.GetList();\r\n\twhile(p_entry)\r\n\t{\r\n\t\tCConcreteMetaPiece *p_meta=p_entry->GetConcreteMeta();\r\n\t\tif (!p_meta->IsRiser())\r\n\t\t{\r\n\t\t\tp_meta->Highlight(on);\t\t\r\n\t\t}\r\n\t\t\t\r\n\t\tp_entry = p_entry->GetNext();\r\n\t}\r\n}\r\n\r\n// This gets called when the CCursor is in paste mode, and needs to display the clipboard contents at\r\n// the cursor position.\r\n// pos and rot are the world position and rotation in degrees of the cursor.\r\n// They may not be cell aligned, and the rotation may not be a multiple of 90 degrees.\r\n// This function will position the meta such that the centre of the clipboard selection is at pos.\r\nvoid CClipboardEntry::ShowMeta(uint8 centre_x, int raiseAmount, uint8 centre_z, Mth::Vector pos, float rot)\r\n{\r\n\tif (!mpMeta)\r\n\t{\r\n\t\t// No meta to display, meaning the clipboard entry is defining a cell height\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Get the vector (in cell units) from the centre of the selection area to the piece.\r\n\tfloat vector_x=mX-centre_x;\r\n\tfloat vector_z=mZ-centre_z;\r\n\r\n\t// Calculate the vector, in world coords, from the centre of the selection to the centre of the piece.\t\r\n\tMth::Vector p(0.0f,0.0f,0.0f);\r\n\tp[X]=vector_x*CParkGenerator::CELL_WIDTH+(mWidth-1)*CParkGenerator::CELL_WIDTH/2.0f;\r\n\tp[Z]=vector_z*CParkGenerator::CELL_LENGTH+(mLength-1)*CParkGenerator::CELL_LENGTH/2.0f;\r\n\r\n\t// Rotate by rot degrees\t\r\n\tfloat rad=rot*3.141592654f/180.0f;\r\n\tfloat s=sinf(rad);\r\n\tfloat c=cosf(rad);\r\n\r\n\tMth::Vector rotated;\r\n\trotated[X]=c*p[X]+s*p[Z];\r\n\trotated[Y]=0.0f;\r\n\trotated[Z]=c*p[Z]-s*p[X];\r\n\t\r\n\t// Add the passed pos to get the final world position of the piece.\r\n\tMth::Vector world_pos=pos+rotated;\r\n\r\n\t// Add in the cell height\r\n\tworld_pos[Y]+=mY*CParkGenerator::CELL_HEIGHT;\r\n\tif (mpMeta->IsRiser())\r\n\t{\r\n\t\tworld_pos[Y]-=CParkGenerator::CELL_HEIGHT;\r\n\t}\t\r\n\t\r\n\t// Create the concrete meta if it does not exist already.\r\n\tif (!mpConcreteMeta)\r\n\t{\r\n\t\tDbg_MsgAssert(mpMeta,(\"NULL mpMeta ?\"));\r\n\t\tmpConcreteMeta=CParkManager::sInstance()->CreateConcreteMeta(mpMeta,true);\r\n\t\tmpConcreteMeta->MarkLocked();\r\n\t}\t\r\n\t\r\n\t// Position the piece, adding in the pieces local rotation value.\r\n\tmpConcreteMeta->SetSoftRot(world_pos,rot+90.0f*m_rot);\r\n}\r\n\r\nbool CClipboardEntry::CreateGapFillerPieces()\r\n{\r\n\tif (!mpMeta)\r\n\t{\r\n\t\t//printf(\"y=%d\\n\",mY);\r\n\t\treturn true;\r\n\t}\r\n\r\n\t//printf(\"y=%d Meta=%s\\n\",mY,Script::FindChecksumName(mpMeta->GetNameChecksum()));\r\n\r\n\tswitch (mpMeta->GetNameChecksum())\r\n\t{\r\n\tcase CRCC(0x66a8fedb,\"floor_block1\"):\r\n\tcase CRCC(0xffa1af61,\"floor_block2\"):\r\n\tcase CRCC(0x88a69ff7,\"floor_block3\"):\r\n\tcase CRCC(0x16c20a54,\"floor_block4\"):\r\n\tcase CRCC(0x61c53ac2,\"floor_block5\"):\r\n\tcase CRCC(0xf8cc6b78,\"floor_block6\"):\r\n\tcase CRCC(0x8fcb5bee,\"floor_block7\"):\r\n\tcase CRCC(0x1f74467f,\"floor_block8\"):\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn true;\r\n\t\tbreak;\r\n\t}\t\t\r\n\r\n\t//printf(\"y=%d Meta=%s\\n\",mY,Script::FindChecksumName(mpMeta->GetNameChecksum()));\r\n\r\n\tbool ran_out_of_memory=false;\r\n\tCClipboardEntry *p_new_list=NULL;\r\n\tCClipboardEntry *p_last_in_list=NULL;\r\n\tfor (int y=mY; y>0; --y)\r\n\t{\r\n\t\tif (Mem::CPoolable<CClipboardEntry>::SGetNumUsedItems()==\r\n\t\t\tMem::CPoolable<CClipboardEntry>::SGetTotalItems())\r\n\t\t{\r\n\t\t\t// Not enough space to create a new CClipboardEntry !\r\n\t\t\tran_out_of_memory=true;\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\t\t\r\n\t\tCClipboardEntry *p_new_entry=new CClipboardEntry;\r\n\t\tif (!p_last_in_list)\r\n\t\t{\r\n\t\t\tp_last_in_list=p_new_entry;\r\n\t\t}\t\r\n\r\n\t\tif (y==mY)\r\n\t\t{\r\n\t\t\tp_new_entry->mpMeta = CParkManager::sInstance()->GetAbstractMeta(CRCD(0x2c5b0277,\"floor_wall_block3\"));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_new_entry->mpMeta = CParkManager::sInstance()->GetAbstractMeta(CRCD(0x72372c50,\"wall_block1\"));\r\n\t\t}\r\n\t\t\t\r\n\t\tp_new_entry->mX=mX;\r\n\t\tp_new_entry->mY=y;\r\n\t\tp_new_entry->mZ=mZ;\r\n\t\tp_new_entry->mWidth=1;\r\n\t\tp_new_entry->mLength=1;\r\n\t\tp_new_entry->m_rot=m_rot;\r\n\t\t\r\n\t\t// Insert into the list.\r\n\t\tp_new_entry->mpNext=p_new_list;\r\n\t\tp_new_list=p_new_entry;\r\n\t}\r\n\t\r\n\tif (p_new_list)\r\n\t{\r\n\t\tDbg_MsgAssert(p_last_in_list,(\"Eh?\"));\r\n\t\tp_last_in_list->mpNext=mpNext;\r\n\t\tmpNext=p_new_list;\r\n\t}\r\n\t\t\r\n\tif (ran_out_of_memory)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\treturn true;\r\n}\r\n\t\r\nCClipboard::CClipboard()\r\n{\r\n\tmp_entries=NULL;\r\n\tm_min_x=m_min_z=255;\r\n\tm_max_x=m_max_z=0;\r\n\t\r\n\tmpNext=NULL;\r\n\tm_area.SetXYZ(0,0,0);\r\n\tm_area.SetWHL(0,0,0);\r\n\t\r\n\tmp_rails=NULL;\r\n}\r\n\r\nCClipboard::~CClipboard()\r\n{\r\n\tdelete_entries();\r\n}\r\n\r\nvoid CClipboard::delete_entries()\r\n{\r\n\tCClipboardEntry *p_entry=mp_entries;\r\n\twhile (p_entry)\r\n\t{\r\n\t\tCClipboardEntry *p_next=p_entry->mpNext;\r\n\t\tdelete p_entry;\r\n\t\tp_entry=p_next;\r\n\t}\t\r\n\tmp_entries=NULL;\r\n\t\r\n\tm_min_x=m_min_z=255;\r\n\tm_max_x=m_max_z=0;\r\n\t\r\n\tm_area.SetXYZ(0,0,0);\r\n\tm_area.SetWHL(0,0,0);\r\n\t\r\n\t// Call UpdateSuperSectors to refresh the collision before deleting the rails otherwise the \r\n\t// collision code will assert when the rail sectors are deleted. (TT6874)\r\n\t// UpdateSuperSectors isn;t normally called on the rails displayed on the cursor because\r\n\t// they don't need collision.\r\n\tNx::CScene *p_cloned_scene=Ed::CParkManager::sInstance()->GetGenerator()->GetClonedScene();\r\n\tp_cloned_scene->UpdateSuperSectors();\r\n\r\n\tObj::CEditedRail *p_rail=mp_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tObj::CEditedRail *p_next=p_rail->mpNext;\r\n\t\tdelete p_rail;\r\n\t\tp_rail=p_next;\r\n\t}\r\n\tmp_rails=NULL;\r\n}\r\n\r\nvoid CClipboard::update_extents(uint8 x, uint8 z)\r\n{\r\n\tif (x < m_min_x)\r\n\t{\r\n\t\tm_min_x=x;\r\n\t}\r\n\tif (x > m_max_x)\r\n\t{\r\n\t\tm_max_x=x;\r\n\t}\r\n\tif (z < m_min_z)\r\n\t{\r\n\t\tm_min_z=z;\r\n\t}\r\n\tif (z > m_max_z)\r\n\t{\r\n\t\tm_max_z=z;\r\n\t}\r\n}\r\n\r\n// Returns false if it fails due to running out of space on the CClipboardEntry pool\r\nbool CClipboard::AddMeta(CConcreteMetaPiece *p_meta, int raiseAmount)\r\n{\r\n\tDbg_MsgAssert(p_meta,(\"NULL p_meta\"));\r\n\r\n\tGridDims dims=p_meta->GetArea();\r\n\tdims.SetXYZ(dims.GetX(),dims.GetY()+raiseAmount,dims.GetZ());\r\n\t//printf(\"AddMeta y=%d raiseAmount=%d, \\t%s Riser=%d\\n\",dims.GetY(),raiseAmount,Script::FindChecksumName(p_meta->GetNameChecksum()),p_meta->IsRiser());\r\n\t\r\n\tif (p_meta->IsRiser())\r\n\t{\r\n\t\tdims.SetXYZ(dims.GetX(),dims.GetY()+1,dims.GetZ());\r\n\t\t\r\n\t\t//printf(\"Riser: %d,%d  %d\\n\",dims.GetX(),dims.GetZ(),dims.GetY());\r\n\t\t\r\n\t\tif (dims.GetY())\r\n\t\t{\r\n\t\t\tif (!AddHeight(dims.GetX(),dims.GetY(),dims.GetZ()))\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\t// Zero height riser pieces (ie, floor pieces) still get added so that they\r\n\t\t// are displayed on the cursor.\r\n\t}\t\r\n\r\n\tCAbstractMetaPiece *p_abstract_meta=CParkManager::sInstance()->GetAbstractMeta(p_meta->GetNameChecksum());\r\n\t\r\n\t// Don't add meta if it is in the list already\r\n\tCClipboardEntry *p_entry=mp_entries;\r\n\twhile (p_entry)\r\n\t{\r\n\t\tif (p_entry->mpMeta==p_abstract_meta &&\r\n\t\t\tp_entry->mX==dims.GetX() &&\r\n\t\t\tp_entry->mY==dims.GetY() &&\r\n\t\t\tp_entry->mZ==dims.GetZ() &&\r\n\t\t\tp_entry->mWidth==dims.GetW() &&\r\n\t\t\tp_entry->mLength==dims.GetL() &&\r\n\t\t\tp_entry->m_rot==p_meta->GetRot())\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\t\r\n\r\n\tif (Mem::CPoolable<CClipboardEntry>::SGetNumUsedItems()==\r\n\t\tMem::CPoolable<CClipboardEntry>::SGetTotalItems())\r\n\t{\r\n\t\t// Not enough space to create a new CClipboardEntry !\r\n\t\treturn false;\r\n\t}\t\r\n\t\t\t\r\n\tCClipboardEntry *p_new_entry=new CClipboardEntry;\r\n\r\n\t// Store a pointer to the abstract meta so that a copy can be made when the time comes to paste.\t\r\n\t// Mustn't store a pointer to the concrete meta because the user may delete that piece later.\r\n\tp_new_entry->mpMeta = p_abstract_meta;\r\n\r\n\t// Store the grid coords of the concrete meta because the abstract meta's x,y,z will be zero.\r\n\tp_new_entry->mX=dims.GetX();\r\n\tp_new_entry->mY=dims.GetY();\r\n\tp_new_entry->mZ=dims.GetZ();\r\n\t// Also store the width and length, needed for calculating the world pos of the centre when\r\n\t// displaying the piece on the cursor.\r\n\t// Note that the width and height will already take into account any rotation that the concrete meta has.\r\n\tp_new_entry->mWidth=dims.GetW();\r\n\tp_new_entry->mLength=dims.GetL();\r\n\r\n\t// Update the min & max x & z for the clipboard selection for calculation of the centre later.\r\n\tupdate_extents(dims.GetX(),\t\t\t\t\tdims.GetZ());\r\n\tupdate_extents(dims.GetX()+dims.GetW()-1,\tdims.GetZ()+dims.GetL()-1);\r\n\t\r\n\tp_new_entry->m_rot=p_meta->GetRot();\r\n\t\r\n\t// Insert into the list.\r\n\tp_new_entry->mpNext=mp_entries;\r\n\tmp_entries=p_new_entry;\r\n\treturn true;\r\n}\r\n\r\n// Returns false if it fails due to running out of space on the CClipboardEntry pool\r\nbool CClipboard::AddHeight(int x, int y, int z)\r\n{\r\n\t// If there is a piece covering this position already then do not add\r\n\t// a new height, to prevent unnecessary column slides.\r\n\tCClipboardEntry *p_entry=mp_entries;\r\n\twhile (p_entry)\r\n\t{\r\n\t\tif (p_entry->mpMeta && !p_entry->mpMeta->IsRiser() &&\r\n\t\t\tp_entry->mX <= x && x < p_entry->mX+p_entry->mWidth &&\r\n\t\t\tp_entry->mZ <= z && z < p_entry->mZ+p_entry->mLength)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\t\r\n\t\r\n\t// If there is a height defined for x,z already then just update it's y\r\n\t// if the passed y is bigger.\r\n\tp_entry=mp_entries;\r\n\twhile (p_entry)\r\n\t{\r\n\t\tif (p_entry->mpMeta==NULL &&\r\n\t\t\tp_entry->mX <= x && x < p_entry->mX+p_entry->mWidth &&\r\n\t\t\tp_entry->mZ <= z && z < p_entry->mZ+p_entry->mLength)\r\n\t\t{\r\n\t\t\tif (y >= p_entry->mY)\r\n\t\t\t{\r\n\t\t\t\tp_entry->mY=y;\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\t\r\n\t\r\n\tif (Mem::CPoolable<CClipboardEntry>::SGetNumUsedItems()==\r\n\t\tMem::CPoolable<CClipboardEntry>::SGetTotalItems())\r\n\t{\r\n\t\t// Not enough space to create a new CClipboardEntry !\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\tCClipboardEntry *p_new_entry=new CClipboardEntry;\r\n\r\n\tp_new_entry->mpMeta = NULL;\r\n\r\n\tp_new_entry->mX=x;\r\n\tp_new_entry->mY=y;\r\n\tp_new_entry->mZ=z;\r\n\tp_new_entry->mWidth=1;\r\n\tp_new_entry->mLength=1;\r\n\r\n\t// Update the min & max x & z for the clipboard selection for calculation of the centre later.\r\n\tupdate_extents(x,z);\r\n\t\r\n\t// Insert into the list.\r\n\tp_new_entry->mpNext=mp_entries;\r\n\tmp_entries=p_new_entry;\r\n\treturn true;\r\n}\r\n\r\n// Creates clipboard entries for all the things in the passed area.\r\n// A clipboard entry will be created if there is a piece in a cell, or if\r\n// the cell has a non-zero height.\r\n// Returns false if it fails due to running out of space on the CClipboardEntry pool.\r\n// If that happens, it will delete any CClipboardEntry's that it already allocated.\r\nbool CClipboard::CopySelectionToClipboard(GridDims area)\r\n{\r\n\tm_area=area;\r\n\t\r\n\tCParkManager *p_manager=CParkManager::sInstance();\r\n\r\n\t// First, figure out how much the selection needs to be raised up so that\r\n\t// all the pieces are above ground level.\r\n\tint most_negative_y=0;\t\r\n\tfor (int x = area.GetX(); x < area.GetX() + area.GetW(); x++)\r\n\t{\r\n\t\tfor (int z = area.GetZ(); z < area.GetZ() + area.GetL(); z++)\r\n\t\t{\r\n\t\t\tCMapListNode *p_entry=p_manager->GetMapListNode(x,z);\r\n\t\t\twhile (p_entry)\r\n\t\t\t{\r\n\t\t\t\tCConcreteMetaPiece *p_meta=p_entry->GetConcreteMeta();\r\n\t\t\t\t\r\n\t\t\t\t//printf(\"Meta name = %s\\n\",Script::FindChecksumName(p_meta->GetNameChecksum()));\r\n\t\t\t\tint y=p_meta->GetArea().GetY();\r\n\t\t\t\tswitch (p_meta->GetNameChecksum())\r\n\t\t\t\t{\r\n\t\t\t\tcase CRCC(0x66a8fedb,\"floor_block1\"):\r\n\t\t\t\tcase CRCC(0xffa1af61,\"floor_block2\"):\r\n\t\t\t\tcase CRCC(0x88a69ff7,\"floor_block3\"):\r\n\t\t\t\tcase CRCC(0x16c20a54,\"floor_block4\"):\r\n\t\t\t\tcase CRCC(0x61c53ac2,\"floor_block5\"):\r\n\t\t\t\tcase CRCC(0xf8cc6b78,\"floor_block6\"):\r\n\t\t\t\tcase CRCC(0x8fcb5bee,\"floor_block7\"):\r\n\t\t\t\tcase CRCC(0x1f74467f,\"floor_block8\"):\r\n\t\t\t\t\t// With floor blocks, the ground position is 1 unit higher up than\r\n\t\t\t\t\t// their stored y, because their stored y is the y of their base.\r\n\t\t\t\t\t++y;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\t\r\n\t\t\t\tif (y < most_negative_y)\r\n\t\t\t\t{\r\n\t\t\t\t\tmost_negative_y=y;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t//printf(\"y=%d  %s\\n\",p_meta->GetArea().GetY(),Script::FindChecksumName(p_meta->GetNameChecksum()));\r\n\t\t\t\t\r\n\t\t\t\tp_entry = p_entry->GetNext();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t\r\n\tint raise_amount=-most_negative_y;\r\n\t\r\n\t\r\n\tfor (int x = area.GetX(); x < area.GetX() + area.GetW(); x++)\r\n\t{\r\n\t\tfor (int z = area.GetZ(); z < area.GetZ() + area.GetL(); z++)\r\n\t\t{\r\n\t\t\tCMapListNode *p_entry=p_manager->GetMapListNode(x,z);\r\n\t\t\twhile (p_entry)\r\n\t\t\t{\r\n\t\t\t\tCConcreteMetaPiece *p_meta=p_entry->GetConcreteMeta();\r\n\t\t\t\tif (p_meta->IsRestartOrFlag())\r\n\t\t\t\t{\r\n\t\t\t\t\t// Don't copy restarts or flags (TT7793)\r\n\t\t\t\t}\r\n\t\t\t\telse if (!p_meta->IsCompletelyWithinArea(area))\r\n\t\t\t\t{\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!AddMeta(p_meta,raise_amount))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Delete the existing CClipboardEntry's so that another attempt\r\n\t\t\t\t\t\t// at calling CopySelectionToClipboard can be made later after the\r\n\t\t\t\t\t\t// calling code has freed up some memory.\r\n\t\t\t\t\t\tdelete_entries();\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\t\r\n\t\t\t\t\r\n\t\t\t\tp_entry = p_entry->GetNext();\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n\r\n\t// Now one last ugly bit. Raising the selection may have moved some simple ground pieces\r\n\t// to above the ground, in which case they won't have pieces filling the gap, which looks odd.\r\n\t// So create these pieces if needed.\r\n\tCClipboardEntry *p_entry=mp_entries;\r\n\twhile (p_entry)\r\n\t{\r\n\t\tif (!p_entry->CreateGapFillerPieces())\r\n\t\t{\r\n\t\t\t// Could not create the pieces, due to low memory.\r\n\t\t\tdelete_entries();\r\n\t\t\treturn false;\r\n\t\t}\t\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\r\n\r\n\r\n\tDbg_MsgAssert(mp_rails==NULL,(\"Expected mp_rails=NULL\"));\r\n\tMth::Vector corner_pos;\r\n\tMth::Vector area_dims;\r\n\tcorner_pos=Ed::CParkManager::Instance()->GridCoordinatesToWorld(area,&area_dims);\r\n\tmp_rails=Obj::GetRailEditor()->GenerateDuplicateRails(corner_pos[X], corner_pos[Z], \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  corner_pos[X]+area_dims[X], corner_pos[Z]+area_dims[Z]);\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\nbool CClipboard::IsEmpty()\r\n{\r\n\tif (mp_entries)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\tif (mp_rails)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\treturn true;\r\n}\r\n\t\t\r\n// Pastes the contents of the clipboard into the position that the cursor is at,\r\n// using the cursor's rotation value.\r\nbool CClipboard::Paste(CCursor *p_cursor)\r\n{\r\n\tSpt::SingletonPtr<CParkEditor> p_editor;\r\n\tif (!p_editor->RoomToCopyOrPaste(m_max_x-m_min_x+1, m_max_z-m_min_z+1))\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\t// Get the map coords of the centre cell of the set of meta's\r\n\tuint8 centre_x=(m_min_x+m_max_x)/2;\r\n\tuint8 centre_z=(m_min_z+m_max_z)/2;\r\n\t\r\n\t// Bail out if any entry cannot be pasted\r\n\tCClipboardEntry *p_entry=mp_entries;\r\n\twhile (p_entry)\r\n\t{\r\n\t\tif (!p_entry->CanPaste(centre_x,centre_z,p_cursor))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\t\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\t\r\n\r\n\t// Bail out if there are not enough free rail points to create the edited rails\r\n\tint num_rail_points_to_paste=0;\r\n\tObj::CEditedRail *p_rail=mp_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tnum_rail_points_to_paste += p_rail->CountPoints();\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n\tif (num_rail_points_to_paste > Obj::GetRailEditor()->GetNumFreePoints() )\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\t\r\n\t// OK to proceed, so paste the entries\r\n\tp_entry=mp_entries;\r\n\twhile (p_entry)\r\n\t{\r\n\t\tp_entry->Paste(centre_x,p_cursor->GetClipboardY(),centre_z,p_cursor);\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\t\r\n\t\r\n\t// and paste the rails\r\n\tMth::Vector clipboard_pos=GetClipboardWorldPos();\r\n\tMth::Vector cursor_pos=p_editor->GetCursorPos();\r\n\t\r\n\tp_rail=mp_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tObj::CEditedRail *p_new_rail=Obj::GetRailEditor()->NewRail();\r\n\t\tp_new_rail->CopyRail(p_rail);\r\n\t\tp_new_rail->RotateAndTranslate(clipboard_pos, cursor_pos, p_cursor->GetRotation()*90.0f);\r\n\t\t\r\n\t\tp_new_rail->UpdateRailGeometry();\r\n\t\tp_new_rail->UpdatePostGeometry();\r\n\t\t\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\n\r\nint CClipboard::GetFloorHeight(CCursor *p_cursor)\r\n{\r\n\t// Get the map coords of the centre cell of the set of meta's\r\n\tuint8 centre_x=(m_min_x+m_max_x)/2;\r\n\tuint8 centre_z=(m_min_z+m_max_z)/2;\r\n\r\n\tint max_height=-1000;\t\r\n\tCClipboardEntry *p_entry=mp_entries;\r\n\twhile (p_entry)\r\n\t{\r\n\t\tint height=p_entry->GetFloorHeight(centre_x,centre_z,p_cursor);\r\n\t\tif (height > max_height)\r\n\t\t{\r\n\t\t\tmax_height=height;\r\n\t\t}\t\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\t\r\n\t\r\n\tif (max_height==-1000)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\treturn max_height;\r\n}\r\n\r\nint CClipboard::FindMaxFloorHeight(CCursor *p_cursor)\r\n{\r\n\t// Get the map coords of the centre cell of the set of meta's\r\n\tuint8 centre_x=(m_min_x+m_max_x)/2;\r\n\tuint8 centre_z=(m_min_z+m_max_z)/2;\r\n\r\n\tint max_floor_height=-1000;\t\r\n\tCClipboardEntry *p_entry=mp_entries;\r\n\twhile (p_entry)\r\n\t{\r\n\t\tint height=p_entry->GetFloorHeight(centre_x,centre_z,p_cursor);\r\n\t\tif (height > max_floor_height)\r\n\t\t{\r\n\t\t\tmax_floor_height=height;\r\n\t\t}\t\r\n\t\t\t\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\t\r\n\t\r\n\tif (max_floor_height != -1000)\r\n\t{\r\n\t\treturn max_floor_height;\r\n\t}\r\n\treturn 0;\t\r\n}\r\n\r\nvoid CClipboard::HighlightIntersectingMetas(CCursor *p_cursor, bool on)\r\n{\r\n\t// Get the map coords of the centre cell of the set of meta's\r\n\tuint8 centre_x=(m_min_x+m_max_x)/2;\r\n\tuint8 centre_z=(m_min_z+m_max_z)/2;\r\n\t\r\n\tCClipboardEntry *p_entry=mp_entries;\r\n\twhile (p_entry)\r\n\t{\r\n\t\tp_entry->HighlightIntersectingMetas(centre_x,centre_z,p_cursor,on);\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\t\r\n}\r\n\r\nint CClipboard::GetWidth()\r\n{\r\n\treturn m_max_x-m_min_x+1;\r\n}\r\n\r\nint CClipboard::GetLength()\r\n{\r\n\treturn m_max_z-m_min_z+1;\r\n}\r\n\r\nvoid CClipboard::GetArea(CCursor *p_cursor, GridDims *p_area)\r\n{\r\n\t// Get the map coords of the centre cell of the set of meta's\r\n\tuint8 centre_x=(m_min_x+m_max_x)/2;\r\n\tuint8 centre_z=(m_min_z+m_max_z)/2;\r\n\t\r\n\tint idx=m_min_x-centre_x;\r\n\tint idz=m_min_z-centre_z;\r\n\tint dx=0;\r\n\tint dz=0;\r\n\t\r\n\tswitch ( p_cursor->GetRotation() )\r\n\t{\r\n\t\tcase Mth::ROT_0:\r\n\t\t\tdx=idx;\r\n\t\t\tdz=idz;\r\n\t\t\tp_area->SetWHL(m_area.GetW(),1,m_area.GetL());\r\n\t\t\tbreak;\r\n\t\tcase Mth::ROT_270:\r\n\t\t\tdx=-idz;\r\n\t\t\tdz=idx;\r\n\t\t\tp_area->SetWHL(m_area.GetL(),1,m_area.GetW());\r\n\t\t\t// Shift dx,dz so that they refer to the top-left point again\r\n\t\t\tdx=dx-m_area.GetL()+1;\r\n\t\t\tbreak;\r\n\t\tcase Mth::ROT_180:\r\n\t\t\tdx=-idx;\r\n\t\t\tdz=-idz;\r\n\t\t\tp_area->SetWHL(m_area.GetW(),1,m_area.GetL());\r\n\t\t\t// Shift dx,dz so that they refer to the top-left point again\r\n\t\t\tdx=dx-m_area.GetW()+1;\r\n\t\t\tdz=dz-m_area.GetL()+1;\r\n\t\t\tbreak;\r\n\t\tcase Mth::ROT_90:\r\n\t\t\tdx=idz;\r\n\t\t\tdz=-idx;\r\n\t\t\tp_area->SetWHL(m_area.GetL(),1,m_area.GetW());\r\n\t\t\t// Shift dx,dz so that they refer to the top-left point again\r\n\t\t\tdz=dz-m_area.GetW()+1;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\r\n\tGridDims cursor_position=p_cursor->GetPosition();\r\n\tp_area->SetXYZ(cursor_position.GetX()+dx,0,cursor_position.GetZ()+dz);\r\n}\r\n\r\nMth::Vector CClipboard::GetClipboardWorldPos()\r\n{\r\n\t// Get the map coords of the centre cell of the set of meta's\r\n\tuint8 centre_x=(m_min_x+m_max_x)/2;\r\n\tuint8 centre_z=(m_min_z+m_max_z)/2;\r\n\t\r\n\tGridDims centre_cell;\r\n\tcentre_cell.SetXYZ(centre_x,m_area.GetY(),centre_z);\r\n\tcentre_cell.SetWHL(1,1,1);\r\n\t\r\n\tMth::Vector corner_pos;\r\n\tMth::Vector area_dims;\r\n\tcorner_pos=Ed::CParkManager::Instance()->GridCoordinatesToWorld(centre_cell,&area_dims);\r\n\t// corner_pos is the world pos of the top left corner of the centre cell\r\n\t\r\n\tMth::Vector clipboard_pos=corner_pos;\r\n\tclipboard_pos[X]+=area_dims[X]/2.0f;\r\n\tclipboard_pos[Z]+=area_dims[Z]/2.0f;\r\n\t// clipboard_pos is the world pos of the centre of the cell\r\n\t\r\n\treturn clipboard_pos;\r\n}\r\n\r\n// This gets called when the CCursor is in paste mode, and needs to display the clipboard contents at\r\n// the cursor position.\r\nvoid CClipboard::ShowMetas(Mth::Vector pos, float rot, int clipboardY)\r\n{\r\n\t// Get the map coords of the centre cell of the set of meta's\r\n\tuint8 centre_x=(m_min_x+m_max_x)/2;\r\n\tuint8 centre_z=(m_min_z+m_max_z)/2;\r\n\t\r\n\tCClipboardEntry *p_entry=mp_entries;\r\n\twhile (p_entry)\r\n\t{\r\n\t\tp_entry->ShowMeta(centre_x,clipboardY,centre_z,pos,rot);\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\t\r\n\t\r\n\t\r\n\tMth::Vector clipboard_pos=GetClipboardWorldPos();\r\n\t\r\n\tObj::CEditedRail *p_rail=mp_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tp_rail->UpdateRailGeometry(clipboard_pos,pos,rot);\r\n\t\tp_rail->UpdatePostGeometry(clipboard_pos,pos,rot);\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\t\r\n}\r\n\r\nvoid CClipboard::DestroyMetas()\r\n{\r\n\tCClipboardEntry *p_entry=mp_entries;\r\n\twhile (p_entry)\r\n\t{\r\n\t\tp_entry->DestroyMeta();\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\t\r\n\r\n\tObj::CEditedRail *p_rail=mp_rails;\r\n\twhile (p_rail)\r\n\t{\r\n\t\tp_rail->DestroyPostGeometry();\r\n\t\tp_rail->DestroyRailGeometry();\r\n\t\tp_rail=p_rail->mpNext;\r\n\t}\t\r\n}\r\n\r\n} // namespace Ed\r\n\r\n"
  },
  {
    "path": "Code/Sk/ParkEditor2/clipboard.h",
    "content": "#ifndef __SK_PARKEDITOR2_CLIPBOARD_H\r\n#define __SK_PARKEDITOR2_CLIPBOARD_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __SYS_MEM_POOLABLE_H\r\n#include <sys/mem/poolable.h>\r\n#endif\r\n\r\n#ifndef __SK_PARKEDITOR2_PARKGEN_H\r\n#include <sk/parkeditor2/parkgen.h>\r\n#endif\r\n\r\nnamespace Obj\r\n{\r\n\tclass CEditedRail;\r\n}\r\n\t\r\nnamespace Ed\r\n{\r\n\r\nclass CAbstractMetaPiece;\r\n\r\nenum\r\n{\r\n\tMAX_CLIPBOARD_METAS=1000,\r\n\tMAX_CLIPBOARDS=6,\r\n\tCLIPBOARD_MAX_W=10,\r\n\tCLIPBOARD_MAX_L=10,\r\n};\r\n\r\nclass CClipboardEntry : public Mem::CPoolable<CClipboardEntry>\r\n{\r\npublic:\r\n\tCClipboardEntry();\r\n\t~CClipboardEntry();\r\n\r\n\tvoid CalculateMapCoords(GridDims *p_mapCoords, uint8 centre_x, uint8 centre_z, CCursor *p_cursor);\r\n\tbool CanPaste(uint8 centre_x, uint8 centre_z, CCursor *p_cursor);\r\n\tvoid Paste(uint8 centre_x, int raiseAmount, uint8 centre_z, CCursor *p_cursor);\r\n\tint\t GetFloorHeight(uint8 centre_x, uint8 centre_z, CCursor *p_cursor);\r\n\tvoid HighlightIntersectingMetas(uint8 centre_x, uint8 centre_z, CCursor *p_cursor, bool on);\r\n\tvoid ShowMeta(uint8 centre_x, int raiseAmount, uint8 centre_z, Mth::Vector pos, float rot);\r\n\tvoid DestroyMeta();\r\n\tbool CreateGapFillerPieces();\r\n\t\r\n\tCAbstractMetaPiece *mpMeta;\r\n\tuint8 mX;\r\n\tsint8 mY;\r\n\tuint8 mZ;\r\n\tMth::ERot90 m_rot;\r\n\tuint8 mWidth;\r\n\tuint8 mLength;\r\n\t\r\n\t// Used when displaying the cursor\r\n\tCConcreteMetaPiece *mpConcreteMeta;\r\n\t\r\n\tCClipboardEntry *mpNext;\r\n};\r\n\r\nclass CClipboard : public Mem::CPoolable<CClipboard>\r\n{\r\n\tGridDims m_area;\r\n\t\r\n\tuint8 m_min_x;\r\n\tuint8 m_min_z;\r\n\tuint8 m_max_x;\r\n\tuint8 m_max_z;\r\n\tvoid update_extents(uint8 x, uint8 z);\r\n\t\r\n\tCClipboardEntry *mp_entries;\r\n\tvoid delete_entries();\r\n\t\r\n\tObj::CEditedRail *mp_rails;\r\n\t\r\npublic:\r\n\tCClipboard();\r\n\t~CClipboard();\r\n\r\n\tbool AddMeta(CConcreteMetaPiece *p_meta, int raiseAmount);\r\n\tbool AddHeight(int x, int y, int z);\r\n\tbool CopySelectionToClipboard(GridDims area);\r\n\tbool IsEmpty();\r\n\tbool Paste(CCursor *p_cursor);\r\n\tint\t GetFloorHeight(CCursor *p_cursor);\r\n\tint\t FindMaxFloorHeight(CCursor *p_cursor);\r\n\tvoid HighlightIntersectingMetas(CCursor *p_cursor, bool on);\r\n\tvoid ShowMetas(Mth::Vector pos, float rot, int clipboardY);\r\n\tvoid DestroyMetas();\r\n\tvoid GetArea(CCursor *p_cursor, GridDims *p_area);\r\n\tMth::Vector GetClipboardWorldPos();\r\n\r\n\tint GetWidth();\r\n\tint GetLength();\r\n\t\r\n\tCClipboard *mpNext;\t\r\n};\r\n\r\n}\r\n\r\n#endif\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sk/Scripting/cfuncs.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Scripting\r\n//* FILENAME:       CFuncs.cpp\r\n//* OWNER:          Kendall Harrison\r\n//* CREATION DATE:  9/14/2000\r\n//****************************************************************************\r\n\r\n// start autoduck documentation\r\n// @DOC cfuncs\r\n// @module cfuncs | None\r\n// @subindex Scripting Database\r\n// @index script | cfuncs\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/scripting/cfuncs.h>\r\n#include <sk/scripting/skfuncs.h>\r\n\r\n#include <sk/objects/pathman.h>\r\n//#include <libscf.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/math.h>\r\n#include <core/thread.h>\r\n#include <core/singleton.h>\r\n#include <core/macros.h>\r\n#include <core/String/stringutils.h>\r\n\r\n#include <sys/demo.h>\r\n#include <sys/timer.h>\r\n#include <sys/File/PRE.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/File/pip.h>\r\n#include <sys/mem/memman.h>\r\n#include <sys/mem/memtest.h>\r\n#include <sys/sioman.h>\r\n#include <sys/sio/keyboard.h>\r\n#include <sys/mcman.h>\r\n#include <sys/config/config.h>\r\n#include <sys/replay/replay.h>\r\n\r\n#ifdef __PLAT_NGPS__\r\n//    #include <sif.h>\r\n//    #include <sifdev.h>\r\n    #include <libcdvd.h>\r\n\t//#include <libscf.h>\r\n\t#include <gfx/ngps/nx/nx_init.h>\r\n#endif\r\n\r\n#ifdef __PLAT_NGC__\r\n#include <sys/ngc/p_render.h>\r\n#include <gfx/ngc/nx/nx_init.h>\r\n#endif\r\n\r\n#include <gfx/gfxman.h>\r\n#include <gfx/bonedanim.h>\r\n#include <gfx/camera.h>\r\n#include <gfx/casutils.h>\r\n#include <gfx/debuggfx.h>\r\n#include <gfx/gfxutils.h>\r\n#include <gfx/modelbuilder.h>\r\n#include <gfx/skeleton.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/NxSector.h>\r\n#include <gfx/NxModel.h>\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/NxLoadScreen.h>\r\n#include <gfx/NxLightMan.h>\r\n#include <gfx/NxViewMan.h>\r\n#include <gfx/NxMiscFX.h>\r\n#include <gfx/NxGeom.h>\r\n\r\n#include <gel/modman.h>\r\n#include <gel/mainloop.h>\r\n#include <gel/objman.h>\r\n#include <gel/inpman.h>\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/music/music.h>\r\n#include <gel/movies/movies.h>\r\n#include <gel/net/net.h>\r\n#include <gel/net/server/netserv.h>\r\n#include <gel/net/client/netclnt.h>\r\n#include <gel/prefs/prefs.h>\r\n#include <gel/assman/assman.h>\r\n#include <gel/objtrack.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/rigidbodycomponent.h>\r\n#include <gel/components/cameracomponent.h>\r\n#include <gel/components/proximtriggercomponent.h>\r\n#include <gel/components/inputcomponent.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n#include <gel/components/soundcomponent.h>\r\n#include <gel/components/streamcomponent.h>\r\n#include <gel/environment/terrain.h>\r\n\r\n\r\n#include <gel/scripting/script.h> \r\n#include <gel/scripting/symboltype.h> \r\n#include <gel/scripting/struct.h> \r\n#include <gel/scripting/array.h> \r\n#include <gel/scripting/symboltable.h> \r\n#include <gel/scripting/checksum.h> \r\n#include <gel/scripting/parse.h> \r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/eval.h>\r\n#include <gel/scripting/string.h>\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n#include <gel/event.h>\r\n \r\n#include <sk/scripting/gs_file.h> \r\n#include <sk/scripting/nodearray.h> \r\n\r\n#include <sk/objects/car.h>\r\n#include <sk/objects/gameobj.h>\r\n#include <sk/objects/gap.h>\r\n#include <sk/objects/moviecam.h>\r\n#include <sk/objects/ped.h>\r\n#include <sk/objects/proxim.h>\r\n#include <sk/objects/emitter.h>\r\n#include <sk/objects/rail.h>\r\n#include <sk/objects/records.h>\r\n#include <sk/objects/restart.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/objects/playerprofilemanager.h>\r\n#include <sk/objects/skatercam.h>\r\n#include <sk/objects/trickobject.h>\r\n#include <sk/objects/viewerobj.h>\r\n\r\n#ifdef TESTING_GUNSLINGER\r\n#include <sk/objects/navigation.h>\r\n#endif\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/modules/skate/competition.h>\r\n#include <sk/modules/skate/GameFlow.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/modules/skate/GoalManager.h>\r\n#include <sk/modules/skate/horse.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/FrontEnd/FrontEnd.h>\r\n//#include <sk/modules/FrontEnd/SoundOptions.h>\r\n//#include <sk/modules/FrontEnd/TrickOptions.h>\r\n#include <sk/modules/Viewer/Viewer.h>\r\n#include <gel/scripting/Debugger.h>\r\n#include <gfx/nxparticlemgr.h>\r\n\r\n#include <sk/ParkEditor2/ParkEd.h>\r\n\r\n#include <sk/components/raileditorcomponent.h>\r\n\r\n#ifdef __PLAT_XBOX__\r\n#include <sk/gamenet/xbox/p_auth.h>\r\n#endif\r\n\r\n#include <sk/language.h>\r\n\r\nbool DumpFunctionTimesTrigger=false;\r\n\r\nvoid MemViewToggle();\r\n\r\nnamespace Script\r\n{\r\n\textern void DumpLastStructs();\r\n}\r\n\r\nnamespace Gfx\r\n{\r\n\tvoid DebuggeryLines_CleanUp( void );\t\t// just for debugging\r\n}\r\n\r\n#ifdef\t__PLAT_NGPS__\r\nnamespace NxPs2\r\n{\r\n#ifdef\t__NOPT_ASSERT__\r\nextern uint32\t\tgPassMask1; \t\t// 1<<6 | 1<<7  (0x40, 0x80)\r\nextern uint32\t\tgPassMask0; \t\t// 1<<6 | 1<<7  (0x40, 0x80)\r\n#endif \r\n}\r\n#endif // __PLAT_NGPS__\r\n\r\n\r\n// This is the level specific qb file.\r\n#if 0\r\nstatic uint32 s_level_specific_qb=0;\r\n#else\r\n// extended to have more than one\r\n#define\tMAX_LEVEL_QBS  2\r\nstatic uint32 s_level_specific_qbs[MAX_LEVEL_QBS];\r\n#endif\r\n\r\n\r\n///////////////////////////////////////////////////////////////////\r\n// some temp debugging functions\r\n#define\tDUMP_LEN\t1024\r\nstatic void * dump_handle;\t\r\nstatic char p_buffer[1024];\r\nstatic char *p_pos;\r\n\r\nint dumping_printfs = 0;\t\t\r\n\r\nbool dump_open(const char *name)\r\n{\t\r\n\tdump_handle = File::Open( name, \"wb\");\t\t\r\n\tp_pos = p_buffer;\r\n\r\n\tif (dump_handle != NULL)\r\n\t{\r\n\t\tdumping_printfs = 1;\r\n\t}\r\n\r\n\treturn ( dump_handle != NULL );\r\n}\r\n\r\nvoid dump_flush()\r\n{\r\n\tint len = p_pos - p_buffer;\r\n\tif (len)\r\n\t{\r\n\t\tFile::Write( p_buffer, len, 1, dump_handle );     \t\t\r\n\t\tp_pos = p_buffer;\r\n\t}\r\n}\r\n\r\n// print to file, replacing lf with cr/lf, so I can read them in notepad\r\nvoid dump_printf(char *p)\r\n{\r\n\tint len = strlen(p);\r\n\tif ((int)(p_pos + len) > (int)(p_buffer + DUMP_LEN-16))\r\n\t{\r\n\t\tdump_flush();\r\n\t}\r\n\t\r\n\tfor (int i= 0; i<len;i++)\r\n\t{\r\n\t\tif (*p != 0x0a)\r\n\t\t{\r\n\t\t\t*p_pos ++ = *p++;     \r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp++;\r\n\t\t\t*p_pos++ = 0x0d;\r\n\t\t\t*p_pos++ = 0x0a;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid dump_close()\r\n{\r\n\tdump_flush();\r\n\tFile::Close( dump_handle );\r\n\tdumping_printfs = 0;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace CFuncs\r\n{\r\n\r\nusing namespace Script;\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nenum{\r\n\tNODE_ACTION_CREATE,\r\n\tNODE_ACTION_KILL,\r\n\tNODE_ACTION_SET_VISIBLE,\r\n\tNODE_ACTION_SET_INVISIBLE,\r\n\tNODE_ACTION_SHATTER,\r\n\tNODE_ACTION_CHECK_IF_ALIVE,\r\n\tNODE_ACTION_SET_COLOR,\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//static Tmr::Time\t\ts_start_network_test_time = 0;\r\n//static Tsk::Task< Tmr::Time >*\ts_network_test_task;\r\nstatic Tsk::Task< int >*\t\ts_second_controller_check_task = NULL;\r\n\r\n// GJ:  viewer mode stuff...  will eventually be moved to CViewer class, hopefully.\r\nstatic int s_view_mode = 0;\r\nstatic uint32\ts_last_broadcast_cheat = 0;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*\r\nstatic void\t\ttest_network_task( const Tsk::Task< Tmr::Time >& task )\r\n{\r\n\t// Wait a second before testing so the user can see the status box\r\n\tif(( Tmr::GetTime() - s_start_network_test_time ) < Tmr::Seconds( 1 ))\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\tNet::Manager * net_man =  Net::Manager::Instance();\r\n\tbool properly_setup;\r\n\t \r\n\tproperly_setup = net_man->NetworkEnvironmentSetup();\r\n\tif( !properly_setup )\r\n\t{\r\n\t\tif( net_man->GetLastError() == Net::vRES_ERROR_DEVICE_NOT_HOT )\r\n\t\t{\r\n\t\t\tScript::CStruct* pStructure;\r\n\t\t\t\r\n\t\t\tpStructure = new Script::CStruct;\r\n\t\t\t\r\n\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_error_not_connected\" ));\r\n\t\t\tScript::RunScript( \"create_net_startup_error_dialog\", pStructure );\r\n\r\n\t\t\tdelete pStructure;\r\n\t\t}\r\n\t\telse if( ( net_man->GetLastError() == Net::vRES_ERROR_DEVICE_NOT_CONNECTED ) ||\r\n\t\t\t\t ( net_man->GetLastError() == Net::vRES_ERROR_UNKNOWN_DEVICE ))\r\n\t\t{\r\n\t\t\tScript::CStruct* pStructure;\r\n\t\t\t\r\n\t\t\tpStructure = new Script::CStruct;\r\n\t\t\t\r\n\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_error_not_detected\" ));\r\n\t\t\tScript::RunScript( \"create_net_startup_error_dialog\", pStructure );\r\n\r\n\t\t\tdelete pStructure;\r\n\t\t}\r\n\t\telse if( net_man->GetLastError() == Net::vRES_ERROR_DHCP )\r\n\t\t{\r\n\t\t\tScript::CStruct* pStructure;\r\n\t\t\t\r\n\t\t\tpStructure = new Script::CStruct;\r\n\t\t\t\r\n\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_error_dhcp_error\" ));\r\n\t\t\tScript::RunScript( \"create_net_startup_error_dialog\", pStructure );\r\n\r\n\t\t\tdelete pStructure;\r\n\t\t}\r\n\t\telse if( net_man->GetLastError() == Net::vRES_ERROR_DEVICE_CHANGED )\r\n\t\t{\r\n\t\t\tScript::CStruct* pStructure;\r\n\t\t\t\r\n\t\t\tpStructure = new Script::CStruct;\r\n\t\t\t\r\n\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_error_changed_device\" ));\r\n\t\t\tScript::RunScript( \"create_net_startup_error_dialog\", pStructure );\r\n\r\n\t\t\tdelete pStructure;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tScript::CStruct* pStructure;\r\n\t\t\t\r\n\t\t\tpStructure = new Script::CStruct;\r\n\t\t\t\r\n\t\t\tpStructure->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_error_general_error\" ));\r\n\t\t\tScript::RunScript( \"create_net_startup_error_dialog\", pStructure );\r\n\r\n\t\t\tdelete pStructure;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{   \r\n\t\tScript::CStruct* pParams;\r\n\r\n\t\tScript::RunScript( \"dialog_box_exit\" );\r\n\t\t//Script::RunScript( \"launch_network_select_menu\" );\r\n\t\t\r\n        pParams = new Script::CStruct;\r\n\r\n\t\tpParams->AddChecksum( \"change_gamemode\", Script::GenerateCRC( \"change_gamemode_net\" ));\r\n\t\tScript::RunScript( \"launch_select_skater_menu\", pParams );\r\n\t\t\r\n\t\tdelete pParams;\r\n\t}\r\n\r\n\tdelete s_network_test_task;\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic\tvoid\ts_second_controller_check_code( const Tsk::Task< int > &task )\r\n{\r\n\t// Get the second controller.\r\n\t SIO::Manager * pSioMan =  SIO::Manager::Instance();\r\n\tSIO::Device *pFirstController=pSioMan->GetDeviceByIndex(0);\r\n\tSIO::Device *pSecondController=pSioMan->GetDeviceByIndex(1);\r\n\t\r\n#ifdef __PLAT_XBOX__\r\n\tint num_plugged_devices;\r\n\tSIO::Device *pThirdController=pSioMan->GetDeviceByIndex(2);\r\n\tSIO::Device *pFourthController=pSioMan->GetDeviceByIndex(3);\r\n\t\r\n\tnum_plugged_devices = 0;\r\n\tif( pFirstController->IsPluggedIn())\r\n\t{\r\n\t\tnum_plugged_devices++;\r\n\t}\r\n\tif( pSecondController->IsPluggedIn())\r\n\t{\r\n\t\tnum_plugged_devices++;\r\n\t}\r\n\tif( pThirdController->IsPluggedIn())\r\n\t{\r\n\t\tnum_plugged_devices++;\r\n\t}\r\n\tif( pFourthController->IsPluggedIn())\r\n\t{\r\n\t\tnum_plugged_devices++;\r\n\t}\r\n\r\n\tif( num_plugged_devices >= 2 )\r\n\t{\r\n\t\tScript::RunScript( \"enable_two_player_option\" );\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tScript::RunScript( \"disable_two_player_option\" );\r\n\t}         \r\n#else\r\n\tif (pSecondController->IsPluggedIn() && pFirstController->IsPluggedIn())\r\n\t{\r\n\t\tScript::RunScript( \"enable_two_player_option\" );\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tScript::RunScript( \"disable_two_player_option\" );\r\n\t}         \r\n#endif\r\n#ifdef __PLAT_XBOX__\r\n\tDWORD result;\r\n\tstatic Tmr::Time s_last_link_test;\r\n\t\r\n\tif(( Tmr::GetTime() - s_last_link_test ) >= Tmr::Seconds( 1 ))\r\n\t{\r\n\t\tresult = XNetGetEthernetLinkStatus();\r\n        if(( result & XNET_ETHERNET_LINK_ACTIVE ) == 0 )\r\n\t\t{\r\n\t\t\tScript::RunScript( \"disable_system_link_option\" );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tScript::RunScript( \"enable_system_link_option\" );\r\n\t\t}\r\n\t\ts_last_link_test = Tmr::GetTime();\r\n\t}\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\nstatic bool SetupNetworkDeviceDialogHandler( Front::EDialogBoxResult Result )\r\n{\r\n\t\r\n\tswitch (Result)\r\n\t{\r\n\t\tcase Front::DB_YES:\r\n\t\t{\r\n\t\t\tMdl::FrontEnd* front = Mdl::FrontEnd::Instance();\r\n\t\t\tFront::MenuFactory* menu_factory = Front::MenuFactory::Instance();\r\n\t\t\tFront::DialogBox* dlg;\r\n\t\t\t \r\n\t\t\tdlg = front->GetDialogBox();\r\n\t\t\tdlg->GoBack();\r\n\t\t\t\t\t\r\n\t\t\tFront::MenuEvent event;\r\n\t\t\tevent.SetTypeAndTarget( Front::MenuEvent::vLINK, Script::GenerateCRC(\"net_network_setup_menu\") );\r\n\t\t\tmenu_factory->LaunchEvent(&event);\r\n\t\t\t\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\r\n\treturn true;\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool ScriptDummyCommand(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// C++ version of the script command\t\r\nbool SetActiveCamera(uint32 id, int viewport, bool move_to_current)\r\n{\r\n\tObj::CCompositeObject *p_obj = (Obj::CCompositeObject *)Obj::CCompositeObjectManager::Instance()->GetObjectByID(id);\r\n\tif (!p_obj)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tObj::CCameraComponent * p_cam_comp = GetCameraComponentFromObject(p_obj); \r\n\t\r\n\tif (p_cam_comp)\r\n\t{\r\n\t\t// Move this camera to the current camera position.  Useful for seamlessly \r\n\t\t// transitioning between cameras\r\n\t\tif (move_to_current)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(Nx::CViewportManager::sGetActiveCamera(viewport), (\"No active camera for viewport %d\\n\",viewport));\r\n\t\t\tp_obj->m_matrix = Nx::CViewportManager::sGetActiveCamera(viewport)->GetMatrix();\r\n\t\t\tp_obj->m_pos = Nx::CViewportManager::sGetActiveCamera(viewport)->GetPos();\t\t\t\r\n\t\t\tp_cam_comp->Update();  // bit dodgy...  force the camera to update itself from the parent object\r\n\t\t}\r\n\t\t\r\n\t\tNx::CViewportManager::sSetCamera( viewport, p_cam_comp->GetCamera() );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Message(\"WARNING:  Trying to set camera from object with no camera component\");\r\n\t}\r\n\r\n#if 0\r\n// this is not needed any more, as the proxim trigger component has been deprecated in favour \r\n// of using whatever camera directly\t\r\n\t// deactivate all proxim trigger components with this viewport on other objects with cameras and activate any proxim trigger on the new camera object\r\n\tObj::CProximTriggerComponent* p_prox_comp\r\n\t\t= static_cast< Obj::CProximTriggerComponent* >(Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType(CRC_PROXIMTRIGGER));\r\n\twhile (p_prox_comp)\r\n\t{\r\n\t\tObj::CCameraComponent* p_peer_cam_comp = GetCameraComponentFromObject(p_prox_comp->GetObject());\r\n\t\t\r\n\t\tif (p_peer_cam_comp)\r\n\t\t{\r\n\t\t\tif (p_peer_cam_comp == p_cam_comp)\r\n\t\t\t{\r\n\t\t\t\tp_prox_comp->SetActive();\r\n\t\t\t\tp_prox_comp->SetViewport(viewport);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif (p_prox_comp->GetViewport() == viewport)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_prox_comp->SetInactive();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tp_prox_comp = static_cast< Obj::CProximTriggerComponent* >(p_prox_comp->GetNextSameType());\r\n\t}\r\n\r\n\t// K: If a different camera is switched to when the game is paused it could be that the geometry\r\n\t// it is looking at was switched off by the previous camera. So refresh the proxim component\r\n\t// to make sure it switches back on.\r\n\t// (This fixes a bug when scrolling through the view-gaps menu, where geometry was switching off)\r\n\tp_prox_comp=GetProximTriggerComponentFromObject(p_obj);\r\n\tif (p_prox_comp)\r\n\t{\r\n\t\tp_prox_comp->ProximUpdate();\r\n\t}\t\r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Waits for n CScript::Update calls.                             */\r\n/******************************************************************/\r\n\r\n// @script | Wait | Waits for a period of time, where the time can be specified in various units. <nl>\r\n// For example:  Wait 1200       By default, the units are milliseconds, so \r\n// this will wait for 1.2 seconds <nl>\r\n// Wait 2.1 seconds     This will wait for 2.1 seconds. <nl>\r\n// Wait 60 frames       This will wait for 60 sixtieths of a second, regardless of the framerate. <nl>\r\n// Wait 60 gameframes       This will wait for exactly 60 logic calls, \r\n// so the actual time it takes will depend on the current framerate. <nl>\r\n// In all the above, the units do not have to be plural, so one could type \r\n// Wait 1 second instead of Wait 1 seconds\r\n// @parm float |  | number of units to wait\r\n// @flag seconds | measure time in seconds\r\n// @flag frames | measure time in frames\r\n// @flag gameframes | measure time in gameframes \r\nbool ScriptWait(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tfloat Period=0.0f;\r\n\tpParams->GetFloat(NONAME,&Period);\r\n\t\r\n\tif (pParams->ContainsFlag(0xd029f619/*\"seconds\"*/) || pParams->ContainsFlag(0x49e0ee96/*\"second\"*/))\r\n\t{\r\n\t\tpScript->WaitTime((int)(Period*1000.0f));\r\n\t\treturn true;\r\n\t}\t\r\n\r\n\tif (pParams->ContainsFlag(0xfc37df05/*\"gameframe\"*/) || pParams->ContainsFlag(0xb99ae3d6/*\"gameframes\"*/) || pParams->ContainsFlag(0xdcd4ce73/*\"game\"*/))\r\n\t{\r\n\t\tpScript->Wait((int)Period);\r\n\t\treturn true;\r\n\t}\t\r\n\r\n\tif (pParams->ContainsFlag(0x4a07c332/*\"frame\"*/) || pParams->ContainsFlag(0x19176c5/*\"frames\"*/))\r\n\t{\r\n\t\tpScript->WaitTime((int)(Period*1000.0f/60.0f)); // This should NOT be changed for PAL, as Tmr::GetTime accounts for PAL\r\n\t\treturn true;\r\n\t}\t\t\r\n\r\n\tif (pParams->ContainsFlag(0xecaa3345/*\"one_per_frame\"*/))\r\n\t{\r\n\t\tpScript->WaitOnePerFrame((int)Period);\r\n\t\treturn true;\r\n\t}\t\r\n\t\r\n\r\n\t\r\n\tpScript->WaitTime((int)Period);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*  Added for testing if statements, may be useful anyway though  */\r\n/******************************************************************/\r\n\r\n// @script | IsZero | added for testing if statements.  may be useful\r\nbool ScriptIsZero(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\t\r\n\tint Val=0;\r\n\tpParams->GetInteger(NONAME,&Val);\r\n\tif (Val==0)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | CastToInteger | If a parameter with the passed name exists and is a float,\r\n// this will cast it down to an integer.\r\n// So for example, if x=3.141, after calling CastToInteger x, x will be 3.\r\n// @uparmopt name | The name of the parameter to be cast down\r\nbool ScriptCastToInteger(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 param_name=0;\r\n\tif (!pParams->GetChecksum(NONAME,&param_name))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tfloat v=0.0f;\r\n\tif (!pScript->GetParams()->GetFloat(param_name,&v))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Need to remove the parameter first, otherwise we will end up with both an integer\r\n\t// and a float parameter with the same name. Components are only automatically replaced if\r\n\t// the new component has the same name and type.\r\n\tpScript->GetParams()->RemoveComponent(param_name);\r\n\tpScript->GetParams()->AddInteger(param_name,(int)v);\r\n\treturn true;\r\n}\r\n\r\n// @script bool | StringToInteger | If a parameter with the passed name exists and is a string,\r\n// this will convert it to a integer.\r\n// So for example, if x=\"123\", after calling StringToInteger x, x will be 123.\r\n// @uparmopt name | The name of the string parameter to be converted.\r\nbool ScriptStringToInteger(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 param_name=0;\r\n\tif (!pParams->GetChecksum(NONAME,&param_name))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tconst char *p_string=\"\";\r\n\tif (!pScript->GetParams()->GetString(param_name,&p_string))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Need to remove the parameter first, otherwise we will end up with both an integer\r\n\t// and a string parameter with the same name. Components are only automatically replaced if\r\n\t// the new component has the same name and type.\r\n\tpScript->GetParams()->RemoveComponent(param_name);\r\n\t\r\n\tint v=0;\r\n\tint len=strlen(p_string);\r\n\tconst char *p_ch=p_string;\r\n\tfor (int i=0; i<len; ++i)\r\n\t{\r\n\t\tDbg_MsgAssert(*p_ch>='0' && *p_ch<='9',(\"\\n%s\\nNon-numeric char in '%s'\",pScript->GetScriptInfo(),p_string));\r\n\t\tv=v*10+*p_ch++-'0';\r\n\t}\r\n\t\r\n\tpScript->GetParams()->AddInteger(param_name,(int)v);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | IntegerEquals | Returns true if the two values equal\r\n// @parmopt int | a | 0 | First value\r\n// @parmopt int | b | 0 | Second value\r\nbool ScriptIntegerEquals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint a = 0;\r\n\tpParams->GetInteger( CRCD(0x174841bc,\"a\"), &a );\r\n\t\r\n\tint b = 0;\r\n\tpParams->GetInteger( CRCD(0x8e411006,\"b\"), &b );\r\n\t\r\n\treturn ( a == b );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | ChecksumEquals | Returns true if two checksums are equal\r\n// @parmopt name | a | 0 (checksum value) | First name\r\n// @parmopt name | b | 0 (checksum value) | Second name\r\nbool ScriptChecksumEquals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\tuint32 a=0;\r\n\tpParams->GetChecksum(\"a\",&a);\r\n\tuint32 b=0;\r\n\tpParams->GetChecksum(\"b\",&b);\r\n\r\n\treturn a==b;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | StringEquals | Returns true if two strings are equal\r\n// @parm string | a | First string\r\n// @parm string | b | Secnond string\r\nbool ScriptStringEquals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\tconst char* a;\r\n\tpParams->GetText(\"a\",&a,true);\r\n\tconst char* b;\r\n\tpParams->GetText(\"b\",&b,true);\r\n\r\n\treturn Script::GenerateCRC(a)==Script::GenerateCRC(b);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | ArrayContains | Returns true if the array contains an\r\n// element equal to the variable. <nl>\r\n// Example:  ArrayContains array=some_int_array contains=4 <nl>\r\n// ArrayContains array=some_string_array contains=\"some_string\"\r\n// @parm array | array | The array to search\r\n// @parm | contains | The element to search for.  Must match array type\r\nbool ScriptArrayContains(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\tScript::CArray* pArray;\r\n\tpParams->GetArray( \"array\", &pArray, true );\r\n\r\n\tuint8 array_type = pArray->GetType();\r\n\r\n\tfor ( uint32 i = 0; i < pArray->GetSize(); i++ )\r\n\t{\r\n\t\tswitch ( array_type )\r\n\t\t{\r\n\t\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\t{\r\n\t\t\t\tint desiredInteger;\r\n\t\t\t\tpParams->GetInteger( \"contains\", &desiredInteger, true );\r\n\t\t\t\tif ( desiredInteger == pArray->GetInt( i ) )\r\n\t\t\t\t\treturn true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t\t{\r\n\t\t\t\tuint32 desiredChecksum;\r\n\t\t\t\tpParams->GetChecksum( \"contains\", &desiredChecksum, true );\r\n\t\t\t\tif ( desiredChecksum == pArray->GetNameChecksum( i ) )\r\n\t\t\t\t\treturn true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase ESYMBOLTYPE_STRING:\r\n\t\t\t{\r\n\t\t\t\tconst char* pDesiredString;\r\n\t\t\t\tpParams->GetText( \"contains\", &pDesiredString, true );\r\n\t\t\t\t// Changed to use stricmp instead of GenerateCRC because GenerateCRC sees \\ and / as\r\n\t\t\t\t// being the same character.\r\n\t\t\t\tif (stricmp(pDesiredString, pArray->GetString( i )) == 0)\r\n\t\t\t\t\treturn true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"This data type is not yet supported by ArrayContains\" ) );\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// item was not found\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetArraySize | returns the number of elements in the specified structure\r\n// @parm | array_size | return value for array size\r\nbool ScriptGetArraySize(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tScript::CArray* pArray;\r\n\t\r\n\tpParams->GetArray( NONAME, &pArray, Script::ASSERT );\r\n\r\n\t// Add support for higher dimensional arrays\r\n\tuint32 index = 0;\r\n\tif(pParams->GetInteger(CRCD(0xba453b9,\"index1\"),(int*)&index, Script::NO_ASSERT))\r\n\t{\r\n\t\tpArray = pArray->GetArray(index);\r\n\r\n\t\tif(pParams->GetInteger(CRCD(0x92ad0203,\"index2\"),(int*)&index, Script::NO_ASSERT))\r\n\t\t{\r\n\t\t\tpArray = pArray->GetArray(index);\r\n\r\n\t\t\tif(pParams->GetInteger(CRCD(0xe5aa3295,\"index3\"),(int*)&index, Script::NO_ASSERT))\r\n\t\t\t{\r\n\t\t\t\tpArray = pArray->GetArray(index);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tpScript->GetParams()->AddInteger( \"array_size\", pArray->GetSize() );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetArrayElement | Changes the value of an element of an array.\r\n// @parm name | ArrayName | The name of the array in the current script's parameters whose\r\n// value is to be changed.\r\n// @parm int | Index | The index of the array element whose value is to be changed.\r\n// @parm int | NewValue | The new value for the element. The type of this value must match the\r\n// type of the array, so it is not necessarily an integer. If the type does not match that of\r\n// the array it will assert.\r\nbool ScriptSetArrayElement(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// TODO: Most of this code should really be in the CArray class. Need to go over that\r\n\t// class to make it easier to manipulate arrays safely. (resize, etc)\r\n\t\r\n\t// Get a pointer to the CArray that is to be modified.\r\n\t// It will be in the script's parameters.\r\n\tuint32 array_name=0;\r\n\tpParams->GetChecksum(\"ArrayName\",&array_name,Script::ASSERT);\r\n\tScript::CArray *p_array=NULL;\r\n\tpScript->GetParams()->GetArray(array_name,&p_array,Script::ASSERT);\r\n\t\r\n\t// Get the index of the element to be changed.\r\n\tuint32 index=0;\r\n\tpParams->GetInteger(\"Index\",(int*)&index,Script::ASSERT);\r\n\r\n\t// Find the new value which is to be written into the array.\t\r\n\tScript::CComponent *p_new_value=pParams->FindNamedComponentRecurse(CRCD(0x4b40630d,\"NewValue\"));\r\n\tDbg_MsgAssert(p_new_value,(\"\\n%s\\nMissing NewValue parameter in call to SetArrayElement\",pScript->GetScriptInfo()));\r\n\t// Resolve the componentn in case the new value is referring to some global.\r\n\tScript::ResolveNameComponent(p_new_value);\r\n\t\r\n\t// Now make a copy of the component. This is because it may contain a pointer, eg a pointer to\r\n\t// a struct, vector, string etc, and that entity may only exist temporarily.\r\n\t// CopyComponent will create a new pointer which will be safe to delete later.\r\n\tScript::CComponent *p_copy=new Script::CComponent;\r\n\tScript::CopyComponent(p_copy,p_new_value);\r\n\r\n\t// Check that the type of the new value is consistent with the type of the array.\r\n\tif (p_array->GetType()==ESYMBOLTYPE_FLOAT && \r\n\t\tp_copy->mType==ESYMBOLTYPE_INTEGER)\r\n\t{\r\n\t\t// It's OK to write an integer value into an array of floats so don't assert in this case.\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(p_copy->mType==p_array->GetType(),(\"Array type of %s does not match the NewValue type of %s in call to SetArrayElement\",Script::GetTypeName(p_array->GetType()),Script::GetTypeName(p_copy->mType)));\r\n\t}\r\n\t\r\n\t// Write the new value into the array.\r\n\tswitch (p_array->GetType())\r\n\t{\r\n\tcase ESYMBOLTYPE_INTEGER:\r\n\t\tp_array->SetInteger(index,p_copy->mIntegerValue);\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_FLOAT:\r\n\t\tif (p_copy->mType==ESYMBOLTYPE_FLOAT)\r\n\t\t{\r\n\t\t\tp_array->SetFloat(index,p_copy->mFloatValue);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(p_copy->mType==ESYMBOLTYPE_INTEGER,(\"Eh ?\"));\r\n\t\t\tp_array->SetFloat(index,(float)p_copy->mIntegerValue);\r\n\t\t}\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_NAME:\r\n\t\tp_array->SetChecksum(index,p_copy->mChecksum);\r\n\t\tbreak;\r\n\t// Now for the types that are referenced by a pointer.\r\n\t// In each of these cases, first the existing pointer in the array gets deleted.\r\n\t// The the pointer to the array of pointers is got, and the new pointer written in.\r\n\t// Cannot use the regular SetString, SetVector etc functions because they all assert if\r\n\t// the existing pointer is not NULL, to catch memory leaks.\r\n    case ESYMBOLTYPE_STRING:\r\n\t{\r\n\t\tScript::DeleteString(p_array->GetString(index));\r\n\t\tchar **pp_strings=(char**)p_array->GetArrayPointer();\r\n\t\t// Need to do a bounds check since not using SetString\r\n\t\tDbg_MsgAssert(index<p_array->GetSize(),(\"Bad index of %d sent to SetArrayElement, array size is %d\",index,p_array->GetSize()));\r\n\t\tpp_strings[index]=p_copy->mpString;\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_LOCALSTRING:\r\n\t{\r\n\t\tScript::DeleteString(p_array->GetString(index));\r\n\t\tchar **pp_strings=(char**)p_array->GetArrayPointer();\r\n\t\tDbg_MsgAssert(index<p_array->GetSize(),(\"Bad index of %d sent to SetArrayElement, array size is %d\",index,p_array->GetSize()));\r\n\t\tpp_strings[index]=p_copy->mpLocalString;\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_PAIR:\r\n\t{\r\n\t\tdelete p_array->GetPair(index);\r\n\t\tScript::CPair **pp_pairs=(Script::CPair**)p_array->GetArrayPointer();\r\n\t\tDbg_MsgAssert(index<p_array->GetSize(),(\"Bad index of %d sent to SetArrayElement, array size is %d\",index,p_array->GetSize()));\r\n\t\tpp_pairs[index]=p_copy->mpPair;\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_VECTOR:\r\n\t{\r\n\t\tdelete p_array->GetVector(index);\r\n\t\tScript::CVector **pp_vectors=(Script::CVector**)p_array->GetArrayPointer();\r\n\t\tDbg_MsgAssert(index<p_array->GetSize(),(\"Bad index of %d sent to SetArrayElement, array size is %d\",index,p_array->GetSize()));\r\n\t\tpp_vectors[index]=p_copy->mpVector;\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_STRUCTURE:\r\n\t{\r\n\t\tdelete p_array->GetStructure(index);\r\n\t\tScript::CStruct **pp_structs=(Script::CStruct**)p_array->GetArrayPointer();\r\n\t\tDbg_MsgAssert(index<p_array->GetSize(),(\"Bad index of %d sent to SetArrayElement, array size is %d\",index,p_array->GetSize()));\r\n\t\tpp_structs[index]=p_copy->mpStructure;\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_ARRAY:\r\n\t{\r\n\t\tScript::CArray *p_old_array=p_array->GetArray(index);\r\n\t\tScript::CleanUpArray(p_old_array);\r\n\t\tdelete p_old_array;\r\n\t\tScript::CArray **pp_arrays=(Script::CArray**)p_array->GetArrayPointer();\r\n\t\tDbg_MsgAssert(index<p_array->GetSize(),(\"Bad index of %d sent to SetArrayElement, array size is %d\",index,p_array->GetSize()));\r\n\t\tpp_arrays[index]=p_copy->mpArray;\r\n\t\tbreak;\r\n\t}\t\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0,(\"Unsupported array type of %s in SetArrayElement\",Script::GetTypeName(p_array->GetType())));\r\n\t\tbreak;\t\t\r\n\t}\r\n\t\r\n\t// Now delete the temporary component, but set any pointer in it to NULL first since the\r\n\t// pointer has been given to the array.\r\n\tp_copy->mUnion=0;\r\n\tdelete p_copy;\r\n\t\r\n\treturn true;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Get2DarrayData | \r\nbool ScriptGet2DArrayData(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 array_name=0;\r\n\tpParams->GetChecksum(CRCD(0x8f61d602,\"ArrayName\"),&array_name,Script::ASSERT);\r\n\tScript::CArray *p_array1=NULL;\r\n\tif(!pScript->GetParams()->GetArray(array_name,&p_array1,Script::NO_ASSERT))\r\n\t{\r\n\t\tp_array1 = Script::GetArray( array_name,Script::ASSERT);\r\n\t}\r\n\r\n\t// Get the index of the element\r\n\tuint32 index1=0;\r\n\tpParams->GetInteger(CRCD(0xba453b9,\"Index1\"),(int*)&index1,Script::ASSERT);\r\n\r\n\t// Get the index of the element\r\n\tuint32 index2=0;\r\n\tpParams->GetInteger(CRCD(0x92ad0203,\"Index2\"),(int*)&index2,Script::ASSERT);\r\n\r\n\r\n\tDbg_MsgAssert(index1<p_array1->GetSize(),(\"Bad index of %d sent to Get2DArrayData, array size is %d\",index1,p_array1->GetSize()));\r\n\tScript::CArray *p_array2=p_array1->GetArray(index1);\r\n\r\n\tDbg_MsgAssert(index2<p_array2->GetSize(),(\"Bad index of %d sent to Get2DArrayData, array size is %d\",index2,p_array2->GetSize()));\r\n\r\n\tswitch (p_array2->GetType())\r\n\t{\r\n\tcase ESYMBOLTYPE_INTEGER:\r\n\t\tpScript->GetParams()->AddInteger( CRCD(0x6820459a,\"val\"), p_array2->GetInteger(index2) );\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_FLOAT:\r\n\t\tpScript->GetParams()->AddFloat( CRCD(0x6820459a,\"val\"), p_array2->GetFloat(index2) );\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_NAME:\r\n\t\tpScript->GetParams()->AddChecksum( CRCD(0x6820459a,\"val\"), p_array2->GetChecksum(index2) );\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_STRING:\r\n\t{\r\n\t\tpScript->GetParams()->AddString( CRCD(0x6820459a,\"val\"), p_array2->GetString(index2) );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_LOCALSTRING:\r\n\t{\r\n\t\tpScript->GetParams()->AddString( CRCD(0x6820459a,\"val\"), p_array2->GetString(index2) );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_PAIR:\r\n\t{\t\r\n\t\tScript::CPair *p_pair = p_array2->GetPair(index2);\r\n\t\tpScript->GetParams()->AddPair( CRCD(0x6820459a,\"val\"), p_pair->mX, p_pair->mY );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_VECTOR:\r\n\t{\r\n\t\tScript::CVector *p_vector = p_array2->GetVector(index2);\r\n\t\t\r\n\t\tpScript->GetParams()->AddVector( CRCD(0x6820459a,\"val\"), p_vector->mX, p_vector->mY, p_vector->mZ );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_STRUCTURE:\r\n\t{\r\n\t\tpScript->GetParams()->AddStructure( CRCD(0x6820459a,\"val\"), p_array2->GetStructure(index2) );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_ARRAY:\r\n\t{\r\n\t\tpScript->GetParams()->AddArray( CRCD(0x6820459a,\"val\"), p_array2->GetArray(index2) );\r\n\t\tbreak;\r\n\t}\t\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0,(\"Unsupported array type of %s\",Script::GetTypeName(p_array2->GetType())));\r\n\t\tbreak;\t\t\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Get3DarrayData | \r\nbool ScriptGet3DArrayData(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 array_name=0;\r\n\tpParams->GetChecksum(CRCD(0x8f61d602,\"ArrayName\"),&array_name,Script::ASSERT);\r\n\tScript::CArray *p_array1=NULL;\r\n\tif(!pScript->GetParams()->GetArray(array_name,&p_array1,Script::NO_ASSERT))\r\n\t{\r\n\t\tp_array1 = Script::GetArray( array_name,Script::ASSERT);\r\n\t}\r\n\r\n\t// Get the index of the element\r\n\tuint32 index1=0;\r\n\tpParams->GetInteger(CRCD(0xba453b9,\"Index1\"),(int*)&index1,Script::ASSERT);\r\n\r\n\t// Get the index of the element\r\n\tuint32 index2=0;\r\n\tpParams->GetInteger(CRCD(0x92ad0203,\"Index2\"),(int*)&index2,Script::ASSERT);\r\n\r\n\t// Get the index of the element\r\n\tuint32 index3=0;\r\n\tpParams->GetInteger(CRCD(0xe5aa3295,\"Index3\"),(int*)&index3,Script::ASSERT);\r\n\r\n\tDbg_MsgAssert(index1<p_array1->GetSize(),(\"Bad index of %d sent to Get3DArrayData, array size is %d\",index1,p_array1->GetSize()));\r\n\tScript::CArray *p_array2=p_array1->GetArray(index1);\r\n\r\n\tDbg_MsgAssert(index2<p_array2->GetSize(),(\"Bad index of %d sent to Get3DArrayData, array size is %d\",index2,p_array2->GetSize()));\r\n\tScript::CArray *p_array3=p_array2->GetArray(index2);\r\n\r\n\tDbg_MsgAssert(index3<p_array3->GetSize(),(\"Bad index of %d sent to Get3DArrayData, array size is %d\",index3,p_array3->GetSize()));\r\n\t\r\n\r\n\tswitch (p_array3->GetType())\r\n\t{\r\n\tcase ESYMBOLTYPE_INTEGER:\r\n\t\tpScript->GetParams()->AddInteger( CRCD(0x6820459a,\"val\"), p_array3->GetInteger(index3) );\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_FLOAT:\r\n\t\tpScript->GetParams()->AddFloat(CRCD(0x6820459a,\"val\"), p_array3->GetFloat(index3) );\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_NAME:\r\n\t\tpScript->GetParams()->AddChecksum( CRCD(0x6820459a,\"val\"), p_array3->GetChecksum(index3) );\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_STRING:\r\n\t{\r\n\t\tpScript->GetParams()->AddString( CRCD(0x6820459a,\"val\"), p_array3->GetString(index3) );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_LOCALSTRING:\r\n\t{\r\n\t\tpScript->GetParams()->AddString( CRCD(0x6820459a,\"val\"), p_array3->GetString(index3) );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_PAIR:\r\n\t{\t\r\n\t\tScript::CPair *p_pair = p_array3->GetPair(index3);\r\n\t\tpScript->GetParams()->AddPair( CRCD(0x6820459a,\"val\"), p_pair->mX, p_pair->mY );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_VECTOR:\r\n\t{\r\n\t\tScript::CVector *p_vector = p_array3->GetVector(index3);\r\n\t\t\r\n\t\tpScript->GetParams()->AddVector( CRCD(0x6820459a,\"val\"), p_vector->mX, p_vector->mY, p_vector->mZ );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_STRUCTURE:\r\n\t{\r\n\t\tpScript->GetParams()->AddStructure( CRCD(0x6820459a,\"val\"), p_array3->GetStructure(index3) );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_ARRAY:\r\n\t{\r\n\t\tpScript->GetParams()->AddArray( CRCD(0x6820459a,\"val\"), p_array3->GetArray(index3) );\r\n\t\tbreak;\r\n\t}\t\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0,(\"Unsupported array type of %s\",Script::GetTypeName(p_array3->GetType())));\r\n\t\tbreak;\t\t\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetNDarrayData | \r\nbool ScriptGetNDArrayData(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 array_name=0;\r\n\tpParams->GetChecksum(CRCD(0x8f61d602,\"ArrayName\"),&array_name,Script::ASSERT);\r\n\tScript::CArray *p_array=NULL;\r\n\tif(!pScript->GetParams()->GetArray(array_name,&p_array,Script::NO_ASSERT))\r\n\t{\r\n\t\tp_array = Script::GetArray( array_name,Script::ASSERT);\r\n\t}\r\n\r\n\tuint32 indices_name=CRCD(0xffc8e484,\"Indices\");\r\n\t//pParams->GetChecksum(\"Indices\",&indices_name,Script::ASSERT);\r\n\tScript::CArray *p_indices=NULL;\r\n\tpScript->GetParams()->GetArray(indices_name,&p_indices,Script::ASSERT);\r\n\r\n\tuint32 i = 0;\r\n\tuint32 index=0;\r\n\tfor(; i < p_indices->GetSize()-1; ++i)\r\n\t{\r\n\t\t// Get the index of the element\r\n\t\tindex = p_indices->GetInteger( i );\r\n\t\t\r\n\t\tp_array = p_array->GetArray(index);\r\n\t}\r\n\tindex = p_indices->GetInteger( i );\r\n\t\r\n\tswitch (p_array->GetType())\r\n\t{\r\n\tcase ESYMBOLTYPE_INTEGER:\r\n\t\tpScript->GetParams()->AddInteger( CRCD(0x6820459a,\"val\"), p_array->GetInteger(index) );\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_FLOAT:\r\n\t\tpScript->GetParams()->AddFloat( CRCD(0x6820459a,\"val\"), p_array->GetFloat(index) );\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_NAME:\r\n\t\tpScript->GetParams()->AddChecksum( CRCD(0x6820459a,\"val\"), p_array->GetChecksum(index) );\r\n\t\tbreak;\r\n    case ESYMBOLTYPE_STRING:\r\n\t{\r\n\t\tpScript->GetParams()->AddString( CRCD(0x6820459a,\"val\"), p_array->GetString(index) );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_LOCALSTRING:\r\n\t{\r\n\t\tpScript->GetParams()->AddString( CRCD(0x6820459a,\"val\"), p_array->GetString(index) );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_PAIR:\r\n\t{\t\r\n\t\tScript::CPair *p_pair = p_array->GetPair(index);\r\n\t\tpScript->GetParams()->AddPair( CRCD(0x6820459a,\"val\"), p_pair->mX, p_pair->mY );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_VECTOR:\r\n\t{\r\n\t\tScript::CVector *p_vector = p_array->GetVector(index);\r\n\t\t\r\n\t\tpScript->GetParams()->AddVector( CRCD(0x6820459a,\"val\"), p_vector->mX, p_vector->mY, p_vector->mZ );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_STRUCTURE:\r\n\t{\r\n\t\tpScript->GetParams()->AddStructure( CRCD(0x6820459a,\"val\"), p_array->GetStructure(index) );\r\n\t\tbreak;\r\n\t}\t\r\n    case ESYMBOLTYPE_ARRAY:\r\n\t{\r\n\t\tpScript->GetParams()->AddArray( CRCD(0x6820459a,\"val\"), p_array->GetArray(index) );\r\n\t\tbreak;\r\n\t}\t\r\n\tdefault:\r\n\t\tDbg_MsgAssert(0,(\"Unsupported array type of %s\",Script::GetTypeName(p_array->GetType())));\r\n\t\tbreak;\t\t\r\n\t}\r\n\treturn true;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AddParams | appends the given structure to the list of params\r\n// @uparmopt {} | structure to append to params\r\nbool ScriptAddParams(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->AppendStructure(pParams);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RemoveComponent | removes a component from the script's list of params\r\n// @uparm name | name of component to remove\r\nbool ScriptRemoveComponent(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 name;\r\n\tif ( !pParams->GetChecksum(\"name\", &name, Script::NO_ASSERT) )\r\n\t{\r\n\t\tpParams->GetChecksum(NONAME, &name, Script::ASSERT);\r\n\t}\r\n\r\n\tpScript->GetParams()->RemoveComponent(name);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic uint32 s_get_bottom_up_free(bool includeFrag)\r\n{\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\tMem::Heap* p_heap = mem_man.GetHeap( CRCD(0xc7800b0,\"BottomUpHeap\") );\r\n\tMem::Region* p_region = p_heap->ParentRegion();\r\n\r\n\tif (includeFrag)\r\n\t{\r\n\t\treturn p_heap->mFreeMem.m_count + p_region->MemAvailable();\r\n\t}\r\n\treturn p_region->MemAvailable();\r\n}\r\n\r\n// @script | SetScriptString | \r\nbool ScriptSetScriptString(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint index=0;\r\n\tpParams->GetInteger(CRCD(0x7f8c98fe,\"index\"),&index);\r\n\t\r\n\tconst char *p_string=\"\";\r\n\tpParams->GetString(CRCD(0x61414d56,\"string\"),&p_string);\r\n\t\r\n\tScript::SetScriptString(index,p_string);\r\n\treturn true;\r\n}\r\n\r\n// @script | GetScriptString | \r\nbool ScriptGetScriptString(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint index=0;\r\n\tpParams->GetInteger(CRCD(0x7f8c98fe,\"index\"),&index);\r\n\t\r\n\tpScript->GetParams()->AddString(CRCD(0x61414d56,\"string\"),Script::GetScriptString(index));\r\n\treturn true;\r\n}\r\n\t\r\n// @script | KenTest1 | old test of ken's\r\nbool ScriptKenTest1(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tstatic bool s_got_main_heap_free_edit=false;\r\n\tstatic uint32 s_main_heap_free_edit=0;\r\n\t\r\n\tif (pParams->ContainsFlag(CRCD(0x1a4e0ef9,\"Clear\")))\r\n\t{\r\n\t\ts_got_main_heap_free_edit=false;\r\n\t\ts_main_heap_free_edit=0;\r\n\t}\t\r\n\t\r\n\tif (!s_got_main_heap_free_edit)\r\n\t{\r\n\t\ts_main_heap_free_edit = s_get_bottom_up_free(true);\r\n\t\tprintf(\"Stored s_main_heap_free_edit\\n\");\r\n\t\ts_got_main_heap_free_edit=true;\r\n\t\treturn true;\r\n\t}\t\r\n\t\r\n#\tif !defined( __PLAT_NGC__ ) || ( defined( __PLAT_NGC__ ) && !defined( __NOPT_FINAL__ ) )\r\n\tuint32 main_heap_free_play = s_get_bottom_up_free(false);\r\n\t\r\n\tprintf(\"main_heap_pad = %d\\n\", s_main_heap_free_edit - main_heap_free_play + 200000);\r\n#endif\t\t// __NOPT_FINAL__\r\n\t\r\n\treturn true;\r\n}\r\n\r\n// Used when creating default file names in the files menu.\r\n// It appends the passed suffix, but if the result will be a string longer than MaxChars\r\n// then it will move the suffix back so that the total number of chars is never more than\r\n// MaxChars.\r\nbool ScriptAppendSuffix(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tenum\r\n\t{\r\n\t\tBUFFER_SIZE=100,\r\n\t};\t\r\n\tchar p_new_text[BUFFER_SIZE];\r\n\t\r\n\tconst char *p_text=\"\";\r\n\tpParams->GetString(CRCD(0xc4745838,\"Text\"), &p_text);\r\n\tint original_text_length=strlen(p_text);\r\n\tDbg_MsgAssert(original_text_length<BUFFER_SIZE,(\"Text '%s' too long\",p_text));\r\n\tstrcpy(p_new_text,p_text);\r\n\t\r\n\tint max_chars=15;\r\n\tpParams->GetInteger(CRCD(0xa6931595,\"MaxChars\"), &max_chars);\r\n\tDbg_MsgAssert(max_chars<BUFFER_SIZE,(\"max_chars too big\"));\r\n\t\r\n\t\r\n\tint suffix=1;\r\n\tpParams->GetInteger(CRCD(0x4a4f7821,\"suffix\"),&suffix);\r\n\t\r\n\tchar p_suffix[20];\r\n\tsprintf(p_suffix, \" %d\",suffix);\r\n\tint suffix_length=strlen(p_suffix);\r\n\tDbg_MsgAssert(suffix_length<max_chars,(\"max_chars of %d too small for suffix '%s'\",suffix_length,p_suffix));\r\n\t\r\n\tif (original_text_length + suffix_length > max_chars)\r\n\t{\r\n\t\tp_new_text[max_chars-suffix_length]=0;\r\n\t}\r\n\tstrcat(p_new_text, p_suffix);\r\n\t\r\n\r\n\tuint32 new_text_name=0;\r\n\tpParams->GetChecksum(CRCD(0x50060694,\"NewTextName\"),&new_text_name);\r\n\t\r\n\tpScript->GetParams()->AddString(new_text_name, p_new_text);\r\n\treturn true;\r\n}\r\n\r\n// @script | FindNearestRailPoint | \r\n// Used by the rail editor for snapping the cursor to the nearest rail point.\r\n// Note that for this to work CParkGenerator::GenerateOutRailSet needs to have been called at some point first.\r\n// If it were not called, this would only find the nearest edited-rail point.\r\nbool ScriptFindNearestRailPoint(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMth::Vector pos;\r\n\tpParams->GetVector(CRCD(0x7f261953,\"Pos\"),&pos,Script::ASSERT);\r\n\t\r\n\tfloat min_dist=150.0f;\r\n\tpParams->GetFloat(CRCD(0x213395f1,\"MinDist\"),&min_dist);\r\n\tfloat min_dist2=min_dist*min_dist;\r\n\r\n\tuint32 ignore_rail_id=0;\r\n\tpParams->GetChecksum(CRCD(0x288a6efe,\"IgnoreRailId\"),&ignore_rail_id);\r\n\r\n\tint ignore_rail_point_index=-1;\r\n\tpParams->GetInteger(CRCD(0xe4d305a7,\"IgnoreRailPointIndex\"),&ignore_rail_point_index);\r\n\r\n\r\n\t// Find the nearest edited-rail point\t\r\n\tMth::Vector edited_rail_nearest_point;\r\n\tfloat edited_rail_nearest_dist2=100000000.0f;\r\n\tuint32 rail_id=0;\r\n\tint rail_point_index=0;\r\n\tObj::GetRailEditor()->FindNearestRailPoint(pos,\r\n\t\t\t\t\t\t\t\t\t\t\t   &edited_rail_nearest_point, &edited_rail_nearest_dist2,\r\n\t\t\t\t\t\t\t\t\t\t\t   &rail_id,&rail_point_index,\r\n\t\t\t\t\t\t\t\t\t\t\t   ignore_rail_id, ignore_rail_point_index);\r\n\t\r\n\t// Then find the nearest rail point on the park editor level geometry.\r\n\t// CParkGenerator::GenerateOutRailSet needs to have been called at some point first for this to\r\n\t// find anything.\r\n\t// Not calling GenerateOutRailSet here because it may take a while to execute.\r\n\tMth::Vector level_nearest_point;\r\n\tfloat level_nearest_dist2=100000000.0f;\r\n\tif (pParams->ContainsFlag(CRCD(0x9c247a94,\"CheckLevelGeometry\")))\r\n\t{\r\n\t\tEd::CParkManager::sInstance()->GetGenerator()->FindNearestRailPoint(pos,&level_nearest_point,&level_nearest_dist2);\r\n\t}\t\r\n\t\r\n\tif (edited_rail_nearest_dist2 < min_dist2 ||\r\n\t\tlevel_nearest_dist2 < min_dist2)\r\n\t{\r\n\t\tMth::Vector nearest_point;\r\n\t\tif (edited_rail_nearest_dist2 < level_nearest_dist2)\r\n\t\t{\r\n\t\t\tnearest_point=edited_rail_nearest_point;\r\n\t\t\t\r\n\t\t\tpScript->GetParams()->AddChecksum(CRCD(0xa61e7cd9,\"rail_id\"),rail_id);\r\n\t\t\tpScript->GetParams()->AddInteger(CRCD(0xab3c14,\"rail_point_index\"),rail_point_index);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tnearest_point=level_nearest_point;\r\n\t\t}\t\r\n\t\tpScript->GetParams()->AddVector(CRCD(0xdf970a05,\"NearestPos\"),nearest_point[X],nearest_point[Y],nearest_point[Z]);\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\nbool ScriptGetTime(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#ifdef __PLAT_NGPS__\r\n/*\r\n\tsceCdCLOCK rtc;\r\n\tsceScfGetLocalTimefromRTC(&rtc);\r\n\r\n\tpScript->GetParams()->AddInteger(\"Hours\",rtc.hour);\t\r\n\tpScript->GetParams()->AddInteger(\"Minutes\",rtc.minute);\t\r\n\tpScript->GetParams()->AddInteger(\"Seconds\",rtc.second);\t\r\n*/\t\r\n#endif\r\n\treturn true;\r\n}\r\n\r\nbool ScriptGetDate(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#ifdef __PLAT_NGPS__\r\n/*\r\n\tsceCdCLOCK rtc;\r\n\tsceScfGetLocalTimefromRTC(&rtc);\r\n\r\n\tpScript->GetParams()->AddInteger(\"Day\",rtc.day);\t\r\n\tpScript->GetParams()->AddInteger(\"Month\",rtc.month);\t\r\n\tpScript->GetParams()->AddInteger(\"Year\",rtc.year);\t\r\n*/\t\r\n#endif\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetObNearestScreenCoord(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptRandomize(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMth::InitialRand(Tmr::ElapsedTime(0));\r\n\treturn true;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | KenTest2 | old test of Ken's\r\nbool ScriptKenTest2(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t//Ed::CParkEditor::Instance()->PlayModeGapManagerChecks();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic Tmr::Time sStartTime=0;\r\nbool ScriptResetTimer(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tsStartTime=Tmr::ElapsedTime(0);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptTimeGreaterThan(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tfloat t=0.0f;\r\n\tpParams->GetFloat(NONAME,&t);\r\n\t\r\n\tif (Tmr::ElapsedTime(sStartTime)>t*1000.0f)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetStartTime(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->AddInteger(CRCD(0xd16b61e6, \"StartTime\"), Tmr::GetTime());\r\n\treturn true;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetElapsedTime(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint start_time;\r\n\tpParams->GetInteger(CRCD(0xd16b61e6, \"StartTime\"), &start_time);\r\n\tpScript->GetParams()->AddInteger(CRCD(0x3eb3566b, \"ElapsedTime\"), Tmr::ElapsedTime(start_time));\r\n\treturn true;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RemoveParameter | Removes the parameter with the given name. If no such parameter\r\n// exists, it will do nothing.\r\n// @uparmopt name | The name of the parameter to be removed\r\nbool ScriptRemoveParameter(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 name=0;\r\n\tpParams->GetChecksum(NONAME,&name);\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tconst char *p_foo=NULL;\r\n\tDbg_MsgAssert(!pParams->GetString(NONAME,&p_foo),(\"\\n%s\\nRemoveParameter requires a name, not a string\",pScript->GetScriptInfo()));\r\n\t#endif\r\n\t\r\n\tCStruct *p_params=pScript->GetParams();\r\n\tDbg_MsgAssert(p_params,(\"NULL p_params ??\"));\r\n\tp_params->RemoveComponent(name);\r\n\tp_params->RemoveFlag(name);\r\n\treturn true;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetRandomValue | Chooses a random number in a specified range. The returned value can \r\n// be selected to be either an integer or a floating point value.\r\n// @parmopt name | name | 0 | The name to be given to the random value parameter. For example, \r\n// name=foo will make the random number be assigned to a parameter called foo.\r\n// @parmopt float | a | 0.0 | The first value in the range.\r\n// @parmopt float | b | 0.0 | The second value in the range. The first value does not have to be smaller than the second.\r\n// @parmopt int | Resolution | 1000 | The number of possible floating point values that could be returned.\r\n// For example, if the range is a=1, b=2 and the resolution is set to 3, it will return either 1, 1.5 or 2\r\n// @flag Integer | Return an integer value in the given range, inclusive of the end values.\r\n// For example, if the range is a=1, b=3 it will return either 1, 2 or 3. Note that a and b need to be \r\n// integers instead of floats in this case. \r\nbool ScriptGetRandomValue(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 param_name=0;\r\n\tpParams->GetChecksum(CRCD(0xa1dc81f9,\"Name\"),&param_name);\r\n\t\t\r\n\tif (pParams->ContainsFlag(CRCD(0xa5f054f4,\"Integer\")))\r\n\t{\r\n\t\tint a=0;\r\n\t\tint b=0;\r\n\t\tpParams->GetInteger(CRCD(0x174841bc,\"a\"),&a);\r\n\t\tpParams->GetInteger(CRCD(0x8e411006,\"b\"),&b);\r\n\t\tif (a>b)\r\n\t\t{\r\n\t\t\tint t=a;\r\n\t\t\ta=b;\r\n\t\t\tb=t;\r\n\t\t}\t\r\n\t\tpScript->GetParams()->AddInteger(param_name,a+Mth::Rnd(b-a+1));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint resolution=1000;\r\n\t\tpParams->GetInteger(CRCD(0x22cf075,\"Resolution\"),&resolution);\r\n\t\tDbg_MsgAssert(resolution>=2,(\"Resolution needs to be at least 2\"));\r\n\r\n\t\tfloat a=0.0f;\r\n\t\tfloat b=0.0f;\r\n\t\tpParams->GetFloat(CRCD(0x174841bc,\"a\"),&a);\r\n\t\tpParams->GetFloat(CRCD(0x8e411006,\"b\"),&b);\r\n\t\t\r\n\t\tpScript->GetParams()->AddFloat(param_name,a+Mth::Rnd(resolution)*(b-a)/(resolution-1));\r\n\t}\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetConfig | Allows various things in the config module to be changed at runtime.\r\n// @parmopt name | Language | | Can be one of English, French or German\r\n// @flag CD | Use CD for file loading\r\n// @flag NotCD | Use host for file loading\r\n// @flag GotExtraMemory | Switch on use of extra memory\r\n// @flag NoExtraMemory | Switch off use of extra memory\r\n// @flag Pal | Be in PAL mode\r\n// @flag NTSC | Be in NTSC mode\r\n// @parmopt int | FrameRate | | Frame rate to use, 50 or 60\r\nbool ScriptSetConfig(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 language_checksum=0;\r\n\tpParams->GetChecksum(CRCD(0x2b248e4a,\"Language\"),&language_checksum);\r\n\t\r\n\tswitch (language_checksum)\r\n\t{\r\n\tcase 0xd37cfdff: // English\r\n\t\tConfig::gLanguage=Config::LANGUAGE_ENGLISH;\r\n\t\tbreak;\r\n\tcase 0x508a31a1: // French\r\n\t\tConfig::gLanguage=Config::LANGUAGE_FRENCH;\r\n\t\tbreak;\r\n\tcase 0x5dcbbf5e: // German\r\n\t\tConfig::gLanguage=Config::LANGUAGE_GERMAN;\r\n\t\tbreak;\r\n\tcase 0xcbe70acb: // Spanish\r\n\t\tConfig::gLanguage=Config::LANGUAGE_FRENCH;\r\n\t\tbreak;\r\n\tcase 0xa8469630: // Italian\r\n\t\tConfig::gLanguage=Config::LANGUAGE_GERMAN;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\t\r\n\tif (pParams->ContainsFlag(CRCD(0xba297025,\"cd\")))\r\n\t{\r\n\t\tif (!Config::gCD)\r\n\t\t{\r\n\t\t\tFile::InstallFileSystem();\r\n\t\t}\r\n\t\tConfig::gCD=true;\r\n\t}\t\r\n\tif (pParams->ContainsFlag(CRCD(0x2b6d7b32,\"notcd\")))\r\n\t{\r\n\t\tif (Config::gCD)\r\n\t\t{\r\n\t\t\tFile::UninstallFileSystem();\r\n\t\t}\r\n\t\tConfig::gCD=false;\r\n\t}\t\r\n\t\r\n\tif (pParams->ContainsFlag(CRCD(0x38d23fd4,\"GotExtraMemory\")))\r\n\t{\r\n\t\tConfig::gGotExtraMemory=true;\r\n\t}\r\n\tif (pParams->ContainsFlag(CRCD(0xaf11b50f,\"NoExtraMemory\")))\t\t\r\n\t{\r\n\t\tConfig::gGotExtraMemory=false;\r\n\t}\r\n\t\r\n\tif (pParams->ContainsFlag(CRCD(0x6cad3928,\"Pal\")))\t\t\r\n\t{\r\n\t\tConfig::gDisplayType=Config::DISPLAY_TYPE_PAL;\r\n\t}\r\n\tif (pParams->ContainsFlag(CRCD(0x86137a88,\"NTSC\")))\t\t\r\n\t{\r\n\t\tConfig::gDisplayType=Config::DISPLAY_TYPE_NTSC;\r\n\t}\r\n\t\r\n\tint frame_rate=60;\r\n\tif (pParams->GetInteger(CRCD(0xee2bc65f,\"FrameRate\"),&frame_rate))\r\n\t{\r\n\t\tConfig::gFPS=frame_rate;\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PrintConfig | Prints the current system configuration, whether it is CD, PAL, etc.\r\nbool ScriptPrintConfig(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tprintf(\"\\n\");\r\n\tprintf(\"System Configuration:\\n\\n\");\r\n\tprintf(\"Hardware       = %s\\n\",Config::GetHardwareName());\r\n\tprintf(\"Display Type   = %s, %d fps\\n\",Config::GetDisplayTypeName(),Config::FPS());\r\n\tprintf(\"Language       = %s\\n\",Config::GetLanguageName());\r\n\tprintf(\"Territory      = %s\\n\",Config::GetTerritoryName());\r\n\tprintf(\"CD             = %s\\n\",Config::CD()?\"True\":\"False\");\r\n\tprintf(\"GotExtraMemory = %s\\n\",Config::GotExtraMemory()?\"True\":\"False\");\r\n\tprintf(\"\\n\");\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | German | Returns true if the current language is German\r\nbool ScriptGerman(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn Config::GetLanguage()==Config::LANGUAGE_GERMAN;\r\n}\r\n\r\n// @script | French | Returns true if the current language is French\r\nbool ScriptFrench(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn Config::GetLanguage()==Config::LANGUAGE_FRENCH;\r\n}\r\n\r\n// @script | Spanish | Returns true if the current language is Spanish\r\nbool ScriptSpanish(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn Config::GetLanguage()==Config::LANGUAGE_SPANISH;\r\n}\r\n\r\n// @script | Italian | Returns true if the current language is Italian\r\nbool ScriptItalian(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn Config::GetLanguage()==Config::LANGUAGE_ITALIAN;\r\n}\r\n\r\n// @script | English | Returns true if the current language is English\r\nbool ScriptEnglish(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn Config::GetLanguage()==Config::LANGUAGE_ENGLISH;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#ifdef\t\t__USE_PROFILER__\t\t\t\r\nstatic Tmr::CPUCycles sStopwatchStartTime=0;\r\n#endif\r\n\r\nbool ScriptResetStopwatch(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#ifdef\t\t__USE_PROFILER__\t\t\t\r\n\tsStopwatchStartTime=Tmr::GetTimeInCPUCycles();\r\n#endif\t\r\n\treturn true;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptPrintStopwatchTime(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#ifdef\t\t__USE_PROFILER__\t\t\t\r\n\tTmr::CPUCycles diff=Tmr::GetTimeInCPUCycles()-sStopwatchStartTime; \r\n\tprintf(\"Stopwatch time = %.3f seconds\\n\",(float)diff/150000000.0f);\r\n#endif\t\r\n\treturn true;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CustomSkaterFilenameDefined | Doesn't appear to be supported\r\nbool ScriptCustomSkaterFilenameDefined(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\t Mdl::Skate * pSkate =  Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile=pSkate->GetCurrentProfile();\r\n\tDbg_MsgAssert(pSkaterProfile,(\"NULL pSkaterProfile\"));\r\n\t\r\n\tif (strcmp(pSkaterProfile->GetCASFileName(),\"Unimplemented\")==0)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetCustomSkaterFilename | Gets the filename for the current CAS\r\nbool ScriptGetCustomSkaterFilename(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tMdl::Skate * pSkate =  Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile=pSkate->GetCurrentProfile();\r\n\tDbg_MsgAssert(pSkaterProfile,(\"NULL pSkaterProfile\"));\r\n\t\r\n\tpScript->GetParams()->AddString(CRCD(0xf36c1878,\"CASFileName\"),pSkaterProfile->GetCASFileName());\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetCustomSkaterFilename | Sets the filename for the current CAS\r\nbool ScriptSetCustomSkaterFilename(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMdl::Skate * pSkate =  Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile=pSkate->GetCurrentProfile();\r\n\tDbg_MsgAssert(pSkaterProfile,(\"NULL pSkaterProfile\"));\r\n\r\n\tconst char *p_file_name=\"Unimplemented\";\r\n\tpParams->GetString(NONAME,&p_file_name);\r\n\tpSkaterProfile->SetCASFileName(p_file_name);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EditingPark | Returns true of we're in the park editor\r\nbool ScriptEditingPark(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#if 0\r\n\tEd::ParkEditor * pParkEd =  Ed::ParkEditor::Instance();\r\n\tif (pParkEd->IsInitialized() && !pParkEd->GameGoingOrOutsideEditor())\r\n\t{\r\n\t\t// We're in the park editor, editing a park.\r\n\t\treturn true;\r\n\t}\r\n#endif\r\n\t\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#define PARK_NAME_BUF_SIZE 128 \r\nstatic char spParkName[PARK_NAME_BUF_SIZE]={0};\r\n\r\n// @script | GetParkName | Gets the current park name\r\nbool ScriptGetParkName(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->AddString(CRCD(0xcc23bddb,\"ParkName\"),spParkName);\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetParkName | Sets the current park name\r\nbool ScriptSetParkName(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_name=\"\";\r\n\tpParams->GetString(NONAME,&p_name);\r\n\tDbg_MsgAssert(strlen(p_name)<PARK_NAME_BUF_SIZE,(\"Park name '%s' too long\",p_name));\r\n\r\n\tstrcpy(spParkName,p_name);\t\r\n\treturn false;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ParkEditorThemeWasSwitched | Check if theme changed\r\nbool ScriptParkEditorThemeWasSwitched(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#if 0\r\n\tEd::ParkEditor * pParkEd =  Ed::ParkEditor::Instance();\r\n\treturn pParkEd->m_themeWasAutoSwitched;\r\n#endif\r\n\treturn false;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic bool MenuIsShown(uint32 id)\r\n{\r\n/*\r\n\t Front::MenuFactory * pMenuFactory =  Front::MenuFactory::Instance();\r\n\tFront::MenuElement *pMenuElement=pMenuFactory->GetMenuElement(id,false); // false means don't assert\r\n\r\n\tif (pMenuElement && pMenuElement->m_isShown)\r\n\t\treturn true;\r\n\telse\r\n\t\treturn false;\r\n*/\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MenuIsShown | Checks array of names (pArray) is shown\r\nbool ScriptMenuIsShown(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// If there is an array of names, check them.\t\t\r\n\tScript::CArray *pArray=NULL;\r\n\tif (pParams->GetArray(NONAME,&pArray))\r\n\t{\r\n\t\tDbg_MsgAssert(pArray,(\"Eh? NULL pArray?\"));\r\n\t\tfor (uint32 i=0; i<pArray->GetSize(); ++i)\r\n\t\t{\r\n\t\t\tif (MenuIsShown(pArray->GetNameChecksum(i)))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tuint32 id=0;\r\n\tif (pParams->GetChecksum(NONAME,&id))\r\n\t{\r\n\t\tif (MenuIsShown(id))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t}\r\n\t\t\t\r\n\treturn false;\t\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic bool MenuIsSelected(uint32 id)\r\n{\r\n\t\r\n\t/*\r\n\t Front::MenuFactory * pMenuFactory =  Front::MenuFactory::Instance();\r\n\tFront::MenuElement *pMenuElement=pMenuFactory->GetMenuElement(id,false); // false means don't assert\r\n\r\n\tif (pMenuElement && pMenuElement->m_isSelected)\r\n\t\treturn true;\r\n\telse\r\n\t\treturn false;\r\n\t*/\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ForEachIn | For each member of the array, run the specified script\r\n// @parm name | Do | The name of the script to run\r\n// @uparm [] | The array on which to run\r\n// @parmopt structure | Params | | any extra parameters that need to be\r\n// merged onto each of those in the array\r\nbool ScriptForEachIn(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 ScriptChecksum=0;\r\n\tpParams->GetChecksum(CRCD(0x62ba3f6a,\"Do\"),&ScriptChecksum);\r\n\tDbg_MsgAssert(ScriptChecksum,(\"\\n%s\\nScript name missing in call to ForEachIn\\n(eg, ForEachIn AnArray Do=AScript)\",pScript->GetScriptInfo()));\r\n\t\r\n\tScript::CArray *pArray=NULL;\r\n\tpParams->GetArray(NONAME,&pArray);\r\n\tDbg_MsgAssert(pArray,(\"\\n%s\\nMissing array parameter in call to ForEachIn\",pScript->GetScriptInfo()));\r\n\tDbg_MsgAssert(pArray->GetSize()==0 || pArray->GetType()==ESYMBOLTYPE_STRUCTURE,(\"\\n%s\\nForEachIn only supports arrays of structures at the moment\",pScript->GetScriptInfo()));\r\n\t\r\n\t\r\n\t// Get any extra parameters that need to be merged onto each of those in the array.\r\n\tScript::CStruct *pExtraParams=NULL;\r\n\tpParams->GetStructure(CRCD(0x7031f10c,\"params\"),&pExtraParams);\r\n\t\r\n\tif (pExtraParams)\r\n\t{\r\n\t\t// Used for holding the merged parameters.\r\n\t\tScript::CStruct *pTotalParams=new Script::CStruct;\r\n\t\t\r\n\t\tfor (uint32 i=0; i<pArray->GetSize(); ++i)\r\n\t\t{\r\n\t\t\tpTotalParams->Clear();\r\n\t\t\t\r\n\t\t\tCStruct *p_array_struct=pArray->GetStructure(i);\r\n\t\t\t\r\n\t\t\tif (p_array_struct)\r\n\t\t\t{\r\n\t\t\t\t*pTotalParams+=*p_array_struct;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tif (pExtraParams)\r\n\t\t\t{\r\n\t\t\t\t*pTotalParams+=*pExtraParams;\r\n\t\t\t}\t\r\n\t\r\n\t\t\tScript::RunScript(ScriptChecksum,pTotalParams,pScript->mpObject);\r\n\t\t}\r\n\t\t\r\n\t\t// Delete the temporary structure.\r\n\t\tdelete pTotalParams;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor (uint32 i=0; i<pArray->GetSize(); ++i)\r\n\t\t{\r\n\t\t\tScript::RunScript(ScriptChecksum,pArray->GetStructure(i),pScript->mpObject);\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SizeOf | \r\n// Puts the size (num elements in) of the passed array into a parameter called ArraySize\r\n// @uparm [] | The array of which we're finding the size\r\nbool ScriptSizeOf(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tScript::CArray *p_array=NULL;\r\n\tpParams->GetArray(NONAME,&p_array);\r\n\t\r\n\tint size=0;\r\n\tif (p_array)\r\n\t{\r\n\t\tsize=p_array->GetSize();\r\n\t}\t\r\n\tpScript->GetParams()->AddComponent(Script::GenerateCRC(\"ArraySize\"),ESYMBOLTYPE_INTEGER,size);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetElement | Retrieves the array element pointed to by \"Index\"\r\n// and places it in the param called \"Element\"\r\n// @uparm [] | the array\r\n// @parmopt int | Index | 0 | The index value of the array element\r\nbool ScriptGetElement(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tScript::CArray *p_array=NULL;\r\n\tpParams->GetArray(NONAME,&p_array);\r\n\r\n\tint index=0;\r\n\tpParams->GetInteger(\"Index\",&index);\r\n\r\n\tpScript->GetParams()->RemoveComponent(0xbebfa1c6/*Element*/);\t\r\n\t\r\n\tif (p_array)\r\n\t{\r\n\t\tif (index<0 || index>=(int)p_array->GetSize())\r\n\t\t{\r\n\t\t   #ifdef __NOPT_ASSERT__\r\n\t\t   printf(\"\\n%s\\nWarning ! Index %d out of range. Array has %d elements\\n\",pScript->GetScriptInfo(),index,p_array->GetSize());\r\n\t\t   #endif\r\n\t\t   return false;\r\n\t\t}\r\n\t\t\r\n\t\tswitch (p_array->GetType())\r\n\t\t{\r\n\t\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\t{\r\n\t\t\tScript::CStruct *p_new=new Script::CStruct;\r\n\t\t\tp_new->AppendStructure(p_array->GetStructure(index));\r\n\t\t\tpScript->GetParams()->AddComponent(0xbebfa1c6/*Element*/,ESYMBOLTYPE_STRUCTUREPOINTER,(int)p_new);\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase ESYMBOLTYPE_ARRAY:\r\n\t\t\tpScript->GetParams()->AddComponent(0xbebfa1c6/*Element*/,p_array->GetArray(index));\r\n\t\t\tbreak;\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\tpScript->GetParams()->AddComponent(0xbebfa1c6/*Element*/,ESYMBOLTYPE_INTEGER,p_array->GetInt(index));\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\tprintf(\"GetElement currently only supports arrays of structures, arrays or integers ... \\n(Requested type=%d)\\n\",p_array->GetType());\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t}\r\n\treturn true;\r\n}\r\n\t\t   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetNextArrayElement | Increments the value in Index and uses it to retrieve that\r\n// element from the array, and puts it in Element\r\n// If no Index parameter exists, it will retrieve the first element of the array, and \r\n// create Index and set it to zero.\r\n// If Index goes off the end of the array, it will remove the Index parameter and\r\n// any existing Element parameter, and return false.\r\n// Hence calling GetNextArrayElement repeatedly will cycle through the array elements.\r\n// @uparm [] | the array\r\nbool ScriptGetNextArrayElement(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tScript::CArray *p_array=NULL;\r\n\tpParams->GetArray(NONAME,&p_array);\r\n\r\n\tint index=-1;\r\n\tpScript->GetParams()->GetInteger(CRCD(0x7f8c98fe,\"Index\"),&index);\r\n\r\n\tpScript->GetParams()->RemoveComponent(0x7f8c98fe/*Index*/);\r\n\tpScript->GetParams()->RemoveComponent(0xbebfa1c6/*Element*/);\r\n\t\r\n\tif (!p_array)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tint size=p_array->GetSize();\r\n\t\r\n\tif (index<0)\r\n\t{\r\n\t\t// No index parameter existed, so set index to the first element of the array.\r\n\t\tindex=0;\r\n\t\t\r\n\t\tif (size==0)\r\n\t\t{\r\n\t\t\t// The array is empty though, so add nothing to the params.\r\n\t\t\treturn false;\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// An index existed already, so increment it.\r\n\t\t++index;\r\n\t\tif (index>=size)\r\n\t\t{\r\n\t\t\t// Run out of array elements!\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\tpScript->GetParams()->AddInteger(CRCD(0x7f8c98fe,\"Index\"),index);\r\n\r\n\tswitch (p_array->GetType())\r\n\t{\r\n\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\tpScript->GetParams()->AddStructure(0xbebfa1c6/*Element*/,p_array->GetStructure(index));\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_ARRAY:\r\n\t\tpScript->GetParams()->AddArray(0xbebfa1c6/*Element*/,p_array->GetArray(index));\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_INTEGER:\r\n\t\tpScript->GetParams()->AddInteger(0xbebfa1c6/*Element*/,p_array->GetInteger(index));\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_FLOAT:\r\n\t\tpScript->GetParams()->AddFloat(0xbebfa1c6/*Element*/,p_array->GetFloat(index));\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_NAME:\r\n\t\tpScript->GetParams()->AddChecksum(0xbebfa1c6/*Element*/,p_array->GetChecksum(index));\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_STRING:\r\n\t\tpScript->GetParams()->AddString(0xbebfa1c6/*Element*/,p_array->GetString(index));\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\tpScript->GetParams()->AddLocalString(0xbebfa1c6/*Element*/,p_array->GetLocalString(index));\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tprintf(\"GetNextArrayElement does not support arrays of type '%s'\\n\",GetTypeName(p_array->GetType()));\r\n\t\tbreak;\r\n\t}\t\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetRandomArrayElement | Chooses a random element of the passed array, and\r\n// puts it in Element. It will put the index of the chosen element into a parameter called Index.\r\n// If the array is empty, it will remove any existing Element and Index parameter and return false.\r\n// @uparm [] | the array\r\nbool ScriptGetRandomArrayElement(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->RemoveComponent(CRCD(0xbebfa1c6,\"Element\"));\r\n\tpScript->GetParams()->RemoveComponent(CRCD(0x7f8c98fe,\"index\"));\r\n\r\n\tScript::CArray *p_array=NULL;\r\n\tpParams->GetArray(NONAME,&p_array);\r\n\r\n\tif (!p_array)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tint size=p_array->GetSize();\r\n\tif (size==0)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\tint index=Mth::Rnd(size);\r\n\t// Wack in the index too cos it is handy to know.\r\n\tpScript->GetParams()->AddInteger(CRCD(0x7f8c98fe,\"index\"),index);\t\r\n\t\t\r\n\tswitch (p_array->GetType())\r\n\t{\r\n\tcase ESYMBOLTYPE_STRUCTURE:\r\n\t\tpScript->GetParams()->AddStructure(CRCD(0xbebfa1c6,\"Element\"),p_array->GetStructure(index));\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_ARRAY:\r\n\t\tpScript->GetParams()->AddArray(CRCD(0xbebfa1c6,\"Element\"),p_array->GetArray(index));\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_INTEGER:\r\n\t\tpScript->GetParams()->AddInteger(CRCD(0xbebfa1c6,\"Element\"),p_array->GetInteger(index));\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_FLOAT:\r\n\t\tpScript->GetParams()->AddFloat(CRCD(0xbebfa1c6,\"Element\"),p_array->GetFloat(index));\r\n\t\tbreak;\r\n\tcase ESYMBOLTYPE_NAME:\r\n\t\tpScript->GetParams()->AddChecksum(CRCD(0xbebfa1c6,\"Element\"),p_array->GetChecksum(index));\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tprintf(\"GetRandomArrayElement does not support arrays of type '%s'\\n\",GetTypeName(p_array->GetType()));\r\n\t\tbreak;\r\n\t}\t\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PermuteArray | Creates a new array equal to the passed array with its elements\r\n// randomly permuted. The new array is put into a parameter named using the passed NewArrayName.\r\n// @parm array | Array | The source array\r\n// @parm name | NewArrayName | The name to be given to the new array parameter.\r\n// @flag MakeNewFirstDifferFromOldLast | Makes the first element of the new array definitely\r\n// be different from the old last element. This is so that the old permutation can be\r\n// concatenated with the new and no consecutive elements will be the same.\r\n// Could be useful for playing songs in a random order with no repeats.\r\n// @flag PermuteSource | If this flag is specified then it will be the source array itself\r\n// that will get permuted, no new array will get created.\r\n// So the NewArrayName parameter is not required in this case, it will be ignored.\r\nbool ScriptPermuteArray(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tScript::CArray *p_source_array=NULL;\r\n\tpParams->GetArray(\"Array\",&p_source_array);\r\n\t\r\n\tif (!p_source_array)\r\n\t{\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tprintf(\"\\n%s\\nPermuteArray requires an Array parameter\\n\",pScript->GetScriptInfo());\r\n\t\t#endif\r\n\t\treturn false;\r\n\t}\r\n\r\n\tCArray *p_array_to_be_permuted=p_source_array;\r\n\tbool create_new_array=!pParams->ContainsFlag(\"PermuteSource\");\r\n\t\r\n\tuint32 new_array_name=0;\r\n\tCArray *p_new_array=NULL;\r\n\t\r\n\tif (create_new_array)\r\n\t{\r\n\t\tpParams->GetChecksum(\"NewArrayName\",&new_array_name);\r\n\t\tif (!new_array_name)\r\n\t\t{\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tprintf(\"\\n%s\\nPermuteArray requires a NewArrayName parameter\\n\",pScript->GetScriptInfo());\r\n\t\t\t#endif\r\n\t\t\treturn false;\r\n\t\t}\t\r\n\t\t\r\n\t\tp_new_array=new CArray;\r\n\t\tCopyArray(p_new_array,p_source_array);\r\n\t\tp_array_to_be_permuted=p_new_array;\r\n\t}\t\r\n\t\r\n\t\r\n\t\r\n\tint size=p_array_to_be_permuted->GetSize();\r\n\tif (size)\r\n\t{\r\n\t\tuint32 *p_array_data=p_array_to_be_permuted->GetArrayPointer();\r\n\t\tDbg_MsgAssert(p_array_data,(\"NULL p_array_data ?\"));\r\n\t\t\r\n\t\tint num_swaps=size*10;\r\n\t\t\r\n\t\tuint32 old_last=p_array_data[size-1];\r\n\t\t\r\n\t\tfor (int i=0; i<num_swaps; ++i)\r\n\t\t{\r\n\t\t\tint a=Mth::Rnd(size);\r\n\t\t\tint b=Mth::Rnd(size);\r\n\t\t\t\r\n\t\t\tuint32 temp=p_array_data[a];\r\n\t\t\tp_array_data[a]=p_array_data[b];\r\n\t\t\tp_array_data[b]=temp;\r\n\t\t}\r\n\t\t\r\n\t\t// Ensure that the new first element is not the same as the old last one,\r\n\t\t// so that when using the function to jumble up a list of soundtracks say,\r\n\t\t// there will never be two consecutive ones the same.\r\n\t\tif (pParams->ContainsFlag(\"MakeNewFirstDifferFromOldLast\") && size>1 && p_array_data[0]==old_last)\r\n\t\t{\r\n\t\t\tint a=0;\r\n\t\t\tint b=1+Mth::Rnd(size-1);\r\n\t\t\t\r\n\t\t\tuint32 temp=p_array_data[a];\r\n\t\t\tp_array_data[a]=p_array_data[b];\r\n\t\t\tp_array_data[b]=temp;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (create_new_array)\r\n\t{\r\n\t\tpScript->GetParams()->AddArrayPointer(new_array_name,p_new_array);\r\n\t}\r\n\t\t\r\n\treturn true;\r\n}\r\n\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetGammaValues( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n#\tif defined( __PLAT_XBOX__ )\r\n\t Gfx::Manager * gfx_man =  Gfx::Manager::Instance();\r\n\tfloat gamma_r;\r\n\tfloat gamma_g;\r\n\tfloat gamma_b;\r\n\tgfx_man->GetGammaNormalized( &gamma_r, &gamma_g, &gamma_b );\r\n\r\n\tpScript->GetParams()->RemoveComponent( \"red\" );\r\n\tpScript->GetParams()->RemoveComponent( \"green\" );\r\n\tpScript->GetParams()->RemoveComponent( \"blue\" );\r\n\r\n\tpScript->GetParams()->AddInteger( \"red\", ( (int)( gamma_r * 100.0f ) ));\r\n\tpScript->GetParams()->AddInteger( \"green\", ( (int)( gamma_g * 100.0f ) ));\r\n\tpScript->GetParams()->AddInteger( \"blue\", ( (int)( gamma_b * 100.0f ) ));\r\n#\tendif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ApplyChangeGamma | This gets called whenever one of \r\n// the color values in the gamma menu changes.\r\n// Called from script in gamemenu.q\r\nbool ScriptApplyChangeGamma( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n#\tif defined( __PLAT_XBOX__ )\t\r\n\t// get the current values\r\n\t Gfx::Manager * gfx_man =  Gfx::Manager::Instance();\r\n\tfloat gamma_r;\r\n\tfloat gamma_g;\r\n\tfloat gamma_b;\r\n\tgfx_man->GetGammaNormalized( &gamma_r, &gamma_g, &gamma_b );\r\n\r\n\tuint32 color;\r\n\tpParams->GetChecksum( \"color\", &color, Script::ASSERT );\r\n\r\n\tfloat change;\r\n\tpParams->GetFloat( \"change\", &change, Script::ASSERT );\r\n\tswitch ( color )\r\n\t{\r\n\tcase CRCC( 0x59ea070, \"red\" ):\r\n\t\tif (( change > 0.0f && gamma_r < 1.0f ) || ( change < 0.0f && gamma_r > 0.0f ))\r\n\t\t\tgamma_r += change;\r\n\t\tbreak;\r\n\tcase CRCC( 0x2f6511de, \"green\" ):\r\n\t\tif (( change > 0.0f && gamma_g < 1.0f ) || ( change < 0.0f && gamma_g > 0.0f ))\r\n\t\t\tgamma_g += change;\r\n\t\tbreak;\r\n\tcase CRCC( 0x61c9354b, \"blue\" ):\r\n\t\tif (( change > 0.0f && gamma_b < 1.0f ) || ( change < 0.0f && gamma_b > 0.0f ))\r\n\t\t\tgamma_b += change;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tDbg_MsgAssert( 0, (\"ApplyChangeGamma called on unknown color\") );\r\n\t}\r\n\t\r\n\tgfx_man->SetGammaNormalized( gamma_r, gamma_g, gamma_b );\r\n\t\r\n/*\t// grab any new values from the params\r\n\tint r, g, b;\r\n\tif ( pParams->GetInteger( \"red\", &r, Script::NO_ASSERT ) )\r\n\t\tgamma_r = (float)(r) / 100.0f;\r\n\tif ( pParams->GetInteger( \"green\", &g, Script::NO_ASSERT ) )\r\n\t\tgamma_g = (float)(g) / 100.0f;\r\n\tif ( pParams->GetInteger( \"blue\", &b, Script::NO_ASSERT ) )\r\n\t\tgamma_b = (float)(b) / 100.0f;\r\n*/\r\n\r\n#\tendif\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GotParam | Checks if the script was passed the specified parameter\r\n// @uparm name | The name of the param to check for\r\nbool ScriptGotParam(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tuint32 FlagChecksum=0;\r\n\tpParams->GetChecksum(NONAME,&FlagChecksum);\r\n\tDbg_MsgAssert(FlagChecksum,(\"GotParam command requires a flag name\"));\r\n\t\r\n\t// Get the script's parameters, and see if they contain the aforementioned flag therein.\r\n\tScript::CStruct *pScriptParams=pScript->GetParams();\r\n\tDbg_MsgAssert(pScriptParams,(\"NULL pScriptParams\"));\r\n\treturn pScriptParams->ContainsComponentNamed(FlagChecksum);\r\n}\r\n\r\nTmr::Time gButtonDebounceTime[PAD_NUMBUTTONS];  // PAD_NUMBUTTONS defined in skater.h for some reason (instead of some controller header)\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ControllerDeboune |\r\n// For example: <nl>\r\n// Debounce X time = 2.0 <nl>\r\n// This will ignore the X button until either the time has elapsed,\r\n// or the X button has been released and subsequently re-pressed. <nl>\r\n// This prevents the press of X from carrying over from one screen to \r\n// the next, and removes the need to have a delay, whilst still allowing \r\n// the user to actively X past things. \r\n// @uparm name | the button\r\n// @parmopt float | time | 1.0 | \r\nbool ScriptControllerDebounce( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tuint32 Checksum = 0;\r\n\tfloat time=1.0f;\r\n\tpParams->GetFloat(0x906b67ba,&time);\t   // \"time\"\r\n\tif ( pParams->GetChecksum( NONAME, &Checksum ) )\r\n\t{\r\n\t\tint Button = Inp::GetButtonIndex(Checksum);\t\r\n\t\tgButtonDebounceTime[Button] = (Tmr::Time)(Tmr::GetTime() + (time * 1000));\r\n\t}\r\n\treturn ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid ResetDebounce( void )\r\n{\r\n\t\r\n\tint i;\r\n\tfor ( i = 0; i < PAD_NUMBUTTONS; i++ )\r\n\t{\r\n\t\tgButtonDebounceTime[ i ] = 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CheckButton(Inp::Handler< Mdl::FrontEnd >* pHandler, uint32 button)\r\n{\r\n\t\r\n\r\n\tif (!pHandler)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\tif (!pHandler->m_Input)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\tint whichButton = Inp::GetButtonIndex( button );\r\n\tif ( gButtonDebounceTime[ whichButton ] > Tmr::GetTime( ) )\r\n\t{\r\n\t\treturn ( false );\r\n\t}\r\n\tswitch ( button )\r\n\t{\r\n\t\tcase ( 0xbc6b118f ): // Up\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_UP] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0xe3006fc4 ): // Down\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_DOWN] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0x85981897 ): // Left\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_LEFT] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0x4b358aeb ): // Right\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_RIGHT] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0xb7231a95 ): // UpLeft\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_UP] )\r\n\t\t\t{\r\n\t\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_LEFT] )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn ( true );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0xa50950c5 ): // UpRight\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_UP] )\r\n\t\t\t{\r\n\t\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_RIGHT] )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn ( true );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0xd8847efa ): // DownLeft\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_DOWN] )\r\n\t\t\t{\r\n\t\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_LEFT] )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn ( true );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0x786b8b68 ): // DownRight\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_DOWN] )\r\n\t\t\t{\r\n\t\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_RIGHT] )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn ( true );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0x2b489a86 ): // Circle\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_CIRCLE] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0x321c9756 ): // Square\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_SQUARE] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0x7323e97c ): // X\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_X] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0x20689278 ): // Triangle\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_TRIANGLE] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0x26b0c991 ): // L1\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_L1] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0xbfb9982b ): // L2\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_L2] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0xf2f1f64e ): // R1\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_R1] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( 0x6bf8a7f4 ): // R2\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_R2] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n        case ( 0x767a45d7 ): // black\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_BLACK] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n        case ( 0xbd30325b ): // white\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_WHITE] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n        case ( 0x9d2d8850 ): // Z\r\n\t\t\tif ( pHandler->m_Input->m_Event[Inp::Data::vA_Z] )\r\n\t\t\t{\r\n\t\t\t\treturn ( true );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ControllerPressed | returns true if the specified button is pressed\r\n// @uparm name | the button to check\r\n// @uparmopt 0 | controller index\r\nbool ScriptControllerPressed(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMdl::FrontEnd* pFront = Mdl::FrontEnd::Instance();\r\n\r\n\tint controller;\r\n\tuint32 button = 0;\r\n\tif ( pParams->GetChecksum( NONAME, &button ) )\r\n\t{\r\n\t\tif ( pParams->GetInteger( NONAME, &controller, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( controller < SIO::vMAX_DEVICES && controller >= 0, ( \"ControllerPressed called with bad controller index\" ) );\r\n\t\t\tif ( CheckButton( pFront->GetInputHandler( controller ), button ) )\r\n\t\t\t\treturn true;\r\n\t\t\telse\r\n\t\t\t\treturn false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfor ( int i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t\t\t{\r\n\t\t\t\tif ( CheckButton( pFront->GetInputHandler( i ), button ) )\r\n\t\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n// @script | GetAnalogueInfo | Reads the analogue sticks, ans returns the floats LeftX, LeftY, RightX and RightY.\r\n// These each range from -1 to 1.\r\n// @parmopt int | Controller | 0 | Controller index\r\nbool ScriptGetAnalogueInfo(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMdl::FrontEnd* pFront = Mdl::FrontEnd::Instance();\r\n\r\n\tint controller=0;\r\n\tpParams->GetInteger( CRCD(0xb30d9965,\"Controller\"), &controller, Script::NO_ASSERT );\r\n\t\r\n\tDbg_MsgAssert( controller < SIO::vMAX_DEVICES && controller >= 0, ( \"ControllerPressed called with bad controller index\" ) );\r\n\tInp::Handler< Mdl::FrontEnd > *p_handler=pFront->GetInputHandler( controller );\r\n\tCControlPad pad;\r\n\tpad.Update(p_handler->m_Input);\r\n\t\r\n\tpScript->GetParams()->AddFloat(CRCD(0x303067f1,\"LeftX\"),pad.m_scaled_leftX);\r\n\tpScript->GetParams()->AddFloat(CRCD(0x47375767,\"LeftY\"),pad.m_scaled_leftY);\r\n\tpScript->GetParams()->AddFloat(CRCD(0x694df774,\"RightX\"),pad.m_scaled_rightX);\r\n\tpScript->GetParams()->AddFloat(CRCD(0x1e4ac7e2,\"RightY\"),pad.m_scaled_rightY);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetSfxVolume | SetSfxVolume [100] <nl>\r\n// Param: volumeLevel <nl>\r\n// range: 0 to 100 (the main mixing volume, affecting all soundfx) <nl>\r\n// default: 100 <nl> <nl>\r\n// Notes: the volume is set to 100 on startup, and can only be modified with this command\r\n// @uparmopt 100.0 | volume\r\nbool ScriptSetVolume( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tfloat Volume = 100.0f;\r\n    \r\n\tpParams->GetFloat( NONAME, &Volume );\r\n\r\n\t Sfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\tsfx_manager->SetMainVolume( Volume );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetMusicVolume | \r\n// @uparmopt 100.0 | volume level\r\nbool ScriptSetMusicVolume( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tfloat Volume = 100.0f;\r\n    \r\n\tpParams->GetFloat( NONAME, &Volume );\r\n\r\n\tPcm::SetVolume( Volume );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetMusicStreamVolume | \r\n// @uparmopt 100.0 | volume level\r\nbool ScriptSetMusicStreamVolume( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tfloat Volume = 100.0f;\r\n    \r\n\tpParams->GetFloat( NONAME, &Volume );\r\n\r\n\tPcm::SetMusicStreamVolume( Volume );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StopMusic | \r\nbool ScriptStopMusic( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tPcm::StopMusic( );\r\n\treturn ( true );\r\n}\r\n\r\n#define CHECKSUM_FADE\t0xb5aa125f // fade\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PauseMusic | \r\nbool ScriptPauseMusic( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tint pausePlease = 1;\r\n\tpParams->GetInteger( NONAME, &pausePlease );\r\n\tPcm::PauseMusic( pausePlease );\r\n\treturn ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PauseStream | \r\n// @uparm 1 | 0 to unpause, 1 to pause\r\nbool ScriptPauseStream( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tint pausePlease = 1;\r\n\tpParams->GetInteger( NONAME, &pausePlease );\r\n\tPcm::PauseStream( pausePlease );\r\n\treturn ( true );\r\n}\r\n\t\t   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LoadMusicHeader | parameter is name of header/wad file (minus extension) \r\n// Do this once on startup. \r\n// Example:  LoadMusicHeader \"music\\music\"\r\n// @uparm \"string\" | name of header/wad file\r\nbool ScriptLoadMusicHeader( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tconst char *pName = NULL;\r\n\tpParams->GetText( NONAME, &pName );\r\n\tif ( pName )\r\n\t{\r\n\t\t// Mick:  Moved to BottomUpHeap, as it is a lot bigger now, and only loaded at startup\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t\tbool done =  ( Pcm::LoadMusicHeader( pName ) );\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\treturn done;\r\n\t\t\r\n\t}\r\n\treturn ( false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LoadStreamHeader | \r\n// @uparm \"string\" | name of header/wad file (minus extension)\r\nbool ScriptLoadStreamHeader( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tconst char *pName = NULL;\r\n\tpParams->GetText( NONAME, &pName );\r\n\tif ( pName )\r\n\t{\r\n\t\t// Mick:  Moved to BottomUpHeap, as it is a lot bigger now, and only loaded at startup\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t\tbool done = ( Pcm::LoadStreamHeader( pName ) );\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\treturn done;\r\n\t}\r\n\treturn ( false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StreamIsAvailable | only available in the skateshop\r\n// @parm int | | which stream \r\nbool ScriptStreamIsAvailable( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tif ( !skate_mod->GetGameMode()->IsFrontEnd() )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"StreamIsAvailable script function is only valid in the skateshop.\" ) );\r\n\t}\r\n\tint whichStream;\r\n\tif ( pParams->GetInteger( NONAME, &whichStream ) )\r\n\t{\r\n\t\tif ( whichStream >= Pcm::GetNumStreamsAvailable( ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"\\n%s\\nAsking for StreamIsAvailable on stream %d, past valid range ( 0 to %d ).\", pScript->GetScriptInfo( ),  whichStream, Pcm::GetNumStreamsAvailable( ) - 1 ) );\r\n\t\t\treturn ( false );\r\n\t\t}\r\n\t\treturn ( Pcm::StreamAvailable( whichStream ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn ( Pcm::StreamAvailable( ) );\r\n\t}\r\n}\r\n\r\n#define CHECKSUM_FLAG_PERM\t0x389129e4\t// \"FLAG_PERM\"\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AddMusicTrack | adds track to list - plays randomly during game <nl>\r\n// Note: The songs that go into the data/music folder (and are added to the\r\n// CD in them 'music' directory) as well as the ambient tracks in data/ambient\r\n// (and in 'ambient' directory on CD) should have a filename of 8 characters\r\n// or less, as otherwise the names get converted upon building a CD\r\n// @uparmopt \"string\" | filename in quotes ( .wav file in data/music ) \r\n// @uparmopt name | filename \r\n// @flag flag_perm | to add the song to the permanent soundtrack list on startup...\r\n// otherwise track is a level-specific ambient type. <nl>\r\nbool ScriptAddMusicTrack( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tconst char *pTrackName = NULL;\r\n\tconst char *pTrackTitle = NULL;\r\n\t// default to ambient tracks...\r\n\tpParams->GetText( NONAME, &pTrackName );\r\n\tpParams->GetText( \"TrackTitle\", &pTrackTitle );\r\n\tint whichList = Pcm::TRACKLIST_LEVEL_SPECIFIC;\r\n\tif ( pParams->ContainsFlag( CHECKSUM_FLAG_PERM ) )\r\n\t{\r\n\t\twhichList = Pcm::TRACKLIST_PERM;\r\n\t}\r\n\t\r\n\tif ( pTrackName )\r\n\t{\r\n\t\tPcm::AddTrackToPlaylist( pTrackName, whichList, pTrackTitle );\r\n\t}\r\n\treturn ( true );\r\n}\r\n\r\n\r\n// @script | ChangeTrackState | Disables or enables one of the permanent music tracks.\r\n// @uparmopt 0 | The index of the track\r\n// @flag Off | Disable the specified track. If omitted, it will enable the track.\r\nbool ScriptChangeTrackState(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint track_num=0;\r\n\tpParams->GetInteger(NONAME,&track_num);\r\n\t\r\n\tPcm::SetTrackForbiddenStatus(track_num,pParams->ContainsFlag(\"Off\"),Pcm::TRACKLIST_PERM);\r\n\treturn true;\r\n}\r\n\t\r\n// @script | TrackEnabled | Returns true if the specified track in the permanent track list is enabled.\r\n// @uparmopt 0 | The index of the track\r\nbool ScriptTrackEnabled(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint track_num=0;\r\n\tpParams->GetInteger(NONAME,&track_num);\r\n\r\n\tif (Pcm::GetNumTracks(Pcm::TRACKLIST_PERM) == 0)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\tDbg_MsgAssert( track_num>=0 && track_num < Pcm::GetNumTracks(Pcm::TRACKLIST_PERM),( \"\\n%s\\nBad track number of %d sent to TrackEnabled, num tracks = %d\", pScript->GetScriptInfo(), track_num, Pcm::GetNumTracks(Pcm::TRACKLIST_PERM) ));\r\n\t\r\n\tuint64 list1,list2;\r\n    Pcm::GetPlaylist(&list1, &list2);\r\n    \r\n    if (track_num<64)\r\n    {\r\n        if (list1 & (((uint64)1) << track_num))\r\n        {\r\n            return false;\r\n        }\r\n    }        \r\n    else\r\n    {\r\n        if (list2 & (((uint64)1) << (track_num-64)))\r\n        {\r\n            return false;\r\n        }\r\n    }\r\n\t\r\n\treturn true;\t\r\n}\r\n\r\nbool ScriptMusicIsPaused(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn Pcm::MusicIsPaused();\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ClearMusicTrackList | \r\n// @flag FLAG_PERM | optionally add FLAG_PERM to clear \r\n// the permanent list, otherwise clear level specific list\r\nbool ScriptClearMusicTrackList( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tint whichList = Pcm::TRACKLIST_LEVEL_SPECIFIC;\r\n\tif ( pParams->ContainsFlag( CHECKSUM_FLAG_PERM ) )\r\n\t{\r\n\t\twhichList = Pcm::TRACKLIST_PERM;\r\n\t}\r\n\tPcm::ClearPlaylist( whichList );\r\n\treturn ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SkipMusicTrack | \r\n// Play next track in the list ( or if in random mode, pick another random track )\r\nbool ScriptSkipMusicTrack( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tPcm::SkipMusicTrack( );\r\n\treturn ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetMusicMode |\r\n// Play music or ambient sounds?\r\n// @uparm 1 | 1 for music on, 0 for music off/ ambience on\r\nbool ScriptSetMusicMode( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tint musicOn = 1;  // 1 for music on, 0 for music off/ambience on\r\n\tpParams->GetInteger( NONAME, &musicOn );\r\n\tPcm::SetActiveTrackList( musicOn ? Pcm::TRACKLIST_PERM : Pcm::TRACKLIST_LEVEL_SPECIFIC );\r\n\treturn ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetRandomMode | \r\n// Play tracks in Random mode or play tracks in order.\r\nbool ScriptSetRandomMode( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tint randomModeOn = 1;\r\n\tpParams->GetInteger( NONAME, &randomModeOn );\r\n\tPcm::SetRandomMode( randomModeOn );\r\n\treturn ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetMusicLooping | \r\n// Loops playing track.\r\n// @uparm 1 | 1 enables looping, 0 disables looping\r\nbool ScriptSetMusicLooping( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tint loopingModeOn = 1;\r\n\tpParams->GetInteger( NONAME, &loopingModeOn );\r\n\tPcm::SetLoopingMode( loopingModeOn );\r\n\treturn ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetCurrentTrack | \r\n// Gets the index of the currently playing music track.\r\nbool ScriptGetCurrentTrack( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n    int track = Pcm::GetCurrentTrack();\r\n    pScript->GetParams()->AddInteger( \"current_track\", track );\r\n    return ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PlayMovie | Play a movie from data\\movies on PC, or \\movies on CD\r\n// @uparm \"string\" | movie name\r\nbool ScriptPlayMovie( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tconst char *pMovieName;\r\n\r\n\r\n\tif ( pParams->GetText( NONAME, &pMovieName, true ) )\r\n\t{\r\n\t\tFlx::PlayMovie( pMovieName );\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UnloadAnim | \r\n// @parm name | descChecksum | asset name\r\n// @parmopt name | refChecksum | 0 | skeleton name\r\nbool ScriptUnloadAnim( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t// get the assman\r\n\tAss::CAssMan * ass_man = Ass::CAssMan::Instance();\r\n\r\n\tconst char* pAnimName = NULL;\r\n\tpParams->GetText( \"name\", &pAnimName, Script::ASSERT );\r\n\r\n\tAss::CAsset* pAsset = ass_man->GetAssetNode( Script::GenerateCRC(pAnimName), false );\r\n\r\n\tif ( pAsset )\r\n\t{\r\n\t\tass_man->DestroyReferences( pAsset );\r\n\t\tass_man->UnloadAsset( pAsset );\r\n\t\t\r\n//\t\tDbg_Message( \"Unloaded asset %s\", \r\n//\t\t\t\t\t pAnimName );\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tDbg_Message( \"Couldn't find asset %s to unload\", \r\n//\t\t\t\t\t pAnimName );\r\n\t}\r\n\r\n\r\n#if 0\r\n\t// can't do it this way, because it \r\n\t// deletes the reference,\r\n\t// not the actual asset itself...\r\n\r\n\tuint32 animName = 0;\r\n\tuint32 refChecksum = 0;\r\n\r\n\tpParams->GetChecksum( \"descChecksum\", &animName, Script::ASSERT );\r\n\r\n\t//printf(\"Called UnloadAnim on %s\\n\",Script::FindChecksumName(animName));\r\n\t\r\n\tif ( !pParams->GetChecksum( \"refChecksum\", &refChecksum, Script::NO_ASSERT ) )\r\n\t{\r\n\t\trefChecksum = ass_man->GetReferenceChecksum();\r\n\t}\r\n\r\n\t// make sure the reference checksum is not 0,\r\n\t// if a reference checksum was not specified\t\r\n\tDbg_MsgAssert( refChecksum != 0, ( \"No ref checksum\" ) );\r\n\r\n\t// kills the original asset\r\n\tAss::CAsset* pAsset = ass_man->GetAssetNode( refChecksum + animName, false );\r\n\tif ( pAsset )\r\n\t{\r\n\t\tass_man->DestroyReferences( pAsset );\r\n\t\tass_man->UnloadAsset( pAsset );\r\n#ifdef __NOPT_ASSERT__\r\n\t\tDbg_Message( \"Unloaded asset %s %s\", \r\n\t\t\t\t\t Script::FindChecksumName( refChecksum ),\r\n\t\t\t\t\t Script::FindChecksumName( animName ) );\r\n#endif\r\n\t}\r\n\telse\r\n\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\tDbg_Message( \"Couldn't find asset %s %s to unload\", \r\n\t\t\t\t\t Script::FindChecksumName( refChecksum ),\r\n\t\t\t\t\t Script::FindChecksumName( animName ) );\r\n#endif\r\n\t}\r\n#endif\r\n\r\n   return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LoadAsset | \r\n// @parm string | name | asset name\r\nbool ScriptLoadAsset( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t Ass::CAssMan * ass_man =  Ass::CAssMan::Instance();\r\n\r\n\tconst char* p_asset_filename;\r\n\tif ( pParams->GetText( (const char*)\"name\", &p_asset_filename, false )\r\n\t\t || pParams->GetText( NONAME, &p_asset_filename, true ) )\r\n\t{\r\n\t\t// either (name=\"XXX\") or (\"XXX\") is required\r\n\t}\r\n\r\n#ifdef __USER_GARY__\r\n//\tDbg_Message( \"*** Loading asset %s, perm=%d\\n\", p_asset_filename, ass_man->GetDefaultPermanent() );\r\n#endif\r\n\r\n//\tif( !ass_man->LoadOrGetAsset( p_asset_filename, false, ass_man->GetDefaultPermanent() ) )\r\n\tif( !ass_man->LoadOrGetAsset( p_asset_filename, false, false, ass_man->GetDefaultPermanent(), 0, NULL, pParams ) )\r\n\t{\r\n\t\tif ( Script::GetInteger( CRCD(0x25dc7904,\"AssertOnMissingAssets\") ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( false,( \"Could not load asset %s\", p_asset_filename ));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\r\n\tuint32 descChecksum = 0;\r\n\tif ( pParams->GetChecksum( (const char*)\"desc\", &descChecksum, false )\r\n\t\t || pParams->GetChecksum( NONAME, &descChecksum, false ) )\r\n\t{\r\n\t\t// either (desc=nnn) or (nnn) is required\r\n\t\tass_man->AddRef(p_asset_filename, descChecksum, 0);\t \r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LoadAnim | loads the specified animation\r\n// @parm string | name | the file name of the animation\r\n// @parm string | desc | description\r\n// @flag async | load animation asynchronously\r\n// returns true if a reference is generated.  false if a reference already exists\r\nbool ScriptLoadAnim( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t Ass::CAssMan * ass_man =  Ass::CAssMan::Instance();\r\n\r\n\t// an anim is just like an asset, except it has a reference added to it\r\n\t\t\r\n\tconst char* p_asset_filename;\r\n\tuint32 descChecksum = 0;\r\n\tpParams->GetText( CRCD(0xa1dc81f9,\"name\"), &p_asset_filename );\r\n\r\n\tpParams->GetChecksum( CRCD(0x4d20d794,\"descChecksum\"), &descChecksum, true );\r\n\r\n\tbool async = false;\r\n\tif( pParams->ContainsFlag( CRCD(0x90e07c79,\"async\") ))\r\n\t{\r\n\t\tasync = true;\r\n\t}\r\n\r\n\tbool use_pip = false;\r\n\tif( pParams->ContainsFlag( CRCD(0x23028e29,\"use_pip\") ))\r\n\t{\r\n\t\tuse_pip = true;\r\n\t}\r\n\r\n\treturn ass_man->LoadAnim( p_asset_filename, descChecksum, ass_man->GetReferenceChecksum(), async, use_pip );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LoadSkeleton | loads the specified skeleton\r\n// @parm string | name | the file name of the skeleton\r\n// @parm string | desc | description\r\nbool ScriptLoadSkeleton( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tAss::CAssMan* ass_man =  Ass::CAssMan::Instance();\r\n\r\n\tconst char* nameBuf;\r\n\tpParams->GetText( (const char*)\"name\", &nameBuf, Script::ASSERT );\r\n\r\n\tuint32 skeletonName;\r\n\tpParams->GetChecksum( NONAME, &skeletonName, Script::ASSERT );\r\n\t\r\n//    Gfx::CSkeletonData* pSkeletonData = (Gfx::CSkeletonData*)ass_man->LoadOrGetAsset(nameBuf, false, ass_man->GetDefaultPermanent());\r\n    Gfx::CSkeletonData* pSkeletonData = (Gfx::CSkeletonData*)ass_man->LoadOrGetAsset(nameBuf, false, false, ass_man->GetDefaultPermanent(), 0);\r\n\tif ( !pSkeletonData )\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"Failed to load skeleton %s\",nameBuf));\r\n\t}\r\n\r\n\t// Now add the reference to it, if one was requested\r\n\t// this gets combined with the \"reference checksum\"\r\n\tif (!ass_man->AssetLoaded(skeletonName))\r\n\t{\r\n\t\tass_man->AddRef(nameBuf, skeletonName, 0);\t \r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptAssManSetReferenceChecksum( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t Ass::CAssMan * ass_man =  Ass::CAssMan::Instance();\r\n\r\n\tuint32 checksum;\r\n\tif ( !pParams->GetChecksum( NONAME, &checksum ) )\r\n\t{\r\n\t\tpParams->GetInteger( NONAME, (int*)&checksum, true );\r\n\t}\r\n\r\n\tass_man->SetReferenceChecksum( checksum );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptAssManSetDefaultPermanent( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t Ass::CAssMan * ass_man =  Ass::CAssMan::Instance();\r\n\r\n\tint permanent;\r\n\tpParams->GetInteger( NONAME, &permanent, true );\r\n\r\n\tass_man->SetDefaultPermanent( permanent );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#define CHECKSUM_PITCH\t\t0xd8604126\t// \"pitch\"\r\n#define CHECKSUM_DROPOFF\t0xff2020ec\t// \"dropoff\"\r\n#define CHECKSUM_VOLUME\t\t0xf6a36814\t// \"vol\"\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LoadSound | \r\n// @uparm \"string\" | The name of the sound file\r\n// @parmopt float | pitch | 100.0 | \r\n// @parmopt float | volume | 100.0 | \r\n// @parmopt float | dropoff | 0.0 | \r\n// @flag PosUpdateWithDoppler | positional update with doppler\r\n// @flag NoReverb | reverb effect disabled for this sound\r\nbool ScriptLoadSound( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tconst char *pSfxName;\r\n\tif ( pParams->GetText( NONAME, &pSfxName, true ) )\r\n\t{\r\n\t\tfloat volume = 100.0f;\r\n\t\tfloat pitch = 100.0f;\r\n\t\tfloat dropoff = 0.0f;\r\n\t\tint flags = 0;\r\n\t\tpParams->GetFloat( CHECKSUM_PITCH, &pitch );\r\n\t\tif ( pParams->GetFloat( CHECKSUM_DROPOFF, &dropoff ) )\r\n\t\t{\r\n\t\t\tdropoff = FEET_TO_INCHES( dropoff );\r\n\t\t}\r\n\t\tpParams->GetFloat( CHECKSUM_VOLUME, &volume );\r\n\t\t\r\n\t\tif ( pParams->ContainsFlag( CHECKSUM_FLAG_PERM ) )\r\n\t\t{\r\n\t\t\tflags |= SFX_FLAG_LOAD_PERM;\r\n\t\t}\r\n\t\tif ( pParams->ContainsFlag( 0xcf15c120 ) ) //\"PosUpdateWithDoppler\"\r\n\t\t{\r\n\t\t\tflags |= SFX_FLAG_POSITIONAL_UPDATE_WITH_DOPPLER;\r\n\t\t}\r\n\t\telse if ( pParams->ContainsFlag( CRCD(0x8b87176f,\"NoReverb\") ) )\r\n\t\t{\r\n\t\t\tflags |= SFX_FLAG_NO_REVERB;\r\n\t\t}\r\n\t\t//else if ( pParams->ContainsFlag( 0x14f9c4fe ) ) // \"PosUpdate\"\r\n\t\t//{\r\n\t\t//\tflags |= SFX_FLAG_POSITIONAL_UPDATE;\r\n\t\t//}\r\n\t\t\t\r\n\t\t Sfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\t\tif ( !sfx_manager->LoadSound( pSfxName, flags, dropoff, pitch, volume ) )\r\n\t\t{\r\n//\t\t\tprintf( \"sound %s couldn't load\\n\", pSfxName );\r\n\t\t}\r\n\t}\r\n\treturn ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PlayStream | \r\n// @uparm name | stream name\r\n// @parmopt float | volume | 100.0 | volume of both left and right channel in percent (overrides volL and volR)\r\n// @parmopt float | volL | 100.0 | volume of left channel\r\n// @parmopt float | volR | 100.0 | volume of right channel\r\n// @parmopt float | pitch | 100.0 | pitch value\r\n// @parmopt int | priority | 50 | priority; higher priority streams can stop lower priority streams.\r\n// @parmopt name | id | 0 | control ID (used instead of stream name for script control purposes)\r\n// @parmopt int | lipsync | 0 | set to 1 to load lipsync data\r\nbool ScriptPlayStream( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tuint32 streamNameChecksum = 0;\r\n\tif ( pParams->GetChecksum( NONAME, &streamNameChecksum ) )\r\n\t{\r\n\t\tfloat volume = 100.0f;\r\n\t\tfloat volL = 100.0f;\r\n\t\tfloat volR = 100.0f;\r\n\t\tfloat pitch = 100.0f;\r\n\t\tint priority = STREAM_DEFAULT_PRIORITY;\r\n\t\tuint32 id = 0;\r\n\t\tint lipsync = 0;\r\n\t\tpParams->GetFloat( \"volL\", &volL );\r\n\t\tpParams->GetFloat( \"volR\", &volR );\r\n\t\tif (pParams->GetFloat( CHECKSUM_VOLUME, &volume ))\r\n\t\t{\r\n\t\t\tvolL = volume;\r\n\t\t\tvolR = volume;\r\n\t\t}\r\n\t\tpParams->GetFloat( CHECKSUM_PITCH, &pitch );\r\n\t\tpParams->GetInteger( 0x9d5923d8, &priority ); // priority\r\n\t\tpParams->GetChecksum( 0x40c698af, &id ); // id\r\n\t\tpParams->GetInteger( CRCD(0xf5c3922b,\"lipsync\") , &lipsync );\r\n\r\n\t\tif (lipsync == 1)\r\n\t\t{\r\n\t\t\tbool loaded = Pcm::CStreamFrameAmpManager::sLoadFrameAmp(streamNameChecksum);\r\n\t\t\tif (!loaded)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0,( \"Couldn't load lipsync data for stream %s\", Script::FindChecksumName(streamNameChecksum)));\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tSfx::sVolume\tvol( Sfx::VOLUME_TYPE_BASIC_2_CHANNEL );\r\n\t\tvol.SetChannelVolume( 0, volL );\r\n\t\tvol.SetChannelVolume( 1, volR );\r\n\t\tPcm::PlayStream( streamNameChecksum, &vol, pitch, priority, id );\r\n\r\n\t\treturn ( true );\r\n\t}\r\n\tDbg_MsgAssert( 0,( \"\\n%s\\nMust specify stream name.\", pScript->GetScriptInfo( ) ));\r\n\treturn ( false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StopStream | stops current stream from playing\r\n// @uparm name | stream name (or control ID, if one was supplied with PlayStream)\r\nbool ScriptStopStream( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tuint32 id;\r\n\tif (pParams->GetChecksum( NONAME, &id ))\r\n\t{\r\n\t\tPcm::StopStreamFromID( id );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tPcm::StopStreams( -1 );\t\t// Stop all streams\r\n\t}\r\n\r\n\treturn ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsStreamPlaying | Returns true if the named stream is currently playing\r\n// @uparm name | stream name (or control ID, if one was supplied with PlayStream)\r\nbool ScriptIsStreamPlaying( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 id = 0;\r\n    \r\n\tif (pParams->GetChecksum( NONAME, &id ))\r\n\t{\r\n\t\treturn Pcm::StreamPlaying(id);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"No stream specified\"));\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetStreamParams | Set the volume or pitch of a playing stream\r\n// @uparm name | stream name (or control ID, if one was supplied with PlayStream)\r\n// @parmopt float | vol | 100.0 | volume of both left and right channel (overrides volL and volR)\r\n// @parmopt float | volL | 100.0 | volume of left channel\r\n// @parmopt float | volR | 100.0 | volume of right channel\r\n// @parmopt float | pitch | 100.0 | pitch\r\nbool ScriptSetStreamParams( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 id = 0;\r\n    \r\n\tif (pParams->GetChecksum( NONAME, &id ))\r\n\t{\r\n\t\tfloat Volume;\r\n\t\tfloat VolL;\r\n\t\tfloat VolR;\r\n\t\tfloat Pitch;\r\n\r\n\t\tbool adjust_vol;\r\n\r\n\t\tadjust_vol = pParams->GetFloat( CRCD(0x5e285a66,\"VolL\"), &VolL );\r\n\t\tadjust_vol = pParams->GetFloat( CRCD(0xa4276705,\"VolR\"), &VolR ) || adjust_vol;\r\n\t\tif (pParams->GetFloat( CRCD(0xf6a36814,\"Vol\"), &Volume ))\r\n\t\t{\r\n\t\t\tVolL = Volume;\r\n\t\t\tVolR = Volume;\r\n\t\t\tadjust_vol = true;\r\n\t\t}\r\n\r\n\t\tbool result = true;\r\n\r\n\t\tif (adjust_vol)\r\n\t\t{\r\n\t\t\tSfx::sVolume vol;\r\n\t\t\tvol.SetSilent();\r\n\t\t\tvol.SetChannelVolume( 0, VolL );\r\n\t\t\tvol.SetChannelVolume( 1, VolR );\r\n\r\n\t\t\tresult = Pcm::SetStreamVolumeFromID(id, &vol);\r\n\t\t}\r\n\r\n\t\tif (pParams->GetFloat( CRCD(0xd8604126,\"Pitch\"), &Pitch ))\r\n\t\t{\r\n\t\t\tresult = Pcm::SetStreamPitchFromID(id, Pitch) && result;\r\n\t\t}\r\n\r\n\t\tif (!result)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"Can't find stream %s\", Script::FindChecksumName(id)));\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"No stream specified\"));\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PlayTrack | \r\n// @uparm \"string\" | filename in quotes (no extension, file should be a \r\n// .wav file in data/music)\r\n// @uparmopt 0 | The index of the track. For use if the name is not known.\r\n// @parmopt int | loop | 0 | continuously play the track if set to non-zero\r\nbool ScriptPlayTrack( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tconst char *songName = NULL;\r\n\tchar p_calculated_track_name[MAX_TRACKNAME_STRING_LENGTH];\r\n    int track_num=999;\r\n\tint loop = 0;\r\n\t\r\n    if (!pParams->GetText( NONAME, &songName ))\r\n\t{\r\n        pParams->GetInteger(NONAME,&track_num);\r\n        songName=Pcm::GetTrackName(track_num,Pcm::TRACKLIST_PERM);\r\n        \r\n\t\tDbg_MsgAssert(strlen(\"MUSIC\\\\VAG\\\\SONGS\\\\\")+strlen(songName)<MAX_TRACKNAME_STRING_LENGTH,(\"Track name '%s' too long\",songName));\r\n\t\tsprintf(p_calculated_track_name,\"MUSIC\\\\VAG\\\\SONGS\\\\%s\",songName);\r\n\t\tsongName=p_calculated_track_name;\r\n\t}\t\r\n\r\n\tpParams->GetInteger(CRCD(0x5ea0e211,\"loop\"), &loop);\r\n\r\n    if ( songName )\r\n\t{\r\n\t\tprintf(\"PlayTrack songName ===================== %s\\n\", songName);\r\n        Pcm::StopMusic( );\r\n        Pcm::PlayTrack( songName, loop );\r\n        Pcm::SetCurrentTrack( track_num );\r\n\t}\r\n\treturn ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PlayMusicStream | Plays a stereo stream through the music channel\r\n// @uparm name | music stream name (in music.wad file)\r\n// @parmopt float | volume | -1.0 | volume in percent; negative value uses music volume\r\nbool ScriptPlayMusicStream( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tuint32 streamNameChecksum = 0;\r\n\tif ( pParams->GetChecksum( NONAME, &streamNameChecksum ) )\r\n\t{\r\n\t\tfloat volume = -1.0f;\r\n\t\tpParams->GetFloat( CHECKSUM_VOLUME, &volume );\r\n\t\tPcm::PlayMusicStream( streamNameChecksum, volume );\r\n\t\treturn ( true );\r\n\t}\r\n\tDbg_MsgAssert( 0,( \"\\n%s\\nMust specify stream name.\", pScript->GetScriptInfo( ) ));\r\n\treturn ( false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LoadStreamFrameAmp | Loads stream frame amplitude data for lipsync\r\n// @uparm name | stream name\r\nbool ScriptLoadStreamFrameAmp( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 streamNameChecksum = 0;\r\n\tif ( pParams->GetChecksum( NONAME, &streamNameChecksum ) )\r\n\t{\r\n\t\treturn Pcm::CStreamFrameAmpManager::sLoadFrameAmp(streamNameChecksum);\r\n\t}\r\n\tDbg_MsgAssert( 0,( \"\\n%s\\nMust specify stream name.\", pScript->GetScriptInfo( ) ));\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | FreeStreamFrameAmp | Frees stream frame amplitude data for lipsync\r\n// @uparm name | stream name\r\nbool ScriptFreeStreamFrameAmp( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 streamNameChecksum = 0;\r\n\tif ( pParams->GetChecksum( NONAME, &streamNameChecksum ) )\r\n\t{\r\n\t\treturn Pcm::CStreamFrameAmpManager::sFreeFrameAmp(streamNameChecksum);\r\n\t}\r\n\tDbg_MsgAssert( 0,( \"\\n%s\\nMust specify stream name.\", pScript->GetScriptInfo( ) ));\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PlaySound | \r\n// @uparm name | sound name\r\n// @parmopt float | vol | 100.0 | volume of both left and right channel (overrides volL and volR)\r\n// @parmopt float | volL | 100.0 | volume of left channel\r\n// @parmopt float | volR | 100.0 | volume of right channel\r\n// @parmopt float | pitch | 100.0 | \r\n// @parmopt name | id | 0 | control ID (used instead of sound name for script control purposes)\r\nbool ScriptPlaySound(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 SoundChecksum = 0;\r\n\tuint32 id = 0;\r\n\tfloat Volume = 100.0f;\r\n\tfloat VolL = 100.0f;\r\n\tfloat VolR = 100.0f;\r\n\tfloat Pitch = 100.0f;\r\n    \r\n\tpParams->GetChecksum( NONAME, &SoundChecksum );\r\n\tpParams->GetFloat( \"VolL\", &VolL );\r\n\tpParams->GetFloat( \"VolR\", &VolR );\r\n\tif (pParams->GetFloat( \"Vol\", &Volume ))\r\n\t{\r\n\t\tVolL = Volume;\r\n\t\tVolR = Volume;\r\n\t}\r\n\tpParams->GetFloat( \"Pitch\", &Pitch );\r\n\tpParams->GetChecksum( CRCD(0x40c698af,\"id\"), &id );\r\n\r\n\tDbg_MsgAssert( SoundChecksum,( \"PlaySound requires the name of the sound\" ));\r\n\t\r\n\tSfx::sVolume vol;\r\n\tvol.SetSilent();\r\n\tvol.SetChannelVolume( 0, VolL );\r\n\tvol.SetChannelVolume( 1, VolR );\r\n\t\r\n\tSfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\tif( !sfx_manager->PlaySound( SoundChecksum, &vol, Pitch, id ))\r\n\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\tprintf( \"failed to play sound %s\", Script::FindChecksumName( SoundChecksum ) );\r\n#endif\t\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StopSound | \r\n// @uparm name | sound name (or control ID, if one was supplied with PlaySound)\r\nbool ScriptStopSound( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 id;\r\n\tif (pParams->GetChecksum( NONAME, &id ))\r\n\t{\r\n\t\tSfx::CSfxManager* sfx_manager = Sfx::CSfxManager::Instance();\r\n\t\tbool result = sfx_manager->StopSound(id);\r\n\r\n\t\tif (!result)\r\n\t\t{\r\n\t\t\tDbg_Message( \"Couldn't find sound %s to stop\", Script::FindChecksumName( id ) );\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"No sound specified\"));\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StopAllSounds | \r\nbool ScriptStopAllSounds(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tSfx::CSfxManager* sfx_manager = Sfx::CSfxManager::Instance();\r\n    sfx_manager->StopAllSounds();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetSoundParams | Set the volume and pitch of a playing sound\r\n// @uparm name | sound name (or control ID, if one was supplied with PlaySound)\r\n// @parmopt float | vol | 100.0 | volume of both left and right channel (overrides volL and volR)\r\n// @parmopt float | volL | 100.0 | volume of left channel\r\n// @parmopt float | volR | 100.0 | volume of right channel\r\n// @parmopt float | pitch | 100.0 | pitch of sound\r\nbool ScriptSetSoundParams( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 id = 0;\r\n    \r\n\tif (pParams->GetChecksum( NONAME, &id ))\r\n\t{\r\n\t\tfloat Volume;\r\n\t\tfloat VolL = 100.0f;\r\n\t\tfloat VolR = 100.0f;\r\n\t\tfloat Pitch = 100.0f;\r\n\r\n\t\tbool adjust_vol;\r\n\r\n\t\tadjust_vol = pParams->GetFloat( CRCD(0x5e285a66,\"VolL\"), &VolL );\r\n\t\tadjust_vol = pParams->GetFloat( CRCD(0xa4276705,\"VolR\"), &VolR ) || adjust_vol;\r\n\t\tif (pParams->GetFloat( CRCD(0xf6a36814,\"Vol\"), &Volume ))\r\n\t\t{\r\n\t\t\tVolL = Volume;\r\n\t\t\tVolR = Volume;\r\n\t\t\tadjust_vol = true;\r\n\t\t}\r\n\r\n\t\tif (pParams->GetFloat( CRCD(0xd8604126,\"Pitch\"), &Pitch ) && !adjust_vol)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"Must set volume when setting pitch\"));\r\n\r\n\t\t}\r\n\r\n\t\tSfx::sVolume vol;\r\n\t\tvol.SetSilent();\r\n\t\tvol.SetChannelVolume( 0, VolL );\r\n\t\tvol.SetChannelVolume( 1, VolR );\r\n\r\n\t\tSfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\t\tif( !sfx_manager->SetSoundParams( id, &vol, Pitch ))\r\n\t\t{\r\n\t#ifdef __NOPT_ASSERT__\r\n\t\t\tDbg_MsgAssert(0, (\"Can't find sound %s\", Script::FindChecksumName(id)));\r\n\t#endif // __NOPT_ASSERT__\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"No sound specified\"));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsSoundPlaying | Returns true if the named sound is currently playing\r\n// @uparm name | sound name (or control ID, if one was supplied with PlaySound)\r\nbool ScriptIsSoundPlaying( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 id = 0;\r\n    \r\n\tif (pParams->GetChecksum( NONAME, &id ))\r\n\t{\r\n\t\tSfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\t\treturn sfx_manager->SoundIsPlaying(id);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"No sound specified\"));\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetSfxReverb | 1st param: reverbLevel <nl>\r\n// default 0 (will turn reverb off) <nl>\r\n// range: 0 to 100 percent <nl>\r\n// 2nd param: mode (see possible values in reverb.q) <nl>\r\n// default is 0 (first value in reverb.q) <nl> <nl>\r\n// Notes: 2nd param (mode) only matters if 1st param (reverbLevel) is \r\n// above 0. On a script Cleanup command, the global reverb is turned off.\r\n// @uparmopt 0.0 | Reverb (cannot be greater than 100)\r\n// @uparmopt name | reverb mode\r\nbool ScriptSetReverb( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tfloat reverb = 0.0f;\r\n\tint reverbMode = 0;\r\n\r\n\t// if the parameter isn't found, it should default to zero!\t\r\n\tpParams->GetFloat( NONAME, &reverb );\r\n\tif ( reverb > 100.0f )\r\n\t{\r\n\t\treverb = 100.0f;\r\n\t\tDbg_Message( \"Reverb greater than 100.  Clipping.\" );\r\n\t}\r\n\t\r\n\t// if the parameter isn't found, it should default to zero!\t\r\n\tpParams->GetInteger( CRCD(0x6835b854,\"mode\"), &reverbMode );\r\n\t\r\n\t Sfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\tsfx_manager->SetReverb( reverb, reverbMode, pParams->ContainsFlag( \"instant\" ) );\r\n\t\r\n\treturn ( true );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetSfxDropoff | SetSfxDropoff [100] <nl>\r\n// Param: dropoff distance (in feet) <nl>\r\n// range: anything above zero <nl>\r\n// default is 100 <nl> <nl>\r\n// Notes: only affects positional soundfx. Also, the global\r\n// dropoff distance is set back to 100 (or whatever you want me\r\n// to set it to) on a script Cleanup command. That way, if somebody \r\n// forgets to call SetSfxDropoff at the beginning of their level, it \r\n// will always be this default instead of staying at whatever level\r\n// the previously loaded level had it set to\r\n// @uparm 1.0 | Dropoff distance\r\nbool ScriptSetDropoff( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tfloat dropoffDist = DEFAULT_DROPOFF_DIST;\r\n\r\n\tpParams->GetFloat( NONAME, &dropoffDist );\r\n\tif ( dropoffDist <= 0.0f )\r\n\t{\r\n\t\tDbg_MsgAssert( 0.0f,( \"Can't have dropoff zero or less.\" ));\r\n\t\treturn ( false );\r\n\t}\r\n\t\r\n\t Sfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\tsfx_manager->SetDefaultDropoffDist( FEET_TO_INCHES( dropoffDist ) );\r\n\t\r\n\treturn ( true );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n\r\nvoid\tset_all_colors(Nx::CScene * p_scene, Image::RGBA rgb, uint32 light_group)\r\n{\r\n\tLst::HashTable< Nx::CSector > * p_sector_list = p_scene->GetSectorList();\r\n\t\r\n\r\n\t\r\n\tif (p_sector_list)\r\n\t{\r\n\t\tp_sector_list->IterateStart();\t\r\n\t\tNx::CSector *p_sector = p_sector_list->IterateNext();\t\t\r\n\t\tif (light_group)\r\n\t\t{\r\n\t\t\twhile(p_sector)\r\n\t\t\t{\r\n\t\t\t\tif (p_sector->GetLightGroup() == light_group)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_sector->SetColor(rgb);\r\n\t\t\t\t}\r\n\t\t\t\tp_sector = p_sector_list->IterateNext();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\twhile(p_sector)\r\n\t\t\t{\r\n\t\t\t\tp_sector->SetColor(rgb);\r\n\t\t\t\tp_sector = p_sector_list->IterateNext();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n// Given a value, a target and a range, then scale the distance from the target by the amount\r\n// so, \r\nfloat compress_value(float value, float target, float amount)\r\n{\r\n\tfloat v =  target + (value-target) * amount;\r\n\tif (v<0.0f) v = 0.0f;\r\n\tif (v>255.0f) v = 255.0f;\r\n\treturn v;\r\n}\r\n\r\nvoid\tcompress_all_vertex_colors(Nx::CScene * p_scene, float target, float amount, uint32 light_group)\r\n{\r\n\tLst::HashTable< Nx::CSector > * p_sector_list = p_scene->GetSectorList();\r\n\t\r\n\tImage::RGBA rgb;\r\n\t\r\n\t\r\n\tif (p_sector_list)\r\n\t{\r\n\t\tp_sector_list->IterateStart();\t\r\n\t\tNx::CSector *p_sector = p_sector_list->IterateNext();\t\t\r\n\t\twhile(p_sector)\r\n\t\t{\r\n\r\n\t\t\tNx::CGeom \t*p_geom = p_sector->GetGeom();\r\n//\t\t\tDbg_MsgAssert(p_geom,(\"sector does not have geometry\"))\r\n\t\t\t\r\n\t\t\tif (p_geom && (!light_group || light_group == p_sector->GetLightGroup()))\r\n\t\t\t{\r\n\t\t\t\t//\r\n\t\t\t\t// Do renderable geometry\r\n\t\t\t\tint verts = p_geom->GetNumRenderVerts();\r\n\t\t\t\r\n\t\t\t\tif (verts)\r\n\t\t\t\t{\r\n\t//\t\t\t\tMth::Vector\t*p_verts = new Mth::Vector[verts];\r\n\t\t\t\t\tImage::RGBA\t*p_colors = new Image::RGBA[verts];\r\n\t//\t\t\t\tp_geom->GetRenderVerts(p_verts);\r\n\t\t\t\t\t//p_source_geom->GetRenderColors(p_colors);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Note: getting the original render colors will allocate lots of memory\r\n\t\t\t\t\t// to store all the origianl colors the firs tiem it is called\r\n\t\t\t\t\tp_geom->GetOrigRenderColors(p_colors);\r\n\t\t\t\t\r\n\t\t\t\t\tImage::RGBA *p_color = p_colors;\r\n\t\t\t\t\tif (target != 0.0 || amount != 0.0)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfor (int i = 0; i < verts; i++)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\trgb.a = p_color->a; \r\n\t\t\t\t\t\t\trgb.r =  (uint8) compress_value((float) p_color->r,target,amount);\t\t\t\t\t\t\r\n\t\t\t\t\t\t\trgb.g =  (uint8) compress_value((float) p_color->g,target,amount);\t\t\t\t\t\t\r\n\t\t\t\t\t\t\trgb.b =  (uint8) compress_value((float) p_color->b,target,amount);\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t*p_color = rgb;\t\t//(*p_color & 0xff000000) | color;\r\n\t\t\t\t\t\t\tp_color++;\r\n\t\t\t\t\t\t} // end for\r\n\t\t\t\t\t}\r\n\t\t\t\r\n\t\t\t\t\t// Set the colors on the actual new geom, not on the source...\t\t\r\n\t\t\t\t\tp_geom->SetRenderColors(p_colors);\r\n\t\t\t\t\t\r\n\t//\t\t\t\tdelete [] p_verts;\r\n\t\t\t\t\tdelete [] p_colors;\r\n\t\t\t\t} // end if\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// debuggery\r\n\t\t\t\t\t//p_geom->SetColor(Image::RGBA(0,0,100,0));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tp_sector = p_sector_list->IterateNext();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\nvoid\tnudge_vertex_colors(Nx::CScene * p_scene, float amount)\r\n{\r\n\tLst::HashTable< Nx::CSector > * p_sector_list = p_scene->GetSectorList();\r\n\t\r\n\tImage::RGBA rgb;\r\n\t\r\n\tif (p_sector_list)\r\n\t{\r\n\t\tp_sector_list->IterateStart();\t\r\n\t\tNx::CSector *p_sector = p_sector_list->IterateNext();\t\t\r\n\t\twhile(p_sector)\r\n\t\t{\r\n\r\n\t\t\tNx::CGeom \t*p_geom = p_sector->GetGeom();\r\n//\t\t\tDbg_MsgAssert(p_geom,(\"sector does not have geometry\"))\r\n\t\t\t\r\n\t\t\tif (p_geom)\r\n\t\t\t{\r\n\t\t\t\t//\r\n\t\t\t\t// Do renderable geometry\r\n\t\t\t\tint verts = p_geom->GetNumRenderVerts();\r\n\t\t\t\r\n\t\t\t\tif (verts)\r\n\t\t\t\t{\r\n\t\t\t\t\tMth::Vector\t*p_verts = new Mth::Vector[verts];\r\n\t\t\t\t\tImage::RGBA\t*p_colors = new Image::RGBA[verts];\r\n\t\t\t\t\tp_geom->GetRenderVerts(p_verts);\r\n\t\t\t\t\t//p_source_geom->GetRenderColors(p_colors);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Note: getting the original render colors will allocate lots of memory\r\n\t\t\t\t\t// to store all the origianl colors the firs tiem it is called\r\n\t\t\t\t\tp_geom->GetOrigRenderColors(p_colors);\r\n\t\t\t\t\r\n\t\t\t\t\tImage::RGBA *p_color = p_colors;\r\n\t\t\t\t\tMth::Vector *p_vert = p_verts;\r\n\t\t\t\t\tfor (int i = 0; i < verts; i++)\r\n\t\t\t\t\t{\r\n\t\t\t//\t\t\tCalculateVertexLighting(*p_vert, *p_color);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\trgb.a = p_color->a; \r\n\r\n\t\t\t\t\t\tMth::Vector col;\r\n\t\t\t\t\t\tcol.Set(p_color->r, p_color->g, p_color->b);\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t// create a pseudo random number based on the vertex position\r\n\t\t\t\t\t\t// so non-common verts in the same position will get the same result\r\n\t\t\t\t\t\t// which is the only way you can get a smooth result\t\t\t\t\t\t\t \r\n\t\t\t\t\t\tint i_random =  (int)((*p_vert)[X]*16.0f) * (int)((*p_vert)[Y]*16.0f) ^ (int)((*p_vert)[Z]*16.0f);\r\n\t\t\t\t\t\tfloat r1 = (float)(i_random & 0x7fff) / 32768.0f;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tfloat\tnudge = 1.0f + ( 2.0f * r1 * amount ) - amount;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tcol *= \tnudge;\r\n\t\t\t\t\t\tif (col[X] < 0.0f) col[X] = 0.0f;\r\n\t\t\t\t\t\tif (col[X] > 255.0f) col[X] = 255.0f;\r\n\t\t\t\t\t\tif (col[Y] < 0.0f) col[Y] = 0.0f;\r\n\t\t\t\t\t\tif (col[Y] > 255.0f) col[Y] = 255.0f;\r\n\t\t\t\t\t\tif (col[Z] < 0.0f) col[Z] = 0.0f;\r\n\t\t\t\t\t\tif (col[Z] > 255.0f) col[Z] = 255.0f;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\trgb.r = (uint8)col[X];\r\n\t\t\t\t\t\trgb.g = (uint8)col[Y];\r\n\t\t\t\t\t\trgb.b = (uint8)col[Z];\r\n\t\t\t\t\t\t \r\n\t\t\t\t\t\t*p_color = rgb;\t\t//(*p_color & 0xff000000) | color;\r\n\t\t\t\t\t\t//*(uint32*)p_color = Mth::Rnd(32767);\t\t//(*p_color & 0xff000000) | color;\r\n\t\t\t\r\n\t\t\t\t\t\tp_color++;\r\n\t\t\t\t\t\tp_vert++;\r\n\t\t\t\t\t} // end for\r\n\t\t\t\r\n\t\t\t\t\t// Set the colors on the actual new geom, not on the source...\t\t\r\n\t\t\t\t\tp_geom->SetRenderColors(p_colors);\r\n\t\t\t\t\t\r\n\t\t\t\t\tdelete [] p_verts;\r\n\t\t\t\t\tdelete [] p_colors;\r\n\t\t\t\t} // end if\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// debuggery\r\n\t\t\t\t\t//p_geom->SetColor(Image::RGBA(0,0,100,0));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tp_sector = p_sector_list->IterateNext();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\nbool ScriptSetSceneColor( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tuint32 color;\r\n\t\r\n\tpParams->GetInteger( \"color\", (int*)&color, TRUE );\r\n\tuint32 sky = color;\r\n\tpParams->GetInteger( \"sky\", (int*)&sky );\r\n\tuint32 light_group =0;\r\n\tpParams->GetChecksum( \"lightgroup\", (uint32*)&light_group );\t\r\n\tNx::CScene\t*p_scene = Nx::CEngine::sGetMainScene();\r\n\t\r\n\tImage::RGBA rgb;\r\n\trgb.r = (uint8)((color)&0xff);\r\n\trgb.g = (uint8)((color>>8)&0xff);\r\n\trgb.b = (uint8)((color>>16)&0xff);\r\n\trgb.a = 0x80;\r\n\t\r\n\tImage::RGBA sky_rgb;\r\n\tsky_rgb.r = (uint8)((sky)&0xff);\r\n\tsky_rgb.g = (uint8)((sky>>8)&0xff);\r\n\tsky_rgb.b = (uint8)((sky>>16)&0xff);\r\n\tsky_rgb.a = 0x80;\r\n\t\r\n\t\r\n\tif (p_scene)\r\n\t{\r\n\t\t// For main scene, just set the root color\r\n\t\t#ifdef\t__PLAT_NGPS__\r\n\r\n\t\t// if doing a global or outdoor change to some color\r\n\t\t// then reset all the colors first\t\t\r\n\t\t// to reset things that were set by individual SetObjectColor  commands\r\n\t\t// like the Chris's best line goal in NJ\r\n\t\tif \t(color != 0x808080 && (light_group == CRCD(0xe3714dc1,\"outdoor\") || light_group == 0))\r\n\t\t{\r\n\t\t\tImage::RGBA clear_rgb(0x80,0x80,0x80,0x80);\r\n\t\t\tset_all_colors(p_scene, clear_rgb, light_group);\t\t\t\t\t\t\r\n\t\t}\r\n\t\t\r\n\t\t// if not the outdoor or default group, or if we are turing lighting off with 0x808080\r\n\t\t// then set it on all nodes\r\n\t\t// otherwise we just set the root color\r\n\t\tif ((light_group != CRCD(0xe3714dc1,\"outdoor\") && light_group != 0 ) || color == 0x808080 \r\n\t\t\t/*|| p_scene->GetID() ==CRCD(0xefc68238,\"cloned\")*/)\r\n\t\t#endif\r\n\t\t{\r\n\t\t\tset_all_colors(p_scene, rgb, light_group);\r\n\t\t}\r\n\t\t\r\n\t\t// Set the root color of the scene.  A PS2 specific optimization\r\n\t\t// which can be ignored by other platforms.\t\t\r\n\t\tif (light_group == CRCD(0xe3714dc1,\"outdoor\") || light_group == 0)\r\n\t\t{\r\n\t\t\tp_scene->SetMajorityColor(rgb);\r\n\t\t}\r\n\t}\r\n\t\r\n\t// K: If the park editor shell scene exists, update its colours too.\r\n\tp_scene=Nx::CEngine::sGetScene(Ed::CParkManager::Instance()->GetShellSceneID());\r\n\tif (p_scene)\r\n\t{\r\n\t\t// Note, cut and paste from above\r\n\t\t#ifdef\t__PLAT_NGPS__\r\n\t\t// if not the outdoor or default group, or if we are turing lighting off with 0x808080\r\n\t\t// then set it on all nodes\r\n\t\t// otherwise we just set the root color\r\n\t\tif ((light_group != CRCD(0xe3714dc1,\"outdoor\") && light_group != 0 ) || color == 0x808080)\r\n\t\t#endif\r\n\t\t{\r\n\t\t\tset_all_colors(p_scene, rgb, light_group);\r\n\t\t}\r\n\t\t\r\n\t\t// Set the root color of the scene.  A PS2 specific optimization\r\n\t\t// which can be ignored by other platforms.\t\t\r\n\t\tif (light_group == CRCD(0xe3714dc1,\"outdoor\") || light_group == 0)\r\n\t\t{\r\n\t\t\tp_scene->SetMajorityColor(rgb);\r\n\t\t}\r\n\t}\r\n\r\n\t\r\n\tp_scene = Nx::CEngine::sGetSkyScene();\r\n\t\r\n\tif (p_scene)\r\n\t{\r\n\t\tset_all_colors(p_scene, sky_rgb, light_group);\r\n\t}\r\n\t\r\n\t// we also need to set the color of all the level objects\r\n\t// assume they are all \"outdoors\"\r\n\tif (light_group == CRCD(0xe3714dc1,\"outdoor\") || light_group == 0)\r\n\t{\r\n\t\tObj::CModelComponent *p_component = static_cast<Obj::CModelComponent*>( Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType( CRC_MODEL ));\r\n\t\twhile( p_component )\r\n\t\t{\r\n\t\t\tp_component->ApplySceneLighting(rgb);\r\n\t\t\tp_component = static_cast<Obj::CModelComponent*>( p_component->GetNextSameType());\r\n\t\t}\r\n\t}\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool ScriptCompressVC( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\r\n\tfloat target = 0.0f;\r\n\tpParams->GetFloat( \"target\", (float*)&target, TRUE );\r\n\tfloat amount = 0.0f;\r\n\tpParams->GetFloat( \"percent\", (float*)&amount );\r\n\tamount = (100.0f - amount)/100.0f;\r\n\tuint32 light_group =0;\r\n\tpParams->GetChecksum( \"lightgroup\", (uint32*)&light_group );\t\r\n\r\n\tNx::CScene\t*p_scene = Nx::CEngine::sGetMainScene();\r\n\tif (p_scene)\r\n\t{\r\n\t\tcompress_all_vertex_colors(p_scene, target, amount, light_group);\r\n\t}\r\n\tp_scene = Nx::CEngine::sGetSkyScene();\r\n\tif (p_scene)\r\n\t{\r\n\t\tcompress_all_vertex_colors(p_scene, target, amount, light_group);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n// @script bool | FakeLights | Adjust lighting for a node-based SceneLight.\r\n// @parm name | id | The name of the node, if only one needs adjusting.\r\n// @parm name | Prefix | The prefix of a set of nodes, if lots need adjusting.\r\n// @parmopt integer | Time | 0 | The time period, in frames, over which the execution of the command\r\n// will be spread so as not to use up too much CPU time in one frame.\r\n// @parmopt float | inner_radius | none | The new radius of the light in inches\r\n// @parmopt float | outer_radius | none | The new radius of the light in inches\r\n// @parmopt float | percent | none | The new intensity percentage\r\n// @parmopt integer | red | none | The new red component of the light color (also green, blue)\r\nbool ScriptFakeLights( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t// If an id is supplied, we want to apply the effect to just one light.\r\n\tuint32 id = 0; \r\n\tif( pParams->GetChecksum( CRCD(0x40c698af,\"id\"), &id ))\r\n\t{\r\n\t\tNx::CLightManager::sFakeLight(id,pParams);\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Get the period in frames over which the command will execute.\r\n\tint time_period=0;\r\n\tpParams->GetInteger(CRCD(0x906b67ba,\"time\"),&time_period);\r\n\t\r\n\t// K: Added this bit to allow a set of nodes with a given prefix to be adjusted.\r\n\tuint32 prefix=0;\t\r\n    if ( pParams->GetChecksumOrStringChecksum( CRCD(0x6c4e7971,\"Prefix\"), &prefix ) )\r\n\t{\r\n\t\tuint16 num_nodes = 0;\r\n\t\tconst uint16 *p_nodes = SkateScript::GetPrefixedNodes( prefix, &num_nodes );\r\n\t\t\r\n\t\tNx::CLightManager::sFakeLights(p_nodes,num_nodes,time_period,pParams);\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool ScriptNudgeVC( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\r\n\tfloat amount = 0.0f;\r\n\tpParams->GetFloat( \"percent\", (float*)&amount, true );\r\n\tamount = (amount)/100.0f;\r\n\tNx::CScene\t*p_scene = Nx::CEngine::sGetMainScene();\r\n\tif (p_scene)\r\n\t{\r\n\t\tnudge_vertex_colors(p_scene,amount);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n// Center the viewer camera on the scene\r\n// (Previously this would center the current camera on the scene, which had unintended results)\r\nvoid\tcenter_camera_on_scene(Nx::CScene * p_scene, float scale, float x_rot, float y_rot, float z_rot, uint32 id=0)\r\n{\r\n\r\n\t// get a bounding box of the world, and center the camera on that\t\r\n\tMth::CBBox bbox;\r\n\t\r\n\tLst::HashTable< Nx::CSector > * p_sector_list = p_scene->GetSectorList();\r\n\tif (p_sector_list)\r\n\t{\r\n\t\tp_sector_list->IterateStart();\t\r\n\t\tNx::CSector *p_sector = p_sector_list->IterateNext();\t\t\r\n\t\twhile(p_sector)\r\n\t\t{\r\n\r\n\t\t\tif ((!id || id == p_sector->GetChecksum()) && p_sector->IsActive())\r\n\t\t\t{\r\n\t\t\t\t\r\n\t\t\t\tNx::CGeom \t*p_geom = p_sector->GetGeom();\r\n\t\t\t\tif (p_geom)\r\n\t\t\t\t{\r\n\t\t\t\t\t//\r\n\t\t\t\t\t// Do renderable geometry\r\n\t\t\t\t\tint verts = p_geom->GetNumRenderVerts();\r\n\t\t\t\t\tif (verts)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMth::Vector\t*p_verts = new Mth::Vector[verts];\r\n\t\t\t\t\t\tp_geom->GetRenderVerts(p_verts);\r\n\t\t\t\t\t\tMth::Vector *p_vert = p_verts;\r\n\t\t\t\t\t\tfor (int i = 0; i < verts; i++)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tbbox.AddPoint(*p_vert);\r\n\t\t\t\t\t\t\t//printf (\"%f,%f,%f,%f\\n\",p_vert[0][X],p_vert[0][Y],p_vert[0][Z],p_vert[0][W]);\r\n//\t\t\t\t\t\t\tif (i>0)\r\n//\t\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t\tGfx::AddDebugLine(p_vert[0],p_vert[-1],0xffffff,100);\r\n//\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tp_vert++;\r\n\t\t\t\t\t\t} // end for\r\n\t\t\t\t\r\n\t\t\t\t\t\tdelete [] p_verts;\r\n\t\t\t\t\t} // end if\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tp_sector = p_sector_list->IterateNext();\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t\r\n\t\r\n\t// Move the camera to the object, and move it back by the width of the object (min 100 ft)\r\n//    Gfx::Camera* pCam = Nx::CViewportManager::sGetCamera( 0 );\r\n\r\n// Mick:  Now we attempt to get the viewer camera object\r\n\r\n\tObj::CCompositeObject *p_obj = (Obj::CCompositeObject *)Obj::CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0xeb17151b,\"viewer_cam\"));\r\n\tif (!p_obj)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t\t\t\t\t\t\t\t \r\n\tDbg_MsgAssert(GetCameraComponentFromObject(p_obj),(\"Viewer Camera Object Missing camera component\"));\r\n\t\r\n\t\r\n\tMth::Vector min = bbox.GetMin();\r\n\tMth::Vector max = bbox.GetMax();\r\n\tMth::Vector mid = (min + max)/2.0f;\r\n\tfloat\tdiagonal = (max - min).Length();\r\n\tif (diagonal < 1000)\r\n\t{\r\n\t\tdiagonal = 1000;\r\n\t}\r\n\r\n\r\n\tdiagonal *= scale;\r\n\r\n\t// Note we are moving the parent object, the camera component takes its pos from this\r\n\tp_obj->GetMatrix().Ident();\r\n\tp_obj->GetMatrix().RotateX(Mth::DegToRad(x_rot));\r\n\tp_obj->GetMatrix().RotateY(Mth::DegToRad(y_rot));\r\n\tp_obj->GetMatrix().RotateZ(Mth::DegToRad(z_rot));\r\n\r\n\t// printf (\"diagonal = %f, mid = [%f,%f,%f]\\nbox = [%f,%f,%f] - [%f,%f,%f]\\n\",diagonal,mid[X],mid[Y],mid[Z],min[X],min[Y],min[Z],max[X],max[Y],max[Z]  );\t\r\n\r\n\tp_obj->SetPos(mid + scale * diagonal * p_obj->GetMatrix().GetAt());\r\n\r\n\t\r\n}\r\n\r\n\r\n// @script | CenterCamera |  Center the camera on the rendered geometry, or an individual object\r\n// @parmopt float | scale | 0.9 | \r\n// @parmopt float | X | -45 | Angle to rotate about X \r\n// @parmopt float | Y | 45 | Angle to rotate about Y\r\n// @parmopt float | Z | 0 | Angle to rotate about X\r\n// @parmopt\tchecksum | id | 0 | checksum of and individual object to center on\r\n// Notes:  The Camera will be centered on the center of the bounding box\r\n// of all exported geometry.  It will be moved back by the size of the diagonal\r\n// of the bounding box, and rotated by the X,Y,Z angles\r\n\r\nbool ScriptCenterCamera( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t// This is only interend to be used in the fly around modes\r\n\t// so kill it during menus\r\n\r\n\tif (!Mdl::CViewer::sGetViewMode())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\r\n\tfloat scale = 0.9f;\r\n\tpParams->GetFloat( \"scale\", &scale );\r\n\tfloat X = -45.0f;;\r\n\tpParams->GetFloat( \"x\", &X );\r\n\tfloat Y = 45.0f;\r\n\tpParams->GetFloat( \"y\", &Y );\r\n\tfloat Z = 0.0f;\r\n\tpParams->GetFloat( \"z\", &Z );\r\n\tuint32 id = 0; \r\n\tpParams->GetChecksum( \"id\", &id );\r\n\r\n\r\n\r\n\r\n\tNx::CScene\t*p_scene = Nx::CEngine::sGetMainScene();\r\n\tif (p_scene)\r\n\t{\r\n\t\tcenter_camera_on_scene(p_scene, scale, X, Y, Z, id);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n#define CHECKSUM_MAXPITCH\t\t\t0xfa3e14c5\t// maxpitch\r\n#define CHECKSUM_MINPITCH\t\t\t0x1c5ebb24\t// minpitch\r\n#define CHECKSUM_MAXVOL\t\t\t\t0x0693daaf\t// maxvol\r\n#define CHECKSUM_MINVOL\t\t\t\t0x4391992d\t// minvol\r\n#define CHECKSUM_TERRAIN\t\t\t0x3789ac4e  // terrain\r\n#define CHECKSUM_TABLE\t\t\t\t0x09d670b9  // table\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LoadTerrainSounds | Loads all the associated sounds for a terrain type of a level.\r\n// @parm name | terrain | Name of terrain\r\n\r\nbool ScriptLoadTerrainSounds( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 terrain_checksum;\r\n\r\n\tif (!pParams->GetChecksum(CHECKSUM_TERRAIN, &terrain_checksum))\r\n\t{\r\n\t\tprintf(\"Expected terrain checksum\\n\");\r\n\t\treturn false;\r\n\t}\r\n\r\n\tETerrainType terrain = Env::CTerrainManager::sGetTerrainFromChecksum(terrain_checksum);\r\n\tEnv::CTerrainManager::sLoadTerrainSounds(terrain);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Goto | jumps to the specified script\r\n// @Uparm name | The name of the script \r\n// @parmopt structure | Params | | parameter list to pass to the new script\r\nbool ScriptGoto(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tuint32 ScriptChecksum=0;\r\n\tpParams->GetChecksum(NONAME,&ScriptChecksum);\r\n\tDbg_MsgAssert(ScriptChecksum,(\"Goto command requires a script name\"));\r\n\t\r\n\tScript::CStruct *pArgs=NULL;\r\n\tpParams->GetStructure(CRCD(0x7031f10c,\"Params\"),&pArgs);\r\n\tpScript->SetScript(ScriptChecksum,pArgs,pScript->mpObject);\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GotoPreserveParams | This has the same effect as goto, \r\n// except all the parameters that were passed to the current script \r\n// will get passed to the new script\r\n// @Uparm name | The name of the script to goto\r\n// @parmopt structure | Params | | additional parameters to pass to script\r\nbool ScriptGotoPreserveParams(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tuint32 ScriptChecksum=0;\r\n\tpParams->GetChecksum(NONAME,&ScriptChecksum);\r\n\tDbg_MsgAssert(ScriptChecksum,(\"GotoPreserveParams command requires a script name\"));\r\n\t\r\n\t// Extract the old script parameters.\r\n\t// Note: Need to do it this way rather than pass pScript->GetParams() to pScript->SetScript,\r\n\t// because SetScript will clear the pScript's params before using the passed params, but\r\n\t// since the passed params ARE the pScript's params, this will mean they will get zeroed.\r\n\tScript::CStruct *pTemp=new Script::CStruct;\r\n\tpTemp->AppendStructure(pScript->GetParams());\r\n\t\r\n\t// If any more params are specified, merge them on too.\r\n\tScript::CStruct *pMoreParams=NULL;\r\n\tpParams->GetStructure(CRCD(0x7031f10c,\"Params\"),&pMoreParams);\r\n\tpTemp->AppendStructure(pMoreParams);\r\n\t\r\n\t\r\n\tpScript->SetScript(ScriptChecksum,pTemp,pScript->mpObject);\r\n\tdelete pTemp;\r\n\t\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GotoRandomScript | This will abort the current script\r\n// and jump to a random one of the scripts specified in an array. <nl>\r\n// For example: <nl>\r\n// GotoRandomScript [ScriptA ScriptB ScriptC]\r\n// @uparm [] | Array of scripts to choose from\r\n\r\nbool ScriptGotoRandomScript(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\t\r\n\tScript::CArray *pArray=NULL;\r\n\tpParams->GetArray(NONAME,&pArray);\r\n\tif (pArray && pArray->GetSize())\r\n\t{\r\n\t\tswitch (pArray->GetType())\r\n\t\t{\r\n\t\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t\t\tpScript->SetScript(pArray->GetNameChecksum(Mth::Rnd(pArray->GetSize())),NULL,pScript->mpObject);\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(0,(\"GotoRandomScript requires an array of script names.\"));\r\n\t\t\t\tbreak;\r\n\t\t}\t\t\r\n\t}\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PrintStruct | Prints the contents of the passed structure\r\n// @uparm structure | The structure to print\r\nbool ScriptPrintStruct(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tScript::PrintContents(pParams);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic CComponent sTempComponent;\r\n\r\nstatic int sFormatText(CStruct *p_dest_struct, CStruct *p_format)\r\n{\r\n\t#define FORMATTED_TEXT_MAX_LEN 1000\r\n\tstatic char s_printf_buffer[FORMATTED_TEXT_MAX_LEN+1];\r\n\r\n\tDbg_MsgAssert(p_format,(\"NULL p_format\"));\r\n\t\r\n\tuint32 string_name_checksum=0;\r\n\tp_format->GetChecksum(CRCD(0xff0db407,\"TextName\"),&string_name_checksum);\r\n\t\r\n\t// If passed a ChecksumName, the checksum of the formatted text will\r\n\t// be calculated and put into a parameter with that name.\r\n\tuint32 checksum_name_checksum=0;\r\n\tp_format->GetChecksum(CRCD(0x76fa7a8f,\"ChecksumName\"),&checksum_name_checksum);\r\n\r\n\tint result = 1;\r\n\t\r\n\tconst char *p_format_text=\"\";\r\n\tif (!p_format->GetString(NONAME,&p_format_text))\r\n\t{\r\n\t\tprintf(\"Expected text format parameters to contain a format string\\n\");\r\n\t\treturn 0;\r\n\t}\t\r\n\t\r\n\tchar *p_dest=s_printf_buffer;\r\n\tconst char *p_scan=p_format_text;\r\n\tint space_left=FORMATTED_TEXT_MAX_LEN;\r\n\twhile (*p_scan)\r\n\t{\r\n\t\tDbg_MsgAssert(space_left,(\"Overflowed formatted text buffer\"));\r\n\r\n\t\tif (p_scan[0]=='\\\\' && p_scan[1]=='%')\r\n\t\t{\r\n\t\t\t// Make \\% equate to %, so that we can have % chars in the string.\r\n\t\t\t++p_scan;\r\n\t\t\t*p_dest++=*p_scan++;\r\n\t\t\t--space_left;\r\n\t\t}\t\r\n\t\telse if (*p_scan=='%')\r\n\t\t{\r\n\t\t\t++p_scan; // Skip over the %\r\n\t\t\t\r\n\t\t\t// Find the component in p_format which has the same name as the name following\r\n\t\t\t// the % sign.\r\n\t\t\t#define PARAM_NAME_MAX_LEN 50\r\n\t\t\tchar p_param_name[PARAM_NAME_MAX_LEN+1];\r\n\t\t\tint c=0;\r\n\t\t\tchar *p_param_name_dest=p_param_name;\r\n\r\n\t\t\tif (*p_scan=='%')\r\n\t\t\t{\r\n\t\t\t\t// Two percents mean that what follows is a name longer than one char.\r\n\t\t\t\t++p_scan;\r\n\t\t\t\t\r\n\t\t\t\twhile ((*p_scan>='a' && *p_scan<='z') ||\r\n\t\t\t\t\t   (*p_scan>='A' && *p_scan<='Z') ||\r\n\t\t\t\t\t   (*p_scan>='0' && *p_scan<='9') ||\r\n\t\t\t\t\t   *p_scan=='_')\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(c<PARAM_NAME_MAX_LEN,(\"Text formatting param name too long in '%s'\",p_format_text));\r\n\t\t\t\t\t*p_param_name_dest++=*p_scan++;\r\n\t\t\t\t\t++c;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// One percent means that the name is defined by just one char.\r\n\t\t\t\t// This is to allow formatting to be used to append strings, for example\r\n\t\t\t\t// \"%sBlaa\"\r\n\t\t\t\t*p_param_name_dest++=*p_scan++;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\t*p_param_name_dest=0;\r\n\t\t\t// Got the param name, so look it up in the p_format structure.\r\n\t\t\tCComponent *p_unresolved_comp=p_format->FindNamedComponentRecurse(GenerateCRC(p_param_name));\r\n\t\t\t\r\n\t\t\tif (!p_unresolved_comp)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"Missing text formatting parameter '%s'\\n\",p_param_name);\r\n\t\t\t\treturn 0;\r\n\t\t\t}\t\r\n\r\n\t\t\t// p_unresolved_comp may have type Name, which may resolve to some global. So use\r\n\t\t\t// the ResolveNameComponent to resolve it.\r\n\t\t\t// Using sTempComponent because ResolveNameComponent may modify the component by\r\n\t\t\t// perhaps setting it's mpStructure or mpArray to equal that of some global symbol.\r\n\t\t\t// It would be bad to modify the contents of p_unresolved_comp because it is\r\n\t\t\t// in the passed structure, which will get cleaned up later, resulting in the deletion\r\n\t\t\t// of the global symbol's pointer, causing horrible crashes.\r\n\t\t\tsTempComponent.mType=p_unresolved_comp->mType;\r\n\t\t\tsTempComponent.mUnion=p_unresolved_comp->mUnion;\r\n\t\t\tResolveNameComponent(&sTempComponent);\r\n\t\t\t\r\n\t\t\tchar p_temp[100];\r\n\t\t\tswitch (sTempComponent.mType)\r\n\t\t\t{\r\n\t\t\t\tcase ESYMBOLTYPE_INTEGER:\r\n\t\t\t\t{\r\n\t\t\t\t\tif (p_format->ContainsFlag(CRCD(0xf138085f,\"UseCommas\")))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tstrcpy(p_temp,Str::PrintThousands(sTempComponent.mIntegerValue));\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsprintf(p_temp,\"%d\",sTempComponent.mIntegerValue);\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tint len=strlen(p_temp);\r\n\t\t\t\t\tDbg_MsgAssert(len<=space_left,(\"Overflowed formatted text buffer\"));\r\n\t\t\t\t\tstrcpy(p_dest,p_temp);\r\n\t\t\t\t\tp_dest+=len;\r\n\t\t\t\t\tspace_left-=len;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\tcase ESYMBOLTYPE_FLOAT:\r\n\t\t\t\t{\r\n\t\t\t\t\tint decimal_places=3;\r\n\t\t\t\t\tchar format_string[16];\r\n\t\t\t\t\tp_format->GetInteger(CRCD(0xd8e2e09f,\"DecimalPlaces\"),&decimal_places);\r\n\t\t\t\t\tDbg_MsgAssert(decimal_places>=0 && decimal_places<10,(\"decimal_places must be less than 10\"));\r\n\t\t\t\t\tsprintf( format_string, \"%%.%df\", decimal_places );\r\n\t\t\t\t\tsprintf(p_temp,format_string,sTempComponent.mFloatValue);\r\n\t\t\t\t\tint len=strlen(p_temp);\r\n\t\t\t\t\tDbg_MsgAssert(len<=space_left,(\"Overflowed formatted text buffer\"));\r\n\t\t\t\t\tstrcpy(p_dest,p_temp);\r\n\t\t\t\t\tp_dest+=len;\r\n\t\t\t\t\tspace_left-=len;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\tcase ESYMBOLTYPE_PAIR:\r\n\t\t\t\t{\r\n\t\t\t\t\tCPair *p_pair=sTempComponent.mpPair;\r\n\t\t\t\t\tDbg_MsgAssert(p_pair,(\"NULL p_pair\"));\r\n\t\t\t\t\t\r\n\t\t\t\t\tsprintf(p_temp,\"(%.3f,%.3f)\",p_pair->mX,p_pair->mY);\r\n\t\t\t\t\tint len=strlen(p_temp);\r\n\t\t\t\t\tDbg_MsgAssert(len<=space_left,(\"Overflowed formatted text buffer\"));\r\n\t\t\t\t\tstrcpy(p_dest,p_temp);\r\n\t\t\t\t\tp_dest+=len;\r\n\t\t\t\t\tspace_left-=len;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\tcase ESYMBOLTYPE_VECTOR:\r\n\t\t\t\t{\r\n\t\t\t\t\tCVector *p_vector=sTempComponent.mpVector;\r\n\t\t\t\t\tDbg_MsgAssert(p_vector,(\"NULL p_vector\"));\r\n\t\t\t\t\t\r\n\t\t\t\t\tsprintf(p_temp,\"(%.3f,%.3f,%.3f)\",p_vector->mX,p_vector->mY,p_vector->mZ);\r\n\t\t\t\t\tint len=strlen(p_temp);\r\n\t\t\t\t\tDbg_MsgAssert(len<=space_left,(\"Overflowed formatted text buffer\"));\r\n\t\t\t\t\tstrcpy(p_dest,p_temp);\r\n\t\t\t\t\tp_dest+=len;\r\n\t\t\t\t\tspace_left-=len;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\tcase ESYMBOLTYPE_NAME:\r\n\t\t\t\t{\r\n\t\t\t\t\t// we set the return result to 2, so we can assert in ScriptFormatText\r\n\t\t\t\t\t// so we can see where in the script we are\r\n\t\t\t\t\tresult = 2;\r\n\t\t\t\t\tsprintf(p_temp,\"%s\",FindChecksumName(sTempComponent.mChecksum));\r\n\t\t\t\t\tint len=strlen(p_temp);\r\n\t\t\t\t\tDbg_MsgAssert(len<=space_left,(\"Overflowed formatted text buffer\"));\r\n\t\t\t\t\tstrcpy(p_dest,p_temp);\r\n\t\t\t\t\tp_dest+=len;\r\n\t\t\t\t\tspace_left-=len;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\tcase ESYMBOLTYPE_STRING:\r\n\t\t\t\tcase ESYMBOLTYPE_LOCALSTRING:\r\n\t\t\t\t{\r\n\t\t\t\t\tconst char *p_source=\"\";\r\n\t\t\t\t\tif (sTempComponent.mType==ESYMBOLTYPE_STRING)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_source=sTempComponent.mpString;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_source=sTempComponent.mpLocalString;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\t\r\n\t\t\t\t\twhile (*p_source)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDbg_MsgAssert(space_left,(\"Overflowed formatted text buffer\"));\r\n\t\t\t\t\t\t*p_dest++=*p_source++;\r\n\t\t\t\t\t\t--space_left;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\tdefault:\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"Error when formatting '%s'\\n'%s' has data type '%s' which is not supported yet.\\n\",p_format_text,p_param_name,Script::GetTypeName(sTempComponent.mType)));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t}\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t*p_dest++=*p_scan++;\r\n\t\t\t--space_left;\r\n\t\t}\t\r\n\t}\r\n\t*p_dest=0;\r\n\r\n\tDbg_MsgAssert(p_dest_struct,(\"NULL p_dest_struct\"));\r\n\tif (string_name_checksum)\r\n\t{\r\n\t\tp_dest_struct->AddString(string_name_checksum,s_printf_buffer);\r\n\t}\t\r\n\tif (checksum_name_checksum)\r\n\t{\r\n\t\tp_dest_struct->AddChecksum(checksum_name_checksum,Script::GenerateCRC(s_printf_buffer));\r\n\t}\t\r\n\treturn result;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | FormatText | Fills in any % characters in the passed format string with the passed\r\n// parameters, and assigns the new string to a parameter with the given name.\r\n// For example:\r\n// FormatText TextName=Line1 \"Hello %f %b\" f=\"Mum\" b=23\r\n// will create the string \"Hello Mum 23\" and assign it to Line1\r\n// The name following the % must consist of a single character. This is to allow formatting to\r\n// be used to append strings, eg \"%sBlaa\"\r\n// If two % signs are used, then the name that follows may consist of more than one char,\r\n// eg \"%%foo blaa\"\r\n//\r\n// Currently supported data types are integer, float, string, local string, vector and pair.\r\n// If any of the parameters are missing it will give an error message and will not create the\r\n// final string. It will not assert though.\r\n//\r\n// @parmopt name | TextName | | The name to be given to the new formatted string\r\n// @parmopt name | ChecksumName | | If this is specified, the checksum of the formatted text\r\n// will be calculated and added using ChecksumName as its name.\r\n// @uparm string | The source format string\r\n// @flag UseCommas | This will make it print any integer using commas to separate thousands for clarity.\r\nbool ScriptFormatText(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tif (sFormatText(pScript->GetParams(),pParams) == 2)\r\n\t{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n//\t\tDbg_MsgAssert(0,(\"%s\\nCannot use checksum names in FormatText\",pScript->GetScriptInfo()));\r\n\t\tprintf (\"%s\\n### WARNING ### - Cannot use checksum names in FormatText\",pScript->GetScriptInfo());\r\n\t#endif\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool s_get_string_from_params(char* p_buffer, Script::CStruct *pParams, Script::CScript* pScript)\r\n{\r\n\tDbg_Assert( p_buffer );\r\n\r\n\tconst char *p_text=\"Default printf text\";\r\n\tif (pParams->GetText(NONAME,&p_text))\r\n\t{\r\n\t\tCStruct *p_format=new CStruct;\r\n\t\tp_format->AddChecksum(GenerateCRC(\"TextName\"),GenerateCRC(\"PrintfText\"));\r\n\t\tp_format->AppendStructure(pParams);\r\n\t\t\r\n\t\tif (sFormatText(p_format,p_format))\r\n\t\t{\r\n\t\t\tp_format->GetString(\"PrintfText\",&p_text);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Warning(\"\\n%s\\nError formatting text for printf\",pScript->GetScriptInfo());\r\n\t\t\tp_text=\"\";\r\n\t\t}\r\n\r\n\t\tsprintf(p_buffer, \"%s\\n\",p_text);\r\n\t\t\r\n\t\tdelete p_format;   \t\t// p_format actually contains the string we are printing, so delete it AFTER the printf\r\n\t\t\r\n\t\treturn true;\r\n\t}\r\n\r\n\tint IntVal=0;\r\n\tif (pParams->GetInteger(NONAME,&IntVal))\r\n\t{\r\n\t\tsprintf(p_buffer, \"%d\\n\",IntVal);\r\n\r\n\t\treturn true;\r\n\t}\r\n\t\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint32 Checksum=0;    \r\n\tif (pParams->GetChecksum(NONAME,&Checksum))\r\n\t{\r\n\t\tsprintf(p_buffer, \"[Checksum] %s\\n\",Script::FindChecksumName(Checksum));\r\n\r\n\t\treturn true;\r\n\t}\r\n\t\t\r\n\tsprintf(p_buffer, \"Empty printf at %s\", pScript->GetScriptInfo());\r\n\t#endif\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Printf | Printf \"Default printf text\" Prints the passed \r\n// text onto the EE0 output on the target manager.\r\n// Printf can will also print the checksum name of any passed checksum, for example:\r\n// printf blaa    // Will print: [Checksum] blaa\r\n// @uparmopt \"text\" | some text to print\r\n// @uparmopt 1 | an int to print\r\n// @uparmopt name | checksum to print\r\n// @flag UseCommas | This will make it print any integer using commas to separate thousands for clarity.\r\nbool ScriptPrintf(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tchar buffer[1024];\r\n\r\n\ts_get_string_from_params(buffer, pParams, pScript);\r\n\t\r\n\tprintf( buffer );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptAssert |\r\nbool ScriptScriptAssert(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tchar buffer[1024];\r\n\r\n\ts_get_string_from_params(buffer, pParams, pScript);\r\n\t\r\n\tDbg_MsgAssert( 0, ( \"%s\\nSCRIPT ASSERT:  %s\", pScript->GetScriptInfo(), buffer ) );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PrintScriptInfo |\r\nbool ScriptPrintScriptInfo(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tprintf(\"+++ScriptInfo+++++++++++++++++++++++++\\n\");\r\n\t\r\n\t// firsts prints out the associated string,\r\n\t// using the \"printf\" script function\r\n\tScriptPrintf(pParams, pScript);\r\n\t\r\n\t// then it asserts\r\n\tprintf(\"%s\",pScript->GetScriptInfo());\r\n\t\r\n\tprintf(\"++++++++++++++++++++++++++++++++++++++\\n\");\r\n\t#endif\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetHackFlag | Sets special hackflag\r\n// @uparmopt 1 | integer flag (1 or 0)\r\nstatic bool HackFlag=false;\r\nbool ScriptSetHackFlag(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tint v=1;\r\n\tpParams->GetInteger(NONAME,&v);\r\n\tHackFlag=v?true:false;\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | HackFlagIsSet | Returns current value of hackflag\r\nbool ScriptHackFlagIsSet(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\treturn HackFlag;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PreloadModel | Preloads model\r\n// Example: PreloadModel name=\"ModelName\" or name=\"levels/skateshop/thps4board_01/thps4board_01.mdl\"\r\n// @parm string | name | The model name\r\nbool ScriptPreloadModel(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char* pModelName;\r\n\tpParams->GetText( \"name\", &pModelName, Script::ASSERT );\r\n\r\n\t// now preload any programmatically-loaded peds\r\n\tNx::CModel* pDummy = Nx::CEngine::sInitModel();\r\n\tDbg_Assert( pDummy );\r\n\t\r\n\tbool forceTexDictLookup = pParams->ContainsFlag( CRCD(0x6c37fdc7,\"AllowReplaceTex\") );\r\n\r\n\tStr::String fullModelName;\r\n\tfullModelName = Gfx::GetModelFileName(pModelName, \".mdl\");\r\n\tpDummy->AddGeom( fullModelName.getString(), 0, true, 0, forceTexDictLookup );\r\n\t\t\r\n\tNx::CEngine::sUninitModel( pDummy );\r\n\t\r\n\treturn true;\r\n}\r\n\t\t   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\n// @script | LoadLevelGeometry | Loads a bsp file. Assumes the current \r\n// directory is \\skate3\\data, so a valid string would be \"levels\\aus\\aus.bsp\". \r\n// Can also have an optional \"Sky=\"xxx.bsp\" parameter for loading the \r\n// sky dome with a level file. The Level and Sky parameters are optional, \r\n// but you must have at least one of them (So you can load just a sky, \r\n// or just a level, if you want).\r\n// @parmopt string | Sky | | .bsp file for sky dome\r\n// @parmopt string | Level | | .bsp file for level\r\n// @parmopt string | Pre_set | | load assets from PRE file\r\nbool ScriptLoadLevelGeometry(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\t File::PreMgr * pre_mgr =  File::PreMgr::Instance();\r\n\t\r\n\tconst char*\tp_level = NULL;\r\n\tconst char*\tp_sky \t= NULL;\r\n\r\n\tpParams->GetText( \"Level\",&p_level );\r\n\tpParams->GetText( \"Sky\", &p_sky );\r\n\r\n\tNx::CTexDict *p_tex_dict, *p_sky_tex_dict;\r\n\tNx::CScene *p_scene, *p_sky_scene;\r\n\r\n\tif (p_sky)\r\n\t{\r\n\t\tp_sky_tex_dict = Nx::CTexDictManager::sLoadTextureDictionary(p_sky);\r\n\t\tDbg_Assert(p_sky_tex_dict);\r\n\t\tp_sky_scene = Nx::CEngine::sLoadScene(p_sky, p_sky_tex_dict, false, true);\t// mark as sky that doesn't go in SuperSectors\r\n\t\tDbg_Assert(p_sky_scene);\r\n\t}\r\n\t\r\n\tif (p_level)\r\n\t{\r\n\t\t//p_tex_dict = Nx::CEngine::sLoadTextures(p_level);\r\n\t\tp_tex_dict = Nx::CTexDictManager::sLoadTextureDictionary(p_level);\r\n\t\tDbg_Assert(p_tex_dict);\r\n\t\tp_scene = Nx::CEngine::sLoadScene(p_level, p_tex_dict);\r\n\t\tDbg_Assert(p_scene);\r\n\t\tp_scene->LoadCollision(p_level);\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptUnloadAllLevelGeometry(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tNx::CEngine::sUnloadAllScenesAndTexDicts();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptLoadScene(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tbool is_dictionary = pParams->ContainsFlag(CRCD(0x3d559e7d,\"is_dictionary\"));  \t\t// piece dictionary, like the park editor\r\n\tbool is_sky = pParams->ContainsFlag(CRCD(0xb5bd28d8,\"is_sky\"));\t\t\t\t\t\t// a sky dome\r\n\tbool is_net = pParams->ContainsFlag(CRCD(0x417149c8,\"is_net\"));\t\t\t\t\t\t// the _net version\r\n\tbool add_super_sectors = ! pParams->ContainsFlag(CRCD(0x8943dbd8,\"no_supersectors\"));\t// optionally ignore supersectors\r\n\t\r\n\tconst char *p_scene_name = NULL;\r\n\tpParams->GetText( CRCD(0x26861025,\"scene\"),&p_scene_name,true );\r\n\tDbg_MsgLog((\"Loading Scene %s ...\",p_scene_name));\r\n\tprintf (\"Loading Scene %s ...\",p_scene_name);\r\n\t\r\n\r\n\t// First load the texture dictionary\r\n\tchar\ttexture_dict_name[128];\r\n\tsprintf(texture_dict_name,\"levels\\\\%s\\\\%s%s.tex\",p_scene_name,p_scene_name,is_net?\"_net\":\"\");\r\n\r\n\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tconst char *p_fallback = \"nj_sky\";\r\n\t// Some debug code to load the NJ sky if default_sky does not exists\r\n\tif (stricmp(texture_dict_name,\"levels\\\\default_sky\\\\default_sky.tex\")==0)\r\n\t{\r\n\t\tprintf (\"TRYING TO LAOD DEFUALT SKY\\n\");\r\n\t\tprintf (\"TRYING TO LAOD DEFUALT SKY\\n\");\r\n\t\tprintf (\"TRYING TO LAOD DEFUALT SKY\\n\");\r\n\t\tprintf (\"TRYING TO LAOD DEFUALT SKY\\n\");\r\n\t\t// it's the default sky, so check if it exists\r\n\t\tif (!File::Exist(texture_dict_name))\r\n\t\t{\r\n\t\t\tprintf (\"NO EXIST\\n\");\r\n\t\t\r\n\t\t\tp_scene_name = p_fallback;\t\t\t\r\n\t\t\tsprintf(texture_dict_name,\"levels\\\\%s\\\\%s.tex\",p_scene_name,p_scene_name);\r\n\t\t}\r\n\t}\r\n\t#endif\r\n\t\r\n\t\r\n\tNx::CTexDict * p_tex_dict = Nx::CTexDictManager::sLoadTextureDictionary(texture_dict_name,true);\r\n\tDbg_MsgAssert(p_tex_dict,(\"ERROR loading tex dict for %s\\n\",texture_dict_name));\r\n\r\n\t// a level ending in _sky is automatically a sky dome\t\r\n\tif (Str::StrStr(p_scene_name,\"_sky\"))\r\n\t{\r\n\t\tis_sky = true;\r\n\t}\r\n\t\r\n\t// Skys always have no supersectors\r\n\tif (is_sky)\r\n\t{\r\n\t\tadd_super_sectors = false;\t\t\r\n\t}\r\n\t\r\n\t// and dictionaries always have no supersectors\r\n\tif (is_dictionary)\r\n\t{\r\n\t\tadd_super_sectors = false;\t\t\r\n\t}\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tNx::CScene * p_scene = \r\n\t#endif\r\n\tNx::CEngine::sLoadScene(p_scene_name, p_tex_dict, add_super_sectors,is_sky,is_dictionary,is_net);\t// mark as sky that doesn't go in SuperSectors\r\n\tDbg_MsgAssert(p_scene,(\"ERROR loading scene for %s\\n\",p_scene_name));\r\n\tprintf (\"... done\\n\");\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptAddScene(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_scene_name = NULL;\r\n\tconst char *p_add_name = NULL;\r\n\tpParams->GetText( \"scene\",&p_scene_name );\r\n\tpParams->GetText( \"add\",&p_add_name );\r\n\tif (p_scene_name && p_add_name)\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tNx::CScene * p_scene =\r\n\t\t#endif\r\n\t\tNx::CEngine::sAddScene(p_scene_name, p_add_name);\r\n\t\tDbg_MsgAssert(p_scene,(\"ERROR adding scene for %s\\n\",p_scene_name));\r\n\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// we have a seperate script command for loading collision\r\n// so we can control the loading of pre files\r\nbool ScriptLoadCollision(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\tconst char *p_scene_name = NULL;\r\n\tpParams->GetText( \"scene\",&p_scene_name );\r\n\tbool is_net = pParams->ContainsFlag(CRCD(0x417149c8,\"is_net\"));\t\t\t\t\t\t// the _net version\r\n\tif (p_scene_name)\r\n\t{\r\n\t\tNx::CScene * p_scene = Nx::CEngine::sGetScene(p_scene_name);\r\n\t\tDbg_MsgAssert(p_scene,(\"Trying to load collision for scene: %s\\n\",p_scene_name));\r\n\t\tDbg_MsgLog((\"Trying to load collision for scene: %s\\n\",p_scene_name));\r\n\t\tp_scene->LoadCollision(p_scene_name, is_net);\t\r\n\t}\r\n\treturn true;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptAddCollision(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_scene_name = NULL;\r\n\tconst char *p_add_name = NULL;\r\n\tpParams->GetText( \"scene\",&p_scene_name );\r\n\tpParams->GetText( \"add\",&p_add_name );\r\n\tif (p_scene_name && p_add_name)\r\n\t{\r\n\t\tNx::CScene * p_scene = Nx::CEngine::sGetScene(p_scene_name);\r\n\t\tDbg_MsgAssert(p_scene,(\"Trying to add collision file %s to scene: %s\\n\", p_add_name, p_scene_name));\r\n\t\tp_scene->AddCollision(p_add_name);\r\n\t}\r\n\treturn true;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptUnloadScene(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_scene_name = NULL;\r\n\tbool matching_names;\r\n\tpParams->GetText( \"scene\",&p_scene_name );\r\n\r\n\tmatching_names = false;\r\n\tif (p_scene_name)\r\n\t{\r\n\t\tNx::CScene *p_scene = Nx::CEngine::sGetScene(p_scene_name);\r\n\t\tif (p_scene)\r\n\t\t{\r\n\t\t\tmatching_names = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_scene = Nx::CEngine::sGetMainScene();\r\n\t\t}\r\n\r\n\t\tif (p_scene)\r\n\t\t{\r\n\t\t\tNx::CTexDict *p_tex_dict = p_scene->GetTexDict();\r\n\r\n\t\t\tNx::CEngine::sUnloadScene(p_scene);\r\n\t\t\t// must unload dictionary after scene\r\n\t\t\tif (p_tex_dict)\r\n\t\t\t{\r\n\t\t\t\tNx::CTexDictManager::sUnloadTextureDictionary(p_tex_dict);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn matching_names;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptQuickReload(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_scene_name = NULL;\r\n\tpParams->GetText( \"scene\",&p_scene_name );\r\n\tif (p_scene_name)\r\n\t{\r\n\t\tNx::CEngine::sQuickReloadGeometry(p_scene_name);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptCreateFromNode( Script::CStruct *pNode )\r\n{\t\r\n//\tDbg_MsgLog((\"CreateFromNodeIndex nodeIndex=%d\",nodeIndex));\r\n\t\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tObj::CRailManager *p_rail_man = skate_mod->GetRailManager();\r\n\tDbg_MsgAssert(p_rail_man,(\"Missing rail manager\"));\t\t\t\t\t \r\n\t\t\t\t\t \r\n//\tScript::CArray *pNodeArray = Script::GetArray( CRCD(0xc472ecc5,\"NodeArray\") );\r\n//\tDbg_MsgAssert( pNodeArray,( \"No NodeArray found\" ));\r\n\r\n\t// We still need the node index for some things (rails, proxim)\r\n\t// nut now we get it from the node\r\n\tint nodeIndex = 0;\r\n\tpNode->GetInteger(CRCD(0xe50d6573,\"NodeIndex\"), &nodeIndex);\r\n\r\n//\tScript::CStruct *pNode=pNodeArray->GetStructure( nodeIndex );\r\n\tDbg_MsgAssert( pNode,( \"NULL pNode\" ));\r\n\r\n\t// If this is a net game, don't load objects that were meant to be left out for \r\n\t// performance/bandwidth/gameplay reasons\r\n\tif ( skate_mod->ShouldBeAbsentNode( pNode ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tMem::Allocator* pCurrentHeapContext = Mem::Manager::sHandle().GetContextAllocator();\r\n\tif ( !( pCurrentHeapContext == Mem::Manager::sHandle().CutsceneBottomUpHeap()\r\n\t\t || pCurrentHeapContext == Mem::Manager::sHandle().BottomUpHeap() ) )\r\n\t{\r\n\t\t// GJ:  this function used to push the bottom up heap context explicitly,\r\n\t\t// but it was causing problems with the cutscene code, which\r\n\t\t// wants to put stuff on the cutscene heap.  however, there's\r\n\t\t// no reason to push the bottom up heap, since the bottom up heap\r\n\t\t// was always the default context anyway...  i think.\r\n\t\tDbg_MsgAssert( 0, ( \"Was expecting bottomupheap context\" ) );\r\n\t}\r\n#endif\r\n\r\n\t/*\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t*/\r\n\r\n\tuint32 ClassChecksum = 0;\r\n\tpNode->GetChecksum( 0x12b4e660 /*\"Class\"*/, &ClassChecksum );\r\n\r\n\t// check for obsolete trigger objects first\r\n\tif ( ClassChecksum == 0xe594f0a2 )\t// trigger\r\n\t{\r\n\t\tuint32 checksumName = 0;\r\n\t\tif ( pNode->GetChecksum( 0xa1dc81f9, &checksumName ) ) // checksum 'name'\r\n\t\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\t\tprintf(\"WARNING:  Trigger objects are obsolete %s\\n\", Script::FindChecksumName(checksumName) );\r\n#endif\t\t\r\n\t\t}\r\n\t}\r\n\r\n\tbool success = true;\r\n\r\n\tswitch (ClassChecksum)\r\n\t{\r\n\t\tcase 0xe47f1b79: //vehicle\r\n\t\t\tDbg_MsgLog((\"Vehicle\"));\r\n\t\t\tMem::PushMemProfile(\"Vehicles\");\r\n\t\t\tObj::CreateCar( skate_mod->GetObjectManager(), pNode );\r\n\t\t\tMem::PopMemProfile();\r\n\t\t\tbreak;\r\n\t\r\n\t\tcase 0xa0dfac98:  //pedestrian\r\n\t\tcase 0x061a741e:  //ped\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgLog((\"Pedestrian\"));\r\n\t\t\t\tMem::PushMemProfile(\"Pedestrians\");\r\n\t\t\t\tObj::CreatePed( skate_mod->GetObjectManager(), pNode );\r\n\t\t\t\tMem::PopMemProfile();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0xef59c100:  //gameobject\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgLog((\"gameobject\"));\r\n\t\t\t\tMem::PushMemProfile(\"Game Objects\");\r\n\t\t\t\tObj::CreateGameObj( skate_mod->GetObjectManager(), pNode );\r\n\t\t\t\tMem::PopMemProfile();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase 0x19b1e241: // ParticleEmitter\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgLog((\"ParticleEmitter\"));\r\n\t\t\t\tMem::PushMemProfile(\"Particle Systems\");\r\n\t\t\t\tObj::CreateParticleEmitter( skate_mod->GetObjectManager(), pNode );\r\n\t\t\t\tMem::PopMemProfile();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 0x9e7d469e: // ParticleObject\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgLog((\"ParticleObject\"));\r\n\t\t\t\tMem::PushMemProfile(\"Particle Systems\");\r\n\t\t\t\tObj::CreateParticleObject( skate_mod->GetObjectManager(), pNode );\r\n\t\t\t\tMem::PopMemProfile();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0xb7b3bd86:  // LevelObject\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgLog((\"LevelObject\"));\r\n\t\t\t\t// create a level object here\r\n\t\t\t\tMem::PushMemProfile(\"LevelObjects\");\r\n\t\t\t\tObj::CreateLevelObj( skate_mod->GetObjectManager(), pNode );\r\n\t\t\t\tMem::PopMemProfile();\r\n\t\t\t\t// Note, we used to turn off the original sector here\r\n\t\t\t\t// this is now done to all LevelObjects in ParseNodeArray\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n//\t\tcase 0xe594f0a2:  // Trigger (geometry containing triggers...)\r\n\t\tcase 0xbf4d3536:  // LevelGeometry\r\n\t\t{\r\n\t\t\tDbg_MsgLog((\"LevelGeometry\"));\r\n\t\t\tuint32 checksumName = 0;\r\n\t\t\tif ( pNode->GetChecksum( 0xa1dc81f9, &checksumName ) ) // checksum 'name'\r\n\t\t\t{\r\n//\t\t\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(checksumName);\r\n\t\t\t\t// We only want to get sectors from the main scene, as that is what the node array applies to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\tNx::CScene * p_main_scene = Nx::CEngine::sGetMainScene();\r\n\t\t\t\tNx::CSector *p_sector = p_main_scene->GetSector(checksumName);\r\n\t\t\t\tif (p_sector)\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(p_sector,(\"sGetSector(0x%x) returned NULL (%s)\",checksumName,Script::FindChecksumName(checksumName)));\r\n\t\t\t\t\tp_sector->SetVisibility(0xffffffff);\r\n\t\t\t\t\tp_sector->SetActive(true);\r\n\t\t\t\t\tp_sector->SetCollidable(true);\r\n\r\n\t\t\t\t\t// If this node is an occluder, let the occlusion code know that this occluder is now enabled.\r\n\t\t\t\t\tif( pNode->ContainsFlag( 0x4e549fe1 /*\"Occluder\"*/ ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tNx::CEngine::sEnableOcclusionPoly( checksumName, true );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf(\" WARNING: sGetSector(0x%x) returned NULL (%s)\\n\",checksumName,Script::FindChecksumName(checksumName));\r\n\t\t\t\t}\r\n\t\t\t\t//Bsp::ClearWorldSectorFlag( checksumName, mSD_KILLED | mSD_NON_COLLIDABLE | mSD_INVISIBLE  | mSD_INVISIBLE2);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n \t\t}\r\n\r\n\t\tcase 0x8e6b02ad:  // railnode\r\n\t\t\tDbg_MsgLog((\"railnode\"));\r\n\t\t\tp_rail_man->SetActive( nodeIndex, true, pNode->ContainsFlag( \"FLAG_WHOLE_RAIL\" ) );\r\n\t\t\tbreak;\r\n\t\tcase CRCC(0x30c19600, \"ClimbingNode\"):\r\n\t\t\tDbg_MsgLog((\"climbingnode\"));\r\n\t\t\tp_rail_man->SetActive( nodeIndex, true, pNode->ContainsFlag( \"FLAG_WHOLE_RAIL\" ) );\r\n\t\t\tbreak;\r\n\t\tcase 0x8470f2e:  // proximnode\r\n\t\t\tDbg_MsgLog((\"proximnode\"));\r\n\t\t\tObj::Proxim_SetActive( nodeIndex, true );\r\n\t\t\tbreak;\t\t\t\r\n\t\tcase 0xd64dc7c2:  // emitterobject\r\n\t\t\tDbg_MsgLog((\"emitterobject\"));\r\n\t\t\tObj::CEmitterManager::sSetEmitterActive( nodeIndex, true );\r\n\t\t\tbreak;\t\t\t\r\n\t\tdefault:\r\n\t\t\tDbg_MsgLog((\"default\"));\r\n\t\t\tsuccess = false;\r\n\t\t\tbreak;\r\n\t}\r\n//\tMem::Manager::sHandle().PopContext();\r\n\treturn success;\r\n}\r\n\r\n\r\nbool ScriptCreateFromNodeIndex( int nodeIndex )\r\n{\t\r\n\treturn ScriptCreateFromNode(SkateScript::GetNode(nodeIndex));\r\n}\r\n\r\n\r\nstruct MaybeKillObjectInfo\r\n{\r\n\tuint32 nodeNum;\r\n\tObj::CObject *forbiddenObject;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void MaybeKillObject( Obj::CObject *pOb, void *pVoidData )\r\n{\r\n\t\r\n\tDbg_MsgAssert(pOb,(\"NULL pOb\"));\r\n\tDbg_MsgAssert(pVoidData,(\"NULL pVoidData\"));\r\n\r\n\tMaybeKillObjectInfo *pInfo;\r\n\tpInfo = ( MaybeKillObjectInfo * )pVoidData;\r\n\t\r\n\tuint32 nodeNum = pInfo->nodeNum;\r\n\tuint32\tnodeName = SkateScript::GetNodeNameChecksum(nodeNum);\r\n\t\r\n\tif ( pOb->GetID() == nodeName )\r\n\t{\r\n\t\tDbg_MsgAssert( pOb != pInfo->forbiddenObject,( \"Can't issue a kill command from within the script of the object you're killing:  Use Die command.\" ));\r\n\t\tpOb->DestroyIfUnlocked( );\r\n//\t\tpOb->MarkAsDead();\r\n\t}\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptKillFromNodeIndex( int nodeIndex, Script::CScript *pScript )\r\n{\t\t\t\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\t\t\r\n\tObj::CRailManager *p_rail_man = skate_mod->GetRailManager();\r\n\tDbg_MsgAssert(p_rail_man,(\"Missing rail manager\"));\t\t\t\t\t \r\n\t\t\t\t\t     \r\n\tScript::CArray *pNodeArray = Script::GetArray( CRCD(0xc472ecc5,\"NodeArray\") );\r\n\tDbg_MsgAssert( pNodeArray,( \"No NodeArray found\" ));\r\n\r\n\tScript::CStruct *pNode=pNodeArray->GetStructure( nodeIndex );\r\n\tDbg_MsgAssert( pNode,( \"NULL pNode\" ));\r\n\r\n\tuint32 ClassChecksum = 0;\r\n\tpNode->GetChecksum( 0x12b4e660 /*\"Class\"*/, &ClassChecksum );\r\n\r\n\r\n\t\t\t\t\t\t\t\t\t\r\n\tswitch (ClassChecksum)\r\n\t{\r\n\t\tcase 0xe47f1b79: // vechicle\r\n\t\tcase 0xa0dfac98: // pedestrian\r\n\t\tcase 0x061a741e: // ped\r\n\t\tcase 0xef59c100: // gameobject\r\n\t\tcase 0x19b1e241: // ParticleEmitter\r\n\t\tcase 0x9e7d469e: // ParticleObject\r\n\t\tcase 0xb7b3bd86: // LevelObject\r\n\t\tcase 0x5b8ab877: // skater\r\n\t\t{\r\n\t\t\tMaybeKillObjectInfo info;\r\n\t\t\tinfo.forbiddenObject = pScript->mpObject;\r\n\t\t\tinfo.nodeNum = nodeIndex;\r\n\t\t\t\r\n\t\t\tskate_mod->GetObjectManager()->ProcessAllObjects( MaybeKillObject, &info );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase CRCC(0x30c19600, \"ClimbingNode\"):\r\n\t\t\tp_rail_man->SetActive( nodeIndex, false, pNode->ContainsFlag( \"FLAG_WHOLE_RAIL\" ) );\r\n\t\t\tbreak;\t\t\r\n\r\n\t\tcase 0x8e6b02ad:  // railnode\r\n\t\t\tp_rail_man->SetActive( nodeIndex, false, pNode->ContainsFlag( \"FLAG_WHOLE_RAIL\" ) );\r\n\t\t\tbreak;\t\t\r\n\r\n\t\tcase 0x8470f2e:  // proximnode\r\n\t\t\tObj::Proxim_SetActive( nodeIndex, false );\r\n\t\t\tbreak;\t\t\t\r\n\r\n\t\tcase 0xd64dc7c2:  // emitterobject\r\n\t\t\tObj::CEmitterManager::sSetEmitterActive( nodeIndex, false );\r\n\t\t\tbreak;\t\t\t\r\n\r\n//\t\tcase 0xe594f0a2:  // Trigger (geometry containing triggers...)\r\n\t\tcase 0xbf4d3536:  // LevelGeometry\r\n\t\t{\r\n\t\t\tuint32 checksumName = 0;\r\n\t\t\tif ( pNode->GetChecksum( 0xa1dc81f9, &checksumName ) ) // checksum 'name'\r\n\t\t\t{\r\n//\t\t\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(checksumName);\t\t\t\t\r\n\t\t\t\t// We only want to get sectors from the main scene, as that is what the node array applies to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\tNx::CScene * p_main_scene = Nx::CEngine::sGetMainScene();\r\n\t\t\t\tNx::CSector *p_sector = p_main_scene->GetSector(checksumName);\r\n\t\t\t\tDbg_MsgAssert(p_sector,(\"sGetSector(0x%x) returned NULL (%s)\",checksumName,Script::FindChecksumName(checksumName)));\r\n\t\t\t\tp_sector->SetActive(false);\r\n\t\t\t\t//Bsp::SetWorldSectorFlag(  checksumName, mSD_KILLED );\r\n\r\n\t\t\t\t// If this node is an occluder, let the occlusion code know that this occluder is no longer enabled.\r\n\t\t\t\tif( pNode->ContainsFlag( 0x4e549fe1 /*\"Occluder\"*/ ))\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(!ScriptInSplitScreenGame(NULL, NULL),\r\n\t\t\t\t\t\t\t\t  (\"Can't turn occlusion polys on or off during a 2 player game\"));\r\n\t\t\t\t\tNx::CEngine::sEnableOcclusionPoly( checksumName, false );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n \t\t}\r\n\r\n\t\tdefault:\r\n\t\t\treturn ( false );\r\n\t\t\tbreak;\r\n\t}\r\n\treturn ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptKillFromNodeNameChecksum( uint32 nodeNameChecksum, Script::CScript *pScript )\r\n{\r\n\r\n\treturn ( ScriptKillFromNodeIndex( SkateScript::FindNamedNode( nodeNameChecksum ), pScript ) );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool DoNodeActionFromNodeNum( int nodeNum, int action, Script::CScript *pScript, Script::CStruct *pParams )\r\n{\r\n    GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tMdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n// In net games, check if the node is flagged to be absent\r\n// and just ignore the command it fo\t\r\n\tif( gamenet_man->InNetMode())\r\n\t{\r\n\t\t// Rather inefficient.  We should get away from refering to nodes by index\r\n\t\tif (skate_mod->ShouldBeAbsentNode( SkateScript::GetNode(nodeNum) ) )\r\n\t\t{\r\n\t\t\t// just ignore the action\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t// note rather dodgy way of determining the viewport of a script\r\n\t// if it has an object, and tht object is the second skater, \r\n\t// and we have two viewports\r\n\t// use viewport 1, otherwise default to viewport 0\t\r\n\tint viewport_number = 0;\r\n\tif (pScript->mpObject && !gamenet_man->InNetGame() && Nx::CViewportManager::sGetNumActiveViewports() == 2)\r\n\t{\r\n\t\tObj::CSkater *pSkater = skate_mod->GetSkater(1);\r\n\t\tif (pScript->mpObject == pSkater )\t\t\r\n\t\t{\r\n\t\t\tviewport_number = 1;\r\n\t\t}\r\n\t}\r\n\t\r\n\t\r\n    switch ( action )\r\n\t{\r\n\t\tcase ( NODE_ACTION_CREATE ):\r\n\t\t\treturn ( ScriptCreateFromNodeIndex( nodeNum ) );\r\n\t\tcase ( NODE_ACTION_KILL ):\r\n\t\t\treturn ( ScriptKillFromNodeIndex( nodeNum, pScript ) );\r\n\t\tcase ( NODE_ACTION_SET_VISIBLE ):\r\n\t\t\treturn ( ScriptSetVisibilityFromNodeIndex( nodeNum, false, viewport_number ) );\r\n\t\tcase ( NODE_ACTION_SET_INVISIBLE ):\r\n\t\t\treturn ( ScriptSetVisibilityFromNodeIndex( nodeNum, true, viewport_number ) );\r\n\t\tcase ( NODE_ACTION_SET_COLOR ):\r\n\t\t\treturn ( ScriptSetColorFromNodeIndex( nodeNum, pParams ) );\r\n\t\tcase NODE_ACTION_SHATTER:\r\n\t\t{   \r\n\t\t\tScriptSetVisibilityFromNodeIndex( nodeNum, false, viewport_number );\r\n\t\t\treturn ScriptShatterFromNodeIndex( nodeNum );\r\n\t\t}\r\n\t\tcase NODE_ACTION_CHECK_IF_ALIVE:\r\n\t\t{\r\n\t\t\treturn ( ScriptCheckExistenceFromNodeIndex( nodeNum ) );\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0,( \"Fire Matt.\" ));\r\n\t\t\treturn ( false );\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Used to perform actions to nodes by prefix, name checksum, or links... General version\r\n// (applicable to nodes that create Environmental Objects, Rails, and all types of CMovingObjects.\r\nbool DoNodeAction( Script::CStruct *pParams, Script::CScript *pScript, int action )\r\n{\r\n\t\r\n\tuint32 nameChecksum;\r\n\tuint32 prefixChecksum;\r\n\t//const char *pPrefix;\r\n\tint i;\r\n\tbool useCurrentLinks = false;\r\n\tif ( pParams->ContainsFlag( 0x2e7d5ee7 ) || // checksum 'links'\r\n\t\t( useCurrentLinks = pParams->ContainsFlag( 0xbceb479a ) ) ) // checksum 'currentlinks'\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"%s:  DoNodeAction with links or currentlinks is deprecated\",pScript->GetScriptInfo()));\r\n\t\r\n\t\t/*\r\n\t\tint numLinks;\r\n\t\tScript::CStruct *pNode = NULL;\r\n\t\tif ( pParams->GetChecksumOrStringChecksum( 0xa1dc81f9, &nameChecksum ) ) // checksum 'name'\r\n\t\t{\r\n\t\t\tif ( useCurrentLinks )\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"\\n%s\\nWarning:  The 'currentLinks' flag only works in an object script on the calling object.\", pScript->GetScriptInfo( ) );\r\n\t\t\t}\r\n\t\t\tpNode = SkateScript::GetNode( SkateScript::FindNamedNode( nameChecksum ) );\r\n\t\t\tDbg_MsgAssert( pNode,( \"\\n%s\\nNo node named %s found\", pScript->GetScriptInfo( ), Script::FindChecksumName( nameChecksum ) ));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( pScript->mNode != -1 )\r\n\t\t\t{\r\n\t\t\t\tpNode = SkateScript::GetNode( pScript->mNode );\r\n\t\t\t\tDbg_MsgAssert( pNode,( \"\\n%s\\nnode %d not found\", pScript->GetScriptInfo( ), pScript->mNode ));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( pScript->mpObject )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( useCurrentLinks )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpNode = SkateScript::GetNode( ((Obj::CMovingObject *) pScript->mpObject.Convert())->m_current_node );\r\n\t\t\t\t\t\tDbg_MsgAssert( pNode,( \"\\n%s\\n object's node %d is invalid\", pScript->GetScriptInfo( ), ((Obj::CMovingObject *) pScript->mpObject.Convert())->m_start_node ));\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpNode = SkateScript::GetNode( ((Obj::CMovingObject *) pScript->mpObject.Convert())->m_start_node );\r\n\t\t\t\t\t\tDbg_MsgAssert( pNode,( \"\\n%s\\n object's node %d is invalid\", pScript->GetScriptInfo( ), ((Obj::CMovingObject *) pScript->mpObject.Convert())->m_start_node ));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( 0,( \"\\n%s\\nNo valid nodes to be found anywherest, dumass.\", pScript->GetScriptInfo( ) ));\r\n\t\t\t\t\treturn ( false );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tDbg_MsgAssert( pNode,( \"What the fuck?  How did this motherfuckin' happen?\" ));\r\n\t\tnumLinks = SkateScript::GetNumLinks( pNode );\r\n\t\tfor ( i = 0; i < numLinks; i++ )\r\n\t\t{\r\n\t\t\tif ( DoNodeActionFromNodeNum( SkateScript::GetLink( pNode, i ), action, pScript ) )\r\n\t\t\t{\r\n\t\t\t\tif ( action == NODE_ACTION_CHECK_IF_ALIVE )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn ( true );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t*/\r\n\r\n\t\treturn ( true );\r\n\t}\r\n    //if ( pParams->GetText( 0x6c4e7971, &pPrefix ) ) // checksum 'prefix'\r\n    if ( pParams->GetChecksumOrStringChecksum( 0x6c4e7971, &prefixChecksum ) ) // checksum 'prefix'\r\n\t{\r\n\t\t// Create with a prefix specified:\r\n\t\tuint16 numNodes = 0;\r\n\t  //  const uint16 *pMatchingNodes = SkateScript::GetPrefixedNodes( pPrefix, &numNodes );\r\n\t\tconst uint16 *pMatchingNodes = SkateScript::GetPrefixedNodes( prefixChecksum, &numNodes );\r\n\t\tfor ( i = 0; i < numNodes; i++ )\r\n\t\t{\r\n\t\t\tif ( DoNodeActionFromNodeNum( pMatchingNodes[ i ], action, pScript, pParams ) )\r\n\t\t\t{\r\n\t\t\t\tif ( action == NODE_ACTION_CHECK_IF_ALIVE )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn ( true );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn ( true );\r\n\t}\r\n\tif ( pParams->GetChecksumOrStringChecksum( 0xa1dc81f9, &nameChecksum ) ) // checksum 'name'\r\n\t{\r\n\t\t// Create with a name specified:\r\n\t\treturn ( DoNodeActionFromNodeNum( SkateScript::FindNamedNode( nameChecksum ), action, pScript, pParams ) );\r\n\t}\r\n\r\n\t// if they're calling \"Invisible\" with no parameters, intending to turn \r\n\t// visibility off on an object from within the object's script, they should\r\n\t// be calling \"Obj_Invisible\" (or Obj_Visible, or Die, create not applicable\r\n\t// since the object would have to have  already been created to be calling\r\n\t// something.)\r\n\tDbg_Message( \"\\n%s\\nSyntax not recognized... object script may need to call Obj_ version. (Ask Matt).\", pScript->GetScriptInfo( ) );\r\n\treturn ( false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptNodeExists( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 node_checksum=0;\r\n\tpParams->GetChecksum(NONAME,&node_checksum,true);\r\n\t\r\n\treturn SkateScript::NodeExists(node_checksum);\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptCreateFromStructure( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\treturn ScriptCreateFromNode( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Create | creates an object node\r\n// @flag links | pass in to perform action to nodes by links\r\n// @flag currentlinks | pass in to perform action to nodes by links\r\n// @parmopt name | name | | The name of the node\r\n// @parmopt name | prefix | | Create with a prefix specified\r\nbool ScriptCreate( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\r\n #ifdef\t__PLAT_NGPS__\t\t\r\n//\t\tsnProfSetRange( -1, (void*)0, (void*)-1);\r\n//\t\tsnProfSetFlagValue(0x01);\r\n #endif\r\n\r\n\r\n\t// Flush dead objects before we create any new ones\r\n\tScriptFlushDeadObjects(NULL,NULL);\t\r\n\t\r\n\tbool result = ( DoNodeAction( pParams, pScript, NODE_ACTION_CREATE ) );\r\n\r\n #ifdef\t__PLAT_NGPS__\t\t\r\n//\t\tsnProfSetRange( 4, (void*)NULL, (void*)-1);\r\n #endif\t\t\r\n \r\n\treturn result;\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetObjectColor | color the object a particular color\r\n// @parm name | name | The name of the piece of level geometry to change color\r\n// @parm int | color | The color to set the object to (as a hexadecimal ABGR value)\r\nbool ScriptSetObjectColor( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\r\n\tbool result = ( DoNodeAction( pParams, pScript, NODE_ACTION_SET_COLOR ) );\r\n\t\r\n\treturn result;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Kill | kills an object node\r\n// @flag links | pass in to perform action to nodes by links\r\n// @flag currentlinks | pass in to perform action to nodes by links\r\n// @parmopt name | name | | The name of the node\r\n// @parmopt name | prefix | | kill with a prefix specified\r\nbool ScriptKill( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\r\n\treturn ( DoNodeAction( pParams, pScript, NODE_ACTION_KILL ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Visible | make object visible\r\n// @flag links | pass in to perform action to nodes by links\r\n// @flag currentlinks | pass in to perform action to nodes by links\r\n// @parmopt name | name | | The name of the node\r\n// @parmopt name | prefix | | act on objects with specified prefix\r\nbool ScriptVisible( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\treturn ( DoNodeAction( pParams, pScript, NODE_ACTION_SET_VISIBLE ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Invisible | make object invisible\r\n// @flag links | pass in to perform action to nodes by links\r\n// @flag currentlinks | pass in to perform action to nodes by links\r\n// @parmopt name | name | | The name of the node\r\n// @parmopt name | prefix | | act on objects with specified prefix\r\nbool ScriptInvisible( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\treturn ( DoNodeAction( pParams, pScript, NODE_ACTION_SET_INVISIBLE ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Shatter | Shatter an object\r\n// @parmopt float | area | 288.0 | the subdivision area above which\r\n// polys will be recursively subdivided. Be careful with this\r\n// parameter - making it too small will cause the buffer to\r\n// overflow and assert. The units are square inches <nl>\r\n// The default value may change\r\n// @parmopt float | variance | 0.0 | the amount the velocity\r\n// of each shard can be (randomly) above the supplied velocity. \r\n// So a value of 1.0 would mean a shard could travel at twice the supplied <nl>\r\n// velocity <nl> The default value may change.\r\n// @parmopt float | spread | 1.0 | determines the degree to which the\r\n// shards will fly apart. The way I figure this is to take the center\r\n// of the bounding box for the object, and then move backwards (spread\r\n// * velocity). This position is then used to figure the start velocity\r\n// for each shard. So the lower the spread value, the less the start\r\n// point moves back, and the more the shards will fly apart. (I can\r\n// draw a diagram if this isn't clear). <nl>\r\n// The default value may change\r\n// @parmopt float | life | 4.0 | how long the shatter atomic will exist for\r\n// (seconds) <nl> The default value may change\r\n// @parmopt | bounce | -10,000 | Default value may change\r\n// @parmopt | scale | 1.0 | Scaling factor for the shards\r\n// @flag use_skater_vel | Use skater velocity to determine\r\n// if object should shatter\r\n// @parm | vel_x | default velocity of shard on x-axis (in inches per second)\r\n// @parm | vel_y | default velocity of shard on y-axis (in inches per second) \r\n// @parm | vel_z | default velocity of shard on z-axis (in inches per second)\r\nbool ScriptShatter( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t// Need to read some params from the script here.\r\n\tfloat\t\tarea\t\t= 0.0f;\r\n\tfloat\t\tvariance\t= 0.0f;\r\n\tfloat\t\tspread\t\t= 0.0f;\r\n\tfloat\t\tlife\t\t= 0.0f;\r\n\tfloat\t\tbounce\t\t= 0.0f;\r\n\tfloat\t\tbounce_amp\t= 0.0f;\r\n\tfloat\t\tscale\t\t= 1.0f;\r\n\tMth::Vector\tvelocity;\r\n\r\n\tif( pParams->ContainsFlag( 0x9f98989e /*\"use_skater_vel\"*/ ))\r\n\t{\r\n\t\tpParams->GetFloat( \"scale\", &scale );\r\n\r\n\t\tObj::CSkater* p_skater = static_cast <Obj::CSkater*>( pScript->mpObject.Convert() );\r\n\t\tDbg_Assert( p_skater );\r\n\r\n\t\tvelocity = p_skater->GetVel() * scale;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Have to supply vel_x, y, and z.\r\n\t\tpParams->GetFloat( \"vel_x\", &velocity[X], true );\r\n\t\tpParams->GetFloat( \"vel_y\", &velocity[Y], true );\r\n\t\tpParams->GetFloat( \"vel_z\", &velocity[Z], true );\r\n\t\tvelocity[W] = 0.0f;\t// To prevent assert on using unitialized vectors \r\n\t}\r\n\r\n\tpParams->GetFloat( \"area\",\t\t\t&area );\r\n\tpParams->GetFloat( \"variance\",\t\t&variance );\r\n\tpParams->GetFloat( \"spread\",\t\t&spread );\r\n\tpParams->GetFloat( \"life\",\t\t\t&life );\r\n\tpParams->GetFloat( \"bounce\",\t\t&bounce );\r\n\tpParams->GetFloat( \"bounce_amp\",\t&bounce_amp );\r\n\r\n\t//////////////////////////////////////////////////////////////////////////////////////////\r\n\t// Mick 09/18/02:  PATCH\r\n\t// setting the shatter area too low (generally to 1000) generates an excessive amount\r\n\t// of polygons in the form of immediate mode primitive, which eat up the DMA buffer on the PS2\r\n\t// So I'm going to limit the area to 2000 in the general case, and to 5000 in multi player games\r\n\tfloat min_area = 2000.0f;\t\t\t\t// single player limit\r\n\tif (Mdl::Skate::Instance()->IsMultiplayerGame())\r\n\t{\r\n\t\tmin_area = 5000.0f;\r\n\t}\r\n\t\r\n\tif (area < min_area)\r\n\t{\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tprintf(\"WARNING:  area %.1f too small for THPS4 PS2 engine, clamping to %.1f\\n\",area,min_area);\r\n\t\t#endif\r\n\t\tarea = min_area;\r\n\t}\r\n\t// END PATCH\r\n\t//////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n\t// Set up values for this shatter.\r\n\tNx::ShatterSetParams( velocity, area, variance, spread, life, bounce, bounce_amp );\r\n\r\n\treturn DoNodeAction( pParams, pScript, NODE_ACTION_SHATTER );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tCleanupBeforeParseNodeArray()\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n\tObj::Proxim_Init();\t\t\t\t\t\r\n\tObj::CEmitterManager::sInit();\r\n\tskate_mod->GetRailManager()->Cleanup();\t\t// probably not needed, as will be done in ScriptCleanup\r\n\tskate_mod->GetTrickObjectManager()->DeleteAllTrickObjects();\r\n\r\n\t// Scene lights are created during the node array parse, so clear them up here ready.\r\n\tNx::CLightManager::sClearSceneLights();\r\n\tNx::CLightManager::sClearVCLights();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ParseNodeArray | Parses the loaded node array \r\nbool ScriptParseNodeArray( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMem::PushMemProfile(\"ParseNodeArray\");\r\n\r\n\tCleanupBeforeParseNodeArray();\t\r\n\r\n\tMdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n\t// Scan through the node array creating all things that need to be created.\r\n\tScript::CArray *pNodeArray=Script::GetArray(CRCD(0xc472ecc5,\"NodeArray\"));\r\n\tDbg_MsgAssert(pNodeArray,(\"No NodeArray found in ParseNodeArray\"));\r\n\r\n\t// Rails are now added seperately\r\n\tMem::PushMemProfile(\"Rail Nodes\");\r\n\tObj::CRailManager *p_rail_man = skate_mod->GetRailManager();\r\n\tDbg_MsgAssert(p_rail_man,(\"Missing rail manager\"));\t\t\t\t\t \r\n\tp_rail_man->AddRailsFromNodeArray(pNodeArray );\t\t\t\t\t \t\t\t\t\t\t\t\t\t  \r\n\tMem::PopMemProfile();\r\n\t\r\n\t// Nav nodes are added separately.\r\n#\tifdef TESTING_GUNSLINGER\r\n\tMem::PushMemProfile( \"Nav Nodes\" );\r\n\tObj::CNavManager* p_nav_man = skate_mod->GetNavManager();\r\n\tDbg_MsgAssert( p_nav_man, ( \"Missing Nav Manager\" ));\r\n\tp_nav_man->AddNavsFromNodeArray( pNodeArray );\r\n\tMem::PopMemProfile();\r\n#\tendif\r\n\r\n\t// We only want to get sectors from the main scene, as that is what the node array applies to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tNx::CScene * p_main_scene = Nx::CEngine::sGetMainScene();\r\n\t\t\t\t\t\t\t\t\t  \r\n\tbool\tfail = false;\r\n\tuint32 i;\t \r\n\tfor (i=0; i<pNodeArray->GetSize(); ++i)\r\n\t{\r\n\t\tScript::CStruct *pNode=pNodeArray->GetStructure(i);\r\n\t\tDbg_MsgAssert(pNode,(\"NULL pNode\"));\r\n\r\n\t\tuint32 ClassChecksum = 0;\r\n\t\tpNode->GetChecksum( 0x12b4e660 /*\"Class\"*/, &ClassChecksum );\r\n\r\n\r\n\t\t// First the nodes that need some special processing\r\n\t\t// for the \"net game\" state\r\n\t\tswitch (ClassChecksum)\r\n\t\t{\t\t\t\t\t\t   \r\n\t\t\t// Note - Rails are no longer added here, but in the AddRailsFromNodeArray, above\r\n\t\t\t\r\n\t\t\tcase 0xb7b3bd86:  // LevelObject\r\n\t\t\t{\r\n\t\t\t\t// A \"LevelObject\" is like \"LevelGeometry\", in that it is a 3DStudio Max object\r\n\t\t\t\t// which is part of the scene (like, a wall or a house)\r\n\t\t\t\t// However, it's going to be movable, so it has to exist in \"local\" coordinate\r\n\t\t\t\t// space, centered around the origin.\r\n\t\t\t\t// When it is exported, the original geometry is just tranlated to the origin, and left there\r\n\t\t\t\t// later we will create a clone of this object, which will be be movable instance\r\n\t\t\t\t// but the original is left alone. So, we always turn off the original instance\r\n\t\t\t\t// of a LevelObject, before we create any instances. The creation is done via\r\n\t\t\t\t// ScriptCreateFromNodeIndex, either below (if createdAtStart), \r\n\t\t\t\t// or via a script command at some indeterminate time in the future.\r\n\t\t\t\tuint32 checksumName = 0;\r\n\t\t\t\tpNode->GetChecksum( 0xa1dc81f9 /*Name*/, &checksumName);\r\n//\t\t\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(checksumName);\r\n\t\t\t\tNx::CSector *p_sector = p_main_scene->GetSector(checksumName);\r\n\t\t\t\tif (p_sector)\r\n\t\t\t\t{\r\n\t\t\t\t\t\tp_sector->SetActive(false);\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase 0x8e6b02ad:  // railnode\r\n\t\t\t{\r\n\t\t\t\tpNode->RemoveComponent(CRCD(0x9d2d0915,\"angles\"));\r\n\t\t\t\tpNode->RemoveComponent(CRCD(0x7321a8d6,\"type\")); \t// Type is no longer used, as \"TerrainType\" suffices\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tcase CRCC(0x30c19600, \"ClimbingNode\"):\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase 0xbf4d3536:  // LevelGeometry\r\n\t\t\t{\r\n\t\t\t\t\r\n\t\t\t\t////////////////////////////////////////////////////////////////////////////////////\r\n\t\t\t\t// Test:  if it's a level object, then remove the angles, collisionmode and position\r\n\t\t\t\tpNode->RemoveComponent(CRCD(0x2d7e583b,\"collisionmode\"));\r\n//\t\t\t\tpNode->RemoveComponent(CRCD(0xb9d31b0a,\"position\"));\r\n//\t\t\t\tpNode->RemoveComponent(CRCD(0x9d2d0915,\"angles\"));\r\n\t\t\t\t////////////////////////////////////////////////////////////////////////////////////\r\n\r\n\t\t\t\t\r\n\t\t\t\t// first get the sector indicated by this level geometry\r\n\t\t\t\tuint32 checksumName = 0;\r\n\t\t\t\tpNode->GetChecksum( 0xa1dc81f9 /*Name*/, &checksumName);\r\n\t\t\t\tif (checksumName == 0)\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::PrintContents(pNode);\r\n\t\t\t\t\tprintf(\"FAILED BECAUSE Node %d is LevelGeometry, but has no Name=....\\n\",i);\r\n\t\t\t\t\tfail = true;\r\n\t\t\t\t}\r\n\t\t\t\t//Nx::CSector *p_sector = Nx::CEngine::sGetSector(checksumName);\r\n\t\t\t\tNx::CSector *p_sector = p_main_scene->GetSector(checksumName);\r\n\t\t\t\t\r\n\t\t\t\t//Dbg_MsgAssert(p_sector,(\"sGetSector(0x%x) returned NULL (%s)\",checksumName,Script::FindChecksumName(checksumName)));\r\n\t\t\t\t\r\n\t\t\t\tif (p_sector)\r\n\t\t\t\t{\r\n\t\t\t\t\t \r\n\t\t\t\t\t// The park editor takes care of it's own visibility\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t// \r\n\r\n\t\t\t\t\t   \r\n\t\t\t\t\tif (Ed::CParkEditor::Instance()->UsingCustomPark()) \t\t// is it a custom park???\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( !( pNode->ContainsFlag( 0x7c2552b9/*\"CreatedAtStart\"*/  ) ) || skate_mod->ShouldBeAbsentNode( pNode ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// if this assertion fires, you are probably try to extend the park\r\n\t\t\t\t\t\t\t// editor to have some sectors be not \"createdatstart\"\r\n\t\t\t\t\t\t\t// which is not currently supported, as the park editor sets up it;s\r\n\t\t\t\t\t\t\t// own visibility and \"active\" state for things like:\r\n\t\t\t\t\t\t\t//   - restart nodes\r\n\t\t\t\t\t\t\t//   - the cursor\r\n\t\t\t\t\t\t\t//   - gap pieces\r\n\t\t\t\t\t\t\t// so you would need to re-work it so they were correctly flagged \r\n\t\t\t\t\t\t\t// as no created at start, and then remove this whole \"UsingCustomPark\" special case\r\n\t\t\t\t\t\t\t// This is also done in the logic around the call to ScriptCreateFromNodeIndex, below, in this function.\r\n\t\t\t\t\t\t\tDbg_MsgAssert(0,(\"Park ed levelgeom not set created at start\"));\r\n\t\t\t\t\t\t}\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// The sector will already be active and visible, since no flags will be set...\r\n\t\t\t\t\t\t// but if we're not created at start, set the non-collide and invisible flags:\r\n\t\t\t\t\t\tif ( !( pNode->ContainsFlag( 0x7c2552b9/*\"CreatedAtStart\"*/  ) ) || skate_mod->ShouldBeAbsentNode( pNode )\r\n\t\t\t\t\t\t\t )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_sector->SetActive(false);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Mick: as ParseNodeArray can get called multiple times\r\n\t\t\t\t\t\t\t// on the same node array\r\n\t\t\t\t\t\t\t// we need to clear any KILLED and INVIVIBLE flags\r\n\t\t\t\t\t\t\t// that might have been set in the previous session\r\n\t\t\t\t\t\t\tp_sector->SetVisibility(0xffffffff);\r\n\t\t\t\t\t\t\tp_sector->SetActive(true);\r\n\t\t\t\t\t\t\tp_sector->SetCollidable(true);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t// If it's an occluder, then we need to flag it as such\r\n\t\t\t\t\tif (  pNode->ContainsFlag( 0x4e549fe1/*\"Occluder\"*/   )\t)\r\n\t\t\t\t\t{\r\n//\t\t\t\t\t\tprintf (\"Occluding node %d, <%s>\\n\",i,Script::FindChecksumName(checksumName));\r\n\t\t\t\t\t\t// This object is an occluder\r\n\t\t\t\t\t\t// so need to flag it as so\r\n\t\t\t\t\t\tp_sector->SetOccluder(true);\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// For now, we make all occluders invisble, so we can see through them\r\n\t\t\t\t\t\t//printf (\"WARNING:   Occluders are being made invisible!!!!!!!\\n\");\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t//printf (\"WARNING:   Occluders are being made invisible!!!!!!!\\n\");\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t//printf (\"WARNING:   Occluders are being made invisible!!!!!!!\\n\");\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\tp_sector->SetActive(false);\r\n\r\n\t\t\t\t\t\t// If this occluder is not created at start, disable it.\r\n\t\t\t\t\t\tif( !pNode->ContainsFlag( 0x7c2552b9 /*\"CreatedAtStart\"*/  ))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tNx::CEngine::sEnableOcclusionPoly( checksumName, false );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Set the light group (usually will be \"outdoor\")\r\n\t\t\t\t\tuint32\tlight_group = CRCD(0xe3714dc1,\"outdoor\");\t\t\t // default to OutDoors\r\n\t\t\t\t\tpNode->GetChecksum(CRCD(0x7e4813a7,\"lightgroup\"),&light_group);\r\n\t\t\t\t\tp_sector->SetLightGroup(light_group);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Only fail in non-multiplayer games\r\n\t\t\t\t\t// as it's quite valid for a sector to not exist in a network game\r\n\t\t\t\t\t// as they are stripped out at SceneConv time \r\n\t\t\t\t\tif (!skate_mod->IsMultiplayerGame())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//printf(\"sGetSector(0x%x) returned NULL (%s)\",checksumName,Script::FindChecksumName(checksumName));\r\n\t\t\t\t\t\tprintf(\"FAILED BECAUSE: Cannot find level geometry or collision for node %d \\nMaybe there are spaces in or after the name of the Max object (%s)?\\nOr maybe the .QN file does not match the .SCN file checked into Perforce?\\n\"\r\n\t\t\t\t\t\t\t\t\t   ,i,Script::FindChecksumName(checksumName));\r\n\t\t\t\t\t\tfail = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\tbool is_trick_object = pNode->ContainsComponentNamed( \"TrickObject\" );\r\n\t\r\n\t\t\t\tif (!Config::CD())\r\n\t\t\t\t{\r\n\t\t\t\t\tbool debug_graffiti = Script::GetInt( \"create_all_trick_objects\", false );\r\n\t\t\t\t\tif ( debug_graffiti )\r\n\t\t\t\t\t\tis_trick_object = true;\r\n\t\t\t\t}\t\t\r\n\r\n\t\t\t\t// Only add trick objects is they are not flagged as absentinnetgames\r\n\t\t\t\tif ( !skate_mod->ShouldBeAbsentNode( pNode ) && is_trick_object )\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::PushMemProfile(\"Trick Object Clusters\");\r\n\t\t\t\t\t// get the node name\r\n\t\t\t\t\tuint32 checksumName;\r\n\t\t\t\t\tpNode->GetChecksum( \"name\", &checksumName, true );\r\n\t\r\n\t\t\t\t\tuint32 clusterName = checksumName;\r\n\t\t\t\t\tpNode->GetChecksum( \"Cluster\", &clusterName, false );\r\n\t\t\t\t\tskate_mod->GetTrickObjectManager()->AddTrickCluster( clusterName );\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t// add the environment object to this cluster\r\n\t\t\t\t\tskate_mod->GetTrickObjectManager()->AddTrickObjectToCluster( checksumName, clusterName );\r\n\t\t\t\t\tMem::PopMemProfile();\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\t// The following nodes are capable of being ignored in net games\t\t\r\n\t\t\r\n\t\tif ( skate_mod->ShouldBeAbsentNode( pNode ) )\r\n\t\t{\r\n\t\t\t// Don't load, as it's a net game\r\n\t\t}\t\r\n\t\telse \r\n\t\t{\r\n\t\t\r\n\t\t\tif (ClassChecksum == 0xbf4d3536 && Ed::CParkEditor::Instance()->UsingCustomPark())  // LevelGeometry\r\n\t\t\t{\r\n\t\t\t\t// Level geometry in park editor is ignored, see above.\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t\r\n\t\t\t\tif (ClassChecksum == 0x8470f2e) // checksum 'ProximNode'\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::PushMemProfile(\"Proximity Nodes\");\r\n\t\t\t\t\tObj::Proxim_AddNode( i, pNode->ContainsFlag( 0x7c2552b9/*\"CreatedAtStart\"*/ ) );\r\n\t\t\t\t\tMem::PopMemProfile();\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (ClassChecksum == 0xd64dc7c2) // checksum 'EmitterObject'\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::PushMemProfile(\"Emitter Objects\");\r\n\t\t\t\t\tObj::CEmitterManager::sAddEmitter( i, pNode->ContainsFlag( 0x7c2552b9/*\"CreatedAtStart\"*/ ) );\r\n\t\t\t\t\tMem::PopMemProfile();\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( pNode->ContainsFlag( 0x7c2552b9 /*\"CreatedAtStart\"*/ ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tScriptCreateFromNodeIndex( i );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\t\t\t\t\r\n\t}\t\r\n\t\r\n\tDbg_MsgAssert(!fail, (\"ParseNodeArray FAILED, see above for reasons labled FAILED BECAUSE \\n\"));\r\n\t\r\n\tObj::Proxim_AddedAll();\r\n\tp_rail_man->AddedAll();\r\n\tMdl::Skate::Instance()->GetGapChecklist()->FindGaps();\r\n\r\n\t/*\r\n\t// STUPID HACK\r\n\tEd::ParkEditor* park_ed = Ed::ParkEditor::Instance();\r\n\tif (park_ed->IsInitialized() && park_ed->GameGoingOrOutsideEditor())\r\n\t\tpark_ed->MakeStuffInvisibleForGameplay();\r\n\t*/\r\n\t\r\n// Mick:\r\n// Level lights need to be created AFTER the node array is parsed, so that the \r\n// lightgroups are set on the level geometry\r\n// otherwise geometry nodes that occur after this one will default to \"outdoor\"\t\r\n\r\n\tfor (i=0; i<pNodeArray->GetSize(); ++i)\r\n\t{\r\n\t\tScript::CStruct *pNode=pNodeArray->GetStructure(i);\r\n\t\tDbg_MsgAssert(pNode,(\"NULL pNode\"));\r\n\r\n\t\tuint32 ClassChecksum = 0;\r\n\t\tpNode->GetChecksum( 0x12b4e660 /*\"Class\"*/, &ClassChecksum );\r\n\r\n\r\n\t\t// First the nodes that need some special processing\r\n\t\t// for the \"net game\" state\r\n\t\tif (ClassChecksum == CRCD(0xa0e52802,\"LevelLight\"))\r\n\t\t{\t\t\t\t\t\t   \r\n\t\t\t// Will need to check a parameter here to see if the light is flagged to affect objects.\r\n\t\t\tbool affects_objects\t= !pNode->ContainsFlag( CRCD( 0xe1509e4f, \"ExcludeSkater\" ));\r\n\t\t\tbool affects_geometry\t= !pNode->ContainsFlag( CRCD( 0x6f050e18, \"ExcludeLevel\" ));\r\n\r\n\t\t\t// Get the name checksum of this node, since this will be used as the link between the node and the Scene Light.\r\n\t\t\tuint32 name_checksum = SkateScript::GetNodeNameChecksum( i );\r\n\r\n\t\t\tMth::Vector pos;\r\n\t\t\tSkateScript::GetPosition( pNode, &pos );\r\n\r\n\t\t\t// Default values.\r\n\t\t\tfloat intensity\t\t= 100.0f;\r\n\t\t\tfloat inner_radius\t= 300.0f;\r\n\t\t\tfloat outer_radius\t= 300.0f;\r\n\r\n\t\t\tpNode->GetFloat( CRCD( 0x2689291c, \"Brightness\" ), &intensity );\t\r\n\t\t\tpNode->GetFloat( CRCD( 0x8d2c287f, \"InnerRadius\" ), &inner_radius );\r\n\t\t\tpNode->GetFloat( CRCD( 0x833950cc, \"OuterRadius\" ), &outer_radius );\r\n\r\n\t\t\tif( !pNode->ContainsFlag( CRCD( 0x7c2552b9, \"CreatedAtStart\" )))\r\n\t\t\t{\r\n\t\t\t\t// This light is not supposed to be active at startup.\r\n\t\t\t}\r\n\r\n\t\t\t// Lights default to pure white in the absence of any color information.\r\n\t\t\tImage::RGBA col( 0xFF, 0xFF, 0xFF, 0x00 );\r\n\r\n\t\t\tScript::CArray *p_array;\r\n\t\t\tpNode->GetArray( CRCD( 0x99a9b716, \"Color\" ), &p_array );\r\n\t\t\tif( p_array )\r\n\t\t\t{\r\n\t\t\t\tcol.r = p_array->GetInteger( 0 );\r\n\t\t\t\tcol.g = p_array->GetInteger( 1 );\r\n\t\t\t\tcol.b = p_array->GetInteger( 2 );\r\n\t\t\t}\r\n\r\n\t\t\tif( affects_objects )\r\n\t\t\t{\r\n\t\t\t\tNx::CSceneLight *p_new_light = Nx::CLightManager::sAddSceneLight();\r\n\t\t\t\tif( p_new_light )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_new_light->SetNameChecksum( name_checksum );\r\n\t\t\t\t\tp_new_light->SetLightPosition( pos );\r\n\r\n\t\t\t\t\t// Set the color, radius and intensity.\r\n\t\t\t\t\tp_new_light->SetLightIntensity( intensity * 0.01f );\r\n\t\t\t\t\tp_new_light->SetLightColor( col );\r\n\t\t\t\t\tp_new_light->SetLightRadius( outer_radius );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"Too many Scene lights\"));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif( affects_geometry )\r\n\t\t\t{\r\n\t\t\t\tNx::CLightManager::sAddVCLight(name_checksum,pos,intensity,col,outer_radius);\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n\t\r\n\r\n\tMem::PopMemProfile(/*\"ParseNodeArray\"*/);\r\n\r\n\treturn true;\r\n}\t\r\n\r\nstatic char LastNodeArrayLoaded[128];\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LoadNodeArray | Will load node array from the file specified \r\n// @uparm \"string\" | File name to load\r\nbool ScriptLoadNodeArray(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMem::PushMemProfile(\"LoadNodeArray\");\r\n\t\r\n\t// Remove any spawned scripts that might have been left over from the previous level.\r\n\tScript::DeleteSpawnedScripts();\r\n\t\t\r\n\t\r\n\tconst char *pFileName=NULL;\r\n\tpParams->GetText(NONAME,&pFileName);\r\n\tDbg_MsgAssert(pFileName,(\"LoadNodeArray requires a file name.\"));\r\n\r\n\tstrcpy(LastNodeArrayLoaded,pFileName);\r\n\r\n\t// Load the QB\r\n\tSkateScript::LoadQB(pFileName);\r\n\t\r\n\t// Ensure it has a node array in it\r\n\tScript::CArray* pNodeArray=Script::GetArray(CRCD(0xc472ecc5,\"NodeArray\"));\r\n\tDbg_MsgAssert(pNodeArray,(\"No NodeArray found in %s\",pFileName));\r\n\r\n\tfor ( uint32 i = 0; i < pNodeArray->GetSize(); i++ )\r\n\t{\r\n\t\tScript::CStruct* pStructure = pNodeArray->GetStructure(i);\r\n\t\tpStructure->AddInteger(\"nodeIndex\", i);\r\n\t}\r\n\r\n\tif (pParams->ContainsFlag(\"park_editor\"))\r\n\t{\r\n\t\t// PARKED4:\r\n\t\t// Nothing needs doing here, we don't preload any models in the park editor\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// not a park editor QB, parse as normal\r\n//\t\tScriptPreloadModels( NULL, NULL );\r\n\t}\r\n\tMem::PopMemProfile(/*\"LoadNodeArray\"*/);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ReLoadNodeArray | Will reload the last node array you loaded, \r\n// without parsing it, and without deleting anything. \r\n// Note, this will load directly from the .qb, so there is NO NEED to rebuild the .pre files. \r\n// Using this command by itself could be used if you are just altering \r\n// stuff like trigger scripts.  However, as it does not respawn anything, \r\n// you have the potential to mess things up.  Give it a go though, you can \r\n// always just do a Select+Circle to make sure. \r\nbool ScriptReLoadNodeArray(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\t\r\n\t\r\n\t// We try to use the Debug heap, as we assume we will be fragmenting memory like a jackass\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t\r\n\tconst char *pFileName=LastNodeArrayLoaded;\r\n\t// Load the QB\r\n\tSkateScript::LoadQB(pFileName);\r\n\t\r\n\t// Ensure it has a node array in it\r\n\tScript::CArray *pNodeArray=Script::GetArray(CRCD(0xc472ecc5,\"NodeArray\"));\r\n\t\r\n\tDbg_MsgAssert(pNodeArray,(\"No NodeArray found in %s\",pFileName));\r\n\t\t\r\n\t// renumber node indices\r\n\tfor ( uint32 i = 0; i < pNodeArray->GetSize(); i++ )\r\n\t{\r\n\t\tScript::CStruct* pStructure = pNodeArray->GetStructure(i);\r\n\t\tpStructure->AddInteger(\"nodeIndex\", i);\r\n\t}\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetBackgroundColor | Sets the background color. Each component \r\n// is in the range 0-255.  The alpha value currently is not used. \r\n// @parmopt int | r | 0 | Red component\r\n// @parmopt int | g | 0 | Green component\r\n// @parmopt int | b | 0 | Blue component\r\n// @parmopt int | alpha | 0 | Alpha value\r\nbool ScriptSetBackgroundColor(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t    \r\n\tint Red=0;\r\n\tint Green=0;\r\n\tint Blue=0;\r\n\tint Alpha=0;\r\n\tpParams->GetInteger(\"r\",&Red);\r\n\tpParams->GetInteger(\"g\",&Green);\r\n\tpParams->GetInteger(\"b\",&Blue);\r\n\tpParams->GetInteger(\"alpha\",&Alpha);\r\n    \r\n/*\t\r\n\tgfx_man->sBackgroundColor.r \t= Red;\r\n\tgfx_man->sBackgroundColor.g = Green;\r\n\tgfx_man->sBackgroundColor.b \t= Blue;\r\n\tgfx_man->sBackgroundColor.a = Alpha;   \r\n*/\r\n\tprintf (\"STUBBED ScriptSetBackgroundColor\\n\");\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetBSPAmbientColor | Sets the ambient color for the BSP \r\n// (The environment, or the non-moving objects). \r\n// NOTE:  This should be set to 0,0,0, as any other setting will result \r\n// in much slowdown.  However, you can set it temporarily if you \r\n// want to try out effects quickly. \r\n// @parmopt int | r | 0 | Red component\r\n// @parmopt int | g | 0 | Green component\r\n// @parmopt int | b | 0 | Blue component\r\n// @parmopt int | alpha | 0 | Alpha value\r\nbool ScriptSetBSPAmbientColor(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tDbg_Message( \"SetBSPAmbientColor is obsolete\" );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetDFFAmbientColor | Sets the ambient color for the DFFs \r\n// (The skater, cars and suchlike.).\r\n// @parmopt int | r | 0 | Red component\r\n// @parmopt int | g | 0 | Green component\r\n// @parmopt int | b | 0 | Blue component\r\n// @parmopt int | alpha | 0 | Alpha value\r\nbool ScriptSetDFFAmbientColor(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\t\t\t\r\n\tDbg_Message( \"SetDFFAmbientColor is obsolete\" );\r\n\treturn true;\r\n}\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetDFFDirectColor | Sets the directional light color \r\n// for the DFFs (The skater, cars and suchlike.).   (Note:  temporary, \r\n// until we get a better lighting setup). \r\n// @parmopt int | r | 0 | Red component\r\n// @parmopt int | g | 0 | Green component\r\n// @parmopt int | b | 0 | Blue component\r\n// @parmopt int | alpha | 0 | Alpha value\r\nbool ScriptSetDFFDirectColor(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tDbg_Message( \"SetDFFDirectColor is obsolete\" );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetDynamicLightModulationFactor | A value of 0.0 means no \r\n// effect (light/dark polys have no effect). \r\n// A value of 1.0 means the maximum possible effect from light/dark polys \r\n// These values will stay set until changed, so designers will want to\r\n// put these in their level startup scripts. \r\n// @parm float | value | \r\n// @parmopt flag | ambient | | \r\n// @parmopt bool | directional | | \r\nbool ScriptSetDynamicLightModulationFactor( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t\r\n\r\n\tbool\tok;\r\n\tint\t\tindex\t= 0;\r\n\tfloat\tvalue\t= 0.0f;\r\n\tif( pParams->GetFloat( \"value\", &value ))\r\n\t{\r\n\t\tif( pParams->ContainsFlag( \"ambient\" ))\r\n\t\t{\r\n\t\t\tNx::CLightManager::sSetAmbientLightModulationFactor(value);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tok = pParams->GetInteger( \"directional\", &index );\r\n\t\t\tNx::CLightManager::sSetDiffuseLightModulationFactor(index, value);\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetClippingDistances | Sets the clipping distances in inches. \r\n// Near should generally be left at 12, Far should be whatever is \r\n// appropriate for your level. Example: \r\n// SetClippingDistances Near=12 Far=8000  \r\n// @parm float | Near |\r\n// @parm float | Far | \r\nbool ScriptSetClippingDistances(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tfloat Near=Gfx::Camera::vDEFAULT_FARZ;\r\n\tfloat Far=Gfx::Camera::vDEFAULT_NEARZ;\r\n\tpParams->GetFloat(\"Near\",&Near);\r\n\tpParams->GetFloat(\"Far\",&Far);\r\n\r\n\t// This is a bit of a patch,\r\n\t// cycle over the two possible cameras, and set the clipping dist\r\n\tfor (int cam = 0; cam < 2; cam ++)\r\n\t{\r\n\t\t\r\n\t\tGfx::Camera *p_cam = Nx::CViewportManager::sGetCamera(cam);\r\n\t\tif (p_cam)\r\n\t\t{\r\n\t\t\tp_cam->SetNearFarClipPlanes(Near,Far);\r\n\t\t}\r\n\t}\r\n\t//Gfx::Camera::SetNearFarClipPlanes(Near,Far);\r\n\r\n\r\n\t// Also Gamecube uses different near and far z clip planes, and has a fog far plane independent of the\r\n\t// camera far plane. So indicate here what the fog far plane for Gamecube should be.\r\n//#\tifdef __PLAT_NGC__\r\n//\tNsRender::setFogFar( Far );\r\n//#\tendif // __PLAT_NGC__\r\n\r\n\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetTrivialFarZClip | Sets the Z clipping distance \r\n// SetTrivialFarZClip on        --- to turn it on\r\n// SetTrivialFarZClip off       --- to turn it off \r\n// @flag on | Pass this in to set the trivial Z clipping\r\n// distance to true or false\r\nbool ScriptSetTrivialFarZClip(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\tbool on = false;\r\n\r\n\tif( pParams->ContainsFlag( \"on\" ))\r\n\t{\r\n\t\ton = true;\r\n\t}\r\n\r\n\t Gfx::Manager * gfx_manager =  Gfx::Manager::Instance();\r\n\tgfx_manager->SetTrivialFarZClip( on );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EnableFog | \r\nbool ScriptEnableFog( Script::CStruct *pParams,\r\n\t\t\t\t\t  Script::CScript *pScript )\r\n{\r\n\tNx::CFog::sEnableFog(true);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DisableFog | \r\nbool ScriptDisableFog( Script::CStruct *pParams,\r\n\t\t\t\t\t  Script::CScript *pScript )\r\n{\r\n\tNx::CFog::sEnableFog(false);\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetFogDistance | Sets the \"near\" distance (in inches) \r\n// at which fogging will begin.  (Polys closer than the near distance\r\n// will not be fogged.  Beyond the near distance, they will become\r\n// increasingly fogged until they reach maximum fogging at the far\r\n// clip distance -- see SetClippingDistances).\r\n// @parm float | distance | distance in inches\r\nbool ScriptSetFogDistance( Script::CStruct *pParams,\r\n\t\t\t\t\t\t   Script::CScript *pScript )\r\n{\r\n\t\r\n\tfloat fog_dist = 0.0f;\r\n\tpParams->GetFloat( \"distance\", &fog_dist );\r\n\r\n\tNx::CFog::sSetFogNearDistance(fog_dist);\r\n\r\n\t// Garrett: Not sure if this is needed anymore, but leaving it there\r\n\t// in case some other platforms need it.\r\n\t// This is a bit of a patch,\r\n\t// cycle over the two possible cameras, and set the clipping dist\r\n\tfor ( int cam = 0; cam < 2; cam++ )\r\n\t{\r\n\t\tGfx::Camera *p_cam = Nx::CViewportManager::sGetCamera(cam);\r\n\t\tif ( NULL != p_cam )\r\n\t\t{\r\n\t\t\tp_cam->SetFogNearPlane( fog_dist );\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetFogExponent | Sets the fog exponent.  The exponent\r\n// value determines the \"spread\" of the fog, or how far out you\r\n// must go before you reach maximum fog.  This component of fog\r\n// will probably change in the near future.\r\n// @parm float | exponent | fog exponent\r\nbool ScriptSetFogExponent( Script::CStruct *pParams,\r\n\t\t\t\t\t\t   Script::CScript *pScript )\r\n{\r\n\tfloat exponent;\r\n\tif (!pParams->GetFloat( \"exponent\", &exponent ))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find parameter 'exponent'\"));\r\n\t}\r\n\r\n\tNx::CFog::sSetFogExponent(exponent);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetFogColor | Sets the color that will be used for\r\n// atmospheric fogging.  Color components are in the range 0-255. \r\n// The alpha component is in the range of 0-128.\r\n// @parmopt int | r | 255 | red component\r\n// @parmopt int | g | 255 | green component\r\n// @parmopt int | b | 255 | blue component\r\n// @parmopt int | a | 128 | alpha component (opacity of fog)\r\nbool ScriptSetFogColor( Script::CStruct *pParams,\r\n\t\t\t\t\t\tScript::CScript *pScript )\r\n{\r\n\t\r\n\tint red = 255;\r\n\tint green = 255;\r\n\tint blue = 255;\r\n\tint alpha = 128;\r\n\tpParams->GetInteger( \"r\", &red );\r\n\tpParams->GetInteger( \"g\", &green );\r\n\tpParams->GetInteger( \"b\", &blue );\r\n\tpParams->GetInteger( \"a\", &alpha );\r\n\r\n\tImage::RGBA rgba(red, green, blue, alpha);\r\n\r\n\tNx::CFog::sSetFogRGBA( rgba );\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\n// @script | SetUVWibbleParams | Sets the UV wibble parameters of a sector\r\n// @parm name | sector | name of sector\r\n// @parm float | u_vel   | u velocity\r\n// @parm float | u_amp   | u amplitude\r\n// @parm float | u_freq  | u frequency\r\n// @parm float | u_phase | u phase\r\n// @parm float | v_vel   | v velocity\r\n// @parm float | v_amp   | v amplitude\r\n// @parm float | v_freq  | v frequency\r\n// @parm float | v_phase | v phase\r\nbool ScriptSetUVWibbleParams(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// Get sector checksum\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(\"sector\", &checksum))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find parameter sector\"));\r\n\t}\r\n\r\n\t// Find sector\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(checksum);\r\n\tDbg_MsgAssert(p_sector, (\"Can't find sector %x in world\", checksum));\r\n\r\n\t// Extract all the parameters\r\n    float u_velocity;\r\n    float u_amplitude;\r\n    float u_frequency;\r\n    float u_phase;\r\n    float v_velocity;\r\n    float v_amplitude;\r\n    float v_frequency;\r\n    float v_phase;\r\n\tbool found_all;\r\n\r\n\tfound_all  = pParams->GetFloat(\"u_vel\", &u_velocity);\r\n\tfound_all &= pParams->GetFloat(\"u_amp\", &u_amplitude);\r\n\tfound_all &= pParams->GetFloat(\"u_freq\", &u_frequency);\r\n\tfound_all &= pParams->GetFloat(\"u_phase\", &u_phase);\r\n\tfound_all &= pParams->GetFloat(\"v_vel\", &v_velocity);\r\n\tfound_all &= pParams->GetFloat(\"v_amp\", &v_amplitude);\r\n\tfound_all &= pParams->GetFloat(\"v_freq\", &v_frequency);\r\n\tfound_all &= pParams->GetFloat(\"v_phase\", &v_phase);\r\n\r\n\tDbg_MsgAssert(found_all, (\"Missing one or more of the wibble parameters.  Must fill them all out.\"));\r\n\r\n\tp_sector->SetUVWibbleParams(u_velocity, u_amplitude, u_frequency, u_phase, v_velocity, v_amplitude, v_frequency, v_phase);\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | EnableExplicitUVWibble | Enables explicit setting of the UV wibble offsets.\r\n// To set the offsets, call SetUVWibbleOffsets.\r\n// @parm name | sector | name of sector\r\nbool ScriptEnableExplicitUVWibble(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// Get sector checksum\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(\"sector\", &checksum))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find parameter sector\"));\r\n\t}\r\n\r\n\t// Find sector\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(checksum);\r\n\tDbg_MsgAssert(p_sector, (\"Can't find sector %x in world\", checksum));\r\n\r\n\tp_sector->UseExplicitUVWibble(true);\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | DisableExplicitUVWibble | Disables explicit setting of the UV wibble offsets.\r\n// @parm name | sector | name of sector\r\nbool ScriptDisableExplicitUVWibble(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// Get sector checksum\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(\"sector\", &checksum))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find parameter sector\"));\r\n\t}\r\n\r\n\t// Find sector\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(checksum);\r\n\tDbg_MsgAssert(p_sector, (\"Can't find sector %x in world\", checksum));\r\n\r\n\tp_sector->UseExplicitUVWibble(false);\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | SetUVWibbleOffsets | Sets the UV wibble offsets explicitly\r\n// @parm name | sector | name of sector\r\n// @parm float | u_off | u offset\r\n// @parm float | v_off | v offset\r\nbool ScriptSetUVWibbleOffsets(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// Get sector checksum\r\n\tuint32 checksum;\r\n\tif (!pParams->GetChecksum(\"sector\", &checksum))\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't find parameter sector\"));\r\n\t}\r\n\r\n\t// Find sector\r\n\tNx::CSector *p_sector = Nx::CEngine::sGetSector(checksum);\r\n\tDbg_MsgAssert(p_sector, (\"Can't find sector %x in world\", checksum));\r\n\r\n\t// Extract all the parameters\r\n    float u_offset;\r\n    float v_offset;\r\n\tbool found_all;\r\n\r\n\tfound_all  = pParams->GetFloat(\"u_off\", &u_offset);\r\n\tfound_all &= pParams->GetFloat(\"v_off\", &v_offset);\r\n\r\n\tDbg_MsgAssert(found_all, (\"Missing one or more of the wibble offset parameters.  Must fill them all out.\"));\r\n\r\n\tp_sector->SetUVWibbleOffsets(u_offset, v_offset);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetPreferenceString(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tScript::CStruct* pStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tuint32 field_id, pref_type;\r\n\tconst char* ui_string;\r\n\tCStruct* pass_back_params;\r\n    \r\n\tpass_back_params = pScript->GetParams();\r\n\r\n\tpParams->GetChecksum( NO_NAME, &field_id );\r\n\tpParams->GetChecksum( \"pref_type\", &pref_type );\r\n\r\n\tpPreferences = Mdl::GetPreferences(pref_type); // This will assert if it cannot find the prefs\r\n\t\r\n\tpStructure = pPreferences->GetPreference( field_id );\r\n\tDbg_MsgAssert(pStructure, (\"\\n%s\\nCan't get preference 0x%x (%s)\",pScript->GetScriptInfo(),field_id, Script::FindChecksumName(field_id)));\r\n\t\r\n\t//pParams->AddStructure( \"preference\", pStructure );\r\n\tpStructure->GetString( \"ui_string\", &ui_string );\r\n\tpass_back_params->AddString( \"ui_string\", ui_string );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetPreferencePassword(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tScript::CStruct* pStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tuint32 field_id, pref_type;\r\n\tconst char* ui_string;\r\n\tCStruct* pass_back_params;\r\n\tstatic char\ts_password_string[32];\r\n\tuint32 i;\r\n    \r\n\tpass_back_params = pScript->GetParams();\r\n\r\n\tpParams->GetChecksum( NO_NAME, &field_id );\r\n\tpParams->GetChecksum( \"pref_type\", &pref_type );\r\n\r\n\tpPreferences = Mdl::GetPreferences(pref_type); // This will assert if it cannot find the prefs\r\n\r\n\tpStructure = pPreferences->GetPreference( field_id );\r\n\t//pParams->AddStructure( \"preference\", pStructure );\r\n\tpStructure->GetString( \"ui_string\", &ui_string );\r\n\tfor( i = 0; i < strlen( ui_string ); i++ )\r\n\t{\r\n\t\ts_password_string[i] = '*';\r\n\t}\r\n\t\r\n\tDbg_Assert( i < 32 );\r\n\ts_password_string[i] = '\\0';\r\n\r\n\tpass_back_params->AddString( \"password_string\", s_password_string );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetPreferenceChecksum(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tScript::CStruct* pStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tuint32 field_id, checksum, pref_type;\r\n\tCStruct* pass_back_params;\r\n    \r\n\tpass_back_params = pScript->GetParams();\r\n\r\n\tpParams->GetChecksum( NO_NAME, &field_id );\r\n\tpParams->GetChecksum( \"pref_type\", &pref_type );\r\n\r\n\tpPreferences = Mdl::GetPreferences(pref_type); // This will assert if it cannot find the prefs\r\n\r\n\tpStructure = pPreferences->GetPreference( field_id );\r\n\t//pParams->AddStructure( \"preference\", pStructure );\r\n\tpStructure->GetChecksum( \"checksum\", &checksum );\r\n\tpass_back_params->AddChecksum( \"checksum\", checksum );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetPreference | sets the prefs to those specified in\r\n// the params structure\r\n// @parm name | field | the field id\r\n// @parm structure | params | \r\nbool ScriptSetPreference(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\t// gets either network or splitscreen prefs, as appropriate\r\n\tPrefs::Preferences* pPreferences = Mdl::GetPreferences( pParams );\r\n\t\r\n\tuint32 field_id;\r\n\tpParams->GetChecksum( \"field\", &field_id, true );\r\n\r\n\tScript::CStruct* pSubParams;\r\n\tpParams->GetStructure( \"params\", &pSubParams, true );\r\n\tpPreferences->SetPreference( field_id, pSubParams );\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tScript::PrintContents(pSubParams);\r\n#endif\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PreferenceEquals | returns true if the actual preference value\r\n// for the given field equals the test value\r\n// @parm name | field | the field id\r\n// @parm name | equals | test value\r\nbool ScriptPreferenceEquals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\t// gets either network or splitscreen prefs, as appropriate\r\n\tPrefs::Preferences* pPreferences = Mdl::GetPreferences( pParams );\r\n\r\n\tuint32 field_id;\r\n\tpParams->GetChecksum(\"field\", &field_id, true);\r\n\r\n\tuint32 test_value;\r\n\tpParams->GetChecksum( \"equals\", &test_value, true );\r\n\r\n\tScript::CStruct* pStructure = pPreferences->GetPreference( field_id );\r\n\tDbg_Assert(pStructure);\r\n\r\n\tuint32 actual_value;\r\n\tpStructure->GetChecksum( \"checksum\", &actual_value, true );\r\n\r\n\treturn ( test_value == actual_value );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetCamera | \r\nbool ScriptResetCamera(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\t// This is a bit of a patch,\r\n\t// cycle over the two possible cameras, and reset them\r\n\tfor (int cam = 0; cam < 2; cam ++)\r\n\t{\r\n\t\t\r\n\t\tGfx::Camera *p_cam = Nx::CViewportManager::sGetCamera(cam);\r\n\t\tif (p_cam)\r\n\t\t{\r\n\t\t\tprintf (\"TODO: ScriptResetCamera not implemented\\n\");\r\n\t\t}\r\n\t}\r\n\t//Gfx::Camera::SetNearFarClipPlanes(Near,Far);\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetVolumeFromValue | sets the volume according to the slider\r\n// @uparm sfxvol | the volume to set (either sfxvol or cdvol)\r\n// @parm name | id | the slider id used to change the volume\r\nbool ScriptSetVolumeFromValue( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\t/*\r\n\tuint32 whichParam;\r\n\tpParams->GetChecksum( NONAME, &whichParam, true );\r\n\r\n\tuint32 slider_id;\r\n\tpParams->GetChecksum( \"id\", &slider_id, true );\r\n\r\n\tFront::MenuFactory* menu_factory = Front::MenuFactory::Instance();\r\n\tFront::SliderMenuElement* pSliderElement = static_cast<Front::SliderMenuElement*>( menu_factory->GetMenuElement( slider_id, true ) );\r\n\tDbg_Assert( pSliderElement );\r\n\r\n\tswitch ( whichParam )\r\n\t{\r\n\t\tcase 0x8d6f6554: // \"sfxvol\"\r\n\t\t{\r\n\t\t\t Sfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\t\t\tsfx_manager->SetMainVolume( ( float )( 10 * pSliderElement->GetValue( ) ) );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0xa5162bd2: // \"cdvol\"\r\n\t\t{\r\n\t\t\t// still set the main music volume even if in the front end!!!\r\n\t\t\tPcm::SetVolume( ( float )( 10 * pSliderElement->GetValue( ) ) );\r\n\r\n\t\t\t// make sure the music is playing and shit...\r\n\t\t\tPcm::PauseMusic( false );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\t// unrecognized sound parameter\r\n\t\t\tDbg_MsgAssert( 0, ( \"Unrecognized sound parameter\" ) );\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\t*/\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetValueFromVolume | \r\n// @uparm sfxvol | the volume you're interested in (either sfxvol, cdvol, or cutvol)\r\nbool ScriptGetValueFromVolume( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\r\n\tuint32 whichParam;\r\n\tpParams->GetChecksum( NONAME, &whichParam, true );\r\n\r\n\tswitch ( whichParam )\r\n\t{\r\n\t\tcase 0x8d6f6554: // \"sfxvol\"\r\n\t\t{\r\n\t\t\t Sfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\t\t\tpScript->GetParams()->AddComponent( Script::GenerateCRC( \"value\" ), ESYMBOLTYPE_INTEGER, ( (int) sfx_manager->GetMainVolume() ) / 10 );\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n\t\tcase 0xa5162bd2: // \"cdvol\"\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddComponent( Script::GenerateCRC( \"value\" ), ESYMBOLTYPE_INTEGER, ( (int) Pcm::GetVolume() ) / 10 );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tcase 0xe32f3525: // \"cutvol\"\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AddComponent( Script::GenerateCRC( \"value\" ), ESYMBOLTYPE_INTEGER, ( (int) Pcm::GetMusicStreamVolume() ) / 10 );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\t// unrecognized sound parameter\r\n\t\t\tDbg_MsgAssert( 0, ( \"Unrecognized sound parameter\" ) );\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetSliderValue | \r\n// @parm name | id | the slider id\r\n// @parm int | value | value to assign to slider\r\nbool ScriptSetSliderValue( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\r\n\t/*\r\n\tuint32 slider_id;\r\n\tpParams->GetChecksum( \"id\", &slider_id, true );\r\n\r\n\tint value;\r\n\tpParams->GetInteger( \"value\", &value, true );\r\n\t\r\n\tFront::MenuFactory* menu_factory = Front::MenuFactory::Instance();\r\n\tFront::SliderMenuElement* pSliderElement = static_cast<Front::SliderMenuElement*>( menu_factory->GetMenuElement( slider_id, true ) );\r\n\tDbg_Assert( pSliderElement );\r\n\tpSliderElement->SetValue( value );\r\n\t*/\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetIconTexture | \r\n// @parm name | id | menuelement\r\n// @parm string | texture | the texture name\r\nbool ScriptSetIconTexture(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\t/*\r\n\tuint32 id;\r\n\tpParams->GetChecksum(\"id\", &id, true);\r\n\t\r\n\tFront::MenuFactory* menu_factory = Front::MenuFactory::Instance();\r\n\tFront::IconMenuElement* pIconElement = static_cast<Front::IconMenuElement*>( menu_factory->GetMenuElement( id, true ) );\r\n\r\n\tif ( pIconElement )\r\n\t{\r\n\t\tconst char* textureName;\r\n\t\tpParams->GetText(\"texture\", &textureName, true);\r\n\t\tpIconElement->SetTexture( textureName );\r\n\t}\r\n\t*/\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n// @script | SetMovementVelocity | Sets the movement (translational) \r\n// speed of the camera in the viewer. The number is in terms of inches per second. \r\n// @parmopt float | vel | 400 | velocity in inches per second\r\nbool ScriptSetMovementVelocity( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tfloat vel = 400;\r\n\tpParams->GetFloat( NONAME, &vel );\r\n\r\n\tMdl::CViewer::sSetMovementVelocity( vel );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetRotateVelocity | Sets the rotational speed of the \r\n// camera in the viewer. The number is in terms of degrees per second. \r\n// @parmopt float | vel | 120 | Rotational speed in degrees per second\r\nbool ScriptSetRotateVelocity( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tfloat vel = 120;\r\n\tpParams->GetFloat( NONAME, &vel );\r\n\r\n\tMdl::CViewer::sSetRotateVelocity( vel );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | OnReload | \r\n// This is a script function that doesn't do anything, it is just used to indicate what should\r\n// happen if the script gets reloaded at runtime. It needs to be the first \r\nbool ScriptOnReload(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetEngine | resets the engine\r\nbool ScriptResetEngine(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\t Mlp::Manager * mlp_manager =  Mlp::Manager::Instance();\r\n\tmlp_manager->QuitLoop();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ToggleMetrics | Toggle metrics - use before ToggleMemMetrics\r\nbool ScriptToggleMetrics(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\t Gfx::Manager * gfx_manager =  Gfx::Manager::Instance();\r\n\tgfx_manager->ToggleMetrics();\r\n    //Script::RunScript( \"show_poly_count\" );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ToggleNetMetrics | \r\nbool ScriptToggleNetMetrics(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\t GameNet::Manager * gamenet_manager =  GameNet::Manager::Instance();\r\n\tgamenet_manager->ToggleMetrics();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ToggleVRAMViewer | Toggle VRAM viewer\r\nbool ScriptToggleVRAMViewer(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\t Gfx::Manager * gfx_manager =  Gfx::Manager::Instance();\r\n\tgfx_manager->ToggleVRAMViewer();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DumpVRAMUsage | Spits out a file detailing VRAM usage \r\n// separately for all four contexts\r\nbool ScriptDumpVRAMUsage(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\t Gfx::Manager * gfx_manager =  Gfx::Manager::Instance();\r\n\tgfx_manager->DumpVRAMUsage();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ToggleLightViewer | Toggle the light viewer\r\nbool ScriptToggleLightViewer(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tDbg_Message( \"ToggleLightViewer is obsolete\" );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | debugrendermode | currently unsupported\r\nbool ScriptSetDebugRenderMode(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tDbg_Message( \"debugrendermode is obsolete\" );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | debugtoggletextureupload | currently unsupported\r\nbool ScriptToggleTextureUpload(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tDbg_Message( \"debugtoggletextureupload is obsolete\" );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | debugtoggletexturedraw | currently unsupported\r\nbool ScriptToggleTextureDraw(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tDbg_Message( \"debugtoggletexturedraw is obsolete\" );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | debugtogglepointdraw | currently unsupported\r\nbool ScriptTogglePointDraw(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tDbg_Message( \"debugtogglepointdraw is obsolete\" );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | debugrendertest1 | old function?  returns true if mbr_nsDebugTest1\r\n// (check cfuncs.cpp) is set\r\nbool ScriptRenderTest1(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n#ifdef __PLAT_NGPS__\r\n//\tmbr_nsDebugTest1=(mbr_nsDebugTest1)?0:1;\r\n#endif\r\n\treturn true;\r\n}\r\n// @script | debugrendertest2 | old function?  returns true if mbr_nsDebugTest2\r\n// (check cfuncs.cpp) is set\r\nbool ScriptRenderTest2(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n#ifdef __PLAT_NGPS__\r\n//\tmbr_nsDebugTest2=(mbr_nsDebugTest2)?0:1;\r\n#endif\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetViewMode | Debugging function to toggle the camera mode,\r\n// switching between normal, free with fixed skater, and free with moving skater\r\n// usually triggers with Select+X (See buttonscripts.q)\r\nbool ScriptSetViewMode(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint viewMode;\r\n\tpParams->GetInteger( NONAME, &viewMode, Script::ASSERT );\r\n\r\n\tDbg_Assert( viewMode >= 0 && viewMode < Obj::NUM_VIEW_MODES );\r\n\r\n\ts_view_mode = viewMode;\r\n\tMdl::CViewer::sSetViewMode( s_view_mode );\r\n\t// Handle toggling to different cameras based on view mode\r\n\t\r\n\tswitch (s_view_mode )\r\n\t{\r\n\t\tcase Obj::GAMEPLAY_SKATER_ACTIVE:\r\n\t\t\tSetActiveCamera(CRCD(0x967c138c,\"skatercam0\"),0, false);\t\t\t\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tSetActiveCamera(CRCD(0xeb17151b,\"viewer_cam\"),0, true);\t\t\t\t\t\t\r\n\t\t\tbreak;\t\t\r\n\t}\r\n\t\r\n\t\t\r\n\tObj::CSkater* pSkater;\r\n\tfor ( int i = 0; i < 8; i++ )\r\n\t{\r\n\t\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\tpSkater = skate_mod->GetSkater(i);\t\t\t\t\t\t   \r\n\t\tif ( pSkater )\t\t\t// Skater might not exist\r\n\t\t{\r\n\t\t\tpSkater->SetViewMode( (Obj::EViewMode)s_view_mode );\r\n\t\t}\r\n\t}\r\n\t\r\n\t// clear out the viewer object, if any\r\n\tMdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();\r\n\tif ( pViewer )\r\n\t{\r\n\t\tpViewer->RemoveViewerObject();   \t\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ToggleMetricItem | ToggleMetricItem will turn on or off \r\n// individual items in the metric display.\r\n// The item parameter is one of: <nl>\r\n// METRIC_TIME <nl>\r\n// METRIC_ARENAUSAGE <nl>            \r\n// METRIC_TOTALPOLYS <nl>\r\n// METRIC_POLYSPROC <nl>\r\n// METRIC_VERTS <nl>\r\n// METRIC_RESOURCEALLOCS <nl>\r\n// METRIC_TEXTUREUPLOADS <nl>\r\n// METRIC_VU1 <nl>\r\n// METRIC_DMA1 <nl>\r\n// METRIC_DMA2 <nl>\r\n// METRIC_VBLANKS <nl>\r\n// METRIC_DRAWTIME <nl>\r\n// METRIC_IHANDLERTIME <nl>\r\n// METRIC_SKYCACHE <nl>\r\n// METRIC_VIDEOMODE <nl>\r\n// METRIC_VRAMUSAGE <nl>\r\n// METRIC_MEMUSED <nl>\r\n// METRIC_MEMFREE <nl>\r\n// METRIC_REGIONINFO <nl>\r\n// @parmopt int | item | 0 | \r\nbool ScriptToggleMetricItem( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\r\n\t\r\n/*\r\n\tuint32 metricFlags = 0;\r\n\tpParams->GetInteger( \"item\", ( int * )&metricFlags );\r\n\r\n\t Gfx::Manager * gfx_manager =  Gfx::Manager::Instance();\r\n\r\n\tGfx::Metrics* pMetrics = gfx_manager->GetMetrics();\r\n\tpMetrics->ToggleMetricItem( metricFlags );\r\n*/\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ToggleMemMetrics | This will replace the PS2 specific\r\n// metrics with a list of the all the memory heaps, together with\r\n// the amount of fragmentation, and the amount of free memory. Note, \r\n// you have to use ToggleMetrics to actually see the metrics before\r\n// using ToggleMemMetrics <nl>\r\n// See the online doc for a full explanation of the various heaps\r\nbool ScriptToggleMemMetrics( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t/* \r\n\t Gfx::Manager * gfx_manager =  Gfx::Manager::Instance();\r\n\tGfx::Metrics* pMetrics = gfx_manager->GetMetrics();\r\n\tpMetrics->ToggleMemMetrics();\r\n\t*/\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// @script | KillAllTextureSplats | Destroys all exisiting texture splats\r\nbool ScriptKillAllTextureSplats( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tNx::KillAllTextureSplats();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ProximCleanup | Destroys all proxim nodes\r\nbool ScriptProximCleanup(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// TT12597: Clear out the proxim node pointers in the stream and sound components\r\n\t// new fast way, just go directly to the components, if any\r\n\tObj::CSoundComponent* p_sound_component = static_cast<Obj::CSoundComponent*>( Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType( CRC_SOUND ));\r\n\twhile( p_sound_component )\r\n\t{\r\n\t\tp_sound_component->ClearProximNode();\r\n\t\t\r\n\t\tp_sound_component = static_cast<Obj::CSoundComponent*>( p_sound_component->GetNextSameType());\r\n\t}\r\n\r\n\tObj::CStreamComponent* p_stream_component = static_cast<Obj::CStreamComponent*>( Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType( CRC_STREAM ));\r\n\twhile( p_stream_component )\r\n\t{\r\n\t\tp_stream_component->ClearProximNode();\r\n\t\t\r\n\t\tp_stream_component = static_cast<Obj::CStreamComponent*>( p_stream_component->GetNextSameType());\r\n\t}\r\n\r\n\tObj::Proxim_Cleanup();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Cleanup | Destroys current world, texture dictionaries, objects and railnodes.\r\n// @flag preserve_skaters | Set this to preserve the skaters\r\nbool ScriptCleanup(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t//\tDumpUnwindStack( 20, 0 );\r\n\t// Wait for any async rendering to finish before we proceed\t\r\n\tNx::CEngine::sFinishRendering();\r\n \t#ifdef\t__PLAT_NGPS__\r\n\tNxPs2::AllocateExtraDMA(false);\r\n\t#endif\r\n\r\n\tReplay::DeallocateReplayMemory();\r\n\t\r\n// goalmanager stuff moved here from Skate::ChangeLevel\r\n    Game::CGoalManager* p_GoalManager = Game::GetGoalManager();\r\n    Dbg_MsgAssert( p_GoalManager, ( \"couldn't get GoalManager\\n\" ) );\r\n    \r\n    p_GoalManager->DeactivateAllGoals();\r\n    p_GoalManager->RemoveAllGoals();\r\n\r\n\t// PARKED4:\r\n\tEd::CParkEditor* p_park_editor = Ed::CParkEditor::Instance();\r\n\tp_park_editor->Cleanup();\r\n\tp_park_editor->DeletePlayModeGapManager();\r\n\t\r\n\tMdl::Skate * skate_mod =  Mdl::Skate::Instance();\t\r\n\tbool preserve;\r\n\tbool was_spawned;\r\n\r\n\tDbg_Printf( \"Performing Cleanup\\n\" );\r\n\r\n\tGfx::DebuggeryLines_CleanUp( );\t// so we remove debug lines between levels\r\n\r\n\tpreserve = false;\r\n\tif( pParams )\r\n\t{\r\n\t\tpreserve = pParams->ContainsFlag(\"preserve_skaters\");\r\n\t}\t\r\n\r\n// ********************************************************************************************\r\n// ********************************************************************************************\r\n// ********************************************************************************************\r\n\t// A hacky way of preserving the running script, since skate's cleanup will destroy all\r\n\t// spawned scripts.\r\n\twas_spawned = false;\r\n\tif( pScript )\r\n\t{\r\n\t\twas_spawned = pScript->mIsSpawned;\r\n\t\tpScript->mIsSpawned = false;\r\n\t}\r\n\t// Delete's session objects managed by the \"Skate::\" code module\t\r\n\tskate_mod->Cleanup( );   \r\n\tif( pScript )\r\n\t{\r\n\t\tpScript->mIsSpawned = was_spawned;\r\n\t}\r\n\t\r\n\t// Destroy other Session Objects\r\n// These can be recreated, no assets are unloaded\r\n\r\n\t//skate_mod->GetGoalManager()->RemoveAllGoals();\t\r\n\r\n\tDbg_Printf( \"Destroying imposters...\" );\r\n\tNx::CEngine::sGetImposterManager()->Cleanup();\r\n\r\n\tDbg_Printf( \"Destroying misc fx...\" );\r\n\tNx::MiscFXCleanup();\r\n\r\n\tDbg_Printf( \"Clearing node-name hash table ...\" );\r\n\tSkateScript::ClearNodeNameHashTable();\r\n\r\n\t// Turn off fogging...let the next level turn it back on if it wants it\r\n\tNx::CFog::sEnableFog(false);\r\n\r\n\tScript::KillStoppedScripts();\r\n\r\n\r\n\tDbg_Printf( \"Cleaning up terrain soundFX manager.\" );\r\n\tEnv::CTerrainManager::sReset();\r\n\tDbg_Printf( \"Done.\\n\" );\r\n\r\n\t\t\t\t   \r\n// ********************************************************************************************\r\n// ********************************************************************************************\r\n// ********************************************************************************************\r\n// Actual unloading of assets starts here \r\n\t\r\n// unload sond effects (just resets the SRAM pointer)\t\t\t\t   \r\n\tDbg_Printf( \"Cleaning up soundFX manager.\" );\r\n\t Sfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\tsfx_manager->CleanUp( );\t\t// Sfx manager uses a very primitive memory management system ... check it out..\r\n\tDbg_Printf( \"Done.\\n\" );\r\n\r\n// Unload object models and animations\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\tprintf (\"unloading assman tables ...........\\n\");\r\n\t Ass::CAssMan * ass_manager =  Ass::CAssMan::Instance();\r\n\tass_manager->UnloadAllTables( );\r\n\tprintf (\"done unloading assman ...........\\n\");\r\n\r\n// ********************************************************************************************\r\n// ********************************************************************************************\r\n// ********************************************************************************************\r\n\tDbg_Printf( \"Unloading NodeArray .QB (level .qn file)\" );\r\n\tScript::CSymbolTableEntry *p_sym=Script::LookUpSymbol(CRCD(0xc472ecc5,\"NodeArray\"));\r\n\tif (p_sym)\r\n\t{\r\n\t\tSkateScript::UnloadQB(p_sym->mSourceFileNameChecksum);\r\n\t}\t\r\n\t\r\n// ********************************************************************************************\r\n// ********************************************************************************************\r\n// ********************************************************************************************\r\n// Unload the level specific qb.\r\n\t// Note: It's ok if s_level_specific_qb is 0, UnloadQB just won't do anything if it can't find it.\r\n\t#if 0\r\n\tSkateScript::UnloadQB(s_level_specific_qb);\r\n\ts_level_specific_qb=0;\r\n\t#else\r\n\tfor (int qb=0;qb<MAX_LEVEL_QBS;qb++)\r\n\t{\r\n\t\tSkateScript::UnloadQB(s_level_specific_qbs[qb]);\r\n\t\ts_level_specific_qbs[qb]=0;\r\n\t}\r\n\t#endif\r\n\t\r\n\r\n// ********************************************************************************************\r\n// ********************************************************************************************\r\n// ********************************************************************************************\r\n\t//  Unload the level geometry\r\n\t\t\t\t\t\r\n\tprintf (\"Starting to unload Geometry from the engine .....\\n\");\r\n\tScriptUnloadAllLevelGeometry(NULL,NULL);\r\n\tprintf (\"Done unloading Geometry from the engine .....\\n\");\t\t\t\t\t \r\n\r\n// ********************************************************************************************\r\n// ********************************************************************************************\r\n// ********************************************************************************************\r\n\t// Maybe unload the skaters\t\t \r\n\tif (preserve)\r\n\t{\r\n\t\t//ScriptUnhookSkaters(NULL,NULL);\t    // just tell the skaters that there is no world loaded  (maybe not needed)\r\n\t\r\n\t\t\t\t\t\t/*\r\n\t\t// NASTY (TEMPORARY) PATCH\r\n\t\t// since the skater is preserved, but the animations have been deleted\r\n\t\t// then we need to recreate the references to them (what was the \"animarray\")\t\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t\tif( skate_mod->GetLocalSkater())\r\n\t\t{\r\n\t\t\tObj::CAnimationComponent* pAnimComponent = GetAnimationComponentFromObject( skate_mod->GetLocalSkater() );\r\n\t\t\tpAnimComponent->SetAnimArray( Script::GenerateCRC(\"animload_human\") );\r\n\t\t}\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t*/\r\n\t\r\n\t}\r\n\telse\t\r\n\t{\r\n\t\tprintf(\"Clean up without preserve skaters\\n\");\r\n\t\t//skate_mod->UnloadSkaters();\r\n\t\t// as we're leaving a level,\r\n\t\t// clean up any additional heaps we might have allocated for the other skaters...\r\n\t\tMem::Manager::sHandle().DeleteSkaterHeaps();\r\n\t}\r\n\r\n\r\n\t// Unload any pip pre files that are no longer being used (eg, collision)\r\n\tconst char *p_pre_name=Pip::GetNextLoadedPre();\r\n\twhile (p_pre_name)\r\n\t{\r\n\t\tconst char *p_next=Pip::GetNextLoadedPre(p_pre_name);\r\n\t\tif (!Pip::PreFileIsInUse(p_pre_name))\r\n\t\t{\r\n\t\t\tPip::UnloadPre(p_pre_name);\r\n\t\t}\r\n\t\tp_pre_name=p_next;\r\n\t}\t\r\n\t\t\r\n\t// unload the skater parts pre file if it is currently loaded\r\n\tFile::PreMgr* pre_mgr = File::PreMgr::Instance();\r\n\tpre_mgr->UnloadPre( \"skaterparts.pre\", true );\t\t\t\r\n\t\r\n\t// Clear away any old cameras\r\n\tNx::CViewportManager::sDeleteMarkedCameras();\r\n\r\n\t// Clear any currently running FakeLights commands.\r\n\tNx::CLightManager::sClearCurrentFakeLightsCommand();\r\n\r\n\t// Clear away any non-permanent heaps\r\n\tNx::FlushParticleTextures(false);\r\n\t\r\n\t\r\n\t// cleanup pathman memory\r\n\tObj::CPathMan* pPathMan = Obj::CPathMan::Instance();\r\n\tpPathMan->DeallocateObjectTrackerMemory();\r\n\r\n\tif( skate_mod->ShouldAllocateNetMiscHeap())\r\n\t{\r\n\t\tDbg_Printf( \"****** LEVEL: 0x%x  0x%x 0x%x\\n\", skate_mod->m_requested_level, skate_mod->m_cur_level, skate_mod->m_prev_level );\r\n\t\tMem::Manager::sHandle().InitNetMiscHeap();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMem::Manager::sHandle().DeleteNetMiscHeap();\r\n\t}\r\n\r\n\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\t\r\n\t// destroy the custom heaps, if they exist\r\n\t// (TODO:  Move this to script, since it really\r\n\t// only applies to the skateshop)\r\n\tmem_man.DeleteNamedHeap( Script::GenerateCRC(\"preview\"), false );\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t// sanity checks for fragmentation\r\n\tMem::Heap* heap = mem_man.BottomUpHeap();\r\n\tint fragmentation = heap->mFreeMem.m_count;\r\n\t\r\n\t#if 1\t\r\n\tif (fragmentation > 10000)\r\n\t{\r\n\t\t// not guaranteed to do anything useful.... might crash the debugger (Mick)\r\n\t\tprintf (\"Dumping Fragments.....\\n\");\r\n\t\tMemView_DumpFragments(heap);\r\n\t\tprintf (\"Done Dumping Fragments.....\\n\");\r\n\t}\r\n\t#endif\r\n\t\r\n\tDbg_MsgAssert(fragmentation < 10000, (\"Excessive bottom up fragmentation (%d) after cleanup\",fragmentation)); \r\n\t\r\n#ifndef __PLAT_NGC__\r\n\theap = mem_man.TopDownHeap();\r\n\tfragmentation = heap->mFreeMem.m_count;\r\n\tif (fragmentation > 10000)\r\n\t{\r\n\t\t// not guaranteed to do anything useful.... might crash the debugger (Mick)\r\n\t\tprintf (\"Dumping Fragments.....\\n\");\r\n\t\tMemView_DumpFragments(heap);\r\n\t\tprintf (\"Done Dumping Fragments.....\\n\");\r\n\t}\r\n\t\r\n\tDbg_MsgAssert(fragmentation < 10000, (\"Excessive top down fragmentation (%d) after cleanup\",fragmentation)); \r\n#endif\t\t// __PLAT_NGC__\r\n\t#endif\r\n\r\n#\tif defined( __PLAT_XBOX__ ) && defined( __NOPT_ASSERT__ )\r\n#\tdefine AddStr(a,b)\t( pstrOut += wsprintf( pstrOut, a, b ))\r\n#\tdefine KB\t\t\t( 1024 )\r\n\tMEMORYSTATUS stat;\r\n\tchar strOut[1024], *pstrOut;\r\n\r\n    // Get the memory status.\r\n    GlobalMemoryStatus( &stat );\r\n\r\n    // Setup the output string.\r\n    pstrOut = strOut;\r\n//\tAddStr( \"%4d total kb of virtual memory.\\n\", stat.dwTotalVirtual / KB );\r\n//\tAddStr( \"%4d  free kb of virtual memory.\\n\", stat.dwAvailVirtual / KB );\r\n    AddStr( \"%4d total kb of physical memory.\\n\", stat.dwTotalPhys / KB );\r\n    AddStr( \"%4d  free kb of physical memory.\\n\", stat.dwAvailPhys / KB );\r\n//\tAddStr( \"%4d  percent of memory is in use.\\n\", stat.dwMemoryLoad );\r\n    OutputDebugString( strOut );\r\n#\tendif\r\n\t\r\n#\tifdef __PLAT_NGPS__\r\n\tif( skate_mod->ShouldAllocateInternetHeap())\r\n\t{\r\n\t\tMem::Manager::sHandle().InitInternetHeap();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMem::Manager::sHandle().DeleteInternetHeap();\r\n\t}\r\n#\tendif // __PLAT_NGPS__\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LoadQB | Loads the specified QB file.\r\n// @uparm \"data\\scripts\\ken.qb\" | File name of the qb to load\r\n// @uparmopt LevelSpecific | Whether this is the level specific script file\r\nbool ScriptLoadQB(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_file_name=NULL;\r\n\tpParams->GetString(NONAME,&p_file_name);\r\n\tDbg_MsgAssert(p_file_name,(\"LoadQB requires a file name.\"));\r\n\r\n\tif (pParams->ContainsFlag(\"LevelSpecific\"))\r\n\t{\r\n\t\t#if 0\r\n\t\tif (s_level_specific_qb)\r\n\t\t{\r\n\t\t\t// Only one level specific qb can exist currently, so make sure\r\n\t\t\t// that the old one is removed, just in case someone did two\r\n\t\t\t// LoadQB's in a row.\r\n\t\t\tSkateScript::UnloadQB(s_level_specific_qb);\r\n\t\t}\t\r\n\t\ts_level_specific_qb=Crc::GenerateCRCFromString(p_file_name);\r\n\t\t#else\r\n\t\t// Now allowing multiple level specific QBs, so \r\n\t\t// just look for a free slot\r\n\t\tint qb;\r\n\t\tfor (qb=0;qb<MAX_LEVEL_QBS;qb++)\r\n\t\t{\r\n\t\t\tif (!s_level_specific_qbs[qb])\r\n\t\t\t{\r\n\t\t\t\ts_level_specific_qbs[qb] = Crc::GenerateCRCFromString(p_file_name);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tDbg_MsgAssert(qb < MAX_LEVEL_QBS, (\"Can't have more that %d level specifc qbs (loading %s)\\n\",MAX_LEVEL_QBS,p_file_name)); \r\n\t\t\r\n\t\t\t\t\r\n\t\t#endif\r\n\t\t\r\n\t\t// Load the QB\r\n\t\tSkateScript::LoadQB(p_file_name,ASSERT_IF_DUPLICATE_SYMBOLS);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// This will not assert if duplicate symbols. This is needed for when a \r\n\t\t// LoadQB command is put in a button-script as a convenient way to reload\r\n\t\t// a qb. If it asserted for duplicate symbols, it would assert due to the\r\n\t\t// qb already being loaded.\r\n\t\tSkateScript::LoadQB(p_file_name);\r\n\t}\t\r\n\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UnloadQB | Unloads the specified QB file.\r\n// @uparm \"data\\scripts\\ken.qb\" | File name of the qb to unload\r\nbool ScriptUnloadQB(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_file_name=NULL;\r\n\tpParams->GetString(NONAME,&p_file_name);\r\n\tDbg_MsgAssert(p_file_name,(\"LoadQB requires a file name.\"));\r\n\r\n\t// Unload the QB\r\n\tuint32 qb_checksum=Crc::GenerateCRCFromString(p_file_name);\r\n\tSkateScript::UnloadQB(qb_checksum);\r\n\r\n\t// If it was the level specific qb, which is normally removed automatically\r\n\t// by ScriptCleanup above.\r\n\t// Since they removed it manually, reset s_level_specific_qb so that it is consistent.\r\n\t#if 0\t\r\n\tif (qb_checksum==s_level_specific_qb)\r\n\t{\r\n\t\ts_level_specific_qb=0;\r\n\t}\r\n\t#else\r\n\tint qb;\r\n\tfor (qb=0;qb<MAX_LEVEL_QBS;qb++)\r\n\t{\r\n\t\tif (qb_checksum == s_level_specific_qbs[qb])\r\n\t\t{\r\n\t\t\ts_level_specific_qbs[qb] = 0;\r\n\t\t}\r\n\t}\r\n\t#endif\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ToggleRenderMode | \r\nbool ScriptToggleRenderMode(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tNx::CEngine::sToggleRenderMode();\t\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n// @script | SetRenderMode | \r\nbool ScriptSetRenderMode(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\tint mode = 0;\r\n\tpParams->GetInteger(CRCD(0x6835b854,\"mode\"),&mode);\r\n\tNx::CEngine::sSetRenderMode(mode);\t\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | SetWireframeMode | \r\nbool ScriptSetWireframeMode(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint mode = 0;\r\n\tpParams->GetInteger(CRCD(0x6835b854,\"mode\"),&mode);\r\n\tNx::CEngine::sSetWireframeMode(mode);\t\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DebugRenderIgnore | \r\n// @parmopt int | ignore_1 | 0 | bitmask of face flags where we ignore this face if bit is 1\r\n// @parmopt int | ignore_0 | 0 | bitmask of face flags where we ignore this face if bit is 0\r\nbool ScriptDebugRenderIgnore(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\tint ignore_0 = 0;\t\r\n\tint ignore_1 = 0;\r\n\tpParams->GetInteger(\"ignore_1\",&ignore_1);\r\n\tpParams->GetInteger(\"ignore_0\",&ignore_0);\r\n\t\t\t\t\t\t  \r\n\tNx::CEngine::sSetDebugIgnore(ignore_1,ignore_0);\t\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetVRAMPackContext | Currently, there are 4 possible \r\n// contexts, 0 through 3, with 0 being the default. There is a script \r\n// command SetVRAMPackContext which takes a number between 0 and 3. \r\n// All packing handled by the intelligent packer will then only pack \r\n// in blocks with a matching context.\r\n// @uparmopt 0 | context number (int)\r\nbool ScriptSetVRAMPackContext(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\tint context = 0;\r\n\tpParams->GetInteger( NONAME, &context );\r\n\r\n#\tifdef __PLAT_NGPS__\r\n//\tRpSkyNXSetVRAMPackContext( (uint32)context );\r\n#\tendif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScreenShot | save a screenshot with specified filename\r\n// @parmopt string | filename | screen | place to save screenshot\r\nbool ScriptScreenShot(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *fileName;\r\n\tbool ret;\r\n\r\n\tret = pParams->GetText( \"filename\", &fileName );\r\n\tif ( !ret )\r\n\t\tfileName = \"screen\";\r\n\r\n\t Gfx::Manager * gfx_manager =  Gfx::Manager::Instance();\r\n\tgfx_manager->ScreenShot( fileName );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// @script | DumpShots | dump memory card screenshots to PC\r\nbool ScriptDumpShots(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t#ifdef\t__PLAT_NGPS__\r\n\tGfx::Manager * gfx_manager =  Gfx::Manager::Instance();\r\n\tgfx_manager->DumpMemcardScreeenshots( );\r\n\t#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IfDebugOn | returns true if debug on\r\nbool ScriptIfDebugOn(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tDbg_MsgAssert(pScript,(\"NULL pScript ?\"));\r\n\tpScript->SwitchOnIfDebugging();\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IfDebugOff | returns true if debug off\r\nbool ScriptIfDebugOff(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tDbg_MsgAssert(pScript,(\"NULL pScript ?\"));\r\n\tpScript->SwitchOffIfDebugging();\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CD | returns true if CD present\r\nbool ScriptCD(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn Config::CD();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | NotCD | returns true if CD not present\r\nbool ScriptNotCD(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn !Config::CD();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Bootstrap | returns true if this is a bootstrap demo\r\nbool ScriptBootstrap(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn Config::Bootstrap();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CasArtist | returns true if cas_artist int is set anywhere\r\nbool ScriptCasArtist(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tbool is_cas_artist = Script::GetInt( \"cas_artist\", false );\r\n\r\n\treturn is_cas_artist;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | NotCasArtist | returns true if cas_artist int is not set\r\nbool ScriptNotCasArtist(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn !ScriptCasArtist( pParams, pScript );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Gunslinger | returns true if a Gunslinger build\r\nbool ScriptGunslinger(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#\tifdef TESTING_GUNSLINGER\r\n\treturn true;\r\n#\telse\r\n\treturn false;\r\n#\tendif\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nenum\r\n{\r\n\tACTION_SET_FLAG,\r\n\tACTION_CLEAR_FLAG,\r\n\tACTION_QUERY_FLAG,\r\n\tACTION_SET_OBJECT_FLAG,    // different than the script flags.\r\n\tACTION_CLEAR_OBJECT_FLAG,  // different than the script flags.\r\n\tACTION_FLAG_EXCEPTION_BY_CHECKSUM,\r\n\tACTION_SEE_IF_OBJECT_EXISTS,\r\n};\r\n\r\nstruct SActionData\r\n{\r\n\tint Flag;\r\n\tint Action;\r\n\tbool ReturnValue;\r\n\tbool ObjectFound;\r\n};\r\n\r\nstruct SActionData_NameChecksum\r\n{\r\n\tuint32 ObjectNameChecksum;\r\n\tSActionData actionData;\r\n};\r\n\r\nstruct SActionData_NodeIndex\r\n{\r\n\tint NodeIndex;\r\n\tSActionData actionData;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void DoAction( Obj::CCompositeObject* pOb, SActionData* pData )\r\n{\r\n\tpData->ObjectFound = true;\r\n\tswitch ( pData->Action )\r\n\t{\r\n\t\tcase ( ACTION_SET_FLAG ):\r\n\t\t\tpOb->mScriptFlags |= ( 1 << pData->Flag );\r\n\t\t\tpData->ReturnValue = true;\r\n\t\t\tbreak;\r\n\t\tcase ( ACTION_CLEAR_FLAG ):\r\n\t\t\tpOb->mScriptFlags &= ~( 1 << pData->Flag );\r\n\t\t\tpData->ReturnValue = true;\r\n\t\t\tbreak;\r\n\t\tcase ( ACTION_QUERY_FLAG ):\r\n\t\t\tif ( pOb->mScriptFlags & ( 1 << pData->Flag ) )\r\n\t\t\t{\r\n\t\t\t\tpData->ReturnValue = true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( ACTION_SET_OBJECT_FLAG ):\r\n\t\t\tpOb->SetFlags(((Obj::CObject *) pOb)->GetFlags() | ( pData->Flag ));\t // Note:  Flags are passed as a bitfield\r\n\t\t\tbreak;\r\n\t\tcase ( ACTION_CLEAR_OBJECT_FLAG ):\r\n\t\t\tpOb->SetFlags(((Obj::CObject *) pOb)->GetFlags() & ~( pData->Flag ));\r\n\t\t\tbreak;\r\n\t\tcase ( ACTION_FLAG_EXCEPTION_BY_CHECKSUM ):\r\n\t\t\t{\r\n\t\t\t\tpOb->SelfEvent((pData->Flag));\r\n\t\t\t\tpData->ReturnValue = true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ( ACTION_SEE_IF_OBJECT_EXISTS ):\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0,( \"Unknown action %d\", pData->Action ));\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void Action_ByNameChecksum( Obj::CObject* pOb, void* pVoidData )\r\n{\r\n\t\r\n\tDbg_MsgAssert(pOb,(\"NULL pOb\"));\r\n\tDbg_MsgAssert(pVoidData,(\"NULL pVoidData\"));\r\n\t\r\n\tSActionData_NameChecksum *pData=(SActionData_NameChecksum*)pVoidData;\r\n\r\n\t// Mick - find objects based either on their node name (soon to go away)\r\n\t// or by their ID (which is set to the node name for composite objects)\t\r\n\tif ( pOb->GetID() == pData->ObjectNameChecksum )\r\n\t{\r\n\t\tDoAction( (Obj::CCompositeObject*)pOb, &pData->actionData );\r\n\t}\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void Action_ByNodeIndex(Obj::CObject* pOb, void* pVoidData)\r\n{\r\n\t\r\n\tDbg_MsgAssert(pOb,(\"NULL pOb\"));\r\n\tDbg_MsgAssert(pVoidData,(\"NULL pVoidData\"));\r\n\t\r\n\tSActionData_NodeIndex *pData=(SActionData_NodeIndex*)pVoidData;\r\n\r\n\tuint32\tnodeName = SkateScript::GetNodeNameChecksum(pData->NodeIndex);\r\n\t\r\n\tif (pOb->GetID() == nodeName )\r\n\t{\r\n\t\tDoAction( (Obj::CCompositeObject*)pOb, &pData->actionData );\r\n\t}\t\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ClearFlag | clears a flag \r\n// @uparm 1 | the flag to clear\r\n// @parmopt name | name | | the name of the object\r\n// @parmopt string | prefix | | prefix value\r\nbool ScriptClearFlag(Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\treturn ( ScriptDoAction( pParams, pScript, ACTION_CLEAR_FLAG ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SendFlag | Sets a specified flag in a named object. All\r\n// objects have a set of 32 flags. For example: <nl>\r\n// SendFlag 14 name =TRG_Car03 ; no quotes <nl>\r\n// This will search all the objects until it finds the one called\r\n// TRG_Car03, and will then set its flag 14. The flag value must\r\n// be between 0 and 31 inclusive. To aid readability, names should\r\n// be used for the flags, and there is a file flags.q where the\r\n// definitions should be put\r\n// @uparm 1 | the flag to set\r\n// @parmopt name | name | | the name of the object\r\n// @parmopt string | prefix | | prefix value\r\nbool ScriptSendFlag(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\treturn ( ScriptDoAction( pParams, pScript, ACTION_SET_FLAG ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | QueryFlag | you can query a flag on an object (or several\r\n// objects if using links parameter or prefix = \"Something_\" parameter\r\n// instead of name = Something_Unique). In the case of one object,\r\n// QueryFlag will return true or false depending on if the flag is set\r\n// or not. In the case of several objects, the function will return true\r\n// if any of the objects specified have that flag set, false otherwise\r\n// @uparm 1 | the flag to query\r\n// @parmopt name | name | | the name of the object\r\n// @parmopt string | prefix | | prefix value\r\nbool ScriptQueryFlag(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\treturn ( ScriptDoAction( pParams, pScript, ACTION_QUERY_FLAG ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SendException | use the SendException command in the same\r\n// way you would use the SendFlag command:  you can specify name=whatever_object\r\n// or links or prefix=\"whatever_\" (just like with SendFlag). \r\n// @uparm Exception | the flag \r\n// @parmopt name | name | | object name\r\n// @parmopt string | prefix | | prefix value\r\nbool ScriptFlagException(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\treturn ( ScriptDoAction( pParams, pScript, ACTION_FLAG_EXCEPTION_BY_CHECKSUM ) );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsAlive | Takes the same arguments as SendFlag etc... Returns\r\n// true if the object currently exists\r\n// @parm name | name | object name\r\nbool ScriptCheckIfAlive( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\r\n\treturn ( DoNodeAction( pParams, pScript, NODE_ACTION_CHECK_IF_ALIVE ) );\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void SetUpActionData( SActionData *pData, int flag, int action )\r\n{\r\n\t\r\n\tDbg_MsgAssert( pData,( \"Fire matt the idiot\" ));\r\n\tpData->Flag = flag;\r\n\tpData->Action = action;\r\n\tpData->ObjectFound = false;\r\n\tpData->ReturnValue = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Used to perform actions to nodes by prefix, name checksum, or links -- but this version\r\n// only operates on the nodes that create CMovingObjects... For the general version (applicable\r\n// to nodes that create Environmental Objects, Rails, etc... AS WELL as CMovingObjects, see\r\n// DoNodeAction( )\r\nbool ScriptDoAction(Script::CStruct *pParams, Script::CScript *pScript, int action )\r\n{\r\n\t\r\n\tint flag = 0;\r\n\tif (action == ACTION_FLAG_EXCEPTION_BY_CHECKSUM)\r\n\t{\r\n\t#ifdef __NOPT_ASSERT__\r\n\t\tbool GotFlag=\r\n\t#endif\t\r\n\t\tpParams->GetChecksum(NONAME,(uint32*)&flag);\r\n\t\tDbg_MsgAssert(GotFlag,(\"\\n%s\\nSendException  require a chechecksum name to be specified.\\n(NOT AN INTEGER)\",pScript->GetScriptInfo()));\r\n\t}\r\n\telse\r\n\t{\r\n\t#ifdef __NOPT_ASSERT__\r\n\t\tbool GotFlag=\r\n\t#endif\t\r\n\t\tpParams->GetInteger(NONAME,&flag);\r\n\t\tDbg_MsgAssert(GotFlag,(\"\\n%s\\nFlag commands require a flag to be specified.\\n(Either an integer or a name defined to be an integer)\",pScript->GetScriptInfo()));\r\n\t\tDbg_MsgAssert(flag>=0 && flag<32,(\"\\n%s\\nBad flag value of %d, value must be between 0 and 31\",pScript->GetScriptInfo(),flag));\r\n\t\r\n\t}\r\n\tuint32 nameChecksum;\r\n\tconst char *pPrefix;\r\n\tint i;\r\n\t\r\n\t\r\n\tbool useCurrentLinks = false;\r\n\tif ( pParams->ContainsFlag( 0x2e7d5ee7 ) || // checksum 'links'\r\n\t\t( useCurrentLinks = pParams->ContainsFlag( 0xbceb479a ) ) ) // checksum 'currentlinks'\r\n\t{\r\n\t\r\n\t\tDbg_MsgAssert(0,(\"\\n%s\\n'links' and 'currentlinks' are deprecated\\n\",pScript->GetScriptInfo()));\r\n\t}\r\n\t\r\n\tif ( pParams->GetChecksum( 0xa1dc81f9, &nameChecksum) )  // 'name'\r\n\t{\r\n\t\tSActionData_NameChecksum Data;\r\n\t\tData.ObjectNameChecksum = nameChecksum;\r\n\t\tSetUpActionData( &Data.actionData, flag, action );\r\n\t\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\tskate_mod->GetObjectManager()->ProcessAllObjects(Action_ByNameChecksum,&Data);\r\n\t\tDbg_MsgAssert( Data.actionData.ObjectFound,( \"\\n%s\\nDidn't find object specified '%s'.\", pScript->GetScriptInfo( ), Script::FindChecksumName( nameChecksum ) ) );\r\n\t\treturn ( Data.actionData.ReturnValue );\r\n\t}\r\n    if ( pParams->GetText( 0x6c4e7971, &pPrefix ) ) // checksum 'prefix'\r\n\t{\r\n\t\t// Create with a prefix specified:\r\n\t\tuint16 numNodes = 0;\r\n\t\tconst uint16 *pMatchingNodes = SkateScript::GetPrefixedNodes( pPrefix, &numNodes );\r\n\t\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\tSActionData_NodeIndex Data;\r\n\t\tSetUpActionData( &Data.actionData, flag, action );\r\n\t\tfor ( i = 0; i < numNodes; i++ )\r\n\t\t{\r\n\t\t\tData.NodeIndex = pMatchingNodes[ i ];\r\n\t\t\tskate_mod->GetObjectManager()->ProcessAllObjects(Action_ByNodeIndex,&Data);\r\n\t\t}\r\n\t\tDbg_MsgAssert( Data.actionData.ObjectFound,( \"\\n%s\\nDidn't find any objects with prefix %s.\", pScript->GetScriptInfo( ), pPrefix ));\r\n\t\treturn ( Data.actionData.ReturnValue );\r\n\t}\r\n#if 0  // put in if ever necessary:\r\n\t// set the flag on ourself:\r\n\tif ( pScript->mpObject )\r\n\t{\r\n\t\tswitch ( action )\r\n\t\t{\r\n\t\t\tcase ( ACTION_SET_FLAG ):\r\n\t\t\t\tpScript->mpObject->mScriptFlags |= ( 1 << flag );\r\n\t\t\t\treturn ( true );\r\n\t\t\tcase ( ACTION_CLEAR_FLAG ):\r\n                pScript->mpObject->mScriptFlags &= ~( 1 << flag );\r\n\t\t\t\treturn ( true );\r\n\t\t\tcase ( ACTION_QUERY_FLAG ):\r\n\t\t\t\treturn ( pScript->mpObject->mScriptFlags & ( 1 << flag );\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert( 0,( \"Unknown flag action %d\", action ));\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"\\n%s\\nNeed to specify an object, or call this command on a script associated with an object.\", pScript->GetScriptInfo( ) ));\r\n\t}\r\n#endif\r\n\tDbg_MsgAssert( 0,( \"\\n%s\\nMust specify a name, links, or prefix please.\", pScript->GetScriptInfo( ) ));\r\n\treturn ( false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptSetVisibilityFromNodeIndex( int nodeIndex, bool invisible, int viewport_number )\r\n{\t\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n\tScript::CArray *pNodeArray = Script::GetArray( CRCD(0xc472ecc5,\"NodeArray\") );\r\n\tDbg_MsgAssert( pNodeArray,( \"No NodeArray found\" ));\r\n\r\n\tScript::CStruct *pNode=pNodeArray->GetStructure( nodeIndex );\r\n\tDbg_MsgAssert( pNode,( \"NULL pNode\" ));\r\n\r\n\t// If this is a net game, don't show/hide objects that were meant to be left out for \r\n\t// performance/bandwidth/gameplay reasons\r\n\tif ( skate_mod->ShouldBeAbsentNode( pNode ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tuint32 ClassChecksum = 0;\r\n\tpNode->GetChecksum( 0x12b4e660 /*\"Class\"*/, &ClassChecksum );\r\n\t\r\n\tswitch (ClassChecksum)\r\n\t{\r\n\t\tcase 0xe47f1b79: // vehicle\r\n\t\tcase 0xa0dfac98: // pedestrian\r\n\t\tcase 0x61a741e:  // ped\r\n\t\tcase 0xef59c100: // gameobject\r\n\t\tcase 0x5b8ab877: // skater\r\n\t\tcase 0x19b1e241: // ParticleEmitter\t  \r\n\t\tcase 0x9e7d469e: // ParticleObject  \r\n\t\t{\r\n\t\t\tSActionData_NodeIndex Data;\r\n\t\t\tData.NodeIndex = nodeIndex;\r\n\t\t\tif ( invisible )\r\n\t\t\t{\r\n\t\t\t\tSetUpActionData( &Data.actionData, Obj::CMovingObject::vINVISIBLE, ACTION_SET_OBJECT_FLAG );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tSetUpActionData( &Data.actionData, Obj::CMovingObject::vINVISIBLE, ACTION_CLEAR_OBJECT_FLAG );\r\n\t\t\t}\r\n\t\t\tData.NodeIndex = nodeIndex;\r\n\t\t\tskate_mod->GetObjectManager()->ProcessAllObjects(Action_ByNodeIndex,&Data);\r\n\t\t\tif ( !Data.actionData.ObjectFound )\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"Vis/Invis:  Object from node %d not found.\", nodeIndex );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0xb7b3bd86:  // LevelObject\r\n\t\tcase 0xbf4d3536:  // LevelGeometry\r\n\t\t{\r\n\t\t\tuint32 checksumName = 0;\r\n\t\t\t//Dbg_MsgAssert( ( \"No world in viewer module...\" ));\r\n\t\t\t\r\n\t\t\tif ( pNode->GetChecksum( 0xa1dc81f9, &checksumName ) ) // checksum 'name'\r\n\t\t\t{\r\n//\t\t\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(checksumName);\r\n\t\t\t\t// We only want to get sectors from the main scene, as that is what the node array applies to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\tNx::CScene * p_main_scene = Nx::CEngine::sGetMainScene();\r\n\t\t\t\tNx::CSector *p_sector = p_main_scene->GetSector(checksumName);\r\n\t\t\t\tDbg_MsgAssert(p_sector,(\"sGetSector(0x%x) returned NULL (%s)\",checksumName,Script::FindChecksumName(checksumName)));\r\n\r\n\t\t\t\tuint32 orig_flag = p_sector->GetVisibility();\r\n\t\t\t\tuint32 flag = 0x1; \r\n\t\t\t\tif (viewport_number == 1)\r\n\t\t\t\t{\r\n\t\t\t\t\tflag = 0x2; \r\n\t\t\t\t}\r\n\t\t\t\tif ( invisible )\r\n\t\t\t\t{\r\n\t\t\t\t\tp_sector->SetVisibility(orig_flag & ~flag);\t\t// clear flags\r\n\t\t\t\t\t//Bsp::SetWorldSectorFlag(  checksumName, flag );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_sector->SetVisibility(orig_flag | flag);\t\t// set flags\r\n\t\t\t\t\t//Bsp::ClearWorldSectorFlag(  checksumName, flag );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n \t\t}\r\n\r\n//\t\tcase 0xe594f0a2:  // Trigger (geometry containing triggers...)\r\n\t\tcase 0x8e6b02ad:  // railnode\r\n\t\tcase CRCC(0x30c19600, \"ClimbingNode\"):\r\n\t\tdefault:\r\n\t\t\treturn ( false );\r\n\t\t\tbreak;\r\n\t}\r\n\treturn ( true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptCheckExistenceFromNodeIndex( int nodeIndex )\r\n{\t\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n\tScript::CArray *pNodeArray = Script::GetArray( CRCD(0xc472ecc5,\"NodeArray\") );\r\n\tDbg_MsgAssert( pNodeArray,( \"No NodeArray found\" ));\r\n\r\n\tScript::CStruct *pNode=pNodeArray->GetStructure( nodeIndex );\r\n\tDbg_MsgAssert( pNode,( \"NULL pNode\" ));\r\n\r\n\tuint32 ClassChecksum = 0;\r\n\tpNode->GetChecksum( 0x12b4e660 /*\"Class\"*/, &ClassChecksum );\r\n\t\r\n\tswitch (ClassChecksum)\r\n\t{\r\n\t\tcase 0xe47f1b79: // vehicle\r\n\t\tcase 0xa0dfac98: // pedestrian\r\n\t\tcase 0x61a741e:  // ped\r\n\t\tcase 0xef59c100: // gameobject\r\n\t\tcase 0x5b8ab877: // skater\r\n\t\tcase 0xb7b3bd86: // LevelObject\r\n\t\tcase 0x19b1e241: // ParticleEmitter\r\n\t\tcase 0x9e7d469e: // ParticleObject\r\n\t\t\r\n\t\t{\r\n\t\t\tSActionData_NodeIndex Data;\r\n\t\t\tData.NodeIndex = nodeIndex;\r\n\t\t\tSetUpActionData( &Data.actionData, 0, ACTION_SEE_IF_OBJECT_EXISTS );\r\n\t\t\tData.NodeIndex = nodeIndex;\r\n\t\t\tskate_mod->GetObjectManager()->ProcessAllObjects(Action_ByNodeIndex,&Data);\r\n\t\t\tif ( !Data.actionData.ObjectFound )\r\n\t\t\t{\r\n\t\t\t\treturn ( false );\r\n\t\t\t}\r\n\t\t\treturn ( true );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0xbf4d3536:  // LevelGeometry\r\n\t\t{\r\n\t\t\tuint32 checksumName = 0;\r\n\t\t\t//Dbg_MsgAssert( ( \"No world in viewer module...\" ));\r\n\t\t\tif ( pNode->GetChecksum( 0xa1dc81f9, &checksumName ) ) // checksum 'name'\r\n\t\t\t{\r\n//\t\t\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(checksumName);\t\t\t\t\r\n\t\t\t\t// We only want to get sectors from the main scene, as that is what the node array applies to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\tNx::CScene * p_main_scene = Nx::CEngine::sGetMainScene();\r\n\t\t\t\tNx::CSector *p_sector = p_main_scene->GetSector(checksumName);\r\n\t\t\t\tDbg_MsgAssert(p_sector,(\"sGetSector(0x%x) returned NULL (%s)\",checksumName,Script::FindChecksumName(checksumName)));\r\n\t\t\t\treturn (p_sector->IsActive());\r\n\t\t\t\t//return ( Bsp::WorldSectorIsAlive( checksumName ) );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n \t\t}\r\n\r\n\t\tcase 0xe594f0a2:  // Trigger (geometry containing triggers...)\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase CRCC(0x30c19600, \"ClimbingNode\"):\r\n\t\tcase 0x8e6b02ad:  // railnode\r\n\t\t\treturn ( skate_mod->GetRailManager()->IsActive( nodeIndex ) );\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn ( false );\r\n\t\t\tbreak;\r\n\t}\r\n\treturn ( true );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptSetColorFromNodeIndex( int nodeIndex, Script::CStruct *pParams )\r\n{\t\r\n\r\n\tuint32 color = 0x808080;\r\n\t\r\n\tpParams->GetInteger( CRCD(0x99a9b716,\"color\"), (int*)&color, TRUE );\r\n\t\r\n\tImage::RGBA rgb;\r\n\trgb.r = (uint8)((color)&0xff);\r\n\trgb.g = (uint8)((color>>8)&0xff);\r\n\trgb.b = (uint8)((color>>16)&0xff);\r\n\trgb.a = 0x80;\r\n\r\n\tScript::CArray *pNodeArray = Script::GetArray( CRCD(0xc472ecc5,\"NodeArray\") );\r\n\tDbg_MsgAssert( pNodeArray,( \"No NodeArray found\" ));\r\n\r\n\tScript::CStruct *pNode=pNodeArray->GetStructure( nodeIndex );\r\n\tDbg_MsgAssert( pNode,( \"NULL pNode\" ));\r\n\r\n\tuint32 ClassChecksum = 0;\r\n\tpNode->GetChecksum( 0x12b4e660 /*\"Class\"*/, &ClassChecksum );\r\n\t\r\n\tswitch (ClassChecksum)\r\n\t{\r\n\t\tcase 0xbf4d3536:  // LevelGeometry\r\n\t\t{\r\n\t\t\tuint32 checksumName = 0;\r\n\t\t\t//Dbg_MsgAssert( ( \"No world in viewer module...\" ));\r\n\t\t\tif ( pNode->GetChecksum( 0xa1dc81f9, &checksumName ) ) // checksum 'name'\r\n\t\t\t{\r\n\t\t\t\tNx::CScene * p_main_scene = Nx::CEngine::sGetMainScene();\r\n\t\t\t\tNx::CSector *p_sector = p_main_scene->GetSector(checksumName);\r\n\t\t\t\tDbg_MsgAssert(p_sector,(\"sGetSector(0x%x) returned NULL (%s)\",checksumName,Script::FindChecksumName(checksumName)));\r\n\t\t\t\tp_sector->SetColor(rgb);\r\n\t\t\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n \t\t}\r\n\t\tdefault:\r\n\t\t\treturn ( false );\r\n\t\t\tbreak;\r\n\t}\r\n\treturn ( true );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptShatterFromNodeIndex( int nodeIndex )\r\n{\r\n\t\r\n\t\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n// Mick:  If pre-running scripts in a net game, we might shatter a lot of glass\r\n// which might run out of memory\r\n// so don't actually shatter the sector if that's what we are doing\r\n\r\n\tif( skate_mod->LaunchingQueuedScripts())\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tScript::CArray *pNodeArray = Script::GetArray( CRCD(0xc472ecc5,\"NodeArray\") );\r\n\tDbg_MsgAssert( pNodeArray,( \"No NodeArray found\" ));\r\n\r\n\tScript::CStruct *pNode=pNodeArray->GetStructure( nodeIndex );\r\n\tDbg_MsgAssert( pNode,( \"NULL pNode\" ));\r\n\r\n\t// If this is a net game, don't show/hide objects that were meant to be left out for \r\n\t// performance/bandwidth/gameplay reasons\r\n\tif ( skate_mod->ShouldBeAbsentNode( pNode ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tuint32 ClassChecksum = 0;\r\n\tpNode->GetChecksum( 0x12b4e660 /*\"Class\"*/, &ClassChecksum );\r\n\r\n\tswitch( ClassChecksum )\r\n\t{\r\n\t\tcase 0xb7b3bd86:  // LevelObject\r\n\t\tcase 0xbf4d3536:  // LevelGeometry\r\n\t\t{\r\n\t\t\t//Dbg_MsgAssert( p_world,( \"No world in viewer module...\" ));\r\n\r\n\t\t\tuint32 checksumName = 0;\r\n\t\t\tif( pNode->GetChecksum( 0xa1dc81f9, &checksumName )) // checksum 'name'\r\n\t\t\t{\r\n//\t\t\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(checksumName);\t\t\t\t\r\n\t\t\t\t// We only want to get sectors from the main scene, as that is what the node array applies to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\tNx::CScene * p_main_scene = Nx::CEngine::sGetMainScene();\r\n\t\t\t\tNx::CSector *p_sector = p_main_scene->GetSector(checksumName);\r\n\t\t\t\tDbg_MsgAssert(p_sector,(\"sGetSector(0x%x) returned NULL (%s)\",checksumName,Script::FindChecksumName(checksumName)));\r\n\t\t\t\tp_sector->SetShatter(true);\r\n\t\t\t\t//Bsp::ShatterWorldSector(  checksumName );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n \t\t}\r\n\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MakeSkaterGoto |\r\n// This will cause the main skater script to jump to the\r\n// specified script. So a script triggered from a trigger poly\r\n// can use this to force the main skater script to jump to a script.\r\n// It will choose the skater that triggered the poly in that case. <nl>\r\n// <nl>\r\n// A script not associated with an object can also use this, in which\r\n// case it will set the script of skater 0. <nl>\r\n// <nl>\r\n// The main skater script itself could also use it, but there would be\r\n// no point since it can use Goto. <nl>\r\n// <nl>\r\n// This should be used with care, since making the skater jump to a\r\n// script when he's in the middle of doing something could confuse him.\r\n// Eg, forcing him to jump to OnGroundAI when he's on a rail will make\r\n// an assert go off.\r\n// @uparm name | Script name\r\n// @parmopt structure | params | | parameters to be passed to new script\r\nbool ScriptMakeSkaterGoto(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\t\r\n\tScript::CStruct *pParamsToPass=NULL;\r\n\tpParams->GetStructure(CRCD(0x7031f10c,\"Params\"),&pParamsToPass);\r\n\t\r\n\tuint32 ScriptChecksum=0;\r\n\tpParams->GetChecksum(NONAME,&ScriptChecksum);\r\n\tDbg_MsgAssert(ScriptChecksum,(\"\\n%s\\nMakeSkaterGoto requires a script name, eg MakeSkaterGoto Blaa\",pScript->GetScriptInfo()));\r\n\r\n\tObj::CSkater *pSkater=NULL;\r\n\tif (pScript && pScript->mpObject && pScript->mpObject->GetType()==SKATE_TYPE_SKATER)\t\r\n\t{\r\n\t\t// If the script using this has an object associated with it, and that object\r\n\t\t// is a skater, then use that skater.\r\n\t\t// This will happen in the case of a trigger script using this command.\r\n\t\tpSkater=(Obj::CSkater*)pScript->mpObject.Convert();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\tint Skater=0;\r\n\t\tif( pParams->GetInteger(\"Skater\",&Skater))\r\n\t\t{\r\n\t\t\tpSkater = skate_mod->GetSkater(Skater);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpSkater = skate_mod->GetLocalSkater();\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tif (pSkater && pSkater->IsLocalClient())\r\n\t{\r\n\t\tpSkater->JumpToScript(ScriptChecksum,pParamsToPass);\r\n\t}\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MakeSkaterGotoSub | interrupts whatever script the skater is doing,\r\n// calls new script, and then returns to the original script.\r\n// @uparm name | script to goto\r\n// @parmopt structure | Params | | parameters to pass to new script\r\n// @parmopt int | Skater | | \r\nbool ScriptMakeSkaterGosub(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tScript::CStruct *pParamsToPass=NULL;\r\n\tpParams->GetStructure(CRCD(0x7031f10c,\"Params\"),&pParamsToPass);\r\n\t\r\n\tuint32 ScriptChecksum=0;\r\n\tpParams->GetChecksum(NONAME,&ScriptChecksum);\r\n\tDbg_MsgAssert(ScriptChecksum,(\"\\n%s\\nMakeSkaterGosub requires a script name, eg MakeSkaterGosub Blaa\",pScript->GetScriptInfo()));\r\n\r\n\tObj::CSkater *pSkater=NULL;\r\n\tif (pScript && pScript->mpObject && pScript->mpObject->GetType()==SKATE_TYPE_SKATER)\t\r\n\t{\r\n\t\t// If the script using this has an object associated with it, and that object\r\n\t\t// is a skater, then use that skater.\r\n\t\t// This will happen in the case of a trigger script using this command.\r\n\t\tpSkater=(Obj::CSkater*)pScript->mpObject.Convert();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\tint Skater=0;\r\n\t\tpParams->GetInteger(\"Skater\",&Skater);\r\n\t\tpSkater = skate_mod->GetSkater(Skater);\t\t\t\t\t\t   \r\n\t}\r\n\t\t\r\n\tif (pSkater)\r\n\t{\r\n\t\tpSkater->CallScript(ScriptChecksum,pParamsToPass);\r\n\t}\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SpawnScript | This will create & run a new script which will\r\n// run -in parallel- until it finishes, when it will die. The new script\r\n// is not associated with any object. The calling script is not affected\r\n// in any way. A typical use of a spawned script would be to play a sound,\r\n// pause, play another sound, etc, for example when an object dies. This\r\n// way the object itself can die straight away\r\n// @uparm name | the name of the script to spawn\r\n// @parmopt structure | Params | | Parameter structure to pass to new script\r\n// @parmopt name | Id | | an id to assign to the spawned script, so it can \r\n// be killed by KillSpawnedScript\r\n// @flag NotSessionSpecific | This will cause the script to not get deleted when the current\r\n// level (session) ends.\r\nbool ScriptSpawnScript(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 ScriptChecksum=0;\r\n\tpParams->GetChecksum(NONAME,&ScriptChecksum);\r\n\tDbg_MsgAssert(ScriptChecksum,(\"\\n%s\\nMissing script name in SpawnScript command.\",pScript->GetScriptInfo()));\r\n\tbool net_enabled, permanent;\r\n\tScript::CStruct *pScriptParams=NULL;\r\n\tpParams->GetStructure(CRCD(0x7031f10c,\"Params\"),&pScriptParams);\r\n\t\r\n\t// The spawned script can optionally be given an Id, so that it can be deleted\r\n\t// by KillSpawnedScript.\r\n\tuint32 Id=0;\r\n\tpParams->GetChecksum(\"Id\",&Id);\r\n\r\n\tuint32 CallbackScript=0;\r\n\tpParams->GetChecksum(\"Callback\",&CallbackScript);\r\n\tScript::CStruct *pCallbackParams=NULL;\r\n\tpParams->GetStructure(\"CallbackParams\",&pCallbackParams);\r\n\t\t\r\n\t//net_enabled = 0;\r\n\t//permanent = 0;\r\n\t//pParams->GetInteger( \"NetEnabled\", &net_enabled );\r\n\t//pParams->GetInteger( \"Permanent\", &permanent );\r\n\tnet_enabled = pParams->ContainsFlag( \"NetEnabled\" );\r\n\tpermanent = pParams->ContainsFlag( \"Permanent\" );\r\n\t\r\n\tint not_session_specific=0;\r\n\tpParams->GetInteger( \"NotSessionSpecific\", &not_session_specific);\r\n\t\r\n\t// copy the parent's node\r\n\t#ifdef __NOPT_ASSERT__\r\n\tScript::CScript *p_script=Script::SpawnScript(ScriptChecksum,pScriptParams,CallbackScript,pCallbackParams,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tpScript->mNode,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tId,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tnet_enabled,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tpermanent,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tnot_session_specific); \t\r\n\tp_script->SetCommentString(\"Spawned by script command SpawnScript\");\r\n\tp_script->SetOriginatingScriptInfo(pScript->GetCurrentLineNumber(),pScript->mScriptChecksum);\r\n\t#else\r\n\tScript::SpawnScript(ScriptChecksum,pScriptParams,CallbackScript,pCallbackParams,\r\n\t\t\t\t\t\tpScript->mNode,\r\n\t\t\t\t\t\tId,\r\n\t\t\t\t\t\tnet_enabled,\r\n\t\t\t\t\t\tpermanent,\r\n\t\t\t\t\t\tnot_session_specific); \t\r\n\t#endif\t\r\n\treturn true;\r\n}\t\r\n\r\n\r\n\t\t\t\r\n// @script | SpawnSound | This will create & run a new script which will\r\n// run -in parallel- until it finishes, when it will die. The new script\r\n// is not associated with any object. The calling script is not affected\r\n// in any way. A typical use of a spawned script would be to play a sound,\r\n// pause, play another sound, etc, for example when an object dies. This\r\n// way the object itself can die straight away\r\n//\r\n// Note, this is the same as SpawnScript, except if the current script is\r\n// attached to an object, then we do the same as Obj_SpawnScript\r\n// So we get attached to the object\r\n//\r\n// @uparm name | the name of the script to spawn\r\n// @parmopt structure | Params | | Parameter structure to pass to new script\r\n// @parmopt name | Id | | an id to assign to the spawned script, so it can \r\n// be killed by KillSpawnedScript\r\nbool ScriptSpawnSound(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tif (pScript->mpObject)\r\n\t{\r\n\t\tuint32 scriptChecksum;\r\n\t\tif ( pParams->GetChecksum( NONAME, &scriptChecksum ) )\r\n\t\t{\r\n\t\t\t// The spawned script can optionally be given an Id, so that it can be deleted\r\n\t\t\t// by KillSpawnedScript.\r\n\t\t\tuint32 Id=0;\r\n\t\t\t// keep the same ID as the parent if not specified...\r\n\t\t\tId = Script::FindSpawnedScriptID(pScript);\r\n\t\t\tpParams->GetChecksum(\"Id\",&Id);\r\n\t\t\tScript::CScriptStructure *pScriptParams = NULL;\r\n\t\t\tpParams->GetStructure( \"Params\", &pScriptParams );\r\n\t\t\t#ifdef __NOPT_ASSERT__\t\r\n\t\t\tScript::CScript *p_script=pScript->mpObject->SpawnScriptPlease( scriptChecksum, pScriptParams, Id );\r\n\t\t\tp_script->SetCommentString(\"Created by SpawnSound\");\r\n\t\t\tp_script->SetOriginatingScriptInfo(pScript->GetCurrentLineNumber(),pScript->mScriptChecksum);\r\n\t\t\t#else\r\n\t\t\tpScript->mpObject->SpawnScriptPlease( scriptChecksum, pScriptParams, Id );\r\n\t\t\t#endif\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn ScriptSpawnScript(pParams,pScript);\t\t\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SpawnSkaterScript | This will create & run a new script\r\n// on the skater which will run in parallel until it finishes, when it\r\n// will die. The calling script is not affected in any way. \r\n// @uparm name | the name of the script to call\r\n// @parmopt structure | Params | | parameter list to pass to new script\r\n// @parmopt name | Id | | an id to assign to the new script so it can \r\n// be killed by KillSpawnedScript\r\nbool ScriptSpawnSkaterScript(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\t// Mostly the same as the code for ScriptSpawnScript\r\n\tuint32 ScriptChecksum=0;\r\n\tpParams->GetChecksum(NONAME,&ScriptChecksum);\r\n\tDbg_MsgAssert(ScriptChecksum,(\"\\n%s\\nMissing script name in SpawnSkaterScript command.\",pScript->GetScriptInfo()));\r\n\t\r\n\tScript::CStruct *pScriptParams=NULL;\r\n\tpParams->GetStructure(CRCD(0x7031f10c,\"Params\"),&pScriptParams);\r\n\t\r\n\t// The spawned script can optionally be given an Id, so that it can be deleted\r\n\t// by KillSpawnedScript.\r\n\tuint32 Id=0;\r\n\tpParams->GetChecksum(\"Id\",&Id);\r\n\r\n\tuint32 CallbackScript=0;\r\n\tpParams->GetChecksum(\"Callback\",&CallbackScript);\r\n\tScript::CStruct *pCallbackParams=NULL;\r\n\tpParams->GetStructure(\"CallbackParams\",&pCallbackParams);\r\n\t\r\n\tScript::CScript *pNewScript=Script::SpawnScript(ScriptChecksum,pScriptParams,CallbackScript,pCallbackParams,pScript->mNode,Id); \t// copy the parent's node\r\n\t#ifdef __NOPT_ASSERT__\r\n\tpNewScript->SetCommentString(\"Spawned by script command SpawnSkaterScript\");\r\n\tpNewScript->SetOriginatingScriptInfo(pScript->GetCurrentLineNumber(),pScript->mScriptChecksum);\r\n\t#endif\t\r\n\t\r\n\t// Now set the object pointer to be the skater.\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tObj::CSkater *pSkater = skate_mod->GetLocalSkater();\t\t\t\t\t\t   \r\n\t\r\n\tpNewScript->mpObject=pSkater;\r\n\t\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | KillSpawnedScript | can be passed a script name or an id\r\n// @parmopt name | Name | | the name of the script\r\n// @parmopt name | Id | | the id of the script\r\nbool ScriptKillSpawnedScript(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tuint32 ScriptChecksum=0;\r\n\tif (pParams->GetChecksum(\"Name\",&ScriptChecksum))\r\n\t{\r\n\t\t// Got a script name, so kill all spawned scripts that ran that script.\r\n\t\tScript::KillSpawnedScriptsThatReferTo(ScriptChecksum);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tuint32 Id=0;\t\t\t\t\t\t\t\t\t\t   \r\n\tif (pParams->GetChecksum(\"Id\",&Id))\r\n\t{\r\n\t\t// They specified an Id, so kill all spawned scripts with this Id.\r\n\t\tScript::KillSpawnedScriptsWithId(Id);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PauseSkaters | This will cause all skaters to freeze.\r\n// They will continue where they left off when UnPauseSkaters is called. \r\n// Note that this command will not pause any spawned scripts associated\r\n// with the skaters, because otherwise it will pause the camera animation\r\n// script too, which is where the command will probably be used most\r\nbool ScriptPauseSkaters( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tReplay::WritePauseSkater();\r\n\t\r\n\tbool hide = pParams->ContainsFlag(\"hide\");\t\r\n\t\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tuint32 NumSkaters=skate_mod->GetNumSkaters();\r\n\tfor (uint32 i=0; i<NumSkaters; ++i)\r\n\t{\r\n\t\tObj::CSkater *pSkater = skate_mod->GetSkater(i);\r\n\t\tif (pSkater && pSkater->IsLocalClient()) // Hmm, assert instead?\r\n\t\t{\r\n\t\t\tpSkater->Pause();\r\n\t\t\tpSkater->Hide(hide);\r\n\t\t}\t\r\n\t}\t\r\n\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UnPauseSkaters | opposite effect of PauseSkaters\r\nbool ScriptUnPauseSkaters( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tReplay::WriteUnPauseSkater();\r\n\t\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tuint32 NumSkaters=skate_mod->GetNumSkaters();\r\n\tfor (uint32 i=0; i<NumSkaters; ++i)\r\n\t{\r\n\t\tObj::CSkater *pSkater = skate_mod->GetSkater(i);\r\n\t\tif (pSkater)\r\n\t\t{\r\n\t\t\tpSkater->UnPause();\r\n\t\t\tpSkater->Hide(false);\r\n\t\t}\t\r\n\t}\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PauseSkater | this pauses an individual skater\r\n// @uparm 0 | skater id\r\nbool ScriptPauseSkater( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tbool hide = pParams->ContainsFlag(\"hide\");\t\r\n\r\n\tint skater_id;\r\n\tpParams->GetInteger( NONAME, &skater_id, true );\r\n\t\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tObj::CSkater *pSkater = skate_mod->GetSkater(skater_id);\r\n\tif (pSkater)\r\n\t{\r\n\t\tpSkater->Pause();\r\n\t\tpSkater->Hide(hide);\r\n\t}\t\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UnPauseSkater | Unpauses an individual skater\r\n// @uparm 0 | skater id\r\nbool ScriptUnPauseSkater( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\r\n\tint skater_id;\r\n\tpParams->GetInteger( NONAME, &skater_id, true );\r\n\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tObj::CSkater *pSkater = skate_mod->GetSkater(skater_id);\r\n\tif (pSkater)\r\n\t{\r\n\t\tpSkater->UnPause();\r\n\t\tpSkater->Hide(false);\r\n\t}\t\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PauseGame | Similar to \"PauseSkaters\", it will pause\r\n// the skaters, and everything else in the world, yet still allow\r\n// you to launch messages and spawn new scripts\r\nbool ScriptPauseGame( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t Mdl::FrontEnd * front =  Mdl::FrontEnd::Instance();\r\n\tfront->PauseGame(true);\r\n\t// if the script was a spawned script\r\n\t// then we want to unpause it, so we can keep running after the game has paused\r\n\tScript::UnpauseSpawnedScript(pScript);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UnPauseGame | \r\nbool ScriptUnPauseGame( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t Mdl::FrontEnd * front =  Mdl::FrontEnd::Instance();\r\n\tfront->PauseGame(false);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsGamePaused | \r\nbool ScriptIsGamePaused( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t Mdl::FrontEnd * front =  Mdl::FrontEnd::Instance();\r\n\tif( front->GamePaused() )\r\n    {\r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PauseObjects |\r\nbool ScriptPauseObjects(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// Pause all composite objects\r\n\tObj::CCompositeObjectManager::Instance()->Pause(true);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UnpauseObjects |\r\nbool ScriptUnPauseObjects(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// Unpause all composite objects\r\n\tObj::CCompositeObjectManager::Instance()->Pause(false);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PauseSpawnedScripts |\r\nbool ScriptPauseSpawnedScripts(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tScript::PauseSpawnedScripts(true);\t\t\r\n\r\n\tif ( pScript->mIsSpawned )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Can't pause spawned scripts from a spawned script\" ) );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UnPauseSpawnedScripts |\r\nbool ScriptUnPauseSpawnedScripts(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tScript::PauseSpawnedScripts(false);\t\t\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetClock | \r\nbool ScriptResetClock( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tint time_limit;\r\n\r\n\t// Clients instead get their time limit from the server\r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\ttime_limit = skate_mod->GetGameMode()->GetTimeLimit();\r\n\t\tskate_mod->SetTimeLimit( time_limit );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PadsPluggedIn | Returns true if at least one pad is plugged in.\r\nbool ScriptPadsPluggedIn( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t Mdl::FrontEnd * p_front =  Mdl::FrontEnd::Instance();\r\n\t return p_front->PadsPluggedIn();\r\n}\t \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DoFlash | Doflash just draws a big poly over the viewport\r\n// and then modulates the color and alpha of that poly over time. There\r\n// is no support for Blendmodes yet. If you are doing a player specific \r\n// flash remember to call it from a skater script so that it works in 2\r\n// player splitscreen\r\n// @parmopt float | duration | 0.0 | \r\n// @parmopt string | texture | | texture name\r\n// @parmopt float | z | 0.0 | z\r\n// @flag fullscreen |\r\n// @flag behind_panel |\r\n// @flag additive |\r\n// @flag subtractive |\r\n// @parmopt int | skater | | for specifying skater when not in skater script\r\n// @flag ignore_pause |\r\n// @parm int | start_r | start red index\r\n// @parm int | start_g | start green index\r\n// @parm int | start_b | start blue index\r\n// @parm int | start_a | start alpha value\r\n// @parm int | end_r | end red index\r\n// @parm int | end_g | end green index\r\n// @parm int | end_b | end blue index\r\n// @parm int | end_a | end alpha value\r\nbool ScriptDoFlash( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\r\n\tfloat\t\tduration\t\t= 0.0f;\r\n\tfloat\t\tz\t\t\t\t= 0.0f;\r\n\tuint32\t\tflags\t\t\t= 0;\r\n\tbool\t\tfullscreen\t\t= false;\r\n\tint\t\t\tskater_num\t\t= -1;\r\n\tconst char*\tp_texture_name\t= NULL;\r\n\r\n\tpParams->GetFloat( \"duration\", &duration );\r\n\t\r\n\tif( duration > 0.0f )\r\n\t{\r\n\t\tpParams->GetText( \"texture\", &p_texture_name );\r\n\r\n\t\tpParams->GetFloat( \"z\", &z );\r\n\r\n//\t\tif( pParams->ContainsFlag( 0xdf6436d2 /*\"fullscreen\"*/ ))\r\n//\t\t{\r\n//\t\t\tflags |= Flash::FLAG_FULLSCREEN;\r\n//\t\t\tfullscreen = true;\r\n//\t\t}\t\r\n\t\tif( pParams->ContainsFlag( 0x70ffc649 /*\"behind_panel\"*/ ))\r\n\t\t{\r\n\t\t\tflags |= Nx::SCREEN_FLASH_FLAG_BEHIND_PANEL;\r\n\t\t}\t\r\n\t\tif( pParams->ContainsFlag( 0x19c43cf6 /*\"additive\"*/ ))\r\n\t\t{\r\n\t\t\tflags |= Nx::SCREEN_FLASH_FLAG_ADDITIVE;\r\n\t\t}\t\r\n\t\telse if( pParams->ContainsFlag( 0x387c9ed6 /*\"subtractive\"*/ ))\r\n\t\t{\r\n\t\t\tflags |= Nx::SCREEN_FLASH_FLAG_SUBTRACTIVE;\r\n\t\t}\t\r\n\r\n\t\tif( !fullscreen )\r\n\t\t{\r\n\t\t\tpParams->GetInteger( \"skater\", &skater_num );\r\n\t\t\tif( skater_num == -1 )\r\n\t\t\t{\r\n\t\t\t\t// No skater parameter provided, so assume running from a skater script.\r\n\t\t\t\tObj::CSkater* p_skater = static_cast <Obj::CSkater*>( pScript->mpObject.Convert() );\r\n\t\t\t\tDbg_Assert( p_skater );\r\n\t\t\t\tskater_num = p_skater->GetSkaterNumber();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( pParams->ContainsFlag( 0xdf6436d2 /*\"ignore_pause\"*/ ))\r\n\t\t{\r\n\t\t\tflags |= Nx::SCREEN_FLASH_FLAG_IGNORE_PAUSE;\r\n\t\t}\t\r\n\r\n\t\tint val = 0;\r\n\t\tImage::RGBA from, to;\r\n\r\n\t\tpParams->GetInteger( \"start_r\",\t&val );\r\n\t\tfrom.r = val;\r\n\t\tpParams->GetInteger( \"start_g\",\t&val );\r\n\t\tfrom.g = val;\r\n\t\tpParams->GetInteger( \"start_b\",\t&val );\r\n\t\tfrom.b = val;\r\n\t\tpParams->GetInteger( \"start_a\",\t&val );\r\n\t\tfrom.a = val;\r\n\r\n\t\tpParams->GetInteger( \"end_r\",\t&val );\r\n\t\tto.r = val;\r\n\t\tpParams->GetInteger( \"end_g\",\t&val );\r\n\t\tto.g = val;\r\n\t\tpParams->GetInteger( \"end_b\",\t&val );\r\n\t\tto.b = val;\r\n\t\tpParams->GetInteger( \"end_a\",\t&val );\r\n\t\tto.a = val;\r\n\r\n\t\tif( fullscreen )\r\n\t\t{\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tNx::AddScreenFlash( skater_num, from, to, duration, z, flags, p_texture_name );\r\n\r\n\t\t\t// Get the panel for player.\r\n\t\t\t//HUD::PanelMgr* panel_mgr = HUD::PanelMgr::Instance();\r\n\t\t\t//HUD::Panel* p_panel = panel_mgr->GetPanelBySkaterId( skater_num );\r\n\t\t\t//p_panel->AddFlash( from, to, duration, z, flags, p_texture_name );\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StartServer | Starts a server using the IP stored in\r\n// the script variable LocalIP, which you also have to define. You\r\n// can also define a script variable called ServerName to name your\r\n// server (i.e. ServerName = MyServer with a max of 15 characters\r\nbool ScriptStartServer(Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\t\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\t// set the appropriate memory context\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\r\n\tskate_mod->StartServer();\r\n\r\n\tif (gamenet_man->InInternetMode())\r\n\t{\r\n\t\t// defer loading the level/starting the game\r\n\t\t// until we have connected to the matchmaker\r\n\t\t//gamenet_man->RequestMatchmakerConnect();\r\n\t\t\r\n\t\t// SG: 9-17-02. Post the game AFTER we're in our first level\r\n\t\t//gamenet_man->PostGame();\r\n\t}\r\n\telse if (gamenet_man->InLanMode())\r\n\t{\r\n\t\t// if we're in LAN mode, start the game immediately\r\n\t}\r\n\t\t\r\n\t// pop the memory context\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LeaveServer | \r\nbool ScriptLeaveServer(Script::CStruct *pParams, Script::CScript *pScript )\r\n{   \r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n\tskate_mod->LeaveServer();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | FindServers | broadcast out to the local subnet for servers\r\nbool ScriptFindServers(Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t// Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\r\n\t//skate_mod->FindServers();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | JoinServer | Join the server in session at the given IP address and port\r\n// @uparm \"string\" | ip address\r\n// @uparm 1 | port\r\nbool ScriptJoinServer(Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n    \r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\tuint32 i;\r\n\r\n\t\t// If playing split screen, create N clients (one for each viewport\r\n\t\t// otherwise, just create one client\r\n//\t\tgamenet_man->SpawnClient( false, true, 0 );\r\n\r\n\t\tuint32 numPlayers = skate_mod->GetGameMode()->GetInitialNumberOfPlayers();\r\n\r\n\t\tfor( i = 0; i < numPlayers; i++ )\r\n\t\t{   \r\n\t\t\tNet::Client* client;\r\n\r\n\t\t\tclient = gamenet_man->SpawnClient( false, true, true, i );\r\n\t\t\t\r\n\t\t\t//skate_mod->JoinServer( false, 0, 0, true, i );\r\n\t\t\tgamenet_man->JoinServer( false, 0, 0, i );\r\n\t\t\tskate_mod->AddNetworkMsgHandlers( client, i );\r\n\t\t\tif( gamenet_man->InNetGame())\r\n\t\t\t{\r\n\t\t\t\tScript::RunScript( \"entered_network_game\" );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t/*int max_players;\r\n\t\tpParams->GetInteger( Script::GenerateCRC( \"MaxPlayers\" ), (int *) &max_players );\r\n\t\tskate_mod->GetGameMode()->SetMaximumNumberOfPlayers( max_players );\r\n\r\n\t\tDbg_Printf( \"**** SETTING MAX PLAYERS TO %d\\n\", max_players );\r\n\t\tDbg_Assert( skate_mod->GetGameMode()->GetMaximumNumberOfPlayers() == (uint32) max_players );*/\r\n\r\n#ifdef __PLAT_XBOX__\r\n\t\tIN_ADDR host_addr;\r\n\t\tint port = 0;\r\n\t\tbool observe_only;\r\n\r\n\t\tpParams->GetInteger( Script::GenerateCRC( \"Address\" ), (int *) &host_addr.s_addr );\r\n\t\tpParams->GetInteger( Script::GenerateCRC( \"Port\" ), &port );\r\n\t\tobserve_only = ( gamenet_man->GetJoinMode() == GameNet::vJOIN_MODE_OBSERVE );\r\n\t\r\n\t\tif( port != 0 )\r\n\t\t{\r\n\t\t\tgamenet_man->SpawnClient( false, false, true, 0 );\r\n\t\t\tgamenet_man->JoinServer( observe_only, (unsigned long) host_addr.s_addr, port, 0 );\r\n\t\t}\r\n#else\r\n\t\tconst char *server_ip = NULL;\r\n\t\tint port = 0;\r\n\t\tbool observe_only;\r\n\t\t\r\n\t\tpParams->GetText( NONAME, &server_ip );\r\n\t\tpParams->GetInteger( NONAME, &port );\r\n\t\tobserve_only = ( gamenet_man->GetJoinMode() == GameNet::vJOIN_MODE_OBSERVE );\r\n\t\r\n\t\tif( server_ip && ( port != 0 ))\r\n\t\t{\r\n\t\t\tgamenet_man->SpawnClient( false, false, true, 0 );\r\n\t\t\tgamenet_man->JoinServer( observe_only, inet_addr( server_ip ), port, 0 );\r\n\t\t}\r\n#endif\r\n\t}\r\n    \r\n\tMem::Manager::sHandle().PopContext();\r\n    \t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetNetworkMode | sets the network mode\r\n// @uparm 0 | mode\r\nbool ScriptSetNetworkMode( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tint mode = 0;\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tmode = 0;\r\n\tpParams->GetInteger( NONAME, &mode );\r\n\tif( mode == 0 )\r\n\t{\r\n\t\tgamenet_man->SetNetworkMode( GameNet::vNO_NET_MODE );\r\n\t}\r\n\telse if( mode == 1 )\r\n\t{\r\n\t\tgamenet_man->SetNetworkMode( GameNet::vLAN_MODE );\r\n\t}\r\n\telse if( mode == 2 )\r\n\t{\r\n\t\tgamenet_man->SetNetworkMode( GameNet::vINTERNET_MODE );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MemViewToggle | \r\nbool ScriptMemViewToggle( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMemViewToggle();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ProfileTasks | profiles task for the number of frames specified\r\n// @uparm 1 | number of frames\r\nbool ScriptProfileTasks( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t Mlp::Manager * mlp_manager =  Mlp::Manager::Instance();\r\n\tint Val=1;\r\n\tpParams->GetInteger(NONAME,&Val);\t\r\n\tprintf (\"\\n\\nProfiling task for %d frames:\\n\",Val);\r\n\tmlp_manager->ProfileTasks(Val);\r\n\t\r\n\treturn true;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UseNetworkPreferences | \r\nbool ScriptUseNetworkPreferences( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->UsePreferences();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptTestNetSetup( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tNet::Manager * net_man =  Net::Manager::Instance();\r\n\tbool properly_setup;\r\n\t \r\n\tproperly_setup = net_man->NetworkEnvironmentSetup();\r\n\tif( !properly_setup )\r\n\t{\r\n\t\tif( net_man->GetLastError() == Net::vRES_ERROR_DEVICE_NOT_HOT )\r\n\t\t{\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_error_not_connected\" ));\r\n\t\t\tScript::RunScript( \"create_net_startup_error_dialog\", pParams );\r\n\t\t}\r\n\t\telse if( net_man->GetLastError() == Net::vRES_ERROR_DEVICE_NOT_CONNECTED )\r\n\t\t{\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_error_device_error\" ));\r\n\t\t\tScript::RunScript( \"create_net_startup_error_dialog\", pParams );\r\n\t\t}\r\n\t\telse if( net_man->GetLastError() == Net::vRES_ERROR_UNKNOWN_DEVICE )\r\n\t\t{\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_error_not_detected\" ));\r\n\t\t\tScript::RunScript( \"create_net_startup_error_dialog\", pParams );\r\n\t\t}\r\n\t\telse if( net_man->GetLastError() == Net::vRES_ERROR_DHCP )\r\n\t\t{\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_error_dhcp_error\" ));\r\n\t\t\tScript::RunScript( \"create_net_startup_error_dialog\", pParams );\r\n\t\t}\r\n\t\telse if( net_man->GetLastError() == Net::vRES_ERROR_DEVICE_CHANGED )\r\n\t\t{\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_error_changed_device\" ));\r\n\t\t\tScript::RunScript( \"create_net_startup_error_dialog\", pParams );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpParams->AddComponent( Script::GenerateCRC( \"text\" ), ESYMBOLTYPE_STRING, Script::GetString( \"net_error_general_error\" ));\r\n\t\t\tScript::RunScript( \"create_net_startup_error_dialog\", pParams );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{   \r\n\t\tuint32 success_script;\r\n\r\n\t\tpParams->GetChecksum( \"success_script\", &success_script, true );\r\n\t\tDbg_Printf( \"***** SUCCESS! RUNNING SCRIPT %p\\n\", success_script );\r\n\t\tScript::RunScript( success_script, pParams );\r\n\t\t\r\n\t\t/*Script::CStruct* pParams;\r\n\r\n\t\tScript::RunScript( \"dialog_box_exit\" );\r\n\t\t//Script::RunScript( \"launch_network_select_menu\" );\r\n\t\t\r\n        pParams = new Script::CStruct;\r\n\r\n\t\tpParams->AddChecksum( \"change_gamemode\", Script::GenerateCRC( \"change_gamemode_net\" ));\r\n\t\tScript::RunScript( \"launch_select_skater_menu\", pParams );\r\n\t\t\r\n\t\tdelete pParams;*/\r\n\t}\r\n\r\n\treturn properly_setup;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptNeedToTestNetSetup( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tNet::Manager * net_man =  Net::Manager::Instance();\r\n\t\r\n\treturn net_man->NeedToTestNetworkEnvironment();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptCanChangeDevices( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tNet::Manager * net_man =  Net::Manager::Instance();\r\n\r\n\treturn net_man->CanChangeDevices();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ConnectToInternet | \r\nbool ScriptConnectToInternet( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tuint32 success, failure;\r\n\r\n\tsuccess = 0;\r\n\tfailure = 0;\r\n\r\n\tpParams->GetChecksum( CRCD(0x90ff204d,\"success\"), &success );\r\n\tpParams->GetChecksum( CRCD(0xde64fc3e,\"failure\"), &failure );\r\n\r\n\treturn gamenet_man->ConnectToInternet( success, failure );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptCancelConnectToInternet( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->CancelConnectToInternet();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptCancelLogon( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n#ifdef __PLAT_XBOX__\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tgamenet_man->mpAuthMan->CancelLogon();\r\n\treturn true;\r\n#else\r\n\treturn true;\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptIsOnline( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t Net::Manager * net_man =  Net::Manager::Instance();\r\n\r\n\treturn net_man->IsOnline();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DisconnectFromInternet | \r\nbool ScriptDisconnectFromInternet( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tuint32 callback_script = 0;\r\n\r\n\tpParams->GetChecksum( CRCD(0x86068bd9,\"callback\"), &callback_script );\r\n\tgamenet_man->DisconnectFromInternet( callback_script );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StopAllScripts | This will cause all scripts in existence\r\n// to stop (including the one calling this function). This function may\r\n// be useful later when doing cleanup type stuff. Note that though this\r\n// command will stop all scripts in existence at the moment it is called,\r\n// it won't prevent new scripts being run by the C-code\r\nbool ScriptStopAllScripts(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tScript::StopAllScripts();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetMenuElementText | sets the specified menu element\r\n// @uparmopt \"Blaa\" | text to use for menu element - \"Blaa\" is the actual default\r\nbool ScriptSetMenuElementText(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\t/*\r\n\tuint32 Id=0;\r\n\tpParams->GetChecksum(\"Id\",&Id);\r\n\tDbg_MsgAssert(Id,(\"SetMenuElementText requires an Id\"));\r\n\t\r\n\tconst char *pText=\"Blaa\";\r\n\tpParams->GetText(NONAME,&pText);\r\n\t\r\n\tFront::MenuEvent event;\r\n\tevent.SetTypeAndTarget(Front::MenuEvent::vSETCONTENTS,Id);\r\n\tScript::CStruct *pData = event.GetData();\t\t\r\n\tpData->AddComponent(Script::GenerateCRC(\"string\"), ESYMBOLTYPE_STRING, pText);\r\n\t Front::MenuFactory * pMenuFactory =  Front::MenuFactory::Instance();\r\n\tpMenuFactory->LaunchEvent(&event);\r\n\t*/\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic bool FirstTimeThisIsCalled_Flag=true;\r\n// @script | FirstTimeThisIsCalled | returns true the first time this is called\r\nbool ScriptFirstTimeThisIsCalled(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tif (FirstTimeThisIsCalled_Flag)\r\n\t{\r\n\t\tFirstTimeThisIsCalled_Flag=false;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\t\t\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EnableActuators | \r\n// @uparm 1 | 1 for enable - 0 for disable.  1 is the default\r\nbool\tScriptEnableActuators(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\t\r\n\tint on = 1;\t\r\n\tpParams->GetInteger(NONAME,&on);\r\n\tInp::Manager * input_man =  Inp::Manager::Instance();\r\n\tMdl::Skate * pSkate =  Mdl::Skate::Instance();\r\n\tfor (int i=0; i< SIO::vMAX_DEVICES; ++i)\r\n\t{\r\n\t\tif ( pSkate->mp_controller_preferences[i].VibrationOn )\r\n\t\t{\r\n\t\t\tif (on)\r\n\t\t\t{\r\n\t\t\t\tinput_man->EnableActuator(i);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tinput_man->DisableActuator(i);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\t\t\t\t\t  \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | InNetGame | returns true if we're in a net game\r\nbool ScriptInNetGame(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\t \r\n\treturn gamenet_man->InNetGame();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsObserving | You can now use the \"IsObserving\" script\r\n// command to perform logic (ex. hide objects) if the player is\r\n// Observing a network game.\r\nbool ScriptIsObserving( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tGameNet::PlayerInfo* player;\r\n\tGameNet::NewPlayerInfo* new_player;\r\n\tLst::Search< GameNet::NewPlayerInfo > sh;\r\n\r\n\tif(( player = gamenet_man->GetLocalPlayer()))\r\n\t{\r\n\t\treturn player->IsObserving();\r\n\t}\r\n\t\t\r\n\t// If we're observing, we need to remove our skater\r\n\tfor( new_player = gamenet_man->FirstNewPlayerInfo( sh ); new_player; new_player = gamenet_man->NextNewPlayerInfo( sh ))\r\n\t{\r\n\t\tif( new_player->Flags & GameNet::PlayerInfo::mLOCAL_PLAYER )\r\n\t\t{\r\n\t\t\tif( new_player->Flags & GameNet::PlayerInfo::mOBSERVER )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn( gamenet_man->GetJoinMode() == GameNet::vJOIN_MODE_OBSERVE );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SkatersAreReady | true if all skaters connected to the server\r\n// are done loading\r\nbool ScriptSkatersAreReady(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\r\n\t// poll the server to find out whether the skaters are done loading\r\n\tif( gamenet_man->ReadyToPlay() && \r\n\t\t( ( skate_mod->GetNumSkaters() > 0 ) ||\r\n\t\t  ( ScriptIsObserving( NULL, NULL ))))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetSlomo | sets slomo to specified value\r\n// @uparmopt 1.0 | value \r\nbool ScriptSetSlomo(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tfloat slomo = 1.0f;\r\n\tpParams->GetFloat(NONAME,&slomo);\r\n\tTmr::SetSlomo(slomo);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetArenaSize | Obsolete function\r\nbool ScriptSetArenaSize(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tDbg_Message( \"SetArenaSize is obsolete\" );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetParticleSysVisibility | no longer supported.\r\nbool ScriptSetParticleSysVisibility( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tprintf (\"STUBBED: ScriptSetParticleSysVisibility\\n\");\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | TogglePlayerNames | \r\nbool ScriptTogglePlayerNames( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->TogglePlayerNames();\r\n\tif( !gamenet_man->ShouldDrawPlayerNames())\r\n\t{\r\n\t\tScript::RunScript( \"destroy_all_player_names\" );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/*************************                          *****************************************/\r\n\r\n// @script | SetCurrentGameType | sets the current game type\r\nbool ScriptSetCurrentGameType( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tskate_mod->SetCurrentGameType();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DumpNetMessageStats | displays all net message stats\r\nbool ScriptDumpNetMessageStats( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tNet::Conn* conn;\r\n\tLst::Search< Net::Conn > sh;\r\n\tNet::App* app;\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n#ifdef __NOPT_ASSERT__\r\n\t Net::Manager * net_man =  Net::Manager::Instance();\r\n#endif\t\t// __NOPT_ASSERT__\r\n\tint i, j, total_size, total_num, size, num;\r\n\tNet::Metrics* metrics;\r\n\r\n\tapp = gamenet_man->GetServer();\r\n\tif( app == NULL )\r\n\t{\r\n\t\tapp = gamenet_man->GetClient( 0 );\r\n\t}\r\n\r\n\tif( app == NULL )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\ti = 0;\r\n    for( conn = app->FirstConnection( &sh ); conn; conn = app->NextConnection( &sh ))\r\n\t{\r\n\t\tmetrics = conn->GetInboundMetrics();\r\n\t\tDbg_Printf( \"Conn %d inbound stats:\\n\", i );\r\n\t\ttotal_size = 0;\r\n\t\ttotal_num = 0;\r\n\t\tfor( j = 0; j < 256; j++ )\r\n\t\t{\r\n\t\t\ttotal_size += metrics->GetTotalMessageData( j );\r\n\t\t\ttotal_num += metrics->GetTotalNumMessagesOfId( j );\r\n\t\t}\r\n\r\n\t\t// Guard against dbz\r\n\t\tif( total_size == 0 )\r\n\t\t{\r\n\t\t\ttotal_size = 1;\r\n\t\t}\r\n\r\n\t\tfor( j = 0; j < 256; j++ )\r\n\t\t{\r\n\t\t\tsize = metrics->GetTotalMessageData( j );\r\n\t\t\tnum = metrics->GetTotalNumMessagesOfId( j );\r\n\r\n\t\t\tif( num > 0 )\r\n\t\t\t{\r\n#\t\t\t\tifdef __NOPT_ASSERT__\r\n\t\t\t\tDbg_Printf( \"[%d-%s] Num: %d Size: %d Pct: %02f\\n\", j, net_man->GetMessageName( j ),\r\n\t\t\t\t\t\tnum, size, (float) size/(float) total_size );\r\n#\t\t\t\tendif // __NOPT_ASSERT__\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tmetrics = conn->GetOutboundMetrics();\r\n\t\tDbg_Printf( \"Conn %d outbound stats:\\n\", i );\r\n\t\ttotal_size = 0;\r\n\t\ttotal_num = 0;\r\n\t\tfor( j = 0; j < 256; j++ )\r\n\t\t{\r\n\t\t\ttotal_size += metrics->GetTotalMessageData( j );\r\n\t\t\ttotal_num += metrics->GetTotalNumMessagesOfId( j );\r\n\t\t}\r\n\r\n\t\t// Guard against dbz\r\n\t\tif( total_size == 0 )\r\n\t\t{\r\n\t\t\ttotal_size = 1;\r\n\t\t}\r\n\r\n\t\tfor( j = 0; j < 256; j++ )\r\n\t\t{\r\n\t\t\tsize = metrics->GetTotalMessageData( j );\r\n\t\t\tnum = metrics->GetTotalNumMessagesOfId( j );\r\n\r\n\t\t\tif( num > 0 )\r\n\t\t\t{\r\n#\t\t\t\tifdef __NOPT_ASSERT__\r\n\t\t\t\tDbg_Printf( \"[%d-%s] Num: %d Size: %d Pct: %02f\\n\", j, net_man->GetMessageName( j ),\r\n\t\t\t\t\t\tnum, size, (float) size/(float) total_size );\r\n#\t\t\t\tendif // __NOPT_ASSERT__\r\n\t\t\t}\r\n\t\t}\r\n\t\ti++;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetServerMode | sets the server mode\r\n// @flag off | \r\nbool  ScriptSetServerMode(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tbool off = pParams->ContainsFlag(\"off\");\r\n    \r\n\tgamenet_man->SetServerMode( !off );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | NotifyBailDone | \r\nbool ScriptNotifyBailDone( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tNet::Client* client;\t\r\n\r\n\tObj::CSkater *pSkater=NULL;\r\n\tif( pScript && pScript->mpObject && pScript->mpObject->GetType() == SKATE_TYPE_SKATER )\t\r\n\t{\r\n\t\t// If the script using this has an object associated with it, and that object\r\n\t\t// is a skater, then use that skater.\r\n\t\tpSkater= (Obj::CSkater *) pScript->mpObject.Convert();\r\n\t}\r\n\r\n\tif( pSkater && pSkater->IsLocalClient())\r\n\t{\r\n\t\tclient = gamenet_man->GetClient( pSkater->GetSkaterNumber());\r\n\t\tif( client )\r\n\t\t{\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\r\n\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_BAIL_DONE;\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DisplayLoadingScreen | shows the loading screen \r\n// @uparm \"string\" | name of the screen to display\r\n// @uparmopt time | the amount of time to display loading bar (default is 0, meaning no loading bar)\r\n// @flag Freeze | just freeze current screen\r\n// @flag Blank | clear screen to black\r\nbool ScriptDisplayLoadingScreen( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tconst char\t*pScreen = \"images\\\\xxxxx\";\t\r\n\tpParams->GetText(NONAME,&pScreen);\r\n\t\r\n\tNx::CLoadScreen::sDisplay( (char*) pScreen, pParams->ContainsFlag(CRCD(0xb96e0be5,\"Freeze\")),pParams->ContainsFlag(CRCD(0xc3d43b9a,\"blank\")));\r\n\r\n\tfloat duration;\r\n\tif (pParams->GetFloat(NONAME,&duration))\r\n\t{\r\n\t\tNx::CLoadScreen::sStartLoadingBar(duration);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | HideLoadingScreen | hides the loading screen \r\nbool ScriptHideLoadingScreen( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t//LoadScreen::Hide();\r\n\tNx::CLoadScreen::sHide();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EnterObserverMode | changes to observer mode (for net game)\r\nbool ScriptEnterObserverMode(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->RequestObserverMode();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ObserveNextSkater | \r\nbool ScriptObserveNextSkater( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n\tskate_mod->ObserveNextSkater();\r\n\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AllowPause | \r\n// @flag off | do not allow pause\r\nbool ScriptAllowPause(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tbool on = true;\r\n\tif (pParams->ContainsFlag(\"off\"))\r\n\t{\r\n\t\ton = false;\r\n\t}\t\t\r\n\r\n\tprintf (\"WARNING: ScriptAllowPause is STUBBED\\n\");\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RefreshServerList | gets a new server list \r\nbool ScriptRefreshServerList(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->RefreshServerList( pParams->ContainsFlag( \"force_refresh\" ));\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StartServerList | \r\nbool ScriptStartServerList(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->StartServerList();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptStartLobbyList( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tif(\tgamenet_man->GetServerListState() == GameNet::vSERVER_LIST_STATE_SHUTDOWN )\r\n\t{\r\n\t\tgamenet_man->SetNextServerListState( GameNet::vSERVER_LIST_STATE_STARTING_LOBBY_LIST );\r\n\t\tgamenet_man->SetServerListState( GameNet::vSERVER_LIST_STATE_INITIALIZE );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgamenet_man->SetServerListState( GameNet::vSERVER_LIST_STATE_STARTING_LOBBY_LIST );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StopServerList | \r\nbool ScriptStopServerList(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->StopServerList();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | FreeServerList | \r\nbool ScriptFreeServerList(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->FreeServerList();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PauseGameFlow | suspends gameflow - should only be called from\r\n// gameflow.q\r\nbool ScriptPauseGameFlow(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tskate_mod->PauseGameFlow( true );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UnPauseGameFlow | \r\nbool ScriptUnpauseGameFlow(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tskate_mod->PauseGameFlow( false );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | InFrontEnd | returns true if we are in the front end\r\nbool ScriptInFrontEnd(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\treturn skate_mod->GetGameMode()->IsFrontEnd();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | InSplitScreenGame | returns true if we are in a split screen game\r\nbool ScriptInSplitScreenGame(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\treturn skate_mod->IsMultiplayerGame() && !gamenet_man->InNetGame() && !skate_mod->GetGameMode()->IsFrontEnd();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | InMultiPlayerGame | \r\nbool ScriptInMultiplayerGame(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\r\n\treturn skate_mod->IsMultiplayerGame();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetFireballLevel(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tint level;\r\n\t \r\n\tScript::CStruct* params = pScript->GetParams();\r\n\r\n \tlevel = skate_mod->GetGameMode()->GetFireballLevel();\r\n\tparams->AddInteger( CRCD(0x651533ec,\"level\"), level );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GameModeEquals | returns true if the current game mode matches\r\n// the specified game mode\r\n// @uparm name | game mode to check. More than one may be specified, eg GameModeEquals is_singlesession is_creategoals\r\nbool ScriptGameModeEquals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t \r\n \tCComponent *pComp=pParams->GetNextComponent();\r\n\twhile (pComp)\r\n\t{\r\n\t\tif (pComp->mNameChecksum==0 && pComp->mType==ESYMBOLTYPE_NAME)\r\n\t\t{\r\n\t\t\tif (skate_mod->GetGameMode()->IsTrue(pComp->mChecksum))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tpComp=pParams->GetNextComponent(pComp);\r\n\t}\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | OnServer | returns true if we are on a server\r\nbool ScriptOnServer(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\treturn gamenet_man->OnServer();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetCurrentLevel | returns level=load_foun  (or whatever)\r\n// so you can use it with LoadLevel, without going through LoadRequestedLevel\r\nbool ScriptGetCurrentLevel(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tpScript->GetParams()->AddComponent( Script::GenerateCRC(\"level\"), ESYMBOLTYPE_NAME, (int)skate_mod->m_requested_level );\r\n\t\r\n\tGame::CGoalManager* p_goal_manager = Game::GetGoalManager();\r\n\tDbg_MsgAssert(p_goal_manager,(\"NULL p_goal_manager ?\"));\r\n\tpScript->GetParams()->AddChecksum(CRCD(0x16a0b364,\"level_structure\"),p_goal_manager->GetLevelStructureName());\r\n\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RestartLevel | RestartLevel is just intended to be called\r\n// when a level is restarted it does not actually restart the level,\r\n// it just sets a few flags and does something with disabling the the\r\n// viewer log that's only related to screenshot mode \r\nbool ScriptRestartLevel(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tskate_mod->RestartLevel();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ToggleScores | toggles game scores\r\nbool ScriptToggleScores(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->ToggleScores();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | XTriggered | \r\nbool ScriptXTriggered(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    Dbg_MsgAssert( 0, ( \"Obsolete function\" ) );\r\n    return false;\r\n\r\n//\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n//\treturn skate_mod->XTriggered();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UsePad | sets the specified skater to use the pad\r\n// @uparmopt 0 | skater id (default is 0)\r\nbool ScriptUsePad(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    Dbg_MsgAssert( 0, ( \"Obsolete function\" ) );\r\n    return false;\r\n\t\r\n/*\r\n    int skaterId = 0;\r\n\tpParams->GetInteger( NONAME, &skaterId );\r\n\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tskate_mod->UsePad( skaterId );\r\n\treturn true;\r\n*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsTrue | Checks to see whether some global constant equals\r\n// 1 or 0.  (If it's not defined anywhere, then it returns 0.) <nl>\r\n// Usage: <nl>\r\n// if IsTrue run_viewer <nl>\r\n//    printf \"I am in viewer mode\" <nl>\r\n// else <nl>\r\n//    printf \"I am in skateshop mode\" <nl>\r\n// endif <nl>\r\n// if IsTrue test_balls <nl>\r\n// where test_balls is defined in \"yourname\".q. <nl>\r\n//    printf \"I am testing my balls here\" <nl>\r\n// endif \r\n// @uparm name | global constant to check\r\nbool ScriptIsTrue(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint Integer=0;\r\n\tpParams->GetInteger( NONAME, &Integer, false );\r\n\t\r\n\treturn Integer;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GameFlow | \r\n// @uparm name | script name\r\nbool ScriptGameFlow(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 ScriptChecksum=0;\r\n\tpParams->GetChecksum(NONAME,&ScriptChecksum);\r\n\tDbg_MsgAssert(ScriptChecksum,(\"\\n%s\\nGameFlow requires a script name, eg Gameflow Blaa\",pScript->GetScriptInfo()));\r\n\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tDbg_AssertPtr( skate_mod->mp_gameFlow );\r\n\tskate_mod->mp_gameFlow->Reset( ScriptChecksum );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptLastBroadcastedCheatWas(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 cheat_flag;\r\n\r\n\tpParams->GetChecksum(CRCD(0xae94c183,\"cheat_flag\"), &cheat_flag, true );\r\n\r\n\treturn( s_last_broadcast_cheat == cheat_flag );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptClearCheats(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tObj::CSkaterCareer* career;\r\n\r\n\tcareer = skate_mod->GetCareer();\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x13d5b5db,\"CHEAT_ON_1\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x8adce461,\"CHEAT_ON_2\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0xfddbd4f7,\"CHEAT_ON_3\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x63bf4154,\"CHEAT_ON_4\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x14b871c2,\"CHEAT_ON_5\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x8db12078,\"CHEAT_ON_6\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0xfab610ee,\"CHEAT_ON_7\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x6a090d7f,\"CHEAT_ON_8\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x1d0e3de9,\"CHEAT_ON_9\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x37cbee45,\"CHEAT_ON_10\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x40ccded3,\"CHEAT_ON_11\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0xd9c58f69,\"CHEAT_ON_12\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0xaec2bfff,\"CHEAT_ON_13\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x30a62a5c,\"CHEAT_ON_14\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x47a11aca,\"CHEAT_ON_15\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0xdea84b70,\"CHEAT_ON_16\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0xa9af7be6,\"CHEAT_ON_17\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x39106677,\"CHEAT_ON_18\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x4e1756e1,\"CHEAT_ON_19\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x1ce6bd86,\"CHEAT_ON_20\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x6be18d10,\"CHEAT_ON_21\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0xf2e8dcaa,\"CHEAT_ON_22\")));\r\n\tcareer->UnSetGlobalFlag( Script::GetInteger(CRCD(0x85efec3c,\"CHEAT_ON_23\")));\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptBroadcastCheat(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tLst::Search< Net::Conn > sh;\r\n\tNet::Conn* conn;\r\n\tNet::Server* server;\r\n\tuint32 cheat_flag;\r\n\tchar on;\r\n\r\n\tpParams->GetChecksum(CRCD(0xae94c183,\"cheat_flag\"), &cheat_flag, true );\r\n\tDbg_Assert( gamenet_man->OnServer());\r\n\tDbg_Assert( gamenet_man->InNetGame());\r\n\tif( pParams->ContainsComponentNamed(CRCD(0xf649d637,\"on\")))\r\n\t{\r\n\t\ton = 1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\ton = 0;\r\n\t}\r\n\r\n\t// Intentionally sprinkled in this function so that hackers have a more-difficult time to \r\n\t// nullify it\r\n\ts_last_broadcast_cheat = cheat_flag;\r\n\tserver = gamenet_man->GetServer();\r\n\tfor( conn = server->FirstConnection( &sh ); conn; conn = server->NextConnection( &sh ))\r\n\t{\r\n\t\tif( conn->IsRemote())\r\n\t\t{\r\n\t\t\tNet::MsgDesc msg_desc;\r\n\t\t\tGameNet::MsgToggleCheat msg;\r\n\t\r\n\t\t\tmsg.m_Cheat = cheat_flag;\r\n\t\t\tmsg.m_On = on;\r\n\t\r\n\t\t\tmsg_desc.m_Id = GameNet::MSG_ID_TOGGLE_CHEAT;\r\n\t\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\t\tmsg_desc.m_Data = &msg;\r\n\t\t\tmsg_desc.m_Length = sizeof( GameNet::MsgToggleCheat );\r\n\t\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\t\r\n\t\t\tserver->EnqueueMessage( conn->GetHandle(), &msg_desc );\r\n\t\t\ts_last_broadcast_cheat = cheat_flag;\r\n\t\t}\r\n\t}\r\n\r\n\ts_last_broadcast_cheat = cheat_flag;\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptCheatAllowed(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 cheat_flag;\r\n\r\n\tpParams->GetChecksum(CRCD(0xae94c183,\"cheat_flag\"), &cheat_flag, true );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | JoinWithPassword | joins the server with the specified password\r\n// @parm string | string | password string\r\nbool ScriptJoinWithPassword(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n    \r\n\tconst char* p_string;\r\n\tpParams->GetText( \"string\", &p_string, true );\r\n\r\n    gamenet_man->ReattemptJoinWithPassword((char*) p_string );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SendChatMessage | \r\n// @parm string | string | the message to send\r\nbool ScriptSendChatMessage(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tconst char* p_string = NULL;\r\n\tpParams->GetText( \"string\", &p_string );\r\n\tif( p_string == NULL )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n#if ( ENGLISH == 0 )\r\n\tif ( ( p_string != NULL ) && ( strlen( p_string ) > 0 ) && ( stricmp( p_string, Script::GetLocalString( \"kc_str_empty\" ) ) ) )\r\n#else\r\n\tif ( ( p_string != NULL ) && ( strlen( p_string ) > 0 ) && ( stricmp( p_string, \"--EMPTY--\" ) ) )\r\n#endif\r\n\t{\r\n\t\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\t\tgamenet_man->SendChatMessage( (char*) p_string );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | InSlapGame | true if we are in a slap or netslap game\r\nbool ScriptInSlapGame( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n\tif( ( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netslap\" )) ||\r\n\t\t(skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"slap\" )))\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetScreenMode | Sets the way the screen will be split up into separate\r\n// viewports in the game. If there is more than one viewport, and multiple skaters\r\n// are active, then each skater will get his own viewport\r\n// @uparm One_Camera | the mode to use - one of the following: <nl>\r\n// One_Camera <nl>\r\n// Split_Vertical <nl>\r\n// Split_Horizontal <nl>\r\n// Split_Quarters\r\nbool ScriptSetScreenMode(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n\tNx::ScriptSetScreenMode( pParams, pScript );\r\n\r\n\tObj::CSkater* pSkater;\r\n\tMdl::Score* pScore;\r\n\tfor( uint i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tpSkater = skate_mod->GetSkater(i);\t\t\t\t\t\t   \r\n\t\tif ( pSkater )\t\t\t// Skater might not exist\r\n\t\t{\r\n\t\t\tpScore = pSkater->GetScoreObject();\r\n\t\t\tpScore->RepositionMeters();\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetScreenModeFromGameMode | sets the appropriate screen mode based on the game mode\r\nbool ScriptSetScreenModeFromGameMode( Script::CStruct *pParams, Script::CScript *pScript )\r\n{           \r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tNx::ScreenMode requested_mode, current_mode;\r\n\r\n\tObj::CSkater* pSkater;\r\n\tMdl::Score* pScore;\r\n\tfor( uint i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tpSkater = skate_mod->GetSkater(i);\t\t\t\t\t\t   \r\n\t\tif ( pSkater && pSkater->IsLocalClient())\t\t\t// Skater might not exist\r\n\t\t{\r\n\t\t\tprintf (\"cfuncs %d: SUTUBBBEDDDDDDDDDDDDDDDDDDDDDDDD\\n\",__LINE__);\r\n\t\t\t\r\n\t\t\t/*\t\t\t\t\t\t\t\r\n\t\t\tGfx::Camera *p_camera = pSkater->GetSkaterCam();\r\n\t\t\tif (p_camera)\r\n\t\t\t{\r\n\t\t\t\tNx::CViewportManager::sSetCameraAllScreenModes(pSkater->GetHeapIndex(), p_camera);\r\n\t\t\t}\r\n\t\t\t*/\r\n\t\t}\r\n\t}\r\n\t\r\n\t// set up the appropriate screen mode\r\n\trequested_mode = skate_mod->GetGameMode()->GetScreenMode();\r\n\tcurrent_mode = Nx::CViewportManager::sGetScreenMode();\r\n\tif(! ((\t( requested_mode == Nx::vSPLIT_V ) &&\r\n\t\t\t( current_mode == Nx::vSPLIT_H )) ||\r\n\t\t\t(( requested_mode == Nx::vSPLIT_H ) &&\r\n\t\t\t( current_mode == Nx::vSPLIT_V ))))\r\n\t{\r\n\t\tNx::CViewportManager::sSetScreenMode( requested_mode );\r\n\t}\r\n\r\n\tfor( uint i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tpSkater = skate_mod->GetSkater(i);\t\t\t\t\t\t   \r\n\t\tif ( pSkater && pSkater->IsLocalClient())\t\t\t// Skater might not exist\r\n\t\t{\r\n\t\t\tpScore = pSkater->GetScoreObject();\r\n\t\t\tpScore->RepositionMeters();\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LoadPendingPlayers | \r\nbool ScriptLoadPendingPlayers( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->LoadPendingPlayers();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LaunchQueuedScripts | \r\nbool ScriptLaunchQueuedScripts( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tGameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->LaunchQueuedScripts();\r\n\r\n\treturn true;\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////////////////\r\n// extend the current parameters to include:  string = \"WOW\"\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetInitialsString | gets the initials string for the player\r\nbool ScriptGetInitialsString( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMdl::Skate * pSkate =  Mdl::Skate::Instance();\r\n\tRecords::CGameRecords *pGameRecords=pSkate->GetGameRecords();\r\n\t\r\n\tpScript->GetParams()->AddComponent( Script::GenerateCRC( \"string\" ), ESYMBOLTYPE_STRING, pGameRecords->GetDefaultInitials()->Get() );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetInitialsString | sets the initials string for the player\r\n// @parm string | string | initials string\r\nbool ScriptSetInitialsString( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\t Mdl::Skate * pSkate =  Mdl::Skate::Instance();\r\n\tRecords::CGameRecords *pGameRecords=pSkate->GetGameRecords();\t\r\n\tconst char *pInitials = \"ERR\";\r\n\tpParams->GetText(\"string\",&pInitials);\r\n\tpGameRecords->SetDefaultInitials(pInitials);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AttachToSkater | (DEPRECATED) Make the current script be running on the skater <nl>\r\n// used for the gameflow, where we are not always sure if there is a skater there <nl>\r\n// use this in place of SpawnSkaterScript in the gameflow <nl>\r\n// if \"AttachToSkater End\" is called then will detatch it <nl>\r\n// must be in mathcing pairs <nl>\r\n// otherwise the gameflow gets messed up <nl>\r\n// when the skater is deleted (as the gameflow gets stopped and deleted) <nl>\r\n// @flag End | \r\nbool\tScriptAttachToSkater(  Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\r\n\tDbg_MsgAssert(0,(\"ScriptAttachToSkater should not be called, as it is old and dangerous\\n\"));\t\r\n\t\r\n\tif (pParams->ContainsFlag(\"End\"))\r\n\t{\r\n\t\tpScript->mpObject = NULL; \r\n\t}\r\n\telse\r\n\t{\r\n\t\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\tObj::CSkater *pSkater = skate_mod->GetLocalSkater();\r\n\t\tDbg_MsgAssert(pSkater,(\"AttachToSkater called before skater exists\"));\r\n\t\tpScript->mpObject = pSkater; \r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | TryCheatString | \r\n// @parm string | string | cheat string to try\r\nbool\tScriptTryCheatString(  Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tchar  b[128];\r\n\tconst char *p;\r\n\tpParams->GetText(\"string\",&p,true);\r\n\tif (strlen(p) < 6)\r\n\t{\r\n\t\tScript::RunScript(\"cheat_playsound_bad\");\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tsprintf(b,\"12345678901234567890\"); \t\t// just in case.....\r\n\tsprintf(b,p);\r\n\t\r\n\t// (Mick)\t\t\t\t\t\t\t\t\t  \r\n\t// We want to generate a 64 bit CRC\r\n\t// so we take 3 checksums, starting from 3 different places\r\n\t// and add the first one to the second two\r\n\t// and use those two numbers as a 64 bit checksum\r\n\t// The idea here is to create a number, from which is is difficult to\r\n\t// go back to the original string\r\n\t// (to do this, you need a fairlry long string, otherwise, you could just try them all\r\n\t// now we do 1 second worth of PS2 precessing the generate the key,\r\n\t// so even on a computer 1000 times as fast, it would take ~30 years to try all six letter keys\r\n\t// So, barring a flaw in my algorithm, should be pretty safe even with short keys \r\n\t\r\n\tuint32 check0 = Script::GenerateCRC(p);\t  // get checksum\r\n\t\r\n\tuint32 check1 = 0;\t\r\n\tfor (int i = 0;i< 100000;i++)\t\t\t  // a hundred thousand calls, to mess with Ken\r\n\t{\r\n\t\tsprintf (b,\"%d\",i+check0);\t\t\t  // print a different number at the start\r\n\t\tb[strlen(b)]='X';\t\t\t\t\t  // link it to the rest of the string\r\n\t\tchar *p1 = b;\r\n\t\twhile (*p1)\r\n\t\t{\r\n\t\t\tcheck1 += 1023 * (*p1++);\t\t\t\t  // and just add up the bytes, oh, how sweet...\r\n\t\t}\r\n\t\tcheck0 = Script::GenerateCRC(b);\t  // oh, I slay myself...\r\n\t}\r\n\tuint32 check2 = Script::GenerateCRC(&p[strlen(p)/3]);\t\r\n\tuint32 check3 = Script::GenerateCRC(b);\t   // use the final string, so no correlation with check2\r\n\t\r\n//\tprintf (\"%x,%x,%x\\n\",check1,check2,check3);\t // three pretty dang random looking numbers\r\n\r\n\tcheck2 ^= check1;\t\t\t\t\t\t\t // munched into two\r\n\tcheck3 ^= check1;\t\t\t\t\t\t\t // (hopefully not a fatal mistake)\r\n\t\r\n//\tprintf (\"%x,%x,%x\\n\",check1,check2,check3);\r\n\t// Print it out, so we can cut and paste\r\n\tprintf (\"\\n{c1=%d c2=%d CheatScript=cheat_xxx },  ; %s\\n\\n\",check2, check3,p); \r\n\t// then search through the cheat array to see if we have a match\r\n\r\n\r\n\t#ifdef\t__PLAT_XBOX__\t\t\t\t \t\r\n\tScript::CArray *pCheatArray = Script::GetArray( \"Cheat_Array_Xbox\" );\r\n\t#endif\r\n\t#ifdef\t__PLAT_NGC__\t\t\t\t \t\r\n\tScript::CArray *pCheatArray = Script::GetArray( \"Cheat_Array_Gamecube\" );\r\n\t#endif\r\n\t#ifdef\t__PLAT_NGPS__\t\t\t\t \t\r\n\tScript::CArray *pCheatArray = Script::GetArray( \"Cheat_Array_PS2\" );\r\n\t#endif\r\n\t\r\n\tDbg_MsgAssert( pCheatArray,( \"No Cheat_Array found\" ));\r\n\tint cheats = pCheatArray->GetSize();\r\n\tbool cheated = false;\r\n\tfor (int cheat = 0;cheat<cheats;cheat++)\r\n\t{\r\n\t\tScript::CStruct *pStruct = pCheatArray->GetStructure(cheat);\r\n\t\tDbg_MsgAssert( pStruct,( \"Cheat Array messed up\" ));\r\n\t\tuint32 c1,c2;\r\n\t\tuint32 cheat_script;\r\n\t\tpStruct->GetInteger(\"c1\",(int*)&c1,true);\r\n\t\tpStruct->GetInteger(\"c2\",(int*)&c2,true);\r\n\t\tpStruct->GetChecksum(\"cheatscript\",&cheat_script,true);\r\n\t\tif (c1 == check2 && c2 == check3)\r\n\t\t{\r\n\t\t\tScript::RunScript(\"cheat_playsound_good\");\r\n\t\t\tScript::RunScript(cheat_script);\r\n\t\t\tcheated = true;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (!cheated)\r\n\t{\r\n\t\t\tScript::RunScript(\"cheat_playsound_bad\");\r\n\t}\r\n\r\n\r\n\t\t\t\t\t\t\t\t\r\n\treturn false;\t\t\t\t\t\t\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LevelIs | true if the level matches the specified level\r\n// @uparm name | level name\r\nbool ScriptLevelIs(  Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\r\n\t// GJ:  this may not work in park editor mode\r\n\tuint32 level_name;\r\n\tpParams->GetChecksum( NONAME, &level_name, true );\r\n\t\r\n\treturn ( skate_mod->m_cur_level == level_name );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StartNetworkLobby | \r\nbool ScriptStartNetworkLobby( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\tgamenet_man->StartNetworkLobby();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ObserversAllowed | \r\nbool ScriptObserversAllowed( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t Net::Manager * net_man =  Net::Manager::Instance();\r\n\t\r\n\t// Modem games cannot host observers\r\n\treturn( net_man->GetConnectionType() != Net::vCONN_TYPE_MODEM );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | NumPlayersAllowed | \r\n// @uparm name | number of players allowed\r\nbool ScriptNumPlayersAllowed( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\t\r\n\tuint32 checksum = 0;\r\n\t Net::Manager * net_man =  Net::Manager::Instance();\r\n\r\n\t// Non-Modem games have no max player restriction\r\n\tif( net_man->GetConnectionType() != Net::vCONN_TYPE_MODEM )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n    \r\n\tpParams->GetChecksum( NONAME, &checksum );\r\n\tif( checksum == Script::GenerateCRC( \"num_4\" ))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AutoDNS | true if auto DNS\r\nbool ScriptAutoDNS( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tScript::CStruct* pStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tuint32 auto_dns_checksum;\r\n\t \r\n\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"auto_dns\") );\r\n\tpStructure->GetChecksum( \"Checksum\", &auto_dns_checksum, true );\r\n\treturn ( auto_dns_checksum == Script::GenerateCRC( \"boolean_true\" ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UsingDefaultMasterServers | true if using the default master\r\n// servers\r\nbool ScriptUsingDefaultMasterServers( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tScript::CStruct* pStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tuint32 default_servers;\r\n\t \r\n\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"use_default_master_servers\") );\r\n\tpStructure->GetChecksum( \"Checksum\", &default_servers, true );\r\n\treturn ( default_servers == Script::GenerateCRC( \"boolean_true\" ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UsingDHCP | true if using DHCP\r\nbool ScriptUsingDHCP( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tScript::CStruct* pStructure;\r\n\tPrefs::Preferences* pPreferences;\r\n\tuint32 ip_assignment;\r\n\t \r\n\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"broadband_type\") );\r\n\tpStructure->GetChecksum( \"Checksum\", &ip_assignment, true );\r\n\treturn ( ip_assignment == Script::GenerateCRC( \"ip_dhcp\" ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | InInternetMode | \r\nbool ScriptInInternetMode( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\r\n\treturn gamenet_man->InInternetMode();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EnteringNetGame | true if we're in a network game but not \r\n// read to play\r\nbool ScriptEnteringNetGame( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n\t return(( gamenet_man->InNetGame()) &&\r\n\t\t\t( skate_mod->m_prev_level == Script::GenerateCRC( \"Load_Skateshop\" )));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DeviceChosen | true if a device type has been chosen\r\nbool ScriptDeviceChosen( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\tuint32 checksum;\r\n\tPrefs::Preferences* pPreferences;\r\n\tScript::CStruct* pStructure;\r\n\r\n\tpPreferences = gamenet_man->GetNetworkPreferences();\r\n\tDbg_Assert( pPreferences );\r\n\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"device_type\") );\r\n\tpStructure->GetChecksum( \"checksum\", &checksum, true );\r\n\r\n\treturn ( checksum != Script::GenerateCRC(\"device_none\"));\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GameIsOver | true if game is over\r\nbool ScriptGameIsOver( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t GameNet::Manager * gamenet_man =  GameNet::Manager::Instance();\r\n\t\r\n\treturn gamenet_man->GameIsOver();\r\n}\r\n\r\nstatic char \ts_level_name[64];\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetLevelName | gets the level name into the above static, so it can be used for the DumpHeaps memory profile dump \r\nbool ScriptSetLevelName( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tconst char* pName;\r\n\tpParams->GetText( NONAME, &pName, true );\r\n\tsprintf(s_level_name,pName);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetPS2 | For testing the reset button handler when\r\n// the Sony Network adapter is loaded\r\nbool ScriptResetPS2( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\r\n#\tifdef __PLAT_NGPS__\r\n\tint stat;\r\n\r\n\tDbg_Printf( \"Resetting PS2\\n\" );\r\n\t\r\n\twhile( sceDevctl(\"dev9x:\", DDIOC_OFF, NULL, 0, NULL, 0 ) < 0 );\r\n\t// PS2 power off\r\n\twhile( !sceCdPowerOff( &stat ) || stat );\r\n#\tendif // __PLAT_NGPS__\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetHD | For testing the reset button handler when\r\n// the Sony Network adapter is loaded\r\nbool ScriptResetHD( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tDbg_Printf( \"Resetting PS2\\n\" );\r\n\r\n#\tifdef __PLAT_NGPS__\r\n\tint stat;\r\n\tsceDevctl(\"pfs:\", PDIOC_CLOSEALL, NULL, 0, NULL, 0);\r\n\twhile (sceDevctl(\"hdd:\", HDIOC_DEV9OFF, NULL, 0, NULL, 0) < 0);\r\n\twhile (sceDevctl(\"dev9x:\", DDIOC_OFF, NULL, 0, NULL, 0) < 0);\r\n    while (!sceCdPowerOff(&stat) || stat);\r\n#\tendif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PAL | returns true if we're in PAL mode\r\nbool ScriptPAL( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n#ifdef\tPAL\r\n\treturn true;\r\n#else\r\n\treturn false;\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Change | changes the symbol to the new value specified.  will do nothing\r\n// if called on the following: a symbol that doesn't already exist, a script symbol, c-function\r\n// or member function symbols <nl>\r\n// should really only be called on strings, floats, and ints <nl>\r\n// example: Change Foo=7\r\n// @uparm name | the name of the symbol to change\r\n// @uparm value | the value to assign to the symbol (make sure type is correct)\r\n// @flag Resolve | If specified, resolve the right hand side if it is a name of a global, so as to lose\r\n// the reference to that global. Ie, Change a=b Resolve where a=6 and b=3.141 will change a to be 3.141,\r\n// and it will remain so even if b is then changed to something else.\r\nbool ScriptChangeSymbolValue(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// Extract the first component from pParams, which is used to define the name of the\r\n\t// symbol to change and the new value to give to it.\r\n\tCComponent *pComp=pParams->GetNextComponent();\r\n\tDbg_MsgAssert(pComp,(\"\\n%s\\nChange function requires a symbol name and new value, eg Change Foo=7\",pScript->GetScriptInfo()));\r\n\tDbg_MsgAssert(pComp->mNameChecksum,(\"\\n%s\\nChange function requires a symbol name and new value, eg Change Foo=7\",pScript->GetScriptInfo()));\r\n\tif (!pComp)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\t// Do a few checks on the old symbol.\r\n\tCSymbolTableEntry *pOld=Script::LookUpSymbol(pComp->mNameChecksum);\r\n\t\r\n\t// Require that the old symbol must exist, otherwise continuing will create the symbol and it will never get deleted,\r\n\t// causing fragmentation & memory leaks etc.\r\n\tif (!pOld)\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"\\n%s\\nTried to change the value of the non-existent symbol '%s'\",pScript->GetScriptInfo(),FindChecksumName(pComp->mNameChecksum)));\r\n\t\treturn false;\r\n\t}\t\r\n\t// Don't allow script symbols to be changed. If this were allowed then all existing CScripts that were running that\r\n\t// script would have to get halted to avoid their PC's becoming invalid, which would require some extra code\r\n\t// and seems kind of a silly thing to want to do anyway.\r\n\tif (pOld->mType==ESYMBOLTYPE_QSCRIPT)\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"\\n%s\\nTried to change the value of the script '%s'\",pScript->GetScriptInfo(),FindChecksumName(pComp->mNameChecksum)));\r\n\t\treturn false;\r\n\t}\t\r\n\t// Don't allow c-function or member function symbols to be changed, cos once changed they'll never be able to be put back.\r\n\tif (pOld->mType==ESYMBOLTYPE_CFUNCTION)\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"\\n%s\\nTried to change the value of the c-function '%s'\",pScript->GetScriptInfo(),FindChecksumName(pComp->mNameChecksum)));\r\n\t\treturn false;\r\n\t}\t\r\n\tif (pOld->mType==ESYMBOLTYPE_MEMBERFUNCTION)\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"\\n%s\\nTried to change the value of the member function '%s'\",pScript->GetScriptInfo(),FindChecksumName(pComp->mNameChecksum)));\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\t// Hmmm, in theory other types could be changed, but they shouldn't be cos it'll cause fragmentation.\r\n\tswitch (pOld->mType)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n        case ESYMBOLTYPE_FLOAT:\r\n        case ESYMBOLTYPE_NAME:\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"\\n%s\\nCannot change the value of '%s' because it has type '%s', and reallocating it will cause memory fragmentation. So there.\",pScript->GetScriptInfo(),FindChecksumName(pComp->mNameChecksum),GetTypeName(pOld->mType)));\r\n\t\t\tbreak;\r\n\t}\t\r\n\t\r\n\t// Remove the old symbol.\r\n\tScript::CleanUpAndRemoveSymbol(pOld);\r\n\r\n\t// Create it afresh.\r\n\tCSymbolTableEntry *pNew=Script::CreateNewSymbolEntry(pComp->mNameChecksum); \r\n\r\n\tCComponent temp;\r\n\ttemp.mType=pComp->mType;\r\n\ttemp.mUnion=pComp->mUnion;\r\n\r\n\t// If they are changing a value to some name, then support the option of resolving that name,\r\n\t// in case it might be a global.\r\n\t// For example, suppose a=6, and b=3.141\r\n\t// 'Change a=b' will change a from 6 to the checksum b. This means it will preserve the reference to b,\r\n\t// so in the C code if a GetFloat(\"a\") is done it will return 3.141, but if b is changed to 28.3, \r\n\t// GetFloat(\"a\") will now return 28.3, because it preserves the reference to b.\r\n\t// However, 'Change a=b Resolve' will change a to be the float 3.141. Even if b is now changed, a has\r\n\t// lost the reference to b and will stay as 3.141.\r\n\tif (temp.mType==ESYMBOLTYPE_NAME)\r\n\t{\r\n\t\tif (pParams->ContainsFlag(CRCD(0x991a7bc3,\"Resolve\")))\r\n\t\t{\r\n\t\t\tCSymbolTableEntry *p_global=Script::Resolve(temp.mChecksum);\r\n\t\t\tif (p_global)\r\n\t\t\t{\r\n\t\t\t\ttemp.mType=p_global->mType;\r\n\t\t\t\ttemp.mUnion=p_global->mUnion;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Copy the new value into the symbol just created.\r\n\tswitch (temp.mType)\r\n\t{\r\n\t\tcase ESYMBOLTYPE_INTEGER:\r\n            pNew->mType=ESYMBOLTYPE_INTEGER;\r\n            pNew->mIntegerValue=temp.mIntegerValue;\r\n            break;\r\n\r\n        case ESYMBOLTYPE_FLOAT:\r\n            pNew->mType=ESYMBOLTYPE_FLOAT;\r\n            pNew->mFloatValue=temp.mFloatValue;\r\n            break;\r\n\r\n        case ESYMBOLTYPE_NAME:\r\n            pNew->mType=ESYMBOLTYPE_NAME;\r\n            pNew->mChecksum=temp.mChecksum;\r\n            break;\r\n\t\t\t\r\n        default:\r\n            Dbg_MsgAssert(0,(\"\\n%s\\nChange function does not support component type '%s'\",pScript->GetScriptInfo(),GetTypeName(temp.mType)));\r\n            break;\r\n\t}\r\n\r\n\t// This is to prevent an assert in the CComponent destructor\r\n\ttemp.mUnion=0;\r\n\t\r\n\treturn true;\t\t\t\t\t\t\t\t\t   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DumpScripts | Prints out the names of all the currently existing scripts.\r\nbool ScriptDumpScripts( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tbool just_stack = pParams->ContainsFlag(\"just_stack\");\r\n\t\r\n\tif (!just_stack)\r\n\t\tScript::DumpScripts();\r\n\t\r\n\t// XXX\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tprintf(\"Script stack is: %s\\n\", pScript->GetScriptInfo());\r\n\t#endif\r\n\t\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | TimeUp | true if time is up\r\nbool ScriptTimeUp( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n     Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\r\n    return skate_mod->GetGameMode()->ShouldUseClock() && ( skate_mod->GetGameMode()->GetTimeLeft() <= 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LaunchViewer | \r\nbool ScriptLaunchViewer( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMdl::Manager * mdl_manager =  Mdl::Manager::Instance();\r\n\tMdl::CViewer* viewer_mod;\r\n\tstatic bool initialized = false;\r\n\t\r\n\tif( initialized )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tviewer_mod = new Mdl::CViewer;\r\n\r\n\tmdl_manager->RegisterModule ( *viewer_mod );\r\n\tmdl_manager->StartModule( *viewer_mod );\r\n\tinitialized = true;\r\n\t\r\n\t\r\n\t// Add the parameters for the skater camera component\t\t\r\n\t// so it can get me as the target\r\n\tScript::CStruct * p_cam_params = new Script::CStruct;\r\n\tp_cam_params->AddChecksum(\"name\",CRCD(0xeb17151b,\"viewer_cam\"));\r\n\t\r\n\t// Also create the camera components here.\r\n\tObj::CCompositeObject *p_cam_object = Obj::CCompositeObjectManager::Instance()->CreateCompositeObjectFromNode(\r\n\t\t\t\t\t\t\t\t\t\tScript::GetArray(\"viewercam_composite_structure\"),p_cam_params);\r\n\t\r\n\tdelete\tp_cam_params;\r\n\tp_cam_object->SetLockOn();\t\t// Lock it so it does not get deleted between levels\r\n\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | LaunchViewer | \r\nbool ScriptLaunchScriptDebugger( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t#ifdef __NOPT_ASSERT__\r\n\tstatic bool initialized = false;\r\n\t\r\n\tif( initialized )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tMdl::Manager::Instance()->StartModule( *Dbg::CScriptDebugger::Instance() );\r\n\t\r\n\tinitialized = true;\r\n\t#endif\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetViewerModel | \r\nbool ScriptSetViewerModel( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();\r\n\r\n\ts_view_mode = (int)Obj::VIEWER_SKATER_PAUSED;\r\n\t\r\n\t// sync the viewer up to cfuncs.cpp's version of s_view_mode\r\n\tpViewer->sSetViewMode( s_view_mode );\r\n\t// Handle toggling to different cameras based on view mode\r\n\t\r\n\tswitch (s_view_mode )\r\n\t{\r\n\t\tcase Obj::GAMEPLAY_SKATER_ACTIVE:\r\n\t\t\tSetActiveCamera(CRCD(0x967c138c,\"skatercam0\"),0, false);\t\t\t\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tSetActiveCamera(CRCD(0xeb17151b,\"viewer_cam\"),0, true);\t\t\t\t\t\t\r\n\t\t\tbreak;\t\t\r\n\t}\r\n\r\n\r\n\tObj::CSkater* pSkater;\r\n\tfor ( int i = 0; i < 8; i++ )\r\n\t{\r\n\t\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\t\tpSkater = skate_mod->GetSkater(i);\t\t\t\t\t\t   \r\n\t\tif ( pSkater )\t\t\t// Skater might not exist\r\n\t\t{\r\n\t\t\tpSkater->SetViewMode( (Obj::EViewMode)s_view_mode );\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( pViewer )\r\n\t{\r\n\t\tpViewer->ResetCameraToViewerObject();\r\n\t\t\r\n\t\tScript::PrintContents(pParams);\r\n\r\n\t\tpViewer->AddViewerObject(pParams);\r\n\r\n\t\t/*\r\n\t\tObj::CViewerObject* pViewerObject = pViewer->GetViewerObject();\r\n\t\tif ( pViewerObject )\r\n\t\t{\r\n\t\t\tpViewerObject->UnloadModel();\r\n\t\t\t\r\n\t\t\tpViewerObject->LoadModel( pParams );\r\n\t\t}\r\n\t\t*/\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetViewerAnim | \r\nbool ScriptSetViewerAnim( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();\r\n\r\n\tif ( pViewer )\r\n\t{\r\n\t\tuint32 animName;\r\n\t\tpParams->GetChecksum( NONAME, &animName, true );\r\n\r\n\t\tObj::CViewerObject* pViewerObject = pViewer->GetViewerObject();\r\n\t\tif ( pViewerObject )\r\n\t\t{\r\n\t\t\tpViewerObject->SetAnim( animName );\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptSetViewerLODDist | \r\nbool ScriptSetViewerLODDist( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();\r\n\r\n\tif ( pViewer )\r\n\t{\r\n\t\tScript::CPair thePair;\r\n\t\tif ( !pParams->GetPair( NONAME, &thePair, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tDbg_Message( \"Looking for pair in the format:  SetViewerLODDist (1,500.0f)\" );\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tObj::CViewerObject* pViewerObject = pViewer->GetViewerObject();\r\n\t\tif ( pViewerObject )\r\n\t\t{\r\n\t\t\tGetModelComponentFromObject( pViewerObject )->SetModelLODDistance( (int)thePair.mX, thePair.mY );\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetViewerObjectID( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t// clear out the viewer object, if any\r\n\tMdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();\r\n\tif ( pViewer )\r\n\t{\r\n\t\tObj::CCompositeObject* pViewerObject = pViewer->GetViewerObject();\r\n\t\tpScript->GetParams()->AddChecksum( CRCD(0x0830ecaf,\"objID\"), pViewerObject->GetID() );\r\n\t\tpScript->GetParams()->AddChecksum( CRCD(0x52280066,\"viewerObjectId\"), pViewerObject->GetID() );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptReloadViewerAnim( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();\r\n\r\n\tif ( pViewer )\r\n\t{\r\n\t\tObj::CViewerObject* pViewerObject = pViewer->GetViewerObject();\r\n\t\tif ( pViewerObject )\r\n\t\t{\r\n\t\t\tuint32 animName;\r\n\t\t\tconst char* fileName;\r\n\r\n\t\t\tif ( pParams->GetChecksum( NONAME, &animName )\r\n\t\t\t\t && pParams->GetText( NONAME, &fileName ) )\r\n\t\t\t{\r\n\t\t\t\tpViewerObject->ReloadAnim( fileName, animName );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tDbg_Message( \"Need 2 parameters to viewer anim:  filename string, and anim checksum\" );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AddRestartsToMenu | adds all restart points to the menu\r\nbool ScriptAddRestartsToMenu( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t\r\n\tScript::CStruct* p_restart_params;\r\n\tint \tnode = -1;\r\n\tint \tentry = 0;\r\n\tdo\r\n\t{\r\n\t\tnode = Obj::GetRestartNode(0, 0, node);\r\n\t\tif (node != -1)\r\n\t\t{\r\n\t\t\tScript::CArray *pNodeArray=Script::GetArray(CRCD(0xc472ecc5,\"NodeArray\"));\r\n\t\t\tScript::CScriptStructure *pNode=pNodeArray->GetStructure(node);\r\n\t\t\tconst char *pName;\r\n\t\t\tif (!pNode->GetText(\"RestartName\",&pName))\r\n\t\t\t{\r\n\t\t\t\tpName = \"Unnamed restart\";\r\n\t\t\t}\r\n\t\t\tp_restart_params = new Script::CStruct;\t\r\n\t\t\tp_restart_params->AddString(\"text\",pName);\r\n\t\t\tp_restart_params->AddChecksum(\"id\",123456 + entry);\r\n\t\t\tp_restart_params->AddChecksum(\"no_bg\",CRCD(0x9f67b2c8,\"no_bg\"));\r\n\t\t\tp_restart_params->AddChecksum(\"centered\",CRCD(0x2a434d05,\"centered\"));\r\n\t\t\tp_restart_params->AddChecksum(\"pad_choose_script\",Script::GenerateCRC(\"skip_to_selected_restart\"));\r\n\t\t\t\r\n\t\t\t// create the parameters that are passed to the X script\r\n\t\t\tScript::CStruct *p_script_params= new Script::CStruct;\r\n\t\t\tp_script_params->AddInteger(\"node_number\",node);\t\r\n\t\t\tp_restart_params->AddStructure(\"pad_choose_params\",p_script_params);\t\t\t\r\n\r\n\t\t\t/*if (!Script::GetInt(\"SimpleRestarts\",false))\r\n\t\t\t{\r\n\t\t\t\tp_restart_params->AddChecksum(\"focus_script\",Script::GenerateCRC(\"preview_restart\"));\r\n\t\t\t\t// also pass it too the Focus script\r\n\t\t\t\tp_restart_params->AddStructure(\"focus_params\",p_script_params);\t\t\t\t\t\t\r\n\t\t\t}*/\r\n\t\t\t\r\n            // scale the restarts\r\n            float initial_scale;\r\n            pParams->GetFloat( \"initial_scale\", &initial_scale, Script::ASSERT );\r\n            p_restart_params->AddFloat( \"scale\", initial_scale );\r\n            //p_restart_params->AddChecksum( \"unfocus_script\", Script::GenerateCRC( \"scale_down_restart\" ) );\r\n\t\t\t\r\n\t\t\tScript::RunScript(\"theme_menu_add_item\",p_restart_params);\r\n\t\t\tdelete p_restart_params;\r\n\t\t\tdelete p_script_params;\r\n\r\n\t\t\tentry++;\r\n\t\t}\r\n\t} while (node != -1);\r\n\r\n\tif (entry == 0)\r\n\t{\r\n\t\t\tp_restart_params = new Script::CStruct;\t\r\n\t\t\tp_restart_params->AddString(\"text\",\"No restarts in level\");\r\n\t\t\tp_restart_params->AddChecksum(\"id\",123456 + entry);\r\n\t\t\tp_restart_params->AddChecksum(\"no_bg\",CRCD(0x9f67b2c8,\"no_bg\"));\r\n\t\t\tp_restart_params->AddChecksum(\"centered\",CRCD(0x2a434d05,\"centered\"));\r\n\t\t\tp_restart_params->AddChecksum(\"pad_choose_script\",Script::GenerateCRC(\"skip_to_selected_restart\"));\r\n\t\t\tScript::RunScript(\"theme_menu_add_item\",p_restart_params);\r\n\t\t\tdelete p_restart_params;\r\n\t}\r\n\r\n\t\r\n\t\r\n\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptAddWarpPointsToMenu( Script::CStruct* pParams, Script::CScript* pScript ) {\r\n    Script::CStruct* p_restart_params;\r\n    \r\n    // grab array of warp points\r\n    Script::CArray *p_Array = NULL;\r\n\r\n    pParams->GetArray( \"nodes\", &p_Array );\r\n    Dbg_MsgAssert(p_Array, (\"AddWarpPointsToMenu requires an array of nodes\"));\r\n    // better only be names\r\n    Dbg_MsgAssert(p_Array->GetType()==ESYMBOLTYPE_NAME,(\"\\n%s\\nnodes: Array must be of names\",pScript->GetScriptInfo()));\r\n    \r\n    \r\n    // add nodes to menu    \r\n    for (uint32 i=0; i<p_Array->GetSize(); ++i) {\r\n\t\t// Obj_MoveToNode name = <nodename> Orient NoReset\r\n        \r\n        p_restart_params = new Script::CStruct;\r\n        \r\n        Script::CScriptStructure *pNode = SkateScript::GetNode( SkateScript::FindNamedNode( p_Array->GetChecksum( i ) ) );\r\n        const char *pName;\r\n        if (!pNode->GetText(\"RestartName\",&pName))\r\n        {\r\n            pName = \"Unnamed restart\";\r\n        }        \r\n        \r\n        p_restart_params->AddString( \"text\", pName );\r\n        p_restart_params->AddChecksum(\"pad_choose_script\",Script::GenerateCRC(\"WarpSkater\"));\r\n\r\n        // create the parameters that are passed to the script\r\n        Script::CStruct *p_script_params = new Script::CStruct;\r\n        p_script_params->AddChecksum( \"nodename\", p_Array->GetChecksum( i ) );\r\n        p_restart_params->AddStructure( \"pad_choose_params\", p_script_params );\r\n\r\n        Script::RunScript( \"make_text_sub_menu_item\", p_restart_params );\r\n        delete p_restart_params;\r\n\r\n    }\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptRunScriptOnObject | allows you to access Obj_ type functions, from a global script\r\nbool ScriptRunScriptOnObject( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t// searches for object by name\r\n\r\n\tuint32 obj_id;\r\n\tpParams->GetChecksum(\"id\", &obj_id, true);\r\n    \r\n\tuint32 scriptName;\r\n\tpParams->GetChecksum(NONAME, &scriptName, true);\r\n\r\n\tScript::CStruct* pSubParams = NULL;\r\n\tpParams->GetStructure(CRCD(0x7031f10c,\"params\"), &pSubParams);\r\n\r\n\tpScript->GetParams()->RemoveComponent(CRCD(0xa2b033fd,\"UniqueID\"));\t\r\n\t\r\n\t // this returns all objects, not just game objects and peds\r\n\tObj::CObject* pObject = Obj::ResolveToObject( obj_id );\r\n\r\n\tif ( pObject )\r\n\t{\r\n\t\t/*\r\n\t\tScript::CScript *pNewScript=Script::SpawnScript(scriptName,pSubParams,0,NULL,scriptName);\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tpNewScript->SetCommentString(\"Spawned by script command RunScriptOnObject\");\r\n\t\tpNewScript->SetOriginatingScriptInfo(pScript->GetCurrentLineNumber(),pScript->mScriptChecksum);\r\n\t\t#endif\t\r\n\t\t\r\n\t\tpNewScript->mpObject = pObject;\r\n\t\t\r\n\t\tpScript->GetParams()->AddChecksum(\"UniqueID\",pNewScript->GetUniqueId());\r\n//\t\tScript::RunScript( scriptName, pSubParams, obj_and_id.pObj );\r\n\r\n\t*/\r\n\t\r\n\t\tif (pObject->GetScript())\r\n\t\t{\r\n\t\t\t// (Mick) If this object has a script, but it's got a NULL mpObject\r\n\t\t\t// that means that script has been cleared in the current game loop\r\n\t\t\t// but not got around to being deleted.\r\n\t\t\t// it's quite safe to re-use it, we just need to set the object on it\r\n\t\t\tif (pObject->GetScript()->mpObject == NULL)\r\n\t\t\t{\r\n\t\t\t\tpObject->GetScript()->mpObject = pObject;\r\n\t\t\t}\r\n\t\t\r\n\t\t\tDbg_MsgAssert(pObject->GetScript()->mpObject == pObject,(\"%s\\nscript object %p not same as object %p\",pScript->GetScriptInfo(),pObject->GetScript()->mpObject.Convert(),pObject));\r\n\t\t}\r\n\t\t// (Mick) Instead of spawning a script, call it on the main script\r\n\t\t// Which allows us to set exceptions and event handlers\r\n\t\t// It's also a lot quicker\r\n\t\t// (Might be problem with parameter conflicts?)\r\n\t\tpObject->CallScript(scriptName, pSubParams);\r\n\t\t\r\n\t\t\r\n\t\treturn true;\r\n\t\r\n\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tprintf( \"Warning: Couldn't find object %s on which to run script %s\\n\", Script::FindChecksumName(obj_id), Script::FindChecksumName(scriptName) );\r\n\t\t#endif\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RunScriptOnComponentType | \r\nbool ScriptRunScriptOnComponentType( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 componentType;\r\n\tpParams->GetChecksum( CRCD(0xb6015ea8,\"component\"), &componentType, Script::ASSERT );\r\n\r\n\tuint32 target;\r\n\tpParams->GetChecksum( CRCD(0xb990d003,\"target\"), &target, Script::ASSERT );\r\n\r\n\tScript::CStruct* pSubParams = NULL;\r\n\tpParams->GetStructure( CRCD(0x7031f10c,\"params\"), &pSubParams, Script::NO_ASSERT );\r\n\r\n\t// new fast way, just go directly to the components, if any\r\n\tObj::CBaseComponent *p_component = Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType( componentType );\r\n\twhile( p_component )\r\n\t{\r\n\t\tp_component->CallMemberFunction( target, pSubParams, pScript );\r\n\t\t\r\n\t\tp_component = p_component->GetNextSameType();\t\t\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | Debounce | This will ignore the specified button\r\n// until either the time has elapsed, or the button has been\r\n// released and subsequently re-pressed. \r\n// For X, this prevents the press of X from carrying over from one\r\n// screen to the next, and removes the need to have a delay,\r\n// whilst still allowing the user to actively X past things\r\n// @uparm X | button name\r\n// @parmopt float | time | 1.0 | time to wait (in seconds)\r\n// @parmopt int | clear | 0 | if 1, then clear the current pressed and triggered states\r\n\t\r\nbool ScriptDebounce( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 ButtonChecksum=0;\r\n\tpParams->GetChecksum(NONAME,&ButtonChecksum);\r\n\tif (!ButtonChecksum)\r\n\t{\r\n\t\treturn true;\r\n\t}\t\r\n\t\r\n\tfloat time=1.0f;\r\n\tpParams->GetFloat(CRCD(0x906b67ba, \"time\"),&time);\r\n\r\n\tint\tclear = 0;\r\n\tpParams->GetInteger(CRCD(0x1a4e0ef9, \"clear\"),&clear);\r\n\t\r\n\tObj::CInputComponent* p_input_component\r\n\t\t= static_cast< Obj::CInputComponent* >(Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType(CRC_INPUT));\r\n\twhile (p_input_component)\r\n\t{\r\n\t\tp_input_component->Debounce(ButtonChecksum, time, clear);\r\n\t\tp_input_component = static_cast< Obj::CInputComponent* >(p_input_component->GetNextSameType());\r\n\t}\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetStatOverride | Set a global stat override for debugging\r\n// set it to 0 to use normal stats\r\nbool ScriptSetStatOverride( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tfloat\tvalue = 0.0f;\r\n\tpParams->GetFloat(NONAME,&value);\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tskate_mod->SetStatOverride(value);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ToggleRails | Toggle the debug display of rails on and off\r\nbool ScriptToggleRails( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tskate_mod->SetDrawRails(!skate_mod->GetDrawRails());\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ToggleRigidBodyDebug | Toggle the debug display of rigidbody characteristics\r\nbool ScriptToggleRigidBodyDebug( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tObj::CRigidBodyComponent::sToggleDrawRigidBodyDebugLines(); \r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CheckForHoles | check the scene file for holes in geometry, and visually display them\r\nbool ScriptCheckForHoles( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tNx::CEngine::sDebugCheckForHoles();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | OnXbox |\r\nbool ScriptOnXbox( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n#ifdef __PLAT_XBOX__\r\n\treturn true;\r\n#else\r\n\treturn false;\r\n#endif\t// __PLAT_XBOX__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GotoXboxDashboard |\r\nbool ScriptGotoXboxDashboard( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n#\tifdef __PLAT_XBOX__\r\n\tLD_LAUNCH_DASHBOARD ld;\r\n    ZeroMemory( &ld, sizeof(ld) );\r\n\r\n\t// In the case where we are rebooting to the memory management section of the dashboard,\r\n\t// this value should contain the total number of blocks needed.\r\n\tuint32 total_blocks_needed = 0;\r\n\r\n\tif( pParams->ContainsFlag( 0x1592cbca /*\"memory\"*/ ))\r\n\t{\r\n\t\tpParams->GetInteger(CRCD(0xb204db86,\"total_blocks_needed\"),(int*)&total_blocks_needed);\r\n\t\t\r\n\t\tld.dwReason\t\t= XLD_LAUNCH_DASHBOARD_MEMORY;\r\n\t\tld.dwParameter1\t= 'U';\r\n\t\tld.dwParameter2\t= total_blocks_needed;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tld.dwReason = XLD_LAUNCH_DASHBOARD_MAIN_MENU;\r\n\t}\r\n\r\n    XLaunchNewImage( NULL, PLAUNCH_DATA( &ld ) );\r\n#\tendif\t// __PLAT_XBOX__\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptSystemLinkEnabled( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n#ifdef __PLAT_XBOX__\r\n\tDWORD result;\r\n\t\r\n\tresult = XNetGetEthernetLinkStatus();\r\n\tif(( result & XNET_ETHERNET_LINK_ACTIVE ) == 0 )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n#endif\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Particle system functions.\r\n// @script | CreateParticleSystem | Creates a particle system.\r\n// @parm name | name | the name of the particle system. (Should be Particle_UnNamed if created from a node)\r\n// @parmopt int | max | 256 | maximum number of particles this system can display.\r\n// @parmopt name | texture | | the name of the texture to apply. No name means use flat shaded.\r\n// @parmopt name | emitscript | | the name of the script to call for emission.\r\n// @parmopt name | updatescript | | the name of the script to call to update position etc.\r\n// @parmopt name | blendmode | diffuse | The blendmode: blend/add/sub/modulate/brighten & \r\n// fixblend/fixadd/fixsub/fixmodulate/fixbrighten & diffuse (no blend at all). Defaults to diffuse.\r\n// @parmopt int | fix | 0 | Fixed alpha value. 128 is normal. Range is 0-255.\r\n// @parmopt name | params | | Sets a parameter block for use with the created particle scripts.\r\n// @parmopt name | type | flat | Sets the type of particle (flat/shaded/smooth/glow). Defaults to flat.\r\n// @parmopt int | segments | 8 | The number of segments in a segmented particle, such as 'Glow'.\r\n// @parmopt float | split | 0.5 | Sets the split point in a segmented particle. 0 = split at center. 1 means split at outer edge.\r\n// @parmopt int | history | 1 | Number of history lists to keep. Minimum is 1 when using trail particle types.\r\n// @parmopt int | perm | 0 | set to 1 if particle system stays between levels (like the skaters)\r\n// update script to grab bone/node positions when attaching.\r\n//\r\n// \r\nbool ScriptCreateParticleSystem( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 name = 0;\r\n\tpParams->GetChecksum(\"Name\",&name);\r\n\r\n\tint max = 256;\r\n\tpParams->GetInteger(\"Max\",&max);\r\n\r\n\tint max_streams = 2;\r\n\tpParams->GetInteger(\"MaxStreams\",&max_streams);\r\n\r\n\tuint32 texture = 0;\r\n\tpParams->GetChecksum(\"Texture\",&texture);\r\n\r\n\tuint32 blendmode = 0x515e298e;\t\t// Defaults to diffuse.\r\n\tpParams->GetChecksum(\"blendmode\",&blendmode);\r\n\t\r\n\tuint32 type = 0xaab555bb;\t\t// Defaults to flat.\r\n\tpParams->GetChecksum(\"type\",&type);\r\n\t\r\n\tint fix = 0;\r\n\tpParams->GetInteger(\"fix\",&fix);\r\n\r\n\tint segments = 8;\r\n\tpParams->GetInteger(\"segments\",&segments);\r\n\r\n\tfloat split = 0.5f;\r\n\tpParams->GetFloat(\"split\",&split);\r\n\r\n\tint history = 1;\r\n\tpParams->GetInteger(\"history\",&history);\r\n\r\n\tint perm = 0;\r\n\tpParams->GetInteger(\"perm\",&perm);\r\n\r\n\t// Create a particle. Will be internally added to the process list, so we don't need to do\r\n\t// anything after it has been created.\r\n\tNx::CParticle * p_particle = Nx::create_particle( name, type, max, max_streams, texture, blendmode, fix, segments, split, history, perm );\r\n\t\r\n\tScript::CStruct* pSubParams = NULL;\r\n\tpParams->GetStructure( \"params\", &pSubParams, Script::NO_ASSERT );\r\n\r\n\tuint32 emitscript = 0;\r\n\tif ( pParams->GetChecksum(\"emitscript\",&emitscript) )\r\n\t{\r\n\t\tp_particle->set_emit_script( emitscript, pSubParams );\r\n\t}\r\n\r\n\t\t\t\t\t\t\t\t\r\n//\tp_particle->SetActive( false );\r\n//\t\t\t\t\t\t\t\t\r\n//\tuint32 active = 0;\r\n//\tif ( pParams->GetChecksum(\"active\",&active) )\r\n//\t{\r\n//\t\tp_particle->SetActive( active );\r\n//\t}\r\n\t\r\n\tuint32 updatescript = 0;\r\n\tif ( pParams->GetChecksum(\"updatescript\",&updatescript) )\r\n\t{\r\n\t\tp_particle->set_update_script( updatescript, pSubParams );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetScript | Sets the emission script.\r\n// @parm name | name | the name of the particle system.\r\n// @parmopt name | emitscript | | the name of the script to call for emission.\r\n// @parmopt name | updatescript | | the name of the script to call to update position etc.\r\n// @parmopt name | params | | Sets a parameter block for use with the created particle scripts.\r\nbool ScriptSetScript( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 name = 0;\r\n\tpParams->GetChecksum(\"Name\",&name);\r\n\r\n\tScript::CStruct* pSubParams = NULL;\r\n\tpParams->GetStructure( \"params\", &pSubParams, Script::NO_ASSERT );\r\n\r\n\tNx::CParticle * p_particle = Nx::get_particle( name );\r\n\tDbg_MsgAssert( p_particle, ( \"Couldn't find the requested particle system.\" ) );\r\n\r\n\tuint32 emitscript = 0;\r\n\tif ( pParams->GetChecksum(\"emitscript\",&emitscript) )\r\n\t{\r\n\t\tp_particle->set_emit_script( emitscript, pSubParams );\r\n\t}\r\n\t\r\n\tuint32 updatescript = 0;\r\n\tif ( pParams->GetChecksum(\"updatescript\",&updatescript) )\r\n\t{\r\n\t\tp_particle->set_update_script( updatescript, pSubParams );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DestroyParticleSystem | Destroys a particle system.\r\n// @parm name | name | the name of the particle system.\r\n// @parmopt int | ifempty | 0 | Set this to 1 if you want the particle system to be destroyed only when empty.\r\nbool ScriptDestroyParticleSystem( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 name = 0;\r\n\tpParams->GetChecksum(\"Name\",&name);\r\n\r\n\tint ifempty = 0;\r\n\tpParams->GetInteger(\"IfEmpty\",&ifempty);\r\n\r\n\tif ( ifempty )\r\n\t{\r\n\t\tNx::destroy_particle_when_empty( name );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNx::destroy_particle( name );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EmptyParticleSystem | Empties the particle system immediately (sets number of particles to 0. \r\n// @parm name | name | the name of the particle system.\r\nbool ScriptEmptyParticleSystem( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 name = 0;\r\n\tpParams->GetChecksum(\"Name\",&name);\r\n\r\n\tNx::CParticle * p_particle = Nx::get_particle( name );\r\n\tDbg_MsgAssert( p_particle, ( \"Couldn't find the requested particle system.\" ) );\r\n\r\n\tp_particle->SetNumParticles( 0 );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ParticleExists | Returns whether the specified particle system exists\r\n// @parm name | name | the name of the particle system.\r\nbool ScriptParticleExists( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 name = 0;\r\n\tif ( !pParams->GetChecksum(\"Name\",&name ) )\r\n\t{\r\n\t\tpParams->GetChecksum(NONAME,&name,Script::ASSERT);\r\n\t}\r\n\r\n\tNx::CParticle * p_particle = Nx::get_particle( name );\r\n\r\n\tif ( p_particle )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StructureContains | true if the structure contains an element\r\n// or flag with the specified name\r\n// @parm structure | structure | the structure to check\r\n// @uparm name | the named param to look for\r\nbool ScriptStructureContains( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tScript::CStruct* p_struct;\r\n\tif ( pParams->GetStructure( \"structure\", &p_struct, Script::NO_ASSERT ) )\r\n\t{\t\r\n\t\t// printf(\"got a structure\\n\");\r\n\t\tuint32 name;\r\n\t\tpParams->GetChecksum( NONAME, &name, Script::NO_ASSERT );\r\n\t\tDbg_MsgAssert( name, ( \"StructureContains called without a param name\" ) );\r\n\t\t// printf(\"checking for a name of %x\\n\", name );\r\n\t\tif ( p_struct->ContainsComponentNamed( name ) )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse\r\n\t\t\treturn p_struct->ContainsFlag( name );\r\n\t}\r\n\t// printf(\"didn't get a structure\\n\");\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetBonePosition | allows you to access Obj_ type functions, from a global script\r\nbool ScriptGetBonePosition( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMth::Vector bonePos;\r\n\tbool success = false;\r\n\t\r\n\t// searches for object by m_id\r\n\tuint32 obj_id;\r\n\tpParams->GetChecksum( CRCD(0x40c698af,\"id\"), &obj_id, Script::ASSERT );\r\n\t\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\t\r\n\tObj::CGeneralManager* pObjectManager = skate_mod->GetObjectManager();\r\n\tDbg_Assert( pObjectManager );\r\n\r\n\tObj::CObject* pObject = pObjectManager->GetObjectByID( obj_id );\r\n\tif ( pObject )\r\n\t{\r\n\t\tDbg_MsgAssert( static_cast<Obj::CMovingObject*>( pObject ), ( \"This function only works on moving objects.\" ) ); \r\n\t\tObj::CMovingObject* pMovingObject = (Obj::CMovingObject*)pObject;\r\n\r\n\t\tuint32 boneName;\r\n\t\tpParams->GetChecksum( CRCD(0xcab94088,\"bone\"), &boneName, Script::ASSERT );\r\n\t\t\r\n\t\tObj::CSkeletonComponent* p_skeleton_component = GetSkeletonComponentFromObject(pMovingObject);\r\n\t\tDbg_Assert(p_skeleton_component);\r\n\t\tsuccess = p_skeleton_component->GetBoneWorldPosition( boneName, &bonePos );\r\n\t}\r\n\t\r\n\t// make sure we have somewhere to return the data\r\n\tDbg_Assert( pScript && pScript->GetParams() );\r\n\tpScript->GetParams()->AddFloat( CRCD(0x7323e97c,\"x\"), bonePos[X] );\r\n\tpScript->GetParams()->AddFloat( CRCD(0x424d9ea,\"y\"), bonePos[Y] );\r\n\tpScript->GetParams()->AddFloat( CRCD(0x9d2d8850,\"z\"), bonePos[Z] );\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ShouldEmitParticles | tests whether the specified particle system is active\r\nbool ScriptShouldEmitParticles( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 name;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &name, Script::ASSERT );\r\n\r\n\tNx::CParticle * p_particle = Nx::get_particle( name );\r\n\r\n\tif ( p_particle )\r\n\t{\r\n\t\treturn p_particle->IsEmitting();\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ParticlesOn | turns on the specified particle system\r\nbool ScriptParticlesOn( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 name;\r\n\tpParams->GetChecksum( \"name\", &name, Script::ASSERT );\r\n\r\n\tNx::CParticle * p_particle = Nx::get_particle( name );\r\n\r\n\tif ( p_particle )\r\n\t{\r\n\t\tp_particle->SetEmitting( true );\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tDbg_MsgAssert( 0, ( \"Couldn't find particle system to turn on\" ) );\r\n\t}\r\n\r\n\treturn ( p_particle != NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ParticlesOff | turns off the specified particle system\r\nbool ScriptParticlesOff( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 name;\r\n\tpParams->GetChecksum( \"name\", &name, Script::ASSERT );\r\n\r\n\tNx::CParticle * p_particle = Nx::get_particle( name );\r\n\r\n\tif ( p_particle )\r\n\t{\r\n\t\tp_particle->SetEmitting( false );\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tDbg_MsgAssert( 0, ( \"Couldn't find particle system to turn off\" ) );\r\n\t}\r\n\r\n\treturn ( p_particle != NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MangleChecksums | adds 2 checksums together and returns the result in \"mangled_id\"\r\n// @parm name | a | First checksum\r\n// @parm name | b | Second checksum\r\n// @parm name | mangled_id | The returned value for the mangled checksum\r\nbool ScriptMangleChecksums( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 a;\r\n\tif ( !pParams->GetChecksum( CRCD(0x174841bc,\"a\"), &a, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tpParams->GetInteger( CRCD(0x174841bc,\"a\"), (int*)&a, Script::ASSERT );\r\n\t}\r\n\t\r\n\tuint32 b;\r\n\tif ( !pParams->GetChecksum( CRCD(0x8e411006,\"b\"), &b, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tpParams->GetInteger( CRCD(0x8e411006,\"b\"), (int*)&b, Script::ASSERT );\r\n\t}\r\n\t\r\n\tuint32 mangled_id = a + b;\r\n\tDbg_Assert( pScript && pScript->GetParams() );\r\n\tpScript->GetParams()->AddChecksum( CRCD(0xfba40626,\"mangled_id\"), mangled_id );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AppendSuffixToChecksum | Appends a string suffix to a checksum and returns the result in \"appended_id\"\r\n// @parm name | Base | The base checksum\r\n// @parm string | SuffixString | The suffix string\r\nbool ScriptAppendSuffixToChecksum( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 base_checksum;\r\n\tpParams->GetChecksum(CRCD(0x3f4b019e, \"Base\"), &base_checksum, Script::ASSERT);\r\n\t\r\n\tconst char* suffix_string;\r\n\tpParams->GetString(CRCD(0x94542eea, \"SuffixString\"), &suffix_string, Script::ASSERT);\r\n\t\r\n\tpScript->GetParams()->AddChecksum(CRCD(0xafb911c6, \"appended_id\"), Crc::ExtendCRCWithString(base_checksum, suffix_string));\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RotateVector | rotates a vector by the specified amount\r\n// @parm float | x | X value of the vector to be rotated (also, the return value)\r\n// @parm float | y | Y value of the vector to be rotated (also, the return value)\r\n// @parm float | z | Z value of the vector to be rotated (also, the return value)\r\n// @parm float | rx | Amount to rotate on X, in degrees\r\n// @parm float | ry | Amount to rotate on Y, in degrees\r\n// @parm float | rz | Amount to rotate on Z, in degrees\r\nbool ScriptRotateVector( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t// get original vector:\r\n\tMth::Vector vec;\r\n\tpParams->GetFloat( \"x\", &vec[X], Script::ASSERT );\r\n\tpParams->GetFloat( \"y\", &vec[Y], Script::ASSERT );\r\n\tpParams->GetFloat( \"z\", &vec[Z], Script::ASSERT );\r\n\tvec[W] = 1.0f;\r\n\r\n\t// get amount to rotate (in degrees)\r\n\tfloat rx = 0.0f;\r\n\tfloat ry = 0.0f;\r\n\tfloat rz = 0.0f;\r\n\tpParams->GetFloat( \"rx\", &rx, Script::NO_ASSERT );\r\n\tpParams->GetFloat( \"ry\", &ry, Script::NO_ASSERT );\r\n\tpParams->GetFloat( \"rz\", &rz, Script::NO_ASSERT );\r\n\r\n\t// rotate the vector\r\n\tMth::Matrix mat;\r\n\tmat.Ident();\r\n\tmat.RotateXLocal( Mth::DegToRad(rx) );\r\n\tmat.RotateYLocal( Mth::DegToRad(ry) );\r\n\tmat.RotateZLocal( Mth::DegToRad(rz) );\r\n\tvec = mat.Transform( vec );\r\n\r\n\t// return the vector\r\n\tpScript->GetParams()->AddFloat( \"x\", vec[X] );\r\n\tpScript->GetParams()->AddFloat( \"y\", vec[Y] );\r\n\tpScript->GetParams()->AddFloat( \"z\", vec[Z] );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsPS2 | Returns true if the current hardware is PS2 (proview/devkit/regular).\r\nbool ScriptIsPS2( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tif (( Config::GetHardware() == Config::HARDWARE_PS2 ) ||\r\n\t\t( Config::GetHardware() == Config::HARDWARE_PS2_PROVIEW ) ||\r\n\t\t( Config::GetHardware() == Config::HARDWARE_PS2_DEVSYSTEM ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsNGC | Returns true if the current hardware is GameCube.\r\nbool ScriptIsNGC( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tif ( ( Config::GetHardware() == Config::HARDWARE_NGC ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsXBOX | Returns true if the current hardware is Xbox.\r\nbool ScriptIsXBOX( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tif ( ( Config::GetHardware() == Config::HARDWARE_XBOX ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsWin32 | Returns true if the current hardware is Win32.\r\nbool ScriptIsWIN32( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tif ( ( Config::GetHardware() == Config::HARDWARE_WIN32 ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetPlatform | Puts the name of the current platform as a checksum into a parameter\r\n// called Platform. The value will be either ps2, xbox, ngc or win32\r\n// Handy for use in script switch statements, rather than having to have nested if's\r\nbool ScriptGetPlatform( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 platform=0;\r\n\t\r\n\tswitch (Config::GetHardware())\r\n\t{\r\n\tcase Config::HARDWARE_PS2:\r\n\tcase Config::HARDWARE_PS2_PROVIEW:\r\n\tcase Config::HARDWARE_PS2_DEVSYSTEM:\r\n\t\tplatform=0x988a3508; // ps2\r\n\t\tbreak;\r\n\tcase Config::HARDWARE_NGC:\r\n\t\tplatform=0xbcf00d45; // ngc\r\n\t\tbreak;\r\n\tcase Config::HARDWARE_XBOX:\r\n\t\tplatform=0x87d839b8; // xbox\r\n\t\tbreak;\r\n\tcase Config::HARDWARE_WIN32:\r\n\t\tplatform=0x4af45e2e; // win32\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\t\r\n\tpScript->GetParams()->AddChecksum(\"Platform\",platform);\t\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptIsPal( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\treturn Config::PAL();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PushMemProfile | push an arbitarily named memory profile (Mick's use only)\r\nbool ScriptPushMemProfile( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t\r\n\tconst char* pContext;\r\n\tpParams->GetText( NONAME, &pContext, true );\r\n\tMem::PushMemProfile((char*)pContext);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PopMemProfile | pop a mem profile that was pushed (Mick's use only)\r\nbool ScriptPopMemProfile( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMem::PopMemProfile();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | TogglePass | Toggle which passes are displayed\r\nbool ScriptTogglePass( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t#ifdef\t__PLAT_NGPS__\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tstatic \tint pass = 0;\r\n\tpass++;\r\n\r\n\t// Let us put a pass value in that will override the toggling value  \r\n\tpParams->GetInteger(CRCD(0x318f2bdb,\"Pass\"),&pass);\r\n\t\r\n\tif (pass == 5)\r\n\t{\r\n\t\tpass = 0;\r\n\t}\r\n\tif (pass)\r\n\t{\r\n\t\tNxPs2::gPassMask1 = 0xc0; \t\t\t// 1<<6 | 1<<7  (0x40, 0x80)\r\n\t\tNxPs2::gPassMask0 = (pass-1)<<6;\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tNxPs2::gPassMask1 = 0;\r\n\t\tNxPs2::gPassMask0 = 0;\r\n\t}\r\n\t#endif\r\n\t#endif\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetScreen | Sets default screen aspect ratio and camera\r\n// @parm float | Aspect | aspect ratio, usually 16/9 (1.777777777) or 4/3 (1.3333333333)\r\n// @parm float | Angle | screen angle in degrees usally 72, or 80 for 16:9 \r\n// @parm int | Letterbox | 0 for non-letterbox, 1 for letterboxed.  Normally used with 4/3 aspect \r\nbool\tScriptSetScreen( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tfloat\tAspect;\r\n\tfloat\tAngle;\r\n\t\r\n\tif (pParams->GetFloat(\"Aspect\",&Aspect))\r\n\t{\r\n\t\tNx::CViewportManager::sSetScreenAspect(Aspect);\r\n\t}\r\n\t\r\n\tif (pParams->GetFloat(\"Angle\",&Angle))\r\n\t{\r\n\t\tNx::CViewportManager::sSetScreenAngle(Angle);\r\n\t}\r\n\t\r\n\tint letterbox;\r\n\tif (pParams->GetInteger(\"Letterbox\",&letterbox))\r\n\t{\r\n\t\tNx::CEngine::sSetLetterbox(letterbox);\r\n\t}\r\n\t\r\n\treturn true;\t   \r\n\t   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetUpperCaseString( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tconst char* initial_string;\r\n\tpParams->GetString( NONAME, &initial_string, Script::ASSERT );\r\n\r\n\tchar new_string[128];\r\n\tstrcpy( new_string, initial_string );\r\n\r\n\tStr::UpperCase( new_string );\r\n\tpScript->GetParams()->AddString( \"UpperCaseString\", new_string );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetGameMode( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n\tuint32 gameMode = skate_mod->GetGameMode()->GetNameChecksum();\r\n\r\n\tpScript->GetParams()->AddChecksum( \"GameMode\", gameMode );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptStartKeyboardHandler( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMdl::FrontEnd* front = Mdl::FrontEnd::Instance();\r\n\tint max_length;\r\n\r\n\tpParams->GetInteger( \"max_length\", &max_length, true );\r\n\tfront->AddKeyboardHandler( max_length );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptEnableKeyboard( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\tSIO::EnableKeyboard( true );\r\n#endif\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptDisableKeyboard( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\tSIO::EnableKeyboard( false );\r\n#endif\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptStopKeyboardHandler( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMdl::FrontEnd* front = Mdl::FrontEnd::Instance();\r\n\r\n\tfront->RemoveKeyboardHandler();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CreateIndexArray | creates an array of ints, where each element\r\n// is equal to its own index\r\n// @uparm 1 | size of array\r\nbool ScriptCreateIndexArray( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tint size;\r\n\tpParams->GetInteger( NONAME, &size, Script::ASSERT );\r\n\r\n\tif ( size < 1 )\r\n\t\tDbg_MsgAssert( 0, ( \"CreateIndexArray called with size less than 1\" ) );\r\n\r\n\tScript::CArray *p_index_array = new Script::CArray();\r\n\tp_index_array->SetSizeAndType( size, ESYMBOLTYPE_INTEGER );\r\n\r\n\tfor ( int i = 0; i < size; i++ )\r\n\t\tp_index_array->SetInteger( i, i );\r\n\r\n\tpScript->GetParams()->AddArray( \"index_array\", p_index_array );\r\n\tScript::CleanUpArray( p_index_array );\r\n\tdelete p_index_array;\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetRescaledTargetValue | \r\n// @parm float | min |  \r\n// @parm float | max | \r\n// @parm float | target | \r\n// @parm float | result | \r\nbool ScriptGetRescaledTargetValue( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tfloat min;\r\n\tfloat max;\r\n\tfloat target;\r\n\tfloat result;\r\n\r\n\tpParams->GetFloat( \"min\", &min, true );\r\n\tpParams->GetFloat( \"max\", &max, true );\r\n\tpParams->GetFloat( \"target\", &target, true );\r\n\r\n\tresult = ( target - min ) / ( max - min );\r\n\r\n\tif ( pParams->ContainsFlag( \"sin_curve\" ) )\r\n\t{\r\n\t\tresult = asinf( result ) * 4096.0f / ( 2.0f * Mth::PI );\r\n\t\r\n\t\tif ( pParams->ContainsFlag( \"backwards\" ) )\r\n\t\t{\r\n\t\t\tresult = 2048.0f - result;\r\n\t\t}\r\n\t}\r\n\r\n//\tDbg_Message( \"min = %f max = %f target = %f result = %f\", min, max, target, result );\r\n\r\n\t// this finds the scaled value between 0.0 and 1.0\r\n\tpScript->GetParams()->AddFloat( \"result\", result );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MenuIsSelected | Checks names in pArray to find selected\r\nbool ScriptMenuIsSelected(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// If there is an array of names, check them.\t\t\r\n\tScript::CArray *pArray=NULL;\r\n\tif (pParams->GetArray(NONAME,&pArray))\r\n\t{\r\n\t\tDbg_MsgAssert(pArray,(\"Eh? NULL pArray?\"));\r\n\t\tfor (uint32 i=0; i<pArray->GetSize(); ++i)\r\n\t\t{\r\n\t\t\tif (MenuIsSelected(pArray->GetNameChecksum(i)))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tuint32 id=0;\r\n\tif (pParams->GetChecksum(NONAME,&id))\r\n\t{\r\n\t\tif (MenuIsSelected(id))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t}\r\n\t\t\t\r\n\treturn false;\t\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetNodeName | Gets the node name of the object running this script, and puts\r\n// it into a parameter called NodeName.\r\n// If there is no such object, it will not add NodeName and will return false.\r\nbool ScriptGetNodeName(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tif (pScript->mpObject)\r\n\t{\r\n\t\tObj::CMovingObject *p_pos_obj = static_cast<Obj::CMovingObject*>(pScript->mpObject.Convert());\r\n\t\tif (p_pos_obj)\r\n\t\t{\r\n\t\t\tif (p_pos_obj->GetID())\r\n\t\t\t{\r\n\t\t\t\tpScript->GetParams()->AddChecksum(\"NodeName\",p_pos_obj->GetID());\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\t\t\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetTesterScript | Sets and starts running the tester script. This is a script which\r\n// will never die and will always be having its update function called every frame.\r\n// Used for auto testing levels.\r\n// SetTesterScript may be called more than once. Any new call will stop the current tester script\r\n// and start the new one.\r\n// If the tester script hits an endscript it still won't die, it will just stick on the endscript\r\n// and not do anything. (This uses negligible processing time)\r\n// @uparm name | The name of the script to run.\r\nbool ScriptSetTesterScript(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 tester_script=0;\r\n\tCStruct *p_params=NULL;\r\n\t\r\n\tpParams->GetChecksum(NONAME,&tester_script);\r\n\tpParams->GetStructure(CRCD(0x7031f10c,\"params\"),&p_params);\r\n\t\r\n\t Mdl::Skate * pSkate =  Mdl::Skate::Instance();\r\n\r\n\tDbg_MsgAssert(pSkate->mp_gameFlow,(\"NULL pSkate->mp_gameFlow ??\"));\r\n\tpSkate->mp_gameFlow->SetTesterScript(tester_script, p_params);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | KillTesterScript | Kills any tester script that is running. \r\n// Returns true if a tester script was running before, false otherwise.\r\nbool ScriptKillTesterScript(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t Mdl::Skate * pSkate =  Mdl::Skate::Instance();\r\n\r\n\tDbg_MsgAssert(pSkate->mp_gameFlow,(\"NULL pSkate->mp_gameFlow ??\"));\r\n\treturn pSkate->mp_gameFlow->KillTesterScript();\r\n}\t\t\t\t\t\t\t\t\t \r\n\r\n// Memory manager related functions\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MemPushContext | \r\n// @uparm 1 | value\r\nbool ScriptMemPushContext( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n//\tMemViewToggle();\r\n\t\r\n\t// 0 is the special case name\r\n\tint Val=0;\t\t\t   \t\t\t// default to 0\r\n\tif ( pParams->GetInteger(NONAME,&Val,false) )\r\n\t{\r\n\t\tif ( Val == 0 )\r\n\t\t{\r\n\t\t\t// is the bottom up heap\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Must specify heap name (instead of number) for MemPushContext (ex: BottomUpHeap)\" ) );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// otherwise, look it up by name\r\n\t\tuint32 whichHeap;\r\n\t\tpParams->GetChecksum( NONAME, &whichHeap, true );\r\n\t\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\t\tMem::Heap* pHeap = mem_man.GetHeap( whichHeap );\r\n\t\tDbg_Assert( pHeap );\r\n\r\n\t\tMem::Manager::sHandle().PushContext( pHeap );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MemPopContext |\r\nbool ScriptMemPopContext( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMem::Manager::sHandle().PopContext();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MemInitHeap |\r\n// @parm name | name | the name of heap to create\r\n// @parm int | size | the size of heap to create\r\nbool ScriptMemInitHeap(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\t\r\n\tconst char* pHeapName;\r\n\tpParams->GetText( \"name\", &pHeapName, true );\r\n\r\n\tint heapSize;\r\n\tpParams->GetInteger( \"size\", &heapSize, true );\r\n\r\n\tuint32 heapName;\r\n\theapName = Script::GenerateCRC( pHeapName );\r\n\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\tDbg_MsgAssert( !mem_man.NamedHeap(heapName, false), ( \"named heap %s already exists\", pHeapName ) )\r\n\tmem_man.InitNamedHeap( heapName, heapSize, pHeapName );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MemDeleteHeap |\r\n// @parm name | name | the name of heap to delete\r\nbool ScriptMemDeleteHeap(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char* pHeapName;\r\n\tpParams->GetText( \"name\", &pHeapName, true );\r\n\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\t\r\n\treturn mem_man.DeleteNamedHeap( Script::GenerateCRC( pHeapName ), false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptMemThreadSafe( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tif (pParams->ContainsFlag( Script::GenerateCRC( \"off\" )))\r\n\t{\r\n\t\tMem::SetThreadSafe( false );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tMem::SetThreadSafe( true );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AnalyzeHeap | analyzes specified heap\r\n// @uparmopt BottomUpHeap | heap to analyze\r\nbool ScriptAnalyzeHeap( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t// GJ:  I am planning to refactor this!\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\tMem::Heap* pHeap = NULL;\r\n\tuint32 whichHeap = Script::GenerateCRC(\"BottomUpHeap\");\r\n\tif ( pParams )\r\n\t{\r\n\t\tpParams->GetChecksum( NONAME, &whichHeap );\r\n\t}\r\n\r\n\tpHeap = mem_man.GetHeap( whichHeap );\r\n\r\n#ifndef __PLAT_NGC__\r\n\tif ( pHeap )\r\n\t{\r\n\t\tMemView_AnalyzeHeap( pHeap );\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PrintMemInfo | displays mem info about specified heap\r\n// @uparmopt BottomUpHeap | which heap to print\r\nbool ScriptPrintMemInfo( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\tMem::Heap* pHeap = NULL;\r\n\tchar buf[64];\r\n\tuint32 whichHeap = Script::GenerateCRC(\"BottomUpHeap\");\r\n\tif ( pParams )\r\n\t{\r\n\t\tpParams->GetChecksum( NONAME, &whichHeap );\r\n\t}\r\n\t\r\n\tpHeap = mem_man.GetHeap( whichHeap );\r\n\tstrcpy( buf, mem_man.GetHeapName( whichHeap ) );\r\n\r\n\tif ( pHeap )\r\n\t{\r\n\t\tprintf(  \"\\n\" );\r\n\r\n\t\tprintf( \"%s:\\n\", buf );\r\n\t\tprintf( \"Used %dK (%d) Peak %dK (%d)\\n\",\r\n\t\t\t\tpHeap->mUsedMem.m_count / 1024,\r\n\t\t\t\tpHeap->mUsedBlocks.m_count,\r\n\t\t\t\tpHeap->mUsedMem.m_peak / 1024,\r\n\t\t\t\tpHeap->mUsedBlocks.m_peak );\r\n\t\tprintf( \"Frag %dK (%d) Peak %dK (%d)\\n\",\r\n\t\t\t\tpHeap->mFreeMem.m_count / 1024,\r\n\t\t\t\tpHeap->mFreeBlocks.m_count,\r\n\t\t\t\tpHeap->mFreeMem.m_peak / 1024,\r\n\t\t\t\tpHeap->mFreeBlocks.m_peak );\r\n\r\n\t\tprintf(  \"\\n\" );\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DisplayFreeMem | displays free mem info of specified heap\r\nbool ScriptDisplayFreeMem( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\r\n\tMem::Heap* heap;\r\n   \r\n\tScript::CStruct* params;\r\n\r\n\tparams = new Script::CStruct;\r\n\tfor (heap = mem_man.FirstHeap(); heap != NULL; heap = mem_man.NextHeap(heap))\r\n\t{\t\t\r\n\t\t\tMem::Region* region = heap->ParentRegion();\t\t\t\r\n\t\t\t\r\n\t\t\tparams->Clear();\r\n\t\t\t\r\n\t\t\tparams->AddChecksum( \"id\", Script::GenerateCRC( heap->GetName() ) );\r\n\t\t\tparams->AddInteger( \"free_mem\", region->MemAvailable() );\r\n\t\t\tparams->AddInteger( \"min_free_mem\", region->MinMemAvailable() );\r\n\r\n\t\t\tScript::RunScript( \"UpdateDisplayFreeMemory\", params );\r\n\t\t\t\r\n\t}\r\n\r\n\tdelete params;\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DumpHeaps | prints out heap contents\r\n// @flag ExactValues | Prints the exact heap sizes in bytes.\r\nbool ScriptDumpHeaps( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n#\tif !defined( __PLAT_NGC__ ) || ( defined( __PLAT_NGC__ ) && !defined( __NOPT_FINAL__ ) )\r\n\r\n\tScript::DumpLastStructs();\r\n\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\r\n#\tifndef __PLAT_XBOX__\r\n#ifndef __PLAT_NGC__\r\n\tchar buf[512];\r\n#endif\t\t// __PLAT_NGC__\r\n#\tendif\r\n\r\n\tMem::Heap* heap;\r\n\r\n#\tifndef __PLAT_XBOX__\r\n#ifndef __PLAT_NGC__\r\n\tdump_open(\"blah.txt\");\r\n#endif\t\t// __PLAT_NGC__\r\n#\tendif\r\n\r\n\tif (pParams->ContainsFlag(CRCD(0xd65b9ac7,\"ExactValues\")))\r\n\t{\r\n\t\tprintf(\"Name              Used    Frag    Free    Min Blocks\\n\");\r\n\t\tprintf(\"--------------- ------ ------- ------- ------ ------\\n\");\r\n\t\tfor (heap = mem_man.FirstHeap(); heap != NULL; heap = mem_man.NextHeap(heap))\r\n\t\t{\t\t\r\n\t\t\t\tMem::Region* region = heap->ParentRegion();\t\t\t\r\n\t\t\t\tprintf( \"%12s: %8d %7d %7d %7d  %5d \\n\",\r\n\t\t\t\t\t\theap->GetName(),\r\n\t\t\t\t\t\theap->mUsedMem.m_count ,\r\n\t\t\t\t\t\theap->mFreeMem.m_count ,\r\n\t\t\t\t\t\tregion->MemAvailable() ,\r\n\t\t\t\t\t\tregion->MinMemAvailable() ,\r\n\t\t\t\t\t\theap->mUsedBlocks.m_count\r\n\t\t\t\t\t\t);\t\t\t\t\t\t\t\t\t\t\r\n\t\t}\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tprintf(\"Name            Used  Frag  Free   Min  Blocks\\n\");\r\n\t\tprintf(\"--------------- ----- ----- ---- ------ ------\\n\");\r\n\t\tfor (heap = mem_man.FirstHeap(); heap != NULL; heap = mem_man.NextHeap(heap))\r\n\t\t{\t\t\r\n\t\t\t\tMem::Region* region = heap->ParentRegion();\t\t\t\r\n\t\t\t\tprintf( \"%12s: %5dK %4dK %4dK %4dK  %5d \\n\",\r\n\t\t\t\t\t\theap->GetName(),\r\n\t\t\t\t\t\theap->mUsedMem.m_count / 1024,\r\n\t\t\t\t\t\theap->mFreeMem.m_count / 1024,\r\n\t\t\t\t\t\tregion->MemAvailable() / 1024,\r\n\t\t\t\t\t\tregion->MinMemAvailable() / 1024,\r\n\t\t\t\t\t\theap->mUsedBlocks.m_count\r\n\t\t\t\t\t\t);\t\t\t\t\t\t\t\t\t\t\r\n\t\t}\r\n\t}\r\n\r\n#\tifndef __PLAT_XBOX__\r\n#ifndef __PLAT_NGC__\r\n\tdump_close();\r\n#endif\t\t// __PLAT_NGC__\r\n#\tendif\r\n\t\r\n\tSfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\tprintf( \"\\nSound mem free %d K  (%d bytes)\\n\", \r\n\t\t sfx_manager->MemAvailable() / 1024, sfx_manager->MemAvailable() );\r\n\r\n#\tifndef __PLAT_XBOX__\r\n#ifndef __PLAT_NGC__\r\n\tchar fileName[256];\r\n\tint i = 0;\r\n\twhile ( TRUE )\r\n\t{\r\n\t\t// The filename is formed from the level name a number, and the free memory\r\n\t\t// you should sort them by DATE, and not by filename\r\n\t\t// \r\n\t\tsprintf( fileName, \"dumps\\\\%s_dump_%02d_%s.txt\",\r\n\t\t\t\t\t\t   s_level_name,\r\n//\t\t\t\t\t\t   __nDATE__,\r\n\t\t\t\t\t//\t   __nTIME__,\r\n\t\t\t\t\t\t   i,\r\n\t\t\t\t\t\t   Str::PrintThousands((mem_man.BottomUpHeap()->ParentRegion()->MemAvailable())) );\r\n\r\n\t\tprintf (\"Filename = <%s>, %d chars\\n\",fileName,strlen(fileName));\r\n\t\t\t\t\t\t   \r\n\t\tif ( FALSE == File::Exist( fileName ))\r\n\t\t\tbreak;\r\n\r\n\t\ti++;\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n#\tendif // __PLAT_XBOX__\r\n\r\n#\tifndef __PLAT_XBOX__\r\n#ifndef __PLAT_NGC__\r\n\tif( dump_open(fileName))\r\n\t{\r\n\t\tsprintf(buf,\"Name            Used  Frag  Free   Blocks\\n\");\r\n\t\tdump_printf(buf);\r\n\t\tsprintf(buf,\"--------------- ----- ----- ------ ------\\n\");\r\n\t\tdump_printf(buf);\r\n\t\tfor (heap = mem_man.FirstHeap(); heap != NULL; heap = mem_man.NextHeap(heap))\r\n\t\t{\t\t\r\n\t\t\t\tMem::Region* region = heap->ParentRegion();\t\t\t\r\n\t\t\t\tsprintf(buf, \"%12s: %5dK %4dK %4dK   %5d \\n\",\r\n\t\t\t\t\t\theap->GetName(),\r\n\t\t\t\t\t\theap->mUsedMem.m_count / 1024,\r\n\t\t\t\t\t\theap->mFreeMem.m_count / 1024,\r\n\t\t\t\t\t\tregion->MemAvailable() / 1024,\r\n\t\t\t\t\t\theap->mUsedBlocks.m_count\r\n\t\t\t\t\t\t);\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\tdump_printf(buf);\r\n\t\t}\r\n\t\tsprintf( buf, \"\\nSound mem free %d K  (%d bytes)\\n\\n\\n\", \r\n\t\t\t sfx_manager->MemAvailable() / 1024, sfx_manager->MemAvailable() );\r\n\t\tdump_printf(buf);\r\n\t\r\n\t\tsprintf(buf,\"Summary\\n----------\\n\\n\");\r\n\t\tdump_printf(buf);\r\n\t\tMem::DumpMemProfile(3);\r\n\t\tsprintf(buf,\"\\n\\nDetails\\n----------\\n\\n\");\r\n\t\tdump_printf(buf);\r\n\t\tMem::DumpMemProfile(100);\r\n\r\n\t\tdump_close();\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n#\tendif //__PLAT_XBOX__\r\n\r\n\tprintf(\"\\nScript pool usage:\\n\");\r\n\tprintf(\"CStruct:           %5d of %5d, max %5d\\n\",CStruct::SGetNumUsedItems(),CStruct::SGetTotalItems(),CStruct::SGetMaxUsedItems());\r\n\tprintf(\"CComponent:        %5d of %5d, max %5d\\n\",CComponent::SGetNumUsedItems(),CComponent::SGetTotalItems(),CComponent::SGetMaxUsedItems());\r\n\tprintf(\"CSymbolTableEntry: %5d of %5d, max %5d\\n\",CSymbolTableEntry::SGetNumUsedItems(),CSymbolTableEntry::SGetTotalItems(),CSymbolTableEntry::SGetMaxUsedItems());\r\n\tprintf(\"CVector:           %5d of %5d, max %5d\\n\",CVector::SGetNumUsedItems(),CVector::SGetTotalItems(),CVector::SGetMaxUsedItems());\r\n\tprintf(\"CPair:             %5d of %5d, max %5d\\n\",CPair::SGetNumUsedItems(),CPair::SGetTotalItems(),CPair::SGetMaxUsedItems());\r\n\tprintf(\"CArray:            %5d of %5d, max %5d\\n\",CArray::SGetNumUsedItems(),CArray::SGetTotalItems(),CArray::SGetMaxUsedItems());\r\n\tprintf(\"CScript:           %5d of %5d, max %5d\\n\",CScript::SGetNumUsedItems(),CScript::SGetTotalItems(),CScript::SGetMaxUsedItems());\r\n\tMem::CCompactPool *p_hash = Mem::PoolManager::SGetPool(Mem::PoolManager::vHASH_ITEM_POOL);\r\n\tprintf(\"CHashItem:         %5d of %5d, max %5d\\n\",p_hash->GetNumUsedItems(),p_hash->GetTotalItems(),p_hash->GetMaxUsedItems());\r\n\tprintf(\"\\n(HashItems are init in main.cpp, others are in init.cpp)\\n\");\r\n#endif\t\t// __NOPT_FINAL__\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DumpFragments | prints out heap fragments\r\nbool ScriptDumpFragments( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tint maxFragmentation = 10000;\r\n\tpParams->GetInteger( NONAME, &maxFragmentation, Script::NO_ASSERT );\r\n\r\n\tif ( pParams->ContainsFlag( \"K\" ) )\r\n\t{\r\n\t\tmaxFragmentation *= 1024;\r\n\t}\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\t\r\n\t// sanity checks for fragmentation\r\n\tMem::Heap* heap = mem_man.BottomUpHeap();\r\n\tint fragmentation = heap->mFreeMem.m_count;\r\n\t\r\n\tif (fragmentation > maxFragmentation)\r\n\t{\r\n\t\t// not guaranteed to do anything useful.... might crash the debugger (Mick)\r\n\t\tprintf (\"Dumping Fragments.....\\n\");\r\n\t\tMemView_DumpFragments(heap);\r\n\t\tprintf (\"Done Dumping Fragments.....\\n\");\r\n\t}\r\n\t\r\n\tDbg_MsgAssert(fragmentation < maxFragmentation, (\"Excessive bottom up fragmentation (%d) after cleanup (max=%d)\",fragmentation,maxFragmentation)); \r\n\t\r\n\theap = mem_man.TopDownHeap();\r\n\tfragmentation = heap->mFreeMem.m_count;\r\n\tif (fragmentation > maxFragmentation)\r\n\t{\r\n\t\t// not guaranteed to do anything useful.... might crash the debugger (Mick)\r\n\t\tprintf (\"Dumping Fragments.....\\n\");\r\n\t\tMemView_DumpFragments(heap);\r\n\t\tprintf (\"Done Dumping Fragments.....\\n\");\r\n\t}\r\n\t\r\n\tDbg_MsgAssert(fragmentation < maxFragmentation, (\"Excessive top down fragmentation (%d) after cleanup (max=%d)\",fragmentation,maxFragmentation)); \r\n#endif\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptClearStruct( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 structName;\r\n\tpParams->GetChecksum( \"struct\", &structName, Script::ASSERT );\r\n\r\n\tScript::CStruct* pStruct = Script::GetStructure( structName, Script::ASSERT );\r\n\tpStruct->Clear();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptAppendStruct( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 structName;\r\n\tpParams->GetChecksum( \"struct\", &structName, Script::ASSERT );\r\n\r\n\tuint32 fieldName;\r\n\tpParams->GetChecksum( \"field\", &fieldName, Script::ASSERT );\r\n\t\r\n\tScript::CStruct* pAppendParams;\r\n\tpParams->GetStructure( \"params\", &pAppendParams, Script::ASSERT );\r\n\r\n\tScript::CStruct* pSubStruct = new Script::CStruct;\r\n\tpSubStruct->AppendStructure( pAppendParams );\r\n\t\r\n\tScript::CStruct* pStruct = Script::GetStructure( structName, Script::ASSERT );\r\n\tpStruct->AddStructurePointer( fieldName, pSubStruct ); \r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptScriptExists( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 script_name_checksum=0;\r\n\tpParams->GetChecksum(NONAME,&script_name_checksum);\r\n\r\n\tCSymbolTableEntry *p_entry=Resolve(script_name_checksum);\r\n\tif (p_entry && p_entry->mType==ESYMBOLTYPE_QSCRIPT)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptSpawnSecondControllerCheck( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t Mlp::Manager * mlp_manager =  Mlp::Manager::Instance();\r\n\tint not_used;\r\n\r\n\tif( s_second_controller_check_task != NULL )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tnot_used = 0;\r\n\ts_second_controller_check_task = new Tsk::Task< int > ( s_second_controller_check_code, not_used );\r\n\tmlp_manager->AddLogicTask ( *s_second_controller_check_task );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptStopSecondControllerCheck( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tDbg_Assert( s_second_controller_check_task != NULL );\r\n\r\n\tdelete s_second_controller_check_task;\r\n\ts_second_controller_check_task = NULL;\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LoadExecPS2 | \r\n// @parm string | elf | elf file to load\r\n// if this fails on a TOOL turn off SN profiling in main.cpp\r\n// and check the media type in prepare_to_exit\r\nbool ScriptLoadExecPS2( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tconst char* p_string;\r\n\tpParams->GetText( \"elf\", &p_string, true );\r\n    Sys::LoadExec( p_string );\r\n#endif // __PLAT_NGPS__\r\n\t\r\n    return true;\t\t// actually will never get here}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\n- TODO - factor out the common functionality of ExitDemo into LoadExecPS2\r\n\r\nthe LoadExecPS2() references lists some common gotchas:\r\n\r\nThe total size of the character strings for the filename and all of the\r\narguments must not exceed 256 bytes. \r\n\r\nNote the following points before calling LoadExecPS2(). \r\n* Terminate or delete all threads other than the thread that will \r\n  execute LoadExecPS2(). \r\n* Cancel all callbacks and interrupt handlers. \r\n* Execute scePadEnd(). \r\n* Execute sceSifExitCmd().\r\n*/\r\n\r\nbool ScriptExitDemo( Script::CStruct*, Script::CScript* )\r\n{\r\n#ifdef __PLAT_NGPS__\r\n    Sys::ExitDemo();\r\n#endif\r\n\r\n\treturn true;\t\t// actually will never get here\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptIsArray( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tScript::CArray* pTest = NULL;\r\n\tif ( pParams->GetArray( NONAME, &pTest, Script::NO_ASSERT ) )\r\n\t\treturn true;\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UseUserSoundtrack | xbox only - uses a certain soundtrack\r\n// @uparm 1 | the soundtrack number\r\nbool ScriptUseUserSoundtrack( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tDbg_MsgAssert( Config::GetHardware() == Config::HARDWARE_XBOX, ( \"UseUserSoundtrack should only be called on the XBox\" ) );\r\n\t\r\n\tint soundtrack;\r\n\tpParams->GetInteger( NONAME, &soundtrack, Script::ASSERT );\r\n\tPcm::UseUserSoundtrack( soundtrack );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UseStandardSoundtrack | xbox only - use the standard soundtrack\r\nbool ScriptUseStandardSoundtrack( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tDbg_MsgAssert( Config::GetHardware() == Config::HARDWARE_XBOX, ( \"UseStandardSoundtrack should only be called on XBox\" ) );\r\n\tPcm::UseStandardSoundtrack();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | DisableReset | ngc only - disable the reset button. If the user presses reset when disabled, a screen will be displayed until it is enabled, and it will reset.\r\nbool ScriptDisableReset( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n#ifdef __PLAT_NGC__\r\n\t//printf(\"DisableReset ...\\n\");\r\n\tNxNgc::EngineGlobals.disableReset = true;\r\n#endif\t\t// __PLAT_NGC__ \r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EnableReset | ngc only - enable the reset button. If reset was pressed while disabled, it will now reset.\r\nbool ScriptEnableReset( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n#ifdef __PLAT_NGC__\r\n\t//printf(\"WARNING! EnableReset ...\\n\");\r\n\r\n\tNxNgc::EngineGlobals.disableReset = false;\r\n#endif\t\t// __PLAT_NGC__ \r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetToIPL | ngc only - resets to IPL screen.\r\nbool ScriptResetToIPL( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n#ifdef __PLAT_NGC__\r\n\tNxNgc::EngineGlobals.resetToIPL = true;\r\n#endif\t\t// __PLAT_NGC__ \r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptInitAnimCompressTable( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tconst char* pFileName;\r\n\tpParams->GetText( NONAME, &pFileName, Script::ASSERT );\r\n\r\n\tuint32 compressTableName;\r\n\tpParams->GetChecksum( NONAME, &compressTableName, Script::ASSERT );\r\n\r\n\tchar filename[256];\r\n\tsprintf( filename, \"%s\", pFileName );//, Nx::CEngine::sGetPlatformExtension() );\r\n\r\n\tswitch ( compressTableName )\r\n\t{\r\n\t\tcase 0xc6a56fe3:\t// q48\r\n\t\t{\r\n\t\t\tGfx::InitQ48Table( filename );\r\n\t\t}\r\n\t\tbreak;\r\n\t\t\r\n\t\tcase 0xc06ead08:\t// t48\r\n\t\t{\r\n\t\t\tGfx::InitT48Table( filename );\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Unrecognized compress table name %s\", Script::FindChecksumName(compressTableName) ) );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Test_Composite is a test array of structures\r\n// that are the components of the composite object, and the parameters passed to it\r\n/*\r\ntest_composite = [\r\n    {\r\n        component = model\r\n        model = \"gameobjects\\skate\\letter_a\\letter_a.mdl\"\r\n    }\r\n    \r\n    {\r\n        component = exceptions\r\n    }\r\n    \r\n    {\r\n        component = bouncyphysics\r\n        bounce = 2\r\n    }\r\n   {\r\n    components = [model, exceptions, explodingphysics]\r\n    model = \"gameobjects\\skate\\letter_a\\letter_a.mdl\"\r\n    bounce = 2\r\n   \r\n} \r\n]\r\n*/\r\n\t\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptCreateCompositeObject( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t// Required array of structures containing \"component=\"\r\n\tScript::CArray*\tp_array = NULL;\r\n\tpParams->GetArray(CRCD(0x11b70a02,\"components\"),&p_array,Script::ASSERT);\r\n\r\n\t// Optional extra structure of parameters that override any provided in the array\t\r\n\tScript::CStruct* p_struct = NULL;\r\n\tpParams->GetStructure(CRCD(0x7031f10c,\"params\"),&p_struct);\r\n\t\r\n\tObj::CCompositeObjectManager::Instance()->CreateCompositeObjectFromNode(p_array, p_struct);\r\n\t\r\n\treturn true;\r\n}\t  \r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the id of an object, and a structure, \r\nbool ScriptRefreshObject( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AutoRail |\r\n// auto-generates rails based of the level's collidable geometry\r\n// @parmopt float | min_rail_edge_angle | 30.0 |\r\n// rails are created only on edges as least as sharp as this angle\r\n// @parmopt float | max_rail_angle_of_assent | 45.0 |\r\n// rails are created only on edges less steep than this angle\r\n// @parmopt float | min_railset_length | 36.0 |\r\n// autorail attempts to join contiguous edges together in order to determine the effective length of a curved rail;\r\n// once this is done, rails shorter than this length in inches are dropped\r\n// @parmopt float | min_edge_length | 0.0 |\r\n// edges below this length in inches are not considered for rail creation, even if they could be part of a curved rail\r\n// @parmopt float | max_corner_in_railset | 50.0 |\r\n// maximum angle between two edges for them to be connected as a curved rail\r\n// @parmopt float | connection_slop | 0.1 |\r\n// slop distance allowed between rail endpoints below which those rails will be snapped togeather\r\n// @parmopt float | farthest_degenerate_rail | 12.0 |\r\n// auto-generated rails\twithin this distance in inches of an old rail will not be created\r\n// @parmopt float | max_degenerate_rail_angle | 20.0 |\r\n// if the angle between an auto-generated rail and a nearly old rail is below this angle, the auto-generated rail will not be created\r\n// @parmopt float | max_low_curb_height | 8.0 |\r\n// curbs below this height in inches are not given rails; controls the low-curb collision feeler length\r\n// @parmopt float | vertical_feeler_length | 60.0 |\r\n// length in inches of the vertical collision feeler\r\n// @parmopt float | crossbar_feeler_length | 12.0 |\r\n// length in inches of the crossbar collision feeler\r\n// @parmopt float | crossbar_feeler_elevation | 12.0 |\r\n// height in inches of the crossbar collision feeler\r\n// @parmopt float | curb_feeler_angle_of_assent | 30.0\t|\r\n// low-curb collision feeler radiates from the rail at this angle above the bordering faces\r\n// @parmopt float | feeler_increment | 36.0 |\r\n// collision feelers are used at each step of this distance in inches along the rail\r\n// @flag no_feelers |\r\n// turns off the checking of the volume around rails by collision feelers\r\n// otherwise this checking is done in order to insure that a rail is not cramped or on a low curb\r\n// @flag no_vertical_feeler |\r\n// turns off the collision feeler which radiates upward from the rail\r\n// @flag no_crossbar_feeler |\r\n// turns off the collision feeler which lies just above the rail and runs perpendicular to it\r\n// @flag no_low_curb_feeler |\r\n// turns off the collision feelers which radiate from the rail just above the bordering faces;\r\n// these collision feelers are used to insure rails are not created on low curbs\r\n// @flag overwrite |\r\n// deletes old rails before auto-generating rails\r\nbool ScriptAutoRail( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMdl::Skate::Instance()->GetRailManager()->AutoGenerateRails(pParams);\r\n\treturn true;\t\t\t  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptInside(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tDbg_MsgAssert(Mdl::Skate::Instance()->mpProximManager->IsInsideFlagValid(), (\"Inside called outside of a proxim trigger script or within a proxim trigger script with a ProximObject\"));\r\n    return Mdl::Skate::Instance()->mpProximManager->IsInside(); \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptSetSpecialBarColors(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    int skater_num;\r\n    pParams->GetInteger( \"skater\", &skater_num, Script::ASSERT );\r\n    \r\n    Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n    Obj::CSkater* pSkater = pSkate->GetSkater( skater_num );\r\n    Mdl::Score *pScore = pSkater->GetScoreObject();\r\n\r\n    pScore->setSpecialBarColors();\r\n    return true;\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tScriptGetMetrics(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n// get various metrics into a structure for display\r\n// You can run this on a spawned script to see in the viewer\r\n\r\n\tScript::CStruct *p_metrics = new Script::CStruct();\r\n\tNx::CEngine::sGetMetrics(p_metrics);\r\n\t\r\n\tScript::CStruct *p_script_params = pScript->GetParams(); \t\t\t\t   \r\n\tp_script_params->AddStructure(\"Metrics\",p_metrics);\r\n\t\r\n\treturn true;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tScriptMoveNode(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n   \t// Given a name and a position, move the node to that position\r\n\t// This can only be applied to one node at once, as it's an absolute position\r\n\t// So we just do everything here.\r\n\r\n\tuint32\tname;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tif ( ! pParams->GetChecksum(CRCD(0xa1dc81f9,\"name\"),&name) )\r\n\t{\r\n\t\tprintf (\"Missing Name\\n\");\r\n\t\treturn false;\r\n\t}\r\n\r\n\tint node_num = SkateScript::FindNamedNode( name, false );\r\n\tif( node_num == -1 )\r\n\t{\r\n\t\tDbg_Printf( \"MoveNode failed. Could not find node %p in the scene\\n\", name );\r\n\t\treturn false;\r\n\t}\r\n\tScript::CStruct *pNode = SkateScript::GetNode( node_num );\r\n\t\r\n\tMth::Vector new_pos, old_pos;\r\n\t\r\n  \tif ( !pParams->GetVector(CRCD(0xb9d31b0a,\"position\"),&new_pos)\r\n\t\t && !pParams->GetVector(CRCD(0x7f261953,\"pos\"),&new_pos) )\r\n\t{\r\n\t\tprintf(\"Missing position parameter in MoveNode\\n\");\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif ( !pNode->GetVector(CRCD(0xb9d31b0a,\"position\"),&old_pos)\r\n\t\t && !pNode->GetVector(CRCD(0x7f261953,\"pos\"),&old_pos) )\r\n\t{\r\n\t\tprintf(\"node is missing position\\n\");\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\t// Move the original node \r\n\t// GJ:  i'm pretty sure that the following is incorrect,\r\n\t// and that the Z component needs to be negated, but since we don't\r\n\t// actually reference the \"position\" component after the object has\r\n\t// been created, the bug has slipped through the cracks...  we're\r\n\t// switching over to the new-style \"pos\" vector anyway\r\n//\tpNode->AddVector(CRCD(0xb9d31b0a,\"position\"),new_pos[X],new_pos[Y],new_pos[Z]);\r\n\tpNode->AddVector(CRCD(0x7f261953,\"pos\"),new_pos[X],new_pos[Y],new_pos[Z]);\r\n\r\n\t// Now look for the node type, and handle the mode for each type of thing\r\n\r\n\tObj::CCompositeObject * p_object = (Obj::CCompositeObject *) Obj::CCompositeObjectManager::Instance()->GetObjectByID(name);\r\n\r\n\tif (p_object)\r\n\t{\r\n\t\t// Might also have to set the pos of the components\r\n\t\t// as they can store internal absolute positions\r\n\t\t// and the pos of the object is only used for display\r\n\t\tp_object->SetPos(new_pos);\r\n\t}\r\n\r\n\tuint32 ClassChecksum = 0;\r\n\tpNode->GetChecksum( 0x12b4e660 /*\"Class\"*/, &ClassChecksum );\r\n\tswitch (ClassChecksum)\r\n\t{\r\n\t\tcase 0xe47f1b79: //vehicle\r\n\t\t\tbreak;\r\n\t\r\n\t\tcase 0xa0dfac98:  //pedestrian\r\n\t\tcase 0x61a741e:  // ped\r\n//\t\t\tObj::CreatePed( skate_mod->GetObjectManager(), nodeIndex );\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0xef59c100:  //gameobject\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase 0x19b1e241: // ParticleEmitter\t\t\r\n\t\t\t{\r\n\t\t\t\tNx::CParticle * p_particle = Nx::get_particle( name );\r\n\t\t\t\tif (p_particle)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_particle->Refresh();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0xb7b3bd86:  // LevelObject\r\n\t\t\t{\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\r\n\t\tcase 0xbf4d3536:  // LevelGeometry\r\n\t\t{\r\n\t\t\t/*Dbg_MsgLog((\"LevelGeometry\"));\r\n\t\t\tuint32 checksumName = 0;\r\n\t\t\tif ( pNode->GetChecksum( 0xa1dc81f9, &checksumName ) ) // checksum 'name'\r\n\t\t\t{\r\n//\t\t\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(checksumName);\r\n\t\t\t\t// We only want to get sectors from the main scene, as that is what the node array applies to\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\tNx::CScene * p_main_scene = Nx::CEngine::sGetMainScene();\r\n\t\t\t\tNx::CSector *p_sector = p_main_scene->GetSector(checksumName);\r\n\t\t\t\tif (p_sector)\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(p_sector,(\"sGetSector(0x%x) returned NULL (%s)\",checksumName,Script::FindChecksumName(checksumName)));\r\n\t\t\t\t\tp_sector->SetWorldPosition(new_pos);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf(\" WARNING: sGetSector(0x%x) returned NULL (%s)\\n\",checksumName,Script::FindChecksumName(checksumName));\r\n\t\t\t\t}\r\n\t\t\t\t//Bsp::ClearWorldSectorFlag( checksumName, mSD_KILLED | mSD_NON_COLLIDABLE | mSD_INVISIBLE  | mSD_INVISIBLE2);\r\n\t\t\t}*/\r\n\t\t\tbreak;\r\n \t\t}\r\n\r\n\t\tcase CRCC(0x30c19600, \"ClimbingNode\"):\r\n\t\tcase 0x8e6b02ad:  // railnode\r\n\t\t\tMdl::Skate::Instance()->GetRailManager()->MoveNode( node_num, new_pos );\r\n\t\t\tbreak;\t\t\t\r\n\t\tcase 0x8470f2e:  // proximnode\r\n//\t\t\tObj::Proxim_SetActive( nodeIndex, true );\r\n\t\t\tbreak;\t\t\t\r\n\t\tdefault:\r\n\t\t\treturn ( false );\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\treturn true;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\t \r\n// @script | SetActiveCamera |\r\n// Sets the active camera to be the camera component of this object\r\n// @parmopt checksum | id | 0 | \r\n// @parmopt integer | viewport | 0 |\r\n// @flag move |\t  move the new camera to the position of the old camera\r\nbool\tScriptSetActiveCamera(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32\tid=0;\r\n\tpParams->GetChecksum(CRCD(0x40c698af,\"id\"),&id);\r\n\tint\tviewport=0;\r\n\tpParams->GetInteger(CRCD(0x9fd29151,\"viewport\"),&viewport);\r\n\tbool move = pParams->ContainsFlag(CRCD(0x10c1c887,\"move\"));\r\n\r\n\treturn SetActiveCamera(id,viewport, move); \t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptSin(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    float x,sin;\r\n    pParams->GetFloat( NONAME , &x, Script::ASSERT );\r\n    \r\n    sin = sinf(Mth::DegToRad(x));\r\n\r\n    Script::CStruct *p_script_params = pScript->GetParams(); \t\t\t\t   \r\n\tp_script_params->AddFloat(\"sin\",sin);\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptCos(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    float x,cos;\r\n    pParams->GetFloat( NONAME , &x, Script::ASSERT );\r\n    \r\n    cos = cosf(Mth::DegToRad(x));\r\n\r\n    Script::CStruct *p_script_params = pScript->GetParams(); \t\t\t\t   \r\n\tp_script_params->AddFloat(\"cos\",cos);\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptTan(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    float x,tan;\r\n    pParams->GetFloat( NONAME , &x, Script::ASSERT );\r\n    \r\n    tan = tanf(Mth::DegToRad(x));\r\n\r\n    Script::CStruct *p_script_params = pScript->GetParams(); \t\t\t\t   \r\n\tp_script_params->AddFloat(\"tan\",tan);\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptASin(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    float x,asin;\r\n    pParams->GetFloat( NONAME , &x, Script::ASSERT );\r\n    \r\n    asin = asinf(x);\r\n    asin = Mth::RadToDeg(asin);\r\n\r\n    Script::CStruct *p_script_params = pScript->GetParams(); \t\t\t\t   \r\n\tp_script_params->AddFloat(\"asin\",asin);\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptACos(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    float x,acos;\r\n    pParams->GetFloat( NONAME , &x, Script::ASSERT );\r\n    \r\n    acos = acosf(x);\r\n    acos = Mth::RadToDeg(acos);\r\n\r\n    Script::CStruct *p_script_params = pScript->GetParams(); \t\t\t\t   \r\n\tp_script_params->AddFloat(\"acos\",acos);\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptATan(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n    float x,atan;\r\n    pParams->GetFloat( NONAME , &x, Script::ASSERT );\r\n    \r\n    atan = atanf(x);\r\n    atan = Mth::RadToDeg(atan);\r\n\r\n    Script::CStruct *p_script_params = pScript->GetParams(); \t\t\t\t   \r\n\tp_script_params->AddFloat(\"atan\",atan);\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Load tracking info from a file, and display it as immediate mode lines\r\nbool ScriptShowTracking(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tGfx::DebugGfx_CleanUp();\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\r\n\tbool do_bonks = pParams->ContainsFlag(CRCD(0xb426bf5a,\"bonks\"));\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\tbool do_grinds = pParams->ContainsFlag(CRCD(0x14240297,\"grinds\"));\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\tbool do_verts = pParams->ContainsFlag(CRCD(0x969d3af6,\"verts\"));\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\tbool do_lines = pParams->ContainsFlag(CRCD(0xb0fe7369,\"lines\"));\t\t\t\t\t\r\n\r\n\t// if nothing specificed, then do everything\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\tif (!do_bonks && !do_grinds && !do_verts && !do_lines)\r\n\t{\r\n\t\tdo_bonks = do_grinds = do_verts\t= do_lines = true;\r\n\t}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n\tconst char *p_name=\"\";\r\n\tpParams->GetString(NONAME,&p_name);\r\n\tif (p_name[1] == ':')\r\n\t{\r\n\t\t// skip over any 'c:' the user might be specifying\r\n\t\t// hopefully they don't try to load things off q:, or something\r\n\t\tprintf (\"WARNING: stripped drive name off file\\n\");\r\n\t\tp_name+=2;\r\n\t}\r\n\tint size=0;\r\n\tvoid * p_file;\r\n\tif (File::Exist(p_name))\r\n\t{\r\n\t\tp_file = File::LoadAlloc(p_name,&size);\r\n\t\r\n\t\tprintf (\"Loaded %s, size = %d, at %p\\n\",p_name,size,p_file);\r\n\t\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tprintf (\"Can't find file: %s\\n\",p_name);\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tint bonks = 0;\r\n\tint grinds = 0;\t\t\t\t \r\n\tint verts = 0;\t\t\t\t \r\n\tint lines = 0;\t\t\t\t \r\n\tchar *p = (char*)p_file;\r\n\twhile (p < ((char*)p_file+size))\r\n\t{\r\n\t\tif (\r\n\t\t\t    p[0] == 0x0a\r\n\t\t\t&&\tp[1] == 'T'\r\n\t\t\t&&\tp[2] == 'r'\r\n\t\t\t&&\tp[3] == 'a'\r\n\t\t\t&&\tp[4] == 'c'\r\n\t\t\t&&\tp[5] == 'k'\r\n\t\t\t&&\tp[6] == 'i'\r\n\t\t\t&&\tp[7] == 'n'\r\n\t\t\t&&\tp[8] == 'g'\r\n\t\t\t)\r\n\t\t{\r\n\t\t\tint type = p[9] - '0';\r\n\t\t\tp += 11;\r\n\t\t\tfloat f[6];\r\n\t\t\tfor (int i=0;i<6;i++)\r\n\t\t\t{\r\n\t\t\t\tf[i] = (float)atof(p);\r\n\t\t\t\twhile (*p=='-' || *p=='.' || (*p>='0' && *p<='9'))\r\n\t\t\t\t{\r\n\t\t\t\t\tp++;\r\n\t\t\t\t}\r\n\t\t\t\tp++;  // skip the comma (or half the EOL)\r\n\t\t\t}\r\n\t\t\tp--;\t// back up!\r\n//\t\t\tprintf (\"%d: %f,%f,%f - %f,%f,%f,%f\\n\",type,f[0],f[1],f[2],f[3],f[4],f[5]);\r\n\r\n\t\t\tMth::Vector start = Mth::Vector(f[0],f[1],f[2]); \r\n\t\t\tMth::Vector end = Mth::Vector(f[3],f[4],f[5]);\r\n\t\t\t\r\n\t\t\tuint32 color = 0xff00ff;\r\n\t\t\tswitch (type)\r\n\t\t\t{\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tbonks++;\r\n\t\t\t\t\tif (!do_bonks) goto sorry;\r\n\t\t\t\t\tcolor = 0xffffff;\t  // white = Bonk\r\n\t\t\t\t\tstart -= (end-start)*10;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tgrinds++;\r\n\t\t\t\t\tif (!do_grinds) goto sorry;\r\n\t\t\t\t\tcolor = 0x0000ff;\t  // Red = Grind\r\n\t\t\t\t\t//start -= (end-start)*2;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3: \r\n\t\t\t\t\tverts++;\r\n\t\t\t\t\tif (!do_verts) goto sorry;\r\n\t\t\t\t\tcolor = 0xffff00;\t  // Cyan = Vert\r\n\t\t\t\t\tstart -= (end-start)*2;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 4: \r\n\t\t\t\t\tlines++;\r\n\t\t\t\t\tif (!do_lines) goto sorry;\r\n\t\t\t\t\tcolor = 0x008000;\t  // Green = Line\r\n\t\t\t\t\tstart -= (end-start)*4;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tcolor = 0xffff;\r\n\t\t\t}\r\n\t\t\tGfx::AddDebugArrow(start, end,color,color,0);\r\nsorry:\t\t\r\n\t\t;\t\r\n\t\t}\r\n\t\r\n\t\r\n\t\tp++;\r\n\t}\r\n\t\r\n\tprintf (\"Bonks = %d,  Grinds = %d, verts= %d, lines = %d\\n\",bonks, grinds, verts, lines);\r\n\t\r\n\tMem::Free(p_file);\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsGrind | \r\nbool ScriptIsGrind(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\treturn pParams->ContainsFlag(CRCD(0x255ed86f, \"Grind\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetColorBufferClear | \r\n// @parmopt integer | clear | 0 |\r\nbool ScriptSetColorBufferClear(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tint\tclear = 0;\r\n\tpParams->GetInteger( CRCD( 0x1a4e0ef9, \"clear\" ), &clear );\r\n\r\n\tNx::CEngine::sSetColorBufferClear( clear > 0 );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ShowCamOffset |\r\n// @parm name | Name | The name of the node we want to get the offset from\r\n// Printfs the cam offset in EE0\r\nbool ScriptShowCamOffset(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t// Given a node name\r\n\t// then calculate a good targetOffset and positionOffset\r\n\t// so we can mode the camera into that position later\r\n\r\n\t// Some common code to either relative, or world specific\r\n\tMth::Matrix cam_matrix = Nx::CViewportManager::sGetActiveCamera()->GetMatrix();\r\n\tMth::Vector cam_pos = Nx::CViewportManager::sGetActiveCamera()->GetPos();\t\t\t\r\n\r\n\t// get a line segment extending fromthe camera forward (note -z)\r\n\tMth::Line cam_fwd;\r\n\tcam_fwd.m_start = cam_pos;\r\n\tcam_fwd.m_end = cam_pos - cam_matrix[Z] * 10000;\r\n\r\n\t\r\n\tuint32 name = 0;\r\n\tif (pParams->GetChecksum(CRCD(0xa1dc81f9,\"name\"),&name))\r\n\t{\r\n\t\t\r\n\t\tif (name != CRCD(0xc588eebc,\"world\"))\r\n\t\t{\r\n\t\t\t// get the node from the node array, and get the position\r\n\t\t\tint node = SkateScript::FindNamedNode(name);\r\n\t\t\tif (node != -1)\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct *pNode = SkateScript::GetNode(node);\r\n\t\t\t\tMth::Vector\tpos;\r\n\t\t\t\tpNode->GetVector(CRCD(0x7f261953,\"pos\"),&pos);\r\n\t\r\n\t\r\n\t\t\t\tMth::Matrix cam_matrix = Nx::CViewportManager::sGetActiveCamera()->GetMatrix();\r\n\t\t\t\tMth::Vector cam_pos = Nx::CViewportManager::sGetActiveCamera()->GetPos();\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t// get a line segment extending fromthe camera forward (note -z)\r\n\t\t\t\tMth::Line cam_fwd;\r\n\t\t\t\tcam_fwd.m_start = cam_pos;\r\n\t\t\t\tcam_fwd.m_end = cam_pos - cam_matrix[Z] * 10000;\r\n\t\t\t\t\r\n\t\t\t\tMth::Line node_up;\r\n\t\t\t\tnode_up.m_start = pos;\r\n\t\t\t\tnode_up.m_end = pos + Mth::Vector(0,10000,0);\r\n\t\r\n\t\t\t\tMth::Vector pa, pb;\t\t\t\r\n\t\t\t\tfloat mua,mub;\r\n\t\t\t\tif (Mth::LineLineIntersect( cam_fwd, node_up, &pa, &pb, &mua, &mub, false ))\r\n\t\t\t\t{\r\n\t\t\t\t\tGfx::AddDebugArrow(pos, pa,0xff0000,0,100);\t\t\t\r\n\t//\t\t\t\tGfx::AddDebugArrow(pa, pb ,0xff00  ,0,100);\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf (\"Can't calculate intersection, move camera a bit\\n\");\r\n\t\t\t\t}\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t//Need to find the offset from this point to the line of sight of the camera\r\n\t\t\t\t// we have  cam_pos = position of camera\r\n\t\t\t\t//          pos     = position of node\r\n\t\t\t\t//          pa      = position of the focus\r\n\t\t\t\t\r\n\t\t\t\tMth::Vector target_offset = pa-pos;\r\n\t\t\t\tMth::Vector position_offset = cam_pos - pa;\r\n\t\t\t\t\r\n\t\t\t\t/*\r\n\t\t\t\tprintf (\"\\nUnrotated - Use if focussing relative to the ground\\n\");\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\tprintf (\"\t\ttargetOffset=(%.1f, %.1f, %.1f)\\n\",target_offset[X],target_offset[Y],target_offset[Z]);\r\n\t\t\t\tprintf (\"\t\tpositionOffset=(%.1f, %.1f, %.1f)\\n\",position_offset[X],position_offset[Y],position_offset[Z]);\r\n\t\t\t\t*/\r\n\t\t\t\t\r\n\t\t\t\t// Now we have to transform it by the inverse fo the matrix representing the orientation fo the node\r\n\t\t\t\tObj::CCompositeObject *p_obj = (Obj::CCompositeObject *)Obj::CCompositeObjectManager::Instance()->GetObjectByID(name);\r\n\t\t\t\tif (!p_obj)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf (\"Can't find the oject this node represents\\n\");\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\t// Get the matrix\r\n\t\t\t\tMth::Matrix obj_mat = p_obj->GetMatrix();\r\n\t\t\t\t// Invert it, as we want to do the opposite of what we will do with the actual values\r\n\t\t\t\tobj_mat.Invert();\r\n\t\t\t\t// apply this, to get the values\r\n\t\t\t\ttarget_offset = obj_mat.TransformAsPos(target_offset);\r\n\t\t\t\tposition_offset = obj_mat.TransformAsPos(position_offset);\r\n\t\t\t\t\r\n//\t\t\t\tprintf (\"\\nRotated (Use if focussing relative to the object's orientation)\\n\");\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\tprintf (\"\t\ttargetid=%s\\n\",Script::FindChecksumName(name)); \r\n\t\t\t\tprintf (\"\t\ttargetOffset=(%.1f, %.1f, %.1f)\\n\",target_offset[X],target_offset[Y],target_offset[Z]);\r\n\t\t\t\tprintf (\"\t\tpositionOffset=(%.1f, %.1f, %.1f)\\n\",position_offset[X],position_offset[Y],position_offset[Z]);\r\n\t\r\n\t\t\t\treturn true;\r\n\t\t\t}\t\t\t\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Looks like we want world coordinates, so print up targetOffset as a point 100 feet in front of the camera\r\n\t// and positionoffset as the actual point of the camera\r\n\tprintf (\"\t\ttargetid=world\\n\"); \r\n\tprintf (\"\t\ttargetOffset=(%.1f, %.1f, %.1f)\\n\",cam_fwd.m_end[X],cam_fwd.m_end[Y],cam_fwd.m_end[Z]);\r\n\tprintf (\"\t\tpositionOffset=(%.1f, %.1f, %.1f)\\n\",cam_pos[X],cam_pos[Y],cam_pos[Z]);\r\n\t\r\n\t\r\n\t\r\n\t#endif\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n// @script | SetEventHandler | register this script to listen for the given event and gosub to the given script in response to the event\r\n// @parm name | Ex | the name of the event listened for\r\n// @parm script | Scr | the script to be run in response to the event\r\n// @parmopt name | Group | the name of this event listeners group; used to identify which listeners to clear when clearing listener groups\r\n// @parmopt structure | Params | this structure is added to the parameter list of the script\r\n// @parmopt flag | exception | set if this causes an exception, rather than a goto\r\nbool ScriptSetEventHandler(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 ex = 0;\r\n\tpParams->GetChecksum(CRCD(0xf8728bec,\"Ex\"), &ex, true);\r\n\tuint32 scr = 0;\r\n\tpParams->GetChecksum(CRCD(0xa6d2d890,\"Scr\"), &scr, true);\r\n\tuint32 group = CRCD(0x1ca1ff20,\"default\");\r\n\tpParams->GetChecksum(CRCD(0x923fbb3a,\"group\"), &group);\t\r\n\tbool exception = pParams->ContainsFlag(CRCD(0x80367192,\"exception\"));\r\n\tScript::CStruct *pExtraParams=NULL;\r\n\tpParams->GetStructure(CRCD(0x7031f10c,\"params\"),&pExtraParams);\r\n\tpScript->SetEventHandler(ex,scr,group,exception,pExtraParams);\t\r\n\treturn true;\r\n}\r\n\r\nbool ScriptClearEventHandler(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 type;\r\n\tpParams->GetChecksum(NO_NAME, &type, Script::ASSERT);\r\n\tpScript->RemoveEventHandler(type);\r\n\treturn true;\r\n}\r\n\t\t\t\r\nbool ScriptClearEventHandlerGroup(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 group = Obj::CEventHandlerTable::vDEFAULT_GROUP;\r\n\tpParams->GetChecksum(NO_NAME, &group);\r\n\tpScript->RemoveEventHandlerGroup(group);\r\n\treturn true;\r\n}\r\n\t\t\r\n// @script | OnExceptionRun | run the specified script on exception\r\n// @uparm name | script name to run\r\n// can be called without a parameter to clear it\r\nbool ScriptOnExceptionRun(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 OnExceptionScriptChecksum = 0;\r\n\tpParams->GetChecksum( NONAME, &OnExceptionScriptChecksum);\r\n\tpScript->SetOnExceptionScriptChecksum(OnExceptionScriptChecksum);\r\n\treturn true;\r\n}\r\n\r\nbool ScriptOnExitRun(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tuint32 OnExitScriptChecksum = 0;\r\n\tpParams->GetChecksum( NONAME, &OnExitScriptChecksum);\r\n\tpScript->SetOnExitScriptChecksum(OnExitScriptChecksum);\r\n\treturn true;\r\n}\r\n\r\n\r\n// @script | Block | Stop execution of this script, allowing to still be woken up by events and exceptions\r\nbool ScriptBlock(Script::CStruct* pParams, Script::CScript* pScript)\r\n{\r\n\tpScript->Block();\r\n\treturn true;\r\n}\r\n\r\n// @script | PrintEventHandlerTable | Prints the event handler table of the current script\r\nbool ScriptPrintEventHandlerTable ( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tpScript->PrintEventHandlerTable();\r\n\treturn true;\r\n}\r\n\r\n\r\n// @script | AllocateSplitScreenDMA | (PS2 only) allocated extra memory for DMA usage\r\nbool ScriptAllocateSplitScreenDMA ( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t#ifdef\t__PLAT_NGPS__\r\n\t\r\n\tNx::CEngine::sFinishRendering();\r\n \tNxPs2::AllocateExtraDMA(true);\r\n\r\n\t#endif\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n// @script | AddSkaterEarly | Create and load a skater, so when we autolaunch a level, it's there.  DEBUG ONLY\r\nbool ScriptAddSkaterEarly( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\r\n\tif (Mdl::Skate::Instance()->GetNumSkaters() == 0)\r\n\t{\r\n\t\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile(0);\r\n\t\tMdl::Skate::Instance()->add_skater( pSkaterProfile, true, 0, 0);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptPreLoadStreamDone( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 streamId;\r\n\tpParams->GetChecksum( NONAME, &streamId, Script::ASSERT );\r\n\treturn Pcm::PreLoadStreamDone( streamId );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptStartPreLoadedStream( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 streamId;\r\n\tpParams->GetChecksum( CRCD(0x8a68ab90,\"streamId\"), &streamId, Script::ASSERT );\r\n\tfloat vol = 100;\r\n\tpParams->GetFloat( CRCD(0x46653221,\"volume\"), &vol, Script::NO_ASSERT );\r\n\tSfx::sVolume* p_volume = new Sfx::sVolume();\r\n\tp_volume->SetChannelVolume( 0, vol );\r\n\tp_volume->SetChannelVolume( 1, vol );\r\n\tbool rc = Pcm::StartPreLoadedStream( streamId, p_volume );\r\n\tdelete p_volume;\r\n\treturn rc;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptFinishRendering( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tNx::CEngine::sFinishRendering();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace CFuncs\r\n"
  },
  {
    "path": "Code/Sk/Scripting/cfuncs.h",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Scripting\r\n//* FILENAME:       CFuncs.h\r\n//* OWNER:          Kendall Harrison\r\n//* CREATION DATE:  9/14/2000\r\n//****************************************************************************\r\n\r\n#ifndef\t__SCRIPTING_CFUNCS_H\r\n#define\t__SCRIPTING_CFUNCS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n// for now, include skfuncs.h, so that\r\n// it won't break the existing CPP files\r\n// that include cfuncs.h\r\n//#include <sk/scripting/skfuncs.h>\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n};\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace CFuncs\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nenum {\r\n\tTYPE_VUTESTOBJECT = 0x8daad03d,\r\n\tVUTESTOBJECT = 0xae96a38,\r\n};\r\n\r\n\r\nbool\tSetActiveCamera(uint32 id, int viewport, bool move_to_current);\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool ScriptDummyCommand(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptAllocateSplitScreenDMA ( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptWait(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptBlock(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPrintEventHandlerTable(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptFormatText(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPrintf(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptScriptAssert(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPrintScriptInfo(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetHackFlag(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptHackFlagIsSet(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPrintStruct(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUnloadAllLevelGeometry(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptLoadScene(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptLoadCollision(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAddScene(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAddCollision(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUnloadScene(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptQuickReload(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptLoadNodeArray(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptReLoadNodeArray(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptParseNodeArray(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetBackgroundColor(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetBSPAmbientColor(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetDFFAmbientColor(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetDFFDirectColor(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetDynamicLightModulationFactor( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetClippingDistances(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetTrivialFarZClip(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptEnableFog(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptDisableFog(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetFogDistance(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetFogExponent(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetFogColor(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetUVWibbleParams(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptEnableExplicitUVWibble(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptDisableExplicitUVWibble(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetUVWibbleOffsets(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetWorldSize( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetMovementVelocity( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetRotateVelocity( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptOnReload(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptResetEngine(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptToggleMetrics(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptToggleVRAMViewer(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetVRAMPackContext(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptDumpVRAMUsage(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptToggleLightViewer(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCleanup(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptProximCleanup(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptLoadQB(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUnloadQB(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetDebugRenderMode(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptToggleTextureUpload(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptToggleTextureDraw(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptTogglePointDraw(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRenderTest1(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRenderTest2(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptIsZero(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCastToInteger(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptStringToInteger(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptIntegerEquals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptChecksumEquals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptStringEquals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptArrayContains(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetArraySize(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetArrayElement(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAddParams(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGet3DArrayData(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGet2DArrayData(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetNDArrayData(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRemoveComponent(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetScriptString(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetScriptString(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptKenTest1(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptKenTest2(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAppendSuffix(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptFindNearestRailPoint(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetTime(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetDate(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetObNearestScreenCoord(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRandomize(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptResetTimer(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptTimeGreaterThan(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetStartTime(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetElapsedTime(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRemoveParameter(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetRandomValue(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetConfig(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPrintConfig(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGerman(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptFrench(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSpanish(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptItalian(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetNodeName(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetTesterScript(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptKillTesterScript(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptResetStopwatch(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPrintStopwatchTime(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCustomSkaterFilenameDefined(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetCustomSkaterFilename(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetCustomSkaterFilename(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptEditingPark(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetParkName(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetParkName(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptParkEditorThemeWasSwitched(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptMenuIsShown(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptMenuIsSelected(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptForEachIn(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSizeOf(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetElement(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetNextArrayElement(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetRandomArrayElement(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPermuteArray(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptApplyChangeGamma( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptGetGammaValues( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptGotParam(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPreloadModel(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGoto(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGotoPreserveParams(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGotoRandomScript(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptToggleRenderMode(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetRenderMode(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetWireframeMode(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptDebugRenderIgnore(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptScreenShot(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptDumpShots(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptToggleMetricItem( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptToggleMemMetrics( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptKillAllTextureSplats( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPlayMovie( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptLoadAsset( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptLoadAnim( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptLoadSkeleton( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptUnloadAnim( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptAssManSetReferenceChecksum( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptAssManSetDefaultPermanent( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptLoadSound( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPlaySound( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptStopSound( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptStopAllSounds( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetSoundParams( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptIsSoundPlaying( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPlayStream( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptStopStream( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetStreamParams( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptIsStreamPlaying( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetReverb( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptLoadTerrainSounds( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetObjectColor( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetSceneColor( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptCompressVC( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptNudgeVC( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptFakeLights( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptCenterCamera( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetDropoff( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetVolume( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetMusicVolume( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetMusicStreamVolume( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptLoadMusicHeader( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptLoadStreamHeader( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptStreamIsAvailable( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPlayTrack( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPlayMusicStream( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSkipMusicTrack( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetRandomMode( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptGetCurrentTrack( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetMusicMode( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetMusicLooping( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptStopMusic( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPauseMusic( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPauseStream( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptLoadStreamFrameAmp( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptFreeStreamFrameAmp( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptAddMusicTrack( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptChangeTrackState(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptTrackEnabled(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptMusicIsPaused(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptClearMusicTrackList( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptIfDebugOn(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptIfDebugOff(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptBootstrap(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCD(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptNotCD(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCasArtist(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptNotCasArtist(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGunslinger(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptDoAction(Script::CStruct *pParams, Script::CScript *pScript, int action );\r\nbool ScriptSendFlag(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptClearFlag(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptQueryFlag(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCheckIfAlive( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptCheckExistenceFromNodeIndex( int nodeIndex );\r\nbool ScriptFlagException(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptMakeSkaterGoto(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptMakeSkaterGosub(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSpawnSound(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSpawnScript(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSpawnSkaterScript(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptKillSpawnedScript(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPauseSkaters( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptUnPauseSkaters( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPauseSkater( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptUnPauseSkater( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPauseGame( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptUnPauseGame( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptIsGamePaused( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPauseObjects( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptUnPauseObjects( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPauseSpawnedScripts( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptUnPauseSpawnedScripts( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptResetClock( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPadsPluggedIn( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptDoFlash( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetViewMode(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptStartServer(Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSpawnCrown(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSpawnCompass(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptLeaveServer(Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptFindServers(Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptJoinServer(Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetNetworkMode( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetServerMode( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptCreateFromNodeIndex( int nodeIndex );\r\nbool ScriptKillFromNodeIndex( int nodeIndex, Script::CScript *pScript );\r\nbool ScriptSetColorFromNodeIndex( int nodeIndex, Script::CStruct *pParams );\r\nbool ScriptShatterFromNodeIndex( int nodeIndex );\r\nbool ScriptSetVisibilityFromNodeIndex( int nodeIndex, bool invisible, int viewport_number = 0 );\r\nbool ScriptNodeExists( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptCreate( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptCreateFromStructure( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptKill( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptVisible( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptInvisible( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptShatter( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptResetCamera(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetValueFromVolume(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetSliderValue(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetVolumeFromValue(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetIconTexture(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptMemViewToggle(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPreferenceEquals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetPreference(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetPreferenceString(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetPreferencePassword(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetPreferenceChecksum(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptMemPushContext(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptMemPopContext(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptProfileTasks( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptUseNetworkPreferences( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptCanChangeDevices( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptNeedToTestNetSetup( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptTestNetSetup( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptConnectToInternet( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptCancelConnectToInternet( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptCancelLogon( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptDisconnectFromInternet( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptIsOnline( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptStopAllScripts( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetMenuElementText(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptFirstTimeThisIsCalled(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptEnableActuators(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptInNetGame(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptToggleNetMetrics(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetSlomo(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetArenaSize(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetParticleSysVisibility( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptTogglePlayerNames( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetCurrentGameType( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptDumpNetMessageStats( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptNotifyBailDone( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptDisplayLoadingScreen( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptHideLoadingScreen( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptObserveNextSkater( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPrintMemInfo( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptDisplayFreeMem( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptAnalyzeHeap( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptMemThreadSafe( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptIsSingleSession(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptEnterObserverMode(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAllowPause(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRefreshServerList(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptStartServerList(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptStopServerList(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptFreeServerList(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPauseGameFlow(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUnpauseGameFlow(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptInFrontEnd(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetFrontEndInactive(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptInSplitScreenGame(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGameModeEquals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetFireballLevel(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptOnServer(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetCurrentLevel(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRestartLevel(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptToggleScores(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptIsTrue(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetLevelLoadScript(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptXTriggered(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUsePad(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptInMultiplayerGame(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptToggleShadowType(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptGameFlow(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptControllerPressed(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetAnalogueInfo(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptControllerDebounce( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptClearCheats(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptBroadcastCheat(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptLastBroadcastedCheatWas(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCheatAllowed(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptJoinWithPassword(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSendChatMessage(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptInSlapGame( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetScreenModeFromGameMode( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetScreenMode( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptLoadPendingPlayers( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptLaunchQueuedScripts( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptIsObserving( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSkatersAreReady(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptGetInitialsString( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetInitialsString( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool\tScriptAttachToSkater(  Script::CStruct *pParams, Script::CScript *pScript );\r\nbool\tScriptTryCheatString(  Script::CStruct *pParams, Script::CScript *pScript );\r\nbool\tScriptLevelIs(  Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptStartNetworkLobby( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptObserversAllowed( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptNumPlayersAllowed( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptAutoDNS( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptUsingDefaultMasterServers( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptUsingDHCP( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptInInternetMode( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptEnteringNetGame( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptDeviceChosen( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptLoadExecPS2( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptExitDemo( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptGameIsOver( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptSetLevelName( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptDumpHeaps( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptDumpFragments( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptResetPS2( Script::CStruct *pParams, Script::CScript *pScript ); \r\nbool ScriptResetHD( Script::CStruct *pParams, Script::CScript *pScript ); \r\nbool ScriptPAL( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptEnglish( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptTimeUp( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptChangeSymbolValue(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptDumpScripts( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptResetPS2( Script::CStruct *pParams, Script::CScript *pScript ); \r\nbool ScriptResetHD( Script::CStruct *pParams, Script::CScript *pScript ); \r\nbool ScriptPAL( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptEnglish( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptTimeUp( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptLaunchViewer( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptLaunchScriptDebugger( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetViewerModel( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetViewerAnim( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetViewerLODDist( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetViewerObjectID( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptReloadViewerAnim( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptInitHealth( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptResetScore( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptAddRestartsToMenu( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptAddWarpPointsToMenu( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptRunScriptOnObject( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptRunScriptOnComponentType( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptTestName( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptDebounce( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetStatOverride( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptToggleRails( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptToggleRigidBodyDebug( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptCheckForHoles( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptStartLobbyList( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptChatConnect( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptChatDisconnect( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptFillPlayerListMenu( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptOnXbox( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGotoXboxDashboard( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSystemLinkEnabled( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptCreateParticleSystem( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetScript( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptDestroyParticleSystem( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptEmptyParticleSystem( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptParticleExists( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptStructureContains( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetBonePosition( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptMangleChecksums( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptAppendSuffixToChecksum( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptShouldEmitParticles( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptParticlesOn( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptParticlesOff( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptRotateVector( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptIsPS2( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptIsXBOX( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptIsNGC( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptIsWIN32( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetPlatform( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptIsPal( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\n\r\nbool ScriptPushMemProfile( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptPopMemProfile( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptTogglePass( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool\tScriptSetScreen( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptGetUpperCaseString( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptGetGameMode( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptStartKeyboardHandler( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptStopKeyboardHandler( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptEnableKeyboard( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptDisableKeyboard( Script::CStruct* pParams, Script::CScript* pScript );\r\n\t \r\nbool ScriptCreateIndexArray( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetRescaledTargetValue( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptMemInitHeap( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptMemDeleteHeap( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptClearStruct( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptAppendStruct( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptScriptExists( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptSpawnSecondControllerCheck( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptStopSecondControllerCheck( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptIsArray( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptUseUserSoundtrack( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptUseStandardSoundtrack( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptDisableReset( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptEnableReset( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptResetToIPL( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptInitAnimCompressTable( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptCreateCompositeObject( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptAutoRail( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptInside( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptSetSpecialBarColors( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetMetrics( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptMoveNode( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetActiveCamera( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptSetColorBufferClear( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetEventHandler( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptClearEventHandler(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptClearEventHandlerGroup(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptOnExceptionRun(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptOnExitRun(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\n\r\n\r\nbool ScriptSin( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptCos( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptTan( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptASin( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptACos( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptATan( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptShowTracking(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\nbool ScriptIsGrind(Script::CStruct* pParams, Script::CScript* pScript);\r\nbool ScriptShowCamOffset(Script::CStruct* pParams, Script::CScript* pScript);\r\n\r\nbool ScriptAddSkaterEarly( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptPreLoadStreamDone( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptStartPreLoadedStream( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptFinishRendering( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace CFuncs\r\n\r\n#endif\t// __SCRIPTING_CFUNCS_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Scripting/ftables.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tScripting                  \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tScripting/ftables.cpp          \t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t09/15/00\t-\tksh\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tLists of C-functions & class member functions callable \t**\r\n**                  from scripts.                                           **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <scripting/ftables.h>\r\n#include <scripting/cfuncs.h>\r\n#include <scripting/skfuncs.h>\r\n#include <scripting/mcfuncs.h>\r\n\r\n#include <gel/scripting/struct.h>\r\n\r\n#include <modules/FrontEnd/FrontEnd.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <modules/Skate/GameMode.h>\r\n#include <modules/Skate/goalmanager.h>\r\n\r\n#include <sk/objects/pathman.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#ifdef __PLAT_NGPS__\r\n#include <sk/gamenet/lobby.h>\r\n#include <sk/gamenet/ngps/p_content.h>\r\n#include <sk/gamenet/ngps/p_buddy.h>\r\n#include <sk/gamenet/ngps/p_stats.h>\r\n#endif\r\n\r\n#include <gel/objtrack.h>\r\n#include <gel/components/trickcomponent.h>\r\n\r\n#include <sys/File/PRE.h>\r\n#include <sys/File/pip.h>\r\n#include <sys/replay/replay.h>\r\n\r\n#include <gfx/Nx.h>\r\n#include <gfx/NxFontMan.h>\r\n#include <gfx/NxTexMan.h>\r\n#include <gfx/NxLightMan.h>\r\n#include <gfx/NxLoadScreen.h>\r\n#include <gfx/NxViewMan.h>\r\n#include <gfx/2D/ScreenElemMan.h>\r\n#include <gfx/FaceMassage.h>\r\n#include <gfx/nxweather.h>\r\n\r\n#include <sk/ParkEditor2/ParkEd.h>\r\n#include <sk/objects/gap.h>\r\n\r\n\r\n\r\n#ifdef __PLAT_NGC__\r\n#include <sys/ngc/p_display.h>\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\t  \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Script\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// A list of all the C functions callable from scripts.\r\n// The name in quotes must be the same as the way it appears in q scripts. (case insensitive)\r\nSCFunction CFunctionLookupTable[]=\r\n{\r\n    {\"Wait\",\t\t\t\tCFuncs::ScriptWait},\r\n\t{\"WaitForEvent\",\t\tObj::ScriptWaitForEvent},\r\n\t{\"Block\",\t\t\t\tCFuncs::ScriptBlock},\r\n\r\n    // Prints the contents of the passed structure.\r\n    {\"PrintStruct\",         CFuncs::ScriptPrintStruct},\r\n\t\r\n\t// Prints the script's event handler table.\r\n    {\"PrintEventHandlerTable\",\tCFuncs::ScriptPrintEventHandlerTable},\r\n    \r\n    {\"AllocateSplitScreenDMA\",\tCFuncs::ScriptAllocateSplitScreenDMA},\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\r\n    // Printf \"Default printf text\"\r\n    {\"Printf\",\t\t\t\tCFuncs::ScriptPrintf},\r\n\t{\"ScriptAssert\",\t\tCFuncs::ScriptScriptAssert},\r\n\t{\"PrintScriptInfo\",\t\tCFuncs::ScriptPrintScriptInfo},\r\n\t{\"FormatText\",\t\t\tCFuncs::ScriptFormatText},\r\n\t\r\n\t{\"SetHackFlag\",\t\t\tCFuncs::ScriptSetHackFlag},\r\n\t{\"HackFlagIsSet\",\t\tCFuncs::ScriptHackFlagIsSet},\r\n\t{\"SetCurrentSkaterProfile\",\tCFuncs::ScriptSetCurrentSkaterProfile},\r\n\t{\"CurrentSkaterProfileIs\",\tCFuncs::ScriptCurrentSkaterProfileIs},\r\n\t{\"AddSkaterProfile\",\t\tCFuncs::ScriptAddSkaterProfile},\r\n\t{\"AddTemporaryProfile\",\t\tCFuncs::ScriptAddTemporaryProfile},\r\n\t{\"RememberTemporaryAppearance\",CFuncs::ScriptRememberTemporaryAppearance},\r\n\t{\"RestoreTemporaryAppearance\",\tCFuncs::ScriptRestoreTemporaryAppearance},\r\n\t{\"SyncPlayer2Profile\",\tCFuncs::ScriptSyncPlayer2Profile},\r\n\t\r\n\t{\"UnloadAllLevelGeometry\",\tCFuncs::ScriptUnloadAllLevelGeometry},\r\n\t\r\n    // LoadLevelGeometry \"blaa\"\r\n\t{\"QuickReload\",\t\t\tCFuncs::ScriptQuickReload},\r\n\t{\"UnloadScene\",\t\t\tCFuncs::ScriptUnloadScene},\r\n\t{\"LoadScene\",\t\t\tCFuncs::ScriptLoadScene},\r\n\t{\"LoadCollision\",\t\tCFuncs::ScriptLoadCollision},\r\n\t{\"AddScene\",\t\t\tCFuncs::ScriptAddScene},\r\n\t{\"AddCollision\",\t\tCFuncs::ScriptAddCollision},\r\n\t{\"ToggleAddScenes\",\t\tNx::ScriptToggleAddScenes},\r\n\t{\"SetScreenBlur\",\t\tNx::ScriptSetScreenBlur},\r\n    // LoadNodeArray \"blaa.qb\"\r\n    {\"LoadNodeArray\",\t\tCFuncs::ScriptLoadNodeArray},\r\n    {\"ReLoadNodeArray\",\t\tCFuncs::ScriptReLoadNodeArray},\r\n\t{\"ParseNodeArray\",\t\tCFuncs::ScriptParseNodeArray},\r\n    \r\n    // SetBackgroundColor r=0 g=0 b=0 alpha=0\r\n    {\"SetBackgroundColor\",  CFuncs::ScriptSetBackgroundColor},\r\n    \r\n    // Won't do anything yet ...   \r\n    // SetAmbientColor r=0 g=0 b=0 alpha=0                                         \r\n//    {\"SetBSPAmbientColor\",  CFuncs::ScriptSetBSPAmbientColor},\r\n//    {\"SetDFFAmbientColor\",  CFuncs::ScriptSetDFFAmbientColor},\r\n//    {\"SetDFFDirectColor\",  CFuncs::ScriptSetDFFDirectColor},\r\n//\t{\"SetDFFDirectRotation\", Mdl::ScriptSetDirectionalLightDirection},\r\n//\t{\"SetDFFDirectActive\", Mdl::ScriptSetDirectionalLightActive},\r\n\t\r\n\t{\"SetDynamicLightModulationFactor\", CFuncs::ScriptSetDynamicLightModulationFactor},\r\n    \r\n    // Sets the clipping distances.\r\n    // SetClippingDistances Near=100 Far=1000\r\n    {\"SetClippingDistances\",    CFuncs::ScriptSetClippingDistances},\r\n\t{\"SetTrivialFarZClip\",\t\tCFuncs::ScriptSetTrivialFarZClip},\r\n    \r\n\t// Sets the default world size (for viewing dffs)\r\n    // SetWorldSize Size=100\r\n//    {\"SetWorldSize\",    CFuncs::ScriptSetWorldSize},\r\n\r\n    // Sets the movement( translational ) velocity for the camera in the viewer\r\n\t{\"SetMovementVelocity\", CFuncs::ScriptSetMovementVelocity },\r\n\t// Sets the rotational velocity for the camera in the viewer\r\n\t{\"SetRotateVelocity\", CFuncs::ScriptSetRotateVelocity},\r\n\r\n\t{\"SkaterLastScoreLandedGreaterThan\", CFuncs::ScriptLastScoreLandedGreaterThan},\r\n\t{\"SkaterLastScoreLandedLessThan\", CFuncs::ScriptLastScoreLandedLessThan},\r\n\t{\"SkaterTotalScoreGreaterThan\", CFuncs::ScriptTotalScoreGreaterThan},\r\n\t{\"AnySkaterTotalScoreAtLeast\", CFuncs::ScriptAnyTotalScoreAtLeast},\r\n\t{\"OnlyOneSkaterLeft\", CFuncs::ScriptOnlyOneSkaterLeft},\r\n\t{\"SkaterTotalScoreLessThan\", CFuncs::ScriptTotalScoreLessThan},\r\n\t{\"SkaterCurrentScorePotGreaterThan\", CFuncs::ScriptCurrentScorePotGreaterThan},\r\n\t{\"SkaterCurrentScorePotLessThan\", CFuncs::ScriptCurrentScorePotLessThan},\r\n\t{\"SkaterGetScoreInfo\", CFuncs::ScriptSkaterGetScoreInfo},\r\n\r\n\t{\"SkaterSpeedGreaterThan\", CFuncs::ScriptSkaterSpeedGreaterThan},\r\n\t{\"SkaterSpeedLessThan\", CFuncs::ScriptSkaterSpeedLessThan},\r\n\r\n\t{\"ToggleAlwaysSpecial\", CFuncs::ScriptToggleAlwaysSpecial},\r\n\r\n\t{\"Debounce\",\t\t\tCFuncs::ScriptDebounce},\r\n\t{\"SetStatOverride\",\t\tCFuncs::ScriptSetStatOverride},\r\n\t{\"ToggleRails\",\t\t\tCFuncs::ScriptToggleRails},\r\n\t{\"ToggleRigidBodyDebug\", CFuncs::ScriptToggleRigidBodyDebug},\r\n\t{\"CheckForHoles\",\t\tCFuncs::ScriptCheckForHoles},\r\n\t\r\n\t{\"OnReload\",\t\t\tCFuncs::ScriptOnReload},\r\n\t{\"ResetEngine\",\t\t\tCFuncs::ScriptResetEngine},\r\n\t{\"ResetSkaters\",\t\tCFuncs::ScriptResetSkaters},\r\n\t{\"ToggleMetrics\",\t\tCFuncs::ScriptToggleMetrics},\r\n\t{\"ToggleVRAMViewer\",\tCFuncs::ScriptToggleVRAMViewer},\r\n\t{\"ToggleLightViewer\",\tCFuncs::ScriptToggleLightViewer},\r\n\t{\"DumpVRAMUsage\",\t\tCFuncs::ScriptDumpVRAMUsage},\r\n\t{\"SetVRAMPackContext\",\tCFuncs::ScriptSetVRAMPackContext},\r\n\t{\"Cleanup\",\t    \t\tCFuncs::ScriptCleanup},\r\n\t{\"ProximCleanup\",  \t\tCFuncs::ScriptProximCleanup},\r\n\t{\"LoadQB\",\t\t\t\tCFuncs::ScriptLoadQB},\r\n\t{\"UnloadQB\",\t\t\tCFuncs::ScriptUnloadQB},\r\n\t{\"DebugRenderIgnore\",\tCFuncs::ScriptDebugRenderIgnore},\r\n\t{\"debugrendermode\",\t\tCFuncs::ScriptSetDebugRenderMode},\r\n\t{\"debugtoggletextureupload\",\t\tCFuncs::ScriptToggleTextureUpload},\r\n\t{\"debugtoggletexturedraw\",\t\tCFuncs::ScriptToggleTextureDraw},\r\n\t{\"debugtogglepointdraw\",\t\tCFuncs::ScriptTogglePointDraw},\r\n\t{\"debugrendertest1\",\t\t\tCFuncs::ScriptRenderTest1},\r\n\t{\"debugrendertest2\",\t\t\tCFuncs::ScriptRenderTest2},\r\n\r\n    {\"IsZero\",\t\t\t\t\tCFuncs::ScriptIsZero},\r\n\t{\"CastToInteger\",\t\t\tCFuncs::ScriptCastToInteger},\r\n\t{\"StringToInteger\",\t\t\tCFuncs::ScriptStringToInteger},\r\n\t{\"IntegerEquals\",\t\t\tCFuncs::ScriptIntegerEquals},\r\n\t{\"ChecksumEquals\",\t\t\tCFuncs::ScriptChecksumEquals},\r\n\t{\"StringEquals\",\t\t\tCFuncs::ScriptStringEquals},\r\n\t{\"ArrayContains\",\t\t\tCFuncs::ScriptArrayContains},\r\n\t{\"GetArraySize\",\t\t\tCFuncs::ScriptGetArraySize},\r\n\t{\"SetArrayElement\",\t\t\tCFuncs::ScriptSetArrayElement},\r\n\t{\"Get3DArrayData\",\t\t\tCFuncs::ScriptGet3DArrayData},\r\n\t{\"Get2DArrayData\",\t\t\tCFuncs::ScriptGet2DArrayData},\r\n\t{\"GetNDArrayData\",\t\t\tCFuncs::ScriptGetNDArrayData},\r\n\t{\"AddParams\",\t\t\t\tCFuncs::ScriptAddParams},\r\n\t{\"RemoveComponent\",\t\t\tCFuncs::ScriptRemoveComponent},\r\n\t{\"SetScriptString\",\t\t\tCFuncs::ScriptSetScriptString},\r\n\t{\"GetScriptString\",\t\t\tCFuncs::ScriptGetScriptString},\r\n    {\"KenTest1\",\t\t\t\tCFuncs::ScriptKenTest1},\r\n    {\"KenTest2\",\t\t\t\tCFuncs::ScriptKenTest2},\r\n\t{\"AppendSuffix\",\t\t\tCFuncs::ScriptAppendSuffix},\r\n\t{\"FindNearestRailPoint\",\tCFuncs::ScriptFindNearestRailPoint},\r\n\t{\"GetTime\",\t\t\t\t\tCFuncs::ScriptGetTime},\r\n\t{\"GetDate\",\t\t\t\t\tCFuncs::ScriptGetDate},\r\n\t{\"GetObNearestScreenCoord\",\tCFuncs::ScriptGetObNearestScreenCoord},\r\n\t{\"Randomize\",\t\t\t\tCFuncs::ScriptRandomize},\r\n\t{\"RunningReplay\",\t\t\tReplay::ScriptRunningReplay},\r\n\t{\"PauseReplay\",\t\t\t\tReplay::ScriptPauseReplay},\r\n\t{\"UnPauseReplay\",\t\t\tReplay::ScriptUnPauseReplay},\r\n\t{\"DeleteDummies\",\t\t\tReplay::ScriptDeleteDummies},\r\n\t{\"ShowGameObjects\",\t\t\tReplay::ScriptShowGameObjects},\r\n\t{\"HideGameObjects\",\t\t\tReplay::ScriptHideGameObjects},\r\n\t{\"PlaybackReplay\",\t\t\tReplay::ScriptPlaybackReplay},\r\n\t{\"ReplayRecordSimpleScriptCall\",\tReplay::ScriptReplayRecordSimpleScriptCall},\r\n\t{\"RecordPanelMessage\",\t\tReplay::ScriptRecordPanelMessage},\r\n\t{\"SwitchToReplayRecordMode\",Replay::ScriptSwitchToReplayRecordMode},\r\n\t{\"SwitchToReplayIdleMode\",\tReplay::ScriptSwitchToReplayIdleMode},\r\n\t{\"AllocateReplayMemory\",\tReplay::ScriptAllocateReplayMemory},\r\n\t{\"DeallocateReplayMemory\",\tReplay::ScriptDeallocateReplayMemory},\r\n\t{\"StartRecordingAfresh\",\t\t\t\tReplay::ScriptStartRecordingAfresh},\r\n\t{\"RememberLevelStructureNameForReplays\",\tReplay::ScriptRememberLevelStructureNameForReplays},\r\n\t{\"GetReplayLevelStructureName\",\tReplay::ScriptGetReplayLevelStructureName},\r\n\t{\"ClearTrickAndScoreText\",\t\tReplay::ScriptClearTrickAndScoreText},\r\n\t{\"NeedToLoadReplayBuffer\",\tCFuncs::ScriptNeedToLoadReplayBuffer},\r\n\t{\"LoadReplayData\",\t\t\tCFuncs::ScriptLoadReplayData},\r\n\t{\"ResetTimer\",\t\t\t\tCFuncs::ScriptResetTimer},\r\n\t{\"TimeGreaterThan\",\t\t\tCFuncs::ScriptTimeGreaterThan},\r\n\t{\"GetStartTime\",\t\t\tCFuncs::ScriptGetStartTime},\r\n\t{\"GetElapsedTime\",          CFuncs::ScriptGetElapsedTime},\r\n\t{\"RemoveParameter\",\t\t\tCFuncs::ScriptRemoveParameter},\r\n\t{\"GetRandomValue\",\t\t\tCFuncs::ScriptGetRandomValue},\r\n\t{\"SetConfig\",\t\t\t\tCFuncs::ScriptSetConfig},\r\n\t{\"PrintConfig\",\t\t\t\tCFuncs::ScriptPrintConfig},\r\n\t{\"German\",\t\t\t\t\tCFuncs::ScriptGerman},\r\n\t{\"French\",\t\t\t\t\tCFuncs::ScriptFrench},\r\n\t{\"Spanish\",\t\t\t\t\tCFuncs::ScriptSpanish},\r\n\t{\"Italian\",\t\t\t\t\tCFuncs::ScriptItalian},\r\n\t{\"GetNodeName\",\t\t\t\tCFuncs::ScriptGetNodeName},\r\n\t{\"SetTesterScript\",\t\t\tCFuncs::ScriptSetTesterScript},\r\n\t{\"KillTesterScript\",\t\tCFuncs::ScriptKillTesterScript},\r\n\t{\"ResetStopwatch\",\t\t\tCFuncs::ScriptResetStopwatch},\r\n\t{\"PrintStopwatchTime\",\t\tCFuncs::ScriptPrintStopwatchTime},\r\n\t{\"CustomSkaterFilenameDefined\",CFuncs::ScriptCustomSkaterFilenameDefined},\r\n\t{\"GetCustomSkaterFilename\",\tCFuncs::ScriptGetCustomSkaterFilename},\r\n\t{\"SetCustomSkaterFilename\",\tCFuncs::ScriptSetCustomSkaterFilename},\r\n\t{\"CurrentSkaterIsPro\",\t\tCFuncs::ScriptCurrentSkaterIsPro},\r\n\t{\"EditingPark\",\t\t\t\tCFuncs::ScriptEditingPark},\r\n\t{\"GetParkName\",\t\t\t\tCFuncs::ScriptGetParkName},\r\n\t{\"SetParkName\",\t\t\t\tCFuncs::ScriptSetParkName},\r\n\t{\"ParkEditorThemeWasSwitched\",CFuncs::ScriptParkEditorThemeWasSwitched},\r\n\t{\"GetGoalsCompleted\",\t\tCFuncs::ScriptGetGoalsCompleted},\r\n\t{\"GetNextLevelRequirements\",CFuncs::ScriptGetNextLevelRequirements},\r\n\t{\"MenuIsShown\",\t\t\t\tCFuncs::ScriptMenuIsShown},\r\n\t{\"MenuIsSelected\",\t\t\tCFuncs::ScriptMenuIsSelected},\r\n\r\n\t{\"GetMostRecentSave\",\t\tCFuncs::ScriptGetMostRecentSave},\r\n\t{\"GetMemCardSpaceAvailable\",CFuncs::ScriptGetMemCardSpaceAvailable},\r\n\t{\"GetMemCardSpaceRequired\",\tCFuncs::ScriptGetMemCardSpaceRequired},\r\n\t{\"MemCardFileExists\",\t\tCFuncs::ScriptMemCardFileExists},\r\n\t{\"DeleteMemCardFile\",\t\tCFuncs::ScriptDeleteMemCardFile},\r\n\t{\"FormatCard\",\t\t\t\tCFuncs::ScriptFormatCard},\r\n\t{\"CardIsInSlot\",\t\t\tCFuncs::ScriptCardIsInSlot},\r\n\t{\"SectorSizeOK\",\t\t\tCFuncs::ScriptSectorSizeOK},\r\n\t{\"CardIsDamaged\",\t\t\tCFuncs::ScriptCardIsDamaged},\r\n\t{\"CardIsForeign\",\t\t\tCFuncs::ScriptCardIsForeign},\r\n\t{\"BadDevice\",\t\t\t\tCFuncs::ScriptBadDevice},\r\n\t{\"GetSaveInfo\",\t\t\t\tCFuncs::ScriptGetSaveInfo},\r\n\t{\"CreateTemporaryMemCardPools\",CFuncs::ScriptCreateTemporaryMemCardPools},\r\n\t{\"RemoveTemporaryMemCardPools\",CFuncs::ScriptRemoveTemporaryMemCardPools},\r\n\t{\"SwitchToTempPoolsIfTheyExist\",CFuncs::ScriptSwitchToTempPoolsIfTheyExist},\r\n\t{\"SwitchToRegularPools\",\tCFuncs::ScriptSwitchToRegularPools},\r\n\t{\"CardIsFormatted\",\t\t\tCFuncs::ScriptCardIsFormatted},\r\n\t{\"SaveFailedDueToInsufficientSpace\",CFuncs::ScriptSaveFailedDueToInsufficientSpace},\r\n\t{\"GetSummaryInfo\",\t\t\tCFuncs::ScriptGetSummaryInfo},\r\n\t{\"SaveToMemoryCard\",\t\tCFuncs::ScriptSaveToMemoryCard},\r\n\t{\"LoadFromMemoryCard\",\t\tCFuncs::ScriptLoadFromMemoryCard},\r\n\t{\"LoadedCustomSkater\",\t\tCFuncs::ScriptLoadedCustomSkater},\r\n\t{\"SetSectionsToApplyWhenLoading\",CFuncs::ScriptSetSectionsToApplyWhenLoading},\r\n\t{\"GetMemCardDataForUpload\",\tCFuncs::ScriptGetMemCardDataForUpload},\r\n\t{\"ClearMemCardDataForUpload\",CFuncs::ScriptClearMemCardDataForUpload},\r\n\t{\"GetMaxTHPS4FilesAllowed\",\tCFuncs::ScriptGetMaxTHPS4FilesAllowed},\r\n\t{\"GetMemCardDirectoryListing\",CFuncs::ScriptGetMemCardDirectoryListing},\r\n\t{\"ForEachIn\",\t\t\t\tCFuncs::ScriptForEachIn},\r\n\t{\"SizeOf\",\t\t\t\t\tCFuncs::ScriptSizeOf},\r\n\t{\"GetElement\",\t\t\t\tCFuncs::ScriptGetElement},\r\n\t{\"GetNextArrayElement\",\t\tCFuncs::ScriptGetNextArrayElement},\r\n\t{\"GetRandomArrayElement\",\tCFuncs::ScriptGetRandomArrayElement},\r\n\t{\"PermuteArray\",\t\t\tCFuncs::ScriptPermuteArray},\r\n\t{\"CreateIndexArray\",\t\tCFuncs::ScriptCreateIndexArray},\r\n\t{\"GetGammaValues\",\t\t\tCFuncs::ScriptGetGammaValues},\r\n\t{\"ApplyChangeGamma\",\t\tCFuncs::ScriptApplyChangeGamma},\r\n\t{\"GotParam\",\t\t\t\tCFuncs::ScriptGotParam},\r\n\t{\"Goto\",\t\t\t\t\tCFuncs::ScriptGoto},\r\n\t{\"GotoPreserveParams\",\t\tCFuncs::ScriptGotoPreserveParams},\r\n\t{\"GotoRandomScript\",\t\tCFuncs::ScriptGotoRandomScript},\r\n\r\n\t{\"PreloadModel\", CFuncs::ScriptPreloadModel},\r\n\r\n\t{\"LaunchPanelMessage\", \t\tCFuncs::ScriptDummyCommand},\r\n\t{\"LaunchLocalPanelMessage\", CFuncs::ScriptDummyCommand},\r\n\t{\"KillMessages\", \t\t\tCFuncs::ScriptDummyCommand},\r\n\t{\"ChangeLocalMessage\", \t\tCFuncs::ScriptDummyCommand},\r\n\t{\"LaunchConsoleMessage\", \tCFuncs::ScriptDummyCommand},\r\n\t//{\"FireMenuEvent\",\t\t\tFront::ScriptFireMenuEvent},\r\n\r\n\t{\"SetViewMode\",\t\t\t\tCFuncs::ScriptSetViewMode},\r\n\t\r\n\t{\"ToggleRenderMode\",\t\tCFuncs::ScriptToggleRenderMode},\r\n\t{\"SetRenderMode\",\t\t\tCFuncs::ScriptSetRenderMode},\r\n\t{\"SetWireframeMode\",\t\tCFuncs::ScriptSetWireframeMode},\r\n\t{\"ScreenShot\",\t\t\t\tCFuncs::ScriptScreenShot},\r\n\t{\"DumpShots\",\t\t\t\tCFuncs::ScriptDumpShots},\r\n\t//{\"SetStat\",\t\t\t\t\tCFuncs::ScriptSetStat},\r\n\r\n\t{\"LoadFont\", \t\t\t\tNx::ScriptLoadFont},\r\n\t{\"UnloadFont\",\t\t\t\tNx::ScriptUnloadFont},\r\n\r\n\t{\"LoadTexture\", \t\t\tNx::ScriptLoadTexture},\r\n\t{\"UnloadTexture\",\t\t\tNx::ScriptUnloadTexture},\r\n\t{\"AddTextureToVram\", \t\tNx::ScriptAddTextureToVram},\r\n\t{\"RemoveTextureFromVram\",\tNx::ScriptRemoveTextureFromVram},\r\n\t{\"LoadFaceTextureFromProfile\", Nx::ScriptLoadFaceTextureFromProfile},\r\n\t{\"Generate32BitImage\",\t\tNx::ScriptGenerate32BitImage},\r\n\t{\"OffsetTexture\",\t\t\tNx::ScriptOffsetTexture},\r\n    {\"AdjustTextureRegion\",\t\tNx::ScriptAdjustTextureRegion},\r\n\t{\"PullTextureToEdge\",\t\tNx::ScriptPullTextureToEdge},\r\n\t{\"PushTextureToPoint\",\t\tNx::ScriptPushTextureToPoint},\r\n\t{\"AdjustTextureBrightness\",\tNx::ScriptAdjustTextureBrightness},\r\n\t{\"AdjustTextureHSV\",\t\tNx::ScriptAdjustTextureHSV},\r\n\t{\"CopyTexture\",\t\t\t\tNx::ScriptCopyTexture},\r\n\t{\"CombineTextures\",\t\t\tNx::ScriptCombineTextures},\r\n\t{\"LoadParticleTexture\",\t\tNx::ScriptLoadParticleTexture},\r\n\t{\"UnloadParticleTexture\",\tNx::ScriptUnloadParticleTexture},\r\n\t{\"LoadSFPTexture\",\t\t\tNx::ScriptLoadSFPTexture},\r\n\t{\"UnloadSFPTexture\",\t\tNx::ScriptUnloadSFPTexture},\r\n\t{\"DumpTextures\",\t\t\tNx::ScriptDumpTextures},\r\n\r\n\t{\"SetModelFaceTexturePoints\", Nx::ScriptSetModelFaceTexturePoints},\r\n\t{\"SetFaceMassageTextureOverlay\", Nx::ScriptSetFaceMassageTextureOverlay},\r\n\t{\"MassageFaceTexture\",\t\tNx::ScriptMassageFaceTexture},\r\n\t{\"AdjustFaceTextureToModel\", Nx::ScriptAdjustFaceTextureToModel},\r\n\t{\"CombineFaceTextureWithOverlay\", Nx::ScriptCombineFaceTextureWithOverlay},\r\n\r\n\t{\"SetLightAmbientColor\",  \tNx::ScriptSetLightAmbientColor},\r\n\t{\"SetLightDirection\",\t\tNx::ScriptSetLightDirection},\r\n\t{\"SetLightDiffuseColor\",\tNx::ScriptSetLightDiffuseColor},\r\n\t{\"PushWorldLights\",\t\t\tNx::ScriptPushWorldLights},\r\n\t{\"PopWorldLights\",\t\t\tNx::ScriptPopWorldLights},\r\n\r\n\t{\"SetColorBufferClear\",\t\tCFuncs::ScriptSetColorBufferClear},\r\n\r\n\t{\"SetEventHandler\",\t\t\tCFuncs::ScriptSetEventHandler},\t   \r\n\t{\"ClearEventHandler\",\t\tCFuncs::ScriptClearEventHandler},\r\n\t{\"ClearEventHandlerGroup\",\tCFuncs::ScriptClearEventHandlerGroup},\r\n\t{\"OnExceptionRun\",\t\t\tCFuncs::ScriptOnExceptionRun},\r\n\t{\"OnExitRun\",\t\t\t\tCFuncs::ScriptOnExitRun},\r\n\t\r\n\t{\"SetUVWibbleParams\",  \t\tCFuncs::ScriptSetUVWibbleParams},\r\n\t{\"EnableExplicitUVWibble\",\tCFuncs::ScriptEnableExplicitUVWibble},\r\n\t{\"DisableExplicitUVWibble\",\tCFuncs::ScriptDisableExplicitUVWibble},\r\n\t{\"SetUVWibbleOffsets\",\t\tCFuncs::ScriptSetUVWibbleOffsets},\r\n\r\n\t{\"ToggleMetricItem\",\t\tCFuncs::ScriptToggleMetricItem},\r\n\t{\"ToggleMemMetrics\",\t\tCFuncs::ScriptToggleMemMetrics},\r\n\r\n\t{\"KillAllTextureSplats\",\tCFuncs::ScriptKillAllTextureSplats},\r\n\t\r\n\t{\"PreloadModels\",\t\t\tCFuncs::ScriptPreloadModels},\r\n\t{\"PreloadPedestrians\",\t\tCFuncs::ScriptPreloadPedestrians},\r\n\t{\"PreselectRandomPedestrians\",\t\tCFuncs::ScriptPreselectRandomPedestrians},\r\n\t{\"ReplaceCarTextures\",\t\tCFuncs::ScriptReplaceCarTextures},\r\n\r\n\t{\"LoadSound\",\t\t\t\tCFuncs::ScriptLoadSound},\r\n    // PlaySound \"SoundName\" Vol=100 Pitch=100\r\n\t{\"PlaySound\",\t\t\t\tCFuncs::ScriptPlaySound},\r\n\t{\"StopSound\",\t\t\t\tCFuncs::ScriptStopSound},\r\n\t{\"StopAllSounds\",\t\t\tCFuncs::ScriptStopAllSounds},\r\n\t{\"SetSoundParams\",\t\t\tCFuncs::ScriptSetSoundParams},\r\n\t{\"IsSoundPlaying\",\t\t\tCFuncs::ScriptIsSoundPlaying},\r\n\t// 0-100 for zero to 100percent reverb level...\r\n\t{\"SetSfxReverb\",   \t\t\tCFuncs::ScriptSetReverb},\r\n\t{\"SetSfxVolume\",   \t\t\tCFuncs::ScriptSetVolume},\r\n\t{\"SetSfxDropoff\",\t\t\tCFuncs::ScriptSetDropoff},\r\n\t{\"LoadTerrainSounds\",\t\tCFuncs::ScriptLoadTerrainSounds},\r\n\t{\"SetObjectColor\",\t\t\tCFuncs::ScriptSetObjectColor},\r\n\t{\"SetSceneColor\",\t\t\tCFuncs::ScriptSetSceneColor},\r\n\t{\"CompressVC\",\t\t\t\tCFuncs::ScriptCompressVC},\r\n\t{\"NudgeVC\",\t\t\t\t\tCFuncs::ScriptNudgeVC},\r\n\t{\"FakeLights\",\t\t\t\tCFuncs::ScriptFakeLights},\r\n\t{\"CenterCamera\",\t\t\tCFuncs::ScriptCenterCamera},\r\n\t// music tracks commands:\r\n\t{\"SetMusicVolume\",\t\t\tCFuncs::ScriptSetMusicVolume},\r\n\t{\"SetMusicStreamVolume\",\tCFuncs::ScriptSetMusicStreamVolume},\r\n\t{\"PlayTrack\",\t\t\t\tCFuncs::ScriptPlayTrack},\r\n\t{\"PlayMusicStream\",\t\t\tCFuncs::ScriptPlayMusicStream},\r\n\t{\"SkipMusicTrack\", \t\t\tCFuncs::ScriptSkipMusicTrack},\r\n\t{\"PauseMusic\",\t\t\t\tCFuncs::ScriptPauseMusic},\r\n\t{\"StopMusic\",\t\t\t\tCFuncs::ScriptStopMusic},\r\n\t{\"SetMusicMode\",\t\t\tCFuncs::ScriptSetMusicMode},\r\n\t{\"SetRandomMode\",\t\t\tCFuncs::ScriptSetRandomMode},\r\n\t{\"SetMusicLooping\",\t\t\tCFuncs::ScriptSetMusicLooping},\r\n\t{\"LoadMusicHeader\",\t\t\tCFuncs::ScriptLoadMusicHeader},\r\n\t{\"LoadStreamHeader\",\t\tCFuncs::ScriptLoadStreamHeader},\r\n\t{\"StreamIsAvailable\",\t\tCFuncs::ScriptStreamIsAvailable}, // only can be used in the skateshop!\r\n\t// tracks added to the tracklist get played randomly during the game...\r\n\t{\"AddMusicTrack\",\t\t\tCFuncs::ScriptAddMusicTrack},\r\n\t{\"ChangeTrackState\",\t\tCFuncs::ScriptChangeTrackState},\r\n    {\"GetCurrentTrack\",\t\t    CFuncs::ScriptGetCurrentTrack},\r\n\t{\"TrackEnabled\",\t\t\tCFuncs::ScriptTrackEnabled},\r\n\t{\"MusicIsPaused\",\t\t\tCFuncs::ScriptMusicIsPaused},\r\n\t{\"ClearMusicTrackList\",\t\tCFuncs::ScriptClearMusicTrackList},\r\n\t{\"PlayStream\",\t\t\t\tCFuncs::ScriptPlayStream},\r\n\t{\"StopStream\",\t\t\t\tCFuncs::ScriptStopStream},\r\n\t{\"PauseStream\",\t\t\t\tCFuncs::ScriptPauseStream},\r\n\t{\"SetStreamParams\",\t\t\tCFuncs::ScriptSetStreamParams},\r\n\t{\"IsStreamPlaying\",\t\t\tCFuncs::ScriptIsStreamPlaying},\r\n\t{\"LoadStreamFrameAmp\",\t\tCFuncs::ScriptLoadStreamFrameAmp},\r\n\t{\"FreeStreamFrameAmp\",\t\tCFuncs::ScriptFreeStreamFrameAmp},\r\n\t{\"PlayMovie\",\t\t\t\tCFuncs::ScriptPlayMovie},\r\n\t\r\n\t{\"SetGameType\",\t\t\t\tMdl::ScriptSetGameType},\r\n\t{\"InTeamGame\",\t\t\t\tMdl::ScriptInTeamGame},\r\n\t{\"SetNumTeams\",\t\t\t\tGameNet::Manager::ScriptSetNumTeams},\r\n\t{\"GetNumTeams\",\t\t\t\tGameNet::Manager::ScriptGetNumTeams},\r\n\t{\"GetNumPlayersOnTeam\",\t\tGameNet::Manager::ScriptGetNumPlayersOnTeam},\r\n\t{\"GetMyTeam\",\t\t\t\tGameNet::Manager::ScriptGetMyTeam},\r\n\t{\"JoinTeam\",\t\t\t\tGameNet::Manager::ScriptJoinTeam},\r\n\t{\"GetCollidingPlayerAndTeam\", CFuncs::ScriptGetCollidingPlayerAndTeam},\r\n    {\"LobbyCheckKeyboard\",      CFuncs::ScriptLobbyCheckKeyboard},\r\n\t{\"TestGameType\",\t\t\tMdl::ScriptTestGameType},\r\n\t{\"TestRequestedGameType\",\tMdl::ScriptTestRequestedGameType},\r\n\t{\"ChangeLevel\",\t\t\t\tMdl::ScriptChangeLevel},\r\n\t{\"LaunchLevel\",\t\t\t\tMdl::ScriptLaunchLevel},\r\n\t{\"RequestLevel\",\t\t\tMdl::ScriptRequestLevel},\r\n\t{\"Retry\",\t\t\t\t\tMdl::ScriptRetry},\r\n\t{\"LaunchGame\",\t\t\t\tMdl::ScriptLaunchGame},\r\n\t{\"ResetLevel\",\t\t\t\tMdl::ScriptResetLevel},\r\n\t{\"FillRankingScreen\",\t\tMdl::ScriptFillRankingScreen},\r\n\t{\"InitSkaterHeaps\",\t\t\tMdl::ScriptInitSkaterHeaps},\r\n\r\n\t{\"NodeExists\",\t\t\t\tCFuncs::ScriptNodeExists},\r\n\t{\"Create\",\t\t\t\t\tCFuncs::ScriptCreate},\r\n\t{\"CreateFromStructure\",\t\tCFuncs::ScriptCreateFromStructure},\r\n\t{\"Kill\",\t\t\t\t\tCFuncs::ScriptKill},\r\n\t{\"Visible\",\t\t\t\t\tCFuncs::ScriptVisible},\r\n\t{\"Invisible\",\t\t\t\tCFuncs::ScriptInvisible},\r\n\t{\"Shatter\",\t\t\t\t\tCFuncs::ScriptShatter},\r\n\r\n\t{\"ToggleSkaterCamMode\",\t\t\t\tCFuncs::ScriptToggleSkaterCamMode},\r\n\t{\"SetSkaterCamLerpReductionTimer\",\tCFuncs::ScriptSetSkaterCamLerpReductionTimer},\r\n\t\r\n\t{\"PlaySkaterCamAnim\",\t\t\t\tCFuncs::ScriptPlaySkaterCamAnim},\r\n\t{\"SetSkaterCamAnimSkippable\",\t\tCFuncs::ScriptSetSkaterCamAnimSkippable},\r\n\t{\"SetSkaterCamAnimShouldPause\",\t\tCFuncs::ScriptSetSkaterCamAnimShouldPause},\r\n\t{\"SkaterCamAnimFinished\",\t\t\tCFuncs::ScriptSkaterCamAnimFinished},\r\n\t{\"SkaterCamAnimHeld\",\t\t\t\tCFuncs::ScriptSkaterCamAnimHeld},\r\n\t{\"KillSkaterCamAnim\",\t\t\t\tCFuncs::ScriptKillSkaterCamAnim},\r\n\t{\"GetSkaterCamAnimParams\",\t\t\tCFuncs::ScriptGetSkaterCamAnimParams},\r\n\t{\"GetCurrentSkaterCamAnimName\",\t\tCFuncs::ScriptGetCurrentSkaterCamAnimName},\r\n\r\n\t{\"PlayMovingObjectAnim\",\t\t   \tCFuncs::ScriptPlayMovingObjectAnim},\r\n\t{\"SetMovingObjectAnimSkippable\",\tCFuncs::ScriptSetMovingObjectAnimSkippable},\r\n\t{\"SetMovingObjectAnimShouldPause\",\tCFuncs::ScriptSetMovingObjectAnimShouldPause},\r\n\t{\"MovingObjectAnimFinished\",\t\tCFuncs::ScriptMovingObjectAnimFinished},\r\n\t{\"MovingObjectAnimHeld\",\t\t\tCFuncs::ScriptMovingObjectAnimHeld},\r\n\t{\"KillMovingObjectAnim\",\t\t\tCFuncs::ScriptKillMovingObjectAnim},\r\n\r\n\t{\"PlayCutscene\",\t\t   \tCFuncs::ScriptPlayCutscene},\r\n\t{\"IsMovieQueued\",\t\t   \tCFuncs::ScriptIsMovieQueued},\r\n\t{\"HasMovieStarted\",\t\t   \tCFuncs::ScriptHasMovieStarted},\r\n\t\r\n\t// (most of the cutscene functions are actually the same\r\n\t// as the movingobjectanim-style functions)\r\n\t{\"SetCutsceneSkippable\",\tCFuncs::ScriptSetSkaterCamAnimSkippable},\r\n\t{\"SetCutsceneShouldPause\",\tCFuncs::ScriptSetSkaterCamAnimShouldPause},\r\n\t{\"CutsceneFinished\",\t\tCFuncs::ScriptSkaterCamAnimFinished},\r\n\t{\"CutsceneHeld\",\t\t\tCFuncs::ScriptSkaterCamAnimHeld},\r\n\t{\"KillCutscene\",\t\t\tCFuncs::ScriptKillSkaterCamAnim},\r\n\r\n\t{\"SkaterDebugOn\",\t\t\tCFuncs::ScriptSkaterDebugOn},\r\n\t{\"SkaterDebugOff\",\t\t\tCFuncs::ScriptSkaterDebugOff},\r\n\t{\"IfDebugOn\",\t\t\t\tCFuncs::ScriptIfDebugOn},\r\n\t{\"IfDebugOff\",\t\t\t\tCFuncs::ScriptIfDebugOff},\r\n\t{\"Bootstrap\",\t\t\t\tCFuncs::ScriptBootstrap},\r\n\t{\"CD\",\t\t\t\t\t\tCFuncs::ScriptCD},\r\n\t{\"NotCD\",\t\t\t\t\tCFuncs::ScriptNotCD},\r\n\t{\"Gunslinger\",\t\t\t\tCFuncs::ScriptGunslinger},\r\n\t{\"CasArtist\",\t\t\t\tCFuncs::ScriptCasArtist},\r\n\t{\"NotCasArtist\",\t\t\tCFuncs::ScriptNotCasArtist},\r\n\t{\"SendFlag\",\t\t\t\tCFuncs::ScriptSendFlag},\r\n\t{\"ClearFlag\",\t\t\t\tCFuncs::ScriptClearFlag},\r\n\t{\"QueryFlag\",\t\t\t\tCFuncs::ScriptQueryFlag},\r\n\t{\"SendException\",\t\t\tCFuncs::ScriptFlagException},\r\n\t{\"IsAlive\",\t\t\t\t\tCFuncs::ScriptCheckIfAlive},\r\n\r\n\t{\"MakeSkaterGoto\",\t\t\tCFuncs::ScriptMakeSkaterGoto},\r\n\t{\"MakeSkaterGosub\",\t\t\tCFuncs::ScriptMakeSkaterGosub},\r\n\r\n\t{\"LaunchMenuScreen\",\t\tMdl::ScriptLaunchMenuScreen},\r\n\t{\"UseOnePadInFrontEnd\",\t\tCFuncs::ScriptDummyCommand},\r\n\t{\"SetMenuAutoRepeatTimes\",\tMdl::ScriptSetMenuAutoRepeatTimes},\r\n\t{\"SetMenuPadMappings\",\t\tMdl::ScriptSetMenuPadMappings},\r\n\t{\"SetButtonEventMappings\",\tMdl::ScriptSetButtonEventMappings},\r\n\t{\"SetAnalogStickActiveForMenus\",\tMdl::ScriptSetAnalogStickActiveForMenus},\r\n\r\n\t{\"ControllerPressed\",\t\tCFuncs::ScriptControllerPressed},\r\n\t{\"ControllerDebounce\",\t\tCFuncs::ScriptControllerDebounce},\r\n\t{\"GetAnalogueInfo\",\t\t\tCFuncs::ScriptGetAnalogueInfo},\r\n\r\n\t{\"SetScreenMode\",\t\t\tCFuncs::ScriptSetScreenMode},\r\n\t{\"ScriptGetScreenMode\",\t\tNx::ScriptGetScreenMode},\r\n\t{\"SetScreenModeFromGameMode\",\tCFuncs::ScriptSetScreenModeFromGameMode},\r\n\t{\"Set2DIn3DSpaceParams\",\t\tNx::ScriptSet2DIn3DSpaceParams},\r\n\t\r\n\r\n\t{\"SpawnScript\",\t\t\t\tCFuncs::ScriptSpawnScript},\r\n\t{\"SpawnSound\",\t\t\t\tCFuncs::ScriptSpawnSound},\r\n\t{\"SpawnSkaterScript\",\t\tCFuncs::ScriptSpawnSkaterScript},\r\n\t{\"KillSpawnedScript\",\t\tCFuncs::ScriptKillSpawnedScript},\r\n\t{\"PauseSkaters\",\t\t\tCFuncs::ScriptPauseSkaters},\r\n\t{\"UnPauseSkaters\",\t\t\tCFuncs::ScriptUnPauseSkaters},\r\n\t{\"PauseSkater\",\t\t\t\tCFuncs::ScriptPauseSkater},\r\n\t{\"UnPauseSkater\",\t\t\tCFuncs::ScriptUnPauseSkater},\r\n\r\n\t{\"PauseGame\",\t\t\t\tCFuncs::ScriptPauseGame},\r\n\t{\"UnPauseGame\",\t\t\t\tCFuncs::ScriptUnPauseGame},\r\n    {\"GameIsPaused\",\t\t\tCFuncs::ScriptIsGamePaused},\r\n\r\n\t{\"PauseObjects\",\t\t\tCFuncs::ScriptPauseObjects},\r\n\t{\"UnPauseObjects\",\t\t\tCFuncs::ScriptUnPauseObjects},\r\n\r\n\t{\"PauseSpawnedScripts\",\t\tCFuncs::ScriptPauseSpawnedScripts},\r\n\t{\"UnPauseSpawnedScripts\",\tCFuncs::ScriptUnPauseSpawnedScripts},\r\n\r\n\t// clock related functions\r\n\t{\"ResetClock\",\t\t\t\tCFuncs::ScriptResetClock},\r\n\t{\"PadsPluggedIn\",\t\t\tCFuncs::ScriptPadsPluggedIn},\r\n\t{\"DoFlash\",\t\t\t\t\tCFuncs::ScriptDoFlash},\r\n\r\n\t{\"InPreFile\",\t\t\t\tFile::ScriptInPreFile},\r\n\t{\"LoadPreFile\",\t\t\t\tFile::ScriptLoadPreFile},\r\n\t{\"UnloadPreFile\",\t\t\tFile::ScriptUnloadPreFile},\r\n\t{\"IsLoadPreFinished\",\t\tFile::ScriptIsLoadPreFinished},\r\n\t{\"AllLoadPreFinished\",\t\tFile::ScriptAllLoadPreFinished},\r\n\t{\"WaitLoadPre\",\t\t\t\tFile::ScriptWaitLoadPre},\r\n\t{\"WaitAllLoadPre\",\t\t\tFile::ScriptWaitAllLoadPre},\r\n\t{\"LoadPipPre\",\t\t\t\tPip::ScriptLoadPipPre},\r\n\t{\"UnLoadPipPre\",\t\t\tPip::ScriptUnloadPipPre},\r\n\t{\"DumpPipPreStatus\",\t\tPip::ScriptDumpPipPreStatus},\r\n\t{\"StartServer\",\t\t\t\tCFuncs::ScriptStartServer},\r\n\t{\"SpawnCrown\",\t\t\t\tGameNet::Manager::ScriptSpawnCrown},\r\n\t{\"StartCTFGame\",\t\t\tGameNet::Manager::ScriptStartCTFGame},\r\n\t{\"EndCTFGame\",\t\t\t\tGameNet::Manager::ScriptEndCTFGame},\r\n\t{\"PlayerTookFlag\",\t\t\tGameNet::Manager::ScriptTookFlag},\r\n\t{\"PlayerCapturedFlag\",\t\tGameNet::Manager::ScriptCapturedFlag},\r\n\t{\"PlayerRetrievedFlag\",\t\tGameNet::Manager::ScriptRetrievedFlag},\r\n\t{\"PlayerHasFlag\",\t\t\tGameNet::Manager::ScriptHasFlag},\r\n    {\"TeamFlagTaken\",\t\t\tGameNet::Manager::ScriptTeamFlagTaken},\r\n\t{\"DisplayFlagBaseWarning\",\tGameNet::Manager::ScriptDisplayFlagBaseWarning},\r\n\t{\"FindServers\",\t\t\t\tCFuncs::ScriptFindServers},\r\n\t{\"FoundServers\",\t\t\tGameNet::Manager::ScriptFoundServers},\r\n\t{\"JoinServer\",\t\t\t\tCFuncs::ScriptJoinServer},\r\n\t{\"LeaveServer\",\t\t\t\tCFuncs::ScriptLeaveServer},\r\n\t{\"SetNetworkMode\",\t\t\tCFuncs::ScriptSetNetworkMode},\r\n\t{\"SetServerMode\",\t\t\tCFuncs::ScriptSetServerMode},\r\n\t{\"StartNetworkGame\",\t\tGameNet::Manager::ScriptStartNetworkGame},\r\n\t{\"NetworkGamePending\",\t\tGameNet::Manager::ScriptNetworkGamePending},\r\n\t{\"EndNetworkGame\", \t\t\tGameNet::Manager::ScriptEndNetworkGame},\r\n\t{\"EnteredNetworkGame\",\t\tGameNet::Manager::ScriptEnteredNetworkGame},\r\n\t{\"JustStartedNetGame\",\t\tGameNet::Manager::ScriptJustStartedNetGame},\r\n\t{\"OverrideGameModeOptions\",\tGame::ScriptOverrideGameModeOptions},\r\n\r\n\t{\"ResetCamera\",\t\t\t\tCFuncs::ScriptResetCamera},\r\n\t{\"GetValueFromVolume\",\t\tCFuncs::ScriptGetValueFromVolume},\r\n\t{\"SetSliderValue\",\t\t\tCFuncs::ScriptSetSliderValue},\r\n\t{\"SetVolumeFromValue\",\t\tCFuncs::ScriptSetVolumeFromValue},\r\n\t\r\n\t{\"ResetDefaultAppearance\",\tCFuncs::ScriptResetDefaultAppearance},\r\n\t{\"ResetDefaultTricks\",\t\tCFuncs::ScriptResetDefaultTricks},\r\n\t{\"ResetDefaultStats\",\t\tCFuncs::ScriptResetDefaultStats},\r\n\t{\"RandomizeAppearance\",\t\tCFuncs::ScriptRandomizeAppearance},\r\n\t{\"PrintCurrentAppearance\",\tCFuncs::ScriptPrintCurrentAppearance},\r\n\t{\"SetNeversoftSkater\",\t\tCFuncs::ScriptSetNeversoftSkater},\r\n\t{\"CurrentProfileIsLocked\",\tCFuncs::ScriptCurrentProfileIsLocked},\r\n\t{\"SetIconTexture\",\t\t\tCFuncs::ScriptSetIconTexture},\r\n\t\r\n\t{\"MemViewToggle\",           CFuncs::ScriptMemViewToggle},\r\n\r\n    {\"EnableFog\",\t\t\t\tCFuncs::ScriptEnableFog},\r\n    {\"DisableFog\",\t\t\t\tCFuncs::ScriptDisableFog},\r\n    {\"SetFogDistance\",\t\t\tCFuncs::ScriptSetFogDistance},\r\n    {\"SetFogExponent\",\t\t\tCFuncs::ScriptSetFogExponent},\r\n\t{\"SetFogColor\",\t\t\t\tCFuncs::ScriptSetFogColor},\r\n\t\r\n\t{\"Change\",\t\t\t\t\tCFuncs::ScriptChangeSymbolValue},\r\n\t{\"PreferenceEquals\",\t\tCFuncs::ScriptPreferenceEquals},\r\n\t{\"SetUIFromPreferences\",\tCFuncs::ScriptSetUIFromPreferences},\r\n\t{\"SetUIFromSkaterProfile\",\tCFuncs::ScriptSetUIFromSkaterProfile},\r\n\t{\"SetPreference\",\t\t\tCFuncs::ScriptSetPreference},\r\n\t{\"SetPreferencesFromUI\",\tCFuncs::ScriptSetPreferencesFromUI},\r\n\t{\"GetPreferenceString\",\t\tCFuncs::ScriptGetPreferenceString},\r\n\t{\"GetPreferencePassword\",\tCFuncs::ScriptGetPreferencePassword},\r\n\t{\"GetPreferenceChecksum\",\tCFuncs::ScriptGetPreferenceChecksum},\r\n\t\r\n\t{\"MemPushContext\",\t\t\tCFuncs::ScriptMemPushContext},\r\n\t{\"MemPopContext\",\t\t\tCFuncs::ScriptMemPopContext},\r\n\t{\"ProfileTasks\",\t\t\tCFuncs::ScriptProfileTasks},\r\n\t{\"UseNetworkPreferences\",\tCFuncs::ScriptUseNetworkPreferences},\r\n\t{\"CanChangeDevices\",\t\tCFuncs::ScriptCanChangeDevices},\r\n\t{\"NeedToTestNetSetup\",\t\tCFuncs::ScriptNeedToTestNetSetup},\r\n\t{\"TestNetSetup\",\t\t\tCFuncs::ScriptTestNetSetup},\r\n\t{\"StopAllScripts\",\t\t\tCFuncs::ScriptStopAllScripts},\r\n\t{\"SetMenuElementText\",\t\tCFuncs::ScriptSetMenuElementText},\r\n\t{\"FirstTimeThisIsCalled\",\tCFuncs::ScriptFirstTimeThisIsCalled},\r\n\t{\"VibrationIsOn\",\t\t\tCFuncs::ScriptVibrationIsOn},\r\n\t{\"VibrationOff\",\t\t\tCFuncs::ScriptVibrationOff},\r\n\t{\"VibrationOn\",\t\t\t\tCFuncs::ScriptVibrationOn},\r\n\t{\"VibrateController\",\t\tCFuncs::ScriptVibrateController},\r\n\t{\"EnableActuators\",\t\t\tCFuncs::ScriptEnableActuators},\r\n\t{\"AutoKickIsOn\",\t\t\tCFuncs::ScriptAutoKickIsOn},\r\n\t{\"AutoKickOn\",\t\t\t\tCFuncs::ScriptAutoKickOn},\r\n\t{\"AutoKickOff\",\t\t\t\tCFuncs::ScriptAutoKickOff},\r\n\t{\"SpinTapsAreOn\",\t\t\tCFuncs::ScriptSpinTapsAreOn},\r\n\t{\"SpinTapsOn\",\t\t\t\tCFuncs::ScriptSpinTapsOn},\r\n\t{\"SpinTapsOff\",\t\t\t\tCFuncs::ScriptSpinTapsOff},\r\n\t{\"IsOnline\",\t\t\t\tCFuncs::ScriptIsOnline},\r\n\t{\"ConnectToInternet\",\t\tCFuncs::ScriptConnectToInternet},\r\n\t{\"CancelConnectToInternet\",\tCFuncs::ScriptCancelConnectToInternet},\r\n\t{\"CancelLogon\",\t\t\t\tCFuncs::ScriptCancelLogon},\r\n\t{\"DisconnectFromInternet\",\tCFuncs::ScriptDisconnectFromInternet},\r\n\t{\"InNetGame\",\t\t\t\tCFuncs::ScriptInNetGame},\r\n\t{\"DumpScripts\",\t\t\t\tCFuncs::ScriptDumpScripts},\r\n\t{\"SetSlomo\",\t\t\t\tCFuncs::ScriptSetSlomo},\r\n\t{\"SetArenaSize\",\t\t\tCFuncs::ScriptSetArenaSize},\r\n\t{\"ToggleNetMetrics\",\t\tCFuncs::ScriptToggleNetMetrics },\r\n\t{\"GetCurrentProDisplayInfo\",CFuncs::ScriptGetCurrentProDisplayInfo},\r\n\t{\"SetPlayerAppearance\",\t\tCFuncs::ScriptSetPlayerAppearance},\r\n\t{\"SetPlayerFaceTexture\",\tCFuncs::ScriptSetPlayerFaceTexture},\r\n    {\"SetPlayerFaceOverlayTexture\",\tCFuncs::ScriptSetPlayerFaceOverlayTexture},\r\n\t{\"ClearPlayerFaceTexture\",\tCFuncs::ScriptClearPlayerFaceTexture},\r\n\t{\"GetPlayerFacePoints\",\t\tCFuncs::ScriptGetPlayerFacePoints},\r\n\t{\"SetPlayerFacePoints\",\t\tCFuncs::ScriptSetPlayerFacePoints},\r\n\t{\"PlayerFaceIsValid\",\t\tCFuncs::ScriptPlayerFaceIsValid},\r\n\t{\"SelectCurrentSkater\",\t\tCFuncs::ScriptSelectCurrentSkater},\r\n\t{\"SetParticleSysVisibility\",CFuncs::ScriptSetParticleSysVisibility},\r\n\t{\"TogglePlayerNames\",\t\tCFuncs::ScriptTogglePlayerNames},\r\n\t{\"SetCurrentGameType\",\t\tCFuncs::ScriptSetCurrentGameType},\r\n\t{\"DumpNetMessageStats\",\t\tCFuncs::ScriptDumpNetMessageStats},\r\n\t{\"NotifyBailDone\",\t\t\tCFuncs::ScriptNotifyBailDone},\r\n\t{\"ClearPowerups\",\t\t\tCFuncs::ScriptClearPowerups},\r\n\t{\"BroadcastProjectile\",\t\tCFuncs::ScriptBroadcastProjectile},\r\n\t{\"BroadcastEnterVehicle\",\tCFuncs::ScriptBroadcastEnterVehicle},\r\n\r\n\t// Loading screen\r\n\t{\"DisplayLoadingScreen\",\tCFuncs::ScriptDisplayLoadingScreen},\r\n\t{\"HideLoadingScreen\",\t\tCFuncs::ScriptHideLoadingScreen},\r\n\r\n\t// Loading bar of loading screen\r\n\t{\"SetLoadingBarPos\",\t\tNx::ScriptSetLoadingBarPos},\r\n\t{\"SetLoadingBarSize\",\t\tNx::ScriptSetLoadingBarSize},\r\n\t{\"SetLoadingBarStartColor\",\tNx::ScriptSetLoadingBarStartColor},\r\n\t{\"SetLoadingBarEndColor\",\tNx::ScriptSetLoadingBarEndColor},\r\n\t{\"SetLoadingBarBorder\",\t\tNx::ScriptSetLoadingBarBorder},\r\n\t{\"SetLoadingBarBorderColor\",Nx::ScriptSetLoadingBarBorderColor},\r\n\r\n\t// park editor, ya munks\r\n\t{\"SetParkEditorTimeOfDay\",\tEd::ScriptSetParkEditorTimeOfDay},\r\n\t{\"GetParkEditorTimeOfDayScript\",Ed::ScriptGetParkEditorTimeOfDayScript},\r\n\t{\"RebuildParkNodeArray\",\tEd::ScriptRebuildParkNodeArray},\r\n\t{\"FreeUpMemoryForPlayingPark\",Ed::ScriptFreeUpMemoryForPlayingPark},\r\n\t{\"CalibrateMemoryGauge\",\tEd::ScriptCalibrateMemoryGauge},\r\n\t{\"GetParkEditorCursorPos\",\tEd::ScriptGetParkEditorCursorPos},\r\n\t{\"SwitchToParkEditorCamera\",Ed::ScriptSwitchToParkEditorCamera},\r\n\t{\"SetParkEditorState\",\t\tEd::ScriptSetParkEditorState},\r\n\t{\"SetParkEditorPauseMode\",\tEd::ScriptSetParkEditorPauseMode},\r\n\t{\"SetParkEditorMaxPlayers\",\tEd::ScriptSetParkEditorMaxPlayers},\r\n\t{\"GetParkEditorMaxPlayers\",\tEd::ScriptGetParkEditorMaxPlayers},\r\n\t{\"GetParkEditorMaxPlayersPossible\",Ed::ScriptGetParkEditorMaxPlayersPossible},\r\n\t{\"CustomParkMode\",\t\t\tEd::ScriptCustomParkMode},\r\n\t{\"CanCleanlyResizePark\",\tEd::ScriptCanCleanlyResizePark},\r\n\t#ifdef __PLAT_NGC__\r\n\t{\"WriteCompressedMapBuffer\",Ed::ScriptWriteCompressedMapBuffer},\r\n\t{\"RequiresDefragment\",\t\tEd::ScriptRequiresDefragment},\r\n\t{\"TopDownHeapTooLow\",\t\tEd::ScriptTopDownHeapTooLow},\r\n\t#endif\r\n\t{\"ResizePark\",\t\t\t\tEd::ScriptResizePark},\r\n\t{\"GetCurrentParkBounds\",\tEd::ScriptGetCurrentParkBounds},\r\n\t{\"CanChangeParkDimension\", \tEd::ScriptCanChangeParkDimension},\r\n\t{\"SaveParkToDisk\",\t\t\tEd::ScriptSaveParkToDisk},\r\n\t{\"LoadParkFromDisk\",\t\tEd::ScriptLoadParkFromDisk},\r\n\t{\"IsParkUnsaved\",\t\t\tEd::ScriptIsParkUnsaved},\r\n\t{\"FireCustomParkGap\",\t\tEd::ScriptFireCustomParkGap},\r\n\t{\"SetEditedParkGapInfo\",\tEd::ScriptSetEditedParkGapInfo},\r\n\t{\"GetEditedParkGapName\",\tEd::ScriptGetEditedParkGapName},\r\n\t{\"ParkEditorSelectionAreaTooBigToCopy\",Ed::ScriptParkEditorSelectionAreaTooBigToCopy},\r\n\t{\"CopyParkEditorSelectionToClipboard\",Ed::ScriptCopyParkEditorSelectionToClipboard},\r\n\t{\"SwitchParkEditorMenuPieceToMostRecentClipboard\",Ed::ScriptSwitchParkEditorMenuPieceToMostRecentClipboard},\r\n\t{\"CutParkEditorAreaSelection\",Ed::ScriptCutParkEditorAreaSelection},\r\n\t{\"ParkEditorAreaSelectionDeletePieces\",Ed::ScriptParkEditorAreaSelectionDeletePieces},\r\n\t{\"ContinueParkEditorAreaSelection\",\tEd::ScriptContinueParkEditorAreaSelection},\r\n\t{\"GetEditorTheme\",\t\t\tEd::ScriptGetEditorTheme},\r\n\t{\"SetEditorTheme\",\t\t\tEd::ScriptSetEditorTheme},\r\n\t{\"GetEditorMaxThemes\",\t\tEd::ScriptGetEditorMaxThemes},\r\n\t{\"GetCustomParkName\",\t\tEd::ScriptGetCustomParkName},\r\n\t{\"SetCustomParkName\",\t\tEd::ScriptSetCustomParkName},\r\n\t{\"BindParkEditorToController\",\tEd::ScriptBindParkEditorToController},\r\n\t{\"ParkEditorCommand\",\t\tCFuncs::ScriptDummyCommand},\r\n\t{\"ParkEditorGetGapName\",\tCFuncs::ScriptDummyCommand},\r\n\t{\"ParkEditorSetGapName\",\tCFuncs::ScriptDummyCommand},\r\n\t{\"IsCustomPark\",\t\t\tEd::ScriptIsCustomPark},\r\n\t{\"IsUnsavedPark\",\t\t\tCFuncs::ScriptDummyCommand},\r\n\t\r\n\t{\"ObserveNextSkater\",\t\tCFuncs::ScriptObserveNextSkater},\r\n\r\n\t// Prints the current memory usage of the bottom up heap\r\n\t{\"PrintMemInfo\",\t\t\tCFuncs::ScriptPrintMemInfo},\r\n\t{\"DisplayFreeMem\",      \tCFuncs::ScriptDisplayFreeMem},\r\n\t{\"AnalyzeHeap\",\t\t\t\tCFuncs::ScriptAnalyzeHeap},\r\n\t{\"SetMemThreadSafe\",\t\tCFuncs::ScriptMemThreadSafe},\r\n\t\r\n\t{\"CareerStartLevel\",\t\tCFuncs::ScriptCareerStartLevel},\r\n\t{\"CareerLevelIs\",\t\t\tCFuncs::ScriptCareerLevelIs},\r\n\t{\"CareerReset\",\t\t\t\tCFuncs::ScriptCareerReset},\r\n\t{\"SetGoal\",               \tCFuncs::ScriptSetGoal},        \r\n\t{\"UnSetGoal\",               CFuncs::ScriptUnSetGoal},        \r\n\t{\"GetGoal\",               \tCFuncs::ScriptGetGoal},        \r\n\t{\"JustGotGoal\",           \tCFuncs::ScriptJustGotGoal},    \r\n\t{\"SetFlag\",               \tCFuncs::ScriptSetFlag},        \r\n\t{\"UnSetFlag\",               CFuncs::ScriptUnSetFlag},        \r\n\t{\"GetFlag\",               \tCFuncs::ScriptGetFlag},        \r\n\t{\"JustGotFlag\",           \tCFuncs::ScriptJustGotFlag},\r\n\t{\"SetScoreGoal\",\t\t\tCFuncs::ScriptSetScoreGoal},\t\t\t\r\n\t{\"ClearScoreGoals\",\t\t\tCFuncs::ScriptClearScoreGoals},\t\t\t\r\n\r\n\t{\"SetGlobalFlag\",           CFuncs::ScriptSetGlobalFlag},        \r\n\t{\"UnSetGlobalFlag\",         CFuncs::ScriptUnSetGlobalFlag},        \r\n\t{\"GetGlobalFlag\",           CFuncs::ScriptGetGlobalFlag},        \r\n\t\r\n\t// Career-related functions...  these refer to skater 0,\r\n\t// so don't try to use these functions from a trick script.\r\n\t{\"ProfileEquals\",\t\t\tCFuncs::ScriptProfileEquals},\r\n\t{\"IsCareerMode\",\t\t\tCFuncs::ScriptIsCareerMode},\r\n\t{\"EndRun\",\t\t\t\t\tCFuncs::ScriptEndRun},\r\n\t{\"AllowPause\",\t\t\t\tCFuncs::ScriptAllowPause},\r\n\r\n\t{\"EnterObserverMode\",\t\tCFuncs::ScriptEnterObserverMode},\r\n\t{\"EnterSurveyorMode\",\t\tGameNet::Manager::ScriptEnterSurveyorMode},\r\n\t{\"ExitSurveyorMode\",\t\tGameNet::Manager::ScriptExitSurveyorMode},\r\n\t\r\n\t{\"RefreshServerList\",\t\tCFuncs::ScriptRefreshServerList},\r\n\t{\"SetJoinMode\",\t\t\t\tGameNet::Manager::ScriptSetJoinMode},\r\n\t{\"SetHostMode\",\t\t\t\tGameNet::Manager::ScriptSetHostMode},\r\n\t{\"IsHost\",\t\t\t\t\tGameNet::Manager::ScriptIsHost},\r\n\t{\"IsAutoServing\",\t\t\tGameNet::Manager::ScriptIsAutoServing},\r\n\t{\"ChangeLevelPending\",\t\tGameNet::Manager::ScriptChangeLevelPending},\r\n\t{\"ToggleProSet\",\t\t\tGameNet::Manager::ScriptToggleProSet},\r\n\t{\"ResetProSetFlags\",\t\tGameNet::Manager::ScriptResetProSetFlags},\r\n\t\t\r\n\t// Some gameflow-related tests\r\n\t{\"PauseGameFlow\",\t\t\tCFuncs::ScriptPauseGameFlow},\r\n\t{\"UnpauseGameFlow\",\t\t\tCFuncs::ScriptUnpauseGameFlow},\r\n\t{\"InFrontEnd\",\t\t\t\tCFuncs::ScriptInFrontEnd},\r\n\t{\"GetFireballLevel\",\t\tCFuncs::ScriptGetFireballLevel},\r\n\t{\"InSplitScreenGame\",\t\tCFuncs::ScriptInSplitScreenGame},\r\n\t{\"GameModeEquals\",\t\t\tCFuncs::ScriptGameModeEquals},\r\n\t{\"OnServer\",\t\t\t\tCFuncs::ScriptOnServer},\r\n\t{\"ShouldEndRun\",\t\t\tCFuncs::ScriptShouldEndRun},\r\n\t{\"InitializeSkaters\",\t\tCFuncs::ScriptInitializeSkaters},\r\n\t{\"SkatersAreReady\",\t\t\tCFuncs::ScriptSkatersAreReady},\r\n\t{\"RestartLevel\",\t\t\tCFuncs::ScriptRestartLevel},\r\n\t{\"EndRunSelected\",\t\t\tCFuncs::ScriptEndRunSelected},\r\n\t{\"AllSkatersAreIdle\",\t\tCFuncs::ScriptAllSkatersAreIdle},\r\n\t{\"FirstTrickStarted\",\t\tCFuncs::ScriptFirstTrickStarted},\r\n\t{\"FirstTrickCompleted\",\t\tCFuncs::ScriptFirstTrickCompleted},\r\n\t{\"CalculateFinalScores\",\tCFuncs::ScriptCalculateFinalScores},\r\n\t{\"ReinsertSkaters\",\t\t\tCFuncs::ScriptReinsertSkaters},\r\n\t{\"UnhookSkaters\",\t\t\tCFuncs::ScriptUnhookSkaters},\r\n\t{\"ToggleScores\",\t\t\tCFuncs::ScriptToggleScores},\r\n\t{\"ApplySplitScreenOptions\",\tCFuncs::ScriptApplySplitScreenOptions},\r\n\t{\"ApplyToSkaterProfile\",\tCFuncs::ScriptApplyToSkaterProfile},\r\n\t{\"RefreshSkaterColors\",\t\tCFuncs::ScriptRefreshSkaterColors},\r\n\t{\"RefreshSkaterScale\",\t\tCFuncs::ScriptRefreshSkaterScale},\r\n\t{\"RefreshSkaterVisibility\", CFuncs::ScriptRefreshSkaterVisibility},\r\n\t{\"RefreshSkaterUV\", \t\tCFuncs::ScriptRefreshSkaterUV},\r\n\t{\"IsTrue\",\t\t\t\t\tCFuncs::ScriptIsTrue},\r\n\t{\"InitSkaterModel\",\t\t\tCFuncs::ScriptInitSkaterModel},\r\n\t{\"RefreshSkaterModel\",\t\tCFuncs::ScriptRefreshSkaterModel},\r\n\t{\"EditPlayerAppearance\",\tCFuncs::ScriptEditPlayerAppearance},\r\n\t{\"GetCurrentSkaterProfileIndex\", CFuncs::ScriptGetCurrentSkaterProfileIndex},\r\n    {\"GetCustomSkaterName\",     CFuncs::ScriptGetCustomSkaterName},\r\n\r\n\t{\"GetCurrentLevel\",\t\t\tCFuncs::ScriptGetCurrentLevel},\r\n\r\n\t{\"StartCompetition\",\t\tCFuncs::ScriptStartCompetition},\r\n\t{\"EndCompetition\",\t\t\tCFuncs::ScriptEndCompetition},\r\n\t{\"CompetitionEnded\",\t\tCFuncs::ScriptCompetitionEnded},\r\n\t{\"StartCompetitionRun\",\t\tCFuncs::ScriptStartCompetitionRun},\r\n\t{\"EndCompetitionRun\",\t\tCFuncs::ScriptEndCompetitionRun},\r\n\r\n\t{\"StartHorse\",\t\t\t\tCFuncs::ScriptStartHorse},\r\n\t{\"EndHorse\",\t\t\t\tCFuncs::ScriptEndHorse},\r\n\t{\"HorseEnded\",\t\t\t\tCFuncs::ScriptHorseEnded},\r\n\t{\"HorseStatusEquals\",\t\tCFuncs::ScriptHorseStatusEquals},\r\n\t{\"StartHorseRun\",\t\t\tCFuncs::ScriptStartHorseRun},\r\n\t{\"EndHorseRun\",\t\t\t\tCFuncs::ScriptEndHorseRun},\r\n\t{\"SwitchHorsePlayers\",\t\tCFuncs::ScriptSwitchHorsePlayers},\r\n\t{\"GetHorseString\",\t\t\tCFuncs::ScriptGetHorseString},\r\n\t{\"IsCurrentHorseSkater\",\tCFuncs::ScriptIsCurrentHorseSkater},\r\n\t{\"ApplyToHorsePanelString\", CFuncs::ScriptApplyToHorsePanelString},\r\n\t\r\n\t{\"XTriggered\",\t\t\t\tCFuncs::ScriptXTriggered},\r\n\t{\"UsePad\",\t\t\t\t\tCFuncs::ScriptUsePad},\r\n\r\n\t{\"InMultiplayerGame\",\t\tCFuncs::ScriptInMultiplayerGame},\t\r\n\t{\"IsTopJudge\",\t\t\t\tCFuncs::ScriptIsTopJudge},\r\n\t{\"PlaceIs\",\t\t\t\t\tCFuncs::ScriptPlaceIs},\r\n\t{\"RoundIs\",\t\t\t\t\tCFuncs::ScriptRoundIs},\r\n\t\r\n\t{\"GameFlow\",\t\t\t\tCFuncs::ScriptGameFlow},\t\r\n\t{\"AwardStatPoint\",\t\t\tCFuncs::ScriptAwardStatPoint},\r\n\t{\"AwardSpecialTrickSlot\",\tCFuncs::ScriptAwardSpecialTrickSlot},\r\n\t{\"UpdateSkaterStats\",\t\tCFuncs::ScriptUpdateSkaterStats},\r\n\t\r\n\t{\"GoalsGreaterThan\",        CFuncs::ScriptGoalsGreaterThan},    \r\n\t{\"GoalsEqualTo\",            CFuncs::ScriptGoalsEqualTo},\r\n\t{\"MedalsGreaterThan\",       CFuncs::ScriptMedalsGreaterThan},   \r\n\t{\"MedalsEqualTo\",           CFuncs::ScriptMedalsEqualTo},       \r\n\t{\"StartServerList\",\t\t\tCFuncs::ScriptStartServerList},\r\n\t{\"StartLobbyList\",\t\t\tCFuncs::ScriptStartLobbyList},\r\n\t{\"NumServersInLobby\",\t\tGameNet::Manager::ScriptGetNumServersInLobby},\r\n#ifdef __PLAT_NGPS__\r\n\t{\"NumPlayersInLobby\",\t\tGameNet::LobbyMan::ScriptGetNumPlayersInLobby},\r\n\t{\"RejoinLobby\",\t\t\t\tGameNet::LobbyMan::ScriptRejoinLobby},\r\n\t{\"ChooseLobby\",\t\t\t\tGameNet::LobbyMan::ScriptChooseLobby},\r\n\t{\"LeaveLobby\",\t\t\t\tGameNet::LobbyMan::ScriptLeaveLobby},\r\n\t{\"LobbyConnect\",\t\t\tGameNet::LobbyMan::ScriptLobbyConnect},\r\n\t{\"LobbyDisconnect\",\t\t\tGameNet::LobbyMan::ScriptLobbyDisconnect},\r\n\t{\"FillLobbyProspectiveBuddyList\",\tGameNet::LobbyMan::ScriptFillLobbyProspectiveBuddyList},\r\n\t{\"StartNatNegotiation\",\t\tGameNet::LobbyMan::ScriptStartNatNegotiation},\r\n\t{\"CancelNatNegotiation\",\tGameNet::LobbyMan::ScriptCancelNatNegotiation},\r\n\t\r\n\t{\"CanHostGame\",             GameNet::LobbyMan::ScriptCanHostGame},\r\n\t{\"SendMessage\",\t\t\t\tGameNet::LobbyMan::ScriptSendMessage},\r\n\t{\"SetQuietMode\",\t\t\tGameNet::LobbyMan::ScriptSetQuietMode},\r\n\t{\"FillPlayerList\",\t\t\tGameNet::LobbyMan::ScriptFillPlayerList},\r\n\t{\"LoadNetConfigs\",\t\t\tGameNet::Manager::ScriptLoadNetConfigs},\r\n\t{\"NoNetConfigFiles\",\t\tGameNet::Manager::ScriptNoNetConfigFiles},\r\n\t{\"FillNetConfigList\",\t\tGameNet::Manager::ScriptFillNetConfigList},\r\n\t{\"ChooseNetConfig\",\t\t\tGameNet::Manager::ScriptChooseNetConfig},\r\n\t{\"FillPlayerListMenu\",\t\tGameNet::Manager::ScriptFillPlayerListMenu},\r\n\t{\"DownloadFace\",\t\t\tGameNet::ContentMan::ScriptDownloadFace},\r\n\t{\"UploadFile\",\t\t\t\tGameNet::ContentMan::ScriptUploadFile},\r\n\t{\"DownloadFile\",\t\t\tGameNet::ContentMan::ScriptDownloadFile},\r\n\t{\"DownloadDirectoryList\",\tGameNet::ContentMan::ScriptDownloadDirectoryList},\r\n\t{\"FreeDirectoryListing\",\tGameNet::ContentMan::ScriptFreeDirectoryListing},\r\n\t{\"FillVaultMenu\",\t\t\tGameNet::ContentMan::ScriptFillVaultMenu},\r\n\t{\"NextVaultCategory\",\t\tGameNet::ContentMan::ScriptNextVaultCategory},\r\n\t{\"PrevVaultCategory\",\t\tGameNet::ContentMan::ScriptPrevVaultCategory},\r\n\t{\"StatsLoggedIn\",\t\t\tGameNet::StatsMan::ScriptStatsLoggedIn},\r\n\t{\"StatsLogIn\",\t\t\t\tGameNet::StatsMan::ScriptStatsLogIn},\r\n\t{\"StatsLogOff\",\t\t\t\tGameNet::StatsMan::ScriptStatsLogOff},\r\n\t{\"ReportStats\",\t\t\t\tGameNet::StatsMan::ScriptReportStats},\r\n\t{\"RetrievePersonalStats\",\tGameNet::StatsMan::ScriptRetrievePersonalStats},\r\n\t{\"RetrieveTopStats\",\t\tGameNet::StatsMan::ScriptRetrieveTopStats},\r\n\t{\"NeedToRetrieveTopStats\",\tGameNet::StatsMan::ScriptNeedToRetrieveTopStats},\r\n\t{\"FillStatsArrays\",\t\t\tGameNet::StatsMan::ScriptFillStatsArrays},\r\n\t{\"GetRank\",\t\t\t\t\tGameNet::StatsMan::ScriptGetRank},\r\n\t{\"CleanUpTopStats\",\t\t\tGameNet::StatsMan::ScriptCleanUpTopStats},\r\n\t{\"ProfileLoggedIn\",\t\t\tGameNet::BuddyMan::ScriptProfileLoggedIn},\r\n\t{\"SetUniqueId\",\t\t\t\tGameNet::BuddyMan::ScriptSetUniqueId},\r\n\t{\"CreateProfile\",\t\t\tGameNet::BuddyMan::ScriptCreateProfile},\r\n\t{\"ProfileLogIn\",\t\t\tGameNet::BuddyMan::ScriptProfileLogIn},\r\n\t{\"ProfileLogOff\",\t\t\tGameNet::BuddyMan::ScriptProfileLogOff},\r\n\t{\"FillBuddyList\",\t\t\tGameNet::BuddyMan::ScriptFillBuddyList},\r\n\t{\"FillProspectiveBuddyList\",GameNet::BuddyMan::ScriptFillProspectiveBuddyList},\r\n\t{\"AddBuddy\",\t\t\t\tGameNet::BuddyMan::ScriptAddBuddy},\r\n\t{\"RemoveBuddy\",\t\t\t\tGameNet::BuddyMan::ScriptRemoveBuddy},\r\n\t{\"CancelAddBuddy\",\t\t\tGameNet::BuddyMan::ScriptCancelAddBuddy},\r\n\t{\"JoinBuddy\",\t\t\t\tGameNet::BuddyMan::ScriptJoinBuddy},\r\n\t{\"HasBuddies\",\t\t\t\tGameNet::BuddyMan::ScriptHasBuddies},\r\n\t{\"BuddyListFull\",\t\t\tGameNet::BuddyMan::ScriptBuddyListFull},\r\n\t{\"SetLobbyStatus\",\t\t\tGameNet::BuddyMan::ScriptSetLobbyStatus},\r\n\t{\"PostGame\",\t\t\t\tGameNet::Manager::ScriptPostGame},\r\n\t{\"AuthenticateClient\",\t\tGameNet::Manager::ScriptAuthenticateClient },\r\n\t{\"WriteDNASBinary\",\t\t\tGameNet::Manager::ScriptWriteDNASBinary },\r\n#endif\r\n\t{\"ConnectedToPeer\",\t\t\tGameNet::Manager::ScriptConnectedToPeer },\r\n\t{\"InGroupRoom\",\t\t\t\tGameNet::Manager::ScriptInGroupRoom},\r\n\t\r\n\t{\"ChooseServer\", \t\t\tGameNet::Manager::ScriptChooseServer},\r\n\t{\"DescribeServer\",\t\t\tGameNet::Manager::ScriptDescribeServer},\r\n\t{\"RetrieveServerInfo\",\t\tGameNet::Manager::ScriptRetrieveServerInfo},\r\n\t{\"CancelJoinServer\", \t\tGameNet::Manager::ScriptCancelJoinServer},\r\n\t{\"ReattemptJoinServer\",\t\tGameNet::Manager::ScriptReattemptJoinServer},\r\n\t{\"CreatePlayerOptions\",     GameNet::Manager::ScriptCreatePlayerOptions},\r\n\t{\"AllPlayersAreReady\",      GameNet::Manager::ScriptAllPlayersAreReady},\r\n\t\r\n\t{\"ChooseAccount\",\t\t\tGameNet::Manager::ScriptChooseAccount},\r\n\t{\"RemovePlayer\",\t\t\tGameNet::Manager::ScriptRemovePlayer},\r\n\t{\"CancelRemovePlayer\",\t\tGameNet::Manager::ScriptCancelRemovePlayer},\r\n\t{\"KickPlayer\",\t\t\t\tGameNet::Manager::ScriptKickPlayer},\r\n\t{\"BanPlayer\",\t\t\t\tGameNet::Manager::ScriptBanPlayer},\r\n\t{\"FCFSRequestStartGame\",\tGameNet::Manager::ScriptFCFSRequestStartGame},\r\n\t{\"FCFSRequestChangeLevel\",\tGameNet::Manager::ScriptFCFSRequestChangeLevel},\r\n\t{\"FCFSRequestToggleProSet\", GameNet::Manager::ScriptFCFSRequestToggleProSet},\r\n\t{\"FCFSRequestToggleGoalSelection\",\tGameNet::Manager::ScriptFCFSRequestToggleGoalSelection},\r\n\t{\"HasSignedDisclaimer\",\t\tGameNet::Manager::ScriptHasSignedDisclaimer},\r\n\t\r\n\t// \"Omnigon\" is code for \"cheat\". Just another attempt to NOT lead hackers directly to the\r\n\t// pile of gold\r\n\t{\"ClearOmnigons\",\t\t\tCFuncs::ScriptClearCheats},\r\n\t{\"BroadcastOmnigon\",\t\tCFuncs::ScriptBroadcastCheat},\r\n\t{\"LastBroadcastedOmnigonWas\",CFuncs::ScriptLastBroadcastedCheatWas},\r\n\t{\"OmnigonAllowed\",\t\t\tCFuncs::ScriptCheatAllowed},\r\n\r\n\t{\"JoinWithPassword\",\t\tCFuncs::ScriptJoinWithPassword},\r\n\t{\"GetRecordText\",\t\t\tCFuncs::ScriptGetRecordText},\r\n\t{\"UpdateRecords\",\t\t\tCFuncs::ScriptUpdateRecords},\r\n\t{\"SendChatMessage\",\t\t\tCFuncs::ScriptSendChatMessage},\r\n\t{\"InSlapGame\",\t\t\t\tCFuncs::ScriptInSlapGame},\r\n\t{\"LoadPendingPlayers\",\t\tCFuncs::ScriptLoadPendingPlayers},\r\n\t{\"DropPendingPlayers\",\t\tGameNet::Manager::ScriptDropPendingPlayers},\r\n\t{\"StopServerList\",\t\t\tCFuncs::ScriptStopServerList},\r\n\t{\"FreeServerList\",\t\t\tCFuncs::ScriptFreeServerList},\r\n\t{\"LaunchQueuedScripts\",     CFuncs::ScriptLaunchQueuedScripts},\r\n\t{\"IsObserving\",\t\t\t\tCFuncs::ScriptIsObserving},\r\n\t{\"GetInitialsString\",\t\tCFuncs::ScriptGetInitialsString},\r\n\t{\"SetInitialsString\",\t\tCFuncs::ScriptSetInitialsString},\r\n\t{\"UpdateInitials\",\t\t\tCFuncs::ScriptUpdateInitials},\r\n\t{\"NewRecord\",\t\t\t\tCFuncs::ScriptNewRecord},\r\n\t{\"AttachToSkater\",\t\t\tCFuncs::ScriptAttachToSkater},\r\n\t{\"TryCheatString\",\t\t\tCFuncs::ScriptTryCheatString},\r\n\t{\"LevelIs\",\t\t\t\t\tCFuncs::ScriptLevelIs},\r\n\t{\"StartNetworkLobby\",\t\tCFuncs::ScriptStartNetworkLobby},\r\n\t{\"ObserversAllowed\",\t\tCFuncs::ScriptObserversAllowed},\r\n\t{\"NumPlayersAllowed\",\t\tCFuncs::ScriptNumPlayersAllowed},\r\n\t{\"AutoDNS\",\t\t\t\t\tCFuncs::ScriptAutoDNS},\r\n\t{\"UsingDefaultMasterServers\",CFuncs::ScriptUsingDefaultMasterServers},\r\n\t{\"UsingDHCP\",\t\t\t\tCFuncs::ScriptUsingDHCP},\r\n\t{\"InInternetMode\",\t\t\tCFuncs::ScriptInInternetMode},\r\n\t{\"LoadExecPS2\",\t\t\t\tCFuncs::ScriptLoadExecPS2},\r\n\t{\"ExitDemo\",\t\t\t\tCFuncs::ScriptExitDemo},\r\n\t{\"SendGameOverToObservers\", GameNet::Manager::ScriptSendGameOverToObservers},\r\n\t{\"GameIsOver\", \t\t\t\tCFuncs::ScriptGameIsOver},\r\n\t{\"EnteringNetGame\",\t\t\tCFuncs::ScriptEnteringNetGame},\r\n\t{\"DeviceChosen\", \t\t\tCFuncs::ScriptDeviceChosen},\r\n\t{\"SetLevelName\",\t\t\tCFuncs::ScriptSetLevelName},\r\n\t{\"TrickOffAllObjects\",\t\tCFuncs::ScriptTrickOffAllObjects},\r\n\t{\"DumpHeaps\",\t\t\t\tCFuncs::ScriptDumpHeaps},\r\n\t{\"DumpFragments\",\t\t\tCFuncs::ScriptDumpFragments},\r\n\t{\"ResetPS2\",\t\t\t\tCFuncs::ScriptResetPS2},\r\n\t{\"ResetHD\",\t\t\t\t\tCFuncs::ScriptResetHD},\r\n\t{\"PAL\",\t\t\t\t\t\tCFuncs::ScriptPAL},\r\n\t{\"English\",\t\t\t\t\tCFuncs::ScriptEnglish},\r\n\t{\"TimeUp\",\t\t\t\t\tCFuncs::ScriptTimeUp},\r\n\t{\"LaunchEvent\",\t\t\t\tObj::ScriptLaunchEvent},\r\n\t{\"FireEvent\",\t\t\t\tObj::ScriptLaunchEvent},\t// LaunchEvent and FireEvent are the same\r\n\t{\"PrintEventLog\",\t\t\tObj::ScriptPrintEventLog},\r\n\t{\"ObjectExists\",\t\t\tObj::ScriptObjectExists},\r\n\t{\"TerminateObjectsScripts\",\tObj::ScriptTerminateObjectsScripts},\r\n\t{\"AssignAlias\",\t\t\t\tObj::ScriptAssignAlias},\r\n\t{\"SetObjectProps\",\t\t\tObj::ScriptSetObjectProperties},\r\n\t{\"CreateScreenElement\",\t\tFront::ScriptCreateScreenElement},\r\n\t{\"DestroyScreenElement\",\tFront::ScriptDestroyScreenElement},\r\n\t{\"RunScriptOnScreenElement\",\tFront::ScriptRunScriptOnScreenElement},\r\n\t{\"SetScreenElementProps\",\tFront::ScriptSetScreenElementProps},\r\n\t{\"GetScreenElementProps\",\tFront::ScriptGetScreenElementProps},\r\n\t{\"DoScreenElementMorph\",\tFront::ScriptDoScreenElementMorph},\r\n\t{\"SetScreenElementLock\",\tFront::ScriptSetScreenElementLock},\r\n\t{\"ScreenElementSystemInit\",\t\tFront::ScriptScreenElementSystemInit},\r\n\t{\"TextElementConcatenate\",\tFront::ScriptTextElementConcatenate},\r\n\t{\"TextElementBackspace\",\tFront::ScriptTextElementBackspace},\r\n\t{\"GetTextElementString\",\tFront::ScriptGetTextElementString},\r\n\t{\"GetTextElementLength\",\tFront::ScriptGetTextElementLength},\r\n\t{\"GetScreenElementDims\", \tFront::ScriptGetScreenElementDims},\r\n\t{\"GetScreenElementPosition\", Front::ScriptGetScreenElementPosition},\r\n\t{\"LaunchViewer\",\t\t\tCFuncs::ScriptLaunchViewer},\r\n\t{\"LaunchScriptDebugger\",\tCFuncs::ScriptLaunchScriptDebugger},\r\n\t{\"SetViewerModel\",\t\t\tCFuncs::ScriptSetViewerModel},\r\n\t{\"SetViewerAnim\",\t\t\tCFuncs::ScriptSetViewerAnim},\r\n\t{\"SetViewerLODDist\",\t\tCFuncs::ScriptSetViewerLODDist},\r\n\t{\"ReloadViewerAnim\",\t\tCFuncs::ScriptReloadViewerAnim},\r\n\t{\"ReloadSkaterCamAnim\",\t\tCFuncs::ScriptReloadSkaterCamAnim},\r\n\t{\"SetScoreDegradation\",\t\tCFuncs::ScriptGameModeSetScoreDegradation},\r\n\t{\"SetScoreAccumulation\",\tCFuncs::ScriptGameModeSetScoreAccumulation},\r\n\t{\"ResetScore\",\t\t\t\tCFuncs::ScriptResetScore},\r\n\t{\"ResetScorePot\", \t\t\tCFuncs::ScriptResetScorePot},\r\n\t{\"ResetScoreDegradation\",\tCFuncs::ScriptResetScoreDegradation},\r\n\t{\"UpdateScore\",\t\t\t\tCFuncs::ScriptUpdateScore},\r\n\t{\"AddRestartsToMenu\",\t\tCFuncs::ScriptAddRestartsToMenu},\r\n\t{\"AddGapsToMenu\",\t\t\tObj::ScriptAddGapsToMenu},\r\n\t{\"CreateGapList\",\t\t\tObj::ScriptCreateGapList},\r\n\t{\"GetLevelGapTotals\",\t\tObj::ScriptGetLevelGapTotals},\r\n\t{\"GiveAllGaps\",\t\t\t\tObj::ScriptGiveAllGaps},\r\n    {\"SetTimeLimit\",            Mdl::ScriptSetTimeLimit},\r\n\t{\"MenuSelectedIndexIs\",\t\tFront::ScriptMenuSelectedIndexIs},\r\n\t{\"ScreenElementExists\",\t\tFront::ScriptScreenElementExists},\r\n\t{\"SetRootScreenElement\",\tFront::ScriptSetRootScreenElement},\r\n\r\n\t// Goal-related stuff\r\n\t{\"GoalManager_AddGoal\",\t\t\t\tGame::ScriptAddGoal},\r\n\t{\"GoalManager_RemoveGoal\",\t\t\tGame::ScriptRemoveGoal},\r\n\t{\"GoalManager_EditGoal\",\t\t\tGame::ScriptEditGoal},\r\n\t{\"GoalManager_ActivateGoal\",\t\tGame::ScriptActivateGoal},\r\n\t{\"GoalManager_DeactivateGoal\",\t\tGame::ScriptDeactivateGoal},\r\n\t{\"GoalManager_ClearLastGoal\",\t\tGame::ScriptClearLastGoal},\r\n\t{\"GoalManager_WinGoal\",\t\t\t\tGame::ScriptWinGoal},\r\n\t{\"GoalManager_LoseGoal\",\t\t\tGame::ScriptLoseGoal},\r\n\t{\"GoalManager_RemoveAllGoals\",\t\tGame::ScriptRemoveAllGoals},\r\n\t{\"GoalManager_DeactivateAllGoals\",\tGame::ScriptDeactivateAllGoals},\r\n\t{\"GoalManager_UninitializeAllGoals\",Game::ScriptUninitializeAllGoals},\r\n\t{\"GoalManager_UninitializeGoal\",\tGame::ScriptUninitializeGoal},\r\n\t{\"GoalManager_InitializeAllGoals\",\tGame::ScriptInitializeAllGoals},\r\n\t{\"GoalManager_InitializeGoal\",\t\tGame::ScriptInitializeGoal},\r\n\t{\"GoalManager_GoalInitialized\",\t\tGame::ScriptGoalInitialized},\r\n\t{\"GoalManager_InitializeAllSelectedGoals\", Game::ScriptInitializeAllSelectedGoals},\r\n\t{\"GoalManager_InitializeAllMinigames\", Game::ScriptInitializeAllMinigames},\r\n\t{\"GoalManager_DeactivateAllMinigames\", Game::ScriptDeactivateAllMinigames},\r\n\t{\"GoalManager_DeactivateCurrentGoal\", Game::ScriptDeactivateCurrentGoal},\r\n\t{\"GoalManager_UpdateAllGoals\",\t\tGame::ScriptUpdateAllGoals},\r\n\t{\"GoalManager_HasActiveGoals\",\t\tGame::ScriptHasActiveGoals},\r\n\t{\"GoalManager_GoalIsActive\",\t\tGame::ScriptGoalIsActive},\r\n\t{\"GoalManager_SetGoalTimer\",\t\tGame::ScriptSetGoalTimer},\r\n\t{\"GoalManager_ZeroGoalTimer\",\t\tGame::ScriptZeroGoalTimer},\r\n\t{\"GoalManager_SetGoalFlag\",\t\t\tGame::ScriptSetGoalFlag},\r\n    {\"GoalManager_HasSeenGoal\",         Game::ScriptHasSeenGoal},\r\n    {\"GoalManager_PauseAllGoals\",       Game::ScriptPauseAllGoals},\r\n    {\"GoalManager_UnPauseAllGoals\",     Game::ScriptUnPauseAllGoals},\r\n    {\"GoalManager_RestartLastGoal\",     Game::ScriptRestartLastGoal},\r\n    // {\"GoalManager_CreateGoalFlag\",      Game::ScriptCreateGoalFlag},\r\n    {\"GoalManager_AllFlagsSet\",         Game::ScriptAllFlagsSet},\r\n\t{\"GoalManager_GoalFlagSet\",\t\t\tGame::ScriptGoalFlagSet},\r\n    {\"GoalManager_CanRetryGoal\",        Game::ScriptCanRetryGoal},      \r\n    {\"GoalManager_GetGoalParams\",       Game::ScriptGetGoalParams},\r\n    {\"GoalManager_CanStartGoal\",        Game::ScriptCanStartGoal},\r\n    {\"GoalManager_NextHorseSpot\",       Game::ScriptNextTourSpot},\r\n\t{\"GoalManager_NextTourSpot\",\t\tGame::ScriptNextTourSpot},\r\n    {\"GoalManager_NextRaceWaypoint\",    Game::ScriptNextRaceWaypoint},\r\n    {\"GoalManager_CreateGoalName\",      Game::ScriptCreateGoalName},\r\n\t{\"GoalManager_GetLevelPrefix\",\t\tGame::ScriptGetLevelPrefix},\r\n    {\"GoalManager_SetGraffitiMode\",     Game::ScriptSetGraffitiMode},\r\n    {\"GoalManager_HasWonGoal\",          Game::ScriptHasWonGoal},\r\n    {\"GoalManager_GotCounterObject\",    Game::ScriptGotCounterObject},\r\n    {\"GoalManager_CounterGoalDone\",     Game::ScriptCounterGoalDone},\r\n\t{\"GoalManager_ClearGoalPoints\",\t\tGame::ScriptClearGoalPoints},\r\n    {\"GoalManager_HasGoalPoints\",       Game::ScriptHasGoalPoints},\r\n    {\"GoalManager_SpendGoalPoints\",     Game::ScriptSpendGoalPoints},\r\n    {\"GoalManager_GetNumberOfGoalPoints\", Game::ScriptGetNumberOfGoalPoints},\r\n    {\"GoalManager_GetCash\",             Game::ScriptGetCash},\r\n    {\"GoalManager_SpendCash\",           Game::ScriptSpendCash},\r\n    {\"GoalManager_AddCash\",             Game::ScriptAddCash},\r\n    {\"GoalManager_HasBeatenGoalWithProset\", Game::ScriptHasBeatenGoalWithProset},\r\n    {\"GoalManager_GetProsetNotPrefix\",  Game::ScriptGetProsetNotPrefix},\r\n    {\"GoalManager_LevelUnload\",         Game::ScriptLevelUnload},\r\n    {\"GoalManager_LevelLoad\",           Game::ScriptLevelLoad},\r\n    {\"GoalManager_NumGoalsBeatenInLevel\",  Game::ScriptNumGoalsBeatenInLevel},\r\n    {\"GoalManager_UnlockGoal\",\t\t\tGame::ScriptUnlockGoal},\r\n\t{\"GoalManager_UnlockAllGoals\",      Game::ScriptUnlockAllGoals},\r\n\t{\"GoalManager_TurnPro\",\t\t\t\tGame::ScriptTurnPro},\r\n\t{\"GoalManager_CheckMinigameRecord\", Game::ScriptCheckMinigameRecord},\r\n\t{\"GoalManager_SetStartTime\",\t\tGame::ScriptSetStartTime},\r\n\t{\"GoalManager_UpdateComboTimer\", \tGame::ScriptUpdateComboTimer},\r\n\t{\"GoalManager_AddMinigameTime\",\t\tGame::ScriptAddMinigameTime},\r\n\t{\"GoalManager_SetStartHeight\", \t\tGame::ScriptSetStartHeight},\r\n\t{\"GoalManager_CheckHeightRecord\", \tGame::ScriptCheckHeightRecord},\r\n\t{\"GoalManager_CheckDistanceRecord\",\tGame::ScriptCheckDistanceRecord},\r\n/*\t\r\n\t{\"GoalManager_ShowGoalPoints\", \t\tGame::ScriptShowGoalPoints},\r\n\t{\"GoalManager_HideGoalPoints\",\t\tGame::ScriptHideGoalPoints},\r\n\t{\"GoalManager_ShowPoints\",\t\t\tGame::ScriptShowPoints},\r\n\t{\"GoalManager_HidePoints\",\t\t\tGame::ScriptHidePoints},\r\n*/\r\n\t{\"GoalManager_AddGoalPoint\",\t\tGame::ScriptAddGoalPoint},\r\n\t{\"GoalManager_PlayGoalStartStream\", Game::ScriptPlayGoalStartStream},\r\n\t{\"GoalManager_PlayGoalWinStream\", \tGame::ScriptPlayGoalWinStream},\r\n\t{\"GoalManager_StopCurrentStream\",\tGame::ScriptStopCurrentStream},\r\n\t{\"GoalManager_PlayGoalWaitStream\",\tGame::ScriptPlayGoalWaitStream},\r\n\t{\"GoalManager_PauseGoal\",\t\t\tGame::ScriptPauseGoal},\r\n\t{\"GoalManager_UnPauseGoal\",\t\t\tGame::ScriptUnPauseGoal},\r\n\t{\"GoalManager_PauseCompetition\",\tGame::ScriptPauseCompetition},\r\n\t{\"GoalManager_UnPauseCompetition\",\tGame::ScriptUnPauseCompetition},\r\n\t{\"GoalManager_UnBeatAllGoals\",\t\tGame::ScriptUnBeatAllGoals},\r\n\t{\"GoalManager_AddViewGoalsList\",\tGame::ScriptAddViewGoalsList},\r\n\t{\"GoalManager_GoalIsLocked\",\t\tGame::ScriptGoalIsLocked},\r\n\t{\"GoalManager_IsInCompetition\",\t\tGame::ScriptIsInCompetition},\r\n\t{\"GoalManager_GetGoalAnimations\",\tGame::ScriptGetGoalAnimations},\r\n\t{\"GoalManager_PlayGoalStream\",\t\tGame::ScriptPlayGoalStream},\r\n\t{\"GoalManager_EndRunCalled\",\t\tGame::ScriptEndRunCalled},\r\n\t{\"GoalManager_ClearEndRun\",\t\t\tGame::ScriptClearEndRun},\r\n\t{\"GoalManager_FinishedEndOfRun\",\tGame::ScriptFinishedEndOfRun},\r\n\t{\"GoalManager_StartedEndOfRun\",\t\tGame::ScriptStartedEndOfRun},\r\n\t{\"GoalManager_SetShouldDeactivateOnExpire\",\tGame::ScriptSetShouldDeactivateOnExpire},\r\n\t{\"GoalManager_EndBetAttempt\",\t\tGame::ScriptEndBetAttempt},\r\n\t{\"GoalManager_StartBetAttempt\",\t\tGame::ScriptStartBetAttempt},\r\n\t{\"GoalManager_WinBet\",\t\t\t\tGame::ScriptWinBet},\r\n\t{\"GoalManager_MoveBettingGuyNow\",\tGame::ScriptMoveBettingGuyNow},\r\n\t{\"GoalManager_BetOffered\",\t\t\tGame::ScriptBetOffered},\r\n\t{\"GoalManager_BetAccepted\",\t\t\tGame::ScriptBetAccepted},\r\n\t{\"GoalManager_BetRefused\",\t\t\tGame::ScriptBetRefused},\r\n\t{\"GoalManager_BetIsActive\",\t\t\tGame::ScriptBetIsActive},\r\n\t{\"GoalManager_AddTempSpecialTrick\",\tGame::ScriptAddTempSpecialTrick},\r\n\t{\"GoalManager_RemoveTempSpecialTrick\", Game::ScriptRemoveTempSpecialTrick},\r\n\t{\"GoalManager_GetTrickFromKeyCombo\", Game::ScriptGetTrickFromKeyCombo},\r\n\t{\"GoalManager_QuickStartGoal\",\t\tGame::ScriptQuickStartGoal},\r\n\t{\"GoalManager_AddGoalChoices\",\t\tGame::ScriptAddGoalChoices},\r\n\t{\"GoalManager_GoalIsSelected\",\t\tGame::ScriptGoalIsSelected},\r\n\t{\"GoalManager_ToggleGoalSelection\",\tGame::ScriptToggleGoalSelection},\r\n\t{\"GoalManager_GoalsAreSelected\",\tGame::ScriptGoalsAreSelected},\r\n\t{\"GoalManager_AddTime\",\t\t\t\tGame::ScriptAddTime},\r\n\t{\"GoalManager_ReplaceTrickText\",\tGame::ScriptReplaceTrickText},\r\n\t// {\"GoalManager_UnlockProSpecificChallenges\",\tGame::ScriptUnlockProSpecificChallenges},\r\n\t// {\"GoalManager_ProSpecificChallengesUnlocked\", Game::ScriptProSpecificChallengesUnlocked},\r\n\t{\"GoalManager_GetNumberCollected\",\tGame::ScriptGetNumberCollected},\r\n\t{\"GoalManager_GetNumberOfFlags\",\tGame::ScriptGetNumberOfFlags},\r\n\t{\"GoalManager_IsPro\",\t\t\t\tGame::ScriptIsPro},\r\n\t{\"GoalManager_ResetGoalFlags\",\t\tGame::ScriptResetGoalFlags},\r\n\t{\"GoalManager_ColorTrickObjects\",\tGame::ScriptColorTrickObjects},\r\n\t{\"GoalManager_GetNumberOfTimesGoalStarted\", Game::ScriptGetNumberOfTimesGoalStarted},\r\n\t{\"GoalManager_GoalExists\",\t\t\tGame::ScriptGoalExists},\r\n\t{\"GoalManager_GetGoalAttemptInfo\",\tGame::ScriptGetGoalAttemptInfo},\r\n\t{\"GoalManager_SetCanStartGoal\",\t\tGame::ScriptSetCanStartGoal},\r\n\t{\"GoalManager_GetLastGoalId\",\t\tGame::ScriptGetLastGoalId},\r\n\t{\"GoalManager_ClearTetrisTricks\",\tGame::ScriptClearTetrisTricks},\r\n\t// {\"GoalManager_MarkProSpecificChallengeBeaten\", Game::ScriptMarkProSpecificChallengeBeaten},\r\n\t// {\"GoalManager_SkaterHasBeatenProSpecificChallenge\", Game::ScriptSkaterHasBeatenProSpecificChallenge},\r\n\t{\"GoalManager_AnnounceGoalStarted\",\tGame::ScriptAnnounceGoalStarted},\r\n\t{\"GoalManager_SetEndRunType\",\t\tGame::ScriptSetEndRunType},\r\n\t{\"GoalManager_GetActiveGoalId\",\t\tGame::ScriptGetActiveGoalId},\r\n\t{\"GoalManager_ResetCareer\",\t\t\tGame::ScriptResetCareer},\r\n\t{\"GoalManager_AwardMinigameCash\",\tGame::ScriptAwardMinigameCash},\r\n\t{\"GoalManager_AwardAllGoalCash\",\tGame::ScriptAwardAllGoalCash},\r\n\t{\"GoalManager_UpdateFamilyTrees\",\tGame::ScriptUpdateFamilyTrees},\r\n\t{\"GoalManager_IsLeafNode\",\t\t\tGame::ScriptIsLeafNode},\r\n\t{\"GoalManager_IsRootNode\",\t\t\tGame::ScriptIsRootNode},\r\n\t{\"GoalManager_SuspendGoalPedLogic\",\tGame::ScriptSuspendGoalPedLogic},\r\n\t{\"GoalManager_RememberLevelStructureName\", Game::ScriptRememberLevelStructureName},\r\n\t{\"GoalManager_SetDifficultyLevel\",\tGame::ScriptSetDifficultyLevel},\r\n\t{\"GoalManager_GetDifficultyLevel\",\tGame::ScriptGetDifficultyLevel},\r\n\t// {\"GoalManager_GetGoalParam\",\t\tGame::ScriptGetGoalParam},\r\n\t{\"GoalManager_RestartStage\",\t\tGame::ScriptRestartStage},\r\n\t{\"GoalManager_CanRestartStage\",\t\tGame::ScriptCanRestartStage},\r\n\t{\"GoalManager_SetGoalChaptersAndStages\", Game::ScriptSetGoalChaptersAndStages},\r\n\t{\"GoalManager_AdvanceStage\", \t\tGame::ScriptAdvanceStage},\r\n\t{\"GoalManager_GetCurrentChapterAndStage\", Game::ScriptGetCurrentChapterAndStage},\r\n\t{\"GoalManager_SetCurrentChapterAndStage\", Game::ScriptSetCurrentChapterAndStage},\r\n\t{\"GoalManager_FilmGoalCheckpoint\",\tGame::ScriptFilmGoalCheckpoint},\r\n\t{\"GoalManager_StartFilming\",\t\tGame::ScriptStartFilming},\r\n\t{\"GoalManager_GoalShouldExpire\",\tGame::ScriptGoalShouldExpire},\r\n\t{\"GoalManager_SetSponsor\",\t\t\tGame::ScriptSetSponsor},\r\n\t{\"GoalManager_GetSponsor\",\t\t\tGame::ScriptGetSponsor},\r\n\t{\"GoalManager_SetTeamMember\",\t\tGame::ScriptSetTeamMember},\r\n\t{\"GoalManager_KillTeamMembers\",\t\tGame::ScriptKillTeamMembers},\r\n    {\"GoalManager_SetTeamName\", \t\tGame::ScriptSetTeamName},\r\n\t{\"GoalManager_GetTeam\",\t\t\t\tGame::ScriptGetTeam},\r\n\t{\"GoalManager_RunLastStageScript\",\tGame::ScriptRunLastStageScript},\r\n\t{\"GoalManager_UnloadLastFam\",\t\tGame::ScriptUnloadLastFam},\r\n\t{\"GoalManager_StopLastStream\",\t\tGame::ScriptStopLastSream},\r\n\t{\"GoalManager_HideAllGoalPeds\",\t\tGame::ScriptHideAllGoalPeds},\r\n\r\n    {\"GetCreateATrickParams\",\t        Game::ScriptGetCreateATrickParams},\r\n    {\"GetCreateATrickOtherParams\",      Game::ScriptGetCreateATrickOtherParams},\r\n    {\"SetCreateATrickParams\",\t        Game::ScriptSetCreateATrickParams},\r\n    {\"SetCreateATrickOtherParams\",      Game::ScriptSetCreateATrickOtherParams},\r\n    {\"SetCreateATrickRotations\",        Game::ScriptSetCreateATrickRotations},\r\n    {\"SetCreateATrickAnimations\",       Game::ScriptSetCreateATrickAnimations},\r\n    {\"GetCreateATrickRotations\",        Game::ScriptGetCreateATrickRotations},\r\n    {\"GetCreateATrickAnimations\",       Game::ScriptGetCreateATrickAnimations},\r\n\r\n    {\"CAT_SetNumAnims\",                 Game::ScriptCAT_SetNumAnims},\r\n    {\"CAT_GetNumAnims\",                 Game::ScriptCAT_GetNumAnims},\r\n    {\"CAT_SetAnimsDone\",                Game::ScriptCAT_SetAnimsDone},\r\n    {\"CAT_GetAnimsDone\",                Game::ScriptCAT_GetAnimsDone},\r\n    {\"CAT_SetRotsDone\",                 Game::ScriptCAT_SetRotsDone},\r\n    {\"CAT_GetRotsDone\",                 Game::ScriptCAT_GetRotsDone},\r\n    {\"CAT_SetBailDone\",                 Game::ScriptCAT_SetBailDone},\r\n    {\"CAT_GetBailDone\",                 Game::ScriptCAT_GetBailDone},\r\n    {\"CAT_SetFlipSkater\",               Game::ScriptCAT_SetFlipSkater},\r\n    {\"CAT_GetFlipSkater\",               Game::ScriptCAT_GetFlipSkater},\r\n    {\"CAT_SetHoldTime\",                 Game::ScriptCAT_SetHoldTime},\r\n    {\"CAT_GetHoldTime\",                 Game::ScriptCAT_GetHoldTime},\r\n    {\"CAT_SetTotalX\",                   Game::ScriptCAT_SetTotalX},\r\n    {\"CAT_GetTotalX\",                   Game::ScriptCAT_GetTotalX},\r\n    {\"CAT_SetTotalY\",                   Game::ScriptCAT_SetTotalY},\r\n    {\"CAT_GetTotalY\",                   Game::ScriptCAT_GetTotalY},\r\n    {\"CAT_SetTotalZ\",                   Game::ScriptCAT_SetTotalZ},\r\n    {\"CAT_GetTotalZ\",                   Game::ScriptCAT_GetTotalZ},\r\n    \r\n    {\"AddWarpPointsToMenu\",             CFuncs::ScriptAddWarpPointsToMenu},\r\n\t{\"RunScriptOnObject\",   \t\t\tCFuncs::ScriptRunScriptOnObject},\r\n\t{\"RunScriptOnComponentType\",\t\tCFuncs::ScriptRunScriptOnComponentType},\r\n\r\n\t// some asset manager functions\r\n\t{\"LoadAsset\",\t\t\t\t\t\tCFuncs::ScriptLoadAsset},\r\n    {\"LoadAnim\",\t\t\t\t\t\tCFuncs::ScriptLoadAnim},\r\n    {\"LoadSkeleton\",\t\t\t\t\tCFuncs::ScriptLoadSkeleton},\r\n    {\"UnloadAnim\",\t\t\t\t\t\tCFuncs::ScriptUnloadAnim},\r\n\t{\"SetDefaultPermanent\",\t\t\t\tCFuncs::ScriptAssManSetDefaultPermanent},\r\n\t{\"SetReferenceChecksum\",\t\t\tCFuncs::ScriptAssManSetReferenceChecksum},\r\n    \r\n    {\"SkaterIsBraking\",                 CFuncs::ScriptSkaterIsBraking},\r\n\t{\"LocalSkaterExists\",\t\t\t\tCFuncs::ScriptLocalSkaterExists},\r\n\t{\"DownloadMotd\",\t\t\t\t\tGameNet::Manager::ScriptDownloadMotd},\r\n\t{\"AlreadyGotMotd\",\t\t\t\t\tGameNet::Manager::ScriptAlreadyGotMotd},\r\n\t{\"AlreadySignedIn\",\t\t\t\t\tGameNet::Manager::ScriptAlreadySignedIn},\r\n\t\r\n\t{\"SignOut\",\t\t\t\t\t\t\tGameNet::Manager::ScriptSignOut},\r\n\t{\"JoinServerComplete\",\t\t\t\tGameNet::Manager::ScriptJoinServerComplete},\r\n\t{\"OnXbox\",\t\t\t\t\t\t\tCFuncs::ScriptOnXbox },\r\n\t{\"SystemLinkEnabled\",\t\t\t\tCFuncs::ScriptSystemLinkEnabled },\r\n\t{\"GotoXboxDashboard\",\t\t\t\tCFuncs::ScriptGotoXboxDashboard },\r\n\r\n\t{\"CreateParticleSystem\",\t\t\tCFuncs::ScriptCreateParticleSystem },\r\n\t{\"SetScript\",\t\t\t\t\t\tCFuncs::ScriptSetScript },\r\n\t{\"DestroyParticleSystem\",\t\t\tCFuncs::ScriptDestroyParticleSystem },\r\n\t{\"EmptyParticleSystem\",\t\t\t\tCFuncs::ScriptEmptyParticleSystem },\r\n\t{\"ParticleExists\",\t\t\t\t\tCFuncs::ScriptParticleExists },\r\n\r\n\t{\"WeatherUpdateGrid\",\t\t\t\tNx::CEngine::ScriptWeatherUpdateGrid },\r\n\t{\"WeatherSetRainHeight\",\t\t\tNx::CEngine::ScriptWeatherSetRainHeight },\r\n\t{\"WeatherSetRainFrames\",\t\t\tNx::CEngine::ScriptWeatherSetRainFrames },\r\n\t{\"WeatherSetRainLength\",\t\t\tNx::CEngine::ScriptWeatherSetRainLength },\r\n\t{\"WeatherSetRainBlendMode\",\t\t\tNx::CEngine::ScriptWeatherSetRainBlendMode },\r\n\t{\"WeatherSetRainRate\",\t\t\t\tNx::CEngine::ScriptWeatherSetRainRate },\r\n    {\"WeatherSetRainColor\",\t\t\t\tNx::CEngine::ScriptWeatherSetRainColor},\r\n\r\n\t{\"WeatherSetSplashRate\",\t\t\tNx::CEngine::ScriptWeatherSetSplashRate },\r\n\t{\"WeatherSetSplashLife\",\t\t\tNx::CEngine::ScriptWeatherSetSplashLife },\r\n\t{\"WeatherSetSplashSize\",\t\t\tNx::CEngine::ScriptWeatherSetSplashSize },\r\n\t{\"WeatherSetSplashColor\",\t\t\tNx::CEngine::ScriptWeatherSetSplashColor },\r\n\t{\"WeatherSetSplashBlendMode\",\t\tNx::CEngine::ScriptWeatherSetSplashBlendMode },\r\n\r\n\t{\"WeatherSetSnowHeight\",\t\t\tNx::CEngine::ScriptWeatherSetSnowHeight },\r\n\t{\"WeatherSetSnowFrames\",\t\t\tNx::CEngine::ScriptWeatherSetSnowFrames },\r\n\t{\"WeatherSetSnowSize\",\t\t\t\tNx::CEngine::ScriptWeatherSetSnowSize },\r\n\t{\"WeatherSetSnowBlendMode\",\t\t\tNx::CEngine::ScriptWeatherSetSnowBlendMode },\r\n\t{\"WeatherSetSnowRate\",\t\t\t\tNx::CEngine::ScriptWeatherSetSnowRate },\r\n    {\"WeatherSetSnowColor\",\t\t\t\tNx::CEngine::ScriptWeatherSetSnowColor},\r\n\r\n    {\"WeatherSetSnowActive\",\t\t\tNx::CEngine::ScriptWeatherSetSnowActive},\r\n    {\"WeatherSetRainActive\",\t\t\tNx::CEngine::ScriptWeatherSetRainActive},\r\n\r\n\t{\"StructureContains\",\t\t\t\tCFuncs::ScriptStructureContains},\r\n\t{\"GetBonePosition\",\t\t\t\t\tCFuncs::ScriptGetBonePosition},\r\n\t{\"ShouldEmitParticles\",\t\t\t\tCFuncs::ScriptShouldEmitParticles},\r\n\t{\"ParticlesOn\",\t\t\t\t\t\tCFuncs::ScriptParticlesOn},\r\n\t{\"ParticlesOff\",\t\t\t\t\tCFuncs::ScriptParticlesOff},\r\n\t{\"MangleChecksums\",\t\t\t\t\tCFuncs::ScriptMangleChecksums},\r\n\t{\"AppendSuffixToChecksum\",\t\t\tCFuncs::ScriptAppendSuffixToChecksum},\r\n\t\r\n\t{\"RotateVector\",\t\t\t\t\tCFuncs::ScriptRotateVector},\r\n\r\n\t{\"IsPS2\",\t\t\t\t\t\t\tCFuncs::ScriptIsPS2},\r\n\t{\"IsNGC\",\t\t\t\t\t\t\tCFuncs::ScriptIsNGC},\r\n\t{\"IsXBOX\",\t\t\t\t\t\t\tCFuncs::ScriptIsXBOX},\r\n\t{\"IsWIN32\",\t\t\t\t\t\t\tCFuncs::ScriptIsWIN32},\r\n\t{\"GetPlatform\",\t\t\t\t\t\tCFuncs::ScriptGetPlatform},\r\n\t{\"IsPal\",\t\t\t\t\t\t\tCFuncs::ScriptIsPal},\r\n\r\n\t{\"PrintSkaterStats\",\t\t\t\tCFuncs::ScriptPrintSkaterStats},\r\n    {\"PrintSkaterStats2\",\t\t\t\tCFuncs::ScriptPrintSkaterStats2},\r\n\t{\"PrintSkaterPosition\",\t\t\t\tCFuncs::ScriptPrintSkaterPosition},\r\n\t{\"GetSkaterID\",\t\t\t\t\t\tCFuncs::ScriptGetSkaterID},\r\n\t{\"GetCurrentSkaterID\",\t\t\t\tCFuncs::ScriptGetCurrentSkaterID},\r\n\t{\"GetViewerObjectID\",\t\t\t\tCFuncs::ScriptGetViewerObjectID},\r\n\t\r\n\t{\"PushMemProfile\",\t\t\t\t\tCFuncs::ScriptPushMemProfile},\r\n\t{\"PopMemProfile\",\t\t\t\t\tCFuncs::ScriptPopMemProfile},\r\n\t{\"TogglePass\",\t\t\t\t\t\tCFuncs::ScriptTogglePass},\r\n\t\r\n\t{\"GetStatValue\",\t\t\t\t\tCFuncs::ScriptGetStatValue},\r\n\t{\"GetNumStatPointsAvailable\",\t\tCFuncs::ScriptGetNumStatPointsAvailable},\r\n\t{\"UnlockSkater\",\t\t\t\t\tCFuncs::ScriptUnlockSkater},\r\n\t{\"SetSkaterProfileInfo\",\t\t\tCFuncs::ScriptSetSkaterProfileInfo},\r\n\t{\"GetSkaterProfileInfo\",\t\t\tCFuncs::ScriptGetSkaterProfileInfo},\r\n\t{\"GetSkaterProfileInfoByName\",\t\tCFuncs::ScriptGetSkaterProfileInfoByName},\r\n\t{\"SetSkaterProfileProperty\",\t\tCFuncs::ScriptSetSkaterProfileProperty},\r\n\t{\"SetSkaterProfileInfoByName\",\t\tCFuncs::ScriptSetSkaterProfileInfoByName},\r\n\t{\"SetScreen\",\t\t\t\t\t\tCFuncs::ScriptSetScreen},\r\n\r\n\t{\"GetUpperCaseString\",\t\t\t\tCFuncs::ScriptGetUpperCaseString},\r\n\r\n\t{\"GetGameMode\",\t\t\t\t\t\tCFuncs::ScriptGetGameMode},\r\n\t{\"StartKeyboardHandler\",\t\t\tCFuncs::ScriptStartKeyboardHandler},\r\n\t{\"StopKeyboardHandler\",\t\t\t\tCFuncs::ScriptStopKeyboardHandler},\r\n\t{\"EnableKeyboard\",\t\t\t\t\tCFuncs::ScriptEnableKeyboard},\r\n\t{\"DisableKeyboard\",\t\t\t\t\tCFuncs::ScriptDisableKeyboard},\r\n\t\r\n\t{\"GetRescaledTargetValue\",\t\t\tCFuncs::ScriptGetRescaledTargetValue},\r\n\t{\"MemInitHeap\",\t\t\t\t\t\tCFuncs::ScriptMemInitHeap},\r\n\t{\"MemDeleteHeap\",\t\t\t\t\tCFuncs::ScriptMemDeleteHeap},\r\n\t{\"ClearStruct\",\t\t\t\t\t\tCFuncs::ScriptClearStruct},\r\n\t{\"AppendStruct\",\t\t\t\t\tCFuncs::ScriptAppendStruct},\r\n\t{\"ScriptExists\",\t\t\t\t\tCFuncs::ScriptScriptExists},\r\n\t{\"GetPlayerAppearancePart\",\t\t\tCFuncs::ScriptGetPlayerAppearancePart},\r\n\t{\"GetActualCASOptionStruct\",\t\tCFuncs::ScriptGetActualCASOptionStruct},\r\n\t{\"GetActualPlayerAppearancePart\",\tCFuncs::ScriptGetActualPlayerAppearancePart},\r\n\t{\"SetPlayerAppearanceColor\",\t\tCFuncs::ScriptSetPlayerAppearanceColor},\r\n\t{\"SetPlayerAppearanceScale\",\t\tCFuncs::ScriptSetPlayerAppearanceScale},\r\n\t{\"SetPlayerAppearanceUV\",\t\t\tCFuncs::ScriptSetPlayerAppearanceUV},\r\n\t{\"FlushDeadObjects\",\t\t\t\tCFuncs::ScriptFlushDeadObjects},\r\n\r\n\t{\"BindTrickToKeyCombo\",\t\t\t\tCFuncs::ScriptBindTrickToKeyCombo},\r\n\t{\"GetKeyComboBoundToTrick\",\t\t\tCFuncs::ScriptGetKeyComboBoundToTrick},\r\n\t{\"UpdateTrickMappings\",\t\t\t\tCFuncs::ScriptUpdateTrickMappings},\r\n\t{\"GetConfigurableTricksFromType\",\tCFuncs::ScriptGetConfigurableTricksFromType},\r\n\t{\"GetTrickDisplayText\",\t\t\t\tCFuncs::ScriptGetTrickDisplayText},\r\n\t{\"GetSpecialTrickInfo\",\t\t\t\tCFuncs::ScriptGetSpecialTrickInfo},\r\n\t{\"GetTrickType\",\t\t\t\t\tCFuncs::ScriptGetTrickType},\r\n\t{\"TrickIsLocked\",\t\t\t\t\tCFuncs::ScriptTrickIsLocked},\r\n\r\n\t{\"SpawnSecondControllerCheck\",\t\tCFuncs::ScriptSpawnSecondControllerCheck},\r\n\t{\"StopSecondControllerCheck\",\t\tCFuncs::ScriptStopSecondControllerCheck},\r\n\r\n\t{\"GetIndexOfItemContaining\",\t\tCFuncs::ScriptGetIndexOfItemContaining},\r\n\t{\"ForEachSkaterName\",\t\t\t\tCFuncs::ScriptForEachSkaterName},\r\n\t{\"ForEachSkaterProfile\",\t\t\tCFuncs::ScriptForEachSkaterProfile},\r\n\t{\"ResetAllToDefaultStats\",\t\t\tCFuncs::ScriptResetAllToDefaultStats},\r\n\t{\"ResetAllToDefaultProfile\",\t\tCFuncs::ScriptResetAllToDefaultProfile},\r\n\t{\"ResetToDefaultProfile\",\t\t\tCFuncs::ScriptResetToDefaultProfile},\r\n\t{\"GetLevelRecords\",\t\t\t\t\tCFuncs::ScriptGetLevelRecords},\r\n\r\n\t{\"ResetComboRecords\",\t\t\t\tCFuncs::ScriptResetComboRecords},\r\n\r\n\t{\"IsArray\",\t\t\t\t\t\t\tCFuncs::ScriptIsArray},\r\n\r\n\t{\"GetNumberOfTrickOccurrences\",\t\tCFuncs::ScriptGetNumberOfTrickOccurrences},\r\n\r\n\t{\"GetNumSoundtracks\",\t\t\t\tCFuncs::ScriptGetNumSoundtracks},\r\n\t{\"GetSoundtrackName\",\t\t\t\tCFuncs::ScriptGetSoundtrackName},\r\n\t{\"UseUserSoundtrack\",\t\t\t\tCFuncs::ScriptUseUserSoundtrack},\r\n\t{\"UseStandardSoundtrack\",\t\t\tCFuncs::ScriptUseStandardSoundtrack},\r\n\t\r\n\t{\"DisableReset\",\t\t\t\t\tCFuncs::ScriptDisableReset},\r\n\t{\"EnableReset\",\t\t\t\t\t\tCFuncs::ScriptEnableReset},\r\n\t{\"ResetToIPL\",\t\t\t\t\t\tCFuncs::ScriptResetToIPL},\r\n\r\n\t{\"BindControllerToSkater\",\t\t\tCFuncs::ScriptBindControllerToSkater},\r\n\t{\"BindFrontEndToController\",\t\tCFuncs::ScriptBindFrontEndToController},\r\n\t{\"ControllerBoundToDifferentSkater\",CFuncs::ScriptControllerBoundToDifferentSkater},\r\n\t{\"ControllerBoundToSkater\",\t\t\tCFuncs::ScriptControllerBoundToSkater},\r\n\r\n\t{\"GetKeyComboArrayFromTrickArray\",\tCFuncs::ScriptGetKeyComboArrayFromTrickArray},\r\n\t{\"InitAnimCompressTable\",\t\t\tCFuncs::ScriptInitAnimCompressTable},\r\n\r\n\t{\"FirstInputReceived\",\t\t\t\tCFuncs::ScriptFirstInputReceived},\r\n\t{\"LockCurrentSkaterProfileIndex\",\tCFuncs::ScriptLockCurrentSkaterProfileIndex},\r\n\r\n\t{\"SetSpecialTrickInfo\",\t\t\t\tCFuncs::ScriptSetSpecialTrickInfo},\r\n    {\"GetSkaterPosition\",\t\t\t\tCFuncs::ScriptGetSkaterPosition},\r\n\t{\"GetSkaterVelocity\",\t\t\t\tCFuncs::ScriptGetSkaterVelocity},\r\n\t{\"InterpolateParameters\",\t\t\tCFuncs::ScriptInterpolateParameters},\r\n\t{\"GetLightCurrentColor\",\t\t\tNx::ScriptGetLightCurrentColor},\r\n    {\"DrawDirectionalLightLines\",\t\tNx::ScriptDrawDirectionalLightLines},\r\n\r\n    {\"CreateCompositeObject\",\t\t\tCFuncs::ScriptCreateCompositeObject},\r\n\t\r\n\t{\"AutoRail\",\t\t\t\t\t\tCFuncs::ScriptAutoRail},\r\n\t\r\n    {\"Inside\",           \t\t\t\tCFuncs::ScriptInside},\r\n\r\n    {\"SetSpecialBarColors\",           \tCFuncs::ScriptSetSpecialBarColors},\r\n\t{\"GetMetrics\",\t\t\t\t\t\tCFuncs::ScriptGetMetrics},\r\n\t{\"MoveNode\",\t\t\t\t\t\tCFuncs::ScriptMoveNode},\r\n\t{\"SetActiveCamera\",\t\t\t\t\tCFuncs::ScriptSetActiveCamera},\r\n\r\n    {\"Sin\",                           \tCFuncs::ScriptSin},\r\n    {\"Cos\",                           \tCFuncs::ScriptCos},\r\n    {\"Tan\",                           \tCFuncs::ScriptTan},\r\n    {\"ASin\",                           \tCFuncs::ScriptASin},\r\n    {\"ACos\",                           \tCFuncs::ScriptACos},\r\n    {\"ATan\",                           \tCFuncs::ScriptATan},\r\n\t\r\n\t{\"ShowTracking\",\t\t\t\t\tCFuncs::ScriptShowTracking},\r\n\t\r\n\t{\"IsGrind\",\t\t\t\t\t\t\tCFuncs::ScriptIsGrind},\r\n\t{\"ShowCamOffset\",\t\t\t\t\tCFuncs::ScriptShowCamOffset},\r\n\t\r\n\t{\"PlaySkaterStream\",\t\t\t\tCFuncs::ScriptPlaySkaterStream},\r\n\r\n    {\"GetTextureFromPath\",              CFuncs::ScriptGetTextureFromPath},\r\n    {\"GetVramUsage\",              CFuncs::ScriptGetVramUsage},\r\n\t{\"CompositeObjectExists\",\t\t\tCFuncs::ScriptCompositeObjectExists},\t\r\n\t\r\n\t{\"DoNextTrick\",\t\t\t\t\tObj::ScriptDoNextTrick},\r\n\r\n\t{\"AllocatePathManMemory\",\t\tObj::ScriptAllocatePathManMemory},\r\n\r\n\r\n\t{\"AddSkaterEarly\",\t\t\t\t\tCFuncs::ScriptAddSkaterEarly},\r\n\r\n\t{\"PreLoadStreamDone\",\t\t\t\tCFuncs::ScriptPreLoadStreamDone},\r\n\t{\"StartPreLoadedStream\",\t\t\tCFuncs::ScriptStartPreLoadedStream},\r\n\t{\"FinishRendering\",\t\t\t\t\tCFuncs::ScriptFinishRendering},\r\n\r\n// Gamecube-specific message functions.\r\n#ifdef __PLAT_NGC__\r\n\t{\"Ngc_BGColor\", \t\t\t\t\tNx::ScriptNgc_BGColor},\r\n\t{\"Ngc_Message\", \t\t\t\t\tNx::ScriptNgc_Message},\r\n\t{\"Ngc_Menu\", \t\t\t\t\t\tNx::ScriptNgc_Menu},\r\n\t{\"Ngc_Set480P\",\t\t\t\t\t\tNx::ScriptNgc_Set480P},\r\n\t{\"Ngc_Set480I\",\t\t\t\t\t\tNx::ScriptNgc_Set480I},\r\n\t{\"Ngc_SetWide\",\t\t\t\t\t\tNx::ScriptNgc_SetWide},\r\n\t{\"Ngc_SetStandard\",\t\t\t\t\tNx::ScriptNgc_SetStandard},\r\n\t{\"Ngc_ReduceColors\",\t\t\t\tNx::ScriptNgc_ReduceColors},\r\n\t{\"Ngc_Set60hz\",\t\t\t\t\t\tNx::ScriptNgc_Set60Hz},\r\n\t{\"Ngc_Set50hz\",\t\t\t\t\t\tNx::ScriptNgc_Set50Hz},\r\n#endif\t\t// __PLAT_NGC__\r\n};\r\n\r\n// A list of all the member function names accessible from scripts.\r\n// The name in quotes must be the same as the way it appears in q scripts. (case insensitive)\r\nconst char *ppMemberFunctionNames[]=\r\n{\r\n\t// used by the asset manager (AssMan)\t\r\n    \"AnimLoaded\",\r\n    \"AssetLoaded\",\r\n\r\n\t// used by Gfx::Camera\r\n\t\"ChangeCameraFOV\",\r\n\r\n\t// used by Obj::CMovieCamera\r\n\t\"SetTargetObject\",\r\n\t\"ClearTargetObject\",\r\n\t \r\n\t// used by Gfx::CModelAppearance\r\n\t\"SetPart\",\r\n\t\"GetPart\",\r\n\t\"ClearPart\",\r\n\t\"SetChecksum\",\r\n\t\"PartGotFlag\",\r\n\t\"GotPart\",\r\n\t\r\n\t// used by Gfx::CModelBuilder\r\n\t\"GeomModulateColor\",\r\n\t\"GeomSetUVOffset\",\r\n\t\"GeomAllocateUVMatrixParams\",\r\n\t\"GeomReplaceTexture\",\r\n\t\"ModelAddGeom\",\r\n\t\"ModelHideGeom\",\r\n\t\"ModelRemovePolys\",\r\n\t\"ModelFinalize\",\r\n    \"ModelResetScale\",\r\n    \"ModelApplyBoneScale\",\r\n    \"ModelApplyBodyShape\",\r\n    \"ModelApplyObjectScale\",\r\n\t\"ModelApplyFaceTexture\",\r\n\t\"ModelRunScript\",\r\n\t\"ModelClearGeom\",\r\n\t\"ModelClearAllGeoms\",\r\n\t\"DebugPrintAppearance\",\r\n\t\"AppearanceAllowScalingCheat\",\r\n\r\n\t// used by Obj::CSkater\r\n\t\"GetStat\",\r\n\t\"GetScriptedStat\",\r\n\t\"SetCustomRestart\",\r\n\t\"SkipToCustomRestart\",\r\n\t\"PausePhysics\",\r\n\t\"UnPausePhysics\",\r\n\t\"SetDriving\",\r\n\t\"UnsetDriving\",\r\n\t\"GetTimeSincePhysicsSwitch\",\r\n\t\"GetPreviousPhysicsStateDuration\",\r\n\t\"DumpEventBuffer\",\r\n\t\"AnimEquals\",\r\n\t\"PlayAnim\",\r\n\t\"BlendPeriodOut\",\r\n\t\"LoopingAnim\",\r\n\t\"AnimFinished\",\r\n\t\"LeftPressed\",\r\n\t\"RightPressed\",\r\n\t\"UpPressed\",\r\n\t\"DownPressed\",\r\n\t\"Jump\",\r\n\t\"Flipped\",\r\n\t\"Switched\",\r\n\t\"Crouched\",\r\n\t\"OnGround\",\r\n\t\"InAir\",\r\n\t\"OnWall\",\r\n\t\"OnLip\",\r\n\t\"OnRail\",\r\n\t\"InWallplant\",\r\n\t\"FirstTimeOnThisRail\",\r\n\t\"InBail\",\r\n\t\"NotInBail\",\r\n\t\"IsInBail\",\r\n\t\"PlayBonkSound\",\r\n\t\"PlayCessSound\",\r\n\t\"PlayLandSound\",\r\n\t\"PlayJumpSound\",\r\n\t\"SpeedLessThan\",\r\n\t\"SpeedGreaterThan\",\r\n\t\"SpeedEquals\",\r\n\t\"Braking\",\r\n\t\"CanBrakeOff\",\r\n\t\"CanBrakeOn\",\r\n\t\"CanKick\",\r\n\t\"CanKickOn\",\r\n\t\"CanKickOff\",\r\n\t\"ForceAutokickOn\",\r\n\t\"ForceAutokickOff\",\r\n\t\"RestoreAutokick\",\r\n\t\"AutoKickIsOff\",\r\n\t\"DoCarPlantBoost\",\r\n\t\"GetAnimLength\",\r\n    \"Obj_GetAnimSpeed\",\r\n\t\"WaitAnim\",\r\n\t\"FrameIs\",\r\n\t\"BashOn\",\r\n\t\"BashOff\",\r\n\t\"SetTrickName\",\r\n\t\"SetTrickScore\",\r\n\t\"GetSpin\",\r\n\t\"Display\",\r\n\t\"HandleLipOllieDirection\",\r\n\t\"EnableDisplayFlip\",\r\n\t\"DisableDisplayFlip\",\r\n\t\"Flip\",\r\n\t\"ResetSwitched\",\r\n\t\"GetHeading\",\r\n\t\"Rotate\",\r\n\t\"RotateDisplay\",\r\n\t\"CancelRotateDisplay\",\r\n\t\"BoardRotate\",\r\n\t\"NoSpin\",\r\n\t\"CanSpin\",\r\n\t\"Move\",\r\n\t\"Hide\",\r\n\t\"Unhide\",\r\n\t\"IsHidden\",\r\n\t\"Suspend\",\r\n\t\"Unsuspend\",\r\n\t\"Pause\",\r\n\t\"Unpause\",\r\n\t\"SetSpeed\",\r\n\t\"GetSpeed\",\r\n\t\"OrientToNormal\",\r\n\t\"Held\",\r\n\t\"Released\",\r\n\t\"HeldLongerThan\",\r\n\t\"EnableInputEvents\",\r\n\t\"DisableInputEvents\",\r\n\t\"HasPowerup\",\r\n\t\"PickedUpPowerup\",\r\n\t\r\n//\t\"DoNextTrick\",\r\n\t\"ClearTricksFrom\",\r\n\t\"SetQueueTricks\",\r\n\t\"ClearTrickQueue\",\r\n\t\"AddTricksToQueue\",\r\n\t\"UseGrindEvents\",\r\n\t\"DoNextManualTrick\",\r\n\t\"SetManualTricks\",\r\n\t\"ClearManualTrick\",\r\n\t\"SetExtraGrindTricks\",\r\n\t\"ClearExtraGrindTrick\",\r\n\t\"AirTimeLessThan\",\r\n\t\"AirTimeGreaterThan\",\r\n\t\"GetAirTime\",\r\n\t\"GetAirTimeLeft\",\r\n\t\"GetSlope\",\r\n\t\"backwards\",\r\n\t\"ClearPanel_Landed\",\r\n\t\"ClearPanel_Bailed\",\r\n\t\"FlipAfter\",\r\n\t\"RotateAfter\",\r\n\t\"BoardRotateAfter\",\r\n\t\"IsFlipAfterSet\",\r\n\t\"TriggerType\",\r\n\t\"KillSkater\",\r\n\t\"FlipAndRotate\",\r\n\t\"DoBalanceTrick\",\r\n\t\"StopBalanceTrick\",\r\n\t\"SwitchOffBalanceMeter\",\r\n\t\"SwitchOnBalanceMeter\",\r\n\t\"StartBalanceTrick\",\r\n\t\"StartSkitch\",\r\n\t\"StopSkitch\",\r\n\t\"Skitching\",\r\n\t\"SetState\",\r\n\t\"ClearEventBuffer\",\r\n\t\"Input_Debounce\",\r\n\t\"DisablePlayerInput\",\r\n\t\"NetDisablePlayerInput\",\r\n\t\"EnablePlayerInput\",\r\n\t\"NetEnablePlayerInput\",\r\n\t\"PlayerInputIsDisabled\",\r\n\t\"StartGap\",\r\n\t\"EndGap\",\r\n\t\"StartGapTrick\",\r\n\t\"CheckGapTricks\",\r\n\t\"ClearGapTricks\",\r\n\t\"GotSpecial\",\r\n\t\"SetRailSound\",\r\n\t\"LockVelocityDirection\",\r\n\t\"SetRollingFriction\",\r\n\t\"SetSpecialFriction\",\r\n\t\"InNollie\",\r\n\t\"NollieOn\",\r\n\t\"NollieOff\",\r\n\t\"InPressure\",\r\n\t\"PressureOn\",\r\n\t\"PressureOff\",\r\n    \"RunStarted\",\r\n\t\"EndOfRunDone\",\r\n\t\"EndOfRunStarted\",\r\n\t\"Goal_EndOfRunDone\",\r\n\t\"Goal_EndOfRunStarted\",\r\n\t\"IsInEndOfRun\",\r\n\t\"DuplicateTrigger\",\r\n\t\"SparksOn\",\r\n\t\"SparksOff\",\r\n\t\"Vibrate\",\r\n\t\"DoingTrick\",\r\n\t\"GetTerrain\",\r\n\t\"BailOn\",\r\n\t\"BailOff\",\r\n\t\"BailIsOn\",\r\n    \"FrontTruckSparks\",\r\n\t\"SetFrontTruckSparks\",\r\n\t\"SetRearTruckSparks\",\r\n\t\r\n\t\"RemoveXEvents\",\r\n\t\"RestoreEvents\",\r\n\t\"YawBetween\",\r\n\t\"PitchGreaterThan\",\r\n\t\"AbsolutePitchGreaterThan\",\r\n\t\"RollGreaterThan\",\r\n\t\"YawingLeft\",\r\n\t\"YawingRight\",\r\n\t// \"PitchingForward\",\r\n\t// \"PitchingBackward\",\r\n\t// \"RollingLeft\",\r\n\t// \"RollingRight\",\r\n\t\"TextureSplat\",\r\n\t\"Skeleton_SpawnTextureSplat\",\r\n\t\"Skeleton_SpawnCompositeObject\",\r\n\t\"TweakTrick\",\r\n\t\"IsLatestTrick\",\r\n\t\"SetGrindTweak\",\r\n\t\"Ledge\",\r\n\t\"BadLedge\",\r\n\t\"SkateInAble\",\r\n\t\"ResetSpin\",\r\n\t\"LastSpinWas\",\r\n\t\"LandedFromSpine\",\r\n\t\"LandedFromVert\",\r\n\t\"SetLandedFromVert\",\r\n\t\"ResetLandedFromVert\",\r\n\t\"InVertAir\",\r\n\t\"AllowLipNoGrind\",\r\n\t\"ClearAllowLipNoGrind\",\r\n\t\"NoRailTricks\",\r\n\t\"AllowRailTricks\",\r\n\t\"SetExtraTricks\",\r\n\t\"KillExtraTricks\",\r\n\t\"TurnToFaceVelocity\",\r\n\t\"SC_SetSkaterCamOverride\",\r\n\t\"SC_ClearSkaterCamOverride\",\r\n\t\"SC_ShakeCamera\",\r\n\t\"SC_SetMode\",\r\n\t\"SetExtraPush\",\r\n\t\"GetMatrixNormal\",\r\n\t\"GetLastGroundPos\",\r\n\t\"ShouldMongo\",\r\n\t\"SetSlotTrick\",\r\n\t\"ChangeProTricks\",\r\n\t\"TrickOffObject\",\r\n\t\"AdjustBalance\",\r\n\t\"IsLocalSkater\",\r\n\t\"SkaterIsNamed\",\r\n\t\"GetCameraId\",\r\n\t\"AddSkaterToWorld\",\r\n\t\"ResetRigidBodyCollisionRadiusBoost\",\r\n\t\"RemoveSkaterFromWorld\",\r\n\t\"OverrideLimits\",\r\n\t\"CreateSpecialItem\",\r\n\t\"DestroySpecialItem\",\r\n\t\"DestroyAllSpecialItems\",\r\n\t\"SpecialItemExists\",\r\n\t\"OverrideCancelGround\",\r\n\t\"BoardIsRotated\",\r\n\t\"GetSkaterNumber\",\r\n\t\"LastScoreLandedGreaterThan\",\r\n\t\"LastScoreLandedLessThan\",\r\n\t\"TotalScoreGreaterThan\",\r\n\t\"TotalScoreLessThan\",\r\n\t\"GetTotalScore\",\r\n\t\"CurrentScorePotGreaterThan\",\r\n\t\"CurrentScorePotLessThan\",\r\n\t\"GetNumberOfNonGapTricks\",\r\n\t\"PlaceBeforeCamera\",\r\n\t\"CancelWallpush\",\r\n\t\r\n\t// used by Obj::CCompositeObject\r\n\t\"Obj_PrintDetails\",\r\n\t\"CreateComponentFromStructure\",\r\n\r\n\t// used by Obj::CMovingObject\r\n\t\"Obj_PlayStream\",\r\n\t\"Obj_StopStream\",\r\n\t\"FollowWaypointPath\",\r\n\t\"LookAtNode\",\r\n//\t\"Obj_WaitForStreamAvailable\",\r\n//\t\"Obj_WaitForStreamToStart\",\r\n//\t\"Obj_WaitStreamFinished\",\r\n\t\"Obj_ShadowOn\",\r\n\t\"Obj_ShadowOff\",\r\n\t// objects would require an animated model to run these functions:\r\n//\t\"RunAnim\",\r\n//\t\"CycleAnim\",\r\n\t\"Obj_WaitRotate\",\r\n\t\"Obj_WaitAnimFinished\",\r\n\t\"AnimExists\",\r\n\t\"Obj_WaitMove\",\r\n\t\"Obj_WaitStop\",\r\n\t// wait functions:\r\n\t// other functions:\r\n\t\"Obj_StopMoving\",\r\n\t\"Obj_StopRotating\",\r\n\t\"Obj_PlaySound\",\r\n\t\"Obj_AdjustSound\",\r\n\t\"Obj_StopSound\",\r\n\t\"Obj_SetSound\", // tell a car, for example, which sound to use for engine loop.\r\n\t\"Obj_Rotate\",\r\n\t\"Obj_RotX\",\r\n\t\"Obj_RotY\",\r\n\t\"Obj_RotZ\",\r\n\t\"Obj_Hover\",\r\n\t\"Obj_StorePos\",\r\n\t\"Obj_StoreNode\",\r\n\t\"Obj_LookAtNodeStored\",\r\n\t\"Obj_LookAtNodeLinked\",\r\n\t\"Obj_LookAtPosStored\",\r\n//\t\"Obj_MoveToNodeStored\",\r\n\t\"Obj_MoveToPosStored\",\r\n\t\"Obj_RandomPathMode\",\r\n\t\"Obj_FollowPathStored\",\r\n\t\"Obj_LookAtNode\",\r\n\t\"Obj_LookAtPos\",\r\n\t\"Obj_LookAtRelPos\",\r\n\t\"Obj_LookAtObject\",\r\n\t\"Obj_AngleToNearestSkaterGreaterThan\",\r\n\t\"Obj_MoveToLink\",\r\n\t\"Obj_GetRandomLink\",\r\n\t\"Obj_MoveToNode\",\r\n\t\"Obj_MoveToPos\",\r\n\t\"Obj_MoveToRelPos\",\r\n\t\"Obj_MoveForward\",\r\n\t\"Obj_MoveLeft\",\r\n\t\"Obj_IsMoving\",\r\n\t\"Obj_IsRotating\",\r\n\t\"Obj_SetConstantHeight\",\r\n\t\"Obj_FollowPath\",\r\n\t\"Obj_FollowPathLinked\",\r\n\t\"Obj_FollowLeader\",\r\n\t\"Obj_LockToObject\",\r\n\t\"Obj_GetSpeed\",\r\n\t\"Obj_GetNextObjOnPath\",\r\n\t\"Obj_SetPathVelocity\",\r\n\t\"Obj_SetPathAcceleration\",\r\n\t\"Obj_SetPathDeceleration\",\r\n\t\"Obj_SetPathMinStopVel\",\r\n\t\"Obj_StopAlongPath\",\r\n\t\"Obj_StartAlongPath\",\r\n\t\"Obj_SetPathTurnDist\",\r\n\t\"Obj_SetGroundOffset\",\r\n\t\"Obj_PlayAnim\",\r\n\t\"Obj_EnableAnimBlending\",\r\n\t\"Obj_SetAnimCycleMode\",\r\n\t\"Obj_AnimEquals\",\r\n\t\"Obj_StickToGround\",\r\n\t\"Obj_PathHeading\",\r\n\t\"Obj_AnimComplete\",\r\n\t\"Obj_AllowSkitching\",\r\n\t\"Obj_GetOrientation\",\r\n\t\"Obj_ReplaceTexture\",\r\n\t\"Obj_ReplaceSpriteTexture\",\r\n\t\"Obj_SetBodyShape\",\r\n\t\"Obj_SetBoneActive\",\r\n\t\"Obj_GetBonePosition\",\r\n\t\"SwitchOnAtomic\",\r\n\t\"SwitchOffAtomic\",\r\n    \"AtomicIsHidden\",\r\n\t\"Obj_ClearGeoms\",\r\n\t\"Obj_InitModel\",\r\n\t\"Obj_InitModelFromProfile\",\r\n\t\"Obj_HasModelLights\",\r\n\t\"Obj_UpdateBrightness\",\r\n\t\"Obj_EnableAmbientLight\",\r\n\t\"Obj_EnableDiffuseLight\",\r\n\t\"Obj_DisableAmbientLight\",\r\n\t\"Obj_DisableDiffuseLight\",\r\n\t\"Obj_SetLightAmbientColor\",\r\n\t\"Obj_SetLightDirection\",\r\n\t\"Obj_SetLightDiffuseColor\",\r\n\t\"Obj_SetUVOffset\",\r\n\t\"Obj_SetUVParams\",\r\n\t\"Obj_SetBoundingSphere\",\r\n\t\"Obj_RestoreBoundingSphere\",\r\n\t\"Obj_SkipToRestart\",\r\n\r\n\t// procedural bone anim functions\r\n\t\"SetBoneTransActive\",\r\n\t\"SetBoneTransMin\",\r\n\t\"SetBoneTransMax\",\r\n\t\"SetBoneTransSpeed\",\r\n\t\"SetBoneTransCurrent\",\r\n\t\"SetBoneRotActive\",\r\n\t\"SetBoneRotMin\",\r\n\t\"SetBoneRotMax\",\r\n\t\"SetBoneRotSpeed\",\r\n\t\"SetBoneRotCurrent\",\r\n\t\"SetBoneScaleActive\",\r\n\t\"SetBoneScaleMin\",\r\n\t\"SetBoneScaleMax\",\r\n\t\"SetBoneScaleSpeed\",\r\n\t\"SetBoneScaleCurrent\",\r\n\t\"AddAnimController\",\r\n\t\"RemoveAnimController\",\r\n\t\"GetPartialAnimParams\",\r\n\t\"SetPartialAnimSpeed\"\r\n\t\"IncrementPartialAnimTime\",\r\n\t\"ReversePartialAnimDirection\",\r\n\t\"SetWobbleDetails\",\r\n\t\"Obj_Flip\",\r\n\t\"Obj_AnimationFlipped\",\r\n\r\n\t// can be used by any Obj::CMovingObject\r\n\t\"Obj_GetId\",\r\n\t\"Die\",\r\n\t\"DisassociateFromObject\",\r\n\t\"Obj_SetInnerRadius\", // inner radius for player 'collision'\r\n\t\"Obj_SetOuterRadius\", // outer radius for player 'collision'\r\n\t\"Obj_SetInnerAvoidRadius\", // inner radius for player avoidance logic\r\n\t\"Obj_SetOuterAvoidRadius\", // outer radius for player avoidance logic\r\n\t\"Obj_FlagSet\",\r\n\t\"Obj_FlagNotSet\",\r\n\t\"Obj_SetFlag\",\r\n\t\"Obj_ClearFlag\",\r\n\t\"Obj_SpawnScript\",\r\n\t\"Obj_KillSpawnedScript\",\r\n\t\"Obj_SwitchScript\",\r\n\t\"Obj_Visible\",\r\n\t\"Obj_Invisible\",\r\n\t\"Obj_ObjectInRadius\",\r\n\t\"Obj_ObjectInRect\",\r\n\t\"Obj_ObjectNotInRect\",\r\n\t\r\n\t// \"Obj_VarGet\",\r\n\t// \"Obj_VarSet\",\r\n\t// \"Obj_VarPrintf\",\r\n\t// \"Obj_VarPrint\",\r\n\t// \"Obj_VarInc\",\r\n\t// \"Obj_VarDec\",\r\n\t// \"Obj_VarLT\",\r\n\t// \"Obj_VarGT\",\r\n\t// \"Obj_VarEQ\",\r\n\t\r\n\t\"Obj_GetCollision\",\r\n\t\"Obj_GetDistToNode\",\r\n\t\"Obj_ApplyScaling\",\r\n\t\"Obj_EnableScaling\",\r\n\t\"Obj_DisableScaling\",\r\n\t\"Obj_SetColor\",\r\n\t\"Obj_ClearColor\",\r\n\t\"Obj_Jump\",\r\n\t\"Obj_WaitJumpFinished\",\r\n\t\"Obj_GetDistanceToObject\",\r\n\t\"Obj_GetOrientationToObject\",\r\n\t\"Obj_GetPosition\",\r\n\t\"Obj_SetPosition\",\r\n\t\"Obj_SetOrientation\",\r\n\t\"Obj_ForceUpdate\",\r\n\t\"Obj_GetVelocity\",\r\n\t\r\n\t// Car member functions:\r\n\t\"EnableCarShadow\",\r\n\t \r\n\t// Ped member functions:\r\n\t\"Ped_SelectAvoidPoint\",\r\n\t\"Ped_MoveTowardsAvoidPoint\",\r\n\t\"Ped_AvoidPointReached\",\r\n\t\"Ped_RememberNextWaypoint\",\r\n\t\"Ped_RememberCurrentPosition\",\r\n\t\"Ped_RememberStickToGround\",\r\n\t\"Ped_RestoreStickToGround\",\r\n\t\"Ped_BackOnOriginalPath\",\r\n\r\n\t// Bouncy obj member functions:\r\n\t\"BouncyObj_PlayerCollisionOn\",\r\n\t\"BouncyObj_PlayerCollisionOff\",\r\n\t\"BouncyObj_Go\",\r\n\t\"MoveToRandomRestart\",\r\n\r\n\t// CRigidBodyComponent member functions:\r\n\t\"RigidBody_IgnoreSkater\",\r\n\t\"RigidBody_Wake\",\r\n\t\"RigidBody_Sleep\",\r\n\t\"RigidBody_Kick\",\r\n\t\"RigidBody_Reset\",\r\n\t\"RigidBody_DisablePlayerCollision\",\r\n\t\"RigidBody_EnablePlayerCollision\",\r\n\t\"RigidBody_MatchVelocityTo\",\r\n\t\r\n\t// CRibbonComponent member functions:\r\n\t// \"Ribbon_Reset\",\r\n\t\r\n\t// CVehicleComponent member functions:\r\n\t\"Vehicle_Kick\",\r\n\t\"Vehicle_Wake\",\r\n\t\"Vehicle_MoveToRestart\",\r\n\t\"Vehicle_PlaceBeforeCamera\",\r\n\t\"Vehicle_AdjustGravity\",\r\n\t// \"Vehicle_ForceBrake\",\r\n\t\"Vehicle_HandbrakeActive\",\r\n\t\"Vehicle_AllWheelsAreInContact\",\r\n\t\"Vehicle_LostCollision\",\r\n\t\"Vehicle_IsSkaterVisible\",\r\n\t\r\n\t// CVehicleCameraComponent member functions:\r\n\t\"VehicleCamera_Reset\",\r\n\t\r\n\r\n\r\n\r\n\r\n\t// CSkaterPhysicsControlComponent member functions:\r\n\t\"Walking\",\r\n\t\"Skating\",\r\n\t\"Driving\",\r\n\t\"SkaterPhysicsControl_SwitchSkatingToWalking\",\r\n\t\"SkaterPhysicsControl_SwitchWalkingToSkating\",\r\n\t\"SetBoardMissing\",\r\n\t\"UnsetBoardMissing\",\r\n\t\"IsBoardMissing\",\r\n\t\r\n\t\r\n\t// CSkaterLoopingSoundComponent member functions:\r\n\t\"SkaterLoopingSound_TurnOn\",\r\n\t\"SkaterLoopingSound_TurnOff\",\r\n\t\r\n\t// CWalkComponent member functions:\r\n\t\"Walk_Jump\",\r\n\t\"Walk_ScaleAnimSpeed\",\r\n\t\"Walk_Ground\",\r\n\t\"Walk_Air\",\r\n\t\"Walk_Hang\",\r\n\t\"Walk_Ladder\",\r\n\t\"Walk_AnimWait\",\r\n\t\"Walk_GetStateTime\",\r\n\t\"Walk_SetDragFactor\",\r\n\t\"Walk_ResetDragFactor\",\r\n\t\"Walk_AnimWaitComplete\",\r\n\t\"Walk_GetSpeedScale\",\r\n    \"Walk_GetHangInitAnimType\",\r\n\t\"Walk_GetStateDuration\",\r\n\t\"Walk_GetPreviousState\",\r\n\t\"Walk_GetState\",\r\n\t\"Walk_GetHangAngle\",\r\n\t\r\n\t// \"Walk_CancelTransitionalMomentum\",\r\n\t// \"Walk_SuppressInAirControl\",\r\n\t\r\n\t// CWalkCameraComponent member functions:\r\n\t\"WalkCamera_FlushRequest\",\r\n\t\"WalkCamera_Reset\",\r\n\t\r\n\t// CSkaterRunTimerComponent member functions:\r\n\t\"RunTimer_Pause\",\r\n\t\"RunTimer_UnPause\",\r\n\t\"RunTimer_GetFactorComplete\",\r\n\t\"RunTimer_GetRunTimerControllerId\",\r\n\t\"RunTimer_GetRunTimerId\",\r\n\t\r\n#\tifdef TESTING_GUNSLINGER\r\n\t// CHorseComponent member functions:\r\n\t\"Horse_GetSpeedScale\",\r\n\t\"Horse_Jump\",\r\n#\tendif\r\n\r\n\t// CScreenElement functions:\r\n\t\"SetProps\",\r\n\t\"DoMorph\",\r\n\t\"GetProps\",\r\n\t\r\n\t// CObject functions:\r\n//\t\"ClearEventHandler\",\r\n//\t\"ClearEventHandlerGroup\",\r\n\t\"SetTags\",\r\n\t\"GetTags\",\r\n\r\n\t// Particle system functions.\r\n\t\"SetPos\",\r\n\t\"SetSpeedRange\",\r\n\t\"SetEmitRange\",\r\n\t\"SetAngleSpread\",\r\n\t\"SetRandomAngle\",\r\n\t\"SetCircularEmit\",\r\n\t\"SetForce\",\r\n\t\"SetParticleSize\",\r\n\t\"SetLife\",\r\n\t\"SetEmitTarget\",\r\n\t\"SetColor\",\r\n\t\"BuildPath\",\r\n\t\"EmptySystem\",\r\n\t\r\n\t\"Emit\",\r\n\t\"EmitRate\",\r\n\r\n    // StatsManagerComponent fuctions\r\n    \"StatsManager_ActivateGoals\",\r\n    \"StatsManager_DeactivateGoals\",\r\n    \"StatsManager_GetGoalStatus\",\r\n    \"StatsManager_ReInit\",\r\n    \"StatsManager_Reset\",\r\n    \"StatsManager_UnlockAmGoals\",\r\n    \"StatsManager_UnlockProGoals\",\r\n\r\n\t// PedLogicComponent functions\r\n\t\"Ped_InitPath\",\r\n\t\"Ped_SetLogicState\",\r\n\t\"Ped_StartMoving\",\r\n\t\"Ped_StopMoving\",\r\n\t\"Ped_IsMoving\",\r\n\t\"Ped_SetStickToGroundDist\",\r\n\t\"Ped_SetIsGrinding\",\r\n\t\"Ped_Bail\",\r\n\t\"Ped_SetIsBailing\",\r\n\t\"Ped_GetCurrentVelocity\",\r\n\t\"Ped_StoreMaxVelocity\",\r\n\t\"Ped_GetOriginalMaxVelocity\",\r\n\t\"Ped_InitVertTrick\",\r\n\t\"Ped_HitWaypoint\",\r\n\t\"Ped_SetIsSkater\",\r\n\t\"Ped_NearVertNode\",\r\n\t\"Ped_PlayJumpSound\",\r\n\t\"Ped_PlayLandSound\",\r\n\t\"Ped_GetCurrentNodeNames\",\r\n\t\r\n\t\"FlagGoalAsWon\",\r\n\t\"FindUnfinishedGoal\",\r\n\t\"GoalExists\",\r\n\t\"NewEditorGoal\",\r\n\t\"RemovedCreatedGoal\",\r\n\t\"GoalHasAllPositionsSet\",\r\n\t\"SetCurrentEditorGoal\",\r\n\t\"SetEditorGoalType\",\r\n\t\"SetEditorGoalDescription\",\r\n\t\"SetEditorGoalWinMessage\",\r\n\t\"GetEditedGoalsInfo\",\r\n\t\"GetNumEditedGoals\",\r\n\t\"GetCurrentEditedGoalId\",\r\n\t\"WriteEditedGoalNodePositions\",\r\n\t\"AddEditedGoalToGoalManager\",\r\n\t\"GetCurrentEditedGoalInfo\",\r\n\t\"SetEditorGoalName\",\r\n\t\"SetEditorPedName\",\r\n\t\"MaxEditedGoalsReached\",\t\r\n\t\"EditGoal\",\r\n\t\"NukeAllGoals\",\r\n\t\"GetMaxGoalsPerLevel\",\r\n\t\"SetGoalScore\",\r\n\t\"SetGoalTimeLimit\",\r\n\t\"SetGoalControlType\",\r\n\t\"RefreshGoalCursorPosition\",\r\n\t\"SetGoalSpecificParams\",\r\n\t\"RemoveGoalSpecificFlag\",\r\n\t\"AddKeyComboSet\",\r\n\t\"GetKeyComboSet\",\r\n\t\"RemoveKeyComboSet\",\r\n\t\"EditedGoalAddGap\",\r\n\t\"EditedGoalRemoveGap\",\r\n\t\"EditedGoalGotGap\",\r\n\t\"EditorCam_Initialise\",\r\n\t\"EditorCam_SetCursorPos\",\r\n\t\"EditorCam_SetOnlyVerticalCollisionChecks\",\r\n\r\n\t// Rail editor component member functions\r\n\t\"GetCursorPosition\",\r\n\t\"NewRail\",\r\n\t\"MaxRailsReached\",\r\n\t\"AddNewPosition\",\r\n\t\"ClearRailEditor\",\r\n\t\"SetEditingMode\",\r\n\t\"GetEditingMode\",\r\n\t\"DrawDottedLine\",\r\n\t\"DeleteDottedLine\",\r\n\t\"UpdateRailPointPosition\",\r\n\t\"HighlightRailPoint\",\r\n\t\"UnHighlightAllRails\",\r\n\t\"DeleteRailPoint\",\r\n\t\"GetEditedRailInfo\",\r\n\t\"DeleteRail\",\r\n\t\"DestroyEditedRailSectors\",\r\n\t\r\n\t\"SetStartPos\",\r\n\t\"SetMidPos\",\r\n\t\"SetEndPos\",\r\n\t\"SetStartBoxDimensions\",\r\n\t\"SetMidBoxDimensions\",\r\n\t\"SetEndBoxDimensions\",\r\n\t\"SetUpdateScript\",\r\n\t\"SetEmitRate\",\r\n\t\"SetLifetime\",\r\n\t\"SetMidPointPct\",\r\n\t\"SetMidpointColorPct\",\r\n\t\"SetStartRadius\",\r\n\t\"SetMidRadius\",\r\n\t\"SetEndRadius\",\r\n\t\"SetStartColor\",\r\n\t\"SetMidColor\",\r\n\t\"SetEndColor\",\r\n    \r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint GetCFunctionLookupTableSize()\r\n{\r\n    return (sizeof(CFunctionLookupTable)/sizeof(SCFunction));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint GetNumMemberFunctions()\r\n{\r\n    return (sizeof(ppMemberFunctionNames)/sizeof(const char *));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Script\r\n\r\n"
  },
  {
    "path": "Code/Sk/Scripting/ftables.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tScripting\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tftables.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**      Created:                09/15/2000      -        ksh                                                                             **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SCRIPTING_FTABLES_H\r\n#define\t__SCRIPTING_FTABLES_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef\t__SCRIPTING_INIT_H\r\n#include <gel/scripting/init.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\nnamespace Script\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern SCFunction CFunctionLookupTable[];\r\n\r\nextern const char *ppMemberFunctionNames[];\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint GetCFunctionLookupTableSize();\r\nint GetNumMemberFunctions();\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace FTables\r\n\r\n#endif\t// __SCRIPTING_FTABLES_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Scripting/gs_file.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// gs_file.cpp\t\tKSH 7 Nov 2001\r\n//\r\n// Game specific functions for loading and unloading qb files.\r\n// These call the LoadQB and UnloadQB functions in the Skate namespace, but then do\r\n// any additional skate-specific processing required.\r\n// For example, if the newly loaded qb contained a NodeArray, node name prefix info\r\n// needs to be regenerated, etc.\r\n// Also, skater exceptions may need to be reloaded.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <sk/scripting/gs_file.h>\r\n#include <gel/scripting/file.h>\r\n#include <gel/scripting/parse.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/string.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/struct.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <core/crc.h> // For Crc::GenerateCRCFromString\r\n#include <sk/components/goaleditorcomponent.h>\r\n#include <sys/file/pip.h>\r\n#include <sk/objects/pathman.h>\r\n#include <core/math.h>\r\n#ifdef __PLAT_NGC__\r\n#include <sys/config/config.h>\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n#include \"string.h\"\r\n\r\n#ifdef __PLAT_NGC__\r\n#include <dolphin.h>\r\n#include \"sys/ngc/p_display.h\"\r\n#endif\t\t// __PLAT_NGC__\r\n\r\nnamespace SkateScript\r\n{\r\nusing namespace Script;\r\n\r\n// The size of the temporary buffer used when parsing the qdir.txt file. Used in LoadAllStartupQBFiles()\r\n#define MAX_QB_FILENAME_CHARS_WITH_PATH 100\r\n\r\n#define QDIR_FILE \"scripts\\\\qdir.txt\"\r\n#define MAIN_QB_FILEPATH \"scripts\\\\\"\r\n\r\nvoid LoadAllStartupQBFiles()\r\n{\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n#ifdef __PLAT_NGC__\r\n\tswitch ( Config::GetLanguage() )\r\n\t{\r\n\t\tcase Config::LANGUAGE_FRENCH:\r\n\t\t\tPip::LoadPre(\"qb.prf\");\r\n\t\t\tbreak;\r\n\t\tcase Config::LANGUAGE_GERMAN:\r\n\t\t\tPip::LoadPre(\"qb.prd\");\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tPip::LoadPre(\"qb.pre\");\r\n\t\t\tbreak;\r\n\t}\r\n#else\r\n\tPip::LoadPre(\"qb.pre\");\r\n#endif\t\t// __PLAT_NGC__\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Load the qdir.txt file\r\n\tconst char *p_qdir=(const char *)Pip::Load(QDIR_FILE);\r\n\tuint32 file_size=Pip::GetFileSize(QDIR_FILE);\r\n\t\r\n\tUsePermanentStringHeap();\r\n\t\r\n    // Load each of the files listed.\r\n\t#define MAX_FILENAME_CHARS 200\r\n\tchar p_file_name[MAX_FILENAME_CHARS+1];\r\n\t\r\n\tconst char *p_scan=p_qdir;\r\n\twhile (p_scan < p_qdir+file_size)\r\n\t{\r\n\t\tint c=0;\r\n\t\twhile (p_scan < p_qdir+file_size && *p_scan!=0x0d && *p_scan!=0x0a)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(c<MAX_FILENAME_CHARS,(\"File name too long\"));\r\n\t\t\tp_file_name[c++]=*p_scan++;\r\n\t\t}\r\n\t\tp_file_name[c]=0;\r\n\t\t// If the above loop broke out because *p_scan was 0x0d or 0x0a then\r\n\t\t// this will skip over it. If p_scan was >= p_qdir+file_size then it\r\n\t\t// still will be after incrementing p_scan so that's OK too.\r\n\t\t++p_scan;\r\n\t\t\r\n\t\t// Skip any empty strings, which will happen when encountering 0x0d,0x0a pairs.\r\n\t\tif (*p_file_name)\r\n\t\t{\r\n\t\t\t// Note: p_file_name will contain the complete path, eg c:\\skate5\\data\\scripts\\blaa.qb\r\n\r\n\t\t\t// Strip off any preceding data path.\t\t\t\r\n\t\t\tchar *p_data_backslash=strstr(p_file_name,\"data\\\\\");\r\n\t\t\tif (p_data_backslash)\r\n\t\t\t{\r\n\t\t\t\tstrcpy( p_file_name, p_data_backslash+5); // Safe cos it will copy backwards\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\t// Make sure this script isn't already loaded.\r\n\t\t\tSkateScript::UnloadQB( Crc::GenerateCRCFromString(p_file_name) );\r\n\r\n\t\t\tSkateScript::LoadQB(p_file_name,\r\n\t\t\t\t\t\t\t\t// We do want assertions if duplicate symbols when loading all \r\n\t\t\t\t\t\t\t\t// the qb's on startup. (Just not when reloading a qb)\r\n\t\t\t\t\t\t\t\tASSERT_IF_DUPLICATE_SYMBOLS);\r\n\t\t}\t\r\n#ifdef __PLAT_NGC__\r\n\t\tNsDisplay::doReset();\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\t}\t\r\n\r\n\tUseRegularStringHeap();\r\n\t\r\n\tPip::Unload(QDIR_FILE);\r\n#ifdef __PLAT_NGC__\r\n\tswitch ( Config::GetLanguage() )\r\n\t{\r\n\t\tcase Config::LANGUAGE_FRENCH:\r\n\t\t\tPip::UnloadPre(\"qb.prf\");\r\n\t\t\tbreak;\r\n\t\tcase Config::LANGUAGE_GERMAN:\r\n\t\t\tPip::UnloadPre(\"qb.prd\");\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tPip::UnloadPre(\"qb.pre\");\r\n\t\t\tbreak;\r\n\t}\r\n#else\r\n\tPip::UnloadPre(\"qb.pre\");\r\n#endif\t\t// __PLAT_NGC__\r\n\t\r\n\t// A very small memory optimization ...\r\n\t// Remove the debugger_names array since it only exists to get its checksum names registered\r\n\t// for the script debugger. They will have got registered by now, so the array is no longer\r\n\t// needed. Saves about 3K.\r\n\tCSymbolTableEntry *p_debugger_names=LookUpSymbol(CRCD(0xc2f97ba7,\"debugger_names\"));\r\n\tif (p_debugger_names)\r\n\t{\r\n\t\tCleanUpAndRemoveSymbol(p_debugger_names);\r\n\t}\r\n}\r\n\r\n// Calls the Script::LoadQB, and then do any game-specific stuff that needs to be done when a qb is reloaded, such as \r\n// generating the node name hash table & prefix info\r\nvoid LoadQB(const char *p_fileName, EBoolAssertIfDuplicateSymbols assertIfDuplicateSymbols)\r\n{\r\n\tDbg_MsgAssert(p_fileName,(\"NULL p_fileName\"));\r\n\t//if (strcmp(\"..\\\\runnow.qb\",p_fileName) != 0)\r\n\t//{\r\n\t//\tprintf(\"Loading %s\\n\",p_fileName); // REMOVE\r\n\t//}\r\n\t// Call the non-game-specific LoadQB, which open the qb and create all the symbols defined within.\r\n\tScript::LoadQB(p_fileName, assertIfDuplicateSymbols);\r\n\t\r\n\tCSymbolTableEntry *p_sym=GetNextSymbolTableEntry();\r\n\twhile (p_sym)\r\n\t{\r\n\t\tif (p_sym->mGotReloaded && \r\n\t\t\tp_sym->mType==ESYMBOLTYPE_ARRAY &&\r\n\t\t\tp_sym->mNameChecksum==0xc472ecc5/*NodeArray*/)\r\n\t\t{\r\n\t\t\t// This will resize the NodeArray, adding the extra nodes required by the goal editor.\r\n\t\t\t// Note that p_sym->mpArray is still valid after doing this, because the resizing only\r\n\t\t\t// causes a reallocation of a buffer inside the CArray, the CArray itself is not reallocated.\r\n\t\t\tObj::InsertGoalEditorNodes();\r\n\t\t\t\r\n\t\t\tCreateNodeNameHashTable();\r\n\t\t\tGeneratePrefixInfo();\r\n\r\n\t\t\t// Do a bit of node array processing.\r\n\t\t\tint size=p_sym->mpArray->GetSize();\r\n\t\t\tfor (int i=0; i<size; ++i)\r\n\t\t\t{\r\n\t\t\t\tCStruct *p_node=p_sym->mpArray->GetStructure(i);\r\n\t\t\t\t\r\n\t\t\t\t// K: This swapping of Position for Pos used to be at a lower level in parse.cpp,\r\n\t\t\t\t// but that had the problem that it was doing the swap on all structures, including those\r\n\t\t\t\t// passed to commands in scripts. So I moved it here so as to only affect those structures\r\n\t\t\t\t// in the node array.\r\n\t\t\t\tMth::Vector p(0.0f,0.0f,0.0f);\r\n\t\t\t\tif (p_node->GetVector(CRCD(0xb9d31b0a,\"Position\"),&p))\r\n\t\t\t\t{\r\n\t\t\t\t\t// GJ:  The \"position\" currently written out \r\n\t\t\t\t\t// by the exporter has an incorrect Z, and there\r\n\t\t\t\t\t// are a bunch of places in the game code which\r\n\t\t\t\t\t// negate the Z value in order to correct it.\r\n\t\t\t\t\t// We're currently in the process of phasing this\r\n\t\t\t\t\t// \"Position\" out, in favor of the \"Pos\" vector, \r\n\t\t\t\t\t// which will have the correct Z.  For backwards\r\n\t\t\t\t\t// compatibility, the code here removes the old\r\n\t\t\t\t\t// \"Position\" vector if it exists and replaces \r\n\t\t\t\t\t// it with the new \"Pos\" vector.  Eventually, \r\n\t\t\t\t\t// once all the levels have been re-exported, \r\n\t\t\t\t\t// we can remove this kludge.\r\n\t\t\t\t\tp_node->RemoveComponent(CRCD(0xb9d31b0a,\"Position\"));\r\n\t\t\t\t\tp_node->AddVector(CRCD(0x7f261953,\"Pos\"),p[X],p[Y],-p[Z]);\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Do some path preprocessing. This adds PathNum parameters to all nodes that\r\n\t\t\t// are on a path so that one can quickly find out what path a particular car is\r\n\t\t\t// on without having to scan through a bunch of nodes.\r\n\t\t\tObj::CPathMan::Instance()->AddPathInfoToNodeArray();\r\n\t\t\t\r\n\t\t\t// Reset the reloaded flag, otherwise it will stick on forever.\r\n\t\t\tp_sym->mGotReloaded=false;\r\n\t\t\t\r\n\t\t\t// No need to keep checking for more NodeArray's, there can be only one.\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tp_sym=GetNextSymbolTableEntry(p_sym);\r\n\t}\t\t\r\n\t\r\n\t// Make sure checksum name lookup table is removed since it is only needed for the node array.\r\n\tRemoveChecksumNameLookupHashTable();\r\n}\r\n\r\n// Calls the Script::UnloadQB and then does any game-specific stuff that needs to be done \r\n// when a qb is unloaded, such as resetting the node name hash table & prefix info.\r\nvoid UnloadQB(uint32 fileNameChecksum)\r\n{\r\n\t// Call the non-game-specific UnloadQB, which will delete all the symbols that came from this qb.\r\n\tScript::UnloadQB(fileNameChecksum);\r\n\t\r\n\tif (!GetArray(0xc472ecc5/*NodeArray*/))\r\n\t{\r\n\t\t// If there is no node array any more then make sure the prefix info and node name lookup\r\n\t\t// info is cleaned up.\r\n\t\tDeletePrefixInfo();\r\n\t\tClearNodeNameHashTable();\r\n\t}\t\r\n}\r\n\r\nuint32 GenerateFileNameChecksum(const char *p_fileName)\r\n{\r\n\tDbg_MsgAssert(p_fileName,(\"NULL p_fileName\"));\r\n\t\r\n\t// TODO May need to process the file name a bit first, eg prefix it with the\r\n\t// full path if it is not there already, before calculating its checksum, in order to ensure a match.\r\n\t// We may want UnloadQB to be able to be passed a filename without the full path.\r\n\t\r\n\t// For the moment though, just calculate the checksum for the string as it is.\r\n\treturn Crc::GenerateCRCFromString(p_fileName);\r\n}\r\n\r\nvoid UnloadQB(const char *p_fileName)\r\n{\r\n\tSkateScript::UnloadQB(GenerateFileNameChecksum(p_fileName));\r\n}\r\n\r\n// TODO Need to add the old 'DoIt' function which executes when a qbr is done. It does a LoadQB then\r\n// reloads the skater exceptions, updates the decks on the skateshop wall, etc...\r\n\r\n} // namespace SkateScript\r\n\r\n"
  },
  {
    "path": "Code/Sk/Scripting/gs_file.h",
    "content": "#ifndef\t__SK_SCRIPTING_GS_FILE_H\r\n#define\t__SK_SCRIPTING_GS_FILE_H\r\n\r\n#ifndef\t__SCRIPTING_SCRIPTDEFS_H\r\n#include <gel/scripting/scriptdefs.h> // For enums\r\n#endif\r\n\r\nnamespace SkateScript\r\n{\r\nusing namespace Script;\r\n\r\nvoid LoadAllStartupQBFiles();\r\nvoid LoadQB(const char *p_fileName, \r\n\t\t\tEBoolAssertIfDuplicateSymbols assertIfDuplicateSymbols=NO_ASSERT_IF_DUPLICATE_SYMBOLS);\r\nvoid UnloadQB(uint32 fileNameChecksum);\r\nuint32 GenerateFileNameChecksum(const char *p_fileName);\r\nvoid UnloadQB(const char *p_fileName);\r\n\r\n} // namespace SkateScript\r\n\r\n#endif // #ifndef\t__SK_SCRIPTING_GS_FILE_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Scripting/gs_init.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// gs_init.cpp\t\tKSH 7 Nov 2001\r\n//\r\n// Game-specific script system initialisation.\r\n// Also calls the non-game-specific script initialisation.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <sk/scripting/gs_init.h>\r\n#include <sk/scripting/gs_file.h>\r\n#include <sk/scripting/nodearray.h>\r\n#include <sk/scripting/ftables.h>\r\n#include <gel/scripting/init.h>\r\n#include <gel/scripting/parse.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/checksum.h>\r\n\r\nnamespace SkateScript\r\n{\r\n\r\n// Called once on startup.\r\nvoid Init()\r\n{\r\n\t// Do the non-game-specific script system initialisation\r\n\tMem::PushMemProfile(\"Script::AllocatePools\");\r\n\tScript::AllocatePools();\r\n\tMem::PopMemProfile();\r\n\t\r\n\t\r\n\t// Now do the game-specific script system initialisation\r\n\tMem::PushMemProfile(\"InitNodeNameHashTable\");\r\n\tInitNodeNameHashTable();\r\n\tMem::PopMemProfile();\r\n\t\r\n\r\n\tMem::PushMemProfile(\"Registering script functions\");\r\n\tScript::RegisterCFunctions(CFunctionLookupTable,GetCFunctionLookupTableSize());\r\n\tScript::RegisterMemberFunctions(ppMemberFunctionNames,GetNumMemberFunctions());\r\n\tMem::PopMemProfile();\r\n\t\r\n}\r\n\r\nvoid Preload()\r\n{\r\n\tLoadAllStartupQBFiles();\r\n\t\r\n\t#ifdef COUNT_USAGE\r\n\tCSymbolTableEntry *p_sym=GetNextSymbolTableEntry();\r\n\twhile (p_sym)\r\n\t{\r\n\t\tif (p_sym->mType==ESYMBOLTYPE_QSCRIPT)\r\n\t\t{\r\n\t\t\t//printf(\"%s\\n\",Script::FindChecksumName(p_sym->mNameChecksum));\r\n\t\t\t\r\n\t\t\tuint8 *p_token=p_sym->mpScript;\r\n\t\t\t// Skip over the 4-byte contents checksum.\r\n\t\t\tp_token+=4;\r\n\t\t\t\r\n\t\t\twhile (*p_token!=ESCRIPTTOKEN_KEYWORD_ENDSCRIPT) \r\n\t\t\t{\r\n\t\t\t\tswitch (*p_token)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase ESCRIPTTOKEN_NAME:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t++p_token;\r\n\t\t\t\t\t\tuint32 name_checksum=Read4Bytes(p_token).mChecksum;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tp_token+=4;\r\n\t\t\t\r\n\t\t\t\t\t\t// Look up the name to see if it is a cfunction or member function.\r\n\t\t\t\t\t\tCSymbolTableEntry *p_entry=Resolve(name_checksum);\r\n\t\t\t\t\t\tif (p_entry)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t//if (name_checksum==0xb0bcbaec)\r\n\t\t\t\t\t\t\t//printf(\"(%s) Type=%s\\n\",Script::FindChecksumName(name_checksum),Script::GetTypeName(p_entry->mType));\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tif (p_entry->mType==ESYMBOLTYPE_CFUNCTION)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t++p_entry->mUsage;\r\n\t\t\t\t\t\t\t\t//printf(\"%s: %s\\n\",Script::FindChecksumName(p_sym->mNameChecksum),Script::FindChecksumName(name_checksum));\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse if (p_entry->mType==ESYMBOLTYPE_MEMBERFUNCTION)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t++p_entry->mUsage;\r\n\t\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t}\t\t\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tp_token=SkipToken(p_token);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t}\r\n\t\tp_sym=GetNextSymbolTableEntry(p_sym);\r\n\t}\t\t\r\n\t\r\n\tp_sym=GetNextSymbolTableEntry();\r\n\twhile (p_sym)\r\n\t{\r\n\t\tif (p_sym->mUsage==0)\r\n\t\t{\r\n\t\t\tif (p_sym->mType==ESYMBOLTYPE_CFUNCTION)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"CFunc %s: Usage=%d\\n\",Script::FindChecksumName(p_sym->mNameChecksum),p_sym->mUsage);\r\n\t\t\t}\r\n\t\t\tif (p_sym->mType==ESYMBOLTYPE_MEMBERFUNCTION)\r\n\t\t\t{\r\n\t\t\t\t//printf(\"MemberFunc %s: Usage=%d\\n\",Script::FindChecksumName(p_sym->mNameChecksum),p_sym->mUsage);\r\n\t\t\t}\r\n\t\t}\t\r\n\t\tp_sym=GetNextSymbolTableEntry(p_sym);\r\n\t}\t\t\r\n\t\r\n\tprintf(\"Finished\\n\");\r\n\twhile (1);\r\n\t#endif // #ifdef COUNT_USAGE\r\n\r\n\r\n\r\n\t\r\n\t// Now that all the qb's are loaded, pre-process all the scripts.\r\n\t//PreProcessScripts();\r\n}\r\n\r\n} // namespace SkateScript\r\n\r\n"
  },
  {
    "path": "Code/Sk/Scripting/gs_init.h",
    "content": "#ifndef\t__SK_SCRIPTING_GS_INIT_H\r\n#define\t__SK_SCRIPTING_GS_INIT_H\r\n\r\nnamespace SkateScript\r\n{\r\n\r\nvoid Init();\r\nvoid Preload();\r\n\r\n} // namespace SkateScript\r\n\r\n#endif // #ifndef __SK_SCRIPTING_GS_INIT_H\r\n"
  },
  {
    "path": "Code/Sk/Scripting/mcfuncs.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Scripting\r\n//* FILENAME:       McFuncs.cpp\r\n//* OWNER:          Kendall Harrison\r\n//* CREATION DATE:  6/10/2002\r\n//****************************************************************************\r\n\r\n// Contains Mem card stuff.\r\n\r\n// TODO: Make all local variables conform to the naming convention! Currently they are a mix\r\n\r\n// start autoduck documentation\r\n// @DOC cfuncs\r\n// @module cfuncs | None\r\n// @subindex Scripting Database\r\n// @index script | cfuncs\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/scripting/mcfuncs.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/mcman.h>\r\n#include <sys/config/config.h>\r\n#include <gel/music/music.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/symboltable.h> \r\n#include <gel/scripting/utils.h>\r\n#include <gel/soundfx/soundfx.h>\r\n#include <sk/objects/records.h>\r\n#include <sk/objects/playerprofilemanager.h>\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/modules/skate/GoalManager.h>\r\n#include <sk/parkeditor2/parked.h>\r\n#include <gel/scripting/component.h>\r\n#include <sys/replay/replay.h>\r\n#include <gel/objtrack.h>\r\n#include <sk/components/goaleditorcomponent.h>\r\n#include <sk/components/raileditorcomponent.h>\r\n\r\n#ifdef __PLAT_NGPS__\r\n#include <libmc.h>\r\n#endif // __PLAT_NGPS__\r\n\r\n#ifdef __PLAT_NGC__\r\n#include \"sys/ngc/p_file.h\"\r\n#include \"sys/ngc/p_buffer.h\"\r\n#include \"sys/ngc/p_dma.h\"\r\n#include \"sys/ngc/p_aram.h\"\r\nbool g_mc_hack = false;\r\nuint32 g_hack_address = 0;\r\nextern char * g_p_buffer;\r\n#endif\t\t// __PLAT_NGC__\r\n\r\nnamespace CFuncs\r\n{\r\n\r\nusing namespace Script;\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Whenever the format of one of these file types has changed such that\r\n// an old save will not load, increment its version number.\r\n/*\r\n// GJ:  I moved this to memcard.q, because the artists/designers sometimes\r\n// do things that will require a version change.\r\n\r\n#define VERSION_OPTIONSANDPROS 10\r\n#define VERSION_NETWORKSETTINGS 3\r\n#define VERSION_CAS 4\r\n#define VERSION_CAT 1\r\n#define VERSION_PARK 2\r\n#define VERSION_REPLAY 6\r\n*/\r\n\r\n// The max number of files that can appear in the file list.\r\n// A max is specified both to ensure we don't run out of memory in the files menu, and\r\n// also to limit the pause before the menu comes up because it has to open each file first\r\n// to extract the summary info.\r\n#define MAX_THPS4_FILES_ALLOWED 75\r\n\r\n// Limit the space that the summary info structure is allowed to take up when written to a buffer.\r\n// This is because we want to be able to quickly read in the summary info from the start of the\r\n// mem card file without having to read in the whole file. (Units are bytes)\r\n#define MAX_SUMMARY_INFO_SIZE 100\r\n\r\n// Max chars allowed in the low level card filename.\r\n#define MAX_CARD_FILE_NAME_CHARS 100\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// This value gets added to the character 'a' in the last char of the \r\n// low-level card filename to indicate what the type of the file is.\r\nenum EMemCardFileType\r\n{\r\n\tMEMCARD_FILETYPE_CAREER,\r\n\tMEMCARD_FILETYPE_CAS,\r\n\tMEMCARD_FILETYPE_PARK,\r\n\tMEMCARD_FILETYPE_REPLAY,\r\n\tMEMCARD_FILETYPE_NETWORKSETTINGS,\r\n    MEMCARD_FILETYPE_CAT,\r\n    MEMCARD_FILETYPE_CREATEDGOALS,\r\n};\r\n\r\n// The old OptionsAndPros save file now contains the custom skater too, and is divided into 4 parts.\r\n// The LoadFromMemoryCard command provides the option of only applying certain parts to the game state.\r\n// For example, when loading a custom skater, only the CUSTOM_SKATER part is applied, so the career\r\n// remains unaffected.\r\nenum EUnifiedSaveFileSubTypes\r\n{\r\n\tAPPLY_GLOBAL_INFO=0,\r\n\tAPPLY_STORY=1,\r\n\tAPPLY_STORY_SKATER=2,\r\n\tAPPLY_CUSTOM_SKATER=3,\r\n};\r\n\t\r\n#ifdef __PLAT_NGC__\r\n// Icons plus banner.\r\n#define\tNGC_MEMCARD_ICON_DATA_SIZE\t\t( 64 + ( 32 * 32 * 7 ) + ( 256 * 2 ) + ( 96 * 32 ) + ( 256 * 2 ) )\r\n#endif\r\n\r\n// The mem card file starts with one of these, followed by two CStruct's as written\r\n// out using WriteToBuffer.\r\n// The first CStruct is the summary info for the file and occupies no more than\r\n// MAX_SUMMARY_INFO_SIZE bytes.\r\n// The second CStruct holds all the save data.\r\nstruct SMcFileHeader\r\n{\r\n\t#ifdef __PLAT_NGC__\r\n\t// On the GameCube the icon data is stored within the file rather than as a\r\n\t// seperate file. So lets wack it into this structure.\r\n\tuint8 mpIconData[NGC_MEMCARD_ICON_DATA_SIZE];\r\n\t#endif\r\n\t\r\n\t#ifdef __PLAT_XBOX__\r\n\t// I think it is a TRC requirement to use the XBox's special way of calculating\r\n\t// a checksum. They probably have ways of telling whether we're using it or not.\r\n\tXCALCSIG_SIGNATURE mSignature;\r\n\t#else\r\n\tuint32 mChecksum;\r\n\t#endif // #ifdef __PLAT_XBOX__\r\n\t\r\n\t// This is so that the files menu can see if a file might be bad \r\n\t// given only the summary info.\r\n\tuint32 mSummaryInfoChecksum;\r\n\tint mSummaryInfoSize;\r\n\r\n\t// This is the size of this header, the summary info structure, and\r\n\t// the main structure, rounded up to the platforms block size.\r\n\t// So for all file types except replays, this should match the total file size.\r\n\t// In the case of replays, the replay data comes after that lot.\r\n\t// mDataSize is needed to indicate the start of the replay data.\r\n\tint mDataSize;\r\n\t\r\n\tint mVersion;\r\n};\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __PLAT_NGC__\r\nstatic unsigned short s_ascii_special[33][2] = {\r\n\t{0x8140, 32},\t\t/*   */\r\n\t{0x8149, 33},\t\t/* ! */\r\n\t{0x8168, 34},\t\t/* \" */\r\n\t{0x8194, 35},\t\t/* # */\r\n\t{0x8190, 36},\t\t/* $ */\r\n\t{0x8193, 37},\t\t/* % */\r\n\t{0x8195, 38},\t\t/* & */\r\n\t{0x8166, 39},\t\t/* ' */\r\n\t{0x8169, 40},\t\t/* ( */\r\n\t{0x816a, 41},\t\t/* ) */\r\n\t{0x8196, 42},\t\t/* * */\r\n\t{0x817b, 43},\t\t/* + */\r\n\t{0x8143, 44},\t\t/* , */\r\n\t{0x817c, 45},\t\t/* - */\r\n\t{0x8144, 46},\t\t/* . */\r\n\t{0x815e, 47},\t\t/* / */\r\n\t{0x8146, 58},\t\t/* : */\r\n\t{0x8147, 59},\t\t/* ; */\r\n\t{0x8171, 60},\t\t/* < */\r\n\t{0x8181, 61},\t\t/* = */\r\n\t{0x8172, 62},\t\t/* > */\r\n\t{0x8148, 63},\t\t/* ? */\r\n\t{0x8197, 64},\t\t/* @ */\r\n\t{0x816d, 91},\t\t/* [ */\r\n\t{0x818f, 92},\t\t/* \\ */\r\n\t{0x816e, 93},\t\t/* ] */\r\n\t{0x814f, 94},\t\t/* ^ */\r\n\t{0x8151, 95},\t\t/* _ */\r\n\t{0x8165, 96},\t\t/* ` */\r\n\t{0x816f, 123},\t\t/* { */\r\n\t{0x8162, 124},\t\t/* | */\r\n\t{0x8170, 125},\t\t/* } */\r\n\t{0x8150, 126},\t\t/* ~ */\r\n};\r\n\r\nstatic unsigned short s_ascii_table[3][2] = {\r\n\t{0x824f, 0x30},\t/* 0-9  */\r\n\t{0x8260, 0x41},\t/* A-Z  */\r\n\t{0x8281, 0x61},\t/* a-z  */\r\n};\r\n#endif // #ifndef __PLAT_NGC__\r\n\r\n// Used by the SaveFailedDueToInsufficientSpace command.\r\nstatic bool s_insufficient_space=false;\r\n\r\n#if __USE_REPLAYS__\r\nstatic char spReplayCardFileName[MAX_CARD_FILE_NAME_CHARS+1];\r\nstatic bool sNeedToLoadReplayBuffer=false;\r\n#endif\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\nstatic const char *s_generate_ascii_checksum(char *p_dest, const char *p_string, uint32 fileType=0);\r\nstatic uint32 s_determine_file_type(char c);\r\n#ifndef __PLAT_NGC__\r\nstatic unsigned short s_ascii_to_sjis(unsigned char ascii_code);\r\n#endif\r\nstatic void s_insert_global_info(CStruct *p_struct);\r\nstatic void s_insert_story_info(CStruct *p_struct);\r\nstatic void s_insert_story_skater_info(CStruct *p_struct);\r\nstatic void s_insert_custom_skater_info(CStruct *p_struct);\r\nstatic void s_insert_game_save_info(uint32 fileType, CStruct *p_struct);\r\nstatic void s_generate_summary_info(CStruct *p_summaryInfo, uint32 fileType, CStruct *p_mainData);\r\n\r\nstatic void s_read_global_info(CStruct *p_globalInfo, CScript *p_script);\r\nstatic void s_read_story_info(CStruct *p_storyInfo);\r\nstatic void s_read_story_skater_info(CStruct *p_storySkaterInfo, CStruct *p_customSkater);\r\nstatic void s_read_custom_skater_info(CStruct *p_customSkater);\r\nstatic void s_read_game_save_info(uint32 fileType, CStruct *p_struct, CScript *p_script);\r\n\r\nstatic int s_get_icon_k_required(uint32 fileType);\r\nstatic int s_calculate_total_space_used_on_card(uint32 fileType, int fileSize);\r\nstatic int s_get_platforms_block_size();\r\nstatic int s_round_up_to_platforms_block_size(int fileSize);\r\nstatic int s_get_version_number(uint32 fileType);\r\nstatic const char *s_generate_xbox_directory_name(uint32 fileType, const char *p_name);\r\nstatic void s_generate_card_directory_name(uint32 fileType, const char *p_name, char *p_card_directory_name);\r\nstatic bool s_make_xbox_dir_and_icons(\tMc::Card *p_card,\r\n\t\t\t\t\t\t\t\t\t\tuint32 fileType, const char *p_name, \r\n\t\t\t\t\t\t\t\t\t\tchar *p_card_file_name,\r\n\t\t\t\t\t\t\t\t\t\tbool *p_insufficientSpace);\r\nstatic bool s_make_ps2_dir_and_icons(\tMc::Card *p_card,\r\n\t\t\t\t\t\t\t\t\t\tuint32 fileType, const char *p_name, \r\n\t\t\t\t\t\t\t\t\t\tchar *p_card_file_name,\r\n\t\t\t\t\t\t\t\t\t\tbool *p_insufficientSpace);\r\nstatic bool s_insert_ngc_icon(\tSMcFileHeader *p_fileHeader, \r\n\t\t\t\t\t\t\t\tMc::Card *p_card,\r\n\t\t\t\t\t\t\t\tMc::File *p_file,\r\n\t\t\t\t\t\t\t\tuint32 fileType,\r\n\t\t\t\t\t\t\t\tconst char *p_name);\r\nstatic uint32 sGetFixedFileSize(uint32 fileType);\r\n\r\n\r\n\r\n// When transferring data between the online vault and the mem card, this structure temporarily holds\r\n// the data. The LoadFromMemoryCard and SaveToMemoryCard commands can be made to load to/from this structure\r\n// instead, so that data can be transferred without loading it into the game.\r\nstatic Script::CStruct *spVaultData=NULL;\r\nstatic uint32 sVaultDataType=0;\r\n\r\n// Steve's code calls this after downloading the binary data from the vault.\r\nvoid SetVaultData(uint8 *p_data, uint32 type)\r\n{\r\n\tif (spVaultData)\r\n\t{\r\n\t\tdelete spVaultData;\r\n\t\tspVaultData=NULL;\r\n\t}\r\n\t\r\n\tspVaultData=new Script::CStruct;\r\n\tScript::ReadFromBuffer(spVaultData,p_data);\r\n\tsVaultDataType=type;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// This calculates an 8 character ascii checksum of the passed string.\r\n// Used for generating the filename of the memory card file from the name the player has chosen.\r\n\r\n// It works by calculating a 32 bit checksum the usual way, then\r\n// converting this number to base 26 and using 'a' to represent 0, 'b' for 1, etc.\r\n// Log to base 26 of 2^32 is 6.8, which means at most 7 ascii characters will be needed, so the \r\n// 8th letter in the string will actually always be a. So the last letter is used to indicate the file type.\r\nstatic const char *s_generate_ascii_checksum(char *p_dest, const char *p_string, uint32 fileType)\r\n{\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest\"));\r\n\t\r\n\tuint32 Checksum=Script::GenerateCRC(p_string);\r\n\tfor (int i=0; i<8; ++i)\r\n\t{\r\n\t\tint Rem=Checksum%26;\r\n\t\tp_dest[i]='a'+Rem;\r\n\t\tChecksum=(Checksum-Rem)/26;\r\n\t}\t\r\n\t// Check that mathematics is still working ok\r\n\tDbg_MsgAssert(Checksum==0,(\"Checksum not zero ???\"));\r\n\tDbg_MsgAssert(p_dest[7]=='a',(\"Last letter of ascii checksum not 'a' ???\"));\r\n\r\n\tswitch (fileType)\r\n\t{\r\n\t\tcase 0xb010f357: // OptionsAndPros\r\n\t\t\tp_dest[7]='a'+MEMCARD_FILETYPE_CAREER;\r\n\t\t\tbreak;\r\n\t\tcase 0xffc529f4: // Cas\r\n\t\t\tDbg_MsgAssert(0,(\"CAS mem card files are no longer supported! Use OptionsAndPros file type instead\"));\r\n\t\t\t//p_dest[7]='a'+MEMCARD_FILETYPE_CAS;\r\n\t\t\tbreak;\r\n        case 0x61a1bc57: // CAT\r\n\t\t\tp_dest[7]='a'+MEMCARD_FILETYPE_CAT;\r\n\t\t\tbreak;\r\n\t\tcase 0x3bf882cc: // Park\r\n\t\t\tp_dest[7]='a'+MEMCARD_FILETYPE_PARK;\r\n\t\t\tbreak;\r\n\t\tcase 0x26c80b0d: // Replay\r\n\t\t\tp_dest[7]='a'+MEMCARD_FILETYPE_REPLAY;\r\n\t\t\tbreak;\r\n\t\tcase 0xca41692d: // NetworkSettings\r\n\t\t\tp_dest[7]='a'+MEMCARD_FILETYPE_NETWORKSETTINGS;\r\n\t\t\tbreak;\r\n\t\tcase 0x62896edf: // CreatedGoals\r\n\t\t\tp_dest[7]='a'+MEMCARD_FILETYPE_CREATEDGOALS;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\tp_dest[8]=0;\r\n\treturn p_dest;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic uint32 s_determine_file_type(char c)\r\n{\r\n\tswitch (c-'a')\r\n\t{\r\n\tcase MEMCARD_FILETYPE_CAREER:\r\n\t\treturn 0xb010f357; // OptionsAndPros\r\n\t\tbreak;\r\n\tcase MEMCARD_FILETYPE_CAS:\r\n\t\treturn 0xffc529f4; // Cas\r\n\t\tbreak;\r\n    case MEMCARD_FILETYPE_CAT:\r\n\t\treturn 0x61a1bc57; // CAT\r\n\t\tbreak;\r\n\tcase MEMCARD_FILETYPE_PARK:\r\n\t\treturn 0x3bf882cc; // Park\r\n\t\tbreak;\r\n\tcase MEMCARD_FILETYPE_REPLAY:\t\r\n\t\treturn 0x26c80b0d; // Replay\r\n\t\tbreak;\r\n\tcase MEMCARD_FILETYPE_NETWORKSETTINGS:\t\r\n\t\treturn 0xca41692d; // NetworkSettings\r\n\t\tbreak;\r\n\tcase MEMCARD_FILETYPE_CREATEDGOALS:\t\r\n\t\treturn 0x62896edf; // CreatedGoals\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn 0;\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n#ifndef __PLAT_NGC__\r\nstatic unsigned short s_ascii_to_sjis(unsigned char ascii_code)\r\n{\r\n\tif (Config::PAL())\r\n\t{\r\n\t\t// The PS2 shell will not display underscores (it shows them as spaces)\r\n\t\t// so convert them to hyphens.\r\n\t\tif (ascii_code=='_')\r\n\t\t{\r\n\t\t\tascii_code='-';\r\n\t\t}\t\r\n\t}\t\r\n\r\n\tswitch ((char)ascii_code)\r\n\t{\r\n\t\tcase '': ascii_code='B'; break;\r\n\t\tcase '': ascii_code='A'; break;\r\n\t\tcase '': ascii_code='U'; break;\r\n\t\tcase '': ascii_code='O'; break;\r\n\t\tcase '': ascii_code='a'; break;\r\n\t\tcase '': ascii_code='a'; break;\r\n\t\tcase '': ascii_code='a'; break;\r\n\t\tcase '': ascii_code='e'; break;\r\n\t\tcase '': ascii_code='e'; break;\r\n\t\tcase '': ascii_code='e'; break;\r\n\t\tcase '': ascii_code='e'; break;\r\n\t\tcase '': ascii_code='i'; break;\r\n\t\tcase '': ascii_code='i'; break;\r\n\t\tcase '': ascii_code='i'; break;\r\n\t\tcase '': ascii_code='o'; break;\r\n\t\tcase '': ascii_code='o'; break;\r\n\t\tcase '': ascii_code='o'; break;\r\n\t\tcase '': ascii_code='u'; break;\r\n\t\tcase '': ascii_code='u'; break;\r\n\t\tcase '': ascii_code='u'; break;\r\n\t\tcase '': ascii_code='c'; break;\r\n\t\tcase '': ascii_code='o'; break;\r\n\t\tdefault: break;\r\n\t}\r\n\t\r\n\tunsigned short sjis_code = 0;\r\n\tunsigned char stmp=0;\r\n\tunsigned char stmp2 = 0;\r\n\r\n\tif((ascii_code >= 0x20) && (ascii_code <= 0x2f))\r\n\t\tstmp2 = 1;\r\n\t\r\n\telse if((ascii_code >= 0x30) && (ascii_code <= 0x39))\r\n\t\tstmp = 0;\r\n\t\r\n\telse if((ascii_code >= 0x3a) && (ascii_code <= 0x40))\r\n\t\tstmp2 = 11;\r\n\t\r\n\telse if((ascii_code >= 0x41) && (ascii_code <= 0x5a))\r\n\t\tstmp = 1;\r\n\t\r\n\telse if((ascii_code >= 0x5b) && (ascii_code <= 0x60))\r\n\t\tstmp2 = 37;\r\n\t\r\n\telse if((ascii_code >= 0x61) && (ascii_code <= 0x7a))\r\n\t\tstmp = 2;\r\n\t\r\n\telse if((ascii_code >= 0x7b) && (ascii_code <= 0x7e))\r\n\t\tstmp2 = 63;\r\n\t\r\n\telse \r\n\t{\r\n\t\tprintf(\"bad ASCII code 0x%x\\n\", ascii_code);\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tif (stmp2)\r\n\t   \tsjis_code = s_ascii_special[ascii_code - 0x20 - (stmp2 - 1)][0];\r\n\telse\r\n\t\tsjis_code = s_ascii_table[stmp][0] + ascii_code - s_ascii_table[stmp][1];\r\n\r\n\treturn sjis_code;\r\n}\r\n#endif\t\t// __PLAT_NGC__\r\n\r\nstatic void s_insert_global_info(CStruct *p_struct)\r\n{\r\n\t// Build the global options structure and insert it into p_struct.\r\n\t\r\n\tScript::CStruct *pOptions=new Script::CStruct;\r\n\t\r\n\t// Attach the split screen preferences.\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tPrefs::Preferences *pPreferences = pSkate->GetSplitScreenPreferences();\r\n\tDbg_MsgAssert(pPreferences,(\"NULL split screen pPreferences\"));\r\n\t\r\n\t// Create a new structure, append the data contained in the preferences, then insert the pointer to the\r\n\t// new structure into pOptions.\r\n\tScript::CStruct *pTemp=new Script::CStruct;\r\n\tpTemp->AppendStructure(pPreferences->GetRoot());\r\n\tpOptions->AddStructurePointer(CRCD(0xf7720c3f,\"SplitScreenPreferences\"),pTemp);\r\n\r\n\t// Get the sound options and stick them in a structure and add that.\r\n\tpTemp=new Script::CStruct;\r\n\t\r\n\tSfx::CSfxManager * pSfxManager = Sfx::CSfxManager::Instance();\r\n\tfloat MainVolume=pSfxManager->GetMainVolume();\r\n\tpTemp->AddFloat(CRCD(0x6f016dfb,\"MainVolume\"),MainVolume);\r\n\r\n\tfloat MusicVolume=Pcm::GetVolume();\r\n\tpTemp->AddFloat(CRCD(0xabd4a575,\"MusicVolume\"),MusicVolume);\r\n\t\r\n\t//uint64 PlayListForbiddenTrackFlags=Pcm::GetPlaylist();\r\n    uint64 list1,list2;\r\n    Pcm::GetPlaylist(&list1, &list2);\r\n\r\n\tuint32 PlayListForbiddenTrackFlags1=(uint32)(list1>>32);\r\n\tuint32 PlayListForbiddenTrackFlags2=(uint32)list1;\r\n\r\n    uint32 PlayListForbiddenTrackFlags3=(uint32)(list2>>32);\r\n\tuint32 PlayListForbiddenTrackFlags4=(uint32)list2;\r\n\t\r\n\tpTemp->AddInteger(CRCD(0x595d2c95,\"PlayListForbiddenTrackFlags1\"),PlayListForbiddenTrackFlags1);\r\n\tpTemp->AddInteger(CRCD(0xc0547d2f,\"PlayListForbiddenTrackFlags2\"),PlayListForbiddenTrackFlags2);\r\n    pTemp->AddInteger(CRCD(0xb7534db9,\"PlayListForbiddenTrackFlags3\"),PlayListForbiddenTrackFlags3);\r\n\tpTemp->AddInteger(CRCD(0x2937d81a,\"PlayListForbiddenTrackFlags4\"),PlayListForbiddenTrackFlags4);\r\n\r\n\t// current_soundtrack only applies to XBox\r\n\tif (Config::GetHardware()==Config::HARDWARE_XBOX)\r\n\t{\r\n\t\tpTemp->AddChecksum(CRCD(0xe1f7c4ae,\"current_soundtrack\"),Script::GetChecksum(\"current_soundtrack\"));\r\n\t}\t\r\n\t\r\n\tif (Pcm::GetRandomMode())\r\n\t{\r\n\t\tpTemp->AddChecksum(NONAME,CRCD(0x31c71b70,\"RandomMode\"));\r\n\t}\t\r\n\t\r\n\tpOptions->AddStructurePointer(CRCD(0x89eb9738,\"SoundOptions\"),pTemp);\r\n\r\n\t// Add the controller preferences.\r\n\tScript::CArray *pControllerPrefs=new Script::CArray;\r\n\tpControllerPrefs->SetSizeAndType(Mdl::Skate::vMAX_SKATERS, ESYMBOLTYPE_STRUCTURE);\r\n\tfor (int i=0; i<Mdl::Skate::vMAX_SKATERS; ++i)\r\n\t{\r\n\t\tpTemp=new Script::CStruct;\r\n\t\tif (pSkate->mp_controller_preferences[i].AutoKickOn)\r\n\t\t{\r\n\t\t\tpTemp->AddChecksum(NONAME,CRCD(0x1eef7085,\"AutoKickOn\"));\r\n\t\t}\t\r\n\t\tif (pSkate->mp_controller_preferences[i].SpinTapsOn)\r\n\t\t{\r\n\t\t\tpTemp->AddChecksum(NONAME,CRCD(0xa483ba67,\"SpinTapsOn\"));\r\n\t\t}\t\r\n\t\tif (pSkate->mp_controller_preferences[i].VibrationOn)\r\n\t\t{\r\n\t\t\tpTemp->AddChecksum(NONAME,CRCD(0x73cee124,\"VibrationOn\"));\r\n\t\t}\t\r\n\t\tpControllerPrefs->SetStructure(i,pTemp);\r\n\t}\t\t\t\r\n\t\r\n\tpOptions->AddArrayPointer(CRCD(0x37bdb853,\"ControllerPreferences\"),pControllerPrefs);\r\n\r\n\t// Insert the taunt stuff\r\n\tGameNet::Manager * pGamenet = GameNet::Manager::Instance();\r\n\tpPreferences=pGamenet->GetTauntPreferences();\r\n\tDbg_MsgAssert(pPreferences,(\"NULL taunt pPreferences\"));\r\n\tpOptions->AddStructure(CRCD(0xe62b6586,\"Taunts\"),pPreferences->GetRoot());\r\n\r\n\t// Now insert the pointer to the newly constucted pOptions into the mem card structure.\r\n\tp_struct->AddStructurePointer(CRCD(0x2fca0578,\"Options\"),pOptions);\r\n\r\n\t// save the career (Game progress, flags and gap checklist)\t\t\t\r\n\tMdl::Skate::Instance()->GetCareer()->WriteIntoStructure(p_struct);\r\n\r\n\t// Add the game records.\t\t  \r\n\tRecords::CGameRecords *pGameRecords=pSkate->GetGameRecords();\r\n\tDbg_MsgAssert(pGameRecords,(\"NULL pGameRecords\"));\r\n\tpGameRecords->WriteIntoStructure(p_struct);\r\n\t\r\n\t// Wack in the pro skater profile info\r\n\tScript::CStruct *p_pros=new Script::CStruct;\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=pSkate->GetPlayerProfileManager();\r\n\tDbg_MsgAssert(pPlayerProfileManager,(\"NULL pPlayerProfileManager\"));\r\n\tpPlayerProfileManager->AddAllProProfileInfo(p_pros);\r\n\tp_struct->AddStructurePointer(CRCD(0xc9986baf,\"Pros\"),p_pros);\r\n\t\r\n\t// Note: Mustn't delete pOptions or the other structures created above\r\n\t// since pointers to these have been given to p_struct.\r\n\t// p_struct will clean them up when it gets deleted.\r\n}\r\n\r\nstatic void s_insert_story_info(CStruct *p_struct)\r\n{\r\n\t// Save the goal manager parameters.\r\n\tGame::CGoalManager* p_goal_manager=Game::GetGoalManager();\r\n\tDbg_MsgAssert(p_goal_manager,(\"NULL p_goal_manager\"));\r\n\t\r\n\tCStruct *p_goal_manager_params=p_goal_manager->GetGoalManagerParams();\r\n\tDbg_MsgAssert(p_goal_manager_params,(\"NULL p_goal_manager_params\"));\r\n\tp_struct->AddStructure(CRCD(0xac7c2b62,\"GoalManagerParams\"),p_goal_manager_params);\r\n}\r\n\r\nstatic void s_insert_story_skater_info(CStruct *p_struct)\r\n{\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = pSkate->GetSkater(0);\r\n\tDbg_Assert( pSkater );\r\n\tpSkater->AddCATInfo(p_struct);\r\n\t\r\n    // stat goal status\r\n    pSkater->AddStatGoalInfo(p_struct);\r\n    \r\n    // chapter status\r\n    pSkater->AddChapterStatusInfo(p_struct);\r\n}\r\n\r\nstatic void s_insert_custom_skater_info(CStruct *p_struct)\r\n{\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=pSkate->GetPlayerProfileManager();\r\n\tDbg_MsgAssert(pPlayerProfileManager,(\"NULL pPlayerProfileManager\"));\r\n\t\r\n\tpPlayerProfileManager->AddCASProfileInfo(p_struct);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void s_insert_game_save_info(uint32 fileType, CStruct *p_struct)\r\n{\r\n\t// WARNING !\t\tWARNING !\t\tWARNING !\t\tWARNING !\t\tWARNING !\r\n\t// Make sure that no function in here stores any pointers to new CStructs.\r\n\t// This is because all new CStructs (and CComponents) allocated here will be coming\r\n\t// off a special pool, to avoid overflowing the regular pool.\r\n\t\r\n\tDbg_MsgAssert(p_struct,(\"NULL p_struct\"));\r\n\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t#if 0 \t\t// Actually remove it fully, as the code that uses it had been temp stubbed out,a nd we don't want to confuse the non final build into thinking it's there\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=pSkate->GetPlayerProfileManager();\r\n\tDbg_MsgAssert(pPlayerProfileManager,(\"NULL pPlayerProfileManager\"));\r\n\t#endif\r\n\t#endif\r\n\t\r\n\tswitch (fileType)\r\n\t{\r\n\t\tcase 0xb010f357: // OptionsAndPros\r\n\t\t{\r\n\t\t\tScript::CStruct *p_global_info=new Script::CStruct;\r\n\t\t\ts_insert_global_info(p_global_info);\r\n\t\t\tp_struct->AddStructurePointer(CRCD(0xf55cbd13,\"GlobalInfo\"),p_global_info);\r\n\t\t\t\r\n\t\t\tScript::CStruct *p_story=new Script::CStruct;\r\n\t\t\ts_insert_story_info(p_story);\r\n\t\t\tp_struct->AddStructurePointer(CRCD(0x14a9fbc7,\"Story\"),p_story);\r\n\t\t\t\r\n\t\t\tScript::CStruct *p_story_skater=new Script::CStruct;\r\n\t\t\ts_insert_story_skater_info(p_story_skater);\r\n\t\t\tp_struct->AddStructurePointer(CRCD(0xdf2f448,\"StorySkater\"),p_story_skater);\r\n\t\t\t\r\n\t\t\tScript::CStruct *p_custom_skater=new Script::CStruct;\r\n\t\t\ts_insert_custom_skater_info(p_custom_skater);\r\n\t\t\tp_struct->AddStructurePointer(CRCD(0x12bfac82,\"CustomSkater\"),p_custom_skater);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0xca41692d: // NetworkSettings\t\t\r\n\t\t{\r\n\t\t\t// Add the network preferences\r\n\t\t\tGameNet::Manager * pGamenet = GameNet::Manager::Instance();\r\n\t\t\tPrefs::Preferences *pPreferences=pGamenet->GetNetworkPreferences();\r\n\t\t\tp_struct->AppendStructure(pPreferences->GetRoot());\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\tcase 0xffc529f4: // Cas\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"CAS mem card files are no longer supported! Use OptionsAndPros file type instead\"));\r\n\t\t\t/*\t\t\r\n\t\t\tpPlayerProfileManager->AddCASProfileInfo(p_struct);\r\n            \r\n            Obj::CSkater* pSkater = pSkate->GetSkater(0);\r\n            Dbg_Assert( pSkater );\r\n            pSkater->AddCATInfo(p_struct);\r\n\t\t\t*/\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        case 0x61a1bc57: // Cat\r\n\t\t{\r\n\t\t\t// Can only edit CAT on skater zero!\r\n            Obj::CSkater* pSkater = pSkate->GetSkater(0);\r\n            Dbg_Assert( pSkater );\r\n            \r\n            // Index is always 0 since that is the only one that can be edited directly.\r\n            Game::CCreateATrick* pCreatedTrick = pSkater->m_created_trick[0];\r\n            Dbg_Assert( pCreatedTrick );\r\n\r\n            //Other params\r\n            p_struct->AddStructure( \"other_params\", pCreatedTrick->mp_other_params );\r\n            \r\n            //Rotation params\r\n            p_struct->AddArray( \"rotation_info\", pCreatedTrick->mp_rotations );\r\n            \r\n            //Animation params\r\n            p_struct->AddArray( \"animation_info\", pCreatedTrick->mp_animations );\r\n        \r\n            break;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x3bf882cc: // Park\t (Save)\r\n\t\t{\r\n\t\t\tEd::CParkManager::Instance()->WriteIntoStructure(p_struct);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x26c80b0d: // Replay\r\n\t\t{\r\n#if __USE_REPLAYS__\r\n\t\t\tReplay::AddReplayMemCardInfo(p_struct);\r\n#endif\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0x62896edf: // CreatedGoals\r\n\t\t{\r\n\t\t\tObj::CCompositeObject *p_obj=(Obj::CCompositeObject*)Obj::CTracker::Instance()->GetObject(CRCD(0x81f01058,\"GoalEditor\"));\r\n\t\t\tDbg_MsgAssert(p_obj,(\"No GoalEditor object\"));\r\n\t\t\tObj::CGoalEditorComponent *p_goal_editor=GetGoalEditorComponentFromObject(p_obj);\r\n\t\t\tDbg_MsgAssert(p_goal_editor,(\"No goal editor component ???\"));\r\n\t\t\tp_goal_editor->WriteIntoStructure(p_struct);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"Bad type of '%s' sent to s_insert_game_save_info\",FindChecksumName(fileType)));\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Inserts summary info for the specified file type into p_struct.\r\n// Summary info is a small amount of info that is written at the start of the mem card file\r\n// so that it can be quickly read out without having to read the whole file.\r\n// The info gets printed at the bottom of the files menu when the highlight is on a file.\r\nstatic void s_generate_summary_info(CStruct *p_summaryInfo, uint32 fileType, CStruct *p_mainData)\r\n{\r\n\t// WARNING !\t\tWARNING !\t\tWARNING !\t\tWARNING !\t\tWARNING !\r\n\t// Make sure that no function in here stores any pointers to new CStructs.\r\n\t// This is because all new CStructs (and CComponents) allocated here will be coming\r\n\t// off a special pool, to avoid overflowing the regular pool.\r\n\t\r\n\tDbg_MsgAssert(p_summaryInfo,(\"NULL p_summaryInfo\"));\r\n\r\n\tif (p_mainData)\r\n\t{\r\n\t\t// Extract the summary info from the passed p_mainData.\r\n\t\t// This is for when the save process is being done on data that got downloaded from the vault.\r\n\t\t\r\n\t\tswitch (fileType)\r\n\t\t{\r\n\t\t\tcase 0xb010f357: // OptionsAndPros\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct *p_story=NULL;\r\n\t\t\t\tp_mainData->GetStructure(CRCD(0x14a9fbc7,\"Story\"),&p_story,Script::ASSERT);\r\n\t\t\t\t\r\n\t\t\t\tScript::CStruct *p_goal_manager_params=NULL;\r\n\t\t\t\tp_story->GetStructure(CRCD(0xac7c2b62,\"GoalManagerParams\"),&p_goal_manager_params,Script::ASSERT);\r\n\r\n\t\t\t\tCStruct *p_more_goal_manager_params=NULL;\r\n\t\t\t\tp_goal_manager_params->GetStructure(CRCD(0x23d4170a,\"GoalManager_Params\"),&p_more_goal_manager_params,Script::ASSERT);\r\n\t\t\t\t\r\n\t\t\t\tint chapter=0;\r\n\t\t\t\tp_more_goal_manager_params->GetInteger(CRCD(0xf884773c,\"CurrentChapter\"),&chapter);\r\n\t\t\t\tp_summaryInfo->AddInteger(CRCD(0xf884773c,\"CurrentChapter\"),chapter);\r\n\t\t\t\t\r\n\t\t\t\t// is_male is used by the script upload_content in net.q\r\n\t\t\t\tScript::CStruct *p_custom_skater=NULL;\r\n\t\t\t\tp_mainData->GetStructure(CRCD(0x12bfac82,\"CustomSkater\"),&p_custom_skater,Script::ASSERT);\r\n\t\t\t\tScript::CStruct *p_custom=NULL;\r\n\t\t\t\tp_custom_skater->GetStructure(CRCD(0xa7be964,\"Custom\"),&p_custom,Script::ASSERT);\r\n\t\t\t\tScript::CStruct *p_info=NULL;\r\n\t\t\t\tp_custom->GetStructure(CRCD(0x3476cea8,\"Info\"),&p_info,Script::ASSERT);\r\n                int is_male=0;\r\n\t\t\t\tp_info->GetInteger(CRCD(0x3f813177,\"is_male\"),&is_male);\r\n\t\t\t\tp_summaryInfo->AddInteger(CRCD(0x3f813177,\"is_male\"),is_male);\r\n                const char *p_name=\"\";\r\n                p_info->GetString(CRCD(0x2ab66cb8,\"display_name\"),&p_name);\r\n\t\t\t\tp_summaryInfo->AddString(CRCD(0xa1dc81f9,\"name\"),p_name);\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tcase 0xca41692d: // NetworkSettings\t\t\r\n\t\t\t{\r\n\t\t\t\tp_summaryInfo->AddString(\"network_id\",\"\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\t\t\r\n\t\t\t\r\n\t\t\tcase 0xffc529f4: // Cas\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0,(\"CAS mem card files are no longer supported! Use OptionsAndPros file type instead\"));\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n            case 0x61a1bc57: // Cat\r\n            {\r\n                Script::CStruct *p_data=NULL;\r\n\t\t\t\tp_mainData->GetStructure(CRCD(0x4137cb14,\"other_params\"),&p_data,Script::ASSERT);\r\n                \r\n                const char *p_name=\"\";\r\n\t\t\t\tp_data->GetString(CRCD(0xa1dc81f9,\"name\"),&p_name,Script::ASSERT);\r\n\r\n                p_summaryInfo->AddString(CRCD(0xa1dc81f9,\"name\"),p_name);\r\n                break;\r\n            }\r\n\r\n\t\t\tcase 0x26c80b0d: // Replay\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\r\n\t\t\tcase 0x3bf882cc: // Park\r\n\t\t\t{\r\n\t\t\t\tint num_edited_goals=0;\r\n\t\t\t\t\r\n\t\t\t\tScript::CArray *p_goals=NULL;\r\n\t\t\t\tScript::CStruct *p_goals_struct=NULL;\r\n\t\t\t\tp_mainData->GetStructure(CRCD(0xd8eb825e,\"Park_editor_goals\"),&p_goals_struct);\r\n\t\t\t\tif (p_goals_struct)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_goals_struct->GetArray(CRCD(0x38dbe1d0,\"Goals\"),&p_goals);\r\n\t\t\t\t\tif (p_goals)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnum_edited_goals=p_goals->GetSize();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\t\r\n\t\t\t\tp_summaryInfo->AddInteger(CRCD(0xe1ec606f,\"num_edited_goals\"),num_edited_goals);\r\n\t\t\t\t\r\n\t\t\t\tint max_players=1;\r\n\t\t\t\tp_mainData->GetInteger(CRCD(0xb7e39b53,\"MaxPlayers\"),&max_players);\r\n\t\t\t\tp_summaryInfo->AddInteger(CRCD(0xb7e39b53,\"MaxPlayers\"),max_players);\r\n\t\t\t\t\r\n\t\t\t\tScript::CArray *p_map=NULL;\r\n\t\t\t\tp_mainData->GetArray(CRCD(0x337c5289,\"Park_editor_map\"),&p_map,Script::ASSERT);\r\n\t\t\t\t\r\n\t\t\t\t// Used by the script upload_content in net.q\r\n\t\t\t\tint num_gaps=0;\r\n\t\t\t\tint num_metas=0;\r\n\t\t\t\tuint16 theme=0;\r\n\t\t\t\tuint32 tod_script=0;\r\n\t\t\t\tint width=0;\r\n\t\t\t\tint length=0;\r\n\t\t\t\tEd::CParkManager::Instance()->GetSummaryInfoFromBuffer((uint8*)p_map->GetArrayPointer(),&num_gaps,&num_metas,&theme,&tod_script,&width,&length);\r\n\t\t\t\tp_summaryInfo->AddInteger(CRCD(0xe6121ed0,\"num_gaps\"),num_gaps);\r\n\t\t\t\tp_summaryInfo->AddInteger(CRCD(0xfff3dc35,\"num_pieces\"),num_metas);\r\n\t\t\t\tp_summaryInfo->AddInteger(CRCD(0x688a18f7,\"theme\"),theme);\r\n\t\t\t\tp_summaryInfo->AddChecksum(CRCD(0x4c72ed98,\"tod_script\"),tod_script);\r\n\t\t\t\tp_summaryInfo->AddInteger(CRCD(0x73e5bad0,\"width\"),width);\r\n\t\t\t\tp_summaryInfo->AddInteger(CRCD(0xfe82614d,\"length\"),length);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tcase 0x62896edf: // CreatedGoals\r\n\t\t\t{\r\n\t\t\t\tint num_edited_goals=0;\r\n\t\t\t\t\r\n\t\t\t\tScript::CArray *p_goals=NULL;\r\n\t\t\t\tp_mainData->GetArray(CRCD(0x38dbe1d0,\"Goals\"),&p_goals);\r\n\t\t\t\tif (p_goals)\r\n\t\t\t\t{\r\n\t\t\t\t\tnum_edited_goals=p_goals->GetSize();\r\n\t\t\t\t}\t\r\n\t\t\t\tp_summaryInfo->AddInteger(CRCD(0xe1ec606f,\"num_edited_goals\"),num_edited_goals);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tdefault:\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0,(\"Bad type of '%s' sent to s_generate_summary_info\",FindChecksumName(fileType)));\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\t\r\n\t\t}\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Get the summary info from the game.\r\n\t\t\r\n\t\tswitch (fileType)\r\n\t\t{\r\n\t\t\tcase 0xb010f357: // OptionsAndPros\r\n\t\t\t{\r\n\t\t\t\tGame::CGoalManager* p_goal_manager=Game::GetGoalManager();\r\n\t\t\t\tDbg_MsgAssert(p_goal_manager,(\"NULL p_goal_manager\"));\r\n\t\t\t\t\r\n\t\t\t\tCStruct *p_goal_manager_params=p_goal_manager->GetGoalManagerParams();\r\n\t\t\t\tDbg_MsgAssert(p_goal_manager_params,(\"NULL p_goal_manager_params\"));\r\n\t\r\n\t\t\t\t// Grab the summary info.\r\n\t\t\t\tCStruct *p_more_goal_manager_params=NULL;\r\n\t\t\t\tp_goal_manager_params->GetStructure(CRCD(0x23d4170a,\"GoalManager_Params\"),&p_more_goal_manager_params);\r\n\t\t\t\tDbg_MsgAssert(p_more_goal_manager_params,(\"No GoalManager_Params structure ??\"));\r\n\t\t\t\t\r\n\t\t\t\tint chapter=0;\r\n\t\t\t\tp_more_goal_manager_params->GetInteger(CRCD(0xf884773c,\"CurrentChapter\"),&chapter);\r\n\t\t\t\tp_summaryInfo->AddInteger(CRCD(0xf884773c,\"CurrentChapter\"),chapter);\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tcase 0xca41692d: // NetworkSettings\t\t\r\n\t\t\t{\r\n\t\t\t\tGameNet::Manager * pGamenet = GameNet::Manager::Instance();\r\n\t\t\t\tPrefs::Preferences *pPreferences=pGamenet->GetNetworkPreferences();\r\n\t\t\t\tCStruct *p_net_stuff=pPreferences->GetRoot();\r\n\t\t\t\t\r\n\t\t\t\t// Grab the summary info.\r\n\t\t\t\tCStruct *p_foo=NULL;\r\n\t\t\t\tp_net_stuff->GetStructure(\"network_id\",&p_foo);\r\n\t\t\t\tDbg_MsgAssert(p_foo,(\"No network_id structure ?\"));\r\n\t\t\t\t\r\n\t\t\t\tconst char *p_name=\"\";\r\n\t\t\t\tp_foo->GetString(\"ui_string\",&p_name);\r\n\t\t\t\t\r\n\t\t\t\tp_summaryInfo->AddString(\"network_id\",p_name);\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\t\t\r\n\t\t\t\r\n\t\t\tcase 0xffc529f4: // Cas\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0,(\"CAS mem card files are no longer supported! Use OptionsAndPros file type instead\"));\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\r\n\t\t\tcase 0x61a1bc57: // Cat\r\n\t\t\t{\r\n\t\t\t\t// Can only edit CAT on skater zero!\r\n                Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n                Obj::CSkater* pSkater = pSkate->GetSkater(0);\r\n                Dbg_Assert( pSkater );\r\n                \r\n                // Index is always 0 since that is the only one that can be edited directly.\r\n                Game::CCreateATrick* pCreatedTrick = pSkater->m_created_trick[0];\r\n                Dbg_Assert( pCreatedTrick );\r\n    \r\n                const char *p_name=\"\";\r\n\t\t\t\tpCreatedTrick->mp_other_params->GetString(CRCD(0xa1dc81f9,\"name\"),&p_name,Script::ASSERT);\r\n\r\n                p_summaryInfo->AddString(CRCD(0xa1dc81f9,\"name\"),p_name);\r\n                break;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase 0x26c80b0d: // Replay\r\n\t\t\t{\r\n\t#if __USE_REPLAYS__\r\n\t\t\t\tReplay::AddReplayMemCardSummaryInfo(p_summaryInfo);\r\n\t#endif\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase 0x3bf882cc: // Park\r\n\t\t\tcase 0x62896edf: // CreatedGoals\r\n\t\t\t{\r\n\t\t\t\tObj::CCompositeObject *p_obj=(Obj::CCompositeObject*)Obj::CTracker::Instance()->GetObject(CRCD(0x81f01058,\"GoalEditor\"));\r\n\t\t\t\tDbg_MsgAssert(p_obj,(\"No GoalEditor object\"));\r\n\t\t\t\tObj::CGoalEditorComponent *p_goal_editor=GetGoalEditorComponentFromObject(p_obj);\r\n\t\t\t\tDbg_MsgAssert(p_goal_editor,(\"No goal editor component ???\"));\r\n\t\t\t\t\r\n\t\t\t\tp_summaryInfo->AddInteger(CRCD(0xe1ec606f,\"num_edited_goals\"),p_goal_editor->GetNumGoals());\r\n\t\t\t\t\r\n\t\t\t\tif (fileType==CRCD(0x3bf882cc,\"Park\"))\r\n\t\t\t\t{\r\n\t\t\t\t\tp_summaryInfo->AddInteger(CRCD(0xb7e39b53,\"MaxPlayers\"),Ed::CParkManager::Instance()->GetGenerator()->GetMaxPlayers());\r\n\t\t\t\t\t\r\n\t\t\t\t\tint num_gaps=0;\r\n\t\t\t\t\tint num_metas=0;\r\n\t\t\t\t\tuint16 theme=0;\r\n\t\t\t\t\tuint32 tod_script=0;\r\n\t\t\t\t\tint width=0;\r\n\t\t\t\t\tint length=0;\r\n\t\t\t\t\tEd::CParkManager::Instance()->WriteCompressedMapBuffer();\t\t// Ensure map buffer is correct\r\n\t\t\t\t\tEd::CParkManager::Instance()->GetSummaryInfoFromBuffer(Ed::CParkManager::Instance()->GetCompressedMapBuffer(),&num_gaps,&num_metas,&theme,&tod_script,&width,&length);\r\n\t\t\t\t\tp_summaryInfo->AddInteger(CRCD(0xe6121ed0,\"num_gaps\"),num_gaps);\r\n\t\t\t\t\tp_summaryInfo->AddInteger(CRCD(0xfff3dc35,\"num_pieces\"),num_metas);\r\n\t\t\t\t\tp_summaryInfo->AddInteger(CRCD(0x688a18f7,\"theme\"),theme);\r\n\t\t\t\t\tp_summaryInfo->AddChecksum(CRCD(0x4c72ed98,\"tod_script\"),tod_script);\r\n\t\t\t\t\tp_summaryInfo->AddInteger(CRCD(0x73e5bad0,\"width\"),width);\r\n\t\t\t\t\tp_summaryInfo->AddInteger(CRCD(0xfe82614d,\"length\"),length);\r\n\t\t\t\t}\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tdefault:\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0,(\"Bad type of '%s' sent to s_generate_summary_info\",FindChecksumName(fileType)));\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\t\r\n\t\t}\t\t\r\n\t}\t\r\n}\r\n\r\nstatic void s_read_global_info(CStruct *p_globalInfo, CScript *p_script)\r\n{\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\t\r\n\tScript::CStruct *pOptions=NULL;\r\n\tp_globalInfo->GetStructure(CRCD(0x2fca0578,\"Options\"),&pOptions);\r\n\tDbg_MsgAssert(pOptions,(\"p_globalInfo is missing Options structure\"));\r\n\t\r\n\t// Extract the split screen preferences\r\n\tScript::CStruct *pTemp=NULL;\r\n\tpOptions->GetStructure(CRCD(0xf7720c3f,\"SplitScreenPreferences\"),&pTemp);\r\n\t\r\n\tPrefs::Preferences *pPreferences = pSkate->GetSplitScreenPreferences();\r\n\tDbg_MsgAssert(pPreferences,(\"NULL split screen pPreferences\"));\r\n\tpPreferences->SetRoot(pTemp);\r\n\r\n\t// Get the taunt preferences\r\n\tpTemp=NULL;\r\n\tpOptions->GetStructure(CRCD(0xe62b6586,\"Taunts\"),&pTemp);\r\n\t\r\n\tGameNet::Manager * pGamenet = GameNet::Manager::Instance();\r\n\tpPreferences=pGamenet->GetTauntPreferences();\r\n\tDbg_MsgAssert(pPreferences,(\"NULL taunt pPreferences\"));\r\n\tpPreferences->SetRoot(pTemp);\r\n\r\n\t\r\n\t// Get the sound options.\r\n\tpOptions->GetStructure(CRCD(0x89eb9738,\"SoundOptions\"),&pTemp);\r\n\tSfx::CSfxManager * pSfxManager = Sfx::CSfxManager::Instance();\r\n\tfloat MainVolume=0;\r\n\tif (pTemp->GetFloat(CRCD(0x6f016dfb,\"MainVolume\"),&MainVolume))\r\n\t{\r\n\t\tpSfxManager->SetMainVolume(MainVolume);\r\n\t}\t\r\n\r\n\tfloat MusicVolume=0;\r\n\tif (pTemp->GetFloat(CRCD(0xabd4a575,\"MusicVolume\"),&MusicVolume))\r\n\t{\r\n\t\tPcm::SetVolume(MusicVolume);\r\n\t}\t\r\n\r\n\tuint64 PlayListForbiddenTrackFlagsA=0;\r\n    uint64 PlayListForbiddenTrackFlagsB=0;\r\n\tuint32 PlayListForbiddenTrackFlags1=0;\r\n\tuint32 PlayListForbiddenTrackFlags2=0;\r\n    uint32 PlayListForbiddenTrackFlags3=0;\r\n\tuint32 PlayListForbiddenTrackFlags4=0;\r\n\r\n\tif (pTemp->GetInteger(CRCD(0x595d2c95,\"PlayListForbiddenTrackFlags1\"),(int*)&PlayListForbiddenTrackFlags1))\r\n\t{\r\n\t\tpTemp->GetInteger(CRCD(0xc0547d2f,\"PlayListForbiddenTrackFlags2\"),(int*)&PlayListForbiddenTrackFlags2);\r\n        pTemp->GetInteger(CRCD(0xb7534db9,\"PlayListForbiddenTrackFlags3\"),(int*)&PlayListForbiddenTrackFlags3);\r\n        pTemp->GetInteger(CRCD(0x2937d81a,\"PlayListForbiddenTrackFlags4\"),(int*)&PlayListForbiddenTrackFlags4);\r\n\t\t\r\n\t\tPlayListForbiddenTrackFlagsA=(((uint64)PlayListForbiddenTrackFlags1)<<32)+PlayListForbiddenTrackFlags2;\r\n        PlayListForbiddenTrackFlagsB=(((uint64)PlayListForbiddenTrackFlags3)<<32)+PlayListForbiddenTrackFlags4;\r\n\t\tPcm::SetPlaylist(PlayListForbiddenTrackFlagsA, PlayListForbiddenTrackFlagsB);\r\n\t}\t\r\n\r\n\tif (pTemp->ContainsFlag(CRCD(0x31c71b70,\"RandomMode\")))\r\n\t{\r\n\t\tPcm::SetRandomMode(true);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tPcm::SetRandomMode(false);\r\n\t}\r\n\r\n\tif (Config::GetHardware()==Config::HARDWARE_XBOX)\r\n\t{\r\n\t\tuint32 current_soundtrack=0xffffffff;\r\n\t\tpTemp->GetChecksum(CRCD(0xe1f7c4ae,\"current_soundtrack\"),&current_soundtrack);\r\n\t\t\r\n\t\tScript::CSymbolTableEntry *p_sym=Script::LookUpSymbol(0xe1f7c4ae/*current_soundtrack*/);\r\n\t\tif (p_sym)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(p_sym->mType==ESYMBOLTYPE_NAME,(\"Expected current_soundtrack to have type checksum\"));\r\n\t\t\tp_sym->mChecksum=current_soundtrack;\r\n\t\t}\t\r\n\t\tScript::CStruct* pTemp2 = new Script::CStruct;\r\n        pTemp2->AddChecksum(CRCD(0x8c465905,\"trackchecksum\"),current_soundtrack);\r\n        Script::RunScript(CRCD(0xd44400c2,\"set_loaded_soundtrack\"), pTemp2);\r\n\t}\t\r\n\r\n\t// Extract the controller preferences\r\n\tScript::CArray *pControllerPrefs=NULL;\r\n\tif (pOptions->GetArray(CRCD(0x37bdb853,\"ControllerPreferences\"),&pControllerPrefs))\r\n\t{\r\n\t\tfor (int i=0; i<Mdl::Skate::vMAX_SKATERS; ++i)\r\n\t\t{\r\n\t\t\tScript::CStruct *pPrefs=pControllerPrefs->GetStructure(i);\r\n\t\t\tDbg_MsgAssert(pPrefs,(\"NULL pPrefs?\"));\r\n\r\n\t\t\tpSkate->SetVibration(i,pPrefs->ContainsFlag(CRCD(0x73cee124,\"VibrationOn\")));\r\n\t\t\tpSkate->SetAutoKick(i,pPrefs->ContainsFlag(CRCD(0x1eef7085,\"AutoKickOn\")));\r\n\t\t\tpSkate->SetSpinTaps(i,pPrefs->ContainsFlag(CRCD(0xa483ba67,\"SpinTapsOn\")));\r\n\t\t}\t\r\n\t}\r\n\t\r\n\t// Extract the game records.\t\t  \r\n\tRecords::CGameRecords *pGameRecords=pSkate->GetGameRecords();\r\n\tDbg_MsgAssert(pGameRecords,(\"NULL pGameRecords\"));\r\n\tpGameRecords->ReadFromStructure(p_globalInfo);\r\n\t\r\n\t// Extract the pro & cas skater profile info\r\n\tScript::CStruct *p_pros=NULL;\r\n\tp_globalInfo->GetStructure(CRCD(0xc9986baf,\"Pros\"),&p_pros,Script::ASSERT);\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=pSkate->GetPlayerProfileManager();\r\n\tpPlayerProfileManager->LoadAllProProfileInfo(p_pros);\r\n\r\n\t// Extract the career info (Game progress, flags and gap checklist)\t\t\t\r\n\tMdl::Skate::Instance()->GetCareer()->ReadFromStructure(p_globalInfo);\r\n\t\r\n\t// Return the LastLevelLoadScript and LastGameMode to the calling script.\r\n\t// Needed by Zac so that after autoloading the game can automatically load up the\r\n\t// last level that was being played when saved.\r\n\tuint32 last_level_load_script=0;\r\n\tuint32 last_game_mode=0;\r\n\tCStruct *p_career=NULL;\r\n\tint current_theme=0;\r\n\tp_globalInfo->GetStructure(CRCD(0x4da4937b,\"Career\"),&p_career);\r\n\tif (p_career)\r\n\t{\r\n\t\tp_career->GetChecksum(CRCD(0xe3335d2f,\"LastLevelLoadScript\"),&last_level_load_script);\r\n\t\tp_career->GetChecksum(CRCD(0x2cc06f5e,\"LastGameMode\"),&last_game_mode);\r\n\t\t// Extract current theme\r\n\t\tp_career->GetInteger(CRCD(0xcc946ff3,\"current_theme\"),&current_theme);\r\n\t}\r\n\tif (last_level_load_script)\r\n\t{\r\n\t\tp_script->GetParams()->AddChecksum(CRCD(0xe3335d2f,\"LastLevelLoadScript\"),last_level_load_script);\r\n\t}\r\n\tif (last_game_mode)\r\n\t{\r\n\t\tp_script->GetParams()->AddChecksum(CRCD(0x2cc06f5e,\"LastGameMode\"),last_game_mode);\r\n\t}\r\n\t//if (current_theme) TT7448: current_theme can be saved as zero\r\n\t//{\r\n\t\tScript::CStruct* pTemp2 = new Script::CStruct;\r\n\t\tpTemp2->AddInteger(CRCD(0x3bed2cf5,\"theme_num\"),current_theme);\r\n\t\tpTemp2->AddChecksum(CRCD(0x476cdadd,\"loading_career\"),0);\r\n\t\tScript::RunScript( \"set_current_theme\", pTemp2 );\r\n\t\tdelete pTemp2;\r\n   // }\r\n\t\r\n\t// Now, if the skater is custom, set his cas file name.\r\n\tObj::CSkaterProfile* pSkaterProfile=pSkate->GetCurrentProfile();\r\n\tif (!pSkaterProfile->IsPro())\r\n\t{\r\n\t\tconst char *pCASFileName=\"Unimplemented\";\r\n\t\tp_globalInfo->GetString(CRCD(0xf36c1878,\"CASFileName\"),&pCASFileName);\r\n\t\tpSkaterProfile->SetCASFileName(pCASFileName);\r\n\t}\r\n}\r\n\t\r\nstatic void s_read_story_info(CStruct *p_storyInfo)\r\n{\r\n\t// Load in the goal manager parameters.\r\n\tCStruct *p_loaded_goal_manager_params=NULL;\r\n\tp_storyInfo->GetStructure(CRCD(0xac7c2b62,\"GoalManagerParams\"),&p_loaded_goal_manager_params);\r\n\tDbg_MsgAssert(p_loaded_goal_manager_params,(\"No goal manager params on mem card\"));\r\n\t\r\n\tGame::CGoalManager* p_goal_manager=Game::GetGoalManager();\r\n\tDbg_MsgAssert(p_goal_manager,(\"NULL p_goal_manager\"));\r\n\t\r\n\tp_goal_manager->ResetCareer();\r\n\t\r\n\tCStruct *p_goal_manager_params=p_goal_manager->GetGoalManagerParams();\r\n\tDbg_MsgAssert(p_goal_manager_params,(\"NULL p_goal_manager_params\"));\r\n\t\r\n\tp_goal_manager_params->Clear();\r\n\tp_goal_manager_params->AppendStructure(p_loaded_goal_manager_params);\r\n\r\n\t// Refresh the goal manager with the new params.\r\n\tp_goal_manager->LevelLoad();\r\n}\r\n\r\nstatic void s_read_story_skater_info(CStruct *p_storySkaterInfo, CStruct *p_customSkater)\r\n{\r\n\t// Which skater are we loading?\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\t\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=pSkate->GetPlayerProfileManager();\r\n\tint index = pPlayerProfileManager->GetCurrentProfileIndex();\r\n\tDbg_MsgAssert(index==0,(\"Should not be loading story skater info into any skater other than skater 0, tried to load it into skater %d\",index));\r\n\r\n\tObj::CSkater* pSkater = pSkate->GetSkater(index);\r\n\tDbg_Assert( pSkater );\r\n\tpSkater->LoadCATInfo(p_storySkaterInfo);\r\n    pSkater->LoadStatGoalInfo(p_storySkaterInfo);\r\n    pSkater->LoadChapterStatusInfo(p_storySkaterInfo);\r\n    \r\n    pPlayerProfileManager->LoadCASProfileInfo(p_customSkater, true);\r\n}\r\n\r\nstatic void s_read_custom_skater_info(CStruct *p_customSkater)\r\n{\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\t\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=pSkate->GetPlayerProfileManager();\r\n    int index = pPlayerProfileManager->GetCurrentProfileIndex();\r\n    \r\n    if ( index == 0 )\r\n    {\r\n        // if this is player one... don't apply the stats\r\n        pPlayerProfileManager->LoadCASProfileInfo(p_customSkater, false);\r\n    }\r\n    else\r\n    {\r\n        // if this is any other skater, then apply the stats\r\n        pPlayerProfileManager->LoadCASProfileInfo(p_customSkater, true);\r\n    }\r\n    \r\n}\r\n\r\nuint32 s_apply_flags=0;\r\nbool s_did_apply_custom_skater_info=false;\r\nstatic void s_read_game_save_info(uint32 fileType, CStruct *p_struct, CScript *p_script)\r\n{\r\n\tDbg_MsgAssert(p_struct,(\"NULL p_struct\"));\r\n\tDbg_MsgAssert(p_script,(\"NULL p_script\"));\r\n\t\r\n\ts_did_apply_custom_skater_info=false;\r\n\t\r\n\tswitch (fileType)\r\n\t{\r\n\t\tcase 0xb010f357: // OptionsAndPros\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(s_apply_flags,(\"s_apply_flags is zero, need to call SetSectionsToApplyWhenLoading\"));\r\n\r\n            if (s_apply_flags & (1<<APPLY_GLOBAL_INFO))\r\n\t\t\t{\r\n                printf(\"APPLY_GLOBAL_INFO\\n\");\r\n                Script::CStruct *p_global_info=NULL;\r\n\t\t\t\tp_struct->GetStructure(CRCD(0xf55cbd13,\"GlobalInfo\"),&p_global_info,Script::ASSERT);\r\n\t\t\t\ts_read_global_info(p_global_info, p_script);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (s_apply_flags & (1<<APPLY_STORY))\r\n\t\t\t{\r\n\t\t\t\t// Must do this before the story skater is loaded\r\n                // so that the proper difficulty is set\r\n                // when the stat goals get loaded\r\n                printf(\"APPLY_STORY\\n\");\r\n                Script::CStruct *p_story_info=NULL;\r\n\t\t\t\tp_struct->GetStructure(CRCD(0x14a9fbc7,\"Story\"),&p_story_info,Script::ASSERT);\r\n\t\t\t\ts_read_story_info(p_story_info);\r\n\t\t\t}\r\n\t\t\t\r\n            if (s_apply_flags & (1<<APPLY_CUSTOM_SKATER))\r\n\t\t\t{\r\n\t\t\t\tprintf(\"APPLY_CUSTOM_SKATER\\n\");\r\n                Script::CStruct *p_custom_skater_info=NULL;\r\n\t\t\t\tp_struct->GetStructure(CRCD(0x12bfac82,\"CustomSkater\"),&p_custom_skater_info,Script::ASSERT);\r\n\t\t\t\ts_read_custom_skater_info(p_custom_skater_info);\r\n\t\t\t\ts_did_apply_custom_skater_info=true;\r\n\t\t\t}\r\n\r\n\t\t\tif (s_apply_flags & (1<<APPLY_STORY_SKATER))\r\n\t\t\t{\r\n\t\t\t\tprintf(\"APPLY_STORY_SKATER\\n\");\r\n                Script::CStruct *p_story_skater_info=NULL;\r\n\t\t\t\tp_struct->GetStructure(CRCD(0xdf2f448,\"StorySkater\"),&p_story_skater_info,Script::ASSERT);\r\n                Script::CStruct *p_custom_skater_info=NULL;\r\n\t\t\t\tp_struct->GetStructure(CRCD(0x12bfac82,\"CustomSkater\"),&p_custom_skater_info,Script::ASSERT);\r\n\t\t\t\ts_read_story_skater_info(p_story_skater_info,p_custom_skater_info);\r\n\t\t\t}\r\n\t\t\t\r\n            // Reset the flags to that the above assert will catch cases where the scripts \r\n\t\t\t// have not called SetSectionsToApplyWhenLoading\t\r\n\t\t\ts_apply_flags=0;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0xca41692d: // NetworkSettings\t\t\r\n\t\t{\r\n\t\t\t// Extract the network preferences\r\n\t\t\tGameNet::Manager * pGamenet = GameNet::Manager::Instance();\r\n\t\t\tPrefs::Preferences *pPreferences=pGamenet->GetNetworkPreferences();\r\n\t\t\tDbg_MsgAssert(pPreferences,(\"NULL network pPreferences\"));\r\n\t\t\tpPreferences->SetRoot(p_struct);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0xffc529f4: // Cas\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"CAS mem card files are no longer supported! Use OptionsAndPros file type instead\"));\r\n\t\t\t/*\r\n\t\t\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\t\t\tObj::CPlayerProfileManager*\tpPlayerProfileManager=pSkate->GetPlayerProfileManager();\r\n\t\t\t//Script::PrintContents( p_struct );\r\n\t\t\tpPlayerProfileManager->LoadCASProfileInfo(p_struct);\r\n\r\n            // Which skater are we loading?\r\n            int index = pPlayerProfileManager->GetCurrentProfileIndex();\r\n\r\n            Obj::CSkater* pSkater = pSkate->GetSkater(index);\r\n            Dbg_Assert( pSkater );\r\n            pSkater->LoadCATInfo(p_struct);\r\n\t\t\t*/\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        case 0x61a1bc57: // Cat\r\n\t\t{\r\n\t\t\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\r\n            Script::CStruct *p_other_params;\r\n            Script::CArray *p_rotation_info;\r\n            Script::CArray *p_animation_info;\r\n            \r\n            Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n            if ( pSkater )\r\n            {\r\n                //Params\r\n                p_struct->GetStructure( \"other_params\", &p_other_params, Script::ASSERT );\r\n                //pSkater->m_created_trick[0]->mp_other_params = p_other_params;\r\n                pSkater->m_created_trick[0]->mp_other_params->AppendStructure( p_other_params );\r\n                \r\n                //Rotations\r\n                p_struct->GetArray( \"rotation_info\", &p_rotation_info, Script::ASSERT );\r\n                Script::CopyArray( pSkater->m_created_trick[0]->mp_rotations, p_rotation_info );\r\n                \r\n                //Animations\r\n                p_struct->GetArray( \"animation_info\", &p_animation_info, Script::ASSERT );\r\n                Script::CopyArray( pSkater->m_created_trick[0]->mp_animations, p_animation_info );\r\n            }\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x3bf882cc: // Park  (read save game info)\r\n\t\t{\r\n\t\t\tEd::CParkManager::Instance()->ReadFromStructure(p_struct);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x26c80b0d: // Replay\r\n\t\t{\r\n#if __USE_REPLAYS__\r\n\t\t\tuint32 level_structure_name=0;\r\n\t\t\tp_struct->GetChecksum(\"level_structure_name\",&level_structure_name);\r\n\t\t\tReplay::SetLevelStructureName(level_structure_name);\r\n\t\t\t\r\n\t\t\t// Look up the load_script in the level structure, and return it to the calling\r\n\t\t\t// script so that after calling LoadFromMemoryCard the script can call the load_script,\r\n\t\t\t// which will load the appropriate level.\r\n\t\t\tCStruct *p_level_structure=GetStructure(level_structure_name);\r\n\t\t\tDbg_MsgAssert(p_level_structure,(\"Could not find level structure '%s'\",FindChecksumName(level_structure_name)));\r\n\t\t\t\r\n\t\t\tuint32 load_script=0;\r\n\t\t\tp_level_structure->GetChecksum(\"load_script\",&load_script);\r\n\t\t\tp_script->GetParams()->AddChecksum(\"load_script\",load_script);\r\n#endif\t\t\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0x62896edf: // CreatedGoals\r\n\t\t{\r\n\t\t\tObj::CCompositeObject *p_obj=(Obj::CCompositeObject*)Obj::CTracker::Instance()->GetObject(CRCD(0x81f01058,\"GoalEditor\"));\r\n\t\t\tDbg_MsgAssert(p_obj,(\"No GoalEditor object\"));\r\n\t\t\tObj::CGoalEditorComponent *p_goal_editor=GetGoalEditorComponentFromObject(p_obj);\r\n\t\t\tDbg_MsgAssert(p_goal_editor,(\"No goal editor component ???\"));\r\n\t\t\t\r\n\t\t\tp_goal_editor->ReadFromStructure(p_struct);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"Bad type of '%s' sent to s_read_game_save_info\",FindChecksumName(fileType)));\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic int s_get_icon_k_required(uint32 fileType)\r\n{\r\n\tswitch (fileType)\r\n\t{\r\n\t\tcase 0xb010f357: // OptionsAndPros\r\n\t\t\treturn Script::GetInteger(CRCD(0x4925ed9e,\"OptionsProsIconSpaceRequired\"));\r\n\t\t\tbreak;\r\n\t\tcase 0xca41692d: // NetworkSettings\r\n\t\t\treturn Script::GetInteger(CRCD(0xf3431f63,\"NetworkSettingsIconSpaceRequired\"));\r\n\t\t\tbreak;\r\n\t\tcase 0xffc529f4: // Cas\r\n\t\t\tDbg_MsgAssert(0,(\"CAS mem card files are no longer supported! Use OptionsAndPros file type instead\"));\t\t\r\n\t\t\t//return Script::GetInteger(\"CASIconSpaceRequired\");\r\n\t\t\tbreak;\r\n        case 0x61a1bc57: // Cat\r\n\t\t\treturn Script::GetInteger(CRCD(0x46b0ef40,\"CATIconSpaceRequired\"));\r\n\t\t\tbreak;\r\n\t\tcase 0x3bf882cc: // Park\r\n\t\t\treturn Script::GetInteger(CRCD(0x82aaf8dc,\"ParkIconSpaceRequired\"));\r\n\t\t\tbreak;\r\n\t\tcase 0x26c80b0d: // Replay\r\n\t\t\treturn Script::GetInteger(CRCD(0x7eaf934f,\"ReplayIconSpaceRequired\"));\r\n\t\t\tbreak;\r\n\t\tcase 0x62896edf: // CreatedGoals\r\n\t\t\treturn Script::GetInteger(CRCD(0x3205bc07,\"CreatedGoalsIconSpaceRequired\"));\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Bad fileType of '%s' sent to s_get_icon_k_required\",FindChecksumName(fileType)));\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic int s_calculate_total_space_used_on_card(uint32 fileType, int fileSize)\r\n{\r\n\tint blocks=s_round_up_to_platforms_block_size(fileSize)/s_get_platforms_block_size();\r\n\r\n\tswitch (Config::GetHardware())\r\n\t{\r\n\tcase Config::HARDWARE_PS2:\r\n\tcase Config::HARDWARE_PS2_PROVIEW:\r\n\tcase Config::HARDWARE_PS2_DEVSYSTEM:\r\n\t{\r\n\t\t// Add in the icon space required\r\n\t\tblocks+=s_get_icon_k_required(fileType);\r\n\t\t\r\n\t\t// Then add in the space used up by the mem card file system.\r\n\t\tblocks+=4;\r\n\t\tbreak;\r\n\t}\r\n\t\t\t\r\n\tcase Config::HARDWARE_XBOX:\r\n\t{\r\n\t\t// Add in the icon space required\r\n\t\tblocks+=3;\r\n\t\tbreak;\r\n\t}\r\n\t\t\t\r\n\tcase Config::HARDWARE_NGC:\r\n\t\t// All done, I think.\r\n\t\tbreak;\r\n\t\t\t\t\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\t\t\r\n\t\r\n\treturn blocks;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// This returns the block size for mem card files.\r\n// On some platforms, using a library function to get the file size will not\r\n// return the original file size, but will return the size rounded up to the next\r\n// multiple of the block size.\r\n// In order that the calculated checksum be the same on loading, the files are always\r\n// padded with zeros to be a multiple of the block size before the checksum is calculated.\r\nstatic int s_get_platforms_block_size()\r\n{\r\n\tswitch (Config::GetHardware())\r\n\t{\r\n\t\tcase Config::HARDWARE_PS2:\r\n\t\tcase Config::HARDWARE_PS2_PROVIEW:\r\n\t\tcase Config::HARDWARE_PS2_DEVSYSTEM:\r\n\t\t\treturn 1024;\r\n\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\tcase Config::HARDWARE_NGC:\r\n\t\t\treturn 8192;\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase Config::HARDWARE_XBOX:\r\n\t\t\treturn 16384;\r\n\t\t\tbreak;\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\treturn 1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int s_round_up_to_platforms_block_size(int fileSize)\r\n{\r\n\tint block_size=s_get_platforms_block_size();\r\n\tif (fileSize%block_size)\r\n\t{\r\n\t\treturn (1+fileSize/block_size)*block_size;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn fileSize;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic int s_get_version_number(uint32 fileType)\r\n{\r\n\tswitch (fileType)\r\n\t{\r\n\t\tcase 0xb010f357: // OptionsAndPros\r\n\t\t\treturn Script::GetInt( \"VERSION_OPTIONSANDPROS\", Script::ASSERT );\r\n\t\t\tbreak;\r\n\t\tcase 0xffc529f4: // Cas\r\n\t\t\tDbg_MsgAssert(0,(\"CAS mem card files are no longer supported! Use OptionsAndPros file type instead\"));\r\n\t\t\t//return Script::GetInt( \"VERSION_CAS\", Script::ASSERT );\r\n\t\t\tbreak;\r\n        case 0x61a1bc57: // Cat\r\n\t\t\treturn Script::GetInt( \"VERSION_CAT\", Script::ASSERT );\r\n\t\t\tbreak;\r\n\t\tcase 0x3bf882cc: // Park\r\n\t\t\treturn Script::GetInt( \"VERSION_PARK\", Script::ASSERT );\r\n\t\t\tbreak;\r\n\t\tcase 0x26c80b0d: // Replay\r\n\t\t\treturn Script::GetInt( \"VERSION_REPLAY\", Script::ASSERT );\r\n\t\t\tbreak;\r\n\t\tcase 0xca41692d: // NetworkSettings\r\n\t\t\treturn Script::GetInt( \"VERSION_NETWORKSETTINGS\", Script::ASSERT );\r\n\t\t\tbreak;\r\n\t\tcase 0x62896edf: // CreatedGoals\r\n\t\t\treturn Script::GetInt( \"VERSION_CREATEDGOALS\", Script::ASSERT );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Bad fileType of '%s' sent to s_get_version_number\",FindChecksumName(fileType)));\r\n\t\t\tbreak;\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\nstatic const char *s_generate_xbox_directory_name(uint32 fileType, const char *p_name)\r\n{\r\n\tstatic char p_directory_name[100];\r\n\t\r\n\tswitch( fileType )\r\n\t{\r\n\t\tcase 0xca41692d: // NetworkSettings\r\n\t\t{\r\n\t\t\tsprintf( p_directory_name,\t\"%s-NetworkSettings\", p_name);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0xb010f357: // OptionsAndPros\r\n\t\t{\r\n\t\t\tsprintf( p_directory_name,\t\"%s-Story/Skater\", p_name );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0xffc529f4: // Cas\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"CAS mem card files are no longer supported! Use OptionsAndPros file type instead\"));\r\n\t\t\t//sprintf( p_directory_name,\t\"%s-Skater\", p_name );\r\n\t\t\tbreak;\r\n\t\t}\r\n        case 0x61a1bc57: // Cat\r\n\t\t{\r\n\t\t\tsprintf( p_directory_name,\t\"%s-Trick\", p_name );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0x3bf882cc: // Park\r\n\t\t{\r\n\t\t\tsprintf( p_directory_name,\t\"%s-Park\", p_name );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0x26c80b0d: // Replay\r\n\t\t{\r\n\t\t\tsprintf( p_directory_name,\t\"%s-Replay\", p_name );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 0x62896edf: // CreatedGoals\r\n\t\t{\r\n\t\t\tsprintf( p_directory_name,\t\"%s-Goals\", p_name );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Bad file type of '%s' for file '%s' sent to s_generate_xbox_directory_name\", FindChecksumName(fileType),p_name));\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t}\r\n\tDbg_MsgAssert( strlen( p_directory_name ) < 100, ( \"Oops\" ));\r\n\t\r\n\treturn p_directory_name;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// Returns false if error.\r\nstatic bool s_make_xbox_dir_and_icons(\tMc::Card *p_card,\r\n\t\t\t\t\t\t\t\t\t\tuint32 fileType, const char *p_name, \r\n\t\t\t\t\t\t\t\t\t\tchar *p_card_file_name,\r\n\t\t\t\t\t\t\t\t\t\tbool *p_insufficientSpace)\r\n{\r\n\tDbg_MsgAssert(p_card_file_name,(\"NULL p_card_file_name\"));\r\n\tp_card_file_name[0]=0;\r\n\t\r\n\t// Generate the directory name\r\n\tconst char *p_directory_name=s_generate_xbox_directory_name(fileType,p_name);\r\n\t\r\n\t// Create the directory\r\n\tif (!p_card->MakeDirectory(p_directory_name))\r\n\t{\r\n\t\tif (p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE)\r\n\t\t{\r\n\t\t\t*p_insufficientSpace=true;\r\n\t\t}\t\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\t// Calculate the low-level file name.\r\n\tconst char *p_low_level_directory_name=p_card->ConvertDirectory(p_directory_name);\r\n\tif (!p_low_level_directory_name)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\tsprintf( p_card_file_name, \"/%s/%s\", p_low_level_directory_name, p_low_level_directory_name );\r\n\tDbg_MsgAssert(strlen(p_card_file_name)<MAX_CARD_FILE_NAME_CHARS,(\"Oops\"));\r\n\r\n\t\r\n\t// Write out the icon file.\t\r\n\tchar\tpTitle[100];\r\n\tchar*\tpSourceIconFile\t\t= \"\";\r\n\tchar*\tpIcoName\t\t\t= \"\";\r\n\r\n\tswitch (fileType)\r\n\t{\r\n\t\tcase 0xb010f357: // OptionsAndPros\r\n\t\t{\r\n\t\t\tconst char *p_title=Script::GetString(CRCD(0x130ab28a,\"cfuncs_str_thugstoryskater\"));\r\n\t\t\tstrcpy(pTitle,p_title);\r\n\t\t\tstrcat(pTitle,p_name);\r\n\t\t\tpIcoName\t\t= \"saveimage.xbx\";\r\n\t\t\tpSourceIconFile\t= \"images\\\\miscellaneous\\\\xbox_icon_career.xbx\";\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0xca41692d: // NetworkSettings\r\n\t\t{\r\n\t\t\tconst char *p_title=Script::GetString(CRCD(0x92c497ae,\"cfuncs_str_thugnetsettings\"));\r\n\t\t\tstrcpy(pTitle,p_title);\r\n\t\t\tstrcat(pTitle,p_name);\r\n\t\t\tpIcoName\t\t= \"saveimage.xbx\";\r\n\t\t\t// Need new icon ...\r\n\t\t\tpSourceIconFile\t= \"images\\\\miscellaneous\\\\xbox_icon_career.xbx\";\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0x62896edf: // CreatedGoals\r\n\t\t{\r\n\t\t\tconst char *p_title=Script::GetString(CRCD(0x257678cb,\"cfuncs_str_thuggoals\"));\r\n\t\t\tstrcpy(pTitle,p_title);\r\n\t\t\tstrcat(pTitle,p_name);\r\n\t\t\tpIcoName\t\t= \"saveimage.xbx\";\r\n\t\t\t// Need new icon ...\r\n\t\t\tpSourceIconFile\t= \"images\\\\miscellaneous\\\\xbox_icon_goal.xbx\";\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0xffc529f4: // Cas\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"CAS mem card files are no longer supported! Use OptionsAndPros file type instead\"));\r\n\t\t\t/*\r\n\t\t\tsprintf(pTitle,\"THUG Skater:%s\",p_name);\r\n\t\t\tpIcoName\t\t= \"saveimage.xbx\";\r\n\t\t\tpSourceIconFile\t= \"images\\\\miscellaneous\\\\xbox_icon_skater.xbx\";\r\n\t\t\t*/\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        case 0x61a1bc57: // CAT\r\n\t\t{\r\n\t\t\tconst char *p_title=Script::GetString(CRCD(0x3aa2cffa,\"cfuncs_str_thugtrick\"));\r\n\t\t\tstrcpy(pTitle,p_title);\r\n\t\t\tstrcat(pTitle,p_name);\r\n\t\t\tpIcoName\t\t= \"saveimage.xbx\";\r\n\t\t\tpSourceIconFile\t= \"images\\\\miscellaneous\\\\xbox_icon_tricks.xbx\";\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x3bf882cc: // Park\r\n\t\t{\r\n\t\t\tconst char *p_title=Script::GetString(CRCD(0x2171fddc,\"cfuncs_str_thugpark\"));\r\n\t\t\tstrcpy(pTitle,p_title);\r\n\t\t\tstrcat(pTitle,p_name);\r\n\t\t\tpIcoName\t\t= \"saveimage.xbx\";\r\n\t\t\tpSourceIconFile\t= \"images\\\\miscellaneous\\\\xbox_icon_park.xbx\";\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x26c80b0d: // Replay\r\n\t\t{\r\n\t\t\t//sprintf(pTitle,\"THUG Replay:%s\",p_name);\r\n\t\t\t//pIcoName\t\t= \"saveimage.xbx\";\r\n\t\t\t//pSourceIconFile\t= \"images\\\\miscellaneous\\\\xbox_icon_replay.xbx\";\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Bad file type sent to s_make_xbox_dir_and_icons\" ));\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t}\r\n\r\n\t// Now load the .ico file into memory\r\n\tuint32\tFileSize\t= 0;\r\n\tchar*\tpIco\t\t= NULL;\r\n\r\n\tFile::StopStreaming();\r\n\t\t\r\n\t// Get the file interface.\r\n    void *pFP = File::Open(pSourceIconFile, \"rb\");\r\n    Dbg_MsgAssert(pFP,(\"No %s file found.\",pSourceIconFile));\r\n\t\r\n\tFileSize = File::GetFileSize( pFP );\r\n\r\n\t// Allocate a buffer to hold the file.\r\n\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().TopDownHeap());\r\n\r\n\t// Allocating the size rounded up to a multiple of 2048 in case file reading only reads a whole number of sectors.\r\n\tpIco = (char*)Mem::Malloc(( FileSize + 2047 ) & ~2047 );\r\n\tDbg_MsgAssert( pIco, ( \"Could not allocate memory for %s\", pSourceIconFile ));\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Read the file into the buffer and close the file.\r\n#ifdef __NOPT_ASSERT__\r\n\tlong BytesRead=\r\n#endif\t\r\n\tFile::Read( pIco, 1, FileSize, pFP );\r\n\tDbg_MsgAssert( (uint32)BytesRead <= FileSize, ( \"Bad rwfread when loading %s\", pSourceIconFile ));\r\n\tFile::Close( pFP );\r\n\r\n\tbool SavedOK = false;\r\n\tchar pFullIcoName[100];\r\n\tsprintf( pFullIcoName, \"\\\\%s\\\\%s\", p_low_level_directory_name, pIcoName );\r\n\tDbg_MsgAssert( strlen( pFullIcoName ) < 100,( \"Ooops\" ));\r\n\t\r\n\tMc::File* pFile = p_card->Open( pFullIcoName, Mc::File::mMODE_WRITE | Mc::File::mMODE_CREATE );\r\n\tif (p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE)\r\n\t{\r\n\t\t*p_insufficientSpace=true;\r\n\t}\t\r\n\t\r\n\tif( pFile )\r\n\t{   \r\n\t\tuint32 CardBytesWritten = pFile->Write( pIco, FileSize );\r\n\t\tif (p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE)\r\n\t\t{\r\n\t\t\t*p_insufficientSpace=true;\r\n\t\t}\t\r\n\t\t\r\n\t\tif( CardBytesWritten == FileSize )\r\n\t\t{\r\n\t\t\tSavedOK = true;\r\n\t\t}\r\n\t\tif( !pFile->Flush())\r\n\t\t{\r\n\t\t\tSavedOK = false;\r\n\t\t}\t\r\n\t\tif( !pFile->Close())\r\n\t\t{\r\n\t\t\tSavedOK = false;\r\n\t\t}\t\r\n\t\tdelete pFile;\r\n\t}\r\n\tMem::Free( pIco );\r\n\treturn SavedOK;\t\r\n}\r\n\r\nstatic void s_generate_card_directory_name(uint32 fileType, const char *p_name, char *p_card_directory_name)\r\n{\r\n\tDbg_MsgAssert(p_card_directory_name,(\"NULL p_card_directory_name\"));\r\n\t\r\n\tchar p_ascii_checksum[20];\r\n\ts_generate_ascii_checksum(p_ascii_checksum,p_name,fileType);\r\n\r\n\tconst char *p_header=Config::GetMemCardHeader();\r\n\tsprintf(p_card_directory_name,\"/%s%s\",p_header,p_ascii_checksum);\r\n\t\t\t\t\t\t\t\t\t\t\t\r\n\tDbg_MsgAssert(strlen(p_card_directory_name)<MAX_CARD_FILE_NAME_CHARS,(\"Oops\"));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#ifdef __PLAT_NGPS__ // Only compile on NGPS cos sceMcIconSys won't compile on other platforms.\r\nstatic bool s_make_ps2_dir_and_icons(\tMc::Card *p_card,\r\n\t\t\t\t\t\t\t\t\t\tuint32 fileType, const char *p_name, \r\n\t\t\t\t\t\t\t\t\t\tchar *p_card_file_name,\r\n\t\t\t\t\t\t\t\t\t\tbool *p_insufficientSpace)\r\n{\r\n\tchar p_directory_name[MAX_CARD_FILE_NAME_CHARS+1];\r\n\ts_generate_card_directory_name(fileType,p_name,p_directory_name);\r\n\t\r\n\tDbg_MsgAssert(p_card_file_name,(\"NULL p_card_file_name\"));\r\n\tsprintf(p_card_file_name,\"%s%s\",p_directory_name,p_directory_name);\r\n\tDbg_MsgAssert(strlen(p_card_file_name)<MAX_CARD_FILE_NAME_CHARS+1,(\"Oops\"));\r\n\t\r\n\t// Check whether the icon file exists\r\n\tchar p_icon_sys[MAX_CARD_FILE_NAME_CHARS+1];\r\n\t\r\n\tsprintf(p_icon_sys,\"%s/icon.sys\",p_directory_name);\r\n\tDbg_MsgAssert(strlen(p_icon_sys)<MAX_CARD_FILE_NAME_CHARS+1,(\"Oops\"));\r\n\t\r\n\tDbg_MsgAssert(p_card,(\"NULL p_card\"));\r\n\tMc::File* pFile=p_card->Open( p_icon_sys, Mc::File::mMODE_READ );\r\n\tif (pFile)\r\n\t{\r\n\t\t// Icon exists already, hence so must the directory, so no need to create it.\r\n\t\tpFile->Flush();\r\n\t\tpFile->Close();\r\n\t\tdelete pFile;\r\n\t\tpFile=NULL;\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\t// Icon does not exist hence the directory cannot either, \r\n\t// so create it and save out the icon.\r\n\tif (!p_card->MakeDirectory(p_directory_name))\r\n\t{\r\n\t\tif (p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE)\r\n\t\t{\r\n\t\t\t*p_insufficientSpace=true;\r\n\t\t}\t\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\t\r\n\tsceMcIconSys IconSys;\r\n\r\n\tsceVu0IVECTOR bgcolor[4] = \r\n\t{\r\n\t\t{ 0x80,    0,    0, 0 },\r\n\t\t{    0, 0x80,    0, 0 },\r\n\t\t{    0,    0, 0x80, 0 },\r\n\t\t{ 0x80, 0x80, 0x80, 0 },\r\n\t};\r\n\t\r\n\tsceVu0FVECTOR lightdir[3] = \r\n\t{\r\n\t\t{ 0.5, 0.0, 0.0, 0.0 },\r\n\t\t{ 0.0, 0.5, 0.0, 0.0 },\r\n\t\t{ 0.0, 0.0, 0.5, 0.0 },\r\n\t};\r\n\r\n\tsceVu0FVECTOR lightcol[3] = \r\n\t{\r\n\t\t{ 0.50, 0.50, 0.50, 0.00 },\r\n\t\t{ 0.25, 0.25, 0.40, 0.00 },\r\n\t\t{ 0.80, 0.80, 0.80, 0.00 },\t\t\r\n\t};\r\n\t\r\n\tsceVu0FVECTOR ambient = { 0.50, 0.50, 0.50, 0.00 };\r\n\t\r\n\tmemset(&IconSys, 0, sizeof(IconSys));\r\n\tstrcpy((char*)IconSys.Head, \"PS2D\");\r\n\t\r\n\t// Convert the title from ascii to shift-jis & write it in.\r\n\t//static char pTitle[100];\r\n\tchar pTitle[100];\r\n\t\r\n\tchar *pSourceIconFile=\"\";\r\n\tchar *pIcoName=\"\";\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint32 ExpectedIcoSize=0;\r\n\t#endif\r\n\r\n\tint LineBreak=16;\r\n\t\r\n\tswitch (fileType)\r\n\t{\r\n\t\tcase 0xb010f357: // OptionsAndPros\r\n\t\t{\r\n\t\t\tstrcpy(pTitle,Script::GetString(CRCD(0x130ab28a,\"cfuncs_str_thugstoryskater\")));\r\n\t\t\tLineBreak=strlen(pTitle);\r\n\t\t\tDbg_MsgAssert(LineBreak<=16,(\"Mem card title '%s' exceeds 16 chars\",pTitle));\r\n\t\t\tDbg_MsgAssert(pTitle[LineBreak-1]==':',(\"Expected mem card file name '%s' to end in ':'\",pTitle));\r\n\t\t\tstrcat(pTitle,p_name);\r\n\t\t\t\r\n\t\t\tpIcoName=\"thps5.ico\";\r\n\t\t\tpSourceIconFile=\"memcard\\\\thps3.icn\";\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tExpectedIcoSize=Script::GetInt(CRCD(0x4925ed9e,\"OptionsProsIconSpaceRequired\"));\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0xca41692d: // NetworkSettings\r\n\t\t{\r\n\t\t\tstrcpy(pTitle,Script::GetString(CRCD(0x92c497ae,\"cfuncs_str_thugnetsettings\")));\r\n\t\t\tLineBreak=strlen(pTitle);\r\n\t\t\tDbg_MsgAssert(LineBreak<=16,(\"Mem card title '%s' exceeds 16 chars\",pTitle));\r\n\t\t\tDbg_MsgAssert(pTitle[LineBreak-1]==':',(\"Expected mem card file name '%s' to end in ':'\",pTitle));\r\n\t\t\tstrcat(pTitle,p_name);\r\n\t\t\t\r\n\t\t\t// For the moment use the options/pros icon, until a new icon is made.\r\n\t\t\t// TODO: Once got a new icon file, remember to update ScriptDeleteMemCardFile too.\r\n\t\t\tpIcoName=\"network.ico\";\r\n\t\t\tpSourceIconFile=\"memcard\\\\network.icn\";\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tExpectedIcoSize=Script::GetInt(CRCD(0xf3431f63,\"NetworkSettingsIconSpaceRequired\"));\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0xffc529f4: // Cas\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"CAS mem card files are no longer supported! Use OptionsAndPros file type instead\"));\r\n\t\t\t/*\r\n\t\t\t#if ENGLISH\r\n\t\t\tsprintf(pTitle,\"THUG Skater:%s\",p_name);\r\n\t\t\t#else\r\n\t\t\tsprintf(pTitle,Script::GetLocalString(CRCD(0x7c2cfe2c,\"cfuncs_str_thps3skater\")),p_name);\r\n\t\t\t#endif\r\n\t\t\tLineBreak=12; // After 'THUG Skater:'\r\n\t\t\t\r\n\t\t\tpIcoName=\"cas.ico\";\r\n\t\t\tpSourceIconFile=\"memcard\\\\cas.icn\";\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tExpectedIcoSize=Script::GetInt(CRCD(0xa79ee524,\"CASIconSpaceRequired\"));\r\n\t\t\t#endif\r\n\t\t\t*/\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        case 0x61a1bc57: // Cat\r\n\t\t{\r\n\t\t\tstrcpy(pTitle,Script::GetString(CRCD(0x3aa2cffa,\"cfuncs_str_thugtrick\")));\r\n\t\t\tLineBreak=strlen(pTitle);\r\n\t\t\tDbg_MsgAssert(LineBreak<=16,(\"Mem card title '%s' exceeds 16 chars\",pTitle));\r\n\t\t\tDbg_MsgAssert(pTitle[LineBreak-1]==':',(\"Expected mem card file name '%s' to end in ':'\",pTitle));\r\n\t\t\tstrcat(pTitle,p_name);\r\n\t\t\t\r\n\t\t\tpIcoName=\"tricks.ico\";\r\n\t\t\tpSourceIconFile=\"memcard\\\\tricks.icn\";\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tExpectedIcoSize=Script::GetInt(CRCD(0x46b0ef40,\"CATIconSpaceRequired\"));\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x62896edf: // CreatedGoals\r\n\t\t{\r\n\t\t\tstrcpy(pTitle,Script::GetString(CRCD(0x257678cb,\"cfuncs_str_thuggoals\")));\r\n\t\t\tLineBreak=strlen(pTitle);\r\n\t\t\tDbg_MsgAssert(LineBreak<=16,(\"Mem card title '%s' exceeds 16 chars\",pTitle));\r\n\t\t\tDbg_MsgAssert(pTitle[LineBreak-1]==':',(\"Expected mem card file name '%s' to end in ':'\",pTitle));\r\n\t\t\tstrcat(pTitle,p_name);\r\n\t\t\t\r\n\t\t\tpIcoName=\"goals.ico\";\r\n\t\t\tpSourceIconFile=\"memcard\\\\goals.icn\";\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tExpectedIcoSize=Script::GetInt(CRCD(0x3205bc07,\"CreatedGoalsIconSpaceRequired\"));\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x3bf882cc: // Park\r\n\t\t{\r\n\t\t\tstrcpy(pTitle,Script::GetString(CRCD(0x2171fddc,\"cfuncs_str_thugpark\")));\r\n\t\t\tLineBreak=strlen(pTitle);\r\n\t\t\tDbg_MsgAssert(LineBreak<=16,(\"Mem card title '%s' exceeds 16 chars\",pTitle));\r\n\t\t\tDbg_MsgAssert(pTitle[LineBreak-1]==':',(\"Expected mem card file name '%s' to end in ':'\",pTitle));\r\n\t\t\tstrcat(pTitle,p_name);\r\n\t\t\t\r\n\t\t\tpIcoName=\"parked.ico\";\r\n\t\t\tpSourceIconFile=\"memcard\\\\parked.icn\";\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tExpectedIcoSize=Script::GetInt(CRCD(0x82aaf8dc,\"ParkIconSpaceRequired\"));\r\n\t\t\t#endif\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"Bad file type sent to s_create_mem_card_icon_file\"));\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t}\r\n\r\n\t// Convert the title to shift-jis and put it in IconSys.TitleName\r\n\tint Len=strlen(pTitle);\r\n\tDbg_MsgAssert(Len<=32,(\"Title too long !!!\"));\r\n\tpTitle[32]=0; // Just to be absolutely sure on non debug builds.\r\n\t\r\n\tchar *pTit=(char*)IconSys.TitleName;\r\n\tfor (int i=0; i<Len; ++i)\r\n\t{\r\n\t\tunsigned short Jis=s_ascii_to_sjis(pTitle[i]);\r\n\t\t*pTit++=(Jis>>8)&0xff;\r\n\t\t*pTit++=Jis&0xff;\r\n\t}\r\n\t*pTit++=0;\r\n\t*pTit=0;\r\n\r\n\t\r\n\tIconSys.OffsLF = 2*LineBreak;\r\n\tIconSys.TransRate = 0x60;\r\n\tmemcpy(IconSys.BgColor, bgcolor, sizeof(bgcolor));\r\n\tmemcpy(IconSys.LightDir, lightdir, sizeof(lightdir));\r\n\tmemcpy(IconSys.LightColor, lightcol, sizeof(lightcol));\r\n\tmemcpy(IconSys.Ambient, ambient, sizeof(ambient));\r\n\r\n\r\n\tstrcpy((char*)IconSys.FnameView, pIcoName);\r\n\tstrcpy((char*)IconSys.FnameCopy, pIcoName);\r\n\tstrcpy((char*)IconSys.FnameDel, pIcoName);\r\n\r\n\t\r\n\t// Now load the .ico file into memory\r\n\tuint32 FileSize=0;\r\n\tchar *pIco=NULL;\r\n\r\n\tFile::StopStreaming();\r\n\t\t\r\n    void *pFP = File::Open(pSourceIconFile, \"rb\");\r\n    Dbg_MsgAssert(pFP,(\"No %s file found.\",pSourceIconFile));\r\n\t\r\n    FileSize=File::GetFileSize(pFP);\r\n\t\r\n\t// Make sure the ico file size matches that specified in memcard.q.\r\n\t// The +1 is because the icon.sys takes up 1K.\r\n\tDbg_MsgAssert(1+(((FileSize+0x3ff)&(~0x3ff)) >> 10)==ExpectedIcoSize,(\"%s icon size mismatch\",Script::FindChecksumName(fileType)));\r\n\t\r\n\t// Allocate a buffer to hold the file.\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t// Allocating the size rounded up to a multiple of 2048 in case file reading only\r\n\t// reads a whole number of sectors.\r\n    pIco=(char*)Mem::Malloc((FileSize+2047)&~2047);\r\n    Dbg_MsgAssert(pIco,(\"Could not allocate memory for %s\",pSourceIconFile));\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\t// Read the file into the buffer and close the file.\r\n#ifdef __NOPT_ASSERT__\r\n\tlong BytesRead=\r\n#endif\t\r\n\tFile::Read(pIco,1,FileSize,pFP);\r\n\tDbg_MsgAssert(BytesRead<=FileSize,(\"Bad rwfread when loading %s\",pSourceIconFile));\r\n    File::Close(pFP);\r\n\t\r\n\t\r\n\tbool SavedOK=false;\r\n\r\n\tpFile=p_card->Open( p_icon_sys, Mc::File::mMODE_WRITE | Mc::File::mMODE_CREATE );\r\n\tif (p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE)\r\n\t{\r\n\t\t*p_insufficientSpace=true;\r\n\t}\t\r\n\t\r\n\tif (pFile)\r\n\t{   \r\n\t\t//printf(\"Writing %s, %d bytes\\n\",pIconSys,sizeof(IconSys));\r\n\t\tuint32 CardBytesWritten=pFile->Write( &IconSys, sizeof(IconSys) );\r\n\t\tif (p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE)\r\n\t\t{\r\n\t\t\t*p_insufficientSpace=true;\r\n\t\t}\t\r\n\t\t\r\n\t\tif (CardBytesWritten==sizeof(IconSys))\r\n\t\t{\r\n\t\t\tSavedOK=true;\r\n\t\t}\r\n\r\n\t\tif (!pFile->Flush())\r\n\t\t{\r\n\t\t\tSavedOK=false;\r\n\t\t}\t\r\n\t\tif (!pFile->Close())\r\n\t\t{\r\n\t\t\tSavedOK=false;\r\n\t\t}\t\r\n\t\t\t\t\r\n\t\tdelete pFile;\r\n\t}\r\n\r\n\t// Bail out straight away if the previous save failed so that the error code as\r\n\t// returned by Card::GetLastError is correct.\r\n\tif (!SavedOK)\r\n\t{\r\n\t\tMem::Free(pIco);\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\tSavedOK=false;\r\n\tchar pFullIcoName[MAX_CARD_FILE_NAME_CHARS+1];\r\n\tsprintf(pFullIcoName,\"%s/%s\",p_directory_name,pIcoName);\r\n\tDbg_MsgAssert(strlen(pFullIcoName)<MAX_CARD_FILE_NAME_CHARS,(\"Ooops\"));\r\n\t\r\n\tpFile=p_card->Open( pFullIcoName, Mc::File::mMODE_WRITE | Mc::File::mMODE_CREATE );\r\n\tif (p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE)\r\n\t{\r\n\t\t*p_insufficientSpace=true;\r\n\t}\t\r\n\t\r\n\tif (pFile)\r\n\t{   \r\n\t\t//printf(\"Writing %s, %d bytes\\n\",pFullIcoName,FileSize);\r\n\t\tuint32 CardBytesWritten=pFile->Write( pIco, FileSize );\r\n\t\tif (p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE)\r\n\t\t{\r\n\t\t\t*p_insufficientSpace=true;\r\n\t\t}\t\r\n\t\t\r\n\t\tif (CardBytesWritten==FileSize)\r\n\t\t{\r\n\t\t\tSavedOK=true;\r\n\t\t}\r\n\r\n\t\tif (!pFile->Flush())\r\n\t\t{\r\n\t\t\tSavedOK=false;\r\n\t\t}\t\r\n\t\tif (!pFile->Close())\r\n\t\t{\r\n\t\t\tSavedOK=false;\r\n\t\t}\t\r\n\t\t\t\t\r\n\t\tdelete pFile;\r\n\t}\r\n\t\r\n\tMem::Free(pIco);\r\n\treturn SavedOK;\r\n}\r\n#else\r\nstatic bool s_make_ps2_dir_and_icons(\tMc::Card *p_card,\r\n\t\t\t\t\t\t\t\t\t\tuint32 fileType, const char *p_name, \r\n\t\t\t\t\t\t\t\t\t\tchar *p_card_file_name,\r\n\t\t\t\t\t\t\t\t\t\tbool *p_insufficientSpace)\r\n{\r\n\treturn false;\r\n}\r\n#endif // #ifdef __PLAT_NGPS__\r\n\r\n#ifdef __PLAT_NGC__\r\nstatic bool s_insert_ngc_icon(\tSMcFileHeader *p_fileHeader, \r\n\t\t\t\t\t\t\t\tMc::Card *p_card,\r\n\t\t\t\t\t\t\t\tMc::File *p_file,\r\n\t\t\t\t\t\t\t\tuint32 fileType,\r\n\t\t\t\t\t\t\t\tconst char *p_name)\r\n{\r\n\r\n\tDbg_MsgAssert(p_fileHeader,(\"NULL p_fileHeader\"));\r\n\tDbg_MsgAssert(p_card,(\"NULL p_card\"));\r\n\tDbg_MsgAssert(p_file,(\"NULL p_file\"));\r\n\tDbg_MsgAssert(p_name,(\"NULL p_name\"));\r\n\t\r\n\tuint8 *p_buffer=p_fileHeader->mpIconData;\r\n\t\r\n\tchar* p_icon_name=\"icons\\\\CreateSk8r_Icon_01.img.ngc\";\r\n\r\n\tswitch( fileType )\r\n\t{\r\n\t\tcase 0xb010f357: // OptionsAndPros\r\n\t\tcase 0xca41692d: // NetworkSettings\t\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\tcase 0xffc529f4: // Cas\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"CAS mem card files are no longer supported! Use OptionsAndPros file type instead\"));\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n        case 0x61a1bc57: // CAT\r\n\t\t{\r\n\t\t\tp_icon_name = \"icons\\\\Trick_Icon_01.img.ngc\";\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 0x62896edf: // CreatedGoals\r\n\t\t{\r\n\t\t\tp_icon_name = \"icons\\\\Goal_Icon_01.img.ngc\";\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase 0x3bf882cc: // Park\r\n\t\t{\r\n\t\t\tp_icon_name = \"icons\\\\ParkEd_Icon_01.img.ngc\";\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Bad file type\" ));\r\n\t\t\tbreak;\r\n\t\t}\t\t\r\n\t}\r\n\t\r\n\t// We used to have each of the save types in the switch statement above choose a different\r\n\t// name, one which contained the save type, ie \"THUG: Skater\"\r\n\t// We then had to change them to all have the same name, namely \"Tony Hawk's Underground\"\r\n\t// This is because Nintendo required that we prefix all our save names with Tony Hawk's Underground, but\r\n\t// when we tried to append the save type as well the text was too long for the IPL screen.\r\n\tstrcpy((char*)p_buffer, Script::GetString(CRCD(0x6a6214bc,\"cfuncs_str_ngc_generic_save_name\")));\r\n\tDbg_MsgAssert(strlen((const char*)p_buffer) < 32,(\"p_buffer '%s' too long\",p_buffer));\r\n\tstrcpy((char*)p_buffer + 32, p_name );\r\n\r\n\t// Find the index of the number character that precedes the .\r\n\t// This used to be set a hard wired value for each of the cases above, but changed to\r\n\t// calculate it instead cos the icon file names could quite likely change.\r\n\tint name_index=0;\r\n\twhile (p_icon_name[name_index] && p_icon_name[name_index] != '.')\r\n\t{\r\n\t\t++name_index;\r\n\t}\r\n\tDbg_MsgAssert(p_icon_name[name_index],(\"No '.' found in icon name '%s'\",p_icon_name));\r\n\t--name_index;\r\n\t\t\r\n\r\n\tCARDStat stat;\r\n\tCARDGetStatus( p_card->GetSlot(), p_file->m_file_number, &stat );\r\n\r\n\t// Set up to write the banner and icon data.\r\n\tchar* next_pixel = (char*)p_buffer + 64;\r\n\r\n\t// Load the banner file.\r\n\tvoid *p_FH = File::Open( \"icons\\\\thps3_bannericon_01.img.ngc\", \"rb\" );\r\n\tDbg_MsgAssert( p_FH, ( \"Couldn't open texture file %s\\n\", \"icons\\\\thps3_bannericon_01.img.ngc\" ) );\r\n\r\n\tint dummy;\r\n\tint width;\r\n\tint height;\r\n\t// Read header info.\r\n\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// version\r\n\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// checksum\r\n\tFile::Read( &width, sizeof( int ), 1, p_FH );\r\n\tFile::Read( &height, sizeof( int ), 1, p_FH );\r\n\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// depth\r\n\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// levels\r\n\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// rwidth\r\n\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// rheight\r\n\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// has_holes/alphamap\r\n\r\n\tDbg_MsgAssert( width == 96, ( \"Bad mem card banner width\" ));\r\n\tDbg_MsgAssert( height == 32, ( \"Bad mem card banner height\" ));\r\n\r\n\t// Read image & palette data.\r\n\tFile::Read( next_pixel, 96 * 32, 1, p_FH );\r\n\tnext_pixel += ( 96 * 32 );\r\n\tFile::Read( next_pixel, 256 * 2, 1, p_FH );\r\n\tnext_pixel += ( 256 * 2 );\r\n\r\n\tFile::Close( p_FH );\r\n\r\n#\tif 0\r\n\t// Write out a dummy array representing the banner image.\r\n\tOSReport( \"unsigned short image[96*32] = {\\n\" );\r\n\tfor( int i = 0; i < 32; ++i )\r\n\t{\r\n\t\tfor( int j = 0; j < 96; ++j )\r\n\t\t{\r\n\t\t\tOSReport( \"0x%x,\", ((unsigned short*)p_texture->m_pPalette )[((unsigned char*)p_texture->m_pImage )[( i * 32 ) + j]] );\r\n\t\t}\r\n\t\tOSReport( \"\\n\" );\r\n\t}\r\n\tOSReport( \"};\\n\" );\r\n#\tendif\r\n\r\n\t// Load the icon files.\r\n\tfor( int i = 0; i < 7; ++i )\r\n\t{\r\n\t\tp_icon_name[name_index] = '1' + i;\r\n\r\n\t\t// Load the icon file.\r\n\t\tvoid *p_FH = File::Open( p_icon_name, \"rb\" );\r\n\t\tDbg_MsgAssert( p_FH, ( \"Couldn't open icon file %s\\n\", p_icon_name ) );\r\n\r\n\t\tint dummy;\r\n\t\tint width;\r\n\t\tint height;\r\n\t\t// Read header info.\r\n\t\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// version\r\n\t\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// checksum\r\n\t\tFile::Read( &width, sizeof( int ), 1, p_FH );\r\n\t\tFile::Read( &height, sizeof( int ), 1, p_FH );\r\n\t\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// depth\r\n\t\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// levels\r\n\t\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// rwidth\r\n\t\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// rheight\r\n\t\tFile::Read( &dummy, sizeof( int ), 1, p_FH );\t\t// has_holes/alphamap\r\n\r\n\t\tDbg_MsgAssert( width == 32, ( \"Bad mem card banner width\" ));\r\n\t\tDbg_MsgAssert( height == 32, ( \"Bad mem card banner height\" ));\r\n\r\n\t\t// Read image & palette data.\r\n\t\tFile::Read( next_pixel, 32 * 32, 1, p_FH );\r\n\t\tnext_pixel += ( 32 * 32 );\r\n\t\tif( i == 6 )\r\n\t\t{\r\n\t\t\tFile::Read( next_pixel, 256 * 2, 1, p_FH );\r\n\t\t\tnext_pixel += 256*2;\r\n\t\t}\r\n\r\n\t\tFile::Close( p_FH );\r\n\r\n\t\t// Icon formats.\r\n\t\tCARDSetIconFormat( &stat, i, CARD_STAT_ICON_C8 ); \r\n\r\n\t\t// Anim speeds.\r\n\t\tCARDSetIconSpeed( &stat, i, CARD_STAT_SPEED_MIDDLE ); \r\n\t}\r\n\r\n\tDbg_MsgAssert(next_pixel==(char*)p_buffer+NGC_MEMCARD_ICON_DATA_SIZE,(\"Incorrect NGC_MEMCARD_ICON_DATA_SIZE, too big by %d bytes\",NGC_MEMCARD_ICON_DATA_SIZE-(next_pixel-(char*)p_buffer)));\r\n\tstat.commentAddr\t= (uint32)p_fileHeader->mpIconData-(uint32)p_fileHeader;\r\n\tstat.iconAddr\t\t= stat.commentAddr + 64;\t// End of comment strings.\r\n\r\n\t// Banner format.\r\n\tCARDSetBannerFormat( &stat, CARD_STAT_BANNER_C8 ); \r\n\tCARDSetIconSpeed( &stat, 7, CARD_STAT_SPEED_END ); \r\n\tCARDSetIconAnim( &stat, CARD_STAT_ANIM_LOOP );\r\n\tCARDSetStatus( p_card->GetSlot(), p_file->m_file_number, &stat );\r\n\treturn true;\r\n}\r\n#else\r\nstatic bool s_insert_ngc_icon(\tSMcFileHeader *p_fileHeader, \r\n\t\t\t\t\t\t\t\tMc::Card *p_card,\r\n\t\t\t\t\t\t\t\tMc::File *p_file,\r\n\t\t\t\t\t\t\t\tuint32 fileType,\r\n\t\t\t\t\t\t\t\tconst char *p_name)\r\n{\r\n\treturn false;\r\n}\r\n#endif // #ifdef __PLAT_NGC__\r\n\r\nstatic bool s_first_date_is_more_recent(Script::CStruct *p_a, Script::CStruct *p_b)\r\n{\r\n\tint year_a=0;\r\n\tint month_a=0;\r\n\tint day_a=0;\r\n\tint hour_a=0;\r\n\tint minutes_a=0;\r\n\tint seconds_a=0;\r\n\t\r\n\tDbg_MsgAssert(p_a,(\"NULL p_a\"));\r\n\tp_a->GetInteger(CRCD(0x447d8cc8,\"Year\"),&year_a);\r\n\tp_a->GetInteger(CRCD(0x7149eff9,\"Month\"),&month_a);\r\n\tp_a->GetInteger(CRCD(0x1a5fd66f,\"Day\"),&day_a);\r\n\tp_a->GetInteger(CRCD(0x8fe1eeb1,\"Hour\"),&hour_a);\r\n\tp_a->GetInteger(CRCD(0x5f94b55c,\"Minutes\"),&minutes_a);\r\n\tp_a->GetInteger(CRCD(0xd029f619,\"Seconds\"),&seconds_a);\r\n\r\n\tint year_b=0;\r\n\tint month_b=0;\r\n\tint day_b=0;\r\n\tint hour_b=0;\r\n\tint minutes_b=0;\r\n\tint seconds_b=0;\r\n\t\r\n\tDbg_MsgAssert(p_b,(\"NULL p_b\"));\r\n\tp_b->GetInteger(CRCD(0x447d8cc8,\"Year\"),&year_b);\r\n\tp_b->GetInteger(CRCD(0x7149eff9,\"Month\"),&month_b);\r\n\tp_b->GetInteger(CRCD(0x1a5fd66f,\"Day\"),&day_b);\r\n\tp_b->GetInteger(CRCD(0x8fe1eeb1,\"Hour\"),&hour_b);\r\n\tp_b->GetInteger(CRCD(0x5f94b55c,\"Minutes\"),&minutes_b);\r\n\tp_b->GetInteger(CRCD(0xd029f619,\"Seconds\"),&seconds_b);\r\n\r\n\tbool more_recent=false;\r\n\t\r\n\tif (year_a < year_b)\r\n\t{\r\n\t}\r\n\telse if (year_a > year_b)\r\n\t{\r\n\t\tmore_recent=true;\r\n\t}\r\n\telse if (month_a < month_b)\r\n\t{\r\n\t}\r\n\telse if (month_a > month_b)\r\n\t{\r\n\t\tmore_recent=true;\r\n\t}\r\n\telse if (day_a < day_b)\r\n\t{\r\n\t}\r\n\telse if (day_a > day_b)\r\n\t{\r\n\t\tmore_recent=true;\r\n\t}\r\n\telse if (hour_a < hour_b)\r\n\t{\r\n\t}\r\n\telse if (hour_a > hour_b)\r\n\t{\r\n\t\tmore_recent=true;\r\n\t}\r\n\telse if (minutes_a < minutes_b)\r\n\t{\r\n\t}\r\n\telse if (minutes_a > minutes_b)\r\n\t{\r\n\t\tmore_recent=true;\r\n\t}\r\n\telse if (seconds_a < seconds_b)\r\n\t{\r\n\t}\r\n\telse if (seconds_a > seconds_b)\r\n\t{\r\n\t\tmore_recent=true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Exactly the same date/time, so call it more recent.\r\n\t\tmore_recent=true;\r\n\t}\r\n\t\r\n\treturn more_recent;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\r\n// @script | GetMostRecentSave | Finds the most recent save of the given type in the passed\r\n// directory listing. Puts the result into a structure called MostRecentSave. Any existing\r\n// parameter called MostRecentSave will be removed first. If there are no files, no MostRecentSave\r\n// parameter will be created.\r\n// @uparmopt [] | The directory listing. Must be an array of structures.\r\n// @uparmopt name | The save type. If omitted it will return the most recent save of any type.\r\nbool ScriptGetMostRecentSave(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->RemoveComponent(\"MostRecentSave\");\r\n\t\r\n\tCArray *p_array=NULL;\r\n\tpParams->GetArray(NONAME,&p_array);\r\n\t\r\n\tif (!p_array)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\tuint32 file_type=0;\r\n\tpParams->GetChecksum(NONAME,&file_type);\r\n\r\n\tCStruct *p_most_recent=NULL;\r\n\tfor (uint32 i=0; i<p_array->GetSize(); ++i)\r\n\t{\r\n\t\tCStruct *p_struct=p_array->GetStructure(i);\r\n\t\t\r\n\t\tuint32 this_file_type=0;\r\n\t\tp_struct->GetChecksum(\"file_type\",&this_file_type);\r\n\t\t\r\n\t\tif (file_type && file_type!=this_file_type)\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tif (p_struct->ContainsFlag(\"BadVersion\") ||\r\n\t\t\tp_struct->ContainsFlag(\"Corrupt\"))\r\n\t\t{\r\n\t\t\tif (Config::GetHardware() == Config::HARDWARE_XBOX ||\r\n\t\t\t\tConfig::GetHardware() == Config::HARDWARE_NGC)\r\n\t\t\t{\r\n\t\t\t\t// For the XBox, do not ignore bad files, so that an error message will appear on bootup\r\n\t\t\t\t// if the most recent save is bad. (TT6236)\r\n\t\t\t\t// Same for NGC (TT13519)\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// For other platforms, find the most recent good save.\r\n\t\t\t\tcontinue;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\t\t\r\n\t\tif (p_most_recent)\r\n\t\t{\r\n\t\t\tif (s_first_date_is_more_recent(p_struct, p_most_recent))\r\n\t\t\t{\r\n\t\t\t\tp_most_recent=p_struct;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_most_recent=p_struct;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\tif (p_most_recent)\r\n\t{\r\n\t\tpScript->GetParams()->AddStructure(\"MostRecentSave\",p_most_recent);\r\n        return true;\r\n\t}\r\n\t\r\n\treturn false;\t\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\r\n// @script | GetMemCardSpaceAvailable | Puts the amount of space left on the mem card\r\n// into the parameter SpaceAvailable. Units are K for the PS2\r\nbool ScriptGetMemCardSpaceAvailable(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->AddInteger(CRCD(0xc37c363,\"SpaceAvailable\"),0);\r\n\tpScript->GetParams()->AddInteger(CRCD(0x855b2fc,\"FilesLeft\"),1000000);\r\n\r\n\tMc::Manager * mc_man = Mc::Manager::Instance();\r\n\tMc::Card* p_card=mc_man->GetCard(0,0);\r\n\tif (p_card)\r\n\t{\r\n\t\tpScript->GetParams()->AddInteger(CRCD(0xc37c363,\"SpaceAvailable\"),p_card->GetNumFreeClusters());\r\n\t\t#ifdef __PLAT_NGC__\r\n\t\tpScript->GetParams()->AddInteger(CRCD(0x855b2fc,\"FilesLeft\"),p_card->CountFilesLeft());\r\n\t\t#endif\r\n\t\t\t\r\n\t\treturn true;\r\n\t}\t\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetMemCardSpaceRequired | Calculates the amount of space required to save the specified\r\n// file type to the memory card, and puts it into the parameter SpaceRequired.\r\n// Units are K for the PS2.\r\n// @uparm name | The save type.\r\nbool ScriptGetMemCardSpaceRequired(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 file_type=0;\r\n\tpParams->GetChecksum(NONAME,&file_type);\r\n\t\r\n\t// s_calculate_total_space_used_on_card adds in the space used by the icons.\r\n\tint space_required=s_calculate_total_space_used_on_card(file_type,sGetFixedFileSize(file_type));\r\n\r\n\tpScript->GetParams()->AddInteger(\"SpaceRequired\",space_required);\r\n\treturn true;\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\r\n// @script | MemCardFileExists | returns true if the file already exists\r\n// on the card\r\n// @parm string | Name | the name of the file\r\n// @parm name | type | the type of the file\r\nbool ScriptMemCardFileExists(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMc::Manager * mc_man = Mc::Manager::Instance();\r\n\tMc::Card* p_card=mc_man->GetCard(0,0);\r\n\tif (!p_card)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\tconst char *p_name=NULL;\r\n\tpParams->GetText(\"Name\",&p_name);\r\n\t\r\n\tuint32 file_type=0;\r\n\tpParams->GetChecksum(\"Type\",&file_type);\r\n\r\n\tif (!p_name || !file_type)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\tchar p_card_file_name[MAX_CARD_FILE_NAME_CHARS+1];\r\n\tp_card_file_name[0]=0;\r\n\r\n\tconst char *p_xbox_directory_name=NULL;\r\n\tconst char *p_xbox_converted_directory_name=NULL;\r\n\t\r\n\tswitch (Config::GetHardware())\r\n\t{\r\n\t\tcase Config::HARDWARE_XBOX:\r\n\t\t{\r\n\t\t\tp_xbox_directory_name=s_generate_xbox_directory_name(file_type,p_name);\r\n\t\t\tp_xbox_converted_directory_name=p_card->ConvertDirectory(p_xbox_directory_name);\r\n\t\t\tif (!p_xbox_converted_directory_name)\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\t\r\n\t\t\tsprintf(p_card_file_name,\"/%s/%s\",p_xbox_converted_directory_name,p_xbox_converted_directory_name);\r\n\t\t\tDbg_MsgAssert(strlen(p_card_file_name)<MAX_CARD_FILE_NAME_CHARS,(\"Oops\"));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase Config::HARDWARE_PS2:\r\n\t\tcase Config::HARDWARE_PS2_PROVIEW:\r\n\t\tcase Config::HARDWARE_PS2_DEVSYSTEM:\r\n\t\tcase Config::HARDWARE_NGC:\r\n\t\t{\r\n\t\t\tconst char *p_header=Config::GetMemCardHeader();\r\n\t\t\tchar p_ascii_checksum[20];\r\n\t\t\ts_generate_ascii_checksum(p_ascii_checksum,p_name,file_type);\r\n\t\t\t\r\n\t\t\tsprintf(p_card_file_name,\"/%s%s/%s%s\",\tp_header,p_ascii_checksum,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tp_header,p_ascii_checksum);\r\n\t\t\tDbg_MsgAssert(strlen(p_card_file_name)<MAX_CARD_FILE_NAME_CHARS,(\"Oops\"));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\t\t\r\n\r\n\tMc::File* pFile = p_card->Open( p_card_file_name, Mc::File::mMODE_READ );\r\n\tif (pFile)\r\n\t{\r\n\t\tint file_size=pFile->Seek(0,Mc::File::BASE_END);\r\n\t\tint total_size_on_card=s_calculate_total_space_used_on_card(file_type,file_size);\r\n\t\tpScript->GetParams()->AddInteger(\"total_file_size\",total_size_on_card);\r\n\t\r\n\t\tpFile->Flush();\r\n\t\tpFile->Close();\r\n\t\tdelete pFile;\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tif (Config::GetHardware()==Config::HARDWARE_XBOX)\r\n\t{\r\n\t\t// Better delete the directory we just created ...\r\n\t\tDbg_MsgAssert(p_xbox_directory_name,(\"NULL p_xbox_directory_name ?\"));\r\n\t\tp_card->DeleteDirectory(p_xbox_directory_name);\r\n\t}\r\n\treturn false;\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\r\n// @script | DeleteMemCardFile | Deletes the specified file from the memory card\r\n// @parmopt string | CardFileName | | The name of the file as stored on the memory card. If this is\r\n// not specified then it is derived from UserFileName and Type\r\n// @parmopt string | UserFileName | | The name of the file as it appears in the files menu\r\n// @parm name | Type | The file type (NetworkSettings, OptionsAndPros, Cas, Park, Replay)\r\n\r\nbool ScriptDeleteMemCardFile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tif ( Config::GetHardware() != Config::HARDWARE_XBOX)\r\n\t{\r\n\t\tPcm::PauseMusic(true);\r\n\t\tPcm::PauseStream(true);\r\n\t}\r\n\t\r\n\tMc::Manager * mc_man = Mc::Manager::Instance();\r\n\tMc::Card* p_card=mc_man->GetCard(0,0);\r\n\tif (!p_card)\r\n\t{\r\n\t\tif ( Config::GetHardware() != Config::HARDWARE_XBOX)\r\n\t\t{\r\n\t\t\tPcm::PauseMusic( -1 );\r\n\t\t\tPcm::PauseStream( -1 );\r\n\t\t}\t\r\n\t\treturn false;\r\n\t}\r\n\t\t\r\n\tbool delete_succeeded=true;\r\n\t\r\n\tconst char *p_xbox_directory_name=NULL;\r\n\tpParams->GetString(\"XBoxDirectoryName\",&p_xbox_directory_name);\r\n\tconst char *p_full_file_name=NULL;\r\n\tpParams->GetString(\"CardFileName\",&p_full_file_name);\r\n\tuint32 file_type=0;\r\n\tpParams->GetChecksum(\"Type\",&file_type);\r\n\tconst char *p_name=\"\";\r\n\tpParams->GetString(\"UserFileName\",&p_name);\r\n\r\n\t\r\n\tswitch (Config::GetHardware())\r\n\t{\r\n\t\tcase Config::HARDWARE_NGC:\r\n\t\t{\r\n\t\t\tif (p_full_file_name)\r\n\t\t\t{\r\n\t\t\t\tif (!p_card->Delete(p_full_file_name))\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete_succeeded=false;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tchar p_temp[MAX_CARD_FILE_NAME_CHARS+1];\r\n\t\t\t\t\r\n\t\t\t\t// If p_full_file_name is not specified then derive it from Type and UserFileName\r\n\t\t\t\t\r\n\t\t\t\tconst char *p_header=Config::GetMemCardHeader();\r\n\t\t\t\tchar p_ascii_checksum[20];\r\n\t\t\t\ts_generate_ascii_checksum(p_ascii_checksum,p_name,file_type);\r\n\t\t\r\n\t\t\t\tsprintf(p_temp,\"%s%s%s%s\",p_header,p_ascii_checksum,\r\n\t\t\t\t\t\t\t\t\t      p_header,p_ascii_checksum);\r\n\t\t\t\tDbg_MsgAssert(strlen(p_temp)<MAX_CARD_FILE_NAME_CHARS,(\"Oops\"));\r\n\t\t\t\t\r\n\t\t\t\tif (!p_card->Delete(p_temp))\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete_succeeded=false;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase Config::HARDWARE_XBOX:\r\n\t\t{\r\n\t\t\tif (!p_xbox_directory_name)\r\n\t\t\t{\r\n\t\t\t\t// Derive p_xbox_directory_name from the file type and user file name\r\n\t\t\t\tp_xbox_directory_name=s_generate_xbox_directory_name(file_type,p_name);\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\tif (!p_card->DeleteDirectory( p_xbox_directory_name ))\r\n\t\t\t{\r\n\t\t\t\tdelete_succeeded=false;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\tcase Config::HARDWARE_PS2:\r\n\t\tcase Config::HARDWARE_PS2_PROVIEW:\r\n\t\tcase Config::HARDWARE_PS2_DEVSYSTEM:\r\n\t\t{\r\n\t\t\tchar p_temp[MAX_CARD_FILE_NAME_CHARS+1];\r\n\t\t\t\r\n\t\t\tif (!p_full_file_name)\r\n\t\t\t{\r\n\t\t\t\t// If p_full_file_name is not specified then derive it from Type and UserFileName\r\n\t\t\t\t\r\n\t\t\t\tconst char *p_header=Config::GetMemCardHeader();\r\n\t\t\t\tchar p_ascii_checksum[20];\r\n\t\t\t\ts_generate_ascii_checksum(p_ascii_checksum,p_name,file_type);\r\n\t\t\r\n\t\t\t\tsprintf(p_temp,\"/%s%s/%s%s\",p_header,p_ascii_checksum,\r\n\t\t\t\t\t\t\t\t\t\t\tp_header,p_ascii_checksum);\r\n\t\t\t\tDbg_MsgAssert(strlen(p_temp)<MAX_CARD_FILE_NAME_CHARS,(\"Oops\"));\r\n\t\t\t\t\r\n\t\t\t\tp_full_file_name=p_temp;\r\n\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t   \r\n\t\t\tint len=strlen(p_full_file_name);\r\n\t\t\tuint32 file_type=s_determine_file_type(p_full_file_name[len-1]);\r\n\t\t\r\n\t\t\t// Generate the directory name.\r\n\t\t\tDbg_MsgAssert(len<100,(\"File name too long\"));\r\n\t\t\tchar p_directory_name[100];\r\n\t\t\tchar *p_dest=p_directory_name;\r\n\t\t\tconst char *p_source=p_full_file_name;\r\n\t\t\t// Copy the first '/'\r\n\t\t\t*p_dest++=*p_source++;\r\n\t\t\twhile (*p_source && *p_source!='/')\r\n\t\t\t{\r\n\t\t\t\t*p_dest++=*p_source++;\r\n\t\t\t}\r\n\t\t\t*p_dest=0;\r\n\t\t\r\n\t\t\t// Delete the file that has the same name as the directory\r\n\t\t\tif (!p_card->Delete(p_full_file_name))\r\n\t\t\t{\r\n\t\t\t\tdelete_succeeded=false;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\t// Delete the icon.sys file\r\n\t\t\tchar p_buf[100];\r\n\t\t\tsprintf(p_buf,\"%s/icon.sys\",p_directory_name);\r\n\t\t\tDbg_MsgAssert(strlen(p_buf)<100,(\"Oops\"));\r\n\t\t\tif (!p_card->Delete(p_buf))\r\n\t\t\t{\r\n\t\t\t\tdelete_succeeded=false;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\t// Delete the .ico file.\r\n\t\t\tswitch (file_type)\r\n\t\t\t{\r\n\t\t\t\tcase 0xffc529f4: // Cas\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"CAS mem card files are no longer supported! Use OptionsAndPros file type instead\"));\r\n\t\t\t\t\t//sprintf(p_buf,\"%s/cas.ico\",p_directory_name);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n                case 0x61a1bc57: // CAT\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf(p_buf,\"%s/tricks.ico\",p_directory_name);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tcase 0x3bf882cc: // Park\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf(p_buf,\"%s/parked.ico\",p_directory_name);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tcase 0x26c80b0d: // Replay\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf(p_buf,\"%s/replay.ico\",p_directory_name);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tcase 0xb010f357: // OptionsAndPros\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf(p_buf,\"%s/thps5.ico\",p_directory_name);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tcase 0x62896edf: // CreatedGoals\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf(p_buf,\"%s/goals.ico\",p_directory_name);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcase 0xca41692d: // NetworkSettings\r\n\t\t\t\t{\r\n\t\t\t\t\t// TODO: Change this once got a new icon file for the net settings\r\n\t\t\t\t\tsprintf(p_buf,\"%s/network.ico\",p_directory_name);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tdefault:\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"Bad file type sent to DeleteMemCardFile\"));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\t\r\n\t\t\t}\r\n\t\t\tDbg_MsgAssert(strlen(p_buf)<100,(\"Oops\"));\r\n\t\t\tif (!p_card->Delete(p_buf))\r\n\t\t\t{\r\n\t\t\t\tdelete_succeeded=false;\r\n\t\t\t}\t\r\n\t\r\n\t\t\t// Delete the directory\r\n\t\t\tif (!p_card->DeleteDirectory(p_directory_name))\r\n\t\t\t{\r\n\t\t\t\tdelete_succeeded=false;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tdelete_succeeded=false;\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t}\r\n\t\t\r\n\tif ( Config::GetHardware() != Config::HARDWARE_XBOX)\r\n\t{\r\n\t\tPcm::PauseMusic( -1 );\r\n\t\tPcm::PauseStream( -1 );\r\n\t}\r\n\t\r\n\treturn delete_succeeded;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | FormatCard | Formats the memory card\r\nbool ScriptFormatCard(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tPcm::PauseMusic(true);\r\n\tPcm::PauseStream(true);\r\n\t\r\n\tMc::Manager * mc_man = Mc::Manager::Instance();\r\n\tMc::Card* p_card=mc_man->GetCard(0,0);\r\n\tbool Worked=false;\r\n\tif (p_card)\r\n\t{\r\n\t\tWorked=p_card->Format();\r\n\t}\r\n\r\n\tPcm::PauseMusic( -1 );\r\n\tPcm::PauseStream( -1 );\r\n\treturn Worked;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CardIsInSlot | returns true if the memory card is in the slot\r\nbool ScriptCardIsInSlot(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tMc::Manager * mc_man = Mc::Manager::Instance();\r\n\tMc::Card* p_card=mc_man->GetCard(0,0);\r\n\tif (p_card)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t#ifdef __PLAT_NGC__\r\n\t\t// On the NGC, p_card will also be NULL if the card is in the slot, but is broken.\r\n\t\tif (mc_man->GotFatalError())\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t\t\r\n\t\t// On the NGC, p_card will also be NULL if something is in the slot,\r\n\t\t// but gives a 'wrong device' error\r\n\t\tif (mc_man->GotWrongDevice())\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t\t#endif\r\n\t\treturn false;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CardIsFormatted | returns true if the memory card is formatted\r\nbool ScriptCardIsFormatted(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tMc::Manager * mc_man = Mc::Manager::Instance();\r\n\tMc::Card* p_card=mc_man->GetCard(0,0);\r\n\tif (p_card)\r\n\t{\r\n\t\treturn p_card->IsFormatted();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// If there is no card, then I guess it isn't formatted.\r\n\t\treturn false;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SaveFailedDueToInsufficientSpace | \r\nbool ScriptSaveFailedDueToInsufficientSpace(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn s_insufficient_space;\r\n}\r\n\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetSummaryInfo\t| \r\nbool ScriptGetSummaryInfo(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 file_type=0;\r\n\tpParams->GetChecksum(NONAME,&file_type);\r\n\t\r\n\tint use_vault_data=0;\r\n\tpParams->GetInteger(CRCD(0xc78dabf6,\"VaultData\"),&use_vault_data);\r\n\t\r\n\tif (use_vault_data)\r\n\t{\r\n\t\tfile_type=sVaultDataType;\r\n\t\tDbg_MsgAssert(spVaultData,(\"Called GetSummaryInfo on the vault data when there was no vault data\"));\r\n\t\ts_generate_summary_info(pScript->GetParams(), file_type, spVaultData);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (file_type==0xb010f357) // OptionsAndPros\r\n\t\t{\r\n\t\t\t// Force the goal manager to refresh the goal manager params structure.\r\n\t\t\t// Note that this cannot be done inside s_generate_summary_info, because LevelUnload()\r\n\t\t\t// will create a structure and store a pointer to it.\r\n\t\t\t// In other places SSwitchToNextPool() will be called before calling s_generate_summary_info,\r\n\t\t\t// and we don't want the structure created by LevelUnload() to come off the special memcard pool.\r\n\t\t\tGame::CGoalManager* p_goal_manager=Game::GetGoalManager();\r\n\t\t\tDbg_MsgAssert(p_goal_manager,(\"NULL p_goal_manager\"));\r\n\t\t\tp_goal_manager->LevelUnload();\r\n\t\t}\r\n\t\t\r\n\t\ts_generate_summary_info(pScript->GetParams(), file_type, NULL);\r\n\t}\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\n#if __USE_REPLAYS__\r\nstatic int sGetReplayDataSize(int num_dummies)\r\n{\r\n\treturn \tsizeof(Replay::SReplayDataHeader)+\r\n\t\t\tnum_dummies*sizeof(Replay::SSavedDummy)+\r\n\t\t\tReplay::GetBufferSize()+\r\n\t\t\t4; // The checksum of that lot\r\n}\t\t\t\r\n#endif\r\n\r\nstatic uint32 sGetFixedFileSize(uint32 fileType)\r\n{\r\n\tuint32 fixed_size=0;\r\n\t\r\n\tswitch (fileType)\r\n\t{\r\n\t\tcase 0xb010f357: // OptionsAndPros\r\n\t\t\tfixed_size=Script::GetInteger(CRCD(0xe7f51ffe,\"SaveSize_OptionsAndPros\"),Script::ASSERT);\r\n\t\t\tbreak;\r\n\t\tcase 0xffc529f4: // Cas\r\n\t\t\tDbg_MsgAssert(0,(\"CAS mem card files are no longer supported! Use OptionsAndPros file type instead\"));\r\n\t\t\t//fixed_size=Script::GetInteger(\"SaveSize_Cas\",Script::ASSERT);\r\n\t\t\tbreak;\r\n        case 0x61a1bc57: // Cat\r\n\t\t\tfixed_size=Script::GetInteger(CRCD(0x9eecdec9,\"SaveSize_Cat\"),Script::ASSERT);\r\n\t\t\tbreak;\r\n\t\tcase 0x62896edf: // CreatedGoals\r\n\t\t\tfixed_size=Script::GetInteger(CRCD(0x3308efc0,\"SaveSize_CreatedGoals\"),Script::ASSERT);\r\n\t\t\tbreak;\r\n\t\tcase 0x3bf882cc: // Park\r\n\t\t\tfixed_size=Script::GetInteger(CRCD(0x2cb071ed,\"SaveSize_Park\"),Script::ASSERT);\r\n\t\t\tbreak;\r\n\t\tcase 0x26c80b0d: // Replay\r\n\t\t\tfixed_size=Script::GetInteger(CRCD(0x8ee3aa00,\"SaveSize_Replay\"),Script::ASSERT);\r\n\t\t\tbreak;\r\n\t\tcase 0xca41692d: // NetworkSettings\r\n\t\t\tfixed_size=Script::GetInteger(CRCD(0x651c978d,\"SaveSize_NetworkSettings\"),Script::ASSERT);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert(0,(\"Bad file_type of %s\",Script::FindChecksumName(fileType)));\r\n\t\t\tbreak;\r\n\t}\r\n\tfixed_size+=sizeof(SMcFileHeader);\r\n\tfixed_size=s_round_up_to_platforms_block_size(fixed_size);\r\n\treturn fixed_size;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SaveToMemoryCard | \r\nbool ScriptSaveToMemoryCard(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tif (Config::GetHardware() == Config::HARDWARE_NGC)\r\n\t{\r\n\t\t// On the GameCube, the temp mem card pools only exist for the duration of this function,\r\n\t\t// because they use space normally used for rendering, hence cannot exist during the mem card scripts\r\n\t\t// which may execute over many frames.\r\n\t\tScriptCreateTemporaryMemCardPools(NULL,NULL);\r\n\t}\r\n\t\t\r\n\tif ( Config::GetHardware() != Config::HARDWARE_XBOX)\r\n\t{\r\n\t\tPcm::PauseMusic(true);\r\n\t\tPcm::PauseStream(true);\r\n\t}\r\n\t\r\n\ts_insufficient_space=false;\r\n\t\r\n\tconst char *p_name=\"\";\r\n\tpParams->GetText(\"Name\",&p_name);\r\n\r\n\tuint32 file_type=0;\r\n\tpParams->GetChecksum(\"Type\",&file_type);\r\n\r\n\t// If the SaveVaultData flag is set, it will save the stored spVaultData, which\r\n\t// will have been loaded from the online vault.\r\n\tint save_vault_data=0;\r\n\tpParams->GetInteger(CRCD(0xbb609e73,\"SaveVaultData\"),&save_vault_data);\r\n\tif (save_vault_data)\r\n\t{\r\n\t\tDbg_MsgAssert(spVaultData,(\"Called SaveToMemoryCard with no vault data\"));\r\n\t\tfile_type=sVaultDataType;\r\n\t}\t\r\n\r\n\r\n\tif (!save_vault_data && file_type==0xb010f357) // OptionsAndPros\r\n\t{\r\n\t\t// Force the goal manager to refresh the goal manager params structure.\r\n\t\t// This has to be done before calling SSwitchToNextPool(), because LevelUnload()\r\n\t\t// will create a structure and store a pointer to it.\r\n\t\t// It is best for the special pools to be kept empty outside of GetMemCardSpaceRequired\r\n\t\t// or SaveToMemoryCard, otherwise saving the game could run out of pool space.\r\n\t\tGame::CGoalManager* p_goal_manager=Game::GetGoalManager();\r\n\t\tDbg_MsgAssert(p_goal_manager,(\"NULL p_goal_manager\"));\r\n\t\tp_goal_manager->LevelUnload();\r\n\t}\r\n\r\n\r\n\t// If the special pools exist, switch to them so that the components & structs etc get allocated off them.\r\n\t// The special pools use the space freed by unloading the skater anims, and are for preventing memory\r\n\t// overflows when the save size gets large.\r\n\tDbg_MsgAssert(CComponent::SGetCurrentPoolIndex()==0,(\"Bad current CComponent pool\"));\r\n\tDbg_MsgAssert(CStruct::SGetCurrentPoolIndex()==0,(\"Bad current CStruct pool\"));\r\n\tDbg_MsgAssert(CVector::SGetCurrentPoolIndex()==0,(\"Bad current CVector pool\"));\r\n\tbool got_special_pools=false;\r\n\tCComponent::SSwitchToNextPool();\r\n\tif (CComponent::SPoolExists())\r\n\t{\r\n\t\tCStruct::SSwitchToNextPool();\r\n\t\tDbg_MsgAssert(CStruct::SPoolExists(),(\"No special CStruct pool ?\"));\r\n\t\tCVector::SSwitchToNextPool();\r\n\t\tDbg_MsgAssert(CVector::SPoolExists(),(\"No special CVector pool ?\"));\r\n\t\t\r\n\t\tgot_special_pools=true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCComponent::SSwitchToPreviousPool();\r\n\t}\t\r\n\r\n\t\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tint initial_ccomponent_num_used_items=CComponent::SGetNumUsedItems();\r\n\tint initial_cstruct_num_used_items=CStruct::SGetNumUsedItems();\r\n\tint initial_cvector_num_used_items=CVector::SGetNumUsedItems();\r\n\t#endif\r\n\r\n\t// WARNING !\t\tWARNING !\t\tWARNING !\t\tWARNING !\t\tWARNING !\r\n\t// Between here and SSwitchToPreviousPool(), all CStruct's and CComponent's will be allocated\r\n\t// off a special pool.\r\n\t// This is to avoid overflowing the regular pools with these temporary big structures.\r\n\t// Make sure that no function, or function that it calls, stores any pointers to new CStructs\r\n\t// between here and SSwitchToPreviousPool().\r\n\t// This is just to keep the special pool clean. Things will get confusing if other stuff\r\n\t// gets allocated off it and uses up space there, cos then saving to mem card could start\r\n\t// running out of pool again.\r\n\r\n\tScript::CStruct *pMemCardStuff=new Script::CStruct;\r\n\tif (save_vault_data)\r\n\t{\r\n\t\tpMemCardStuff->AppendStructure(spVaultData);\r\n\t}\r\n\telse\r\n\t{\r\n\t\ts_insert_game_save_info(file_type,pMemCardStuff);\t\r\n\t}\t\r\n\t//Script::PrintContents(pMemCardStuff);\r\n\t\r\n\tScript::CStruct *pSummaryInfo=new Script::CStruct;\r\n\ts_generate_summary_info(pSummaryInfo,file_type,pMemCardStuff);\t\r\n\t\r\n\t// Put the user filename into the summary info too.\r\n\tpSummaryInfo->AddString(\"filename\",p_name);\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tprintf(\"Save type = '%s'\\n\",Script::FindChecksumName(file_type));\r\n\tprintf(\"Num CComponents used by save = %d\\n\",CComponent::SGetNumUsedItems()-initial_ccomponent_num_used_items);\r\n\tprintf(\"Num CStructs used by game save = %d\\n\",CStruct::SGetNumUsedItems()-initial_cstruct_num_used_items);\r\n\tprintf(\"Num CVectors used by game save = %d\\n\",CVector::SGetNumUsedItems()-initial_cvector_num_used_items);\r\n\t#endif\r\n\r\n\r\n\tMc::File* pFile=NULL;\r\n\tuint8 *pTemp=NULL;\r\n\tuint8 *p_pad=NULL;\r\n\tuint32 pad_size=0;\r\n\tbool SavedOK=false;\r\n\r\n\tuint32 CardBytesWritten=0;\r\n\tuint8 *p_dest=NULL;\r\n\tSMcFileHeader *p_file_header=NULL;\r\n\tuint32 BytesWritten=0;\r\n\t\r\n\tMc::Manager * mc_man=NULL;\r\n\tMc::Card* p_card=NULL;\r\n\t\r\n\t// fixed_size is the hard-wired file size as defined in memcard.q, rounded up to\r\n\t// the platform's block size. A file of exactly this size will be opened for writing.\r\n\t// The code will assert if the required space is greater than this.\r\n\t// The file sizes are required to be fixed as a TRC thing for GameCube.\r\n\tuint32 fixed_size=sGetFixedFileSize(file_type);\r\n\t\r\n\t// header_and_structures_size is the exact space used by the header, summary info, and \r\n\t// game save info structures. It is not rounded up to the platform's block size.\r\n\t// For all save types except replays, this comprises all the info in the file.\r\n\t// Replay's have the replay data tagged on the end of the file instead, because there\r\n\t// is not enough memory to keep it in the structures.\r\n\tuint32 header_and_structures_size=0;\r\n\r\n\t\r\n\t// This is the size of the replay data, if any. Not rounded up to the platform's block size.\r\n\tuint32 replay_data_size=0;\r\n\r\n#if __USE_REPLAYS__\r\n\t// The big replay data has to be tagged on the end rather than being put inside pMemCardStuff\r\n\t// since there is not enough memory to make a copy of the replay data there.\r\n\tReplay::SReplayDataHeader replay_data_header;\r\n\tif (file_type==0x26c80b0d/* Replay */)\r\n\t{\r\n\t\tReplay::WriteReplayDataHeader(&replay_data_header);\r\n\t\treplay_data_size=sGetReplayDataSize(replay_data_header.mNumStartStateDummies);\r\n\t}\t\r\n#endif\t\r\n\t\r\n\t/////////////////////////////////////////////////////////////////////////\r\n\t//pMemCardStuff->PrintContents();\r\n\t//printf(\"Space required = %d\\n\",pMemCardStuff->CalculateBufferSize());\r\n\t/////////////////////////////////////////////////////////////////////////\r\n\t\r\n\t// Get how much space is needed to store the structures.\r\n\t// Calculating this before opening the file so that if CalculateBufferSize fails,\r\n\t// the file won't be left with zero size, erasing the previous save game.\r\n\t// Passing fixed_size as the size of the temp buffer used when calculating the actual size needed.\r\n\tuint32 structure_size=CalculateBufferSize(pMemCardStuff, fixed_size);\r\n\tuint32 summary_info_size=CalculateBufferSize(pSummaryInfo,MAX_SUMMARY_INFO_SIZE);\r\n\tDbg_MsgAssert(summary_info_size<=MAX_SUMMARY_INFO_SIZE,(\"summary_info_size too big !!\"));\r\n\theader_and_structures_size=sizeof(SMcFileHeader)+summary_info_size+structure_size;\r\n\r\n\tuint32 required_size=header_and_structures_size+replay_data_size;\r\n\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tDbg_MsgAssert(required_size <= fixed_size,(\"Need to update fixed file size for type '%s'\\nMin required size = %d\",Script::FindChecksumName(file_type),required_size));\r\n\tprintf(\"required_size=%d, fixed_size=%d, %d percent\\n\",required_size,fixed_size,(100*required_size)/fixed_size);\r\n\tif (required_size > fixed_size)\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\t\r\n\t#endif\r\n\r\n\tpad_size=fixed_size-required_size;\r\n\tif (pad_size && Config::GetHardware() != Config::HARDWARE_NGC)\r\n\t{\r\n\t\tp_pad=(uint8*)Mem::Malloc(pad_size);\r\n\t\tfor (uint32 i=0; i<pad_size; ++i)\r\n\t\t{\r\n\t\t\tp_pad[i]=0x69;\r\n\t\t}\r\n\t}\r\n\t\r\n\tmc_man = Mc::Manager::Instance();\r\n\tp_card=mc_man->GetCard(0,0);\r\n\tif (!p_card)\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\r\n\t// GameCube often crashes if try to do card operations on a bad card, so do this check first.\r\n\tif (!p_card->IsFormatted())\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\r\n\t\r\n\tchar p_card_file_name[MAX_CARD_FILE_NAME_CHARS+1];\r\n\tswitch (Config::GetHardware())\r\n\t{\r\n\t\tcase Config::HARDWARE_PS2:\r\n\t\tcase Config::HARDWARE_PS2_PROVIEW:\r\n\t\tcase Config::HARDWARE_PS2_DEVSYSTEM:\r\n\t\t\tif (!s_make_ps2_dir_and_icons(p_card,\r\n\t\t\t\t\t\t\t\t\t\t  file_type,p_name,\r\n\t\t\t\t\t\t\t\t\t\t  p_card_file_name,\r\n\t\t\t\t\t\t\t\t\t\t  &s_insufficient_space))\r\n\t\t\t{\r\n\t\t\t\tgoto ERROR;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\r\n\t\tcase Config::HARDWARE_NGC:\r\n\t\t{\r\n\t\t\t// On the NGC, just generate the card file name.\r\n\t\t\t// The icon cannot be created at this point because on the NGC the\r\n\t\t\t// icon images have to be stored in the file data itself, so we have to\r\n\t\t\t// wait until after the file is opened.\r\n\t\t\tchar p_directory_name[MAX_CARD_FILE_NAME_CHARS+1];\r\n\t\t\ts_generate_card_directory_name(file_type,p_name,p_directory_name);\r\n\t\t\t\r\n\t\t\tsprintf(p_card_file_name,\"%s%s\",p_directory_name,p_directory_name);\r\n\t\t\tDbg_MsgAssert(strlen(p_card_file_name)<MAX_CARD_FILE_NAME_CHARS+1,(\"Oops\"));\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\tcase Config::HARDWARE_XBOX:\r\n\t\t\tif (!s_make_xbox_dir_and_icons(p_card,\r\n\t\t\t\t\t\t\t\t\t\t   file_type,p_name,\r\n\t\t\t\t\t\t\t\t\t\t   p_card_file_name,\r\n\t\t\t\t\t\t\t\t\t\t   &s_insufficient_space))\r\n\t\t\t{\r\n\t\t\t\tgoto ERROR;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\t{\r\n\t\t\t\tgoto ERROR;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n\t\t\t\r\n\r\n\t// Open a file big enough to hold all the data.\r\n\t//printf(\"Opening file %s of size %d for writing\\n\",p_card_file_name,fixed_size);\r\n\tpFile=p_card->Open( p_card_file_name, Mc::File::mMODE_WRITE | Mc::File::mMODE_CREATE, fixed_size );\r\n\ts_insufficient_space=p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE;\r\n\r\n\tif (!pFile)\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\r\n\t\t\r\n\tpTemp=(uint8*)Mem::Malloc(header_and_structures_size);\r\n\t\r\n\tp_file_header=(SMcFileHeader*)pTemp;\r\n\t// Zero the whole structure to ensure that the XBox mSignature member is zeroed since\r\n\t// it will be part of the data who's signature is calculated.\r\n\tp_dest=(uint8*)p_file_header;\r\n\tfor (uint32 i=0; i<sizeof(SMcFileHeader); ++i)\r\n\t{\r\n\t\t*p_dest++=0;\r\n\t}\r\n\r\n\tif (Config::GetHardware()==Config::HARDWARE_NGC)\r\n\t{\r\n\t\tif (!s_insert_ngc_icon(p_file_header,p_card,pFile,file_type,p_name))\r\n\t\t{\r\n\t\t\tgoto ERROR;\r\n\t\t}\r\n\t}\r\n\t\r\n\tp_file_header->mVersion=s_get_version_number(file_type);\r\n\tp_file_header->mSummaryInfoSize=summary_info_size;\r\n\tp_file_header->mDataSize=header_and_structures_size;\r\n\r\n\tp_dest=(uint8*)(p_file_header+1);\r\n\r\n\t// Write in the summary info and calculate its checksum.\r\n\tBytesWritten=WriteToBuffer(pSummaryInfo, p_dest, summary_info_size, Script::NO_ASSERT);\r\n\tif (BytesWritten!=summary_info_size)\r\n\t{\r\n\t\t// Note: This assert is surrounded by an if to prevent a warning on non debug builds\r\n\t\t// due to the BytesWritten variable being unused.\r\n\t\tDbg_MsgAssert(0,(\"BytesWritten does not equal summary_info_size ?\"));\r\n\t}\t\r\n\tp_file_header->mSummaryInfoChecksum=Crc::GenerateCRCCaseSensitive((const char *)p_dest,summary_info_size);\r\n\tp_dest+=summary_info_size;\r\n\r\n\t\r\n\t// Write in the game save info\r\n\tBytesWritten=WriteToBuffer(pMemCardStuff, p_dest, structure_size, Script::NO_ASSERT);\r\n\t\r\n\t// K: Last minute fix, 'encrypt' the network settings so that the AOL info cannot be \r\n\t// read. Not very secure, but it should be enough to make the strings non obvious.\r\n\tif (file_type==0xca41692d) // NetworkSettings\r\n\t{\r\n\t\t//printf(\"Encrypting %d bytes ...\\n\",structure_size);\r\n\t\tfor (uint32 e=0; e<structure_size; ++e)\r\n\t\t{\r\n\t\t\tp_dest[e]+=0x69;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (BytesWritten!=structure_size)\r\n\t{\r\n\t\t// Note: This assert is surrounded by an if to prevent a warning on non debug builds\r\n\t\t// due to the BytesWritten variable being unused.\r\n\t\tDbg_MsgAssert(0,(\"BytesWritten does not equal structure_size ?\"));\r\n\t}\t\r\n\tp_dest+=structure_size;\r\n\r\n\tDbg_MsgAssert(p_dest==pTemp+header_and_structures_size,(\"What ?\"));\r\n\t\t\t\t\t\r\n\t#ifdef __PLAT_XBOX__\r\n\tHANDLE h_signature=XCalculateSignatureBegin(0);\r\n\tif (XCalculateSignatureUpdate(h_signature,(const BYTE *)(pTemp),header_and_structures_size) != ERROR_SUCCESS)\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"XCalculateSignatureUpdate failed!\"));\r\n\t}\r\n\tif (pad_size)\r\n\t{\r\n\t\tDbg_MsgAssert(p_pad,(\"NULL p_pad ?\"));\r\n\t\tif (XCalculateSignatureUpdate(h_signature,(const BYTE *)(p_pad),pad_size) != ERROR_SUCCESS)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"XCalculateSignatureUpdate failed!\"));\r\n\t\t}\r\n\t}\t\r\n\tif (XCalculateSignatureEnd(h_signature,&p_file_header->mSignature)!=ERROR_SUCCESS)\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"XCalculateSignatureEnd failed!\"));\r\n\t}\r\n\t#else\r\n\t// Now calculate a checksum of all that data.\r\n\t// It will include the contents of p_file_header in the data too, \r\n\t// including mChecksum itself which will be zero at this point.\r\n\t// By zeroing mChecksum and including it in the data that is checksum'd it\r\n\t// means that the order of the members of SMcFileHeader does not matter.\r\n\t// Just seems kind of ugly having to have mChecksum be the first member, cos\r\n\t// it would also mean having to take the address of the second member to get\r\n\t// the start address of the data to checksum, bleurgh.\r\n\t\r\n\tp_file_header->mChecksum=Crc::GenerateCRCCaseSensitive((const char*)pTemp,header_and_structures_size);\r\n\t#endif // #ifdef __PLAT_XBOX__\r\n\t\r\n\tCardBytesWritten=pFile->Write( pTemp, header_and_structures_size );\r\n\t//printf(\"Wrote %d bytes\\n\",CardBytesWritten);\r\n\ts_insufficient_space=p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE;\r\n\tif (CardBytesWritten!=header_and_structures_size)\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\r\n\r\n\r\n#if __USE_REPLAYS__\r\n\t// Write out the big replay buffer.\r\n\t// It cannot be written out in one go by getting its base pointer, because on\r\n\t// the GameCube it is stored in ARAM.\r\n\t// The only way to access it is via the ReadFromBuffer function.\r\n\t// Also, there is not enough memory to copy it into a big temporary buffer, \r\n\t// so write it out in small chunks.\r\n\tif (file_type==0x26c80b0d/* Replay */)\r\n\t{\r\n\t\t// Initialise the checksum, which is calculated cumulatively.\r\n\t\tuint32 replay_data_checksum=0xffffffff;\r\n\t\t\r\n\t\t// Write out the replay data header.\r\n\t\tCardBytesWritten=pFile->Write( (uint8*)&replay_data_header, sizeof(Replay::SReplayDataHeader) );\r\n\t\ts_insufficient_space=p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE;\r\n\t\tif (CardBytesWritten!=sizeof(Replay::SReplayDataHeader))\r\n\t\t{\r\n\t\t\tgoto ERROR;\r\n\t\t}\r\n\t\r\n\t\treplay_data_checksum=Crc::UpdateCRC((const char *)&replay_data_header,sizeof(Replay::SReplayDataHeader),replay_data_checksum);\r\n\r\n\r\n\t\t// Write out the start-state dummies.\t\r\n\t\tReplay::SSavedDummy saved_dummy;\r\n\t\tReplay::CDummy *p_dummy=Replay::GetFirstStartStateDummy();\r\n\t\tint count=0;\r\n\t\twhile (p_dummy)\r\n\t\t{\r\n\t\t\tp_dummy->Save(&saved_dummy);\r\n\t\t\t\r\n\t\t\tCardBytesWritten=pFile->Write( (uint8*)&saved_dummy, sizeof(Replay::SSavedDummy) );\r\n\t\t\ts_insufficient_space=p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE;\r\n\t\t\tif (CardBytesWritten!=sizeof(Replay::SSavedDummy))\r\n\t\t\t{\r\n\t\t\t\tgoto ERROR;\r\n\t\t\t}\r\n\t\t\treplay_data_checksum=Crc::UpdateCRC((const char *)&saved_dummy,sizeof(Replay::SSavedDummy),replay_data_checksum);\r\n\t\t\t\r\n\t\t\tp_dummy=p_dummy->mpNext;\r\n\t\t\t++count;\r\n\t\t}\r\n\t\tif (count!=replay_data_header.mNumStartStateDummies)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"Dummy count mismatch\"));\r\n\t\t}\t\r\n\t\t\r\n\t\tint buf_size=Replay::GetBufferSize();\r\n\t\tDbg_MsgAssert((buf_size%REPLAY_BUFFER_CHUNK_SIZE)==0,(\"Replay buffer size not a multiple of REPLAY_BUFFER_CHUNK_SIZE\"));\r\n\t\t\r\n\t\tuint8 *p_chunk=Replay::GetTempBuffer();\r\n\t\tint num_chunks=buf_size/REPLAY_BUFFER_CHUNK_SIZE;\r\n\t\t\r\n\t\tuint32 offset=0;\r\n\t\tfor (int i=0; i<num_chunks; ++i)\r\n\t\t{\r\n\t\t\tReplay::ReadFromBuffer(p_chunk,offset,REPLAY_BUFFER_CHUNK_SIZE);\r\n\t\t\treplay_data_checksum=Crc::UpdateCRC((const char *)p_chunk,REPLAY_BUFFER_CHUNK_SIZE,replay_data_checksum);\r\n\t\t\t\r\n\t\t\toffset+=REPLAY_BUFFER_CHUNK_SIZE;\r\n\t\t\t\r\n\t\t\tCardBytesWritten=pFile->Write( p_chunk, REPLAY_BUFFER_CHUNK_SIZE );\r\n\t\t\ts_insufficient_space=p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE;\r\n\t\t\tif (CardBytesWritten!=REPLAY_BUFFER_CHUNK_SIZE)\r\n\t\t\t{\r\n\t\t\t\tgoto ERROR;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Write out the replay data checksum\r\n\t\tCardBytesWritten=pFile->Write( (uint8*)&replay_data_checksum, 4 );\r\n\t\ts_insufficient_space=p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE;\r\n\t\tif (CardBytesWritten!=4)\r\n\t\t{\r\n\t\t\tgoto ERROR;\r\n\t\t}\r\n\t}\r\n#endif\r\n\t\r\n\t// Now write out padding so as to make sure the file has size fixed_size, otherwise\r\n\t// there will be a discrepancy between the space that the game claims is required and\r\n\t// the size that appears in the file list, and I'll get a ton of TT bugs.\r\n\tif ( Config::GetHardware() != Config::HARDWARE_NGC)\r\n\t{\r\n\t\t// TODO: Fix bug in the Write function for the NGC. It always writes from offset 0,\r\n\t\t// meaning that writing this padding overwrites the start of the file data.\r\n\t\t// We don't actually have to write this padding on the NGC, because the resultant file size\r\n\t\t// will be exactly that specified in the file Open command.\r\n\t\t// But the bug will manifest itself when saving the replay data, so need to fix it ...\r\n\t\tif (pad_size)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(p_pad,(\"NULL p_pad ?\"));\t\t\t\r\n\t\t\tCardBytesWritten=pFile->Write( p_pad, pad_size );\r\n\t\t\t//printf(\"Wrote %d bytes\\n\",CardBytesWritten);\r\n\t\t\t\r\n\t\t\ts_insufficient_space=p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE;\r\n\t\t\tif (CardBytesWritten != pad_size)\r\n\t\t\t{\r\n\t\t\t\tgoto ERROR;\r\n\t\t\t}\r\n\t\t}\t\r\n\t}\t\r\n\t\r\n\tSavedOK=true;\r\n\t\r\nERROR:\t\r\n\tif (p_pad)\r\n\t{\r\n\t\tMem::Free(p_pad);\r\n\t}\r\n\tif (pTemp)\r\n\t{\r\n\t\tMem::Free(pTemp);\r\n\t}\r\n\tif (pFile)\r\n\t{\r\n\t\tif (!pFile->Flush())\r\n\t\t{\r\n\t\t\tSavedOK=false;\r\n\t\t}\t\r\n\t\tif (!pFile->Close())\r\n\t\t{\r\n\t\t\tSavedOK=false;\r\n\t\t}\t\r\n\t\tdelete pFile;\r\n\t}\t\r\n\t\r\n\tdelete pSummaryInfo;\r\n\tdelete pMemCardStuff;\r\n\r\n\t\r\n\tif (got_special_pools)\r\n\t{\r\n\t\tDbg_MsgAssert(CComponent::SGetNumUsedItems()==0,(\"Expected the special mem card CComponent pool to be empty at this point, but got %d items\",CComponent::SGetNumUsedItems()));\r\n\t\tDbg_MsgAssert(CStruct::SGetNumUsedItems()==0,(\"Expected the special mem card CStruct pool to be empty at this point, but got %d items\",CStruct::SGetNumUsedItems()));\r\n\t\tDbg_MsgAssert(CVector::SGetNumUsedItems()==0,(\"Expected the special mem card CVector pool to be empty at this point, but got %d items\",CVector::SGetNumUsedItems()));\r\n\t\tCComponent::SSwitchToPreviousPool();\r\n\t\tCStruct::SSwitchToPreviousPool();\r\n\t\tCVector::SSwitchToPreviousPool();\r\n\t}\r\n\t\r\n\tif ( Config::GetHardware() != Config::HARDWARE_XBOX)\r\n\t{\r\n\t\tPcm::PauseMusic( -1 );\r\n\t\tPcm::PauseStream( -1 );\r\n\t}\r\n\r\n\tif (Config::GetHardware() == Config::HARDWARE_NGC)\r\n\t{\r\n\t\tScriptRemoveTemporaryMemCardPools(NULL,NULL);\r\n\t}\r\n\t\t\r\n\treturn SavedOK;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#if __USE_REPLAYS__\r\n\t#ifdef __PLAT_NGC__\r\n\tstatic SMcFileHeader sFileHeader __attribute__((aligned( 32 )));\r\n\t#else\r\n\tstatic SMcFileHeader sFileHeader;\r\n\t#endif\r\n#endif\r\n\r\nbool ScriptSetSectionsToApplyWhenLoading(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    printf(\"ScriptSetSectionsToApplyWhenLoading was called.........................\\n\");\r\n    // These flags only apply when loading type OptionsAndPros.\r\n\t// They allow for only certain sections of the file being applied to the game state.\r\n\t// For example, when loading a custom skater, only the CUSTOM_SKATER part must be applied.\r\n\ts_apply_flags=0;\r\n\t\r\n\tif (pParams->ContainsFlag(CRCD(0x16b506c0,\"ApplyCustomSkater\")))\r\n\t{\r\n\t\ts_apply_flags |= 1<<APPLY_CUSTOM_SKATER;\r\n\t}\t\r\n\tif (pParams->ContainsFlag(CRCD(0xdc7ea3ce,\"ApplyStorySkater\")))\r\n\t{\r\n\t\ts_apply_flags |= 1<<APPLY_STORY_SKATER;\r\n\t}\t\r\n\tif (pParams->ContainsFlag(CRCD(0x33ec233f,\"ApplyStory\")))\r\n\t{\r\n\t\ts_apply_flags |= 1<<APPLY_STORY;\r\n\t}\t\r\n\tif (pParams->ContainsFlag(CRCD(0xb39d7cc4,\"ApplyGeneralOptions\")))\r\n\t{\r\n\t\ts_apply_flags |= 1<<APPLY_GLOBAL_INFO;\r\n\t}\t\r\n\t\r\n\tif (pParams->ContainsFlag(CRCD(0xc4e78e22,\"all\")))\r\n\t{\r\n\t\ts_apply_flags=0xffffffff;\r\n\t}\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n// @script | LoadFromMemoryCard | Load the specified file from the memory card\r\n// @parm string | Name | The name of the file to load\r\n// @parm name | Type | The type of the file (cas, network, park, etc.)\r\nbool ScriptLoadFromMemoryCard(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tDbg_MsgAssert(!Config::Bootstrap(),(\"Can't use memory card from bootstrap demo\"));\r\n\r\n\tif ( Config::GetHardware() != Config::HARDWARE_XBOX)\r\n\t{\r\n\t\tPcm::PauseMusic(true);\r\n\t\tPcm::PauseStream(true);\r\n\t}\r\n\t\t\r\n\t// Create structures for holding the summary info & game save info\r\n\tCStruct *pSummaryInfo=new CStruct;\r\n\tCStruct *pMemCardStuff=new CStruct;\r\n\r\n\t// A bunch of variable declarations, which need to be up here cos there are goto's later\r\n\tconst char *p_name=\"\";\r\n\tuint32 file_type=0;\r\n\t\r\n\tMc::File* p_file=NULL;\r\n\tint file_size=0;\r\n\tuint8 *p_temp=NULL;\r\n\tuint8 *p_stuff=NULL;\r\n\tSMcFileHeader *p_file_header;\r\n\tbool loaded_ok=false;\r\n\tuint32 calculated_checksum=0;\r\n\tuint32 stored_checksum=0;\r\n\tbool checksum_matches=false;\r\n\t\r\n\t// The LoadForUpload flag is passed as an integer so that that calls to LoadFromMemoryCard\r\n\t// in script can set LoadForUpload equal to the value of some script global for convenience.\r\n\tint load_for_upload=0;\r\n\tpParams->GetInteger(CRCD(0x8c6808d4,\"LoadForUpload\"),&load_for_upload);\r\n\r\n\t#ifdef __PLAT_XBOX__\r\n\tXCALCSIG_SIGNATURE stored_signature;\r\n\tXCALCSIG_SIGNATURE calculated_signature;\r\n\tHANDLE h_signature;\r\n\tBYTE *p_a=NULL;\r\n\tBYTE *p_b=NULL;\r\n\t#endif\t\r\n\t\r\n\t// Get the card.\r\n\tMc::Manager * mc_man = Mc::Manager::Instance();\r\n\tMc::Card* p_card=mc_man->GetCard(0,0);\r\n\tif (!p_card)\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\r\n\t// GameCube often crashes if try to do card operations on a bad card, so do this check first.\r\n\tif (!p_card->IsFormatted())\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\r\n\t\t\r\n\t\t\r\n\tpParams->GetText(\"Name\",&p_name);\r\n\tpParams->GetChecksum(\"Type\",&file_type);\r\n\r\n\t// Calculate the low-level filename\r\n\tchar p_card_file_name[MAX_CARD_FILE_NAME_CHARS+1];\r\n\tp_card_file_name[0]=0;\r\n\t\r\n\tswitch (Config::GetHardware())\r\n\t{\r\n\t\tcase Config::HARDWARE_PS2:\r\n\t\tcase Config::HARDWARE_PS2_PROVIEW:\r\n\t\tcase Config::HARDWARE_PS2_DEVSYSTEM:\r\n\t\t{\r\n\t\t\tconst char *p_header=Config::GetMemCardHeader();\r\n\t\t\tchar p_ascii_checksum[20];\r\n\t\t\ts_generate_ascii_checksum(p_ascii_checksum,p_name,file_type);\r\n\t\t\t\r\n\t\t\tsprintf(p_card_file_name,\"/%s%s/%s%s\",\tp_header,p_ascii_checksum,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tp_header,p_ascii_checksum);\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase Config::HARDWARE_NGC:\r\n\t\t{\r\n\t\t\tchar p_directory_name[MAX_CARD_FILE_NAME_CHARS+1];\r\n\t\t\ts_generate_card_directory_name(file_type,p_name,p_directory_name);\r\n\t\t\t\r\n\t\t\tsprintf(p_card_file_name,\"%s%s\",p_directory_name,p_directory_name);\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase Config::HARDWARE_XBOX:\r\n\t\t{\r\n\t\t\t// Generate the directory name\r\n\t\t\tconst char *p_directory_name=s_generate_xbox_directory_name(file_type,p_name);\r\n\t\t\tconst char *p_low_level_directory_name=p_card->ConvertDirectory(p_directory_name);\r\n\t\t\r\n\t\t\tif (!p_low_level_directory_name)\r\n\t\t\t{\r\n\t\t\t\tgoto ERROR;\r\n\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t// Calculate the low-level file name.\r\n\t\t\tsprintf( p_card_file_name, \"/%s/%s\", p_low_level_directory_name, p_low_level_directory_name );\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tgoto ERROR;\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t}\r\n\t\r\n\tDbg_MsgAssert(strlen(p_card_file_name)<MAX_CARD_FILE_NAME_CHARS+1,(\"Oops\"));\r\n\t\r\n#if __USE_REPLAYS__\r\n\tif (file_type==0x26c80b0d/* Replay */)\r\n\t{\r\n\t\tstrcpy(spReplayCardFileName,p_card_file_name);\r\n\t\tsNeedToLoadReplayBuffer=true;\r\n\t}\r\n#endif\r\n\t\t\r\n\t// Open the file.\r\n\tp_file=p_card->Open( p_card_file_name, Mc::File::mMODE_READ );\r\n\tif (!p_file)\r\n\t{\r\n\t\t// File could not be opened\r\n\t\tgoto ERROR;\r\n\t}\t\r\n\t\r\n\t// File opened OK\r\n\t\r\n\t// Check the file size.\r\n\tfile_size=p_file->Seek( 0 ,Mc::File::BASE_END);\r\n\t// Removed the file size check, because the fixed size needed to be updated, and keeping the\r\n\t// check would prevent existing parks from being able to be loaded.\r\n\t//if (file_size != (int)sGetFixedFileSize(file_type))\r\n\t//{\r\n\t//\t// Size mismatch, so consider the file corrupted.\r\n\t//\tpScript->GetParams()->AddChecksum(NONAME,GenerateCRC(\"CorruptedData\"));\r\n\t//\tgoto ERROR;\r\n\t//}\t\r\n\t\r\n\t// Read the file into memory\r\n\t// Allocate a temporary buffer for reading the file into\r\n\tp_temp=(uint8*)Mem::Malloc(file_size);\r\n\tDbg_MsgAssert(p_temp,(\"Could not allocate %d bytes for file buffer for file %s\",file_size,p_card_file_name));\r\n\r\n\tp_file->Seek(0,Mc::File::BASE_START);\r\n\tif (p_file->Read(p_temp, file_size) != file_size)\r\n\t{\r\n\t\t// Some sort of read error.\r\n\t\tgoto ERROR;\r\n\t}\t\t\r\n\t\r\n\t// Seemed to read into memory OK\r\n\t// Check if the data is corrupt by recalculating the checksum.\r\n\tp_stuff=p_temp;\r\n\tp_file_header=(SMcFileHeader*)p_stuff;\r\n\t\r\n\t#ifdef __PLAT_XBOX__\r\n\t// Load p_file_header->mSignature into stored_signature\r\n\t// then zero out p_file_header->mSignature\r\n\tp_a=p_file_header->mSignature.Signature;\r\n\tp_b=stored_signature.Signature;\r\n\tfor (int i=0; i<XCALCSIG_SIGNATURE_SIZE; ++i)\r\n\t{\r\n\t\t*p_b=*p_a;\r\n\t\t*p_a=0;\r\n\t\t++p_a;\r\n\t\t++p_b;\r\n\t}\r\n\t\t\t\t\t\t\t\r\n\t// Calculate the signature of the data.\t\t\t\t\t\t\r\n\th_signature=XCalculateSignatureBegin(0);\r\n\tif (XCalculateSignatureUpdate(h_signature,(const BYTE *)p_stuff,file_size) != ERROR_SUCCESS)\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"XCalculateSignatureUpdate failed!\"));\r\n\t}\r\n\tif (XCalculateSignatureEnd(h_signature,&calculated_signature)!=ERROR_SUCCESS)\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"XCalculateSignatureEnd failed!\"));\r\n\t}\r\n\t\r\n\t// Compare the calculated signature with the stored one.\r\n\tp_a=stored_signature.Signature;\r\n\tp_b=calculated_signature.Signature;\r\n\tchecksum_matches=true;\r\n\tfor (int i=0; i<XCALCSIG_SIGNATURE_SIZE; ++i)\r\n\t{\r\n\t\tif (*p_a != *p_b)\r\n\t\t{\r\n\t\t\tchecksum_matches=false;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t++p_a;\r\n\t\t++p_b;\r\n\t}\t\t\r\n\r\n\t#else\r\n\tchecksum_matches=false;\r\n\tstored_checksum=p_file_header->mChecksum;\r\n\t\r\n\t// Set the checksum to zero because that was what it was when\r\n\t// the checksum was calculated.\r\n\tp_file_header->mChecksum=0;\r\n\t// Using p_file_header->mDataSize instead of file_size, because file_size includes the\r\n\t// padding, which is not included in the checksum calculation on PS2 and NGC\r\n\tif (p_file_header->mDataSize > 500000)\r\n\t{\r\n\t\t// If mDataSize itself is corrupted, then don't go trying to calculate the\r\n\t\t// checksum of megabytes of data, in case that hangs the game by hitting some sort\r\n\t\t// of restricted memory location.\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcalculated_checksum=Crc::GenerateCRCCaseSensitive((const char*)p_stuff,p_file_header->mDataSize);\r\n\t\r\n\t\tif (calculated_checksum==stored_checksum &&\r\n\t\t\tp_file_header->mVersion==s_get_version_number(file_type))\r\n\t\t{\r\n\t\t\tchecksum_matches=true;\r\n\t\t}\r\n\t}\t\r\n\t#endif\r\n\r\n\t\t\r\n\tif (checksum_matches)\r\n\t{\r\n\t\t// The data is OK, so it is safe to parse it.\r\n\t\t\r\n\t\t// Skip over the header.\r\n\t\tp_stuff=(uint8*)(p_file_header+1);\r\n\r\n\t\t// Skip over the summary info\r\n\t\tp_stuff=ReadFromBuffer(pSummaryInfo, p_stuff);\r\n\r\n\t\t// K: Last minute fix, 'decrypt' the network settings.\r\n\t\tif (file_type==0xca41692d) // NetworkSettings\r\n\t\t{\r\n\t\t\tint num_bytes=p_file_header->mDataSize-(p_stuff-((uint8*)p_file_header));\r\n\t\t\t//printf(\"Decrypting %d bytes ...\\n\",num_bytes);\r\n\t\t\tfor (int e=0; e<num_bytes; ++e)\r\n\t\t\t{\r\n\t\t\t\tp_stuff[e]-=0x69;\r\n\t\t\t}\r\n\t\t}\t\r\n\r\n\t\t// Read in the game save info\t\t\t\t\t\t\r\n\t\tReadFromBuffer(pMemCardStuff, p_stuff);\r\n\r\n\t\t// The data is now safely in pMemCardStuff ...\r\n\t\t\r\n\t\tif (load_for_upload)\r\n\t\t{\r\n\t\t\t// If the file was loaded for upload to the net, then do not process the data\r\n\t\t\t// but just store it away so that the GetMemCardDataForUpload command can retrieve\r\n\t\t\t// it a bit later.\r\n\t\t\tDbg_MsgAssert(spVaultData==NULL,(\"\\n%s\\nLoadFromMemoryCard expected the vault data to be cleared at this point ?\",pScript->GetScriptInfo()));\r\n\t\t\tspVaultData=new Script::CStruct;\r\n\t\t\tspVaultData->AppendStructure(pMemCardStuff);\r\n\t\t\tsVaultDataType=file_type;\r\n\r\n            if ( file_type == CRCD(0x61a1bc57,\"cat\") )\r\n            {\r\n                // load Created trick in edit slot so we can get some info out of it for uploading\r\n                s_read_game_save_info(file_type, pMemCardStuff, pScript);\r\n            }\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// process the data according to the type of file loaded.\r\n\t\t\ts_read_game_save_info(file_type, pMemCardStuff, pScript);\r\n\t\t}\r\n\t\t\t\t\r\n\t\tloaded_ok=true;\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\t// Corrupted data, or bad version number\r\n\t\tpScript->GetParams()->AddChecksum(NONAME,GenerateCRC(\"CorruptedData\"));\r\n\t}\t\r\n\r\n\t// if the loading was successful,\r\n\t// then run some post-load functions\r\n\tif ( loaded_ok )\r\n\t{\r\n\t\tif (load_for_upload)\r\n\t\t{\r\n\t\t\t// If the file was loaded for upload to the net, then do not do any post processing,\r\n\t\t\t// since the data has just been stored away for retrieval later.\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tScript::RunScript( \"post_load_from_memory_card\", pParams );\r\n\t\t}\t\r\n\t}\r\n\r\nERROR:\t\r\n\t// Cleanup and unpause the music.\r\n\tif (p_file)\r\n\t{\r\n\t\tp_file->Close();\r\n\t\tdelete p_file;\r\n\t}\r\n\r\n\tif (p_temp)\r\n\t{\r\n\t\tMem::Free(p_temp);\r\n\t}\r\n\r\n\tdelete pSummaryInfo;\r\n\tdelete pMemCardStuff;\r\n\tif ( Config::GetHardware() != Config::HARDWARE_XBOX)\r\n\t{\r\n\t\tPcm::PauseMusic( -1 );\r\n\t\tPcm::PauseStream( -1 );\r\n\t}\r\n\t\t\r\n\treturn loaded_ok;\r\n}\r\n\r\nbool ScriptLoadedCustomSkater(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn s_did_apply_custom_skater_info;\r\n}\t\r\n\r\n// Functions required for when loading a file of mem card for uploading to the net.\r\nbool ScriptGetMemCardDataForUpload(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tDbg_MsgAssert(spVaultData,(\"\\n%s\\nNo mem card data present\",pScript->GetScriptInfo()));\r\n\t\r\n\tpScript->GetParams()->AddStructure(CRCD(0x6d2ab6a,\"DataForUpload\"),spVaultData);\r\n\tpScript->GetParams()->AddChecksum(CRCD(0x7321a8d6,\"Type\"),sVaultDataType);\r\n\treturn true;\r\n}\t\r\n\r\nbool ScriptClearMemCardDataForUpload(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tif (spVaultData)\r\n\t{\r\n\t\tdelete spVaultData;\r\n\t\tspVaultData=NULL;\r\n\t}\t\r\n\tsVaultDataType=0;\r\n\treturn true;\r\n}\t\r\n\r\nbool ScriptNeedToLoadReplayBuffer(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#if __USE_REPLAYS__\r\n\treturn sNeedToLoadReplayBuffer;\r\n#else\r\n\treturn false;\r\n#endif\r\n}\r\n\r\nbool ScriptLoadReplayData(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#if __USE_REPLAYS__\r\n\tDbg_MsgAssert(!Config::Bootstrap(),(\"Can't use memory card from bootstrap demo\"));\r\n\r\n\tPcm::PauseMusic(true);\r\n\tPcm::PauseStream(true);\r\n\t\r\n\tDbg_MsgAssert(sNeedToLoadReplayBuffer,(\"Called LoadReplayBuffer when sNeedToLoadReplayBuffer is false\"));\r\n\r\n\tint replay_buffer_size=0;\r\n\tReplay::SReplayDataHeader header;\r\n\tReplay::SSavedDummy saved_dummy;\r\n\tuint32 replay_data_checksum=0xffffffff; // Initialise the checksum, which is calculated accumulatively.\r\n\tuint32 ch=0;\t\r\n\tbool loaded_ok=false;\r\n\tint bytes_read=0;\r\n\tMc::File* p_file=NULL;\r\n\tuint8 *p_chunk=NULL;\r\n\tint num_chunks=0;\r\n\tint offset=0;\r\n\t\r\n\t// Get the card.\r\n\tMc::Manager * mc_man = Mc::Manager::Instance();\r\n\tMc::Card* p_card=mc_man->GetCard(0,0);\r\n\tif (!p_card)\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\r\n\t\r\n\t// GameCube often crashes if try to do card operations on a bad card, so do this check first.\r\n\tif (!p_card->IsFormatted())\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\r\n\r\n\t// Open the file.\r\n\tp_file=p_card->Open( spReplayCardFileName, Mc::File::mMODE_READ );\r\n\tif (!p_file)\r\n\t{\r\n\t\t// File could not be opened\r\n\t\tgoto ERROR;\r\n\t}\t\r\n\t\r\n\t// File opened OK\r\n\r\n\t// Seek to the start of the replay data by reading in the header, reading out the start data\r\n\t// size from the header, then seeking there.\t\r\n\tp_file->Seek( 0 ,Mc::File::BASE_START);\r\n\tif (p_file->Read((uint8*)&sFileHeader, sizeof(SMcFileHeader)) != sizeof(SMcFileHeader))\r\n\t{\r\n\t\t// Some sort of read error.\r\n\t\tgoto ERROR;\r\n\t}\t\t\r\n\tp_file->Seek(sFileHeader.mDataSize,Mc::File::BASE_START);\r\n\r\n\t// Make sure the buffer does exist\r\n\tReplay::AllocateBuffer();\r\n\t// and that it is cleared to start with.\r\n\tReplay::ClearBuffer();\r\n\t\t\t\r\n\t// Read in the header\t\t\t\r\n\tbytes_read=p_file->Read( (uint8*)&header, sizeof(Replay::SReplayDataHeader) );\r\n\tif (bytes_read!=sizeof(Replay::SReplayDataHeader))\r\n\t{\r\n\t\t// Some sort of read error.\r\n\t\tgoto ERROR;\r\n\t}\r\n\tReplay::ReadReplayDataHeader(&header);\r\n\treplay_data_checksum=Crc::UpdateCRC((const char *)&header,sizeof(Replay::SReplayDataHeader),replay_data_checksum);\r\n\t\r\n\t// Read in the dummies\r\n\tfor (int i=0; i<header.mNumStartStateDummies; ++i)\r\n\t{\r\n\t\tbytes_read=p_file->Read( (uint8*)&saved_dummy, sizeof(Replay::SSavedDummy) );\r\n\t\tif (bytes_read!=sizeof(Replay::SSavedDummy))\r\n\t\t{\r\n\t\t\t// Some sort of read error.\r\n\t\t\tgoto ERROR;\r\n\t\t}\r\n\t\treplay_data_checksum=Crc::UpdateCRC((const char *)&saved_dummy,sizeof(Replay::SSavedDummy),replay_data_checksum);\r\n\t\t\r\n\t\tReplay::CreateDummyFromSaveData(&saved_dummy);\r\n\t}\r\n\t\t\t\r\n\t// Read the data in a chunk at a time.\r\n\treplay_buffer_size=Replay::GetBufferSize();\r\n\tDbg_MsgAssert((replay_buffer_size%REPLAY_BUFFER_CHUNK_SIZE)==0,(\"Replay buffer size not a multiple of REPLAY_BUFFER_CHUNK_SIZE\"));\r\n\t\r\n\tp_chunk=Replay::GetTempBuffer();\r\n\tnum_chunks=replay_buffer_size/REPLAY_BUFFER_CHUNK_SIZE;\r\n\t\r\n\toffset=0;\r\n\tfor (int i=0; i<num_chunks; ++i)\r\n\t{\r\n\t\tbytes_read=p_file->Read( p_chunk, REPLAY_BUFFER_CHUNK_SIZE );\r\n\t\tif (bytes_read!=REPLAY_BUFFER_CHUNK_SIZE)\r\n\t\t{\r\n\t\t\t// Some sort of read error.\r\n\t\t\tgoto ERROR;\r\n\t\t}\r\n\t\tReplay::WriteIntoBuffer(p_chunk,offset,REPLAY_BUFFER_CHUNK_SIZE);\r\n\t\treplay_data_checksum=Crc::UpdateCRC((const char *)p_chunk,REPLAY_BUFFER_CHUNK_SIZE,replay_data_checksum);\r\n\t\t\r\n\t\toffset+=REPLAY_BUFFER_CHUNK_SIZE;\r\n\t}\r\n\r\n\t// Read in and check the checksum\r\n\tbytes_read=p_file->Read( (uint8*)&ch, 4 );\r\n\tif (bytes_read!=4)\r\n\t{\r\n\t\t// Some sort of read error.\r\n\t\tgoto ERROR;\r\n\t}\r\n\tif (ch != replay_data_checksum)\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\t\r\n\t\t\r\n\t// Hooray!\t\r\n\tloaded_ok=true;\r\n\r\nERROR:\t\r\n\tsNeedToLoadReplayBuffer=false;\r\n\t\r\n\tif (p_file)\r\n\t{\r\n\t\tp_file->Close();\r\n\t\tdelete p_file;\r\n\t}\r\n\r\n\tPcm::PauseMusic( -1 );\r\n\tPcm::PauseStream( -1 );\r\n\treturn loaded_ok;\r\n#else\r\n\treturn false;\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetMaxTHPS4FilesAllowed(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->AddInteger(\"MaxTHPS4FilesAllowed\",MAX_THPS4_FILES_ALLOWED);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic uint8 spSummaryInfoBuffer[sizeof(SMcFileHeader)+MAX_SUMMARY_INFO_SIZE];\r\nbool ScriptGetMemCardDirectoryListing(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->RemoveComponent(\"DirectoryListing\");\r\n\tpScript->GetParams()->RemoveComponent(\"FilesLimitReached\");\r\n\tpScript->GetParams()->RemoveComponent(\"TotalTHPS4FilesOnCard\");\r\n\r\n\tuint32 file_type_to_list=0;\r\n\tpParams->GetChecksum(\"FileType\",&file_type_to_list);\r\n\r\n\t// Get a directory listing of the whole card.\r\n\tMc::Manager * p_mc_man = Mc::Manager::Instance();\r\n\tMc::Card* p_card=p_mc_man->GetCard(0,0);\r\n\tif (!p_card)\r\n\t{\r\n\t\treturn true;\r\n\t}\t\r\n\r\n\tLst::Head< Mc::File > file_list;\r\n\tp_card->GetFileList( \"*\", file_list );\r\n\r\n\t// If the special pools exist, switch to them so that the components & structs etc get allocated off them.\r\n\t// The special pools use the space freed by unloading the skater anims, and are for preventing memory\r\n\t// overflows when the save size gets large.\r\n\tDbg_MsgAssert(CComponent::SGetCurrentPoolIndex()==0,(\"Bad current CComponent pool\"));\r\n\tDbg_MsgAssert(CStruct::SGetCurrentPoolIndex()==0,(\"Bad current CStruct pool\"));\r\n\tbool got_special_pools=false;\r\n\t\r\n\tCComponent::SSwitchToNextPool();\r\n\tif (CComponent::SPoolExists())\r\n\t{\r\n\t\tCStruct::SSwitchToNextPool();\r\n\t\tDbg_MsgAssert(CStruct::SPoolExists(),(\"No special CStruct pool ?\"));\r\n\t\tgot_special_pools=true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCComponent::SSwitchToPreviousPool();\r\n\t}\t\r\n\r\n\t\r\n\tint num_files_added=0;\r\n\tCStruct *pp_structs[MAX_THPS4_FILES_ALLOWED];\r\n\t\r\n\t// Run through all the files (well, directory names actually) and compare their\r\n\t// first 12 characters with the THPS4 header.\t\r\n\tconst char *p_header=Config::GetMemCardHeader();\r\n\tint header_len=strlen(p_header);\r\n\t\r\n\tint num_files=file_list.CountItems();\r\n\tint total_thps4_files=0;\r\n\tfor (int i=0; i<num_files; ++i)\r\n\t{\r\n\t\tMc::File *p_file=file_list.GetItem(i)->GetData();\r\n\t\t\r\n\t\tbool is_THPS4_file=true;\r\n\t\t\r\n\t\t// No need to check the file name if it's the XBox because all the files\r\n\t\t// will be in our filespace.\r\n\t\tif ( Config::GetHardware() != Config::HARDWARE_XBOX )\r\n\t\t{\r\n\t\t\tfor (int j=0; j<header_len; ++j)\r\n\t\t\t{\r\n\t\t\t\tif (p_file->m_Filename[j]!=p_header[j])\r\n\t\t\t\t{\r\n\t\t\t\t\tis_THPS4_file=false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\t\r\n\t\t\r\n\t\tif (!is_THPS4_file)\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\t++total_thps4_files;\r\n\t\t\r\n\t\t// It is a THPS4 file, so compare the file type with that requested.\r\n\t\tuint32 file_type=0;\r\n\t\t\r\n\t\t\r\n\t\tswitch (Config::GetHardware())\r\n\t\t{\r\n\t\tcase Config::HARDWARE_PS2:\r\n\t\tcase Config::HARDWARE_PS2_PROVIEW:\r\n\t\tcase Config::HARDWARE_PS2_DEVSYSTEM:\r\n\t\tcase Config::HARDWARE_NGC:\r\n\t\t\t// The filetype is indicated by the last letter of the 8 characters\r\n\t\t\t// that follow the header. The other 7 contain the ascii checksum of\r\n\t\t\t// the full file name as entered by the user.\r\n\t\t\tfile_type=s_determine_file_type(p_file->m_Filename[header_len+8-1]);\r\n\t\t\tbreak;\r\n\t\tcase Config::HARDWARE_XBOX:\r\n\t\t{\r\n\t\t\t// TODO: Remove this ifdef somehow, needed currently because m_DisplayFilename\r\n\t\t\t// is only defined for XBox. Shouldn't really have any platform ifdefs in this file.\r\n\t\t\t#ifdef __PLAT_XBOX__\r\n\t\t\tint length = strlen( p_file->m_DisplayFilename );\r\n\t\t\tif( stricmp( &p_file->m_DisplayFilename[length - 15], \"NetworkSettings\" ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tfile_type = 0xca41692d; // NetworkSettings\r\n\t\t\t}\r\n\t\t\telse if( stricmp( &p_file->m_DisplayFilename[length - 6], \"Skater\" ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tfile_type = 0xb010f357; // OptionsAndPros\r\n\t\t\t}\r\n\t\t\telse if( stricmp( &p_file->m_DisplayFilename[length - 4], \"Park\" ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tfile_type = 0x3bf882cc; // Park\r\n\t\t\t}\r\n\t\t\telse if( stricmp( &p_file->m_DisplayFilename[length - 6], \"Skater\" ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tfile_type = 0xffc529f4; // Cas\r\n\t\t\t}\r\n            else if( stricmp( &p_file->m_DisplayFilename[length - 5], \"Trick\" ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tfile_type = 0x61a1bc57; // CAT\r\n\t\t\t}\r\n\t\t\telse if( stricmp( &p_file->m_DisplayFilename[length - 6], \"Replay\" ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tfile_type = 0x26c80b0d; // Replay\r\n\t\t\t}\r\n\t\t\telse if( stricmp( &p_file->m_DisplayFilename[length - 5], \"Goals\" ) == 0 )\r\n\t\t\t{\r\n\t\t\t\tfile_type = 0x62896edf; // CreatedGoals\r\n\t\t\t}\r\n\t\t\t#endif // #ifdef __PLAT_XBOX__\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase Config::HARDWARE_WIN32:\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\tif ( (file_type_to_list==0 && file_type!=0) || \r\n\t\t\t file_type==file_type_to_list)\r\n\t\t{\r\n\t\t\tif (num_files_added < MAX_THPS4_FILES_ALLOWED)\r\n\t\t\t{\r\n\t\t\t\t// It's safe to add a new entry to the array.\r\n\t\t\t\tCStruct *p_struct=new CStruct;\r\n\t\t\t\tp_struct->AddChecksum(\"file_type\",file_type);\r\n\t\t\t\tp_struct->AddInteger(\"Index\",num_files_added);\r\n\r\n\r\n\t\t\t\tp_struct->AddInteger(\"Year\",p_file->m_Modified.m_Year);\r\n\t\t\t\tp_struct->AddInteger(\"Month\",p_file->m_Modified.m_Month);\r\n\t\t\t\tp_struct->AddInteger(\"Day\",p_file->m_Modified.m_Day);\r\n\t\t\t\tp_struct->AddInteger(\"Hour\",p_file->m_Modified.m_Hour);\r\n\t\t\t\tp_struct->AddInteger(\"Minutes\",p_file->m_Modified.m_Minutes);\r\n\t\t\t\tp_struct->AddInteger(\"Seconds\",p_file->m_Modified.m_Seconds);\r\n\r\n\t\t\t\t\r\n\t\t\t\tchar p_card_file_name[100];\r\n\t\t\t\tif (Config::GetHardware()==Config::HARDWARE_NGC)\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf(p_card_file_name,\"%s\",p_file->m_Filename);\r\n\t\t\t\t}\t\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf(p_card_file_name,\"/%s/%s\",p_file->m_Filename,p_file->m_Filename);\r\n\t\t\t\t}\t\r\n\t\t\t\tDbg_MsgAssert(strlen(p_card_file_name)<100,(\"Oops\"));\r\n\t\t\t\t\r\n\t\t\t\t// Store the low level file name in the structure too so that the scripts\r\n\t\t\t\t// can pass it on to the file delete function. This is necessary because\r\n\t\t\t\t// even though the low level file name can be derived from the file name as\r\n\t\t\t\t// stored in the file itself, if the file is corrupted the name might be too,\r\n\t\t\t\t// so in that case it would not be possible to delete it.\r\n\t\t\t\tp_struct->AddString(\"actual_file_name\",p_card_file_name);\r\n\t\t\t\t\r\n\t\t\t\t#ifdef __PLAT_XBOX__\r\n\t\t\t\tp_struct->AddString(\"xbox_directory_name\",p_file->m_DisplayFilename);\r\n\t\t\t\t#endif\r\n\r\n\t\t\t\t// Need to open the file to get the summary info out of it ...\r\n\t\t\t\tMc::File* p_mc_file=p_card->Open( p_card_file_name, Mc::File::mMODE_READ );\r\n\t\t\t\tif (p_mc_file)\r\n\t\t\t\t{   \r\n\t\t\t\t\t// File opened OK, so grab the first hundred or so bytes.\r\n\t\t\t\t\tp_mc_file->Seek( 0 ,Mc::File::BASE_START);\r\n\t\t\t\t\tp_mc_file->Read( spSummaryInfoBuffer, sizeof(SMcFileHeader)+MAX_SUMMARY_INFO_SIZE );\r\n\t\t\t\t\t\r\n\t\t\t\t\tSMcFileHeader *p_file_header=(SMcFileHeader*)spSummaryInfoBuffer;\r\n\t\t\t\t\tuint8 *p_summary_info=(uint8*)(p_file_header+1);\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Determine whether the summary info is corrupted.\r\n\t\t\t\t\tbool corrupt_summary_info=false;\r\n\t\t\t\t\tif (p_file_header->mSummaryInfoSize > MAX_SUMMARY_INFO_SIZE)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// The mSummaryInfoSize itself is corrupted!\r\n\t\t\t\t\t\tcorrupt_summary_info=true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tuint32 calculated_summary_info_checksum=Crc::GenerateCRCCaseSensitive((const char *)p_summary_info,p_file_header->mSummaryInfoSize);\r\n\t\t\t\t\t\tif (calculated_summary_info_checksum != p_file_header->mSummaryInfoChecksum)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tcorrupt_summary_info=true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\t\t\r\n\r\n\t\t\t\t\t// Calculate the total file size\r\n\t\t\t\t\tint file_size=p_mc_file->Seek(0,Mc::File::BASE_END);\r\n\t\t\t\t\t//printf(\"Directory listing: %s, size=%d\\n\",p_card_file_name,file_size);\r\n\t\t\t\t\tint total_size_on_card=s_calculate_total_space_used_on_card(file_type,file_size);\r\n\t\t\t\t\tp_struct->AddInteger(\"total_file_size\",total_size_on_card);\r\n\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Removed the file size check, because the fixed size needed to be updated, and keeping the\r\n\t\t\t\t\t// check would prevent existing parks from being able to be loaded.\r\n\t\t\t\t\t//if (corrupt_summary_info || file_size != (int)sGetFixedFileSize(file_type))\r\n\t\t\t\t\tif (corrupt_summary_info)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_struct->AddChecksum(NONAME,Script::GenerateCRC(\"Corrupt\"));\r\n\t\t\t\t\t\tif (Config::GetHardware()==Config::HARDWARE_NGC)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_struct->AddString(\"filename\",GetString(\"NGCDamagedFile\"));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_struct->AddString(\"filename\",GetString(\"DamagedFile\"));\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if (p_file_header->mVersion!=s_get_version_number(file_type))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\t\t\tp_struct->AddChecksum(NONAME,Script::GenerateCRC(\"BadVersion\"));\r\n\t\t\t\t\t\tp_struct->AddString(\"filename\",GetString(\"BadVersionNumber\"));\r\n\t\t\t\t\t\t#else\r\n\t\t\t\t\t\tp_struct->AddChecksum(NONAME,Script::GenerateCRC(\"Corrupt\"));\r\n\t\t\t\t\t\tif (Config::GetHardware()==Config::HARDWARE_NGC)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_struct->AddString(\"filename\",GetString(\"NGCDamagedFile\"));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_struct->AddString(\"filename\",GetString(\"DamagedFile\"));\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Extract the summary info and stick it in the structure.\r\n\t\t\t\t\t\t// This summary info gets printed at the bottom of the files menu when\r\n\t\t\t\t\t\t// the highlight is on the file.\r\n\t\t\t\t\t\t// The summary info is actually in the main structure stored in the file,\r\n\t\t\t\t\t\t// but that would require loading in the whole thing which would take a\r\n\t\t\t\t\t\t// long time.\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t// Have to use a temporary structure because ReadFromBuffer clears the\r\n\t\t\t\t\t\t// passed structure first.\r\n\t\t\t\t\t\tCStruct *p_temp=new CStruct;\r\n\t\t\t\t\t\tReadFromBuffer(p_temp,p_summary_info);\r\n\t\t\t\t\t\tp_struct->AppendStructure(p_temp);\r\n\t\t\t\t\t\tdelete p_temp;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tp_mc_file->Close();\r\n\t\t\t\t\tdelete p_mc_file;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// If the file did not open at all, treat it as corrupted.\r\n\t\t\t\t\tp_struct->AddChecksum(NONAME,Script::GenerateCRC(\"Corrupt\"));\r\n\t\t\t\t\tp_struct->AddString(\"filename\",GetString(\"DamagedFile\"));\r\n\t\t\t\t}\t\r\n\t\t\t\t\t\r\n\t\t\t\tpp_structs[num_files_added++]=p_struct;\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\t\r\n\r\n\tif (got_special_pools)\r\n\t{\r\n\t\t// Note: The pools will contain stuff at this point. The script will delete them\r\n\t\t// when it does its cleanup.\r\n\t\tCComponent::SSwitchToPreviousPool();\r\n\t\tCStruct::SSwitchToPreviousPool();\r\n\t}\r\n\t\r\n\t// The file_list will probably get cleaned up when it goes out of scope, but just to be sure ...\r\n\tfile_list.DestroyAllNodes();\r\n\r\n\tpScript->GetParams()->AddInteger(\"TotalTHPS4FilesOnCard\",total_thps4_files);\r\n\t\r\n\t// Set the FilesLimitReached flag so that the script can determine whether to add\r\n\t// the 'Create New' entry to the files menu.\r\n\tif (total_thps4_files >= MAX_THPS4_FILES_ALLOWED)\r\n\t{\r\n\t\tpScript->GetParams()->AddChecksum(NONAME,0x4eec27b5/*FilesLimitReached*/);\r\n\t}\r\n\t\r\n\t// If files were found, add the array to the script's params.\r\n\tif (num_files_added)\r\n\t{\r\n\t\t// First, sort the array so that the files are definitely in date order (TT6112)\r\n\t\twhile (true)\r\n\t\t{\r\n\t\t\tbool did_a_swap=false;\r\n\t\t\t\r\n\t\t\tfor (int i=0; i<num_files_added-1; ++i)\r\n\t\t\t{\r\n\t\t\t\tif (s_first_date_is_more_recent(pp_structs[i+1],pp_structs[i]))\r\n\t\t\t\t{\r\n\t\t\t\t\tCStruct *p_temp=pp_structs[i];\r\n\t\t\t\t\tpp_structs[i]=pp_structs[i+1];\r\n\t\t\t\t\tpp_structs[i+1]=p_temp;\r\n\t\t\t\t\tdid_a_swap=true;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (!did_a_swap)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t\r\n\t\r\n\t\tCArray *p_directory_listing_array=new CArray;\r\n\t\tp_directory_listing_array->SetSizeAndType(num_files_added,ESYMBOLTYPE_STRUCTURE);\r\n\t\t\r\n\t\tfor (int f=0; f<num_files_added; ++f)\r\n\t\t{\r\n\t\t\tp_directory_listing_array->SetStructure(f,pp_structs[f]);\r\n\t\t}\r\n\t\t\r\n\t\tpScript->GetParams()->AddArrayPointer(\"DirectoryListing\",p_directory_listing_array);\r\n\t\t\r\n\t\t// Note: Not deleting the pp_structs[], cos they've been given to the array.\r\n\t\t// Not deleting p_directory_listing_array, because it's been given to the scripts params.\r\n\t}\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\n// Returns true if the sector size is 8K, false otherwise.\r\n// Needed as part of the GameCube card check procedure to check that the card is not some weird type.\r\n// If it's a PS2 build, it will just return true.\r\nbool ScriptSectorSizeOK(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t#ifdef __PLAT_NGC__\r\n\tSpt::SingletonPtr< Mc::Manager > mc_man;\r\n\tMc::Card* pCard=mc_man->GetCard(0,0);\r\n\tif (pCard)\r\n\t{\r\n\t\tif (pCard->m_sector_size==8192)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\t\t\r\n\treturn false;\r\n\t#else\r\n\treturn true;\r\n\t#endif\r\n}\r\n\r\nbool ScriptCardIsDamaged(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t#ifdef __PLAT_NGC__\r\n\tSpt::SingletonPtr< Mc::Manager > mc_man;\r\n\tMc::Card* pCard=mc_man->GetCard(0,0);\r\n\tif (pCard)\r\n\t{\r\n\t\treturn pCard->m_broken;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (mc_man->GotFatalError())\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\t\r\n\treturn false;\r\n\t#else\r\n\treturn false;\r\n\t#endif\r\n}\r\n\r\nbool ScriptCardIsForeign(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t#ifdef __PLAT_NGC__\r\n\tSpt::SingletonPtr< Mc::Manager > mc_man;\r\n\tMc::Card* pCard=mc_man->GetCard(0,0);\r\n\tif (pCard)\r\n\t{\r\n\t\treturn pCard->IsForeign();\r\n\t}\r\n\treturn false;\r\n\t#else\r\n\treturn false;\r\n\t#endif\r\n}\r\n\r\nbool ScriptBadDevice(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t#ifdef __PLAT_NGC__\r\n\tSpt::SingletonPtr< Mc::Manager > mc_man;\r\n\tMc::Card* pCard=mc_man->GetCard(0,0);\r\n\tif (pCard)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (mc_man->GotWrongDevice())\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\t\r\n\treturn false;\r\n\t#else\r\n\treturn false;\r\n\t#endif\r\n}\r\n\r\n// For debugging, so that we can use the script debugger to view the contents of the save structure that would\r\n// get saved out to the mem card.\r\nbool ScriptGetSaveInfo(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 file_type=0;\r\n\tpParams->GetChecksum(CRCD(0x7321a8d6,\"type\"),&file_type);\r\n\r\n\tScript::CStruct *p_main_structure=new Script::CStruct;\r\n\ts_insert_game_save_info(file_type, p_main_structure);\r\n\tuint32 structure_size=CalculateBufferSize(p_main_structure);\r\n\t\r\n\tScript::CStruct *p_summary_info=new Script::CStruct;\r\n\ts_generate_summary_info(p_summary_info, file_type, p_main_structure);\r\n\tuint32 summary_info_size=CalculateBufferSize(p_summary_info);\r\n\r\n\t\r\n\tpScript->GetParams()->AddInteger(CRCD(0x172c1344,\"MainStructureSize\"),structure_size);\r\n\tpScript->GetParams()->AddInteger(CRCD(0x96635475,\"SummaryInfoSize\"),summary_info_size);\r\n\tpScript->GetParams()->AddInteger(CRCD(0x6afd2f7f,\"MaxSummaryInfoSize\"),MAX_SUMMARY_INFO_SIZE);\r\n\tpScript->GetParams()->AddInteger(CRCD(0xecbb8262,\"TotalSize\"),sizeof(SMcFileHeader)+summary_info_size+structure_size);\r\n\tpScript->GetParams()->AddInteger(CRCD(0xb35eb1d1,\"MaxTotalSize\"),sGetFixedFileSize(file_type));\r\n\t\r\n\tpScript->GetParams()->AddStructurePointer(CRCD(0x703e60ca,\"SummaryInfo\"),p_summary_info);\r\n\tpScript->GetParams()->AddStructurePointer(CRCD(0x671c9c00,\"MainStructure\"),p_main_structure);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n// It is safe to call this multiple times.\r\nbool ScriptCreateTemporaryMemCardPools(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// If the pools exist already, do nothing.\r\n\tCComponent::SSwitchToNextPool();\r\n\tif (CComponent::SPoolExists())\r\n\t{\r\n\t\tCComponent::SSwitchToPreviousPool();\r\n\t\t\r\n\t\tCStruct::SSwitchToNextPool();\t\t\t\t\t\t\t\t \r\n\t\tDbg_MsgAssert(CStruct::SPoolExists(),(\"Expected CStruct pool to exist\"));\r\n\t\tCStruct::SSwitchToPreviousPool();\r\n\r\n\t\tCVector::SSwitchToNextPool();\t\t\t\t\t\t\t\t \r\n\t\tDbg_MsgAssert(CVector::SPoolExists(),(\"Expected CVector pool to exist\"));\r\n\t\tCVector::SSwitchToPreviousPool();\r\n\t\t\r\n\t\treturn true;\r\n\t}\t\r\n\tCComponent::SSwitchToPreviousPool();\r\n\t\r\n#ifdef __PLAT_NGC__\r\n#define NUM_COM 16000\r\n#define NUM_STR 8000\r\n#define NUM_VEC 3000\r\n\r\n#define BUFFER_SIZE ( ( NUM_COM * 16 ) + ( NUM_STR * 8 ) + ( NUM_VEC * 16 ) )\r\n\r\n\t// Time for a hack...\r\n\tg_mc_hack = true;\r\n\r\n\tg_hack_address = NsARAM::alloc( BUFFER_SIZE );\r\n\tif ( g_hack_address )\r\n\t{\r\n\t\tNsDMA::toARAM( g_hack_address, g_p_buffer, BUFFER_SIZE );\r\n\t}\r\n\r\n\tmemset( g_p_buffer, 0, BUFFER_SIZE );\r\n\r\n\tNsBuffer::reset( false );\r\n#else\r\n#define NUM_COM 50000\r\n#define NUM_STR 50000\r\n#define NUM_VEC 10000\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\t\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\r\n\tMem::PushMemProfile(\"Mem card CComponent\");\r\n\tDbg_MsgAssert(CComponent::SGetCurrentPoolIndex()==0,(\"Bad current CComponent pool\"));\r\n\tCComponent::SSwitchToNextPool();\r\n\tCComponent::SCreatePool(NUM_COM, \"Reserve CComponent\");\r\n\tCComponent::SSwitchToPreviousPool();\r\n\tMem::PopMemProfile();\r\n\t\t\t\t\t\t\t\t\t\t \r\n\tMem::PushMemProfile(\"Mem card CStruct\");\r\n\tDbg_MsgAssert(CStruct::SGetCurrentPoolIndex()==0,(\"Bad current CStruct pool\"));\r\n\tCStruct::SSwitchToNextPool();\r\n\tCStruct::SCreatePool(NUM_STR, \"Reserve CStruct\");\r\n\tCStruct::SSwitchToPreviousPool();\r\n\tMem::PopMemProfile();\r\n\t\r\n\t// 12 bytes each  (Actually 16)\r\n\tMem::PushMemProfile(\"Mem card CVector\");\r\n\tDbg_MsgAssert(CVector::SGetCurrentPoolIndex()==0,(\"Bad current CVector pool\"));\r\n\tCVector::SSwitchToNextPool();\r\n\tCVector::SCreatePool(NUM_VEC, \"Reserve CVector\");\r\n\tCVector::SSwitchToPreviousPool();\r\n\tMem::PopMemProfile();\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn true;\r\n}\r\n\r\n// It is safe to call this multiple times.\r\nbool ScriptRemoveTemporaryMemCardPools(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tDbg_MsgAssert(CComponent::SGetCurrentPoolIndex()==0,(\"Bad current CComponent pool\"));\r\n\tCComponent::SSwitchToNextPool();\r\n\tCComponent::SRemovePool(); // Does nothing if the pool does not exist.\r\n\tCComponent::SSwitchToPreviousPool();\r\n\t\r\n\tDbg_MsgAssert(CStruct::SGetCurrentPoolIndex()==0,(\"Bad current CStruct pool\"));\r\n\tCStruct::SSwitchToNextPool();\r\n\tCStruct::SRemovePool();\r\n\tCStruct::SSwitchToPreviousPool();\r\n\t\t\r\n\tDbg_MsgAssert(CVector::SGetCurrentPoolIndex()==0,(\"Bad current CVector pool\"));\r\n\tCVector::SSwitchToNextPool();\r\n\tCVector::SRemovePool();\r\n\tCVector::SSwitchToPreviousPool();\r\n\t\r\n#ifdef __PLAT_NGC__\r\n\tif ( g_hack_address )\r\n\t{\r\n\t\tNsDMA::toMRAM( g_p_buffer, g_hack_address, BUFFER_SIZE );\r\n\t}\r\n\tNsARAM::free( g_hack_address );\r\n\r\n\tg_mc_hack = false;\r\n\tNsBuffer::reset( true );\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\treturn true;\r\n}\r\n\r\nbool ScriptSwitchToTempPoolsIfTheyExist(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tDbg_MsgAssert(CComponent::SGetCurrentPoolIndex()==0 && CStruct::SGetCurrentPoolIndex()==0 && CVector::SGetCurrentPoolIndex()==0, (\"Expected current pools to be 0\"));\r\n\tCComponent::SSwitchToNextPool();\r\n\tCStruct::SSwitchToNextPool();\r\n\tCVector::SSwitchToNextPool();\r\n\tif (CComponent::SPoolExists() && CStruct::SPoolExists() && CVector::SPoolExists())\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\tCComponent::SSwitchToPreviousPool();\r\n\tCStruct::SSwitchToPreviousPool();\r\n\tCVector::SSwitchToPreviousPool();\r\n\r\n\treturn false;\r\n}\r\n\r\nbool ScriptSwitchToRegularPools(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tif (CComponent::SGetCurrentPoolIndex()==0 && \r\n\t\tCStruct::SGetCurrentPoolIndex()==0 &&\r\n\t\tCVector::SGetCurrentPoolIndex()==0)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\t\r\n\tCComponent::SSwitchToPreviousPool();\r\n\tCStruct::SSwitchToPreviousPool();\r\n\tCVector::SSwitchToPreviousPool();\r\n\treturn true;\r\n}\r\n\r\n// Saves any old data file to mem card\r\nbool SaveDataFile(const char *p_name, uint8 *p_data, uint32 size)\r\n{\r\n\tDbg_MsgAssert(p_name,(\"NULL p_name\"));\r\n\tDbg_MsgAssert(p_data,(\"NULL p_data\"));\r\n\r\n\tswitch (Config::GetHardware())\r\n\t{\r\n\t\tcase Config::HARDWARE_PS2:\r\n\t\tcase Config::HARDWARE_PS2_PROVIEW:\r\n\t\tcase Config::HARDWARE_PS2_DEVSYSTEM:\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t\t\tbreak;\r\n\t}\r\n\t\t\t\t\r\n\tif ( Config::GetHardware() != Config::HARDWARE_XBOX)\r\n\t{\r\n\t\tPcm::PauseMusic(true);\r\n\t\tPcm::PauseStream(true);\r\n\t}\r\n\t\r\n\tMc::File* pFile=NULL;\r\n\tchar p_card_file_name[MAX_CARD_FILE_NAME_CHARS+1];\r\n\tconst char *p_header=Config::GetMemCardHeader();\r\n\tchar p_ascii_checksum[20];\r\n\tint suffix=0;\r\n\t#define FULL_NAME_BUF_SIZE 100\r\n\tchar p_full_name[FULL_NAME_BUF_SIZE];\r\n\tbool SavedOK=false;\r\n\tuint32 CardBytesWritten=0;\r\n\r\n\r\n\tMc::Manager * mc_man = Mc::Manager::Instance();\r\n\tMc::Card* p_card=mc_man->GetCard(0,0);\r\n\tif (!p_card)\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\r\n\r\n\twhile (true)\r\n\t{\r\n\t\tDbg_MsgAssert(strlen(p_name)<FULL_NAME_BUF_SIZE-3,(\"p_name too long\"));\r\n\t\tsprintf(p_full_name,\"%s%03d\",p_name,suffix);\r\n\t\ts_generate_ascii_checksum(p_ascii_checksum,p_full_name,0xb010f357/*OptionsAndPros*/);\r\n\t\tsprintf(p_card_file_name,\"/%s%s/%s%s\",\tp_header,p_ascii_checksum,\r\n\t\t\t\t\t\t\t\t\t\t\t\tp_header,p_ascii_checksum);\r\n\t\tDbg_MsgAssert(strlen(p_card_file_name)<MAX_CARD_FILE_NAME_CHARS,(\"Oops\"));\r\n\r\n\t\tpFile = p_card->Open( p_card_file_name, Mc::File::mMODE_READ );\r\n\t\tif (pFile)\r\n\t\t{\r\n\t\t\tpFile->Flush();\r\n\t\t\tpFile->Close();\r\n\t\t\tdelete pFile;\r\n\t\t\tpFile=NULL;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t++suffix;\r\n\t\tDbg_MsgAssert(suffix<1000,(\"Too many files!!\"));\r\n\t}\t\t\r\n\r\n\tprintf (\"Creating mem card file '%s'\\n\",p_full_name);\r\n\t\r\n\tif (!s_make_ps2_dir_and_icons(p_card,\r\n\t\t\t\t\t\t\t\t  0xb010f357, // OptionsAndPros tee hee\r\n\t\t\t\t\t\t\t\t  p_full_name,\r\n\t\t\t\t\t\t\t\t  p_card_file_name,\r\n\t\t\t\t\t\t\t\t  &s_insufficient_space))\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\r\n\r\n\t// Open a file big enough to hold all data\r\n\tpFile=p_card->Open( p_card_file_name, Mc::File::mMODE_WRITE | Mc::File::mMODE_CREATE, s_round_up_to_platforms_block_size(size) );\r\n\ts_insufficient_space=p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE;\r\n\r\n\tif (!pFile)\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\r\n\r\n\tCardBytesWritten=pFile->Write( p_data, size );\r\n\ts_insufficient_space=p_card->GetLastError()==Mc::Card::vINSUFFICIENT_SPACE;\r\n\tif (CardBytesWritten!=size)\r\n\t{\r\n\t\tgoto ERROR;\r\n\t}\r\n\r\n\tSavedOK=true;\r\n\t\r\nERROR:\t\r\n\tif (pFile)\r\n\t{\r\n\t\tif (!pFile->Flush())\r\n\t\t{\r\n\t\t\tSavedOK=false;\r\n\t\t}\t\r\n\t\tif (!pFile->Close())\r\n\t\t{\r\n\t\t\tSavedOK=false;\r\n\t\t}\t\r\n\t\tdelete pFile;\r\n\t}\t\r\n\r\n\tif ( Config::GetHardware() != Config::HARDWARE_XBOX)\r\n\t{\r\n\t\tPcm::PauseMusic( -1 );\r\n\t\tPcm::PauseStream( -1 );\r\n\t}\r\n\t\t\r\n\treturn SavedOK;\r\n}\r\n\r\n\r\n\r\n// Load len bytes of any old data file to mem card to p_data\r\nbool LoadDataFile(const char *p_name, uint8 *p_data, uint32 size)\r\n{\r\n\tDbg_MsgAssert(p_name,(\"NULL p_name\"));\r\n\tDbg_MsgAssert(p_data,(\"NULL p_data\"));\r\n\r\n\tswitch (Config::GetHardware())\r\n\t{\r\n\t\tcase Config::HARDWARE_PS2:\r\n\t\tcase Config::HARDWARE_PS2_PROVIEW:\r\n\t\tcase Config::HARDWARE_PS2_DEVSYSTEM:\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t\t\tbreak;\r\n\t}\r\n\t\t\t\t\r\n\tif ( Config::GetHardware() != Config::HARDWARE_XBOX)\r\n\t{\r\n\t\tPcm::PauseMusic(true);\r\n\t\tPcm::PauseStream(true);\r\n\t}\r\n\t\r\n\tMc::File* pFile=NULL;\r\n\tchar p_card_file_name[MAX_CARD_FILE_NAME_CHARS+1];\r\n\tconst char *p_header=Config::GetMemCardHeader();\r\n\tchar p_ascii_checksum[20];\r\n\t#define FULL_NAME_BUF_SIZE 100\r\n\tchar p_full_name[FULL_NAME_BUF_SIZE];\r\n\r\n\tMc::Manager * mc_man = Mc::Manager::Instance();\r\n\tMc::Card* p_card=mc_man->GetCard(0,0);\r\n\tif (!p_card)\r\n\t{\r\n\t\treturn false;;\r\n\t}\r\n\r\n\tDbg_MsgAssert(strlen(p_name)<FULL_NAME_BUF_SIZE-3,(\"p_name too long\"));\r\n\tsprintf(p_full_name,\"%s\",p_name);\r\n\ts_generate_ascii_checksum(p_ascii_checksum,p_full_name,0xb010f357/*OptionsAndPros*/);\r\n\tsprintf(p_card_file_name,\"/%s%s/%s%s\",\tp_header,p_ascii_checksum,\r\n\t\t\t\t\t\t\t\t\t\t\tp_header,p_ascii_checksum);\r\n\tDbg_MsgAssert(strlen(p_card_file_name)<MAX_CARD_FILE_NAME_CHARS,(\"Oops\"));\r\n\r\n\tpFile = p_card->Open( p_card_file_name, Mc::File::mMODE_READ );\r\n\tif (pFile)\r\n\t{\r\n\t\tprintf (\"Loading From Memory Card\\n\");\r\n\t\tpFile->Flush();\r\n\t\tpFile->Seek( 0 ,Mc::File::BASE_START);\r\n\t\tpFile->Read(p_data,size);\r\n\t\tpFile->Flush();\r\n\t\tpFile->Close();\r\n\t\tdelete pFile;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n} // namespace CFuncs\r\n\r\n"
  },
  {
    "path": "Code/Sk/Scripting/mcfuncs.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tScripting\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmcfuncs.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t06/10/2002\t-\tksh\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SCRIPTING_MCFUNCS_H\r\n#define\t__SCRIPTING_MCFUNCS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n};\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace CFuncs\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool ScriptGetMostRecentSave(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetMemCardSpaceAvailable(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetMemCardSpaceRequired(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptMemCardFileExists(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptDeleteMemCardFile(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptFormatCard(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCardIsInSlot(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCardIsFormatted(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSaveFailedDueToInsufficientSpace(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetSummaryInfo(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSaveToMemoryCard(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetSectionsToApplyWhenLoading(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptLoadFromMemoryCard(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptLoadedCustomSkater(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetMemCardDataForUpload(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptClearMemCardDataForUpload(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptNeedToLoadReplayBuffer(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptLoadReplayData(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetMemCardDirectoryListing(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetMaxTHPS4FilesAllowed(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSectorSizeOK(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCardIsDamaged(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCardIsForeign(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptBadDevice(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptGetSaveInfo(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCreateTemporaryMemCardPools(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRemoveTemporaryMemCardPools(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSwitchToTempPoolsIfTheyExist(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSwitchToRegularPools(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\n\r\nbool SaveDataFile(const char *p_name, uint8 *p_data, uint32 size);\r\nbool LoadDataFile(const char *p_name, uint8 *p_data, uint32 size);\r\n\r\nvoid SetVaultData(uint8 *p_data, uint32 type);\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace CFuncs\r\n\r\n#endif\t// __SCRIPTING_MCFUNCS_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Scripting/nodearray.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// nodearray.cpp\t\tKSH 7 Nov 2001\r\n//\r\n// Functions related to the NodeArray, such as the node name hash table,\r\n// prefix info for rapidly finding all the nodes with a given prefix,\r\n// and utility functions for getting the links and stuff.\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <sk/scripting/nodearray.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/tokens.h>\r\n#include <gel/scripting/parse.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/scriptcache.h>\r\n#include <core/crc.h> // For Crc::GenerateCRCFromString\r\n#include <core/math.h>\r\n#include <sk/components/goaleditorcomponent.h>\r\n\r\nnamespace SkateScript\r\n{\r\nusing namespace Script;\r\n\r\n////////////////////////////////////////////////////////////////////\r\n//\r\n// Node name hash table stuff, for speeding up FindNamedNode\r\n//\r\n////////////////////////////////////////////////////////////////////\r\n\r\n#if\t1//def __PLAT_NGC__\r\n\r\n// Gets called from SkateScript::Init in sk\\scripting\\init.cpp\r\nvoid InitNodeNameHashTable()\r\n{\r\n}\r\n\r\n// Resets the hash table, and deletes any extra entries created.\r\n// This currently gets called from the rwviewer cleanup function.\r\nvoid ClearNodeNameHashTable()\r\n{\r\n}\r\n\r\n// Given that a new NodeArray symbol has got loaded due to the loading of a qb containing it,\r\n// this will generate the node name hash table.\r\n\r\n// More efficient hash table.\r\n#define HASH_SIZE 16384\r\n#define HASH_MASK (HASH_SIZE-1)\r\n\r\nshort node_hash[HASH_SIZE];\r\n\r\nvoid CreateNodeNameHashTable()\r\n{\r\n\tfor ( int lp = 0; lp < HASH_SIZE; lp++ )\r\n\t{\r\n\t\tnode_hash[lp] = -1;\r\n\t}\r\n\t// Get the NodeArray\r\n\tCArray *p_node_array=GetArray(0xc472ecc5/*NodeArray*/);\r\n\tDbg_MsgAssert(p_node_array,(\"CreateNodeNameHashTable could not find NodeArray\"));\r\n\r\n\t// Scan through each node, getting it's name, and if it has a name add it in to the hash table.\t\r\n\tfor (uint32 i=0; i<p_node_array->GetSize(); ++i)\r\n\t{\r\n\t\tCStruct *p_node=p_node_array->GetStructure(i);\r\n\t\t\r\n\t\tuint32 name_checksum=0;\r\n\t\tif (p_node->GetChecksum(\"Name\",&name_checksum))\r\n\t\t{\r\n\t\t\tuint16 hash = (uint16)(name_checksum & HASH_MASK );\r\n\r\n\t\t\twhile ( node_hash[hash] != -1 )\r\n\t\t\t{\r\n\t\t\t\thash++;\r\n\t\t\t\thash &= HASH_MASK;\r\n\t\t\t}\r\n\t\t\tnode_hash[hash] = i;\r\n\t\t}\r\n\t}\r\n}\r\n\t\r\n// Searches the node array for a node whose Name is the passed checksum.\r\nint FindNamedNode(uint32 checksum, bool assert)\r\n{\r\n\t// Get the NodeArray\r\n\tCArray *p_node_array=GetArray(CRCD(0xc472ecc5,\"NodeArray\"));\r\n\tDbg_MsgAssert(p_node_array,(\"CreateNodeNameHashTable could not find NodeArray\"));\r\n\r\n\t// Added 9/18/03 for THUG submission. If the node array doesn't exist, interpret that\r\n\t// as just another condition of the node not existing\r\n\tif( p_node_array == NULL )\r\n\t{\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tuint16 hash = (uint16)(checksum & HASH_MASK );\r\n\r\n\twhile ( node_hash[hash] != -1 )\r\n\t{\r\n\t\tCStruct *p_node=p_node_array->GetStructure(node_hash[hash]);\r\n\t\tif ( assert ) Dbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\t\t\r\n\t\tuint32 name_checksum=0;\r\n\t\tif (p_node->GetChecksum(CRCD(0xa1dc81f9,\"Name\"),&name_checksum))\r\n\t\t{\r\n\t\t\tif ( name_checksum == checksum )\r\n\t\t\t{\r\n\t\t\t\treturn node_hash[hash];\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\thash++;\r\n\t\thash &= HASH_MASK;\r\n\t}\r\n\r\n//\t// Scan through each node, getting it's name, and if it has a name add it in to the hash table.\t\r\n//\tfor (uint32 i=0; i<p_node_array->GetSize(); ++i)\r\n//\t{\r\n//\t\tCStruct *p_node=p_node_array->GetStructure(i);\r\n//\t\tif ( assert ) Dbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n//\t\t\r\n//\t\tuint32 name_checksum=0;\r\n//\t\tif (p_node->GetChecksum(\"Name\",&name_checksum))\r\n//\t\t{\r\n//\t\t\tif ( name_checksum == checksum )\r\n//\t\t\t{\r\n//\t\t\t\treturn i;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n\treturn -1;\r\n}\r\n\r\nint FindNamedNode(const char *p_name)\r\n{\r\n\treturn FindNamedNode(Crc::GenerateCRCFromString(p_name));\r\n}\r\n\r\n// Added for use by the NodeExists script function\r\nbool NodeExists(uint32 checksum)\r\n{\r\n\treturn ( FindNamedNode( checksum, true ) == -1 ) ? false : true;\r\n\r\n//\t// Get the NodeArray\r\n//\tCArray *p_node_array=GetArray(0xc472ecc5/*NodeArray*/);\r\n//\tDbg_MsgAssert(p_node_array,(\"CreateNodeNameHashTable could not find NodeArray\"));\r\n//\r\n//\t// Scan through each node, getting it's name, and if it has a name add it in to the hash table.\t\r\n//\tfor (uint32 i=0; i<p_node_array->GetSize(); ++i)\r\n//\t{\r\n//\t\tCStruct *p_node=p_node_array->GetStructure(i);\r\n//\t\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n//\t\t\r\n//\t\tuint32 name_checksum=0;\r\n//\t\tif (p_node->GetChecksum(\"Name\",&name_checksum))\r\n//\t\t{\r\n//\t\t\tif ( name_checksum == checksum )\r\n//\t\t\t{\r\n//\t\t\t\treturn true;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\treturn false;\r\n}\r\n\r\n#else\r\n\r\n#define\t__OLD_HASH_TABLE__  0\r\n#define NODE_NAME_HASHBITS 13\r\n\r\n#if __OLD_HASH_TABLE__\r\n#define NODE_NAME_HASH_SIZE ((1<<NODE_NAME_HASHBITS))\r\n#else\r\n#define NODE_NAME_HASH_SIZE ((1<<NODE_NAME_HASHBITS) + 100)\r\n#endif\r\n\r\nstruct SNodeNameHashEntry\r\n{\r\n\tuint32 mNameChecksum;\r\n\tuint32 mNodeIndex;\r\n\t#if\t__OLD_HASH_TABLE__\r\n\tSNodeNameHashEntry *mpNext;\r\n\t#endif\t\r\n};\r\n\r\nstatic bool s_node_name_hash_table_initialised=false;\r\nstatic SNodeNameHashEntry sp_node_name_hash_table[NODE_NAME_HASH_SIZE];\r\n\r\n// Gets called from SkateScript::Init in sk\\scripting\\init.cpp\r\nvoid InitNodeNameHashTable()\r\n{\r\n\tprintf(\"InitNodeNameHashTable ...\\n\");\r\n\tfor (int i=0; i<(NODE_NAME_HASH_SIZE); ++i)\r\n\t{\r\n\t\tsp_node_name_hash_table[i].mNameChecksum=0;\r\n\t\tsp_node_name_hash_table[i].mNodeIndex=0;\r\n\t#if\t__OLD_HASH_TABLE__\r\n\t\tsp_node_name_hash_table[i].mpNext=NULL;\r\n\t#endif\r\n\t}\t\r\n\ts_node_name_hash_table_initialised=true;\r\n}\r\n\r\n// Resets the hash table, and deletes any extra entries created.\r\n// This currently gets called from the rwviewer cleanup function.\r\nvoid ClearNodeNameHashTable()\r\n{\r\n\tDbg_MsgAssert(s_node_name_hash_table_initialised,(\"Node name hash table not initialised\"));\r\n\tfor (int i=0; i<(NODE_NAME_HASH_SIZE); ++i)\r\n\t{\r\n\t\t#if\t__OLD_HASH_TABLE__\r\n\t\t\tSNodeNameHashEntry *p_entry=sp_node_name_hash_table[i].mpNext;\r\n\t\t\t// Delete any extra entries.\r\n\t\t\twhile (p_entry)\r\n\t\t\t{\r\n\t\t\t\tSNodeNameHashEntry *p_next=p_entry->mpNext;\r\n\t\t\t\tMem::Free(p_entry);\r\n\t\t\t\tp_entry=p_next;\r\n\t\t\t}\r\n\t\t\tsp_node_name_hash_table[i].mpNext=NULL;\t\r\n\t\t#endif\t\t\t\t\t\r\n\t\tsp_node_name_hash_table[i].mNameChecksum=0;\r\n\t\tsp_node_name_hash_table[i].mNodeIndex=0;\r\n\t}\t\r\n}\r\n\r\n// Given that a new NodeArray symbol has got loaded due to the loading of a qb containing it,\r\n// this will generate the node name hash table.\r\nvoid CreateNodeNameHashTable()\r\n{\r\n\tDbg_MsgAssert(s_node_name_hash_table_initialised,(\"Node name hash table not initialised\"));\r\n\t\r\n\t// Make sure the old one is cleared.\r\n\tClearNodeNameHashTable();\r\n\r\n\t// Get the NodeArray\r\n\tCArray *p_node_array=GetArray(0xc472ecc5/*NodeArray*/);\r\n\tDbg_MsgAssert(p_node_array,(\"CreateNodeNameHashTable could not find NodeArray\"));\r\n\r\n\t// Make sure we're using the script heap, cos the hash table is going to hang around\r\n\t// for the duration of the level.\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());\r\n\r\n\t// Scan through each node, getting it's name, and if it has a name add it in to the hash table.\t\r\n\tfor (uint32 i=0; i<p_node_array->GetSize(); ++i)\r\n\t{\r\n\t\tCStruct *p_node=p_node_array->GetStructure(i);\r\n\t\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\t\t\r\n\t\tuint32 name_checksum=0;\r\n\t\tif (p_node->GetChecksum(\"Name\",&name_checksum))\r\n\t\t{\r\n\t\t\t// Node i has name name_checksum, so add it in to the hash table.\r\n\t\t\t\r\n\t\t\t// A checksum of zero is used to indicate an empty hash table entry,\r\n\t\t\t// so check that the name checksum is not zero by chance.\r\n\t\t\tDbg_MsgAssert(name_checksum,(\"Node has zero name checksum ?\"));\r\n\t\t\t\r\n\t\t\tSNodeNameHashEntry *p_entry=&sp_node_name_hash_table[name_checksum&((1<<NODE_NAME_HASHBITS)-1)];\r\n\t\t\t// p_entry is now the entry in the hash table array indexed by the lower bits of the checksum.\r\n\t\t\t\r\n\t\t\t#if\t__OLD_HASH_TABLE__\r\n\t\t\tif (p_entry->mNameChecksum)\r\n\t\t\t{\r\n\t\t\t\t// p_entry is already occupied, so skip to the end of the list that starts at p_entry.\r\n\t\t\t\twhile (p_entry->mpNext)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_entry=p_entry->mpNext;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// p_entry is now the last entry in the list.\r\n\t\t\t\t\r\n\t\t\t\t// Create a new entry and fill it in.\r\n\t\t\t\tSNodeNameHashEntry *p_new=(SNodeNameHashEntry*)Mem::Malloc(sizeof(SNodeNameHashEntry));\r\n\t\t\t\tp_new->mNameChecksum=name_checksum;\r\n\t\t\t\tp_new->mNodeIndex=i;\r\n\t\t\t\tp_new->mpNext=NULL;\r\n\t\t\t\t\r\n\t\t\t\t// Tag it onto the end of the list.\r\n\t\t\t\tp_entry->mpNext=p_new;\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// p_entry is free, so stick the info in there.\r\n\t\t\t\tp_entry->mNameChecksum=name_checksum;\r\n\t\t\t\tp_entry->mNodeIndex=i;\r\n\t\t\t\t// Quick check for leaks.\r\n\t\t\t\tDbg_MsgAssert(p_entry->mpNext==NULL,(\"p_entry->mpNext not NULL ??\"));\r\n\t\t\t\tp_entry->mpNext=NULL;\r\n\t\t\t}\r\n\t\t\t#else\r\n\t\t\t// just skip forward until we find an empty entry\r\n\t\t\twhile (p_entry->mNameChecksum)\r\n\t\t\t{\r\n\t\t\t\tp_entry++;\r\n\t\t\t\t// note in the following assertion we leave one entry to guarentee we have\r\n\t\t\t\t// a zero entry roadblock to stop searches\r\n\t\t\t\t// otherwise we have a slight possibility of very obscure bugs\r\n\t\t\t\tDbg_MsgAssert(p_entry < &sp_node_name_hash_table[NODE_NAME_HASH_SIZE-1],(\"Hash table overflow\"));\r\n\t\t\t}\r\n\t\t\tp_entry->mNameChecksum=name_checksum;\r\n\t\t\tp_entry->mNodeIndex=i;\r\n\t\t\t#endif\r\n\t\r\n\t\t}\r\n\t}\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\t\r\n// Searches the node array for a node whose Name is the passed checksum.\r\nint FindNamedNode(uint32 checksum, bool assert)\r\n{\r\n\t// TODO: Fix bug where this returns 0 when a checksum of 0 is passed. It should\r\n\t// not find a node in that case.\r\n\t\r\n\tDbg_MsgAssert(s_node_name_hash_table_initialised,(\"Node name hash table not initialised\"));\r\n\r\n\tSNodeNameHashEntry *p_entry=&sp_node_name_hash_table[checksum&((1<<NODE_NAME_HASHBITS)-1)];\r\n\t\r\n\t#if\t__OLD_HASH_TABLE__\r\n\twhile (p_entry && p_entry->mNameChecksum!=checksum)\r\n\t{\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\r\n\t\r\n\tif (assert)\r\n\t{\r\n\t\tDbg_MsgAssert(p_entry,(\"No node with name %s found.\",FindChecksumName(checksum)));\r\n\t}\r\n\tif (!p_entry)\r\n\t{\r\n\t\treturn -1;\r\n\t}\r\n\t#else\r\n\twhile (p_entry->mNameChecksum && p_entry->mNameChecksum!=checksum)\r\n\t{\r\n\t\tp_entry++;\r\n\t}\r\n\t\r\n\tif (assert)\r\n\t{\r\n\t\tDbg_MsgAssert(p_entry->mNameChecksum,(\"No node with name %s found.\",FindChecksumName(checksum)));\r\n\t}\r\n\t\r\n\tif (!p_entry->mNameChecksum)\r\n\t{\r\n\t\treturn -1;\r\n\t}\r\n\t#endif\t\t\r\n\t\r\n\treturn p_entry->mNodeIndex;\r\n}\r\n\r\nint FindNamedNode(const char *p_name)\r\n{\r\n\treturn FindNamedNode(Crc::GenerateCRCFromString(p_name));\r\n}\r\n\r\n// Added for use by the NodeExists script function\r\nbool NodeExists(uint32 checksum)\r\n{\r\n\tDbg_MsgAssert(s_node_name_hash_table_initialised,(\"Node name hash table not initialised\"));\r\n\r\n\tSNodeNameHashEntry *p_entry=&sp_node_name_hash_table[checksum&((1<<NODE_NAME_HASHBITS)-1)];\r\n\t#if\t__OLD_HASH_TABLE__\r\n\twhile (p_entry && p_entry->mNameChecksum!=checksum)\r\n\t{\r\n\t\tp_entry=p_entry->mpNext;\r\n\t}\r\n\tif (p_entry)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t#else\r\n\twhile (p_entry->mNameChecksum && p_entry->mNameChecksum!=checksum)\r\n\t{\r\n\t\tp_entry=p_entry++;\r\n\t}\r\n\tif (p_entry->mNameChecksum)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t#endif\r\n\t\r\n\treturn false;\r\n}\r\n\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n////////////////////////////////////////////////////////////////////\r\n//\r\n// Node name prefix stuff.\r\n//\r\n////////////////////////////////////////////////////////////////////\r\n\r\n// Linked list stuff, used when generating the node lists.\r\n// These only exist temporarily in memory.\r\nstruct STempNode\r\n{\r\n\tint mNodeIndex;\r\n\tSTempNode *mpNext;\r\n};\r\n\r\n// MEMOPT 800K TEMP Size of temporary buffer used when generating prefix info.\r\n#define NUM_TEMP_NODES 120000\r\nstatic STempNode *sp_temp_nodes=NULL;\r\nstatic STempNode *sp_free_temp_nodes=NULL;\r\n\r\n// The lookup table, which exists in memory for the duration of the level.\r\nstruct SPrefixLookup\r\n{\r\n\t// Checksum of the prefix string\r\n\tuint32 mChecksum;\r\n\t\r\n\t// Pointer to the list of node indices of the nodes that have this prefix.\r\n\tunion\r\n\t{\r\n\t\t// Points to somewhere inside sp_node_list_buffer\r\n\t\t// pNodeList[0] contains the number of nodes.\r\n\t\tuint16 *mpNodeList;\r\n\t\t\r\n\t\t// Points to a temporary linked list of nodes, which is used for speed when generating the prefix info.\r\n\t\t// (Uses up too much memory to keep in memory all the time)\r\n\t\tSTempNode *mpTempNodesHeadPointer;\r\n\t};\t\r\n};\r\n\r\n// MEMOPT 80K PERM An array of SPrefixLookup's, one for each possible prefix.\r\n// This array is kept in order of checksum, smallest checksum first, to enable quick searching\r\n// using a binary search.\r\n#define MAX_PREFIX_LOOKUPS 13000\r\nstatic SPrefixLookup sp_prefix_lookups[MAX_PREFIX_LOOKUPS];\r\nstatic uint32 s_num_prefix_lookups=0;\r\n\r\n// MEMOPT 200K PERM Big array of uint16's for holding the node lists.\r\n#define NODE_LIST_BUFFER_SIZE 121000\r\nstatic uint32 s_node_list_buffer_used=0;\r\nstatic uint16 sp_node_list_buffer[NODE_LIST_BUFFER_SIZE];\r\n\r\n// Does a binary search of the lookup table, and returns the index of the entry \r\n// that has the passed checksum.\r\n// If there is no matching entry, it will return the index of the entry with the next smallest\r\n// checksum.\r\n// If there is no matching entry, and the passed checksum is smaller than the smallest checksum in the\r\n// table, then it will return 0.\r\nstatic uint32 sFindPrefixLookup(uint32 checksum)\r\n{\r\n\tDbg_MsgAssert(s_num_prefix_lookups,(\"Zero s_num_prefix_lookups\"));\r\n\tuint32 bottom=0;\r\n\tuint32 top=s_num_prefix_lookups-1;\r\n\tuint32 middle=(bottom+top)>>1;\r\n\t\r\n\twhile (bottom!=middle)\r\n\t{\r\n\t\tuint32 ch=sp_prefix_lookups[middle].mChecksum;\r\n\t\t\r\n\t\tif (ch==checksum)\r\n\t\t{\r\n\t\t\treturn middle;\r\n\t\t}\r\n\t\telse if (checksum<ch)\r\n\t\t{\r\n\t\t\ttop=middle;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbottom=middle;\r\n\t\t}\r\n\t\tmiddle=(bottom+top)>>1;\t\t\r\n\t}\t\t\r\n\tif (sp_prefix_lookups[top].mChecksum > checksum)\r\n\t{\r\n\t\treturn bottom;\r\n\t}\t\r\n\treturn top;\r\n}\r\n\r\n// Creates the big temporary array of nodes.\r\nstatic void sCreateTempNodes()\r\n{\r\n\tDbg_MsgAssert(sp_temp_nodes==NULL,(\"sp_temp_nodes not NULL ?\"));\r\n\tsp_temp_nodes=(STempNode*)Mem::Malloc(NUM_TEMP_NODES*sizeof(STempNode));\r\n\tDbg_MsgAssert(sp_temp_nodes,(\"Could not allocate sp_temp_nodes\"));\r\n\t\r\n\t// Link them all into a free list.\r\n\tfor (int i=0; i<NUM_TEMP_NODES-1; ++i)\r\n\t{\r\n\t\tsp_temp_nodes[i].mpNext=&sp_temp_nodes[i+1];\r\n\t}\r\n\tsp_temp_nodes[NUM_TEMP_NODES-1].mpNext=NULL;\r\n\t\r\n\tsp_free_temp_nodes=sp_temp_nodes;\r\n}\r\n\r\n// Deletes the big temporary array of nodes.\r\nstatic void sDeleteTempNodes()\r\n{\r\n    if (sp_temp_nodes)\r\n\t{\r\n\t\tMem::Free(sp_temp_nodes);\r\n\t\tsp_temp_nodes=NULL;\r\n\t\tsp_free_temp_nodes=NULL;\r\n\t}\t\r\n}\r\n\r\n// Grabs a new node out of the array.\r\nstatic STempNode *sNewTempNode()\r\n{\r\n\tDbg_MsgAssert(sp_free_temp_nodes,(\"Ran out of temp nodes when generating prefix info\"));\r\n\tSTempNode *p_new=sp_free_temp_nodes;\r\n\tsp_free_temp_nodes=sp_free_temp_nodes->mpNext;\r\n\treturn p_new;\r\n}\r\n\r\n// Converts the linked lists of nodes into simple arrays, kept in the sp_node_list_buffer static array.\r\n// Uses up less memory. Also means the rest of the game code that calls GetPrefixInfo does not have\r\n// to be changed.\r\nstatic void sConvertTempNodes()\r\n{\r\n\tDbg_MsgAssert(s_node_list_buffer_used==0,(\"Expected s_node_list_buffer_used to be 0\"));\r\n\tuint16 *p_buf=sp_node_list_buffer;\r\n\t\r\n\t// For each prefix in the lookup table ...\r\n\tfor (uint32 i=0; i<s_num_prefix_lookups; ++i)\r\n\t{\r\n\t\t// Get the linked list.\r\n\t\tSTempNode *p_first=sp_prefix_lookups[i].mpTempNodesHeadPointer;\r\n\t\tDbg_MsgAssert(p_first,(\"NULL p_first\"));\r\n\t\t\r\n\t\t// Count how many nodes are in it.\r\n\t\tint count=0;\r\n\t\tSTempNode *p_node=p_first;\r\n\t\twhile (p_node)\r\n\t\t{\r\n\t\t\t++count;\r\n\t\t\tp_node=p_node->mpNext;\r\n\t\t}\r\n\t\t\r\n\t\t// Check there is enough space to copy the node list into.\r\n\t\tDbg_MsgAssert(s_node_list_buffer_used+1+count<=NODE_LIST_BUFFER_SIZE,(\"Node list buffer overflow\"));\r\n\r\n\t\t// Make the prefix entry now point to the simple array.\r\n\t\tsp_prefix_lookups[i].mpNodeList=p_buf;\r\n\t\t\r\n\t\t// First entry is the count.\t\t\r\n\t\t*p_buf++=count;\r\n\t\t// Copy in all the node indices.\r\n\t\tp_node=p_first;\r\n\t\twhile (p_node)\r\n\t\t{\r\n\t\t\t*p_buf++=p_node->mNodeIndex;\r\n\t\t\tp_node=p_node->mpNext;\r\n\t\t}\r\n\t\t\r\n\t\t// Update the space used. The +1 is for the count.\r\n\t\ts_node_list_buffer_used+=1+count;\r\n\t}\t\r\n//\tDbg_MsgAssert(0,(\"buffer = %d\\n\",s_node_list_buffer_used));\t\r\n}\r\n\r\n// Adds a new node index to a particular prefix checksum's entry in the lookup table.\r\nstatic void sAddNewPrefix(uint32 checksum, int nodeIndex)\r\n{\r\n\t// sFindPrefixLookup will assert if s_num_prefix_lookups is zero, so do this\r\n\t// as a special case for the very first one added.\r\n\tif (s_num_prefix_lookups==0)\r\n\t{\r\n\t\tSTempNode *p_new=sNewTempNode();\r\n\t\tp_new->mNodeIndex=nodeIndex;\r\n\t\tp_new->mpNext=NULL;\r\n\t\t\r\n\t\t// Stick it in at index 0. The array will be maintained as a sorted\r\n\t\t// array from now on.\r\n\t\tsp_prefix_lookups[0].mChecksum=checksum;\r\n\t\tsp_prefix_lookups[0].mpTempNodesHeadPointer=p_new;\r\n\t\t\r\n\t\t++s_num_prefix_lookups;\r\n\t\t// All done.\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\t// Look up the checksum, which may not be there.\r\n\tint index=sFindPrefixLookup(checksum);\r\n\tuint32 ch=sp_prefix_lookups[index].mChecksum;\r\n\t// ch may or may not be checksum. If it isn't, it will either be the next smallest one in the\r\n\t// array, or it will be the checksum at index 0 in the case of checksum being smaller than all of them.\r\n\t\r\n\tif (ch==checksum)\r\n\t{\r\n\t\t// This prefix is already in the array, so just have to add the new node index to\r\n\t\t// its list.\r\n\t\t\r\n\t\tSTempNode *p_new=sNewTempNode();\r\n\t\tp_new->mNodeIndex=nodeIndex;\r\n\t\tp_new->mpNext=sp_prefix_lookups[index].mpTempNodesHeadPointer;\r\n\t\t\r\n\t\tsp_prefix_lookups[index].mpTempNodesHeadPointer=p_new;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// The prefix is not in the table, so we have to add it.\r\n\t\t\r\n\t\tDbg_MsgAssert(s_num_prefix_lookups<MAX_PREFIX_LOOKUPS,(\"Too many prefixes\"));\r\n\t\t\r\n\t\tif (checksum>ch)\r\n\t\t{\r\n\t\t\t// The above if will mostly be true, because usually Ch will be the next smaller checksum\r\n\t\t\t// in the table. Hence we increment index so that all the checksums above ch get shifted up,\r\n\t\t\t// so that the new checksum can be inserted at index, maintaining the sort order.\r\n\t\t\t++index;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// The above if will be false in the case of checksum being smaller than all the current checksums\r\n\t\t\t// in the table. In this case, all the checksums need to be shifted up and checksum inserted at the\r\n\t\t\t// bottom, so index should be zero here.\r\n\t\t\tDbg_MsgAssert(index==0,(\"index not zero ?\"));\r\n\t\t}\t\t\r\n\r\n\t\t// Shift everything up one so that the new checksum can be inserted.\r\n\t\tfor (int i=s_num_prefix_lookups; i>index; --i)\r\n\t\t{\r\n\t\t\tsp_prefix_lookups[i]=sp_prefix_lookups[i-1];\r\n\t\t}\r\n\t\t\r\n\t\t// Insert the new checksum, and make a new list for it with just one entry at the moment.\r\n\t\tSTempNode *p_new=sNewTempNode();\r\n\t\tp_new->mNodeIndex=nodeIndex;\r\n\t\tp_new->mpNext=NULL;\r\n\t\t\r\n\t\tsp_prefix_lookups[index].mChecksum=checksum;\r\n\t\tsp_prefix_lookups[index].mpTempNodesHeadPointer=p_new;\r\n\t\t\r\n\t\t// Increment the count.\r\n\t\t++s_num_prefix_lookups;\r\n\t}\r\n}\r\n\r\nvoid DeletePrefixInfo()\r\n{\r\n\t// Just to be sure.\r\n\tsDeleteTempNodes();\r\n\t\r\n\ts_node_list_buffer_used=0;\r\n\ts_num_prefix_lookups=0;\r\n}\t\r\n\r\n// This is called from LoadQB if the QB contains a NodeArray.\t\r\nvoid GeneratePrefixInfo()\r\n{\r\n\tDeletePrefixInfo();\r\n\t\r\n\t// Create the temporary array of nodes used to make linked lists in sAddNewPrefix, for speed.\r\n\tsCreateTempNodes();\r\n\r\n\t// Scan through all the nodes, look up their names, and add all their possible\r\n\t// prefixes to the lookup table.\r\n\tCArray *p_node_array=GetArray(0xc472ecc5/*NodeArray*/);\r\n\tDbg_MsgAssert(p_node_array,(\"NodeArray not found\"));\r\n\tfor (uint32 i=0; i<p_node_array->GetSize(); ++i)\r\n\t{\r\n\t\tCStruct *p_node=p_node_array->GetStructure(i);\r\n\t\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\t\tuint32 name_checksum=0;\r\n\t\tp_node->GetChecksum(\"Name\",&name_checksum);\r\n\t\t\r\n\t\tif (name_checksum)\r\n\t\t{\r\n\t\t\t// Search the hash table for the name.\r\n\t\t\tconst char *p_name=GetChecksumNameFromLastQB(name_checksum);\r\n\t\t\tif (p_name)\r\n\t\t\t{\r\n\t\t\t\t// Add all the possible prefixes to the lookup table.\r\n\t\t\t\tint string_length=strlen(p_name);\r\n\t\t\t\tfor (int j=1; j<=string_length; ++j)\r\n\t\t\t\t{\r\n\t\t\t\t\tsAddNewPrefix(Crc::GenerateCRC(p_name,j),i);\r\n\t\t\t\t}\t\t\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n\r\n\t// Move the info in the linked lists into the more memory efficient static array.\r\n\tsConvertTempNodes();\r\n\t// Remove the temporary stuff.\r\n\tsDeleteTempNodes();\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\t// Quick check to make sure the lookup table seems right.\r\n\tif (s_num_prefix_lookups)\r\n\t{\r\n\t\tfor (uint32 i=0; i<s_num_prefix_lookups-1; ++i)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(sp_prefix_lookups[i].mChecksum<sp_prefix_lookups[i+1].mChecksum,(\"Out of order\"));\r\n\t\t}\t\r\n\t}\t\r\n\t#endif\t\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n//\r\n// GetPrefixedNodes function.\r\n// This will return an array of node indices, which are all the nodes\r\n// whose names are prefixed with the passed string.\r\n// For example, if passed \"a\", it will return all nodes whose names\r\n// begin with 'a'.\r\n// If passed \"TRG_\" it will return all nodes beginning with TRG_, etc.\r\n// It is not case sensitive.\r\n//\r\n//\r\n// It returns an array of uint16's, which are the node numbers of\r\n// the matching nodes.\r\n// It loads the size of the array into the passed p_numMatches.\r\n//\r\n// Note: It will never return NULL, but p_numMatches may contain zero.\r\n//\r\n////////////////////////////////////////////////////////////////////\r\nconst uint16 *GetPrefixedNodes(uint32 checksum, uint16 *p_numMatches)\r\n{\r\n\tstatic uint16 s_dummy=0;\r\n\t\t\r\n\tif (s_num_prefix_lookups)\r\n\t{\r\n\t\t// Look it up using a binary search.\r\n\t\tuint32 index=sFindPrefixLookup(checksum);\r\n\t\tif (sp_prefix_lookups[index].mChecksum==checksum)\r\n\t\t{\r\n\t\t\t// It matches, so return the pre-calculated node list for this prefix.\r\n\t\t\tuint16 *p_node_list=sp_prefix_lookups[index].mpNodeList;\r\n\t\t\t*p_numMatches=*p_node_list++;\t\t \r\n\t\t\t\r\n\t\t\treturn p_node_list;\r\n\t\t}\t\r\n\t}\t\r\n\t\r\n\t// No matches, so return a node count of zero.\r\n\t*p_numMatches=0;\r\n\treturn &s_dummy;\r\n}\r\n\r\n\r\nconst uint16 *GetPrefixedNodes(const char *p_prefix, uint16 *p_numMatches)\r\n{\r\n\tuint32 checksum=Crc::GenerateCRCFromString(p_prefix);\r\n\treturn GetPrefixedNodes(checksum,p_numMatches);\r\n}\r\n\r\n\r\n// return the index of the node nearest to this position that\r\n// matches this prefix\r\nint\tGetNearestNodeByPrefix(uint32 prefix, const Mth::Vector &pos)\r\n{\r\n\tCArray *p_node_array=GetArray(0xc472ecc5/*NodeArray*/);\r\n\tDbg_MsgAssert(p_node_array,(\"NodeArray not found\"));\r\n\r\n\tint\tclosest_node = -1;\r\n\tfloat\tclosest_dist = 1e20f;\r\n\tuint16\tnum_nodes = 0;\r\n\tconst uint16 *\tp_nodes =  GetPrefixedNodes(prefix,&num_nodes);\r\n\twhile (num_nodes)\r\n\t{\r\n\t\tScript::CStruct * p_node = p_node_array->GetStructure(*p_nodes);\r\n\t\tMth::Vector node_pos;\r\n\t\tp_node->GetVector(CRCD(0x7f261953,\"pos\"),&node_pos);\r\n\t\tfloat\tnode_dist = (node_pos - pos).LengthSqr();\r\n\t\t//printf (\"Node %d at (%.02f, %.02f, %.02f)  dist %.02f\\n\",*p_nodes,node_pos[X],node_pos[Y],node_pos[Z],node_dist);\r\n\t\tif (node_dist < closest_dist)\r\n\t\t{\r\n\t\t  //  printf (\"closest node %d\\n\",*p_nodes);\r\n\t\t\tclosest_dist = node_dist;\r\n\t\t\tclosest_node = *p_nodes;\r\n\t\t}\r\n\t\r\n\t\tp_nodes++;\r\n\t\tnum_nodes--;\r\n\t}\r\n\t\r\n\treturn closest_node;\t\t\t\t   \r\n\t\t\t\t   \r\n}\r\n\r\n\r\n// return the index of the node nearest to this position that\r\n// matches this prefix\r\nint\tGetNearestNodeByPrefix(const char *p_prefix, const Mth::Vector &pos)\r\n{\r\n\treturn GetNearestNodeByPrefix(Crc::GenerateCRCFromString(p_prefix),pos);\r\n}\r\n\r\n\r\n////////////////////////////////////////////////////////////////////\r\n//\r\n// Utility functions for getting nodes, links, etc\r\n//\r\n////////////////////////////////////////////////////////////////////\r\n\r\nCStruct *GetNode(int nodeIndex)\r\n{\r\n\tCArray *p_node_array=GetArray(0xc472ecc5/*NodeArray*/);\r\n\tDbg_MsgAssert(p_node_array,(\"NodeArray not found\"));\r\n\tCStruct *p_node=p_node_array->GetStructure(nodeIndex);\r\n\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\treturn p_node;\r\n}\r\n\r\n\r\n// This is a DEPRECATED function\r\n// only in to support the rather odd manner of access in nodes via index\r\nuint32\tGetNodeNameChecksum(int nodeIndex)\r\n{\r\n\tCStruct *p_struct = GetNode(nodeIndex);\r\n\tuint32 name = 0;\r\n\tp_struct->GetChecksum(CRCD(0xa1dc81f9,\"name\"),&name);\r\n\treturn name;\r\n}\r\n\r\nuint32 GetNumLinks(CStruct *p_node)\r\n{\r\n\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\tCArray *p_links=NULL;\r\n\tp_node->GetArray(0x2e7d5ee7/*Links*/,&p_links);\r\n\tif (p_links==NULL)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\treturn p_links->GetSize();\r\n}\r\n\r\nuint32 GetNumLinks(int nodeIndex)\r\n{\r\n\tCArray *p_node_array=GetArray(0xc472ecc5/*NodeArray*/, NO_ASSERT);\r\n\tif (p_node_array)\r\n\t{\r\n\t\tCStruct *p_node=p_node_array->GetStructure(nodeIndex);\r\n\t\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\t\r\n\t\treturn GetNumLinks(p_node);\r\n\t}\t\r\n\treturn 0;\r\n}\r\n\r\nint GetLink(CStruct *p_node, int linkNumber)\r\n{\r\n\tDbg_MsgAssert( p_node, ( \"NULL p_node\" ) );\r\n\tCArray *p_links=NULL;\r\n\tp_node->GetArray( CRCD( 0x2e7d5ee7, \"Links\" ), &p_links);\r\n\tDbg_MsgAssert( p_links, ( \"Tried to call GetLink when there are no links\" ) );\r\n\tDbg_MsgAssert( p_links->GetSize(), ( \"Tried to call GetLink when there are no links (empty Links array)\" ) );\r\n\treturn p_links->GetInteger( linkNumber );\r\n}\r\n\r\nint GetLink(int nodeIndex, int linkNumber)\r\n{\r\n\treturn GetLink(GetNode(nodeIndex),linkNumber);\r\n}\r\n\r\n// return true if Node1 is linked to Node2\r\nbool IsLinkedTo(int node1, int node2)\r\n{\r\n\tint n = GetNumLinks(node1);\r\n\tfor (int i = 0; i<n; i++)\t \t\t\t// will work for zero links \r\n\t{\r\n\t\tif (GetLink(node1,i) == node2) \t\t// if any link from Node1 is to Node2\r\n\t\t{\r\n\t\t\treturn true;\t\t\t\t    // then we are linked\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid GetPosition(CStruct *p_node, Mth::Vector *p_vector)\r\n{\r\n\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\tDbg_MsgAssert(p_vector,(\"NULL p_vector\"));\r\n\t   \r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tif ( p_node->GetVector(CRCD(0xb9d31b0a,\"Position\"),p_vector,Script::NO_ASSERT) )\r\n\t{\r\n\t\tuint32 name = 0;\r\n\t\tp_node->GetChecksum(CRCD(0xa1dc81f9,\"name\"),&name);\r\n\t\tif (name)\r\n\t\t{\r\n\t\t\tDbg_Message( \"Warning:  'Position' deprecated! reexport, node %s\",Script::FindChecksumName(name) );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Message( \"Warning:  'Position' deprecated! reexport\" );\r\n\t\t}\r\n\t}\r\n\t#endif\r\n\r\n\tif ( p_node->GetVector(CRCD(0x7f261953,\"pos\"),p_vector,Script::NO_ASSERT) )\r\n\t{\r\n\t\t// no need to negate the new style vectors\r\n\t}\r\n\telse if ( p_node->GetVector(CRCD(0xb9d31b0a,\"Position\"),p_vector,Script::NO_ASSERT) )\r\n\t{\r\n\t\t(*p_vector)[Z]=-(*p_vector)[Z];\r\n\t}\r\n\telse\r\n\t{\r\n\t\t*p_vector = Mth::Vector(0.0f,0.0f,0.0f,1.0f);\r\n//\t\tScript::PrintContents( p_node );\r\n//\t\tDbg_MsgAssert( 0, ( \"No 'pos' vector found in node\" ) );\r\n\t}\r\n}\r\n\r\nvoid GetPosition(int nodeIndex, Mth::Vector *p_vector)\r\n{\r\n\tDbg_MsgAssert(p_vector,(\"NULL p_vector\"));\r\n\tGetPosition(GetNode(nodeIndex),p_vector);\r\n}\r\n\r\nvoid GetOrientation(CStruct *p_node, Mth::Matrix *p_matrix)\r\n{\r\n\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\tDbg_MsgAssert(p_matrix,(\"NULL p_matrix\"));\r\n\t   \r\n\tMth::Vector orientation_vector;\r\n\tif ( p_node->GetVector(CRCD(0xc97f3aa9, \"orientation\"),&orientation_vector,Script::NO_ASSERT) )\r\n\t{\r\n\t\t// assumes a positive scalar component\r\n\t\tMth::Quat orientation_quat;\r\n\t\torientation_quat.SetVector(orientation_vector);\r\n\t\torientation_quat.SetScalar(sqrtf(1.0f - orientation_vector.LengthSqr()));\r\n\t\t\r\n\t\torientation_quat.GetMatrix(*p_matrix);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_matrix->Identity();\r\n\t}\r\n}\r\n\r\nvoid GetOrientation(int nodeIndex, Mth::Vector *p_matrix)\r\n{\r\n\tDbg_MsgAssert(p_matrix,(\"NULL p_matrix\"));\r\n\tGetPosition(GetNode(nodeIndex),p_matrix);\r\n}\r\n\r\nvoid GetAngles(CStruct *p_node, Mth::Vector *p_vector)\r\n{\r\n\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\tDbg_MsgAssert(p_vector,(\"NULL p_vector\"));\r\n\t// Make sure they are initialised to zero, in case there is no Angles component.\r\n\t// Angles components of (0,0,0) are ommitted to save memory.\r\n\tp_vector->Set(); \r\n\tp_node->GetVector(0x9d2d0915/*Angles*/,p_vector);\r\n}\r\n\r\nvoid GetAngles(int nodeIndex, Mth::Vector *p_vector)\r\n{\r\n\tDbg_MsgAssert(p_vector,(\"NULL p_vector\"));\r\n\tGetAngles(GetNode(nodeIndex),p_vector);\r\n}\r\n\r\nCArray *GetIgnoredLightArray(CStruct *p_node)\r\n{\r\n\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\tCArray *p_ignored_lights=NULL;\r\n\tp_node->GetArray(0xb7b030be/*IgnoredLights*/,&p_ignored_lights);\r\n\treturn p_ignored_lights;\r\n}\r\n\r\nCArray *GetIgnoredLightArray(int nodeIndex)\r\n{\r\n\treturn GetIgnoredLightArray(GetNode(nodeIndex));\r\n}\r\n\r\n// Used by Ryan in the Park Editor.\r\n// This creates an array (called NodeArray) of Size structures, with all the entries initialised to empty structures.\r\nvoid CreateNodeArray(int size, bool hackUseFrontEndHeap)\r\n{\r\n\t// copied from Script::Cleanup()\r\n\t//KillStoppedScripts();\r\n\t//RemoveOldTriggerScripts();\r\n\t//RemoveSymbol(GenerateCRC(\"TriggerScripts\"));\r\n\tCleanUpAndRemoveSymbol(CRCD(0xc472ecc5,\"NodeArray\"));\r\n\tDeletePrefixInfo();\r\n\tClearNodeNameHashTable();\r\n\t\r\n\t// Make sure it doesn't exist already.\r\n\t// ParseQB will catch this anyway, but may as well check before getting there.\r\n\tDbg_MsgAssert(GetArray(CRCD(0xc472ecc5,\"NodeArray\"))==NULL,(\"Called CreateNodeArray when a NodeArray already exists\"));\r\n\r\n\r\n\t// Create a dummy QB file, and parse it the usual way.\t\r\n\tif (hackUseFrontEndHeap)\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap()); // Use the temporary heap.\r\n\telse\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap()); // Use the temporary heap.\r\n\tuint8 *p_dummy_qb=(uint8*)Mem::Malloc((1\t\t\t// ESCRIPTTOKEN_NAME\r\n\t\t\t\t\t\t\t\t\t\t +4\t\t\t// Checksum of 'NodeArray'\r\n\t\t\t\t\t\t\t\t\t\t +1\t\t\t// ESCRIPTTOKEN_EQUALS\r\n\t\t\t\t\t\t\t\t\t\t +1\t\t\t// ESCRIPTTOKEN_STARTARRAY\r\n\t\t\t\t\t\t\t\t\t\t +2*size\t// ESCRIPTTOKEN_STARTSTRUCT,ESCRIPTTOKEN_ENDSTRUCT pairs\r\n\t\t\t\t\t\t\t\t\t\t +1\t\t\t// ESCRIPTTOKEN_ENDARRAY\r\n\t\t\t\t\t\t\t\t\t\t +1\t\t\t// ESCRIPTTOKEN_ENDOFFILE\r\n\t\t\t\t\t\t\t\t\t\t )*sizeof(uint8));\r\n\tuint8 *p_qb=p_dummy_qb;\r\n\t\r\n\t*p_qb++=ESCRIPTTOKEN_NAME;\r\n\t*p_qb++=0xc5; // Checksum of 'NodeArray'\r\n\t*p_qb++=0xec;\r\n\t*p_qb++=0x72;\r\n\t*p_qb++=0xc4;\r\n\t*p_qb++=ESCRIPTTOKEN_EQUALS;\r\n\t*p_qb++=ESCRIPTTOKEN_STARTARRAY;\r\n\tfor (int i=0; i<size; ++i)\r\n\t{\r\n\t\t*p_qb++=ESCRIPTTOKEN_STARTSTRUCT;\r\n\t\t*p_qb++=ESCRIPTTOKEN_ENDSTRUCT;\r\n\t}\r\n\t*p_qb++=ESCRIPTTOKEN_ENDARRAY;\r\n\t*p_qb=ESCRIPTTOKEN_ENDOFFILE;\r\n\r\n\t// Parse it the usual way.\r\n\tParseQB(\"levels\\\\sk5ed\\\\sk5ed.qb\",p_dummy_qb,ASSERT_IF_DUPLICATE_SYMBOLS);\r\n\t// TODO ParseQB no longer does the node name hash table generation etc, so need to copy\r\n\t// the calls to the code that does that from SkateScript::LoadQB in sk\\scripting\\file.cpp\r\n\t\t\t\r\n\t// This next bit is a fix to the assert that was happening when attempting to qbr within the\r\n\t// park editor:\t\t\r\n\t// Set the mGotReloaded to false for the newly created symbol, otherwise it will be left\r\n\t// stuck on causing the next qbr to make it think that the NodeArray got reloaded by that qbr,\r\n\t// which will then cause an assert.\r\n\tCSymbolTableEntry *p_new_node_array=Script::LookUpSymbol(\"NodeArray\");\r\n\tDbg_MsgAssert(p_new_node_array,(\"What? No NodeArray?\"));\r\n\tp_new_node_array->mGotReloaded=false;\r\n\r\n\tObj::InsertGoalEditorNodes();\r\n\t\r\n\tMem::Free(p_dummy_qb);\r\n\tMem::Manager::sHandle().PopContext();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n//\r\n// Given a script, and the checksum of a function to look for,\r\n// this will search through the script for any calls to that function.\r\n// It will recursively search through any script calls.\r\n// The callback function is called for each occurrence of the function\r\n// call found, and the parameter list for that call is also passed.\r\n//\r\n// NOTE: Don't store the passed CStruct pointer! \r\n// It's a local variable in FindReferences.\r\n// To store the parameters create a new CStruct and use the\r\n// AppendStructure member function to copy in the contents of the\r\n// passed one.\r\n//\r\n////////////////////////////////////////////////////////////////////\r\n\r\n// Note: p_args contains the set of parameters that were passed to scriptToScanThrough. It is passed so that\r\n// the <,> syntax can be evaluated. This is necessary because sometimes the EndGap command is not directly\r\n// passed the text and score, they might get passed via the <...> syntax, for example see the\r\n// Gap_Gen_End script in sk4_scripts.q\r\nstatic void FindReferences(uint32 scriptToScanThrough, uint32 functionToScanFor, void (*p_callback)(Script::CStruct *, const uint8 *), Script::CStruct *p_args, int Count)\r\n{\r\n\t// Don't recurse too deeply otherwise some levels take ages finding the gaps (eg, the secret level)\r\n\tif (Count > 5)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tDbg_MsgAssert(p_callback,(\"NULL p_callback\"));\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\t// Look up the function being scanned for to see if it is a cfunction.\r\n    bool (*p_cfunction)(CStruct *pParams, CScript *pCScript)=NULL;\r\n\tCSymbolTableEntry *p_function_entry=LookUpSymbol(functionToScanFor);\r\n\tif (p_function_entry && p_function_entry->mType==ESYMBOLTYPE_CFUNCTION)\r\n\t{\r\n\t\tp_cfunction=p_function_entry->mpCFunction;\r\n\t}\t\r\n\tDbg_MsgAssert(p_cfunction==NULL,(\"Cannot use FindReferences to find cfunction calls yet ...\"));\r\n\t#endif\r\n\r\n\t#ifdef NO_SCRIPT_CACHING\r\n\t// Look up the script\r\n\tCSymbolTableEntry *p_script_entry=LookUpSymbol(scriptToScanThrough);\r\n\tif (!p_script_entry)\r\n\t{\r\n\t\tDbg_Warning(\"Script '%s' not found in call to FindReferences\",FindChecksumName(scriptToScanThrough));\r\n\t\treturn;\r\n\t}\r\n\tDbg_MsgAssert(p_script_entry->mType==ESYMBOLTYPE_QSCRIPT,(\"'%s' is not a qscript\",FindChecksumName(scriptToScanThrough)));\r\n\t\r\n\t// Get a pointer to it.\r\n\tuint8 *p_token=p_script_entry->mpScript;\r\n\tDbg_MsgAssert(p_token,(\"NULL p_token ???\"));\r\n\t// Skip over the 4-byte contents checksum.\r\n\tp_token+=4;\r\n\t#else\r\n\t\r\n\tScript::CScriptCache *p_script_cache=Script::CScriptCache::Instance();\r\n\tDbg_MsgAssert(p_script_cache,(\"NULL p_script_cache\"));\r\n\tuint8 *p_script=p_script_cache->GetScript(scriptToScanThrough);\r\n\tDbg_MsgAssert(p_script,(\"Script %s not found in script cache\",Script::FindChecksumName(scriptToScanThrough)));\r\n\tuint8 *p_token=p_script;\r\n\t\r\n\t#endif\r\n\t\r\n\t\r\n\t// Create a structure for holding parameters.\r\n\tCStruct *p_params=new CStruct;\r\n\r\n\t// Skip to the first line of the script.\t\r\n\tp_token=SkipToStartOfNextLine(p_token);\r\n\r\n\t\r\n\t// Now scan through each token of the script in turn, looking for any calls to functionToScanFor.\r\n\t\r\n\tbool finished=false;\r\n    while (!finished)\r\n    {\r\n        switch (*p_token)\r\n        {\r\n\t\tcase ESCRIPTTOKEN_RUNTIME_CFUNCTION:\r\n\t\t{\r\n\t\t\t// Skip over CFunction calls for now.\r\n\t\t\tp_token+=5;\r\n\t\t\tp_token=SkipToStartOfNextLine(p_token);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n        case ESCRIPTTOKEN_NAME:\r\n\t\tcase ESCRIPTTOKEN_RUNTIME_MEMBERFUNCTION:\r\n        {\r\n\t\t\t// Remember the location for passing to the callback.\r\n\t\t\tconst uint8 *p_location=p_token;\r\n\t\t\t\r\n            ++p_token;\r\n            uint32 name_checksum=Read4Bytes(p_token).mChecksum;\r\n            p_token+=4;\r\n\r\n\t\t\t// Skip over lines of script that are setting parameters\r\n\t\t\tif (*p_token==ESCRIPTTOKEN_EQUALS)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\t\r\n\t\t\t\r\n            CSymbolTableEntry *p_entry=Resolve(name_checksum);\r\n\t\t\tif (p_entry)\r\n\t\t\t{\r\n\t\t\t\tswitch (p_entry->mType)\r\n\t\t\t\t{\r\n\t\t\t\tcase ESYMBOLTYPE_CFUNCTION:\r\n\t\t\t\t\tDbg_MsgAssert(p_entry->mpCFunction,(\"\\nLine %d of %s\\nNULL pCFunction\",GetLineNumber(p_token),FindChecksumName(p_entry->mSourceFileNameChecksum)));\r\n\t\t\t\t\r\n\t\t\t\t\tif (name_checksum==functionToScanFor)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Found the required function call! Get the params and call the callback.\r\n\t\t\t\t\t\tp_params->Clear();\r\n\t\t\t\t\t\t// Note: Uses p_args to look up any params enclosed in <,> that are encountered.\r\n\t\t\t\t\t\tp_token=AddComponentsUntilEndOfLine(p_params,p_token,p_args);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t//printf(\"Callback: %s\\n\",FindChecksumName(scriptToScanThrough));\r\n\t\t\t\t\t\t(*p_callback)(p_params,p_location);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_token=SkipToStartOfNextLine(p_token);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase ESYMBOLTYPE_MEMBERFUNCTION:\r\n\t\t\t\t\tif (name_checksum==functionToScanFor)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Found the required function call! Get the params and call the callback.\r\n\t\t\t\t\t\tp_params->Clear();\r\n\t\t\t\t\t\t// Note: Uses p_args to look up any params enclosed in <,> that are encountered.\r\n\t\t\t\t\t\tp_token=AddComponentsUntilEndOfLine(p_params,p_token,p_args);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t//printf(\"Callback: %s\\n\",FindChecksumName(scriptToScanThrough));\r\n\t\t\t\t\t\t(*p_callback)(p_params,p_location);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif (name_checksum==0xe5399fb2) // EndGap\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tuint32 GapScript=0;\r\n\t\t\t\t\t\t\tif (p_params->GetChecksum(\"GapScript\",&GapScript))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// Passing NULL for p_args here because it is not clear what parameters are\r\n\t\t\t\t\t\t\t\t// going to be passed to the GapScript when it is run.\r\n\t\t\t\t\t\t\t\tFindReferences(GapScript,functionToScanFor,p_callback,NULL,Count+1);\r\n\t\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_token=SkipToStartOfNextLine(p_token);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tcase ESYMBOLTYPE_QSCRIPT:\r\n\t\t\t\t\tp_params->Clear();\r\n\t\t\t\t\t// Note: Uses p_args to look up any params enclosed in <,> that are encountered.\r\n\t\t\t\t\tp_token=AddComponentsUntilEndOfLine(p_params,p_token,p_args);\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (name_checksum==functionToScanFor)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Found the required function call! Get the params and call the callback.\r\n\t\t\t\t\t\t//printf(\"Callback: %s\\n\",FindChecksumName(scriptToScanThrough));\r\n\t\t\t\t\t\t(*p_callback)(p_params,p_location);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_token=SkipToStartOfNextLine(p_token);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t// It's a q-script, so recursively search that too.\r\n\t\t\t\t\t// Passing the just calculated p_params so that the <,> syntax within the script\r\n\t\t\t\t\t// can be evaluated.\r\n\t\t\t\t\tFindReferences(name_checksum,functionToScanFor,p_callback,p_params,Count+1);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}    \r\n\t\t\t}\r\n            break;\r\n        }    \r\n\r\n        case ESCRIPTTOKEN_KEYWORD_REPEAT:\r\n            p_token=SkipToken(p_token);\r\n\t\t\t// Scan over any repeat parameters.\r\n\t\t\tp_token=SkipToStartOfNextLine(p_token);\r\n            break;\r\n\r\n\t\tcase ESCRIPTTOKEN_KEYWORD_IF:\r\n            p_token=SkipToken(p_token);\r\n\r\n\t\t\tif (*p_token==ESCRIPTTOKEN_KEYWORD_NOT)\r\n\t\t\t{\r\n\t\t\t\tp_token=SkipToken(p_token);\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\t// If the if keyword is followed by an open parenthesis, then it must be using an\r\n\t\t\t// expression. Often the expression may contain c-function calls, such as:\r\n\t\t\t// if ( (GotParam Foo) | (GotParam Blaa) )\r\n\t\t\t// This was causing a problem because this loop would skip over the open parenthesis,\r\n\t\t\t// get to the GotParam, and then recognizing that GotParam is a cfunction it would\r\n\t\t\t// try to skip to the next line, but then that would cause a parenthesis mismatch\r\n\t\t\t// assert in SkipToStartOfNextLine because the open parenth had been skipped over.\r\n\t\t\t// So to get around that, skip to the next line as soon as the open parenth is detected.\r\n\t\t\tif (*p_token==ESCRIPTTOKEN_OPENPARENTH)\r\n\t\t\t{\r\n\t\t\t\tp_token=SkipToStartOfNextLine(p_token);\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t\t\r\n        case ESCRIPTTOKEN_KEYWORD_ENDSCRIPT:\r\n\t\t\tfinished=true;\r\n            break;\r\n\r\n        default:\r\n            p_token=SkipToken(p_token);\r\n            break;\r\n        }\r\n    }\r\n\r\n\t#ifndef NO_SCRIPT_CACHING\r\n\tp_script_cache->DecrementScriptUsage(scriptToScanThrough);\r\n\t#endif\r\n\t\r\n\t// Delete the temporary p_params.\r\n\tdelete p_params;\t\r\n}\r\n\r\nvoid ScanNodeScripts(uint32 componentName, uint32 functionName, void (*p_callback)(CStruct *, const uint8 *))\r\n{\r\n\tScript::DisableExpressionEvaluatorErrorChecking();\r\n\t\r\n\tCArray *p_node_array=GetArray(0xc472ecc5); // Checksum of NodeArray\r\n\tDbg_MsgAssert(p_node_array,(\"NodeArray not found\"));\r\n\t\r\n\tfor (uint32 i=0; i<p_node_array->GetSize(); ++i)\r\n\t{\r\n\t\tCStruct *p_node=p_node_array->GetStructure(i);\r\n\t\tDbg_MsgAssert(p_node,(\"NULL p_node\"));\r\n\t\t\r\n\t\tuint32 script_checksum=0;\r\n\t\tif (p_node->GetChecksum(componentName,&script_checksum))\r\n\t\t{\r\n\t\t\tFindReferences(script_checksum,functionName,p_callback,NULL,0);\r\n\t\t}\t\r\n\t}\r\n\t\r\n\tScript::EnableExpressionEvaluatorErrorChecking();\r\n}\r\n\r\n} // namespace SkateScript\r\n\r\n"
  },
  {
    "path": "Code/Sk/Scripting/nodearray.h",
    "content": "#ifndef\t__SK_SCRIPTING_NODEARRAY_H\r\n#define\t__SK_SCRIPTING_NODEARRAY_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\nnamespace Mth\r\n{\r\nclass Vector;\r\nclass Matrix;\r\n}\r\n\r\nnamespace Script\r\n{\r\nclass CStruct;\r\nclass CArray;\r\n}\t\r\n\r\nnamespace SkateScript\r\n{\r\nusing namespace Script;\r\n\r\nvoid InitNodeNameHashTable();\r\nvoid ClearNodeNameHashTable();\r\nvoid CreateNodeNameHashTable();\r\nint FindNamedNode(uint32 checksum, bool assert=true);\r\nint FindNamedNode(const char *p_name);\r\nbool NodeExists(uint32 checksum);\r\n\r\nvoid DeletePrefixInfo();\r\nvoid GeneratePrefixInfo();\r\nconst uint16 *GetPrefixedNodes(const char *p_prefix, uint16 *p_numMatches);\r\nconst uint16 *GetPrefixedNodes(uint32 checksum, uint16 *p_numMatches);\r\n\r\nint\tGetNearestNodeByPrefix(uint32 prefix, const Mth::Vector &pos);\r\nint\tGetNearestNodeByPrefix(const char * p_prefix, const Mth::Vector &pos);\r\n\r\n\r\nCStruct *GetNode(int nodeIndex);\r\nuint32\tGetNodeNameChecksum(int nodeIndex);\r\nuint32 GetNumLinks(CStruct *p_node);\r\nuint32 GetNumLinks(int nodeIndex);\r\nint GetLink(CStruct *p_node, int linkNumber);\r\nint GetLink(int nodeIndex, int linkNumber);\r\nbool IsLinkedTo(int node1, int node2);\r\n\r\nvoid GetPosition(CStruct *p_node, Mth::Vector *p_vector);\r\nvoid GetPosition(int nodeIndex, Mth::Vector *p_vector);\r\nvoid GetOrientation(CStruct *p_node, Mth::Matrix *p_matrix);\r\nvoid GetOrientation(int nodeIndex, Mth::Matrix *p_matrix);\r\nvoid GetAngles(CStruct *p_node, Mth::Vector *p_vector);\r\nvoid GetAngles(int nodeIndex, Mth::Vector *p_vector);\r\n\r\nCArray *GetIgnoredLightArray(CStruct *p_node);\r\nCArray *GetIgnoredLightArray(int nodeIndex);\r\n\r\nvoid CreateNodeArray(int size, bool hackUseFrontEndHeapYouFucker);\r\nvoid ScanNodeScripts(uint32 componentName, uint32 functionName, void (*p_callback)(CStruct *, const uint8 *));\r\n\r\n} // namespace SkateScript\r\n\r\n#endif // #ifndef\t__SK_SCRIPTING_NODEARRAY_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/Scripting/skfuncs.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         Sk/Scripting\r\n//* FILENAME:       SkFuncs.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  6/10/2002\r\n//****************************************************************************\r\n\r\n// start autoduck documentation\r\n// @DOC skfuncs\r\n// @module skfuncs | None\r\n// @subindex Scripting Database\r\n// @index script | skfuncs\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sk/scripting/skfuncs.h>\r\n\r\n#include <gel/assman/assman.h>\r\n\t\t\t\t\t\t\t \r\n#include <gel/objman.h>\r\n#include <gel/objtrack.h>\r\n\r\n#include <gel/components/modelcomponent.h>\r\n#include <gel/components/skatercameracomponent.h>\r\n#include <gel/components/trickcomponent.h>\r\n\r\n#include <gel/object/compositeobject.h>\r\n#include <gel/object/compositeobjectmanager.h>\r\n\r\n#include <gel/scripting/script.h> \r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h> \r\n#include <gel/scripting/checksum.h> \r\n#include <gel/scripting/component.h>\r\n#include <gel/scripting/utils.h>\r\n\r\n#include <gel/music/music.h>\r\n#include <gel/net/client/netclnt.h>\r\n \r\n#include <gfx/casutils.h>\r\n#include <gfx/facetexture.h>\r\n#include <gfx/gfxutils.h>\r\n#include <gfx/modelbuilder.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxmodel.h>\r\n\r\n#include <sk/gamenet/gamenet.h>\r\n#include <sk/scripting/nodearray.h>\r\n\r\n#include <sk/modules/skate/competition.h>\r\n#include <sk/modules/skate/gamemode.h>\r\n#include <sk/modules/skate/horse.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/frontend/frontend.h>\r\n\r\n#include <sk/objects/gameobj.h>\r\n#include <sk/objects/moviecam.h>\r\n#include <sk/objects/records.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/skaterprofile.h>\r\n#include <sk/objects/playerprofilemanager.h>\r\n#include <sk/objects/skatercareer.h>\r\n\r\n#include <sk/components/skaterstatecomponent.h>\r\n#include <sk/parkeditor2/parked.h>\r\n\r\n#include <sys/config/config.h>\r\n#include <Gfx/NGPS/NX/chars.h>\r\n\r\n#include <sys/SIO/keyboard.h>\r\n\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/pre.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Front\r\n{\r\n\textern void SetScoreTHPS4(char* score_text, int skater_num);\r\n}\r\n\r\nnamespace CFuncs\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void s_preload_ped_part( uint32 partChecksum )\r\n{\r\n\tScript::CArray* pArray = Script::GetArray( partChecksum );\r\n\tDbg_Assert( pArray );\r\n\r\n\tfor ( uint32 i = 0; i < pArray->GetSize(); i++ )\r\n\t{\r\n\t\tScript::CStruct* pStruct = pArray->GetStructure( i );\r\n\r\n\t\tint allow_random = 0;\r\n\t\tpStruct->GetInteger( CRCD(0xf1e3cd22,\"allow_random\"), &allow_random, Script::NO_ASSERT );\r\n\t\t\t\r\n\t\tif ( allow_random )\r\n\t\t{\r\n\t\t\tconst char* pMeshName;\r\n\t\t\tif ( pStruct->GetText( CRCD(0x1e90c5a9,\"mesh\"), &pMeshName, false ) )\r\n\t\t\t{\r\n\t\t\t\tNx::CModel* pDummy = Nx::CEngine::sInitModel();\r\n//\t\t\t\tDbg_Message(\"Preloading random ped model %s\", pMeshName );\r\n\t\t\t\tpDummy->AddGeom( pMeshName, 0, true );\r\n\t\t\t\tNx::CEngine::sUninitModel( pDummy );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Score queries:\r\n\r\nstatic int s_get_score_from_params( Script::CStruct *pParams, Script::CScript *pScript )\r\n{  \r\n\tint score;\r\n\tif ( !pParams->GetInteger( NONAME, &score ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"\\n%s\\nMust provide an integer for s_get_score_from_params.\", pScript->GetScriptInfo( ) ));\r\n\t\treturn ( 0 );\r\n\t}\r\n\treturn ( score );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic Mdl::Score* s_get_score_struct( void )\r\n{\r\n\t// find the skater, get the score landed:\r\n\tObj::CSkater *pSkater = Mdl::Skate::Instance()->GetLocalSkater();\t\t\t\t\t\t   \r\n\tif ( pSkater )\r\n\t{\r\n\t\treturn ( pSkater->GetScoreObject() );\r\n\t}\r\n\treturn ( NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Local function to return a career, given a flag number\r\nstatic Obj::CSkaterCareer* s_get_career( int flag, Script::CStruct *pParams )\r\n{\r\n// Now this always just returns the global career, just kept for convenience\t\r\n\treturn Mdl::Skate::Instance()->GetCareer();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CurrentSkaterIsPro | Checks if the current skater is pro\r\nbool ScriptCurrentSkaterIsPro(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\tObj::CSkaterProfile *pSkaterProfile = Mdl::Skate::Instance()->GetCurrentProfile(pParams);\r\n\treturn ( pSkaterProfile && pSkaterProfile->IsPro() );\r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetGoalsCompleted | Returns goals (competitions) completed\r\nbool ScriptGetGoalsCompleted(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\tDbg_MsgAssert(pCareer,(\"NULL pCareer\"));\r\n\t\r\n\tint LevelNumber=0;\r\n\tpParams->GetInteger(NONAME,&LevelNumber);\r\n\tchar pBuf[100];\r\n\r\n\tsprintf(pBuf,\"%d/9\",pCareer->CountGoalsCompleted(LevelNumber));\r\n\tpScript->GetParams()->AddComponent(CRCD(0xc661fe79,\"GoalsCompleted\"),ESYMBOLTYPE_STRING,pBuf);\r\n\tpScript->GetParams()->AddComponent(CRCD(0xa43dc969,\"BestMedal\"),ESYMBOLTYPE_STRING,\"---\");\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetNextLevelRequirements | Gets number of goals needed for next level\r\nbool ScriptGetNextLevelRequirements(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\tDbg_MsgAssert(pCareer,(\"NULL pCareer\"));\r\n\t\r\n\tchar pBuf[100];\r\n\tsprintf(pBuf,\"---\");\r\n\t\r\n\tint TotalGoals=pCareer->CountTotalGoalsCompleted();\r\n\tint TotalMedals=pCareer->CountMedals();\r\n\t\r\n\tScript::CArray *pUnlockRequirementsArray=Script::GetArray(CRCD(0x1d8f1a7e,\"UnlockRequirements\"));\r\n\tfor (uint32 i=0; i<pUnlockRequirementsArray->GetSize(); ++i)\r\n\t{\r\n\t\tScript::CStruct *pUnlockRequirements=pUnlockRequirementsArray->GetStructure(i);\r\n\t\t\r\n\t\tint NumGoalsRequired=0;\r\n\t\tint NumMedalsRequired=0;\r\n\t\t\r\n\t\tif (pUnlockRequirements->ContainsFlag(CRCD(0x38dbe1d0,\"Goals\")) || pUnlockRequirements->ContainsFlag(CRCD(0x032314d1,\"Goal\")))\r\n\t\t{\r\n\t\t\t// Need a certain number of goals.\r\n\t\t\tpUnlockRequirements->GetInteger(NONAME,&NumGoalsRequired);\r\n\t\t}\t\r\n\t\t\t\t\r\n\t\tif (pUnlockRequirements->ContainsFlag(CRCD(0x56907f8b,\"Medals\")) || pUnlockRequirements->ContainsFlag(CRCD(0x23bba846,\"Medal\")))\r\n\t\t{\r\n\t\t\t// Need a certain number of medals.\r\n\t\t\tpUnlockRequirements->GetInteger(NONAME,&NumMedalsRequired);\r\n\t\t}\r\n\t\t\r\n\t\t#if ENGLISH\r\n\t\tif (TotalGoals<NumGoalsRequired)\r\n\t\t{\r\n\t\t\tsprintf(pBuf,\"%d goals for next Level\",NumGoalsRequired-TotalGoals);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tif (TotalMedals<NumMedalsRequired)\r\n\t\t{\r\n\t\t\tsprintf(pBuf,\"%d medals for next level\",NumMedalsRequired-TotalMedals);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t#else\r\n\t\tif (TotalGoals<NumGoalsRequired)\r\n\t\t{\r\n\t\t\tsprintf(pBuf,Script::GetLocalString(CRCD(0x407bfd24,\"cfuncs_str_goalsfornextlevel\")),NumGoalsRequired-TotalGoals);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tif (TotalMedals<NumMedalsRequired)\r\n\t\t{\r\n\t\t\tsprintf(pBuf,Script::GetLocalString(CRCD(0x4f3e243e,\"cfuncs_str_medalsfornextlevel\")),NumMedalsRequired-TotalMedals);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t#endif\t\t\r\n\t}\t\t\r\n\t\r\n\tpScript->GetParams()->AddComponent(CRCD(0xaf2305a6,\"NextLevelRequirements\"),ESYMBOLTYPE_STRING,pBuf);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetCurrentSkaterProfile | \r\n// @uparmopt 0 | Skater profile index - must be 0 or 1\r\nbool ScriptSetCurrentSkaterProfile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\t\r\n\tint Profile=0;\r\n\tpParams->GetInteger(NONAME,&Profile);\r\n\tDbg_MsgAssert(Profile==0 || Profile==1,(\"\\n%s\\nBad index sent to SetCurrentSkaterProfile, must be 0 or 1\",pScript->GetScriptInfo()));\r\n\t\r\n\t\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tpPlayerProfileManager->SetCurrentProfileIndex(Profile);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CurrentSkaterProfileIs | Checks if current skater profile is \r\n// equal to index value passed in\r\n// @uparmopt 0 | Index value - must be 0 or 1\r\nbool ScriptCurrentSkaterProfileIs(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\tint Profile=0;\r\n\tpParams->GetInteger(NONAME,&Profile);\r\n\tDbg_MsgAssert(Profile==0 || Profile==1,(\"\\n%s\\nBad index sent to CurrentSkaterProfileIs, must be 0 or 1\",pScript->GetScriptInfo()));\r\n\t\r\n\t\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\t\r\n\treturn pPlayerProfileManager->GetCurrentProfileIndex()==Profile;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AddSkaterProfile | Adds skater profile \r\n// @parm name | name | The name of the profile\r\nbool ScriptAddSkaterProfile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\treturn pPlayerProfileManager->AddNewProfile( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AddTemporaryProfile | Adds temporary skater profile\r\n// (used for credits, to temporarily hijack the skater profile\r\nbool ScriptAddTemporaryProfile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 profileName;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &profileName, Script::ASSERT );\r\n\t\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\treturn pPlayerProfileManager->AddTemporaryProfile( profileName );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RememberTemporaryAppearance | \r\nbool ScriptRememberTemporaryAppearance(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 profileName;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &profileName, Script::ASSERT );\r\n\t\r\n\tGfx::CModelAppearance theAppearance;\r\n\tGfx::CModelAppearance* pAppearance = NULL;\r\n\t\r\n\tObj::CPlayerProfileManager* pProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\r\n\tScript::CStruct* pAppearanceStruct;\r\n\tif ( pParams->GetStructure( CRCD(0xefc8944c,\"appearance_structure\"), &pAppearanceStruct, Script::NO_ASSERT ) )\r\n\t{\r\n\t\ttheAppearance.Load( pAppearanceStruct );\r\n\t\tpAppearance = &theAppearance;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint playerNum;\r\n\t\tpParams->GetInteger( CRCD(0x67e6859a,\"player\"), &playerNum, Script::ASSERT );\r\n\r\n\t\tObj::CSkaterProfile* pProfile = pProfileManager->GetProfile( playerNum );\r\n\t\tDbg_Assert( pProfile );\r\n\t\tpAppearance = pProfile->GetAppearance();\r\n\t}\r\n\tDbg_Assert( pAppearance );\r\n\r\n\tObj::CSkaterProfile* pTempProfile = pProfileManager->GetTemporaryProfile( profileName );\r\n\tDbg_Assert( pTempProfile );\r\n\tGfx::CModelAppearance* pTempAppearance = pTempProfile->GetAppearance();\r\n\tDbg_Assert( pTempAppearance );\r\n\r\n\tif ( pParams->ContainsFlag( CRCD(0x3af36e6d,\"NoFaceTexture\") ) )\r\n\t{\r\n\t\tScript::CStruct* pOriginalStructure = pAppearance->GetStructure();\r\n\t\tScript::CStruct* pTempStructure = pTempAppearance->GetStructure();\r\n\t\tpTempStructure->Clear();\r\n\t\tpTempStructure->AppendStructure( pOriginalStructure );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t*pTempAppearance = *pAppearance;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RestoreTemporaryAppearance | \r\nbool ScriptRestoreTemporaryAppearance(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 profileName;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &profileName, Script::ASSERT );\r\n\t\r\n\tint playerNum;\r\n\tpParams->GetInteger( CRCD(0x67e6859a,\"player\"), &playerNum, Script::ASSERT );\r\n\r\n\tObj::CPlayerProfileManager* pProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pProfile = pProfileManager->GetProfile( playerNum );\r\n\tDbg_Assert( pProfile );\r\n\tGfx::CModelAppearance* pAppearance = pProfile->GetAppearance();\r\n\tDbg_Assert( pAppearance );\r\n\r\n\tObj::CSkaterProfile* pTempProfile = pProfileManager->GetTemporaryProfile( profileName );\r\n\tDbg_Assert( pTempProfile );\r\n\tGfx::CModelAppearance* pTempAppearance = pTempProfile->GetAppearance();\r\n\tDbg_Assert( pTempAppearance );\r\n\r\n\tif ( pParams->ContainsFlag( CRCD(0x3af36e6d,\"NoFaceTexture\") ) )\r\n\t{\r\n\t\tScript::CStruct* pOriginalStructure = pAppearance->GetStructure();\r\n\t\tScript::CStruct* pTempStructure = pTempAppearance->GetStructure();\r\n\t\tpOriginalStructure->Clear();\r\n\t\tpOriginalStructure->AppendStructure( pTempStructure );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t*pAppearance = *pTempAppearance;\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SyncPlayer2Profile | \r\nbool ScriptSyncPlayer2Profile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tpPlayerProfileManager->SyncPlayer2();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PreloadModels | \r\nbool ScriptPreloadModels( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t// Load all the files to get them into the asset manager, \r\n\t// while the PRE file is still in memory\r\n\r\n\tMem::PushMemProfile(\"PreLoadModels\");\r\n  \r\n\t// now loop through the NodeArray, looking for single-skinned models\r\n\tScript::CArray *pNodeArray = Script::GetArray( CRCD(0xc472ecc5,\"NodeArray\") );\r\n\tDbg_MsgAssert( pNodeArray, ( \"No NodeArray found in ParseNodeArray\" ) );\r\n\r\n\tfor ( uint32 i = 0; i < pNodeArray->GetSize(); i++ )\r\n\t{\r\n\t\tScript::CStruct* pNode = pNodeArray->GetStructure( i );\r\n\t\tDbg_MsgAssert( pNode, ( \"NULL pNode\" ) );\r\n\r\n\t\t// The following nodes are capable of being ignored in net games\t\t\r\n\t\t\t\t\r\n\t\tif ( Mdl::Skate::Instance()->ShouldBeAbsentNode( pNode ) )\r\n\t\t{\r\n\t\t\t// Don't load, as it's a net game\r\n\t\t}\t\r\n\t\telse \r\n\t\t{\r\n\t\t\tuint32 ClassChecksum = 0;\r\n\t\t\tpNode->GetChecksum( CRCD(0x12b4e660,\"Class\"), &ClassChecksum );\r\n\r\n\t\t\tuint32 TypeChecksum = 0;\r\n\t\t\tpNode->GetChecksum(CRCD(0x7321a8d6,\"Type\"), &TypeChecksum );\r\n\t\t\t\r\n\t\t\t// first eliminate the flag models, if this is non-net game \r\n\t\t\t// On load model IF a multiplayer game OR NOT a flag model\r\n\t\t\tif (Mdl::Skate::Instance()->IsMultiplayerGame() ||\r\n\t\t\t\tTypeChecksum != CRCD(0xbebb41f0,\"Flag_Red\")         && \r\n\t\t\t\tTypeChecksum != CRCD(0x836284a5,\"Flag_Red_Base\")    &&\r\n\t\t\t\tTypeChecksum != CRCD(0xc3ebe05e,\"Flag_Green\") \t\t && \r\n\t\t\t\tTypeChecksum != CRCD(0x4f8ff239,\"Flag_Green_base\")\t &&\r\n\t\t\t\tTypeChecksum != CRCD(0x8cca938a,\"Flag_Blue\")\t\t &&\r\n\t\t\t\tTypeChecksum != CRCD(0x41e5bcf,\"Flag_Blue_base\")\t &&\r\n\t\t\t\tTypeChecksum != CRCD(0xc2af1eb1,\"Flag_Yellow\")\t\t &&\r\n\t\t\t\tTypeChecksum != CRCD(0xed3ad7fe,\"Flag_Yellow_base\") )\r\n\t\t\t{\r\n\t\r\n\t\t\t\t// Handle pre-loading of models for non-net game nodes\r\n\t\t\t\tswitch (ClassChecksum)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase 0xa0dfac98: // Pedestrian\r\n\t\t\t\t\tcase 0xa71394a2: // AnimatingObject\r\n\t\t\t\t\tcase 0x19b1e241: // ParticleEmitter\t\t\t\t\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 0xe47f1b79: // Vehicle\r\n\t\t\t\t\tcase 0xef59c100: // GameObject\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tconst char *pModelName = NULL;\r\n\t\r\n\t\t\t\t\t\t\tif ( pNode->GetText( 0x286a8d26, &pModelName ) ) // checksum 'model'\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tconst char* p_model_name;\r\n\t\t\t\t\t\t\t\tpNode->GetText( CRCD(0x286a8d26,\"model\"), &p_model_name, true );\r\n\t\t\t\t\t\t\t\tif (stricmp(\"none\",p_model_name) != 0)\r\n\t\t\t\t\t\t\t\t{\t\t   \r\n\t\t\t\t\t\t\t\t\tStr::String fullModelName;\r\n\t\t\t\t\t\t\t\t\tfullModelName = Gfx::GetModelFileName(p_model_name, \".mdl\");\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\tNx::CModel* p_dummy = Nx::CEngine::sInitModel();\r\n\t\t\t\t\t\t\t\t\t//Dbg_Message( \"Preloading model %s\", fullModelName.getString() );\r\n\t\r\n\t\t\t\t\t\t\t\t\t//int texDictOffset = 0;\r\n\t\t\t\t\t\t\t\t\t//pNode->GetInteger( \"texDictOffset\", &texDictOffset, false );\r\n\t\r\n\t\t\t\t\t\t\t\t\tbool forceTexDictLookup = pNode->ContainsFlag( CRCD(0x6c37fdc7,\"AllowReplaceTex\") );\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\tp_dummy->AddGeom( fullModelName.getString(), 0, true, 0, forceTexDictLookup );\r\n\t\t\t\t\t\t\t\t\tNx::CEngine::sUninitModel( p_dummy );\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\t\t\t\t\r\n\t}\r\n\r\n\tMem::PopMemProfile(/*\"PreLoadModels\"*/);\r\n\t\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PreloadPedestrians | \r\nbool ScriptPreloadPedestrians( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n//\tTmr::Time baseTime = Tmr::ElapsedTime(0);\r\n\r\n\t// should be skipped for net game?\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tif ( gamenet_man->InNetGame()/* || Mdl::Skate::Instance()->IsMultiplayerGame()*/)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif ( Script::GetInt( \"NoPreloadRandomPeds\", false ) )\r\n\t{\r\n\t\t// some create-a-skater artists don't want to\r\n\t\t// preload their random peds\r\n\t\treturn false;\r\n\t}\r\n\r\n\tMem::PushMemProfile(\"PreLoadPedestrians\");\r\n\r\n\tif (pParams->ContainsFlag(CRCD(0xf6f8e158,\"no_random\")))\r\n\t{\r\n\t\t// This feature used when pre-loading peds for created goals in the park editor,\r\n\t\t// where we don't want loads of parts cos there isn't much memory\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// loop through the master_editable_list, looking for\r\n\t\t// randomizable parts (based on the \"allow_random\" flag\r\n\t\t// which should have been set when preselecting ped parts.\r\n\t\ts_preload_ped_part( Script::GenerateCRC(\"ped_m_head\") );\r\n\t\ts_preload_ped_part( Script::GenerateCRC(\"ped_m_torso\") );\r\n\t\ts_preload_ped_part( Script::GenerateCRC(\"ped_m_legs\") );\r\n\t\ts_preload_ped_part( Script::GenerateCRC(\"ped_f_head\") );\r\n\t\ts_preload_ped_part( Script::GenerateCRC(\"ped_f_torso\") );\r\n\t\ts_preload_ped_part( Script::GenerateCRC(\"ped_f_legs\") );\r\n\t}\r\n\t\r\n\t// should really do an examination of what parts the thing actually uses\r\n\t// and then the levelassetlister should list those...\r\n\r\n\t// loop through the NodeArray, looking for single-skinned models\r\n\tScript::CArray *pNodeArray = Script::GetArray( CRCD(0xc472ecc5,\"NodeArray\") );\r\n\tDbg_MsgAssert( pNodeArray, ( \"No NodeArray found in ParseNodeArray\" ) );\r\n\r\n\tfor ( uint32 i = 0; i < pNodeArray->GetSize(); i++ )\r\n\t{\r\n\t\t// we need to give it a texDictOffset so that it\r\n\t\t// doesn't conflict with the secret ped skaters...\r\n\t\t// (make sure it's less than the cutscene tex dict range, \r\n\t\t// though, or else it would conflict with the cutscene objects)\r\n\t\tint texDictOffset = Mdl::Skate::vMAX_SKATERS;\r\n\r\n        Script::CStruct* pNode = pNodeArray->GetStructure( i );\r\n\t\tDbg_MsgAssert( pNode, ( \"NULL pNode\" ) );\r\n\r\n\t\tuint32 ClassChecksum = 0;\r\n\t\tpNode->GetChecksum( Script::GenerateCRC(\"Class\"), &ClassChecksum );\r\n\r\n\t\tif ( ClassChecksum == Script::GenerateCRC(\"pedestrian\") )\r\n\t\t{\r\n\t\t\tconst char* p_model_name;\r\n\t\t\tif ( pNode->GetText( \"model\", &p_model_name, false ) )\r\n\t\t\t{\r\n\t\t\t\tStr::String fullModelName;\r\n\t\t\t\tfullModelName = Gfx::GetModelFileName(p_model_name, \".skin\");\r\n\r\n\t\t\t\t// preload the model!\r\n\t\t\t\tNx::CModel* pDummy = Nx::CEngine::sInitModel();\r\n//\t\t\t\tDbg_Message(\"Preloading single-skinned ped model %s\", fullModelName.getString() );\r\n\t\t\t\tpDummy->AddGeom( fullModelName.getString(), 0, true, texDictOffset );\r\n\t\t\t\t\r\n\t\t\t\tNx::CEngine::sUninitModel( pDummy );\r\n\t\t\t}\r\n\r\n\t\t\t// preload the shadow if necessary\r\n\t\t\tconst char* p_shadow_model_name;\r\n\t\t\tif ( pNode->GetText( \"shadowmodel\", &p_shadow_model_name, false ) )\r\n\t\t\t{\r\n\t\t\t\tStr::String fullModelName;\r\n\t\t\t\tfullModelName = Gfx::GetModelFileName(p_shadow_model_name, \".mdl\");\r\n\r\n\t\t\t\t// preload the model!\r\n\t\t\t\tNx::CModel* pDummy = Nx::CEngine::sInitModel();\r\n//\t\t\t\tDbg_Message(\"Preloading single-skinned ped model %s\", fullModelName.getString() );\r\n\t\t\t\tpDummy->AddGeom( fullModelName.getString(), 0, true, texDictOffset );\r\n\r\n\t\t\t\tNx::CEngine::sUninitModel( pDummy );\r\n\t\t\t}\r\n\r\n\r\n\t\t\t// now find the non-randoms\r\n\t\t\tuint32 profileName;\r\n\t\t\tif ( pNode->GetChecksum( CRCD(0x7ea855f0,\"profile\"), &profileName, false ) )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pStruct = Script::GetStructure( profileName );\r\n\t\t\t\tif ( pStruct )\t\t\t\t   \r\n\t\t\t\t{\r\n\t\t\t\t\tNx::CModel* pDummy = Nx::CEngine::sInitModel();\r\n\t\t\t\t\tDbg_Assert( pDummy );\r\n  //  \t\t\t\tpDummy->LoadSkeleton( Script::GenerateCRC(\"human\") );\r\n\t\t\t\t\tGfx::CModelAppearance theTempAppearance;\r\n\t\t\t\t\ttheTempAppearance.Load( pStruct, false );\r\n\t\t\t\t\tGfx::CModelBuilder theBuilder( true, texDictOffset );\r\n\t\t\t\t\ttheBuilder.BuildModel( &theTempAppearance, pDummy, NULL, Script::GenerateCRC(\"preload_model_from_appearance\") );\r\n\t\t\t\t\tNx::CEngine::sUninitModel( pDummy );\r\n    \t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n//\tDbg_Message( \"Preloading peds took %d ms\", Tmr::ElapsedTime( baseTime ) );\r\n\t\t\t\r\n\tMem::PopMemProfile(/*\"PreLoadModels\"*/);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PreselectRandomPedestrians | \r\n// Example: PreselectRandomPedestrians part=ped_f_legs list=sch_ped_f_legs num=4\r\nbool ScriptPreselectRandomPedestrians( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 fullPartChecksum;\r\n\tpParams->GetChecksum( CRCD(0xb6f08f39,\"part\"), &fullPartChecksum, Script::ASSERT );\r\n\r\n\tScript::CArray* pFullPartArray = NULL;\r\n\tpFullPartArray = Script::GetArray( fullPartChecksum, Script::ASSERT );\r\n\r\n\tuint32 levelName = Mdl::Skate::Instance()->m_requested_level;\r\n\r\n\tDbg_Message( \"Pre-selecting %s in %s\", Script::FindChecksumName(fullPartChecksum), Script::FindChecksumName(levelName) );\r\n\r\n\t// go through the specified part array,\r\n\t// and remove any \"allow_random\" components...\r\n\tuint32 fullPartArraySize = pFullPartArray->GetSize();\r\n\tfor ( uint32 i = 0; i < fullPartArraySize; i++ )\r\n\t{\r\n\t\tScript::CStruct* pStruct = pFullPartArray->GetStructure( i );\r\n\t\t\r\n\t\t// allowed_to_pick is a temp variable used only by this function...\r\n\t\t// clear it already exists...\r\n\t\tpStruct->RemoveComponent( CRCD(0x355f9467,\"allowed_to_pick\") );\r\n\r\n\t\t// they all default to not be able to be randomized\r\n\t\tpStruct->AddInteger( CRCD(0xf1e3cd22,\"allow_random\"), 0 );\r\n\r\n\t\tpStruct->AddInteger( CRCD(0x92bddfd9,\"already_selected\"), 0 );\r\n\t\t\r\n\t\tpStruct->AddInteger( CRCD(0x4b833e64,\"random_index\"), -1 );\r\n\t}\r\n\t\r\n\tint allowableCount = 0;\r\n\tfor ( uint32 i = 0; i < fullPartArraySize; i++ )\r\n\t{\r\n\t\tScript::CStruct* pStruct = pFullPartArray->GetStructure( i );\r\n\t\t\r\n\t\tbool allowed_to_pick = true;\r\n\r\n\t\t// if it's level-specific...\r\n\t\tScript::CStruct* pLevelSpecificStruct;\r\n\t\tif ( pStruct->ContainsComponentNamed( CRCD(0xf6f8e158,\"no_random\") ) )\r\n\t\t{\r\n\t\t\tallowed_to_pick = false;\r\n\t\t\r\n\t\t\tif ( pStruct->GetStructure( CRCD(0x3598bf7d,\"level_specific\"), &pLevelSpecificStruct, false ) )\r\n\t\t\t{\r\n\t\t\t\t// sanity check:  level_specific and no_random are mutually exclusive\r\n\t\t\t\tScript::PrintContents( pStruct );\r\n\t\t\t\tDbg_MsgAssert( 0, ( \"no_random should not be used with level_specific\" ) );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( pStruct->GetStructure( CRCD(0x3598bf7d,\"level_specific\"), &pLevelSpecificStruct, false ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( !pStruct->ContainsComponentNamed(CRCD(0x94d12f97,\"exclude_from_levels\")), ( \"level_specific and exclude_from_levels are mutually exclusive\" ) )\r\n\r\n\t\t\t// check to see if we're in this level...\r\n\t\t\tallowed_to_pick = pLevelSpecificStruct->ContainsComponentNamed( levelName );\r\n\t\t}\r\n\t\telse if ( pStruct->GetStructure( CRCD(0x94d12f97,\"exclude_from_levels\"), &pLevelSpecificStruct, false ) )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( !pStruct->ContainsComponentNamed(CRCD(0x3598bf7d,\"level_specific\")), ( \"level_specific and exclude_from_levels are mutually exclusive\" ) )\r\n\r\n\t\t\t// check to see if we're in this level...\r\n\t\t\tallowed_to_pick = !pLevelSpecificStruct->ContainsComponentNamed( levelName );\r\n\t\t}\r\n\t\t \r\n\t\tif ( allowed_to_pick )\r\n\t\t{\r\n\t\t\tallowableCount++;\r\n\t\t\tpStruct->AddInteger( CRCD(0x355f9467,\"allowed_to_pick\"), 1 );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// clear the already picked flag\r\n\t\t\tpStruct->AddInteger( CRCD(0x355f9467,\"allowed_to_pick\"), 0 );\r\n\t\t\t\r\n\t\t\tif ( Script::GetInt( \"cas_artist\", false ) )\r\n\t\t\t{\r\n//\t\t\t\tDbg_Message(\"Disallowing...\");\r\n//\t\t\t\tScript::PrintContents(pStruct);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Nolan's Fisherman Example:\r\n\t// If a non-randomized profile explicitly loads up a random ped part anyway,\r\n\t// then add that random ped asset to the pool of allowable randomized ped parts\r\n\tScript::CArray *pNodeArray=Script::GetArray( CRCD(0xc472ecc5,\"NodeArray\") );\r\n\tDbg_MsgAssert( pNodeArray, ( \"No NodeArray found in PreselectRandomPedestrians\" ) );\r\n\tfor ( uint32 i = 0; i < pNodeArray->GetSize(); i++ )\r\n\t{\r\n\t\tScript::CStruct* pNode = pNodeArray->GetStructure( i );\r\n\t\tDbg_MsgAssert( pNode, ( \"NULL pNode\" ) );\r\n\r\n\t\tuint32 ClassChecksum = 0;\r\n\t\tpNode->GetChecksum( Script::GenerateCRC(\"Class\"), &ClassChecksum );\r\n\r\n\t\tif ( ClassChecksum == Script::GenerateCRC(\"pedestrian\") )\r\n\t\t{\r\n\t\t\t// now find the non-randoms\r\n\t\t\tuint32 profileName;\r\n\t\t\tif ( pNode->GetChecksum( CRCD(0x7ea855f0,\"profile\"), &profileName, false ) )\r\n\t\t\t{\r\n\t\t\t\tScript::CStruct* pProfileStruct = Script::GetStructure( profileName );\r\n\t\t\t\tif ( pProfileStruct )\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::CStruct* pVirtualStruct;\r\n\t\t\t\t\tif ( pProfileStruct->GetStructure( fullPartChecksum, &pVirtualStruct, false ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tuint32 descID;\r\n\t\t\t\t\t\tif ( pVirtualStruct->GetChecksum( CRCD(0x4bb2084e,\"desc_id\"), &descID, false ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tScript::CStruct* pActualStruct = Cas::GetOptionStructure( fullPartChecksum, descID, false );\r\n\t\t\t\t\t\t\tif ( pActualStruct && !pActualStruct->ContainsComponentNamed( CRCD(0xf6f8e158,\"no_random\") ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif ( Script::GetInt( \"cas_artist\", false ) )\r\n\t\t\t\t\t\t\t\t{\r\n//\t\t\t\t\t\t\t\t\tDbg_Message( \"Allowing to pick %s\", Script::FindChecksumName( descID ) );\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\tpActualStruct->AddInteger( CRCD(0xf1e3cd22,\"allow_random\"), 1 );\r\n\t\t\t\t\t\t\t\tpActualStruct->AddInteger( CRCD(0x355f9467,\"allowed_to_pick\"), 1 );\r\n\r\n\t\t\t\t\t\t\t\t// these get lowest-priority when randomizing...\r\n\t\t\t\t\t\t\t\tpActualStruct->AddInteger( CRCD(0x92bddfd9,\"already_selected\"), 1 );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// sanity check that the number specified is \r\n\t// greater than the actual number of random parts\r\n\tint numToSelect = allowableCount;\r\n\tpParams->GetInteger( CRCD(0x23bc5091,\"num\"), &numToSelect, Script::NO_ASSERT );\r\n\tif ( numToSelect > allowableCount )\r\n\t{\r\n\t\tDbg_Message( \"Not enough parts in list %s to select from (need %d, have %d)!\", Script::FindChecksumName(fullPartChecksum), numToSelect, allowableCount );\r\n\t\tnumToSelect = allowableCount;\r\n\t}\r\n\r\n\t//-------------------------------------------------------------\r\n\t// look for a item with a universal skin tone first...  if it\r\n\t// exists, automatically preselect it.  otherwise, make sure\r\n\t// that at least one of each skintone is chosen, or else the\r\n\t// skintones may not match up after part randomization.\r\n\tScript::CStruct* pSkinTonePicks[64];\r\n\tint skinToneCount = 0;\r\n\r\n\tCas::BuildRandomSetList( fullPartChecksum, 0, pSkinTonePicks, &skinToneCount );\r\n\tif ( skinToneCount )\r\n\t{\r\n\t\tScript::CStruct* pStruct = pSkinTonePicks[Mth::Rnd( skinToneCount )];\r\n\t\t\r\n\t\tpStruct->AddInteger( CRCD(0xf1e3cd22,\"allow_random\"), 1 );\r\n\t\tpStruct->AddInteger( CRCD(0x355f9467,\"allowed_to_pick\"), 0 );\r\n\t\tpStruct->AddInteger( CRCD(0x4b833e64,\"random_index\"), numToSelect-1 );\r\n\t\tnumToSelect--;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// this code will only kick in if all of the options have a skin-tone\r\n\t\t// (random_set) associated with it \r\n\t\tDbg_MsgAssert( numToSelect >= 3, ( \"Num parts to select (%d) must be >= 3, so that ped skin tones will work (either need to increase '%s' in levels.q, or add at least one universal skintone option)\", numToSelect, Script::FindChecksumName(fullPartChecksum) ) );\r\n\t\t\r\n\t\tScript::CStruct* pStruct;\r\n\r\n\t\tCas::BuildRandomSetList( fullPartChecksum, CRCD(0x94e5a308,\"light\"), pSkinTonePicks, &skinToneCount );\r\n\t\tDbg_MsgAssert( skinToneCount, ( \"Couldn't find light-skinned version of this part %s\", Script::FindChecksumName(fullPartChecksum) ) );\r\n\t\tpStruct = pSkinTonePicks[Mth::Rnd( skinToneCount )];\r\n\t\tpStruct->AddInteger( CRCD(0xf1e3cd22,\"allow_random\"), 1 );\r\n\t\tpStruct->AddInteger( CRCD(0x355f9467,\"allowed_to_pick\"), 0 );\r\n\t\tpStruct->AddInteger( CRCD(0x4b833e64,\"random_index\"), numToSelect-1 );\r\n\t\tnumToSelect--;\r\n\t\t\r\n\t\tCas::BuildRandomSetList( fullPartChecksum, CRCC(0x85aaf0d8,\"tan\"), pSkinTonePicks, &skinToneCount );\r\n\t\tDbg_MsgAssert( skinToneCount, ( \"Couldn't find tan-skinned version of this part %s\", Script::FindChecksumName(fullPartChecksum) ) );\r\n\t\tpStruct = pSkinTonePicks[Mth::Rnd( skinToneCount )];\r\n\t\tpStruct->AddInteger( CRCD(0xf1e3cd22,\"allow_random\"), 1 );\r\n\t\tpStruct->AddInteger( CRCD(0x355f9467,\"allowed_to_pick\"), 0 );\r\n\t\tpStruct->AddInteger( CRCD(0x4b833e64,\"random_index\"), numToSelect-1 );\r\n\t\tnumToSelect--;\r\n\t\t\r\n\t\tCas::BuildRandomSetList( fullPartChecksum, CRCC(0xe4834204,\"dark\"), pSkinTonePicks, &skinToneCount );\r\n\t\tDbg_MsgAssert( skinToneCount, ( \"Couldn't find dark-skinned version of this part %s\", Script::FindChecksumName(fullPartChecksum) ) );\r\n\t\tpStruct = pSkinTonePicks[Mth::Rnd( skinToneCount )];\r\n\t\tpStruct->AddInteger( CRCD(0xf1e3cd22,\"allow_random\"), 1 );\r\n\t\tpStruct->AddInteger( CRCD(0x355f9467,\"allowed_to_pick\"), 0 );\r\n\t\tpStruct->AddInteger( CRCD(0x4b833e64,\"random_index\"), numToSelect-1 );\r\n\t\tnumToSelect--;\r\n\t}\r\n\t//-------------------------------------------------------------\r\n\r\n\t//-------------------------------------------------------------\r\n\t// now, add the \"allow_random\" flag to <numToSelect> of the items in the list...\r\n\tfor ( int i = 0; i < numToSelect; i++ )\r\n\t{\r\n\t\tint allowed_to_pick = 0;\r\n\t\twhile ( !allowed_to_pick )\r\n\t\t{\r\n\t\t\tint randomPick = Mth::Rnd( fullPartArraySize );\r\n\t\t\tDbg_Assert( randomPick >= 0 && randomPick < (int)fullPartArraySize );\r\n\r\n\t\t\tScript::CStruct* pStruct = pFullPartArray->GetStructure( randomPick );\r\n\t\t\tpStruct->GetInteger( CRCD(0x355f9467,\"allowed_to_pick\"), &allowed_to_pick, Script::ASSERT );\r\n\t\t\tif ( allowed_to_pick )\r\n\t\t\t{\r\n\t\t\t\tpStruct->AddInteger( CRCD(0xf1e3cd22,\"allow_random\"), 1 );\r\n\t\t\t\tpStruct->AddInteger( CRCD(0x355f9467,\"allowed_to_pick\"), 0 );\r\n\t\t\t\tpStruct->AddInteger( CRCD(0x4b833e64,\"random_index\"), i );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t//-------------------------------------------------------------\r\n\r\n\t//-------------------------------------------------------------\r\n\t// debugging code to show which items are allowed to be randomized\r\n#ifdef __NOPT_ASSERT__\r\n\tint randomCount = 0;\r\n\t\r\n\tfor ( uint32 i = 0; i < fullPartArraySize; i++ )\r\n\t{\r\n\t\tScript::CStruct* pStruct = pFullPartArray->GetStructure( i );\r\n\t\t\r\n\t\tint allow_random = 0;\r\n\t\tpStruct->GetInteger( CRCD(0xf1e3cd22,\"allow_random\"), &allow_random, Script::ASSERT );\r\n\r\n\t\tuint32 descID;\r\n\t\tpStruct->GetChecksum( CRCD(0x4bb2084e,\"desc_id\"), &descID, Script::ASSERT );\r\n\r\n\t\tif ( allow_random )\r\n\t\t{\r\n\t\t\tDbg_Message( \"Setting random part #%d: %s (%d)\", randomCount++, Script::FindChecksumName(descID), numToSelect );\r\n\t\t}\r\n\t\t\r\n\t\t// get rid of temp variable...\r\n\t\tpStruct->RemoveComponent( CRCD(0x355f9467,\"allowed_to_pick\") );\r\n\t}\r\n#endif // __NOPT_ASSERT__\r\n\t//-------------------------------------------------------------\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptReplaceCarTextures( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t// this is a highly-specific function used for quickly changing\r\n\t// a car's headlight textures for time-of-day stuff\r\n\t// (the previous implementation was too slow, \r\n\t// involving looping through each model component,\r\n\t// getting the model, and attempting to replaceTexture\r\n\t// on it...  this one targets car objects, and\r\n\t// skips over texture dictionaries that have already\r\n\t// been swapped)\r\n\r\n//\tTmr::Time baseTime = Tmr::ElapsedTime(0);\r\n\t\r\n\tint num_to_rebuild = 0;\r\n\r\n\tconst int vMAX_TEX_DICTS = 32;\r\n\tNx::CTexDict* tex_dicts[vMAX_TEX_DICTS];\r\n\tint num_tex_dicts = 0;\r\n\r\n\t// new fast way, just go directly to the components, if any\r\n\t// (this is still kind of slow, so you wouldn't want to call it that often,\r\n\t// maybe only when any hiccups can be masked out with a screen fade or something)\r\n\tObj::CModelComponent *p_component = (Obj::CModelComponent*)Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType( CRC_MODEL );\r\n\twhile( p_component )\r\n\t{\r\n\t\t// GJ TODO:  somehow loop through all the\r\n\t\t// skin assets in the asset manager\r\n\t\tif ( p_component->GetObject()->GetType() == SKATE_TYPE_CAR )\r\n\t\t{\r\n\t\t\tNx::CModel* pModel = p_component->GetModel();\r\n\r\n\t\t\tbool must_rebuild = false;\r\n\r\n\t\t\tfor ( int i = 0; i < pModel->GetNumGeoms(); i++ )\r\n\t\t\t{\r\n\t\t\t\tNx::CTexDict* pTexDict = pModel->GetTexDictByIndex( i );\r\n\r\n\t\t\t\tbool found = false;\r\n\r\n\t\t\t\t// if any tex dict in the model's list\r\n\t\t\t\t// has not been processed yet, then\r\n\t\t\t\t// replace it\r\n\t\t\t\tfor ( int j = 0; j < num_tex_dicts; j++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( pTexDict == tex_dicts[j] )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfound = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( !found )\r\n\t\t\t\t{\r\n\t\t\t\t\t// mark that texture dictionary as\r\n\t\t\t\t\t// processed, so that we don't have\r\n\t\t\t\t\t// to reprocess future objects\r\n                    Dbg_MsgAssert( num_tex_dicts < vMAX_TEX_DICTS, ( \"Too many texture dictionaries to search through\" ) );\r\n\t\t\t\t\ttex_dicts[num_tex_dicts] = pTexDict;\r\n\t\t\t\t\tnum_tex_dicts++;\r\n\t\t\t\t\t\r\n\t\t\t\t\tmust_rebuild = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif ( must_rebuild )\r\n\t\t\t{                \r\n\t\t\t\tnum_to_rebuild++;\r\n\t\t\t\tp_component->CallMemberFunction( CRCD(0x83f9be15,\"Obj_ReplaceTexture\"), pParams, pScript );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_component = (Obj::CModelComponent*)p_component->GetNextSameType();\t\t\r\n\t}\r\n\r\n//\tDbg_Message( \"ReplaceCarTextures on %d items took %d ms\", num_to_rebuild, Tmr::ElapsedTime( baseTime ) );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetUIFromPreferences | \r\n// @parmopt name | field | | field name\r\n// @parmopt string | field | | field string\r\n// @parmopt name | select_if | | check if this name equals the value of\r\n// checksum in the field\r\n// @parmopt name | menu_id | | the menu id to act on if the select_if is true\r\n// @parmopt name | id | | the control id\r\n// @flag mask_password | if set, all letters are replaced with stars \r\nbool ScriptSetUIFromPreferences(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// gets either network or splitscreen prefs, as appropriate\r\n\tPrefs::Preferences* pPreferences = Mdl::GetPreferences( pParams );\r\n\t\r\n\tuint32 field_id;\r\n\r\n\t// look for either a field checksum or string\r\n\tif ( !pParams->GetChecksum(\"field\", &field_id ) )\r\n\t{\r\n\t\tconst char* pFieldName;\r\n\t\tpParams->GetText(\"field\", &pFieldName, true);\r\n\t\tfield_id = Script::GenerateCRC( pFieldName );\r\n\t}\r\n\t\r\n\tuint32 checksum_value1;\r\n\tif ( pParams->GetChecksum( \"select_if\", &checksum_value1 ) )\r\n\t{\t\r\n\t\tScript::CStruct* pStructure = pPreferences->GetPreference( field_id );\r\n\t\tDbg_Assert(pStructure);\r\n\t\tuint32 checksum_value2;\r\n\t\tpStructure->GetChecksum( \"checksum\", &checksum_value2, true );\r\n\r\n\t\tif ( checksum_value1 == checksum_value2 )\r\n\t\t{\r\n\t\t\t/*\r\n\t\t\tuint32 menu_id;\r\n\t\t\tpParams->GetChecksum( \"menu_id\", &menu_id, true );\r\n\t\t\tFront::MenuFactory* menu_factory = Front::MenuFactory::Instance();\r\n\t\t\tFront::MenuElement *pMenuElement=menu_factory->GetMenuElement(menu_id);\r\n\t\t\tFront::VerticalMenu *pMenu=static_cast<Front::VerticalMenu*>(pMenuElement);\r\n\t\t\tDbg_MsgAssert(pMenu,(\"\\n%s\\nNo menu with id '%s' found\",pScript->GetScriptInfo(),Script::FindChecksumName(menu_id)));\r\n\r\n\t\t\tScript::PrintContents(pParams);\r\n\r\n\t\t\tuint32 control_id;\r\n\t\t\tpParams->GetChecksum( \"id\", &control_id, true );\r\n//\t\t\tpParams->GetChecksum( \"control_id\", &control_id, true );\r\n\t\t\tpMenu->AttemptSelect( control_id );\r\n\t\t\t*/\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tuint32 control_name;\r\n\t\tpParams->GetChecksum( \"id\", &control_name, true );\r\n\r\n\t\tint mask_password = pParams->ContainsFlag( \"mask_password\" );\r\n\t\r\n\t\t// update all the elements\r\n\t\tpPreferences->UpdateUIElement( control_name, field_id, mask_password );\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetUIFromSkaterProfile | \r\n// @parm name | field_id | the field id\r\n// @parmopt name | select_if | | \r\n// @parmopt name | menu_id | | the menu id\r\n// @parmopt name | control_id | | \r\n// @parmopt name | slider_id | |\r\nbool ScriptSetUIFromSkaterProfile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\t/*\r\n\tuint32 field_id;\r\n\tpParams->GetChecksum( \"field_id\", &field_id, true );\r\n\r\n\r\n\tFront::MenuFactory* menu_factory = Front::MenuFactory::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile;\r\n\tpSkaterProfile = Mdl::Skate::Instance()->GetCurrentProfile(pParams);\r\n\r\n\tuint32 slider_id;\r\n\tuint32 control_id;\r\n\tuint32 checksum_value;\r\n\tif ( pParams->GetChecksum( \"select_if\", &checksum_value ) )\r\n\t{\r\n\t\tif ( checksum_value == pSkaterProfile->GetChecksumValue(field_id) )\r\n\t\t{\r\n\t\t\tuint32 menu_id;\r\n\t\t\tpParams->GetChecksum( \"menu_id\", &menu_id, true );\r\n\t\t\tFront::MenuElement *pMenuElement=menu_factory->GetMenuElement(menu_id);\r\n\t\t\tFront::VerticalMenu *pMenu=static_cast<Front::VerticalMenu*>(pMenuElement);\r\n\t\t\tDbg_MsgAssert(pMenu,(\"\\n%s\\nNo menu with id '%s' found\",pScript->GetScriptInfo(),Script::FindChecksumName(menu_id)));\r\n\t\t\tpParams->GetChecksum( \"control_id\", &control_id, true );\r\n\t\t\tpMenu->AttemptSelect( control_id );\r\n\t\t}\r\n\t}\r\n\telse if ( pParams->GetChecksum( \"slider_id\", &slider_id ) )\r\n\t{\r\n\t\t// slider element\r\n\t\tFront::SliderMenuElement* pSliderElement = static_cast<Front::SliderMenuElement*>( menu_factory->GetMenuElement( slider_id, true ) );\r\n\t\tpSliderElement->SetValue( pSkaterProfile->GetUIValue(field_id) );\r\n\t}\r\n\telse if ( pParams->GetChecksum( \"control_id\", &control_id ) )\r\n\t{\t\t\r\n\t\tFront::MenuEvent event;\r\n\t\tevent.SetTypeAndTarget(Front::MenuEvent::vSETCONTENTS, control_id );\r\n\t\tevent.GetData()->AddComponent(Script::GenerateCRC(\"string\"), ESYMBOLTYPE_STRING, pSkaterProfile->GetUIString(field_id).getString() );\r\n\t\tmenu_factory->LaunchEvent(&event);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Assert( 0 );\r\n\t}\r\n\t*/\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetPreferencesFromUI | changes field defined by string to value defined by field\r\n// @parm string | string | \r\n// @parm string | field | \r\n// @parmopt name | level_checksum | | \r\nbool ScriptSetPreferencesFromUI(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// gets either network or splitscreen prefs, as appropriate\r\n\tPrefs::Preferences* pPreferences = Mdl::GetPreferences( pParams );\r\n\r\n\tconst char* p_string;\r\n\tpParams->GetText( \"string\", &p_string, true );\r\n\r\n\tconst char* pFieldName;\r\n\tpParams->GetText(\"field\", &pFieldName, true);\r\n\r\n\tDbg_Message( \"Changing field %s to %s\", pFieldName, p_string );\r\n\t\r\n\t// transfer data back into the preferences\r\n\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"ui_string\"), ESYMBOLTYPE_STRING, p_string );\r\n\t\r\n\tuint32 checksum;\r\n\tchecksum = 0;\r\n\tpParams->GetChecksum( \"checksum\", &checksum );\r\n\tpTempStructure->AddComponent( Script::GenerateCRC(\"checksum\"), ESYMBOLTYPE_NAME, (int) checksum );\r\n\r\n\tif( ( stricmp( pFieldName, \"time_limit\" ) == 0 ) ||\r\n\t\t( stricmp( pFieldName, \"horse_time_limit\" ) == 0 ))\r\n\t{\r\n\t\tint time;\r\n\r\n\t\tpParams->GetInteger( \"time\", &time );\r\n\t\tDbg_Message( \"Changing time to %d\", time );\r\n\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"time\"), ESYMBOLTYPE_INTEGER, time );\r\n\t}\r\n\r\n\tif( stricmp( pFieldName, \"target_score\" ) == 0 )\r\n\t{\r\n\t\tint score;\r\n\r\n\t\tif( pParams->GetInteger( \"score\", &score ) == false )\r\n\t\t{\r\n\t\t\tpParams->GetInteger( \"time\", &score, Script::ASSERT );\r\n\t\t\tscore = Tmr::Seconds( score );\r\n\t\t}\r\n\t\t\r\n\t\tDbg_Message( \"Changing score to %d\", score );\r\n\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"score\"), ESYMBOLTYPE_INTEGER, score );\r\n\t}\r\n\r\n\r\n\r\n\tpPreferences->SetPreference( Script::GenerateCRC(pFieldName), pTempStructure );\r\n\tdelete pTempStructure;\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetAllToDefaultStats | \r\nbool ScriptResetAllToDefaultStats( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n//\tTmr::Time baseTime = Tmr::ElapsedTime(0);\r\n\r\n\tScript::CArray* pMasterSkaterArray = Script::GetArray( \"master_skater_list\", Script::ASSERT );\r\n\r\n\tfor ( uint32 i = 0; i < pMasterSkaterArray->GetSize(); i++ )\r\n\t{\r\n\t\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\t\t\r\n\t\tScript::CStruct* pOriginalInfo = pMasterSkaterArray->GetStructure( i );\r\n\r\n\t\tuint32 skaterName;\r\n\t\tpOriginalInfo->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &skaterName, Script::ASSERT );\r\n\r\n\t\tScript::CArray* pStatNameArray = Script::GetArray( \"stat_names\" );\r\n\t\tfor ( uint32 j = 0; j < pStatNameArray->GetSize(); j++ )\r\n\t\t{\r\n\t\t\tScript::CStruct* pStatInfo = pStatNameArray->GetStructure(j);\r\n\t\t\t\r\n\t\t\tuint32 statName;\r\n\t\t\tpStatInfo->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &statName, Script::ASSERT );\r\n\t\t\t\r\n\t\t\tint statVal;\r\n\t\t\tpOriginalInfo->GetInteger( statName, &statVal, Script::ASSERT );\r\n\t\t\tpTempStructure->AddInteger( statName, statVal );\r\n\t\t}\r\n\r\n\t\tint pointsAvailable;\r\n\t\tpOriginalInfo->GetInteger( \"points_available\", &pointsAvailable, Script::ASSERT );\r\n\t\tpTempStructure->AddInteger( \"points_available\", pointsAvailable );\r\n\r\n\t\t// now add it to the corresponding skater profile\r\n\t\tObj::CPlayerProfileManager*\tpPlayerProfileManager=Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\t\tuint32 numProfiles = pPlayerProfileManager->GetNumProfileTemplates();\r\n\t\tfor ( uint32 j = 0; j < numProfiles; j++ )\r\n\t\t{\r\n\t\t\tObj::CSkaterProfile* pProfile = pPlayerProfileManager->GetProfileTemplateByIndex(j);\r\n\t\t\tDbg_Assert( pProfile );\r\n\t\t\tScript::CStruct* pInfo = pProfile->GetInfo();\r\n\r\n\t\t\tuint32 test;\r\n\t\t\tpInfo->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &test, Script::ASSERT );\r\n\t\t\tif ( test == skaterName )\r\n\t\t\t{\r\n\t\t\t\tpInfo->AppendStructure( pTempStructure );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tdelete pTempStructure;\r\n\t}\r\n\r\n//\tDbg_Message( \"ResetAllToDefaultStats took %d ms\", Tmr::ElapsedTime( baseTime ) );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetToDefaultProfile | \r\nbool ScriptResetToDefaultProfile( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n//\tTmr::Time baseTime = Tmr::ElapsedTime(0);\r\n\r\n\tuint32 resetThisSkaterName;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &resetThisSkaterName, Script::ASSERT );\r\n\r\n\tScript::CArray* pMasterSkaterArray = Script::GetArray( \"master_skater_list\", Script::ASSERT );\r\n\r\n\tfor ( uint32 i = 0; i < pMasterSkaterArray->GetSize(); i++ )\r\n\t{\r\n\t\tScript::CStruct* pOriginalInfo = pMasterSkaterArray->GetStructure( i );\r\n\t\tDbg_Assert( pOriginalInfo );\r\n\r\n\t\tuint32 skaterName;\r\n\t\tpOriginalInfo->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &skaterName, Script::ASSERT );\r\n\r\n\t\tif ( resetThisSkaterName == skaterName )\r\n\t\t{\r\n\t\t\tObj::CPlayerProfileManager*\tpPlayerProfileManager=Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\t\t\tObj::CSkaterProfile* pProfile = pPlayerProfileManager->GetProfileTemplate( skaterName );\r\n\t\t\tDbg_Assert( pProfile );\r\n\r\n\t\t\tuint32 partial;\r\n            if ( pParams->GetChecksum( CRCD(0x55f82f0b,\"partial\"), &partial, Script::NO_ASSERT ) )\r\n            {\r\n                // resets appearance, tricks, NOT STATS\r\n                pProfile->PartialReset( pOriginalInfo );\r\n            }\r\n            else\r\n            {\r\n                // resets appearance, stats, tricks\r\n    \t\t\tpProfile->Reset( pOriginalInfo );\r\n            }\r\n\t\t}\r\n\t}\r\n\r\n//\tDbg_Message( \"ResetAllToDefaultProfile took %d ms\", Tmr::ElapsedTime( baseTime ) );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetAllToDefaultProfile | \r\nbool ScriptResetAllToDefaultProfile( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n//\tTmr::Time baseTime = Tmr::ElapsedTime(0);\r\n\r\n\tScript::CArray* pMasterSkaterArray = Script::GetArray( \"master_skater_list\", Script::ASSERT );\r\n\r\n\tfor ( uint32 i = 0; i < pMasterSkaterArray->GetSize(); i++ )\r\n\t{\r\n\t\tScript::CStruct* pOriginalInfo = pMasterSkaterArray->GetStructure( i );\r\n\t\tDbg_Assert( pOriginalInfo );\r\n\r\n\t\tuint32 skaterName;\r\n\t\tpOriginalInfo->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &skaterName, Script::ASSERT );\r\n\r\n\t\tObj::CPlayerProfileManager*\tpPlayerProfileManager=Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\t\tObj::CSkaterProfile* pProfile = pPlayerProfileManager->GetProfileTemplate( skaterName );\r\n\t\tDbg_Assert( pProfile );\r\n\t\t\t\r\n\t\t// resets appearance, stats, tricks\r\n\t\tpProfile->Reset( pOriginalInfo );\r\n\t}\r\n\r\n//\tDbg_Message( \"ResetAllToDefaultProfile took %d ms\", Tmr::ElapsedTime( baseTime ) );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ForEachSkaterName | \r\nbool ScriptForEachSkaterName( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n//\tTmr::Time baseTime = Tmr::ElapsedTime(0);\r\n\r\n\tuint32 scriptToRun;\r\n\tpParams->GetChecksum( CRCD(0x62ba3f6a,\"do\"), &scriptToRun, Script::ASSERT );\r\n\r\n\tScript::CStruct* pSubParams = NULL;\r\n\tpParams->GetStructure( CRCD(0x7031f10c,\"params\"), &pSubParams, Script::NO_ASSERT );\r\n\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tint numProfiles = pPlayerProfileManager->GetNumProfileTemplates();\r\n\tfor ( int i = 0; i < numProfiles; i++ )\r\n\t{\r\n\t\tObj::CSkaterProfile* pProfile = pPlayerProfileManager->GetProfileTemplateByIndex(i);\r\n\t\tDbg_Assert( pProfile );\r\n\t\tScript::CStruct* pInfo = pProfile->GetInfo();\r\n\r\n\t\tuint32 skaterName;\r\n\t\tpInfo->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &skaterName, Script::ASSERT );\r\n\r\n\t\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\t\tpTempStructure->AppendStructure( pSubParams );\r\n\t\tpTempStructure->AddChecksum( CRCD(0xa1dc81f9,\"name\"), skaterName );\r\n\t\tScript::RunScript( scriptToRun, pTempStructure );\r\n\t\tdelete pTempStructure;\r\n\t}\r\n\r\n//\tDbg_Message( \"ScriptForEachSkaterName took %d ms\", Tmr::ElapsedTime( baseTime ) );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ForEachSkaterProfile | \r\nbool ScriptForEachSkaterProfile( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n//\tTmr::Time baseTime = Tmr::ElapsedTime(0);\r\n\r\n\tuint32 scriptToRun;\r\n\tpParams->GetChecksum( CRCD(0x62ba3f6a,\"Do\"), &scriptToRun, Script::ASSERT );\r\n\r\n\tScript::CStruct* pSubParams = NULL;\r\n\tpParams->GetStructure( CRCD(0x7031f10c,\"params\"), &pSubParams, Script::NO_ASSERT );\r\n\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tint numProfiles = pPlayerProfileManager->GetNumProfileTemplates();\r\n\tfor ( int i = 0; i < numProfiles; i++ )\r\n\t{\r\n\t\tObj::CSkaterProfile* pProfile = pPlayerProfileManager->GetProfileTemplateByIndex(i);\r\n\t\tDbg_Assert( pProfile );\r\n\t\tScript::CStruct* pInfo = pProfile->GetInfo();\r\n\r\n\t\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\t\tpTempStructure->AppendStructure( pSubParams );\r\n\t\tpTempStructure->AppendStructure( pInfo );\r\n\t\tScript::RunScript( scriptToRun, pTempStructure );\r\n\t\tdelete pTempStructure;\r\n\t}\r\n\r\n//\tDbg_Message( \"ScriptForEachSkaterProfile took %d ms\", Tmr::ElapsedTime( baseTime ) );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetSkaterProfileInfoByName | appends the skater profile info to the\r\n// calling script's params. returns false if the specified profile can't be found\r\n// @parm name | name | the name to search for\r\nbool ScriptGetSkaterProfileInfoByName( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 name;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &name, Script::ASSERT );\r\n\t\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tint numProfiles = pPlayerProfileManager->GetNumProfileTemplates();\r\n\tfor ( int i = 0; i < numProfiles; i++ )\r\n\t{\r\n\t\tObj::CSkaterProfile* pProfile = pPlayerProfileManager->GetProfileTemplateByIndex(i);\r\n\t\tDbg_Assert( pProfile );\r\n\t\tScript::CStruct* pInfo = pProfile->GetInfo();\r\n\r\n\t\tuint32 test;\r\n\t\tpInfo->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &test, Script::ASSERT );\r\n\t\tif ( test == name )\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AppendStructure( pInfo );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetSkaterProfileInfoByName | appends the skater profile info to the\r\n// calling script's params. returns false if the specified profile can't be found\r\n// @parm name | name | the name to search for\r\n// @parm structure | params | the params structure to append to the skater profile\r\nbool ScriptSetSkaterProfileInfoByName( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 name;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &name, Script::ASSERT );\r\n\r\n\tScript::CStruct* pSubParams = NULL;\r\n\tpParams->GetStructure( \"params\", &pSubParams, Script::ASSERT );\r\n\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tint numProfiles = pPlayerProfileManager->GetNumProfileTemplates();\r\n\tfor ( int i = 0; i < numProfiles; i++ )\r\n\t{\r\n\t\tObj::CSkaterProfile* pProfile = pPlayerProfileManager->GetProfileTemplateByIndex(i);\r\n\t\tDbg_Assert( pProfile );\r\n\t\tScript::CStruct* pInfo = pProfile->GetInfo();\r\n\r\n\t\tuint32 test;\r\n\t\tpInfo->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &test, Script::ASSERT );\r\n\t\tif ( test == name )\r\n\t\t{\r\n\t\t\tpInfo->AppendStructure( pSubParams );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetDefaultAppearance | \r\n// @parm int | skater | the skater to reset\r\nbool ScriptResetDefaultAppearance( Script::CStruct *pParams, Script::CScript *pScript )\r\n{   \r\n\r\n\tObj::CSkaterProfile* pSkaterProfile;\r\n\tpSkaterProfile = Mdl::Skate::Instance()->GetCurrentProfile(pParams);\r\n\tpSkaterProfile->ResetDefaultAppearance();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetDefaultTricks | \r\n// @parm int | skater | the skater to reset\r\nbool ScriptResetDefaultTricks( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\t\r\n\r\n\tObj::CSkaterProfile* pSkaterProfile;\r\n\tpSkaterProfile = Mdl::Skate::Instance()->GetCurrentProfile(pParams);\r\n\tpSkaterProfile->ResetDefaultTricks();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetDefaultStats | \r\n// @parm int | skater | the skater to reset\r\nbool ScriptResetDefaultStats( Script::CStruct *pParams, Script::CScript *pScript )\r\n{   \r\n\r\n\tObj::CSkaterProfile* pSkaterProfile;\r\n\tpSkaterProfile = Mdl::Skate::Instance()->GetCurrentProfile(pParams);\r\n\tpSkaterProfile->ResetDefaultStats();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RandomizeAppearance | \r\n// @parm int | skater | the skater to randomize\r\nbool ScriptRandomizeAppearance( Script::CStruct *pParams, Script::CScript *pScript )\r\n{  \r\n\tDbg_Message( \"STUB:  RandomizeAppearance\" );\r\n\r\n\t/*\r\n\r\n\tObj::CSkaterProfile* pSkaterProfile;\r\n\tpSkaterProfile = Mdl::Skate::Instance()->GetCurrentProfile(pParams);\r\n\tGfx::CModelAppearance* pSkaterAppearance = pSkaterProfile->GetAppearance();\r\n\tDbg_Assert( pSkaterAppearance );\r\n\tpSkaterAppearance->Randomize();\r\n\t */\r\n\r\n\t// Randomize: Randomizes parts, height, weight\r\n\t// Possibly to be moved into script...\r\n\t// Needs to take disqualifications into account\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PrintCurrentAppearance | \r\n// @parm int | skater | the skater num\r\nbool ScriptPrintCurrentAppearance(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\r\n\t\r\n\tObj::CSkaterProfile* pSkaterProfile;\r\n\tpSkaterProfile = Mdl::Skate::Instance()->GetCurrentProfile(pParams);\r\n\tGfx::CModelAppearance* pAppearance;\r\n\tpAppearance = pSkaterProfile->GetAppearance();\r\n\tpAppearance->PrintContents(pAppearance->GetStructure());\r\n\t\r\n\t/*const Gfx::CFaceTexture* p_face = pAppearance->GetFaceTexture();\r\n\tif( p_face && p_face->IsValid())\r\n\t\tpAppearance->GetFaceTexture()->PrintContents();*/\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetNeversoftSkater | \r\n// @parm int | skater | the skater num\r\n// @parm structure | appearance | current appearance structure \r\n// @parm structure | info | current info structure\r\nbool ScriptSetNeversoftSkater(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\r\n\t// debug info:\r\n//\tprintf( \"Set Neversoft Skater\" );\r\n//\tpParams->PrintContents();\r\n\r\n\t// make sure it's a custom skater\r\n\tObj::CSkaterProfile* pSkaterProfile;\r\n\tpSkaterProfile = Mdl::Skate::Instance()->GetCurrentProfile(pParams);\r\n\tDbg_MsgAssert( !pSkaterProfile->IsPro(), ( \"This function only works on a custom skater.\" ) );\r\n\r\n\t// get the current appearance structure\r\n\tScript::CStruct* pAppearanceStructure;\r\n\tpParams->GetStructure( \"appearance\", &pAppearanceStructure, true );\r\n\r\n\t// apply the desired appearance structure\r\n\tGfx::CModelAppearance* pAppearance = pSkaterProfile->GetAppearance();\r\n\tpAppearance->Load( pAppearanceStructure );\r\n\r\n\t// get the current info structure\r\n\tScript::CStruct* pInfoStructure;\r\n\tpParams->GetStructure( \"info\", &pInfoStructure, true );\r\n\r\n\t// append the new info structure\r\n\tScript::CStruct* pInfo = pSkaterProfile->GetInfo();\r\n\tpInfo->AppendStructure( pInfoStructure );\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tScript::PrintContents(pInfo);\r\n#endif\r\n\t// TODO:  since the career is being reset,\r\n\t// we should clear the info too (like stats and trick configs)\r\n\t\r\n\tpSkaterProfile->SetHeadIsLocked( true );\r\n\r\n\t// reset the career as well\r\n//\tObj::CSkaterCareer* pCareer = pSkaterProfile->GetCareer();\r\n//\tpCareer->Reset();\r\n//\r\n//\t// reset the career flags\r\n//\tfor ( int i = 0; i < Script::GetInt( \"FIRST_SHARED_GLOBAL_FLAG\" ); i++ )\r\n//\t{\r\n//\t\tpCareer->UnSetGlobalFlag( i );\r\n//\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CurrentProfileIsLocked | returns true if this skater profile is locked\r\n// @parm int | skater | the skater num\r\nbool ScriptCurrentProfileIsLocked(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\tObj::CSkaterProfile* pSkaterProfile;\r\n\tpSkaterProfile = Mdl::Skate::Instance()->GetCurrentProfile(pParams);\r\n\treturn pSkaterProfile->IsLocked();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetSkaters | skip skaters to their restart points\r\n// can specify either a node number or a node name\r\n// the node number is ued by the \"goto restart\" menu\r\n// @parmopt int | node_number | -1 | number of a node to skip the skater to \r\n// @parmopt name | node_name |  | name of a node to skip the skater to \r\nbool ScriptResetSkaters(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint node = -1;\r\n\tif (!pParams->GetInteger(\"node_number\",&node))\r\n\t{\r\n\t\tuint32\tnode_name;\r\n\t\tif (pParams->GetChecksum(\"node_name\",&node_name))\r\n\t\t{\r\n\t\t\tnode = SkateScript::FindNamedNode(node_name);\r\n\t\t}\t\r\n\t}\r\n\t\t\t\t\t\t \r\n\tMdl::Skate::Instance()->ResetSkaters(node, pParams->ContainsFlag(CRCD(0xd6f06bf6, \"RestartWalking\")));\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetSkaterProfileInfo | Appends the structure to the specified skater\r\n// profile info.  (Should only append the item if the item is of the same\r\n// type)\r\n// @parm int | player | the player slot to set\r\n// @parm structure | params | the stuff to set\r\nbool ScriptSetSkaterProfileInfo(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// now append appropriate data\r\n\tint \tplayerNum;\r\n\tpParams->GetInteger( CRCD(0x67e6859a,\"player\"), &playerNum, Script::ASSERT );\r\n\r\n\tScript::CStruct* pAppendStruct;\r\n\tpParams->GetStructure( \"params\", &pAppendStruct, Script::ASSERT );\r\n\r\n\tObj::CPlayerProfileManager* pProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pProfile = pProfileManager->GetProfile( playerNum );\r\n\tScript::CStruct* pStruct = pProfile->GetInfo();\r\n\r\n\tpStruct->AppendStructure( pAppendStruct );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetSkaterProfileInfo | Returns the skater profile info in the script params\r\n// @parm int | player | the player slot to get\r\n// @parm float | value | value \r\nbool ScriptGetSkaterProfileInfo(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint \tplayerNum;\r\n\tpParams->GetInteger( CRCD(0x67e6859a,\"player\"), &playerNum, Script::ASSERT );\t\r\n\t\r\n\tObj::CPlayerProfileManager* pProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pProfile = pProfileManager->GetProfile( playerNum );\r\n\t\r\n\tDbg_MsgAssert( pScript, ( \"NULL pScript\" ) );\r\n\tDbg_MsgAssert( pScript->GetParams(), ( \"NULL pScript params\" ) );\r\n\r\n\tpScript->GetParams()->AppendStructure( pProfile->GetInfo() );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetSkaterProfileProperty | Debugging function to set individual stats\r\n// @parm int | stat | the stat to set\r\n// @parm float | value | value \r\nbool ScriptSetSkaterProfileProperty(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\tint \tplayerNum;\r\n\tpParams->GetInteger( CRCD(0x67e6859a,\"player\"), &playerNum, Script::ASSERT );\r\n\r\n\tuint32 \tstat;\r\n\tint\t\tvalue;\r\n\tpParams->GetChecksum( NONAME, &stat );\r\n\tpParams->GetInteger( NONAME, &value );\r\n\r\n\t\r\n\tObj::CPlayerProfileManager* pProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pProfile = pProfileManager->GetProfile( playerNum );\r\n\r\n\treturn pProfile->SetPropertyValue( stat, value );\r\n\r\n/*\t// If no skater was specified, change the stats of all local skaters\r\n\tif( pScript->mpObject == NULL )\r\n\t{\r\n\t\tfor( i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )\r\n\t\t{\r\n\t\t\tpSkater = Mdl::Skate::Instance()->GetSkater(i);\r\n\t\t\tif (pSkater && pSkater->IsLocalClient())\t\t\t// Skater might not exist\r\n\t\t\t{\r\n\t\t\t\tpSkater->SetStat((Obj::CSkater::EStat)stat,value);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpSkater = static_cast <Obj::CSkater*>( pScript->mpObject );\r\n\t\tDbg_Assert( pSkater );\r\n\r\n\t\tpSkater->SetStat((Obj::CSkater::EStat)stat,value);\r\n\t}\r\n\t\r\n\treturn true;\r\n*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ToggleAlwaysSpecial | ToggleAlwaysSpecial (on/off) fixes the \r\n// special meter to be always full. <nl>\r\n// ToggleAlwaysSpecial         ; Toggle it (useful for puttin on a button) <nl>\r\n// ToggleAlwaysSpecial on      ; Sets it on <nl>\r\n// ToggleAlwaysSpecial off     ; Sets it off <nl>\r\n// Note that when you set it on, the special meter is immediately full.\r\n// However, when you turn it off, then the special meter will just decay \r\n// normally, so it might not be immediately obvious that you switched it off. \r\nbool ScriptToggleAlwaysSpecial(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tbool on = pParams->ContainsFlag(\"on\");\r\n\tbool off = pParams->ContainsFlag(\"off\");\r\n\t\r\n\r\n\tfor (int i=0;i<8;i++)\r\n\t{\r\n\t\tObj::CSkater *pSkater = Mdl::Skate::Instance()->GetSkater(i);\t\t\t\t\t\t   \r\n\t\tif (pSkater)\t\t\t// Skater might not exist\r\n\t\t{\r\n\t\t\tif (on)\r\n\t\t\t{\r\n\t\t\t\tpSkater->SetAlwaysSpecial(true);\r\n\t\t\t}\r\n\t\t\telse if (off)\r\n\t\t\t{\r\n\t\t\t\tpSkater->SetAlwaysSpecial(false);\r\n\t\t\t}\r\n\t\t\telse \r\n\t\t\t{\r\n\t\t\t\tpSkater->ToggleAlwaysSpecial();\r\n\t\t\t}\r\n\t\t}\t\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | SkaterSpeedGreaterThan | Check the skater speed, as if to have a ped\r\n// not fall when the skater is stationary\r\n// @parm float | speed | Speed to check against\r\nbool ScriptSkaterSpeedGreaterThan( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tfloat speed;\r\n\tif ( pParams->GetFloat( NONAME, &speed ) )\r\n\t{\r\n\t\t\r\n\t\tObj::CSkater *pSkater = Mdl::Skate::Instance()->GetLocalSkater();\t\t\t\t\t\t   \r\n\t\tif ( pSkater )\r\n\t\t{\r\n\t\t\tfloat skaterVel = pSkater->GetVel( ).Length( );\r\n\t\t\tif ( skaterVel > speed)\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | SkaterSpeedLessThan | Check the skater speed, as if to have a ped\r\n// not fall when the skater is stationary\r\n// @parm float | speed | Speed to check against\r\nbool ScriptSkaterSpeedLessThan( Script::CStruct *pParams, Script::CScript *pScript )\r\n{   \r\n\tfloat speed;\r\n\tif ( pParams->GetFloat( NONAME, &speed ) )\r\n\t{\r\n\t\t\r\n\t\tObj::CSkater *pSkater = Mdl::Skate::Instance()->GetLocalSkater();\t\t\t\t\t\t   \r\n\t\tif ( pSkater )\r\n\t\t{\r\n\t\t\tfloat skaterVel = pSkater->GetVel( ).Length( );\r\n\t\t\tif ( skaterVel < speed )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | SkaterLastScoreLandedGreaterThan | Detects last score to trigger if script.\r\n// Example: if SkaterLastScoreLandedGreaterThan 2000 --do cool stuff-- endif\r\n// @uparm 1 | Score (int)\r\nbool ScriptLastScoreLandedGreaterThan( Script::CStruct *pParams, Script::CScript *pScript )\r\n{   \r\n\tint score;\r\n\tscore = s_get_score_from_params( pParams, pScript );\r\n\tMdl::Score *pScore;\r\n\tpScore = s_get_score_struct( );\r\n\tif ( pScore )\r\n\t{\r\n\t\tint scorePot = pScore->GetLastScoreLanded();\r\n\t\tif ( scorePot > score )\r\n\t\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | SkaterLastScoreLandedLessThan | Detects last score to trigger if script.\r\n// Example: if SkaterLastScoreLandedLessThan 2000 --do cool stuff-- endif\r\n// @uparm 1 | Score (int)\r\nbool ScriptLastScoreLandedLessThan( Script::CStruct *pParams, Script::CScript *pScript )\r\n{   \r\n\tint score;\r\n\tscore = s_get_score_from_params( pParams, pScript );\r\n\t\r\n\tMdl::Score *pScore;\r\n\t\r\n\tpScore = s_get_score_struct( );\r\n\tif ( pScore )\r\n\t{\r\n\t\tint scorePot = pScore->GetLastScoreLanded();\r\n\t\tif ( scorePot < score )\r\n\t\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | AnySkaterTotalScoreGreaterThan | Checks if any skaters' score is greater than the score paramter\r\n// Example: if AnySkaterTotalScoreGreaterThan 2000 --do cool stuff-- endif\r\n// @uparm 1 | Score (int)\r\nbool ScriptAnyTotalScoreAtLeast( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\r\n\tGameNet::PlayerInfo* player;\r\n\tLst::Search< GameNet::PlayerInfo > sh;\r\n\tint score;\r\n\tscore = s_get_score_from_params( pParams, pScript );\r\n\r\n\tif( Mdl::Skate::Instance()->GetGameMode()->IsTeamGame())\r\n\t{\r\n\t\tint i;\r\n\t\tint total_score[GameNet::vMAX_TEAMS] = {0};\r\n\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tMdl::Score* pScore = player->m_Skater->GetScoreObject();\r\n\r\n\t\t\ttotal_score[player->m_Team] += pScore->GetTotalScore();\r\n\t\t}\r\n\r\n\t\tfor( i = 0; i < GameNet::vMAX_TEAMS; i++ )\r\n\t\t{\r\n\t\t\tif( total_score[i] >= score )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tif( player->m_Skater )\r\n\t\t\t{\r\n\t\t\t\tMdl::Score *pScore;\r\n\t\r\n\t\t\t\tpScore = player->m_Skater->GetScoreObject();\r\n\t\t\t\tint totalScore = pScore->GetTotalScore();\r\n\t\t\t\tif( totalScore >= score )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptOnlyOneSkaterLeft( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\r\n\tGameNet::PlayerInfo* player;\r\n\tLst::Search< GameNet::PlayerInfo > sh;\r\n\tLst::Search< GameNet::NewPlayerInfo > new_sh;\r\n\tint num_participants_left;\r\n\t\r\n\tnum_participants_left = 0;\r\n\tif( Mdl::Skate::Instance()->GetGameMode()->IsTeamGame())\r\n\t{\r\n\t\tint i;\r\n\t\tint total_score[GameNet::vMAX_TEAMS] = {0};\r\n\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tMdl::Score* pScore = player->m_Skater->GetScoreObject();\r\n\r\n\t\t\ttotal_score[player->m_Team] += pScore->GetTotalScore();\r\n\t\t}\r\n\r\n\t\tfor( i = 0; i < GameNet::vMAX_TEAMS; i++ )\r\n\t\t{\r\n\t\t\tif( total_score[i] > 0 )\r\n\t\t\t{\r\n\t\t\t\tnum_participants_left++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If we're still waiting to load players fully, this test is invalid\r\n\t\tif( gamenet_man->FirstNewPlayerInfo( new_sh ))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint num_players;\r\n\r\n\t\tnum_players = 0;\r\n\t\tfor( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))\r\n\t\t{\r\n\t\t\tif( player->m_Skater )\r\n\t\t\t{\r\n\t\t\t\tMdl::Score *pScore;\r\n\t\r\n\t\t\t\tnum_players++;\r\n\t\t\t\tpScore = player->m_Skater->GetScoreObject();\r\n\t\t\t\tint totalScore = pScore->GetTotalScore();\r\n\t\t\t\tif( totalScore > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tnum_participants_left++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If we're still waiting to load players fully, this test is invalid\r\n\t\tif( gamenet_man->FirstNewPlayerInfo( new_sh ))\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tif( num_players == 1 )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t\r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\tif(\t( gamenet_man->GetHostMode() == GameNet::vHOST_MODE_AUTO_SERVE ) ||\r\n\t\t\t( gamenet_man->GetHostMode() == GameNet::vHOST_MODE_FCFS ))\r\n\t\t{\r\n\t\t\tif( num_participants_left == 0 )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn num_participants_left == 1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | SkaterTotalScoreGreaterThan | Detects last score to trigger if script.\r\n// Example: if SkaterTotalScoreGreaterThan 2000 --do cool stuff-- endif\r\n// @uparm 1 | Score (int)\r\nbool ScriptTotalScoreGreaterThan( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t\r\n\tint score;\r\n\tscore = s_get_score_from_params( pParams, pScript );\r\n\tMdl::Score *pScore;\r\n\tpScore = s_get_score_struct( );\r\n\tif ( pScore )\r\n\t{\r\n\t\tint totalScore = pScore->GetTotalScore();\r\n\t\tif ( totalScore > score )\r\n\t\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | SkaterTotalScoreLessThan | Detects last score to trigger if script.\r\n// Example: if SkaterTotalScoreLessThan 2000 --do cool stuff-- endif\r\n// @uparm 1 | Score (int)\r\nbool ScriptTotalScoreLessThan( Script::CStruct *pParams, Script::CScript *pScript )\r\n{   \r\n\tint score;\r\n\tscore = s_get_score_from_params( pParams, pScript );\r\n\tMdl::Score *pScore;\r\n\tpScore = s_get_score_struct( );\r\n\tif ( pScore )\r\n\t{\r\n\t\tint totalScore = pScore->GetTotalScore();\r\n\t\tif ( totalScore < score )\r\n\t\t\treturn ( true );\r\n\t}\r\n\treturn ( false );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | SkaterCurrentScorePotGreaterThan | Detects last score to trigger if script.\r\n// Example: if SkaterCurrentScorePotGreaterThan 2000 --do cool stuff-- endif\r\n// @uparm 1 | Score (int)\r\nbool ScriptCurrentScorePotGreaterThan( Script::CStruct *pParams, Script::CScript *pScript )\r\n{   \r\n\tint score;\r\n\tint scale;\r\n\t\r\n\tscale = 1;\r\n\tscore = s_get_score_from_params( pParams, pScript );\r\n\tpParams->GetInteger( CRCD(0xb08c5ae8,\"point_scale\"), &scale );\r\n\tscore *= scale;\r\n\r\n\tMdl::Score *pScore;\r\n\tpScore = s_get_score_struct( );\r\n\tif ( pScore )\r\n\t{\r\n\t\tint curScore = pScore->GetScorePotValue();\r\n\t\tif ( curScore > score )\r\n\t\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script bool | SkaterCurrentScorePotLessThan | Detects last score to trigger if script.\r\n// Example: if SkaterCurrentScorePotLessThan 2000 --do cool stuff-- endif\r\n// @uparm 1 | Score (int)\r\nbool ScriptCurrentScorePotLessThan( Script::CStruct *pParams, Script::CScript *pScript )\r\n{   \r\n\tint score;\r\n\tscore = s_get_score_from_params( pParams, pScript );\r\n\tMdl::Score *pScore;\r\n\tpScore = s_get_score_struct( );\r\n\tif ( pScore )\r\n\t{\r\n\t\tint curScore = pScore->GetScorePotValue();\r\n\t\tif ( curScore < score )\r\n\t\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n// @script | SkaterGetScoreInfo | Adds the parameters ScorePot, TotalScore and LastScoreLanded to the script's parameters.\r\nbool ScriptSkaterGetScoreInfo( Script::CStruct *pParams, Script::CScript *pScript )\r\n{   \r\n\tMdl::Score *p_score=s_get_score_struct( );\r\n\t\r\n\tpScript->GetParams()->AddInteger(CRCD(0x95e84391,\"ScorePot\"),p_score->GetScorePotValue());\r\n\tpScript->GetParams()->AddInteger(CRCD(0xee5b2b48,\"TotalScore\"),p_score->GetTotalScore());\r\n\tpScript->GetParams()->AddInteger(CRCD(0xea60ac69,\"LastScoreLanded\"),p_score->GetLastScoreLanded());\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalGreaterThan | Counts the number of goals you have got.\r\n// @uparm 1.0 | value to check\r\nbool ScriptGoalsGreaterThan( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \r\n\tfloat num;\r\n\tif ( pParams->GetFloat( NONAME, &num ) )\r\n\t{\r\n\t\r\n\t\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\t\r\n\t\tif (pCareer->CountTotalGoalsCompleted() > num)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GoalsEqualTo | Counts the number of goals you have got. \r\n// @uparm 1.0 | number of goals\r\nbool ScriptGoalsEqualTo( Script::CStruct *pParams, Script::CScript *pScript )\r\n{  \r\n\tfloat num;\r\n\tif ( pParams->GetFloat( NONAME, &num ) )\r\n\t{\r\n\t\r\n\t\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\t\r\n\t\tif (pCareer->CountTotalGoalsCompleted() == num)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MedalsGreaterThan |  Counts the number of medals you have got.  This \r\n// is just the number of levels you have gotten a medal in, so it will be 0 - 3.\r\n// @uparm 1.0 | number of medals\r\nbool ScriptMedalsGreaterThan( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \r\n\tfloat num;\r\n\tif ( pParams->GetFloat( NONAME, &num ) )\r\n\t{\r\n\t\r\n\t\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\t\r\n\t\tif (pCareer->CountMedals() > num)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MedalsEqualTo |  Counts the number of medals you have got.  This \r\n// is just the number of levels you have gotten a medal in, so it will be 0 - 3.\r\n// @uparm 1.0 | number of medals\r\nbool ScriptMedalsEqualTo( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\tfloat num;\r\n\tif ( pParams->GetFloat( NONAME, &num ) )\r\n\t{\r\n\t\r\n\t\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\t\r\n\t\tif (pCareer->CountMedals() == num)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ToggleSkaterCamMode | Toggles the camera mode for a given skater\r\n// @parm int | skater | \r\nbool ScriptToggleSkaterCamMode(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint skater;\r\n\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skater );\r\n\r\n\t\r\n\tif (!Mdl::Skate::Instance()->GetGameMode()->IsFrontEnd())\r\n\t{\r\n\t\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\t\r\n\t\tObj::CSkater* p_skater = NULL;\r\n\t\t\r\n\t\tif (skater == 0)\r\n\t\t{\r\n\t\t\tGameNet::PlayerInfo* player;\r\n\t\t\tplayer = gamenet_man->GetLocalPlayer();\r\n\t\t\tif( player )\r\n\t\t\t{\r\n\t\t\t\tp_skater = player->m_Skater;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\tp_skater = Mdl::Skate::Instance()->GetSkater( skater );\r\n\t\t}\r\n\t\t\r\n\t\tif( p_skater )\r\n\t\t{\r\n\t\t\t/*\r\n\t\t\tif ( p_skater->GetSkaterCam()->mMode < Obj::CSkaterCam::SKATERCAM_NUM_NORMAL_MODES )\r\n\t\t\t{\r\n\t\t\t\tp_skater->ToggleCamMode();\r\n\t\t\t}\r\n\t\t\t*/\r\n\t\t\tGetSkaterCameraComponentFromObject(p_skater->GetCamera())->ToggleMode();\r\n\t\t\t\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetSkaterID | returns the id of the skater, so that you can run member functions on it from a global script\r\n// @parm int | skater | Which skater's ID you want to grab\r\n// The skater's id is returned in objID, check the script for examples\r\n\r\nbool ScriptGetSkaterID( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t// in this context, skater really means \"viewport\"\r\n\tint skaterId;\r\n\tObj::CSkater* pSkater = NULL;\r\n\tif ( pParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skaterId ) )\r\n\t\t pSkater = Mdl::Skate::Instance()->GetSkater( skaterId );\r\n\telse\t\r\n\t\tpSkater = Mdl::Skate::Instance()->GetLocalSkater();\r\n\t\r\n\tif ( pSkater && pSkater->IsLocalClient() )\r\n\t{\r\n\t\tuint32 id = pSkater->GetID();\r\n\t\tDbg_Assert( pScript && pScript->GetParams() );\r\n\t\tpScript->GetParams()->AddChecksum( \"objID\", id );\r\n\t\t// Dbg_Printf( \"************** SKATER ID %d\\n\", id );\r\n\t\treturn true;\r\n\t}\r\n\tDbg_MsgAssert( 0, ( \"Couldn't find specified skater\" ) );\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetCurrentSkaterID( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tDbg_Assert( pScript->mpObject );\r\n\r\n\tObj::CSkater* pSkater = static_cast <Obj::CSkater*>( pScript->mpObject.Convert() );\r\n\tif( pSkater && pSkater->IsLocalClient() )\r\n\t{\r\n\t\tuint32 id = pSkater->GetID();\r\n\t\tDbg_Assert( pScript && pScript->GetParams() );\r\n\t\tpScript->GetParams()->AddChecksum( \"objID\", id );\r\n\t\t//Dbg_Printf( \"************** SKATER ID %d\\n\", id );\r\n\t\treturn true;\r\n\t}\r\n\tDbg_MsgAssert( 0, ( \"Couldn't find specified skater\" ) );\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetSkaterCamLerpReductionTimer | \r\n// @parmopt float | time | 0.0 | time value\r\nbool ScriptSetSkaterCamLerpReductionTimer( Script::CStruct *pParams, Script::CScript *pScript )\r\n{  \r\n/*\t\r\n\tObj::CSkater* p_skater = static_cast <Obj::CSkater*>( pScript->mpObject.Convert() );\r\n\tDbg_Assert( p_skater );\r\n\r\n\tObj::CSkaterCam* p_cam = p_skater->GetSkaterCam();\r\n\tif( p_cam == NULL )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tfloat time = 0.0f;\r\n\tpParams->GetFloat( 0x906b67ba, &time, true );  // time\r\n\r\n\tp_cam->SetLerpReductionTimer( time );\r\n*/\r\n//\tprintf (\"skfuncs %d: SUTUBBBEDDDDDDDDDDDDDDDDDDDDDDDD\\n\",__LINE__);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PlaySkaterCamAnim | Play a camera animation for a given skater <nl>\r\n// Example usage:\r\n// script play_photoguy_cam\r\n//\t\tTRG_G_TS_PhotoGuy:Obj_GetID\r\n//\t\tPlaySkaterCamAnim skater=0 name=G_TS_CameraStart targetID=objID targetOffset=(0,50,0) positionOffset=(-100, 50, -100)\r\n//\t\t; camera looks at a point 50 units above the photoguy, camera is fixed to a position 50 units above, 100 units behind, and 100 units to the left\r\n// endscript\r\n// @parmopt int | skater | 0 |\r\n// @parmopt name | skaterId | | find the skater by id, rather than index\r\n// @flag stop | \r\n// @parm name | name | the name of the animation\r\n// @flag loop | loop the animation\r\n// @flag focus_skater | \r\n// @flag play_hold | \r\n// @parmopt int | skippable | | whether the movie is skippable\r\n// @parmopt name | exitScript | | name of script to run when the movie finishes/is skipped through\r\n// @parmopt structure | exitParams | | additional parameters to be passed to the exitScript\r\n// @parmopt name | targetID | | m_id of the object to follow (not the node's name!  see example below) \r\n// @parmopt vector | targetOffset | | offset from the specified targetID to look at (in local space, not world space)\r\n// @parmopt vector | positionOffset | | overrides the camera position with the specified offset from the specified targetID\r\nbool ScriptPlaySkaterCamAnim( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tif ( pParams->ContainsFlag( CRCD(0x0c567fa2,\"use_last_camera\") ) )\r\n\t{\r\n\t\t// used so that we don't go back to the skatercam\r\n\t\t// when the \"want to save\" dialog comes up\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tskate_mod->GetMovieManager()->ApplyLastCamera();\r\n\t\treturn true;\r\n\t}\r\n\r\n \t// in this context, skater really means \"viewport\"\r\n\tint skaterIndex = 0;\r\n\tuint32 skaterId;\r\n\tObj::CSkater* pSkater = NULL;\r\n\tif ( pParams->GetChecksum( \"skaterId\", &skaterId, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tObj::CObject* pObj = Obj::ResolveToObject( skaterId);\r\n\t\tDbg_MsgAssert( pObj && pObj->GetType() == SKATE_TYPE_SKATER, ( \"%x is not a skater.\", skaterId ) );\r\n\t\tpSkater = (Obj::CSkater*)pObj;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skaterIndex );\r\n\t\tpSkater = Mdl::Skate::Instance()->GetSkater( skaterIndex );\r\n\t}\r\n\t\r\n\tif ( pSkater )\r\n\t{\r\n\t\tif ( pSkater->IsLocalClient() )\r\n\t\t{\r\n\t\t\t// The stop flag is read with highest priority.\r\n\t\t\tif ( pParams->ContainsFlag( \"stop\" ) )\r\n\t\t\t{\r\n\t\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\t\tskate_mod->GetMovieManager()->ClearMovieQueue();\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tuint32 movieName = 0;\r\n\t\t\t\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &movieName );\r\n\r\n\t\t\t\t// GJ:  The camera may not be framed properly if the\r\n\t\t\t\t// skater was scaled up, so the following script will\r\n\t\t\t\t// shut off the scaling on the skater...  restore_skater_camera\r\n\t\t\t\t// will re-enable it when the movie is done\r\n\t\t\t\tScript::RunScript( CRCD(0xdf00bdff,\"disable_skater_scaling\") );\r\n\r\n\t\t\t\t// start the movie with the default params...\r\n\t\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\t\tskate_mod->GetMovieManager()->AddMovieToQueue( movieName, pParams, CRCD(0x66b7dd11,\"skatercamanim\") );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( !pSkater->IsLocalClient() )\r\n\t\t\t{\r\n\t\t\t\tprintf(\"this isn't a local skater!\\n\");\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetSkaterCamAnimSkippable | set the current anim for a given\r\n// skater as skippable\r\n// @parmopt int | skater | 0 | the skater\r\n// @parmopt name | skaterId | | the id of the skater\r\n// @parmopt int | name | | the name of the movie to set skippable (otherwise, it will use the currently-playing movie)\r\n// @parmopt int | skippable | 0 | set to anything greater than 0 to set anim to skippable\r\nbool ScriptSetSkaterCamAnimSkippable( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t// in this context, skater really means \"viewport\"\r\n\tuint32 skaterId;\r\n\tint skaterIndex = 0;\r\n\r\n\tObj::CSkater* pSkater = NULL;\r\n\tif ( pParams->GetChecksum( \"skaterId\", &skaterId, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tObj::CObject* pObj = Obj::ResolveToObject( skaterId);\r\n\t\tDbg_MsgAssert( pObj && pObj->GetType() == SKATE_TYPE_SKATER, ( \"%x is not a CSkater\", skaterId ) );\r\n\t\tpSkater = (Obj::CSkater*)pObj;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skaterIndex );\r\n\t\tpSkater = Mdl::Skate::Instance()->GetSkater( skaterIndex );\r\n\t}\r\n\t\t\r\n\tif( pSkater && pSkater->IsLocalClient() )\r\n\t{\r\n\t\tuint32 movieName = 0;\r\n\t\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &movieName );\r\n\r\n\t\tint skippable = 0;\r\n\t\tpParams->GetInteger( \"skippable\", &skippable );\r\n\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tskate_mod->GetMovieManager()->SetMovieSkippable( movieName, skippable );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetSkaterCamAnimShouldPause | changes the pause mode of a skater cam.\r\n// If the pause mode is set to false, the cam will play even if the game is paused\r\n// @parmopt name | skaterId | | the id of the skater\r\n// @parmopt int | skater | 0 | the skater index\r\nbool ScriptSetSkaterCamAnimShouldPause( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 skaterId;\r\n\tint skaterIndex = 0;\r\n\tObj::CSkater* pSkater = NULL;\r\n\tif ( pParams->GetChecksum( \"skaterId\", &skaterId, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tObj::CObject* pObj = Obj::ResolveToObject( skaterId);\r\n\t\tDbg_MsgAssert( pObj && pObj->GetType() == SKATE_TYPE_SKATER, ( \"%x is not a CSkater\", skaterId ) );\r\n\t\tpSkater = (Obj::CSkater*)pObj;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skaterIndex );\r\n\t\tpSkater = Mdl::Skate::Instance()->GetSkater( skaterIndex );\r\n\t}\r\n\r\n\tif ( pSkater && pSkater->IsLocalClient() )\r\n\t{\r\n\t\tuint32 movieName = 0;\r\n\t\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &movieName );\r\n\r\n\t\tint should_pause = 0;\r\n\t\tpParams->GetInteger( \"should_pause\", &should_pause );\r\n\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tskate_mod->GetMovieManager()->SetMoviePauseMode( movieName, should_pause );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetCurrentSkaterCamAnimName | returns the name of the current skater cam (if any)\r\nbool ScriptGetCurrentSkaterCamAnimName( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tuint32 movieName = skate_mod->GetMovieManager()->GetCurrentMovieName();\r\n\tif ( movieName != 0 )\r\n\t{\r\n\t\tpScript->GetParams()->AddChecksum( CRCD(0xa1dc81f9,\"name\"), movieName );\r\n\t\treturn true;\r\n\t}\r\n\r\n\tpScript->GetParams()->AddString( CRCD(0xa1dc81f9,\"name\"), \"none\" );\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetSkaterCamAnimParams | returns the params of the current skater cam \r\nbool ScriptGetSkaterCamAnimParams( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 name = 0;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &name, Script::NO_ASSERT );\r\n\t\r\n\tuint32 skaterId;\r\n\tint skaterIndex = 0;\r\n\tObj::CSkater* pSkater = NULL;\r\n\tif ( pParams->GetChecksum( \"skaterId\", &skaterId, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tObj::CObject* pObj = Obj::ResolveToObject( skaterId);\r\n\t\tDbg_MsgAssert( pObj && pObj->GetType() == SKATE_TYPE_SKATER, ( \"%x is not a CSkater\", skaterId ) );\r\n\t\tpSkater = (Obj::CSkater*)pObj;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skaterIndex );\r\n\t\tpSkater = Mdl::Skate::Instance()->GetSkater( skaterIndex );\r\n\t}\r\n\r\n\tif ( pSkater && pSkater->IsLocalClient() )\r\n\t{\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\tScript::CStruct* pMovieParams = skate_mod->GetMovieManager()->GetMovieParams( name );\r\n\t\tif ( pMovieParams )\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AppendStructure( pMovieParams );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SkaterCamAnimFinished | returns true if the anim for the\r\n// given skater is finished\r\n// @parmopt int | skater | 0 | the skater\r\n// @parmopt name | skaterId | | the id of the skater\r\n// @parmopt int | cam | 1 | the camera number \r\nbool ScriptSkaterCamAnimFinished( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t// in this context, skater really means \"viewport\"\r\n\tuint32 skaterId;\r\n\tint skaterIndex = 0;\r\n\tObj::CSkater* pSkater = NULL;\r\n\tif ( pParams->GetChecksum( \"skaterId\", &skaterId, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tObj::CObject* pObj = Obj::ResolveToObject( skaterId);\r\n\t\tDbg_MsgAssert( pObj && pObj->GetType() == SKATE_TYPE_SKATER, ( \"%x is not a CSkater\", skaterId ) );\r\n\t\tpSkater = (Obj::CSkater*)pObj;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skaterIndex );\r\n\t\tpSkater = Mdl::Skate::Instance()->GetSkater( skaterIndex );\r\n\t}\r\n\t\t\r\n\tif( pSkater && pSkater->IsLocalClient() )\r\n\t{\r\n\t\tuint32 movieName = 0;\r\n\t\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &movieName );\r\n\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\treturn skate_mod->GetMovieManager()->IsMovieComplete( movieName );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SkaterCamAnimHeld | returns true if anim is held\r\n// @parmopt int | skater | 0 | the skater\r\n// @parmopt name | skater | | the id of the skater\r\nbool ScriptSkaterCamAnimHeld( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\t\r\n\t// in this context, skater really means \"viewport\"\r\n\tuint32 skaterId;\r\n\tint skaterIndex = 0;\r\n\tObj::CSkater* pSkater = NULL;\r\n\tif ( pParams->GetChecksum( \"skaterId\", &skaterId, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tObj::CObject* pObj = Obj::ResolveToObject( skaterId);\r\n\t\tDbg_MsgAssert( pObj && pObj->GetType() == SKATE_TYPE_SKATER, ( \"%x is not a CSkater\", skaterId ) );\r\n\t\tpSkater = (Obj::CSkater*)pObj;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skaterIndex );\r\n\t\tpSkater = Mdl::Skate::Instance()->GetSkater( skaterIndex );\r\n\t}\r\n\t\t\r\n\tif( pSkater && pSkater->IsLocalClient() )\r\n\t{\r\n\t\tuint32 movieName = 0;\r\n\t\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &movieName );\r\n\r\n\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\treturn skate_mod->GetMovieManager()->IsMovieHeld( movieName );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | KillSkaterCamAnim | \r\n// @parmopt int | skater | 0 | the skater\r\n// @parmopt name | skaterId | | the id of the skater\r\n// @flag current | kill the current cam anim\r\n// @flag all | kill all cam anims\r\nbool ScriptKillSkaterCamAnim( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tbool success = true;\r\n\r\n\t// in this context, skater really means \"viewport\"\r\n\tuint32 skaterId;\r\n\tint skaterIndex = 0;\r\n\tObj::CSkater* pSkater = NULL;\r\n\tif ( pParams->GetChecksum( \"skaterId\", &skaterId, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tObj::CObject* pObj = Obj::ResolveToObject( skaterId);\r\n\t\tDbg_MsgAssert( pObj && pObj->GetType() == SKATE_TYPE_SKATER, ( \"%x is not a CSkater\", skaterId ) );\r\n\t\tpSkater = (Obj::CSkater*)pObj;\r\n\t}\r\n\telse if( pParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skaterIndex ))\r\n\t{\r\n\t\tpSkater = Mdl::Skate::Instance()->GetSkater( skaterIndex );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpSkater = Mdl::Skate::Instance()->GetLocalSkater();\r\n\t}\r\n\t\t\r\n\tif( pSkater && pSkater->IsLocalClient() )\r\n\t{\r\n\t\tif ( pParams->ContainsFlag( \"current\" ) )\r\n\t\t{\r\n\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\tsuccess = skate_mod->GetMovieManager()->AbortCurrentMovie( false );\r\n\t\t}\r\n\t\telse if ( pParams->ContainsFlag( \"all\" ) )\r\n\t\t{\r\n\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\tskate_mod->GetMovieManager()->ClearMovieQueue();\r\n\t\t\tsuccess = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tuint32 movieName = 0;\r\n\t\t\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &movieName, true );\r\n\t\t\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\t\tskate_mod->GetMovieManager()->RemoveMovieFromQueue( movieName );\r\n\t\t\tsuccess = true;\r\n\t\t}\r\n\t}\r\n\r\n\t// GJ:  if the movie queue is empty, it's time to restore the skater\r\n\t// camera (this fixes SK5:TT13239 - \"View goals - camera stays on\r\n\t// view goal position instead of returning to skater when unpausing\"\r\n\t// or one of the park editor cameras\r\n\tif ( !Mdl::Skate::Instance()->GetMovieManager()->IsRolling() )\r\n\t{\r\n\t\tif ( Ed::CParkEditor::Instance()->EditingCustomPark() )\r\n\t\t{\r\n\t\t\tEd::CParkEditor::Instance()->SetAppropriateCamera();\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tScript::RunScript( CRCD(0x15674315,\"restore_skater_camera\") );\r\n\t\t}\r\n\t}\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ReloadSkaterCamAnim | undocumented\r\nbool ScriptReloadSkaterCamAnim( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tif ( !Config::GotExtraMemory() )\r\n\t{\r\n\t\tDbg_Message( \"ReloadSkaterCamAnim:  This function only works with the extra debug heap.  (Otherwise, it would fragment the bottom-up heap.)\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tuint32 animName;\r\n\tconst char* pFileName;\r\n\r\n\tif ( !pParams->GetChecksum( NONAME, &animName, false ) )\r\n\t{\r\n\t\tDbg_Message( \"ReloadSkaterCamAnim:  Missing cam anim name.\\n\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif ( !pParams->GetText( NONAME, &pFileName, false )\t)\r\n\t{\r\n\t\tDbg_Message( \"ReloadSkaterCamAnim:  Missing cam anim filename.\\n\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tDbg_Message( \"Reloading movie %08x with file %s...\", animName, pFileName );\r\n\r\n\t// clear any existing movies in the queue, just in case we were in the middle of playing the anim to be replaced\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tskate_mod->GetMovieManager()->ClearMovieQueue();\r\n\r\n\t// reload the appropriate asset\r\n\tAss::CAssMan * ass_man = Ass::CAssMan::Instance();\r\n\t\r\n\t// on the debug heap\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t\r\n\tbool success =  ass_man->ReloadAsset( animName, pFileName, false );\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PlayCutscene | Play a cutscene\r\nbool ScriptPlayCutscene( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tif( pParams->ContainsFlag( \"stop\" ))\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"stop parameter doesn't work with PlayCutscene\" ) );\r\n\t}\r\n\t\r\n//\tuint32 movieName = 0;\r\n//\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &movieName );\r\n\r\n\t// all cutscenes are named as \"cutscene\"...  this will\r\n\t// help me enforce that there is only one cutscene playing\r\n\t// at any given time...\r\n\tuint32 movieName = CRCD(0xf5012f52,\"cutscene\");\r\n\r\n\t// We don't want any messages showing through the cutscene\r\n\tScript::RunScript(\"destroy_goal_panel_messages\");\r\n\r\n\t// start the movie with the default params...\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tskate_mod->GetMovieManager()->AddMovieToQueue( movieName, pParams, CRCD(0xf5012f52,\"cutscene\") );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | HasMovieStarted | return true if the video of a movie has started \r\n// (after loading data)\r\nbool ScriptHasMovieStarted( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\treturn skate_mod->GetMovieManager()->HasMovieStarted();\r\n}\r\n   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsMovieQueued | return true if there are any movies in the queue,\r\n// regardless of whether the video has started\r\nbool ScriptIsMovieQueued( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\treturn skate_mod->GetMovieManager()->IsMovieQueued();\r\n}\r\n   \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PlayMovingObjectAnim | Play an scene-based animation (earthquake, for instance)\r\nbool ScriptPlayMovingObjectAnim( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tif( pParams->ContainsFlag( \"stop\" ))\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"stop parameter doesn't work with PlayMovingObjectAnim\" ) );\r\n\t}\r\n\t\r\n\tuint32 movieName = 0;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &movieName );\r\n\r\n\tDbg_Message( \"playmovingobjectanim %s\", Script::FindChecksumName(movieName) );\r\n\r\n\t// start the movie with the default params...\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tskate_mod->GetObjectAnimManager()->AddMovieToQueue( movieName, pParams, CRCD(0x12743edb,\"objectanim\") );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetMovingObjectAnimSkippable | set the current movie as skippable\r\n// @parmopt int | name | | the name of the movie to set skippable (otherwise, it will use the currently-playing movie)\r\n// @parmopt int | skippable | 0 | set to anything greater than 0 to set anim to skippable\r\nbool ScriptSetMovingObjectAnimSkippable( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 movieName = 0;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &movieName );\r\n\r\n\tint skippable = 0;\r\n\tpParams->GetInteger( \"skippable\", &skippable );\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tskate_mod->GetObjectAnimManager()->SetMovieSkippable( movieName, skippable );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetMovingObjectAnimShouldPause | changes the pause mode of a skater cam.\r\n// If the pause mode is set to false, the cam will play even if the game is paused\r\nbool ScriptSetMovingObjectAnimShouldPause( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 movieName = 0;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &movieName );\r\n\r\n\tint should_pause = 0;\r\n\tpParams->GetInteger( \"should_pause\", &should_pause );\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tskate_mod->GetObjectAnimManager()->SetMoviePauseMode( movieName, should_pause );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MovingObjectAnimFinished | returns true if the anim for the\r\n// given skater is finished\r\n// @parm int | skater | the skater\r\n// @parmopt int | cam | 1 | the camera number \r\nbool ScriptMovingObjectAnimFinished( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 movieName = 0;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &movieName );\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\treturn skate_mod->GetObjectAnimManager()->IsMovieComplete( movieName );\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | MovingObjectAnimHeld | returns true if anim is held\r\n// @parm int | skater | the skater\r\nbool ScriptMovingObjectAnimHeld( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\t\r\n\tuint32 movieName = 0;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &movieName );\r\n\t\t\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\treturn skate_mod->GetObjectAnimManager()->IsMovieHeld( movieName );\r\n}\r\n\r\n/******************************************************************/\r\n/*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | KillMovingObjectAnim | \r\n// @parmopt int | skater | 0 | the skater\r\n// @flag current | kill the current cam anim\r\n// @flag all | kill all cam anims\r\nbool ScriptKillMovingObjectAnim( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CMovieManager* pObjectAnimManager = skate_mod->GetObjectAnimManager(); \r\n\r\n\tif ( pParams->ContainsFlag( \"current\" ) )\r\n\t{\r\n\t\treturn pObjectAnimManager->AbortCurrentMovie( false );\r\n\t}\r\n\telse if ( pParams->ContainsFlag( \"all\" ) )\r\n\t{\r\n\t\tpObjectAnimManager->ClearMovieQueue();\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tuint32 movieName = 0;\r\n\t\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &movieName, true );\r\n\t\tpObjectAnimManager->RemoveMovieFromQueue( movieName );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ReloadMovingObjectAnim | undocumented\r\nbool ScriptReloadMovingObjectAnim( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tif ( !Config::GotExtraMemory() )\r\n\t{\r\n\t\tDbg_Message( \"ReloadMovingObjectAnim:  This function only works with the extra debug heap.  (Otherwise, it would fragment the bottom-up heap.)\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tuint32 animName;\r\n\tconst char* pFileName;\r\n\r\n\tif ( !pParams->GetChecksum( NONAME, &animName, false ) )\r\n\t{\r\n\t\tDbg_Message( \"ReloadMovingObjectAnim:  Missing cam anim name.\\n\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif ( !pParams->GetText( NONAME, &pFileName, false )\t)\r\n\t{\r\n\t\tDbg_Message( \"ReloadMovingObjectAnim:  Missing cam anim filename.\\n\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tDbg_Message( \"Reloading movie %08x with file %s...\", animName, pFileName );\r\n\r\n\t// clear any existing movies in the queue, just in case we were in the middle of playing the anim to be replaced\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tskate_mod->GetObjectAnimManager()->ClearMovieQueue();\r\n\r\n\t// reload the appropriate asset\r\n\tAss::CAssMan * ass_man = Ass::CAssMan::Instance();\r\n\t\r\n\t// on the debug heap\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t\r\n\tbool success = ass_man->ReloadAsset( animName, pFileName, false );\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// @script | SkaterDebugOn | sets debug to on\r\nbool ScriptSkaterDebugOn(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\tObj::DebugSkaterScripts=true;\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SkaterDebugOff | sets debug to off\r\nbool ScriptSkaterDebugOff(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\tObj::DebugSkaterScripts=false;\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | VibrationIsOn | returns true if vibration for the specified\r\n// player is on\r\n// @uparm 0 | the player \r\nbool ScriptVibrationIsOn(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint i=0;\r\n\tpParams->GetInteger(NONAME,&i);\r\n\tDbg_MsgAssert(i>=0 && i<Mdl::Skate::vMAX_SKATERS, (\"Bad index of %d sent to VibrationIsOn\",i));\r\n\r\n\treturn Mdl::Skate::Instance()->mp_controller_preferences[i].VibrationOn;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | VibrationOn | turns on vibration for the specified player\r\n// @uparm 0 | player\r\nbool ScriptVibrationOn(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint i=0;\r\n\tpParams->GetInteger(NONAME,&i);\r\n\tDbg_MsgAssert(i>=0 && i<Mdl::Skate::vMAX_SKATERS, (\"Bad index of %d sent to VibrationOn\",i));\r\n\t\r\n\tMdl::Skate::Instance()->SetVibration(i,true);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | VibrationOff | turns off vibration for the specified player\r\n// @uparm 0 | the player \r\nbool ScriptVibrationOff(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint i=0;\r\n\tpParams->GetInteger(NONAME,&i);\r\n\tDbg_MsgAssert(i>=0 && i<Mdl::Skate::vMAX_SKATERS, (\"Bad index of %d sent to VibrationOn\",i));\r\n\t\r\n\tMdl::Skate::Instance()->SetVibration(i,false);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AutoKickIsOn | returns true if autokick is on for the specified skater\r\n// @uparmopt 0 | skater\r\nbool ScriptAutoKickIsOn(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\tint i=0;\r\n\tpParams->GetInteger(NONAME,&i);\r\n\tDbg_MsgAssert(i>=0 && i<Mdl::Skate::vMAX_SKATERS, (\"Bad index of %d sent to AutoKickIsOn\",i));\r\n\t\r\n\treturn Mdl::Skate::Instance()->mp_controller_preferences[i].AutoKickOn;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AutoKickOn | turns on autokick for the specified player\r\n// @uparmopt 0 | the skater\r\nbool ScriptAutoKickOn(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\tint i=0;\r\n\tpParams->GetInteger(NONAME,&i);\r\n\tDbg_MsgAssert(i>=0 && i<Mdl::Skate::vMAX_SKATERS, (\"Bad index of %d sent to AutoKickOn\",i));\r\n\t\r\n\tMdl::Skate::Instance()->SetAutoKick(i,true);\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AutoKickOff | turns off autokick for the specified player\r\n// @uparmopt 0 | skater\r\nbool ScriptAutoKickOff(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\tint i=0;\r\n\tpParams->GetInteger(NONAME,&i);\r\n\tDbg_MsgAssert(i>=0 && i<Mdl::Skate::vMAX_SKATERS, (\"Bad index of %d sent to AutoKickOff\",i));\r\n\t\r\n\tMdl::Skate::Instance()->SetAutoKick(i,false);\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SpinTapsAreOn | returns true if spin taps are on\r\n// @uparmopt 0 | skater\r\nbool ScriptSpinTapsAreOn(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\tint i=0;\r\n\tpParams->GetInteger(NONAME,&i);\r\n\tDbg_MsgAssert(i>=0 && i<Mdl::Skate::vMAX_SKATERS, (\"Bad index of %d sent to SpinTapsAreOn\",i));\r\n\t\r\n\t\r\n\treturn Mdl::Skate::Instance()->mp_controller_preferences[i].SpinTapsOn;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SpinTapsOn | turns on spin taps for the specified skater\r\n// @uparmopt 0 | skater\r\nbool ScriptSpinTapsOn(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint i=0;\r\n\tpParams->GetInteger(NONAME,&i);\r\n\tDbg_MsgAssert(i>=0 && i<Mdl::Skate::vMAX_SKATERS, (\"Bad index of %d sent to SpinTapsOn\",i));\r\n\t\r\n\tMdl::Skate::Instance()->SetSpinTaps(i,true);\r\n\treturn true;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SpinTapsOff | turns off spin taps for the specified skater\r\n// @uparmopt 0 | skater\r\nbool ScriptSpinTapsOff(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\tint i=0;\r\n\tpParams->GetInteger(NONAME,&i);\r\n\tDbg_MsgAssert(i>=0 && i<Mdl::Skate::vMAX_SKATERS, (\"Bad index of %d sent to SpinTapsOff\",i));\r\n\t\r\n\tMdl::Skate::Instance()->SetSpinTaps(i,false);\r\n\treturn true;\r\n}\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetCurrentProDisplayInfo | \r\nbool ScriptGetCurrentProDisplayInfo(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetCurrentProfile();\r\n\r\n\tpScript->GetParams()->AddComponent( Script::GenerateCRC( \"string\" ), ESYMBOLTYPE_STRING, pSkaterProfile->GetDisplayName());\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetPlayerAppearance | sets the player appearance \r\n// @parmopt int | player | 0 | index of player whose appearance you want to edit\r\n// @parmopt name | appearance_structure | | the name of the profile\r\nbool ScriptSetPlayerAppearance(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\t\r\n\tint player;\r\n\tpParams->GetInteger( CRCD(0x67e6859a,\"player\"), &player, Script::ASSERT );\r\n\t\r\n\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( player );\r\n\tGfx::CModelAppearance* pAppearance = pSkaterProfile->GetAppearance();\r\n\t\r\n\tScript::CStruct* pAppearanceStruct;\r\n\tpParams->GetStructure( \"appearance_structure\", &pAppearanceStruct, Script::ASSERT );\r\n\tpAppearance->Load( pAppearanceStruct );\r\n\t\r\n\treturn true;\r\n}\r\n\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetPlayerFacePoints | Gets the player face points and puts it in the structure \"current_face_points\"\r\n// @parm int | player | 0 | index of player\r\nbool ScriptGetPlayerFacePoints(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint player;\r\n\tpParams->GetInteger( CRCD(0x67e6859a,\"player\"), &player, Script::ASSERT );\r\n\t\r\n\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( player );\r\n\tGfx::CModelAppearance* pAppearance = pSkaterProfile->GetAppearance();\r\n\t\r\n\tGfx::CFaceTexture* pFaceTexture = pAppearance->GetFaceTexture();\r\n\tDbg_MsgAssert( pFaceTexture, ( \"Appearance doesn't have a face texture1\" ) );\r\n\tDbg_MsgAssert( pFaceTexture->IsValid(), ( \"Face texture has not been initialized with valid texture data\" ) );\r\n\r\n\tScript::CStruct *pFacePointsStruct = NULL;\r\n\r\n\tbool make_new_structure = false;\r\n\tif (!pScript->GetParams()->GetStructure( CRCD(0x12e87395,\"current_face_points\"), &pFacePointsStruct ))\r\n\t{\r\n\t\tpFacePointsStruct = new Script::CStruct;\r\n\t\tmake_new_structure = true;\r\n\t}\r\n\r\n\tNx::SFacePoints theFacePoints;\r\n\ttheFacePoints = pFaceTexture->GetFacePoints( );\r\n\tif ( !Nx::SetFacePointsStruct( theFacePoints, pFacePointsStruct ) )\r\n\t{\r\n\t\tScript::PrintContents( pParams );\r\n\t\tDbg_MsgAssert( 0, (\"Couldn't set face points to structure\") );\r\n\t}\r\n\r\n\tif (make_new_structure)\r\n\t{\r\n\t\tpScript->GetParams()->AddStructure( CRCD(0x12e87395,\"current_face_points\"), pFacePointsStruct );\r\n\t\tdelete pFacePointsStruct;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetPlayerFacePoints |\r\n// @parmopt struct | face_points | face points structure\r\nbool ScriptSetPlayerFacePoints(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint player;\r\n\tpParams->GetInteger( CRCD(0x67e6859a,\"player\"), &player, Script::ASSERT );\r\n\t\r\n\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( player );\r\n\tGfx::CModelAppearance* pAppearance = pSkaterProfile->GetAppearance();\r\n\t\r\n\tGfx::CFaceTexture* pFaceTexture = pAppearance->GetFaceTexture();\r\n\tDbg_MsgAssert( pFaceTexture, ( \"Appearance doesn't have a face texture1\" ) );\r\n\tDbg_MsgAssert( pFaceTexture->IsValid(), ( \"Face texture has not been initialized with valid texture data\" ) );\r\n\r\n\tNx::SFacePoints theFacePoints;\r\n\tScript::CStruct *pFacePointsStruct;\r\n\tif (!pParams->GetStructure(\"face_points\", &pFacePointsStruct))\r\n\t{\r\n\t\tpFacePointsStruct = pParams;\r\n\t}\r\n\tif ( !Nx::GetFacePointsStruct( theFacePoints, pFacePointsStruct ) )\r\n\t{\r\n\t\tScript::PrintContents( pParams );\r\n\t\tDbg_MsgAssert( 0, (\"Couldn't read face points from structure\") );\r\n\t}\r\n\tpFaceTexture->SetFacePoints( theFacePoints );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetPlayerFaceTexture |\r\nbool ScriptSetPlayerFaceTexture(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint player;\r\n\tpParams->GetInteger( CRCD(0x67e6859a,\"player\"), &player, Script::ASSERT );\r\n\t\r\n\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( player );\r\n\tGfx::CModelAppearance* pAppearance = pSkaterProfile->GetAppearance();\r\n\t\r\n\tconst char* pFaceName;\r\n\tpParams->GetText( CRCD(0x7d99f28d,\"texture\"), &pFaceName, Script::ASSERT );\r\n\r\n\t// by default, LoadFace will prepend the filename with \"images\\\\\"\r\n\t// however, the neversoft skater images are located in \"textures\\\\\"\r\n\t// so the following flag will tell LoadFace not to prepend the\r\n\t// filename\r\n\tbool fullPathIncluded = pParams->ContainsFlag( CRCD(0x54c2e57c,\"FullPathIncluded\") );\r\n\r\n\tGfx::CFaceTexture* pFaceTexture = pAppearance->GetFaceTexture();\r\n\tDbg_MsgAssert( pFaceTexture, ( \"Appearance doesn't have a face texture2\" ) );\r\n\tpFaceTexture->LoadFace( pFaceName, fullPathIncluded );\r\n\r\n\tDbg_MsgAssert( pFaceTexture->IsValid(), ( \"Face texture should now be considered valid\" ) );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetPlayerFaceOverlayTexture |\r\nbool ScriptSetPlayerFaceOverlayTexture(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint player;\r\n\tpParams->GetInteger( CRCD(0x67e6859a,\"player\"), &player, Script::ASSERT );\r\n\t\r\n\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( player );\r\n\tGfx::CModelAppearance* pAppearance = pSkaterProfile->GetAppearance();\r\n\t\r\n\tconst char* pOverlayTextureName;\r\n\tpParams->GetText( CRCD(0x7d99f28d,\"texture\"), &pOverlayTextureName, Script::ASSERT );\r\n\r\n\tGfx::CFaceTexture* pFaceTexture = pAppearance->GetFaceTexture();\r\n\tDbg_MsgAssert( pFaceTexture, ( \"Appearance doesn't have a face texture3\" ) );\r\n\tDbg_MsgAssert( pFaceTexture->IsValid(), ( \"Face texture is not valid\" ) );\r\n\r\n\tpFaceTexture->SetOverlayTextureName( pOverlayTextureName );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ClearPlayerFaceTexture |\r\nbool ScriptClearPlayerFaceTexture(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\tint player;\r\n\tpParams->GetInteger( CRCD(0x67e6859a,\"player\"), &player, Script::ASSERT );\r\n\t\r\n\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( player );\r\n\tGfx::CModelAppearance* pAppearance = pSkaterProfile->GetAppearance();\r\n\tDbg_Assert( pAppearance );\r\n\r\n\tGfx::CFaceTexture* pFaceTexture = pAppearance->GetFaceTexture();\r\n\tDbg_MsgAssert( pFaceTexture, ( \"Appearance doesn't have a face texture4\" ) );\r\n\tpFaceTexture->SetValid( false );\r\n#endif\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PlayerFaceIsValid | returns whether the player has already loaded or downloaded a face\r\nbool ScriptPlayerFaceIsValid(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint player;\r\n\tpParams->GetInteger( CRCD(0x67e6859a,\"player\"), &player, Script::ASSERT );\r\n\t\r\n\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( player );\r\n\tGfx::CModelAppearance* pAppearance = pSkaterProfile->GetAppearance();\r\n\tDbg_Assert( pAppearance );\r\n\r\n\tGfx::CFaceTexture* pFaceTexture = pAppearance->GetFaceTexture();\r\n\t//Dbg_MsgAssert( pFaceTexture, ( \"Appearance doesn't have a face texture5\" ) );\r\n    if ( pFaceTexture )\r\n    {\r\n        return pFaceTexture->IsValid();\r\n    }\r\n    else\r\n    {\r\n        //Appearance doesn't have a face texture\r\n        return false;\r\n    }\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SelectCurrentSkater | sets the current profile to the specified skater\r\n// @parmopt name | name | | the name of the profile\r\n// @uparmopt name | name of the profile\r\nbool ScriptSelectCurrentSkater(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\t\r\n\tuint32 profileName;\r\n\tif ( !pParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &profileName, false ) )\r\n\t{\r\n\t\tpParams->GetChecksum( NONAME, &profileName, true );\r\n\t}\r\n\r\n\t\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager=Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetCurrentProfile();\r\n\r\n\t// remember old checksum to see if the data has changed\r\n\tif ( pSkaterProfile->GetSkaterNameChecksum() == profileName )\r\n\t{\r\n\t\t// no change\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tpPlayerProfileManager->ApplyTemplateToCurrentProfile( profileName );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CareerStartLevel | Called at the start of the level, and whenever\r\n// the level is restarted (by a retry, for example).  This will set the level\r\n// number (unless you pass -1, in which case it uses the \"current level\"). This\r\n// will store the values of the career goals, and the level flags, at the start\r\n// of the level, so at the end of the level, we will be able to see if we have\r\n// just got a particular goal, and play appropriate rewards. Currently you\r\n// should not have to mess with this.  I've added appropriate CareerStartLevel \r\n// commands in the level loading script in levels.q.  I've also added (in the\r\n// C++ code) what amounts to \"CareerStartLevel level = -1\" to the \"RestartLevel\"\r\n// function in skate.cpp.  This gets called whenever you restart a level (via\r\n// a retry). \r\n// @parm int | level | the level to start\r\nbool ScriptCareerStartLevel(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint level; \t\t\r\n\tpParams->GetInteger(\"level\", &level, true);  \t\t// Note we assert if \"level\" is missing\r\n\tMdl::Skate::Instance()->GetCareer()->StartLevel(level);\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CareerLevelIs | This is true if the current level number, as specified\r\n// in the last call to CareerStartLevel, matches the value passed, for example: <nl>\r\n// if CareerLevelIs 1 <nl>\r\n//   printf \"Foundry!\" <nl>\r\n// endif\r\n// @uparm 1 | level to check\r\nbool ScriptCareerLevelIs(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint level; \t\t\r\n\tpParams->GetInteger(NONAME, &level, true);\t// Note we assert if the level value is missing\r\n\t\r\n\r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\r\n\treturn pCareer->GetLevel()==level;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetRecordText | \r\n// @parmopt int | level | | level num (default is current level)\r\nbool ScriptGetRecordText(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint level; \t  \r\n\t  \r\n\r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\r\n\tif (!pParams->GetInteger(\"level\", &level, false))\t\r\n\t{\r\n\t\tlevel = pCareer->GetLevel();\r\n\t}\r\n\t\t\t  \r\n\tMdl::Skate::Instance()->GetRecordsText(level);\t\r\n\treturn true;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UpdateRecords | \r\nbool ScriptUpdateRecords(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\tMdl::Skate::Instance()->UpdateRecords();\t\r\n\treturn true;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CareerReset | Resets all the career info back to as if you've\r\n// just started a new career.  Note that this also sets the current level\r\n// to 0 (as you'd not have unlocked any levels).  So if you want to use\r\n// this in the middle of playing a  level, then you'd better add a \"StartLevel\r\n// level = ???\" to set the correct level. See ResetLevelGoals for more\r\nbool ScriptCareerReset(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\r\n\tpCareer->Reset();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetGoal | Sets the goal to the \"got\" state.  All this does\r\n// is set a flag, anything else, like playing sounds, should be done in script\r\n// @parm int | goal | the goal num\r\nbool ScriptSetGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint goal; \t\t\r\n\tpParams->GetInteger(\"goal\", &goal, true);  \t\t// Note we assert if \"goal\" is missing\r\n\t\r\n\r\n\t\r\n\t// if we are not in career mode, then exit  \t\t   \r\n\tif (!Mdl::Skate::Instance()->GetGameMode()->IsTrue( CRCD(0x1ded1ea4,\"is_career\") ) && !Mdl::Skate::Instance()->GetGameMode()->IsFrontEnd() )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\t\r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\r\n\tpCareer->SetGoal(goal);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UnSetGoal | Clears a particular goal flag\r\n// @parm int | goal | goal flag to clear\r\nbool ScriptUnSetGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint goal; \t\t\r\n\tpParams->GetInteger(\"goal\", &goal, true);  \t\t// Note we assert if \"goal\" is missing\r\n\t\r\n\r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\r\n\tpCareer->UnSetGoal(goal);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetGoal | Get the state of a goal.  Will be \"true\" if you have\r\n// got the goal, either in this session, or in some previous session. For\r\n// example: <nl> \r\n// if GetGoal goal = GOAL_SKATE  ; if got SKATE, then do nothing here <nl>\r\n// else <nl>\r\n//   trigger skater letters <nl>\r\n// endif <nl>\r\n// The primary purpose of this function is the modify the functionality\r\n// of the startup script, to stop things from being created, and to modify\r\n// the intro camera. \r\n// @parm int | goal | the goal to check\r\nbool ScriptGetGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint goal; \t\t\r\n\tpParams->GetInteger(\"goal\", &goal, true);  \t\t// Note we assert if \"goal\" is missing\r\n\t\r\n\r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\r\n\treturn pCareer->GetGoal(goal);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | JustGotGoal | Is \"true\" if you got this goal in the current\r\n// session (still valid if the session has just ended). For example: <nl>\r\n// if JustGotoGoal goal = GOAL_SKATE <nl>\r\n//  LaunchPanelMessage \"Yay! You got the skate letters\" <nl>\r\n// endif \r\n// The primary purpose if to play one-time congratulatory sequences at\r\n// the end of the level, in the end-level script.  This flag will only\r\n// be true during the session when you actually get the goal\r\n// @parm int | goal | goal th check\r\nbool ScriptJustGotGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint goal; \t\t\r\n\tpParams->GetInteger(\"goal\", &goal, true);  \t\t// Note we assert if \"goal\" is missing\r\n\t\r\n\r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\r\n\treturn pCareer->JustGotGoal(goal);   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetFlag | similar to setgoal.  there are 32 flags per level,\r\n// numbered 0 - 31.\r\n// @parm int | flag | the flag to set\r\nbool ScriptSetFlag(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint flag; \t\t\r\n\tpParams->GetInteger(\"flag\", &flag, true);  \t\t// Note we assert if \"flag\" is missing\r\n\t\r\n\r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\r\n\tpCareer->SetFlag(flag);\r\n\t\r\n\tif (flag==Script::GetInt(\"GOAL_DECK\"))\r\n\t{\r\n\t\t//Front::GetNewDeck();\r\n\t}\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UnSetFlag | similar to unsetgoal.  there are 32 flags per level,\r\n// numbered 0 - 31.\r\n// @parm int | flag | the flag to unset\r\n// @parmopt int | level | | level number\r\nbool ScriptUnSetFlag(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint flag; \t\t\r\n\tpParams->GetInteger(\"flag\", &flag, true);  \t\t// Note we assert if \"flag\" is missing\r\n\t\r\n\r\n\tint level = -1;\r\n\tpParams->GetInteger( \"level\", &level, Script::NO_ASSERT );\r\n\r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\r\n\tpCareer->UnSetFlag(flag, level);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetFlag | similar to GetGoal.  gets the state of the flag\r\n// @parm int | flag | the flag to get\r\n// @parmopt int | level | | the level number (for level specific flags).  if\r\n// no level number is given, it will use the current level number\r\nbool ScriptGetFlag(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint flag;\r\n\tpParams->GetInteger(\"flag\", &flag, true);  \t\t// Note we assert if \"flag\" is missing\r\n\t\r\n\tint level = 0;\r\n\tpParams->GetInteger( \"level\", &level, Script::NO_ASSERT );\r\n\r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\tif ( level )\r\n\t\treturn pCareer->GetFlag( flag, level );\r\n\r\n\treturn pCareer->GetFlag( flag );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | JustGotFlag | similar to the JustGotGoal command.  returns true\r\n// if we just got this flag\r\n// @parm int | flag | the flag to check\r\nbool ScriptJustGotFlag(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint flag; \t\t\r\n\tpParams->GetInteger(\"flag\", &flag, true);  \t\t// Note we assert if \"flag\" is missing\r\n\t\r\n\r\n\tObj::CSkaterCareer* pCareer = Mdl::Skate::Instance()->GetCareer();\r\n\treturn pCareer->JustGotFlag(flag);\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetGlobalFlag | sets a global flag\r\n// @parm int | flag | the global flag to set\r\nbool ScriptSetGlobalFlag(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tif (!pParams->ContainsComponentNamed(\"flag\"))\r\n\t{\r\n\t\tprintf(\"Call to SetGlobalFlag has no flag (or that flag is undefined.\\n%s\", pScript->GetScriptInfo());\r\n\t\tDbg_Assert(false);\r\n\t}\r\n#endif\r\n\r\n\tint flag; \t\t\r\n\tpParams->GetInteger(CRCD(0x2e0b1465, \"flag\"), &flag, true);  \t\t// Note we assert if \"flag\" is missing\r\n\t\r\n\ts_get_career(flag,pParams)->SetGlobalFlag(flag);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UnSetGlobalFlag | unsets a global flag\r\n// @parm int | flag | the flag to unset\r\nbool ScriptUnSetGlobalFlag(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tif (!pParams->ContainsComponentNamed(\"flag\"))\r\n\t{\r\n\t\tprintf(\"Call to UnSetGlobalFlag has no flag (or that flag is undefined.\\n%s\", pScript->GetScriptInfo());\r\n\t\tDbg_Assert(false);\r\n\t}\r\n#endif\r\n\r\n\tint flag; \t\t\r\n\tpParams->GetInteger(CRCD(0x2e0b1465, \"flag\"), &flag, true);  \t\t// Note we assert if \"flag\" is missing\r\n\t\r\n\r\n\t\r\n\ts_get_career(flag,pParams)->UnSetGlobalFlag(flag);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetGlobalFlag | gets a global flag\r\n// @parm int | flag | the flag to get\r\nbool ScriptGetGlobalFlag(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tif (!pParams->ContainsComponentNamed(\"flag\"))\r\n\t{\r\n\t\tprintf(\"Call to GetGlobalFlag has no flag (or that flag is undefined.\\n%s\", pScript->GetScriptInfo());\r\n\t\tDbg_Assert(false);\r\n\t}\r\n#endif\r\n\t\r\n\tint flag; \t\t\r\n\tpParams->GetInteger(CRCD(0x2e0b1465, \"flag\"), &flag, true);  \t\t// Note we assert if \"flag\" is missing\r\n\t\r\n\treturn Mdl::Skate::Instance()->GetCareer()->GetGlobalFlag(flag);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ProfileEquals | tells us whether the skater matches the given\r\n// criteria.  example: <nl>\r\n// if ProfileEquals is_pro\r\n// @flag is_pro | check if this is a pro skater\r\n// @flag is_custom | check if this is a custom skater\r\n// @parmopt name | is_named | | check if the skater has the specified name\r\n// @parmopt name | stance | | check for this stance\r\nbool ScriptProfileEquals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// look for the specified skater (0 by default)\r\n\tObj::CSkater* pSkater;\r\n\t\r\n\t// if this function is being called through\r\n\t// a skater script, then use the specified skater...\r\n\tif( pScript && pScript->mpObject && pScript->mpObject->GetType() == SKATE_TYPE_SKATER )\t\r\n\t{\r\n\t\tpSkater = (Obj::CSkater *) pScript->mpObject.Convert();\r\n\t\treturn pSkater->SkaterEquals( pParams );\r\n\t}\r\n\r\n\tif ( !Mdl::Skate::Instance()->IsMultiplayerGame() || Mdl::Skate::Instance()->GetGameMode()->IsFrontEnd() )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"ProfileEquals should only be called from a skater script in a multiplayer game.\" ) );\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// otherwise, get the first skater and check him\r\n\tpSkater = Mdl::Skate::Instance()->GetSkater( 0 );\r\n\tif( pSkater == NULL )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn pSkater->SkaterEquals( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsCareerMode | returns true if the current game mode is\r\n// career mode\r\nbool ScriptIsCareerMode(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\r\n\treturn Mdl::Skate::Instance()->GetGameMode()->IsTrue( CRCD(0x1ded1ea4,\"is_career\") );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ClearScoreGoals | clears all the score goals\r\nbool ScriptClearScoreGoals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\tMdl::Skate::Instance()->ClearScoreGoals();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetScoreGoal | used to add a new score goal.  examples: <nl>\r\n// SetScoreGoal  score = 1200000 goalscript = Got_SickScore goal=GOAL_SICKSCORE <nl>\r\n// SetScoreGoal    score = 30000 goalscript = Got_HighScore goal=GOAL_HIGHSCORE\r\n// @parm int | score | the score value for this goal\r\n// @parm name | goalscript | the script to run \r\n// @parm int | goal | goal number\r\nbool ScriptSetScoreGoal(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint score;\r\n\tpParams->GetInteger(\"score\", &score, true);\r\n\tuint32\tscript;\r\n\tpParams->GetChecksum(\"goalscript\", &script, true);\r\n\tint\tgoal;\r\n\tpParams->GetInteger(\"goal\", &goal, true);\r\n\r\n\t\r\n\t// Note, for now we are just using the goal number as an index into the table\r\n\t// so long as we have enough entries, we will be fine\r\n\tMdl::Skate::Instance()->SetScoreGoalScore(goal,score);\r\n\tMdl::Skate::Instance()->SetScoreGoalScript(goal,script);\r\n\tMdl::Skate::Instance()->SetScoreGoalGoal(goal,goal);\r\n\t\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EndRun | This command will end the current run (same as\r\n// used by the \"end run\" selection in the pause menu)\r\nbool ScriptEndRun(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\tMdl::Skate::Instance()->EndRun();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ShouldEndRun | if \"end run\" was selected from the menu\r\n// of the end conditions for this game mode have been met\r\nbool ScriptShouldEndRun(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\t// if \"end run\" was selected from the menu or the\r\n\t// end conditions for this game mode have been met\r\n\treturn ( Mdl::Skate::Instance()->EndRunSelected() || Mdl::Skate::Instance()->GetGameMode()->EndConditionsMet() );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | InitializeSkaters | \r\nbool ScriptInitializeSkaters(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\t\r\n\r\n\tfor ( unsigned int i = 0; i < Mdl::Skate::Instance()->GetNumSkaters(); i++)\r\n\t{\r\n\t\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetSkater(i);\r\n\t\tDbg_Assert( pSkater );\r\n\t\tif( pSkater->IsLocalClient())\r\n\t\t{\r\n\t\t\tpSkater->Reset();\r\n\t\t}\r\n\t\tMdl::Skate::Instance()->HideSkater( pSkater, false );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EndRunSelected | true if \"end run\" was selected from the menu\r\nbool ScriptEndRunSelected(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\t// if \"end run\" was selected from the menu\r\n\treturn Mdl::Skate::Instance()->EndRunSelected();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AllSkatersAreIdle | true if all skaters are idle\r\nbool ScriptAllSkatersAreIdle(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\treturn Mdl::Skate::Instance()->SkatersAreIdle();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | FirstTrickStarted | should only be called in horse mode.  \r\nbool ScriptFirstTrickStarted(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\treturn Mdl::Skate::Instance()->FirstTrickStarted();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | FirstTrickCompleted | should only be called in horse mode\r\nbool ScriptFirstTrickCompleted(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\treturn Mdl::Skate::Instance()->FirstTrickCompleted();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CalculateFinalScores | final scores for all skaters on server\r\nbool ScriptCalculateFinalScores(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\t\r\n\r\n\tif( gamenet_man->OnServer())\r\n\t{\r\n\t\tMdl::Skate::Instance()->SendScoreUpdates( true );\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn gamenet_man->HaveReceivedFinalScores();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ReinsertSkaters | adds all skaters to the current world\r\nbool ScriptReinsertSkaters(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n    // For now, this is commented out, until I can get the\r\n    // skin model functionality over into the new CModel class.\r\n\t\r\n\t// synchronous, no need to pass through net msgs\r\n\t// add the skaters back to the world\r\n\t\r\n\tfor ( uint32 i = 0; i < Mdl::Skate::Instance()->GetNumSkaters(); i++ )\r\n\t{   \r\n\t\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetSkater( i );\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterHeap(pSkater->GetHeapIndex()));\r\n\t\tpSkater->AddToCurrentWorld();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UnhookSkaters | Unhook the skaters from the world, so it can be unloaded\r\nbool ScriptUnhookSkaters(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tfor ( uint32 i = 0; i < Mdl::Skate::Instance()->GetNumSkaters(); i++ )\r\n\t{   \r\n\t\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetSkater( i );\r\n\t\tpSkater->RemoveFromCurrentWorld();\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ApplySplitScreenOptions | applies various split screen prefs - \r\n// game type, time limit, etc.\r\nbool ScriptApplySplitScreenOptions(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tPrefs::Preferences* pPreferences;\r\n\r\n\tpPreferences = Mdl::Skate::Instance()->GetSplitScreenPreferences();\r\n\tDbg_Assert(pPreferences);\r\n\r\n\tScript::CStruct* pStructure;\r\n\tuint32 checksum;\r\n\r\n\t// change the game type\r\n\tpStructure = pPreferences->GetPreference( Script::GenerateCRC(\"game_type\") );\r\n\tDbg_Assert(pStructure);\r\n\tpStructure->GetChecksum( \"checksum\", &checksum, true );\r\n\tMdl::Skate::Instance()->GetGameMode()->LoadGameType( checksum );\r\n\r\n\tint time_limit = pPreferences->GetPreferenceValue( Script::GenerateCRC(\"time_limit\"), Script::GenerateCRC(\"time\") );\r\n\r\n\tif ( Mdl::Skate::Instance()->GetGameMode()->IsTrue( \"is_horse\" ) )\r\n\t{\r\n\t\ttime_limit = pPreferences->GetPreferenceValue( Script::GenerateCRC(\"horse_time_limit\"), Script::GenerateCRC(\"time\") );\r\n\t\tMdl::Skate::Instance()->GetHorse()->SetWord( pPreferences->GetPreferenceString(  Script::GenerateCRC(\"horse_word\"), Script::GenerateCRC(\"ui_string\") ) );\r\n\r\n\t\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"default_time_limit\"), ESYMBOLTYPE_INTEGER, time_limit );\r\n\t\tMdl::Skate::Instance()->GetGameMode()->OverrideOptions( pTempStructure );\t\t\r\n\t\tMdl::Skate::Instance()->SetTimeLimit( time_limit );\r\n\t\tdelete pTempStructure;\r\n\r\n\t\t//Mdl::Skate::Instance()->SetShadowMode( Gfx::vDETAILED_SHADOW );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//Mdl::Skate::Instance()->SetShadowMode( Gfx::vSIMPLE_SHADOW );\r\n\t}\r\n\t\r\n\t/*if( Mdl::Skate::Instance()->GetGameMode()->IsTrue( \"is_king\" ))\r\n\t{\r\n\t\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\t\tScript::CArray* pArray = new Script::CArray;\r\n\t\tScript::CopyArray(pArray,Script::GetArray(\"targetScoreArray\"));\r\n\t\tScript::CStruct* pSubStruct = pArray->GetStructure(0);\r\n\t\tDbg_Assert(pSubStruct);\r\n\t\tpSubStruct->AddComponent(Script::GenerateCRC(\"score\"),ESYMBOLTYPE_INTEGER, (int) Tmr::Seconds( time_limit ));\r\n\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"default_time_limit\"), ESYMBOLTYPE_INTEGER, (int) 0 );\r\n\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"victory_conditions\"), pArray );\r\n\t\tMdl::Skate::Instance()->GetGameMode()->OverrideOptions( pTempStructure );\r\n\t\tMdl::Skate::Instance()->SetTimeLimit( 0 );\r\n\t\tdelete pTempStructure;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// if the time limit is fixed, then don't override it\r\n\t\tif ( !Mdl::Skate::Instance()->GetGameMode()->IsTimeLimitConfigurable() )\r\n\t\t{\r\n\t\t\ttime_limit = Mdl::Skate::Instance()->GetGameMode()->GetTimeLimit();\r\n\t\t}\r\n\r\n\t\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\t\tpTempStructure->AddComponent( Script::GenerateCRC(\"default_time_limit\"), ESYMBOLTYPE_INTEGER, time_limit );\r\n\t\tMdl::Skate::Instance()->GetGameMode()->OverrideOptions( pTempStructure );\t\t\r\n\t\tMdl::Skate::Instance()->SetTimeLimit( time_limit );\r\n\t\tdelete pTempStructure;\r\n\t}\r\n\t\r\n//\tprintf(\"Applying time limit\\n\");\r\n//\tpTempStructure->PrintContents();\r\n\r\n\t// update all the skaters' stats\r\n\tfor ( unsigned int i = 0; i < Mdl::Skate::Instance()->GetNumSkaters(); i++)\r\n\t{\r\n\t\tObj::CSkater *pSkater = Mdl::Skate::Instance()->GetSkater(i);\r\n\t\tDbg_Assert( pSkater );\r\n\r\n\t\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( pSkater->GetID() );\r\n\t\tpSkater->UpdateStats( pSkaterProfile );\r\n\t}*/\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StartCompetition | \r\n// @parm float | gold | \r\n// @parm float | silver | \r\n// @parm float | bronze | \r\n// @parm float | gold_score |\r\n// @parm float | silver_score | \r\n// @parm float | bronze_score | \r\n// @parm float | bail | \r\nbool ScriptStartCompetition(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\t\r\n//\tfloat bronze, float silver, float gold, float bronze_score, float silver_score, float gold_score, float bail)\r\n\tfloat\tgold,silver,bronze;\r\n\tfloat\tgold_score,silver_score,bronze_score;\r\n\tfloat \tbail;\r\n\t\r\n\tif (!pParams->GetFloat(\"gold\",&gold))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"\\n%s\\nStartCompetition missing 'gold' parameter\",pScript->GetScriptInfo()));\t\t\r\n\t}\r\n\t\r\n\tif (!pParams->GetFloat(\"silver\",&silver))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"\\n%s\\nStartCompetition missing 'silver' parameter\",pScript->GetScriptInfo()));\t\t\r\n\t}\r\n\t\t\r\n\tif (!pParams->GetFloat(\"bronze\",&bronze))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"\\n%s\\nStartCompetition missing 'bronze' parameter\",pScript->GetScriptInfo()));\t\t\r\n\t}\r\n\tif (!pParams->GetFloat(\"gold_score\",&gold_score))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"\\n%s\\nStartCompetition missing 'gold_score' parameter\",pScript->GetScriptInfo()));\t\t\r\n\t}\r\n\t\r\n\tif (!pParams->GetFloat(\"silver_score\",&silver_score))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"\\n%s\\nStartCompetition missing 'silver_score' parameter\",pScript->GetScriptInfo()));\t\t\r\n\t}\r\n\t\t\r\n\tif (!pParams->GetFloat(\"bronze_score\",&bronze_score))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"\\n%s\\nStartCompetition missing 'bronze_score' parameter\",pScript->GetScriptInfo()));\t\t\r\n\t}\r\n\tif (!pParams->GetFloat(\"bail\",&bail))\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"\\n%s\\nStartCompetition missing 'bail' parameter\",pScript->GetScriptInfo()));\t\t\r\n\t}\r\n\tScript::CStruct* pExtraParams = NULL;\r\n\tpParams->GetStructure( CRCD(0xa61dc9a4,\"extra_params\"), &pExtraParams, Script::NO_ASSERT );\r\n\r\n\t// Need to use SkaterInfoHeap, as new strings can get created, which can fragment memory \t\t\t\t\t\t\t\t\t   \r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\t\r\n\tif ( pExtraParams )\r\n\t\tMdl::Skate::Instance()->GetCompetition()->EditParams( pExtraParams );\r\n\tMdl::Skate::Instance()->GetCompetition()->StartCompetition(bronze, silver, gold, bronze_score, silver_score, gold_score, bail);\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StartCompetitionRun | \r\nbool ScriptStartCompetitionRun(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tMdl::Skate::Instance()->GetCompetition()->StartRun();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EndCompetitionRun | \r\nbool ScriptEndCompetitionRun(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tObj::CSkater *pSkater = Mdl::Skate::Instance()->GetLocalSkater();\t\t\t\t\t\t   \r\n\tMdl::Score *pScore=pSkater->GetScoreObject();\r\n\tint score = pScore->GetTotalScore();\r\n\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\tMdl::Skate::Instance()->GetCompetition()->EndRun(score);\r\n\tMdl::Skate::Instance()->GetCompetition()->SetupJudgeText();\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsTopJudge | true if the specified judge is the top judge\r\n// @uparm 1 | judge num\r\nbool ScriptIsTopJudge(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\tint judge;\r\n\tpParams->GetInteger(NONAME,&judge);\r\n\r\n\t\r\n\treturn Mdl::Skate::Instance()->GetCompetition()->IsTopJudge(judge);\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PlaceIs | true if the comp place is equal to the specified place\r\n// @uparm 1 | place\r\nbool ScriptPlaceIs(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint place;\r\n\tpParams->GetInteger(NONAME,&place);\r\n\r\n\t\r\n\treturn Mdl::Skate::Instance()->GetCompetition()->PlaceIs(place);\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RoundIs | true if the round equals the specified round\r\n// @uparm 1 | round\r\nbool ScriptRoundIs(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint round;\r\n\tpParams->GetInteger(NONAME,&round);\r\n\r\n\t\r\n\treturn Mdl::Skate::Instance()->GetCompetition()->RoundIs(round);\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EndCompetition | \r\nbool ScriptEndCompetition(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());\r\n\tMdl::Skate::Instance()->GetCompetition()->EndCompetition();\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CompetitionEnded | true if the comp has ended\r\nbool ScriptCompetitionEnded(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\treturn Mdl::Skate::Instance()->GetCompetition()->CompetitionEnded();\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StartHorse |\r\nbool ScriptStartHorse(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tMdl::Skate::Instance()->GetHorse()->Init();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EndHorse | \r\nbool ScriptEndHorse(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | HorseEnded | true if horse has ended\r\nbool ScriptHorseEnded(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\t\r\n\treturn Mdl::Skate::Instance()->GetHorse()->Ended();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | HorseStatusEquals | pass in one or more of the flags to check status\r\n// @flag GotLetter |\r\n// @flag TieScore |\r\n// @flag BeatScore |\r\n// @flag Ended |\r\n// @flag Idle |\r\n// @flag NoScoreSet |\r\n// @flag Terminator |\r\nbool ScriptHorseStatusEquals(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\treturn Mdl::Skate::Instance()->GetHorse()->StatusEquals( pParams );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | StartHorseRun | \r\nbool ScriptStartHorseRun(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tMdl::Skate::Instance()->GetHorse()->StartRun();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EndHorseRun | \r\nbool ScriptEndHorseRun(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tMdl::Skate::Instance()->GetHorse()->EndRun();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SwitchHorsePlayers | switches to the next valid player\r\nbool ScriptSwitchHorsePlayers(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tMdl::Skate::Instance()->GetHorse()->SwitchPlayers();\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ApplyToHorsePanelString | \r\n// @parm name | whichString | the string to apply to\r\nbool ScriptApplyToHorsePanelString(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 whichString, id;\r\n\tpParams->GetChecksum( \"whichString\", &whichString, true );\r\n\tpParams->GetChecksum( \"id\", &id, true );\r\n\t\r\n\tStr::String horseString = Mdl::Skate::Instance()->GetHorse()->GetString( whichString );\r\n\r\n\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetSkaterById( Mdl::Skate::Instance()->GetHorse()->GetCurrentSkaterId() );\r\n\tDbg_Assert( pSkater );\r\n\t\r\n\tScript::CStruct* pTempStructure = new Script::CStruct;\r\n\t*pTempStructure+=*pParams;\r\n\tpTempStructure->AddString( \"text\", horseString.getString() );\r\n\tpTempStructure->AddChecksum( \"id\", id );\r\n\tScript::RunScript( \"create_horse_panel_message\", pTempStructure, pSkater );\r\n\tdelete pTempStructure;\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// @parm name | whichString | the string to apply to\r\n// @parmopt int | skater | 0 | the skater we're applying to (default is 0)\r\nbool ScriptGetHorseString(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tuint32 whichString;\r\n\tScript::CStruct* p_return_parms;\r\n\tpParams->GetChecksum( \"whichString\", &whichString, true );\r\n\r\n\tStr::String horseString = Mdl::Skate::Instance()->GetHorse()->GetString( whichString );\r\n\r\n\tp_return_parms = pScript->GetParams();\r\n\tp_return_parms->AddString( \"text\", horseString.getString());\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | IsCurrentHorseSkater | true if the current horse skater\r\n// is the same as the specified skater id\r\n// @uparm 1 | skater id\r\nbool ScriptIsCurrentHorseSkater(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint skaterId;\r\n\tif( pParams->GetInteger( NONAME, &skaterId, false ) == false )\r\n\t{\r\n\t\tpParams->GetChecksum( NONAME, (uint32*) &skaterId, true );\r\n\t}\r\n\t\r\n\t\r\n\treturn ( Mdl::Skate::Instance()->GetHorse()->GetCurrentSkaterId() == skaterId );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ApplyToSkaterProfile | \r\n// @parmopt int | skater | 0 | the skater we're applying to (default is 0)\r\n// @parmopt name | field_id | | the field to change\r\n// @parmopt name | slider_id | | if the value is specified in a slider\r\n// @parmopt name | keyboard_id | | value specified in a string\r\n// @parmopt name | value | | specific value (in the absence of slider or keyboard)\r\nbool ScriptApplyToSkaterProfile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{   \r\n\t/*\r\n\tObj::CSkaterProfile* pProfile = NULL;\r\n\r\n\t// look for the specified skater (0 by default)\r\n\tint skater;\r\n\r\n\r\n\tif ( pParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skater ) )\r\n\t{\r\n\t\t// get the specified skater profile\r\n\t\tpProfile = Mdl::Skate::Instance()->GetProfile( skater );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// look up the current skater profile\r\n\t\tpProfile = Mdl::Skate::Instance()->GetCurrentProfile( pParams );\r\n\t}\r\n\r\n\tDbg_MsgAssert( pProfile,( \"No profile found\" ));\r\n\r\n\tuint32 field_id;\r\n\tuint32 checksumValue;\r\n\tuint32 slider_id;\r\n\tuint32 keyboard_id;\r\n\tpParams->GetChecksum( \"field_id\", &field_id, true );\r\n\r\n\t// the value will be in one of two places...\r\n\tif ( pParams->GetChecksum( \"slider_id\", &slider_id ) )\r\n\t{\r\n\t\t// de-reference the specified slider_id\r\n\t\tFront::MenuFactory* menu_factory = Front::MenuFactory::Instance();\r\n\t\tFront::SliderMenuElement* pSliderElement = static_cast<Front::SliderMenuElement*>( menu_factory->GetMenuElement( slider_id, true ) );\r\n\t\tuint32 value = pSliderElement->GetValue();\r\n\t\tpProfile->SetSkaterProperty( field_id, value );\r\n\t}\r\n\telse if ( pParams->GetChecksum( \"keyboard_id\", &keyboard_id ) )\r\n\t{\r\n\t\t// de-reference the specified slider_id\r\n\t\tFront::MenuFactory* menu_factory = Front::MenuFactory::Instance();\r\n\t\tFront::KeyboardControl* pKeyboardControl = static_cast<Front::KeyboardControl*>( menu_factory->GetMenuElement( keyboard_id, true ) );\r\n\t\tStr::String myString = pKeyboardControl->GetString();\r\n\r\n\t\tif ( strlen( myString.getString() ) )\r\n\t\t{\r\n\t\t\tprintf(\"Setting property %s to %s\\n\", Script::FindChecksumName(field_id), myString.getString() );\r\n\t\t\tpProfile->SetSkaterProperty( field_id, myString.getString() );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tprintf(\"No string supplied.  Ignoring change to %s\\n\", Script::FindChecksumName(field_id) );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// look for checksum value\r\n\t\tpParams->GetChecksum( \"value\", &checksumValue, true );\r\n\t\tprintf(\"Setting %s\\n\", Script::FindChecksumName( checksumValue ));\r\n\t\tpProfile->SetSkaterProperty( field_id, checksumValue );\r\n\t}\r\n\t*/\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RefreshSkaterColors | this just synchs up the on-screen \r\n// skater with the color in the skater profile, in case it's changed\r\nbool ScriptRefreshSkaterColors(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint profile = 0;\r\n\tint skater = 0;\r\n\t\r\n\tpParams->GetInteger( CRCD(0x7ea855f0,\"profile\"), &profile, Script::ASSERT );\r\n\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skater, Script::ASSERT );\r\n//\tDbg_Printf( \"Skater %d  Profile %d\\n\", skater, profile );\r\n\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetSkater(skater);\r\n\tDbg_Assert( pSkater );\r\n\r\n\tObj::CSkaterProfile* pProfile = Mdl::Skate::Instance()->GetProfile( profile );\r\n\tDbg_Assert( pProfile );\r\n    Gfx::CModelAppearance* pAppearance = pProfile->GetAppearance();\r\n\t\r\n\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( pSkater );\r\n\tpModelComponent->RefreshModel( pAppearance, Gfx::vCHECKSUM_COLOR_MODEL_FROM_APPEARANCE );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RefreshSkaterScale | this just synchs up the on-screen \r\n// skater with the scale in the skater profile, in case it's changed\r\nbool ScriptRefreshSkaterScale(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint profile = 0;\r\n\tint skater = 0;\r\n\t\r\n\tpParams->GetInteger( CRCD(0x7ea855f0,\"profile\"), &profile, Script::ASSERT );\r\n\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skater, Script::ASSERT );\r\n//\tDbg_Printf( \"Skater %d  Profile %d\\n\", skater, profile );\r\n\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetSkater(skater);\r\n\tDbg_Assert( pSkater );\r\n\r\n\tObj::CSkaterProfile* pProfile = Mdl::Skate::Instance()->GetProfile( profile );\r\n\tDbg_Assert( pProfile );\r\n    Gfx::CModelAppearance* pAppearance = pProfile->GetAppearance();\r\n\t\r\n\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( pSkater );\r\n\tpModelComponent->RefreshModel( pAppearance, Gfx::vCHECKSUM_SCALE_MODEL_FROM_APPEARANCE );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RefreshSkaterVisibility | this just synchs up the on-screen \r\n// skater with the hidegeoms in the skater profile, in case it's changed\r\n// (such as in the invisible man cheat\r\nbool ScriptRefreshSkaterVisibility(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint profile = 0;\r\n\tint skater = 0;\r\n\t\r\n\tpParams->GetInteger( CRCD(0x7ea855f0,\"profile\"), &profile, Script::ASSERT );\r\n\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skater, Script::ASSERT );\r\n//\tDbg_Printf( \"Skater %d  Profile %d\\n\", skater, profile );\r\n\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetSkater(skater);\r\n\tDbg_Assert( pSkater );\r\n\r\n\tObj::CSkaterProfile* pProfile = Mdl::Skate::Instance()->GetProfile( profile );\r\n\tDbg_Assert( pProfile );\r\n    Gfx::CModelAppearance* pAppearance = pProfile->GetAppearance();\r\n\t\r\n\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( pSkater );\r\n\tpModelComponent->RefreshModel( pAppearance, Gfx::vCHECKSUM_HIDE_MODEL_FROM_APPEARANCE );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RefreshSkaterUV | this just synchs up the on-screen \r\n// skater with the UVs in the skater profile, in case it's changed\r\nbool ScriptRefreshSkaterUV(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint profile = 0;\r\n\tint skater = 0;\r\n\t\r\n\tpParams->GetInteger( CRCD(0x7ea855f0,\"profile\"), &profile, Script::ASSERT );\r\n\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skater, Script::ASSERT );\r\n//\tDbg_Printf( \"Skater %d  Profile %d\\n\", skater, profile );\r\n\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetSkater(skater);\r\n\tDbg_Assert( pSkater );\r\n\r\n\tObj::CSkaterProfile* pProfile = Mdl::Skate::Instance()->GetProfile( profile );\r\n\tDbg_Assert( pProfile );\r\n    Gfx::CModelAppearance* pAppearance = pProfile->GetAppearance();\r\n\t\r\n\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( pSkater );\r\n\tpModelComponent->RefreshModel( pAppearance, CRCD(0x91d6261,\"set_uv_from_appearance\") );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AwardStatPoint | awards a stat point to the current skater\r\n// @uparmopt 1 | increment value (can be negative)\r\nbool ScriptAwardStatPoint(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetCurrentProfile();\r\n\r\n\tint inc_val = 1;\r\n\tpParams->GetInteger( NONAME, &inc_val, Script::NO_ASSERT );\r\n\r\n\tpSkaterProfile->AwardStatPoint( inc_val );\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | AwardSpecialTrickSlot | awards a new special trick slot to the \r\n// current skater profile\r\n// @flag all | award a trickslot to all profiles\r\nbool ScriptAwardSpecialTrickSlot(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tObj::CPlayerProfileManager* pPlayerProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tif ( pParams->ContainsFlag( \"all\" ) )\r\n\t{\r\n\t\tint num_profiles = pPlayerProfileManager->GetNumProfileTemplates();\r\n\t\tfor ( int i = 0; i < num_profiles; i++ )\r\n\t\t{\r\n\t\t\tObj::CSkaterProfile* pTempProfile = pPlayerProfileManager->GetProfileTemplateByIndex( i );\r\n\t\t\tpTempProfile->AwardSpecialTrickSlot();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetCurrentProfile();\r\n\t\tpSkaterProfile->AwardSpecialTrickSlot();\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UpdateSkaterStats | \r\nbool ScriptUpdateSkaterStats(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tint player;\r\n\tpParams->GetInteger(CRCD(0x67e6859a,\"player\"), &player, Script::ASSERT);\t\r\n\t\t\r\n\tObj::CSkater *pSkater = Mdl::Skate::Instance()->GetSkater(player);\r\n\tDbg_Assert(pSkater);\r\n\r\n\tObj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile(player);\r\n\tpSkater->UpdateStats(pSkaterProfile);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UpdateInitials | \r\nbool ScriptUpdateInitials( Script::CStruct *pParams, Script::CScript *pScript )\r\n{   \r\n\t\r\n\tint level = Mdl::Skate::Instance()->GetCareer()->GetLevel();\r\n\tRecords::CGameRecords *pGameRecords=Mdl::Skate::Instance()->GetGameRecords();\t\r\n\tpGameRecords->GetLevelRecords(level)->UpdateInitials(pGameRecords->GetDefaultInitials());\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | NewRecord | return true if the last call to UpdateRecords made\r\n// there be a new record\r\nbool ScriptNewRecord(  Script::CStruct *pParams, Script::CScript *pScript )\r\n{      \r\n\treturn Mdl::Skate::Instance()->m_new_record;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | TrickOffAllObjects | \r\n// @uparmopt 0 | skater id (0 is default)\r\nbool ScriptTrickOffAllObjects( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t// a cheat for getting all the graffiti objects\r\n\r\n\tif (!Config::CD())\r\n\t{\t\r\n\t\tint skater_id = 0;\r\n\t\tpParams->GetInteger( NONAME, &skater_id );\r\n\t\tMdl::Skate::Instance()->GetTrickObjectManager()->TrickOffAllObjects( skater_id );\r\n\t}\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetScoreDegredation | \r\n// @uparm 1 | should degrade amount\r\nbool ScriptGameModeSetScoreDegradation( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n    \r\n\t\r\n\tint should_degrade = 1;\r\n\r\n\tpParams->GetInteger( NONAME, &should_degrade );\r\n\r\n\tMdl::Skate::Instance()->GetGameMode()->SetScoreDegradation( should_degrade );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetScoreAccumulation | \r\n// @uparm 1 | should accumulate amount\r\nbool ScriptGameModeSetScoreAccumulation( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n    \r\n\t\r\n\tint should_accumulate = 1;\r\n\r\n\tpParams->GetInteger( NONAME, &should_accumulate );\r\n\r\n\tMdl::Skate::Instance()->GetGameMode()->SetScoreAccumulation( should_accumulate );\r\n\r\n\tif ( should_accumulate == 0 && pParams->ContainsFlag( \"freeze_score\" ) )\r\n\t{\r\n\t\tMdl::Skate::Instance()->GetGameMode()->SetScoreFrozen( true );\r\n\t}\r\n\telse \r\n\t{\r\n\t\tMdl::Skate::Instance()->GetGameMode()->SetScoreFrozen( false );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetScore |\r\nbool ScriptResetScore(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\r\n\tDbg_Printf( \"******** RESET SCORE\\n\" );\r\n\r\n    for (uint32 i=0;i<skate_mod->GetNumSkaters();i++)\r\n\t{\r\n\t\tObj::CSkater* p_Skater = skate_mod->GetSkater( i );\r\n\t\tif ( p_Skater->IsLocalClient() )\r\n\t\t{\r\n\t\t\tMdl::Score * p_Score = ( p_Skater->GetScoreObject() );\r\n\t\t\tDbg_Assert( p_Score );\r\n\r\n\t\t\tp_Score->Reset();\r\n\t\t\tif( ( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"netking\" )) ||\r\n\t\t\t\t( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( \"king\" )))\r\n\t\t\t{\r\n\t\t\t\tFront::SetScoreTHPS4( \"0:00\", p_Skater->GetHeapIndex());\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tFront::SetScoreTHPS4( \"0\", p_Skater->GetHeapIndex());\r\n\t\t\t}\r\n\t\t\t\r\n\t\t}\r\n\t}\r\n\t\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UpdateScore |\r\nbool ScriptUpdateScore(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\r\n    for (uint32 i=0;i<skate_mod->GetNumSkaters();i++)\r\n\t{\r\n\t\tObj::CSkater* p_Skater = skate_mod->GetSkater( i );\r\n\t\tif ( p_Skater->IsLocalClient() )\r\n\t\t{\r\n\t\t\tMdl::Score * p_Score = ( p_Skater->GetScoreObject() );\r\n\t\t\tDbg_Assert( p_Score );\r\n\r\n\t\t\tp_Score->SetTotalScore( p_Score->GetTotalScore());\r\n\t\t}\r\n\t}\r\n\t\r\n    return true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetScoreDegradation | doesn't seem to do anything...\r\nbool ScriptResetScoreDegradation( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SkaterIsBraking | returns true if the local skater is braking\r\nbool ScriptSkaterIsBraking( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n    \r\n    Obj::CCompositeObject *pSkater = Mdl::Skate::Instance()->GetLocalSkater();\t\t\t\t\t\t   \r\n    Dbg_Assert( pSkater );\r\n    return pSkater->CallMemberFunction(CRCD(0x1f8bbd05, \"Braking\"), pParams, pScript);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LocalSkaterExists | returns true if the local skater exists\r\nbool ScriptLocalSkaterExists( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\t\r\n    Obj::CSkater *pSkater = Mdl::Skate::Instance()->GetLocalSkater();\t\t\t\t\t\t   \r\n    \r\n    return ( pSkater != NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | InitSkaterModel | This will destroy the specified\r\n// skater's model and replace it with the specified model or\r\n// profile\r\nbool ScriptInitSkaterModel(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tint player_num = 0;\r\n\tpParams->GetInteger( NONAME, &player_num );\r\n\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetSkater(player_num);\r\n\tDbg_Assert( pSkater );\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterGeomHeap(pSkater->GetHeapIndex()));\r\n   \t\r\n\tuint32 appearance_structure_name;\r\n\tpParams->GetChecksum( \"default_appearance\", &appearance_structure_name, true );\r\n//\tScript::PrintContents( pParams );\r\n\r\n\t// create the model\r\n\tGfx::CModelAppearance theAppearance;\r\n\ttheAppearance.Load( appearance_structure_name );\r\n\r\n\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( pSkater );\r\n\tpModelComponent->InitModelFromProfile( &theAppearance, false, pSkater->GetHeapIndex() );\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | RefreshSkaterModel | This will destroy the specified\r\n// skater's model and replace it with the specified model or\r\n// profile\r\n// If there is a composite object called \"bailboard\" that will be destroyed\r\nbool ScriptRefreshSkaterModel(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\t\r\n\tint profile = 0;\r\n\tint skater = 0;\r\n\tint no_name = 0;\r\n\t\r\n\t\r\n\t\r\n\tpParams->GetInteger( NONAME, &no_name );\r\n\tprofile = no_name;\r\n\tskater = no_name;\r\n\tpParams->GetInteger( CRCD(0x7ea855f0,\"profile\"), &profile );\r\n\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skater );\r\n\tDbg_Printf( \"Skater %d  Profile %d\\n\", skater, profile );\r\n\tObj::CSkater* pSkater = Mdl::Skate::Instance()->GetSkater(skater);\r\n\tDbg_MsgAssert( pSkater, ( \"Couldn't find specified skater\" ) );\r\n\r\n\r\n\t// (Mick) Now check for bailboard, and kill it\r\n\t// Bit of a patch really, but a fairly safe high level one.\r\n\t// (need a more general solution for killing model that has instances...)\r\n\tif (pSkater->GetSkaterNumber() == 0)\t// Only need it for single player\r\n\t{\r\n\t\tObj::CCompositeObject*p_bailboard = (Obj::CCompositeObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0x884ef81b,\"bailboard\"));\r\n\t\tif (p_bailboard)\r\n\t\t{\r\n\t\t\tp_bailboard->MarkAsDead();\r\n\t\t\tObj::CCompositeObjectManager::Instance()->FlushDeadObjects();\r\n\t\t}\r\n\t}\r\n\r\n\tObj::CSkaterProfile* pProfile = Mdl::Skate::Instance()->GetProfile( profile );\r\n\tDbg_Assert( pProfile );\r\n    Gfx::CModelAppearance* pAppearance = pProfile->GetAppearance();\r\n\t\r\n\t// GJ:  rebuilding the face and texture takes\r\n\t// a while, causes Pcm audio \"panic\" assert...\r\n\t// just to be safe, i'll pause the music while\r\n\t// the model is being rebuilt.\r\n\t/*bool should_pause_music = !Pcm::MusicIsPaused();\r\n\t\r\n\tif ( should_pause_music )\r\n\t{\r\n\t\tPcm::PauseMusic( true );\r\n\t}*/\r\n\r\n\t// create the model\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterGeomHeap(pSkater->GetHeapIndex()));\r\n\r\n\tNx::CEngine::sFinishRendering();\r\n   \r\n#ifdef __PLAT_NGC__\r\n\tFile::PreMgr* pre_mgr = File::PreMgr::Instance();\r\n\tbool loaded = pre_mgr->InPre( \"skaterparts.pre\");\r\n\tif ( !loaded )\r\n\t{\r\n\t\tpre_mgr->LoadPre( \"skaterparts.pre\", false);\r\n\t}\r\n#endif\r\n\tObj::CModelComponent* pModelComponent = GetModelComponentFromObject( pSkater );\r\n\tpModelComponent->InitModelFromProfile( pAppearance, false, pSkater->GetHeapIndex() );\r\n#ifdef __PLAT_NGC__\r\n\tif ( !loaded )\r\n\t{\r\n\t\tpre_mgr->UnloadPre( \"skaterparts.pre\");\r\n\t}\r\n#endif\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterHeap(pSkater->GetHeapIndex()));\r\n\t\r\n\tpSkater->UpdateStats( pProfile );\r\n\r\n\tObj::CTrickComponent* pTrickComponent = GetTrickComponentFromObject(pSkater);\r\n\tDbg_Assert(pTrickComponent);\r\n\tpTrickComponent->UpdateTrickMappings( pProfile );\r\n\r\n\tpSkater->UpdateSkaterInfo( pProfile );\r\n\r\n\tMem::Manager::sHandle().PopContext();\r\n\r\n    uint32 board;\r\n    if ( pParams->GetChecksum( CRCD(0x41eec86b,\"no_board\"), &board ) )\r\n    {\r\n        // if Refreshing the skater in the CAS level,\r\n        // Hide the board\r\n        //Mdl::Skate * skate_mod =  Mdl::Skate::Instance();\r\n        //if ( skate_mod->m_cur_level == CRCD(0xa368b4f1,\"load_cas\") )\r\n        //{\r\n            // turn off board\r\n            Obj::CModelComponent* pModelComponent = GetModelComponentFromObject(pSkater);\r\n            pModelComponent->HideGeom(CRCD(0xa7a9d4b8,\"board\"), true, true);\r\n\r\n\t\t\t// GJ THPS5: Kludge to fix TT12405: CAS - board \r\n\t\t\t// appears when adjusting leg tattoos\r\n\t\t\t// generally, this function will be called from a spawned script,\r\n\t\t\t// which gets called after the composite objects are updated\r\n\t\t\t// for the frame...  because of this, it will take 1 frame\r\n\t\t\t// for the hide flag to take effect, unless we explicitly update\r\n\t\t\t// the model component here\r\n            pModelComponent->Update();\r\n        //}\r\n    }\r\n    \r\n\t/*if ( should_pause_music )\r\n\t{\r\n\t\t// unpause the music\r\n\t\tPcm::PauseMusic( false );\r\n\t}*/\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | EditPlayerAppearance | This runs an object script on the specified\r\n// appearance structure\r\n// @parm name | target | name of script that gets run on the player's appearance\r\n// @parmopt structure | targetParams | | extra parameters sent to the target script\r\nbool ScriptEditPlayerAppearance(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\t\r\n\tint profile_num = 0;\r\n\tint no_name = 0;\r\n\t\r\n\tpParams->GetInteger( NONAME, &no_name );\r\n\tprofile_num = no_name;\r\n\tpParams->GetInteger( CRCD(0x7ea855f0,\"profile\"), &profile_num );\r\n\tDbg_Printf( \"Profile %d\\n\", profile_num );\r\n\r\n\tObj::CSkaterProfile* pProfile = Mdl::Skate::Instance()->GetProfile( profile_num );\r\n\tDbg_Assert( pProfile );\r\n    Gfx::CModelAppearance* pAppearance = pProfile->GetAppearance();\r\n\t   \t\r\n\tuint32 target;\r\n\tpParams->GetChecksum(CRCD(0xb990d003,\"target\"), &target, Script::ASSERT);\r\n\r\n\tScript::CStruct* pTargetParams = NULL;\r\n\tpParams->GetStructure(CRCD(0x46a2869c,\"targetParams\"), &pTargetParams, Script::NO_ASSERT);\r\n\r\n\t// runs an object script on the specified appearance structure\r\n\tScript::RunScript(target, pTargetParams, pAppearance);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetCurrentSkaterProfileIndex | This returns the currently selected\r\n// profile (either player 0 or player 1), presumably for use by other script functions\r\n// @parm int | currentSkaterProfileIndex | index of currently selected profile (return value)\r\nbool ScriptGetCurrentSkaterProfileIndex(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tint index = pPlayerProfileManager->GetCurrentProfileIndex();\r\n\tpScript->GetParams()->AddInteger(CRCD(0x3c64476b,\"currentSkaterProfileIndex\"), index);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetCustomSkaterName | \r\nbool ScriptGetCustomSkaterName(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\tObj::CPlayerProfileManager*\tpPlayerProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tconst char* name = pPlayerProfileManager->GetProfileTemplate(CRCD(0xa7be964,\"custom\"))->GetDisplayName();\r\n\tpScript->GetParams()->AddString(CRCD(0x2ab66cb8,\"display_name\"), name);\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetScorePot | this will reset the local skater's current score pot.\r\n// This currently just calls the Bail member func of the score object...\r\nbool ScriptResetScorePot(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\t\r\n\tbool useBailStyle = pParams->ContainsFlag(CRCD(0x929eb4d5, \"UseBailStyle\"));\r\n\t\r\n    for (uint32 i=0;i<skate_mod->GetNumSkaters();i++)\r\n\t{\r\n\t\tObj::CSkater* p_Skater = skate_mod->GetSkater( i );\r\n\t\tif ( p_Skater->IsLocalClient() )\r\n\t\t{   \r\n\t\t\tMdl::Score *pScore=p_Skater->GetScoreObject();\r\n\r\n\t\t\tDbg_Assert( pScore );\r\n\t\t\tpScore->Bail(!useBailStyle);\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptPrintSkaterStats | prints the specified skater's stats\r\nbool ScriptPrintSkaterStats( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n    for (uint32 i=0;i<skate_mod->GetNumSkaters();i++)\r\n\t{\r\n\t\tprintf(\"Skater %d stats:\\n\", i);\r\n\r\n\t\tObj::CSkater* pSkater = skate_mod->GetSkater( i );\r\n\t\t\r\n\t\tprintf(\"Air    %2.2f\\n\",pSkater->GetStat(Obj::CSkater::STATS_AIR));\t\t\r\n\t\tprintf(\"Run    %2.2f\\n\",pSkater->GetStat(Obj::CSkater::STATS_RUN));\t\t\r\n\t\tprintf(\"Ollie  %2.2f\\n\",pSkater->GetStat(Obj::CSkater::STATS_OLLIE));\t\t\r\n\t\tprintf(\"Speed  %2.2f\\n\",pSkater->GetStat(Obj::CSkater::STATS_SPEED));\t\t\r\n\t\tprintf(\"Spin   %2.2f\\n\",pSkater->GetStat(Obj::CSkater::STATS_SPIN));\t\t\r\n\t\tprintf(\"Flip   %2.2f\\n\",pSkater->GetStat(Obj::CSkater::STATS_FLIPSPEED));\t\t\r\n\t\tprintf(\"Switch %2.2f\\n\",pSkater->GetStat(Obj::CSkater::STATS_SWITCH));\t\t\r\n\t\tprintf(\"Rail   %2.2f\\n\",pSkater->GetStat(Obj::CSkater::STATS_RAILBALANCE));\t\t\r\n\t\tprintf(\"Lip    %2.2f\\n\",pSkater->GetStat(Obj::CSkater::STATS_LIPBALANCE));\t\t\r\n\t\tprintf(\"Manual %2.2f\\n\",pSkater->GetStat(Obj::CSkater::STATS_MANUAL));\t\t\r\n\t}\r\n#endif\t\t// __NOPT_ASSERT__\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ScriptPrintSkaterStats | prints the specified skater's stats\r\nbool ScriptPrintSkaterStats2( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n    for (uint32 i=0;i<skate_mod->GetNumSkaters();i++)\r\n\t{\r\n\t\tprintf(\"Skater %d stats:\\n\", i);\r\n\r\n        Obj::CPlayerProfileManager* pProfileManager = skate_mod->GetPlayerProfileManager();\r\n        Obj::CSkaterProfile* pProfile = pProfileManager->GetProfile( i );\r\n\t\t\r\n\t\tprintf(\"Air    %i\\n\",pProfile->GetStatValue(CRCD(0x439f4704,\"AIR\")));\t\t\r\n\t\tprintf(\"Run    %i\\n\",pProfile->GetStatValue(CRCD(0xaf895b3f,\"RUN\")));\t\t\r\n\t\tprintf(\"Ollie  %i\\n\",pProfile->GetStatValue(CRCD(0x9b65d7b8,\"OLLIE\")));\t\t\r\n\t\tprintf(\"Speed  %i\\n\",pProfile->GetStatValue(CRCD(0xf0d90109,\"SPEED\")));\t\t\r\n\t\tprintf(\"Spin   %i\\n\",pProfile->GetStatValue(CRCD(0xedf5db70,\"SPIN\")));\t\t\r\n\t\tprintf(\"Flip   %i\\n\",pProfile->GetStatValue(CRCD(0x6dcb497c,\"FLIP_SPEED\")));\t\t\r\n\t\tprintf(\"Switch %i\\n\",pProfile->GetStatValue(CRCD(0x9016b4e7,\"SWITCH\")));\t\t\r\n\t\tprintf(\"Rail   %i\\n\",pProfile->GetStatValue(CRCD(0xf73a13e3,\"RAIL_BALANCE\")));\t\t\r\n\t\tprintf(\"Lip    %i\\n\",pProfile->GetStatValue(CRCD(0xae798769,\"LIP_BALANCE\")));\t\t\r\n\t\tprintf(\"Manual %i\\n\",pProfile->GetStatValue(CRCD(0xb1fc0722,\"MANUAL_BALANCE\")));\t\t\r\n\t}\r\n#endif\t\t// __NOPT_ASSERT__\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | PrintSkaterPosition | prints the local skater's current position\r\nbool ScriptPrintSkaterPosition( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n#ifdef __NOPT_ASSERT__\r\n\tObj::CSkater *pSkater = Mdl::Skate::Instance()->GetLocalSkater();\r\n\t\r\n\tMth::Vector pos = pSkater->GetPos();\r\n\tfloat x = pos.GetX();\r\n\tfloat y = pos.GetY();\r\n\tfloat z = pos.GetZ();\r\n\r\n\tDbg_Message(\"(%f, %f, %f)\", x, y, z);\r\n#endif\t\t// __NOPT_ASSERT__\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetSkaterPosition | prints the local skater's current position\r\nbool ScriptGetSkaterPosition( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\r\n    Obj::CSkater* pSkater = static_cast< Obj::CSkater* >(pScript->mpObject.Convert());\r\n\t\r\n    if (pSkater) \r\n    {\r\n    \tMth::Vector pos = pSkater->GetPos();\r\n    \tfloat x = pos.GetX();\r\n    \tfloat y = pos.GetY();\r\n    \tfloat z = pos.GetZ();\r\n    \r\n        pScript->GetParams()->AddInteger(\"x\", x);\r\n        pScript->GetParams()->AddInteger(\"y\", y);\r\n        pScript->GetParams()->AddInteger(\"z\", z);\r\n    \r\n        return true;\r\n    }\r\n    \r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetSkaterPosition | prints the local skater's current position\r\nbool ScriptGetSkaterVelocity( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\r\n    Obj::CSkater* pSkater = static_cast< Obj::CSkater* >(pScript->mpObject.Convert());\r\n\t\r\n    if (pSkater) \r\n    {\r\n    \tMth::Vector vel = pSkater->GetVel();\r\n    \tfloat x = vel.GetX();\r\n    \tfloat y = vel.GetY();\r\n    \tfloat z = vel.GetZ();\r\n\t\tfloat scale = 1.0f;\r\n\t\tfloat skew_angle = 0.0f;\r\n    \r\n\t\t\r\n\t\tpParams->GetFloat( CRCD(0x5582fe27,\"skew_angle\"), &skew_angle );\r\n\r\n        pScript->GetParams()->AddInteger(CRCD(0x6187906d,\"vel_x\"), x);\r\n        pScript->GetParams()->AddInteger(CRCD(0x1680a0fb,\"vel_y\"), y);\r\n        pScript->GetParams()->AddInteger(CRCD(0x8f89f141,\"vel_z\"), z);\r\n\r\n\t\tpParams->GetFloat( CRCD(0x13b9da7b,\"scale\"), &scale );\r\n\r\n\t\tvel[Y] = 0.0f;\r\n\r\n\t\tif( vel.Length() > 100.0f )\r\n\t\t{\r\n\t\t\tvel.Normalize();\r\n\r\n\t\t\tif( skew_angle != 0 )\r\n\t\t\t{\r\n\t\t\t\tMth::Matrix rot_mat;\r\n\t\r\n\t\t\t\trot_mat.Ident();\r\n\t\t\t\trot_mat.RotateY( Mth::DegToRad( skew_angle ));\r\n\t\r\n\t\t\t\tvel = rot_mat.Transform( vel );\r\n\t\t\t}\r\n\r\n\t\t\tpScript->GetParams()->AddInteger(\"scaled_x\", vel[X] * scale );\r\n\t\t\tpScript->GetParams()->AddInteger(\"scaled_y\", vel[Y] * scale );\r\n\t\t\tpScript->GetParams()->AddInteger(\"scaled_z\", vel[Z] * scale );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tMth::Vector facing;\r\n\r\n\t\t\tfacing = pSkater->GetMatrix()[Mth::AT];\r\n\t\r\n\t\t\tif( skew_angle != 0 )\r\n\t\t\t{\r\n\t\t\t\tMth::Matrix rot_mat;\r\n\t\r\n\t\t\t\trot_mat = pSkater->GetMatrix();\r\n\t\t\t\trot_mat.RotateYLocal( Mth::DegToRad( skew_angle ));\r\n\t\r\n\t\t\t\tfacing = rot_mat[Mth::AT];\r\n\t\t\t}\r\n\r\n\t\t\tpScript->GetParams()->AddInteger(CRCD(0xbded7a76,\"scaled_x\"), facing[X] * scale );\r\n\t\t\tpScript->GetParams()->AddInteger(CRCD(0xcaea4ae0,\"scaled_y\"), facing[Y] * scale );\r\n\t\t\tpScript->GetParams()->AddInteger(CRCD(0x53e31b5a,\"scaled_z\"), facing[Z] * scale );\r\n\t\t}\r\n    \r\n        return true;\r\n    }\r\n    \r\n    return false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetStatValue | this returns the specified stat value in\r\n// the script's params as stat_value\r\n// @uparm STATS_AIR | global int value of the stat (defined in physics.q)\r\n// @parmopt name | skater | | the name of the profile you wish to get.  If you don't\r\n// provide a name, the current skater's profile will be returned\r\nbool ScriptGetStatValue( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 stat;\r\n\tpParams->GetChecksum( NONAME, &stat, Script::ASSERT );\r\n\r\n\tuint32 name;\r\n\t\r\n\tObj::CPlayerProfileManager* pPlayerProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pSkaterProfile = NULL;\r\n\tif ( pParams->GetChecksum( CRCD(0x5b8ab877,\"skater\"), &name, Script::NO_ASSERT ) )\r\n\t\tpSkaterProfile = pPlayerProfileManager->GetProfileTemplate( name );\r\n\telse\r\n\t\tpSkaterProfile = pPlayerProfileManager->GetCurrentProfile();\r\n\t\r\n\tDbg_MsgAssert( pSkaterProfile, ( \"Unable to get skater profile\") );\r\n\tint value = pSkaterProfile->GetStatValue( stat );\r\n\tpScript->GetParams()->AddInteger( \"stat_value\", value );\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetNumStatPointsAvailable | returns the number in the scripts\r\n// params as points_available\r\n// @parm int | player | the player number to check \r\nbool ScriptGetNumStatPointsAvailable( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tint player;\r\n\tpParams->GetInteger( CRCD(0x67e6859a,\"player\"), &player, Script::ASSERT );\r\n\r\n\t\r\n\tObj::CPlayerProfileManager* pProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pProfile = pProfileManager->GetProfile( player );\r\n\tint num = pProfile->GetNumStatPointsAvailable();\r\n\tpScript->GetParams()->AddInteger( \"points_available\", num );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UnlockSkater | this makes locked characters accessible\r\n// to the player\r\n// @parm name | skater | the name of the locked character to unlock\r\nbool ScriptUnlockSkater( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 name;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &name, Script::ASSERT );\r\n\r\n\tObj::CPlayerProfileManager* pPlayerProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pSkaterProfile = pPlayerProfileManager->GetProfileTemplate( name );\r\n\tDbg_MsgAssert( pSkaterProfile, ( \"Unable to get skater profile\") );\r\n\r\n\tint isLocked = 1;\r\n\tpSkaterProfile->GetInfo()->GetInteger( \"is_hidden\", &isLocked, Script::ASSERT );\r\n\tif ( isLocked )\r\n\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\t// don't need to sync it up to the current skater profiles,\r\n\t\t// because, theoretically, the player won't be able to\r\n\t\t// choose him through the front end...\r\n\t\tObj::CSkaterProfile* pCurrentSkaterProfile = pPlayerProfileManager->GetCurrentProfile();\r\n\t\tDbg_MsgAssert( pCurrentSkaterProfile->GetSkaterNameChecksum() != name, \r\n\t\t\t\t\t   ( \"Locked skaters aren't supposed to be currently selected!\", \r\n\t\t\t\t\t\t Script::FindChecksumName(name) ) );\r\n#endif\r\n\t\tDbg_Message( \"%s was locked\\n\", Script::FindChecksumName(name) );\r\n\t\tpSkaterProfile->GetInfo()->AddInteger( \"is_hidden\", 0 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Message( \"%s was not locked\\n\", Script::FindChecksumName(name) );\r\n\t}\r\n\t\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetActualCASOptionStruct( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 partChecksum;\r\n\tpParams->GetChecksum(CRCD(0xb6f08f39,\"part\"), &partChecksum, Script::ASSERT);\r\n\t\r\n\tuint32 descChecksum;\r\n\tpParams->GetChecksum(CRCD(0x4bb2084e,\"desc_id\"), &descChecksum, Script::ASSERT);\r\n\r\n\tScript::CStruct* pActualStruct = Cas::GetOptionStructure( partChecksum, descChecksum );\r\n\r\n\tpScript->GetParams()->AppendStructure( pActualStruct );\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetActualPlayerAppearancePart( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tint player_num = 0;\r\n\tpParams->GetInteger(CRCD(0x67e6859a,\"player\"), &player_num);\r\n\t\r\n\tObj::CSkaterProfile* pProfile = Mdl::Skate::Instance()->GetProfile(player_num);\r\n\tDbg_Assert(pProfile);\r\n    Gfx::CModelAppearance* pAppearance = pProfile->GetAppearance();\r\n\r\n\tuint32 partChecksum;\r\n\tif ( pParams->GetChecksum( CRCD(0xb6f08f39,\"part\"), &partChecksum, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tScript::CStruct* pVirtualStruct;\r\n\t\tpVirtualStruct = pAppearance->GetActualDescStructure( partChecksum );\r\n\t\tif ( pVirtualStruct )\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AppendStructure( pVirtualStruct );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetPlayerAppearancePart( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\t\r\n\tint player_num = 0;\r\n\tpParams->GetInteger(CRCD(0x67e6859a,\"player\"), &player_num);\r\n\t\r\n\tObj::CSkaterProfile* pProfile = Mdl::Skate::Instance()->GetProfile(player_num);\r\n\tDbg_Assert(pProfile);\r\n    Gfx::CModelAppearance* pAppearance = pProfile->GetAppearance();\r\n\r\n\tuint32 partChecksum;\r\n\tif ( pParams->GetChecksum( CRCD(0xb6f08f39,\"part\"), &partChecksum, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tScript::CStruct* pVirtualStruct;\r\n\t\tpVirtualStruct = pAppearance->GetVirtualDescStructure( partChecksum );\r\n\t\tif ( pVirtualStruct )\r\n\t\t{\r\n\t\t\tpScript->GetParams()->AppendStructure( pVirtualStruct );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptSetPlayerAppearanceColor( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tint player_num = 0;\r\n\tpParams->GetInteger(CRCD(0x67e6859a,\"player\"), &player_num);\r\n\t\r\n\tObj::CSkaterProfile* pProfile = Mdl::Skate::Instance()->GetProfile(player_num);\r\n\tDbg_Assert(pProfile);\r\n    Gfx::CModelAppearance* pAppearance = pProfile->GetAppearance();\r\n\tDbg_Assert( pAppearance );\r\n\r\n\tuint32 partChecksum;\r\n\tpParams->GetChecksum( CRCD(0xb6f08f39,\"part\"), &partChecksum, Script::ASSERT );\r\n\r\n\tScript::CStruct* pVirtualStruct;\r\n\tpVirtualStruct = pAppearance->GetVirtualDescStructure( partChecksum );\r\n\r\n\tif ( pVirtualStruct )\r\n\t{\r\n\t\tfloat h, s, v;\r\n\t\tint useDefaultHSV;\r\n\t\tpParams->GetFloat( CRCD(0x6e94f918,\"h\"), &h, Script::ASSERT );\r\n\t\tpParams->GetFloat( CRCD(0xe4f130f4,\"s\"), &s, Script::ASSERT );\r\n\t\tpParams->GetFloat( CRCD(0x949bc47b,\"v\"), &v, Script::ASSERT );\r\n\t\tpParams->GetInteger( CRCD(0x97dbdde6,\"use_default_hsv\"), &useDefaultHSV, Script::ASSERT );\r\n\r\n\t\tpVirtualStruct->AddInteger( CRCD(0x6e94f918,\"h\"), (int)h );\r\n\t\tpVirtualStruct->AddInteger( CRCD(0xe4f130f4,\"s\"), (int)s );\r\n\t\tpVirtualStruct->AddInteger( CRCD(0x949bc47b,\"v\"), (int)v );\r\n\t\tpVirtualStruct->AddInteger( CRCD(0x97dbdde6,\"use_default_hsv\"), useDefaultHSV );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Message( \"Nothing to color...  (appearance doesn't contain %s)\", Script::FindChecksumName(partChecksum) );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptSetPlayerAppearanceScale( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tint player_num = 0;\r\n\tpParams->GetInteger(CRCD(0x67e6859a,\"player\"), &player_num);\r\n\t\r\n\tObj::CSkaterProfile* pProfile = Mdl::Skate::Instance()->GetProfile(player_num);\r\n\tDbg_Assert(pProfile);\r\n    Gfx::CModelAppearance* pAppearance = pProfile->GetAppearance();\r\n\tDbg_Assert( pAppearance );\r\n\r\n\tuint32 partChecksum;\r\n\tpParams->GetChecksum( CRCD(0xb6f08f39,\"part\"), &partChecksum, Script::ASSERT );\r\n\r\n\tScript::CStruct* pVirtualStruct;\r\n\tpVirtualStruct = pAppearance->GetVirtualDescStructure( partChecksum );\r\n\r\n\tif ( !pVirtualStruct )\r\n\t{\r\n\t\tpVirtualStruct = new Script::CStruct;\r\n\t\tScript::CStruct* pAppearanceStruct = pAppearance->GetStructure();\r\n\t\tpAppearanceStruct->AddStructurePointer( partChecksum, pVirtualStruct );\r\n\t}\r\n\r\n\tfloat x;\r\n\tif ( pParams->GetFloat( CRCD(0x7323e97c,\"x\"), &x, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tpVirtualStruct->AddInteger( CRCD(0x7323e97c,\"x\"), (int)x );\r\n\t}\r\n\t\r\n\tfloat y;\r\n\tif ( pParams->GetFloat( CRCD(0x424d9ea,\"y\"), &y, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tpVirtualStruct->AddInteger( CRCD(0x424d9ea,\"y\"), (int)y );\r\n\t}\r\n\t\r\n\tfloat z;\r\n\tif ( pParams->GetFloat( CRCD(0x9d2d8850,\"z\"), &z, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tpVirtualStruct->AddInteger( CRCD(0x9d2d8850,\"z\"), (int)z );\r\n\t}\r\n\t\r\n\tint useDefaultScale;\r\n\tif ( pParams->GetInteger( CRCD(0x5a96985d,\"use_default_scale\"), &useDefaultScale, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tpVirtualStruct->AddInteger( CRCD(0x5a96985d,\"use_default_scale\"), useDefaultScale );\r\n\t}\t\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptSetPlayerAppearanceUV( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tint player_num = 0;\r\n\tpParams->GetInteger(CRCD(0x67e6859a,\"player\"), &player_num);\r\n\t\r\n\tObj::CSkaterProfile* pProfile = Mdl::Skate::Instance()->GetProfile(player_num);\r\n\tDbg_Assert(pProfile);\r\n    Gfx::CModelAppearance* pAppearance = pProfile->GetAppearance();\r\n\tDbg_Assert( pAppearance );\r\n\r\n\tuint32 partChecksum;\r\n\tpParams->GetChecksum( CRCD(0xb6f08f39,\"part\"), &partChecksum, Script::ASSERT );\r\n\r\n\tScript::CStruct* pVirtualStruct;\r\n\tpVirtualStruct = pAppearance->GetVirtualDescStructure( partChecksum );\r\n\r\n\tif ( pVirtualStruct )\r\n\t{\r\n\t\tfloat u, v, uv_scale, uv_rot;\r\n\t\tint useDefaultUV;\r\n\t\tpParams->GetFloat( CRCD(0xcf6aa087,\"uv_u\"), &u, Script::ASSERT );\r\n\t\tpParams->GetFloat( CRCD(0x5663f13d,\"uv_v\"), &v, Script::ASSERT );\r\n\t\tpParams->GetFloat( CRCD(0x266932c8,\"uv_scale\"), &uv_scale, Script::ASSERT );\r\n\t\tpParams->GetFloat( CRCD(0x1256b6c6,\"uv_rot\"), &uv_rot, Script::ASSERT );\r\n\t\tpParams->GetInteger( CRCD(0x8602f6ee,\"use_default_uv\"), &useDefaultUV, Script::ASSERT );\r\n\t\t\t\t   \r\n\t\tpVirtualStruct->AddFloat( CRCD(0xcf6aa087,\"uv_u\"), u );\r\n\t\tpVirtualStruct->AddFloat( CRCD(0x5663f13d,\"uv_v\"), v );\r\n\t\tpVirtualStruct->AddFloat( CRCD(0x266932c8,\"uv_scale\"), uv_scale );\r\n\t\tpVirtualStruct->AddFloat( CRCD(0x1256b6c6,\"uv_rot\"), uv_rot );\r\n\t\tpVirtualStruct->AddInteger( CRCD(0x8602f6ee,\"use_default_uv\"), useDefaultUV );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Message( \"Nothing to wibble...  (appearance doesn't contain %s yet?)\", Script::FindChecksumName(partChecksum) );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* GetNextUndisqualified( Script::CArray* pPartArray, int startIndex )\r\n{\r\n\tDbg_Assert( pPartArray );\r\n\r\n\tstartIndex++;\r\n\tif ( startIndex >= (int)pPartArray->GetSize() )\r\n\t{\r\n\t\tstartIndex -= pPartArray->GetSize();\r\n\t}\r\n\r\n\tfor ( int i = 0; i < (int)pPartArray->GetSize(); i++ )\r\n\t{\r\n\t\tint currIndex = (i + startIndex) % pPartArray->GetSize();\r\n\r\n\t\tScript::CStruct* pCurrStruct = pPartArray->GetStructure( currIndex );\r\n\t\t\r\n\t\tint disqualified;\r\n\t\tpCurrStruct->GetInteger( \"disqualified\", &disqualified, true );\r\n\t\tif ( !disqualified )\r\n\t\t{\r\n\t\t\treturn pCurrStruct;\r\n\t\t}\r\n\t}\r\n\r\n\t// none found...\r\n\treturn pPartArray->GetStructure( startIndex );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nScript::CStruct* GetPrevUndisqualified( Script::CArray* pPartArray, int startIndex )\r\n{\r\n\tDbg_Assert( pPartArray );\r\n\r\n\tstartIndex--;\r\n\tif ( startIndex < 0 )\r\n\t{\r\n\t\tstartIndex += pPartArray->GetSize();\r\n\t}\r\n\r\n\tfor ( int i = (int)pPartArray->GetSize(); i >= 0; i-- )\r\n\t{\r\n\t\tint currIndex = (i + startIndex) % pPartArray->GetSize();\r\n\r\n\t\tScript::CStruct* pCurrStruct = pPartArray->GetStructure( currIndex );\r\n\t\t\r\n\t\tint disqualified;\r\n\t\tpCurrStruct->GetInteger( \"disqualified\", &disqualified, true );\r\n\t\tif ( !disqualified )\r\n\t\t{\r\n\t\t\treturn pCurrStruct;\r\n\t\t}\r\n\t}\r\n\r\n\t// none found...\r\n\treturn pPartArray->GetStructure( startIndex );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | FlushDeadObjects | \r\n// flush any objects that are marked as dead\r\n// used so we can be sure they have gone, so we can re-use the memory\r\n// and also avoid fragmentation\r\nbool ScriptFlushDeadObjects( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMdl::Skate::Instance()->GetObjectManager()->FlushDeadObjects();\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | BindTrickToKeyCombo | binds the given trick to the key combo\r\n// @parm name | key_combo |\r\n// @parm name | trick_checksum |\r\n// @parmopt int | update_mappings | 1 | automatically update the trick mappings.\r\n// This should only be 0 in a split screen game\r\nbool ScriptBindTrickToKeyCombo( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 key_combo;\r\n\tpParams->GetChecksum( \"key_combo\", &key_combo, Script::ASSERT );\r\n\r\n\tuint32 trick_checksum=0;\r\n\tpParams->GetChecksum( \"trick\", &trick_checksum );\r\n\r\n\t// For create-a-tricks, the trick parameter is an integer index.\r\n\tint create_a_trick=0;\r\n\tbool got_create_a_trick=false;\r\n\tif (pParams->GetInteger( \"trick\", &create_a_trick ))\r\n\t{\r\n\t\tgot_create_a_trick=true;\r\n\t}\t\r\n\r\n\tDbg_MsgAssert(got_create_a_trick || trick_checksum,(\"\\n%s\\nMissing trick parameter\",pScript->GetScriptInfo()));\r\n\t\r\n\tbool update_mappings = true;\r\n\tint update_param = 1;\r\n\tpParams->GetInteger( \"update_mappings\", &update_param, Script::NO_ASSERT );\r\n\tif ( update_param == 0 )\r\n\t\tupdate_mappings = false;\r\n\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile();\r\n\r\n\t// are we binding a special trick?\r\n\tif ( pParams->ContainsFlag( \"special\" ) )\r\n\t{\r\n\t\tint index;\r\n\t\tif ( !pParams->GetInteger( \"index\", &index, Script::NO_ASSERT ) )\r\n        {\r\n            return false;\r\n        }\r\n        \r\n\t\t// add a new slot and update info\r\n\t\tObj::SSpecialTrickInfo trickInfo;\r\n\t\ttrickInfo.m_TrickSlot = key_combo;\r\n\t\tif (got_create_a_trick)\r\n\t\t{\r\n            trickInfo.m_TrickName = create_a_trick;\r\n        }\r\n        else\r\n        {\r\n            trickInfo.m_TrickName = trick_checksum;\r\n        }\r\n\t\tif ( pParams->ContainsFlag( CRCD(0x61a1bc57,\"cat\") ) )\r\n\t\t{\r\n\t\t\ttrickInfo.m_isCat = true;\r\n\t\t}\r\n        else\r\n        {\r\n\t\t\ttrickInfo.m_isCat = false;\r\n\t\t}\r\n\r\n        pSkaterProfile->SetSpecialTrickInfo( index, trickInfo, update_mappings );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tScript::CStruct* pTricks = pSkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") );\r\n\t\t\r\n\t\tif (got_create_a_trick)\r\n\t\t{\r\n\t\t\t// Make sure any existing checksum parameter is removed.\r\n\t\t\tpTricks->RemoveComponent(key_combo);\r\n\t\t\tpTricks->AddInteger( key_combo, create_a_trick );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpTricks->RemoveComponent(key_combo);\r\n            pTricks->AddChecksum( key_combo, trick_checksum );\r\n\t\t}\t\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// this does breadth first recursion on the structure and returns trick\r\n// highest in the tree (parent overwrites child).\r\nstatic uint32 s_find_trick_in_mapping( Script::CStruct* pMapping, uint32 trick_checksum, int recurse_level )\r\n{\r\n\tif ( recurse_level > 10 )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"GetKeyComboArrayFromTrickArray recursed too much.\" ) );\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tScript::CComponent* p_comp = pMapping->GetNextComponent( NULL );\r\n\tuint32 rv = 0;\r\n\twhile ( p_comp )\r\n\t{\r\n\t\tScript::CStruct* pTestStruct = Script::GetStructure( p_comp->mChecksum, Script::NO_ASSERT );\r\n\t\tScript::CComponent* p_next = pMapping->GetNextComponent( p_comp );\r\n\t\tif ( !rv && p_comp->mType == ESYMBOLTYPE_STRUCTURE )\r\n\t\t{\r\n\t\t\t// printf(\"recursing to level %i\\n\", recurse_level);\r\n\t\t\trv = s_find_trick_in_mapping( p_comp->mpStructure, trick_checksum, recurse_level + 1 );\r\n\t\t}\r\n\t\telse if ( !rv && pTestStruct )\r\n\t\t{\r\n\t\t\t// printf(\"recursing to level %i\\n\", recurse_level);\r\n\t\t\trv = s_find_trick_in_mapping( pTestStruct, trick_checksum, recurse_level + 1 );\r\n\t\t}\r\n\t\tif ( p_comp->mType == ESYMBOLTYPE_NAME && p_comp->mChecksum == trick_checksum )\r\n\t\t\trv = p_comp->mNameChecksum;\r\n\r\n\t\tp_comp = p_next;\r\n\t}\r\n\treturn rv;\r\n}\r\n\r\nstatic uint32 s_find_cat_in_mapping( Script::CStruct* pMapping, int cat_num )\r\n{\r\n\tScript::CComponent* p_comp = pMapping->GetNextComponent( NULL );\r\n\tuint32 rv = 0;\r\n\r\n    while ( p_comp )\r\n\t{\r\n        Script::CComponent* p_next = pMapping->GetNextComponent( p_comp );\r\n        if ( p_comp->mType == ESYMBOLTYPE_INTEGER && p_comp->mIntegerValue == cat_num )\r\n        {\r\n            printf(\"s_find_cat_in_mapping found %i\\n\", p_comp->mIntegerValue );\r\n            rv = p_comp->mNameChecksum;\r\n        }\r\n        p_comp = p_next;\r\n\t}\r\n    return rv;\r\n}\r\n\r\n// @script | GetKeyComboBoundToTrick | looks for any key combos that are currently\r\n// associated with the specified trick.  The result is stored in current_key_combo\r\n// @parm name | trick | trick to look for\r\nbool ScriptGetKeyComboBoundToTrick( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 trick_checksum = NULL;\r\n    int cat_num;\r\n    if (!pParams->GetChecksum( CRCD(0x270f56e1,\"trick\"), &trick_checksum, Script::NO_ASSERT) )\r\n    {\r\n        pParams->GetInteger( CRCD(0xa75b8581,\"cat_num\"), &cat_num, Script::ASSERT );\r\n    }\r\n\t\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile();\r\n\r\n\tuint32 key_combo = 0;\r\n\tbool found_special = false;\r\n\tint special_index = 0;\r\n\t\r\n    if (trick_checksum)\r\n    {\r\n        if ( !pParams->ContainsFlag( CRCD(0xb394c01c,\"special\") ) )\r\n    \t{\r\n    \t\tScript::CStruct* pTricks = pSkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") );\r\n    \t\r\n    \t\tuint32 test_key_combo = s_find_trick_in_mapping( pTricks, trick_checksum, 0 );\r\n    \t\t\r\n    \t\t// check that the mapping holds true the other way (ie, when we grab the trick\r\n    \t\t// based on this key_combo, do we get the same trick?).\r\n    \t\tuint32 test_trick_checksum = 0;\r\n    \t\tif ( pTricks->GetChecksum( test_key_combo, &test_trick_checksum, Script::NO_ASSERT ) && test_trick_checksum == trick_checksum )\r\n    \t\t\t\tkey_combo = test_key_combo;\r\n    \t}\r\n    \telse\r\n    \t{\r\n    \t\tif ( !key_combo && pParams->ContainsFlag( CRCD(0xb394c01c,\"special\") ) )\r\n    \t\t{\r\n    \t\t\t// printf(\"searching for special trick\\n\");\r\n    \t\t\tint numTricks = pSkaterProfile->GetNumSpecialTrickSlots();\r\n    \t\t\t// printf(\"%i tricks to check\\n\", numTricks);\r\n    \t\r\n    \t\t\t// search through current special tricks\r\n    \t\t\tfor ( int i = 0; i < numTricks; i++ )\r\n    \t\t\t{\r\n    \t\t\t\tObj::SSpecialTrickInfo trick_info = pSkaterProfile->GetSpecialTrickInfo( i );\r\n    \t\t\t\tif ( trick_info.m_TrickName == trick_checksum )\r\n    \t\t\t\t{\r\n    \t\t\t\t\tprintf(\"GetKeyComboBoundToTrick found a special trick\\n\");\r\n    \t\t\t\t\tfound_special = true;\r\n    \t\t\t\t\tspecial_index = i;\r\n    \t\t\t\t\tkey_combo = trick_info.m_TrickSlot;\r\n    \t\t\t\t\tbreak;\r\n    \t\t\t\t}\r\n    \t\t\t}\r\n    \t\t}\r\n    \t}\r\n    }\r\n    else\r\n    {\r\n        Script::CStruct* pTricks = pSkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") );\r\n    \t\r\n        key_combo = s_find_cat_in_mapping( pTricks, cat_num );\r\n    }\r\n    \r\n\t\r\n\tif ( key_combo )\r\n\t{\r\n\t\tpScript->GetParams()->AddChecksum( \"current_key_combo\", key_combo );\r\n\t\tif ( found_special )\r\n\t\t{\r\n\t\t\tprintf(\"current_index: %i\\n\", special_index);\r\n\t\t\tpScript->GetParams()->AddInteger( \"current_index\", special_index );\r\n\t\t}\r\n\t\treturn true;\r\n\t}\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | UpdateTrickMappings | forces the trick mappings to update\r\n// @parmopt int | skater | | the skater num\r\n// @parmopt name | skaterId | | the id of the skater\r\nbool ScriptUpdateTrickMappings( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\r\n\tObj::CPlayerProfileManager* pProfileMan = pSkate->GetPlayerProfileManager();\r\n\t\r\n\t// TODO: if we ever do split screen network games, this will not work!\r\n\t// It assumes there is only one local skater when in a net game\r\n\tif ( gamenet_man->InNetGame() )\r\n\t{\r\n\t\tObj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n\t\tDbg_MsgAssert( pSkater, ( \"UpdateTrickMappings couldn't find a local skater\" ) );\r\n\t\t\r\n\t\tObj::CSkaterProfile* pProfile = pProfileMan->GetProfile( 0 );\r\n\t\t\r\n\t\tObj::CTrickComponent* pTrickComponent = GetTrickComponentFromObject(pSkater);\r\n\t\tDbg_Assert(pTrickComponent);\r\n\t\tpTrickComponent->UpdateTrickMappings( pProfile );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint skater_num;\r\n\t\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skater_num, Script::ASSERT );\r\n\t\tObj::CSkater* pSkater = pSkate->GetSkater( skater_num );\r\n\t\tDbg_Assert( pSkater );\r\n\t\tObj::CSkaterProfile* pProfile = pProfileMan->GetProfile( skater_num );\r\n\t\tDbg_Assert( pProfile );\r\n\t\r\n\t\tif ( pSkater && pProfile )\r\n\t\t{\r\n\t\t\tObj::CTrickComponent* pTrickComponent = GetTrickComponentFromObject(pSkater);\r\n\t\t\tDbg_Assert(pTrickComponent);\r\n\t\t\tpTrickComponent->UpdateTrickMappings( pProfile );\r\n\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetConfigurableTricksFromType | returns an array of trick checksums\r\n// which have the type specified.  The array is stored as ConfigurableTricks\r\n// @parm name | type | the type to search for\r\n// @flag special | search for special tricks of this type\r\nbool ScriptGetConfigurableTricksFromType( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 type = 0;\r\n\tpParams->GetChecksum( \"type\", &type, Script::NO_ASSERT );\r\n\r\n\tbool find_special = pParams->ContainsFlag( \"special\" );\r\n\r\n\tDbg_MsgAssert( type || find_special, ( \"You must specify a type or provide the special flag\" ) );\r\n\r\n\tuint32 trick_list[128];\r\n\tint num_found = 0;\r\n    int cat_list[128];\r\n    int num_cats_found = 0;\r\n    \r\n    // grab some checksums\r\n    //uint32 createdtrick = Script::GenerateCRC( \"CreatedTrick\" );\r\n    uint32 grabtrick = Script::GenerateCRC( \"GrabTrick\" );\r\n    uint32 fliptrick = Script::GenerateCRC( \"FlipTrick\" );\r\n\r\n\t// grab the list of all tricks\r\n\tScript::CArray* p_all_tricks = Script::GetArray( \"ConfigurableTricks\", Script::ASSERT );\r\n\tDbg_MsgAssert( p_all_tricks->GetType() == ESYMBOLTYPE_NAME, ( \"ConfigurableTricks array had wrong type\\n\" ) );\r\n\r\n\tint size = p_all_tricks->GetSize();\r\n\tfor ( int i = 0; i < size; i++ )\r\n\t{\r\n\t\tDbg_MsgAssert( num_found < 128, ( \"Found too many tricks\" ) );\r\n\t\t\r\n\t\tuint32 trick = p_all_tricks->GetChecksum( i );\r\n\t\tScript::CStruct* p_trick = Script::GetStructure( trick, Script::NO_ASSERT );\r\n\r\n        if ( p_trick )\r\n\t\t{\r\n\t\t\t// get the type\r\n\t\t\tuint32 current_trick_type;\r\n\r\n\t\t\t// first check for optional TrickType var\r\n\t\t\tif ( !p_trick->GetChecksum( \"TrickType\", &current_trick_type, Script::NO_ASSERT ) )\r\n\t\t\t{\r\n\t\t\t\tif ( !p_trick->GetChecksum( \"Scr\", &current_trick_type, Script::NO_ASSERT ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t// assume it's a grind\r\n\t\t\t\t\tcurrent_trick_type = Script::GenerateCRC( \"GrindTrick\" );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif ( ( find_special && !type ) || current_trick_type == type )\r\n\t\t\t{\r\n\t\t\t\t// get the params array and look for the special flag\r\n\t\t\t\tScript::CStruct* p_trick_params;\r\n\t\t\t\tp_trick->GetStructure( \"Params\", &p_trick_params, Script::ASSERT );\r\n\r\n\t\t\t\tif ( find_special && p_trick_params->ContainsFlag( \"IsSpecial\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\ttrick_list[num_found] = trick;\r\n\t\t\t\t\tnum_found++;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( !find_special && !p_trick_params->ContainsFlag( \"IsSpecial\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\ttrick_list[num_found] = trick;\r\n\t\t\t\t\tnum_found++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n    // if type is grab or flip then list created tricks too!\r\n    if ( type == grabtrick || type == fliptrick )\r\n    {\r\n        Mdl::Skate * pSkate = Mdl::Skate::Instance();\r\n        Obj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n\t    if ( pSkater )\r\n        {\r\n            int size = Game::vMAX_CREATED_TRICKS;\r\n            for ( int i = 1; i < size; i++ )    // start at one because 0 is just a clipboard!\r\n        \t{\r\n                int full = 0;\r\n                if ( pSkater->m_created_trick[i]->mp_other_params->GetInteger( CRCD(0x1f802b5f,\"full\"), &full, Script::NO_ASSERT ) )\r\n                {\r\n                    if ( full )\r\n                    {\r\n                        cat_list[num_cats_found] = i; //trick;\r\n                        num_cats_found++;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n\tif ( num_found == 0 )\r\n\t\treturn false;\r\n\r\n\t// create an array to return\r\n\tScript::CArray* p_configurable_tricks = new Script::CArray();\r\n\tp_configurable_tricks->SetSizeAndType( num_found, ESYMBOLTYPE_NAME );\r\n\tfor ( int i = 0; i < num_found; i++ )\r\n\t\tp_configurable_tricks->SetChecksum( i, trick_list[i] );\r\n\r\n\t// add the array\r\n\tpScript->GetParams()->AddArrayPointer( \"ConfigurableTricks\", p_configurable_tricks );\r\n\r\n    if ( num_cats_found > 0 )\r\n    {\r\n        // create an array to return\r\n    \tScript::CArray* p_configurable_cats = new Script::CArray();\r\n    \tp_configurable_cats->SetSizeAndType(num_cats_found, ESYMBOLTYPE_INTEGER );\r\n    \tfor ( int i = 0; i < num_cats_found; i++ )\r\n    \t\tp_configurable_cats->SetInteger( i, cat_list[i] );\r\n    \r\n    \t// add the array\r\n    \tpScript->GetParams()->AddArrayPointer( \"ConfigurableCats\", p_configurable_cats );\r\n    }\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | TrickIsLocked | true if the trick is associated with a skater\r\n// that is locked\r\n// @parm name | trick | the trick name\r\nbool ScriptTrickIsLocked( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 trick;\r\n\tpParams->GetChecksum( \"trick\", &trick, Script::ASSERT );\r\n\r\n\tScript::CStruct* p_trick = Script::GetStructure( trick, Script::ASSERT );\r\n\r\n\tif ( p_trick )\r\n\t{\r\n\t\tScript::CStruct* p_trick_params;\r\n\t\tp_trick->GetStructure( \"Params\", &p_trick_params, Script::ASSERT );\r\n\r\n\t\tuint32 skater;\r\n\t\tif ( p_trick_params && p_trick_params->GetChecksum( CRCD(0x5b8ab877,\"skater\"), &skater, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\tObj::CPlayerProfileManager* pPlayerProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager();\r\n\t\t\t\r\n\t\t\tif ( p_trick_params->ContainsFlag( \"OnlyWith\" ) )\r\n\t\t\t{\r\n\t\t\t\tObj::CSkaterProfile* pCurrentProfile = pPlayerProfileManager->GetCurrentProfile();\r\n\t\t\t\treturn ( pCurrentProfile->GetSkaterNameChecksum() != skater );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tint num_profiles = pPlayerProfileManager->GetNumProfileTemplates();\r\n\t\t\t\tfor ( int i = 0; i < num_profiles; i++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tObj::CSkaterProfile* pProfile = pPlayerProfileManager->GetProfileTemplateByIndex( i );\r\n\t\t\t\t\tif ( pProfile->GetSkaterNameChecksum() == skater )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint isLocked = 0;\r\n\t\t\t\t\t\tpProfile->GetInfo()->GetInteger( \"is_hidden\", &isLocked, Script::NO_ASSERT );\r\n\t\t\t\t\t\treturn ( isLocked != 0 );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tDbg_MsgAssert( 0, ( \"TrickIsLocked confused by skater %s in trick %s\\n\", Script::FindChecksumName( skater ), Script::FindChecksumName( trick ) ) );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t\tDbg_MsgAssert( 0, ( \"TrickIsLocked couldn't find trick %s\\n\", Script::FindChecksumName( trick ) ) );\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetTrickDisplayText | gets the text corresponding to this trick\r\n// @parm name | trick | the trick name\r\nbool ScriptGetTrickDisplayText( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 trick;\r\n\tpParams->GetChecksum( \"trick\", &trick, Script::ASSERT );\r\n\r\n\tScript::CStruct* p_trick = Script::GetStructure( trick, Script::ASSERT );\r\n\r\n\tif ( p_trick )\r\n\t{\r\n\t\tScript::CStruct* p_trick_params;\r\n\t\tp_trick->GetStructure( \"Params\", &p_trick_params, Script::ASSERT );\r\n\r\n\t\tconst char* p_trick_name;\r\n\t\tp_trick_params->GetLocalString( CRCD(0xa1dc81f9,\"name\"), &p_trick_name, Script::ASSERT );\r\n\r\n\t\tpScript->GetParams()->AddString( \"trick_display_text\", p_trick_name );\r\n\r\n\t\t// look for any double tap tricks\r\n\t\tuint32 extra_trick = 0;\r\n\t\tif ( !p_trick_params->GetChecksum( \"ExtraTricks\", &extra_trick, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\t// look for an array of extra tricks and grab the first one\r\n\t\t\tScript::CArray* p_extra_tricks;\r\n\t\t\tif ( p_trick_params->GetArray( \"ExtraTricks\", &p_extra_tricks, Script::NO_ASSERT ) )\r\n\t\t\t\textra_trick = p_extra_tricks->GetChecksum( 0 );\r\n\t\t}\r\n\r\n\t\t// add any extra trick info\r\n\t\tif ( extra_trick )\r\n\t\t{\r\n\t\t\t// grab this extra trick\r\n\t\t\tScript::CArray* p_temp = Script::GetArray( extra_trick, Script::ASSERT );\r\n\t\t\tScript::CStruct* p_extra_trick = p_temp->GetStructure( 0 );\r\n\t\t\tDbg_Assert( p_extra_trick );\r\n\t\t\tScript::CStruct* p_extra_trick_params;\r\n\t\t\tp_extra_trick->GetStructure( \"Params\", &p_extra_trick_params, Script::ASSERT );\r\n\t\t\tconst char* p_extra_trick_string;\r\n\t\t\tp_extra_trick_params->GetString( CRCD(0xa1dc81f9,\"name\"), &p_extra_trick_string, Script::ASSERT );\r\n\t\t\tpScript->GetParams()->AddString( \"extra_trick_string\", p_extra_trick_string );\r\n\t\t\tpScript->GetParams()->AddChecksum( \"extra_trick_checksum\", extra_trick );\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetSpecialTrickInfo | gets the special trick info for the slot\r\n// specified\r\n// @parm int | index | the special trick slot\r\nbool ScriptGetSpecialTrickInfo( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tint index;\r\n\tpParams->GetInteger( \"index\", &index, Script::ASSERT );\r\n\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* p_SkaterProfile = skate_mod->GetCurrentProfile();\r\n\tObj::SSpecialTrickInfo trick_info = p_SkaterProfile->GetSpecialTrickInfo( index );\r\n\r\n\tpScript->GetParams()->AddChecksum( \"special_trickslot\", trick_info.m_TrickSlot );\r\n\t\r\n    \r\n    if ( trick_info.m_isCat )\r\n    {\r\n        pScript->GetParams()->AddInteger( \"special_trickname\", trick_info.m_TrickName );\r\n    }\r\n    else\r\n    {\r\n        pScript->GetParams()->AddChecksum( \"special_trickname\", trick_info.m_TrickName );\r\n    }\r\n    \r\n    pScript->GetParams()->AddInteger( \"isCat\", trick_info.m_isCat );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetTrickType | gets the type of the specified trick and returns\r\n// the result in the trick_type param\r\n// @parm name | trick | the name of the trick\r\nbool ScriptGetTrickType( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 trick_checksum;\r\n\tpParams->GetChecksum( \"trick\", &trick_checksum, Script::ASSERT );\r\n\r\n\tScript::CStruct* p_trick = Script::GetStructure( trick_checksum, Script::ASSERT );\r\n\r\n\tuint32 trick_type;\r\n\t// first check for optional TrickType var\r\n\tif ( !p_trick->GetChecksum( \"TrickType\", &trick_type, Script::NO_ASSERT ) )\r\n\t{\r\n\t\tif ( !p_trick->GetChecksum( \"Scr\", &trick_type, Script::NO_ASSERT ) )\r\n\t\t{\r\n\t\t\t// assume it's a grind\r\n\t\t\ttrick_type = Script::GenerateCRC( \"GrindTrick\" );\r\n\t\t}\r\n\t}\r\n\tpScript->GetParams()->AddChecksum( \"trick_type\", trick_type );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetIndexOfItemContaining | this will search through the given\r\n// array (must be an array of structures) for the structure containing a param\r\n// the index will be placed in the calling script's params (index)\r\n// @parm array | array | the array to search\r\n// @parmopt int | index | 0 | index to start at\r\n// @parm name | name | name of the param to search for\r\n// @parm name | value | value param should have for a match\r\nbool ScriptGetIndexOfItemContaining( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tuint32 array_name;\r\n\tpParams->GetChecksum( \"array\", &array_name, Script::ASSERT );\r\n\tScript::CArray* p_array = Script::GetArray( array_name, Script::ASSERT );\r\n\tDbg_MsgAssert( p_array->GetType() == ESYMBOLTYPE_STRUCTURE, ( \"This function only works on arrays of structures.\" ) );\r\n\r\n\tuint32 item;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &item, Script::ASSERT );\r\n\r\n\tint index = 0;\r\n\tpParams->GetInteger( \"index\", &index, Script::NO_ASSERT );\r\n\r\n\tuint32 value;\r\n\tpParams->GetChecksum( \"value\", &value, Script::ASSERT );\r\n\r\n\tint array_size = p_array->GetSize();\r\n\tfor ( ; index < array_size; index++ )\r\n\t{\r\n\t\tScript::CStruct* p_struct = p_array->GetStructure( index );\r\n\t\tif ( p_struct->ContainsComponentNamed( item ) )\r\n\t\t{\r\n\t\t\tuint32 item_value;\r\n\t\t\tp_struct->GetChecksum( item, &item_value, Script::ASSERT );\r\n\t\t\tif ( item_value == value )\r\n\t\t\t{\r\n\t\t\t\tpScript->GetParams()->AddInteger( \"index\", index );\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetLevelRecords | appends the records to the calling script's params\r\nbool ScriptGetLevelRecords( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\t\r\n\tint levelNum;\r\n\tif ( !pParams->GetInteger( \"level\", &levelNum, Script::NO_ASSERT ) )\r\n\t\tlevelNum = pSkate->GetCareer()->GetLevel();\t\r\n\t\r\n\tRecords::CGameRecords* pGameRecords = pSkate->GetGameRecords();\r\n\tRecords::CLevelRecords* pLevelRecords = pGameRecords->GetLevelRecords( levelNum );\r\n\tpLevelRecords->WriteIntoStructure( pScript->GetParams() );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ResetComboRecords | resets the score object's combo records\r\nbool ScriptResetComboRecords( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = pSkate->GetLocalSkater();\r\n\tif( pSkater )\r\n\t{\r\n\t\tMdl::Score* pScore = pSkater->GetScoreObject();\r\n\t\r\n\t\tpScore->ResetComboRecords();\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetNumberOfTrickOccurrences | returns the number of times\r\n// the given trick appears in the skater's current score pot\r\n// @parm string | TrickText | trick string to look for\r\nbool ScriptGetNumberOfTrickOccurrences( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tconst char* p_trick;\r\n\tpParams->GetString( \"TrickText\", &p_trick, Script::ASSERT );\r\n\tuint32 trick = Script::GenerateCRC( p_trick );\r\n\r\n\tMdl::Skate * skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater* pSkater = skate_mod->GetLocalSkater();\r\n\tMdl::Score* pScore = pSkater->GetScoreObject();\r\n\r\n\tint num = pScore->GetCurrentNumberOfOccurrencesByName( trick );\r\n\tpScript->GetParams()->AddInteger( \"number_of_occurrences\", num );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetNumSoundtracks | returns the number of soundtracks\r\n// in the numSoundtracks param\r\nbool ScriptGetNumSoundtracks( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tDbg_MsgAssert( Config::GetHardware() == Config::HARDWARE_XBOX, ( \"GetNumSoundtracks can only be called on XBox\" ) );\r\n\tint numSoundtracks = Nx::CEngine::sGetNumSoundtracks();\r\n\tpScript->GetParams()->AddInteger( \"numSoundtracks\", numSoundtracks );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetSoundtrackName( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tDbg_MsgAssert( Config::GetHardware() == Config::HARDWARE_XBOX, ( \"GetNumSoundtracks can only be called on XBox\" ) );\r\n\tint soundtrack_number;\r\n\tpParams->GetInteger( NONAME, &soundtrack_number, Script::ASSERT );\r\n\tconst char* pSoundtrackName = Nx::CEngine::sGetSoundtrackName( soundtrack_number );\r\n\tpScript->GetParams()->AddString( \"soundtrackName\", pSoundtrackName );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | BindControllerToSkater | remaps the given controller to the\r\n// skater\r\n// @parm int | controller | the controller number\r\n// @parm int | skater_heap_index | the skater num\r\nbool ScriptBindControllerToSkater( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tint controller;\r\n\tpParams->GetInteger( \"controller\", &controller, Script::ASSERT );\r\n\r\n\tint skater;\r\n\tpParams->GetInteger( \"skater_heap_index\", &skater, Script::ASSERT );\r\n\r\n\tprintf(\"attempting to bind skater %i to controller %i\\n\", skater, controller);\r\n\r\n\tMdl::Skate *pSkate = Mdl::Skate::Instance();\r\n\tpSkate->m_device_server_map[skater] = controller;\r\n\r\n\tpSkate->UpdateSkaterInputHandlers();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptBindFrontEndToController( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tint controller;\r\n\tpParams->GetInteger( \"controller\", &controller, Script::ASSERT );\r\n\r\n\tint front_end_pad;\r\n\tpParams->GetInteger( \"front_end_pad\", &front_end_pad, Script::ASSERT );\r\n\r\n\tprintf(\"attempting to bind front end %i to controller %i\\n\", front_end_pad, controller);\r\n\r\n\tMdl::FrontEnd *pFrontEnd = Mdl::FrontEnd::Instance();\r\n\t\r\n\t// find any controllers using this front end mapping and switch\r\n\tint current = pFrontEnd->m_device_server_map[front_end_pad];\r\n\tfor ( int i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t{\r\n\t\tif ( pFrontEnd->m_device_server_map[i] == controller )\r\n\t\t\tpFrontEnd->m_device_server_map[i] = current;\r\n\t}\r\n\tpFrontEnd->m_device_server_map[front_end_pad] = controller;\r\n\r\n\tpFrontEnd->UpdateInputHandlerMappings();\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | ControllerBoundToDifferentSkater | \r\n// @parm int | controller |\r\n// @parm int | skater | \r\nbool ScriptControllerBoundToDifferentSkater( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tint skater;\r\n\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skater, Script::ASSERT );\r\n\r\n\tint controller;\r\n\tpParams->GetInteger( \"controller\", &controller, Script::ASSERT );\r\n\r\n\tMdl::Skate* pSkate = Mdl::Skate::Instance();\r\n\t\r\n\tfor ( int i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )\r\n\t{\r\n\t\t// don't check the skater we're trying to bind\r\n\t\tif ( i == skater )\r\n\t\t\tcontinue;\r\n\r\n\t\tObj::CSkater* pSkater = pSkate->GetSkater( i );\r\n\t\tif ( pSkater && pSkater->IsLocalClient() )\r\n\t\t{\r\n\t\t\tif ( pSkate->m_device_server_map[i] == controller )\r\n\t\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptControllerBoundToSkater( Script::CStruct* pParams, Script::CScript* pScript )\r\n{\r\n\tint controller;\r\n\tpParams->GetInteger( \"controller\", &controller, Script::ASSERT );\r\n\r\n\tint skater;\r\n\tpParams->GetInteger( CRCD(0x5b8ab877,\"skater\"), &skater, Script::ASSERT );\r\n\r\n\tDbg_MsgAssert( skater >= 0 && skater < Mdl::Skate::vMAX_SKATERS, ( \"Bad skater index %i passed to ControllerBoundToSkater\\n\", skater ) );\r\n\treturn ( Mdl::Skate::Instance()->m_device_server_map[skater] == controller );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetKeyComboArrayFromTrickArray | returns an array of key combos (KeyCombos)\r\n// that correspond to the passed trick array\r\n// @parm array | tricks | array of trick names, eg [Trick_KickFlip Trick_HeelFlip]\r\nbool ScriptGetKeyComboArrayFromTrickArray( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tScript::CArray* pTricks;\r\n\tpParams->GetArray( \"tricks\", &pTricks, Script::ASSERT );\r\n\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tObj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile();\r\n\tScript::CStruct* pTrickMapping = pSkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,\"trick_mapping\") );\r\n\r\n\tint size = pTricks->GetSize();\r\n\t// make a return array\r\n\tScript::CArray* pKeyCombos = new Script::CArray();\r\n\tpKeyCombos->SetSizeAndType( size, ESYMBOLTYPE_NAME );\r\n\r\n\tfor ( int i = 0; i < size; i++ )\r\n\t{\r\n\t\tuint32 trick_checksum = pTricks->GetChecksum( i );\r\n\t\t\r\n\t\t// search for this trick in the current mapping\r\n\t\tuint32 key_combo = s_find_trick_in_mapping( pTrickMapping, trick_checksum, 0 );\r\n\r\n\t\tif ( key_combo == 0 )\r\n\t\t{\r\n\t\t\t// look for a special trick\r\n\t\t\tint num_specials = pSkaterProfile->GetNumSpecialTrickSlots();\r\n\t\t\tfor ( int j = 0; j < num_specials; j++ )\r\n\t\t\t{\r\n\t\t\t\tObj::SSpecialTrickInfo trick_info = pSkaterProfile->GetSpecialTrickInfo( j );\r\n\t\t\t\tif ( trick_info.m_TrickName == trick_checksum )\r\n\t\t\t\t{\r\n\t\t\t\t\tkey_combo = trick_info.m_TrickSlot;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\t\t\t\r\n\t\t}\r\n\r\n\t\tDbg_MsgAssert( key_combo != 0, ( \"GetKeyComboFromTrickArray found an unmpped trick - %s\", Script::FindChecksumName( trick_checksum ) ) );\r\n\t\tpKeyCombos->SetChecksum( i, key_combo );\r\n\t}\r\n\r\n\tpScript->GetParams()->AddArray( \"KeyCombos\", pKeyCombos );\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | FirstInputReceived | the game does not start checking for\r\n// disconnected controllers until this is called\r\nbool ScriptFirstInputReceived( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMdl::Skate::Instance()->FirstInputReceived();\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | VibrateController | \r\n// @parm int | port | \r\n// @parm int | actuator |\r\n// @parm int | percent |\r\nbool ScriptVibrateController( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tint port;\r\n\tpParams->GetInteger( \"port\", &port, Script::ASSERT );\r\n\r\n\tint actuator;\r\n\tpParams->GetInteger( \"actuator\", &actuator, Script::ASSERT );\r\n\r\n\tint percent;\r\n\tpParams->GetInteger( \"percent\", &percent, Script::ASSERT );\r\n\t\r\n\tSIO::Manager* sio_manager = SIO::Manager::Instance();\r\n\r\n\t// TODO: this won't work if we support multitap (assumes slot 0)\r\n\tSIO::Device* pDevice = sio_manager->GetDevice( port, 0 );\r\n\tif ( pDevice )\r\n\t{\r\n\t\tpDevice->ActivateActuator( actuator, percent );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | LockCurrentSkaterProfileIndex | \r\nbool ScriptLockCurrentSkaterProfileIndex( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tint locked = true;\r\n\tpParams->GetInteger( NONAME, &locked, Script::ASSERT );\r\n\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\r\n\tObj::CPlayerProfileManager* pProfileMan = pSkate->GetPlayerProfileManager();\r\n\tpProfileMan->LockCurrentSkaterProfileIndex( locked );\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | SetSpecialTrickInfo | \r\n// @parm int | slot | \r\n// @parm name | trick_name | \r\n// @parm name | key_combo |\r\n// @flag update_mappings | \r\nbool ScriptSetSpecialTrickInfo( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tint slot;\r\n\tpParams->GetInteger( \"slot\", &slot, Script::ASSERT );\r\n\r\n\tuint32 trick_name;\r\n\tpParams->GetChecksum( \"trick_name\", &trick_name, Script::ASSERT );\r\n\t\r\n\tuint32 key_combo;\r\n\tpParams->GetChecksum( \"key_combo\", &key_combo, Script::ASSERT );\r\n\r\n\tMdl::Skate* skate_mod = Mdl::Skate::Instance();\r\n\tObj::CPlayerProfileManager* pPlayerProfileManager = skate_mod->GetPlayerProfileManager();\r\n\tObj::CSkaterProfile* pProfile = NULL;\r\n\tpProfile = pPlayerProfileManager->GetCurrentProfile();\r\n\r\n\tDbg_MsgAssert( pProfile, ( \"SetSpecialTrickInfo couldn't get a profile\" ) );\r\n\tif ( pProfile )\r\n\t{\r\n\t\t// printf(\"setting slot %i to %s, %s\\n\", slot, Script::FindChecksumName( trick_name ), Script::FindChecksumName( key_combo ) );\r\n\t\tObj::SSpecialTrickInfo trickInfo;\r\n\t\ttrickInfo.m_TrickName = trick_name;\r\n\t\ttrickInfo.m_TrickSlot = key_combo;\r\n\t\tpProfile->SetSpecialTrickInfo( slot, trickInfo, false );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic bool s_is_angle(Script::CArray *p_angles_array, uint32 component_name)\r\n{\r\n\tif (!p_angles_array)\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tuint32 size=p_angles_array->GetSize();\r\n\tfor (uint32 i=0; i<size; ++i)\r\n\t{\r\n\t\tif (component_name==p_angles_array->GetChecksum(i))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\t\r\nstatic float make_angle_in_range(float a)\r\n{\r\n\twhile (a < 0.0f)\r\n\t{\r\n\t\ta+=360.0f;\r\n\t}\r\n\twhile (a > 360.0f)\r\n\t{\r\n\t\ta-=360.0f;\r\n\t}\r\n\treturn a;\r\n}\r\n\t\t\r\n// @script | InterpolateParameters | This will scan through the structure A, and any parameters in it\r\n// which have type int or float and such that the same named parameter exists in B and also has type int\r\n// or float will have their value interpolated between the two values, and the parameter put into a\r\n// returned structure named Interpolated.\r\n// Note that the returned structure will only contain the parameters that were interpolated, so if\r\n// structure A contained a string, that parameter will not get into Interpolated\r\n// @parm structure | a | The first structure\r\n// @parm structure | b | The second structure\r\n// @parmopt float | Proportion | 0.0 | A value between 0 and 1. 0 means all of structure A and none of structure B,\r\n// 1 means all of B and none of A. 0.5 will therefore be half way between the two.\r\n// @parmopt array | Ignore | | An optional array of parameter names to ignore. Parameters whose type cannot\r\n// be interpolated, such as strings, will automatically be ignored, but the Ignore array allows certain\r\n// integer or float params to be ignored too.\r\n// @parmopt array | Angles | | An optional array of parameters whose values are to be treated as angles.\r\n// So when interpolating between 10 and 350 degrees for example, instead of simply interpolating from\r\n// the number 10 to 350, it will go from 10 backwards through 0 and 359 to 350.\r\nbool ScriptInterpolateParameters( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tScript::CStruct *p_new_structure=new Script::CStruct;\r\n\t\r\n\tScript::CStruct *p_a=NULL;\r\n\tpParams->GetStructure(CRCD(0x174841bc,\"a\"),&p_a,Script::ASSERT);\r\n\t\r\n\tScript::CStruct *p_b=NULL;\r\n\tpParams->GetStructure(CRCD(0x8e411006,\"b\"),&p_b,Script::ASSERT);\r\n\t\r\n\tfloat proportion=0.0f;\r\n\tpParams->GetFloat(CRCD(0x404e690d,\"Proportion\"),&proportion);\r\n\t\r\n\tScript::CArray *p_ignore=NULL;\r\n\tpParams->GetArray(CRCD(0xf277291d,\"Ignore\"),&p_ignore);\r\n\t\r\n\tScript::CArray *p_angles_array=NULL;\r\n\tpParams->GetArray(CRCD(0x9d2d0915,\"Angles\"),&p_angles_array);\r\n\t\r\n\tScript::CComponent *p_comp = p_a->GetNextComponent();\r\n\twhile (p_comp)\r\n\t{\r\n\t\tbool ignore=false;\r\n\t\t\r\n\t\tif (p_ignore)\r\n\t\t{\r\n\t\t\tfor (uint32 i=0; i<p_ignore->GetSize(); ++i)\r\n\t\t\t{\r\n\t\t\t\tif (p_comp->mNameChecksum==p_ignore->GetChecksum(i))\r\n\t\t\t\t{\r\n\t\t\t\t\tignore=true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!ignore)\r\n\t\t{\r\n\t\t\tuint32 component_name=0;\r\n\t\t\tfloat value_a=0.0f;\r\n\t\t\tbool write_integer=true;\r\n\t\t\t\r\n\t\t\t// See if the component in structure A is of a type that needs to be interpolated.\r\n\t\t\tif (p_comp->mType==ESYMBOLTYPE_INTEGER)\r\n\t\t\t{\r\n\t\t\t\tcomponent_name=p_comp->mNameChecksum;\r\n\t\t\t\tvalue_a=(float)p_comp->mIntegerValue;\r\n\t\t\t}\r\n\t\t\telse if (p_comp->mType==ESYMBOLTYPE_FLOAT)\r\n\t\t\t{\r\n\t\t\t\tcomponent_name=p_comp->mNameChecksum;\r\n\t\t\t\tvalue_a=p_comp->mFloatValue;\r\n\t\t\t\twrite_integer=false;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// If found a candidate for interpolation, see if there is a similarly named\r\n\t\t\t// component in structure B, and if so, interpolate between the two and stick\r\n\t\t\t// a new component of that name into the new structure.\r\n\t\t\tif (component_name)\r\n\t\t\t{\r\n\t\t\t\tbool got_value_b=false;\r\n\t\t\t\t\r\n\t\t\t\tfloat value_b=0.0f;\r\n\t\t\t\tint integer_value_b=0;\r\n\t\t\t\tif (p_b->GetInteger(component_name,&integer_value_b))\r\n\t\t\t\t{\r\n\t\t\t\t\tgot_value_b=true;\r\n\t\t\t\t\tvalue_b=(float)integer_value_b;\r\n\t\t\t\t}\r\n\t\t\t\telse if (p_b->GetFloat(component_name,&value_b))\r\n\t\t\t\t{\r\n\t\t\t\t\tgot_value_b=true;\r\n\t\t\t\t\twrite_integer=false;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (got_value_b)\r\n\t\t\t\t{\r\n\t\t\t\t\tfloat new_value=0.0f;\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (s_is_angle(p_angles_array,component_name))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfloat d=value_b-value_a;\r\n\t\t\t\t\t\td=make_angle_in_range(d);\r\n\t\t\t\t\t\tif (d > 180.0f)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\td=-(360.0f-d);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tnew_value=value_a+proportion*d;\r\n\t\t\t\t\t\tnew_value=make_angle_in_range(new_value);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnew_value=value_a+proportion*(value_b-value_a);\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\tif (write_integer)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_new_structure->AddInteger(component_name,(int)new_value);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_new_structure->AddFloat(component_name,new_value);\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t\t\t\r\n\t\tp_comp = pParams->GetNextComponent(p_comp);\r\n\t}\t\r\n\t\r\n\tpScript->GetParams()->AddStructurePointer(CRCD(0xff6f3872,\"Interpolated\"),p_new_structure);\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t\r\n// @script | PlaySkaterStream | skater member func.\r\n// @parm string | type | the stream type.\r\n// @parmopt int | num_possible | 10 | the maximum number of streams to search for\r\nbool ScriptPlaySkaterStream ( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tDbg_Assert(pScript->mpObject);\r\n\tDbg_MsgAssert(pScript->mpObject->GetType() == SKATE_TYPE_SKATER, (\"PlaySkaterStream may only be called on a skater object\"));\r\n\t\r\n\tObj::CSkater* p_skater = static_cast< Obj::CSkater* >(pScript->mpObject.Convert());\r\n\t\t\r\n\tconst char* p_type;\r\n\tpParams->GetString( CRCD(0x7321a8d6,\"type\"), &p_type, Script::ASSERT );\r\n\t\r\n\tint max_num = 10;\r\n\tpParams->GetInteger( CRCD(0x58492707,\"num_possible\"), &max_num, Script::NO_ASSERT );\r\n\r\n\tScript::CArray* p_stream_indices = new Script::CArray();\r\n\tp_stream_indices->SetSizeAndType( max_num, ESYMBOLTYPE_INTEGER );\r\n\t// generate list of indices (start at 1)\r\n\tfor ( int i = 0; i < max_num; i++ )\r\n\t\tp_stream_indices->SetInteger( i, i + 1 );\r\n\r\n\t// randomize list\r\n\tfor ( int i = 0; i < max_num; i++ )\r\n\t{\r\n\t\t// grab a random index and switch with the current index\r\n\t\tint random_index = Mth::Rnd( max_num );\r\n\t\tint random_value = p_stream_indices->GetInteger( random_index );\r\n\t\tp_stream_indices->SetInteger( random_index, p_stream_indices->GetInteger( i ) );\r\n\t\tp_stream_indices->SetInteger( i, random_value );\r\n\t}\r\n\r\n\t// get the skater's first name\r\n\tchar p_first_name[128];\r\n\tstrcpy( p_first_name, p_skater->m_firstName );\r\n\r\n\t// resolve to last name\r\n\tchar p_last_name[128];\r\n\r\n\tif ( p_skater->m_isPro )\r\n\t{\r\n\t\t// grab the last name string from global array\r\n\t\tScript::CStruct* pLastNames = Script::GetStructure( CRCD(0x5775194e,\"goal_pro_last_names\"), Script::ASSERT );\r\n\t\tuint32 first_name_checksum = Script::GenerateCRC( p_first_name );\r\n\t\tconst char* p_temp_last_name;\r\n\t\tpLastNames->GetString( first_name_checksum, &p_temp_last_name, Script::ASSERT );\r\n\t\tDbg_MsgAssert( strlen( p_temp_last_name ) < 128, ( \"buffer overflow\" ) );\r\n\t\tstrcpy( p_last_name, p_temp_last_name );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tstrcpy( p_last_name, \"custom\" );\r\n\t\tif ( p_skater->m_isMale )\r\n\t\t{\r\n\t\t\tstrcat( p_last_name, \"m\" );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tstrcat( p_last_name, \"f\" );\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tDbg_MsgAssert( strlen( p_last_name ) < 128, ( \"buffer overflow in PlaySkaterStream: %s\", p_last_name ) );\r\n\t// find the first valid stream and play\r\n\tchar stream_name[128];\r\n\t\t\r\n\tfor ( int i = 0; i < max_num; i++ )\r\n\t{\r\n\t\tDbg_MsgAssert( strlen( p_last_name ) + strlen( p_type ) + 2 < 128, ( \"buffer overflow in PlaySkaterStream: %s\", stream_name ) );\r\n\t\tsprintf( stream_name, \"%s_%s%02i\", p_last_name, p_type, p_stream_indices->GetInteger( i ) );\r\n\t\t\r\n\t\t// printf(\"figured a stream name of %s\\n\", stream_name);\r\n\t\tif ( Pcm::StreamExists( Script::GenerateCRC( stream_name ) ) )\r\n\t\t{\r\n\t\t\tScript::CStruct* pTemp = new Script::CStruct;\r\n\t\t\tpTemp->AddChecksum( \"stream_checksum\", Script::GenerateCRC( stream_name ) );\r\n\t\t\tScript::RunScript( \"skater_play_bail_stream\", pTemp, pScript->mpObject );\r\n\t\t\tdelete pTemp;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tScript::CleanUpArray( p_stream_indices );\r\n\tdelete p_stream_indices;\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetTextureFromPath | returns the file name for a texture\r\n// from the end of the give path\r\n// @parm string | path | path of file including file name\r\nbool ScriptGetTextureFromPath( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tconst char* p_path;\r\n    char new_string[32];\r\n    int i, t=0;\r\n\r\n\tpParams->GetString( CRCD(0xf4ab74f0,\"path\"), &p_path, Script::ASSERT );\r\n\r\n    int length = strlen( p_path );\r\n\r\n    // find last '/' in path\r\n    for (i=(length); i>=0; i--)\t \t// Mick: was previously \"length+1\", which would start at the character AFTER the string\r\n    {\t\t\t\t\t\t\t\t// which on rare occasions was a '/' char, which caused obscure crashes.\r\n        if ( ( p_path[i] == '/' ) || ( p_path[i] == '\\\\' ) )\r\n        {\r\n            break;\r\n        }\r\n    }\r\n\r\n    // copy everything after '/' into texture\r\n    for (int p=(i+1); p<=length; p++)\r\n    {\r\n        new_string[t] = p_path[p];\r\n        t++;\r\n    }\r\n\t\r\n\r\n\tpScript->GetParams()->AddString( CRCD(0x7d99f28d,\"texture\"), new_string );\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | GetVramUsage | \r\nbool ScriptGetVramUsage( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n#\tifdef __PLAT_NGPS__\r\n\t//printf(\"FontVramStart = %uK \\n\", (NxPs2::FontVramStart/4) );\r\n    //printf(\"FontVramBase = %uK \\n\", (NxPs2::FontVramBase/4) );\r\n    printf(\"FontVramSize = %uK \\n\", (NxPs2::FontVramSize/4) );\r\n    printf(\"Font Usage = %uK \\n\", ( (NxPs2::FontVramBase - NxPs2::FontVramStart )/4) );\r\n#\tendif\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// @script | CompositeObjectExists | \r\nbool ScriptCompositeObjectExists ( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 name;\r\n\tpParams->GetChecksum( CRCD(0xa1dc81f9,\"name\"), &name, Script::ASSERT );\r\n\tObj::CObject* pObj = Obj::ResolveToObject( name );\r\n\treturn ( pObj != NULL );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptClearPowerups( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tint i;\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\r\n\tfor( i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )\r\n\t{\r\n\t\tObj::CSkater* pSkater = pSkate->GetSkater( i );\r\n\t\tif( pSkater )\r\n\t\t{\r\n\t\t\tObj::CSkaterStateComponent *p_component = (Obj::CSkaterStateComponent*)Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType( CRC_SKATERSTATE );\r\n\t\t\tp_component->ClearPowerups();\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptBroadcastProjectile( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 type;\r\n\tMth::Vector pos, vel;\r\n\tint radius;\r\n\tfloat scale;\r\n\tuint32 id;\r\n\tGameNet::Manager * gamenet_man = GameNet::Manager::Instance();\r\n\tNet::Client* client;\r\n\t\r\n\tpParams->GetChecksum( CRCD(0x830ecaf,\"objID\"), &id );\r\n\tpParams->GetChecksum( CRCD(0x7321a8d6,\"type\"), &type );\r\n\tpParams->GetVector( CRCD(0x7f261953,\"pos\"), &pos );\r\n\tpParams->GetVector( CRCD(0xc4c809e,\"vel\"), &vel );\r\n\tpParams->GetFloat( CRCD(0x13b9da7b,\"scale\"), &scale );\r\n\tpParams->GetInteger( CRCD(0xc48391a5,\"radius\"), &radius );\r\n\r\n\tclient = gamenet_man->GetClient( 0 );\r\n\tif( client )\r\n\t{\r\n\t\tNet::MsgDesc msg_desc;\r\n\t\tGameNet::MsgProjectile msg;\r\n\t\t\r\n\t\tmsg.m_Id = id;\r\n\t\tmsg.m_Pos = pos;\r\n\t\tmsg.m_Vel = vel;\r\n\t\tmsg.m_Radius = radius;\r\n\t\tmsg.m_Scale = scale;\r\n\t\tmsg.m_Latency = 0;\r\n\t\tmsg.m_Type = type;\r\n\r\n\t\tmsg_desc.m_Id = GameNet::MSG_ID_SPAWN_PROJECTILE;\r\n\t\tmsg_desc.m_Data = &msg;\r\n\t\tmsg_desc.m_Length = sizeof( GameNet::MsgProjectile );\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\r\n\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptBroadcastEnterVehicle ( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tuint32 id;\r\n\tuint32 control_type;\r\n\tGameNet::Manager* gamenet_man = GameNet::Manager::Instance();\r\n\tNet::Client* client;\r\n\t\r\n\tpParams->GetChecksum( CRCD(0x5b24faaa, \"SkaterId\"), &id, Script::ASSERT );\r\n\tpParams->GetChecksum( CRCD(0x81cff663, \"control_type\"), &control_type, Script::ASSERT );\r\n\t\r\n\tclient = gamenet_man->GetClient( 0 );\r\n\tif( client )\r\n\t{\r\n\t\tNet::MsgDesc msg_desc;\r\n\t\tGameNet::MsgEnterVehicle msg;\r\n\t\t\r\n\t\tmsg.m_Id = id;\r\n\t\tmsg.m_ControlType = control_type;\r\n\r\n\t\tmsg_desc.m_Id = GameNet::MSG_ID_ENTER_VEHICLE;\r\n\t\tmsg_desc.m_Data = &msg;\r\n\t\tmsg_desc.m_Length = sizeof( GameNet::MsgEnterVehicle );\r\n\t\tmsg_desc.m_Queue = Net::QUEUE_SEQUENCED;\r\n\t\tmsg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;\r\n\t\r\n\t\tclient->EnqueueMessageToServer( &msg_desc );\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool ScriptGetCollidingPlayerAndTeam( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tint team = -1;\r\n\tint player_id = -1;\r\n    Script::CStruct* p_pass_back_params = pScript->GetParams();\r\n\tfloat nearest_distance = 999999.9999f;\r\n\tObj::CCompositeObject* flag_obj;\r\n\r\n\tflag_obj = static_cast <Obj::CCompositeObject*>( pScript->mpObject.Convert() );\r\n\tDbg_Assert( flag_obj );\r\n\t\r\n\tint exclude_team;\r\n\tpParams->GetInteger(CRCD(0x6c2a140f, \"exclude_team\"), &exclude_team, Script::ASSERT);\r\n\t\r\n\tfloat radius_squared;\r\n\tpParams->GetFloat(CRCD(0xc48391a5, \"radius\"), &radius_squared, Script::ASSERT);\r\n\tradius_squared = FEET_TO_INCHES(radius_squared) * FEET_TO_INCHES(radius_squared);\r\n\t\r\n\tGameNet::PlayerInfo* player;\r\n\tfor (uint32 i = 0; i < Mdl::Skate::Instance()->GetNumSkaters(); i++)\r\n\t{\r\n\t\tObj::CCompositeObject* p_skater = Mdl::Skate::Instance()->GetSkater(i);\r\n\t\t\r\n\t\tif( p_skater )\r\n\t\t{\r\n\t\t\tplayer = GameNet::Manager::Instance()->GetPlayerByObjectID(p_skater->GetID());\r\n\t\t\tif (!player) continue;\r\n\r\n\t\t\t// If a player on the flag's team collides with the flag and doesn't have an enemy flag, just ignore it\r\n\t\t\tif ((player->m_Team == exclude_team) && !player->HasCTFFlag()) continue;\r\n\r\n\t\t\t// If a player already has a flag, just ignore it. They're being greedy.\r\n\t\t\tif ((player->m_Team != exclude_team ) && player->HasCTFFlag()) continue;\r\n\t\t\t\r\n\t\t\tfloat this_dist = Mth::DistanceSqr( p_skater->m_pos, flag_obj->GetPos());\r\n\t\t\t\r\n\t\t\tif (this_dist < radius_squared && this_dist < nearest_distance)\r\n\t\t\t{\r\n\t\t\t\tnearest_distance = this_dist;\r\n\t\t\t\tplayer_id = p_skater->GetID();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (player_id > -1)\r\n\t{\r\n\t\tplayer = GameNet::Manager::Instance()->GetPlayerByObjectID(player_id);\r\n\t\tteam = player->m_Team;\r\n\t}\r\n\r\n\tp_pass_back_params->AddInteger(CRCD(0x3b1f59e0, \"team\"), team);\r\n\tp_pass_back_params->AddInteger(CRCD(0x67e6859a, \"player\"), player_id);\r\n\treturn true;\r\n}\r\n\r\nbool ScriptLobbyCheckKeyboard( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tint num_chars;\r\n\tchar makes[256];\r\n    \r\n\tnum_chars = SIO::KeyboardRead( makes );\r\n\r\n    if( num_chars > 0 )\r\n\t{\r\n\t\t// Space brings up the chat interface\r\n\t\tif( makes[0] == 32 )\r\n\t\t{\r\n\t\t\tScript::CStruct* pParams;\r\n\t\t\t\r\n\t\t\t// Enter and space act as \"choose\" only if you're not currently using the on-screen keyboard\r\n            pParams = new Script::CStruct;\r\n\t\t\tpParams->AddChecksum( Script::GenerateCRC( \"id\" ), Script::GenerateCRC( \"keyboard_anchor\" ));\r\n            if( Obj::ScriptObjectExists( pParams, NULL ) == false )\r\n\t\t\t{\r\n                Script::RunScript( \"lobby_enter_kb_chat\" );\r\n                SIO::KeyboardClear();\r\n\t\t\t}\r\n            delete pParams;\r\n\t\t}\r\n    }\r\n    return true;\r\n}\r\n \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\nbool ScriptMarkRestarts ( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\t// Green:\tPlayer1\r\n\t// Purple:\tMultiplayer\r\n\t// Cyan:\tHorse\r\n\t// Red:\t\tCTF\r\n\t// Blue:\tTeam\r\n\t// Yellow:\tCrown\r\n\t\r\n\tScript::CArray *pNodeArray = Script::GetArray(CRCD(0xc472ecc5, \"NodeArray\"));\r\n\tfor (int i = pNodeArray->GetSize(); i--; )\r\n\t{\r\n\t\tuint32 color = 0;\r\n\t\tMth::Vector offset;\r\n\t\t\r\n\t\tuint32 node_class;\r\n\t\tpNodeArray->GetStructure(i)->GetChecksum(CRCD(0x12b4e660, \"Class\"), &node_class);\r\n\t\tif (node_class == CRCD(0x1806ddf8, \"Restart\"))\r\n\t\t{\r\n\t\t\tScript::CArray *pRestartTypes;\r\n\t\t\tpNodeArray->GetStructure(i)->GetArray(CRCD(0xdd304987, \"restart_types\"), &pRestartTypes);\r\n\t\t\tfor (int j = pRestartTypes->GetSize(); j--; )\r\n\t\t\t{\r\n\t\t\t\tswitch (pRestartTypes->GetChecksum(j))\r\n\t\t\t\t{\r\n\t\t\t\t\tcase CRCC(0x41639ce5, \"Player1\"):\r\n\t\t\t\t\t\tcolor = MAKE_RGB(0, 255, 0);\r\n\t\t\t\t\t\toffset.Set(0.0f, 0.0f, 0.0f);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase CRCC(0xbae0e4da, \"Multiplayer\"):\r\n\t\t\t\t\t\tcolor = MAKE_RGB(255, 0, 255);\r\n\t\t\t\t\t\toffset.Set(1.0f, 0.0f, 0.0f);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase CRCC(0x9d65d0e7, \"Horse\"):\r\n\t\t\t\t\t\tcolor = MAKE_RGB(0, 255, 255);\r\n\t\t\t\t\t\toffset.Set(0.0f, 1.0f, 0.0f);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase CRCC(0xa5ad2b0b, \"CTF\"):\r\n\t\t\t\t\t\tcolor = MAKE_RGB(255, 0, 0);\r\n\t\t\t\t\t\toffset.Set(0.0f, 0.0f, 1.0f);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase CRCC(0x3b1f59e0, \"Team\"):\r\n\t\t\t\t\t\tcolor = MAKE_RGB(0, 0, 255);\r\n\t\t\t\t\t\toffset.Set(1.0f, 1.0f, 0.0f);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if (node_class == CRCD(0xf8565321, \"GenericNode\"))\r\n\t\t{\r\n\t\t\tuint32 type;\r\n\t\t\tpNodeArray->GetStructure(i)->GetChecksum(CRCD(0x7321a8d6, \"Type\"), &type);\r\n\t\t\tif (type != CRCD(0xaf86421b, \"Crown\")) continue;\r\n\t\t\t\r\n\t\t\tcolor = MAKE_RGB(255, 255, 0);\r\n\t\t\toffset.Set(0.0f, 1.0f, 1.0f);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tMth::Vector pos;\r\n\t\tSkateScript::GetPosition(i, &pos);\r\n\t\t\r\n\t\tGfx::AddDebugLine(pos, pos + 12.0f * offset + Mth::Vector(0.0f, 140.0f, 0.0f), color, 0, 0);\r\n\t}\r\n\t\r\n\treturn true;\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace CFuncs\r\n"
  },
  {
    "path": "Code/Sk/Scripting/skfuncs.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tPS2\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tScripting\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcfuncs.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t09/14/2000\t-\tksh\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SCRIPTING_SKFUNCS_H\r\n#define\t__SCRIPTING_SKFUNCS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n};\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace CFuncs\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool ScriptCurrentSkaterIsPro(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetGoalsCompleted(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetNextLevelRequirements(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetCurrentSkaterProfile(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCurrentSkaterProfileIs(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAddSkaterProfile(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAddTemporaryProfile(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRememberTemporaryAppearance(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRestoreTemporaryAppearance(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSyncPlayer2Profile(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPreloadModels( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPreloadPedestrians( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPreselectRandomPedestrians( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptReplaceCarTextures( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetSkaterProfileInfo(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetSkaterProfileInfo(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetUIFromPreferences(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetUIFromSkaterProfile(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetPreferencesFromUI(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptResetDefaultAppearance(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptResetDefaultTricks(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptResetDefaultStats(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRandomizeAppearance(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPrintCurrentAppearance(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetNeversoftSkater(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCurrentProfileIsLocked(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptResetSkaters(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetSkaterProfileProperty(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptToggleAlwaysSpecial( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSkaterSpeedGreaterThan( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSkaterSpeedLessThan( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptLastScoreLandedGreaterThan( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptLastScoreLandedLessThan( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptAnyTotalScoreAtLeast( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptOnlyOneSkaterLeft( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptTotalScoreGreaterThan( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptTotalScoreLessThan( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptCurrentScorePotGreaterThan( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptCurrentScorePotLessThan( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSkaterGetScoreInfo( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptGoalsGreaterThan( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptGoalsEqualTo( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptMedalsGreaterThan( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptMedalsEqualTo( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptToggleStats(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptToggleSkaterCamMode(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetSkaterID( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetCurrentSkaterID( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptResetScore( Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUpdateScore( Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptPlaySkaterCamAnim( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetSkaterCamAnimSkippable( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetSkaterCamAnimShouldPause( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSkaterCamAnimFinished( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSkaterCamAnimHeld( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptKillSkaterCamAnim( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptGetSkaterCamAnimParams( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptGetCurrentSkaterCamAnimName( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptPlayMovingObjectAnim( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPlayCutscene( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptHasMovieStarted( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptIsMovieQueued( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetMovingObjectAnimSkippable( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetMovingObjectAnimShouldPause( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptMovingObjectAnimFinished( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptMovingObjectAnimHeld( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptKillMovingObjectAnim( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptSetSkaterCamLerpReductionTimer( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptReloadSkaterCamAnim( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSkaterDebugOn(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSkaterDebugOff(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptVibrationIsOn(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptVibrationOn(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptVibrationOff(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAutoKickIsOn(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAutoKickOn(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAutoKickOff(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSpinTapsAreOn(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSpinTapsOn(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSpinTapsOff(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetCurrentProDisplayInfo(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetPlayerAppearance(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetPlayerFacePoints(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetPlayerFacePoints(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetPlayerFaceTexture(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetPlayerFaceOverlayTexture(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptClearPlayerFaceTexture(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPlayerFaceIsValid(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSelectCurrentSkater(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCareerStartLevel(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCareerLevelIs(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetRecordText(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUpdateRecords(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCareerReset(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUnSetGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptJustGotGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetFlag(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUnSetFlag(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetFlag(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptJustGotFlag(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetGlobalFlag(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUnSetGlobalFlag(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetGlobalFlag(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptProfileEquals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptIsCareerMode(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptClearScoreGoals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSetScoreGoal(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptEndRun(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptShouldEndRun(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptInitializeSkaters(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptEndRunSelected(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAllSkatersAreIdle(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptFirstTrickStarted( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptFirstTrickCompleted( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptCalculateFinalScores(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptReinsertSkaters(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUnhookSkaters(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptApplySplitScreenOptions(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptStartCompetition(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptStartCompetitionRun(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptEndCompetitionRun(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptIsTopJudge(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptPlaceIs(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRoundIs(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptEndCompetition(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptCompetitionEnded(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptStartHorse(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptEndHorse(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptHorseEnded(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptHorseStatusEquals(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptStartHorseRun(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptEndHorseRun(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSwitchHorsePlayers(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetHorseString(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptIsCurrentHorseSkater(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptApplyToHorsePanelString(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptApplyToSkaterProfile(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptApplyColorToSkaterProfile(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRefreshSkaterColors(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRefreshSkaterScale(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRefreshSkaterVisibility(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRefreshSkaterUV(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAwardStatPoint(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAwardSpecialTrickSlot(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUpdateSkaterStats(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUpdateInitials( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptNewRecord(  Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptTrickOffAllObjects( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptGameModeSetScoreDegradation( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGameModeSetScoreAccumulation( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptResetScoreDegradation( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSkaterIsBraking( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptLocalSkaterExists( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptInitSkaterModel(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRefreshSkaterModel(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptEditPlayerAppearance(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetCurrentSkaterProfileIndex(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptGetCustomSkaterName(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptResetScorePot( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptPrintSkaterStats( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptPrintSkaterStats2( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptPrintSkaterPosition( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetSkaterPosition( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetSkaterVelocity( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetStatValue( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetNumStatPointsAvailable( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptUnlockSkater( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetActualCASOptionStruct( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetActualPlayerAppearancePart( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetPlayerAppearancePart( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetPlayerAppearanceColor( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetPlayerAppearanceScale( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptSetPlayerAppearanceUV( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptFlushDeadObjects( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptBindTrickToKeyCombo( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetKeyComboBoundToTrick( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptUpdateTrickMappings( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetConfigurableTricksFromType( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptTrickIsLocked( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetTrickDisplayText( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetSpecialTrickInfo( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptGetTrickType( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptGetIndexOfItemContaining( Script::CStruct* pParams, Script::CScript* pScript );\r\nbool ScriptForEachSkaterName( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptForEachSkaterProfile( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptResetAllToDefaultStats( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptResetAllToDefaultProfile( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptResetToDefaultProfile( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptGetLevelRecords( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptResetComboRecords( Script::CStruct* pParams, Script::CScript* pScript );\r\n\r\nbool ScriptGetSkaterProfileInfoByName( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSetSkaterProfileInfoByName( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptGetNumberOfTrickOccurrences( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptGetNumSoundtracks( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptGetSoundtrackName( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptControllerBoundToDifferentSkater( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptBindControllerToSkater( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptBindFrontEndToController( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptControllerBoundToSkater( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptGetKeyComboArrayFromTrickArray( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptFirstInputReceived( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptVibrateController( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptLockCurrentSkaterProfileIndex( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptSetSpecialTrickInfo( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptInterpolateParameters( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptPlaySkaterStream ( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptGetTextureFromPath ( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptGetVramUsage ( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptCompositeObjectExists ( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptClearPowerups( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptBroadcastProjectile( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptBroadcastEnterVehicle ( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptGetCollidingPlayerAndTeam( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptLobbyCheckKeyboard( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace CFuncs\r\n\r\n#endif\t// __SCRIPTING_SKFUNCS_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/heap_sizes.h",
    "content": "#ifndef __SK_HEAP_SIZES_H\r\n#define __SK_HEAP_SIZES_H\r\n\r\n// Sizes of heaps\r\n\r\n#define\tEXTRA 1000000\r\n\r\n\r\n#ifdef __PLAT_WN32__\r\n\r\n#define\t_SCRIPT_HEAP_SIZE\t\t\t\t(1024)\r\n#define\tSCRIPT_CACHE_HEAP_SIZE\t\t\t(1024)\r\n#define\tFRONTEND_HEAP_SIZE\t\t\t\t(1024)\r\n#define\tNETWORK_HEAP_qSIZE\t\t\t\t(1024)\r\n#define PROFILER_HEAP_SIZE\t\t\t\t\t(1024)\r\n#define\tSKATERINFO_HEAP_SIZE\t\t\t(1024)\r\n#define\tSKATER_HEAP_SIZE\t\t\t\t(1024)\t\t// default size of skater heap\r\n#define SKATER_GEOM_HEAP_SIZE\t\t\t(1024)\r\n#define BOOTSTRAP_FRONTEND_HEAP_SIZE\t(1024)\r\n#define INTERNET_HEAP_SIZE\t\t\t\t(1024)\r\n#define NETMISC_HEAP_SIZE\t\t\t\t(1024)\r\n#define\tTHEME_HEAP_SIZE     \t\t\t (1024)\t\t// theme textures heap size\r\n\r\n#else\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n// K: On debug builds line number info is included in the qb's so add in another 500K for it.\r\n// On release builds the line number info is excluded by passing the nolinenumbers switch to\r\n// cleanass when it is called from easyburn.bat\r\n#define\t_SCRIPT_HEAP_SIZE\t\t\t\t\t(3824000+500000+130000)\r\n#else\r\n#define\t_SCRIPT_HEAP_SIZE\t\t\t\t\t(3824000+130000)\t   \r\n#endif\r\n\r\n// Mick: Note the FRONTEND_HEAP_SIZE encompasses both Frontend and Net heaps.\r\n// as they share the same region, with Net being top down.\r\n#define\tFRONTEND_HEAP_SIZE\t\t\t\t\t(1100000)  \t \t// was 800000\r\n\r\n#define NETMISC_HEAP_SIZE\t\t\t\t\t(160000)\r\n#define\tBOOTSTRAP_FRONTEND_HEAP_SIZE\t\t(FRONTEND_HEAP_SIZE-100000)\t\t// we have no network play in bootstrap mode  \r\n#define INTERNET_HEAP_SIZE\t\t\t\t\t(450000)\r\n#define PROFILER_HEAP_SIZE\t\t\t\t\t(60000)\r\n\r\n// GJ:  I temporarily increased the size\r\n// of the skater info heap until we can figure\r\n// out how the face texture pathway is going to\r\n// work (right now, I need a heap that wouldn't\r\n// get destroyed when changing levels, to store\r\n// 17K worth of temporary face texture data)\r\n//#define\tSKATERINFO_HEAP_SIZE\t\t\t \t(40000)\r\n// Mick: Increased it again for 2P\r\n#define\tSKATERINFO_HEAP_SIZE\t\t\t \t(60000+2000+20000)\t// extra 2000 for skater cams +20K for 2p fragmentation concerns\r\n\r\n#define\tSKATER_HEAP_SIZE\t\t\t\t \t(120000-40000+1000-2000)\t// default size of skater heap, minus 2000 since skater cams moved to skater info heap\r\n#define\tSKATER_GEOM_HEAP_SIZE\t\t\t \t(680000 - 16000)\t\t// default size of skater heap, plus a little extra cause we were running out for E3\r\n#define\tTHEME_HEAP_SIZE     \t\t\t \t(204800)\t\t// theme textures heap size\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#ifdef\t__NOPT_ASSERT__\r\n// On a regular development build, the memory usage is very different\r\n// to a \"final=\" build.  Firstly there is the extra debug code, mostly assertions,\r\n// but also memory blocks have a 32 byte rather than 16 byte header\r\n// and many data structures have extra fields for debugging purposes\r\n// this all means that the game will not fit in 32MB, so to fix this, the\r\n// script heap is placed in \"debug\" memory (>32MB)\r\n// Just that alone would result in there seeming to be MORE memory avaialbe in the normal build\r\n// so to conteeract that, we allocate a block off the bottom_up heap,\r\n// The size of this block is SCRIPT_HEAP_SIZE-DEBUG_ADJUSTMENT\r\n// So you need to adjust DEBUG_ADJUSTMENT so the amount of free memory\r\n// on the main heap is the same in a development build\r\n// and in a \"final=\" cd build, for example, if you had for CD final build:\r\n// \r\n// Name            Used  Frag  Free   Min  Blocks                                  \r\n// --------------- ----- ----- ---- ------ ------                                  \r\n//     Top Down:  3942K    0K  894K  884K   3933 \r\n//     BottomUp: 23275K   23K  894K  884K  10432  \r\n//\r\n// and on a regular build:\r\n//\r\n//     Top Down:  4004K    0K  579K  523K   3933   \r\n//     BottomUp: 22115K   23K  579K  523K  10601\r\n//\r\n// Then you see that the regular build is underreporting the actual amount of free memory\r\n// and you should in theory add (894-579) = 315K\r\n// In practice it's a good idea to not push things right to the wire, as memory\r\n// usage can vary in differing situation (specifically when the number of blocks vary,\r\n// like a large number of small allocations vs a small number of large allocations.)\r\n// Since the above was from a worst case situation (NJ), I feel that 200K would be appropiate\r\n\t\r\n#define\tDEBUG_ADJUSTMENT\t\t\t\t\t(1126400 + 200000 + 300000 + 100000 + 350000 ) // (1126400)\t\t// difference in free memory for \"final=\" vs debug build\r\n#endif // __NOPT_ASSERT__\r\n#endif // __PLAT_NGPS__\r\n\r\n#endif // __PLAT_WN32__\r\n\r\n#ifdef __PLAT_XBOX__\r\n// Just need to override some of these values - want to keep as much the same as possible tho.\r\n#undef\tSKATER_HEAP_SIZE\r\n#define\tSKATER_HEAP_SIZE\t\t\t\t( 120000 - 40000 - 2000)\r\n\r\n#undef\tSKATER_GEOM_HEAP_SIZE\r\n#define\tSKATER_GEOM_HEAP_SIZE\t\t\t( 480000 )\r\n\r\n#undef\tTHEME_HEAP_SIZE\r\n#define\tTHEME_HEAP_SIZE\t\t\t\t\t( 307200 )\r\n\r\n#undef\tFRONTEND_HEAP_SIZE\r\n#define\tFRONTEND_HEAP_SIZE\t\t\t\t( 1050000 )\r\n\r\n\r\n#endif // __PLAT_XBOX__\r\n\r\n#ifdef __PLAT_NGC__\r\n// Just need to override some of these values - want to keep as much the same as possible tho.\r\n#undef\tSKATER_HEAP_SIZE\r\n#define\tSKATER_HEAP_SIZE\t\t\t\t( ( 120000 - 40000 - 2000) + 1000 )\r\n#undef\tPROFILER_HEAP_SIZE\r\n#define PROFILER_HEAP_SIZE\t\t\t\t\t  (40000)\r\n#undef\tFRONTEND_HEAP_SIZE\r\n#define\tFRONTEND_HEAP_SIZE\t\t\t\t( 650000 )\r\n#undef\tSKATER_GEOM_HEAP_SIZE\r\n#define\tSKATER_GEOM_HEAP_SIZE\t\t\t (470000)\t\t// default size of skater heap\r\n#undef\tTHEME_HEAP_SIZE\r\n#define\tTHEME_HEAP_SIZE     \t\t\t \t(330000)\t\t// theme textures heap size\r\n#define\tSCRIPT_HEAP_SIZE (_SCRIPT_HEAP_SIZE-(300000+(1024*1024)))\r\n\r\n#undef\tSKATERINFO_HEAP_SIZE\r\n#define\tSKATERINFO_HEAP_SIZE\t\t\t \t(60000+2000+20000+18000)\t// extra 2000 for skater cams +20K for 2p fragmentation concerns\r\n\r\n#define\tAUDIO_HEAP_SIZE\t\t\t \t\t\t(310*1024)\r\n#else\r\n// All platforms except for NGC\r\n#define\tSCRIPT_HEAP_SIZE _SCRIPT_HEAP_SIZE\r\n#endif // __PLAT_NGC__\r\n\r\n\r\n#endif // __SK_HEAP_SIZES_H\r\n\r\n"
  },
  {
    "path": "Code/Sk/language.h",
    "content": "#ifndef\t__SK_LANGUAGE_H\r\n#define\t__SK_LANGUAGE_H\r\n\r\n#ifdef __PLAT_XBOX__\r\n#include <xtl.h>\r\n#endif // __PLAT_XBOX__\r\n\r\n// These only apply if PAL\r\n#define ENGLISH 1\r\n#define FRENCH 0\r\n#define GERMAN 0\r\n\r\ninline bool IsEnglish( void )\r\n{\r\n#\tifdef __PLAT_XBOX__\r\n\tDWORD lang = XGetLanguage();\r\n\tif( lang == XC_LANGUAGE_ENGLISH )\r\n\t\treturn true;\r\n\telse\r\n\t{\r\n\t\t// For NTSC, the only language allowed is English.\r\n\t\tif( XGetVideoStandard() != XC_VIDEO_STANDARD_PAL_I )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Any languages other than French and German should also be considered English.\r\n\t\tif(( lang != XC_LANGUAGE_GERMAN ) && ( lang != XC_LANGUAGE_FRENCH ))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n//\t\treturn true;\t\t// For now...\r\n#\telse\r\n#\tif ENGLISH\r\n\treturn true;\r\n#\telse\r\n\treturn false\r\n#\tendif // ENGLISH\r\n#\tendif // __PLAT_XBOX__\r\n}\r\n\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Sk/ngc/crt0.s",
    "content": "##\r\n## SN Systems C/C++ Startup Module\r\n##\r\n#\t.include \"defs.s\"\t\t\t# equates\r\n#\r\n#\t.section .data\r\n#wdbmsg:\r\n#\t.string\t\"Waiting for SN Debugger...\\n\"\r\n#\t.byte\t0\r\n#\t.align\t4\r\n#\r\n#\t.section .init\r\n#\t.global\t__start\t\t\t\t# the only thing we need to export\r\n#\t\r\n#__start:\r\n#    lis     %r1, _stack_addr@h        \t# set r1, r2, r13 as required by PPC EABI\r\n#    ori     %r1, %r1, _stack_addr@l\r\n#\r\n#    lis     %r2, _SDA2_BASE_@h\t\t\t# __SDA2_BASE_ is generated by linker */\r\n#    ori     %r2, %r2, _SDA2_BASE_@l\r\n#\r\n#    lis     %r13, _SDA_BASE_@h\t\t\t# _SDA_BASE_ is generated by linker\r\n#    ori     %r13, %r13, _SDA_BASE_@l\r\n#\r\n#    bl      __init_hardware\t\t\t\t# why do we have to call this?\r\n#\r\n#    li      %r0, -1               \t\t# leave stack space for main params and lr stash\r\n#    stwu    %r1, -8(%r1)               \r\n#    stw     0, 4(%r1)                \r\n#    stw     0, 0(%r1)\r\n#\r\n## Init the BSS sections to 0\r\n#\r\n#\tlis\t\t%r3,_f_bss@ha\r\n#\taddi\t%r3,%r3,_f_bss@l\r\n#\tli\t\t%r4,0\r\n#\tlis\t\t%r5,_e_bss@ha\r\n#\taddi\t%r5,%r5,_e_bss@l\r\n#\tsubf\t%r5,%r3,%r5\r\n#\tbl\t\tmemset\r\n#\r\n#\tlis\t\t%r3,_f_sbss@ha\r\n#\taddi\t%r3,%r3,_f_sbss@l\r\n#\tli\t\t%r4, 0\r\n#\tlis\t\t%r5,_e_sbss@ha\r\n#\taddi\t%r5,%r5,_e_sbss@l\r\n#\tsubf\t%r5,%r3,%r5\r\n#\tbl\t\tmemset\r\n#\r\n#\tli\t\t%r4,0\r\n#\tlis\t\t%r5,0x8000\t\t\t# use cached address space\r\n#\tstw\t\t%r4,0x44(%r5)\t\t# write it to the DBException structure in low mem\r\n#\r\n## OK, now check to see if debugging is enabled\r\n#\tli\t\t%r29,0\t\t\t\t# r29 == 0  =>  debugging not enabled\r\n#\tlis\t\t%r6,BOOTINFO2_ADDR@ha\r\n#\taddi\t%r6,%r6,BOOTINFO2_ADDR@l\r\n#\tlwz\t\t%r6,0(%r6)\t\t\t# get r6 = ptr to BOOTINFO2\r\n#\tcmpi\t%cr0,%r6,0\r\n#\tbeq\t\t_skipdbg\t\t\t# skip if BOOTINFO2 does not exist\r\n#\r\n#\tlwz\t\t%r3,OS_BI2_DEBUGFLAG_OFFSET(%r6)\t# this will be 2 if we are debugging\r\n#\tcmpli\t%cr0,%r3,2\r\n#\tblt\t\t_skipdbg\t\t\t# 2=>DDH, 3=>GDEV\r\n#\r\n#\tbl\t\tSNDebugInit\t\t\t# can we reach it with a bl? May need an \"li32 + blrl\"\r\n#\tli\t\t%r29,1\r\n#\r\n#_skipdbg:\r\n#\tbl\t\t_ParseCmdLine\t\t# must do it here (before OSInit) because it may adjust ARENAHI\r\n#\tmr\t\t%r30,%r3\r\n#\tmr\t\t%r31,%r4\r\n#\r\n#\tbl      DBInit\r\n#\tbl      OSInit\t\t\t\t# this will make the callback to EnableMetroTRKInterrupts\r\n#\r\n##    bl      __init_user\t\t\t# C++ constructors. No, now handled in call to _main() from main()\r\n#\r\n#\tcmpi\t%cr0,%r29,0\r\n#\tbeq\t\t_sktr\r\n#\r\n#\tlis\t\t%r3,wdbmsg@h\r\n#\tori\t\t%r3,%r3,wdbmsg@l\r\n#\tbl\t\tOSReport\r\n#\r\n#\tmfmsr\t%r5\r\n#\tlis\t\t%r4,(~MSR_EE)@h\t\t# li32 r4,MSR_EE (=0xFFFF7FFF)\r\n#\tori\t\t%r4,%r4,(~MSR_EE)@l\r\n#\tand\t\t%r4,%r5,%r4\t\t\t# disable external ints (so SRR stays safe)\r\n#\tmtmsr\t%r4\r\n#\tsync\t\t\t\t\t\t# make sure ints are off before next bit of code\r\n#\tori\t\t%r5,%r5,MSR_BE\t\t# and set BRANCH TRACE bit (will go of after bl main)\r\n#\tmtspr\tspr_srr1,%r5\r\n#\r\n#\tlis\t\t%r4,_sktr@h\r\n#\tori\t\t%r4,%r4,_sktr@l\t\t# li32\t%r4,_sktr\r\n#\tmtspr\tspr_srr0,%r4\r\n#\trfi\r\n#\r\n#_sktr:\r\n#\tbl      pre_main\r\n#\r\n### Fill stack with 55.\r\n##\r\n##\tlis\t\t%r4,_stack_end@ha\r\n##\taddi\t%r4,%r4,_stack_end@l\r\n##\tli\t\t%r5,0x55\r\n##\tlis\t\t%r6,_stack_addr@ha\r\n##\taddi\t%r6,%r6,_stack_addr@l\r\n##\tsubf\t%r6,%r4,%r6\r\n##\tli\t\t%r6,0x80\r\n##\tsubf\t%r6,%r6,%r4\r\n##\tbl\t\tmemset\r\n#\r\n#\r\n#\r\n#\r\n#\tmr\t\t%r3,%r30\t\t\t# restore argc\r\n#\tmr\t\t%r4,%r31\t\t\t# and argv\r\n#\tbl      main\t\t\t\t# so we can call main()\r\n#    bl      post_main\r\n#    b       exit\r\n#\r\n#\r\n## process command line\r\n#_ParseCmdLine:\r\n#\tlis\t\t%r6,BOOTINFO2_ADDR@ha\r\n#\taddi\t%r6,%r6,BOOTINFO2_ADDR@l\r\n#\tlwz\t\t%r5,0(%r6)\t\t\t# get r6 = ptr to BOOTINFO2\r\n#\tcmpi\t%cr0,%r5,0\r\n#\tbne\t\t_gargs\r\n#\r\n#_noargs:\r\n#    li      %r3,0\r\n#    li      %r4,0\r\n#\tblr\r\n#\r\n#_gargs:\r\n#\tlwz\t\t%r6,OS_BI2_ARGOFFSET_OFFSET(%r5)\t#argument offset\r\n#\tcmpi\t%cr0,%r6,0\r\n#\tbeq\t\t_noargs\t\t\t\t# no arguments\r\n#\tadd\t\t%r6,%r5,%r6\t\t\t# argument start\r\n#\r\n#\tlwz\t\t%r3,0(%r6)\t\t\t# get argc\r\n#\tcmpi\t%cr0,%r3,0\r\n#\tbeq\t\t_noargs\t\t\t\t# shouldn't happen\r\n#\r\n#\taddi\t%r4,%r6,4\t\t\t# argv\r\n#\tmtctr\t%r3\r\n#_lp:\r\n#\taddi\t%r6,%r6,4\r\n#\tlwz\t\t%r7,0(%r6)\r\n#\tadd\t\t%r7,%r7,%r5\r\n#\tstw\t\t%r7,0(%r6)\r\n#\tbdnz\t_lp\r\n#\r\n## set ARENAHI to be *below* the arguments\r\n#\tlis\t\t%r5,ARENAHI_ADDR@ha\r\n#\taddi\t%r5,%r5,ARENAHI_ADDR@l\r\n#\tclrrwi\t%r7,%r4,5\t\t\t# align it by 32bytes\r\n#\tstw\t\t%r7,0(%r5)\r\n#\r\n#\tblr\r\n#\r\n## Bill's hack Yuk Yuk\r\n#\r\n#\t.section .data\r\n#\t.extern read\r\n#\t.extern pre_main\r\n#\t.extern main\r\n#\t.extern __mod2i\r\n#LinkFiddle:\r\n#\t.long read\r\n#\t.long __mod2i\r\n\r\n"
  },
  {
    "path": "Code/Sk/ngc/defs.s",
    "content": "# register numbers for mfspr/mtspr\r\n\r\n\t.equ\tspr_xer,1\r\n\t.equ\tspr_lr,8\r\n\t.equ\tspr_ctr,9\r\n\r\n\t.equ\tspr_upmc1,937\r\n\t.equ\tspr_upmc2,938\r\n\t.equ\tspr_upmc3,941\r\n\t.equ\tspr_upmc4,942\r\n\r\n\t.equ\tspr_usia,939\r\n\r\n\t.equ\tspr_ummcr0,936\r\n\t.equ\tspr_ummcr1,940\r\n\r\n\t.equ\tspr_hid0,1008\r\n\t.equ\tspr_hid1,1009\r\n\r\n\t.equ\tspr_pvr,287\r\n\r\n\t.equ\tspr_ibat0u,528\r\n\t.equ\tspr_ibat0l,529\r\n\t.equ\tspr_ibat1u,530\r\n\t.equ\tspr_ibat1l,531\r\n\t.equ\tspr_ibat2u,532\r\n\t.equ\tspr_ibat2l,533\r\n\t.equ\tspr_ibat3u,534\r\n\t.equ\tspr_ibat3l,535\r\n\r\n\t.equ\tspr_dbat0u,536\r\n\t.equ\tspr_dbat0l,537\r\n\t.equ\tspr_dbat1u,538\r\n\t.equ\tspr_dbat1l,539\r\n\t.equ\tspr_dbat2u,540\r\n\t.equ\tspr_dbat2l,541\r\n\t.equ\tspr_dbat3u,542\r\n\t.equ\tspr_dbat3l,543\r\n\r\n\t.equ\tspr_sdr1,25\r\n\r\n\t.equ\tspr_sprg0,272\r\n\t.equ\tspr_sprg1,273\r\n\t.equ\tspr_sprg2,274\r\n\t.equ\tspr_sprg3,275\r\n\r\n\t.equ\tspr_dar,19\r\n\t.equ\tspr_dsisr,18\r\n\r\n\t.equ\tspr_srr0,26\r\n\t.equ\tspr_srr1,27\r\n\r\n\t.equ\tspr_ear,282\r\n\r\n\t.equ\tspr_dabr,1013\r\n\r\n\t.equ\tspr_tbl,284\r\n\t.equ\tspr_tbu,285\r\n\r\n\t.equ\tspr_l2cr,1017\r\n\r\n\t.equ\tspr_dec,22\r\n\r\n\t.equ\tspr_iabr,1010\r\n\r\n\t.equ\tspr_pmc1,953\r\n\t.equ\tspr_pmc2,954\r\n\t.equ\tspr_pmc3,957\r\n\t.equ\tspr_pmc4,958\r\n\r\n\t.equ\tspr_sia,955\r\n\r\n\t.equ\tspr_mmcr0,952\r\n\t.equ\tspr_mmcr1,956\r\n\r\n\t.equ\tspr_thrm1,1020\r\n\t.equ\tspr_thrm2,1021\r\n\t.equ\tspr_thrm3,1022\r\n\r\n\t.equ\tspr_ictc,1019\r\n\r\n# gekko registers\r\n\t.equ\tspr_gqr0,912\r\n\t.equ\tspr_gqr1,913\r\n\t.equ\tspr_gqr2,914\r\n\t.equ\tspr_gqr3,915\r\n\t.equ\tspr_gqr4,916\r\n\t.equ\tspr_gqr5,917\r\n\t.equ\tspr_gqr6,918\r\n\t.equ\tspr_gqr7,919\r\n\r\n\t.equ\tspr_hid2,920\r\n\r\n\t.equ\tspr_wpar,921\r\n\r\n\t.equ\tspr_dmau,922\r\n\t.equ\tspr_dmal,923\r\n# end of gekko registers\r\n\r\n\t.equ\tMSR_POW,0x00040000\t# Power Management\r\n\t.equ\tMSR_ILE,0x00010000\t# Interrupt Little Endian\r\n\t.equ\tMSR_EE,0x00008000\t# external interrupt\r\n\t.equ\tMSR_PR,0x00004000\t# privilege level(should be 0)\r\n\t.equ\tMSR_FP,0x00002000\t# floating point available\r\n\t.equ\tMSR_ME,0x00001000\t# machine check enable\r\n\t.equ\tMSR_FE0,0x00000800\t# floating point exception enable\r\n\t.equ\tMSR_SE,0x00000400\t# single step trace enable\r\n\t.equ\tMSR_BE,0x00000200\t# branch trace enable\r\n\t.equ\tMSR_FE1,0x00000100\t# floating point exception enable\r\n\t.equ\tMSR_IP,0x00000040\t# Exception prefix\r\n\t.equ\tMSR_IR,0x00000020\t# instruction relocate\r\n\t.equ\tMSR_DR,0x00000010\t# data relocate\r\n\t.equ\tMSR_PM,0x00000004\t# Performance monitor marked mode\r\n\t.equ\tMSR_RI,0x00000002\t# Recoverable interrupt\r\n\t.equ\tMSR_LE,0x00000001\t# Little Endian\r\n\r\n\t.equ\tMSR_POW_BIT,13\t\t# Power Management\r\n\t.equ\tMSR_ILE_BIT,15\t\t# Interrupt Little Endian\r\n\t.equ\tMSR_EE_BIT,16\t\t# external interrupt\r\n\t.equ\tMSR_PR_BIT,17\t\t# privilege level (should be 0)\r\n\t.equ\tMSR_FP_BIT,18\t\t# floating point available\r\n\t.equ\tMSR_ME_BIT,19\t\t# machine check enable\r\n\t.equ\tMSR_FE0_BIT,20\t\t# floating point exception enable\r\n\t.equ\tMSR_SE_BIT,21\t\t# single step trace enable\r\n\t.equ\tMSR_BE_BIT,22\t\t# branch trace enable\r\n\t.equ\tMSR_FE1_BIT,23\t\t# floating point exception enable\r\n\t.equ\tMSR_IP_BIT,25\t\t# Exception prefix\r\n\t.equ\tMSR_IR_BIT,26\t\t# instruction relocate\r\n\t.equ\tMSR_DR_BIT,27\t\t# data relocate\r\n\t.equ\tMSR_PM_BIT,29\t\t# Performance monitor marked mode\r\n\t.equ\tMSR_RI_BIT,30\t\t# Recoverable interrupt\r\n\t.equ\tMSR_LE_BIT,31\t\t# Little Endian\r\n\r\n\r\n\t.equ\tHID2_LSQE,0x80000000\t# L/S quantize enable\r\n\t.equ\tHID2_WPE,0x40000000\t# Write pipe enable\r\n\t.equ\tHID2_PSE,0x20000000\t# Paired single enable\r\n\t.equ\tHID2_LCE,0x10000000\t# Locked cache enable\r\n\r\n\t.equ\tHID2_DCHERR,0x00800000\t# ERROR: dcbz_l cache hit\r\n\t.equ\tHID2_DNCERR,0x00400000\t# ERROR: DMA access to normal cache\r\n\t.equ\tHID2_DCMERR,0x00200000\t# ERROR: DMA cache miss error\r\n\t.equ\tHID2_DQOERR,0x00100000\t# ERROR: DMA queue overflow\r\n\t.equ\tHID2_DCHEE,0x00080000\t# dcbz_l cache hit error enable\r\n\t.equ\tHID2_DNCEE,0x00040000\t# DMA access to normal cache error enable\r\n\t.equ\tHID2_DCMEE,0x00020000\t# DMA cache miss error error enable\r\n\t.equ\tHID2_DQOEE,0x00010000\t# DMA queue overflow error enable\r\n\r\n\t.equ\tHID2_DMAQL_MASK,0x0F000000\t# DMA queue length mask\r\n\t.equ\tHID2_DMAQL_SHIFT,24\t\t# DMA queue shift\r\n\r\n\t.equ\tHID2_LSQE_BIT,0\r\n\t.equ\tHID2_WPE_BIT,1\r\n\t.equ\tHID2_PSE_BIT,2\r\n\t.equ\tHID2_LCE_BIT,3\r\n\r\n\t.equ\tHID2_DCHERR_BIT,8   \r\n\t.equ\tHID2_DNCERR_BIT,9\r\n\t.equ\tHID2_DCMERR_BIT,10\r\n\t.equ\tHID2_DQOERR_BIT,11\r\n\t.equ\tHID2_DCHEE_BIT,12\r\n\t.equ\tHID2_DNCEE_BIT,13\r\n\t.equ\tHID2_DCMEE_BIT,14\r\n\t.equ\tHID2_DQOEE_BIT,15\r\n\r\n#------------------------------------------\r\n\r\n\t.equ\tEX_SYSTEM_RESET,0\r\n\t.equ\tEX_MACHINE_CHECK,1\r\n\t.equ\tEX_DSI,2\r\n\t.equ\tEX_ISI,3\r\n\t.equ\tEX_EXTERNAL_INTERRUPT,4\r\n\t.equ\tEX_ALIGNMENT,5\r\n\t.equ\tEX_PROGRAM,6\r\n\t.equ\tEX_FLOATING_POINT,7\r\n\t.equ\tEX_DECREMENTER,8\r\n\t.equ\tEX_SYSTEM_CALL,9\r\n\t.equ\tEX_TRACE,10\r\n\t.equ\tEX_PERFORMANCE_MONITOR,11\r\n\t.equ\tEX_BREAKPOINT,12\r\n\t.equ\tEX_SYSTEM_INTERRUPT,13\r\n\t.equ\tEX_THERMAL_INTERRUPT,14\r\n\t.equ\tEX_MAX,15\r\n\r\n\t.equ\tREAL_EX_SYSTEM_RESET,0\r\n\t.equ\tREAL_EX_MACHINE_CHECK,1\r\n\t.equ\tREAL_EX_DSI,2\r\n\t.equ\tREAL_EX_ISI,3\r\n\t.equ\tREAL_EX_EXTERNAL_INTERRUPT,4\r\n\t.equ\tREAL_EX_ALIGNMENT,5\r\n\t.equ\tREAL_EX_PROGRAM,6\r\n\t.equ\tREAL_EX_FLOATING_POINT,7\r\n\t.equ\tREAL_EX_DECREMENTER,8\r\n\t.equ\tREAL_EX_SYSTEM_CALL,11\r\n\t.equ\tREAL_EX_TRACE,12\r\n\t.equ\tREAL_EX_PERFORMANCE_MONITOR,14\r\n\t.equ\tREAL_EX_BREAKPOINT,18\r\n\t.equ\tREAL_EX_SYSTEM_INTERRUPT,21\r\n\t.equ\tREAL_EX_THERMAL_INTERRUPT,22\r\n\t.equ\tREAL_EX_MAX,15\r\n\r\n#------------------------------------------\r\n\r\n\t.equ\tCMD_OK,0\r\n\t.equ\tCMD_PK_2SMALL,1\r\n\t.equ\tCMD_COMMSERR,2\r\n\r\n#-----------------------------------------\r\n# Boot Info2 is a 8K byte structure that is loaded to himem\r\n# (lower than FST) by apploader.\r\n\r\n\t.equ\tBOOTINFO2_ADDR,0x800000F4\r\n\r\n\t.equ\tOS_BI2_SIZE,0x2000      \t\t\t# 8K \r\n\t.equ\tOS_BI2_DEBUGMONSIZE_OFFSET,0x0000\r\n\t.equ\tOS_BI2_SIMMEMSIZE_OFFSET,0x0004\r\n\t.equ\tOS_BI2_ARGOFFSET_OFFSET,0x0008\r\n\t.equ\tOS_BI2_DEBUGFLAG_OFFSET,0x000c\r\n\t.equ\tOS_BI2_TRKLOCATION_OFFSET,0x0010\r\n\t.equ\tOS_BI2_TRKSIZE_OFFSET,0x0014\r\n\t.equ\tOS_BI2_COUNTRYCODE_OFFSET,0x0018\r\n\t.equ\tOS_BI2_ARGSIZE_MAX,0x1000      \t\t# 4K\r\n\t.equ\tOS_BI2_COUNTRYCODE_JP,0\r\n\t.equ\tOS_BI2_COUNTRYCODE_US,1\r\n\r\n\t.equ\tARENAHI_ADDR,0x80000034\r\n"
  },
  {
    "path": "Code/Sk/product_codes.h",
    "content": "#ifndef\t__SK_PRODUCT_CODES_H\r\n#define\t__SK_PRODUCT_CODES_H\r\n\r\nnamespace Config\r\n{\r\n\r\n// The mem card headers\r\n// These are also used to derive the elf name for comparison so that the language can be\r\n// autodetected, in sys\\config\\ngps\\p_config.cpp\r\n#define NGPS_NTSC \"BASLUS-20731\"    // Mick: 20731 is the official THPS5 NTSC SLUS number\r\n#define NGPS_PAL_ENGLISH \"BESLES-51848\"\r\n#define NGPS_PAL_FRENCH \"BESLES-51851\"   // <<<<<<<<<<<<<<<<<<<  just guessing here.....\r\n#define NGPS_PAL_GERMAN \"BESLES-51852\"\r\n#define NGPS_PAL_ITALIAN \"BESLES-51853\"\r\n#define NGPS_PAL_SPANISH \"BESLES-51854\"\r\n\r\n};\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Sk/template.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t<project>\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t<module>\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t<filename>.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\txx/xx/xx\t- xxx\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__<FILENAME>_H\r\n#define\t__<FILENAME>_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Clase Definitions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#endif\t// __<FILENAME>_H"
  },
  {
    "path": "Code/Sys/Config/NGC/p_config.cpp",
    "content": "// Config Manager stuff. KSH 20 Mar 2002\r\n#include <sys/config/config.h>\r\n#include <dolphin.h>\r\n#include <sys/file/filesys.h>\r\n\r\nextern void * get_font_file_address( const char * p_filename );\r\n\r\nnamespace Config\r\n{\r\n\r\nvoid Plat_Init(sint argc, char** argv)\r\n{\r\n\tgHardware=HARDWARE_NGC;\r\n\t\r\n\t// I don't know yet how to autodetect the language for this platform, so\r\n\t// just set it to English for the moment.\r\n\t\r\n\tswitch ( OSGetLanguage() )\r\n\t{\r\n\t\tcase OS_LANG_GERMAN:\r\n\t\t\tgLanguage=LANGUAGE_GERMAN;\r\n\t\t\tbreak;\r\n\t\tcase OS_LANG_FRENCH:\r\n\t\t\tgLanguage=LANGUAGE_FRENCH;\r\n\t\t\t{\r\n\t\t\t\t// Load French font file.\r\n\t\t\t\tvoid * p = get_font_file_address( \"small\" );\r\n\t\t\t\tvoid *p_FH = File::Open( \"fonts\\\\small_fr.fnt.ngc\", \"rb\" );\r\n\t\t\t\tif( p_FH )\r\n\t\t\t\t{\r\n\t\t\t\t\tint size = File::GetFileSize( p_FH );\r\n\t\t\t\t\tchar * p_new = new char[size];\r\n\t\t\t\t\tFile::Read( p_new, size, 1, p_FH );\r\n\t\t\t\t\tmemcpy( p, p_new, size );\r\n\t\t\t\t\tdelete p_new;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase OS_LANG_SPANISH:\r\n\t\tcase OS_LANG_ITALIAN:\r\n\t\tcase OS_LANG_DUTCH:\r\n\t\tcase OS_LANG_ENGLISH:\r\n\t\tdefault:\r\n\t\t\tgLanguage=LANGUAGE_ENGLISH;\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\t// Autodetect these somehow ...\r\n\tif ( VIGetTvFormat() == VI_PAL )\r\n\t{\r\n\t\tgDisplayType=DISPLAY_TYPE_PAL;\r\n\t\tgFPS=50;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgDisplayType=DISPLAY_TYPE_NTSC;\r\n\t\tgFPS=60;\r\n\t}\r\n\t\r\n\t// See if we're on a devkit or not by checking the amount of memory\r\n\tint megs = (uint32)OSGetArenaHi() - (uint32)OSGetArenaLo();\r\n\r\n\tif ( megs >= ( 1024 * 1024 * 24 ) )\r\n\t{\r\n\t\t// We're on a devkit\r\n\t\tgCD=false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// We're on an NR-Reader\r\n\t\tgCD=true;\r\n\t}\r\n\t\r\n\tgpMemCardHeader=\"SK5\";\r\n}\r\n\r\n} // namespace Config\r\n\r\n"
  },
  {
    "path": "Code/Sys/Config/NGPS/p_config.cpp",
    "content": "// Config Manager stuff. KSH 20 Mar 2002\r\n#include <sys/config/config.h>\r\n#include <sk/product_codes.h>\r\n#include <libscf.h>\r\n\r\nextern \"C\"\r\n{\r\nint snputs(const char* pszStr);\r\n}\r\n\r\nnamespace Config\r\n{\r\n\r\nstatic char s_elf_name[64];  // will be 'local' or 'skate5'\r\n\r\nconst char * GetElfName()\r\n{\r\n\treturn (const char *)s_elf_name;\r\n}\r\n\r\nstatic const char *sGenerateElfName(const char *p_memCardHeader)\r\n{\r\n\tDbg_MsgAssert(strlen(p_memCardHeader)==12,(\"Bad length for mem card header '%s'\\n\",p_memCardHeader));\r\n\tstatic char sp_elf_name[50];\r\n\r\n\t// Note: p_memCardHeader will have the form \"BASLUS-20731\"\r\n\t// \"BASLUS-20731\" needs to map to an elf name of \"cdrom:\\SLUS_207.31;1\"\r\n\t\r\n\tsprintf(sp_elf_name,\"cdrom0:\\\\SL%cS_%c%c%c.%c%c;1\",\r\n\t\t\tp_memCardHeader[4],\r\n\t\t\tp_memCardHeader[7],\r\n\t\t\tp_memCardHeader[8],\r\n\t\t\tp_memCardHeader[9],\r\n\t\t\tp_memCardHeader[10],\r\n\t\t\tp_memCardHeader[11]);\r\n\treturn sp_elf_name;\r\n}\r\n\r\nvoid Plat_Init(sint argc, char** argv)\r\n{\r\n\tgHardware=HARDWARE_UNDEFINED;\r\n\tgGotExtraMemory=false;\r\n\tgCD=false;\r\n\r\n\r\n\t\r\n\t// must check to see if the supplied filename starts \"cdrom0:\\THPS4\\\"    SLUS_207.31;1\r\n\r\n\t// if the first real argument exists and starts with a digit, then assume\r\n\t// that we are running from a bootstrap (as we will just have been passed the language in argv[1])\r\n\t// and preempt any other parameters...\r\n\t// so assume running on a regular PS2, from the CD\r\n\tif (argc > 1)\r\n\t{\r\n\t\tif (argv[1][0] >= '0' && argv[1][0] <= '9')\r\n\t\t{\r\n\t\t\tprintf (\"argv[1][0] is a digit, so assuming bootstrap format, using \\\\thps4 directory\\n\");\r\n\t\t\tgBootstrap=true;\r\n\t\t\tgSonyBootstrap = true;\r\n\t\t\tgHardware=HARDWARE_PS2;\r\n\t\t\tgGotExtraMemory=false;\r\n\t\t\tgCD=true;\r\n\r\n\t\t\t// the rest we could, in theory, set from the sceLibDemo calls......\t\t\t\r\n\t\t\tgLanguage=LANGUAGE_ENGLISH;\r\n\t\t\tgTerritory=TERRITORY_UNDEFINED;\r\n\t\t\tgDisplayType=DISPLAY_TYPE_NTSC;\r\n\t\t\tgFPS=60;\r\n\r\n\t\t\t\r\n\t\t\treturn;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tprintf (\"argv[1][0] (%s) is not digit, so it's a regular boot, using root\\n\",argv[1]);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tprintf (\"no arguments, so it's a regular boot, using root\\n\");\r\n\t}\r\n\t\r\n\r\n\t\r\n\t// If the filename ends in .elf, then extract out the name\r\n\t// c:\\skate5\\build\\NGPSgnu\\local.elf\r\n\tif (stricmp(argv[0]+strlen(argv[0])-4,\".elf\")==0)\r\n\t{\r\n\t\tchar *p = argv[0]+strlen(argv[0])-5;\t\t// letter before the .elf\r\n\t\twhile (*p != '\\\\') p--;\r\n\t\tp++; // first letter of the name\r\n\t\tchar *q = &s_elf_name[0];\r\n\t\twhile (*p != '.') *q++ = *p++;\r\n\t\t*q++ = 0;\r\n\t}\r\n\t\r\n\r\n\tif (!argv[0] || stricmp(argv[0]+strlen(argv[0])-4,\".elf\")==0)\r\n\t{\r\n\t\tgHardware=HARDWARE_PS2_DEVSYSTEM;\r\n\t\tgGotExtraMemory=true;\r\n\t\tgCD=false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// It's just a normal PS2\r\n\t\tgHardware=HARDWARE_PS2;\r\n\t\tgGotExtraMemory=false;\r\n\t\tgCD=true;\r\n\t}\r\n\t\r\n\t// Check command line to see if they're using ProView\r\n\tif (snputs(\"Plat_Init detected ProView ...\\n\")!=-1)\r\n\t{\r\n\t\tgHardware=HARDWARE_PS2_PROVIEW;\r\n\t\tgGotExtraMemory=false;\r\n\t\tgCD=false;\r\n\t}\r\n\t\r\n\t// Check command line to see if they want to force gGotExtraMemory on or off\r\n\tif (CommandLineContainsFlag(\"GotExtraMemory\",argc,argv))\t\t\r\n\t{\r\n\t\tgGotExtraMemory=true;\r\n\t}\r\n\tif (CommandLineContainsFlag(\"NoExtraMemory\",argc,argv))\t\t\r\n\t{\r\n\t\tgGotExtraMemory=false;\r\n\t}\r\n\t\r\n\t// Detect the language from the product code.\r\n\tgLanguage=LANGUAGE_ENGLISH;\r\n\tgpMemCardHeader=NGPS_NTSC;\r\n\tif (argv[0])\r\n\t{\r\n\t\t// Doing a stricmp just in case it changes to be CDROM later or something.\r\n\t\tif (stricmp(argv[0],sGenerateElfName(NGPS_NTSC))==0)\r\n\t\t{\r\n\t\t\tgLanguage=LANGUAGE_ENGLISH;\r\n\t\t\tgpMemCardHeader=NGPS_NTSC;\r\n\t\t}\r\n\t\telse if (stricmp(argv[0],sGenerateElfName(NGPS_PAL_ENGLISH))==0)\r\n\t\t{\r\n\t\t\tgLanguage=LANGUAGE_ENGLISH;\r\n\t\t\tgpMemCardHeader=NGPS_PAL_ENGLISH;\r\n\t\t}\r\n\t\telse if (stricmp(argv[0],sGenerateElfName(NGPS_PAL_FRENCH))==0)\r\n\t\t{\r\n\t\t\tgLanguage=LANGUAGE_FRENCH;\r\n\t\t\tgpMemCardHeader=NGPS_PAL_FRENCH;\r\n\t\t}\r\n\t\telse if (stricmp(argv[0],sGenerateElfName(NGPS_PAL_GERMAN))==0)\r\n\t\t{\r\n\t\t\tgLanguage=LANGUAGE_GERMAN;\r\n\t\t\tgpMemCardHeader=NGPS_PAL_GERMAN;\r\n\t\t}\r\n\t\telse if (stricmp(argv[0],sGenerateElfName(NGPS_PAL_ITALIAN))==0)\r\n\t\t{\r\n\t\t\tgLanguage=LANGUAGE_ITALIAN;\r\n\t\t\tgpMemCardHeader=NGPS_PAL_ITALIAN;\r\n\t\t}\r\n\t\telse if (stricmp(argv[0],sGenerateElfName(NGPS_PAL_SPANISH))==0)\r\n\t\t{\r\n\t\t\tgLanguage=LANGUAGE_SPANISH;\r\n\t\t\tgpMemCardHeader=NGPS_PAL_SPANISH;\r\n\t\t}\r\n\t}\t\r\n\r\n\t// They may want to force the language to be something else from the command line ...\r\n\tconst char *p_language=GetCommandLineParam(\"Language\",argc,argv);\r\n\tif (p_language)\r\n\t{\r\n\t\tif (stricmp(p_language,\"English\")==0)\r\n\t\t{\r\n\t\t\tgLanguage=LANGUAGE_ENGLISH;\r\n\t\t\tgpMemCardHeader=NGPS_NTSC;\r\n\t\t}\r\n\t\telse if (stricmp(p_language,\"French\")==0)\r\n\t\t{\r\n\t\t\tgLanguage=LANGUAGE_FRENCH;\r\n\t\t\tgpMemCardHeader=NGPS_PAL_FRENCH;\r\n\t\t}\r\n\t\telse if (stricmp(p_language,\"German\")==0)\r\n\t\t{\r\n\t\t\tgLanguage=LANGUAGE_GERMAN;\r\n\t\t\tgpMemCardHeader=NGPS_PAL_GERMAN;\r\n\t\t}\r\n\t\telse if (stricmp(p_language,\"Italian\")==0)\r\n\t\t{\r\n\t\t\tgLanguage=LANGUAGE_ITALIAN;\r\n\t\t\tgpMemCardHeader=NGPS_PAL_ITALIAN;\r\n\t\t}\r\n\t\telse if (stricmp(p_language,\"Spanish\")==0)\r\n\t\t{\r\n\t\t\tgLanguage=LANGUAGE_SPANISH;\r\n\t\t\tgpMemCardHeader=NGPS_PAL_SPANISH;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"Language '%s' not supported\",p_language));\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t\r\n\tgTerritory=TERRITORY_UNDEFINED;\r\n\r\n\tgDisplayType=DISPLAY_TYPE_NTSC;\r\n\tgFPS=60;\r\n\t\r\n\t// Figure out if it is PAL from the product code ...\r\n\tif (argv[0])\r\n\t{\r\n\t\tchar p_temp[50];\r\n\t\tstrncpy(p_temp,argv[0],12);\r\n\t\tp_temp[12]=0; // strncpy won't terminate\r\n\t\t// Doing a stricmp just in case it changes to be CDROM later or something.\r\n\t\tif (stricmp(p_temp,\"cdrom0:\\\\SLES\")==0)\r\n\t\t{\r\n\t\t\tgDisplayType=DISPLAY_TYPE_PAL;\r\n\t\t\tgFPS=50;\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n} // namespace Config\r\n\r\n"
  },
  {
    "path": "Code/Sys/Config/Win32/p_config.cpp",
    "content": "// Config Manager stuff. KSH 20 Mar 2002\r\n#include <sys/config/config.h>\r\n\r\nnamespace Config\r\n{\r\n\r\nvoid Plat_Init(sint argc, char** argv)\r\n{\r\n\tgHardware\t= HARDWARE_WIN32;\r\n\tgLanguage\t= LANGUAGE_ENGLISH;\t\r\n\tgGotExtraMemory = true;\r\n}\r\n\r\n} // namespace Config\r\n\r\n"
  },
  {
    "path": "Code/Sys/Config/XBox/p_config.cpp",
    "content": "// Config Manager stuff. KSH 20 Mar 2002\r\n#include <sys/config/config.h>\r\n\r\nnamespace Config\r\n{\r\n\r\nvoid Plat_Init(sint argc, char** argv)\r\n{\r\n\tgHardware\t= HARDWARE_XBOX;\r\n\tDWORD lang\t= XGetLanguage();\r\n\tif( lang == XC_LANGUAGE_ENGLISH )\r\n\t\tgLanguage = LANGUAGE_ENGLISH;\r\n\telse\r\n\t{\r\n\t\tif( XGetVideoStandard() != XC_VIDEO_STANDARD_PAL_I )\r\n\t\t{\r\n\t\t\t// For NTSC, the only language allowed is English.\r\n\t\t\tgLanguage = LANGUAGE_ENGLISH;\r\n\t\t}\r\n\t\telse if( lang == XC_LANGUAGE_FRENCH )\r\n\t\t{\r\n\t\t\tgLanguage = LANGUAGE_FRENCH;\r\n\t\t}\r\n\t\telse if( lang == XC_LANGUAGE_GERMAN )\r\n\t\t{\r\n\t\t\tgLanguage = LANGUAGE_GERMAN;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Any languages other than French and German should also be considered English.\r\n\t\t\tgLanguage = LANGUAGE_ENGLISH;\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Kind of meaningless, but default CD to true for Final builds, false otherwise.\r\n#\tifdef __NOPT_ASSERT__\r\n\tgCD = false;\r\n#\telse\r\n\tgCD = true;\r\n#\tendif\r\n\t\r\n\tswitch( XGetVideoStandard())\r\n\t{\r\n\t\tcase XC_VIDEO_STANDARD_PAL_I:\r\n\t\t{\r\n\t\t\tgDisplayType\t= DISPLAY_TYPE_PAL;\r\n\t\t\tgFPS\t\t\t= 50;\r\n\t\t\tif( XGetVideoFlags() & XC_VIDEO_FLAGS_PAL_60Hz )\r\n\t\t\t{\r\n\t\t\t\tgFPS\t\t=\t60;\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase XC_VIDEO_STANDARD_NTSC_M:\r\n\t\tcase XC_VIDEO_STANDARD_NTSC_J:\r\n\t\t{\r\n\t\t\tgDisplayType\t= DISPLAY_TYPE_NTSC;\r\n\t\t\tgFPS\t\t\t= 60;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, (\"Unrecognized return value (%d) from XGetVideoStandard()\", XGetVideoStandard()));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\n} // namespace Config\r\n\r\n"
  },
  {
    "path": "Code/Sys/Config/config.cpp",
    "content": "// Config Manager stuff. KSH 20 Mar 2002\r\n#include <sys/config/config.h>\r\n\r\nnamespace Config\r\n{\r\nELanguage gLanguage=LANGUAGE_UNDEFINED;\r\nETerritory gTerritory=TERRITORY_UNDEFINED;\r\nEHardware gHardware=HARDWARE_UNDEFINED;\r\nbool gGotExtraMemory=false;\r\nbool gCD=false;\r\nbool gBootstrap=false;\r\nbool gSonyBootstrap=false;\r\nfloat\tgMasterVolume = 100.0f; \t\t// precentage at which we play the overall volume\r\nchar\tgReturnTo[128];\t\t\t\t\t// full path of executable we return to from a demo (second argument if first is \"bootstrap\")\r\nchar\tgReturnString[128];\t\t\t\t// string that we return for demo\r\n\r\nEDisplayType gDisplayType=DISPLAY_TYPE_NTSC;\r\nint gFPS=60;\r\n\r\nconst char *gpMemCardHeader=\"\";\r\n\r\n// Returns true if p_string starts with p_prefix. Non-case-sensitive.\r\n// (don't want to use strstr cos it is case sensitive)\r\nstatic bool sIsPrefixedWith(const char *p_string, const char *p_prefix)\r\n{\r\n\tif (!p_string || !p_prefix) return false;\r\n\t\r\n\tint string_len=strlen(p_string);\r\n\tint prefix_len=strlen(p_prefix);\r\n\tif (prefix_len>string_len)\r\n\t{\r\n\t\t// Can't be prefixed if shorter than the prefix.\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tchar p_buf[100];\r\n\tDbg_MsgAssert(string_len<100,(\"String too long for buffer\"));\r\n\tstrcpy(p_buf,p_string);\r\n\tp_buf[prefix_len]=0;\r\n\tif (stricmp(p_buf,p_prefix)==0)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n// If p_name is found to be followed by an equals in the command line, then this function\r\n// will return the word following the equals.\r\n// If p_name is not found, or equals blank, it will return NULL. \r\nconst char *GetCommandLineParam(const char *p_name, sint argc, char** argv)\r\n{\r\n\tconst char *p_found=NULL;\r\n\t\r\n\tfor (int i=0; i<argc; ++i)\r\n\t{\r\n\t\tif (sIsPrefixedWith(argv[i],p_name))\r\n\t\t{\r\n\t\t\t// p_name matches the start of argv[i]\r\n\t\t\t// Now see if it is followed by an equals.\r\n\t\t\tint len=strlen(p_name);\r\n\t\t\tchar *p_next_char=argv[i]+len;\r\n\t\t\tif (*p_next_char=='=')\r\n\t\t\t{\r\n\t\t\t\t// It is followed by an equals.\r\n\t\t\t\t++p_next_char;\r\n\t\t\t\tif (*p_next_char)\r\n\t\t\t\t{\r\n\t\t\t\t\t// There is something after the equals, so use that.\r\n\t\t\t\t\tp_found=argv[i]+len+1;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Use the next word, if there is one.\r\n\t\t\t\t\tif (i<argc-1)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_found=argv[i+1];\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (*p_next_char==0)\r\n\t\t\t{\r\n\t\t\t\t// p_name matches argv[i] exactly.\r\n\t\t\t\t// So see if argv[i+1] starts with an equals.\r\n\t\t\t\tif (i<argc-1 && argv[i+1][0]=='=')\r\n\t\t\t\t{\r\n\t\t\t\t\tif (argv[i+1][1]==0)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// argv[i+1] is just '=', so use the next string.\r\n\t\t\t\t\t\tif (i<argc-2)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_found=argv[i+2];\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// There is a word following the initial '=' in argv[i+1],\r\n\t\t\t\t\t\t// so use that word.\r\n\t\t\t\t\t\tp_found=argv[i+1]+1;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn p_found;\r\n}\r\n\r\n// Returns true if the command line contains the word p_name anywhere. Not case sensitive.\r\nbool CommandLineContainsFlag(const char *p_name, sint argc, char** argv)\r\n{\r\n\tif (!p_name) return false;\r\n\t\r\n\tfor (int i=0; i<argc; ++i)\r\n\t{\r\n\t\tif (stricmp(argv[i],p_name)==0)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\t\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n// This function is the first thing called from main()\r\n// It fills in all the globals in the Config namespace.\r\n// It calls the platform specific Plat_Init() first.\r\n// The idea is that the Plat_Init() function will do its best to fill in as many of the globals\r\n// as it can.\r\n// Then, the rest of the Init() function will fill in any that are missing, or override some\r\n// based on the command line parameters.\r\n\r\n// For example, the PS2 Plat_Init will look at the executable name to derive the territory.\r\n// However, if the executable name is just skate5.elf it contains no territory info.\r\n// So the Init() function, on seeing that the territory is undefined, will derive the territory\r\n// from the language and whether it is PAL.\r\nvoid Init(sint argc, char** argv)\r\n{\r\n\tPlat_Init(argc,argv);\r\n\t\r\n\t// Override the gCD flag if CD or NotCD are present on the command line.\r\n\tif (CommandLineContainsFlag(\"CD\",argc,argv))\t\t\r\n\t{\r\n\t\tgCD=true;\r\n\t}\r\n\tif (CommandLineContainsFlag(\"NotCD\",argc,argv))\t\t\r\n\t{\r\n\t\tgCD=false;\r\n\t}\r\n\r\n\tif (CommandLineContainsFlag(\"Bootstrap\",argc,argv))\t\t\r\n\t{\r\n\t\tgBootstrap=true;\r\n\t\tif (argc > 2)\r\n\t\t{\r\n\t\t\tstrcpy(gReturnTo,argv[2]);\r\n\t\t\tif (argc > 3)\r\n\t\t\t{\r\n\t\t\t\tstrcpy(gReturnString,argv[3]);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsprintf(gReturnString,\"THPS4\");\r\n\t\t\t}\t\t\t\r\n\t\t\tprintf (\"This bootstrap demo will return to %s passing back: %s\\n\",gReturnTo,gReturnString);\r\n\t\t}\r\n\t}\r\n\tif (CommandLineContainsFlag(\"NotBootstrap\",argc,argv))\t\t\r\n\t{\r\n\t\tgBootstrap=false;\r\n\t}\r\n\t\r\n\tif (CommandLineContainsFlag(\"Pal\",argc,argv))\t\t\r\n\t{\r\n\t\tgDisplayType=DISPLAY_TYPE_PAL;\r\n\t}\r\n\tif (CommandLineContainsFlag(\"NTSC\",argc,argv))\t\t\r\n\t{\r\n\t\tgDisplayType=DISPLAY_TYPE_NTSC;\r\n\t}\r\n\t\r\n\tconst char *p_frame_rate=GetCommandLineParam(\"FrameRate\",argc,argv);\r\n\tif (p_frame_rate)\r\n\t{\r\n\t\tif (strcmp(p_frame_rate,\"50\")==0)\r\n\t\t{\r\n\t\t\tgFPS=50;\r\n\t\t}\r\n\t\tif (strcmp(p_frame_rate,\"60\")==0)\r\n\t\t{\r\n\t\t\tgFPS=60;\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\nconst char* GetMemCardHeader()\r\n{\r\n\treturn gpMemCardHeader;\t\r\n}\r\n\r\n// Return the string for the directory we are running in\r\n// generally this will be the root\r\n// but when making a demo disk, then it will be the \"THPS4\" directory\r\nconst char* GetDirectory()\r\n{\r\n\tif (Bootstrap())\r\n\t{\r\n\t\treturn\t\"THPS4\\\\\";\t // generally a subdirectory off the root\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn \"\";\t\t\t // nothing needed it it is the root\r\n\t}\r\n}\r\n\r\nconst char* GetLanguageName()\r\n{\r\n\tswitch (gLanguage)\r\n\t{\r\n\tcase LANGUAGE_ENGLISH: \t\treturn \"English\"; break;\r\n\tcase LANGUAGE_FRENCH: \t\treturn \"French\"; break;\r\n\tcase LANGUAGE_GERMAN: \t\treturn \"German\"; break;\r\n\tcase LANGUAGE_JAPANESE:\t\treturn \"Japanese\"; break;\r\n\tcase LANGUAGE_SPANISH:\t\treturn \"Spanish\"; break;\r\n\tcase LANGUAGE_ITALIAN:\t\treturn \"Italian\"; break;\r\n\tcase LANGUAGE_DUTCH:\t\treturn \"Dutch\"; break;\r\n\tcase LANGUAGE_PORTUGUESE:\treturn \"Portuguese\"; break;\r\n\tdefault: \t\t\t\treturn \"Unknown language\"; break;\r\n\t}\r\n}\r\n\r\nconst char* GetTerritoryName()\r\n{\r\n\tswitch (gTerritory)\r\n\t{\r\n\tcase TERRITORY_EUROPE: \treturn \"Europe\"; break;\r\n\tcase TERRITORY_US: \t\treturn \"US\"; break;\r\n\tcase TERRITORY_ASIA: \treturn \"Asia\"; break;\r\n\tdefault: \t\t\t\treturn \"Unknown territory\"; break;\r\n\t}\r\n}\r\n\r\nconst char* GetHardwareName()\r\n{\r\n\tswitch (gHardware)\r\n\t{\r\n\tcase HARDWARE_PS2: \t\t\t\treturn \"PS2\"; break;\r\n\tcase HARDWARE_PS2_PROVIEW:\t\treturn \"PS2 ProView\"; break;\r\n\tcase HARDWARE_PS2_DEVSYSTEM:\treturn \"PS2 Dev System\"; break;\r\n\tcase HARDWARE_XBOX:\t\t\t\treturn \"XBox\"; break;\r\n\tcase HARDWARE_NGC:\t\t\t\treturn \"GameCube\"; break;\r\n\tcase HARDWARE_WIN32:\t\t\treturn \"Win32\"; break;\r\n\tdefault:\t\t\t\t\t\treturn \"Unknown platform\"; break;\r\n\t}\t\r\n}\r\n\r\nconst char* GetDisplayTypeName()\r\n{\r\n\tswitch (gDisplayType)\r\n\t{\r\n\tcase DISPLAY_TYPE_PAL:\t\treturn \"PAL\"; break;\r\n\tcase DISPLAY_TYPE_NTSC:\t\treturn \"NTSC\"; break;\r\n\tdefault:\t\t\t\t\treturn \"Unknown display type\"; break;\r\n\t}\r\n}\r\n\r\n} // namespace Config\r\n\r\n"
  },
  {
    "path": "Code/Sys/Config/config.h",
    "content": "// Config Manager stuff. KSH 20 Mar 2002\r\n//\r\n// A bunch of inline functions for quering what type of platform the executable is running on,\r\n// what language is set, whether it's PAL or NTSC, etc blaa blaa.\r\n//\r\n// The first thing main() does is call the Config::Init function, which parses the command\r\n// line and does various things to work out what the config is. Then the inline functions just\r\n// return the values calculated in Init, so they're nice and fast.\r\n\r\n\r\n#ifndef\t__CONFIG_CONFIG_H\r\n#define\t__CONFIG_CONFIG_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\nnamespace Config\r\n{\r\n\r\nenum ELanguage\r\n{\r\n\tLANGUAGE_UNDEFINED,\r\n\t\r\n\t// Prefixed with LANGUAGE_ so that they don't clash with the old defines that are still\r\n\t// in the code.\r\n\tLANGUAGE_JAPANESE,\r\n\tLANGUAGE_ENGLISH,\r\n\tLANGUAGE_FRENCH,\r\n\tLANGUAGE_SPANISH,\r\n\tLANGUAGE_GERMAN,\r\n\tLANGUAGE_ITALIAN,\r\n\tLANGUAGE_DUTCH,\r\n\tLANGUAGE_PORTUGUESE,\r\n};\r\n\r\nenum ETerritory\r\n{\r\n\tTERRITORY_UNDEFINED,\r\n\tTERRITORY_EUROPE,\r\n\tTERRITORY_US,\r\n\tTERRITORY_ASIA,\r\n};\r\n\r\nenum EHardware\r\n{\r\n\t// All prefixed with HARDWARE_ to be consistent with the language enum above ...\r\n\tHARDWARE_UNDEFINED,\r\n\t\r\n\tHARDWARE_PS2,\t\t\t// A normal PS2\r\n\tHARDWARE_PS2_PROVIEW,\t// A PS2 running ProView\r\n\tHARDWARE_PS2_DEVSYSTEM,\t// A dev system with lots of memory\r\n\t\r\n\tHARDWARE_XBOX,\t\t// An XBox\r\n\tHARDWARE_NGC,\t\t// A GameCube\r\n\tHARDWARE_WIN32,\t\t// A PC running Win32\r\n};\r\n\r\nenum EDisplayType\r\n{\r\n\tDISPLAY_TYPE_PAL,\r\n\tDISPLAY_TYPE_NTSC,\r\n};\r\n\r\nextern EDisplayType gDisplayType;\r\ninline EDisplayType GetDisplayType() {return gDisplayType;}\r\n// Perhaps change this to just return a bool if speed is a problem ...\r\ninline bool PAL() {return gDisplayType==DISPLAY_TYPE_PAL;}\r\ninline bool NTSC() {return gDisplayType==DISPLAY_TYPE_NTSC;}\r\n\r\nextern int gFPS;\r\nextern inline int FPS() {return gFPS;}\r\n\r\nextern EHardware gHardware;\r\ninline EHardware GetHardware() {return gHardware;}\r\n\r\nextern bool gGotExtraMemory;\r\ninline bool GotExtraMemory() {return gGotExtraMemory;}\r\n\r\nextern ELanguage gLanguage;\r\ninline ELanguage GetLanguage() {return gLanguage;}\r\n\r\nextern ETerritory gTerritory;\r\ninline ETerritory GetTerritory() {return gTerritory;}\r\n\r\nextern bool gCD;\r\ninline bool CD() {return gCD;}\r\n\r\nextern\tfloat\tgMasterVolume;\r\ninline\tfloat\tGetMasterVolume() {return gMasterVolume;}\r\ninline\tvoid \tSetMasterVolume(float vol) {gMasterVolume=vol;}\r\n\r\nextern bool gBootstrap;\r\nextern bool gSonyBootstrap;\r\ninline bool Bootstrap() {return gBootstrap;}\t\t\t\t// true if some kind of bootstrap demo\r\ninline bool SonyBootstrap() {return gSonyBootstrap;}\t\t// true if it's a Sony specific bootstrap demo (with timeout, etc)\r\nextern char\tgReturnTo[];  \r\nextern char\tgReturnString[];\r\n\r\nextern const char *gpMemCardHeader;\r\n\r\nconst char* GetDirectory();\r\n\r\nconst char* GetMemCardHeader();\r\n\r\nconst char *GetCommandLineParam(const char *p_name, sint argc, char** argv);\r\nbool CommandLineContainsFlag(const char *p_name, sint argc, char** argv);\r\n\r\nvoid Init(sint argc, char** argv);\r\nvoid Plat_Init(sint argc, char** argv);\r\n\r\n// Utility functions.\r\nconst char* GetLanguageName();\r\nconst char* GetTerritoryName();\r\nconst char* GetHardwareName();\r\nconst char* GetDisplayTypeName();\r\n\r\n// Sony Specific, not needed on the others\r\nconst char *GetElfName();\r\n\r\n\r\n} // namespace Config\r\n\r\n#endif\t// __CONFIG_CONFIG_H\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/AsyncFilesys.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// AsyncFilesys.cpp\t\tGRJ 8 Oct 2002\r\n//\r\n// Asynchronous file system\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <sys/file/AsyncFilesys.h>\r\n#include <gel/mainloop.h>\r\n\r\nnamespace File\r\n{\r\n\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n// Constants\r\n//\r\n\r\nconst uint32\tCAsyncFileHandle::MAX_FILE_SIZE = (uint32) ((uint64) (1 << 31) - 1);\t// 1 Gig (Because we are using signed, we lose a bit)\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCAsyncFileHandle::CAsyncFileHandle()\r\n{\r\n\tinit();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::init()\r\n{\r\n\t// Init vars\r\n\tmp_callback = NULL;\r\n\tm_callback_arg0 = 0;\r\n\tm_callback_arg1 = 0;\r\n\tm_current_function = FUNC_IDLE;\r\n\tm_mem_destination = (EAsyncMemoryType) DEFAULT_MEMORY_TYPE;\r\n\tm_stream = false;\r\n\tm_blocking = true;\t\t\t// Makes it async\r\n\tm_buffer_size = DEFAULT_BUFFER_SIZE;\r\n\tm_priority = DEFAULT_ASYNC_PRIORITY;\r\n\r\n\tm_file_size = -1;\r\n\tm_position = -1;\r\n\tm_busy_count = 0;\r\n\tm_last_result = 0;\r\n\r\n\tmp_pre_file = NULL;\r\n\r\n\tplat_init();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCAsyncFileHandle::~CAsyncFileHandle()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvolatile bool\t\tCAsyncFileHandle::IsBusy( void )\r\n{\r\n\t// Don't think we need the plat_is_busy()\r\n\treturn get_busy_count() > 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\t\tCAsyncFileHandle::WaitForIO( void )\r\n{\r\n\tdo\r\n\t{\r\n\t\t// Process any pending callbacks\r\n\t\tCAsyncFileLoader::s_execute_callback_list();\r\n\t} while (IsBusy());\r\n\r\n\treturn m_last_result;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::SetPriority( int priority )\r\n{\r\n\t//Dbg_MsgAssert(!IsBusy(), (\"Can't set file parameters: asynchronous file handle already busy.\"));\r\n\tm_current_function = FUNC_IDLE;\r\n\r\n\tm_priority = priority;\r\n\r\n\tplat_set_priority(priority);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::SetStream( bool stream )\r\n{\r\n\t//Dbg_MsgAssert(!IsBusy(), (\"Can't set file parameters: asynchronous file handle already busy.\"));\r\n\tm_current_function = FUNC_IDLE;\r\n\r\n\tm_stream = stream;\r\n\r\n\tplat_set_stream(stream);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::SetDestination( EAsyncMemoryType destination )\r\n{\r\n\t//Dbg_MsgAssert(!IsBusy(), (\"Can't set file parameters: asynchronous file handle already busy.\"));\r\n\tm_current_function = FUNC_IDLE;\r\n\r\n\tm_mem_destination = destination;\r\n\r\n\tplat_set_destination(destination);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::SetBufferSize( size_t buffer_size )\r\n{\r\n\t//Dbg_MsgAssert(!IsBusy(), (\"Can't set file parameters: asynchronous file handle already busy.\"));\r\n\tm_current_function = FUNC_IDLE;\r\n\r\n\tm_buffer_size = buffer_size;\r\n\r\n\tplat_set_buffer_size(buffer_size);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::SetBlocking( bool block )\r\n{\r\n\t//Dbg_MsgAssert(!IsBusy(), (\"Can't set file parameters: asynchronous file handle already busy.\"));\r\n\tm_current_function = FUNC_IDLE;\r\n\r\n\tm_blocking = block;\r\n\r\n\tplat_set_blocking(block);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::SetCallback( AsyncCallback p_callback, unsigned int arg0, unsigned int arg1)\r\n{\r\n\tmp_callback = p_callback;\r\n\tm_callback_arg0 = arg0;\r\n\tm_callback_arg1 = arg1;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsize_t\t\t\t\tCAsyncFileHandle::GetFileSize( void )\r\n{\r\n\tif (mp_pre_file)\r\n\t{\r\n\t\tDbg_Assert(PreMgr::sPreEnabled());\r\n\r\n        m_last_result = PreMgr::pre_get_file_size(mp_pre_file);\r\n\r\n\t\tDbg_Assert(PreMgr::sPreExecuteSuccess());\r\n\t\tDbg_MsgAssert(m_last_result, (\"PRE file size is 0\"));\r\n\r\n\t\treturn m_last_result;\r\n\t}\r\n\r\n\t// Make sure we have a valid file size first\r\n\twhile (m_file_size < 0)\r\n\t\t;\r\n\r\n\treturn m_file_size;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nsize_t\t\t\t\tCAsyncFileHandle::Load(void *p_buffer)\r\n{\r\n\t//Dbg_MsgAssert(!IsBusy(), (\"Can't start new load: asynchronous file handle already busy.\"));\r\n\r\n\tm_current_function = FUNC_LOAD;\r\n\r\n\tif (mp_pre_file)\r\n\t{\r\n\t\tDbg_Assert(PreMgr::sPreEnabled());\r\n\r\n\t\tint size = PreMgr::pre_get_file_size(mp_pre_file);\r\n\t\tPreMgr::pre_fseek(mp_pre_file, SEEK_SET, 0);\r\n        m_last_result = PreMgr::pre_fread(p_buffer, 1, size, mp_pre_file);\r\n\r\n\t\tDbg_Assert(PreMgr::sPreExecuteSuccess());\r\n\r\n\t\tinc_busy_count();\r\n\t\tio_callback(m_current_function, m_last_result, 0);\t\t\t// Must call this when we are done\r\n\t\treturn m_last_result;\r\n\t}\r\n\r\n\treturn plat_load(p_buffer);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nsize_t\t\t\t\tCAsyncFileHandle::Read(void *p_buffer, size_t size, size_t count)\r\n{\r\n\t//Dbg_MsgAssert(!IsBusy(), (\"Can't start new read: asynchronous file handle already busy.\"));\r\n\r\n\tm_current_function = FUNC_READ;\r\n\r\n\tif (mp_pre_file)\r\n\t{\r\n\t\tDbg_Assert(PreMgr::sPreEnabled());\r\n\r\n\t\tm_last_result = PreMgr::pre_fread(p_buffer, size, count, mp_pre_file);\r\n\r\n\t\tDbg_Assert(PreMgr::sPreExecuteSuccess());\r\n\r\n\t\tinc_busy_count();\r\n\t\tio_callback(m_current_function, m_last_result, 0);\t\t\t// Must call this when we are done\r\n\t\treturn m_last_result;\r\n\t}\r\n\r\n\treturn plat_read(p_buffer, size, count);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nsize_t\t\t\t\tCAsyncFileHandle::Write(void *p_buffer, size_t size, size_t count)\r\n{\r\n\t//Dbg_MsgAssert(!IsBusy(), (\"Can't start new write: asynchronous file handle already busy.\"));\r\n\r\n\tm_current_function = FUNC_WRITE;\r\n\r\n\tif (mp_pre_file)\r\n\t{\r\n\t\tDbg_Assert(PreMgr::sPreEnabled());\r\n\r\n\t\tm_last_result = PreMgr::pre_fwrite(p_buffer, size, count, mp_pre_file);\r\n\r\n\t\tDbg_Assert(PreMgr::sPreExecuteSuccess());\r\n\r\n\t\tinc_busy_count();\r\n\t\tio_callback(m_current_function, m_last_result, 0);\t\t\t// Must call this when we are done\r\n\t\treturn m_last_result;\r\n\t}\r\n\r\n\treturn plat_write(p_buffer, size, count);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\t\tCAsyncFileHandle::Seek(long offset, int origin)\r\n{\r\n\t//Dbg_MsgAssert(!IsBusy(), (\"Can't seek: asynchronous file handle already busy.\"));\r\n\r\n\tm_current_function = FUNC_SEEK;\r\n\r\n\tif (mp_pre_file)\r\n\t{\r\n\t\tDbg_Assert(PreMgr::sPreEnabled());\r\n\r\n\t\tm_last_result = PreMgr::pre_fseek(mp_pre_file, offset, origin);\r\n\r\n\t\tDbg_Assert(PreMgr::sPreExecuteSuccess());\r\n\r\n\t\tinc_busy_count();\r\n\t\tio_callback(m_current_function, m_last_result, 0);\t\t\t// Must call this when we are done\r\n\t\treturn m_last_result;\r\n\t}\r\n\r\n\treturn plat_seek(offset, origin);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::io_callback(EAsyncFunctionType function, int result, uint32 data)\r\n{\r\n\tm_last_result = result;\r\n\tCAsyncFileLoader::s_new_io_completion = true;\r\n\r\n\t// Call user function, if any\r\n\tif (mp_callback)\r\n\t{\r\n\t\tCAsyncFileLoader::s_add_callback(this, function, result);\r\n\t} else {\r\n\t\tpost_io_callback();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::post_io_callback()\r\n{\r\n\t// Clean up\r\n\tDbg_MsgAssert(get_busy_count() > 0, (\"We will go into a neagtive busy with completion of function %d\", m_current_function));\r\n\tif (dec_busy_count() == 0)\r\n\t{\r\n\t\tm_current_function = FUNC_IDLE;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCAsyncFileHandle::open(const char *filename, bool blocking, int priority)\r\n{\r\n\tDbg_MsgAssert(!IsBusy(), (\"Can't open file %s: asynchronous file handle already busy.\", filename));\r\n\tDbg_MsgAssert(!mp_pre_file, (\"Can't open file %s: already open as a PRE file.\", filename));\r\n\r\n\tm_priority = priority;\r\n\tm_blocking = blocking;\r\n\r\n\tm_current_function = FUNC_OPEN;\r\n\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        mp_pre_file = PreMgr::pre_fopen(filename, \"rb\", true);\r\n        if (mp_pre_file)\r\n\t\t{\r\n\t\t\tDbg_Assert(PreMgr::sPreExecuteSuccess());\r\n\r\n\t\t\tm_blocking = true;\t\t// Since PRE files are in memory, they will finish \"instantly\"\r\n\t\t\tm_last_result = true;\r\n\r\n\t\t\tinc_busy_count();\r\n\t\t\tio_callback(m_current_function, m_last_result, 0);\t\t\t// Must call this when we are done\r\n\t\t\treturn m_last_result;\r\n\t\t}\r\n    }\r\n\r\n\treturn plat_open(filename);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCAsyncFileHandle::close()\r\n{\r\n\tm_current_function = FUNC_CLOSE;\r\n\r\n\tif (mp_pre_file)\r\n\t{\r\n\t\tDbg_Assert(PreMgr::sPreEnabled());\r\n\r\n        m_last_result = PreMgr::pre_fclose(mp_pre_file, true);\r\n\r\n\t\tDbg_Assert(PreMgr::sPreExecuteSuccess());\r\n\r\n\t\tinc_busy_count();\r\n\t\tio_callback(m_current_function, m_last_result, 0);\t\t\t// Must call this when we are done\r\n\t\treturn m_last_result;\r\n\t}\r\n\r\n\treturn plat_close();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* plat stubs\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::plat_init()\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::Init\\n\");\r\n}\r\n\r\nbool\t\t\t\tCAsyncFileHandle::plat_open(const char *filename)\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::Open\\n\");\r\n\r\n\treturn false;\r\n}\r\n\r\nbool\t\t\t\tCAsyncFileHandle::plat_close()\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::Close\\n\");\r\n\r\n\treturn false;\r\n}\r\n\r\nvolatile bool\t\tCAsyncFileHandle::plat_is_done()\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::IsDone\\n\");\r\n\r\n\treturn false;\r\n}\r\n\r\nvolatile bool\t\tCAsyncFileHandle::plat_is_busy()\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::IsBusy\\n\");\r\n\r\n\treturn false;\r\n}\r\n\r\nbool\t\t\t\tCAsyncFileHandle::plat_is_eof() const\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::IsEOF\\n\");\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::plat_set_priority( int priority )\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::SetPriority\\n\");\r\n}\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::plat_set_stream( bool stream )\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::SetStream\\n\");\r\n}\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::plat_set_destination( EAsyncMemoryType destination )\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::SetDestination\\n\");\r\n}\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::plat_set_buffer_size( size_t buffer_size )\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::SetBufferSize\\n\");\r\n}\r\n\r\nvoid\t\t\t\tCAsyncFileHandle::plat_set_blocking( bool block )\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::SetBlocking\\n\");\r\n}\r\n\r\nsize_t\t\t\t\tCAsyncFileHandle::plat_load(void *p_buffer)\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::Load\\n\");\r\n\r\n\treturn 0;\r\n}\r\n\r\nsize_t\t\t\t\tCAsyncFileHandle::plat_read(void *p_buffer, size_t size, size_t count)\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::Read\\n\");\r\n\r\n\treturn 0;\r\n}\r\n\r\nsize_t\t\t\t\tCAsyncFileHandle::plat_write(void *p_buffer, size_t size, size_t count)\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::Write\\n\");\r\n\r\n\treturn 0;\r\n}\r\n\r\nchar *\t\t\t\tCAsyncFileHandle::plat_get_s(char *p_buffer, int maxlen)\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::GetS\\n\");\r\n\r\n\treturn NULL;\r\n}\r\n\r\nint\t\t\t\t\tCAsyncFileHandle::plat_seek(long offset, int origin)\r\n{\r\n\tprintf (\"STUB: CAsyncFileHandle::Seek\\n\");\r\n\r\n\treturn 0;\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\nCAsyncFileHandle\t*\tCAsyncFileLoader::s_file_handles[MAX_FILE_HANDLES];\r\nint\t\t\t\t\t\tCAsyncFileLoader::s_free_handle_index = 0;\r\n\r\nvolatile int\t\t\tCAsyncFileLoader::s_manager_busy_count = 0;\r\nvolatile bool\t\t\tCAsyncFileLoader::s_new_io_completion = false;\r\n\r\nvolatile CAsyncFileLoader::SCallback\tCAsyncFileLoader::s_callback_list[2][MAX_PENDING_CALLBACKS];\r\nvolatile int\t\t\t\t\t\t\tCAsyncFileLoader::s_num_callbacks[2] = { 0, 0 };\r\nint\t\t\t\t\t\t\t\t\t\tCAsyncFileLoader::s_cur_callback_list_index = 0;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileLoader::sInit()\r\n{\r\n\ts_free_handle_index = 0;\r\n\ts_plat_init();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileLoader::sCleanup()\r\n{\r\n\ts_plat_cleanup();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCAsyncFileLoader::sAsyncSupported()\r\n{\r\n\treturn s_plat_async_supported();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCAsyncFileLoader::sExist(const char *filename)\r\n{\r\n\treturn s_plat_exist(filename);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCAsyncFileHandle *\tCAsyncFileLoader::sOpen(const char *filename, bool blocking, int priority)\r\n{\r\n\tCAsyncFileHandle *p_file_handle = s_get_file_handle();\r\n\r\n\tif (p_file_handle)\r\n\t{\r\n\t\tif (!p_file_handle->open(filename, blocking, priority))\r\n\t\t{\r\n\t\t\t//Dbg_MsgAssert(0, (\"Error opening Async file %s\", filename));\r\n\t\t\ts_free_file_handle(p_file_handle);\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\r\n\t\treturn p_file_handle;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Out of Async handles\"));\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCAsyncFileLoader::sClose(CAsyncFileHandle *p_file_handle)\r\n{\r\n\r\n\tbool result = p_file_handle->close();\r\n\r\n\tbool free_result = s_free_file_handle(p_file_handle);\r\n\tif ( !free_result )\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"sClose(): Can't find async handle in CAsyncFileLoader\"));\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid\t\t\t\tCAsyncFileLoader::sWaitForIOEvent(bool all_io_events)\r\n{\r\n\tbool done = false;\r\n\r\n\twhile (!done)\r\n\t{\r\n\t\tprintf(\"CAsyncFileLoader waiting for io completion: busy count %d completion %d\\n\", s_manager_busy_count, s_new_io_completion);\r\n\r\n\t\t// Wait for an event\r\n\t\twhile (!s_new_io_completion)\r\n\t\t\t;\r\n\r\n\t\tprintf(\"CAsyncFileLoader got completion: busy count %d completion %d\\n\", s_manager_busy_count, s_new_io_completion);\r\n\r\n\t\t// execute callbacks\r\n\t\ts_execute_callback_list();\r\n\r\n\t\tdone = true;\t// assume we are done for now\r\n\t\tif (all_io_events)\r\n\t\t{\r\n\t\t\tfor (int i = 0; i < MAX_FILE_HANDLES; i++)\r\n\t\t\t{\r\n\t\t\t\tif (s_file_handles[i]->IsBusy())\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf(\"CAsyncFileLoader still needs to wait for file handle %d\\n\", i);\r\n\t\t\t\t\tDbg_MsgAssert(s_manager_busy_count, (\"CAsyncFileLoader busy count is 0 while file handle %d is busy\", i));\r\n\t\t\t\t\tdone = false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCAsyncFileLoader::sAsyncInUse()\r\n{\r\n#if 0\r\n\tfor (int i = 0; i < MAX_FILE_HANDLES; i++)\r\n\t{\r\n\t\tif (s_file_handles[i]->IsBusy())\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n#endif\r\n\r\n\tDbg_MsgAssert(s_manager_busy_count >= 0, (\"CAsyncFileLoader busy count is negative: %d\", s_manager_busy_count));\r\n\treturn s_manager_busy_count > 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCAsyncFileHandle *\tCAsyncFileLoader::s_get_file_handle()\r\n{\r\n\tif (s_free_handle_index < MAX_FILE_HANDLES)\r\n\t{\r\n\t\t// Find a non-busy handle and exchange with busy, if necessary\r\n\t\tif (s_file_handles[s_free_handle_index]->IsBusy())\r\n\t\t{\r\n\t\t\tint i;\r\n\t\t\tfor (i = s_free_handle_index + 1; i < MAX_FILE_HANDLES; i++)\r\n\t\t\t{\r\n\t\t\t\tif (!s_file_handles[i]->IsBusy())\r\n\t\t\t\t{\r\n\t\t\t\t\tCAsyncFileHandle *p_temp = s_file_handles[i];\r\n\t\t\t\t\ts_file_handles[i] = s_file_handles[s_free_handle_index];\r\n\t\t\t\t\ts_file_handles[s_free_handle_index] = p_temp;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// If we are full, wait for this one\r\n\t\t\tif (i == MAX_FILE_HANDLES)\r\n\t\t\t{\r\n\t\t\t\tDbg_Message(\"CAsyncFileLoader::sOpen(): waiting for old handle to finish up\");\r\n\t\t\t\ts_file_handles[s_free_handle_index]->WaitForIO();\r\n\t\t\t\tDbg_Message(\"CAsyncFileLoader::sOpen(): done waiting.\");\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\ts_file_handles[s_free_handle_index]->init();\t\t// Clear out any old stuff first\r\n\r\n\t\treturn s_file_handles[s_free_handle_index++];\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCAsyncFileLoader::s_free_file_handle(CAsyncFileHandle *p_file_handle)\r\n{\r\n\tDbg_Assert(s_free_handle_index);\r\n\r\n\tfor (int i = 0; i < MAX_FILE_HANDLES; i++)\r\n\t{\r\n\t\tif (p_file_handle == s_file_handles[i])\r\n\t\t{\r\n\t\t\t// Found it, exchange it with last open handle\r\n\t\t\ts_file_handles[i] = s_file_handles[--s_free_handle_index];\r\n\t\t\ts_file_handles[s_free_handle_index] = p_file_handle;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileLoader::s_add_callback(CAsyncFileHandle *p_file, EAsyncFunctionType function, int result)\r\n{\r\n\t// This will be called from an interrupt\r\n\t//scePrintf(\"Adding callback for handle %x\\n\", p_file);\r\n\tDbg_MsgAssert(s_num_callbacks[s_cur_callback_list_index] < MAX_PENDING_CALLBACKS, (\"add_callback(): list is full\"));\r\n\r\n\tvolatile SCallback * p_callback_entry =  &s_callback_list[s_cur_callback_list_index][s_num_callbacks[s_cur_callback_list_index]++];\r\n\r\n\tp_callback_entry->mp_file_handle\t= p_file;\r\n\tp_callback_entry->m_function\t\t= function;\r\n\tp_callback_entry->m_result\t\t\t= result;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid\t\t\t\tCAsyncFileLoader::s_update()\r\n{\r\n\ts_plat_update();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileLoader::s_execute_callback_list()\r\n{\r\n\ts_plat_swap_callback_list();\r\n\r\n\tint list_index = s_cur_callback_list_index ^ 1;\t// Look at old list\r\n\tint num_callbacks = s_num_callbacks[list_index];\r\n\r\n\tfor (int i = 0; i < num_callbacks; i++)\r\n\t{\r\n\t\tvolatile SCallback * p_callback_entry =  &s_callback_list[list_index][i];\r\n\r\n\t\tCAsyncFileHandle *p_file = p_callback_entry->mp_file_handle;\r\n\t\tDbg_Assert(p_file->mp_callback);\r\n\r\n\t\t//Dbg_Message(\"Executing callback for handle %x\", p_file);\r\n\r\n\t\t// Call the callback and the post callback\r\n\t\t(*p_file->mp_callback)(p_file, p_callback_entry->m_function, p_callback_entry->m_result,\r\n\t\t\t\t\t\t\t   p_file->m_callback_arg0, p_file->m_callback_arg1);\r\n\t\tp_file->post_io_callback();\r\n\t}\r\n\r\n\ts_num_callbacks[list_index] = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nDefineSingletonClass( CAsyncFilePoll, \"Async File System Poll module\" );\r\n\r\nCAsyncFilePoll::CAsyncFilePoll()\r\n{\r\n\tmp_logic_task = new Tsk::Task< CAsyncFilePoll > ( CAsyncFilePoll::s_logic_code, *this );\r\n}\r\n\r\nCAsyncFilePoll::~CAsyncFilePoll()\r\n{\r\n\tdelete mp_logic_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAsyncFilePoll::v_start_cb ( void )\r\n{\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\tmlp_manager->AddLogicTask( *mp_logic_task );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAsyncFilePoll::v_stop_cb ( void )\r\n{\r\n\tmp_logic_task->Remove();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid CAsyncFilePoll::s_logic_code ( const Tsk::Task< CAsyncFilePoll >& task )\r\n{\r\n\tDbg_AssertType ( &task, Tsk::Task< CAsyncFilePoll > );\r\n\r\n\tCAsyncFileLoader::s_update();\r\n\tCAsyncFileLoader::s_execute_callback_list();\r\n}\r\n\r\n}\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/AsyncFilesys.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tFile\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t09/24/02\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/AsyncFilesys.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_FILE_ASYNC_FILESYS_H\r\n#define\t__SYS_FILE_ASYNC_FILESYS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __GEL_MODULE_H\r\n#include <gel/module.h>\r\n#endif\r\n\r\n#include <sys/file/AsyncTypes.h>\r\n#include <sys/file/Pre.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define   \tDEFAULT_ASYNC_PRIORITY\t(100)\r\n#define   \tDEFAULT_BUFFER_SIZE\t\t(64 * 1024)\r\n\r\nnamespace Pcm\r\n{\r\n\tclass CFileStreamInfo;\r\n}\r\n\r\nnamespace File\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Forward declarations\r\nclass CAsyncFileHandle;\r\nclass CAsyncFileLoader;\r\nclass CAsyncFilePoll;\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// The asynchronous file class\r\n//\r\nclass CAsyncFileHandle\r\n{\r\npublic:\r\n\r\n\t// A callback is called after the completion of every async function\r\n\ttypedef void (* AsyncCallback)(CAsyncFileHandle *, EAsyncFunctionType function, int result, unsigned int arg0, unsigned int arg1);\r\n\r\n\r\n\t// Check read status\r\n\tvolatile bool\t\tIsDone( void );\r\n\tvolatile bool\t\tIsBusy( void );\r\n\tbool\t\t\t\tIsEOF( void ) const;\r\n\tint\t\t\t\t\tWaitForIO( void );\r\n\r\n\t// Change parameters\r\n\tvoid\t\t\t\tSetPriority( int priority );\r\n\tvoid\t\t\t\tSetStream( bool stream );\t\t\t// Tells if loaded all at once or streamed one buffer at a time\r\n\tvoid\t\t\t\tSetDestination( EAsyncMemoryType destination );\r\n\tvoid\t\t\t\tSetBufferSize( size_t buffer_size );\r\n\tvoid\t\t\t\tSetBlocking( bool block );\r\n\tvoid\t\t\t\tSetCallback( AsyncCallback p_callback, unsigned int arg0, unsigned int arg1 );\r\n\r\n\tsize_t\t\t\t\tGetFileSize( void );\r\n\r\n\t// Async commands\r\n\tsize_t\t\t\t\tLoad( void *p_buffer );\r\n\tsize_t\t\t\t\tRead( void *p_buffer, size_t size, size_t count );\r\n\tsize_t\t\t\t\tWrite( void *p_buffer, size_t size, size_t count );\r\n\tchar *\t\t\t\tGetS( char *p_buffer, int maxlen );\t// Probably don't need this one\r\n\tint\t\t\t\t\tSeek( long offset, int origin );\r\n\r\nprotected:\r\n\t\t\t\t\t\tCAsyncFileHandle();\r\n\tvirtual \t\t\t~CAsyncFileHandle();\r\n\r\n\tvoid\t\t\t\tinit( void );\r\n\r\n\tbool\t\t\t\topen( const char *filename, bool blocking = true, int priority = DEFAULT_ASYNC_PRIORITY );\r\n\tbool\t\t\t\tclose( void );\r\n\r\n\t// Internal busy counter functions\r\n\tvolatile int\t\tinc_busy_count();\t\t\t// Increment and return current count\r\n\tvolatile int\t\tdec_busy_count();\t\t\t// Decrement and return current count\r\n\tvolatile int\t\tget_busy_count();\t\t\t// Just return current count\r\n\r\n\t// Internal callback\r\n\tvirtual void\t\tio_callback(EAsyncFunctionType function, int result, uint32 data);\r\n\tvoid\t\t\t\tpost_io_callback();\r\n\r\n\t// These could be changed by an interrupt, so they are volatile\r\n\tvolatile int\t\tm_last_result;\r\n\r\n\t// Callback\r\n\tAsyncCallback\t\tmp_callback;\r\n\tunsigned int\t\tm_callback_arg0;\r\n\tunsigned int\t\tm_callback_arg1;\r\n\tEAsyncFunctionType\tm_current_function;\t\t// So callback knows what was completed\r\n\r\n\tEAsyncMemoryType\tm_mem_destination;\r\n\tbool\t\t\t\tm_stream;\r\n\tbool\t\t\t\tm_blocking;\r\n\tuint32\t\t\t\tm_buffer_size;\r\n\tint\t\t\t\t\tm_priority;\r\n\r\n\tvolatile int\t\tm_file_size;\r\n\tvolatile int\t\tm_position;\r\n\r\n\t// PRE file\r\n\tPreFile::FileHandle *mp_pre_file;\r\n\r\n\t// constants\r\n\tstatic const uint32\tMAX_FILE_SIZE;\r\n\r\n\t// platform-specific calls\r\n\tvirtual void\t\tplat_init( void );\r\n\r\n\tvirtual bool\t\tplat_open( const char *filename );\r\n\tvirtual bool\t\tplat_close( void );\r\n\r\n\tvirtual volatile bool\tplat_is_done( void );\r\n\tvirtual volatile bool\tplat_is_busy( void );\r\n\tvirtual bool\t\tplat_is_eof( void ) const;\r\n\r\n\tvirtual void\t\tplat_set_priority( int priority );\r\n\tvirtual void\t\tplat_set_stream( bool stream );\r\n\tvirtual void\t\tplat_set_destination( EAsyncMemoryType destination );\r\n\tvirtual void\t\tplat_set_buffer_size( size_t buffer_size );\r\n\tvirtual void\t\tplat_set_blocking( bool block );\r\n\r\n\tvirtual size_t\t\tplat_load( void *p_buffer );\r\n\tvirtual size_t\t\tplat_read( void *p_buffer, size_t size, size_t count );\r\n\tvirtual size_t\t\tplat_write( void *p_buffer, size_t size, size_t count );\r\n\tvirtual char *\t\tplat_get_s( char *p_buffer, int maxlen );\r\n\tvirtual int\t\t\tplat_seek( long offset, int origin );\r\n\r\nprivate:\r\n\tvolatile int\t\tm_busy_count;\t\t// Number of items we are waiting to finish asynchronously\r\n\r\n\t// Friends\r\n\tfriend CAsyncFileLoader;\r\n\r\n};\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// The interface to start and end async loads\r\n//\r\nclass CAsyncFileLoader\r\n{\r\npublic:\r\n\tstatic void\t\t\t\t\tsInit();\r\n\tstatic void\t\t\t\t\tsCleanup();\r\n\r\n\tstatic bool\t\t\t\t\tsAsyncSupported();\t\t\t\t\t\t\t// Returns true if async has been implemented on\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// the platform\r\n\r\n\t/////////////////////////////////////////////////////////////////////\r\n\t// The following are our versions of the ANSI file IO functions.\r\n\t//\r\n\tstatic bool\t\t\t\t\tsExist( const char *filename );\t\t\t\t// Nothing special about this function\r\n\tstatic CAsyncFileHandle *\tsOpen( const char *filename, bool blocking = true, int priority = DEFAULT_ASYNC_PRIORITY );\r\n\tstatic bool\t\t\t\t\tsClose( CAsyncFileHandle *p_file_handle );\r\n\r\n\t// IO Waiting\r\n\tstatic void\t\t\t\t\tsWaitForIOEvent(bool all_io_events);\t\t// Returns when we get an async result\r\n\tstatic bool\t\t\t\t\tsAsyncInUse();\t\t\t\t\t\t\t\t// Slow\r\n\r\n\r\nprotected:\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tMAX_FILE_HANDLES = \t\t16,\r\n\t\tMAX_PENDING_CALLBACKS = 16,\r\n\t};\r\n\r\n\t// Callback data\r\n\tstruct SCallback\r\n\t{\r\n\t\tCAsyncFileHandle *\t\t\t\tmp_file_handle;\r\n\t\tEAsyncFunctionType\t\t\t\tm_function;\r\n\t\tint\t\t\t\t\t\t\t\tm_result;\r\n\t};\r\n\r\n\t// This should actually be declared below the p-line\r\n\tstatic CAsyncFileHandle *\ts_file_handles[MAX_FILE_HANDLES];\r\n\tstatic int\t\t\t\t\ts_free_handle_index;\r\n\r\n\t// Status\r\n\tstatic volatile int\t\t\ts_manager_busy_count;\t\t// Is 0 when there are no outstanding async IO requests\r\n\tstatic volatile bool\t\ts_new_io_completion;\t\t// File handle got callback since s_execute_callback_list()\r\n\r\n\t// Current callback list\r\n\tstatic volatile SCallback\ts_callback_list[2][MAX_PENDING_CALLBACKS];\r\n\tstatic volatile int\t\t\ts_num_callbacks[2];\r\n\tstatic int\t\t\t\t\ts_cur_callback_list_index;\r\n\r\n\t// File handle management\r\n\tstatic CAsyncFileHandle *\ts_get_file_handle();\r\n\tstatic bool\t\t\t\t\ts_free_file_handle(CAsyncFileHandle *p_file_handle);\r\n\r\n\t// callback list functions\r\n\tstatic void\t\t\t\t\ts_add_callback(CAsyncFileHandle *p_file, EAsyncFunctionType function, int result);\r\n\tstatic void\t\t\t\t\ts_execute_callback_list();\r\n\r\n\t// Increment and decrement the manager busy count.  Should only be called by CAsyncFileHandle::inc_busy_count()\r\n\t// and CAsyncFileHandle::dec_busy_count()\r\n\tstatic void\t\t\t\t\ts_inc_manager_busy_count();\r\n\tstatic void\t\t\t\t\ts_dec_manager_busy_count();\r\n\r\n\t// Primarily to allow per-frame polling for platforms that may not support system callbacks on i/o routines\r\n\tstatic void\t\t\t\t\ts_update();\r\n\r\n\t// platform-specific calls\r\n\tstatic void\t\t\t\t\ts_plat_init();\r\n\tstatic void\t\t\t\t\ts_plat_cleanup();\r\n\r\n\tstatic bool\t\t\t\t\ts_plat_async_supported();\r\n\r\n\tstatic bool\t\t\t\t\ts_plat_exist( const char *filename );\r\n\tstatic CAsyncFileHandle *\ts_plat_open( const char *filename, int priority );\r\n\tstatic bool\t\t\t\t\ts_plat_close( CAsyncFileHandle *p_file_handle );\r\n\r\n\tstatic void\t\t\t\t\ts_plat_swap_callback_list();\t\t// This is needed below the p-line because interrupts\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// need to be disabled for a bit\r\n\tstatic void\t\t\t\t\ts_plat_update();\r\n\r\n\t// Friends\r\n\tfriend CAsyncFilePoll;\r\n\tfriend CAsyncFileHandle;\r\n};\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// This defines the singleton class for the one-a-frame async calls that are needed.\r\n// For now, just the callbacks that have stacked up in CAsyncFileLoader are called\r\n//\r\nclass CAsyncFilePoll  : public Mdl::Module\r\n{\r\n\tDeclareSingletonClass( CAsyncFilePoll );\r\n\r\n\t\t\tCAsyncFilePoll();\r\n\tvirtual ~CAsyncFilePoll();\r\n\r\n\tvoid v_start_cb ( void );\r\n\tvoid v_stop_cb ( void );\r\n\t\r\n\tstatic Tsk::Task< CAsyncFilePoll >::Code s_logic_code;       \r\n\tTsk::Task< CAsyncFilePoll > *mp_logic_task;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline void\t\t\t\tCAsyncFileLoader::s_inc_manager_busy_count()\r\n{\r\n\ts_manager_busy_count++;\r\n}\r\n\r\ninline void\t\t\t\tCAsyncFileLoader::s_dec_manager_busy_count()\r\n{\r\n\ts_manager_busy_count--;\r\n}\r\n\r\ninline volatile int\t\tCAsyncFileHandle::inc_busy_count()\r\n{\r\n\tCAsyncFileLoader::s_inc_manager_busy_count();\t\t\t// Also increment manager\r\n\treturn ++m_busy_count;\r\n}\r\n\r\ninline volatile int\t\tCAsyncFileHandle::dec_busy_count()\r\n{\r\n\tCAsyncFileLoader::s_dec_manager_busy_count();\t\t\t// Also decrement manager\r\n\treturn --m_busy_count;\r\n}\r\n\r\ninline volatile int\t\tCAsyncFileHandle::get_busy_count()\r\n{\r\n\treturn m_busy_count;\r\n}\r\n\r\n} // namespace File\r\n\r\n#endif  // __SYS_FILE_ASYNC_FILESYS_H\r\n"
  },
  {
    "path": "Code/Sys/File/AsyncTypes.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tFile\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t09/24/02\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/AsyncFilesys.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_FILE_ASYNC_TYPES_H\r\n#define\t__SYS_FILE_ASYNC_TYPES_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define   \tDEFAULT_MEMORY_TYPE\t\t(0)\r\n\r\nnamespace File\r\n{\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nenum EAsyncMemoryType\t// This belongs below the p-line, but need to think of a general way communicate\r\n{\t\t\t\t\t\t// this above the p-line.\r\n#ifdef __PLAT_NGPS__\r\n\tMEM_EE = DEFAULT_MEMORY_TYPE,\r\n\tMEM_IOP,\r\n#endif // __PLAT_NGPS__\r\n\r\n#ifdef __PLAT_NGC__\r\n\tMEM_DRAM = DEFAULT_MEMORY_TYPE,\r\n\tMEM_ARAM,\r\n#endif // __PLAT_NGC__\r\n\r\n#ifdef __PLAT_XBOX__\r\n\tMEM_MAIN = DEFAULT_MEMORY_TYPE,\t\t// Only 1 type for XBox\r\n#endif //__PLAT_XBOX__\r\n};\r\n\r\nenum EAsyncFunctionType\r\n{\r\n\tFUNC_IDLE,\r\n\tFUNC_OPEN,\r\n\tFUNC_LOAD,\r\n\tFUNC_READ,\r\n\tFUNC_WRITE,\r\n\tFUNC_SEEK,\r\n\tFUNC_CLOSE,\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n} // namespace File\r\n\r\n#endif  // __SYS_FILE_ASYNC_TYPES_H\r\n"
  },
  {
    "path": "Code/Sys/File/FileLibrary.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         File\r\n//* FILENAME:       FileLibrary.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  01/21/2003\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sys/file/filelibrary.h>\r\n\r\n#include <sys/file/asyncfilesys.h>\r\n#include <sys/file/filesys.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/script.h>\r\n\r\n#include <sys/mem/memman.h>\r\n\r\n#ifdef __PLAT_NGC__\r\n#include <gel/music/music.h>\r\n#include <sys/ngc/p_aram.h>\r\n#include <sys/ngc/p_dma.h>\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace File\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstruct SLibHeader\r\n{\r\n\tuint32\tversionNumber;\r\n\tint\t\tnumFiles;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid filesync_async_callback(File::CAsyncFileHandle*, File::EAsyncFunctionType function, int result, unsigned int arg0, unsigned int arg1)\r\n{\r\n\t// Dbg_Message(\"Got callback from %x\", arg0);\r\n\tif (function == File::FUNC_READ)\r\n\t{\r\n\t\tCFileLibrary* p_data = (CFileLibrary*)arg0;\r\n\t\tbool assertOnFail = (bool)arg1;\r\n\r\n\t\tp_data->PostLoad( assertOnFail, result );\r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t   \r\nCFileLibrary::CFileLibrary()\r\n{\r\n#ifndef __PLAT_NGC__\r\n\tmp_baseBuffer = NULL;\r\n\tmp_fileBuffer = NULL;\r\n#endif\t\t// __PLAT_NGC__\r\n\tmp_fileHandle = NULL;\r\n\tm_dataLoaded = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCFileLibrary::~CFileLibrary()\r\n{\r\n#ifdef __PLAT_NGC__\r\n\tNsARAM::free( m_aramOffset );\r\n#else\r\n\tif ( mp_baseBuffer )\r\n\t{\r\n\t\tMem::Free( mp_baseBuffer );\r\n\t\tmp_baseBuffer = NULL;\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\t\r\n\tif ( mp_fileHandle )\r\n\t{\r\n\t\tDbg_MsgAssert( m_dataLoaded, ( \"Can't delete CFileLibrary while it is still being loaded\" ) );\r\n\t\tFile::CAsyncFileLoader::sClose( mp_fileHandle );\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t   \r\nbool CFileLibrary::LoadFinished() const\r\n{\r\n\treturn m_dataLoaded;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CFileLibrary::PostLoad( bool assertOnFail, int file_size )\r\n{\r\n\t// Handle end of async, if that was used\r\n\tif ( mp_fileHandle )\r\n\t{\r\n\t\tFile::CAsyncFileLoader::sClose( mp_fileHandle );\r\n\t\tmp_fileHandle = NULL;\r\n\t}\r\n\t\r\n\tDbg_MsgAssert( (file_size & 0x3) == 0, ( \"Size of file is not multiple of 4 (%d bytes)\", file_size ) );\r\n\r\n#ifdef __PLAT_NGC__\r\n#define XFER_SIZE ( sizeof( SLibHeader ) + ( vMAX_LIB_FILES * sizeof( SFileInfo ) ) )\r\n\tchar buffer[ XFER_SIZE ];\r\n\r\n\tNsDMA::toMRAM( buffer, m_aramOffset, XFER_SIZE );\r\n\r\n\tuint8 *pFileData = (uint8*)buffer; \r\n#else\r\n\tuint8 *pFileData = (uint8*)mp_fileBuffer;\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\tSLibHeader* pHeader = (SLibHeader*)pFileData;\r\n\t\r\n\tpFileData += sizeof( SLibHeader );\r\n#ifndef __PLAT_NGC__\r\n\tif ( pFileData > ( mp_fileBuffer + file_size ) )\r\n\t{\r\n\t\t// out of bounds\r\n\t\tgoto load_fail;\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\tm_numFiles = pHeader->numFiles;\r\n\r\n#ifndef __PLAT_NGC__\r\n\tDbg_MsgAssert( m_numFiles > 0, ( \"No files found in lib mp_fileBuffer = %p\", mp_fileBuffer ) );\r\n    Dbg_MsgAssert( m_numFiles < vMAX_LIB_FILES, ( \"Too many subfiles found in lib (%d files, max=%d)\", m_numFiles, vMAX_LIB_FILES ) );\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\t// read in table of contents information\r\n\tmemcpy( &m_fileInfo, pFileData, (sizeof(SFileInfo) * m_numFiles) );\r\n\tpFileData += (sizeof(SFileInfo) * m_numFiles);\r\n#ifndef __PLAT_NGC__\r\n\tif ( pFileData > ( mp_fileBuffer + file_size ) )\r\n\t{\r\n\t\t// out of bounds\r\n\t\tgoto load_fail;\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\t\r\n\tfor ( int i = 0; i < m_numFiles; i++ )\r\n\t{\r\n#ifdef __PLAT_NGC__\r\n\t\tm_fileOffsets[i] = (uint32)(m_aramOffset + m_fileInfo[i].fileOffset);\r\n\t\tmp_filePointers[i] = NULL;\r\n#else\r\n\t\tmp_filePointers[i] = (uint32*)(mp_fileBuffer + m_fileInfo[i].fileOffset);\r\n#endif\t\t// __PLAT_NGC__\r\n\t\tDbg_Message( \"File %d @ %08x %s [%d bytes]\", i, m_fileInfo[i].fileNameChecksum, Script::FindChecksumName(m_fileInfo[i].fileExtensionChecksum), m_fileInfo[i].fileSize );\r\n\t}\r\n\t\r\n#ifndef __PLAT_NGC__\r\n\t// to reduce the amount of temp memory needed, we first load the LIB file\r\n\t// on the bottom up heap, and then copy sub-file individually onto the top\r\n\t// down heap (as we reallocate shrink the original LIB file on the bottom up heap)\r\n\tfor ( int i = m_numFiles - 1; i >= 0; i-- )\r\n\t{\r\n\t\tint file_size = m_fileInfo[i].fileSize;\r\n\t\t\r\n\t\tuint32* pTempFilePointer = mp_filePointers[i];\r\n\t\t\r\n\t\t// GJ:  When I first wrote this class, I wanted to make it generic, \r\n\t\t// but it gradually became more cutscene-specific to fix\r\n\t\t// memory issues.  For example, the following uses the\r\n\t\t// \"cutscene heap\" to reduce temp memory overhead.  Perhaps\r\n\t\t// later on, I can just store the appropriate top/bottomheap pointers\r\n\t\t// during initialization\r\n\t\tDbg_MsgAssert( Mem::Manager::sHandle().CutsceneTopDownHeap(), ( \"No cutscene heap?\" ) ); \r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().CutsceneTopDownHeap());\r\n\t\tmp_filePointers[i] = (uint32*)Mem::Malloc( file_size );\r\n\t\tmemcpy( mp_filePointers[i], pTempFilePointer, file_size );\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n#ifdef\t__NOPT_ASSERT__\r\n\t\tuint8* pOldBuffer = mp_baseBuffer;\r\n#endif\r\n\t\t\r\n\t\tDbg_MsgAssert( Mem::Manager::sHandle().CutsceneBottomUpHeap(), ( \"No cutscene heap?\" ) ); \r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().CutsceneBottomUpHeap());\r\n\t\tmp_baseBuffer = (uint8*)Mem::ReallocateShrink( Mem::GetAllocSize(mp_baseBuffer) - file_size, mp_baseBuffer );\r\n\t\tDbg_MsgAssert( mp_baseBuffer == pOldBuffer, ( \"Pointer was not supposed to change except for shrinking\" ) );\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\r\n\t// by this point, all that should be left in the original block\r\n\t// is the header, which we don't need any more\r\n\tMem::Free( mp_baseBuffer );\r\n\tmp_baseBuffer = NULL;\r\n\tmp_fileBuffer = NULL;\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\t// if the data is ready to be accessed\r\n\tm_dataLoaded = true;\r\n\r\n\treturn true;\r\n\r\n#ifndef __PLAT_NGC__\r\nload_fail:\r\n\tDbg_MsgAssert( 0, ( \"Parsing of library failed\" ) );\r\n\treturn false;\r\n#endif\t\t// __PLAT_NGC__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CFileLibrary::Load( const char* p_fileName, bool assertOnFail, bool async_load )\r\n{\r\n#ifndef __PLAT_NGC__\r\n\t// See Garrett, Garrett, or Mick for explanation.\r\n\t\r\n\tDbg_MsgAssert( !async_load, ( \"Cutscenes aren't supposed to be async loaded anymore\" ) );\r\n\tint file_size;\r\n\t\r\n\tDbg_MsgAssert( Mem::Manager::sHandle().CutsceneBottomUpHeap(), ( \"No cutscene heap?\" ) ); \r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().CutsceneBottomUpHeap());\r\n\t\r\n\tmp_baseBuffer = (uint8*)LoadAlloc( p_fileName, &file_size );\r\n\tmp_fileBuffer = mp_baseBuffer;\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n\treturn PostLoad(assertOnFail, file_size);\r\n#endif\r\n\r\n#ifdef __PLAT_NGC__\r\n\t// Make sure music is off here as we really need the memory.\r\n//\tPcm::StopMusic();\r\n\r\n\tasync_load = false;\r\n#else\r\n\t// Turn off async for platforms that don't support it\r\n\tif (!File::CAsyncFileLoader::sAsyncSupported())\r\n\t{\r\n\t\tasync_load = false;\r\n\t}\r\n\t\r\n\tif ( async_load )\r\n\t{\r\n\t\t// Pre-load\r\n\t\tDbg_Assert( !mp_fileHandle );\r\n\r\n\t\tmp_fileHandle = File::CAsyncFileLoader::sOpen( p_fileName, !async_load );\r\n\r\n\t\t// make sure the file is valid\r\n\t\tif ( !mp_fileHandle )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( assertOnFail, ( \"Load of %s failed - file not found?\", p_fileName ) );\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tint file_size = mp_fileHandle->GetFileSize();\r\n\r\n\t\tif ( file_size == 0 )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, (\"Library file %s size is 0 (possibly not found?)\", p_fileName) );\r\n\t\t\tFile::CAsyncFileLoader::sClose( mp_fileHandle );\r\n\t\t\tmp_fileHandle = NULL;\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tDbg_Assert( !mp_fileBuffer );\r\n\t\tDbg_Assert( !mp_baseBuffer );\r\n\t\t\r\n\t\t// to reduce the amount of temp memory needed, we first load the LIB file\r\n\t\t// on the bottom up heap, and then copy sub-file individually onto the top\r\n\t\t// down heap (as we reallocate shrink the original LIB file on the bottom up heap)\r\n\t\tDbg_MsgAssert( Mem::Manager::sHandle().CutsceneBottomUpHeap(), ( \"No cutscene heap?\" ) ); \r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().CutsceneBottomUpHeap());\r\n\t\tmp_baseBuffer = (uint8*) Mem::Malloc( file_size + 64 );\r\n\t\tmp_fileBuffer = (uint8*)(((uint32)mp_baseBuffer+63)&~63);\r\n\t\tmp_fileBuffer = mp_baseBuffer;\t\t// Garrett: De-aligning pointer since async filesystem should take care of it.\t\t\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t// Set the callback\r\n\t\tmp_fileHandle->SetCallback( filesync_async_callback, (unsigned int)this, (unsigned int)assertOnFail );\r\n\r\n\t\t// read the file in\r\n\t\tmp_fileHandle->Read( mp_fileBuffer, 1, file_size );\r\n\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n#endif\t\t// __PLAT_NGC__\r\n\t{\t\t\t\t   \r\n\t\t// open the file as a stream\r\n\t\tvoid* pStream = File::Open( p_fileName, \"rb\" );\r\n\t\r\n\t\t// make sure the file is valid\r\n\t\tif ( !pStream )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( assertOnFail, (\"Load of %s failed - file not found?\", p_fileName) );\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tint file_size = File::GetFileSize( pStream );\r\n\t\tDbg_MsgAssert( file_size, ( \"Library file size is 0\" ) );\r\n\t\t\r\n#ifndef __PLAT_NGC__\r\n\t\tDbg_Assert( !mp_fileBuffer );\r\n\t\tDbg_Assert( !mp_baseBuffer );\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\r\n#ifdef __PLAT_NGC__\r\n\t\t// Allocate ARAM\r\n\t\tm_aramOffset = NsARAM::alloc( file_size, NsARAM::TOPDOWN );\r\n\r\n#define BUFFER_SIZE ( 16 * 1024 )\r\n\r\n\t\t// read the file in blocks & transfer to ARAM\r\n\t\tchar buffer[BUFFER_SIZE];\r\n\t\tint size = file_size;\r\n\t\tuint32 offset = m_aramOffset;\r\n\r\n\t\twhile ( size > BUFFER_SIZE )\r\n\t\t{\r\n\t\t\tFile::Read( buffer, 1, BUFFER_SIZE, pStream );\r\n\t\t\tNsDMA::toARAM( offset, buffer, BUFFER_SIZE );\r\n\r\n\t\t\tsize -= BUFFER_SIZE;\r\n\t\t\toffset += BUFFER_SIZE;\r\n\t\t}\r\n\r\n\t\t// Read & transfer last bit.\r\n\t\tif ( size )\r\n\t\t{\r\n\t\t\tFile::Read( buffer, 1, size, pStream ); \r\n\t\t\tNsDMA::toARAM( offset, buffer, size );\r\n\t\t}\r\n//\t\tmp_baseBuffer = (uint8*)Mem::Malloc( file_size );\r\n//\t\tmp_fileBuffer = mp_baseBuffer;\r\n#else\r\n\t\t// to reduce the amount of temp memory needed, we first load the LIB file\r\n\t\t// on the bottom up heap, and then copy sub-file individually onto the top\r\n\t\t// down heap (as we reallocate shrink the original LIB file on the bottom up heap)\r\n\t\tDbg_MsgAssert( Mem::Manager::sHandle().CutsceneBottomUpHeap(), ( \"No cutscene heap?\" ) ); \r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().CutsceneBottomUpHeap());\r\n\t\tmp_baseBuffer = (uint8*)Mem::Malloc( file_size );\r\n\t\tmp_fileBuffer = mp_baseBuffer;\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\r\n\t\t// read the file in\r\n\t\tif ( !File::Read( mp_fileBuffer, 1, file_size, pStream ) )\r\n\t\t{\r\n\t\t\tMem::Free( mp_fileBuffer );\r\n\t\t\tmp_baseBuffer = NULL;\r\n\t\t\tmp_fileBuffer = NULL;\r\n\t\t\tFile::Close( pStream );\r\n\r\n\t\t\tDbg_MsgAssert( assertOnFail, ( \"Load of %s failed - bad format?\", p_fileName ) );\r\n\t\t\treturn false;\r\n\t\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\t\tFile::Close(pStream);\r\n\r\n\t\treturn PostLoad(assertOnFail, file_size);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t   \r\nint CFileLibrary::GetNumFiles() const \r\n{\r\n\treturn m_numFiles;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t   \r\nuint32* CFileLibrary::GetFileData( int index )\r\n{\r\n\tDbg_MsgAssert( index >= 0 && index < m_numFiles, ( \"Out of range file index %d\", index ) );\r\n\r\n#ifdef __PLAT_NGC__\r\n\tif ( !mp_filePointers[index] )\r\n\t{\r\n\t\t// Allocate memory & copy over.\r\n//\t\tDbg_MsgAssert( Mem::Manager::sHandle().CutsceneTopDownHeap(), ( \"No cutscene heap?\" ) ); \r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().CutsceneTopDownHeap());\r\n\r\n\t\tint mem_available;\r\n\t\tbool need_to_pop = false;\r\n\t\tint size = m_fileInfo[index].fileSize;\r\n\r\n\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().AudioHeap() );\r\n\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\tif ( size < ( mem_available - ( 15 * 1024 ) ) )\r\n\t\t{\r\n\t\t\tneed_to_pop = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().FrontEndHeap() );\r\n\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\tif ( size < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t{\r\n\t\t\t\tneed_to_pop = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ThemeHeap() );\r\n\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\tif ( size < ( mem_available - ( 5 * 1024 ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\tMem::Manager::sHandle().PushContext( Mem::Manager::sHandle().ScriptHeap() );\r\n\t\t\t\t\tmem_available = Mem::Manager::sHandle().Available();\r\n\t\t\t\t\tif ( size < ( mem_available - ( 40 * 1024 ) ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tneed_to_pop = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tmp_filePointers[index] = (uint32*)Mem::Malloc( m_fileInfo[index].fileSize );\r\n\t\tNsDMA::toMRAM( mp_filePointers[index], m_fileOffsets[index], m_fileInfo[index].fileSize );\r\n\r\n\t\tif ( need_to_pop )\r\n\t\t{\r\n\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t}\r\n\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\treturn mp_filePointers[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t   \r\nconst SFileInfo* CFileLibrary::GetFileInfo( int index ) const\r\n{\r\n\tDbg_MsgAssert( index >= 0 && index < m_numFiles, ( \"Out of range file index %d\", index ) );\r\n\r\n\treturn &m_fileInfo[index];\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t   \r\nconst SFileInfo* CFileLibrary::GetFileInfo( uint32 name, uint32 extension, bool assertOnFail ) const\r\n{\r\n\tfor ( int index = 0; index < m_numFiles; index++ )\r\n\t{\r\n\t\tif ( m_fileInfo[index].fileNameChecksum == name && m_fileInfo[index].fileExtensionChecksum == extension )\r\n\t\t{\r\n\t\t\treturn &m_fileInfo[index];\r\n\t\t}\r\n\t}\r\n\r\n\tif ( assertOnFail )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Couldn't find file %08x %08x\\n\", name, extension ) );\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t   \r\nuint32* CFileLibrary::GetFileData( uint32 name, uint32 extension, bool assertOnFail )\r\n{\r\n\tfor ( int index = 0; index < m_numFiles; index++ )\r\n\t{\r\n\t\tif ( m_fileInfo[index].fileNameChecksum == name && m_fileInfo[index].fileExtensionChecksum == extension )\r\n\t\t{\r\n\t\t\treturn GetFileData( index );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( assertOnFail )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Couldn't find file %08x %08x\\n\", name, extension ) );\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t   \r\nbool CFileLibrary::ClearFile( uint32 name, uint32 extension )\r\n{\r\n\tbool success = false;\r\n\r\n\tfor ( int index = 0; index < m_numFiles; index++ )\r\n\t{\r\n\t\tif ( m_fileInfo[index].fileNameChecksum == name && m_fileInfo[index].fileExtensionChecksum == extension )\r\n\t\t{\r\n\t\t\tMem::Free( mp_filePointers[index] );\r\n\t\t\tmp_filePointers[index] = NULL;\r\n\t\t\tsuccess = true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn success;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t   \r\nbool CFileLibrary::FileExists( uint32 name, uint32 extension )\r\n{\r\n\tfor ( int index = 0; index < m_numFiles; index++ )\r\n\t{\r\n\t\tif ( m_fileInfo[index].fileNameChecksum == name && m_fileInfo[index].fileExtensionChecksum == extension )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\t\t\t   \r\n} // namespace File\r\n"
  },
  {
    "path": "Code/Sys/File/FileLibrary.h",
    "content": "//****************************************************************************\r\n//* MODULE:         File\r\n//* FILENAME:       FileLibrary.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  01/21/2003\r\n//****************************************************************************\r\n\r\n#ifndef __SYS_FILE_FILELIBRARY_H\r\n#define __SYS_FILE_FILELIBRARY_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n\r\nnamespace File\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\tclass CAsyncFileHandle;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstruct SFileInfo\r\n{\r\n\tuint32\tfileOffset;\r\n\tint\t\tfileSize;\r\n\tuint32\tfileNameChecksum;\r\n\tuint32\tfileExtensionChecksum;\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass CFileLibrary : public Spt::Class\r\n{\r\nprotected:\r\n\tenum\r\n\t{\r\n\t\tvMAX_LIB_FILES = 128\r\n\t};\r\n\r\npublic:\r\n\tCFileLibrary();\r\n\tvirtual \t\t\t~CFileLibrary();\r\n\r\npublic:\r\n\tbool \t\t\t\tLoad( const char* p_fileName, bool assertOnFail, bool async_load );\r\n\tbool\t\t\t\tPostLoad( bool assertOnFail, int file_size );\r\n\tbool\t\t\t\tLoadFinished() const;\r\n\r\npublic:\r\n\tint\t\t\t\t\tGetNumFiles() const;\r\n\tuint32*\t\t\t\tGetFileData( int index );\r\n\tuint32*\t\t\t\tGetFileData( uint32 name, uint32 extension, bool assertOnFail = true );\r\n\tconst SFileInfo*\tGetFileInfo( int index ) const;\r\n\tconst SFileInfo*\tGetFileInfo( uint32 name, uint32 extension, bool assertOnFail = true ) const;\r\n\tbool\t\t\t\tClearFile( uint32 name, uint32 extension );\r\n\tbool\t\t\t\tFileExists( uint32 name, uint32 extension );\r\n\r\nprotected:\r\n\tCAsyncFileHandle*\tmp_fileHandle;\r\n#ifdef __PLAT_NGC__\r\n\tuint32\t\t\t\tm_aramOffset;\r\n#else\r\n\tuint8* \t\t\t\tmp_baseBuffer;\r\n\tuint8* \t\t\t\tmp_fileBuffer;\r\n#endif\t\t// __PLAT_NGC__\r\n\tint\t\t\t\t\tm_numFiles;\r\n\tint\t\t\t\t\tm_originalNumFiles;\r\n\tSFileInfo\t\t\tm_fileInfo[vMAX_LIB_FILES];\r\n#ifdef __PLAT_NGC__\r\n\tuint32\t\t\t\tm_fileOffsets[vMAX_LIB_FILES];\r\n#endif\t\t// __PLAT_NGC__\r\n\tuint32*\t\t\t\tmp_filePointers[vMAX_LIB_FILES];\r\n\tbool\t\t\t\tm_dataLoaded;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace File\r\n\r\n#endif\t// __SYS_FILE_FILELIBRARY_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/PRE.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tskate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\t\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\trjm\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// start autoduck documentation\r\n// @DOC pre\r\n// @module pre | None\r\n// @subindex Scripting Database\r\n// @index script | pre\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#include <eekernel.h>\r\n#endif\t\t//\t__PLAT_NGPS__\r\n#include <core/defines.h>\r\n//#include <core/HashTable.h>\r\n#include <core/StringHashTable.h>\r\n#include <sys/File/PRE.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/AsyncFilesys.h>\r\n#include <sys/config/config.h>\r\n\r\n// cd shared by the music streaming stuff...  ASSERT if file access attempted\r\n// while music is streaming:\r\n#include <gel/music/music.h>\r\n\r\n// script stuff\r\n#include <gel/scripting/struct.h> \r\n#include <gel/scripting/symboltable.h>\r\n\r\n#ifdef __PLAT_NGC__\r\n#include \"sys/ngc/p_aram.h\"\r\n#include \"sys/ngc/p_dma.h\"\r\n#include \"sys/ngc/p_display.h\"\r\n#ifdef __NOPT_FINAL__\r\n#define __PRE_ARAM__\r\n#endif\t\t// __NOPT_FINAL__\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define DEBUG_PRE 0\r\n\r\n#define\tPRE_NAME_OFFSET 16\t\t// was 12, but then I added an extra checksum field\r\n\r\nnamespace File\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define CURRENT_PRE_VERSION\t0xabcd0003\t\t\t// as of 3/14/2001\r\n//#define CURRENT_PRE_VERSION\t0xabcd0001\t\t// until 3/14/2001\r\n\r\n#define RINGBUFFERSIZE\t\t 4096\t/* N size of ring buffer */\t\r\n#define MATCHLIMIT\t\t   18\t/* F upper limit for match_length */\r\n#define THRESHOLD\t2   /* encode string into position and length */\r\n\r\n#define WriteOut(x) \t{*pOut++ = x;}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nPreMgr *PreMgr::sp_mgr = NULL;\r\nbool    PreMgr::s_lastExecuteSuccess = false; \r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n#define USE_BUFFER\t1\t\t // we don't need no stinking buffer!!!!\r\n \r\n#if USE_BUFFER\r\n#ifdef\t__PLAT_NGPS__\r\n// ring buffer is just over 4K 4096+17), \r\n// so fits nicely in the PS2's 16K scratchpad \r\nunsigned char\ttext_buf[RINGBUFFERSIZE + MATCHLIMIT - 1];\t\r\n// Note:  if we try to use the scratchpad, like this\r\n// then the code actually runs slower\r\n// if we want to optimize this, then it should\r\n// be hand crafted in assembly, using 128bit registers\r\n//\tconst unsigned char * text_buf = (unsigned char*) 0x70000000;\r\n//\t#define text_buf ((unsigned char*) 0x70000000)\r\n#else\r\nunsigned char\r\n\t\ttext_buf[RINGBUFFERSIZE + MATCHLIMIT - 1];\t/* ring buffer of size N,\r\n\t\t\twith extra F-1 bytes to facilitate string comparison */\r\n#endif\r\n#endif\r\n\r\n\r\n#ifdef __PRE_ARAM__\r\n#define\tReadInto(x)\t\tif (!Len) break; Len--; x = get_byte( p_buffer ) \r\n#define\tReadInto2(x)\tLen--; x = get_byte( p_buffer ) \t  // version that knows Len is Ok\r\n#else\r\n#define\tReadInto(x)\t\tif (!Len) break; Len--; x = *pIn++ \r\n#define\tReadInto2(x)\tLen--; x = *pIn++ \t  // version that knows Len is Ok\r\n#endif\t\t// __PRE_ARAM__\r\n\r\n\r\n// Decode an LZSS encoded stream\r\n// Runs at approx 12MB/s on PS2\t without scratchpad (which slows it down in C)\r\n// a 32x CD would run at 4.8MB/sec, although we seem to get a lot less than this\r\n// with our current file system, more like 600K per seconds.....\r\n// Need to write a fast streaming file system....\r\n\r\n#ifdef __PRE_ARAM__\r\n#define INPUT_BUFFER_SIZE (16 * 1024)\r\nstatic uint32 p_aram_in;\r\nstatic int aram_len = 0;\r\nstatic int buffer_bytes = 0;\r\nstatic int buffer_offset = 0;\r\nstatic unsigned char get_byte( unsigned char * p_buffer )\r\n{\r\n\tif ( buffer_bytes == 0 )\r\n\t{\r\n\t\tint toread;\r\n\t\tif ( aram_len >= INPUT_BUFFER_SIZE )\r\n\t\t{\r\n\t\t\ttoread = INPUT_BUFFER_SIZE;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttoread = aram_len;\r\n\t\t}\r\n\r\n\t\tNsDMA::toMRAM( p_buffer, p_aram_in, toread );\r\n\t\tp_aram_in += INPUT_BUFFER_SIZE;\r\n\t\taram_len -= INPUT_BUFFER_SIZE;\r\n\t\tbuffer_bytes = toread; \r\n\t\tbuffer_offset = 0;\r\n\t}\r\n\tunsigned char bb = p_buffer[buffer_offset];\r\n\tbuffer_bytes--;\r\n\tbuffer_offset++;\r\n\treturn bb;\r\n}\r\n#endif\t\t// __PRE_ARAM__\r\n\r\nvoid DecodeLZSS(unsigned char *pIn, unsigned char *pOut, int Len)\t/* Just the reverse of Encode(). */\r\n{\r\n\tint  i, j, k, r, c;\r\n//\tuint64\tLongWord;\r\n//\tint bytes = 0;\r\n//\tunsigned char *pScratch;\r\n\tunsigned int  flags;\r\n\r\n\t// Ensure we have decent values for the decode length\r\n\tDbg_Assert(( Len >= 0 ) && ( Len < 0x2000000 ));\r\n\r\n\tif(( Len < 0 ) || ( Len >= 0x2000000 ))\r\n\t{\r\n\t\twhile( 1 );\r\n\t}\r\n#ifdef __PRE_ARAM__\r\n\tunsigned char p_buffer[INPUT_BUFFER_SIZE];\r\n\tp_aram_in = (uint32)pIn;\r\n\taram_len = Len;\r\n#endif\t\t// __PRE_ARAM__\r\n\r\n\r\n//\tint basetime =  (int) Tmr::ElapsedTime(0);\r\n//\tint len = Len;\r\n\r\n//\tint\tOutBytes = 4;\r\n//\tint\tOutWord = 0;\r\n\r\n\t#if USE_BUFFER\r\n\tfor (i = 0; i < RINGBUFFERSIZE - MATCHLIMIT; i++)\r\n\t\t text_buf[i] = ' ';\r\n\tr = RINGBUFFERSIZE - MATCHLIMIT;\r\n\t#else\r\n\tr = RINGBUFFERSIZE - MATCHLIMIT;\r\n\t#endif\r\n\tflags = 0;\r\n\tfor ( ; ; )\r\n\t{\r\n\t\tif (((flags >>= 1) & 256) == 0)\r\n\t\t{\r\n\t\t\tReadInto(c);\r\n\t\t\tflags = c | 0xff00;\t\t\t/* uses higher byte cleverly */\r\n\t\t}\t\t\t\t\t\t\t\t\t\t/* to count eight */\r\n\t\tif (flags & 1)\r\n\t\t{\r\n\t\t\tReadInto(c);\r\n\t\t\t//\t\t\tputc(c, outfile);\r\n\t\t\tWriteOut(c);\r\n\t\t\t#if USE_BUFFER\r\n\t\t\ttext_buf[r++] = c;\r\n\t\t\tr &= (RINGBUFFERSIZE - 1);\r\n\t\t\t#else\r\n\t\t\tr++;\r\n//\t\t\tr &= (RINGBUFFERSIZE - 1);\t  // don't need to wrap r until it is used\r\n\t\t\t#endif\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tReadInto(i);\t\t\t\r\n\t\t\tReadInto2(j);\t\t\t// note, don't need to check len on this one.... \r\n\t\t\t\r\n\t\t\ti |= ((j & 0xf0) << 4);\t\t\t\t\t\t// i is 12 bit offset\r\n\t\t\t\r\n\t\t\t#if !USE_BUFFER\r\n\t\t\tj = (j & 0x0f) + THRESHOLD+1;\t\t\t\t// j is 4 bit length (above the threshold)\r\n\t\t\tunsigned char *pStream;\r\n\t\t\tr &= (RINGBUFFERSIZE - 1);\t\t\t\t\t// wrap r around before it is used\r\n\t\t\tpStream = pOut - r;\t\t\t\t\t  \t\t// get base of block\r\n\t\t\tif (i>=r)\t\t\t\t\t\t\t\t\t\t// if offset > r, then\r\n\t\t\t\tpStream -= RINGBUFFERSIZE;\t\t\t\t// it's the previous block\r\n\t\t\tpStream += i;\t\t\t\t\t\t\t\t\t// add in the offset to the base\r\n\t\t\tr+=j;\t\t\t\t\t\t\t\t\t\t\t\t// add size to r\r\n\t\t\twhile (j--)\t\t\t\t\t\t\t\t\t\t// copy j bytes\r\n\t\t\t\tWriteOut(*pStream++);\r\n\t\t\t#else\r\n\t\t\t\r\n\t\t\tj = (j & 0x0f) + THRESHOLD;\t\t\t\t// j is 4 bit length (above the threshold)\r\n\t\t\tfor (k = 0; k <= j; k++)\t\t\t\t\t// just copy the bytes\r\n\t\t\t{\r\n\t\t\t\tc =  text_buf[(i+k) & (RINGBUFFERSIZE - 1)]; \r\n\t\t\t\tWriteOut(c);\r\n\t\t\t\ttext_buf[r++] = c;\r\n\t\t\t\tr &= (RINGBUFFERSIZE - 1);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t}\r\n\t}\r\n//\tint Time = (int) Tmr::ElapsedTime(basetime);\r\n//\tif (Time > 5)\r\n//\t{\r\n//\t\tprintf(\"decomp time is %d ms, for %d bytes,  %d bytes/second\\n\", Time,len, len * 1000 /Time );\r\n//\t}\r\n\r\n}\r\n\r\nvoid EndOfDecodeLZSS( void )\r\n{\r\n} \r\n\r\n\r\nvoid PreFile::s_delete_file(_File *pFile, void *pData)\r\n{\r\n\tDbg_Assert(pFile);\r\n\tdelete pFile;\r\n}\r\n\r\n\r\n\r\n\r\nPreFile::PreFile(uint8 *p_file_buffer, bool useBottomUpHeap)\r\n{\r\n\tm_use_bottom_up_heap=useBottomUpHeap;\r\n\t\r\n\tmp_table = new Lst::StringHashTable<_File>(4);\t\r\n\r\n\tDbg_AssertPtr(p_file_buffer);\r\n\r\n\tmp_buffer = p_file_buffer;\r\n\t#ifdef __NOPT_ASSERT__\r\n#ifdef __PRE_ARAM__\r\n\tuint version;\r\n\tNsDMA::toMRAM( &version, (uint32)mp_buffer + 4, 4 );\r\n#else\r\n\tuint version = \t*((int *) (mp_buffer + 4));\r\n#endif\t\t// __PRE_ARAM__\r\n\tDbg_MsgAssert(version == CURRENT_PRE_VERSION,( \"PRE file version (%x) not current (%x)\",version,CURRENT_PRE_VERSION));\r\n\t#endif\r\n#ifdef __PRE_ARAM__\r\n\tNsDMA::toMRAM( &m_numEntries, (uint32)mp_buffer + 8, 4 );\r\n#else\r\n\tm_numEntries = *((int *)(mp_buffer + 8));\r\n#endif\t\t// __PRE_ARAM__\r\n\r\n\tuint8 *pEntry = mp_buffer + 12;\r\n\tfor (int i = 0; i < m_numEntries; i++)\r\n\t{\r\n#ifdef __PRE_ARAM__\r\n\t\tint data_size;\r\n\t\tint compressed_data_size;\r\n\t\tshort text_size;\r\n\t\tNsDMA::toMRAM( &data_size, (uint32)pEntry, 4 );\r\n\t\tNsDMA::toMRAM( &compressed_data_size, (uint32)pEntry + 4, 4 );\r\n\t\tNsDMA::toMRAM( &text_size, (uint32)pEntry + 8, 2 );\r\n#else\r\n\t\tint data_size \t\t\t\t= *((int *) pEntry);\r\n\t\tint compressed_data_size \t= *((int *) (pEntry + 4));\r\n\t\tint text_size\t \t\t\t= *((short *) (pEntry + 8));\r\n#endif\t\t// __PRE_ARAM__\r\n\t\tint actual_data_size = (compressed_data_size != 0) ? compressed_data_size : data_size;\r\n\t\t\t\r\n#ifdef __PRE_ARAM__\r\n\t\tchar pName[1024];\r\n\t\tNsDMA::toMRAM( pName, (uint32)pEntry + PRE_NAME_OFFSET, text_size );\r\n#else\r\n\t\tchar *pName = (char *) pEntry + PRE_NAME_OFFSET;\r\n#endif\t\t// __PRE_ARAM__\r\n\t\tuint8 *pCompressedData = pEntry + PRE_NAME_OFFSET + text_size;\r\n\t\t\r\n\t\t_File *pFile;\r\n\t\tif (m_use_bottom_up_heap)\r\n\t\t{\r\n\t\t\tpFile = new (Mem::Manager::sHandle().BottomUpHeap()) _File;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpFile = new (Mem::Manager::sHandle().TopDownHeap()) _File;\r\n\t\t}\t\r\n\r\n\t\tif (!mp_table->GetItem(pName)) \r\n\t\t{\r\n\t\t\t// file is not in table, safe to add\r\n\t\t\tmp_table->PutItem(pName, pFile);\r\n\t\t\t\r\n\t\t\tpFile->compressedDataSize = compressed_data_size;\r\n\t\t\tpFile->pCompressedData = pCompressedData; \r\n\t\t\tpFile->pData = NULL;\r\n\t\t\tpFile->m_position = 0;\r\n\t\t\tpFile->m_filesize = data_size;\r\n\t\t}\r\n\t\telse\r\n\t\t\t// Somehow, file is already in table, just kill it\r\n\t\t\t// Later, I'll want to add an assert\r\n\t\t\tdelete pFile;\r\n\t\t\r\n#\t\tif DEBUG_PRE\r\n\t\tprintf(\"   %s, size %d\\n\", pName, data_size);\r\n#\t\tendif\r\n\t\t\r\n\t\tpEntry += PRE_NAME_OFFSET + text_size + ((actual_data_size + 3) & (~3));\r\n\t}\r\n\r\n#\tif DEBUG_PRE\r\n\tprintf(\"Done loading PRE\\n\");\r\n#\tendif\r\n\t\r\n\tmp_activeFile = NULL;\r\n\tm_numOpenAsyncFiles = 0;\r\n}\r\n\r\n\r\n\r\nPreFile::~PreFile()\r\n{\r\n#ifdef __PRE_ARAM__\r\n\tNsARAM::free( (uint32)mp_buffer );\r\n#else\r\n\tdelete mp_buffer;\r\n#endif\t\t// __PRE_ARAM__\r\n\tmp_table->HandleCallback(s_delete_file, NULL);\r\n\tmp_table->FlushAllItems();\r\n\r\n\tdelete mp_table;\r\n\r\n\tDbg_MsgAssert(m_numOpenAsyncFiles == 0, (\"Can't unload Pre because there are still %d async files open\", m_numOpenAsyncFiles));\r\n}\r\n\r\n\r\nbool PreFile::FileExists(const char *pName)\r\n{\r\n\t\r\n\t_File *pFile = mp_table->GetItem(pName, false);\r\n\treturn (pFile != NULL);\r\n}\r\n\r\n// returns handle pointer\r\nPreFile::FileHandle *PreFile::GetContainedFile(const char *pName)\r\n{\r\n\t\r\n\t_File *pFile = mp_table->GetItem(pName, false);\r\n\tif (!pFile) \r\n\t\treturn NULL;\r\n\t\r\n\tPreFile::FileHandle *pHandle = pFile;\r\n\t//// kinda roundabout, but sets mp_activeFile\r\n\tGetContainedFileByHandle(pHandle);\r\n\t\r\n#ifdef __PLAT_NGC__\r\n\tNsDisplay::doReset();\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\t// do we need to fetch file data?\r\n\tif (!mp_activeFile->pData)\r\n\t{\r\n\t\tif (mp_activeFile->compressedDataSize)\r\n\t\t{\r\n\t\t\tMem::PushMemProfile((char*)pName);\r\n\t\t\tif (m_use_bottom_up_heap)\r\n\t\t\t{\r\n\t\t\t\tmp_activeFile->pData = new (Mem::Manager::sHandle().BottomUpHeap()) uint8[mp_activeFile->m_filesize];\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmp_activeFile->pData = new (Mem::Manager::sHandle().TopDownHeap()) uint8[mp_activeFile->m_filesize];\t\t\r\n\t\t\t}\t\r\n\t\t\tMem::PopMemProfile();\r\n\t\t\t// need to uncompress data\r\n\t\t\tDecodeLZSS(mp_activeFile->pCompressedData, mp_activeFile->pData, mp_activeFile->compressedDataSize);\t\r\n\t\t}\r\n#ifdef __PRE_ARAM__\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Just DMA to main RAM.\r\n\t\t\tMem::PushMemProfile((char*)pName);\r\n\t\t\tif (m_use_bottom_up_heap)\r\n\t\t\t{\r\n\t\t\t\tmp_activeFile->pData = new (Mem::Manager::sHandle().BottomUpHeap()) uint8[mp_activeFile->m_filesize];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmp_activeFile->pData = new (Mem::Manager::sHandle().TopDownHeap()) uint8[mp_activeFile->m_filesize];\r\n\t\t\t}\t\r\n\t\t\tMem::PopMemProfile();\r\n\t\t\tNsDMA::toMRAM( mp_activeFile->pData, (uint32)mp_activeFile->pCompressedData, mp_activeFile->m_filesize );\r\n\t\t}\r\n#endif\t\t// __PRE_ARAM__\r\n\t}\r\n\r\n\t\r\n\r\n\treturn pHandle;\r\n}\r\n\r\n\r\n// allocate memory and load file directly from a pre file, if it is there\r\n// This avoids the problem of having to have the decompressed file in memory twice\r\n// when we are loading directly, like with Pip::Load()\r\n// using this enables us to actually load network game, where there is 1MB less heap during loading\r\n//\r\n// returns a pointer to the file in memory\r\n// or NULL if the file is not in this pre file.\r\n// optional parameter p_dest, if set to anything other then NULL, then load file to this destination\r\nvoid *PreFile::LoadContainedFile(const char *pName,int *p_size, void *p_dest)\r\n{\r\n\r\n//\tprintf (\"LoadContainedFile(%s\\n\",pName);\r\n\t\r\n\t_File *pFile = mp_table->GetItem(pName, false);\r\n\tif (!pFile) \r\n\t{\r\n\t\treturn NULL;\r\n\t}\t\r\n\t\r\n\t*p_size = pFile->m_filesize;\r\n\r\n\t// If destination was passed as NULL, then allocate memory\t\r\n\tif (!p_dest)\r\n\t{\r\n\t\tp_dest = Mem::Malloc(pFile->m_filesize);\t\t\r\n\t}\r\n\t\r\n\t// do we need to deompress file data?\r\n\tif (!pFile->pData)\r\n\t{\r\n\t\tif (pFile->compressedDataSize)\r\n\t\t{\r\n\t\t\t// need to uncompress data\r\n\t\t\t//DecodeLZSS(mp_activeFile->pCompressedData, mp_activeFile->pData, mp_activeFile->compressedDataSize);\t\r\n\t\t\tDecodeLZSS(pFile->pCompressedData, (uint8*)p_dest, pFile->compressedDataSize);\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n#ifdef __PRE_ARAM__\r\n\t\t\t// Just DMA to main RAM.\r\n\t\t\tNsDMA::toMRAM( p_dest, (uint32)pFile->pCompressedData, pFile->m_filesize );\r\n#else\r\n\t\t\tmemcpy(p_dest,(void*)pFile->pCompressedData,pFile->m_filesize);\r\n#endif\t\t// __PRE_ARAM__\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n//\t\tprintf (\"Copying %d bytes from %p to %p\\n\",pFile->sky.SOF,p_dest,(void*)pFile->pData);\r\n\t\tmemcpy(p_dest,(void*)pFile->pData,pFile->m_filesize);\r\n\t}\r\n\treturn  p_dest;\r\n}\r\n\t\r\n\r\n\r\nuint8 *PreFile::GetContainedFileByHandle(PreFile::FileHandle *pHandle)\r\n{\r\n\tmp_table->IterateStart();\r\n\t_File *pFile = mp_table->IterateNext();\r\n\twhile(pFile)\r\n\t{\r\n\t\tuint8 *pCompressedData = pFile->pCompressedData;\r\n\t\tif (pCompressedData && pFile == pHandle)\r\n\t\t{\r\n\t\t\tmp_activeFile = pFile;\r\n\t\t\t\r\n\t\t\tif (mp_activeFile->compressedDataSize)\r\n\t\t\t\treturn mp_activeFile->pData;\r\n\t\t\telse\r\n\t\t\t\treturn mp_activeFile->pCompressedData;\r\n\t\t}\r\n\t\tpFile = mp_table->IterateNext();\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\nvoid PreFile::Reset()\r\n{\r\n\t\r\n\tDbg_AssertPtr(mp_activeFile);\r\n\r\n\tmp_activeFile->m_position = 0;\r\n}\r\n\r\n\r\n\r\nuint32 PreFile::Read(void *addr, uint32 count)\r\n{\r\n\t\r\n\tDbg_AssertPtr(mp_activeFile);\r\n\r\n\tint seek_offs = mp_activeFile->m_position;\r\n\tunsigned int limit = mp_activeFile->m_filesize - seek_offs;\r\n\tint copy_number = (count <= limit) ? count : limit; \r\n#ifdef __PRE_ARAM__\r\n\tmemcpy(addr, mp_activeFile->pData + mp_activeFile->m_position, copy_number);\r\n#else\r\n\tif (mp_activeFile->compressedDataSize)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_activeFile->pData,( \"file not uncompressed\"));\r\n\t\tmemcpy(addr, mp_activeFile->pData + mp_activeFile->m_position, copy_number);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmemcpy(addr, mp_activeFile->pCompressedData + mp_activeFile->m_position, copy_number);\r\n\t}\r\n#endif\t\t// __PRE_ARAM__\r\n\r\n\tmp_activeFile->m_position += copy_number;\r\n\r\n#if DEBUG_PRE\r\n\t\tprintf(\"PRE: read %d bytes from file, handle 0x%x\\n\", copy_number, (int) mp_activeFile->pData);\r\n#endif\r\n\treturn copy_number;\r\n}\r\n\r\n\r\n\r\nint PreFile::Eof()\r\n{\r\n\t\r\n\tDbg_AssertPtr(mp_activeFile);\r\n\r\n\tif (mp_activeFile->m_position >= mp_activeFile->m_filesize)\r\n\t{\r\n#if DEBUG_PRE\r\n\t\tprintf(\"PRE: at end of file\\n\");\r\n#endif\r\n\t\treturn 1;\r\n\t}\r\n\r\n#if DEBUG_PRE\r\n\tprintf(\"PRE: not at end of file\\n\");\r\n#endif\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nvoid PreFile::Open(bool async)\r\n{\r\n\tif (async)\r\n\t{\r\n\t\tm_numOpenAsyncFiles++;\r\n\t}\r\n}\r\n\r\nvoid PreFile::Close(bool async)\r\n{\r\n\t\r\n\t//Dbg_MsgAssert(mp_activeFile->pData,( \"file not uncompressed\"));\r\n\r\n\tif (mp_activeFile->pData)\r\n\t\tdelete mp_activeFile->pData;\r\n\tmp_activeFile->pData = NULL;\r\n\r\n\tif (async)\r\n\t{\r\n\t\tm_numOpenAsyncFiles--;\r\n\t\tDbg_MsgAssert(m_numOpenAsyncFiles >= 0, (\"PreFile: m_numOpenAsyncFiles is negative after Close()\"));\r\n\t}\r\n}\r\n\r\n\r\n\r\nint PreFile::Seek(long offset, int origin)\r\n{\r\n\tint32 old_pos = mp_activeFile->m_position;\r\n\r\n\t// SEEK_CUR, SEEK_END, SEEK_SET\r\n\tswitch(origin)\r\n\t{\r\n\t\tcase SEEK_CUR:\r\n\t\t\tmp_activeFile->m_position += offset;\r\n\t\t\tbreak;\r\n\t\tcase SEEK_END:\r\n\t\t\tmp_activeFile->m_position = mp_activeFile->m_filesize - offset;\r\n\t\t\tbreak;\r\n\t\tcase SEEK_SET:\r\n\t\t\tmp_activeFile->m_position = offset;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\treturn -1;\r\n\t}\r\n\r\n\tif (mp_activeFile->m_position < 0 || mp_activeFile->m_position > mp_activeFile->m_filesize)\r\n\t{\r\n\t\tmp_activeFile->m_position = old_pos;\r\n\t\treturn -1;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nPreMgr::PreMgr() \r\n{\r\n\tmp_table = new Lst::StringHashTable<PreFile>(4);\r\n\r\n\tsp_mgr = this;\r\n\r\n\r\n\tmp_activeHandle = NULL;\r\n\tmp_activeData = NULL;\r\n\r\n\tmp_activeNonPreHandle = NULL;\r\n\r\n\tm_num_pending_pre_files = 0;\r\n}\r\n\r\n\r\n\r\nPreMgr::~PreMgr()\r\n{\r\n\tdelete mp_table;\r\n}\r\n\r\n\r\n\r\n// Returns handle\r\n// Not frequently called\r\nPreFile::FileHandle *PreMgr::getContainedFile(const char *pName)\r\n{\r\n\t\r\n\tDbg_AssertPtr(pName);\r\n\r\n\t// replace all '/' with '\\'\r\n\tchar cleaned_name[128];\r\n\tconst char *pCharIn = pName;\r\n\tchar *pCharOut = cleaned_name;\r\n\twhile (1)\r\n\t{\r\n\t\t*pCharOut = *pCharIn;\r\n\t\tif (*pCharIn == '\\0') break;\r\n\t\tif (*pCharOut == '/') *pCharOut = '\\\\';\r\n\t\tpCharIn++;\r\n\t\tpCharOut++;\t\t\r\n\t}\r\n\r\n\tPreFile::FileHandle *pHandle = NULL;\r\n\r\n\tmp_table->IterateStart();\r\n\tPreFile *pPre = mp_table->IterateNext();\r\n\twhile(pPre)\r\n\t{\r\n\t\tpHandle = pPre->GetContainedFile(cleaned_name);\r\n\t\tif (pHandle) \r\n\t\t{\r\n\t\t\tmp_activePre = pPre;\r\n\t\t\tmp_activeHandle = pHandle;\r\n\t\t\tmp_activeData = pPre->GetContainedFileByHandle(pHandle);\r\n#\t\t\tifdef __PLAT_NGPS__\r\n\t\t\tscePrintf(\"+++ %s is in PRE\\n\", cleaned_name);\r\n#\t\t\tendif\r\n\t\t\treturn pHandle;\r\n\t\t}\r\n\t\tpPre = mp_table->IterateNext();\r\n\t}\r\n\r\n#\tifdef __PLAT_NGPS__\r\n\tscePrintf(\"--- %s not found in PRE\\n\", cleaned_name);\r\n#\tendif\r\n\treturn NULL;\r\n}\r\n\r\n// returns true if the file exists in any of the pre files\r\nbool\tPreMgr::fileExists(const char *pName)\r\n{\r\n\tDbg_AssertPtr(pName);\r\n\t// replace all '/' with '\\'\r\n\tchar cleaned_name[128];\r\n\tconst char *pCharIn = pName;\r\n\tchar *pCharOut = cleaned_name;\r\n\twhile (1)\r\n\t{\r\n\t\t*pCharOut = *pCharIn;\r\n\t\tif (*pCharIn == '\\0') break;\r\n\t\tif (*pCharOut == '/') *pCharOut = '\\\\';\r\n\t\tpCharIn++;\r\n\t\tpCharOut++;\t\t\r\n\t}\r\n\r\n\tmp_table->IterateStart();\r\n\tPreFile *pPre = mp_table->IterateNext();\r\n\twhile(pPre)\r\n\t{\r\n\t\tif (pPre->FileExists(cleaned_name))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tpPre = mp_table->IterateNext();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n// returns pointer to data\r\nuint8 *PreMgr::getContainedFileByHandle(PreFile::FileHandle *pHandle)\r\n{\r\n\t\r\n\tDbg_AssertPtr(pHandle);\r\n\r\n\t// if we know that the file in question is not in the PRE system,\r\n\t// then it's a regular file, don't waste time looking for it\r\n\tif (mp_activeNonPreHandle == pHandle)\r\n\t\treturn NULL;\r\n\t\r\n\tif (mp_activeHandle == pHandle)\r\n\t\t// mp_activePre will be unchanged\r\n\t\treturn mp_activeData;\r\n\t\r\n\tuint8 *pData = NULL;\r\n\tmp_table->IterateStart();\r\n\tPreFile *pPre = mp_table->IterateNext();\r\n\twhile(pPre)\r\n\t{\r\n\t\tpData = pPre->GetContainedFileByHandle(pHandle);\r\n\t\tif (pData)\r\n\t\t{\r\n\t\t\tmp_activePre = pPre;\r\n\t\t\tmp_activeHandle = pHandle;\r\n\t\t\tmp_activeData = pData;\t\t\t\r\n\t\t\treturn pData;\r\n\t\t}\r\n\t\tpPre = mp_table->IterateNext();\r\n\t}\r\n\r\n\t// obviously this file is not in the PRE system, mark as such\r\n\tmp_activeNonPreHandle = pHandle;\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n// there's a wrapper around this now, so that we can do\r\n// some memory-context switching\r\nvoid PreMgr::loadPre(const char *pFilename, bool async, bool dont_assert, bool useBottomUpHeap)\r\n{\r\n#ifdef DVDETH\r\n\tm_blockPreLoading = true;\r\n#else\r\n\tm_blockPreLoading = (bool) Script::GetInt(\"block_pre_loading\", false);\r\n#endif\t\t// DVDETH \r\n\r\n\tif (m_blockPreLoading)\r\n\t\treturn;\r\n\r\n\t// Turn off async for platforms that don't support it\r\n\tif (!File::CAsyncFileLoader::sAsyncSupported())\r\n\t{\r\n\t\tasync = false;\r\n\t}\r\n\r\n#ifdef __PRE_ARAM__\r\n\tDbg_MsgAssert(!async, (\"Async loading not implemented for ARAM transfer\"));\r\n#endif\r\n\r\n\tif( !async && Pcm::UsingCD() )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Moved this to below the Pcm::UsingCD() call as that is used (bad!!) to turn off\r\n\t// music and streams.\r\n#\tifdef __PLAT_NGPS__\r\n//\tscePrintf(\"Loading PRE file %s...\\n\", pFilename);\r\n#\tendif\r\n\r\n\tchar fullname[256];\r\n\tsprintf(fullname, \"pre\\\\%s\", pFilename);\r\n\r\n#\tifdef __PLAT_XBOX__\r\n\t// Replace the .pre extension (if one exists) with .prx for Xbox PRE file.\r\n\tif( strrchr( pFilename, '.' ) && ( strlen( fullname ) > 4 ))\r\n\t{\r\n\t\tfullname[strlen( fullname ) - 1] = 'x';\r\n\t}\r\n#\tendif\r\n\r\n#\tif !defined( __PLAT_NGC__ ) || ( defined( __PLAT_NGC__ ) && !defined( __NOPT_FINAL__ ) )\r\n\tTmr::Time basetime = Tmr::ElapsedTime(0);\r\n#endif\r\n\r\n\tint file_size;\r\n\tuint8 *pFile = NULL;\r\n\r\n\t// Try loading asynchronously\r\n\tif (async)\r\n\t{\r\n\t\tDbg_MsgAssert(m_num_pending_pre_files < MAX_NUM_ASYNC_LOADS, (\"Too many async LoadPre's pending\"));\r\n\r\n\t\tCAsyncFileHandle *p_fileHandle = CAsyncFileLoader::sOpen( fullname, !async );\r\n\t\tif (p_fileHandle)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(strlen(pFilename) < MAX_COMPACT_FILE_NAME, (\"Pre file name %s is greater than %d bytes\", pFilename, MAX_COMPACT_FILE_NAME - 1));\r\n\r\n\t\t\t// Add to pending list\r\n\t\t\tstrcpy(m_pending_pre_files[m_num_pending_pre_files].m_file_name, pFilename);\r\n\t\t\tm_pending_pre_files[m_num_pending_pre_files++].mp_file_handle = p_fileHandle;\r\n\r\n\t\t\tfile_size = p_fileHandle->GetFileSize();\r\n\t\t\tDbg_MsgAssert(file_size, (\"Pre file size is 0\"));\r\n\r\n\t\t\tMem::PushMemProfile((char*)fullname);\r\n\t\t\tif (useBottomUpHeap)\r\n\t\t\t{\r\n\t\t\t\tpFile = new (Mem::Manager::sHandle().BottomUpHeap()) uint8[file_size];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpFile = new (Mem::Manager::sHandle().TopDownHeap()) uint8[file_size];\r\n\t\t\t}\t\r\n\t\t\tMem::PopMemProfile();\r\n\r\n\t\t\t// Set the callback\r\n\t\t\tp_fileHandle->SetCallback(async_callback, (unsigned int) this, (unsigned int) pFile);\r\n\r\n\t\t\t// read the file in\r\n\t\t\tp_fileHandle->Read( pFile, 1, file_size );\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\t// If we got here, we didn't do an async load\r\n\tfile_size = CanFileBeLoadedQuickly( fullname );\r\n\tif ( file_size )\r\n\t{\r\n\t\tMem::PushMemProfile((char*)fullname);\r\n\t\tif (useBottomUpHeap)\r\n\t\t{\r\n\t\t\tpFile = new (Mem::Manager::sHandle().BottomUpHeap()) uint8[file_size];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpFile = new (Mem::Manager::sHandle().TopDownHeap()) uint8[file_size];\r\n\t\t}\t\r\n\t\tMem::PopMemProfile();\r\n\t\tbool fileLoaded= LoadFileQuicklyPlease( fullname, pFile );\r\n\t\tif ( !fileLoaded )\r\n\t\t{\r\n\t\t\tprintf( \"pre file %s failed to load quickly.\\n\", fullname );\r\n\t\t\tDbg_MsgAssert( 0,( \"Fire Matt - pre file didn't load quickly.\" ));\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t\tvoid *fp = File::Open(fullname, \"rb\");\r\n\t\t\tif (!fp)\r\n\t\t\t{\r\n\t\t\t// always run the code below if CD build\r\n\t\t\t\tif (dont_assert || Config::CD()) \r\n\t\t\t\t{\r\n\t\t\t\t\tprintf(\"couldn't open %s\\n\", fullname);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tDbg_MsgAssert(0,( \"couldn't open %s\\n\", fullname));\r\n\t\t\t}\r\n\r\n\r\n#ifdef __PRE_ARAM__\r\n\t\t\tFile::Read(&file_size, 4, 1, fp);\r\n\t\t\tDbg_MsgAssert(file_size > 0,( \"%s has incorrect file size\\n\", fullname));\r\n\t\t\tif (Config::CD())\r\n\t\t\t{\r\n\t\t\t\tif (file_size <= 0) printf(\"%s has incorrect file size\\n\", fullname);\r\n\t\t\t}\t\r\n\r\n\t\t\t// Stream the file into ARAM.\r\n\t\t\t#define PRE_BUFFER_SIZE (16 * 1024)\r\n\t\t\tchar p_buffer[PRE_BUFFER_SIZE];\r\n\r\n\t\t\tuint32 p_aram;\r\n\t\t\tif (useBottomUpHeap)\r\n\t\t\t{\r\n\t\t\t\tp_aram = NsARAM::alloc( file_size, NsARAM::BOTTOMUP );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_aram = NsARAM::alloc( file_size, NsARAM::TOPDOWN );\r\n\t\t\t}\t\r\n\t\t\tif ( p_aram )\r\n\t\t\t{\r\n\t\t\t\tint adjust = 4;\r\n\t\t\t\tuint32 toread = file_size;\r\n\t\t\t\tuint32 current_aram_offset = p_aram;\r\n\t\t\t\twhile ( toread )\r\n\t\t\t\t{\r\n\t\t\t\t\tuint32 thistime = PRE_BUFFER_SIZE;\r\n\t\t\t\t\tif ( toread < PRE_BUFFER_SIZE ) thistime = toread;\r\n\r\n\t\t\t\t\tFile::Read(&p_buffer[adjust], 1, thistime - adjust, fp);\r\n\t\t\t\t\tDCFlushRange ( p_buffer, thistime );\r\n\t\t\t\t\tNsDMA::toARAM( current_aram_offset, p_buffer, thistime );\r\n\t\t\t\t\ttoread -= thistime;\r\n\t\t\t\t\tcurrent_aram_offset += thistime;\r\n\t\t\t\t\tadjust = 0;\r\n\t\t\t\t}\r\n\t\t\t\tFile::Close(fp);\r\n\t\t\t\tpFile = (uint8 *)p_aram;\r\n\t\t\t}\r\n#else\r\n\t\t\tfile_size = File::GetFileSize(fp);\r\n\t\t// Now allocates the .PRE file from the top of the heap, to avoid fragmentation.\r\n\t\t\tMem::PushMemProfile((char*)fullname);\r\n\t\t\tif (useBottomUpHeap)\r\n\t\t\t{\r\n\t\t\t\tpFile = new (Mem::Manager::sHandle().BottomUpHeap()) uint8[file_size];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpFile = new (Mem::Manager::sHandle().TopDownHeap()) uint8[file_size];\r\n\t\t\t}\t\r\n\t\t\tMem::PopMemProfile();\r\n\t\t//uint8 *pFile = new uint8[file_size];\r\n\t\t\tFile::Read(pFile, 1, file_size, fp);\r\n\r\n\t\t\tint read_file_size = *((int *) pFile);\r\n\t\t\tDbg_MsgAssert(file_size == read_file_size,( \"%s has incorrect file size: %d vs. expected %d\\n\", fullname, file_size, read_file_size));\r\n\t\t\tif (Config::CD())\r\n\t\t\t{\r\n\t\t\t\tif (file_size != read_file_size) printf(\"%s has incorrect file size\\n\", fullname);\r\n\t\t\t}\r\n\r\n\t\t\tFile::Close(fp);\r\n#endif\t\t// __PRE_ARAM__\r\n\t\t}\r\n\r\n#\tif !defined( __PLAT_NGC__ ) || ( defined( __PLAT_NGC__ ) && !defined( __NOPT_FINAL__ ) )\r\n\tprintf(\"load time for file %s size %d is %d ms\\n\", pFilename, file_size, (int) Tmr::ElapsedTime(basetime));\r\n#endif\r\n\r\n\t// the PRE file object winds up at the top of the heap, too. This is fine because\r\n\t// it will be unloaded at the same time as the big file buffer\r\n\tif (useBottomUpHeap)\r\n\t{\r\n\t\tif (!mp_table->PutItem(pFilename, new (Mem::Manager::sHandle().BottomUpHeap()) PreFile(pFile,useBottomUpHeap)))\r\n\t\t\tDbg_MsgAssert(0,( \"PRE %s loaded twice\", pFilename));\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (!mp_table->PutItem(pFilename, new (Mem::Manager::sHandle().TopDownHeap()) PreFile(pFile)))\r\n\t\t\tDbg_MsgAssert(0,( \"PRE %s loaded twice\", pFilename));\r\n\t}\t\t\r\n}\r\n\r\n// Finishes the loading sequence\r\nvoid   \tPreMgr::postLoadPre(CAsyncFileHandle *p_file_handle, uint8 *pData, int size)\r\n{\r\n\t// Find entry in pending list\r\n\tfor (int i = 0; i < m_num_pending_pre_files; i++)\r\n\t{\r\n\t\tif (m_pending_pre_files[i].mp_file_handle == p_file_handle)\r\n\t\t{\r\n\t\t\t// the PRE file object winds up at the top of the heap, too. This is fine because\r\n\t\t\t// it will be unloaded at the same time as the big file buffer\r\n\t\t\tif (!mp_table->PutItem(m_pending_pre_files[i].m_file_name, new (Mem::Manager::sHandle().TopDownHeap()) PreFile(pData)))\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0,( \"PRE %s loaded twice\", m_pending_pre_files[i].m_file_name));\r\n\t\t\t}\r\n\r\n\t\t\t// Copy last one to this position\r\n\t\t\tm_pending_pre_files[i] = m_pending_pre_files[--m_num_pending_pre_files];\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert(0, (\"PreMgr::postLoadPre(): Can't find entry in pending Pre file list\"));\r\n}\r\n\r\n// Handles all the async callbacks.  Makes sure we only do something on the appropriate callback\r\nvoid\tPreMgr::async_callback(CAsyncFileHandle *p_file_handle, EAsyncFunctionType function,\r\n\t\t\t\t\t\t\t   int result, unsigned int arg0, unsigned int arg1)\r\n{\r\n\tif (function == File::FUNC_READ)\r\n\t{\r\n\t\tPreMgr *p_mgr = (PreMgr *) arg0;\r\n\r\n\t\tp_mgr->postLoadPre(p_file_handle, (uint8 *) arg1, result);\r\n\t}\r\n}\r\n\r\n// Returns point in string where it will fit in compact space\r\nchar *\tPreMgr::getCompactFileName(char *pName)\r\n{\r\n\tint length = strlen(pName);\r\n\r\n\tif (length < MAX_COMPACT_FILE_NAME)\r\n\t{\r\n\t\treturn pName;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint offset = length - (MAX_COMPACT_FILE_NAME - 1);\r\n\r\n\t\treturn pName + offset;\r\n\t\t//return (char *) ((int) pName + offset);\r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nDefineSingletonClass(PreMgr, \"PRE Manager\");\r\n\r\n\r\n\r\nbool PreMgr::InPre(const char *pFilename)\r\n{\r\n\t\r\n\r\n\treturn mp_table->GetItem( pFilename );\r\n}\r\n\r\n\r\n\r\nvoid PreMgr::LoadPre(const char *pFilename, bool async, bool dont_assert, bool useBottomUpHeap)\r\n{\r\n\t// GJ:  This function is a wrapper around loadPRE(), to\r\n\t// make sure that all allocations go on the top-down heap\r\n\t\r\n\t// K: Unless they want to use the bottom up heap :)\r\n\t// Needed so that the anims pre can be put on the bottom up, so that the decompressed anims\r\n\t// can be put on the top-down, then the pre removed without leaving a hole.\r\n\tif (useBottomUpHeap)\r\n\t{\r\n\t\t//printf(\"Loading %s to bottom up heap\\n\",pFilename);\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//printf(\"Loading %s to top down heap\\n\",pFilename);\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t}\t\r\n\tloadPre(pFilename, async, dont_assert, useBottomUpHeap);\r\n\tMem::Manager::sHandle().PopContext();\t\r\n}\r\n\r\n\r\n// This function exisits for historical reasons\r\nvoid PreMgr::LoadPrePermanently(const char *pFilename, bool async, bool dont_assert)\r\n{\r\n\r\n\t// Load the pre file...\r\n\t// This will go on the top-down heap by default\r\n\tLoadPre(pFilename, async, dont_assert);\r\n\r\n}\r\n\r\n\r\n\r\nvoid PreMgr::UnloadPre(const char *pFilename, bool dont_assert)\r\n{\r\n#\tifdef __PLAT_NGPS__\r\n//\tscePrintf(\"Unloading PRE file %s\\n\", pFilename);\r\n#\tendif\r\n\t//printf(\"Unloading PRE file %s\\n\", pFilename);\r\n\t\r\n\tif (m_blockPreLoading)\r\n\t\treturn;\r\n\t\r\n\tPreFile *pThePre = mp_table->GetItem(pFilename);\r\n\tif (!pThePre)\r\n\t{\r\n\t\tif (dont_assert) return;\r\n#\tifndef __PLAT_NGC__\r\n\t\tDbg_MsgAssert(0,( \"PRE file %s not in PRE manager\", pFilename));\r\n#\tendif\r\n\t}\r\n\r\n\tmp_table->FlushItem(pFilename);\r\n\tdelete pThePre;\r\n}\r\n\r\nbool PreMgr::IsLoadPreFinished(const char *pFilename)\r\n{\r\n\t// If it's in the pending list, it isn't done loading\r\n\tfor (int i = 0; i < m_num_pending_pre_files; i++)\r\n\t{\r\n\t\tif (strcmp(m_pending_pre_files[i].m_file_name, pFilename) == 0)\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert(InPre(pFilename), (\"IsLoadPreFinished(): Can't find Pre file\"));\r\n\r\n\treturn true;\r\n}\r\n\r\nbool PreMgr::AllLoadPreFinished()\r\n{\r\n\treturn m_num_pending_pre_files == 0;\r\n}\r\n\r\nvoid PreMgr::WaitLoadPre(const char *pFilename)\r\n{\r\n\twhile (!IsLoadPreFinished(pFilename))\r\n\t{\r\n\t\t// We got to call this to allow callbacks to come through\r\n\t\tCAsyncFileLoader::sWaitForIOEvent(false);\r\n\t}\r\n}\r\n\r\nvoid PreMgr::WaitAllLoadPre()\r\n{\r\n\twhile (!AllLoadPreFinished())\r\n\t{\r\n\t\t// We got to call this to allow callbacks to come through\r\n\t\tCAsyncFileLoader::sWaitForIOEvent(false);\r\n\t}\r\n}\r\n\r\nbool PreMgr::sPreEnabled()\r\n{\r\n\treturn sp_mgr != NULL;\r\n}\r\n\r\nbool PreMgr::sPreExecuteSuccess()\r\n{\r\n\treturn s_lastExecuteSuccess; \r\n}\r\n\r\nbool PreMgr::pre_fexist(const char *name)\r\n{\r\n\t\r\n\tDbg_MsgAssert(name,( \"requesting file NULL\"));\t\r\n\t\r\n\tif (sp_mgr->fileExists(name)) \r\n\t{\r\n#\t\tif DEBUG_PRE\r\n\t\tprintf(\"PRE: file %s exists\\n\", name);\r\n#\t\tendif\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn true;\r\n\t}\r\n//\tif ( Pcm::UsingCD( ) )\r\n//\t{\r\n//\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n//\t\treturn false;\r\n//\t}\r\n\r\n\treturn s_lastExecuteSuccess = false;\r\n}\r\n\r\n\r\n\r\nPreFile::FileHandle *PreMgr::pre_fopen(const char *name, const char *access, bool async)\r\n{\r\n\tDbg_MsgAssert(name,( \"trying to open file NULL\"));\t\r\n\r\n\tPreFile::FileHandle *pHandle = sp_mgr->getContainedFile(name);\r\n\tif (pHandle)\r\n\t{\r\n\t\tsp_mgr->mp_activePre->Open(async);\r\n\r\n\t\t// if we are going to write the file, we want to use the regular file system\r\n\t\tconst char *pChar = access;\r\n\t\tbool am_writing = false;\r\n\t\twhile(*pChar)\r\n\t\t{\r\n\t\t\tif (*pChar != 'r' && *pChar != 'b')\r\n\t\t\t\tam_writing = true;\r\n\t\t\tpChar++;\r\n\t\t}\r\n\t\t\r\n\t\tif (am_writing)\r\n\t\t{\r\n#\t\t\tifdef __PLAT_NGPS__\r\n//\t\t\tscePrintf(\"    writing file %s\\n\", name);\r\n#\t\t\tendif\r\n\r\n\t\t\t// am writing, so we don't need file open in PRE system\r\n\t\t\tsp_mgr->mp_activePre->Close(async);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// we're reading the file from the PRE system\r\n#\t\t\tif DEBUG_PRE\r\n\t\t\tprintf(\"PRE: opened file %s, handle is 0x%x\\n\", name, (int) pHandle);\r\n#\t\t\tendif\r\n\t\t\tsp_mgr->mp_activePre->Reset();\r\n\t\t\ts_lastExecuteSuccess = true;\r\n\t\t\treturn pHandle;\r\n\t\t}\r\n\t}\r\n\r\n//\t// if we get here, we are using the regular file system\r\n//\tif ( Pcm::UsingCD( ) )\r\n//\t{\r\n//\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n//\t\treturn NULL;\r\n//\t}\r\n\r\n\ts_lastExecuteSuccess = false;\r\n\treturn NULL;\r\n\r\n\t//return pHandle;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_fclose(PreFile::FileHandle *fptr, bool async)\r\n{\r\n\t\t\r\n\tDbg_MsgAssert(fptr,( \"calling fclose with invalid file ptr\"));\t\r\n\t\r\n\tuint8 *pData = sp_mgr->getContainedFileByHandle(fptr);\r\n\tif (pData)\r\n\t{\r\n#if DEBUG_PRE\r\n\t\tprintf(\"PRE: closed file, handle 0x%x\\n\", (int) fptr);\r\n#endif\r\n\t\tsp_mgr->mp_activePre->Close(async);\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn 0;\r\n\t}\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nsize_t PreMgr::pre_fread(void *addr, size_t size, size_t count, PreFile::FileHandle *fptr)\r\n{\r\n\t\t\r\n\tDbg_MsgAssert(fptr,( \"calling fread with invalid file ptr\"));\t\t\r\n\r\n\tuint8 *pData = sp_mgr->getContainedFileByHandle(fptr);\r\n\tif (pData)\r\n\t{\r\n\t\t// read from a simulated file stream in PRE file\r\n\t\tDbg_AssertPtr(sp_mgr->mp_activePre);\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn sp_mgr->mp_activePre->Read(addr, size * count);\r\n\t}\r\n//\tif ( Pcm::UsingCD( ) )\r\n//\t{\r\n//\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n//\t\treturn 0;\r\n//\t}\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nsize_t  PreMgr::pre_fwrite(const void *addr, size_t size, size_t count, PreFile::FileHandle *fptr)\r\n{\r\n\t\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint8 *pData = \r\n\t#endif\r\n\tsp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"can't write to a PRE file\"));\r\n\t\r\n//\tif ( Pcm::UsingCD( ) )\r\n//\t{\r\n//\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n//\t\treturn 0;\r\n//\t}\r\n\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nchar *PreMgr::pre_fgets(char *buffer, int maxLen, PreFile::FileHandle *fptr)\r\n{\r\n\t\t\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint8 *pData = \r\n\t#endif\r\n\tsp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"can't do string ops on a PRE file\"));\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_fputs(const char *buffer, PreFile::FileHandle *fptr)\r\n{\r\n\t\t\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint8 *pData = \r\n\t#endif\r\n\tsp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"can't do string ops on a PRE file\"));\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_feof(PreFile::FileHandle *fptr)\r\n{\r\n\t\t\r\n\tDbg_MsgAssert(fptr,( \"calling feof with invalid file ptr\"));\t\t\r\n\r\n\tuint8 *pData = \tsp_mgr->getContainedFileByHandle(fptr);\r\n\tif (pData)\r\n\t{\r\n\t\tDbg_AssertPtr(sp_mgr->mp_activePre);\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn sp_mgr->mp_activePre->Eof();\r\n\t}\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_fseek(PreFile::FileHandle *fptr, long offset, int origin)\r\n{\r\n\t\t\r\n\r\n\tuint8 *pData = \tsp_mgr->getContainedFileByHandle(fptr);\r\n\tif (pData)\r\n\t{\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn sp_mgr->mp_activePre->Seek(offset, origin);\r\n\t}\r\n\r\n\tDbg_MsgAssert(!pData,( \"seek not supported for PRE file\"));\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_fflush(PreFile::FileHandle *fptr)\r\n{\r\n\t\t\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint8 *pData = \r\n\t#endif\r\n\tsp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"flush not supported for PRE file\"));\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_ftell(PreFile::FileHandle *fptr)\r\n{\r\n\t\t\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint8 *pData = \r\n\t#endif\r\n\tsp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"tell supported for PRE file\"));\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\nint\tPreMgr::pre_get_file_size(PreFile::FileHandle *fptr)\r\n{\r\n\tuint8 *pData = \tsp_mgr->getContainedFileByHandle(fptr);\r\n\tif (pData)\r\n\t{\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn sp_mgr->mp_activePre->GetFileSize();\r\n\t}\r\n\r\n\tDbg_MsgAssert(!pData,( \"get_file_size not supported for PRE file\"));\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\nint PreMgr::pre_get_file_position(PreFile::FileHandle *fptr)\r\n{\r\n\tuint8 *pData = \tsp_mgr->getContainedFileByHandle(fptr);\r\n\tif (pData)\r\n\t{\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn sp_mgr->mp_activePre->GetFilePosition();\r\n\t}\r\n\r\n\tDbg_MsgAssert(!pData,( \"get_file_position not supported for PRE file\"));\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n// @script | InPreFile | \r\n// @uparm \"string\" | filename\r\nbool ScriptInPreFile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *pFilename;\r\n\tpParams->GetText(NONAME, &pFilename, true);\r\n\r\n\tPreMgr* pre_mgr = PreMgr::Instance();\r\n\treturn pre_mgr->InPre(pFilename);\r\n}\r\n\r\n\r\n\r\n// @script | LoadPreFile | \r\n// @uparm \"string\" | filename\r\n// @flag async | Load Asynchronously\r\n// @flag dont_assert | \r\n// @flag use_bottom_up_heap | \r\nbool ScriptLoadPreFile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *pFilename;\r\n\tpParams->GetText(NONAME, &pFilename, true);\r\n\r\n\tPreMgr* pre_mgr = PreMgr::Instance();\r\n\tpre_mgr->LoadPre(pFilename, \r\n\t\t\t\t\t pParams->ContainsFlag(CRCD(0x90e07c79,\"async\")),\r\n\t\t\t\t\tpParams->ContainsFlag(CRCD(0x3d92465e,\"dont_assert\")),\r\n\t\t\t\t\tpParams->ContainsFlag(CRCD(0xa44c770f,\"use_bottom_up_heap\")));\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n// @script | UnloadPreFile | \r\n// @flag BoardsPre | \r\n// @flag dont_assert | \r\n// @uparm \"string\" | filename\r\nbool ScriptUnloadPreFile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\tPreMgr* pre_mgr = PreMgr::Instance();\r\n\t\r\n\tif (pParams->ContainsFlag(\"BoardsPre\"))\r\n\t{\r\n\t\t\r\n//\t\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n//\t\tpSkate->UnloadBoardPreIfPresent(pParams->ContainsFlag(\"dont_assert\"));\r\n\t\tprintf (\"STUBBED:  Unload BoardsPre, in ScriptUnloadPreFile\\n\");\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tconst char *pFilename;\r\n\tpParams->GetText(NONAME, &pFilename, true);\r\n\r\n\tpre_mgr->UnloadPre(pFilename, pParams->ContainsFlag(\"dont_assert\"));\r\n\treturn true;\r\n}\r\n\r\n// @script | IsLoadPreFinished | Returns true if Pre file has finished loading\r\n// @uparm \"string\" | filename\r\nbool ScriptIsLoadPreFinished(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tPreMgr* pre_mgr = PreMgr::Instance();\r\n\r\n\tconst char *pFilename;\r\n\tpParams->GetText(NONAME, &pFilename, true);\r\n\r\n\treturn pre_mgr->IsLoadPreFinished(pFilename);\r\n}\r\n\r\n// @script | AllLoadPreFinished | Returns true if all LoadPre commands have completed\r\nbool ScriptAllLoadPreFinished(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tPreMgr* pre_mgr = PreMgr::Instance();\r\n\r\n\treturn pre_mgr->AllLoadPreFinished();\r\n}\r\n\r\n// @script | WaitLoadPre | Waits for Pre file to finished loading\r\n// @uparm \"string\" | filename\r\nbool ScriptWaitLoadPre(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tPreMgr* pre_mgr = PreMgr::Instance();\r\n\r\n\tconst char *pFilename;\r\n\tpParams->GetText(NONAME, &pFilename, true);\r\n\r\n\tpre_mgr->WaitLoadPre(pFilename);\r\n\treturn true;\r\n}\r\n\r\n// @script | WaitAllLoadPre | Waits for all Pre files to finished loading\r\nbool ScriptWaitAllLoadPre(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tPreMgr* pre_mgr = PreMgr::Instance();\r\n\r\n\tpre_mgr->WaitAllLoadPre();\r\n\treturn true;\r\n}\r\n\r\n// if a file is in a pre, then:\r\n// allocate memory for the file\r\n// if file is uncompressed\r\n//   copy it down\r\n// else\r\n//   decompress\r\n\r\nvoid * PreMgr::LoadFile(const char *pName, int *p_size, void *p_dest)\r\n{\r\n// NOTE: THIS IS JUST CUT AND PASTE FROM Pre::fileExists\r\n\tDbg_AssertPtr(pName);\r\n\t// replace all '/' with '\\'\r\n\tchar cleaned_name[128];\r\n\tconst char *pCharIn = pName;\r\n\tchar *pCharOut = cleaned_name;\r\n\twhile (1)\r\n\t{\r\n\t\t*pCharOut = *pCharIn;\r\n\t\tif (*pCharIn == '\\0') break;\r\n\t\tif (*pCharOut == '/') *pCharOut = '\\\\';\r\n\t\tpCharIn++;\r\n\t\tpCharOut++;\t\t\r\n\t}\r\n\r\n\tmp_table->IterateStart();\r\n\tPreFile *pPre = mp_table->IterateNext();\r\n\twhile(pPre)\r\n\t{\r\n\t\t\r\n\t\tvoid *p_data = pPre->LoadContainedFile(cleaned_name,p_size, p_dest);\r\n\t\tif (p_data)\r\n\t\t{\r\n\t\t\treturn p_data;\r\n\t\t}\r\n\t\tpPre = mp_table->IterateNext();\r\n\t}\r\n\treturn NULL;\r\n\r\n}\r\n\r\n\r\n\r\n} // namespace File\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/PRE.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2001 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\t\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\trjm, 1/23/2001\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_FILE_PRE_H\r\n#define __CORE_FILE_PRE_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sys/file/AsyncTypes.h>\r\n\r\nnamespace Lst\r\n{\r\n\ttemplate<class _V> class StringHashTable;\r\n}\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n}\t\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace File\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool ScriptInPreFile(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptLoadPreFile(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUnloadPreFile(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptIsLoadPreFinished(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptAllLoadPreFinished(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptWaitLoadPre(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptWaitAllLoadPre(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass CAsyncFileHandle;\r\nclass PreMgr;\r\nclass  PreFile  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic:\r\n\r\n\t// The actual PRE file (it is public so that FileHandle can be made public).\r\n\tstruct _File\r\n\t{\r\n\t\tint\t\t\t\tcompressedDataSize;\r\n\t\tuint8 *\t\t\tpCompressedData;\r\n\t\tuint8 *\t\t\tpData;\r\n\t\tint\t\t\t\tm_position;\r\n\t\tint\t\t\t\tm_filesize;\r\n\t};\r\n\r\n\t// Just typedef a file handle type since the file itself contains all the info\r\n\ttypedef _File FileHandle;\r\n\r\n\tPreFile(uint8 *p_file_buffer, bool useBottomUpHeap=false);\r\n\t~PreFile();\r\n\t\r\n\t\r\n\t\r\n\tbool \t\tFileExists(const char *pName);\r\n\tvoid*\t\tLoadContainedFile(const char *pName,int *p_size, void *p_dest = NULL);\r\n\tFileHandle*\tGetContainedFile(const char *pName);\r\n\tuint8*\t\tGetContainedFileByHandle(FileHandle *pHandle);\r\n\r\n\tvoid Reset();\r\n\tuint32 Read(void *addr, uint32 count);\r\n\tint Eof();\r\n\tvoid Open(bool async);\r\n\tvoid Close(bool async);\r\n\tint Seek(long offset, int origin);\r\n\tint TellActive( void )\t\t\t\t{ if( mp_activeFile ){ return mp_activeFile->m_position; }else{ return 0; }}\r\n\tint GetFileSize( void )\t\t\t\t{ if( mp_activeFile ){ return mp_activeFile->m_filesize; }else{ return 0; }}\r\n\tint GetFilePosition( void )\t\t\t{ if( mp_activeFile ){ return mp_activeFile->m_position; }else{ return 0; }}\r\n\r\nprivate:\r\n\r\n\tstatic void\t\t\t\t\t\ts_delete_file(_File *pFile, void *pData);\r\n\t\r\n\tuint8 *\t\t\t\t\t\t\tmp_buffer;\r\n\tint\t\t\t\t\t\t\t\tm_numEntries;\r\n\t\r\n\t// maps filenames to pointers\r\n\tLst::StringHashTable<_File> *\tmp_table;\r\n\r\n\t_File *\t\t\t\t\t\t\tmp_activeFile;\r\n\r\n\tint\t\t\t\t\t\t\t\tm_numOpenAsyncFiles;\r\n\t\r\n\tbool\t\t\t\t\t\t\tm_use_bottom_up_heap;\r\n};\r\n\r\n\r\n\r\n\r\nclass  PreMgr  : public Spt::Class\r\n{\r\n\t\r\n\tDeclareSingletonClass(PreMgr);\r\n\r\npublic:\r\n\tbool InPre(const char *pFilename);\r\n\tvoid LoadPre(const char *pFilename, bool async, bool dont_assert = false, bool useBottomUpHeap=false);\r\n\tvoid LoadPrePermanently(const char *pFilename, bool async, bool dont_assert = false);\r\n\tvoid UnloadPre(const char *pFilename, bool dont_assert = false);\r\n\tvoid * LoadFile(const char *pName, int *p_size, void *p_dest = NULL);\r\n\r\n\t// Async check functions\r\n\tbool IsLoadPreFinished(const char *pFilename);\r\n\tbool AllLoadPreFinished();\r\n\tvoid WaitLoadPre(const char *pFilename);\r\n\tvoid WaitAllLoadPre();\r\n\r\n\tstatic bool sPreEnabled();\r\n\tstatic bool sPreExecuteSuccess();\r\n\t\r\n\tstatic bool\t\t\t\t\tpre_fexist(const char *name);\r\n\tstatic PreFile::FileHandle *pre_fopen(const char *name, const char *access, bool async = false);\r\n\tstatic int\t\t\t\t\tpre_fclose(PreFile::FileHandle *fptr, bool async = false);\r\n\tstatic size_t\t\t\t\tpre_fread(void *addr, size_t size, size_t count, PreFile::FileHandle *fptr);\r\n\tstatic size_t\t\t\t\tpre_fwrite(const void *addr, size_t size, size_t count, PreFile::FileHandle *fptr);\r\n\tstatic char *\t\t\t\tpre_fgets(char *buffer, int maxLen, PreFile::FileHandle *fptr);\r\n\tstatic int\t\t\t\t\tpre_fputs(const char *buffer, PreFile::FileHandle *fptr);\r\n\tstatic int\t\t\t\t\tpre_feof(PreFile::FileHandle *fptr);\r\n\tstatic int\t\t\t\t\tpre_fseek(PreFile::FileHandle *fptr, long offset, int origin);\r\n\tstatic int\t\t\t\t\tpre_fflush(PreFile::FileHandle *fptr);\r\n\tstatic int\t\t\t\t\tpre_ftell(PreFile::FileHandle *fptr);\r\n\tstatic int\t\t\t\t\tpre_get_file_size(PreFile::FileHandle *fptr);\r\n\tstatic int\t\t\t\t\tpre_get_file_position(PreFile::FileHandle *fptr);\r\n\r\nprivate:\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tMAX_COMPACT_FILE_NAME = 64,\t\t\t\t// Only store the right-most characters of the filename to save space\r\n\t\tMAX_NUM_ASYNC_LOADS = 8,\r\n\t};\r\n\r\n\t// Holds data for pending async loads\r\n\tstruct SPendingAsync\r\n\t{\r\n\t\tCAsyncFileHandle *\t\t\tmp_file_handle;\r\n\t\tchar\t\t\t\t\t\tm_file_name[MAX_COMPACT_FILE_NAME];\r\n\t};\r\n\r\n\tPreMgr();\r\n\t~PreMgr();\r\n\r\n\tvoid\t\t\t\t loadPre(const char *pFilename, bool async, bool dont_assert = false, bool useBottomUpHeap=false);\r\n    void    \t\t\t postLoadPre(CAsyncFileHandle *p_file_handle, uint8 *pData, int size);\r\n\tbool\t\t\t\t fileExists(const char *pName);\r\n\tPreFile::FileHandle *getContainedFile(const char *pName);\r\n\tuint8 *\t\t\t\t getContainedFileByHandle(PreFile::FileHandle *pHandle);\r\n\r\n\tstatic char *\t\t getCompactFileName(char *pName);\t\t// Returns point in string where it will fit in compact space\r\n\r\n\tstatic void\t\t\t async_callback(CAsyncFileHandle *p_file_handle, EAsyncFunctionType function,\r\n\t\t\t\t\t\t\t\t\t\tint result, unsigned int arg0, unsigned int arg1);\r\n\r\n\tPreFile\t\t\t\t\t\t\t*mp_activePre;\r\n\tPreFile::FileHandle *\t \t\tmp_activeHandle;\r\n\tuint8 *\t\t\t\t\t\t\tmp_activeData;\r\n\t// handle of current file being accessed from regular file system, for quick check\r\n\tvoid *\t\t\t\t\t\t\tmp_activeNonPreHandle;\r\n\r\n\tstatic bool\t\t\t\t\t\ts_lastExecuteSuccess;\r\n\tstatic PreMgr *\t\t\t\t\tsp_mgr;\r\n\t\r\n\tLst::StringHashTable<PreFile> *\tmp_table;\r\n\r\n\tbool\t\t\t\t\t\t\tm_blockPreLoading;\r\n\r\n\t// Async status\r\n\tSPendingAsync\t\t\t\t\tm_pending_pre_files[MAX_NUM_ASYNC_LOADS];\r\n\tint\t\t\t\t\t\t\t\tm_num_pending_pre_files;\r\n};\r\n\r\n\r\n} // namespace File\r\n\r\n#endif\t// __CORE_FILE_PRE_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/XBox/hed.cpp",
    "content": "/*\tHeader file functionality...\r\n\t.Hed files that describe the contents of .Wad files\r\n\tWritten by Ken, stolen by Matt*/\r\n#include <stdio.h>\r\n#include <string.h>\r\n#include <ctype.h>\r\n\r\n#include <core/macros.h>\r\n#include <core/defines.h>\r\n\r\n#include <gel/scripting/script.h> \r\n\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/xbox/hed.h>\r\n\r\nnamespace File\r\n{\r\n\r\n// Searches the hed file for the filename. If not found, returns NULL.\r\nSHed *FindFileInHed(const char *pFilename, SHed *pHed)\r\n{\r\n\tDbg_MsgAssert(pFilename,(\"NULL pFilename\"));\r\n\tDbg_MsgAssert(pHed,(\"NULL pHed\"));\r\n\t\r\n\t#define FILENAME_BUF_SIZE 200\r\n\tchar pBuf[FILENAME_BUF_SIZE];\r\n\tDbg_MsgAssert(strlen(pFilename)<FILENAME_BUF_SIZE,(\"File name too long.\"));\r\n\t// Make sure that pBuf starts with a backslash, since the names listed in\r\n\t// the hed file all do.\r\n\tif (pFilename[0]!='\\\\' && pFilename[0]!='/')\r\n\t{\r\n\t\tpBuf[0]='\\\\';\r\n\t\tpBuf[1]=0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tpBuf[0]=0;\r\n\t}\r\n\t// Append the passed filename.\r\n\tstrcat(pBuf,pFilename);\r\n\t// Scan through and convert all forward slashes to backslashes since that's\r\n\t// how they're listed in the hed.\r\n\tchar *pCh=pBuf;\r\n\twhile (*pCh)\r\n\t{\r\n\t\tif (*pCh=='/')\r\n\t\t{\r\n\t\t\t*pCh='\\\\';\r\n\t\t}\r\n\t\t++pCh;\r\n\t}\t\t\t\t\r\n\t\r\n\t// Search the hed until the file is found, or not.\r\n\tSHed *pHd=pHed;\r\n\twhile (pHd->Offset!=0xffffffff)\r\n\t{\t\t\t\t\t\t  \r\n\t\tif (stricmp(pBuf,pHd->pFilename)==0)\r\n\t\t{\r\n\t\t\treturn pHd;\r\n\t\t}\r\n\t\t\r\n\t\t// Get the total space occupied by the file name, which is\r\n\t\t// the length +1 (to include the terminator) then rounded up\r\n\t\t// to a multiple of 4.\r\n\t\tint Len=strlen(pHd->pFilename)+1;\r\n\t\tLen=(Len+3)&~3;\r\n\t\tpHd=(SHed*)(pHd->pFilename+Len);\r\n\t}\r\n\treturn NULL;\t\r\n}\r\n\r\n// Searches the hed file for the filename with the same checksum. If not found, returns NULL.\r\nSHed *FindFileInHedUsingChecksum( uint32 checksum, SHed *pHed, bool stripPath )\r\n{\r\n\tDbg_MsgAssert(pHed,(\"NULL pHed\"));\r\n\t\r\n\t// Search the hed until the file is found, or not.\r\n\tSHed *pHd=pHed;\r\n\tconst char *pFilename;\r\n\twhile (pHd->Offset!=0xffffffff)\r\n\t{\r\n\t\tpFilename = pHd->pFilename;\r\n\t\tif ( stripPath )\r\n\t\t{\r\n\t\t\tint i;\r\n\t\t\tfor ( i = strlen( pFilename ) - 2; i >= 0; i-- )\r\n\t\t\t{\r\n\t\t\t\tif ( pFilename[ i ] == '\\\\' )\r\n\t\t\t\t{\r\n\t\t\t\t\tpFilename = &pFilename[ i + 1 ];\r\n\t\t\t\t\ti = -1;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( Script::GenerateCRC( pFilename ) == checksum )\r\n\t\t{\r\n\t\t\treturn ( pHd );\r\n\t\t}\r\n\t\t// Get the total space occupied by the file name, which is\r\n\t\t// the length +1 (to include the terminator) then rounded up\r\n\t\t// to a multiple of 4.\r\n\t\tint Len=strlen(pHd->pFilename)+1;\r\n\t\tLen=(Len+3)&~3;\r\n\t\tpHd=(SHed*)(pHd->pFilename+Len);\r\n\t}\r\n\treturn NULL;\t\r\n}\r\n\r\n\r\n\r\nSHed *LoadHed( const char *filename )\r\n{\r\n\tchar tempFileName[255];\r\n\tsprintf( tempFileName, \"%s.HED\", filename );\r\n\r\n\tvoid *fp = File::Open( tempFileName, \"rb\" );\r\n\tif ( !fp )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Couldn't find hed file %s\", tempFileName ));\r\n\t\treturn NULL;\r\n\t}\r\n\tint fileSize = File::GetFileSize( fp );\r\n\tFile::Seek( fp, 0, SEEK_SET );\r\n\t\r\n\tSHed *pHed = (SHed*)Mem::Malloc(( fileSize + 2047 ) & ~2047 );\r\n\tDbg_MsgAssert( pHed,( \"Failed to allocate memory for hed %s\", tempFileName ));\r\n\t\r\n\tFile::Read( pHed, 1, fileSize, fp );\r\n\tFile::Close( fp );\r\n\treturn pHed;\r\n}\r\n\r\n} // namespace File\r\n"
  },
  {
    "path": "Code/Sys/File/XBox/hed.h",
    "content": "/*\tHeader file functionality...\r\n\t.Hed files that describe the contents of .Wad files\r\n\tWritten by Ken, stolen by Matt*/\r\n#ifndef __HED_H__\r\n#define __HED_H__\r\n\r\nnamespace File\r\n{\r\n\r\nstruct SHed\r\n{\r\n\t// A SECTOR_SIZE aligned offset of a file within skate3.wad\r\n\tuint32 Offset;\r\n\t\r\n\t// The file size, which is the raw file size, not rounded up\r\n\t// to a multiple of SECTOR_SIZE\r\n\tuint32 FileSize;\r\n\t\r\n\t// The filename, which is actually bigger than one byte, tee hee.\r\n\tconst char pFilename[1];\r\n};\r\n\r\n\r\nSHed *FindFileInHed(const char *pFilename, SHed *pHed );\r\nSHed *FindFileInHedUsingChecksum( uint32 checksum, SHed *pHed, bool stripPath );\r\nSHed *LoadHed( const char *filename );\r\n\r\n} // namespace File\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sys/File/XBox/p_AsyncFilesys.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// p_AsyncFilesys.cpp\t\tGRJ 11 Oct 2002\r\n//\r\n// Asynchronous file system\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <sys/config/config.h>\r\n\r\n#include <sys/file/xbox/p_AsyncFilesys.h>\r\n\r\nnamespace File\r\n{\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic uint32 RoundToNearestSectorSize( uint32 size )\r\n{\r\n\t// Round up to the nearest sector size of a DVD, which is 2048 bytes.\r\n\treturn ( size + 0x7FF ) & ~0x7FF;\r\n}\r\n\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxAsyncFileHandle::CXboxAsyncFileHandle( void )\r\n{\r\n\tm_num_open_requests\t\t= 0;\r\n\tmp_non_aligned_buffer\t= NULL;\r\n\tmp_temp_aligned_buffer\t= NULL;\r\n\tmh_file\t\t\t\t\t= INVALID_HANDLE_VALUE;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCXboxAsyncFileHandle::~CXboxAsyncFileHandle()\r\n{\r\n}\r\n\t\r\n\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxAsyncFileHandle::plat_open( const char *filename )\r\n{\r\n\tm_position = 0;\r\n\r\n\t// The following code duplicates that in prefopen(). At some point the filenme modification code\r\n\t// should probably be abstracted out.\r\n\r\n\t// Used for prepending the root data directory on filesystem calls.\r\n\tchar\t\tnameConversionBuffer[256] = \"d:\\\\data\\\\\";\r\n\tint\t\t\tindex = 8;\r\n\tconst char*\tp_skip;\r\n\r\n\tif(( filename[0] == 'c' ) && ( filename[1] == ':' ))\r\n\t{\r\n\t\t// Filename is of the form c:\\skate4\\data\\foo...\r\n\t\tp_skip = filename + 15;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Filename is of the form foo...\r\n\t\tp_skip = filename;\r\n\t}\r\n\r\n\twhile( nameConversionBuffer[index] = *p_skip )\r\n\t{\r\n\t\t// Switch forward slash directory separators to the supported backslash.\r\n\t\tif( nameConversionBuffer[index] == '/' )\r\n\t\t{\r\n\t\t\tnameConversionBuffer[index] = '\\\\';\r\n\t\t}\r\n\t\t++index;\r\n\t\t++p_skip;\r\n\t}\r\n\tnameConversionBuffer[index] = 0;\r\n\r\n\t// If this is a .tex file, switch to a .txx file.\r\n\tif((( nameConversionBuffer[index - 1] ) == 'x' ) &&\r\n\t   (( nameConversionBuffer[index - 2] ) == 'e' ) &&\r\n\t   (( nameConversionBuffer[index - 3] ) == 't' ))\r\n\t{\r\n\t\tnameConversionBuffer[index - 2] = 'x';\r\n\t}\r\n\r\n\t// If this is a .pre file, switch to a .prx file.\r\n\tif((( nameConversionBuffer[index - 1] ) == 'e' ) &&\r\n\t   (( nameConversionBuffer[index - 2] ) == 'r' ) &&\r\n\t   (( nameConversionBuffer[index - 3] ) == 'p' ))\r\n\t{\r\n\t\tnameConversionBuffer[index - 1] = 'x';\r\n\t}\r\n\r\n\tinc_busy_count();\r\n\r\n\tmh_file = CreateFile(\tnameConversionBuffer,\t\t\t\t\t\t\t// File name\r\n\t\t\t\t\t\t\tGENERIC_READ,\t\t\t\t\t\t\t\t\t// Access mode\r\n\t\t\t\t\t\t\tFILE_SHARE_READ,\t\t\t\t\t\t\t\t// Share mode\r\n\t\t\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t\t\t\t// SD\r\n\t\t\t\t\t\t\tOPEN_EXISTING,\t\t\t\t\t\t\t\t\t// How to create\r\n\t\t\t\t\t\t\tFILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,\t// File attributes\r\n\t\t\t\t\t\t\tNULL );\t\t\t\t\t\t\t\t\t\t\t// Handle to template file\r\n\r\n\tif( mh_file == INVALID_HANDLE_VALUE )\r\n\t{\r\n        return false;\r\n\t}\r\n\r\n\t// Immediately obtain the file size.\r\n\tm_file_size = ::GetFileSize( mh_file, NULL );\r\n\tDbg_Assert( m_file_size != -1 );\r\n\r\n\t// Round to nearest sector size, since this will be required for async reads anyway.\r\n\tm_file_size = RoundToNearestSectorSize( m_file_size );\r\n\r\n\tio_callback( m_current_function, (int)mh_file, m_file_size );\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxAsyncFileHandle::io_callback( EAsyncFunctionType function, int result, uint32 data )\r\n{\r\n\t// Do any special function processing\r\n\tswitch (function)\r\n\t{\r\n\t\tcase FUNC_OPEN:\r\n\t\t{\r\n\t\t\tif( result < 0 )\r\n\t\t\t{\r\n//\t\t\t\tDbg_MsgAssert( 0, ( \"Error: Async open returned %d\", result ));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_file_size = data;\r\n\t\t\t}\r\n//\t\t\tShowAsyncInfo(\"io_callback: Open returned handle index %d with filesize %d\\n\", result, data);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\tcase FUNC_SEEK:\r\n\t\tif (result < 0)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"Error: Async seek returned %d\", result));\r\n\t\t} else {\r\n\t\t\tm_position = result;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\tcase FUNC_LOAD:\r\n\tcase FUNC_READ:\r\n\t\tif (mp_temp_aligned_buffer && (result > 0))\r\n\t\t{\r\n\t\t\tmemcpy(mp_non_aligned_buffer, mp_temp_aligned_buffer, result);\r\n\t\t}\r\n\t\t// don't break, continue on below\r\n\r\n\tcase FUNC_WRITE:\r\n\t\tif (result < 0)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"Error: Async IO returned %d\", result));\r\n\t\t} else {\r\n\t\t\tm_position += result;\r\n\t\t\tif (mp_temp_aligned_buffer)\r\n\t\t\t{\r\n\t\t\t\tdelete mp_temp_aligned_buffer;\r\n\t\t\t\tmp_non_aligned_buffer = NULL;\r\n\t\t\t\tmp_temp_aligned_buffer = NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\tcase FUNC_IDLE:\r\n\t\t// Don't want m_busy to change or user-defined callback to be executed\r\n\t\treturn;\r\n\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\t// Check to make sure request buffer will be clear\r\n\tif (get_busy_count() > 0)\r\n\t{\r\n\t\t//Dbg_MsgAssert(m_num_open_requests == 1, (\"Sill other open requests\"));\r\n\t}\r\n\r\n\t// Now handle the above p-line stuff\r\n\tCAsyncFileHandle::io_callback(function, result, data);\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxAsyncFileHandle::add_request_id( int request_id, EAsyncFunctionType function )\r\n{\r\n\tif (m_num_open_requests >= NUM_REQUESTS)\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Too many open requests for file handle\"));\r\n\t\treturn false;\r\n\t}\r\n\r\n\tm_open_requests[m_num_open_requests].m_request_id = request_id;\r\n\tm_open_requests[m_num_open_requests++].m_function = function;\r\n\r\n\t//scePrintf(\"Adding request %d to entry #%d for %x with busy %d\\n\", request_id, (m_num_open_requests-1), this, get_busy_count());\r\n\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nEAsyncFunctionType\tCXboxAsyncFileHandle::get_request_function( int request_id ) const\r\n{\r\n\t// Find request id in list\r\n\tfor (int i = 0; i < m_num_open_requests; i++)\r\n\t{\r\n\t\tif (m_open_requests[i].m_request_id == request_id)\r\n\t\t{\r\n\t\t\treturn m_open_requests[i].m_function;\r\n\t\t}\r\n\t}\r\n\r\n\t// Request not found\r\n\tDbg_MsgAssert(0, (\"Can't find request %d on %x\", request_id, this));\r\n\treturn FUNC_IDLE;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxAsyncFileHandle::clear_request_id( int request_id )\r\n{\r\n\tif (m_num_open_requests <= 0)\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't clear request: Open request list empty\"));\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Find request id in list\r\n\tfor (int i = 0; i < m_num_open_requests; i++)\r\n\t{\r\n\t\tif (m_open_requests[i].m_request_id == request_id)\r\n\t\t{\r\n\t\t\t// Just move end of list to here\r\n\t\t\tm_open_requests[i] = m_open_requests[--m_num_open_requests];\r\n\t\t\t//scePrintf(\"Clearing request %d from entry #%d\\n\", request_id, i);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Request not found\r\n\tDbg_MsgAssert(0, (\"Can't clear request: Not found\"));\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxAsyncFileHandle::plat_init( void )\r\n{\r\n\tm_num_open_requests\t\t= 0;\r\n\tmp_non_aligned_buffer\t= NULL;\r\n\tmp_temp_aligned_buffer\t= NULL;\r\n\r\n\t// Set up the overlapped structure.\r\n\tm_overlapped.Offset\t\t= 0;\r\n\tm_overlapped.OffsetHigh\t= 0;\r\n\tm_overlapped.hEvent\t\t= NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvolatile bool CXboxAsyncFileHandle::plat_is_done( void )\r\n{\r\n\tbool is_done = false;\r\n\r\n\tif( m_last_result == ERROR_IO_PENDING )\r\n\t{\r\n\t\tis_done = HasOverlappedIoCompleted( &m_overlapped );\r\n\t\tif( is_done )\r\n\t\t{\r\n\t\t\t// I/O operation is complete, so GetOverlappedResult() should retuen true.\r\n\t\t\tuint32 bt;\r\n\t\t\tbool result\t= GetOverlappedResult(\tmh_file,\t\t// handle to file, pipe, or device\r\n\t\t\t\t\t\t\t\t\t\t\t\t&m_overlapped,\t// overlapped structure\r\n\t\t\t\t\t\t\t\t\t\t\t\t&bt,\t\t\t// bytes transferred\r\n\t\t\t\t\t\t\t\t\t\t\t\tfalse );\t\t// wait option\r\n\r\n\t\t\tDbg_Assert( result );\r\n\r\n\t\t\tm_last_result = ERROR_SUCCESS;\r\n\r\n\t\t\t// Must call this when we are done.\r\n\t\t\tio_callback( m_current_function, bt, 0 );\t\r\n\t\t}\r\n\t}\r\n\treturn is_done;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvolatile bool CXboxAsyncFileHandle::plat_is_busy( void )\r\n{\r\n\treturn ( m_last_result == ERROR_IO_PENDING );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxAsyncFileHandle::plat_is_eof( void ) const\r\n{\r\n\treturn ( m_last_result == ERROR_HANDLE_EOF );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxAsyncFileHandle::plat_set_priority( int priority )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxAsyncFileHandle::plat_set_stream( bool stream )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxAsyncFileHandle::plat_set_destination( EAsyncMemoryType destination )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxAsyncFileHandle::plat_set_buffer_size( size_t buffer_size )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CXboxAsyncFileHandle::plat_set_blocking( bool block )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsize_t CXboxAsyncFileHandle::plat_load( void *p_buffer )\r\n{\r\n\t// This function will just get the file size and do one big read.\r\n\t// Set up the overlapped structure.\r\n\tm_overlapped.Offset\t\t= 0;\r\n\tm_overlapped.OffsetHigh\t= 0;\r\n\tm_overlapped.hEvent\t\t= NULL;\r\n\r\n\t// And do the read.\r\n\treturn plat_read( p_buffer, 1, GetFileSize());\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsize_t CXboxAsyncFileHandle::plat_read( void *p_buffer, size_t size, size_t count )\r\n{\r\n\tuint32 total_bytes = RoundToNearestSectorSize( size * count );\r\n\r\n\tinc_busy_count();\r\n\r\n\tbool result =  ReadFile(\tmh_file,\t\t\t\t\t\t\t// Handle to file\r\n\t\t\t\t\t\t\t\tp_buffer,\t\t\t\t\t\t\t// Data buffer\r\n\t\t\t\t\t\t\t\ttotal_bytes,\t\t\t\t\t\t// Number of bytes to read\r\n\t\t\t\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t// Number of bytes read\r\n\t\t\t\t\t\t\t\t&m_overlapped );\t\t\t\t\t// Overlapped buffer\r\n\r\n\t// If there was a problem, or the async. operation's still pending... \r\n\tif( !result ) \r\n\t{ \r\n\t\t// Deal with the error code. \r\n\t\tm_last_result = GetLastError();\r\n\t\tswitch( m_last_result ) \r\n\t\t{ \r\n\t\t\tcase ERROR_HANDLE_EOF: \r\n\t\t\t{ \r\n\t            // We've reached the end of the file during the call to ReadFile.\r\n\t\t\t\tbreak;\r\n\t\t\t} \r\n \r\n\t\t\tcase ERROR_IO_PENDING: \r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tdefault:\r\n\t\t\t{\r\n\t\t\t\tDbg_Assert( 0 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsize_t CXboxAsyncFileHandle::plat_write( void *p_buffer, size_t size, size_t count )\r\n{\r\n\tDbg_Assert( 0 );\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nchar *CXboxAsyncFileHandle::plat_get_s( char *p_buffer, int maxlen )\r\n{\r\n\tDbg_Assert( 0 );\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint CXboxAsyncFileHandle::plat_seek( long offset, int origin )\r\n{\r\n\tDbg_Assert( 0 );\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CXboxAsyncFileHandle::plat_close( void )\r\n{\r\n\tif( mh_file != INVALID_HANDLE_VALUE )\r\n\t{\r\n\t\tinc_busy_count();\r\n\r\n\t\tCloseHandle( mh_file );\r\n\t\tmh_file = INVALID_HANDLE_VALUE;\r\n\r\n\t\tio_callback( m_current_function, 0, 0 );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\t\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CAsyncFileLoader::s_plat_init( void )\r\n{\r\n\tfor( int i = 0; i < MAX_FILE_HANDLES; ++i )\r\n\t{\r\n\t\tif( s_file_handles[i] )\r\n\t\t{\r\n\t\t\ts_file_handles[i]->init();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ts_file_handles[i] = new CXboxAsyncFileHandle;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CAsyncFileLoader::s_plat_cleanup( void )\r\n{\r\n\tfor( int i = 0; i < MAX_FILE_HANDLES; ++i )\r\n\t{\r\n\t\tif( s_file_handles[i] )\r\n\t\t{\r\n\t\t\tdelete s_file_handles[i];\r\n\t\t\ts_file_handles[i] = NULL;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CAsyncFileLoader::s_plat_async_supported( void )\r\n{\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool CAsyncFileLoader::s_plat_exist( const char *filename )\r\n{\r\n\tHANDLE h_file = CreateFile( filename,\t\t\t\t\t\t\t// File name\r\n\t\t\t\t\t0,\t\t\t\t\t\t\t\t\t\t\t\t// Access mode\r\n\t\t\t\t\tFILE_SHARE_READ,\t\t\t\t\t\t\t\t// Share mode\r\n\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t\t\t\t// SD\r\n\t\t\t\t\tOPEN_EXISTING,\t\t\t\t\t\t\t\t\t// How to create\r\n\t\t\t\t\tFILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,\t// File attributes\r\n\t\t\t\t\tNULL );\t\t\t\t\t\t\t\t\t\t\t// Handle to template file\r\n\r\n\tif( h_file == INVALID_HANDLE_VALUE )\r\n\t{\r\n        return false;\r\n\t}\r\n\r\n\tCloseHandle( h_file );\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nCAsyncFileHandle *CAsyncFileLoader::s_plat_open( const char *filename, int priority )\r\n{\r\n\tCXboxAsyncFileHandle *p_handle = new CXboxAsyncFileHandle();\r\n\tp_handle->plat_init();\r\n\r\n\tbool opened = p_handle->plat_open( filename );\r\n\tif( !opened )\r\n\t{\r\n\t\tdelete p_handle;\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\treturn p_handle;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CAsyncFileLoader::s_plat_swap_callback_list( void )\r\n{\r\n\ts_cur_callback_list_index\t= s_cur_callback_list_index ^ 1;\t// Swap indices...\r\n\ts_new_io_completion\t\t\t= false;\t\t\t\t\t\t\t// ...and clear flag.\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid CAsyncFileLoader::s_plat_update( void )\r\n{\r\n\tfor( int h = 0; h < MAX_FILE_HANDLES; ++h )\r\n\t{\r\n\t\tif( s_file_handles[h] )\r\n\t\t{\r\n\t\t\tif( s_file_handles[h]->IsBusy())\r\n\t\t\t{\r\n\t\t\t\tCXboxAsyncFileHandle*\tp_xbox_handle = static_cast<CXboxAsyncFileHandle*>( s_file_handles[h] );\r\n\t\t\t\tp_xbox_handle->plat_is_done();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n}\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/XBox/p_AsyncFilesys.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tFile\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t10/11/02\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/p_AsyncFilesys.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_FILE_P_ASYNC_FILESYS_H\r\n#define\t__SYS_FILE_P_ASYNC_FILESYS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sys/file/AsyncFilesys.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace File\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CXboxAsyncFileHandle : public CAsyncFileHandle\r\n{\r\npublic:\r\n\r\nprotected:\r\n\r\n\t\t\t\t\t\t\tCXboxAsyncFileHandle();\r\n\tvirtual \t\t\t\t~CXboxAsyncFileHandle();\r\n\r\n\tstatic VOID CALLBACK\tsAsyncFileReadTimerAPCProc( LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue );\r\n\r\nprivate:\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tNUM_REQUESTS = 8\r\n\t};\r\n\r\n\t// Request data\r\n\tstruct SRequest\r\n\t{\r\n\t\tint\t\t\t\t\tm_request_id;\r\n\t\tEAsyncFunctionType\tm_function;\r\n\t};\r\n\r\n\t// Callback functions\r\n\tvirtual void\t\tio_callback(EAsyncFunctionType function, int result, uint32 data);\r\n\r\n\t// Open requests\r\n\tSRequest\t\t  \tm_open_requests[NUM_REQUESTS];\r\n\tvolatile int\t\tm_num_open_requests;\r\n\r\n\t// Non-aligned buffer IO\r\n\tuint8 *\t\t\t\tmp_non_aligned_buffer;\r\n\tuint8 *\t\t\t\tmp_temp_aligned_buffer;\r\n\r\n\t// Xbox-specific file handle.\r\n\tHANDLE\t\t\t\tmh_file;\r\n\tOVERLAPPED\t\t\tm_overlapped;\t// OVERLAPPED structure required for async reading on Xbox\r\n\r\n\tbool\t\t\t\tadd_request_id( int request_id, EAsyncFunctionType function );\r\n\tEAsyncFunctionType\tget_request_function( int request_id ) const;\r\n\tbool\t\t\t\tclear_request_id( int request_id );\r\n\r\n\t// platform-specific calls\r\n\tvirtual void\t\t\tplat_init( void );\r\n\r\n\tvirtual bool\t\t\tplat_open( const char *filename );\r\n\tvirtual bool\t\t\tplat_close( void );\r\n\r\n\tvirtual volatile bool\tplat_is_done( void );\r\n\tvirtual volatile bool\tplat_is_busy( void );\r\n\tvirtual bool\t\t\tplat_is_eof( void ) const;\r\n\r\n\tvirtual void\t\t\tplat_set_priority( int priority );\r\n\tvirtual void\t\t\tplat_set_stream( bool stream );\r\n\tvirtual void\t\t\tplat_set_destination( EAsyncMemoryType destination );\r\n\tvirtual void\t\t\tplat_set_buffer_size( size_t buffer_size );\r\n\tvirtual void\t\t\tplat_set_blocking( bool block );\r\n\r\n\tvirtual size_t\t\t\tplat_load( void *p_buffer );\r\n\tvirtual size_t\t\t\tplat_read( void *p_buffer, size_t size, size_t count );\r\n\tvirtual size_t\t\t\tplat_write( void *p_buffer, size_t size, size_t count );\r\n\tvirtual char *\t\t\tplat_get_s( char *p_buffer, int maxlen );\r\n\tvirtual int\t\t\t\tplat_seek( long offset, int origin );\r\n\r\n\t// Friends\r\n\tfriend CAsyncFileLoader;\r\n};\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace File\r\n\r\n#endif  // __SYS_FILE_P_ASYNC_FILESYS_H\r\n"
  },
  {
    "path": "Code/Sys/File/XBox/p_filesys.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSystem Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tFile IO (File) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_filesys.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t09/25/00\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXBox File System\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n#include <stdio.h>\r\n#include <string.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/AsyncFilesys.h>\r\n#include <sys/file/PRE.h>\r\n#include <sys/file/xbox/p_streamer.h>\r\n#include <sys/config/config.h>\r\n\r\n#include <gfx/xbox/nx/nx_init.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace File\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define READBUFFERSIZE\t\t\t\t10240\r\n#define\tPREPEND_START_POS\t\t\t8\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nBOOL OkayToUseUtilityDrive = FALSE;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/* prefopen\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Same as fopen() except it will prepend the data root directory */\r\n/* For Xbox, path is always relative to location of .xbe image\t  */\r\n/* and default path from that location is d:\\\t\t\t\t\t  */\r\n/* So incoming files of the form:\t\t\t\t\t\t\t\t  */\r\n/* c:\\skate3\\data\\foo...\tbecome\td:\\data\\foo...\t\t\t\t  */\r\n/* foo...\t\t\t\t\tbecome\td:\\data\\foo...\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void* prefopen( const char *filename, const char *mode )\r\n{\r\n\t// Used for prepending the root data directory on filesystem calls.\r\n\tchar\t\tnameConversionBuffer[256] = \"d:\\\\data\\\\\";\r\n\tint\t\t\tindex = PREPEND_START_POS;\r\n\tconst char*\tp_skip;\r\n\r\n\tif(( filename[0] == 'c' ) && ( filename[1] == ':' ))\r\n\t{\r\n\t\t// Filename is of the form c:\\skate4\\data\\foo...\r\n\t\tp_skip = filename + 15;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Filename is of the form foo...\r\n\t\tp_skip = filename;\r\n\t}\r\n\r\n\twhile( nameConversionBuffer[index] = *p_skip )\r\n\t{\r\n\t\t// Switch forward slash directory separators to the supported backslash.\r\n\t\tif( nameConversionBuffer[index] == '/' )\r\n\t\t{\r\n\t\t\tnameConversionBuffer[index] = '\\\\';\r\n\t\t}\r\n\t\t++index;\r\n\t\t++p_skip;\r\n\t}\r\n\tnameConversionBuffer[index] = 0;\r\n\r\n\t// If this is a .tex file, switch to a .txx file.\r\n\tif((( nameConversionBuffer[index - 1] ) == 'x' ) &&\r\n\t   (( nameConversionBuffer[index - 2] ) == 'e' ) &&\r\n\t   (( nameConversionBuffer[index - 3] ) == 't' ))\r\n\t{\r\n\t\tnameConversionBuffer[index - 2] = 'x';\r\n\t}\r\n\r\n\t// If this is a .pre file, switch to a .prx file.\r\n\tif(((( nameConversionBuffer[index - 1] ) == 'e' ) || (( nameConversionBuffer[index - 1] ) == 'x' )) &&\r\n\t    (( nameConversionBuffer[index - 2] ) == 'r' ) &&\r\n\t    (( nameConversionBuffer[index - 3] ) == 'p' ))\r\n\t{\r\n#\t\tifdef __PAL_BUILD__\r\n\t\t// Switch to a .prf, .prg or .prx file, depending on language.\r\n\t\tswitch( Config::GetLanguage())\r\n\t\t{\r\n\t\t\tcase Config::LANGUAGE_FRENCH:\r\n\t\t\t{\r\n\t\t\t\tnameConversionBuffer[index - 1] = 'f';\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase Config::LANGUAGE_GERMAN:\r\n\t\t\t{\r\n\t\t\t\tnameConversionBuffer[index - 1] = 'g';\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:\r\n\t\t\t{\r\n\t\t\t\tnameConversionBuffer[index - 1] = 'x';\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n#\t\telse\r\n\t\tnameConversionBuffer[index - 1] = 'x';\r\n#\t\tendif // __PLAT_BUILD__\r\n\t}\r\n\r\n\t// First we try reading the file from the utility partition (z:\\) on the HD, rather than the DVD.\r\n\tHANDLE h_file = INVALID_HANDLE_VALUE;\r\n\tif( OkayToUseUtilityDrive )\r\n\t{\r\n\t\tnameConversionBuffer[0] = 'Z';\r\n\t\th_file = CreateFile( nameConversionBuffer, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r\n\t}\r\n\r\n\tif( h_file == INVALID_HANDLE_VALUE )\r\n\t{\r\n\t\t// Not on the utility partition, so load it from the DVD.\r\n\t\tnameConversionBuffer[0] = 'D';\r\n\t\th_file = CreateFile( nameConversionBuffer, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r\n\r\n\t\t// Deal with various error returns.\r\n\t\tif( h_file == INVALID_HANDLE_VALUE )\r\n\t\t{\r\n\t\t\tDWORD error = GetLastError();\r\n\r\n\t\t\t// Need to exclude this error from the test, since screenshot and other code sometimes check to see if a file exists, and it\r\n\t\t\t// is valid to just return the error code if it doesn't.\r\n\t\t\tif( error != ERROR_FILE_NOT_FOUND )\r\n\t\t\t{\r\n\t\t\t\t// Catch-all error indicating a fatal problem. Can't continue at this point.\r\n\t\t\t\t// The ideal solution would be a catch/throw exception mechanism, but we don't include exception handling at the moment.\r\n\t\t\t\t// For now just call this NxXbox function, which is slightly messy since it means we have to include a gfx\\ file.\r\n\t\t\t\tprintf( \"FatalFileError: %x %s\\n\", error, nameConversionBuffer );\r\n\t\t\t\tNxXbox::FatalFileError((uint32)INVALID_HANDLE_VALUE );\r\n\t\t\t}\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// All is well.\r\n\t\t\treturn h_file;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn h_file;\r\n\t}\r\n}\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic CThreadedLevelLoader *pLoader;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid InstallFileSystem( void )\r\n{\r\n#\tif 0\r\n\t// This is where we start the thread that will deal with copying commonly used data from the DVD to the utility\r\n\t// region (z:\\) on the HD.\r\n\tpLoader = new CThreadedLevelLoader();\r\n\r\n\tSLevelDesc level_descs[] = {{ \"pre\\\\alc.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\alccol.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\alcscn.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\anims.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\bits.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\cnv.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\cnvcol.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\cnvscn.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\fonts.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\jnk.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\jnkcol.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\jnkscn.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\kon.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\koncol.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\konscn.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\lon.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\loncol.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\lonscn.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\qb.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\sch.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\schcol.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\schscn.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\sf2.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\sf2col.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\sf2scn.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\skaterparts.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\skater_sounds.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\skateshop.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\skateshopcol.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\skateshopscn.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\skeletons.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\zoo.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\zoocol.prx\" },\r\n\t\t\t\t\t\t\t\t{ \"pre\\\\zooscn.prx\" }};\r\n\r\n\tstatic BYTE data_buffer[32 * 1024];\r\n\tpLoader->Initialize( level_descs, 34, data_buffer, 32 * 1024, &OkayToUseUtilityDrive );\r\n\tpLoader->AsyncStreamLevel( 0 );\r\n#\tendif\r\n\r\n\t// Initialise the async file system.\r\n\tFile::CAsyncFileLoader::sInit();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nlong GetFileSize( void* pFP )\r\n{\r\n\tDbg_MsgAssert( pFP, ( \"NULL pFP sent to GetFileSize\" ));\r\n\r\n\tif( PreMgr::sPreEnabled())\r\n    {\r\n\t\tint retval = PreMgr::pre_get_file_size( (PreFile::FileHandle *) pFP );\r\n\t\tif( PreMgr::sPreExecuteSuccess())\r\n\t\t\treturn retval;\r\n\t}\r\n\t\r\n\tLARGE_INTEGER\tli;\r\n\tGetFileSizeEx((HANDLE)pFP, &li );\r\n\treturn (long)li.LowPart;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nlong GetFilePosition( void *pFP )\r\n{\r\n\tDbg_MsgAssert( pFP, ( \"NULL pFP sent to GetFilePosition\" ));\r\n\r\n\tif( PreMgr::sPreEnabled())\r\n\t{\r\n\t\tint retval = PreMgr::pre_get_file_position((PreFile::FileHandle*)pFP );\r\n\t\tif( PreMgr::sPreExecuteSuccess())\r\n\t\t\treturn retval;\r\n\t}\r\n\r\n\tlong pos = SetFilePointer(\t(HANDLE)pFP,\t// Handle to file\r\n\t\t\t\t\t\t\t\t0,\t\t\t\t// Bytes to move pointer\r\n\t\t\t\t\t\t\t\t0,\t\t\t\t// High bytes to move pointer\r\n\t\t\t\t\t\t\t\tFILE_CURRENT );\t// Starting point\r\n\treturn pos;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid InitQuickFileSystem( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint32\tCanFileBeLoadedQuickly( const char* filename )\r\n{\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool LoadFileQuicklyPlease( const char* filename, uint8 *addr )\r\n{\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid StopStreaming( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid UninstallFileSystem( void )\r\n{\r\n}\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Our versions of the ANSI file IO functions. They call\r\n// the PreMgr first to see if the file is in a PRE file.\r\n////////////////////////////////////////////////////////////////////\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Exist( const char *filename )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        bool retval = PreMgr::pre_fexist(filename);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tvoid *p_result = prefopen( filename, \"rb\" );\r\n\tif( p_result != NULL )\r\n\t{\r\n\t\tClose( p_result );\r\n\t}\r\n\r\n\treturn( p_result != NULL );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid * Open( const char *filename, const char *access )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        void * retval = PreMgr::pre_fopen(filename, access);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\treturn prefopen( filename, access );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint Close( void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_fclose((PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tCloseHandle((HANDLE)pFP );\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsize_t Read( void *addr, size_t size, size_t count, void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        size_t retval = PreMgr::pre_fread( addr, size, count, (PreFile::FileHandle*)pFP );\r\n\t\tif( PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tDWORD bytes_read;\r\n\tif( ReadFile((HANDLE)pFP, addr, size * count, &bytes_read, NULL ))\r\n\t{\r\n\t\t// All is well.\r\n\t\treturn bytes_read;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Read error.\r\n\t\tDWORD last_error = GetLastError();\r\n\r\n\t\tif( last_error == ERROR_HANDLE_EOF )\r\n\t\t{\r\n\t\t\t// Continue in this case.\r\n\t\t\treturn bytes_read;\r\n\t\t}\r\n\r\n\t\tNxXbox::FatalFileError( last_error );\r\n\t\treturn bytes_read;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Read an Integer in little endian format. Just read it directly */\r\n/* into memory...\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\nsize_t ReadInt( void *addr, void *pFP )\r\n{\r\n\treturn Read( addr, 4, 1, pFP );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nsize_t Write( const void *addr, size_t size, size_t count, void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        size_t retval = PreMgr::pre_fwrite(addr, size, count, (PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nchar * GetS( char *buffer, int maxlen, void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        char * retval = PreMgr::pre_fgets(buffer, maxlen, (PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint PutS( const char *buffer, void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_fputs(buffer, (PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint Eof( void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_feof((PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint Seek( void *pFP, long offset, int origin )\r\n{\r\n\tif( PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_fseek((PreFile::FileHandle *) pFP, offset, origin);\r\n\t\tif( PreMgr::sPreExecuteSuccess())\r\n\t\t\treturn retval;\r\n\t}\r\n\treturn SetFilePointer((HANDLE)pFP, offset, NULL, ( origin == SEEK_CUR ) ? FILE_CURRENT : (( origin == SEEK_SET ) ? FILE_BEGIN : FILE_END ));\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint Flush( void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_fflush((PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace File\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/XBox/p_pre.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tskate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tXbox specific PRE module \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_pre.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\tdc\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/HashTable.h>\r\n#include <core/StringHashTable.h>\r\n#include <sys/File/PRE.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/config/config.h>\r\n#include <gel/music/music.h>\r\n\r\n// script stuff\r\n#include <gel/scripting/struct.h> \r\n#include <gel/scripting/symboltable.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define DEBUG_PRE 0\r\n\r\nnamespace File\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define CURRENT_PRE_VERSION\t0xabcd0002\t\t\t// as of 3/14/2001\r\n//#define CURRENT_PRE_VERSION\t0xabcd0001\t\t// until 3/14/2001\r\n\r\n#define RINGBUFFERSIZE\t\t 4096\t/* N size of ring buffer */\t\r\n#define MATCHLIMIT\t\t   18\t/* F upper limit for match_length */\r\n#define THRESHOLD\t2   /* encode string into position and length */\r\n\r\n#define WriteOut(x) \t{*pOut++ = x;}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nPreMgr *PreMgr::sp_mgr = NULL;\r\nbool    PreMgr::s_lastExecuteSuccess = false; \r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n#define USE_BUFFER\t1\t\t // we don't need no stinking buffer!!!!\r\n \r\n#if USE_BUFFER\r\nunsigned char\ttext_buf[RINGBUFFERSIZE + MATCHLIMIT - 1];\t\r\n#endif\r\n\r\n\r\n#define\tReadInto(x)\t\tif (!Len) break; Len--; x = *pIn++ \r\n#define\tReadInto2(x)\tLen--; x = *pIn++ \t  // version that knows Len is Ok\r\n\r\n\r\n// Decode an LZSS encoded stream\r\n// Runs at approx 12MB/s on PS2\t without scratchpad (which slows it down in C)\r\n// a 32x CD would run at 4.8MB/sec, although we seem to get a lot less than this\r\n// with our current file system, more like 600K per seconds.....\r\n// Need to write a fast streaming file system....\r\n\r\nvoid DecodeLZSS( unsigned char *pIn, unsigned char *pOut, int Len )\t/* Just the reverse of Encode(). */\r\n{\r\n\tint  i, j, k, r, c;\r\n//\tuint64\tLongWord;\r\n//\tint bytes = 0;\r\n//\tunsigned char *pScratch;\r\n\tunsigned int  flags;\r\n\r\n\r\n\r\n//\tint basetime =  (int) Tmr::ElapsedTime(0);\r\n//\tint len = Len;\r\n\r\n//\tint\tOutBytes = 4;\r\n//\tint\tOutWord = 0;\r\n\r\n#\tif USE_BUFFER\r\n\tfor (i = 0; i < RINGBUFFERSIZE - MATCHLIMIT; i++)\r\n\t\t text_buf[i] = ' ';\r\n\tr = RINGBUFFERSIZE - MATCHLIMIT;\r\n#\telse\r\n\tr = RINGBUFFERSIZE - MATCHLIMIT;\r\n#\tendif\r\n\tflags = 0;\r\n\tfor ( ; ; )\r\n\t{\r\n\t\tif (((flags >>= 1) & 256) == 0)\r\n\t\t{\r\n\t\t\tReadInto(c);\r\n\t\t\tflags = c | 0xff00;\t\t\t/* uses higher byte cleverly */\r\n\t\t}\t\t\t\t\t\t\t\t\t\t/* to count eight */\r\n\t\tif (flags & 1)\r\n\t\t{\r\n\t\t\tReadInto(c);\r\n\t\t\t//\t\t\tputc(c, outfile);\r\n\t\t\tWriteOut(c);\r\n\t\t\t#if USE_BUFFER\r\n\t\t\ttext_buf[r++] = c;\r\n\t\t\tr &= (RINGBUFFERSIZE - 1);\r\n\t\t\t#else\r\n\t\t\tr++;\r\n//\t\t\tr &= (RINGBUFFERSIZE - 1);\t  // don't need to wrap r until it is used\r\n\t\t\t#endif\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tReadInto(i);\t\t\t\r\n\t\t\tReadInto2(j);\t\t\t// note, don't need to check len on this one.... \r\n\t\t\t\r\n\t\t\ti |= ((j & 0xf0) << 4);\t\t\t\t\t\t// i is 12 bit offset\r\n\t\t\t\r\n\t\t\t#if !USE_BUFFER\r\n\t\t\tj = (j & 0x0f) + THRESHOLD+1;\t\t\t\t// j is 4 bit length (above the threshold)\r\n\t\t\tunsigned char *pStream;\r\n\t\t\tr &= (RINGBUFFERSIZE - 1);\t\t\t\t\t// wrap r around before it is used\r\n\t\t\tpStream = pOut - r;\t\t\t\t\t  \t\t// get base of block\r\n\t\t\tif (i>=r)\t\t\t\t\t\t\t\t\t\t// if offset > r, then\r\n\t\t\t\tpStream -= RINGBUFFERSIZE;\t\t\t\t// it's the previous block\r\n\t\t\tpStream += i;\t\t\t\t\t\t\t\t\t// add in the offset to the base\r\n\t\t\tr+=j;\t\t\t\t\t\t\t\t\t\t\t\t// add size to r\r\n\t\t\twhile (j--)\t\t\t\t\t\t\t\t\t\t// copy j bytes\r\n\t\t\t\tWriteOut(*pStream++);\r\n\t\t\t#else\r\n\t\t\t\r\n\t\t\tj = (j & 0x0f) + THRESHOLD;\t\t\t\t// j is 4 bit length (above the threshold)\r\n\t\t\tfor (k = 0; k <= j; k++)\t\t\t\t\t// just copy the bytes\r\n\t\t\t{\r\n\t\t\t\tc =  text_buf[(i+k) & (RINGBUFFERSIZE - 1)]; \r\n\t\t\t\tWriteOut(c);\r\n\t\t\t\ttext_buf[r++] = c;\r\n\t\t\t\tr &= (RINGBUFFERSIZE - 1);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t}\r\n\t}\r\n//\tint Time = (int) Tmr::ElapsedTime(basetime);\r\n//\tif (Time > 5)\r\n//\t{\r\n//\t\tprintf(\"decomp time is %d ms, for %d bytes,  %d bytes/second\\n\", Time,len, len * 1000 /Time );\r\n//\t}\r\n\r\n}\r\n\r\n\r\n\r\n\r\nvoid PreFile::s_delete_file(_File *pFile, void *pData)\r\n{\r\n\tDbg_Assert(pFile);\r\n\tdelete pFile;\r\n}\r\n\r\n\r\n\r\n\r\nPreFile::PreFile(uint8 *p_file_buffer)\r\n{\r\n\tmp_table = new Lst::StringHashTable<_File>(4);\t\r\n\r\n\tDbg_AssertPtr(p_file_buffer);\r\n\r\n\tmp_buffer = p_file_buffer;\r\n\tuint version = *((int *) (mp_buffer + 4));\r\n\tDbg_MsgAssert(version == CURRENT_PRE_VERSION,( \"PRE file version not current\"));\r\n\tm_numEntries = *((int *)(mp_buffer + 8));\r\n\r\n\tuint8 *pEntry = mp_buffer + 12;\r\n\tfor (int i = 0; i < m_numEntries; i++)\r\n\t{\r\n\t\tint data_size \t\t\t\t= *((int *) pEntry);\r\n\t\tint compressed_data_size \t= *((int *) (pEntry + 4));\r\n\t\tint text_size \t\t\t\t= *((int *) (pEntry + 8));\r\n\t\tint actual_data_size = (compressed_data_size != 0) ? compressed_data_size : data_size;\r\n\t\t\t\r\n\t\tchar *pName = (char *) pEntry + 12;\r\n\t\tuint8 *pCompressedData = pEntry + 12 + text_size;\r\n\t\t\r\n\t\t_File *pFile = new (Mem::Manager::sHandle().TopDownHeap()) _File;\r\n\r\n\t\tif (!mp_table->GetItem(pName)) \r\n\t\t{\r\n\t\t\t// file is not in table, safe to add\r\n\t\t\tmp_table->PutItem(pName, pFile);\r\n\r\n\t\tpFile->compressedDataSize = compressed_data_size;\r\n\t\tpFile->pCompressedData = pCompressedData; \r\n\t\tpFile->pData = NULL;\r\n\t\tpFile->sky.POS = 0;\r\n\t\tpFile->sky.SOF = data_size;\r\n\t\t}\r\n\t\telse\r\n\t\t\t// Somehow, file is already in table, just kill it\r\n\t\t\t// Later, I'll want to add an assert\r\n\t\t\tdelete pFile;\r\n\t\t\r\n#\t\tif DEBUG_PRE\r\n\t\tprintf(\"   %s, size %d\\n\", pName, data_size);\r\n#\t\tendif\r\n\t\t\r\n\t\tpEntry += 12 + text_size + ((actual_data_size + 3) & (~3));\r\n\t}\r\n\r\n#\tif DEBUG_PRE\r\n\tprintf(\"Done loading PRE\\n\");\r\n#\tendif\r\n\t\r\n\tmp_activeFile = NULL;\r\n}\r\n\r\n\r\n\r\nPreFile::~PreFile()\r\n{\r\n\tdelete mp_buffer;\r\n\tmp_table->HandleCallback(s_delete_file, NULL);\r\n\tmp_table->FlushAllItems();\r\n\r\n\tdelete mp_table;\r\n}\r\n\r\n\r\n\r\nbool PreFile::FileExists(const char *pName)\r\n{\r\n\t\r\n\t_File *pFile = mp_table->GetItem(pName, false);\r\n\treturn (pFile != NULL);\r\n}\r\n\r\n\r\n\r\n// returns handle pointer\r\nvoid *PreFile::GetContainedFile(const char *pName)\r\n{\r\n\r\n\t_File *pFile = mp_table->GetItem(pName, false);\r\n\tif (!pFile) \r\n\t\treturn NULL;\r\n\t\r\n\tdumbSkyFile *pHandle = &pFile->sky;\r\n\t// kinda roundabout, but sets mp_activeFile\r\n\tGetContainedFileByHandle(pHandle);\r\n\t\r\n\t// do we need to fetch file data?\r\n\tif (!mp_activeFile->pData)\r\n\t{\r\n\t\tif (mp_activeFile->compressedDataSize)\r\n\t\t{\r\n\t\tmp_activeFile->pData = new (Mem::Manager::sHandle().TopDownHeap()) uint8[mp_activeFile->sky.SOF];\t\t\r\n\t\t\t// need to uncompress data\r\n\t\t\tDecodeLZSS(mp_activeFile->pCompressedData, mp_activeFile->pData, mp_activeFile->compressedDataSize);\t\r\n\t\t}\r\n\t}\r\n\r\n\treturn pHandle;\r\n}\r\n\t\r\n\r\n\r\nuint8 *PreFile::GetContainedFileByHandle(void *pHandle)\r\n{\r\n\tmp_table->IterateStart();\r\n\t_File *pFile = mp_table->IterateNext();\r\n\twhile(pFile)\r\n\t{\r\n\t\tuint8 *pCompressedData = pFile->pCompressedData;\r\n\t\tif (pCompressedData && &pFile->sky == pHandle)\r\n\t\t{\r\n\t\t\tmp_activeFile = pFile;\r\n\t\t\t\r\n\t\t\tif (mp_activeFile->compressedDataSize)\r\n\t\t\treturn mp_activeFile->pData;\r\n\t\t\telse\r\n\t\t\t\treturn mp_activeFile->pCompressedData;\r\n\t\t}\r\n\t\tpFile = mp_table->IterateNext();\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n// allocate memory and load file directly from a pre file, if it is there\r\n// This avoids the problem of having to have the decompressed file in memory twice\r\n// when we are loading directly, like with Pip::Load()\r\n// using this enables us to actually load network game, where there is 1MB less heap during loading\r\n//\r\n// returns a pointer to the file in memory\r\n// or NULL if the file is not in this pre file.\r\nvoid *PreFile::LoadContainedFile( const char *pName, int *p_size, void *p_dest )\r\n{\r\n\t// The dest parameter is used only on Ps2.\r\n\tDbg_Assert( p_dest == NULL );\r\n\t\r\n\t_File *pFile = mp_table->GetItem( pName, false );\r\n\tif( !pFile ) \r\n\t{\r\n\t\treturn NULL;\r\n\t}\t\r\n\t\r\n\t*p_size = pFile->sky.SOF;\r\n\t\r\n\tp_dest = Mem::Malloc( pFile->sky.SOF );\r\n\t\r\n\t// Do we need to decompress file data?\r\n\tif( !pFile->pData )\r\n\t{\r\n\t\tif( pFile->compressedDataSize )\r\n\t\t{\r\n\t\t\t// Need to uncompress data.\r\n\t\t\tDecodeLZSS( pFile->pCompressedData, (uint8*)p_dest, pFile->compressedDataSize );\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmemcpy( p_dest, (void*)pFile->pCompressedData, pFile->sky.SOF );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmemcpy( p_dest, (void*)pFile->pData, pFile->sky.SOF );\r\n\t}\r\n\treturn p_dest;\r\n}\r\n\r\n\r\n\r\nvoid PreFile::Reset()\r\n{\r\n\t\r\n\tDbg_AssertPtr(mp_activeFile);\r\n\r\n\tmp_activeFile->sky.POS = 0;\r\n}\r\n\r\n\r\n\r\nuint32 PreFile::Read( void *addr, uint32 count )\r\n{\r\n\t\r\n\tDbg_AssertPtr( mp_activeFile );\r\n\r\n\tint seek_offs = mp_activeFile->sky.POS;\r\n\tunsigned int limit = mp_activeFile->sky.SOF - seek_offs;\r\n\tint copy_number = (count <= limit) ? count : limit; \r\n\tif (mp_activeFile->compressedDataSize)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_activeFile->pData,( \"file not uncompressed\"));\r\n\tmemcpy( addr, mp_activeFile->pData + mp_activeFile->sky.POS, copy_number );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmemcpy(addr, mp_activeFile->pCompressedData + mp_activeFile->sky.POS, copy_number);\r\n\t}\r\n\t\r\n\tmp_activeFile->sky.POS += copy_number;\r\n\r\n#\tif DEBUG_PRE\r\n\tprintf(\"PRE: read %d bytes from file, handle 0x%x\\n\", copy_number, (int) mp_activeFile->pData);\r\n#\tendif\r\n\treturn copy_number;\r\n}\r\n\r\n\r\n\r\nint PreFile::Eof()\r\n{\r\n\t\r\n\tDbg_AssertPtr(mp_activeFile);\r\n\r\n\tif (mp_activeFile->sky.POS >= mp_activeFile->sky.SOF)\r\n\t{\r\n#if DEBUG_PRE\r\n\t\tprintf(\"PRE: at end of file\\n\");\r\n#endif\r\n\t\treturn 1;\r\n\t}\r\n\r\n#if DEBUG_PRE\r\n\tprintf(\"PRE: not at end of file\\n\");\r\n#endif\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nvoid PreFile::Close()\r\n{\r\n\r\n\t//Dbg_MsgAssert(mp_activeFile->pData,( \"file not uncompressed\"));\r\n\r\n\tif (mp_activeFile->pData)\r\n\tdelete mp_activeFile->pData;\r\n\tmp_activeFile->pData = NULL;\r\n}\r\n\r\n\r\n\r\nint PreFile::Seek(long offset, int origin)\r\n{\r\n\tint32 old_pos = mp_activeFile->sky.POS;\r\n\r\n\t// SEEK_CUR, SEEK_END, SEEK_SET\r\n\tswitch(origin)\r\n\t{\r\n\t\tcase SEEK_CUR:\r\n\t\t\tmp_activeFile->sky.POS += offset;\r\n\t\t\tbreak;\r\n\t\tcase SEEK_END:\r\n\t\t\tmp_activeFile->sky.POS = mp_activeFile->sky.SOF - offset;\r\n\t\t\tbreak;\r\n\t\tcase SEEK_SET:\r\n\t\t\tmp_activeFile->sky.POS = offset;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\treturn -1;\r\n\t}\r\n\r\n\tif (mp_activeFile->sky.POS < 0 || mp_activeFile->sky.POS > mp_activeFile->sky.SOF)\r\n\t{\r\n\t\tmp_activeFile->sky.POS = old_pos;\r\n\t\treturn -1;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nPreMgr::PreMgr() \r\n{\r\n\tmp_table = new Lst::StringHashTable<PreFile>(4);\r\n\r\n\tsp_mgr = this;\r\n\r\n\r\n\tmp_activeHandle = NULL;\r\n\tmp_activeData = NULL;\r\n\r\n\tmp_activeNonPreHandle = NULL;\r\n}\r\n\r\n\r\n\r\nPreMgr::~PreMgr()\r\n{\r\n\tdelete mp_table;\r\n}\r\n\r\n\r\n\r\n// Returns handle\r\n// Not frequently called\r\nvoid *PreMgr::getContainedFile(const char *pName)\r\n{\r\n\t\r\n\tDbg_AssertPtr(pName);\r\n\r\n\t// replace all '/' with '\\'\r\n\tchar cleaned_name[128];\r\n\tconst char *pCharIn = pName;\r\n\tchar *pCharOut = cleaned_name;\r\n\twhile (1)\r\n\t{\r\n\t\t*pCharOut = *pCharIn;\r\n\t\tif (*pCharIn == '\\0') break;\r\n\t\tif (*pCharOut == '/') *pCharOut = '\\\\';\r\n\t\tpCharIn++;\r\n\t\tpCharOut++;\t\t\r\n\t}\r\n\r\n\tvoid *pHandle = NULL;\r\n\r\n\tmp_table->IterateStart();\r\n\tPreFile *pPre = mp_table->IterateNext();\r\n\twhile(pPre)\r\n\t{\r\n\t\t\tpHandle = pPre->GetContainedFile(cleaned_name);\r\n\t\tif (pHandle) \r\n\t\t{\r\n\t\t\tmp_activePre = pPre;\r\n\t\t\tmp_activeHandle = pHandle;\r\n\t\t\tmp_activeData = pPre->GetContainedFileByHandle(pHandle);\r\n#\t\t\tifdef __PLAT_NGPS__\r\n//\t\t\tscePrintf(\"+++ %s is in PRE\\n\", cleaned_name);\r\n#\t\t\tendif\r\n\t\t\treturn pHandle;\r\n\t\t}\r\n\t\tpPre = mp_table->IterateNext();\r\n\t}\r\n\r\n#\tifdef __PLAT_NGPS__\r\n//\tscePrintf(\"--- %s not found in PRE\\n\", cleaned_name);\r\n#\tendif\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n// returns true if the file exists in any of the pre files\r\nbool\tPreMgr::fileExists(const char *pName)\r\n{\r\n\tDbg_AssertPtr(pName);\r\n\t// replace all '/' with '\\'\r\n\tchar cleaned_name[128];\r\n\tconst char *pCharIn = pName;\r\n\tchar *pCharOut = cleaned_name;\r\n\twhile (1)\r\n\t{\r\n\t\t*pCharOut = *pCharIn;\r\n\t\tif (*pCharIn == '\\0') break;\r\n\t\tif (*pCharOut == '/') *pCharOut = '\\\\';\r\n\t\tpCharIn++;\r\n\t\tpCharOut++;\t\t\r\n\t}\r\n\r\n\tmp_table->IterateStart();\r\n\tPreFile *pPre = mp_table->IterateNext();\r\n\twhile(pPre)\r\n\t{\r\n\t\tif (pPre->FileExists(cleaned_name))\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tpPre = mp_table->IterateNext();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n// returns pointer to data\r\nuint8 *PreMgr::getContainedFileByHandle(void *pHandle)\r\n{\r\n\t\r\n\tDbg_AssertPtr(pHandle);\r\n\r\n\t// if we know that the file in question is not in the PRE system,\r\n\t// then it's a regular file, don't waste time looking for it\r\n\tif (mp_activeNonPreHandle == pHandle)\r\n\t\treturn NULL;\r\n\t\r\n\tif (mp_activeHandle == pHandle)\r\n\t\t// mp_activePre will be unchanged\r\n\t\treturn mp_activeData;\r\n\t\r\n\tuint8 *pData = NULL;\r\n\tmp_table->IterateStart();\r\n\tPreFile *pPre = mp_table->IterateNext();\r\n\twhile(pPre)\r\n\t{\r\n\t\t\tpData = pPre->GetContainedFileByHandle(pHandle);\r\n\t\tif (pData)\r\n\t\t{\r\n\t\t\tmp_activePre = pPre;\r\n\t\t\tmp_activeHandle = pHandle;\r\n\t\t\tmp_activeData = pData;\t\t\t\r\n\t\t\treturn pData;\r\n\t\t}\r\n\t\tpPre = mp_table->IterateNext();\r\n\t}\r\n\r\n\t// obviously this file is not in the PRE system, mark as such\r\n\tmp_activeNonPreHandle = pHandle;\r\n\treturn NULL;\r\n}\r\n\r\n// there's a wrapper around this now, so that we can do\r\n// some memory-context switching\r\nvoid PreMgr::loadPre(const char *pFilename, bool dont_assert)\r\n{\r\n\tm_blockPreLoading = (bool) Script::GetInt(\"block_pre_loading\", false);\r\n\r\n\tif (m_blockPreLoading)\r\n\t\treturn;\r\n\r\n\tif( Pcm::UsingCD() )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Moved this to below the Pcm::UsingCD() call as that is used (bad!!) to turn off\r\n\t// music and streams.\r\n#\tifdef __PLAT_NGC__\r\n\tOSReport ( \"Warning: Attempting to load pre file: %s (ignored)\\n\", pFilename );\r\n\treturn;\r\n#\tendif // __PLAT_NGC__\r\n\r\n#\tifdef __PLAT_NGPS__\r\n//\tscePrintf(\"Loading PRE file %s...\\n\", pFilename);\r\n#\tendif\r\n\r\n\tchar fullname[256];\r\n\tsprintf(fullname, \"pre\\\\%s\", pFilename);\r\n\r\n\t// Replace the .pre extension with .prx for Xbox PRE file.\r\n\tfullname[strlen( fullname ) - 1] = 'x';\r\n\r\n\t// Create a lower-case version.\r\n\tchar lower[128];\r\n\tfor( unsigned int lp = 0; lp < strlen( fullname ) + 1; lp++ ) lower[lp] = tolower( fullname[lp] );\r\n\r\n\tTmr::Time basetime = Tmr::ElapsedTime(0);\r\n\r\n\tint file_size;\r\n\tuint8 *pFile = NULL;\r\n\r\n\tfile_size = CanFileBeLoadedQuickly( fullname );\r\n\tif ( file_size )\r\n\t{\r\n\t\tpFile = new (Mem::Manager::sHandle().TopDownHeap()) uint8[file_size];\r\n\t\tbool fileLoaded= LoadFileQuicklyPlease( fullname, pFile );\r\n\t\tif ( !fileLoaded )\r\n\t\t{\r\n\t\t\tprintf( \"pre file %s failed to load quickly.\\n\", fullname );\r\n\t\t\tDbg_MsgAssert( 0,( \"Fire Matt - pre file didn't load quickly.\" ));\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n#ifdef __PLAT_NGC__\r\n\t\tNsFile file;\r\n\t\tif ( file.exist( fullname ) )\r\n\t\t{\r\n\t\t\tfile.open( fullname );\r\n#else\r\n\t\t\tvoid *fp = File::Open(fullname, \"rb\");\r\n\t\t\tif (!fp)\r\n\t\t\t{\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\t// always run the code below if CD build\r\n\t\t\t\tif (dont_assert || Config::CD()) \r\n\t\t\t\t{\r\n\t\t\t\t\tprintf(\"couldn't open %s\\n\", fullname);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tDbg_MsgAssert(0,( \"couldn't open %s\\n\", fullname));\r\n\t\t\t}\r\n\r\n\r\n#ifdef __PLAT_NGC__\r\n\t\t\tfile.read( &file_size, 4 );\r\n\t\t\tfile_size = nLtEn32(file_size);\r\n#else\r\n\t\t\tFile::Read(&file_size, 4, 1, fp);\r\n\t\t\tDbg_MsgAssert(file_size > 0,( \"%s has incorrect file size\\n\", fullname));\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t\tif (Config::CD())\r\n\t\t\t{\r\n\t\t\t\tif (file_size <= 0) printf(\"%s has incorrect file size\\n\", fullname);\r\n\t\t\t}\t\r\n\r\n\r\n\t\t// Now allocates the .PRE file from the top of the heap, to avoid fragmentation.\r\n\t\t\tpFile = new (Mem::Manager::sHandle().TopDownHeap()) uint8[file_size];\r\n\t\t//uint8 *pFile = new uint8[file_size];\r\n#ifdef __PLAT_NGC__\r\n\t\t\tfile.read( pFile + 4, file_size );\r\n\t\t\tfile.close();\r\n#else\r\n\t\t\tFile::Read(pFile + 4, 1, file_size, fp);\r\n\t\t\tFile::Close(fp);\r\n#endif\t\t// __PLAT_NGC__\r\n\t\t}\r\n\r\n\t\tprintf(\"load time for file size %d is %d ms\\n\", file_size, (int) Tmr::ElapsedTime(basetime));\r\n\r\n\t// the PRE file object winds up at the top of the heap, too. This is fine because\r\n\t// it will be unloaded at the same time as the big file buffer\r\n\t\tif (!mp_table->PutItem(pFilename, new (Mem::Manager::sHandle().TopDownHeap()) PreFile(pFile)))\r\n\t\t\tDbg_MsgAssert(0,( \"PRE %s loaded twice\", pFilename));\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nDefineSingletonClass(PreMgr, \"PRE Manager\");\r\n\r\n\r\n\r\nbool PreMgr::InPre(const char *pFilename)\r\n{\r\n\r\n\r\n\treturn mp_table->GetItem( pFilename );\r\n}\r\n\r\n\r\n\r\nvoid PreMgr::LoadPre( const char *pFilename, bool dont_assert )\r\n{\r\n\t// GJ:  This function is a wrapper around loadPRE(), to\r\n\t// make sure that all allocations go on the top-down heap\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tloadPre(pFilename, dont_assert);\r\n\tMem::Manager::sHandle().PopContext();\t\r\n}\r\n\r\n\r\n\r\nvoid PreMgr::LoadPrePermanently(const char *pFilename, bool dont_assert)\r\n{\r\n\t// GJ:  This function is a wrapper around LoadPRE(),\r\n\t// used for loading PRE files which will reside in memory\r\n\t// permanently.  Essentially, we need to make sure that the\r\n\t// data is above Renderware's resource arena.  If you didn't\r\n\t// use this function, you'd get fragmentation when the resource\r\n\t// arena resized itself.\r\n\r\n\t// Mick: Removed reference to renderware, the old \"arena\" concept is gone\r\n\r\n\t\r\n\t// Load the pre file...\r\n\t// This will go on the top-down heap by default\r\n\tLoadPre(pFilename, dont_assert);\r\n\r\n}\r\n\r\n\r\n\r\nvoid PreMgr::UnloadPre(const char *pFilename, bool dont_assert)\r\n{\r\n\r\n//\tscePrintf(\"Unloading PRE file %s\\n\", pFilename);\r\n\t\r\n\tif (m_blockPreLoading)\r\n\t\treturn;\r\n\t\r\n\tPreFile *pThePre = mp_table->GetItem(pFilename);\r\n\tif (!pThePre)\r\n\t{\r\n\t\tif (dont_assert) return;\r\n\t\tDbg_MsgAssert(0,( \"PRE file %s not in PRE manager\", pFilename));\r\n\t}\r\n\r\n\tmp_table->FlushItem(pFilename);\r\n\tdelete pThePre;\r\n}\r\n\r\n\r\nbool PreMgr::sPreEnabled()\r\n{\r\n\treturn sp_mgr != NULL;\r\n}\r\n\r\nbool PreMgr::sPreExecuteSuccess()\r\n{\r\n\treturn s_lastExecuteSuccess; \r\n}\r\n\r\n#\tifndef __PLAT_NGC__\r\nbool PreMgr::pre_fexist(const char *name)\r\n{\r\n\tDbg_MsgAssert(name,( \"requesting file NULL\"));\t\r\n\t\r\n\tif( sp_mgr->fileExists( name ))\r\n\t{\r\n#\t\tif DEBUG_PRE\r\n\t\tprintf(\"PRE: file %s exists\\n\", name);\r\n#\t\tendif\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn true;\r\n\t}\r\n\tif ( Pcm::UsingCD( ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn s_lastExecuteSuccess = false;\r\n}\r\n\r\n\r\n\r\nvoid *PreMgr::pre_fopen(const char *name, const char *access)\r\n{\r\n\tDbg_MsgAssert(name,( \"trying to open file NULL\" ));\t\r\n\r\n\tchar nameConversionBuffer[256];\r\n\r\n\t// Just as we do in the Xbox version of prefopen(), if this is a .tex file, switch to a .txx file.\r\n\tint length = strlen( name );\r\n\tstrncpy( nameConversionBuffer, name, length + 1 );\r\n\tif((( nameConversionBuffer[length - 1] ) == 'x' ) &&\r\n\t   (( nameConversionBuffer[length - 2] ) == 'e' ) &&\r\n\t   (( nameConversionBuffer[length - 3] ) == 't' ))\r\n\t{\r\n\t\tnameConversionBuffer[length - 2] = 'x';\r\n\t}\r\n\r\n\tvoid *pHandle = sp_mgr->getContainedFile( nameConversionBuffer );\r\n\tif( pHandle )\r\n\t{\r\n\t\t// if we are going to write the file, we want to use the regular file system\r\n\t\tconst char *pChar = access;\r\n\t\tbool am_writing = false;\r\n\t\twhile(*pChar)\r\n\t\t{\r\n\t\t\tif (*pChar != 'r' && *pChar != 'b')\r\n\t\t\t\tam_writing = true;\r\n\t\t\tpChar++;\r\n\t\t}\r\n\t\t\r\n\t\tif (am_writing)\r\n\t\t{\r\n#\t\t\tifdef __PLAT_NGPS__\r\n//\t\t\tscePrintf(\"    writing file %s\\n\", name);\r\n#\t\t\tendif\r\n\r\n\t\t\t// am writing, so we don't need file open in PRE system\r\n\t\t\tsp_mgr->mp_activePre->Close();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// we're reading the file from the PRE system\r\n#\t\t\tif DEBUG_PRE\r\n\t\t\tprintf(\"PRE: opened file %s, handle is 0x%x\\n\", name, (int) pHandle);\r\n#\t\t\tendif\r\n\t\t\tsp_mgr->mp_activePre->Reset();\r\n\t\t\ts_lastExecuteSuccess = true;\r\n\t\t\treturn pHandle;\r\n\t\t}\r\n\t}\r\n\r\n\t// if we get here, we are using the regular file system\r\n\tif( Pcm::UsingCD())\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"File access forbidden while PCM audio is in progress.\" ));\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\ts_lastExecuteSuccess = false;\r\n\treturn NULL;\r\n\r\n\t//return pHandle;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_fclose(void *fptr)\r\n{\r\n\t\t\r\n\tDbg_MsgAssert(fptr,( \"calling fclose with invalid file ptr\"));\t\r\n\t\r\n\tuint8 *pData = sp_mgr->getContainedFileByHandle(fptr);\r\n\tif (pData)\r\n\t{\r\n#if DEBUG_PRE\r\n\t\tprintf(\"PRE: closed file, handle 0x%x\\n\", (int) fptr);\r\n#endif\r\n\t\tsp_mgr->mp_activePre->Close();\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn 0;\r\n\t}\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nsize_t PreMgr::pre_fread(void *addr, size_t size, size_t count, void *fptr)\r\n{\r\n\t\t\r\n\tDbg_MsgAssert(fptr,( \"calling fread with invalid file ptr\"));\t\t\r\n\r\n\tuint8 *pData = sp_mgr->getContainedFileByHandle( fptr );\r\n\tif (pData)\r\n\t{\r\n\t\t// read from a simulated file stream in PRE file\r\n\t\tDbg_AssertPtr(sp_mgr->mp_activePre);\r\n\r\n\t\t// There is a subtle bug in the PS2 version, in that the pre version of fread()\r\n\t\t// returns the number of bytes read, rather than the number of items. This\r\n\t\t// version does return the correct value.\r\n\t\tsize_t bytes_read = sp_mgr->mp_activePre->Read( addr, size * count );\r\n//\t\treturn bytes_read / size;\r\n\t\treturn bytes_read;\r\n\t}\r\n\tif ( Pcm::UsingCD( ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n\t\treturn 0;\r\n\t}\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nsize_t  PreMgr::pre_fwrite(const void *addr, size_t size, size_t count, void *fptr)\r\n{\r\n\r\n\r\n\tuint8 *pData = sp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"can't write to a PRE file\"));\r\n\t\r\n\tif ( Pcm::UsingCD( ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n\t\treturn 0;\r\n\t}\r\n\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nchar *PreMgr::pre_fgets(char *buffer, int maxLen, void *fptr)\r\n{\r\n\t\t\r\n\r\n\tuint8 *pData = sp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"can't do string ops on a PRE file\"));\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_fputs(const char *buffer, void *fptr)\r\n{\r\n\t\t\r\n\r\n\tuint8 *pData = sp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"can't do string ops on a PRE file\"));\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_feof(void *fptr)\r\n{\r\n\t\t\r\n\tDbg_MsgAssert(fptr,( \"calling feof with invalid file ptr\"));\t\t\r\n\r\n\tuint8 *pData = sp_mgr->getContainedFileByHandle(fptr);\r\n\tif (pData)\r\n\t{\r\n\t\tDbg_AssertPtr(sp_mgr->mp_activePre);\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn sp_mgr->mp_activePre->Eof();\r\n\t}\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_fseek(void *fptr, long offset, int origin)\r\n{\r\n\t\t\r\n\r\n\tuint8 *pData = sp_mgr->getContainedFileByHandle(fptr);\r\n\tif( pData )\r\n\t{\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn sp_mgr->mp_activePre->Seek( offset, origin );\r\n\t}\r\n\r\n\tDbg_MsgAssert( !pData, ( \"seek not supported for PRE file\" ));\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_fflush(void *fptr)\r\n{\r\n\r\n\r\n\tuint8 *pData = sp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"flush not supported for PRE file\"));\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_ftell(void *fptr)\r\n{\r\n\r\n\r\n\tuint8 *pData = sp_mgr->getContainedFileByHandle(fptr);\r\n\tif( pData )\r\n\t{\r\n\t\treturn sp_mgr->mp_activePre->TellActive();\r\n\t}\r\n\r\n\tDbg_MsgAssert( !pData, ( \"tell supported for PRE file\" ));\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n#\tendif\t\t// __PLAT_NGC__\r\n\r\n\r\n\r\n// @script | InPreFile | \r\n// @uparm \"string\" | filename\r\nbool ScriptInPreFile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *pFilename;\r\n\tpParams->GetText(NONAME, &pFilename, true);\r\n\r\n\tSpt::SingletonPtr<PreMgr> pre_mgr;\r\n\treturn pre_mgr->InPre(pFilename);\r\n}\r\n\r\n\r\n\r\n// @script | LoadPreFile | \r\n// @uparm \"string\" | filename\r\n// @flag dont_assert | \r\nbool ScriptLoadPreFile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *pFilename;\r\n\tpParams->GetText(NONAME, &pFilename, true);\r\n\r\n\tSpt::SingletonPtr<PreMgr> pre_mgr;\r\n\tpre_mgr->LoadPre(pFilename, pParams->ContainsFlag(\"dont_assert\"));\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n// @script | UnloadPreFile | \r\n// @flag BoardsPre | \r\n// @flag dont_assert | \r\n// @uparm \"string\" | filename\r\nbool ScriptUnloadPreFile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\r\n\r\n\tSpt::SingletonPtr<PreMgr> pre_mgr;\r\n\t\r\n\tif (pParams->ContainsFlag(\"BoardsPre\"))\r\n\t{\r\n\t\t\r\n//\t\tSpt::SingletonPtr< Mdl::Skate >\tpSkate;\r\n//\t\tpSkate->UnloadBoardPreIfPresent(pParams->ContainsFlag(\"dont_assert\"));\r\n\t\tprintf (\"STUBBED:  Unload BoardsPre, in ScriptUnloadPreFile\\n\");\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tconst char *pFilename;\r\n\tpParams->GetText(NONAME, &pFilename, true);\r\n\r\n\tpre_mgr->UnloadPre(pFilename, pParams->ContainsFlag(\"dont_assert\"));\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\nvoid *PreMgr::LoadFile( const char *pName, int *p_size, void *p_dest )\r\n{\r\n\t// The dest parameter is used only on Ps2.\r\n\tDbg_Assert( p_dest == NULL );\r\n\r\n\t// NOTE: THIS IS JUST CUT AND PASTE FROM Pre::fileExists\r\n\tDbg_AssertPtr( pName );\r\n\r\n\t// Replace all '/' with '\\'\r\n\tchar cleaned_name[128];\r\n\tconst char *pCharIn = pName;\r\n\tchar *pCharOut = cleaned_name;\r\n\twhile (1)\r\n\t{\r\n\t\t*pCharOut = *pCharIn;\r\n\t\tif (*pCharIn == '\\0') break;\r\n\t\tif (*pCharOut == '/') *pCharOut = '\\\\';\r\n\t\tpCharIn++;\r\n\t\tpCharOut++;\t\t\r\n\t}\r\n\r\n\tmp_table->IterateStart();\r\n\tPreFile *pPre = mp_table->IterateNext();\r\n\twhile(pPre)\r\n\t{\r\n\t\t\r\n\t\tvoid *p_data = pPre->LoadContainedFile(cleaned_name,p_size);\r\n\t\tif (p_data)\r\n\t\t{\r\n\t\t\treturn p_data;\r\n\t\t}\r\n\t\tpPre = mp_table->IterateNext();\r\n\t}\r\n\treturn NULL;\r\n\r\n}\r\n\r\n\r\n\r\n} // namespace File\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/XBox/p_streamer.cpp",
    "content": "#include <core/defines.h>\r\n#include <core/crc.h>\r\n#include \"p_streamer.h\"\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// DVD/HD sector sizes (these will never change)\r\n//-----------------------------------------------------------------------------\r\n#define HD_SECTOR_SIZE\t( 512 )\r\n#define DVD_SECTOR_SIZE\t( 2 * 1024 )\r\n\r\nconst char *p_time_string = __TIME__;\r\nconst char *p_date_string = __DATE__;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: CheckDMAAlignment\r\n// Desc: checks the alignment of file offset, read/write size, and \r\n//       target/source memory for DMA IO\r\n//-----------------------------------------------------------------------------\r\n#ifdef _DEBUG\r\nVOID Check_DMA_Alignment( HANDLE hFile, VOID* pBuffer, DWORD dwOffset, DWORD dwNumBytesIO )\r\n{\r\n    // assert proper target memory alignment\r\n    Dbg_Assert( pBuffer );\r\n    Dbg_Assert( (DWORD(pBuffer) & 0x00000003) == 0 );\r\n\r\n     // figure out whether this file is on the DVD or hard disk\r\n    BY_HANDLE_FILE_INFORMATION Info;\r\n    GetFileInformationByHandle( hFile, &Info );\r\n    DWORD dwDVDSerialNumber;\r\n    GetVolumeInformation( \"D:\\\\\", NULL, 0, &dwDVDSerialNumber, NULL, NULL, NULL, 0 );\r\n\r\n    // assert proper file offset and read/write size\r\n    if( Info.dwVolumeSerialNumber == dwDVDSerialNumber )\r\n    {\r\n        Dbg_Assert( dwOffset % DVD_SECTOR_SIZE == 0 );         \r\n        Dbg_Assert( dwNumBytesIO % DVD_SECTOR_SIZE == 0); \r\n    }\r\n    else\r\n    {\r\n        Dbg_Assert( dwOffset % HD_SECTOR_SIZE == 0 );       \r\n        Dbg_Assert( dwNumBytesIO % HD_SECTOR_SIZE == 0 ); \r\n    }\r\n}\r\n#endif\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: CLevelLoader()\r\n// Desc: Constructor\r\n//-----------------------------------------------------------------------------\r\nCLevelLoader::CLevelLoader()\r\n:   m_pSysMemData( NULL ),\r\n    m_dwSysMemSize( 0 ),\r\n    m_pLevels( NULL ),\r\n    m_dwNumLevels( 0 ),\r\n    m_pCurrentLevel( NULL ),\r\n    m_IOState( Idle ),\r\n    m_pSysMemBuffer( NULL ),\r\n    m_pFileSig( NULL ),\r\n    m_hSignature( INVALID_HANDLE_VALUE )\r\n{\r\n    // create file sig buffer\r\n    Dbg_Assert( m_pFileSig == NULL );\r\n    Dbg_Assert( XCALCSIG_SIGNATURE_SIZE + sizeof(SIG_MAGIC) <= HD_SECTOR_SIZE );\r\n\tm_pFileSig = new BYTE[HD_SECTOR_SIZE];\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ~CLevelLoader()\r\n// Desc: Destructor\r\n//-----------------------------------------------------------------------------\r\nCLevelLoader::~CLevelLoader()\r\n{\r\n    // Ensure we are not being deleted in the middle of an IO op.\r\n\tDbg_Assert( IsIdle());\r\n\r\n    // These should be already be cleaned up.\r\n    Dbg_Assert( m_hSignature == INVALID_HANDLE_VALUE );\r\n    Dbg_Assert( m_pSysMemBuffer == NULL );\r\n    Dbg_Assert( m_pFileSig == NULL );\r\n\r\n    // Close all handles.\r\n    for( UINT i = 0; i < m_dwNumLevels; i++ )\r\n    {\r\n        CloseHandle( m_pLevels[i].hDVDFile );\r\n        CloseHandle( m_pLevels[i].hHDFile );\r\n        CloseHandle( m_pLevels[i].hSigFile );\r\n    }\r\n\r\n\t// We don't own this memory, so don't delete it.\r\n    m_pSysMemData = NULL;\r\n\r\n\t// Free the level state array.\r\n\tdelete [] m_pLevels;\r\n\tm_pLevels = NULL;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: Initialize\r\n// Desc: Initialize loader\r\n//-----------------------------------------------------------------------------\r\nHRESULT CLevelLoader::Initialize( SLevelDesc* pDescs, DWORD dwNumLevels, BYTE* pSysMemData, DWORD dwSysMemSize, BOOL *p_signal )\r\n{\r\n\t// Make sure relevant data directories are on the HD utility section.\r\n\tCreateDirectory( \"Z:\\\\data\", NULL );\r\n\tCreateDirectory( \"Z:\\\\data\\\\pre\", NULL );\r\n\tCreateDirectory( \"Z:\\\\data\\\\music\", NULL );\r\n\tCreateDirectory( \"Z:\\\\data\\\\music\\\\wma\", NULL );\r\n\r\n\t// Copy signal.\r\n\tm_pOkayToUseUtilityDrive = p_signal;\r\n\t\r\n\t// Initialize data.\r\n\tDbg_Assert( pSysMemData );\r\n    m_dwSysMemSize\t= dwSysMemSize;\r\n    m_pSysMemData\t= pSysMemData;\r\n\r\n\t// Create level states.\r\n\tm_dwNumLevels = dwNumLevels;\r\n\tm_pLevels = new SLevelState[m_dwNumLevels];\r\n    \r\n\t// Init level states.\r\n    for( UINT i = 0; i < m_dwNumLevels; i++ )\r\n    {\r\n        // Copy level desc.\r\n        m_pLevels[i].Desc = pDescs[i];\r\n\r\n\t\t// Clear file handle.\r\n        m_pLevels[i].hDVDFile\t\t\t= INVALID_HANDLE_VALUE;\r\n        m_pLevels[i].hHDFile\t\t\t= INVALID_HANDLE_VALUE;\r\n        m_pLevels[i].hSigFile\t\t\t= INVALID_HANDLE_VALUE;\r\n        m_pLevels[i].bWasPreCached\t\t= FALSE;\r\n        m_pLevels[i].bWasCacheCorrupted\t= FALSE;\r\n        m_pLevels[i].dwDVDFileSize\t\t= 0;\r\n    }\r\n\r\n\treturn RefreshLevelStates();\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: RefreshLevelStates\r\n// Desc: Refreshes the level loader's level states\r\n//-----------------------------------------------------------------------------\r\nHRESULT CLevelLoader::RefreshLevelStates()\r\n{\r\n    Dbg_Assert( IsIdle());\r\n\r\n    // Init states.\r\n    for( UINT i = 0; i < m_dwNumLevels; i++ )\r\n    {   \r\n        m_pLevels[i].bIsPreCached = FALSE;\r\n        m_pLevels[i].bIsCacheCorrupted = FALSE;\r\n\r\n        m_pLevels[i].bIsOpen = FALSE;\r\n        m_pLevels[i].dwSysMemSize = 0;\r\n        m_pLevels[i].dwVidMemSize = 0;\r\n\r\n        // Close any opened handles.\r\n        CloseHandle( m_pLevels[i].hDVDFile );\r\n        CloseHandle( m_pLevels[i].hSigFile );\r\n        CloseHandle( m_pLevels[i].hHDFile );\r\n\r\n        m_pLevels[i].hDVDFile = INVALID_HANDLE_VALUE;\r\n        m_pLevels[i].hHDFile = INVALID_HANDLE_VALUE;\r\n        m_pLevels[i].hSigFile = INVALID_HANDLE_VALUE;\r\n\r\n    }\r\n    return S_OK;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/* Name: OpenLevel\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Desc: opens a level\t\t\t\t\t\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nHRESULT CLevelLoader::OpenLevel( SLevelState* pLevel, DWORD dwFlags )\r\n{\r\n\t// If the level has never been opened before, open in.\r\n    if( !pLevel->bIsOpen )\r\n    {\r\n        // Check that the level file handles are not open.\r\n        Dbg_Assert( pLevel->hDVDFile == INVALID_HANDLE_VALUE );\r\n        Dbg_Assert( pLevel->hHDFile == INVALID_HANDLE_VALUE );\r\n        Dbg_Assert( pLevel->hSigFile == INVALID_HANDLE_VALUE );\r\n\r\n        char szBuffer[MAX_PATH];\r\n        \r\n\t\t// DVD File.\r\n        sprintf( szBuffer, \"D:\\\\data\\\\%s\", pLevel->Desc.szName );\r\n\r\n        // Open DVD file for reading.\r\n\t\tpLevel->hDVDFile = CreateFile( szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, dwFlags, NULL );\r\n\r\n\t\tif( pLevel->hDVDFile == INVALID_HANDLE_VALUE )\r\n\t\t\treturn EndOpenLevel( pLevel, BadOpen );\r\n\r\n\t\t// Get size of file on DVD. NOTE: This size is used to help detect corrupt cached levels. If a cached level\r\n\t\t// is not the same size as its DVD counterpart, the cached level is considered corrupt.\r\n        pLevel->dwDVDFileSize = ::GetFileSize( pLevel->hDVDFile, NULL );\r\n\r\n\t\t// NOTE: Both files stored on the utility drive (signature file and level) are pre-sized. This prevents the files from\r\n\t\t// becoming fragmented in the FATX.  Also, Overlapped reads/writes to the hard disk are synchronous if the file system\r\n\t\t// has to hit the FATX to determine local->physical cluster mapping.\r\n\r\n        // SIG File.\r\n        sprintf( szBuffer, \"Z:\\\\data\\\\%s.sig\", pLevel->Desc.szName );\r\n\r\n\t\t// See if we have a cached sig.\r\n        pLevel->bIsPreCached = ( GetFileAttributes( szBuffer ) != DWORD( -1 ));\r\n                \r\n\t\t// Open sig file for reading and writing.\r\n        pLevel->hSigFile = CreateFile( szBuffer,\r\n                                       GENERIC_READ | GENERIC_WRITE,\r\n                                       FILE_SHARE_READ |\r\n                                       FILE_SHARE_WRITE |\r\n                                       FILE_SHARE_DELETE,\r\n                                       NULL,\r\n                                       OPEN_ALWAYS,\r\n                                       dwFlags,\r\n                                       NULL );\r\n        if( pLevel->hSigFile == INVALID_HANDLE_VALUE )\r\n            return EndOpenLevel( pLevel, BadOpen );\r\n        \r\n\t\t// Cache is corrupted if sig file is not the right size. NOTE: The sig file is HD_SECTOR_SIZE in size. The actual\r\n\t\t// signature calculated by XCalculateSignature* is much smaller that HD_SECTOR_SIZE, but we must write at least\r\n\t\t// HD_SECTOR_SIZE to use DMA on the hard disk.\r\n\t\tpLevel->bIsCacheCorrupted = pLevel->bIsPreCached && ::GetFileSize( pLevel->hSigFile, NULL ) != HD_SECTOR_SIZE;\r\n        \r\n\t\t// If the sig file is corrupted or not saved, resize it.\r\n        if( !pLevel->bIsPreCached || pLevel->bIsCacheCorrupted )\r\n        {\r\n\t\t\t// Set file size for faster write.\r\n            SetFilePointer( pLevel->hSigFile, HD_SECTOR_SIZE, NULL, FILE_BEGIN );\r\n\t\t\tSetEndOfFile( pLevel->hSigFile );\r\n            \r\n\t\t\t// Clear Sig magic number.\r\n            BYTE apyBuffer[HD_SECTOR_SIZE];\r\n            *(DWORD*)(apyBuffer) = ~SIG_MAGIC;\r\n            SetCurrentFile( pLevel->hSigFile );\r\n            if( FAILED( DoIO( Write, apyBuffer, HD_SECTOR_SIZE )))\r\n                return EndOpenLevel( pLevel, BadSigMagicWrite );\r\n\r\n\t\t\t// Wait for IO completion for sig magic writes.\r\n            while( HasIOCompleted() != S_OK );\r\n        }\r\n\r\n        \r\n        // CACHED file.\r\n        sprintf( szBuffer, \"Z:\\\\data\\\\%s\", pLevel->Desc.szName );\r\n\r\n\t\t// See if we have a cached file.\r\n        pLevel->bIsPreCached = pLevel->bIsPreCached && ( GetFileAttributes( szBuffer ) != DWORD( -1 )); \r\n        \r\n        // Open cached file for reading and writing.\r\n        pLevel->hHDFile = CreateFile( szBuffer,\r\n                                      GENERIC_WRITE | GENERIC_READ, \r\n                                      FILE_SHARE_READ |\r\n                                      FILE_SHARE_WRITE |\r\n                                      FILE_SHARE_DELETE,\r\n                                      NULL,\r\n                                      OPEN_ALWAYS,\r\n                                      dwFlags,\r\n                                      NULL );\r\n\r\n        if( pLevel->hHDFile == INVALID_HANDLE_VALUE )\r\n            return EndOpenLevel( pLevel, BadOpen );\r\n        \r\n\t\t// Cache is corrupted if cache file is not the right size\r\n\t\tpLevel->bIsCacheCorrupted = pLevel->bIsPreCached && (( ::GetFileSize( pLevel->hHDFile, NULL ) != pLevel->dwDVDFileSize ) || pLevel->bIsCacheCorrupted );\r\n\r\n        // If the cache file is corrupted or not saved, resize it.\r\n        if( !pLevel->bIsPreCached || pLevel->bIsCacheCorrupted )\r\n        {\r\n            // Set file size for faster write.\r\n\t\t\tDWORD rv = SetFilePointer( pLevel->hHDFile, pLevel->dwDVDFileSize, NULL, FILE_BEGIN );\r\n\t\t\tif( rv == INVALID_SET_FILE_POINTER )\r\n\t\t\t{\r\n\t\t\t\tDWORD last_error = GetLastError();\r\n\t\t\t\tprintf( \"Last error: %x\\n\", last_error );\r\n\t\t\t}\r\n\t\t\tSetEndOfFile( pLevel->hHDFile );\r\n        }\r\n\t\treturn EndOpenLevel( pLevel, FilesOpened );\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: AsyncStreamLevel\r\n// Desc: Loads all the resources from the given XPR asynchronously using DMA\r\n//-----------------------------------------------------------------------------\r\nVOID CLevelLoader::AsyncStreamLevel( DWORD dwLevel )\r\n{\r\n    Dbg_Assert( IsIdle() );\r\n    Dbg_Assert( dwLevel < m_dwNumLevels );\r\n\r\n\t// We are no longer idle.\r\n\tm_IOState = Begin;\r\n\r\n    // set current level\r\n\tm_pCurrentLevel\t\t= &m_pLevels[dwLevel];\r\n    m_dwCurrentLevel\t= dwLevel;\r\n\r\n\t// Start timer.\r\n\tm_dStartTime = Tmr::GetTime();\r\n}\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: StreamCurrentBundle()\r\n// Desc: updates the streaming state, returning S_OK when finished\r\n//-----------------------------------------------------------------------------\r\nHRESULT CLevelLoader::StreamCurrentLevel()\r\n{\r\n    HRESULT hr;\r\n  \r\n    switch(m_IOState)\r\n    {\r\n        case Begin:\r\n        {\r\n            // reset IO\r\n            ResetStreaming();\r\n\r\n            // if we are reading from the cache, get the signature\r\n            if( IsCurrentCacheGood())\r\n            {\r\n                SetCurrentFile( m_pCurrentLevel->hSigFile );\r\n                if( FAILED( hr = DoIO( Read, m_pFileSig, HD_SECTOR_SIZE )))\r\n                    return EndStreamLevel( BadRead );\r\n            }\r\n            m_IOState = LoadSig;\r\n        }\r\n\r\n        case LoadSig:\r\n        {\r\n            // wait for previous IO to complete\r\n            if( FAILED( hr = HasIOCompleted()))\r\n                return EndStreamLevel( hr == E_PENDING ? Pending : BadRead );\r\n            \r\n            // Reading cached file, so a signature exists\r\n            if( IsCurrentCacheGood())\r\n            {\r\n\t\t\t\t// Look for sig magic number.\r\n\t\t\t\tDWORD dwSig;\r\n\t\t\t\tdwSig = *(DWORD*)( m_pFileSig );\r\n\t\t\t\tif( dwSig != SIG_MAGIC )\r\n                {\r\n                    if( dwSig == ~SIG_MAGIC )\r\n                        return EndStreamLevel( NoSigMagic );\r\n                    else\r\n                        return EndStreamLevel( BadSig );\r\n                }\r\n\t\t\t\t\r\n\t\t\t\t// Check date and time.            \r\n\t\t\t\tdwSig = *(((DWORD*)m_pFileSig ) + 1 );\r\n\t\t\t\tif( dwSig != Crc::GenerateCRCFromString( p_date_string ))\r\n                {\r\n\t\t\t\t\treturn EndStreamLevel( BadSig );\r\n                }\r\n\t\t\t\tdwSig = *(((DWORD*)m_pFileSig ) + 2 );\r\n\t\t\t\tif( dwSig != Crc::GenerateCRCFromString( p_time_string ))\r\n                {\r\n\t\t\t\t\treturn EndStreamLevel( BadSig );\r\n                }\r\n\t\t\t}\r\n            else\r\n\t\t\t{\r\n                // Set sig magic number so it is written out.\r\n                *(((DWORD*)m_pFileSig )\t+ 0 )\t= SIG_MAGIC;\r\n                *(((DWORD*)m_pFileSig ) + 1 )\t= Crc::GenerateCRCFromString( p_date_string );\r\n                *(((DWORD*)m_pFileSig ) + 2 )\t= Crc::GenerateCRCFromString( p_time_string );\r\n\t\t\t}\r\n\r\n            m_IOState = LoadSysMem;\r\n        }\r\n\r\n        case LoadSysMem:\r\n        {\r\n            // Wait for previous IO to complete.\r\n            if( FAILED( hr = HasIOCompleted()))\r\n                return EndStreamLevel( hr == E_PENDING ? Pending : BadRead );\r\n        \r\n            // Read initial system memory buffer.\r\n            if( IsCurrentCacheGood())\r\n\t\t\t{\r\n\t\t\t\t// At this point we have decided the sig file is fine, which indicates that the cached file is fine also.\r\n\t\t\t\t// As such, no further work required for this file.\r\n//\t\t\t\tSetCurrentFile( m_pCurrentLevel->hHDFile );\r\n\t\t\t\tm_pCurrentLevel->bIsPreCached = TRUE;\r\n\t\t\t\tm_pCurrentLevel->bIsCacheCorrupted = FALSE;\r\n\t\t\t\treturn EndStreamLevel( Finished );\r\n\t\t\t}\r\n            else\r\n\t\t\t{\r\n\t\t\t\t// Set file pointer to start of HD file.\r\n                SetCurrentFile( m_pCurrentLevel->hHDFile );\r\n\t\t\t\t\r\n\t\t\t\t// Set file pointer to start of DVD file.\r\n                SetCurrentFile( m_pCurrentLevel->hDVDFile );\r\n\t\t\t}\r\n\r\n\t\t\t// At this point we want to loop through reading the buffer and writing it until teh file is fully written.\r\n\t\t\tDWORD\ttotal_bytes_read\t\t= 0;\r\n\t\t\tDWORD\ttotal_bytes_written\t\t= 0;\r\n\t\t\tint\t\tbytes_remaining\t\t\t= m_pCurrentLevel->dwDVDFileSize;\r\n\t\t\tfor( ;; )\r\n\t\t\t{\r\n\t\t\t\t// Set the DVD file, but don't reset the file pointer.\r\n                SetCurrentFile( m_pCurrentLevel->hDVDFile, FALSE );\r\n\r\n//\t\t\t\tDWORD bytes_to_transfer = ( bytes_remaining >= m_dwSysMemSize ) ? m_dwSysMemSize : bytes_remaining;\r\n\t\t\t\tDWORD bytes_to_transfer = ( bytes_remaining >= (int)m_dwSysMemSize ) ? m_dwSysMemSize : m_dwSysMemSize;\r\n\t\t\t\t\r\n\t\t\t\tif( FAILED( DoIO( Read, m_pSysMemData, bytes_to_transfer )))\r\n\t                return EndStreamLevel( BadRead );\r\n\r\n\t\t\t\ttotal_bytes_read += bytes_to_transfer;\r\n\r\n\t\t\t\t// Set the HD file, but don't reset the file pointer.\r\n\t\t\t\tSetCurrentFile( m_pCurrentLevel->hHDFile, FALSE );\r\n\r\n\t\t\t\tif( FAILED( DoIO( Write, m_pSysMemData, bytes_to_transfer )))\r\n\t                return EndStreamLevel( BadWrite );\r\n\t\t\t\t\r\n\t\t\t\ttotal_bytes_written += bytes_to_transfer;\r\n\t\t\t\tbytes_remaining -= bytes_to_transfer;\r\n\t\t\t\t\r\n\t\t\t\tif( bytes_remaining <= 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tDWORD rv = SetFilePointer( m_pCurrentLevel->hHDFile, m_pCurrentLevel->dwDVDFileSize, NULL, FILE_BEGIN );\r\n\t\t\t\t\tif( rv == INVALID_SET_FILE_POINTER )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDWORD last_error = GetLastError();\r\n\t\t\t\t\t\tprintf( \"Last error: %x\\n\", last_error );\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tSetEndOfFile( m_pCurrentLevel->hHDFile );\r\n\t\t\t\t\t\r\n\t\t\t\t\tm_IOState = WriteSig;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n        }\r\n\r\n        case WriteSig:\r\n        {\r\n            // Wait for previous IO to complete.\r\n            if( FAILED( hr = HasIOCompleted() ) )\r\n                return EndStreamLevel( hr == E_PENDING ? Pending : BadRead );\r\n    \r\n\t\t\t// We are now loaded.\r\n\t\t\tm_dLoadTime = Tmr::GetTime() - m_dStartTime;\r\n\r\n            // We write the sig file last. If the box is turned off during a cache operation, the sig file will be missing.\r\n            // If the box is turned off during the write of the sig file, it won't have a header or will not match the level\r\n            // data. In either case, the level will be re-cached.\r\n            SetCurrentFile( m_pCurrentLevel->hSigFile );\r\n            if( FAILED( hr = DoIO( Write, m_pFileSig, HD_SECTOR_SIZE) ) )\r\n                return EndStreamLevel( BadWrite );\r\n\r\n            m_IOState = End;\r\n        }\r\n\r\n        case End:\r\n        {\r\n            // Wait for previous IO to complete.\r\n            if( FAILED( hr = HasIOCompleted() ) )\r\n                return EndStreamLevel( hr == E_PENDING ? Pending : BadRead );\r\n    \r\n\t\t\t// Record cache time.\r\n\t\t\tm_dCacheTime = Tmr::GetTime() - m_dStartTime;\r\n\r\n\t\t\t// We are now cached.\r\n            m_pCurrentLevel->bIsPreCached\t\t= TRUE;\r\n            m_pCurrentLevel->bIsCacheCorrupted\t= FALSE;\r\n\r\n            return EndStreamLevel( Finished );\r\n        }\r\n    }\r\n\r\n    // should never reach here\r\n    Dbg_Assert( FALSE );\r\n    return E_FAIL;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: EndOpenLevel()\r\n// Desc: called when IO has completed or there is an error\r\n//-----------------------------------------------------------------------------\r\nHRESULT CLevelLoader::EndOpenLevel( SLevelState* pLevel, FileOpenStatus Status)\r\n{\r\n    Dbg_Assert(pLevel);\r\n\r\n    if(Status == BadOpen || Status == BadSigMagicWrite)\r\n    {\r\n        // close all file handles\r\n        CloseHandle( pLevel->hDVDFile );\r\n        CloseHandle( pLevel->hHDFile );\r\n        CloseHandle( pLevel->hSigFile );\r\n        pLevel->hDVDFile = INVALID_HANDLE_VALUE;\r\n        pLevel->hHDFile = INVALID_HANDLE_VALUE;\r\n        pLevel->hSigFile = INVALID_HANDLE_VALUE;\r\n\r\n        return E_FAIL;\r\n    }\r\n\r\n    // level is now opened\r\n    pLevel->bIsOpen = TRUE;\r\n\r\n    return S_OK;\r\n}\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: EndStreamLevel()\r\n// Desc: called when IO has completed or there is an error\r\n//-----------------------------------------------------------------------------\r\nHRESULT CLevelLoader::EndStreamLevel( FileIOStatus Status )\r\n{\r\n    // if IO is not pending, we are finished\r\n    if(Status != Pending)\r\n    {\r\n        // close the signature if needed\r\n        if( m_hSignature != INVALID_HANDLE_VALUE )\r\n        {\r\n            XCalculateSignatureEnd( m_hSignature, NULL );\r\n            m_hSignature = INVALID_HANDLE_VALUE;\r\n        }\r\n    }\r\n\r\n    // determine new state\r\n    switch(Status)\r\n    {\r\n        case BadRead:\r\n        case BadHeader:\r\n        case BadSig:\r\n        case SigMismatch:\r\n            m_pCurrentLevel->bIsCacheCorrupted = TRUE;\r\n            m_IOState = Begin; // retry streaming the level\r\n            return E_FAIL;\r\n        case NoSigMagic:\r\n            m_pCurrentLevel->bIsPreCached = FALSE;\r\n            m_IOState = Begin; // retry streaming the level\r\n            return E_FAIL;\r\n        case BadWrite:  // if we have a bad write, finish anyways since the cache will be corrupt next time around\r\n            m_pCurrentLevel->bIsCacheCorrupted = TRUE;\r\n        case Finished:\r\n            m_IOState = Idle;  // done with IO, so we are now idle\r\n\r\n\t\t\t// close all file handles\r\n\t\t\tCloseHandle( m_pCurrentLevel->hDVDFile );\r\n\t\t\tCloseHandle( m_pCurrentLevel->hHDFile );\r\n\t\t\tCloseHandle( m_pCurrentLevel->hSigFile );\r\n\t\t\tm_pCurrentLevel->hDVDFile = INVALID_HANDLE_VALUE;\r\n\t\t\tm_pCurrentLevel->hHDFile = INVALID_HANDLE_VALUE;\r\n\t\t\tm_pCurrentLevel->hSigFile = INVALID_HANDLE_VALUE;\r\n\t\t\t\r\n\t\t\treturn S_OK;\r\n        case Pending:\r\n            return E_PENDING;\r\n    }\r\n\r\n    // should never reach here\r\n    Dbg_Assert( FALSE );\r\n    return E_FAIL;\r\n}\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: CRestIO()\r\n// Desc: Records last state for current level and get ready for IO\r\n//-----------------------------------------------------------------------------\r\nVOID CLevelLoader::ResetStreaming()\r\n{\r\n    // record last state\r\n    m_pCurrentLevel->bWasPreCached = m_pCurrentLevel->bIsPreCached;\r\n    m_pCurrentLevel->bWasCacheCorrupted = m_pCurrentLevel->bIsCacheCorrupted;\r\n\r\n    // begin signature\r\n    Dbg_Assert( m_hSignature == INVALID_HANDLE_VALUE );\r\n    m_hSignature = XCalculateSignatureBegin( XCALCSIG_FLAG_NON_ROAMABLE );\r\n    Dbg_Assert( m_hSignature != INVALID_HANDLE_VALUE );\r\n\r\n    // create file sig buffer\r\n//    Dbg_Assert( m_pFileSig == NULL );\r\n//    Dbg_Assert( XCALCSIG_SIGNATURE_SIZE + sizeof(SIG_MAGIC) <= HD_SECTOR_SIZE );\r\n//    m_pFileSig = new BYTE[HD_SECTOR_SIZE];\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: IOProc\r\n// Desc: Thread proc for IO\r\n//-----------------------------------------------------------------------------\r\nDWORD WINAPI IOProc( LPVOID lpParameter )\r\n{\r\n    CThreadedLevelLoader* pLoader = (CThreadedLevelLoader*)lpParameter;\r\n    Dbg_Assert( pLoader );\r\n   \r\n\t// Wait for the IO event to be signaled.\r\n\tWaitForSingleObject( pLoader->m_hEvent, INFINITE );\r\n\t\r\n\tfor( ;; )\r\n    {\r\n        \r\n        // NOTE: In the threaded version of the loader, we are able to open\r\n        //       files and set file sizes mid-game without noticing a severe\r\n        //       frame \"glitch.\"  If you use overlapped IO, you must remember\r\n        //       that OpenFile, SetEndOfFile, etc. are blocking\r\n\r\n        // open the current level\r\n        // If we can't open files, we are in trouble, so in the release build, we just keep trying\r\n//        while( FAILED( pLoader->OpenLevel( pLoader->m_pCurrentLevel, FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN )))\r\n        while( FAILED( pLoader->OpenLevel( pLoader->m_pCurrentLevel, FILE_FLAG_SEQUENTIAL_SCAN )))\r\n        {\r\n            // break in the debug build to find out what the problem is\r\n            Dbg_Assert( FALSE );\r\n        }\r\n    \r\n        // Keep trying to load and cache the level until we are successful.\r\n        while( FAILED( pLoader->StreamCurrentLevel()));\r\n\r\n\t\t// Level loaded and cached.\r\n\t\t++pLoader->m_dwCurrentLevel;\r\n\t\tif( pLoader->m_dwCurrentLevel < pLoader->m_dwNumLevels )\r\n\t\t{\r\n\t\t\tpLoader->m_pCurrentLevel = &pLoader->m_pLevels[pLoader->m_dwCurrentLevel];\r\n\t\t\tpLoader->m_IOState = CThreadedLevelLoader::Begin;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\r\n\t}\r\n\r\n\t// If the loaded has closed the thread we are finished. Signal the boolean value passed in.\r\n\t*( pLoader->m_pOkayToUseUtilityDrive ) = true;\r\n\r\n\tExitThread( 0 );\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: CThreadedLevelLoader()\r\n// Desc: Constructor\r\n//-----------------------------------------------------------------------------\r\nCThreadedLevelLoader::CThreadedLevelLoader() : m_bKillThread( FALSE )\r\n{\r\n    // Create event that is used to block the thread when it is not being used for IO.\r\n    m_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );\r\n\r\n    // Create IO thread.\r\n    m_hThread =  CreateThread( NULL, 0, IOProc, this, 0, NULL);     \r\n\r\n\tSetCurrentFile( INVALID_HANDLE_VALUE );\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: ~CThreadedLevelLoader()\r\n// Desc: Destructor\r\n//-----------------------------------------------------------------------------\r\nCThreadedLevelLoader::~CThreadedLevelLoader()\r\n{\r\n    Dbg_Assert( IsIdle() );\r\n\r\n    // Kill the thread.\r\n\r\n    // signal thread \r\n    m_bKillThread = TRUE;\r\n    SetEvent( m_hEvent );\r\n    \r\n    // wait for thread to exit\r\n    DWORD dwExitStatus;\r\n    do\r\n    {\r\n        SwitchToThread();  // try to get the thread to execute\r\n        GetExitCodeThread( m_hThread, &dwExitStatus );\r\n    }\r\n    while( dwExitStatus == STILL_ACTIVE );\r\n\r\n    // close handle to thread and event\r\n    CloseHandle( m_hThread );\r\n    CloseHandle( m_hEvent );\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: DoIO\r\n// Desc: wrapper for ::ReadFile and ::WriteFile that checks parameters\r\n//-----------------------------------------------------------------------------\r\nHRESULT CThreadedLevelLoader::DoIO( IOType Type, VOID* pBuffer, DWORD dwNumBytes )\r\n{\r\n    // Check DMA alignment\r\n#\tifdef _DEBUG\r\n    Check_DMA_Alignment( m_hFile, pBuffer, SetFilePointer( m_hFile, 0, NULL, FILE_CURRENT ), dwNumBytes );\r\n#\tendif\r\n\r\n    // Do IO\r\n    DWORD dwNumBytesIO;\r\n    BOOL bSuccess;\r\n    if(Type == Read)\r\n    {\r\n        bSuccess = ::ReadFile( m_hFile, pBuffer, dwNumBytes, &dwNumBytesIO, NULL );\r\n    }\r\n    else\r\n        bSuccess = ::WriteFile( m_hFile, pBuffer, dwNumBytes, &dwNumBytesIO, NULL );\r\n\r\n\t// If IO is successful and we have the number of expected bytes, return success.\r\n    // NOTE: If the file size is X*SECTORSIZE + Y where Y is less than SECTORSIZE, we still request SECTORSIZE bytes when reading Y\r\n    // in order to get DMA. The file system will return success, and the number of bytes read/written is Y.\r\n    if( !bSuccess || ( dwNumBytesIO != dwNumBytes && SetFilePointer( m_hFile, 0, NULL, FILE_CURRENT ) != GetFileSize( m_hFile, NULL )))\r\n//\tif( !bSuccess )\r\n        return E_FAIL;\r\n        \r\n    return S_OK;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: SetCurrentFile\r\n// Desc: Sets the current file to be used during IO\r\n//-----------------------------------------------------------------------------\r\nVOID CThreadedLevelLoader::SetCurrentFile( HANDLE hFile, BOOL to_start )\r\n{\r\n\tif(( hFile != INVALID_HANDLE_VALUE ) && to_start )\r\n\t{\r\n\t\t// Reset file pointer to beginning.\r\n\t\tSetFilePointer( hFile, 0, NULL, FILE_BEGIN );\r\n\t}\r\n    m_hFile = hFile;\r\n}\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: AsyncStreamLevel\r\n// Desc: Begins streaming of the level.  returns immediately\r\n//-----------------------------------------------------------------------------\r\nVOID CThreadedLevelLoader::AsyncStreamLevel( DWORD dwLevel )\r\n{\r\n    CLevelLoader::AsyncStreamLevel( dwLevel );\r\n\r\n\t// Signal thread to start IO.\r\n\tSetEvent( m_hEvent );\r\n}\r\n"
  },
  {
    "path": "Code/Sys/File/XBox/p_streamer.h",
    "content": "//-----------------------------------------------------------------------------\r\n// File: LevelLoader.h\r\n//\r\n// Desc: Asynchronously loads and caches level data from XPR (Xbox Packed\r\n// Resource) files using DMA.  \r\n//\r\n// Hist: 03.12.02 - New for May XDK release\r\n//\r\n// Copyright (c) Microsoft Corporation. All rights reserved.\r\n//-----------------------------------------------------------------------------\r\n#ifndef LEVEL_LOADER_H\r\n#define LEVEL_LOADER_H\r\n\r\n#include <xtl.h>\r\n#include <xgraphics.h>\r\n#include <cstdio>\r\n#include <sys\\timer.h>\r\n\r\n\r\n\r\n// NOTE: The terms \"system memory\" and \"video memory\" are used throughout the\r\n//       source code.  \"Video memory\" is continuous physically addressed\r\n//       write-combining memory that is used for GPU resources. \"System memory\"\r\n//       is virtually addressed cached memory that is used by the CPU.\r\n\r\n//-----------------------------------------------------------------------------\r\n// SIG_MAGIC\r\n// Marker that specifies that a signature file exists and is valid.\r\n// Overlapped IO may open and pre-size a file without writing to it and\r\n// we want to detect this without signaling a corruption error.\r\n//-----------------------------------------------------------------------------\r\n#define SIG_MAGIC 0xF0F0F0F0ul\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: SLevelDesc\r\n// Desc: Struct that describes a level\r\n//-----------------------------------------------------------------------------\r\nstruct SLevelDesc\r\n{\r\n    const CHAR* szName;          // level is assumed to be at media\\szName.xpr\r\n//    DWORD       dwNumResources;  // number of resources in level\r\n//    XBRESOURCE* pResourceTags;   // array or resource tags\r\n};\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: SLevelState\r\n// Desc: Struct to hold state about a level\r\n//-----------------------------------------------------------------------------\r\nstruct SLevelState\r\n{\r\n    SLevelDesc  Desc;\r\n    DWORD       dwDVDFileSize;   // size of level on DVD.  used for error\r\n                                 // detection\r\n    // state of level cache\r\n    BOOL        bIsPreCached;            \r\n    BOOL        bWasPreCached;\r\n    BOOL        bIsCacheCorrupted;\r\n    BOOL        bWasCacheCorrupted;\r\n\r\n    // memory requirements for the level\r\n    DWORD       dwSysMemSize;       \r\n    DWORD       dwVidMemSize;\r\n\r\n    // level file handles\r\n    HANDLE      hDVDFile;       // DVD file handle\r\n    HANDLE      hHDFile;        // Utility region file handle\r\n    HANDLE      hSigFile;       // signature file handle\r\n\r\n    BOOL        bIsOpen;        // are the handles opened\r\n};\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: class CLevelLoader\r\n// Desc: Cached level base class\r\n//       Handles loading and caching of levels\r\n//-----------------------------------------------------------------------------\r\nclass CLevelLoader \r\n{\r\npublic:\r\n    // Constructor/destructor\r\n                    CLevelLoader();\r\n    virtual         ~CLevelLoader();\r\n\r\n    // Initializes the class with a list of levels and memory\r\n    HRESULT         Initialize( SLevelDesc* pDescs, DWORD dwNumlevels, BYTE* pSysMemData, DWORD dwSysMemSize, BOOL *p_signal );\r\n\r\n    // Load the specified level asynchronously\r\n    virtual VOID    AsyncStreamLevel( DWORD dwlevel );\r\n\r\n    // Updates load/cache state\r\n    virtual VOID    Update() = 0;\r\n\r\n    // refreshes the opened and loads states of all levels\r\n    virtual HRESULT RefreshLevelStates();\r\n\r\n\r\n    // function to retrieve state of current level\r\n    inline DWORD   GetCurrentDVDFileSize() const;\r\n    inline BOOL    IsCurrentPrecached() const;        \r\n    inline BOOL    WasCurrentPrecached() const;       \r\n    inline BOOL    IsCurrentCacheCorrupted() const;  \r\n    inline BOOL    WasCurrentCacheCorrupted() const;  \r\n    inline BOOL    IsCurrentOpen() const;\r\n    inline BOOL    IsCurrentLoaded() const;\r\n    \r\n    // functions to retrieve state of loader\r\n    inline BOOL    IsCacheing() const;\r\n    inline BOOL    IsLoading() const;\r\n    inline BOOL    IsIdle() const;\r\n    inline DOUBLE  GetLoadTime() const;   \r\n    inline DOUBLE  GetCacheTime() const;  \r\n    \r\n    // functions to retrieve resource by their offset\r\n    inline VOID*                    GetData( DWORD dwOffset ) const;\r\n    inline LPDIRECT3DRESOURCE8      GetResource( DWORD dwOffset ) const;\r\n    inline LPDIRECT3DTEXTURE8       GetTexture( DWORD dwOffset ) const;\r\n    inline LPDIRECT3DCUBETEXTURE8   GetCubemap( DWORD dwOffset ) const;\r\n    inline LPDIRECT3DVOLUMETEXTURE8 GetVolumeTexture( DWORD dwOffset ) const;\r\n    inline LPDIRECT3DVERTEXBUFFER8  GetVertexBuffer( DWORD dwOffset ) const;\r\n    \r\n    // Functions to retrieve resources by their name\r\n    VOID*                           GetData( const CHAR* strName ) const;\r\n    inline LPDIRECT3DRESOURCE8      GetResource( const CHAR* strName ) const;\r\n    inline LPDIRECT3DTEXTURE8       GetTexture( const CHAR* strName ) const;\r\n    inline LPDIRECT3DCUBETEXTURE8   GetCubemap( const CHAR* strName ) const;\r\n    inline LPDIRECT3DVOLUMETEXTURE8 GetVolumeTexture( const CHAR* strN ) const;\r\n    inline LPDIRECT3DVERTEXBUFFER8  GetVertexBuffer( const CHAR* strN ) const;\r\n    \r\nprotected:\r\n\r\n    // IO status\r\n    enum FileIOStatus\r\n    {\r\n        BadRead = 0,\r\n        BadWrite,\r\n        BadHeader,\r\n        BadSig,\r\n        SigMismatch,\r\n        NoSigMagic,\r\n        Finished,\r\n        Pending\r\n    };\r\n\r\n    // Openfile status\r\n    enum FileOpenStatus\r\n    {\r\n        BadOpen = 0,\r\n        BadSigMagicWrite,\r\n        FilesOpened\r\n    };\r\n\r\n     // type of IO requested\r\n    enum IOType\r\n    {\r\n        Read = 0,\r\n        Write,\r\n    };\r\n\r\n    // current step in loading the level resources\r\n    enum IOState\r\n    {\r\n        Begin = 0,\r\n        LoadSig,\r\n        LoadSysMem,\r\n        ParseHeader,\r\n        CalcSig,\r\n        LoadVidMem,\r\n        RegisterResources,\r\n        WriteSysMem,\r\n        WriteVidMem,\r\n        WriteSig,\r\n        End,\r\n        Idle\r\n    };\r\n\r\n\r\n    // opens the current level\r\n    HRESULT         OpenLevel( SLevelState* pState, DWORD dwFlags );\r\n    HRESULT         EndOpenLevel( SLevelState* pLevel, FileOpenStatus Status );\r\n\r\n    // streams the current level\r\n    HRESULT         StreamCurrentLevel();\r\n    VOID            ResetStreaming();\r\n    HRESULT         EndStreamLevel( FileIOStatus Status );\r\n\r\n    // is the current cache valid\r\n    inline BOOL     IsCurrentCacheGood();\r\n\r\n    // set the current IO file\r\n    virtual VOID    SetCurrentFile( HANDLE hFile, BOOL to_start = TRUE ) = 0;\r\n\r\n    // wrappers for read and write file\r\n    virtual HRESULT DoIO( IOType Type, VOID* pBuffer, DWORD dwNumBytes ) = 0;\r\n\r\n    // has an IO op completed\r\n    virtual HRESULT HasIOCompleted() = 0;\r\n\r\n\r\n\r\n    // Allocated memory for resource headers etc.\r\n    BYTE*           m_pSysMemData;    \r\n    DWORD           m_dwSysMemSize;\r\n\r\n    // level state array\r\n    SLevelState*    m_pLevels;\r\n    DWORD           m_dwNumLevels;\r\n    DWORD           m_dwCurrentLevel;\r\n\r\n    // current level\r\n    SLevelState*   m_pCurrentLevel;\r\n\r\n    // stats data\r\n\tTmr::Time\t\tm_dStartTime;\r\n    Tmr::Time\t\tm_dLoadTime;        \r\n    Tmr::Time\t\tm_dCacheTime;\r\n    \r\n    // current IO state\r\n    IOState         m_IOState;\r\n\r\n    // temp variables used during load\r\n    BYTE*           m_pSysMemBuffer;\r\n    BYTE*           m_pFileSig;\r\n    HANDLE          m_hSignature;\r\n\r\n\tBOOL\t\t\t*m_pOkayToUseUtilityDrive;\r\n};\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Inlined accessors\r\n//-----------------------------------------------------------------------------\r\ninline DWORD CLevelLoader::GetCurrentDVDFileSize() const\r\n{\r\n    return m_pCurrentLevel ? m_pCurrentLevel->dwDVDFileSize: 0;\r\n}\r\ninline BOOL CLevelLoader::IsCurrentPrecached() const        \r\n{\r\n    return m_pCurrentLevel ? m_pCurrentLevel->bIsPreCached : FALSE;\r\n}\r\ninline BOOL CLevelLoader::WasCurrentPrecached() const       \r\n{\r\n    return m_pCurrentLevel ? m_pCurrentLevel->bWasPreCached : FALSE;\r\n}\r\ninline BOOL CLevelLoader::IsCurrentCacheCorrupted() const   \r\n{\r\n    return m_pCurrentLevel ? m_pCurrentLevel->bIsCacheCorrupted : FALSE;\r\n}\r\ninline BOOL CLevelLoader::WasCurrentCacheCorrupted() const  \r\n{\r\n    return m_pCurrentLevel ? m_pCurrentLevel->bWasCacheCorrupted : FALSE;\r\n}\r\ninline BOOL CLevelLoader::IsCurrentOpen() const           \r\n{\r\n    return m_pCurrentLevel ? m_pCurrentLevel->bIsOpen : FALSE;\r\n}\r\ninline BOOL CLevelLoader::IsCacheing() const\r\n{\r\n    return m_pCurrentLevel &&\r\n        m_IOState > RegisterResources && m_IOState < Idle;\r\n}\r\ninline BOOL CLevelLoader::IsCurrentLoaded() const\r\n{\r\n    return m_pCurrentLevel && m_IOState > RegisterResources;\r\n}\r\ninline BOOL CLevelLoader::IsLoading() const\r\n{\r\n    return m_pCurrentLevel && m_IOState < WriteSysMem;\r\n}\r\ninline DOUBLE CLevelLoader::GetLoadTime() const\r\n{\r\n    return m_dLoadTime;\r\n}\r\ninline DOUBLE CLevelLoader::GetCacheTime() const\r\n{\r\n    return m_dCacheTime;\r\n}\r\ninline BOOL CLevelLoader::IsIdle() const\r\n{\r\n    return m_IOState == Idle;\r\n}\r\ninline BOOL CLevelLoader::IsCurrentCacheGood()\r\n{\r\n    return m_pCurrentLevel ? m_pCurrentLevel->bIsPreCached\r\n           && !m_pCurrentLevel->bIsCacheCorrupted : FALSE;\r\n}\r\ninline VOID* CLevelLoader::GetData( DWORD dwOffset ) const\r\n{\r\n    return m_pCurrentLevel ? &m_pSysMemData[dwOffset] : NULL;\r\n}\r\ninline LPDIRECT3DRESOURCE8 CLevelLoader::GetResource( DWORD dwOffset ) const\r\n{\r\n    return (LPDIRECT3DRESOURCE8)GetData(dwOffset);\r\n}\r\ninline LPDIRECT3DTEXTURE8 CLevelLoader::GetTexture( DWORD dwOffset ) const\r\n{\r\n    return (LPDIRECT3DTEXTURE8)GetData( dwOffset );\r\n}\r\ninline LPDIRECT3DCUBETEXTURE8\r\nCLevelLoader::GetCubemap( DWORD dwOffset ) const\r\n{\r\n    return (LPDIRECT3DCUBETEXTURE8)GetData( dwOffset );\r\n}\r\ninline LPDIRECT3DVOLUMETEXTURE8\r\nCLevelLoader::GetVolumeTexture( DWORD dwOffset ) const\r\n{\r\n    return (LPDIRECT3DVOLUMETEXTURE8)GetData( dwOffset );\r\n}\r\ninline LPDIRECT3DVERTEXBUFFER8\r\nCLevelLoader::GetVertexBuffer( DWORD dwOffset ) const\r\n{\r\n    return (LPDIRECT3DVERTEXBUFFER8)GetData( dwOffset );\r\n}\r\ninline LPDIRECT3DRESOURCE8\r\nCLevelLoader::GetResource( const CHAR* strName ) const\r\n{\r\n    return (LPDIRECT3DRESOURCE8)GetData( strName );\r\n}\r\ninline LPDIRECT3DTEXTURE8\r\nCLevelLoader::GetTexture( const CHAR* strName ) const\r\n{\r\n    return (LPDIRECT3DTEXTURE8)GetResource( strName );\r\n}\r\ninline LPDIRECT3DCUBETEXTURE8\r\nCLevelLoader::GetCubemap( const CHAR* strName ) const\r\n{\r\n    return (LPDIRECT3DCUBETEXTURE8)GetResource( strName );\r\n}\r\ninline LPDIRECT3DVOLUMETEXTURE8\r\nCLevelLoader::GetVolumeTexture( const CHAR* strName ) const\r\n{\r\n    return (LPDIRECT3DVOLUMETEXTURE8)GetResource( strName );\r\n}\r\ninline LPDIRECT3DVERTEXBUFFER8\r\nCLevelLoader::GetVertexBuffer( const CHAR* strName ) const\r\n{\r\n    return (LPDIRECT3DVERTEXBUFFER8)GetResource( strName );\r\n}\r\n\r\n\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name:  IOProc\r\n// Desc: Thread proc for IO\r\n//-----------------------------------------------------------------------------\r\nDWORD WINAPI IOProc( LPVOID lpParameter );\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n// Name: class CThreadedLevelLoader\r\n// Desc: Threaded Cached resource.  Handles loading and caching of packed\r\n//       resources, using a thread\r\n//-----------------------------------------------------------------------------\r\nclass CThreadedLevelLoader : public CLevelLoader\r\n{\r\npublic:\r\n\r\n    // Constructor/destructor\r\n                    CThreadedLevelLoader();\r\n    virtual         ~CThreadedLevelLoader();\r\n\r\n    virtual VOID    AsyncStreamLevel( DWORD dwlevel );\r\n    virtual VOID    Update() {} // does nothing for the threaded version\r\n\r\nprotected:\r\n\r\n    virtual VOID    SetCurrentFile( HANDLE hFile, BOOL to_start = TRUE );\r\n    virtual HRESULT DoIO( IOType Type, VOID* pBuffer, DWORD dwNumBytes );\r\n    virtual HRESULT HasIOCompleted() { return S_OK; }; // IO is synchronous\r\n                                                       // but in its own thread\r\n\r\n    \r\n    // current file\r\n    HANDLE          m_hFile;\r\n    \r\n    // thread handle and wake event\r\n    HANDLE          m_hEvent;\r\n    HANDLE          m_hThread;\r\n\r\n    // signal to kill the thread (only done when the class is destroyed)\r\n    BOOL            m_bKillThread;\r\n\r\n    // the IO proc is our friend\r\n    friend          DWORD WINAPI IOProc( LPVOID lpParameter );\r\n};\r\n\r\n\r\n\r\n\r\n#endif //LEVEL_LOADER_H\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/filesys.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory Manager (Mem)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/mem/alloc.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_FILE_FILESYS_H\r\n#define\t__SYS_FILE_FILESYS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace File\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid InstallFileSystem( void );\r\nvoid UninstallFileSystem( void );\r\nlong GetFileSize(void *pFP);\r\nlong GetFilePosition(void *pFP);\r\nfloat GetPercentageRead(void *pFP);\r\nvoid InitQuickFileSystem( void );\r\nvoid ResetQuickFileSystem( void );\r\n\r\nuint32\tCanFileBeLoadedQuickly( const char *filename );\r\nbool LoadFileQuicklyPlease( const char *filename, uint8 *addr );\r\n\r\nvoid   *LoadAlloc(const char *p_fileName, int *p_filesize=NULL, void *p_dest = NULL, int maxSize=0);\r\n\r\n\r\nvoid StopStreaming( void );\r\n\r\n/////////////////////////////////////////////////////////////////////\r\n// The following are our versions of the ANSI file IO functions.\r\n//\r\nbool   Exist( const char *filename );\r\nvoid * Open( const char *filename, const char *access );\r\nint    Close( void *pFP );\r\nsize_t Read( void *addr, size_t size, size_t count, void *pFP );\r\nsize_t ReadInt( void *addr, void *pFP );\r\nsize_t Write( const void *addr, size_t size, size_t count, void *pFP );\r\nchar * GetS( char *buffer, int maxlen, void *pFP );\r\nint    PutS( const char *buffer, void *pFP );\r\nint    Eof( void *pFP );\r\nint    Seek( void *pFP, long offset, int origin );\r\nint\t   Tell( void* pFP );\r\nint    Flush( void *pFP );\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace File\r\n\r\n#endif  // __SYS_FILE_FILESYS_H\r\n"
  },
  {
    "path": "Code/Sys/File/memfile.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\r\n//\r\n// memfile.h\r\n//\r\n// memory mapped file replacement functions\r\n// allow you to load a file to memory, and then use these MemFile:: functions\r\n// instead of File:: functions, to load it exactly the same as before\r\n// so you would replace\r\n// \tFile::Read(\r\n// with\r\n//\tMEM_Read(\r\n//\r\n// Note that since these are macros, they dont return anything\r\n//\r\n#define MEM_Read( addr, size, count, pFP )\t   \\\r\n{\t\t\t\t\t\t\t\t\t\t\t   \\\r\n\tchar *p = (char*)(addr);\t\t\t\t   \\\r\n\tchar *q = (char*)(pFP);\t\t\t\t\t   \\\r\n\tint total = (size)*(count);\t\t\t\t   \\\r\n\tfor (;total>0;total--)\t\t\t\t\t   \\\r\n\t\t*p++ = *q++;\t\t\t\t\t\t   \\\r\n\tpFP = (void*) q;\t\t\t\t\t\t   \\\r\n}\t\t\t\t\t\t\t\t\t\t\t   \\\r\n\r\n#define MEM_Seek(pFP, offset, origin )\t   \\\r\n{\t\t\t\t\t\t\t\t\t\t   \\\r\n\tpFP = (void*)((char*)(pFP) + (offset));  \\\r\n}\t\t\t\t\t\t\t\t\t\t   \\\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/ngc/hed.cpp",
    "content": "/*\tHeader file functionality...\r\n\t.Hed files that describe the contents of .Wad files\r\n\tWritten by Ken, stolen by Matt*/\r\n//#include <eetypes.h>\r\n//#include <eekernel.h>\r\n//#include <stdio.h>\r\n//#include <sifdev.h>\r\n//#include <libsdr.h>\r\n//#include <sdrcmd.h>\r\n//#include <sdmacro.h>\r\n//#include <string.h>\r\n//#include <ctype.h>\r\n//#include <sif.h>\r\n//#include <sifrpc.h>\r\n//\r\n//#include <libcdvd.h>\r\n\r\n#include <core/macros.h>\r\n#include <core/defines.h>\r\n\r\n#include <gel/scripting/script.h> \r\n\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/ngc/hed.h>\r\n#include <sys/ngc/p_file.h>\r\n\r\nbool sLoadingHed = false;\r\n\r\nnamespace File\r\n{\r\n\r\nstatic void get_checksums( const char * p_name, uint32 * p_dir, uint32 * p_file )\r\n{\r\n\tchar name[128];\r\n\tchar dir[128];\r\n\tchar file[128];\r\n\tuint lp;\r\n\r\n\t// Convert / to \\\\.\r\n\tfor ( lp = 0; lp <= strlen( p_name ); lp++ )\r\n\t{\r\n\t\tname[lp] = p_name[lp];\r\n\t\tif ( name[lp] == '/' ) name[lp] = '\\\\';\r\n\t}\r\n\r\n\t// Find the directory name and the filename.\r\n\tfor ( lp = strlen( name ) - 1; lp >= 0; lp-- )\r\n\t{\r\n\t\tif ( name[lp] == '\\\\' )\r\n\t\t{\r\n\t\t\t// Found the directory end.\r\n\t\t\tstrcpy( file, &name[lp+1] );\r\n\t\t\tname[lp] = '\\0';\r\n\t\t\tstrcpy( dir, name );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// Chop off the extension (if it exists). \r\n\tif ( file[strlen(file)-4] == '.' )\r\n\t{\r\n\t\tfile[strlen(file)-4] = '\\0';\r\n\t}\r\n\r\n\t// Create checksums.\r\n\tif ( p_dir ) *p_dir = Script::GenerateCRC( dir );\r\n\tif ( p_file ) *p_file = Script::GenerateCRC( file );\r\n}\r\n\r\n\r\n\r\n\r\n// Searches the hed file for the filename. If not found, returns NULL.\r\nSHedFile *FindFileInHed(const char *pFilename, SHed *pHed)\r\n{\r\n\tif ( sLoadingHed ) return NULL;\r\n\r\n\tDbg_MsgAssert(pFilename,(\"NULL pFilename\"));\r\n\tDbg_MsgAssert(pHed,(\"NULL pHed\"));\r\n\r\n\tuint32 check_dir;\r\n\tuint32 check_file;\r\n\r\n\tget_checksums( pFilename, &check_dir, &check_file );\r\n\r\n\tSHed *pHd=pHed;\r\n\twhile ( pHd->numFiles != 0xffffffff )\r\n\t{\r\n\t\tif ( pHd->Checksum == check_dir )\r\n\t\t{\r\n\t\t\tSHedFile * pF = pHd->p_fileList;\r\n\t\t\tfor ( uint lp2 = 0; lp2 < pHd->numFiles; lp2++ )\r\n\t\t\t{\r\n\t\t\t\tif ( pF->Checksum == check_file )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn pF;\r\n\t\t\t\t}\r\n\t\t\t\tpF++;\r\n\t\t\t}\r\n\t\t}\r\n\t\tpHd++;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n// Searches the hed file for the filename with the same checksum. If not found, returns NULL.\r\nSHedFile *FindFileInHedUsingChecksum( uint32 checksum, SHed *pHed )\r\n{\r\n\tif ( sLoadingHed ) return NULL;\r\n\r\n\tDbg_MsgAssert(pHed,(\"NULL pHed\"));\r\n\r\n\tSHed *pHd=pHed;\r\n\twhile ( pHd->numFiles != 0xffffffff )\r\n\t{\r\n\t\tSHedFile * pF = pHd->p_fileList;\r\n\t\tfor ( uint lp2 = 0; lp2 < pHd->numFiles; lp2++ )\r\n\t\t{\r\n\t\t\tif ( pF->Checksum == checksum )\r\n\t\t\t{\r\n\t\t\t\treturn pF;\r\n\t\t\t}\r\n\t\t\tpF++;\r\n\t\t}\r\n\t\tpHd++;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n//#ifdef __NOPT_CDROM__\r\n//\r\n//extern void StopStreaming( void );\r\n//\r\n//SHed *LoadHed( const char *filename )\r\n//{\r\n//\tNsFile file;\r\n//\tSHed *pHed = NULL;\r\n////\tint HedId=-1;\r\n//\tchar hedFileName[255];\r\n//\tchar uppercaseFilename[ 255 ];\r\n//\tint sL = strlen( filename );\r\n//\tDbg_MsgAssert( sL < 255,( \"Filename %s too long\", filename ));\r\n//\tint i;\r\n//\tfor ( i = 0; i < sL; i++ )\r\n//\t{\r\n//\t\tuppercaseFilename[ i ] = toupper( filename[ i ] );\r\n//\t}\r\n//\tuppercaseFilename[ i ] = '\\0';\r\n//\tStopStreaming( );\r\n//\tsprintf( hedFileName, \"cdrom0:\\\\%s.HED;1\", uppercaseFilename );\r\n//\twhile (HedId<0)\r\n//\t{\r\n//\t\tfile.open( hedFileName );\r\n////\t\tHedId=sceOpen( hedFileName, SCE_RDONLY );\r\n//\t\tif (HedId<0)\r\n//\t\t{\r\n//\t\t\tprintf(\"Retrying opening %s\\n\", hedFileName );\r\n//\t\t}\t\r\n//\t}\r\n//\tprintf(\"%s opened successfully\\n\", uppercaseFilename );\r\n////\tlong HedSize=sceLseek(HedId, 0, SCE_SEEK_END);\r\n//\tlong HedSize=file.size();\r\n//\t\r\n//\tDbg_MsgAssert(pHed==NULL,(\"pHed not NULL ?\"));\r\n//\tpHed=(SHed*)Mem::Malloc((HedSize+2047)&~2047);\r\n//\r\n///*\r\n//\tchar *p = (char*) pHed;  \r\n//\t// Hmmm.....\r\n//\tfor (int i=0 ;i < (HedSize+2047)&~2047;i++)\r\n//\t{\r\n//\t\tp[i] = 0x55;\r\n//\t}\r\n//*/\t\t\t\t\t\t\r\n//\t\t\t\t\t\r\n////\tsceLseek(HedId, 0, SCE_SEEK_SET);\r\n////\tsceRead(HedId,pHed,HedSize);\r\n////\tsceClose(HedId);\r\n//\tfile.read( pHed,, HedSize );\r\n//\tfile.close();\r\n//\treturn ( pHed );\r\n//\treturn ( NULL );\r\n//}\r\n//#else\r\n//\r\nSHed *LoadHed( const char *filename )\r\n{\r\n\tsLoadingHed = true;\r\n\r\n\tint lp;\r\n\tchar tempFileName[255];\r\n\tsprintf( tempFileName, \"%sNGC.HED\", filename );\r\n\r\n\tvoid *fp = File::Open( tempFileName, \"rb\" );\r\n\r\n\tint fileSize = File::GetFileSize( fp );\r\n\t\r\n\tuint32 *pHed = (uint32 *)new (Mem::Manager::sHandle().TopDownHeap()) uint8[fileSize];\r\n\tDbg_MsgAssert( pHed,( \"Failed to allocate memory for hed %s\", tempFileName ));\r\n\r\n\tFile::Read( pHed, 1, fileSize, fp );\r\n\tFile::Close( fp );\r\n\r\n\t// Convert to more compact list.\r\n\tint files = 0;\r\n\tint dirs = 0;\r\n\r\n\t// First, count how many files we have.\r\n\tuint32 * p32 = pHed;\r\n\twhile ( p32[0] != 0xffffffff )\r\n\t{\r\n\t\tfiles++;\r\n\r\n\t\t// Byte order is reversed on NGC.\r\n\t\tp32[0] = ( ( p32[0] >> 24 ) & 0xff ) | ( ( p32[0] >> 8 ) & 0xff00 ) | ( ( p32[0] << 8 ) & 0xff0000 ) | ( ( p32[0] << 24 ) & 0xff000000 );\r\n\t\tp32[1] = ( ( p32[1] >> 24 ) & 0xff ) | ( ( p32[1] >> 8 ) & 0xff00 ) | ( ( p32[1] << 8 ) & 0xff0000 ) | ( ( p32[1] << 24 ) & 0xff000000 );\r\n\r\n\t\tint len = strlen( (char *)&p32[2] ) + 1;\r\n\t\tlen = ( len + 3 ) & ~3;\r\n\t\tp32 = (uint32*)(((int)&p32[2]) + len);\r\n\t}\r\n\r\n\t// Build list of checksums.\r\n\tuint32 *p_offset = new (Mem::Manager::sHandle().TopDownHeap()) uint32[files];\r\n\tuint32 *p_size = new (Mem::Manager::sHandle().TopDownHeap()) uint32[files];\r\n\tuint32 *dir_check = new (Mem::Manager::sHandle().TopDownHeap()) uint32[files];\r\n\tuint32 *file_check = new (Mem::Manager::sHandle().TopDownHeap()) uint32[files];\r\n\tint count = 0;\r\n\tp32 = pHed;\r\n\twhile ( p32[0] != 0xffffffff )\r\n\t{\r\n\t\tp_offset[count] = p32[0];\r\n\t\tp_size[count] = p32[1];\r\n\t\tget_checksums( (char *)&p32[2], &dir_check[count], &file_check[count] );\r\n\t\tcount++;\r\n\r\n\t\tint len = strlen( (char *)&p32[2] ) + 1;\r\n\t\tlen = ( len + 3 ) & ~3;\r\n\t\tp32 = (uint32*)(((int)&p32[2]) + len);\r\n\t}\r\n\r\n\t// Second, count how many directories we have.\r\n\tfor ( lp = 0; lp < files; lp++ )\r\n\t{\r\n\t\tbool unique = true;\r\n\t\tfor ( int lp2 = 0; lp2 < lp; lp2++ )\r\n\t\t{\r\n\t\t\tif ( dir_check[lp] == dir_check[lp2] )\r\n\t\t\t{\r\n\t\t\t\tunique = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( unique ) dirs++;\r\n\t}\r\n\r\n\t// Now, allocate final piece of memory.\r\n\tint size = ( sizeof( SHed ) * ( dirs + 1 ) ) + ( sizeof( SHedFile ) * files );\r\n\tSHed * p_hed = (SHed *)new uint8[size];\r\n\r\n\t// Fill in directory entries.\r\n\tint dirs_added = 0;\r\n\tfor ( lp = 0; lp < files; lp++ )\r\n\t{\r\n\t\tbool unique = true;\r\n\t\tfor ( int lp2 = 0; lp2 < dirs_added; lp2++ )\r\n\t\t{\r\n\t\t\tif ( p_hed[lp2].Checksum == dir_check[lp] )\r\n\t\t\t{\r\n\t\t\t\tunique = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( unique )\r\n\t\t{\r\n\t\t\tp_hed[dirs_added].Checksum = dir_check[lp];\r\n\t\t\tdirs_added++;\r\n\t\t}\r\n\t}\r\n\r\n\t// Fill in file entries.\r\n\tSHedFile * p_hed_file = (SHedFile *)&p_hed[(dirs+1)];\r\n\tfor ( lp = 0; lp < dirs; lp++ )\r\n\t{\r\n\t\tp_hed[lp].p_fileList = p_hed_file;\r\n\t\tint files_this_dir = 0;\r\n\t\tfor ( int lp2 = 0; lp2 < files; lp2++ )\r\n\t\t{\r\n\t\t\tif ( dir_check[lp2] == p_hed[lp].Checksum )\r\n\t\t\t{\r\n\t\t\t\tp_hed_file->Offset = p_offset[lp2];\r\n\t\t\t\tp_hed_file->FileSize = p_size[lp2];\r\n\t\t\t\tp_hed_file->Checksum = file_check[lp2];\r\n\t\t\t\tfiles_this_dir++;\r\n\t\t\t\tp_hed_file++;\r\n\t\t\t}\r\n\t\t}\r\n\t\tp_hed[lp].numFiles = files_this_dir;\r\n\t}\r\n\tp_hed[dirs].numFiles = 0xffffffff;\r\n\r\n\t// Get rid of temp data.\r\n\tdelete file_check;\r\n\tdelete dir_check;\r\n\tdelete p_size;\r\n\tdelete p_offset;\r\n\tdelete pHed;\r\n\r\n\tsLoadingHed = false;\r\n\r\n\treturn p_hed;\r\n}\r\n//#endif\r\n\r\n} // namespace File\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/ngc/hed.h",
    "content": "/*\tHeader file functionality...\r\n\t.Hed files that describe the contents of .Wad files\r\n\tWritten by Ken, stolen by Matt*/\r\n#ifndef __HED_H__\r\n#define __HED_H__\r\n\r\nnamespace File\r\n{\r\n\r\nstruct SHedFile\r\n{\r\n\t// A SECTOR_SIZE aligned offset of a file within skate3.wad\r\n\tuint32 Offset;\r\n\t\r\n\t// The file size, which is the raw file size, not rounded up\r\n\t// to a multiple of SECTOR_SIZE\r\n\tuint32 FileSize;\r\n\t\r\n\t// Filename checksum (does not include directory).\r\n\tuint32 Checksum;\r\n};\r\n\r\nstruct SHed\r\n{\r\n\t// Number of files in this directory.\r\n\tuint32 numFiles;\r\n\t\r\n\t// Checksum of this directory.\r\n\tuint32 Checksum;\r\n\r\n\t// Pointer to File list.\r\n\tSHedFile * p_fileList;\r\n\r\n\t// The filename, which is actually bigger than one byte, tee hee.\r\n//\tconst char pFilename[1];\r\n};\r\n\r\n\r\nSHedFile *FindFileInHed(const char *pFilename, SHed *pHed );\r\nSHedFile *FindFileInHedUsingChecksum( uint32 checksum, SHed *pHed );\r\nSHed *LoadHed( const char *filename );\r\n\r\n} // namespace File\r\n\r\n#endif\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/ngc/p_AsyncFilesys.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// p_AsyncFilesys.cpp\t\tGRJ 11 Oct 2002\r\n//\r\n// Asynchronous file system\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <sys/config/config.h>\r\n\r\n#include <sys/file/ngc/p_AsyncFilesys.h>\r\n\r\nnamespace File\r\n{\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid\t\t\t\tCAsyncFileLoader::s_plat_init()\r\n{\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid\t\t\t\tCAsyncFileLoader::s_plat_cleanup()\r\n{\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCAsyncFileLoader::s_plat_async_supported()\r\n{\r\n\t// Not implemented yet\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool\t\t\t\tCAsyncFileLoader::s_plat_exist(const char *filename)\r\n{\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileLoader::s_plat_update(void)\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid\t\t\t\tCAsyncFileLoader::s_plat_swap_callback_list()\r\n{\r\n}\r\n\r\n}\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/ngc/p_asyncFilesys.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tFile\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t10/11/02\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/p_AsyncFilesys.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_FILE_P_ASYNC_FILESYS_H\r\n#define\t__SYS_FILE_P_ASYNC_FILESYS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sys/file/AsyncFilesys.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace File\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace File\r\n\r\n#endif  // __SYS_FILE_P_ASYNC_FILESYS_H\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/ngc/p_filesys.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSystem Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tFile IO (File) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_filesys.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t09/25/00\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXBox File System\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdio.h>\r\n#include <string.h>\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/PRE.h>\r\n\r\n#include <sys/ngc/p_file.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace File\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define CDROMx   // Use this define to get CDROM behavior\r\n\r\n#define RWGDFSGLOBAL(var)\t(RWPLUGINOFFSET(gdfsGlobals, RwEngineInstance, gdfsModuleInfo.globalsOffset)->var)\r\n\r\n#define\tPREPEND_START_POS\t8\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#define READBUFFERSIZE (10240*5)\r\n\r\n// GJ:  I added this to track how many skyFiles are active\r\n// at any given time.  I am assuming that there's only one,\r\n// in which case I can just create one global instance\r\n// (previously, we were allocating it off the current heap,\r\n// which was causing me grief during the CAS loading process)\r\n//int g_fileOpenCount = 0;\r\n\r\nstruct skyFile\r\n{\r\n\t\r\n\t// the following must match the dumbSkyFile struct\r\n\t// in pre.cpp, or else pre file i/o won't work properly\r\n\tint\t\t\t\tgdfs;\r\n\tint32\t\t\tPOS;\r\n\tint32\t\t\tSOF;\r\n\r\n\t// the rest is skyFile-specific\r\n//\tuint8\t\t\treadBuffer[READBUFFERSIZE];\r\n\tuint32\t\tbufferPos;\r\n\tbool\t\t\tbufferValid;\r\n\tbool\t\t\tlocked;\t\t\t// whether the skyfile is currently in use\r\n\t\r\n\t// Used when CD\r\n\tuint32\t\t\tWadOffset;\r\n\tconst char\t\t*pFilename;\r\n\t\r\n\t// Used when non-CD\r\n\t#define MAX_PFILESYS_NAME_SIZE 100\r\n\tchar filename[ MAX_PFILESYS_NAME_SIZE ];\r\n\r\n\tNsFile ngcFile;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//static\tRwFileFunctions\ts_old_fs;\r\n//static\tRwInt32\t\t\ts_open_files = 0;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/* prefopen\t\t\t\t\t\t\t\t\t\t\t\t\t\t  */\r\n/* Same as fopen() except it will prepend the data root directory */\r\n/* For Xbox, path is always relative to location of .xbe image\t  */\r\n/* and default path from that location is d:\\\t\t\t\t\t  */\r\n/* So incoming files of the form:\t\t\t\t\t\t\t\t  */\r\n/* c:\\skate3\\data\\foo...\tbecome\td:\\data\\foo...\t\t\t\t  */\r\n/* foo...\t\t\t\t\tbecome\td:\\data\\foo...\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n//static void* prefopen( const char *filename, const char *mode )\r\n//{\r\n//\t// Used for prepending the root data directory on filesystem calls.\r\n//\tchar\t\tnameConversionBuffer[256] = \"d:\\\\data\\\\\";\r\n//\tint\t\t\tindex = PREPEND_START_POS;\r\n//\tconst char*\tp_skip;\r\n//\r\n//\tif(( filename[0] == 'c' ) && ( filename[1] == ':' ))\r\n//\t{\r\n//\t\t// Filename is of the form c:\\skate3\\data\\foo...\r\n//\t\tp_skip = filename + 15;\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\t// Filename is of the form foo...\r\n//\t\tp_skip = filename;\r\n//\t}\r\n//\r\n//\twhile( nameConversionBuffer[index] = *p_skip )\r\n//\t{\r\n//\t\t// Switch forward slash directory separators to the supported backslash.\r\n//\t\tif( nameConversionBuffer[index] == '/' )\r\n//\t\t{\r\n//\t\t\tnameConversionBuffer[index] = '\\\\';\r\n//\t\t}\r\n//\t\t++index;\r\n//\t\t++p_skip;\r\n//\t}\r\n//\tnameConversionBuffer[index] = 0;\r\n//\r\n//\t// Final hack - if this is a .tex file, switch to a .txx file.\r\n//\tif((( nameConversionBuffer[index - 1] ) == 'x' ) &&\r\n//\t   (( nameConversionBuffer[index - 2] ) == 'e' ) &&\r\n//\t   (( nameConversionBuffer[index - 3] ) == 't' ))\r\n//\t{\r\n//\t\tnameConversionBuffer[index - 2] = 'x';\r\n//\t}\r\n//\r\n////\treturn fopen( nameConversionBuffer, mode );\r\n//\r\n//\tHANDLE h_file = CreateFile( nameConversionBuffer, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r\n//\treturn ( h_file == INVALID_HANDLE_VALUE ) ? NULL : h_file;\r\n//}\r\n\r\n\r\n// At first, I assumed that only one skyfile could be open at\r\n// a time, but that's not true when testing streams from the\r\n// PC build.\r\n// pc builds need to have two (one for normal files, and one for streams)\r\n// GJ:  for THPS4, we increased this to 3, so that we can play multiple streams\r\nconst int MAXOPENFILES = 3;\r\n\r\n// Ken note: It used to be that MAXOPENFILES was defined to be 1 when __NOPT_CDROM__OLD\r\n// was set. Now that __NOPT_CDROM__OLD is not used anymore and CD() is used at runtime\r\n// instead, I made MAXOPENFILES always 2. Then, where MAXOPENFILES used to be used in the code\r\n// it now uses a var set to 1 or 2 depending on CD()\r\nstatic skyFile g_skyFile[MAXOPENFILES];\r\n\r\nskyFile* lock_skyfile( void )\r\n{\r\n\t// cd builds can only have one file open at any given time\r\n\tint max_open_files=MAXOPENFILES;\r\n\t\r\n\tint i;\r\n\t// this tries to find an unlocked skyfile\r\n\tfor ( i = 0; i < max_open_files; i++ )\r\n\t{\r\n\t\tif ( !g_skyFile[i].locked )\r\n\t\t{\r\n\t\t\tg_skyFile[i].locked = true;\r\n\t\t\tg_skyFile[i].ngcFile.m_FileOpen\t\t\t= 0; \r\n\t\t\tg_skyFile[i].ngcFile.m_sizeCached\t\t= 0; \r\n\t\t\tg_skyFile[i].ngcFile.m_numCacheBytes\t= 0; \r\n\t\t\tg_skyFile[i].ngcFile.m_seekOffset\t\t= 0;\r\n\t\t\tg_skyFile[i].ngcFile.m_preHandle\t\t= NULL;\r\n\t\t\tg_skyFile[i].ngcFile.m_unique_tag\t\t= 0x1234ABCD;\r\n\t\t\treturn &g_skyFile[i];\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_Message( \"Here are the files currently open:\" );\r\n\tfor ( i = 0; i < max_open_files; i++ )\r\n\t{\r\n\t\tDbg_Message( \"%s\", g_skyFile[ i ].filename );\r\n\t}\t\r\n\r\n\t// if we get here, that means that all the sky files were locked\r\n\tDbg_MsgAssert( 0, ( \"Trying to open too many files simultaneously (max=%d)\", max_open_files ) );\r\n\treturn NULL;\r\n}\r\n\r\nvoid unlock_skyfile( skyFile* pSkyFile )\r\n{\r\n\t// cd builds can only have one file open at any given time\r\n\tint max_open_files=MAXOPENFILES;\r\n\t\r\n\r\n\t// this tries to find the sky file that the caller is referencing\r\n\tfor ( int i = 0; i < max_open_files; i++ )\r\n\t{\r\n\t\tif ( pSkyFile == &g_skyFile[i] )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( g_skyFile[i].locked, ( \"Trying to unlock a sky file too many times\" ) );\r\n\t\t\tg_skyFile[i].locked = false;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\t// if we get here, that means that the pointer didn't match one of the valid skyfiles\r\n\tDbg_MsgAssert( 0, ( \"Unrecognized sky file\" ) );\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nlong GetFileSize( void* pFP )\r\n{\r\n\tDbg_MsgAssert(pFP,(\"NULL pFP sent to GetFileSize\"));\r\n\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_get_file_size((PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tskyFile* fp = (skyFile*)pFP;\r\n\treturn fp->ngcFile.size();\r\n}\r\n\r\nlong GetFilePosition(void *pFP)\r\n{\r\n\t\r\n\tDbg_MsgAssert(pFP,(\"NULL pFP sent to GetFilePosition\"));\r\n\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_get_file_position((PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tskyFile* fp = (skyFile*)pFP;\r\n\treturn fp->ngcFile.tell();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid InstallFileSystem( void )\r\n{\r\n/*\r\n\tRwFileFunctions*\tfs = RwOsGetFileInterface();\r\n\tDbg_MsgAssert( fs,( \"File System not found\" ));\r\n\t\r\n\ts_old_fs = *fs;    \r\n    \r\n\tfs->rwfexist\t= fexist;\t\t\t\r\n\tfs->rwfopen\t\t= (rwFnFopen)prefopen;\r\n\tfs->rwfclose\t= (rwFnFclose)fclose;\r\n\tfs->rwfread\t\t= (rwFnFread)fread;\r\n\tfs->rwfwrite\t= (rwFnFwrite)fwrite;\r\n\tfs->rwfgets\t\t= (rwFnFgets)fgets;\r\n\tfs->rwfputs\t\t= (rwFnFputs)fputs;\r\n\tfs->rwfeof\t\t= (rwFnFeof)feof;\r\n\tfs->rwfseek\t\t= (rwFnFseek)fseek;\r\n\tfs->rwfflush\t= (rwFnFflush)fflush;\r\n\tfs->rwftell\t\t= (rwFnFtell)ftell;\r\n*/\r\n}\r\n\r\nvoid InitQuickFileSystem( void )\r\n{\r\n}\r\n\r\nuint32\tCanFileBeLoadedQuickly( const char* filename )\r\n{\r\n\treturn 0;\r\n}\r\n\r\nbool LoadFileQuicklyPlease( const char* filename, uint8 *addr )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid StopStreaming( void )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid UninstallFileSystem( void )\r\n{\r\n/*\r\n\tRwFileFunctions*\tfs = RwOsGetFileInterface();\r\n\r\n\tDbg_MsgAssert( fs,( \"File System not found\" ));\r\n\r\n\t*fs = s_old_fs;\t\t// restore old\r\n*/\r\n\r\n}\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Our versions of the ANSI file IO functions.  They call\r\n// the PreMgr first to see if the file is in a PRE file.\r\n////////////////////////////////////////////////////////////////////\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Exist                                                          \r\nbool Exist( const char *filename )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        bool retval = PreMgr::pre_fexist(filename);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tNsFile f;\r\n\treturn f.exist( filename );\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Open                                                          \r\nvoid * Open( const char *filename, const char *access )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        void * retval = PreMgr::pre_fopen(filename, access);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tskyFile *fp = lock_skyfile();\r\n\tif ( fp )\r\n\t{\r\n\t\tstrcpy( fp->filename, filename );\r\n\t\r\n\t\tif ( fp->ngcFile.open( filename ) )\r\n\t\t{\r\n\t\t\tfp->SOF = fp->ngcFile.size();\r\n\t\r\n\t\t\treturn (void *)fp;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tunlock_skyfile( fp );\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Close                                                          \r\nint Close( void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_fclose((PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tskyFile* fp = (skyFile*)pFP;\r\n\tfp->ngcFile.close();\r\n\r\n\tunlock_skyfile( fp );\r\n\treturn 0;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Read                                                          \r\nsize_t Read( void *addr, size_t size, size_t count, void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        size_t retval = PreMgr::pre_fread(addr, size, count, (PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tskyFile* fp = (skyFile*)pFP;\r\n\treturn fp->ngcFile.read( addr, size * count ); \r\n}\r\n\r\n\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////\r\n// Read an Integer in PS2 (littleendian) format\r\n// we just read it directly into memory...\r\nsize_t ReadInt( void *addr, void *pFP )\r\n{\r\n\treturn Read(addr,4,1,pFP);\t\r\n}\r\n\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Write                                                          \r\nsize_t Write( const void *addr, size_t size, size_t count, void *pFP )\r\n{\r\n//    if (PreMgr::sPreEnabled())\r\n//    {\r\n//        size_t retval = PreMgr::pre_fwrite(addr, size, count, (PreFile::FileHandle *) pFP);\r\n//        if (PreMgr::sPreExecuteSuccess())\r\n//            return retval;\r\n//    }\r\n//\r\n////    return skyFwrite(addr, size, count, pFP);\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// GetS                                                          \r\nchar * GetS( char *buffer, int maxlen, void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        char * retval = PreMgr::pre_fgets(buffer, maxlen, (PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tskyFile* fp = (skyFile*)pFP;\r\n\treturn fp->ngcFile.gets( buffer, maxlen ); \r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// PutS                                                          \r\nint PutS( const char *buffer, void *pFP )\r\n{\r\n//    if (PreMgr::sPreEnabled())\r\n//    {\r\n//        int retval = PreMgr::pre_fputs(buffer, (PreFile::FileHandle *) pFP);\r\n//        if (PreMgr::sPreExecuteSuccess())\r\n//            return retval;\r\n//    }\r\n//\r\n////    return skyFputs(buffer, pFP);\r\n\treturn 0;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Eof                                                          \r\nint Eof( void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_feof((PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tskyFile* fp = (skyFile*)pFP;\r\n\treturn fp->ngcFile.eof();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Seek                                                          \r\nint Seek( void *pFP, long offset, int origin )\r\n{\r\n\tif( PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_fseek((PreFile::FileHandle *) pFP, offset, origin);\r\n\t\tif( PreMgr::sPreExecuteSuccess())\r\n\t\t\treturn retval;\r\n\t}\r\n\tskyFile* fp = (skyFile*)pFP;\r\n\tswitch ( origin ) {\r\n\t\tcase SEEK_SET:\r\n\t\t\tfp->ngcFile.seek( NsFileSeek_Start, offset );\r\n\t\t\tbreak;\r\n\t\tcase SEEK_END:\r\n\t\t\tfp->ngcFile.seek( NsFileSeek_End, offset );\r\n\t\t\tbreak;\r\n\t\tcase SEEK_CUR:\r\n\t\tdefault:\r\n\t\t\tfp->ngcFile.seek( NsFileSeek_Current, offset );\r\n\t\t\tbreak;\r\n\t}\r\n\treturn fp->ngcFile.tell();\r\n}\r\n\r\nint32\tTell( void* pFP )\r\n{\r\n\tskyFile* fp = (skyFile *) pFP;\r\n\treturn fp->POS;\r\n}\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Flush                                                          \r\nint Flush( void *pFP )\r\n{\r\n//    if (PreMgr::sPreEnabled())\r\n//    {\r\n//        int retval = PreMgr::pre_fflush((PreFile::FileHandle *) pFP);\r\n//        if (PreMgr::sPreExecuteSuccess())\r\n//            return retval;\r\n//    }\r\n//\r\n////    return skyFflush(pFP);\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace File\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/ngc/p_pre.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tskate3\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\t\t\t\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\trjm\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\t\t\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// start autoduck documentation\r\n// @DOC pre\r\n// @module pre | None\r\n// @subindex Scripting Database\r\n// @index script | pre\r\n                         \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#include <eekernel.h>\r\n#include <core/defines.h>\r\n#include <core/HashTable.h>\r\n#include <sys/File/PRE.h>\r\n#include <sys/file/filesys.h>\r\n\r\n// cd shared by the music streaming stuff...  ASSERT if file access attempted\r\n// while music is streaming:\r\n#include <gel/music/music.h>\r\n\r\n// script stuff\r\n#include <gel/scripting/struct.h> \r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <sys/config/config.h>\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define DEBUG_PRE 0\r\n\r\nnamespace File\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define CURRENT_PRE_VERSION\t0xabcd0002\t\t\t// as of 3/14/2001\r\n//#define CURRENT_PRE_VERSION\t0xabcd0001\t\t// until 3/14/2001\r\n\r\n#define RINGBUFFERSIZE\t\t 4096\t/* N size of ring buffer */\t\r\n#define MATCHLIMIT\t\t   18\t/* F upper limit for match_length */\r\n#define THRESHOLD\t2   /* encode string into position and length */\r\n\r\n#define WriteOut(x) \t{*pOut++ = x;}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nPreMgr *PreMgr::sp_mgr = NULL;\r\nbool    PreMgr::s_lastExecuteSuccess = false; \r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n#define USE_BUFFER\t1\t\t // we don't need no stinking buffer!!!!\r\n \r\n#if USE_BUFFER\r\n#ifdef\t__PLAT_NGPS__\r\n// ring buffer is just over 4K 4096+17), \r\n// so fits nicely in the PS2's 8K scratchpad \r\nunsigned char\ttext_buf[RINGBUFFERSIZE + MATCHLIMIT - 1];\t\r\n// Note:  if we try to use the scratchpad, like this\r\n// then the code actually runs slower\r\n// if we want to optimize this, then it should\r\n// be hand crafted in assembly, using 128bit registers\r\n//\tconst unsigned char * text_buf = (unsigned char*) 0x70000000;\r\n#else\r\nunsigned char\r\n\t\ttext_buf[RINGBUFFERSIZE + MATCHLIMIT - 1];\t/* ring buffer of size N,\r\n\t\t\twith extra F-1 bytes to facilitate string comparison */\r\n#endif\r\n#endif\r\n\r\n\r\n#define\tReadInto(x)\t\tif (!Len) break; Len--; x = *pIn++ \r\n#define\tReadInto2(x)\tLen--; x = *pIn++ \t  // version that knows Len is Ok\r\n\r\n\r\n// Decode an LZSS encoded stream\r\n// Runs at approx 12MB/s on PS2\t without scratchpad (which slows it down in C)\r\n// a 32x CD would run at 4.8MB/sec, although we seem to get a lot less than this\r\n// with our current file system, more like 600K per seconds.....\r\n// Need to write a fast streaming file system....\r\n\r\nvoid DecodeLZSS(unsigned char *pIn, unsigned char *pOut, int Len)\t/* Just the reverse of Encode(). */\r\n{\r\n\tint  i, j, k, r, c;\r\n//\tuint64\tLongWord;\r\n//\tint bytes = 0;\r\n//\tunsigned char *pScratch;\r\n\tunsigned int  flags;\r\n\r\n\r\n\r\n//\tint basetime =  (int) Tmr::ElapsedTime(0);\r\n//\tint len = Len;\r\n\r\n//\tint\tOutBytes = 4;\r\n//\tint\tOutWord = 0;\r\n\r\n\t#if USE_BUFFER\r\n\tfor (i = 0; i < RINGBUFFERSIZE - MATCHLIMIT; i++)\r\n\t\t text_buf[i] = ' ';\r\n\tr = RINGBUFFERSIZE - MATCHLIMIT;\r\n\t#else\r\n\tr = RINGBUFFERSIZE - MATCHLIMIT;\r\n\t#endif\r\n\tflags = 0;\r\n\tfor ( ; ; )\r\n\t{\r\n\t\tif (((flags >>= 1) & 256) == 0)\r\n\t\t{\r\n\t\t\tReadInto(c);\r\n\t\t\tflags = c | 0xff00;\t\t\t/* uses higher byte cleverly */\r\n\t\t}\t\t\t\t\t\t\t\t\t\t/* to count eight */\r\n\t\tif (flags & 1)\r\n\t\t{\r\n\t\t\tReadInto(c);\r\n\t\t\t//\t\t\tputc(c, outfile);\r\n\t\t\tWriteOut(c);\r\n\t\t\t#if USE_BUFFER\r\n\t\t\ttext_buf[r++] = c;\r\n\t\t\tr &= (RINGBUFFERSIZE - 1);\r\n\t\t\t#else\r\n\t\t\tr++;\r\n//\t\t\tr &= (RINGBUFFERSIZE - 1);\t  // don't need to wrap r until it is used\r\n\t\t\t#endif\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tReadInto(i);\t\t\t\r\n\t\t\tReadInto2(j);\t\t\t// note, don't need to check len on this one.... \r\n\t\t\t\r\n\t\t\ti |= ((j & 0xf0) << 4);\t\t\t\t\t\t// i is 12 bit offset\r\n\t\t\t\r\n\t\t\t#if !USE_BUFFER\r\n\t\t\tj = (j & 0x0f) + THRESHOLD+1;\t\t\t\t// j is 4 bit length (above the threshold)\r\n\t\t\tunsigned char *pStream;\r\n\t\t\tr &= (RINGBUFFERSIZE - 1);\t\t\t\t\t// wrap r around before it is used\r\n\t\t\tpStream = pOut - r;\t\t\t\t\t  \t\t// get base of block\r\n\t\t\tif (i>=r)\t\t\t\t\t\t\t\t\t\t// if offset > r, then\r\n\t\t\t\tpStream -= RINGBUFFERSIZE;\t\t\t\t// it's the previous block\r\n\t\t\tpStream += i;\t\t\t\t\t\t\t\t\t// add in the offset to the base\r\n\t\t\tr+=j;\t\t\t\t\t\t\t\t\t\t\t\t// add size to r\r\n\t\t\twhile (j--)\t\t\t\t\t\t\t\t\t\t// copy j bytes\r\n\t\t\t\tWriteOut(*pStream++);\r\n\t\t\t#else\r\n\t\t\t\r\n\t\t\tj = (j & 0x0f) + THRESHOLD;\t\t\t\t// j is 4 bit length (above the threshold)\r\n\t\t\tfor (k = 0; k <= j; k++)\t\t\t\t\t// just copy the bytes\r\n\t\t\t{\r\n\t\t\t\tc =  text_buf[(i+k) & (RINGBUFFERSIZE - 1)]; \r\n\t\t\t\tWriteOut(c);\r\n\t\t\t\ttext_buf[r++] = c;\r\n\t\t\t\tr &= (RINGBUFFERSIZE - 1);\r\n\t\t\t}\r\n\t\t\t#endif\r\n\t\t}\r\n\t}\r\n//\tint Time = (int) Tmr::ElapsedTime(basetime);\r\n//\tif (Time > 5)\r\n//\t{\r\n//\t\tprintf(\"decomp time is %d ms, for %d bytes,  %d bytes/second\\n\", Time,len, len * 1000 /Time );\r\n//\t}\r\n\r\n}\r\n\r\n\r\n\r\n\r\nvoid PreFile::s_delete_file(_File *pFile, void *pData)\r\n{\r\n\tDbg_Assert(pFile);\r\n\tdelete pFile;\r\n}\r\n\r\n\r\n\r\n\r\nPreFile::PreFile(uint8 *p_file_buffer)\r\n{\r\n\tmp_table = new Lst::StringHashTable<_File>(4);\t\r\n\r\n\tDbg_AssertPtr(p_file_buffer);\r\n\r\n\tmp_buffer = p_file_buffer;\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint version = \t*((int *) (mp_buffer + 4));\r\n\tDbg_MsgAssert(version == CURRENT_PRE_VERSION,( \"PRE file version (%x) not current (%x)\",version,CURRENT_PRE_VERSION));\r\n\t#endif\r\n\tm_numEntries = *((int *)(mp_buffer + 8));\r\n\r\n\tuint8 *pEntry = mp_buffer + 12;\r\n\tfor (int i = 0; i < m_numEntries; i++)\r\n\t{\r\n\t\tint data_size \t\t\t\t= *((int *) pEntry);\r\n\t\tint compressed_data_size \t= *((int *) (pEntry + 4));\r\n\t\tint text_size \t\t\t\t= *((int *) (pEntry + 8));\r\n\t\tint actual_data_size = (compressed_data_size != 0) ? compressed_data_size : data_size;\r\n\t\t\t\r\n\t\tchar *pName = (char *) pEntry + 12;\r\n\t\tuint8 *pCompressedData = pEntry + 12 + text_size;\r\n\t\t\r\n\t\t_File *pFile = new (Mem::Manager::sHandle().TopDownHeap()) _File;\r\n\r\n\t\tif (!mp_table->GetItem(pName)) \r\n\t\t{\r\n\t\t\t// file is not in table, safe to add\r\n\t\t\tmp_table->PutItem(pName, pFile);\r\n\t\t\t\r\n\t\t\tpFile->compressedDataSize = compressed_data_size;\r\n\t\t\tpFile->pCompressedData = pCompressedData; \r\n\t\t\tpFile->pData = NULL;\r\n\t\t\tpFile->sky.POS = 0;\r\n\t\t\tpFile->sky.SOF = data_size;\r\n\t\t}\r\n\t\telse\r\n\t\t\t// Somehow, file is already in table, just kill it\r\n\t\t\t// Later, I'll want to add an assert\r\n\t\t\tdelete pFile;\r\n\t\t\r\n#\t\tif DEBUG_PRE\r\n\t\tprintf(\"   %s, size %d\\n\", pName, data_size);\r\n#\t\tendif\r\n\t\t\r\n\t\tpEntry += 12 + text_size + ((actual_data_size + 3) & (~3));\r\n\t}\r\n\r\n#\tif DEBUG_PRE\r\n\tprintf(\"Done loading PRE\\n\");\r\n#\tendif\r\n\t\r\n\tmp_activeFile = NULL;\r\n}\r\n\r\n\r\n\r\nPreFile::~PreFile()\r\n{\r\n\tdelete mp_buffer;\r\n\tmp_table->HandleCallback(s_delete_file, NULL);\r\n\tmp_table->FlushAllItems();\r\n\r\n\tdelete mp_table;\r\n}\r\n\r\n\r\n\r\n// returns handle pointer\r\nvoid *PreFile::GetContainedFile(const char *pName)\r\n{\r\n\t\r\n\t_File *pFile = mp_table->GetItem(pName, false);\r\n\tif (!pFile) \r\n\t\treturn NULL;\r\n\t\r\n\tdumbSkyFile *pHandle = &pFile->sky;\r\n\t// kinda roundabout, but sets mp_activeFile\r\n\tGetContainedFileByHandle(pHandle);\r\n\t\r\n\t// do we need to fetch file data?\r\n\tif (!mp_activeFile->pData)\r\n\t{\r\n\t\tif (mp_activeFile->compressedDataSize)\r\n\t\t{\r\n\t\t\tmp_activeFile->pData = new (Mem::Manager::sHandle().TopDownHeap()) uint8[mp_activeFile->sky.SOF];\t\t\r\n\t\t\t// need to uncompress data\r\n\t\t\tDecodeLZSS(mp_activeFile->pCompressedData, mp_activeFile->pData, mp_activeFile->compressedDataSize);\t\r\n\t\t}\r\n\t}\r\n\r\n\treturn pHandle;\r\n}\r\n\t\r\n\r\n\r\nuint8 *PreFile::GetContainedFileByHandle(void *pHandle)\r\n{\r\n\tmp_table->IterateStart();\r\n\t_File *pFile = mp_table->IterateNext();\r\n\twhile(pFile)\r\n\t{\r\n\t\tuint8 *pCompressedData = pFile->pCompressedData;\r\n\t\tif (pCompressedData && &pFile->sky == pHandle)\r\n\t\t{\r\n\t\t\tmp_activeFile = pFile;\r\n\t\t\t\r\n\t\t\tif (mp_activeFile->compressedDataSize)\r\n\t\t\t\treturn mp_activeFile->pData;\r\n\t\t\telse\r\n\t\t\t\treturn mp_activeFile->pCompressedData;\r\n\t\t}\r\n\t\tpFile = mp_table->IterateNext();\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\nvoid PreFile::Reset()\r\n{\r\n\t\r\n\tDbg_AssertPtr(mp_activeFile);\r\n\r\n\tmp_activeFile->sky.POS = 0;\r\n}\r\n\r\n\r\n\r\nuint32 PreFile::Read(void *addr, uint32 count)\r\n{\r\n\t\r\n\tDbg_AssertPtr(mp_activeFile);\r\n\r\n\tint seek_offs = mp_activeFile->sky.POS;\r\n\tunsigned int limit = mp_activeFile->sky.SOF - seek_offs;\r\n\tint copy_number = (count <= limit) ? count : limit; \r\n\tif (mp_activeFile->compressedDataSize)\r\n\t{\r\n\t\tDbg_MsgAssert(mp_activeFile->pData,( \"file not uncompressed\"));\r\n\t\tmemcpy(addr, mp_activeFile->pData + mp_activeFile->sky.POS, copy_number);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmemcpy(addr, mp_activeFile->pCompressedData + mp_activeFile->sky.POS, copy_number);\r\n\t}\r\n\r\n\tmp_activeFile->sky.POS += copy_number;\r\n\r\n#if DEBUG_PRE\r\n\t\tprintf(\"PRE: read %d bytes from file, handle 0x%x\\n\", copy_number, (int) mp_activeFile->pData);\r\n#endif\r\n\treturn copy_number;\r\n}\r\n\r\n\r\n\r\nint PreFile::Eof()\r\n{\r\n\t\r\n\tDbg_AssertPtr(mp_activeFile);\r\n\r\n\tif (mp_activeFile->sky.POS >= mp_activeFile->sky.SOF)\r\n\t{\r\n#if DEBUG_PRE\r\n\t\tprintf(\"PRE: at end of file\\n\");\r\n#endif\r\n\t\treturn 1;\r\n\t}\r\n\r\n#if DEBUG_PRE\r\n\tprintf(\"PRE: not at end of file\\n\");\r\n#endif\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nvoid PreFile::Close()\r\n{\r\n\t\r\n\t//Dbg_MsgAssert(mp_activeFile->pData,( \"file not uncompressed\"));\r\n\r\n\tif (mp_activeFile->pData)\r\n\t\tdelete mp_activeFile->pData;\r\n\tmp_activeFile->pData = NULL;\r\n}\r\n\r\n\r\n\r\nint PreFile::Seek(long offset, int origin)\r\n{\r\n\tint32 old_pos = mp_activeFile->sky.POS;\r\n\r\n\t// SEEK_CUR, SEEK_END, SEEK_SET\r\n\tswitch(origin)\r\n\t{\r\n\t\tcase SEEK_CUR:\r\n\t\t\tmp_activeFile->sky.POS += offset;\r\n\t\t\tbreak;\r\n\t\tcase SEEK_END:\r\n\t\t\tmp_activeFile->sky.POS = mp_activeFile->sky.SOF - offset;\r\n\t\t\tbreak;\r\n\t\tcase SEEK_SET:\r\n\t\t\tmp_activeFile->sky.POS = offset;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\treturn -1;\r\n\t}\r\n\r\n\tif (mp_activeFile->sky.POS < 0 || mp_activeFile->sky.POS > mp_activeFile->sky.SOF)\r\n\t{\r\n\t\tmp_activeFile->sky.POS = old_pos;\r\n\t\treturn -1;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nPreMgr::PreMgr() \r\n{\r\n\tmp_table = new Lst::StringHashTable<PreFile>(4);\r\n\r\n\tsp_mgr = this;\r\n\r\n\r\n\tmp_activeHandle = NULL;\r\n\tmp_activeData = NULL;\r\n\r\n\tmp_activeNonPreHandle = NULL;\r\n}\r\n\r\n\r\n\r\nPreMgr::~PreMgr()\r\n{\r\n\tdelete mp_table;\r\n}\r\n\r\n\r\n\r\n// Returns handle\r\n// Not frequently called\r\nvoid *PreMgr::getContainedFile(const char *pName)\r\n{\r\n\t\r\n\tDbg_AssertPtr(pName);\r\n\r\n\t// replace all '/' with '\\'\r\n\tchar cleaned_name[128];\r\n\tconst char *pCharIn = pName;\r\n\tchar *pCharOut = cleaned_name;\r\n\twhile (1)\r\n\t{\r\n\t\t*pCharOut = *pCharIn;\r\n\t\tif (*pCharIn == '\\0') break;\r\n\t\tif (*pCharOut == '/') *pCharOut = '\\\\';\r\n\t\tpCharIn++;\r\n\t\tpCharOut++;\t\t\r\n\t}\r\n\r\n\tvoid *pHandle = NULL;\r\n\r\n\tmp_table->IterateStart();\r\n\tPreFile *pPre = mp_table->IterateNext();\r\n\twhile(pPre)\r\n\t{\r\n\t\tpHandle = pPre->GetContainedFile(cleaned_name);\r\n\t\tif (pHandle) \r\n\t\t{\r\n\t\t\tmp_activePre = pPre;\r\n\t\t\tmp_activeHandle = pHandle;\r\n\t\t\tmp_activeData = pPre->GetContainedFileByHandle(pHandle);\r\n#\t\t\tifdef __PLAT_NGPS__\r\n\t\t\tscePrintf(\"+++ %s is in PRE\\n\", cleaned_name);\r\n#\t\t\tendif\r\n\t\t\treturn pHandle;\r\n\t\t}\r\n\t\tpPre = mp_table->IterateNext();\r\n\t}\r\n\r\n#\tifdef __PLAT_NGPS__\r\n\tscePrintf(\"--- %s not found in PRE\\n\", cleaned_name);\r\n#\tendif\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n// returns pointer to data\r\nuint8 *PreMgr::getContainedFileByHandle(void *pHandle)\r\n{\r\n\t\r\n\tDbg_AssertPtr(pHandle);\r\n\r\n\t// if we know that the file in question is not in the PRE system,\r\n\t// then it's a regular file, don't waste time looking for it\r\n\tif (mp_activeNonPreHandle == pHandle)\r\n\t\treturn NULL;\r\n\t\r\n\tif (mp_activeHandle == pHandle)\r\n\t\t// mp_activePre will be unchanged\r\n\t\treturn mp_activeData;\r\n\t\r\n\tuint8 *pData = NULL;\r\n\tmp_table->IterateStart();\r\n\tPreFile *pPre = mp_table->IterateNext();\r\n\twhile(pPre)\r\n\t{\r\n\t\tpData = pPre->GetContainedFileByHandle(pHandle);\r\n\t\tif (pData)\r\n\t\t{\r\n\t\t\tmp_activePre = pPre;\r\n\t\t\tmp_activeHandle = pHandle;\r\n\t\t\tmp_activeData = pData;\t\t\t\r\n\t\t\treturn pData;\r\n\t\t}\r\n\t\tpPre = mp_table->IterateNext();\r\n\t}\r\n\r\n\t// obviously this file is not in the PRE system, mark as such\r\n\tmp_activeNonPreHandle = pHandle;\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n// there's a wrapper around this now, so that we can do\r\n// some memory-context switching\r\nvoid PreMgr::loadPre(const char *pFilename, bool dont_assert)\r\n{\r\n\t\r\n\r\n#\tifdef __PLAT_XBOX__\r\n\t// Do nothing.\r\n\treturn;\r\n#\tendif\r\n\r\n\r\n\r\n\tm_blockPreLoading = (bool) Script::GetInt(\"block_pre_loading\", false);\r\n\r\n\tif (m_blockPreLoading)\r\n\t\treturn;\r\n\r\n\tif( Pcm::UsingCD() )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Moved this to below the Pcm::UsingCD() call as that is used (bad!!) to turn off\r\n\t// music and streams.\r\n#\tifdef __PLAT_NGPS__\r\n//\tscePrintf(\"Loading PRE file %s...\\n\", pFilename);\r\n#\tendif\r\n\r\n\tchar fullname[256];\r\n\tsprintf(fullname, \"pre\\\\%s\", pFilename);\r\n\r\n\tTmr::Time basetime = Tmr::ElapsedTime(0);\r\n\r\n\r\n\tint file_size;\r\n\tuint8 *pFile = NULL;\r\n\r\n\tfile_size = CanFileBeLoadedQuickly( fullname );\r\n\tif ( file_size )\r\n\t{\r\n\t\tpFile = new (Mem::Manager::sHandle().TopDownHeap()) uint8[file_size];\r\n\t\tbool fileLoaded= LoadFileQuicklyPlease( fullname, pFile );\r\n\t\tif ( !fileLoaded )\r\n\t\t{\r\n\t\t\tprintf( \"pre file %s failed to load quickly.\\n\", fullname );\r\n\t\t\tDbg_MsgAssert( 0,( \"Fire Matt - pre file didn't load quickly.\" ));\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t\tvoid *fp = File::Open(fullname, \"rb\");\r\n\t\t\tif (!fp)\r\n\t\t\t{\r\n\t\t\t// always run the code below if CD build\r\n\t\t\t\tif (dont_assert || Config::CD()) \r\n\t\t\t\t{\r\n\t\t\t\t\tprintf(\"couldn't open %s\\n\", fullname);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tDbg_MsgAssert(0,( \"couldn't open %s\\n\", fullname));\r\n\t\t\t}\r\n\r\n\r\n\t\t\tFile::Read(&file_size, 4, 1, fp);\r\n\t\t\tDbg_MsgAssert(file_size > 0,( \"%s has incorrect file size\\n\", fullname));\r\n\t\t\tif (Config::CD())\r\n\t\t\t{\r\n\t\t\t\tif (file_size <= 0) printf(\"%s has incorrect file size\\n\", fullname);\r\n\t\t\t}\t\r\n\r\n\r\n\t\t// Now allocates the .PRE file from the top of the heap, to avoid fragmentation.\r\n\t\t\tpFile = new (Mem::Manager::sHandle().TopDownHeap()) uint8[file_size];\r\n\t\t//uint8 *pFile = new uint8[file_size];\r\n\t\t\tFile::Read(pFile + 4, 1, file_size, fp);\r\n\t\t\tFile::Close(fp);\r\n\t\t}\r\n\r\n\t\tprintf(\"load time for file size %d is %d ms\\n\", file_size, (int) Tmr::ElapsedTime(basetime));\r\n\r\n\t// the PRE file object winds up at the top of the heap, too. This is fine because\r\n\t// it will be unloaded at the same time as the big file buffer\r\n\t\tif (!mp_table->PutItem(pFilename, new (Mem::Manager::sHandle().TopDownHeap()) PreFile(pFile)))\r\n\t\t\tDbg_MsgAssert(0,( \"PRE %s loaded twice\", pFilename));\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nDefineSingletonClass(PreMgr, \"PRE Manager\");\r\n\r\n\r\n\r\nbool PreMgr::InPre(const char *pFilename)\r\n{\r\n\t\r\n\r\n\treturn mp_table->GetItem( pFilename );\r\n}\r\n\r\n\r\n\r\nvoid PreMgr::LoadPre(const char *pFilename, bool dont_assert)\r\n{\r\n\t// GJ:  This function is a wrapper around loadPRE(), to\r\n\t// make sure that all allocations go on the top-down heap\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tloadPre(pFilename, dont_assert);\r\n\tMem::Manager::sHandle().PopContext();\t\r\n}\r\n\r\n\r\n\r\nvoid PreMgr::LoadPrePermanently(const char *pFilename, bool dont_assert)\r\n{\r\n\t// GJ:  This function is a wrapper around LoadPRE(),\r\n\t// used for loading PRE files which will reside in memory\r\n\t// permanently.  Essentially, we need to make sure that the\r\n\t// data is above Renderware's resource arena.  If you didn't\r\n\t// use this function, you'd get fragmentation when the resource\r\n\t// arena resized itself.\r\n\r\n\t// Mick: Removed reference to renderware, the old \"arena\" concept is gone\r\n\r\n\t\r\n\t// Load the pre file...\r\n\t// This will go on the top-down heap by default\r\n\tLoadPre(pFilename, dont_assert);\r\n\r\n}\r\n\r\n\r\n\r\nvoid PreMgr::UnloadPre(const char *pFilename, bool dont_assert)\r\n{\r\n\t\r\n\r\n#\tifdef __PLAT_NGPS__\r\n//\tscePrintf(\"Unloading PRE file %s\\n\", pFilename);\r\n#\tendif\r\n\t\r\n\tif (m_blockPreLoading)\r\n\t\treturn;\r\n\t\r\n\tPreFile *pThePre = mp_table->GetItem(pFilename);\r\n\tif (!pThePre)\r\n\t{\r\n\t\tif (dont_assert) return;\r\n\t\tDbg_MsgAssert(0,( \"PRE file %s not in PRE manager\", pFilename));\r\n\t}\r\n\r\n\tmp_table->FlushItem(pFilename);\r\n\tdelete pThePre;\r\n}\r\n\r\n\r\nbool PreMgr::sPreEnabled()\r\n{\r\n\treturn sp_mgr != NULL;\r\n}\r\n\r\nbool PreMgr::sPreExecuteSuccess()\r\n{\r\n\treturn s_lastExecuteSuccess; \r\n}\r\n\r\nbool PreMgr::pre_fexist(const char *name)\r\n{\r\n\t\r\n\tDbg_MsgAssert(name,( \"requesting file NULL\"));\t\r\n\t\r\n\tif (sp_mgr->getContainedFile(name)) \r\n\t{\r\n#\t\tif DEBUG_PRE\r\n\t\tprintf(\"PRE: file %s exists\\n\", name);\r\n#\t\tendif\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn true;\r\n\t}\r\n\tif ( Pcm::UsingCD( ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn s_lastExecuteSuccess = false;\r\n}\r\n\r\n\r\n\r\nvoid *PreMgr::pre_fopen(const char *name, const char *access)\r\n{\r\n\t\t\r\n\tDbg_MsgAssert(name,( \"trying to open file NULL\"));\t\r\n\r\n\tvoid *pHandle = sp_mgr->getContainedFile(name);\r\n\tif (pHandle)\r\n\t{\r\n\t\t// if we are going to write the file, we want to use the regular file system\r\n\t\tconst char *pChar = access;\r\n\t\tbool am_writing = false;\r\n\t\twhile(*pChar)\r\n\t\t{\r\n\t\t\tif (*pChar != 'r' && *pChar != 'b')\r\n\t\t\t\tam_writing = true;\r\n\t\t\tpChar++;\r\n\t\t}\r\n\t\t\r\n\t\tif (am_writing)\r\n\t\t{\r\n#\t\t\tifdef __PLAT_NGPS__\r\n//\t\t\tscePrintf(\"    writing file %s\\n\", name);\r\n#\t\t\tendif\r\n\r\n\t\t\t// am writing, so we don't need file open in PRE system\r\n\t\t\tsp_mgr->mp_activePre->Close();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// we're reading the file from the PRE system\r\n#\t\t\tif DEBUG_PRE\r\n\t\t\tprintf(\"PRE: opened file %s, handle is 0x%x\\n\", name, (int) pHandle);\r\n#\t\t\tendif\r\n\t\t\tsp_mgr->mp_activePre->Reset();\r\n\t\t\ts_lastExecuteSuccess = true;\r\n\t\t\treturn pHandle;\r\n\t\t}\r\n\t}\r\n\r\n\t// if we get here, we are using the regular file system\r\n\tif ( Pcm::UsingCD( ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\ts_lastExecuteSuccess = false;\r\n\treturn NULL;\r\n\r\n\t//return pHandle;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_fclose(void *fptr)\r\n{\r\n\t\t\r\n\tDbg_MsgAssert(fptr,( \"calling fclose with invalid file ptr\"));\t\r\n\t\r\n\tuint8 *pData = sp_mgr->getContainedFileByHandle(fptr);\r\n\tif (pData)\r\n\t{\r\n#if DEBUG_PRE\r\n\t\tprintf(\"PRE: closed file, handle 0x%x\\n\", (int) fptr);\r\n#endif\r\n\t\tsp_mgr->mp_activePre->Close();\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn 0;\r\n\t}\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nsize_t PreMgr::pre_fread(void *addr, size_t size, size_t count, void *fptr)\r\n{\r\n\t\t\r\n\tDbg_MsgAssert(fptr,( \"calling fread with invalid file ptr\"));\t\t\r\n\r\n\tuint8 *pData = sp_mgr->getContainedFileByHandle(fptr);\r\n\tif (pData)\r\n\t{\r\n\t\t// read from a simulated file stream in PRE file\r\n\t\tDbg_AssertPtr(sp_mgr->mp_activePre);\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn sp_mgr->mp_activePre->Read(addr, size * count);\r\n\t}\r\n\tif ( Pcm::UsingCD( ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n\t\treturn 0;\r\n\t}\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nsize_t  PreMgr::pre_fwrite(const void *addr, size_t size, size_t count, void *fptr)\r\n{\r\n\t\t\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint8 *pData = \r\n\t#endif\r\n\tsp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"can't write to a PRE file\"));\r\n\t\r\n\tif ( Pcm::UsingCD( ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n\t\treturn 0;\r\n\t}\r\n\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nchar *PreMgr::pre_fgets(char *buffer, int maxLen, void *fptr)\r\n{\r\n\t\t\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint8 *pData = \r\n\t#endif\r\n\tsp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"can't do string ops on a PRE file\"));\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_fputs(const char *buffer, void *fptr)\r\n{\r\n\t\t\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint8 *pData = \r\n\t#endif\r\n\tsp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"can't do string ops on a PRE file\"));\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_feof(void *fptr)\r\n{\r\n\t\t\r\n\tDbg_MsgAssert(fptr,( \"calling feof with invalid file ptr\"));\t\t\r\n\r\n\tuint8 *pData = \tsp_mgr->getContainedFileByHandle(fptr);\r\n\tif (pData)\r\n\t{\r\n\t\tDbg_AssertPtr(sp_mgr->mp_activePre);\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn sp_mgr->mp_activePre->Eof();\r\n\t}\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_fseek(void *fptr, long offset, int origin)\r\n{\r\n\t\t\r\n\r\n\tuint8 *pData = \tsp_mgr->getContainedFileByHandle(fptr);\r\n\tif (pData)\r\n\t{\r\n\t\ts_lastExecuteSuccess = true;\r\n\t\treturn sp_mgr->mp_activePre->Seek(offset, origin);\r\n\t}\r\n\r\n\tDbg_MsgAssert(!pData,( \"seek not supported for PRE file\"));\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_fflush(void *fptr)\r\n{\r\n\t\t\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint8 *pData = \r\n\t#endif\r\n\tsp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"flush not supported for PRE file\"));\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\nint PreMgr::pre_ftell(void *fptr)\r\n{\r\n\t\t\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tuint8 *pData = \r\n\t#endif\r\n\tsp_mgr->getContainedFileByHandle(fptr);\r\n\tDbg_MsgAssert(!pData,( \"tell supported for PRE file\"));\r\n\t\r\n\ts_lastExecuteSuccess = false;\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n// @script | InPreFile | \r\n// @uparm \"string\" | filename\r\nbool ScriptInPreFile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *pFilename;\r\n\tpParams->GetText(NONAME, &pFilename, true);\r\n\r\n\tSpt::SingletonPtr<PreMgr> pre_mgr;\r\n\treturn pre_mgr->InPre(pFilename);\r\n}\r\n\r\n\r\n\r\n// @script | LoadPreFile | \r\n// @uparm \"string\" | filename\r\n// @flag dont_assert | \r\nbool ScriptLoadPreFile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *pFilename;\r\n\tpParams->GetText(NONAME, &pFilename, true);\r\n\r\n\tSpt::SingletonPtr<PreMgr> pre_mgr;\r\n\tpre_mgr->LoadPre(pFilename, pParams->ContainsFlag(\"dont_assert\"));\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n// @script | UnloadPreFile | \r\n// @flag BoardsPre | \r\n// @flag dont_assert | \r\n// @uparm \"string\" | filename\r\nbool ScriptUnloadPreFile(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t\r\n\r\n\tSpt::SingletonPtr<PreMgr> pre_mgr;\r\n\t\r\n\tif (pParams->ContainsFlag(\"BoardsPre\"))\r\n\t{\r\n\t\t\r\n//\t\tSpt::SingletonPtr< Mdl::Skate >\tpSkate;\r\n//\t\tpSkate->UnloadBoardPreIfPresent(pParams->ContainsFlag(\"dont_assert\"));\r\n\t\tprintf (\"STUBBED:  Unload BoardsPre, in ScriptUnloadPreFile\\n\");\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tconst char *pFilename;\r\n\tpParams->GetText(NONAME, &pFilename, true);\r\n\r\n\tpre_mgr->UnloadPre(pFilename, pParams->ContainsFlag(\"dont_assert\"));\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n} // namespace File\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/ngps/FileIO/FIleIO_IOP.h",
    "content": "\r\n// This file is included by the IOP side only.  Make sure all\r\n// changes are C compatible.\r\n\r\n#ifndef\t__SYS_FILE_NGPS_FILEIO_IOP_H\r\n#define\t__SYS_FILE_NGPS_FILEIO_IOP_H\r\n\r\n#include \"fileio.h\"\r\n\r\n\r\n#if 0\r\n#define PRINTF(x) printf x\r\n#else\r\n#define PRINTF(x) \r\n#endif\r\n//#define ERROR(x) printf x\r\n#define ERROR(A...) Kprintf(##A); while(1)\r\n#define xPRINTF(x) \r\n\r\n#define BASE_priority  32\r\n\r\n#define TRUE 1\r\n#define FALSE 0\r\n\r\n#define FILEIO_MAX_HANDLERS\t\t(16)\r\n#define FILEIO_MAX_BUFFERS\t\t((NUM_DEVICE_TYPES - 1) * 2)\t\t// Don't need buffer for the Unknown device\r\n#define FILEIO_MAX_TASKS\t\t(20)\r\n\r\n// Function enums (for callback)\r\ntypedef enum\r\n{\r\n\tFILEIO_FUNCTION_IDLE = 0,\t\t\t\t\t// No function is being waited on\r\n\tFILEIO_FUNCTION_OPEN,\r\n\tFILEIO_FUNCTION_SEEK,\r\n\tFILEIO_FUNCTION_READ,\r\n\tFILEIO_FUNCTION_WRITE,\r\n} EFileIOFunction;\r\n\r\n// Device types\r\ntypedef enum\r\n{\r\n\tDEVICE_CD = 0,\r\n\tDEVICE_HOST,\r\n\tDEVICE_UNKNOWN,\t\t// This is always the last device type (also where all requests start)\r\n\tNUM_DEVICE_TYPES,\r\n} EDeviceType;\r\n\r\ntypedef enum\r\n{\r\n\tMEM_EE = 0,\r\n\tMEM_IOP,\r\n} EMemoryType;\r\n\r\n// FileIOHandle Flags\r\n#define\tFILEIO_HANDLE_BUSY\t\t(0x0001)\t\t// Handle currently busy\r\n#define\tFILEIO_HANDLE_RESERVED\t(0x0002)\t\t// Handle currently allocated to someone\r\n#define\tFILEIO_HANDLE_PREV_DMA\t(0x0004)\t\t// Already sent out DMA info (meaning m_last_dma_id is valid)\r\n#define\tFILEIO_HANDLE_NOWAIT\t(0x0008)\t\t// Last function called finished immediately\r\n#define\tFILEIO_HANDLE_EE_MEMORY\t(0x0010)\t\t// Destionion is EE memory\r\n\r\n// File handle\r\ntypedef struct\r\n{\r\n\t// General data\r\n\tvolatile int\tm_flags;\r\n//\tvoid *\t\t\tmp_buffer[2];\t\t// This is only needed for EE transfers\r\n//\tint\t\t\t\tm_buffer_index;\t\t// This is only needed for EE transfers\r\n\tvoid *\t\t\tmp_dest_buffer;\t\t// Could be either an EE or IOP address\r\n\tint\t\t\t\tm_buffer_size;\r\n\tEDeviceType\t\tm_device_type;\r\n\tint\t\t\t\tm_host_fd;\t\t\t// File descriptor for host IO\r\n\tint\t\t\t\tm_priority;\r\n\tint\t\t\t\tm_stream;\r\n\tint\t\t\t\tm_start_sector;\r\n\tint\t\t\t\tm_cur_sector;\r\n\tint\t\t\t\tm_cur_position;\r\n\tint\t\t\t\tm_file_size;\r\n\tint\t\t\t\tm_open_request_id;\r\n\tSFileIORequest *mp_blocked_request;\t// If handle is marked BUSY but waiting for the device, this is the request that\r\n\t\t\t\t\t\t\t\t\t\t// will execute when the device finally becomes free.\r\n\r\n\t// Current IO variables\r\n\tEFileIOFunction\tm_cur_function;\r\n\tint\t\t\t\tm_bytes_to_process;\r\n\tint\t\t\t\tm_bytes_processing;\r\n\tunsigned short\tm_non_aligned_start_bytes;\r\n\tunsigned short\tm_non_aligned_end_bytes;\r\n\tint\t\t\t\tm_request_id;\r\n\tint\t\t\t\tm_return_value;\r\n\tint\t\t\t\tm_return_data;\r\n\tunsigned int\tm_last_dma_id;\r\n} SFileIOHandle;\r\n\r\n// Request task\r\ntypedef struct FileIOTask\r\n{\r\n\tSFileIORequestEntry \tm_entry;\r\n\tSFileIOHandle *\t\t\tmp_file_handle;\r\n\tstruct FileIOTask *\t\tmp_cont;\t// Continued packets for the same request\r\n\tstruct FileIOTask *\t\tmp_next;\r\n} SFileIOTask;\r\n\r\n// Device status\r\ntypedef struct\r\n{\r\n\tvolatile int\tm_in_use;\r\n\tvolatile int\tm_waiting_callback;\r\n\tSFileIOHandle *\tmp_file_handle;\r\n\tvoid *\t\t\tmp_buffer[2];\t\t// This is only needed for EE transfers\r\n\tint\t\t\t\tm_buffer_index;\t\t// This is only needed for EE transfers\r\n\tint\t\t\t\tm_cur_sector;\r\n\tint\t\t\t\tm_cur_position;\r\n\tSFileIOTask *\tmp_task_list;\r\n} SFileIODevice;\r\n\r\n\r\n// Request state\r\ntypedef enum\r\n{\r\n\tREQUEST_OPEN,\t\t\t// Still waiting to be started\r\n\tREQUEST_PROCESSING,\t\t// Currently executing\r\n\tREQUEST_APPEND,\t\t\t// Needs appending to a current request\r\n\tREQUEST_COMPLETE,\t\t// Done\r\n} ERequestState;\r\n\r\n// Request Status\r\ntypedef struct\r\n{\r\n\tint\t\t\t\tm_request_id;\r\n\tERequestState\tm_request_state;\r\n\tSFileIOHandle *\tmp_file_handle;\r\n\tint\t\t\t\tm_return_value;\r\n\tint\t\t\t\tm_return_data;\r\n} SRequestStatus;\r\n\r\n#endif\t// __SYS_FILE_NGPS_FILEIO_IOP_H\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/ngps/FileIO/FileIO.h",
    "content": "// This file is included by both the EE and IOP side.  Make sure all\r\n// changes are C compatible.\r\n\r\n#ifndef\t__SYS_FILE_NGPS_FILEIO_H\r\n#define\t__SYS_FILE_NGPS_FILEIO_H\r\n\r\n#include <sifcmd.h>\r\n\r\n#ifndef SECTOR_SIZE\r\n#define SECTOR_SIZE\t\t\t\t\t\t\t( 2048 )\r\n#endif // SECTOR_SIZE\r\n\r\n// Make sure these don't conflict with the Stream IRX\r\n#define FILEIO_REQUEST_COMMAND\t\t\t\t(1)\r\n#define FILEIO_RESULT_COMMAND\t\t\t\t(1)\r\n#define FILEIO_NUM_COMMAND_HANDLERS \t\t(0x10)\r\n\r\n#define FILEIO_TEMP_HANDLE_FLAG\t\t\t\t(0x80000000)\r\n\r\n#define FILEIO_MAX_FILENAME_SIZE\t\t\t(80)\r\n\r\n#define FILEIO_BUFFER_SECTORS\t\t\t\t(8)\r\n#define FILEIO_BUFFER_SIZE\t\t\t\t\t(FILEIO_BUFFER_SECTORS * SECTOR_SIZE)\r\n\r\n#define FILEIO_CACHE_BLOCK_SIZE\t\t\t\t(64)\t\t\t\t\t\t\t\t// Cache block size for EE\r\n#define FILEIO_CACHE_BLOCK_NONALIGN_MASK\t(FILEIO_CACHE_BLOCK_SIZE - 1)\t\t// Masks out the non-aligned address bits\r\n#define FILEIO_CACHE_BLOCK_ALIGN_MASK\t\t(~FILEIO_CACHE_BLOCK_NONALIGN_MASK)\t// Masks out the aligned address bits\r\n\r\n// The FileIO commands\r\ntypedef enum\r\n{\r\n\tFILEIO_INIT = 0,\r\n\tFILEIO_OPEN,\r\n\tFILEIO_CLOSE,\r\n\tFILEIO_READ,\r\n\tFILEIO_WRITE,\r\n\tFILEIO_SEEK,\r\n\tFILEIO_SET,\r\n\tFILEIO_CONT,\r\n} FileIOCommand;\r\n\r\ntypedef enum\r\n{\r\n\tFILEIO_VAR_PRIORITY,\r\n\tFILEIO_VAR_BUFFER_SIZE,\r\n\tFILEIO_VAR_STREAM,\r\n\tFILEIO_VAR_DESTINATION,\r\n} FileIOVariable;\r\n\r\ntypedef enum\r\n{\r\n\tFILEIO_HOSTOPEN_FALSE = 0,\r\n\tFILEIO_HOSTOPEN_TRUE,\r\n\tFILEIO_HOSTOPEN_EXTEND_NAME,\r\n} FileIOHostOpen;\r\n\r\n////////////////////////////////////\r\n// Command parameters\r\n// All structures sizes + 4 bytes (for command itself) must be 16-byte aligned\r\n//\r\n\r\n// General Parameters\r\ntypedef struct\r\n{\r\n\tint\t\t\t\tm_param[3];\r\n} SGeneralParam;\r\n\r\n// Init Parameters\r\ntypedef struct\r\n{\r\n\tint\t\t\t\tm_priority;\r\n\tint\t\t\t\tm_buffer_size;\r\n\tshort\t\t\tm_memory_dest;\r\n\tshort\t\t\tm_init_cd_device;\r\n} SInitParam;\r\n\r\n// Open Parameters\r\ntypedef struct\r\n{\r\n\tint\t\t\t\tm_sector_number;\r\n\tint\t\t\t\tm_file_size;\r\n} SRawFileName;\r\n\r\ntypedef struct\r\n{\r\n\tint\t\t\t\tm_buffer_size;\r\n\tint\t\t\t\tm_priority;\r\n\r\n\t// Unions must be named in C\r\n\tunion\r\n\t{\r\n\t\tchar\t\t m_filename[FILEIO_MAX_FILENAME_SIZE];\r\n\t\tSRawFileName m_raw_name;\r\n\t} m_file;\r\n\r\n\tshort\t\t\tm_attributes;\r\n\tunsigned char\tm_host_read;\r\n\tunsigned char\tm_memory_dest;\r\n} SOpenParam;\r\n\r\n// Close Parameters\r\ntypedef struct\r\n{\r\n\tunsigned int\tm_file_handle;\r\n\tint\t\t\t\tm_pad[2];\r\n} SCloseParam;\r\n\r\n// Read/Write Parameters\r\ntypedef struct\r\n{\r\n\tunsigned int\tm_file_handle;\r\n\tvoid *\t\t\tm_buffer;\r\n\tsize_t\t\t\tm_size;\r\n\tunsigned short\tm_non_aligned_start_bytes;\r\n\tunsigned short\tm_non_aligned_end_bytes;\r\n\tint\t\t\t\tm_pad[3];\r\n} SRWParam;\r\n\r\n// Seek Parameters\r\ntypedef struct\r\n{\r\n\tunsigned int\tm_file_handle;\r\n\tint\t\t\t\tm_offset;\r\n\tint\t\t\t\tm_origin;\r\n} SSeekParam;\r\n\r\n// Set Parameters\r\ntypedef struct\r\n{\r\n\tunsigned int\tm_file_handle;\r\n\tFileIOVariable\tm_variable;\r\n\tint\t\t\t\tm_value;\r\n} SSetParam;\r\n\r\n// Parameter Union\r\ntypedef union\r\n{\r\n\tSGeneralParam\tm_general;\r\n\tSInitParam\t\tm_init;\r\n\tSOpenParam\t\tm_open;\r\n\tSCloseParam\t\tm_close;\r\n\tSRWParam\t\tm_rw;\r\n\tSSeekParam\t\tm_seek;\r\n\tSSetParam\t\tm_set;\r\n} SFileIOParam;\r\n\r\n// Make sure this doesn't break the alignment of SSifCmdFileIOReqPacket\r\ntypedef struct\r\n{\r\n\t// Add union first so it aligns correctly\r\n\tSFileIOParam\t\tm_param;\r\n\tFileIOCommand\t\tm_command;\r\n} SFileIORequest;\r\n\r\n\r\n////////////////////////////////////\r\n// Other structures\r\n// \r\n\r\n// SifCmd structures ( keeping them 128-bit aligned )\r\ntypedef struct\r\n{\r\n\tsceSifCmdHdr\tm_header;\r\n\tSFileIORequest\tm_request;\r\n} SFileIORequestPacket;\r\n\r\n// Packet that is sent back to EE after a request is made\r\ntypedef struct\r\n{\r\n\tsceSifCmdHdr\tm_header;\r\n\tint\t\t\t\tm_return_value;\t\t\t// Return value\r\n\tint\t\t\t\tm_done;\t\t\t\t\t// Indicates request completed\r\n\tint\t\t\t\tm_byte_transfer;\t\t// Number of bytes copied in secondary DMA\r\n\tint\t\t\t\tm_return_data;\t\t\t// Additional return data\r\n\r\n\t// Non-aligned data buffer (for beginning and end of buffers that don't cover a whole cache block)\r\n\tint\t\t\t\tm_non_aligned_data_size;\r\n\tunsigned char\tm_non_aligned_data[FILEIO_CACHE_BLOCK_SIZE + 12];\t// Need the additional 12 bytes to align this packet\r\n} SFileIOResultPacket;\r\n\r\n// Stores the request\r\ntypedef struct FileIORequestEntry\r\n{\r\n\tSFileIORequest\t\t\t\tm_request;\r\n\tint\t\t\t\t\t\t\tm_request_id;\r\n} SFileIORequestEntry;\r\n\r\n#endif\t// __SYS_FILE_NGPS_FILEIO_H\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n"
  },
  {
    "path": "Code/Sys/File/ngps/FileIO/Makefile",
    "content": "ifeq ($(wildcard PathDefs),)\r\nPathDefs:\r\n\tiop-path-setup\r\n\tmake all\r\nelse\r\ninclude PathDefs\r\nendif\r\n\r\nTOPDIR = /usr/local/sce\r\nINCOPT = -I$(TOPDIR)/common/include -I$(TOPDIR)/iop/install/include\r\n\r\nCFLAGS  = $(INCOPT) -I. -Wall -G0 -g -D__LANGUAGE_C\r\nASFLAGS = $(INCOPT) -G0\r\nRM          = /bin/rm -f\r\n\r\nCOMPILE.s = $(CC) -xassembler-with-cpp $(ASFLAGS) $(CPPFLAGS) $(TARGET_MACH) -c\r\n\r\n#----------- customize section --------------\r\nPROGNAME = fileio\r\n\r\nOBJS     = start.o command.o\r\n#ILIBS\t= -ilb=$(TOP)lib/iop.ilb \r\nILIBS\t=\r\nLIBI\t= /usr/local/sce/iop/install/lib\r\n\r\n#----------- rules --------------\r\nall:\t$(PROGNAME).irx\r\n\r\nclean:\r\n\trm -f *.o $(PROGNAME).irx *.obj *.map\r\n\r\n$(PROGNAME).irx: $(OBJS)\r\n\t$(LINK.o)  -o $@ \\\r\n\t\t$(OBJS) -L../../../lib -L./ -L$(LIBI) -ilb=cdvdman.ilb\r\n\r\nstart.o:\tfileio.h fileio_iop.h\r\ncommand.o:\tfileio.h fileio_iop.h\r\n"
  },
  {
    "path": "Code/Sys/File/ngps/FileIO/PathDefs",
    "content": "AR\t = snarl.exe\r\nAS\t = ps2cc -iop\r\nCC\t = ps2cc -iop\r\nGCC\t = ps2cc -iop\r\nLD\t = ps2cc -iop\r\nNM\t = C:/usr/local/sce/iop/gcc/bin/iop-nm.exe\r\nSIZE\t = iop-size.exe\r\nSTRIP\t = C:/usr/local/sce/iop/gcc/bin/iop-strip.exe\r\nRANLIB\t = C:/usr/local/sce/iop/gcc/bin/iop-ranlib.exe\r\nOBJCOPY\t = C:/usr/local/sce/iop/gcc/bin/iop-objcopy.exe\r\nOBJDUMP\t = C:/usr/local/sce/iop/gcc/bin/iop-objdump.exe\r\nIFIXUP\t = iopfixup.exe\r\nILBGEN\t = C:/usr/local/sce/iop/gcc/bin/ioplibgen.exe\r\nILBLD\t = C:/usr/local/sce/iop/gcc/mipsel-scei-elfl/bin/ioplibld.exe\r\nILBDUMP\t = C:/usr/local/sce/iop/gcc/mipsel-scei-elfl/bin/ioplibdump.exe\r\nBIN2OBJ\t = bin2elf.exe\r\n"
  },
  {
    "path": "Code/Sys/File/ngps/FileIO/command.c",
    "content": "/* FileIO -- Converted from Sony samples -- Garrett Oct 2002 */\r\n\r\n#include <kernel.h>\r\n#include <libcdvd.h>\r\n#include <sys/types.h>\r\n#include <sys/file.h>\r\n#include <stdio.h>\r\n#include <string.h>\r\n#include <sif.h>\r\n#include <sifrpc.h>\r\n#include <sifcmd.h>\r\n#include <thread.h>\r\n#include \"fileio.h\"\r\n#include \"fileio_iop.h\"\r\n\r\n// ================================================================\r\n\r\n#define MAX(a,b)  (((a) > (b)) ? (a) : (b))\r\n#define MIN(a,b)  (((a) < (b)) ? (a) : (b))\r\n\r\n// FileIO prototypes\r\nstatic int FileIO_GetDescriptor(int memory_destination, int buffer_size);\r\nstatic int FileIO_FindFileHandleIndex(volatile unsigned int *p_file_handle_index);\r\n\r\nstatic void FileIO_Init(int priority, int buffer_size, short memory_destination, short init_cd_device);\r\nstatic void FileIO_Open(int sector_num, int file_size, int memory_destination, int buffer_size, int priority, int attributes);\r\nstatic void FileIO_HostOpen(char *p_filename, int memory_destination, int buffer_size, int priority, int attributes,\r\n\t\t\t\t\t\t\tFileIOHostOpen open_type, SFileIORequest *p_cont_request);\r\nstatic void FileIO_Close(volatile unsigned int *p_file_handle_index);\r\nstatic void FileIO_Read(SFileIORequest *p_request, volatile unsigned int *p_file_handle_index, void *p_buffer, int size, int non_aligned_start_bytes, int non_aligned_end_bytes);\r\nstatic void FileIO_Write(SFileIORequest *p_request, volatile unsigned int *p_file_handle_index, void *p_buffer, int size, int non_aligned_start_bytes, int non_aligned_end_bytes);\r\nstatic void FileIO_Seek(volatile unsigned int *p_file_handle_index, int offset, int origin);\r\nstatic void FileIO_Set(volatile unsigned int *p_file_handle_index, FileIOVariable variable, int value);\r\n\r\n// Debug info\r\n#define SHOW_FILEIO_INFO\t0\r\n\r\n#if SHOW_FILEIO_INFO\r\n#define ShowFileIOInfo(A...) Kprintf(##A)\r\n#else\r\n#define ShowFileIOInfo(A...) \r\n#endif\r\n\r\nunsigned int gThid = 0;\r\nunsigned int gSem = 0;\r\nunsigned int gCmdSem = 0;\r\n\r\n// Defaults\r\nint gDefaultPriority;\r\nint gDefaultBufferSize;\r\nint gDefaultMemoryDestination;\r\n\r\n// File handles and buffers\r\nSFileIOHandle\tgFileHandle[FILEIO_MAX_HANDLERS];\r\nunsigned char\tgFileBuffer[FILEIO_MAX_BUFFERS][FILEIO_BUFFER_SIZE];\r\nunsigned char *\tgFileBufferList[FILEIO_MAX_BUFFERS];\r\n\r\nint gFreeFileBufferIndex;\r\n\r\n// Device status var\r\nstatic SFileIODevice sFileIODevices[NUM_DEVICE_TYPES];\r\n\r\nstatic SFileIOResultPacket s_result_packet;\r\n\r\nstatic SRequestStatus s_cur_command_status;\r\n\r\nstatic void ServiceCurrentFileHandle(int resend);\r\nstatic int  StartCdRead(int start_sector, int num_sectors, void *p_buffer);\r\nstatic void SendNowaitResult();\r\n\r\nstatic int\tGetResultPacketSize(SFileIOResultPacket *p_packet);\r\n\r\nstatic void AppendTask(SFileIODevice *p_device, SFileIOTask *p_task);\r\nstatic void InsertTask(SFileIODevice *p_device, SFileIOTask *p_task);\r\nstatic void RemoveTask(SFileIODevice *p_device, SFileIOTask *p_task);\r\nstatic int  AppendContRequest(SFileIOTask *p_task);\r\n\r\n\r\n//\r\n// Callback\r\nstatic void cd_callback(int arg)\r\n{\r\n\tvoid *p_ee_addr = NULL, *p_iop_addr = NULL;\r\n\tint block_size = 0;\r\n\tSFileIODevice *p_device = &sFileIODevices[DEVICE_CD];\r\n\tSFileIOHandle *p_file = p_device->mp_file_handle;\r\n\tint resend = FALSE;\r\n\r\n\t// Lame hack to make sure we issued the sceCd call, not some legacy code\r\n\tif (!p_device->m_in_use)\r\n\t{\r\n\t\tShowFileIOInfo(\"Got CD callback even though we didn't issue a command\\n\");\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Wait for previous transfer to finish before we try to read any more (maybe we shouldn't do this in a callback)\r\n\tif (p_file->m_flags & FILEIO_HANDLE_PREV_DMA)\r\n\t{\r\n\t\twhile(sceSifDmaStat(p_file->m_last_dma_id) >= 0)\r\n\t\t\t;\r\n\t}\r\n\r\n\t// Clear out data transfer size\r\n\ts_result_packet.m_non_aligned_data_size = 0;\r\n\r\n\tswitch (p_file->m_cur_function)\r\n\t{\r\n\tcase FILEIO_FUNCTION_READ:\r\n\t\t// Check that we got the correct arg back.  Re-send command if not.\r\n\t\tif ((arg != SCECdFuncRead) && (arg != SCECdFuncSeek))\r\n\t\t{\r\n\t\t\tresend = TRUE;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// We probably won't set this for an IOP memory operation\r\n\t\ts_result_packet.m_byte_transfer = p_file->m_bytes_processing;\r\n\r\n\t\t// Figure out if we are done before calling ServiceCurrentFileHandle()\r\n\t\ts_result_packet.m_done = (p_file->m_bytes_to_process == 0);\r\n\t\ts_result_packet.m_header.opt = p_file->m_request_id;\r\n\t\ts_result_packet.m_return_value = p_file->m_return_value;\r\n\t\ts_result_packet.m_return_data = p_file->m_return_data;\r\n\r\n\t\t// Do we need to transfer to EE?\r\n\t\tif (p_file->m_flags & FILEIO_HANDLE_EE_MEMORY)\r\n\t\t{\r\n\t\t\tp_iop_addr = p_device->mp_buffer[p_device->m_buffer_index];\r\n\t\t\tp_device->m_buffer_index ^= 1;\r\n\r\n\t\t\tp_ee_addr = p_file->mp_dest_buffer;\r\n\t\t\tblock_size = p_file->m_bytes_processing;\r\n\r\n\t\t\t// Check non-alignment\r\n\t\t\tif (p_file->m_non_aligned_start_bytes)\r\n\t\t\t{\r\n\t\t\t\ts_result_packet.m_non_aligned_data_size = p_file->m_non_aligned_start_bytes;\r\n\t\t\t\tmemcpy(s_result_packet.m_non_aligned_data, p_iop_addr, p_file->m_non_aligned_start_bytes);\r\n\r\n\t\t\t\tp_file->m_non_aligned_start_bytes = 0;\r\n\t\t\t\t//if (s_result_packet.m_done && p_file->m_non_aligned_end_bytes)\r\n\t\t\t\t//{\r\n\t\t\t\t//\tKprintf(\"Have both non-aligned data at beginning and end of buffer\\n\");\r\n\t\t\t\t//}\r\n\t\t\t}\r\n\t\t\telse if (s_result_packet.m_done && p_file->m_non_aligned_end_bytes)\r\n\t\t\t{\r\n\t\t\t\ts_result_packet.m_non_aligned_data_size = p_file->m_non_aligned_end_bytes;\r\n\t\t\t\tmemcpy(s_result_packet.m_non_aligned_data, p_iop_addr + (block_size - p_file->m_non_aligned_end_bytes), p_file->m_non_aligned_end_bytes);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Advance dest pointer\r\n\t\tp_file->mp_dest_buffer = p_file->mp_dest_buffer + block_size;\r\n\r\n\t\tbreak;\r\n\r\n\tcase FILEIO_FUNCTION_OPEN:\r\n\tcase FILEIO_FUNCTION_SEEK:\r\n\t\ts_result_packet.m_byte_transfer = 0;\r\n\t\ts_result_packet.m_done = TRUE;\r\n\t\ts_result_packet.m_return_value = p_file->m_return_value;\r\n\t\ts_result_packet.m_return_data = p_file->m_return_data;\r\n\t\ts_result_packet.m_header.opt = s_cur_command_status.m_request_id;\r\n\t\tp_file->m_cur_function = FILEIO_FUNCTION_IDLE;\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\t// Something went wrong here\r\n\t\tShowFileIOInfo(\"Got cd callback from an unexpected function: %d\\n\", p_file->m_cur_function);\r\n\t\ts_result_packet.m_byte_transfer = 0;\r\n\t\ts_result_packet.m_done = TRUE;\r\n\t\ts_result_packet.m_return_value = -1;\r\n\t\ts_result_packet.m_return_data = -1;\r\n\t\ts_result_packet.m_header.opt = s_cur_command_status.m_request_id;\r\n\t\tbreak;\r\n\r\n\t}\r\n\r\n\tif (!resend)\r\n\t{\r\n\t\tp_file->m_flags |= FILEIO_HANDLE_PREV_DMA;\r\n\t\tp_file->m_last_dma_id = isceSifSendCmd(FILEIO_RESULT_COMMAND, &s_result_packet, GetResultPacketSize(&s_result_packet), p_iop_addr, p_ee_addr, block_size);\r\n\t}\r\n\tShowFileIOInfo(\"FileIO cd callback: sent result %d back from %x to %x of size %d with data %x %x %x %x and arg %x error %d resend %d\\n\", s_result_packet.m_return_value, p_iop_addr, p_ee_addr, block_size,\r\n\t\t\t\t   ((unsigned int *) p_iop_addr)[0],\r\n\t\t\t\t   ((unsigned int *) p_iop_addr)[1],\r\n\t\t\t\t   ((unsigned int *) p_iop_addr)[2],\r\n\t\t\t\t   ((unsigned int *) p_iop_addr)[3],\r\n\t\t\t\t   arg, sceCdGetError(), resend );\r\n\r\n\t// Check to see if we need to send out more CD commands\r\n\tServiceCurrentFileHandle(resend);\r\n\r\n\t// Wake up the dispatch thread\r\n\tiSignalSema(gCmdSem);\r\n}\r\n\r\n// Can be called from both from outside and within a CD callback\r\nstatic void ServiceCurrentFileHandle(int resend)\r\n{\r\n\tint sectors_to_read;\r\n\tSFileIODevice *p_device = &sFileIODevices[DEVICE_CD];\r\n\tSFileIOHandle *p_file = p_device->mp_file_handle;\r\n\r\n\t// Read parameters: need to save in case of resend\r\n\tstatic int cur_sector;\r\n\tstatic int num_sectors;\r\n\tstatic void *p_local_buffer;\r\n\r\n\tif (resend)\r\n\t{\r\n\t\tShowFileIOInfo(\"ServiceCurrentFileHandle %x: Resending read of %d sectors starting at %d to %x with %d bytes left\\n\", p_file, num_sectors, cur_sector, p_local_buffer, p_file->m_bytes_to_process);\r\n\r\n\t\tStartCdRead(cur_sector, num_sectors, p_local_buffer);\r\n\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Right now, this only does something with reads\r\n\tif (p_file->m_cur_function != FILEIO_FUNCTION_READ)\r\n\t{\r\n\t\t// We're done\r\n\t\tp_file->m_flags &= ~FILEIO_HANDLE_BUSY;\r\n\t\tp_device->m_in_use = FALSE;\r\n\r\n\t\treturn;\r\n\t}\r\n\r\n\tsectors_to_read = (p_file->m_bytes_to_process + SECTOR_SIZE - 1) / SECTOR_SIZE;\r\n\r\n\t// Check if we need to seek first\r\n\tif (p_file->m_cur_sector != p_device->m_cur_sector)\r\n\t{\r\n\t\tp_device->m_cur_sector = p_file->m_cur_sector;\r\n\t\tp_device->m_cur_position = p_file->m_cur_position;\r\n\r\n\t\t// We don't need to seek since the read does it for us.\r\n\t\t//sceCdSeek(p_file->m_cur_sector);\r\n\t\t//ShowFileIOInfo(\"ServiceCurrentFileHandle %x: Seeking to sector %d\\n\", p_file, p_file->m_cur_sector);\r\n\t\t//return;\r\n\t}\r\n\r\n\tif (sectors_to_read)\r\n\t{\r\n\t\tcur_sector = p_file->m_cur_sector;\r\n\r\n\t\tif (p_file->m_flags & FILEIO_HANDLE_EE_MEMORY)\r\n\t\t{\r\n\t\t\tp_local_buffer = p_device->mp_buffer[p_device->m_buffer_index];\r\n\t\t\tnum_sectors = MIN(FILEIO_BUFFER_SECTORS, sectors_to_read);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Note that we don't handle the last sector properly, which most likely won't be\r\n\t\t\t// filled (and would overwrite the output buffer).\r\n\t\t\tp_local_buffer = p_file->mp_dest_buffer;\r\n\t\t\tnum_sectors = sectors_to_read;\r\n\t\t}\r\n\r\n\t\t// Advance the file stats before the read call, since, in theory, the read could call the\r\n\t\t// callback immediately\r\n\t\tp_file->m_cur_sector += num_sectors;\r\n\t\tp_file->m_cur_position += num_sectors * SECTOR_SIZE;\r\n\t\tp_file->m_bytes_processing = MIN(num_sectors * SECTOR_SIZE, p_file->m_bytes_to_process);\r\n\t\tp_file->m_bytes_to_process = MAX(p_file->m_bytes_to_process - p_file->m_bytes_processing, 0);\r\n\r\n\t\tShowFileIOInfo(\"ServiceCurrentFileHandle %x: Reading %d sectors starting at %d to %x with %d bytes left\\n\", p_file, num_sectors, cur_sector, p_local_buffer, p_file->m_bytes_to_process);\r\n\t\tp_device->m_cur_sector = p_file->m_cur_sector;\r\n\t\tp_device->m_cur_position = p_file->m_cur_position;\r\n\r\n\t\tStartCdRead(cur_sector, num_sectors, p_local_buffer);\r\n\t} else {\r\n\t\t// We're done\r\n\t\tp_file->m_flags &= ~FILEIO_HANDLE_BUSY;\r\n\t\tp_device->m_in_use = FALSE;\r\n\r\n\t\t// Send message to EE that we are done\r\n\t}\r\n}\r\n\r\n#define NUM_WAIT_CLICKS 1000\r\n\r\nstatic int StartCdRead(int start_sector, int num_sectors, void *p_buffer)\r\n{\r\n\tint result;\r\n\tsceCdRMode mode;\r\n\tint retries = 0;\r\n\tstatic int wait_read = 0;\r\n\r\n\tif (wait_read)\r\n\t{\r\n\t\tShowFileIOInfo(\"Got callback while waiting to resend\\n\");\r\n\t\treturn 0;\r\n\t}\r\n\r\n\twait_read = 1;\r\n\r\n\tmode.trycount = 255;\r\n\tmode.spindlctrl = SCECdSpinNom;\r\n\tmode.datapattern = SCECdSecS2048;\r\n\tmode.pad = 0;\r\n\r\n\tdo\r\n\t{\r\n\t\t//if (sceCdSync( 1 ))\r\n\t\t//\tShowFileIOInfo(\"Sync isn't ready before the CD read\\n\");\r\n\r\n\t\tresult = sceCdRead(start_sector, num_sectors, p_buffer, &mode);\r\n\r\n\t\tif (result == 0)\r\n\t\t{\r\n\t\t\tint i, j = 0;\r\n\r\n\t\t\tKprintf(\"sceCdRead() didn't start.  Returned %d with error %d.  Retrying...\\n\", result, sceCdGetError());\r\n\r\n\t\t\tsceCdSync( 0 );\r\n\r\n\t\t\tdo\r\n\t\t\t{\r\n\t\t\t\tfor ( i = 0; i < NUM_WAIT_CLICKS; i++ )\r\n\t\t\t\t\t;\r\n\t\t\t\tif ( j++ > NUM_WAIT_CLICKS )\r\n\t\t\t\t{\r\n\t\t\t\t\tj = 0;\r\n\t\t\t\t}\r\n\t\t\t} while ( j != 0 );\r\n\r\n            while(sceCdDiskReady(0)!=SCECdComplete)\r\n\t\t\t\t;\r\n\t\t\t//sceCdSeek(0);\r\n\t\t\t//sceCdSync( 0 );\r\n\t\t\t//result = 1;\r\n\t\t\tretries++;\r\n\t\t}\r\n\t} while ((result == 0) && (retries <= 15));\t\t// Need to eventually abort this if retries get too high\r\n\r\n\twait_read = 0;\r\n\r\n\treturn result;\r\n}\r\n\r\n// Returns packet size of result, rounded up to a 16-byte chunk\r\nstatic int GetResultPacketSize(SFileIOResultPacket *p_packet)\r\n{\r\n\tunsigned int base_size = ((unsigned int) &(p_packet->m_non_aligned_data[0]) - (unsigned int) p_packet);\r\n\r\n\treturn ((base_size + p_packet->m_non_aligned_data_size) + 0xf) & ~0xf;\r\n}\r\n\r\n////////////////////////////////\r\n// Tries to find the real file handle index from the open request ID\r\nstatic int FileIO_FindFileHandleIndex(volatile unsigned int *p_file_handle_index)\r\n{\r\n\tint fd;\r\n\tint open_request_id = (int) (*p_file_handle_index & ~FILEIO_TEMP_HANDLE_FLAG);\r\n\r\n\tfor (fd = 0; fd < FILEIO_MAX_HANDLERS; fd++)\r\n\t{\r\n\t\tif (gFileHandle[fd].m_open_request_id == open_request_id)\r\n\t\t{\r\n\t\t\tShowFileIOInfo(\"FileIO: converting open request id %d to file handle index %d\\n\", open_request_id, fd);\r\n\t\t\t*p_file_handle_index = fd;\r\n\t\t\treturn TRUE;\r\n\t\t}\r\n\t}\r\n\r\n\tShowFileIOInfo(\"FileIO: can't convert open request id %d to file handle index\\n\", open_request_id);\r\n\treturn FALSE;\r\n}\r\n\r\n////////////////////////////////\r\n// Init\r\nstatic void FileIO_Init(int priority, int buffer_size, short memory_destination, short init_cd_device)\r\n{\r\n\tint detected_disk_type;\r\n\tint i;\r\n\r\n\tprintf(\"Starting FileIO_Init\\n\");\r\n\r\n\tsFileIODevices[DEVICE_CD].m_in_use = FALSE;\r\n\tsFileIODevices[DEVICE_CD].mp_file_handle = NULL;\r\n\r\n\t// Init drive\r\n\tif (init_cd_device)\r\n\t{\r\n#if 0\t\t// Doesn't seem to be necessary, since we already do this on the EE\r\n\t\tsceCdInit(SCECdINIT);\r\n\t\tsceCdMmode(SCECdDVD);\r\n\r\n\t\t// find the disk type, this might be different from what we intialized to \r\n\t\tprintf(\"FileIO: sceCdGetDiskType   \");\r\n\t\tdetected_disk_type= sceCdGetDiskType();\r\n\t\tswitch(detected_disk_type)\r\n\t\t{\r\n\t\t\tcase SCECdIllgalMedia:\r\n\t\t\tprintf(\"Disk Type= IllgalMedia\\n\"); break;\r\n\t\t\tcase SCECdPS2DVD:\r\n\t\t\tprintf(\"Disk Type= PlayStation2 DVD\\n\"); break;\r\n\t\t\tcase SCECdPS2CD:\r\n\t\t\tprintf(\"Disk Type= PlayStation2 CD\\n\"); break;\r\n\t\t\tcase SCECdPS2CDDA:\r\n\t\t\tprintf(\"Disk Type= PlayStation2 CD with CDDA\\n\"); break;\r\n\t\t\tcase SCECdPSCD:\r\n\t\t\tprintf(\"Disk Type= PlayStation CD\\n\"); break;\r\n\t\t\tcase SCECdPSCDDA:\r\n\t\t\tprintf(\"Disk Type= PlayStation CD with CDDA\\n\"); break;\r\n\t\t\tcase SCECdDVDV:\r\n\t\t\tprintf(\"Disk Type= DVD video\\n\"); break;\r\n\t\t\tcase SCECdCDDA:\r\n\t\t\tprintf(\"Disk Type= CD-DA\\n\"); break;\r\n\t\t\tcase SCECdDETCT:\r\n\t\t\tprintf(\"Working\\n\"); break;\r\n\t\t\tcase SCECdNODISC: \r\n\t\t\tprintf(\"Disk Type= No Disc\\n\"); break;\r\n\t\t\tdefault:\r\n\t\t\tprintf(\"Disk Type= OTHER DISK\\n\"); break;\r\n\t\t}\r\n\r\n\t\t// If disk type has changed to a CD, then need to re-initialize it\t\t\t\t\t\t\t   \r\n\t\tif (detected_disk_type == SCECdPS2CD)\r\n\t\t{\r\n\t\t\t#if __DVD_ONLY__\r\n\t\t\tprintf( \"*** ERROR - CD Detected, needs DVD.\\n\" );\r\n\t\t\t#else\r\n\t\t\tprintf( \"reinitializing for Ps2CD\\n\" );\r\n\t\t\tsceCdMmode(SCECdCD);\r\n\t\t\tprintf( \"done reinitializing\\n\" );\r\n\t\t\t#endif\t\t\r\n\t\t}\r\n#endif\r\n\r\n\t\t// Set up callback\r\n\t\tsceCdCallback(cd_callback);\r\n\t}\r\n\r\n\t// Set default parameters\r\n\tgDefaultPriority\t\t\t= priority;\r\n\tgDefaultBufferSize\t\t\t= buffer_size;\r\n\tgDefaultMemoryDestination\t= memory_destination;\r\n\r\n\t// Init the file handles and buffers\r\n\tfor (i = 0; i < FILEIO_MAX_HANDLERS; i++)\r\n\t{\r\n\t\tgFileHandle[i].m_flags\t\t\t= 0;\t\t// Neither busy nor reserved\r\n\t\t//gFileHandle[i].mp_buffer[0]\t\t= NULL;\r\n\t\t//gFileHandle[i].mp_buffer[1]\t\t= NULL;\r\n\t\t//gFileHandle[i].m_buffer_index  \t= -1;\r\n\t\tgFileHandle[i].mp_dest_buffer\t= NULL;\r\n\t\tgFileHandle[i].m_device_type\t= DEVICE_UNKNOWN;\r\n\t\tgFileHandle[i].m_buffer_size\t= buffer_size;\r\n\t\tgFileHandle[i].m_host_fd\t\t= -1;\r\n\t\tgFileHandle[i].m_priority\t\t= priority;\r\n\t\tgFileHandle[i].m_stream\t\t\t= FALSE;\r\n\t\tgFileHandle[i].m_start_sector\t= 0;\r\n\t\tgFileHandle[i].m_cur_sector\t\t= 0;\r\n\t\tgFileHandle[i].m_cur_position\t= 0;\r\n\t\tgFileHandle[i].m_file_size\t\t= 0;\r\n\t\tgFileHandle[i].m_open_request_id= -1;\r\n\t}\r\n\r\n\tfor (i = 0; i < FILEIO_MAX_BUFFERS; i++)\r\n\t{\r\n\t\tgFileBufferList[i] = gFileBuffer[i];\r\n\t}\r\n\r\n\tgFreeFileBufferIndex = 0;\r\n\r\n\t// Allocate device buffers\r\n\tfor (i = 0; i < DEVICE_UNKNOWN; i++)\r\n\t{\r\n\t\tif ((gFreeFileBufferIndex + 1) < FILEIO_MAX_BUFFERS)\r\n\t\t{\r\n\t\t\t// Use buffer size in the future\r\n\t\t\tsFileIODevices[i].mp_buffer[0] = gFileBufferList[gFreeFileBufferIndex++];\r\n\t\t\tsFileIODevices[i].mp_buffer[1] = gFileBufferList[gFreeFileBufferIndex++];\r\n\t\t\tsFileIODevices[i].m_buffer_index = 0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Can't allocate\r\n\t\t\tprintf(\"Out of fileio memory buffers\\n\");\r\n\t\t\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\t\t\ts_cur_command_status.m_return_value = -1;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tprintf(\"Done FileIO_Init\\n\");\r\n\r\n\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\ts_cur_command_status.m_return_value = TRUE;\r\n\treturn;\r\n}\r\n\r\n////////////////////////////////\r\n// GetDescriptor\r\nstatic int FileIO_GetDescriptor(int memory_destination, int buffer_size)\r\n{\r\n\tint i;\r\n\r\n\tfor (i = 0; i < FILEIO_MAX_HANDLERS; i++)\r\n\t{\r\n\t\tif (!(gFileHandle[i].m_flags & FILEIO_HANDLE_RESERVED))\r\n\t\t{\r\n\t\t\tgFileHandle[i].m_buffer_size = buffer_size;\r\n\r\n\t\t\tif (memory_destination == MEM_EE)\r\n\t\t\t{\r\n\t\t\t\tgFileHandle[i].m_flags |= FILEIO_HANDLE_EE_MEMORY;\r\n#if 0\r\n\t\t\t\tif ((gFreeFileBufferIndex + 1) < FILEIO_MAX_BUFFERS)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Use buffer size in the future\r\n\t\t\t\t\tgFileHandle[i].mp_buffer[0] = gFileBufferList[gFreeFileBufferIndex++];\r\n\t\t\t\t\tgFileHandle[i].mp_buffer[1] = gFileBufferList[gFreeFileBufferIndex++];\r\n\t\t\t\t\tgFileHandle[i].m_buffer_index = 0;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Can't open\r\n\t\t\t\t\tprintf(\"Out of fileio memory buffers\\n\");\r\n\t\t\t\t\treturn -1;\r\n\t\t\t\t}\r\n#endif\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tgFileHandle[i].m_flags &= ~FILEIO_HANDLE_EE_MEMORY;\r\n#if 0\r\n\t\t\t\tgFileHandle[i].mp_buffer[0] = NULL;\r\n\t\t\t\tgFileHandle[i].mp_buffer[1] = NULL;\r\n\t\t\t\tgFileHandle[i].m_buffer_index = -1;\r\n#endif\r\n\t\t\t}\r\n\r\n\t\t\tgFileHandle[i].m_flags |= FILEIO_HANDLE_RESERVED;\r\n\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\r\n\t// Couldn't find a free descriptor\r\n\tprintf(\"Out of fileio file descriptors\\n\");\r\n\treturn -1;\r\n\r\n}\r\n\r\n////////////////////////////////\r\n// Open\r\nstatic void FileIO_Open(int sector_num, int file_size, int memory_destination, int buffer_size, int priority, int attributes)\r\n{\r\n\tint fd = FileIO_GetDescriptor(memory_destination, buffer_size);\r\n\r\n\tif (fd >= 0)\r\n\t{\r\n\t\t// Init the handle itself\r\n\t\tgFileHandle[fd].m_device_type = DEVICE_CD;\r\n\t\tgFileHandle[fd].mp_dest_buffer = NULL;\r\n\t\tgFileHandle[fd].m_host_fd = -1;\r\n\t\tgFileHandle[fd].m_priority = priority;\r\n\t\tgFileHandle[fd].m_stream = FALSE;\r\n\t\tgFileHandle[fd].m_start_sector = sector_num;\r\n\t\tgFileHandle[fd].m_cur_sector = sector_num;\r\n\t\tgFileHandle[fd].m_cur_position = 0;\r\n\t\tgFileHandle[fd].m_file_size = file_size;\r\n\t\tgFileHandle[fd].m_open_request_id= s_cur_command_status.m_request_id;\r\n\t\tgFileHandle[fd].mp_blocked_request = NULL;\r\n\t\tgFileHandle[fd].m_flags &= ~FILEIO_HANDLE_BUSY;\r\n\t\tgFileHandle[fd].m_cur_function = FILEIO_FUNCTION_IDLE;\r\n\r\n\t\t// Don't do seek, just return\r\n\t\tgFileHandle[fd].m_return_value = fd;\r\n\t\tgFileHandle[fd].m_return_data = file_size;\r\n\t\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\t\ts_cur_command_status.mp_file_handle = &(gFileHandle[fd]);\r\n\t\ts_cur_command_status.m_return_value = fd;\r\n\t\ts_cur_command_status.m_return_data = file_size;\r\n\t\tShowFileIOInfo(\"Opened file using handle %d\\n\", fd);\r\n\t} else {\r\n\t\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\t\ts_cur_command_status.m_return_value = -1;\r\n\t\treturn;\r\n\t}\r\n}\r\n\r\n////////////////////////////////\r\n// HostOpen\r\nstatic void FileIO_HostOpen(char *p_filename, int memory_destination, int buffer_size, int priority, int attributes,\r\n\t\t\t\t\t\t\tFileIOHostOpen open_type, SFileIORequest *p_cont_request)\r\n{\r\n\tint fd, host_fd;\r\n\tchar full_filename[FILEIO_MAX_FILENAME_SIZE * 2];\r\n\r\n\tstrcpy(full_filename, p_filename);\r\n\tif (open_type == FILEIO_HOSTOPEN_EXTEND_NAME)\r\n\t{\r\n\t\tif (p_cont_request)\r\n\t\t{\r\n\t\t\tstrcat(full_filename, p_cont_request->m_param.m_open.m_file.m_filename);\r\n\t\t\tShowFileIOInfo(\"FileIO HostOpen: opening extended filename %s\\n\", full_filename);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tShowFileIOInfo(\"FileIO HostOpen: waiting for rest of filename for %s\\n\", p_filename);\r\n\t\t\ts_cur_command_status.m_request_state = REQUEST_OPEN;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\thost_fd = open(full_filename, O_RDONLY);\r\n\tif (host_fd >= 0)\r\n\t{\r\n\t\t// Find file size\r\n\t\tint file_size = lseek(host_fd, 0, SEEK_END);\r\n\t\tlseek(host_fd, 0, SEEK_SET);\r\n\r\n\t\tfd = FileIO_GetDescriptor(memory_destination, buffer_size);\r\n\r\n\t\tif (fd >= 0)\r\n\t\t{\r\n\t\t\t// Init the handle itself\r\n\t\t\tgFileHandle[fd].m_device_type = DEVICE_HOST;\r\n\t\t\tgFileHandle[fd].mp_dest_buffer = NULL;\r\n\t\t\tgFileHandle[fd].m_priority = priority;\r\n\t\t\tgFileHandle[fd].m_stream = FALSE;\r\n\t\t\tgFileHandle[fd].m_start_sector = -1;\r\n\t\t\tgFileHandle[fd].m_cur_sector = -1;\r\n\t\t\tgFileHandle[fd].m_cur_position = 0;\r\n\t\t\tgFileHandle[fd].m_file_size = file_size;\r\n\t\t\tgFileHandle[fd].m_open_request_id= s_cur_command_status.m_request_id;\r\n\t\t\tgFileHandle[fd].mp_blocked_request = NULL;\r\n\t\t\tgFileHandle[fd].m_flags &= ~FILEIO_HANDLE_BUSY;\r\n\t\t\tgFileHandle[fd].m_cur_function = FILEIO_FUNCTION_IDLE;\r\n\r\n\t\t\t// Do a open\r\n\t\t\tgFileHandle[fd].m_host_fd = host_fd;\r\n\r\n\t\t\tgFileHandle[fd].m_return_value = fd;\r\n\t\t\tgFileHandle[fd].m_return_data = file_size;\r\n\r\n\t\t\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\t\t\ts_cur_command_status.mp_file_handle = &(gFileHandle[fd]);\r\n\t\t\ts_cur_command_status.m_return_value = fd;\r\n\t\t\ts_cur_command_status.m_return_data = file_size;\r\n\t\t\treturn;\r\n\t\t} else {\r\n\t\t\tprintf(\"Can't get free descriptor for host open of %s\\n\", full_filename);\r\n\t\t\tclose(host_fd);\r\n\t\t}\r\n\t} else {\r\n\t\tprintf(\"Can't open file %s on host\\n\", full_filename);\r\n\t}\r\n\r\n\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\ts_cur_command_status.m_return_value = -1;\r\n\treturn;\r\n}\r\n\r\n////////////////////////////////\r\n// Close\r\nstatic void FileIO_Close(volatile unsigned int *p_file_handle_index)\r\n{\r\n\tSFileIOHandle *p_file;\r\n\t//int i, j;\r\n\r\n\t// See if we have the correct index, and if we can't get it, return\r\n\tif ((*p_file_handle_index & FILEIO_TEMP_HANDLE_FLAG) && !FileIO_FindFileHandleIndex(p_file_handle_index))\r\n\t{\r\n\t\ts_cur_command_status.m_request_state = REQUEST_OPEN;\r\n\t\treturn;\r\n\t}\r\n\r\n\tp_file = &(gFileHandle[*p_file_handle_index]);\r\n\r\n\tif (p_file->m_flags & FILEIO_HANDLE_RESERVED)\r\n\t{\r\n\t\ts_cur_command_status.mp_file_handle = p_file;\r\n\r\n\t\t// Can't close if we're busy\r\n\t\tif (p_file->m_flags & FILEIO_HANDLE_BUSY)\r\n\t\t{\r\n\t\t\ts_cur_command_status.m_request_state = REQUEST_OPEN;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Check if a host handle\r\n\t\tif (p_file->m_host_fd >= 0)\r\n\t\t{\r\n\t\t\tclose(p_file->m_host_fd);\r\n\t\t}\r\n\r\n#if 0\r\n\t\t// Check if buffer needs freeing\r\n\t\tif (p_file->mp_buffer[0])\r\n\t\t{\r\n\t\t\tfor (i = 0; i < FILEIO_MAX_BUFFERS; i++)\r\n\t\t\t{\r\n\t\t\t\tfor (j = 0; j < 2; j++)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (p_file->mp_buffer[j] == gFileBufferList[i])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Found it, exchange it with last used buffer\r\n\t\t\t\t\t\tgFileBufferList[i] = gFileBufferList[--gFreeFileBufferIndex];\r\n\t\t\t\t\t\tgFileBufferList[gFreeFileBufferIndex] = p_file->mp_buffer[j];\r\n\t\t\t\t\t\tp_file->mp_buffer[j] = NULL;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tp_file->m_buffer_index = -1;\r\n\t\t}\r\n#endif\r\n\r\n\t\tp_file->m_flags &= ~FILEIO_HANDLE_RESERVED;\r\n\r\n\t\tShowFileIOInfo(\"CLOSE: handle %d open and not busy\\n\", *p_file_handle_index);\r\n\t\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\t\ts_cur_command_status.m_return_value = TRUE;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Handle wasn't open\r\n\tShowFileIOInfo(\"CLOSE: handle %d not open\\n\", *p_file_handle_index);\r\n\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\ts_cur_command_status.m_return_value = FALSE;\r\n\treturn;\r\n}\r\n\r\n////////////////////////////////\r\n// Read\r\nstatic void FileIO_Read(SFileIORequest *p_request, volatile unsigned int *p_file_handle_index, void *p_buffer, int size, int non_aligned_start_bytes, int non_aligned_end_bytes)\r\n{\r\n\tSFileIOHandle *p_file;\r\n\tint host_read;\r\n\tint bytes_to_read;\r\n\r\n\t// See if we have the correct index, and if we can't get it, return\r\n\tif ((*p_file_handle_index & FILEIO_TEMP_HANDLE_FLAG) && !FileIO_FindFileHandleIndex(p_file_handle_index))\r\n\t{\r\n\t\ts_cur_command_status.m_request_state = REQUEST_OPEN;\r\n\t\treturn;\r\n\t}\r\n\r\n\tp_file = &(gFileHandle[*p_file_handle_index]);\r\n\thost_read = (p_file->m_host_fd >= 0);\r\n\r\n\ts_cur_command_status.mp_file_handle = p_file;\r\n\r\n\t// Can't add additional read if we're already busy\r\n\tif ((p_file->m_flags & FILEIO_HANDLE_BUSY) && !(p_file->mp_blocked_request && (p_file->mp_blocked_request == p_request)))\r\n\t{\r\n\t\ts_cur_command_status.m_request_state = REQUEST_OPEN;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Check to make sure device is free\r\n\tif (host_read)\r\n\t{\r\n\t\t// Nothing to check for now\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (sFileIODevices[DEVICE_CD].m_in_use)\r\n\t\t{\r\n\t\t\t// Mark file handle as blocked\r\n\t\t\tp_file->mp_blocked_request = p_request;\r\n\t\t\tp_file->m_flags |= FILEIO_HANDLE_BUSY;\r\n\r\n\t\t\ts_cur_command_status.m_request_state = REQUEST_OPEN;\r\n\t\t\treturn;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Clear blocked status\r\n\t\t\tp_file->mp_blocked_request = NULL;\r\n\t\t\tp_file->m_flags &= ~FILEIO_HANDLE_BUSY;\r\n\t\t}\r\n\t}\r\n\r\n\t// We won't support non sector aligned reads now\r\n\tif (!host_read && (p_file->m_cur_position & (SECTOR_SIZE - 1)))\r\n\t{\r\n\t\tprintf(\"Can't read from position %d because it isn't on a sector boundary\\n\", p_file->m_cur_position);\r\n\t\tp_file->m_cur_function = FILEIO_FUNCTION_IDLE;\r\n\t\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\t\ts_cur_command_status.m_return_value = -1;\r\n\t\treturn;\r\n\t}\r\n\r\n\tp_file->m_bytes_to_process = MIN(size, p_file->m_file_size - p_file->m_cur_position);\r\n\tp_file->m_bytes_processing = 0;\r\n\tp_file->m_non_aligned_start_bytes = non_aligned_start_bytes;\r\n\tp_file->m_non_aligned_end_bytes = non_aligned_end_bytes;\r\n\tp_file->m_request_id = s_cur_command_status.m_request_id;\r\n\r\n\t// Set destination buffer (EE or IOP address) and size\r\n\tp_file->mp_dest_buffer = p_buffer;\r\n\tbytes_to_read = p_file->m_bytes_to_process;\r\n\r\n\t// Do the actual read\r\n\tif (host_read)\r\n\t{\r\n\t\tSFileIODevice *p_device = &sFileIODevices[DEVICE_HOST];\r\n\r\n\t\t// We should really be looking for the old one and making sure it is done\r\n\t\tp_file->m_flags &= ~FILEIO_HANDLE_PREV_DMA;\r\n\r\n\t\t// Just do the read here until we set up a separate thread\r\n\t\twhile (p_file->m_bytes_to_process)\r\n\t\t{\r\n\t\t\tvoid *p_ee_addr = NULL, *p_iop_addr = NULL;\r\n\t\t\tint block_size = 0;\r\n\t\t\tint num_bytes;\r\n\t\t\tvoid *p_local_buffer;\r\n\r\n\t\t\tif (p_file->m_flags & FILEIO_HANDLE_EE_MEMORY)\r\n\t\t\t{\r\n\t\t\t\tp_local_buffer = p_device->mp_buffer[p_device->m_buffer_index];\r\n\t\t\t\tnum_bytes = MIN(FILEIO_BUFFER_SIZE, p_file->m_bytes_to_process);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_local_buffer = p_file->mp_dest_buffer;\r\n\t\t\t\tnum_bytes = p_file->m_bytes_to_process;\r\n\t\t\t}\r\n\r\n\t\t\t// Advance the file stats before the read call, since, in theory, the read could call the\r\n\t\t\t// callback immediately\r\n\t\t\tp_file->m_cur_position += num_bytes;\r\n\t\t\tp_file->m_bytes_processing = num_bytes;\r\n\t\t\tp_file->m_bytes_to_process = p_file->m_bytes_to_process - p_file->m_bytes_processing;\r\n\r\n\t\t\tShowFileIOInfo(\"Host read %x: Reading %d bytes to %x with %d bytes left\\n\", p_file, num_bytes, p_local_buffer, p_file->m_bytes_to_process);\r\n\t\t\tread(p_file->m_host_fd, p_local_buffer, num_bytes);\r\n\r\n\t\t\t// Wait for previous transfer to finish before we try to read any more (maybe we shouldn't do this in a callback)\r\n\t\t\tif (p_file->m_flags & FILEIO_HANDLE_PREV_DMA)\r\n\t\t\t{\r\n\t\t\t\twhile(sceSifDmaStat(p_file->m_last_dma_id) >= 0)\r\n\t\t\t\t\t;\r\n\t\t\t}\r\n\r\n\t\t\t// We probably won't set this for an IOP memory operation\r\n\t\t\ts_result_packet.m_byte_transfer = p_file->m_bytes_processing;\r\n\r\n\t\t\t// Figure out if we are done before calling ServiceCurrentFileHandle()\r\n\t\t\ts_result_packet.m_done = (p_file->m_bytes_to_process == 0);\r\n\t\t\ts_result_packet.m_header.opt = p_file->m_request_id;\r\n\t\t\ts_result_packet.m_return_value = bytes_to_read;\r\n\t\t\ts_result_packet.m_non_aligned_data_size = 0;\r\n\r\n\t\t\t// Do we need to transfer to EE?\r\n\t\t\tif (p_file->m_flags & FILEIO_HANDLE_EE_MEMORY)\r\n\t\t\t{\r\n\t\t\t\tp_iop_addr = p_local_buffer;\r\n\t\t\t\tp_device->m_buffer_index ^= 1;\r\n\r\n\t\t\t\tp_ee_addr = p_file->mp_dest_buffer;\r\n\t\t\t\tblock_size = p_file->m_bytes_processing;\r\n\r\n\t\t\t\t// Check non-alignment\r\n\t\t\t\tif (p_file->m_non_aligned_start_bytes)\r\n\t\t\t\t{\r\n\t\t\t\t\ts_result_packet.m_non_aligned_data_size = p_file->m_non_aligned_start_bytes;\r\n\t\t\t\t\tmemcpy(s_result_packet.m_non_aligned_data, p_iop_addr, p_file->m_non_aligned_start_bytes);\r\n\r\n\t\t\t\t\tp_file->m_non_aligned_start_bytes = 0;\r\n\t\t\t\t}\r\n\t\t\t\telse if (s_result_packet.m_done && p_file->m_non_aligned_end_bytes)\r\n\t\t\t\t{\r\n\t\t\t\t\ts_result_packet.m_non_aligned_data_size = p_file->m_non_aligned_end_bytes;\r\n\t\t\t\t\tmemcpy(s_result_packet.m_non_aligned_data, p_iop_addr + (block_size - p_file->m_non_aligned_end_bytes), p_file->m_non_aligned_end_bytes);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Advance dest pointer\r\n\t\t\tp_file->mp_dest_buffer = p_file->mp_dest_buffer + block_size;\r\n\r\n\t\t\tp_file->m_flags |= FILEIO_HANDLE_PREV_DMA;\r\n\t\t\tp_file->m_last_dma_id = sceSifSendCmd(FILEIO_RESULT_COMMAND, &s_result_packet, GetResultPacketSize(&s_result_packet), p_iop_addr, p_ee_addr, block_size);\r\n\t\t\tShowFileIOInfo(\"FileIO host read: sent result %d back from %x to %x of size %d\\n\", s_result_packet.m_return_value, p_iop_addr, p_ee_addr, block_size);\r\n\t\t}\r\n\r\n\t\ts_cur_command_status.m_request_state = REQUEST_PROCESSING;\t\t// Don't want to send another result packet\r\n\t\tp_file->m_return_value = bytes_to_read;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// We should really be looking for the old one and making sure it is done\r\n\t\tp_file->m_flags &= ~FILEIO_HANDLE_PREV_DMA;\r\n\r\n\t\t// Mark that we are using the CD\r\n\t\tp_file->m_flags |= FILEIO_HANDLE_BUSY;\r\n\t\tsFileIODevices[DEVICE_CD].m_in_use = TRUE;\r\n\t\tsFileIODevices[DEVICE_CD].mp_file_handle = p_file;\r\n\r\n\t\tp_file->m_cur_function = FILEIO_FUNCTION_READ;\r\n\t\tp_file->m_return_value = p_file->m_bytes_to_process;\r\n\t\ts_cur_command_status.m_request_state = REQUEST_PROCESSING;\r\n\r\n\t\tServiceCurrentFileHandle(FALSE);\r\n\t}\r\n\r\n\treturn;\r\n}\r\n\r\n////////////////////////////////\r\n// Write\r\nstatic void FileIO_Write(SFileIORequest *p_request, volatile unsigned int *p_file_handle_index, void *p_buffer, int size, int non_aligned_start_bytes, int non_aligned_end_bytes)\r\n{\r\n\tSFileIOHandle *p_file;\r\n\r\n\t// See if we have the correct index, and if we can't get it, return\r\n\tif ((*p_file_handle_index & FILEIO_TEMP_HANDLE_FLAG) && !FileIO_FindFileHandleIndex(p_file_handle_index))\r\n\t{\r\n\t\ts_cur_command_status.m_request_state = REQUEST_OPEN;\r\n\t\treturn;\r\n\t}\r\n\r\n\tp_file = &(gFileHandle[*p_file_handle_index]);\r\n\r\n\ts_cur_command_status.mp_file_handle = p_file;\r\n\r\n\t// Can't write if we're already busy\r\n\tif ((p_file->m_flags & FILEIO_HANDLE_BUSY) && !(p_file->mp_blocked_request && (p_file->mp_blocked_request == p_request)))\r\n\t{\r\n\t\ts_cur_command_status.m_request_state = REQUEST_OPEN;\r\n\t\treturn;\r\n\t}\r\n\r\n\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\ts_cur_command_status.m_return_value = -1;\r\n\treturn;\r\n}\r\n\r\n////////////////////////////////\r\n// Seek\r\nstatic void FileIO_Seek(volatile unsigned int *p_file_handle_index, int offset, int origin)\r\n{\r\n\tint new_position;\r\n\tSFileIOHandle *p_file;\r\n\r\n\t// See if we have the correct index, and if we can't get it, return\r\n\tif ((*p_file_handle_index & FILEIO_TEMP_HANDLE_FLAG) && !FileIO_FindFileHandleIndex(p_file_handle_index))\r\n\t{\r\n\t\ts_cur_command_status.m_request_state = REQUEST_OPEN;\r\n\t\treturn;\r\n\t}\r\n\r\n\tp_file = &(gFileHandle[*p_file_handle_index]);\r\n\r\n\ts_cur_command_status.mp_file_handle = p_file;\r\n\r\n\t// Can't start seek if we're already busy\r\n\tif (p_file->m_flags & FILEIO_HANDLE_BUSY)\r\n\t{\r\n\t\ts_cur_command_status.m_request_state = REQUEST_OPEN;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Do the adjustments\r\n\tswitch (origin)\r\n\t{\r\n\tcase SEEK_CUR:\r\n\t\tnew_position = p_file->m_cur_position + offset;\r\n\t\tbreak;\r\n\r\n\tcase SEEK_SET:\r\n\t\tnew_position = offset;\r\n\t\tbreak;\r\n\r\n\tcase SEEK_END:\r\n\t\tnew_position = p_file->m_file_size - offset;\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\tp_file->m_cur_function = FILEIO_FUNCTION_IDLE;\r\n\t\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\t\ts_cur_command_status.m_return_value = -1;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Check if before beginning\r\n\tif (new_position < 0)\r\n\t{\r\n\t\tnew_position = 0;\r\n\t}\r\n\r\n\t// Check if past EOF\r\n\tif (new_position > p_file->m_file_size)\r\n\t{\r\n\t\tnew_position = p_file->m_file_size;\r\n\t}\r\n\r\n\tif (p_file->m_host_fd >= 0)\r\n\t{\r\n\t\t// Device ready\r\n\t\tp_file->m_cur_position = new_position;\r\n\r\n\t\t// Do the seek\r\n\t\tlseek(p_file->m_host_fd, p_file->m_cur_position, SEEK_SET);\r\n\r\n\t\tp_file->m_return_value = p_file->m_cur_position;\r\n\t\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\t\ts_cur_command_status.m_return_value = p_file->m_cur_position;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Change position\r\n\t\tp_file->m_cur_position = new_position;\r\n\r\n\t\t// Also set the new current sector\r\n\t\tp_file->m_cur_sector = p_file->m_start_sector + (p_file->m_cur_position / SECTOR_SIZE);\r\n\r\n\t\tp_file->m_return_value = p_file->m_cur_position;\r\n\t\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\t\ts_cur_command_status.m_return_value = p_file->m_cur_position;\r\n\t}\r\n\r\n\treturn;\r\n}\r\n\r\nstatic void FileIO_Set(volatile unsigned int *p_file_handle_index, FileIOVariable variable, int value)\r\n{\r\n\tSFileIOHandle *p_file;\r\n\r\n\t// See if we have the correct index, and if we can't get it, return\r\n\tif ((*p_file_handle_index & FILEIO_TEMP_HANDLE_FLAG) && !FileIO_FindFileHandleIndex(p_file_handle_index))\r\n\t{\r\n\t\ts_cur_command_status.m_request_state = REQUEST_OPEN;\r\n\t\treturn;\r\n\t}\r\n\r\n\tp_file = &(gFileHandle[*p_file_handle_index]);\r\n\r\n\ts_cur_command_status.mp_file_handle = p_file;\r\n\r\n\t// Can't change parameters if we're already busy\r\n\tif (p_file->m_flags & FILEIO_HANDLE_BUSY)\r\n\t{\r\n\t\ts_cur_command_status.m_request_state = REQUEST_OPEN;\r\n\t\treturn;\r\n\t}\r\n\r\n\ts_cur_command_status.m_request_state = REQUEST_COMPLETE;\r\n\r\n\tswitch (variable)\r\n\t{\r\n\tcase FILEIO_VAR_PRIORITY:\r\n\t\tp_file->m_priority = value;\r\n\t\tbreak;\r\n\r\n\tcase FILEIO_VAR_BUFFER_SIZE:\r\n\t\tp_file->m_buffer_size = value;\r\n\t\tbreak;\r\n\r\n\tcase FILEIO_VAR_STREAM:\r\n\t\tp_file->m_stream = value;\r\n\t\tbreak;\r\n\r\n\tcase FILEIO_VAR_DESTINATION:\r\n\t\t// Not sure how to handle this one yet, since buffers may need to be acquired or freed\r\n\t\tif (value == MEM_EE)\r\n\t\t{\r\n\t\t\tp_file->m_flags |= FILEIO_HANDLE_EE_MEMORY;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_file->m_flags &= ~FILEIO_HANDLE_EE_MEMORY;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\ts_cur_command_status.m_return_value = FALSE;\r\n\t\treturn;\r\n\t}\r\n\r\n\ts_cur_command_status.m_return_value = TRUE;\r\n\treturn;\r\n}\r\n\r\n// EzADPCM_INIT\r\nint AdpcmInit( int pIopBuf )\r\n{\r\n#if 0\r\n\tint i;\r\n\tif ( gEECommand & PCMSTATUS_INITIALIZED )\r\n\t{\r\n\t\treturn ( 0 );\r\n\t}\r\n\r\n    if ( gSem == 0 )\r\n\t{\r\n\t\tstruct SemaParam sem;\r\n\t\tsem.initCount = 0;\r\n\t\tsem.maxCount = 1;\r\n\t\tsem.attr = AT_THFIFO;\r\n\t\tgSem = CreateSema (&sem);\r\n    }\r\n    if (gThid == 0)\r\n\t{\r\n\t\tstruct ThreadParam param;\r\n\t\tparam.attr         = TH_C;\r\n\t\tparam.entry        = RefreshStreams;\r\n\t\tparam.initPriority = BASE_priority-3;\r\n\t\tparam.stackSize    = 0x800; // was 800\r\n\t\tparam.option = 0;\r\n\t\tgThid = CreateThread (&param);\r\n\t\tprintf( \"EzADPCM: create thread ID= %d\\n\", gThid );\r\n\t\tStartThread (gThid, (u_long) NULL);\r\n    }\r\n\r\n\tmemset( gStreamInfo, 0, sizeof( struct StreamInfo ) * NUM_STREAMS );\r\n\tmemset( &gMusicInfo, 0, sizeof( struct StreamInfo ) );\r\n\t\r\n\tgpIopBuf = pIopBuf;\r\n\tgEECommand |= PCMSTATUS_INITIALIZED;\r\n\t//printf( \"PCM Irx iop buf %d\\n\", gpIopBuf );\r\n\t//Dbug_Printf( \"PCM irx is initialized\\n\" );\r\n#endif\r\n    return gThid;\r\n}\r\n\r\n// EzADPCM_QUIT\r\nvoid AdpcmQuit( void )\r\n{\r\n    DeleteThread (gThid);\r\n    gThid = 0;\r\n#if 0\r\n    DeleteSema (gSem);\r\n    gSem = 0;\r\n#endif\r\n    return;\r\n}\r\n\r\n/* internal */\r\nint RefreshStreams( int status )\r\n{\r\n\t//int i;\r\n\r\n    while ( 1 )\r\n\t{\r\n\t\tWaitSema(gSem);\r\n#if 0\r\n\t\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t\t{\r\n\t\t\tCheckStream( i );\r\n\t\t}\r\n\t\tCheckMusic( );\r\n\r\n\t\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t\t{\r\n\t\t\twhile ( gStreamInfo[ i ].update )\r\n\t\t\t{\r\n\t\t\t\tgStreamInfo[ i ].update--;\r\n\t\t\t\tUpdateStream( i );\r\n\t\t\t}\r\n\t\t}\r\n\t\twhile ( gMusicInfo.update )\r\n\t\t{\r\n\t\t\tgMusicInfo.update--;\r\n\t\t\tUpdateMusic( );\r\n\t\t}\r\n\t\tif ( gMusicInfo.volumeSet )\r\n\t\t{\r\n\t\t\tgMusicInfo.volumeSet = 0;\r\n\t\t\tAdpcmSetMusicVolumeDirect( gMusicInfo.volume );\r\n\t\t}\r\n\t\tfor ( i = 0; i < NUM_STREAMS; i++ )\r\n\t\t{\r\n\t\t\tif ( gStreamInfo[ i ].volumeSet )\r\n\t\t\t{\r\n\t\t\t\tgStreamInfo[ i ].volumeSet = 0;\r\n\t\t\t\tAdpcmSetStreamVolumeDirect( gStreamInfo[ i ].volume, i );\r\n\t\t\t}\r\n\t\t}\r\n#endif\r\n    }\r\n    return 0;\r\n}\r\n\r\nstatic ERequestState dispatch(volatile SFileIOTask *p_request_task)\r\n{ \r\n\tvolatile SFileIORequestEntry *p_request_entry = &(p_request_task->m_entry);\r\n\tvolatile SFileIORequest *p_request = &(p_request_entry->m_request);\r\n\tSFileIORequest *p_cont_request = (p_request_task->mp_cont) ? (&p_request_task->mp_cont->m_entry.m_request) : NULL;\r\n\r\n\t// Assume command will need to be completed asynchronously\r\n\ts_cur_command_status.m_request_state = REQUEST_OPEN;\r\n\ts_cur_command_status.m_request_id = p_request_entry->m_request_id;\r\n\ts_cur_command_status.mp_file_handle = NULL;\r\n\r\n    switch ( p_request->m_command )\r\n\t{\r\n\tcase FILEIO_INIT:\r\n\t\tFileIO_Init(p_request->m_param.m_init.m_priority,\r\n\t\t\t\t\tp_request->m_param.m_init.m_buffer_size,\r\n\t\t\t\t\tp_request->m_param.m_init.m_memory_dest,\r\n\t\t\t\t\tp_request->m_param.m_init.m_init_cd_device);\r\n\t\tbreak;\r\n\t\t\r\n\tcase FILEIO_OPEN:\r\n\t\tif (p_request->m_param.m_open.m_host_read)\r\n\t\t{\r\n\t\t\tFileIO_HostOpen((char *) p_request->m_param.m_open.m_file.m_filename,\r\n\t\t\t\t\t\t\tp_request->m_param.m_open.m_memory_dest,\r\n\t\t\t\t\t\t\tp_request->m_param.m_open.m_buffer_size,\r\n\t\t\t\t\t\t\tp_request->m_param.m_open.m_priority,\r\n\t\t\t\t\t\t\tp_request->m_param.m_open.m_attributes,\r\n\t\t\t\t\t\t\tp_request->m_param.m_open.m_host_read,\r\n\t\t\t\t\t\t\tp_cont_request);\r\n\t\t} else {\r\n\t\t\tFileIO_Open(p_request->m_param.m_open.m_file.m_raw_name.m_sector_number, \r\n\t\t\t\t\t\tp_request->m_param.m_open.m_file.m_raw_name.m_file_size,\r\n\t\t\t\t\t\tp_request->m_param.m_open.m_memory_dest,\r\n\t\t\t\t\t\tp_request->m_param.m_open.m_buffer_size,\r\n\t\t\t\t\t\tp_request->m_param.m_open.m_priority,\r\n\t\t\t\t\t\tp_request->m_param.m_open.m_attributes);\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\tcase FILEIO_CLOSE:\r\n\t\tFileIO_Close(&p_request->m_param.m_close.m_file_handle);\r\n\t\tbreak;\r\n\r\n\tcase FILEIO_READ:\r\n\t\tFileIO_Read((SFileIORequest *) p_request, &p_request->m_param.m_rw.m_file_handle, p_request->m_param.m_rw.m_buffer,\r\n\t\t\t\t\tp_request->m_param.m_rw.m_size, p_request->m_param.m_rw.m_non_aligned_start_bytes,\r\n\t\t\t\t\tp_request->m_param.m_rw.m_non_aligned_end_bytes);\r\n\t\tbreak;\r\n\r\n\tcase FILEIO_WRITE:\r\n\t\tFileIO_Write((SFileIORequest *) p_request, &p_request->m_param.m_rw.m_file_handle, p_request->m_param.m_rw.m_buffer,\r\n\t\t\t\t\t p_request->m_param.m_rw.m_size, p_request->m_param.m_rw.m_non_aligned_start_bytes,\r\n\t\t\t\t\t p_request->m_param.m_rw.m_non_aligned_end_bytes);\r\n\t\tbreak;\r\n\r\n\tcase FILEIO_SEEK:\r\n\t\tFileIO_Seek(&p_request->m_param.m_seek.m_file_handle, p_request->m_param.m_seek.m_offset,\r\n\t\t\t\t\tp_request->m_param.m_seek.m_origin);\r\n\t\tbreak;\r\n\r\n\tcase FILEIO_SET:\r\n\t\tFileIO_Set(&p_request->m_param.m_set.m_file_handle, p_request->m_param.m_set.m_variable,\r\n\t\t\t\t   p_request->m_param.m_set.m_value);\r\n\t\tbreak;\r\n\r\n\tcase FILEIO_CONT:\r\n\t\ts_cur_command_status.m_request_state = REQUEST_APPEND;\r\n\t\tbreak;\r\n\r\n\tdefault:\r\n\t\tERROR (\"FileIO driver error: unknown command %d \\n\", p_request->m_command);\r\n\t\ts_cur_command_status.m_return_value = -1;\r\n\t\tbreak;\r\n    }\r\n\r\n\t// Copy file handle in case we need it later\r\n\tp_request_task->mp_file_handle = s_cur_command_status.mp_file_handle;\r\n\r\n\tswitch (s_cur_command_status.m_request_state)\r\n\t{\r\n\tcase REQUEST_OPEN:\r\n\t\t// This isn't an error or warning anymore: it's now normal\r\n\t\t//ERROR ((\"FileIO driver error: request %d should not end in a open request state\\n\", p_request_entry->m_request_id));\r\n\t\t//printf(\"FileIO driver warning: request %d with command %d ended in a open request state\\n\", p_request_entry->m_request_id, p_request->m_command);\r\n\t\tbreak;\r\n\r\n\tcase REQUEST_PROCESSING:\r\n\t\tbreak;\r\n\r\n\tcase REQUEST_APPEND:\r\n\t\tbreak;\r\n\r\n\tcase REQUEST_COMPLETE:\r\n\t\t// Send result back to EE now if command completed\r\n\t\tSendNowaitResult();\r\n\t\tbreak;\r\n\t}\r\n\r\n    return s_cur_command_status.m_request_state;\r\n}\r\n\r\n\r\nstatic sceSifCmdData cmdbuffer[FILEIO_NUM_COMMAND_HANDLERS];\r\n\r\n#define NUM_FILEIO_REQUESTS\t(16)\r\n\r\n// Note these can be changed in an interrupt\r\nstatic volatile SFileIORequestEntry sFileIORequestArray[NUM_FILEIO_REQUESTS];\r\nstatic volatile int sFirstFileIORequest;\t\t// Interrupt only reads this value.\r\nstatic volatile\tint sFreeFileIORequest;\t\t\t// This is the main variable that changes in the interrupt\r\n\r\n// The task entries\r\nstatic SFileIOTask sFileIOTaskArray[FILEIO_MAX_TASKS];\r\nstatic SFileIOTask *spTaskFreeList = NULL;\r\n\r\nstatic void request_callback(void *p, void *q);\r\n\r\nint fileio_command_loop( void )\r\n{\r\n\tint oldStat;\r\n\tint i;\r\n\tEDeviceType cur_device;\r\n\r\n\t// Create semaphore to signal command came in\r\n\tstruct SemaParam sem;\r\n\tsem.initCount = 0;\r\n\tsem.maxCount = 1;\r\n\tsem.attr = AT_THFIFO;\r\n\tgCmdSem = CreateSema(&sem);\r\n\r\n\t// Init the stream queue\r\n\tsFirstFileIORequest = 0;\r\n\tsFreeFileIORequest = 0;\r\n\r\n\t// Init free task list\r\n\tspTaskFreeList = NULL;\r\n\tfor (i = 0; i < FILEIO_MAX_TASKS; i++)\r\n\t{\r\n\t\tsFileIOTaskArray[i].mp_file_handle = NULL;\r\n\r\n\t\t// Add to beginning of list\r\n\t\tsFileIOTaskArray[i].mp_next = spTaskFreeList;\r\n\t\tspTaskFreeList = &sFileIOTaskArray[i];\r\n\t}\r\n\r\n\t// Init devices\r\n\tfor (i = 0; i < NUM_DEVICE_TYPES; i++)\r\n\t{\r\n\t\tsFileIODevices[i].m_in_use = FALSE;\r\n\t\tsFileIODevices[i].m_waiting_callback = FALSE;\r\n\t\tsFileIODevices[i].mp_file_handle = NULL;\r\n\t\tsFileIODevices[i].mp_task_list = NULL;\r\n\t\tsFileIODevices[i].m_cur_position = -1;\r\n\t\tsFileIODevices[i].m_cur_sector = -1;\r\n\t\tsFileIODevices[i].mp_buffer[0] = NULL;\r\n\t\tsFileIODevices[i].mp_buffer[1] = NULL;\r\n\t\tsFileIODevices[i].m_buffer_index = -1;\r\n\t}\r\n\r\n\tsceSifInitRpc(0);\r\n\r\n\t// set local buffer & functions\r\n\tCpuSuspendIntr(&oldStat);\r\n\r\n\t// SIFCMD\r\n\tsceSifSetCmdBuffer( &cmdbuffer[0], FILEIO_NUM_COMMAND_HANDLERS);\r\n\r\n\tsceSifAddCmdHandler(FILEIO_REQUEST_COMMAND, (void *) request_callback, NULL );\r\n\r\n\tCpuResumeIntr(oldStat);\r\n\r\n\t// The loop\r\n\twhile (1) {\r\n\t\t//ShowFileIOInfo(\"waiting for command semaphore\\n\");\r\n\t\tWaitSema(gCmdSem);\t\t// Get signal from callback\r\n\t\t//ShowFileIOInfo(\"got command semaphore\\n\");\r\n\r\n\t\t// Move new requests into schedule list\r\n\t\t// Note that FreeStreamRequest can change in the interrupt at any time\r\n\t\t// Also, FirstStreamRequest is examined in the interrupt, but just to make sure we don't overflow the buffer\r\n\t\twhile (sFreeFileIORequest != sFirstFileIORequest)\r\n\t\t{\r\n\t\t\tvolatile SFileIORequestEntry *p_request = &(sFileIORequestArray[sFirstFileIORequest]);\r\n\t\t\tSFileIOTask *p_new_task;\r\n\t\t\tShowFileIOInfo(\"FileIO: got request id %d with command %x\\n\", p_request->m_request_id, p_request->m_request.m_command);\r\n\r\n\t\t\t// Get a new task entry\r\n\t\t\tp_new_task = spTaskFreeList;\r\n\t\t\tspTaskFreeList = p_new_task->mp_next;\r\n\t\t\tp_new_task->mp_next = NULL;\r\n\r\n\t\t\t// Copy data\r\n\t\t\tp_new_task->m_entry = *p_request;\r\n\t\t\tp_new_task->mp_file_handle = NULL;\r\n\t\t\tp_new_task->mp_cont = NULL;\r\n\r\n\t\t\t// And put onto unknown device task list\r\n\t\t\tAppendTask(&sFileIODevices[DEVICE_UNKNOWN], p_new_task);\r\n\r\n\t\t\t// Increment request index; Note that interrupt can look at this\r\n\t\t\tsFirstFileIORequest = (sFirstFileIORequest + 1) % NUM_FILEIO_REQUESTS;\r\n\t\t}\r\n\r\n\t\t// Process device tasks\r\n\t\tfor (cur_device = DEVICE_CD; cur_device < NUM_DEVICE_TYPES; cur_device++)\r\n\t\t{\r\n\t\t\tSFileIODevice *p_device = &sFileIODevices[cur_device];\r\n\t\t\tSFileIOTask *p_task;\r\n\r\n\t\t\t// Skip if busy\r\n\t\t\tif (p_device->m_in_use)\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tp_task = p_device->mp_task_list;\r\n\t\t\twhile (p_task)\r\n\t\t\t{\r\n\t\t\t\tERequestState ret;\r\n\t\t\t\tSFileIOTask *p_dispatch_task;\r\n\r\n\t\t\t\tp_dispatch_task = p_task;\r\n\r\n\t\t\t\tShowFileIOInfo(\"FileIO: doing request id %d with command %x\\n\", p_dispatch_task->m_entry.m_request_id, p_dispatch_task->m_entry.m_request.m_command);\r\n\t\t\t\tret = dispatch(p_dispatch_task);\r\n\r\n\t\t\t\tp_task = p_task->mp_next;\r\n\r\n\t\t\t\tswitch (ret)\r\n\t\t\t\t{\r\n\t\t\t\tcase REQUEST_OPEN:\r\n\t\t\t\t\t// Move to other device\r\n\t\t\t\t\tif (p_dispatch_task->mp_file_handle && (p_dispatch_task->mp_file_handle->m_device_type != cur_device))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tRemoveTask(p_device, p_dispatch_task);\r\n\t\t\t\t\t\tInsertTask(&sFileIODevices[p_dispatch_task->mp_file_handle->m_device_type], p_dispatch_task);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase REQUEST_APPEND:\r\n\t\t\t\t\t// Add the request to an existing request\r\n\t\t\t\t\tif (AppendContRequest(p_dispatch_task))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tShowFileIOInfo(\"***************** FileIO: appended request id %d of command %x\\n\", p_dispatch_task->m_entry.m_request_id, p_dispatch_task->m_entry.m_request.m_command);\r\n\t\t\t\t\t\tRemoveTask(p_device, p_dispatch_task);\r\n\t\t\t\t\t\tSignalSema(gCmdSem);\t\t// So the other task can be retried\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase REQUEST_PROCESSING:\r\n\t\t\t\tcase REQUEST_COMPLETE:\r\n\t\t\t\t\tRemoveTask(p_device, p_dispatch_task);\r\n\t\t\t\t\tif (p_dispatch_task->mp_cont)\t\t\t// Check if we have a continuation request\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_dispatch_task->mp_cont->mp_next = spTaskFreeList;\r\n\t\t\t\t\t\tspTaskFreeList = p_dispatch_task->mp_cont;\r\n\t\t\t\t\t\tp_dispatch_task->mp_cont = NULL;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tp_dispatch_task->mp_next = spTaskFreeList;\r\n\t\t\t\t\tspTaskFreeList = p_dispatch_task;\r\n\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n    return 0;\r\n}\r\n\r\nstatic void SendNowaitResult()\r\n{\r\n\tstatic SFileIOResultPacket fileIOResult;\r\n\r\n\tstatic unsigned int last_cmd_id = 0;\r\n\tstatic int did_dma_send = FALSE;\r\n\r\n\t// Send the result back\r\n\tif (did_dma_send && last_cmd_id >= 0)\t// Wait for previous send to complete (it should already be done, though)\r\n\t{\r\n\t   while(sceSifDmaStat(last_cmd_id) >= 0)\r\n\t\t   Kprintf(\"Waiting for DMA\\n\");\r\n\t}\r\n\r\n\t// Gotta copy the id into SStreamRequest\r\n\tfileIOResult.m_header.opt = s_cur_command_status.m_request_id;\t// Copy id\r\n\tfileIOResult.m_return_value = s_cur_command_status.m_return_value;\r\n\tfileIOResult.m_return_data = s_cur_command_status.m_return_data;\r\n\tfileIOResult.m_done = TRUE;\r\n\tfileIOResult.m_non_aligned_data_size = 0;\r\n\tdid_dma_send = TRUE;\r\n\tlast_cmd_id = sceSifSendCmd(FILEIO_RESULT_COMMAND, &fileIOResult, GetResultPacketSize(&fileIOResult), 0, 0, 0);\r\n\tShowFileIOInfo(\"FileIO: sent nowait result id %d back\\n\", s_cur_command_status.m_request_id);\r\n}\r\n\r\nstatic void request_callback(void *p, void *q)\r\n{\r\n\tSFileIORequestPacket *h = (SFileIORequestPacket *) p;\r\n\r\n\t// Check to make sure we can add\r\n\tint nextFreeReq = (sFreeFileIORequest + 1) % NUM_FILEIO_REQUESTS;\r\n\tif (nextFreeReq == sFirstFileIORequest)\r\n\t{\r\n\t\t// We can't allow a request to be ignored.  We must abort\r\n\t\tERROR((\"******************************** FileIO driver error: too many requests ********************************\\n\" ));\r\n\t}\r\n\r\n\tShowFileIOInfo(\"FileIO: received request id %d with command %x\\n\", h->m_header.opt, h->m_request.m_command);\r\n\r\n\t// Copy the request into the reuest queue\r\n\tsFileIORequestArray[sFreeFileIORequest].m_request = h->m_request;\r\n\tsFileIORequestArray[sFreeFileIORequest].m_request_id = h->m_header.opt;\r\n\tsFreeFileIORequest = nextFreeReq;\r\n\r\n\t// And wake up the dispatch thread\r\n\tiSignalSema(gCmdSem);\r\n}\r\n\r\n// Adds p_task to the end of the device task list\r\nstatic void AppendTask(SFileIODevice *p_device, SFileIOTask *p_task)\r\n{\r\n\tSFileIOTask *p_task_list = p_device->mp_task_list;\r\n\tif (p_task_list)\r\n\t{\r\n\t\t// Find end of list\r\n\t\twhile (p_task_list->mp_next)\r\n\t\t{\r\n\t\t\tp_task_list = p_task_list->mp_next;\r\n\t\t}\r\n\r\n\t\tp_task->mp_next = p_task_list->mp_next;\r\n\t\tp_task_list->mp_next = p_task;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Empty list\r\n\t\tp_device->mp_task_list = p_task;\r\n\t\tp_task->mp_next = NULL;\r\n\t}\r\n}\r\n\r\n#define GetPriority(x) ((x) ? (x)->m_priority : gDefaultPriority)\r\n\r\n// Inserts p_task into the device task list sorted by priority\r\nstatic void InsertTask(SFileIODevice *p_device, SFileIOTask *p_task)\r\n{\r\n\tSFileIOTask *p_task_node = p_device->mp_task_list;\r\n\tSFileIOTask *p_prev_node = NULL;\r\n\r\n\tint priority = GetPriority(p_task->mp_file_handle);\r\n\r\n\t// Find point in list\r\n\twhile (p_task_node)\r\n\t{\r\n\t\tif (priority < GetPriority(p_task_node->mp_file_handle))\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tp_prev_node = p_task_node;\r\n\t\tp_task_node = p_task_node->mp_next;\r\n\t}\r\n\r\n\t// Insert\r\n\tif (p_prev_node)\r\n\t{\r\n\t\tp_task->mp_next = p_task_node;\r\n\t\tp_prev_node->mp_next = p_task;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Head of list\r\n\t\tp_task->mp_next = p_device->mp_task_list;\r\n\t\tp_device->mp_task_list = p_task;\r\n\t}\r\n}\r\n\r\n// Removes p_task from the device task list\r\nstatic void RemoveTask(SFileIODevice *p_device, SFileIOTask *p_task)\r\n{\r\n\tSFileIOTask *p_task_node = p_device->mp_task_list;\r\n\r\n\tif (p_task == p_task_node)\r\n\t{\r\n\t\t// Head of list\r\n\t\tp_device->mp_task_list = p_task->mp_next;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Find item in list\r\n\t\twhile (p_task_node->mp_next)\r\n\t\t{\r\n\t\t\tif (p_task == p_task_node->mp_next)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tp_task_node = p_task_node->mp_next;\r\n\t\t}\r\n\r\n\t\t// Remove\r\n\t\tp_task_node->mp_next = p_task->mp_next;\r\n\t}\r\n\tp_task->mp_next = NULL;\r\n}\r\n\r\nstatic int AppendContRequest(SFileIOTask *p_task)\r\n{\r\n\tEDeviceType cur_device;\r\n\r\n\t// Process device tasks\r\n\tfor (cur_device = DEVICE_CD; cur_device < NUM_DEVICE_TYPES; cur_device++)\r\n\t{\r\n\t\tSFileIODevice *p_device = &sFileIODevices[cur_device];\r\n\t\tSFileIOTask *p_task_node;\r\n\r\n\t\tp_task_node = p_device->mp_task_list;\r\n\r\n\t\t// Find item in list\r\n\t\twhile (p_task_node)\r\n\t\t{\r\n\t\t\tif (p_task->m_entry.m_request_id == p_task_node->m_entry.m_request_id && (p_task != p_task_node))\r\n\t\t\t{\r\n\t\t\t\tp_task_node->mp_cont = p_task;\r\n\t\t\t\treturn TRUE;\r\n\t\t\t}\r\n\r\n\t\t\tp_task_node = p_task_node->mp_next;\r\n\t\t}\r\n\t}\r\n\r\n\treturn FALSE;\r\n}\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n"
  },
  {
    "path": "Code/Sys/File/ngps/FileIO/start.c",
    "content": "/* FileIO -- Converted from Sony samples -- Garrett Oct 2002 */\r\n\r\n#include <kernel.h>\r\n#include <sys/types.h>\r\n#include <stdio.h>\r\n#include <sif.h>\r\n#include <sifrpc.h>\r\n#include <sifcmd.h>\r\n#include \"fileio.h\"\r\n#include \"fileio_iop.h\"\r\n\r\nModuleInfo Module = {\"fileio_driver\", 0x0112};\r\n\r\n// in command.c\r\nextern int fileio_command_loop (void);\r\n\r\nint start()\r\n{\r\n    struct ThreadParam param;\r\n    int th;\r\n\r\n    if (!sceSifCheckInit())\r\n\t{\r\n\t\tsceSifInit();\r\n\t}\r\n    sceSifInitRpc(0);\r\n\r\n    printf(\"FileIO driver version 0.1\\n\");\r\n\r\n    param.attr         = TH_C;\r\n    param.entry        = fileio_command_loop;\r\n    param.initPriority = BASE_priority - 2;\r\n    param.stackSize    = 0x800;\r\n    param.option       = 0;\r\n    th = CreateThread(&param);\r\n    if (th > 0) {\r\n\t\tStartThread(th, 0);\r\n    } else {\r\n\t\treturn 1;\r\n    }\r\n\r\n\treturn 0;\r\n}\r\n\r\n/* ----------------------------------------------------------------\r\n *\tEnd on File\r\n * ---------------------------------------------------------------- */\r\n"
  },
  {
    "path": "Code/Sys/File/ngps/hed.cpp",
    "content": "/*\tHeader file functionality...\r\n\t.Hed files that describe the contents of .Wad files\r\n\tWritten by Ken, stolen by Matt*/\r\n#include <eetypes.h>\r\n#include <eekernel.h>\r\n#include <stdio.h>\r\n#include <sifdev.h>\r\n#include <libsdr.h>\r\n#include <sdrcmd.h>\r\n#include <sdmacro.h>\r\n#include <string.h>\r\n#include <ctype.h>\r\n#include <sif.h>\r\n#include <sifrpc.h>\r\n\r\n#include <libcdvd.h>\r\n\r\n\r\n#include <core/macros.h>\r\n#include <core/defines.h>\r\n\r\n#include <gel/scripting/script.h> \r\n\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/ngps/hed.h>\r\n#include <sys/config/config.h>\r\n\r\nnamespace File\r\n{\r\n\r\nstatic void get_checksums( const char * p_name, uint32 * p_dir, uint32 * p_file )\r\n{\r\n\tchar name[128];\r\n\tchar dir[128];\r\n\tchar file[128];\r\n\tuint lp;\r\n\r\n\t// Convert / to \\\\.\r\n\tfor ( lp = 0; lp <= strlen( p_name ); lp++ )\r\n\t{\r\n\t\tname[lp] = p_name[lp];\r\n\t\tif ( name[lp] == '/' ) name[lp] = '\\\\';\r\n\t}\r\n\r\n\t// Find the directory name and the filename.\r\n\tfor ( lp = strlen( name ) - 1; lp >= 0; lp-- )\r\n\t{\r\n\t\tif ( name[lp] == '\\\\' )\r\n\t\t{\r\n\t\t\t// Found the directory end.\r\n\t\t\tstrcpy( file, &name[lp+1] );\r\n\t\t\tname[lp] = '\\0';\r\n\t\t\tif ( name[0]=='\\\\' )\r\n\t\t\t{\r\n\t\t\t\tstrcpy( dir, &name[1] );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tstrcpy( dir, name );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// Create checksums.\r\n\tif ( p_dir ) *p_dir = Script::GenerateCRC( dir );\r\n\tif ( p_file ) *p_file = Script::GenerateCRC( file );\r\n}\r\n\r\n\r\n// Searches the hed file for the filename. If not found, returns NULL.\r\nSHedFile *FindFileInHed(const char *pFilename, SHed *pHed)\r\n{\r\n\tDbg_MsgAssert(pFilename,(\"NULL pFilename\"));\r\n\tDbg_MsgAssert(pHed,(\"NULL pHed\"));\r\n\r\n\tuint32 check_dir;\r\n\tuint32 check_file;\r\n\r\n\tget_checksums( pFilename, &check_dir, &check_file );\r\n\r\n\tSHed *pHd=pHed;\r\n\twhile ( pHd->numFiles != 0xffffffff )\r\n\t{\r\n\t\tif ( pHd->Checksum == check_dir )\r\n\t\t{\r\n\t\t\tSHedFile * pF = pHd->p_fileList;\r\n\t\t\tfor ( uint lp2 = 0; lp2 < pHd->numFiles; lp2++ )\r\n\t\t\t{\r\n\t\t\t\tif ( pF->Checksum == check_file )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn pF;\r\n\t\t\t\t}\r\n\t\t\t\tpF++;\r\n\t\t\t}\r\n\t\t}\r\n\t\tpHd++;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n// Searches the hed file for the filename with the same checksum. If not found, returns NULL.\r\nSHedFile *FindFileInHedUsingChecksum( uint32 checksum, SHed *pHed )\r\n{\r\n\t// Garrett: This function can take over .1 ms to execute when there are over 2000 entries.  We may want to make a better\r\n\t// search for this.\r\n\t//uint64 start_time = Tmr::GetTimeInUSeconds();\t\r\n\t//int iterations = 0;\r\n\r\n\tDbg_MsgAssert(pHed,(\"NULL pHed\"));\r\n\r\n\tSHed *pHd=pHed;\r\n\twhile ( pHd->numFiles != 0xffffffff )\r\n\t{\r\n\t\tSHedFile * pF = pHd->p_fileList;\r\n\t\tfor ( uint lp2 = 0; lp2 < pHd->numFiles; lp2++ )\r\n\t\t{\r\n\t\t\t//iterations++;\r\n\t\t\tif ( pF->Checksum == checksum )\r\n\t\t\t{\r\n\t\t\t\t//uint64 end_time = Tmr::GetTimeInUSeconds();\t\r\n\t\t\t\t//if ((end_time - start_time) > 100)\r\n\t\t\t\t//\tDbg_Message(\"FindNameFromChecksum Found Iterations %d Time %d\", iterations, (end_time - start_time));\r\n\t\t\t\treturn pF;\r\n\t\t\t}\r\n\t\t\tpF++;\r\n\t\t}\r\n\t\tpHd++;\r\n\t}\r\n\r\n\t//uint64 end_time = Tmr::GetTimeInUSeconds();\t\r\n\t//if ((end_time - start_time) > 100)\r\n\t//\tDbg_Message(\"FindNameFromChecksum NotFound Iterations %d Time %d\", iterations, (end_time - start_time));\r\n\treturn NULL;\r\n}\r\n\r\nextern void StopStreaming( void );\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n// Keep track of the hed buffers so the leak code doesn't think they are leaks\r\n#define MAX_HED_BUFFERS 3\r\nuint32 *sp_hed_buffers[MAX_HED_BUFFERS] = { (uint32 *) 16, (uint32 *) 16, (uint32 *) 16 };\r\nint s_num_hed_buffers = 0;\r\n#endif //\t__NOPT_ASSERT__\r\n\r\nSHed *LoadHed( const char *filename, bool force_cd, bool no_wad )\r\n{\r\n\tint lp;\r\n\tuint32 *pHed = NULL;\r\n\r\n\tif (Config::CD() || force_cd)\r\n\t{\r\n\t\tint HedId=-1;\r\n\t\tchar hedFileName[255];\r\n\t\tchar uppercaseFilename[ 255 ];\r\n\t\tint sL = strlen( filename );\r\n\t\tDbg_MsgAssert( sL < 255,( \"Filename %s too long\", filename ));\r\n\t\tint i;\r\n\t\tfor ( i = 0; i < sL; i++ )\r\n\t\t{\r\n\t\t\tuppercaseFilename[ i ] = toupper( filename[ i ] );\r\n\t\t}\r\n\t\tuppercaseFilename[ i ] = '\\0';\r\n\t\tStopStreaming( );\r\n\t\tsprintf( hedFileName, \"cdrom0:\\\\%s%s.HED;1\", Config::GetDirectory(),uppercaseFilename );\r\n\t\tint retry = 0;\r\n\t\twhile (HedId<0)\r\n\t\t{\r\n\t\t\tHedId=sceOpen( hedFileName, SCE_RDONLY );\r\n\t\t\tif (HedId<0)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"Retrying opening %s\\n\", hedFileName );\r\n\t\t\t\tretry++;\r\n\t\t\t\tif (retry == 10)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn NULL;\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t}\r\n\t\tprintf(\"%s opened successfully\\n\", uppercaseFilename );\r\n\t\tlong HedSize=sceLseek(HedId, 0, SCE_SEEK_END);\r\n\t\t\r\n\t\tDbg_MsgAssert(pHed==NULL,(\"pHed not NULL ?\"));\r\n\t\tif (no_wad)\r\n\t\t{\r\n\t\t\t// We'll want to keep this around\r\n\t\t\tpHed = new (Mem::Manager::sHandle().DebugHeap()) uint32[((HedSize+2047)&~2047) >> 2];\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpHed=(uint32*)Mem::Malloc((HedSize+2047)&~2047);\r\n\t\t}\r\n\t\tDbg_MsgAssert(pHed,(\"pHed NULL ?\"));\r\n\r\n\t/*\r\n\t\tchar *p = (char*) pHed;  \r\n\t\t// Hmmm.....\r\n\t\tfor (int i=0 ;i < (HedSize+2047)&~2047;i++)\r\n\t\t{\r\n\t\t\tp[i] = 0x55;\r\n\t\t}\r\n\t*/\t\t\t\t\t\t\r\n\t\t// 9/5/03 - Garrett: Burn fix.  Added retry code to see if HED file actually written.\r\n\t\t// If it cannot, it frees the buffer and returns NULL.\r\n\t\tint read_bytes = 0;\r\n\t\tretry = 0;\r\n\t\twhile (read_bytes != HedSize)\r\n\t\t{\r\n\t\t\tsceLseek(HedId, 0, SCE_SEEK_SET);\r\n\t\t\tread_bytes = sceRead(HedId,pHed,HedSize);\r\n\t\t\tif (read_bytes != HedSize)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"READ ERROR: Retrying read of %s\\n\", hedFileName );\r\n\t\t\t\tretry++;\r\n\t\t\t\tif (retry == 4)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf(\"READ ERROR: aborting read of %s\\n\", hedFileName );\r\n\t\t\t\t\tdelete pHed;\r\n\t\t\t\t\treturn NULL;\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t}\r\n\r\n\t\tsceClose(HedId);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tchar tempFileName[ 255];\r\n\r\n\t\t// Make filename\r\n\t\tif (no_wad)\r\n\t\t{\r\n\t\t\tsprintf( tempFileName, \"host:%shost.HED\", filename );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsprintf( tempFileName, \"host:%s.HED\", filename );\r\n\t\t}\r\n\t\r\n\t\tvoid *fp = File::Open( tempFileName, \"rb\" );\r\n\t\tif ( !fp )\r\n\t\t{\r\n// Mick:   Don't assert, as we want to be able to run without a .HED on the disk, for music\r\n//\t\t\tDbg_MsgAssert( 0,( \"Couldn't find hed file %s\", tempFileName ));\r\n\t\t\tprintf( \"failed to find %s\\n\", tempFileName );\r\n\t\t\treturn ( NULL );\r\n\t\t}\r\n\t\tint fileSize = File::GetFileSize( fp );\r\n\t\tFile::Seek( fp, 0, SEEK_SET );\r\n\t\t\r\n\t\tif (no_wad)\r\n\t\t{\r\n\t\t\t// We'll want to keep this around\r\n\t\t\tpHed = new (Mem::Manager::sHandle().DebugHeap()) uint32[((fileSize+2047)&~2047) >> 2];\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\t\t\tif (s_num_hed_buffers < MAX_HED_BUFFERS)\r\n\t\t\t{\r\n\t\t\t\tsp_hed_buffers[s_num_hed_buffers++] = pHed;\r\n\t\t\t}\r\n#endif //\t__NOPT_ASSERT__\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpHed=(uint32*)Mem::Malloc((fileSize+2047)&~2047);\r\n\t\t}\r\n\t\tDbg_MsgAssert( pHed,( \"Failed to allocate memory for hed %s\", tempFileName ));\r\n\t\t\r\n\t\tFile::Read( pHed, 1, fileSize, fp );\r\n\t\tFile::Close( fp );\r\n\t}\r\n\r\n\t// Convert to more compact list.\r\n\tint files = 0;\r\n\tint dirs = 0;\r\n\r\n\t// First, count how many files we have.\r\n\tuint32 * p32 = pHed;\r\n\twhile ( p32[0] != 0xffffffff )\r\n\t{\r\n\t\tfiles++;\r\n\r\n\t\tint len = strlen( (char *)&p32[2] ) + 1;\r\n\t\tlen = ( len + 3 ) & ~3;\r\n\t\tp32 = (uint32*)(((int)&p32[2]) + len);\r\n\t}\r\n\r\n\t// Build list of checksums.\r\n\tuint32 *p_offset = new (Mem::Manager::sHandle().TopDownHeap()) uint32[files];\r\n\tuint32 *p_size = new (Mem::Manager::sHandle().TopDownHeap()) uint32[files];\r\n\tuint32 *dir_check = new (Mem::Manager::sHandle().TopDownHeap()) uint32[files];\r\n\tuint32 *file_check = new (Mem::Manager::sHandle().TopDownHeap()) uint32[files];\r\n\tchar **p_filename = new (Mem::Manager::sHandle().TopDownHeap()) (char *)[files];\r\n\tint count = 0;\r\n\tp32 = pHed;\r\n\twhile ( p32[0] != 0xffffffff )\r\n\t{\r\n\t\tp_offset[count] = p32[0];\r\n\t\tp_size[count] = p32[1];\r\n\t\tp_filename[count] = (char *)&p32[2];\r\n\t\tget_checksums( (char *)&p32[2], &dir_check[count], &file_check[count] );\r\n\t\tcount++;\r\n\r\n\t\tint len = strlen( (char *)&p32[2] ) + 1;\r\n\t\tlen = ( len + 3 ) & ~3;\r\n\t\tp32 = (uint32*)(((int)&p32[2]) + len);\r\n\t}\r\n\r\n\t// Second, count how many directories we have.\r\n\tfor ( lp = 0; lp < files; lp++ )\r\n\t{\r\n\t\tbool unique = true;\r\n\t\tfor ( int lp2 = 0; lp2 < lp; lp2++ )\r\n\t\t{\r\n\t\t\tif ( dir_check[lp] == dir_check[lp2] )\r\n\t\t\t{\r\n\t\t\t\tunique = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( unique ) dirs++;\r\n\t}\r\n\r\n\t// Now, allocate final piece of memory.\r\n\tint size = ( sizeof( SHed ) * ( dirs + 1 ) ) + ( sizeof( SHedFile ) * files );\r\n\tSHed * p_hed = (SHed *)new uint8[size];\r\n\r\n\t// Fill in directory entries.\r\n\tint dirs_added = 0;\r\n\tfor ( lp = 0; lp < files; lp++ )\r\n\t{\r\n\t\tbool unique = true;\r\n\t\tfor ( int lp2 = 0; lp2 < dirs_added; lp2++ )\r\n\t\t{\r\n\t\t\tif ( p_hed[lp2].Checksum == dir_check[lp] )\r\n\t\t\t{\r\n\t\t\t\tunique = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( unique )\r\n\t\t{\r\n\t\t\tp_hed[dirs_added].Checksum = dir_check[lp];\r\n\t\t\tdirs_added++;\r\n\t\t}\r\n\t}\r\n\r\n\t// Fill in file entries.\r\n\tSHedFile * p_hed_file = (SHedFile *)&p_hed[(dirs+1)];\r\n\tfor ( lp = 0; lp < dirs; lp++ )\r\n\t{\r\n\t\tp_hed[lp].p_fileList = p_hed_file;\r\n\t\tint files_this_dir = 0;\r\n\t\tfor ( int lp2 = 0; lp2 < files; lp2++ )\r\n\t\t{\r\n\t\t\tif ( dir_check[lp2] == p_hed[lp].Checksum )\r\n\t\t\t{\r\n\t\t\t\tp_hed_file->FileSize = p_size[lp2];\r\n\t\t\t\tif (no_wad)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_hed_file->p_filename = p_filename[lp2];\r\n\t\t\t\t\tp_hed_file->FileSize |= SHedFile::mNO_WAD;\t\t// This marks that we are using the no_wad version\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_hed_file->Offset = p_offset[lp2];\r\n\t\t\t\t}\r\n\t\t\t\tp_hed_file->Checksum = file_check[lp2];\r\n\t\t\t\tfiles_this_dir++;\r\n\t\t\t\tp_hed_file++;\r\n\t\t\t}\r\n\t\t}\r\n\t\tp_hed[lp].numFiles = files_this_dir;\r\n\t}\r\n\tp_hed[dirs].numFiles = 0xffffffff;\r\n\r\n\t// Get rid of temp data.\r\n\tdelete p_filename;\r\n\tdelete file_check;\r\n\tdelete dir_check;\r\n\tdelete p_size;\r\n\tdelete p_offset;\r\n\tif (!no_wad)\r\n\t{\r\n\t\tdelete pHed;\r\n\t}\r\n\r\n\treturn p_hed;\r\n}\r\n\r\n} // namespace File\r\n"
  },
  {
    "path": "Code/Sys/File/ngps/hed.h",
    "content": "/*\tHeader file functionality...\r\n\t.Hed files that describe the contents of .Wad files\r\n\tWritten by Ken, stolen by Matt*/\r\n#ifndef __HED_H__\r\n#define __HED_H__\r\n\r\nnamespace File\r\n{\r\n\r\nstruct SHedFile\r\n{\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tmNO_WAD = 0x80000000\r\n\t};\r\n\r\n\tbool\t\tHasNoWad() const { return FileSize & mNO_WAD; }\r\n\tuint32\t\tGetFileSize() const { return FileSize & (~mNO_WAD); }\r\n\r\n\tunion\r\n\t{\r\n\t\tuint32 Offset; \t\t\t// A SECTOR_SIZE aligned offset of a file within skate3.wad\r\n\t\tchar * p_filename; \t\t// The filename itself (for no_wad heds)\r\n\t};\r\n\r\n\t// The file size, which is the raw file size, not rounded up\r\n\t// to a multiple of SECTOR_SIZE.  Highest bit is set if no wad\r\n\t// file is associated with it.\r\n\tuint32 FileSize;\r\n\r\n\t// Filename checksum (does not include directory).\r\n\tuint32 Checksum;\r\n};\r\n\r\nstruct SHed\r\n{\r\n\t// Number of files in this directory.\r\n\tuint32 numFiles;\r\n\t\r\n\t// Checksum of this directory.\r\n\tuint32 Checksum;\r\n\r\n\t// Pointer to File list.\r\n\tSHedFile * p_fileList;\r\n\r\n\t// The filename, which is actually bigger than one byte, tee hee.\r\n//\tconst char pFilename[1];\r\n};\r\n\r\n\r\nSHedFile *FindFileInHed(const char *pFilename, SHed *pHed );\r\nSHedFile *FindFileInHedUsingChecksum( uint32 checksum, SHed *pHed );\r\nSHed *LoadHed( const char *filename, bool force_cd = false, bool no_wad = false );\r\n\r\n} // namespace File\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sys/File/ngps/p_AsyncFilesys.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// p_AsyncFilesys.cpp\t\tGRJ 11 Oct 2002\r\n//\r\n// Asynchronous file system\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include <sys/config/config.h>\r\n\r\n#include <sys/file/ngps/p_AsyncFilesys.h>\r\n#include <sys/file/ngps/hed.h>\r\n#include <sys/file/ngps/FileIO/FileIO.h>\r\n\r\n#include <eetypes.h>\r\n#include <eekernel.h>\r\n#include <sif.h>\r\n#include <sifrpc.h>\r\n\r\nnamespace File\r\n{\r\n\r\n// Debug info\r\n#define SHOW_ASYNC_INFO\t0\r\n\r\n#if SHOW_ASYNC_INFO\r\n#define ShowAsyncInfo(A...) scePrintf(##A)\r\n#else\r\n#define ShowAsyncInfo(A...) \r\n#endif\r\n\r\nextern SHed *gpHed;\t\t// Made global for p_AsyncFilesystem\r\nextern unsigned int gWadLSN;\r\n\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2AsyncFileHandle::CPs2AsyncFileHandle()\r\n{\r\n\tm_file_handle_index = -1;\r\n\tm_num_open_requests = 0;\r\n\tmp_non_aligned_buffer = NULL;\r\n\tmp_temp_aligned_buffer = NULL;\r\n\tmp_temp_aligned_buffer_base = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCPs2AsyncFileHandle::~CPs2AsyncFileHandle()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCPs2AsyncFileHandle::io_callback(EAsyncFunctionType function, int result, uint32 data)\r\n{\r\n\tSFileIOResultPacket *p_packet = (SFileIOResultPacket *) data;\r\n\tint return_data = p_packet->m_return_data;\r\n\r\n\t// Do any special function processing\r\n\tswitch (function)\r\n\t{\r\n\tcase FUNC_OPEN:\r\n\t\tm_file_handle_index = result;\t\t// Save IOP file handle index\r\n\t\tif (result < 0)\r\n\t\t{\r\n\t\t\t//Dbg_MsgAssert(0, (\"Error: Async open returned %d\", result));\r\n\t\t\tm_file_size = 0;\r\n\t\t} else {\r\n\t\t\tm_file_size = return_data;\r\n\t\t\tShowAsyncInfo(\"io_callback: Open returned handle index %d with filesize %d\\n\", result, return_data);\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\tcase FUNC_SEEK:\r\n\t\tif (result < 0)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"Error: Async seek returned %d\", result));\r\n\t\t} else {\r\n\t\t\tm_position = result;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\tcase FUNC_LOAD:\r\n\tcase FUNC_READ:\r\n\t\tif (mp_temp_aligned_buffer && (result > 0))\r\n\t\t{\r\n\t\t\tShowAsyncInfo(\"Copying from %x to %x of size %d\", mp_temp_aligned_buffer, mp_non_aligned_buffer, result);\r\n\t\t\tmemcpy(mp_non_aligned_buffer, mp_temp_aligned_buffer, result);\r\n\t\t}\r\n\r\n\t\t// don't break, continue on below\r\n\r\n\tcase FUNC_WRITE:\r\n\t\tif (result < 0)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0, (\"Error: Async IO returned %d\", result));\r\n\t\t} else {\r\n\t\t\tm_position += result;\r\n\t\t\tif (mp_temp_aligned_buffer)\r\n\t\t\t{\r\n\t\t\t\tCPs2AsyncFileLoader::sIAddBufferToFreeList(mp_temp_aligned_buffer_base);\r\n\t\t\t\tmp_non_aligned_buffer = NULL;\r\n\t\t\t\tmp_temp_aligned_buffer = NULL;\r\n\t\t\t\tmp_temp_aligned_buffer_base = NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\tcase FUNC_CLOSE:\r\n\t\tif (get_busy_count() > 1)\r\n\t\t{\r\n\t\t\tscePrintf(\"********* ERROR: Still other %d requests open after close completed on handle %x and request id %d\\n\", get_busy_count() - 1, this, p_packet->m_header.opt);\r\n\t\t\t//while (1)\r\n\t\t\t//\t;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\tcase FUNC_IDLE:\r\n\t\t// Don't want m_busy to change or user-defined callback to be executed\r\n\t\treturn;\r\n\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\t// Check to make sure request buffer will be clear\r\n\tif (get_busy_count() > 0)\r\n\t{\r\n\t\t//Dbg_MsgAssert(m_num_open_requests == 1, (\"Sill other open requests\"));\r\n\t}\r\n\r\n\t// Now handle the above p-line stuff\r\n\tCAsyncFileHandle::io_callback(function, result, return_data);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCPs2AsyncFileHandle::non_cache_aligned_data_copy(SFileIOResultPacket *p_result, bool last_packet)\r\n{\r\n\tDbg_Assert(p_result->m_non_aligned_data_size > 0);\r\n\t\r\n\tint request_id = p_result->m_header.opt;\r\n\tconst SRequest *p_request = get_request(request_id);\r\n\tDbg_Assert(p_request);\r\n\tDbg_Assert(p_request->mp_buffer);\r\n\r\n\t// Check if it goes at the start or end\r\n\tif (last_packet)\r\n\t{\r\n\t\t// end of buffer\r\n\t\tmemcpy((void *) ((uint32) p_request->mp_buffer + (p_request->m_buffer_size - p_result->m_non_aligned_data_size)),\r\n\t\t\t   p_result->m_non_aligned_data, p_result->m_non_aligned_data_size);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// beginning of buffer\r\n\t\tmemcpy(p_request->mp_buffer, p_result->m_non_aligned_data, p_result->m_non_aligned_data_size);\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCPs2AsyncFileHandle::add_request_id(int request_id, EAsyncFunctionType function, SFileIORequestPacket *p_packet)\r\n{\r\n\tif (m_num_open_requests >= NUM_REQUESTS)\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Too many open requests for file handle\"));\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// We must disable interrupts here so that the IO interrupts don't change things underneath us.\r\n\tDI();\r\n\r\n\t// Save buffer info if it is a read\r\n\tif (p_packet->m_request.m_command == FILEIO_READ)\r\n\t{\r\n\t\tm_open_requests[m_num_open_requests].mp_buffer = (uint8 *) p_packet->m_request.m_param.m_rw.m_buffer;\r\n\t\tm_open_requests[m_num_open_requests].m_buffer_size = p_packet->m_request.m_param.m_rw.m_size;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_open_requests[m_num_open_requests].mp_buffer = NULL;\r\n\t\tm_open_requests[m_num_open_requests].m_buffer_size = 0;\r\n\t}\r\n\r\n\tm_open_requests[m_num_open_requests].m_request_id = request_id;\r\n\tm_open_requests[m_num_open_requests++].m_function = function;\r\n\r\n\t// And re-enable interrupts\r\n\tEI();\r\n\r\n\t//scePrintf(\"Adding request %d to entry #%d for %x with busy %d\\n\", request_id, (m_num_open_requests-1), this, get_busy_count());\r\n\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nEAsyncFunctionType\tCPs2AsyncFileHandle::get_request_function(int request_id) const\r\n{\r\n\t// Find request id in list\r\n\tfor (int i = 0; i < m_num_open_requests; i++)\r\n\t{\r\n\t\tif (m_open_requests[i].m_request_id == request_id)\r\n\t\t{\r\n\t\t\treturn m_open_requests[i].m_function;\r\n\t\t}\r\n\t}\r\n\r\n\t// Request not found\r\n\tDbg_MsgAssert(0, (\"Can't find request %d on %x\", request_id, this));\r\n\treturn FUNC_IDLE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst CPs2AsyncFileHandle::SRequest *\tCPs2AsyncFileHandle::get_request(int request_id) const\r\n{\r\n\t// Find request id in list\r\n\tfor (int i = 0; i < m_num_open_requests; i++)\r\n\t{\r\n\t\tif (m_open_requests[i].m_request_id == request_id)\r\n\t\t{\r\n\t\t\treturn &(m_open_requests[i]);\r\n\t\t}\r\n\t}\r\n\r\n\t// Request not found\r\n\tDbg_MsgAssert(0, (\"Can't find request %d on %x\", request_id, this));\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCPs2AsyncFileHandle::clear_request_id(int request_id)\r\n{\r\n\tif (m_num_open_requests <= 0)\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Can't clear request: Open request list empty\"));\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Find request id in list\r\n\tfor (int i = 0; i < m_num_open_requests; i++)\r\n\t{\r\n\t\tif (m_open_requests[i].m_request_id == request_id)\r\n\t\t{\r\n\t\t\t// Just move end of list to here\r\n\t\t\tm_open_requests[i] = m_open_requests[--m_num_open_requests];\r\n\t\t\t//scePrintf(\"Clearing request %d from entry #%d\\n\", request_id, i);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\t// Request not found\r\n\tDbg_MsgAssert(0, (\"Can't clear request: Not found\"));\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCPs2AsyncFileHandle::plat_init()\r\n{\r\n\tm_file_handle_index = -1;\r\n\tm_num_open_requests = 0;\r\n\tmp_non_aligned_buffer = NULL;\r\n\tmp_temp_aligned_buffer = NULL;\r\n\tmp_temp_aligned_buffer_base = NULL;\r\n}\r\n\r\nvolatile bool\t\tCPs2AsyncFileHandle::plat_is_done()\r\n{\r\n\t//Dbg_MsgAssert(m_file_handle_index != -1, (\"Invalid IOP file handle index: %d\", m_file_handle_index));\r\n\r\n\treturn false;\r\n}\r\n\r\nvolatile bool\t\tCPs2AsyncFileHandle::plat_is_busy()\r\n{\r\n\t//Dbg_MsgAssert(m_file_handle_index != -1, (\"Invalid IOP file handle index: %d\", m_file_handle_index));\r\n\r\n\treturn false;\r\n}\r\n\r\nbool\t\t\t\tCPs2AsyncFileHandle::plat_is_eof() const\r\n{\r\n\t//Dbg_MsgAssert(m_file_handle_index != -1, (\"Invalid IOP file handle index: %d\", m_file_handle_index));\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCPs2AsyncFileHandle::plat_set_priority( int priority )\r\n{\r\n\t//Dbg_MsgAssert(m_file_handle_index != -1, (\"Invalid IOP file handle index: %d\", m_file_handle_index));\r\n\r\n\t// Now send the packet\r\n\tSFileIORequestPacket set_packet __attribute__ ((aligned(16)));\r\n\r\n\tset_packet.m_request.m_command\t\t\t\t\t\t= FILEIO_SET;\r\n\tset_packet.m_request.m_param.m_set.m_file_handle\t= m_file_handle_index;\r\n\tset_packet.m_request.m_param.m_set.m_variable\t\t= FILEIO_VAR_PRIORITY;\r\n\tset_packet.m_request.m_param.m_set.m_value\t\t\t= priority;\r\n\r\n\tCFileIOManager::sSendCommand(&set_packet, this, true);\r\n\r\n\tif (m_blocking)\r\n\t{\r\n\t\tWaitForIO();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCPs2AsyncFileHandle::plat_set_stream( bool stream )\r\n{\r\n\t//Dbg_MsgAssert(m_file_handle_index != -1, (\"Invalid IOP file handle index: %d\", m_file_handle_index));\r\n\r\n\t// Now send the packet\r\n\tSFileIORequestPacket set_packet __attribute__ ((aligned(16)));\r\n\r\n\tset_packet.m_request.m_command\t\t\t\t\t\t= FILEIO_SET;\r\n\tset_packet.m_request.m_param.m_set.m_file_handle\t= m_file_handle_index;\r\n\tset_packet.m_request.m_param.m_set.m_variable\t\t= FILEIO_VAR_STREAM;\r\n\tset_packet.m_request.m_param.m_set.m_value\t\t\t= stream;\r\n\r\n\tCFileIOManager::sSendCommand(&set_packet, this, true);\r\n\r\n\tif (m_blocking)\r\n\t{\r\n\t\tWaitForIO();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCPs2AsyncFileHandle::plat_set_destination( EAsyncMemoryType destination )\r\n{\r\n\t//Dbg_MsgAssert(m_file_handle_index != -1, (\"Invalid IOP file handle index: %d\", m_file_handle_index));\r\n\r\n\t// Now send the packet\r\n\tSFileIORequestPacket set_packet __attribute__ ((aligned(16)));\r\n\r\n\tset_packet.m_request.m_command\t\t\t\t\t\t= FILEIO_SET;\r\n\tset_packet.m_request.m_param.m_set.m_file_handle\t= m_file_handle_index;\r\n\tset_packet.m_request.m_param.m_set.m_variable\t\t= FILEIO_VAR_DESTINATION;\r\n\tset_packet.m_request.m_param.m_set.m_value\t\t\t= destination;\r\n\r\n\tCFileIOManager::sSendCommand(&set_packet, this, true);\r\n\r\n\tif (m_blocking)\r\n\t{\r\n\t\tWaitForIO();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCPs2AsyncFileHandle::plat_set_buffer_size( size_t buffer_size )\r\n{\r\n\t//Dbg_MsgAssert(m_file_handle_index != -1, (\"Invalid IOP file handle index: %d\", m_file_handle_index));\r\n\r\n\t// Now send the packet\r\n\tSFileIORequestPacket set_packet __attribute__ ((aligned(16)));\r\n\r\n\tset_packet.m_request.m_command\t\t\t\t\t\t= FILEIO_SET;\r\n\tset_packet.m_request.m_param.m_set.m_file_handle\t= m_file_handle_index;\r\n\tset_packet.m_request.m_param.m_set.m_variable\t\t= FILEIO_VAR_BUFFER_SIZE;\r\n\tset_packet.m_request.m_param.m_set.m_value\t\t\t= buffer_size;\r\n\r\n\tCFileIOManager::sSendCommand(&set_packet, this, true);\r\n\r\n\tif (m_blocking)\r\n\t{\r\n\t\tWaitForIO();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCPs2AsyncFileHandle::plat_set_blocking( bool block )\r\n{\r\n\t// IOP doesn't need to be notified\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nsize_t\t\t\t\tCPs2AsyncFileHandle::plat_load(void *p_buffer)\r\n{\r\n\t// This function will just get the file size and do one big read\r\n\t// It is not truly asynchronous now because of the seek wait\r\n\t//Dbg_MsgAssert(m_file_handle_index != -1, (\"Invalid IOP file handle index: %d\", m_file_handle_index));\r\n\r\n\tif (m_position != 0)\r\n\t{\r\n\t\tShowAsyncInfo(\"plat_load: Doing seek.\\n\");\r\n\t\t// Now put at the beginning\r\n\t\tSeek(0, SEEK_SET);\r\n\t\tWaitForIO();\r\n\r\n\t\tm_current_function = FUNC_LOAD;\r\n\t}\r\n\r\n\tShowAsyncInfo(\"plat_load: Reading into buffer %x.\\n\", p_buffer);\r\n\t// And do the read\r\n\treturn plat_read(p_buffer, 1, GetFileSize());\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nsize_t\t\t\t\tCPs2AsyncFileHandle::plat_read(void *p_buffer, size_t size, size_t count)\r\n{\r\n\t//Dbg_MsgAssert(m_file_handle_index != -1, (\"Invalid IOP file handle index: %d\", m_file_handle_index));\r\n\t//Dbg_MsgAssert((((uint32) p_buffer) & 0xF) == 0, (\"Buffer %x needs to be quadword aligned\", p_buffer));\r\n\r\n\t// Now send the packet\r\n\tSFileIORequestPacket read_packet __attribute__ ((aligned(16)));\r\n\r\n\tuint32 non_aligned_cache_start_bytes = 0;\r\n\tuint32 non_aligned_cache_end_bytes = 0;\r\n\r\n\t// Read in non-aligned bytes first (this is a temp hack)\r\n\tif (m_mem_destination == MEM_EE)\r\n\t{\r\n\t\t// only look for 16-byte alignment here\r\n\t\tbool non_aligned_bytes = ((uint32) p_buffer) & 0xF;\r\n\r\n\t\t// Also check to see if we aren't cache aligned on either end of a small buffer, since we assume the\r\n\t\t// cache alignment problem is at the end of a small buffer.\r\n\t\tint non_aligned_cache_bytes = ((uint32) p_buffer) & FILEIO_CACHE_BLOCK_NONALIGN_MASK;\r\n\t\tif (non_aligned_cache_bytes)\r\n\t\t{\r\n\t\t\tnon_aligned_cache_bytes = FILEIO_CACHE_BLOCK_SIZE - non_aligned_cache_bytes;\r\n\t\t}\r\n\t\t//bool non_aligned_cache_size = ((size * count) - non_aligned_cache_bytes) & FILEIO_CACHE_BLOCK_NONALIGN_MASK;\r\n\r\n\t\tif (non_aligned_bytes || ((non_aligned_cache_bytes /*|| non_aligned_cache_size*/) && (size * count) < FILEIO_BUFFER_SIZE))\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(!mp_temp_aligned_buffer_base, (\"Handling two small reads in succession not implemented yet\"));\r\n\r\n\t\t\tint aligned_size = ((size * count) + (2 * (FILEIO_CACHE_BLOCK_SIZE - 1))) & FILEIO_CACHE_BLOCK_ALIGN_MASK;\r\n\t\t\tmp_non_aligned_buffer = (uint8 *) p_buffer;\r\n\t\t\tmp_temp_aligned_buffer_base = CPs2AsyncFileLoader::sGetBuffer(aligned_size);\r\n\t\t\tmp_temp_aligned_buffer = (uint8 *) (((uint32) mp_temp_aligned_buffer_base + (FILEIO_CACHE_BLOCK_SIZE - 1)) & FILEIO_CACHE_BLOCK_ALIGN_MASK);\r\n\t\t\tp_buffer = mp_temp_aligned_buffer;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Now check for cache-alignment problems that will be handled with the messages\r\n\t\t\tnon_aligned_cache_start_bytes = (((uint32) p_buffer) & FILEIO_CACHE_BLOCK_NONALIGN_MASK);\r\n\t\t\tif (non_aligned_cache_start_bytes)\r\n\t\t\t{\r\n\t\t\t\tnon_aligned_cache_start_bytes = FILEIO_CACHE_BLOCK_SIZE - non_aligned_cache_start_bytes;\r\n\t\t\t}\r\n\t\t\tnon_aligned_cache_end_bytes = ((size * count) - non_aligned_cache_start_bytes) & FILEIO_CACHE_BLOCK_NONALIGN_MASK;\r\n\t\t}\r\n\t}\r\n\r\n\tread_packet.m_request.m_command\t\t\t\t\t\t\t\t = FILEIO_READ;\r\n\tread_packet.m_request.m_param.m_rw.m_file_handle\t\t\t = m_file_handle_index;\r\n\tread_packet.m_request.m_param.m_rw.m_buffer\t\t\t\t\t = p_buffer;\r\n\tread_packet.m_request.m_param.m_rw.m_size\t\t\t\t\t = size * count;\r\n\tread_packet.m_request.m_param.m_rw.m_non_aligned_start_bytes = non_aligned_cache_start_bytes;\r\n\tread_packet.m_request.m_param.m_rw.m_non_aligned_end_bytes\t = non_aligned_cache_end_bytes;\r\n\r\n\t// Mark as busy before sending command\r\n\tinc_busy_count();\r\n\r\n\t// Garrett (4/18/03): According to the Sony Newsgroups, a FlushCache is not needed if only 1 packet is sent.\r\n\t// Only the additional packet needs the flush.  I think this was helping the issue of non-64 byte aligned\r\n\t// read buffers.  We should try taking this out after the buffers are aligned.\r\n\tFlushCache(WRITEBACK_DCACHE);\t\t// This one is needed, but I think invalidating the cache will work, instead\r\n\r\n\tCFileIOManager::sSendCommand(&read_packet, this, true);\r\n\r\n\tDbg_Assert(((non_aligned_cache_start_bytes == 0) || (non_aligned_cache_end_bytes == 0)) || ((size * count) >= FILEIO_BUFFER_SIZE));\r\n\r\n\tif (m_blocking)\r\n\t{\r\n\t\treturn WaitForIO();\r\n\t} else {\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nsize_t\t\t\t\tCPs2AsyncFileHandle::plat_write(void *p_buffer, size_t size, size_t count)\r\n{\r\n\t//Dbg_MsgAssert(m_file_handle_index != -1, (\"Invalid IOP file handle index: %d\", m_file_handle_index));\r\n\tDbg_MsgAssert((((uint32) p_buffer) & 0xF) == 0, (\"Buffer %x needs to be quadword aligned\", p_buffer));\r\n\r\n\t// Now send the packet\r\n\tSFileIORequestPacket write_packet __attribute__ ((aligned(16)));\r\n\r\n\twrite_packet.m_request.m_command\t\t\t\t\t= FILEIO_WRITE;\r\n\twrite_packet.m_request.m_param.m_rw.m_file_handle\t= m_file_handle_index;\r\n\twrite_packet.m_request.m_param.m_rw.m_buffer\t\t= p_buffer;\r\n\twrite_packet.m_request.m_param.m_rw.m_size\t\t\t= size * count;\r\n\r\n\t// Mark as busy before sending command\r\n\tinc_busy_count();\r\n\r\n\tFlushCache(WRITEBACK_DCACHE);\t\t// This one is needed, but I think invalidating the cache will work, instead\r\n\r\n\tint req_id = CFileIOManager::sSendCommand(&write_packet, this, true);\r\n\r\n\t// Wait for result\r\n\tCFileIOManager::sWaitRequestCompletion(req_id);\r\n\r\n\treturn CFileIOManager::sGetRequestResult(write_packet.m_header.opt);\r\n}\r\n\r\nchar *\t\t\t\tCPs2AsyncFileHandle::plat_get_s(char *p_buffer, int maxlen)\r\n{\r\n\t//Dbg_MsgAssert(m_file_handle_index != -1, (\"Invalid IOP file handle index: %d\", m_file_handle_index));\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\t\tCPs2AsyncFileHandle::plat_seek(long offset, int origin)\r\n{\r\n\t//Dbg_MsgAssert(m_file_handle_index != -1, (\"Invalid IOP file handle index: %d\", m_file_handle_index));\r\n\r\n\t// Now send the packet\r\n\tSFileIORequestPacket seek_packet __attribute__ ((aligned(16)));\r\n\r\n\tseek_packet.m_request.m_command\t\t\t\t\t\t= FILEIO_SEEK;\r\n\tseek_packet.m_request.m_param.m_seek.m_file_handle\t= m_file_handle_index;\r\n\tseek_packet.m_request.m_param.m_seek.m_offset\t\t= offset;\r\n\tseek_packet.m_request.m_param.m_seek.m_origin\t\t= origin;\r\n\r\n\t// Mark as busy before sending command\r\n\tinc_busy_count();\r\n\r\n\tCFileIOManager::sSendCommand(&seek_packet, this, true);\r\n\r\n\tif (m_blocking)\r\n\t{\r\n\t\treturn WaitForIO();\r\n\t} else {\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCPs2AsyncFileHandle::plat_open(const char *filename)\r\n{\r\n\t// Init vars\r\n\tm_position = 0;\r\n\r\n\t// Now send the packet\r\n\tconst char *p_continued_filename = NULL;\r\n\tSFileIORequestPacket open_packet __attribute__ ((aligned(16)));\r\n\r\n\topen_packet.m_request.m_command\t\t\t\t\t\t\t\t\t\t\t= FILEIO_OPEN;\r\n\tif (Config::CD())\r\n\t{\r\n\t\tif ( !gpHed )\r\n\t\t{\r\n\t\t\treturn ( false );\r\n\t\t}\r\n\t\tSHedFile *tempHed = FindFileInHed( filename, gpHed );\r\n\t\tif ( !tempHed )\r\n\t\t{\r\n\t\t\t//Dbg_MsgAssert( 0,( \"File %s cannot be found in Hed file.\", filename ));\r\n\t\t\tDbg_Message( \"File %s cannot be found in Hed file.\", filename );\r\n\t\t\treturn ( false );\r\n\t\t}\r\n\r\n\t\tm_file_size = tempHed->GetFileSize();\r\n\r\n\t\topen_packet.m_request.m_param.m_open.m_file.m_raw_name.m_sector_number\t= gWadLSN + (tempHed->Offset / SECTOR_SIZE);\r\n\t\topen_packet.m_request.m_param.m_open.m_file.m_raw_name.m_file_size\t\t= m_file_size;\r\n\t\topen_packet.m_request.m_param.m_open.m_host_read \t\t\t\t\t\t= FILEIO_HOSTOPEN_FALSE;\r\n\r\n\t\tShowAsyncInfo(\"Sending open command for file %s of size %d and offset %d at sector %d\\n\", filename, m_file_size, tempHed->Offset, gWadLSN + (tempHed->Offset / SECTOR_SIZE));\r\n\t} else {\r\n\t\t//Dbg_MsgAssert(strlen(filename) < FILEIO_MAX_FILENAME_SIZE, (\"Can't open file %s: name longer than %d chars\", filename, FILEIO_MAX_FILENAME_SIZE - 1));\r\n\r\n\t\t// Copy filename and check if we need to insert a \"host0:\" into the name\r\n\t\tuint chars_copied = FILEIO_MAX_FILENAME_SIZE - 1;\r\n\t\tif (strchr(filename, ':'))\r\n\t\t{\r\n\t\t\tstrncpy(open_packet.m_request.m_param.m_open.m_file.m_filename, filename, chars_copied);\r\n\t\t} else {\r\n\t\t\t//Dbg_MsgAssert(strlen(filename) < (FILEIO_MAX_FILENAME_SIZE - 5), (\"Can't open file %s: name longer than %d chars\", filename, FILEIO_MAX_FILENAME_SIZE - 6));\r\n\t\t\tchars_copied -= 5;\r\n\t\t\tstrcpy(open_packet.m_request.m_param.m_open.m_file.m_filename, \"host:\");\r\n\t\t\tstrncpy(&open_packet.m_request.m_param.m_open.m_file.m_filename[5], filename, chars_copied);\r\n\t\t}\r\n\r\n\t\t// Check for long filename\r\n\t\tif (chars_copied < strlen(filename))\r\n\t\t{\r\n\t\t\tp_continued_filename = &(filename[chars_copied]);\r\n\t\t\topen_packet.m_request.m_param.m_open.m_host_read = FILEIO_HOSTOPEN_EXTEND_NAME;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\topen_packet.m_request.m_param.m_open.m_host_read = FILEIO_HOSTOPEN_TRUE;\r\n\t\t}\r\n\r\n\r\n\t\tShowAsyncInfo(\"Sending host open command for file %s\\n\", filename);\r\n\t}\r\n\topen_packet.m_request.m_param.m_open.m_memory_dest \t\t\t\t\t\t= m_mem_destination;\r\n\topen_packet.m_request.m_param.m_open.m_buffer_size \t\t\t\t\t\t= m_buffer_size;\r\n\topen_packet.m_request.m_param.m_open.m_priority \t\t\t\t\t\t= m_priority;\r\n\topen_packet.m_request.m_param.m_open.m_attributes\t\t\t\t\t\t= 0;\t\t// need to define this\r\n\r\n\t// Mark as busy before sending command\r\n\tinc_busy_count();\r\n\r\n\tuint request_id = CFileIOManager::sSendCommand(&open_packet, this, true);\r\n\r\n\tif (p_continued_filename)\r\n\t{\r\n\t\tDbg_MsgAssert(strlen(p_continued_filename) < FILEIO_MAX_FILENAME_SIZE, (\"Can't open file %s: name longer than %d chars\", filename, (FILEIO_MAX_FILENAME_SIZE - 1) * 2));\r\n\t\tstrcpy(open_packet.m_request.m_param.m_open.m_file.m_filename, p_continued_filename);\r\n\r\n\t\topen_packet.m_request.m_command\t= FILEIO_CONT;\r\n\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tuint cont_request_id = \r\n\t\t#endif\r\n\t\tCFileIOManager::sSendCommand(&open_packet, this, true, request_id);\r\n\t\tDbg_Assert(cont_request_id == request_id);\r\n\t}\r\n\r\n\tif (m_blocking)\r\n\t{\r\n\t\treturn WaitForIO() >= 0;\r\n\t} else {\r\n\t\t// Copy request ID into file handle to use as temp file handle\r\n\t\tm_file_handle_index = (int) (FILEIO_TEMP_HANDLE_FLAG | request_id);\r\n\t\treturn true;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCPs2AsyncFileHandle::raw_open(unsigned int lsn, bool blocking, int priority)\r\n{\r\n\tDbg_MsgAssert(!IsBusy(), (\"Can't open raw file %d: asynchronous file handle already busy.\", lsn));\r\n\tDbg_MsgAssert(!mp_pre_file, (\"Can't open raw file %d: already open as a PRE file.\", lsn));\r\n\r\n\t// Make sure we are using the CD\r\n\tif (!Config::CD())\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Raw Open not supported in host mode\"));\r\n\t\treturn false;\r\n\t}\r\n\r\n\tm_priority = priority;\r\n\tm_blocking = blocking;\r\n\r\n\tm_current_function = FUNC_OPEN;\r\n\r\n\t// Init vars\r\n\tm_position = 0;\r\n\r\n\t// Now send the packet\r\n\tSFileIORequestPacket open_packet __attribute__ ((aligned(16)));\r\n\r\n\t// Make it the max file size since a the WADs don't keep track of how big they are\r\n\tm_file_size = MAX_FILE_SIZE;\r\n\r\n\topen_packet.m_request.m_command\t\t\t\t\t\t\t\t\t\t\t= FILEIO_OPEN;\r\n\topen_packet.m_request.m_param.m_open.m_file.m_raw_name.m_sector_number\t= lsn;\r\n\topen_packet.m_request.m_param.m_open.m_file.m_raw_name.m_file_size\t\t= m_file_size;\r\n\topen_packet.m_request.m_param.m_open.m_host_read \t\t\t\t\t\t= FILEIO_HOSTOPEN_FALSE;\r\n\topen_packet.m_request.m_param.m_open.m_memory_dest \t\t\t\t\t\t= m_mem_destination;\r\n\topen_packet.m_request.m_param.m_open.m_buffer_size \t\t\t\t\t\t= m_buffer_size;\r\n\topen_packet.m_request.m_param.m_open.m_priority \t\t\t\t\t\t= m_priority;\r\n\topen_packet.m_request.m_param.m_open.m_attributes\t\t\t\t\t\t= 0;\t\t// need to define this\r\n\r\n\tShowAsyncInfo(\"Sending raw open command for file of size %d at sector %d\\n\", m_file_size, lsn);\r\n\r\n\t// Mark as busy before sending command\r\n\tinc_busy_count();\r\n\r\n\tuint request_id = CFileIOManager::sSendCommand(&open_packet, this, true);\r\n\r\n\tif (m_blocking)\r\n\t{\r\n\t\treturn WaitForIO() >= 0;\r\n\t} else {\r\n\t\t// Copy request ID into file handle to use as temp file handle\r\n\t\tm_file_handle_index = (int) (FILEIO_TEMP_HANDLE_FLAG | request_id);\r\n\t\treturn true;\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCPs2AsyncFileHandle::plat_close()\r\n{\r\n\t//Dbg_MsgAssert(m_file_handle_index != -1, (\"Invalid IOP file handle index: %d\", m_file_handle_index));\r\n\r\n\t// Now send the packet\r\n\tSFileIORequestPacket close_packet __attribute__ ((aligned(16)));\r\n\r\n\tclose_packet.m_request.m_command\t\t\t\t\t\t= FILEIO_CLOSE;\r\n\tclose_packet.m_request.m_param.m_close.m_file_handle\t= m_file_handle_index;\r\n\r\n\t// Mark as busy before sending command\r\n\tinc_busy_count();\r\n\r\n\tCFileIOManager::sSendCommand(&close_packet, this, true);\r\n\r\n\tm_file_handle_index = -1;\r\n\r\n\tif (m_blocking)\r\n\t{\r\n\t\treturn WaitForIO();\r\n\t} else {\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\nCPs2AsyncFileLoader::SAlignBuffer\tCPs2AsyncFileLoader::s_buffer_list[BUFFER_LIST_SIZE];\r\n//volatile int\t\tCPs2AsyncFileLoader::s_free_buffer_list_size = 0;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCAsyncFileHandle *\tCPs2AsyncFileLoader::sRawOpen( unsigned int lsn, bool blocking, int priority )\r\n{\r\n\tCPs2AsyncFileHandle *p_file_handle = static_cast<CPs2AsyncFileHandle *>(s_get_file_handle());\r\n\r\n\tif (p_file_handle)\r\n\t{\r\n\t\tif (!p_file_handle->raw_open(lsn, blocking, priority))\r\n\t\t{\r\n\t\t\t//Dbg_MsgAssert(0, (\"Error opening Async file %s\", filename));\r\n\t\t\ts_free_file_handle(p_file_handle);\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\r\n\t\treturn p_file_handle;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Out of Async handles\"));\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint8 *\t\t\t\tCPs2AsyncFileLoader::sGetBuffer( uint size )\r\n{\r\n#if 0\r\n\tif (size > ALIGN_BUFFER_SIZE)\r\n\t{\r\n\t\tDbg_Message(\"sGetBuffer() is trying to allocate %d.  Max buffer size is %d\", size, ALIGN_BUFFER_SIZE);\r\n\t\tDbg_MsgAssert(0, (\"sGetBuffer() is trying to allocate %d.  Max buffer size is %d\", size, ALIGN_BUFFER_SIZE));\r\n\t}\r\n\r\n\tif (s_free_buffer_list_size == 0)\r\n\t{\r\n\t\tDbg_Message(\"sGetBuffer() out of buffers\");\r\n\t\tDbg_MsgAssert(0, (\"sGetBuffer() out of buffers\"));\r\n\t}\r\n#endif\r\n\r\n\t//Dbg_Message(\"***** Getting async buffer of size %d\", size);\r\n\r\n\tvolatile uint8 *p_buffer = NULL;\r\n\t// Make sure interrupts are off\r\n\tDI();\r\n\tfor (int i = 0; i < BUFFER_LIST_SIZE; i++)\r\n\t{\r\n\t\tif ((s_buffer_list[i].m_size >= size) && !s_buffer_list[i].m_used)\r\n\t\t{\r\n\t\t\tp_buffer = s_buffer_list[i].mp_buffer;\r\n\t\t\ts_buffer_list[i].m_used = true;\r\n\t\t}\r\n\t}\r\n\tEI();\r\n\r\n\tDbg_MsgAssert(p_buffer, (\"Couldn't allocate align buffer of size %d\", size));\r\n\r\n\treturn (uint8 *) p_buffer;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCPs2AsyncFileLoader::sAddBufferToFreeList( uint8 *p_dealloc_buffer )\r\n{\r\n\t// Make sure interrupts are off\r\n\tDI();\r\n\r\n\tsIAddBufferToFreeList(p_dealloc_buffer);\r\n\r\n\tEI();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCPs2AsyncFileLoader::sIAddBufferToFreeList( uint8 *p_dealloc_buffer )\r\n{\r\n\t//scePrintf(\"***** Freeing async buffer\\n\");\r\n\r\n#if 0 //def __NOPT_ASSERT__\r\n\tif (s_free_buffer_list_size >= FREE_LIST_SIZE)\r\n\t{\r\n\t\tscePrintf(\"CPs2AsyncFileLoader::sIAddBufferToFreeList(): Free list full.  Tell Garrett.\\n\");\r\n\t\twhile (s_free_buffer_list_size >= FREE_LIST_SIZE)\t\t// We are basically stuck here\r\n\t\t\t;\r\n\t}\r\n#endif // __NOPT_ASSERT__\r\n\r\n\tfor (int i = 0; i < BUFFER_LIST_SIZE; i++)\r\n\t{\r\n\t\tif (s_buffer_list[i].mp_buffer == p_dealloc_buffer)\r\n\t\t{\r\n#ifdef __NOPT_ASSERT__\r\n\t\t\tif (!s_buffer_list[i].m_used)\r\n\t\t\t{\r\n\t\t\t\tscePrintf(\"CPs2AsyncFileLoader::sIAddBufferToFreeList(): Freeing a buffer that is already free.  Tell Garrett.\\n\");\r\n\t\t\t\twhile (1)\r\n\t\t\t\t\t;\r\n\t\t\t}\r\n#endif // __NOPT_ASSERT__\r\n\r\n\t\t\ts_buffer_list[i].m_used = false;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tscePrintf(\"CPs2AsyncFileLoader::sIAddBufferToFreeList(): Pointer wrong value.  Tell Garrett.\\n\");\r\n\twhile (1)\r\n\t\t;\r\n#endif // __NOPT_ASSERT__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCPs2AsyncFileLoader::sAllocateFreeListBuffers( )\r\n{\r\n\tint size_chunk = (ALIGN_MAX_BUFFER_SIZE - ALIGN_MIN_BUFFER_SIZE) / (BUFFER_LIST_SIZE - 1);\r\n\tfor (int i = 0; i < BUFFER_LIST_SIZE; i++)\r\n\t{\r\n\t\tint buffer_size = ALIGN_MIN_BUFFER_SIZE + (size_chunk * i);\r\n\t\ts_buffer_list[i].mp_buffer = new uint8[buffer_size];\r\n\t\ts_buffer_list[i].m_size = buffer_size;\r\n\t\ts_buffer_list[i].m_used = false;\r\n\t\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCPs2AsyncFileLoader::sDeallocateFreeListBuffers( )\r\n{\r\n\tDbg_Assert(0);\t\t// We shouldn't be calling this now\r\n\r\n#if 0 \r\n\t// Make sure interrupts are off\r\n\tDI();\r\n\r\n\tfor (int i = 0; i < s_free_buffer_list_size; i++)\r\n\t{\r\n\t\tdelete [] s_free_buffer_list[i];\r\n\t\ts_free_buffer_list[i] = NULL;\r\n\t}\r\n\ts_free_buffer_list_size = 0;\r\n\r\n\tEI();\r\n#endif\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\nsceSifCmdData\tCFileIOManager::s_cmdbuffer[FILEIO_NUM_COMMAND_HANDLERS];\r\n\r\nint\t\t\t\tCFileIOManager::s_cur_request_id = 0;\r\n\r\nCFileIOManager::SOpenRequest\tCFileIOManager::s_open_requests[NUM_REQUESTS];\r\nint\t\t\t\t\t\t\t\tCFileIOManager::s_free_request_index = 0;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*   CALLBACK                                                     */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \t\t\t\tCFileIOManager::s_result_callback(void *p, void *q)\r\n{\r\n\tSFileIOResultPacket *h = (SFileIOResultPacket *) p;\r\n\tint request_id = h->m_header.opt;\r\n\r\n\tSOpenRequest *p_request = s_find_request(request_id);\r\n\tDbg_MsgAssert(p_request, (\"Can't find request id # %d\", request_id));\r\n\r\n\tp_request->m_result = h->m_return_value;\r\n\tp_request->m_done = h->m_done;\r\n\r\n\t//scePrintf( \"Got IOP request %d result value %d back with done = %d\\n\", request_id, p_request->m_result, p_request->m_done );\r\n\r\n\t// Call file handle callback if request is completed\r\n\tif (p_request->mp_cur_file)\r\n\t{\r\n\t\t// Check if we got any non-aligned data back\r\n\t\tif (h->m_non_aligned_data_size > 0)\r\n\t\t{\r\n\t\t\tp_request->mp_cur_file->non_cache_aligned_data_copy(h, p_request->m_done);\r\n\t\t}\r\n\r\n\t\tif (p_request->m_done)\r\n\t\t{\r\n\t\t\t//p_request->mp_cur_file->io_callback(p_request->mp_cur_file->get_request_function(request_id), p_request->m_result, h->m_return_data);\r\n\t\t\tp_request->mp_cur_file->io_callback(p_request->mp_cur_file->get_request_function(request_id), p_request->m_result, (uint32) h);\r\n\t\t\tp_request->mp_cur_file->clear_request_id(request_id);\r\n\t\t}\r\n\t}\r\n\r\n\tShowAsyncInfo( \"Got IOP request %d result value %d back with done = %d\\n\", request_id, p_request->m_result, p_request->m_done );\r\n\t\r\n\tExitHandler();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCFileIOManager::SOpenRequest *\t\tCFileIOManager::s_find_request(int request_id)\r\n{\r\n\t// Start at the last used index, probably the one used\r\n\tint index = s_prev_open_index(s_free_request_index);\r\n\r\n\tSOpenRequest *p_start_request = &(s_open_requests[index]);\r\n\tSOpenRequest *p_request = p_start_request;\r\n\r\n\tdo\r\n\t{\r\n\t\tif (p_request->m_id == request_id)\r\n\t\t{\r\n\t\t\treturn p_request;\r\n\t\t}\r\n\t\t\r\n\t\tindex = s_prev_open_index(index);\r\n\t\tp_request = &(s_open_requests[index]);\r\n\t} while (p_request != p_start_request);\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCFileIOManager::sInit()\r\n{\r\n\t// Communicate with the IOP side\r\n    sceSifInitRpc(0);\r\n\tDI();\r\n\r\n\tShowAsyncInfo( \"Setting up Sif Cmd with FileIO IRX...\\n\" );\r\n\tsceSifSetCmdBuffer(&s_cmdbuffer[0], FILEIO_NUM_COMMAND_HANDLERS);\r\n\tsceSifAddCmdHandler(FILEIO_RESULT_COMMAND, s_result_callback, NULL);\r\n\r\n\tEI();\r\n\r\n\t// Clear out pending requests\r\n\tfor (int i = 0; i < NUM_REQUESTS; i++)\r\n\t{\r\n\t\ts_open_requests[i].m_done = true;\r\n\t\ts_open_requests[i].m_id = -1;\r\n\t\ts_open_requests[i].m_result = -1;\r\n\t}\r\n\ts_free_request_index = 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\t\tCFileIOManager::sSendCommand(SFileIORequestPacket *p_packet, CPs2AsyncFileHandle *p_file, bool wait_for_send, int continuation_request)\r\n{\r\n\tSOpenRequest *p_request;\r\n\r\n\tif (continuation_request >= 0)\r\n\t{\r\n\t\tp_request = s_find_request(continuation_request);\r\n\t\tDbg_MsgAssert(p_request, (\"Can't find open request %d to continue\", continuation_request));\r\n\r\n\t\t// Just in case they didn't wait before\r\n\t\tsWaitSendCompletion(p_request->m_id);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_request = &(s_open_requests[s_free_request_index]);\r\n\t\tDbg_MsgAssert(p_request->m_done, (\"Too many open requests\"));\r\n\t\ts_free_request_index = s_next_open_index(s_free_request_index);\r\n\r\n\t\tint request_id = s_cur_request_id++;\r\n\r\n\t\tp_request->m_done\t\t= false;\t\t// Callback will change it to true\r\n\t\tp_request->m_id\t\t\t= request_id;\r\n\t\tp_request->mp_cur_file\t= p_file;\r\n\t\tif (p_file)\r\n\t\t{\r\n\t\t\tp_file->add_request_id(request_id, p_file->m_current_function, p_packet);\r\n\t\t}\r\n\r\n\t\tp_packet->m_header.opt = request_id;\r\n\t}\r\n\r\n\tp_request->m_sif_cmd_id = sceSifSendCmd(FILEIO_REQUEST_COMMAND, p_packet, sizeof(SFileIORequestPacket), 0, 0, 0);\r\n\r\n\tif (wait_for_send)\r\n\t{\r\n\t\tsWaitSendCompletion(p_request->m_id);\r\n\t}\r\n\r\n\treturn p_request->m_id;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCFileIOManager::sWaitSendCompletion(int request_id)\r\n{\r\n\tSOpenRequest *p_request = s_find_request(request_id);\r\n\tDbg_MsgAssert(p_request, (\"Can't find request id # %d\", request_id));\r\n\r\n\twhile(sceSifDmaStat(p_request->m_sif_cmd_id) >= 0)\r\n\t\t;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCFileIOManager::sWaitRequestCompletion(int request_id)\r\n{\r\n\tSOpenRequest *p_request = s_find_request(request_id);\r\n\tDbg_MsgAssert(p_request, (\"Can't find request id # %d\", request_id));\r\n\r\n\twhile (!p_request->CommandDone())\r\n\t\t;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvolatile bool\t\tCFileIOManager::sCommandDone(int request_id)\r\n{\r\n\tSOpenRequest *p_request = s_find_request(request_id);\r\n\tDbg_MsgAssert(p_request, (\"Can't find request id # %d\", request_id));\r\n\r\n\treturn p_request->m_done;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\t\t\t\tCFileIOManager::sGetRequestResult(int request_id)\r\n{\r\n\tSOpenRequest *p_request = s_find_request(request_id);\r\n\tDbg_MsgAssert(p_request, (\"Can't find request id # %d\", request_id));\r\n\r\n\treturn p_request->m_result;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileLoader::s_plat_init()\r\n{\r\n\tfor (int i = 0; i < MAX_FILE_HANDLES; i++)\r\n\t{\r\n\t\tif (s_file_handles[i])\r\n\t\t{\r\n\t\t\ts_file_handles[i]->init();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ts_file_handles[i] = new CPs2AsyncFileHandle;\r\n\t\t}\r\n\t}\r\n\r\n\t// Allocate EE align buffers\r\n\tCPs2AsyncFileLoader::sAllocateFreeListBuffers();\r\n\r\n\t// Init the FileIO Manager\r\n\tCFileIOManager::sInit();\r\n\r\n\t// Now send the first packet\r\n\tSFileIORequestPacket init_packet __attribute__ ((aligned(16)));\r\n\r\n\tinit_packet.m_request.m_command\t\t\t\t\t\t= FILEIO_INIT;\r\n\tinit_packet.m_request.m_param.m_init.m_buffer_size\t= DEFAULT_BUFFER_SIZE;\r\n\tinit_packet.m_request.m_param.m_init.m_priority\t\t= DEFAULT_ASYNC_PRIORITY;\r\n\tinit_packet.m_request.m_param.m_init.m_memory_dest\t= DEFAULT_MEMORY_TYPE;\r\n\tinit_packet.m_request.m_param.m_init.m_init_cd_device = Config::CD();\r\n\r\n\tint req_id = CFileIOManager::sSendCommand(&init_packet, NULL, true);\r\n\r\n\tDbg_Message(\"Sending first init command to fileio.irx: waiting for completion\");\r\n\r\n\t// Wait for result (no async inits)\r\n\tCFileIOManager::sWaitRequestCompletion(req_id);\r\n\r\n\tDbg_Message(\"Sent first init command to fileio.irx.\");\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileLoader::s_plat_cleanup()\r\n{\r\n\tfor (int i = 0; i < MAX_FILE_HANDLES; i++)\r\n\t{\r\n\t\tif (s_file_handles[i])\r\n\t\t{\r\n\t\t\tdelete s_file_handles[i];\r\n\r\n\t\t\ts_file_handles[i] = NULL;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCAsyncFileLoader::s_plat_async_supported()\r\n{\r\n\t// Works on the PS2\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\t\t\t\tCAsyncFileLoader::s_plat_exist(const char *filename)\r\n{\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileLoader::s_plat_update(void)\r\n{\r\n\t//// Free any buffers let go during an interrupt\r\n\t//CPs2AsyncFileLoader::sDeallocateFreeListBuffers();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\t\t\tCAsyncFileLoader::s_plat_swap_callback_list()\r\n{\r\n\t// We must disable interrupts here so that the IO interrupts don't change things underneath us.\r\n\tDI();\r\n\r\n\ts_cur_callback_list_index = s_cur_callback_list_index ^ 1;\t// Swap Indexes\r\n\ts_new_io_completion = false;\t\t\t\t\t\t\t\t// And clear flag\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tbool new_list_clear = s_num_callbacks[s_cur_callback_list_index] == 0;\r\n#endif // __NOPT_ASSERT__\r\n\r\n\t// And re-enable interrupts\r\n\tEI();\r\n\r\n\tDbg_MsgAssert(new_list_clear, (\"Async IO swapped callback list isn't empty\"));\r\n}\r\n\r\n}\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/ngps/p_AsyncFilesys.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tFile\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t10/11/02\t-\tgrj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/p_AsyncFilesys.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_FILE_P_ASYNC_FILESYS_H\r\n#define\t__SYS_FILE_P_ASYNC_FILESYS_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sys/file/AsyncFilesys.h>\r\n#include <sys/file/ngps/FileIO/FileIO.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace File\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Forward declarations\r\nclass CFileIOManager;\r\nclass CPs2AsyncFileLoader;\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// The asynchronous file class\r\n//\r\nclass CPs2AsyncFileHandle : public CAsyncFileHandle\r\n{\r\npublic:\r\n\r\nprotected:\r\n\r\n\t\t\t\t\t\tCPs2AsyncFileHandle();\r\n\tvirtual \t\t\t~CPs2AsyncFileHandle();\r\n\r\nprivate:\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tNUM_REQUESTS = 16\r\n\t};\r\n\r\n\t// Request data\r\n\tstruct SRequest\r\n\t{\r\n\t\tint\t\t\t\t\tm_request_id;\r\n\t\tEAsyncFunctionType\tm_function;\r\n\t\tuint8 *\t\t\t\tmp_buffer;\r\n\t\tint\t\t\t\t\tm_buffer_size;\r\n\t};\r\n\r\n\t// Callback functions\r\n\tvirtual void\t\tio_callback(EAsyncFunctionType function, int result, uint32 data);\r\n\r\n\tvolatile int\t\tm_file_handle_index;\r\n\r\n\t// Open requests\r\n\tSRequest\t\t  \tm_open_requests[NUM_REQUESTS];\r\n\tvolatile int\t\tm_num_open_requests;\r\n\r\n\t// Non-aligned buffer IO\r\n\tuint8 *\t\t\t\tmp_non_aligned_buffer;\r\n\tuint8 *\t\t\t\tmp_temp_aligned_buffer;\r\n\tuint8 *\t\t\t\tmp_temp_aligned_buffer_base;\r\n\r\n\tbool\t\t\t\tadd_request_id(int request_id, EAsyncFunctionType function, SFileIORequestPacket *p_packet);\r\n\tEAsyncFunctionType\tget_request_function(int request_id) const;\r\n\tconst SRequest *\tget_request(int request_id) const;\r\n\tbool\t\t\t\tclear_request_id(int request_id);\r\n\r\n\t// PS2 only IO calls\r\n\tbool\t\t\t\traw_open(unsigned int lsn, bool blocking, int priority);\r\n\r\n\t// PS2 internal calls\r\n\tvoid\t\t\t\tnon_cache_aligned_data_copy(SFileIOResultPacket *p_result, bool last_packet);\r\n\r\n\t// platform-specific calls\r\n\tvirtual void\t\tplat_init( void );\r\n\r\n\tvirtual bool\t\tplat_open( const char *filename );\r\n\tvirtual bool\t\tplat_close( void );\r\n\r\n\tvirtual volatile bool\tplat_is_done( void );\r\n\tvirtual volatile bool\tplat_is_busy( void );\r\n\tvirtual bool\t\tplat_is_eof( void ) const;\r\n\r\n\tvirtual void\t\tplat_set_priority( int priority );\r\n\tvirtual void\t\tplat_set_stream( bool stream );\r\n\tvirtual void\t\tplat_set_destination( EAsyncMemoryType destination );\r\n\tvirtual void\t\tplat_set_buffer_size( size_t buffer_size );\r\n\tvirtual void\t\tplat_set_blocking( bool block );\r\n\r\n\tvirtual size_t\t\tplat_load( void *p_buffer );\r\n\tvirtual size_t\t\tplat_read( void *p_buffer, size_t size, size_t count );\r\n\tvirtual size_t\t\tplat_write( void *p_buffer, size_t size, size_t count );\r\n\tvirtual char *\t\tplat_get_s( char *p_buffer, int maxlen );\r\n\tvirtual int\t\t\tplat_seek( long offset, int origin );\r\n\r\n\t// Friends\r\n\tfriend CAsyncFileLoader;\r\n\tfriend CPs2AsyncFileLoader;\r\n\tfriend CFileIOManager;\r\n};\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// The interface to start and end async loads\r\n//\r\nclass CPs2AsyncFileLoader : public CAsyncFileLoader\r\n{\r\npublic:\r\n\t// Opens a \"file\" by specifying the starting logical sector number of a file\r\n\tstatic CAsyncFileHandle *\tsRawOpen( unsigned int lsn, bool blocking = true, int priority = DEFAULT_ASYNC_PRIORITY );\r\n\r\n\t// Deallocation of buffers cannot be done in interrupt mode.  The FileLoader update function will need to\r\n\t// clear them out.\r\n\tstatic void\t\t\t\t\tsAllocateFreeListBuffers( );\r\n\tstatic void\t\t\t\t\tsDeallocateFreeListBuffers( );\r\n\r\n\tstatic uint8 *\t\t\t\tsGetBuffer( uint size );\t\t\t\t\t\t\t\t// thread only\r\n\tstatic void\t\t\t\t\tsAddBufferToFreeList( uint8 *p_dealloc_buffer );\t\t// thread only\r\n\tstatic void\t\t\t\t\tsIAddBufferToFreeList( uint8 *p_dealloc_buffer );\t\t// interrupt only\r\n\r\nprivate:\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tALIGN_MAX_BUFFER_SIZE = 17000,\r\n\t\tALIGN_MIN_BUFFER_SIZE = 4096,\r\n\t\tBUFFER_LIST_SIZE = 2\r\n\t};\r\n\r\n\t// Buffer struct\r\n\tstruct SAlignBuffer\r\n\t{\r\n\t\tuint\t\t\t\t\tm_size;\r\n\t\tvolatile bool\t\t\tm_used;\r\n\t\tvolatile uint8 *\t\tmp_buffer;\r\n\t};\r\n\r\n\tstatic SAlignBuffer\t\t\ts_buffer_list[BUFFER_LIST_SIZE];\r\n//\tstatic volatile int\t\t\ts_free_buffer_list_size;\r\n};\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////\r\n// File IO manager that communicates with the IOP module\r\n//\r\nclass CFileIOManager\r\n{\r\npublic:\r\n\tstatic void\t\t\t\t\tsInit();\r\n\r\n\t// IOP command functions\r\n\tstatic int\t\t\t\t\tsSendCommand(SFileIORequestPacket *p_packet, CPs2AsyncFileHandle *p_file = NULL, bool wait_for_send = false,\r\n\t\t\t\t\t\t\t\t\t\t\t int continuation_request = -1);\r\n\tstatic void\t\t\t\t\tsWaitSendCompletion(int request_id);\r\n\tstatic void\t\t\t\t\tsWaitRequestCompletion(int request_id);\r\n\r\n\tstatic volatile bool\t\tsCommandDone(int request_id);\r\n\r\n\tstatic int\t\t\t\t\tsGetRequestResult(int request_id);\r\n\r\nprivate:\r\n\t// Constants\r\n\tenum\r\n\t{\r\n\t\tNUM_REQUESTS = 64\r\n\t};\r\n\r\n\tstruct SOpenRequest\r\n\t{\r\n\t\tinline volatile bool\tCommandDone();\r\n\r\n\t\tCPs2AsyncFileHandle *\tmp_cur_file;\r\n\t\tint\t\t\t\t\t\tm_id;\r\n\t\tint\t\t\t\t\t\tm_sif_cmd_id;\r\n\t\tvolatile bool \t\t\tm_done;\r\n\t\tvolatile int \t\t\tm_result;\r\n\t};\r\n\r\n\tstatic void \t\t\t\ts_result_callback(void *p, void *q);\r\n\r\n\tstatic int\t\t\t\t\ts_prev_open_index(int index) { return (index > 0) ? index - 1 : NUM_REQUESTS - 1; }\r\n\tstatic int\t\t\t\t\ts_next_open_index(int index) { return (index + 1) % NUM_REQUESTS; }\r\n\tstatic SOpenRequest *\t\ts_find_request(int request_id);\r\n\r\n\t// Data for the actual SifCmd transfers\r\n\tstatic sceSifCmdData \t\ts_cmdbuffer[FILEIO_NUM_COMMAND_HANDLERS];\r\n\r\n\tstatic int \t\t\t\t\ts_cur_request_id;\r\n\r\n\t// Open requests\r\n\tstatic SOpenRequest\t\t\ts_open_requests[NUM_REQUESTS];\r\n\tstatic int\t\t\t\t\ts_free_request_index;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline volatile bool\t\tCFileIOManager::SOpenRequest::CommandDone()\r\n{\r\n\treturn m_done;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace File\r\n\r\n#endif  // __SYS_FILE_P_ASYNC_FILESYS_H\r\n"
  },
  {
    "path": "Code/Sys/File/ngps/p_filesys.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSystem Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tFile IO (File) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_filesys.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPS2 File System\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdio.h>\r\n#include <string.h>\r\n#include <sifdev.h>\r\n#include <sifrpc.h>\r\n#include <libcdvd.h>\r\n#include <libdma.h>\r\n\r\n#include <core/defines.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/AsyncFilesys.h>\r\n#include <sys/file/PRE.h>\r\n#include <sys/file/ngps/hed.h>\r\n#include <sys/file/ngps/p_AsyncFilesys.h>\r\n#include <sys/config/config.h>\r\n\r\n#include <gel/music/music.h>\r\n#include <gel/scripting/symboltable.h>\r\n\r\n#include <dnas/dnas2.h>\r\n\r\n#ifdef\tPAL\r\n#define\t__DVD_ONLY__ 0\t\t\t\t// 0 = DVD or CD,  1 = Just DVD (for copy protection)\r\n#else\r\n#define\t__DVD_ONLY__ 0\t\t\t\t// 0 = DVD or CD,  1 = Just DVD (for copy protection)\r\n#endif\r\n\r\n#define ASYNC_QUICK_FILESYS 1\r\n#define ASYNC_HOST_FILESYS\t0\r\n#define DISABLE_QUICK_FILESYSTEM\t0\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace File\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef SECTOR_SIZE\r\n#define SECTOR_SIZE 2048\r\n#endif // SECTOR_SIZE\r\n\r\n\r\n\r\n// MEMOPT: If we run out of IOP memory again, it is possible that we could use the pcm buffer\r\n// (The one that is TOTAL_IOP_BUFFER_SIZE_NEEDED) for the file i/o, since probably music or \r\n// streams will not need to be playing when a file is loading.\r\n// That would free up 2048*48=98304 bytes!!\r\n#define FILESYS_NUM_SECTORS_IN_BUFFER\t\t\t48\r\n#define FILESYS_STREAM_BUFFER_NUM_PARTITIONS\t3\r\n#define FILESYS_IOP_BUFFER_SIZE\t\t\t\t\t( SECTOR_SIZE * FILESYS_NUM_SECTORS_IN_BUFFER )\r\n#define FILESYS_NUM_SECTORS_PER_READ\t\t\t16\r\n#define\tFILESYS_CD_READ_SIZE\t\t\t\t\t( SECTOR_SIZE * FILESYS_NUM_SECTORS_PER_READ )\r\n#define IOP_TO_EE_BUFFER_ALLIGNMENT\t\t\t\t64\r\n\r\n// Static globals:\r\nstatic void\t\t\t\t*gFilesysIOPStreamBuffer = NULL;\r\n//static char\t\t\t\t*gIOPToEEBuffer;\r\n\t   unsigned int\t\tgWadLSN = 0;          // Made global for p_AsyncFilesystem\r\nstatic bool\t\t\t\tgQuickFileSystemInitialzed = false;\r\nstatic bool\t\t\t\tgStreaming = false;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define READBUFFERSIZE (10240*5)\r\n\r\n// GJ:  I added this to track how many skyFiles are active\r\n// at any given time.  I am assuming that there's only one,\r\n// in which case I can just create one global instance\r\n// (previously, we were allocating it off the current heap,\r\n// which was causing me grief during the CAS loading process)\r\n//int g_fileOpenCount = 0;\r\n\r\nstruct skyFile\r\n{\r\n\t\r\n\t// the following must match the dumbSkyFile struct\r\n\t// in pre.cpp, or else pre file i/o won't work properly\r\n\tint\t\t\t\tgdfs;\r\n\tint32\t\t\tPOS;\r\n\tint32\t\t\tSOF;\r\n\r\n\t// the rest is skyFile-specific\r\n\tuint8\t\t\treadBuffer[READBUFFERSIZE];\r\n\tuint32\t\tbufferPos;\r\n\tbool\t\t\tbufferValid;\r\n\tbool\t\t\tlocked;\t\t\t// whether the skyfile is currently in use\r\n\t\r\n\t// Used when CD\r\n\tuint32\t\t\tWadOffset;\r\n\tconst char\t\t*pFilename;\r\n\t\r\n\t// Used when non-CD\r\n\t#define MAX_PFILESYS_NAME_SIZE 255\r\n\tchar filename[ MAX_PFILESYS_NAME_SIZE ];\r\n#if ASYNC_HOST_FILESYS\r\n\tCAsyncFileHandle *p_async_file;\r\n#endif\r\n};\r\n\r\n// At first, I assumed that only one skyfile could be open at\r\n// a time, but that's not true when testing streams from the\r\n// PC build.\r\n// pc builds need to have two (one for normal files, and one for streams)\r\n// GJ:  for THPS4, we increased this to 3, so that we can play multiple streams\r\nconst int MAXOPENFILES = 3;\r\n\r\n// Ken note: It used to be that MAXOPENFILES was defined to be 1 when __NOPT_CDROM__OLD\r\n// was set. Now that __NOPT_CDROM__OLD is not used anymore and CD() is used at runtime\r\n// instead, I made MAXOPENFILES always 2. Then, where MAXOPENFILES used to be used in the code\r\n// it now uses a var set to 1 or 2 depending on CD()\r\nstatic skyFile g_skyFile[MAXOPENFILES];\r\n\r\nskyFile* lock_skyfile( void )\r\n{\r\n\t// cd builds can only have one file open at any given time\r\n\tint max_open_files=Config::CD() ? 1:MAXOPENFILES;\r\n\t\r\n\tint i;\r\n\t// this tries to find an unlocked skyfile\r\n\tfor ( i = 0; i < max_open_files; i++ )\r\n\t{\r\n\t\tif ( !g_skyFile[i].locked )\r\n\t\t{\r\n\t\t\tg_skyFile[i].locked = true;\r\n\t\t\treturn &g_skyFile[i];\r\n\t\t}\r\n\t}\r\n\r\n\tif (!Config::CD())\r\n\t{\r\n\t\tDbg_Message( \"Here are the files currently open:\" );\r\n\t\tfor ( i = 0; i < max_open_files; i++ )\r\n\t\t{\r\n\t\t\tDbg_Message( \"%s\", g_skyFile[ i ].filename );\r\n\t\t}\r\n\t}\t\r\n\r\n\t// if we get here, that means that all the sky files were locked\r\n\tDbg_MsgAssert( 0, ( \"Trying to open too many files simultaneously (max=%d)\", max_open_files ) );\r\n\treturn NULL;\r\n}\r\n\r\nvoid unlock_skyfile( skyFile* pSkyFile )\r\n{\r\n\t// cd builds can only have one file open at any given time\r\n\tint max_open_files=Config::CD() ? 1:MAXOPENFILES;\r\n\t\r\n\r\n\t// this tries to find the sky file that the caller is referencing\r\n\tfor ( int i = 0; i < max_open_files; i++ )\r\n\t{\r\n\t\tif ( pSkyFile == &g_skyFile[i] )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( g_skyFile[i].locked, ( \"Trying to unlock a sky file too many times\" ) );\r\n\t\t\tg_skyFile[i].locked = false;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\t// if we get here, that means that the pointer didn't match one of the valid skyfiles\r\n\tDbg_MsgAssert( 0, ( \"Unrecognized sky file\" ) );\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic\tint32\t\t\ts_open_files = 0;\r\n\r\n// The header file (SKATE4.hed) used for looking up where files are within\r\n// SKATE4.wad\r\nSHed *gpHed=NULL;\t\t// Made global for p_AsyncFilesystem\r\nstatic int WadId=-1;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/* skyTransMode                                                   */\r\n/*                                                                */\r\n/* Attempt to convert a mode string to an open mode\t\t\t\t  */ \r\n/*                                                                */\r\n/* On entry  : access mode\t\t\t\t\t\t\t\t\t\t  */\r\n/* On exit   : integer mode\t\t\t\t\t\t\t\t\t\t  */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic int skyTransMode(const char *access)\r\n{\r\n\t\r\n\r\n\tint mode;\r\n\tchar *r;\r\n\tchar *w;\r\n\tchar *a;\r\n\tchar *plus;\r\n\tchar *n;\r\n\tchar *d;\r\n\r\n\t/* I add a couple of new characters for now:\r\n\t   n non-blocking mode\r\n\t   d no write back d cache */\r\n\r\n\tr = strrchr(access, (int)'r');\r\n\tw = strrchr(access, (int)'w');\r\n\ta = strrchr(access, (int)'a');\r\n\tplus = strrchr(access, (int)'+');\r\n\tn = strrchr(access, (int)'n');\r\n\td = strrchr(access, (int)'d');\r\n\r\n\tif (plus)\r\n\t\tmode = SCE_RDWR;\r\n\telse if (r)\r\n\t\tmode = SCE_RDONLY;\r\n\telse if (w)\r\n\t\tmode = SCE_WRONLY;\r\n\telse if (a)\r\n\t\tmode = SCE_WRONLY;\r\n\telse\r\n\t\treturn(0);\r\n\r\n\t/* later we will test for SCE_CREAT & !SCE_TRUNC as a seek to end of file */\r\n\tif (w)\r\n\t\tmode |= SCE_CREAT | SCE_TRUNC;\r\n\r\n\tif (a)\r\n\t\tmode |= SCE_CREAT;\r\n\r\n\tif (n)\r\n\t\tmode |= SCE_NOWAIT;\r\n\r\n\tif (d)\r\n\t\tDbg_MsgAssert( 0,( \"Hmm... gotta find out what SCE_NOWBDC was in previous library.\" ));\r\n//\t\tmode |= SCE_NOWBDC;\r\n\r\n\treturn(mode);\r\n}\r\n\r\nvoid StartStreaming( uint32 lsn )\r\n{\r\n\tDbg_MsgAssert( gFilesysIOPStreamBuffer,( \"IOP stream buffer not initialized\" ));\r\n\r\n\tsceCdSync(0);\t\t\t// Make sure there aren't any non-blocking CD reads happening\r\n\tPcm::StopStreams( );\t// Garrett: I found streamed sounds can skip when using the quick load\r\n//\tif ( Pcm::UsingCD( ) )\r\n//\t{\r\n//\t\tDbg_MsgAssert( 0,( \"File access forbidden while PCM audio is in progress.\" ));\r\n//\t}\r\n\tsceCdRMode mode;\r\n\tmode.trycount = 255;\r\n\tmode.spindlctrl = SCECdSpinNom;\r\n    mode.datapattern = SCECdSecS2048;\r\n\tmode.pad = 0;\r\n\twhile ( !( gStreaming = sceCdStStart( lsn, &mode ) ) )\r\n\t{\r\n\t\tprintf( \"aah ha! would have caused the crash!!!\\n\" );\r\n\t\tsceCdStop();\r\n\t\tsceCdSync(0);\r\n\t}\r\n}\r\n\r\nvoid StopStreaming( void )\r\n{\r\n\tif (!Config::CD())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tif ( gStreaming )\r\n\t{\r\n\t\twhile ( !sceCdStStop( ) )\r\n\t\t{\r\n\t\t\tprintf( \"sceCdStStop failed\\n\" );\r\n\t\t}\r\n\t}\r\n\tgStreaming = false;\r\n}\r\n\r\n\r\nuint32 CanFileBeLoadedQuickly( const char *filename )\r\n{\r\n#if DISABLE_QUICK_FILESYSTEM\r\n\treturn 0;\r\n#endif\r\n\r\n\tif (!Config::CD())\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\t\t\r\n\tif ( !gQuickFileSystemInitialzed )\r\n\t{\r\n\t\treturn ( 0 );\r\n\t}\r\n    if ( !gpHed )\r\n\t{\r\n\t\treturn ( 0 );\r\n\t}\r\n\tSHedFile *tempHed = FindFileInHed( filename, gpHed );\r\n\tif ( tempHed )\r\n\t\treturn ( tempHed->GetFileSize() );\r\n\treturn ( 0 );\r\n}\r\n\r\n#if ASYNC_QUICK_FILESYS == 0\r\nstatic void HandleCDStreamingError( uint32 lsn )\r\n{\r\n\t\r\n\tint err;\r\n\terr = sceCdGetError( );\r\n\tprintf( \"CD Error %d\\n\", err );\r\n\t// let's just stop everything, and try again fresh and new:\r\n\tsceCdBreak( );\r\n\tsceCdSync( 0 );\r\n\tStartStreaming( lsn );\r\n/*\tswitch ( err )\r\n\t{\r\n\t\tcase ( SCECdErNO ):\r\n\t\t\tbreak;\r\n\t\tcase ( SCECdErTRMOPN ):\r\n\t\t\tbreak;\r\n\t\tcase ( ):\r\n\t\t\tbreak;\r\n\t\tcase ( ):\r\n\t\t\tbreak;\r\n\t\tcase ( ):\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}*/\r\n}\r\n#endif // ASYNC_QUICK_FILESYS == 0\r\n\r\nbool LoadFileQuicklyPlease( const char *filename, uint8 *addr )\r\n{\r\n\tif (!Config::CD())\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif ( !gQuickFileSystemInitialzed )\r\n\t{\r\n\t\treturn ( false );\r\n\t}\r\n\t\t\r\n#if ASYNC_QUICK_FILESYS\r\n\r\n\tCAsyncFileHandle *p_handle = CAsyncFileLoader::sOpen(filename, false);\r\n\tif (p_handle)\r\n\t{\r\n\t\tp_handle->Load(addr);\r\n\t\tp_handle->WaitForIO();\r\n\t\tCAsyncFileLoader::sClose(p_handle);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0, (\"Didn't get handle pointer from async filesys for file %s\", filename));\r\n\t\treturn false;\r\n\t}\r\n\r\n#else\r\n\tDbg_MsgAssert( gFilesysIOPStreamBuffer,( \"IOP stream buffer not initialized\" ));\r\n\r\n\tif ( !gpHed )\r\n\t{\r\n\t\treturn ( false );\r\n\t}\r\n\r\n\tSHedFile *tempHed = FindFileInHed( filename, gpHed );\r\n\tif ( !tempHed )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"File cannot be loaded quickly.\" ));\r\n\t\treturn ( false );\r\n\t}\r\n\tuint32 bytesRequired = tempHed->GetFileSize();\r\n//\tuint32 offsetWithinBuffer = tempHed->Offset & ( SECTOR_SIZE - 1 );\r\n\tif ( tempHed->Offset & ( SECTOR_SIZE - 1 ) )\r\n\t{\r\n\t\tint i;\r\n\t\tfor ( i = 0; i != -1; i++ )\r\n\t\t{\r\n\t\t\tprintf( \"fix wad so all files start on 2048 boundary.\\n\" );\r\n\t\t}\r\n\t}\r\n\r\n\tif (CAsyncFileLoader::sAsyncInUse())\r\n\t{\r\n\t\tCAsyncFileLoader::sWaitForIOEvent(true);\r\n\t\tDbg_Message(\"************************ Can't do a normal read when async filesystem is in use\");\r\n\t\t//Dbg_MsgAssert(0, (\"Can't do a normal read when async filesystem is in use\"));\r\n\t}\r\n\r\n\tuint32 lsn = gWadLSN;\r\n\tlsn += tempHed->Offset / SECTOR_SIZE;\r\n\r\n\tuint8 *pEEBuffer = new uint8[ FILESYS_CD_READ_SIZE + IOP_TO_EE_BUFFER_ALLIGNMENT ];\r\n\r\n\tuint8 *pData = pEEBuffer;\r\n\tpData = ( uint8 * )( ( ( int )pEEBuffer + ( IOP_TO_EE_BUFFER_ALLIGNMENT - 1 ) ) & ~( IOP_TO_EE_BUFFER_ALLIGNMENT - 1 ) );\r\n\r\n\tuint32 numSectorsToRead;\r\n\tuint32 err;\r\n\tuint32 numBytesToCopy;\r\n\tuint32 i;\r\n\tuint32 *pAI;\r\n\tuint32 *pDI;\r\n\tif ( gStreaming )\r\n\t{\r\n\t\tif ( !sceCdStSeek( lsn ) )\r\n\t\t{\r\n\t\t\tStartStreaming( lsn );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tStartStreaming( lsn );\r\n\t}\r\n\twhile ( bytesRequired )\r\n\t{\r\n\t\tif ( /*offsetWithinBuffer +*/ bytesRequired < FILESYS_CD_READ_SIZE )\r\n\t\t{\r\n\t\t\tnumBytesToCopy = bytesRequired;\r\n\t\t\tnumSectorsToRead = ( ( /*offsetWithinBuffer +*/ bytesRequired ) / SECTOR_SIZE );\r\n\t\t\tif ( bytesRequired & ( SECTOR_SIZE - 1 ) )\r\n\t\t\t numSectorsToRead++;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tnumBytesToCopy = FILESYS_CD_READ_SIZE;// - offsetWithinBuffer;\r\n\t\t\tnumSectorsToRead = FILESYS_NUM_SECTORS_PER_READ;\r\n\t\t}\r\n\t\t\r\n\t\t// read in a chunk at a time ( 50 sectors? 100 sectors? )\r\n\t\tuint32 sectorsRead;\r\n\t\tsectorsRead = sceCdStRead( numSectorsToRead, ( uint32 * )pData, STMBLK, &err );\r\n\t\t\r\n\t\tint numErrors = 0;\r\n\t\twhile ( sectorsRead != numSectorsToRead )\r\n\t\t{\r\n\t\t\tprintf(\"QuickLoad: Could only read %d of the %d sectors for file %s\\n\", sectorsRead, numSectorsToRead, filename);\r\n\t\t\tsceCdStSeek( lsn );\r\n\t\t\tsectorsRead = sceCdStRead( numSectorsToRead, ( uint32 * )pData, STMBLK, &err );\r\n\t\t\tif ( numErrors++ >= 12 )\r\n\t\t\t{\r\n\t\t\t\t// figure out what the problem is using sceCDGetError( ) and either try to\r\n\t\t\t\t// recover or put up an error screen or something?\r\n\t\t\t\tHandleCDStreamingError( lsn );\r\n\t\t\t\tnumErrors = 0;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tpAI = ( uint32 * )( addr );\r\n\t\tpDI = ( uint32 * )( pData );\r\n\t\t// copy the data from the buffer to the given address:\r\n\t\tfor ( i = 0; i < ( numBytesToCopy >> 2 ); i++ )\r\n\t\t{\r\n\t\t\t*pAI++ = *pDI++;\r\n\t\t}\r\n\t\tfor ( i = 0; i < ( numBytesToCopy & 3 ); i++ )\r\n\t\t{\r\n\t\t\t//addr[ 1 + ( numBytesToCopy & ~3 ) + i ] = pData[ 1 + ( numBytesToCopy & ~3 ) + i ];\r\n\t\t\taddr[  ( numBytesToCopy & ~3 ) + i ] = pData[ ( numBytesToCopy & ~3 ) + i ];\r\n\t\t}\r\n\t\t\r\n\t\taddr += numBytesToCopy;\r\n\t\tbytesRequired -= numBytesToCopy;\r\n\t\t\r\n\t\tlsn += numSectorsToRead;\r\n//\t\toffsetWithinBuffer = 0;\r\n\t}\r\n//\tsceCdStPause( );\r\n\r\n// Mick: 8/28/02 - I added the next line\r\n// the aim is to stop streaming now, so we don't have to do the extra call to\r\n// sceCdStSeek  for the next call to this functions\r\n// The speeds up the loading of skaters by 20%\r\n\tStopStreaming();\r\n\r\n\tdelete pEEBuffer;\r\n#endif // ASYNC_QUICK_FILESYS\r\n\r\n\treturn ( true );\r\n}\r\n\r\nstatic void* cdFopen(const char *fname, const char *access)\r\n{\r\n\t\r\n\t\r\n\tSHedFile *pHd=FindFileInHed(fname, gpHed);\r\n\tif (!pHd)\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tskyFile *fp = lock_skyfile();\r\n\r\n\tif (!fp)\r\n\t{\r\n\t\treturn (NULL);\r\n\t}\r\n\r\n\tint mode = skyTransMode(access);\r\n\tif (!mode)\r\n\t{\r\n\t\tunlock_skyfile( fp );\r\n\t\treturn (NULL);\r\n\t}\r\n\r\n\tfp->pFilename=fname;\r\n\tfp->WadOffset=pHd->Offset;\t\t\t\t\t\r\n\tfp->SOF=pHd->FileSize;\r\n\tfp->POS=0;\r\n\tfp->gdfs=0;\r\n#if ASYNC_HOST_FILESYS\r\n\tfp->p_async_file = NULL;\r\n#endif\r\n\t/* Initialise the buffer to show nothing buffered */\r\n\tfp->bufferPos = READBUFFERSIZE;\r\n\t\r\n\t/* SCE_CREAT & !SCE_TRUNC mean seek to end of file */\r\n\t//if (!((mode & SCE_CREAT) && !(mode & SCE_TRUNC)))\r\n\t//{\r\n\t//\tfp->POS = fp->SOF;\r\n\t//}\r\n\t\r\n\ts_open_files++;\r\n\r\n\treturn ((void *)fp);\r\n}\r\n\r\nstatic int cdFclose( void* fptr )\r\n{\r\n\t\r\n\t\r\n\tskyFile* fp = (skyFile*)fptr;\r\n\r\n\tDbg_AssertPtr( fptr );\r\n\r\n\r\n\tif ( fp && s_open_files )\r\n\t{\r\n\t\tunlock_skyfile( fp );\r\n        \r\n\t\ts_open_files--;\r\n\r\n\t\treturn 0;\r\n\t}\r\n\r\n\treturn -1;\r\n}\r\n\r\nstatic bool cdFexist( const char* name )\r\n{\r\n\t\r\n\tif (FindFileInHed(name, gpHed))\r\n\t{\r\n\t\treturn true;\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n}\r\n\r\nstatic size_t cdFread(void *addr, size_t size, size_t count, void *fptr)\r\n{\r\n\t\r\n\tskyFile     *fp = (skyFile *)fptr;\r\n\tsize_t      numBytesToRead = size * count;\r\n\tint         bytesRead, bytesRead2;\r\n\r\n\tbytesRead = 0;\r\n\r\n\tStopStreaming( );\r\n\r\n//\tchar * after = (char*)addr + numBytesToRead; \t\t\t\t\t\t\t   \r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\r\n\t/* Trim number of bytes for the size of the file */\r\n\tif ((fp->POS + (int32)numBytesToRead) > fp->SOF)\r\n\t{\r\n\t\tnumBytesToRead = fp->SOF - fp->POS;\r\n\t}\r\n\r\n\t\r\n\t/* First try and use the buffer */\r\n\tif ((fp->bufferPos < READBUFFERSIZE) &&\r\n\t\t(bytesRead < (int32)numBytesToRead))\r\n\t{\r\n\t\t/* Pull from the buffer */\r\n\t\tif (numBytesToRead < (READBUFFERSIZE-fp->bufferPos))\r\n\t\t{\r\n\t\t\t/* Can satisfy entirely from buffer */\r\n\t\t\tbytesRead = numBytesToRead;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t/* Pull as much as possible from the buffer */\r\n\t\t\tbytesRead = READBUFFERSIZE-fp->bufferPos;\r\n\t\t}\r\n\r\n\t\t/* Copy it */\r\n\t\tmemcpy(addr, &fp->readBuffer[fp->bufferPos], bytesRead);\r\n\r\n\t\t/* Update target address and source address */\r\n\t\taddr = (void *)((uint8 *)addr + bytesRead);\r\n\t\tfp->bufferPos += bytesRead;\r\n\t\tfp->POS += bytesRead;\r\n\t}\r\n\r\n\t/* If next bit is bigger than a buffer, read it directly and ignore the\r\n\t * buffer.\r\n\t */\r\n\tif ((numBytesToRead-bytesRead) > 0)\r\n\t{\r\n\t\tif ((numBytesToRead-bytesRead) >= READBUFFERSIZE)\r\n\t\t{\r\n\t\t\tbytesRead2 = (numBytesToRead-bytesRead);\r\n\t\t\t//bytesRead2 = sceRead(fp->gdfs, addr, bytesRead2);\r\n\t\t\tDbg_MsgAssert(WadId>=0,(\"Bad WadId\"));\t\r\n\t\t\t//Dbg_Message(\"Seeking to LSN %d\", fp->WadOffset+fp->POS);\r\n\t\t\tsceLseek(WadId, fp->WadOffset+fp->POS, SCE_SEEK_SET);\r\n\t\t\tbytesRead2=sceRead(WadId,addr,bytesRead2);\r\n\t\t\t\r\n\t\t\tif (bytesRead2 < 0)\r\n\t\t\t{\r\n\t\t\t\tbytesRead2 = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t/* Go via the buffer */\r\n\t\t\t//sceRead(fp->gdfs, fp->readBuffer, READBUFFERSIZE);\r\n\t\t\tDbg_MsgAssert(WadId>=0,(\"Bad WadId\"));\t\r\n\t\t\t//Dbg_Message(\"Seeking to LSN %d\", fp->WadOffset+fp->POS);\r\n\t\t\tsceLseek(WadId, fp->WadOffset+fp->POS, SCE_SEEK_SET);\r\n\t\t\tsceRead(WadId,fp->readBuffer, READBUFFERSIZE);\r\n\r\n\t\t\t\r\n\t\t\tbytesRead2 = (numBytesToRead-bytesRead);\r\n\t\t\tmemcpy(addr, fp->readBuffer, bytesRead2);\r\n\t\t\tfp->bufferPos = bytesRead2;\r\n\t\t}\r\n\t\tfp->POS += bytesRead2;\r\n\t\tbytesRead += bytesRead2;\r\n\t}\r\n\r\n\treturn (bytesRead/size);\r\n}\r\n\r\nstatic size_t cdFwrite( const void *addr, size_t size, size_t count, void *fptr )\r\n{\r\n\t\r\n\tskyFile  *fp = (skyFile *)fptr;\r\n\tDbg_AssertPtr( fptr );\r\n\t\r\n\tfp->POS+=size*count;\t\t\t \r\n\tfp->SOF=fp->POS;\r\n\treturn count;\r\n}\r\n\r\nstatic int cdFseek(void *fptr, long offset, int origin)\r\n{\r\n\t\r\n\r\n\tskyFile      *fp = (skyFile *)fptr;\r\n\tint32      oldFPos, bufStart;\r\n\tbool       noBuffer = FALSE;\r\n\r\n\tDbg_AssertPtr( fptr );\r\n\r\n\toldFPos = fp->POS;\r\n\tbufStart = oldFPos - fp->bufferPos;\r\n\tif (fp->bufferPos == READBUFFERSIZE) noBuffer = TRUE;\r\n\tfp->bufferPos = READBUFFERSIZE;\r\n\r\n\tswitch (origin)\r\n\t{\r\n\t\tcase SEEK_CUR:\r\n\t\t{            \r\n\t\t\t/* Does the seek stay in the buffer */\r\n\t\t\tif ((oldFPos + offset >= bufStart) &&\r\n\t\t\t\t(oldFPos + offset < bufStart+READBUFFERSIZE))\r\n\t\t\t{\r\n\t\t\t\tfp->bufferPos = (oldFPos + offset) - bufStart;\r\n\t\t\t\tfp->POS += offset;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfp->POS+=offset;\r\n\t\t\t\tif (fp->POS<0 || fp->POS>fp->SOF)\r\n\t\t\t\t{\r\n\t\t\t\t\tfp->POS=-1;\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"Bad offset sent to cdFseek (SEEK_CUR) offset=%ld pos=%d size=%d\",offset,fp->POS-offset,fp->SOF));\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase SEEK_END:\r\n\t\t{\r\n\t\t\tfp->POS=fp->SOF-offset;\r\n\t\t\tif (fp->POS<0 || fp->POS>fp->SOF)\r\n\t\t\t{\r\n\t\t\t\tfp->POS=-1;\r\n\t\t\t\tDbg_MsgAssert(0,(\"Bad offset sent to cdFseek (SEEK_END)\"));\t\t\t\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase SEEK_SET:\r\n\t\t{\r\n\t\t\tfp->POS=offset;\r\n\t\t\tif (fp->POS<0 || fp->POS>fp->SOF)\r\n\t\t\t{\r\n\t\t\t\tfp->POS=-1;\r\n\t\t\t\tDbg_MsgAssert(0,(\"Bad offset sent to cdFseek (SEEK_SET)\"));\t\t\t\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\treturn (-1);\r\n\t\t}\r\n\t}\r\n\r\n\tif (noBuffer)\r\n\t\tfp->bufferPos = READBUFFERSIZE;\r\n\r\n\tif (fp->POS == -1)\r\n\t{\r\n\t\t/* This may not be valid */\r\n\t\tfp->POS = oldFPos;\r\n\t\tfp->bufferPos = READBUFFERSIZE;\r\n\t\treturn (-1);\r\n\t}\r\n\r\n\treturn (0);\r\n}\r\n\r\nstatic char * cdFgets(char *buffer, int maxLen, void *fptr)\r\n{\r\n\t\r\n\tDbg_MsgAssert(0,(\"fgets not done yet\"));\r\n\treturn NULL;\r\n}\r\n\r\nstatic int cdFputs( const char *buffer, void *fptr)\r\n{\r\n\t\r\n\tDbg_MsgAssert(0,(\"Cannot fputs to CD\"));\r\n\treturn 0;\r\n}\r\n\r\nstatic int cdFeof( void* fptr )\r\n{\r\n\t\r\n\r\n\tskyFile  *fp = (skyFile*)fptr;\r\n\r\n\tDbg_AssertPtr( fptr );\r\n\r\n\treturn ( fp->POS >= fp->SOF) ;\r\n}\r\n\r\nstatic int cdFflush( void* )\r\n{\r\n\t\r\n\t\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/* skyFopen                                                       */\r\n/*                                                                */\r\n/* On entry   : Filename, access mode                             */\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void* skyFopen(const char *fname, const char *access)\r\n{\r\n\t\r\n\r\n\tskyFile*\tfp;\r\n\tint         mode;\r\n\r\n\tStopStreaming( );\r\n\r\n\t/* Allocate structure for holding info */\r\n\tfp = lock_skyfile();\r\n\r\n\tif (!fp)\r\n\t{\r\n\t\treturn (NULL);\r\n\t}\r\n\r\n\tmode = skyTransMode(access);\r\n\tif (!mode)\r\n\t{\r\n\t\treturn (NULL);\r\n\t}\r\n\r\n#if ASYNC_HOST_FILESYS\r\n\tfp->p_async_file = CAsyncFileLoader::sOpen(fname, true);\r\n\r\n\tif (!fp->p_async_file)\r\n\t{\r\n\t\tunlock_skyfile( fp );\r\n\t\treturn (NULL);\r\n\t}\r\n\r\n\t// Get file size (will come up with better way)\r\n\tfp->SOF = fp->p_async_file->GetFileSize();\r\n\tfp->POS = 0;\r\n\t//fp->p_async_file->Seek(0, SEEK_END);\r\n\t//fp->SOF = fp->p_async_file->WaitForIO();\r\n\t//fp->p_async_file->Seek(0, SEEK_SET);\r\n\t//fp->POS = fp->p_async_file->WaitForIO();\r\n#else\r\n\tchar      name[256];\r\n\tchar*\t\tnameptr;\r\n\r\n\t/* First manipulate the filename into a Sky friendly name */\r\n\tif (strchr(fname, ':'))\r\n\t{\r\n\t\tstrncpy(name, fname, 255);\r\n\t}\r\n\telse\r\n\t{\r\n#ifdef SCE_11\r\n\t\tstrcpy(name, \"sim:\");\r\n\t\tstrncpy(&name[4], fname, 251);\r\n#else\r\n\t\tstrcpy(name, \"host:\");\r\n\t\tstrncpy(&name[5], fname, 250);\r\n#endif       \r\n\t}\r\n\t/* force null termination */\r\n\tname[255] = 0;\r\n\r\n\tnameptr = name;\r\n\twhile(*nameptr)\r\n\t{\r\n\t\tif (*nameptr == '\\\\') *nameptr = '/';\r\n\t\tnameptr++;\r\n\t}\r\n\r\n\tfp->gdfs = sceOpen(name, mode);\r\n\r\n\tif (fp->gdfs < 0)\r\n\t{\r\n\t\tunlock_skyfile( fp );\r\n\t\treturn (NULL);\r\n\t}\r\n\r\n\t/* We seek to the end of the file to get size */\r\n\tfp->SOF = fp->POS = sceLseek(fp->gdfs, 0, SCE_SEEK_END);\r\n\tif (fp->SOF< 0)\r\n\t{\r\n\t\tsceClose(fp->gdfs);\r\n\t\tunlock_skyfile( fp );\r\n\t\treturn (NULL);\r\n\t}\r\n\t/* SCE_CREAT & !SCE_TRUNC mean seek to end of file */\r\n\tif (!((mode & SCE_CREAT) && !(mode & SCE_TRUNC)))\r\n\t{\r\n\t\tfp->POS = sceLseek(fp->gdfs, 0, SCE_SEEK_SET);\r\n\r\n\t\tif (fp->POS < 0)\r\n\t\t{\r\n\t\t\tsceClose(fp->gdfs);\r\n\t\t\tunlock_skyfile( fp );\r\n\t\t\t\r\n\t\t\treturn (NULL);\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\t/* Initialise the buffer to show nothing buffered */\r\n\tfp->bufferPos = READBUFFERSIZE;\r\n\tstrncpy( fp->filename, fname, MAX_PFILESYS_NAME_SIZE );\r\n\ts_open_files++;\r\n\r\n\treturn ((void *)fp);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/* skyFclose                                                      */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic int skyFclose( void* fptr )\r\n{\r\n\t\r\n\r\n\tskyFile* fp = (skyFile*)fptr;\r\n\r\n\tDbg_AssertPtr( fptr );\r\n\r\n\tif ( fp && s_open_files )\r\n\t{\r\n#if ASYNC_HOST_FILESYS\r\n\t\tCAsyncFileLoader::sClose(fp->p_async_file);\r\n\t\tfp->p_async_file = NULL;\r\n#else\r\n\t\tsceClose( fp->gdfs );\r\n#endif\r\n\t\tunlock_skyfile( fp );\r\n        \r\n\t\ts_open_files--;\r\n\r\n\t\treturn 0;\r\n\t}\r\n\r\n\treturn -1;\r\n}\r\n\r\n/******************************************************************/\r\n/* skyFexist                                                      */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic bool skyFexist( const char* name )\r\n{\r\n\t\r\n\r\n\tvoid* res = File::Open( name, \"r\" );\r\n\r\n\tif ( res )\r\n\t{\r\n\t\tFile::Close( res );\r\n\t\treturn TRUE;\r\n\t}\r\n\r\n\treturn FALSE;\r\n}\r\n\r\n/******************************************************************/\r\n/* skyFread                                                       */\r\n/*                                                                */\r\n/* On entry : Address to read to, block size, block count, file   */\r\n/* On exit  : Number of bytes read                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic size_t skyFread(void *addr, size_t size, size_t count, void *fptr)\r\n{\r\n\t\r\n\t\r\n\tskyFile     *fp = (skyFile *)fptr;\r\n\tsize_t      numBytesToRead = size * count;\r\n\tint         bytesRead = 0;\r\n\r\n\tStopStreaming( );\r\n\r\n\t/* Trim number of bytes for the size of the file */\r\n\tif ((fp->POS + (int32)numBytesToRead) > fp->SOF)\r\n\t{\r\n\t\tnumBytesToRead = fp->SOF - fp->POS;\r\n\t}\r\n\r\n#if ASYNC_HOST_FILESYS\r\n\tfp->p_async_file->Read(addr, size, count);\r\n\tbytesRead = fp->p_async_file->WaitForIO();\r\n\tfp->POS += bytesRead;\r\n#else\r\n\tint bytesRead2;\r\n\r\n\t/* First try and use the buffer */\r\n\tif ((fp->bufferPos < READBUFFERSIZE) &&\r\n\t\t(bytesRead < (int32)numBytesToRead))\r\n\t{\r\n\t\t/* Pull from the buffer */\r\n\t\tif (numBytesToRead < (READBUFFERSIZE-fp->bufferPos))\r\n\t\t{\r\n\t\t\t/* Can satisfy entirely from buffer */\r\n\t\t\tbytesRead = numBytesToRead;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t/* Pull as much as possible from the buffer */\r\n\t\t\tbytesRead = READBUFFERSIZE-fp->bufferPos;\r\n\t\t}\r\n\r\n\t\t/* Copy it */\r\n\t\tmemcpy(addr, &fp->readBuffer[fp->bufferPos], bytesRead);\r\n\r\n\t\t/* Update target address and source address */\r\n\t\taddr = (void *)((uint8 *)addr + bytesRead);\r\n\t\tfp->bufferPos += bytesRead;\r\n\t\tfp->POS += bytesRead;\r\n\t}\r\n\r\n\t/* If next bit is bigger than a buffer, read it directly and ignore the\r\n\t * buffer.\r\n\t */\r\n\tif ((numBytesToRead-bytesRead) > 0)\r\n\t{\r\n\t\tif ((numBytesToRead-bytesRead) >= READBUFFERSIZE)\r\n\t\t{\r\n\t\t\tbytesRead2 = (numBytesToRead-bytesRead);\r\n\t\t\tbytesRead2 = sceRead(fp->gdfs, addr, bytesRead2);\r\n\t\t\tif (bytesRead2 < 0)\r\n\t\t\t{\r\n\t\t\t\tbytesRead2 = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t/* Go via the buffer */\r\n\t\t\tsceRead(fp->gdfs, fp->readBuffer, READBUFFERSIZE);\r\n\t\t\tbytesRead2 = (numBytesToRead-bytesRead);\r\n\t\t\tmemcpy(addr, fp->readBuffer, bytesRead2);\r\n\t\t\tfp->bufferPos = bytesRead2;\r\n\t\t}\r\n\t\tfp->POS += bytesRead2;\r\n\t\tbytesRead += bytesRead2;\r\n\t}\r\n#endif\r\n\r\n\treturn (bytesRead/size);\r\n}\r\n\r\n/******************************************************************/\r\n/* skyFwrite                                                      */\r\n/*                                                                */\r\n/* On entry : Address to write from, block size, block count, file*/\r\n/* On exit  : Number of bytes written                             */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic size_t skyFwrite( const void *addr, size_t size, size_t count, void *fptr )\r\n{\r\n\t\r\n\r\n\tint         bytesWritten;\r\n\tskyFile*\tfp = (skyFile*)fptr;\r\n\tint32     numBytesToWrite = size * count;\r\n\r\n\tDbg_AssertPtr( addr );\r\n\tDbg_AssertPtr( fptr );\r\n\r\n\tbytesWritten = sceWrite( fp->gdfs, (void*)addr, numBytesToWrite );\r\n\r\n\tif (bytesWritten != -1)\r\n\t{\r\n\t\tfp->POS += bytesWritten;\r\n\t\tif (fp->POS > fp->SOF)\r\n\t\t\tfp->SOF = fp->POS;\r\n\t\treturn (size>0?bytesWritten/size:0);\r\n\t}\r\n\treturn (0);\r\n}\r\n\r\n/******************************************************************/\r\n/* skyFseek                                                       */\r\n/*                                                                */\r\n/* On entry   : file to seek in, offset, how to seek\t  \t\t  */\r\n/* On exit    : success/failure                                   */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic int skyFseek(void *fptr, long offset, int origin)\r\n{\r\n\t\r\n\r\n\tskyFile      *fp = (skyFile *)fptr;\r\n\r\n\tDbg_AssertPtr( fptr );\r\n\r\n\tStopStreaming( );\r\n\r\n#if ASYNC_HOST_FILESYS\r\n\tfp->p_async_file->Seek(offset, origin);\r\n\tfp->POS = fp->p_async_file->WaitForIO();\r\n#else\r\n\tint32      oldFPos, bufStart;\r\n\tbool       noBuffer = FALSE;\r\n\r\n\toldFPos = fp->POS;\r\n\tbufStart = oldFPos - fp->bufferPos;\r\n\tif (fp->bufferPos == READBUFFERSIZE) noBuffer = TRUE;\r\n\tfp->bufferPos = READBUFFERSIZE;\r\n\r\n\tswitch (origin)\r\n\t{\r\n\t\tcase SEEK_CUR:\r\n\t\t{            \r\n\t\t\t/* Does the seek stay in the buffer */\r\n\t\t\tif ((oldFPos + offset >= bufStart) &&\r\n\t\t\t\t(oldFPos + offset < bufStart+READBUFFERSIZE))\r\n\t\t\t{\r\n\t\t\t\tfp->bufferPos = (oldFPos + offset) - bufStart;\r\n\t\t\t\tfp->POS += offset;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfp->POS = sceLseek(fp->gdfs, oldFPos + offset, SCE_SEEK_SET);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase SEEK_END:\r\n\t\t{\r\n\t\t\tfp->POS = sceLseek(fp->gdfs, offset, SCE_SEEK_END);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase SEEK_SET:\r\n\t\t{\r\n\t\t\tfp->POS = sceLseek(fp->gdfs, offset, SCE_SEEK_SET);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\treturn (-1);\r\n\t\t}\r\n\t}\r\n\r\n\tif (noBuffer)\r\n\t\tfp->bufferPos = READBUFFERSIZE;\r\n\r\n\tif (fp->POS == -1)\r\n\t{\r\n\t\t/* This may not be valid */\r\n\t\tfp->POS = oldFPos;\r\n\t\tfp->bufferPos = READBUFFERSIZE;\r\n\t\treturn (-1);\r\n\t}\r\n#endif\r\n\treturn (0);\r\n}\r\n\r\n/******************************************************************/\r\n/* skyFgets                                                       */\r\n/*                                                                */\r\n/* On entry   : Buffer to read into, max chars to read, file\t  */\r\n/* On exit    : Non negative value on success                     */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic char * skyFgets(char *buffer, int maxLen, void *fptr)\r\n{\r\n\t\r\n\r\n\tskyFile            *fp = (skyFile *) fptr;\r\n\tint32             i;\r\n\tint32             numBytesRead;\r\n\r\n\tDbg_AssertPtr( buffer );\r\n\tDbg_AssertPtr( fptr );\r\n\r\n\ti = 0;\r\n\r\n\tnumBytesRead = skyFread(buffer, 1, maxLen - 1, fp);\r\n\r\n\tif (numBytesRead == 0)\r\n\t{\r\n\t\treturn (NULL);\r\n\t}\r\n\r\n\twhile (i < numBytesRead)\r\n\t{\r\n\t\tif (buffer[i] == '\\n')\r\n\t\t{\r\n\t\t\ti++;\r\n\r\n\t\t\tbuffer[i] = '\\0';\r\n\r\n\t\t\t/* the file pointer needs */\r\n\t\t\t/* to be reset as skyFread */\r\n\t\t\t/* will have overshot the */\r\n\t\t\t/* first new line         */\r\n\r\n\t\t\ti -= numBytesRead;\r\n\t\t\tskyFseek(fp, i, SEEK_CUR);\r\n\r\n\t\t\treturn (buffer);\r\n\t\t}\r\n\t\telse if ( buffer[i] == 0x0D )\r\n\t\t{\r\n\t\t\tif ((i < (numBytesRead - 1)) && (buffer[i + 1] == '\\n'))\r\n\t\t\t{\r\n\t\t\t\tmemcpy(&buffer[i], &buffer[i + 1], (numBytesRead - i - 1));\r\n\t\t\t\tnumBytesRead--;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t\ti++;\r\n\t\t}\r\n\t\telse\r\n\t\t\ti++;\r\n\t}\r\n\r\n\t/*\r\n\t * Don't return NULL because we could have read maxLen bytes\r\n\t * without finding a \\n\r\n\t */\r\n\treturn (buffer);\r\n}\r\n\r\n/******************************************************************/\r\n/* skyFputs                                                       */\r\n/*                                                                */\r\n/* On entry   : Buffer to write from, file to write to            */\r\n/* On exit    : Non negative value on success                     */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic int skyFputs( const char *buffer, void *fptr)\r\n{\r\n\t\r\n\r\n\tskyFile   *fp = (skyFile *)fptr;\r\n\tint i, j;\r\n\r\n\tDbg_AssertPtr( buffer );\r\n\tDbg_AssertPtr( fptr );\r\n\r\n\ti = strlen(buffer);\r\n\tj = sceWrite(fp->gdfs, (void*)buffer, i);\r\n\r\n\tif (j != -1)\r\n\t{\r\n\t\tfp->POS += j;\r\n\t\tif (fp->POS > fp->SOF)\r\n\t\t\tfp->SOF = fp->POS;\r\n\t}\r\n\tif ((j == -1) || (i != j))\r\n\t{\r\n\t\treturn (EOF);\r\n\t}\r\n\treturn (j);\r\n}\r\n\r\n/******************************************************************/\r\n/* skyFeof                                                        */\r\n/*                                                                */\r\n/* On entry   : File to test for eof                              */\r\n/* On exit    : Non zero if end of file reached                   */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic int skyFeof( void* fptr )\r\n{\r\n\t\r\n\r\n\tskyFile  *fp = (skyFile*)fptr;\r\n\r\n\tDbg_AssertPtr( fptr );\r\n\r\n\treturn ( fp->POS >= fp->SOF) ;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic int skyFflush( void* )\r\n{\r\n\t\r\n\r\n\treturn 0;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nlong GetFileSize(void *pFP)\r\n{\r\n\t\r\n\tDbg_MsgAssert(pFP,(\"NULL pFP sent to GetFileSize\"));\r\n\r\n#if ASYNC_HOST_FILESYS\r\n\tskyFile      *fp = (skyFile *)pFP;\r\n\tif (!Config::CD() && fp->p_async_file)\r\n\t{\r\n\t\treturn fp->p_async_file->GetFileSize();\r\n\t}\r\n#endif\r\n\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_get_file_size((PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\treturn ((skyFile*)pFP)->SOF;\r\n}\r\n\r\nlong GetFilePosition(void *pFP)\r\n{\r\n\t\r\n\tDbg_MsgAssert(pFP,(\"NULL pFP sent to GetFilePosition\"));\r\n\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_get_file_position((PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\treturn ((skyFile*)pFP)->POS;\r\n}\r\n\r\nfloat GetPercentageRead(void *pFP)\r\n{\r\n\tDbg_MsgAssert(pFP,(\"NULL pFP sent to GetPercentageRead\"));\r\n\r\n\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        int position = PreMgr::pre_get_file_position((PreFile::FileHandle *) pFP);\r\n        int size = PreMgr::pre_get_file_size((PreFile::FileHandle *) pFP);\r\n\r\n        if (PreMgr::sPreExecuteSuccess())\r\n\t\t\treturn 100.0 * position / size;\r\n    }\r\n\r\n\treturn 100.0*((skyFile*)pFP)->POS/((skyFile*)pFP)->SOF;\r\n}\r\n\t\r\nvoid InstallFileSystem( void )\r\n{\r\n\t// cd builds can only have one file open at any given time\r\n\tint max_open_files=Config::CD() ? 1:MAXOPENFILES;\r\n\r\n\r\n\t// initialize the locks on the sky files\r\n\tfor ( int i = 0; i < max_open_files; i++ )\r\n\t{\r\n\t\tg_skyFile[i].locked = false;\r\n\t}\r\n\t\r\n    \r\n\tif (Config::CD())\r\n\t{\r\n\t\tint\tdisk_type = SCECdDVD;\r\n\t\r\n\t\t// Initialise the CD\r\n\t\tprintf(\"Initialising CD ...\\n\");\r\n\t//\tint err1 = \r\n\t\tsceCdInit(SCECdINIT);\r\n\t\t\r\n\t\t//int err2 = sceCdMmode(SCECdDVD);\r\n\t//\tint err2 = \r\n\t\tsceCdMmode(disk_type);\r\n\t\r\n\t\r\n\t\t// find the disk type, this might be different from what we intialized to \r\n\t\tprintf(\" sceCdGetDiskType   \");\r\n\t\tint detected_disk_type= sceCdGetDiskType();\r\n\t\tswitch(detected_disk_type)\r\n\t\t{\r\n\t\t\tcase SCECdIllgalMedia:\r\n\t\t\tprintf(\"Disk Type= IllgalMedia\\n\"); break;\r\n\t\t\tcase SCECdPS2DVD:\r\n\t\t\tprintf(\"Disk Type= PlayStation2 DVD\\n\"); break;\r\n\t\t\tcase SCECdPS2CD:\r\n\t\t\tprintf(\"Disk Type= PlayStation2 CD\\n\"); break;\r\n\t\t\tcase SCECdPS2CDDA:\r\n\t\t\tprintf(\"Disk Type= PlayStation2 CD with CDDA\\n\"); break;\r\n\t\t\tcase SCECdPSCD:\r\n\t\t\tprintf(\"Disk Type= PlayStation CD\\n\"); break;\r\n\t\t\tcase SCECdPSCDDA:\r\n\t\t\tprintf(\"Disk Type= PlayStation CD with CDDA\\n\"); break;\r\n\t\t\tcase SCECdDVDV:\r\n\t\t\tprintf(\"Disk Type= DVD video\\n\"); break;\r\n\t\t\tcase SCECdCDDA:\r\n\t\t\tprintf(\"Disk Type= CD-DA\\n\"); break;\r\n\t\t\tcase SCECdDETCT:\r\n\t\t\tprintf(\"Working\\n\"); break;\r\n\t\t\tcase SCECdNODISC: \r\n\t\t\tprintf(\"Disk Type= No Disc\\n\"); break;\r\n\t\t\tdefault:\r\n\t\t\tprintf(\"Disk Type= OTHER DISK\\n\"); break;\r\n\t\t}\r\n\t\t\r\n\t\t// If disk type has changed to a CD, then need to re-initialize it\t\t\t\t\t\t\t   \r\n\t\tif (detected_disk_type == SCECdPS2CD)\r\n\t\t{\r\n\t\t\t#if __DVD_ONLY__\r\n\t\t\tprintf( \"*** ERROR - CD Detected, needs DVD.\\n\" );\r\n\t\t\t#else\r\n\t\t\tprintf( \"reinitializing for Ps2CD\\n\" );\r\n\t\t\tdisk_type = SCECdCD;\r\n\t\t\tsceCdMmode(disk_type);\r\n\t\t\tprintf( \"done reinitializing\\n\" );\r\n\t\t\t#endif\t\t\r\n\t\t}\r\n\t\t\r\n\t\r\n\t//\tprintf(\"'tis done. errs = %d, %d\\n\",err1,err2);\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t\t\t\t   \r\n\t\t\t\t\t\t   \r\n\t\t// This next bit is essential for when making a bootable disc, ie one that will\r\n\t\t// boot on the actual PS rather than just the dev system.\r\n\t//#ifdef __NOPT_BOOTABLE__\r\n\t\t// K: Commented out __NOPT_BOOTABLE__, since it is set when __NOPT_CDROM__OLD is set.\r\n\t\r\n\t\t/* Reboot IOP, replace default modules  */\r\n\t\tchar  path[128];\r\n//\t\tsprintf(path,\"cdrom0:\\\\%sIOP\\\\IOPRP260.IMG;1\",Config::GetDirectory()); \r\n//\t\tsprintf(path,\"host0:\\\\SKATE5\\\\DATA\\\\IOPMODULES\\\\DNAS280.IMG;1\");\r\n\t\t\r\n\t\t\r\n\t\tsprintf(path,\"cdrom0:\\\\%sIOP\\\\DNAS280.IMG;1\",Config::GetDirectory()); \r\n\t\twhile ( !sceSifRebootIop((const char*) path) ); /* (Important) Unlimited retries */\r\n\t\twhile( !sceSifSyncIop() );\r\n\t\t\r\n\t\t\r\n\t\t/* Reinitialize */\r\n\t\tsceSifInitRpc(0);\r\n\t\tsceCdInit(SCECdINIT);\r\n\t\t\r\n\t//    sceCdMmode(SCECdDVD);   /* Media: CD-ROM */\r\n\t\tsceCdMmode(disk_type);   /* Media: CD-ROM */\r\n\t\t\r\n\t\tsceFsReset();\r\n\t//#endif // __NOPT_BOOTABLE__\r\n\r\n\t\tprintf(\"Opening hed file ...\\n\");\r\n\t\t// Open the hed file and load it into memory.\r\n\t\tgpHed = LoadHed( \"SKATE5\");\r\n\t\t\r\n\t/*\t\r\n\t\tprintf (\"Size = %d, adjusted = %d\\n\",HedSize,(HedSize+2047)&~204);\r\n\t\r\n\t\tfor (int i = HedSize; i< (HedSize+2047)&~204; i++)\r\n\t\t{\r\n\t\t\tif (p[i] != 0x55)\r\n\t\t\t{\r\n\t\t\t\tprintf (\"Overrun ? %d = %2x\\n\",i,p[i]);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t*/\r\n\t\tprintf(\"Opening wad file ...\\n\");\t\t\t\t\t\t\t\t\t\t\t\t \t\r\n\t\t// Open the wad and keep it open for future reference.\t\r\n\t\tDbg_MsgAssert(WadId==-1,(\"WadId not -1 ?\"));\t\t\t\t\t   \r\n\t\twhile (WadId<0)\r\n\t\t{\r\n\t\t\tchar  path[128];\r\n\t\t\tsprintf(path,\"cdrom0:\\\\%sSKATE5.WAD;1\",Config::GetDirectory()); \r\n\t\t\tWadId=sceOpen(path,SCE_RDONLY);\r\n\t\t\tif (WadId<0)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"Retrying opening SKATE5.wad ...\\n\");\r\n\t\t\t}\r\n\t\t}\t\t\r\n\t\tprintf( \"opened successfully\\n\" );\r\n\t}   \r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid UninstallFileSystem( void )\r\n{\r\n\tif (Config::CD())\r\n\t{\r\n\t\t// Free the hed file buffer.\r\n\t\tDbg_MsgAssert(gpHed,(\"NULL gpHed ?\"));\r\n\t\tMem::Free(gpHed);\r\n\t\tgpHed=NULL;\r\n\t\t\r\n\t\tDbg_MsgAssert(WadId>=0,(\"Bad WadId\"));\r\n\t\tsceClose(WadId);\r\n\t\tWadId=-1;\r\n\t\r\n\t\t// free IOP memory:\r\n\t\tif ( gFilesysIOPStreamBuffer )\r\n\t\t{\r\n\t\t\tsceSifFreeIopHeap( gFilesysIOPStreamBuffer ) ;\r\n\t\t\tgFilesysIOPStreamBuffer = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid InitQuickFileSystem( void )\r\n{\r\n\r\n\t// get the LSN to allow us to figure out where every other file is...\r\n\tsceCdlFILE wadInfo;\r\n\tchar  path[128];\r\n\tsprintf(path,\"\\\\%sSKATE5.WAD;1\",Config::GetDirectory()); \r\n\twhile ( !sceCdSearchFile( &wadInfo, path ) )\r\n\t{\r\n\t\tprintf(\"Retrying finding SKATE5.wad ...\\n\");\r\n\t}\r\n\t//printf( \"after search file\\n\" );\r\n\tgWadLSN = wadInfo.lsn;\r\n\r\n#if DISABLE_QUICK_FILESYSTEM\r\n\treturn;\r\n#endif\r\n\r\n#if ASYNC_QUICK_FILESYS == 0\r\n\t// allocate our streaming buffer (iop side) for files:\r\n\t//printf( \"before alloc heap\\n\" );\t\r\n\r\n\tgFilesysIOPStreamBuffer = sceSifAllocIopHeap( FILESYS_IOP_BUFFER_SIZE );\r\n\t\r\n\t//printf( \"after alloc heap: buffer %x of size %d\\n\", gFilesysIOPStreamBuffer, FILESYS_IOP_BUFFER_SIZE );\t\r\n\r\n\tDbg_MsgAssert( gFilesysIOPStreamBuffer,( \"IOP stream buffer allocation failed.\" ));\r\n\r\n\t//printf( \"before stream init\\n\" );\t\r\n\t// initialize streaming capabilities and shit...\r\n\twhile ( !sceCdStInit( FILESYS_NUM_SECTORS_IN_BUFFER, FILESYS_STREAM_BUFFER_NUM_PARTITIONS, (unsigned int)gFilesysIOPStreamBuffer ) )\r\n\t{\r\n\t\tprintf( \"trying to init CD stream\\n\" );\r\n\t}\r\n\t//printf( \"after stream init\\n\" );\r\n\r\n\tStartStreaming( gWadLSN );\r\n#endif\r\n\r\n\tgQuickFileSystemInitialzed = true;\r\n\r\n\t//printf( \"after StartStreaming()\\n\" );\r\n} // end of InitQuickFileSystem( )\t\r\n\r\n\r\n// We need to execute this after we have used the Cd Stream calls in other routines\r\nvoid ResetQuickFileSystem( void )\r\n{\r\n#if ASYNC_QUICK_FILESYS == 0\r\n\tDbg_MsgAssert( gFilesysIOPStreamBuffer,( \"IOP stream buffer not initialized\" ));\r\n\r\n\t// initialize streaming capabilities and shit...\r\n\twhile ( !sceCdStInit( FILESYS_NUM_SECTORS_IN_BUFFER, FILESYS_STREAM_BUFFER_NUM_PARTITIONS, (unsigned int)gFilesysIOPStreamBuffer ) )\r\n\t{\r\n\t\tprintf( \"trying to init CD stream\\n\" );\r\n\t}\r\n#endif\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Our versions of the ANSI file IO functions.  They call\r\n// the PreMgr first to see if the file is in a PRE file.\r\n////////////////////////////////////////////////////////////////////\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Exist                                                          \r\nbool Exist( const char *filename )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        bool retval = PreMgr::pre_fexist(filename);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn cdFexist(filename);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn skyFexist(filename);\r\n\t}\t\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Open                                                          \r\nvoid * Open( const char *filename, const char *access )\r\n{\r\n\tbool use_pre = true;\r\n#if ASYNC_HOST_FILESYS\r\n\tuse_pre = Config::CD();\r\n#endif\r\n\r\n\t// Don't use pre files if writing to disk (eg when writing parks)\r\n\tif (access[0]=='w')\r\n\t{\r\n\t\tuse_pre=false;\r\n\t}\r\n\t\t\r\n\tif (Script::GetInt(CRCD(0xe99935c2,\"show_filenames\"),false))\r\n\t{\r\n\t\tprintf (\".... Open %s\\n\",filename);\r\n\t}\r\n\r\n\r\n    if (use_pre && PreMgr::sPreEnabled())\r\n    {\r\n        void * retval = PreMgr::pre_fopen(filename, access);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn cdFopen(filename, access);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn skyFopen(filename, access);\r\n\t}\t\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Close                                                          \r\nint Close( void *pFP )\r\n{\r\n\tbool use_pre = true;\r\n#if ASYNC_HOST_FILESYS\r\n\tuse_pre = Config::CD();\r\n#endif\r\n\r\n    if (use_pre && PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_fclose((PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn cdFclose(pFP);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn skyFclose(pFP);\r\n\t}\t\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Read                                                          \r\nsize_t Read( void *addr, size_t size, size_t count, void *pFP )\r\n{\r\n\tbool use_pre = true;\r\n#if ASYNC_HOST_FILESYS\r\n\tuse_pre = Config::CD();\r\n#endif\r\n\r\n    if (use_pre && PreMgr::sPreEnabled())\r\n    {\r\n        size_t retval = PreMgr::pre_fread(addr, size, count, (PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tif (CAsyncFileLoader::sAsyncInUse())\r\n\t{\r\n\t\tCAsyncFileLoader::sWaitForIOEvent(true);\r\n\t\tDbg_Message(\"************************ Can't do a normal read when async filesystem is in use\");\r\n\t\t//Dbg_MsgAssert(0, (\"Can't do a normal read when async filesystem is in use\"));\r\n\t}\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn cdFread(addr, size, count, pFP);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn skyFread(addr, size, count, pFP);\r\n\t}\t\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////\r\n// Read an Integer in PS2 (littleendian) format\r\n// we just read it directly into memory...\r\nsize_t ReadInt( void *addr, void *pFP )\r\n{\r\n\treturn Read(addr,4,1,pFP);\t\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Write                                                          \r\nsize_t Write( const void *addr, size_t size, size_t count, void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        size_t retval = PreMgr::pre_fwrite(addr, size, count, (PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn cdFwrite(addr, size, count, pFP);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn skyFwrite(addr, size, count, pFP);\r\n\t}\t\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// GetS                                                          \r\nchar * GetS( char *buffer, int maxlen, void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        char * retval = PreMgr::pre_fgets(buffer, maxlen, (PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn cdFgets(buffer, maxlen, pFP);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn skyFgets(buffer, maxlen, pFP);\r\n\t}\t\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// PutS                                                          \r\nint PutS( const char *buffer, void *pFP )\r\n{\r\n    if (PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_fputs(buffer, (PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn cdFputs(buffer, pFP);\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\treturn skyFputs(buffer, pFP);\r\n\t}\t\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Eof                                                          \r\nint Eof( void *pFP )\r\n{\r\n\tbool use_pre = true;\r\n#if ASYNC_HOST_FILESYS\r\n\tuse_pre = Config::CD();\r\n#endif\r\n\r\n    if (use_pre && PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_feof((PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn cdFeof(pFP);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn skyFeof(pFP);\r\n\t}\t\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Seek                                                          \r\nint Seek( void *pFP, long offset, int origin )\r\n{\r\n\tbool use_pre = true;\r\n#if ASYNC_HOST_FILESYS\r\n\tuse_pre = Config::CD();\r\n#endif\r\n\r\n    if (use_pre && PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_fseek((PreFile::FileHandle *) pFP, offset, origin);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn cdFseek(pFP, offset, origin);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn skyFseek(pFP, offset, origin);\r\n\t}\t\r\n}\r\n\r\nint32\tTell( void* pFP )\r\n{\r\n\tskyFile* fp = (skyFile *) pFP;\r\n\treturn fp->POS;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////\r\n// Flush                                                          \r\nint Flush( void *pFP )\r\n{\r\n\tbool use_pre = true;\r\n#if ASYNC_HOST_FILESYS\r\n\tuse_pre = Config::CD();\r\n#endif\r\n\r\n    if (use_pre && PreMgr::sPreEnabled())\r\n    {\r\n        int retval = PreMgr::pre_fflush((PreFile::FileHandle *) pFP);\r\n        if (PreMgr::sPreExecuteSuccess())\r\n            return retval;\r\n    }\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\treturn cdFflush(pFP);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn skyFflush(pFP);\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace File\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/pip.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////\r\n//\r\n// pip.cpp\t\tKSH 6 Feb 2002\r\n//\r\n// Pre-in-Place stuff\r\n//\r\n///////////////////////////////////////////////////////////////////////////////////////\r\n\r\n// start autoduck documentation\r\n// @DOC pip\r\n// @module pip | None\r\n// @subindex Scripting Database\r\n// @index script | pip\r\n\r\n// TODO\r\n// Use Shrink to shrink the memory block to get rid of the 2048 padding at the end.\r\n// (This will only be effective when the bottom-up heap is being used though)\r\n\r\n// TODO but non-essential:\r\n// Make Unload work if passed the pointer.\r\n// Make GetFileSize work if passed the pointer.\r\n\r\n// 11Dec02 JCB - Andre wanted me to use tolower() instead of strncmpi()\r\n#include <ctype.h>\r\n\r\n#include <sys/file/pip.h>\r\n#include <sys/file/pre.h>\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/struct.h>\r\n#include <sys/file/filesys.h>\r\n#include <core/compress.h>\r\n\r\nnamespace Pip\r\n{\r\n\r\n#define IN_PLACE_DECOMPRESSION_MARGIN 3072\r\n\r\n\r\nenum EQuadAligned\r\n{\r\n\tNOT_QUAD_WORD_ALIGNED=0,\r\n\tQUAD_WORD_ALIGNED\r\n};\r\n\r\n\r\n#define CURRENT_PRE_VERSION\t0xabcd0003\t\t\t// as of 3/14/2001 (and as of 2/12/2002)\r\n\r\nstruct SPreHeader\r\n{\r\n\tint\t\tmSize;\r\n\tint\t\tmVersion;\r\n\tint\t\tmNumFiles;\r\n};\r\n\r\n\r\nstruct SPreContained\r\n{\r\n\tuint32\tmDataSize;\r\n\tuint32\tmCompressedSize;\r\n\tuint16\tmNameSize;\r\n\r\n\t// In makepre.cpp, mNameSize is stored in 4 bytes. When the pre is in memory though, I'm\r\n\t// borrowing the two high bytes to use as a usage indicator to indicate whether this\r\n\t// contained file is 'open', ie has had Load called on it. The count value is the number\r\n\t// of times the file has been opened using Load. Gets decremented when Unload is called.\r\n\t// (The LoadPre function checks that they are all zero to start with when a new pre is loaded)\r\n\tuint16  mUsage;\r\n\r\n\t// Mick - added space for a checksum of mpName\r\n\t// as otherwise we spend over five seconds at boot up in re-calculating checksums n^2 times\t\r\n\tuint32 \tmChecksum;\r\n\t\r\n\t// Keep mpName the last member of this struct, cos I calculate the space used by the other\r\n\t// members by subtracting &p->mDataSize from p->mpName.\r\n\t// mpName will probably not move anyway, cos this strcture is part of the pre file format.\r\n\tchar\tmpName[1];\r\n};\r\n\r\n\r\n\r\nstatic SPreContained *sSkipToNextPreContained(SPreContained *p_preContained, EQuadAligned quadWordAlignedData=QUAD_WORD_ALIGNED);\r\nstatic SPreHeader \t *sSkipOverPreName(const char *p_pre_name);\r\nstatic SPreContained *sSeeIfFileIsInAnyPre(uint32 fileNameCRC);\r\n#ifdef __NOPT_ASSERT__\r\nstatic const char \t *sGetPreName(SPreContained *p_contained_file);\r\n#endif\r\n\r\n#define MAX_PRE_FILES 100\r\n// char* because each pre is prefixed with the name of the pre.\r\nstatic char *spp_pre_files[MAX_PRE_FILES];\r\n\r\nstruct SUnPreedFile\r\n{\r\n\tuint8 *mpFileData;\r\n\tuint32 mFileNameChecksum;\r\n\tuint32 mFileSize;\r\n\tuint32 mUsage;\r\n};\r\n\r\n#define MAX_UNPREED_FILES 200\r\nstatic SUnPreedFile sp_unpreed_files[MAX_UNPREED_FILES];\r\n\r\n// This class only exists so that I can declare an instance of it and hence\r\n// use its constructor to initialise the above arrays.\r\n// Saves me having to call an init function from somewhere early on in the code,\r\n// which might get moved around later and cause problems.\r\n// This way, the arrays are guaranteed to have got initialised even before main() is\r\n// called. I think ...\r\nclass CInit\r\n{\r\npublic:\r\n\tCInit()\r\n\t{\r\n\t\tint i;\r\n\r\n\t\tfor (i=0; i<MAX_PRE_FILES; ++i)\r\n\t\t{\r\n\t\t\tspp_pre_files[i]=NULL;\r\n\t\t}\r\n\r\n\t\tfor (i=0; i<MAX_UNPREED_FILES; ++i)\r\n\t\t{\r\n\t\t\tsp_unpreed_files[i].mpFileData=NULL;\r\n\t\t\tsp_unpreed_files[i].mFileNameChecksum=0;\r\n\t\t\tsp_unpreed_files[i].mFileSize=0;\r\n\t\t\tsp_unpreed_files[i].mUsage=0;\r\n\t\t}\r\n\t}\r\n};\r\nstatic CInit s_initter;\r\n\r\n// Given a pointer to a SPreContained, this will calculate a pointer to the next.\r\n// When used on a source pre quadWordAlignedData should be set to NOT_QUAD_WORD_ALIGNED, since the\r\n// contained files are not aligned in the pre files on disc.\r\n// When used on the processed pre, quadWordAlignedData should be set to QUAD_WORD_ALIGNED, which is its default value.\r\nstatic SPreContained *sSkipToNextPreContained(SPreContained *p_preContained, EQuadAligned quadWordAlignedData)\r\n{\r\n\tDbg_MsgAssert(p_preContained,(\"NULL p_preContained\"));\r\n\r\n\r\n\tint total_data_size=p_preContained->mDataSize;\r\n\tif (p_preContained->mCompressedSize)\r\n\t{\r\n\t\ttotal_data_size=p_preContained->mCompressedSize;\r\n\t}\r\n\ttotal_data_size=(total_data_size+3)&~3;\r\n\r\n//\tprintf (\"p_preContained = %p\\n, total_data = %d, name = (%p) %s\",p_preContained,total_data_size,p_preContained->mpName,p_preContained->mpName);\r\n\t\r\n\tuint32 p_next=(uint32)p_preContained->mpName;\r\n\tp_next+=p_preContained->mNameSize;\r\n\tif (quadWordAlignedData)\r\n\t{\r\n\t\tp_next=(p_next+15)&~15;\r\n\t}\r\n\tp_next+=total_data_size;\r\n\r\n\treturn (SPreContained*)p_next;\r\n}\r\n\r\nstatic SPreHeader *sSkipOverPreName(const char *p_pre_name)\r\n{\r\n\tDbg_MsgAssert(p_pre_name,(\"NULL p_pre_name\"));\r\n\r\n\tint len=strlen(p_pre_name)+1; // +1 for terminator\r\n\tlen=(len+15)&~15;\t// Round up to a multiple of 16\r\n\treturn (SPreHeader*)(p_pre_name+len);\r\n}\r\n\r\n// Loads a pre file into memory. The name must have no path since the pre is\r\n// assumed to be in the data\\pre directory.\r\n// Ie, a valid name would be \"alc.pre\"\r\nvoid LoadPre(const char *p_preFileName)\r\n{\r\n\tDbg_MsgAssert(p_preFileName,(\"NULL p_preFileName\"));\r\n\r\n\t// Check to see if the pre is already loaded, and return without doing anything if it is.\r\n\tfor (int i=0; i<MAX_PRE_FILES; ++i)\r\n\t{\r\n\t\tif (spp_pre_files[i])\r\n\t\t{\r\n\t\t\t// Do a case-insensitive comparison.\r\n\t\t\tif (stricmp(spp_pre_files[i],p_preFileName)==0)\r\n\t\t\t{\r\n\t\t\t\t// Found it! Nothing to do.\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Not loaded already, so need to load it.\r\n\t// Find a spare slot ...\r\n\tint spare_index=-1;\r\n\tfor (int pre=0; pre<MAX_PRE_FILES; ++pre)\r\n\t{\r\n\t\tif (!spp_pre_files[pre])\r\n\t\t{\r\n\t\t\tspare_index=pre;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tDbg_MsgAssert(spare_index!=-1, (\"Reached limit of %d pre files loaded at once.\",MAX_PRE_FILES));\r\n\r\n\t// Prefix with 'pre\\'\r\n\tchar p_full_pre_name[500];\r\n\tDbg_MsgAssert(strlen(p_preFileName)<400,(\"Pre name too long: '%s'\",p_preFileName));\r\n\tsprintf(p_full_pre_name,\"pre\\\\%s\",p_preFileName);\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tprintf(\"Loading pip pre '%s'\\n\",p_preFileName);\r\n\t#endif\r\n\r\n\t// Calculate the space needed to store the pre name, which will get stuck before the\r\n\t// file data.\r\n\tint name_size=strlen(p_preFileName)+1;\r\n\tname_size=(name_size+15)&~15;\r\n\r\n\r\n\r\n\tchar *p_old_file_data=NULL;\r\n\tuint32 original_file_size = File::CanFileBeLoadedQuickly( p_full_pre_name );\r\n\tuint32 old_pre_buffer_size=0;\r\n\r\n\tif (original_file_size)\r\n\t{\r\n\t\t// Goody! It can be loaded quickly.\r\n\r\n\t\told_pre_buffer_size=(original_file_size+2047)&~2047;\r\n\t\told_pre_buffer_size+=name_size;\r\n\r\n\t\tp_old_file_data=(char*)Mem::Malloc(old_pre_buffer_size);\r\n\t\tDbg_MsgAssert(p_old_file_data,(\"Could not allocate memory for file %s\",p_full_pre_name));\r\n\r\n\t\t// Copy in the pre name at the start of the buffer.\r\n\t\tstrcpy(p_old_file_data,p_preFileName);\r\n\r\n\t\tbool fileLoaded = File::LoadFileQuicklyPlease( p_full_pre_name, (uint8*)(p_old_file_data+name_size) );\r\n\t\tif ( !fileLoaded )\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0,( \"File %s failed to load quickly.\\n\", p_full_pre_name));\r\n\t\t\tMem::Free(p_old_file_data);\r\n\t\t\tp_old_file_data=NULL;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Open the file & get its file size\r\n\t\tvoid *p_file = File::Open(p_full_pre_name, \"rb\");\r\n\r\n\t\tif (!p_file)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"Could not open file %s\",p_full_pre_name));\r\n\t\t}\r\n\r\n\t\toriginal_file_size=File::GetFileSize(p_file);\r\n\t\tif (!original_file_size)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(0,(\"Zero file size for file %s\",p_full_pre_name));\r\n\t\t}\r\n\r\n\r\n\t\t// Allocate memory.\r\n\t\t// Just to be safe, make sure the buffer is at least the file size rounded up to the\r\n\t\t// next multiple of 2048, cos maybe loading a file off CD will always load\r\n\t\t// whole numbers of sectors.\r\n\t\t// Haven't checked that though.\r\n\t\told_pre_buffer_size=(original_file_size+2047)&~2047;\r\n\t\told_pre_buffer_size+=name_size;\r\n\r\n\t\tp_old_file_data=(char*)Mem::Malloc(old_pre_buffer_size);\r\n\t\tDbg_MsgAssert(p_old_file_data,(\"Could not allocate memory for file %s\",p_full_pre_name));\r\n\r\n\t\t// Copy in the pre name at the start of the buffer.\r\n\t\tstrcpy(p_old_file_data,p_preFileName);\r\n\r\n\t\t// Load the file into memory then close the file.\r\n\t\t#ifdef __NOPT_ASSERT__\r\n\t\tlong bytes_read=File::Read(p_old_file_data+name_size, 1, original_file_size, p_file);\r\n\t\tDbg_MsgAssert(bytes_read<=(long)original_file_size,(\"bytes_read>original_file_size ?\"));\r\n\t\t#else\r\n\t\tFile::Read(p_old_file_data+name_size, 1, original_file_size, p_file);\r\n\t\t#endif\r\n\r\n\t\tFile::Close(p_file);\r\n\t}\r\n\r\n\r\n\t// Calculate the new buffer size required.\r\n\t// Note that even if no decompression is required, the new buffer will probably need to\r\n\t// be bigger than the old, because the contained files need to be moved so that they all start\r\n\t// on 16 byte boundaries. This is required by the collision code for example.\r\n\r\n\tuint32 new_pre_buffer_size=name_size;\r\n\tnew_pre_buffer_size+=sizeof(SPreHeader);\r\n\r\n\tSPreHeader *p_pre_header=sSkipOverPreName(p_old_file_data);\r\n\tuint32 num_files=p_pre_header->mNumFiles;\r\n\tSPreContained *p_contained=(SPreContained*)(p_pre_header+1);\r\n\tfor (uint32 f=0; f<num_files; ++f)\r\n\t{\r\n\t\t// Do a quick check to make sure that all the usage values are initially zero.\r\n\t\t// They should be, because the namesize member should never be bigger than 65535 ...\r\n\t\tDbg_MsgAssert(p_contained->mUsage==0,(\"The file %s in %s has mUsage=%d ??\",p_contained->mpName,p_preFileName,p_contained->mUsage));\r\n\r\n\t\tnew_pre_buffer_size+=(uint32)p_contained->mpName-(uint32)p_contained;\r\n\t\tnew_pre_buffer_size+=p_contained->mNameSize;\r\n\r\n\t\tnew_pre_buffer_size=(new_pre_buffer_size+15)&~15;\r\n\r\n\t\tnew_pre_buffer_size+=(p_contained->mDataSize+3)&~3;\r\n\r\n\t\tp_contained=sSkipToNextPreContained(p_contained,NOT_QUAD_WORD_ALIGNED);\r\n\t}\r\n\r\n\t// Need to add a small margin to prevent decompressed data overtaking the compressed data.\r\n\tnew_pre_buffer_size+=IN_PLACE_DECOMPRESSION_MARGIN;\r\n\r\n\t// At this point we have:\r\n\t//\r\n\t// original_file_size\tThe exact size of the original pre file. Will be a multiple of 4.\r\n\t//\r\n\t// name_size\t\t\tThe size of the pre name, rounded up to a multiple of 4\r\n\t//\r\n\t// old_pre_buffer_size\tThe size of the memory buffer pointed to by p_old_file_data\r\n\t//\t\t\t\t\t\tEquals name_size +  (original_file_size, rounded up to a multiple of 2048)\r\n\t//\r\n\t// new_pre_buffer_size\tThe required size of the new buffer, to contain the decompressed pre,\r\n\t//\t\t\t\t\t\twith all the files moved to be at 16 byte boundaries.\r\n\t//\r\n\r\n\t#ifdef __NOPT_ASSERT__\r\n\tprintf(\"Decompressing and rearranging pre file ...\\n\");\r\n\t#endif\r\n\r\n\t// Note: It does not matter if new_pre_buffer_size is not a multiple of 2048 any more.\r\n\t// old_pre_buffer_size was only a multiple of 2048 to ensure that the file loading\r\n\t// did not overrun the end of the buffer. I think file loading may only load a whole\r\n\t// number of sectors.\r\n\r\n\r\n\t// Reallocate the buffer.\r\n\tchar *p_new_file_data=NULL;\r\n\tif (Mem::Manager::sHandle().GetContextDirection()==Mem::Allocator::vTOP_DOWN)\r\n\t{\r\n\t\t// If using the top-down heap expand the buffer downwards ...\r\n\r\n\t\t// p_new_file_data will become a pointer lower down in memory than p_old_file_data.\r\n\t\t// The old data pointed to by p_old_file_data will still be there.\r\n\t\t// The memory between p_new_file_data and p_old_file_data is all free to use. Hoorah!\r\n\t\tp_new_file_data=(char*)Mem::ReallocateDown(new_pre_buffer_size,p_old_file_data);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// If using the top-down heap expand the buffer upwards ...\r\n\t\tp_new_file_data=(char*)Mem::ReallocateUp(new_pre_buffer_size,p_old_file_data);\r\n\t\tDbg_MsgAssert(p_new_file_data,(\"ReallocateUp failed!\"));\r\n\r\n\t\t// Now need to move the data up so that it can be decompressed into the gap below.\r\n\t\tuint32 *p_source=(uint32*)(p_old_file_data+old_pre_buffer_size);\r\n\t\tuint32 *p_dest=(uint32*)(p_new_file_data+new_pre_buffer_size);\r\n\t\t// Loading backwards cos the destination overlaps the source.\r\n\r\n\t\t// Note: Did some timing tests to see if this was was slow, but it's not really.\r\n\t\t// To load all the pre files in the game, one after the other, takes an average of\r\n\t\t// 32.406 seconds when the top down heap is used. When using the bottom up, which\r\n\t\t// necessitates doing this copy, it takes 33.518 seconds.\r\n\t\t// So per pre file that isn't much. (There's about 60 pre files)\r\n\t\tDbg_MsgAssert((old_pre_buffer_size&3)==0,(\"old_pre_buffer_size not a multiple of 4 ?\"));\r\n\t\tuint32 num_longs=old_pre_buffer_size/4;\r\n\t\tfor (uint32 i=0; i<num_longs; ++i)\r\n\t\t{\r\n\t\t\t--p_source;\r\n\t\t\t--p_dest;\r\n\t\t\t*p_dest=*p_source;\r\n\t\t}\r\n\r\n\t\t// Now update p_old_file_data to point where it should.\r\n\t\tp_old_file_data=p_new_file_data+new_pre_buffer_size-old_pre_buffer_size;\r\n\t}\r\n\r\n\t// Copy the pre name down.\r\n\tfor (int i=0; i<name_size; ++i)\r\n\t{\r\n\t\tp_new_file_data[i]=p_old_file_data[i];\r\n\t}\r\n\r\n\t// Write in the new pre header\r\n\tSPreHeader *p_source_header=(SPreHeader*)(p_old_file_data+name_size);\r\n\tSPreHeader *p_dest_header=(SPreHeader*)(p_new_file_data+name_size);\r\n\tp_dest_header->mNumFiles=p_source_header->mNumFiles;\r\n\tp_dest_header->mVersion=p_source_header->mVersion;\r\n\r\n\t// Copy down each of the contained files, decompressing those that need it.\r\n\tSPreContained *p_source_contained=(SPreContained*)(p_source_header+1);\r\n\tSPreContained *p_dest_contained=(SPreContained*)(p_dest_header+1);\r\n\tfor (uint32 f=0; f<num_files; ++f)\r\n\t{\r\n\t\t// Copy down the contained file's header.\r\n\t\tp_dest_contained->mDataSize=p_source_contained->mDataSize;\r\n\t\tp_dest_contained->mChecksum=p_source_contained->mChecksum;\r\n\t\tp_dest_contained->mCompressedSize=0; // The new file will not be compressed.\r\n\t\tp_dest_contained->mUsage=0;\r\n\t\tp_dest_contained->mNameSize=p_source_contained->mNameSize;\r\n\t\tfor (int i=0; i<p_source_contained->mNameSize; ++i)\r\n\t\t{\r\n\t\t\tp_dest_contained->mpName[i]=p_source_contained->mpName[i];\r\n\t\t}\r\n\r\n\t\t// Pre-calculate p_next_source_contained because decompression may (and often will)\r\n\t\t// cause the new data to overwrite the contents of p_source_contained.\r\n\t\tSPreContained *p_next_source_contained=sSkipToNextPreContained(p_source_contained,NOT_QUAD_WORD_ALIGNED);\r\n\r\n\t\tuint8 *p_source=(uint8*)(p_source_contained->mpName+p_source_contained->mNameSize);\r\n\t\tuint8 *p_dest=(uint8*)(p_dest_contained->mpName+p_dest_contained->mNameSize);\r\n\t\tp_dest=(uint8*)( ((uint32)p_dest+15)&~15 );\r\n\r\n\t\tif (p_source_contained->mCompressedSize)\r\n\t\t{\r\n\t\t\tuint32 num_bytes_decompressed=p_dest_contained->mDataSize;\r\n\t\t\tuint8 *p_end=DecodeLZSS(p_source,p_dest,p_source_contained->mCompressedSize);\r\n\t\t\tDbg_MsgAssert(p_end==p_dest+num_bytes_decompressed,(\"Eh? DecodeLZSS wrote %d bytes, expected it to write %d\",p_end-p_dest,num_bytes_decompressed));\r\n\r\n\t\t\t// For neatness, write zero's into the pad bytes at the end, otherwise they'll\r\n\t\t\t// be uninitialised data.\r\n\t\t\twhile (num_bytes_decompressed & 3)\r\n\t\t\t{\r\n\t\t\t\t*p_end++=0;\r\n\t\t\t\t++num_bytes_decompressed;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Uncompressed, so just copy the data down.\r\n\t\t\tuint32 *p_source_long=(uint32*)p_source;\r\n\t\t\tuint32 *p_dest_long=(uint32*)p_dest;\r\n\t\t\t// mDataSize is not necessarily a multiple of 4, but the actual data will be\r\n\t\t\t// padded at the end so that it does occupy a whole number of long words.\r\n\t\t\t// So the +3 is to ensure that n is rounded up to the next whole number of longs.\r\n\t\t\tuint32 n=(p_source_contained->mDataSize+3)/4;\r\n\r\n\t\t\tfor (uint32 i=0; i<n; ++i)\r\n\t\t\t{\r\n\t\t\t\t*p_dest_long++=*p_source_long++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_source_contained=p_next_source_contained;\r\n\r\n\t\tp_dest_contained=sSkipToNextPreContained(p_dest_contained);\r\n\t}\r\n\r\n\t// I don't think I ever need to reference mSize again, but might as well make it correct.\r\n\tp_dest_header->mSize=(uint32)p_dest_contained-(uint32)p_dest_header;\r\n\r\n\t//printf(\"Wasted space = %d\\n\",new_pre_buffer_size-((uint32)p_dest_contained-(uint32)p_new_file_data));\r\n\r\n\tspp_pre_files[spare_index]=p_new_file_data;\r\n\t#ifdef __NOPT_ASSERT__\r\n\tprintf(\"Done\\n\");\r\n\t#endif\r\n}\r\n\r\n// Removes the specified pre from memory. The name must have no path since the pre is\r\n// assumed to be in the data\\pre directory.\r\n// Ie, a valid name would be \"alc.pre\"\r\n//\r\n// Won't do anything if the pre is gone already.\r\n// Asserts if any of the files in the pre are still 'open' in that they haven't had Unload called.\r\nbool UnloadPre(const char *p_preFileName)\r\n{\r\n\tbool success = false;\r\n\r\n\tDbg_MsgAssert(p_preFileName,(\"NULL p_preFileName\"));\r\n\r\n\tfor (int i=0; i<MAX_PRE_FILES; ++i)\r\n\t{\r\n\t\tif (spp_pre_files[i])\r\n\t\t{\r\n\t\t\t// Do a case-insensitive comparison.\r\n\t\t\tif (stricmp(spp_pre_files[i],p_preFileName)==0)\r\n\t\t\t{\r\n\t\t\t\t// Found it!\r\n\r\n\t\t\t\t// Before unloading it, make sure none of the files within is still open.\r\n\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\tSPreHeader *p_pre_header=sSkipOverPreName(spp_pre_files[i]);\r\n\t\t\t\tint num_files=p_pre_header->mNumFiles;\r\n\t\t\t\tSPreContained *p_contained=(SPreContained*)(p_pre_header+1);\r\n\t\t\t\tfor (int f=0; f<num_files; ++f)\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(!p_contained->mUsage,(\"Tried to unload %s when the file %s contained within it was still open! (mUsage=%d)\",spp_pre_files[i],p_contained->mpName,p_contained->mUsage));\r\n\t\t\t\t\tp_contained=sSkipToNextPreContained(p_contained);\r\n\t\t\t\t}\r\n\t\t\t\t#endif\r\n\r\n\t\t\t\t// Delete it.\r\n\t\t\t\tMem::Free(spp_pre_files[i]);\r\n\t\t\t\tspp_pre_files[i]=NULL;\r\n\r\n\t\t\t\t// we've successfully unloaded a pre\r\n\t\t\t\tsuccess = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Not found, so nothing to do.\r\n\treturn success;\r\n}\r\n\r\n// Searches each of the loaded pre files for the passed contained file.\r\n// Returns NULL if not found.\r\nstatic SPreContained *sSeeIfFileIsInAnyPre(uint32 fileNameCRC)\r\n{\r\n\tfor (int i=0; i<MAX_PRE_FILES; ++i)\r\n\t{\r\n\t\tif (spp_pre_files[i])\r\n\t\t{\r\n\t\t\tSPreHeader *p_pre_header=sSkipOverPreName(spp_pre_files[i]);\r\n\t\t\tint num_files=p_pre_header->mNumFiles;\r\n\t\t\tSPreContained *p_contained=(SPreContained*)(p_pre_header+1);\r\n\t\t\tfor (int f=0; f<num_files; ++f)\r\n\t\t\t{\r\n\t\t\t\t//Dbg_MsgAssert(Crc::GenerateCRCFromString(p_contained->mpName) == p_contained->mChecksum,\r\n\t\t\t\t//(\"Checksum for %s (%x) not %x\",p_contained->mpName,Crc::GenerateCRCFromString(p_contained->mpName),p_contained->mChecksum));\r\n\t\t\t\t//if ( Crc::GenerateCRCFromString(p_contained->mpName) == fileNameCRC )\r\n\t\t\t\tif ( p_contained->mChecksum == fileNameCRC )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn p_contained;\r\n\t\t\t\t}\r\n\t\t\t\tp_contained=sSkipToNextPreContained(p_contained);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn NULL;\r\n}\r\n\r\n#ifdef __NOPT_ASSERT__\r\n// Finds which pre the passed file is contained in, and returns a pointer to the pre name.\r\n// Returns \"Unknown\" if not found anywhere.\r\nstatic const char *sGetPreName(SPreContained *p_contained_file)\r\n{\r\n\tfor (int i=0; i<MAX_PRE_FILES; ++i)\r\n\t{\r\n\t\tif (spp_pre_files[i])\r\n\t\t{\r\n\t\t\tSPreHeader *p_pre_header=sSkipOverPreName(spp_pre_files[i]);\r\n\t\t\tint num_files=p_pre_header->mNumFiles;\r\n\t\t\tSPreContained *p_contained=(SPreContained*)(p_pre_header+1);\r\n\t\t\tfor (int f=0; f<num_files; ++f)\r\n\t\t\t{\r\n\t\t\t\tif (p_contained==p_contained_file)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn spp_pre_files[i];\r\n\t\t\t\t}\r\n\t\t\t\tp_contained=sSkipToNextPreContained(p_contained);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn \"Unknown\";\r\n}\r\n#endif\r\n\r\nvoid* Load(const char* p_fileName)\r\n{\r\n\tuint32 filename_checksum=Crc::GenerateCRCFromString(p_fileName);\r\n\t\r\n\t// First, see if the file is in one of the loaded pre files.\r\n\tSPreContained *p_contained_file=sSeeIfFileIsInAnyPre( filename_checksum );\r\n\tif (p_contained_file)\r\n\t{\r\n\t\t++p_contained_file->mUsage;\r\n\r\n\t\tDbg_MsgAssert(p_contained_file->mCompressedSize==0,(\"The file '%s' is stored compressed in %s !\",p_fileName,sGetPreName(p_contained_file)));\r\n\r\n\t\tuint32 p_data=(uint32)p_contained_file->mpName+p_contained_file->mNameSize;\r\n\t\tp_data=(p_data+15)&~15;\r\n\t\treturn (void*)p_data;\r\n\t}\r\n\r\n\t// Next, see if it is one of the unpreed files that is already loaded.\r\n\tfor (int i=0; i<MAX_UNPREED_FILES; ++i)\r\n\t{\r\n\t\tif (sp_unpreed_files[i].mpFileData)\r\n\t\t{\r\n\t\t\tif (sp_unpreed_files[i].mFileNameChecksum==filename_checksum)\r\n\t\t\t{\r\n\t\t\t\t// It is already loaded, so increment the usage and return the pointer.\r\n\t\t\t\t++sp_unpreed_files[i].mUsage;\r\n\r\n\t\t\t\tDbg_MsgAssert(sp_unpreed_files[i].mpFileData,(\"NULL sp_unpreed_files[i].mpFileData ?\"));\r\n\t\t\t\treturn sp_unpreed_files[i].mpFileData;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// It's not in a pre, and it is not already loaded, so load it.\r\n\r\n\t// Find a free slot.\r\n\tSUnPreedFile *p_new_unpreed_file=NULL;\r\n\tfor (int i=0; i<MAX_UNPREED_FILES; ++i)\r\n\t{\r\n\t\tif (!sp_unpreed_files[i].mpFileData)\r\n\t\t{\r\n\t\t\tp_new_unpreed_file=&sp_unpreed_files[i];\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tDbg_MsgAssert(p_new_unpreed_file,(\"Too many unpreed files open at once! Max=%d (MAX_UNPREED_FILES in pip.cpp)\",MAX_UNPREED_FILES));\r\n\r\n\t// allocate memory, and load the file\r\n\tint\tfile_size;\r\n\tuint8 * p_file_data = (uint8*) File::LoadAlloc(p_fileName,&file_size);\r\n\tDbg_MsgAssert(p_file_data,(\"Failsed to load %s\\n\",p_fileName));\r\n\r\n\t// Fill in the slot.\r\n\tp_new_unpreed_file->mpFileData=p_file_data;\r\n\tp_new_unpreed_file->mFileSize=file_size;\r\n\r\n\tp_new_unpreed_file->mFileNameChecksum=filename_checksum;\r\n\tp_new_unpreed_file->mUsage=1;\r\n\r\n\treturn p_file_data;\r\n}\r\n\r\nvoid Unload(uint32 fileNameCRC)\r\n{\r\n\t// See if it is one of the unpreed files.\r\n\t#ifdef __NOPT_ASSERT__\r\n\tbool is_an_unpreed_file=false;\r\n\t#endif\r\n\tfor (int i=0; i<MAX_UNPREED_FILES; ++i)\r\n\t{\r\n\t\tif (sp_unpreed_files[i].mpFileData)\r\n\t\t{\r\n\t\t\tif ( sp_unpreed_files[i].mFileNameChecksum == fileNameCRC )\r\n\t\t\t{\r\n\t\t\t\t// Decrement the usage\r\n\t\t\t\tif (sp_unpreed_files[i].mUsage)\r\n\t\t\t\t{\r\n\t\t\t\t\t--sp_unpreed_files[i].mUsage;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Free up the memory if nothing is using this file any more.\r\n\t\t\t\tif (sp_unpreed_files[i].mUsage==0)\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::Free(sp_unpreed_files[i].mpFileData);\r\n\t\t\t\t\tsp_unpreed_files[i].mpFileData=NULL;\r\n\r\n\t\t\t\t\tsp_unpreed_files[i].mFileSize=0;\r\n\t\t\t\t\tsp_unpreed_files[i].mFileNameChecksum=0;\r\n\t\t\t\t\tsp_unpreed_files[i].mUsage=0;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\tis_an_unpreed_file=true;\r\n\t\t\t\t#endif\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tSPreContained *p_contained_file=sSeeIfFileIsInAnyPre(fileNameCRC);\r\n\tif (p_contained_file)\r\n\t{\r\n\t\tDbg_MsgAssert(!is_an_unpreed_file,(\"Tried to unload '%s' which was loaded unpreed, but also exists in %s ?\",p_contained_file->mpName,sGetPreName(p_contained_file)));\r\n\r\n\t\t// Decrement the usage.\r\n\t\tif (p_contained_file->mUsage)\r\n\t\t{\r\n\t\t\t--p_contained_file->mUsage;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n// If the file is unpreed, this will decrement the usage and free the memory specially allocated\r\n// for it if the usage has reached zero.\r\n// If the file is in a loaded pre, it will decrement that files usage in the pre.\r\n// If the file is both of the above, it will assert.\r\n// If it is neither, it won't do anything.\r\nvoid Unload(const char *p_fileName)\r\n{\r\n\tDbg_MsgAssert(p_fileName,(\"NULL p_fileName\"));\r\n\r\n\tUnload( Crc::GenerateCRCFromString(p_fileName) );\r\n}\r\n\r\nuint32 GetFileSize(uint32 fileNameCRC)\r\n{\r\n\t// See if it is one of the unpreed files.\r\n\t#ifdef __NOPT_ASSERT__\r\n\tbool is_an_unpreed_file=false;\r\n\t#endif\r\n\tfor (int i=0; i<MAX_UNPREED_FILES; ++i)\r\n\t{\r\n\t\tif (sp_unpreed_files[i].mpFileData)\r\n\t\t{\r\n\t\t\tif ( sp_unpreed_files[i].mFileNameChecksum == fileNameCRC )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(sp_unpreed_files[i].mFileSize,(\"Zero mFileSize ??\"));\r\n\t\t\t\treturn sp_unpreed_files[i].mFileSize;\r\n\r\n\t\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\t\tis_an_unpreed_file=true;\r\n\t\t\t\t#endif\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tSPreContained *p_contained_file=sSeeIfFileIsInAnyPre( fileNameCRC );\r\n\tif (p_contained_file)\r\n\t{\r\n\t\tDbg_MsgAssert(!is_an_unpreed_file,(\"'%s' is both unpreed, and also exists in %s ?\",p_contained_file->mpName,sGetPreName(p_contained_file)));\r\n\t\tDbg_MsgAssert(p_contained_file->mDataSize,(\"Zero mDataSize ??\"));\r\n\t\treturn p_contained_file->mDataSize;\r\n\t}\r\n\r\n//\tDbg_MsgAssert(0,(\"File '%s' not found loaded anywhere\",p_fileName));\r\n\treturn 0;\r\n}\r\n\r\nuint32 GetFileSize(const char *p_fileName)\r\n{\r\n\tDbg_MsgAssert(p_fileName,(\"NULL p_fileName\"));\r\n\r\n\tuint32 file_size = GetFileSize( Crc::GenerateCRCFromString(p_fileName) );\r\n\r\n\tif ( file_size == 0 )\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"File '%s' not found loaded anywhere\",p_fileName));\r\n\t}\r\n\r\n\treturn file_size;\r\n}\r\n\r\nconst char *GetNextLoadedPre(const char *p_pre_name)\r\n{\r\n\tif (p_pre_name==NULL)\r\n\t{\r\n\t\tfor (int i=0; i<MAX_PRE_FILES; ++i)\r\n\t\t{\r\n\t\t\tif (spp_pre_files[i])\r\n\t\t\t{\r\n\t\t\t\treturn spp_pre_files[i];\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tbool found=false;\r\n\tfor (int i=0; i<MAX_PRE_FILES; ++i)\r\n\t{\r\n\t\tif (spp_pre_files[i])\r\n\t\t{\r\n\t\t\tif (found)\r\n\t\t\t{\r\n\t\t\t\treturn spp_pre_files[i];\r\n\t\t\t}\r\n\t\t\t// Do a case-insensitive comparison.\r\n\t\t\tif (stricmp(spp_pre_files[i],p_pre_name)==0)\r\n\t\t\t{\r\n\t\t\t\tfound=true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\nbool PreFileIsInUse(const char *p_pre_name)\r\n{\r\n\tDbg_MsgAssert(p_pre_name,(\"NULL p_pre_name\"));\r\n\r\n\tfor (int i=0; i<MAX_PRE_FILES; ++i)\r\n\t{\r\n\t\tif (spp_pre_files[i])\r\n\t\t{\r\n\t\t\t// Do a case-insensitive comparison.\r\n\t\t\tif (stricmp(spp_pre_files[i],p_pre_name)==0)\r\n\t\t\t{\r\n\t\t\t\t// Found it!\r\n\r\n\t\t\t\tSPreHeader *p_pre_header=sSkipOverPreName(spp_pre_files[i]);\r\n\t\t\t\tint num_files=p_pre_header->mNumFiles;\r\n\t\t\t\tSPreContained *p_contained=(SPreContained*)(p_pre_header+1);\r\n\t\t\t\tfor (int f=0; f<num_files; ++f)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (p_contained->mUsage)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tp_contained=sSkipToNextPreContained(p_contained);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n// @script | LoadPipPre |\r\n// @uparm \"string\" | filename\r\n// @parmopt name | heap | 0 (checksum value) | Which heap to use.\r\n// Possible values are TopDown or BottomUp\r\n// If no heap is specified it will use whatever the current heap is.\r\nbool ScriptLoadPipPre(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_filename;\r\n\tpParams->GetString(NONAME, &p_filename, Script::ASSERT);\r\n\r\n\tuint32 chosen_heap=0;\r\n\tpParams->GetChecksum(\"Heap\",&chosen_heap);\r\n\tswitch (chosen_heap)\r\n\t{\r\n\t\tcase 0:\r\n\t\t\tchosen_heap = 0;\r\n\t\t\t// Use whatever the current heap is.\r\n\t\t\tbreak;\r\n\t\tcase 0x477fc6de: // TopDown\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\t\t\tbreak;\r\n\t\tcase 0xc80bf12d: // BottomUp\r\n\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_Warning(\"Heap '%s' not supported by LoadPipPre, using current heap instead.\",Script::FindChecksumName(chosen_heap));\r\n\t\t\tchosen_heap=0;\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tLoadPre(p_filename);\r\n\r\n\tif (chosen_heap)\r\n\t{\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n// @script | UnLoadPipPre |\r\n// @uparm \"string\" | filename\r\nbool ScriptUnloadPipPre(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tconst char *p_filename;\r\n\tpParams->GetString(NONAME, &p_filename, Script::ASSERT);\r\n\r\n\treturn UnloadPre(p_filename);\r\n}\r\n\r\n// @script | DumpPipPreStatus | Prints the status of the currently loaded pre files.\r\n// @flag ShowPreedFiles | Lists all the files contained within each pre, together with their usage value.\r\n// @flag ShowUnPreedFiles | Lists all the files currently open which were not in a pre,\r\n// so were individually opened.\r\n// @flag ShowOnlyOpenFiles | When listing the files in each pre, only display those whose usage is\r\n// greater than zero.\r\nbool ScriptDumpPipPreStatus(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tbool show_preed_files=pParams->ContainsFlag(\"ShowPreedFiles\");\r\n\tbool show_unpreed_files=pParams->ContainsFlag(\"ShowUnPreedFiles\");\r\n\tbool show_only_open_files=pParams->ContainsFlag(\"ShowOnlyOpenFiles\");\r\n\r\n\tprintf(\"Currently loaded pre files:\\n\");\r\n\r\n\tfor (int i=0; i<MAX_PRE_FILES; ++i)\r\n\t{\r\n\t\tif (spp_pre_files[i])\r\n\t\t{\r\n\t\t\tprintf(\"### %s ###\\n\",spp_pre_files[i]);\r\n\r\n\t\t\tif (show_preed_files)\r\n\t\t\t{\r\n\t\t\t\tSPreHeader *p_pre_header=sSkipOverPreName(spp_pre_files[i]);\r\n\t\t\t\tint num_files=p_pre_header->mNumFiles;\r\n\t\t\t\tSPreContained *p_contained=(SPreContained*)(p_pre_header+1);\r\n\t\t\t\tfor (int f=0; f<num_files; ++f)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!show_only_open_files || p_contained->mUsage)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tprintf(\"Usage:%d  File: %s\\n\",p_contained->mUsage,p_contained->mpName);\r\n\t\t\t\t\t\t// Delay so that printf does not break when there are lots of files.\r\n\t\t\t\t\t\tfor (volatile int pp=0; pp<100000; ++pp);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tp_contained=sSkipToNextPreContained(p_contained);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (show_unpreed_files)\r\n\t{\r\n\t\tprintf(\"Currently loaded un-preed files:\\n\");\r\n\r\n\t\tfor (int i=0; i<MAX_UNPREED_FILES; ++i)\r\n\t\t{\r\n\t\t\tif (sp_unpreed_files[i].mpFileData)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"Usage:%d  File: %s\\n\",sp_unpreed_files[i].mUsage,Script::FindChecksumName(sp_unpreed_files[i].mFileNameChecksum));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////\r\n// File:: functions\r\n// Should really be in filesys.cpp, but there is none!!!!\r\n\r\nnamespace File\r\n{\r\n\r\n\r\n// Load file as quickly as possible\r\n// Try loading from the pre manager first, then from the CD, using the \"quick filesys\"\r\n// then finally using the regular file loading functions\r\n// returns pointer to allocated memory, or NULL if file fails to load\r\n// optionally returns size of file in bytes, in *p_filesize (ignored if p_filesize is NULL)\r\n// if file fails to load, *p_filesize will be 0\r\n// if you pass in p_dest, you must also pass in maxSize, the size of the buffer\r\nvoid * LoadAlloc(const char *p_fileName, int *p_filesize, void *p_dest, int maxSize)\r\n{\r\n\r\n\t// Mick 2/19/2003 - Removed code that stripped project specific headers\r\n\t// as this is now handled at the gs_file level\r\n\t\r\n\tint\tfile_size = 0;\r\n// Perhaps the file is in a PRE file,  so try loading it directly, as that will be quickest\r\n\tuint8 *p_file_data = (uint8*)File::PreMgr::Instance()->LoadFile(p_fileName,&file_size, p_dest);\r\n\tif (!p_file_data)\r\n\t{\r\n\t\t// nope, so try loading \"Quickly\" (basically if we are on a CD)\r\n\t\tfile_size = File::CanFileBeLoadedQuickly( p_fileName );\r\n\t\tif (file_size)\r\n\t\t{\r\n\t\t\t// It can be loaded quickly.\r\n\t\t\tif (!p_dest)\r\n\t\t\t{\r\n\t\t\t\tp_file_data=(uint8*)Mem::Malloc((file_size+2047)&~2047);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_file_data = (uint8*)p_dest;\r\n\t\t\t}\r\n\r\n\t\t\tbool fileLoaded = File::LoadFileQuicklyPlease( p_fileName, p_file_data );\r\n\t\t\tif ( !fileLoaded )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( 0,( \"File %s failed to load quickly.\\n\", p_fileName));\r\n\t\t\t\tif (!p_dest)\r\n\t\t\t\t{\r\n\t\t\t\t\tMem::Free(p_file_data);\r\n\t\t\t\t}\r\n\t\t\t\tp_file_data=NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// can't load quickly, so probably loading from the PC\r\n\t\t\t// Open the file & get its file size\r\n\r\n\t\t\tvoid *p_file = File::Open(p_fileName, \"rb\");\r\n\t\t\tif (!p_file)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0,(\"Could not open file '%s'\",p_fileName));\r\n\t\t\t}\r\n\r\n\t\t\tfile_size=File::GetFileSize(p_file);\r\n\t\t\tif (!file_size)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(0,(\"Zero file size for file %s\",p_fileName));\r\n\t\t\t}\r\n\r\n\t\t\tif (!p_dest)\r\n\t\t\t{\r\n\t\t\t\t// Allocate memory.\r\n\t\t\t\t// Just to be safe, allocate a buffer of size file_size rounded up to the\r\n\t\t\t\t// next multiple of 2048, cos maybe loading a file off CD will always load\r\n\t\t\t\t// whole numbers of sectors.\r\n\t\t\t\t// Haven't checked that though.\r\n\t\t\t\tp_file_data=(uint8*)Mem::Malloc((file_size+2047)&~2047);\r\n\t\t\t\tDbg_MsgAssert(p_file_data,(\"Could not allocate memory for file %s\",p_fileName));\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_file_data = (uint8*)p_dest;\r\n\t\t\t}\r\n\t\t\t// Load the file into memory then close the file.\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tlong bytes_read=File::Read(p_file_data, 1, file_size, p_file);\r\n\t\t\tDbg_MsgAssert(bytes_read<=file_size,(\"bytes_read>file_size ?\"));\r\n\t\t\t#else\r\n\t\t\tFile::Read(p_file_data, 1, file_size, p_file);\r\n\t\t\t#endif\r\n\r\n\t\t\tFile::Close(p_file);\r\n\t\t}\r\n\t\t// Shrink memory back down to accurate usage - saves 43K total in the school!!!\r\n\t\tif (!p_dest && p_file_data)\r\n\t\t{\r\n\t\t\tMem::ReallocateShrink(file_size,p_file_data);\r\n\t\t}\r\n\t}\r\n\tif (p_filesize)\r\n\t{\r\n\t\t*p_filesize = file_size;\r\n\t}\r\n\t// If we specified a destination, then make sure we did not overflow it\r\n\tif (p_dest)\r\n\t{\r\n\t\tDbg_MsgAssert(((file_size + 2047)&~2047) < maxSize,(\"file size (%d) overflows buffer (%d) for %s\\n\",file_size,maxSize,p_fileName));\r\n\t}\r\n\treturn (void *)p_file_data;\r\n}\r\n\r\n\r\n}\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/File/pip.h",
    "content": "#ifndef\t__FILE_PIP_H\r\n#define\t__FILE_PIP_H\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n}\t\r\n\r\nnamespace Pip\r\n{\r\nvoid\tLoadPre(const char *p_preFileName);\r\nbool\tUnloadPre(const char *p_preFileName);\r\n\r\nvoid*\tLoad(const char *p_fileName);\r\nvoid\tUnload(const char *p_fileName);\r\nuint32\tGetFileSize(const char *p_fileName);\r\n\r\n// GJ:  sometimes it's useful to do this\r\n// by checksum, so that we don't have to keep \r\n// the full filename string hanging around\r\nvoid\tUnload(uint32 fileNameCRC);\r\nuint32\tGetFileSize(uint32 fileNameCRC);\r\n\r\nconst char *GetNextLoadedPre(const char *p_pre_name=NULL);\r\nbool PreFileIsInUse(const char *p_pre_name);\r\n\r\nbool ScriptLoadPipPre(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptUnloadPipPre(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptDumpPipPreStatus(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Sys/McMan.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemCard  (Mc)\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsys/mcman.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t03/06/2001\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __SYS_MCMAN_H\r\n#define __SYS_MCMAN_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/singleton.h>\r\n#ifdef __PLAT_NGC__\r\n#include <dolphin.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mc\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass Card;\r\n\r\nclass DateTime\r\n{\r\npublic:\r\n\tunsigned char \tm_Seconds;\r\n\tunsigned char\tm_Minutes;\r\n\tunsigned char \tm_Hour;\r\n\tunsigned char \tm_Day;\r\n\tunsigned char \tm_Month;\r\n\tunsigned short\tm_Year;\r\n};\r\n\r\nclass File : public Lst::Node< File >\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tmMODE_READ\t\t= 0x0001,\r\n\t\tmMODE_WRITE\t\t= 0x0002,\r\n\t\tmMODE_CREATE\t= 0x0004,\r\n\t};\r\n\r\n\tenum FilePointerBase\r\n\t{\r\n\t\tBASE_START,\r\n\t\tBASE_CURRENT,\r\n\t\tBASE_END,\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n\t\tmATTRIB_READABLE\t\t= 0x0001,\r\n\t\tmATTRIB_WRITEABLE\t\t= 0x0002,\r\n\t\tmATTRIB_EXECUTABLE\t\t= 0x0004,\r\n\t\tmATTRIB_DUP_PROHIBITED\t= 0x0008,\r\n\t\tmATTRIB_DIRECTORY\t\t= 0x0010,\r\n\t\tmATTRIB_CLOSED\t\t\t= 0x0020,\r\n\t\tmATTRIB_PDA_APP\t\t\t= 0x0040,\r\n\t\tmATTRIB_PS1_FILE\t\t= 0x0080,\r\n\t};\r\n\tenum\r\n\t{\r\n\t\tvMAX_FILENAME_LEN = 31,\r\n\t\tvMAX_DISPLAY_FILENAME_LEN\t= 63\r\n\t};\r\n\r\n\t\t\t\t\tFile( int fd, Card* card );\r\n\t\t\t\t\t~File();\r\n\t\t\t\t\t\r\n\t\t\r\n\tchar\t\t\tm_Filename[vMAX_FILENAME_LEN+1];\r\n\tDateTime\t\tm_Created;\t\r\n\tDateTime\t\tm_Modified;\r\n\tunsigned int\tm_Size;\r\n\tunsigned short\tm_Attribs;\r\n\r\n\tbool\t\t\tClose( void );\r\n\tint\t\t\t\tWrite( void* data, int len );\r\n\tint\t\t\t\tRead( void* data, int len );\r\n\tint\t\t\t\tSeek( int offset, FilePointerBase base );\r\n\tbool\t\t\tFlush( void );\r\n\r\n#\tifdef __PLAT_XBOX__\r\n\tchar\t\t\tm_DisplayFilename[vMAX_DISPLAY_FILENAME_LEN+1];\r\n#\tendif\r\n\r\n#\tifdef __PLAT_NGC__\r\n\tCARDFileInfo\tm_file_info;\r\n\tint\t\t\t\tm_file_number;\t\t// Set when opened.\r\n\t\r\n\tbool\t\t\tm_need_to_flush;\r\n\tint\t\t\t\tm_write_offset;\r\n\tuint8\t\t   *mp_write_buffer;\r\n\tint\t\t\t\tm_read_offset;\r\n\tuint8\t\t   *mp_read_buffer;\r\n#\tendif\r\n\r\nprivate:\r\n\tint\t\t\t\tm_fd;\r\n\tCard*\t\t\tm_card;\r\n};\r\n\r\nclass  Card  : public Spt::Class\r\n{\r\npublic:\r\n\tfriend class Manager;\r\n\r\n\tenum\r\n\t{\r\n\t\tvERROR_FORMATTED,\r\n\t\tvERROR_UNFORMATTED,\r\n\t\tvINSUFFICIENT_SPACE,\r\n\t\tvINVALID_PATH,\r\n\t\tvNO_CARD,\r\n\t\tvACCESS_ERROR,\r\n\t\tvSUBDIR_NOT_EMPTY,\r\n\t\tvTOO_MANY_OPEN_FILES,\r\n\t\tvUNKNOWN,\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n\t\tvDEV_NONE,\r\n\t\tvDEV_PS1_CARD,\r\n\t\tvDEV_PS2_CARD,\r\n\t\tvDEV_POCKET_STATION,\r\n\t\tvDEV_XBOX_CARD,\r\n\t\tvDEV_XBOX_HARD_DRIVE,\r\n\t\tvDEV_GC_CARD,\r\n\t};\r\n\r\n\tenum\r\n\t{\r\n\t\tvMAX_FILES_PER_DIRECTORY = 32,\r\n\t};\r\n\r\n\tbool\t\t\tMakeDirectory( const char* dir_name );\r\n\tbool\t\t\tDeleteDirectory( const char* dir_name );\r\n\tconst char\t   *ConvertDirectory( const char* dir_name );\r\n\t\r\n\tbool\t\t\tChangeDirectory( const char* dir_name );\r\n\t\r\n\tFile*\t\t\tOpen( const char* filename, int mode, int size = 0 );\t// Size used by NGC for file creation.\r\n\t\r\n\tbool\t\t\tDelete( const char* filename );\r\n\tbool\t\t\tRename( const char* old_name, const char* new_name );\r\n\r\n\tbool\t\t\tFormat( void );\r\n\tbool\t\t\tUnformat( void );\r\n\tbool\t\t\tIsFormatted( void );\r\n\t\r\n\tint\t\t\t\tGetSlot( void )\t\t\t{ return m_slot; }\r\n\tint\t\t\t\tGetDeviceType( void );\r\n\tint\t\t\t\tGetNumFreeClusters( void );\r\n\tint\t\t\t\tGetNumFreeEntries( const char* path );\r\n\r\n\tvoid\t\t\tSetError( int error ) { m_last_error = error; }\r\n\tint\t\t\t\tGetLastError( void ) { return m_last_error; }\r\n\r\n\tbool\t\t\tGetFileList( const char* mask, Lst::Head< File > &file_list );\r\n\r\n#\tifdef __PLAT_NGC__\r\n\tint\t\t\t\tm_mem_size;\t\t\t\t// Overall memory size of unit.\r\n\tint\t\t\t\tm_sector_size;\t\t\t// Sector size of unit.\r\n\tchar*\t\t\tmp_work_area;\t\t\t// Used also as a flag: == NULL means not yet mounted.\r\n\tbool\t\t\tm_broken;\r\n\tint \t\t\tCountFilesLeft();\t\t\t// Required to check if there are enough files left to allow a game save.\r\n\tbool\t\t\tIsForeign( void );\r\n\tbool\t\t\tIsBadDevice( void );\r\n#\tendif\r\n\r\n#\tifdef __PLAT_XBOX__\r\n\tvoid\t\t\tSetAsHardDrive();\r\n#\tendif // #ifdef __PLAT_XBOX__\r\n\r\nprivate:\r\n\tint\t\t\t\tm_port;\r\n\tint\t\t\t\tm_slot;\r\n\tint\t\t\t\tm_last_error;\r\n\r\n#\tifdef __PLAT_XBOX__\r\n\tchar\t\t\tm_mounted_drive_letter;\t// Used also as a flag: == 0 means not yet mounted.\r\n\tenum\r\n\t{\r\n\t\tvDIRECTORY_NAME_BUF_SIZE=64\r\n\t};\t\r\n#\tendif // #ifdef __PLAT_XBOX__\r\n};\r\n\r\nclass  Manager  : public Spt::Class\r\n{\r\n\r\npublic :\r\n\tenum\r\n\t{\r\n#\t\tifdef __PLAT_XBOX__\r\n\t\tvMAX_PORT = 4,\t\t\t// Four controllers...\r\n\t\tvMAX_SLOT = 2,\t\t\t// ...each with 2 slots for memory cards.\r\n#\t\telif defined __PLAT_NGC__\r\n\t\tvMAX_PORT = 1,\t\t\t// Just plug them into the console itself, so 1 port...\r\n\t\tvMAX_SLOT = 1,\t\t\t// ...with 2 slots for memory cards.\r\n#\t\telse\r\n\t\tvMAX_PORT = 2,\r\n\t\tvMAX_SLOT = 4,\r\n#\t\tendif // #ifdef __PLAT_XBOX__\r\n\t};\r\n\r\n\tint\t\t\t\tGetMaxSlots( int port );\r\n\tCard*\t\t\tGetCard( int port, int slot );\r\n\tCard*\t\t\tGetCardEx( int port, int slot )\t{ return &( m_card[port][slot] ); }\r\n#\tifdef __PLAT_NGC__\r\n\tvoid\t\t\tSetFatalError( bool error )\t\t{ m_hasFatalError = error; }\r\n\tbool\t\t\tGotFatalError( void )\t\t\t{ return m_hasFatalError; }\r\n\tvoid\t\t\tSetWrongDevice( bool error )\t{ m_wrongDevice = error; }\r\n\tbool\t\t\tGotWrongDevice( void )\t\t\t{ return m_wrongDevice; }\r\n#\tendif // #ifdef __PLAT_NGC__\r\n\r\nprivate :\r\n\t\t\t\t\t~Manager ( void );\r\n\t\t\t\t\tManager ( void );\r\n\r\n\t\t\t\t\tCard\t\t\tm_card[vMAX_PORT][vMAX_SLOT];\r\n#\tifdef __PLAT_NGC__\r\n\tbool\t\t\tm_hasFatalError;\r\n\tbool\t\t\tm_wrongDevice;\r\n#\tendif // #ifdef __PLAT_NGC__\r\n\r\n#\tifdef __PLAT_XBOX__\r\n\tCard m_hard_drive;\r\n#\tendif // #ifdef __PLAT_XBOX__\r\n\t\r\n\tDeclareSingletonClass( Manager );\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mc\r\n\r\n#endif\t// __GEL_MCMAN_H\r\n\r\n"
  },
  {
    "path": "Code/Sys/Mem/CompactPool.cpp",
    "content": "#include <core/defines.h>\r\n#include <sys/mem/CompactPool.h>\r\n\r\n\r\n#ifdef __DEBUG_COMPACTPOOL__\r\n//#define __REALLY_DEBUG_COMPACTPOOL__\r\n\r\n\r\n#endif\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n#define\tREPORT_ON\t\t0\t\t// change this to the address of a black you want to watch\r\n#endif\r\n\r\n#ifdef __PLAT_NGC__\r\nextern bool g_mc_hack;\r\n#include \"sys/ngc/p_buffer.h\"\r\n#endif\t\t// __PLAT_NGC__\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\nCCompactPool::CCompactPool(int item_size, int desired_num_items, char *name)\r\n{\r\n\tm_totalItems = desired_num_items;\r\n\tm_itemSize = item_size;\r\n\tDbg_MsgAssert(m_itemSize >= 4, (\"item size too small (%d)\", m_itemSize));\r\n\r\n#ifdef __PLAT_NGC__\r\n\tif ( g_mc_hack )\r\n\t{\r\n\t\tmp_buffer = (uint8*)NsBuffer::alloc( m_totalItems * m_itemSize );\r\n\t}\r\n\telse\r\n#endif\t\t// __PLAT_NGC__\r\n\t{\r\n\t\tmp_buffer = new uint8[m_totalItems * m_itemSize];\r\n\t}\r\n\tmp_buffer_end = mp_buffer + m_totalItems * m_itemSize;\r\n\r\n\tm_currentUsedItems = 0;\r\n\tm_maxUsedItems = 0;\r\n\r\n\t// set up free list\r\n\tmp_freeList = (uint32 *) mp_buffer;\r\n\tuint8 *pItem = mp_buffer;\r\n\tfor (int i = 0; i < m_totalItems; i++)\r\n\t{\r\n\t\tif (i < m_totalItems - 1)\r\n\t\t\t*((uint32 **) pItem) = (uint32 *) (pItem + m_itemSize);\r\n\t\telse\r\n\t\t\t*((uint32 **) pItem) = NULL;\r\n\t\tpItem += m_itemSize;\r\n\t}\r\n\r\n\tif (name)\r\n\t\tstrcpy(m_name, name);\r\n\telse\r\n\t\tstrcpy(m_name, \"unnamed\");\r\n\r\n#ifdef __REALLY_DEBUG_COMPACTPOOL__\r\n\r\n\tm_maxUsedItems = 0;\r\n\r\n\tint total_marker_blocks = (m_totalItems + 31) >> 5;\r\n\tmp_used_marker_tab = new uint32[total_marker_blocks];\r\n\t//printf(\"ZOOPY: %d marker blocks, marker tab at 0x%x\\n\", total_marker_blocks, mp_used_marker_tab);\r\n\tfor (int b = 0; b < total_marker_blocks; b++)\r\n\t\tmp_used_marker_tab[b] = 0;\r\n#endif\r\n}\r\n\r\n\r\n\r\n\r\nCCompactPool::~CCompactPool()\r\n{\r\n\tDbg_MsgAssert(!m_currentUsedItems, (\"pool still contains items\"));\r\n\r\n#ifdef __PLAT_NGC__\r\n\tif ( !g_mc_hack )\r\n#endif\t\t// __PLAT_NGC__\r\n\t{\r\n\t\tdelete mp_buffer;\r\n\t}\r\n\r\n#ifdef __REALLY_DEBUG_COMPACTPOOL__\r\n\tRyan(\"Freeing pool %s, max items used in this pool: %d\\n\", m_name, m_maxUsedItems);\r\n\tdelete [] mp_used_marker_tab;\r\n\tmp_used_marker_tab = NULL;\r\n\tm_maxUsedItems = 0;\r\n#endif\r\n}\r\n\r\n   \r\nbool CCompactPool::IsInPool(void *p)\r\n{\r\n\tif (p>=mp_buffer && p<mp_buffer_end)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\t\t\t\r\n\r\n\r\nvoid * CCompactPool::Allocate()\r\n{\r\n\tif (mp_freeList)\r\n\t{\r\n\t\tm_currentUsedItems++;\r\n\r\n\t\tif (m_currentUsedItems > m_maxUsedItems)\r\n\t\t{\r\n\t\t\tm_maxUsedItems = m_currentUsedItems;\r\n\t\t}\r\n#ifdef __REALLY_DEBUG_COMPACTPOOL__\t\t\r\n\r\n\t\tuint32 marker_num = ((uint32) mp_freeList - (uint32) mp_buffer) / m_itemSize;\r\n\t\tuint32 marker_tab_entry = marker_num >> 5;\r\n\t\tuint32 marker_tab_bit = marker_num - (marker_tab_entry << 5);\r\n\t\t//printf(\"ZOOPY: allocating using entry %d, bit %d, marker tab at 0x%x\\n\", marker_tab_entry, marker_tab_bit, mp_used_marker_tab);\r\n\t\tDbg_MsgAssert(mp_used_marker_tab, (\"max used items %d\", m_maxUsedItems));\r\n\t\tmp_used_marker_tab[marker_tab_entry] |= (1<<marker_tab_bit);\r\n#endif\r\n\t\r\n\t\t//printf(\"CCompactPool::Allocate(), now %d used items out of %d\\n\", m_currentUsedItems, m_totalItems);\r\n\t\t\r\n\t\tvoid *pItem = mp_freeList;\r\n\t\tmp_freeList = (uint32 *) *mp_freeList;\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\tif ((int)pItem == REPORT_ON)\r\n\t\t{\r\n\t\t\tprintf (\"++++ CCompactPool::Allocate %p\\n\",pItem);\r\n\t\t\tDumpUnwindStack(20,0);\r\n\t\t}\r\n\t\t#endif\r\n\t\treturn pItem;\r\n\t}\r\n\r\n\tDbg_MsgAssert(0, (\"Out of %ss (%d max) in their Compact Pool\", m_name, m_totalItems));\r\n\t\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\nvoid CCompactPool::Free(void *pFreeItem)\r\n{\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tif ((int)pFreeItem == REPORT_ON)\r\n\t{\r\n\t\tprintf (\"--- CCompactPool::Free %p\\n\",pFreeItem);\r\n\t\tDumpUnwindStack(20,0);\r\n\t}\r\n\t#endif\r\n#ifdef __REALLY_DEBUG_COMPACTPOOL__\r\n\t// make sure block is within range\r\n\tint pool_item = ((int) ((uint8 *) pFreeItem - mp_buffer)) / m_itemSize;\r\n\tDbg_MsgAssert(pool_item >= 0 && pool_item < m_totalItems, (\"item (%d) out of range (%d)\", pool_item, m_totalItems));\r\n\tDbg_Assert(!(((uint32) pFreeItem) & 3));\r\n\t\r\n\tuint32 marker_tab_entry = pool_item >> 5;\r\n\tuint32 marker_tab_bit = pool_item - (marker_tab_entry << 5);\r\n\t//printf(\"ZOOPY: freeing using entry %d, bit %d, marker tab at 0x%x\\n\", marker_tab_entry, marker_tab_bit, mp_used_marker_tab);\r\n\tDbg_Assert(mp_used_marker_tab);\r\n\tDbg_MsgAssert(mp_used_marker_tab[marker_tab_entry] & (1<<marker_tab_bit), (\"already freed item from pool\"));\r\n\tmp_used_marker_tab[marker_tab_entry] &= ~(1<<marker_tab_bit);\t\r\n#endif\r\n\r\n\tm_currentUsedItems--;\r\n\t\r\n\t//printf(\"CCompactPool::Free(), now %d used items out of %d\\n\", m_currentUsedItems, m_totalItems);\r\n\t\r\n\t*((uint32 **) pFreeItem) = mp_freeList;\r\n\tmp_freeList = (uint32 *) pFreeItem;\r\n\t\r\n/*\r\n#ifdef __REALLY_DEBUG_COMPACTPOOL__\r\n\tuint32 *p_free_next = *((uint32 **) mp_freeList);\r\n\tif (p_free_next)\r\n\t{\r\n\t\tint pool_item = ((int) ((uint8 *) p_free_next - mp_buffer)) / m_itemSize;\r\n\t\tDbg_MsgAssert(pool_item >= 0 && pool_item < m_totalItems, (\"next item (%d) out of range (%d)\", pool_item, m_totalItems));\r\n\t}\r\n#endif\r\n*/\r\n}\r\n\r\n\r\n\r\n} // namespace Mem\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/Mem/CompactPool.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t8/2/2001 - rjm\t\t\t\t\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __SYS_MEM_COMPACTPOOL_H\r\n#define __SYS_MEM_COMPACTPOOL_H\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#ifdef __NOPT_ASSERT__\r\n#define __DEBUG_COMPACTPOOL__\r\n#endif\r\n\r\n\r\nnamespace Mem\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CCompactPool\r\n{\r\npublic:\r\n\t\t\t\t\t\tCCompactPool(int item_size, int desired_num_items, char *name = NULL);\r\n\t\t\t\t\t\t~CCompactPool();\r\n\r\n\tvoid *\t\t\t\tAllocate();\r\n\tvoid \t\t\t\tFree(void *pFreeItem);\r\n\tint\t\t\t\t\tGetMaxUsedItems() {return m_maxUsedItems;}\r\n\tint\t\t\t\t\tGetNumUsedItems() {return m_currentUsedItems;}\r\n\tint\t\t\t\t\tGetTotalItems() {return m_totalItems;}\r\n\tchar *\t\t\t\tGetName() {return m_name;}\r\n\tbool\t\t\t\tIsInPool(void *p);\r\n\t\r\nprivate:\r\n\tuint8 *\t\t\t\tmp_buffer;\r\n\tuint8 *\t\t\t\tmp_buffer_end;\r\n\tint\t\t\t\t\tm_totalItems; // that we have room for\r\n\tint\t\t\t\t\tm_itemSize;\r\n\r\n\tint\t\t\t\t\tm_currentUsedItems;\r\n\r\n\tuint32 *\t\t\tmp_freeList;\r\n\r\n\tchar\t\t\t\tm_name[64];\r\n\tint\t\t\t\t\tm_maxUsedItems;\r\n#ifdef __DEBUG_COMPACTPOOL__\r\n\tuint32 *\t\t\tmp_used_marker_tab;\r\n\t\r\n#endif\r\n\r\n};\r\n\r\n\r\n\r\n\r\n/*\r\ntemplate<class _V>\r\nclass StaticCCompactPool\r\n{\r\npublic:\r\n\tstatic void\t\t\tSAllocPool(int size, char *name = NULL) {sp_pool = new CCompactPool<_V>(size, name);}\r\n\tstatic void\t\t\tSFreePool()\t{delete sp_pool;}\r\n\tstatic _V*\t\t\tSCreate() {return sp_pool->Create();}\r\n\tstatic void\t\t\tSFree(_V *pItem) {sp_pool->Free(pItem);}\r\n\r\n\tstatic int\t\t\tSGetNumUsedItems() {return sp_pool->GetNumUsedItems();}\r\n\r\nprotected:\r\n\tstatic CCompactPool<_V> *\tsp_pool;\r\n};\r\n*/\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n}\r\n\r\n#endif\t// __SYS_MEM_CCOMPACTPOOL_H\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/Mem/PoolManager.cpp",
    "content": "#include <sys/mem/PoolManager.h>\r\n#include <core/hashtable.h>\r\n\r\n//DefinePoolableClass(Lst::HashItem)\r\n\r\n\r\nnamespace Mem \r\n{\r\n\r\n\r\nMem::CCompactPool *\t\tPoolManager::sp_pool[PoolManager::vTOTAL_POOLS] =\r\n{\r\n\tNULL\r\n};\r\n\r\n\r\n\r\n\r\nvoid PoolManager::SSetupPool(int poolId, int numItems)\r\n{\r\n\tDbg_MsgAssert(poolId >= 0 && poolId < vTOTAL_POOLS, (\"%d not a valid pool\", poolId));\r\n\tDbg_MsgAssert(!sp_pool[poolId], (\"pool %d already exists\", poolId));\r\n\r\n\tif (poolId == vHASH_ITEM_POOL)\r\n\t\tsp_pool[poolId] = new Mem::CCompactPool(s_get_item_size(poolId), numItems, \"HashItem\");\r\n}\r\n\r\n\r\n\r\n\r\nvoid PoolManager::SDestroyPool(int poolId)\r\n{\r\n\tDbg_MsgAssert(poolId >= 0 && poolId < vTOTAL_POOLS, (\"%d not a valid pool\", poolId));\r\n\tDbg_MsgAssert(sp_pool[poolId], (\"pool %d doesn't exist\", poolId));\r\n\t\r\n\tdelete sp_pool[poolId];\r\n\tsp_pool[poolId] = NULL;\r\n}\r\n\r\n\r\n\r\n\r\nvoid *PoolManager::SCreateItem(int poolId)\r\n{\r\n\tDbg_MsgAssert(poolId >= 0 && poolId < vTOTAL_POOLS, (\"%d not a valid pool\", poolId));\r\n\t\r\n\tif (sp_pool[poolId])\r\n\t{\r\n\t\treturn sp_pool[poolId]->Allocate();\r\n\t}\r\n\r\n\treturn new char[s_get_item_size(poolId)];\r\n}\r\n\r\n\r\n\r\n\r\nvoid PoolManager::SFreeItem(int poolId, void *pItem)\r\n{\r\n\tDbg_MsgAssert(poolId >= 0 && poolId < vTOTAL_POOLS, (\"%d not a valid pool\", poolId));\r\n\t\r\n\tif (sp_pool[poolId])\r\n\t{\r\n\t\tsp_pool[poolId]->Free(pItem);\r\n\t\treturn;\r\n\t}\r\n\r\n\tdelete [] (char *)pItem;\r\n}\r\n\r\n// Provide access to the pools for debugging (like reporting usage)\r\nMem::CCompactPool * PoolManager::SGetPool(int poolId)\r\n{\r\n\treturn sp_pool[poolId];\t\r\n}\r\n\r\n\r\n\r\n\r\nint PoolManager::s_get_item_size(int poolId)\r\n{\r\n\tif (poolId == vHASH_ITEM_POOL)\r\n\t\treturn sizeof(Lst::HashItem<void *>);\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Sys/Mem/PoolManager.h",
    "content": "#ifndef __SYS_MEM_POOLMANAGER_H\r\n#define __SYS_MEM_POOLMANAGER_H\r\n\r\n#include <sys/mem/CompactPool.h>\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n/*\r\n\tUsed in cases where one can't simply make a class poolable\r\n\tby inheriting from CPoolable, for example, where we want\r\n\tevery HashItem<T> class instance to come off the same\r\n\tpool.\r\n*/\r\n\r\nclass PoolManager\r\n{\r\npublic:\r\n\r\n\tenum\r\n\t{\r\n\t\tvHASH_ITEM_POOL =\t0,\r\n\t\tvTOTAL_POOLS\t=\t1,\r\n\t};\r\n\r\n\tstatic void\t\t\t\tSSetupPool(int poolId, int numItems);\r\n\tstatic void\t\t\t\tSDestroyPool(int poolId);\r\n\r\n\tstatic void *\t\t\tSCreateItem(int poolId);\r\n\tstatic void\t\t\t\tSFreeItem(int poolId, void *pItem);\r\n\tstatic Mem::CCompactPool * \tSGetPool(int poolId);\r\n\t\r\n\r\nprivate:\r\n\r\n\tstatic int\t\t\t\ts_get_item_size(int poolId);\r\n\r\n\tstatic Mem::CCompactPool *sp_pool[vTOTAL_POOLS];\r\n};\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "Code/Sys/Mem/Poolable.cpp",
    "content": "#include <sys/mem/CompactPool.h>\r\n#include <sys/mem/Poolable.h>\r\n\r\nnamespace Mem\r\n{\r\n\r\n\tint gHeapPools = false;\t\t\t// set to true to use debug heap instead of pools\r\n\r\n\r\nCCompactPool *CPoolable<PoolTest>::sp_pool[POOL_STACK_SIZE] = {NULL,NULL};\t\t\t\t\t\t\t\t\t\r\nbool CPoolable<PoolTest>::s_internallyCreatedPool[POOL_STACK_SIZE] = {false,false};\r\nint CPoolable<PoolTest>::s_currentPool=0;\t\t\t\t\t\t\r\n\r\n\r\nPoolTest::PoolTest()\r\n{\r\n\tprintf(\"created PoolTest object\\n\");\r\n}\r\n\r\n\r\n\r\n\r\nPoolTest::~PoolTest()\r\n{\r\n\tprintf(\"~PoolTest()\\n\");\r\n}\r\n\r\n\r\n\r\n\r\n}\r\n"
  },
  {
    "path": "Code/Sys/Mem/Poolable.h",
    "content": "/*\r\n\tMODULE DESCRIPTION\r\n\t\r\n\tPoolable.h, RJM, 10/18/2001\r\n*/\r\n\r\n#ifndef __SYS_MEM_POOLABLE_H\r\n#define __SYS_MEM_POOLABLE_H\r\n\r\n#include <sys/mem/CompactPool.h>\r\n#include <sys/mem/memman.h>\r\n\r\n#define DefinePoolableClass(_T)\t\t\t\t\t\t\t\t\t\t\\\r\nnamespace Mem\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\tMem::CCompactPool *Mem::CPoolable< _T >::sp_pool[POOL_STACK_SIZE] = {NULL,NULL};\t\t\\\r\n\tbool Mem::CPoolable< _T >::s_internallyCreatedPool[POOL_STACK_SIZE] = {false,false};\t\\\r\n\tint Mem::CPoolable< _T >::s_currentPool=0;\t\t\t\t\t\t\\\r\n}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\textern int gHeapPools;\r\n\r\n//class CCompactPool;\r\n\r\n\r\ntemplate <class _T>\r\nclass CPoolable\r\n{\r\n\tenum EPoolStackSize\r\n\t{\r\n\t\tPOOL_STACK_SIZE=2\r\n\t};\r\n\t\t\r\npublic:\r\n\tstatic void\t\t\t\t\t\t\tSCreatePool(int num_items, char *name);\r\n\tstatic void\t\t\t\t\t\t\tSAttachPool(CCompactPool *pPool);\r\n\tstatic void\t\t\t\t\t\t\tSRemovePool();\r\n\tstatic int\t\t\t\t\t\t\tSGetMaxUsedItems();\r\n\tstatic int\t\t\t\t\t\t\tSGetNumUsedItems();\r\n\tstatic int\t\t\t\t\t\t\tSGetTotalItems();\r\n\t\t\t\t\t\t\t  \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tstatic void\t\t\t\t\t\t\tSPrintInfo();\r\n\t\r\n\tstatic void\t\t\t\t\t\t\tSSwitchToNextPool();\r\n\tstatic void\t\t\t\t\t\t\tSSwitchToPreviousPool();\r\n\t\r\n\tstatic int\t\t\t\t\t\t\tSGetCurrentPoolIndex();\r\n\tstatic bool\t\t\t\t\t\t\tSPoolExists();\r\n\t\r\n\tvoid * operator new (size_t size);\t\t\t\t\t\t\t\t\t\t  \t\r\n\tvoid operator delete (void * pMem);\t\t\t\t\t\t\t\t\t   \t\t\r\nprotected:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tstatic CCompactPool *\t\t\t\tsp_pool[POOL_STACK_SIZE];\r\n\tstatic bool\t  \t\t\t\t\t\ts_internallyCreatedPool[POOL_STACK_SIZE];  \t\r\n\tstatic int\t\t\t\t\t\t\ts_currentPool;\r\n};\r\n\r\n\r\n\r\n\r\nclass PoolTest : public CPoolable<PoolTest>\r\n{\r\n\r\npublic:\r\n\tPoolTest();\r\n\t~PoolTest();\r\n\r\n\tint m_monkey;\r\n};\r\n\r\n\r\n\r\n\r\ntemplate<class _T>\r\nvoid *CPoolable<_T>::operator new (size_t size)\t\t\t\t\t\t\t\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tDbg_Assert(size == sizeof(_T));\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t//printf(\"in CPoolable operator new\\n\");\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tif (gHeapPools)\r\n\t{\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());\r\n\t\tvoid *p = ::new char[size];\t\t\t\t\t\t\t\t\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\treturn p;\r\n\t}\r\n\t#endif\r\n\t\r\n\tif (sp_pool[s_currentPool])\t \r\n\t{\r\n\t\treturn sp_pool[s_currentPool]->Allocate();\t\t\t\t\t\t\t\t\r\n\t}\r\n\r\n\treturn ::new char[size];\t\t\t\t\t\t\t\t\r\n}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\r\n\r\n\r\ntemplate<class _T>\r\nvoid CPoolable<_T>::operator delete (void * pMem)\t\t\t\t\t\t\t\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tDbg_Assert(pMem);  \r\n\t#ifdef\t__NOPT_ASSERT__\r\n\tif (gHeapPools)\r\n\t{\r\n\t\tdelete [] (char *)pMem;\t\t\t\t\t\t\t\t\t\t\t\r\n\t\treturn;\r\n\t}\r\n\t#endif\r\n\t\r\n\t// pMem contains no info as to which pool it was allocated from, because that would\r\n\t// use up too much memory.\r\n\t// So query the pools to see if it is in them.\r\n\t\r\n\tCCompactPool *p_pool=sp_pool[s_currentPool];\r\n\t// Check if it is in the current pool, which it will be most of the time.\r\n\tif (p_pool && p_pool->IsInPool(pMem))\r\n\t{\r\n\t\tp_pool->Free(pMem);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Otherwise try the other one, which exists for saving games to mem card.\r\n\t\tDbg_MsgAssert(POOL_STACK_SIZE==2,(\"Only two pool supported at the moment\"));\r\n\t\tp_pool=sp_pool[s_currentPool ^ 1];\r\n\t\tif (p_pool && p_pool->IsInPool(pMem))\r\n\t\t{\r\n\t\t\tp_pool->Free(pMem);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tdelete [] (char *)pMem;\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t}\r\n\t}\t\t\r\n}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\r\n\r\n\r\ntemplate<class _T>\r\nvoid CPoolable<_T>::SCreatePool(int num_items, char *name)\t\t\t\t\t\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tDbg_Assert(!sp_pool[s_currentPool]);\t\t\t\t\t\t\t\t\t\t\r\n\tsp_pool[s_currentPool] = new CCompactPool(sizeof(_T), num_items, name);\t\t\r\n\ts_internallyCreatedPool[s_currentPool] = true;\r\n}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\ntemplate<class _T>\r\nbool CPoolable<_T>::SPoolExists()\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tif (sp_pool[s_currentPool])\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\t\t\r\n \r\n\r\ntemplate<class _T>\r\nvoid CPoolable<_T>::SAttachPool(CCompactPool *pPool)\t\t\t\t\t\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tDbg_Assert(!sp_pool[s_currentPool]);\t\t\t\t\t\t\t\t\t\t\r\n\tDbg_Assert(pPool);\t\t\t\t\t\t\t\t\t\t\r\n\tsp_pool[s_currentPool] = pPool;\t\t\r\n\ts_internallyCreatedPool[s_currentPool] = false;\r\n}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\r\n\r\n\r\ntemplate<class _T>\r\nvoid CPoolable<_T>::SRemovePool()\t\t\t\t\t\t\t\t\t\t\t\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\tif (sp_pool[s_currentPool])\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\tif (s_internallyCreatedPool[s_currentPool])\r\n\t\t\tdelete sp_pool[s_currentPool];\t\t\t\t\t\t\t\t\t\t\t\r\n\t\tsp_pool[s_currentPool] = NULL;\t\t\t\t\t\t\t\t\t\t\t\r\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\r\ntemplate<class _T>\r\nint CPoolable<_T>::SGetCurrentPoolIndex()\r\n{\r\n\treturn s_currentPool;\r\n}\r\n\r\ntemplate<class _T>\r\nvoid CPoolable<_T>::SSwitchToNextPool()\r\n{\r\n\tDbg_MsgAssert(s_currentPool<POOL_STACK_SIZE-1,(\"Called SSwitchToNextPool with no next pool\"));\r\n\t++s_currentPool;\r\n}\r\n\t\r\ntemplate<class _T>\r\nvoid CPoolable<_T>::SSwitchToPreviousPool()\r\n{\r\n\tDbg_MsgAssert(s_currentPool,(\"Called SSwitchToPreviousPool with no previous pool\"));\r\n\t--s_currentPool;\r\n}\r\n\r\ntemplate<class _T>\r\nint CPoolable<_T>::SGetMaxUsedItems()\t\t\t\t\t\t\t\t\t\t\t\r\n{\r\n\treturn sp_pool[s_currentPool]->GetMaxUsedItems();\r\n}\r\n\r\n\r\ntemplate<class _T>\r\nint CPoolable<_T>::SGetNumUsedItems()\t\t\t\t\t\t\t\t\t\t\t\r\n{\r\n\treturn sp_pool[s_currentPool]->GetNumUsedItems();\r\n}\r\n\r\ntemplate<class _T>\r\nint CPoolable<_T>::SGetTotalItems()\t\t\t\t\t\t\t\t\t\t\t\r\n{\r\n\treturn sp_pool[s_currentPool]->GetTotalItems();\r\n}\r\n\r\n\r\n\r\n\r\ntemplate<class _T>\r\nvoid CPoolable<_T>::SPrintInfo()\t\t\t\t\t\t\t\t\t\t\t\r\n{\r\n\tprintf(\"pool is at %p\\n\", sp_pool[s_currentPool]);\r\n}\r\n\r\n\r\n\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sys/Mem/alloc.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSystem Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory (Mem) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\talloc.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tAbstract Allocator class\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/support.h>\r\n#include \"memman.h\"\r\n#include \"alloc.h\"\r\n\r\n#ifdef __PLAT_NGC__\r\n#ifdef __EFFICIENT__\r\n#include <dolphin.h>\r\n#endif\t\t// __EFFICIENT__\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nuint\t\tAllocator::s_current_id = 1;\r\n#ifdef __EFFICIENT__\r\nuint\t\tAllocator::s_align_stack[16] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\r\nuint\t\tAllocator::s_align_stack_index = 0;\r\nconst uint\tAllocator::BlockHeader::sSize = sizeof(BlockHeader); \r\n#else\r\n#ifdef __PLAT_NGC__\r\nconst uint\tAllocator::BlockHeader::sSize = (uint)nAlignUpBy( sizeof(BlockHeader), 5 ); \r\n#else\r\nconst uint\tAllocator::BlockHeader::sSize = (uint)nAlignUpBy( sizeof(BlockHeader), 4 ); \r\n#endif\t\t// __PLAT_NGC__\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nAllocator::Context::Context( void ) \r\n: m_node( this ), mp_free_list( NULL ) \r\n{\r\n\t\r\n\r\n#ifdef __LINKED_LIST_HEAP__\r\n\tmp_used_list = NULL;\r\n#endif\r\n\r\n\tDbg_AssertType( &m_node, Lst::Node< Context > );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nAllocator::Context::~Context( void ) \r\n{\r\n\t\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\tDbg_MsgAssert( mp_used_list == NULL,( \"Memory Leak\" ));\r\n\tDbg_MsgAssert( mp_free_list == NULL,( \"Corrupt Free List\" ));\r\n\tDbg_AssertType( &m_node, Lst::Node< Context > );\r\n#endif\r\n}\r\n\r\n\r\nbool Allocator::s_valid( void* pAddr )\r\n{\r\n\tBlockHeader* p_bheader = BlockHeader::sRead( pAddr ); \r\n\treturn (p_bheader->mId == vALLOC_MAGIC);\r\n}\r\n\r\nsize_t Allocator::s_get_alloc_size( void* pAddr )\r\n{\r\n\tBlockHeader* p_bheader = BlockHeader::sRead( pAddr ); \r\n\treturn (p_bheader->mSize);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nAllocator* Allocator::s_free( void* pAddr )\r\n{   \r\n\tBlockHeader* p_bheader = BlockHeader::sRead( pAddr ); \r\n\tAllocator* p_ret = p_bheader->mpAlloc;\r\n\r\n#if 0\r\n\t\r\n\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\t\r\n\tbool found = false;\r\n\tfor (Mem::Heap* heap = mem_man.FirstHeap(); heap != NULL; heap = mem_man.NextHeap(heap))\r\n\t{\t\t\r\n\t\tif (heap == p_ret) found = true;\r\n\t}\r\n\tDbg_MsgAssert(found,(\"Double dealloc of %p, allocator = %p?\", pAddr, p_ret));\r\n#endif\r\n\r\n\tDbg_MsgAssert(p_bheader->mId != 0xDEADDEAD,(\"Freeing Block Twice!\\n\"));\r\n\tDbg_MsgAssert(p_bheader->mId == vALLOC_MAGIC,(\"Freeing Corrupt Block\\n\"));\r\n\t\r\n\tp_bheader->mpAlloc->free( p_bheader );\r\n\tp_bheader->mId = 0xDEADDEAD;\t\t\t\t\t\t// clear Handle ID to DEAD value\r\n\r\n\treturn p_ret;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAllocator::s_set_id( void* pAddr )\r\n{\r\n\t\r\n\r\n\tBlockHeader* p_bheader = (BlockHeader*)( ((uint)pAddr) - BlockHeader::sSize );\r\n#ifdef __EFFICIENT__\r\n\tp_bheader = (BlockHeader*)(((uint)p_bheader) - p_bheader->mPadBytes);\r\n#endif\t\t// __EFFICIENT__\r\n\tDbg_AssertType( p_bheader, BlockHeader );\r\n\tDbg_AssertType( p_bheader->mpAlloc, Allocator );\r\n\t\r\n\tp_bheader->mId = vALLOC_MAGIC;\t\t//\ts_current_id++;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nAllocator::BlockHeader* Allocator::BlockHeader::sRead( void* pAddr )\r\n{\r\n\tBlockHeader* p_ret = (BlockHeader*)(((uint)pAddr) - BlockHeader::sSize);\r\n#ifdef __EFFICIENT__\r\n\tp_ret = (BlockHeader*)(((uint)p_ret) - p_ret->mPadBytes);\r\n#endif\t\t// __EFFICIENT__\r\n\t\r\n\tDbg_AssertType( p_ret, BlockHeader );\r\n\tDbg_AssertType( p_ret->mpAlloc, Allocator );\r\n\t\r\n\treturn p_ret;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nAllocator::Allocator( Region* region, Direction dir, char *p_name )\r\n: mp_region( region ), m_dir( dir ), mp_name(p_name)\r\n{\r\n\t\r\n\t\r\n\tmp_region->RegisterAllocator( this );\r\n\t\r\n\tm_context_stack.AddToHead( &m_initial_context.m_node );\r\n\tmp_context = &m_initial_context;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nAllocator::~Allocator( void )\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert( !m_context_stack.IsEmpty(),( \"Heap stack underflow\" ));\r\n\r\n\tmp_region->UnregisterAllocator( this ); \r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nuint\tAllocator::sGetId( void* pAddr )\r\n{\r\n\t\r\n\r\n#ifdef __EFFICIENT__\r\n\tif ( pAddr == NULL )\r\n#else\r\n\tif (( pAddr == NULL ) || !nAligned( pAddr ))\r\n#endif\t\t// __EFFICIENT__\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tBlockHeader* p_bheader = (BlockHeader*)( ((uint)pAddr) - BlockHeader::sSize );\r\n#ifdef __EFFICIENT__\r\n\tp_bheader = (BlockHeader*)(((uint)p_bheader) - p_bheader->mPadBytes);\r\n#endif\t\t// __EFFICIENT__\r\n\r\n\treturn p_bheader->mId;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAllocator::PushContext( void )\r\n{\r\n\t\r\n\r\n\tContext* new_context = new Context;\r\n\tm_context_stack.AddToHead( &new_context->m_node );\r\n\tmp_context = new_context;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tAllocator::PopContext( void )\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert( !m_context_stack.IsEmpty(),( \"Heap stack underflow\" ));\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\tdump_free_list();\r\n\tdump_used_list();\r\n#endif\r\n\r\n\tdelete mp_context;\r\n\t\t\r\n\tLst::Search< Context > sh;\r\n\tmp_context = sh.FirstItem( m_context_stack );\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\r\nvoid \tAllocator::dump_used_list( void )\r\n{\r\n\t\r\n#ifndef __PLAT_NGC__\r\n\tBlockHeader*\tp_header = mp_context->mp_used_list;\r\n\t\r\n\tDbg_Message( \"USED LIST for Heap (%p)\", this );\r\n\r\n\twhile ( p_header )\r\n\t{\r\n\t\tDbg_AssertType( p_header, BlockHeader );\r\n\t\tDbg_Message ( \"%p  %x   (%p)\", (void*)((uint)p_header + BlockHeader::sSize ), \r\n\t\t\t\t\t\t\t\t\t\tp_header->mSize, p_header->mp_next_used );\r\n\t\tp_header = p_header->mp_next_used;\r\n\t}\r\n\r\n\tDbg_Message( \"----------------------\" );\r\n#endif\t\t// __PLAT_NGC__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \tAllocator::dump_free_list( void )\r\n{\r\n\t\r\n\t\r\n\tBlockHeader*\tp_header = mp_context->mp_free_list;\r\n\t\r\n\tDbg_Message( \"FREE LIST for Heap (%p)\", this );\r\n\t\r\n\twhile ( p_header )\r\n\t{\r\n\t\tDbg_AssertType( p_header, BlockHeader );\r\n\t\tDbg_Message ( \"%p  %x   (%p)\", (void*)((uint)p_header + BlockHeader::sSize ), \r\n\t\t\t\t\t\t\t\t\t\tp_header->mSize, p_header->mpNext );\r\n\t\tp_header = p_header->mpNext;\r\n\t}\r\n\r\n\tDbg_Message( \"----------------------\" );\r\n}\r\n\r\n#endif\r\n\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__    \r\n\r\n// find the block that contains this pointer\r\n// return NULL if not found   \r\n// also includes the header area of the block  \t\t\t\t\t\t\t   \r\nvoid * Allocator::find_block(void *p)\r\n{\r\n\r\n\tBlockHeader*\tp_header = mp_context->mp_used_list;\r\n\t\r\n\twhile ( p_header )\r\n\t{\r\n\t\t\r\n\t\tvoid * p_start = (void*)((uint)p_header + BlockHeader::sSize);\r\n\t\tint size = p_header->mSize;\r\n\t\tvoid * p_end = (void*)((int)p_start + size);\r\n\r\n\t\tif (p >= p_start && p <p_end)\r\n\t\t{\r\n\t\t\treturn (void*)p_header; \r\n\t\t}\t\t\r\n\t\tp_header = p_header->mp_next_used;\r\n\t}\r\n\treturn NULL;\t\r\n}\r\n\r\nAllocator::BlockHeader* Allocator::first_block()\r\n{\r\n\r\n\tBlockHeader*\tp_header = mp_context->mp_used_list;\r\n\t\r\n\treturn p_header;\t\r\n}\r\n\r\n\r\n\r\n\r\n#endif\r\n\r\nbool  SameContext(void *p_mem,  Mem::Allocator *p_alloc)\r\n{\r\n\tAllocator::BlockHeader* p_bheader = Allocator::BlockHeader::sRead( p_mem ); \r\n\treturn (p_bheader->mpAlloc == p_alloc);\r\n}\r\n\r\n\r\n#ifdef __EFFICIENT__\r\nvoid Allocator::PushAlign( int align )\r\n{\r\n\ts_align_stack_index++;\r\n\r\n\tswitch ( align )\r\n\t{\r\n\t\tcase 4:\r\n\t\t\ts_align_stack[s_align_stack_index] = 2;\r\n\t\t\tbreak;\r\n\t\tcase 8:\r\n\t\t\ts_align_stack[s_align_stack_index] = 3;\r\n\t\t\tbreak;\r\n\t\tcase 16:\r\n\t\t\ts_align_stack[s_align_stack_index] = 4;\r\n\t\t\tbreak;\r\n\t\tcase 32:\r\n\t\t\ts_align_stack[s_align_stack_index] = 5;\r\n\t\t\tbreak;\r\n\t\tcase 64:\r\n\t\t\ts_align_stack[s_align_stack_index] = 6;\r\n\t\t\tbreak;\r\n\t\tcase 128:\r\n\t\t\ts_align_stack[s_align_stack_index] = 7;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( false, ( \"Illegal alignment (%d) specified. Must be 4, 8, 16, 32, 64 or 128.\\n\", align ) );\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid Allocator::PopAlign( void )\r\n{\r\n\ts_align_stack_index--;\r\n}\r\n\r\nuint Allocator::GetAlign( void )\r\n{\r\n\treturn s_align_stack[s_align_stack_index];\r\n}\r\n#endif\t\t// __EFFICIENT__\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n"
  },
  {
    "path": "Code/Sys/Mem/alloc.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory Manager (Mem)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/mem/alloc.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_MEM_ALLOC_H\r\n#define\t__SYS_MEM_ALLOC_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/support.h>\r\n#include <sys\\mem\\region.h>\r\n#include <sys/mem/memdbg.h>\r\n\r\n#ifdef __PLAT_NGC__\r\n#define __EFFICIENT__\t\t// Comment in for efficient allocation.\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n//#ifdef\t__PLAT_NGPS__\t\t\t\t\t\t\t\t\t\t\t  \r\n#define\t__LINKED_LIST_HEAP__    \r\n//#else\r\n//#ifdef __NOPT_DEBUG__\r\n//#define\t__LINKED_LIST_HEAP__    \r\n//#endif\r\n//#endif\r\n\r\n// Mick: on the CD build, we don't need any memory tracking\r\n// this saves us at least 300K as we have over 30,000 individual allocations... crazy\r\n// K: This used to be #ifdef __NOPT_CDROM__, changed cos the nopt_cdrom define is now gone.\r\n#ifndef\t__NOPT_ASSERT__\r\n#undef\t__LINKED_LIST_HEAP__\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\nconst\tuint\tvALLOC_MAGIC = 0xCF801FE1;\t\t\t// just a random magic number, to indicate a block is valid\r\n\r\nclass\tCMemProfile;\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Region;\r\n\r\nclass  Record  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic:\r\n\t\t\tRecord( void ) : m_count(0), m_peak(0) {}\r\n\r\n\t\t\tint\t\tm_count;\r\n\t\t\tint\t\tm_peak;\r\n\r\n\t\t\tRecord&\t\toperator+=( int src );\r\n\t\t\tRecord&\t\toperator-=( int src );\r\n\r\n\tconst \tRecord\t\toperator++( int src );\r\n\tconst \tRecord\t\toperator--( int src );\r\n\t\t\tRecord&\t\toperator++( void );\r\n\t\t\tRecord&\t\toperator--( void );\r\n\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  Allocator  : public Spt::Class\t\t\t\t// abstract base class \t\t\t\r\n{\r\n\t\r\n\r\n\tfriend class Manager;\r\n\tfriend class Region;\r\n\r\npublic :\r\n\r\n\tenum Direction\r\n\t{\t\t\r\n\t\tvBOTTOM_UP\t= +1,\r\n\t\tvTOP_DOWN\t= -1\r\n\t};\r\n\r\n\tstatic\t\tuint \t\t\tsGetId( void* pAddr );\r\n\t\t\r\n\t\t\t\tRegion*\t\t\tParentRegion( void );\r\n\r\n\t\t\t\tRecord\t\t\tmUsedBlocks;\r\n\t\t\t\tRecord\t\t\tmFreeBlocks;\r\n\t\t\t\tRecord\t\t\tmUsedMem;\r\n\t\t\t\tRecord\t\t\tmFreeMem;\r\n\r\n\r\n\tvirtual\t\tvoid\t\t\tPushContext( void );\r\n\tvirtual\t\tvoid\t\t\tPopContext( void );\r\n\r\n#ifdef __EFFICIENT__\r\n\t\t\t\tvoid\t\t\tPushAlign( int align );\r\n\t\t\t\tvoid\t\t\tPopAlign( void );\r\n\t\t\t\tuint\t\t\tGetAlign( void );\r\n#endif\t\t// __EFFICIENT__\r\n\r\n#ifdef __NOPT_DEBUG__\r\n\t\t\t\tvoid\t\t\tdump_free_list ( void );\r\n\t\t\t\tvoid\t\t\tdump_used_list ( void );\r\n#endif\r\n\r\n\t\t\t\tchar *\tGetName() {return mp_name;}\r\n\t\t\t\tDirection GetDirection() {return m_dir;}\r\n\r\n/// sorry, need to access this from elsewhere, for debugging... (MICK)\r\n//protected :\r\n\r\n\tclass  BlockHeader  //: public Spt::Class\r\n\t{\r\n\t\t\r\n\t\r\n\tpublic :\r\n\r\n#ifdef __NOPT_MEM_DEBUG__\r\n\r\n\t\t\t\tvoid\t\t\t\tDbgAllocateBlock( void );\r\n\t\t\t\tvoid\t\t\t\tDbgFreeBlock( void );\r\n\t\t\t\tvoid\t\t\t\tDbgDump( void );\r\n\r\n#endif // __NOPT_MEM_DEBUG__\r\n\r\n\t\t\t\t\t\t\t\t\tBlockHeader( Allocator* pAlloc, size_t size );\r\n\t\t\t\t\t\t\t\t\t~BlockHeader( void );\r\n\r\n\t\tstatic\tBlockHeader* \t\tsRead( void* pMem );\r\n\t\t\r\n\t\t\t\tunion\r\n\t\t\t\t{\r\n\t\t\t\t\tAllocator*\t\tmpAlloc;\r\n\t\t\t\t\tBlockHeader*\tmpNext;\r\n\t\t\t\t};\r\n\r\n#ifndef __EFFICIENT__\r\n\t\t\t\tuint\t\t\t\tmSize;\r\n#endif\r\n\t\t\t\tuint\t\t\t\tmId;\r\n#ifdef __EFFICIENT__\r\n#ifdef __NOPT_ASSERT__\r\n\t\t\t\tCMemProfile\t*\t\tmp_profile;\r\n#endif\t\t// __NOPT_ASSERT__\r\n#else\r\n\t\t\t\tCMemProfile\t*\t\tmp_profile;\r\n#endif __EFFICIENT__\r\n\r\n\r\n\t\tstatic const uint\t\t\tsSize; // Aligned Block Header size\r\n\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__    \r\n\r\n\t\t\t\tBlockHeader*\t\tmp_prev_used;\r\n\t\t\t\tBlockHeader*\t\tmp_next_used;\r\n\t\t\t\t\r\n\t\t\t\tvoid *\t\t\t\tmp_debug_data;\t\t// added for tracking callstacks for each allocation\r\n\r\n#endif // __NOPT_DEBUG__\r\n\r\n#ifdef __EFFICIENT__\r\n\t\t\t\tuint\t\t\t\tmSize:24;\r\n\t\t\t\tuint\t\t\t\tmPadBytes:8;\t\t// Must be last byte in structure.\r\n#endif\r\n\t};\r\n\r\n#ifdef __LINKED_LIST_HEAP__\r\n\t\t\t\tvoid * \t\t\t\tfind_block(void *p);\r\n\t\t\t\tBlockHeader* \t\tfirst_block();\r\n#endif\r\n\t\r\n    \r\n\tclass  Context  : public Spt::Class\r\n\t{\r\n\t\t\r\n\tpublic:\r\n\t\t\t\t\t\t\t\tContext( void );\r\n\t\t\t\t\t\t\t\t~Context( void );\r\n\t\r\n\t\tLst::Node< Context >\tm_node;\r\n\t\tBlockHeader*\t\t\tmp_free_list;\r\n\t\r\n\t#ifdef\t__LINKED_LIST_HEAP__    \r\n\t\tBlockHeader*\t\t\tmp_used_list;\r\n\t#endif\r\n\t\r\n\t};\r\n\r\n\t\t\t\t\t\t\t\t\tAllocator( Region* region, Direction dir, char *p_name );\r\n\tvirtual\t\t\t\t\t\t\t~Allocator( void );\r\n\t\r\n\t\t\tRegion*\t\t\t\t\tmp_region;\r\n\t\t\tDirection\t\t\t\tm_dir;\r\n\t\t\tvoid*\t\t\t\t\tmp_top;\r\n\t\t\tContext*\t\t\t\tmp_context;\r\n\r\n\t\t\tchar *\t\t\t\t\tmp_name;\t\t// debugging name, for checking\r\n\r\n\t\t\tLst::Head< Context >\tm_context_stack;\r\n\r\nprivate :\r\n\r\n\tstatic  bool \t\t\ts_valid( void* pAddr );\r\n\tstatic\tsize_t\t\t\ts_get_alloc_size( void* pAddr );\r\n\tstatic\tAllocator* \t\ts_free( void* pAddr );\r\n\tstatic\tvoid \t\t\ts_set_id( void* pAddr );\r\n\tvirtual void*\t\t\tallocate( size_t size, bool assert_on_fail ) = 0;\r\n\tvirtual int\t\t\t\tavailable(  ) {Dbg_MsgAssert(0,(\"available() not defined for this allocator!\")); return 0;}\r\n\tvirtual void*\t\t\treallocate_down( size_t newSize, void* pOld ) {Dbg_MsgAssert(0,(\"reallocate_down not defined for this allocator!\")); return NULL;}\r\n\tvirtual void*\t\t\treallocate_up( size_t newSize, void* pOld ) {Dbg_MsgAssert(0,(\"reallocate_up not defined for this allocator!\")); return NULL;}\r\n\tvirtual void*\t\t\treallocate_shrink( size_t newSize, void* pOld ) {Dbg_MsgAssert(0,(\"reallocate_shrink not defined for this allocator!\")); return NULL;}\r\n\tvirtual\tvoid\t\t\tfree( BlockHeader* pAddr ) = 0;\r\n\r\n\tstatic\tuint\t\t\ts_current_id;\r\n\t\t\tContext\t\t\tm_initial_context;\r\n#ifdef __EFFICIENT__\r\n\tstatic uint\t\t\t\ts_align_stack[16];\r\n\tstatic uint\t\t\t\ts_align_stack_index;\r\n#endif\t\t// __EFFICIENT__\r\n};                  \t\t\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline Record& Record::operator++( void )\t\t\t// prefix\r\n{\r\n\t\r\n\r\n\t*this += 1;\r\n\treturn\t*this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Record Record::operator++( int )\t// postfix\r\n{\r\n\t\r\n\t\r\n\tRecord ret = *this;\r\n\t++( *this );\r\n\r\n\treturn ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Record& Record::operator--( void )\t\t// prefix\r\n{\r\n\t\r\n\r\n\t*this -= 1;\r\n\treturn\t*this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline const Record Record::operator--( int )\t// postfix\r\n{\r\n\t\r\n\t\r\n\tRecord ret = *this;\r\n\t--( *this );\r\n\r\n\treturn ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Record& Record::operator+=( int src )\r\n{\r\n\t\r\n\r\n\tm_count += src;\r\n\t\r\n\tif( m_count > m_peak )\r\n\t{\r\n\t\tm_peak = m_count;\r\n\t}\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Record& Record::operator-=( int src )\r\n{\r\n\t\r\n\t\r\n\tm_count -= src;\r\n\r\n\tDbg_MsgAssert(( m_count >= 0 ), ( \"Count Underflow\" ));\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Region* Allocator::ParentRegion( void )\r\n{\r\n\t\r\n\r\n\treturn mp_region; \r\n}\r\n\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef __EFFICIENT__\r\ninline Allocator::BlockHeader::BlockHeader( Allocator* pAlloc, size_t size )\r\n: mpAlloc( pAlloc ), mSize( size ), mPadBytes( 0 )\r\n#else\r\ninline Allocator::BlockHeader::BlockHeader( Allocator* pAlloc, size_t size )\r\n: mpAlloc( pAlloc ), mSize( size )\r\n#endif\t// __EFFICIENT__\r\n{\r\n\t\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__    \r\n\r\n\tmp_next_used = NULL;\r\n\tmp_prev_used = NULL;\r\n\tmp_debug_data  = NULL;\r\n\r\n#endif\r\n#ifdef __NOPT_ASSERT__\r\n\tmp_profile = NULL;\r\n#endif\t\t// __NOPT_ASSERT__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline Allocator::BlockHeader::~BlockHeader( void )\r\n{\r\n\t\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__    \r\n\tDbg_MsgAssert( mp_prev_used == NULL, ( \"internal error\" ));\r\n\tDbg_MsgAssert( mp_next_used == NULL, ( \"internal error\" ));\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#ifdef __NOPT_MEM_DEBUG__\r\n\r\n\r\ninline void\tAllocator::BlockHeader::DbgAllocateBlock( void )\r\n{\t\r\n\t\r\n\r\n\tuint64* ptr = (uint64*)((uint)this + sSize );\r\n\r\n\tfor ( uint i = 0; i < mSize; i += 8 )\r\n\t{\r\n\t\t*ptr++ = vALLOCATED_BLOCK;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\tAllocator::BlockHeader::DbgFreeBlock( void )\r\n{\r\n\t\r\n\t\r\n\tuint64* ptr = (uint64*)((uint)this + sSize ); \t\r\n\r\n\tfor ( uint i = 0; i < mSize; i += 8 )\r\n\t{\r\n\t\t*ptr++ = vFREE_BLOCK;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\tAllocator::BlockHeader::DbgDump( void )\r\n{\r\n\t\r\n#ifdef __NOPT_FULL_DEBUG__\r\n\tDbg_Message ( \"\\nBlockHeader [%p]\\nmpAlloc/Next:%p\\nSize %d\\nstamp %x\\n\", this, mpAlloc, mSize, classStamp );\r\n#else\r\n\tDbg_Message ( \"\\nBlockHeader [%p]\\nmpAlloc/Next:%p\\nSize %d\\n\", this, mpAlloc, mSize );\r\n#endif\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#endif // __NOPT_MEM_DEBUG__\r\n\r\nbool  SameContext(void *p_mem,  Allocator *p_alloc);\r\n\r\n\r\n} // namespace Mem\r\n\r\n#endif  // __SYS_MEM_ALLOC_H\r\n"
  },
  {
    "path": "Code/Sys/Mem/handle.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory Manager (Mem)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/mem/handle.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_MEM_HANDLE_H\r\n#define\t__SYS_MEM_HANDLE_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/support.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnTemplateBaseClass( _T, Handle )\r\n{\r\n\t\r\n\r\n\t\r\npublic :\r\n\r\n\t\t\t\t\t\t\t\tHandle( _T* ptr = NULL );\r\n\t\t\t\t\t\t\t\t~Handle( void );\r\n\r\n\ttemplate < class _NewT >\t\t\t\t\t\t                    // template copy contructor\r\n\t\t\t\t\t\t\t\tHandle( Handle< _NewT >& rhs ); \t\t// needed to support inheritance correctly\r\n\t\r\n\ttemplate < class _NewT > \t\r\n\t\tHandle< _T >&\t\t\toperator = ( Handle< _NewT >& rhs );\t// template assignment operator\r\n\t\tHandle< _T >&\t\t\toperator = ( _T* ptr );\r\n\r\n\t\t_T*\t\t\t\t\t\tGetPointer( void ) const;\r\n\t\t\r\nprotected :\r\n\r\n\t\t_T*\t\t\t\t\t\tm_ptr;\r\n\t\tuint\t\t\t\t\tm_id;\r\n\t\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ntemplate < class _T > inline   \r\nHandle< _T >::Handle< _T >( _T* ptr ) \r\n: m_ptr ( ptr ), m_id ( Allocator::sGetId( ptr ))\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\n#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))\r\n// This version to fix Visual C++ compiler lack of ANSI C++ compliance.\r\n#else\r\ntemplate < class _T > template < class _NewT > inline\r\nHandle< _T >::Handle< _T >( Handle< _NewT >& rhs )\r\n: m_ptr ( rhs.m_ptr ), m_id ( rhs.m_id )\r\n{\r\n\t\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nHandle< _T >::~Handle( void )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))\r\n// This version to fix Visual C++ compiler lack of ANSI C++ compliance.\r\n#else\r\n template < class _T > template < class _NewT > inline\r\nHandle< _T >&\t\tHandle< _T >::operator = ( Handle< _NewT >& rhs ) \r\n{\r\n\t\r\n\r\n\tm_ptr = rhs.m_ptr;\r\n\tm_id  = rhs.m_id;\r\n\r\n\treturn *this;\t\r\n}\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nHandle< _T >&\t\tHandle< _T >::operator = ( _T* ptr ) \r\n{\r\n\t\r\n\r\n\tm_ptr = ptr;\r\n\tm_id  = Allocator::sGetId( ptr );\r\n\r\n\treturn *this;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\n_T*\t\tHandle< _T >::GetPointer ( void ) const \r\n{\r\n\t\r\n\r\n\tif (( m_ptr ) && ( m_id == Allocator::sGetId( m_ptr )))\r\n\t{\r\n\t\tDbg_AssertType( m_ptr, _T );\r\n\t\treturn m_ptr;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n#endif  // __SYS_MEM_HANDLE_H\t\t\t\t\t\t\t\t\r\n"
  },
  {
    "path": "Code/Sys/Mem/heap.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSystem Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory (Mem) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\theap.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tMaintained by:\tMick\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tHeap class\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n// (Mick) undefine this line if you want the full PS2 callstack reporting on allocations\r\n// and the trashing of memory\r\n// Also you might want to set gHeapPools in Poolable.cpp\r\n// which makes the pools use the debug heap, so this debuggin applies to them.\r\n#define __PURE_HEAP__\t\t\t// No debugging\r\n\r\n//////////////////////////////////////////////////////\r\n// Memory Debugging Trick:\r\n// dump the call stack for allocations and de-allocation of \r\n// a particular block \r\n// (maybe extend this to any block that encompasses this address????)  \t\t\t\t\t\t\t   \r\n#define\t\tREPORT_ON\t\t0\t\t\t// would be somethng like 0x3a2b50, if you want it to work \r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include \"memman.h\"\r\n#include \"heap.h\"\r\n#include <sys\\mem\\region.h>\r\n\r\n#define DUMP_HEAP 0\t\t\t// Change to 1 to have a handy text dump in memory of the heap status.\r\n\t\t\t\t\t\t\t// Use the debugger to see it - look at gMemStatus, 64 bytes per line.\r\n\r\n#define NUM_ADDRESS 0\t\t// Change this to 8 to have a handy list of addresses to check.\r\n\t\t\t\t\t\t\t// If set to 0, no extra code/data will be generated.\r\n\t\t\t\t\t\t\t// Remember to change to 8, compile, then get the addresses in question\r\n\t\t\t\t\t\t\t// as the act of adding this code/data will change your addresses.\r\n#if NUM_ADDRESS > 0\r\nuint32 gAddress[NUM_ADDRESS] =\r\n{\r\n\t0x81828561,\r\n\t0x818284c3,\r\n\t0x81827621,\r\n\t0x818275e3,\r\n\t0x81827541,\r\n\t0x81826523,\r\n\t0x818264e1,\r\n\t0x81826443\r\n};\r\n\r\nint g128 = 0;\r\nint g32 = 0;\r\n\r\nstatic void check_address( void * p, int size )\r\n{\r\n\tfor ( int lp = 0; lp < 8; lp++ )\r\n\t{\r\n\t\tif ( gAddress[lp] == ((uint32)p) ) {\r\n\t\t\tDbg_Message( \"We found the address we're looking for: 0x%08x (%d)\\n\", (uint32)p, size );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( size == 32 )\r\n\t{\r\n\t\tg32++;\r\n\t}\r\n\tif ( size == 128 )\r\n\t{\r\n\t\tg128++;\r\n\t}\r\n}\r\n\r\n#else\r\n#define check_address(a,b)\r\n#endif\r\n\r\n#if DUMP_HEAP == 1\r\n#ifdef __PLAT_XBOX__\r\nstatic SIZE_T\tpeakUsage = 64 * 1024 * 1024;\t// 64mb.\r\nchar gMemStatus[64*28];\r\n#else\r\nchar gMemStatus[64*16];\r\n#endif\r\n\r\nvoid dump_heap( void )\r\n{\r\n\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\r\n\tsprintf(&gMemStatus[64*0], \"Name            Used   Frag   Free   Blocks                    \\n\");\r\n\tsprintf(&gMemStatus[64*1], \"--------------- ------ ------ ------ ------                    \\n\");\r\n\tMem::Heap* heap;\r\n\tint line = 2;\r\n\tfor (heap = mem_man.FirstHeap(); heap != NULL; heap = mem_man.NextHeap(heap))\r\n\t{\t\t\r\n\t\t\tMem::Region* region = heap->ParentRegion();\t\t\t\r\n\t\t\tsprintf( &gMemStatus[64*line], \"%12s: %5dK %5dK %5dK   %5d \\n\",\r\n\t\t\t\t\theap->GetName(),\r\n\t\t\t\t\theap->mUsedMem.m_count / 1024,\r\n\t\t\t\t\theap->mFreeMem.m_count / 1024,\r\n\t\t\t\t\tregion->MemAvailable() / 1024,\r\n\t\t\t\t\theap->mUsedBlocks.m_count\r\n\t\t\t\t\t);\r\n\t\t\tline++;\r\n\t}\r\n\r\n#\tifdef __PLAT_XBOX__\r\n\tMEMORYSTATUS stat;\r\n    GlobalMemoryStatus( &stat );\r\n    sprintf( &gMemStatus[64 * line++], \"%4d  free kb of physical memory.\\n\", stat.dwAvailPhys / 1024 );\r\n\r\n\tif( stat.dwAvailPhys < peakUsage )\r\n\t\tpeakUsage = stat.dwAvailPhys;\r\n\r\n    sprintf( &gMemStatus[64 * line++], \"%4d  free kb at peak physical memory usage.\\n\", peakUsage / 1024 );\r\n#\tendif\r\n\r\n\r\n\r\n}\r\n#endif\t\t// DUMP_HEAP == 1\r\n\t\r\nnamespace Script\r\n{\r\n\tclass\tCStruct;\r\n\tclass\tCScript;\r\n}\r\n\r\nnamespace CFuncs\r\n{\r\nbool ScriptDumpHeaps( Script::CStruct *pParams, Script::CScript *pScript );\r\n}\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#include <gfx/ngps/p_memview.h>\r\n#elif defined( __PLAT_NGC__ )\r\n#include <gfx/ngc/p_memview.h>\r\n#endif\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__NOPT_ASSERT__\r\n#define\t__PURE_HEAP__\r\n#endif\r\n\r\n\r\n#ifndef\t__PURE_HEAP__\t\t\r\n#define\t__TRASH_BLOCKS__\t\t\t\t// define this to trash contents of alloc and free, regardless of build\t\t\t\t\r\n#endif\r\n\r\n\r\n\t\t\t\t\t\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline Mem::Allocator::BlockHeader*\tHeap::next_addr( Allocator::BlockHeader* pHeader )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( pHeader, BlockHeader );\r\n\r\n\treturn (BlockHeader*)( (uint)pHeader + BlockHeader::sSize + pHeader->mSize );\r\n}\r\n\r\n\r\n#ifdef\t__TRASH_BLOCKS__\r\n\r\n//static const uint64 vTRASH_ALLOCATED_BLOCK = 0x0101010101010101;\r\nstatic const uint64 vTRASH_ALLOCATED_BLOCK = 0x5555555555555555LL; \t// grey\r\nstatic const uint64 vTRASH_FREE_BLOCK \t =   0xbbbbbbbbbbbbbbbbLL;\t// white\r\n//static const uint64 vTRASH_FREE_BLOCK \t =       0x3f3f003f3f003f3f;\t// ??? ??? (with 0 so string are terminated)\r\n\t\t\t\t\t\t\t\t\r\n\r\ninline void\tTrash_AllocateBlock( Mem::Allocator::BlockHeader* pBlock )\r\n{\t\r\n#ifdef __EFFICIENT__\r\n\tmemset( (void*)((uint)pBlock + Mem::Allocator::BlockHeader::sSize ), vTRASH_ALLOCATED_BLOCK & 0xff, pBlock->mSize );\r\n#else\r\n\tuint64* ptr = (uint64*)((uint)pBlock + Mem::Allocator::BlockHeader::sSize );\r\n\r\n\tfor ( uint i = 0; i < pBlock->mSize; i += 8 )\r\n\t{\r\n\t\t*ptr++ = vTRASH_ALLOCATED_BLOCK;\r\n\t}\r\n#endif\t\t// __EFFICIENT__\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline void\tTrash_FreeBlock( Mem::Allocator::BlockHeader* pBlock )\r\n{\r\n#ifdef __EFFICIENT__\r\n\tmemset( (void*)((uint)pBlock + Mem::Allocator::BlockHeader::sSize ), vTRASH_FREE_BLOCK & 0xff, pBlock->mSize );\r\n#else\r\n\tuint64* ptr = (uint64*)((uint)pBlock + Mem::Allocator::BlockHeader::sSize ); \t\r\n\r\n\tfor ( uint i = 0; i < pBlock->mSize; i += 8 )\r\n\t{\r\n\t\t*ptr++ = vTRASH_FREE_BLOCK;\r\n\t}\r\n#endif\t\t// __EFFICIENT__\r\n}\r\n\r\ninline void\tTrash_FreeBlockHeader( Mem::Allocator::BlockHeader* pBlock )\r\n{\r\n#ifdef __EFFICIENT__\r\n\tmemset( (void*)((uint)pBlock), vTRASH_FREE_BLOCK & 0xff, Mem::Allocator::BlockHeader::sSize );\r\n#else\r\n\tuint64* ptr = (uint64*)((uint)pBlock); \t\r\n\r\n\tfor ( uint i = 0; i < Mem::Allocator::BlockHeader::sSize; i += 8 )\r\n\t{\r\n\t\t*ptr++ = vTRASH_FREE_BLOCK;\r\n\t}\r\n#endif\t\t// __EFFICIENT__\r\n}\r\n\r\n\r\n#endif\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tHeap::free ( BlockHeader* pFreeBlock )\r\n{\r\n#if DUMP_HEAP == 1\r\n\tdump_heap();\r\n#endif\t\t// DUMP_HEAP == 1\r\n\t\r\n#ifdef __EFFICIENT__\r\n\tpFreeBlock->mSize += pFreeBlock->mPadBytes;\r\n\tpFreeBlock->mPadBytes = 0;\r\n#endif\t\t// __EFFICIENT__\r\n\t\r\n\tDbg_AssertType ( pFreeBlock, BlockHeader );\r\n\r\n\t#ifdef\t__NOPT_ASSERT__\r\n\t#ifdef\t__PLAT_NGPS__\r\n\t// find what feeded a particular block\r\n\tif ( ((uint)pFreeBlock + BlockHeader::sSize) == REPORT_ON)\r\n\t{\r\n\t\tprintf (\"Freeing 0x%x\",REPORT_ON);\r\n\t\tDumpUnwindStack(20,NULL);\r\n\t}\r\n\t#endif\r\n\t#endif\r\n\t\t\t  \r\n\t\t\t  \r\n\tBlockHeader*\tp_before = NULL;\r\n\tBlockHeader*\tp_2before = NULL;\r\n\tBlockHeader*\tp_after = mp_context->mp_free_list;\r\n\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__    \r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#ifndef\t__PURE_HEAP__\t\t\r\n\tMemView_Free((void*)pFreeBlock);\r\n#endif\r\n#endif\r\n\tFreeMemProfile(pFreeBlock);\r\n\r\n\t// mp_next_used and mp_prev_used are a doble linked null ternimated list\r\n\r\n\t// unlink next and prev\r\n\tif ( pFreeBlock->mp_next_used )\r\n\t{\r\n\t\tpFreeBlock->mp_next_used->mp_prev_used = pFreeBlock->mp_prev_used;\r\n\t}\r\n\tif ( pFreeBlock->mp_prev_used )\r\n\t{\r\n\t\tpFreeBlock->mp_prev_used->mp_next_used = pFreeBlock->mp_next_used;\r\n\t}\r\n\t// unlink if it's the head of the list\r\n\tif ( mp_context->mp_used_list == pFreeBlock )\r\n\t{\r\n\t\tmp_context->mp_used_list = pFreeBlock->mp_next_used;\r\n\t}\r\n\r\n\tpFreeBlock->mp_prev_used = NULL;\r\n\tpFreeBlock->mp_next_used = NULL;\r\n\r\n#endif\r\n\r\n// we trash the free block before we merge it with anything\r\n// otherwise we end us trashing multi-megabytes\r\n// when memory is fragmented (which it often is, in the middle of things)\r\n\t#ifdef\t__TRASH_BLOCKS__\r\n\tTrash_FreeBlock ( pFreeBlock ); \r\n\t#endif\r\n\r\n\tmFreeBlocks++;\r\n\tmFreeMem += pFreeBlock->mSize;\r\n\r\n\tmUsedBlocks--;\r\n\tmUsedMem -= pFreeBlock->mSize;\r\n\r\n\t// p_after starts at the head of the free list\r\n\t// and traverses it until p_after is the block after this \r\n\t// block\r\n\twhile ( p_after && ( (uint)p_after < (uint)pFreeBlock ))\r\n\t{\t\t\r\n\t\tp_2before = p_before;\r\n\t\tp_before = p_after;\r\n\t\tp_after = p_after->mpNext;\r\n\t}\r\n\r\n\tpFreeBlock->mpNext = p_after; \t\t\t\t\t\t// insert pFreeBlock before p_after\r\n\t\r\n\r\n\tif ( p_after )\r\n\t{\r\n\t\tif ( next_addr( pFreeBlock ) == p_after ) \t\t// p_after joins pFreeBlock\r\n\t\t{\r\n\t\t\tpFreeBlock->mpNext = p_after->mpNext;\r\n\t\t\tpFreeBlock->mSize += p_after->mSize + BlockHeader::sSize;\r\n\t\t\t\r\n\t\t\t\t\t\t\t\t\t  \r\n\t\t\tp_after->~BlockHeader();\r\n\t\t\t#ifdef\t__TRASH_BLOCKS__\r\n\t\t\tTrash_FreeBlockHeader ( p_after ); \r\n\t\t\t#endif\r\n\t\t\tmFreeBlocks--;\r\n\t\t\tmFreeMem += BlockHeader::sSize;\r\n\t\t\tmUsedMem -= BlockHeader::sSize;\r\n\t\t}\r\n\t}\r\n\t\r\n\t\r\n\tif ( p_before )\r\n\t{\r\n\t\tif ( next_addr( p_before ) == pFreeBlock )\t\t// pFreeBlock joins p_before\r\n\t\t{\t\r\n\t\t\tp_before->mSize += pFreeBlock->mSize + BlockHeader::sSize;\r\n\t\t\tp_before->mpNext = pFreeBlock->mpNext;\r\n\r\n\r\n\r\n\t\t\tpFreeBlock->~BlockHeader();\r\n\t\t\t\r\n\t\t\t#ifdef\t__TRASH_BLOCKS__\r\n\t\t\tTrash_FreeBlockHeader ( pFreeBlock ); \r\n\t\t\t#endif\r\n\r\n\t\t\t\r\n\t\t\tmFreeBlocks--;\r\n\t\t\tmFreeMem += BlockHeader::sSize;\r\n\t\t\tmUsedMem -= BlockHeader::sSize;\r\n\t\t\t\r\n\t\t\tpFreeBlock = p_before;\r\n\t\t\tp_before = p_2before;\r\n\t\t}\r\n\t\telse\t\t\t\t\t\t\t\t\t\t\t// insert pFreeBlock after p_before\r\n\t\t{\t\t\t\t\t\t\t   \t\t\t\t\r\n\t\t\tp_before->mpNext = pFreeBlock;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_context->mp_free_list = pFreeBlock;\r\n\t}\r\n\r\n\tMemDbg_FreeBlock ( pFreeBlock ); \r\n\t\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// reclaim free space in region\r\n\r\n\tif ( ( m_dir == vBOTTOM_UP ) && ( !p_after ) && \r\n\t\t ( mp_top == (void*)((uint)pFreeBlock + pFreeBlock->mSize + BlockHeader::sSize )))\r\n\t{\r\n\t\tif( p_before )\r\n\t\t{\r\n\t\t\tp_before->mpNext = NULL;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_context->mp_free_list = NULL;\r\n\t\t}\r\n\r\n\r\n\r\n\t\tmp_top = (void*)((uint)mp_top - ( pFreeBlock->mSize + BlockHeader::sSize) * m_dir );\r\n\t\tpFreeBlock->~BlockHeader();\r\n\t\tmFreeBlocks--;\r\n\t\tmFreeMem -= pFreeBlock->mSize;\r\n\t\tmUsedMem -= BlockHeader::sSize;\r\n\t\t#ifdef\t__TRASH_BLOCKS__\r\n\t\tTrash_FreeBlockHeader ( pFreeBlock ); \r\n\t\t#endif\r\n\t}\r\n\telse if (( m_dir == vTOP_DOWN ) && ( !p_before ) &&\r\n\t\t\t ( mp_top == (void*)((uint)pFreeBlock )))\r\n\t{\t\t \r\n\t\r\n\t\r\n\t\tmp_top = (void*)((uint)mp_top - ( pFreeBlock->mSize + BlockHeader::sSize) * m_dir );\r\n\t\tmp_context->mp_free_list = pFreeBlock->mpNext;\r\n\t\tpFreeBlock->~BlockHeader();\r\n\t\t\r\n\t\t\r\n\t\tmFreeBlocks--;\r\n\t\tmFreeMem -= pFreeBlock->mSize;\r\n\t\tmUsedMem -= BlockHeader::sSize;\r\n\t\t#ifdef\t__TRASH_BLOCKS__\r\n\t\tTrash_FreeBlockHeader ( pFreeBlock ); \r\n\t\t#endif\r\n\t}\r\n\t\r\n#if 0\r\n\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\tMem::Heap* heap = mem_man.BottomUpHeap();\r\n\tMem::Region* region = heap->ParentRegion();\r\n\tif (heap->mFreeMem.m_count > 3200*1000)\r\n\t{\r\n\t\tprintf (\"\\nBottomUp Fragmentation %7dK, in %5d Blocks\\n\",heap->mFreeMem.m_count / 1024, heap->mFreeBlocks.m_count);\r\n\t\tDumpUnwindStack(20,NULL);\r\n\t\tMemView_DumpFragments(heap);\t\t\r\n\t\tDbg_MsgAssert(0,(\"Frag\"));\r\n\t}\r\n#endif\r\n\t\r\n\t\r\n\t\r\n}\r\n\r\n\r\n// Returns the size in bytes of either the largest free fragmented block,\r\n// or the free space in the region whichever is larger\r\nint Heap::LargestFreeBlock()\r\n{\r\n\t\r\n\tuint32 size = 0;\r\n\tBlockHeader* p_header = mp_context->mp_free_list;\r\n\twhile ( p_header ) \r\n\t{\r\n\t\tif ( p_header->mSize >= size )\r\n\t\t{\r\n\t\t\tsize = p_header->mSize;\r\n\t\t}\r\n\t\tp_header = p_header->mpNext;\r\n\t}\r\n\tuint32 region_size = mp_region->MemAvailable();\r\n\tif (region_size > size)\r\n\t{\t\r\n\t\tsize = region_size;\r\n\t}\r\n\treturn size;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Note the block returned might be bigger than asked for\r\n// by 16 or 32 bytes.\r\n// memory system calls MUST account for this \r\nvoid*\tHeap::allocate( size_t size, bool assert_on_fail )\r\n{\r\n#ifdef\t__PLAT_NGPS__\r\n//\tif (size > 10*1024)\r\n//\t{\r\n//\t\tprintf (\"\\nAllocating %d\\n\",size);\r\n//\t\tprintf (\"%s\\n\",Mem::Manager::sHandle().GetContextName());\r\n//\t}\r\n\t#endif\r\n\t\r\n\tDbg_MsgAssert(size >0, (\"Trying to allocate Zero bytes\\n\"));\r\n\t/*\r\n\tif (size == 0)\r\n\t{\r\n\t\tstatic int zeros=0;\r\n\t\tprintf(\"(%d) Trying to allocate Zero bytes\\n\", zeros++);\r\n\t\tDumpUnwindStack(20,NULL);\r\n\t}\r\n\t*/\t\r\n\t\r\n\t\r\n#if DUMP_HEAP == 1\r\n\tdump_heap();\r\n#endif\t\t// DUMP_HEAP == 1\r\n\r\n\tBlockHeader* p_header = mp_context->mp_free_list;\r\n\tBlockHeader* p_freeblock = NULL;\r\n\tBlockHeader* p_last = NULL;\r\n\tBlockHeader* p_prev = NULL;\r\n\r\n//\tprintf (\"Trying to allocate %d bytes, current free list = %p\\n\",size,p_header);\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t\t \r\n//\tif (size == 8688) while (1);\t\t\r\n\r\n#ifdef __EFFICIENT__\r\n\tint align = 1 << GetAlign();\r\n\tint offset_bytes;\r\n\tsize = (uint)nAlignUpBy( size, 2 );\t// all allocations aligned by 4 bytes\r\n#else\r\n#ifdef __PLAT_NGC__\r\n\tsize = (uint)nAlignUpBy( size, 5 );\t// all allocations aligned by 16 bytes\r\n#else\r\n\tsize = (uint)nAlignUpBy( size, 4 );\t// all allocations aligned by 16 bytes\r\n#endif\r\n#endif\r\n\twhile ( p_header ) \t// find smallest free block large enough to fulfill request\r\n\t{\r\n\t\tDbg_AssertType ( p_header, BlockHeader );\r\n\r\n#ifdef __EFFICIENT__\r\n\t\tint off = ( ( ( (int)p_header + BlockHeader::sSize ) + ( align - 1 ) ) & -align ) - ( (int)p_header + BlockHeader::sSize );\r\n\t\tuint adjusted_size = size + off;\r\n\t\tif ( p_header->mSize >= adjusted_size )\r\n#else\r\n\t\tif ( p_header->mSize >= size )\r\n#endif\r\n\t\t{\r\n\t\t\tif (( p_freeblock == NULL ) || ( p_freeblock->mSize > p_header->mSize ))\r\n\t\t\t{\r\n\t\t\t\tp_prev = p_last;\r\n\t\t\t\tp_freeblock = p_header;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tp_last = p_header;\r\n\t\tp_header = p_header->mpNext;\r\n\t}\r\n\r\n\tif ( p_freeblock )\t// found a free block large enough\r\n\t{\t\r\n#ifdef __EFFICIENT__\r\n\t\toffset_bytes = ( ( ( (int)p_freeblock + BlockHeader::sSize ) + ( align - 1 ) ) & -align ) - ( (int)p_freeblock + BlockHeader::sSize );\r\n#endif\r\n\t\tif ( p_prev )\r\n\t\t{\r\n\t\t\tp_prev->mpNext = p_freeblock->mpNext;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmp_context->mp_free_list = p_freeblock->mpNext;\r\n\t\t}\r\n\r\n\t\tp_freeblock->mpAlloc = this;\r\n\r\n\t\tmFreeBlocks--;\r\n\t\tmUsedBlocks++;\r\n\t\tmFreeMem -= p_freeblock->mSize;\r\n\t\tmUsedMem += p_freeblock->mSize;\r\n\r\n#ifdef __EFFICIENT__\r\n\t\tBlockHeader*\tp_leftover \t= (BlockHeader*)((uint)p_freeblock + BlockHeader::sSize + size + offset_bytes );\r\n\t\tint\t\t\t\tnew_size \t= p_freeblock->mSize - size - BlockHeader::sSize - offset_bytes;\r\n#else\r\n\t\tBlockHeader*\tp_leftover \t= (BlockHeader*)((uint)p_freeblock + BlockHeader::sSize + size );\r\n\t\tint\t\t\t\tnew_size \t= p_freeblock->mSize - size - BlockHeader::sSize;\r\n#endif\t\t// __EFFICIENT__\r\n\t\t\r\n\t\tif ( new_size > 0 )\t// create new free node for left-over memory\r\n\t\t{\r\n\t\t\tp_freeblock->mSize = size;\r\n\t\t\tnew ((void*)p_leftover) BlockHeader( this, new_size );\t\t\t\r\n\t\t\tmUsedBlocks++;\r\n\t\t\tfree( p_leftover );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// new_size is 0, which implies that this block is (size) ... (size + BlockHeader::Size)\r\n\t\t\t// which means we'll be allocating a bit more than we need\r\n\t\t\t// but as (size) is not reference again, then that's not a problem\r\n#ifdef __EFFICIENT__\r\n\t\t\tp_freeblock->mSize -= offset_bytes;\r\n#endif\t\t// __EFFICIENT__\r\n\t\t}\r\n\r\n\t}\r\n\telse\t\t\t\t// request extra space from region\r\n\t{\r\n\t\tp_freeblock = (BlockHeader*)mp_region->Allocate( this, size + BlockHeader::sSize, assert_on_fail );\r\n\r\n#ifdef __EFFICIENT__\r\n\t\tif ( m_dir == vBOTTOM_UP )\r\n\t\t{\r\n\t\t\toffset_bytes = ( ( ( (int)p_freeblock + BlockHeader::sSize ) + ( align - 1 ) ) & -align ) - ( (int)p_freeblock + BlockHeader::sSize );\r\n\t\t\t// Allocate, but keep the original pointer.\r\n\t\t\tmp_region->Allocate( this, offset_bytes, assert_on_fail );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\toffset_bytes = ( (int)p_freeblock + BlockHeader::sSize ) - ( ( (int)p_freeblock + BlockHeader::sSize ) & -align );\r\n\t\t\t// Allocate, increase size, not offset bytes.\r\n\t\t\tif ( offset_bytes )\r\n\t\t\t{\r\n\t\t\t\tp_freeblock = (BlockHeader*)mp_region->Allocate( this, offset_bytes, assert_on_fail );\r\n\t\t\t\tsize += offset_bytes;\r\n\t\t\t\toffset_bytes = 0;\r\n\t\t\t}\r\n\t\t}\r\n#endif\r\n\t\tif ( p_freeblock )\r\n\t\t{\r\n\t\t\tnew ((void*)p_freeblock) BlockHeader( this, size );\r\n\r\n\t\t\tmUsedBlocks++;\r\n#ifdef __EFFICIENT__\r\n\t\t\tmUsedMem += size + BlockHeader::sSize + offset_bytes;\r\n#else\t\t\t\r\n\t\t\tmUsedMem += size + BlockHeader::sSize;\r\n#endif\t\t// __EFFICIENT__\r\n\t\t}\r\n\t}\r\n\r\n\tif ( p_freeblock )\r\n\t{\t\t\r\n\t\tMemDbg_AllocateBlock ( p_freeblock );\r\n\r\n\t\t#ifdef\t__TRASH_BLOCKS__\r\n\t\tTrash_AllocateBlock ( p_freeblock ); \r\n\t\t#endif\r\n\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__    \r\n\r\n\t\tif( mp_context->mp_used_list )\r\n\t\t{\r\n\t\t\tp_freeblock->mp_next_used = mp_context->mp_used_list;\r\n\t\t\tmp_context->mp_used_list->mp_prev_used = p_freeblock;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_freeblock->mp_next_used = NULL;\t \t\r\n\t\t}\t\r\n\t\tp_freeblock->mp_prev_used = NULL;\t\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#ifndef\t__PURE_HEAP__\t\t\r\n\t\tMemView_Alloc((void*)p_freeblock);\r\n#endif\r\n#endif\r\n\t\tmp_context->mp_used_list = p_freeblock; \r\n#endif\r\n\t\tAllocMemProfile(p_freeblock);\r\n\r\n\t\t#ifdef\t__NOPT_ASSERT__\r\n\t\t#ifdef\t__PLAT_NGPS__\r\n\t\t// find what allocated a particular block\r\n\t\tif ( ((uint)p_freeblock + BlockHeader::sSize) == REPORT_ON)\r\n\t\t{\r\n\t\t\tprintf (\"allocating 0x%x\",REPORT_ON);\r\n\t\t\tDumpUnwindStack(20,NULL);\r\n\t\t}\r\n\t\t#endif\r\n\t\t#endif\r\n\r\n#ifdef __EFFICIENT__\r\n\t\tcheck_address( (void*)((uint)p_freeblock + BlockHeader::sSize + offset_bytes), size );\r\n\r\n\t\t// Fill padding bytes with bytes offset value.\r\n\t\tp_freeblock->mPadBytes = offset_bytes;\r\n\t\tuint8 * p8 = (uint8*)((uint)p_freeblock + BlockHeader::sSize);\r\n\t\tfor ( int lp = 0; lp < offset_bytes; lp++ )\r\n\t\t{\r\n\t\t\t*p8++ = offset_bytes;\r\n\t\t}\r\n\r\n\t\treturn (void*)((uint)p_freeblock + BlockHeader::sSize + offset_bytes);\r\n#else\r\n\t\tcheck_address( (void*)((uint)p_freeblock + BlockHeader::sSize), size );\r\n\r\n\t\treturn (void*)((uint)p_freeblock + BlockHeader::sSize);\r\n#endif\t\t// __EFFICIENT__\r\n\t}\r\n\r\n// Mick: heap allocations currently coded to ALWAYS assert on fail\r\n//\tif ( assert_on_fail )\r\n\t{\r\n\t\tDbg_MsgAssert ( false,( \"Failed to allocate %d bytes\", size ));\r\n\r\n\r\n\t}\r\n\r\n//\tMem::Heap* heap = Mem::Manager::sHandle().BottomUpHeap();\r\n//\tprintf (\"Dumping Fragments.....\\n\");\r\n//\tMemView_DumpFragments(heap);\r\n\t\r\n\r\n\tprintf (\"----------------------------------\\n\");\r\n\tprintf (\"failed to allocate %d bytes\\n\", size); \t\r\n\r\n#ifdef __PLAT_NGC__\r\n#ifndef __NOPT_FINAL__\r\n\t{\r\n\t\tMem::Manager& mem_man = Mem::Manager::sHandle();\r\n\r\n\t\tprintf (\"MEM CONTEXT: %s\\n\",Mem::Manager::sHandle().GetContextName());\r\n\t\tprintf(\"Name            Used  Frag  Free   Blocks\\n\");\r\n\t\tprintf(\"--------------- ----- ----- ------ ------\\n\");\r\n\t\tMem::Heap* heap;\r\n\t\tfor (heap = mem_man.FirstHeap(); heap != NULL; heap = mem_man.NextHeap(heap))\r\n\t\t{\t\t\r\n\t\t\t\tMem::Region* region = heap->ParentRegion();\t\t\t\r\n\t\t\t\tprintf( \"%12s: %6dK %6dK %6dK   %6d \\n\",\r\n\t\t\t\t\t\theap->GetName(),\r\n\t\t\t\t\t\theap->mUsedMem.m_count / 1024,\r\n\t\t\t\t\t\theap->mFreeMem.m_count / 1024,\r\n\t\t\t\t\t\tregion->MemAvailable() / 1024,\r\n\t\t\t\t\t\theap->mUsedBlocks.m_count\r\n\t\t\t\t\t\t);\t\t\t\t\t\t\t\t\t\t\r\n\t\t}\r\n\t}\r\n#endif\r\n#endif\t\t// __PLAT_NGC__ \r\n\r\n#ifndef __PLAT_WN32__\r\n\tCFuncs::ScriptDumpHeaps(NULL,NULL);\r\n#endif\r\n\r\n\treturn NULL;\r\n\r\n}\r\n\r\nint\tHeap::available()\r\n{\r\n\treturn LargestFreeBlock();\r\n}\r\n\r\n// Ken addition, for use by pip.cpp when it needs to reallocate the block of memory used\r\n// by a pre file that has just been loaded in, so that the pre can be decompressed.\r\n//\r\n// This function will return a pointer to a new block of memory which includes the original\r\n// block, but such that the returned pointer is lower down in memory than the original.\r\n// The original contents of the memory block will be unchanged.\r\n// This function is most likely to work if used on the top-down heap.\r\n// It will assert if it does not work.\r\nvoid* Heap::reallocate_down( size_t newSize, void *pOld )\r\n{\r\n\t// What this function is going to do is allocate a new block with size equal to \r\n\t// the difference between newSize and the size of pOld, then see if the new block \r\n\t// is directly below the passed pOld.\r\n\t// If it is, then it will merge the two blocks together.\r\n\t// If it is not, it will assert.\r\n\t\r\n\tDbg_MsgAssert(pOld,(\"NULL pOld sent to reallocate_down !\"));\r\n\tBlockHeader* p_old_block = BlockHeader::sRead( pOld ); \r\n\t\r\n#ifdef __EFFICIENT__\r\n\tnewSize = (uint)nAlignUpBy( newSize, 2 );\t// all allocations aligned by 4 bytes\r\n#else\r\n#ifdef __PLAT_NGC__\r\n\tnewSize = (uint)nAlignUpBy( newSize, 5 );\t// all allocations aligned by 32 bytes\r\n#else\r\n\tnewSize = (uint)nAlignUpBy( newSize, 4 );\t// all allocations aligned by 16 bytes\r\n#endif\r\n#endif\t\t// __EFFICIENT__\r\n\t\r\n\tDbg_MsgAssert(p_old_block->mSize < newSize,(\"Tried to reallocate a block that was already big enough, old size=%d, requested size=%d\",p_old_block->mSize,newSize));\r\n\t\r\n\t// When bobbling together the new and old blocks, we will gain the space used by the old\r\n\t// block header, so we don't really need to include that space in the new allocation request.\r\n\t// But, if newSize is exactly a blockheader size bigger than the old, then that would cause\r\n\t// allocate to be called on a size of zero.\r\n\t// So allocate a blockheader size more than necessary to avoid this.\r\n\tvoid *p_new=allocate(newSize-p_old_block->mSize,true);\r\n\tDbg_MsgAssert(p_new,(\"allocate failed!\"));\r\n\t\r\n\t// Got the new block, so now check that it is directly below the old.\t\r\n\tBlockHeader* p_new_block=BlockHeader::sRead( p_new );\r\n\tDbg_MsgAssert( (BlockHeader*)(((uint)p_new)+p_new_block->mSize) == p_old_block,(\"reallocate_down failed! New block is not directly below the old.\"));\r\n\t\r\n\t// Got this far, so the new block is right below the old.\r\n\t// Now we have to remove the old block header so as to bobble the two blocks together.\r\n\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__    \r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#ifndef\t__PURE_HEAP__\t  \r\n\t// Both blocks need to be freed from the memory tracker\r\n\t// as together they take up all the space of the new block, whcih will be added below  \r\n\tMemView_Free((void*)p_old_block); \r\n\tMemView_Free((void*)p_new_block); \r\n#endif\r\n#endif\r\n\r\n\t// mp_next_used and mp_prev_used are a doble linked null ternimated list\r\n\r\n\t// unlink next and prev\r\n\tif ( p_old_block->mp_next_used )\r\n\t{\r\n\t\tp_old_block->mp_next_used->mp_prev_used = p_old_block->mp_prev_used;\r\n\t}\r\n\tif ( p_old_block->mp_prev_used )\r\n\t{\r\n\t\tp_old_block->mp_prev_used->mp_next_used = p_old_block->mp_next_used;\r\n\t}\r\n\t// unlink if it's the head of the list\r\n\tif ( mp_context->mp_used_list == p_old_block )\r\n\t{\r\n\t\tmp_context->mp_used_list = p_old_block->mp_next_used;\r\n\t}\r\n\r\n\tp_old_block->mp_prev_used = NULL;\r\n\tp_old_block->mp_next_used = NULL;\r\n#endif\r\n// Free both blocks, so we can just add one later\r\n\tFreeMemProfile(p_old_block);\r\n\tFreeMemProfile(p_new_block);\r\n\r\n#ifdef __EFFICIENT__\r\n\tnewSize += p_old_block->mPadBytes;\r\n#endif\t\t// __EFFICIENT__\r\n\r\n\tp_old_block->~BlockHeader();\t\r\n\t#ifdef\t__TRASH_BLOCKS__\r\n\tTrash_FreeBlockHeader ( p_old_block ); \r\n\t#endif\r\n\t\r\n\t// The memory occupied by the old block header has gone from being used as a BlockHeader, \r\n\t// to being used as part of a used memory block, so mUsedMem does not need to change.\r\n\t// The number of used blocks has changed though, since two are being merged into one.\r\n\t--mUsedBlocks;\r\n\t// Nothing has changed regarding free blocks, so mFreeBlocks and mFreeMem stay the same.\r\n\t\r\n\t\r\n\t// That's p_old_block cleaned up, so now modify p_new_block's size.\r\n\tp_new_block->mSize=newSize+BlockHeader::sSize;\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#ifndef\t__PURE_HEAP__\t\t\r\n\tMemView_Alloc((void*)p_new_block);\r\n#endif\r\n#endif\r\n\tAllocMemProfile(p_new_block);\r\n\r\n\t\r\n#ifdef __EFFICIENT__\r\n\treturn (void*)((uint)p_new_block + BlockHeader::sSize + p_new_block->mPadBytes);\r\n#else\r\n\treturn (void*)((uint)p_new_block + BlockHeader::sSize);\r\n#endif\t\t// __EFFICIENT__\r\n}\r\n\r\n// This will make the passed memory block bigger.\r\n// The original contents of the memory block will be unchanged.\r\n// This function is most likely to work if used on the bottom-up heap.\r\n// It will assert if it does not work.\r\nvoid *Heap::reallocate_up( size_t newSize, void *pOld )\r\n{\r\n\t// What this function is going to do is allocate a new block with size equal to \r\n\t// the difference between newSize and the size of pOld, then see if the new block \r\n\t// is directly above the passed pOld.\r\n\t// If it is, then it will merge the two blocks together.\r\n\t// If it is not, it will assert.\r\n\t\r\n\tDbg_MsgAssert(pOld,(\"NULL pOld sent to reallocate_up !\"));\r\n\tBlockHeader* p_old_block = BlockHeader::sRead( pOld ); \r\n\t\r\n#ifdef __EFFICIENT__\r\n\tnewSize = (uint)nAlignUpBy( newSize, 2 );\t// all allocations aligned by 4 bytes\r\n#else\r\n#ifdef __PLAT_NGC__\r\n\tnewSize = (uint)nAlignUpBy( newSize, 5 );\t// all allocations aligned by 32 bytes\r\n#else\r\n\tnewSize = (uint)nAlignUpBy( newSize, 4 );\t// all allocations aligned by 16 bytes\r\n#endif\r\n#endif\t\t// __EFFICIENT__\r\n\t\r\n\tif (p_old_block->mSize >= newSize)\r\n\t{\r\n\t\t// The current block is already big enough, so nothing to do.\r\n\t\treturn pOld;\r\n\t}\r\n\t\t\r\n\t// When bobbling together the new and old blocks, we will gain the space used by the old\r\n\t// block header, so we don't really need to include that space in the new allocation request.\r\n\t// But, if newSize is exactly a blockheader size bigger than the old, then that would cause\r\n\t// allocate to be called on a size of zero.\r\n\t// So allocate a blockheader size more than necessary to avoid this.\r\n\tvoid *p_new=allocate(newSize-p_old_block->mSize,true);\r\n\tDbg_MsgAssert(p_new,(\"allocate failed!\"));\r\n\t\r\n\t// Got the new block, so now check that it is directly above the old.\t\r\n\tBlockHeader* p_new_block=BlockHeader::sRead( p_new );\r\n\tif ( (BlockHeader*)(((uint)pOld)+p_old_block->mSize) != p_new_block)\r\n\t{\r\n\t\t// It isn't!\r\n\t\tfree(p_new_block);\r\n\t\treturn NULL;\r\n\t}\t\r\n\t\r\n\t// Got this far, so the new block is right above the old.\r\n\t// Now we have to remove the new block header so as to bobble the two blocks together.\r\n\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__    \r\n\r\n// remove both blocks from memory tracking, ready to add the new block\r\n// that encompasses both of them\r\n#ifdef\t__PLAT_NGPS__\r\n#ifndef\t__PURE_HEAP__\t\t\r\n\tMemView_Free((void*)p_old_block); \r\n\tMemView_Free((void*)p_new_block); \r\n#endif\r\n#endif\r\n\t// mp_next_used and mp_prev_used are a doble linked null ternimated list\r\n\r\n\t// unlink next and prev\r\n\tif ( p_new_block->mp_next_used )\r\n\t{\r\n\t\tp_new_block->mp_next_used->mp_prev_used = p_new_block->mp_prev_used;\r\n\t}\r\n\tif ( p_new_block->mp_prev_used )\r\n\t{\r\n\t\tp_new_block->mp_prev_used->mp_next_used = p_new_block->mp_next_used;\r\n\t}\r\n\t// unlink if it's the head of the list\r\n\tif ( mp_context->mp_used_list == p_new_block )\r\n\t{\r\n\t\tmp_context->mp_used_list = p_new_block->mp_next_used;\r\n\t}\r\n\r\n\tp_new_block->mp_prev_used = NULL;\r\n\tp_new_block->mp_next_used = NULL;\r\n#endif\r\n\tFreeMemProfile(p_old_block);\r\n\tFreeMemProfile(p_new_block);\r\n\r\n\t// (Mick) Since the alloc function might return a bigger block than was asked for\r\n\t// we need to account for this in calculating the size of the new block\r\n\t// we can get the size of the new block before we trash the header\r\n\tint new_block_size = p_new_block->mSize;\r\n\r\n\tp_new_block->~BlockHeader();\t\r\n\t#ifdef\t__TRASH_BLOCKS__\r\n\tTrash_FreeBlockHeader ( p_new_block ); \r\n\t#endif\r\n\t\r\n\t// The memory occupied by the new block header has gone from being used as a BlockHeader, \r\n\t// to being used as part of a used memory block, so mUsedMem does not need to change.\r\n\t// The number of used blocks has changed though, since two are being merged into one.\r\n\t--mUsedBlocks;\r\n\t// Nothing has changed regarding free blocks, so mFreeBlocks and mFreeMem stay the same.\r\n\r\n#ifdef\t__NOPT_ASSERT__\r\n\tif (pOld == (void*)REPORT_ON)\r\n\t{\r\n\t\tprintf (\"%p: realloced up from %d to %d (actually %d) bytes\\n\", p_old_block, p_old_block->mSize, newSize, new_block_size + BlockHeader::sSize);  \t\r\n\t}\r\n#endif\r\n\t\r\n\t\r\n\t// That's p_new_block cleaned up, so now modify p_old_block's size.\r\n//\tp_old_block->mSize=newSize+BlockHeader::sSize;\t\t // Old method, did not account for alloc returning oversized blocks\r\n\tp_old_block->mSize += new_block_size + BlockHeader::sSize;\t  // (Mick) New method, uses the actual size of the new block (plus blockheader)\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#ifndef\t__PURE_HEAP__\t\t\r\n\tMemView_Alloc((void*)p_old_block); \r\n#endif\r\n#endif\r\n\tAllocMemProfile(p_old_block);\r\n\r\n\r\n\t\r\n\treturn pOld;\r\n}\r\n\r\nvoid *Heap::reallocate_shrink( size_t newSize, void *pOld )\r\n{\r\n\t// This will shrink the passed block by creating a new free block out of the remaining\r\n\t// space, if there is enough room to make a new free block. (at least 32 bytes needed)\r\n\t// It creates the new free block by first creating a new used block, then freeing that.\r\n\t// That way, all the merging of free blocks will be taken care of.\r\n\t\t\r\n\tDbg_MsgAssert(pOld,(\"NULL pOld sent to reallocate_up !\"));\r\n\tBlockHeader* p_old_block = BlockHeader::sRead( pOld ); \r\n\r\n\r\n\tDbg_MsgAssert(p_old_block->mpAlloc == this,(\"Shrinking block in wrong context\"));\r\n\r\n\r\n\t\r\n\t//printf(\"Block size before shrinking = %d\\n\",p_old_block->mSize);\r\n\t\r\n\tDbg_MsgAssert(newSize<=p_old_block->mSize,(\"Larger size sent to reallocate_shrink:\\nold size=%d  requested new size=%d\",p_old_block->mSize,newSize));\r\n\tuint32 size_diff=p_old_block->mSize-newSize;\r\n\t\r\n\t// We can only shrink down by a number of bytes that is divisible be 16 (4 on ngc), so\r\n\t// that the resulting block size for the old block remains a multiple of 16 (4)\r\n#ifdef __EFFICIENT__\r\n\tsize_diff&=~((1<<2)-1);\r\n#else\r\n\t#ifdef __PLAT_NGC__\r\n\tsize_diff&=~((1<<5)-1);\r\n\t#else\r\n\tsize_diff&=~((1<<4)-1);\r\n\t#endif\r\n#endif\t\t// __EFFICIENT__\r\n\t\r\n\t// If the amount the block is being shrunk by is not enough to hold a block header\r\n\t// with a bit left over, then we can't make a new free block with it, so return without\r\n\t// doing anything.\r\n\tif (size_diff<=BlockHeader::sSize)\r\n\t{\r\n\t\treturn pOld;\r\n\t}\t\r\n\t\r\n\t// Calculate a pointer to the new block.\r\n\tBlockHeader *p_new_block=(BlockHeader*)((uint32)pOld+p_old_block->mSize-size_diff);\r\n\r\n\t#ifdef\t__PLAT_NGPS__\r\n\tDbg_MsgAssert(((int)p_new_block&0xf) == 0,(\"p_new_block odd (%p), pOld = %p, p_old_block = %p, p_old_block->mSize = %d, size_diff = %d\",\r\n\t\t\t\t\t\t\t\t\t\tp_new_block, pOld, p_old_block->mSize, size_diff));\r\n\t#endif\r\n\t\r\n\t// Fill in new block header\r\n\tp_new_block->mSize=size_diff-BlockHeader::sSize;\r\n#ifdef __EFFICIENT__\r\n\tp_new_block->mPadBytes = 0;\r\n#endif\t\t// __EFFICIENT__ \r\n\t/////////////////////////////////////////////////////////////////////\r\n\t// Do all the stuff one needs to do when creating a new used block.\r\n\t// I just happily cut-and-pasted this lot from ::allocate\r\n\tp_new_block->mpAlloc = this;\r\n\tMemDbg_AllocateBlock ( p_new_block );\r\n\t#ifdef\t__TRASH_BLOCKS__\r\n\tTrash_AllocateBlock ( p_new_block ); \r\n\t#endif\r\n\r\n#ifdef\t__LINKED_LIST_HEAP__    \r\n\r\n\tif( mp_context->mp_used_list )\r\n\t{\r\n\t\tp_new_block->mp_next_used = mp_context->mp_used_list;\r\n\t\tmp_context->mp_used_list->mp_prev_used = p_new_block;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_new_block->mp_next_used = NULL;\t \t\r\n\t}\t\r\n\tp_new_block->mp_prev_used = NULL;\t\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#ifndef\t__PURE_HEAP__\t\t\r\n\tMemView_Alloc((void*)p_new_block);\r\n#endif\r\n#endif\r\n\tmp_context->mp_used_list = p_new_block; \r\n#endif\r\n\tAllocMemProfile(p_new_block);\r\n\t/////////////////////////////////////////////////////////////////////\r\n\t\r\n\t// mUsedMem does not change, since we've made a new used block out of memory\r\n\t// that was already being used.\r\n\t// The number of used blocks has increased by one though.\r\n\t++mUsedBlocks;\r\n\t// Nothing has changed regarding mFreeBlocks or mFreeMem yet. That will all be handled\r\n\t// when the block gets freed.\r\n\t\r\n\t// Free the block just created.\r\n\tfree(p_new_block);\r\n\t\t\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n#ifndef\t__PURE_HEAP__\t\t\r\n\tMemView_Free((void*)p_old_block);\t   // free at old size\r\n#endif\r\n#endif\r\n\tFreeMemProfile(p_old_block);\r\n\r\n\t// Update the size of the old block.\r\n\tp_old_block->mSize-=size_diff;\r\n\t\r\n#ifdef\t__PLAT_NGPS__\r\n#ifndef\t__PURE_HEAP__\t\t\r\n\tMemView_Alloc((void*)p_old_block);\t   // re-register at new size\r\n#endif\r\n#endif\r\n\tAllocMemProfile(p_old_block);\r\n\r\n\t\r\n\t//printf(\"New block size after shrinking = %d\\n\",p_old_block->mSize);\r\n\treturn pOld;\r\n}\r\n\r\n/****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nHeap::Heap( Region* region, Direction dir, char *p_name )\r\n: Allocator( region, dir, p_name )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n"
  },
  {
    "path": "Code/Sys/Mem/heap.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory Manager (Mem)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/mem/heap.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_MEM_HEAP_H\r\n#define\t__SYS_MEM_HEAP_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include \"alloc.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Region;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nclass  Heap : public  Allocator \t\t\t\r\n{\r\n\t\r\n\t\r\n\tfriend class Manager;\r\n\r\npublic :\r\n\t\t\r\n\t\t\t\t\t\t\t\tHeap( Region* region, Direction dir = vBOTTOM_UP, char* p_name = \"unknown heap\" );\r\n\r\n\tint\t\t\t\t\t\t\tLargestFreeBlock();\r\n\t\r\nprivate :\r\n\t\r\n\tvirtual\t\tvoid*\t\t\tallocate( size_t size, bool assert_on_fail );\r\n\tvirtual\t\tvoid\t\t\tfree( BlockHeader* pHeader );\r\n\r\n\tvirtual\t\tint\t\t\t\tavailable();\r\n\tvirtual\t\tvoid* \t\t\treallocate_down( size_t new_size, void *pOld );\r\n\tvirtual\t\tvoid*\t\t\treallocate_up( size_t newSize, void *pOld );\r\n\tvirtual\t\tvoid*\t\t\treallocate_shrink( size_t newSize, void *pOld );\r\n\t\r\n\t\t\t\t\r\n\t\t\t\tBlockHeader*\tnext_addr( BlockHeader* pHeader );\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n#endif  // __SYS_MEM_HEAP_H\r\n"
  },
  {
    "path": "Code/Sys/Mem/memdbg.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory Management (Mem)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsys/mem/memdbg.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_MEM_MEMDBG_H\r\n#define\t__SYS_MEM_MEMDBG_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mem\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#if defined( __PLAT_WN32__ ) || defined( __PLAT_XBOX__ )\r\nstatic const uint64 vALLOCATED_BLOCK = 0x0101010101010101i64;\r\nstatic const uint64 vFREE_BLOCK \t = 0x0303030303030303i64;\r\n#else\r\nstatic const uint64 vALLOCATED_BLOCK = 0x0101010101010101LL;\r\nstatic const uint64 vFREE_BLOCK \t = 0x0303030303030303LL;\r\n#endif\t// __PLAT_WN32__\r\n\r\n#ifdef __NOPT_MEM_DEBUG__\r\n\t\r\n#define MemDbg_AllocateBlock(_header)\t_header->DbgAllocateBlock()\r\n#define MemDbg_FreeBlock(_header)\t\t_header->DbgFreeBlock()\r\n\r\n#else // !__NOPT_MEM_DEBUG__\r\n\r\n#define MemDbg_AllocateBlock(_header)\r\n#define MemDbg_FreeBlock(_header)\r\n\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n   \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n#endif  // __SYS_MEM_MEMDBG_H\t\t\t\t\t\t\t\t\r\n"
  },
  {
    "path": "Code/Sys/Mem/memman.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSystem Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory (Mem) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmemman.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMemory manager\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <malloc.h>\r\n#include <string.h>\r\n#include <core/defines.h>\r\n#include <core/thread.h>\r\n#include <core/string/stringutils.h>\r\n#include \"memman.h\"\r\n#include <sys\\mem\\region.h>\r\n#include <sys\\config\\config.h>\t// for memory profiling, to see if we ahve the extra memory\r\n#include \"heap.h\"\r\n#include \"alloc.h\"\r\n#include <sys/profiler.h>\r\n#ifdef __PLAT_XBOX__\r\n#include <xtl.h>\r\n#endif\r\n#ifdef __PLAT_NGC__\r\n#include <dolphin.h>\r\n#endif\r\n\r\n#include <sk/heap_sizes.h>\r\n\r\n\r\n#ifdef\t__PLAT_NGPS__\r\n\r\nstatic\tbool\ts_use_semaphore = false;\r\n\r\nvoid WaitSemaMaybe(int sema)\r\n{\r\n\tif (s_use_semaphore)\r\n\t{\r\n\t\tWaitSema(sema);\r\n\t}\r\n}\r\n\r\n\r\nvoid SignalSemaMaybe(int sema) \r\n{\r\n\tif (s_use_semaphore)\r\n\t{\r\n\t\tSignalSema(sema);\r\n\t}\r\n}\r\n\r\n#endif\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#if defined ( __PLAT_NGPS__ )\r\nextern char _code_start[]\t\t\t\t\t__attribute__((section(\".text\")));\r\nextern char _code_end[]\t\t\t\t\t\t__attribute__((section(\".text\")));\r\nextern char _data_end[]\t\t\t\t\t\t__attribute__((section(\".text\")));\r\nextern char _mem_start[]\t\t\t\t\t__attribute__((section(\".mem_block\")));\r\nextern char _mem_end[]\t\t\t\t\t\t__attribute__((section(\".mem_block\")));\r\nextern char _std_mem_end[]\t\t\t\t\t__attribute__((section(\".mem_block\")));\r\nextern char _debug_heap_start[]\t\t\t\t__attribute__((section(\".mem_block\")));\r\nextern char _script_heap_start[]\t\t\t__attribute__((section(\".mem_block\")));\r\n#else\r\nchar* \t_code_start;\r\nchar* \t_code_end;\r\nchar* \t_data_end;\r\nchar* \t_mem_start;\r\nchar* \t_mem_end;\r\nchar*\t_std_mem_end;\r\nchar *\t_debug_heap_start;\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nchar \t\t\tManager::s_manager_buffer[sizeof(Manager)];\r\nchar \t\t\tManager::s_region_buffer[sizeof(Region)];\r\nchar \t\t\tManager::s_script_region_buffer[sizeof(Region)];\r\nchar \t\t\tManager::s_top_heap_buffer[sizeof(Heap)];\r\nchar \t\t\tManager::s_bot_heap_buffer[sizeof(Heap)];\r\nchar \t\t\tManager::s_debug_heap_buffer[sizeof(Heap)];\r\nManager*\t\tManager::sp_instance = NULL;\r\n#ifdef __PLAT_NGPS__\r\nstatic\tint\t\ts_context_semaphore;\r\n#endif\r\nchar\t\t\tManager::s_debug_region_buffer[sizeof(Region)];\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::Manager( void )\r\n{\r\n\t\r\n\t\r\n\tm_current_id = 0;\r\n\tmp_process_man = NULL;\r\n\t\r\n#\tif defined ( __PLAT_XBOX__ )\r\n\t// Just grab 33mb of main memory.\r\n\t_mem_start\t\t= (char*)XPhysicalAlloc(\t33 * 1024 * 1024,\t\t\t\t// size of region\r\n\t\t\t\t\t\t\t\t\t\t\t\tMAXULONG_PTR,\t\t\t\t\t// base physical address\r\n\t\t\t\t\t\t\t\t\t\t\t\t0,\t\t\t\t\t\t\t\t// memory alignment\r\n\t\t\t\t\t\t\t\t\t\t\t\tPAGE_READWRITE );\t\t\t\t// memory protection and type\r\n\r\n\t_mem_end\t\t= _mem_start + ( 33 * 1024 * 1024 );\r\n\t_std_mem_end\t= _mem_end;\r\n#\telif defined ( __PLAT_WN32__ )\r\n\t// Nasty hack for WN32 for now - just grab 38mb of main memory via a malloc.\r\n\t_mem_start\t= (char *)malloc( 38 * 1024 * 1024 );\r\n\t_mem_end\t= _mem_start + ( 38 * 1024 * 1024 );\r\n\t_std_mem_end = _mem_end;\r\n\r\n#\tendif \r\n#\tif defined ( __PLAT_NGC__ )\r\n\t// Fill in what we know.\r\n\t_code_start\t\t= (char *)0xfadebabe;\t\t// Junk addresses.\r\n\t_code_end\t\t= (char *)0xfacced00;\r\n\t_data_end\t\t= (char *)0xcaccfacc;\r\n\t_mem_start\t\t= &((char *)OSGetArenaLo())[8192];  // Real, actual useful addresses.\r\n\t_mem_end\t\t= (char *)OSGetArenaHi();\r\n\t_std_mem_end\t= (char *)OSGetArenaHi();\r\n#\tendif\r\n\r\n\t// create root memory region\r\n\tmp_region \t= new ((void*)s_region_buffer) Region( nAlignUp( _mem_start ), nAlignDown( _std_mem_end ) );\r\n\r\n\t// create default heaps\r\n\tmp_top_heap = new ((void*)s_top_heap_buffer) Heap( mp_region, Heap::vTOP_DOWN, \"Top Down\" );\r\n\tmp_bot_heap = new ((void*)s_bot_heap_buffer) Heap( mp_region, Heap::vBOTTOM_UP, \"BottomUp\" );\r\n\r\n\tm_heap_list[0] = mp_top_heap;\r\n\tm_heap_list[1] = mp_bot_heap;\r\n\t\r\n\tm_num_heaps = 2;\r\n\r\n#\tif !defined( __PLAT_NGC__ ) || ( defined( __PLAT_NGC__ ) && !defined( __NOPT_FINAL__ ) )\r\n\tuint codesize = ((uint)(_code_end) - (uint)(_code_start))/1024;\r\n\tuint datasize = ((uint)(_data_end) - (uint)(_code_end))/1024;\r\n\tprintf ( \"code [%p - %p] (%dK) + data [%p - %p] (%dK) = %dK \\n\",\r\n\t\t\t _code_start, _code_end, codesize, \r\n\t\t\t _code_end, _data_end, datasize,\r\n\t\t\t codesize + datasize );\r\n#endif\r\n\t\t\t \r\n\tm_pushed_context_count = 0;\r\n\tmp_internet_region = NULL;\r\n\tmp_net_misc_region = NULL;\r\n\r\n\tmp_cutscene_region = NULL;\r\n\tmp_cutscene_bottom_heap = NULL;\r\n\tmp_cutscene_top_heap = NULL;\r\n\r\n#ifdef __PLAT_NGPS__\r\n\t// Create a semaphore to prevent threads from re-entering push/pop memory contexts\r\n\tstruct SemaParam params;\r\n\r\n\tparams.initCount = 1;\r\n\tparams.maxCount = 10;\r\n\r\n\ts_context_semaphore = CreateSema( &params );\t\t\t \r\n#endif\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager( void )\r\n{\r\n\t\r\n\r\n\tmp_top_heap->~Heap();\r\n\tmp_bot_heap->~Heap();\r\n\tmp_region->~Region();\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tDeleteSema( s_context_semaphore );\r\n#endif\r\n}\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid*\tManager::New( size_t size, bool assert_on_fail, Allocator* pAlloc )\r\n{   \r\n#ifdef __PLAT_NGPS__\r\n\tWaitSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n\r\n\tif ( !pAlloc ) \t\t\t\t\t// set to 'default' allocator\r\n\t{\r\n\t\tpAlloc = mp_context->mp_alloc;\r\n\t}\r\n\r\n\tvoid* p_ret = pAlloc->allocate( size, assert_on_fail );\r\n\t\r\n\tif ( p_ret )\t// if allocation was successful\r\n\t{\r\n\t\tAllocator::s_set_id( p_ret );\t\t// stamp ID; used by Mem::Handle\r\n\t}\r\n\r\n#if 0 \r\n\tif ( mp_process_man )\r\n\t{\r\n\t\tmp_process_man->AllocEv( p_ret, size, pAlloc );\r\n\t}\r\n#endif\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tSignalSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n\r\n\treturn p_ret;\r\n}\r\n\r\n\r\n// Returns the amount of memory avaialbe in the current context\r\n// currently this is only valid for Heaps\r\nint\t\tManager::Available()\r\n{\r\n\treturn mp_context->mp_alloc->available();\r\n}\r\n\r\n// Ken addition, for use by pip.cpp when it needs to reallocate the block of memory used\r\n// by a pre file that has just been loaded in, so that the pre can be decompressed.\r\nvoid*\tManager::ReallocateDown( size_t newSize, void *pOld, Allocator* pAlloc )\r\n{   \r\n#ifdef __PLAT_NGPS__\r\n\tWaitSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n\r\n\tif ( !pAlloc ) \t\t\t\t\t// set to 'default' allocator\r\n\t{\r\n\t\tpAlloc = mp_context->mp_alloc;\r\n\t}\r\n\r\n\tvoid* p_ret = pAlloc->reallocate_down( newSize, pOld );\r\n\t\r\n\tif ( p_ret )\t// if allocation was successful\r\n\t{\r\n\t\tAllocator::s_set_id( p_ret );\t\t// stamp ID; used by Mem::Handle\r\n\t}\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tSignalSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n\r\n\treturn p_ret;\r\n}\r\n\r\n// Ken addition, for use by pip.cpp when it needs to reallocate the block of memory used\r\n// by a pre file that has just been loaded in, so that the pre can be decompressed.\r\n// This is for when the bottoms-up heap is being used.\r\nvoid *Manager::ReallocateUp( size_t newSize, void *pOld, Allocator* pAlloc )\r\n{   \r\n#ifdef __PLAT_NGPS__\r\n\tWaitSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n\r\n\tif ( !pAlloc ) \t\t\t\t\t// set to 'default' allocator\r\n\t{\r\n\t\tpAlloc = mp_context->mp_alloc;\r\n\t}\r\n\r\n\tvoid* p_ret = pAlloc->reallocate_up( newSize, pOld );\r\n\t\r\n\tif ( p_ret )\t// if allocation was successful\r\n\t{\r\n\t\tAllocator::s_set_id( p_ret );\t\t// stamp ID; used by Mem::Handle\r\n\t}\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tSignalSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n\r\n\treturn p_ret;\r\n}\r\n\r\nvoid *Manager::ReallocateShrink( size_t newSize, void *pOld, Allocator* pAlloc )\r\n{   \r\n#ifdef __PLAT_NGPS__\r\n\tWaitSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n\r\n\tif ( !pAlloc ) \t\t\t\t\t// set to 'default' allocator\r\n\t{\r\n\t\tpAlloc = mp_context->mp_alloc;\r\n\t}\r\n\r\n\tvoid* p_ret = pAlloc->reallocate_shrink( newSize, pOld );\r\n\t\r\n\tif ( p_ret )\t// if allocation was successful\r\n\t{\r\n\t\tAllocator::s_set_id( p_ret );\t\t// stamp ID; used by Mem::Handle\r\n\t}\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tSignalSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::PushMemoryMarker( uint32 uiID )\r\n{\r\n}\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::PopMemoryMarker( uint32 uiID )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nvoid\tManager::Delete( void* pAddr )\r\n{\r\n#ifdef __PLAT_NGPS__\r\n\tWaitSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n\r\n\tif( pAddr != NULL )\r\n\t{\r\n\t\tAllocator::s_free( pAddr );\r\n\r\n#if 0\r\n\t\t// 000810 JAB: Modified s_free to return the allocator.\r\n\t\tif (mp_process_man)\r\n\t\t{\r\n\t\t\tmp_process_man->FreeEv( pAddr, p_alloc );\r\n\t\t}\r\n#endif\r\n\r\n\t}\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tSignalSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nbool\tManager::Valid( void* pAddr )\r\n{\r\n\tif( pAddr != NULL )\r\n\t{\r\n\t\treturn Allocator::s_valid( pAddr );\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nsize_t\tManager::GetAllocSize( void* pAddr )\r\n{\r\n\tif( pAddr != NULL )\r\n\t{\r\n\t\treturn Allocator::s_get_alloc_size( pAddr );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Trying to get the size of an invalid block\" ) );\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::PushContext( Allocator* alloc )\r\n{\r\n\t\r\n\tDbg_AssertType ( alloc, Allocator );\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tWaitSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n\r\n//\tprintf (\"Pushed context %d to %s\\n\",m_pushed_context_count, alloc->GetName());\r\n//\tDumpUnwindStack(20,0);\r\n\r\n\tDbg_MsgAssert(m_pushed_context_count < vMAX_CONTEXT-1,(\"Pushed too many contexts\"));\r\n\tmp_context = &m_contexts[m_pushed_context_count];\t\r\n\tmp_context->mp_alloc = alloc;\t\r\n\tm_pushed_context_count++;\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tSignalSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::PopContext( void )\r\n{\r\n\t\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tWaitSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n\r\n\tDbg_MsgAssert( m_pushed_context_count,( \"Heap stack underflow\" ));\r\n\t\r\n\tm_pushed_context_count--;\r\n\tm_contexts[m_pushed_context_count].mp_alloc = (Mem::Allocator*)-1;\t\r\n\tif (m_pushed_context_count)\r\n\t{\r\n\t\tmp_context = &m_contexts[m_pushed_context_count-1];\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_context = NULL;\t // stack has now been emptied\r\n\t}\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tSignalSemaMaybe( s_context_semaphore );\r\n#endif // __PLAT_NGPS__\r\n}\r\n\r\n//GJ:  Context number doesn't seem to be used...\r\n//Originally, it was used so that you could access the heaps from script,\r\n//but now you can access the heaps using names, so the numbers aren't needed\r\n//any more\r\n//int Manager::GetContextNumber()\r\n//{   \r\n//\treturn mp_context->mp_alloc->GetNumber();\t\t\r\n//}\r\n\r\nchar * Manager::GetContextName()\r\n{\r\n\t\r\n\treturn mp_context->mp_alloc->GetName();\t\t\r\n}\r\n\r\nAllocator* Manager::GetContextAllocator()\r\n{\r\n\t\r\n\treturn mp_context->mp_alloc;\t\t\r\n}\r\n\r\n// Added by Ken, so that pip.cpp knows whether to try and expand a memory block up or down.\r\nAllocator::Direction Manager::GetContextDirection()\r\n{\r\n\t\r\n\treturn mp_context->mp_alloc->GetDirection();\t\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nconst char* Manager::GetHeapName( uint32 whichHeap )\r\n{\r\n\t// first look through the named heaps...\r\n\tCNamedHeapInfo* pInfo = find_named_heap_info( whichHeap );\r\n\tif ( pInfo )\r\n\t{\r\n\t\treturn pInfo->mp_heap_name;\r\n\t}\r\n\t\r\n\tswitch ( whichHeap )\r\n\t{\r\n\t\tcase 0xc7800b0:\t\t// bottomupheap\r\n\t\t\treturn \"BottomUpHeap\";\r\n\t\t\tbreak;\r\n\t\tcase 0x8fdb68af:\t\t// topdownheap\r\n\t\t\treturn \"TopDownHeap\";\r\n\t\t\tbreak;\r\n\t\tcase 0x62f3a0f3:\t\t// frontendheap\r\n\t\t\treturn \"FrontEndHeap\";\r\n\t\t\tbreak;\r\n\t\tcase 0xe3551d2e:\t\t// networkheap\r\n\t\t\treturn \"NetworkHeap\";\r\n\t\t\tbreak;\r\n\t\tcase 0x96d29d93:\t\t// netmischeap\r\n\t\t\treturn \"NetMiscHeap\";\r\n\t\t\tbreak;\r\n\t\tcase 0xfcd5166b:\t\t// internettopdownheap\r\n\t\t\treturn \"InternetTopDownHeap\";\r\n\t\t\tbreak;\r\n\t\tcase 0x90020867:\t\t// internetbottomupheap\r\n\t\t\treturn \"InternetBottomUpHeap\";\r\n\t\t\tbreak;\r\n\t\tcase 0xfa33d9b:\t\t// scriptheap\r\n\t\t\treturn \"ScriptHeap\";\r\n\t\t\tbreak;\r\n\t\tcase 0x70cb0238:\t\t// debugheap\r\n\t\t\treturn \"DebugHeap\";\r\n\t\t\tbreak;\r\n\t\tcase 0xc3909393:\t\t// skaterheap0\r\n\t\t\treturn \"Skater0\";\r\n\t\t\tbreak;\r\n\t\tcase 0xb497a305:\t\t// skaterheap1\r\n\t\t\treturn \"Skater1\";\r\n\t\t\tbreak;\r\n\t\tcase 0x2d9ef2bf:\t\t// skaterheap2\r\n\t\t\treturn \"Skater2\";\r\n\t\t\tbreak;\r\n\t\tcase 0x5a99c229:\t\t// skaterheap3\r\n\t\t\treturn \"Skater3\";\r\n\t\t\tbreak;\r\n\t\tcase 0x572a9f4c:\t\t// skatergeomheap0\r\n\t\t\treturn \"SkaterGeom0\";\r\n\t\t\tbreak;\r\n\t\tcase 0x202dafda:\t\t// skatergeomheap1\r\n\t\t\treturn \"SkaterGeom1\";\r\n\t\t\tbreak;\r\n\t\tcase 0xb924fe60:\t\t// skatergeomheap2\r\n\t\t\treturn \"SkaterGeom2\";\r\n\t\t\tbreak;\r\n\t\tcase 0xce23cef6:\t\t// skatergeomheap3\r\n\t\t\treturn \"SkaterGeom3\";\r\n\t\t\tbreak;\r\n\t\tcase 0x8682d24:\t\t// skaterinfoheap\r\n\t\t\treturn \"SkaterInfo\";\r\n\t\t\tbreak;\r\n        case 0x17ecb880:\t\t// themeheap\r\n\t\t\treturn \"ThemeHeap\";\r\n            break;\r\n        case 0x7ed56b49:\t\t// CutsceneBottomUpHeap\r\n\t\t\treturn \"CutsceneBottomUp\";\r\n            break;\r\n        case 0x25d71469:\t\t// CutsceneTopDownHeap\r\n\t\t\treturn \"CutsceneTopDown\";\r\n            break;\r\n\t\tdefault:\t// unrecognized heap\r\n\t\t\tDbg_Assert ( 0 );\r\n\t}\r\n\r\n\treturn \"Unrecognized Heap\";\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nHeap* Manager::GetHeap( uint32 whichHeap )\r\n{\r\n\tHeap* pHeap = NULL;\r\n\r\n\t// first look through the named heaps...\r\n\tCNamedHeapInfo* pInfo = find_named_heap_info( whichHeap );\r\n\tif ( pInfo )\r\n\t{\r\n\t\treturn pInfo->mp_heap;\r\n\t}\r\n\r\n\tswitch ( whichHeap )\r\n\t{\r\n\t\tcase 0xc7800b0:\t\t// bottomupheap\r\n\t\t\tpHeap = BottomUpHeap();\r\n\t\t\tbreak;\r\n\t\tcase 0x8fdb68af:\t\t// topdownheap\r\n\t\t\tpHeap = TopDownHeap();\r\n\t\t\tbreak;\r\n\t\tcase 0x62f3a0f3:\t\t// frontendheap\r\n\t\t\tpHeap = FrontEndHeap();\r\n\t\t\tbreak;\r\n\t\tcase 0xe3551d2e:\t\t// networkheap\r\n\t\t\tpHeap = NetworkHeap();\r\n\t\t\tbreak;\r\n\t\tcase 0x96d29d93:\t\t// netmischeap\r\n\t\t\tpHeap = NetMiscHeap();\r\n\t\t\tbreak;\r\n\t\tcase 0xfcd5166b:\t\t// internettopdownheap\r\n\t\t\tpHeap = InternetTopDownHeap();\r\n\t\t\tbreak;\r\n\t\tcase 0x90020867:\t\t// internetbottomupheap\r\n\t\t\tpHeap = InternetBottomUpHeap();\r\n\t\t\tbreak;\r\n\t\tcase 0xfa33d9b:\t\t// scriptheap\r\n\t\t\tpHeap = ScriptHeap();\r\n\t\t\tbreak;\r\n\t\tcase 0x70cb0238:\t\t// debugheap\r\n\t\t\tpHeap = DebugHeap();\r\n\t\t\tbreak;\r\n\t\tcase 0xc3909393:\t\t// skaterheap0\r\n\t\t\tpHeap = SkaterHeap(0);\r\n\t\t\tbreak;\r\n\t\tcase 0xb497a305:\t\t// skaterheap1\r\n\t\t\tpHeap = SkaterHeap(1);\r\n\t\t\tbreak;\r\n\t\tcase 0x2d9ef2bf:\t\t// skaterheap2\r\n\t\t\tpHeap = SkaterHeap(2);\r\n\t\t\tbreak;\r\n\t\tcase 0x5a99c229:\t\t// skaterheap3\r\n\t\t\tpHeap = SkaterHeap(3);\r\n\t\t\tbreak;\r\n\t\tcase 0x572a9f4c:\t\t// skatergeomheap0\r\n\t\t\tpHeap = SkaterGeomHeap(0);\r\n\t\t\tbreak;\r\n\t\tcase 0x202dafda:\t\t// skatergeomheap1\r\n\t\t\tpHeap = SkaterGeomHeap(1);\r\n\t\tbreak;\r\n\t\tcase 0xb924fe60:\t\t// skatergeomheap2\r\n\t\t\tpHeap = SkaterGeomHeap(2);\r\n\t\tbreak;\r\n\t\tcase 0xce23cef6:\t\t// skatergeomheap3\r\n\t\t\tpHeap = SkaterGeomHeap(3);\r\n\t\tbreak;\r\n\t\tcase 0x8682d24:\t\t// skaterinfoheap\r\n\t\t\tpHeap = SkaterInfoHeap();\r\n\t\tbreak;\r\n        case 0x17ecb880:\t\t// themeheap\r\n\t\t\tpHeap = ThemeHeap();\r\n\t\tbreak;\r\n        case 0x7ed56b49:\t\t// CutsceneBottomUpHeap\r\n\t\t\tpHeap = CutsceneBottomUpHeap();\r\n\t\tbreak;\r\n        case 0x25d71469:\t\t// CutsceneTopDownHeap\r\n\t\t\tpHeap = CutsceneTopDownHeap();\r\n\t\tbreak;\r\n\t\tdefault:\t// unrecognized heap\r\n\t\t\tDbg_MsgAssert ( 0, ( \"Unrecognized heap %08x\", whichHeap ) );\r\n\t}\r\n\r\n\treturn pHeap;\r\n}\r\n\r\n\r\nMem::Heap *Manager::CreateHeap( Region* region, Mem::Allocator::Direction dir, char* p_name)\r\n{\r\n\tMem::Heap * pHeap = new Mem::Heap(region, dir, p_name);\r\n\t// At this point we can maintain the heap list \r\n\tm_heap_list[m_num_heaps++] = pHeap;\r\n\treturn pHeap;\r\n}\r\n\r\nvoid Manager::RemoveHeap(Mem::Heap *pHeap)\r\n{\r\n\r\n#ifndef __PLAT_WN32__\r\n\t#ifdef\t__NOPT_ASSERT__\t\t\t \r\n\t// Check first to see if there is something on the heap before it is deleted\r\n\t// Deleting a heap with stuff on it might indicate an error\r\n\tif (pHeap->mUsedBlocks.m_count)\r\n\t{\r\n\t\tprintf (\"Deleting a heap %s with %d used blocks still on it\\n\",pHeap->mp_name,pHeap->mUsedBlocks.m_count);\r\n\t\t#ifndef __PLAT_NGC__\r\n\t\tprintf (\"\\n\\nDumping Heap\\n\");\r\n\t\tMemView_DumpHeap(pHeap);\r\n\t\tprintf (\"\\n\\nAnalyzing Heap\\n\");\r\n\t\tMemView_AnalyzeHeap(pHeap);\r\n\t\tDbg_MsgAssert(0, (\"Deleting heap <%s> with %d used blocks still on it\\n\",pHeap->mp_name,pHeap->mUsedBlocks.m_count));\r\n\t\t\r\n\t\t#endif\t\t// __PLAT_NGC__\r\n\t}\r\n\t#endif\r\n#endif\r\n\r\n\t// remove from list of heaps\r\n\tfor (int i=0;i<m_num_heaps;i++)\r\n\t{\r\n\t\tif (m_heap_list[i] == pHeap)\r\n\t\t{\r\n\t\t\tm_num_heaps--;\t \t\t\t\t\t\t\t// chop off the last heaps\r\n\t\t\tm_heap_list[i] = m_heap_list[m_num_heaps]; \t// and insert if in the hole\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\t\r\n\t\r\n\tdelete pHeap;\t\r\n\t\r\n}\r\n\r\nMem::Heap *\t\tManager::FirstHeap()\r\n{\r\n\tif (m_num_heaps)\r\n\t{\r\n\t\treturn m_heap_list[0];\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n\r\nMem::Heap *\t\tManager::NextHeap(Mem::Heap * pHeap)\r\n{\r\n\tfor (int i = 0; i<m_num_heaps-1;i++)\r\n\t{\r\n\t\tif (m_heap_list[i] == pHeap)\r\n\t\t{\r\n\t\t\treturn m_heap_list[i+1];\r\n\t\t}\r\n\t}\r\n\treturn NULL;\t\r\n}\r\n\r\n#ifdef\tDEBUG_ADJUSTMENT\r\nstatic void *p_adjustment;\r\n#endif\r\n\r\nvoid Manager::InitOtherHeaps()\r\n{\r\n\tif (Config::Bootstrap())\r\n\t{\r\n\t\tmp_frontend_region = new Mem::AllocRegion( (BOOTSTRAP_FRONTEND_HEAP_SIZE) );\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmp_frontend_region = new Mem::AllocRegion( (FRONTEND_HEAP_SIZE) );\t\r\n\t}\r\n\t\r\n\tprintf (\"allocated mp_frontend_region at %p\\n\",mp_frontend_region);\r\n\t\r\n\t// Network heap is now a top down heap on the the FE region\r\n\t// as they are mutually exclusive in their peak usages\r\n\t// since network heap is only really used in game, when FE usage is small\r\n\tmp_network_heap = CreateHeap( mp_frontend_region, Mem::Allocator::vTOP_DOWN, \"Network\" );\r\n\tprintf (\"Setup TOP_DOWN mp_network_heap at %p\\n\",mp_network_heap);\r\n\tmp_frontend_heap = CreateHeap( mp_frontend_region, Mem::Allocator::vBOTTOM_UP, \"FrontEnd\" );\r\n\tprintf (\"Setup mp_frontend_heap at %p\\n\",mp_frontend_heap);\r\n\t\r\n#ifdef __PLAT_NGC__\r\n\tmp_audio_region = new Mem::AllocRegion( (AUDIO_HEAP_SIZE) );\t\r\n\tprintf (\"allocated mp_audio_region at %p\\n\",mp_audio_region);\r\n\tmp_audio_heap = CreateHeap( mp_audio_region, Mem::Allocator::vBOTTOM_UP, \"Audio\" );\r\n\tprintf (\"Setup mp_audio_heap at %p\\n\",mp_audio_heap);\r\n#endif\t\t// __PLAT_NGC__ \r\n\r\n#ifdef\tDEBUG_ADJUSTMENT\r\n// allocate the script region off the debug heap\r\n// and then allocate a block of size (SCRIPT_HEAP_SIZE-DEBUG_ADJUSTMENT)\r\n// to bring regular memory usage back into line with non-debug builds\r\n\tmp_script_region \t= new ((void*)s_script_region_buffer) Region( nAlignUp( _script_heap_start ), nAlignDown( _script_heap_start+SCRIPT_HEAP_SIZE ) );\r\n\tprintf (\"allocated mp_script_region at %p\\n\",mp_script_region);\r\n\tmp_script_heap = CreateHeap( mp_script_region, Mem::Allocator::vBOTTOM_UP, \"Script\" );\r\n\tprintf (\"Setup mp_script_heap at %p\\n\",mp_script_heap);\r\n\t// and allocate the extra memory of the regular heap and forget about it\r\n\tp_adjustment = Mem::Malloc(SCRIPT_HEAP_SIZE-DEBUG_ADJUSTMENT);\r\n#else\t\r\n\tmp_script_region = new Mem::AllocRegion( (SCRIPT_HEAP_SIZE) );\t\r\n\tprintf (\"allocated mp_script_region at %p\\n\",mp_script_region);\r\n\tmp_script_heap = CreateHeap( mp_script_region, Mem::Allocator::vBOTTOM_UP, \"Script\" );\r\n\tprintf (\"Setup mp_script_heap at %p\\n\",mp_script_heap);\r\n#endif\r\n\r\n#ifdef\t\t__USE_PROFILER__\r\n\tmp_profiler_region = new Mem::AllocRegion( (PROFILER_HEAP_SIZE) );\t\r\n\tprintf (\"allocated mp_profiler_region at %p\\n\",mp_profiler_region);\r\n\tmp_profiler_heap = CreateHeap( mp_profiler_region, Mem::Allocator::vBOTTOM_UP, \"profiler\" );\r\n\tprintf (\"Setup mp_profiler_heap at %p\\n\",mp_profiler_heap);\r\n#endif\r\n\r\n\tmp_skater_info_region = new Mem::AllocRegion( (SKATERINFO_HEAP_SIZE) );\t\r\n\tprintf (\"allocated mp_skater_info_region at %p\\n\",mp_skater_info_region);\r\n\tmp_skater_info_heap = CreateHeap( mp_skater_info_region, Mem::Allocator::vBOTTOM_UP, \"skt_info\" );\r\n\tprintf (\"Setup mp_skater_info_heap at %p\\n\",mp_skater_info_heap);\r\n\r\n    mp_theme_region = new Mem::AllocRegion( (THEME_HEAP_SIZE) );\t\r\n\tprintf (\"allocated mp_theme_region at %p\\n\",mp_theme_region);\r\n\tmp_theme_heap = CreateHeap( mp_theme_region, Mem::Allocator::vBOTTOM_UP, \"theme\" );\r\n\tprintf (\"Setup mp_theme_heap at %p\\n\",mp_theme_heap);\r\n\r\n\t// Allocate the permanent skater heap(s)\r\n\t\r\n\tfor (int i = 0; i< NUM_PERM_SKATER_HEAPS; i++)\r\n\t{\r\n\t\tmp_skater_region[i] = new Mem::AllocRegion( (SKATER_HEAP_SIZE) );\t\r\n\t\tprintf (\"allocated mp_skater_region at %p\\n\",mp_skater_region[i]);\r\n\t\tmp_skater_heap[i] = CreateHeap( mp_skater_region[i], Mem::Allocator::vBOTTOM_UP, \"skater\" );\r\n\t\tprintf (\"Setup mp_skater_heap at %p\\n\",mp_skater_heap[i]);\r\n\r\n\t\tmp_skater_geom_region[i] = new Mem::AllocRegion( (SKATER_GEOM_HEAP_SIZE) );\r\n\t\tprintf (\"allocated mp_skater_geom_region at %p\\n\",mp_skater_geom_region[i]);\r\n\t\tmp_skater_geom_heap[i] = CreateHeap( mp_skater_geom_region[i], Mem::Allocator::vBOTTOM_UP, \"skater_geom\" );\r\n\t\tprintf (\"Setup mp_skater_geom_heap at %p\\n\",mp_skater_geom_heap[i]);\r\n\t}\r\n\t// clear other temp heaps to null\r\n\tfor (int heap = NUM_PERM_SKATER_HEAPS; heap < NUM_SKATER_HEAPS; heap++)\r\n\t{\r\n\t\tmp_skater_region[heap] = NULL;\t\t\t\r\n\t\tmp_skater_heap[heap] = NULL;\t  \r\n\r\n\t\tmp_skater_geom_region[heap] = NULL;\r\n\t\tmp_skater_geom_heap[heap] = NULL;\r\n\t}\r\n}\r\n\r\nvoid Manager::InitNetMiscHeap()\r\n{\r\n\tif( mp_net_misc_region == NULL )\r\n\t{\r\n\r\n\t\t//#ifndef\t__NOPT_ASSERT__\r\n\t\t#if\t1\t\t// always allocate internet heap normally\r\n\t\t// normally the internet heap just goes on the top down heap\r\n\t\tsp_instance->PushContext( sp_instance->mp_bot_heap );\r\n\t\t#else\r\n\t\t// but with assertions there is not enough room, so put it on the debug heap\r\n\t\tif (Config::GotExtraMemory())\r\n\t\t{\r\n\t\t\tsp_instance->PushContext( sp_instance->mp_debug_heap );\t\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// running on a regular PS2, allow them to try, but will probably fail later with out of memory\r\n\t\t\tsp_instance->PushContext( sp_instance->mp_bot_heap );\r\n\t\t}\r\n\t\t#endif\t\t\r\n\t\t\r\n\t\tmp_net_misc_region = new Mem::AllocRegion( (NETMISC_HEAP_SIZE) );\t\r\n\t\tmp_net_misc_heap = CreateHeap( mp_net_misc_region, Mem::Allocator::vBOTTOM_UP, \"NetMisc\" );\r\n\r\n\t\tsp_instance->PopContext();\r\n\t}\r\n}\r\n\r\nvoid Manager::DeleteNetMiscHeap()\r\n{\r\n\tif( mp_net_misc_region )\r\n\t{\r\n\t\tRemoveHeap( mp_net_misc_heap );\r\n\t\tdelete mp_net_misc_region;\r\n\t\tmp_net_misc_region = NULL;\r\n\t}\r\n}\r\n\r\nvoid Manager::InitInternetHeap()\r\n{\r\n\tif( mp_internet_region == NULL )\r\n\t{\r\n\r\n\t\t//#ifndef\t__NOPT_ASSERT__\r\n\t\t#if\t1\t\t// always allocate internet heap normally\r\n\t\t// normally the internet heap just goes on the top down heap\r\n\t\tsp_instance->PushContext( sp_instance->mp_bot_heap );\r\n\t\t#else\r\n\t\t// but with assertions there is not enough room, so put it on the debug heap\r\n\t\tif (Config::GotExtraMemory())\r\n\t\t{\r\n\t\t\tsp_instance->PushContext( sp_instance->mp_debug_heap );\t\t\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// running on a regular PS2, allow them to try, but will probably fail later with out of memory\r\n\t\t\tsp_instance->PushContext( sp_instance->mp_bot_heap );\r\n\t\t}\r\n\t\t#endif\t\t\r\n\t\t\r\n\t\tmp_internet_region = new Mem::AllocRegion( (INTERNET_HEAP_SIZE) );\t\r\n\t\tmp_internet_top_heap = CreateHeap( mp_internet_region, Mem::Allocator::vTOP_DOWN, \"InternetTopDown\" );\r\n\t\tmp_internet_bottom_heap = CreateHeap( mp_internet_region, Mem::Allocator::vBOTTOM_UP, \"InternetBottomUp\" );\r\n\r\n\t\tsp_instance->PopContext();\r\n\t}\r\n}\r\n\r\nvoid Manager::DeleteInternetHeap()\r\n{\r\n\tif( mp_internet_region )\r\n\t{\r\n\t\tRemoveHeap( mp_internet_top_heap );\r\n\t\tRemoveHeap( mp_internet_bottom_heap );\r\n\t\tdelete mp_internet_region;\r\n\t\tmp_internet_region = NULL;\r\n\t}\r\n}\r\n\r\nvoid Manager::InitCutsceneHeap( int heap_size )\r\n{\r\n\t// Note that it will create the cutscene heap on the current mem context...\r\n\r\n\tif ( mp_cutscene_region == NULL )\r\n\t{\r\n\t\t// put it on the top-down heap, because it's used only temporarily\r\n//\t\tsp_instance->PushContext( sp_instance->mp_top_heap );\r\n\t\t\r\n\t\tmp_cutscene_region = new Mem::AllocRegion( heap_size );\r\n\r\n\t\tDbg_MsgAssert( mp_cutscene_bottom_heap == NULL, ( \"CutsceneBottomUpHeap already exists\" ) );\r\n\t\tmp_cutscene_bottom_heap = CreateHeap( mp_cutscene_region, Mem::Allocator::vBOTTOM_UP, \"CutsceneBottomUp\" );\r\n\t\t\r\n\t\tDbg_MsgAssert( mp_cutscene_top_heap == NULL, ( \"CutsceneTopDownHeap already exists\" ) );\r\n\t\tmp_cutscene_top_heap = CreateHeap( mp_cutscene_region, Mem::Allocator::vTOP_DOWN, \"CutsceneTopDown\" );\r\n\r\n//\t\tsp_instance->PopContext();\r\n\t}\r\n}\r\n\r\nvoid Manager::DeleteCutsceneHeap()\r\n{\r\n\tif ( mp_cutscene_region )\r\n\t{\r\n\t\tRemoveHeap( mp_cutscene_bottom_heap );\r\n\t\tmp_cutscene_bottom_heap = NULL;\r\n\t\t\r\n\t\tRemoveHeap( mp_cutscene_top_heap );\r\n\t\tmp_cutscene_top_heap = NULL;\r\n\r\n\t\tdelete mp_cutscene_region;\r\n\t\tmp_cutscene_region = NULL;\r\n\t}\r\n}\r\n\r\n\r\nvoid Manager::InitDebugHeap()\r\n{\r\n\t#ifdef\t__PLAT_NGPS__\r\n\t// The Debug heap is allocated directly from debug memory (>32MB on PS2)\r\n\t// as such, it should only ever be used on the TOOL (T10K) debug stations, or equivalents on other platforms \r\n\tmp_debug_region \t= new ((void*)s_debug_region_buffer) Region( nAlignUp( _debug_heap_start ), nAlignDown( _debug_heap_start+DEBUG_HEAP_SIZE ) );\r\n\tmp_debug_heap = CreateHeap( mp_debug_region, Mem::Allocator::vBOTTOM_UP, \"debug\" );\r\n\t#endif\r\n}\r\n\r\nvoid Manager::InitSkaterHeaps(int players)\r\n{\r\n\tprintf (\"Init Skater Heaps\\n\");\r\n\t   \r\n\t// some game modes specify 8 players, however 4 of those\r\n\t// are observers ??? \r\n\t// anyway, for now, just don't allow them to create more heaps than the max\r\n\t// it will assert later if you try to access a heap that has not been created\t\t\t\t\t\t\t   \r\n\tif (players > NUM_SKATER_HEAPS)\r\n\t{\r\n\t\tplayers = NUM_SKATER_HEAPS;\r\n\t}\r\n\t\r\n\t// Initialize the other skater heaps\r\n\tfor (int heap = NUM_PERM_SKATER_HEAPS; heap < players; heap++)\r\n\t{\r\n\t\tDbg_MsgAssert(!mp_skater_region[heap],( \"Skater region %d is still active!!!\\n\",heap));\r\n\t\tDbg_MsgAssert(!mp_skater_heap[heap],( \"Skater heap %d is still active!!!\\n\",heap));\r\n\t\tmp_skater_region[heap] = new Mem::AllocRegion( (SKATER_HEAP_SIZE) );\t\r\n\t\tprintf (\"EXTRA: allocated mp_skater_region at %p\\n\",mp_skater_region[heap]);\r\n\t\tmp_skater_heap[heap] = CreateHeap( mp_skater_region[heap], Mem::Allocator::vBOTTOM_UP, \"skaterX\" );\r\n\t\tprintf (\"EXTRA: Setup mp_skater_heap at %p\\n\",mp_skater_heap[heap]);\r\n\t\r\n\t\tDbg_MsgAssert(!mp_skater_geom_region[heap],( \"Skater geom region %d is still active!!!\\n\",heap));\r\n\t\tDbg_MsgAssert(!mp_skater_geom_heap[heap],( \"Skater geom heap %d is still active!!!\\n\",heap));\r\n\t\tmp_skater_geom_region[heap] = new Mem::AllocRegion( (SKATER_GEOM_HEAP_SIZE) );\t\r\n\t\tprintf (\"EXTRA: allocated mp_skater_region at %p\\n\",mp_skater_geom_region[heap]);\r\n\t\tmp_skater_geom_heap[heap] = CreateHeap( mp_skater_geom_region[heap], Mem::Allocator::vBOTTOM_UP, \"skaterGeomX\" );\r\n\t\tprintf (\"EXTRA: Setup mp_skater_geom_heap at %p\\n\",mp_skater_geom_heap[heap]);\r\n\t}\r\n\t\r\n\tprintf (\"END Init Skater Heaps\\n\");\r\n}\r\n\r\n// Delete the temporary skater heaps\r\nvoid Manager::DeleteSkaterHeaps()\r\n{\r\n\tfor (int i=NUM_PERM_SKATER_HEAPS;i<NUM_SKATER_HEAPS;i++)\r\n\t{\r\n\t\tif (mp_skater_region[i])\r\n\t\t{\t\t\r\n\t\t\tprintf (\"DELETING SKATER HEAP %d\\n\",i);\r\n\t\t\tRemoveHeap(mp_skater_heap[i]);\r\n\t\t\tdelete mp_skater_region[i];\r\n\t\t\tmp_skater_heap[i] = NULL;\r\n\t\t\tmp_skater_region[i] = NULL;\r\n\t\t}\r\n\r\n\t\tif (mp_skater_geom_region[i])\r\n\t\t{\r\n\t\t\tprintf (\"DELETING SKATER GEOM HEAP %d\\n\",i);\r\n\t\t\tRemoveHeap(mp_skater_geom_heap[i]);\r\n\t\t\tdelete mp_skater_geom_region[i];\r\n\t\t\tmp_skater_geom_heap[i] = NULL;\r\n\t\t\tmp_skater_geom_region[i] = NULL;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Manager::DeleteOtherHeaps()\r\n{\r\n\tRemoveHeap(mp_frontend_heap);\r\n\tdelete mp_frontend_region;\r\n\tRemoveHeap(mp_script_heap);\r\n\tdelete mp_script_region;\r\n\tRemoveHeap(mp_network_heap);\r\n\tdelete mp_network_region;\r\n#ifdef\t\t__USE_PROFILER__\r\n\tRemoveHeap(mp_profiler_heap);\r\n\tdelete mp_debug_region;\r\n#endif\t\r\n\tRemoveHeap(mp_skater_info_heap);\r\n\tdelete mp_skater_info_region;\r\n\t// Deallocate the permanent skater heap(s)\r\n\tfor (int i = 0; i< NUM_PERM_SKATER_HEAPS; i++)\r\n\t{\r\n\t\tRemoveHeap(mp_skater_heap[i]);\r\n        delete mp_skater_region[i];\r\n\t\t\r\n\t\tRemoveHeap(mp_skater_geom_heap[i]);\r\n\t\tdelete mp_skater_geom_region[i];\r\n\t}\r\n\tDeleteSkaterHeaps();\t\t// just in case we did some preemptive exit\r\n}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::sSetUp( void )\r\n{\r\n\t\r\n\r\n\tif ( !sp_instance )\r\n\t{\r\n\t\tsp_instance = new ((void*)s_manager_buffer) Manager;\r\n\r\n\t\tsp_instance->PushContext( sp_instance->mp_bot_heap );\t\t// make bottom-up heap default\r\n    \r\n//\t\tsp_instance->InitOtherHeaps();\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Warning( \"Already Initialized!\" );\r\n\t}\r\n}\r\n\r\n// K: Separated this out from sSetUp because this needs to be called from main(), after\r\n// the config manager has initialised, because it must only be called if extra memory is\r\n// available, and we only know that after Config::Init has been called.\r\n// sSetUp is called from pre_main, and the config manager cannot be called from there \r\n// because it needs the command line args.\r\nvoid Manager::sSetUpDebugHeap( void )\r\n{\r\n\tif ( sp_instance )\r\n\t{\r\n\t\tsp_instance->InitDebugHeap();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(0,(\"Called sSetUpDebugHeap when mem manager not initialized!\"));\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::sCloseDown( void )\r\n{\r\n\t\r\n\r\n\tif ( sp_instance )\r\n\t{\r\n\t\t\r\n#ifndef __PLAT_WN32__\r\n\t\tsp_instance->DeleteOtherHeaps();\t\t\t\t\t\t\t\r\n#endif\t\t\r\n\t\tsp_instance->PopContext();\r\n\r\n\t\tsp_instance->~Manager();\r\n\t\tsp_instance = NULL;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_Warning( \"Not Initialized!\" );\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n\r\nvoid Manager::RegisterPcsMemMan( Pcs::Manager* pReg ) \r\n{\r\n\t\r\n\r\n\tDbg_Assert( mp_process_man == NULL );\t// should not initialize twice.\r\n\r\n\tmp_process_man = pReg;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCNamedHeapInfo* Manager::find_named_heap_info( uint32 name )\r\n{\r\n\tfor ( int i = 0; i < NUM_NAMED_HEAPS; i++ )\r\n\t{\r\n\t\tif ( m_named_heap_info[i].m_used && m_named_heap_info[i].m_name == name )\r\n\t\t{\r\n\t\t\treturn &m_named_heap_info[i];\r\n\t\t}\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nHeap* Manager::NamedHeap( uint32 name, bool assertOnFail )\r\n{\r\n\tCNamedHeapInfo* pInfo = find_named_heap_info( name );\r\n\r\n\tif ( pInfo )\r\n\t{\r\n\t\treturn pInfo->mp_heap;\r\n\t}\r\n\t\t\r\n\tDbg_MsgAssert( !assertOnFail, ( \"Couldn't find named heap %08x\", name ) );\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::InitNamedHeap( uint32 name, uint32 size, const char* pHeapName )\r\n{\r\n\tCNamedHeapInfo* pNamedHeapInfo = NULL;\r\n\r\n\tfor ( int i = 0; i < NUM_NAMED_HEAPS; i++ )\r\n\t{\r\n\t\tif ( !m_named_heap_info[i].m_used )\r\n\t\t{\r\n\t\t\tpNamedHeapInfo = &m_named_heap_info[i];\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tDbg_MsgAssert( pNamedHeapInfo, ( \"No more free named heaps (Increase NUM_NAMED_HEAPS from %d)!\", NUM_NAMED_HEAPS ) );\r\n\r\n\t// set the correct name\r\n\tpNamedHeapInfo->m_name = name;\r\n\tDbg_MsgAssert( strlen(pHeapName) < CNamedHeapInfo::vMAX_HEAP_NAME_LEN, ( \"Heap name %s is too long\", pHeapName ) );\r\n\tstrcpy( pNamedHeapInfo->mp_heap_name, pHeapName );\r\n\t\r\n\tDbg_MsgAssert(!pNamedHeapInfo->mp_region, ( \"Named region is still active\" ) );\r\n\tpNamedHeapInfo->mp_region =\tnew Mem::AllocRegion( size );\t\r\n\tDbg_Message( \"EXTRA: Allocated pNamedHeapInfo->mp_region at %p\", pNamedHeapInfo->mp_region );\r\n\t\r\n\tDbg_MsgAssert(!pNamedHeapInfo->mp_heap, (\"Named heap is still active\"));\r\n\tpNamedHeapInfo->mp_heap = CreateHeap( pNamedHeapInfo->mp_region, \r\n\t\t\t\t\t\t\t\t\t\t  Mem::Allocator::vBOTTOM_UP, \r\n\t\t\t\t\t\t\t\t\t\t  pNamedHeapInfo->mp_heap_name );\r\n\tDbg_Message( \"EXTRA: Setup pNamedHeapInfo->mp_region at %p\", pNamedHeapInfo->mp_heap );\r\n\r\n\tpNamedHeapInfo->m_used = true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Manager::DeleteNamedHeap( uint32 name, bool assertOnFail )\r\n{\r\n\tCNamedHeapInfo* pInfo = find_named_heap_info( name );\r\n\r\n\tif ( pInfo )\r\n\t{\r\n\t\tDbg_Message( \"Deleting named heap %s\", pInfo->mp_heap_name );\r\n\t\tDbg_Assert( pInfo->mp_region );\r\n\t\tDbg_Assert( pInfo->mp_heap );\r\n\t\tRemoveHeap( pInfo->mp_heap );\r\n\t\tdelete pInfo->mp_region;\r\n\t\tpInfo->mp_region = NULL;\r\n\t\tpInfo->mp_heap = NULL;\r\n\t\tpInfo->m_name = 0;\r\n\t\tpInfo->m_used = false;\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert( !assertOnFail, ( \"Couldn't find named heap %08x to delete\", name ) );\r\n\t}\r\n\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid*\tMalloc( size_t size )\r\n{\r\n\t\r\n\t\r\n\tvoid *v =  Mem::Manager::sHandle().New( size, true );\r\n\t\r\n\treturn v;\r\n}\r\n\r\nint\t\tAvailable()\r\n{\r\n\treturn Mem::Manager::sHandle().Available(); \r\n}\r\n\r\nvoid* ReallocateDown( size_t newSize, void *pOld )\r\n{\r\n\treturn Mem::Manager::sHandle().ReallocateDown(newSize,pOld);\r\n}\r\n\r\nvoid* ReallocateUp( size_t newSize, void *pOld )\r\n{\r\n\treturn Mem::Manager::sHandle().ReallocateUp(newSize,pOld);\r\n}\r\n\r\nvoid* ReallocateShrink( size_t newSize, void *pOld )\r\n{\r\n\treturn Mem::Manager::sHandle().ReallocateShrink(newSize,pOld);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tFree( void* pAddr )\r\n{\r\n\t\r\n\r\n\tMem::Manager::sHandle().Delete( pAddr );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tValid( void* pAddr )\r\n{\t\r\n\treturn Mem::Manager::sHandle().Valid( pAddr );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nsize_t\tGetAllocSize( void* pAddr )\r\n{\r\n\treturn Mem::Manager::sHandle().GetAllocSize( pAddr );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid*\tRealloc( void* mem, size_t newSize )\r\n{\r\n\t/* should really add resize functions to do this more efficiently */\r\n\r\n\tvoid* ptr = NULL;\r\n\r\n\tif ( newSize )\r\n\t{   \r\n//\t\tMem::Manager::sHandle().PushContext(Manager::sHandle().TopDownHeap());\r\n\t\tptr = Mem::Manager::sHandle().New( newSize, true );\r\n//\t\tMem::Manager::sHandle().PopContext();\t\r\n\t}\r\n\r\n\tif ( mem )\r\n\t{\r\n\t\tif ( ptr )\r\n\t\t{\r\n\t\t\tmemmove ( ptr, mem, newSize ); \r\n\t\t}\r\n\r\n\t\tMem::Manager::sHandle().Delete( mem );\r\n\t}\r\n\t\r\n\treturn ptr;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid*\tCalloc( size_t numObj, size_t sizeObj )\r\n{\r\n\t\r\n\t\r\n\treturn Mem::Manager::sHandle().New(( numObj * sizeObj ), true );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// enable multiple threads to access the memory manager at once\r\nvoid\tSetThreadSafe(bool safe)\r\n{\r\n\t#ifdef\t__PLAT_NGPS__\r\n\t\ts_use_semaphore = safe;\t\r\n\t#endif\r\n}\r\n\r\nbool\tIsThreadSafe( void )\r\n{\r\n#ifdef\t__PLAT_NGPS__\r\n\treturn s_use_semaphore;\r\n#else\r\n\treturn false;\r\n#endif\r\n}\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\r\n#define\tMAX_PROFILE_NAME 64\r\n#define\tMAX_NUM_PROFILES  5000\r\n#define\tMAX_LEVELS\t  32\r\n\r\nclass\tCMemProfile\r\n{\t\t  \r\npublic:\r\n\tchar\tm_type[MAX_PROFILE_NAME];\r\n\tint\t\tm_blocks;\r\n\tint\t\tm_size;\r\n\tint\t\tm_depth;\r\n\tint\t\tm_count;\t\t// number of pushes of same nam, same depth context\r\n\tint\t\tm_link;\t\t\t// link forward to profile that has merged with this profile\r\n};\r\n\r\n\r\n//static\t\tCMemProfile\t\t\t\ts_profile_list[MAX_NUM_PROFILES];\t\t// a flat array of all profiles\r\nstatic\t\tCMemProfile\t\t\t*\ts_profile_list;\t\t// a dynamically allocated flat array of all profiles\r\n\t\r\nstatic\t\tCMemProfile\t*\t\t\ts_profile_stack[MAX_LEVELS];\t\t// stack of pushed profiles \r\n\t\r\nstatic\t\tint\t\t\t\t\t\ts_profile_count = 0;\r\n\t\r\nstatic\t\tCMemProfile*\t\t\tsp_current_profile = NULL;\t\t\t\t\t\t\t// current entry in profile list (will need to pop back....\r\nstatic\t\tint\t\t\t\t\t\ts_profile_stack_depth = 0;\t\t\t\t\t\t// depth in stack (index into m_profile_stack[])\r\nstatic\t\tint\t\t\t\t\t\ts_next_profile = 0;\t\t\t\t\t\t\t\t// index into array\r\n\r\n//static \t\tint\t\t\t\t\t\ts_launched = false;\t\t// true after we've laucnhed the level once\r\n\r\nstatic\t\tbool\t\t\t\t\ts_active = true;\r\n\r\nvoid\tPushMemProfile(char *p_type)\r\n{\r\n\tif( s_active )\r\n\t{\r\n\t\r\n\t\tif (!s_profile_list)\r\n\t\t{\r\n\t\t\tif (Config::GotExtraMemory())\r\n\t\t\t{\r\n\t\t\t\tMem::Manager::sHandle().PushContext(Manager::sHandle().DebugHeap());\r\n\t\t\t\ts_profile_list = (CMemProfile *)Mem::Malloc(MAX_NUM_PROFILES *sizeof(CMemProfile));\r\n\t\t\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ts_active = false;\t\t\t// no extra memory, or maybe it's an X-Box....\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif (s_next_profile >= MAX_NUM_PROFILES)\r\n\t\t{\r\n\t\t\ts_active = false;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n/*\t\t\r\n\t\tif (!strcmp(\"LaunchLevel\",p_type))\r\n\t\t{\r\n\t\t\tif (s_launched)\r\n\t\t\t{\r\n\t\t\t\ts_active = false;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\ts_launched = true;\r\n\t\t}\r\n*/\r\n\t\t\t\t\t\t\t  \r\n\t\t// if we have a current profile, then push it\r\n\t\tif (sp_current_profile)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(s_profile_stack_depth < MAX_LEVELS,(\"mem profile stack overflow, unmatched push?\"));\r\n\t\t\ts_profile_stack[s_profile_stack_depth++] = sp_current_profile;\r\n\t\t}\r\n\t\t\r\n\t\t// get a new profile from the list\r\n\t\tDbg_MsgAssert(s_next_profile < MAX_NUM_PROFILES,(\"mem profile heap overflow, too many pushes\"));\r\n\t\tsp_current_profile = &s_profile_list[s_next_profile++];\r\n\r\n\r\n\r\n\r\n\t\t// just copy over the memory containing the name\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\t\tchar *p = &(sp_current_profile->m_type[0]);\r\n\t\tchar *q = (char*) p_type;\r\n\t\tfor (int i=0;i<MAX_PROFILE_NAME;i++)\r\n\t\t{\r\n\t\t\t*p++ = *q++;\t\t\t\r\n\t\t}\r\n\t\t// and set the counters to zero\r\n\t\tsp_current_profile->m_blocks = 0;\r\n\t\tsp_current_profile->m_size = 0;\r\n\t\tsp_current_profile->m_depth = s_profile_stack_depth;\r\n\t\tsp_current_profile->m_count = 1;\r\n\t\tsp_current_profile->m_link = 0;\r\n\r\n\t\t// Then, search back through the list to see if there \r\n\t\t// are any entries att he same level that have this same string\r\n\t\t// if so, then zero the old instance, and add the size and count to this one\r\n\t\t// there should only be one, as any other one would already be zeroed\r\n\t\tint\tcheck = s_next_profile-2;\r\n\t\twhile (check>0\r\n\t\t\t\t&& s_profile_list[check].m_depth == s_profile_stack_depth)\r\n\t\t{\r\n\t\t\tif (s_profile_list[check].m_depth == s_profile_stack_depth)\r\n\t\t\t{\r\n\t\t\t\t// same depth\r\n\t\t\t\tif (strcmp(s_profile_list[check].m_type,p_type) == 0)\r\n\t\t\t\t{\r\n\t\t\t\t\t// same string, so bring this one forward to add to this\r\n\t\t\t\t\tsp_current_profile->m_blocks += s_profile_list[check].m_blocks;\r\n\t\t\t\t\tsp_current_profile->m_size += s_profile_list[check].m_size;\r\n\t\t\t\t\tsp_current_profile->m_count += s_profile_list[check].m_count;\r\n\t\t\t\t\t// and zero out the old one\t\t\t\t\t\r\n\t\t\t\t\ts_profile_list[check].m_blocks = 0;\r\n\t\t\t\t\ts_profile_list[check].m_size = 0;\r\n\t\t\t\t\t// Patch in the index of the new profile,\r\n\t\t\t\t\t// so late deletions can be accounted for\r\n\t\t\t\t\ts_profile_list[check].m_link = s_profile_stack_depth - 1;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tcheck--;\r\n\t\t}\r\n\r\n\r\n\t}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n\r\nvoid\tPopMemProfile()\r\n{\r\n\tif( s_active)\r\n\t{\r\n\t\tDbg_MsgAssert(sp_current_profile,(\"Popped one more memory profile than we pushed\"));\r\n\r\n\t\t// set time on the current profile\t\t\r\n//\t\tsp_current_profile->m_end_time = Tmr::GetTimeInUSeconds();\r\n\t\t\r\n\t\tif ( ! s_profile_stack_depth)\r\n\t\t{\r\n\t\t\t// nothing left on stack, so set current profile to NULL\r\n\t\t\tsp_current_profile = NULL;\r\n\t\t\t// update the count of valid profiles\r\n\t\t\ts_profile_count = s_next_profile;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// get the last profile pushed on the stack\r\n\t\t\tsp_current_profile = s_profile_stack[--s_profile_stack_depth]; \r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n// given an index in the the mem profile list\r\n// then get the total size of all allocations\r\n// at this level, or below\r\n// up the next entry at the same depth, or the end of the list\r\nint\t\ttotal_size(int n)\r\n{\r\n\t\r\n\tint size = s_profile_list[n].m_size;\r\n\tint depth = s_profile_list[n].m_depth;\r\n\tn++;\r\n\twhile (n < s_next_profile && s_profile_list[n].m_depth > depth)\r\n\t{\r\n\t\tsize += s_profile_list[n].m_size;\r\n\t\tn++;\r\n\t}\r\n\treturn size;\r\n\t\t\t\t\t\r\n}\r\n\r\n#ifndef __PLAT_WN32__\r\n// dump the memory profile in a tree format, like\r\n//\r\n//  level stuff     100000\r\n//     peds           5000\r\n//     cars          23000\r\n//    other          72000\r\n//  skater stuff    ...... \r\nvoid\tDumpMemProfile(int level, char *p_type)\r\n{\r\n\tchar buf[512];\r\n\tif( s_active )\r\n\t{\r\n\t\r\n\r\n\r\n\t\tprintf (\"\\nDumping Memory Profile\\n\");\r\n\t\tprintf (\"There are %d mem profile contexts\\n\",s_next_profile);\r\n\t\tfor (int i=0;i<s_next_profile;i++)\r\n\t\t{\r\n\t\t\tif (s_profile_list[i].m_depth <= level)\r\n\t\t\t{\r\n\t\t\t\tif (total_size(i))\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf (buf,\"%2d: \",s_profile_list[i].m_depth);\r\n\t\t\t\t\tdump_printf(buf);\r\n\t\t\t\t\tfor (int tab = 0;tab < s_profile_list[i].m_depth;tab++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsprintf(buf,\"   \");\r\n\t\t\t\t\t\tdump_printf(buf);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsprintf (buf,\">%10s____\",Str::PrintThousands(total_size(i)));\r\n\t\t\t\t\tdump_printf(buf);\r\n\t\t\t\t\tif (s_profile_list[i].m_count == 1)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsprintf (buf,\"%s\\n\",s_profile_list[i].m_type);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsprintf (buf,\"%s (%d) (avg: %s)\\n\",s_profile_list[i].m_type,s_profile_list[i].m_count,Str::PrintThousands(total_size(i)/s_profile_list[i].m_count));\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdump_printf(buf);\r\n\t\t\t\t\tif (s_profile_list[i].m_depth < level && s_profile_list[i].m_size && total_size(i) != s_profile_list[i].m_size)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsprintf (buf,\"%2d: \",s_profile_list[i].m_depth+1);\r\n\t\t\t\t\t\tdump_printf(buf);\r\n\t\t\t\t\t\tfor (int tab2 = 0;tab2 < s_profile_list[i].m_depth+1;tab2++)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tsprintf(buf,\"   \");\r\n\t\t\t\t\t\t\tdump_printf(buf);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tsprintf (buf,\">%10s____\",Str::PrintThousands(s_profile_list[i].m_size));\r\n\t\t\t\t\t\tdump_printf(buf);\r\n\t\t\t\t\t\tsprintf (buf,\"Untracked %s\\n\",s_profile_list[i].m_type);\t\t\t\r\n\t\t\t\t\t\tdump_printf(buf);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tprintf (\"Mem Profiler not active, probably overflowed, try restarting...\\n\");\r\n\t}\r\n}\r\n#endif// __PLAT_WN32__\r\nvoid\tAllocMemProfile(Allocator::BlockHeader* p_block)\r\n{\r\n\tif( s_active )\r\n\t{\r\n\t\tif (sp_current_profile)\r\n\t\t{\r\n\t\t\tsp_current_profile->m_blocks++;\r\n\t\t\t\r\n\t\t\t// If it's on the debug heap, then set size to zero to avoid confusion\r\n\t\t\tif (Mem::Manager::sHandle().GetContextAllocator() != Mem::Manager::sHandle().DebugHeap())\r\n\t\t\t{\r\n\t\t\t\tsp_current_profile->m_size += p_block->mSize;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tp_block->mp_profile = sp_current_profile;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid\tFreeMemProfile(Allocator::BlockHeader* p_block)\r\n{\r\n\tif( s_active )\r\n\t{\r\n\t\t\r\n\t\tCMemProfile\t*\tp_profile  = p_block->mp_profile;\t\t\t\t\t\t  \r\n\t\tif (p_profile)\r\n\t\t{\r\n//\t\t\tDbg_MsgAssert(p_profile->m_blocks,(\"mutli-block freed out of context\"));\r\n\t\t\t// Skip over any that have been combined, until we find the final combined block\r\n\t\t\twhile (p_profile->m_link != 0)\r\n\t\t\t{\r\n\t\t\t\tp_profile = &s_profile_list[p_profile->m_link];\r\n\t\t\t}\r\n\t\t\tp_profile->m_blocks--;\r\n\t\t\tp_profile->m_size -= p_block->mSize;\r\n\t\t\tp_profile = NULL;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n#else\r\n\r\nvoid\tPushMemProfile(char *p_type)\r\n{\r\n}\r\n\r\nvoid\tPopMemProfile()\r\n{\r\n}\r\n\r\n#ifndef __PLAT_WN32__\r\nvoid\tDumpMemProfile(int level, char *p_type)\r\n{\r\n}\r\n#endif// __PLAT_WN32__\r\n\r\nvoid\tAllocMemProfile(Allocator::BlockHeader* p_block)\r\n{\r\n}\r\n\r\nvoid\tFreeMemProfile(Allocator::BlockHeader* p_block)\r\n{\r\n}\r\n\r\n#endif __NOPT_ASSERT__\r\n\r\n\r\n} // namespace Mem\r\n\r\n"
  },
  {
    "path": "Code/Sys/Mem/memman.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory Manager (Mem)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/mem/memman.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_MEM_MEMMAN_H\r\n#define\t__SYS_MEM_MEMMAN_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/singleton.h>\r\n#include <core/list.h>\r\n#include <sys\\mem\\region.h>\r\n#include \"heap.h\"\r\n#include \"alloc.h\"\r\n//#ifndef __PLAT_XBOX__\r\n\r\n#ifndef\t__SYS_MEM_MEMPTR_H\r\n#\tinclude \"memptr.h\"\r\n#endif\r\n//#endif\r\n#include \"handle.h\"\r\n\r\n#if 0\r\n#ifdef __PLAT_WN32__\r\n#include \"mem/wn32/p_memman.h\"\r\n#else\r\n#ifdef __PLAT_NGPS__\r\n#include \"mem/ngps/p_memman.h\"\r\n#else\r\n#ifdef __PLAT_NGC__\r\n#include \"mem/ngc/p_memman.h\"\r\n#else\r\n#error Unsupported Platform\r\n#endif\r\n#endif\r\n#endif\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// redefine the standard memory library functions, so they give us errors\r\n\r\n\r\n#define\tNUM_PERM_SKATER_HEAPS\t1\r\n#define\tNUM_SKATER_HEAPS\t\t8\r\n#define NUM_NAMED_HEAPS\t\t\t4\r\n\r\n#define\t\tDEBUG_HEAP_SIZE\t\t\t\t32767*1024\t\t// 1K short of 32MB\r\n\r\n\t\t\r\nnamespace Pcs\r\n{\r\n\tclass Manager;\r\n}\r\n\r\nnamespace Mem\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass CNamedHeapInfo\r\n{\r\npublic:\r\n\tenum\r\n\t{\r\n\t\tvMAX_HEAP_NAME_LEN = 128\r\n\t};\r\n\r\n\tCNamedHeapInfo()\r\n\t{\r\n\t\tmp_region = NULL;\r\n\t\tmp_heap = NULL;\r\n\t\tm_name = 0;\r\n\t\tm_used = false;\r\n\t}\r\n\r\npublic:\r\n\tRegion*\t\tmp_region;\r\n\tHeap*\t\tmp_heap;\r\n\tuint32\t\tm_name;\r\n\tchar\t\tmp_heap_name[vMAX_HEAP_NAME_LEN];\r\n\tbool\t\tm_used;\r\n};\r\n\r\nclass Manager : public Spt::Class\t\t\t\r\n{\r\n\t\r\npublic:\r\n\r\n\tenum\r\n\t{\r\n\t\tvMAX_CONTEXT = 16,\r\n\t\tvMAX_HEAPS = 32\r\n\t};\r\n\r\n\tvoid\t\t\t\t\t\tPushContext( Allocator* alloc );\r\n\tvoid\t\t\t\t\t\tPopContext( void );\r\n\r\n\tvoid*\t\t\t\t\t\tNew( size_t size, bool assert_on_fail = true, Allocator* pAlloc = NULL );\r\n\tint\t\t\t\t\t\t\tAvailable();\r\n\tvoid*\t\t\t\t\t\tReallocateDown( size_t newSize, void *pOld, Allocator* pAlloc = NULL );\r\n\tvoid*\t\t\t\t\t\tReallocateUp( size_t newSize, void *pOld, Allocator* pAlloc = NULL );\r\n\tvoid*\t\t\t\t\t\tReallocateShrink( size_t newSize, void *pOld, Allocator* pAlloc = NULL );\r\n\tvoid\t\t\t\t\t\tDelete( void* pAddr );\r\n\tbool\t\t\t\t\t\tValid( void* pAddr );\r\n\tsize_t\t\t\t\t\t\tGetAllocSize( void* pAddr );\r\n\t\t\t\t\t\t\t\t\r\n\tHeap*\t\t\t\t\t\tTopDownHeap( void ) \t\t{ return mp_top_heap; }\r\n\tHeap*\t\t\t\t\t\tBottomUpHeap( void )  \t\t{ return mp_bot_heap; }\r\n\tHeap*\t\t\t\t\t\tFrontEndHeap( void ) \t\t{ return mp_frontend_heap; }\r\n\tHeap*\t\t\t\t\t\tScriptHeap( void ) \t\t\t{ return mp_script_heap; }\r\n\tHeap*\t\t\t\t\t\tNetworkHeap( void ) \t\t{ return mp_network_heap; }\r\n\tHeap*\t\t\t\t\t\tNetMiscHeap( void ) \t\t{ return mp_net_misc_heap; }\r\n\tHeap*\t\t\t\t\t\tProfilerHeap( void ) \t\t{ return mp_profiler_heap; }\r\n\tHeap*\t\t\t\t\t\tDebugHeap( void ) \t\t\t{ return mp_debug_heap; }\r\n\tHeap*\t\t\t\t\t\tSkaterHeap( int n ) \t\t{ return mp_skater_heap[n]; }\r\n\tHeap*\t\t\t\t\t\tSkaterInfoHeap( ) \t\t\t{ return mp_skater_info_heap; }\r\n\tHeap*\t\t\t\t\t\tSkaterGeomHeap( int n ) \t{ return mp_skater_geom_heap[n]; }\r\n\tHeap*\t\t\t\t\t\tInternetTopDownHeap( void )\t{ return mp_internet_top_heap; }\r\n\tHeap*\t\t\t\t\t\tInternetBottomUpHeap( void ){ return mp_internet_bottom_heap; }\r\n    Heap*\t\t\t\t\t\tThemeHeap( void )           { return mp_theme_heap; }\r\n\tHeap*\t\t\t\t\t\tCutsceneTopDownHeap( void )\t{ return mp_cutscene_top_heap; }\r\n\tHeap*\t\t\t\t\t\tCutsceneBottomUpHeap( void ){ return mp_cutscene_bottom_heap; }\r\n#ifdef __PLAT_NGC__\r\n\tHeap*\t\t\t\t\t\tAudioHeap( void )\t\t\t{ return mp_audio_heap; }\r\n#endif\t\r\n\tHeap*\t\t\t\t\t\tNamedHeap( uint32 name, bool assertOnFail = true );\r\n\r\n\tvoid\t\t\t\t\t\tRegisterPcsMemMan( Pcs::Manager* );\r\n\r\n\t/* Global versions for all memory allocations */\r\n\tvoid\t\t\t\t\t\tPushMemoryMarker( uint32 uiID );\r\n\tvoid\t\t\t\t\t\tPopMemoryMarker( uint32 uiID );\r\n\r\n\tstatic void\t\t\t\t\tsSetUp( void );\r\n\tstatic void\t\t\t\t\tsSetUpDebugHeap( void );\r\n\t\r\n\tstatic void\t\t\t\t\tsCloseDown( void );\r\n\tstatic Manager&\t\t\t\tsHandle( void );\r\n\r\n\t\r\n\tvoid \t\t\t\t\t\tInitOtherHeaps();\r\n\tvoid \t\t\t\t\t\tDeleteOtherHeaps();\r\n\r\n\tvoid\t\t\t\t\t\tInitInternetHeap();\r\n\tvoid\t\t\t\t\t\tDeleteInternetHeap();\r\n\r\n\tvoid\t\t\t\t\t\tInitNetMiscHeap();\r\n\tvoid\t\t\t\t\t\tDeleteNetMiscHeap();\r\n\r\n\tvoid\t\t\t\t\t\tInitCutsceneHeap(int heap_size);\r\n\tvoid\t\t\t\t\t\tDeleteCutsceneHeap();\r\n\r\n\tvoid\t\t\t\t\t\tInitDebugHeap();\r\n\r\n\tvoid \t\t\t\t\t\tInitSkaterHeaps(int players);\r\n\tvoid \t\t\t\t\t\tDeleteSkaterHeaps();\r\n\r\n\tvoid\t\t\t\t\t\tInitNamedHeap(uint32 name, uint32 size, const char* pHeapName);\r\n\tbool\t\t\t\t\t\tDeleteNamedHeap(uint32 name, bool assertOnFail = true);\r\n\t\r\n\tconst char*\t\t\t\t\tGetHeapName( uint32 whichHeap );\r\n\tHeap *\t\t\t\t\t\tGetHeap( uint32 whichHeap );\r\n\r\n\tHeap *\t\t\t\t\t\tCreateHeap( Region* region, Mem::Allocator::Direction dir /*= Mem::Allocator::vBOTTOM_UP*/, char* p_name );//= \"unknown heap\" );\r\n\tvoid\t\t\t\t\t\tRemoveHeap( Heap * pHeap); \r\n\tHeap *\t\t\t\t\t\tFirstHeap();\r\n\tHeap *\t\t\t\t\t\tNextHeap(Heap * pHeap);\r\n\t\r\n\r\n//\tint \t\t\t\t\t\tGetContextNumber();\r\n\tchar *\t\t\t\t\t\tGetContextName();\r\n\tAllocator::Direction\t\tGetContextDirection();\r\n\tAllocator*\t\t\t\t\tGetContextAllocator();\r\n\r\n\r\n\t\t\t\t\t\t\t\t~Manager( void );\r\nprivate :\r\n\t\t\t\t\t\t\t\tManager( void );\t\t\t\t\t\t\t\t   \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\tMem::Heap *\t\t\t\t\tm_heap_list[vMAX_HEAPS]; \r\n\tint\t\t\t\t\t\t\tm_num_heaps;   \t\t\t\t\t\t\t\r\n\r\n\tstatic char \t\t\t\ts_manager_buffer[];\r\n\tstatic char \t\t\t\ts_region_buffer[];\r\n\tstatic char \t\t\t\ts_debug_region_buffer[];\r\n\tstatic char \t\t\t\ts_script_region_buffer[];\r\n\tstatic char \t\t\t\ts_profiler_region_buffer[];\r\n\tstatic char \t\t\t\ts_debug_heap_buffer[];\r\n\tstatic char \t\t\t\ts_top_heap_buffer[];\r\n\tstatic char \t\t\t\ts_bot_heap_buffer[];\r\n\tstatic bool\t\t\t\t\ts_initialized;\r\n\tstatic Manager*\t\t\t\tsp_instance;\r\n\t\t\r\n\tclass MemManContext\r\n\t{\r\n\t\r\n\t\tfriend class Manager;\r\n\t\r\n\tprivate:\r\n\t\tAllocator*\t\t\t\t\t\tmp_alloc;\r\n\t};\r\n\r\n\r\n\tPtr< MemManContext > \t\tmp_context;\r\n\r\n\t// Mick: Contexts are now statically allocated off this \r\n\t// array, rather than off the heap, as that was causing fragmentation\r\n\t// in rare but crash-worthy circumstances\t\t\t\r\n\tMemManContext\t\t\t\tm_contexts[vMAX_CONTEXT];\r\n\tint\t\t\t\t\t\t\tm_pushed_context_count;\r\n\r\n\r\n\tRegion*\t\t\t\t\t\tmp_region;\r\n\tHeap*\t\t\t\t\t\tmp_top_heap;\r\n\tHeap*\t\t\t\t\t\tmp_bot_heap;\r\n\t\r\n\tRegion*\t\t\t\t\t\tmp_frontend_region;\r\n\tHeap*\t\t\t\t\t\tmp_frontend_heap;\r\n\r\n\tRegion*\t\t\t\t\t\tmp_script_region;\r\n\tHeap*\t\t\t\t\t\tmp_script_heap;\r\n\r\n\tRegion*\t\t\t\t\t\tmp_network_region;\r\n\tHeap*\t\t\t\t\t\tmp_network_heap;\r\n\r\n\tRegion*\t\t\t\t\t\tmp_net_misc_region;\r\n\tHeap*\t\t\t\t\t\tmp_net_misc_heap;\r\n\r\n\tRegion*\t\t\t\t\t\tmp_internet_region;\r\n\tHeap*\t\t\t\t\t\tmp_internet_top_heap;\r\n\tHeap*\t\t\t\t\t\tmp_internet_bottom_heap;\r\n\r\n\tRegion*\t\t\t\t\t\tmp_cutscene_region;\r\n\tHeap*\t\t\t\t\t\tmp_cutscene_top_heap;\r\n\tHeap*\t\t\t\t\t\tmp_cutscene_bottom_heap;\r\n\r\n#ifdef __PLAT_NGC__\r\n\tRegion*\t\t\t\t\t\tmp_audio_region;\r\n\tHeap*\t\t\t\t\t\tmp_audio_heap;\r\n#endif\t\t// __PLAT_NGC__\r\n\r\n\tRegion*\t\t\t\t\t\tmp_debug_region;\r\n\tHeap*\t\t\t\t\t\tmp_debug_heap;\r\n\r\n\tRegion*\t\t\t\t\t\tmp_profiler_region;\r\n\tHeap*\t\t\t\t\t\tmp_profiler_heap;\r\n\r\n\tRegion*\t\t\t\t\t\tmp_skater_region[NUM_SKATER_HEAPS];\r\n\tHeap*\t\t\t\t\t\tmp_skater_heap[NUM_SKATER_HEAPS];\r\n\t\r\n\tRegion*\t\t\t\t\t\tmp_skater_geom_region[NUM_SKATER_HEAPS];\r\n\tHeap*\t\t\t\t\t\tmp_skater_geom_heap[NUM_SKATER_HEAPS];\r\n\r\n\tCNamedHeapInfo\t\t\t\tm_named_heap_info[NUM_NAMED_HEAPS];\r\n\r\n\tRegion*\t\t\t\t\t\tmp_skater_info_region;\r\n\tHeap*\t\t\t\t\t\tmp_skater_info_heap;\r\n\r\n    Region*\t\t\t\t\t\tmp_theme_region;\r\n\tHeap*\t\t\t\t\t\tmp_theme_heap;\r\n\r\n\tPcs::Manager*\t\t\t\tmp_process_man;\r\n\tuint\t\t\t\t\t\tm_current_id;\r\n\r\nprotected:\r\n\tCNamedHeapInfo*\t\t\t\tfind_named_heap_info( uint32 name );\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern \"C\"\r\n{\r\n\r\nint\t\tAvailable();\r\nvoid*\tMalloc( size_t size );\r\nvoid\tFree( void* mem );\r\nbool\tValid( void* pAddr );\r\nsize_t\tGetAllocSize( void* pAddr );\r\nvoid*\tReallocateDown( size_t newSize, void *pOld );\r\nvoid*\tReallocateUp( size_t newSize, void *pOld );\r\nvoid*\tReallocateShrink( size_t newSize, void *pOld );\r\nvoid*\tRealloc( void* mem, size_t newSize );\r\nvoid*\tCalloc( size_t numObj, size_t sizeObj );\r\n}\r\n\r\nvoid\tPushMemProfile(char *p_type);\r\nvoid\tPopMemProfile();\r\nvoid\tDumpMemProfile(int level, char *p_type=NULL);\r\nvoid\tAllocMemProfile(Allocator::BlockHeader* p_block);\r\nvoid\tFreeMemProfile(Allocator::BlockHeader* p_block);\r\n\r\nvoid\tSetThreadSafe(bool safe);\r\nbool\tIsThreadSafe( void );\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline Manager&\tManager::sHandle( void )\r\n{\r\n\t\r\n\r\n\tDbg_AssertType( sp_instance, Manager );\r\n\r\n\treturn *sp_instance;\r\n}\r\n\r\n\r\n} // namespace Mem\r\n\r\n\r\n// Some debug functions\r\nbool dump_open(const char *name);\r\nvoid dump_printf(char *p);\r\nvoid dump_close();\r\nextern int dumping_printfs;\r\n\r\n\r\n\r\n#endif  // __SYS_MEM_MEMMAN_H\r\n"
  },
  {
    "path": "Code/Sys/Mem/memptr.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory Manager (Mem)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/mem/memptr.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_MEM_MEMPTR_H\r\n#define\t__SYS_MEM_MEMPTR_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#include <core/support.h>\r\n\r\n#include <core/support/support.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mem\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnTemplateBaseClass( _T, PtrToConst )\r\n{\r\n\t\r\npublic :\r\n\r\n\t\t\t\t\t\t\t\tPtrToConst( const _T* ptr = NULL );\r\n\t\t\t\t\t\t\t\t~PtrToConst( void );\r\n\r\n#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))\r\n\r\n\t\t\t\t\t\t\t\tPtrToConst( const PtrToConst< _T >& rhs );\r\n\t\tPtrToConst< _T >&\t\toperator= ( const PtrToConst< _T >& rhs );\r\n\r\n#else\r\n\r\n\ttemplate < class _NewT >\t\t\t\t\t\t                    \t\t// template copy contructor\r\n\t\t\t\t\t\t\t\tPtrToConst( const PtrToConst< _NewT >& rhs ); \t// needed to support inheritance correctly\r\n\r\n\ttemplate < class _NewT > \t\r\n\t\tPtrToConst< _T >&\t\toperator = ( const PtrToConst< _NewT >& rhs );\t// template assignment operator\r\n\r\n#endif\t\t\r\n\t\tPtrToConst< _T >&\t\toperator = ( const _T* ptr );\r\n\r\n\t\tPtrToConst< _T >&\t\toperator++ ( void ); \t\t\t\t\t\t\t// ++ptr   \r\n\t\tconst PtrToConst< _T >\toperator++ ( int ); \t\t\t\t\t\t\t// ptr++   \r\n\t\tPtrToConst< _T >&\t\toperator-- ( void );\t\t\t\t\t\t\t// --ptr\r\n\t\tconst PtrToConst< _T >\toperator-- ( int );\t\t\t\t\t\t\t\t// ptr--\r\n\t\tPtrToConst< _T >&\t\toperator+= ( int val );\r\n\t\tPtrToConst< _T >&\t\toperator-= ( int val );\r\n\r\n\t\tbool\t\t\t\t\toperator ! () const;                    \t\t// operator! - use to test for null\r\n\t\t\r\n\t\tconst _T&\t\t\t\toperator * () const;\r\n\t\tconst _T*\t\t\t\toperator -> () const;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\tconst _T*\t\t\t\tAddr( void ) const;\t\t\t\t\t\t\t\t// Retrieve 'dumb' pointer\r\n\t\t\r\nprotected :\r\n\r\n\t\tunion\r\n\t\t{\r\n\t\t\tconst\t_T*\t\tm_const_ptr;\r\n\t\t\t\t\t_T*\t\tm_ptr;\r\n\t\t};\r\n\t\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nnTemplateSubClass( _T, Ptr, PtrToConst< _T > )\r\n{\r\n\r\n\t\r\npublic :\r\n\t\t\t\t\t\t\t\tPtr( const _T* ptr = NULL );\r\n\t\t\t\t\t\t\t\t~Ptr( void );\r\n\r\n#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))\r\n\r\n\t\t\t\t\t\t\t\tPtr( const Ptr< _T >& rhs );\r\n\t\tPtr< _T >&\t\t\t\toperator= ( const Ptr< _T >& rhs );\r\n\r\n#else\r\n\ttemplate < class _NewT >\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t\t\tPtr( const Ptr< _NewT >& rhs );\t\r\n\r\n\ttemplate < class _NewT > \t\r\n\t\tPtr< _T >&\t\t\t\toperator = ( const Ptr< _NewT >& rhs );\t\t\t// template assignment operator\r\n#endif\t\t\r\n\t\tPtr< _T >&\t\t\t\toperator = ( const _T* ptr );\r\n\t\t_T&\t\t\t\t\t\toperator * ( void ) const; \r\n\t\t_T*\t\t\t\t\t\toperator -> ( void ) const;\r\n\t\t_T*\t\t\t\t\t\tAddr( void ) const;\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* PtrToConst< _T >                                               */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline   \r\nPtrToConst< _T >::PtrToConst< _T >( const _T* ptr ) \r\n: m_const_ptr ( ptr )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nPtrToConst< _T >::~PtrToConst( void )\r\n{\r\n\t\r\n\r\n}\r\n\r\n#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nPtrToConst< _T >::PtrToConst( const PtrToConst< _T >& rhs )\r\n: m_const_ptr ( rhs.Addr() )\r\n{\r\n\t\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nPtrToConst< _T >&\t\tPtrToConst< _T >::operator= ( const PtrToConst< _T >& rhs )\r\n{\r\n\t\r\n\t\r\n\tm_const_ptr = rhs.Addr();\r\n\treturn *this;\t\r\n}\r\n\r\n#else\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ntemplate < class _T > template < class _NewT > inline\r\nPtrToConst< _T >::PtrToConst< _T >( const PtrToConst< _NewT >& rhs )\r\n: m_const_ptr ( rhs.Addr() )\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert( false, ( \"Microsoft VC++ sucks - don't do this (yet)\" ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > template < class _NewT > inline\r\nPtrToConst< _T >&\t\tPtrToConst< _T >::operator = ( const PtrToConst< _NewT >& rhs ) \r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert( false, ( \"Microsoft VC++ sucks - don't do this (yet)\" ));\r\n\r\n\tm_const_ptr = rhs.Addr();\r\n\treturn *this;\t\r\n}\r\n\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nPtrToConst< _T >&\t\tPtrToConst< _T >::operator = ( const _T* ptr ) \r\n{\r\n\t\r\n\r\n\tm_const_ptr = ptr;\r\n\treturn *this;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nconst _T&\t\tPtrToConst< _T >::operator * ( void ) const \r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( m_const_ptr, _T );\r\n\t\r\n\treturn *m_const_ptr;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nPtrToConst< _T >&\tPtrToConst< _T >::operator+= ( int val )\r\n{\r\n\t\r\n\r\n\tm_const_ptr += val;\r\n\tDbg_AssertType( m_const_ptr, _T );\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nPtrToConst< _T >&\tPtrToConst< _T >::operator-= ( int val )\r\n{\r\n\t\r\n\r\n\tm_const_ptr -= val;\r\n\r\n\tDbg_AssertType( m_const_ptr, _T );\r\n\t\r\n\treturn *this;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nPtrToConst< _T >&\tPtrToConst< _T >::operator++ ( void )\r\n{\r\n\t\r\n\r\n\t*this += 1;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nconst PtrToConst< _T >\tPtrToConst< _T >::operator++ ( int )\r\n{\r\n\t\r\n\t\r\n\tPtrToConst< _T > old = *this;\r\n\r\n\t++(*this);\r\n\r\n\treturn old;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nPtrToConst< _T >&\tPtrToConst< _T >::operator-- ( void )\r\n{\r\n\t\r\n\r\n\tDbg_AssertType( m_const_ptr, _T );\r\n\r\n\t*this -= 1;\r\n\r\n\treturn *this;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nconst PtrToConst< _T >\tPtrToConst< _T >::operator-- ( int )\r\n{\r\n\t\r\n\r\n\tDbg_AssertType( m_const_ptr, _T );\r\n\t\r\n\tPtrToConst< _T > old = *this;\r\n\r\n\t--(*this);\r\n\r\n\treturn old;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nconst _T*\t\tPtrToConst< _T >::operator -> ( void ) const \r\n{\r\n\t\r\n\r\n\tDbg_AssertType( m_const_ptr, _T );\r\n\t\r\n\treturn m_const_ptr;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nbool\t\tPtrToConst< _T >::operator ! ( void ) const \r\n{\r\n\t\r\n\r\n\treturn ( m_const_ptr == NULL );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nconst _T*\t\tPtrToConst< _T >::Addr ( void ) const \r\n{\r\n\t\r\n\r\n\treturn m_const_ptr;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nconst PtrToConst< _T > operator+ ( const PtrToConst< _T >& lhs, int rhs )\r\n{\r\n\t\r\n\t\r\n\tPtrToConst< _T >\tret = lhs;\r\n\tret += rhs;\r\n\t\r\n\treturn ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nconst PtrToConst< _T > operator- ( const PtrToConst< _T >& lhs, int rhs )\r\n{\r\n\t\r\n\t\r\n\tPtrToConst< _T >\tret = lhs;\r\n\tret -= rhs;\r\n\t\r\n\treturn ret;\r\n}\r\n\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Ptr< _T >                                                      */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline   \r\nPtr< _T >::Ptr( const _T* ptr )\r\n: PtrToConst< _T >( ptr )\r\n{\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nPtr< _T >::~Ptr( void )\r\n{\r\n\t\r\n}\r\n\r\n#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nPtr< _T >::Ptr( const Ptr< _T >& rhs )\r\n: PtrToConst< _T >( rhs )\r\n{\r\n\t\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\t\r\nPtr< _T >&\t\tPtr< _T >::operator= ( const Ptr< _T >& rhs )\r\n{\r\n\t\r\n\t\r\n\tm_const_ptr = rhs.Addr();\r\n\treturn *this;\t\r\n}\r\n\r\n#else\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\ntemplate < class _T > template < class _NewT > inline\r\nPtr< _T >::Ptr( const Ptr< _NewT >& rhs )\t\r\n: PtrToConst< _T >( rhs )\r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert( false, ( \"Microsoft VC++ sucks - don't do this (yet)\" ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > template < class _NewT > inline\r\nPtr< _T >&\t\tPtr< _T >::operator= ( const Ptr< _NewT >& rhs ) \r\n{\r\n\t\r\n\r\n\tDbg_MsgAssert( false, ( \"Microsoft VC++ sucks - don't do this (yet)\" ));\r\n\r\n\tm_const_ptr = rhs.Addr();\r\n\treturn *this;\t\r\n}\r\n\r\n#endif\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\nPtr< _T >&\t\tPtr< _T >::operator= ( const _T* ptr ) \r\n{\r\n\t\r\n\r\n\tm_const_ptr = ptr;\r\n\treturn *this;\t\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\n_T&\t\tPtr< _T >::operator * ( void ) const \r\n{\r\n\t\r\n\r\n\tDbg_AssertType( m_ptr, _T );\r\n\r\n\treturn *m_ptr;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\n_T*\t\tPtr< _T >::operator -> ( void ) const \r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( m_ptr, _T );\r\n\t\r\n\treturn m_ptr;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ntemplate < class _T > inline\r\n_T*\t\tPtr< _T >::Addr ( void ) const \r\n{\r\n\t\r\n\r\n\treturn m_ptr;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n#endif  // __SYS_MEM_MEMPTR_H\t\t\t\t\t\t\t\t\r\n"
  },
  {
    "path": "Code/Sys/Mem/memtest.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSystem Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory (Mem) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmemtest.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMemory test code\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <sys\\mem\\region.h>\r\n#include \"heap.h\"\r\n#include \"pool.h\"\r\n#include \"pile.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  TestA  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic :\r\n\t\t\tTestA ( uint val = 999 ) : value (val ) { }\r\n\tuint\tGetValue( void ) const  { return value; }\r\n\r\nprotected :\r\n\r\n\tuint\tvalue;\r\n\r\n};\r\n\r\nclass  TestB : public  TestA \r\n{\r\n\t\r\n\r\npublic :\r\n\t\t\tTestB ( uint val = 666 ) { value = val; }\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid Test( void )\r\n{\r\n\t\r\n\r\n\tDbg_Message( \"Testing Memory sub-system\" );\r\n\r\n\tDbg_Message ( \"Allocate 1M region from Mem::Manager's default BottomUp Heap\" );\r\n\t\r\n\tMem::AllocRegion*\tregion = new Mem::AllocRegion( 1024 * 1024 );\r\n\t\r\n\tDbg_Message ( \"Create Bottom-Up Heap and Top-Down Pile within region\" );\r\n\r\n\tMem::Heap*\t\t\theap = new Mem::Heap( region, Mem::Allocator::vBOTTOM_UP );\r\n\tMem::Pile*\t\t\tpile = new Mem::Pile( region, Mem::Allocator::vTOP_DOWN );\r\n\r\n\tDbg_Message ( \"Set current allocator to Mem::Manager's default TopDown Heap\" );\r\n\r\n\tManager::sHandle().PushContext( Manager::sHandle().TopDownHeap() );\r\n\r\n\tDbg_Message ( \"Allocate another 1M region\" );\r\n\r\n\tMem::AllocRegion*\tregion2 = new Mem::AllocRegion( 1024 * 1024 );\r\n\tDbg_Message ( \"Create Bottom-Up Pool (16x1K slots) and Top-Down Heap within region\" );\r\n\r\n\tMem::Pool*\t\t\tpool = new Mem::Pool( region2, 1024, 16 );\r\n\tMem::Heap*\t\t\theap2 = new Mem::Heap( region2, Mem::Allocator::vTOP_DOWN );\r\n\t\r\n\tManager::sHandle().PushContext( pile );\r\n\r\n//\tchar*\ttest1( new char[100] );\r\n//\tMem::Ptr<char>\ttest1( new char[100] );\r\n\t\r\n\tMem::Ptr< TestB >\ttestB = new TestB[10];\r\n\t\t\t\t\t\t\r\n\r\n\tDbg_Message ( \"Test B = %p, value = %d\", testB.Addr(), testB->GetValue() );\r\n#if 0\r\n\tMem::Manager::sInstance().Delete(testB.Addr());\r\n\tuint\ta = testB->GetValue();\r\n#endif\r\n\r\n\r\n\t\r\n//\tMem::Ptr< TestA >\tctestA = testB;\r\n//\tMem::PtrToConst< TestA >\tctestA = testB;\r\n\t\r\n\r\n\r\n\r\n\r\n//\tMem::Ptr< TestA >\ttestA( testB );\r\n\r\n//\tMem::Ptr< TestA >\ttestA;\r\n//\ttestA = testB;\r\n\r\n#if 0 // poor little XBOX - can't handleit!\r\n\tMem::Ptr< TestA >\ttestA = testB;\r\n\ttestA+=9;\t // 10 doesn't assert properly - why???\r\n#endif\r\n\r\n//\tMem::PtrToConst< TestA >\tctestA( testB );\r\n\r\n\r\n//\tMem::PtrToConst< TestA >\tctestA;\r\n//\tctestA = testB;\r\n\t\r\n//\tMem::PtrToConst< TestA >\tctestA = testB;\t // gives warning\r\n\t\r\n//\tMem::PtrToConst< TestB >\tctestB = testB;\r\n//\tMem::PtrToConst< TestA >\tctestA = ctestB;\t\r\n\t\r\n\t\r\n//\tctestB = testB;\r\n//\tctestB->GetValue();\r\n//\tTestB\tttestB = *ctestB++;\r\n\t\r\n#if 0\r\n\tMem::PtrToConst< TestB >\tstestB1 = (ctestB + 1);\r\n\r\n\tMem::PtrToConst< TestB >\tstestB10 = (ctestB + 10);\r\n#endif\r\n\r\n\r\n//\tMem::Ptr< int >\t\tintPtr = new int;\r\n//\tint\t\tb = *intPtr;\r\n\r\n\tchar*\ttest2[17];\r\n\r\n\tfor( uint i = 0; i < 16; i++ )\r\n\t{\r\n\t\ttest2[i] = new (pool) char[1024];\r\n\t\tDbg_Message ( \"%x  should be valid address\", test2[i] );\r\n\t}\r\n\r\n\ttest2[16] = new (pool, false) char[1024];\r\n\tDbg_Message ( \" %x  should be NULL address ( no free slots )\", test2[16] ); \r\n\r\n\tdelete test2[0];\r\n\tdelete test2[1];\r\n\r\n\tchar* test3 = new char;\r\n\t\r\n\tManager::sHandle().PushContext( heap );\r\n\r\n\tchar* test4 = new char;\r\n\r\n\tManager::sHandle().PushContext( heap2 );\r\n\t\r\n\tManager::sHandle().PopContext();\r\n\tManager::sHandle().PopContext();\r\n\tManager::sHandle().PopContext();\r\n\r\n\tdelete test3;\r\n\tdelete test4;\r\n//\tdelete test4;\r\n\r\n\tdelete heap;\r\n\tdelete pile;\r\n\tdelete pool;\r\n\tdelete heap2;\r\n\r\n\r\n/*\r\n\tchar*  tmp1 = new char;\r\n\tint*  tmp2 = new int;\r\n\tshort*  tmp3 = new short;\r\n\tdelete tmp1;\r\n\tdelete tmp3;\r\n\tdelete tmp2;\r\n*/\r\n\r\n\tTestA*\ttesta = new TestA;\r\n\tMem::Handle< TestA > test_handle = testa;\r\n\r\n\tTestA*\tgooda = test_handle.GetPointer();\r\n\tDbg_AssertType( testa, TestA );\r\n\t\r\n\tDbg_MsgAssert(( gooda == testa ),( \"Handles pointer not valid\" ));\r\n\r\n\tif( gooda != testa )\r\n\t{\r\n\t\tprintf(\"Error!!!!!   Handles pointer not valid\\n\" );\r\n\t}\r\n\r\n\tDbg_AssertType( gooda, TestA );\r\n\r\n\tdelete testa;\r\n//\ttesta = new TestA;\r\n\r\n\tgooda = test_handle.GetPointer();\t\r\n\tDbg_MsgAssert(( gooda == NULL ),( \"Handles pointer not NULL\" ));\r\n\r\n\tif( gooda )\r\n\t{\r\n\t\tprintf(\"Error!!!!!   Handles pointer not NULL\\n\" );\r\n\t}\r\n\r\n\tDbg_MsgAssert(( false ),(\"DONE\" ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n"
  },
  {
    "path": "Code/Sys/Mem/memtest.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory Manager (Mem)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/mem/memtest.h\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_MEM_MEMTEST_H\r\n#define\t__SYS_MEM_MEMTEST_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid Test( void );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n#endif  // __SYS_MEM_MEMTEST_H\r\n"
  },
  {
    "path": "Code/Sys/Mem/pile.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSystem Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory (Mem) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tpile.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tPile class\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include \"pile.h\"\r\n#include <sys\\mem\\region.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid*\tPile::allocate( size_t size, bool assert_on_fail )\r\n{\r\n\t\r\n\t\t\r\n#ifdef __PLAT_NGC__\r\n\tsize = (uint)nAlignUpBy( size, 5 );\r\n#else\r\n\tsize = (uint)nAlignUpBy( size, 4 );\r\n#endif\r\n\t\r\n\tBlockHeader* p_header = (BlockHeader*)mp_region->Allocate( this, size + BlockHeader::sSize, assert_on_fail );\r\n\r\n\tif ( p_header )\r\n\t{\r\n\t\tnew ((void*)p_header) BlockHeader( this, size ); \r\n\r\n\t\tDbg_Code \r\n\t\t(\r\n\t\t\tm_alloc_count++;\r\n\t\t)\r\n\t}\r\n\telse if ( assert_on_fail )\r\n\t{\r\n\t\tDbg_MsgAssert ( false,( \"Failed to allocate %d bytes\", size ));\r\n\t}\r\n\r\n\tMemDbg_AllocateBlock ( p_header );\t\r\n\t\r\n\treturn (void*)((uint)p_header + BlockHeader::sSize);\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPile::free( BlockHeader* pHeader )\r\n{\r\n\t\r\n\t\r\n\tMemDbg_FreeBlock ( pHeader );\t\r\n\r\n\tpHeader->~BlockHeader();\r\n\r\n\tDbg_Code \r\n\t(\r\n\t\tDbg_MsgAssert(( m_alloc_count > 0 ),( \"Internal Error - freed too many blocks!!\" ));\r\n\t\tm_alloc_count--;\r\n\t)\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nPile::Pile( Region* region, Direction dir )\r\n: Allocator( region, dir, \"Pile\" )\r\n{\r\n\t\r\n\t\r\n\tmp_base = mp_top;\r\n\r\n\tDbg_Code\r\n\t(\r\n\t\tm_depth = 0;\r\n\t)\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPile::~Pile( void )\r\n{\r\n\t\r\n\r\n\tDbg_Code\r\n\t(\r\n\t\tDbg_MsgAssert(( m_depth == 0 ),( \"Context Stack not empty (%d items)\", m_depth ));\r\n\t\r\n\t\t// warn if there are still allocations.\r\n\t\tDbg_MsgAssert(( m_alloc_count == 0 ),( \"Pile still contains allocations\" ));\r\n\t)\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid \tPile::PushContext( void )\r\n{\r\n\t\r\n\r\n\tvoid** p_top = (void**)mp_top;\r\n\t*p_top = mp_base;\r\n\tmp_base = p_top;\r\n\tmp_top = p_top + m_dir;\r\n\t\r\n\tDbg_Code\r\n\t(\r\n\t\tm_depth++;\r\n\t)\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPile::PopContext( void )\r\n{\r\n\t\r\n\t\t\r\n\tDbg_Code\r\n\t(\r\n\t\tDbg_MsgAssert( m_depth > 0,( \"Context stack underflow\" ));\r\n\t\tm_depth--;\r\n\t)\r\n\r\n\tmp_top = mp_base;\r\n\tmp_base = *(void**)mp_top;\r\n\tmp_top = (void*)( (void**)(mp_top) + m_dir );\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n"
  },
  {
    "path": "Code/Sys/Mem/pile.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory Manager (Mem)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/mem/pile.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_MEM_PILE_H\r\n#define\t__SYS_MEM_PILE_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include \"alloc.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Region;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nclass  Pile : public  Allocator \t\t\t\r\n{\r\n\t\r\n\t\r\n\tfriend class Manager;\r\n\r\npublic :\r\n\t\t\r\n\t\t\t\t\t\t\tPile( Region* region, Direction dir = vBOTTOM_UP );\r\n\tvirtual\t\t\t\t\t~Pile( void );\r\n\t\r\n\tvirtual\t\tvoid\t\tPushContext( void );\r\n\tvirtual\t\tvoid\t\tPopContext( void );\r\n\r\nprivate :\r\n\t\r\n\tvirtual\t\tvoid*\t\tallocate( size_t size, bool assert_on_fail );\r\n\tvirtual\t\tvoid\t\tfree( BlockHeader* pHeader );\r\n\t\r\n\tvoid*\t\t\t\t\tmp_base;\r\n\t\r\n\tDbg_Code\r\n\t(\r\n\t\tsint\t\t\t\tm_depth;\r\n\t\tsint\t\t\t\tm_alloc_count;\r\n\t)\r\n};\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n#endif  // __SYS_MEM_PILE_H\r\n"
  },
  {
    "path": "Code/Sys/Mem/pool.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSystem Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory (Mem) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tpool.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/29/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMemory Pool class\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include \"memman.h\"\r\n#include \"pool.h\"\r\n#include <sys\\mem\\region.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid Pool::dump_free_list( void )\r\n{\r\n\t\r\n\t\r\n\tBlockHeader*\tp_header = mp_free_list;\r\n\r\n\twhile ( p_header )\r\n\t{\r\n\t\tDbg_AssertType( p_header, BlockHeader );\r\n\t\tDbg_Message ( \"%p  %d   (%p)\", (void*)((uint)p_header + sizeof( BlockHeader )), \r\n\t\t\t\t\t\t\t\t\t\tp_header->mSize, p_header->mpNext );\r\n\t\tp_header = p_header->mpNext;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid*\tPool::allocate( size_t size, bool assert_on_fail )\r\n{\r\n\t\r\n\t\t\r\n\tDbg_MsgAssert ( size <= m_size,( \"Failed to allocate: Size (%x) > Pool Element (%x)\", size, m_size ));\r\n\r\n\tif ( mp_free_list )\r\n\t{\r\n\t\tDbg_AssertType( mp_free_list, BlockHeader );\r\n\t\t\r\n\t\tBlockHeader* p_header = mp_free_list;\r\n\t\t\r\n\t\tmp_free_list = p_header->mpNext;\r\n\t\tp_header->mpAlloc = this;\r\n\r\n\t\tMemDbg_AllocateBlock ( p_header );\t\r\n\r\n\t\treturn (void*)((uint)p_header + BlockHeader::sSize);\r\n\t}\r\n\r\n\tif ( assert_on_fail )\r\n\t{\r\n\t\tDbg_MsgAssert ( false,( \"Failed to allocate %d bytes, no free slots\", size ));\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tPool::free( BlockHeader* pFreeBlock )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType( pFreeBlock, BlockHeader );\r\n\r\n\tMemDbg_FreeBlock ( pFreeBlock );\t\r\n\t   \r\n\tpFreeBlock->mpNext = mp_free_list;\r\n\tmp_free_list = pFreeBlock;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nPool::Pool( Region* region, size_t size, uint count, Direction dir )\r\n: Allocator( region, dir, \"Pool\" ), m_count( count), m_size( size )\r\n{\r\n\t\r\n\r\n\tif ( !nAlignedBy( m_size, 4 ))\r\n\t{\r\n#ifdef __PLAT_NGC__\r\n\t\tDbg_Warning ( \"size %x must be 32 byte aligned ( setting to %x )\", m_size, nAlignUpBy( (void*)m_size, 5 ));\r\n\t\tm_size = (size_t)nAlignUpBy( m_size, 5 );\r\n#else\r\n\t\tDbg_Warning ( \"size %x must be 16 byte aligned ( setting to %x )\", m_size, nAlignUpBy( (void*)m_size, 4 ));\r\n\t\tm_size = (size_t)nAlignUpBy( m_size, 4 );\r\n#endif\r\n\t}\r\n\r\n\tBlockHeader* p_freeblock = (BlockHeader*)mp_region->Allocate( this, ( m_size + BlockHeader::sSize ) * m_count );\r\n\t\r\n\tDbg_MsgAssert ( p_freeblock,( \"Failed to allocate Memory Pool from Region\" ));\r\n\r\n\tmp_free_list = p_freeblock;\r\n\r\n\tfor ( uint i = 0; i < ( m_count - 1 ); i++ )\r\n\t{\r\n\t\tnew ((void*)p_freeblock) BlockHeader( this, m_size );\t\t\r\n\t\t\r\n\t\tBlockHeader* p_nextblock = (BlockHeader*)( (uint)p_freeblock + BlockHeader::sSize + m_size ); \r\n\t\tp_freeblock->mpNext = p_nextblock;\r\n\t\tp_freeblock = p_nextblock;\r\n\t}\r\n\r\n\tnew ((void*)p_freeblock) BlockHeader( this, m_size );\t\t\r\n\tp_freeblock->mpNext = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nPool::~Pool( void )\r\n{\r\n\t\r\n\r\n\tDbg_Code  // warn if there are still allocated slots.\r\n\t(\r\n\t\tuint free_list_count = 0;\r\n\r\n\t\tfor ( BlockHeader* p_free_list = mp_free_list; p_free_list; p_free_list = p_free_list->mpNext )\r\n\t\t{\r\n\t\t\tfree_list_count++;\r\n\t\t}\r\n\r\n\t\tDbg_MsgAssert(( free_list_count == m_count ),( \"Pool still contains allocated slots\" ));\r\n\t)\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n"
  },
  {
    "path": "Code/Sys/Mem/pool.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory Manager (Mem)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tcore/sys/mem/pool.h\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_MEM_POOL_H\r\n#define\t__SYS_MEM_POOL_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include \"alloc.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Region;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  Pool : public  Allocator \t\t\t\r\n{\r\n\t\r\n\t\r\n\tfriend class Manager;\r\n\r\npublic :\r\n\t\t\r\n\t\t\t\t\t\t\t\tPool( Region* region, size_t size, uint count, Direction dir = vBOTTOM_UP );\r\n\tvirtual\t\t\t\t\t\t~Pool( void );\r\n\t\r\nprivate :\r\n\t\r\n\tvirtual\t\tvoid*\t\t\tallocate( size_t size, bool assert_on_fail );\r\n\tvirtual\t\tvoid\t\t\tfree( BlockHeader* pHeader );\r\n\t\t\t\tvoid\t\t\tdump_free_list( void );\r\n\r\n\t\t\t\tBlockHeader*\tmp_free_list;\r\n\t\t\t\tuint\t\t\tm_count;\r\n\t\t\t\tsize_t\t\t\tm_size;\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n#endif  // __SYS_MEM_POOL_H\r\n"
  },
  {
    "path": "Code/Sys/Mem/region.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSystem Library\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory (Mem) \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tregion.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tRegion Class\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <sys\\mem\\region.h>\r\n#include <sys/config/config.h>\r\n#include \"alloc.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nRegion::~Region( void )\r\n{\r\n\t\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tRegion::init( void* pStart, void* pEnd )\r\n{\r\n\t\r\n\r\n\tDbg_AssertPtr( pStart );\r\n\r\n\tmp_start\t= pStart;\r\n\tmp_end\t\t= pEnd;\r\n\r\n\tm_min_free  = (int)pEnd - (int)pStart;\r\n\r\n\tm_alloc[vBOTTOM_UP] = \r\n\tm_alloc[vTOP_DOWN] \t= NULL;\r\n\r\n\tDbg_Notify( \"Region(%p) created %p -> %p \", this, mp_start, mp_end );\r\n\r\n\tif (!Config::CD())\r\n\t{\r\n#ifdef __CLEAR_MEMORY__\r\n\t\tuint64* ptr = (uint64*)mp_start; \r\n\t\tuint \tsize = (uint)mp_end - (uint)mp_start;\r\n\t\r\n\t\tfor ( uint i = 0; i < size; i += 8 )\r\n\t\t{\r\n\t\t\t*ptr++ = vFREE_BLOCK;\r\n\t\t}\r\n#endif\r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid\t\tRegion::RegisterAllocator( Allocator* pAlloc )\r\n{\r\n\t\r\n\r\n\tint index = ( pAlloc->m_dir & 2 ) >> 1;\r\n\r\n\tDbg_MsgAssert ( m_alloc[index] == NULL,( \"Attempt to register multiple Allocators\" ));\r\n\r\n\tm_alloc[index] = pAlloc;\r\n\r\n\tpAlloc->mp_top = ( pAlloc->m_dir == Allocator::vBOTTOM_UP ) ? mp_start : mp_end;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tRegion::UnregisterAllocator( Allocator* pAlloc )\r\n{\r\n\t\r\n\t\r\n\tint index = ( pAlloc->m_dir & 2 ) >> 1;\r\n\t\r\n\tDbg_MsgAssert ( m_alloc[index] == pAlloc,( \"Allocator not currently registered\" ));\r\n\r\n\tm_alloc[index] = NULL;\r\n}\r\n\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Givne an allocator pAlloc, then allocate some space from this region\r\n// for this allocator\r\n// account for the m_dir flag in the allocator, which will be -1 or +1\r\n\r\nvoid*\t\tRegion::Allocate( Allocator* pAlloc, size_t size, bool assert_on_fail )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType ( pAlloc, Allocator );\r\n\r\n\t// Get index = 0 if BottomUp\r\n\t//     index = 1 if TopDown\r\n\tint index = ( pAlloc->m_dir & 2 ) >> 1;\r\n\tDbg_MsgAssert ( m_alloc[index] == pAlloc,( \"Allocator not currently registered\" ));\r\n\r\n\t// mp_top of an allocator is the \"Top\" of the heap relative to what direction it is going in\r\n\t// hence for a BottomUp heap, the mp_top will be the byte after the highest byte\r\n\t// and for a TopDown heap, the mp_top will be the lowest byte\t\r\n\t\r\n\t// here we get a new p_top for the allocator in pAlloc\r\n\t// then we just need to test it\r\n\tvoid* p_top = (void*) (( (uint)pAlloc->mp_top ) + ( size * pAlloc->m_dir ) );\r\n\t\r\n\tif( Allocator* p_alloc = m_alloc[index^1] )\t  // If other allocator exists\r\n\t{\r\n\t\tif ( index == vBOTTOM_UP )\t\t\t\t  // we are bottom up, other allocater is top down\r\n\t\t{\r\n\t\t\tif ( p_top > p_alloc->mp_top )\t\t // our new top is above the other allocator's base\r\n\t\t\t{\r\n\t\t\t\tif( assert_on_fail )\t\t\t // so fail\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( false,( \"Failed to Allocate %d bytes\", size ));\r\n\t\t\t\t}\r\n\t\t\t\tDbg_Warning( \"Failed to Allocate %d bytes\", size ); \r\n\t\t\t\treturn NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\t// we are top down, other allocator is bottom up\r\n\t\t{\r\n\t\t\tif ( p_top < p_alloc->mp_top )\t\t\t// new top is below the other allocator's top\r\n\t\t\t{\r\n\t\t\t\tif( assert_on_fail )\t\t\t\t// so fail\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( false,( \"Failed to Allocate %d bytes\", size ));\r\n\t\t\t\t}\r\n\t\t\t\tDbg_Warning( \"Failed to Allocate %d bytes\", size ); \r\n\t\t\t\treturn NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// here there is no other allocator\r\n\t\tif ( index == vBOTTOM_UP )\t\t\t\t// for a single bottom up heap\r\n\t\t{\r\n\t\t\tif ( p_top > mp_end )  \t\t\t\t// if new p_top goes past end of region\r\n\t\t\t{\r\n\t\t\t\tif( assert_on_fail )\t\t\t// then fail\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( false,( \"Failed to Allocate %d bytes\", size ));\r\n\t\t\t\t}\r\n\t\t\t\tDbg_Warning( \"Failed to Allocate %d bytes\", size ); \r\n\t\t\t\treturn NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\t// single top down\theap\r\n\t\t{\r\n\t\t\tif ( p_top < mp_start )\t\t // p_top goes below start of region\r\n\t\t\t{\r\n\t\t\t\tif( assert_on_fail )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( false,( \"Failed to Allocate %d bytes\", size ));\r\n\t\t\t\t}\r\n\t\t\t\tDbg_Warning( \"Failed to Allocate %d bytes\", size ); \r\n\t\t\t\treturn NULL;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// If it's vBOTTOM_UP then\r\n\t//    return pAlloc->mp_top, which is the old end of the heap, and the start of the new block\r\n\t// else\r\n\t// \t  return p_top, which is the base of the new block (when heap growing downwards)\r\n\r\n\tvoid* p_ret = ( index == vBOTTOM_UP ) ? pAlloc->mp_top : p_top;\r\n\r\n\t// store new \"top\" of heap\r\n\tpAlloc->mp_top = p_top;\r\n\r\n\tint free = MemAvailable();\r\n\tif (free < m_min_free)\r\n\t{\r\n\t\tm_min_free = free;\r\n\t}\r\n\r\n\r\n\t// and return the start of the new memory\r\n\treturn p_ret;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nRegion::Region( void* pStart, void* pEnd )\r\n{\r\n\t\r\n\t\t\r\n\tinit( pStart, pEnd );\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nAllocRegion::AllocRegion( size_t size )\r\n{\r\n\t\r\n\r\n\tsize = (size_t) nAlignDown( size );\r\n\t\r\n\tmp_start = new char[size];\r\n\t\r\n\tinit( mp_start, (void*)( (uint)mp_start + size ));\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nAllocRegion::~AllocRegion( void )\r\n{\r\n\t\r\n\r\n\tdelete[] (char *)mp_start;\r\n}\r\n\t\t\t\t\t\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Region::MemAvailable( void )\r\n{\r\n\t\r\n\t\t\r\n\tint bot = (int)((m_alloc[0]) ? m_alloc[0]->mp_top : mp_start);\r\n\tint top = (int)((m_alloc[1]) ? m_alloc[1]->mp_top : mp_end);\r\n\r\n\treturn ((int)top - (int)bot);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n"
  },
  {
    "path": "Code/Sys/Mem/region.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t                        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSys Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMemory Manager (Mem)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/20/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t/sys/mem/region.h   \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef\t__SYS_MEM_REGION_H\r\n#define\t__SYS_MEM_REGION_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mem\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass Allocator;\r\n\r\nclass  Region  : public Spt::Class\t\t\t\r\n{\r\n\t\r\n\r\n\tfriend class Manager;\r\n\r\npublic :\r\n\t\t\r\n\tvoid*\t\tStartAddr ( void ) const { return mp_start; }\r\n\tvoid*\t\tEndAddr ( void ) const { return mp_end; }\r\n\r\n\tvoid\t\tRegisterAllocator( Allocator* alloc );\t\t\r\n\tvoid\t\tUnregisterAllocator( Allocator* alloc );\r\n\tvoid*\t\tAllocate( Allocator* pAlloc, size_t size, bool assert_on_fail = true );\r\n\tint\t\t\tMemAvailable( void );\r\n\tint\t\t\tMinMemAvailable( void ) {return m_min_free;}\r\n\tint\t\t\tTotalSize( void );\r\n\r\n\tvirtual\t\t~Region();\r\n\r\nprotected :\r\n\t\t\t\tRegion( void ){};\r\n\t\t\t\tRegion( void* pStart, void* pEnd );\r\n\r\n\tvoid\t\tinit ( void* pStart, void* pEnd );\r\n\tvoid*\t\tmp_start;\r\n\r\n\r\n\tint\t\t\tm_min_free;\t\t// minimum amount of free memory\r\n\r\nprivate :\r\n\t\r\n\tenum\r\n\t{\r\n\t\tvBOTTOM_UP,\r\n\t\tvTOP_DOWN,\r\n\t\tvMAX_ALLOCS\r\n\t};\r\n\r\n\tvoid*\t\tmp_end;\r\n\r\n\tAllocator*\tm_alloc[vMAX_ALLOCS];\r\n\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  AllocRegion : public  Region \t\t\t\r\n{\r\n\t\r\n\r\n\tfriend class Manager;\r\n\r\npublic :\r\n\t\t\t\tAllocRegion( size_t size );\r\n\tvirtual\t\t~AllocRegion( void );\r\n\r\nprivate :\r\n\r\n\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline int Region::TotalSize( void )\r\n{\r\n\t\r\n\t\t\r\n\treturn ((int)mp_end - (int)mp_start);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mem\r\n\r\n#endif  // __SYS_MEM_REGION_H\r\n"
  },
  {
    "path": "Code/Sys/MemCard/NGPS/p_McMan.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMc\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmemcard.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/06/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMemcard - platform-specific implementations\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n\r\n#include <sys/mcman.h>\r\n\r\n#include <libmc.h>\r\n#include <sifdev.h>\r\n#include <libscf.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Mc\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefineSingletonClass( Manager, \"MemCard Manager\" );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nManager::Manager( void )\r\n{\r\n\t\r\n\r\n\tint result;\r\n\tint i, j;\r\n\r\n\tresult = sceMcInit();\r\n\tDbg_MsgAssert( result == 0,( \"Failed to initialize memory card system\\n\" ));\r\n\r\n\tfor( i = 0; i < vMAX_PORT; i++ )\r\n\t{\r\n\t\tfor( j = 0; j < vMAX_SLOT; j++ )\r\n\t\t{\r\n\t\t\tm_card[i][j].m_port = i;\r\n\t\t\tm_card[i][j].m_slot = j;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager( void )\r\n{\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint\t\tManager::GetMaxSlots( int port )\r\n{\r\n\tint result;\r\n\r\n   \tresult = sceMcGetSlotMax( port );\r\n\tif( result >= 0 )\r\n\t{\r\n\t\treturn result;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCard*\tManager::GetCard( int port, int slot )\r\n{\r\n\t\r\n\tint type;\r\n\r\n\tDbg_Assert( port < vMAX_PORT );\r\n\tDbg_Assert( slot < vMAX_SLOT );\r\n\t\r\n\tCard* card = &m_card[port][slot];\r\n\r\n\ttype = card->GetDeviceType();\r\n\tif(\t( type == Card::vDEV_PS1_CARD ) ||\r\n\t\t( type == Card::vDEV_PS2_CARD ))\r\n\t{\r\n\t\treturn card;\r\n\t}\r\n    \r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\twait_for_async_call_to_finish( Card* card )\r\n{\r\n\tint ret_val;\r\n\r\n\t\r\n\r\n\tsceMcSync( 0, NULL, &ret_val );\r\n\tif( ret_val < 0 )\r\n\t{   \r\n\t\tswitch( ret_val )\r\n\t\t{\r\n\t\t\tcase -1:\r\n\t\t\t\tDbg_Printf( \"Switched to formated card\\n\" );\r\n\t\t\t\tcard->SetError( Card::vERROR_FORMATTED );\r\n\t\t\t\tbreak;\r\n\t\t\tcase -2:\r\n\t\t\t\tDbg_Printf( \"Error: Unformatted Card\\n\" );\r\n\t\t\t\tcard->SetError( Card::vERROR_UNFORMATTED );\r\n\t\t\t\tbreak;\r\n\t\t\tcase -3:\r\n\t\t\t\tDbg_Printf( \"Error: Insufficient Space\\n\" );\r\n\t\t\t\tcard->SetError( Card::vINSUFFICIENT_SPACE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase -4:\r\n\t\t\t\tDbg_Printf( \"Error: Invalid Path\\n\" );\r\n\t\t\t\tcard->SetError( Card::vINVALID_PATH );\r\n\t\t\t\tbreak;\r\n\t\t\tcase -5:\r\n\t\t\t\tDbg_Printf( \"Error: Access Error\\n\" );\r\n\t\t\t\tcard->SetError( Card::vACCESS_ERROR );\r\n\t\t\t\tbreak;\r\n\t\t\tcase -6:\r\n\t\t\t\tDbg_Printf( \"Error: Subdir not empty\\n\" );\r\n\t\t\t\tcard->SetError( Card::vSUBDIR_NOT_EMPTY );\r\n\t\t\t\tbreak;\r\n\t\t\tcase -7:\r\n\t\t\t\tDbg_Printf( \"Error: Too many open files\\n\" );\r\n\t\t\t\tcard->SetError( Card::vTOO_MANY_OPEN_FILES );\r\n\t\t\t\tbreak;\r\n\t\t\tcase -10:\r\n\t\t\t\tDbg_Printf( \"Error: No card\\n\" );\r\n\t\t\t\tcard->SetError( Card::vNO_CARD );\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tcard->SetError( Card::vUNKNOWN );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\treturn ret_val;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCard::MakeDirectory( const char* dir_name )\r\n{\r\n\tint result;\r\n\t \r\n\t\r\n\r\n\tresult = sceMcMkdir( m_port, m_slot, dir_name );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tSetError( vUNKNOWN );\r\n\t\treturn false;\r\n\t}\r\n    \r\n\tint ErrorCode=wait_for_async_call_to_finish( this );\r\n\tif (ErrorCode==-4)\r\n\t{\r\n\t\t// If, the directory exists already, don't make it an error\r\n\t\tErrorCode=0;\r\n\t}\t\r\n\t\r\n\treturn( ErrorCode == 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Card::DeleteDirectory( const char* dir_name )\r\n{\r\n\t// On the PS2, the Delete() function used for files can also\r\n\t// be used to delete a directory.\r\n\treturn Delete(dir_name);\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst char *Card::ConvertDirectory( const char* dir_name )\r\n{\r\n\treturn NULL;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool \tCard::ChangeDirectory( const char* dir_name )\r\n{\r\n\tint result;\r\n\r\n\tresult = sceMcChdir( m_port, m_slot, dir_name, NULL );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tSetError( vUNKNOWN );\r\n\t\treturn false;\r\n\t}\r\n    \r\n\treturn( wait_for_async_call_to_finish( this ) == 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCard::Format( void )\r\n{\r\n\tint result;\r\n\r\n\tresult = sceMcFormat( m_port, m_slot );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tSetError( vUNKNOWN );\r\n\t\treturn false;\r\n\t}\r\n    \r\n\treturn( wait_for_async_call_to_finish( this ) == 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCard::Unformat( void )\r\n{\r\n\tint result;\r\n\r\n\tresult = sceMcUnformat( m_port, m_slot );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tSetError( vUNKNOWN );\r\n\t\treturn false;\r\n\t}\r\n    \r\n\treturn( wait_for_async_call_to_finish( this ) == 0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCard::IsFormatted( void )\r\n{\r\n\tint formatted;\r\n\tint result;\r\n\r\n    result = sceMcGetInfo( m_port, m_slot, NULL, NULL, &formatted );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tSetError( vUNKNOWN );\r\n\t\treturn false;\r\n\t}\r\n    \r\n\tresult = wait_for_async_call_to_finish( this );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tSetError( vUNKNOWN );\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn( formatted == 1 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tCard::GetDeviceType( void )\r\n{\r\n\tint type;\r\n\tint result;\r\n\r\n    result = sceMcGetInfo( m_port, m_slot, &type, NULL, NULL );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tSetError( vUNKNOWN );\r\n\t\treturn vDEV_NONE;\r\n\t}\r\n    \r\n\tresult = wait_for_async_call_to_finish( this );\r\n\tif(\tresult != 0 )\r\n\t{\r\n\t\tif(\t( GetLastError() != vERROR_UNFORMATTED ) &&\r\n\t\t\t( GetLastError() != vERROR_FORMATTED ))\r\n\t\t{\r\n\t\t\tSetError( vUNKNOWN );\r\n\t\t\treturn vDEV_NONE;\r\n\t\t}\r\n\t}\r\n\r\n\tswitch( type )\r\n\t{\r\n\t\tcase 1:\r\n\t\t\treturn vDEV_PS1_CARD;\r\n\t\tcase 2:\r\n\t\t\treturn vDEV_PS2_CARD;\r\n\t\tcase 3:\r\n\t\t\treturn vDEV_POCKET_STATION;\r\n\t\tdefault:\r\n\t\t\treturn vDEV_NONE;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tCard::GetNumFreeClusters( void )\r\n{\r\n\tint free_clusters;\r\n\tint result;\r\n\r\n    result = sceMcGetInfo( m_port, m_slot, NULL, &free_clusters, NULL );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tSetError( vUNKNOWN );\r\n\t\treturn 0;\r\n\t}\r\n    \r\n\tresult = wait_for_async_call_to_finish( this );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tSetError( vUNKNOWN );\r\n\t\treturn 0;\r\n\t}\r\n\r\n\treturn free_clusters;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tCard::GetNumFreeEntries( const char* path )\r\n{\r\n\tint result;\r\n\r\n    result = sceMcGetEntSpace( m_port, m_slot, path );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tSetError( vUNKNOWN );\r\n\t\treturn 0;\r\n\t}\r\n    \r\n\treturn( wait_for_async_call_to_finish( this ));\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCard::Delete( const char* filename )\r\n{\r\n\tint result;\r\n\r\n\tresult = sceMcDelete( m_port, m_slot, filename );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tSetError( vUNKNOWN );\r\n\t\treturn false;\r\n\t}\r\n    \r\n\tint ErrorCode=wait_for_async_call_to_finish( this );\r\n\tif (ErrorCode==-4)\r\n\t{\r\n\t\t// The the error was that the file already did not exist, don't report this as an error.\r\n\t\tErrorCode=0;\r\n\t}\r\n\t\t\r\n\treturn( ErrorCode==0 );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tCard::Rename( const char* old_name, const char* new_name )\r\n{\r\n\tint result;\r\n\r\n\tresult = sceMcRename( m_port, m_slot, old_name, new_name );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tSetError( vUNKNOWN );\r\n\t\treturn false;\r\n\t}\r\n    \r\n\treturn( wait_for_async_call_to_finish( this ) == 0 );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nFile*\tCard::Open( const char* filename, int mode, int size )\r\n{\r\n\tint result, fd;\r\n\tint open_mode;\r\n\tFile* file;\r\n\r\n\t\r\n\r\n\t//Dbg_MsgAssert( strlen( filename ) < 31,( \"Filename exceeds max length\\n\" ));\r\n\r\n\tfile = NULL;\r\n\topen_mode = 0;\r\n\tif( mode & File::mMODE_READ )\r\n\t{\r\n\t\topen_mode |= SCE_RDONLY;\r\n\t}\r\n\tif( mode & File::mMODE_WRITE )\r\n\t{\r\n\t\topen_mode |= SCE_WRONLY;\r\n\t}\r\n\tif( mode & File::mMODE_CREATE )\r\n\t{\r\n\t\topen_mode |= SCE_CREAT;\r\n\t}\r\n\tresult = sceMcOpen( m_port, m_slot, filename, open_mode );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tDbg_Printf( \"Unknown Error\\n\" );\r\n\t\tSetError( vUNKNOWN );\r\n\t\treturn NULL;\r\n\t}\r\n    \r\n\tfd = wait_for_async_call_to_finish( this );\r\n\tif( fd >= 0 )\r\n\t{\r\n\t\tfile = new File( fd, this );\r\n\t}\r\n\treturn file;\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Ken: This used to be a local variable in Card::GetFileList, but sceMcGetDir requires that\r\n// this buffer be 64 byte aligned, and occasionally it would not be, causing the contents of\r\n// file_table to be undefined after the call to sceMcGetDir.\r\n// Unfortunately, Sony did not make sceMcGetDir return an error code in this case, the blighters.\r\n//\r\nstatic sceMcTblGetDir file_table[Card::vMAX_FILES_PER_DIRECTORY];   \t\r\n\r\nbool\tCard::GetFileList( const char* mask, Lst::Head< File > &file_list )\r\n{\r\n\t\r\n\tint result, i;\r\n\t\t\r\n\tDbg_MsgAssert( mask != NULL,( \"Mask must be a valid search string. You may use wildcards\\n\" ));\r\n\r\n\tDbg_MsgAssert( (((uint32)file_table)&63)==0, (\"file_table not 64 byte aligned\"));\r\n\t\r\n\t\r\n\tint CallNumber=0;\r\n\twhile (true)\r\n\t{\r\n\t\tresult = sceMcGetDir( m_port, m_slot, mask, CallNumber, vMAX_FILES_PER_DIRECTORY, file_table );\r\n\t\tif( result != 0 )\r\n\t\t{\r\n\t\t\tSetError( vUNKNOWN );\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\t\r\n\t\tint NumFilesReturned = wait_for_async_call_to_finish( this );\r\n\t\tfor( i = 0; i < NumFilesReturned; i++ )\r\n\t\t{\r\n\t\t\tFile *new_file;\r\n\r\n\t\t\tnew_file = new File( 0, this );\r\n\r\n\t\t\tstrcpy( new_file->m_Filename, (char *) file_table[i].EntryName );\r\n\t\t\tnew_file->m_Size = file_table[i].FileSizeByte;\r\n\t\t\t\r\n\t\t\tnew_file->m_Attribs = 0;\r\n\t\t\tif( file_table[i].AttrFile & sceMcFileAttrReadable )\r\n\t\t\t{\r\n\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_READABLE;\r\n\t\t\t}\r\n\t\t\tif( file_table[i].AttrFile & sceMcFileAttrWriteable )\r\n\t\t\t{\r\n\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_WRITEABLE;\r\n\t\t\t}\r\n\t\t\tif( file_table[i].AttrFile & sceMcFileAttrExecutable )\r\n\t\t\t{\r\n\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_EXECUTABLE;\r\n\t\t\t}\r\n\t\t\tif( file_table[i].AttrFile & sceMcFileAttrDupProhibit )\r\n\t\t\t{\r\n\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_DUP_PROHIBITED;\r\n\t\t\t}\r\n\t\t\tif( file_table[i].AttrFile & sceMcFileAttrSubdir )\r\n\t\t\t{\r\n\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_DIRECTORY;\r\n\t\t\t}\r\n\t\t\tif( file_table[i].AttrFile & sceMcFileAttrClosed )\r\n\t\t\t{\r\n\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_CLOSED;\r\n\t\t\t}\r\n\t\t\tif( file_table[i].AttrFile & sceMcFileAttrPDAExec )\r\n\t\t\t{\r\n\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_PDA_APP;\r\n\t\t\t}\r\n\t\t\tif( file_table[i].AttrFile & sceMcFileAttrPS1 )\r\n\t\t\t{\r\n\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_PS1_FILE;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tsceCdCLOCK myClock;\r\n\t\t\tmyClock.day=itob(file_table[i]._Modify.Day);\r\n\t\t\tmyClock.hour=itob(file_table[i]._Modify.Hour);\r\n\t\t\tmyClock.minute=itob(file_table[i]._Modify.Min);\r\n\t\t\tmyClock.month=itob(file_table[i]._Modify.Month);\r\n\t\t\tmyClock.second=itob(file_table[i]._Modify.Sec);\r\n\t\t\tmyClock.year=itob(file_table[i]._Modify.Year%100);\r\n\t\t\tsceScfGetLocalTimefromRTC(&myClock);\r\n\t\t\tnew_file->m_Modified.m_Seconds \t= btoi(myClock.second);\r\n\t\t\tnew_file->m_Modified.m_Minutes \t= btoi(myClock.minute);\r\n\t\t\tnew_file->m_Modified.m_Hour \t= btoi(myClock.hour);\r\n\t\t\tnew_file->m_Modified.m_Day \t\t= btoi(myClock.day);\r\n\t\t\tnew_file->m_Modified.m_Month \t= btoi(myClock.month);\r\n\t\t\tnew_file->m_Modified.m_Year \t= btoi(myClock.year)+2000;\r\n\t\t\t\r\n\t\t\tmyClock.day=itob(file_table[i]._Create.Day);\r\n\t\t\tmyClock.hour=itob(file_table[i]._Create.Hour);\r\n\t\t\tmyClock.minute=itob(file_table[i]._Create.Min);\r\n\t\t\tmyClock.month=itob(file_table[i]._Create.Month);\r\n\t\t\tmyClock.second=itob(file_table[i]._Create.Sec);\r\n\t\t\tmyClock.year=itob(file_table[i]._Create.Year%100);\r\n\t\t\tsceScfGetLocalTimefromRTC(&myClock);\r\n\t\t\tnew_file->m_Created.m_Seconds \t= btoi(myClock.second);\r\n\t\t\tnew_file->m_Created.m_Minutes \t= btoi(myClock.minute);\r\n\t\t\tnew_file->m_Created.m_Hour \t\t= btoi(myClock.hour);  \r\n\t\t\tnew_file->m_Created.m_Day \t\t= btoi(myClock.day);   \r\n\t\t\tnew_file->m_Created.m_Month \t= btoi(myClock.month); \r\n\t\t\tnew_file->m_Created.m_Year \t\t= btoi(myClock.year)+2000;  \r\n\r\n\t\t\tfile_list.AddToTail( new_file );\r\n\t\t}\r\n\t\t\r\n\t\tif (NumFilesReturned<vMAX_FILES_PER_DIRECTORY)\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t++CallNumber;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nFile::File( int fd, Card* card ) : Lst::Node< File > ( this ), m_fd( fd ), m_card( card )\r\n{\r\n}\r\n\t\t\r\nFile::~File()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool\tFile::Close( void )\r\n{\r\n\tint result;\r\n\r\n\tresult = sceMcClose( m_fd );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tm_card->SetError( Card::vUNKNOWN );\r\n\t\treturn 0;\r\n\t}\r\n    \r\n\treturn( wait_for_async_call_to_finish( m_card ) == 0 );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tFile::Seek( int offset, FilePointerBase base )\r\n{\r\n\tint result;\r\n\tint mode;\r\n\r\n\t\r\n\r\n\tswitch( base )\r\n\t{\r\n\t\tcase BASE_START:\r\n\t\t\tmode = 0;\r\n\t\t\tbreak;\r\n\t\tcase BASE_CURRENT:\r\n\t\t\tmode = 1;\r\n\t\t\tbreak;\r\n\t\tcase BASE_END:\r\n\t\t\tmode = 2;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tmode = 1;\r\n\t\t\tDbg_MsgAssert( 0,( \"Invalid FilePointerBase\\n\" ));\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tresult = sceMcSeek( m_fd, offset, mode );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tm_card->SetError( Card::vUNKNOWN );\r\n\t\treturn 0;\r\n\t}\r\n    \r\n\treturn( wait_for_async_call_to_finish( m_card ));\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool \tFile::Flush( void )\r\n{\r\n\tint result;\r\n\r\n\tresult = sceMcFlush( m_fd );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tm_card->SetError( Card::vUNKNOWN );\r\n\t\treturn false;\r\n\t}\r\n    \r\n\treturn( wait_for_async_call_to_finish( m_card ) == 0 );\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tFile::Write( void* data, int len )\r\n{\r\n\tint result;\r\n\r\n\tresult = sceMcWrite( m_fd, data, len );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tm_card->SetError( Card::vUNKNOWN );\r\n\t\treturn 0;\r\n\t}\r\n    \r\n\treturn( wait_for_async_call_to_finish( m_card ));\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\t\tFile::Read( void* buff, int len )\r\n{\r\n\tint result;\r\n\r\n\t\r\n\r\n\tresult = sceMcRead( m_fd, buff, len );\r\n\tif( result != 0 )\r\n\t{\r\n\t\tDbg_Printf( \"Error: Could not read data\\n\" );\r\n\t\tm_card->SetError( Card::vUNKNOWN );\r\n\t\treturn 0;\r\n\t}\r\n    \r\n\treturn( wait_for_async_call_to_finish( m_card ));\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mc\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/MemCard/XBox/p_McMan.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMc\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmemcard.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/06/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMemcard - platform-specific implementations\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n\r\n#include <sys/mcman.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mc\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define MAX_FILENAME_LENGTH\t128\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefineSingletonClass( Manager, \"MemCard Manager\" );\r\n\r\nstatic char cardFilenameBuffer[MAX_FILENAME_LENGTH];\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nManager::Manager( void )\r\n{\r\n\tint i, j;\r\n\r\n\tfor( i = 0; i < vMAX_PORT; i++ )\r\n\t{\r\n\t\tfor( j = 0; j < vMAX_SLOT; j++ )\r\n\t\t{\r\n\t\t\tm_card[i][j].m_port = i;\r\n\t\t\tm_card[i][j].m_slot = j;\r\n\t\t}\r\n\t}\r\n\t\r\n\tm_hard_drive.SetAsHardDrive();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager( void )\r\n{\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint\tManager::GetMaxSlots( int port )\r\n{\r\n\treturn vMAX_SLOT;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCard* Manager::GetCard( int port, int slot )\r\n{\r\n\t// Ignore port and slot, since on the XBox we're only using the hard drive.\r\n\treturn &m_hard_drive;\r\n}\r\n\r\n// Skate3 code, disabled for now.\r\n#\tif 0\r\nCard* Manager::GetHardDrive( )\r\n{\r\n\treturn &m_hard_drive;\r\n}\r\n\r\nconst char* Manager::GetLastCardName( int port, int slot )\r\n{\r\n\tDbg_Assert( port < vMAX_PORT );\r\n\tDbg_Assert( slot < vMAX_SLOT );\r\n\t\r\n\tCard *p_card = &m_card[port][slot];\r\n\treturn p_card->GetLastPersonalizedName();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst char *Card::GetPersonalizedName()\r\n{\r\n\t// Only get the name if the card is mounted and is not the hard drive.\r\n\tif (m_mounted_drive_letter && m_mounted_drive_letter!='u')\r\n\t{\r\n\t\tsprintf(mp_personalized_name,\"\");\r\n\t\t\r\n\t\tWCHAR p_personalized_name[MAX_MUNAME+10];\r\n\t\tDWORD rv=XMUNameFromDriveLetter(m_mounted_drive_letter,p_personalized_name,MAX_MUNAME);\r\n\t\tif (rv==ERROR_SUCCESS)\r\n\t\t{\r\n\t\t\t// Instead of doing a wsprintfA( mp_personalized_name, \"%ls\", p_personalized_name );\r\n\t\t\t// which will terminate as soon as it hits a bad char, convert each WCHAR one at a \r\n\t\t\t// time so that all good characters come across.\r\n\t\t\tchar *p_dest=mp_personalized_name;\r\n\t\t\tint count=0;\r\n\t\t\tWCHAR p_temp[2]; // A buffer for holding one WCHAR at a time for sending to wsprintfA\r\n\t\t\tp_temp[1]=0;\r\n\t\t\tconst WCHAR *p_scan=p_personalized_name;\r\n\t\t\twhile (*p_scan) // WCHAR strings are terminated by a 0 just like normal strings, except its a 2byte 0.\r\n\t\t\t{\r\n\t\t\t\tp_temp[0]=*p_scan++;\r\n\t\t\t\t\r\n\t\t\t\tchar p_one_char[10];\r\n\t\t\t\twsprintfA( p_one_char, \"%ls\", p_temp);\r\n\t\t\t\t// p_one_char now contains a one char string.\r\n\t\t\t\t\r\n\t\t\t\tif (count<MAX_MUNAME)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (*p_one_char)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t*p_dest=*p_one_char;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Bad char, so write a ~ so that it appears as a xbox null char.\r\n\t\t\t\t\t\t*p_dest='~';\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\t++p_dest;\r\n\t\t\t\t\t++count;\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t\t*p_dest=0;\r\n\t\t\r\n\t\t\r\n\t\t\tint len=strlen(mp_personalized_name);\r\n\t\t\t\r\n\t\t\tfor (int i=0; i<len; ++i)\r\n\t\t\t{\r\n\t\t\t\t// Force any special characters (arrows or button icons) to be displayed\r\n\t\t\t\t// as the xbox NULL character by changing them to an invalid character.\r\n\t\t\t\tswitch (mp_personalized_name[i])\r\n\t\t\t\t{\r\n\t\t\t\tcase '': case '': case '': case '':\r\n\t\t\t\tcase '': case '': case '': case '':\r\n\t\t\t\tcase '': case '': case '': case '':\r\n\t\t\t\tcase -1: // This is the weird lower-case-y-umlaut character.\r\n\t\t\t\t\t\t // Note: The upper case y-umlaut character appears to be viewed as a\r\n\t\t\t\t\t\t // terminator character by XMUNameFromDriveLetter ( = bug?)\r\n\t\t\t\t\tmp_personalized_name[i]='~';\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t#ifdef __NOPT_ASSERT__\r\n\t\t\tchar p_temp[100];\r\n\t\t\tsprintf(p_temp,\"XMUNameFromDriveLetter error code = %d\\n\",rv);\r\n\t\t\tOutputDebugString(p_temp);\r\n\t\t\t#endif\r\n\t\t}\t\r\n\t}\r\n\t\r\n\treturn mp_personalized_name;\r\n}\r\n\r\nconst char *Card::GetLastPersonalizedName()\r\n{\r\n\treturn mp_personalized_name;\r\n}\r\n\r\nbool Card::THPS3SavesExist()\r\n{\r\n\tif ( m_mounted_drive_letter == 0 )\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\tcardFilenameBuffer[0] = m_mounted_drive_letter;\r\n\tcardFilenameBuffer[1] = ':';\r\n\tcardFilenameBuffer[2] = '\\\\';\r\n\tcardFilenameBuffer[3] = 0;\r\n\t\r\n\tXGAME_FIND_DATA data;\r\n\tHANDLE rv=XFindFirstSaveGame(cardFilenameBuffer,&data);\r\n\tif (rv==INVALID_HANDLE_VALUE)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\tXFindClose(rv);\r\n\t\treturn true;\r\n\t}\t\r\n}\r\n\t\r\nbool Card::CasParkOrReplaysExist()\r\n{\r\n\tif ( m_mounted_drive_letter == 0 )\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\tchar p_optpros_name[100];\r\n\tsprintf( p_optpros_name,\"/Options and Pros\" );\r\n\tConvertDirectory( p_optpros_name, p_optpros_name );\r\n\tstrcat(p_optpros_name,\"\\\\\");\r\n\t\r\n\tcardFilenameBuffer[0] = m_mounted_drive_letter;\r\n\tcardFilenameBuffer[1] = ':';\r\n\tcardFilenameBuffer[2] = '\\\\';\r\n\tcardFilenameBuffer[3] = 0;\r\n\t\r\n\tXGAME_FIND_DATA data;\r\n\tHANDLE rv=XFindFirstSaveGame(cardFilenameBuffer,&data);\r\n\tif (rv==INVALID_HANDLE_VALUE)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\tbool cas_park_or_replays_exist=false;\r\n\twhile (true)\r\n\t{\r\n\t\tif (stricmp(data.szSaveGameDirectory+3,p_optpros_name)==0)\r\n\t\t{\r\n\t\t\t// It's the optpros file\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\t// It either a cas, park or replay.\r\n\t\t\tcas_park_or_replays_exist=true;\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\t\r\n\t\tif (XFindNextSaveGame(rv,&data))\r\n\t\t{\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\t\t\r\n\tXFindClose(rv);\r\n\treturn cas_park_or_replays_exist;\r\n}\r\n\r\n// Returns true if the total number of cas, park or replay files is the max allowed.\r\nbool Card::MaxFilesReached()\r\n{\r\n\tif ( m_mounted_drive_letter == 0 )\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\tchar p_optpros_name[100];\r\n\tsprintf( p_optpros_name,\"/Options and Pros\" );\r\n\tConvertDirectory( p_optpros_name, p_optpros_name );\r\n\tstrcat(p_optpros_name,\"\\\\\");\r\n\t\r\n\tcardFilenameBuffer[0] = m_mounted_drive_letter;\r\n\tcardFilenameBuffer[1] = ':';\r\n\tcardFilenameBuffer[2] = '\\\\';\r\n\tcardFilenameBuffer[3] = 0;\r\n\t\r\n\tXGAME_FIND_DATA data;\r\n\tHANDLE rv=XFindFirstSaveGame(cardFilenameBuffer,&data);\r\n\tif (rv==INVALID_HANDLE_VALUE)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\t\r\n\tint num_files=0;\r\n\twhile (true)\r\n\t{\r\n\t\tif (stricmp(data.szSaveGameDirectory+3,p_optpros_name)==0)\r\n\t\t{\r\n\t\t\t// It's the optpros file\r\n\t\t}\t\r\n\t\telse\r\n\t\t{\r\n\t\t\t// It either a cas, park or replay.\r\n\t\t\t++num_files;\r\n\t\t}\t\r\n\t\t\r\n\t\tif (!XFindNextSaveGame(rv,&data))\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\t\t\r\n\tXFindClose(rv);\r\n\t\r\n\tif (num_files>=75)\r\n\t{\r\n\t\treturn true;\r\n\t}\t\r\n\treturn false;\r\n}\r\n#\tendif\r\n\t\r\n\r\n// Note: dir_name must no longer start with a backslash, it should just be \"Career2-Career\" etc.\r\nbool Card::MakeDirectory( const char* dir_name )\r\n{\r\n\tchar\toutput_dir[vDIRECTORY_NAME_BUF_SIZE];\r\n\tWCHAR\tinput_name[vDIRECTORY_NAME_BUF_SIZE];\r\n\r\n\twsprintfW( input_name, L\"%hs\", dir_name );\r\n\tDWORD rv = XCreateSaveGame(\t\"u:\\\\\",\t\t\t\t// Root of device on which to create the save game.\r\n\t\t\t\t\t\t\t\tinput_name,\t\t\t// Name of save game (effectively directory name).\r\n\t\t\t\t\t\t\t\tOPEN_ALWAYS,\t\t// Open disposition.\r\n\t\t\t\t\t\t\t\t0,\t\t\t\t\t// Creation flags.\r\n\t\t\t\t\t\t\t\toutput_dir,\t\t\t// String to take resultant directory name buffer.\r\n\t\t\t\t\t\t\t\tvDIRECTORY_NAME_BUF_SIZE );\t// Size of directory name buffer.\r\n\r\n\tif( rv == ERROR_SUCCESS )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (rv==ERROR_DISK_FULL)\r\n\t{\r\n\t\tm_last_error=vINSUFFICIENT_SPACE;\r\n\t}\r\n\t\t\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst char *Card::ConvertDirectory( const char* dir_name )\r\n{\r\n\tstatic char\toutput_dir[vDIRECTORY_NAME_BUF_SIZE];\r\n\tWCHAR\tinput_name[vDIRECTORY_NAME_BUF_SIZE];\r\n\r\n\twsprintfW( input_name, L\"%hs\", dir_name );\r\n\tDWORD rv = XCreateSaveGame(\t\"u:\\\\\",\t\t\t\t// Root of device on which to create the save game.\r\n\t\t\t\t\t\t\t\tinput_name,\t\t\t// Name of save game (effectively directory name).\r\n\t\t\t\t\t\t\t\tOPEN_EXISTING,\t\t// Open disposition.\r\n\t\t\t\t\t\t\t\t0,\t\t\t\t\t// Creation flags.\r\n\t\t\t\t\t\t\t\toutput_dir,\t\t\t// String to take resultant directory name buffer.\r\n\t\t\t\t\t\t\t\tvDIRECTORY_NAME_BUF_SIZE );\t// Size of directory name buffer.\r\n\r\n\tif( rv == ERROR_SUCCESS )\r\n\t{\r\n\t\t// Remove the initial \"u:\\\" and the final \"\\\"\r\n\t\tstrcpy(output_dir,output_dir+3);\r\n\t\toutput_dir[strlen(output_dir)-1]=0;\r\n\t\t\r\n\t\treturn output_dir;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\t\r\n\r\n// Skate3 code, disabled for now.\r\n#if 0\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::ConvertDirectory( const char* dir_name, char* output_name )\r\n{\r\n\t// K: This used to assert.\r\n\tif (m_mounted_drive_letter==0)\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\r\n\t// Seems incoming filenames are of the form /foo etc.\r\n\tcardFilenameBuffer[0] = m_mounted_drive_letter;\r\n\tcardFilenameBuffer[1] = ':';\r\n\tcardFilenameBuffer[2] = '\\\\';\r\n\tcardFilenameBuffer[3] = 0;\r\n\r\n\t++dir_name;\r\n\tint index = 4;\r\n\twhile( cardFilenameBuffer[index] = *dir_name )\r\n\t{\r\n\t\t// Switch forward slash directory separators to the supported backslash.\r\n\t\tif( cardFilenameBuffer[index] == '/' )\r\n\t\t{\r\n\t\t\tcardFilenameBuffer[index] = '\\\\';\r\n\t\t}\r\n\t\t++index;\r\n\t\t++dir_name;\r\n\t}\r\n\r\n\tchar\toutput_dir[64];\r\n\tWCHAR\tinput_name[64];\r\n\r\n\twsprintfW( input_name, L\"%hs\", &cardFilenameBuffer[4] );\r\n\tDWORD rv = XCreateSaveGame(\tcardFilenameBuffer,\t// Root of device on which to create the save game.\r\n\t\t\t\t\t\t\t\tinput_name,\t\t\t// Name of save game (effectively directory name).\r\n\t\t\t\t\t\t\t\tOPEN_EXISTING,\t\t// Open disposition.\r\n\t\t\t\t\t\t\t\t0,\t\t\t\t\t// Creation flags.\r\n\t\t\t\t\t\t\t\toutput_dir,\t\t\t// String to take resultant directory name buffer.\r\n\t\t\t\t\t\t\t\t64 );\t\t\t\t// Size of directory name buffer.\r\n\r\n\tif( rv == ERROR_SUCCESS )\r\n\t{\r\n\t\t// Copy over output directory, stripping leading drive, colon and backslash, and removing trailing backslash.\r\n\t\tstrcpy( output_name, &output_dir[3] );\r\n\t\toutput_name[strlen( output_name ) - 1] = 0;\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::DeleteDirectory( const char* dir_name )\r\n{\r\n\tDbg_Assert( m_mounted_drive_letter != 0 );\r\n\r\n\t// Seems incoming filenames are of the form /foo etc.\r\n\tcardFilenameBuffer[0] = m_mounted_drive_letter;\r\n\tcardFilenameBuffer[1] = ':';\r\n\tcardFilenameBuffer[2] = '\\\\';\r\n\tcardFilenameBuffer[3] = 0;\r\n\r\n\t++dir_name;\r\n\tint index = 4;\r\n\twhile( cardFilenameBuffer[index] = *dir_name )\r\n\t{\r\n\t\t// Switch forward slash directory separators to the supported backslash.\r\n\t\tif( cardFilenameBuffer[index] == '/' )\r\n\t\t{\r\n\t\t\tcardFilenameBuffer[index] = '\\\\';\r\n\t\t}\r\n\t\t++index;\r\n\t\t++dir_name;\r\n\t}\r\n\r\n\tWCHAR\tinput_name[64];\r\n\twsprintfW( input_name, L\"%hs\", &cardFilenameBuffer[4] );\r\n\tDWORD rv = XDeleteSaveGame(\tcardFilenameBuffer,\t\t\t// Root of device on which to create the save game.\r\n\t\t\t\t\t\t\t\tinput_name );\r\n\r\n\tif( rv == ERROR_SUCCESS )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n#endif\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n// Given the name of a file, this will delete it's directory, which\r\n// will result in the deletion of the directory, the file, and the icon.\r\n// The name must not be preceded with a backslash, ie should be \"Career12-Career\" for example.\r\nbool Card::DeleteDirectory( const char* dir_name )\r\n{\r\n\tWCHAR\tinput_name[64];\r\n\twsprintfW( input_name, L\"%hs\", dir_name );\r\n\tDWORD rv = XDeleteSaveGame(\t\"u:\\\\\", input_name );\r\n\r\n\tif( rv == ERROR_SUCCESS )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::ChangeDirectory( const char* dir_name )\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::Format( void )\r\n{\r\n\t// Not supported from within an Xbox title.\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::Unformat( void )\r\n{\r\n\t// Not supported from within an Xbox title.\r\n\treturn false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::IsFormatted( void )\r\n{\r\n\t// Must be formatted to have got this far on an Xbox title.\r\n\treturn true;\r\n}\r\n\r\n\r\nvoid Card::SetAsHardDrive()\r\n{\r\n\tm_mounted_drive_letter='u';\r\n}\r\n\r\n// Skate3 code, disabled for now.\r\n#if 0\r\nbool Card::IsHardDrive()\r\n{\r\n\treturn m_mounted_drive_letter=='u';\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Card::UnMount( void )\r\n{\r\n\t// Can't unmount the hard drive.\r\n\tif( m_mounted_drive_letter=='u' )\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n    m_mount_error=false;\r\n\tm_mount_failed_due_to_card_full=false;\r\n\tm_mount_failed_due_to_card_unformatted=false;\r\n\t\r\n\tif( m_mounted_drive_letter )\r\n\t{\r\n\t\tDWORD rv = XUnmountMU(m_port, ( m_slot == 0 ) ? XDEVICE_TOP_SLOT : XDEVICE_BOTTOM_SLOT);\r\n\t\tif (rv != ERROR_SUCCESS)\r\n\t\t{\r\n\t\t\tm_mount_error=true;\r\n\t\t\tif (rv==ERROR_DISK_FULL)\r\n\t\t\t{\r\n\t\t\t\tm_mount_failed_due_to_card_full=true;\r\n\t\t\t}\t\r\n\t\t\tif (rv==ERROR_UNRECOGNIZED_VOLUME)\t\r\n\t\t\t{\r\n\t\t\t\tm_mount_failed_due_to_card_unformatted=true;\r\n\t\t\t}\r\n\t\t}    \r\n\t\tm_mounted_drive_letter=0;\r\n\t}\r\n}\r\n\t\r\n#endif\r\n\r\n\r\nint\tCard::GetDeviceType( void )\r\n{\r\n\treturn vDEV_XBOX_HARD_DRIVE;\r\n}\r\n\r\n\r\n// Skate3 code, disabled for now.\r\n#if 0\r\n\r\nbool Card::GetMountError()\r\n{\r\n    return m_mount_error;\r\n}\r\n\r\nbool Card::MountFailedDueToCardFull()\r\n{\r\n\treturn m_mount_failed_due_to_card_full;\r\n}\t\r\n\r\nbool Card::MountFailedDueToCardUnformatted()\r\n{\r\n\treturn m_mount_failed_due_to_card_unformatted;\r\n}\t\r\n\r\n#endif\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint\tCard::GetNumFreeClusters( void )\r\n{\r\n\tif( m_mounted_drive_letter )\r\n\t{\r\n\t\tchar p_drive[20];\r\n\t\tstrcpy(p_drive,\"z:\\\\\");\r\n\t\t\r\n\t\tULARGE_INTEGER\tuliFreeAvail;\r\n\t\tULARGE_INTEGER\tuliTotal;\r\n\r\n\t\tp_drive[0] = m_mounted_drive_letter;\r\n\t\tBOOL br\t\t= GetDiskFreeSpaceEx( p_drive, &uliFreeAvail, &uliTotal, NULL );\r\n\t\tif( br )\r\n\t\t{\r\n\t\t\t// Each increment of HighPart represents 2^32 bytes, which is (2^32)/16384=262144 blocks.\r\n\t\t\treturn uliFreeAvail.HighPart*262144 + uliFreeAvail.LowPart/16384;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint\tCard::GetNumFreeEntries( const char* path )\r\n{\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::Delete( const char* filename )\r\n{\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::Rename( const char* old_name, const char* new_name )\r\n{\r\n\treturn true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nFile* Card::Open( const char* filename, int mode, int size )\r\n{\r\n\tDbg_Assert( m_mounted_drive_letter != 0 );\r\n\r\n\tm_last_error=0;\r\n\t\r\n\tFile*\tp_file\t\t= NULL;\r\n\tHANDLE\thandle;\r\n\r\n\t// Seems incoming filenames are of the form /foo/bar etc.\r\n\tcardFilenameBuffer[0] = m_mounted_drive_letter;\r\n\tcardFilenameBuffer[1] = ':';\r\n\r\n\tint index = 2;\r\n\twhile( cardFilenameBuffer[index] = *filename )\r\n\t{\r\n\t\t// Switch forward slash directory separators to the supported backslash.\r\n\t\tif( cardFilenameBuffer[index] == '/' )\r\n\t\t{\r\n\t\t\tcardFilenameBuffer[index] = '\\\\';\r\n\t\t}\r\n\t\t++index;\r\n\t\t++filename;\r\n\t}\r\n\r\n\tDWORD dwDesiredAccess;\r\n\tDWORD dwCreationDisposition;\r\n\r\n\tswitch( mode )\r\n\t{\r\n\t\tcase File::mMODE_READ:\r\n\t\t{\r\n\t\t\tdwDesiredAccess\t\t\t= GENERIC_READ;\r\n\t\t\tdwCreationDisposition\t= OPEN_EXISTING;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase File::mMODE_WRITE:\r\n\t\t{\r\n\t\t\tdwDesiredAccess\t\t\t= GENERIC_WRITE;\r\n\t\t\tdwCreationDisposition\t= OPEN_EXISTING;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase ( File::mMODE_WRITE | File::mMODE_CREATE ):\r\n\t\t{\r\n\t\t\tdwDesiredAccess\t\t\t= GENERIC_WRITE;\r\n\t\t\tdwCreationDisposition\t= OPEN_ALWAYS;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase File::mMODE_CREATE:\r\n\t\t{\r\n\t\t\tdwDesiredAccess\t\t\t= GENERIC_WRITE;\r\n\t\t\tdwCreationDisposition\t= CREATE_NEW;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase ( File::mMODE_READ | File::mMODE_WRITE ):\r\n\t\t{\r\n\t\t\tdwDesiredAccess\t= GENERIC_READ | GENERIC_WRITE;\r\n\t\t\tdwCreationDisposition\t= OPEN_EXISTING;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t}\r\n\r\n\thandle = CreateFile(\tcardFilenameBuffer,\t\t\t\t\t\t\t// file name\r\n\t\t\t\t\t\t\tdwDesiredAccess,\t\t\t\t\t\t\t// access mode\r\n\t\t\t\t\t\t\t0,\t\t\t\t\t\t\t\t\t\t\t// share mode\r\n\t\t\t\t\t\t\tNULL,\t\t\t\t\t\t\t\t\t\t// security attributes\r\n\t\t\t\t\t\t\tdwCreationDisposition,\t\t\t\t\t\t// how to create\r\n\t\t\t\t\t\t\tFILE_ATTRIBUTE_NORMAL,\t\t\t\t\t\t// file attributes and flags\r\n\t\t\t\t\t\t\tNULL );\t\t\t\t                        // handle to template file\r\n\r\n\tif( handle != INVALID_HANDLE_VALUE )\r\n\t{\r\n\t\tp_file = new File( (int)handle, this );\r\n\t\t\r\n\t\tWIN32_FILE_ATTRIBUTE_DATA file_attribute_data;\r\n\t\tif (GetFileAttributesEx(cardFilenameBuffer,GetFileExInfoStandard,&file_attribute_data))\r\n\t\t{\r\n//\t\t\tSkate3 code, disabled for now.\r\n#\t\t\tif 0\r\n\t\t\tp_file->m_file_time=file_attribute_data.ftLastWriteTime;\r\n#\t\t\tendif\r\n\t\t}\t\r\n\t\t\r\n\t\treturn p_file;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (GetLastError()==ERROR_DISK_FULL)\r\n\t\t{\r\n\t\t\tm_last_error=vINSUFFICIENT_SPACE;\r\n\t\t}\r\n\t}\t\r\n\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::GetFileList( const char* mask, Lst::Head< File > &file_list )\r\n{\r\n\tHANDLE\t\t\thandle;\r\n\tXGAME_FIND_DATA\tfind_data;\r\n\r\n\tcardFilenameBuffer[0] = m_mounted_drive_letter;\r\n\tcardFilenameBuffer[1] = ':';\r\n\tcardFilenameBuffer[2] = '\\\\';\r\n\r\n\tcardFilenameBuffer[3] = 0;\r\n\tif(( handle = XFindFirstSaveGame( cardFilenameBuffer, &find_data )) == INVALID_HANDLE_VALUE )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tdo\r\n\t{\r\n\t\tFile* new_file = new File( 0, this );\r\n\r\n\t\t// Skip copying the drive stuff, just copy the directory, and strip the trailing '\\'.\r\n\t\tstrcpy( new_file->m_Filename, (char*)&find_data.szSaveGameDirectory[3] );\r\n\t\tnew_file->m_Filename[strlen( new_file->m_Filename ) - 1] = 0;\r\n\r\n\t\twsprintfA( new_file->m_DisplayFilename, \"%ls\", find_data.szSaveGameName );\r\n\t\t\r\n\t\tFILETIME local_file_time;\r\n\t\tFileTimeToLocalFileTime(&find_data.wfd.ftLastWriteTime,&local_file_time);\r\n\t\tSYSTEMTIME system_file_time;\r\n\t\tFileTimeToSystemTime(&local_file_time,&system_file_time);\r\n\t\t\r\n\t\tnew_file->m_Modified.m_Year=system_file_time.wYear;\r\n\t\tnew_file->m_Modified.m_Month=system_file_time.wMonth;\r\n\t\tnew_file->m_Modified.m_Day=system_file_time.wDay;\r\n\t\tnew_file->m_Modified.m_Hour=system_file_time.wHour;\r\n\t\tnew_file->m_Modified.m_Minutes=system_file_time.wMinute;\r\n\t\tnew_file->m_Modified.m_Seconds=system_file_time.wSecond;\r\n\t\t\r\n\t\tnew_file->m_Size\t= find_data.wfd.nFileSizeLow;\r\n\t\tnew_file->m_Attribs\t= 0;\r\n\t\tfile_list.AddToTail( new_file );\r\n\t}\r\n\twhile( XFindNextSaveGame( handle, &find_data ));\r\n\tXFindClose( handle );\r\n\treturn true;\r\n}\r\n\r\n\r\nFile::File( int fd, Card* card ) : Lst::Node< File > ( this ), m_fd( fd ), m_card( card )\r\n{\r\n}\r\n\t\t\r\nFile::~File()\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint File::Seek( int offset, FilePointerBase base )\r\n{\r\n\tDbg_Assert( m_fd != 0 );\r\n\r\n\tDWORD dwMoveMethod;\r\n\r\n\tswitch( base )\r\n\t{\r\n\t\tcase BASE_START:\r\n\t\t\tdwMoveMethod = FILE_BEGIN;\r\n\t\t\tbreak;\r\n\t\tcase BASE_CURRENT:\r\n\t\t\tdwMoveMethod = FILE_CURRENT;\r\n\t\t\tbreak;\r\n\t\tcase BASE_END:\r\n\t\t\tdwMoveMethod = FILE_END;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tdwMoveMethod = FILE_END;\r\n\t\t\tDbg_MsgAssert( 0,( \"Invalid FilePointerBase\\n\" ));\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\r\n\tDWORD result = SetFilePointer(\t(HANDLE)m_fd,\t\t// handle to file\r\n\t\t\t\t\t\t\t\t\toffset,\t\t\t\t// bytes to move pointer\r\n\t\t\t\t\t\t\t\t\tNULL,\t\t\t\t// high-order bytes to move pointer\r\n\t\t\t\t\t\t\t\t\tdwMoveMethod );\t\t// starting point\r\n\r\n\treturn result;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool File::Flush( void )\r\n{\r\n\tDbg_Assert( m_fd != 0 );\r\n\r\n\tFlushFileBuffers((HANDLE)m_fd );\r\n\r\n\t// The FlushFileBuffers() is pretty strict about what types of files wmay be flushed,\r\n\t// whereas the PS2 equivalent doesn't really care. Just return a positive response always,\r\n\t// no critical stuff predicated on this return anway.\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tFile::Write( void* data, int len )\r\n{\r\n\tDbg_Assert( m_fd != 0 );\r\n\r\n//\tSkate3 code, disabled for now.\r\n#\tif 0\r\n\tm_not_enough_space_to_write_file=false;\r\n#\tendif\r\n\r\n\tDWORD bytes_written;\r\n\tBOOL rv = WriteFile(\t(HANDLE)m_fd,\t\t// handle to file\r\n\t\t\t\t\t\t\tdata,\t\t\t\t// data buffer\r\n\t\t\t\t\t\t\tlen,\t\t\t\t// number of bytes to write\r\n\t\t\t\t\t\t\t&bytes_written,\t\t// number of bytes written\r\n\t\t\t\t\t\t\tNULL );\t\t\t\t// overlapped buffer\r\n\t\t\t\t\t\t\t\r\n//\tSkate3 code, disabled for now.\r\n#\tif 0\r\n\tif (rv==ERROR_NOT_ENOUGH_MEMORY)\r\n\t{\r\n\t\tm_not_enough_space_to_write_file=true;\r\n\t}\r\n\tif (GetLastError()==ERROR_DISK_FULL)\r\n\t{\r\n\t\tm_not_enough_space_to_write_file=true;\r\n\t}\r\n#\tendif\r\n\t\t\r\n\tif( rv )\r\n\t{\r\n\t\treturn (int)bytes_written;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tFile::Read( void* buff, int len )\r\n{\r\n\tDbg_Assert( m_fd != 0 );\r\n\r\n\tDWORD bytes_read;\r\n\tBOOL rv = ReadFile(\t(HANDLE)m_fd,\t\t\t// handle to file\r\n\t\t\t\t\t\tbuff,\t\t\t\t\t// data buffer\r\n\t\t\t\t\t\tlen,\t\t\t\t\t// number of bytes to read\r\n\t\t\t\t\t\t&bytes_read,\t\t\t// number of bytes read\r\n\t\t\t\t\t\tNULL );\t\t\t\t\t// overlapped buffer\r\n\tif( rv )\r\n\t{\r\n\t\treturn (int)bytes_read;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool File::Close( void )\r\n{\r\n\tDbg_Assert( m_fd != 0 );\r\n\r\n\treturn CloseHandle((HANDLE)m_fd );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mc\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/MemCard/ngc/p_McMan.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tMc\t\t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tmemcard.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t03/06/01\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tMemcard - platform-specific implementations\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/singleton.h>\r\n\r\n#include <sys/mcman.h>\r\n#include <sys/ngc/p_display.h>\r\n#include <gel/mainloop.h>\r\n#include <gfx/ngc/nx/nx_init.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Mc\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\t\t\t\t\t\t\t\t\t\t\t\t\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define MAX_FILENAME_LENGTH\tCARD_FILENAME_MAX\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefineSingletonClass( Manager, \"MemCard Manager\" );\r\n\r\nstatic char cardFilenameBuffer[MAX_FILENAME_LENGTH];\r\n\r\nstatic bool initCalled = false;\r\n\r\n// Implicit assumption here is that vMAX_PORT == 1, which is always true for Gamecube.\r\nstatic char cardWorkArea[Manager::vMAX_SLOT][CARD_WORKAREA_SIZE] __attribute__((aligned( 32 )));\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic void detachCallback( s32 chan, s32 result )\r\n{\r\n\tOSReport( \"card %d detached: result = %d\\n\", chan, result );\r\n\r\n\tSpt::SingletonPtr< Mc::Manager > mc_man;\r\n\r\n\t// Don't want to call GetCard() here, since that will go off and try to verify the card...\r\n\tCard* p_card = mc_man->GetCardEx( 0, chan );\r\n\tif( p_card && p_card->mp_work_area )\r\n\t{\r\n//\t\tdelete[] p_card->mp_work_area;\r\n\t\tp_card->mp_work_area\t= NULL;\r\n\t}\r\n}\r\n\r\n\r\n\r\nManager::Manager( void )\r\n{\r\n\tif( !initCalled )\r\n\t{\r\n\t\tinitCalled = true;\r\n\t\tCARDInit();\r\n\t}\r\n\r\n\tfor( int i = 0; i < vMAX_PORT; i++ )\r\n\t{\r\n\t\tfor( int j = 0; j < vMAX_SLOT; j++ )\r\n\t\t{\r\n\t\t\tm_card[i][j].m_port = i;\r\n\t\t\tm_card[i][j].m_slot = j;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager( void )\r\n{\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint\tManager::GetMaxSlots( int port )\r\n{\r\n\treturn vMAX_SLOT;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nCard* Manager::GetCard( int port, int slot )\r\n{\r\n\tDbg_Assert( port < vMAX_PORT );\r\n\tDbg_Assert( slot < vMAX_SLOT );\r\n\t\r\n\t// Disable the reset button. Scripts will also do this by calling the script command\r\n\t// DisableReset at appropriate points.\r\n\t// The scripts may disable reset a bit earlier, eg when a 'checking card' message is on\r\n\t// screen. They do that to prevent lots of TT bugs because if the reset button is enabled\r\n\t// during the message it will seem like you can reset during card access, even though the\r\n\t// card is not really being accessed then.\r\n\t// It is done here too as a guarantee.\r\n\t//printf(\"GetCard is disabling reset ...\\n\");\r\n\t//NxNgc::EngineGlobals.disableReset = true;\r\n\t\r\n\tCard*\tcard\t= &m_card[port][slot];\r\n\tint\t\ttype\t= card->GetDeviceType();\r\n\r\n\tif( type == Card::vDEV_GC_CARD )\r\n\t{\r\n\t\treturn card;\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Card::MakeDirectory( const char* dir_name )\r\n{\r\n//\tDbg_Assert( m_mounted_drive_letter != 0 );\r\n//\r\n//\t// Seems incoming filenames are of the form /foo etc.\r\n//\r\n//\tcardFilenameBuffer[0] = m_mounted_drive_letter;\r\n//\tcardFilenameBuffer[1] = ':';\r\n//\r\n//\tint index = 2;\r\n//\twhile( cardFilenameBuffer[index] = *dir_name )\r\n//\t{\r\n//\t\t// Switch forward slash directory separators to the supported backslash.\r\n//\t\tif( cardFilenameBuffer[index] == '/' )\r\n//\t\t{\r\n//\t\t\tcardFilenameBuffer[index] = '\\\\';\r\n//\t\t}\r\n//\t\t++index;\r\n//\t\t++dir_name;\r\n//\t}\r\n//\r\n//\tif( CreateDirectory( cardFilenameBuffer, NULL ))\r\n//\t{\r\n//\t\treturn true;\r\n//\t}\r\n\r\n\t// Directory structure is not supported on Gamecube memory cards.\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::DeleteDirectory( const char* dir_name )\r\n{\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nconst char *Card::ConvertDirectory( const char* dir_name )\r\n{\r\n\treturn NULL;\r\n}\t\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Card::ChangeDirectory( const char* dir_name )\r\n{\r\n\t// Directory structure is not supported on Gamecube memory cards.\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::Format( void )\r\n{\r\n\tif( mp_work_area )\r\n\t{\r\n\t\ts32 format_result = CARDFormat( m_slot );\r\n\t\t\r\n\t\tif( format_result != CARD_RESULT_READY )\r\n\t\t{\r\n\t\t\t// If the format fails, then we need to do a CARDMount again, otherwise\t\r\n\t\t\t// CARDCheck will always return CARD_RESULT_NOCARD, even if a good card is inserted. (TT4975)\r\n\t\t\t// Force a CARDMount by deleting the mp_work_area buffer and calling GetDeviceType.\r\n\t\t\tif( mp_work_area )\r\n\t\t\t{\r\n\t//\t\t\tdelete [] mp_work_area;\r\n\t\t\t\tmp_work_area = NULL;\r\n\t\t\t}\r\n\t\t\tGetDeviceType();\r\n\t\t\t\r\n\t\t\tm_broken=true;\r\n\t\t}\r\n\t\t\r\n\t\tif( format_result == CARD_RESULT_READY )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::Unformat( void )\r\n{\r\n\t// Not supported from within a GameCube title.\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::IsFormatted( void )\r\n{\r\n\tif( mp_work_area )\r\n\t{\r\n\t\ts32 check_result = CARDCheck( m_slot );\r\n\t\tif (check_result==CARD_RESULT_IOERROR)\r\n\t\t{\r\n\t\t\tm_broken=true;\r\n\t\t}\t\r\n\t\tif( check_result == CARD_RESULT_READY )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::IsForeign( void )\r\n{\r\n\tif( mp_work_area )\r\n\t{\r\n\t\tu16 encode;\r\n\t\tCARDGetEncoding(m_slot,&encode);\r\n\t\tif (encode==CARD_ENCODE_SJIS)\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool Card::IsBadDevice( void )\r\n{\r\n\tif( mp_work_area )\r\n\t{\r\n\t\ts32 check_result = CARDCheck( m_slot );\r\n\t\tif( check_result == CARD_RESULT_WRONGDEVICE )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tCard::GetDeviceType( void )\r\n{\r\n\t// See whether this card is present.\r\n\ts32\tmem_size;\r\n\ts32\tsector_size;\r\n\ts32\tprobe_result;\r\n\ts32 loop_iterations\t= 0;\r\n\r\n\t// Cleat fatal error tracking variable.\r\n\tSpt::SingletonPtr< Mc::Manager > mc_man;\r\n\tmc_man->SetFatalError( false );\r\n\tmc_man->SetWrongDevice( false );\r\n\r\n\tdo\r\n\t{\r\n\t\t// This would appear to be a problem with the 0.93 dev hardware.\r\n\t\tprobe_result = CARDProbeEx( m_slot, &mem_size, &sector_size );\r\n\r\n\t\t// CARDProbeEx() will return BUSY if the system is still checking the card, so safe to quit on a NOCARD.\r\n\t\tif( probe_result == CARD_RESULT_NOCARD )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tif( probe_result == CARD_RESULT_WRONGDEVICE )\r\n\t\t{\r\n\t\t\tmc_man->SetWrongDevice( true );\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\r\n//\t\t// Check for reset being pushed.\r\n//\t\tif( NsDisplay::shouldReset())\r\n//\t\t{\r\n//\t\t\t// Prepare the game side of things for reset.\r\n//\t\t\tSpt::SingletonPtr< Mlp::Manager > mlp_manager;\r\n//\t\t\t//mlp_manager->PrepareReset();\r\n//\r\n//\t\t\t// Prepare the system side of things for reset.\r\n//\t\t\tNsDisplay::doReset();\r\n//\t\t}\r\n\t}\r\n\twhile(( probe_result != CARD_RESULT_READY ) && ( ++loop_iterations < 1000000 ));\r\n\r\n\tswitch( probe_result )\r\n\t{\r\n\t\tcase CARD_RESULT_BUSY:\r\n\t\tcase CARD_RESULT_NOCARD:\r\n\t\tcase CARD_RESULT_READY:\r\n\t\tcase CARD_RESULT_FATAL_ERROR:\r\n\t\t{\r\n\t\t\t// If this card is not mounted, mount it now.\r\n\t\t\tif( mp_work_area == NULL )\r\n\t\t\t{\r\n\t\t\t\tm_broken=false;\r\n\t\t\t\t\r\n//\t\t\t\tmp_work_area = new char[CARD_WORKAREA_SIZE];\r\n\t\t\t\tmp_work_area = &( cardWorkArea[m_slot][0] );\r\n\t\t\t\tDbg_MsgAssert( (((uint32)mp_work_area)&0x1f)==0, (\"mp_work_area not 32 byte aligned\"));\r\n\t\t\t\t\r\n\t\t\t\ts32 mount_result = CARDMount( m_slot, mp_work_area, detachCallback );\r\n\t\t\t\t\r\n\t\t\t\tif (mount_result == CARD_RESULT_BROKEN)\r\n\t\t\t\t{\r\n\t\t\t\t\ts32 check_result = CARDCheck( m_slot );\r\n\t\t\t\t\t//if (check_result == CARD_RESULT_BROKEN || check_result==CARD_RESULT_IOERROR)\r\n\t\t\t\t\tif (check_result==CARD_RESULT_IOERROR)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_broken=true;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\tif(( mount_result == CARD_RESULT_READY ) || ( mount_result == CARD_RESULT_BROKEN ) || ( mount_result == CARD_RESULT_ENCODING ))\r\n\t\t\t\t{\r\n\t\t\t\t\t// Mounted. Required to call CARDCheck() at this stage.\r\n\t\t\t\t\ts32 check_result = CARDCheck( m_slot );\r\n\t\t\t\t\t\r\n\t\t\t\t\tif(( check_result == CARD_RESULT_READY ) || ( check_result == CARD_RESULT_BROKEN ) || ( mount_result == CARD_RESULT_ENCODING ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_mem_size\t\t= mem_size;\r\n\t\t\t\t\t\tm_sector_size\t= sector_size;\r\n\r\n\t\t\t\t\t\treturn vDEV_GC_CARD;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n//\t\t\t\t\t\tdelete [] mp_work_area;\r\n\t\t\t\t\t\tmp_work_area = NULL;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif(( mount_result == CARD_RESULT_IOERROR ) || ( mount_result == CARD_RESULT_FATAL_ERROR ))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Set Manager tracking variable.\r\n\t\t\t\t\t\tmc_man->SetFatalError( true );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if (mount_result==CARD_RESULT_WRONGDEVICE)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmc_man->SetWrongDevice( true );\r\n\t\t\t\t\t}\t\r\n//\t\t\t\t\tdelete [] mp_work_area;\r\n\t\t\t\t\tmp_work_area = NULL;\r\n\t\t\t\t}\r\n\t\t\t}\t\t\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn vDEV_GC_CARD;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase CARD_RESULT_WRONGDEVICE:\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\t// No valid card, or can't be processed at this time.\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\t\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tCard::GetNumFreeClusters( void )\r\n{\r\n\ts32 bytes_free;\r\n\ts32 files_free;\r\n\ts32 free_result = CARDFreeBlocks( m_slot, &bytes_free, &files_free );\r\n\tif( free_result == CARD_RESULT_READY )\r\n\t{\r\n\t\treturn bytes_free / 8192;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tCard::GetNumFreeEntries( const char* path )\r\n{\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Card::Delete( const char* filename )\r\n{\r\n\t// Seems incoming filenames are of the form /foo/bar etc. Since there is no\r\n\t// directory structure on the Gamecube memory card, just convert to a single filename\r\n\t// by removing '\\' and '/'.\r\n\tint index = 0;\r\n\twhile(( cardFilenameBuffer[index] = *filename ))\r\n\t{\r\n\t\tDbg_Assert( index < MAX_FILENAME_LENGTH );\r\n\r\n\t\t// Switch forward slash directory separators to the supported backslash.\r\n\t\tif(( cardFilenameBuffer[index] == '/' ) || ( cardFilenameBuffer[index] == '\\\\' ) || ( cardFilenameBuffer[index] == '.' ))\r\n\t\t{\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t++index;\r\n\t\t}\r\n\t\t++filename;\r\n\t}\r\n\r\n\ts32 delete_result = CARDDelete( m_slot, cardFilenameBuffer );\r\n\tif( delete_result == CARD_RESULT_IOERROR )\r\n\t{\r\n\t\tm_broken=true;\r\n\t}\r\n\r\n\tif( delete_result == CARD_RESULT_READY )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Card::Rename( const char* old_name, const char* new_name )\r\n{\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nFile* Card::Open( const char* filename, int mode, int size )\r\n{\r\n\tDbg_Assert( mp_work_area != 0 );\r\n\r\n\t// Create the file here, it may be deleted if the open fails.\r\n\tFile* p_file = new File( 0, this );\r\n\r\n\t// Seems incoming filenames are of the form /foo/bar etc. Since there is no\r\n\t// directory structure on the Gamecube memory card, just convert to a single filename\r\n\t// by removing '\\' and '/'.\r\n\tint index = 0;\r\n\twhile(( cardFilenameBuffer[index] = *filename ))\r\n\t{\r\n\t\tDbg_MsgAssert( index < MAX_FILENAME_LENGTH, ( \"Filename: %s too long\\n\", filename ));\r\n\r\n\t\t// Switch forward slash directory separators to the supported backslash.\r\n\t\tif(( cardFilenameBuffer[index] == '/' ) || ( cardFilenameBuffer[index] == '\\\\' ) || ( cardFilenameBuffer[index] == '.' ))\r\n\t\t{\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t++index;\r\n\t\t}\r\n\t\t++filename;\r\n\t}\r\n\r\n\t// If we might be creating the file, ensure the size is aligned to a multiple of the sector size.\r\n\tif( mode & File::mMODE_CREATE )\r\n\t{\r\n\t\tDbg_Assert( m_sector_size > 0 );\r\n\t\tsize = ( size + ( m_sector_size - 1 )) & ~( m_sector_size - 1 );\r\n\t}\r\n\r\n\ts32 open_result;\r\n\tswitch( mode )\r\n\t{\r\n\t\tcase File::mMODE_READ:\r\n\t\t{\r\n\t\t\topen_result = CARDOpen( m_slot, cardFilenameBuffer, &p_file->m_file_info );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase File::mMODE_WRITE:\r\n\t\t{\r\n\t\t\topen_result = CARDOpen( m_slot, cardFilenameBuffer, &p_file->m_file_info );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase ( File::mMODE_WRITE | File::mMODE_CREATE ):\r\n\t\t{\r\n\t\t\topen_result = CARDOpen( m_slot, cardFilenameBuffer, &p_file->m_file_info );\r\n\t\t\tif( open_result == CARD_RESULT_NOFILE )\r\n\t\t\t{\r\n\t\t\t\topen_result = CARDCreate( m_slot, cardFilenameBuffer, size, &p_file->m_file_info );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase File::mMODE_CREATE:\r\n\t\t{\r\n\t\t\topen_result = CARDCreate( m_slot, cardFilenameBuffer, size, &p_file->m_file_info );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase ( File::mMODE_READ | File::mMODE_WRITE ):\r\n\t\t{\r\n\t\t\topen_result = CARDOpen( m_slot, cardFilenameBuffer, &p_file->m_file_info );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_Assert( 0 );\r\n\t\t\topen_result = CARD_RESULT_FATAL_ERROR;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (open_result == CARD_RESULT_INSSPACE )\r\n\t{\r\n\t\tSetError(vINSUFFICIENT_SPACE);\r\n\t}\r\n\t\t\r\n\tif( open_result == CARD_RESULT_READY )\r\n\t{\r\n\t\t// Set the file number.\r\n\t\tp_file->m_file_number = CARDGetFileNo( &p_file->m_file_info );\r\n\t\treturn p_file;\r\n\t}\r\n\r\n\tdelete p_file;\r\n\treturn NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void s_convert_time(uint32 seconds, DateTime *p_dateTime)\r\n{\r\n\t// seconds is the number of seconds since 01/01/2000 midnight\r\n\t\r\n\tOSCalendarTime ct;\r\n\r\n\tOSTicksToCalendarTime(OSSecondsToTicks((uint64)seconds),&ct);\r\n\tp_dateTime->m_Seconds = ct.sec;\r\n\tp_dateTime->m_Minutes = ct.min;\r\n\tp_dateTime->m_Hour = ct.hour;\r\n\tp_dateTime->m_Day = ct.mday;\r\n\t// The month value in OSCalendarTime starts at 0. May as well make it consistent\r\n\t// with the other platforms by adding 1. It doesn't really matter whether 1 is added\r\n\t// or not though cos the date is only used to determine the most recent save.\r\n\tp_dateTime->m_Month = ct.mon+1;\r\n\tp_dateTime->m_Year = ct.year;\r\n}\r\n\r\nbool Card::GetFileList( const char* mask, Lst::Head< File > &file_list )\r\n{\r\n\tfor( int i = 0; i < 127; ++i )\r\n\t{\r\n\t\tCARDStat stat;\r\n\t\ts32\tresult = CARDGetStatus( 0, i, &stat );\r\n\t\tif( result == CARD_RESULT_READY )\r\n\t\t{\r\n\t\t\tFile* new_file;\r\n\r\n\t\t\tnew_file = new File( 0, this );\r\n\t\t\tstrcpy( new_file->m_Filename, (char*)stat.fileName );\r\n\t\t\tnew_file->m_Size = stat.length;\r\n\t\t\t\r\n\t\t\tnew_file->m_Attribs = 0;\r\n\t\t\tnew_file->m_Attribs |= File::mATTRIB_READABLE;\r\n\t\t\tnew_file->m_Attribs |= File::mATTRIB_WRITEABLE;\r\n\r\n\t\t\ts_convert_time(stat.time,&new_file->m_Modified);\r\n\t\t\t\r\n//\t\t\tif( file_table[i].AttrFile & sceMcFileAttrExecutable )\r\n//\t\t\t{\r\n//\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_EXECUTABLE;\r\n//\t\t\t}\r\n//\t\t\tif( file_table[i].AttrFile & sceMcFileAttrDupProhibit )\r\n//\t\t\t{\r\n//\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_DUP_PROHIBITED;\r\n//\t\t\t}\r\n//\t\t\tif( file_table[i].AttrFile & sceMcFileAttrSubdir )\r\n//\t\t\t{\r\n//\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_DIRECTORY;\r\n//\t\t\t}\r\n//\t\t\tif( file_table[i].AttrFile & sceMcFileAttrClosed )\r\n//\t\t\t{\r\n//\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_CLOSED;\r\n//\t\t\t}\r\n//\t\t\tif( file_table[i].AttrFile & sceMcFileAttrPDAExec )\r\n//\t\t\t{\r\n//\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_PDA_APP;\r\n//\t\t\t}\r\n//\t\t\tif( file_table[i].AttrFile & sceMcFileAttrPS1 )\r\n//\t\t\t{\r\n//\t\t\t\tnew_file->m_Attribs |= File::mATTRIB_PS1_FILE;\r\n//\t\t\t}\r\n//\t\t\tnew_file->m_Created.m_Seconds = file_table[i]._Create.Sec;\r\n//\t\t\tnew_file->m_Created.m_Minutes = file_table[i]._Create.Min;\r\n//\t\t\tnew_file->m_Created.m_Hour = file_table[i]._Create.Hour;\r\n//\t\t\tnew_file->m_Created.m_Day = file_table[i]._Create.Day;\r\n//\t\t\tnew_file->m_Created.m_Month = file_table[i]._Create.Month;\r\n//\t\t\tnew_file->m_Created.m_Year = file_table[i]._Create.Year;\r\n\r\n//\t\t\tnew_file->m_Modified.m_Seconds = file_table[i]._Modify.Sec;\r\n//\t\t\tnew_file->m_Modified.m_Minutes = file_table[i]._Modify.Min;\r\n//\t\t\tnew_file->m_Modified.m_Hour = file_table[i]._Modify.Hour;\r\n//\t\t\tnew_file->m_Modified.m_Day = file_table[i]._Modify.Day;\r\n//\t\t\tnew_file->m_Modified.m_Month = file_table[i]._Modify.Month;\r\n//\t\t\tnew_file->m_Modified.m_Year = file_table[i]._Modify.Year;\r\n\r\n\t\t\tfile_list.AddToTail( new_file );\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Card::CountFilesLeft()\r\n{\r\n\tint NumFiles=0;\r\n\tfor( int i = 0; i < 127; ++i )\r\n\t{\r\n\t\tCARDStat stat;\r\n\t\ts32\tresult = CARDGetStatus( 0, i, &stat );\r\n\t\tif( result == CARD_RESULT_READY )\r\n\t\t{\r\n\t\t\t++NumFiles;\r\n\t\t}\r\n\t}\r\n\treturn 127-NumFiles;\r\n}\r\n\r\nFile::File( int fd, Card* card ) : Lst::Node< File > ( this ), m_fd( fd ), m_card( card )\r\n{\r\n\tm_need_to_flush=false;\r\n\tm_write_offset=0;\r\n\tmp_write_buffer=NULL;\r\n\t\r\n\tm_read_offset=0;\r\n\tmp_read_buffer=NULL;\r\n}\r\n\t\t\r\nFile::~File()\r\n{\r\n\tDbg_MsgAssert(!m_need_to_flush,(\"Closed mem card file when it needed flushing\"));\r\n\t\r\n\tif (mp_write_buffer)\r\n\t{\r\n\t\tMem::Free(mp_write_buffer);\r\n\t\tmp_write_buffer=NULL;\r\n\t}\t\r\n\tif (mp_read_buffer)\r\n\t{\r\n\t\tMem::Free(mp_read_buffer);\r\n\t\tmp_read_buffer=NULL;\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint File::Seek( int offset, FilePointerBase base )\r\n{\r\n\tm_read_offset=offset;\r\n\t// Force a reload of the read buffer by deleting it.\r\n\tif (mp_read_buffer)\r\n\t{\r\n\t\tMem::Free(mp_read_buffer);\r\n\t\tmp_read_buffer=NULL;\r\n\t}\r\n\t\t\r\n\tint result = 0;\r\n\r\n\tswitch( base )\r\n\t{\r\n\t\tcase BASE_START:\r\n\t\t\tbreak;\r\n\t\tcase BASE_CURRENT:\r\n\t\t\tDbg_MsgAssert( 0, ( \"Not supported\" ));\r\n\t\t\tbreak;\r\n\t\tcase BASE_END:\r\n\t\t{\r\n\t\t\tCARDStat\tstatus;\r\n\t\t\ts32\t\t\tstatus_result = CARDGetStatus( m_card->GetSlot(), m_file_number, &status );\r\n\t\t\tif( status_result == CARD_RESULT_READY )\r\n\t\t\t{\r\n\t\t\t\tresult = status.length - offset;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0,( \"Invalid FilePointerBase\\n\" ));\r\n\t\t\treturn 0;\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool File::Flush( void )\r\n{\r\n\t// The FlushFileBuffers() is pretty strict about what types of files wmay be flushed,\r\n\t// whereas the PS2 equivalent doesn't really care. Just return a positive response always,\r\n\t// no critical stuff predicated on this return anway.\r\n\t\r\n\tif (!m_need_to_flush)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tint num_bytes_to_write=m_write_offset%m_card->m_sector_size;\r\n\tDbg_MsgAssert(num_bytes_to_write,(\"Got zero num_bytes_to_write in File::Flush\"));\r\n\t\r\n\tDbg_MsgAssert(mp_write_buffer,(\"NULL mp_write_buffer\"));\r\n\tmemset(mp_write_buffer+num_bytes_to_write,0,m_card->m_sector_size-num_bytes_to_write);\r\n\t\r\n\tint file_offset=m_write_offset-num_bytes_to_write;\r\n\t\r\n\tDbg_MsgAssert(file_offset%m_card->m_sector_size == 0,(\"Bad file_offset\"));\r\n\ts32 write_result = CARDWrite( &m_file_info, mp_write_buffer, m_card->m_sector_size, file_offset );\r\n\tif ( write_result != CARD_RESULT_READY )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t\r\n\tm_need_to_flush=false;\r\n\tm_write_offset=0;\r\n\tif (mp_write_buffer)\r\n\t{\r\n\t\tMem::Free(mp_write_buffer);\r\n\t\tmp_write_buffer=NULL;\r\n\t}\t\r\n\t\r\n\treturn true;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint\tFile::Write( void* data, int len )\r\n{\r\n\tDbg_MsgAssert(data,(\"NULL data\"));\r\n\tDbg_Assert( len > 0 );\r\n\tDbg_Assert( m_card->m_sector_size > 0 );\r\n\r\n\tif (!mp_write_buffer)\r\n\t{\r\n\t\t// Grab a sector-sized chunk of memory, ensuring it is 32-byte aligned.\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\t\tmp_write_buffer = (uint8*)Mem::Malloc(m_card->m_sector_size);\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t}\r\n\tDbg_MsgAssert(mp_write_buffer,(\"NULL mp_write_buffer\"));\r\n\t\r\n\t// Ensure the buffer address is 32 byte aligned.\r\n\tDbg_MsgAssert((((unsigned int)mp_write_buffer ) & 31 ) == 0, ( \"file write buffer must be 32 byte aligned\" ));\r\n\r\n\tm_need_to_flush=false;\r\n\r\n\tint\tbytes_remaining_to_write = len;\r\n\tunsigned char*\tp_source_buffer\t= (unsigned char*)data;\r\n\r\n\tint write_buffer_sector_offset=m_write_offset%m_card->m_sector_size;\r\n\tint write_buffer_left=m_card->m_sector_size - write_buffer_sector_offset;\r\n\t\t\r\n\tif (bytes_remaining_to_write < write_buffer_left)\r\n\t{\r\n\t\tmemcpy( mp_write_buffer+write_buffer_sector_offset, p_source_buffer, bytes_remaining_to_write);\r\n\t\tm_write_offset+=bytes_remaining_to_write;\r\n\t\tm_need_to_flush=true;\r\n\t\treturn len;\r\n\t}\r\n\r\n\tint file_offset=m_write_offset-write_buffer_sector_offset;\r\n\r\n\tif (write_buffer_left)\r\n\t{\r\n\t\tDbg_MsgAssert(write_buffer_sector_offset+write_buffer_left==m_card->m_sector_size,(\"Oops\"));\r\n\t\tmemcpy( mp_write_buffer+write_buffer_sector_offset, p_source_buffer, write_buffer_left);\r\n\t\tm_write_offset+=write_buffer_left;\r\n\t\tbytes_remaining_to_write-=write_buffer_left;\r\n\t\tp_source_buffer+=write_buffer_left;\r\n\t\t\r\n\t\tDbg_MsgAssert(file_offset%m_card->m_sector_size == 0,(\"Bad file_offset\"));\r\n\t\ts32 write_result = CARDWrite( &m_file_info, mp_write_buffer, m_card->m_sector_size, file_offset );\r\n\t\tif ( write_result != CARD_RESULT_READY )\r\n\t\t{\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\tfile_offset+=m_card->m_sector_size;\r\n\t\tm_need_to_flush=false;\r\n\t}\r\n\r\n\twhile (bytes_remaining_to_write)\r\n\t{\r\n\t\tif (bytes_remaining_to_write >= m_card->m_sector_size)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(m_write_offset%m_card->m_sector_size == 0,(\"Oops\"));\r\n\t\t\t\r\n\t\t\tmemcpy( mp_write_buffer, p_source_buffer, m_card->m_sector_size);\r\n\t\t\tm_write_offset+=m_card->m_sector_size;\r\n\t\t\tbytes_remaining_to_write-=m_card->m_sector_size;\r\n\t\t\tp_source_buffer+=m_card->m_sector_size;\r\n\t\t\t\r\n\t\t\tDbg_MsgAssert(file_offset%m_card->m_sector_size == 0,(\"Bad file_offset\"));\r\n\t\t\ts32 write_result = CARDWrite( &m_file_info, mp_write_buffer, m_card->m_sector_size, file_offset );\r\n\t\t\tif ( write_result != CARD_RESULT_READY )\r\n\t\t\t{\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t\tfile_offset+=m_card->m_sector_size;\r\n\t\t\tm_need_to_flush=false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmemcpy( mp_write_buffer, p_source_buffer, bytes_remaining_to_write);\r\n\t\t\tmemset( mp_write_buffer+bytes_remaining_to_write, 0, m_card->m_sector_size-bytes_remaining_to_write);\r\n\t\t\t\r\n\t\t\tm_write_offset+=bytes_remaining_to_write;\r\n\t\t\tbytes_remaining_to_write=0;\r\n\t\t\tm_need_to_flush=true;\r\n\t\t}\r\n\t}\r\n\treturn len;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint\tFile::Read( void* buff, int len )\r\n{\r\n\tDbg_Assert( len > 0 );\r\n\tDbg_Assert( m_card->m_sector_size > 0 );\r\n\r\n\tint read_buffer_sector_offset=m_read_offset%m_card->m_sector_size;\r\n\tint read_buffer_left=m_card->m_sector_size - read_buffer_sector_offset;\r\n\r\n\tif (!mp_read_buffer)\r\n\t{\r\n\t\t// Similar process to write, in that we read 1 sector at a time. So grab a sector-sized chunk of memory,\r\n\t\t// ensuring it is 32-byte aligned.\r\n\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\t\tmp_read_buffer = (uint8*)Mem::Malloc(m_card->m_sector_size);\r\n\t\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\t\tMem::Manager::sHandle().PopContext();\r\n\t\t\r\n\t\tDbg_MsgAssert(mp_read_buffer,(\"NULL mp_read_buffer\"));\r\n\t\t\r\n\t\t// Ensure the buffer address is 32 byte aligned.\r\n\t\tDbg_MsgAssert((((unsigned int)mp_read_buffer ) & 31 ) == 0, ( \"file read buffer must be 32 byte aligned\" ));\r\n\t\t\r\n\t\t// Also ensure the buffer is a multiple of CARD_READ_SIZE (should be, since this is smaller than the smallest sector).\r\n\t\tDbg_MsgAssert(( m_card->m_sector_size & ( CARD_READ_SIZE - 1 )) == 0, ( \"read buffer must be multiple of CARD_READ_SIZE\" ));\r\n\t\t\r\n\r\n\t\tint file_offset=m_read_offset-read_buffer_sector_offset;\r\n\t\tDbg_MsgAssert(file_offset%m_card->m_sector_size == 0,(\"Bad file_offset\"));\r\n\t\ts32 read_result = CARDRead( &m_file_info, mp_read_buffer, m_card->m_sector_size, file_offset);\r\n\t\tif (read_result != CARD_RESULT_READY)\r\n\t\t{\r\n\t\t\treturn 0;\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (read_buffer_sector_offset==0)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(m_read_offset%m_card->m_sector_size == 0,(\"Bad m_read_offset\"));\r\n\t\t\ts32 read_result = CARDRead( &m_file_info, mp_read_buffer, m_card->m_sector_size, m_read_offset);\r\n\t\t\tif (read_result != CARD_RESULT_READY)\r\n\t\t\t{\r\n\t\t\t\treturn 0;\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t}\r\n\r\n\r\n\tint\tbytes_remaining_to_read\t= len;\r\n\tunsigned char*\tp_dest_buffer\t= (unsigned char*)buff;\r\n\r\n\twhile (true)\r\n\t{\r\n\t\tif (bytes_remaining_to_read < read_buffer_left)\r\n\t\t{\r\n\t\t\tif (bytes_remaining_to_read)\r\n\t\t\t{\r\n\t\t\t\t// The required data is all in the buffer already so copy it out and return.\r\n\t\t\t\tmemcpy(p_dest_buffer,mp_read_buffer+read_buffer_sector_offset,bytes_remaining_to_read);\r\n\t\t\t\tm_read_offset+=bytes_remaining_to_read;\r\n\t\t\t}\t\r\n\t\t\treturn len;\r\n\t\t}\r\n\t\t\t\r\n\t\t// Copy out what is left in the buffer\r\n\t\tmemcpy(p_dest_buffer,mp_read_buffer+read_buffer_sector_offset,read_buffer_left);\r\n\t\tp_dest_buffer+=read_buffer_left;\r\n\t\tm_read_offset+=read_buffer_left;\r\n\t\tbytes_remaining_to_read-=read_buffer_left;\r\n\t\t\r\n\t\tif (bytes_remaining_to_read==0)\r\n\t\t{\r\n\t\t\treturn len;\r\n\t\t}\r\n\t\t\r\n\t\t\r\n\t\tDbg_MsgAssert(m_read_offset%m_card->m_sector_size == 0,(\"Bad m_read_offset\"));\r\n\t\ts32 read_result = CARDRead( &m_file_info, mp_read_buffer, m_card->m_sector_size, m_read_offset);\r\n\t\tif (read_result != CARD_RESULT_READY)\r\n\t\t{\r\n\t\t\treturn 0;\r\n\t\t}\t\r\n\t\t\t\r\n\t\tread_buffer_left=m_card->m_sector_size;\r\n\t\tread_buffer_sector_offset=0;\r\n\t}\r\n\t\t\t\r\n\treturn 0;\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nbool File::Close( void )\r\n{\r\n\ts32 close_result = CARDClose( &m_file_info );\r\n\tif( close_result == CARD_RESULT_READY )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Mc\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/Profiler.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2002 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSysLib (System Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSys\t\t\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tprofiler.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tProfiler class\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdio.h>\r\n#include <core/defines.h>\r\n#include <sys/sys.h>\r\n#include <sys/timer.h>\r\n#include <sys/profiler.h>\r\n\r\n#ifndef __PLAT_WN32__\r\n#include <gfx/gfxman.h>\r\n#endif // __PLAT_WN32__\r\n\r\n#ifdef\t__PLAT_NGPS__\t\r\n#include <gfx/ngps/nx/line.h>\r\n#endif\r\n#ifdef\t__PLAT_NGC__\t\r\n#include <sys\\ngc\\p_gx.h>\r\n#include <sys\\ngc\\p_prim.h>\r\n#include <sys\\ngc\\p_camera.h>\r\n#endif\r\n\r\n\r\n\r\n#ifdef\t\t__USE_PROFILER__\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Sys\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nTmr::MicroSeconds\tProfiler::s_base_time[ 2 ];\r\nuint32\t\t\t\tProfiler::s_default_color = 0x00ff0000;\r\nint\t\t\t\t\tProfiler::s_flip = 0;\r\n#ifdef\t__PLAT_NGC__\t\r\nbool\t\t\t\tProfiler::s_enabled = true;\r\nbool\t\t\t\tProfiler::s_active = true;\r\n#else\r\nbool\t\t\t\tProfiler::s_enabled = false;\r\nbool\t\t\t\tProfiler::s_active = false;\r\n#endif\r\nuint\t\t\t\tProfiler::s_vblanks;\r\nfloat\t\t\t\tProfiler::s_width;\r\nfloat\t\t\t\tProfiler::s_height;\r\nfloat \t\t\t\tProfiler::s_scale;\r\nfloat\t\t\t\tProfiler::s_left_x;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nProfiler* CPUProfiler;\t\t  \r\nProfiler* VUProfiler;\t\t  \r\nProfiler* DMAProfiler;\t\t  \r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tPrivate Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n\r\nProfiler::Profiler( uint line )\r\n{\r\n\tm_top_y = s_height * line;\r\n\tstart_new_frame();\t\t\t// just ensure everything points to something reasonable\r\n}\r\n\r\n/******************************************************************/\r\n\r\nProfiler::~Profiler( void )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n\r\nvoid\t\t\tbox(int x0,int y0, int x1, int y1, uint32 color)\r\n{\r\n#ifdef\t__PLAT_NGPS__\t\r\n\tNxPs2::BeginLines2D(0x80000000 + color);\r\n\tNxPs2::DrawLine2D(x0,y0,0, x1,y0,0);\r\n\tNxPs2::DrawLine2D(x1,y0,0, x1,y1,0);\r\n\tNxPs2::DrawLine2D(x1,y1,0, x0,y1,0);\r\n\tNxPs2::DrawLine2D(x0,y1,0, x0,y0,0);\r\n\tNxPs2::EndLines2D();\r\n#endif\r\n\r\n\r\n\r\n#ifdef\t__PLAT_NGC__\t\r\n//\tNsPrim::line ( (float)x0, (float)y0, (float)x1, (float)y0, (GXColor){(color>>0)&0xff,(color>>8)&0xff,(color>>16)&0xff,255} );\r\n//\tNsPrim::line ( (float)x1, (float)y0, (float)x1, (float)y1, (GXColor){(color>>0)&0xff,(color>>8)&0xff,(color>>16)&0xff,255} );\r\n//\tNsPrim::line ( (float)x1, (float)y1, (float)x0, (float)y1, (GXColor){(color>>0)&0xff,(color>>8)&0xff,(color>>16)&0xff,255} );\r\n//\tNsPrim::line ( (float)x0, (float)y1, (float)x0, (float)y0, (GXColor){(color>>0)&0xff,(color>>8)&0xff,(color>>16)&0xff,255} );\r\n\r\n\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){(color>>0)&0xff,(color>>8)&0xff,(color>>16)&0xff,255} );\r\n\r\n\t// Send coordinates.\r\n\tGX::Begin( GX_LINESTRIP, GX_VTXFMT0, 5 ); \r\n\t\tGX::Position3f32( (float)x0, (float)y0, -1.0f );\r\n\t\tGX::Position3f32( (float)x1, (float)y0, -1.0f );\r\n\t\tGX::Position3f32( (float)x1, (float)y1, -1.0f );\r\n\t\tGX::Position3f32( (float)x0, (float)y1, -1.0f );\r\n\t\tGX::Position3f32( (float)x0, (float)y0, -1.0f );\r\n\tGX::End();\r\n\r\n#endif\r\n\r\n\r\n}\r\n\r\nvoid\t\t\tline(int x0,int y0, int x1, int y1, uint32 color)\r\n{\r\n#ifdef\t__PLAT_NGPS__\t\r\n\tNxPs2::BeginLines2D(0x80000000 + color);\r\n\tNxPs2::DrawLine2D(x0,y0,0, x1,y1,0);\r\n\tNxPs2::EndLines2D();\r\n#endif\r\n\r\n\r\n#ifdef\t__PLAT_NGC__\t\r\n//\tNsPrim::line ( (float)x0, (float)y0, (float)x1, (float)y1, (GXColor){(color>>0)&0xff,(color>>8)&0xff,(color>>16)&0xff,255} );\r\n\r\n\tGX::SetChanAmbColor( GX_COLOR0A0, (GXColor){(color>>0)&0xff,(color>>8)&0xff,(color>>16)&0xff,255} );\r\n\r\n\t// Send coordinates.\r\n\tGX::Begin( GX_LINES, GX_VTXFMT0, 2 ); \r\n\t\tGX::Position3f32( (float)x0, (float)y0, -1.0f );\r\n\t\tGX::Position3f32( (float)x1, (float)y1, -1.0f );\r\n\tGX::End();\r\n\r\n#endif\r\n\r\n}\r\n\r\n/******************************************************************/\r\n\r\nvoid\t\t\tbox(float x0,float y0, float x1, float y1, uint32 color)\r\n{\r\n\tbox ((int)x0,(int)y0,(int)x1,(int)y1, color);\r\n}\r\n\r\n\r\n/******************************************************************/\r\n\r\nvoid Profiler::start_new_frame( void )\r\n{\r\n\tmp_current_context_list \t= m_context_list[ s_flip ];\r\n\tmpp_current_context_stack \t= m_context_stack[ s_flip ];\r\n\tmp_current_context \t\t\t= NULL;\t\t\t\t\t\t\t\t// nothing has been pushed yet\r\n\tmp_current_context_count\t= &m_context_count[ s_flip ];\r\n\tm_context_stack_depth\t\t= 0;\t\t\t\t\t\t\t\t// nothing on stack\r\n\tm_next_context\t\t\t\t= 0;\t\t\t\t\t\t\t\t// start of list (index into mp_current_context_list)\r\n\tm_acc\t\t\t\t\t\t= false;\r\n\tmp_acc_context\t\t\t\t= NULL;\r\n}\r\n\r\n/******************************************************************/\r\n\r\nvoid Profiler::render()\r\n{\r\n\tif ( s_active )\r\n\t{\r\n\t\t/* We draw from the buffer that's not being updated this frame */\r\n\t\tint drawFlip = s_flip ^ 1;\r\n\t\t\r\n\t\tSProfileContext *p_context = m_context_list[ drawFlip ];\r\n\t\tTmr::MicroSeconds\tbase_time = s_base_time[ drawFlip ];\r\n\t\tint n = m_context_count[ drawFlip ];\r\n\t\twhile ( n--)\r\n\t\t{\r\n\t\t\tfloat startx \t= ( (uint32)(p_context->m_start_time - base_time) ) * s_scale;\r\n\t\t\tfloat endx \t\t= ( (uint32)(p_context->m_end_time - base_time) ) * s_scale;\r\n\t\t\tfloat top_y \t= m_top_y +( p_context->m_depth)* (s_height+2);\r\n\t\t\tbox((s_left_x+startx),(top_y),  (s_left_x+endx),( top_y + s_height) , p_context->m_color);   \r\n\t\t\tp_context++;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid Profiler::PushContext( uint32 color, bool acc )\r\n{\r\n\t\r\n\tif( s_active )\r\n\t{\r\n\t\tif ( acc && mp_acc_context )\r\n\t\t{\r\n\t\t\t// Want to accumulate to last context.\r\n\t\t\tm_acc_time = Tmr::GetTimeInUSeconds(); \r\n\t\t\tm_acc_first = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// if we have a current context, then push it\r\n\t\t\tif (mp_current_context)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(m_context_stack_depth < PROF_MAX_LEVELS,(\"Context stack overflow\"));\r\n\t\t\t\tmpp_current_context_stack[m_context_stack_depth++] = mp_current_context;\r\n\t\t\t}\r\n\r\n\t\t\t// get a new context from the list\r\n\t\t\tDbg_MsgAssert(m_next_context < PROF_MAX_CONTEXTS,(\"Context heap overflow\"));\r\n\t\t\tmp_current_context = &mp_current_context_list[m_next_context++];\r\n\t\t\t// and fill it in with the start time, depth and color\r\n\t\t\t// (the end time is filled in by the Pop) \r\n\t\t\tmp_current_context->m_start_time = Tmr::GetTimeInUSeconds();\r\n\t\t\tmp_current_context->m_depth = m_context_stack_depth;\r\n\t\t\tmp_current_context->m_color = color;\r\n\t\t\tif ( acc )\r\n\t\t\t{\r\n\t\t\t\tmp_acc_context = mp_current_context;\r\n\t\t\t\tm_acc_first = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_acc = acc;\r\n\t}\r\n}\r\n\r\n\r\nvoid Profiler::PushContext( uint8 r, uint8 g, uint8 b, bool acc )\r\n{\r\n\tuint32 color = (b<<16)+(g<<8)+(r);\r\n\tPushContext(color, acc);\r\n}\r\n\r\n/******************************************************************/\r\n\r\nvoid Profiler::PopContext( void )\r\n{\r\n\tif( s_active)\r\n\t{\r\n\t\tif ( m_acc && !m_acc_first )\r\n\t\t{\r\n\t\t\tmp_acc_context->m_end_time += Tmr::GetTimeInUSeconds() - m_acc_time;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// set time on the current context\t\t\r\n\t\t\tDbg_MsgAssert(mp_current_context,(\"Popped one more profiler context than we pushed\"));\r\n\r\n\t\t\tmp_current_context->m_end_time = Tmr::GetTimeInUSeconds();\r\n\r\n\t\t\tif ( ! m_context_stack_depth)\r\n\t\t\t{\r\n\t\t\t\t// nothing left on stack, so set current context to NULL\r\n\t\t\t\tmp_current_context = NULL;\r\n\t\t\t\t// update the count of valid contexts\r\n\t\t\t\t*mp_current_context_count = m_next_context;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// get the last context pushed on the stack\r\n\t\t\t\tmp_current_context = mpp_current_context_stack[--m_context_stack_depth]; \r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n\r\nvoid Profiler::sSetUp( uint vblanks )\r\n{\r\n\t\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ProfilerHeap());\r\n\t\r\n\ts_width = 640 * 0.8;\r\n\ts_height = 448 * 0.01;\r\n\ts_left_x = 640 * 0.1;\r\n\ts_vblanks = vblanks;\r\n\ts_scale = ( s_width * 60 ) / ( 1000000 * s_vblanks );\r\n\r\n\tVUProfiler  =  new Profiler( 84 );\r\n\tDMAProfiler =  new Profiler( 86 );\r\n\tCPUProfiler =  new Profiler( 88 );\r\n\t\r\n#ifdef\t__PLAT_NGC__\t\r\n\ts_active = true;\r\n\ts_enabled = true;\r\n#else\r\n\ts_active = false;\r\n\ts_enabled = false;\r\n#endif\r\n\t\r\n\tMem::Manager::sHandle().PopContext();\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n    \r\nvoid Profiler::sCloseDown( void )\r\n{\r\n\tdelete VUProfiler;\r\n\tdelete DMAProfiler;\r\n\tdelete CPUProfiler;\r\n\tVUProfiler = NULL;\r\n\tDMAProfiler = NULL;\r\n\tCPUProfiler = NULL;\r\n}\r\n\r\n/******************************************************************/\r\n    \r\nvoid Profiler::sRender( void )\r\n{\r\n\tif (s_active && s_enabled)\r\n\t{\r\n#ifdef\t__PLAT_NGC__\t\r\n\t\tNsCamera cam;\r\n\t\tcam.orthographic( 0, 0, 640, 448 );\r\n\t\tcam.begin();\r\n\t\tGX::SetZMode( GX_FALSE, GX_ALWAYS, GX_TRUE );\r\n\r\n\t\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );\r\n\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\r\n\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t   GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\r\n\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC,\r\n\t\t\t\t\t\t\t\t\t\t   GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\r\n\t\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n\r\n\t\tGX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n#endif\t// __PLAT_NGC__\t\r\n\r\n\t\tfor (uint x = 0; x<s_vblanks+1;x++)\r\n\t\t{\r\n\t\t\tline((int)(s_left_x + x * s_width / s_vblanks), 370,   \r\n\t\t\t\t (int)(s_left_x + x * s_width / s_vblanks), 410, 0x800080);   \r\n\t\t\t\r\n\t\t}\r\n\t\r\n\t\tVUProfiler->render();\r\n\t\tDMAProfiler->render();\r\n\t\tCPUProfiler->render();\r\n\t\r\n#ifdef\t__PLAT_NGC__\t\r\n\t\tcam.end();\r\n#endif\t// __PLAT_NGC__\t\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n\r\nvoid Profiler::sStartFrame( void )\r\n{\r\n\t\r\n\r\n\ts_active = s_enabled;\r\n\ts_flip ^= 1;\r\n\ts_base_time[ s_flip ] = Tmr::GetTimeInUSeconds();\r\n\tCPUProfiler->start_new_frame();\r\n\tVUProfiler->start_new_frame();\r\n\tDMAProfiler->start_new_frame();\r\n}\r\n/******************************************************************/\r\n\r\nvoid Profiler::sEndFrame( void )\r\n{\r\n\r\n}\r\n\r\n/******************************************************************/\r\n\r\nvoid Profiler::sEnable( void )\r\n{\r\n\ts_enabled = true;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n\r\nvoid Profiler::sDisable( void )\r\n{\r\n\ts_enabled = false;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\t\tRender_Profiler()\t\t\t// easy function to allow it to be rendered from simpler code \r\n{\r\n\tProfiler::sRender();\r\n}\r\n    \r\n} // namespace Sys\r\n\t\t\t\t  \r\n\r\n#endif\t//\t\t__USE_PROFILER__\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/Profiler.h",
    "content": "\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSysLib (System Library)\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSys  \t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsys/profiler.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated: \t\t11/15/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __SYS_PROFILER_H\r\n#define __SYS_PROFILER_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n#include <core/list.h>\r\n#include <sys/timer.h>\r\n\r\n#ifndef\t__SYS_MEM_MEMPTR_H\r\n#include <sys/mem/memptr.h>\r\n#endif\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __PLAT_WN32__\r\n\r\n#ifndef\t\t__NOPT_FINAL__\r\n#ifdef\t\t__PLAT_NGPS__\t\r\n#define\t\t__USE_PROFILER__\t\t\t// use this one to turn profiling on/off\r\n#endif\t\t//\t__PLAT_NGPS__\t\r\n\r\n\r\n#define\tPROF_MAX_LEVELS\t\t16\t\t \t\t\t// depth of profiler stack\r\n#define\tPROF_MAX_CONTEXTS\t512\t\t\t\t// number of push/pops possible\r\n\r\nnamespace Sys\r\n{\r\n\r\n\r\nvoid\t\tRender_Profiler();\t\t\t// easy function to allow it to be rendered from simpler code \r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// a profiler context represtens a single atomic measurement of time\r\n// a simgle block of color on the profiler bar, at a particular level\r\nstruct  SProfileContext \r\n{\r\n\tuint32\t\t\t\t\t\t\tm_color;\t\t\t\t// color of this context\r\n\tint\t\t\t\t\t\t\t\tm_depth;\t\t\t\t// level in the stack\r\n\tTmr::MicroSeconds\t\t\t\tm_start_time;\t\t\t// when it started\r\n\tTmr::MicroSeconds\t\t\t\tm_end_time;\t\t\t\t// when it ended\r\n};\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  Profiler  : public Spt::Class\r\n{\r\n\t\r\n\r\npublic:\r\n\r\n\r\n#ifdef\t\t__USE_PROFILER__\r\n\tvoid\t\t\t\t\t\tPushContext( uint8 r, uint8 g, uint8 b, bool acc = false );\r\n\tvoid\t\t\t\t\t\tPushContext( uint32 rgba, bool acc = false);\r\n\tvoid\t\t\t\t\t\tPopContext( void );\r\n\t\t\r\n\tstatic void\t\t\t\t\tsSetUp( uint vblanks );\r\n\tstatic void\t\t\t\t\tsCloseDown( void );\r\n\tstatic void\t\t\t\t\tsRender( void );\r\n\r\n\tstatic void\t\t\t\t\tsEnable( void );\r\n\tstatic void\t\t\t\t\tsDisable( void );\r\n\tstatic void\t\t\t\t\tsStartFrame( void );\r\n\tstatic void\t\t\t\t\tsEndFrame( void );\r\n#else\r\n\tinline void\t\t\t\t\tPushContext( uint8 r,\r\n\t\t\t\t\t\t\t\t\t\t\t uint8 g,\r\n\t\t\t\t\t\t\t\t\t\t\t uint8 b,\r\n\t\t\t\t\t\t\t\t\t\t\t bool acc ){}\r\n\tinline void\t\t\t\t\tPushContext( uint32 rgba,\r\n\t\t\t\t\t\t\t\t\t\t\t bool acc ){}\r\n\tinline void\t\t\t\t\tPopContext( void ){}\r\n\t\t\r\n\tinline  static void\t\t\t\t\t\tsSetUp( uint vblanks ){}\r\n\tinline  static  void\t\t\t\t\tsCloseDown( void ){}\r\n\tinline  static  void\t\t\t\t\tsRender( void ){}\r\n\r\n\tinline  static  void\t\t\t\t\tsEnable( void ){}\r\n\tinline  static  void\t\t\t\t\tsDisable( void ){}\r\n\tinline  static  void\t\t\t\t\tsStartFrame( void ){}\r\n\tinline  static  void\t\t\t\t\tsEndFrame( void ){}\r\n#endif\t\r\n\r\n\t\t\t\t\t\t\t\t~Profiler( void );\t\t \r\n\r\nprivate:\r\n#ifdef\t\t__USE_PROFILER__\r\n\t\t\t\t\t\t\t\tProfiler( uint line );\r\n\t\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\t\t\trender( void );\r\n\tvoid\t\t\t\t\t\tstart_new_frame( void );\r\n\tSProfileContext\t\t\t\tm_context_list[ 2 ][PROF_MAX_CONTEXTS];\t\t// a flat array of all contexts\r\n\tSProfileContext*\t\t\tmp_current_context_list;\t\t\t\t\t// pointer to one of the above, for speed\r\n\t\r\n\tSProfileContext\t*\t\t\tm_context_stack[ 2 ][PROF_MAX_LEVELS];\t\t// stack of pushed contexts (usually max 3 deep)\r\n\tSProfileContext**\t\t\tmpp_current_context_stack;\t\t\t\t\t// pointer to one of the above, for speed\r\n\t\r\n\tint\t\t\t\t\t\t\tm_context_count[2];\r\n\tint\t*\t\t\t\t\t\tmp_current_context_count;\r\n\t\r\n\tSProfileContext*\t\t\tmp_current_context;\t\t\t\t\t\t\t// current entry in context list (will need to pop back....\r\n\tint\t\t\t\t\t\t\tm_context_stack_depth;\t\t\t\t\t\t// depth in stack (index into m_context_stack[])\r\n\tint\t\t\t\t\t\t\tm_next_context;\t\t\t\t\t\t\t\t// index into array\r\n\t\r\n\tfloat\t\t\t\t\t\tm_top_y;\t\t\t\t\t\t\t\t// screen coord of top of profiler\r\n\t\r\n\tstatic Tmr::MicroSeconds\ts_base_time[2];\r\n\tstatic int\t\t\t\t\ts_flip;\r\n\tstatic bool\t\t\t\t\ts_enabled;\r\n\tstatic bool\t\t\t\t\ts_active;\r\n\r\n\r\n\tstatic uint\t\t\t\t\ts_vblanks;\r\n\tstatic float\t\t\t\ts_width;\r\n\tstatic float\t\t\t\ts_height;\r\n\tstatic float \t\t\t\ts_scale;\r\n\t\r\n\tstatic float\t\t\t\ts_left_x;\r\n\r\n\tstatic uint32\t\t\t\ts_default_color;\r\n\tstatic Profiler*\t\t\ts_cpu_profiler;\r\n\r\n\tbool\t\t\t\t\t\tm_acc;\t\t\t\t\t// Accumulation?\r\n\tbool\t\t\t\t\t\tm_acc_first;\r\n\tTmr::MicroSeconds\t\t\tm_acc_time;\t\t\t\t// Accumulation time.\r\n\tSProfileContext*\t\t\tmp_acc_context;\r\n#endif\r\n};\r\n\r\n/*****************************s************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern Profiler*\tCPUProfiler;\r\nextern Profiler*\tVUProfiler;\r\nextern Profiler*\tDMAProfiler;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n} // namespace Sys\r\n\r\n#endif\r\n#endif\t// __PLAT_WN32__\r\n#endif // __SYS_PROFILER_H\r\n\r\n"
  },
  {
    "path": "Code/Sys/Replay/NGC/p_replay.cpp",
    "content": "#if 0\r\n#include <sys/replay/replay.h>\r\n#include <sys/ngc/p_aram.h>\r\n#include <sys/ngc/p_dma.h>\r\n\r\n#define MAX_BUFFER (20*1024)\r\n#define MAX_FILL_BUFFER (8*1024)\r\n\r\nnamespace Replay\r\n{\r\n\r\n// Must be a multiple of REPLAY_BUFFER_CHUNK_SIZE\r\n#define REPLAY_BUFFER_SIZE 1048576\r\n//#define REPLAY_BUFFER_SIZE ( REPLAY_BUFFER_CHUNK_SIZE * 96 )\r\n//#define REPLAY_BUFFER_SIZE (20480*4)\r\n\r\nstatic uint32 sp_buffer=0;\r\n\r\n// Allocates the big buffer for storing replays. Never gets deallocated. (Currently)\r\nvoid AllocateBuffer()\r\n{\r\n\tif (sp_buffer)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n//\tsp_buffer=(uint8*)Mem::Malloc(REPLAY_BUFFER_SIZE);\r\n\tsp_buffer = NsARAM::alloc( REPLAY_BUFFER_SIZE );\r\n\tDbg_MsgAssert(sp_buffer,(\"Could not allocate replay buffer\"));\r\n}\r\n\r\nvoid DeallocateBuffer()\r\n{\r\n\tif (sp_buffer)\r\n\t{\r\n\t\tNsARAM::free( sp_buffer );\r\n\t\tsp_buffer=0;\r\n\t}\r\n}\r\n\r\nuint32 GetBufferSize()\r\n{\r\n\treturn REPLAY_BUFFER_SIZE;\r\n}\r\n\r\nbool BufferAllocated()\r\n{\r\n\tif (sp_buffer)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\t\r\n// Reads numBytes out of the buffer starting at offset bufferOffset, into p_dest.\r\n// Asserts if there are not enough source bytes.\r\nvoid ReadFromBuffer(uint8 *p_dest, int bufferOffset, int numBytes)\r\n{\r\n//\tOSReport( \"READ: 0x%08x - %d bytes\\n\", bufferOffset, numBytes );\r\n\tDbg_MsgAssert(sp_buffer,(\"Replay buffer has not been allocated\"));\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest sent to Replay::Read()\"));\r\n\tDbg_MsgAssert(bufferOffset>=0 && bufferOffset<REPLAY_BUFFER_SIZE,(\"Bad bufferOffset of %d sent to Read()\",bufferOffset));\r\n\tDbg_MsgAssert(bufferOffset+numBytes<=REPLAY_BUFFER_SIZE,(\"Requested Read() goes past the end of the buffer:\\nbufferOffset=%d numBytes=%d REPLAY_BUFFER_SIZE=%d\",bufferOffset,numBytes,REPLAY_BUFFER_SIZE));\r\n\r\n//\tmemcpy(p_dest,sp_buffer+bufferOffset,numBytes);\r\n\r\n\tchar buffer[MAX_BUFFER] __attribute__ (( aligned( 32 )));\r\n\tint aligned_off = bufferOffset & 0xffffffe0;\r\n\tint aligned_size = ( ( ( bufferOffset + numBytes ) - aligned_off ) + 31 ) & 0xffffffe0;\r\n\r\n\tif ( aligned_size > MAX_BUFFER )\r\n\t{\r\n\t\tOSReport( \"Transfer too large: %d - max = %d\\n\", aligned_size, MAX_BUFFER );\r\n\t\twhile (1 == 1);\r\n\t}\r\n\r\n\tNsDMA::toMRAM( buffer, sp_buffer+aligned_off, aligned_size );\r\n\tmemcpy( p_dest, &buffer[bufferOffset-aligned_off], numBytes );\r\n}\r\n\r\n// Writes numBytes into the buffer. Asserts if there is not enough space.\r\nvoid WriteIntoBuffer(uint8 *p_source, int bufferOffset, int numBytes)\r\n{\r\n//\tOSReport( \"WRITE: 0x%08x - %d bytes\\n\", bufferOffset, numBytes );\r\n\r\n\tDbg_MsgAssert(sp_buffer,(\"Replay buffer has not been allocated\"));\r\n\tDbg_MsgAssert(p_source,(\"NULL p_source sent to Replay::Write()\"));\r\n\tDbg_MsgAssert(bufferOffset>=0 && bufferOffset<REPLAY_BUFFER_SIZE,(\"Bad bufferOffset of %d sent to Write()\",bufferOffset));\r\n\tDbg_MsgAssert(bufferOffset+numBytes<=REPLAY_BUFFER_SIZE,(\"Requested Write() goes past the end of the buffer:\\nbufferOffset=%d numBytes=%d REPLAY_BUFFER_SIZE=%d\",bufferOffset,numBytes,REPLAY_BUFFER_SIZE));\r\n\t\r\n//\tmemcpy(sp_buffer+bufferOffset,p_source,numBytes);\r\n\t\r\n\t// First, we read what's in ARAM to MRAM, then copy our data in and DMA it back.\r\n\tchar buffer[MAX_BUFFER] __attribute__ (( aligned( 32 )));\r\n\tint aligned_off = bufferOffset & 0xffffffe0;\r\n\tint aligned_size = ( ( ( bufferOffset + numBytes ) - aligned_off ) + 31 ) & 0xffffffe0;\r\n\r\n\tif ( aligned_size > MAX_BUFFER )\r\n\t{\r\n\t\tOSReport( \"Transfer too large: %d - max = %d\\n\", aligned_size, MAX_BUFFER );\r\n\t\twhile (1 == 1);\r\n\t}\r\n\r\n\tNsDMA::toMRAM( buffer, sp_buffer+aligned_off, aligned_size );\r\n\tmemcpy( &buffer[bufferOffset-aligned_off], p_source, numBytes );\r\n\tNsDMA::toARAM( sp_buffer+aligned_off, buffer, aligned_size );\r\n}\r\n\r\nvoid FillBuffer(int bufferOffset, int numBytes, uint8 value)\r\n{\r\n//\tOSReport( \"FILL: 0x%08x - %d bytes, 0x%02x\\n\", bufferOffset, numBytes, value );\r\n\tDbg_MsgAssert(sp_buffer,(\"Replay buffer has not been allocated\"));\r\n\tDbg_MsgAssert(bufferOffset>=0 && bufferOffset<REPLAY_BUFFER_SIZE,(\"Bad bufferOffset of %d sent to FillBuffer()\",bufferOffset));\r\n\tDbg_MsgAssert(bufferOffset+numBytes<=REPLAY_BUFFER_SIZE,(\"Requested FillBuffer() goes past the end of the buffer:\\nbufferOffset=%d numBytes=%d REPLAY_BUFFER_SIZE=%d\",bufferOffset,numBytes,REPLAY_BUFFER_SIZE));\r\n\t\r\n//\tmemset(sp_buffer+bufferOffset,value,numBytes);\r\n\tint off = 0;\r\n\tint size = numBytes;\r\n\tuint8 buffer[MAX_FILL_BUFFER] __attribute__ (( aligned( 32 )));\r\n\tmemset(buffer,value,MAX_FILL_BUFFER);\r\n\r\n//\tif ( ( bufferOffset == 0 ) && ( ( numBytes % MAX_FILL_BUFFER ) == 0 ) )\r\n//\t{\r\n//\t\t// Fast version.\r\n//\t\twhile ( size > MAX_FILL_BUFFER )\r\n//\t\t{\r\n//\t\t\tNsDMA::toARAM( sp_buffer+bufferOffset+off, buffer, MAX_FILL_BUFFER );\r\n//\t\t\tsize -= MAX_FILL_BUFFER;\r\n//\t\t\toff += MAX_FILL_BUFFER;\r\n//\t\t}\r\n//\t}\r\n//\telse\r\n\t{\r\n\t\twhile ( size > MAX_FILL_BUFFER )\r\n\t\t{\r\n\t\t\tWriteIntoBuffer( buffer, bufferOffset+off, MAX_FILL_BUFFER );\r\n\t\t\tsize -= MAX_FILL_BUFFER;\r\n\t\t\toff += MAX_FILL_BUFFER;\r\n\t\t}\r\n\t\tif ( size ) WriteIntoBuffer( buffer, bufferOffset+off, size ); \r\n\t}\r\n\r\n}\r\n\r\n}  // namespace Replay\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sys/Replay/NGPS/p_replay.cpp",
    "content": "#include <sys/replay/replay.h>\r\n#if 0\r\nnamespace Replay\r\n{\r\n\r\n// Must be a multiple of REPLAY_BUFFER_CHUNK_SIZE\r\n//#define REPLAY_BUFFER_SIZE 1048576\r\n#define REPLAY_BUFFER_SIZE 200704\t\t\t// Mick - changed back to this, as the old levels are running out of memory\r\n//#define REPLAY_BUFFER_SIZE (20480*4)\r\n\r\nstatic uint8 *sp_buffer=NULL;\r\n\r\n// Allocates the big buffer for storing replays. Never gets deallocated. (Currently)\r\nvoid AllocateBuffer()\r\n{\r\n\tif (sp_buffer)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tsp_buffer=(uint8*)Mem::Malloc(REPLAY_BUFFER_SIZE);\r\n\tDbg_MsgAssert(sp_buffer,(\"Could not allocate replay buffer\"));\r\n}\r\n\r\nvoid DeallocateBuffer()\r\n{\r\n\tif (sp_buffer)\r\n\t{\r\n\t\tMem::Free(sp_buffer);\r\n\t\tsp_buffer=NULL;\r\n\t}\r\n}\r\n\r\nuint32 GetBufferSize()\r\n{\r\n\treturn REPLAY_BUFFER_SIZE;\r\n}\r\n\r\nbool BufferAllocated()\r\n{\r\n\tif (sp_buffer)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\t\r\n// Reads numBytes out of the buffer starting at offset bufferOffset, into p_dest.\r\n// Asserts if there are not enough source bytes.\r\nvoid ReadFromBuffer(uint8 *p_dest, int bufferOffset, int numBytes)\r\n{\r\n\tDbg_MsgAssert(sp_buffer,(\"Replay buffer has not been allocated\"));\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest sent to Replay::Read()\"));\r\n\tDbg_MsgAssert(bufferOffset>=0 && bufferOffset<REPLAY_BUFFER_SIZE,(\"Bad bufferOffset of %d sent to Read()\",bufferOffset));\r\n\tDbg_MsgAssert(bufferOffset+numBytes<=REPLAY_BUFFER_SIZE,(\"Requested Read() goes past the end of the buffer:\\nbufferOffset=%d numBytes=%d REPLAY_BUFFER_SIZE=%d\",bufferOffset,numBytes,REPLAY_BUFFER_SIZE));\r\n\r\n\tmemcpy(p_dest,sp_buffer+bufferOffset,numBytes);\r\n}\r\n\r\n// Writes numBytes into the buffer. Asserts if there is not enough space.\r\nvoid WriteIntoBuffer(uint8 *p_source, int bufferOffset, int numBytes)\r\n{\r\n\tDbg_MsgAssert(sp_buffer,(\"Replay buffer has not been allocated\"));\r\n\tDbg_MsgAssert(p_source,(\"NULL p_source sent to Replay::Write()\"));\r\n\tDbg_MsgAssert(bufferOffset>=0 && bufferOffset<REPLAY_BUFFER_SIZE,(\"Bad bufferOffset of %d sent to Write()\",bufferOffset));\r\n\tDbg_MsgAssert(bufferOffset+numBytes<=REPLAY_BUFFER_SIZE,(\"Requested Write() goes past the end of the buffer:\\nbufferOffset=%d numBytes=%d REPLAY_BUFFER_SIZE=%d\",bufferOffset,numBytes,REPLAY_BUFFER_SIZE));\r\n\t\r\n\tmemcpy(sp_buffer+bufferOffset,p_source,numBytes);\r\n}\r\n\r\nvoid FillBuffer(int bufferOffset, int numBytes, uint8 value)\r\n{\r\n\tDbg_MsgAssert(sp_buffer,(\"Replay buffer has not been allocated\"));\r\n\tDbg_MsgAssert(bufferOffset>=0 && bufferOffset<REPLAY_BUFFER_SIZE,(\"Bad bufferOffset of %d sent to FillBuffer()\",bufferOffset));\r\n\tDbg_MsgAssert(bufferOffset+numBytes<=REPLAY_BUFFER_SIZE,(\"Requested FillBuffer() goes past the end of the buffer:\\nbufferOffset=%d numBytes=%d REPLAY_BUFFER_SIZE=%d\",bufferOffset,numBytes,REPLAY_BUFFER_SIZE));\r\n\t\r\n\tmemset(sp_buffer+bufferOffset,value,numBytes);\r\n}\r\n\r\n}  // namespace Replay\r\n#endif\r\n"
  },
  {
    "path": "Code/Sys/Replay/Win32/p_replay.cpp",
    "content": "#include <sys/replay/replay.h>\r\n\r\nnamespace Replay\r\n{\r\n\r\n// Must be a multiple of REPLAY_BUFFER_CHUNK_SIZE\r\n#define REPLAY_BUFFER_SIZE 200704\r\n\r\nstatic uint8 *sp_buffer=NULL;\r\n\r\n// Allocates the big buffer for storing replays. Never gets deallocated. (Currently)\r\nvoid AllocateBuffer()\r\n{\r\n\tif (sp_buffer)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tsp_buffer=(uint8*)Mem::Malloc(REPLAY_BUFFER_SIZE);\r\n\tDbg_MsgAssert(sp_buffer,(\"Could not allocate replay buffer\"));\r\n}\r\n\r\nvoid DeallocateBuffer()\r\n{\r\n\tif (sp_buffer)\r\n\t{\r\n\t\tMem::Free(sp_buffer);\r\n\t\tsp_buffer=NULL;\r\n\t}\r\n}\r\n\r\nuint32 GetBufferSize()\r\n{\r\n\treturn REPLAY_BUFFER_SIZE;\r\n}\r\n\r\nbool BufferAllocated()\r\n{\r\n\tif (sp_buffer)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\t\r\n// Reads numBytes out of the buffer starting at offset bufferOffset, into p_dest.\r\n// Asserts if there are not enough source bytes.\r\nvoid ReadFromBuffer(uint8 *p_dest, int bufferOffset, int numBytes)\r\n{\r\n\tDbg_MsgAssert(sp_buffer,(\"Replay buffer has not been allocated\"));\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest sent to Replay::Read()\"));\r\n\tDbg_MsgAssert(bufferOffset>=0 && bufferOffset<REPLAY_BUFFER_SIZE,(\"Bad bufferOffset of %d sent to Read()\",bufferOffset));\r\n\tDbg_MsgAssert(bufferOffset+numBytes<=REPLAY_BUFFER_SIZE,(\"Requested Read() goes past the end of the buffer:\\nbufferOffset=%d numBytes=%d REPLAY_BUFFER_SIZE=%d\",bufferOffset,numBytes,REPLAY_BUFFER_SIZE));\r\n\r\n\tmemcpy(p_dest,sp_buffer+bufferOffset,numBytes);\r\n}\r\n\r\n// Writes numBytes into the buffer. Asserts if there is not enough space.\r\nvoid WriteIntoBuffer(uint8 *p_source, int bufferOffset, int numBytes)\r\n{\r\n\tDbg_MsgAssert(sp_buffer,(\"Replay buffer has not been allocated\"));\r\n\tDbg_MsgAssert(p_source,(\"NULL p_source sent to Replay::Write()\"));\r\n\tDbg_MsgAssert(bufferOffset>=0 && bufferOffset<REPLAY_BUFFER_SIZE,(\"Bad bufferOffset of %d sent to Write()\",bufferOffset));\r\n\tDbg_MsgAssert(bufferOffset+numBytes<=REPLAY_BUFFER_SIZE,(\"Requested Write() goes past the end of the buffer:\\nbufferOffset=%d numBytes=%d REPLAY_BUFFER_SIZE=%d\",bufferOffset,numBytes,REPLAY_BUFFER_SIZE));\r\n\t\r\n\tmemcpy(sp_buffer+bufferOffset,p_source,numBytes);\r\n}\r\n\r\nvoid FillBuffer(int bufferOffset, int numBytes, uint8 value)\r\n{\r\n\tDbg_MsgAssert(sp_buffer,(\"Replay buffer has not been allocated\"));\r\n\tDbg_MsgAssert(bufferOffset>=0 && bufferOffset<REPLAY_BUFFER_SIZE,(\"Bad bufferOffset of %d sent to FillBuffer()\",bufferOffset));\r\n\tDbg_MsgAssert(bufferOffset+numBytes<=REPLAY_BUFFER_SIZE,(\"Requested FillBuffer() goes past the end of the buffer:\\nbufferOffset=%d numBytes=%d REPLAY_BUFFER_SIZE=%d\",bufferOffset,numBytes,REPLAY_BUFFER_SIZE));\r\n\t\r\n\tmemset(sp_buffer+bufferOffset,value,numBytes);\r\n}\r\n\r\n}  // namespace Replay\r\n\r\n"
  },
  {
    "path": "Code/Sys/Replay/XBox/p_replay.cpp",
    "content": "#include <sys/replay/replay.h>\r\n\r\n#if 0\r\n\r\nnamespace Replay\r\n{\r\n\r\n// Must be a multiple of REPLAY_BUFFER_CHUNK_SIZE\r\n#define REPLAY_BUFFER_SIZE 1048576\r\n\r\nstatic uint8 *sp_buffer=NULL;\r\n\r\n// Allocates the big buffer for storing replays. Never gets deallocated. (Currently)\r\nvoid AllocateBuffer()\r\n{\r\n\tif (sp_buffer)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tsp_buffer=(uint8*)Mem::Malloc(REPLAY_BUFFER_SIZE);\r\n\tDbg_MsgAssert(sp_buffer,(\"Could not allocate replay buffer\"));\r\n}\r\n\r\nvoid DeallocateBuffer()\r\n{\r\n\tif (sp_buffer)\r\n\t{\r\n\t\tMem::Free(sp_buffer);\r\n\t\tsp_buffer=NULL;\r\n\t}\r\n}\r\n\r\nuint32 GetBufferSize()\r\n{\r\n\treturn REPLAY_BUFFER_SIZE;\r\n}\r\n\r\nbool BufferAllocated()\r\n{\r\n\tif (sp_buffer)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\t\r\n// Reads numBytes out of the buffer starting at offset bufferOffset, into p_dest.\r\n// Asserts if there are not enough source bytes.\r\nvoid ReadFromBuffer(uint8 *p_dest, int bufferOffset, int numBytes)\r\n{\r\n\tDbg_MsgAssert(sp_buffer,(\"Replay buffer has not been allocated\"));\r\n\tDbg_MsgAssert(p_dest,(\"NULL p_dest sent to Replay::Read()\"));\r\n\tDbg_MsgAssert(bufferOffset>=0 && bufferOffset<REPLAY_BUFFER_SIZE,(\"Bad bufferOffset of %d sent to Read()\",bufferOffset));\r\n\tDbg_MsgAssert(bufferOffset+numBytes<=REPLAY_BUFFER_SIZE,(\"Requested Read() goes past the end of the buffer:\\nbufferOffset=%d numBytes=%d REPLAY_BUFFER_SIZE=%d\",bufferOffset,numBytes,REPLAY_BUFFER_SIZE));\r\n\r\n\tmemcpy(p_dest,sp_buffer+bufferOffset,numBytes);\r\n}\r\n\r\n// Writes numBytes into the buffer. Asserts if there is not enough space.\r\nvoid WriteIntoBuffer(uint8 *p_source, int bufferOffset, int numBytes)\r\n{\r\n\tDbg_MsgAssert(sp_buffer,(\"Replay buffer has not been allocated\"));\r\n\tDbg_MsgAssert(p_source,(\"NULL p_source sent to Replay::Write()\"));\r\n\tDbg_MsgAssert(bufferOffset>=0 && bufferOffset<REPLAY_BUFFER_SIZE,(\"Bad bufferOffset of %d sent to Write()\",bufferOffset));\r\n\tDbg_MsgAssert(bufferOffset+numBytes<=REPLAY_BUFFER_SIZE,(\"Requested Write() goes past the end of the buffer:\\nbufferOffset=%d numBytes=%d REPLAY_BUFFER_SIZE=%d\",bufferOffset,numBytes,REPLAY_BUFFER_SIZE));\r\n\t\r\n\tmemcpy(sp_buffer+bufferOffset,p_source,numBytes);\r\n}\r\n\r\nvoid FillBuffer(int bufferOffset, int numBytes, uint8 value)\r\n{\r\n\tDbg_MsgAssert(sp_buffer,(\"Replay buffer has not been allocated\"));\r\n\tDbg_MsgAssert(bufferOffset>=0 && bufferOffset<REPLAY_BUFFER_SIZE,(\"Bad bufferOffset of %d sent to FillBuffer()\",bufferOffset));\r\n\tDbg_MsgAssert(bufferOffset+numBytes<=REPLAY_BUFFER_SIZE,(\"Requested FillBuffer() goes past the end of the buffer:\\nbufferOffset=%d numBytes=%d REPLAY_BUFFER_SIZE=%d\",bufferOffset,numBytes,REPLAY_BUFFER_SIZE));\r\n\t\r\n\tmemset(sp_buffer+bufferOffset,value,numBytes);\r\n}\r\n\r\n}  // namespace Replay\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sys/Replay/replay.cpp",
    "content": "/*\tThis is for storing information during a game that\r\n\twill be used to watch a replay of the game.\r\n\r\n\tSo far, it is only used for single player games, in\r\n\tsingle session or career modes.\r\n\r\n*/\r\n\r\n\r\n#include <sys/replay/replay.h>\r\n\r\n#if __USE_REPLAYS__\r\n\r\n#include <sys/mem/poolable.h>\r\n\r\n#include <sk/objects/movingobject.h>\r\n\r\n#include <gfx/2D/ScreenElement2.h>\r\n#include <gfx/2D/SpriteElement.h>\r\n#include <gfx/skeleton.h>\r\n#include <gfx/nxgeom.h>\r\n\r\n#include <gel/scripting/checksum.h>\r\n#include <gel/scripting/parse.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include <gel/scripting/script.h>\r\n#include <gel/scripting/utils.h>\r\n#include <gel/environment/terrain.h>\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n#include <gel/mainloop.h>\r\n#include <gel/music/music.h>\r\n#include <gel/assman/assman.h>\r\n#include <gel/objtrack.h>\r\n#include <sk/modules/skate/skate.h>\r\n#include <sk/modules/frontend/frontend.h>\r\n#include <gfx/nx.h>\r\n#include <gfx/nxmodel.h>\r\n#include <gfx/nxmiscfx.h>\r\n#include <gfx/modelbuilder.h>\r\n#include <gfx/ModelAppearance.h>\r\n#include <gfx/gfxutils.h>\r\n#include <gfx/2d/textelement.h>\r\n#include <gfx/2d/screenelemman.h>\r\n#include <sk/objects/car.h>\r\n#include <sk/objects/ped.h>\r\n#include <sk/objects/skater.h>\r\n#include <sk/objects/skatercareer.h>\r\n#include <sk/objects/skaterflags.h>\r\n#include <sk/objects/gameobj.h>\r\n#include <sk/components/skatercorephysicscomponent.h>\r\n#include <sk/gamenet/gamenet.h>\r\n#include <gfx/nxviewman.h>\r\n#include <sys/config/config.h>\r\n#include <gel/components/animationcomponent.h>\r\n#include <gel/components/skeletoncomponent.h>\r\n#include <gel/components/soundcomponent.h>\r\n#include <gel/components/vibrationcomponent.h>\r\n#include <gel/components/motioncomponent.h>\r\n\r\n// disabling replays while we refactor\r\n#define DISABLE_REPLAYS\r\n//#define CHECK_TOKEN_USAGE\r\n\r\nnamespace CFuncs\r\n{\r\n\tbool CheckButton(Inp::Handler< Mdl::FrontEnd >* pHandler, uint32 button);\r\n}\t\r\n\r\nnamespace Replay\r\n{\r\n\r\nDefineSingletonClass( Manager, \"Replay Manager\" )\r\n\r\n// These are hard coded rather than wasting space in the replay data. It would waste quite\r\n// a bit of space since there are lots of hovering cash icons. They all appear to use the same\r\n// parameters anyway.\r\n#define HOVER_ROTATE_SPEED 250.0f\r\n#define HOVER_AMPLITUDE 10.0f\r\n#define HOVER_PERIOD 1000\r\n#define HOVER_PERIOD_RND 100\r\n\r\nstatic uint32 sLevelStructureName=0;\r\n\r\nstatic uint32 sNextPlaybackFrameOffset=0;\r\nstatic bool sBufferFilling=true;\r\nstatic bool sReachedEndOfReplay=false;\r\nstatic bool sReplayPaused=false;\r\nstatic bool sNeedToInitialiseVibration=false;\r\nstatic bool sTrickTextGotCleared=false;\r\n\r\nstatic uint32 sBigBufferStartOffset=0;\r\nstatic uint32 sBigBufferEndOffset=0;\r\n\r\n// This is a small buffer where the replay info for one frame is stored.\r\n// It is then appended to the big cyclic buffer by sWriteFrameBufferToBigBuffer\r\n#define FRAME_BUFFER_SIZE 20480\r\nstatic uint8 spFrameBuffer[FRAME_BUFFER_SIZE];\r\nstatic uint8 *spFrameBufferPos=NULL;\r\n\r\nenum EReplayMode\r\n{\r\n\tNONE,\r\n\tRECORD,\r\n\tPLAYBACK\r\n};\r\nstatic EReplayMode sMode=NONE;\r\n\t\r\nenum EPointerType\r\n{\r\n\tUNDEFINED,\r\n\tCMOVINGOBJECT,\r\n\tCSCREENELEMENT,\r\n};\r\n\r\nenum ESpecialIDs\r\n{\r\n\tID_SKATER=0,\r\n\tID_CAMERA=1,\r\n};\r\n\t\r\nenum EAnimStartEndType\r\n{\r\n\tSTART_TO_END,\r\n\tEND_TO_START,\r\n\tSPECIFIC_START_END_TIMES\r\n};\r\n\r\nenum EReplayToken\r\n{\r\n\tBLANK=0,\r\n\tFRAME_START,\r\n\tCREATE_OBJECT,\r\n\tKILL_OBJECT,\r\n\tOBJECT_ID,\r\n\tMODEL_NAME,\r\n\tSKELETON_NAME,\r\n\tPROFILE_NAME,\r\n\tSECTOR_NAME,\r\n\tANIM_SCRIPT_NAME,\r\n\tSET_SCALE,\r\n\tSET_POSITION,\r\n\tSET_POSITION_ANGLES,\t\r\n\tSET_VELOCITY,\r\n\tSET_ANGLE_X,\r\n\tSET_ANGLE_Y,\r\n\tSET_ANGLE_Z,\r\n\tSET_ANGULAR_VELOCITY_X,\r\n\tSET_ANGULAR_VELOCITY_Y,\r\n\tSET_ANGULAR_VELOCITY_Z,\r\n\t\r\n\tPRIMARY_ANIM_CONTROLLER_CHANGES,\r\n\tDEGENERATE_ANIM_CONTROLLER_CHANGES,\r\n\t\r\n\tPLAY_POSITIONAL_SOUND_EFFECT,\r\n\tPLAY_SKATER_SOUND_EFFECT,\r\n\tPLAY_SOUND,\r\n\t\r\n\tPLAY_LOOPING_SOUND,\r\n\tSTOP_LOOPING_SOUND,\r\n\tPITCH_MIN,\r\n\tPITCH_MAX,\r\n\t\r\n\tSCREEN_BLUR,\r\n\tSCREEN_FLASH,\r\n\t\r\n\tSPARKS_ON,\r\n\tSPARKS_OFF,\r\n\t\r\n\tTRICK_TEXT,\r\n\tTRICK_TEXT_PULSE,\r\n\tTRICK_TEXT_COUNTDOWN,\r\n\tTRICK_TEXT_LANDED,\r\n\tTRICK_TEXT_BAIL,\r\n\t\r\n\tSCORE_POT_TEXT,\r\n\t\r\n\tPANEL_MESSAGE,\r\n\t\r\n\tSET_ATOMIC_STATES,\r\n\t\t\r\n\tMANUAL_METER_ON,\r\n\tMANUAL_METER_OFF,\r\n\tBALANCE_METER_ON,\r\n\tBALANCE_METER_OFF,\r\n\t\r\n\tFLIP,\r\n\tUNFLIP,\r\n\t\r\n\tMODEL_ACTIVE,\r\n\tMODEL_INACTIVE,\r\n\t\r\n\tPAD_VIBRATION,\r\n\tPLAY_POSITIONAL_STREAM,\r\n\tPLAY_STREAM,\r\n\tSTOP_STREAM,\r\n\t\r\n\tSET_CAR_ROTATION_X,\r\n\tSET_CAR_ROTATION_X_VEL,\r\n\tSET_WHEEL_ROTATION_X,\r\n\tSET_WHEEL_ROTATION_X_VEL,\r\n\tSET_WHEEL_ROTATION_Y,\r\n\tSET_WHEEL_ROTATION_Y_VEL,\r\n\t\r\n\tHOVERING,\r\n\t\r\n\tSECTOR_ACTIVE,\r\n\tSECTOR_INACTIVE,\r\n\r\n\tSECTOR_VISIBLE,\r\n\tSECTOR_INVISIBLE,\r\n\t\r\n\tSHATTER_PARAMS,\r\n\tSHATTER_ON,\r\n\tSHATTER_OFF,\r\n\r\n\tTEXTURE_SPLAT,\r\n\t\r\n\tSCRIPT_CALL,\r\n\tSKATER_SCRIPT_CALL,\r\n\t\r\n\tPAUSE_SKATER,\r\n\tUNPAUSE_SKATER,\r\n\t\t\r\n\t// Keep the total number of tokens less than 256, cos they're stored in a byte.\r\n\tNUM_REPLAY_TOKEN_TYPES\r\n};\r\n\r\nclass CPosTracker\r\n{\r\n\tfloat m_calculated_last;\r\n\tfloat m_vel;\r\n\tfloat m_actual_last;\r\n\t\r\npublic:\r\n\tCPosTracker();\r\n\t~CPosTracker();\r\n\t\r\n\tvoid WriteChanges(float newVal, EReplayToken setToken, EReplayToken velToken, float tolerance=0.005f);\r\n\tfloat GetActualLast() {return m_actual_last;}\r\n};\r\n\r\nclass CSkaterTrackingInfo\r\n{\r\npublic:\r\n\tCSkaterTrackingInfo();\r\n\t~CSkaterTrackingInfo();\r\n\r\n\tvoid Reset();\r\n\r\n    enum\r\n    {\r\n        NUM_DEGENERATE_ANIMS = 3\r\n    };\r\n    Gfx::CAnimChannel m_degenerateControllers[NUM_DEGENERATE_ANIMS];\r\n\t\r\n\tbool m_playing_looping_sound;\r\n\tuint32 m_looping_sound_checksum;\r\n\tfloat m_pitch_min;\r\n\tfloat m_pitch_max;\r\n};\r\n\r\nCSkaterTrackingInfo::CSkaterTrackingInfo()\r\n{\r\n\tReset();\r\n}\r\n\r\nCSkaterTrackingInfo::~CSkaterTrackingInfo()\r\n{\r\n}\r\n\r\nvoid CSkaterTrackingInfo::Reset()\r\n{\r\n\tfor (int i=0; i<NUM_DEGENERATE_ANIMS; ++i)\r\n\t{\r\n\t\tm_degenerateControllers[i].Reset();\r\n\t}\r\n\t\r\n\tm_playing_looping_sound=false;\r\n\tm_looping_sound_checksum=0;\r\n\tm_pitch_min=-1.0f; // Choose strange defaults to ensure a change is detected at the start.\r\n\tm_pitch_max=-1.0f;\r\n}\r\n\r\nenum ETrackingInfoFlags\r\n{\r\n\tTRACKING_INFO_FLAG_OBJECT_CREATED\t= (1<<0),\r\n\tTRACKING_INFO_FLAG_FLIPPED\t\t\t= (1<<1),\r\n\tTRACKING_INFO_FLAG_ACTIVE\t\t\t= (1<<2),\r\n\tTRACKING_INFO_FLAG_HOVERING\t\t\t= (1<<3),\r\n};\r\n\r\nclass CTrackingInfo : public Mem::CPoolable<CTrackingInfo>\r\n{\r\npublic:\t\r\n\tCTrackingInfo();\r\n\t~CTrackingInfo();\r\n\r\n\tCTrackingInfo *mpNext;\r\n\tCTrackingInfo *mpPrevious;\r\n\t\r\n\tvoid SetMovingObject(Obj::CMovingObject *p_ob);\r\n\tvoid SetSkaterCamera();\r\n\r\n\tvoid RecordPositionAndAngleChanges(Mth::Vector &actual_pos, Mth::Vector &actual_angles, bool exact=false);\r\n\r\n\tuint32 m_id;\r\n\tEPointerType mPointerType;\r\n\tObj::CSmtPtr<Obj::CMovingObject> mpMovingObject;\r\n\t\t\r\n\tuint32 mFlags;\r\n\tfloat mScale;\r\n\t\r\n\tMth::Vector mReplayVel;\r\n\tMth::Vector mReplayLastPos;\r\n\tMth::Vector mActualLastPos;\r\n\r\n\tCPosTracker mTrackerAngleX;\r\n\tCPosTracker mTrackerAngleY;\r\n\tCPosTracker mTrackerAngleZ;\r\n\r\n\tMth::Matrix mLastMatrix;\r\n\t\t\r\n\tCPosTracker mTrackerCarRotationX;\r\n\tCPosTracker mTrackerWheelRotationX;\r\n\tCPosTracker mTrackerWheelRotationY;\r\n\r\n\tGfx::CAnimChannel m_primaryController;\r\n\t\r\n\t// Made this static because only the skater needs these members, and there is only one skater.\r\n\t// Need to keep the CTrackingInfo class as small as possible because a pool of 300 of them exists.\r\n\tstatic CSkaterTrackingInfo sSkaterTrackingInfo;\r\n\t\r\n\tstatic int sScreenBlurTracker;\r\n\t\r\n};\t\r\nCSkaterTrackingInfo CTrackingInfo::sSkaterTrackingInfo;\r\nint CTrackingInfo::sScreenBlurTracker=0;\r\n\r\n\r\nstatic CTrackingInfo *spTrackingInfoHead=NULL;\r\nstatic Lst::HashTable<CTrackingInfo> sTrackingInfoHashTable(8);\r\n\r\nstatic CDummy *spStartStateDummies=NULL;\r\nstatic CDummy *spReplayDummies=NULL;\r\n\r\nstatic Lst::HashTable<CDummy> sObjectStartStateHashTable(8);\r\nstatic Lst::HashTable<CDummy> sReplayDummysHashTable(8);\r\n\r\nstatic SGlobalStates sStartState;\r\nstatic SGlobalStates sCurrentState;\r\n}\r\n\r\nDefinePoolableClass(Replay::CTrackingInfo);\r\n\r\nnamespace Replay\r\n{\r\n\r\n#define MAX_PANEL_MESSAGE_SIZE 200\r\n\r\nstatic void sDeleteObjectTrackingInfo();\r\nstatic Lst::HashTable<CDummy> *sGetDummyHashTable(EDummyList whichList);\r\nstatic CDummy *sGetDummyListHeadPointer(EDummyList whichList);\r\nstatic void sSetDummyListHeadPointer(EDummyList whichList, CDummy *p_dummy);\r\nstatic int sCountStartStateDummies();\r\nstatic void sStopReplayDummyLoopingSounds();\r\nstatic uint32 sReadAnimControllerChanges(uint32 offset, Gfx::CAnimChannel *p_anim_controller);\r\nstatic uint32 sReadFrame(uint32 offset, bool *p_nothingFollows, EDummyList whichList);\r\nstatic void sMakeEnoughSpace(uint32 frameSize);\r\nstatic void sWriteFrameBufferToBigBuffer();\r\nstatic void sWriteSingleToken(EReplayToken token);\r\nstatic void sWriteUint8(uint8 v);\r\nstatic void sWriteUint32(EReplayToken token, uint32 v);\r\nstatic void sWriteUint32(uint32 v);\r\nstatic void sWriteFloat(EReplayToken token, float f);\r\nstatic void sWriteFloat(float f);\r\nstatic void sWriteVector(EReplayToken token, Mth::Vector &v);\r\n//static void sWriteString(EReplayToken token, const char *p_string);\r\n//static uint8 sWriteCAnimChannelChanges(const Gfx::CAnimChannel *p_a, const Gfx::CAnimChannel *p_b);\r\nstatic bool sIsFlipped(Obj::CMovingObject *p_movingObject);\r\nstatic void sRecordSkaterCamera(CTrackingInfo *p_info);\r\nstatic void sRecordCMovingObject(CTrackingInfo *p_info);\r\nstatic void sRecord();\r\nstatic void sPlayback(bool display=true);\r\nstatic void sEnsureTrackerExists( Obj::CObject *p_ob, void *p_data );\r\nstatic void sEnsureCameraTrackerExists();\r\nstatic void sHideForReplayPlayback( Obj::CObject *p_ob, void *p_data );\r\nstatic void sRestoreAfterReplayPlayback( Obj::CObject *p_ob, void *p_data );\r\nstatic void sDeleteDummies(EDummyList whichList);\r\nstatic void sUnpauseCertainScreenElements();\r\nstatic void sSwitchOffVibrations();\r\nstatic void sClearLastPanelMessage();\r\nstatic void sClearTrickAndScoreText();\r\nstatic Obj::CSkater *sGetSkater();\r\nstatic Mdl::Score *sGetSkaterScoreObject();\r\n#ifdef CHECK_TOKEN_USAGE\r\nstatic const char *sGetTokenName(EReplayToken token);\r\n#endif\r\n\r\nSGlobalStates::SGlobalStates()\r\n{\r\n\tReset();\r\n}\r\n\r\nSGlobalStates::~SGlobalStates()\r\n{\r\n}\r\n\r\nvoid SGlobalStates::Reset()\r\n{\r\n\tmBalanceMeterStatus=false;\r\n\tmBalanceMeterValue=0.0f;\r\n\r\n\tmManualMeterStatus=false;\r\n\tmManualMeterValue=0.0f;\r\n\t\r\n\tint i;\r\n\tfor (i=0; i<Obj::CVibrationComponent::vVB_NUM_ACTUATORS; ++i)\r\n\t{\r\n\t\tmActuatorStrength[i]=0;\r\n\t}\t\r\n\r\n\tfor (i=0; i<SECTOR_STATUS_BUFFER_SIZE; ++i)\r\n\t{\r\n\t\tmpSectorStatus[i]=0xffffffff; // All sectors active and visible\r\n\t}\r\n\t\r\n\tmSkaterPaused=false;\r\n}\r\n\r\nCPosTracker::CPosTracker()\r\n{\r\n\tm_vel=0.0f;\r\n\tm_actual_last=0.0f;\r\n\tm_calculated_last=0.0f;\r\n}\r\n\r\nCPosTracker::~CPosTracker()\r\n{\r\n}\r\n\t\r\nvoid CPosTracker::WriteChanges(float newVal, EReplayToken setToken, EReplayToken velToken, float tolerance)\r\n{\r\n\tfloat predicted=m_calculated_last+m_vel;\r\n\tfloat d=newVal-predicted;\r\n\tif (fabs(d) > tolerance)\r\n\t{\r\n\t\tm_calculated_last=newVal;\r\n\t\tsWriteFloat(setToken,newVal);\r\n\t\t\r\n\t\tm_vel=newVal-m_actual_last;\r\n\t\tsWriteFloat(velToken,m_vel);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_calculated_last=predicted;\r\n\t}\t\r\n    m_actual_last=newVal;\r\n}\r\n\r\nCTrackingInfo::CTrackingInfo()\r\n{\r\n\tm_id=0xffffffff;\t\t\r\n\tmPointerType=UNDEFINED;\r\n\tmpMovingObject=NULL;\r\n\tmFlags=0;\r\n\tmScale=1.0f;\r\n\t\t\t\r\n\tmReplayVel.Set();\r\n\tmReplayLastPos.Set();\r\n\tmActualLastPos.Set();\r\n\r\n\t// Making sure this won't match the object's matrix on the first frame so that\r\n\t// changes will get recorded for the first frame.\r\n\tmLastMatrix[0][0]=0.0f;\t\r\n\r\n\tm_primaryController.Reset();\r\n\t\r\n\tmpNext=spTrackingInfoHead;\r\n\tmpPrevious=NULL;\r\n\tif (mpNext)\r\n\t{\r\n\t\tmpNext->mpPrevious=this;\r\n\t}\r\n\tspTrackingInfoHead=this;\r\n}\r\n\r\nCTrackingInfo::~CTrackingInfo()\r\n{\r\n\tif (mpPrevious) mpPrevious->mpNext=mpNext;\r\n\tif (mpNext) mpNext->mpPrevious=mpPrevious;\r\n\tif (!mpPrevious) spTrackingInfoHead=mpNext;\r\n\t\r\n\tsTrackingInfoHashTable.FlushItem((uint32)m_id);\r\n}\r\n\r\nvoid CTrackingInfo::SetMovingObject(Obj::CMovingObject *p_ob)\r\n{\r\n\tmPointerType=CMOVINGOBJECT;\r\n\tmpMovingObject=p_ob;\r\n\tm_id=p_ob->GetID();\r\n\t\r\n\t// Use p_ob as the hash key so that the CTrackingInfo for any given CMovingObject\r\n\t// can be quickly looked up.\r\n\tsTrackingInfoHashTable.PutItem((uint32)m_id,this);\r\n}\t\r\n\r\nvoid CTrackingInfo::SetSkaterCamera()\r\n{\r\n\tDbg_MsgAssert(mPointerType==UNDEFINED,(\"Expected mPointerType to be UNDEFINED\"));\r\n\tDbg_MsgAssert(mpMovingObject==NULL,(\"Expected mpMovingObject to be NULL\"));\r\n\tmpMovingObject=NULL;\r\n\t\r\n\tm_id=ID_CAMERA;\r\n\tsTrackingInfoHashTable.PutItem((uint32)m_id,this);\r\n}\r\n\r\nvoid CTrackingInfo::RecordPositionAndAngleChanges(Mth::Vector &actual_pos, Mth::Vector &actual_angles, bool exact)\r\n{\r\n\tif (exact)\r\n\t{\r\n\t\tsWriteSingleToken(SET_POSITION_ANGLES);\r\n\t\tsWriteFloat(actual_pos[X]);\r\n\t\tsWriteFloat(actual_pos[Y]);\r\n\t\tsWriteFloat(actual_pos[Z]);\r\n\t\tsWriteFloat(actual_angles[X]);\r\n\t\tsWriteFloat(actual_angles[Y]);\r\n\t\tsWriteFloat(actual_angles[Z]);\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\t// Compare the actual position with that predicted by the last\r\n\t// position and velocity\r\n\tMth::Vector predicted_pos=mReplayLastPos+mReplayVel;\r\n\tMth::Vector d=actual_pos-predicted_pos;\r\n\t\r\n\tif (fabs(d[X]) > 0.1f || fabs(d[Y]) > 0.1f || fabs(d[Z]) > 0.1f)\r\n\t{\r\n\t\tmReplayLastPos=actual_pos;\r\n\t\tsWriteVector(SET_POSITION,actual_pos);\r\n\r\n\t\t\r\n\t\tmReplayVel=actual_pos-mActualLastPos;\r\n\t\tsWriteVector(SET_VELOCITY,mReplayVel);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmReplayLastPos=predicted_pos;\r\n\t}\t\r\n    mActualLastPos=actual_pos;\r\n\r\n\r\n\t// Do the angles.\r\n\tmTrackerAngleX.WriteChanges(actual_angles[X],SET_ANGLE_X,SET_ANGULAR_VELOCITY_X);\r\n\tmTrackerAngleY.WriteChanges(actual_angles[Y],SET_ANGLE_Y,SET_ANGULAR_VELOCITY_Y);\r\n\tmTrackerAngleZ.WriteChanges(actual_angles[Z],SET_ANGLE_Z,SET_ANGULAR_VELOCITY_Z);\r\n}\r\n\r\nstatic void sDeleteObjectTrackingInfo()\r\n{\r\n\tCTrackingInfo *p_info=spTrackingInfoHead;\r\n\twhile (p_info)\r\n\t{\r\n\t\tCTrackingInfo *p_next=p_info->mpNext;\r\n\t\tdelete p_info;\r\n\t\tp_info=p_next;\r\n\t}\t\r\n}\r\n\r\nstatic Lst::HashTable<CDummy> *sGetDummyHashTable(EDummyList whichList)\r\n{\r\n\tif (whichList==START_STATE_DUMMY_LIST)\r\n\t{\r\n\t\treturn &sObjectStartStateHashTable;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn &sReplayDummysHashTable;\r\n\t}\r\n}\r\n\t\t\r\nCDummy *GetFirstStartStateDummy()\r\n{\r\n\treturn spStartStateDummies;\r\n}\r\n\t\r\nstatic CDummy *sGetDummyListHeadPointer(EDummyList whichList)\r\n{\r\n\tif (whichList==START_STATE_DUMMY_LIST)\r\n\t{\r\n\t\treturn spStartStateDummies;\r\n\t}\r\n\telse\t\r\n\t{\r\n\t\treturn spReplayDummies;\r\n\t}\r\n}\r\n\r\nstatic void sSetDummyListHeadPointer(EDummyList whichList, CDummy *p_dummy)\r\n{\r\n\tif (whichList==START_STATE_DUMMY_LIST)\r\n\t{\r\n\t\tspStartStateDummies=p_dummy;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tspReplayDummies=p_dummy;\r\n\t}\r\n}\r\n\t\t\r\nstatic int sCountStartStateDummies()\r\n{\r\n\tint n=0;\r\n\tCDummy *p_dummy=spStartStateDummies;\r\n\twhile (p_dummy)\r\n\t{\r\n\t\t++n;\r\n\t\tp_dummy=p_dummy->mpNext;\r\n\t}\r\n\treturn n;\t\r\n}\r\n\r\n#ifdef CHECK_TOKEN_USAGE\r\nstatic const char *sGetTokenName(EReplayToken token)\r\n{\r\n\tswitch (token)\r\n\t{\r\n\tcase BLANK                               :return \"BLANK\"; break;\r\n\tcase FRAME_START                         :return \"FRAME_START\"; break;                       \r\n\tcase CREATE_OBJECT                       :return \"CREATE_OBJECT\"; break;                     \r\n\tcase KILL_OBJECT                         :return \"KILL_OBJECT\"; break;                       \r\n\tcase OBJECT_ID                           :return \"OBJECT_ID\"; break;                         \r\n\tcase MODEL_NAME                          :return \"MODEL_NAME\"; break;                        \r\n\tcase SKELETON_NAME                       :return \"SKELETON_NAME\"; break;                     \r\n\tcase PROFILE_NAME                        :return \"PROFILE_NAME\"; break;                      \r\n\tcase SECTOR_NAME                         :return \"SECTOR_NAME\"; break;                       \r\n\tcase ANIM_SCRIPT_NAME                    :return \"ANIM_SCRIPT_NAME\"; break;                  \r\n\tcase SET_POSITION                        :return \"SET_POSITION\"; break;                      \r\n\tcase SET_POSITION_ANGLES\t             :return \"SET_POSITION_ANGLES\"; break;               \r\n\tcase SET_VELOCITY                        :return \"SET_VELOCITY\"; break;                      \r\n\tcase SET_ANGLE_X                         :return \"SET_ANGLE_X\"; break;                       \r\n\tcase SET_ANGLE_Y                         :return \"SET_ANGLE_Y\"; break;                       \r\n\tcase SET_ANGLE_Z                         :return \"SET_ANGLE_Z\"; break;                       \r\n\tcase SET_ANGULAR_VELOCITY_X              :return \"SET_ANGULAR_VELOCITY_X\"; break;            \r\n\tcase SET_ANGULAR_VELOCITY_Y              :return \"SET_ANGULAR_VELOCITY_Y\"; break;            \r\n\tcase SET_ANGULAR_VELOCITY_Z              :return \"SET_ANGULAR_VELOCITY_Z\"; break;            \r\n\tcase PRIMARY_ANIM_CONTROLLER_CHANGES     :return \"PRIMARY_ANIM_CONTROLLER_CHANGES\"; break;   \r\n\tcase DEGENERATE_ANIM_CONTROLLER_CHANGES  :return \"DEGENERATE_ANIM_CONTROLLER_CHANGES\"; break;\r\n\tcase PLAY_POSITIONAL_SOUND_EFFECT        :return \"PLAY_POSITIONAL_SOUND_EFFECT\"; break;      \r\n\tcase PLAY_SKATER_SOUND_EFFECT            :return \"PLAY_SKATER_SOUND_EFFECT\"; break;          \r\n\tcase PLAY_SOUND\t\t\t\t\t\t\t :return \"PLAY_SOUND\"; break;\r\n\tcase PLAY_LOOPING_SOUND\t\t\t\t\t :return \"PLAY_LOOPING_SOUND\"; break;\r\n\tcase STOP_LOOPING_SOUND\t\t\t\t\t :return \"STOP_LOOPING_SOUND\"; break;\r\n\tcase PITCH_MIN\t\t\t\t\t\t\t :return \"PITCH_MIN\"; break;\r\n\tcase PITCH_MAX\t\t\t\t\t\t\t :return \"PITCH_MAX\"; break;\r\n\tcase SCREEN_BLUR                         :return \"SCREEN_BLUR\"; break;                       \r\n\tcase SCREEN_FLASH\t\t\t\t\t\t :return \"SCREEN_FLASH\"; break;\r\n\tcase SPARKS_ON                           :return \"SPARKS_ON\"; break;                         \r\n\tcase SPARKS_OFF                          :return \"SPARKS_OFF\"; break;                        \r\n\tcase TRICK_TEXT                          :return \"TRICK_TEXT\"; break;                        \r\n\tcase TRICK_TEXT_PULSE                    :return \"TRICK_TEXT_PULSE\"; break;                  \r\n\tcase TRICK_TEXT_COUNTDOWN                :return \"TRICK_TEXT_COUNTDOWN\"; break;              \r\n\tcase TRICK_TEXT_LANDED                   :return \"TRICK_TEXT_LANDED\"; break;                 \r\n\tcase TRICK_TEXT_BAIL                     :return \"TRICK_TEXT_BAIL\"; break;                   \r\n\tcase SCORE_POT_TEXT                      :return \"SCORE_POT_TEXT\"; break;                    \r\n\tcase PANEL_MESSAGE                       :return \"PANEL_MESSAGE\"; break;                     \r\n\tcase SET_ATOMIC_STATES                   :return \"SET_ATOMIC_STATES\"; break;                  \r\n\tcase MANUAL_METER_ON                     :return \"MANUAL_METER_ON\"; break;                   \r\n\tcase MANUAL_METER_OFF                    :return \"MANUAL_METER_OFF\"; break;                  \r\n\tcase BALANCE_METER_ON                    :return \"BALANCE_METER_ON\"; break;                  \r\n\tcase BALANCE_METER_OFF                   :return \"BALANCE_METER_OFF\"; break;                 \r\n\tcase FLIP                                :return \"FLIP\"; break;                              \r\n\tcase UNFLIP                              :return \"UNFLIP\"; break;                            \r\n\tcase MODEL_ACTIVE                        :return \"MODEL_ACTIVE\"; break;                              \r\n\tcase MODEL_INACTIVE                      :return \"MODEL_INACTIVE\"; break;                              \r\n\tcase PAD_VIBRATION                       :return \"PAD_VIBRATION\"; break;                     \r\n\tcase PLAY_POSITIONAL_STREAM              :return \"PLAY_POSITIONAL_STREAM\"; break;            \r\n\tcase PLAY_STREAM                         :return \"PLAY_STREAM\"; break;                       \r\n\tcase STOP_STREAM                         :return \"STOP_STREAM\"; break;                       \r\n\tcase SET_CAR_ROTATION_X                  :return \"SET_CAR_ROTATION_X\"; break;                \r\n\tcase SET_CAR_ROTATION_X_VEL              :return \"SET_CAR_ROTATION_X_VEL\"; break;            \r\n\tcase SET_WHEEL_ROTATION_X                :return \"SET_WHEEL_ROTATION_X\"; break;              \r\n\tcase SET_WHEEL_ROTATION_X_VEL            :return \"SET_WHEEL_ROTATION_X_VEL\"; break;          \r\n\tcase SET_WHEEL_ROTATION_Y                :return \"SET_WHEEL_ROTATION_Y\"; break;              \r\n\tcase SET_WHEEL_ROTATION_Y_VEL            :return \"SET_WHEEL_ROTATION_Y_VEL\"; break;          \r\n\tcase HOVERING\t\t\t\t\t\t\t :return \"HOVERING\"; break;          \r\n\tcase SECTOR_ACTIVE\t\t\t\t\t\t :return \"SECTOR_ACTIVE\"; break;          \r\n\tcase SECTOR_INACTIVE\t\t\t\t\t :return \"SECTOR_INACTIVE\"; break;          \r\n\tcase SECTOR_VISIBLE\t\t\t\t\t\t :return \"SECTOR_VISIBLE\"; break;          \r\n\tcase SECTOR_INVISIBLE\t\t\t\t\t :return \"SECTOR_INVISIBLE\"; break;          \r\n\tcase SHATTER_PARAMS\t\t\t\t\t \t :return \"SHATTER_PARAMS\"; break;          \r\n\tcase SHATTER_ON\t\t\t\t\t \t\t :return \"SHATTER_ON\"; break;          \r\n\tcase SHATTER_OFF\t\t\t\t \t\t :return \"SHATTER_OFF\"; break;          \r\n\tcase TEXTURE_SPLAT\t\t\t\t\t\t :return \"TEXTURE_SPLAT\"; break;\r\n\tcase SCRIPT_CALL\t\t\t\t\t\t :return \"SCRIPT_CALL\"; break;\r\n\tcase SKATER_SCRIPT_CALL\t\t\t\t\t :return \"SKATER_SCRIPT_CALL\"; break;\r\n\tcase PAUSE_SKATER\t\t\t\t\t\t :return \"PAUSE_SKATER\"; break;\r\n\tcase UNPAUSE_SKATER\t\t\t\t\t\t :return \"UNPAUSE_SKATER\"; break;\r\n\tdefault\t\t\t\t\t\t\t\t\t :return \"UNKNOWN\"; break;\r\n\t}\r\n}\r\n#endif\r\n\r\n// When the game is in paused mode, which it will be when running a replay, certain screen\r\n// elements such as the balance meters will not update properly.\r\n// This function will unpause them so that they work during the replay.\r\nstatic void sUnpauseCertainScreenElements()\r\n{\r\n\tFront::CScreenElementManager* p_manager = Front::CScreenElementManager::Instance();\r\n\tFront::CSpriteElement *p_balance_meter = (Front::CSpriteElement *) p_manager->GetElement(0xa4db8a4b + sGetSkater()->GetHeapIndex()).Convert(); // \"the_balance_meter\"\r\n\tDbg_MsgAssert(p_balance_meter,(\"NULL p_balance_meter\"));\r\n\tFront::CSpriteElement *p_balance_arrow = (Front::CSpriteElement *) p_balance_meter->GetFirstChild().Convert();\r\n\t\r\n\tp_balance_meter->SetMorphPausedState(false);\r\n\tp_balance_arrow->SetMorphPausedState(false);\r\n}\r\n\r\nstatic void sSwitchOffVibrations()\r\n{\r\n\tObj::CSkater *p_skater=sGetSkater();\r\n\tfor (int i=0; i<Obj::CVibrationComponent::vVB_NUM_ACTUATORS; ++i)\r\n\t{\r\n\t\tp_skater->GetDevice()->ActivateActuator(i,0);\r\n\t}\t\r\n}\r\n\r\nstatic Obj::CSkater *sGetSkater()\r\n{\r\n\tMdl::Skate * p_skate_mod = Mdl::Skate::Instance();\r\n\tObj::CSkater *p_skater = p_skate_mod->GetSkater(0);\r\n\tDbg_MsgAssert(p_skater,(\"NULL p_skater\"));\r\n\treturn p_skater;\r\n}\r\n\t\r\nstatic Mdl::Score *sGetSkaterScoreObject()\r\n{\r\n\tMdl::Score *p_score=sGetSkater()->GetScoreObject();\r\n\tDbg_MsgAssert(p_score,(\"NULL p_score\"));\r\n\treturn p_score;\r\n}\r\n\r\nstatic void sDeleteDummies(EDummyList whichList)\r\n{\r\n\tCDummy *p_dummy=sGetDummyListHeadPointer(whichList);\r\n\twhile (p_dummy)\r\n\t{\r\n\t\tCDummy *p_next=p_dummy->mpNext;\r\n\t\tdelete p_dummy;\r\n\t\tp_dummy=p_next;\r\n\t}\t\r\n\tsGetDummyHashTable(whichList)->FlushAllItems();\r\n\tDbg_MsgAssert(spReplayDummies==NULL,(\"Hey! spReplayDummies not NULL !!!\"));\r\n}\r\n\r\nbool ScriptDeleteDummies( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tsDeleteDummies(PLAYBACK_DUMMY_LIST);\r\n\treturn true;\r\n}\r\n\t\r\nCDummy::CDummy(EDummyList whichList, uint32 id)\r\n{\r\n\tm_list=whichList;\r\n\tSetID(id);\r\n\r\n\tmpNext=sGetDummyListHeadPointer(m_list);\r\n\tmpPrevious=NULL;\r\n\tif (mpNext)\r\n\t{\r\n\t\tmpNext->mpPrevious=this;\r\n\t}\t\r\n\tsSetDummyListHeadPointer(m_list,this);\r\n\tsGetDummyHashTable(whichList)->PutItem(m_id,this);\r\n\t\r\n\t//m_type = SKATE_TYPE_REPLAY_DUMMY;\r\n\r\n\tmAtomicStates=0xffffffff;\r\n\r\n\tmFlags=0;\r\n\t\r\n\t// Add a bit of randomness so that groups of hovering things slowly\r\n\t// go out of phase with each other rather than hovering in unison.\r\n\tmHoverPeriod=HOVER_PERIOD+Mth::Rnd(2*HOVER_PERIOD_RND+1)-HOVER_PERIOD_RND;\r\n\tDbg_MsgAssert(mHoverPeriod>0,(\"Bad mHoverPeriod\"));\r\n\t\r\n\tm_car_rotation_x=0.0f;\r\n\tm_car_rotation_x_vel=0.0f;\r\n\tm_wheel_rotation_x=0.0f;\r\n\tm_wheel_rotation_x_vel=0.0f;\r\n\tm_wheel_rotation_y=0.0f;\r\n\tm_wheel_rotation_y_vel=0.0f;\r\n\r\n\tmAnimScriptName=0;\r\n\tmSectorName=0;\r\n\tmScale=1.0f;\r\n\r\n\tm_looping_sound_id=0;\r\n\tm_looping_sound_checksum=0;\r\n\tm_pitch_min=50.0f;\r\n\tm_pitch_max=120.0f;\r\n\t\t\t\r\n\tm_is_displayed=true;\r\n\t\t\t\t\r\n\t// Note: CDummy is derived from CMovingObject which is derived from Spt::Class, so we\r\n\t// get the autozeroing of the members.\r\n}\r\n\r\nCDummy::~CDummy()\r\n{\r\n\tif (mp_rendered_model && m_id!=0)\r\n\t{\r\n\t\t// Must call sUninitModel rather than just delete it.\r\n\t\tNx::CEngine::sUninitModel(mp_rendered_model);\r\n    }\r\n\r\n    if (mp_skeletonComponent)\r\n    {\r\n        delete mp_skeletonComponent;\r\n\t\tmp_skeletonComponent = NULL;\r\n    }\r\n\t\r\n\tif (mpPrevious) mpPrevious->mpNext=mpNext;\r\n\tif (mpNext) mpNext->mpPrevious=mpPrevious;\r\n\tif (mpPrevious==NULL)\r\n\t{\r\n\t\tsSetDummyListHeadPointer(m_list,mpNext);\r\n\t}\t\r\n\t\r\n\tsGetDummyHashTable(m_list)->FlushItem(m_id);\r\n\t\r\n\tif (mp_skater_camera)\r\n\t{\r\n\t\tdelete mp_skater_camera;\r\n//\t\tObj::CSkater *p_skater=sGetSkater();\r\n\r\n\t\t// Replay has finished, so we'd want to switch the camera back to the skater camera\r\n\t\t// can't do it the old way, need to use\r\n\t\t\r\n\t\tprintf (\"STUBBED:  replay.cpp, line %d  -------- not resetting skater camera\\n\",__LINE__);\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t//Nx::CViewportManager::sSetCamera( /*m_skater_number*/0, p_skater->GetSkaterCam() );\t\t\t\r\n\t}\t\r\n}\r\n\r\nCDummy& CDummy::operator=( const CDummy& rhs )\r\n{\r\n#if 0\r\n\tDbg_MsgAssert(strlen(rhs.mpModelName)<=MAX_MODEL_NAME_CHARS,(\"rhs mpModelName too long ?\"));\r\n\tstrcpy(mpModelName,rhs.mpModelName);\r\n\tmSkeletonName=rhs.mSkeletonName;\r\n\tmProfileName=rhs.mProfileName;\r\n\tmAnimScriptName=rhs.mAnimScriptName;\r\n\tmSectorName=rhs.mSectorName;\r\n\tmScale=rhs.mScale;\r\n\t\r\n\tmFlags=rhs.mFlags;\r\n\t\r\n\tmHoverPeriod=rhs.mHoverPeriod;\r\n\t\r\n\t// Don't really need to copy m_id and m_pos here, because they are members of\r\n\t// CMovingObject so will get copied by the CMovingObject default assignement operator, I think.\r\n\t// I feel more comfortable doing it here too though.\r\n\tm_id=rhs.m_id;\r\n\tm_pos=rhs.m_pos;\r\n\tm_type=rhs.m_type;\r\n\t\r\n\tm_vel=rhs.m_vel;\r\n\tm_angles=rhs.m_angles;\r\n\tm_ang_vel=rhs.m_ang_vel;\r\n\r\n\t// This is because for the skater dummy the speed for calculating the looping sound\r\n\t// volume is calculated using m_old_pos. If it were left equal to 0,0,0 it would cause the\r\n\t// looping sound to be played at max volume for the first frame, because it would think\r\n\t// the skater was moving very fast.\r\n\tm_old_pos=m_pos;\r\n\r\n\tm_car_rotation_x\t\t=rhs.m_car_rotation_x;\r\n\tm_car_rotation_x_vel    =rhs.m_car_rotation_x_vel;\r\n\tm_wheel_rotation_x      =rhs.m_wheel_rotation_x;\r\n\tm_wheel_rotation_x_vel  =rhs.m_wheel_rotation_x_vel;\r\n\tm_wheel_rotation_y      =rhs.m_wheel_rotation_y;\r\n\tm_wheel_rotation_y_vel  =rhs.m_wheel_rotation_y_vel;\r\n\t\r\n\tm_primaryController=rhs.m_primaryController;\r\n\t\r\n\tfor (int i=0; i<NUM_DEGENERATE_ANIMS; ++i)\r\n\t{\r\n\t\tm_degenerateControllers[i]=rhs.m_degenerateControllers[i];\r\n\t}\r\n\t\t\r\n\tmp_rendered_model=NULL;\r\n\tmp_skater_camera=NULL;\r\n\t\r\n\tmAtomicStates=rhs.mAtomicStates;\r\n\r\n\t// Note: m_looping_sound_id is not copied, since this is a unique id for the instance of the sound.\r\n\tm_looping_sound_checksum=rhs.m_looping_sound_checksum;\r\n\tm_pitch_min=rhs.m_pitch_min;\r\n\tm_pitch_max=rhs.m_pitch_max;\r\n#endif\r\n\t\r\n\t// CDummy::m_list is not copied, and similarly not mpNext or mpPrevious because the\r\n\t// new CDummy may want to be in a different list. Copying mpNext and mpPrevious would\r\n\t// tangle up the lists anyway.\r\n\treturn *this;\r\n}\r\n\r\nvoid CDummy::Save(SSavedDummy *p_saved_dummy)\r\n{\r\n#if 0\r\n\tDbg_MsgAssert(p_saved_dummy,(\"NULL p_saved_dummy\"));\r\n\r\n\tDbg_MsgAssert(strlen(mpModelName)<=MAX_MODEL_NAME_CHARS,(\"mpModelName too long ?\"));\r\n\tstrcpy(p_saved_dummy->mpModelName,mpModelName);\r\n\t\r\n\tp_saved_dummy->m_id\t\t\t\t=\tm_id;\r\n\tp_saved_dummy->m_type\t\t\t=\tm_type;\r\n\tp_saved_dummy->mSkeletonName\t=\tmSkeletonName;\r\n\tp_saved_dummy->mProfileName\t\t=\tmProfileName;\r\n\tp_saved_dummy->mAnimScriptName\t=\tmAnimScriptName;\r\n\tp_saved_dummy->mSectorName\t\t=\tmSectorName;\r\n\tp_saved_dummy->mScale\t\t\t=\tmScale;\r\n\tp_saved_dummy->mFlags\t\t\t=\tmFlags;\r\n\t// Note: The mHoverPeriod is not saved out. No need, it does not need to be restored exactly,\r\n\t// and the CDummy constructor generates a new random value for it.\r\n\tp_saved_dummy->m_pos\t\t\t=\tm_pos;\r\n\tp_saved_dummy->m_vel\t\t\t=\tm_vel;\r\n\tp_saved_dummy->m_angles\t\t\t=\tm_angles;\r\n\tp_saved_dummy->m_ang_vel\t\t=\tm_ang_vel;\r\n\tp_saved_dummy->m_car_rotation_x       = m_car_rotation_x;      \r\n\tp_saved_dummy->m_car_rotation_x_vel   = m_car_rotation_x_vel;  \r\n\tp_saved_dummy->m_wheel_rotation_x     = m_wheel_rotation_x;    \r\n\tp_saved_dummy->m_wheel_rotation_x_vel = m_wheel_rotation_x_vel;\r\n\tp_saved_dummy->m_wheel_rotation_y     = m_wheel_rotation_y;    \r\n\tp_saved_dummy->m_wheel_rotation_y_vel = m_wheel_rotation_y_vel;\r\n\t\r\n\tp_saved_dummy->m_primaryController\t\t=\tm_primaryController;\r\n\t\r\n\tfor (int i=0; i<NUM_DEGENERATE_ANIMS; ++i)\r\n\t{\r\n\t\tp_saved_dummy->m_degenerateControllers[i]=m_degenerateControllers[i];\r\n\t}\r\n\t\r\n\tp_saved_dummy->mAtomicStates\t\t= mAtomicStates;\r\n\r\n\t// Note: m_looping_sound_id is not saved, since this is a unique id for the instance of the sound.\r\n\tp_saved_dummy->m_looping_sound_checksum = m_looping_sound_checksum;\r\n\tp_saved_dummy->m_pitch_min = m_pitch_min;\r\n\tp_saved_dummy->m_pitch_max = m_pitch_max;\r\n#endif\r\n}\r\n\r\nvoid CDummy::UpdateLoopingSound()\r\n{\r\n\tif (!m_looping_sound_checksum)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tfloat percent_of_max_speed=100.0f;\r\n\tfloat maxSpeed = 1100.0f;\r\n\tMth::Vector v=m_pos-m_old_pos;\r\n\tv[Y]=0.0f;\r\n\tfloat speed = v.Length( ) * 60.0f;\r\n\tif ( fabsf( speed ) < maxSpeed )\r\n\t{\r\n\t\tpercent_of_max_speed=( 100.0f * speed ) / maxSpeed;\r\n\t}\r\n\r\n\tSfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\t\r\n\tif (!m_looping_sound_id)\r\n\t{\r\n\t\tm_looping_sound_id = sfx_manager->PlaySound( m_looping_sound_checksum, 0, 0 );\r\n\t}\r\n\t\t\r\n\tSfx::sVolume vol;\r\n\tsfx_manager->SetVolumeFromPos( &vol, m_pos, sfx_manager->GetDropoffDist( m_looping_sound_checksum ) );\r\n\t\r\n\tvol.PercentageAdjustment( percent_of_max_speed );\r\n\r\n\tfloat pitch = PERCENT( m_pitch_max - m_pitch_min, percent_of_max_speed );\r\n\tpitch += m_pitch_min;\r\n\t\r\n\tsfx_manager->UpdateLoopingSound(m_looping_sound_id,&vol,pitch);\r\n}\t\t\r\n\r\nvoid CDummy::Update()\r\n{\r\n#if 0\r\n\tif (mFlags&DUMMY_FLAG_HOVERING)\r\n\t{\r\n\t\tm_angles[Y]+=DEGREES_TO_RADIANS(HOVER_ROTATE_SPEED)/60.0f;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_angles+=m_ang_vel;\r\n\t\tm_pos+=m_vel;\r\n\t\r\n\t\tif (m_type==SKATE_TYPE_CAR)\r\n\t\t{\r\n\t\t\tm_car_rotation_x\t+= m_car_rotation_x_vel; \r\n\t\t\tm_wheel_rotation_x\t+= m_wheel_rotation_x_vel;\r\n\t\t\tm_wheel_rotation_y\t+= m_wheel_rotation_y_vel;\r\n\t\t}\r\n\t\r\n\t\tif (m_list==PLAYBACK_DUMMY_LIST)\r\n\t\t{\r\n\t\t\tMth::Matrix mat(m_angles[X],m_angles[Y],m_angles[Z]);\r\n\t\t\tObj::CSkater *p_skater=sGetSkater();\r\n\t\t\t\r\n\t\t\tif (m_id==ID_SKATER)\r\n\t\t\t{\r\n\t\t\t\tp_skater->UpdateShadow(m_pos,mat);\r\n\t\t\t\t\r\n\t\t\t\t// Update the skater's pos and display matrix so that the sparks follow the dummy.\r\n\t\t\t\t// The skater's RestoreAfterReplayPlayback function will restore the skater's\r\n\t\t\t\t// original position when the replay ends.\r\n\t\t\t\tp_skater->SetActualDisplayMatrix(mat);\r\n\t\t\t\tp_skater->m_pos=m_pos;\r\n\t\t\t\t\r\n\t\t\t\tUpdateLoopingSound();\r\n\t\t\t}\t\r\n\t\t\telse if (m_id==ID_CAMERA)\r\n\t\t\t{\r\n\t\t\t\tif (!mp_skater_camera)\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_skater_camera=new Gfx::Camera;\r\n\t\t\t\t\t\r\n\t\t\t\t\t//mp_skater_camera=new Obj::CSkaterCam(0);\r\n\t\t\t\t\t//mp_skater_camera->SetMode( Obj::CSkaterCam::SKATERCAM_MODE_NORMAL_MEDIUM, 0.0f );\r\n\t\t\t\t\t//mp_skater_camera->SetSkater(p_skater);\r\n\t\t\t\t\t\r\n\t\t\t\t\tNx::CViewportManager::sSetCamera( /*m_skater_number*/0, mp_skater_camera );\t\t\t\r\n\t\t\t\t}\t\t\r\n\t\t\t\t\r\n\t\t\t\t//mp_skater_camera->Update();\r\n\t\t\t\tm_pos[W]=1.0f;\r\n\t\t\t\tmp_skater_camera->SetPos(m_pos);\r\n\t\t\t\tmp_skater_camera->SetMatrix(mat);\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n\t\r\n\tm_old_pos=m_pos;\r\n#endif\r\n}\r\n\r\nvoid CDummy::CreateModel()\r\n{\r\n#if 0\r\n\tDbg_MsgAssert(mp_rendered_model==NULL,(\"Called CreateModel() when model already exists\"));\r\n\r\n\tif (m_id==ID_SKATER)\r\n\t{\r\n\t\tObj::CSkater *p_skater=sGetSkater();\r\n\t\tmp_rendered_model=p_skater->GetModel();\r\n\t\t// This switches off any bouncing boobs on Jenna initially.\r\n\t\tDbg_Assert( p_skater->GetSkeleton() );\r\n\t\tp_skater->GetSkeleton()->SetProceduralBoneTransActive( 0x47c76c69/*breast_cloth_zz*/, 0 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (mpModelName[0]==0 && mProfileName==0 && mSectorName==0)\r\n\t\t{\r\n\t\t\tm_is_displayed=false;\r\n\t\t\treturn;\r\n\t\t}\r\n\t\r\n\t\tmp_rendered_model = Nx::CEngine::sInitModel();\r\n\t\tDbg_MsgAssert(mp_rendered_model,(\"sInitModel() returned NULL\"));\r\n\t\tMth::Vector scale(mScale,mScale,mScale);\r\n\t\tmp_rendered_model->SetScale(scale);\r\n\r\n\t\tswitch (m_type)\r\n\t\t{\r\n\t\t\tcase SKATE_TYPE_CAR:\r\n\t\t\t\tif (mSkeletonName)\r\n\t\t\t\t{\r\n\t\t\t\t\tthis->LoadSkeleton(mSkeletonName);\r\n\t\t\t\t}\r\n\t\t\t\tif (mpModelName[0])\r\n\t\t\t\t{\r\n\t\t\t\t\tmp_rendered_model->AddGeom(mpModelName, 0, true );\r\n\t\t\t\t}\t\t\r\n\t\t\t\tbreak;\r\n\t\t\tcase SKATE_TYPE_PED:\t\r\n\t\t\t\tif (mSkeletonName)\r\n\t\t\t\t{\r\n\t\t\t\t\tthis->LoadSkeleton(mSkeletonName);\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (mProfileName)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tGfx::CModelAppearance thePedAppearance;\r\n\t\t\t\t\t\tthePedAppearance.Load( mProfileName );\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tGfx::CModelBuilder theBuilder( true, 0 );\r\n\t\t\t\t\t\ttheBuilder.BuildModel( &thePedAppearance, mp_rendered_model );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tStr::String fullModelName;\r\n\t\t\t\t\t\tfullModelName = Gfx::GetModelFileName(mpModelName, \".skin\");\r\n\t\t\t\t\t\r\n\t\t\t\t\t\tmp_rendered_model->AddGeom(fullModelName.getString(), 0, true );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase SKATE_TYPE_GAME_OBJ:\t\r\n\t\t\tcase SKATE_TYPE_BOUNCY_OBJ:\t\r\n\t\t\t\tif (mSectorName)\r\n\t\t\t\t{\r\n\t\t\t\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(mSectorName);\r\n\t\t\t\t\t\r\n\t\t\t\t\tif ( p_sector )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// need to clone the source, not the instance?\r\n\t\t\t\t\t\tNx::CGeom* pGeom = p_sector->GetGeom();\r\n\t\t\t\t\t\tif( pGeom )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tNx::CGeom* pClonedGeom = pGeom->Clone( true );\r\n\t\t\t\t\t\t\tpClonedGeom->SetActive(true);\r\n\t\t\t\t\t\t\tmp_rendered_model->AddGeom( pClonedGeom, 0 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\r\n\t\t\t\telse if (mSkeletonName)\r\n\t\t\t\t{\r\n\t\t\t\t\tthis->LoadSkeleton(mSkeletonName);\r\n\t\t\t\t\t\r\n\t\t\t\t\tAss::CAssMan*\tass_manager = Ass::CAssMan::Instance();\r\n\t\t\t\t\tass_manager->SetReferenceChecksum( mAnimScriptName );\r\n\t\t\t\t\tScript::RunScript( mAnimScriptName );\r\n\t\t\t\t\t\r\n\t\t\t\t\tStr::String fullModelName;\r\n\t\t\t\t\tfullModelName = Gfx::GetModelFileName(mpModelName, \".skin\");\r\n\t\t\t\t\r\n\t\t\t\t\tmp_rendered_model->AddGeom(fullModelName.getString(), 0, true );\r\n\t\t\t\t}\r\n\t\t\t\telse if (mpModelName[0])\r\n\t\t\t\t{\r\n\t\t\t\t\tStr::String fullModelName;\r\n\t\t\t\t\tfullModelName = Gfx::GetModelFileName(mpModelName, \".mdl\");\r\n\t\t\t\t\t\r\n\t\t\t\t\tmp_rendered_model->AddGeom(fullModelName.getString(), 0, true );\r\n\t\t\t\t}\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\t\t\r\n\t}\t\r\n\t\r\n\t// Now initialise the atomic states according to the states stored in the dummy.\r\n\tDbg_MsgAssert(mp_rendered_model,(\"NULL mp_rendered_model\"));\r\n\tmp_rendered_model->SetGeomActiveMask(mAtomicStates);\r\n\r\n\tmp_rendered_model->SetActive(mFlags & DUMMY_FLAG_ACTIVE);\r\n\t\r\n\t// And initialise the flipped status\r\n\tGfx::CSkeleton* p_skeleton=this->GetSkeleton();\r\n\tif (m_id==ID_SKATER)\r\n\t{\r\n\t\tObj::CSkater *p_skater=sGetSkater();\r\n\t\tp_skeleton = p_skater->GetSkeleton();\r\n\t}\r\n#endif\r\n\r\n#if 0\r\n\tif (p_skeleton)\r\n\t{\r\n\t\tp_skeleton->FlipAnimation( 0, mFlags&DUMMY_FLAG_FLIPPED, 0, false );\r\n\t}\r\n#endif\r\n}\r\n\r\nvoid CDummy::DisplayModel()\r\n{\r\n\tif (mp_rendered_model && mp_rendered_model->GetActive())\r\n\t{\r\n\t\tMth::Matrix display_matrix(m_angles[X],m_angles[Y],m_angles[Z]);\r\n\t\tdisplay_matrix[Mth::POS] = m_pos;\r\n\t\tdisplay_matrix[Mth::POS][W] = 1.0f;\r\n\r\n\t\tbool should_animate=true;\r\n\t\tif (!mSkeletonName)\r\n\t\t{\r\n\t\t\tshould_animate=false;\r\n\t\t}\t\r\n\t\t\r\n\t\tswitch (m_type)\r\n\t\t{\r\n\t\t\tcase SKATE_TYPE_CAR:\r\n\t\t\t{\r\n\t\t\t\tif (!mp_rendered_model->GetHierarchy())\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\r\n\t\t\t\t// This updates the rotating wheels.\r\n\t\t\t\tObj::CalculateCarHierarchyMatrices( GetSkeleton(),\r\n                                                    mp_rendered_model,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tm_car_rotation_x,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tm_wheel_rotation_x,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tm_wheel_rotation_y);\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SKATE_TYPE_PED:\r\n\t\t\tcase SKATE_TYPE_SKATER:\r\n\t\t\tcase SKATE_TYPE_GAME_OBJ:\r\n\t\t\t\tif (should_animate)\r\n\t\t\t\t{\r\n//                    if ( mp_skeletonComponent )\r\n//                    {\r\n//                        mp_skeletonComponent->SetNeutralPose( mAnimScriptName+0x1ca1ff20/*default*/ );\r\n//                    }\r\n\t\t\t\t\t\r\n#if 0\r\n\t\t\t\t\tint degeneratingCount = 0;\r\n\t\t\t\t\tfor ( int i = 0; i < NUM_DEGENERATE_ANIMS; i++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( m_degenerateControllers[i].GetStatus() != Gfx::ANIM_STATUS_INACTIVE )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tdegeneratingCount++;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tif ( degeneratingCount )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// animation has blending...\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tuint32 degenerate_anim_name0,degenerate_anim_name1,degenerate_anim_name2;\r\n\t\t\t\t\t\tfloat degenerate_anim_time0,degenerate_anim_time1,degenerate_anim_time2;\r\n\t\t\t\t\t\tfloat degenerate_anim_blend_value0,degenerate_anim_blend_value1,degenerate_anim_blend_value2;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tm_degenerateControllers[0].GetNameTimeAndBlendValue(&degenerate_anim_name0,&degenerate_anim_time0,&degenerate_anim_blend_value0);\r\n\t\t\t\t\t\tm_degenerateControllers[1].GetNameTimeAndBlendValue(&degenerate_anim_name1,&degenerate_anim_time1,&degenerate_anim_blend_value1);\r\n\t\t\t\t\t\tm_degenerateControllers[2].GetNameTimeAndBlendValue(&degenerate_anim_name2,&degenerate_anim_time2,&degenerate_anim_blend_value2);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif (degenerate_anim_name0) degenerate_anim_name0+=mAnimScriptName;\r\n\t\t\t\t\t\tif (degenerate_anim_name1) degenerate_anim_name1+=mAnimScriptName;\r\n\t\t\t\t\t\tif (degenerate_anim_name2) degenerate_anim_name2+=mAnimScriptName;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t#if 0\r\n\t\t\t\t\t\t// disabled replays of skeletons until the transition is complete\r\n                        if ( mp_skeletonComponent )\r\n                        {\r\n                            mp_skeletonComponent->Update( \r\n                                mAnimScriptName+m_primaryController.GetAnimName(), m_primaryController.GetCurrentAnimTime(),\r\n                                degenerate_anim_name0,degenerate_anim_time0,degenerate_anim_blend_value0,\r\n                                degenerate_anim_name1,degenerate_anim_time1,degenerate_anim_blend_value1,\r\n                                degenerate_anim_name2,degenerate_anim_time2,degenerate_anim_blend_value2 );                        }\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t#if 0\r\n\t\t\t\t\t\t// disabled replays of skeletons until the transition is complete\r\n\t\t\t\t\t\tif ( mp_skeletonComponent )\r\n                        {\r\n                            mp_skeletonComponent->Update( mAnimScriptName+m_primaryController.GetAnimName(),\r\n\t\t\t\t\t\t\t\tm_primaryController.GetCurrentAnimTime() );\r\n                        }\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t}\r\n#endif\r\n\t\t\t\t\r\n\t\t\t\t}\t\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\t\t\r\n\r\n\r\n\t\tif (mFlags&DUMMY_FLAG_HOVERING)\r\n\t\t{\r\n\t\t\tuint32 t=Tmr::ElapsedTime(0)%mHoverPeriod;\r\n\t\t\tdisplay_matrix[Mth::POS][Y]+=HOVER_AMPLITUDE*sinf(t*2*3.141592653f/mHoverPeriod);\r\n\t\t}\r\n\t\t\r\n\t\tmp_rendered_model->Render(&display_matrix,!should_animate,GetSkeleton());\r\n\t}\t\r\n}\r\n\r\nvoid CDummy::UpdateMutedSounds()\r\n{\r\n\tGetSoundComponent()->UpdateMutedSounds();\r\n}\t\r\n\r\nstatic void sStopReplayDummyLoopingSounds()\r\n{\r\n\tSfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\t\r\n\tCDummy *p_dummy=spReplayDummies;\r\n\twhile (p_dummy)\r\n\t{\r\n\t\tif (p_dummy->m_looping_sound_id)\r\n\t\t{\r\n\t\t\tsfx_manager->StopSound( p_dummy->m_looping_sound_id );\r\n\t\t\tp_dummy->m_looping_sound_id=0;\r\n\t\t}\t\r\n\t\t\r\n\t\tp_dummy=p_dummy->mpNext;\r\n\t}\r\n}\r\n\t\t\r\nvoid ClearBuffer()\r\n{\r\n\tif (BufferAllocated())\r\n\t{\r\n\t\tFillBuffer(0,GetBufferSize(),BLANK);\r\n\t}\t\r\n\tsBigBufferStartOffset=0;\r\n\tsBigBufferEndOffset=0;\r\n\tsBufferFilling=true;\r\n}\r\n\r\nstatic uint8 spBufferChunk[REPLAY_BUFFER_CHUNK_SIZE];\r\nuint8 *GetTempBuffer()\r\n{\r\n\treturn spBufferChunk;\r\n}\r\n\t\r\nvoid WriteReplayDataHeader(SReplayDataHeader *p_header)\r\n{\r\n\tDbg_MsgAssert(p_header,(\"NULL p_header\"));\r\n\tp_header->mBufferStartOffset=sBigBufferStartOffset;\r\n\tp_header->mBufferEndOffset=sBigBufferEndOffset;\r\n\tp_header->mNumStartStateDummies=sCountStartStateDummies();\r\n\tp_header->mStartState=sStartState;\r\n}\r\n\r\nvoid ReadReplayDataHeader(const SReplayDataHeader *p_header)\r\n{\r\n\tDbg_MsgAssert(p_header,(\"NULL p_header\"));\r\n\tsBigBufferStartOffset=p_header->mBufferStartOffset;\r\n\tsBigBufferEndOffset=p_header->mBufferEndOffset;\r\n\tsStartState=p_header->mStartState;\r\n\tNx::CEngine::sReadSectorStatusBitfield(sStartState.mpSectorStatus,SECTOR_STATUS_BUFFER_SIZE);\r\n}\r\n\t\r\nvoid CreateDummyFromSaveData(SSavedDummy *p_saved_dummy)\r\n{\r\n#if 0\r\n\tDbg_MsgAssert(p_saved_dummy,(\"NULL p_saved_dummy\"));\r\n\t\r\n\tCDummy *p_dummy=new CDummy(START_STATE_DUMMY_LIST,p_saved_dummy->m_id);\r\n\tp_dummy->SetType(p_saved_dummy->m_type);\r\n\t\r\n\tDbg_MsgAssert(strlen(p_saved_dummy->mpModelName)<=MAX_MODEL_NAME_CHARS,(\"p_saved_dummy mpModelName too long ?\"));\r\n\tstrcpy(p_dummy->mpModelName,p_saved_dummy->mpModelName);\r\n\t\r\n\tp_dummy->mSkeletonName\t=\tp_saved_dummy->mSkeletonName;\r\n\tp_dummy->mProfileName\t=\tp_saved_dummy->mProfileName;\r\n\tp_dummy->mAnimScriptName=\tp_saved_dummy->mAnimScriptName;\r\n\tp_dummy->mSectorName\t=\tp_saved_dummy->mSectorName;\r\n\tp_dummy->mScale\t\t\t=\tp_saved_dummy->mScale;\r\n\tp_dummy->mFlags\t\t\t=\tp_saved_dummy->mFlags;\r\n\t// Note: The mHoverPeriod is not restored. No need, it does not need to be restored exactly,\r\n\t// and the CDummy constructor will have generated a new random value for it.\r\n\tp_dummy->m_pos\t\t\t=\tp_saved_dummy->m_pos;\r\n\tp_dummy->m_vel\t\t\t=\tp_saved_dummy->m_vel;\r\n\tp_dummy->m_angles\t\t=\tp_saved_dummy->m_angles;\r\n\tp_dummy->m_ang_vel\t\t=\tp_saved_dummy->m_ang_vel;\r\n\tp_dummy->m_car_rotation_x       = p_saved_dummy->m_car_rotation_x;      \r\n\tp_dummy->m_car_rotation_x_vel   = p_saved_dummy->m_car_rotation_x_vel;  \r\n\tp_dummy->m_wheel_rotation_x     = p_saved_dummy->m_wheel_rotation_x;    \r\n\tp_dummy->m_wheel_rotation_x_vel = p_saved_dummy->m_wheel_rotation_x_vel;\r\n\tp_dummy->m_wheel_rotation_y     = p_saved_dummy->m_wheel_rotation_y;    \r\n\tp_dummy->m_wheel_rotation_y_vel = p_saved_dummy->m_wheel_rotation_y_vel;\r\n\t\r\n\tp_dummy->m_primaryController\t=\tp_saved_dummy->m_primaryController;\r\n\t\r\n\tfor (int i=0; i<NUM_DEGENERATE_ANIMS; ++i)\r\n\t{\r\n\t\tp_dummy->m_degenerateControllers[i]=p_saved_dummy->m_degenerateControllers[i];\r\n\t}\r\n\t\r\n\tp_dummy->mAtomicStates\t\t\t= p_saved_dummy->mAtomicStates;\r\n\r\n\t// The looping sound id is not copied in, since it is a unique id for the instance of the sound.\r\n\tp_dummy->m_looping_sound_id=0;\r\n\tp_dummy->m_looping_sound_checksum = p_saved_dummy->m_looping_sound_checksum;\r\n\tp_dummy->m_pitch_min = p_saved_dummy->m_pitch_min;\r\n\tp_dummy->m_pitch_max = p_saved_dummy->m_pitch_max;\r\n\t\r\n\t// This is because for the skater dummy the speed for calculating the looping sound\r\n\t// volume is calculated using m_old_pos. If it were left equal to 0,0,0 it would cause the\r\n\t// looping sound to be played at max volume for the first frame, because it would think\r\n\t// the skater was moving very fast.\r\n\tp_dummy->m_old_pos=p_dummy->m_pos;\r\n#endif\r\n}\r\n\r\nstatic bool sPoolsCreated=false;\r\n//char p_foo[sizeof(CTrackingInfo)/0];\r\nvoid CreatePools()\r\n{\r\n\tif (!sPoolsCreated)\r\n\t{\r\n\t\t// MEMOPT: Make this pool smaller\r\n\t\tCTrackingInfo::SCreatePool(300, \"CTrackingInfo\");\r\n\t\tsPoolsCreated=true;\r\n\t}\t\r\n}\r\n\r\nvoid RemovePools()\r\n{\r\n\tif (sPoolsCreated)\r\n\t{\r\n\t\tCTrackingInfo::SRemovePool();\r\n\t\tsPoolsCreated=false;\r\n\t}\t\r\n}\r\n\r\nbool ScriptReplayRecordSimpleScriptCall(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\t// Do nothing if not in record mode.\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\t\r\n\tuint32 script_name=0;\r\n\tpParams->GetChecksum(\"scriptname\",&script_name);\r\n\t\r\n\tif (pParams->ContainsFlag(\"skaterscript\"))\r\n\t{\r\n\t\tsWriteUint32(SKATER_SCRIPT_CALL,script_name);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsWriteUint32(SCRIPT_CALL,script_name);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nstatic uint32 sLastRecordedPanelMessageID=0;\r\nbool ScriptRecordPanelMessage(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Remember what the last panel message id was so that it can be killed before\r\n\t// replaying the replay.\r\n\t//sLastRecordedPanelMessageID=0;\r\n\t//pParams->GetChecksum(\"id\",&sLastRecordedPanelMessageID);\r\n\t\r\n\tFront::CScreenElementManager* p_manager = Front::CScreenElementManager::Instance();\r\n\tsLastRecordedPanelMessageID = p_manager->ResolveComplexID(pParams, \"id\");\r\n\t\r\n\t\r\n\t\r\n\tuint8 p_buf[MAX_PANEL_MESSAGE_SIZE];\r\n\tint size=Script::WriteToBuffer(pParams,p_buf,MAX_PANEL_MESSAGE_SIZE,Script::NO_ASSERT);\r\n\tif (!size)\r\n\t{\r\n\t\tScript::PrintContents(pParams);\r\n\t\tDbg_MsgAssert(0,(\"Panel message structure too big\"));\r\n\t\treturn true;\r\n\t}\t\r\n\t\r\n\tsWriteUint32(PANEL_MESSAGE,size);\r\n\t\r\n\tDbg_MsgAssert(spFrameBufferPos+size <= spFrameBuffer+FRAME_BUFFER_SIZE,(\"Replay frame buffer overflow\"));\r\n\tmemcpy(spFrameBufferPos,p_buf,size);\r\n\tspFrameBufferPos+=size;\r\n\t\r\n\treturn true;\r\n}\r\n\t\r\n// Call this to allocate the resources needed to store a replay.\r\n// May be called repeatedly.\r\nbool ScriptAllocateReplayMemory(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\treturn true;\r\n\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n\tAllocateBuffer();\r\n\tClearBuffer();\r\n\tCreatePools();\r\n\tMem::Manager::sHandle().PopContext();\r\n\tsMode=RECORD;\t\r\n\t\r\n\tCTrackingInfo::sSkaterTrackingInfo.Reset();\r\n\tNx::CEngine::sInitReplayStartState();\r\n\treturn true;\r\n}\r\n\r\nvoid DeallocateReplayMemory()\r\n{\r\n\tsDeleteDummies(START_STATE_DUMMY_LIST);\r\n\tsDeleteDummies(PLAYBACK_DUMMY_LIST);\r\n\tDbg_MsgAssert(spReplayDummies==NULL,(\"Hey! spReplayDummies not NULL !!!\"));\r\n\tsDeleteObjectTrackingInfo();\r\n\tClearBuffer();\r\n\tDeallocateBuffer();\r\n\tRemovePools();\r\n\tsStartState.Reset();\r\n\tsCurrentState.Reset();\r\n\tsMode=NONE;\r\n}\r\n\r\n// Call this to free up the resources used to store a replay.\r\n// May be called repeatedly.\r\nbool ScriptDeallocateReplayMemory(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tDeallocateReplayMemory();\r\n\treturn true;\r\n}\t\r\n\r\n// If in record mode, this will clear what has been recorded and start afresh.\r\nvoid StartRecordingAfresh()\r\n{\r\n\tDbg_MsgAssert(!Mdl::Skate::Instance()->IsMultiplayerGame(),(\"Tried to start recording replay in multiplayer game\"));\r\n\tsMode=RECORD;\r\n\r\n\tsDeleteDummies(START_STATE_DUMMY_LIST);\r\n\tsDeleteDummies(PLAYBACK_DUMMY_LIST);\r\n\tDbg_MsgAssert(spReplayDummies==NULL,(\"Hey! spReplayDummies not NULL !!!\"));\r\n\tsDeleteObjectTrackingInfo();\r\n\tClearBuffer();\r\n\tsStartState.Reset();\r\n\tsCurrentState.Reset();\r\n\tCTrackingInfo::sSkaterTrackingInfo.Reset();\r\n\tNx::CEngine::sInitReplayStartState();\r\n}\r\n\r\nbool ScriptStartRecordingAfresh(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tif (Mdl::Skate::Instance()->IsMultiplayerGame())\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\tStartRecordingAfresh();\r\n\treturn true;\r\n}\t\r\n\r\nstatic uint32 sReadAnimControllerChanges(uint32 offset, Gfx::CAnimChannel *p_anim_controller)\r\n{\r\n\t#define MAX_CHANGES 18\r\n\tuint8 p_buf[5*MAX_CHANGES];\r\n\t\r\n\tuint8 num_changes;\r\n\tReadFromBuffer(&num_changes,offset,1);\r\n\t++offset;\r\n\tDbg_MsgAssert(num_changes<=MAX_CHANGES,(\"Too many anim controller changes in one instruction\"));\r\n\t\r\n\tReadFromBuffer(p_buf,offset,5*num_changes);\r\n\toffset+=5*num_changes;\r\n\t\r\n\tuint32 *p_dest=(uint32*)p_anim_controller;\r\n\tuint8 *p_foo=p_buf;\r\n\tfor (int i=0; i<num_changes; ++i)\r\n\t{\r\n\t\tuint8 off=*p_foo++;\r\n\t\tDbg_MsgAssert(off<sizeof(Gfx::CAnimChannel)/4,(\"Bad offset of %d in anim controller change instruction\",off));\r\n\t\tp_dest[off]=Script::Read4Bytes(p_foo).mUInt;\r\n\t\tp_foo+=4;\r\n\t}\r\n\r\n\treturn offset;\r\n}\r\n\r\n\r\n#define TRICK_TEXT_BUF_SIZE 5000\r\nstatic char spTrickText[TRICK_TEXT_BUF_SIZE];\r\n// TODO: This is duplicated in score.cpp, move it to a header ...\r\nconst int TRICK_LIMIT = 250;\r\n\r\n#ifdef CHECK_TOKEN_USAGE\r\nstatic int sTokenCount[NUM_REPLAY_TOKEN_TYPES];\r\n#endif\r\n\r\n// If the offset points to a frame, ie data that starts with the FRAME_START token, it will\r\n// skip over it and return the new offset.\r\n// If nothing follows the frame, it will set the contents of p_nothingFollows to true, false otherwise.\r\n// Nothing follows the frame if either it is followed by a BLANK token, or if the offset following\r\n// it is the end of the big buffer.\r\n//\r\n// If offset does not point to a FRAME_START token, then the returned offset will be unchanged.\r\nstatic uint32 sReadFrame(uint32 offset, bool *p_nothingFollows, EDummyList whichList)\r\n{\r\n\tDbg_MsgAssert(p_nothingFollows,(\"NULL p_nothingFollows\"));\r\n\tDbg_MsgAssert(offset<GetBufferSize(),(\"Bad offset sent to sReadFrame\"));\r\n\r\n\t#ifdef CHECK_TOKEN_USAGE\r\n\tfor (int i=0; i<NUM_REPLAY_TOKEN_TYPES; ++i)\r\n\t{\r\n\t\tsTokenCount[i]=0;\r\n\t}\t\r\n\t#endif\r\n\r\n\r\n\tuint8 token;\r\n\tReadFromBuffer(&token,offset,1);\r\n\tif (token!=FRAME_START)\r\n\t{\r\n\t\t*p_nothingFollows=true;\r\n\t\treturn offset;\r\n\t}\t\r\n\toffset+=5;\r\n\r\n\r\n\tObj::CSkater *p_skater=sGetSkater();\r\n\t\r\n\tLst::HashTable<CDummy> *p_dummy_table=sGetDummyHashTable(whichList);\r\n\t*p_nothingFollows=false;\r\n\tCDummy *p_dummy=NULL;\r\n\tbool end=false;\r\n\twhile (!end)\r\n\t{\r\n\t\tif (offset==GetBufferSize())\r\n\t\t{\r\n\t\t\t*p_nothingFollows=true;\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tDbg_MsgAssert(offset<GetBufferSize(),(\"sReadFrame went past the end of the buffer\"));\r\n\t\t\r\n\t\tReadFromBuffer(&token,offset,1);\r\n\t\t\r\n\t\t#ifdef CHECK_TOKEN_USAGE\r\n\t\tDbg_MsgAssert(token<NUM_REPLAY_TOKEN_TYPES,(\"Bad token\"));\r\n\t\t++sTokenCount[token];\r\n\t\t#endif\r\n\t\t\r\n\t\tswitch (token)\r\n\t\t{\r\n\t\t\tcase BLANK:\r\n\t\t\t\t*p_nothingFollows=true;\r\n\t\t\t\tend=true;\r\n\t\t\t\tbreak;\r\n\t\t\t\t\r\n\t\t\tcase FRAME_START:\t\r\n\t\t\t\tend=true;\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase SCREEN_BLUR:\r\n\t\t\t{\r\n\t\t\t\t// Must not do blurs if recording\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\toffset+=1+4;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t++offset;\r\n\t\t\t\tint amount;\r\n\t\t\t\tReadFromBuffer((uint8*)&amount,offset,4);\r\n\t\t\t\tamount=Script::Read4Bytes((uint8*)&amount).mInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tNx::CEngine::sSetScreenBlur(amount);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tcase SCREEN_FLASH:\r\n\t\t\t{\r\n\t\t\t\t// Must not do flashes if recording\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\toffset+=1+4*6;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t++offset;\r\n\t\t\t\t\r\n\t\t\t\tint viewport;\r\n\t\t\t\tReadFromBuffer((uint8*)&viewport,offset,4);\r\n\t\t\t\tviewport=Script::Read4Bytes((uint8*)&viewport).mInt;\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\tImage::RGBA from;\r\n\t\t\t\tReadFromBuffer((uint8*)&from,offset,4);\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tImage::RGBA to;\r\n\t\t\t\tReadFromBuffer((uint8*)&to,offset,4);\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\tfloat duration;\r\n\t\t\t\tReadFromBuffer((uint8*)&duration,offset,4);\r\n\t\t\t\tduration=Script::Read4Bytes((uint8*)&duration).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tfloat z;\r\n\t\t\t\tReadFromBuffer((uint8*)&z,offset,4);\r\n\t\t\t\tz=Script::Read4Bytes((uint8*)&z).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tuint32 flags;\r\n\t\t\t\tReadFromBuffer((uint8*)&flags,offset,4);\r\n\t\t\t\tflags=Script::Read4Bytes((uint8*)&flags).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tflags|=Nx::SCREEN_FLASH_FLAG_IGNORE_PAUSE;\r\n\t\t\t\t\r\n\t\t\t\tNx::AddScreenFlash(viewport,from,to,duration,z,flags,NULL);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tcase SHATTER_PARAMS:\r\n\t\t\t{\r\n\t\t\t\t// Must not do shatters if recording\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\toffset+=1+4*9;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t++offset;\r\n\t\t\t\t\r\n\t\t\t\tMth::Vector velocity;\r\n\t\t\t\tReadFromBuffer((uint8*)&velocity[X],offset,4*3);\r\n\t\t\t\tvelocity[X]=Script::Read4Bytes((uint8*)&velocity[X]).mFloat;\r\n\t\t\t\tvelocity[Y]=Script::Read4Bytes((uint8*)&velocity[Y]).mFloat;\r\n\t\t\t\tvelocity[Z]=Script::Read4Bytes((uint8*)&velocity[Z]).mFloat;\r\n\t\t\t\toffset+=4*3;\r\n\t\t\t\t\r\n\t\t\t\tfloat area_test, velocity_variance, spread_factor, lifetime;\r\n\t\t\t\tfloat bounce, bounce_amplitude;\r\n\t\t\t\t\r\n\t\t\t\tReadFromBuffer((uint8*)&area_test,offset,4);\r\n\t\t\t\tarea_test=Script::Read4Bytes((uint8*)&area_test).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&velocity_variance,offset,4);\r\n\t\t\t\tvelocity_variance=Script::Read4Bytes((uint8*)&velocity_variance).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&spread_factor,offset,4);\r\n\t\t\t\tspread_factor=Script::Read4Bytes((uint8*)&spread_factor).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&lifetime,offset,4);\r\n\t\t\t\tlifetime=Script::Read4Bytes((uint8*)&lifetime).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&bounce,offset,4);\r\n\t\t\t\tbounce=Script::Read4Bytes((uint8*)&bounce).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&bounce_amplitude,offset,4);\r\n\t\t\t\tbounce_amplitude=Script::Read4Bytes((uint8*)&bounce_amplitude).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tNx::ShatterSetParams( velocity, area_test, velocity_variance, spread_factor, lifetime, bounce, bounce_amplitude );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tcase TEXTURE_SPLAT:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\t\r\n\t\t\t\tMth::Vector splat_start;\r\n\t\t\t\tReadFromBuffer((uint8*)&splat_start[X],offset,4*3);\r\n\t\t\t\tsplat_start[X]=Script::Read4Bytes((uint8*)&splat_start[X]).mFloat;\r\n\t\t\t\tsplat_start[Y]=Script::Read4Bytes((uint8*)&splat_start[Y]).mFloat;\r\n\t\t\t\tsplat_start[Z]=Script::Read4Bytes((uint8*)&splat_start[Z]).mFloat;\r\n\t\t\t\toffset+=4*3;\r\n\r\n\t\t\t\tMth::Vector splat_end;\r\n\t\t\t\tReadFromBuffer((uint8*)&splat_end[X],offset,4*3);\r\n\t\t\t\tsplat_end[X]=Script::Read4Bytes((uint8*)&splat_end[X]).mFloat;\r\n\t\t\t\tsplat_end[Y]=Script::Read4Bytes((uint8*)&splat_end[Y]).mFloat;\r\n\t\t\t\tsplat_end[Z]=Script::Read4Bytes((uint8*)&splat_end[Z]).mFloat;\r\n\t\t\t\toffset+=4*3;\r\n\r\n\t\t\t\tfloat size;\r\n\t\t\t\tReadFromBuffer((uint8*)&size,offset,4);\r\n\t\t\t\tsize=Script::Read4Bytes((uint8*)&size).mFloat;\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\tfloat lifetime;\r\n\t\t\t\tReadFromBuffer((uint8*)&lifetime,offset,4);\r\n\t\t\t\tlifetime=Script::Read4Bytes((uint8*)&lifetime).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tuint8 len;\r\n\t\t\t\tReadFromBuffer(&len,offset,1);\r\n\t\t\t\t++offset;\r\n\t\t\t\tchar p_text[100];\r\n\t\t\t\tDbg_MsgAssert(len<100,(\"Texture splat file name string too long\\n\"));\r\n\t\t\t\tReadFromBuffer((uint8*)p_text,offset,len);\r\n\t\t\t\toffset+=len;\r\n\t\t\t\tp_text[len]=0;\r\n\r\n\t\t\t\tuint32 trail;\r\n\t\t\t\tReadFromBuffer((uint8*)&trail,offset,4);\r\n\t\t\t\ttrail=Script::Read4Bytes((uint8*)&trail).mUInt;\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\t// Must not do splats if recording\r\n\t\t\t\t// Still need to do the above reads due to the string that needs to be\r\n\t\t\t\t// skipped over.\r\n\t\t\t\tif (sMode!=RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\tNx::TextureSplat(splat_start,splat_end,size,lifetime,p_text,trail);\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tcase SHATTER_ON:\r\n\t\t\tcase SHATTER_OFF:\r\n\t\t\t{\r\n\t\t\t\t// Must not do shatters if recording\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\toffset+=1+4;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t++offset;\r\n\r\n\t\t\t\tuint32 sector_name;\r\n\t\t\t\tReadFromBuffer((uint8*)&sector_name,offset,4);\r\n\t\t\t\tsector_name=Script::Read4Bytes((uint8*)&sector_name).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\r\n\t\t\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(sector_name);\r\n\t\t\t\tif (p_sector)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_sector->SetShatter(token==SHATTER_ON);\r\n\t\t\t\t}\t\r\n\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t\r\n\t\t\tcase SCRIPT_CALL:\t\r\n\t\t\tcase SKATER_SCRIPT_CALL: // Used to record BloodParticlesOn & off\r\n\t\t\t{\r\n\t\t\t\t// Must not call the script if recording.\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\toffset+=1+4;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t++offset;\r\n\r\n\t\t\t\tuint32 script_name;\r\n\t\t\t\tReadFromBuffer((uint8*)&script_name,offset,4);\r\n\t\t\t\tscript_name=Script::Read4Bytes((uint8*)&script_name).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tif (token==SCRIPT_CALL)\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript(script_name);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tScript::RunScript( script_name, NULL, p_skater );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase PAD_VIBRATION:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint8 actuator;\r\n\t\t\t\tReadFromBuffer(&actuator,offset,1);\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(actuator<Obj::CVibrationComponent::vVB_NUM_ACTUATORS,(\"Bad actuator value of %d\",actuator));\r\n\t\t\t\t\r\n\t\t\t\tint percent;\r\n\t\t\t\tReadFromBuffer((uint8*)&percent,offset,4);\r\n\t\t\t\tpercent=Script::Read4Bytes((uint8*)&percent).mInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tif (whichList==START_STATE_DUMMY_LIST)\r\n\t\t\t\t{\r\n\t\t\t\t\tsStartState.mActuatorStrength[actuator]=percent;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tsCurrentState.mActuatorStrength[actuator]=percent;\r\n\t\t\t\t\tp_skater->GetDevice()->ActivateActuator(actuator,percent);\r\n\t\t\t\t}\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\t// This command is needed because when the goal cutscenes play in mid goal\r\n\t\t\t// they do a PauseSkaters command, which in-game pauses the vibrations.\r\n\t\t\t// Need to do that in the replay too, otherwise in the 4 angry seals goal in sf\r\n\t\t\t// the pad vibrates during the camera anims, cos the skater is usually in a grind then.\r\n\t\t\tcase PAUSE_SKATER:\t\r\n\t\t\tcase UNPAUSE_SKATER:\t\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\t\r\n\t\t\t\tif (whichList==START_STATE_DUMMY_LIST)\r\n\t\t\t\t{\r\n\t\t\t\t\tsStartState.mSkaterPaused=(token==PAUSE_SKATER);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tsCurrentState.mSkaterPaused=(token==PAUSE_SKATER);\r\n\t\t\t\t\tif (sCurrentState.mSkaterPaused)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Switch off the vibrations.\r\n\t\t\t\t\t\tfor (int i=0; i<Obj::CVibrationComponent::vVB_NUM_ACTUATORS; ++i)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_skater->GetDevice()->ActivateActuator(i,0);\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Restore the vibrations.\r\n\t\t\t\t\t\tfor (int i=0; i<Obj::CVibrationComponent::vVB_NUM_ACTUATORS; ++i)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tp_skater->GetDevice()->ActivateActuator(i,sCurrentState.mActuatorStrength[i]);\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tcase MANUAL_METER_ON:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tfloat value;\r\n\t\t\t\tReadFromBuffer((uint8*)&value,offset,4);\r\n\t\t\t\tvalue=Script::Read4Bytes((uint8*)&value).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tif (whichList==START_STATE_DUMMY_LIST)\r\n\t\t\t\t{\r\n\t\t\t\t\tsStartState.mManualMeterStatus=true;\r\n\t\t\t\t\tsStartState.mManualMeterValue=value;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tsCurrentState.mManualMeterStatus=true;\r\n\t\t\t\t\tsCurrentState.mManualMeterValue=value;\r\n\t\t\t\t\tsGetSkaterScoreObject()->SetManualMeter(true,value);\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase MANUAL_METER_OFF:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\t\t\r\n\t\t\t\tif (whichList==START_STATE_DUMMY_LIST)\r\n\t\t\t\t{\r\n\t\t\t\t\tsStartState.mManualMeterStatus=false;\r\n\t\t\t\t\tsStartState.mManualMeterValue=0.0f;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tsCurrentState.mManualMeterStatus=false;\r\n\t\t\t\t\tsCurrentState.mManualMeterValue=0.0f;\r\n\t\t\t\t\tsGetSkaterScoreObject()->SetManualMeter(false);\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tcase BALANCE_METER_ON:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tfloat value;\r\n\t\t\t\tReadFromBuffer((uint8*)&value,offset,4);\r\n\t\t\t\tvalue=Script::Read4Bytes((uint8*)&value).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tif (whichList==START_STATE_DUMMY_LIST)\r\n\t\t\t\t{\r\n\t\t\t\t\tsStartState.mBalanceMeterStatus=true;\r\n\t\t\t\t\tsStartState.mBalanceMeterValue=value;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tsCurrentState.mBalanceMeterStatus=true;\r\n\t\t\t\t\tsCurrentState.mBalanceMeterValue=value;\r\n\t\t\t\t\tsGetSkaterScoreObject()->SetBalanceMeter(true,value);\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase BALANCE_METER_OFF:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\t\t\r\n\t\t\t\tif (whichList==START_STATE_DUMMY_LIST)\r\n\t\t\t\t{\r\n\t\t\t\t\tsStartState.mBalanceMeterStatus=false;\r\n\t\t\t\t\tsStartState.mBalanceMeterValue=0.0f;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tsCurrentState.mBalanceMeterStatus=false;\r\n\t\t\t\t\tsCurrentState.mBalanceMeterValue=0.0f;\r\n\t\t\t\t\tsGetSkaterScoreObject()->SetBalanceMeter(false);\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n#if 0\r\n\t\t\tcase FLIP:\t\r\n\t\t\tcase UNFLIP:\t\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\t\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tif (token==FLIP)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_dummy->mFlags|=DUMMY_FLAG_FLIPPED;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_dummy->mFlags&=~DUMMY_FLAG_FLIPPED;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (whichList==PLAYBACK_DUMMY_LIST && p_dummy->mp_rendered_model)\r\n\t\t\t\t{\r\n\t\t\t\t\tGfx::CSkeleton* p_skeleton=p_dummy->GetSkeleton();\r\n\t\t\t\t\tif (p_skeleton)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_skeleton->FlipAnimation( 0, p_dummy->mFlags&DUMMY_FLAG_FLIPPED, 0, false );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n#endif\r\n\r\n\t\t\tcase MODEL_ACTIVE:\t\r\n\t\t\tcase MODEL_INACTIVE:\t\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\t\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tif (token==MODEL_ACTIVE)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_dummy->mFlags|=DUMMY_FLAG_ACTIVE;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_dummy->mFlags&=~DUMMY_FLAG_ACTIVE;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (whichList==PLAYBACK_DUMMY_LIST && p_dummy->mp_rendered_model)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_dummy->mp_rendered_model->SetActive(p_dummy->mFlags&DUMMY_FLAG_ACTIVE);\r\n\t\t\t\t}\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tcase SPARKS_ON:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\t// Must not do sparks if recording\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tScript::RunScript( \"sparks_on\", NULL, p_skater );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tcase SPARKS_OFF:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tScript::RunScript( \"sparks_off\", NULL, p_skater );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase PANEL_MESSAGE:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tint size;\r\n\t\t\t\tReadFromBuffer((uint8*)&size,offset,4);\r\n\t\t\t\tsize=Script::Read4Bytes((uint8*)&size).mInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tuint8 p_buf[MAX_PANEL_MESSAGE_SIZE];\r\n\t\t\t\tDbg_MsgAssert(size<=MAX_PANEL_MESSAGE_SIZE,(\"Panel message size too big in replay\"));\r\n\t\t\t\tReadFromBuffer(p_buf,offset,size);\r\n\t\t\t\toffset+=size;\r\n\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tScript::CStruct *p_struct=new Script::CStruct;\r\n\t\t\t\tScript::ReadFromBuffer(p_struct,p_buf);\r\n\t\t\t\tScript::RunScript(\"Create_Panel_Message\",p_struct);\r\n\t\t\t\tdelete p_struct;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\tcase SCORE_POT_TEXT:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint8 len;\r\n\t\t\t\tReadFromBuffer(&len,offset,1);\r\n\t\t\t\t++offset;\r\n\t\t\t\tchar p_text[100];\r\n\t\t\t\tif (len<100)\r\n\t\t\t\t{\r\n\t\t\t\t\tReadFromBuffer((uint8*)p_text,offset,len);\r\n\t\t\t\t\tp_text[len]=0;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_text[0]=0;\r\n\t\t\t\t}\r\n\t\t\t\toffset+=len;\r\n\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tFront::CScreenElementManager* p_manager = Front::CScreenElementManager::Instance();\r\n\t\t\t\t\r\n\t\t\t\tint index = p_skater->GetHeapIndex();\r\n\r\n\t\t\t\tFront::CTextElement *p_score_pot_text = (Front::CTextElement *) p_manager->GetElement(0xf4d3a70e + index ).Convert(); // \"the_score_pot_text\"\r\n\t\t\t\tif (p_score_pot_text)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_score_pot_text->SetText(p_text);\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase TRICK_TEXT:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint8 num_strings;\r\n\t\t\t\tReadFromBuffer(&num_strings,offset,1);\r\n\t\t\t\t++offset;\r\n\r\n\t\t\t\tconst char *pp_text[TRICK_LIMIT];\r\n\t\t\t\tint num_strings_loaded=0;\r\n\t\t\t\tchar *p_dest=spTrickText;\r\n\t\t\t\tfor (uint8 i=0; i<num_strings; ++i)\r\n\t\t\t\t{\r\n\t\t\t\t\tuint8 len;\r\n\t\t\t\t\tReadFromBuffer(&len,offset,1);\r\n\t\t\t\t\t++offset;\r\n\r\n\t\t\t\t\t// Only copy the string into the buffer if there is enough room,\r\n\t\t\t\t\t// for safety. Not asserting, in case this happens on a release build.\r\n\t\t\t\t\tif (p_dest+len+1-spTrickText < TRICK_TEXT_BUF_SIZE && num_strings_loaded<TRICK_LIMIT)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpp_text[num_strings_loaded++]=p_dest;\r\n\t\t\t\t\t\tReadFromBuffer((uint8*)p_dest,offset,len);\r\n\t\t\t\t\t\tp_dest+=len;\r\n\t\t\t\t\t\t*p_dest++=0;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\toffset+=len;\r\n\t\t\t\t}\t\r\n\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tFront::CScreenElementManager* p_manager = Front::CScreenElementManager::Instance();\r\n\t\t\t\t\t\r\n\t\t\t\t\tint index=p_skater->GetHeapIndex();\r\n\t\t\t\t\t\r\n\t\t\t\t\tFront::CTextBlockElement *p_text_block = (Front::CTextBlockElement *) p_manager->GetElement(0x44727dae/*the_trick_text*/ + index ).Convert();\r\n\t\t\t\t\tif (p_text_block)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_text_block->SetText(pp_text, num_strings_loaded);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsTrickTextGotCleared=false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tcase TRICK_TEXT_PULSE:\r\n\t\t\tcase TRICK_TEXT_COUNTDOWN:\r\n\t\t\tcase TRICK_TEXT_LANDED:\r\n\t\t\tcase TRICK_TEXT_BAIL:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tif (sTrickTextGotCleared)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\tint index=p_skater->GetHeapIndex();\r\n\t\t\t\t\r\n\t\t\t\tMdl::Score *p_score=p_skater->GetScoreObject();\r\n\t\t\t\t\r\n\t\t\t\tswitch (token)\r\n\t\t\t\t{\r\n\t\t\t\t\tcase TRICK_TEXT_PULSE:\r\n\t\t\t\t\t\tp_score->TrickTextPulse(index);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase TRICK_TEXT_COUNTDOWN:\r\n\t\t\t\t\t\tp_score->TrickTextCountdown(index);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase TRICK_TEXT_LANDED:\r\n\t\t\t\t\t\tp_score->TrickTextLanded(index);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase TRICK_TEXT_BAIL:\r\n\t\t\t\t\t\tp_score->TrickTextBail(index);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase SET_ATOMIC_STATES:\t\t\t\t\t\t\t\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint32 id;\r\n\t\t\t\tReadFromBuffer((uint8*)&id,offset,4);\r\n\t\t\t\tid=Script::Read4Bytes((uint8*)&id).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tuint32 atomic_states;\r\n\t\t\t\tReadFromBuffer((uint8*)&atomic_states,offset,4);\r\n\t\t\t\tatomic_states=Script::Read4Bytes((uint8*)&atomic_states).mUInt;\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\tp_dummy=p_dummy_table->GetItem(id);\r\n\t\t\t\tif (p_dummy)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Record the atomic state change in the dummy too, so that the initial states\r\n\t\t\t\t\t// can be set at the start of replay playback.\r\n\t\t\t\t\tp_dummy->mAtomicStates=atomic_states;\r\n\t\t\t\t\r\n\t\t\t\t\tif (p_dummy->mp_rendered_model)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tp_dummy->mp_rendered_model->SetGeomActiveMask(atomic_states);\r\n\t\t\t\t\t}\t\t\t\t\r\n\t\t\t\t}\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase PLAY_STREAM:\r\n\t\t\t{\r\n\t\t\t\t// Must not play sounds if recording\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\toffset+=1+4*5;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint32 checksum;\r\n//\t\t\t\tfloat volume_l, volume_r;\r\n\t\t\t\tfloat vol;\r\n\t\t\t\tfloat pitch;\r\n\r\n\t\t\t\tint priority;\r\n\t\t\t\tReadFromBuffer((uint8*)&checksum,offset,4);\r\n\t\t\t\tchecksum=Script::Read4Bytes((uint8*)&checksum).mUInt;\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\tuint32 volume_type;\r\n\t\t\t\tReadFromBuffer((uint8*)&volume_type,offset,4);\r\n\t\t\t\tvolume_type=Script::Read4Bytes((uint8*)&volume_type).mInt;\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\tSfx::sVolume vol_struct((Sfx::EVolumeType)volume_type );\r\n\r\n\t\t\t\tReadFromBuffer((uint8*)&vol,offset,4);\r\n\t\t\t\tvol=Script::Read4Bytes((uint8*)&vol).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tvol_struct.SetChannelVolume( 0, vol );\r\n\r\n\t\t\t\tReadFromBuffer((uint8*)&vol,offset,4);\r\n\t\t\t\tvol=Script::Read4Bytes((uint8*)&vol).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tvol_struct.SetChannelVolume( 1, vol );\r\n\r\n\t\t\t\t// Read channels 2, 3 and 4 if a 5 channel sound type.\r\n\t\t\t\tif( vol_struct.GetVolumeType() == Sfx::VOLUME_TYPE_5_CHANNEL_DOLBY5_1 )\r\n\t\t\t\t{\r\n\t\t\t\t\tReadFromBuffer((uint8*)&vol,offset,4);\r\n\t\t\t\t\tvol=Script::Read4Bytes((uint8*)&vol).mFloat;\r\n\t\t\t\t\toffset+=4;\r\n\t\t\t\t\tvol_struct.SetChannelVolume( 2, vol );\r\n\r\n\t\t\t\t\tReadFromBuffer((uint8*)&vol,offset,4);\r\n\t\t\t\t\tvol=Script::Read4Bytes((uint8*)&vol).mFloat;\r\n\t\t\t\t\toffset+=4;\r\n\t\t\t\t\tvol_struct.SetChannelVolume( 3, vol );\r\n\r\n\t\t\t\t\tReadFromBuffer((uint8*)&vol,offset,4);\r\n\t\t\t\t\tvol=Script::Read4Bytes((uint8*)&vol).mFloat;\r\n\t\t\t\t\toffset+=4;\r\n\t\t\t\t\tvol_struct.SetChannelVolume( 4, vol );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tReadFromBuffer((uint8*)&pitch,offset,4);\r\n\t\t\t\tpitch=Script::Read4Bytes((uint8*)&pitch).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&priority,offset,4);\r\n\t\t\t\tpriority=Script::Read4Bytes((uint8*)&priority).mInt;\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\tPcm::PlayStream(checksum,&vol_struct,pitch,priority);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tcase STOP_STREAM:\r\n\t\t\t{\r\n\t\t\t\t// Must not stop streams if recording\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\toffset+=1+4;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t++offset;\r\n\t\t\t\tint channel;\r\n\t\t\t\tReadFromBuffer((uint8*)&channel,offset,4);\r\n\t\t\t\tchannel=Script::Read4Bytes((uint8*)&channel).mInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tPcm::StopStreams(channel);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\tcase PLAY_POSITIONAL_STREAM:\r\n\t\t\t{\r\n\t\t\t\t// Must not play sounds if recording\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\toffset+=1+4*7;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint32 id, stream_name;\r\n\t\t\t\tfloat volume, pitch, drop_off;\r\n\t\t\t\tint priority, use_pos_info;\r\n\t\t\t\tReadFromBuffer((uint8*)&id,offset,4);\r\n\t\t\t\tid=Script::Read4Bytes((uint8*)&id).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&stream_name,offset,4);\r\n\t\t\t\tstream_name=Script::Read4Bytes((uint8*)&stream_name).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&drop_off,offset,4);\r\n\t\t\t\tdrop_off=Script::Read4Bytes((uint8*)&drop_off).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&volume,offset,4);\r\n\t\t\t\tvolume=Script::Read4Bytes((uint8*)&volume).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&pitch,offset,4);\r\n\t\t\t\tpitch=Script::Read4Bytes((uint8*)&pitch).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&priority,offset,4);\r\n\t\t\t\tpriority=Script::Read4Bytes((uint8*)&priority).mInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&use_pos_info,offset,4);\r\n\t\t\t\tuse_pos_info=Script::Read4Bytes((uint8*)&use_pos_info).mInt;\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\tp_dummy=p_dummy_table->GetItem(id);\r\n\t\t\t\tif (p_dummy)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf (\"STUBBED replay.cpp %d\\n\",__LINE__);\r\n//\t\t\t\t\tPcm::PlayStreamFromObject(p_dummy,stream_name,drop_off,volume,pitch,channel,use_pos_info);\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase PLAY_POSITIONAL_SOUND_EFFECT:\t\t\t\t\r\n\t\t\t{\r\n\t\t\t\t// Must not play sounds if recording\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\toffset+=1+4*5;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint32 id, sound_name;\r\n\t\t\t\tfloat volume, pitch, drop_off_dist;\r\n\t\t\t\tReadFromBuffer((uint8*)&id,offset,4);\r\n\t\t\t\tid=Script::Read4Bytes((uint8*)&id).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&sound_name,offset,4);\r\n\t\t\t\tsound_name=Script::Read4Bytes((uint8*)&sound_name).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&volume,offset,4);\r\n\t\t\t\tvolume=Script::Read4Bytes((uint8*)&volume).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&pitch,offset,4);\r\n\t\t\t\tpitch=Script::Read4Bytes((uint8*)&pitch).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&drop_off_dist,offset,4);\r\n\t\t\t\tdrop_off_dist=Script::Read4Bytes((uint8*)&drop_off_dist).mFloat;\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\tp_dummy=p_dummy_table->GetItem(id);\r\n\t\t\t\tif (p_dummy)\r\n\t\t\t\t{\r\n\t\t\t\t\tSfx::CSfxManager * p_sfx_manager = Sfx::CSfxManager::Instance();\r\n\t\t\t\t\tSfx::SoundUpdateInfo soundUpdateInfo;\r\n\t\t\t\t\tsoundUpdateInfo.volume = volume;\r\n\t\t\t\t\tsoundUpdateInfo.pitch = pitch;\r\n\t\t\t\t\tsoundUpdateInfo.dropoffDist = drop_off_dist;\r\n\r\n\t\t\t\t\t// These next two parameters need to be added to the replay code\r\n\t\t\t\t\tsoundUpdateInfo.dropoffFunction = DROPOFF_FUNC_STANDARD;\r\n\t\t\t\t\tbool noPosUpdate = false;\r\n\t\t\t\t\tp_sfx_manager->PlaySoundWithPos( sound_name, &soundUpdateInfo, GetSoundComponentFromObject( p_dummy ), noPosUpdate );\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tcase PLAY_SKATER_SOUND_EFFECT:\t\t\t\t\r\n\t\t\t{\r\n\t\t\t\t// Must not play sounds if recording\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\toffset+=1+4*6;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t++offset;\r\n\t\t\t\t\r\n\t\t\t\tint which_array, surface_flag;\r\n\t\t\t\tMth::Vector pos;\r\n\t\t\t\tfloat vol_percent;\r\n\t\t\t\t\r\n\t\t\t\tReadFromBuffer((uint8*)&which_array,offset,4);\r\n\t\t\t\twhich_array=Script::Read4Bytes((uint8*)&which_array).mInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&surface_flag,offset,4);\r\n\t\t\t\tsurface_flag=Script::Read4Bytes((uint8*)&surface_flag).mInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&pos[X],offset,4);\r\n\t\t\t\tpos[X]=Script::Read4Bytes((uint8*)&pos[X]).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&pos[Y],offset,4);\r\n\t\t\t\tpos[Y]=Script::Read4Bytes((uint8*)&pos[Y]).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&pos[Z],offset,4);\r\n\t\t\t\tpos[Z]=Script::Read4Bytes((uint8*)&pos[Z]).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&vol_percent,offset,4);\r\n\t\t\t\tvol_percent=Script::Read4Bytes((uint8*)&vol_percent).mFloat;\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\t// NOTE: need to record sound pitch and choice for use here\r\n\t\t\t\tEnv::CTerrainManager::sPlaySound((Env::ETerrainActionType) which_array, (ETerrainType) surface_flag,pos,vol_percent,100.0f,0.0f,false);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tcase PLAY_SOUND:\r\n\t\t\t{\r\n\t\t\t\t// Must not play sounds if recording\r\n\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t{\r\n\t\t\t\t\toffset+=1+4*4;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t++offset;\r\n\t\t\t\t\r\n\t\t\t\tuint32 checksum;\r\n\t\t\t\tReadFromBuffer((uint8*)&checksum,offset,4);\r\n\t\t\t\tchecksum=Script::Read4Bytes((uint8*)&checksum).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tfloat vol_l,vol_r;\r\n\t\t\t\tReadFromBuffer((uint8*)&vol_l,offset,4);\r\n\t\t\t\tvol_l=Script::Read4Bytes((uint8*)&vol_l).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer((uint8*)&vol_r,offset,4);\r\n\t\t\t\tvol_r=Script::Read4Bytes((uint8*)&vol_r).mFloat;\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\tfloat pitch;\r\n\t\t\t\tReadFromBuffer((uint8*)&pitch,offset,4);\r\n\t\t\t\tpitch=Script::Read4Bytes((uint8*)&pitch).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tSfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\r\n\t\t\t\t// Dave note 10/17/02, the replay code should store all 5 channels where appropriate.\r\n\t\t\t\tSfx::sVolume vol;\r\n\t\t\t\tvol.SetSilent();\r\n\t\t\t\tvol.SetChannelVolume( 0, vol_l );\r\n\t\t\t\tvol.SetChannelVolume( 1, vol_r );\r\n//\t\t\t\tsfx_manager->PlaySound(checksum,vol_l,vol_r,pitch);\r\n\t\t\t\tsfx_manager->PlaySound(checksum,&vol,pitch);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase PLAY_LOOPING_SOUND:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\t\r\n\t\t\t\tuint32 checksum;\r\n\t\t\t\tReadFromBuffer((uint8*)&checksum,offset,4);\r\n\t\t\t\tchecksum=Script::Read4Bytes((uint8*)&checksum).mUInt;\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\tp_dummy->m_looping_sound_checksum=checksum;\r\n\t\t\t\t\t\r\n\t\t\t\tif (whichList==PLAYBACK_DUMMY_LIST)\r\n\t\t\t\t{\r\n\t\t\t\t\tSfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\t\t\t\t\t\r\n\t\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\t\tif (p_dummy->m_looping_sound_id)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsfx_manager->StopSound( p_dummy->m_looping_sound_id );\r\n\t\t\t\t\t}\t\r\n\t\t\t\t\tp_dummy->m_looping_sound_id = sfx_manager->PlaySound( checksum, 0, 0 );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// This bit will execute if the list is the start-state dummy list.\r\n\t\t\t\t\t// m_looping_sound_id isn't used in that case, but may as well set it to zero.\r\n\t\t\t\t\tp_dummy->m_looping_sound_id=0;\r\n\t\t\t\t}\t\r\n\t\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tcase STOP_LOOPING_SOUND:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\t\r\n\t\t\t\tif (whichList==PLAYBACK_DUMMY_LIST)\r\n\t\t\t\t{\r\n\t\t\t\t\tSfx::CSfxManager * sfx_manager =  Sfx::CSfxManager::Instance();\r\n\t\t\t\t\t\r\n\t\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\t\tif (p_dummy->m_looping_sound_id)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsfx_manager->StopSound( p_dummy->m_looping_sound_id );\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\tp_dummy->m_looping_sound_id=0;\r\n\t\t\t\tp_dummy->m_looping_sound_checksum=0;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tcase PITCH_MIN:\r\n\t\t\tcase PITCH_MAX:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\t\r\n\t\t\t\tfloat pitch;\r\n\t\t\t\tReadFromBuffer((uint8*)&pitch,offset,4);\r\n\t\t\t\tpitch=Script::Read4Bytes((uint8*)&pitch).mFloat;\r\n\t\t\t\toffset+=4;\r\n\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tif (token==PITCH_MIN)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_dummy->m_pitch_min=pitch;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tp_dummy->m_pitch_max=pitch;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tcase OBJECT_ID:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint32 id;\r\n\t\t\t\tReadFromBuffer((uint8*)&id,offset,4);\r\n\t\t\t\tid=Script::Read4Bytes((uint8*)&id).mUInt;\r\n\t\t\t\t\r\n\t\t\t\tp_dummy=p_dummy_table->GetItem(id);\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?  id=%d\",id));\r\n\t\t\t\t\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tcase CREATE_OBJECT:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint32 id;\r\n\t\t\t\tuint8 type;\r\n\t\t\t\tReadFromBuffer((uint8*)&id,offset,4);\r\n\t\t\t\tid=Script::Read4Bytes((uint8*)&id).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tReadFromBuffer(&type,offset,1);\r\n\t\t\t\t++offset;\r\n\t\t\t\t\r\n\t\t\t\tp_dummy=p_dummy_table->GetItem(id);\r\n\t\t\t\tif (!p_dummy)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_dummy=new CDummy(whichList,id);\r\n\t\t\t\t\tp_dummy->SetType(type);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"Got CREATE_OBJECT when dummy already exists ?\"));\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tcase KILL_OBJECT:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint32 id;\r\n\t\t\t\tReadFromBuffer((uint8*)&id,offset,4);\r\n\t\t\t\tid=Script::Read4Bytes((uint8*)&id).mUInt;\r\n\t\t\t\t\r\n\t\t\t\tp_dummy=p_dummy_table->GetItem(id);\r\n\t\t\t\tif (p_dummy)\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete p_dummy;\r\n\t\t\t\t\tp_dummy=NULL;\r\n\t\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n#if 0\r\n\t\t\tcase MODEL_NAME:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint8 len;\r\n\t\t\t\tReadFromBuffer(&len,offset,1);\r\n\t\t\t\t++offset;\r\n\t\t\t\t\r\n\t\t\t\tDbg_MsgAssert(len<=MAX_MODEL_NAME_CHARS,(\"Too many chars in model name\"));\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)p_dummy->mpModelName,offset,len);\r\n\t\t\t\t// The string has no terminating 0 in the big buffer, so wack one on.\r\n\t\t\t\tp_dummy->mpModelName[len]=0;\r\n\t\t\t\toffset+=len;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n#endif\r\n\t\t\tcase SKELETON_NAME:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->mSkeletonName,offset,4);\r\n\t\t\t\tp_dummy->mSkeletonName=Script::Read4Bytes((uint8*)&p_dummy->mSkeletonName).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase PROFILE_NAME:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->mProfileName,offset,4);\r\n\t\t\t\tp_dummy->mProfileName=Script::Read4Bytes((uint8*)&p_dummy->mProfileName).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase SECTOR_NAME:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->mSectorName,offset,4);\r\n\t\t\t\tp_dummy->mSectorName=Script::Read4Bytes((uint8*)&p_dummy->mSectorName).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase ANIM_SCRIPT_NAME:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->mAnimScriptName,offset,4);\r\n\t\t\t\tp_dummy->mAnimScriptName=Script::Read4Bytes((uint8*)&p_dummy->mAnimScriptName).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase SET_SCALE:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->mScale,offset,4);\r\n\t\t\t\tp_dummy->mScale=Script::Read4Bytes((uint8*)&p_dummy->mScale).mFloat;\r\n\t\t\t\tif (p_dummy->mp_rendered_model)\r\n\t\t\t\t{\r\n\t\t\t\t\tMth::Vector s(p_dummy->mScale,p_dummy->mScale,p_dummy->mScale);\r\n\t\t\t\t\tp_dummy->mp_rendered_model->SetScale(s);\r\n\t\t\t\t}\t\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SET_CAR_ROTATION_X:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_car_rotation_x,offset,4);\r\n\t\t\t\tp_dummy->m_car_rotation_x=Script::Read4Bytes((uint8*)&p_dummy->m_car_rotation_x).mFloat;\r\n\t\t\t\tp_dummy->m_car_rotation_x_vel=0.0f;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SET_WHEEL_ROTATION_X:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_wheel_rotation_x,offset,4);\r\n\t\t\t\tp_dummy->m_wheel_rotation_x=Script::Read4Bytes((uint8*)&p_dummy->m_wheel_rotation_x).mFloat;\r\n\t\t\t\tp_dummy->m_wheel_rotation_x_vel=0.0f;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SET_WHEEL_ROTATION_Y:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_wheel_rotation_y,offset,4);\r\n\t\t\t\tp_dummy->m_wheel_rotation_y=Script::Read4Bytes((uint8*)&p_dummy->m_wheel_rotation_y).mFloat;\r\n\t\t\t\tp_dummy->m_wheel_rotation_y_vel=0.0f;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SET_CAR_ROTATION_X_VEL:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_car_rotation_x_vel,offset,4);\r\n\t\t\t\tp_dummy->m_car_rotation_x_vel=Script::Read4Bytes((uint8*)&p_dummy->m_car_rotation_x_vel).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SET_WHEEL_ROTATION_X_VEL:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_wheel_rotation_x_vel,offset,4);\r\n\t\t\t\tp_dummy->m_wheel_rotation_x_vel=Script::Read4Bytes((uint8*)&p_dummy->m_wheel_rotation_x_vel).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SET_WHEEL_ROTATION_Y_VEL:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_wheel_rotation_y_vel,offset,4);\r\n\t\t\t\tp_dummy->m_wheel_rotation_y_vel=Script::Read4Bytes((uint8*)&p_dummy->m_wheel_rotation_y_vel).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tcase SET_ANGLE_X:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_angles[X],offset,4);\r\n\t\t\t\tp_dummy->m_angles[X]=Script::Read4Bytes((uint8*)&p_dummy->m_angles[X]).mFloat;\r\n\t\t\t\tp_dummy->m_ang_vel[X]=0.0f;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SET_ANGLE_Y:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_angles[Y],offset,4);\r\n\t\t\t\tp_dummy->m_angles[Y]=Script::Read4Bytes((uint8*)&p_dummy->m_angles[Y]).mFloat;\r\n\t\t\t\tp_dummy->m_ang_vel[Y]=0.0f;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SET_ANGLE_Z:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_angles[Z],offset,4);\r\n\t\t\t\tp_dummy->m_angles[Z]=Script::Read4Bytes((uint8*)&p_dummy->m_angles[Z]).mFloat;\r\n\t\t\t\tp_dummy->m_ang_vel[Z]=0.0f;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SET_ANGULAR_VELOCITY_X:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_ang_vel[X],offset,4);\r\n\t\t\t\tp_dummy->m_ang_vel[X]=Script::Read4Bytes((uint8*)&p_dummy->m_ang_vel[X]).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SET_ANGULAR_VELOCITY_Y:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_ang_vel[Y],offset,4);\r\n\t\t\t\tp_dummy->m_ang_vel[Y]=Script::Read4Bytes((uint8*)&p_dummy->m_ang_vel[Y]).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SET_ANGULAR_VELOCITY_Z:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_ang_vel[Z],offset,4);\r\n\t\t\t\tp_dummy->m_ang_vel[Z]=Script::Read4Bytes((uint8*)&p_dummy->m_ang_vel[Z]).mFloat;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t\t\r\n\t\t\tcase SET_POSITION:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_pos[X],offset,4*3);\r\n\t\t\t\tp_dummy->m_pos[X]=Script::Read4Bytes((uint8*)&p_dummy->m_pos[X]).mFloat;\r\n\t\t\t\tp_dummy->m_pos[Y]=Script::Read4Bytes((uint8*)&p_dummy->m_pos[Y]).mFloat;\r\n\t\t\t\tp_dummy->m_pos[Z]=Script::Read4Bytes((uint8*)&p_dummy->m_pos[Z]).mFloat;\r\n\t\t\t\tp_dummy->m_vel.Set();\r\n\t\t\t\t\r\n\t\t\t\toffset+=4*3;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tcase SET_POSITION_ANGLES:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\t\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_pos[X],offset,4*3);\r\n\t\t\t\tp_dummy->m_pos[X]=Script::Read4Bytes((uint8*)&p_dummy->m_pos[X]).mFloat;\r\n\t\t\t\tp_dummy->m_pos[Y]=Script::Read4Bytes((uint8*)&p_dummy->m_pos[Y]).mFloat;\r\n\t\t\t\tp_dummy->m_pos[Z]=Script::Read4Bytes((uint8*)&p_dummy->m_pos[Z]).mFloat;\r\n\t\t\t\toffset+=4*3;\r\n\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_angles[X],offset,4*3);\r\n\t\t\t\tp_dummy->m_angles[X]=Script::Read4Bytes((uint8*)&p_dummy->m_angles[X]).mFloat;\r\n\t\t\t\tp_dummy->m_angles[Y]=Script::Read4Bytes((uint8*)&p_dummy->m_angles[Y]).mFloat;\r\n\t\t\t\tp_dummy->m_angles[Z]=Script::Read4Bytes((uint8*)&p_dummy->m_angles[Z]).mFloat;\r\n\t\t\t\toffset+=4*3;\r\n\t\t\t\t\r\n\t\t\t\tp_dummy->m_vel.Set();\r\n\t\t\t\tp_dummy->m_ang_vel.Set();\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tcase SET_VELOCITY:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_vel[X],offset,4*3);\r\n\t\t\t\tp_dummy->m_vel[X]=Script::Read4Bytes((uint8*)&p_dummy->m_vel[X]).mFloat;\r\n\t\t\t\tp_dummy->m_vel[Y]=Script::Read4Bytes((uint8*)&p_dummy->m_vel[Y]).mFloat;\r\n\t\t\t\tp_dummy->m_vel[Z]=Script::Read4Bytes((uint8*)&p_dummy->m_vel[Z]).mFloat;\r\n\t\t\t\toffset+=4*3;\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase PRIMARY_ANIM_CONTROLLER_CHANGES:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\toffset=sReadAnimControllerChanges(offset,&p_dummy->m_primaryController);\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase DEGENERATE_ANIM_CONTROLLER_CHANGES:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint8 index=0;\r\n\t\t\t\tReadFromBuffer(&index,offset,1);\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tDbg_MsgAssert(p_dummy->GetID()==ID_SKATER,(\"Got degenerate anim changes for a non-skater ?\"));\r\n\t\t\t\toffset=sReadAnimControllerChanges(offset,&p_dummy->m_degenerateControllers[index]);\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase HOVERING:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tDbg_MsgAssert(p_dummy,(\"NULL p_dummy ?\"));\r\n\t\t\t\tp_dummy->mFlags|=DUMMY_FLAG_HOVERING;\r\n\t\t\t\t\r\n\t\t\t\tReadFromBuffer((uint8*)&p_dummy->m_pos[X],offset,4*3);\r\n\t\t\t\tp_dummy->m_pos[X]=Script::Read4Bytes((uint8*)&p_dummy->m_pos[X]).mFloat;\r\n\t\t\t\tp_dummy->m_pos[Y]=Script::Read4Bytes((uint8*)&p_dummy->m_pos[Y]).mFloat;\r\n\t\t\t\tp_dummy->m_pos[Z]=Script::Read4Bytes((uint8*)&p_dummy->m_pos[Z]).mFloat;\r\n\t\t\t\toffset+=4*3;\r\n\t\t\t\t\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tcase SECTOR_ACTIVE:\r\n\t\t\tcase SECTOR_INACTIVE:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint32 sector_name;\r\n\t\t\t\tReadFromBuffer((uint8*)&sector_name,offset,4);\r\n\t\t\t\tsector_name=Script::Read4Bytes((uint8*)&sector_name).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(sector_name);\r\n\t\t\t\tif (p_sector)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// If recording, apply to the start state.\r\n\t\t\t\t\t\tp_sector->SetActiveAtReplayStart(token==SECTOR_ACTIVE);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Otherwise apply to the current world.\r\n\t\t\t\t\t\tp_sector->SetActive(token==SECTOR_ACTIVE);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\r\n\t\t\tcase SECTOR_VISIBLE:\r\n\t\t\tcase SECTOR_INVISIBLE:\r\n\t\t\t{\r\n\t\t\t\t++offset;\r\n\t\t\t\tuint32 sector_name;\r\n\t\t\t\tReadFromBuffer((uint8*)&sector_name,offset,4);\r\n\t\t\t\tsector_name=Script::Read4Bytes((uint8*)&sector_name).mUInt;\r\n\t\t\t\toffset+=4;\r\n\t\t\t\t\r\n\t\t\t\tNx::CSector *p_sector = Nx::CEngine::sGetSector(sector_name);\r\n\t\t\t\tif (p_sector)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (sMode==RECORD)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// If recording, apply to the start state.\r\n\t\t\t\t\t\tp_sector->SetVisibleAtReplayStart(token==SECTOR_VISIBLE);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Otherwise apply to the current world.\r\n\t\t\t\t\t\tp_sector->SetVisibility(token==SECTOR_VISIBLE ?0xff:0x00);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(0,(\"Unsupported token type of %d in sReadFrame\",token));\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\t\r\n\r\n\t// Update all the dummy objects\r\n\tp_dummy=sGetDummyListHeadPointer(whichList);\r\n\twhile (p_dummy)\r\n\t{\r\n\t\tif (whichList==PLAYBACK_DUMMY_LIST && !p_dummy->mp_rendered_model && p_dummy->m_is_displayed)\r\n\t\t{\r\n\t\t\tp_dummy->CreateModel();\r\n\t\t}\r\n\t\t\r\n\t\tp_dummy->Update();\t\t\r\n\t\tp_dummy=p_dummy->mpNext;\r\n\t}\t\r\n\r\n\r\n\r\n\t#ifdef CHECK_TOKEN_USAGE\r\n\tsTokenCount[OBJECT_ID]=0;\r\n\tint biggest=0;\r\n\tint worst_token=-1;\r\n\tfor (int i=0; i<NUM_REPLAY_TOKEN_TYPES; ++i)\r\n\t{\r\n\t\tif (sTokenCount[i]>biggest)\r\n\t\t{\r\n\t\t\tbiggest=sTokenCount[i];\r\n\t\t\tworst_token=i;\r\n\t\t}\t\r\n\t}\t\r\n\tprintf(\"Worst token = %s\\n\",sGetTokenName((EReplayToken)worst_token));\r\n\t#endif\r\n\r\n\r\n\r\n\r\n\treturn offset;\r\n}\r\n\r\n// After calling this, sBigBufferEndOffset will be guaranteed to point to enough contiguous space\r\n// to hold frameSize bytes.\r\nstatic void sMakeEnoughSpace(uint32 frameSize)\r\n{\r\n\t// This loop makes one modification to the buffer each time around, and breaks out once\r\n\t// enough space has been freed.\r\n\twhile (true)\r\n\t{\r\n\t\tif (sBigBufferStartOffset < sBigBufferEndOffset)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(sBigBufferStartOffset==0,(\"sBigBufferStartOffset not zero ?\"));\r\n\t\t\t\r\n\t\t\t// We know that all the space from sBigBufferEndOffset to the end of the buffer\r\n\t\t\t// is free to use, so check if that space is big enough.\r\n\t\t\tif (GetBufferSize()-sBigBufferEndOffset >= frameSize)\r\n\t\t\t{\r\n\t\t\t\t// It is!\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Wrap the end offset around to the start of the buffer, so that next time\r\n\t\t\t\t// around this loop frames at the start will start getting chomped up to make space.\r\n\t\t\t\tsBigBufferEndOffset=0;\r\n\t\t\t\t\r\n\t\t\t\tsBufferFilling=false;\r\n\t\t\t}\t\r\n\t\t}\r\n\t\telse if (sBigBufferStartOffset > sBigBufferEndOffset)\r\n\t\t{\r\n\t\t\t// The space between end and start is free to use, so check if it is big enough. \r\n\t\t\tif (sBigBufferStartOffset-sBigBufferEndOffset >= frameSize)\r\n\t\t\t{\r\n\t\t\t\t// It is!\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Skip the start offset over the frame it is pointing to.\r\n\t\t\t\tbool nothing_follows=false;\r\n\t\t\t\tuint32 old_start=sBigBufferStartOffset;\r\n\t\t\t\tsBigBufferStartOffset=sReadFrame(sBigBufferStartOffset,&nothing_follows,START_STATE_DUMMY_LIST);\r\n\t\t\t\tif (sBigBufferStartOffset==old_start)\r\n\t\t\t\t{\r\n\t\t\t\t\t// The start offset did not move, meaning it is pointing to empty space.\r\n\t\t\t\t\t// The only time this should happen is when the buffer is empty, in which\r\n\t\t\t\t\t// case the start and end offset should both be zero. So assert.\r\n\t\t\t\t\tDbg_MsgAssert(0,(\"Start offset points to empty space, even though it is greater than end offset ?\"));\r\n\t\t\t\t\t\r\n\t\t\t\t\t// Just in case this does ever happen on a release build, reset the buffer so that\r\n\t\t\t\t\t// it does not hang. All that will happen is that the replay will be lost.\r\n\t\t\t\t\tsDeleteDummies(START_STATE_DUMMY_LIST);\r\n\t\t\t\t\tsDeleteDummies(PLAYBACK_DUMMY_LIST);\r\n\t\t\t\t\tDbg_MsgAssert(spReplayDummies==NULL,(\"Hey! spReplayDummies not NULL !!!\"));\r\n\t\t\t\t\tsDeleteObjectTrackingInfo();\r\n\t\t\t\t\tClearBuffer();\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Fill the frame just skipped over with BLANK's\r\n\t\t\t\t\tFillBuffer(old_start,sBigBufferStartOffset-old_start,BLANK);\r\n\t\t\t\t\t// Wrap around if necessary.\r\n\t\t\t\t\tif (nothing_follows)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsBigBufferStartOffset=0;\r\n\t\t\t\t\t}\t\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// sBigBufferStartOffset equals sBigBufferEndOffset\r\n\t\t\tbool nothing_follows=false;\r\n\t\t\tuint32 old_start=sBigBufferStartOffset;\r\n\t\t\tsBigBufferStartOffset=sReadFrame(sBigBufferStartOffset,&nothing_follows,START_STATE_DUMMY_LIST);\r\n\t\t\tif (sBigBufferStartOffset==old_start)\r\n\t\t\t{\r\n\t\t\t\t// If the start offset did not move, it must be pointing to empty space.\r\n\t\t\t\t// The only time the start offset should point to empty space is when the \r\n\t\t\t\t// buffer is totally empty, in which case the start offset would be expected to be zero.\r\n\t\t\t\t// So check that.\r\n\t\t\t\tDbg_MsgAssert(sBigBufferStartOffset==0,(\"Expected sBigBufferStartOffset to be zero\"));\r\n\t\t\t\t// Check that the frame size is not bigger than the entire buffer.\r\n\t\t\t\tDbg_MsgAssert(GetBufferSize() >= frameSize,(\"Frame size %d too big for replay buffer\",frameSize));\r\n\t\t\t\t// There is enough space, so break out.\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// Fill the frame just skipped over with BLANK's\r\n\t\t\t\tFillBuffer(old_start,sBigBufferStartOffset-old_start,BLANK);\r\n\t\t\t\t// Wrap around if necessary.\r\n\t\t\t\tif (nothing_follows)\r\n\t\t\t\t{\r\n\t\t\t\t\tsBigBufferStartOffset=0;\r\n\t\t\t\t}\t\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\nstatic void sWriteFrameBufferToBigBuffer()\r\n{\r\n\tuint32 frame_size=spFrameBufferPos-spFrameBuffer;\r\n\r\n\tsMakeEnoughSpace(frame_size);\r\n\r\n\t// sBigBufferEndOffset is now guaranteed to point to enough contiguous space to\r\n\t// hold frame_size bytes, so write in the frame data.\r\n\tWriteIntoBuffer(spFrameBuffer,sBigBufferEndOffset,frame_size);\r\n\tsBigBufferEndOffset+=frame_size;\r\n\t// Wrap around if necessary.\r\n\tif (sBigBufferEndOffset==GetBufferSize())\r\n\t{\r\n\t\tsBigBufferEndOffset=0;\r\n\t}\t\r\n}\r\n\r\nstatic void sWriteSingleToken(EReplayToken token)\r\n{\r\n\tDbg_MsgAssert(!Mdl::Skate::Instance()->IsMultiplayerGame(),(\"Replay Active in Multiplayer game!\"));\r\n\tDbg_MsgAssert(spFrameBufferPos+1 <= spFrameBuffer+FRAME_BUFFER_SIZE,(\"Replay frame buffer overflow\"));\r\n\t\r\n\t*spFrameBufferPos++=token;\r\n}\r\n\r\n/*\r\nstatic void sWriteUint8(EReplayToken token, uint8 v)\r\n{\r\n\tDbg_MsgAssert(spFrameBufferPos+2 <= spFrameBuffer+FRAME_BUFFER_SIZE,(\"Replay frame buffer overflow\"));\r\n\t\r\n\t*spFrameBufferPos++=token;\r\n\t*spFrameBufferPos++=v;\r\n}\r\n*/\r\n\r\nstatic void sWriteUint8(uint8 v)\r\n{\r\n\tDbg_MsgAssert(spFrameBufferPos+1 <= spFrameBuffer+FRAME_BUFFER_SIZE,(\"Replay frame buffer overflow\"));\r\n\t*spFrameBufferPos++=v;\r\n}\r\n\r\nstatic void sWriteUint32(EReplayToken token, uint32 v)\r\n{\r\n\tDbg_MsgAssert(spFrameBufferPos+5 <= spFrameBuffer+FRAME_BUFFER_SIZE,(\"Replay frame buffer overflow\"));\r\n\t\r\n\t*spFrameBufferPos++=token;\r\n\tspFrameBufferPos=Script::Write4Bytes(spFrameBufferPos, v);\r\n}\r\n\r\nstatic void sWriteUint32(uint32 v)\r\n{\r\n\tDbg_MsgAssert(spFrameBufferPos+4 <= spFrameBuffer+FRAME_BUFFER_SIZE,(\"Replay frame buffer overflow\"));\r\n\t\r\n\tspFrameBufferPos=Script::Write4Bytes(spFrameBufferPos, v);\r\n}\r\n\r\nstatic void sWriteFloat(EReplayToken token, float f)\r\n{\r\n\tDbg_MsgAssert(spFrameBufferPos+5 <= spFrameBuffer+FRAME_BUFFER_SIZE,(\"Replay frame buffer overflow\"));\r\n\t\r\n\t*spFrameBufferPos++=token;\r\n\tspFrameBufferPos=Script::Write4Bytes(spFrameBufferPos, f);\r\n}\r\n\r\nstatic void sWriteFloat(float f)\r\n{\r\n\tDbg_MsgAssert(spFrameBufferPos+4 <= spFrameBuffer+FRAME_BUFFER_SIZE,(\"Replay frame buffer overflow\"));\r\n\t\r\n\tspFrameBufferPos=Script::Write4Bytes(spFrameBufferPos, f);\r\n}\r\n\r\n/*\r\nstatic void sWrite2Floats(EReplayToken token, float a, float b)\r\n{\r\n\tDbg_MsgAssert(spFrameBufferPos+9 <= spFrameBuffer+FRAME_BUFFER_SIZE,(\"Replay frame buffer overflow\"));\r\n\t\r\n\t*spFrameBufferPos++=token;\r\n\tspFrameBufferPos=Script::Write4Bytes(spFrameBufferPos, a);\r\n\tspFrameBufferPos=Script::Write4Bytes(spFrameBufferPos, b);\r\n}\r\n*/\r\n\r\nstatic void sWriteVector(EReplayToken token, Mth::Vector &v)\r\n{\r\n\tDbg_MsgAssert(spFrameBufferPos+13 <= spFrameBuffer+FRAME_BUFFER_SIZE,(\"Replay frame buffer overflow\"));\r\n\t\r\n\t*spFrameBufferPos++=token;\r\n\tspFrameBufferPos=Script::Write4Bytes(spFrameBufferPos, v[X]);\r\n\tspFrameBufferPos=Script::Write4Bytes(spFrameBufferPos, v[Y]);\r\n\tspFrameBufferPos=Script::Write4Bytes(spFrameBufferPos, v[Z]);\r\n}\r\n\r\n#if 0\r\nstatic void sWriteString(EReplayToken token, const char *p_string)\r\n{\r\n\tDbg_MsgAssert(p_string,(\"NULL p_string\"));\r\n\tint len=strlen(p_string);\r\n\tDbg_MsgAssert(len<256,(\"String length too big, '%s'\",p_string));\r\n\tDbg_MsgAssert(spFrameBufferPos+2+len <= spFrameBuffer+FRAME_BUFFER_SIZE,(\"Replay frame buffer overflow\"));\r\n\t\r\n\t*spFrameBufferPos++=token;\r\n\t*spFrameBufferPos++=len;\r\n\tfor (int i=0; i<len; ++i)\r\n\t{\r\n\t\t*spFrameBufferPos++=*p_string++;\r\n\t}\t\r\n\t// Note that the string is not terminated with a zero. Instead it is preceded with a byte\r\n\t// containing its length.\r\n\t// This is so that the string can be read out of the buffer in one go using ReadFromBuffer, rather\r\n\t// than one byte at a time.\r\n\t// I'm not sure how slow ReadFromBuffer is going to be on the GameCube since it will be in aram.\r\n}\r\n\r\nstatic void sWriteString(const char *p_string)\r\n{\r\n\tDbg_MsgAssert(p_string,(\"NULL p_string\"));\r\n\tint len=strlen(p_string);\r\n\tDbg_MsgAssert(len<256,(\"String length too big, '%s'\",p_string));\r\n\tDbg_MsgAssert(spFrameBufferPos+1+len <= spFrameBuffer+FRAME_BUFFER_SIZE,(\"Replay frame buffer overflow\"));\r\n\t\r\n\t*spFrameBufferPos++=len;\r\n\tfor (int i=0; i<len; ++i)\r\n\t{\r\n\t\t*spFrameBufferPos++=*p_string++;\r\n\t}\t\r\n\t// Note that the string is not terminated with a zero. Instead it is preceded with a byte\r\n\t// containing its length.\r\n\t// This is so that the string can be read out of the buffer in one go using ReadFromBuffer, rather\r\n\t// than one byte at a time.\r\n\t// I'm not sure how slow ReadFromBuffer is going to be on the GameCube since it will be in aram.\r\n}\r\n#endif\r\n\r\n#if 0\r\nstatic uint8 sWriteCAnimChannelChanges(const Gfx::CAnimChannel *p_a, const Gfx::CAnimChannel *p_b)\r\n{\r\n\tuint8 num_changes_written=0;\r\n\t\r\n\tDbg_MsgAssert((sizeof(Gfx::CAnimChannel)&3)==0,(\"sizeof(Gfx::CAnimChannel) not a multiple of 4 ??\"));\r\n\tDbg_MsgAssert(sizeof(Gfx::CAnimChannel)/4 < 256,(\"sizeof(Gfx::CAnimChannel) too big !\"));\r\n\t\r\n\tuint32 *p_words_a=(uint32*)p_a;\r\n\tuint32 *p_words_b=(uint32*)p_b;\r\n\tfor (uint8 i=0; i<sizeof(Gfx::CAnimChannel)/4; ++i)\r\n\t{\r\n\t\tif (1)//i!=Gfx::CAnimChannel::sGetCurrentTimeOffset())\r\n\t\t{\r\n\t\t\tif (*p_words_a != *p_words_b)\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert(spFrameBufferPos+5 <= spFrameBuffer+FRAME_BUFFER_SIZE,(\"Replay frame buffer overflow\"));\r\n\t\t\t\t*spFrameBufferPos++=i;\r\n\t\t\t\tspFrameBufferPos=Script::Write4Bytes(spFrameBufferPos, *p_words_b);\r\n\t\t\t\t++num_changes_written;\r\n\t\t\t}\r\n\t\t}\t\r\n\t\t++p_words_a;\r\n\t\t++p_words_b;\r\n\t}\r\n\r\n\treturn num_changes_written;\r\n}\r\n#endif\r\n\r\nvoid WritePadVibration(int actuator, int percent)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tif (Config::GetHardware()==Config::HARDWARE_NGC)\r\n\t{\r\n\t\t// NGC must not replay vibrations, TRC requirement.\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\tsWriteSingleToken(PAD_VIBRATION);\r\n\tsWriteUint8(actuator);\r\n\tsWriteUint32(percent);\r\n}\r\n\r\nvoid WritePauseSkater()\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(PAUSE_SKATER);\r\n}\r\n\r\nvoid WriteUnPauseSkater()\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(UNPAUSE_SKATER);\r\n}\r\n\r\nvoid WriteScreenFlash(int viewport, Image::RGBA from, Image::RGBA to, float duration, float z, uint32 flags)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tsWriteSingleToken(SCREEN_FLASH);\r\n\tsWriteUint32(viewport);\r\n\tDbg_MsgAssert(sizeof(Image::RGBA)==4,(\"sizeof(Image::RGBA) not 4 ??\"));\r\n\tsWriteUint32(*(uint32*)&from);\r\n\tsWriteUint32(*(uint32*)&to);\r\n\tsWriteFloat(duration);\r\n\tsWriteFloat(z);\r\n\tsWriteUint32(flags);\r\n}\r\n\r\nvoid WriteShatterParams(\tMth::Vector& velocity, float area_test, float velocity_variance, \r\n\t\t\t\t\t\t\tfloat spread_factor, float lifetime, float bounce, float bounce_amplitude)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(SHATTER_PARAMS);\r\n\tsWriteFloat(velocity[X]);\r\n\tsWriteFloat(velocity[Y]);\r\n\tsWriteFloat(velocity[Z]);\r\n\tsWriteFloat(area_test);\r\n\tsWriteFloat(velocity_variance);\r\n\tsWriteFloat(spread_factor);\r\n\tsWriteFloat(lifetime);\r\n\tsWriteFloat(bounce);\r\n\tsWriteFloat(bounce_amplitude);\r\n}\r\n\r\nvoid Replay::WriteTextureSplat(Mth::Vector& splat_start, Mth::Vector& splat_end, float size, float lifetime, const char *p_texture_name, uint32 trail )\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(TEXTURE_SPLAT);\r\n\tsWriteFloat(splat_start[X]);\r\n\tsWriteFloat(splat_start[Y]);\r\n\tsWriteFloat(splat_start[Z]);\r\n\tsWriteFloat(splat_end[X]);\r\n\tsWriteFloat(splat_end[Y]);\r\n\tsWriteFloat(splat_end[Z]);\r\n\tsWriteFloat(size);\r\n\tsWriteFloat(lifetime);\r\n//\tsWriteString(p_texture_name);\r\n\tsWriteUint32(trail);\r\n}\r\n\r\nvoid WriteShatter(uint32 sectorName, bool on)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tsWriteSingleToken(on ? SHATTER_ON:SHATTER_OFF);\r\n\tsWriteUint32(sectorName);\r\n}\r\n\r\nvoid WriteSectorActiveStatus(uint32 sectorName, bool active)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tsWriteUint32(active ? SECTOR_ACTIVE:SECTOR_INACTIVE,sectorName);\r\n}\t\r\n\r\nvoid WriteSectorVisibleStatus(uint32 sectorName, bool visible)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tsWriteUint32(visible ? SECTOR_VISIBLE:SECTOR_INVISIBLE,sectorName);\r\n}\t\r\n\t\r\nvoid WriteManualMeter(bool state, float value)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tif (state)\r\n\t{\r\n\t\tsWriteSingleToken(MANUAL_METER_ON);\r\n\t\tsWriteFloat(value);\r\n\t\tsCurrentState.mManualMeterStatus=true;\r\n\t\tsCurrentState.mManualMeterValue=value;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (sCurrentState.mManualMeterStatus)\r\n\t\t{\r\n\t\t\tsWriteSingleToken(MANUAL_METER_OFF);\r\n\t\t\tsCurrentState.mManualMeterStatus=false;\r\n\t\t\tsCurrentState.mManualMeterValue=0.0f;\r\n\t\t}\r\n\t}\t\t\r\n}\r\n\r\nvoid WriteBalanceMeter(bool state, float value)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tif (state)\r\n\t{\r\n\t\tsWriteSingleToken(BALANCE_METER_ON);\r\n\t\tsWriteFloat(value);\r\n\t\tsCurrentState.mBalanceMeterStatus=true;\r\n\t\tsCurrentState.mBalanceMeterValue=value;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (sCurrentState.mBalanceMeterStatus)\r\n\t\t{\r\n\t\t\tsWriteSingleToken(BALANCE_METER_OFF);\r\n\t\t\tsCurrentState.mBalanceMeterStatus=false;\r\n\t\t\tsCurrentState.mBalanceMeterValue=0.0f;\r\n\t\t}\r\n\t}\t\t\r\n}\r\n\r\nvoid WriteSparksOn()\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(SPARKS_ON);\r\n}\t\r\n\r\nvoid WriteSparksOff()\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(SPARKS_OFF);\r\n}\t\r\n\r\nvoid WriteScorePotText(const char *p_text)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tDbg_MsgAssert(p_text,(\"NULL p_text\"));\r\n\tsWriteSingleToken(SCORE_POT_TEXT);\r\n//\tsWriteString(p_text);\r\n}\r\n\r\nstatic uint32 sLastTrickTextChecksum=0;\r\nvoid WriteTrickText(const char **pp_text, int numStrings)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tuint32 ch=0;\r\n\tfor (int i=0; i<numStrings; ++i)\r\n\t{\r\n\t\tch=Crc::UpdateCRC(pp_text[i],strlen(pp_text[i]),ch);\r\n\t}\t\r\n\tif (ch==sLastTrickTextChecksum)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tsLastTrickTextChecksum=ch;\t\r\n\t\r\n\tsWriteSingleToken(TRICK_TEXT);\r\n\tDbg_MsgAssert(numStrings<256,(\"numStrings too big\"));\r\n\tsWriteUint8(numStrings);\r\n\tfor (int string=0; string<numStrings; ++string)\r\n\t{\r\n//\t\tsWriteString(pp_text[string]);\r\n\t}\t\r\n}\r\n\r\nvoid WriteTrickTextPulse()\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(TRICK_TEXT_PULSE);\r\n}\r\n\r\nvoid WriteTrickTextCountdown()\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(TRICK_TEXT_COUNTDOWN);\r\n}\r\n\r\nvoid WriteTrickTextLanded()\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(TRICK_TEXT_LANDED);\r\n}\r\n\r\nvoid WriteTrickTextBail()\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(TRICK_TEXT_BAIL);\r\n}\r\n\r\nvoid WriteSetAtomicStates(uint32 id, uint32 mask)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(SET_ATOMIC_STATES);\r\n\tsWriteUint32(id);\r\n\tsWriteUint32(mask);\r\n}\r\n\r\nvoid WritePlayStream(uint32 checksum, Sfx::sVolume *p_volume, float pitch, int priority)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(PLAY_STREAM);\r\n\tsWriteUint32(checksum);\r\n\r\n\tsWriteUint32(p_volume->GetVolumeType());\r\n\tsWriteFloat(p_volume->GetChannelVolume(0));\r\n\tsWriteFloat(p_volume->GetChannelVolume(1));\r\n\tif( p_volume->GetVolumeType() == Sfx::VOLUME_TYPE_5_CHANNEL_DOLBY5_1 )\r\n\t{\r\n\t\tsWriteFloat(p_volume->GetChannelVolume(2));\r\n\t\tsWriteFloat(p_volume->GetChannelVolume(3));\r\n\t\tsWriteFloat(p_volume->GetChannelVolume(4));\r\n\t}\r\n\r\n\tsWriteFloat(pitch);\r\n\tsWriteUint32(priority);\r\n}\r\n\r\nvoid WriteStopStream(int channel)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tsWriteSingleToken(STOP_STREAM);\r\n\tsWriteUint32(channel);\r\n}\r\n\r\nvoid WritePositionalStream(uint32 dummyId, uint32 streamNameChecksum, float dropoff, float volume, float pitch, int priority, int use_pos_info)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(PLAY_POSITIONAL_STREAM);\r\n\tsWriteUint32(dummyId);\r\n\tsWriteUint32(streamNameChecksum);\r\n\tsWriteFloat(dropoff);\r\n\tsWriteFloat(volume);\r\n\tsWriteFloat(pitch);\r\n\tsWriteUint32(priority);\r\n\tsWriteUint32(use_pos_info);\r\n}\t\r\n\r\nvoid WritePositionalSoundEffect(uint32 dummyId, uint32 soundName, float volume, float pitch, float dropOffDist)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(PLAY_POSITIONAL_SOUND_EFFECT);\r\n\tsWriteUint32(dummyId);\r\n\tsWriteUint32(soundName);\r\n\tsWriteFloat(volume);\r\n\tsWriteFloat(pitch);\r\n\tsWriteFloat(dropOffDist);\r\n}\t\r\n\r\n// Called from CSk3SfxManager::PlaySound, takes the same parameters, except for 'propogate' (sic)\r\n// which I guess will always be false, since no replays in multiplayer.\r\nvoid WriteSkaterSoundEffect(int whichArray, int surfaceFlag, const Mth::Vector &pos, \r\n\t\t\t\t\t\t\tfloat volPercent)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(PLAY_SKATER_SOUND_EFFECT);\r\n\tsWriteUint32(whichArray);\r\n\tsWriteUint32(surfaceFlag);\r\n\tsWriteFloat(pos[X]);\r\n\tsWriteFloat(pos[Y]);\r\n\tsWriteFloat(pos[Z]);\r\n\tsWriteFloat(volPercent);\r\n}\r\n\r\nvoid WritePlaySound(uint32 checksum, float volL, float volR, float pitch)\r\n{\r\n\tif (sMode!=RECORD)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tsWriteSingleToken(PLAY_SOUND);\r\n\tsWriteUint32(checksum);\r\n\tsWriteFloat(volL);\r\n\tsWriteFloat(volR);\r\n\tsWriteFloat(pitch);\r\n}\r\n\r\nstatic void sRecordSkaterCamera(CTrackingInfo *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info\"));\r\n\t\r\n\tif (p_info->mFlags & TRACKING_INFO_FLAG_OBJECT_CREATED)\r\n\t{\r\n\t\tsWriteUint32(CREATE_OBJECT,ID_CAMERA);\r\n\t\tsWriteUint8(SKATE_TYPE_UNDEFINED);\r\n\t\tp_info->mFlags &= ~TRACKING_INFO_FLAG_OBJECT_CREATED;\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\t// Write in the object Id\r\n\t\tsWriteUint32(OBJECT_ID,ID_CAMERA);\r\n\t}\t\r\n\t\r\n\tObj::CSkater *p_skater=sGetSkater();\r\n\tGfx::Camera *p_skater_camera=p_skater->GetActiveCamera();\r\n\tDbg_MsgAssert(p_skater_camera,(\"NULL p_skater_camera\"));\r\n\t\r\n\tMth::Vector actual_angles;\r\n\tp_skater_camera->GetMatrix().GetEulers(actual_angles);\r\n\tp_info->RecordPositionAndAngleChanges(p_skater_camera->GetPos(),actual_angles,true);\r\n}\r\n\r\nstatic bool sIsFlipped(Obj::CMovingObject *p_movingObject)\r\n{\r\n\tDbg_MsgAssert(p_movingObject,(\"NULL p_movingObject\"));\r\n\t\r\n\tif (p_movingObject->GetType()==SKATE_TYPE_SKATER)\r\n\t{\r\n\t\treturn GetSkaterCorePhysicsComponentFromObject(p_movingObject)->GetFlag(Obj::FLIPPED);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert( 0, ( \"Flipped-ness has been moved to animation component\" ) );\r\n\t\treturn false;\r\n//\t\treturn p_movingObject->IsFlipped();\r\n\t}\r\n}\r\n\r\nstatic void sRecordCMovingObject(CTrackingInfo *p_info)\r\n{\r\n\tDbg_MsgAssert(p_info,(\"NULL p_info\"));\r\n\tDbg_MsgAssert(p_info->mPointerType==CMOVINGOBJECT,(\"Not a moving object?\"));\r\n\t\r\n\tif (!p_info->mpMovingObject)\r\n\t{\r\n\t\tsWriteUint32(KILL_OBJECT,p_info->m_id);\r\n\t\tdelete p_info;\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tObj::CMovingObject *p_moving_object=p_info->mpMovingObject;\r\n\tNx::CModel* p_model=p_moving_object->GetModel();\r\n\r\n\tuint8 *p_start=spFrameBufferPos;\r\n\t\r\n\tif (p_info->mFlags & TRACKING_INFO_FLAG_OBJECT_CREATED)\r\n\t{\r\n\t\tsWriteUint32(CREATE_OBJECT,p_moving_object->GetID());\r\n\t\tsWriteUint8(p_moving_object->GetType());\r\n\t\tp_info->mFlags &= ~TRACKING_INFO_FLAG_OBJECT_CREATED;\r\n\r\n\t\tObj::CAnimationComponent* pAnimComponent = GetAnimationComponentFromObject( p_moving_object );\r\n        if ( pAnimComponent )\r\n        {\r\n            sWriteUint32(ANIM_SCRIPT_NAME,pAnimComponent->GetAnimScriptName());\r\n        }\r\n        else\r\n        {\r\n            sWriteUint32(ANIM_SCRIPT_NAME,0);\r\n        }\r\n\r\n\t\tswitch (p_moving_object->GetType())\r\n\t\t{\r\n\t\t\tcase SKATE_TYPE_SKATER:\r\n\t\t\t\tsWriteUint32(SKELETON_NAME,0x5a9d2a0a/*Human*/);\r\n\t\t\t\tbreak;\r\n\t\t\tcase SKATE_TYPE_CAR:\r\n\t\t\t{\r\n\t\t\t\t/*\r\n\t\t\t\tObj::CCar *p_car=(Obj::CCar*)p_moving_object;\r\n\t\t\t\tObj::CModelRestorationInfo *p_model_restoration_info=&p_car->m_model_restoration_info;\r\n\t\t\t\t\r\n\t\t\t\tsWriteUint32(SKELETON_NAME,p_model_restoration_info->mSkeletonName);\r\n\t\t\t\tsWriteString(MODEL_NAME,p_model_restoration_info->GetModelName());\r\n\t\t\t\t*/\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SKATE_TYPE_PED:\r\n\t\t\t{\r\n\t\t\t\t/*\r\n\t\t\t\tObj::CPed *p_ped=(Obj::CPed*)p_moving_object;\r\n\t\t\t\tObj::CModelRestorationInfo *p_model_restoration_info=&p_ped->m_model_restoration_info;\r\n\t\t\t\t\r\n\t\t\t\tsWriteUint32(SKELETON_NAME,p_model_restoration_info->mSkeletonName);\r\n\t\t\t\tif (p_model_restoration_info->mProfileName)\r\n\t\t\t\t{\r\n\t\t\t\t\tsWriteUint32(PROFILE_NAME,p_model_restoration_info->mProfileName);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tsWriteString(MODEL_NAME,p_model_restoration_info->GetModelName());\r\n\t\t\t\t}\r\n\t\t\t\t*/\r\n\t\t\t\tbreak;\r\n\t\t\t}\t\r\n\t\t\tcase SKATE_TYPE_GAME_OBJ:\r\n\t\t\t{\r\n\t\t\t\t/*\r\n\t\t\t\tObj::CGameObj *p_game_ob=(Obj::CGameObj*)p_moving_object;\r\n\t\t\t\tObj::CModelRestorationInfo *p_model_restoration_info=&p_game_ob->m_model_restoration_info;\r\n\t\t\t \r\n\t\t\t\tsWriteUint32(SECTOR_NAME,p_model_restoration_info->mSectorName);\r\n\t\t\t\tsWriteUint32(SKELETON_NAME,p_model_restoration_info->mSkeletonName);\r\n\t\t\t\tsWriteString(MODEL_NAME,p_model_restoration_info->GetModelName());\r\n\t\t\t\t*/\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t/*\r\n\t\t\t// CBouncyObj has been replaced by CComposite object\r\n\t\t\tcase SKATE_TYPE_BOUNCY_OBJ:\r\n\t\t\t{\r\n\t\t\t\tObj::CBouncyObj *p_bouncy_ob=(Obj::CBouncyObj*)p_moving_object;\r\n\t\t\t\tObj::CModelRestorationInfo *p_model_restoration_info=&p_bouncy_ob->m_model_restoration_info;\r\n\t\t\t\t\r\n\t\t\t\tsWriteUint32(SECTOR_NAME,p_model_restoration_info->mSectorName);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t*/\r\n\t\t\tdefault:\r\n\t\t\t\tprintf(\"Created object, type=%d\\n\",p_moving_object->GetType());\r\n\t\t\t\tbreak;\r\n\t\t}\t\t\r\n\r\n\t\tp_info->mFlags &= ~TRACKING_INFO_FLAG_ACTIVE;\r\n\t\tp_info->mFlags &= ~TRACKING_INFO_FLAG_FLIPPED;\r\n\t\tp_info->mFlags &= ~TRACKING_INFO_FLAG_HOVERING;\r\n\t\t\r\n\t\t// Write out a SET_ATOMIC_STATES token to initialise the atomic states of the\r\n\t\t// dummy when it gets created later.\r\n\t\tif (p_model)\r\n\t\t{\r\n\t\t\tsWriteUint32(SET_ATOMIC_STATES,p_moving_object->GetID());\r\n\t\t\tsWriteUint32(p_model->GetGeomActiveMask());\r\n\t\t}\t\r\n\t}\t\r\n\telse\r\n\t{\r\n\t\t// Write in the object Id\r\n\t\tsWriteUint32(OBJECT_ID,p_moving_object->GetID());\r\n\t}\t\r\n\r\n\tif (p_model && p_model->GetScale().GetX() != p_info->mScale)\r\n\t{\r\n\t\t// Some peds do use non 1 scale, eg the gorilla in the tram in the zoo\r\n\t\t// And the shark in sf2\r\n\t\tsWriteFloat(SET_SCALE,p_model->GetScale().GetX());\r\n\t\tp_info->mScale=p_model->GetScale().GetX();\r\n\t}\t\r\n\r\n\tbool hovering=false;\r\n\tObj::CMotionComponent *p_motion_component=GetMotionComponentFromObject(p_moving_object);\r\n\tif (p_motion_component)\r\n\t{\r\n\t\thovering = p_motion_component->IsHovering();\r\n\t}\r\n\r\n\t\r\n\t\r\n\tif (hovering)\r\n\t{\r\n\t\tif (p_info->mFlags & TRACKING_INFO_FLAG_HOVERING)\r\n\t\t{\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_info->mFlags |= TRACKING_INFO_FLAG_HOVERING;\r\n\t\t\tMth::Vector pos;\r\n\t\t\tp_motion_component->GetHoverOrgPos(&pos);\r\n\t\t\t\r\n\t\t\tsWriteSingleToken(HOVERING);\r\n\t\t\tsWriteFloat(pos[X]);\r\n\t\t\tsWriteFloat(pos[Y]);\r\n\t\t\tsWriteFloat(pos[Z]);\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (p_info->mFlags & TRACKING_INFO_FLAG_HOVERING)\r\n\t\t{\r\n\t\t\t// Need to support this? I don't think anything ever goes from hovering to not hovering?\r\n\t\t}\r\n\t}\r\n\t\t\t\t\t\t\r\n\tbool flipped=sIsFlipped(p_moving_object);\r\n\tif (flipped)\r\n\t{\r\n\t\tif (p_info->mFlags & TRACKING_INFO_FLAG_FLIPPED)\r\n\t\t{\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_info->mFlags |= TRACKING_INFO_FLAG_FLIPPED;\r\n\t\t\tsWriteSingleToken(FLIP);\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (p_info->mFlags & TRACKING_INFO_FLAG_FLIPPED)\r\n\t\t{\r\n\t\t\tp_info->mFlags &= ~TRACKING_INFO_FLAG_FLIPPED;\r\n\t\t\tsWriteSingleToken(UNFLIP);\r\n\t\t}\r\n\t}\r\n\r\n\tbool active=false;\r\n\tif (p_model)\r\n\t{\r\n\t\tactive=p_model->GetActive();\r\n\t}\r\n\tif (active)\r\n\t{\r\n\t\tif (p_info->mFlags & TRACKING_INFO_FLAG_ACTIVE)\r\n\t\t{\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_info->mFlags |= TRACKING_INFO_FLAG_ACTIVE;\r\n\t\t\tsWriteSingleToken(MODEL_ACTIVE);\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (p_info->mFlags & TRACKING_INFO_FLAG_ACTIVE)\r\n\t\t{\r\n\t\t\tp_info->mFlags &= ~TRACKING_INFO_FLAG_ACTIVE;\r\n\t\t\tsWriteSingleToken(MODEL_INACTIVE);\r\n\t\t}\r\n\t}\r\n\t\r\n\t//Mth::Matrix objects_display_matrix=p_moving_object->GetDisplayMatrix();\r\n\t//objects_display_matrix[Mth::POS]=p_moving_object->GetPos();\r\n\t//Mth::Vector actual_pos=objects_display_matrix[Mth::POS];\r\n\t\r\n\tif (!hovering)\r\n\t{\r\n\t\tMth::Vector actual_pos=p_moving_object->GetPos();\r\n\t\tMth::Vector actual_angles;\r\n\t\t\r\n\t\t//if (p_moving_object->IsSpecialItem())\r\n\t\t//{\r\n\t\t//\tprintf(\"Recording exact pos of special item %x\\n\",p_moving_object->GetID());\r\n\t\t//}\r\n\t\t\t\r\n\t\t// GJ:  Need to reimplement special-case special item code\r\n\t\t// because the current implementation conflicts with our\r\n\t\t// new CCOmpositeObject model.\r\n\t\tif (p_info->m_id==ID_SKATER )\r\n//\t\tif (p_info->m_id==ID_SKATER || p_moving_object->IsSpecialItem())\r\n\t\t{\r\n\t\t\tp_moving_object->GetDisplayMatrix().GetEulers(actual_angles);\r\n\t\t\tp_info->RecordPositionAndAngleChanges(actual_pos,actual_angles,true);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (p_moving_object->GetDisplayMatrix() != p_info->mLastMatrix)\r\n\t\t\t{\r\n\t\t\t\tp_moving_object->GetDisplayMatrix().GetEulers(actual_angles);\r\n\t\t\t\tp_info->mLastMatrix=p_moving_object->GetDisplayMatrix();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tactual_angles[X]=p_info->mTrackerAngleX.GetActualLast();\r\n\t\t\t\tactual_angles[Y]=p_info->mTrackerAngleY.GetActualLast();\r\n\t\t\t\tactual_angles[Z]=p_info->mTrackerAngleZ.GetActualLast();\r\n\t\t\t}\t\r\n\t\t\tp_info->RecordPositionAndAngleChanges(actual_pos,actual_angles);\r\n\t\t}\t\r\n\t}\r\n\t\t\r\n\t// Do the animation stuff ...\r\n#if 0\r\n\tuint8 *p_num_changes=NULL;\r\n\tuint8 num_changes=0;\r\n\t\r\n\tObj::CAnimationComponent* pAnimComponent = GetAnimationComponentFromObject( p_moving_object );\r\n\tif ( pAnimComponent && pAnimComponent->HasAnims() )\r\n\t{\r\n\t\tsWriteSingleToken(PRIMARY_ANIM_CONTROLLER_CHANGES);\r\n\t\tp_num_changes=spFrameBufferPos;\r\n\t\t++spFrameBufferPos;\r\n\t\tnum_changes=sWriteCAnimChannelChanges(&p_info->m_primaryController,pAnimComponent->GetPrimaryController());\r\n\t\tif (!num_changes)\r\n\t\t{\r\n\t\t\tspFrameBufferPos-=2;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_info->m_primaryController=*pAnimComponent->GetPrimaryController();\r\n\t\t\t*p_num_changes=num_changes;\r\n\t\t}\r\n\t}\t\r\n\t\r\n\tif (p_info->m_id==ID_SKATER)\r\n\t{\r\n\t\tfor (int i=0; i<NUM_DEGENERATE_ANIMS; ++i)\r\n\t\t{\r\n\t\t\tsWriteSingleToken(DEGENERATE_ANIM_CONTROLLER_CHANGES);\r\n\t\t\tsWriteUint8(i);\r\n\t\t\tp_num_changes=spFrameBufferPos;\r\n\t\t\t++spFrameBufferPos;\r\n            if (pAnimComponent)\r\n            {\r\n                num_changes=sWriteCAnimChannelChanges(&p_info->sSkaterTrackingInfo.m_degenerateControllers[i],pAnimComponent->GetDegenerateController(i));\r\n            }\r\n            else\r\n            {\r\n                num_changes=0;\r\n            }\r\n\t\t\tif (!num_changes)\r\n\t\t\t{\r\n\t\t\t\tspFrameBufferPos-=3;\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_info->sSkaterTrackingInfo.m_degenerateControllers[i]=*pAnimComponent->GetDegenerateController(i);\r\n\t\t\t\t*p_num_changes=num_changes;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// Check for skater looping sound changes\r\n\t\tuint32 skater_looping_sound_id=0;\r\n\t\tuint32 skater_looping_sound_checksum=0;\r\n\t\tfloat skater_pitch_min;\r\n\t\tfloat skater_pitch_max;\r\n\t\tObj::CSkater *p_skater=(Obj::CSkater*)p_moving_object;\r\n\t\t\r\n\t\t// NOTE: this information has moved to CSkaterLoopingSoundComponent\r\n\t\tp_skater->GetLoopingSoundInfo(\t&skater_looping_sound_id,\r\n\t\t\t\t\t\t\t\t\t\t&skater_looping_sound_checksum,\r\n\t\t\t\t\t\t\t\t\t\t&skater_pitch_min,\r\n\t\t\t\t\t\t\t\t\t\t&skater_pitch_max);\r\n\t\tif (skater_looping_sound_id)\r\n\t\t{\r\n\t\t\t// Skater is playing a looping sound\r\n\t\t\tif (CTrackingInfo::sSkaterTrackingInfo.m_playing_looping_sound)\r\n\t\t\t{\r\n\t\t\t\t// Tracker already knows the skater was playing a looping sound, but\r\n\t\t\t\t// perhaps the name of the sound has changed.\r\n\t\t\t\tif (CTrackingInfo::sSkaterTrackingInfo.m_looping_sound_checksum != skater_looping_sound_checksum)\r\n\t\t\t\t{\r\n\t\t\t\t\tsWriteUint32(PLAY_LOOPING_SOUND,skater_looping_sound_checksum);\r\n\t\t\t\t\tCTrackingInfo::sSkaterTrackingInfo.m_looping_sound_checksum = skater_looping_sound_checksum;\r\n\t\t\t\t}\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsWriteUint32(PLAY_LOOPING_SOUND,skater_looping_sound_checksum);\r\n\t\t\t\tCTrackingInfo::sSkaterTrackingInfo.m_looping_sound_checksum = skater_looping_sound_checksum;\r\n\t\t\t\tCTrackingInfo::sSkaterTrackingInfo.m_playing_looping_sound=true;\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\tif (skater_pitch_min != CTrackingInfo::sSkaterTrackingInfo.m_pitch_min)\r\n\t\t\t{\r\n\t\t\t\tsWriteFloat(PITCH_MIN,skater_pitch_min);\r\n\t\t\t\tCTrackingInfo::sSkaterTrackingInfo.m_pitch_min = skater_pitch_min;\r\n\t\t\t}\t\r\n\t\t\tif (skater_pitch_max != CTrackingInfo::sSkaterTrackingInfo.m_pitch_max)\r\n\t\t\t{\r\n\t\t\t\tsWriteFloat(PITCH_MAX,skater_pitch_max);\r\n\t\t\t\tCTrackingInfo::sSkaterTrackingInfo.m_pitch_max = skater_pitch_max;\r\n\t\t\t}\t\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (CTrackingInfo::sSkaterTrackingInfo.m_playing_looping_sound)\r\n\t\t\t{\r\n\t\t\t\tsWriteSingleToken(STOP_LOOPING_SOUND);\r\n\t\t\t\tCTrackingInfo::sSkaterTrackingInfo.m_playing_looping_sound=false;\r\n\t\t\t\tCTrackingInfo::sSkaterTrackingInfo.m_looping_sound_checksum=0;\r\n\t\t\t}\r\n\t\t}\t\t\r\n\t}\t\r\n#endif\r\n\r\n\tif (p_moving_object->GetType()==SKATE_TYPE_CAR)\r\n\t{\r\n\t\tfloat car_rotation_x, wheel_rotation_x, wheel_rotation_y;\r\n\t\t((Obj::CCar*)p_moving_object)->GetRotationValues(&car_rotation_x,&wheel_rotation_x,&wheel_rotation_y);\r\n\t\t\r\n\t\tp_info->mTrackerCarRotationX.WriteChanges(car_rotation_x,SET_CAR_ROTATION_X,SET_CAR_ROTATION_X_VEL);\r\n\t\tp_info->mTrackerWheelRotationX.WriteChanges(wheel_rotation_x,SET_WHEEL_ROTATION_X,SET_WHEEL_ROTATION_X_VEL);\r\n\t\tp_info->mTrackerWheelRotationY.WriteChanges(wheel_rotation_y,SET_WHEEL_ROTATION_Y,SET_WHEEL_ROTATION_Y_VEL);\r\n\t}\r\n\t\r\n\t// If no changes at all got written in for this object, then remove the object Id.\r\n\t// This is an important space optimization, because if this redundant info were not\r\n\t// removed then each frame would be several hundred bytes bigger.\r\n\tif (*p_start==OBJECT_ID && spFrameBufferPos-p_start==5)\r\n\t{\r\n\t\tspFrameBufferPos=p_start;\r\n\t}\t\r\n}\r\n\r\n//static int record_frame=0;\r\nstatic void sRecord()\r\n{\r\n\tCTrackingInfo *p_info=spTrackingInfoHead;\r\n\twhile (p_info)\r\n\t{\r\n\t\tCTrackingInfo *p_next=p_info->mpNext;\r\n\r\n\t\tif (p_info->m_id==ID_CAMERA)\r\n\t\t{\r\n\t\t\tsRecordSkaterCamera(p_info);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tswitch (p_info->mPointerType)\r\n\t\t\t{\r\n\t\t\t\tcase CMOVINGOBJECT:\r\n\t\t\t\t\tsRecordCMovingObject(p_info);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\t\t\t\t\t\t\t\r\n\t\tp_info=p_next;\r\n\t}\t\r\n\r\n\tint current_blur=Nx::CEngine::sGetScreenBlur();\r\n\tif (current_blur != CTrackingInfo::sScreenBlurTracker)\r\n\t{\r\n\t\tsWriteSingleToken(SCREEN_BLUR);\r\n\t\tsWriteUint32(current_blur);\r\n\t\tCTrackingInfo::sScreenBlurTracker=current_blur;\r\n\t}\t\r\n\t\r\n\t// REMOVE\r\n\t//printf(\"Size=%d\\n\",spFrameBufferPos-spFrameBuffer);\r\n\t\r\n\tsWriteFrameBufferToBigBuffer();\r\n}\r\n\r\n//static int playback_frame=0;\r\nstatic void sPlayback(bool display)\r\n{\r\n\t// If reached the end of the replay, do nothing.\r\n\tif (sReachedEndOfReplay)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\tif (sReplayPaused)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\r\n\tObj::CSkater *p_skater=sGetSkater();\r\n\t// NGC must not replay vibrations, TRC requirement.\r\n\tif (Config::GetHardware() != Config::HARDWARE_NGC)\r\n\t{\r\n\t\tif (sNeedToInitialiseVibration)\r\n\t\t{\r\n\t\t\tif (!sCurrentState.mSkaterPaused)\r\n\t\t\t{\r\n\t\t\t\tfor (int i=0; i<Obj::CVibrationComponent::vVB_NUM_ACTUATORS; ++i)\r\n\t\t\t\t{\r\n\t\t\t\t\tp_skater->GetDevice()->ActivateActuator(i,sCurrentState.mActuatorStrength[i]);\r\n\t\t\t\t}\t\r\n\t\t\t}\t\r\n\t\t\tsNeedToInitialiseVibration=false;\r\n\t\t}\r\n\t}\r\n\t\t\r\n\t// Read the next frame\r\n\tbool nothing_follows=false;\r\n\tsNextPlaybackFrameOffset=sReadFrame(sNextPlaybackFrameOffset,&nothing_follows,PLAYBACK_DUMMY_LIST);\r\n\r\n\t// The process of reading the frame will have updated all the dummy's.\r\n\t// Now display them & do other misc stuff like update sounds.\r\n\tCDummy *p_dummy=spReplayDummies;\r\n\twhile (p_dummy)\r\n\t{\r\n\t\tp_dummy->UpdateMutedSounds();\r\n\t\tif (display)\r\n\t\t{\r\n\t\t\tp_dummy->DisplayModel();\r\n\t\t}\t\r\n\t\tp_dummy=p_dummy->mpNext;\r\n\t}\r\n\r\n\r\n\t// Wrap around if reached the end of the replay buffer.\r\n\tif (sNextPlaybackFrameOffset==GetBufferSize())\r\n\t{\r\n\t\tsNextPlaybackFrameOffset=0;\r\n\t}\r\n\t\r\n\t// It is possible that the frame could be followed by some space filled with\r\n\t// BLANK, so skip over it until either a new frame is hit or we get back\r\n\t// to the start frame.\r\n\twhile (true)\r\n\t{\r\n\t\tuint8 token;\r\n\t\tReadFromBuffer(&token,sNextPlaybackFrameOffset,1);\r\n\t\t\r\n\t\tif (token != BLANK)\r\n\t\t{\r\n\t\t\t// Hit a new frame\r\n\t\t\tDbg_MsgAssert(token==FRAME_START,(\"Expected token to be FRAME_START\"));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\t\t// sBufferFilling is a flag used to indicate that the buffer is filling up for the\r\n\t\t// first time and has not cycled around yet.\r\n\t\t// Knowing this means we don't need to read each individual byte, since we know everything\r\n\t\t// will be blank till the end of the buffer, so just set sNextPlaybackFrameOffset to 0\r\n\t\t// straight away.\r\n\t\t// This is a speed optimization for the GameCube, since it has a 4meg replay buffer, and\r\n\t\t// it takes several seconds so read all those blanks.\r\n\t\tif (sBufferFilling)\r\n\t\t{\r\n\t\t\tDbg_MsgAssert(sBigBufferStartOffset==0,(\"Expected sBigBufferStartOffset to be zero when the buffer is filling up?\"));\r\n\t\t\tsNextPlaybackFrameOffset=0;\r\n\t\t}\r\n\t\t\r\n\t\tif (sNextPlaybackFrameOffset==sBigBufferStartOffset)\r\n\t\t{\r\n\t\t\t// Reached the start again.\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t\t\r\n\t\t++sNextPlaybackFrameOffset;\r\n\t\tif (sNextPlaybackFrameOffset==GetBufferSize())\r\n\t\t{\r\n\t\t\tsNextPlaybackFrameOffset=0;\r\n\t\t}\r\n\t}\t\t\t\t\t\r\n\t\t\r\n\t// If we've got back to the start, then that is the end of the replay,\r\n\t// so kill all the dummys and restore everything the way it was.\r\n\tif (sNextPlaybackFrameOffset==sBigBufferStartOffset)\r\n\t{\r\n\t\t// Switch off any vibrations being done by the replay, so that they do not continue\r\n\t\t// while the end-replay menu is on screen.\r\n\t\t// Note that any vibrations that were being done in-game before the replay was run will\r\n\t\t// automatically get restored when the game is un-paused, so we do not need to restore them here.\r\n\t\tsSwitchOffVibrations();\r\n\r\n\t\tsStopReplayDummyLoopingSounds();\r\n\t\t\r\n\t\t// Now that the replay has ended, the player may want to save it to mem card.\r\n\t\t// So make sure that the start-state contains the correct active/visible status of all the sectors.\r\n\t\tNx::CEngine::sWriteSectorStatusBitfield(sStartState.mpSectorStatus,SECTOR_STATUS_BUFFER_SIZE);\r\n\t\t\r\n\t\tScript::RunScript(\"EndOfReplay\");\r\n\t\tsReachedEndOfReplay=true;\r\n\t}\t\r\n}\r\n\r\nstatic void sEnsureTrackerExists( Obj::CObject *p_ob, void *p_data )\r\n{\r\n\tDbg_MsgAssert(p_ob,(\"NULL p_ob\"));\r\n\r\n\tCTrackingInfo *p_info=sTrackingInfoHashTable.GetItem((uint32)p_ob->GetID());\r\n\tif (!p_info)\r\n\t{\r\n\t\tint type=p_ob->GetType();\r\n\t\tDbg_MsgAssert(!(p_ob->GetID()==0 && type!=SKATE_TYPE_SKATER),(\"Non-skater object has an id of 0, type=%d\\n\",type));\r\n\t\t\r\n\t\tif (type==SKATE_TYPE_CAR ||\r\n\t\t\ttype==SKATE_TYPE_PED ||\r\n\t\t\ttype==SKATE_TYPE_BOUNCY_OBJ ||\r\n\t\t\ttype==SKATE_TYPE_SKATER ||\r\n\t\t\ttype==SKATE_TYPE_GAME_OBJ)\r\n\t\t{\r\n\t\t\tp_info=new CTrackingInfo;\r\n\t\t\tp_info->SetMovingObject((Obj::CMovingObject*)p_ob);\r\n\t\t\tp_info->mFlags |= TRACKING_INFO_FLAG_OBJECT_CREATED;\r\n\t\t}\t\r\n\t}\t\r\n}\r\n\r\nstatic void sEnsureCameraTrackerExists()\r\n{\r\n\tCTrackingInfo *p_info=sTrackingInfoHashTable.GetItem((uint32)ID_CAMERA);\r\n\tif (!p_info)\r\n\t{\r\n\t\tp_info=new CTrackingInfo;\r\n\t\tp_info->SetSkaterCamera();\r\n\t\tp_info->mFlags |= TRACKING_INFO_FLAG_OBJECT_CREATED;\r\n\t}\t\r\n}\r\n\r\nstatic void sHideForReplayPlayback( Obj::CObject *p_ob, void *p_data )\r\n{\r\n\tDbg_MsgAssert(p_ob,(\"NULL p_ob\"));\r\n\tp_ob->HideForReplayPlayback();\r\n}\r\n\r\nstatic void sRestoreAfterReplayPlayback( Obj::CObject *p_ob, void *p_data )\r\n{\r\n\tDbg_MsgAssert(p_ob,(\"NULL p_ob\"));\r\n\tp_ob->RestoreAfterReplayPlayback();\r\n}\r\n\r\nstatic void sClearLastPanelMessage()\r\n{\r\n\tScript::CStruct *p_params=new Script::CStruct;\r\n\tp_params->AddChecksum(\"id\",sLastRecordedPanelMessageID);\r\n\t\r\n\tScript::RunScript(\"kill_panel_message_if_it_exists\",p_params);\r\n\tdelete p_params;\r\n}\r\n\r\nstatic void sClearTrickAndScoreText()\r\n{\r\n\tFront::CScreenElementManager* p_manager = Front::CScreenElementManager::Instance();\r\n\tint index=sGetSkater()->GetHeapIndex();\r\n\tFront::CTextBlockElement *p_text_block = (Front::CTextBlockElement *) p_manager->GetElement(0x44727dae/*the_trick_text*/ + index ).Convert();\r\n\tif (p_text_block)\r\n\t{\r\n\t\tp_text_block->SetText(NULL, 0);\r\n\t}\r\n\tFront::CTextElement *p_score_pot_text = (Front::CTextElement *) p_manager->GetElement(0xf4d3a70e + index ).Convert(); // \"the_score_pot_text\"\r\n\tif (p_score_pot_text)\r\n\t{\r\n\t\tp_score_pot_text->SetText(\"\");\r\n\t}\r\n\tsTrickTextGotCleared=true;\r\n}\r\n\r\nbool ScriptClearTrickAndScoreText(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tsClearTrickAndScoreText();\r\n\treturn true;\r\n}\r\n\r\nbool ScriptPlaybackReplay(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tsClearTrickAndScoreText();\r\n\tsClearLastPanelMessage();\r\n\tNx::MiscFXCleanup();\r\n\tNx::CEngine::sSetScreenBlur(0);\r\n\t\r\n\t// Check that there are no replay dummy's in existence at the moment.\r\n\tDbg_MsgAssert(spReplayDummies==NULL,(\"Expected spReplayDummies to be NULL\")); \r\n\tsReplayDummysHashTable.IterateStart();\r\n\tDbg_MsgAssert(sReplayDummysHashTable.IterateNext()==NULL,(\"Expected sReplayDummysHashTable to be empty\")); \r\n\r\n\t// Create the replay dummy's by making copies of the start-state dummy's.\r\n\tCDummy *p_source_dummy=spStartStateDummies;\r\n\twhile (p_source_dummy)\r\n\t{\r\n\t\tCDummy *p_new_dummy=new CDummy(PLAYBACK_DUMMY_LIST,p_source_dummy->GetID());\r\n\t\t// Make a copy of the contents of the CDummy.\r\n\t\t// The assignement operator for CDummy is overloaded.\r\n\t\t*p_new_dummy=*p_source_dummy;\r\n\t\t\r\n\t\tp_source_dummy=p_source_dummy->mpNext;\r\n\t}\t\r\n\r\n\tNx::CEngine::sPrepareSectorsForReplayPlayback(pParams->ContainsFlag(\"store\"));\r\n\t\r\n\tsCurrentState=sStartState;\r\n\tsNextPlaybackFrameOffset=sBigBufferStartOffset;\r\n\tsLastTrickTextChecksum=0;\r\n\tsMode=PLAYBACK;\r\n\tsReachedEndOfReplay=false;\r\n\tsReplayPaused=false;\r\n\t\r\n\t// NGC must not replay vibrations, TRC requirement.\r\n\tif (Config::GetHardware()==Config::HARDWARE_NGC)\r\n\t{\r\n\t\tsSwitchOffVibrations();\r\n\t}\r\n\t\t\r\n\tsNeedToInitialiseVibration=true;\r\n\tsUnpauseCertainScreenElements();\r\n\t\r\n\treturn true;\r\n}\r\n\r\nbool ScriptHideGameObjects( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tpSkate->GetObjectManager()->ProcessAllObjects( sHideForReplayPlayback, NULL );\r\n\treturn true;\r\n}\r\n\r\nbool ScriptShowGameObjects( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tMdl::Skate * pSkate = Mdl::Skate::Instance();\r\n\tpSkate->GetObjectManager()->ProcessAllObjects( sRestoreAfterReplayPlayback, NULL );\r\n\t\r\n\t// Make sure that the balance meters are not left on if the replay was quit during a balance.\r\n\tsGetSkaterScoreObject()->SetManualMeter(false);\r\n\tsGetSkaterScoreObject()->SetBalanceMeter(false);\r\n\t\r\n\t// Restore the active/visible state of the world sectors.\r\n\tNx::CEngine::sRestoreSectorsAfterReplayPlayback();\r\n\treturn true;\r\n}\r\n\r\nbool ScriptSwitchToReplayRecordMode( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tif (Mdl::Skate::Instance()->IsMultiplayerGame())\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\tsMode=RECORD;\r\n\treturn true;\r\n}\r\n\r\nbool ScriptSwitchToReplayIdleMode( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tif (Mdl::Skate::Instance()->IsMultiplayerGame())\r\n\t{\r\n\t\treturn false;\r\n\t}\t\r\n\tsMode=NONE;\r\n\treturn true;\r\n}\r\n\r\nbool RunningReplay()\r\n{\r\n\treturn sMode==PLAYBACK;\r\n}\r\n\r\nbool ScriptRunningReplay( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\treturn RunningReplay();\r\n}\r\n\t\r\nbool ScriptPauseReplay( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tsReplayPaused=true;\t\r\n\t\r\n\t// Switch off any vibration while the replay is paused\r\n\tsSwitchOffVibrations();\r\n\t\r\n\tsStopReplayDummyLoopingSounds();\r\n\t\r\n\t// Then set this flag so that the sPlayback function will switch the vibration back\r\n\t// on if need be once the replay is unpaused.\r\n\tsNeedToInitialiseVibration=true;\r\n\treturn true;\r\n}\r\n\r\nbool ScriptUnPauseReplay( Script::CStruct *pParams, Script::CScript *pScript )\r\n{\r\n\tsReplayPaused=false;\t\r\n\tsUnpauseCertainScreenElements();\r\n\treturn true;\r\n}\r\n\t\r\nbool Paused()\r\n{\r\n\treturn sReplayPaused;\r\n}\r\n\t\r\nvoid AddReplayMemCardInfo(Script::CStruct *p_struct)\r\n{\r\n\tDbg_MsgAssert(p_struct,(\"NULL p_struct\"));\r\n\tp_struct->AddChecksum(\"level_structure_name\",sLevelStructureName);\r\n}\r\n\r\nvoid AddReplayMemCardSummaryInfo(Script::CStruct *p_struct)\r\n{\r\n\tDbg_MsgAssert(p_struct,(\"NULL p_struct\"));\r\n\t\r\n\tScript::CStruct *p_level_def=Script::GetStructure(sLevelStructureName);\r\n\tDbg_MsgAssert(p_level_def,(\"Could not find level def '%s'\",Script::FindChecksumName(sLevelStructureName)));\r\n\t\r\n\tconst char *p_level_name=\"\";\r\n\tp_level_def->GetString(\"Name\",&p_level_name);\r\n\t\r\n\tp_struct->AddString(\"LevelName\",p_level_name);\r\n}\r\n\r\nbool ScriptRememberLevelStructureNameForReplays(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpParams->GetChecksum(\"level_structure_name\",&sLevelStructureName,Script::ASSERT);\r\n\treturn true;\r\n}\r\n\r\nvoid SetLevelStructureName(uint32 level_structure_name)\r\n{\r\n\tsLevelStructureName=level_structure_name;\r\n}\r\n\r\nbool ScriptGetReplayLevelStructureName(Script::CStruct *pParams, Script::CScript *pScript)\r\n{\r\n\tpScript->GetParams()->AddChecksum(\"level_structure_name\",sLevelStructureName);\r\n\treturn true;\r\n}\r\n\r\nManager::Manager()\r\n{\r\n\tDbg_MsgAssert(NUM_REPLAY_TOKEN_TYPES<=256,(\"Too many token types !!\"));\r\n\t\r\n\tmp_start_frame_task = new Tsk::Task< Manager > ( s_start_frame_code, *this,\r\n\t\t\t\t\t\t\t\t\t\tTsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_REPLAY_START_FRAME );\r\n\r\n\tmp_end_frame_task = new Tsk::Task< Manager > ( s_end_frame_code, *this,\r\n\t\t\t\t\t\t\t\t\t\tTsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_REPLAY_END_FRAME );\r\n\t\t\t\t\t\t\t\t\t\t\r\n\tMlp::Manager * mlp_manager = Mlp::Manager::Instance();\r\n\tmlp_manager->AddLogicTask( *mp_start_frame_task );\r\n\tmlp_manager->AddLogicTask( *mp_end_frame_task );\r\n}\r\n\r\nManager::~Manager()\r\n{\r\n\tdelete mp_start_frame_task;\r\n\tdelete mp_end_frame_task;\r\n}\r\n\r\nvoid Manager::s_start_frame_code( const Tsk::Task< Manager >& task )\r\n{\r\n\t//Manager& man = task.GetData();\r\n\tspFrameBufferPos=spFrameBuffer;\r\n\tsWriteUint32(FRAME_START,Tmr::GetTime());\r\n}\r\n\r\n/*\r\nstatic Tmr::CPUCycles sStartTime;\r\nstatic int s_num_times=0;\r\nstatic int s_time_index=0;\r\n#define MAX_TIMES 60\r\nstatic Tmr::CPUCycles spTimes[MAX_TIMES];\r\n\r\nvoid NewTime(Tmr::CPUCycles t)\r\n{\r\n\tspTimes[s_time_index++]=t;\r\n\tif (s_time_index>=MAX_TIMES)\r\n\t{\r\n\t\ts_time_index=0;\r\n\t}\r\n\tif (s_num_times<MAX_TIMES)\r\n\t{\r\n\t\t++s_num_times;\r\n\t}\r\n\t\r\n\tTmr::CPUCycles total=0;\r\n\tfor (int i=0; i<s_num_times; ++i)\r\n\t{\r\n\t\ttotal+=spTimes[i];\r\n\t}\t\r\n\t\r\n\tprintf(\"%d\\n\",total/s_num_times);\r\n}\t\r\n*/\r\n\r\nvoid Manager::s_end_frame_code( const Tsk::Task< Manager >& task )\r\n{\r\n\t//Manager& man = task.GetData();\r\n\t#ifdef DISABLE_REPLAYS\r\n\treturn;\r\n\t#endif\r\n\r\n\tif (Mdl::Skate::Instance()->IsMultiplayerGame())\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n\tswitch (sMode)\r\n\t{\r\n\t\tcase RECORD:\r\n\t\t{\r\n\t\t\t//sStartTime=Tmr::GetTimeInCPUCycles();\r\n\r\n\t\t\tsEnsureCameraTrackerExists();\r\n\t\t\t\t\t\r\n\t\t\tMdl::FrontEnd* p_front = Mdl::FrontEnd::Instance();\r\n\t\t\tif (!p_front->GamePaused())\r\n\t\t\t{\r\n\t\t\t\tMdl::Skate * p_skate = Mdl::Skate::Instance();\r\n\t\t\t\tp_skate->GetObjectManager()->ProcessAllObjects( sEnsureTrackerExists, NULL );\r\n\t\t\t\t\r\n\t\t\t\tsRecord();\r\n\t\t\t}\t\r\n\t\t\t\r\n\t\t\t//Tmr::CPUCycles t_record_time=Tmr::GetTimeInCPUCycles()-sStartTime;\r\n\t\t\t//NewTime(t_record_time);\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tcase PLAYBACK:\r\n\t\t{\r\n\t\t\tbool left=false;\r\n\t\t\tbool right=false;\r\n\t\t\tMdl::FrontEnd* pFront = Mdl::FrontEnd::Instance();\r\n\t\r\n\t\t\tfor ( int i = 0; i < SIO::vMAX_DEVICES; i++ )\r\n\t\t\t{\r\n\t\t\t\tif ( CFuncs::CheckButton( pFront->GetInputHandler( i ), 0x85981897 ) ) // left\r\n\t\t\t\t{\r\n\t\t\t\t\tleft=true;\r\n\t\t\t\t}\t\r\n\t\t\t\tif ( CFuncs::CheckButton( pFront->GetInputHandler( i ), 0x4b358aeb ) ) // right\r\n\t\t\t\t{\r\n\t\t\t\t\tright=true;\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (left)\r\n\t\t\t{\r\n\t\t\t\tif (Tmr::GetVblanks()&1)\r\n\t\t\t\t{\r\n\t\t\t\t\tsPlayback();\r\n\t\t\t\t}\t\r\n\t\t\t}\r\n\t\t\telse if (right)\r\n\t\t\t{\r\n\t\t\t\tsPlayback(false);\r\n\t\t\t\tsPlayback();\r\n\t\t\t}\t\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsPlayback();\r\n\t\t\t}\t\r\n\t\t\tbreak;\r\n\t\t}\t\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nGfx::CSkeleton* CDummy::GetSkeleton()\r\n{\r\n\tif ( mp_skeletonComponent )\r\n\t{\r\n\t\treturn mp_skeletonComponent->GetSkeleton();\r\n\t}\r\n\r\n\treturn NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool CDummy::LoadSkeleton( uint32 skeletonName )\r\n{\r\n    // temporarily moved this function from CModel,\r\n    // in order to make it easier to split off\r\n    // skeleton into its own component.\r\n\r\n\tGfx::CSkeletonData* pSkeletonData = (Gfx::CSkeletonData*) Ass::CAssMan::Instance()->GetAsset( skeletonName, false );\r\n\r\n\tif ( !pSkeletonData )\r\n\t{\r\n\t\tDbg_MsgAssert( 0, (\"Unrecognized skeleton %s. (Is skeleton.q up to date?)\", Script::FindChecksumName(skeletonName)) );\r\n\t}\r\n    \r\n\tDbg_MsgAssert( mp_skeletonComponent == NULL, ( \"Model already has skeleton component.  Possible memory leak?\" ) );    \r\n\tmp_skeletonComponent = new Obj::CSkeletonComponent;\r\n\r\n    Script::CStruct* pTempStructure = new Script::CStruct;\r\n    pTempStructure->AddChecksum( CRCD(0x222756d5,\"skeleton\"), skeletonName );\r\n    \r\n    mp_skeletonComponent->InitFromStructure( pTempStructure );\r\n    delete pTempStructure;\r\n\r\n#ifdef __NOPT_ASSERT__\r\n\tGfx::CSkeleton* pSkeleton = mp_skeletonComponent->GetSkeleton();\r\n    \r\n    Dbg_Assert( pSkeleton );\r\n    Dbg_Assert( pSkeleton->GetNumBones() > 0 );\r\n#endif\t\t// __NOPT_ASSERT__\r\n\t\r\n\treturn true;\r\n//    return mp_rendered_model->SetSkeleton( mp_skeletonComponent->GetSkeleton() );\r\n}\r\n\r\n}  // namespace Replay\r\n\r\n#endif\r\n"
  },
  {
    "path": "Code/Sys/Replay/replay.h",
    "content": "#ifndef __SYS_REPLAY_H\r\n#define __SYS_REPLAY_H\r\n\r\n#define\t__USE_REPLAYS__ 0\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n#ifndef __CORE_TASK_H\r\n#include <core/task.h>\r\n#endif\r\n\r\n#ifndef __CORE_MATH_VECTOR_H\r\n#include <core/math/vector.h>\r\n#endif\r\n\r\n#ifndef __GFX_ANIMCONTROLLER_H\r\n#include <gfx/animcontroller.h>\r\n#endif\r\n\r\n#ifndef\t__GFX_NXMODEL_H__\r\n#include <gfx/nxmodel.h>\r\n#endif\r\n\r\n#ifndef __GEL_OBJECT_H\r\n#include <gel/object.h>\r\n#endif\r\n\r\n#ifndef __GEL_SOUNDFX_H\r\n#include <gel/soundfx/soundfx.h>\r\n#endif\r\n\r\n#ifndef __GEL_COMPONENTS_VIBRATIONCOMPONENT_H\r\n#include <gel/components/vibrationcomponent.h>\r\n#endif\r\n\r\n#ifndef __OBJECTS_SKATER_H\r\n#include <sk/objects/skater.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Obj\r\n{\r\n\tclass CObject;\r\n\tclass CSkeletonComponent;\r\n}\r\n\r\nnamespace Script\r\n{\r\n\tclass CStruct;\r\n\tclass CScript;\r\n}\r\n\t\r\nnamespace Replay\r\n{\r\n\r\nclass  Manager  : public Spt::Class\r\n{\r\n\tTsk::Task< Manager > *mp_start_frame_task;\r\n\tstatic\tTsk::Task< Manager >::Code \ts_start_frame_code;\r\n\r\n\tTsk::Task< Manager > *mp_end_frame_task;\r\n\tstatic\tTsk::Task< Manager >::Code \ts_end_frame_code;\r\n\r\npublic:\r\n\tManager();\r\n\t~Manager();\r\n\t\r\nprivate:\t\r\n\tDeclareSingletonClass( Manager );\r\n};\r\n\r\n// 128 allows for a max of 4096 sectors\r\n#define SECTOR_STATUS_BUFFER_SIZE 128\r\nstruct SGlobalStates\r\n{\r\npublic:\r\n\tSGlobalStates();\r\n\t~SGlobalStates();\r\n\r\n\tvoid Reset();\r\n\t// Warning! If any new members get added or removed, update VERSION_REPLAY in mcfuncs.cpp\r\n\t// Also update the Reset function.\r\n\tbool mManualMeterStatus;\r\n\tfloat mManualMeterValue;\r\n\tbool mBalanceMeterStatus;\r\n\tfloat mBalanceMeterValue;\r\n\t\r\n\tint mActuatorStrength[Obj::CVibrationComponent::vVB_NUM_ACTUATORS];\r\n\tuint32 mpSectorStatus[SECTOR_STATUS_BUFFER_SIZE];\r\n\tbool mSkaterPaused;\r\n};\r\n\r\nstruct SReplayDataHeader\r\n{\r\n\tuint32 mBufferStartOffset;\r\n\tuint32 mBufferEndOffset;\r\n\tint mNumStartStateDummies;\r\n\tSGlobalStates mStartState;\r\n};\r\n\r\nenum\r\n{\r\n\tNUM_DEGENERATE_ANIMS=3\r\n};\t\r\n\r\nenum\r\n{\r\n\tDUMMY_FLAG_FLIPPED\t\t= (1<<0),\r\n\tDUMMY_FLAG_HOVERING\t\t= (1<<1),\r\n\tDUMMY_FLAG_ACTIVE\t\t= (1<<2),\r\n\t// Keep the number of these <= 32\r\n};\r\n\t\r\nstruct SSavedDummy\r\n{\r\n\tuint32 m_id;\r\n\tint\tm_type;\r\n//\tchar mpModelName[MAX_MODEL_NAME_CHARS+1];\t\r\n\tuint32 mSkeletonName;\r\n\tuint32 mProfileName;\r\n\tuint32 mAnimScriptName;\r\n\tuint32 mSectorName;\r\n\tuint32 mFlags;\r\n\tfloat  mScale;\r\n\t\r\n\tMth::Vector m_pos;\r\n\tMth::Vector m_vel;\r\n\tMth::Vector m_angles;\r\n\tMth::Vector m_ang_vel;\r\n\tfloat m_car_rotation_x;\r\n\tfloat m_car_rotation_x_vel;\r\n\tfloat m_wheel_rotation_x;\r\n\tfloat m_wheel_rotation_x_vel;\r\n\tfloat m_wheel_rotation_y;\r\n\tfloat m_wheel_rotation_y_vel;\r\n\r\n\tGfx::CAnimChannel\tm_primaryController;\r\n\r\n    Gfx::CAnimChannel   m_degenerateControllers[NUM_DEGENERATE_ANIMS];\r\n\tuint32 mAtomicStates;\r\n\t// These only apply to the skater.\r\n\tuint32 m_looping_sound_checksum;\r\n\tfloat m_pitch_min;\r\n\tfloat m_pitch_max;\r\n};\r\n\r\nenum EDummyList\r\n{\r\n\tSTART_STATE_DUMMY_LIST,\r\n\tPLAYBACK_DUMMY_LIST,\r\n};\r\n\r\nclass CDummy : public Obj::CMovingObject\r\n{\r\npublic:\t\r\n\tCDummy(EDummyList whichList, uint32 id);\r\n\tvirtual ~CDummy(void);\r\n\r\n\t// If any new members are added to CDummy, remember to update the following:\r\n\t// CDummy constructor, initialise new member\r\n\t// assignement operator, copy new member.\r\n\t// CDummy::Save function, save new member, and add to SSavedDummy, and update mem card version number\r\n\t// Replay::CreateDummyFromSaveData function, copy in new member.\r\n\t// Update VERSION_REPLAY in memcard.q\r\n\tCDummy& operator=( const CDummy& rhs );\r\n\r\n\tEDummyList m_list;\r\n\tCDummy *mpNext;\r\n\tCDummy *mpPrevious;\r\n\t\r\n\tvoid Update();\r\n\tvoid CreateModel();\r\n\tvoid DisplayModel();\r\n\tvoid UpdateMutedSounds();\r\n\tvoid UpdateLoopingSound();\r\n\t\r\n\tvoid Save(SSavedDummy *p_saved_dummy);\r\n\r\n//\tchar mpModelName[MAX_MODEL_NAME_CHARS+1];\t\r\n\tuint32 mSkeletonName;\r\n\tuint32 mProfileName;\r\n\tuint32 mAnimScriptName;\r\n\tuint32 mSectorName;\r\n\r\n\tbool m_is_displayed;\r\n\t\r\n\tfloat mScale;\r\n\t\r\n\tuint32 mFlags;\r\n\r\n\tint mHoverPeriod;\r\n\t\r\n\tMth::Vector m_vel;\r\n\tMth::Vector m_angles;\r\n\tMth::Vector m_ang_vel;\r\n\r\n\tfloat m_car_rotation_x;\r\n\tfloat m_car_rotation_x_vel;\r\n\tfloat m_wheel_rotation_x;\r\n\tfloat m_wheel_rotation_x_vel;\r\n\tfloat m_wheel_rotation_y;\r\n\tfloat m_wheel_rotation_y_vel;\r\n\t\r\n\tGfx::CAnimChannel \tm_primaryController;\r\n\r\n    Gfx::CAnimChannel    m_degenerateControllers[NUM_DEGENERATE_ANIMS];\r\n\t\r\n    Nx::CModel *mp_rendered_model;\r\n\tGfx::Camera *mp_skater_camera;\r\n\t//Obj::CSkaterCam *mp_skater_camera;\r\n\t\r\n\tuint32 mAtomicStates;\r\n\t\r\n\tuint32 m_looping_sound_id;\r\n\tuint32 m_looping_sound_checksum;\r\n\tfloat m_pitch_min;\r\n\tfloat m_pitch_max;\r\n\r\n    // TEMP\r\n    bool LoadSkeleton( uint32 skeletonChecksum );\r\n    Gfx::CSkeleton* GetSkeleton();\r\n    Obj::CSkeletonComponent* mp_skeletonComponent;\r\n};\r\n\r\n// The bigger this is the better, since it will speed up saving of replays to mem card.\r\n// A static buffer of this size exists though, so don't make it too big.\r\n#define REPLAY_BUFFER_CHUNK_SIZE 2048\r\n\r\n\r\n#if __USE_REPLAYS__  \r\n\r\n// These functions have platform specific versions.\r\n// On the GameCube for example, the buffer is in ARAM.\r\nvoid AllocateBuffer();\r\nvoid DeallocateBuffer();\r\nbool BufferAllocated();\r\nuint32 GetBufferSize();\r\nvoid ReadFromBuffer(uint8 *p_dest, int bufferOffset, int numBytes);\r\nvoid WriteIntoBuffer(uint8 *p_source, int bufferOffset, int numBytes);\r\nvoid FillBuffer(int bufferOffset, int numBytes, uint8 value);\r\nvoid WriteReplayDataHeader(SReplayDataHeader *p_header);\r\nvoid ReadReplayDataHeader(const SReplayDataHeader *p_header);\r\nvoid CreateDummyFromSaveData(SSavedDummy *p_saved_dummy);\r\nCDummy *GetFirstStartStateDummy();\r\n\r\nvoid ClearBuffer();\r\nuint8 *GetTempBuffer();\r\nvoid CreatePools();\r\nvoid RemovePools();\r\nvoid DeallocateReplayMemory();\r\nbool ScriptDeleteDummies( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptHideGameObjects( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptShowGameObjects( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptRunningReplay( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptPauseReplay( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptUnPauseReplay( Script::CStruct *pParams, Script::CScript *pScript );\r\n\r\nbool ScriptAllocateReplayMemory(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptDeallocateReplayMemory(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptStartRecordingAfresh(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptRememberLevelStructureNameForReplays(Script::CStruct *pParams, Script::CScript *pScript);\r\nvoid SetLevelStructureName(uint32 level_structure_name);\r\nbool ScriptGetReplayLevelStructureName(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptPlaybackReplay(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nbool ScriptReplayRecordSimpleScriptCall(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptRecordPanelMessage(Script::CStruct *pParams, Script::CScript *pScript);\r\nbool ScriptSwitchToReplayRecordMode( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptSwitchToReplayIdleMode( Script::CStruct *pParams, Script::CScript *pScript );\r\nbool ScriptClearTrickAndScoreText(Script::CStruct *pParams, Script::CScript *pScript);\r\n\r\nvoid WritePadVibration(int actuator, int percent);\r\nvoid WritePauseSkater();\r\nvoid WriteUnPauseSkater();\r\nvoid WriteScreenFlash(int viewport, Image::RGBA from, Image::RGBA to, float duration, float z, uint32 flags);\r\nvoid WriteShatter(uint32 sectorName, bool on);\r\nvoid WriteShatterParams(Mth::Vector& velocity, float area_test, float velocity_variance, float spread_factor, float lifetime, float bounce, float bounce_amplitude);\r\nvoid WriteTextureSplat(Mth::Vector& splat_start, Mth::Vector& splat_end, float size, float lifetime, const char *p_texture_name, uint32 trail );\r\nvoid WriteSectorActiveStatus(uint32 sectorName, bool active);\r\nvoid WriteSectorVisibleStatus(uint32 sectorName, bool visible);\r\nvoid WriteManualMeter(bool state, float value);\r\nvoid WriteBalanceMeter(bool state, float value);\r\nvoid WriteSparksOn();\r\nvoid WriteSparksOff();\r\nvoid WriteScorePotText(const char *p_text);\r\nvoid WriteTrickText(const char **pp_text, int numStrings);\r\nvoid WriteTrickTextPulse();\r\nvoid WriteTrickTextCountdown();\r\nvoid WriteTrickTextLanded();\r\nvoid WriteTrickTextBail();\r\nvoid WriteSetAtomicStates(uint32 id, uint32 mask);\r\nvoid WritePlayStream(uint32 checksum, Sfx::sVolume *p_volume, float pitch, int priority);\r\nvoid WriteStopStream(int channel);\r\nvoid WritePositionalStream(uint32 dummyId, uint32 streamNameChecksum, float dropoff, float volume, float pitch, int priority, int use_pos_info);\r\nvoid WritePositionalSoundEffect(uint32 dummyId, uint32 soundName, float volume, float pitch, float dropOffDist);\r\nvoid WriteSkaterSoundEffect(int whichArray, int surfaceFlag, const Mth::Vector &pos, \r\n\t\t\t\t\t\t\tfloat volPercent);\r\nvoid WritePlaySound(uint32 checksum, float volL, float volR, float pitch);\r\nvoid PrepareForReplayPlayback(bool hideObjects);\r\nbool RunningReplay();\r\nbool Paused();\r\nvoid AddReplayMemCardInfo(Script::CStruct *p_struct);\r\nvoid AddReplayMemCardSummaryInfo(Script::CStruct *p_struct);\r\nSGlobalStates *GetStartState();\r\n\r\n#else\r\n\r\n// These functions have platform specific versions.\r\n// On the GameCube for example, the buffer is in ARAM.\r\ninline void AllocateBuffer(){}\r\ninline void DeallocateBuffer(){}\r\n//bool BufferAllocated(){}\r\n//uint32 GetBufferSize(){}\r\ninline void ReadFromBuffer(uint8 *p_dest, int bufferOffset, int numBytes){}\r\ninline void WriteIntoBuffer(uint8 *p_source, int bufferOffset, int numBytes){}\r\ninline void FillBuffer(int bufferOffset, int numBytes, uint8 value){}\r\ninline void WriteReplayDataHeader(SReplayDataHeader *p_header){}\r\ninline void ReadReplayDataHeader(const SReplayDataHeader *p_header){}\r\ninline void CreateDummyFromSaveData(SSavedDummy *p_saved_dummy){}\r\n//CDummy *GetFirstStartStateDummy(){}\r\n\r\ninline void ClearBuffer(){}\r\n//uint8 *GetTempBuffer(){}\r\ninline void CreatePools(){}\r\ninline void RemovePools(){}\r\ninline void DeallocateReplayMemory(){}\r\ninline bool ScriptDeleteDummies( Script::CStruct *pParams, Script::CScript *pScript ){return true;}\r\ninline bool ScriptHideGameObjects( Script::CStruct *pParams, Script::CScript *pScript ){return true;}\r\ninline bool ScriptShowGameObjects( Script::CStruct *pParams, Script::CScript *pScript ){return true;}\r\ninline bool ScriptRunningReplay( Script::CStruct *pParams, Script::CScript *pScript ){return false;}\r\ninline bool ScriptPauseReplay( Script::CStruct *pParams, Script::CScript *pScript ){return true;}\r\ninline bool ScriptUnPauseReplay( Script::CStruct *pParams, Script::CScript *pScript ){return true;}\r\n\r\ninline bool ScriptAllocateReplayMemory(Script::CStruct *pParams, Script::CScript *pScript){return true;}\r\ninline bool ScriptDeallocateReplayMemory(Script::CStruct *pParams, Script::CScript *pScript){return true;}\r\ninline bool ScriptStartRecordingAfresh(Script::CStruct *pParams, Script::CScript *pScript){return true;}\r\n\r\ninline bool ScriptRememberLevelStructureNameForReplays(Script::CStruct *pParams, Script::CScript *pScript){return true;}\r\ninline void SetLevelStructureName(uint32 level_structure_name){}\r\ninline bool ScriptGetReplayLevelStructureName(Script::CStruct *pParams, Script::CScript *pScript){return true;}\r\n\r\ninline bool ScriptPlaybackReplay(Script::CStruct *pParams, Script::CScript *pScript){return true;}\r\n\r\ninline bool ScriptReplayRecordSimpleScriptCall(Script::CStruct *pParams, Script::CScript *pScript){return true;}\r\ninline bool ScriptRecordPanelMessage(Script::CStruct *pParams, Script::CScript *pScript){return true;}\r\ninline bool ScriptSwitchToReplayRecordMode( Script::CStruct *pParams, Script::CScript *pScript ){return true;}\r\ninline bool ScriptSwitchToReplayIdleMode( Script::CStruct *pParams, Script::CScript *pScript ){return true;}\r\ninline bool ScriptClearTrickAndScoreText(Script::CStruct *pParams, Script::CScript *pScript){return true;}\r\n\r\ninline void WritePadVibration(int actuator, int percent){}\r\ninline void WritePauseSkater(){}\r\ninline void WriteUnPauseSkater(){}\r\ninline void WriteScreenFlash(int viewport, Image::RGBA from, Image::RGBA to, float duration, float z, uint32 flags){}\r\ninline void WriteShatter(uint32 sectorName, bool on){}\r\ninline void WriteShatterParams(Mth::Vector& velocity, float area_test, float velocity_variance, float spread_factor, float lifetime, float bounce, float bounce_amplitude){}\r\ninline void WriteTextureSplat(Mth::Vector& splat_start, Mth::Vector& splat_end, float size, float lifetime, const char *p_texture_name, uint32 trail ){}\r\ninline void WriteSectorActiveStatus(uint32 sectorName, bool active){}\r\ninline void WriteSectorVisibleStatus(uint32 sectorName, bool visible){}\r\ninline void WriteManualMeter(bool state, float value){}\r\ninline void WriteBalanceMeter(bool state, float value){}\r\ninline void WriteSparksOn(){}\r\ninline void WriteSparksOff(){}\r\ninline void WriteScorePotText(const char *p_text){}\r\ninline void WriteTrickText(const char **pp_text, int numStrings){}\r\ninline void WriteTrickTextPulse(){}\r\ninline void WriteTrickTextCountdown(){}\r\ninline void WriteTrickTextLanded(){}\r\ninline void WriteTrickTextBail(){}\r\ninline void WriteSetAtomicStates(uint32 id, uint32 mask){}\r\ninline void WritePlayStream(uint32 checksum, Sfx::sVolume *p_volume, float pitch, int priority){}\r\ninline void WriteStopStream(int channel){}\r\ninline void WritePositionalStream(uint32 dummyId, uint32 streamNameChecksum, float dropoff, float volume, float pitch, int priority, int use_pos_info){}\r\ninline void WritePositionalSoundEffect(uint32 dummyId, uint32 soundName, float volume, float pitch, float dropOffDist){}\r\ninline void WriteSkaterSoundEffect(int whichArray, int surfaceFlag, const Mth::Vector &pos, \r\n\t\t\t\t\t\t\tfloat volPercent){}\r\ninline void WritePlaySound(uint32 checksum, float volL, float volR, float pitch){}\r\ninline void PrepareForReplayPlayback(bool hideObjects){}\r\ninline bool RunningReplay(){return false;}\r\ninline bool Paused(){return false;}\r\ninline void AddReplayMemCardInfo(Script::CStruct *p_struct){}\r\ninline void AddReplayMemCardSummaryInfo(Script::CStruct *p_struct){}\r\n//SGlobalStates *GetStartState(){}\r\n#endif\r\n\r\n} // namespace Replay\r\n\r\n#endif\t// __SYS_REPLAY_H\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/SIO/NGPS/p_keyboard.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSYS (SYS_) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tkeyboard.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/08/2001\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tUSB Keyboard interface\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <core/task.h>\r\n\r\n#include <sys/sio/keyboard.h>\r\n#include <sys/config/config.h>\r\n\r\n#include <gel/mainloop.h>\r\n\r\n#include <eekernel.h>\r\n#include <eeregs.h>\r\n#include <stdio.h>\r\n#include <sifdev.h>\r\n#include <sifrpc.h>\r\n\r\n#include <libusbkb.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace SIO\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define USBKEYBD_ARG \"keybd=8\\0debug=1\"\r\n\r\nstatic\tunsigned char *s_old_status = NULL;\r\nstatic\tUSBKBINFO_t\ts_info;\r\nstatic\tu_char \t\ts_location[7];\r\nstatic\tUSBKBDATA_t s_kdata;\r\nstatic\tint\t\t\ts_max_connect;\r\nstatic\tchar\t\ts_makes[32];\r\nstatic\tint\t\t\ts_num_makes;\r\nstatic  bool\t\ts_active = true;\r\nstatic  bool\t\ts_enabled = true;\r\n\r\nstatic \tTsk::Task< int >*\t\ts_kb_read_logic_task;\r\n\r\nenum\r\n{\r\n\tvKEYCODE_F1\t\t= \t0x803A,\r\n\tvKEYCODE_F2\t\t= \t0x803B,\r\n\tvKEYCODE_F3\t\t= \t0x803C,\r\n\tvKEYCODE_F4\t\t= \t0x803D,\r\n\tvKEYCODE_RIGHT\t=\t0x804F,\r\n\tvKEYCODE_LEFT\t=\t0x8050,\r\n\tvKEYCODE_DOWN\t=\t0x8051,\r\n\tvKEYCODE_UP\t\t=\t0x8052,\r\n\tvKEYCODE_ESC\t= \t0x8029,\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic void s_init_newkeyboard( int i );\r\nstatic int s_capture_input( int i, char* makes );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid\tkb_read_logic_code ( const Tsk::Task< int >& task )\r\n{\r\n\tint i, result;\r\n\r\n\tif (!s_active || !s_enabled)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n    \r\n\ts_num_makes = 0;\r\n\r\n    result = sceUsbKbGetInfo( &s_info );\r\n\tif( result != USBKB_OK ) \r\n\t{\r\n\t\tDbg_Printf( \"Error%d : sceUsbKbGetInfo\\n\", result );\r\n\t\treturn;\r\n\t}\r\n\tsceUsbKbSync( USBKB_WAIT, &result );\r\n\tif( result != USBKB_OK ) \r\n\t{\r\n\t\tDbg_Printf( \"Error%d : sceUsbKbSync\\n\", result );\r\n\t\treturn;\r\n\t}\r\n  \r\n    // reading keyboard\r\n\tfor( i = 0; i < s_max_connect; i++)  \r\n\t{\r\n\t\tif( s_info.status[i] == 0 ) \r\n\t\t{ \r\n\t\t\tcontinue; \r\n\t\t}  // not connected\r\n\r\n\t\tif( s_old_status[i] == 0 ) \r\n\t\t{\r\n\t\t\tDbg_Printf( \"New keyboard %d is connected\\n\", i );\r\n\t\t\ts_init_newkeyboard(i);\r\n\t\t}\r\n\r\n\t\tresult = sceUsbKbRead( i, &s_kdata );\r\n\t\tif( result != USBKB_OK ) \r\n\t\t{\r\n\t\t\tDbg_Printf( \"Error%d : sceUsbKbRead\\n\", result );\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tsceUsbKbSync( USBKB_WAIT, &result );\r\n\t\tif( result != USBKB_OK ) \r\n\t\t{\r\n\t\t\tDbg_Printf( \"Error%d : sceUsbKbSync\\n\",result);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif( s_kdata.len == 0 ) \r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tresult = sceUsbKbGetLocation( i, s_location );\r\n\t\tif( result != USBKB_OK ) \r\n\t\t{\r\n\t\t\tDbg_Printf( \"Error%d : sceUsbKbGetLocation\\n\", result );\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\tsceUsbKbSync( USBKB_WAIT, &result );\r\n\t\tif( result != USBKB_OK ) \r\n\t\t{\r\n\t\t\tDbg_Printf( \"Error%d : sceUsbKbSync\\n\", result );\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t\r\n\t\ts_num_makes = s_capture_input( i, s_makes );\r\n\t}\r\n  \r\n\tfor( i = 0; i < s_max_connect; i++ ) \r\n\t{ \r\n\t\ts_old_status[i] = s_info.status[i]; \r\n\t}\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint KeyboardInit(void)\r\n{\r\n\t\r\n\t\r\n\tint result;\r\n    char *option = USBKEYBD_ARG;\r\n\tint i;\r\n\tMlp::Manager * mlp_man = Mlp::Manager::Instance();\r\n\t\r\n\r\n\t//sceSifInitRpc(0);\r\n\t\r\n\tif (Config::CD())\r\n\t{\r\n\t\tchar  path[128];\r\n\t\tsprintf(path,\"cdrom0:\\\\%sIOP\\\\USBKB.IRX\",Config::GetDirectory()); \r\n\r\n\t\tresult = sceSifLoadModule(\r\n\t\t\t\t   path,\r\n\t\t\t\t\tsizeof( USBKEYBD_ARG ) + 1, option );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tresult = sceSifLoadModule(\r\n\t\t\t\t   \"host0:IOPModules/usbkb.irx\",\r\n\t\t\t\t\tsizeof( USBKEYBD_ARG ) + 1, option );\r\n\t}\t\t\t\t\r\n\t\r\n\tif( result < 0 )\r\n    {\r\n        Dbg_MsgAssert( 0,( \"EE:Can't load module usbkb.irx\\n\" ));\r\n\t\treturn -1;\r\n\t}\r\n\r\n    result = sceUsbKbInit( &s_max_connect );\r\n    if( result == USBKB_NG ) \r\n\t{\r\n\t\tDbg_Printf( \"Initialize error\\n\" );\r\n\t\treturn -1;\r\n\t}\r\n\r\n    s_old_status = new unsigned char[ s_max_connect ];\r\n    for( i = 0; i < s_max_connect; i++ ) \r\n\t{ \r\n\t\ts_old_status[i] = 0; \r\n\t}\r\n\r\n\tint arg;\r\n\t// Just send an int because Tsk::Task is a template and needs some sort of\r\n\t// specific data type. So I just chose int and pass an int even though I don't use it\r\n\ts_kb_read_logic_task = new Tsk::Task< int > ( kb_read_logic_code, arg );\r\n\tmlp_man->AddSystemTask( *s_kb_read_logic_task );\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint KeyboardDeinit(void)\r\n{\r\n\tdelete s_kb_read_logic_task;\r\n\tdelete s_old_status;\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint KeyboardRead( char* makes )\r\n{\r\n\tint i;\r\n\tfor( i = 0; i < s_num_makes; i++ )\r\n\t{\r\n\t\tmakes[i] = s_makes[i];\r\n\t}\r\n\r\n\treturn s_num_makes;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid KeyboardClear( void )\r\n{\r\n\ts_num_makes = 0;\r\n}\r\n\r\n\r\nvoid SetKeyboardActive(bool active)\r\n{\r\n\ts_active = active;\r\n}\r\n\r\nvoid EnableKeyboard( bool enable )\r\n{\r\n\ts_enabled = enable;\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic void s_init_newkeyboard( int i )\r\n{       \r\n\tint result;\r\n\t\r\n\tresult = sceUsbKbSetLEDStatus( i, USBKB_LED_NUM_LOCK );\r\n\tif( result != USBKB_OK ) \r\n\t{\r\n\t\tDbg_Printf( \"Error%d : sceUsbKbSetLEDStatus\\n\", result );\r\n\t} \r\n\telse \r\n\t{\r\n\t\tsceUsbKbSync(USBKB_WAIT,&result);\r\n\t\tif( result != USBKB_OK ) \r\n\t\t{\r\n\t\t\tDbg_Printf( \"Error%d : sceUsbKbSync\\n\", result );\r\n\t\t}\r\n\t}\r\n\t\r\n\tresult = sceUsbKbSetLEDMode( i, USBKB_LED_MODE_AUTO1 );\r\n\tif( result != USBKB_OK ) \r\n\t{\r\n\t\tDbg_Printf( \"Error%d : sceUsbKbSetLEDMode\\n\", result );\r\n\t} \r\n\telse \r\n\t{\r\n\t\tsceUsbKbSync( USBKB_WAIT, &result );\r\n\t\tif( result != USBKB_OK ) \r\n\t\t{\r\n\t\t\tDbg_Printf( \"Error%d : sceUsbKbSync\\n\", result );\r\n\t\t}\r\n\t}\r\n\t\r\n\tsceUsbKbSetRepeat( i, 30, 2 );\r\n\tsceUsbKbSetCodeType( i, USBKB_CODETYPE_ASCII );\r\n\tsceUsbKbSetArrangement( i, USBKB_ARRANGEMENT_101 );//USBKB_ARRANGEMENT_106 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nstatic int s_capture_input( int i, char* makes )\r\n{\r\n\tu_short kcode;\r\n\tint j, index;\r\n\t\r\n\t//Dbg_Printf( \"usbkeybd%d : \", i );\r\n\t\r\n\t//Dbg_Printf( \"port=\" );\r\n\t//for( k = 0; k < 7 && s_location[k] != 0; k++ )\r\n\t//{\r\n\t\t//Dbg_Printf( \"%s%d\", ((k)? \",\": \"\" ), s_location[k] );\r\n\t//}\r\n\t  \r\n\t\r\n\t//Dbg_Printf( \" : LED[%02X] \", s_kdata.led );\r\n\t\r\n\t//Dbg_Printf( \"MKEY[%02X] \", s_kdata.mkey );\r\n\t\r\n\t//Dbg_Printf( \"KEY[\" );\r\n\t\r\n\tindex = 0;\r\n\tfor( j=0; j < s_kdata.len; j++ ) \r\n\t{\r\n\t\tkcode = s_kdata.keycode[j];\r\n\t\tif( kcode & USBKB_RAWDAT ) \r\n\t\t{\r\n\t\t\t//Dbg_Printf( \"%04X \", kcode );\r\n\t\t\tswitch( kcode )\r\n\t\t\t{   \r\n\t\t\t\tcase vKEYCODE_F1:\r\n\t\t\t\t\tmakes[index++] = vKB_F1;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vKEYCODE_F2:\r\n\t\t\t\t\tmakes[index++] = vKB_F2;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vKEYCODE_F3:\r\n\t\t\t\t\tmakes[index++] = vKB_F3;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vKEYCODE_F4:\r\n\t\t\t\t\tmakes[index++] = vKB_F4;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vKEYCODE_RIGHT:\r\n\t\t\t\t\tmakes[index++] = vKB_RIGHT;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vKEYCODE_LEFT:\r\n\t\t\t\t\tmakes[index++] = vKB_LEFT;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vKEYCODE_DOWN:\r\n\t\t\t\t\tmakes[index++] = vKB_DOWN;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vKEYCODE_UP:\r\n\t\t\t\t\tmakes[index++] = vKB_UP;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vKEYCODE_ESC:\r\n\t\t\t\t\tmakes[index++] = vKB_ESCAPE;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif( kcode & USBKB_KEYPAD ) \r\n\t\t{\r\n\t\t\t// 10 key\r\n\t\t\tif((kcode & 0x00ff) == '\\n')\r\n\t\t\t{ \r\n\t\t\t\t//Dbg_Printf( \"(\\\\n)\" ); \r\n\t\t\t\tmakes[index++] = vKB_ENTER;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t//Dbg_Printf( \"(%c) \", kcode & ~USBKB_KEYPAD );\r\n\t\t\tmakes[index++] = kcode & ~USBKB_KEYPAD;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t// Normal key\r\n\t\tif((kcode & 0x00ff) == '\\0' ) \r\n\t\t{ \r\n\t\t\t//Dbg_Printf( \"\\'\\\\0\\'\" ); \r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif((kcode & 0x00ff) == '\\n' ) \r\n\t\t{ \r\n\t\t\t//Dbg_Printf( \"\\'\\\\n\\'\" ); \r\n\t\t\tmakes[index++] = vKB_ENTER;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif((kcode & 0x00ff) == '\\t' ) \r\n\t\t{ \r\n\t\t\t//Dbg_Printf( \"\\'\\\\t\\'\" ); \r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif((kcode & 0x00ff) == '\\b' ) \r\n\t\t{ \r\n\t\t\t//Dbg_Printf( \"\\'\\\\b\\'\" ); \r\n\t\t\tmakes[index++] = vKB_BACKSPACE;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t//Dbg_Printf( \"\\'%c\\' \", kcode );\r\n\t\tmakes[index++] = kcode;\r\n\t}\r\n\t//Dbg_Printf( \"]\\n\" ); \r\n\r\n\treturn index;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace SIO\r\n"
  },
  {
    "path": "Code/Sys/SIO/XBox/p_keyboard.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSYS (SYS_) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tkeyboard.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/08/2001\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tUSB Keyboard interface\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <sys/sio/keyboard.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace SIO\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint KeyboardInit(void)\r\n{\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint KeyboardDeinit(void)\r\n{\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint KeyboardRead( char* makes )\r\n{\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid KeyboardClear( void )\r\n{\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace SIO\r\n"
  },
  {
    "path": "Code/Sys/SIO/XBox/p_siodev.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSYS (SYS_) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsiodev.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/26/2000\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGeneric input device\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n#include <stdlib.h>\r\n#include <string.h>\r\n         \r\n#include <core/defines.h>\r\n#include <sys/sioman.h>\r\n#include <sys/mem/memman.h>\r\n#include <sk/parkeditor2/parked.h>\r\n#include <gel/scripting/script.h>\r\n#include <gfx/2d/screenelemman.h>\r\n\r\n//#include <libpad.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace SIO\r\n{\r\n\r\n\r\n// Maps Xbox thumbstick values in the range [-32767, 32767] to PS2 thumstick values in the range [0, 255].\r\n#define XboxThumbToPS2Thumb( v )\t(( v + 32767 ) / 256 )\r\n\r\n// K: Index of the last pad to have a button pressed. Used when a level is chosen in the skateshop.\r\n// The pad used to control the player is whatever pad was used to choose the level.\r\nint gLastPadPressed=0;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic void set_xbox_actuators( HANDLE handle, unsigned short left_motor, unsigned short right_motor )\r\n{\r\n\t// Want this to be static since otherwise it would potentially go out of scope and be written to.\r\n\tstatic XINPUT_FEEDBACK input_feedback[32];\r\n\tstatic int next_index\t\t\t= 0;\r\n\t\r\n\t// The Ps2 left motor is the high frequency motor, the right motor is a simple on/off low frequency motor.\r\n\t// On the Xbox it is the reverse (although the left motor has more control than simple on/off).\r\n\t\r\n\tinput_feedback[next_index].Header.dwStatus\t\t\t= 0;\r\n\tinput_feedback[next_index].Header.hEvent\t\t\t= NULL;\r\n\tinput_feedback[next_index].Rumble.wLeftMotorSpeed\t= right_motor;\r\n\tinput_feedback[next_index].Rumble.wRightMotorSpeed\t= left_motor;\r\n\r\n\tDWORD status = XInputSetState( handle, &input_feedback[next_index] );\r\n\tDbg_Assert(( status == ERROR_IO_PENDING ) || ( status == ERROR_SUCCESS ) || ( status == ERROR_DEVICE_NOT_CONNECTED ));\r\n\r\n\t// Cycle array member.\r\n\tif( ++next_index >= 32 )\r\n\t{\r\n\t\tnext_index = 0;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n    \r\nvoid Device::process( void )\r\n{\r\n\tm_plugged_in = false;\r\n\r\n    switch( m_state )\r\n    {\r\n    case vIDLE:\r\n        break;\r\n\r\n    case vBUSY:\r\n        wait();\r\n        break;\r\n\r\n    case vACQUIRING:\r\n        acquisition_pending();\r\n        break;\r\n\r\n    case vACQUIRED:\r\n        read_data();\r\n        break;\r\n\r\n    default:\r\n        break;\r\n\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::wait( void )\r\n{\r\n    Dbg_MsgAssert(( m_next_state >= 0 ) && ( m_next_state <= vNUM_STATES ),( \"No next state set for wait state\" ));\r\n\r\n\tif ( get_status() != vNOTREADY )\r\n\t{\r\n\t\tm_state = m_next_state;\r\n\t\tm_next_state = vIDLE;\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::read_data ( void )\r\n{\r\n\tXINPUT_STATE\txis;\r\n\tHRESULT\t\t\thr;\r\n\r\n\tm_plugged_in = false;\r\n\r\n\tif( m_data.m_handle == NULL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\thr = XInputGetState( m_data.m_handle, &xis );\r\n\tif( hr != ERROR_SUCCESS )\r\n\t{\r\n\t\tXInputClose( m_data.m_handle );\r\n\t\tm_data.m_handle\t= NULL;\r\n\t\tm_data.m_valid\t= false;\r\n\t\tUnacquire();\r\n\t\tAcquire();\r\n\t\treturn;\r\n\t}\r\n\r\n\tm_data.m_valid\t= true;\r\n\tm_plugged_in\t= true;\r\n\r\n\t// Convert this data back into PS2-style 'raw' data for a DUALSHOCK2.\r\n\tm_data.m_control_data[0] = 0;\t\t\t\t\t\t// 'Valid' info flag.\r\n\tm_data.m_control_data[1] = ( 0x07 << 4 ) | 16;\t\t// DUALSHOCK2 id + data length.\r\n\r\n\tm_data.m_control_data[2] = 0xFF;\t\t\t\t\t// Turn off all buttons by default.\r\n\tm_data.m_control_data[3] = 0xFF;\t\t\t\t\t// Turn off all buttons by default.\r\n\r\n\tm_data.m_control_data[2] ^= ( xis.Gamepad.wButtons & XINPUT_GAMEPAD_START ) ? ( 1 << 3 ) : 0;\t\t// XBox 'Start' = PS2 'Start'.\r\n\tm_data.m_control_data[2] ^= ( xis.Gamepad.wButtons & XINPUT_GAMEPAD_BACK ) ? ( 1 << 0 ) : 0;\t\t// XBox 'Back' = PS2 'Select'.\r\n\tm_data.m_control_data[2] ^= ( xis.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB ) ? ( 1 << 1 ) : 0;\t// Xbox 'Left Stick Button' = PS2 'Left Stick Button'.\r\n\tm_data.m_control_data[2] ^= ( xis.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB ) ? ( 1 << 2 ): 0;\t// Xbox 'Right Stick Button' = PS2 'Right Stick Button'.\r\n\r\n\t// TRC 1.4-1-26 to eliminate crosstalk must disregard values below 0x20.\r\n\tm_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_Y] >= 0x20 ) ? ( 1 << 4 ) : 0;\t// XBox 'Y' = PS2 'Triangle'.\r\n\tm_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_B] >= 0x20 ) ? ( 1 << 5 ) : 0;\t// XBox 'B' = PS2 'Circle'.\r\n\tm_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_A] >= 0x20 ) ? ( 1 << 6 ) : 0;\t// XBox 'A' = PS2 'X'.\r\n\tm_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_X] >= 0x20 ) ? ( 1 << 7 ) : 0;\t// XBox 'X' = PS2 'Square'.\r\n\t\t\r\n\tif( Ed::CParkEditor::Instance()->EditingCustomPark())\r\n\t{\r\n\t\t// In the Park Editor, black and white buttons are L1 and L2, triggers are R1 and R2... unless the gap name keyboard is active :(\r\n\t\tbool\t\t\t\t\t\t\tkeyboard_active\t\t= false;\r\n\t\tFront::CScreenElementManager\t*p_screen_elem_man\t= Front::CScreenElementManager::Instance();\r\n\t\tif( p_screen_elem_man )\r\n\t\t{\r\n\t\t\tFront::CScreenElement\t\t*p_keyboard\t\t\t= p_screen_elem_man->GetElement( Script::GenerateCRC( \"keyboard_anchor\" ) , Front::CScreenElementManager::DONT_ASSERT );\r\n\t\t\tif( p_keyboard )\r\n\t\t\t{\r\n\t\t\t\tkeyboard_active\t= true;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif( keyboard_active\t)\r\n\t\t{\r\n\t\t\tm_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] > 0x20 ) ? ( 1 << 1 ) : 0;\t\t// XBox  'Right Trigger'= PS2 'R2'.\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] > 0x20 ) ? ( 1 << 2 ) : 0;\t\t// XBox  'Right Trigger'= PS2 'L1'.\r\n\t\t}\r\n\t\t\r\n\t\tm_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER] > 0x20 ) ? ( 1 << 0 ) : 0;\t\t\t// XBox 'Left Trigger' = PS2 'L2'.\r\n\t\t// New! Black and white are no longer mapped to R2 and L2 but are treated as seperate buttons\r\n\t\t//m_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_WHITE] > 0x20 ) ? ( 1 << 1 ) : 0;\t\t\t\t\t// XBox 'White' = PS2 'R2'.\r\n\t\t//m_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_BLACK] > 0x20 ) ? ( 1 << 3 ) : 0;\t\t\t\t\t// XBox 'Black' = PS2 'R1'.\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// New! Black and white are no longer mapped to R2 and L2 but are treated as seperate buttons\r\n\r\n\t\t// Outside of the Park Editor, either black or white buttons act as L1 and R1...\r\n\t\t//m_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_WHITE] > 0x20 ) ? (( 1 << 2 ) | ( 1 << 3 )) : 0;\t// XBox 'White' = PS2 'L1' + PS2 'R1'.\r\n//\t\tm_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_BLACK] > 0x20 ) ? (( 1 << 2 ) | ( 1 << 3 )) : 0;\t// XBox 'Black'= PS2 'L1' + PS2 'R1'.\r\n\t\t//m_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_BLACK] > 0x20 ) ? (( 1 << 0 ) | ( 1 << 1 )) : 0;\t// XBox 'Black'= PS2 'L2' + PS2 'R2'.\r\n\t\t\r\n\t\t// ...triggers function as both L1/L2 and R1/R2.\t\t\r\n\t\tm_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER] > 128 ) ? ( 1 << 0 ) : 0;\t\t\t\t// XBox 'Left Trigger pressed down > halfway' = PS2 'L2'.\r\n\t\tm_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] > 128 ) ? ( 1 << 1 ) : 0;\t\t\t// XBox 'Right Trigger pressed down > halfway' = PS2 'R2'.\r\n\r\n\t\tm_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER] > 0x20 ) ? ( 1 << 2 ) : 0;\t\t\t\t// XBox 'Left Trigger' = PS2 'L1'.\r\n\t\tm_data.m_control_data[3] ^= ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] > 0x20 ) ? ( 1 << 3 ) : 0;\t\t\t\t// XBox 'Right Trigger' = PS2 'R1'.\r\n\t}\r\n\r\n\t// Make analog buttons full depression if pressed.\r\n\t// Xbox analog buttons return analog value in range [0, 255].\r\n\tm_data.m_control_data[12] = ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_Y] > 0x20 ) ? xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_Y] : 0;\t\t\t\t\t\t\t// XBox 'Y' = PS2 Analog 'Triangle'.\r\n\tm_data.m_control_data[13] = ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_B] > 0x20 ) ? xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_B] : 0;\t\t\t\t\t\t\t// XBox 'B' = PS2 Analog 'Circle'.\r\n\tm_data.m_control_data[14] = ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_A] > 0x20 ) ? xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_A] : 0;\t\t\t\t\t\t\t// XBox 'A' = PS2 Analog 'X'.\r\n\tm_data.m_control_data[15] = ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_X] > 0x20 ) ? xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_X] : 0;\t\t\t\t\t\t\t// XBox 'X' = PS2 'Square'.\r\n\tm_data.m_control_data[16] = ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER] > 0x20 ) ? xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER] : 0;\t// XBox 'Left Trigger' = PS2 Analog 'L1'.\r\n\tm_data.m_control_data[17] = ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] > 0x20 ) ? xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] : 0;\t// XBox 'Right Trigger' = PS2 Analog 'R1'.\r\n\t// Black and white are no longer mapped to R2 and L2, but are treated as separate buttons.\r\n\t//m_data.m_control_data[18] = ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_WHITE] > 0x20 ) ? xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_WHITE] : 0;\t\t\t\t\t// XBox 'White' = PS2 Analog 'L2'.\r\n\t//m_data.m_control_data[19] = ( xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_BLACK] > 0x20 ) ? xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_BLACK] : 0;\t\t\t\t\t// XBox 'Black' = PS2 Analog 'R2'.\r\n\tm_data.m_control_data[18]=0;\r\n\tm_data.m_control_data[19]=0;\r\n\r\n\t// Zero out the d-pad pressure values.\r\n\tm_data.m_control_data[8]\t= 0x00;\r\n\tm_data.m_control_data[9]\t= 0x00;\r\n\tm_data.m_control_data[10]\t= 0x00;\r\n\tm_data.m_control_data[11]\t= 0x00;\r\n\r\n\t// Handle 8 position d-pad.\r\n\tm_data.m_control_data[2] ^= ( xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ) ? ( 1 << 4 ) : 0;\t\t// XBox 'DPad Up' = PS2 'DPad Up'.\r\n\tm_data.m_control_data[10] = ( xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ) ? 0xFF : 0;\t\t\t// XBox 'DPad Up' = PS2 'DPad Up'.\r\n\tm_data.m_control_data[2] ^= ( xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) ? ( 1 << 5 ) : 0;\t// XBox 'DPad Right' = PS2 'DPad Right'.\r\n\tm_data.m_control_data[8] = ( xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) ? 0xFF : 0;\t\t\t// XBox 'DPad Right' = PS2 'DPad Right'.\r\n\tm_data.m_control_data[2] ^= ( xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) ? ( 1 << 6 ) : 0;\t// XBox 'DPad Down' = PS2 'DPad Down'.\r\n\tm_data.m_control_data[11] = ( xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) ? 0xFF : 0;\t\t\t// XBox 'DPad Down' = PS2 'DPad Down'.\r\n\tm_data.m_control_data[2] ^= ( xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) ? ( 1 << 7 ) : 0;\t// XBox 'DPad Left' = PS2 'DPad Left'.\r\n\tm_data.m_control_data[9] = ( xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) ? 0xFF : 0;\t\t\t// XBox 'DPad Left' = PS2 'DPad Left'.\r\n\r\n\t// Xbox thumbsticks return analog value in range [-32767, 32767].\r\n\tm_data.m_control_data[4] = XboxThumbToPS2Thumb( xis.Gamepad.sThumbRX );\t// Analog stick right (X direction).\r\n\tm_data.m_control_data[5] = XboxThumbToPS2Thumb( -xis.Gamepad.sThumbRY );\t// Analog stick right (Y direction).\r\n\tm_data.m_control_data[6] = XboxThumbToPS2Thumb( xis.Gamepad.sThumbLX );\t// Analog stick left (X direction).\r\n\tm_data.m_control_data[7] = XboxThumbToPS2Thumb( -xis.Gamepad.sThumbLY );\t// Analog stick left (Y direction).\r\n\r\n\t// K: Use m_control_data[20] to store the state of the black & white buttons.\r\n\tm_data.m_control_data[20]=0;\r\n\tif (xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_BLACK] > 0x20)\r\n\t{\r\n\t\tm_data.m_control_data[20] |= (1<<0);\r\n\t}\t\r\n\tif (xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_WHITE] > 0x20)\r\n\t{\r\n\t\tm_data.m_control_data[20] |= (1<<1);\r\n\t}\t\r\n\r\n\t\r\n\tuint32 buttons = 0xFFFF ^ (( m_data.m_control_data[2] << 8 ) | m_data.m_control_data[3] );\r\n\r\n\t// Skate3 specific code, removed for now.\r\n\tif( buttons )\r\n\t{\r\n\t\tm_pressed = true;\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_pressed = false;\r\n\t}\t\r\n\t\t\r\n\r\n\tif(( xis.Gamepad.wButtons & XINPUT_GAMEPAD_START) || xis.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_A] >= 0x20 )\r\n\t{\r\n\t\tm_start_or_a_pressed = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_start_or_a_pressed = false;\r\n\t}\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Device::IsPluggedIn( void )\r\n{\r\n\treturn m_plugged_in;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::acquisition_pending( void )\r\n{\r\n    int status;\r\n\r\n\tif( m_data.m_handle == NULL )\r\n\t{\r\n\t\t++m_unplugged_counter;\r\n\r\n\t\t// Retry to connect every second or so.\r\n\t\tif(( m_unplugged_counter & 0x3F ) == m_unplugged_retry )\r\n\t\t{\r\n\t\t\tm_data.m_handle = XInputOpen( XDEVICE_TYPE_GAMEPAD, m_data.m_port, XDEVICE_NO_SLOT, NULL );\r\n\t\t}\r\n\t\t\r\n\t\tif( m_data.m_handle == NULL )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n    status = get_status();\r\n                        \r\n    if(( status == vCONNECTED ) || ( status == vREADY ))\r\n    {\r\n        // Sucessful.  Now query the controller for capabilities.\r\n\t\tm_unplugged_counter = 0;\r\n        query_capabilities();\r\n    }\r\n        \r\n\t// failed to acquire controller\r\n\t// stay in this state and continue to try to acquire it or prompt the user if it is mandatory\r\n\t// that they have a controller in   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::query_capabilities( void )\r\n{   \r\n\t// Currently assumes standard XBox controller.\r\n    int id = vANALOG_CTRL;\r\n    \r\n    m_data.m_type = id;\r\n\r\n\tswitch( id )\r\n\t{   \r\n\t\tcase vANALOG_CTRL:\r\n\t\t{\r\n\t\t\tm_data.m_caps.SetMask( mANALOG_BUTTONS );\r\n\r\n\t\t\tm_data.m_num_actuators\t\t= 2;\r\n\t\t\tm_data.m_actuator_max[0]\t= 255;\r\n\t\t\tm_data.m_actuator_max[1]\t= 255;\r\n\t\t\tm_data.m_caps.SetMask( mACTUATORS );\r\n\r\n\t\t\tm_state = vBUSY;\r\n\t\t\tm_next_state = vACQUIRED;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_Message( \"Detected Controller of unknown type in %d:%d\", m_data.m_port, m_data.m_slot );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n    m_state = vACQUIRED;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Device::get_status( void )\r\n{\r\n\tif( m_data.m_handle )\r\n\t{\r\n\t\tXINPUT_STATE state;\r\n\t\tif( XInputGetState( m_data.m_handle, &state ) == ERROR_SUCCESS )\r\n\t\t{\r\n\t\t\treturn vREADY;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Could do more checking here of the return value.\r\n\t\t\treturn vDISCONNECTED;\r\n\t\t}\r\n\t}\r\n\r\n\treturn vDISCONNECTED;\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDevice::Device ( int index, int port, int slot )\r\n{\r\n\tm_node = new Lst::Node< Device > ( this );\r\n\tDbg_AssertType ( m_node, Lst::Node< Device > );\r\n\r\n    Dbg_Assert( port < vMAX_PORT );\r\n    Dbg_Assert( slot < vMAX_SLOT );\r\n\r\n    m_state = vIDLE;\r\n    m_next_state = vIDLE;\r\n    m_index = index;\r\n\r\n    // Initialize device\r\n    m_data.m_port = port;\r\n    m_data.m_slot = slot;\r\n    m_data.m_caps.ClearAll();\r\n    m_data.m_num_actuators = 0;\r\n    m_data.m_valid = false;\r\n\r\n    memset( m_data.m_actuator_direct, 0, ACTUATOR_BUFFER_LENGTH );\r\n    memset( m_data.m_actuator_align, 0xFF, ACTUATOR_BUFFER_LENGTH );\r\n    m_data.m_actuator_align[0] = 0;\r\n    m_data.m_actuator_align[1] = 1;\r\n\r\n    memset( m_data.m_control_data, 0, CTRL_BUFFER_LENGTH );\r\n//\tm_data.m_prealbuffer = Mem::Malloc( scePadDmaBufferMax * sizeof( uint128) + 63 );\r\n\tm_data.m_dma_buff =  (unsigned char*)((((uint32)m_data.m_prealbuffer)+63)&~63);\r\n\t\r\n\t// Random retry for unplugged controllers.\r\n\tm_unplugged_retry = rand() & 0x3F;\r\n\r\n//\tmemset( m_data.m_dma_buff, 0, sizeof( uint128 ) * scePadDmaBufferMax );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nDevice::~Device ( void )\r\n{\r\n\tDbg_AssertType ( m_node, Lst::Node< Device > );\r\n//\tMem::Free( m_data.m_prealbuffer );\r\n\r\n\tXInputClose( m_data.m_handle );\r\n\r\n\tdelete m_node;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::Acquire( void )\r\n{\r\n    Dbg_Message( \"Acquiring controller port %d slot %d\\n\", m_data.m_port, m_data.m_slot );\r\n\r\n    if( m_state == vIDLE )\r\n    {\r\n\t\t// Acquire device handle.\r\n\t\tm_data.m_handle = XInputOpen( XDEVICE_TYPE_GAMEPAD, m_data.m_port, XDEVICE_NO_SLOT, NULL );\r\n\r\n//\t\tif( m_data.m_handle )\r\n\t\t{\r\n\t\t\t// Store capabilites of the device\r\n//\t\t\tXINPUT_CAPABILITIES caps;\r\n//\t\t\tXInputGetCapabilities( m_data.m_handle, &caps );\r\n\r\n//\t\t\tmemset( m_data.m_control_data, 0, CTRL_BUFFER_LENGTH );\r\n\t\t\tm_data.m_valid = false;\r\n\t\t\tm_state = vACQUIRING;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tDbg_Warning( \"failed to open controller port %d slot %d\\n\", m_data.m_port, m_data.m_slot );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid Device::Unacquire ( void )\r\n{\r\n    Dbg_Message( \"Unacquiring controller port %d slot %d\\n\", m_data.m_port, m_data.m_slot );\r\n\r\n    if( m_state == vACQUIRED )\r\n    {\r\n\t\tm_data.m_handle = NULL;\r\n    }\r\n\r\n    m_state = vIDLE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Device::ActivateActuator( int act_num, int percent )\r\n{\r\n\t// Do nothing if the actuators are disabled.\r\n\tif( m_data.m_actuators_disabled )\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n    \r\n    // First, make sure we're in a ready state and our controller has actuators\r\n\tread_data();\r\n    if(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n    {\r\n        if(( act_num >= 0 ) && ( act_num < m_data.m_num_actuators ))\r\n        {\r\n\t\t\tunsigned short left_motor, right_motor;           \r\n\t\t\tfloat act_strength\t\t\t\t\t\t= ((float)percent * m_data.m_actuator_max[act_num] ) * 0.01f;\r\n\t\t\tm_data.m_actuator_direct[act_num]\t\t= (unsigned char)act_strength;\r\n\r\n\t\t\t// Scale the values from [0,255] to [0,65535].\r\n\t\t\tif( act_num == 0 )\r\n\t\t\t{\r\n\t\t\t\tleft_motor\t= (unsigned short)( act_strength * 256.0f );\r\n\t\t\t\tright_motor\t= (unsigned short)m_data.m_actuator_direct[1] * 256;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tleft_motor\t= (unsigned short)m_data.m_actuator_direct[0] * 256;\r\n\t\t\t\tright_motor\t= (unsigned short)( act_strength * 256.0f );\r\n\t\t\t}\r\n\r\n\t\t\tset_xbox_actuators( m_data.m_handle, left_motor, right_motor );\r\n        }\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/* These disable or enable pad vibration.\r\n/******************************************************************/\r\nvoid Device::DisableActuators()\r\n{\r\n\t// If disabled already do nothing.\r\n\tif( m_data.m_actuators_disabled )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\t// Run through all the actuators and make sure they're off.\r\n\tif(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n    {\r\n\t\tfor( int i = 0; i < m_data.m_num_actuators; ++i )\r\n\t\t{\r\n\t\t\t// Switch it off.\r\n\t\t\tm_data.m_actuator_direct[i] = 0;\r\n\t\t}\t\r\n\t\tset_xbox_actuators( m_data.m_handle, 0, 0 );\r\n\t}\t\r\n\t\r\n\t// Set the flag.\r\n\tm_data.m_actuators_disabled = true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Device::EnableActuators( void )\r\n{\r\n\tm_data.m_actuators_disabled = false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Device::ResetActuators( void )\r\n{\r\n\tif( m_data.m_actuators_disabled )\r\n\t{\r\n\t\t// If disabled, then should be off anyway but toggle the states to make sure.\r\n\t\tEnableActuators();\r\n\t\tDisableActuators();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// If enabled, then we disable them, which switched them off and then enable them again (in the off position).\r\n\t\tDisableActuators();\r\n\t\tEnableActuators();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Ken: This gets called for each pad device when the game gets   */\r\n/* paused. It remembers whether the pad was vibrating & switches  */\r\n/* off vibration.\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::Pause( void )\r\n{\r\n\t// If paused already do nothing.\r\n\tif( !m_data.m_paused_ref.InUse())\r\n\t{\t\t\r\n\t    // First, make sure we're in a ready state and our controller has actuators\r\n\t    if(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n\t\t{\r\n\t\t\tfor( int i = 0; i<m_data.m_num_actuators; ++i )\r\n\t\t\t{\r\n\t\t\t\t// Save the old actuator vibration strength.\r\n\t\t\t\tm_data.m_actuator_old_direct[i] = m_data.m_actuator_direct[i];\r\n\r\n\t\t\t\t// Then switch it off.\r\n\t\t\t\tm_data.m_actuator_direct[i] = 0;\r\n\t\t\t}\t\r\n\t\t\tset_xbox_actuators( m_data.m_handle, 0, 0 );\r\n\t\t}\t\r\n\t}\r\n\tm_data.m_paused_ref.Acquire();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Restores the vibration status.                                 */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::UnPause( void )\r\n{\r\n\t// If not paused, do nothing.\r\n\tif( m_data.m_paused_ref.InUse())\r\n\t{\t\t\r\n\t\tm_data.m_paused_ref.Release();\r\n\t\tif( !m_data.m_paused_ref.InUse())\r\n\t\t{\r\n\t\t    // First, make sure we're in a ready state and our controller has actuators\r\n\t\t    if(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n\t\t    {\r\n\t\t\t\tfor( int i = 0; i < m_data.m_num_actuators; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Restore the saved vibration strength.\r\n\t\t\t\t\tm_data.m_actuator_direct[i] = m_data.m_actuator_old_direct[i];\r\n\t\t\t\t}\r\n\t\t\t\tset_xbox_actuators( m_data.m_handle,\r\n\t\t\t\t\t\t\t\t\t(unsigned short)m_data.m_actuator_direct[0] * 256,\r\n\t\t\t\t\t\t\t\t\t(unsigned short)m_data.m_actuator_direct[1] * 256 );\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/* Switches off vibration, and also zeros the saved\t\t\t\t  */\r\n/* vibration levels too so that unpausing will not\t\t\t\t  */\r\n/* switch them on again for goodness sake.\t\t\t\t\t\t  */\r\n/******************************************************************/\r\nvoid Device::StopAllVibrationIncludingSaved()\r\n{\r\n\t// First, make sure we're in a ready state and our controller has actuators\r\n\tif(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n\t{\r\n\t\tfor( int i = 0; i < m_data.m_num_actuators; ++i )\r\n\t\t{\r\n\t\t\tm_data.m_actuator_direct[i]\t\t= 0;\r\n\t\t\tm_data.m_actuator_old_direct[i]\t= 0;\r\n\t\t}\t\r\n\t\tset_xbox_actuators( m_data.m_handle, 0, 0 );\r\n\t}\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Device::ActivatePressureSensitiveMode( void )\r\n{\r\n    if( m_data.m_caps.TestMask( mANALOG_BUTTONS ))\r\n    {\r\n//\t\tif( scePadEnterPressMode( m_data.m_port, m_data.m_slot ) == 1 )\r\n\t\t{\r\n\t\t\tm_state = vBUSY;\r\n\t\t\tm_next_state = vACQUIRED;\r\n\t\t}\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::DeactivatePressureSensitiveMode( void )\r\n{\r\n    if( m_data.m_caps.TestMask( mANALOG_BUTTONS ))\r\n    {\r\n//\t\tif( scePadExitPressMode( m_data.m_port, m_data.m_slot ) == 1 )\r\n\t\t{\r\n\t\t\tm_state = vBUSY;\r\n\t\t\tm_next_state = vACQUIRED;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n} // namespace SIO\r\n"
  },
  {
    "path": "Code/Sys/SIO/XBox/p_sioman.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSYS (SYS_) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsioman.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/26/2000\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSerial IO Manager\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n\r\n#include <core/defines.h>\r\n\r\n#include <sys/sioman.h>\r\n#include <sys/siodev.h>\r\n#include <sys/sio/keyboard.h>\r\n\r\n#include <gel/module.h>\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/soundfx/xbox/p_sfx.h>\r\n#include <gel/music/music.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nextern int KeyboardInit(void);\r\n       \r\nnamespace SIO\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefineSingletonClass( Manager, \"Serial IO Manager\" );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid Manager::process_devices( const Tsk::Task< Manager::DeviceList >& task )\r\n{\r\n\tDevice*\t\t\t\t\tdevice;\r\n\tLst::Search< Device >\t    sh;\r\n\tManager::DeviceList&\tdevice_list = task.GetData();\r\n\r\n\tdevice = sh.FirstItem ( device_list );\r\n\r\n\twhile ( device )\r\n\t{\r\n\t\tDbg_AssertType ( device, Device );\r\n\r\n\t\tdevice->process();\r\n\t\tdevice = sh.NextItem();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nDevice* Manager::create_device( int index, int port, int slot )\r\n{\r\n    Device *device;\r\n        \r\n    device = new Device( index, port, slot );\r\n\r\n    return device;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nManager::Manager ( void )\r\n{\r\n    int i, index;\r\n\r\n\tXDEVICE_PREALLOC_TYPE xdpt[] = {{ XDEVICE_TYPE_GAMEPAD,\t\t\t4 },\r\n\t\t\t\t\t\t\t\t\t{ XDEVICE_TYPE_MEMORY_UNIT,\t\t1 }};\r\n\r\n\t// Initialize the peripherals.\r\n\tXInitDevices( sizeof( xdpt ) / sizeof( XDEVICE_PREALLOC_TYPE ), xdpt );\r\n\r\n\t// Create the keyboard queue.\r\n//\tXInputDebugInitKeyboardQueue( &xdkp );\r\n\r\n    m_process_devices_task = new Tsk::Task< DeviceList > ( Manager::process_devices, m_devices );\r\n    \r\n\t// Pause briefly here to give the system time to enumerate the attached devices.\r\n\tSleep( 1000 );\r\n\r\n    index = 0;\r\n    for( i = 0; i < SIO::vMAX_PORT; i++ )\r\n    {\r\n\t    Device* p_device;\r\n\r\n\t\tif(( p_device = create_device( index, i, 0 )))\r\n\t\t{\r\n\t\t\tm_devices.AddToTail( p_device->m_node );\r\n\t\t\tp_device->Acquire();\r\n\t\t\tindex++;\r\n\t\t}\r\n    }\r\n    \r\n\tif( !Pcm::NoMusicPlease())\r\n\t{\r\n\t\tPcm::Init();\r\n\t}\r\n\r\n\tDbg_Message( \"Initialized Controller lib\\n\" );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nManager::~Manager( void )\r\n{\r\n    Device*\t\t\t\t\tdevice;\r\n    Device*\t\t\t\t\tnext;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    device = sh.FirstItem ( m_devices );\r\n    \r\n    while ( device )\r\n    {\r\n        Dbg_AssertType ( device, Device );\r\n    \r\n        next = sh.NextItem();\r\n    \r\n        delete device;\r\n        device = next;\r\n    }\r\n\r\n    delete m_process_devices_task;\r\n\r\n#\tif KEYBOARD_ON\r\n\t// Initialize the keyboard.\r\n\tKeyboardDeinit();\r\n#\tendif\r\n\r\n\tDbg_Message( \"Shut down IOP Controller Lib\\n\" );\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Manager::ProcessDevices( void )\r\n{\r\n\tDevice*\t\t\t\t\tdevice;\r\n\tLst::Search< Device >\tsh;\r\n\tManager::DeviceList&\tdevice_list = m_devices;\r\n\r\n\tdevice = sh.FirstItem( device_list );\r\n\r\n\twhile( device )\r\n\t{\r\n\t\tDbg_AssertType ( device, Device );\r\n\r\n\t\tdevice->process();\r\n\t\tdevice = sh.NextItem();\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nDevice* Manager::GetDevice( int port, int slot )\r\n{\r\n    Device*\t\t\t\t\tdevice;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    device = sh.FirstItem ( m_devices );\r\n    \r\n    for( device = sh.FirstItem ( m_devices ); device;\r\n            device = sh.NextItem ())\r\n    {\r\n        if( ( device->GetPort() == port ) &&\r\n            ( device->GetSlot() == slot ))\r\n        {\r\n            return device;\r\n        }\r\n    }\r\n    \r\n    return NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nDevice* Manager::GetDeviceByIndex( int index )\r\n{\r\n    Device*\t\t\t\t\tdevice;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    device = sh.FirstItem ( m_devices );\r\n    \r\n    for( device = sh.FirstItem ( m_devices ); device;\r\n            device = sh.NextItem ())\r\n    {\r\n        if( device->GetIndex() == index )\r\n        {\r\n            return device;\r\n        }\r\n    }\r\n    \r\n    return NULL;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Manager::Pause()\r\n{\r\n    Device*\t\t\t\t\tdevice;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    for( device = sh.FirstItem( m_devices ); device; device = sh.NextItem())\r\n    {\r\n\t\tdevice->Pause();\r\n    }\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Manager::UnPause( void )\r\n{\r\n    Device*\t\t\t\t\tdevice;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    for( device = sh.FirstItem( m_devices ); device; device = sh.NextItem())\r\n    {\r\n\t\tdevice->UnPause();\r\n    }\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace SIO\r\n"
  },
  {
    "path": "Code/Sys/SIO/keyboard.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSYS (SYS_) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tkeyboard.h\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/08/2001\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tUSB Keyboard interface\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#ifndef __SYS_KEYBOARD_H\r\n#define __SYS_KEYBOARD_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace SIO\r\n{\r\n\r\n\t\r\n\r\n#define KEYBOARD_ON\t(1)\r\n\t\t\t\r\nenum\r\n{\r\n\tvKB_LEFT\t= 20,\t// start it high so as not to interfere with button/pad enums \r\n\tvKB_RIGHT,\r\n\tvKB_UP,\r\n\tvKB_DOWN,\r\n\tvKB_BACKSPACE,\r\n\tvKB_ENTER,\r\n\tvKB_ESCAPE,\r\n\tvKB_F1,\r\n\tvKB_F2,\r\n\tvKB_F3,\r\n\tvKB_F4\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint KeyboardInit(void);\r\nint KeyboardDeinit(void);\r\nint KeyboardRead( char* makes );\r\nvoid KeyboardClear( void );\r\nvoid SetKeyboardActive(bool active);\r\nvoid EnableKeyboard( bool enable );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace SIO\r\n\r\n#endif\t// __SYS_KEYBOARD__H\r\n\r\n"
  },
  {
    "path": "Code/Sys/SIO/ngc/p_keyboard.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSYS (SYS_) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tkeyboard.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t03/08/2001\t-\tgj\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tUSB Keyboard interface\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <sys/sio/keyboard.h>\r\n\r\n//#include <eekernel.h>\r\n//#include <eeregs.h>\r\n//#include <stdio.h>\r\n//#include <sifdev.h>\r\n//#include <sifrpc.h>\r\n//\r\n//#include <libusbkb.h>\r\nextern \"C\"\r\n{\r\nint sceUsbKbInit(int *max_connect) { return 0; }\r\nint sceUsbKbGetInfo(int *info) { return 0; }\r\nint sceUsbKbRead(unsigned int no,int *data) { return 0; }\r\nint sceUsbKbGetLocation(int no,unsigned char *location) { return 0; }\r\nint sceUsbKbSetLEDStatus(int no, unsigned char led) { return 0; }\r\nint sceUsbKbSetLEDMode(int no, int mode) { return 0; }\r\nint sceUsbKbSetRepeat(int no, int sta_time, int interval) { return 0; }\r\nint sceUsbKbSetCodeType(int no, int type) { return 0; }\r\nint sceUsbKbSetArrangement(int no, int arrange) { return 0; }\r\nint sceUsbKbSync(int mode, int *result) { return 0; }\r\n}\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace SIO\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define USBKEYBD_ARG \"keybd=8\\0debug=1\"\r\n\r\nstatic\tunsigned char *s_old_status = NULL;\r\n//static\tint\ts_info;\r\n//static\tunsigned char \t\ts_location[7];\r\n//static\tint s_kdata;\r\nstatic\tint\t\t\ts_max_connect;\r\n\r\nenum\r\n{\r\n\tvKEYCODE_RIGHT\t=\t0x804F,\r\n\tvKEYCODE_LEFT\t=\t0x8050,\r\n\tvKEYCODE_DOWN\t=\t0x8051,\r\n\tvKEYCODE_UP\t\t=\t0x8052,\r\n\tvKEYCODE_ESC\t= \t0x8029,\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//static void s_init_newkeyboard( int i );\r\n//static int s_capture_input( int i, char* makes );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint KeyboardInit(void)\r\n{\r\n\tint result;\r\n//    char *option = USBKEYBD_ARG;\r\n\tint i;\r\n\r\n\t//sceSifInitRpc(0);\r\n\t\r\n//#ifdef __NOPT_CDROM__OLD\r\n//\tresult = sceSifLoadModule(\r\n//               \"cdrom0:\\\\USBKB.IRX\",\r\n//                sizeof( USBKEYBD_ARG ) + 1, option );\r\n//#else\r\n//\tresult = sceSifLoadModule(\r\n//               \"host0:IOPModules/usbkb.irx\",\r\n//                sizeof( USBKEYBD_ARG ) + 1, option );\r\n//#endif\r\n\t\r\n//\tif( result < 0 )\r\n    {\r\n        Dbg_MsgAssert( 0,( \"EE:Can't load module usbkb.irx\\n\" ));\r\n\t\treturn -1;\r\n\t}\r\n\r\n    result = sceUsbKbInit( &s_max_connect );\r\n//    if( result == USBKB_NG ) \r\n\t{\r\n\t\tDbg_Printf( \"Initialize error\\n\" );\r\n\t\treturn -1;\r\n\t}\r\n\r\n    s_old_status = new unsigned char[ s_max_connect ];\r\n    for( i = 0; i < s_max_connect; i++ ) \r\n\t{ \r\n\t\ts_old_status[i] = 0; \r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint KeyboardRead( char* makes )\r\n{\r\n//\tint result;\r\n//\tint i, num_strokes;\r\n//\r\n//\t// get keyboard info\r\n//\tresult = sceUsbKbGetInfo( &s_info );\r\n////\tif( result != USBKB_OK ) \r\n//\t{\r\n//\t\tDbg_Printf( \"Error%d : sceUsbKbGetInfo\\n\", result );\r\n//\t\treturn 0;\r\n//\t}\r\n////\tsceUsbKbSync( USBKB_WAIT, &result );\r\n////\tif( result != USBKB_OK ) \r\n//\t{\r\n//\t\tDbg_Printf( \"Error%d : sceUsbKbSync\\n\", result );\r\n//\t\treturn 0;\r\n//\t}\r\n//  \r\n//\tnum_strokes = 0;\r\n//\t// reading keyboard\r\n//\tfor( i = 0; i < s_max_connect; i++)  \r\n//\t{\r\n////\t\tif( s_info.status[i] == 0 ) \r\n//\t\t{ \r\n//\t\t\tcontinue; \r\n//\t\t}  // not connected\r\n//\r\n//\t\tif( s_old_status[i] == 0 ) \r\n//\t\t{\r\n//\t\t\tDbg_Printf( \"New keyboard %d is connected\\n\", i );\r\n//\t\t\ts_init_newkeyboard(i);\r\n//\t\t}\r\n//\r\n//\t\tresult = sceUsbKbRead( i, &s_kdata );\r\n////\t\tif( result != USBKB_OK ) \r\n//\t\t{\r\n//\t\t\tDbg_Printf( \"Error%d : sceUsbKbRead\\n\", result );\r\n//\t\t\tcontinue;\r\n//\t\t}\r\n////\t\tsceUsbKbSync( USBKB_WAIT, &result );\r\n////\t\tif( result != USBKB_OK ) \r\n//\t\t{\r\n//\t\t\tDbg_Printf( \"Error%d : sceUsbKbSync\\n\",result);\r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\r\n////\t\tif( s_kdata.len == 0 ) \r\n//\t\t{\r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\r\n////\t\tresult = sceUsbKbGetLocation( i, s_location );\r\n////\t\tif( result != USBKB_OK ) \r\n//\t\t{\r\n//\t\t\tDbg_Printf( \"Error%d : sceUsbKbGetLocation\\n\", result );\r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\t\t\r\n////\t\tsceUsbKbSync( USBKB_WAIT, &result );\r\n////\t\tif( result != USBKB_OK ) \r\n//\t\t{\r\n//\t\t\tDbg_Printf( \"Error%d : sceUsbKbSync\\n\", result );\r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\t\t\r\n//\t\tnum_strokes = s_capture_input( i, makes );\r\n//\t}\r\n//  \r\n//\tfor( i = 0; i < s_max_connect; i++ ) \r\n//\t{ \r\n////\t\ts_old_status[i] = s_info.status[i]; \r\n//\t}\r\n//\r\n//\treturn num_strokes;\r\n\treturn 0;\r\n}\r\n\r\nvoid KeyboardClear( void )\r\n{\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n//static void s_init_newkeyboard( int i )\r\n//{       \r\n//\tint result;\r\n//\t\r\n//\tresult = sceUsbKbSetLEDStatus( i, USBKB_LED_NUM_LOCK );\r\n//\tif( result != USBKB_OK ) \r\n//\t{\r\n//\t\tDbg_Printf( \"Error%d : sceUsbKbSetLEDStatus\\n\", result );\r\n//\t} \r\n//\telse \r\n//\t{\r\n//\t\tsceUsbKbSync(USBKB_WAIT,&result);\r\n//\t\tif( result != USBKB_OK ) \r\n//\t\t{\r\n//\t\t\tDbg_Printf( \"Error%d : sceUsbKbSync\\n\", result );\r\n//\t\t}\r\n//\t}\r\n//\t\r\n//\tresult = sceUsbKbSetLEDMode( i, USBKB_LED_MODE_AUTO1 );\r\n//\tif( result != USBKB_OK ) \r\n//\t{\r\n//\t\tDbg_Printf( \"Error%d : sceUsbKbSetLEDMode\\n\", result );\r\n//\t} \r\n//\telse \r\n//\t{\r\n//\t\tsceUsbKbSync( USBKB_WAIT, &result );\r\n//\t\tif( result != USBKB_OK ) \r\n//\t\t{\r\n//\t\t\tDbg_Printf( \"Error%d : sceUsbKbSync\\n\", result );\r\n//\t\t}\r\n//\t}\r\n//\t\r\n//\tsceUsbKbSetRepeat( i, 30, 2 );\r\n//\tsceUsbKbSetCodeType( i, USBKB_CODETYPE_ASCII );\r\n//\tsceUsbKbSetArrangement( i, USBKB_ARRANGEMENT_106 );\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n//static int s_capture_input( int i, char* makes )\r\n//{\r\n//\tunsigned short kcode;\r\n//\tint j, k, index;\r\n//\t\r\n//\t//Dbg_Printf( \"usbkeybd%d : \", i );\r\n//\t\r\n//\t//Dbg_Printf( \"port=\" );\r\n//\tfor( k = 0; k < 7 && s_location[k] != 0; k++ )\r\n//\t{\r\n//\t\t//Dbg_Printf( \"%s%d\", ((k)? \",\": \"\" ), s_location[k] );\r\n//\t}\r\n//\t  \r\n//\t\r\n//\t//Dbg_Printf( \" : LED[%02X] \", s_kdata.led );\r\n//\t\r\n//\t//Dbg_Printf( \"MKEY[%02X] \", s_kdata.mkey );\r\n//\t\r\n//\t//Dbg_Printf( \"KEY[\" );\r\n//\t\r\n//\tindex = 0;\r\n//\tfor( j=0; j < s_kdata.len; j++ ) \r\n//\t{\r\n//\t\tkcode = s_kdata.keycode[j];\r\n//\t\tif( kcode & USBKB_RAWDAT ) \r\n//\t\t{\r\n//\t\t\t//Dbg_Printf( \"%04X \", kcode );\r\n//\t\t\tswitch( kcode )\r\n//\t\t\t{   \r\n//\t\t\t\tcase vKEYCODE_RIGHT:\r\n//\t\t\t\t\tmakes[index++] = vKB_RIGHT;\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\tcase vKEYCODE_LEFT:\r\n//\t\t\t\t\tmakes[index++] = vKB_LEFT;\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\tcase vKEYCODE_DOWN:\r\n//\t\t\t\t\tmakes[index++] = vKB_DOWN;\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\tcase vKEYCODE_UP:\r\n//\t\t\t\t\tmakes[index++] = vKB_UP;\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\tcase vKEYCODE_ESC:\r\n//\t\t\t\t\tmakes[index++] = vKB_ESCAPE;\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t}\r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\t\tif( kcode & USBKB_KEYPAD ) \r\n//\t\t{\r\n//\t\t\t// 10 key\r\n//\t\t\tif((kcode & 0x00ff) == '\\n')\r\n//\t\t\t{ \r\n//\t\t\t\t//Dbg_Printf( \"(\\\\n)\" ); \r\n//\t\t\t\tmakes[index++] = vKB_ENTER;\r\n//\t\t\t\tcontinue;\r\n//\t\t\t}\r\n//\t\t\t//Dbg_Printf( \"(%c) \", kcode & ~USBKB_KEYPAD );\r\n//\t\t\tmakes[index++] = kcode & ~USBKB_KEYPAD;\r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\t\t// Normal key\r\n//\t\tif((kcode & 0x00ff) == '\\0' ) \r\n//\t\t{ \r\n//\t\t\t//Dbg_Printf( \"\\'\\\\0\\'\" ); \r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\t\tif((kcode & 0x00ff) == '\\n' ) \r\n//\t\t{ \r\n//\t\t\t//Dbg_Printf( \"\\'\\\\n\\'\" ); \r\n//\t\t\tmakes[index++] = vKB_ENTER;\r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\t\tif((kcode & 0x00ff) == '\\t' ) \r\n//\t\t{ \r\n//\t\t\t//Dbg_Printf( \"\\'\\\\t\\'\" ); \r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\t\tif((kcode & 0x00ff) == '\\b' ) \r\n//\t\t{ \r\n//\t\t\t//Dbg_Printf( \"\\'\\\\b\\'\" ); \r\n//\t\t\tmakes[index++] = vKB_BACKSPACE;\r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\t\t//Dbg_Printf( \"\\'%c\\' \", kcode );\r\n//\t\tmakes[index++] = kcode;\r\n//\t}\r\n//\t//Dbg_Printf( \"]\\n\" ); \r\n//\r\n//\treturn index;\r\n//\treturn 0;\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace SIO\r\n"
  },
  {
    "path": "Code/Sys/SIO/ngc/siodev.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSYS (SYS_) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsiodev.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/26/2000\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGeneric input device\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdlib.h>\r\n#include <string.h>\r\n         \r\n#include <core/defines.h>\r\n#include <sys/sioman.h>\r\n#include <sys/mem/memman.h>\r\n//#include <libpad.h>\r\n\r\n#include <dolphin.h>\r\n#include \"sys/ngc/p_hwpad.h\"\r\n\r\n// PJR - Doh!\r\nextern PADStatus padData[PAD_MAX_CONTROLLERS]; // game pad state\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace SIO\r\n{\r\n  \r\n\r\n// Maps Xbox thumbstick values in the range [-32767, 32767] to PS2 thumstick values in the range [0, 255].\r\n#define XboxThumbToPS2Thumb( v )\t(( v + 32767 ) / 256 )\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n    \r\nvoid Device::process( void )\r\n{\r\n    switch( m_state )\r\n    {\r\n\r\n    case vIDLE:\r\n        break;\r\n\r\n    case vBUSY:\r\n        wait();\r\n        break;\r\n\r\n    case vACQUIRING:\r\n        acquisition_pending();\r\n        break;\r\n\r\n    case vACQUIRED:\r\n        read_data();\r\n        break;\r\n\r\n    default:\r\n        break;\r\n\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::wait( void )\r\n{\r\n    Dbg_MsgAssert(( m_next_state >= 0 ) && ( m_next_state <= vNUM_STATES ),( \"No next state set for wait state\" ));\r\n\r\n\tif ( get_status() != vNOTREADY )\r\n\t{\r\n\t\tm_state = m_next_state;\r\n\t\tm_next_state = vIDLE;\r\n\t}\r\n}\r\n\r\n\r\n//int gButton_Option = 0;\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Device::read_data( void )\r\n{\r\n\tPADStatus * p;\r\n\r\n\t// Need to check here for the controller becoming detached.\r\n\tif( padData[m_data.m_port].err == PAD_ERR_NO_CONTROLLER )\r\n\t{\r\n\t\tm_plugged_in\t= false;\r\n\t\tm_data.m_valid\t= false;\r\n\t\tUnacquire();\r\n\t\tAcquire();\r\n\t\treturn;\r\n\t}\r\n\r\n\tm_data.m_valid\t= true;\r\n\tm_plugged_in\t= true;\r\n\r\n\tp = &padData[m_data.m_port];\r\n\r\n\t// Convert this data back into PS2-style 'raw' data for a DUALSHOCK2.\r\n\tm_data.m_control_data[0] = 0;\t\t\t\t\t\t// 'Valid' info flag.\r\n\tm_data.m_control_data[1] = ( 0x07 << 4 ) | 16;\t\t// DUALSHOCK2 id + data length.\r\n\r\n\tm_data.m_control_data[2] = 0xFF;\t\t\t\t\t// Turn off all buttons by default.\r\n\tm_data.m_control_data[3] = 0xFF;\t\t\t\t\t// Turn off all buttons by default.\r\n\r\n\tm_data.m_control_data[2] ^= ( ( p->button & PAD_BUTTON_START ) && !( p->button & PAD_TRIGGER_Z ) ) ? ( 1 << 3 ) : 0;\t// Gamecube 'Start' = PS2 'Start' (only if Z is not also pressed).\r\n\r\n\t#if 0 // Dan: none of the Z-shifting crap\r\n\t// Gamecube 'Z' = PS2 'Select'.\r\n\t// Directly mapping to select is disabled.\r\n\r\n\t// Gamecube 'Z' plus 'L' = PS2 'Right Stick Button'.\r\n\t// Gamecube 'Z' plus 'R' = PS2 'shift' (this allows the camera mode shifting).\r\n\tif( p->button & PAD_TRIGGER_Z )\r\n\t{\r\n\t\t// with Z pressed, triggers are L2/R2\r\n\t\t\r\n\t\t// GameCube 'Z' plus 'L' = PS2 'Right Stick Button'. \r\n\t\tif( p->button & PAD_TRIGGER_L )\r\n\t\t{\r\n\t\t\tm_data.m_control_data[2] ^= ( 1 << 1 );\r\n\t\t} else\r\n\r\n\t\t// GameCube 'Z' plus 'R' = PS2 'Right Stick Button'. \r\n\t\tif( p->button & PAD_TRIGGER_R )\r\n\t\t{\r\n\t\t\tm_data.m_control_data[2] ^= ( 1 << 2 );\r\n\t\t} else\r\n\r\n//\t\t// Z button + START is PS2 'Select'.\r\n//\t\tif( p->button & PAD_BUTTON_START )\r\n//\t\t{\r\n//\t\t\tm_data.m_control_data[2] ^= ( 1 << 0 );\r\n//\t\t}\r\n\t\t// Z button without L & R is PS2 L1+R1.\r\n\t\t{\r\n\t\t\tm_data.m_control_data[3] ^= ( 1 << 2 ) | ( 1 << 3 );\r\n\t\t\tm_data.m_control_data[2] ^= ( 1 << 0 );\r\n\t\t}\r\n\t}\r\n\t#endif\r\n\r\n\t// Temp hack to get fly-around working.\r\n\tif( p->button & PAD_TRIGGER_Z )\r\n\t{\r\n\t\tm_data.m_control_data[2] ^= ( 1 << 0 );\r\n\t}\r\n\r\n\tm_data.m_control_data[3] ^= ( p->button & PAD_BUTTON_Y ) ? ( 1 << 4 ) : 0;\t\t// Gamecube 'Y' = PS2 'Triangle'.\r\n\tm_data.m_control_data[3] ^= ( p->button & PAD_BUTTON_X ) ? ( 1 << 5 ) : 0;\t\t// Gamecibe 'X' = PS2 'Circle'.\r\n\tm_data.m_control_data[3] ^= ( p->button & PAD_BUTTON_A ) ? ( 1 << 6 ) : 0;\t\t// Gamecube 'A' = PS2 'X'.\r\n\tm_data.m_control_data[3] ^= ( p->button & PAD_BUTTON_B ) ? ( 1 << 7 ) : 0;\t\t// Gamecube 'B' = PS2 'Square'.\r\n\r\n\t// Dan: none of this analog crap\r\n\t// m_data.m_control_data[3] ^= ( p->triggerLeft  > 128 ) ? ( 1 << 2 ) : 0;\t\t// XBox 'Left Trigger pressed down > halfway' = PS2 'L1'.\r\n\t// m_data.m_control_data[3] ^= ( p->triggerRight > 128 ) ? ( 1 << 3 ) : 0;\t\t// XBox 'Right Trigger pressed down > halfway' = PS2 'R1'.\r\n\t// m_data.m_control_data[3] ^= ( p->triggerLeft  > 16 ) ? ( 1 << 0 ) : 0;\t\t// XBox 'Left Trigger' = PS2 'L2'.\r\n\t// m_data.m_control_data[3] ^= ( p->triggerRight > 16 ) ? ( 1 << 1 ) : 0;\t\t// XBox 'Right Trigger' = PS2 'R2'.\r\n\t\r\n\tm_data.m_control_data[3] ^= ( p->triggerLeft  > 128 ) ? ( 1 << 2 ) : 0;\t\t\t// Gamecube 'Left Trigger = PS2 'L1'.\r\n\tm_data.m_control_data[3] ^= ( p->triggerRight > 128 ) ? ( 1 << 3 ) : 0;\t\t\t// Gamecube 'Right Trigger = PS2 'R1'.\r\n\t\r\n\t// Dan: Store the state of Z in m_control_data[20] above Xbox's black and white buttons.\r\n\tm_data.m_control_data[20]=0;\r\n\tif (p->button & PAD_TRIGGER_Z)\r\n\t{\r\n\t\tm_data.m_control_data[20] |= (1<<2);\r\n\t}\t\r\n\r\n\t// Make analog buttons full depression if pressed.\r\n\t// Ngc analog buttons return analog value in range [0, 255].\r\n\tm_data.m_control_data[12] = ( p->button & PAD_BUTTON_Y ) ? 255 : 0;\t\t\t\t// Gamecube 'Y' = PS2 Analog 'Triangle'.\r\n\tm_data.m_control_data[13] = ( p->button & PAD_BUTTON_X ) ? 255 : 0;\t\t\t\t// Gamecube 'X' = PS2 Analog 'Circle'.\r\n\tm_data.m_control_data[14] = p->analogA;\t\t\t\t\t\t\t\t\t\t\t// Gamecube 'A' = PS2 Analog 'X'.\r\n\tm_data.m_control_data[15] = p->analogB;\t\t\t\t\t\t\t\t\t\t\t// Gamecube 'B' = PS2 'Square'.\r\n\t\r\n\tm_data.m_control_data[16] = ( p->triggerLeft  > 128 ) ? 255 : 0;\t\t\t\t// Gamecube 'Left Trigger' = PS2 Analog 'L1'.\r\n\tm_data.m_control_data[17] = ( p->triggerRight > 128 ) ? 255 : 0;\t\t\t\t// Gamecube 'Right Trigger' = PS2 Analog 'R1'.\r\n\tm_data.m_control_data[18] = 0;\t\t\t\t\t\t\t\t\t\t\t\t\t// Gamecube no 'L2'\r\n\tm_data.m_control_data[19] = 0;\t\t\t\t\t\t\t\t\t\t\t\t\t// Gamecube no 'R2'\r\n\r\n\t// Zero out the d-pad pressure values.\r\n\tm_data.m_control_data[8]\t= 0x00;\r\n\tm_data.m_control_data[9]\t= 0x00;\r\n\tm_data.m_control_data[10]\t= 0x00;\r\n\tm_data.m_control_data[11]\t= 0x00;\r\n\r\n\t// Handle 8 position d-pad.\r\n\tm_data.m_control_data[2] ^= ( p->button & PAD_BUTTON_UP ) ? ( 1 << 4 ) : 0;\t\t// Gamecube 'DPad Up' = PS2 'DPad Up'.\r\n\tm_data.m_control_data[10] = ( p->button & PAD_BUTTON_UP ) ? 0xFF : 0;\t\t\t// Gamecube 'DPad Up' = PS2 'DPad Up'.\r\n\tm_data.m_control_data[2] ^= ( p->button & PAD_BUTTON_RIGHT ) ? ( 1 << 5 ) : 0;\t// Gamecube 'DPad Right' = PS2 'DPad Right'.\r\n\tm_data.m_control_data[8] = ( p->button & PAD_BUTTON_RIGHT ) ? 0xFF : 0;\t\t\t// Gamecube 'DPad Right' = PS2 'DPad Right'.\r\n\tm_data.m_control_data[2] ^= ( p->button & PAD_BUTTON_DOWN ) ? ( 1 << 6 ) : 0;\t// Gamecube 'DPad Down' = PS2 'DPad Down'.\r\n\tm_data.m_control_data[11] = ( p->button & PAD_BUTTON_DOWN ) ? 0xFF : 0;\t\t\t// Gamecube 'DPad Down' = PS2 'DPad Down'.\r\n\tm_data.m_control_data[2] ^= ( p->button & PAD_BUTTON_LEFT ) ? ( 1 << 7 ) : 0;\t// Gamecube 'DPad Left' = PS2 'DPad Left'.\r\n\tm_data.m_control_data[9] = ( p->button & PAD_BUTTON_LEFT ) ? 0xFF : 0;\t\t\t// Gamecube 'DPad Left' = PS2 'DPad Left'.\r\n\r\n\t// Gamecube thumbsticks return analog value in range [-128, 127].\r\n\tint stx = (int)(((float)p->stickX) * 2.0f );\r\n\tint sty = (int)(((float)p->stickY) * 2.0f );\r\n\tif ( stx < -128 ) stx = -128;\r\n\tif ( stx > 127 ) stx = 127;\r\n\tif ( sty < -128 ) sty = -128;\r\n\tif ( sty > 127 ) sty = 127;\r\n\r\n\tint subx = (int)(((float)p->substickX) * 2.0f );\r\n\tint suby = (int)(((float)p->substickY) * 2.0f );\r\n\tif ( subx < -128 ) subx = -128;\r\n\tif ( subx > 127 ) subx = 127;\r\n\tif ( suby < -128 ) suby = -128;\r\n\tif ( suby > 127 ) suby = 127;\r\n\r\n\tm_data.m_control_data[4] = (unsigned char)(subx+128);\t\t// Analog stick right (X direction).\r\n\tm_data.m_control_data[5] = 255 - (unsigned char)(suby+128);\t// Analog stick right (Y direction).\r\n\tm_data.m_control_data[6] = (unsigned char)(stx+128);\t\t// Analog stick left (X direction).\r\n\tm_data.m_control_data[7] = 255 - (unsigned char)(sty+128);\t// Analog stick left (Y direction).\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Device::IsPluggedIn( void )\r\n{\r\n\treturn m_plugged_in;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::acquisition_pending( void )\r\n{\r\n    int status;\r\n\r\n    status = get_status();\r\n                        \r\n    if(( status == vCONNECTED ) || ( status == vREADY ))\r\n    {\r\n        // sucessful.  Now query the controller for capabilities\r\n        query_capabilities();\r\n    }\r\n        \r\n\t// failed to acquire controller\r\n\t// stay in this state and continue to try to acquire it or prompt the user if it is mandatory\r\n\t// that they have a controller in   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::query_capabilities( void )\r\n{   \r\n\t// Currently assumes standard Gamecube controller.\r\n    int id = vANALOG_CTRL;\r\n    \r\n    m_data.m_type = id;\r\n\r\n\tswitch( id )\r\n\t{   \r\n\t\tcase vANALOG_CTRL:\r\n\t\t{\r\n\t\t\tm_data.m_caps.SetMask( mANALOG_BUTTONS );\r\n\r\n\t\t\t// GameCube actually only has 1, but we need to track 2 since PS2 and Xbox have 2,\r\n\t\t\t// and incoming requests could be for either.\r\n\t\t\tm_data.m_num_actuators = 2;\r\n\t\t\tm_data.m_caps.SetMask( mACTUATORS );\r\n\t\t\tm_data.m_actuator_max[0] = 1;\r\n\t\t\tm_data.m_actuator_max[1] = 1;\r\n\r\n\t\t\tm_state = vBUSY;\r\n\t\t\tm_next_state = vACQUIRED;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_Message( \"Detected Controller of unknown type in %d:%d\", m_data.m_port, m_data.m_slot );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n    m_state = vACQUIRED;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Device::get_status( void )\r\n{\r\n\tif( m_data.m_port < 4 )\r\n\t{\r\n\t\tif( padData[m_data.m_port].err == PAD_ERR_NONE )\r\n\t\t{\r\n\t\t\treturn vREADY;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Could do more checking here of the return value.\r\n\t\t\treturn vDISCONNECTED;\r\n\t\t}\r\n\t}\r\n\treturn vDISCONNECTED;\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDevice::Device ( int index, int port, int slot )\r\n{\r\n\tm_node = new Lst::Node< Device > ( this );\r\n\tDbg_AssertType ( m_node, Lst::Node< Device > );\r\n\r\n    Dbg_Assert( port < vMAX_PORT );\r\n    Dbg_Assert( slot < vMAX_SLOT );\r\n\r\n    m_state = vIDLE;\r\n    m_next_state = vIDLE;\r\n    m_index = index;\r\n\r\n    // Initialize device\r\n    m_data.m_port = port;\r\n    m_data.m_slot = slot;\r\n    m_data.m_caps.ClearAll();\r\n    m_data.m_num_actuators = 0;\r\n    m_data.m_valid = false;\r\n\r\n    memset( m_data.m_actuator_direct, 0, ACTUATOR_BUFFER_LENGTH );\r\n    memset( m_data.m_actuator_align, 0xFF, ACTUATOR_BUFFER_LENGTH );\r\n    m_data.m_actuator_align[0] = 0;\r\n    m_data.m_actuator_align[1] = 1;\r\n\r\n    memset( m_data.m_control_data, 0, CTRL_BUFFER_LENGTH );\r\n//\tm_data.m_prealbuffer = Mem::Malloc( scePadDmaBufferMax * sizeof( uint128) + 63 );\r\n\tm_data.m_dma_buff =  (unsigned char*)((((uint32)m_data.m_prealbuffer)+63)&~63);\r\n\t\r\n//    memset( m_data.m_dma_buff, 0, sizeof( uint128 ) * scePadDmaBufferMax );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nDevice::~Device ( void )\r\n{\r\n\tDbg_AssertType ( m_node, Lst::Node< Device > );\r\n//\tMem::Free( m_data.m_prealbuffer );\r\n\r\n//\tXInputClose( m_data.m_handle );\r\n\r\n\tdelete m_node;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::Acquire( void )\r\n{\r\n    Dbg_Message( \"Acquiring controller port %d slot %d\\n\", m_data.m_port, m_data.m_slot );\r\n\r\n    if( m_state == vIDLE )\r\n    {\r\n\t\tif( m_data.m_port < 4 )\r\n\t\t{\r\n\t\t\t// Acquire device handle.\r\n//\t\t\tm_data.m_handle = XInputOpen( XDEVICE_TYPE_GAMEPAD, m_data.m_port, XDEVICE_NO_SLOT, NULL );\r\n//\r\n//\t\t\tif( m_data.m_handle )\r\n\t\t\t{\r\n\t\t\t\t// Store capabilites of the device\r\n//\t\t\t\tXINPUT_CAPABILITIES caps;\r\n//\t\t\t\tXInputGetCapabilities( m_data.m_handle, &caps );\r\n\r\n//\t\t\t\tmemset( m_data.m_control_data, 0, CTRL_BUFFER_LENGTH );\r\n\t\t\t\tm_data.m_valid = false;\r\n\t\t\t\tm_state = vACQUIRING;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tDbg_Warning( \"failed to open controller port %d slot %d\\n\", m_data.m_port, m_data.m_slot );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid Device::Unacquire ( void )\r\n{\r\n    Dbg_Message( \"Unacquiring controller port %d slot %d\\n\", m_data.m_port, m_data.m_slot );\r\n\r\n    if( m_state == vACQUIRED )\r\n    {\r\n//\t\tif( scePadPortClose( m_data.m_port, m_data.m_slot ) != 1 )\r\n//\t\t{\r\n//\t\t\tDbg_Warning( \"failed to close controller port %d slot %d\\n\", m_data.m_port, m_data.m_slot );\r\n//\t\t}\r\n    }\r\n\r\n    m_state = vIDLE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Device::ActivateActuator( int act_num, int percent )\r\n{\r\n\t// Do nothing if the actuators are disabled.\r\n\tif( m_data.m_actuators_disabled )\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n    float act_strength;\r\n    \r\n    // First, make sure we're in a ready state and our controller has actuators\r\n    if(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n    {\r\n\t\t// Rumble regardless. The problem here is that incoming rumble requests can be for motors\r\n\t\t// other than 0 - PS2 and Xbox have 2 motors. So, if the request is not for motor0, if it \r\n\t\tif(( act_num >= 0 ) && ( act_num < m_data.m_num_actuators ))\r\n        {\r\n//\t\t\tact_strength = ((float) percent * m_data.m_actuator_max[act_num] ) / 100.0f;\r\n\t\t\tact_strength = percent;\r\n\r\n            // for lack of a rounding function, perform this check here\r\n//\t\t\tif( m_data.m_actuator_max[act_num] == 1 )\r\n//\t\t\t{\r\n//\t\t\t\tif( act_strength > 0.0f )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tm_data.m_actuator_direct[act_num] = 1;\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tm_data.m_actuator_direct[act_num] = 0;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\tm_data.m_actuator_direct[act_num] = (unsigned char) act_strength;\r\n//\t\t\t}\r\n\t\t\tm_data.m_actuator_direct[act_num] = ( act_strength > 0.0f ) ? 1 : 0;\r\n            \r\n\t\t\t// If either tracked motor is on, rumble the single motor, otherwise turn it off.\r\n\t\t\tPADControlMotor( m_data.m_port, (( m_data.m_actuator_direct[0] > 0 ) || ( m_data.m_actuator_direct[1] > 0 )) ? PAD_MOTOR_RUMBLE : PAD_MOTOR_STOP );\r\n        }\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/* These disable or enable pad vibration.\r\n/******************************************************************/\r\nvoid Device::DisableActuators()\r\n{\r\n\t// If disabled already do nothing.\r\n\tif (m_data.m_actuators_disabled)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\t// Run through all the actuators and make sure they're off.\r\n    if(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n    {\r\n\t\tfor (int i=0; i<m_data.m_num_actuators; ++i)\r\n\t\t{\r\n\t\t\t// Switch it off.\r\n\t\t\tm_data.m_actuator_direct[i] = 0;\r\n\t\t}\t\r\n\r\n        //scePadSetActDirect( m_data.m_port, m_data.m_slot, m_data.m_actuator_direct );\r\n\t\tPADControlMotor( m_data.m_port, PAD_MOTOR_STOP );\r\n\t}\t\r\n\t\r\n\t// Set the flag.\r\n\tm_data.m_actuators_disabled=true;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Device::EnableActuators( void )\r\n{\r\n\tm_data.m_actuators_disabled=false;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Device::ResetActuators( void )\r\n{\r\n\tif (m_data.m_actuators_disabled)\r\n\t{\r\n\t\t// If disabled, then should be off anyway\r\n\t\t// but toggle the states to make sure\r\n\t\tEnableActuators();\r\n\t\tDisableActuators();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// If enabled, then we disable them, which switched them off\r\n\t\t// and then enable them again (in the off position).\r\n\t\tDisableActuators();\r\n\t\tEnableActuators();\r\n\t}\r\n\t\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Ken: This gets called for each pad device when the game gets   */\r\n/* paused. It remembers whether the pad was vibrating & switches  */\r\n/* off vibration.\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::Pause()\r\n{\r\n\t// If paused already do nothing.\r\n\tif( !m_data.m_paused_ref.InUse())\r\n\t{\t\t\r\n\t    // First, make sure we're in a ready state and our controller has actuators\r\n\t    if(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n\t\t{\r\n\t\t\tfor (int i=0; i<m_data.m_num_actuators; ++i)\r\n\t\t\t{\r\n\t\t\t\t// Save the old actuator vibration strength.\r\n\t\t\t\tm_data.m_actuator_old_direct[i]=m_data.m_actuator_direct[i];\r\n\r\n\t\t\t\t// Then switch it off.\r\n\t\t\t\tm_data.m_actuator_direct[i] = 0;\r\n\t\t\t}\t\r\n\t\t\tPADControlMotor( m_data.m_port, PAD_MOTOR_STOP );\r\n\t\t}\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Just to be sure, ensure the motor is stopped.\t\t\r\n\t\tPADControlMotor( m_data.m_port, PAD_MOTOR_STOP );\r\n\t}\r\n\t\r\n\tm_data.m_paused_ref.Acquire();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Restores the vibration status.                                 */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::UnPause()\r\n{\r\n\t// If not paused, do nothing.\r\n\tif( m_data.m_paused_ref.InUse())\r\n\t{\t\t\r\n\t\tm_data.m_paused_ref.Release();\r\n\t\tif( !m_data.m_paused_ref.InUse())\r\n\t\t{\r\n\t\t    // First, make sure we're in a ready state and our controller has actuators\r\n\t\t    if(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n\t\t    {\r\n\t\t\t\tfor( int i = 0; i < m_data.m_num_actuators; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Restore the saved vibration strength.\r\n\t\t\t\t\tm_data.m_actuator_direct[i]=m_data.m_actuator_old_direct[i];\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// If either tracked motor is on, rumble the single motor, otherwise turn it off.\r\n\t\t\t\tPADControlMotor( m_data.m_port, (( m_data.m_actuator_direct[0] > 0 ) || ( m_data.m_actuator_direct[1] > 0 )) ? PAD_MOTOR_RUMBLE : PAD_MOTOR_STOP );\r\n\r\n//\t\t\t\tscePadSetActDirect( m_data.m_port, m_data.m_slot, m_data.m_actuator_direct );\r\n\t\t\t}\t\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n// Switches off vibration, and also zeros the saved\r\n// vibration levels too so that unpausing will not \r\n// switch them on again for goodness sake.         \r\nvoid Device::StopAllVibrationIncludingSaved()\r\n{\r\n\t// First, make sure we're in a ready state and our controller has actuators\r\n\tif(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n\t{\r\n\t\tfor (int i=0; i<m_data.m_num_actuators; ++i)\r\n\t\t{\r\n\t\t\tm_data.m_actuator_direct[i]=0;\r\n\t\t\tm_data.m_actuator_old_direct[i]=0;\r\n\t\t}\t\r\n\t\tPADControlMotor( m_data.m_port, (( m_data.m_actuator_direct[0] > 0 ) || ( m_data.m_actuator_direct[1] > 0 )) ? PAD_MOTOR_RUMBLE : PAD_MOTOR_STOP );\r\n\r\n//\t\tscePadSetActDirect( m_data.m_port, m_data.m_slot, m_data.m_actuator_direct );\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::ActivatePressureSensitiveMode( void )\r\n{\r\n    if( m_data.m_caps.TestMask( mANALOG_BUTTONS ))\r\n    {\r\n//\t\tif( scePadEnterPressMode( m_data.m_port, m_data.m_slot ) == 1 )\r\n\t\t{\r\n\t\t\tm_state = vBUSY;\r\n\t\t\tm_next_state = vACQUIRED;\r\n\t\t}\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::DeactivatePressureSensitiveMode( void )\r\n{\r\n    if( m_data.m_caps.TestMask( mANALOG_BUTTONS ))\r\n    {\r\n//\t\tif( scePadExitPressMode( m_data.m_port, m_data.m_slot ) == 1 )\r\n\t\t{\r\n\t\t\tm_state = vBUSY;\r\n\t\t\tm_next_state = vACQUIRED;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n} // namespace SIO\r\n\r\n"
  },
  {
    "path": "Code/Sys/SIO/ngc/sioman.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSYS (SYS_) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsioman.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/26/2000\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSerial IO Manager\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n#include <sys/sioman.h>\r\n#include <sys/siodev.h>\r\n//#include <sys/sio/keyboard.h>\r\n\r\n#include <gel/module.h>\r\n//#include <gel/soundfx/soundfx.h>\r\n//#include <gel/soundfx/xbox/p_sfx.h>\r\n#include <gel/music/music.h>\r\n\r\n#include <dolphin.h>\r\n#include \"sys/ngc/p_hwpad.h\"\r\n\r\n\tPADStatus padData[PAD_MAX_CONTROLLERS]; // game pad state\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace SIO\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefineSingletonClass( Manager, \"Serial IO Manager\" );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nvoid Manager::process_devices( const Tsk::Task< Manager::DeviceList >& task )\r\n{\r\n//\tDbg_AssertType ( task, Tsk::Task< INP_MANAGER::DEVICE_LIST > );\r\n\r\n\tDevice*\t\t\t\t\tdevice;\r\n\tLst::Search< Device >\t    sh;\r\n\tManager::DeviceList&\tdevice_list = task.GetData();\r\n\r\n\tdevice = sh.FirstItem ( device_list );\r\n\r\n\t// Deal with hot-switching controllers.\r\n\tu32 reset_mask = 0;\r\n\tif( padData[0].err == PAD_ERR_NO_CONTROLLER )\r\n\t{\r\n\t\treset_mask |= PAD_CHAN0_BIT;\r\n\t}\r\n\tif( padData[1].err == PAD_ERR_NO_CONTROLLER )\r\n\t{\r\n\t\treset_mask |= PAD_CHAN1_BIT;\r\n\t}\r\n\tif( reset_mask )\r\n\t{\r\n\t\tPADReset( reset_mask );\r\n\t}\r\n\r\n\twhile ( device )\r\n\t{\r\n\t\tDbg_AssertType ( device, Device );\r\n\r\n\t\tdevice->process();\r\n\t\tdevice = sh.NextItem();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nDevice* Manager::create_device( int index, int port, int slot )\r\n{\r\n    Device *device;\r\n        \r\n    device = new Device( index, port, slot );\r\n\r\n    return device;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::Manager ( void )\r\n{\r\n    int i, j, index;\r\n\r\n//\tXDEVICE_PREALLOC_TYPE xdpt[] = {{ XDEVICE_TYPE_GAMEPAD,\t\t\t4 },\r\n//\t\t\t\t\t\t\t\t\t{ XDEVICE_TYPE_MEMORY_UNIT,\t\t8 }};\r\n////\t\t\t\t\t\t\t\t\t{ XDEVICE_TYPE_DEBUG_KEYBOARD,\t1 }};\r\n//\r\n//\t// Initialize the peripherals.\r\n//\tXInitDevices( sizeof( xdpt ) / sizeof( XDEVICE_PREALLOC_TYPE ), xdpt );\r\n\r\n\t// Create the keyboard queue.\r\n//\tXInputDebugInitKeyboardQueue( &xdkp );\r\n\r\n//#\tif KEYBOARD_ON\r\n//\t// Initialize the keyboard.\r\n//\tKeyboardInit();\r\n//#\tendif\r\n\r\n    m_process_devices_task = new Tsk::Task< DeviceList > ( Manager::process_devices, m_devices );\r\n    \r\n\t// Pause briefly here to give the system time to enumerate the attached devices.\r\n//\tSleep( 500 );\r\n\r\n    index = 0;\r\n    for( i = 0; i < vMAX_PORT; i++ )\r\n    {\r\n//\t\tfor( j = 0; j < scePadGetSlotMax ( i ); j++ )\r\n\t\tfor( j = 0; j < 1; j++ )\r\n\t\t{\r\n\t\t    Device* p_device;\r\n\r\n\t\t\tif(( p_device = create_device ( index, i, j )))\r\n\t\t\t{\r\n\t\t\t\tm_devices.AddToTail( p_device->m_node );\r\n\t\t\t\tp_device->Acquire();\r\n\t\t\t\tindex++;\r\n\t\t\t}\r\n\t\t}\r\n    }\r\n    \r\n#\tif !NO_MUSIC_PLEASE\r\n\t// Moved this since the pcm stuff for ngc needs the sfx stuff initialised first.\r\n//\tPcm::Init();\r\n#\tendif\r\n\r\n    Dbg_Message( \"Initialized IOP controller lib\\n\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager( void )\r\n{\r\n    Device*\t\t\t\t\tdevice;\r\n    Device*\t\t\t\t\tnext;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    device = sh.FirstItem ( m_devices );\r\n    \r\n    while ( device )\r\n    {\r\n        Dbg_AssertType ( device, Device );\r\n    \r\n        next = sh.NextItem();\r\n    \r\n        delete device;\r\n        device = next;\r\n    }\r\n\r\n    delete m_process_devices_task;\r\n\r\n\tDbg_Message( \"Shut down IOP Controller Lib\\n\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nDevice* Manager::GetDevice( int port, int slot )\r\n{\r\n    Device*\t\t\t\t\tdevice;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    device = sh.FirstItem ( m_devices );\r\n    \r\n    for( device = sh.FirstItem ( m_devices ); device;\r\n            device = sh.NextItem ())\r\n    {\r\n        if( ( device->GetPort() == port ) &&\r\n            ( device->GetSlot() == slot ))\r\n        {\r\n            return device;\r\n        }\r\n    }\r\n    \r\n    return NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nDevice* Manager::GetDeviceByIndex( int index )\r\n{\r\n    Device*\t\t\t\t\tdevice;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    device = sh.FirstItem ( m_devices );\r\n    \r\n    for( device = sh.FirstItem ( m_devices ); device;\r\n            device = sh.NextItem ())\r\n    {\r\n        if( device->GetIndex() == index )\r\n        {\r\n            return device;\r\n        }\r\n    }\r\n    \r\n    return NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::Pause()\r\n{\r\n    Device*\t\t\t\t\tdevice;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    for( device = sh.FirstItem( m_devices ); device; device = sh.NextItem())\r\n    {\r\n\t\tdevice->Pause();\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::UnPause( void )\r\n{\r\n    Device*\t\t\t\t\tdevice;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    for( device = sh.FirstItem( m_devices ); device; device = sh.NextItem())\r\n    {\r\n\t\tdevice->UnPause();\r\n    }\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace SIO\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/SIO/siodev.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSYS (SYS_) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsiodev.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/26/2000\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGeneric input device\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <stdlib.h>\r\n#include <string.h>\r\n         \r\n#include <core/defines.h>\r\n#include <sys/sioman.h>\r\n#include <sys/mem/memman.h>\r\n#include <libpad.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace SIO\r\n{\r\n  \r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n    \r\nvoid Device::process( void )\r\n{\r\n    \r\n\r\n    switch( m_state )\r\n    {\r\n\r\n    case vIDLE:\r\n        break;\r\n\r\n    case vBUSY:\r\n        wait();\r\n        break;\r\n\r\n    case vACQUIRING:\r\n        acquisition_pending();\r\n        break;\r\n\r\n\tcase vPRESS_MODE_ON_COMPLETE:\r\n\t\tm_data.m_button_mode = vANALOG;\r\n\t\tm_state = vACQUIRED;\r\n\t\tbreak;\r\n\r\n\tcase vPRESS_MODE_OFF_COMPLETE:\r\n\t\tm_data.m_button_mode = vDIGITAL;\r\n\t\tm_state = vACQUIRED;\r\n\t\tbreak;\r\n\t\r\n    case vACQUIRED:\r\n        read_data();\r\n        break;\r\n\r\n    default:\r\n        break;\r\n\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::wait( void )\r\n{\r\n    \r\n\r\n    Dbg_MsgAssert(( m_next_state >= 0 ) && ( m_next_state <= vNUM_STATES ),( \"No next state set for wait state\" ));\r\n\r\n    if( scePadGetReqState( m_data.m_port, m_data.m_slot ) != scePadReqStateBusy )\r\n    {\r\n        if( get_status() != vNOTREADY )\r\n        {\r\n            m_state = m_next_state;\r\n            m_next_state = vIDLE;\r\n        }\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::read_data ( void )\r\n{\r\n    \r\n\r\n    int state;\r\n\r\n    state = scePadGetState( m_data.m_port, m_data.m_slot );\r\n\r\n    switch ( state )\r\n    {\r\n    case scePadStateFindCTP1:\r\n    case scePadStateStable:\r\n        if( scePadRead( m_data.m_port, m_data.m_slot, m_data.m_control_data ) > 0 )\r\n        {\r\n            m_data.m_valid = true;\r\n\t\t\tm_plugged_in=true;\r\n        }\r\n        else\r\n        {\r\n            m_data.m_valid = false;\r\n        }\r\n        break;\r\n\r\n    case scePadStateDiscon:\r\n        // We lost connection to the controller. Try to reacquire it\r\n        // Also, display message if it is required.\r\n\t\tm_plugged_in=false;\r\n        Unacquire();\r\n        Acquire();\r\n        break;\r\n    }                  \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool Device::IsPluggedIn()\r\n{\r\n    \r\n\treturn m_plugged_in;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::acquisition_pending( void )\r\n{\r\n    \r\n\r\n    int status;\r\n\r\n    status = get_status();\r\n                        \r\n    if(( status == vCONNECTED ) || ( status == vREADY ))\r\n    {\r\n        // sucessful.  Now query the controller for capabilities\r\n        query_capabilities();\r\n    }\r\n        \r\n\t// failed to acquire controller\r\n\t// stay in this state and continue to try to acquire it or prompt the user if it is mandatory\r\n\t// that they have a controller in   \r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::query_capabilities( void )\r\n{   \r\n    \r\n\r\n    int id, ex_id;\r\n\r\n    // Get controller ID\r\n    id = scePadInfoMode( m_data.m_port, m_data.m_slot, InfoModeCurID, 0 );\r\n    \r\n    if( id == 0 )\r\n    {\r\n        Dbg_Warning( \"Unsupported controller or controller disconnected\" );\r\n        Unacquire();\r\n        return;\r\n    }\r\n\r\n    // Get extended ID, if one exists\r\n    ex_id = scePadInfoMode( m_data.m_port, m_data.m_slot, InfoModeCurExID, 0 );\r\n    // if we have a valid extended ID, use it instead\r\n    if( ex_id > 0 )\r\n    { \r\n        id = ex_id;\r\n    }\r\n    \r\n    m_data.m_type = id;\r\n\tm_data.m_button_mode = vDIGITAL;\r\n\r\n    switch( id )\r\n    {   \r\n    case vNEGI_COM:\r\n        Dbg_Message( \"Detected NeGi-CON Controller in %d:%d\", m_data.m_port, m_data.m_slot );\r\n        break;\r\n\r\n    case vKONAMI_GUN:\r\n        Dbg_Message( \"Detected GunCON(Konami) Controller in %d:%d\", m_data.m_port, m_data.m_slot );\r\n        break;\r\n\r\n    case vDIGITAL_CTRL:\r\n        Dbg_Message( \"Detected Digital Controller in %d:%d\", m_data.m_port, m_data.m_slot );\r\n        // Switch to Analog if it's supported\r\n        if( scePadInfoMode( m_data.m_port, m_data.m_slot, InfoModeCurExID, 0 ) != 0 )\r\n        {   \r\n            if( scePadSetMainMode( m_data.m_port, m_data.m_slot, 1, 3 ) == 0 )\r\n            {\r\n                Dbg_Warning( \"scePadSetMainMode not sent properly\" );\r\n            }\r\n\t\t\t// Return so that we stay in this state and re-query as an analog controller\r\n\t\t\treturn;\r\n        }\r\n        \r\n        break;\r\n\r\n    case vJOYSTICK:\r\n        Dbg_Message( \"Detected Analog Joystick in %d:%d\", m_data.m_port, m_data.m_slot );\r\n        break;\r\n\r\n    case vNAMCO_GUN:\r\n        Dbg_Message( \"Detected GunCON(NAMCO) Controller in %d:%d\", m_data.m_port, m_data.m_slot );\r\n        break;\r\n\r\n\r\n    case vANALOG_CTRL:\r\n        {\r\n            int i, j;\r\n\r\n            Dbg_Message( \"Detected Analog Controller in %d:%d\", m_data.m_port, m_data.m_slot );\r\n            m_data.m_caps.SetMask( mANALOG );\r\n            // check if it's a dual shock 2\r\n\t\t\tif( scePadInfoPressMode( m_data.m_port, m_data.m_slot ) == 1 )\r\n\t\t\t{\r\n\t\t\t\tm_data.m_caps.SetMask( mANALOG_BUTTONS );\r\n\t\t\t}\r\n\r\n            // check for actuator support\r\n            if(( m_data.m_num_actuators = scePadInfoAct( m_data.m_port, m_data.m_slot, -1, 0 )) > 0 )\r\n            {\r\n                m_data.m_caps.SetMask( mACTUATORS );\r\n\r\n                for( i = 0; i < m_data.m_num_actuators; i++ )\r\n                {\r\n                    int power;\r\n\r\n                    power = scePadInfoAct( m_data.m_port, m_data.m_slot, i, InfoActSize );\r\n                    if( power == 0 )\r\n                    {\r\n                        m_data.m_actuator_max[i] = 1;\r\n                    }\r\n                    else\r\n                    {\r\n                        m_data.m_actuator_max[i] = 255;\r\n                    }\r\n\t            }\r\n\r\n                for( i = 0; i < m_data.m_num_actuators; i++ )\r\n                {\r\n                    m_data.m_actuator_align[ i ] = i;\r\n                }\r\n\r\n                for( j = i; j < 6; j++ )\r\n                {\r\n                    m_data.m_actuator_align[ j ] = 0xFF;\r\n                }\r\n                \r\n                if( scePadSetActAlign( m_data.m_port, m_data.m_slot, m_data.m_actuator_align ) == 0 )\r\n                {\r\n                    Dbg_Warning( \"scePadSetActAlign not sent properly\" );\r\n                }\r\n\r\n                m_state = vBUSY;\r\n                m_next_state = vACQUIRED;\r\n                return;\r\n            }\r\n            break;\r\n        }\r\n        \r\n    case vFISHING_CTRL:\r\n        Dbg_Message( \"Detected TSURI-CON(fishing) Controller in %d:%d\", m_data.m_port, m_data.m_slot );\r\n        break;\r\n        \r\n    case vJOG_CTRL:\r\n        Dbg_Message( \"Detected JOG-CON Controller in %d:%d\", m_data.m_port, m_data.m_slot );\r\n        break;\r\n\r\n    default:\r\n        Dbg_Message( \"Detected Controller of unknown type in %d:%d\", m_data.m_port, m_data.m_slot );\r\n        break;\r\n    }\r\n\r\n    m_state = vACQUIRED;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nint Device::get_status( void )\r\n{\r\n    \r\n\r\n    int state;\r\n\r\n    state = scePadGetState( m_data.m_port, m_data.m_slot );\r\n    switch ( state )\r\n    {\r\n        \r\n    case scePadStateFindCTP1:\r\n    \treturn vREADY;\r\n\t\t\r\n\tcase scePadStateStable:   \r\n        return vCONNECTED;\r\n\r\n    case scePadStateError:\r\n    case scePadStateDiscon:\r\n\tcase scePadStateClosed:\r\n\t\tm_plugged_in = false;\r\n        // problems with controller connection\r\n\t\treturn vDISCONNECTED;\r\n\r\n    case scePadStateFindPad:\r\n    case scePadStateExecCmd:\r\n\t\treturn vNOTREADY;\r\n\r\n    default:\r\n        Dbg_MsgAssert( 0,( \"Unhandled Controller Pad State\" ));\r\n        return vREADY;\r\n    }                 \r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDevice::Device ( int index, int port, int slot )\r\n{\r\n\tm_node = new Lst::Node< Device > ( this );\r\n\tDbg_AssertType ( m_node, Lst::Node< Device > );\r\n\r\n    Dbg_Assert( port < vMAX_PORT );\r\n    Dbg_Assert( slot < vMAX_SLOT );\r\n\r\n    m_state = vIDLE;\r\n    m_next_state = vIDLE;\r\n    m_index = index;\r\n\r\n    // Initialize device\r\n    m_data.m_port = port;\r\n    m_data.m_slot = slot;\r\n    m_data.m_caps.ClearAll();\r\n    m_data.m_num_actuators = 0;\r\n\tm_data.m_button_mode = vDIGITAL;\r\n    m_data.m_valid = false;\r\n\r\n\tm_plugged_in = true;\r\n    \r\n    \r\n    memset( m_data.m_actuator_direct, 0, ACTUATOR_BUFFER_LENGTH );\r\n    memset( m_data.m_actuator_align, 0xFF, ACTUATOR_BUFFER_LENGTH );\r\n    m_data.m_actuator_align[0] = 0;\r\n    m_data.m_actuator_align[1] = 1;\r\n\r\n    memset( m_data.m_control_data, 0, CTRL_BUFFER_LENGTH );\r\n\tm_data.m_prealbuffer = Mem::Malloc( scePadDmaBufferMax * sizeof( uint128) + 63 );\r\n\tm_data.m_dma_buff =  (unsigned char*)((((uint32)m_data.m_prealbuffer)+63)&~63);\r\n\t\r\n    memset( m_data.m_dma_buff, 0, sizeof( uint128 ) * scePadDmaBufferMax );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nDevice::~Device ( void )\r\n{\r\n\t\r\n\r\n\tDbg_AssertType ( m_node, Lst::Node< Device > );\r\n\tMem::Free( m_data.m_prealbuffer );\r\n\tdelete m_node;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::Acquire ( void )\r\n{\r\n    \r\n    \r\n    Dbg_Message( \"Acquiring controller port %d slot %d\\n\", m_data.m_port, m_data.m_slot );\r\n\r\n    if( m_state == vIDLE )\r\n    {\r\n        if( scePadPortOpen( m_data.m_port, m_data.m_slot, (uint128*)m_data.m_dma_buff ) == 1 )\r\n        {   \r\n            memset( m_data.m_control_data, 0, CTRL_BUFFER_LENGTH );\r\n            \r\n            m_data.m_valid = false;\r\n            m_state = vACQUIRING;\r\n        }\r\n        else\r\n        {\r\n            Dbg_Warning( \"failed to open controller port %d slot %d\\n\", m_data.m_port, m_data.m_slot );\r\n        }\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\t\r\nvoid Device::Unacquire ( void )\r\n{\r\n    \r\n\r\n    Dbg_Message( \"Unacquiring controller port %d slot %d\\n\", m_data.m_port, m_data.m_slot );\r\n\r\n    if( m_state == vACQUIRED )\r\n    {\r\n        if( scePadPortClose( m_data.m_port, m_data.m_slot ) != 1 )\r\n        {\r\n            Dbg_Warning( \"failed to close controller port %d slot %d\\n\", m_data.m_port, m_data.m_slot );\r\n        }\r\n    }\r\n\r\n    m_state = vIDLE;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::ActivateActuator( int act_num, int percent )\r\n{\r\n\r\n\r\n\t\r\n\t// Do nothing if the actuators are disabled.\r\n\tif (m_data.m_actuators_disabled)\r\n\t{\r\n\t\treturn;\r\n\t}\t\r\n\t\r\n    float act_strength;\r\n    \r\n    // First, make sure we're in a ready state and our controller has actuators\r\n    if(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n    {\r\n        if(( act_num >= 0 ) && ( act_num < m_data.m_num_actuators ))\r\n        {\r\n            act_strength = ((float) percent * m_data.m_actuator_max[act_num] ) / 100.0f;\r\n            // for lack of a rounding function, perform this check here\r\n            if( m_data.m_actuator_max[act_num] == 1 )\r\n            {\r\n                if( act_strength > 0.001f )\r\n                {\r\n                    m_data.m_actuator_direct[act_num] = 1;\r\n                }\r\n                else\r\n                {\r\n                    m_data.m_actuator_direct[act_num] = 0;\r\n                }\r\n            }\r\n            else\r\n            {\r\n                m_data.m_actuator_direct[act_num] = (unsigned char) act_strength;\r\n            }\r\n            \r\n            scePadSetActDirect( m_data.m_port, m_data.m_slot, m_data.m_actuator_direct );\r\n        }\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/* These disable or enable pad vibration.\r\n/******************************************************************/\r\nvoid Device::DisableActuators()\r\n{\r\n    \r\n\r\n\t// If disabled already do nothing.\r\n\tif (m_data.m_actuators_disabled)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\t\r\n\t// Run through all the actuators and make sure they're off.\r\n    if(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n    {\r\n\t\tfor (int i=0; i<m_data.m_num_actuators; ++i)\r\n\t\t{\r\n\t\t\t// Switch it off.\r\n\t\t\tm_data.m_actuator_direct[i] = 0;\r\n\t\t}\t\r\n        scePadSetActDirect( m_data.m_port, m_data.m_slot, m_data.m_actuator_direct );\r\n\t}\t\r\n\t\r\n\t// Set the flag.\r\n\tm_data.m_actuators_disabled=true;\r\n}\r\n\r\nvoid Device::EnableActuators()\r\n{\r\n    \r\n\tm_data.m_actuators_disabled=false;\r\n}\r\n\r\n\r\nvoid Device::ResetActuators()\r\n{\r\n\tif (m_data.m_actuators_disabled)\r\n\t{\r\n\t\t// If disabled, then should be off anyway\r\n\t\t// but toggle the states to make sure\r\n\t\tEnableActuators();\r\n\t\tDisableActuators();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// If enabled, then we disable them, which switched them off\r\n\t\t// and then enable them again (in the off position).\r\n\t\tDisableActuators();\r\n\t\tEnableActuators();\r\n\t}\r\n\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Ken: This gets called for each pad device when the game gets   */\r\n/* paused. It remembers whether the pad was vibrating & switches  */\r\n/* off vibration.\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::Pause()\r\n{\r\n    \r\n\r\n\tif (!m_data.m_paused_ref.InUse())\r\n\t{\r\n\t\t// First, make sure we're in a ready state and our controller has actuators\r\n\t\tif(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n\t\t{\r\n\t\t\tfor (int i=0; i<m_data.m_num_actuators; ++i)\r\n\t\t\t{\r\n\t\t\t\t// Save the old actuator vibration strength.\r\n\t\t\t\tm_data.m_actuator_old_direct[i]=m_data.m_actuator_direct[i];\r\n\t\t\t\t// Then switch it off.\r\n\t\t\t\tm_data.m_actuator_direct[i] = 0;\r\n\t\t\t}\t\r\n\t\t\tscePadSetActDirect( m_data.m_port, m_data.m_slot, m_data.m_actuator_direct );\r\n\t\t}\t\r\n\t}\t\r\n\t\r\n\tm_data.m_paused_ref.Acquire();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/* Restores the vibration status.                                 */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::UnPause()\r\n{\r\n    \r\n\t\r\n\tif (m_data.m_paused_ref.InUse())\r\n\t{\r\n\t\tm_data.m_paused_ref.Release();\r\n\t\tif (!m_data.m_paused_ref.InUse())\r\n\t\t{\r\n\t\t\t// First, make sure we're in a ready state and our controller has actuators\r\n\t\t\tif(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n\t\t\t{\r\n\t\t\t\tfor (int i=0; i<m_data.m_num_actuators; ++i)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Restore the saved vibration strength.\r\n\t\t\t\t\tm_data.m_actuator_direct[i]=m_data.m_actuator_old_direct[i];\r\n\t\t\t\t}\t\r\n\t\t\t\tscePadSetActDirect( m_data.m_port, m_data.m_slot, m_data.m_actuator_direct );\r\n\t\t\t}\t\r\n\t\t}\t\r\n\t}\r\n}\r\n\r\n// Switches off vibration, and also zeros the saved\r\n// vibration levels too so that unpausing will not \r\n// switch them on again for goodness sake.         \r\nvoid Device::StopAllVibrationIncludingSaved()\r\n{\r\n\t// First, make sure we're in a ready state and our controller has actuators\r\n\tif(( m_state == vACQUIRED ) && ( m_data.m_caps.TestMask( mACTUATORS )))\r\n\t{\r\n\t\tfor (int i=0; i<m_data.m_num_actuators; ++i)\r\n\t\t{\r\n\t\t\tm_data.m_actuator_direct[i]=0;\r\n\t\t\tm_data.m_actuator_old_direct[i]=0;\r\n\t\t}\t\r\n\t\tscePadSetActDirect( m_data.m_port, m_data.m_slot, m_data.m_actuator_direct );\r\n\t}\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::ActivatePressureSensitiveMode( void )\r\n{\r\n    \r\n\r\n    if( m_data.m_caps.TestMask( mANALOG_BUTTONS ))\r\n    {\r\n        if( scePadEnterPressMode( m_data.m_port, m_data.m_slot ) == 1 )\r\n        {\r\n            m_state = vBUSY;\r\n            m_next_state = vPRESS_MODE_ON_COMPLETE;\r\n        }\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Device::DeactivatePressureSensitiveMode( void )\r\n{\r\n    \r\n\r\n    if( m_data.m_caps.TestMask( mANALOG_BUTTONS ))\r\n    {\r\n        if( scePadExitPressMode( m_data.m_port, m_data.m_slot ) == 1 )\r\n        {\r\n            m_state = vBUSY;\r\n            m_next_state = vPRESS_MODE_OFF_COMPLETE;\r\n        }\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n} // namespace SIO\r\n"
  },
  {
    "path": "Code/Sys/SIO/sioman.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSYS (SYS_) \t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsioman.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/26/2000\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSerial IO Manager\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <string.h>\r\n#include <sifdev.h>\r\n#include <sifrpc.h>\r\n\r\n#include <core/defines.h>\r\n\r\n#include <sys/sioman.h>\r\n#include <sys/siodev.h>\r\n#include <sys/sio/keyboard.h>\r\n#include <sys/file/filesys.h>\r\n#include <sys/file/AsyncFilesys.h>\r\n#include <sys/config/config.h>\r\n#include <gel/module.h>\r\n\r\n#include <libpad.h>\r\n#include <libcdvd.h>\r\n//#include <libmtap.h>\r\n\r\n#include <libsdr.h>\r\n#include <sdrcmd.h>\r\n\r\n#include <sif.h>\r\n#include <sifcmd.h>\r\n#include <sifrpc.h>\r\n\r\n#include <gel/soundfx/soundfx.h>\r\n#include <gel/soundfx/ngps/p_sfx.h>\r\n#include <gel/music/music.h>\r\n\r\n#include <dnas/dnas2.h>\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n       \r\nnamespace SIO\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDefineSingletonClass( Manager, \"Serial IO Manager\" );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define CD_TEST 0\r\n#if CD_TEST\r\nstatic void cd_test()\r\n{\r\n\tint i;\r\n\tint\tdisk_type = SCECdDVD;\r\n\r\n\tsceCdInit(SCECdINIT);\r\n\tsceCdMmode(disk_type);\r\n\tprintf(\" sceCdGetDiskType   \");\r\n\tint detected_disk_type= sceCdGetDiskType();\r\n\tswitch(detected_disk_type)\r\n\t{\r\n\t\tcase SCECdIllgalMedia:\r\n\t\tprintf(\"Disk Type= IllgalMedia\\n\"); break;\r\n\t\tcase SCECdPS2DVD:\r\n\t\tprintf(\"Disk Type= PlayStation2 DVD\\n\"); break;\r\n\t\tcase SCECdPS2CD:\r\n\t\tprintf(\"Disk Type= PlayStation2 CD\\n\"); break;\r\n\t\tcase SCECdPS2CDDA:\r\n\t\tprintf(\"Disk Type= PlayStation2 CD with CDDA\\n\"); break;\r\n\t\tcase SCECdPSCD:\r\n\t\tprintf(\"Disk Type= PlayStation CD\\n\"); break;\r\n\t\tcase SCECdPSCDDA:\r\n\t\tprintf(\"Disk Type= PlayStation CD with CDDA\\n\"); break;\r\n\t\tcase SCECdDVDV:\r\n\t\tprintf(\"Disk Type= DVD video\\n\"); break;\r\n\t\tcase SCECdCDDA:\r\n\t\tprintf(\"Disk Type= CD-DA\\n\"); break;\r\n\t\tcase SCECdDETCT:\r\n\t\tprintf(\"Working\\n\"); break;\r\n\t\tcase SCECdNODISC: \r\n\t\tprintf(\"Disk Type= No Disc\\n\"); break;\r\n\t\tdefault:\r\n\t\tprintf(\"Disk Type= OTHER DISK\\n\"); break;\r\n\t}\r\n\r\n\t// If disk type has changed to a CD, then need to re-initialize it\t\t\t\t\t\t\t   \r\n\tif ((detected_disk_type == SCECdPS2CD) || (detected_disk_type == SCECdPSCD))\r\n\t{\r\n\t\tdisk_type = SCECdCD;\r\n\t\tsceCdMmode(disk_type);\r\n\t}\r\n\t// This next bit is essential for when making a bootable disc, ie one that will\r\n\t// boot on the actual PS rather than just the dev system.\r\n\t// K: Commented out __NOPT_BOOTABLE__, since it is set when __NOPT_CDROM__OLD is set.\r\n\r\n\t/* Reboot IOP, replace default modules  */\r\n\tchar  path[128];\r\n\t\r\n\t// THIS CODE IS NOT USED - JUST A TEST FUNCTION!!!!!\r\n\tsprintf(path,\"host0:\\\\SKATE5\\\\DATA\\\\IOPMODULES\\\\DNAS280.IMG\");\t   // ALSO NEED TO CHANGE In p_filesys.cpp\r\n\t\r\n\t\r\n\twhile ( !sceDNAS2NetSifRebootIop(path) ); /* (Important) Unlimited retries */\r\n\twhile( !sceSifSyncIop() );\r\n\r\n\t/* Reinitialize */\r\n\tsceSifInitRpc(0);\r\n\tsceCdInit(SCECdINIT);\r\n\r\n\tsceCdMmode(disk_type);   /* Media: CD-ROM */\r\n\r\n\tsceFsReset();\r\n\r\n\tint fd = sceDopen(\"cdrom0:\");\r\n\tif (fd >= 0)\r\n\t{\r\n\t\tstruct sce_dirent dir_entry;\r\n\t\tDbg_Message(\"Reading directory\");\r\n\t\twhile (sceDread(fd, &dir_entry) > 0)\r\n\t\t{\r\n\t\t\tDbg_Message(\"Found entry %s\", dir_entry.d_name);\r\n\t\t}\r\n\t\tsceDclose(fd);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Couldn't open directory, try raw read\r\n\t\tuint32 buffer[512 + 16];\r\n\t\tfor (i = 0; i < 512; i++)\r\n\t\t{\r\n\t\t\tbuffer[i] = 0xDEADBEEF;\r\n\t\t}\r\n\r\n\t\tsceCdRMode mode;\r\n\t\tmode.trycount = 255;\r\n\t\tmode.spindlctrl = SCECdSpinNom;\r\n\t\tmode.datapattern = SCECdSecS2048;\r\n\t\tmode.pad = 0;\r\n\r\n\t\tint ret_val = sceCdRead(0, 1, buffer, &mode);\r\n\t\tif (ret_val == 1)\r\n\t\t{\r\n\t\t\tsceCdSync(0);\r\n\t\t\tDbg_Message(\"Read Sector, here is the dump (make sure you don't see 0xDEADBEEF in data)\");\r\n\r\n\t\t\t// Read data, print it\r\n\t\t\tfor (i = 0; i < 512; i += 4)\r\n\t\t\t{\r\n\t\t\t\tDbg_Message(\"0x%08x 0x%08x 0x%08x 0x%08x\", buffer[i], buffer[i + 1], buffer[i + 2], buffer[i + 3]);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDbg_Message(\"Couldn't Read Sector. Error = %x\", sceCdGetError());\r\n\t\t}\r\n\t}\r\n\tDbg_Assert(0);\r\n}\r\n#endif\r\n\r\nvoid\t\tManager::process_devices( const Tsk::Task< Manager::DeviceList >& task )\r\n{\r\n\t\r\n//\tDbg_AssertType ( task, Tsk::Task< INP_MANAGER::DEVICE_LIST > );\r\n\r\n\tDevice*\t\t\t\t\tdevice;\r\n\tLst::Search< Device >\t    sh;\r\n\tManager::DeviceList&\tdevice_list = task.GetData();\r\n\r\n\tdevice = sh.FirstItem ( device_list );\r\n\r\n\twhile ( device )\r\n\t{\r\n\t\tDbg_AssertType ( device, Device );\r\n\r\n\t\tdevice->process();\r\n\t\tdevice = sh.NextItem();\r\n\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nDevice* Manager::create_device( int index, int port, int slot )\r\n{\r\n    \r\n\r\n    Device *device;\r\n        \r\n    device = new Device( index, port, slot );\r\n\r\n    return device;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n#define MAX_IRX_NAME_CHARS 100\r\nstatic char pIRXNameBuf[MAX_IRX_NAME_CHARS+1];\r\n\r\n// Loads an IRX file. The name must not have the .irx extension, it gets added by the function.\r\n// Returns 0 if successful, -1 if error. (But it will assert in debug mode)\r\nint LoadIRX(const char *pName, int num_args, char* args, bool assert_on_fail)\r\n{\r\n    \r\n\t\r\n\tFile::StopStreaming( );\r\n\tif ( Pcm::UsingCD( ) )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Using CD returned TRUE.\" ));\r\n\t\treturn ( -1 );\r\n\t}\r\n\r\n\t// Start the name with the appropriate thingy.\r\n\tif (Config::CD())\r\n\t{\r\n\t\tDbg_MsgAssert(strlen(\"cdrom0:\\\\xxxxxxxxxxxxxxxxxIOP\\\\\")+strlen(pName)+strlen(\".IRX\")<=MAX_IRX_NAME_CHARS,(\"String in pName is too long.\"));\r\n\t\tchar  path[128];\r\n\t\tsprintf(path,\"cdrom0:\\\\%sIOP\\\\\",Config::GetDirectory());\r\n\t\tstrcpy(pIRXNameBuf,path);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDbg_MsgAssert(strlen(\"host0:IOPModules/\")+strlen(pName)+strlen(\".IRX\")<=MAX_IRX_NAME_CHARS,(\"String in pName is too long.\"));\r\n\t\tstrcpy(pIRXNameBuf,\"host0:IOPModules/\");\r\n\t}\t\r\n\t\r\n\t// Append the name in upper case.\r\n\tchar *pDest=pIRXNameBuf+strlen(pIRXNameBuf);\r\n\tconst char *pSource=pName;\r\n\twhile (*pSource)\r\n\t{\r\n\t\tchar ch=*pSource++;\r\n\t\tif (ch>='a' && ch<='z')\r\n\t\t{\r\n\t\t\tch='A'+ch-'a';\r\n\t\t}\t\r\n\t\t*pDest++=ch;\r\n\t}\r\n\t*pDest=0;\r\n\t\r\n\t// Append the extension.\r\n\tstrcat(pIRXNameBuf,\".IRX\");\r\n\t\r\n\tint result;\r\n\tif(( result = sceSifLoadModule(pIRXNameBuf, num_args, args )) < 0 )\r\n\t{\r\n\t\tDbg_MsgAssert( !assert_on_fail,( \"Can't load module %s. Result: %d\\n\",pIRXNameBuf, result ));\r\n\t\t\r\n\t\treturn result;\r\n\t}   \r\n\treturn 0;\t\t\r\n}\r\n\r\nManager::Manager( void )\r\n{\r\n    \r\n\r\n    int i, j, index;\r\n    Device *device;\r\n    \r\n    sceSifInitRpc(0);\r\n\r\n#if CD_TEST\r\n\tcd_test();\r\n#endif\r\n\r\n\tLoadIRX(\"sio2man\");\r\n#ifdef MULTI_TAP_SUPPORT\r\n\tLoadIRX(\"mtapman\");\r\n#endif // MULTI_TAP_SUPPORT\r\n\tLoadIRX(\"mcman\");\r\n\tLoadIRX(\"mcserv\");\r\n\tLoadIRX(\"padman\");\r\n\tLoadIRX(\"cdvdstm\");\r\n    \r\n\t// Moved the loading of the SN Stack module here from net.cpp because it seems to use some\r\n\t// temporary memory upon startup that causes it to exceed the IOP memory limit if loaded\r\n\t// last.\r\n#ifdef __NOPT_DEBUG__\r\n\tLoadIRX( \"SNSTKDBG\" );\r\n#else\r\n\tLoadIRX( \"SNSTKREL\" );\r\n#endif\r\n\r\n\tif (!Sfx::NoSoundPlease() || !Pcm::NoMusicPlease() || !Pcm::StreamsDisabled())\r\n\t{\r\n\t\tLoadIRX(\"libsd\");\t// sound chip SPU2 lib\r\n\t\tLoadIRX(\"sdrdrv\");\t// sound driver lib?\r\n\t}\r\n\r\n\t// Async file driver\r\n\tLoadIRX(\"fileio\");\r\n\t// Init the new async stuff\r\n\tFile::CAsyncFileLoader::sInit();\r\n\r\n\tif (!Sfx::NoSoundPlease() || !Pcm::NoMusicPlease() || !Pcm::StreamsDisabled())\r\n\t{\r\n\t\tLoadIRX(\"ezpcm\");\t// streaming music...\r\n\t}\r\n\r\n\tLoadIRX(\"usbd\");\t\t// usb driver\r\n\r\n\t#define ICON_FILE\t\"foo\"\t//\"mc0:BASLUS-20731/NAAPROIA/SYS_NET.ICO\"// \"foo\"\r\n\t#define ICON_SYS_FILE\t\"bar\"\t//\"mc0:BASLUS-20731/NAAPROIA/icon.sys\"// \"bar\"\r\n\r\n\tstatic char netcnfArgs[] = \"icon=\"ICON_FILE\"\\0iconsys=\"ICON_SYS_FILE;\r\n\r\n\tLoadIRX(\"netcnf\", sizeof(netcnfArgs), netcnfArgs );\r\n\r\n#if ( KEYBOARD_ON )\r\n\t// initialize the keyboard\r\n\tKeyboardInit();\r\n#endif\r\n\r\n\t// initialise IOP memory ( used for CD filesystem and for music ).\r\n\tif( sceSifInitIopHeap( ) < 0 )\r\n\t{\r\n\t\tDbg_MsgAssert( 0,( \"Failed to init IOP Heap\\n\"));\r\n\t}\r\n\r\n    if( scePadInit( 0 ) != 1 )\r\n    {\r\n        Dbg_MsgAssert( false,( \"failed to init IOP controller lib\\n\" ));\r\n    }\r\n                         \r\n#ifdef MULTI_TAP_SUPPORT\r\n    sceMtapInit();\r\n\tsceMtapPortOpen( 0 );\r\n    if( sceMtapGetConnection( 0 ) != 1 )\r\n\t{\r\n\t\tsceMtapPortClose( 0 );\r\n\t}\r\n#endif // MULTI_TAP_SUPPORT\r\n\r\n    m_process_devices_task = new Tsk::Task< DeviceList > ( Manager::process_devices, m_devices );\r\n    \r\n    index = 0;\r\n    for( i = 0; i < vMAX_PORT; i++ )\r\n    {\r\n       for( j = 0; j < scePadGetSlotMax ( i ); j++ )\r\n       {\r\n           if(( device = create_device ( index, i, j )))\r\n           {\r\n               m_devices.AddToTail( device->m_node );\r\n               device->Acquire();\r\n               index++;\r\n           }\r\n       }\r\n    }\r\n\t\r\n\tif (!Sfx::NoSoundPlease())\r\n\t{\r\n\t\tSfx::PS2Sfx_InitCold( );\r\n\t}\r\n\t\r\n\tif (!Pcm::NoMusicPlease() || !Pcm::StreamsDisabled())\r\n\t{\r\n\t\tPcm::Init( );\r\n\t}\r\n\r\n\tif (Config::CD())\r\n\t{\r\n\t\tFile::InitQuickFileSystem( );\r\n\t}\t\r\n    Dbg_Message( \"Initialized IOP controller lib\\n\" );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nManager::~Manager( void )\r\n{\r\n    \r\n\r\n    Device*\t\t\t\t\tdevice;\r\n    Device*\t\t\t\t\tnext;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    device = sh.FirstItem ( m_devices );\r\n    \r\n    while ( device )\r\n    {\r\n        Dbg_AssertType ( device, Device );\r\n    \r\n        next = sh.NextItem();\r\n    \r\n        delete device;\r\n        device = next;\r\n    }\r\n\r\n    delete m_process_devices_task;\r\n\r\n    if( scePadEnd() == 1 )\r\n    {\r\n        Dbg_Message( \"Shut down IOP Controller Lib\\n\" );\r\n    }\r\n    else\r\n    {\r\n        Dbg_MsgAssert( false,( \"Failed to shut down IOP Controller Lib\\n\" ));\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nDevice* Manager::GetDevice( int port, int slot )\r\n{\r\n    \r\n\r\n    Device*\t\t\t\t\tdevice;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    for( device = sh.FirstItem ( m_devices ); device;\r\n            device = sh.NextItem ())\r\n    {\r\n        if( ( device->GetPort() == port ) &&\r\n            ( device->GetSlot() == slot ))\r\n        {\r\n            return device;\r\n        }\r\n    }\r\n    \r\n    return NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nDevice* Manager::GetDeviceByIndex( int index )\r\n{\r\n    \r\n\r\n    Device*\t\t\t\t\tdevice;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    for( device = sh.FirstItem ( m_devices ); device;\r\n            device = sh.NextItem ())\r\n    {\r\n        if( device->GetIndex() == index )\r\n        {\r\n            return device;\r\n        }\r\n    }\r\n    \r\n    return NULL;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*  Ken: Runs through all the devices pausing each one.           */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::Pause()\r\n{\r\n    \r\n\r\n    Device*\t\t\t\t\tdevice;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    for( device = sh.FirstItem ( m_devices ); device;\r\n            device = sh.NextItem ())\r\n    {\r\n\t\tdevice->Pause();\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*  Ken: Runs through all the devices unpausing each one.         */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Manager::UnPause()\r\n{\r\n    \r\n\r\n    Device*\t\t\t\t\tdevice;\r\n    Lst::Search< Device >\tsh;\r\n    \r\n    for( device = sh.FirstItem ( m_devices ); device;\r\n            device = sh.NextItem ())\r\n    {\r\n\t\tdevice->UnPause();\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace SIO\r\n"
  },
  {
    "path": "Code/Sys/Win32/p_timer.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTimer (TMR)\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tngps/p_timer.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t09/25/00\t-\tdc\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tXBox System Timer\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <windows.h>\r\n#include <mmsystem.h>\r\n#include <time.h>\r\n#include <sys/timer.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Tmr \r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//static clock_t\t\t\tstart_count;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************\r\n\r\nManager::Manager ( void )\r\n{\r\n\tDbg_MemberFunction;\r\n\t\r\n\t// Set the start count.\r\n\tstart_count = timeGetTime();\t\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************\r\n\r\nManager::~Manager ( void )\r\n{\r\n\tDbg_MemberFunction;    \r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n \r\nTime GetTime ( void )\r\n{\r\n\treturn timeGetTime();\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n \r\nMicroSeconds GetTimeInUSeconds( void )\r\n{\r\n\treturn timeGetTime() * 1000;\r\n}\r\n\r\nfloat FrameLength()\r\n{\r\n\treturn 16;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Tmr\r\n"
  },
  {
    "path": "Code/Sys/XBox/p_timer.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTimer (TMR)\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tngps/p_timer.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t01/13/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNGPS System Timer\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <xtl.h>\r\n#include <time.h>\r\n#include <sys/timer.h>\r\n#include <sys/profiler.h>\r\n#include <sys/config/config.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Tmr \r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define vHIREZ_CMP 15000\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic volatile uint64\ts_count;\r\n\r\n#define\tvSMOOTH_N  4\t\r\n\r\nstatic volatile uint64\ts_vblank = 0;\r\nstatic volatile uint64\ts_total_vblanks = 0;\r\nstatic float\t\t\ts_slomo = 1.0f;\r\nstatic uint64\t\t\ts_render_frame = 0;\t\r\nstatic uint64\t\t\ts_stored_vblank = 0;\r\nstatic volatile bool\ts_vsync_handler_installed = false;\r\nstatic volatile bool\ts_swap_handler_installed = false;\r\n\r\nstatic clock_t\t\t\thigh_count;\r\nstatic clock_t\t\t\tstart_count;\r\nstatic __int64\t\t\thigh_count_high_precision;\r\nstatic __int64\t\t\tstart_count_high_precision;\r\n\r\nstatic uint64 GetGameVblanks();\r\n\r\nstruct STimerInfo\r\n{\r\n\tfloat\trender_length;\r\n\tdouble\tuncapped_render_length;\r\n\tint\t\trender_buffer[vSMOOTH_N];\r\n\tuint64\trender_vblank;\r\n\tuint64\trender_last_vblank;\t\r\n\tint\t\trender_index;\r\n};\r\n\r\nstatic STimerInfo gTimerInfo;\r\nstatic STimerInfo gStoredTimerInfo;\r\nstatic float xrate = 60.0f;\r\n\r\nstatic void InitTimerInfo( void )\r\n{\r\n\tstatic bool xrate_set = false;\r\n\r\n\tif( !xrate_set )\r\n\t{\r\n\t\txrate\t\t= (float)Config::FPS();\r\n\t\txrate_set\t= true;\r\n\t}\r\n\r\n\tgTimerInfo.render_length\t\t\t= 0.01666666f;\t\t// defualt to 1/60th\r\n\tgTimerInfo.uncapped_render_length\t= 0.01666666f;\t\t// defualt to 1/60th\r\n\tfor( int i = 0; i < vSMOOTH_N; i++ )\r\n\t{\r\n\t\tgTimerInfo.render_buffer[ i ] = 1;\r\n\t}\r\n\tgTimerInfo.render_vblank\t\t\t= 0;\t\r\n\tgTimerInfo.render_last_vblank\t\t= 0;\r\n\tgTimerInfo.render_index\t\t\t\t= 0;\r\n\r\n\tgStoredTimerInfo\t\t\t\t\t= gTimerInfo;\r\n\r\n\ts_stored_vblank\t\t\t\t\t\t= 0;\r\n\ts_vblank\t\t\t\t\t\t\t= 0;\r\n}\r\n\r\n//#ifdef __NOPT_PROFILE__\r\n\r\n//Sys::ProfileData\tDMAProfileData;\r\n//Sys::ProfileData\tVU1ProfileData;\r\n\r\n//#endif // __NOPT_PROFILE__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n__int64 __declspec( naked ) __stdcall getCycles( void )\r\n{\r\n\t_asm\r\n\t{\r\n\t\trdtsc\r\n\t\tret\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void __cdecl s_vsync_handler( D3DVBLANKDATA *pData )\r\n{\r\n\t// inc vblanks    \r\n\ts_vblank++;\r\n\ts_total_vblanks++;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void __cdecl s_swap_callback_handler( D3DSWAPDATA *pData )\r\n{\r\n\t// This callback function will be called when a Swap or Present is encountered by the GPU, in order to provide information as to when\r\n\t// Swap or Present calls are actually handled by the GPU. Swap and Present are like all other rendering functions in that they are enqueued\r\n\t// in the push-buffer and so the handling of the actual command is not synchronous with the actual function call.\r\n\t// Even if the Swap or Present is called by the title before a vertical blank, it may not be handled by the GPU until after the vertical blank\r\n\t// because the GPU still has to process all of the commands in the push-buffer that are before the Swap or Present.\r\n\t++s_render_frame;\r\n\t\r\n\tint diff;\r\n\tgTimerInfo.render_last_vblank\t= gTimerInfo.render_vblank;\r\n\tgTimerInfo.render_vblank\t\t= pData->SwapVBlank;\r\n\tdiff = (int)( gTimerInfo.render_vblank - gTimerInfo.render_last_vblank );\r\n\r\n\tgTimerInfo.render_buffer[gTimerInfo.render_index++]\t= diff;\r\n\r\n\t// Wrap the index around.\t\r\n\tif( gTimerInfo.render_index == vSMOOTH_N )\r\n\t{\r\n\t\tgTimerInfo.render_index = 0;\t\t\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Init( void )\r\n{\r\n\tInitTimerInfo();\r\n\t\r\n\ts_count\t\t\t\t\t\t= 0;\r\n\tstart_count\t\t\t\t\t= clock();\r\n\thigh_count\t\t\t\t\t= (clock_t)0;\r\n\tstart_count_high_precision\t= getCycles();\r\n\thigh_count_high_precision\t= (__int64)0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid DeInit( void )\r\n{\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid InstallVSyncHandlers( void )\r\n{\r\n\tif( !s_vsync_handler_installed )\r\n\t{\r\n\t\t// Install the vertical blank callback handler.\r\n\t\tD3DDevice_SetVerticalBlankCallback( s_vsync_handler );\r\n\t\ts_vsync_handler_installed = true;\r\n\t}\r\n\r\n\tif( !s_swap_handler_installed )\r\n\t{\r\n\t\t// Install the swap callback handler at this point.\r\n\t\tD3DDevice_SetSwapCallback( s_swap_callback_handler );\r\n\t\ts_swap_handler_installed = true;\r\n\t}\r\n}\r\n\r\n\r\n\r\n// when pausing the game, call this to store the current state of OncePerRender( ) (only essential in replay mode)\r\nvoid StoreTimerInfo( void )\r\n{\r\n}\r\n\r\n\r\n\r\nvoid RecallTimerInfo( void )\r\n{\r\n}\r\n\r\n\r\n\r\n// Call this function once per rendering loop, to increment the \r\n// m_render_frame variable\r\n// This function should be synchronized in some way to the vblank, so that it is called \r\n// directly after the vblank that rendering starts on\r\nvoid OncePerRender( void )\r\n{\r\n#\tifdef STOPWATCH_STUFF\r\n\tScript::IncrementStopwatchFrameIndices();\r\n\tScript::DumpFunctionTimes();\r\n\tScript::ResetFunctionCounts();\t\r\n#\tendif\r\n\r\n\tint total\t\t\t= 0;\r\n\tint uncapped_total\t= 0;\r\n\r\n\tfor( int i = 0; i < vSMOOTH_N; ++i )\r\n\t{\r\n\t\tint diff = gTimerInfo.render_buffer[i];\r\n\t\tuncapped_total += diff;\r\n\r\n\t\t// Handle very bad values.\r\n\t\tif( diff > 10 || diff < 0 )\t\t\r\n\t\t{\r\n\t\t\tdiff = 1;\r\n\t\t}\r\n\r\n\t\t// Clamp to 4.\r\n\t\tif( diff > 4 )\r\n\t\t{\r\n\t\t\tdiff = 4;\r\n\t\t}\t\t\r\n\t\ttotal += diff;\r\n\t}\r\n\r\n\tgTimerInfo.render_length = (float)total / (float)vSMOOTH_N;\r\n\r\n\tif( gTimerInfo.render_length < 1.0f )\r\n\t{\r\n\t\tgTimerInfo.render_length = 1.0f;\r\n\t}\r\n\r\n\tgTimerInfo.uncapped_render_length = (double)uncapped_total/(double)vSMOOTH_N; \r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint64 GetRenderFrame( void )\r\n{\r\n\treturn s_render_frame;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid Vblank( void )\r\n{\r\n\ts_total_vblanks++;\r\n\ts_vblank++;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic uint64 GetGameVblanks( void )\r\n{\r\n\treturn s_vblank;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nuint64 GetVblanks( void )\r\n{\r\n\treturn s_total_vblanks;\r\n}\r\n\r\n\r\n\r\n// call \"StartLogic\" when all the logic functions are going to be called  \r\n//void Manager::StartLogic()\r\n//{\r\n//}\r\n\r\n// returns the PROJECTED length of the next frame, for use in logic calculations\r\n// done by averaging the frame lengths of the last N frames (default N = 4)\r\n// at 60fps (NTSC), this would return 1/60\r\n// at 50fps (PAL), this would return 1/50\t\t   \r\n// complications arise when the framerate changes\r\n// we want the physics to move smoothly and consistently at all framerates\r\n// however, all we know is the number of ticks the last frames took\r\n// we also need to ensure that the total of all the \"FrameLength\" calls will\r\n// reflect the actual time that has passed\r\n//\t\t\t\t |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |   |    |   \r\n// say we have   1    1    1    .    2    1    1    1    .    2    1    .    2    1    1    1   .    2 \r\n//    (10x1 + 4x2  = 18 frames\r\n//\r\n//\r\n// now, let's work in 1/60ths of a second for now....\r\n// let's take the average of the last 4 frames, as the logic time we will return for this frame\r\n//\r\n//               1    1    1         1.25 1.25 1.25 1.25     1.25 1.25      1.5  1.5  1.25 1.25     1.25\r\n//\r\n// the reason we do the averaging is to smooth out discontinuities\r\n// if we simply use the length of the previous frame, then if we were to be alternating between 1 and 2 frames\r\n// then the logic would move 2 on frames of length 1, and move 1 on frames of length 2\r\n// this would essentially make the skater visually move alternately .5x and 2x his actual speed\r\n// this looks incredibly jerky, as there is a 4x difference per frame   \r\n// by smoothing it out, you would move 1.5 on every frame, giving relative motion of 0.6666 and 1.3333, \r\n// this is still jerky, but half as much as the unsmoothed version.\r\nfloat FrameLength( void )\r\n{\r\n\treturn gTimerInfo.render_length / xrate * GetSlomo();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nfloat GetSlomo( void )\r\n{\r\n\treturn s_slomo;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid SetSlomo( float slomo )\r\n{\r\n\ts_slomo = slomo;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ndouble UncappedFrameLength()\r\n{\r\n\treturn gTimerInfo.uncapped_render_length / xrate;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid VSync( void )\r\n{\r\n\tuint64 now = GetVblanks();\r\n\twhile( now == GetVblanks());\t\r\n}\r\n \r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nMicroSeconds GetTimeInUSeconds( void )\r\n{\r\n\thigh_count_high_precision = ( getCycles() - start_count_high_precision ) / 733;\r\n\treturn static_cast<Time>( high_count_high_precision );\r\n}\r\n\r\n\r\n\r\n// Added by Ken, to get higher resolution when timing Script::Update, which needs to\r\n// subtract out the time spent in calling C-functions to get an accurate measurement\r\n// of how long the actual script interpretation is taking.\r\nCPUCycles \tGetTimeInCPUCycles ( void )\r\n{\r\n\tuint64\thigh0, low0, high1, low1;\r\n\r\n    high0 = s_count;\r\n\tlow0  = 0;\r\n    high1 = s_count;\r\n    low1  = 0;\r\n\r\n    if( high0 == high1 )\r\n    {\r\n\t\treturn ((high0 * vHIREZ_CMP) + low0);\r\n    }\r\n    else\r\n    {\r\n\t\treturn ((high1 * vHIREZ_CMP) + low1);\r\n    }\r\n\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid RestartClock( void )\r\n{\r\n\tInitTimerInfo();\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nTime GetTime( void )\r\n{\r\n\t// E3 fix by Ken: Changed to do it this way because otherwise the multiply by 1000 overflows after a day or so.\r\n\t// By using 50/3 instead, and using a float, means it'll overflow after about 50 days instead.\r\n\t// The accuracy will slowly degrade over time. Stays accurate to within a few milliseconds after a week though.\r\n\t// Note: The casting of s_vblank (which is a uint64) to a uint32 before casting to a float is important. If the\r\n\t// uint64 is cast straight to a float it will do tons of floating point stuff which take ages.\r\n\treturn (uint32) (((float)(uint32)s_vblank)*(1000.0f / (float)xrate));\r\n}\r\n\r\n\r\n} // namespace Tmr\r\n\r\n"
  },
  {
    "path": "Code/Sys/demo.cpp",
    "content": "//****************************************************************************\r\n//* MODULE:         sys\r\n//* FILENAME:       Demo.cpp\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/16/2002\r\n//****************************************************************************\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <sys/demo.h>\r\n\r\n#include <core/defines.h>\r\n\r\n#include <gel/music/music.h>\r\n#include <gel/soundfx/soundfx.h>\r\n\r\n#ifdef __PLAT_NGPS__\r\n    #include <eekernel.h>\r\n    #include <eetypes.h>\r\n    #include <libcdvd.h>\r\n    #include <libpad.h>\r\n\r\n    #include <libscedemo.h>\r\n    extern\tsceDemoEndReason demo_exit_reason;\r\n    extern \"C\" void sceSifExitCmd(void);\r\n\r\n    #include <gfx/ngps/nx/nx_init.h>\r\n#endif // __PLAT_NGPS__\r\n\r\n#include <sys/config/config.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Sys\r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Externals\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __PLAT_NGPS__\r\n\r\nvoid prepare_to_exit()\r\n{\r\n\tprintf (\"******  Exiting THPS Demo *****\\n\");\r\n\r\n\t//Nx::CEngine::sSuspendEngine();\t\t// turn off Nx engine interrupts\r\n\tNxPs2::SuspendEngine();\t\t\t\t// \r\n\t\r\n\tSfx::CSfxManager* sfx_manager =  Sfx::CSfxManager::Instance();\r\n\tsfx_manager->PauseSounds( );\r\n\tif (!Config::CD())\r\n\t{\r\n\t\tprintf (\"Re-initializing the CD/DVD drive\\n\");\r\n\t\t// if we did not come from a CD, then we need to initilaize the CD here\r\n\t\t// so we can test exiting back to the bootstrap program\r\n\t    sceCdInit(SCECdINIT);\r\n\t    sceCdMmode(SCECdDVD);\r\n\t    sceCdDiskReady(0);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tprintf (\"Stopping streaming etc, on CD/DVD drive\\n\");\r\n\t\tPcm::StopStreams(  );\r\n\t\tPcm::StopMusic(  );\r\n\t\tsceCdStStop();\t\t\t\t// also stop streaming....\t   Yes!!\r\n\t\tsceCdStop();\t\t\t\t// stop Cd\r\n\t\tsceCdSync(0);\t\t\t\t// wait for commands to execute\r\n\t\tsceCdDiskReady(0);\t\t   \t// wait for Cd to be ready again\r\n\t}\t\r\n\r\n\tscePadEnd();\t\t\t\t// Another Sony reccomendation (from James Wang, newgroup post, 6/11/2002)\r\n\r\n}\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nbool LoadExec( const char* pELFName )\r\n{\r\n\r\n#ifdef __PLAT_NGPS__\r\n\tchar p_string[100];\r\n\tsprintf(p_string,\"%s;1\",pELFName);\t   \t\t// add on the ;1\r\n\r\n\tprepare_to_exit();\r\n\t\t\r\n\tsceSifExitCmd();\t\t\t// Sony suggested fix to make LoadExecPS2 work more reliably. \r\n    \r\n\tchar *args[4];\r\n\targs[0] =  \"bootstrap\";\r\n\tif (Config::NTSC())\r\n\t{\r\n\t\targs[1] =  \"cdrom0:\\\\SLUS_207.31;1\";\r\n\t\targs[2] = \"\";\r\n\t\targs[3] = \"\";\r\n\t}\r\n\telse\r\n\t{\t\r\n\t\tswitch (Config::GetLanguage())\r\n\t\t{\r\n\t\t\tcase Config::LANGUAGE_FRENCH:\r\n\t\t\t\targs[1] =  \"cdrom0:\\\\SLES_518.51;1\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase Config::LANGUAGE_GERMAN:\r\n\t\t\t\targs[1] =  \"cdrom0:\\\\SLES_518.52;1\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase Config::LANGUAGE_ITALIAN:\r\n\t\t\t\targs[1] =  \"cdrom0:\\\\SLES_518.53;1\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase Config::LANGUAGE_SPANISH:\r\n\t\t\t\targs[1] =  \"cdrom0:\\\\SLES_518.54;1\";\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tDbg_MsgAssert(0,(\"Bad Language (%d)\",(int)(Config::GetLanguage())));\r\n\t\t\t\t// allow drop through to english as a failsafe.  \r\n\t\t\tcase Config::LANGUAGE_ENGLISH:\r\n\t\t\t\targs[1] =  \"cdrom0:\\\\SLES_518.48;1\";\r\n\t\t\t\tbreak;\t\t\t\r\n\t\t}\r\n\t\targs[2] = \"PAL\";\r\n\t\targs[3] = \"Framerate=50\";\r\n\t}\r\n    printf (\"LoadExecPS2(%s) args = (%s,%s,%s,%s)\\n\",p_string, args[0], args[1], args[2], args[3] );\r\n\tLoadExecPS2(p_string, 4, args);\r\n\tprintf (\"LoadExecPS2 Failed - probably file not found, profiling on, or bad media type\\n\");\r\n//    LoadExecPS2(\"cdrom0:\\\\demo\\\\slus_201.99;1\", 2, args);\r\n   \r\n\r\n#endif\t\t// __PLAT_NGC__\r\n\treturn true;\t\t// actually will never get here}\r\n}\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n/*\r\n- TODO - factor out the common functionality of ExitDemo into LoadExecPS2\r\n\r\nthe LoadExecPS2() references lists some common gotchas:\r\n\r\nThe total size of the character strings for the filename and all of the\r\narguments must not exceed 256 bytes. \r\n\r\nNote the following points before calling LoadExecPS2(). \r\n* Terminate or delete all threads other than the thread that will \r\n  execute LoadExecPS2(). \r\n* Cancel all callbacks and interrupt handlers. \r\n* Execute scePadEnd(). \r\n* Execute sceSifExitCmd().\r\n*/\r\n\r\nbool ExitDemo()\r\n{\r\n\r\n#ifdef\t__PLAT_NGPS__\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\r\n\tprepare_to_exit();\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\r\n\twhile (1)\r\n\t{\t\t\r\n\t\tsceSifExitCmd();\t\t\t// Sony suggested fix to make LoadExecPS2 work more reliably. \r\n\t\r\n\t\tif (Config::SonyBootstrap())\r\n\t\t{\r\n\t\t\tprintf (\"Exiting with sceDemoEnd\\n\");\r\n\t\t\tsceDemoEnd(demo_exit_reason);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsceSifExitCmd();\t\t\t// Sony suggested fix to make LoadExecPS2 work more reliably. \r\n\t\t\tchar *args[] = {Config::gReturnString };\r\n\t\t\tprintf (\"Exiting with LoadExecPS2( %s [%s] )\\n\", Config::gReturnTo, Config::gReturnString); \r\n\t\t\tLoadExecPS2(Config::gReturnTo, 1, args);\r\n\t\t}\r\n\t\tprintf (\"ERROR - Failed to exit!!!!!!! RETRYING\\n\");\r\n\t}\t\t\r\n#endif\r\n   \r\n\treturn true;\t\t// actually will never get here\r\n}\r\n\r\n} // namespace Sys\r\n"
  },
  {
    "path": "Code/Sys/demo.h",
    "content": "//****************************************************************************\r\n//* MODULE:         sys\r\n//* FILENAME:       Demo.h\r\n//* OWNER:          Gary Jesdanun\r\n//* CREATION DATE:  10/16/2002\r\n//****************************************************************************\r\n\r\n#ifndef __SYS_DEMO_H\r\n#define __SYS_DEMO_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Sys\r\n{\r\n \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nbool LoadExec( const char* pELFName );\r\nbool ExitDemo();\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Sys\r\n\r\n#endif\t// __SYS_DEMO_H\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_anim.cpp",
    "content": "//#include <math.h>\r\n//#include \"p_anim.h\"\r\n//#include \"p_file.h\"\r\n//#include \"p_assert.h\"\r\n//#include \"p_matrix.h\"\r\n//\r\n//#define rpSKINPOPPARENTMATRIX\t 0x01\r\n//#define rpSKINPUSHPARENTMATRIX\t 0x02\r\n//#define rpSKINANIMATEVERTEXGROUP 0x08\r\n//\r\n//NsAnim::NsAnim ( unsigned int numBones )\r\n//{\r\n//\tm_q0\t\t\t\t= new NsQFrame[numBones];\r\n//\tm_t0\t\t\t\t= new NsTFrame[numBones];\r\n//\tm_q1\t\t\t\t= new NsQFrame[numBones];\r\n//\tm_t1\t\t\t\t= new NsTFrame[numBones];\r\n//\tm_qnow\t\t\t\t= new NsQFrame[numBones];\r\n//\tm_tnow\t\t\t\t= new NsTFrame[numBones];\r\n////\tm_pBoneMat\t\t\t= new ROMtx[numBones];\r\n//\r\n//\tm_pQ0\t\t\t\t= NULL;\r\n//\tm_pT0\t\t\t\t= NULL;\r\n//\tm_pQ1\t\t\t\t= NULL;\r\n//\tm_pT1\t\t\t\t= NULL;\r\n//\r\n//\tm_pCurrentSequence\t= NULL;\r\n//\r\n//\tm_numCachedBones\t= numBones;\r\n//\tm_duration\t\t\t= 0.0f;\r\n//\tm_cachedTime\t\t= -1.0f;\r\n//\tm_time\t\t\t\t= 0.0f;\r\n//}\r\n//\r\n//NsAnim::NsAnim ( NsAnim_Sequence * pAnim, unsigned int numBones )\r\n//{\r\n//\tm_q0\t\t\t\t= new NsQFrame[numBones];\r\n//\tm_t0\t\t\t\t= new NsTFrame[numBones];\r\n//\tm_q1\t\t\t\t= new NsQFrame[numBones];\r\n//\tm_t1\t\t\t\t= new NsTFrame[numBones];\r\n//\tm_qnow\t\t\t\t= new NsQFrame[numBones];\r\n//\tm_tnow\t\t\t\t= new NsTFrame[numBones];\r\n////\tm_pBoneMat\t\t\t= new ROMtx[numBones];\r\n//\r\n//\tm_numCachedBones\t= numBones;\r\n//\tm_cachedTime\t\t= -1.0f;\r\n//\tm_time\t\t\t\t= 0.0f;\r\n//\r\n//\tsetCurrentSequence( pAnim );\r\n//}\r\n//\r\n//void NsAnim::setCurrentSequence ( NsAnim_Sequence * pSequence )\r\n//{\r\n//\tif ( m_pCurrentSequence != pSequence ) {\r\n//\t\tm_pCurrentSequence = pSequence;\r\n//\t\treset();\r\n//\t}\r\n//}\r\n//\r\n//void NsAnim::reset ( void )\r\n//{\r\n//\tif ( m_pCurrentSequence ) {\r\n//\t\tNsQFrame  * pQFrame;\r\n//\t\tNsTFrame  * pTFrame;\r\n//\t\tint\t\t\tlp;\r\n//\r\n//\t\t// Set duration.\r\n//\t\tm_duration = m_pCurrentSequence->duration;\r\n//\t\tm_cachedTime = 0.0f;\r\n//\r\n//\t\t// Point to Q & T Frames.\r\n//\t\tpQFrame = (NsQFrame *)&m_pCurrentSequence[1];\r\n//\t\tpTFrame = (NsTFrame *)&pQFrame[m_pCurrentSequence->numQFrames];\r\n//\t\t// Fill in key 0.\r\n//\t\tfor ( lp = 0; lp < m_numCachedBones; lp++ ) {\r\n//\t\t\tm_q0[lp].q.setX( -pQFrame->q.getX() );\r\n//\t\t\tm_q0[lp].q.setY( -pQFrame->q.getY() );\r\n//\t\t\tm_q0[lp].q.setZ( -pQFrame->q.getZ() );\r\n//\t\t\tm_q0[lp].q.setW(  pQFrame->q.getW() );\r\n//\t\t\tm_q0[lp].time =  pQFrame->time;\r\n//\r\n//\t\t\tm_t0[lp].v.copy( pTFrame->v );\r\n//\t\t\tm_t0[lp].time = pTFrame->time;\r\n//\t\t\tpQFrame++;\r\n//\t\t\tpTFrame++;\r\n//\t\t}\r\n//\t\tm_pQ0 = pQFrame;\r\n//\t\tm_pT0 = pTFrame;\r\n//\t\t// Fill in key 1.\r\n//\t\tfor ( lp = 0; lp < m_numCachedBones; lp++ ) {\r\n//\t\t\tm_q1[lp].q.setX( -pQFrame->q.getX() );\r\n//\t\t\tm_q1[lp].q.setY( -pQFrame->q.getY() );\r\n//\t\t\tm_q1[lp].q.setZ( -pQFrame->q.getZ() );\r\n//\t\t\tm_q1[lp].q.setW(  pQFrame->q.getW() );\r\n//\t\t\tm_q1[lp].time =  pQFrame->time;\r\n//\r\n//\t\t\tm_t1[lp].v.copy( pTFrame->v );\r\n//\t\t\tm_t1[lp].time = pTFrame->time;\r\n//\t\t\tpQFrame++;\r\n//\t\t\tpTFrame++;\r\n//\t\t}\r\n//\t\tm_pQ1 = pQFrame;\r\n//\t\tm_pT1 = pTFrame;\r\n//\t}\r\n//}\r\n//\r\n//NsAnim::~NsAnim()\r\n//{\r\n//\tif ( m_q0 )\t\t\tdelete m_q0;\r\n//\tif ( m_t0 )\t\t\tdelete m_t0;\r\n//\tif ( m_q1 )\t\t\tdelete m_q1;\r\n//\tif ( m_t1 )\t\t\tdelete m_t1;\r\n//\tif ( m_qnow )\t\tdelete m_qnow;\r\n//\tif ( m_tnow )\t\tdelete m_tnow;\r\n////\tif ( m_pBoneMat )\tdelete m_pBoneMat;\r\n//}\r\n//\r\n//NsAnim& NsAnim::clone ( void )\r\n//{\r\n//\tNsAnim\t  * pClonedAnim;\r\n//\r\n//\t// Create a cloned anim.\r\n//\tpClonedAnim = new NsAnim( m_pCurrentSequence, m_numCachedBones );\r\n//\r\n//\treturn *pClonedAnim;\r\n//}\r\n//\r\n//void NsAnim::update ( void )\r\n//{\r\n//\tNsQFrame\t  * pLastQFrame;\r\n//\tNsTFrame\t  * pLastTFrame;\r\n//\tint\t\t\t\tlp;\r\n//\tunsigned int\trepeat;\r\n//\tfloat\t\t\tlowesttime;\r\n//\r\n//\tif ( !m_pCurrentSequence ) return;\r\n//\r\n//\tassertp ( m_pQ0 );\r\n//\tassertp ( m_pQ1 );\r\n//\tassertp ( m_pT0 );\r\n//\tassertp ( m_pT1 );\r\n//\r\n//\t// If the new time is less than the old time, re-init.\r\n//\tif ( m_cachedTime > m_time ) {\r\n//\t\treset();\r\n//\t}\r\n//\t// If time is less than 0, reset and quit.\r\n//\tif ( m_time < 0.0f ) {\r\n//\t\treset();\r\n//\t\tm_time = 0.0f;\r\n//\t\tm_cachedTime = m_time;\r\n//\t\treturn;\r\n//\t}\r\n//\t// Cache the new time.\r\n//\tm_cachedTime = m_time;\r\n//\r\n////\t// If the new time is past the end of the sequence, re-init.\r\n////\tif ( m_time > m_duration ) reset();\r\n////\tif ( m_time > m_duration ) m_time = m_duration;\r\n////\t// If the new time is before beginning of the sequence, re-init.\r\n////\tif ( m_time < 0.0f ) reset();\r\n////\twhile ( m_time < 0.0f ) m_time += m_duration;\r\n////\t// Cache the new time.\r\n////\tm_cachedTime = m_time;\r\n//\r\n//\t// Go through each key and see if we need a new quat.\r\n//\t// Do this on key1, and copy key1's old quat to key0 if a new key1 is required.\r\n//\trepeat = 1;\r\n//\r\n//\t// Point to last Q & T Frames.\r\n//\tpLastQFrame = (NsQFrame *)&m_pCurrentSequence[1];\r\n//\tpLastQFrame = &pLastQFrame[m_pCurrentSequence->numQFrames];\r\n//\tpLastTFrame = (NsTFrame *)pLastQFrame;\r\n//\tpLastTFrame = &pLastTFrame[m_pCurrentSequence->numTFrames];\r\n//\t// Update quats.\r\n//\twhile ( repeat ) {\r\n//\t\trepeat = 0;\r\n//\t\t// First, find the lowest q time.\r\n//\t\tlowesttime = m_time;\r\n//\t\tfor ( lp = 0; lp < m_numCachedBones; lp++ ) {\r\n//\t\t\tif ( m_q1[lp].time <= lowesttime ) lowesttime = m_q1[lp].time;\r\n//\t\t}\r\n//\t\t// Now, update all keys with lowesttime.\r\n//\t\tfor ( lp = 0; lp < m_numCachedBones; lp++ ) {\r\n//\t\t\t// See if we need a new Q Frame.\r\n//\t\t\tif ( !( m_q1[lp].time > lowesttime ) && ( m_pQ1 < pLastQFrame ) ) {\r\n//\t\t\t\tm_q0[lp].q.setX( m_q1[lp].q.getX() );\r\n//\t\t\t\tm_q0[lp].q.setY( m_q1[lp].q.getY() );\r\n//\t\t\t\tm_q0[lp].q.setZ( m_q1[lp].q.getZ() );\r\n//\t\t\t\tm_q0[lp].q.setW( m_q1[lp].q.getW() );\r\n//\t\t\t\tm_q0[lp].time = m_q1[lp].time;\r\n//\r\n//\t\t\t\tm_q1[lp].q.setX( -m_pQ1->q.getX() );\r\n//\t\t\t\tm_q1[lp].q.setY( -m_pQ1->q.getY() );\r\n//\t\t\t\tm_q1[lp].q.setZ( -m_pQ1->q.getZ() );\r\n//\t\t\t\tm_q1[lp].q.setW(  m_pQ1->q.getW() );\r\n//\t\t\t\tm_q1[lp].time = m_pQ1->time;\r\n//\r\n//\t\t\t\tm_pQ1++;\r\n//\t\t\t\trepeat = 1;\t\t// Make this loop happen again as we may have passed more than 1 key.\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\t// Update translations.\r\n//\trepeat = 1;\r\n//\twhile ( repeat ) {\r\n//\t\trepeat = 0;\r\n//\t\t// Second, find the lowest t time.\r\n//\t\tlowesttime = m_time;\r\n//\t\tfor ( lp = 0; lp < m_numCachedBones; lp++ ) {\r\n//\t\t\tif ( m_t1[lp].time <= lowesttime ) lowesttime = m_t1[lp].time;\r\n//\t\t}\r\n//\t\t// Now, update all keys with lowesttime.\r\n//\t\tfor ( lp = 0; lp < m_numCachedBones; lp++ ) {\r\n//\t\t\t// See if we need a new T Frame.\r\n//\t\t\tif ( !( m_t1[lp].time > lowesttime ) && ( m_pT1 < pLastTFrame ) ) {\r\n//\t\t\t\tm_t0[lp].v.copy( m_t1[lp].v );\r\n//\t\t\t\tm_t0[lp].time = m_t1[lp].time;\r\n//\r\n//\t\t\t\tm_t1[lp].v.copy( m_pT1->v );\r\n//\t\t\t\tm_t1[lp].time = m_pT1->time;\r\n//\r\n//\t\t\t\tm_pT1++;\r\n//\t\t\t\trepeat = 1;\t\t// Make this loop happen again as we may have passed more than 1 key.\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//void NsAnim::buildKeys( void )\r\n//{\r\n//\tfor( int i = 0; i < m_numCachedBones; ++i )\r\n//\t{\r\n//\t\tgetQuat ( i, &m_qnow[i].q );\r\n//\t\tgetTrans( i, &m_tnow[i].v.x, &m_tnow[i].v.y, &m_tnow[i].v.z );\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tload\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tpFilename\tThe filename to load\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tLoads an animation sequence (allocates memory), and assigns it\t*\r\n// *\t\t\t\tto the current animation object. Also caches time=0.0f.\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n//void NsAnim::load ( char * pFilename )\r\n////static void LoadAnim ( void * pDest, int number )\r\n//{\r\n//\tNsFile\tf;\r\n//\r\n//\tassertp ( pFilename );\r\n//\r\n//\t// Load the animation sequence.\r\n//\tm_pCurrentSequence = (NsAnim_Sequence *)f.load ( pFilename );\r\n//\r\n//\t// Cache at time=0.0f.\r\n//\treset();\r\n//}\r\n//\r\n//\r\n//\r\n//#if 0 // This functionality moved to NsClump.\r\n//void NsAnim::flipBoneMatrices( ROMtx* p_matrices, unsigned int num_flip_pairs, unsigned int* p_flip_pairs )\r\n//{\r\n//\t// Remember the incoming matrices have already been converted to fast-trasnformation format...\r\n//\t// To flip the anim, simply negate the x axis components of the 'at' and 'up' vectors, Tten rebuild\r\n//\t// the right vector. (Negating the x component of the right vector will lead to matrix inversion, which will flip textures etc.)\r\n//\tfor( unsigned int i = 0;; i += 2 )\r\n//\t{\r\n//\t\tassertp(( i + 1 ) < ( num_flip_pairs * 2 ));\r\n//\t\tint matrix0 = p_flip_pairs[i];\r\n//\t\tif( matrix0 == -1 )\r\n//\t\t{\r\n//\t\t\t// Not interested.\r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\r\n//\t\tint matrix1 = p_flip_pairs[i + 1];\r\n//\r\n//\t\tif(( matrix0 == 0 ) && ( matrix1 == 0 ))\r\n//\t\t{\r\n//\t\t\t// Terminator.\r\n//\t\t\tbreak;\r\n//\t\t}\r\n//\r\n//\t\tNsVector right, up, at, pos;\r\n//\r\n//\t\tif( matrix1 == -1 )\r\n//\t\t{\r\n//\t\t\t// Just a simple rotate.\r\n//\t\t\tROMtx* p_matrix0\t= p_matrices + matrix0;\r\n//\r\n//\t\t\t// Generate the right vector from up and at.\r\n//\t\t\tup.set( -p_matrix0[0][0][1], p_matrix0[0][1][1], p_matrix0[0][2][1] );\r\n//\t\t\tat.set( -p_matrix0[0][0][2], p_matrix0[0][1][2], p_matrix0[0][2][2] );\r\n//\t\t\tright.cross( up, at );\r\n//\r\n//\t\t\tpos.set( -p_matrix0[0][3][0], p_matrix0[0][3][1], p_matrix0[0][3][2] );\r\n//\r\n//\t\t\tp_matrix0[0][0][0]\t= right.x;\r\n//\t\t\tp_matrix0[0][1][0]\t= right.y;\r\n//\t\t\tp_matrix0[0][2][0]\t= right.z;\r\n//\t\t\tp_matrix0[0][0][1]\t= up.x;\r\n//\t\t\tp_matrix0[0][0][2]\t= at.x;\r\n//\t\t\tp_matrix0[0][3][0]\t= pos.x;\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tROMtx* p_matrix0\t= p_matrices + matrix0;\r\n//\t\t\tROMtx* p_matrix1\t= p_matrices + matrix1;\r\n//\r\n//\t\t\t// Need to save matrix1 as it will now be written to.\r\n//\t\t\tROMtx m1;\r\n//\t\t\tmemcpy( &m1, p_matrix1, sizeof( ROMtx ));\r\n//\r\n//\t\t\t// Generate the right vector from up and at.\r\n//\t\t\tup.set( -p_matrix0[0][0][1], p_matrix0[0][1][1], p_matrix0[0][2][1] );\r\n//\t\t\tat.set( -p_matrix0[0][0][2], p_matrix0[0][1][2], p_matrix0[0][2][2] );\r\n//\t\t\tright.cross( up, at );\r\n//\t\t\tpos.set( -p_matrix0[0][3][0], p_matrix0[0][3][1], p_matrix0[0][3][2] );\r\n//\r\n//\t\t\tp_matrix1[0][0][0]\t= right.x;\r\n//\t\t\tp_matrix1[0][1][0]\t= right.y;\r\n//\t\t\tp_matrix1[0][2][0]\t= right.z;\r\n//\t\t\tp_matrix1[0][0][1]\t= up.x;\r\n//\t\t\tp_matrix1[0][1][1]\t= up.y;\r\n//\t\t\tp_matrix1[0][2][1]\t= up.z;\r\n//\t\t\tp_matrix1[0][0][2]\t= at.x;\r\n//\t\t\tp_matrix1[0][1][2]\t= at.y;\r\n//\t\t\tp_matrix1[0][2][2]\t= at.z;\r\n//\t\t\tp_matrix1[0][3][0]\t= pos.x;\r\n//\t\t\tp_matrix1[0][3][1]\t= pos.y;\r\n//\t\t\tp_matrix1[0][3][2]\t= pos.z;\r\n//\r\n//\t\t\t// Generate the right vector from up and at.\r\n//\t\t\tup.set( -m1[0][1], m1[1][1], m1[2][1] );\r\n//\t\t\tat.set( -m1[0][2], m1[1][2], m1[2][2] );\r\n//\t\t\tright.cross( up, at );\r\n//\t\t\tpos.set( -m1[3][0], m1[3][1], m1[3][2] );\r\n//\r\n//\t\t\tp_matrix0[0][0][0]\t= right.x;\r\n//\t\t\tp_matrix0[0][1][0]\t= right.y;\r\n//\t\t\tp_matrix0[0][2][0]\t= right.z;\r\n//\t\t\tp_matrix0[0][0][1]\t= up.x;\r\n//\t\t\tp_matrix0[0][1][1]\t= up.y;\r\n//\t\t\tp_matrix0[0][2][1]\t= up.z;\r\n//\t\t\tp_matrix0[0][0][2]\t= at.x;\r\n//\t\t\tp_matrix0[0][1][2]\t= at.y;\r\n//\t\t\tp_matrix0[0][2][2]\t= at.z;\r\n//\t\t\tp_matrix0[0][3][0]\t= pos.x;\r\n//\t\t\tp_matrix0[0][3][1]\t= pos.y;\r\n//\t\t\tp_matrix0[0][3][2]\t= pos.z;\r\n//\t\t}\r\n//\t}\r\n//}\r\n//#endif\r\n//\r\n//\r\n//\r\n//#if 0 // This functionality moved to NsClump.\r\n//ROMtx * NsAnim::buildBoneMatrices ( NsAnim_BoneData * pBoneData )\r\n//{\r\n//\tNsQuat\t\tquat;\r\n//    NsMatrix\tbts;\r\n//\tint\t\t\tlp;\r\n//\tint\t\t\tcurrentMatrix;\r\n//    NsMatrix\tparentMatrix;\r\n//    NsMatrix\tmatrixStack[32];\r\n//    NsMatrix  * pMatrixStackTop = matrixStack;\r\n//\tfloat\t\ttx, ty, tz;\r\n//\tNsMatrix\tboneMatrix;\r\n//\tNsMatrix\ttempMatrix;\r\n//\r\n//\t// Point up what we need.\r\n//\tcurrentMatrix = -1;\r\n//\r\n//\t// This is the root.\r\n//    parentMatrix.identity();\r\n//\r\n//\tfor ( lp = 0; lp < m_numCachedBones; lp++ ) {\r\n//\t\t// Build bone to skin (bts) matrix.\r\n//\t\tbts.setRight( pBoneData[lp].rightx, pBoneData[lp].upx, pBoneData[lp].atx );\r\n//\t\tbts.setUp( pBoneData[lp].righty, pBoneData[lp].upy, pBoneData[lp].aty );\r\n//\t\tbts.setAt( pBoneData[lp].rightz, pBoneData[lp].upz, pBoneData[lp].atz );\r\n//\t\tbts.setPos( pBoneData[lp].posx, pBoneData[lp].posy, pBoneData[lp].posz );\r\n//\r\n//\t\t// Push parent if required.\r\n//\t\tif ( pBoneData[lp].flags & rpSKINPUSHPARENTMATRIX ) {\r\n//\t\t\tmemcpy ( pMatrixStackTop, &parentMatrix, sizeof ( NsMatrix ) );\r\n//\t\t\tpMatrixStackTop++;\r\n//\t\t}\r\n//\r\n//\t\tgetQuat ( lp, &quat );\r\n//\t\tgetTrans( lp, &tx, &ty, &tz );\r\n//\t\tboneMatrix.fromQuat( &quat );\r\n//\t\tboneMatrix.setPos( tx, ty, tz );\r\n///*\r\n//\t\t// Convert quaternion keyframe to matrix.\r\n//\t\t// Note: imaginary part is negated to be Watt-style...\r\n//\t\tquat0.x = -pQ[lp].q.x;\r\n//\t\tquat0.y = -pQ[lp].q.y;\r\n//\t\tquat0.z = -pQ[lp].q.z;\r\n//\t\tquat0.w =  pQ[lp].q.w;\r\n//\t\tquat1.x = -pQ[lp+numBones].q.x;\r\n//\t\tquat1.y = -pQ[lp+numBones].q.y;\r\n//\t\tquat1.z = -pQ[lp+numBones].q.z;\r\n//\t\tquat1.w =  pQ[lp+numBones].q.w;\r\n//\r\n//\t\tquatSlerp ( &quat0, &quat1, time, &quat );\r\n//\r\n//\t\tMTXQuat ( boneMatrix, &quat );\r\n//\r\n//\t\tMTXRowCol(boneMatrix,0,3) = pT[lp].x;\r\n//\t\tMTXRowCol(boneMatrix,1,3) = pT[lp].y;\r\n//\t\tMTXRowCol(boneMatrix,2,3) = pT[lp].z;\r\n//*/\r\n//\t\t// Multiply this matrix by the parent.\r\n//\t\ttempMatrix.cat( parentMatrix, boneMatrix );\r\n//\t\t// Multiply this matrix by the parent.\r\n//\t\tbts.cat( tempMatrix, bts );\r\n//\r\n//\t\t// Convert this matrix to the format required for fast transformation.\r\n////\t\tPSMTXReorder ( bts, pBoneMat[lp] );\r\n//\r\n//\t\tm_pBoneMat[lp][0][0] = bts.getRightX();\r\n//\t\tm_pBoneMat[lp][0][1] = bts.getUpX();\r\n//\t\tm_pBoneMat[lp][0][2] = bts.getAtX();\r\n//\t\tm_pBoneMat[lp][1][0] = bts.getRightY();\r\n//\t\tm_pBoneMat[lp][1][1] = bts.getUpY();\r\n//\t\tm_pBoneMat[lp][1][2] = bts.getAtY();\r\n//\t\tm_pBoneMat[lp][2][0] = bts.getRightZ();\r\n//\t\tm_pBoneMat[lp][2][1] = bts.getUpZ();\r\n//\t\tm_pBoneMat[lp][2][2] = bts.getAtZ();\r\n//\t\tm_pBoneMat[lp][3][0] = bts.getPosX();\r\n//\t\tm_pBoneMat[lp][3][1] = bts.getPosY();\r\n//\t\tm_pBoneMat[lp][3][2] = bts.getPosZ();\r\n//\r\n//\t\t// view * model.\r\n////\t    MTXConcat(v, objMat, pBoneMat[lp]);\t// Note: pMatrixList[0] really objMat.\r\n////\t\t// (view * model) * bts.\r\n////\t    MTXConcat(pBoneMat[lp], bts, pBoneMat[lp]);\r\n//\r\n//\t\t// Calculate light matrix.\r\n////\t\tMTXInverse(pBoneMat[lp], mvi);\r\n////\t\tMTXTranspose(mvi, ipBoneMat[lp]);\r\n//\r\n//\t\t// Update parent (pop if required).\r\n//\t\tif ( pBoneData[lp].flags & rpSKINPOPPARENTMATRIX) {\r\n//\t\t\tpMatrixStackTop--;\r\n//\t\t\tmemcpy ( &parentMatrix, pMatrixStackTop, sizeof ( NsMatrix ) );\r\n//        } else {\r\n//\t\t\tmemcpy ( &parentMatrix, &tempMatrix, sizeof ( NsMatrix ) );\r\n//        }\r\n//\t}\r\n//\r\n//\treturn m_pBoneMat;\r\n//}\r\n//#endif\r\n//\r\n//\r\n//\r\n//void NsAnim::getQuat ( unsigned int bone, NsQuat * pQuat )\r\n//{\r\n//\tfloat terp;\r\n//\tfloat time;\r\n//\r\n//\tif ( m_time < 0.0f ) {\r\n//\t\ttime = 0.0f;\r\n//\t} else if ( m_time > m_duration ) {\r\n//\t\ttime = m_duration;\r\n//\t} else {\r\n//\t\ttime = m_time;\r\n//\t}\r\n//\r\n//\t// Normalize Q time.\r\n//\tterp = ( time - m_q0[bone].time ) / ( m_q1[bone].time - m_q0[bone].time );\r\n//\t// Interpolate quaternion.\r\n//\tpQuat->slerp( m_q0[bone].q, m_q1[bone].q, terp );\r\n//\r\n////\tmemcpy( (void *)pQuat, (void *)&q0[bone].q, sizeof ( NsQuat ) );\r\n//}\r\n//\r\n//void NsAnim::getTrans ( unsigned int bone, float * pX, float * pY, float * pZ )\r\n//{\r\n//\tfloat terp;\r\n//\tfloat time;\r\n//\r\n//\tif ( m_time < 0.0f ) {\r\n//\t\ttime = 0.0f;\r\n//\t} else if ( m_time > m_duration ) {\r\n//\t\ttime = m_duration;\r\n//\t} else {\r\n//\t\ttime = m_time;\r\n//\t}\r\n//\r\n//\t// Normalize T time.\r\n//\tterp = ( time - m_t0[bone].time ) / ( m_t1[bone].time - m_t0[bone].time );\r\n//\t// Interpolate translation.\r\n//\t*pX = ( ( m_t1[bone].v.x - m_t0[bone].v.x ) * terp ) + m_t0[bone].v.x;\r\n//\t*pY = ( ( m_t1[bone].v.y - m_t0[bone].v.y ) * terp ) + m_t0[bone].v.y;\r\n//\t*pZ = ( ( m_t1[bone].v.z - m_t0[bone].v.z ) * terp ) + m_t0[bone].v.z;\r\n//}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_anim.h",
    "content": "//#ifndef _ANIM_H_\r\n//#define _ANIM_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_quat.h\"\r\n//#include \"p_matrix.h\"\r\n//\r\n//typedef struct {\r\n//\tNsVector\tv;\r\n//\tfloat\t\ttime;\r\n//} NsTFrame;\r\n//\r\n//typedef struct {\r\n//\tNsQuat\tq;\r\n//\tfloat\ttime;\r\n//} NsQFrame;\r\n//\r\n//typedef struct {\r\n//\tunsigned int\tid;\r\n//\tunsigned int\tnumQFrames;\r\n//\tunsigned int\tnumTFrames;\r\n//\tunsigned int\tnumFrames;\r\n//\tunsigned int\tflags;\r\n//\tfloat\t\t\tduration;\r\n//\tunsigned int\tpad[2];\r\n//} NsAnim_Sequence;\r\n//\r\n//typedef struct {\r\n//\tunsigned int\tid;\r\n//\tunsigned int\tnumBones;\r\n//\tunsigned int\tpad[6];\r\n//} NsAnim_BoneHeader;\r\n//\r\n//typedef struct {\r\n//\tfloat\t\t\trightx;\r\n//\tfloat\t\t\trighty;\r\n//\tfloat\t\t\trightz;\r\n//\tunsigned int\tmatrixFlags;\r\n//\tfloat\t\t\tupx;\r\n//\tfloat\t\t\tupy;\r\n//\tfloat\t\t\tupz;\r\n//\tunsigned int\tboneIndex;\r\n//\tfloat\t\t\tatx;\r\n//\tfloat\t\t\taty;\r\n//\tfloat\t\t\tatz;\r\n//\tunsigned int\tboneTag;\r\n//\tfloat\t\t\tposx;\r\n//\tfloat\t\t\tposy;\r\n//\tfloat\t\t\tposz;\r\n//\tunsigned int\tflags;\r\n//} NsAnim_BoneData;\r\n//\r\n//typedef struct {\r\n//\tunsigned int\tid;\r\n//\tunsigned int\tnumVerts;\r\n//\tunsigned int\tpad[6];\r\n//} NsAnim_SkinHeader;\r\n//\r\n//typedef struct {\r\n//\tunsigned char\tindex[4];\r\n//\tfloat\t\t\tweight[4];\r\n//} NsAnim_Weight;\r\n//\r\n//typedef struct {\r\n//\tfloat pos[3];\r\n//\tfloat norm[3];\r\n//} NsAnim_PosNormPair;\r\n//\r\n//typedef struct {\r\n//\tfloat w[2];\r\n//} NsAnim_WeightPair;\r\n//\r\n//class NsAnim\r\n//{\r\n//\tNsQFrame\t\t  * m_q0;\t// Malloc size ( QFrame ) * numBones\r\n//\tNsTFrame\t\t  * m_t0;\t// Malloc size ( TFrame ) * numBones\r\n//\tNsQFrame\t\t  * m_q1;\t// Malloc size ( QFrame ) * numBones\r\n//\tNsTFrame\t\t  * m_t1;\t// Malloc size ( TFrame ) * numBones\r\n//\tNsQFrame\t\t  * m_qnow;\t// Malloc size ( QFrame ) * numBones\r\n//\tNsTFrame\t\t  * m_tnow;\t// Malloc size ( TFrame ) * numBones\r\n//\tNsQFrame\t\t  * m_pQ0;\r\n//\tNsTFrame\t\t  * m_pT0;\r\n//\tNsQFrame\t\t  * m_pQ1;\r\n//\tNsTFrame\t\t  * m_pT1;\r\n//\tNsAnim_Sequence\t  * m_pCurrentSequence;\r\n//\tint\t\t\t\t\tm_numCachedBones;\r\n//\tfloat\t\t\t\tm_duration;\r\n//\tfloat\t\t\t\tm_cachedTime;\r\n////\tROMtx\t\t\t  * m_pBoneMat;\r\n//\tfloat\t\t\t\tm_time;\r\n//\r\n//\tvoid\t\t\t\treset\t\t\t\t( void );\r\n//\tvoid\t\t\t\tgetQuat\t\t\t\t( unsigned int bone, NsQuat * pQuat );\r\n//\tvoid\t\t\t\tgetTrans\t\t\t( unsigned int bone, float * pX, float * pY, float * pZ );\r\n//public:\r\n//\r\n//\t\t\t\t\t\tNsAnim\t\t\t\t( unsigned int numBones );\r\n//\t\t\t\t\t\tNsAnim\t\t\t\t( NsAnim_Sequence * pAnim, unsigned int numBones );\r\n//\r\n//\t\t\t\t\t\t~NsAnim\t\t\t\t();\r\n//\r\n//\tvoid\t\t\t\tsetCurrentSequence\t( NsAnim_Sequence * pSequence );\r\n//\r\n//\tvoid\t\t\t\tupdate\t\t\t\t( void );\r\n//\tvoid\t\t\t\tload\t\t\t\t( char * pFilename );\r\n//\r\n//\tvoid\t\t\t\tbuildKeys\t\t\t( void );\r\n////\tvoid\t\t\t\tflipBoneMatrices\t( ROMtx* p_matrices, unsigned int num_flip_pairs, unsigned int* p_flip_pairs );\r\n////\tROMtx\t\t\t  * buildBoneMatrices\t( NsAnim_BoneData * pBoneData );\r\n//\r\n//\tNsAnim&\t\t\t\tclone\t\t\t\t( void );\r\n//\r\n//\tint\t\t\t\t\tnumBones\t\t\t( void ) { return m_numCachedBones; }\r\n//\r\n//\tvoid\t\t\t\tsetTime\t\t\t\t( float time ) { m_time = time; }\r\n//\tfloat\t\t\t\tgetTime\t\t\t\t( void ) { return m_time; }\r\n//\tNsQFrame*\t\t\tgetQFrameNow\t\t( void ) { return m_qnow; }\r\n//\tNsTFrame*\t\t\tgetTFrameNow\t\t( void ) { return m_tnow; }\r\n//};\r\n//\r\n//#endif\t\t// _ANIM_H_\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_anim_core.s",
    "content": "//////////////////////////////////////////////////////////////////////////\r\n//                                                                      //\r\n// Register layout:                                                     //\r\n//                                                                      //\r\n// Register\t\t\t  | Type\t\t| Used for:                         //\r\n// -------------------+-------------+---------------------------------- //\r\n// R0\t\t\t\t  | Volatile\t| Language Specific                 //\r\n// R1\t\t\t\t  | Dedicated\t| Stack Pointer (SP)                //\r\n// R2\t\t\t\t  | Dedicated\t| Read-only small data area anchor  //\r\n// R3 - R4\t\t\t  | Volatile\t| Parameter passing / return values //\r\n// R5 - R10\t\t\t  | Volatile\t| Parameter passing                 //\r\n// R11 - R12\t\t  | Volatile    |                                   //\r\n// R13\t\t\t\t  | Dedicated\t| Read-write small data area anchor //\r\n// R14 - R31\t\t  | Nonvolatile |                                   //\r\n// F0\t\t\t\t  | Volatile\t| Language specific                 //\r\n// F1\t\t\t\t  | Volatile\t| Parameter passing / return values //\r\n// F2 - F8\t\t\t  | Volatile\t| Parameter passing                 //\r\n// F9 - F13\t\t\t  | Volatile    |                                   //\r\n// F14 - F31\t\t  | Nonvolatile |                                   //\r\n// Fields CR2 - CR4\t  | Nonvolatile |                                   //\r\n// Other CR fields\t  | Volatile    |                                   //\r\n// Other registers\t  | Volatile    |                                   //\r\n//                                                                      //\r\n//////////////////////////////////////////////////////////////////////////\r\n\r\n#\t.include \"core/defs.s\"\t\t\t# equates\r\n\r\n\t.section .code\r\n\r\n#\t.extern blah\r\n\r\n\t.equ\tSKN_GQR_POS,6\r\n\t.equ\tSKN_GQR_NORM,7\r\n\r\n\t.equ\tSKN_GQR_UV,0\r\n\r\n\t.equ\tSKN_GQR_U8,2\r\n\t.equ\tSKN_GQR_U16,3\r\n\t.equ\tSKN_GQR_S8,4\r\n\t.equ\tSKN_GQR_S16,5\r\n\r\n#---------------------------------------------------------------------------\r\n# Particle rendering.\r\n#---------------------------------------------------------------------------\r\n\r\n\t.equ\tm_num_particles,\t(4*0)\r\n\t.equ\tm_rate,             (4*1)\r\n\t.equ\tm_interval,         (4*2)\r\n\t.equ\tm_oldest_age,       (4*3)\r\n//\t.equ\tm_rand_seed,        (4*4)\r\n//\t.equ\tm_rand_a,           (4*5)\r\n//\t.equ\tm_rand_b,           (4*6)\r\n\t.equ\tm_rand_current,\t\t(4*4)\r\n\r\n\t.scope\r\n\t.global\tRenderNewParticles\r\nRenderNewParticles:\r\n\t# Input parameters.\r\n\t.equr\t\t@p_stream,\t\t%r3\t\t\t\t# CParticleStream* p_stream\r\n\t.equr\t\t@lifetime,\t\t%f1\t\t\t\t# float lifetime\r\n\t.equr\t\t@midpercent,\t%f2\t\t\t\t# float midpercent\r\n\t.equr\t\t@use_mid_color,\t%r4\t\t\t\t# bool use_mid_color\r\n\t.equr\t\t@p_color0,\t\t%r5\t\t\t\t# GXColor p_color0\r\n\t.equr\t\t@s0,\t\t\t%r6\t\t\t\t# Mth::Vector * s0\r\n\t.equr\t\t@sr,\t\t\t%r7\t\t\t\t# Mth::Vector * sr\r\n\t.equr\t\t@su,\t\t\t%r8\t\t\t\t# Mth::Vector * su\r\n\t.equr\t\t@p_params,\t\t%r9\t\t\t\t# float * p_params\r\n\t.equr\t\t@nearz,\t\t\t%f3\t\t\t\t# float nearz\r\n\r\n\t.equr\t\t@t2,\t\t\t%f2\t\t\t\t# Temporary\r\n\t.equr\t\t@t,\t\t\t\t%f31\r\n\t.equr\t\t@midpoint_time,\t%f4\r\n\t.equr\t\t@fone,\t\t\t%f5\r\n\t.equr\t\t@rXY,\t\t\t%f6\r\n\t.equr\t\t@rZW,\t\t\t%f7\r\n\t.equr\t\t@s0XY,\t\t\t%f8\r\n\t.equr\t\t@s0ZW,\t\t\t%f9\r\n\t.equr\t\t@s1XY,\t\t\t%f10\r\n\t.equr\t\t@s1ZW,\t\t\t%f11\r\n\t.equr\t\t@s2XY,\t\t\t%f12\r\n\t.equr\t\t@s2ZW,\t\t\t%f13\r\n\t.equr\t\t@p0XY,\t\t\t%f14\r\n\t.equr\t\t@p0ZW,\t\t\t%f15\r\n\t.equr\t\t@p1XY,\t\t\t%f16\r\n\t.equr\t\t@p1ZW,\t\t\t%f17\r\n\t.equr\t\t@p2XY,\t\t\t%f18\r\n\t.equr\t\t@p2ZW,\t\t\t%f19\r\n\t.equr\t\t@srXY,\t\t\t%f20\r\n\t.equr\t\t@srZW,\t\t\t%f21\r\n\t.equr\t\t@suXY,\t\t\t%f22\r\n\t.equr\t\t@suZW,\t\t\t%f23\r\n\t.equr\t\t@posXY,\t\t\t%f24\r\n\t.equr\t\t@posZW,\t\t\t%f25\r\n\t.equr\t\t@interval,\t\t%f26\r\n//\t.equr\t\t@v0XY,\t\t\t%f27\r\n//\t.equr\t\t@v0ZW,\t\t\t%f28\r\n//\t.equr\t\t@v1XY,\t\t\t%f29\r\n//\t.equr\t\t@v1ZW,\t\t\t%f30\r\n//\t.equr\t\t@fzero,\t\t\t%f31\r\n\r\n//\t.equr\t\t@srsXY,\t\t\t@t2\r\n//\t.equr\t\t@srsZW,\t\t\t@lifetime\r\n//\t.equr\t\t@susXY,\t\t\t@rXY\r\n//\t.equr\t\t@susZW,\t\t\t@rZW\r\n\t.equr\t\t@srsXY,\t\t\t%f27\r\n\t.equr\t\t@srsZW,\t\t\t%f28\r\n\t.equr\t\t@susXY,\t\t\t%f29\r\n\t.equr\t\t@susZW,\t\t\t%f30\r\n\r\n\t.equr\t\t@quad,\t\t\t%r6\r\n\t.equr\t\t@four,\t\t\t%r7\r\n\t.equr\t\t@rand_current,\t%r8\r\n//\t.equr\t\t@bit_pattern,\t%r8\r\n\t.equr\t\t@p_rand,\t\t%r14\r\n\t.equr\t\t@zero,\t\t\t%r10\r\n\t.equr\t\t@xfreg,\t\t\t%r11\r\n\t.equr\t\t@xfaddr,\t\t%r12\r\n//\t.equr\t\t@color0,\t\t%r11\r\n//\t.equr\t\t@color1,\t\t%r12\r\n//\t.equr\t\t@color2,\t\t%r14\r\n\t.equr\t\t@fifo,\t\t\t%r15\r\n\t.equr\t\t@temp,\t\t\t%r16\r\n\t.equr\t\t@bp,\t\t\t%r17\r\n\t.equr\t\t@psize,\t\t\t%r18\r\n\t.equr\t\t@point,\t\t\t%r19\r\n\t.equr\t\t@one,\t\t\t%r20\r\n\r\n\tstwu    %r1, -256(%r1)\r\n\tstfd    %f14, ( 2*4)(%r1)\r\n\tstfd    %f15, ( 4*4)(%r1)\r\n\tstfd    %f16, ( 6*4)(%r1)\r\n\tstfd    %f17, ( 8*4)(%r1)\r\n\tstfd    %f18, (10*4)(%r1)\r\n\tstfd    %f19, (12*4)(%r1)\r\n\tstfd    %f20, (14*4)(%r1)\r\n\tstfd    %f21, (16*4)(%r1)\r\n\tstfd    %f22, (18*4)(%r1)\r\n\tstfd    %f23, (20*4)(%r1)\r\n\tstfd    %f24, (22*4)(%r1)\r\n\tstfd    %f25, (24*4)(%r1)\r\n\tstfd    %f26, (26*4)(%r1)\r\n\tstfd    %f27, (28*4)(%r1)\r\n\tstfd    %f28, (30*4)(%r1)\r\n\tstfd    %f29, (32*4)(%r1)\r\n\tstfd    %f30, (34*4)(%r1)\r\n\tstfd    %f31, (36*4)(%r1)\r\n\tstw\t\t%r14, (38*4)(%r1)  \r\n\tstw\t\t%r15, (39*4)(%r1)  \r\n\tstw\t\t%r16, (40*4)(%r1)  \r\n\tstw\t\t%r17, (41*4)(%r1)  \r\n\tstw\t\t%r18, (42*4)(%r1)  \r\n\tstw\t\t%r19, (43*4)(%r1)  \r\n\tstw\t\t%r20, (44*4)(%r1)  \r\n\t\t\t\t\t\t   \r\n\t// Load up immediate values.\r\n\tpsq_l\t\t@s0XY,\t\t\t0(@s0),\t\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@s0ZW,\t\t\t8(@s0),\t\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@s1XY,\t\t\t16(@s0),\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@s1ZW,\t\t\t24(@s0),\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@s2XY,\t\t\t32(@s0),\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@s2ZW,\t\t\t40(@s0),\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\r\n\tpsq_l\t\t@p0XY,\t\t\t48(@s0),\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@p0ZW,\t\t\t56(@s0),\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@p1XY,\t\t\t64(@s0),\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@p1ZW,\t\t\t72(@s0),\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@p2XY,\t\t\t80(@s0),\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@p2ZW,\t\t\t88(@s0),\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\r\n\tpsq_l\t\t@suXY,\t\t\t0(@su),\t\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@suZW,\t\t\t8(@su),\t\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@srXY,\t\t\t0(@sr),\t\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@srZW,\t\t\t8(@sr),\t\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\r\n\tlis\t\t\t@temp,\t\t\t@six_data@h\r\n\tori\t\t\t@temp,\t\t\t@temp,\t\t\t\t\t\t@six_data@l\r\n\tpsq_l\t\t@t,\t\t\t\t0(@temp),\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tps_merge00\t@nearz,\t\t\t@nearz,\t\t\t\t\t\t@t\t\t// nearz now has 6 in 1.\r\n\r\n//\tlwz\t\t\t@color0,\t\t0(@p_color0)\r\n//\tlwz\t\t\t@color1,\t\t4(@p_color0)\r\n//\tlwz\t\t\t@color2,\t\t8(@p_color0)\r\n\r\n\tlis\t\t\t@temp,\t\t\t@one_data@h\r\n\tori\t\t\t@temp,\t\t\t@temp,\t\t\t\t\t\t@one_data@l\r\n\tpsq_l\t\t@fone,\t\t\t0(@temp),\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n//\tps_sub\t\t@fzero,\t\t\t@fone,\t\t\t\t\t\t@fone\r\n\r\n//\tlis\t\t\t@bit_pattern,\t0x1010\r\n//\tori\t\t\t@bit_pattern,\t@bit_pattern,\t\t\t\t0x1010\r\n\r\n\tlis\t\t\t@p_rand,\t\t@rand_data@h\r\n\tori\t\t\t@p_rand,\t\t@p_rand,\t\t\t\t\t@rand_data@l\r\n\r\n\tlis\t\t\t@fifo,\t\t\t0xcc01\r\n\taddi\t\t@fifo,\t\t\t@fifo,\t\t\t\t\t\t-0x8000\r\n\r\n\tps_merge00\t@midpercent,\t@midpercent,\t\t\t\t@midpercent\r\n\tps_merge00\t@lifetime,\t\t@lifetime,\t\t\t\t\t@lifetime\r\n\r\n\tli\t\t\t@zero,\t\t\t0x0\r\n\tli\t\t\t@quad,\t\t\t0x80\r\n\tli\t\t\t@four,\t\t\t4\r\n\tli\t\t\t@xfreg,\t\t\t0x10\r\n\tli\t\t\t@xfaddr,\t\t0x100c\r\n\tli\t\t\t@bp,\t\t\t0x61\r\n\tlis\t\t\t@psize,\t\t\t0x2228\r\n\tli\t\t\t@point,\t\t\t0xb8\r\n\tli\t\t\t@one,\t\t\t1\r\n\r\n\tpsq_l\t\t@interval,\t\tm_interval(@p_stream),\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tps_merge00\t@interval,\t\t@interval,\t\t\t\t\t@interval\r\n\r\n//\tfloat t\t\t\t\t= p_stream->m_oldest_age;\r\n\tpsq_l\t\t@t,\t\t\t\tm_oldest_age(@p_stream),\t1,\t\t\t\tSKN_GQR_UV\r\n\tps_merge00\t@t,\t\t\t\t@t,\t\t\t\t\t\t\t@t\r\n\r\n//\tfloat midpoint_time = m_params.m_Lifetime * ( m_params.m_ColorMidpointPct * 0.01f );\r\n\tlis\t\t\t@temp,\t\t\t@tenth_data@h\r\n\tori\t\t\t@temp,\t\t\t@temp,\t\t\t\t\t\t@tenth_data@l\r\n\tpsq_l\t\t@midpoint_time,\t0(@temp),\t\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tps_mul\t\t@midpoint_time,\t@midpoint_time,\t\t\t\t@midpercent\r\n\tps_mul\t\t@midpoint_time,\t@midpoint_time,\t\t\t\t@lifetime\r\n\r\n//\tseed_particle_rnd( p_stream->m_rand_seed, p_stream->m_rand_a, p_stream->m_rand_b );\r\n//\tlwz\t\t\t@rand_seed,\t\tm_rand_seed(@p_stream)\r\n//\tlwz\t\t\t@rand_a,\t\tm_rand_a(@p_stream)\r\n//\tlwz\t\t\t@rand_b,\t\tm_rand_b(@p_stream)\r\n\tlwz\t\t\t@rand_current,\tm_rand_current(@p_stream)\r\n\r\n//\tfor( int p = 0; p < p_stream->m_num_particles; ++p )\r\n\tlwz\t\t\t@temp,\t\t\tm_num_particles(@p_stream)\r\n\tmtctr   \t@temp\r\n\r\n@particle_loop:\r\n//\t\tMth::Vector r( 1.0f + ((float)particle_rnd( 16384 ) / 16384 ), \r\n//\t\t1.0f + ((float)particle_rnd( 16384 ) / 16384 ),\r\n//\t\t1.0f + ((float)particle_rnd( 16384 ) / 16384 ),\r\n//\t\t1.0f + ((float)particle_rnd( 16384 ) / 16384 ));\r\n\r\n//\t\trand_seed\t= rand_seed * rand_a + rand_b;\r\n//\t\trand_a\t\t= ( rand_a ^ rand_seed ) + ( rand_seed >> 4 );\r\n//\t\trand_b\t\t+= ( rand_seed >> 3 ) - 0x10101010L;\r\n//\t\treturn (int)(( rand_seed & 0xffff ) * n ) >> 16;\r\n\r\n//\tmullw\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t@rand_a\r\n//\tadd\t\t\t@rand_seed,\t\t@temp,\t\t\t\t\t\t@rand_b\r\n//\txor\t\t\t@rand_a,\t\t@rand_seed,\t\t\t\t\t@rand_a\r\n//\tsrwi\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t4\r\n//\tadd\t\t\t@rand_a,\t\t@rand_a,\t\t\t\t\t@temp\r\n//\tsrwi\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t3\r\n//\tsub\t\t\t@temp,\t\t\t@temp,\t\t\t\t\t\t@bit_pattern\r\n//\tadd\t\t\t@rand_b,\t\t@rand_b,\t\t\t\t\t@temp\r\n//\tandi.\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t0xffff\r\n//\tsrwi\t\t@temp,\t\t\t@temp,\t\t\t\t\t\t2\r\n//\tsth\t\t\t@temp,\t\t\t0(@p_rand)\r\n//\r\n//\tmullw\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t@rand_a\r\n//\tadd\t\t\t@rand_seed,\t\t@temp,\t\t\t\t\t\t@rand_b\r\n//\txor\t\t\t@rand_a,\t\t@rand_seed,\t\t\t\t\t@rand_a\r\n//\tsrwi\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t4\r\n//\tadd\t\t\t@rand_a,\t\t@rand_a,\t\t\t\t\t@temp\r\n//\tsrwi\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t3\r\n//\tsub\t\t\t@temp,\t\t\t@temp,\t\t\t\t\t\t@bit_pattern\r\n//\tadd\t\t\t@rand_b,\t\t@rand_b,\t\t\t\t\t@temp\r\n//\tandi.\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t0xffff\r\n//\tsrwi\t\t@temp,\t\t\t@temp,\t\t\t\t\t\t2\r\n//\tsth\t\t\t@temp,\t\t\t2(@p_rand)\r\n//\r\n//\tmullw\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t@rand_a\r\n//\tadd\t\t\t@rand_seed,\t\t@temp,\t\t\t\t\t\t@rand_b\r\n//\txor\t\t\t@rand_a,\t\t@rand_seed,\t\t\t\t\t@rand_a\r\n//\tsrwi\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t4\r\n//\tadd\t\t\t@rand_a,\t\t@rand_a,\t\t\t\t\t@temp\r\n//\tsrwi\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t3\r\n//\tsub\t\t\t@temp,\t\t\t@temp,\t\t\t\t\t\t@bit_pattern\r\n//\tadd\t\t\t@rand_b,\t\t@rand_b,\t\t\t\t\t@temp\r\n//\tandi.\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t0xffff\r\n//\tsrwi\t\t@temp,\t\t\t@temp,\t\t\t\t\t\t2\r\n//\tsth\t\t\t@temp,\t\t\t4(@p_rand)\r\n//\r\n//\tmullw\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t@rand_a\r\n//\tadd\t\t\t@rand_seed,\t\t@temp,\t\t\t\t\t\t@rand_b\r\n//\txor\t\t\t@rand_a,\t\t@rand_seed,\t\t\t\t\t@rand_a\r\n//\tsrwi\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t4\r\n//\tadd\t\t\t@rand_a,\t\t@rand_a,\t\t\t\t\t@temp\r\n//\tsrwi\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t3\r\n//\tsub\t\t\t@temp,\t\t\t@temp,\t\t\t\t\t\t@bit_pattern\r\n//\tadd\t\t\t@rand_b,\t\t@rand_b,\t\t\t\t\t@temp\r\n//\tandi.\t\t@temp,\t\t\t@rand_seed,\t\t\t\t\t0xffff\r\n//\tsrwi\t\t@temp,\t\t\t@temp,\t\t\t\t\t\t2\r\n//\tsth\t\t\t@temp,\t\t\t6(@p_rand)\r\n\r\n\r\n//\t\t\tif( m_params.m_UseMidcolor )\r\n//\t\t\t{\r\n//\t\t\t\tif( t > midpoint_time )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tcolor_interpolator\t= ( t - midpoint_time ) * ReciprocalEstimate_ASM( m_params.m_Lifetime - midpoint_time );\r\n//\t\t\t\t\tcol0\t\t\t\t= m_params.m_Color[1];\r\n//\t\t\t\t\tcol1\t\t\t\t= m_params.m_Color[2];\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tcolor_interpolator\t= t * ReciprocalEstimate_ASM( midpoint_time );\r\n//\t\t\t\t\tcol0\t\t\t\t= m_params.m_Color[0];\r\n//\t\t\t\t\tcol1\t\t\t\t= m_params.m_Color[1];\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\telse \r\n//\t\t\t{\r\n//\t\t\t\tcolor_interpolator\t\t= t * ReciprocalEstimate_ASM( m_params.m_Lifetime );\r\n//\t\t\t\tcol0\t\t\t\t\t= m_params.m_Color[0];\r\n//\t\t\t\tcol1\t\t\t\t\t= m_params.m_Color[2];\r\n//\t\t\t}\r\n\tandi.\t\t@temp,\t\t\t@use_mid_color,\t\t\t\t1\r\n\tbeq\t\t\t@no_mid\r\n\r\n\tps_cmpu0\t%cr0,\t\t\t@t,\t\t\t\t\t\t\t@midpoint_time\r\n\tble\t\t\t@after_mid\r\n// before midpoint\r\n\tps_sub\t\t@t2,\t\t\t@lifetime,\t\t\t\t\t@midpoint_time\r\n\tps_res\t\t@t2,\t\t\t@t2\r\n\tps_sub\t\t@rXY,\t\t\t@t,\t\t\t\t\t\t\t@midpoint_time \r\n\tps_mul\t\t@t2,\t\t\t@t2,\t\t\t\t\t\t@rXY\r\n\tpsq_l\t\t@susXY,\t\t\t4(@p_color0),\t\t\t\t0,\t\t\t\tSKN_GQR_U8\r\n\tpsq_l\t\t@susZW,\t\t\t6(@p_color0),\t\t\t\t0,\t\t\t\tSKN_GQR_U8\r\n\tpsq_l\t\t@srsXY,\t\t\t8(@p_color0),\t\t\t\t0,\t\t\t\tSKN_GQR_U8\r\n\tpsq_l\t\t@srsZW,\t\t\t10(@p_color0),\t\t\t\t0,\t\t\t\tSKN_GQR_U8\r\n\r\n\tb\t\t\t@over_mid\r\n@after_mid:\r\n// after midpoint\r\n\tps_res\t\t@t2,\t\t\t@midpoint_time\r\n\tps_mul\t\t@t2,\t\t\t@t2,\t\t\t\t\t\t@t\r\n\tpsq_l\t\t@susXY,\t\t\t0(@p_color0),\t\t\t\t0,\t\t\t\tSKN_GQR_U8\r\n\tpsq_l\t\t@susZW,\t\t\t2(@p_color0),\t\t\t\t0,\t\t\t\tSKN_GQR_U8\r\n\tpsq_l\t\t@srsXY,\t\t\t4(@p_color0),\t\t\t\t0,\t\t\t\tSKN_GQR_U8\r\n\tpsq_l\t\t@srsZW,\t\t\t6(@p_color0),\t\t\t\t0,\t\t\t\tSKN_GQR_U8\r\n\r\n\tb\t\t\t@over_mid\r\n\r\n@no_mid:\r\n// no midpoint.\r\n\tps_res\t\t@t2,\t\t\t@lifetime\r\n\tps_mul\t\t@t2,\t\t\t@t2,\t\t\t\t\t\t@t\r\n\tpsq_l\t\t@susXY,\t\t\t0(@p_color0),\t\t\t\t0,\t\t\t\tSKN_GQR_U8\r\n\tpsq_l\t\t@susZW,\t\t\t2(@p_color0),\t\t\t\t0,\t\t\t\tSKN_GQR_U8\r\n\tpsq_l\t\t@srsXY,\t\t\t8(@p_color0),\t\t\t\t0,\t\t\t\tSKN_GQR_U8\r\n\tpsq_l\t\t@srsZW,\t\t\t10(@p_color0),\t\t\t\t0,\t\t\t\tSKN_GQR_U8\r\n\r\n@over_mid:\r\n\tps_sub\t\t@rXY,\t\t\t@srsXY,\t\t\t\t\t\t@susXY\r\n\tps_sub\t\t@rZW,\t\t\t@srsZW,\t\t\t\t\t\t@susZW\r\n\tps_madd\t\t@rXY,\t\t\t@rXY,\t\t\t\t\t\t@t2,\t\t\t@susXY\r\n\tps_madd\t\t@rZW,\t\t\t@rZW,\t\t\t\t\t\t@t2,            @susZW\r\n\r\n// Store material color here.\r\n\tstb\t\t\t@xfreg,\t\t\t0(@fifo)\r\n\tsth\t\t\t@zero,\t\t\t0(@fifo)\r\n\tsth\t\t\t@xfaddr,\t\t0(@fifo)\r\n\tps_merge11\t@t2,\t\t\t@rXY,\t\t\t\t\t\t@rXY\r\n\tpsq_st\t\t@rXY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_U8\r\n\tpsq_st\t\t@t2,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_U8\r\n\tps_merge11\t@t2,\t\t\t@rZW,\t\t\t\t\t\t@rZW\r\n\tpsq_st\t\t@rZW,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_U8\r\n\tpsq_st\t\t@t2,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_U8\r\n\r\n//\t\tMth::Vector r;\r\n//\t\tr[X] = 1.0f + ((float)( rand_current = ( ( rand_current & 1 ) ? ( rand_current >> 1 ) ^ 0x3500 : ( rand_current >> 1 ) ) ) / 16384.0f );\r\n//\t\tr[Y] = 1.0f + ((float)( rand_current = ( ( rand_current & 1 ) ? ( rand_current >> 1 ) ^ 0x3500 : ( rand_current >> 1 ) ) ) / 16384.0f );\r\n//\t\tr[Z] = 1.0f + ((float)( rand_current = ( ( rand_current & 1 ) ? ( rand_current >> 1 ) ^ 0x3500 : ( rand_current >> 1 ) ) ) / 16384.0f );\r\n//\t\tr[W] = 1.0f + ((float)( rand_current = ( ( rand_current & 1 ) ? ( rand_current >> 1 ) ^ 0x3500 : ( rand_current >> 1 ) ) ) / 16384.0f );\r\n\r\n\tandi.\t\t@temp,\t\t\t@rand_current,\t\t\t\t1\r\n\tsrwi\t\t@rand_current,\t@rand_current,\t\t\t\t1\t\t// Doesn't affect CR\r\n\tbeq\t\t\t@over_0\r\n\txori\t\t@rand_current,\t@rand_current,\t\t\t\t0x3500\r\n@over_0:\r\n\tsth\t\t\t@rand_current,\t0(@p_rand)\r\n\r\n\tandi.\t\t@temp,\t\t\t@rand_current,\t\t\t\t1\r\n\tsrwi\t\t@rand_current,\t@rand_current,\t\t\t\t1\t\t// Doesn't affect CR\r\n\tbeq\t\t\t@over_1\r\n\txori\t\t@rand_current,\t@rand_current,\t\t\t\t0x3500\r\n@over_1:\r\n\tsth\t\t\t@rand_current,\t2(@p_rand)\r\n\r\n\tandi.\t\t@temp,\t\t\t@rand_current,\t\t\t\t1\r\n\tsrwi\t\t@rand_current,\t@rand_current,\t\t\t\t1\t\t// Doesn't affect CR\r\n\tbeq\t\t\t@over_2\r\n\txori\t\t@rand_current,\t@rand_current,\t\t\t\t0x3500\r\n@over_2:\r\n\tsth\t\t\t@rand_current,\t4(@p_rand)\r\n\r\n\tandi.\t\t@temp,\t\t\t@rand_current,\t\t\t\t1\r\n\tsrwi\t\t@rand_current,\t@rand_current,\t\t\t\t1\t\t// Doesn't affect CR\r\n\tbeq\t\t\t@over_3\r\n\txori\t\t@rand_current,\t@rand_current,\t\t\t\t0x3500\r\n@over_3:\r\n\tsth\t\t\t@rand_current,\t6(@p_rand)\r\n\r\n\tpsq_l\t\t@rXY, \t\t\t0(@p_rand),\t\t\t\t\t0,\t\t\t\tSKN_GQR_NORM\r\n\tpsq_l\t\t@rZW, \t\t\t4(@p_rand),\t\t\t\t\t0,\t\t\t\tSKN_GQR_NORM\r\n\tps_add\t\t@rXY,\t\t\t@rXY,\t\t\t\t\t\t@fone\r\n\tps_add\t\t@rZW,\t\t\t@rZW,\t\t\t\t\t\t@fone\r\n\r\n//\tMth::Vector pos = ( m_p0 + ( t * m_p1 ) + (( t * t ) * m_p2 )) + ( m_s0 + ( t * m_s1 ) + (( t * t ) * m_s2 )).Scale( r );\r\n//pos = ( m_p0 +\r\n//\t\t( t * m_p1 ) +\r\n//\t\t(( t * t ) * m_p2 )) +\r\n//\r\n//\t\t( m_s0 +\r\n//\t\t( t * m_s1 ) +\r\n//\t\t(( t * t ) * m_s2 ))\r\n//\t\t.Scale( r );\r\n\t\r\n\tps_mul\t\t@t2,\t\t\t@t,\t\t\t\t\t\t\t@t\r\n\r\n\tps_madd\t\t@posXY,\t\t\t@t,\t\t\t\t\t\t\t@s1XY,\t\t\t@s0XY\r\n\tps_madd\t\t@posZW,\t\t\t@t,\t\t\t\t\t\t\t@s1ZW,\t\t\t@s0ZW\r\n\tps_madd\t\t@posXY,\t\t\t@t2,\t\t\t\t\t\t@s2XY,\t\t\t@posXY\r\n\tps_madd\t\t@posZW,\t\t\t@t2,\t\t\t\t\t\t@s2ZW,\t\t\t@posZW\r\n\r\n\tps_mul\t\t@posXY,\t\t\t@posXY,\t\t\t\t\t\t@rXY\r\n\tps_mul\t\t@posZW,\t\t\t@posZW,\t\t\t\t\t\t@rZW\r\n\r\n\tps_madd\t\t@rXY,\t\t\t@t,\t\t\t\t\t\t\t@p1XY,\t\t\t@p0XY\r\n\tps_madd\t\t@rZW,\t\t\t@t,\t\t\t\t\t\t\t@p1ZW,\t\t\t@p0ZW\r\n\tps_madd\t\t@rXY,\t\t\t@t2,\t\t\t\t\t\t@p2XY,\t\t\t@rXY\r\n\tps_madd\t\t@rZW,\t\t\t@t2,\t\t\t\t\t\t@p2ZW,\t\t\t@rZW\r\n\r\n\tps_add\t\t@posXY,\t\t\t@posXY,\t\t\t\t\t\t@rXY\r\n\tps_add\t\t@posZW,\t\t\t@posZW,\t\t\t\t\t\t@rZW\r\n\r\n\r\n\t.equr\t\t@mXY,\t\t\t@srsXY\r\n\t.equr\t\t@mWZ,\t\t\t@srsZW\r\n\t.equr\t\t@pm1vp2,\t\t@susXY\r\n\t.equr\t\t@ftemp,\t\t\t@susZW\r\n\r\n//\tfloat z = p_mtx->getAtX()*pos[X] + p_mtx->getAtY()*pos[Y] + p_mtx->getAtZ()*pos[Z] + p_mtx->getPosZ();\r\n\tpsq_l\t\t@mXY, \t\t\t0(@p_params),\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\tpsq_l\t\t@mWZ, \t\t\t8(@p_params),\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\r\n\tps_mul\t\t@mXY,\t\t\t@posXY,\t\t\t\t\t\t@mXY\r\n\tps_madds1\t@mWZ,\t\t\t@posZW,\t\t\t\t\t\t@mWZ,\t\t\t@mWZ\r\n\tps_add\t\t@mWZ,\t\t\t@mWZ,\t\t\t\t\t\t@mXY\r\n\tps_merge11  @mXY,\t\t\t@mXY,\t\t\t\t\t\t@mXY\r\n\tps_add\t\t@mWZ,\t\t\t@mWZ,\t\t\t\t\t\t@mXY\t\t\t// mZW0 = z\r\n\tps_neg\t\t@mWZ,\t\t\t@mWZ                                        // mZW0 = -z\r\n\r\n//\tfloat xc = pos[W] * pm[1];\t// + z * pm[2];\r\n\tpsq_l\t\t@pm1vp2,\t\t16(@p_params),\t\t\t\t0,\t\t\t\tSKN_GQR_UV\r\n\r\n\tps_muls1\t@ftemp,\t\t\t@pm1vp2,\t\t\t\t\t@posZW\t\t\t// @ftemp0=pm1*w\r\n\tps_div\t\t@mXY,\t\t\t@fone,\t\t\t\t\t\t@mWZ\t\t\t// @mXY0=1/z\r\n\tps_muls1\t@ftemp,\t\t\t@ftemp,\t\t\t\t\t\t@pm1vp2\t\t\t// @ftemp0=xc*vp2\r\n\tps_mul\t\t@ftemp,\t\t\t@ftemp,\t\t\t\t\t\t@mXY\t\t\t// sc\r\n\t\r\n\tps_muls1\t@mXY,\t\t\t@ftemp,\t\t\t\t\t\t@nearz\t\t\t// sc * 6\r\n\tpsq_st\t\t@mXY,\t\t\t0(@p_rand),\t\t\t\t\t1,\t\t\t\t5 // s16, no scaling.\r\n\tlhz\t\t\t@temp,\t\t\t0(@p_rand)\r\n\tcmpi\t\t%cr0,\t\t\t@temp,\t\t\t\t\t\t256\r\n\tbge\t\t\t@notile\r\n\r\n\tslwi\t\t@temp,\t\t\t@temp,\t\t\t\t\t\t8\r\n\tor\t\t\t@temp,\t\t\t@psize,\t\t\t\t\t\t@temp\r\n\r\n\tstb\t\t\t@bp,\t\t\t0(@fifo)\r\n\tstw\t\t\t@temp,\t\t\t0(@fifo)\r\n\tstb\t\t\t@point,\t\t\t0(@fifo)\r\n\tsth\t\t\t@one,\t\t\t0(@fifo)\r\n\r\n\tps_sub\t\t@t2,\t\t\t@fone,\t\t\t\t\t\t@fone\r\n\tpsq_st\t\t@posXY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@rXY,\t\t\t@posXY,\t\t\t\t\t\t@posXY\r\n\tpsq_st\t\t@rXY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@posZW,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@t2,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@t2,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\r\n\tb\t\t\t@skip\r\n\r\n@notile:\r\n\tps_cmpu0\t%cr0,\t\t\t@ftemp,\t\t\t\t\t\t@nearz\r\n\tble\t\t\t@ok\r\n\r\n//\tpos[W] = ( pos[W] * 256.0f ) / sc;\r\n\tps_muls1\t@mXY,\t\t\t@nearz,\t\t\t\t\t\t@posZW\r\n\tps_div\t\t@mXY,\t\t\t@mXY,\t\t\t\t\t\t@ftemp\r\n\tps_merge00\t@posZW,\t\t\t@posZW,\t\t\t\t\t\t@mXY\r\n@ok:\r\n\r\n//\tNsVector sr;\r\n//\tsr.x = screen_right.x * pos[W];\r\n//\tsr.y = screen_right.y * pos[W];\r\n//\tsr.z = screen_right.z * pos[W];\r\n//\tNsVector su;\r\n//\tsu.x = screen_up.x * pos[W];\r\n//\tsu.y = screen_up.y * pos[W];\r\n//\tsu.z = screen_up.z * pos[W];\r\n\tps_merge11  @susZW,\t\t\t@posZW,\t\t\t\t\t\t@posZW\r\n\tps_mul\t\t@srsXY,\t\t\t@srXY,\t\t\t\t\t\t@susZW\r\n\tps_mul\t\t@srsZW,\t\t\t@srZW,\t\t\t\t\t\t@susZW\r\n\tps_mul\t\t@susXY,\t\t\t@suXY,\t\t\t\t\t\t@susZW\r\n\tps_mul\t\t@susZW,\t\t\t@suZW,\t\t\t\t\t\t@susZW\r\n\r\n\tstb\t\t\t@quad,\t\t\t0(@fifo)\r\n\tsth\t\t\t@four,\t\t\t0(@fifo)\r\n\r\n\tps_add\t\t@posXY,\t\t\t@posXY,\t\t\t\t\t\t@susXY\r\n\tps_add\t\t@posZW,\t\t\t@posZW,\t\t\t\t\t\t@susZW\r\n\tps_sub\t\t@posXY,\t\t\t@posXY,\t\t\t\t\t\t@srsXY\r\n\tps_sub\t\t@posZW,\t\t\t@posZW,\t\t\t\t\t\t@srsZW\r\n\r\n\tps_add\t\t@susXY,\t\t\t@susXY,\t\t\t\t\t\t@susXY\r\n\tps_add\t\t@susZW,\t\t\t@susZW,\t\t\t\t\t\t@susZW\r\n\tps_add\t\t@srsXY,\t\t\t@srsXY,\t\t\t\t\t\t@srsXY\r\n\tps_add\t\t@srsZW,\t\t\t@srsZW,\t\t\t\t\t\t@srsZW\r\n\r\n\tps_sub\t\t@t2,\t\t\t@fone,\t\t\t\t\t\t@fone\r\n\t// Store pos, 0,0\r\n\tpsq_st\t\t@posXY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@rXY,\t\t\t@posXY,\t\t\t\t\t\t@posXY\r\n\tpsq_st\t\t@rXY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@posZW,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@t2,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@t2,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\r\n\tps_add\t\t@posXY,\t\t\t@posXY,\t\t\t\t\t\t@srsXY\r\n\tps_add\t\t@posZW,\t\t\t@posZW,\t\t\t\t\t\t@srsZW\r\n\t// Store pos, 1,0\r\n\tpsq_st\t\t@posXY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@rXY,\t\t\t@posXY,\t\t\t\t\t\t@posXY\r\n\tpsq_st\t\t@rXY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@posZW,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@fone,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@t2,\t\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\r\n\tps_sub\t\t@posXY,\t\t\t@posXY,\t\t\t\t\t\t@susXY\r\n\tps_sub\t\t@posZW,\t\t\t@posZW,\t\t\t\t\t\t@susZW\r\n\t// Store pos, 1,1\r\n\tpsq_st\t\t@posXY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@rXY,\t\t\t@posXY,\t\t\t\t\t\t@posXY\r\n\tpsq_st\t\t@rXY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@posZW,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@fone,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@fone,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\r\n\tps_sub\t\t@posXY,\t\t\t@posXY,\t\t\t\t\t\t@srsXY\r\n\tps_sub\t\t@posZW,\t\t\t@posZW,\t\t\t\t\t\t@srsZW\r\n\t// Store pos, 0,1\r\n\tpsq_st\t\t@posXY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@rXY,\t\t\t@posXY,\t\t\t\t\t\t@posXY\r\n\tpsq_st\t\t@rXY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@posZW,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@t2,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\tpsq_st\t\t@fone,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\r\n\r\n\r\n//\tps_add\t\t@v1XY,\t\t\t@posXY,\t\t\t\t\t\t@susXY\r\n//\tps_add\t\t@v1ZW,\t\t\t@posZW,\t\t\t\t\t\t@susZW\r\n//\tps_sub\t\t@v0XY,\t\t\t@v1XY,\t\t\t\t\t\t@srsXY\r\n//\tps_sub\t\t@v0ZW,\t\t\t@v1ZW,\t\t\t\t\t\t@srsZW\r\n//\t// Store pos, 0,0\r\n//\tpsq_st\t\t@v0XY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tps_merge11\t@v0XY,\t\t\t@v0XY,\t\t\t\t\t\t@v0XY\r\n//\tpsq_st\t\t@v0XY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tpsq_st\t\t@v0ZW,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tpsq_st\t\t@fzero,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tpsq_st\t\t@fzero,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\r\n//\tps_add\t\t@v0XY,\t\t\t@v1XY,\t\t\t\t\t\t@srsXY\r\n//\tps_add\t\t@v0ZW,\t\t\t@v1ZW,\t\t\t\t\t\t@srsZW\r\n//\t// Store pos, 1,0\r\n//\tpsq_st\t\t@v0XY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tps_merge11\t@v0XY,\t\t\t@v0XY,\t\t\t\t\t\t@v0XY\r\n//\tpsq_st\t\t@v0XY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tpsq_st\t\t@v0ZW,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tpsq_st\t\t@fone,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tpsq_st\t\t@fzero,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\r\n//\tps_sub\t\t@v1XY,\t\t\t@posXY,\t\t\t\t\t\t@susXY\r\n//\tps_sub\t\t@v1ZW,\t\t\t@posZW,\t\t\t\t\t\t@susZW\r\n//\tps_add\t\t@v0XY,\t\t\t@v1XY,\t\t\t\t\t\t@srsXY\r\n//\tps_add\t\t@v0ZW,\t\t\t@v1ZW,\t\t\t\t\t\t@srsZW\r\n//\t// Store pos, 1,1\r\n//\tpsq_st\t\t@v0XY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tps_merge11\t@v0XY,\t\t\t@v0XY,\t\t\t\t\t\t@v0XY\r\n//\tpsq_st\t\t@v0XY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tpsq_st\t\t@v0ZW,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tpsq_st\t\t@fone,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tpsq_st\t\t@fone,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\r\n//\tps_sub\t\t@v0XY,\t\t\t@v1XY,\t\t\t\t\t\t@srsXY\r\n//\tps_sub\t\t@v0ZW,\t\t\t@v1ZW,\t\t\t\t\t\t@srsZW\r\n//\t// Store pos, 0,1\r\n//\tpsq_st\t\t@v0XY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tps_merge11\t@v0XY,\t\t\t@v0XY,\t\t\t\t\t\t@v0XY\r\n//\tpsq_st\t\t@v0XY,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tpsq_st\t\t@v0ZW,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tpsq_st\t\t@fzero,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n//\tpsq_st\t\t@fone,\t\t\t0(@fifo),\t\t\t\t\t1,\t\t\t\tSKN_GQR_UV\r\n\r\n//\tt -= p_stream->m_interval;\r\n@skip:\r\n\tps_sub\t\t@t,\t\t\t\t@t,\t\t\t\t\t\t\t@interval\r\n\r\n\r\n\r\n//\tcmpw\t\t@use_mid_color,\t@zero\r\n//\tbeq\t\t\t@no_mid\r\n//\t\r\n//\tb\t\t\t@over_mid\r\n//@no_mid:\r\n//\t\r\n//@over_mid:\r\n\r\n\r\n\r\n\r\n\r\n//\tfres\t\t@in, @in\r\n\tbdnz+\t\t@particle_loop\r\n\r\n\tlfd\t\t%f14, ( 2*4)(%r1)\r\n\tlfd\t\t%f15, ( 4*4)(%r1)\r\n\tlfd\t\t%f16, ( 6*4)(%r1)\r\n\tlfd\t\t%f17, ( 8*4)(%r1)\r\n\tlfd\t\t%f18, (10*4)(%r1)\r\n\tlfd\t\t%f19, (12*4)(%r1)\r\n\tlfd\t\t%f20, (14*4)(%r1)\r\n\tlfd\t\t%f21, (16*4)(%r1)\r\n\tlfd\t\t%f22, (18*4)(%r1)\r\n\tlfd\t\t%f23, (20*4)(%r1)\r\n\tlfd\t\t%f24, (22*4)(%r1)\r\n\tlfd\t\t%f25, (24*4)(%r1)\r\n\tlfd\t\t%f26, (26*4)(%r1)\r\n\tlfd\t\t%f27, (28*4)(%r1)\r\n\tlfd\t\t%f28, (30*4)(%r1)\r\n\tlfd\t\t%f29, (32*4)(%r1)\r\n\tlfd\t\t%f30, (34*4)(%r1)\r\n\tlfd\t\t%f31, (36*4)(%r1)\r\n\tlwz\t\t%r14, (38*4)(%r1)\r\n\tlwz\t\t%r15, (39*4)(%r1)\r\n\tlwz\t\t%r16, (40*4)(%r1)\r\n\tlwz\t\t%r17, (41*4)(%r1)\r\n\tlwz\t\t%r18, (42*4)(%r1)\r\n\tlwz\t\t%r19, (43*4)(%r1)\r\n\tlwz\t\t%r20, (44*4)(%r1)\r\n\taddi    %r1, %r1, 256\r\n\tblr\r\n\r\n@tenth_data:\r\n\t.float\t(0.01)\r\n\t.float\t(0.01)\r\n\t.float\t(0.01)\r\n\t.float\t(0.01)\r\n\r\n@one_data:\r\n\t.float\t(1.0)\r\n\t.float\t(1.0)\r\n\t.float\t(1.0)\r\n\t.float\t(1.0)\r\n\r\n@rand_data:\r\n\t.float\t(1.0)\t\t// garbage\r\n\t.float\t(1.0)\r\n\t.float\t(1.0)\r\n\t.float\t(1.0)\r\n\r\n@six_data:\r\n\t.float\t(6.0)\r\n\t.float\t(6.0)\r\n\t.float\t(6.0)\r\n\t.float\t(6.0)\r\n\r\n@temp_data:\r\n\t.float\t(0.0)\r\n\t.float\t(0.0)\r\n\t.float\t(0.0)\r\n\t.float\t(0.0)\r\n\r\n\t.endscope\r\n\r\n#---------------------------------------------------------------------------\r\n# Reciprocal estimate.\r\n#---------------------------------------------------------------------------\r\n\r\n\t.scope\r\n\t.global\tReciprocalEstimate_ASM\r\nReciprocalEstimate_ASM:\r\n\t# Input parameters.\r\n\t.equr\t\t@in,\t\t\t%f1\t\t\t\t# float f\r\n\r\n\tfres\t\t@in, @in\r\n\tblr\r\n\t.endscope\r\n\r\n#---------------------------------------------------------------------------\r\n# Convert an array of fixed point shorts (1.9.6) to floating point.\r\n#---------------------------------------------------------------------------\r\n\r\n\t.scope\r\n\t.global\tConvertFixed196ToFloat\r\nConvertFixed196ToFloat:\r\n\t# Input parameters.\r\n\t.equr\t\t@in,\t\t\t%r3\t\t\t\t# s16 * p_source\r\n\t.equr\t\t@out,\t\t\t%r4\t\t\t\t# float * p_dest\r\n\t.equr\t\t@count,\t\t\t%r5\t\t\t\t# int count\r\n\r\n\t.equr\t\t@X_Y,\t\t\t%f0\r\n\t.equr\t\t@Z_n,\t\t\t%f1\r\n\r\n\taddi    \t@in,\t\t\t@in,\t\t\t-8\r\n\taddi    \t@out,\t\t\t@out,\t\t\t-4\r\n\t\r\n\tmtctr   \t@count\r\n\r\n@mloop:\r\n\tpsq_lu  \t@X_Y, \t\t\t8(@in), \t\t0, \t\t\tSKN_GQR_POS\r\n\tpsq_lu  \t@Z_n, \t\t\t4(@in), \t\t1, \t\t\tSKN_GQR_POS\r\n\t\t\t\t   \r\n\tpsq_stu \t@X_Y, \t\t\t4(@out), \t\t0, \t\t\tSKN_GQR_UV\r\n\tpsq_stu \t@Z_n, \t\t\t8(@out), \t\t1, \t\t\tSKN_GQR_UV\r\n\r\n\tbdnz+ @mloop\r\n\tblr\r\n\t.endscope\r\n\r\n#---------------------------------------------------------------------------\r\n# Calculate the dot product for every face.\r\n#---------------------------------------------------------------------------\r\n\r\n\t.scope\r\n\t.global\tCalculateDotProducts\r\nCalculateDotProducts:\r\n\t.equr\t\t@vert,\t\t\t%r3\t\t\t\t# s16 * p_xyz\r\n\t.equr\t\t@idx,\t\t\t%r4\t\t\t\t# u16 * p_index_list\r\n\t.equr\t\t@dot,\t\t\t%r5\t\t\t\t# float * p_dot\r\n\t.equr\t\t@count,\t\t\t%r6\t\t\t\t# int count\r\n\t.equr\t\t@px,\t\t\t%f1\t\t\t\t# float px\r\n\t.equr\t\t@py,\t\t\t%f2\t\t\t\t# float py\r\n\t.equr\t\t@pz,\t\t\t%f3\t\t\t\t# float pz\r\n\r\n\t.equr\t\t@idx0,\t\t\t%r7\r\n\t.equr\t\t@idx1,\t\t\t%r8\r\n\t.equr\t\t@idx2,\t\t\t%r9\r\n\r\n\t.equr\t\t@address,\t\t%r10\r\n\r\n\t.equr\t\t@tmp0,\t\t\t%r11\r\n\t.equr\t\t@tmp1,\t\t\t%r12\r\n\r\n\t.equr\t\t@X0_Y0,\t\t\t%f0\r\n\t.equr\t\t@Z0_nn,\t\t\t%f4\r\n\t.equr\t\t@X1_Y1,\t\t\t%f5\r\n\t.equr\t\t@Z1_nn,\t\t\t%f6\r\n\t.equr\t\t@X2_Y2,\t\t\t%f7\r\n\t.equr\t\t@Z2_nn,\t\t\t%f8\r\n\r\n\t.equr\t\t@XY10,\t\t\t%f9\r\n\t.equr\t\t@Zn10,\t\t\t%f10\r\n\t.equr\t\t@XY20,\t\t\t%f11\r\n\t.equr\t\t@Zn20,\t\t\t%f12\r\n\r\n\t.equr\t\t@P_1X2Z_1Y2Z,\t%f0\t\t// Can re-use 1st set of floats now.\r\n\t.equr\t\t@P_2X1Z_2Y1Z,\t%f4\r\n\t.equr\t\t@P_nnnn_1Y2X,\t%f5\r\n\t.equr\t\t@P_1X2Y_nnnn,\t%f6\r\n\r\n\t.equr\t\t@NX_nn,\t\t\t%f7\r\n\t.equr\t\t@NY_nn,\t\t\t%f8\r\n\t.equr\t\t@NZ_nn,\t\t\t%f9\r\n\r\n\taddi\t\t@idx,\t\t\t@idx,\t\t\t-2\r\n\taddi\t\t@dot,\t\t\t@dot,\t\t\t-4\r\n\r\n\tmtctr   \t@count\r\n@mloop:\r\n\t// Read & Multiply indices by 12.\r\n\tlhzu\t\t@idx0,\t\t\t2(@idx)\r\n\tslwi\t\t@tmp0,\t\t\t@idx0,\t\t\t2\r\n\tslwi\t\t@tmp1,\t\t\t@tmp0,\t\t\t1\r\n\tadd\t\t\t@idx0,\t\t\t@tmp0,\t\t\t@tmp1\r\n\tadd\t\t\t@idx0,\t\t\t@vert,\t\t\t@idx0\r\n\r\n\tlhzu\t\t@idx1,\t\t\t2(@idx)\r\n\tslwi\t\t@tmp0,\t\t\t@idx1,\t\t\t2\r\n\tslwi\t\t@tmp1,\t\t\t@tmp0,\t\t\t1\r\n\tadd\t\t\t@idx1,\t\t\t@tmp0,\t\t\t@tmp1\r\n\tadd\t\t\t@idx1,\t\t\t@vert,\t\t\t@idx1\r\n\r\n\tlhzu\t\t@idx2,\t\t\t2(@idx)\r\n\tslwi\t\t@tmp0,\t\t\t@idx2,\t\t\t2\r\n\tslwi\t\t@tmp1,\t\t\t@tmp0,\t\t\t1\r\n\tadd\t\t\t@idx2,\t\t\t@tmp0,\t\t\t@tmp1\r\n\tadd\t\t\t@idx2,\t\t\t@vert,\t\t\t@idx2\r\n\r\n\t// Read vertices for each corner (sticking with shorts as less data will be read).\r\n\tpsq_l\t\t@X0_Y0,\t\t\t0(@idx0),\t\t0,\t\t\tSKN_GQR_POS\r\n\tpsq_l\t\t@Z0_nn,\t\t\t4(@idx0),\t\t1,\t\t\tSKN_GQR_POS\r\n\tpsq_l\t\t@X1_Y1,\t\t\t0(@idx1),\t\t0,\t\t\tSKN_GQR_POS\r\n\tpsq_l\t\t@Z1_nn,\t\t\t4(@idx1),\t\t1,\t\t\tSKN_GQR_POS\r\n\tpsq_l\t\t@X2_Y2,\t\t\t0(@idx2),\t\t0,\t\t\tSKN_GQR_POS\r\n\tpsq_l\t\t@Z2_nn,\t\t\t4(@idx2),\t\t1,\t\t\tSKN_GQR_POS\r\n\t\r\n\t// Do subtractions for cross product.\r\n\tps_sub\t\t@XY10,\t\t\t@X1_Y1,\t\t\t@X0_Y0\r\n\tps_sub\t\t@Zn10,\t\t\t@Z1_nn,\t\t\t@Z0_nn\r\n\tps_sub\t\t@XY20,\t\t\t@X2_Y2,\t\t\t@X0_Y0\r\n\tps_sub\t\t@Zn20,\t\t\t@Z2_nn,\t\t\t@Z0_nn\r\n\t\r\n\t// Do multiplications for cross product.\r\n\tps_muls0\t@P_1X2Z_1Y2Z,\t@XY10,\t\t\t@Zn20\r\n\tps_muls0\t@P_2X1Z_2Y1Z,\t@XY20,\t\t\t@Zn10\r\n\tps_muls0\t@P_nnnn_1Y2X,\t@XY10,\t\t\t@XY20\r\n\tps_muls1\t@P_1X2Y_nnnn,\t@XY10,\t\t\t@XY20\r\n\tps_merge11\t@P_nnnn_1Y2X,\t@P_nnnn_1Y2X,\t@P_nnnn_1Y2X\r\n\r\n\t// Finish cross product to give surface normal.\r\n\tps_sub\t\t@NX_nn,\t\t\t@P_1X2Z_1Y2Z,\t@P_2X1Z_2Y1Z\t\t// X=1\r\n\tps_sub\t\t@NY_nn,\t\t\t@P_2X1Z_2Y1Z,\t@P_1X2Z_1Y2Z\t\t// Y=0\r\n\tps_sub\t\t@NZ_nn,\t\t\t@P_1X2Y_nnnn,\t@P_nnnn_1Y2X\r\n\tps_merge11\t@NX_nn,\t\t\t@NX_nn,\t\t\t@NX_nn\r\n\r\n\t// Do dot product of projection direction and normal.\r\n\tps_mul\t\t@NX_nn,\t\t\t@px,\t\t\t@NX_nn\r\n\tps_madd\t\t@NY_nn,\t\t\t@py,\t\t\t@NY_nn,\t\t@NX_nn\r\n\tps_madd\t\t@NZ_nn,\t\t\t@pz,\t\t\t@NZ_nn,\t\t@NY_nn\r\n\r\n\t// Write out dot product.\r\n\tpsq_stu \t@NZ_nn, \t\t\t4(@dot), \t\t1, \t\t\tSKN_GQR_UV\r\n\r\n\tbdnz+ @mloop\r\n\tblr\r\n\t.endscope\r\n\r\n#---------------------------------------------------------------------------\r\n# Render shadow volumes.\r\n#---------------------------------------------------------------------------\r\n\r\n\t.scope\r\n\t.global\tRenderShadows\r\nRenderShadows:\r\n\t.equr\t\t@vert,\t\t\t%r3\t\t\t\t# s16 * p_xyz\r\n\t.equr\t\t@idx,\t\t\t%r4\t\t\t\t# u16 * p_index_list\r\n\t.equr\t\t@edge,\t\t\t%r5\t\t\t\t# NxNgc::sShadowEdge * p_neighbor_list \r\n\t.equr\t\t@dot,\t\t\t%r6\t\t\t\t# float * p_dot\r\n\t.equr\t\t@count,\t\t\t%r7\t\t\t\t# int count\r\n\t.equr\t\t@px,\t\t\t%f1\t\t\t\t# float px\r\n\t.equr\t\t@py,\t\t\t%f2\t\t\t\t# float py\r\n\t.equr\t\t@pz,\t\t\t%f3\t\t\t\t# float pz\r\n\t.equr\t\t@tx,\t\t\t%f4\t\t\t\t# float tx\r\n\t.equr\t\t@ty,\t\t\t%f5\t\t\t\t# float ty\r\n   \t.equr\t\t@tz,\t\t\t%f6\t\t\t\t# float tz\r\n\r\n\t.equr\t\t@PX_PY,\t\t\t%f1\t\t\t\t# frees up f2.\r\n\t.equr\t\t@PZ_nn,\t\t\t%f3\r\n\t.equr\t\t@TX_TY,\t\t\t%f4\t\t\t\t# frees up f5.\r\n\t.equr\t\t@TZ_nn,\t\t\t%f6\r\n\r\n\t.equr\t\t@idx0,\t\t\t%r12\r\n\t.equr\t\t@idx1,\t\t\t%r8\r\n\t.equr\t\t@idx2,\t\t\t%r9\r\n\r\n\t.equr\t\t@address,\t\t%r10\r\n\r\n\t.equr\t\t@tmp0,\t\t\t%r11\r\n//\t.equr\t\t@tmp1,\t\t\t%r12\r\n\r\n\t.equr\t\t@FIFO,\t\t\t%r14\r\n\t.equr\t\t@BP,\t\t\t%r15\r\n//\t.equr\t\t@XF,\t\t\t%r16\r\n\t.equr\t\t@BLEND_ADD,\t\t%r17\r\n\t.equr\t\t@BLEND_SUB,\t\t%r18\r\n//\t.equr\t\t@CULL_FRONT,\t%r19\r\n//\t.equr\t\t@CULL_BACK,\t\t%r20\r\n\t.equr\t\t@RZERO,\t\t\t%r21\r\n//\t.equr\t\t@XF_NUMTEX_ID,\t%r22\r\n//\t.equr\t\t@XF_NUMCOL_ID,\t%r23\r\n//\t.equr\t\t@RONE,\t\t\t%r24\r\n\t.equr\t\t@TRISTRIP,\t\t%r25\r\n\t.equr\t\t@NUMVERTS10,\t%r26\r\n\t.equr\t\t@NUMVERTS8,\t\t%r22\r\n\t.equr\t\t@NUMVERTS6,\t\t%r23\r\n\t.equr\t\t@NUMVERTS3,\t\t%r24\r\n\r\n\t.equr\t\t@shape,\t\t\t%r19\r\n\t.equr\t\t@dot_base,\t\t%r20\r\n\r\n\t.equr\t\t@X0_Y0,\t\t\t%f0\r\n\t.equr\t\t@Z0_nn,\t\t\t%f2\r\n\t.equr\t\t@X1_Y1,\t\t\t%f17\r\n\t.equr\t\t@Z1_nn,\t\t\t%f5\r\n\t.equr\t\t@X2_Y2,\t\t\t%f18\r\n\t.equr\t\t@Z2_nn,\t\t\t%f7\r\n\r\n\t.equr\t\t@X3_Y3,\t\t\t%f8\r\n\t.equr\t\t@Z3_nn,\t\t\t%f9\r\n\t.equr\t\t@X4_Y4,\t\t\t%f10\r\n\t.equr\t\t@Z4_nn,\t\t\t%f11\r\n\t.equr\t\t@X5_Y5,\t\t\t%f12\r\n\t.equr\t\t@Z5_nn,\t\t\t%f13\r\n\r\n\t.equr\t\t@DOT,\t\t\t%f14\r\n\t.equr\t\t@ZERO,\t\t\t%f15\r\n\t.equr\t\t@FTEMP,\t\t\t%f16\r\n\r\n\tstwu    %r1, -160(%r1)\r\n\tstfd    %f14, 8(%r1)\r\n\tstfd    %f15, 16(%r1)\r\n\tstfd    %f16, 24(%r1)\r\n\tstfd    %f17, 32(%r1)\r\n\tstfd    %f18, 40(%r1)\r\n\tstw\t\t%r14, 48(%r1)\r\n\tstw\t\t%r15, 52(%r1)\r\n\tstw\t\t%r16, 56(%r1)\r\n\tstw\t\t%r17, 60(%r1)\r\n\tstw\t\t%r18, 64(%r1)\r\n\tstw\t\t%r19, 68(%r1)\r\n\tstw\t\t%r20, 72(%r1)\r\n\tstw\t\t%r21, 76(%r1)\r\n\tstw\t\t%r22, 76(%r1)\r\n\tstw\t\t%r23, 80(%r1)\r\n\tstw\t\t%r24, 84(%r1)\r\n\tstw\t\t%r25, 88(%r1)\r\n\tstw\t\t%r25, 92(%r1)\r\n\tstw\t\t%r26, 96(%r1)\r\n\tstw\t\t%r27, 100(%r1)\r\n\r\n\t// 33222222222211111111110000000000\r\n\t// 10987654321098765432109876543210\r\n\t//\r\n\t// ADD: 0x0131\r\n\t//\r\n\t// 00000000000000000000000100110001\r\n\t//\r\n\t// SUB: 0x0931\r\n\t//\r\n\t// 00000000000000000000100100110001\r\n\r\n\t// 33222222222211111111110000000000\r\n\t// 10987654321098765432109876543210\r\n\t//\r\n\t// FRONT: 0x8010\r\n\t//\r\n\t// 00000000000000001000000000010000\r\n\t//\r\n\t// BACK: 0x4010\r\n\t//\r\n\t// 00000000000000000100000000010000\r\n\r\n\tli\t\t\t@RZERO,\t\t\t0x0\r\n\tlis\t\t\t@FIFO,\t\t\t0xcc01\r\n\taddi\t\t@FIFO,\t\t\t@FIFO,\t\t\t-0x8000\r\n\tli\t\t\t@BP,\t\t\t0x61\r\n//\tli\t\t\t@XF,\t\t\t0x10\r\n\tlis\t\t\t@BLEND_SUB,\t\t0x4100\r\n\taddi\t\t@BLEND_ADD,\t\t@BLEND_SUB,\t\t0x0131 \r\n\taddi\t\t@BLEND_SUB,\t\t@BLEND_SUB,\t\t0x0931\r\n//\tori\t\t\t@CULL_FRONT,\t@RZERO,\t\t\t0x8010\r\n//\tli\t\t\t@CULL_BACK,\t\t0x4010\r\n//\tli\t\t\t@XF_NUMTEX_ID,\t0x103f\r\n//\tli\t\t\t@XF_NUMCOL_ID,\t0x1009\r\n\tli\t\t\t@TRISTRIP,\t\t0x98\r\n\tli\t\t\t@NUMVERTS10,\t10\r\n\tli\t\t\t@NUMVERTS8,\t\t8\r\n\tli\t\t\t@NUMVERTS6,\t\t6\r\n\tli\t\t\t@NUMVERTS3,\t\t3\r\n\r\n\tps_merge00\t@PX_PY,\t\t\t@px,\t\t\t@py\r\n\tps_merge00\t@TX_TY,\t\t\t@tx,\t\t\t@ty\r\n\r\n\tadd\t\t\t@dot_base,\t\t@dot,\t\t\t@RZERO\r\n\r\n\taddi\t\t@edge,\t\t\t@edge,\t\t\t-2\r\n\taddi\t\t@idx,\t\t\t@idx,\t\t\t-2\r\n\taddi\t\t@dot,\t\t\t@dot,\t\t\t-4\r\n\r\n\tps_sub\t\t@ZERO,\t\t\t@ZERO,\t\t\t@ZERO\t// Create 0.0f.\r\n\r\n//\t// Set cull mode.\r\n//\tli\t\t\t@tmp0,\t\t\t0x10\r\n//\tstb\t\t\t@tmp0,\t\t\t(@FIFO)\r\n//\tsth\t\t\t@RZERO,\t\t\t(@FIFO)\r\n//\tli\t\t\t@tmp0,\t\t\t0x103f\r\n//\tsth\t\t\t@tmp0,\t\t\t(@FIFO)\r\n//\tstw\t\t\t@RZERO,\t\t\t(@FIFO)\t\t// Num Tex Gens\r\n//\r\n//\tli\t\t\t@tmp0,\t\t\t0x10\r\n//\tstb\t\t\t@tmp0,\t\t\t(@FIFO)\r\n//\tsth\t\t\t@RZERO,\t\t\t(@FIFO)\r\n//\tli\t\t\t@tmp0,\t\t\t0x1009\r\n//\tsth\t\t\t@tmp0,\t\t\t(@FIFO)\r\n//\tli\t\t\t@tmp0,\t\t\t0x1\r\n//\tstw\t\t\t@tmp0,\t\t\t(@FIFO)\t\t// Num Color Channels.\r\n//\r\n//\tstb\t\t\t@BP,\t\t\t(@FIFO)\r\n//\tori\t\t\t@tmp0,\t\t\t@RZERO,\t\t\t0x8010\t\t// 8010=FRONT, 4010=BACK\r\n//\tstw\t\t\t@tmp0,\t(@FIFO)\r\n\r\n\t// Write out some bullshit data to fix the XF Stall bug.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS10,\t(@FIFO)\r\n\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@ZERO,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\r\n\r\n\tmtctr   \t@count\r\n\r\n@mloopadd:\r\n\t// Read dot product & see if face is visible.\r\n\tpsq_lu\t\t@DOT,\t\t\t4(@dot),\t\t1,\t\t\tSKN_GQR_UV\r\n\r\n\tps_cmpu0\t%cr0,\t\t\t@DOT,\t\t\t@ZERO\r\n\tble\t\t\t@skipadd\r\n\r\n\t// Read neighbor values.\r\n\tlhau\t\t@idx0,\t\t\t2(@edge)\r\n\tlhau\t\t@idx1,\t\t\t2(@edge)\r\n\tlhau\t\t@idx2,\t\t\t2(@edge)\r\n\r\n\tadd\t\t\t@shape,\t\t\t@RZERO,\t\t\t@RZERO\r\n\r\n\t// Check side 01.\r\n\tcmpw\t\t@idx0,\t\t\t@RZERO\r\n\tblt\t\t\t@set01\r\n\tslwi\t\t@idx0,\t\t\t@idx0,\t\t\t2\r\n\tadd\t\t\t@idx0,\t\t\t@idx0,\t\t\t@dot_base\r\n\tpsq_l\t\t@DOT,\t\t\t0(@idx0),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_cmpu0\t%cr0,\t\t\t@DOT,\t\t\t@ZERO\r\n\tbgt\t\t\t@skip01\r\n@set01:\r\n\tori\t\t\t@shape,\t\t\t@shape,\t\t\t1\r\n\r\n@skip01:\r\n\r\n\t// Check side 12.\r\n\tcmpw\t\t@idx1,\t\t\t@RZERO\r\n\tblt\t\t\t@set12\r\n\tslwi\t\t@idx1,\t\t\t@idx1,\t\t\t2\r\n\tadd\t\t\t@idx1,\t\t\t@idx1,\t\t\t@dot_base\r\n\tpsq_l\t\t@DOT,\t\t\t0(@idx1),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_cmpu0\t%cr0,\t\t\t@DOT,\t\t\t@ZERO\r\n\tbgt\t\t\t@skip12\r\n@set12:\r\n\tori\t\t\t@shape,\t\t\t@shape,\t\t\t2\r\n\r\n@skip12:\r\n\r\n\t// Check side 20.\r\n\tcmpw\t\t@idx2,\t\t\t@RZERO\r\n\tblt\t\t\t@set20\r\n\tslwi\t\t@idx2,\t\t\t@idx2,\t\t\t2\r\n\tadd\t\t\t@idx2,\t\t\t@idx2,\t\t\t@dot_base\r\n\tpsq_l\t\t@DOT,\t\t\t0(@idx2),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_cmpu0\t%cr0,\t\t\t@DOT,\t\t\t@ZERO\r\n\tbgt\t\t\t@skip20\r\n@set20:\r\n\tori\t\t\t@shape,\t\t\t@shape,\t\t\t4\r\n\r\n@skip20:\r\n\r\n\t// Read & Multiply indices by 12.\r\n\tlhzu\t\t@idx0,\t\t\t2(@idx)\r\n\tslwi\t\t@tmp0,\t\t\t@idx0,\t\t\t2\r\n\tslwi\t\t@idx0,\t\t\t@tmp0,\t\t\t1\r\n\tadd\t\t\t@idx0,\t\t\t@tmp0,\t\t\t@idx0\r\n\tadd\t\t\t@idx0,\t\t\t@vert,\t\t\t@idx0\r\n\r\n\tlhzu\t\t@idx1,\t\t\t2(@idx)\r\n\tslwi\t\t@tmp0,\t\t\t@idx1,\t\t\t2\r\n\tslwi\t\t@idx1,\t\t\t@tmp0,\t\t\t1\r\n\tadd\t\t\t@idx1,\t\t\t@tmp0,\t\t\t@idx1\r\n\tadd\t\t\t@idx1,\t\t\t@vert,\t\t\t@idx1\r\n\r\n\tlhzu\t\t@idx2,\t\t\t2(@idx)\r\n\tslwi\t\t@tmp0,\t\t\t@idx2,\t\t\t2\r\n\tslwi\t\t@idx2,\t\t\t@tmp0,\t\t\t1\r\n\tadd\t\t\t@idx2,\t\t\t@tmp0,\t\t\t@idx2\r\n\tadd\t\t\t@idx2,\t\t\t@vert,\t\t\t@idx2\r\n\r\n\t// Read vertices for each corner (sticking with shorts as less data will be read).\r\n\tpsq_l\t\t@X0_Y0,\t\t\t0(@idx0),\t\t0,\t\t\tSKN_GQR_POS\r\n\tpsq_l\t\t@Z0_nn,\t\t\t4(@idx0),\t\t1,\t\t\tSKN_GQR_POS\r\n\tpsq_l\t\t@X1_Y1,\t\t\t0(@idx1),\t\t0,\t\t\tSKN_GQR_POS\r\n\tpsq_l\t\t@Z1_nn,\t\t\t4(@idx1),\t\t1,\t\t\tSKN_GQR_POS\r\n\tpsq_l\t\t@X2_Y2,\t\t\t0(@idx2),\t\t0,\t\t\tSKN_GQR_POS\r\n\tpsq_l\t\t@Z2_nn,\t\t\t4(@idx2),\t\t1,\t\t\tSKN_GQR_POS\r\n\r\n\t// Fabricate points 3, 4 & 5.\r\n\tps_add\t\t@X3_Y3,\t\t\t@X0_Y0,\t\t\t@PX_PY\r\n\tps_add\t\t@Z3_nn,\t\t\t@Z0_nn,\t\t\t@PZ_nn\r\n\tps_add\t\t@X4_Y4,\t\t\t@X1_Y1,\t\t\t@PX_PY\r\n\tps_add\t\t@Z4_nn,\t\t\t@Z1_nn,\t\t\t@PZ_nn\r\n\tps_add\t\t@X5_Y5,\t\t\t@X2_Y2,\t\t\t@PX_PY\r\n\tps_add\t\t@Z5_nn,\t\t\t@Z2_nn,\t\t\t@PZ_nn\r\n\r\n\t// Tweak points 0, 1 & 2.\r\n\tps_add\t\t@X0_Y0,\t\t\t@X0_Y0,\t\t\t@TX_TY\r\n\tps_add\t\t@Z0_nn,\t\t\t@Z0_nn,\t\t\t@TZ_nn\r\n\tps_add\t\t@X1_Y1,\t\t\t@X1_Y1,\t\t\t@TX_TY\r\n\tps_add\t\t@Z1_nn,\t\t\t@Z1_nn,\t\t\t@TZ_nn\r\n\tps_add\t\t@X2_Y2,\t\t\t@X2_Y2,\t\t\t@TX_TY\r\n\tps_add\t\t@Z2_nn,\t\t\t@Z2_nn,\t\t\t@TZ_nn\r\n\r\n\t// Set blend mode.\r\n\tstb\t\t\t@BP,\t\t\t(@FIFO)\r\n\tstw\t\t\t@BLEND_ADD,\t\t(@FIFO)\r\n\r\n\t// Check for all shapes.\r\n\tcmpi\t\t%cr0,\t\t\t@shape,\t\t\t0\r\n\tbne\t\t\t@not0\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS3,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS3,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\t// Set blend mode.\r\n\tstb\t\t\t@BP,\t\t\t(@FIFO)\r\n\tstw\t\t\t@BLEND_SUB,\t\t(@FIFO)\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS3,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS3,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tb\t\t\t@overall\r\n@not0:\r\n\r\n\tcmpi\t\t%cr0,           @shape,\t\t\t1\r\n\tbne\t\t\t@not1\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS6,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\t// Set blend mode.\r\n\tstb\t\t\t@BP,\t\t\t(@FIFO)\r\n\tstw\t\t\t@BLEND_SUB,\t\t(@FIFO)\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS6,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tb\t\t\t@overall\r\n@not1:\r\n\r\n\tcmpi\t\t%cr0,           @shape,\t\t\t2\r\n\tbne\t\t\t@not2\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS6,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\t// Set blend mode.\r\n\tstb\t\t\t@BP,\t\t\t(@FIFO)\r\n\tstw\t\t\t@BLEND_SUB,\t\t(@FIFO)\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS6,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tb\t\t\t@overall\r\n@not2:\r\n\r\n\tcmpi\t\t%cr0,           @shape,\t\t\t3\r\n\tbne\t\t\t@not3\r\n\t\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS8,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\t// Set blend mode.\r\n\tstb\t\t\t@BP,\t\t\t(@FIFO)\r\n\tstw\t\t\t@BLEND_SUB,\t\t(@FIFO)\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS8,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tb\t\t\t@overall\r\n@not3:\r\n\r\n\tcmpi\t\t%cr0,           @shape,\t\t\t4\r\n\tbne\t\t\t@not4\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS6,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\t// Set blend mode.\r\n\tstb\t\t\t@BP,\t\t\t(@FIFO)\r\n\tstw\t\t\t@BLEND_SUB,\t\t(@FIFO)\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS6,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\t\t\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tb\t\t\t@overall\r\n@not4:\r\n\t\t\r\n\tcmpi\t\t%cr0,           @shape,\t\t\t5\r\n\tbne\t\t\t@not5\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS8,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\t// Set blend mode.\r\n\tstb\t\t\t@BP,\t\t\t(@FIFO)\r\n\tstw\t\t\t@BLEND_SUB,\t\t(@FIFO)\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS8,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tb\t\t\t@overall\r\n@not5:\r\n\t\r\n\tcmpi\t\t%cr0,           @shape,\t\t\t6\r\n\tbne\t\t\t@not6\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS8,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\t// Set blend mode.\r\n\tstb\t\t\t@BP,\t\t\t(@FIFO)\r\n\tstw\t\t\t@BLEND_SUB,\t\t(@FIFO)\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS8,\t\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tb\t\t\t@overall\r\n@not6:\r\n\t\t\r\n\tcmpi\t\t%cr0,           @shape,\t\t\t7\r\n\tbne\t\t\t@not7\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS10,\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\t// Set blend mode.\r\n\tstb\t\t\t@BP,\t\t\t(@FIFO)\r\n\tstw\t\t\t@BLEND_SUB,\t\t(@FIFO)\r\n\r\n\t// Write mesh.\r\n\tstb\t\t\t@TRISTRIP,\t\t(@FIFO)\r\n\tsth\t\t\t@NUMVERTS10,\t(@FIFO)\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),\t\t1,\t\t\tSKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X4_Y4,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X4_Y4,\t\t\t@X4_Y4\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z4_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X1_Y1,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X1_Y1,\t\t\t@X1_Y1\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z1_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X0_Y0,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X0_Y0,\t\t\t@X0_Y0\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z0_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X2_Y2,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X2_Y2,\t\t\t@X2_Y2\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z2_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X3_Y3,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X3_Y3,\t\t\t@X3_Y3\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z3_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n\tpsq_st\t\t@X5_Y5,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tps_merge11\t@FTEMP,\t\t\t@X5_Y5,\t\t\t@X5_Y5\r\n\tpsq_st\t\t@FTEMP,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\tpsq_st\t\t@Z5_nn,\t\t\t0(@FIFO),       1,          SKN_GQR_UV\r\n\r\n@not7:\r\n@overall:\r\n\r\n\tbdnz+\t\t@mloopadd\r\n\tb\t\t\t@overskip\r\n\r\n@skipadd:\r\n\taddi\t\t@idx,\t\t\t@idx,\t\t\t6\r\n\taddi\t\t@edge,\t\t\t@edge,\t\t\t6\r\n\tbdnz+\t\t@mloopadd\r\n@overskip:\r\n\t\t\r\n\tlfd    %f14, 8(%r1)\r\n\tlfd    %f15, 16(%r1)\r\n\tlfd    %f16, 24(%r1)\r\n\tlfd    %f17, 32(%r1)\r\n\tlfd    %f18, 40(%r1)\r\n\tlwz\t   %r14, 48(%r1)\r\n\tlwz\t   %r15, 52(%r1)\r\n\tlwz\t   %r16, 56(%r1)\r\n\tlwz\t   %r17, 60(%r1)\r\n\tlwz\t   %r18, 64(%r1)\r\n\tlwz\t   %r19, 68(%r1)\r\n\tlwz\t   %r20, 72(%r1)\r\n\tlwz\t   %r21, 76(%r1)\r\n\tlwz\t   %r22, 76(%r1)\r\n\tlwz\t   %r23, 80(%r1)\r\n\tlwz\t   %r24, 84(%r1)\r\n\tlwz\t   %r25, 88(%r1)\r\n\tlwz\t   %r25, 92(%r1)\r\n\tlwz\t   %r26, 96(%r1)\r\n\tlwz\t   %r27, 100(%r1)\r\n\taddi    %r1, %r1, 160\r\n\tblr\r\n\t.endscope\r\n\r\n//#---------------------------------------------------------------------------\r\n//#  Name:         SKN1Vecs16Norms16\r\n//#\r\n//#  Description:  Transforms array of vertex-normal pairs.\r\n//#\r\n//#                Differs from a standard matrix-vector multiply in that the\r\n//#                normals are not translated.  Before you ask, no, there is \r\n//#                no cycle gain from applying a 3x3 matrix vs. applying a 4x3\r\n//#                matrix.  Also, because we are always doing vertex-normal\r\n//#                pairs, no need to check for odd # of transforms, etc.\r\n//#\r\n//#  Arguments:    m           column-major matrix to apply\r\n//#                srcBase     ptr to source vert/norm pairs\r\n//#                dstBase     ptr to destination, can be same as source\r\n//#                count       number of vert/norm pairs.\r\n//#\r\n//#  Returns:      None.\r\n//#---------------------------------------------------------------------------\r\n//\r\n//\t.scope\r\n//\t.global\tFakeEnvMap\r\n//FakeEnvMap:\r\n//\t# Input parameters.\r\n//\t.equr\t\t@m,\t\t\t\t%r3\t#    ROMtx   m\r\n//\t.equr\t\t@srcPos,\t\t%r4\t#    s16  *srcPos\r\n//\t.equr\t\t@srcNorm,\t\t%r5\t#    s16  *srcNorm\r\n//\t.equr\t\t@dstBase,\t\t%r6\t#    s16  *dstBase\r\n//\t.equr\t\t@count,\t\t\t%r7\t#    u32     count\r\n//\r\n//\t.equr\t\t@M00_M10,\t\t%f0\r\n//\t.equr\t\t@M20_nnn,\t\t%f1\r\n//\t.equr\t\t@M01_M11,\t\t%f2\r\n//\t.equr\t\t@M21_nnn,\t\t%f3\r\n//\t.equr\t\t@M02_M12,\t\t%f4\r\n//\t.equr\t\t@M22_nnn,\t\t%f5\r\n//\t.equr\t\t@M03_M13,\t\t%f6\r\n//\t.equr\t\t@M23_nnn,\t\t%f7\r\n//\r\n//# source vectors - 2 3D vectors in 3 PS registers\r\n//\t.equr\t\t@SX0_SY0,\t\t%f8\r\n//\t.equr\t\t@SZ0_nnn,\t\t%f9\r\n//\t.equr\t\t@nnn_SX1,\t\t%f10\r\n//\t.equr\t\t@SY1_SZ1,\t\t%f11\r\n//\r\n//# Destination registers - 2 3d vectors in 4 PS registers\r\n//\t.equr\t\t@DX0_DY0,\t\t%f12\r\n//\t.equr\t\t@DZ0_nnn,\t\t%f13\r\n//\t.equr\t\t@DX1_DY1,\t\t%f14\r\n//\t.equr\t\t@DZ1_nnn,\t\t%f15\r\n//\r\n//# temp registers for writing back values.  These registers store the final\r\n//# results from the PREVIOUS loop\r\n//\t.equr\t\t@WX0_WY0,\t\t%f16\r\n//\t.equr\t\t@WZ0_nnn,\t\t%f17\r\n//\t.equr\t\t@WX1_WY1,\t\t%f18\r\n//\t.equr\t\t@WZ1_nnn,\t\t%f19\r\n//\r\n//\t.equr\t\t@HALF,\t\t\t%f20\r\n//\t.equr\t\t@ONE,\t\t\t%f21\r\n//\t.equr\t\t@ONEZ,\t\t\t%f22\r\n//\r\n//    stwu    %r1, -96(%r1)\r\n//    stfd    %f14, 8(%r1)\r\n//    stfd    %f15, 16(%r1)\r\n//    addi    @count, @count, -1 // unrolled\r\n//    stfd    %f16, 24(%r1)\r\n//    stfd    %f17, 32(%r1)\r\n//    stfd    %f18, 40(%r1)\r\n//    stfd    %f19, 48(%r1)\r\n//    stfd    %f20, 56(%r1)\r\n//    stfd    %f21, 64(%r1)\r\n//    stfd    %f22, 72(%r1)\r\n//    mtctr   @count\r\n//    \r\n//\tlis     %r9, @half_data@h\r\n//\tori     %r9, %r9, @half_data@l\r\n//\tpsq_l   @HALF, 0(%r9),0,SKN_GQR_UV\r\n//\r\n//\tlis     %r9, @one_data@h\r\n//\tori     %r9, %r9, @one_data@l\r\n//\tpsq_l   @ONE, 0(%r9),0,SKN_GQR_UV\r\n//\r\n//\t// load matrix\r\n//    psq_l   @M00_M10, 0(@m),0,0  \r\n//\taddi    @srcPos, @srcPos, -2\r\n//    addi    @srcNorm, @srcNorm, -4\r\n//    psq_l   @M20_nnn, 8(@m),1,0  \r\n//    addi    @dstBase, @dstBase, -8\r\n//    psq_l   @M03_M13, 36(@m),0,0 \r\n//    psq_lu  @SX0_SY0, 2(@srcPos), 0, SKN_GQR_POS\r\n//    psq_l   @M23_nnn, 44(@m),1,0 \r\n//    psq_lu  @SZ0_nnn, 4(@srcPos), 0, SKN_GQR_POS\r\n//\tpsq_lu  @nnn_SX1, 2(@srcNorm), 0, SKN_GQR_NORM\r\n//\r\n//    // ------------------------------UNROLLED\r\n//\r\n//    // Apply first column and translation term\r\n//    ps_madds0    @DX0_DY0, @M00_M10, @SX0_SY0, @M03_M13\r\n//      psq_l   @M01_M11, 12(@m),0,0\r\n//    ps_madds0    @DZ0_nnn, @M20_nnn, @SX0_SY0, @M23_nnn\r\n//      psq_l   @M21_nnn, 20(@m),1,0   \r\n//    ps_muls1     @DX1_DY1, @M00_M10, @nnn_SX1  // no trans for norms\r\n//      psq_lu  @SY1_SZ1,4(@srcNorm), 0, SKN_GQR_NORM\r\n//    ps_muls1     @DZ1_nnn, @M20_nnn, @nnn_SX1  // no trans for norms\r\n//      psq_l   @M22_nnn, 32(@m),1,0 \r\n//\r\n//    // Apply second column\r\n//     ps_madds1    @DX0_DY0, @M01_M11, @SX0_SY0, @DX0_DY0\r\n//    ps_madds1    @DZ0_nnn, @M21_nnn, @SX0_SY0, @DZ0_nnn\r\n//      psq_l   @M02_M12, 24(@m),0,0 \r\n//    ps_madds0    @DX1_DY1, @M01_M11, @SY1_SZ1, @DX1_DY1\r\n//      psq_lu @SX0_SY0, 2(@srcPos), 0, SKN_GQR_POS\r\n//    ps_madds0    @DZ1_nnn, @M21_nnn, @SY1_SZ1, @DZ1_nnn\r\n//\r\n//    // Apply third column and Write final values to temp W registers\r\n//    ps_madds0    @WX0_WY0, @M02_M12, @SZ0_nnn, @DX0_DY0\r\n//    ps_madds0    @WZ0_nnn, @M22_nnn, @SZ0_nnn, @DZ0_nnn\r\n//      psq_lu @SZ0_nnn, 4(@srcPos), 0, SKN_GQR_POS\r\n//    ps_madds1    @WX1_WY1, @M02_M12, @SY1_SZ1, @DX1_DY1\r\n//\t  psq_lu @nnn_SX1,2(@srcNorm), 0, SKN_GQR_NORM\r\n//    ps_madds1    @WZ1_nnn, @M22_nnn, @SY1_SZ1, @DZ1_nnn\r\n//      psq_lu @SY1_SZ1,4(@srcNorm), 0, SKN_GQR_NORM\r\n//\r\n//    // -------------------------- LOOP START\r\n//@mloop:\r\n//    ps_madds0    @DX0_DY0, @M00_M10, @SX0_SY0, @M03_M13\r\n//\r\n//;//\tps_neg\t\t @WX1_WY1, @WX1_WY1\r\n//\t\tps_div\t\t@ONEZ, @ONE, @WZ0_nnn\t\t\t\t// Calculate 1/z to 0\r\n//    ps_madds0    @DZ0_nnn, @M20_nnn, @SX0_SY0, @M23_nnn\r\n//\t\tps_madds0   @WX1_WY1, @WX0_WY0, @ONEZ, @WX1_WY1\t\t// x,y * 1/z + nx,ny.\r\n//    ps_muls1     @DX1_DY1, @M00_M10, @nnn_SX1\r\n//\t\tps_madd\t\t @WX1_WY1, @WX1_WY1, @HALF, @HALF\t\t// (x.y*.5)+.5 instead of (x.y+1)*.5\r\n//    ps_muls1     @DZ1_nnn, @M20_nnn, @nnn_SX1\r\n//\t\tpsq_stu     @WX1_WY1, 8(@dstBase), 0, SKN_GQR_UV\r\n//    ps_madds1    @DX0_DY0, @M01_M11, @SX0_SY0, @DX0_DY0\r\n//    ps_madds1    @DZ0_nnn, @M21_nnn, @SX0_SY0, @DZ0_nnn\r\n//      psq_lu @SX0_SY0, 2(@srcPos), 0, SKN_GQR_POS // NEXT SX0 SY0\r\n//    ps_madds0    @DX1_DY1, @M01_M11, @SY1_SZ1, @DX1_DY1\r\n//    ps_madds0    @DZ1_nnn, @M21_nnn, @SY1_SZ1, @DZ1_nnn\r\n//\r\n//    // Write final values to temp registers\r\n//    ps_madds0    @WX0_WY0, @M02_M12, @SZ0_nnn, @DX0_DY0\r\n//    ps_madds0    @WZ0_nnn, @M22_nnn, @SZ0_nnn, @DZ0_nnn\r\n//      psq_lu @SZ0_nnn, 4(@srcPos), 0, SKN_GQR_POS // NEXT SZ0 SX1\r\n//    ps_madds1    @WX1_WY1, @M02_M12, @SY1_SZ1, @DX1_DY1\r\n//\t\tpsq_lu @nnn_SX1,2(@srcNorm), 0, SKN_GQR_NORM // NEXT SY1 SZ1\r\n//    ps_madds1    @WZ1_nnn, @M22_nnn, @SY1_SZ1, @DZ1_nnn\r\n//      psq_lu @SY1_SZ1,4(@srcNorm), 0, SKN_GQR_NORM // NEXT SY1 SZ1\r\n//\r\n//    bdnz+ @mloop    // -------------------------- LOOP END\r\n//\r\n//;//\tps_neg\t\t @WX1_WY1, @WX1_WY1\r\n//\tps_div\t\t@ONEZ, @ONE, @WZ0_nnn\t\t\t\t// Calculate 1/z to 0\r\n//\tps_madds0   @WX1_WY1, @WX0_WY0, @ONEZ, @WX1_WY1\t\t// x,y * 1/z + nx,ny.\r\n//\tps_madd\t @WX1_WY1, @WX1_WY1, @HALF, @HALF\t\t// (x,y*.5)+.5 instead of (x,y+1)*.5\r\n//\r\n//    psq_stu     @WX1_WY1, 8(@dstBase), 0, SKN_GQR_UV\r\n//\r\n//\r\n//@return:    \r\n//    lfd     %f14, 8(%r1)\r\n//    lfd     %f15, 16(%r1)\r\n//    lfd     %f16, 24(%r1)\r\n//    lfd     %f17, 32(%r1)\r\n//    lfd     %f18, 40(%r1)\r\n//    lfd     %f19, 48(%r1)\r\n//    lfd     %f20, 56(%r1)\r\n//    lfd     %f21, 64(%r1)\r\n//    lfd     %f22, 72(%r1)\r\n//    addi    %r1, %r1, 96\r\n//    blr\r\n//\r\n//@half_data:\r\n//\t.float\t(0.5)\r\n//\t.float\t(0.5)\r\n//\t.float\t(0.5)\r\n//\t.float\t(0.5)\r\n//\r\n//@one_data:\r\n//\t.float\t(1.0)\r\n//\t.float\t(1.0)\r\n//\t.float\t(1.0)\r\n//\t.float\t(1.0)\r\n//\r\n//\t.endscope\r\n//\r\n//;//---------------------------------------------------------------------\r\n//;//---------------------------------------------------------------------\r\n//;//---------------------------------------------------------------------\r\n//\r\n//\t.scope\r\n//\t.global\tFakeEnvMapFloat\r\n//FakeEnvMapFloat:\r\n//\t# Input parameters.\r\n//\t.equr\t\t@m,\t\t\t\t%r3\t#    ROMtx   m\r\n//\t.equr\t\t@srcPos,\t\t%r4\t#    float  *srcPos\r\n//\t.equr\t\t@srcNorm,\t\t%r5\t#    s16  *srcNorm\r\n//\t.equr\t\t@dstBase,\t\t%r6\t#    s16  *dstBase\r\n//\t.equr\t\t@count,\t\t\t%r7\t#    u32     count\r\n//\r\n//\t.equr\t\t@M00_M10,\t\t%f0\r\n//\t.equr\t\t@M20_nnn,\t\t%f1\r\n//\t.equr\t\t@M01_M11,\t\t%f2\r\n//\t.equr\t\t@M21_nnn,\t\t%f3\r\n//\t.equr\t\t@M02_M12,\t\t%f4\r\n//\t.equr\t\t@M22_nnn,\t\t%f5\r\n//\t.equr\t\t@M03_M13,\t\t%f6\r\n//\t.equr\t\t@M23_nnn,\t\t%f7\r\n//\r\n//# source vectors - 2 3D vectors in 3 PS registers\r\n//\t.equr\t\t@SX0_SY0,\t\t%f8\r\n//\t.equr\t\t@SZ0_nnn,\t\t%f9\r\n//\t.equr\t\t@nnn_SX1,\t\t%f10\r\n//\t.equr\t\t@SY1_SZ1,\t\t%f11\r\n//\r\n//# Destination registers - 2 3d vectors in 4 PS registers\r\n//\t.equr\t\t@DX0_DY0,\t\t%f12\r\n//\t.equr\t\t@DZ0_nnn,\t\t%f13\r\n//\t.equr\t\t@DX1_DY1,\t\t%f14\r\n//\t.equr\t\t@DZ1_nnn,\t\t%f15\r\n//\r\n//# temp registers for writing back values.  These registers store the final\r\n//# results from the PREVIOUS loop\r\n//\t.equr\t\t@WX0_WY0,\t\t%f16\r\n//\t.equr\t\t@WZ0_nnn,\t\t%f17\r\n//\t.equr\t\t@WX1_WY1,\t\t%f18\r\n//\t.equr\t\t@WZ1_nnn,\t\t%f19\r\n//\r\n//\t.equr\t\t@HALF,\t\t\t%f20\r\n//\t.equr\t\t@ONE,\t\t\t%f21\r\n//\t.equr\t\t@ONEZ,\t\t\t%f22\r\n//\r\n//\tstwu    %r1, -96(%r1)\r\n//\tstfd    %f14, 8(%r1)\r\n//\tstfd    %f15, 16(%r1)\r\n//\taddi    @count, @count, -1 // unrolled\r\n//\tstfd    %f16, 24(%r1)\r\n//\tstfd    %f17, 32(%r1)\r\n//\tstfd    %f18, 40(%r1)\r\n//\tstfd    %f19, 48(%r1)\r\n//\tstfd    %f20, 56(%r1)\r\n//\tstfd    %f21, 64(%r1)\r\n//\tstfd    %f22, 72(%r1)\r\n//\tmtctr   @count\r\n//\r\n//\tlis     %r9, @half_data@h\r\n//\tori     %r9, %r9, @half_data@l\r\n//\tpsq_l   @HALF, 0(%r9),0,SKN_GQR_UV\r\n//\r\n//\tlis     %r9, @one_data@h\r\n//\tori     %r9, %r9, @one_data@l\r\n//\tpsq_l   @ONE, 0(%r9),0,SKN_GQR_UV\r\n//\r\n//\t// load matrix\r\n//\tpsq_l   @M00_M10, 0(@m),0,0  \r\n//\taddi    @srcPos, @srcPos, -4\r\n//\taddi    @srcNorm, @srcNorm, -4\r\n//\tpsq_l   @M20_nnn, 8(@m),1,0  \r\n//\taddi    @dstBase, @dstBase, -8\r\n//\tpsq_l   @M03_M13, 36(@m),0,0 \r\n//\tpsq_lu  @SX0_SY0, 4(@srcPos), 0, SKN_GQR_UV\r\n//\tpsq_l   @M23_nnn, 44(@m),1,0 \r\n//\tpsq_lu  @SZ0_nnn, 8(@srcPos), 0, SKN_GQR_UV\r\n//\tpsq_lu  @nnn_SX1, 2(@srcNorm), 0, SKN_GQR_NORM\r\n//\r\n//\t// ------------------------------UNROLLED\r\n//\r\n//\t// Apply first column and translation term\r\n//\tps_madds0    @DX0_DY0, @M00_M10, @SX0_SY0, @M03_M13\r\n//\t  psq_l   @M01_M11, 12(@m),0,0\r\n//\tps_madds0    @DZ0_nnn, @M20_nnn, @SX0_SY0, @M23_nnn\r\n//\t  psq_l   @M21_nnn, 20(@m),1,0   \r\n//\tps_muls1     @DX1_DY1, @M00_M10, @nnn_SX1  // no trans for norms\r\n//\t  psq_lu  @SY1_SZ1,4(@srcNorm), 0, SKN_GQR_NORM\r\n//\tps_muls1     @DZ1_nnn, @M20_nnn, @nnn_SX1  // no trans for norms\r\n//\t  psq_l   @M22_nnn, 32(@m),1,0 \r\n//\r\n//\t// Apply second column\r\n//\t ps_madds1    @DX0_DY0, @M01_M11, @SX0_SY0, @DX0_DY0\r\n//\tps_madds1    @DZ0_nnn, @M21_nnn, @SX0_SY0, @DZ0_nnn\r\n//\t  psq_l   @M02_M12, 24(@m),0,0 \r\n//\tps_madds0    @DX1_DY1, @M01_M11, @SY1_SZ1, @DX1_DY1\r\n//\t  psq_lu @SX0_SY0, 4(@srcPos), 0, SKN_GQR_UV\r\n//\tps_madds0    @DZ1_nnn, @M21_nnn, @SY1_SZ1, @DZ1_nnn\r\n//\r\n//\t// Apply third column and Write final values to temp W registers\r\n//\tps_madds0    @WX0_WY0, @M02_M12, @SZ0_nnn, @DX0_DY0\r\n//\tps_madds0    @WZ0_nnn, @M22_nnn, @SZ0_nnn, @DZ0_nnn\r\n//\t  psq_lu @SZ0_nnn, 8(@srcPos), 0, SKN_GQR_UV\r\n//\tps_madds1    @WX1_WY1, @M02_M12, @SY1_SZ1, @DX1_DY1\r\n//\t  psq_lu @nnn_SX1,2(@srcNorm), 0, SKN_GQR_NORM\r\n//\tps_madds1    @WZ1_nnn, @M22_nnn, @SY1_SZ1, @DZ1_nnn\r\n//\t  psq_lu @SY1_SZ1,4(@srcNorm), 0, SKN_GQR_NORM\r\n//\r\n//\t// -------------------------- LOOP START\r\n//@mloop:\r\n//\tps_madds0    @DX0_DY0, @M00_M10, @SX0_SY0, @M03_M13\r\n//\r\n//;//\tps_neg\t\t @WX1_WY1, @WX1_WY1\r\n//\t\tps_div\t\t@ONEZ, @ONE, @WZ0_nnn\t\t\t\t// Calculate 1/z to 0\r\n//\tps_madds0    @DZ0_nnn, @M20_nnn, @SX0_SY0, @M23_nnn\r\n//\t\tps_madds0   @WX1_WY1, @WX0_WY0, @ONEZ, @WX1_WY1\t\t// x,y * 1/z + nx,ny.\r\n//\tps_muls1     @DX1_DY1, @M00_M10, @nnn_SX1\r\n//\t\tps_madd\t\t @WX1_WY1, @WX1_WY1, @HALF, @HALF\t\t// (x.y*.5)+.5 instead of (x.y+1)*.5\r\n//\tps_muls1     @DZ1_nnn, @M20_nnn, @nnn_SX1\r\n//\t\tpsq_stu     @WX1_WY1, 8(@dstBase), 0, SKN_GQR_UV\r\n//\tps_madds1    @DX0_DY0, @M01_M11, @SX0_SY0, @DX0_DY0\r\n//\tps_madds1    @DZ0_nnn, @M21_nnn, @SX0_SY0, @DZ0_nnn\r\n//\t  psq_lu @SX0_SY0, 4(@srcPos), 0, SKN_GQR_UV // NEXT SX0 SY0\r\n//\tps_madds0    @DX1_DY1, @M01_M11, @SY1_SZ1, @DX1_DY1\r\n//\tps_madds0    @DZ1_nnn, @M21_nnn, @SY1_SZ1, @DZ1_nnn\r\n//\r\n//\t// Write final values to temp registers\r\n//\tps_madds0    @WX0_WY0, @M02_M12, @SZ0_nnn, @DX0_DY0\r\n//\tps_madds0    @WZ0_nnn, @M22_nnn, @SZ0_nnn, @DZ0_nnn\r\n//\t  psq_lu @SZ0_nnn, 8(@srcPos), 0, SKN_GQR_UV // NEXT SZ0 SX1\r\n//\tps_madds1    @WX1_WY1, @M02_M12, @SY1_SZ1, @DX1_DY1\r\n//\t\tpsq_lu @nnn_SX1,2(@srcNorm), 0, SKN_GQR_NORM // NEXT SY1 SZ1\r\n//\tps_madds1    @WZ1_nnn, @M22_nnn, @SY1_SZ1, @DZ1_nnn\r\n//\t  psq_lu @SY1_SZ1,4(@srcNorm), 0, SKN_GQR_NORM // NEXT SY1 SZ1\r\n//\r\n//\tbdnz+ @mloop    // -------------------------- LOOP END\r\n//\r\n//;//\tps_neg\t\t @WX1_WY1, @WX1_WY1\r\n//\tps_div\t\t@ONEZ, @ONE, @WZ0_nnn\t\t\t\t// Calculate 1/z to 0\r\n//\tps_madds0   @WX1_WY1, @WX0_WY0, @ONEZ, @WX1_WY1\t\t// x,y * 1/z + nx,ny.\r\n//\tps_madd\t @WX1_WY1, @WX1_WY1, @HALF, @HALF\t\t// (x,y*.5)+.5 instead of (x,y+1)*.5\r\n//\r\n//\tpsq_stu     @WX1_WY1, 8(@dstBase), 0, SKN_GQR_UV\r\n//\r\n//\r\n//@return:    \r\n//\tlfd     %f14, 8(%r1)\r\n//\tlfd     %f15, 16(%r1)\r\n//\tlfd     %f16, 24(%r1)\r\n//\tlfd     %f17, 32(%r1)\r\n//\tlfd     %f18, 40(%r1)\r\n//\tlfd     %f19, 48(%r1)\r\n//\tlfd     %f20, 56(%r1)\r\n//\tlfd     %f21, 64(%r1)\r\n//\tlfd     %f22, 72(%r1)\r\n//\taddi    %r1, %r1, 96\r\n//\tblr\r\n//\r\n//@half_data:\r\n//\t.float\t(0.5)\r\n//\t.float\t(0.5)\r\n//\t.float\t(0.5)\r\n//\t.float\t(0.5)\r\n//\r\n//@one_data:\r\n//\t.float\t(1.0)\r\n//\t.float\t(1.0)\r\n//\t.float\t(1.0)\r\n//\t.float\t(1.0)\r\n//\r\n//\t.endscope\r\n//\r\n//;//---------------------------------------------------------------------\r\n//;//---------------------------------------------------------------------\r\n//;//---------------------------------------------------------------------\r\n//\r\n//\t.scope\r\n//\t.global\tFakeEnvMapSkin\r\n//FakeEnvMapSkin:\r\n//\t# Input parameters.\r\n//\t.equr\t\t@m,\t\t\t\t%r3\t#    ROMtx   m\r\n//\t.equr\t\t@srcPosNorm,\t%r4\t#    s16  *srcPosNorm\r\n//\t.equr\t\t@dstBase,\t\t%r5\t#    s16  *dstBase\r\n//\t.equr\t\t@count,\t\t\t%r6\t#    u32     count\r\n//\r\n//\t.equr\t\t@M00_M10,\t\t%f0\r\n//\t.equr\t\t@M20_nnn,\t\t%f1\r\n//\t.equr\t\t@M01_M11,\t\t%f2\r\n//\t.equr\t\t@M21_nnn,\t\t%f3\r\n//\t.equr\t\t@M02_M12,\t\t%f4\r\n//\t.equr\t\t@M22_nnn,\t\t%f5\r\n//\t.equr\t\t@M03_M13,\t\t%f6\r\n//\t.equr\t\t@M23_nnn,\t\t%f7\r\n//\r\n//# source vectors - 2 3D vectors in 3 PS registers\r\n//\t.equr\t\t@SX0_SY0,\t\t%f8\r\n//\t.equr\t\t@SZ0_SX1,\t\t%f9\r\n//\t.equr\t\t@SY1_SZ1,\t\t%f10\r\n//\r\n//# Destination registers - 2 3d vectors in 4 PS registers\r\n//\t.equr\t\t@DX0_DY0,\t\t%f11\r\n//\t.equr\t\t@DZ0_nnn,\t\t%f12\r\n//\t.equr\t\t@DX1_DY1,\t\t%f13\r\n//\t.equr\t\t@DZ1_nnn,\t\t%f14\r\n//\r\n//# temp registers for writing back values.  These registers store the final\r\n//# results from the PREVIOUS loop\r\n//\t.equr\t\t@WX0_WY0,\t\t%f15\r\n//\t.equr\t\t@WZ0_nnn,\t\t%f16\r\n//\t.equr\t\t@WX1_WY1,\t\t%f17\r\n//\t.equr\t\t@WZ1_nnn,\t\t%f18\r\n//\r\n//\t.equr\t\t@HALF,\t\t\t%f19\r\n//\t.equr\t\t@ONE,\t\t\t%f20\r\n//\t.equr\t\t@ONEZ,\t\t\t%f21\r\n//\r\n//\tstwu    %r1, -96(%r1)\r\n//\tstfd    %f14, 8(%r1)\r\n//\tstfd    %f15, 16(%r1)\r\n//\taddi    @count, @count, -1 // unrolled\r\n//\tstfd    %f16, 24(%r1)\r\n//\tstfd    %f17, 32(%r1)\r\n//\tstfd    %f18, 40(%r1)\r\n//\tstfd    %f19, 48(%r1)\r\n//\tstfd    %f20, 56(%r1)\r\n//\tstfd    %f21, 64(%r1)\r\n//\tmtctr   @count\r\n//\t\r\n//\tlis     %r9, @half_data@h\r\n//\tori     %r9, %r9, @half_data@l\r\n//\tpsq_l   @HALF, 0(%r9),0,SKN_GQR_UV\r\n//\r\n//\tlis     %r9, @one_data@h\r\n//\tori     %r9, %r9, @one_data@l\r\n//\tpsq_l   @ONE, 0(%r9),0,SKN_GQR_UV\r\n//\r\n//\t// load matrix\r\n//\tpsq_l   @M00_M10, 0(@m),0,0  \r\n//\taddi    @srcPosNorm, @srcPosNorm, -4\r\n//\tpsq_l   @M20_nnn, 8(@m),1,0  \r\n//\taddi    @dstBase, @dstBase, -8\r\n//\tpsq_l   @M03_M13, 36(@m),0,0 \r\n//\tpsq_lu  @SX0_SY0, 4(@srcPosNorm), 0, SKN_GQR_POS\r\n//\tpsq_l   @M23_nnn, 44(@m),1,0 \r\n//\tpsq_lu  @SZ0_SX1, 4(@srcPosNorm), 0, SKN_GQR_POS\r\n//\r\n//\t// ------------------------------UNROLLED\r\n//\r\n//\t// Apply first column and translation term\r\n//\tps_madds0    @DX0_DY0, @M00_M10, @SX0_SY0, @M03_M13\r\n//\t  psq_l   @M01_M11, 12(@m),0,0\r\n//\tps_madds0    @DZ0_nnn, @M20_nnn, @SX0_SY0, @M23_nnn\r\n//\t  psq_l   @M21_nnn, 20(@m),1,0   \r\n//\tps_muls1     @DX1_DY1, @M00_M10, @SZ0_SX1  // no trans for norms\r\n//\t  psq_lu  @SY1_SZ1,4(@srcPosNorm), 0, SKN_GQR_POS\r\n//\tps_muls1     @DZ1_nnn, @M20_nnn, @SZ0_SX1  // no trans for norms\r\n//\t  psq_l   @M22_nnn, 32(@m),1,0 \r\n//\r\n//\t// Apply second column\r\n//\t ps_madds1    @DX0_DY0, @M01_M11, @SX0_SY0, @DX0_DY0\r\n//\tps_madds1    @DZ0_nnn, @M21_nnn, @SX0_SY0, @DZ0_nnn\r\n//\t  psq_l   @M02_M12, 24(@m),0,0 \r\n//\tps_madds0    @DX1_DY1, @M01_M11, @SY1_SZ1, @DX1_DY1\r\n//\t  psq_lu @SX0_SY0, 4(@srcPosNorm), 0, SKN_GQR_POS\r\n//\tps_madds0    @DZ1_nnn, @M21_nnn, @SY1_SZ1, @DZ1_nnn\r\n//\r\n//\t// Apply third column and Write final values to temp W registers\r\n//\tps_madds0    @WX0_WY0, @M02_M12, @SZ0_SX1, @DX0_DY0\r\n//\tps_madds0    @WZ0_nnn, @M22_nnn, @SZ0_SX1, @DZ0_nnn\r\n//\t  psq_lu @SZ0_SX1, 4(@srcPosNorm), 0, SKN_GQR_POS\r\n//\tps_madds1    @WX1_WY1, @M02_M12, @SY1_SZ1, @DX1_DY1\r\n//\tps_madds1    @WZ1_nnn, @M22_nnn, @SY1_SZ1, @DZ1_nnn\r\n//\t  psq_lu @SY1_SZ1,4(@srcPosNorm), 0, SKN_GQR_POS\r\n//\r\n//\t// -------------------------- LOOP START\r\n//@mloop:\r\n//\tps_madds0    @DX0_DY0, @M00_M10, @SX0_SY0, @M03_M13\r\n//\r\n//;//\tps_neg\t\t @WX1_WY1, @WX1_WY1\r\n//\t\tps_div\t\t@ONEZ, @ONE, @WZ0_nnn\t\t\t\t// Calculate 1/z to 0\r\n//\tps_madds0    @DZ0_nnn, @M20_nnn, @SX0_SY0, @M23_nnn\r\n//\t\tps_madds0   @WX1_WY1, @WX0_WY0, @ONEZ, @WX1_WY1\t\t// x,y * 1/z + nx,ny.\r\n//\tps_muls1     @DX1_DY1, @M00_M10, @SZ0_SX1\r\n//\t\tps_madd\t\t @WX1_WY1, @WX1_WY1, @HALF, @HALF\t\t// (x.y*.5)+.5 instead of (x.y+1)*.5\r\n//\tps_muls1     @DZ1_nnn, @M20_nnn, @SZ0_SX1\r\n//\t\tpsq_stu     @WX1_WY1, 8(@dstBase), 0, SKN_GQR_UV\r\n//\tps_madds1    @DX0_DY0, @M01_M11, @SX0_SY0, @DX0_DY0\r\n//\tps_madds1    @DZ0_nnn, @M21_nnn, @SX0_SY0, @DZ0_nnn\r\n//\t  psq_lu @SX0_SY0, 4(@srcPosNorm), 0, SKN_GQR_POS // NEXT SX0 SY0\r\n//\tps_madds0    @DX1_DY1, @M01_M11, @SY1_SZ1, @DX1_DY1\r\n//\tps_madds0    @DZ1_nnn, @M21_nnn, @SY1_SZ1, @DZ1_nnn\r\n//\r\n//\t// Write final values to temp registers\r\n//\tps_madds0    @WX0_WY0, @M02_M12, @SZ0_SX1, @DX0_DY0\r\n//\tps_madds0    @WZ0_nnn, @M22_nnn, @SZ0_SX1, @DZ0_nnn\r\n//\t  psq_lu @SZ0_SX1, 4(@srcPosNorm), 0, SKN_GQR_POS // NEXT SZ0 SX1\r\n//\tps_madds1    @WX1_WY1, @M02_M12, @SY1_SZ1, @DX1_DY1\r\n//\tps_madds1    @WZ1_nnn, @M22_nnn, @SY1_SZ1, @DZ1_nnn\r\n//\t  psq_lu @SY1_SZ1,4(@srcPosNorm), 0, SKN_GQR_POS // NEXT SY1 SZ1\r\n//\r\n//\tbdnz+ @mloop    // -------------------------- LOOP END\r\n//\r\n//;//\tps_neg\t\t @WX1_WY1, @WX1_WY1\r\n//\tps_div\t\t@ONEZ, @ONE, @WZ0_nnn\t\t\t\t// Calculate 1/z to 0\r\n//\tps_madds0   @WX1_WY1, @WX0_WY0, @ONEZ, @WX1_WY1\t\t// x,y * 1/z + nx,ny.\r\n//\tps_madd\t @WX1_WY1, @WX1_WY1, @HALF, @HALF\t\t// (x,y*.5)+.5 instead of (x,y+1)*.5\r\n//\r\n//\tpsq_stu     @WX1_WY1, 8(@dstBase), 0, SKN_GQR_UV\r\n//\r\n//\r\n//@return:    \r\n//\tlfd     %f14, 8(%r1)\r\n//\tlfd     %f15, 16(%r1)\r\n//\tlfd     %f16, 24(%r1)\r\n//\tlfd     %f17, 32(%r1)\r\n//\tlfd     %f18, 40(%r1)\r\n//\tlfd     %f19, 48(%r1)\r\n//\tlfd     %f20, 56(%r1)\r\n//\tlfd     %f21, 64(%r1)\r\n//\taddi    %r1, %r1, 96\r\n//\tblr\r\n//\r\n//@half_data:\r\n//\t.float\t(0.5)\r\n//\t.float\t(0.5)\r\n//\t.float\t(0.5)\r\n//\t.float\t(0.5)\r\n//\r\n//@one_data:\r\n//\t.float\t(1.0)\r\n//\t.float\t(1.0)\r\n//\t.float\t(1.0)\r\n//\t.float\t(1.0)\r\n//\r\n//\t.endscope\r\n//\r\n//;//---------------------------------------------------------------------\r\n//;//---------------------------------------------------------------------\r\n//;//---------------------------------------------------------------------\r\n//\r\n//\r\n//\r\n//\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n;//\t# Input parameters.\r\n;//\t.equr\t\t@m,\t\t\t\t%r3\t#    ROMtx   m\r\n;//\t.equr\t\t@srcBase,\t\t%r4\t#    float  *srcBase\r\n;//\t.equr\t\t@dstBase,\t\t%r5\t#    float  *dstBase\r\n;//\t.equr\t\t@count,\t\t\t%r6\t#    u32     count\r\n;//\r\n;//\t.equr\t\t@M00_M10,\t\t%f0\r\n;//\t.equr\t\t@M20_nnn,\t\t%f1\r\n;//\t.equr\t\t@M01_M11,\t\t%f2\r\n;//\t.equr\t\t@M21_nnn,\t\t%f3\r\n;//\t.equr\t\t@M02_M12,\t\t%f4\r\n;//\t.equr\t\t@M22_nnn,\t\t%f5\r\n;//\t.equr\t\t@M03_M13,\t\t%f6\r\n;//\t.equr\t\t@M23_nnn,\t\t%f7\r\n;//\r\n;//# source vectors - 2 3D vectors in 3 PS registers\r\n;//\t.equr\t\t@SX0_SY0,\t\t%f8\r\n;//\t.equr\t\t@SZ0_SX1,\t\t%f9\r\n;//\t.equr\t\t@SY1_SZ1,\t\t%f10\r\n;//\r\n;//# Destination registers - 2 3d vectors in 4 PS registers\r\n;//\t.equr\t\t@DX0_DY0,\t\t%f11\r\n;//\t.equr\t\t@DZ0_nnn,\t\t%f12\r\n;//\t.equr\t\t@DX1_DY1,\t\t%f13\r\n;//\t.equr\t\t@DZ1_nnn,\t\t%f14\r\n;//\r\n;//# temp registers for writing back values.  These registers store the final\r\n;//# results from the PREVIOUS loop\r\n;//\t.equr\t\t@WX0_WY0,\t\t%f15\r\n;//\t.equr\t\t@WZ0_nnn,\t\t%f16\r\n;//\t.equr\t\t@WX1_WY1,\t\t%f17\r\n;//\t.equr\t\t@WZ1_nnn,\t\t%f18\r\n;//\r\n;//\tstwu\t\t%r1,\t\t\t-64(%r1)\r\n;//\tstfd\t\t%f14,\t\t\t8(%r1)\r\n;//\tstfd\t\t%f15,\t\t\t16(%r1)\r\n;//\taddi\t\t@count,\t\t\t@count,\t\t\t-1\t\t\t\t\t\t\t\t# unrolled\r\n;//\tstfd\t\t%f16,\t\t\t24(%r1)\r\n;//\tstfd\t\t%f17,\t\t\t32(%r1)\r\n;//\tstfd\t\t%f18,\t\t\t40(%r1)\r\n;//\tmtctr\t\t@count\r\n;//\t# load matrix\r\n;//\tpsq_l   \t@M00_M10,\t\t0(@m),\t\t\t0,\t\t\t\t0  \r\n;//\taddi    \t@srcBase,\t\t@srcBase,\t\t-8\r\n;//\tpsq_l   \t@M20_nnn,\t\t8(@m),\t\t\t1,\t\t\t\t0  \r\n;//\taddi    \t@dstBase,\t\t@dstBase,\t\t-4\r\n;//\tpsq_l   \t@M03_M13,\t\t36(@m),\t\t\t0,\t\t\t\t0 \r\n;//\tpsq_lu  \t@SX0_SY0,\t\t8(@srcBase),\t0,\t\t\t\tSKN_GQR_VERT\r\n;//\tpsq_l   \t@M23_nnn,\t\t44(@m),\t\t\t1,\t\t\t\t0 \r\n;//\tpsq_lu  \t@SZ0_SX1,\t\t8(@srcBase),\t0,\t\t\t\tSKN_GQR_VERT\r\n;//\r\n;//    # ------------------------------UNROLLED\r\n;//\r\n;//    # Apply first column and translation term\r\n;//\tps_madds0\t@DX0_DY0,\t\t@M00_M10,\t\t@SX0_SY0,\t\t@M03_M13\r\n;//\tpsq_l\t\t@M01_M11,\t\t12(@m),\t\t\t0,\t\t\t\t0\r\n;//\tps_madds0\t@DZ0_nnn,\t\t@M20_nnn,\t\t@SX0_SY0,\t\t@M23_nnn\r\n;//\tpsq_l\t\t@M21_nnn,\t\t20(@m),\t\t\t1,\t\t\t\t0   \r\n;//\tps_muls1\t@DX1_DY1,\t\t@M00_M10,\t\t@SZ0_SX1\t\t\t\t\t\t# no trans for norms\r\n;//\tpsq_lu\t\t@SY1_SZ1,\t\t8(@srcBase),\t0,\t\t\t\tSKN_GQR_VERT\r\n;//\tps_muls1\t@DZ1_nnn,\t\t@M20_nnn,\t\t@SZ0_SX1\t\t\t\t\t\t# no trans for norms\r\n;//\tpsq_l\t\t@M22_nnn,\t\t32(@m),\t\t\t1,\t\t\t\t0 \r\n;//\r\n;//    # Apply second column\r\n;//\tps_madds1\t@DX0_DY0,\t\t@M01_M11,\t\t@SX0_SY0,\t\t@DX0_DY0\r\n;//\tps_madds1\t@DZ0_nnn,\t\t@M21_nnn,\t\t@SX0_SY0,\t\t@DZ0_nnn\r\n;//\tpsq_l\t\t@M02_M12,\t\t24(@m),\t\t\t0,\t\t\t\t0 \r\n;//\tps_madds0\t@DX1_DY1,\t\t@M01_M11,\t\t@SY1_SZ1,\t\t@DX1_DY1\r\n;//\tpsq_lu\t\t@SX0_SY0,\t\t8(@srcBase),\t0,\t\t\t\tSKN_GQR_VERT\r\n;//\tps_madds0\t@DZ1_nnn,\t\t@M21_nnn,\t\t@SY1_SZ1,\t\t@DZ1_nnn\r\n;//\r\n;//\t# Apply third column and Write final values to temp W registers\r\n;//\tps_madds0\t@WX0_WY0,\t\t@M02_M12,\t\t@SZ0_SX1,\t\t@DX0_DY0\r\n;//\tps_madds0\t@WZ0_nnn,\t\t@M22_nnn,\t\t@SZ0_SX1,\t\t@DZ0_nnn\r\n;//\tpsq_lu\t\t@SZ0_SX1,\t\t8(@srcBase),\t0,\t\t\t\tSKN_GQR_VERT\r\n;//\tps_madds1\t@WX1_WY1,\t\t@M02_M12,\t\t@SY1_SZ1,\t\t@DX1_DY1\r\n;//\tps_madds1\t@WZ1_nnn,\t\t@M22_nnn,\t\t@SY1_SZ1,\t\t@DZ1_nnn\r\n;//\tpsq_lu\t\t@SY1_SZ1,\t\t8(@srcBase),\t0,\t\t\t\tSKN_GQR_VERT\r\n;//\r\n;//\t# -------------------------- LOOP START\r\n;//@mloop:\r\n;//\tps_madds0\t@DX0_DY0,\t\t@M00_M10,\t\t@SX0_SY0,\t\t@M03_M13\r\n;//\tpsq_stu\t\t@WX0_WY0,\t\t4(@dstBase),\t0,\t\t\t\tSKN_GQR_VERT\r\n;//\tps_madds0\t@DZ0_nnn,\t\t@M20_nnn,\t\t@SX0_SY0,\t\t@M23_nnn\r\n;//\tpsq_stu\t\t@WZ0_nnn,\t\t8(@dstBase),\t1,\t\t\t\tSKN_GQR_VERT\r\n;//\tps_muls1\t@DX1_DY1,\t\t@M00_M10,\t\t@SZ0_SX1\r\n;//\tpsq_stu\t\t@WX1_WY1,\t\t4(@dstBase),\t0,\t\t\t\tSKN_GQR_VERT\r\n;//\tps_muls1\t@DZ1_nnn,\t\t@M20_nnn,\t\t@SZ0_SX1\r\n;//\tpsq_stu\t\t@WZ1_nnn,\t\t8(@dstBase),\t1,\t\t\t\tSKN_GQR_VERT\r\n;//\tps_madds1\t@DX0_DY0,\t\t@M01_M11,\t\t@SX0_SY0,\t\t@DX0_DY0\r\n;//\tps_madds1\t@DZ0_nnn,\t\t@M21_nnn,\t\t@SX0_SY0,\t\t@DZ0_nnn\r\n;//\tpsq_lu\t\t@SX0_SY0,\t\t8(@srcBase),\t0,\t\t\t\tSKN_GQR_VERT\t# NEXT SX0 SY0\r\n;//\tps_madds0\t@DX1_DY1,\t\t@M01_M11,\t\t@SY1_SZ1,\t\t@DX1_DY1\r\n;//\tps_madds0\t@DZ1_nnn,\t\t@M21_nnn,\t\t@SY1_SZ1,\t\t@DZ1_nnn\r\n;//\r\n;//\t# Write final values to temp registers\r\n;//\tps_madds0\t@WX0_WY0,\t\t@M02_M12,\t\t@SZ0_SX1,\t\t@DX0_DY0\r\n;//\tps_madds0\t@WZ0_nnn,\t\t@M22_nnn,\t\t@SZ0_SX1,\t\t@DZ0_nnn\r\n;//\tpsq_lu\t\t@SZ0_SX1,\t\t8(@srcBase),\t0,\t\t\t\tSKN_GQR_VERT\t# NEXT SZ0 SX1\r\n;//\tps_madds1\t@WX1_WY1,\t\t@M02_M12,\t\t@SY1_SZ1,\t\t@DX1_DY1\r\n;//\tps_madds1\t@WZ1_nnn,\t\t@M22_nnn,\t\t@SY1_SZ1,\t\t@DZ1_nnn\r\n;//\tpsq_lu\t\t@SY1_SZ1,\t\t8(@srcBase),\t0,\t\t\t\tSKN_GQR_VERT\t# NEXT SY1 SZ1\r\n;//\r\n;//\tbdnz+\t\t@mloop\r\n;//\t# -------------------------- LOOP END\r\n;//\r\n;//\tpsq_stu\t\t@WX0_WY0,\t\t4(@dstBase),\t0,\t\t\t\tSKN_GQR_VERT\r\n;//\tpsq_stu\t\t@WZ0_nnn,\t\t8(@dstBase),\t1,\t\t\t\tSKN_GQR_VERT\r\n;//\tpsq_stu\t\t@WX1_WY1,\t\t4(@dstBase),\t0,\t\t\t\tSKN_GQR_VERT\r\n;//\tpsq_stu\t\t@WZ1_nnn,\t\t8(@dstBase),\t1,\t\t\t\tSKN_GQR_VERT\r\n;//\r\n;//\r\n;//@return:    \r\n;//    lfd\t\t\t%f14,\t\t\t8(%r1)\r\n;//    lfd\t\t\t%f15,\t\t\t16(%r1)\r\n;//    lfd\t\t\t%f16,\t\t\t24(%r1)\r\n;//    lfd\t\t\t%f17,\t\t\t32(%r1)\r\n;//    lfd\t\t\t%f18,\t\t\t40(%r1)\r\n;//    addi\t\t%r1,\t\t\t%r1,\t\t\t64\r\n;//    blr\r\n\r\n#---------------------------------------------------------------------------\r\n#  Name:         SKN1Vecs16Norms16\r\n#\r\n#  Description:  Transforms array of vertex-normal pairs.\r\n#\r\n#                Differs from a standard matrix-vector multiply in that the\r\n#                normals are not translated.  Before you ask, no, there is \r\n#                no cycle gain from applying a 3x3 matrix vs. applying a 4x3\r\n#                matrix.  Also, because we are always doing vertex-normal\r\n#                pairs, no need to check for odd # of transforms, etc.\r\n#\r\n#  Arguments:    m           column-major matrix to apply\r\n#                srcBase     ptr to source vert/norm pairs\r\n#                dstBase     ptr to destination, can be same as source\r\n#                count       number of vert/norm pairs.\r\n#\r\n#  Returns:      None.\r\n#---------------------------------------------------------------------------\r\n\r\n\t.scope\r\n\t.global\tTransformSingle\r\nTransformSingle:\r\n\r\n\t.equr\t\t@m,\t\t\t\t%r3\t#    ROMtx   m\r\n\t.equr\t\t@srcBase,\t\t%r4\t#    s16*    srcBase\r\n\t.equr\t\t@dstBase,\t\t%r5\t#    s16*  \t dstBase\r\n\t.equr\t\t@count,\t\t\t%r6\t#    u32     count\r\n\r\n\t.equr\t\t@M00_M10,\t\t%f0\r\n\t.equr\t\t@M20_nnn,\t\t%f1\r\n\t.equr\t\t@M01_M11,\t\t%f2\r\n\t.equr\t\t@M21_nnn,\t\t%f3\r\n\t.equr\t\t@M02_M12,\t\t%f4\r\n\t.equr\t\t@M22_nnn,\t\t%f5\r\n\t.equr\t\t@M03_M13,\t\t%f6\r\n\t.equr\t\t@M23_nnn,\t\t%f7\r\n\r\n# source vectors - 2 3D vectors in 3 PS registers\r\n\t.equr\t\t@SX0_SY0,\t\t%f8\r\n\t.equr\t\t@SZ0_SX1,\t\t%f9\r\n\t.equr\t\t@SY1_SZ1,\t\t%f10\r\n\r\n# Destination registers - 2 3d vectors in 4 PS registers\r\n\t.equr\t\t@DX0_DY0,\t\t%f11\r\n\t.equr\t\t@DZ0_nnn,\t\t%f12\r\n\t.equr\t\t@DX1_DY1,\t\t%f13\r\n\t.equr\t\t@DZ1_nnn,\t\t%f14\r\n\r\n# temp registers for writing back values.  These registers store the final\r\n# results from the PREVIOUS loop\r\n\t.equr\t\t@WX0_WY0,\t\t%f15\r\n\t.equr\t\t@WZ0_nnn,\t\t%f16\r\n\t.equr\t\t@WX1_WY1,\t\t%f17\r\n\t.equr\t\t@WZ1_nnn,\t\t%f18\r\n\r\n\tstwu\t\t%r1,\t\t\t-64(%r1)\r\n\tstfd\t\t%f14,\t\t\t8(%r1)\r\n\tstfd\t\t%f15,\t\t\t16(%r1)\r\n\taddi\t\t@count,\t\t\t@count,\t\t\t-1\t\t\t\t\t\t\t\t# unrolled\r\n\tstfd\t\t%f16,\t\t\t24(%r1)\r\n\tstfd\t\t%f17,\t\t\t32(%r1)\r\n\tstfd\t\t%f18,\t\t\t40(%r1)\r\n\tmtctr\t\t@count\r\n\r\n\t# load matrix\r\n\tpsq_l\t\t@M00_M10,\t\t0(@m),\t\t\t0,\t\t\t\t0  \r\n\taddi\t\t@srcBase,\t\t@srcBase,\t\t-4\r\n\tpsq_l\t\t@M20_nnn,\t\t8(@m),\t\t\t1,\t\t\t\t0  \r\n\taddi\t\t@dstBase,\t\t@dstBase,\t\t-2          \t\r\n\tpsq_l\t\t@M03_M13,\t\t36(@m),\t\t\t0,\t\t\t\t0 \r\n\tpsq_lu\t\t@SX0_SY0,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\tpsq_l\t\t@M23_nnn,\t\t44(@m),\t\t\t1,\t\t\t\t0 \r\n\tpsq_lu\t\t@SZ0_SX1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\t\r\n\t# ------------------------------UNROLLED                \t\r\n\t\r\n\t# Apply first column and translation term               \t\r\n\tps_madds0\t@DX0_DY0,\t\t@M00_M10,\t\t@SX0_SY0,\t\t@M03_M13\r\n\tpsq_l\t\t@M01_M11,\t\t12(@m),\t\t\t0,\t\t\t\t0\r\n\tps_madds0\t@DZ0_nnn,\t\t@M20_nnn,\t\t@SX0_SY0,\t\t@M23_nnn\r\n\tpsq_l\t\t@M21_nnn,\t\t20(@m),\t\t\t1,\t\t\t\t0   \r\n\tps_muls1\t@DX1_DY1,\t\t@M00_M10,\t\t@SZ0_SX1\t\t\t\t\t\t# no trans for norms\r\n\tpsq_lu\t\t@SY1_SZ1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\tps_muls1\t@DZ1_nnn,\t\t@M20_nnn,\t\t@SZ0_SX1\t\t\t\t\t\t# no trans for norms\r\n\tpsq_l\t\t@M22_nnn,\t\t32(@m),\t\t\t1,\t\t\t\t0 \r\n\t\r\n\t# Apply second column                                   \t\r\n\tps_madds1\t@DX0_DY0,\t\t@M01_M11,\t\t@SX0_SY0,\t\t@DX0_DY0\r\n\tps_madds1\t@DZ0_nnn,\t\t@M21_nnn,\t\t@SX0_SY0,\t\t@DZ0_nnn\r\n\tpsq_l\t\t@M02_M12,\t\t24(@m),\t\t\t0,\t\t\t\t0 \r\n\tps_madds0\t@DX1_DY1,\t\t@M01_M11,\t\t@SY1_SZ1,\t\t@DX1_DY1\r\n\tpsq_lu\t\t@SX0_SY0,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\tps_madds0\t@DZ1_nnn,\t\t@M21_nnn,\t\t@SY1_SZ1,\t\t@DZ1_nnn\r\n\r\n\t# Apply third column and Write final values to temp W registers\r\n\tps_madds0\t@WX0_WY0,\t\t@M02_M12,\t\t@SZ0_SX1,\t\t@DX0_DY0\r\n\tps_madds0\t@WZ0_nnn,\t\t@M22_nnn,\t\t@SZ0_SX1,\t\t@DZ0_nnn\r\n\tpsq_lu\t\t@SZ0_SX1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\tps_madds1\t@WX1_WY1,\t\t@M02_M12,\t\t@SY1_SZ1,\t\t@DX1_DY1\r\n\tps_madds1\t@WZ1_nnn,\t\t@M22_nnn,\t\t@SY1_SZ1,\t\t@DZ1_nnn\r\n\tpsq_lu\t\t@SY1_SZ1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\r\n\t# -------------------------- LOOP START\r\n@_mloop:\r\n\tps_madds0\t@DX0_DY0,\t\t@M00_M10,\t\t@SX0_SY0,\t\t@M03_M13\r\n\tpsq_stu\t\t@WX0_WY0,\t\t2(@dstBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\tps_madds0\t@DZ0_nnn,\t\t@M20_nnn,\t\t@SX0_SY0,\t\t@M23_nnn\r\n\tpsq_stu\t\t@WZ0_nnn,\t\t4(@dstBase),\t1,\t\t\t\tSKN_GQR_POS\r\n\tps_muls1\t@DX1_DY1,\t\t@M00_M10,\t\t@SZ0_SX1\r\n\tpsq_stu\t\t@WX1_WY1,\t\t2(@dstBase),\t0,\t\t\t\tSKN_GQR_POS\t//NORM\r\n\tps_muls1\t@DZ1_nnn,\t\t@M20_nnn,\t\t@SZ0_SX1\r\n\tpsq_stu\t\t@WZ1_nnn,\t\t4(@dstBase),\t1,\t\t\t\tSKN_GQR_POS\t//NORM\r\n\tps_madds1\t@DX0_DY0,\t\t@M01_M11,\t\t@SX0_SY0,\t\t@DX0_DY0\r\n\tps_madds1\t@DZ0_nnn,\t\t@M21_nnn,\t\t@SX0_SY0,\t\t@DZ0_nnn\r\n\tpsq_lu\t\t@SX0_SY0,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\t\t# NEXT SX0 SY0\r\n\tps_madds0\t@DX1_DY1,\t\t@M01_M11,\t\t@SY1_SZ1,\t\t@DX1_DY1\r\n\tps_madds0\t@DZ1_nnn,\t\t@M21_nnn,\t\t@SY1_SZ1,\t\t@DZ1_nnn\r\n\r\n\t# Write final values to temp registers\r\n\tps_madds0\t@WX0_WY0,\t\t@M02_M12,\t\t@SZ0_SX1,\t\t@DX0_DY0\r\n\tps_madds0\t@WZ0_nnn,\t\t@M22_nnn,\t\t@SZ0_SX1,\t\t@DZ0_nnn\r\n\tpsq_lu\t\t@SZ0_SX1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\t\t# NEXT SZ0 SX1\r\n\tps_madds1\t@WX1_WY1,\t\t@M02_M12,\t\t@SY1_SZ1,\t\t@DX1_DY1\r\n\tps_madds1\t@WZ1_nnn,\t\t@M22_nnn,\t\t@SY1_SZ1,\t\t@DZ1_nnn\r\n\tpsq_lu\t\t@SY1_SZ1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\t\t# NEXT SY1 SZ1\r\n\r\n\tbdnz+\t\t@_mloop    # -------------------------- LOOP END\r\n\r\n\tpsq_stu\t\t@WX0_WY0,\t\t2(@dstBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\tpsq_stu\t\t@WZ0_nnn,\t\t4(@dstBase),\t1,\t\t\t\tSKN_GQR_POS\r\n\tpsq_stu\t\t@WX1_WY1,\t\t2(@dstBase),\t0,\t\t\t\tSKN_GQR_POS\t//NORM\r\n\tpsq_stu\t\t@WZ1_nnn,\t\t4(@dstBase),\t1,\t\t\t\tSKN_GQR_POS //NORM\r\n\r\n\r\n@_return:    \r\n\tlfd\t\t\t%f14,\t\t\t8(%r1)\r\n\tlfd\t\t\t%f15,\t\t\t16(%r1)\r\n\tlfd\t\t\t%f16,\t\t\t24(%r1)\r\n\tlfd\t\t\t%f17,\t\t\t32(%r1)\r\n\tlfd\t\t\t%f18,\t\t\t40(%r1)\r\n\taddi\t\t%r1,\t\t\t%r1,\t\t\t64\r\n\tblr\r\n\r\n\t.endscope\r\n\r\n#---------------------------------------------------------------------------\r\n#  Name:         SKNVecs16Norms16NoTouch\r\n#\r\n#  Description:  Blends array of vertex-normal pairs between 2 matrices.\r\n#                Note that normals are not translated\r\n#\r\n#                NOTE: no cache touches are done.  Should use locked cache\r\n#                      to avoid cache pollution and misses.\r\n#\r\n#  Arguments:    m0          matrix 1\r\n#                m1          matrix 2\r\n#                wtBase      ptr to array of weights, 2 per vert/norm pair\r\n#                srcBase     ptr to source vert/norm pairs\r\n#                dstBase     ptr to destination, can be same as source\r\n#                count       number of vert/norm pairs.\r\n#\r\n#  Returns:      None.\r\n#---------------------------------------------------------------------------\r\n\r\n\t.scope\r\n\t.global\tTransformDouble\r\nTransformDouble:\r\n\r\n\t.equr\t\t@m0,\t\t\t%r3\t#    ROMtx   m0\r\n\t.equr\t\t@m1,\t\t\t%r4\t#    ROMtx   m1\r\n\t.equr\t\t@wtBase,\t\t%r5\t#    s16*  wtBase\r\n\t.equr\t\t@srcBase,\t\t%r6\t#    s16*  srcBase\r\n\t.equr\t\t@dstBase,\t\t%r7\t#    s16*  dstBase\r\n\t.equr\t\t@count,\t\t\t%r8\t#    u32     count\r\n\r\n\t.equr\t\t@COUNTTEMP,\t\t%r9\r\n\t.equr\t\t@READAHEAD,\t\t%r10\r\n\r\n\t.equr\t\t@M00_M10,\t\t%f0\r\n\t.equr\t\t@M20_nnn,\t\t%f1\r\n\t.equr\t\t@M01_M11,\t\t%f2\r\n\t.equr\t\t@M21_nnn,\t\t%f3\r\n\t.equr\t\t@M02_M12,\t\t%f4\r\n\t.equr\t\t@M22_nnn,\t\t%f5\r\n\t.equr\t\t@M03_M13,\t\t%f6\r\n\t.equr\t\t@M23_nnn,\t\t%f7\r\n\r\n# source vectors - 2 3D vectors in 3 PS registers\r\n\t.equr\t\t@SX0_SY0,\t\t%f8\r\n\t.equr\t\t@SZ0_SX1,\t\t%f9\r\n\t.equr\t\t@SY1_SZ1,\t\t%f10\r\n\r\n\t.equr\t\t@TX0_TY0,\t\t%f11\r\n\t.equr\t\t@TZ0_nnn,\t\t%f12\r\n\t.equr\t\t@TX1_TY1,\t\t%f13\r\n\t.equr\t\t@TZ1_nnn,\t\t%f14 \r\n\r\n# temp registers for writing back values.  These registers store the final\r\n# results from the PREVIOUS loop\r\n\t.equr\t\t@WX0_WY0,\t\t%f15\r\n\t.equr\t\t@WZ0_nnn,\t\t%f16\r\n\t.equr\t\t@WX1_WY1,\t\t%f17\r\n\t.equr\t\t@WZ1_nnn,\t\t%f18\r\n\r\n# second matrix\r\n\t.equr\t\t@N00_N10,\t\t%f19\r\n\t.equr\t\t@N20_nnn,\t\t%f20\r\n\t.equr\t\t@N01_N11,\t\t%f21\r\n\t.equr\t\t@N21_nnn,\t\t%f22\r\n\t.equr\t\t@N02_N12,\t\t%f23\r\n\t.equr\t\t@N22_nnn,\t\t%f24\r\n\t.equr\t\t@N03_N13,\t\t%f25\r\n\t.equr\t\t@N23_nnn,\t\t%f26\r\n\r\n# current weight for 1 vert\r\n\t.equr\t\t@WT0,\t\t\t%f27\r\n\r\n    stwu\t\t%r1,\t\t\t-160(%r1)\r\n    stfd\t\t%f14,\t\t\t8(%r1)\r\n\t# unrolled once\r\n    addi\t\t@COUNTTEMP,\t\t@count,\t\t\t-1\r\n\tstfd\t\t%f15,\t\t\t16(%r1)\r\n\tstfd\t\t%f16,\t\t\t24(%r1)\r\n\tstfd\t\t%f17,\t\t\t32(%r1)\r\n\tstfd\t\t%f18,\t\t\t40(%r1)\r\n\tstfd\t\t%f19,\t\t\t48(%r1)\r\n\tstfd\t\t%f20,\t\t\t56(%r1)\r\n\tstfd\t\t%f21,\t\t\t64(%r1)\r\n    addi\t\t@READAHEAD,\t\t%r0,\t\t\t32\r\n\tstfd\t\t%f22,\t\t\t72(%r1)\r\n\tstfd\t\t%f23,\t\t\t80(%r1)\r\n\tstfd\t\t%f24,\t\t\t88(%r1)\r\n\tstfd\t\t%f25,\t\t\t96(%r1)\r\n\tstfd\t\t%f26,\t\t\t104(%r1)\r\n\tstfd\t\t%f27,\t\t\t112(%r1)\r\n\r\n    mtctr\t\t@COUNTTEMP\r\n\t# load matrix\r\n\tpsq_l\t\t@M00_M10,\t\t0(@m0),\t\t\t0,\t\t\t\t0  \r\n\taddi\t\t@srcBase,\t\t@srcBase,\t\t-4\r\n\tpsq_l\t\t@M20_nnn,\t\t8(@m0),\t\t\t1,\t\t\t\t0  \r\n\taddi\t\t@dstBase,\t\t@dstBase,\t\t-2\r\n\tpsq_l\t\t@M03_M13,\t\t36(@m0),\t\t0,\t\t\t\t0 \r\n\taddi\t\t@wtBase,\t\t@wtBase,\t\t-4\r\n\tpsq_lu\t\t@SX0_SY0,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\tpsq_l\t\t@M23_nnn,\t\t44(@m0),\t\t1,\t\t\t\t0 \r\n\tpsq_lu\t\t@SZ0_SX1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\r\n    # ------------------------------UNROLLED\r\n\tpsq_lu\t\t@WT0,\t\t\t4(@wtBase),\t\t0,\t\t\t\tSKN_GQR_NORM\r\n\t\r\n\t# Apply first column and translation term\r\n\tps_madds0\t@WX0_WY0,\t\t@M00_M10,\t\t@SX0_SY0,\t\t@M03_M13\r\n\tpsq_l\t\t@M01_M11,\t\t12(@m0),\t\t0,\t\t\t\t0 \r\n\tps_madds0\t@WZ0_nnn,\t\t@M20_nnn,\t\t@SX0_SY0,\t\t@M23_nnn\r\n\tpsq_l\t\t@M21_nnn,\t\t20(@m0),\t\t1,\t\t\t\t0   \r\n\tps_muls1\t@WX1_WY1,\t\t@M00_M10,\t\t@SZ0_SX1\t\t\t\t\t\t# no translation for normals\r\n\tpsq_lu\t\t@SY1_SZ1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\tps_muls1\t@WZ1_nnn,\t\t@M20_nnn,\t\t@SZ0_SX1\t\t\t\t\t\t# no translation for normals\r\n\tpsq_l\t\t@M22_nnn,\t\t32(@m0),\t\t1,\t\t\t\t0 \r\n\t\r\n\t# Apply second column\r\n\tps_madds1\t@WX0_WY0,\t\t@M01_M11,\t\t@SX0_SY0,\t\t@WX0_WY0\r\n\tpsq_l\t\t@N00_N10,\t\t0(@m1),\t\t\t0,\t\t\t\t0  \r\n\tps_madds1\t@WZ0_nnn,\t\t@M21_nnn,\t\t@SX0_SY0,\t\t@WZ0_nnn\r\n\tpsq_l\t\t@M02_M12,\t\t24(@m0),\t\t0,\t\t\t\t0 \r\n\tps_madds0\t@WX1_WY1,\t\t@M01_M11,\t\t@SY1_SZ1,\t\t@WX1_WY1\r\n\tpsq_l\t\t@N20_nnn,\t\t8(@m1),\t\t\t0,\t\t\t\t0  \r\n\tps_madds0\t@WZ1_nnn,\t\t@M21_nnn,\t\t@SY1_SZ1,\t\t@WZ1_nnn\r\n\tpsq_l\t\t@N01_N11,\t\t12(@m1),\t\t0,\t\t\t\t0  \r\n\t\r\n\t# Apply third column and Write final values to temp W registers\r\n\tps_madds0\t@WX0_WY0,\t\t@M02_M12,\t\t@SZ0_SX1,\t\t@WX0_WY0\r\n\tpsq_l\t\t@N21_nnn,\t\t20(@m1),\t\t0,\t\t\t\t0  \r\n\tps_madds0\t@WZ0_nnn,\t\t@M22_nnn,\t\t@SZ0_SX1,\t\t@WZ0_nnn\r\n\tpsq_l\t\t@N02_N12,\t\t24(@m1),\t\t0,\t\t\t\t0  \r\n\tps_madds1\t@WX1_WY1,\t\t@M02_M12,\t\t@SY1_SZ1,\t\t@WX1_WY1\r\n\tpsq_l\t\t@N22_nnn,\t\t32(@m1),\t\t0,\t\t\t\t0  \r\n\tps_madds1\t@WZ1_nnn,\t\t@M22_nnn,\t\t@SY1_SZ1,\t\t@WZ1_nnn\r\n\tpsq_l\t\t@N03_N13,\t\t36(@m1),\t\t0,\t\t\t\t0  \r\n\t\r\n\t# now apply weights to W vectors\r\n\tps_muls0\t@WX0_WY0,\t\t@WX0_WY0,\t\t@WT0\r\n\tpsq_l\t\t@N23_nnn,\t\t44(@m1),\t\t0,\t\t\t\t0  \r\n\tps_muls0\t@WZ0_nnn,\t\t@WZ0_nnn,\t\t@WT0\r\n\tps_muls0\t@WX1_WY1,\t\t@WX1_WY1,\t\t@WT0\r\n\tps_muls0\t@WZ1_nnn,\t\t@WZ1_nnn,\t\t@WT0\r\n\t\r\n\t\r\n\t# now transform by second matrix into TX* registers\r\n\tps_madds0\t@TX0_TY0,\t\t@N00_N10,\t\t@SX0_SY0,\t\t@N03_N13\r\n\tps_madds0\t@TZ0_nnn,\t\t@N20_nnn,\t\t@SX0_SY0,\t\t@N23_nnn\r\n\tps_muls1\t@TX1_TY1,\t\t@N00_N10,\t\t@SZ0_SX1\t\t\t\t\t\t# no translation for normals\r\n\tps_muls1\t@TZ1_nnn,\t\t@N20_nnn,\t\t@SZ0_SX1\t\t\t\t\t\t# no translation for normals\r\n\tps_madds1\t@TX0_TY0,\t\t@N01_N11,\t\t@SX0_SY0,\t\t@TX0_TY0\r\n\tps_madds1\t@TZ0_nnn,\t\t@N21_nnn,\t\t@SX0_SY0,\t\t@TZ0_nnn\r\n\tps_madds0\t@TX1_TY1,\t\t@N01_N11,\t\t@SY1_SZ1,\t\t@TX1_TY1\r\n\tpsq_lu\t\t@SX0_SY0,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\t# XXX LOAD NEW\r\n\tps_madds0\t@TZ1_nnn,\t\t@N21_nnn,\t\t@SY1_SZ1,\t\t@TZ1_nnn\r\n\t\r\n\t# Write final values to temp registers\r\n\tps_madds0\t@TX0_TY0,\t\t@N02_N12,\t\t@SZ0_SX1,\t\t@TX0_TY0\r\n\tps_madds0\t@TZ0_nnn,\t\t@N22_nnn,\t\t@SZ0_SX1,\t\t@TZ0_nnn\r\n\tps_madds1\t@TX1_TY1,\t\t@N02_N12,\t\t@SY1_SZ1,\t\t@TX1_TY1\r\n\tps_madds1\t@TZ1_nnn,\t\t@N22_nnn,\t\t@SY1_SZ1,\t\t@TZ1_nnn\r\n\tpsq_lu\t\t@SZ0_SX1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\t# XXX LOAD NEW\r\n\t\r\n\t# madd the second xformed verts with temps, and store them out\r\n\tps_madds1\t@TX0_TY0,\t\t@TX0_TY0,\t\t@WT0,\t\t\t@WX0_WY0\r\n\tps_madds1\t@TZ0_nnn,\t\t@TZ0_nnn,\t\t@WT0,\t\t\t@WZ0_nnn\r\n\tps_madds1\t@TX1_TY1,\t\t@TX1_TY1,\t\t@WT0,\t\t\t@WX1_WY1\r\n\tpsq_lu\t\t@SY1_SZ1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\t# XXX LOAD NEW\r\n\tps_madds1\t@TZ1_nnn,\t\t@TZ1_nnn,\t\t@WT0,\t\t\t@WZ1_nnn\r\n\t\r\n\t# -------------------------- LOOP START\r\n@_mloop:\r\n\r\n\r\n\r\n\tps_madds0\t@WX0_WY0,\t\t@M00_M10,\t\t@SX0_SY0,\t\t@M03_M13\r\n\tpsq_stu\t\t@TX0_TY0,\t\t2(@dstBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\tps_madds0\t@WZ0_nnn,\t\t@M20_nnn,\t\t@SX0_SY0,\t\t@M23_nnn\r\n\tpsq_stu\t\t@TZ0_nnn,\t\t4(@dstBase),\t1,\t\t\t\tSKN_GQR_POS\r\n\tps_muls1\t@WX1_WY1,\t\t@M00_M10,\t\t@SZ0_SX1\t\t\t\t\t\t# no translation for normals\r\n\tpsq_stu\t\t@TX1_TY1,\t\t2(@dstBase),\t0,\t\t\t\tSKN_GQR_POS //NORM\r\n\tps_muls1\t@WZ1_nnn,\t\t@M20_nnn,\t\t@SZ0_SX1\t\t\t\t\t\t# no translation for normals\r\n\tpsq_stu\t\t@TZ1_nnn,\t\t4(@dstBase),\t1,\t\t\t\tSKN_GQR_POS //NORM\r\n\t\r\n\t#  DX0=M01*SY0+DX0, DY0=M11*SY0+DY0\r\n\t#  DZ0=M21*SY0+DZ0\r\n\t#  DX1=M01*SY1+DX1, DY1=M11*SY1+DY1\r\n\t#  DZ1=M21*SY1+DZ1\r\n\t\r\n\tps_madds1\t@WX0_WY0,\t\t@M01_M11,\t\t@SX0_SY0,\t\t@WX0_WY0\r\n\tps_madds1\t@WZ0_nnn,\t\t@M21_nnn,\t\t@SX0_SY0,\t\t@WZ0_nnn\r\n\tdcbt\t\t@READAHEAD,\t\t@srcBase \t\t         \t\t\r\n\tps_madds0\t@WX1_WY1,\t\t@M01_M11,\t\t@SY1_SZ1,\t\t@WX1_WY1\r\n\tps_madds0\t@WZ1_nnn,\t\t@M21_nnn,\t\t@SY1_SZ1,\t\t@WZ1_nnn\r\n\t\r\n\t#  DX0=M02*SZ0+DX0, DY0=M12*SZ0+DY0\r\n\t#  DZ0=M22*SZ0+DZ0\r\n\t#  DX1=M02*SZ1+DX1, DY1=M12*SZ1+DY1\r\n\t#  DZ1=M22*SZ1+DZ1\r\n\t\r\n\t# Write final values to temp registers\r\n\tps_madds0\t@WX0_WY0,\t\t@M02_M12,\t\t@SZ0_SX1,\t\t@WX0_WY0\r\n\tps_madds0\t@WZ0_nnn,\t\t@M22_nnn,\t\t@SZ0_SX1,\t\t@WZ0_nnn\r\n\tpsq_lu\t\t@WT0,\t\t\t4(@wtBase),\t\t0,\t\t\t\tSKN_GQR_NORM\r\n\tps_madds1\t@WX1_WY1,\t\t@M02_M12,\t\t@SY1_SZ1,\t\t@WX1_WY1\r\n\tps_madds1\t@WZ1_nnn,\t\t@M22_nnn,\t\t@SY1_SZ1,\t\t@WZ1_nnn\r\n\t\r\n\t\r\n\t# now apply weights to w vectors\r\n\tps_muls0\t@WX0_WY0,\t\t@WX0_WY0,\t\t@WT0\r\n\tps_muls0\t@WZ0_nnn,\t\t@WZ0_nnn,\t\t@WT0\r\n\tps_muls0\t@WX1_WY1,\t\t@WX1_WY1,\t\t@WT0\r\n\tps_muls0\t@WZ1_nnn,\t\t@WZ1_nnn,\t\t@WT0\r\n\t\r\n\t\r\n\t# now transform by second matrix into TX* registers\r\n\tps_madds0\t@TX0_TY0,\t\t@N00_N10,\t\t@SX0_SY0,\t\t@N03_N13\r\n\tps_madds0\t@TZ0_nnn,\t\t@N20_nnn,\t\t@SX0_SY0,\t\t@N23_nnn\r\n\tdcbt\t\t@READAHEAD,\t\t@dstBase\r\n\tps_muls1\t@TX1_TY1,\t\t@N00_N10,\t\t@SZ0_SX1\t\t\t\t\t\t# no translation for normals\r\n\tps_muls1\t@TZ1_nnn,\t\t@N20_nnn,\t\t@SZ0_SX1\t\t\t\t\t\t# no translation for normals\r\n\tps_madds1\t@TX0_TY0,\t\t@N01_N11,\t\t@SX0_SY0,\t\t@TX0_TY0\r\n\tps_madds1\t@TZ0_nnn,\t\t@N21_nnn,\t\t@SX0_SY0,\t\t@TZ0_nnn\r\n\tps_madds0\t@TX1_TY1,\t\t@N01_N11,\t\t@SY1_SZ1,\t\t@TX1_TY1\r\n\tpsq_lu\t\t@SX0_SY0,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\t# XXX LOAD NEW\r\n\tps_madds0\t@TZ1_nnn,\t\t@N21_nnn,\t\t@SY1_SZ1,\t\t@TZ1_nnn\r\n\t\r\n\t# Write final values to temp registers\r\n\tps_madds0\t@TX0_TY0,\t\t@N02_N12,\t\t@SZ0_SX1,\t\t@TX0_TY0\r\n\tps_madds0\t@TZ0_nnn,\t\t@N22_nnn,\t\t@SZ0_SX1,\t\t@TZ0_nnn\r\n\tps_madds1\t@TX1_TY1,\t\t@N02_N12,\t\t@SY1_SZ1,\t\t@TX1_TY1\r\n\tps_madds1\t@TZ1_nnn,\t\t@N22_nnn,\t\t@SY1_SZ1,\t\t@TZ1_nnn\r\n\tpsq_lu\t\t@SZ0_SX1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\t# XXX LOAD NEW\r\n\t\r\n\t# madd the second xformed verts with temps, and store them out\r\n\tps_madds1\t@TX0_TY0,\t\t@TX0_TY0,\t\t@WT0,\t\t\t@WX0_WY0\r\n\tps_madds1\t@TZ0_nnn,\t\t@TZ0_nnn,\t\t@WT0,\t\t\t@WZ0_nnn\r\n\tps_madds1\t@TX1_TY1,\t\t@TX1_TY1,\t\t@WT0,\t\t\t@WX1_WY1\r\n\tpsq_lu\t\t@SY1_SZ1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\t# XXX LOAD NEW\r\n\tps_madds1\t@TZ1_nnn,\t\t@TZ1_nnn,\t\t@WT0,\t\t\t@WZ1_nnn\r\n\t\r\n\t\r\n\t\r\n\tbdnz+\t\t@_mloop    # -------------------------- LOOP END\r\n\t\r\n\tpsq_stu\t\t@TX0_TY0,\t\t2(@dstBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\tpsq_stu\t\t@TZ0_nnn,\t\t4(@dstBase),\t1,\t\t\t\tSKN_GQR_POS\r\n\tpsq_stu\t\t@TX1_TY1,\t\t2(@dstBase),\t0,\t\t\t\tSKN_GQR_POS\t//NORM\r\n\tpsq_stu\t\t@TZ1_nnn,\t\t4(@dstBase),\t1,\t\t\t\tSKN_GQR_POS //NORM\r\n\t\r\n\t\r\n@_return:    \r\n\tlfd\t\t\t%f14,\t\t\t8(%r1)\r\n\tlfd\t\t\t%f15,\t\t\t16(%r1)\r\n\tlfd\t\t\t%f16,\t\t\t24(%r1)\r\n\tlfd\t\t\t%f17,\t\t\t32(%r1)\r\n\tlfd\t\t\t%f18,\t\t\t40(%r1)\r\n\tlfd\t\t\t%f19,\t\t\t48(%r1)\r\n\tlfd\t\t\t%f20,\t\t\t56(%r1)\r\n\tlfd\t\t\t%f21,\t\t\t64(%r1)\r\n\tlfd\t\t\t%f22,\t\t\t72(%r1)\r\n\tlfd\t\t\t%f23,\t\t\t80(%r1)\r\n\tlfd\t\t\t%f24,\t\t\t88(%r1)\r\n\tlfd\t\t\t%f25,\t\t\t96(%r1)\r\n\tlfd\t\t\t%f26,\t\t\t104(%r1)\r\n\tlfd\t\t\t%f27,\t\t\t112(%r1)\r\n\taddi\t\t%r1,\t\t\t%r1,\t\t\t160\r\n\tblr\r\n\r\n\t.endscope\r\n\r\n#---------------------------------------------------------------------------\r\n#  Name:         SKNAccVecs16Norms16Iu16\r\n#\r\n#  Description:  General accumulation code\r\n#                Assumes source data is duplicated in linear fashion\r\n#                Assumes u16 indices\r\n#\r\n#                Loop cannot be unrolled since we must handle 1 length lists\r\n#                as well\r\n#\r\n#  Arguments:    m       current animation matrix\r\n#                count   number of vertex-normal pairs\r\n#                vnlist  source data for vertex-normal pairs, pre-blended\r\n#                dest    destination array\r\n#                indices indices into the destination array\r\n#                weights list of weights, use GQ%r6\r\n#\r\n#  Returns:      None.\r\n#---------------------------------------------------------------------------\r\n\t.scope\r\n\t.global\tTransformAcc\r\nTransformAcc:\r\n\r\n\t.equr\t\t@m,\t\t\t\t%r3\t#\tROMtx      m\r\n\t.equr\t\t@count,\t\t\t%r4\t#\tu16        count\r\n\t.equr\t\t@srcBase,\t\t%r5\t#\tfloat     *srcBase\r\n\t.equr\t\t@dstBase,\t\t%r6\t#\ts16     *dstBase\r\n\t.equr\t\t@indices,\t\t%r7\t#\tu16       *indices\r\n\t.equr\t\t@weights,\t\t%r8\t#\ts16     *weights\r\n\r\n\t.equr\t\t@M00_M10,\t\t%f0\r\n\t.equr\t\t@M20_nnn,\t\t%f1\r\n\t.equr\t\t@M01_M11,\t\t%f2\r\n\t.equr\t\t@M21_nnn,\t\t%f3\r\n\t.equr\t\t@M02_M12,\t\t%f4\r\n\t.equr\t\t@M22_nnn,\t\t%f5\r\n\t.equr\t\t@M03_M13,\t\t%f6\r\n\t.equr\t\t@M23_nnn,\t\t%f7\r\n\r\n# source vectors - 2 3D vectors in 3 PS registers\r\n\t.equr\t\t@SX0_SY0,\t\t%f8\r\n\t.equr\t\t@SZ0_SX1,\t\t%f9\r\n\t.equr\t\t@SY1_SZ1,\t\t%f10\r\n\r\n# Destination registers - 2 3d vectors in 4 PS registers\r\n\t.equr\t\t@DX0_DY0,\t\t%f11\r\n\t.equr\t\t@DZ0_nnn,\t\t%f12\r\n\t.equr\t\t@DX1_DY1,\t\t%f13\r\n\t.equr\t\t@DZ1_nnn,\t\t%f14\r\n\r\n# accumulation registers\r\n\t.equr\t\t@AX0_AY0,\t\t%f19\r\n\t.equr\t\t@AZ0_nnn,\t\t%f20\r\n\t.equr\t\t@AX1_AY1,\t\t%f21\r\n\t.equr\t\t@AZ1_nnn,\t\t%f22\r\n\r\n# temp registers for writing back values.  These registers store the final\r\n# results from the PREVIOUS loop\r\n\t.equr\t\t@WX0_WY0,\t\t%f15\r\n\t.equr\t\t@WZ0_nnn,\t\t%f16\r\n\t.equr\t\t@WX1_WY1,\t\t%f17\r\n\t.equr\t\t@WZ1_nnn,\t\t%f18\r\n\r\n\t.equr\t\t@WEIGHT,\t\t%f23\r\n\r\n\t.equr\t\t@INDEX,\t\t\t%r9\r\n\t.equr\t\t@DESTADDR,\t\t%r10\r\n\t.equr\t\t@INDEXTMP,\t\t%r11\r\n\r\n\tstwu\t\t%r1,\t\t\t-160(%r1)\r\n\taddi\t\t@indices,\t\t@indices,\t\t-2\t\t\t\t\t\t\t\t# for load-update\r\n\tstfd\t\t%f14,\t\t\t8(%r1)\r\n\tlhzu\t\t@INDEX,\t\t\t2(@indices)\t\t\t\t\t\t\t\t\t\t# index for first destination\r\n\tstfd\t\t%f15,\t\t\t16(%r1)\r\n\tstfd\t\t%f16,\t\t\t24(%r1)\r\n\tadd\t\t\t@INDEXTMP,\t\t@INDEX,\t\t\t@INDEX\t\t\t\t\t\t\t# addr for dest = dest + (index*3*sizeof (s16))\r\n\tstfd\t\t%f17,\t\t\t32(%r1)\r\n\tadd\t\t\t@INDEX,\t\t\t@INDEX,\t\t\t@INDEXTMP\t\t\t\t\t\t# addr for dest = dest + (index*3*sizeof (s16))\r\n\tstfd\t\t%f18,\t\t\t40(%r1)\r\n\tadd\t\t\t@INDEX,\t\t\t@INDEX,\t\t\t@INDEX\t\t\t\t\t\t\t# x 2 for s16\r\n\tstfd\t\t%f19,\t\t\t48(%r1)\r\n\tadd\t\t\t@INDEX,\t\t\t@INDEX,\t\t\t@INDEX\t\t\t\t\t\t\t# x 2 for vert/norm\r\n\tstfd\t\t%f20,\t\t\t56(%r1)\r\n\tadd\t\t\t@DESTADDR,\t\t@INDEX,\t\t\t@dstBase\r\n\tstfd\t\t%f21,\t\t\t64(%r1)\r\n\taddi\t\t@weights,\t\t@weights,\t\t-2\r\n\tstfd\t\t%f22,\t\t\t72(%r1)\r\n\tstfd\t\t%f23,\t\t\t80(%r1)\r\n\r\n\tmtctr\t\t@count\r\n\r\n\tpsq_l\t\t@M00_M10,\t\t0(@m),\t\t\t0,\t\t\t\t0\r\n\taddi\t\t@srcBase,\t\t@srcBase,\t\t-4\r\n\tpsq_l\t\t@M20_nnn,\t\t8(@m),\t\t\t1,\t\t\t\t0\r\n\tpsq_l\t\t@M03_M13,\t\t36(@m),\t\t\t0,\t\t\t\t0\r\n\tpsq_l\t\t@M23_nnn,\t\t44(@m),\t\t\t1,\t\t\t\t0\r\n\tpsq_lu\t\t@SX0_SY0,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\tpsq_lu\t\t@SZ0_SX1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\r\n\r\n\tpsq_l\t\t@M01_M11,\t\t12(@m),\t\t\t0,\t\t\t\t0\r\n\tpsq_l\t\t@M21_nnn,\t\t20(@m),\t\t\t1,\t\t\t\t0\r\n\tpsq_lu\t\t@SY1_SZ1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\r\n\tpsq_l\t\t@M22_nnn,\t\t32(@m),\t\t\t1,\t\t\t\t0\r\n\tpsq_l\t\t@M02_M12,\t\t24(@m),\t\t\t0,\t\t\t\t0\r\n\r\n    # -------------------------- LOOP START\r\n@mloop:\r\n\tps_madds0\t@DX0_DY0,\t\t@M00_M10,\t\t@SX0_SY0,\t\t@M03_M13\r\n\tpsq_lu\t\t@WEIGHT,\t\t2(@weights),\t1,\t\t\t\tSKN_GQR_NORM\r\n\tps_madds0\t@DZ0_nnn,\t\t@M20_nnn,\t\t@SX0_SY0,\t\t@M23_nnn\r\n\tps_muls1\t@DX1_DY1,\t\t@M00_M10,\t\t@SZ0_SX1\r\n\tpsq_l\t\t@AX0_AY0,\t\t0(@DESTADDR),\t0,\t\t\t\tSKN_GQR_POS\r\n\tps_muls1\t@DZ1_nnn,\t\t@M20_nnn,\t\t@SZ0_SX1\r\n\r\n\tps_madds1\t@DX0_DY0,\t\t@M01_M11,\t\t@SX0_SY0,\t\t@DX0_DY0\r\n\tps_madds1\t@DZ0_nnn,\t\t@M21_nnn,\t\t@SX0_SY0,\t\t@DZ0_nnn\r\n\tpsq_l\t\t@AZ0_nnn,\t\t4(@DESTADDR),\t1,\t\t\t\tSKN_GQR_POS\r\n\tps_madds0\t@DX1_DY1,\t\t@M01_M11,\t\t@SY1_SZ1,\t\t@DX1_DY1\r\n\tps_madds0\t@DZ1_nnn,\t\t@M21_nnn,\t\t@SY1_SZ1,\t\t@DZ1_nnn\r\n\tpsq_l\t\t@AX1_AY1,\t\t6(@DESTADDR),\t0,\t\t\t\tSKN_GQR_POS\r\n\tps_madds0\t@WX0_WY0,\t\t@M02_M12,\t\t@SZ0_SX1,\t\t@DX0_DY0\r\n\tps_madds0\t@WZ0_nnn,\t\t@M22_nnn,\t\t@SZ0_SX1,\t\t@DZ0_nnn\r\n\tlhzu\t\t@INDEX,\t\t\t2(@indices)\t\t\t\t\t\t\t\t\t\t# index for destination\r\n\tps_madds1\t@WX1_WY1,\t\t@M02_M12,\t\t@SY1_SZ1,\t\t@DX1_DY1\r\n\tps_madds1\t@WZ1_nnn,\t\t@M22_nnn,\t\t@SY1_SZ1,\t\t@DZ1_nnn\r\n\tpsq_l\t\t@AZ1_nnn,\t\t10(@DESTADDR),\t1,\t\t\t\tSKN_GQR_POS\r\n\t# accumulate\r\n\tps_madds0\t@AX0_AY0,\t\t@WX0_WY0,\t\t@WEIGHT,\t\t@AX0_AY0\r\n\tpsq_lu\t\t@SX0_SY0,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\t# NEXT data\r\n\tps_madds0\t@AZ0_nnn,\t\t@WZ0_nnn,\t\t@WEIGHT,\t\t@AZ0_nnn\r\n\tpsq_lu\t\t@SZ0_SX1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\t# NEXT data\r\n\tps_madds0\t@AX1_AY1,\t\t@WX1_WY1,\t\t@WEIGHT,\t\t@AX1_AY1\r\n\tpsq_lu\t\t@SY1_SZ1,\t\t4(@srcBase),\t0,\t\t\t\tSKN_GQR_POS\t# NEXT data\r\n\tps_madds0\t@AZ1_nnn,\t\t@WZ1_nnn,\t\t@WEIGHT,\t\t@AZ1_nnn\r\n\tadd\t\t\t@INDEXTMP,\t\t@INDEX,\t\t\t@INDEX\t\t\t\t\t\t\t# NEXT DESTADDR\r\n\tpsq_st\t\t@AX0_AY0,\t\t0(@DESTADDR),\t0,\t\t\t\tSKN_GQR_POS\r\n\tadd\t\t\t@INDEX,\t\t\t@INDEX,\t\t\t@INDEXTMP\t\t\t\t\t\t# NEXT DESTADDR\r\n\tpsq_st\t\t@AZ0_nnn,\t\t4(@DESTADDR),\t1,\t\t\t\tSKN_GQR_POS\r\n\tadd\t\t\t@INDEX,\t\t\t@INDEX,\t\t\t@INDEX\t\t\t\t\t\t\t# NEXT DESTADDR\r\n\tpsq_st\t\t@AX1_AY1,\t\t6(@DESTADDR),\t0,\t\t\t\tSKN_GQR_POS\t//NORM\r\n\tadd\t\t\t@INDEX,\t\t\t@INDEX,\t\t\t@INDEX\t\t\t\t\t\t\t# NEXT DESTADDR\r\n\tpsq_st\t\t@AZ1_nnn,\t\t10(@DESTADDR),\t1,\t\t\t\tSKN_GQR_POS\t//NORM\r\n\tdcbst\t\t0,\t\t\t\t@DESTADDR\t\t\t\t\t\t\t\t\t\t# FLUSH data to memory\r\n\tadd\t\t\t@DESTADDR,\t\t@INDEX,\t\t\t@dstBase\t\t\t\t\t\t# NEXT DESTADDR\r\n\r\n\tbdnz+\t\t@mloop\r\n\t# -------------------------- LOOP END\r\n\r\n\r\n@return:    \r\n    lfd\t\t\t%f14,\t\t\t8(%r1)\r\n    lfd\t\t\t%f15,\t\t\t16(%r1)\r\n    lfd\t\t\t%f16,\t\t\t24(%r1)\r\n    lfd\t\t\t%f17,\t\t\t32(%r1)\r\n    lfd\t\t\t%f18,\t\t\t40(%r1)\r\n    lfd\t\t\t%f19,\t\t\t48(%r1)\r\n    lfd\t\t\t%f20,\t\t\t56(%r1)\r\n    lfd\t\t\t%f21,\t\t\t64(%r1)\r\n    lfd\t\t\t%f22,\t\t\t72(%r1)\r\n    lfd\t\t\t%f23,\t\t\t80(%r1)\r\n    addi\t\t%r1,\t\t\t%r1,\t\t\t160\r\n    blr\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_aram.cpp",
    "content": "/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsARAM\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tARAMs matrices.\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#include \"p_ARAM.h\"\r\n\r\n/********************************************************************************\r\n * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n \r\n/********************************************************************************\r\n * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n#define MAX_BU_BLOCKS 4500\r\n#define MAX_TD_BLOCKS 128\r\n#define MAX_SK0_BLOCKS 2\r\n#define MAX_SK1_BLOCKS 2\r\n#define MAX_SCRIPT_BLOCKS (1024 * 6)\r\n\r\nuint32 p_bu[MAX_BU_BLOCKS];\r\nuint32 p_td[MAX_TD_BLOCKS];\r\nuint32 p_sk0[MAX_SK0_BLOCKS];\r\nuint32 p_sk1[MAX_SK1_BLOCKS];\r\nuint32 p_script[MAX_SCRIPT_BLOCKS];\r\nchar abu[MAX_BU_BLOCKS];\t\t// 1=allocated, 0=freed\r\nchar atd[MAX_TD_BLOCKS];\t\t// 1=allocated, 0=freed\r\nchar ask0[MAX_SK0_BLOCKS];\t// 1=allocated, 0=freed\r\nchar ask1[MAX_SK1_BLOCKS];\t// 1=allocated, 0=freed\r\nchar ascript[MAX_SCRIPT_BLOCKS];\t// 1=allocated, 0=freed\r\nint num_bu;\r\nint num_td;\r\nint num_sk0;\r\nint num_sk1;\r\nint num_script;\r\nuint32 p_cur_td;\r\n\r\nuint32 p_bu_base;\r\nuint32 p_td_base;\r\nuint32 p_sk0_base;\r\nuint32 p_sk1_base;\r\nuint32 p_script_base;\r\n\r\nuint32 g_min_unused = ( 16 * 1024 * 1024 );\r\nuint32 g_fragmented_bu = 0;\r\nuint32 g_fragmented_td = 0;\r\n\r\n#define SKATER0_HEAP_SIZE ( 1 * 1024 )\r\n#define SKATER1_HEAP_SIZE ( 1 * 1024 )\r\n\r\n#ifdef __NOPT_FINAL__\r\n#define SCRIPT_HEAP_SIZE ( 1280 * 1024 )\r\n#else\r\n#define SCRIPT_HEAP_SIZE ( 1800 * 1024 )\r\n#endif\t\t// __NOPT_FINAL__\r\n\r\n/********************************************************************************\r\n * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nvoid NsARAM::init( void )\r\n{\r\n\tnum_bu = 0;\r\n\tnum_td = 0;\r\n\tnum_sk0 = 0;\r\n\tnum_sk1 = 0;\r\n\r\n\tp_bu_base = ARGetBaseAddress();\r\n\tp_sk0_base = ( 1024 * 1024 * 16 ) - SKATER0_HEAP_SIZE; \r\n\tp_sk1_base = p_sk0_base - SKATER1_HEAP_SIZE;\r\n\tp_script_base = p_sk1_base - SCRIPT_HEAP_SIZE;\r\n\tp_td_base = p_script_base;\r\n\tp_bu[0] = p_bu_base;\r\n\tp_sk0[0] = p_sk0_base;\r\n\tp_sk1[0] = p_sk1_base;\r\n\tp_script[0] = p_script_base;\r\n\tp_cur_td = p_td_base;\r\n}\r\n\r\nuint32 NsARAM::alloc( uint32 size, HEAPTYPE heap )\r\n{\r\n\tint lp;\r\n//\tint plus_size;\r\n//\tbool found;\r\n\tuint32 rv = 0;\r\n\r\n\tswitch ( heap )\r\n\t{\r\n\t\tcase BOTTOMUP:\r\n\t\t\tif ( unused() < size )\r\n\t\t\t{\r\n\t\t\t\tOSReport( \"Not enough ARAM for allocation: %d (unused=%d)\\n\", size, unused() );\r\n\t\t\t\twhile (1);\r\n\t\t\t}\r\n\r\n\t\t\t// Make sure we have enough ARAM left to make the allocation.\r\n\t\t\tif ( ( p_bu[num_bu] + size ) <= p_cur_td )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( num_bu < MAX_BU_BLOCKS, ( \"Too many BU allocations - %d, max is %d\", num_bu, MAX_BU_BLOCKS ) );\r\n\t\t\t\trv = p_bu[num_bu];\t\t\t\t\t// The address we're going to return.\r\n\t\t\t\tabu[num_bu] = 1;\t\t\t\t\t// Set this entry as allocated.\r\n\t\t\t\tnum_bu++;\t\t\t\t\t\t\t// Added 1 allocation.\r\n\t\t\t\tp_bu[num_bu] = p_bu[num_bu-1] + ( ( size + 31 ) & ~31 );\t// Move current pointer on.\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase TOPDOWN:\r\n\t\t\tif ( unused() < size )\r\n\t\t\t{\r\n\t\t\t\tOSReport( \"Not enough ARAM for allocation: %d (unused=%d)\\n\", size, unused() );\r\n\t\t\t\twhile (1);\r\n\t\t\t}\r\n\r\n\t\t\t// Make sure we have enough ARAM left to make the allocation.\r\n\t\t\tif ( ( p_cur_td - size ) >= p_bu[num_bu] )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( num_td < MAX_TD_BLOCKS, ( \"Too many TD allocations - %d, max is %d\", num_td, MAX_TD_BLOCKS ) );\r\n\t\t\t\tp_cur_td -= ( size + 31 ) & ~31;\t// Move current pointer on.\r\n\t\t\t\trv = p_cur_td;\t\t\t\t\t\t// The address we're going to return.\r\n\t\t\t\tp_td[num_td] = p_cur_td;\t\t\t// Set the pointer in the bu stack.\r\n\t\t\t\tatd[num_td] = 1;\t\t\t\t\t// Set this entry as allocated.\r\n\t\t\t\tnum_td++;\t\t\t\t\t\t\t// Added 1 allocation.\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase SKATER0:\r\n\t\t\tif ( ( ( p_sk0_base + SKATER0_HEAP_SIZE ) - p_sk0[num_sk0] ) < size )\r\n\t\t\t{\r\n\t\t\t\tOSReport( \"Not enough ARAM for allocation: %d (unused=%d)\\n\", size, ( ( p_sk0_base + SKATER0_HEAP_SIZE ) - p_sk0[num_sk0] ) );\r\n\t\t\t\twhile (1);\r\n\t\t\t}\r\n\r\n\t\t\t// Make sure we have enough ARAM left to make the allocation.\r\n\t\t\tif ( ( p_sk0[num_sk0] + size ) <= ( p_sk0_base + SKATER0_HEAP_SIZE ) )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( num_sk0 < MAX_SK0_BLOCKS, ( \"Too many sk0 allocations - %d, max is %d\", num_sk0, MAX_SK0_BLOCKS ) );\r\n\t\t\t\trv = p_sk0[num_sk0];\t\t\t\t// The address we're going to return.\r\n\t\t\t\task0[num_sk0] = 1;\t\t\t\t\t// Set this entry as allocated.\r\n\t\t\t\tnum_sk0++;\t\t\t\t\t\t\t// Added 1 allocation.\r\n\t\t\t\tp_sk0[num_sk0] = p_sk0[num_sk0-1] + ( ( size + 31 ) & ~31 );\t// Move current pointer on.\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase SKATER1:\r\n\t\t\tif ( ( ( p_sk1_base + SKATER1_HEAP_SIZE ) - p_sk1[num_sk1] ) < size )\r\n\t\t\t{\r\n\t\t\t\tOSReport( \"Not enough ARAM for allocation: %d (unused=%d)\\n\", size, ( ( p_sk1_base + SKATER1_HEAP_SIZE ) - p_sk1[num_sk1] ) );\r\n\t\t\t\twhile (1);\r\n\t\t\t}\r\n\r\n\t\t\t// Make sure we have enough ARAM left to make the allocation.\r\n\t\t\tif ( ( p_sk1[num_sk1] + size ) <= ( p_sk1_base + SKATER1_HEAP_SIZE ) )\r\n\t\t\t{\r\n\t\t\t\tDbg_MsgAssert( num_sk1 < MAX_SK1_BLOCKS, ( \"Too many sk1 allocations - %d, max is %d\", num_sk1, MAX_SK1_BLOCKS ) );\r\n\t\t\t\trv = p_sk1[num_sk1];\t\t\t\t// The address we're going to return.\r\n\t\t\t\task1[num_sk1] = 1;\t\t\t\t\t// Set this entry as allocated.\r\n\t\t\t\tnum_sk1++;\t\t\t\t\t\t\t// Added 1 allocation.\r\n\t\t\t\tp_sk1[num_sk1] = p_sk1[num_sk1-1] + ( ( size + 31 ) & ~31 );\t// Move current pointer on.\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase SCRIPT:\r\n//\t\t\t// Search for an empty block that fits exactly.\r\n//\t\t\tplus_size = ( ( size + 31 ) & ~31 );\r\n//\t\t\tfound = false;\r\n//\t\t\tfor ( lp = 0; lp < ( num_script - 1 ); lp++ )\r\n//\t\t\t{\r\n//\t\t\t\tif ( !ascript[lp] && ( ( p_script[lp+1] - p_script[lp] ) == size ) )\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// Found a slot.\r\n//\t\t\t\t\tascript[lp] = 1;\r\n//\t\t\t\t\tfound = true;\r\n//\t\t\t\t\trv = p_script[lp];\t\t\t\t// The address we're going to return.\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\r\n//\t\t\tif ( !found )\r\n//\t\t\t{\r\n\t\t\t\tif ( ( ( p_script_base + SCRIPT_HEAP_SIZE ) - p_script[num_script] ) < size )\r\n\t\t\t\t{\r\n\t\t\t\t\tOSReport( \"Not enough ARAM for allocation: %d (unused=%d)\\n\", size, ( ( p_script_base + SCRIPT_HEAP_SIZE ) - p_script[num_script] ) );\r\n\t\t\t\t\twhile (1);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Make sure we have enough ARAM left to make the allocation.\r\n\t\t\t\tif ( ( p_script[num_script] + size ) <= ( p_script_base + SCRIPT_HEAP_SIZE ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tDbg_MsgAssert( num_script < MAX_SCRIPT_BLOCKS, ( \"Too many script allocations - %d, max is %d\", num_script, MAX_SCRIPT_BLOCKS ) );\r\n\t\t\t\t\trv = p_script[num_script];\t\t\t\t// The address we're going to return.\r\n\t\t\t\t\tascript[num_script] = 1;\t\t\t\t\t// Set this entry as allocated.\r\n\t\t\t\t\tnum_script++;\t\t\t\t\t\t\t// Added 1 allocation.\r\n\t\t\t\t\tp_script[num_script] = p_script[num_script-1] + ( ( size + 31 ) & ~31 );\t// Move current pointer on.\r\n\t\t\t\t}\r\n//\t\t\t}\r\n\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tuint32 c_unused = unused();\r\n\tif ( c_unused < g_min_unused ) g_min_unused = c_unused;\r\n\r\n\tg_fragmented_bu = 0;\r\n\tfor ( lp = 0; lp < ( num_bu - 1 ); lp++ )\r\n\t{\r\n\t\tif ( !abu[lp] )\r\n\t\t{\r\n\t\t\t// Found it! Calculate size.\r\n\t\t\tg_fragmented_bu += p_bu[lp+1] - p_bu[lp];\r\n\t\t}\r\n\t}\r\n\r\n\tg_fragmented_td = 0;\r\n\tfor ( lp = 0; lp < ( num_td - 1 ); lp++ )\r\n\t{\r\n\t\tif ( !atd[lp] )\r\n\t\t{\r\n\t\t\t// Found it! Calculate size.\r\n\t\t\tg_fragmented_td += p_td[lp-1] - p_td[lp];\r\n\t\t}\r\n\t}\r\n\r\n\treturn rv;\r\n}\r\n\r\nvoid NsARAM::free( uint32 p )\r\n{\r\n\tint lp;\r\n\r\n\t// BOTTOMUP:: Search for this pointer.\r\n\tfor ( lp = 0; lp < num_bu; lp++ )\r\n\t{\r\n\t\tif ( p_bu[lp] == p )\r\n\t\t{\r\n\t\t\t// Found it! Flag it as freed.\r\n\t\t\tabu[lp] = 0;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// BOTTOMUP:: Scan the stack pointer list & see if we can reduce it.\r\n\tfor ( lp = (num_bu-1); lp >= 0; lp-- )\r\n\t{\r\n\t\tif ( abu[lp] )\r\n\t\t{\r\n\t\t\t// Found an allocated entry - this is the top of the stack. Adjust to it.\r\n\t\t\tnum_bu = lp + 1;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tnum_bu = lp;\r\n\t\t}\r\n\t}\r\n\r\n\t// TOPDOWN:: Search for this pointer.\r\n\tfor ( lp = 0; lp < num_td; lp++ )\r\n\t{\r\n\t\tif ( p_td[lp] == p )\r\n\t\t{\r\n\t\t\t// Found it! Flag it as freed.\r\n\t\t\tatd[lp] = 0;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// TOPDOWN:: Scan the stack pointer list & see if we can reduce it.\r\n\tfor ( lp = (num_td-1); lp >= 0; lp-- )\r\n\t{\r\n\t\tif ( atd[lp] )\r\n\t\t{\r\n\t\t\t// Found an allocated entry - this is the top of the stack. Adjust to it.\r\n\t\t\tnum_td = lp + 1;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// Set current top-down pointer.\r\n\tif ( num_td )\r\n\t{\r\n\t\tp_cur_td = p_td[num_td-1];\r\n\t}\r\n\telse\r\n\t{\r\n\t\tp_cur_td = p_td_base;\r\n\t}\r\n\r\n\t// SKATER0:: Search for this pointer.\r\n\tfor ( lp = 0; lp < num_sk0; lp++ )\r\n\t{\r\n\t\tif ( p_sk0[lp] == p )\r\n\t\t{\r\n\t\t\t// Found it! Flag it as freed.\r\n\t\t\task0[lp] = 0;\r\n//\t\t\tOSReport( \"Freed address: %d\\n\", p );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// SKATER0:: Scan the stack pointer list & see if we can reduce it.\r\n\tfor ( lp = (num_sk0-1); lp >= 0; lp-- )\r\n\t{\r\n\t\tif ( ask0[lp] )\r\n\t\t{\r\n\t\t\t// Found an allocated entry - this is the top of the stack. Adjust to it.\r\n\t\t\tnum_sk0 = lp + 1;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tnum_sk0 = lp;\r\n\t\t}\r\n\t}\r\n\r\n\t// SKATER1:: Search for this pointer.\r\n\tfor ( lp = 0; lp < num_sk1; lp++ )\r\n\t{\r\n\t\tif ( p_sk1[lp] == p )\r\n\t\t{\r\n\t\t\t// Found it! Flag it as freed.\r\n\t\t\task1[lp] = 0;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// SKATER1:: Scan the stack pointer list & see if we can reduce it.\r\n\tfor ( lp = (num_sk1-1); lp >= 0; lp-- )\r\n\t{\r\n\t\tif ( ask1[lp] )\r\n\t\t{\r\n\t\t\t// Found an allocated entry - this is the top of the stack. Adjust to it.\r\n\t\t\tnum_sk1 = lp + 1;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tnum_sk1 = lp;\r\n\t\t}\r\n\t}\r\n\r\n\t// SCRIPT:: Search for this pointer.\r\n\tfor ( lp = 0; lp < num_script; lp++ )\r\n\t{\r\n\t\tif ( p_script[lp] == p )\r\n\t\t{\r\n\t\t\t// Found it! Flag it as freed.\r\n\t\t\tascript[lp] = 0;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// SCRIPT:: Scan the stack pointer list & see if we can reduce it.\r\n\tfor ( lp = (num_script-1); lp >= 0; lp-- )\r\n\t{\r\n\t\tif ( ascript[lp] )\r\n\t\t{\r\n\t\t\t// Found an allocated entry - this is the top of the stack. Adjust to it.\r\n\t\t\tnum_script = lp + 1;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tnum_script = lp;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\tg_fragmented_bu = 0;\r\n\tfor ( lp = 0; lp < ( num_bu - 1 ); lp++ )\r\n\t{\r\n\t\tif ( !abu[lp] )\r\n\t\t{\r\n\t\t\t// Found it! Calculate size.\r\n\t\t\tg_fragmented_bu += p_bu[lp+1] - p_bu[lp];\r\n\t\t}\r\n\t}\r\n\r\n\tg_fragmented_td = 0;\r\n\tfor ( lp = 0; lp < ( num_td - 1 ); lp++ )\r\n\t{\r\n\t\tif ( !atd[lp] )\r\n\t\t{\r\n\t\t\t// Found it! Calculate size.\r\n\t\t\tg_fragmented_td += p_td[lp-1] - p_td[lp];\r\n\t\t}\r\n\t}\r\n}\r\n\r\nuint32 NsARAM::unused( void )\r\n{\r\n\treturn p_cur_td - p_bu[num_bu];\r\n}\r\n\r\nuint32 NsARAM::getSize( uint32 p )\r\n{\r\n\tint lp;\r\n\tuint32 rv = 0;\r\n\r\n\t// BOTTOMUP:: Search for this pointer.\r\n\tfor ( lp = 0; lp < num_bu; lp++ )\r\n\t{\r\n\t\tif ( p_bu[lp] == p )\r\n\t\t{\r\n\t\t\t// Found it! Calculate size.\r\n\t\t\trv = p_bu[lp+1] - p_bu[lp];\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// TOPDOWN:: Search for this pointer.\r\n\tfor ( lp = 0; lp < num_td; lp++ )\r\n\t{\r\n\t\tif ( p_td[lp] == p )\r\n\t\t{\r\n\t\t\t// Found it! Calculate size.\r\n\t\t\trv = p_td[lp-1] - p_bu[lp];\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// SKATER0:: Search for this pointer.\r\n\tfor ( lp = 0; lp < num_sk0; lp++ )\r\n\t{\r\n\t\tif ( p_sk0[lp] == p )\r\n\t\t{\r\n\t\t\t// Found it! Calculate size.\r\n\t\t\trv = p_sk0[lp+1] - p_sk0[lp];\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// SKATER1:: Search for this pointer.\r\n\tfor ( lp = 0; lp < num_sk1; lp++ )\r\n\t{\r\n\t\tif ( p_sk1[lp] == p )\r\n\t\t{\r\n\t\t\t// Found it! Calculate size.\r\n\t\t\trv = p_sk1[lp+1] - p_sk1[lp];\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// SCRIPT:: Search for this pointer.\r\n\tfor ( lp = 0; lp < num_script; lp++ )\r\n\t{\r\n\t\tif ( p_script[lp] == p )\r\n\t\t{\r\n\t\t\t// Found it! Calculate size.\r\n\t\t\trv = p_script[lp+1] - p_script[lp];\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\treturn rv;\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_aram.h",
    "content": "#ifndef _ARAM_H_\r\n#define _ARAM_H_\r\n\r\n#ifndef __CORE_DEFINES_H\r\n\t#include <core/defines.h>\r\n#endif\r\n\r\n#include <dolphin.h>\r\n\r\nnamespace NsARAM\r\n{\r\n\ttypedef enum {\r\n\t\tBOTTOMUP = 0,\r\n\t\tTOPDOWN,\r\n\t\tSKATER0,\r\n\t\tSKATER1,\r\n\t\tSCRIPT,\r\n\r\n\t\tNUMHEAPS,\r\n\t} HEAPTYPE;\r\n\r\n\tvoid\tinit\t( void );\r\n\tuint32\talloc\t( uint32 size, HEAPTYPE heap = BOTTOMUP );\r\n\tvoid\tfree\t( uint32 p );\r\n\tuint32\tgetSize\t( uint32 p );\r\n\r\n\tuint32\tunused\t( void );\r\n};\r\n\r\n#endif\t\t// _ARAM_H_\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_assert.h",
    "content": "#define assertf( _exp, _params ) ( ( _exp ) ? ( void ) 0 : ( OSReport ( \"\" ), OSReport ( \"**************************************\\n\" ), OSReport ( \"Assertion failed: \\\"%s\\\"\\n\", #_exp ), OSReport _params, OSPanic(__FILE__, __LINE__, \"Function \\\"%s\\\" failed\", __FUNCTION__ ) ) )\r\n#define assert( _exp ) ( ( _exp ) ? ( void ) 0 : ( OSReport ( \"\" ), OSReport ( \"**************************************\\n\" ), OSReport ( \"Assertion failed: \\\"%s\\\"\\n\", #_exp ), OSPanic(__FILE__, __LINE__, \"Function \\\"%s\\\" failed\", __FUNCTION__ ) ) )\r\n#define assertp( _ptr ) ( ( _ptr ) ? ( void ) 0 : ( OSReport ( \"\" ), OSReport ( \"**************************************\\n\" ), OSReport ( \"Pointer Assertion failed: \\\"%s\\\" = %08x\\n\", #_ptr, _ptr ), OSPanic(__FILE__, __LINE__, \"Function \\\"%s\\\" failed\", __FUNCTION__ ) ) )\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_atomic.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsAtomic\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tHolds Clump data & draws it.\t\t\t\t\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include <math.h>\r\n//#include <string.h>\r\n//#include \"p_atomic.h\"\r\n//#include \"p_frame.h\"\r\n//#include <charpipeline/GQRSetup.h>\r\n//#include \"p_profile.h\"\r\n//#include \"p_display.h\"\r\n//#include \"p_assert.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//// See 'RpAtomicFlag' in rpworld.h\r\n//#define COLLIDABLE 1\r\n//#define VISIBLE 4\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsProfile AnimTime( \"Anim Time\", 256 );\r\n//int gTripleMem = 0;\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//extern \"C\" {\r\n//\r\n//extern void TransformSingle\t( ROMtx m, float * srcBase, float * dstBase, u32 count );\r\n//extern void TransformDouble\t( ROMtx m0, ROMtx m1, float * wtBase, float * srcBase, float * dstBase, u32 count );\r\n//extern void TransformAcc\t( ROMtx m, u16 count, float * srcBase, float * dstBase, u16 * indices, float * weights );\r\n//\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsAtomic\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tDeclares a clump object.\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n//NsAtomic::NsAtomic()\r\n//{\r\n//\tm_pMaterial\t= NULL;\r\n//\tm_pFrame\t\t= NULL;\r\n//\tm_pNext\t\t= NULL;\r\n//\tm_pDoubleData\t= NULL;\r\n//\tm_pAccData\t= NULL;\r\n//\tm_flags = VISIBLE | COLLIDABLE;\r\n//\tm_pTransformedVertices = NULL;\r\n//\tm_pTransformedVertices2 = NULL;\r\n//\tm_pTransformedVertices3 = NULL;\r\n//\tm_pGeometryArrays = NULL;\r\n//\r\n//\tm_pSkinBox = NULL;\r\n//\tm_pCAS16 = NULL;\r\n//\tm_pFlipPairs = NULL;\r\n//\tm_pCAS32 = NULL;\r\n//\tm_pPartChecksums = NULL;\r\n//\tm_pBranchNodes = NULL;\r\n//\tm_pLeafNodes = NULL;\r\n//\tm_pTriangleMap = NULL;\r\n//\r\n//\tm_lastTransform = -1;\t\t// Force 1st transform to always happen.\r\n//}\r\n//\r\n//NsAtomic::NsAtomic( NsModel * pModelData, NsTextureMan * pTexMan )\r\n//{\r\n//\tm_pMaterial\t= NULL;\r\n//\tm_pFrame\t\t= NULL;\r\n//\tm_pNext\t\t= NULL;\r\n//\tm_pDoubleData\t= NULL;\r\n//\tm_pAccData\t= NULL;\r\n//\tm_flags = VISIBLE | COLLIDABLE;\r\n//\tm_pTransformedVertices = NULL;\r\n//\tm_pTransformedVertices2 = NULL;\r\n//\tm_pTransformedVertices3 = NULL;\r\n//\tm_pGeometryArrays = NULL;\r\n//\r\n//\tm_pSkinBox = NULL;\r\n//\tm_pCAS16 = NULL;\r\n//\tm_pFlipPairs = NULL;\r\n//\tm_pCAS32 = NULL;\r\n//\tm_pPartChecksums = NULL;\r\n//\tm_pBranchNodes = NULL;\r\n//\tm_pLeafNodes = NULL;\r\n//\tm_pTriangleMap = NULL;\r\n//\r\n//\tm_lastTransform = -1;\t\t// Force 1st transform to always happen.\r\n//\t\r\n//\tsetModel( pModelData, pTexMan );\r\n//}\r\n//\r\n//NsAtomic::~NsAtomic()\r\n//{\r\n////\tif ( pFrame ) delete pFrame;\r\n//\r\n//\tNsDisplay::flush();\r\n//\t\r\n//\t// Multi-reference stuff.\r\n//\tif ( m_pMaterial ) {\r\n//\t\tif ( m_pMaterial->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pMaterial;\r\n//\t\t} else {\r\n//\t\t\tm_pMaterial->removeReference();\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tif ( m_pDoubleData ) {\r\n//\t\tif ( m_pDoubleData->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pDoubleData;\r\n//\t\t} else {\r\n//\t\t\tm_pDoubleData->removeReference();\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tif ( m_pAccData ) {\r\n//\t\tif ( m_pAccData->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pAccData;\r\n//\t\t} else {\r\n//\t\t\tm_pAccData->removeReference();\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tif ( m_pTransformedVertices && ( m_pTransformedVertices != m_pGeometryArrays ) ) {\r\n//\t\tif ( m_pTransformedVertices->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pTransformedVertices;\r\n//\t\t} else {\r\n//\t\t\tm_pTransformedVertices->removeReference();\r\n//\t\t}\r\n//\t}\r\n//\tif ( m_pTransformedVertices2 ) delete m_pTransformedVertices2;\r\n//\tif ( m_pTransformedVertices3 ) delete m_pTransformedVertices3;\r\n//\r\n//\tif ( m_pGeometryArrays ) {\r\n//\t\tif ( m_pGeometryArrays->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pGeometryArrays;\r\n//\t\t} else {\r\n//\t\t\tm_pGeometryArrays->removeReference();\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tif ( m_pSkinBox ) {\r\n//\t\tif ( m_pSkinBox->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pSkinBox;\r\n//\t\t} else {\r\n//\t\t\tm_pSkinBox->removeReference();\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tif ( m_pCAS16 ) {\r\n//\t\tif ( m_pCAS16->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pCAS16;\r\n//\t\t} else {\r\n//\t\t\tm_pCAS16->removeReference();\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tif ( m_pFlipPairs ) {\r\n//\t\tif ( m_pFlipPairs->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pFlipPairs;\r\n//\t\t} else {\r\n//\t\t\tm_pFlipPairs->removeReference();\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tif ( m_pCAS32 ) {\r\n//\t\tif ( m_pCAS32->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pCAS32;\r\n//\t\t} else {\r\n//\t\t\tm_pCAS32->removeReference();\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tif ( m_pPartChecksums ) {\r\n//\t\tif ( m_pPartChecksums->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pPartChecksums;\r\n//\t\t} else {\r\n//\t\t\tm_pPartChecksums->removeReference();\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tif ( m_pBranchNodes ) {\r\n//\t\tif ( m_pBranchNodes->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pBranchNodes;\r\n//\t\t} else {\r\n//\t\t\tm_pBranchNodes->removeReference();\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tif ( m_pLeafNodes ) {\r\n//\t\tif ( m_pLeafNodes->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pLeafNodes;\r\n//\t\t} else {\r\n//\t\t\tm_pLeafNodes->removeReference();\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tif ( m_pTriangleMap ) {\r\n//\t\tif ( m_pTriangleMap->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pTriangleMap;\r\n//\t\t} else {\r\n//\t\t\tm_pTriangleMap->removeReference();\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n//NsModel * NsAtomic::setModel( NsModel * pModelData, NsTextureMan * pTexMan )\r\n//{\r\n//\tNsModel * pNextModel;\r\n//\r\n//\t// Generate a material manager.\r\n//\tm_pMaterial = new NsMaterialMan(pModelData->m_numMaterials);\r\n//\r\n//\t// Build the materials.\r\n//\tpModelData->buildMaterials ( m_pMaterial, pTexMan );\r\n//\r\n//\t// Attach a frame.\r\n////\tpFrame = new NsFrame;\r\n//\r\n//\t// Build the display list.\r\n//\tpNextModel = (NsModel *)pModelData->draw( m_pMaterial, NULL, 0, 0 );\r\n//\tm_pTransformedVertices = m_pGeometryArrays = new NsRefTransformedVertices( (NsAnim_PosNormPair *)pModelData->getVertexPool() );\r\n//\r\n//\t// The display lists no longer own the pools.\r\n//\tfor ( int lp = 0; lp < m_pMaterial->m_materialListSize; lp++ ) {\r\n//\t\tNsDL * pDL = m_pMaterial->m_pSortedMaterialList[lp]->headDL();\r\n//\t\twhile ( pDL ) {\r\n//\t\t\tif ( pDL->m_pParent->m_pVertexPool ) {\r\n//\t\t\t\t// Set flag to stop vpool being deallocated elsewhere.\r\n//\t\t\t\tpDL->m_pParent->m_vpoolFlags |= (1<<4);\r\n//\t\t\t}\r\n//\t\t\tpDL = pDL->m_pNext;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tNsSkinData\t\t  * pSkinData;\r\n//\tNsBBox\t\t\t  * pSkinBox;\r\n//\tunsigned short\t  * pCAS16;\r\n//\tunsigned int\t  * pFlipPairs;\r\n//\tunsigned int\t  * pCAS32;\r\n//\tunsigned int\t  * pPartChecksums;\r\n//\tNsBranch\t\t  * pBranchNodes;\r\n//\tNsLeaf\t\t\t  * pLeafNodes;\r\n//\tunsigned int\t  * pTriangleMap;\r\n//\r\n//\tpSkinData = pModelData->m_pSkinData;\r\n//\tpSkinBox = (NsBBox *)&pSkinData[1];\r\n//\tpCAS16 = (unsigned short *)&pSkinBox[pSkinData->numSkinBoxes];\r\n//\tpFlipPairs = (unsigned int *)&pCAS16[pSkinData->numCAS16+(pSkinData->numCAS16&1)];\r\n//\tpCAS32 = (unsigned int *)&pFlipPairs[pSkinData->numFlipPairs * 2];\r\n//\tpPartChecksums = (unsigned int *)&pCAS32[pSkinData->numCAS32];\r\n//\tpBranchNodes = (NsBranch *)&pPartChecksums[pSkinData->numPartChecksums];\r\n//\tpLeafNodes = (NsLeaf *)&pBranchNodes[pSkinData->numLeaf ? pSkinData->numLeaf - 1 : 0];\r\n//\tpTriangleMap = (unsigned int *)&pLeafNodes[pSkinData->numLeaf];\r\n//\r\n//\tm_numSkinBoxes = pSkinData->numSkinBoxes;\r\n//\tm_numCAS16 = pSkinData->numCAS16;\r\n//\tm_numFlipPairs = pSkinData->numFlipPairs;\r\n//\tm_numCAS32 = pSkinData->numCAS32;\r\n//\tm_numPartChecksums = pSkinData->numPartChecksums;\r\n//\tm_removeCAS32 = pSkinData->removeCAS32;\r\n//\tm_removeCAS16 = pSkinData->removeCAS16;\r\n//\tm_numBranchNodes = pSkinData->numLeaf ? pSkinData->numLeaf - 1 : 0;\r\n//\tm_numLeafNodes = pSkinData->numLeaf;\r\n//\tm_numTriangles = pSkinData->numTri;\r\n//\t\r\n//\t// Copy the skin boxes.\r\n//\tif ( m_numSkinBoxes ) {\r\n//\t\tm_pSkinBox = new NsRefSkinBox( new NsBBox[m_numSkinBoxes] );\r\n//\t\tmemcpy ( m_pSkinBox->m_pSkinBox, pSkinBox, sizeof ( NsBBox ) * m_numSkinBoxes );\r\n//\t}\r\n//\r\n//\t// Copy the 16 bit CAS flags.\r\n//\tif ( m_numCAS16 ) {\r\n//\t\tm_pCAS16 = new NsRefCAS16( new unsigned short[m_numCAS16] );\r\n//\t\tmemcpy ( m_pCAS16->m_pCAS16, pCAS16, sizeof ( unsigned short ) * m_numCAS16 );\r\n//\t}\r\n//\r\n//\t// Copy the flip pairs.\r\n//\tif ( m_numFlipPairs ) {\r\n//\t\tm_pFlipPairs = new NsRefFlipPairs( new unsigned int[m_numFlipPairs * 2] );\r\n//\t\tmemcpy ( m_pFlipPairs->m_pFlipPairs, pFlipPairs, sizeof ( unsigned int ) * m_numFlipPairs * 2 );\r\n//\t}\r\n//\r\n//\t// Copy the 32 bit CAS flags.\r\n//\tif ( m_numCAS32 ) {\r\n//\t\tm_pCAS32 = new NsRefCAS32( new unsigned int[m_numCAS32] );\r\n//\t\tmemcpy ( m_pCAS32->m_pCAS32, pCAS32, sizeof ( unsigned int ) * m_numCAS32 );\r\n//\t}\r\n//\r\n//\t// Copy the 32 bit CAS flags.\r\n//\tif ( m_numPartChecksums ) {\r\n//\t\tm_pPartChecksums = new NsRefPartChecksums( new unsigned int[m_numPartChecksums] );\r\n//\t\tmemcpy ( m_pPartChecksums->m_pPartChecksums, pPartChecksums, sizeof ( unsigned int ) * m_numPartChecksums );\r\n//\t}\r\n//\r\n//\t// Copy the branch nodes.\r\n//\tif ( m_numBranchNodes ) {\r\n//\t\tm_pBranchNodes = new NsRefBranchNodes( new NsBranch[m_numBranchNodes] );\r\n//\t\tmemcpy ( m_pBranchNodes->m_pBranchNodes, pBranchNodes, sizeof ( NsBranch ) * m_numBranchNodes );\r\n//\t}\r\n//\r\n//\t// Copy the leaf nodes.\r\n//\tif ( m_numLeafNodes ) {\r\n//\t\tm_pLeafNodes = new NsRefLeafNodes( new NsLeaf[m_numLeafNodes] );\r\n//\t\tmemcpy ( m_pLeafNodes->m_pLeafNodes, pLeafNodes, sizeof ( NsLeaf ) * m_numLeafNodes );\r\n//\t}\r\n//\r\n//\t// Copy the triangle map.\r\n//\tif ( m_numTriangles ) {\r\n//\t\tm_pTriangleMap = new NsRefTriangleMap( new unsigned int[m_numTriangles] );\r\n//\t\tmemcpy ( m_pTriangleMap->m_pTriangleMap, pTriangleMap, sizeof ( unsigned int ) * m_numTriangles );\r\n//\t}\r\n//\r\n//\tm_stride = pModelData->getStride() * sizeof ( NsVector );\r\n//\tm_numVertices = pModelData->m_numVertex;\r\n//\tm_frameNumber = (unsigned int)pModelData->m_frameNumber;\r\n//\r\n//\t// Fix branch data.\r\n//\tif ( m_numBranchNodes ) {\r\n//\t\tunsigned int  * p32 = (unsigned int *)m_pBranchNodes->m_pBranchNodes;\r\n//\t\tunsigned int\tvalue;\r\n//\t\tfor ( unsigned int lp = 0; lp < m_numBranchNodes; lp++ ) {\r\n//\t\t\tvalue = *p32++;\r\n//\t\t\tm_pBranchNodes->m_pBranchNodes[lp].type = (unsigned short)( ( value >> 16 ) & 0x0000ffff );\r\n//\t\t\tm_pBranchNodes->m_pBranchNodes[lp].leftType = (unsigned char)( ( value >> 8 ) & 0x000000ff );\r\n//\t\t\tm_pBranchNodes->m_pBranchNodes[lp].rightType = (unsigned char)( value & 0x000000ff );\r\n//\t\t\tvalue = *p32++;\r\n//\t\t\tm_pBranchNodes->m_pBranchNodes[lp].leftNode = (unsigned short)( ( value >> 16 ) & 0x0000ffff );\r\n//\t\t\tm_pBranchNodes->m_pBranchNodes[lp].rightNode = (unsigned short)( value & 0x0000ffff );\r\n//\t\t\tp32 += 2;\r\n//\t\t}\r\n//\t}\r\n//\t\r\n//\t// Fix leaf data.\r\n//\tif ( m_numLeafNodes ) {\r\n//\t\tunsigned int  * p32 = (unsigned int *)m_pLeafNodes->m_pLeafNodes;\r\n//\t\tunsigned int\tvalue;\r\n//\t\tfor ( unsigned int lp = 0; lp < m_numLeafNodes; lp++ ) {\r\n//\t\t\tvalue = *p32++;\r\n//\t\t\tm_pLeafNodes->m_pLeafNodes[lp].numPolygons = (unsigned short)( ( value >> 16 ) & 0x0000ffff );\r\n//\t\t\tm_pLeafNodes->m_pLeafNodes[lp].firstPolygon = (unsigned short)( value & 0x0000ffff );\r\n//\t\t}\r\n//\t}\r\n//\t\r\n//\treturn pNextModel;\r\n//}\r\n//\r\n//void NsAtomic::draw( NsCamera * camera )\r\n//{\r\n//\t// Check atomic visibility flags.\r\n//\tif ( !( m_flags & VISIBLE ) ) return;\r\n//\r\n////\tMtx\t\t\tm;\r\n////\tMtx\t\t\ts;\r\n//\r\n//\t// Setup draw parameters.\r\n//\tNsRender::setCullMode ( NsCullMode_Never );\r\n////\tsceneMaterial.cull( camera->getCurrent() );\r\n////\tsceneMaterial.draw();\r\n//\r\n//\tNsAnim_PosNormPair\t  * pPool;\r\n//\tif ( m_pDoubleData ) {\r\n//\t\tswitch ( NsDisplay::getCurrentBufferIndex() ) {\r\n//\t\t\tcase 0:\r\n//\t\t\t\tpPool = m_pTransformedVertices->m_pTransformedVertices;\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase 1:\r\n//\t\t\t\tpPool = m_pTransformedVertices2;\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase 2:\r\n//\t\t\t\tpPool = m_pTransformedVertices3;\r\n//\t\t\t\tbreak;\r\n//\t\t\tdefault:\r\n//\t\t\t\tassertf ( false, ( \"Illegal triple buffer index.\\n\" ) );\r\n//\t\t\t\tpPool = NULL;\r\n//\t\t\t\tbreak;\r\n//\t\t}\r\n//\t} else {\r\n//\t\tpPool = m_pTransformedVertices->m_pTransformedVertices;\r\n//\t}\r\n//\r\n//\t// Point to array for this atomic (could be cloned).\r\n//    GXSetArray(GX_VA_POS, pPool->pos, m_stride);\r\n//\tif ( m_stride > (int)( 3 * sizeof ( float ) ) ) {\r\n//\t\tGXSetArray(GX_VA_NRM, pPool->norm, m_stride);\r\n//\t}\r\n//\r\n//\t// Draw it.\r\n//\tm_pMaterial->draw();\r\n//\r\n//\t// Draw a cube, too.\r\n////\tNsRender::setBlendMode ( NsBlendMode_None, NULL, (unsigned char)255 );\r\n////    MTXScale(s,8,8,8);\r\n////    MTXConcat(m,s,m);\r\n////    GX::LoadPosMtxImm( m, GX_PNMTX0 );\r\n////\tGXDrawCube();\r\n//}\r\n//\r\n//void NsAtomic::draw ( NsCamera * camera, ROMtx * pBoneMatrices, unsigned int transform )\r\n//{\r\n//\tNsAnim_PosNormPair\t  * pPool;\r\n//\tunsigned int\t\t  * p32;\r\n//\tNsAnim_PosNormPair\t  * pPosNormPair;\r\n//\tNsAnim_WeightPair\t  * pWeight;\r\n//\tfloat\t\t\t\t  * pSingleWeight;\r\n//\tunsigned short\t\t  * pIndices;\r\n//\r\n//\t// Check atomic visibility flags.\r\n//\tif ( !( m_flags & VISIBLE ) ) return;\r\n//\r\n//// \t// Point up stuff we're interested in.\t\r\n//// \tpMaterial = (unsigned char *)&pModel[8];\r\n//// \tpGeom = (unsigned int *)&pMaterial[pModel[0]*64];\r\n////\tpCount = (unsigned int *)&pSkinHeader[1];\r\n//\r\n//\tif ( m_pTransformedVertices && m_numVertices && ( m_lastTransform != NsDisplay::getCurrentBufferIndex() ) && transform ) {\r\n//\t\tAnimTime.start();\r\n//\r\n//\t\t// Transform paired vertices.\r\n//\t\tswitch ( NsDisplay::getCurrentBufferIndex() ) {\r\n//\t\t\tcase 0:\r\n//\t\t\t\tpPool = m_pTransformedVertices->m_pTransformedVertices;\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase 1:\r\n//\t\t\t\tpPool = m_pTransformedVertices2;\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase 2:\r\n//\t\t\t\tpPool = m_pTransformedVertices3;\r\n//\t\t\t\tbreak;\r\n//\t\t\tdefault:\r\n//\t\t\t\tassertf ( false, ( \"Illegal triple buffer index.\\n\" ) );\r\n//\t\t\t\tpPool = NULL;\r\n//\t\t\t\tbreak;\r\n//\t\t}\r\n//\r\n//\t\tp32 = m_pDoubleData->m_pDoubleData;\r\n//\t\twhile ( p32[0] ) {\r\n//\t\t\tpPosNormPair = (NsAnim_PosNormPair *)&p32[2];\r\n//\t\t\tpWeight = (NsAnim_WeightPair *)&pPosNormPair[p32[0]];\r\n//\r\n//\t\t\tTransformDouble( pBoneMatrices[p32[1]&255], pBoneMatrices[(p32[1]>>8)&255], pWeight->w, pPosNormPair->pos, pPool->pos, p32[0] == 1 ? 2 : p32[0] );\r\n//\t\t\t//TransformSingle( pBoneMatrices[p32[1]&255], pPosNormPair->pos, pPool->pos, p32[0] == 1 ? 2 : p32[0] );\r\n//\t\t\tpPool += p32[0];\r\n//\t\t\tp32 = (unsigned int *)&pWeight[p32[0]];\r\n//\t\t}\r\n//\r\n//\t\t// Transform accumulation vertices.\r\n//\t\tswitch ( NsDisplay::getCurrentBufferIndex() ) {\r\n//\t\t\tcase 0:\r\n//\t\t\t\tpPool = m_pTransformedVertices->m_pTransformedVertices;\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase 1:\r\n//\t\t\t\tpPool = m_pTransformedVertices2;\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase 2:\r\n//\t\t\t\tpPool = m_pTransformedVertices3;\r\n//\t\t\t\tbreak;\r\n//\t\t\tdefault:\r\n//\t\t\t\tassertf ( false, ( \"Illegal triple buffer index.\\n\" ) );\r\n//\t\t\t\tpPool = NULL;\r\n//\t\t\t\tbreak;\r\n//\t\t}\r\n//\r\n//\t\tp32 = m_pAccData->m_pAccData;\r\n//\t\twhile ( p32[0] ) {\r\n//\t\t\tpPosNormPair = (NsAnim_PosNormPair *)&p32[2];\r\n//\t\t\tpSingleWeight = (float *)&pPosNormPair[p32[0]];\r\n//\t\t\tpIndices = (unsigned short *)&pSingleWeight[p32[0]];\r\n//\r\n//\t\t\tTransformAcc ( pBoneMatrices[p32[1]], p32[0], pPosNormPair->pos, pPool->pos, pIndices, pSingleWeight );\r\n//\t\t\tp32 = (unsigned int *)&pIndices[p32[0]+(p32[0]&1)];\r\n//\t\t}\r\n//\t\tDCFlushRange(pPool, sizeof ( NsAnim_PosNormPair ) * m_numVertices);\r\n//\t\r\n//\t\tm_lastTransform = NsDisplay::getCurrentBufferIndex();\r\n//\t\t\r\n//\t\tAnimTime.stop();\r\n//\t\r\n//\t\t\r\n////\t\tNsAnim_PosNormPair\t  * p;\r\n////\t\tp = m_pTransformedVertices->m_pTransformedVertices;\r\n////\t\tm_pTransformedVertices->m_pTransformedVertices = m_pTransformedVertices2;\r\n////\t\tm_pTransformedVertices2 = m_pTransformedVertices3;\r\n////\t\tm_pTransformedVertices3 = p;\r\n//\t}\r\n//\r\n//\tdraw( camera );\r\n//}\r\n//\r\n//NsAtomic& NsAtomic::clone ( void )\r\n//{\r\n//\tNsAtomic  * pClonedAtomic;\r\n//\r\n//\t// Create a cloned atomic.\r\n//\tpClonedAtomic = new NsAtomic;\r\n//\tmemcpy( pClonedAtomic, this, sizeof( NsAtomic ) );\r\n//\r\n////\t// Clone the frame.\r\n////\tpClonedAtomic->setFrame( new NsFrame );\r\n////\tmemcpy( pClonedAtomic->getFrame(), m_pFrame, sizeof( NsFrame ) );\r\n//\r\n//\t// Allocate a new transformed vertex pool (only if we have a skin attached).\r\n//\tif ( m_pDoubleData ) {\r\n//\t\tpClonedAtomic->m_pTransformedVertices = new NsRefTransformedVertices( new NsAnim_PosNormPair[(m_numVertices+1)] );\r\n//\t\tpClonedAtomic->m_pTransformedVertices2 = new NsAnim_PosNormPair[(m_numVertices+1)];\r\n//\t\tpClonedAtomic->m_pTransformedVertices3 = new NsAnim_PosNormPair[(m_numVertices+1)];\r\n//\t\tgTripleMem += sizeof( NsAnim_PosNormPair ) * (m_numVertices+1) * 3;\r\n//\t}\r\n//\r\n//\t// Multi-reference counts.\r\n//\tif ( m_pGeometryArrays ) m_pGeometryArrays->addReference();\r\n//\tif ( m_pMaterial ) m_pMaterial->addReference();\r\n//\tif ( m_pDoubleData ) m_pDoubleData->addReference();\r\n//\tif ( m_pAccData ) m_pAccData->addReference();\r\n//\tif ( m_pSkinBox ) m_pSkinBox->addReference();\r\n//\tif ( m_pCAS16 ) m_pCAS16->addReference();\r\n//\tif ( m_pFlipPairs ) m_pFlipPairs->addReference();\r\n//\tif ( m_pCAS32 ) m_pCAS32->addReference();\r\n//\tif ( m_pPartChecksums ) m_pPartChecksums->addReference();\r\n//\tif ( m_pBranchNodes ) m_pBranchNodes->addReference();\r\n//\tif ( m_pLeafNodes ) m_pLeafNodes->addReference();\r\n//\tif ( m_pTriangleMap ) m_pTriangleMap->addReference();\r\n//\r\n//\treturn *pClonedAtomic;\r\n//}\r\n//\r\n//NsAnim_SkinHeader * NsAtomic::attachSkinData ( NsAnim_SkinHeader * pSkinHeader )\r\n//{\r\n//\tunsigned int\t\t  * pSkinData;\r\n//\tNsAnim_PosNormPair\t  * pPosNormPair;\r\n//\tNsAnim_WeightPair\t  * pWeight;\r\n//\tfloat\t\t\t\t  * pSingleWeight;\r\n//\tunsigned short\t\t  * pIndices;\r\n//\tunsigned int\t\t  * pStart;\r\n//\tint\t\t\t\t\t\tsize;\r\n//\r\n//\tpSkinData = (unsigned int *)&pSkinHeader[1];\r\n//\r\n//\t// Skip the double blend data, and count the number of vertices in this atomic.\r\n//\tpStart = pSkinData;\r\n//\twhile ( pSkinData[0] ) {\r\n//\t\tpPosNormPair = (NsAnim_PosNormPair *)&pSkinData[2];\r\n//\t\tpWeight = (NsAnim_WeightPair *)&pPosNormPair[pSkinData[0]];\r\n//\t\tpSkinData = (unsigned int *)&pWeight[pSkinData[0]];\r\n//\t}\r\n//\tpSkinData++;\t\t// Skip the terminator.\r\n//\r\n//\t// Make a new instance of this data.\r\n//\tsize = ((int)pSkinData)-((int)pStart);\r\n//\tm_pDoubleData = new NsRefDoubleData( new unsigned int[size/4] );\r\n//\tmemcpy ( m_pDoubleData->m_pDoubleData, pStart, size );\r\n//\r\n//\t// Skip the accumulation blend data.\r\n//\tpStart = pSkinData;\r\n//\twhile ( pSkinData[0] ) {\r\n//\t\tpPosNormPair = (NsAnim_PosNormPair *)&pSkinData[2];\r\n//\t\tpSingleWeight = (float *)&pPosNormPair[pSkinData[0]];\r\n//\t\tpIndices = (unsigned short *)&pSingleWeight[pSkinData[0]];\r\n//\t\tpSkinData = (unsigned int *)&pIndices[pSkinData[0]+(pSkinData[0]&1)];\r\n//\t}\r\n//\tpSkinData++;\t\t// Skip the terminator.\r\n//\r\n//\t// Make a new instance of this data.\r\n//\tsize = ((int)pSkinData)-((int)pStart);\r\n//\tm_pAccData = new NsRefAccData( new unsigned int[size/4] );\r\n//\tmemcpy ( m_pAccData->m_pAccData, pStart, size );\r\n//\r\n//\t// Allocate 2nd & 3rd transform buffers.\r\n//\tm_pTransformedVertices2 = new NsAnim_PosNormPair[(m_numVertices+1)];\r\n//\tm_pTransformedVertices3 = new NsAnim_PosNormPair[(m_numVertices+1)];\r\n//\tgTripleMem += sizeof( NsAnim_PosNormPair ) * (m_numVertices+1) * 2;\r\n//\r\n//\treturn (NsAnim_SkinHeader *)pSkinData;\r\n//}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_atomic.h",
    "content": "//#ifndef _ATOMIC_H_\r\n//#define _ATOMIC_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_model.h\"\r\n//#include \"p_frame.h\"\r\n//#include \"p_anim.h\"\r\n//#include \"p_reftypes.h\"\r\n//\r\n//class NsAtomic\r\n//{\r\n//\tNsMaterialMan\t\t  * m_pMaterial;\r\n//\tNsFrame\t\t\t\t  * m_pFrame;\r\n//\t// Animation weight data, stage 1 - paired blending.\r\n//\tNsRefDoubleData\t\t  * m_pDoubleData;\r\n//\t// Animation weight data, stage 2 - accumulative blending.\r\n//\tNsRefAccData\t\t  * m_pAccData;\r\n//\t// Animation vertex/normal pool.\r\n//\tint\t\t\t\t\t\tm_numVertices;\r\n//\tNsRefTransformedVertices* m_pGeometryArrays;\r\n//\tNsRefTransformedVertices* m_pTransformedVertices;\r\n//\tNsAnim_PosNormPair\t  * m_pTransformedVertices2;\r\n//\tNsAnim_PosNormPair\t  * m_pTransformedVertices3;\r\n//\tint\t\t\t\t\t\tm_lastTransform;\r\n//\tint\t\t\t\t\t\tm_stride;\r\n//\r\n//\tunsigned int\t\t\tm_numSkinBoxes;\r\n//\tunsigned int\t\t\tm_numCAS16;\r\n//\tunsigned int\t\t\tm_numFlipPairs;\r\n//\tunsigned int\t\t\tm_numCAS32;\r\n//\tunsigned int\t\t\tm_numPartChecksums;\r\n//\r\n//\tNsRefSkinBox\t\t  * m_pSkinBox;\r\n//\tNsRefCAS16\t\t\t  * m_pCAS16;\r\n//\tNsRefFlipPairs\t\t  * m_pFlipPairs;\r\n//\tNsRefCAS32\t\t\t  * m_pCAS32;\r\n//\tNsRefPartChecksums\t  * m_pPartChecksums;\r\n//\tunsigned short\t\t\tm_removeCAS16;\r\n//\tunsigned int\t\t\tm_removeCAS32;\r\n//\r\n//\tunsigned int\t\t\tm_frameNumber;\r\n//\tNsAtomic\t\t\t  * m_pNext;\r\n//\r\n//\tvoid\t\t\t\t  * m_pClump;\r\n//\r\n//\tunsigned int\t\t\tm_flags;\t// Same as RpAtomicFlag.\r\n//\r\n//\t// BSP data.\r\n//\tunsigned int\t\t\tm_numBranchNodes;\r\n//\tunsigned int\t\t\tm_numLeafNodes;\r\n//\tunsigned int\t\t\tm_numTriangles;\r\n//\tNsRefBranchNodes\t  * m_pBranchNodes;\r\n//\tNsRefLeafNodes\t\t  * m_pLeafNodes;\r\n//\tNsRefTriangleMap\t  * m_pTriangleMap;\r\n//\r\n//public:\r\n//\tfriend class NsClump;\r\n//\tfriend class NsModel;\r\n//\t\t\t\t\t\t\tNsAtomic\t\t();\r\n//\t\t\t\t\t\t\tNsAtomic\t\t( NsModel * pModelData, NsTextureMan * pTexMan );\r\n//\t\t\t\t\t\t\t~NsAtomic\t\t();\r\n//\r\n//\tNsModel\t\t\t\t  * setModel\t\t( NsModel * pModelData, NsTextureMan * pTexMan );\r\n//\r\n//\tvoid\t\t\t\t\tdraw\t\t\t( NsCamera * camera );\r\n//\tvoid\t\t\t\t\tdraw\t\t\t( NsCamera * camera, ROMtx * pBoneMatrices, unsigned int transform );\r\n//\r\n//\r\n//\tNsFrame\t\t\t\t  * getFrame\t\t( void ) { return m_pFrame; };\r\n//\tvoid\t\t\t\t\tsetFrame\t\t( NsFrame * p ) { m_pFrame = p; };\r\n//\r\n//\tNsAtomic&\t\t\t\tclone\t\t\t( void );\r\n//\r\n//\tNsAnim_SkinHeader\t  * attachSkinData\t( NsAnim_SkinHeader * pSkinHeader );\r\n//\r\n//\tvoid\t\t\t\t  * getClump\t\t( void ) { return m_pClump; }\r\n//\r\n//\tNsMaterialMan\t\t  * getMaterials\t( void ) { return m_pMaterial; }\r\n//\tvoid\t\t\t\t\tsetMaterials\t( NsMaterialMan * p_mat ) { m_pMaterial = p_mat; }\r\n//\r\n//\tunsigned int\t\t\tgetNumSkinBoxes\t\t( void ) { return m_numSkinBoxes; }\r\n//\tunsigned int\t\t\tgetNumCASFlags16\t( void ) { return m_numCAS16; }\r\n//\tunsigned int\t\t\tgetNumFlipPairs\t\t( void ) { return m_numFlipPairs; }\r\n//\tunsigned int\t\t\tgetNumCASFlags32\t( void ) { return m_numCAS32; }\r\n//\tunsigned int\t\t\tgetNumPartChecksums\t( void ) { return m_numPartChecksums; }\r\n//\r\n//\tNsBBox\t\t\t\t  * getSkinBoxes\t\t( void ) { return m_pSkinBox ? m_pSkinBox->m_pSkinBox : NULL; }\r\n//\tunsigned short\t\t  * getCASFlags16\t\t( void ) { return m_pCAS16 ? m_pCAS16->m_pCAS16 : NULL; }\r\n//\tunsigned int\t\t  * getFlipPairs\t\t( void ) { return m_pFlipPairs ? m_pFlipPairs->m_pFlipPairs : NULL; }\r\n//\tunsigned int\t\t  * getCASFlags32\t\t( void ) { return m_pCAS32 ? m_pCAS32->m_pCAS32 : NULL; }\r\n//\tunsigned int\t\t  * getPartChecksums\t( void ) { return m_pPartChecksums ? m_pPartChecksums->m_pPartChecksums : NULL; }\r\n//\tunsigned short\t\t\tgetCASRemoveFlags16\t( void ) { return m_removeCAS16; }\r\n//\tunsigned int\t\t\tgetCASRemoveFlags32\t( void ) { return m_removeCAS32; }\r\n//\r\n//\tvoid\t\t\t\t\tsetFlags\t\t\t( unsigned int flags ) { m_flags = flags; }\r\n//\tunsigned int\t\t\tgetFlags\t\t\t( void ) { return m_flags; }\r\n//\r\n//\t// BSP data.\r\n//\tunsigned int\t\t\tgetNumBranchNodes\t( void ) { return m_numBranchNodes; }\r\n//\tunsigned int\t\t\tgetNumLeafNodes\t\t( void ) { return m_numLeafNodes; }\r\n//\tunsigned int\t\t\tgetNumTriangles\t\t( void ) { return m_numTriangles; }\r\n//\tNsBranch\t\t\t  * getBranchNodes\t\t( void ) { return m_pBranchNodes->m_pBranchNodes; }\r\n//\tNsLeaf\t\t\t\t  * getLeafNodes\t\t( void ) { return m_pLeafNodes->m_pLeafNodes; }\r\n//\tunsigned int\t\t  * getTriangleMap\t\t( void ) { return m_pTriangleMap->m_pTriangleMap; }\r\n//\r\n//};\r\n//\r\n//#endif\t\t// _ATOMIC_H_\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_bbox.cpp",
    "content": "/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsBBox\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tMatrix functionality.\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#include <math.h>\r\n#include <string.h>\r\n#include \"p_bbox.h\"\r\n\r\n/********************************************************************************\r\n * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nnamespace NsBBox\r\n{\r\n}\t\t// namespace NsBBox\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_bbox.h",
    "content": "#ifndef _BBOX_H_\r\n#define _BBOX_H_\r\n\r\n#include <dolphin.h>\r\n#include \"p_matrix.h\"\r\n\r\nclass NsBBox\r\n{\r\npublic:\r\n\tNsVector\tm_min;\r\n\tNsVector\tm_max;\r\n};\r\n\r\n#endif\t\t// _BBOX_H_\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_buffer.cpp",
    "content": "/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsBuffer\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tProvides a cyclic buffer for rendering purposes.\t\t\t\t*\r\n *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t2002 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#include \"p_buffer.h\"\r\n\r\n/********************************************************************************\r\n * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n \r\n/********************************************************************************\r\n * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nchar * g_p_buffer = NULL;\r\nint g_buffer_offset = 0;\r\nint g_buffer_size = 0;\r\n\r\nint g_current_bytes = 0;\r\nint g_last_bytes = 0;\r\n\r\nint g_max_bytes = 0;\r\n\r\n/********************************************************************************\r\n * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nnamespace NsBuffer\r\n{\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tinit\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tSize of buffer to initialize.\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tCreates a buffer for rendering allocations.\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nvoid init ( int size )\r\n{\r\n\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\tg_p_buffer = new char[size];\r\n\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\tg_buffer_offset = 0;\r\n\tg_buffer_size = size;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\treset\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tReset buffer to beginning location.\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tResets to beginning of buffer.\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nvoid reset( bool clear )\r\n{\r\n\tg_buffer_offset = 0;\r\n\tg_current_bytes = 0;\r\n\r\n\tif ( clear )\r\n\t{\r\n\t\tmemset( g_p_buffer, 0, g_buffer_size );\r\n\t}\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tbegin\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tLatches stat information for the current frame.\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nvoid begin ( void )\r\n{\r\n\tg_current_bytes = 0;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tend\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tCalculates stat information for the current frame.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nvoid end ( void )\r\n{\r\n\tif ( g_max_bytes < g_current_bytes )\r\n\t{\r\n\t\tg_max_bytes = g_current_bytes;\r\n\t}\r\n\r\n\tg_last_bytes = g_current_bytes;\r\n\tg_current_bytes = 0;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\talloc\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNumber of bytes to allocate.\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPointer to buffer space.\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tAllocates the requested amount of buffer space.\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nvoid * alloc ( int size )\r\n{\r\n\tif ( !g_p_buffer ) return NULL;\r\n\r\n\tvoid * rv = NULL;\r\n\r\n\t// See if the remaining buffer space is large enough.\r\n\tif ( ( g_buffer_size - g_buffer_offset ) < size )\r\n\t{\r\n\t\t// Not large enough, go back to the beginning.\r\n\t\tg_buffer_offset = 0;\r\n\t}\r\n\trv = &g_p_buffer[g_buffer_offset];\r\n\tg_buffer_offset += size;\r\n\tg_current_bytes += size;\r\n\r\n\treturn rv;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tbytes_used\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tCalculates stat information for the current frame.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nint bytes_used ( void )\r\n{\r\n\treturn g_last_bytes;\r\n}\r\n\r\nint get_size ( void )\r\n{\r\n\treturn g_buffer_size;\r\n}\r\n\r\n}\t\t// NsBuffer\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_buffer.h",
    "content": "#ifndef _BUFFER_H_\r\n#define _BUFFER_H_\r\n\r\n#ifndef __CORE_DEFINES_H\r\n\t#include <core/defines.h>\r\n#endif\r\n\r\nnamespace NsBuffer\r\n{\r\n\tvoid\tinit\t( int size );\r\n\tvoid\treset\t( bool clear = false );\r\n\tvoid\tbegin\t( void );\r\n\tvoid\tend\t\t( void );\r\n\r\n\tvoid *\talloc\t( int size );\r\n\r\n\t// Stat tracking\r\n\tint\t\tbytes_used\t( void );\r\n\r\n\tint\t\tget_size\t( void );\r\n}\r\n\r\n#endif\t\t// _ARAM_H_\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_camera.cpp",
    "content": "/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsCamera\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tFunctionality to set up cameras and minipulate them.\t\t\t*\r\n *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#include <math.h>\r\n#include \"p_camera.h\"\r\n#include \"p_prim.h\"\r\n#include \"p_gx.h\"\r\n\r\n/********************************************************************************\r\n * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#define RwV3dDotProductMacro(a, b)                              \\\r\n    ((((( (((a)->x) * ((b)->x))) +                          \t\\\r\n        ( (((a)->y) * ((b)->y))))) +                        \t\\\r\n        ( (((a)->z) * ((b)->z)))))                          \t\\\r\n\r\n#define RwV3dScaleMacro(o, a, s)                                \\\r\n{                                                               \\\r\n    (o)->x = (((a)->x) * ( (s)));                           \t\\\r\n    (o)->y = (((a)->y) * ( (s)));                           \t\\\r\n    (o)->z = (((a)->z) * ( (s)));                           \t\\\r\n}                                                               \\\r\n\r\n#define RwV3dIncrementScaledMacro(o, a, s)                      \\\r\n{                                                               \\\r\n    (o)->x += (((a)->x) * ( (s)));                          \t\\\r\n    (o)->y += (((a)->y) * ( (s)));                          \t\\\r\n    (o)->z += (((a)->z) * ( (s)));                          \t\\\r\n}                                                               \\\r\n\r\n/********************************************************************************\r\n * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nNsVector\tmovement( 0.0f, 0.0f, 0.0f );\r\nNsVector\tposition( 0.0f, 0.0f, 0.0f );\r\nNsVector\trotation( 0.0f, 0.0f, 0.0f );\r\nNsMatrix\ttemp0;\r\nNsMatrix\ttemp1;\r\nNsMatrix\tsceneMat;\r\nNsMatrix\tskyMat;\r\n\r\n/********************************************************************************\r\n * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nextern PADStatus padData[PAD_MAX_CONTROLLERS]; // game pad state\r\nPADStatus * pPad = &padData[0];\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsCamera\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tGenerates a camera object.\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nNsCamera::NsCamera()\r\n{\r\n\t// Default border settings.\r\n\torthographic( 0, 0, 640, 448 );\r\n\r\n\t// Default up vector: y is up.\r\n\tm_up.set( 0.0f, 1.0f, 0.0f );\r\n\r\n\t// Default position.\r\n\tm_camera.set( 0.0f, 0.0f, 0.0f );\r\n\r\n\t// No frame.\r\n\tm_pFrame = NULL;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsCamera\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tDeletes a camera object.\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nNsCamera::~NsCamera()\r\n{\r\n//\tif ( m_pFrame ) delete m_pFrame;\r\n}\r\n\r\nvoid NsCamera::pos ( float x, float y, float z )\r\n{\r\n\tm_camera.set( x, y, z );\r\n}\r\n\r\nvoid NsCamera::up ( float x, float y, float z )\r\n{\r\n\tm_up.set( x, y, z );\r\n}\r\n\r\nvoid NsCamera::lookAt ( float x, float y, float z )\r\n{\r\n\tNsVector lookat;\r\n\r\n\tlookat.set( x, y, z );\r\n\r\n\tm_matrix.lookAt( &m_camera, &m_up, &lookat );\r\n}\r\n\r\nfloat line_x0 = 0.0f;\r\nfloat line_y0 = 100.0f;\r\nfloat line_z0 = 0.0f;\r\nfloat line_x1 = 0.0f;\r\nfloat line_y1 = 0.0f;\r\nfloat line_z1 = 0.0f;\r\n\r\nfloat gPosX = 320;\r\nfloat gPosY = 240;\r\nfloat gPosZ = 0;\r\n\r\nfloat gUpX = 0;\r\nfloat gUpY = 1;\r\nfloat gUpZ = 0;\r\n\r\nfloat gAtX = 320;\r\nfloat gAtY = 240;\r\nfloat gAtZ = 1;\r\n\r\nvoid NsCamera::_setCurrent ( NsMatrix * object )\r\n{\r\n\tNsMatrix m;\r\n\tNsMatrix m2;\r\n\r\n\tmovement.set( 0.0f, 0.0f, 0.0f );\r\n\r\n\t// Test pad for rotation.\t\t\r\n//\tif ( pPad->button & PAD_BUTTON_X ) {\r\n//\t\t// Move line.\r\n//\t\tif ( ( pPad->stickY > 8 ) || ( pPad->stickY < -8 ) ) {\r\n//\t\t\tline_z0 -= ((float)pPad->stickY)/256.0f;\r\n//\t\t\tline_z1 -= ((float)pPad->stickY)/256.0f;\r\n//\t\t}\r\n//\t\tif ( ( pPad->stickX > 8 ) || ( pPad->stickX < -8 ) ) {\r\n//\t\t\tline_x0 += ((float)pPad->stickX)/256.0f;\r\n//\t\t\tline_x1 += ((float)pPad->stickX)/256.0f;\r\n//\t\t}\r\n//\t\tif ( pPad->button & PAD_BUTTON_Y ) {\r\n//\t\t\tline_y0 -= 0.25f;\r\n//\t\t\tline_y1 -= 0.25f;\r\n//\t\t}\r\n//\t\tif ( pPad->button & PAD_BUTTON_B ) {\r\n//\t\t\tline_y0 += 0.25f;\r\n//\t\t\tline_y1 += 0.25f;\r\n//\t\t}\r\n//\t} else {\r\n//\t\t// Rotation.\r\n//\t\tif ( ( pPad->stickY > 8 ) || ( pPad->stickY < -8 ) ) {\r\n//\t\t\trotation.x = rotation.x - ((float)pPad->stickY)/512.0f;\r\n//\t\t}\r\n//\t\tif ( ( pPad->stickX > 8 ) || ( pPad->stickX < -8 ) ) {\r\n//\t\t    rotation.y = rotation.y + ((float)pPad->stickX)/512.0f;\r\n//\t\t}\r\n//\t}\r\n//\t// Test pad for movement.\r\n//\tif ( ( pPad->substickY > 8 ) || ( pPad->substickY < -8 ) ) {\r\n//\t\tmovement.z = -((float)pPad->substickY)/64.0f;\r\n//\t}\r\n//\tif ( ( pPad->substickX > 8 ) || ( pPad->substickX < -8 ) ) {\r\n//\t    movement.x = -((float)-pPad->substickX)/64.0f;\r\n//\t}\r\n//\tif ( pPad->button & PAD_BUTTON_Y ) movement.y -= 0.5f;\r\n//\tif ( pPad->button & PAD_BUTTON_B ) movement.y += 0.5f;\r\n\r\n\t// Generate rotation matrix.\r\n\ttemp0.rotateX( rotation.x, NsMatrix_Combine_Replace );\r\n\ttemp1.rotateY( rotation.y, NsMatrix_Combine_Replace );\r\n    skyMat.cat( temp0, temp1 );\r\n\r\n    // Generate movement vector by multiplying the desired movement vector\r\n    // by the inverse of the view matrix.\r\n\ttemp1.invert( skyMat );\r\n\ttemp1.multiply( &movement, &movement );\r\n\tposition.add( movement );\r\n\r\n    // Generate the translation matrix, and concatonate the rotation matrix.\r\n\tsceneMat.translate( &position, NsMatrix_Combine_Replace );\r\n\tsceneMat.cat( skyMat, sceneMat );\r\n\r\n//\tm.identity();\r\n//\tm2.identity();\r\n\tm.copy( *object );\r\n\tm2.copy( *object );\r\n\r\n\tm.setRight( 1.0f, 0.0f, 0.0f );\r\n\tm.setUp( 0.0f, 1.0f, 0.0f );\r\n\tm.setAt( 0.0f, 0.0f, 1.0f );\r\n\tm.setPos( -m.getPosX(), -m.getPosY(), -m.getPosZ() );\r\n\tm2.setPos( 0.0f, 0.0f, 0.0f );\r\n\r\n\tm.cat( m2, m );\r\n\tm.cat( sceneMat, m );\r\n\r\n\tif ( m_type == GX_ORTHOGRAPHIC ) {\r\n\t\tm2.copy( m_matrix );\r\n\t\tNsVector vs( m_clip_w / viewx, m_clip_h / viewy, 1.0f );\r\n\t\tm2.scale( &vs, NsMatrix_Combine_Post );\r\n\t\tm_current.cat( m2, m );\r\n\t\r\n\t\tGX::SetScissorBoxOffset ( ( 320 - ( m_clip_w / 2 ) ) - m_clip_x, ( 224 - ( m_clip_h / 2 ) ) - m_clip_y );\r\n\t\tGX::SetScissor (320 - ( m_clip_w / 2 ), 224 - ( m_clip_h / 2 ), m_clip_w, m_clip_h );\r\n\t} else {\r\n\t\tm_current.cat( m_matrix, m );\r\n\t\tGX::SetScissorBoxOffset ( 0, 0 );\r\n\t}\r\n\r\n    GX::LoadPosMtxImm( m_current.m_matrix, GX_PNMTX0 );\r\n\r\n\t// This makes the perspective center be at the center of the viewport.\r\n\t//GXSetScissorBoxOffset ( ( 320 - ( m_clip_w / 2 ) ) - m_clip_x, ( 224 - ( m_clip_h / 2 ) ) - m_clip_y );\r\n\t//GXSetScissor (320 - ( m_clip_w / 2 ), 224 - ( m_clip_h / 2 ), m_clip_w, m_clip_h );\r\n//\tGXSetScissor (0, 0, m_clip_w, 480/*m_clip_h*/ );\r\n\r\n\t// Previously in viewport.\r\n    GX::SetProjection( m_viewmatrix, m_type );\r\n}\r\n\r\nvoid NsCamera::begin ( void )\r\n{\r\n\tif ( m_pFrame ) {\r\n\t\t_setCurrent ( m_pFrame->getModelMatrix() );\r\n\t} else {\r\n\t\tNsMatrix mId;\r\n\t\tmId.identity();\r\n\t\t_setCurrent ( &mId );\r\n\t}\r\n}\r\n\r\nvoid NsCamera::offset ( float x, float y, float z )\r\n{\r\n\tNsMatrix offset;\r\n\tNsVector v( x, y, z );\r\n\toffset.copy( m_current );\r\n\toffset.translate( &v, NsMatrix_Combine_Pre );\r\n\r\n    GX::LoadPosMtxImm( offset.m_matrix, GX_PNMTX0 );\r\n}\r\n\r\nvoid NsCamera::end ( void )\r\n{\r\n}\r\n\r\n// Previously in viewport.\r\nvoid NsCamera::perspective ( u32 x, u32 y, u32 width, u32 height )\r\n{\r\n    float left\t= -0.080F;\r\n    float top\t= 0.060F;\r\n    float znear\t= 2.0F;\r\n    float zfar\t= 40000.0F;\r\n    \r\n    MTXFrustum ( m_viewmatrix, top, -top, left, -left, znear, zfar );\r\n\r\n\tm_type = GX_PERSPECTIVE;\r\n\r\n\tclip ( x, y, width, height );\r\n\r\n\t// Default matrix - just like PS2 - aaaah.\r\n\tpos\t\t( 0, 0, 0 );\r\n\tup\t\t( 0, 1, 0 );\r\n\tlookAt\t( 0, 0, 1 );\r\n}\r\n\r\n// Previously in viewport.\r\nvoid NsCamera::perspective ( float width, float height, float znear, float zfar )\r\n{\r\n    MTXFrustum ( m_viewmatrix, height, -height, -width, width, znear, zfar );\r\n\r\n\tm_type = GX_PERSPECTIVE;\r\n\r\n\tclip ( 0, 0, 640, 448 );\r\n\r\n\t// Default matrix - just like PS2 - aaaah.\r\n\tpos\t\t( 0, 0, 0 );\r\n\tup\t\t( 0, 1, 0 );\r\n\tlookAt\t( 0, 0, 1 );\r\n}\r\n\r\nvoid NsCamera::perspective ( float fovy, float aspect )\r\n{\r\n    MTXPerspective ( m_viewmatrix, fovy, aspect, 2.0f, 40000.0f );\r\n\r\n\tm_type = GX_PERSPECTIVE;\r\n\r\n\t// Default matrix - just like PS2 - aaaah.\r\n\tpos\t\t( 0, 0, 0 );\r\n\tup\t\t( 0, 1, 0 );\r\n\tlookAt\t( 0, 0, 1 );\r\n}\r\n\r\nvoid NsCamera::orthographic ( u32 x, u32 y, u32 width, u32 height )\r\n{\r\n    float left\t= -320.0f;\r\n    float top\t= 224.0f;\t\t//40.0F;\r\n    float znear\t= 1.0F;\r\n    float zfar\t= 100000.0F;\r\n    \r\n    MTXOrtho ( m_viewmatrix, top, -top, left, -left, znear, zfar );\r\n\r\n\tm_type = GX_ORTHOGRAPHIC;\r\n\r\n\tclip ( x, y, width, height );\r\n\r\n\tm_matrix.setRight( 1.0f, 0.0f, 0.0f );\r\n\tm_matrix.setUp( 0.0f, -1.0f, 0.0f );\r\n\tm_matrix.setAt( 0.0f, 0.0f, 1.0f );\r\n\tm_matrix.setPosX( -320 );\r\n\tm_matrix.setPosY( 224 );\r\n\tm_matrix.setPosZ( 0 );\r\n\r\n\t// Default viewplane size.\r\n\tsetViewWindow( width, height );\r\n}\r\n\r\nvoid NsCamera::clip ( u32 x, u32 y, u32 width, u32 height )\r\n{\r\n\tm_clip_x = x;\r\n\tm_clip_y = y;\r\n\tm_clip_w = width;\r\n\tm_clip_h = height;\r\n}\r\n\r\nvoid NsCamera::setViewWindow( float x, float y )\r\n{\r\n\tviewx = x;\r\n\tviewy = y;\r\n\tview1x = 1.0f / x;\r\n\tview1y = 1.0f / y;\r\n}\r\n\r\n//\t// Generate rotation matrix.\r\n////\trotation.x = 32.0f;\r\n//\trotation.y += 0.5f;\r\n//    MTXRotDeg(temp0, 'x', rotation.x );\r\n//    MTXRotDeg(temp1, 'y', rotation.y );\r\n//    MTXConcat(temp0, temp1, skyMat);\r\n//\r\n//    // Generate movement vector by multiplying the desired movement vector\r\n//    // by the inverse of the view matrix.\r\n//    MTXInverse ( skyMat, temp1 );\r\n//    MTXMultVec(temp1, &movement, &movement );\r\n//    position.x += movement.x;\r\n//    position.y += movement.y;\r\n//    position.z += movement.z;\r\n//\r\n//    // Generate the translation matrix, and concatonate the rotation matrix.\r\n//\tMTXTrans (sceneMat, position.x, position.y, position.z );\r\n//    MTXConcat(skyMat, sceneMat, sceneMat);\r\n\r\nNsMatrix * NsCamera::getViewMatrix ( void )\r\n{\r\n    float\t\t\tscale;\r\n    NsVector\t\tvVector;\r\n    NsVector\t\ttemp;\r\n    NsVector\t\tcpos;\r\n    NsMatrix\t  *\tcameraLTM;\r\n\r\n    cameraLTM = getFrame()->getModelMatrix();\r\n\tcpos.set( cameraLTM->getPosX(), cameraLTM->getPosY(), cameraLTM->getPosZ() );\r\n\r\n    /*INDENT OFF */\r\n\r\n    /*\r\n     * Builds the concatenation of the following matrices:\r\n     *\r\n     *  [ [ -Right_X,    Up_X,      At_X,    0 ]       re-orient\r\n     *    [ -Right_Y,    Up_Y,      At_Y,    0 ]\r\n     *    [ -Right_Z,    Up_Z,      At_Z,    0 ]\r\n     *    [ pos Right, -(pos Up), -(pos At), 1 ] ]\r\n     *  [ [   1,      0,    0, 0 ]                     offset eye\r\n     *    [   0,      1,    0, 0 ]\r\n     *    [ off_x,  off_y,  1, 0 ]\r\n     *    [ -off_x, -off_y, 0, 1 ] ]\r\n     *  [ [ 0.5 / width,      0,       0, 0 ]          scale for view window\r\n     *    [      0,      0.5 / height, 0, 0 ]\r\n     *    [      0,           0,       1, 0 ]\r\n     *    [      0,           0,       0, 1 ] ]\r\n     *  [ [ 1, 0,  0, 0 ]                              project & flip y\r\n     *    [ 0, -1, 0, 0 ]\r\n     *    [ 0, 0,  1, 1 ]                              DIFFERS FROM PARALLEL\r\n     *    [ 0, 0,  0, 0 ] ]\r\n     *  [ [  1,   0,  0, 0 ]                           xform XY\r\n     *    [  0,   1,  0, 0 ]                           from [-0.5..0.5]^2\r\n     *    [  0,   0,  1, 0 ]                           to   [0..1]^2\r\n     *    [ 0.5, 0.5, 0, 1 ] ]\r\n     */\r\n\r\n    /*INDENT ON */\r\n\r\n    /* At */\r\n    scale = (view1x * ((float) ((-0.5))));\r\n\tvVector.scale( *cameraLTM->getRight(), scale );\r\n\r\n    scale = ( 0.5f - (scale * 0.0f) );\r\n\ttemp.scale( *cameraLTM->getAt(), scale );\r\n\tvVector.add( temp );\r\n\r\n\tm_view.setRight( &vVector );\r\n\r\n    m_view.setRightX( vVector.x );\r\n    m_view.setUpX( vVector.y );\r\n    m_view.setAtX( vVector.z );\r\n    m_view.setPosX ( 0.5f - ( scale + cpos.dot( vVector ) ) );\r\n\r\n    /* Up */\r\n    scale = ( view1y * -0.5f );\r\n\tvVector.scale( *cameraLTM->getUp(), scale );\r\n\r\n    scale = ( 0.5f + (scale * 0.0f) );\r\n\ttemp.scale( *cameraLTM->getAt(), scale );\r\n\tvVector.add( temp );\r\n\r\n    m_view.setRightY( vVector.x );\r\n    m_view.setUpY( vVector.y );\r\n    m_view.setAtY( vVector.z );\r\n    m_view.setPosY ( 0.5f - ( scale + cpos.dot( vVector ) ) );\r\n\r\n    /* At */\r\n    m_view.setRightZ(cameraLTM->getAt()->x );\r\n    m_view.setUpZ( cameraLTM->getAt()->y );\r\n    m_view.setAtZ( cameraLTM->getAt()->z );\r\n    m_view.setPosZ ( -cpos.dot( *cameraLTM->getAt() ) );\r\n\r\n\treturn &m_view;\r\n}"
  },
  {
    "path": "Code/Sys/ngc/p_camera.h",
    "content": "#ifndef _CAMERA_H_\r\n#define _CAMERA_H_\r\n\r\n#include <dolphin.h>\r\n#include \"p_frame.h\"\r\n\r\nclass NsCamera\r\n{\r\n\tfriend class NsMatrix;\r\n\r\n\tNsMatrix\t\t\tm_matrix;\r\n    NsVector\t\t\tm_up;\r\n    NsVector\t\t\tm_camera;\r\n\tNsMatrix\t\t\tm_current;\r\n\r\n\tNsMatrix\t\t\tm_view;\r\n\r\n\tNsFrame\t\t\t  * m_pFrame;\r\n\r\n\tfloat\t\t\t\tviewx, viewy;\r\n\tfloat\t\t\t\tview1x, view1y;\r\n\r\n\t// Previously in viewport.\r\n\tGXProjectionType\tm_type;\r\n\tMtx44\t\t\t\tm_viewmatrix;\r\n\tu32\t\t\t\t\tm_clip_x, m_clip_y;\r\n\tu32\t\t\t\t\tm_clip_w, m_clip_h;\r\n\r\n\tvoid\t\t_setCurrent ( NsMatrix * object );\r\npublic:\r\n\t\t\t\tNsCamera\t\t();\r\n\t\t\t\t~NsCamera\t\t();\r\n\r\n\tvoid\t\tpos\t\t\t\t( float x, float y, float z );\r\n\tvoid\t\tup\t\t\t\t( float x, float y, float z );\r\n\tvoid\t\tlookAt\t\t\t( float x, float y, float z );\r\n\tvoid\t\tbegin\t\t\t( void );\r\n\tvoid\t\tend\t\t\t\t( void );\r\n\r\n\tvoid\t\toffset\t\t\t( float x, float y, float z );\r\n\r\n\tNsMatrix  * getCurrent\t\t( void ) { return &m_current; };\r\n\tNsMatrix  * getViewMatrix\t( void );\r\n\r\n\tNsFrame\t  * getFrame\t\t( void ) { return m_pFrame; };\r\n\tvoid\t\tsetFrame\t\t( NsFrame * p ) { m_pFrame = p; };\r\n\r\n\t// Previously in viewport.\r\n\tvoid\t\tperspective\t\t( void ) { m_type = GX_PERSPECTIVE; };\r\n\tvoid\t\tperspective\t\t( u32 x, u32 y, u32 width, u32 height );\r\n\tvoid\t\tperspective\t\t( float width, float height, float znear, float zfar );\r\n\tvoid\t\tperspective\t\t( float fovy, float aspect );\r\n\tvoid\t\torthographic\t( void ) { m_type = GX_ORTHOGRAPHIC; };\r\n\tvoid\t\torthographic\t( u32 x, u32 y, u32 width, u32 height );\r\n\r\n\tvoid\t\tsetViewWindow\t( float x, float y );\r\n\r\n\tvoid\t\tclip\t\t\t( u32 x, u32 y, u32 width, u32 height );\r\n\r\n\tfloat\t\tGetViewMatrix\t( int x, int y ) { return m_viewmatrix[x][y]; }\r\n\tvoid\t\tSetViewMatrix\t( int x, int y, float v ) { m_viewmatrix[x][y] = v; }\r\n};\r\n\r\n#endif\t\t// _CAMERA_H_\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_clump.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsClump\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tHolds Clump data & draws it.\t\t\t\t\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include <math.h>\r\n//#include <string.h>\r\n//#include \"p_clump.h\"\r\n//#include \"p_file.h\"\r\n//#include \"p_prim.h\"\r\n//#include <sk/engine/bsputils.h>\r\n//#include \"p_display.h\"\r\n//#include \"p_assert.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#define rpWORLDUVS ( rpWORLDTEXTURED2 | rpWORLDTEXTURED )\r\n//\r\n//#define rpSKINPOPPARENTMATRIX\t 0x01\r\n//#define rpSKINPUSHPARENTMATRIX\t 0x02\r\n//\r\n//enum\r\n//{\r\n//\tmTWO_SIDED\t\t\t= 0x01,\r\n//\tmINVISIBLE\t\t\t= 0x02,\r\n//\tmFRONT_FACING\t\t= 0x04,\r\n//\tmTRANSPARENT\t\t= 0x08,\r\n//\tmDECAL\t\t\t\t= 0x10,\r\n//\tmUV_WIBBLE_SUPPORT\t= 0x20,\t// If these two values change, notify Steve as Rw references \r\n//\tmVC_WIBBLE_SUPPORT\t= 0x40, // these two flags by value.\r\n//};\r\n//\r\n//enum RpWorldFlag\r\n//{\r\n//    rpWORLDTRISTRIP = 0x01,     /**<This world's meshes can be rendered\r\n//                                   as tri strips */\r\n//    rpWORLDTEXTURED = 0x04,     /**<This world has one set of texture coordinates */\r\n//    rpWORLDPRELIT = 0x08,       /**<This world has luminance values */\r\n//    rpWORLDNORMALS = 0x10,      /**<This world has normals */\r\n//    rpWORLDLIGHT = 0x20,        /**<This world will be lit */\r\n//    rpWORLDMODULATEMATERIALCOLOR = 0x40, /**<Modulate material color with\r\n//                                            vertex colors (pre-lit + lit) */\r\n//    rpWORLDTEXTURED2 = 0x80, /**<This world has 2 set of texture coordinates */\r\n//\r\n//    /*\r\n//     * These flags are stored in the flags field in an RwObject, the flag field is 8bit.\r\n//     */\r\n//\r\n//    rpWORLDSECTORSOVERLAP = 0x40000000,\r\n//};\r\n//typedef enum RpWorldFlag RpWorldFlag;\r\n//\r\n//enum\r\n//{\r\n//\tMAX_NUM_SEQUENCES\t= 8\r\n//};\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsClump\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tDeclares a clump object.\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n//NsClump::NsClump()\r\n//{\r\n//\tm_pAtomicHead = NULL;\r\n//\tm_numAtomic\t= 0;\r\n//\r\n//\tfor( int i = 0; i < NUM_BLEND_ANIMS; ++i )\r\n//\t{\r\n//\t\tm_pAnim[i]\t\t\t= NULL;\r\n//\t\tm_AnimWeights[i]\t= ( i == 0 ) ? 1.0f : 0.0f;\r\n//\t}\r\n//\r\n//\tm_AnimFlipped = false;\r\n//\tm_pFrameList = NULL;\r\n//\tm_pBoneMat = NULL;\r\n//\tm_pBoneData = NULL;\r\n//\r\n//\tm_pWorld = NULL;\r\n//\tm_pUserData = NULL;\r\n//\tm_pTexMan\t= NULL;\r\n//}\r\n//\r\n//NsClump::NsClump( NsModel * pModelData )\r\n//{\r\n//\tm_pAtomicHead = NULL;\r\n//\tm_numAtomic\t= 0;\r\n//\r\n//\tfor( int i = 0; i < NUM_BLEND_ANIMS; ++i )\r\n//\t{\r\n//\t\tm_pAnim[i]\t\t= NULL;\r\n//\t\tm_AnimWeights[i]\t= ( i == 0 ) ? 1.0f : 0.0f;\r\n//\t}\r\n//\r\n//\tm_AnimFlipped = false;\r\n//\tm_pFrameList = NULL;\r\n//\tm_pBoneMat = NULL;\r\n//\tm_pBoneData = NULL;\r\n//\r\n//\tm_pWorld = NULL;\r\n//\tm_pUserData = NULL;\r\n//\tm_pTexMan\t= NULL;\r\n//\r\n//\tsetModel( pModelData );\r\n//}\r\n//\r\n//NsClump::NsClump( unsigned int * pDFF )\r\n//{\r\n//\tm_pAtomicHead = NULL;\r\n//\tm_numAtomic\t= 0;\r\n//\r\n//\tfor( int i = 0; i < NUM_BLEND_ANIMS; ++i )\r\n//\t{\r\n//\t\tm_pAnim[i]\t\t= NULL;\r\n//\t\tm_AnimWeights[i]\t= ( i == 0 ) ? 1.0f : 0.0f;\r\n//\t}\r\n//\r\n//\tm_AnimFlipped = false;\r\n//\tm_pFrameList = NULL;\r\n//\tm_pBoneMat = NULL;\r\n//\tm_pBoneData = NULL;\r\n//\r\n//\tm_pWorld = NULL;\r\n//\tm_pUserData = NULL;\r\n//\tm_pTexMan\t= NULL;\r\n//\r\n//\tsetAtomics( pDFF );\r\n//}\r\n//\r\n//NsClump::~NsClump()\r\n//{\r\n////\tOSReport( \"Deleting clump:\\n\" );\r\n//\r\n//\tNsDisplay::flush();\r\n//\t\r\n//\tNsAtomic * pAtomic = m_pAtomicHead;\r\n//\twhile ( pAtomic ) {\r\n//\t\tNsAtomic * pDelete = pAtomic;\r\n//\t\tpAtomic = pAtomic->m_pNext;\r\n////\t\tOSReport( \"...pAtomic 0x%08x\\n\", pDelete );\r\n//\t\tdelete pDelete;\r\n//\t}\r\n////\tOSReport( \"m_pFrame 0x%08x\\n\", m_pFrame );\r\n////\tOSReport( \"m_pBoneMat 0x%08x\\n\", m_pBoneMat );\r\n////\tOSReport( \"m_pBoneData 0x%08x\\n\", m_pBoneData );\r\n//\tif ( m_pFrameList ) delete m_pFrameList;\r\n//\tif ( m_pBoneMat ) delete m_pBoneMat;\r\n//\r\n//\tfor ( int lp = 0; lp < NUM_BLEND_ANIMS; lp++ ) {\r\n////\t\tOSReport( \"m_pAnim[%d] 0x%08x\\n\", lp, m_pAnim[lp] );\r\n//\t\tif ( m_pAnim[lp] ) delete m_pAnim[lp];\r\n//\t}\r\n//\r\n//\t// Multi-reference stuff.\r\n//\tif ( m_pBoneData ) {\r\n//\t\tif ( m_pBoneData->totalReferences() == 0 ) {\r\n//\t\t\tdelete m_pBoneData;\r\n//\t\t} else {\r\n//\t\t\tm_pBoneData->removeReference();\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n//NsClump& NsClump::clone ( void )\r\n//{\r\n//\tint\t\t\t\t\tlp;\r\n//\tNsClump\t\t\t  * pClonedClump;\r\n//\tNsAnim\t\t\t  * pClonedAnim;\r\n//\tNsAtomic\t\t  * pClonedAtomic;\r\n//\tNsAtomic\t\t  * pAtomic;\r\n//\r\n//\t// Create a new clump.\r\n//\tpClonedClump = new NsClump;\r\n//\tmemcpy( pClonedClump, this, sizeof( NsClump ) );\r\n//\tpClonedClump->m_pAtomicHead = NULL;\r\n//\tpClonedClump->m_numAtomic = 0;\r\n//\t// Create new anim structure.\r\n//\tfor( int i = 0; i < NUM_BLEND_ANIMS; ++i )\r\n//\t{\r\n//\t\tif ( m_pAnim[i] ) {\r\n//\t\t\tpClonedAnim = &m_pAnim[i]->clone();\r\n//\r\n////\t\t\tmemcpy( pClonedAnim, m_pAnim, sizeof( NsAnim ) );\r\n//\t\t\tpClonedClump->m_pAnim[i] = pClonedAnim;\r\n//\t\t}\r\n//\t}\r\n//\t// Copy the bone data.\r\n////\tif ( m_pBoneData ) {\r\n////\t\tpClonedClump->m_pBoneData = new NsAnim_BoneData[m_numBones];\r\n////\t\tmemcpy ( pClonedClump->m_pBoneData, m_pBoneData, sizeof ( NsAnim_BoneData ) * m_numBones );\r\n////\t}\r\n//\r\n////\tif ( m_pFrame ) {\r\n////\t\tpClonedClump->m_pFrame = new NsFrame;\r\n////\t\tmemcpy ( pClonedClump->m_pFrame, m_pFrame, sizeof ( NsFrame ) );\r\n////\t}\r\n//\r\n//\tpAtomic = m_pAtomicHead;\r\n//\t// Copy the atomics over.\r\n//\tfor ( lp = 0; lp < m_numAtomic; lp++ ) {\r\n//\t\t// Create a cloned atomic.\r\n//\t\tpClonedAtomic = &pAtomic->clone();\r\n//\r\n//\t\t// Add it to the cloned clump.\r\n//\t\tpClonedClump->addAtomic( pClonedAtomic );\r\n//\r\n////\t\t// If this is the head node, set up the frame for the clump.\r\n////\t\tif ( pAtomic->getFrame() == m_pFrame ) {\r\n////\t\t\tdelete pClonedAtomic->getFrame();\r\n////\t\t\tpClonedAtomic->setFrame( pClonedClump->m_pFrame );\r\n//////\t\t\tpClonedClump->m_pFrame = pClonedAtomic->getFrame();\r\n////\t\t}\r\n//\r\n//\t\t// Onto the next atomic.\r\n//\t\tpAtomic = pAtomic->m_pNext;\r\n//\t}\r\n////\tif ( m_numAtomic ) pClonedClump->m_pFrame = pClonedClump->m_pAtomicHead->getFrame();\r\n//\r\n//\r\n//\t// Copy the framelist.\r\n//\tpClonedClump->m_pFrameList = new NsFrame[m_numFrames];\r\n//\tmemcpy ( pClonedClump->m_pFrameList, m_pFrameList, sizeof ( NsFrame ) * m_numFrames );\r\n//\tpClonedClump->m_pFrame = &pClonedClump->m_pFrameList[0];\r\n//\r\n//\t// Copy the bone matrices if present.\r\n//\tif( m_pBoneMat )\r\n//\t{\r\n//\t\tpClonedClump->m_pBoneMat = new ROMtx[m_numBones];\r\n//\t\tmemcpy( pClonedClump->m_pBoneMat, m_pBoneMat, sizeof( ROMtx ) * m_numBones );\r\n//\t}\r\n//\r\n//\t// Search all atomics, and attach it the ones with this framenumber.\r\n//\tpAtomic = pClonedClump->m_pAtomicHead;\r\n//\twhile ( pAtomic ) {\r\n////\t\tdelete pAtomic->getFrame();\r\n//\t\tpAtomic->setFrame( &pClonedClump->m_pFrameList[pAtomic->m_frameNumber] );\r\n//\t\tpAtomic = pAtomic->m_pNext;\r\n//\t}\r\n//\r\n//\t// Multi-reference counts.\r\n//\tif ( m_pBoneData ) m_pBoneData->addReference();\r\n//\r\n//\treturn *pClonedClump;\r\n//}\r\n//\r\n//NsModel * NsClump::setModel ( NsModel * pModelData )\r\n//{\r\n//\tNsModel * m_pNextModel;\r\n//\r\n//\t// Create the atomic.\r\n//\tNsAtomic * pAtomic = new NsAtomic;\r\n//\tm_pNextModel = pAtomic->setModel( pModelData, m_pTexMan );\r\n//\taddAtomic( pAtomic );\r\n//\r\n//\t// Set the frame.\r\n//\tm_pFrame = new NsFrame;\r\n//\tm_pAtomicHead->setFrame( m_pFrame );\r\n//\r\n//\t// Dummy up the framelist.\r\n//\tm_numFrames = 1;\r\n//\tm_pFrameList = m_pFrame;\r\n//\r\n//\treturn m_pNextModel;\r\n//}\r\n//\r\n//void NsClump::setAtomics ( unsigned int * pDFF )\r\n//{\r\n//\tNsFrame\t\t  * pFrameList = (NsFrame *)&pDFF[8];\r\n//\tNsModel\t\t  * pModelData = (NsModel *)&pFrameList[pDFF[2]];\r\n//\tNsModel\t\t  * m_pNextModel;\r\n//\tunsigned int\tlp;\r\n//\tNsAtomic\t  * pAtomic;\r\n//\r\n//\t// Note, these are added in reverse ( I believe Renderware does it like\r\n//\t// that, as adding them forwards is bogus).\r\n//\tm_pFrame = NULL;\r\n//\tfor ( lp = 0; lp < pDFF[0]; lp++ ) {\r\n//\t\tpAtomic = new NsAtomic;\r\n//\t\tm_pNextModel = pAtomic->setModel( pModelData, m_pTexMan );\r\n//\t\tOSReport ( \"Atomic %d: %d\\n\", lp, pModelData->m_frameNumber );\r\n//\t\taddAtomic( pAtomic );\r\n////\t\tpAtomic->m_pNext = m_pAtomicHead;\r\n////\t\tm_pAtomicHead = pAtomic;\r\n////\t\tm_numAtomic++;\r\n//\t\tpModelData = m_pNextModel;\r\n//\t}\r\n//\r\n//\t// Turn the framelist into actual frames and attach to the atomics.\r\n//\tm_numFrames = pDFF[2];\r\n//\tm_pFrameList = new NsFrame[m_numFrames];\r\n//\tmemcpy ( m_pFrameList, pFrameList, sizeof ( NsFrame ) * m_numFrames );\r\n//\tm_pFrame = &m_pFrameList[0];\r\n//\r\n//\t// Search all atomics, and attach it the ones with this framenumber.\r\n//\tpAtomic = m_pAtomicHead;\r\n//\twhile ( pAtomic ) {\r\n//\t\tpAtomic->setFrame( &m_pFrameList[pAtomic->m_frameNumber] );\r\n//\t\tpAtomic = pAtomic->m_pNext;\r\n//\t}\r\n//\r\n//\t// If this clump has an animation hierarchy, set it up.\r\n//\tif ( pDFF[1] ) {\r\n//\r\n//\t\tunsigned char\t  * p8;\r\n//\t\tNsAnim_BoneHeader * pBoneHeader;\r\n//\t\tNsAnim_SkinHeader * pSkinHeader;\r\n//\t\tNsAnim_BoneData\t  * pTempBone;\r\n//\r\n////\t\tNsWeightPair\t  * pWeight;\r\n////\t\tfloat\t\t\t  *\tpSingleWeight;\r\n////\t\tunsigned short\t  * pIndices;\r\n////\r\n////\t\tNsPosNormPair\t  * pPosNormPair;\r\n////\t\tNsPosNormPair\t  *\tpTransformedVertices;\r\n////\t\tNsPosNormPair\t  * pCurrentVertexPool;\r\n////\t\tunsigned int\t  * pCount;\r\n////\r\n////\t\tunsigned int\t  * pIndex;\r\n////\r\n////\t\tunsigned char\t  * p8;\r\n////\r\n////\t\tunsigned int\t  * vertexcount;\r\n//\r\n//\t\t// Skip the actual DFF data & point to the animation data.\r\n//\t\tp8 = (unsigned char *)pDFF;\r\n//\t\tpBoneHeader = (NsAnim_BoneHeader *)&p8[pDFF[1]];\r\n//\t\tpTempBone = (NsAnim_BoneData *)&pBoneHeader[1];\r\n//\t\tpSkinHeader = (NsAnim_SkinHeader *)&pTempBone[pBoneHeader->numBones];\r\n//\t\tm_numBones = pBoneHeader->numBones;\r\n//\r\n//\t\tfor( int i = 0; i < NUM_BLEND_ANIMS; ++i )\r\n//\t\t{\r\n//\t\t\tm_pAnim[i] = new NsAnim( m_numBones );\r\n//\t\t}\r\n//\r\n//\t\t// Copy the bone data.\r\n//\t\tm_pBoneData = new NsRefBoneData( new NsAnim_BoneData[pBoneHeader->numBones] );\r\n//\t\tmemcpy ( m_pBoneData->m_pBoneData, pTempBone, sizeof ( NsAnim_BoneData ) * pBoneHeader->numBones );\r\n//\r\n//\t\t// Create the bone display matrices.\r\n//\t\tm_pBoneMat = new ROMtx[pBoneHeader->numBones];\r\n//\r\n//\t\t// Attach animation data to all atomics.\r\n//\t\tpAtomic = m_pAtomicHead;\r\n//\t\twhile ( pAtomic ) {\r\n//\t\t\t// The atomic will attach the animation data, and return a pointer past it.\r\n//\t\t\tpSkinHeader = pAtomic->attachSkinData( pSkinHeader );\r\n//\r\n//\t\t\t// Next atomic.\r\n//\t\t\tpAtomic = pAtomic->m_pNext;\r\n//\t\t}\r\n////\t\tfor ( lp = 0; lp < pDFF[0]; lp++ ) {\r\n////\t\t\t\r\n////\r\n////\r\n////\t\t\tpCount = (unsigned int *)&pSkinHeader[1];\r\n////\r\n////\t\t\t// Scan to end of blended weights.\r\n////\t\t\tvertexcount = 0;\r\n////\t\t\twhile ( pCount[0] ) {\r\n////\t\t\t\tpPosNormPair = (PosNormPair *)&pCount[2];\r\n////\t\t\t\tpWeight = (WeightPair *)&pPosNormPair[pCount[0]];\r\n////\t\t\t\tvertexcount += pCount[0];\r\n////\t\t\t\tpCount = (unsigned int *)&pWeight[pCount[0]];\r\n////\t\t\t}\r\n////\t\t\tpCount++;\r\n////\r\n////\t\t\t// Now, we know how many vertices for this atomic, and how many\r\n////\t\t\t// pairs - attach them.\r\n////\r\n////\t\t\t// Onto animation data for next atomic.\r\n////\t\t\tpTransformedVertices = pPool;\r\n////\t\t}\r\n//\t}\r\n//}\r\n//\r\n//void NsClump::merge( NsClump& source )\r\n//{\r\n//\tNsAtomic * pAtomic = source.m_pAtomicHead;\r\n//\r\n//\t// Merge in the materials.\r\n//\tm_pTexMan->merge( *source.m_pTexMan );\r\n//\r\n//\t// Add all atomics from the source.\r\n//\twhile ( pAtomic ) {\r\n//\t\t// Point to the clump's frame.\r\n//\t\tpAtomic->m_pFrame = m_pFrame;\r\n//\t\t// Delete the  flippairs\r\n//\t\tif ( pAtomic->m_pFlipPairs ) {\r\n//\t\t\tif ( pAtomic->m_pFlipPairs->totalReferences() == 0 ) {\r\n//\t\t\t\tdelete pAtomic->m_pFlipPairs;\r\n//\t\t\t\tpAtomic->m_pFlipPairs = NULL;\r\n//\t\t\t\tpAtomic->m_numFlipPairs = 0;\r\n//\t\t\t} else {\r\n//\t\t\t\tpAtomic->m_pFlipPairs->removeReference();\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\t// Add this atomic to the clump.\r\n//\t\taddAtomic( pAtomic );\r\n//\t\t// Onto the next one, deleting as we go.\r\n//\t\tpAtomic = pAtomic->m_pNext;\r\n//\t}\r\n//\tsource.m_pAtomicHead = NULL;\r\n//\tsource.m_numAtomic = 0;\r\n//}\r\n//\r\n//\r\n//\r\n//void NsClump::buildBoneMatrices( NsQFrame* p_q_frames, NsTFrame* p_t_frames )\r\n//{\r\n//    NsMatrix\t\tbts;\r\n//\tunsigned int\tlp;\r\n//\tint\t\t\t\tcurrentMatrix;\r\n//    NsMatrix\t\tparentMatrix;\r\n//    NsMatrix\t\tmatrixStack[32];\r\n//    NsMatrix  *\t\tpMatrixStackTop = matrixStack;\r\n//\tNsMatrix\t\tboneMatrix;\r\n//\tNsMatrix\t\ttempMatrix;\r\n//\r\n//\t// Point up what we need.\r\n//\tcurrentMatrix = -1;\r\n//\r\n//\t// This is the root.\r\n//    parentMatrix.identity();\r\n//\r\n//\tfor ( lp = 0; lp < m_numBones; lp++ ) {\r\n//\t\t// Build bone to skin (bts) matrix.\r\n//\t\tbts.setRight( m_pBoneData->m_pBoneData[lp].rightx, m_pBoneData->m_pBoneData[lp].upx, m_pBoneData->m_pBoneData[lp].atx );\r\n//\t\tbts.setUp( m_pBoneData->m_pBoneData[lp].righty, m_pBoneData->m_pBoneData[lp].upy, m_pBoneData->m_pBoneData[lp].aty );\r\n//\t\tbts.setAt( m_pBoneData->m_pBoneData[lp].rightz, m_pBoneData->m_pBoneData[lp].upz, m_pBoneData->m_pBoneData[lp].atz );\r\n//\t\tbts.setPos( m_pBoneData->m_pBoneData[lp].posx, m_pBoneData->m_pBoneData[lp].posy, m_pBoneData->m_pBoneData[lp].posz );\r\n//\r\n//\t\t// Push parent if required.\r\n//\t\tif ( m_pBoneData->m_pBoneData[lp].flags & rpSKINPUSHPARENTMATRIX ) {\r\n//\t\t\tmemcpy ( pMatrixStackTop, &parentMatrix, sizeof ( NsMatrix ) );\r\n//\t\t\tpMatrixStackTop++;\r\n//\t\t}\r\n//\r\n//\t\tboneMatrix.fromQuat( &p_q_frames[lp].q );\r\n//\t\tboneMatrix.setPos( p_t_frames[lp].v.x, p_t_frames[lp].v.y, p_t_frames[lp].v.z );\r\n//\r\n//\t\t// Multiply this matrix by the parent.\r\n//\t\ttempMatrix.cat( parentMatrix, boneMatrix );\r\n//\r\n//\t\t// Multiply this matrix by the parent.\r\n//\t\tbts.cat( tempMatrix, bts );\r\n//\r\n//\t\t// Convert this matrix to the format required for fast transformation.\r\n////\t\tPSMTXReorder ( bts, pBoneMat[lp] );\r\n//\r\n//\t\tm_pBoneMat[lp][0][0] = bts.getRightX();\r\n//\t\tm_pBoneMat[lp][0][1] = bts.getUpX();\r\n//\t\tm_pBoneMat[lp][0][2] = bts.getAtX();\r\n//\t\tm_pBoneMat[lp][1][0] = bts.getRightY();\r\n//\t\tm_pBoneMat[lp][1][1] = bts.getUpY();\r\n//\t\tm_pBoneMat[lp][1][2] = bts.getAtY();\r\n//\t\tm_pBoneMat[lp][2][0] = bts.getRightZ();\r\n//\t\tm_pBoneMat[lp][2][1] = bts.getUpZ();\r\n//\t\tm_pBoneMat[lp][2][2] = bts.getAtZ();\r\n//\t\tm_pBoneMat[lp][3][0] = bts.getPosX();\r\n//\t\tm_pBoneMat[lp][3][1] = bts.getPosY();\r\n//\t\tm_pBoneMat[lp][3][2] = bts.getPosZ();\r\n//\r\n//\t\t// Update parent (pop if required).\r\n//\t\tif ( m_pBoneData->m_pBoneData[lp].flags & rpSKINPOPPARENTMATRIX) {\r\n//\t\t\tpMatrixStackTop--;\r\n//\t\t\tmemcpy ( &parentMatrix, pMatrixStackTop, sizeof ( NsMatrix ) );\r\n//        } else {\r\n//\t\t\tmemcpy ( &parentMatrix, &tempMatrix, sizeof ( NsMatrix ) );\r\n//        }\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//void NsClump::flipBoneMatrices( void )\r\n//{\r\n//\tNsAtomic * pAtomic = m_pAtomicHead;\r\n//\twhile ( pAtomic ) {\r\n//\t\tif ( pAtomic->m_numFlipPairs > 0 ) {\r\n//\t\t\t// Flips the ROMtx matrices (pre built fast-trasnformation format matrices).\r\n//\t\t\t// To flip the hierarchy, simply negate the x axis components of the 'at' and 'up' vectors, Then rebuild\r\n//\t\t\t// the right vector. (Negating the x component of the right vector will lead to matrix inversion, which will flip textures etc.)\r\n//\t\t\tfor( unsigned int i = 0;; i += 2 )\r\n//\t\t\t{\r\n//\t\t\t\tassertp(( i + 1 ) < ( pAtomic->m_numFlipPairs * 2 ));\r\n//\t\t\t\tint matrix0 = pAtomic->m_pFlipPairs->m_pFlipPairs[i];\r\n//\t\t\t\tif( matrix0 == -1 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// Not interested.\r\n//\t\t\t\t\tcontinue;\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tint matrix1 = pAtomic->m_pFlipPairs->m_pFlipPairs[i + 1];\r\n//\r\n//\t\t\t\tif(( matrix0 == 0 ) && ( matrix1 == 0 ))\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// Terminator.\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tNsVector right, up, at, pos;\r\n//\r\n//\t\t\t\tif( matrix1 == -1 )\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// Just a simple rotate.\r\n//\t\t\t\t\tROMtx* p_matrix0\t= m_pBoneMat + matrix0;\r\n//\r\n//\t\t\t\t\t// Generate the right vector from up and at.\r\n//\t\t\t\t\tup.set( -p_matrix0[0][0][1], p_matrix0[0][1][1], p_matrix0[0][2][1] );\r\n//\t\t\t\t\tat.set( -p_matrix0[0][0][2], p_matrix0[0][1][2], p_matrix0[0][2][2] );\r\n//\t\t\t\t\tright.cross( up, at );\r\n//\r\n//\t\t\t\t\tpos.set( -p_matrix0[0][3][0], p_matrix0[0][3][1], p_matrix0[0][3][2] );\r\n//\r\n//\t\t\t\t\tp_matrix0[0][0][0]\t= right.x;\r\n//\t\t\t\t\tp_matrix0[0][1][0]\t= right.y;\r\n//\t\t\t\t\tp_matrix0[0][2][0]\t= right.z;\r\n//\t\t\t\t\tp_matrix0[0][0][1]\t= up.x;\r\n//\t\t\t\t\tp_matrix0[0][0][2]\t= at.x;\r\n//\t\t\t\t\tp_matrix0[0][3][0]\t= pos.x;\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tROMtx* p_matrix0\t= m_pBoneMat + matrix0;\r\n//\t\t\t\t\tROMtx* p_matrix1\t= m_pBoneMat + matrix1;\r\n//\r\n//\t\t\t\t\t// Need to save matrix1 as it will now be written to.\r\n//\t\t\t\t\tROMtx m1;\r\n//\t\t\t\t\tmemcpy( &m1, p_matrix1, sizeof( ROMtx ));\r\n//\r\n//\t\t\t\t\t// Generate the right vector from up and at.\r\n//\t\t\t\t\tup.set( -p_matrix0[0][0][1], p_matrix0[0][1][1], p_matrix0[0][2][1] );\r\n//\t\t\t\t\tat.set( -p_matrix0[0][0][2], p_matrix0[0][1][2], p_matrix0[0][2][2] );\r\n//\t\t\t\t\tright.cross( up, at );\r\n//\t\t\t\t\tpos.set( -p_matrix0[0][3][0], p_matrix0[0][3][1], p_matrix0[0][3][2] );\r\n//\r\n//\t\t\t\t\tp_matrix1[0][0][0]\t= right.x;\r\n//\t\t\t\t\tp_matrix1[0][1][0]\t= right.y;\r\n//\t\t\t\t\tp_matrix1[0][2][0]\t= right.z;\r\n//\t\t\t\t\tp_matrix1[0][0][1]\t= up.x;\r\n//\t\t\t\t\tp_matrix1[0][1][1]\t= up.y;\r\n//\t\t\t\t\tp_matrix1[0][2][1]\t= up.z;\r\n//\t\t\t\t\tp_matrix1[0][0][2]\t= at.x;\r\n//\t\t\t\t\tp_matrix1[0][1][2]\t= at.y;\r\n//\t\t\t\t\tp_matrix1[0][2][2]\t= at.z;\r\n//\t\t\t\t\tp_matrix1[0][3][0]\t= pos.x;\r\n//\t\t\t\t\tp_matrix1[0][3][1]\t= pos.y;\r\n//\t\t\t\t\tp_matrix1[0][3][2]\t= pos.z;\r\n//\r\n//\t\t\t\t\t// Generate the right vector from up and at.\r\n//\t\t\t\t\tup.set( -m1[0][1], m1[1][1], m1[2][1] );\r\n//\t\t\t\t\tat.set( -m1[0][2], m1[1][2], m1[2][2] );\r\n//\t\t\t\t\tright.cross( up, at );\r\n//\t\t\t\t\tpos.set( -m1[3][0], m1[3][1], m1[3][2] );\r\n//\r\n//\t\t\t\t\tp_matrix0[0][0][0]\t= right.x;\r\n//\t\t\t\t\tp_matrix0[0][1][0]\t= right.y;\r\n//\t\t\t\t\tp_matrix0[0][2][0]\t= right.z;\r\n//\t\t\t\t\tp_matrix0[0][0][1]\t= up.x;\r\n//\t\t\t\t\tp_matrix0[0][1][1]\t= up.y;\r\n//\t\t\t\t\tp_matrix0[0][2][1]\t= up.z;\r\n//\t\t\t\t\tp_matrix0[0][0][2]\t= at.x;\r\n//\t\t\t\t\tp_matrix0[0][1][2]\t= at.y;\r\n//\t\t\t\t\tp_matrix0[0][2][2]\t= at.z;\r\n//\t\t\t\t\tp_matrix0[0][3][0]\t= pos.x;\r\n//\t\t\t\t\tp_matrix0[0][3][1]\t= pos.y;\r\n//\t\t\t\t\tp_matrix0[0][3][2]\t= pos.z;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\tpAtomic = pAtomic->m_pNext;\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n//void NsClump::processAnims( void )\r\n//{\r\n//\t// Check there are valid animations attached.\r\n//\tassertp( m_pAnim[0] );\r\n//\r\n//\t// Update the keyframes & buid the bone matrices if we're animated.\r\n//\tfor( int i = 0; i < NUM_BLEND_ANIMS; ++i )\r\n//\t{\r\n//\t\tif( m_pAnim[i] && ( m_AnimWeights[i] > 0.0f ))\r\n//\t\t{\r\n//\t\t\t// Select the correct start and end keys for each bone.\r\n//\t\t\tm_pAnim[i]->update();\r\n//\r\n//\t\t\t// Interpolate the intermediate key for time <t> for each bone.\t\t\t\r\n//\t\t\tm_pAnim[i]->buildKeys();\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t// We now have one or more animations with correct keys. If not currently blending, we can use the\r\n//\t// keys from the first animation, otherwise, we have to build a weighted set of keys considering\r\n//\t// all animations that are currently in the blend.\r\n//\tif( m_AnimWeights[0] == 1.0f )\r\n//\t{\r\n//\t\t// No blending required.\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\t// Scan through the sets of frames, interpolating between the 2 based on the blend values.\r\n//\t\tfloat sum = 0.0f;\r\n//\t\tfor( int i1 = ( NUM_BLEND_ANIMS - 1 ); i1 > 0; --i1 )\r\n//\t\t{\r\n//\t\t\tfloat blend1 = m_AnimWeights[i1];\r\n//\t\t\tif( blend1 > 0.0f )\r\n//\t\t\t{\r\n//\t\t\t\tblend1 += sum;\r\n//\r\n//\t\t\t\tint i0 = i1 - 1;\r\n//\t\t\t\twhile(( m_AnimWeights[i0] <= 0.0f ) && ( i0 > 0 ))\r\n//\t\t\t\t{\r\n//\t\t\t\t\t--i0;\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tfloat blend0 = m_AnimWeights[i0];\r\n//\r\n//\t\t\t\tsum += m_AnimWeights[i1];\r\n//\r\n//\t\t\t\t// Need to normalise blend0 and blend1 so they sum to 1.0.\r\n//\t\t\t\tblend0 /= ( blend0 + blend1 );\r\n//\t\t\t\tblend1 = 1.0f - blend0;\r\n//\r\n//\t\t\t\tfor( unsigned int bone = 0; bone < m_numBones; ++bone )\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// Linearly interpolate positions, SLERP the quaternions.\r\n//\t\t\t\t\tm_pAnim[i0]->getTFrameNow()[bone].v.lerp( m_pAnim[i0]->getTFrameNow()[bone].v, m_pAnim[i1]->getTFrameNow()[bone].v, blend1 );\r\n//\t\t\t\t\tm_pAnim[i0]->getQFrameNow()[bone].q.slerp( m_pAnim[i0]->getQFrameNow()[bone].q, m_pAnim[i1]->getQFrameNow()[bone].q, blend1 );\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t// Build the final bone matrices.\r\n//\tbuildBoneMatrices( m_pAnim[0]->getQFrameNow(), m_pAnim[0]->getTFrameNow());\r\n//\r\n//\t// If the animation is flipped, post-process the ROMtx bone matrix array.\r\n//\tif( m_AnimFlipped && m_pAnim[0] )\r\n//\t{\r\n//\t\tflipBoneMatrices();\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n//void NsClump::getHookPosition( NsVector& hook_in, unsigned int bone, NsVector& hook_out )\r\n//{\r\n//    NsMatrix bm;\r\n//\r\n//\tbm.setRightX( m_pBoneMat[bone][0][0] );\r\n//\tbm.setUpX( m_pBoneMat[bone][0][1] );\r\n//\tbm.setAtX( m_pBoneMat[bone][0][2] );\r\n//\tbm.setRightY( m_pBoneMat[bone][1][0] );\r\n//\tbm.setUpY( m_pBoneMat[bone][1][1] );\r\n//\tbm.setAtY( m_pBoneMat[bone][1][2] );\r\n//\tbm.setRightZ( m_pBoneMat[bone][2][0] );\r\n//\tbm.setUpZ( m_pBoneMat[bone][2][1] );\r\n//\tbm.setAtZ( m_pBoneMat[bone][2][2] );\r\n//\tbm.setPosX( m_pBoneMat[bone][3][0] );\r\n//\tbm.setPosY( m_pBoneMat[bone][3][1] );\r\n//\tbm.setPosZ( m_pBoneMat[bone][3][2] );\r\n//\r\n//\tNsVector temp;\r\n//\r\n//\tbm.multiply( &hook_in, &temp );\r\n//\tm_pFrame->getModelMatrix()->multiply( &temp, &hook_out );\r\n//}\r\n//\r\n//void NsClump::draw( NsCamera * camera, unsigned int transform )\r\n//{\r\n//\tNsMatrix\t\troot;\r\n//\tNsMatrix\t\tmodel_transform = *m_pFrame->getModelMatrix();\r\n//\tNsMatrix\t\tm;\r\n////\tNsMatrix\t\tfinal;\r\n//\tNsAtomic\t  * pAtomic;\r\n//\tunsigned int\tvisible;\r\n//\r\n//\t// Cat the clump's frame with the camera view matrix.\r\n//\troot.cat( *camera->getCurrent(), *m_pFrame->getModelMatrix() );\r\n//\r\n//\t// Do animation processing where appropriate.\r\n//\tif( m_pAnim[0] )\r\n//\t{\r\n//\t\tprocessAnims();\r\n//\t}\r\n//\r\n//\t// If you want to perform lighting, you must also set normal transformation matrix. In general case, such\r\n//\t// matrix can be obtained as inverse-transpose of the position transform matrix.\r\n//\tNsMatrix inverse_model_transform;\r\n//\r\n//\tpAtomic = m_pAtomicHead;\r\n//\twhile ( pAtomic ) {\r\n//\t\t// Cat this matrix with the the parent matrix (unless it is the parent).\r\n//\t\tif ( m_pFrame == pAtomic->getFrame() ) {\r\n//\t\t\tGX::LoadPosMtxImm( root.m_matrix, GX_PNMTX0 );\r\n//\t\t\tvisible = pAtomic->getMaterials()->cull( &root );\r\n//\r\n//\t\t\tMTXInverse( model_transform.m_matrix, inverse_model_transform.m_matrix );\r\n//\t\t} else {\r\n//\t\t\tm.cat( root, *pAtomic->getFrame()->getModelMatrix() );\r\n//\t\t\tGX::LoadPosMtxImm( m.m_matrix, GX_PNMTX0 );\r\n//\t\t\tvisible = pAtomic->getMaterials()->cull( &m );\r\n//\t\t\t\r\n//\t\t\tm.cat( model_transform, *pAtomic->getFrame()->getModelMatrix() );\r\n//\t\t\tMTXInverse( m.m_matrix, inverse_model_transform.m_matrix );\r\n//\t\t}\r\n//\t\tif ( visible ) {\r\n//\t\t\tNsMatrix normal_transform;\r\n//\t\t\tMTXTranspose( inverse_model_transform.m_matrix, normal_transform.m_matrix );\r\n//\t\t\tGXLoadNrmMtxImm( normal_transform.m_matrix, GX_PNMTX0 );\r\n//\t\r\n//\t\t\t// Draw it.\r\n//\t\t\tif ( m_pAnim[0] ) {\r\n//\t\t\t\t// Animated.\r\n//\t\t\t\tpAtomic->draw( camera, m_pBoneMat, transform );\r\n//\t\t\t} else {\r\n//\t\t\t\t// Static.\r\n//\t\t\t\tpAtomic->draw( camera );\r\n//\t\t\t}\r\n//\t\t}\r\n//\r\n//\t\t// Onto the next one.\r\n//\t\tpAtomic = pAtomic->m_pNext;\r\n//\t}\r\n//}\r\n//\r\n////void NsClump::applyAnim( NsAnim * m_pAnim )\r\n////{\r\n////\tMtx\troot;\r\n////\tMtx\tm;\r\n////\r\n////\tNsAtomic * pAtomic = m_pAtomicHead;\r\n////\r\n////\tMTXConcat(camera->getCurrent(), m_pFrame->getModelMatrix(), root);\r\n////\r\n////\twhile ( pAtomic ) {\r\n////\t\t// Cat this matrix with the the parent matrix (unless it is the parent).\r\n////\t\tif ( m_pFrame == pAtomic->getFrame() ) {\r\n////\t\t    GX::LoadPosMtxImm( root, GX_PNMTX0 );\r\n////\t\t} else {\r\n////\t\t\tMTXConcat(root, pAtomic->getFrame()->getModelMatrix(), m);\r\n////\t\t    GX::LoadPosMtxImm( m, GX_PNMTX0 );\r\n////\t\t}\r\n////\t\t// Draw it.\r\n////\t\tpAtomic->draw( camera );\r\n////\t\t// Onto the next one.\r\n////\t\tpAtomic = pAtomic->m_pNext;\r\n////\t}\r\n////}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tdraw\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tpMaterialList\tThe list of materials this model uses.\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tDraws the specified model.\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n////void NsClump::draw( NsCamera * camera,  )\r\n////{\r\n////\t// Animated draw.\r\n////\tbuildBoneMatrices( m_pAnim, pDFF, v, objMat, boneMat );\r\n////\t_drawSkinned ( pMaterialList, v, pDFF, objMat, m_pAnim, pPool, boneMat );\r\n//\r\n//// \tpModel = &pDFF[8];\r\n////\r\n////\tp8 = (unsigned char *)pDFF;\r\n////\tpBoneHeader = (BoneHeader *)&p8[pDFF[1]];\r\n////\tm_pBoneData = (BoneData *)&pBoneHeader[1];\r\n////\tpSkinHeader = (SkinHeader *)&m_pBoneData[pBoneHeader->m_numBones];\r\n////\r\n////\tpTransformedVertices = pPool;\r\n////\t//\tpTex = TexMan_Retrieve ( \"SUB_AS_satellite_01.png\" );\r\n////\tfor ( chunk = 0; chunk < pDFF[0]; chunk++ ) {\r\n////\r\n////\t \t// Point up stuff we're interested in.\t\r\n////\t \tpMaterial = (unsigned char *)&pModel[8];\r\n////\t \tpGeom = (unsigned int *)&pMaterial[pModel[0]*64];\r\n////\t\tpCount = (unsigned int *)&pSkinHeader[1];\r\n////\r\n////\t\t// Transform paired vertices.\r\n////\t    GQRSetup6 ( 0, GQR_TYPE_F32, 0, GQR_TYPE_F32 );\t\t// Set read/write scale & type.\t\t\r\n////\t    GQRSetup7 ( 0, GQR_TYPE_F32, 0, GQR_TYPE_F32 );\t\t// Set read/write scale & type.\t\t\r\n////\t\tpCurrentVertexPool = pTransformedVertices;\r\n////\t\tvertexcount = 0;\r\n////\t\twhile ( pCount[0] ) {\r\n////\t\t\tpPosNormPair = (PosNormPair *)&pCount[2];\r\n////\t\t\tpWeight = (WeightPair *)&pPosNormPair[pCount[0]];\r\n////\r\n////\t\t\tif ( blendVtx ) {\r\n////\t\t\t\tBlendTransformFloat( pBoneMat[pCount[1]&255], pBoneMat[(pCount[1]>>8)&255], pWeight->w, pPosNormPair->pos, pTransformedVertices->pos, pCount[0] == 1 ? 2 : pCount[0] );\r\n//////\t\t\t\tDCFlushRange(pTransformedVertices, sizeof ( PosNormPair ) * pCount[0]);\r\n////\t\t\t\tpTransformedVertices += pCount[0];\r\n////\t\t\t} else {\r\n////\t\t\t\tTransformFloat( pBoneMat[pCount[1]&255], pPosNormPair->pos, pTransformedVertices->pos, pCount[0] == 1 ? 2 : pCount[0] );\r\n//////\t\t\t\tDCFlushRange(pTransformedVertices, sizeof ( PosNormPair ) * pCount[0]);\r\n////\t\t\t\tpTransformedVertices += pCount[0];\r\n////\t\t\t}\r\n////\t\t\tvertexcount += pCount[0];\r\n////\t\t\tpCount = (unsigned int *)&pWeight[pCount[0]];\r\n////\t\t}\r\n////\t\tpCount++;\r\n////\r\n////\t\t// Transform accumulation vertices.\r\n////\t\twhile ( pCount[0] ) {\r\n////\t\t\tpPosNormPair = (PosNormPair *)&pCount[2];\r\n////\t\t\tpSingleWeight = (float *)&pPosNormPair[pCount[0]];\r\n////\t\t\tpIndices = (unsigned short *)&pSingleWeight[pCount[0]];\r\n////\r\n////\t\t\tif ( blendVtx ) {\r\n////\t\t\t\tAccTransformFloat ( pBoneMat[pCount[1]], pCount[0], pPosNormPair->pos, pCurrentVertexPool->pos, pIndices, pSingleWeight );\r\n////\t\t\t}\r\n////\t\t\tpCount = (unsigned int *)&pIndices[pCount[0]+(pCount[0]&1)];\r\n////\t\t}\r\n////\t\tpCount++;\r\n////\t\tDCFlushRange(pCurrentVertexPool, sizeof ( PosNormPair ) * vertexcount);\r\n////\r\n////\t    // Set format of position, color and tex coordinates.\r\n////\t    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);\r\n////\t\tif ( pGeom[3] & rpWORLDNORMALS ) GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);\r\n////\t    if ( pGeom[3] & rpWORLDPRELIT ) GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);\r\n////\t\tif ( pGeom[3] & rpWORLDUVS ) GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);\r\n////\r\n////\t\tGXSetNumTevStages(1);\r\n////}\r\n//\r\n//\r\n//\r\n//void NsClump::setAnimWeights( float* p_weights, int num_weights )\r\n//{\r\n//\tassertp( num_weights <= NUM_BLEND_ANIMS );\r\n//\r\n//\tfor( int i = 0; i < NUM_BLEND_ANIMS; ++i )\r\n//\t{\r\n//\t\tif( i < num_weights )\r\n//\t\t{\r\n//\t\t\tm_AnimWeights[i] = p_weights[i];\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\t// Any weights not specified are assumed to be zero.\r\n//\t\t\tm_AnimWeights[i] = 0.0f;\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n//void NsClump::forAllAtomics ( NsClump_Callback pCB, void * pData )\r\n//{\r\n//\tNsAtomic * pAtomic = m_pAtomicHead;\r\n//\twhile ( pAtomic ) {\r\n//\t\tif ( pCB ) pAtomic = pCB( pAtomic, pData );\r\n//\t\tif ( !pAtomic ) break;\r\n//\t\tpAtomic = pAtomic->m_pNext;\r\n//\t}\r\n//}\r\n//\r\n//void NsClump::addAtomic ( NsAtomic * pAtomic )\r\n//{\r\n//\tNsAtomic  * pSearchAtomic;\r\n//\r\n//\tif ( m_pAtomicHead == NULL ) {\r\n//\t\t// First one, just add it.\r\n//\t\tm_pAtomicHead = pAtomic;\r\n//\t} else {\r\n//\t\t// Find the last atomic in the list (must do this to keep the order the same).\r\n//\t\tpSearchAtomic = m_pAtomicHead;\r\n//\t\twhile ( pSearchAtomic->m_pNext ) pSearchAtomic = pSearchAtomic->m_pNext;\r\n//\t\tpSearchAtomic->m_pNext = pAtomic;\r\n//\t}\r\n//\tpAtomic->m_pNext = NULL;\r\n//\tm_numAtomic++;\r\n//\tpAtomic->m_pClump = this;\r\n//}\r\n//\r\n//void NsClump::removeAtomic ( NsAtomic * pAtomicToRemove )\r\n//{\r\n//\tNsAtomic *  pSearchAtomic;\r\n//\tNsAtomic ** ppLastAtomic;\r\n//\r\n//\tpSearchAtomic = m_pAtomicHead;\r\n//\tppLastAtomic = &m_pAtomicHead;\r\n//\twhile ( pSearchAtomic ) {\r\n//\t\t// See if this is the one.\r\n//\t\tif ( pSearchAtomic == pAtomicToRemove ) {\r\n//\t\t\t// Link over this Atomic.\r\n//\t\t\t*ppLastAtomic = pSearchAtomic->m_pNext;\r\n//\t\t\tbreak;\r\n//\t\t}\r\n//\t\t// No match, point up the last Atomic pointer to pointer.\r\n//\t\tppLastAtomic = &pSearchAtomic->m_pNext;\r\n//\t\t// Onto the next one.\r\n//\t\tpSearchAtomic = pSearchAtomic->m_pNext;\r\n//\t}\r\n//\tm_numAtomic--;\r\n//}\r\n//\r\n//void NsClump::removeCASPolys( unsigned int flags )\r\n//{\r\n//\t// Parse each atomic in turn.\r\n//\tNsAtomic * pAtomic = m_pAtomicHead;\r\n//\twhile ( pAtomic ) {\r\n//\t\tif ( pAtomic->m_numCAS32 > 0 ) {\r\n//\t\t\t// Parse each material in turn.\r\n//\t\t\tfor ( int lp = 0; lp < pAtomic->m_pMaterial->m_materialListSize; lp++ ) {\r\n//\t\t\t\t// Parse each DL in turn.\r\n//\t\t\t\tNsDL * pDL = pAtomic->m_pMaterial->retrieve( lp )->headDL();\r\n//\t\t\t\twhile ( pDL ) {\r\n//\t\t\t\t\tunsigned char * p8;\r\n//\t\t\t\t\tunsigned char search[3];\r\n//\r\n//\t\t\t\t\tp8 = (unsigned char *)&pDL[1];\r\n//\r\n//\t\t\t\t\tsearch[0] = search[1] = search[2] = 0xff;\r\n//\t\t\t\t\tfor ( unsigned int ss = 0; ss < pDL->m_size; ss++ ) {\r\n//\t\t\t\t\t\tsearch[0] = search[1];\r\n//\t\t\t\t\t\tsearch[1] = search[2];\r\n//\t\t\t\t\t\tsearch[2] = *p8++;\r\n//\r\n//\t\t\t\t\t\tif (\t( ( search[0] & 0xf8 ) == GX_DRAW_TRIANGLES ) &&\r\n//\t\t\t\t\t\t\t\t( ( ( search[1] << 8 ) | search[2] ) == (int)pDL->m_numIdx ) ) {\r\n//\t\t\t\t\t\t\t// Found it!!! Now, kill all polys with matching flags.\r\n//\t\t\t\t\t\t\tunsigned short * p16 = (unsigned short *)p8;\r\n//\t\t\t\t\t\t\tint\tidxpervtx;\r\n//\r\n//\t\t\t\t\t\t\t// Calculate how many indices per vertex.\r\n//\t\t\t\t\t\t\tidxpervtx = 1;\t// Always have pos.\r\n//\t\t\t\t\t\t    if ( pDL->m_flags & rpWORLDPRELIT ) idxpervtx++;\r\n//\t\t\t\t\t\t\tif ( pDL->m_flags & rpWORLDNORMALS ) idxpervtx++;\r\n//\t\t\t\t\t\t\tif ( pDL->m_flags & rpWORLDUVS ) idxpervtx++;\r\n//\r\n//\t\t\t\t\t\t\t// Kill all polys that have the specified bits set.\r\n//\t\t\t\t\t\t\tfor ( int ii = 0; ii < ( pDL->m_numIdx / 3 ); ii++ ) {\r\n//\t\t\t\t\t\t\t\tif ( pAtomic->m_pCAS32->m_pCAS32[pDL->m_polyBase + ii] & flags ) {\r\n//\t\t\t\t\t\t\t\t\tfor ( int vv = 0; vv < (idxpervtx * 3); vv++ ) {\r\n//\t\t\t\t\t\t\t\t\t\tp16[vv] = 0;\r\n//\t\t\t\t\t\t\t\t\t}\r\n//\t\t\t\t\t\t\t\t}\r\n//\t\t\t\t\t\t\t\tp16 += idxpervtx * 3;\r\n//\t\t\t\t\t\t\t}\r\n//\r\n////\t\t\t\t\t\t\tOSReport( \"Contents of DL: %02x %02x %02x %02x\\n\", p8[0], p8[1], p8[2], p8[3] );\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\tpDL = pDL->m_pNext;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t}\r\n//\r\n//\t\tpAtomic = pAtomic->m_pNext;\r\n//\t}\r\n//\r\n//\r\n////\tint lp;\r\n////\tNsMaterialMan * pMat = atomic->getMaterials();\r\n////\tfor ( lp = 0; lp < pMat->m_numTotal; lp++ ) {\r\n////\t\tpMat->retrieve( lp )->headDL()->removePoly(0);\r\n////\t}\r\n//\r\n//\r\n//\r\n////\tunsigned char * p8;\r\n////\tunsigned char * pEnd;\r\n//\r\n//\t// We basically need to parse all display lists, and remove the polys with\r\n//\t// matching flags.\r\n//\r\n////\t// Parse the display list.\r\n////\tp8 = (unsigned char *)&this[1];\r\n////\tpEnd = &p8[m_size];\r\n////\twhile ( p8 < pEnd ) {\r\n////\t\tswitch ( *p8 & 0xf8 ) {\r\n////\t\t\tcase GX_NOP:\r\n////\t\t\t\tp8++;\r\n////\t\t\t\tbreak;\r\n////\t\t\tcase GX_LOAD_BP_REG:\r\n////\t\t\t\tp8+=4;\r\n////\t\t\t\tbreak;\r\n////\t\t\tcase GX_DRAW_QUADS:\r\n////\t\t\t\tbreak;\r\n////\t\t\tcase GX_DRAW_TRIANGLES:\r\n////\t\t\t\tbreak;\r\n////\t\t\tcase GX_DRAW_TRIANGLE_STRIP:\r\n////\t\t\t\tbreak;\r\n////\t\t\tcase GX_DRAW_TRIANGLE_FAN:\r\n////\t\t\t\tbreak;\r\n////\t\t\tcase GX_DRAW_LINES:\r\n////\t\t\t\tbreak;\r\n////\t\t\tcase GX_DRAW_LINE_STRIP:\r\n////\t\t\t\tbreak;\r\n////\t\t\tcase GX_DRAW_POINTS:\r\n////\t\t\t\tbreak;\r\n////\t\t\tdefault:\r\n////\t\t\t\tp8++;\r\n////\t\t\t\tbreak;\r\n////\t\t}\r\n////\t}\r\n//}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_clump.h",
    "content": "//#ifndef _CLUMP_H_\r\n//#define _CLUMP_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_camera.h\"\r\n//#include \"p_texman.h\"\r\n//#include \"p_matman.h\"\r\n//#include \"p_dlman.h\"\r\n//#include \"p_model.h\"\r\n//#include \"p_frame.h\"\r\n//#include \"p_atomic.h\"\r\n//#include \"p_anim.h\"\r\n//#include \"p_reftypes.h\"\r\n//\r\n//typedef NsAtomic * (*NsClump_Callback)( NsAtomic * clump, void * data );\r\n//\r\n//class NsClump\r\n//{\r\n//\tstatic const int\tNUM_BLEND_ANIMS\t= 3;\t\t\t// Max number of blended anims.\r\n//\r\n//\tNsFrame\t\t\t  *\tm_pFrame;\r\n//\tNsAtomic\t\t  * m_pAtomicHead;\r\n//\tint\t\t\t\t\tm_numAtomic;\r\n//\r\n//\tROMtx\t\t\t  * m_pBoneMat;\r\n//\tNsRefBoneData\t  * m_pBoneData;\r\n//\tNsAnim\t\t\t  * m_pAnim[NUM_BLEND_ANIMS];\r\n//\tfloat\t\t\t\tm_AnimWeights[NUM_BLEND_ANIMS];\t// Weight per anim for blending.\r\n//\tbool\t\t\t\tm_AnimFlipped;\r\n//\r\n//\tunsigned int\t\tm_numBones;\r\n//\r\n//\tNsFrame\t\t\t  *\tm_pFrameList;\r\n//\tint\t\t\t\t\tm_numFrames;\r\n//\r\n//\tNsClump\t\t\t  * m_pNext;\r\n//\r\n//\tvoid\t\t\t  * m_pWorld;\r\n//\tvoid\t\t\t  * m_pUserData;\r\n//\r\n//\tNsTextureMan\t  * m_pTexMan;\r\n//public:\r\n//\tfriend class NsScene;\r\n//\r\n//\t\t\t\t\t\tNsClump\t\t\t\t();\r\n//\t\t\t\t\t\tNsClump\t\t\t\t( NsModel * pModelData );\r\n//\t\t\t\t\t\tNsClump\t\t\t\t( unsigned int * pDFF );\r\n//\t\t\t\t\t\t~NsClump\t\t\t();\r\n//\r\n//\tNsClump&\t\t\tclone\t\t\t\t( void );\r\n//\tvoid\t\t\t\tmerge\t\t\t\t( NsClump& source );\r\n//\r\n//\tNsModel\t\t\t  * setModel\t\t\t( NsModel * pModelData );\r\n//\tvoid\t\t\t\tsetAtomics\t\t\t( unsigned int * pDFF );\r\n//\tvoid\t\t\t  * getUserData\t\t\t( void )\t\t\t{ return m_pUserData; }\r\n//\tvoid\t\t\t\tsetUserData\t\t\t( void * p_data )\t{ m_pUserData = p_data; }\r\n//\r\n//\tvoid\t\t\t\taddAtomic\t\t\t( NsAtomic * pAtomic );\r\n//\tvoid\t\t\t\tremoveAtomic\t\t( NsAtomic * pAtomicToRemove );\r\n//\r\n//\tvoid\t\t\t\tdraw\t\t\t\t( NsCamera * camera, unsigned int transform );\r\n//\r\n//\tNsFrame\t\t\t  * getFrame\t\t\t( void ) { return m_pFrame; };\r\n//\tvoid\t\t\t\tsetFrame\t\t\t( NsFrame * p ) { m_pFrame = p; };\r\n//\r\n//\tvoid\t\t\t\tflipAnim\t\t\t( bool flip )\t{ m_AnimFlipped = flip; };\r\n//\tvoid\t\t\t\tsetAnimWeights\t\t( float* p_weights, int num_weights );\r\n//\tvoid\t\t\t\tbuildBoneMatrices\t( NsQFrame* p_q_frames, NsTFrame* p_t_frames );\r\n//\tvoid\t\t\t\tflipBoneMatrices\t( void );\r\n//\tvoid\t\t\t\tprocessAnims\t\t( void );\r\n//\tvoid\t\t\t\tgetHookPosition\t\t( NsVector& hook_in, unsigned int bone, NsVector& hook_out );\r\n//\r\n//\tvoid\t\t\t\tforAllAtomics\t\t( NsClump_Callback pCB, void * pData );\r\n//\r\n//\tNsAnim\t\t\t  * getAnim\t\t\t\t( int index )\t{ return m_pAnim[index]; };\r\n//\r\n//\tvoid\t\t\t  * getWorld\t\t\t( void ) { return m_pWorld; }\r\n//\r\n//\tint\t\t\t\t\tgetNumAtomics\t\t( void ) { return m_numAtomic; }\r\n//\tunsigned int\t\tgetNumBones\t\t\t( void ) { return m_numBones; }\r\n//\r\n//\tvoid\t\t\t\tremoveCASPolys\t\t( unsigned int flags );\r\n//\r\n//\tvoid\t\t\t\tsetTexMan\t\t\t( NsTextureMan * pTexMan ) { m_pTexMan = pTexMan; }\r\n//\tNsTextureMan\t  * getTexMan\t\t\t( void ) { return m_pTexMan; }\r\n//};\r\n//\r\n//#endif\t\t// _CLUMP_H_\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_collision.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsCollision\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include \"p_hw.h\"\r\n//#include \"p_collision.h\"\r\n//#include \"p_assert.h\"\r\n//#include \"p_render.h\"\r\n//#include \"p_prim.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsCollision\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsCollision::NsCollision()\r\n//{\r\n//\tm_pHead = NULL;\r\n//}\r\n//\r\n//NsCollision::~NsCollision()\r\n//{\r\n//\t// Delete all collision structures.\r\n//\tNsTree * pTree = m_pHead;\r\n//\tNsTree * pDelete;\r\n//\twhile ( pTree ) {\r\n//\t\tpDelete = pTree;\r\n//\t\tpTree = pTree->m_pNext;\r\n//\t\tdelete pDelete;\r\n//\t}\r\n//}\r\n//\r\n//void NsCollision::addTree( void * pTree, unsigned int numLeaf, unsigned int numTri, NsDL * pDL )\r\n//{\r\n//\tNsTree * p = new NsTree( pTree, numLeaf, numTri, pDL );\r\n//\tp->m_pNext = m_pHead;\r\n//\tm_pHead = p;\r\n//}\r\n//\r\n//int NsCollision::findCollision( NsLine * pLine, NsDL::Collision_LineCallback pCb, void * pData )\r\n//{\r\n//\tint rv = 0;\r\n//\tNsTree * pTree = m_pHead;\r\n//\twhile ( pTree ) {\r\n//\t\tif ( pTree->m_numLeafNodes && pTree->m_numTriangles ) {\r\n//\t\t\tif ( pTree->findCollision( pLine, pCb, pData ) ) {\r\n//\t\t\t\trv = 1;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\tpTree = pTree->m_pNext;\r\n//\t}\r\n//\treturn rv;\r\n//}\r\n//\r\n//NsTree::NsTree( void * pTree, unsigned int numLeaf, unsigned int numTri, NsDL * pDL )\r\n//{\r\n//\tNsBranch\t\t  * pBranchNodes;\r\n//\tNsLeaf\t\t\t  * pLeafNodes;\r\n//\tunsigned int\t  * pTriangleMap;\r\n//\r\n//\t// Point up DL.\r\n//\tm_pDL = pDL;\r\n//\r\n//\t// Set pointers & counts up.\r\n//\tm_numBranchNodes\t= numLeaf ? numLeaf - 1 : 0;\r\n//\tm_numLeafNodes\t\t= numLeaf;\r\n//\tm_numTriangles\t\t= numTri;\r\n//\r\n//\tpBranchNodes\t\t= (NsBranch *)pTree;\r\n//\tpLeafNodes\t\t\t= (NsLeaf *)&pBranchNodes[m_numBranchNodes];\r\n//\tpTriangleMap\t\t= (unsigned int *)&pLeafNodes[m_numLeafNodes];\r\n//\r\n//\t// Copy the branch nodes.\r\n//\tif ( m_numBranchNodes ) {\r\n//\t\tm_pBranchNodes = new NsBranch[m_numBranchNodes];\r\n//\t\tmemcpy ( m_pBranchNodes, pBranchNodes, sizeof ( NsBranch ) * m_numBranchNodes );\r\n//\t} else {\r\n//\t\tm_pBranchNodes = NULL;\r\n//\t}\r\n//\r\n//\t// Copy the leaf nodes.\r\n//\tif ( m_numLeafNodes ) {\r\n//\t\tm_pLeafNodes = new NsLeaf[m_numLeafNodes];\r\n//\t\tmemcpy ( m_pLeafNodes, pLeafNodes, sizeof ( NsLeaf ) * m_numLeafNodes );\r\n//\t} else {\r\n//\t\tm_pLeafNodes = NULL;\r\n//\t}\r\n//\r\n//\t// Copy the triangle map.\r\n//\tif ( m_numTriangles ) {\r\n//\t\tm_pTriangleMap = new unsigned int[m_numTriangles];\r\n//\t\tmemcpy ( m_pTriangleMap, pTriangleMap, sizeof ( unsigned int ) * m_numTriangles );\r\n//\t} else {\r\n//\t\tm_pTriangleMap = NULL;\r\n//\t}\r\n//\r\n//\t// Fix branch data.\r\n//\t{\r\n//\t\tunsigned int  * p32 = (unsigned int *)m_pBranchNodes;\r\n//\t\tunsigned int\tvalue;\r\n//\t\tfor ( unsigned int lp = 0; lp < m_numBranchNodes; lp++ ) {\r\n//\t\t\tvalue = *p32++;\r\n//\t\t\tm_pBranchNodes[lp].type = (unsigned short)( ( value >> 16 ) & 0x0000ffff );\r\n//\t\t\tm_pBranchNodes[lp].leftType = (unsigned char)( ( value >> 8 ) & 0x000000ff );\r\n//\t\t\tm_pBranchNodes[lp].rightType = (unsigned char)( value & 0x000000ff );\r\n//\t\t\tvalue = *p32++;\r\n//\t\t\tm_pBranchNodes[lp].leftNode = (unsigned short)( ( value >> 16 ) & 0x0000ffff );\r\n//\t\t\tm_pBranchNodes[lp].rightNode = (unsigned short)( value & 0x0000ffff );\r\n//\t\t\tp32 += 2;\r\n//\t\t}\r\n//\t}\r\n//\t\r\n//\t// Fix leaf data.\r\n//\t{\r\n//\t\tunsigned int  * p32 = (unsigned int *)m_pLeafNodes;\r\n//\t\tunsigned int\tvalue;\r\n//\t\tfor ( unsigned int lp = 0; lp < m_numLeafNodes; lp++ ) {\r\n//\t\t\tvalue = *p32++;\r\n//\t\t\tm_pLeafNodes[lp].numPolygons = (unsigned short)( ( value >> 16 ) & 0x0000ffff );\r\n//\t\t\tm_pLeafNodes[lp].firstPolygon = (unsigned short)( value & 0x0000ffff );\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n//NsTree::~NsTree()\r\n//{\r\n//\tif ( m_pBranchNodes )\tdelete m_pBranchNodes;\r\n//\tif ( m_pLeafNodes )\t\tdelete m_pLeafNodes;\r\n//\tif ( m_pTriangleMap )\tdelete m_pTriangleMap;\r\n//}\r\n//\r\n///******************************************************************************\r\n// *  \r\n// *  Line test with polygons in BSP leaf node\r\n// */\r\n//int NsTree::testPolygons( unsigned int numPolygons, unsigned int polyOffset, NsLine * pLine, NsDL::Collision_LineCallback pCb, void * pData )\r\n//{\r\n//\tunsigned short\t  * polygons = m_pDL->getConnectList();\r\n//\tunsigned int\t  * polyIndex = m_pTriangleMap;\r\n//\tNsVector\t\t  * vertices = m_pDL->getVertexPool();\r\n//\r\n//    while (numPolygons--)\r\n//    {\r\n//\t\tunsigned short\t*poly;\r\n//\t\tNsTriangle\t\tct;\r\n//\t\tfloat\t\t\tdistance;\r\n//\t\tunsigned int\tresult;\r\n//\r\n//\t\t// Build the collision triangle.\r\n//        poly = polygons + ( *polyIndex * 3 );\r\n//        *ct.corner( 0 ) = *(vertices + ( poly[0] * m_pDL->getStride() ));\r\n//        *ct.corner( 1 ) = *(vertices + ( poly[1] * m_pDL->getStride() ));\r\n//        *ct.corner( 2 ) = *(vertices + ( poly[2] * m_pDL->getStride() ));\r\n//\r\n//        /* Test for collision */\r\n//\t\tresult = pLine->intersectTriangle( &distance, &ct );\r\n//\r\n//        if (result)\r\n//        {\r\n//\t\t\tNsCollisionTriangle\ttri; \r\n//\r\n//\t\t\t// Create triangle data.\r\n//\t\t\tNsVector l10;\r\n//\t\t\tNsVector l20;\r\n//\t\t\tl10.sub( *ct.corner(1), *ct.corner(0) );\r\n//\t\t\tl20.sub( *ct.corner(2), *ct.corner(0) );\r\n//\t\t\ttri.normal.cross( l10, l20 );\r\n//\t\t\ttri.normal.normalize();\r\n//\t\t\ttri.vertices[0] = ct.corner( 0 );\r\n//\t\t\ttri.vertices[1] = ct.corner( 1 );\r\n//\t\t\ttri.vertices[2] = ct.corner( 2 );\r\n//\t\t\ttri.point.set( tri.vertices[0]->x, tri.vertices[0]->y, tri.vertices[0]->z );\r\n//\t\t\ttri.index\t\t= *polyIndex;\r\n//\t\t\t// Execute callback.\r\n//\t\t\tif ( pCb ) {\r\n//\t\t\t\tif ( !pCb( pLine, *m_pDL, &tri, distance, pData ) ) {\r\n//\t\t\t\t\t/* Early out */\r\n//\t\t\t\t\treturn 0;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//        }\r\n//\r\n//        polyIndex++;\r\n//    }\r\n//\r\n//\treturn 1;\r\n//}\r\n//\r\n//\r\n///******************************************************************************\r\n// *\r\n// *  Line intersections with collision BSP leaf nodes\r\n// *\r\n// *  Early out with NULL if callback returns NULL.\r\n// */\r\n//\r\n//typedef struct nodeInfo nodeInfo;\r\n//struct nodeInfo\r\n//{\r\n//    unsigned int\ttype;\r\n//    unsigned int\tindex;\r\n//};\r\n//\r\n//typedef union NsSplitBits NsSplitBits;\r\n//union NsSplitBits\r\n//{\r\n//    float\t\t\t\t\tnReal;\r\n//    volatile int\t\t\tnInt;\r\n//    volatile unsigned int\tnUInt;\r\n//};\r\n//\r\n//#define NsCollision_LeafNode\t(1)\r\n//#define NsCollision_BranchNode\t(2)\r\n//#define NsCollision_MaxDepth\t(32)\r\n//\r\n///* Local macro to aid readability */\r\n//#define PUSH_NODE_INFO(_type, _index, lineStart, lineEnd)       \\\r\n//    {                                                           \\\r\n//        nStack++;                                               \\\r\n//        nodeStack[nStack].type = (_type);                       \\\r\n//        nodeStack[nStack].index = (_index);                     \\\r\n//        lineStack[nStack].start = (lineStart);                  \\\r\n//        lineStack[nStack].end = (lineEnd);                      \\\r\n//    }                                                           \\\r\n//\r\n//#define GETCOORD(vect,y)\t\t\t\t\t\t\t\t\t\t\\\r\n//    (*(float *)(((unsigned char *)(&((vect).x)))+(unsigned int)(y)))\r\n//\r\n//int NsTree::findCollision( NsLine * pLine, NsDL::Collision_LineCallback pCb, void * pData )\r\n//{\r\n//\t// First, calculate the gradient.\r\n//\tNsVector\tdelta;\r\n//\tfloat\t\trecip;\r\n//\tfloat\t\tdydx;\r\n//\tfloat\t\tdzdx;\r\n//\tfloat\t\tdxdy;\r\n//\tfloat\t\tdzdy;\r\n//\tfloat\t\tdxdz;\r\n//\tfloat\t\tdydz;\r\n//\r\n//\tdelta.sub( pLine->end, pLine->start );\r\n//\r\n//    recip = (delta.x != 0.0f) ? (1.0f / delta.x) : 0.0f;\r\n//    dydx = delta.y * recip;\r\n//    dzdx = delta.z * recip;\r\n//\r\n//    recip = (delta.y != 0.0f) ? (1.0f / delta.y) : 0.0f;\r\n//    dxdy = delta.x * recip;\r\n//    dzdy = delta.z * recip;\r\n//\r\n//    recip = (delta.z != 0.0f) ? (1.0f / delta.z) : 0.0f;\r\n//    dxdz = delta.x * recip;\r\n//    dydz = delta.y * recip;\r\n//\r\n//    /* Need data stack for recursion */\r\n//    int\t\t\tnStack;\r\n//    nodeInfo\tnodeStack[NsCollision_MaxDepth + 1], node;\r\n//    NsLine\t\tlineStack[NsCollision_MaxDepth + 1], currLine;\r\n//\r\n//    /* Go down tree recursively */\r\n//    node.type\t= m_pBranchNodes ? NsCollision_BranchNode : NsCollision_LeafNode;\r\n//    node.index\t= 0;\r\n//    currLine\t= *pLine;\r\n//    nStack\t\t= 0;\r\n//\r\n//    while (nStack >= 0)\r\n//    {\r\n//        if (node.type == NsCollision_LeafNode)\r\n//        {\r\n//            NsLeaf\t  * leaf;\r\n//\r\n//            leaf = m_pLeafNodes + node.index;\r\n//\r\n//\t\t\tif ( !testPolygons( leaf->numPolygons, leaf->firstPolygon, pLine, pCb, pData ) ) {\r\n//\t\t\t\treturn 0;\r\n//\t\t\t}\r\n//\r\n//            /* Unstack */\r\n//            node\t\t= nodeStack[nStack];\r\n//            currLine\t= lineStack[nStack];\r\n//            nStack--;\r\n//        }\r\n//        else\r\n//        {\r\n//            NsSplitBits\t\tlStart, lEnd;\r\n//            NsSplitBits\t\trStart, rEnd;\r\n//            NsBranch\t  * branch;\r\n//\r\n//            /* Its a plane, find out which way we need to go */\r\n//            branch = m_pBranchNodes + node.index;\r\n//\r\n//            /* Find out where line end points are in relation to the plane\r\n//             * Note: leftValue > rightValue as these mean value for left and right\r\n//             * sector respectively. \r\n//             */\r\n//            lStart.nReal = GETCOORD(currLine.start, branch->type)\r\n//                - branch->leftValue;\r\n//            lEnd.nReal = GETCOORD(currLine.end, branch->type)\r\n//                - branch->leftValue;\r\n//            rStart.nReal = GETCOORD(currLine.start, branch->type)\r\n//                - branch->rightValue;\r\n//            rEnd.nReal = GETCOORD(currLine.end, branch->type)\r\n//                - branch->rightValue;\r\n//\r\n//            /* First test if it's entirely one side or the other \r\n//             * Note that the line can never lie in the plane, because we use \r\n//             * the sign bits to determine which sides the ends are on, so zero\r\n//             * means on the right.\r\n//             */\r\n//            if (rStart.nInt < 0 && rEnd.nInt < 0)\r\n//            {\r\n//                /* totally left */\r\n//                node.type = branch->leftType;\r\n//                node.index = branch->leftNode;\r\n//            }\r\n//            else if (lStart.nInt >= 0 && lEnd.nInt >= 0)\r\n//            {\r\n//                /* totally right */\r\n//                node.type = branch->rightType;\r\n//                node.index = branch->rightNode;\r\n//            }\r\n//            else if (!((lStart.nInt ^ lEnd.nInt) & 0x80000000) &&\r\n//                     !((rStart.nInt ^ rEnd.nInt) & 0x80000000))\r\n//            {\r\n//                /* Doesn't cross either, sat in overlap regions */\r\n//                if (rStart.nInt < rEnd.nInt)\r\n//                {\r\n//                    /* go left, stack right */\r\n//                    PUSH_NODE_INFO(branch->rightType, branch->rightNode,\r\n//                                   currLine.start, currLine.end);\r\n//                    node.type = branch->leftType;\r\n//                    node.index = branch->leftNode;\r\n//                }\r\n//                else\r\n//                {\r\n//                    /* go right, stack left */\r\n//                    PUSH_NODE_INFO(branch->leftType, branch->leftNode,\r\n//                                   currLine.start, currLine.end);\r\n//                    node.type = branch->rightType;\r\n//                    node.index = branch->rightNode;\r\n//                }\r\n//            }\r\n//            else\r\n//            {\r\n//                if (((lStart.nInt ^ lEnd.nInt) & 0x80000000) &&\r\n//                    (rStart.nInt >= 0 && rEnd.nInt >= 0))\r\n//                {\r\n//                    /* crosses left and totally in right */\r\n//                    NsVector\tvTmp;\r\n//\r\n//                    /* Calculate an intersection point for left plane */\r\n////                    _rpLinePlaneIntersectMacro(&vTmp, &currLine, grad,\r\n////                                               branch->type,\r\n////                                               branch->leftValue);\r\n//\t\t\t\t\tfloat\tld;\r\n//\t\t\t\t\tswitch ( branch->type ) {\r\n//\t\t\t\t\t\tcase 0:\r\n//\t\t\t\t\t\t\tld = branch->leftValue - currLine.start.x;\r\n//\t\t\t\t\t\t\tvTmp.x = branch->leftValue;\r\n//\t\t\t\t\t\t\tvTmp.y = currLine.start.y + dydx * ld;\r\n//\t\t\t\t\t\t\tvTmp.z = currLine.start.z + dzdx * ld;\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 4:\r\n//\t\t\t\t\t\t\tld = branch->leftValue - currLine.start.y;\r\n//\t\t\t\t\t\t\tvTmp.x = currLine.start.x + dxdy * ld;\r\n//\t\t\t\t\t\t\tvTmp.y = branch->leftValue;\r\n//\t\t\t\t\t\t\tvTmp.z = currLine.start.z + dzdy * ld;\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 8:\r\n//\t\t\t\t\t\t\tld = branch->leftValue - currLine.start.z;\r\n//\t\t\t\t\t\t\tvTmp.x = currLine.start.x + dxdz * ld;\r\n//\t\t\t\t\t\t\tvTmp.y = currLine.start.y + dydz * ld;\r\n//\t\t\t\t\t\t\tvTmp.z = branch->leftValue;\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\r\n//                    if (lStart.nInt < 0)\r\n//                    {\r\n//                        /* stack right go left */\r\n//                        PUSH_NODE_INFO(branch->rightType,\r\n//                                       branch->rightNode,\r\n//                                       currLine.start, currLine.end);\r\n//                        node.type = branch->leftType;\r\n//                        node.index = branch->leftNode;\r\n//                        currLine.end = vTmp;\r\n//                    }\r\n//                    else\r\n//                    {\r\n//                        /* stack left go right */\r\n//                        PUSH_NODE_INFO(branch->leftType,\r\n//                                       branch->leftNode, vTmp,\r\n//                                       currLine.end);\r\n//                        node.type = branch->rightType;\r\n//                        node.index = branch->rightNode;\r\n//                    }\r\n//                }\r\n//                else if (((rStart.nInt ^ rEnd.nInt) & 0x80000000) &&\r\n//                         (lStart.nInt < 0 && lEnd.nInt < 0))\r\n//                {\r\n//                    /* crosses right and totally in left */\r\n//                    NsVector\tvTmp;\r\n//\r\n//                    /* Calculate an intersection point for right plane */\r\n////                    _rpLinePlaneIntersectMacro(&vTmp, &currLine, grad,\r\n////                                               branch->type,\r\n////                                               branch->rightValue);\r\n//\t\t\t\t\tfloat\tld;\r\n//\t\t\t\t\tswitch ( branch->type ) {\r\n//\t\t\t\t\t\tcase 0:\r\n//\t\t\t\t\t\t\tld = branch->rightValue - currLine.start.x;\r\n//\t\t\t\t\t\t\tvTmp.x = branch->rightValue;\r\n//\t\t\t\t\t\t\tvTmp.y = currLine.start.y + dydx * ld;\r\n//\t\t\t\t\t\t\tvTmp.z = currLine.start.z + dzdx * ld;\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 4:\r\n//\t\t\t\t\t\t\tld = branch->rightValue - currLine.start.y;\r\n//\t\t\t\t\t\t\tvTmp.x = currLine.start.x + dxdy * ld;\r\n//\t\t\t\t\t\t\tvTmp.y = branch->rightValue;\r\n//\t\t\t\t\t\t\tvTmp.z = currLine.start.z + dzdy * ld;\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 8:\r\n//\t\t\t\t\t\t\tld = branch->rightValue - currLine.start.z;\r\n//\t\t\t\t\t\t\tvTmp.x = currLine.start.x + dxdz * ld;\r\n//\t\t\t\t\t\t\tvTmp.y = currLine.start.y + dydz * ld;\r\n//\t\t\t\t\t\t\tvTmp.z = branch->rightValue;\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\r\n//                    if (rStart.nInt < 0)\r\n//                    {\r\n//                        /* stack right go left */\r\n//                        PUSH_NODE_INFO(branch->rightType,\r\n//                                       branch->rightNode, vTmp,\r\n//                                       currLine.end);\r\n//                        node.type = branch->leftType;\r\n//                        node.index = branch->leftNode;\r\n//                    }\r\n//                    else\r\n//                    {\r\n//                        /* stack left go right */\r\n//                        PUSH_NODE_INFO(branch->leftType,\r\n//                                       branch->leftNode, currLine.start,\r\n//                                       currLine.end);\r\n//                        node.type = branch->rightType;\r\n//                        node.index = branch->rightNode;\r\n//                        currLine.end = vTmp;\r\n//                    }\r\n//                }\r\n//                else\r\n//                {\r\n//                    /* Must cross both planes */\r\n//                    NsVector\tvLeft, vRight;\r\n//\t\t\t\t\tfloat\tld;\r\n//\r\n//                    /* Calc intersections at planes */\r\n////                    _rpLinePlaneIntersectMacro(&vLeft, &currLine, grad,\r\n////                                               branch->type,\r\n////                                               branch->leftValue);\r\n//\t\t\t\t\tswitch ( branch->type ) {\r\n//\t\t\t\t\t\tcase 0:\r\n//\t\t\t\t\t\t\tld = branch->leftValue - currLine.start.x;\r\n//\t\t\t\t\t\t\tvLeft.x = branch->leftValue;\r\n//\t\t\t\t\t\t\tvLeft.y = currLine.start.y + dydx * ld;\r\n//\t\t\t\t\t\t\tvLeft.z = currLine.start.z + dzdx * ld;\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 4:\r\n//\t\t\t\t\t\t\tld = branch->leftValue - currLine.start.y;\r\n//\t\t\t\t\t\t\tvLeft.x = currLine.start.x + dxdy * ld;\r\n//\t\t\t\t\t\t\tvLeft.y = branch->leftValue;\r\n//\t\t\t\t\t\t\tvLeft.z = currLine.start.z + dzdy * ld;\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 8:\r\n//\t\t\t\t\t\t\tld = branch->leftValue - currLine.start.z;\r\n//\t\t\t\t\t\t\tvLeft.x = currLine.start.x + dxdz * ld;\r\n//\t\t\t\t\t\t\tvLeft.y = currLine.start.y + dydz * ld;\r\n//\t\t\t\t\t\t\tvLeft.z = branch->leftValue;\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\r\n////                    _rpLinePlaneIntersectMacro(&vRight, &currLine, grad,\r\n////                                               branch->type,\r\n////                                               branch->rightValue);\r\n//\t\t\t\t\tswitch ( branch->type ) {\r\n//\t\t\t\t\t\tcase 0:\r\n//\t\t\t\t\t\t\tld = branch->rightValue - currLine.start.x;\r\n//\t\t\t\t\t\t\tvRight.x = branch->rightValue;\r\n//\t\t\t\t\t\t\tvRight.y = currLine.start.y + dydx * ld;\r\n//\t\t\t\t\t\t\tvRight.z = currLine.start.z + dzdx * ld;\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 4:\r\n//\t\t\t\t\t\t\tld = branch->rightValue - currLine.start.y;\r\n//\t\t\t\t\t\t\tvRight.x = currLine.start.x + dxdy * ld;\r\n//\t\t\t\t\t\t\tvRight.y = branch->rightValue;\r\n//\t\t\t\t\t\t\tvRight.z = currLine.start.z + dzdy * ld;\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tcase 8:\r\n//\t\t\t\t\t\t\tld = branch->rightValue - currLine.start.z;\r\n//\t\t\t\t\t\t\tvRight.x = currLine.start.x + dxdz * ld;\r\n//\t\t\t\t\t\t\tvRight.y = currLine.start.y + dydz * ld;\r\n//\t\t\t\t\t\t\tvRight.z = branch->rightValue;\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\r\n//                    if (lStart.nInt < 0)\r\n//                    {\r\n//                        /* Stack right, go left */\r\n//                        PUSH_NODE_INFO(branch->rightType,\r\n//                                       branch->rightNode, vRight,\r\n//                                       currLine.end);\r\n//                        node.type = branch->leftType;\r\n//                        node.index = branch->leftNode;\r\n//                        currLine.end = vLeft;\r\n//                    }\r\n//                    else\r\n//                    {\r\n//                        /* Stack left, go right */\r\n//                        /* Calc intersection for left plane and stack */\r\n//                        PUSH_NODE_INFO(branch->leftType,\r\n//                                       branch->leftNode, vLeft,\r\n//                                       currLine.end);\r\n//                        node.type = branch->rightType;\r\n//                        node.index = branch->rightNode;\r\n//                        currLine.end = vRight;\r\n//                    }\r\n//                }\r\n//            }\r\n//        }\r\n//    }\r\n//\r\n//    /* All done */\r\n//\treturn 1;\r\n//}\r\n\t\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_collision.h",
    "content": "//#ifndef _COLLISION_H_\r\n//#define _COLLISION_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_triangle.h\"\r\n//#include \"p_matrix.h\"\r\n//#include \"p_dl.h\"\r\n//\r\n//typedef struct {\r\n//\tunsigned short\ttype;\r\n//\tunsigned char\tleftType;\r\n//\tunsigned char\trightType;\r\n//\tunsigned short\tleftNode;\r\n//\tunsigned short\trightNode;\r\n//\tfloat\t\t\tleftValue;\r\n//\tfloat\t\t\trightValue;\r\n//} NsBranch;\r\n//\r\n//typedef struct {\r\n//\tunsigned short\tnumPolygons;\r\n//\tunsigned short\tfirstPolygon;\r\n//} NsLeaf;\r\n//\r\n//class NsTree\r\n//{\r\n//\tint\t\ttestPolygons\t( unsigned int numPolygons, unsigned int polyOffset, NsLine * pLine, NsDL::Collision_LineCallback pCb, void * pData );\r\n//public:\r\n//\tunsigned int\t\tm_numBranchNodes;\r\n//\tunsigned int\t\tm_numLeafNodes;\r\n//\tunsigned int\t\tm_numTriangles;\r\n//\tNsBranch\t\t  * m_pBranchNodes;\r\n//\tNsLeaf\t\t\t  * m_pLeafNodes;\r\n//\tunsigned int\t  * m_pTriangleMap;\r\n//\r\n//\tNsDL\t\t\t  * m_pDL;\r\n//\r\n//\tNsTree\t\t\t  * m_pNext;\r\n//\r\n//\t\t\tNsTree\t\t\t( void * pTree, unsigned int numLeaf, unsigned int numTri, NsDL * pDL ); \r\n//\t\t\t~NsTree\t\t\t();\r\n//\r\n//\tint\t\tfindCollision\t( NsLine * pLine, NsDL::Collision_LineCallback pCb, void * pData );\r\n//};\r\n//\r\n//class NsCollision\r\n//{\r\n//\tNsTree\t  * m_pHead;\r\n//public:\r\n//\r\n//\t\t\tNsCollision\t\t();\r\n//\t\t\t~NsCollision\t();\r\n//\r\n//\tvoid\taddTree\t\t\t( void * pTree, unsigned int numLeaf, unsigned int numTri, NsDL * pDL );\r\n//\r\n//\tint\t\tfindCollision\t( NsLine * pLine, NsDL::Collision_LineCallback pCb, void * pData );\r\n//};\r\n//\r\n//#endif\t\t// _COLLISION_H_\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_debugfont.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tRender\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tAllows a rendering context to be opened and modified as desired\t*\r\n// *\t\t\t\tby the user. A rendering context must be open before Prim or\t*\r\n// *\t\t\t\tModel commands can be issued.\t\t\t\t\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include <math.h>\r\n//#include <stdarg.h>\r\n//#include \"p_debugfont.h\"\r\n//#include \"p_render.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//float ySpacing = 0.0f;\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//extern unsigned char debugFont[(512/8)*128];\r\n//\r\n//namespace NsDebugFont\r\n//{\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tprint\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tOpens the drawing context. This must be called before any\t\t*\r\n// *\t\t\t\tprimitives can be built. Sets up an orthogonal viewport.\t\t*\r\n// *\t\t\t\tThe viewport is set to 0.0f,0.0f at the top-left corner, and\t*\r\n// *\t\t\t\t640.0f,480.0f at the bottom-right corner.\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void printCharacterScaleUp ( float x, float y, int size, GXColor color, char c )\r\n//{\r\n//\tunsigned char * p8;\r\n//\tint\t\t\t\txx;\r\n//\tint\t\t\t\tyy;\r\n//\tunsigned short\tline;\r\n//\tfloat\t\t\tscale;\r\n//\tfloat\t\t\tsx;\r\n//\tfloat\t\t\tsy;\r\n//\tfloat\t\t\tex;\r\n//\tfloat\t\t\tey;\r\n//\r\n//\tp8 = &debugFont[((c&0x1f)*2)+((c&0xe0)*32)];\r\n//\tscale = (float)size / 16.0f;\r\n//\r\n//\tfor ( yy = 0; yy < 16; yy++ ) {\r\n//\t\t// Read this line.\r\n//\t\tline = ( p8[0] << 8 ) | p8[1];\r\n//\t\tfor ( xx = 0; xx < 16; xx++ ) {\r\n//\t\t\tif ( line & ( 0x8000 >> xx ) ) {\r\n//\t\t\t\tsx = x+(((float)xx)*scale);\r\n//\t\t\t\tsy = y+(((float)yy)*scale);\r\n//\t\t\t\tex = x+(((float)xx+1)*scale);\r\n//\t\t\t\tey = y+(((float)yy+1)*scale);\r\n//\t\t\t\tNsPrim::box ( sx, sy, ex, ey, color );\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\t// Move down a line.\r\n//\t\tp8 += (512/8);\r\n//\t}\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tprint\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tOpens the drawing context. This must be called before any\t\t*\r\n// *\t\t\t\tprimitives can be built. Sets up an orthogonal viewport.\t\t*\r\n// *\t\t\t\tThe viewport is set to 0.0f,0.0f at the top-left corner, and\t*\r\n// *\t\t\t\t640.0f,480.0f at the bottom-right corner.\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void printCharacter ( float x, float y, int size, GXColor color, char c )\r\n//{\r\n//\tunsigned char * p8;\r\n//\tint\t\t\t\txx;\r\n//\tint\t\t\t\tyy;\r\n//\tunsigned short\tline;\r\n//\r\n//\tif ( size < 16 ) {\r\n//\t\tprintCharacterScaleDown ( x, y, size, color, c );\r\n//\t} else if ( size == 16 ) {\r\n//\r\n//\t\tp8 = &debugFont[((c&0x1f)*2)+((c&0xe0)*32)];\r\n//\r\n//\t\tfor ( yy = 0; yy < 16; yy++ ) {\r\n//\t\t\t// Read this line.\r\n//\t\t\tline = ( p8[0] << 8 ) | p8[1];\r\n//\t\t\tfor ( xx = 0; xx < 16; xx++ ) {\r\n//\t\t\t\tif ( line & ( 0x8000 >> xx ) ) {\r\n//\t\t\t\t\tNsPrim::point ( x+(float)xx, y+(float)yy, color );\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\t// Move down a line.\r\n//\t\t\tp8 += (512/8);\r\n//\t\t}\r\n//\t} else {\r\n//\t\tprintCharacterScaleUp ( x, y, size, color, c );\r\n//\t}\r\n//\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tprint\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tOpens the drawing context. This must be called before any\t\t*\r\n// *\t\t\t\tprimitives can be built. Sets up an orthogonal viewport.\t\t*\r\n// *\t\t\t\tThe viewport is set to 0.0f,0.0f at the top-left corner, and\t*\r\n// *\t\t\t\t640.0f,480.0f at the bottom-right corner.\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void printCharacterScaleDown ( float x, float y, int size, GXColor color, char c )\r\n//{\r\n//\tunsigned char * p8;\r\n//\tint\t\t\t\txx;\r\n//\tint\t\t\t\tyy;\r\n//\tunsigned short\tline;\r\n//\tfloat\t\t\tscale;\r\n//\tunsigned char\tintensity[16][16];\r\n//\tunsigned char\tarea[16][16];\r\n//\r\n//\tscale = (float)size / 16.0f;\r\n//\tp8 = &debugFont[((c&0x1f)*2)+((c&0xe0)*32)];\r\n//\r\n//\t// Reset Intensity level.\r\n//\tfor ( yy = 0; yy < size; yy++ ) {\r\n//\t\tfor ( xx = 0; xx < size; xx++ ) {\r\n//\t\t\tintensity[yy][xx] = 0;\r\n//\t\t\tarea[yy][xx] = 0;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t// Set Intensity level.\r\n//\tfor ( yy = 0; yy < 16; yy++ ) {\r\n//\t\tline = ( p8[0] << 8 ) | p8[1];\r\n//\t\tfor ( xx = 0; xx < 16; xx++ ) {\r\n//\t\t\tif ( line & ( 0x8000 >> xx ) ) intensity[(int)((float)yy*scale)][(int)((float)xx*scale)]++;\r\n//\t\t\tarea[(int)((float)yy*scale)][(int)((float)xx*scale)]+=2;\r\n//\t\t}\r\n//\t\t// Move down a line.\r\n//\t\tp8 += 512/8;\r\n//\t}\r\n//\r\n//\t// Draw pixels.\r\n//\tfor ( yy = 0; yy < size; yy++ ) {\r\n//\t\tfor ( xx = 0; xx < size; xx++ ) {\r\n//\t\t\tif ( intensity[yy][xx] ) {\r\n//\t\t\t\tNsPrim::point ( x+(float)xx, y+(float)yy, (GXColor) { (color.r>>1)+((color.r*intensity[yy][xx])/area[yy][xx]), (color.g>>1)+((color.g*intensity[yy][xx])/area[yy][xx]), (color.b>>1)+((color.b*intensity[yy][xx])/area[yy][xx]), color.a } );\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tprint\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tOpens the drawing context. This must be called before any\t\t*\r\n// *\t\t\t\tprimitives can be built. Sets up an orthogonal viewport.\t\t*\r\n// *\t\t\t\tThe viewport is set to 0.0f,0.0f at the top-left corner, and\t*\r\n// *\t\t\t\t640.0f,480.0f at the bottom-right corner.\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void printf ( float x, float y, NsFontEffect fe, int size, GXColor color, char * format, ... )\r\n//{\r\n//\tva_list\tmarker;\r\n////\tint\t\tlp;\r\n//\tchar\tbuffer[1024*8];\r\n//\tchar  * p8;\r\n//\tfloat\tleft;\r\n//\tfloat\tcx;\r\n//\tfloat\tcy;\r\n//\r\n//\t// Call our sprintf which correctly handles float, double and long double.\r\n//\tva_start ( marker, format );\r\n//\tvsprintf ( buffer, format, marker );\r\n//\r\n//\tleft = x;\r\n//\tcx = x;\r\n//\tcy = y;\r\n//\r\n//\tNsRender::setZMode ( NsZMode_Always, 0, 0, 0 );\r\n//\r\n//\tp8 = buffer;\r\n//\twhile ( *p8 ) {\r\n//\t\tswitch ( *p8 ) {\r\n//\t\t\tcase '\\n':\r\n//\t\t\t\tcx = left;\r\n//\t\t\t\tcy += (float)size + ySpacing;\r\n//\t\t\t\tbreak;\r\n//\t\t\tdefault:\r\n//\t\t\t\tswitch ( fe ) {\r\n//\t\t\t\t\tcase NsFontEffect_Shadow:\r\n//\t\t\t\t\t\tprintCharacter ( cx+1.0f, cy+1.0f, size, (GXColor){0,0,0,128}, *p8 );\r\n//\t\t\t\t\t\tprintCharacter ( cx, cy, size, color, *p8 );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tcase NsFontEffect_Outline:\r\n//\t\t\t\t\t\tprintCharacter ( cx-1.0f, cy, size, (GXColor){0,0,0,128}, *p8 );\r\n//\t\t\t\t\t\tprintCharacter ( cx+1.0f, cy, size, (GXColor){0,0,0,128}, *p8 );\r\n//\t\t\t\t\t\tprintCharacter ( cx, cy-1.0f, size, (GXColor){0,0,0,128}, *p8 );\r\n//\t\t\t\t\t\tprintCharacter ( cx, cy+1.0f, size, (GXColor){0,0,0,128}, *p8 );\r\n//\t\t\t\t\t\tprintCharacter ( cx, cy, size, color, *p8 );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tcase NsFontEffect_Bold:\r\n//\t\t\t\t\t\tprintCharacter ( cx-1.0f, cy, size, color, *p8 );\r\n//\t\t\t\t\t\tprintCharacter ( cx+1.0f, cy, size, color, *p8 );\r\n//\t\t\t\t\t\tprintCharacter ( cx, cy-1.0f, size, color, *p8 );\r\n//\t\t\t\t\t\tprintCharacter ( cx, cy+1.0f, size, color, *p8 );\r\n//\t\t\t\t\t\tprintCharacter ( cx, cy, size, color, *p8 );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tdefault:\r\n//\t\t\t\t\t\tprintCharacter ( cx, cy, size, color, *p8 );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tcx += (float)size;\r\n//\t\t\t\tbreak;\r\n//\t\t}\r\n//\t\tp8++;\r\n//\t}\r\n//\r\n//\tva_end ( marker );\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tsetYSpacing\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tspacing\tThe amount of space between y lines.\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tSet sthe amount of space that is added between character lines.\t*\r\n// *\t\t\t\tDefault is set to 0.0f;\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void setYSpacing ( float spacing )\r\n//{\r\n//\tySpacing = spacing;\r\n//}\r\n//\r\n//}\t\t// namespace Render\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_debugfont.h",
    "content": "//#ifndef _DEBUGFONT_H_\r\n//#define _DEBUGFONT_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_prim.h\"\r\n//\r\n//typedef enum {\r\n//\tNsFontEffect_None = 0,\r\n//\tNsFontEffect_Shadow,\r\n//\tNsFontEffect_Outline,\r\n//\tNsFontEffect_Bold,\r\n//\r\n//\tNsFontEffect_Max\r\n//} NsFontEffect;\r\n//\r\n//namespace NsDebugFont\r\n//{\r\n//\tvoid printCharacterScaleUp\t\t( float x, float y, int size, GXColor color, char c );\r\n//\tvoid printCharacterScaleDown\t( float x, float y, int size, GXColor color, char c );\r\n//\tvoid printCharacter\t\t\t\t( float x, float y, int size, GXColor color, char c );\r\n//\tvoid printf\t\t\t\t\t\t( float x, float y, NsFontEffect fe, int size, GXColor color, char * format, ... );\r\n//\r\n//\tvoid setYSpacing\t\t\t\t( float spacing );\r\n//};\r\n//\r\n//#endif\t\t// _DEBUGFONT_H_\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_display.cpp",
    "content": "/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsDisplay\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tSets up and manages a triple-buffered display. This code is\t\t*\r\n *\t\t\t\tderived from the Nintendo \"frb-triple\" example.\t\t\t\t\t*\r\n *\t\t\t\tTake a look at Sony's documentation for more information at:\t*\r\n *\t\t\t\t$/DolphinSDK1.0/man/demos/gxdemos/Framebuffer/frb-triple.html \t*\r\n *\t\t\t\tAlso, check out the original source code at:\t\t\t\t\t*\r\n *\t\t\t\t$/DolphinSDK1.0/build/demos/gxdemo/src/Framebuffer/frb-triple.c *\r\n *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#include \"p_hw.h\"\r\n//#include <stdlib.h>\r\n#include \"p_display.h\"\r\n//#include <dolphin\\dtk.h>\r\n#include <sys\\timer.h>\r\n#include <sys\\ngc\\p_render.h>\r\n//#include <sys\\ngc\\p_screenshot.h>\r\n#include <sys\\ngc\\p_prim.h>\r\n#include <sys\\ngc\\p_camera.h>\r\n#include <sys\\ngc\\p_dvd.h>\r\n#include <gel/scripting/script.h> \r\n#include \"gfx/ngc/nx/nx_init.h\"\r\n#include <gel/mainloop.h>\r\n\r\n#include <sys/ngc/p_display.h>\r\n#include <sys/ngc/p_render.h>\r\n#include <sys/ngc/p_prim.h>\r\n#include <gfx/ngc/nx/nx_init.h>\r\n#include <gfx/ngc/nx/chars.h>\r\n#include <gfx/ngc/nx/render.h>\r\n#include <gfx/nxfontman.h>\r\n#include <gfx/ngc/p_nxfont.h>\r\n#include <gel/scripting/symboltable.h> \r\n\r\n#include <core/defines.h>\r\n#include <core/String/stringutils.h>\r\n#include <gfx/NxFontMan.h>\r\n#include <gel/Scripting/script.h>\r\n#include <gel/scripting/struct.h>\r\n#include <gel/scripting/array.h>\r\n#include <gel/scripting/symboltable.h>\r\n#include \t\"gfx\\ngc\\nx\\nx_init.h\"\r\n#include \"gel\\music\\ngc\\p_music.h\"\r\n#include <sys\\ngc\\p_profile.h>\r\n#include \"VIDSimpleAudio.h\"\r\n\r\nextern GXRenderModeObj *rmode;\r\nextern GXRenderModeObj rmodeobj;\r\nextern int inDrawingContext;\r\n\r\nextern DVDCallback last_callback[8];\r\nextern s32 last_callback_length[8];\r\nextern DVDFileInfo* last_callback_fileInfo[8];\r\nextern int last_callback_counter[8];\r\n\r\nbool g_need_to_flush = true;\r\n\r\n//NsProfile profile_gpu( \"gpu\", 256 );\r\n\r\n//#define __INFO_REPORT__\r\n\r\n#define P0_COUNT 35\r\n#define P1_COUNT 22\r\n\r\nbool g_legal = false;\r\n\r\n#ifdef __INFO_REPORT__\r\nint gp0 = GX_PERF0_XF_WAIT_IN;\r\nint gp1 = GX_PERF1_TX_IDLE;\r\nchar g_gp_info0[64*P0_COUNT];\r\nchar g_gp_info1[64*P1_COUNT];\r\n\r\nint frames = 0;\r\n\r\nu32 _p0, _p1;\r\nchar * p0_name[] =\r\n{\r\n    \"GX_PERF0_VERTICES            \",\r\n\t\"GX_PERF0_CLIP_VTX            \",\r\n\t\"GX_PERF0_CLIP_CLKS           \",\r\n\t\"GX_PERF0_XF_WAIT_IN          \",\r\n\t\"GX_PERF0_XF_WAIT_OUT         \",\r\n\t\"GX_PERF0_XF_XFRM_CLKS        \",\r\n\t\"GX_PERF0_XF_LIT_CLKS         \",\r\n\t\"GX_PERF0_XF_BOT_CLKS         \",\r\n\t\"GX_PERF0_XF_REGLD_CLKS       \",\r\n\t\"GX_PERF0_XF_REGRD_CLKS       \",\r\n\t\"GX_PERF0_CLIP_RATIO          \",\r\n\r\n\t\"GX_PERF0_TRIANGLES           \",\r\n\t\"GX_PERF0_TRIANGLES_CULLED    \",\r\n\t\"GX_PERF0_TRIANGLES_PASSED    \",\r\n\t\"GX_PERF0_TRIANGLES_SCISSORED \",\r\n\t\"GX_PERF0_TRIANGLES_0TEX      \",\r\n\t\"GX_PERF0_TRIANGLES_1TEX      \",\r\n\t\"GX_PERF0_TRIANGLES_2TEX      \",\r\n\t\"GX_PERF0_TRIANGLES_3TEX      \",\r\n\t\"GX_PERF0_TRIANGLES_4TEX      \",\r\n\t\"GX_PERF0_TRIANGLES_5TEX      \",\r\n\t\"GX_PERF0_TRIANGLES_6TEX      \",\r\n\t\"GX_PERF0_TRIANGLES_7TEX      \",\r\n\t\"GX_PERF0_TRIANGLES_8TEX      \",\r\n\t\"GX_PERF0_TRIANGLES_0CLR      \",\r\n\t\"GX_PERF0_TRIANGLES_1CLR      \",\r\n\t\"GX_PERF0_TRIANGLES_2CLR      \",\r\n\r\n\t\"GX_PERF0_QUAD_0CVG           \",\r\n\t\"GX_PERF0_QUAD_NON0CVG        \",\r\n\t\"GX_PERF0_QUAD_1CVG           \",\r\n\t\"GX_PERF0_QUAD_2CVG           \",\r\n\t\"GX_PERF0_QUAD_3CVG           \",\r\n\t\"GX_PERF0_QUAD_4CVG           \",\r\n\t\"GX_PERF0_AVG_QUAD_CNT        \",\r\n\r\n\t\"GX_PERF0_CLOCKS              \",\r\n\t\"GX_PERF0_NONE                \"\r\n\r\n};\r\n\r\n/********************************/\r\nchar * p1_name[] =\r\n{\r\n\t\"GX_PERF1_TEXELS              \",\r\n\t\"GX_PERF1_TX_IDLE             \",\r\n\t\"GX_PERF1_TX_REGS             \",\r\n\t\"GX_PERF1_TX_MEMSTALL         \",\r\n\t\"GX_PERF1_TC_CHECK1_2         \",\r\n\t\"GX_PERF1_TC_CHECK3_4         \",\r\n\t\"GX_PERF1_TC_CHECK5_6         \",\r\n\t\"GX_PERF1_TC_CHECK7_8         \",\r\n\t\"GX_PERF1_TC_MISS             \",\r\n\r\n\t\"GX_PERF1_VC_ELEMQ_FULL       \",\r\n\t\"GX_PERF1_VC_MISSQ_FULL       \",\r\n\t\"GX_PERF1_VC_MEMREQ_FULL      \",\r\n\t\"GX_PERF1_VC_STATUS7          \",\r\n\t\"GX_PERF1_VC_MISSREP_FULL     \",\r\n\t\"GX_PERF1_VC_STREAMBUF_LOW    \",\r\n\t\"GX_PERF1_VC_ALL_STALLS       \",\r\n\t\"GX_PERF1_VERTICES            \",\r\n\r\n\t\"GX_PERF1_FIFO_REQ            \",\r\n\t\"GX_PERF1_CALL_REQ            \",\r\n\t\"GX_PERF1_VC_MISS_REQ         \",\r\n\t\"GX_PERF1_CP_ALL_REQ          \",\r\n\r\n\t\"GX_PERF1_CLOCKS              \",\r\n\t\"GX_PERF1_NONE                \"\r\n\r\n};\r\n#endif\t\t// __INFO_REPORT__\r\n\r\n/********************************************************************************\r\n * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#define QUEUE_MAX 5\r\n#define QUEUE_EMPTY QUEUE_MAX\r\n\r\nu8 g_blur = 0;\r\n\r\nextern bool\t\tgLoadingBarActive;\r\nextern int\t\t\tgLoadBarTotalFrames;\r\nextern int\t\t\tgLoadBarNumFrames;\r\nextern int\t\t\tgLoadBarX;\r\nextern int\t\t\tgLoadBarY;\r\nextern int\t\t\tgLoadBarWidth;\r\nextern int\t\t\tgLoadBarHeight;\r\nextern int\t\t\tgLoadBarStartColor[4];\r\nextern int\t\t\tgLoadBarDeltaColor[4];\r\nextern int\t\t\tgLoadBarBorderWidth;\r\nextern int\t\t\tgLoadBarBorderHeight;\r\nextern int\t\t\tgLoadBarBorderColor[4];\r\n\r\nGXColor\t\t\t\tmessageColor = {0,0,0,255};\r\nstatic float\t\tlasty = 0;\r\nstatic float\t\tprevx = 0;\r\nstatic float\t\tprevy = 0;\r\nstatic int\t\t\tselection = 0;\r\nstatic int\t\t\tselection_max = 0;\r\nstatic int\t\t\treset_enabled_frames = 0;\r\n\r\n/********************************************************************************\r\n * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\ntypedef struct QItem_ \r\n{\r\n    void* writePtr;\r\n    void* dataPtr;\r\n    void* copyXFB;\r\n} NsDisplay_QItem;\r\n\r\ntypedef struct Queue_\r\n{\r\n    NsDisplay_QItem entry[QUEUE_MAX];\r\n    u16 top;\r\n    u16 bot;\r\n} NsDisplay_Queue;\r\n\r\n/********************************************************************************\r\n * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nvoid\t(*pIconCallback)( void )\t= NULL;\r\n\r\nstatic NsDisplay_Queue\tRenderQ;\t\t\t\t// Queue for frames in FIFO\r\nstatic NsDisplay_Queue\tDoneQ;\t\t\t\t\t// Queue for frames finished already\r\n\r\nstatic void\t\t\t  * myXFB1;\t\t\t\t\t// Pointers to the two XFB's\r\nstatic void\t\t\t  * myXFB2;\r\nstatic void\t\t\t  * copyXFB;\t\t\t\t// Which XFB to copy to next\r\nstatic void\t\t\t  * dispXFB;\t\t\t\t// Which XFB is being displayed now\r\n\r\nstatic GXBool\t\t\tBPSet;\t\t\t\t\t// Is the FIFO breakpoint set?\r\nstatic GXBool\t\t\tBPWait;\t\t\t\t\t// Is breakpt reset waiting on VBlank?\r\nstatic GXBool\t\t\tBPGo;\t\t\t\t\t// Indicates breakpt should be released\r\n\r\nstatic u16\t\t\t\tlastVCBToken;\t\t\t// Last sync token the VBlank callback saw\r\nstatic u16\t\t\t\tnewToken;\t\t\t\t// Value to use for new sync token.\r\n\r\nstatic OSThreadQueue\twaitingDoneRender;\t\t// Threads waiting for frames to finish\r\n\r\nstatic OSThread\t\t\tCUThread;\t\t\t\t// OS data for clean-up thread\r\nstatic u8\t\t\t\tCUThreadStack[4096];\t// Stack for clean-up thread\r\n\r\nstatic OSAlarm\t\t\ts_bg_alarm;\r\nstatic OSThread\t\t\ts_bg_thread;\r\nstatic u8\t\t\t\ts_bg_thread_stack[4096];\r\n\r\nstatic int\t\t\t\tinitCount = 0;\t\t\t// We can only initialize this once.\r\n\r\nstatic int\t\t\t\tinDisplayContext = 0;\r\n\r\nint\t\t\t\t\t\tresetDown = 0;\t\t\t// Whether the reset button has been pressed.\r\n\r\nstatic int\t\t\t\tcurrentBuffer = 0;\t\t// Current buffer to use for triple buffering.\r\n/********************************************************************************\r\n * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nstatic void\t\t\t\tBPCallback\t\t\t( void );\r\nstatic void\t\t\t\tSetNextBreakPt\t\t( void );\r\nstatic void\t\t\t\tVIPreCallback\t\t( u32 retraceCount );\r\nstatic void\t\t\t\tVIPostCallback\t\t( u32 retraceCount );\r\nstatic void\t\t\t  * CleanupThread\t\t( void * param );\r\nstatic void\t\t\t  * bg_thread_func\t\t( void * param );\r\nstatic void\t\t\t\tbg_alarm_handler\t( OSAlarm* alarm, OSContext* context );\r\n\r\nstatic void\t\t\t\tinit_queue\t\t\t( NsDisplay_Queue *q );\r\nstatic void\t\t\t\tenqueue\t\t\t\t( NsDisplay_Queue *q, NsDisplay_QItem *qitm );\r\nstatic NsDisplay_QItem\tdequeue\t\t\t\t( NsDisplay_Queue *q );\r\nstatic NsDisplay_QItem\tqueue_front\t\t\t( NsDisplay_Queue *q );\r\nstatic GXBool\t\t\tqueue_empty\t\t\t( NsDisplay_Queue *q );\r\nstatic u32\t\t\t\tqueue_length\t\t( NsDisplay_Queue *q );\r\n\r\nstatic NsDisplay_StartRenderingCallback\tstartCB = NULL;\r\nstatic NsDisplay_EndRenderingCallback\tendCB = NULL;\r\n\r\n\r\n/********************************************************************************\r\n * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nextern void\t\t\t  * hwFrameBuffer1;        // Where to find XFB info\r\nextern void\t\t\t  * hwFrameBuffer2;\r\nextern PADStatus\t\tpadData[PAD_MAX_CONTROLLERS]; // game pad state\r\n\r\n//static void* MyAlloc( u32 size )\r\n//{\r\n//\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n//\tvoid* p = new char[size];\r\n//\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n//\r\n//\treturn p;\r\n//}\r\n//\r\n//static void MyFree( void* block )\r\n//{\r\n//\tdelete (char *)block;\r\n//}\r\n\r\nstatic u32 Update_input( void )\r\n{\r\n\r\n  int i;\r\n//  u32 ResetReq = 0;\r\n//  PADStatus Pad[PAD_MAX_CONTROLLERS];\r\n  u32 PadButtonDownVal;\r\n  static u16 buttonLast[4] ={ 0, 0, 0, 0 };\r\n\r\n  //\r\n  // Read current PAD status and clamp the analog inputs\r\n  //\r\n\r\n//  hwPadRead();\r\n\r\n//  PADRead(Pad);\r\n//  PADClamp(Pad);\r\n\r\n//  //\r\n//  // Do we have an input device handle yet?\r\n//  //\r\n//\r\n//  for ( i = 0 ; i < PAD_MAX_CONTROLLERS ; i++ )\r\n//  {\r\n//    if ( padData[i].err == PAD_ERR_TRANSFER )\r\n//    {\r\n//      return( 0 );\r\n//    }\r\n//    else if ( padData[i].err == PAD_ERR_NONE )\r\n//    {\r\n//      break;\r\n//    }\r\n//    else if ( padData[i].err == PAD_ERR_NO_CONTROLLER )\r\n//    {\r\n//      ResetReq |= (PAD_CHAN0_BIT >> i);\r\n//    }\r\n//  }\r\n//\r\n//  //\r\n//  // A pad isn't plugged in\r\n//  //\r\n//\r\n//  if ( i == PAD_MAX_CONTROLLERS )\r\n//  {\r\n//    //\r\n//    // Reset pad channels which have been not valid\r\n//    //\r\n//\r\n//    if ( ResetReq )\r\n//    {\r\n//      PADReset( ResetReq );\r\n//    }\r\n//\r\n//    buttonLast[0] = 0;\r\n//    buttonLast[1] = 0;\r\n//    buttonLast[2] = 0;\r\n//    buttonLast[3] = 0;\r\n//    return( 0 );\r\n//  }\r\n\r\n  //\r\n  // Get the button downs and save the current state\r\n  //\r\n\r\n  PadButtonDownVal = 0;\r\n  for ( i = 0 ; i < PAD_MAX_CONTROLLERS ; i++ )\r\n  {\r\n\t  PadButtonDownVal |= PADButtonDown ( buttonLast[i], padData[i].button );\r\n\t  buttonLast[i] = padData[i].button;\r\n  }\r\n\r\n\r\n//  //\r\n//  // Handle the loop control\r\n//  //\r\n//\r\n//  if ( PadButtonDownVal & PAD_BUTTON_START )\r\n//  {\r\n//    Loop_current = ! Loop_current;\r\n//  }\r\n//\r\n//  //\r\n//  // Handle the skip to the next files\r\n//  //\r\n//\r\n//  if ( Pad[i].button & PAD_BUTTON_A )\r\n//  {\r\n//    return( 1 );\r\n//  }\r\n//\r\n//  return( 0 );\r\n\r\n  return PadButtonDownVal;\r\n}\r\n\r\nvoid NsDisplay::Check480P( void )\r\n{\r\n\t// See if the 480p/widescreen menu should be displayed\r\n\tu32 buttons = 0;\r\n\r\n\tNxNgc::EngineGlobals.screen_brightness = 0.0f;\r\n\tfor ( int lp = 0; lp < 4; lp++ )\r\n\t{\r\n\t\tNsDisplay::begin();\r\n\t\tNsRender::begin();\r\n\t\tNsRender::end();\r\n\t\tNsDisplay::end( true );\r\n\r\n\t\tfor ( int i = 0 ; i < PAD_MAX_CONTROLLERS ; i++ )\r\n\t\t{\r\n\t\t\tbuttons |= padData[i].button;\r\n\t\t}\r\n\t}\r\n\r\n\tNxNgc::EngineGlobals.screen_brightness = 1.0f;\r\n\r\n\t// If we have a cable connected, we can continue...\r\n\tif ( VIGetDTVStatus() )\r\n\t{\r\n\t\tif ( ( buttons & PAD_BUTTON_B ) || OSGetProgressiveMode() )\r\n\t\t{\r\n\t\t\twhile ( !( buttons & PAD_BUTTON_A ) )\r\n\t\t\t{\r\n\t\t\t\t// Render the text.\r\n\t\t\t\tNsDisplay::begin();\r\n\t\t\t\tNsRender::begin();\r\n\t\r\n\t\t\t\tNsCamera cam;\r\n\t\t\t\tcam.orthographic( 0, 0, 640, 448 );\r\n\t\r\n\t\t\t\t// Draw the screen.\r\n\t\t\t\tNsPrim::begin();\r\n\t\r\n\t\t\t\tcam.begin();\r\n\t\r\n\t\t\t\tGX::SetZMode( GX_FALSE, GX_ALWAYS, GX_TRUE );\r\n\t\r\n\t\t\t\tNxNgc::set_blend_mode( NxNgc::vBLEND_MODE_BLEND );\r\n\t\r\n\t\t\t\tScript::RunScript( \"ngc_widescreen\" );\r\n\t\r\n\t\t\t\tNsDisplay::setBackgroundColor( messageColor );\r\n\t\r\n\t\t\t\tcam.end();\r\n\t\r\n\t\t\t\tNsPrim::end();\r\n\t\r\n\t\t\t\tNsRender::end();\r\n\t\t\t\tNsDisplay::end( true );\r\n\t\r\n\t\t\t\tbuttons = Update_input();\r\n\t\r\n\t\t\t\tif ( buttons & PAD_BUTTON_DOWN ) selection++;\r\n\t\t\t\tif ( buttons & PAD_BUTTON_UP ) selection--;\r\n\t\t\t\tif ( selection < 0 ) selection = 0;\r\n\t\t\t\tif ( selection >= selection_max ) selection = selection_max - 1;\r\n\t\t\t}\r\n\t\t\t// Clear to black.\r\n\t\t\tNsDisplay::setBackgroundColor( (GXColor){0,0,0,0} );\r\n\t\t\tNsDisplay::begin();\r\n\t\t\tNsDisplay::end( true );\r\n\t\t\tNsDisplay::begin();\r\n\t\t\tNsDisplay::end( true );\r\n\r\n\t\t\t// Run the selected script.\r\n\t\t\tchar buf[32];\r\n\t\t\tsprintf( buf, \"ngc_select%d\", selection );\r\n\t\t\tScript::RunScript( buf );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// No cable, turn off progressive mode.\r\n\t\tOSSetProgressiveMode(0);\r\n\t}\r\n\r\n\t// Must display licensed by nintendo screen.\r\n\tdisplay_legal();\r\n\tg_legal = true;\r\n}\r\n\r\nvoid NsDisplay::Check60Hz( void )\r\n{\r\n\t// See if the 60Hz menu should be displayed\r\n\tu32 buttons = 0;\r\n\r\n\tNxNgc::EngineGlobals.screen_brightness = 0.0f;\r\n\tfor ( int lp = 0; lp < 4; lp++ )\r\n\t{\r\n\t\tNsDisplay::begin();\r\n\t\tNsRender::begin();\r\n\t\tNsRender::end();\r\n\t\tNsDisplay::end( true );\r\n\r\n\t\tfor ( int i = 0 ; i < PAD_MAX_CONTROLLERS ; i++ )\r\n\t\t{\r\n\t\t\tbuttons |= padData[i].button;\r\n\t\t}\r\n\t}\r\n\r\n\tNxNgc::EngineGlobals.screen_brightness = 1.0f;\r\n\r\n\t// If we press the B button, or we're already in 60hz mode...\r\n\tif ( ( buttons & PAD_BUTTON_B ) || OSGetEuRgb60Mode() )\r\n\t{\r\n\t\twhile ( !( buttons & PAD_BUTTON_A ) )\r\n\t\t{\r\n\t\t\t// Render the text.\r\n\t\t\tNsDisplay::begin();\r\n\t\t\tNsRender::begin();\r\n\r\n\t\t\tNsCamera cam;\r\n\t\t\tcam.orthographic( 0, 0, 640, 448 );\r\n\r\n\t\t\t// Draw the screen.\r\n\t\t\tNsPrim::begin();\r\n\r\n\t\t\tcam.begin();\r\n\r\n\t\t\tGX::SetZMode( GX_FALSE, GX_ALWAYS, GX_TRUE );\r\n\r\n\t\t\tNxNgc::set_blend_mode( NxNgc::vBLEND_MODE_BLEND );\r\n\r\n\t\t\tScript::RunScript( \"ngc_pal60\" );\r\n\r\n\t\t\tNsDisplay::setBackgroundColor( messageColor );\r\n\r\n\t\t\tcam.end();\r\n\r\n\t\t\tNsPrim::end();\r\n\r\n\t\t\tNsRender::end();\r\n\t\t\tNsDisplay::end( true );\r\n\r\n\t\t\tbuttons = Update_input();\r\n\r\n\t\t\tif ( buttons & PAD_BUTTON_DOWN ) selection++;\r\n\t\t\tif ( buttons & PAD_BUTTON_UP ) selection--;\r\n\t\t\tif ( selection < 0 ) selection = 0;\r\n\t\t\tif ( selection >= selection_max ) selection = selection_max - 1;\r\n\t\t}\r\n\t\t// Clear to black.\r\n\t\tNsDisplay::setBackgroundColor( (GXColor){0,0,0,0} );\r\n\t\tNsDisplay::begin();\r\n\t\tNsDisplay::end( true );\r\n\t\tNsDisplay::begin();\r\n\t\tNsDisplay::end( true );\r\n\r\n\t\t// Run the selected script.\r\n\t\tchar buf[32];\r\n\t\tsprintf( buf, \"ngc_selectPAL%d\", selection );\r\n\t\tScript::RunScript( buf );\r\n\t}\r\n\r\n\t// Must display licensed by nintendo screen.\r\n\tdisplay_legal();\r\n\tg_legal = true;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsDisplay\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tInitializes the OS, pad, DVD, video functions from the Nintendo\t*\r\n *\t\t\t\tlibrary, using hwInit(). The display defaults to\t\t\t\t*\r\n *\t\t\t\tGXNtsc480IntDf. Gamma defaults to GX_GM_1_0.\t\t\t\t\t*\r\n *\t\t\t\tTriple buffering is also set up here, with the display turned\t*\r\n *\t\t\t\toff as a default. The display will become visible once the\t\t*\r\n *\t\t\t\tfirst frame has been rendered. This will happen at some point\t*\r\n *\t\t\t\tafter the end() function is called.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsDisplay::init( void )\r\n{\r\n//    GXFifoObj * fifo;\r\n//    GXFifoObj * fifoCPUCurrent;\r\n\r\n#define FIFO_SIZE (256*1024)\r\n#define FIFO_DRAWDONE_TOKEN  0xBEEF\r\n#define FIFO_DRAWING_TOKEN   0xCACE\r\n\r\n\tDbg_MsgAssert ( initCount == 0, ( \"Display module can only be instanced once.\\nThis is the 2nd instance of this class.\\n\" ) );\r\n\tinitCount++;\r\n\r\n\thwInit(NULL);\t\t// Init the OS, game pad, graphics and  video.\r\n\r\n\r\n\r\n\r\n\r\n\r\n//    fifo = (GXFifoObj *)OSAlloc( sizeof(GXFifoObj) );\r\n//\r\n//    // get the default fifo and free it\r\n//    GXSetDrawDone();\r\n//    fifoCPUCurrent = GXGetCPUFifo();\r\n//\r\n//    // allocate new fifos\r\n//    GXInitFifoBase( fifo, OSAlloc(FIFO_SIZE), FIFO_SIZE );\r\n//\r\n//    // set the CPU and GP fifo\r\n//    GXSetCPUFifo( fifo );\r\n//    GXSetGPFifo( fifo );        \r\n//\r\n//    // set a drawdone token in the fifo\r\n//    GXSetDrawSync( FIFO_DRAWDONE_TOKEN );\r\n//\r\n////    // install a callback so we can capture the GP rendering time\r\n////    GXSetDrawDoneCallback( CheckRenderingTime );\r\n//\r\n//    // free the default fifo when we set GP fifo to a different fifo\r\n//    OSFree( GXGetFifoBase(fifoCPUCurrent) );\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\tGX::SetDispCopyGamma( GX_GM_1_0 );\r\n\r\n\tBPSet  = GX_FALSE;\r\n\tBPWait = GX_FALSE;\r\n\tBPGo   = GX_FALSE;\r\n\r\n\tlastVCBToken = 0;\r\n\tnewToken = 1;\r\n\r\n\r\n    init_queue(&RenderQ);\r\n    init_queue(&DoneQ);\r\n\r\n    OSInitThreadQueue( &waitingDoneRender );\r\n\r\n    // Creates a new thread. The thread is suspended by default.\r\n    OSCreateThread(\r\n        &CUThread,                          // ptr to the thread to init\r\n        CleanupThread,               \t\t// ptr to the start routine\r\n        0,                                  // param passed to start routine\r\n        CUThreadStack+sizeof(CUThreadStack),// initial stack address\r\n        sizeof CUThreadStack,\r\n        14,                                 // scheduling priority\r\n        OS_THREAD_ATTR_DETACH);             // detached by default\r\n\r\n    // Starts the thread\r\n    OSResumeThread(&CUThread);\r\n\r\n    myXFB1 = hwFrameBuffer1;\r\n    myXFB2 = hwFrameBuffer2;\r\n    dispXFB = myXFB1;\r\n    copyXFB = myXFB2;\r\n\r\n    (void) VISetPreRetraceCallback(VIPreCallback);\r\n    (void) VISetPostRetraceCallback(VIPostCallback);\r\n    (void) GX::SetBreakPtCallback(BPCallback);\r\n\r\n    // The screen won't actually unblank until the first frame has\r\n    // been displayed (until VIFlush is called and retrace occurs).\r\n    VISetBlack(FALSE);\r\n\r\n\t// This should move to a target/platform module or something...\r\n//\tOSInitFastCast();\r\n\r\n\t// Set XF Stall bug to on.\r\n//\tGXSetMisc( GX_MT_XF_FLUSH, GX_XF_FLUSH_SAFE );\r\n\r\n\t// Create & start the background thread.\r\n\tOSCreateThread(\r\n        &s_bg_thread,                          // ptr to the thread to init\r\n        bg_thread_func,               \t\t// ptr to the start routine\r\n        0,                                  // param passed to start routine\r\n\t\ts_bg_thread_stack+sizeof(s_bg_thread_stack),// initial stack address\r\n        sizeof s_bg_thread_stack,\r\n        14,                                 // scheduling priority\r\n        OS_THREAD_ATTR_DETACH);             // detached by default\r\n\tOSSetAlarm( &s_bg_alarm, OSMillisecondsToTicks( (long long int)( 1000.0f / 60.0f ) ), bg_alarm_handler );\r\n//\tOSResumeThread( &s_bg_thread );\r\n\t}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tbegin\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tCalls hwBeforeRender, which sets up the viewport, and\t\t\t*\r\n *\t\t\t\tinvalidates the vertex and texture cache.\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsDisplay::begin ( void )\r\n{\r\n\tNsDisplay::doReset();\r\n\tif ( inDisplayContext == 1 ) return;\r\n\r\n    hwBeforeRender();\r\n\r\n    // We must keep latency down while still keeping the FIFO full.\r\n    // We allow only two frames to be in the FIFO at once.\r\n\r\n\t// This is a critical section that requires no interrupts to\r\n\t// happen in between the \"if\" and the \"sleep\".  The sleep will\r\n\t// reenable interrupts, allowing one to wake up this thread.\r\n\r\n\tint enabled = OSDisableInterrupts();\r\n\tif (queue_length(&RenderQ) > 1) \r\n\t{\r\n\t\tOSSleepThread( &waitingDoneRender );\r\n\t}\r\n\tOSRestoreInterrupts(enabled);\r\n\t\r\n\t// Read PAD data.\r\n//\tPADRead( padData );\r\n\t\r\n\tinDisplayContext = 1;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tend\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tQueues up the current display list for rendering. Also swaps\t*\r\n *\t\t\t\tthe current draw/display XFB.\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsDisplay::end ( bool clear )\r\n{\r\n\tif ( !gLoadingBarActive ) g_need_to_flush = true;\r\n\r\n    void* tmp_read;\r\n    void* tmp_write;\r\n    NsDisplay_QItem qitm;\r\n    int   enabled;\r\n\r\n\tif ( inDisplayContext == 0 ) return;\r\n\r\n\r\n//\t//************************************\r\n//\r\n//\tGX::SetNumTevStages( 1 );\r\n//\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);\r\n//\tGX::SetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGX::SetNumTexGens( 0 );\r\n//\tGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\tGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\tGX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );\r\n//\tGX::SetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n//\tGX::SetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n//\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\r\n//\tint dc = inDrawingContext;\r\n//\tinDrawingContext = 1;\r\n//\tprofile_gpu.histogram( 32, 32, 96, 96, (GXColor){0,128,255,255} );\r\n//\tinDrawingContext = dc;\r\n//\r\n//\t//************************************\r\n\r\n    // End of frame code:\r\n    GX::Flush();\r\n    \r\n    GX::GetFifoPtrs(GX::GetCPUFifo(), &tmp_read, &tmp_write);\r\n\r\n    // Create new render queue item\r\n    qitm.writePtr = tmp_write;\r\n    qitm.dataPtr = NULL;        // pointer to frame-related user data\r\n    qitm.copyXFB = copyXFB;\r\n    \r\n    // Technically, you can work this such that you don't\r\n    // need the OSDisabled interrupts.  You need to rework\r\n    // the enqueue/dequeue routines a bit, though, to make\r\n    // them non-interfere with each other.\r\n\r\n    enabled = OSDisableInterrupts();\r\n    enqueue(&RenderQ, &qitm);\r\n    OSRestoreInterrupts(enabled);\r\n\r\n    if (BPSet == GX_FALSE) {\r\n    \r\n        BPSet = GX_TRUE;\r\n        GX::EnableBreakPt( tmp_write );\r\n\t\tif ( startCB ) startCB();\r\n//\t\tprofile_gpu.start();\r\n\r\n#ifdef __INFO_REPORT__\r\n\t\tGX::ReadGPMetric( &_p0, &_p1 );\r\n#endif\t\t// __INFO_REPORT__\r\n\r\n#ifdef __INFO_REPORT__\r\n//\t\tGXClearPixMetric();\r\n\t\tGX::SetGPMetric( (GXPerf0)gp0, (GXPerf1)gp1 );\r\n\r\n\t\tGX::ClearGPMetric();\r\n#endif\t\t// __INFO_REPORT__\r\n    }\r\n\r\n    GX::SetDrawSync( newToken );\r\n\t\r\n\t//BEGIN SCREENSHOT CODE\r\n//\tSCREENSHOTService( hwGetCurrentBuffer(), MyAlloc, MyFree );\r\n\t//END SCREENSHOT CODE\r\n\r\n\tu8 newFilter[7];\r\n\t\r\n\tnewFilter[0] = 8 + ( ( g_blur * 24 ) / 8 );\r\n\tnewFilter[1] = 8 - ( ( g_blur * 8 ) / 8 );\r\n\tnewFilter[2] = 10 - ( ( g_blur * 10 ) / 8 );\r\n\tnewFilter[3] = 12 - ( ( g_blur * 12 ) / 8 );\r\n\tnewFilter[4] = 10 - ( ( g_blur * 10 ) / 8 );\r\n\tnewFilter[5] = 8 - ( ( g_blur * 8 ) / 8 );\r\n\tnewFilter[6] = 8 + ( ( g_blur * 24 ) / 8 );\r\n\r\n\tfor ( int i = 0; i < 7; ++i )\r\n\t{\r\n\t\tnewFilter[i] = u8( (float)newFilter[i] * NxNgc::EngineGlobals.screen_brightness );\r\n\t}\r\n\r\n\tGX::SetCopyFilter( rmode->aa, rmode->sample_pattern, GX_TRUE, newFilter );\r\n\tGX::CopyDisp( copyXFB, ( clear ) ? GX_TRUE : GX_FALSE );\r\n\tGX::SetCopyFilter( rmode->aa, rmode->sample_pattern, GX_TRUE, rmode->vfilter );\r\n\t\r\n//\tGXCopyDisp( copyXFB, ( clear ) ? GX_TRUE : GX_FALSE );\r\n\r\n//\tGXCopyDisp( copyXFB, GX_FALSE );\r\n\tGX::Flush();\r\n\r\n#ifdef __INFO_REPORT__\r\n\tframes++;\r\n\tsprintf( &g_gp_info0[gp0*64], \"%s: %9d\", p0_name[gp0], (int)_p0 / frames );\r\n\tsprintf( &g_gp_info1[gp1*64], \"%s: %9d\", p1_name[gp1], (int)_p1 / frames );\r\n//\tif ( ( p0 > 10 ) || ( p1 > 10 ) ) OSReport( \"p0/p1: %8d - %8d\\n\", p0, p1 );\r\n\r\n//\tgp0++;\r\n//\tgp1++;\r\n//\tif ( gp0 >= P0_COUNT ) gp0 = 0;\r\n//\tif ( gp1 >= P1_COUNT ) gp1 = 0;\r\n#endif\t\t// __INFO_REPORT__\r\n\r\n    newToken++;\r\n    copyXFB = (copyXFB == myXFB1) ? myXFB2 : myXFB1;\r\n\r\n\tinDisplayContext = 0;\r\n\r\n\tcurrentBuffer++;\r\n\tif ( currentBuffer == 2 ) currentBuffer = 0;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tsetBackgroundColor\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor\tThe rgba color to set the background to.\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tSets the background color to the specified color. At the\t\t*\r\n *\t\t\t\tbeginning of drawing, the screen is cleared to a specific\t\t*\r\n *\t\t\t\tcolor - it defaults to 0,0,0,0.\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsDisplay::setBackgroundColor ( GXColor color )\r\n{\r\n    GX::SetCopyClear ( color, 0x00ffffff );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tsetRenderStartCallback\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tpCB\tThe callback to set - NULL means no callback.\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tSets up the callback to be called when rendering for a frame\t*\r\n *\t\t\t\tactually begins - note that when you call NsDisplay::begin or\t*\r\n *\t\t\t\tNsDisplay::End bears no relation to when the rendering actually\t*\r\n *\t\t\t\tstarts or stops. This function is intended to be useful for\t\t*\r\n *\t\t\t\tprofiling the performance of the graphics processor.\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsDisplay::setRenderStartCallback ( NsDisplay_StartRenderingCallback pCB )\r\n{\r\n\tstartCB = pCB;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tsetRenderEndCallback\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tpCB\tThe callback to set - NULL means no callback.\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tSets up the callback to be called when rendering for a frame\t*\r\n *\t\t\t\tactually ends - note that when you call NsDisplay::begin or\t\t*\r\n *\t\t\t\tNsDisplay::End bears no relation to when the rendering actually\t*\r\n *\t\t\t\tstarts or stops. This function is intended to be useful for\t\t*\r\n *\t\t\t\tprofiling the performance of the graphics processor.\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsDisplay::setRenderEndCallback ( NsDisplay_EndRenderingCallback pCB )\r\n{\r\n\tendCB = pCB;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tflush\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tWaits for all queued drawing commands to be executed. Use this\t*\r\n *\t\t\t\tif you want to make sure that the graphics processor is not\t\t*\r\n *\t\t\t\treliant upon a piece of memory you want to free up (such as\t\t*\r\n *\t\t\t\trendering a loading screen texture, then freeing it).\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsDisplay::flush ( void )\r\n{\r\n\tif ( !g_need_to_flush ) return;\r\n\tg_need_to_flush = false;\r\n\tfor ( int lp = 0; lp < 3; lp++ ) {\r\n//\t\tbegin();\r\n\t\thwBeforeRender();\r\n\t\t\r\n\t\t// End of frame code:\r\n\t\tGX::Flush();\r\n\r\n\t\tVIWaitForRetrace();\r\n\r\n//\t\tGXGetFifoPtrs(GXGetCPUFifo(), &tmp_read, &tmp_write);\r\n//\r\n//\t\t// Create new render queue item\r\n//\t\tqitm.writePtr = tmp_write;\r\n//\t\tqitm.dataPtr = NULL;        // pointer to frame-related user data\r\n//\t\tqitm.copyXFB = copyXFB;\r\n//\r\n//\t\t// Technically, you can work this such that you don't\r\n//\t\t// need the OSDisabled interrupts.  You need to rework\r\n//\t\t// the enqueue/dequeue routines a bit, though, to make\r\n//\t\t// them non-interfere with each other.\r\n//\r\n//\t\tenabled = OSDisableInterrupts();\r\n//\t\tenqueue(&RenderQ, &qitm);\r\n//\t\tOSRestoreInterrupts(enabled);\r\n//\r\n//\t\tif (BPSet == GX_FALSE) {\r\n//\r\n//\t\t\tBPSet = GX_TRUE;\r\n//\t\t\tGXEnableBreakPt( tmp_write );\r\n//\t\t}\r\n//\r\n//\t\tGXSetDrawSync( newToken );\r\n//\t\tGXCopyDisp( copyXFB, ( clear ) ? GX_TRUE : GX_FALSE );\r\n//\t\tGXFlush();\r\n//\r\n//\t\tnewToken++;\r\n//\t\tcopyXFB = (copyXFB == myXFB1) ? myXFB2 : myXFB1;\r\n\r\n\r\n\t}\r\n\r\n    int enabled = OSDisableInterrupts();\r\n\tcurrentBuffer = 0;\t\t// Current buffer to use for triple buffering.\r\n\tBPSet  = GX_FALSE;\r\n\tBPWait = GX_FALSE;\r\n\tBPGo   = GX_FALSE;\r\n\r\n\tlastVCBToken = 0;\r\n\tnewToken = 1;\r\n    myXFB1 = hwFrameBuffer1;\r\n    myXFB2 = hwFrameBuffer2;\r\n    dispXFB = myXFB1;\r\n    copyXFB = myXFB2;\r\n\r\n    init_queue(&RenderQ);\r\n    init_queue(&DoneQ);\r\n    OSRestoreInterrupts(enabled);\r\n\r\n//\tGXSetDrawDone();\r\n//\tGXWaitDrawDone();\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tgetCurrentBufferIndex\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tGets the current buffer index used for triple buffering.\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nint NsDisplay::getCurrentBufferIndex ( void )\r\n{\r\n\treturn currentBuffer;\r\n}\r\n\r\n\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tshouldReset\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nbool NsDisplay::shouldReset( void )\r\n{\r\n\treturn ( ( resetDown == 2 ) || NxNgc::EngineGlobals.resetToIPL );\r\n}\r\n\r\n\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tdoReset\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n//static volatile bool\tflushComplete;\r\n//\r\n//static void flushCallback( void )\r\n//{\r\n//\tflushComplete = true;\r\n//}\r\n//\r\n\r\n//static void _color( GXColor col )\r\n//{\r\n//\tNsDisplay::setBackgroundColor( col );\r\n//\r\n//\tfor ( int lp = 0; lp < 4; lp++ )\r\n//\t{\r\n//\t\tNsDisplay::begin();\r\n//\t\tNsRender::begin();\r\n//\t\tNsRender::end();\r\n//\t\tNsDisplay::end(true);\r\n//\t}\r\n//}\r\n\r\n#define _color(a,b,c,d)\r\n\r\nvoid NsDisplay::doReset( bool hard_reset, bool forceMenu )\r\n{\r\n\t// Reset has to be enabled for 4 frames to be recognized.\r\n\tif ( reset_enabled_frames < 4 )\r\n\t{\r\n\t\t// Count up if reset is not disabled.\r\n\t\tif ( !NxNgc::EngineGlobals.disableReset )\r\n\t\t{\r\n\t\t\treset_enabled_frames++;\r\n\t\t}\r\n\r\n\t}\r\n\t// If reset is disabled, the counting starts again at 0.\r\n\tif ( NxNgc::EngineGlobals.disableReset )\r\n\t{\r\n\t\treset_enabled_frames = 0;\r\n\t}\r\n\r\n\tif ( NsDisplay::shouldReset() && !NxNgc::EngineGlobals.disableReset && ( reset_enabled_frames == 4 ) )\r\n\t{\r\n//\t\tNsDisplay::doReset(false, false);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t_color( (GXColor){128,128,128,255} );\r\n\r\n\tbool reset = false;\r\n\tbool hard = false;\r\n\tbool force = false;\r\n\t// Reset if we pressed the button, but ony if it's not disabled.\r\n\tif ( NsDisplay::shouldReset() && !NxNgc::EngineGlobals.disableReset )\r\n\t{\r\n\t\tswitch ( DVDError() )\r\n\t\t{\r\n\t\t\tcase DVD_STATE_COVER_OPEN:\r\n\t\t\tcase DVD_STATE_NO_DISK:\r\n\t\t\tcase DVD_STATE_WRONG_DISK:\r\n\t\t\t\t// As per lot-check 4.5.\r\n\t\t\t\treset = true;\r\n\t\t\t\thard = true;\r\n\t\t\t\tforce = false;\r\n//\t\t\t\t\tNsDisplay::doReset( true, false );\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n//\t\t\t\t\tNsDisplay::doReset( false, false );\r\n\t\t\t\treset = true;\r\n\t\t\t\thard = false;\r\n\t\t\t\tforce = false;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( NxNgc::EngineGlobals.resetToIPL )\r\n\t{\r\n//\t\tNsDisplay::doReset( true, true );\r\n\t\treset = true;\r\n\t\thard = true;\r\n\t\tforce = true;\r\n\t}\r\n\r\n\tif ( !reset ) return;\r\n\thard_reset = hard;\r\n\tforceMenu = force;\r\n\r\n//\tDTKFlushTracks( flushCallback );\r\n\t//while( !flushComplete );\r\n\r\n\t_color( (GXColor){128,0,0,255} );\r\n\r\n\t// Recalibrate pads (also stops motor).\r\n\tPADRecalibrate( PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT );\r\n\r\n\t_color( (GXColor){0,128,0,255} );\r\n\tPcm::PCMAudio_StopMusic( true );\r\n//#ifndef DVDETH\r\n//\tDTKFlushTracks( NULL );\r\n//#endif\t\t// DVDETH\r\n\r\n\t_color( (GXColor){0,0,128,255} );\r\n\tVISetBlack( TRUE );\r\n    VIFlush();\r\n    VIWaitForRetrace();\r\n\tNxNgc::EngineGlobals.use_60hz = false;\r\n//\tNsDisplay::setBackgroundColor((GXColor){ 0, 0, 0, 0 });\r\n//\tfor( int i = 0; i < 2; ++i )\r\n//\t{\r\n//\t\tNsDisplay::begin();\r\n//\t\tNsRender::begin();\r\n//\t\tNsRender::end();\r\n//\t\tNsDisplay::end();\r\n//\t}\r\n//\tNsDisplay::flush();\r\n\r\n\t// Determine whether the correct disc is in the drive - if not we need to do a hot reset.\r\n//\tbool disk_okay = DVDCheckDisk();\r\n\r\n\t// Shut down audio libs - flush pending ARQ transfers and wait for DMA to finish.\r\n\t_color( (GXColor){255,0,0,255} );\r\n\tARQFlushQueue();\r\n\t_color( (GXColor){0,255,0,255} );\r\n\twhile( ARGetDMAStatus() != 0 );\r\n\t_color( (GXColor){0,0,255,255} );\r\n\r\n\tAXQuit();\r\n\t_color( (GXColor){255,255,0,255} );\r\n\tAIReset();\r\n\t_color( (GXColor){0,255,255,255} );\r\n\tARQReset();\r\n\t_color( (GXColor){255,255,255,255} );\r\n\tARReset();\r\n\r\n\t_color( (GXColor){255,0,255,255} );\r\n\t\r\n\t// Perform reset.\r\n\tif( hard_reset || forceMenu )\r\n\t{\r\n\t\tOSResetSystem( OS_RESET_HOTRESET, 0, forceMenu ? TRUE : FALSE );\r\n\t\treturn;\r\n\t}\r\n\r\n//\tif( disk_okay )\r\n//\t{\r\n\t\tOSResetSystem( OS_RESET_RESTART, 0, FALSE );\r\n//\t}\t\r\n//\telse\r\n//\t{\r\n//\t\tOSResetSystem( OS_RESET_HOTRESET, 0, FALSE );\r\n//\t}\r\n}\r\n\r\n\r\n\r\n/*---------------------------------------------------------------------------*\r\n   Breakpoint Interrupt Callback\r\n *---------------------------------------------------------------------------*/\r\n\r\nstatic void BPCallback ( void )\r\n{\r\n//\tprofile_gpu.stop();\r\n\r\n    NsDisplay_QItem qitm;\r\n    \r\n    qitm = queue_front(&RenderQ);\r\n\r\n    // Check whether or not the just-finished frame can be\r\n    // copied already or if it must wait (due to lack of a\r\n    // free XFB).  If it must wait, set a flag for the VBlank\r\n    // interrupt callback to take care of it.\r\n\r\n    if (qitm.copyXFB == dispXFB) \r\n    {\r\n        BPWait = GX_TRUE;\r\n    }\r\n    else\r\n    {\r\n\t\tSetNextBreakPt();\r\n    }\r\n\r\n\tif ( endCB ) endCB();\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n   Routine to move breakpoint ahead, deal with finished frames.\r\n *---------------------------------------------------------------------------*/\r\n\r\nstatic void SetNextBreakPt ( void )\r\n{\r\n    NsDisplay_QItem qitm;\r\n\r\n    // Move entry from RenderQ to DoneQ.\r\n\r\n    qitm = dequeue(&RenderQ);\r\n\r\n    enqueue(&DoneQ, &qitm);\r\n\r\n    OSWakeupThread( &waitingDoneRender );\r\n\r\n    // Move breakpoint to next entry, if any.\r\n\r\n    if (queue_empty(&RenderQ))\r\n    {\r\n        GX::DisableBreakPt();\r\n        BPSet = GX_FALSE;\r\n//\t\tprofile_gpu.start();\r\n\t}\r\n    else\r\n    {\r\n        qitm = queue_front(&RenderQ);\r\n        GX::EnableBreakPt( qitm.writePtr );\r\n\t\tif ( startCB ) startCB();\r\n    }\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n   VI Pre Callback (VBlank interrupt)\r\n\r\n   The VI Pre callback should be kept minimal, since the VI registers\r\n   must be set before too much time passes.  Additional bookkeeping is\r\n   done in the VI Post callback.\r\n\r\n *---------------------------------------------------------------------------*/\r\n\r\nstatic void VIPreCallback ( u32 retraceCount )\r\n{\r\n//    #pragma unused (retraceCount)\r\n    u16 token;\r\n\r\n    // We don't need to worry about missed tokens, since \r\n    // the breakpt holds up the tokens, and the logic only\r\n    // allows one token out the gate at a time.\r\n\r\n    token = GX::ReadDrawSync();\r\n\r\n    // We actually need to use only 1 bit from the sync token.\r\n\r\n    if (token == (u16) (lastVCBToken+1))\r\n    {\r\n        lastVCBToken = token;\r\n\r\n        dispXFB = (dispXFB == myXFB1) ? myXFB2 : myXFB1;\r\n\r\n        VISetNextFrameBuffer( dispXFB );\r\n        VIFlush();\r\n\r\n#ifndef DVDETH\r\n\t\t// We swapped the frame buffers. Start audio (if not yet active & waiting)\r\n\t\t// (we make sure we get at most 2 active channels (even if the file has more channels to offer))\r\n\t\t{\r\n\t\t\tstatic const u32 mask[1] = {0x00000003};\r\n\t\t\tVIDSimpleAudioStartPlayback(mask,1);\r\n\t\t}\r\n#endif\t\t// DVDETH\r\n\r\n        BPGo = GX_TRUE;\r\n    }\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n   VI Post Callback (VBlank interrupt)\r\n *---------------------------------------------------------------------------*/\r\n\r\nstatic void VIPostCallback ( u32 retraceCount )\r\n{\r\n//    #pragma unused (retraceCount)\r\n\r\n    if (BPWait && BPGo)\r\n    {\r\n        SetNextBreakPt();\r\n        BPWait = GX_FALSE;\r\n        BPGo = GX_FALSE;\r\n    }\r\n\r\n\t// Read PAD data.\r\n\thwPadRead();\r\n\r\n//\t// Obtain reset button state.\r\n//\tif( resetDown == 0 )\r\n//\t{\r\n//\t\tif( OSGetResetButtonState())\r\n//\t\t{\r\n//\t\t\t// Wait for the button to be released.\r\n//\t\t\tresetDown = 1;\r\n//\t\t}\r\n//\t}\r\n//\telse\r\n\tif( resetDown == 1 )\r\n\t{\r\n\t\tif( !OSGetResetButtonState())\r\n\t\t{\r\n\t\t\t// The button has been released.\r\n\t\t\tresetDown = 2;\r\n\t\t}\r\n\t}\r\n\r\n\tif( pIconCallback )\r\n\t{\r\n\t\tpIconCallback();\r\n\t}\r\n\r\n\t// Call the timer vblank callback.\r\n\tTmr::IncrementVblankCounters();\r\n\r\n\tOSResumeThread( &s_bg_thread );\r\n\r\n\t// Issue DVD callback.\r\n\tfor ( int lp = 0; lp < 8; lp++ )\r\n\t{\r\n\t\tif ( last_callback_counter[lp] == 0 )\r\n\t\t{\r\n\t\t\tlast_callback[lp]( last_callback_length[lp], last_callback_fileInfo[lp] );\r\n\t\t}\r\n\t\tif ( last_callback_counter[lp] >= 0 ) last_callback_counter[lp]--;\r\n\t}\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n   Cleanup Thread\r\n *---------------------------------------------------------------------------*/\r\n\r\nstatic void * CleanupThread ( void* param )\r\n{\r\n//    #pragma unused (param)\r\n    NsDisplay_QItem qitm;\r\n\r\n    while(1) {\r\n\r\n        OSSleepThread( &waitingDoneRender );\r\n        \r\n        qitm = dequeue(&DoneQ);\r\n\r\n        // Take qitm.dataPtr and do any necessary cleanup.\r\n        // That is, free up any data that only needed to be\r\n        // around for the GP to read while rendering the frame.\r\n    }\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n * Quick and dirty queue implementation.\r\n *---------------------------------------------------------------------------*/\r\n\r\nstatic void init_queue(NsDisplay_Queue *q)\r\n{\r\n    q->top = QUEUE_EMPTY;\r\n}\r\n\r\nstatic void enqueue(NsDisplay_Queue *q, NsDisplay_QItem *qitm)\r\n{\r\n    if (q->top == QUEUE_EMPTY) \r\n    {\r\n        q->top = q->bot = 0;\r\n    }\r\n    else\r\n    {\r\n        q->top = (u16) ((q->top+1) % QUEUE_MAX);\r\n    \r\n\t\tDbg_MsgAssert ( q->top != q->bot, ( \"queue overflow\" ) );\r\n    }\r\n    \r\n    q->entry[q->top] = *qitm;\r\n}\r\n\r\nstatic NsDisplay_QItem dequeue(NsDisplay_Queue *q)\r\n{\r\n    u16 bot = q->bot;\r\n\r\n\tDbg_MsgAssert ( q->top != QUEUE_EMPTY, ( \"queue underflow\" ) );\r\n    \r\n    if (q->bot == q->top) \r\n    {\r\n        q->top = QUEUE_EMPTY;\r\n    }\r\n    else\r\n    {\r\n        q->bot = (u16) ((q->bot+1) % QUEUE_MAX);\r\n    }\r\n\r\n    return q->entry[bot];\r\n}\r\n\r\nstatic NsDisplay_QItem queue_front(NsDisplay_Queue *q)\r\n{\r\n\tDbg_MsgAssert ( q->top != QUEUE_EMPTY, ( \"queue empty\" ) );\r\n\r\n    return q->entry[q->bot];\r\n}\r\n\r\nstatic GXBool queue_empty(NsDisplay_Queue *q)\r\n{\r\n    return q->top == QUEUE_EMPTY;\r\n}\r\n\r\nstatic u32 queue_length(NsDisplay_Queue *q)\r\n{\r\n    if (q->top == QUEUE_EMPTY) return 0;\r\n\r\n    if (q->top > q->bot)\r\n        return (u32) ((s32) q->top - q->bot + 1);\r\n    else\r\n        return (u32) ((s32) (q->top + QUEUE_MAX) - q->bot + 1);\r\n}\r\n\r\nstatic void * bg_thread_func ( void* param )\r\n{\r\n//\tint count = 0;\r\n//\tint tick = 0;\r\n\r\n//\tbool waiting_for_reset = false;\r\n\r\n    while( 1 )\r\n\t{\r\n////\r\n////\t\tif ( NsDisplay::shouldReset() && !waiting_for_reset ) {\r\n////\t\tif ( ( NsDisplay::shouldReset() && NxNgc::EngineGlobals.disableReset ) || ( DVDError() && Script::GetInteger( \"allow_dvd_errors\" ) ) && !NxNgc::EngineGlobals.gpuBusy ) {\r\n//\t\tif ( ( DVDError() && Script::GetInteger( \"allow_dvd_errors\" ) ) && !NxNgc::EngineGlobals.gpuBusy ) {\r\n//\t\t\t//OSReport( \"We have to reset now.\\n\" );\r\n//\t\t\twaiting_for_reset = true;\r\n//\r\n//\t\t\tNxNgc::EngineGlobals.screen_brightness = 1.0f;\r\n//\r\n//\t\t\t// Render the text.\r\n//\t\t\tNsDisplay::begin();\r\n//\t\t\tNsRender::begin();\r\n////\t\t\tGX::SetCullMode ( GX_CULL_NONE );\r\n//\r\n//\t\t\tNsCamera cam;\r\n//\t\t\tcam.orthographic( 0, 0, 640, 448 );\r\n//\r\n//\t\t\t// Draw the screen.\r\n//\t\t\tNsPrim::begin();\r\n//\r\n//\t\t\tcam.begin();\r\n//\r\n//\t\t\tGX::SetZMode( GX_FALSE, GX_ALWAYS, GX_TRUE );\r\n//\r\n//\t\t\tNxNgc::set_blend_mode( NxNgc::vBLEND_MODE_ADD );\r\n//\r\n////\t\t\tif ( NsDisplay::shouldReset() )\r\n////\t\t\t{\r\n////\t\t\t\t// Reset message.\r\n////\t\t\t\tScript::RunScript( \"ngc_reset\" );\r\n////\t\t\t}\r\n////\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\t// DVD Error message.\r\n//\t\t\t\tswitch ( DVDError() )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tcase DVD_STATE_FATAL_ERROR:\r\n//\t\t\t\t\tcase DVD_STATE_RETRY:\r\n//\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_fatal\" );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tcase DVD_STATE_COVER_OPEN:\r\n//\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_cover_open\" );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tcase DVD_STATE_NO_DISK:\r\n//\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_no_disk\" );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tcase DVD_STATE_WRONG_DISK:\r\n//\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_wrong_disk\" );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tdefault:\r\n//\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_unknown\" );\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\r\n//\t\t\tNsDisplay::setBackgroundColor( messageColor );\r\n//\r\n//\t\t\tcam.end();\r\n//\r\n//\t\t\tNsPrim::end();\r\n//\r\n//\t\t\tNsRender::end();\r\n//\t\t\tNsDisplay::end( false );\r\n//\r\n//\t\t\t// Notes:\r\n//\t\t\t// Parameters to set in script:\r\n//\t\t\t//\r\n//\t\t\t// reset_font = \"testtitle\"\r\n//\t\t\t// reset_text = \"RESET\"\r\n//\t\t\t// reset_text_col = 255,255,255,255\r\n//\t\t\t// reset_bg_col = 255,0,32,255\r\n//\t\t}\r\n\r\n\t\tif ( !NsDisplay::shouldReset() && !DVDError() ) gLoadBarNumFrames++;\r\n\r\n\t\tif ( gLoadingBarActive && !NxNgc::EngineGlobals.gpuBusy && !NsDisplay::shouldReset() )\r\n\t\t{\r\n\t\t\tNsDisplay::begin();\r\n\t\t\tNsRender::begin();\r\n\t\t\tNsPrim::begin();\r\n\r\n\t\t\tNsCamera camera2D;\r\n\t\t\tcamera2D.orthographic( 0, 0, 640, 448 );\r\n\r\n\t\t\tcamera2D.begin();\r\n\r\n\t\t\tint cur_width = (gLoadBarWidth - 1);\r\n\t\t\tif (gLoadBarNumFrames < gLoadBarTotalFrames)\r\n\t\t\t{\r\n\t\t\t\tcur_width = (cur_width * gLoadBarNumFrames) / gLoadBarTotalFrames;\r\n\t\t\t}\r\n\r\n\t\t\tint x1 = gLoadBarX;\r\n\t\t\tint y1 = gLoadBarY;\r\n\t\t\tint x2 = x1 + cur_width;\r\n\t\t\tint y2 = y1 + (gLoadBarHeight - 1);\r\n\r\n\t\t\tint end_color[4];\r\n\t\t\tif (gLoadBarNumFrames < gLoadBarTotalFrames)\r\n\t\t\t{\r\n\t\t\t\tend_color[0] = gLoadBarStartColor[0] + ((gLoadBarDeltaColor[0] * gLoadBarNumFrames) / gLoadBarTotalFrames);\r\n\t\t\t\tend_color[1] = gLoadBarStartColor[1] + ((gLoadBarDeltaColor[1] * gLoadBarNumFrames) / gLoadBarTotalFrames);\r\n\t\t\t\tend_color[2] = gLoadBarStartColor[2] + ((gLoadBarDeltaColor[2] * gLoadBarNumFrames) / gLoadBarTotalFrames);\r\n\t\t\t\tend_color[3] = gLoadBarStartColor[3] + ((gLoadBarDeltaColor[3] * gLoadBarNumFrames) / gLoadBarTotalFrames);\r\n\t\t\t} else {\r\n\t\t\t\tend_color[0] = gLoadBarStartColor[0] + gLoadBarDeltaColor[0];\r\n\t\t\t\tend_color[1] = gLoadBarStartColor[1] + gLoadBarDeltaColor[1];\r\n\t\t\t\tend_color[2] = gLoadBarStartColor[2] + gLoadBarDeltaColor[2];\r\n\t\t\t\tend_color[3] = gLoadBarStartColor[3] + gLoadBarDeltaColor[3];\r\n\t\t\t}\r\n\r\n\t\t\tint border_x1 = x1 - gLoadBarBorderWidth;\r\n\t\t\tint border_y1 = y1 - gLoadBarBorderHeight;\r\n\t\t\tint border_x2 = x1 + (gLoadBarWidth - 1) + gLoadBarBorderWidth;\r\n\t\t\tint border_y2 = y2 + gLoadBarBorderHeight;\r\n\r\n\t\t\tu32 bc = gLoadBarBorderColor[3]|(gLoadBarBorderColor[2]<<8)|(gLoadBarBorderColor[1]<<16)|(gLoadBarBorderColor[0]<<24);\r\n\t\t\tu32 sc = gLoadBarStartColor[3]|(gLoadBarStartColor[2]<<8)|(gLoadBarStartColor[1]<<16)|(gLoadBarStartColor[0]<<24); \r\n\t\t\tu32 ec = end_color[3]|(end_color[2]<<8)|(end_color[1]<<16)|(end_color[0]<<24);\r\n\r\n\t\t\tGX::SetZMode( GX_FALSE, GX_ALWAYS, GX_FALSE );\r\n\t\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n\t\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_RASA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tGX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n\r\n\t\t\tGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);\r\n\t\t\tGX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );\r\n\t\t\tGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n\t\t\tGX::SetBlendMode( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );\r\n\r\n\t\t\t// Set current vertex descriptor to enable position and color0.\r\n\t\t\t// Both use 8b index to access their data arrays.\r\n\t\t\tGX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\r\n\t\t\t// Set material color.\r\n\t\t\tGX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n\r\n\t\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\r\n\t\t\t// Border\r\n\t\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\t\t\tGX::Position3f32( border_x1, border_y1, -1.0f );\r\n\t\t\t\tGX::Color1u32( bc );\r\n\t\t\t\tGX::Position3f32( border_x1, border_y2, -1.0f );\r\n\t\t\t\tGX::Color1u32( bc );\r\n\t\t\t\tGX::Position3f32( border_x2, border_y2, -1.0f );\r\n\t\t\t\tGX::Color1u32( bc );\r\n\t\t\t\tGX::Position3f32( border_x2, border_y1, -1.0f );\r\n\t\t\t\tGX::Color1u32( bc );\r\n\t\t\tGX::End();\r\n\t\t\t\r\n\t\t\t// Bar\r\n\t\t\tGX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n\t\t\t\tGX::Position3f32( x1, y1, -1.0f );\r\n\t\t\t\tGX::Color1u32( sc );\r\n\t\t\t\tGX::Position3f32( x1, y2, -1.0f );\r\n\t\t\t\tGX::Color1u32( sc );\r\n\t\t\t\tGX::Position3f32( x2, y2, -1.0f );\r\n\t\t\t\tGX::Color1u32( ec );\r\n\t\t\t\tGX::Position3f32( x2, y1, -1.0f );\r\n\t\t\t\tGX::Color1u32( ec );\r\n\t\t\tGX::End();\r\n\r\n\t\t\tcamera2D.end();\r\n\r\n\t\t\tNsPrim::end();\r\n\t\t\tNsRender::end();\r\n\t\t\tNsDisplay::end( false );\r\n\r\n//\t\t\tcurrent_image = ( current_image + 1 ) % p_data->m_NumFrames ;\r\n\t\t}\r\n\r\n\t\t// Vsync callback will resume it.\r\n\t\tOSSuspendThread( &s_bg_thread );\r\n    }\r\n}\r\n\r\nstatic void bg_alarm_handler( OSAlarm* alarm, OSContext* context )\r\n{\r\n\t// Check the thread has not been resumed yet...\r\n\tif( OSIsThreadSuspended( &s_bg_thread ))\r\n\t{\r\n\t\tOSResumeThread( &s_bg_thread );\r\n\t}\r\n}\r\n\r\nvoid display_legal( void )\r\n{\r\n\tNsDisplay::flush();\r\n\r\n\tint frames;\r\n\tif ( !g_legal )\r\n\t{\r\n\t\tframes = 10;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tframes = 2;\r\n\r\n\t}\r\n\r\n\tfor ( int lp = 0; lp < frames; lp++ )\r\n\t{\r\n\t\tif ( g_legal )\r\n\t\t{\r\n\t\t\tNxNgc::EngineGlobals.screen_brightness = 1.0f;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tNxNgc::EngineGlobals.screen_brightness = ( 1.0f * (float)lp ) / (float)frames;\r\n\t\t}\r\n\t\t// Render the text.\r\n\t\tNsDisplay::begin();\r\n\t\tNsRender::begin();\r\n\r\n\t\tNsCamera cam;\r\n\t\tcam.orthographic( 0, 0, 640, 448 );\r\n\r\n\t\t// Draw the screen.\r\n\t\tNsPrim::begin();\r\n\r\n\t\tcam.begin();\r\n\r\n\t\tGX::SetZMode( GX_FALSE, GX_ALWAYS, GX_FALSE );\r\n\r\n\t\tNxNgc::set_blend_mode( NxNgc::vBLEND_MODE_BLEND );\r\n\r\n\t\tScript::RunScript( \"ngc_license\" );\r\n\r\n\t\tNsDisplay::setBackgroundColor( messageColor );\r\n\r\n\t\tcam.end();\r\n\r\n\t\tNsPrim::end();\r\n\r\n\t\tNsRender::end();\r\n\t\tNsDisplay::end( true );\r\n\t}\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\nbool ScriptNgc_BGColor(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tint r = messageColor.r;\r\n\tint g = messageColor.g;\r\n\tint b = messageColor.b;\r\n\tint a = messageColor.a;\r\n\r\n\tpParams->GetInteger(\"r\",&r);\r\n\tpParams->GetInteger(\"g\",&g);\r\n\tpParams->GetInteger(\"b\",&b);\r\n\tpParams->GetInteger(\"a\",&a);\r\n\r\n\tmessageColor.r = r;\r\n\tmessageColor.g = g;\r\n\tmessageColor.b = b;\r\n\tmessageColor.a = a;\r\n\r\n\treturn true;\r\n}\r\n\r\nbool ScriptNgc_Message(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tNxNgc::SText message;\r\n\tNx::CFont * p_cfont;\r\n\tconst char * p_font_name = NULL;\r\n\tconst char * p_text = NULL;\r\n\r\n\tif ( !pParams->GetString( \"font\", &p_font_name ) ) return false;\r\n\tif ( !pParams->GetString( \"text\", &p_text ) ) return false;\r\n\tfloat y = lasty;\r\n\tpParams->GetFloat( \"y\", &y );\r\n\r\n\t// We can only draw a text string if we have a font & a string.\r\n\tif ( p_font_name && p_text )\r\n\t{\r\n\t\tp_cfont = Nx::CFontManager::sGetFont( p_font_name );\r\n\t\tif ( !p_cfont )\r\n\t\t{\r\n\t\t\tNx::CFontManager::sLoadFont( p_font_name );\r\n\t\t\tp_cfont = Nx::CFontManager::sGetFont( p_font_name );\r\n\t\t\tif ( !p_cfont ) return true;\r\n\t\t}\r\n\t\tmessage.mp_string = (char *)p_text;\r\n\r\n\t\tint sr = 128;\r\n\t\tint sg = 128;\r\n\t\tint sb = 128;\r\n\t\tint sa = 255;\r\n\t\tpParams->GetInteger( \"r\", &sr );\r\n\t\tpParams->GetInteger( \"g\", &sg );\r\n\t\tpParams->GetInteger( \"b\", &sb );\r\n\t\tpParams->GetInteger( \"a\", &sa );\r\n\t\tmessage.m_rgba = sa | ( sb << 8 ) | ( sg << 16 ) | ( sr << 24 );\r\n\r\n\t\tNx::CNgcFont * p_nfont = static_cast<Nx::CNgcFont*>( p_cfont );\r\n\t\tNxNgc::SFont * p_font = p_nfont->GetEngineFont();\r\n\t\tmessage.mp_font = p_font;\r\n\t\tfloat w, h;\r\n\t\tif ( p_font )\r\n\t\t{\r\n\t\t\tfloat x = 0.0f;\r\n\t\t\tmessage.m_ypos = y;\r\n\t\t\tfloat scale = 1.0f;\r\n\t\t\tpParams->GetFloat( \"scale\", &scale );\r\n\t\t\tmessage.m_xscale = scale;\r\n\t\t\tmessage.m_yscale = scale;\r\n\t\t\tmessage.m_color_override = false;\r\n\r\n\t\t\tp_font->QueryString( message.mp_string, w, h );\r\n\t\t\tif ( pParams->GetFloat( \"x\", &x ) )\r\n\t\t\t{\r\n\t\t\t\tmessage.m_xpos = x;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmessage.m_xpos = ( 640.0f - ( w * scale ) ) / 2.0f;\r\n\t\t\t}\r\n\t\r\n\t\t\tfloat appendx = 0.0f;\r\n\t\t\tfloat appendy = 0.0f;\r\n\t\t\tbool append = false;\r\n\t\t\tif ( pParams->GetFloat( \"appendx\", &appendx ) || pParams->GetFloat( \"appendy\", &appendy ) )\r\n\t\t\t{\r\n\t\t\t\tappend = true;\r\n\t\t\t\tpParams->GetFloat( \"appendx\", &appendx );\r\n\t\t\t\tpParams->GetFloat( \"appendy\", &appendy );\r\n\t\t\t\tmessage.m_xpos = prevx + appendx;\r\n\t\t\t\tmessage.m_ypos = prevy + appendy;\r\n\t\t\t}\r\n\r\n\t\t\tmessage.DrawSingle();\r\n\t\r\n\t\t\tprevx = message.m_xpos + ( w * scale );\r\n\t\t\tprevy = y;\r\n\r\n\t\t\tif ( !append )\r\n\t\t\t{\r\n\t\t\t\tlasty = y + (float)((int)( h * scale ));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool ScriptNgc_Menu(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tNxNgc::SText message;\r\n\tNx::CFont * p_cfont;\r\n\tconst char * p_font_name = NULL;\r\n\tint items = 0;\r\n\tconst char * p_item;\r\n\tchar buf[32];\r\n\tint sr = 128;\r\n\tint sg = 128;\r\n\tint sb = 128;\r\n\tint sa = 255;\r\n\tint ur = 128;\r\n\tint ug = 128;\r\n\tint ub = 128;\r\n\tint ua = 255;\r\n\r\n\tpParams->GetString( \"font\", &p_font_name );\r\n\tpParams->GetInteger( \"items\", &items );\r\n\tpParams->GetInteger( \"sr\", &sr );\r\n\tpParams->GetInteger( \"sg\", &sg );\r\n\tpParams->GetInteger( \"sb\", &sb );\r\n\tpParams->GetInteger( \"sa\", &sa );\r\n\tpParams->GetInteger( \"ur\", &ur );\r\n\tpParams->GetInteger( \"ug\", &ug );\r\n\tpParams->GetInteger( \"ub\", &ub );\r\n\tpParams->GetInteger( \"ua\", &ua );\r\n\r\n\t// We can only draw a text string if we have a font & a string.\r\n\tif ( p_font_name && items )\r\n\t{\r\n\t\tNx::CFontManager::sLoadFont( p_font_name );\r\n\t\tp_cfont = Nx::CFontManager::sGetFont( p_font_name );\r\n\r\n\t\tfor ( int lp = 0; lp < items; lp++ )\r\n\t\t{\r\n\t\t\tp_item = NULL;\r\n\t\t\tsprintf( buf, \"item%d\", lp );\r\n\t\t\tpParams->GetString( buf, &p_item );\r\n\r\n\t\t\tif ( p_item )\r\n\t\t\t{\r\n\t\t\t\tmessage.mp_string = (char *)p_item;\r\n\r\n\t\t\t\tfloat scale = 1.0f;\r\n\t\t\t\tpParams->GetFloat( \"scale\", &scale );\r\n\r\n\t\t\t\tif ( lp == selection )\r\n\t\t\t\t{\r\n\t\t\t\t\tmessage.m_rgba = sa | ( sb << 8 ) | ( sg << 16 ) | ( sr << 24 );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tmessage.m_rgba = ua | ( ub << 8 ) | ( ug << 16 ) | ( ur << 24 );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tNx::CNgcFont * p_nfont = static_cast<Nx::CNgcFont*>( p_cfont );\r\n\t\t\t\tNxNgc::SFont * p_font = p_nfont->GetEngineFont();\r\n\t\t\t\tmessage.mp_font = p_font;\r\n\t\t\t\tfloat w, h;\r\n\t\t\t\tp_font->QueryString( message.mp_string, w, h );\r\n\t\t\t\tmessage.m_xpos = ( 640.0f - ( w * scale ) ) / 2.0f;\r\n\t\t\t\tmessage.m_ypos = lasty;\r\n\t\t\t\tmessage.m_xscale = scale;\r\n\t\t\t\tmessage.m_yscale = scale;\r\n\t\t\t\tmessage.m_color_override = false;\r\n\r\n\t\t\t\tmessage.DrawSingle();\r\n\r\n\t\t\t\tlasty += (float)((int)( h * scale ));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tselection_max = items;\r\n\r\n\treturn true;\r\n}\r\n\r\nbool ScriptNgc_Set480P(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tOSSetProgressiveMode(1);\r\n\tNxNgc::EngineGlobals.use_480p = true;\r\n\thwReInit( NULL );\r\n\r\n\t// Must display screen saying that progressive mode has been set.\r\n\tfor ( int lp = 0; lp < 240; lp++ )\r\n\t{\r\n\t\t// Render the text.\r\n\t\tNsDisplay::begin();\r\n\t\tNsRender::begin();\r\n\r\n\t\tNsCamera cam;\r\n\t\tcam.orthographic( 0, 0, 640, 448 );\r\n\r\n\t\t// Draw the screen.\r\n\t\tNsPrim::begin();\r\n\r\n\t\tcam.begin();\r\n\r\n\t\tGX::SetZMode( GX_FALSE, GX_ALWAYS, GX_TRUE );\r\n\r\n\t\tNxNgc::set_blend_mode( NxNgc::vBLEND_MODE_BLEND );\r\n\r\n\t\tif ( lp > 60 ) Script::RunScript( \"ngc_progressive\" );\r\n\r\n\t\tNsDisplay::setBackgroundColor( messageColor );\r\n\r\n\t\tcam.end();\r\n\r\n\t\tNsPrim::end();\r\n\r\n\t\tNsRender::end();\r\n\t\tNsDisplay::end( true );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool ScriptNgc_Set480I(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\t// Already in 480I to display menu. Just set the SRAM bit.\r\n\tOSSetProgressiveMode(0);\r\n\r\n\treturn true;\r\n}\r\n\r\nbool ScriptNgc_Set60Hz(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tOSSetEuRgb60Mode(1);\r\n\tNxNgc::EngineGlobals.use_60hz = true;\r\n\thwReInit( NULL );\r\n\r\n\thwGXInit();\r\n    VIConfigure(rmode);\r\n\r\n\tConfig::gFPS = 60;\r\n\r\n\t// Must display screen saying that 60hz mode has been set.\r\n\tfor ( int lp = 0; lp < 240; lp++ )\r\n\t{\r\n\t\t// Render the text.\r\n\t\tNsDisplay::begin();\r\n\t\tNsRender::begin();\r\n\r\n\t\tNsCamera cam;\r\n\t\tcam.orthographic( 0, 0, 640, 448 );\r\n\r\n\t\t// Draw the screen.\r\n\t\tNsPrim::begin();\r\n\r\n\t\tcam.begin();\r\n\r\n\t\tGX::SetZMode( GX_FALSE, GX_ALWAYS, GX_TRUE );\r\n\r\n\t\tNxNgc::set_blend_mode( NxNgc::vBLEND_MODE_BLEND );\r\n\r\n\t\tif ( lp > 60 ) Script::RunScript( \"ngc_60Hz\" );\r\n\r\n\t\tNsDisplay::setBackgroundColor( messageColor );\r\n\r\n\t\tcam.end();\r\n\r\n\t\tNsPrim::end();\r\n\r\n\t\tNsRender::end();\r\n\t\tNsDisplay::end( true );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool ScriptNgc_Set50Hz(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tOSSetEuRgb60Mode(0);\r\n\tNxNgc::EngineGlobals.use_60hz = false;\r\n\r\n\tConfig::gFPS = 50;\r\n\r\n\t// Must display screen saying that 50hz mode has been set.\r\n\tfor ( int lp = 0; lp < 240; lp++ )\r\n\t{\r\n\t\t// Render the text.\r\n\t\tNsDisplay::begin();\r\n\t\tNsRender::begin();\r\n\r\n\t\tNsCamera cam;\r\n\t\tcam.orthographic( 0, 0, 640, 448 );\r\n\r\n\t\t// Draw the screen.\r\n\t\tNsPrim::begin();\r\n\r\n\t\tcam.begin();\r\n\r\n\t\tGX::SetZMode( GX_FALSE, GX_ALWAYS, GX_TRUE );\r\n\r\n\t\tNxNgc::set_blend_mode( NxNgc::vBLEND_MODE_BLEND );\r\n\r\n\t\tif ( lp > 60 ) Script::RunScript( \"ngc_50Hz\" );\r\n\r\n\t\tNsDisplay::setBackgroundColor( messageColor );\r\n\r\n\t\tcam.end();\r\n\r\n\t\tNsPrim::end();\r\n\r\n\t\tNsRender::end();\r\n\t\tNsDisplay::end( true );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool ScriptNgc_SetWide(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tNxNgc::EngineGlobals.use_widescreen = true;\r\n\r\n\treturn true;\r\n}\r\n\r\nbool ScriptNgc_SetStandard(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tNxNgc::EngineGlobals.use_widescreen = false;\r\n\r\n\treturn true;\r\n}\r\n\r\nbool ScriptNgc_ReduceColors(Script::CScriptStructure *pParams, Script::CScript *pScript)\r\n{\r\n\tbool truth;\r\n\tif ( pParams->GetInteger( NONAME, (int*)&truth ) )\r\n\t{\r\n\t\tNxNgc::EngineGlobals.reduceColors = truth;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n}\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_display.h",
    "content": "#ifndef _DISPLAY_H_\r\n#define _DISPLAY_H_\r\n\r\ntypedef void (*NsDisplay_StartRenderingCallback)(void);\r\ntypedef void (*NsDisplay_EndRenderingCallback)(void);\r\n\r\nnamespace NsDisplay\r\n{\r\n\tvoid\t\t\tinit\t\t\t\t\t( void );\r\n\r\n\tvoid\t\t\tbegin\t\t\t\t\t( void );\r\n\tvoid\t\t\tend\t\t\t\t\t\t( bool clear = true );\r\n\r\n\tvoid\t\t\tsetBackgroundColor\t\t( GXColor color );\r\n\r\n\tvoid\t\t\tsetRenderStartCallback\t( NsDisplay_StartRenderingCallback pCB );\r\n\tvoid\t\t\tsetRenderEndCallback\t( NsDisplay_EndRenderingCallback pCB );\r\n\r\n\tvoid\t\t\tflush\t\t\t\t\t( void );\r\n\r\n\tint\t\t\t\tgetCurrentBufferIndex\t( void );\r\n\r\n\tbool\t\t\tshouldReset\t\t\t\t( void );\r\n\tvoid\t\t\tdoReset\t\t\t\t\t( bool hard_reset = false, bool forceMenu = false );\r\n\r\n\tvoid\t\t\tCheck480P\t\t\t\t( void );\r\n\tvoid\t\t\tCheck60Hz\t\t\t\t( void );\r\n};\r\n\r\nvoid display_legal( void );\r\n\r\nnamespace Script\r\n{\r\n\tclass CScriptStructure;\r\n\tclass CScript;\r\n}\r\n\r\nnamespace Nx\r\n{\r\n\r\nbool ScriptNgc_BGColor(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptNgc_Message(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptNgc_Menu(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptNgc_Set480P(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptNgc_Set480I(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptNgc_Set60Hz(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptNgc_Set50Hz(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptNgc_SetWide(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptNgc_SetStandard(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\nbool ScriptNgc_ReduceColors(Script::CScriptStructure *pParams, Script::CScript *pScript);\r\n\r\n}\r\n\r\n#endif\t\t// _DISPLAY_H_\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_dl.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tDL\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tObject container for a pre-built display list.\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include <math.h>\r\n//#include \"p_dl.h\"\r\n//#include \"p_prim.h\"\r\n//#include \"p_render.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tupload\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tpTex\tPointer to the texture to upload.\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tUploads the specified texture.\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n////int\tNsCollision::findCollision\t( NsSphere * pSphere, NsCollision_SphereCallback pCb, void * pData );\r\n//int\tNsDL::findCollision( NsLine * pLine, NsDL::Collision_LineCallback pCb, void * pData )\r\n//\r\n//{\r\n//\tunsigned int\t\t\tlp;\r\n//\tint\t\t\t\t\t\tresult;\r\n//\tint\t\t\t\t\t\trv = 0;\r\n//\tNsTriangle\t\t\t\tct;\r\n//\tfloat\t\t\t\t\tdistance;\r\n//\tNsCollisionTriangle\t\ttri;\r\n//\tNsBBox\t\t\t\t\tline;\r\n//\tunsigned short\t\t  * pConnect;\r\n//\r\n//\tline.m_min.x = pLine->start.x < pLine->end.x ? pLine->start.x : pLine->end.x;\r\n//\tline.m_min.y = pLine->start.y < pLine->end.y ? pLine->start.y : pLine->end.y;\r\n//\tline.m_min.z = pLine->start.z < pLine->end.z ? pLine->start.z : pLine->end.z;\r\n//\tline.m_max.x = pLine->start.x > pLine->end.x ? pLine->start.x : pLine->end.x;\r\n//\tline.m_max.y = pLine->start.y > pLine->end.y ? pLine->start.y : pLine->end.y;\r\n//\tline.m_max.z = pLine->start.z > pLine->end.z ? pLine->start.z : pLine->end.z;\r\n//\r\n//\tpConnect = getConnectList();\r\n//\t// Calculate the intersection on each triangle.\r\n//\tfor ( lp = 0; lp < m_numPoly; lp++ ) {\r\n//\t\t// Build the collision triangle.\r\n//\t\ttri.vertices[0] = getVertex( *pConnect++ );\r\n//\t\ttri.vertices[1] = getVertex( *pConnect++ );\r\n//\t\ttri.vertices[2] = getVertex( *pConnect++ );\r\n//\t\t*ct.corner( 0 ) = *tri.vertices[0];\r\n//\t\t*ct.corner( 1 ) = *tri.vertices[1];\r\n//\t\t*ct.corner( 2 ) = *tri.vertices[2];\r\n//\r\n//\t\t// First, see if bounding box passes.\r\n//\t\tif (\t( ct.corner(0)->x > line.m_max.x ) &&\r\n//\t\t\t\t( ct.corner(1)->x > line.m_max.x ) &&\r\n//\t\t\t\t( ct.corner(2)->x > line.m_max.x ) ) continue;\r\n//\t\tif (\t( ct.corner(0)->x < line.m_min.x ) &&\r\n//\t\t\t\t( ct.corner(1)->x < line.m_min.x ) &&\r\n//\t\t\t\t( ct.corner(2)->x < line.m_min.x ) ) continue;\r\n//\t\tif (\t( ct.corner(0)->y > line.m_max.y ) &&\r\n//\t\t\t\t( ct.corner(1)->y > line.m_max.y ) &&\r\n//\t\t\t\t( ct.corner(2)->y > line.m_max.y ) ) continue;\r\n//\t\tif (\t( ct.corner(0)->y < line.m_min.y ) &&\r\n//\t\t\t\t( ct.corner(1)->y < line.m_min.y ) &&\r\n//\t\t\t\t( ct.corner(2)->y < line.m_min.y ) ) continue;\r\n//\t\tif (\t( ct.corner(0)->z > line.m_max.z ) &&\r\n//\t\t\t\t( ct.corner(1)->z > line.m_max.z ) &&\r\n//\t\t\t\t( ct.corner(2)->z > line.m_max.z ) ) continue;\r\n//\t\tif (\t( ct.corner(0)->z < line.m_min.z ) &&\r\n//\t\t\t\t( ct.corner(1)->z < line.m_min.z ) &&\r\n//\t\t\t\t( ct.corner(2)->z < line.m_min.z ) ) continue;\r\n//\r\n//\t\t// Now, do triangle test.\r\n//\t\tresult = pLine->intersectTriangle( &distance, &ct );\r\n//\t\t// If triangle intersection hapenned, deal with it.\r\n//\t\tif ( result ) {\r\n//\t\t\trv = 1;\r\n//\t\t\t// Create triangle data.\r\n//\t\t\tNsVector l10;\r\n//\t\t\tNsVector l20;\r\n//\t\t\tl10.sub( *ct.corner(1), *ct.corner(0) );\r\n//\t\t\tl20.sub( *ct.corner(2), *ct.corner(0) );\r\n//\t\t\ttri.normal.cross( l10, l20 );\r\n//\t\t\ttri.normal.normalize();\r\n//\r\n////\t\t\ttri.normal.set( 0.0f, 1.0f, 0.0f );\r\n//\t\t\ttri.point.set( tri.vertices[0]->x, tri.vertices[0]->y, tri.vertices[0]->z );\r\n//\t\t\ttri.index\t\t= lp;\r\n//\t\t\t// Execute callback.\r\n//\t\t\tif ( pCb ) pCb( pLine, *this, &tri, distance, pData );\r\n//\r\n//\r\n////RpCollisionTriangle *world_collision_cb( RpIntersection *is, \r\n////                 NsWorldSector *sector,\r\n////                 RpCollisionTriangle *collPlane,\r\n////                 RwReal &distance,\r\n////                 void *data )\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n//\r\n////\t\t\tif ( NsPrim::begun() ) {\r\n////\t\t\t\tNsVector\tr;\r\n////\t\t\t\t// Calculate intersection point.\r\n////\t\t\t\tr.sub( *&pLine->end, *&pLine->start );\r\n////\t\t\t\tr.x = ( r.x * distance ) + pLine->start.x;\r\n////\t\t\t\tr.y = ( r.y * distance ) + pLine->start.y;\r\n////\t\t\t\tr.z = ( r.z * distance ) + pLine->start.z;\r\n////\t\t\t\t// Draw a collision cross.\r\n////\t\t\t\tNsRender::setBlendMode( NsBlendMode_None, NULL, (unsigned char)0 );\r\n////\t\t\t\tNsPrim::line( r.x, r.y, r.z, r.x+25.0f, r.y, r.z,       (GXColor){255,0,0,255} );\r\n////\t\t\t\tNsPrim::line( r.x, r.y, r.z, r.x-25.0f, r.y, r.z,       (GXColor){255,0,0,255} );\r\n////\t\t\t\tNsPrim::line( r.x, r.y, r.z, r.x,       r.y, r.z+25.0f, (GXColor){255,0,0,255} );\r\n////\t\t\t\tNsPrim::line( r.x, r.y, r.z, r.x,       r.y, r.z-25.0f, (GXColor){255,0,0,255} );\r\n////\r\n////\t\t\t\tNsPrim::line(\r\n////\t\t\t\t\tct.corner(0)->x, ct.corner(0)->y, ct.corner(0)->z,\r\n////\t\t\t\t\tct.corner(1)->x, ct.corner(1)->y, ct.corner(1)->z,\r\n////\t\t\t\t\t(GXColor){0,255,0,255} );\r\n////\t\t\t\tNsPrim::line(\r\n////\t\t\t\t\tct.corner(1)->x, ct.corner(1)->y, ct.corner(1)->z,\r\n////\t\t\t\t\tct.corner(2)->x, ct.corner(2)->y, ct.corner(2)->z,\r\n////\t\t\t\t\t(GXColor){0,255,0,255} );\r\n////\t\t\t\tNsPrim::line(\r\n////\t\t\t\t\tct.corner(2)->x, ct.corner(2)->y, ct.corner(2)->z,\r\n////\t\t\t\t\tct.corner(0)->x, ct.corner(0)->y, ct.corner(0)->z,\r\n////\t\t\t\t\t(GXColor){0,255,0,255} );\r\n////\t\t\t\tNsPrim::line(\r\n////\t\t\t\t\tct.corner(0)->x, ct.corner(0)->y, ct.corner(0)->z,\r\n////\t\t\t\t\tct.corner(0)->x+tri.normal.x, ct.corner(0)->y+tri.normal.y, ct.corner(0)->z+tri.normal.z,\r\n////\t\t\t\t\t(GXColor){0,255,0,255} );\r\n////\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\treturn rv;\r\n//}\r\n//\r\n//int NsDL::cull ( NsMatrix * m )\r\n//{\r\n//\tint\t\t\t\tlp;\r\n//\tunsigned int\tcode;\r\n//\tunsigned int\tcodeAND;\r\n//\tf32\t\t\t\trx[8], ry[8], rz[8];\r\n//\tf32\t\t\t\tp[GX_PROJECTION_SZ];\r\n//\tf32\t\t\t\tvp[GX_VIEWPORT_SZ];\r\n//\tu32\t\t\t\tclip_x;\r\n//\tu32\t\t\t\tclip_y;\r\n//\tu32\t\t\t\tclip_w;\r\n//\tu32\t\t\t\tclip_h;\r\n//\tfloat\t\t\tclip_l;\r\n//\tfloat\t\t\tclip_t;\r\n//\tfloat\t\t\tclip_r;\r\n//\tfloat\t\t\tclip_b;\r\n//\tMtxPtr\t\t\tview;\r\n//\tfloat\t\t\tminx, miny, minz;\r\n//\tfloat\t\t\tmaxx, maxy, maxz;\r\n//\r\n//\tGXGetProjectionv( p );\r\n//\tGXGetViewportv( vp );\r\n//\tGXGetScissor ( &clip_x, &clip_y, &clip_w, &clip_h );\r\n//\tclip_l = (float)clip_x;\r\n//\tclip_t = (float)clip_y;\r\n//\tclip_r = (float)(clip_x + clip_w);\r\n//\tclip_b = (float)(clip_y + clip_h);\r\n//\r\n//\tview = m->m_matrix;\r\n//\r\n//\tminx = m_cull.box.m_min.x;\r\n//\tminy = m_cull.box.m_min.y;\r\n//\tminz = m_cull.box.m_min.z;\r\n//\tmaxx = m_cull.box.m_max.x;\r\n//\tmaxy = m_cull.box.m_max.y;\r\n//\tmaxz = m_cull.box.m_max.z;\r\n//\tGXProject ( minx, miny, minz, view, p, vp, &rx[0], &ry[0], &rz[0] );\r\n//\tGXProject ( minx, maxy, minz, view, p, vp, &rx[1], &ry[1], &rz[1] );\r\n//\tGXProject ( maxx, miny, minz, view, p, vp, &rx[2], &ry[2], &rz[2] );\r\n//\tGXProject ( maxx, maxy, minz, view, p, vp, &rx[3], &ry[3], &rz[3] );\r\n//\tGXProject ( minx, miny, maxz, view, p, vp, &rx[4], &ry[4], &rz[4] );\r\n//\tGXProject ( minx, maxy, maxz, view, p, vp, &rx[5], &ry[5], &rz[5] );\r\n//\tGXProject ( maxx, miny, maxz, view, p, vp, &rx[6], &ry[6], &rz[6] );\r\n//\tGXProject ( maxx, maxy, maxz, view, p, vp, &rx[7], &ry[7], &rz[7] );\r\n//\tm_cull.visible = 1;\r\n//\r\n//\t// Generate clip code. {page 178, Procedural Elements for Computer Graphics}\r\n//\t// 1001|1000|1010\r\n//\t//     |    |\r\n//\t// ----+----+----\r\n//\t// 0001|0000|0010\r\n//\t//     |    |\r\n//\t// ----+----+----\r\n//\t// 0101|0100|0110\r\n//\t//     |    |\r\n//\t//\r\n//\t// Addition: Bit 4 is used for z behind.\r\n//\r\n//\tcodeAND\t= 0x001f;\r\n//\tfor ( lp = 0; lp < 8; lp++ ) {\r\n//\t\t// Only check x/y if z is valid (if z is invalid, the x/y values will be garbage).\r\n//\t\tif ( rz[lp] > 1.0f   ) {\r\n//\t\t\tcode = (1<<4);\r\n//\t\t} else {\r\n//\t\t\tcode = 0;\r\n//\t\t\tif ( rx[lp] < clip_l ) code |= (1<<0);\r\n//\t\t\tif ( rx[lp] > clip_r ) code |= (1<<1);\r\n//\t\t\tif ( ry[lp] > clip_b ) code |= (1<<2);\r\n//\t\t\tif ( ry[lp] < clip_t ) code |= (1<<3);\r\n//\t\t}\r\n//\t\tcodeAND\t&= code;\r\n//\t}\r\n//\tm_cull.clipCodeAND = codeAND;\r\n//\t// If any bits are set in the AND code, the object is invisible.\r\n//\tif ( codeAND ) {\r\n//\t\tm_cull.visible = 0;\r\n//\t}\r\n//\t\r\n//\treturn !m_cull.visible;\t\t// 0 = not culled, 1 = culled.\r\n//}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_dl.h",
    "content": "//#ifndef _DL_H_\r\n//#define _DL_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_frame.h\"\r\n//#include \"p_matrix.h\"\r\n//#include \"p_bbox.h\"\r\n//#include \"p_triangle.h\"\r\n//\r\n//typedef struct NsCull_Item NsCull_Item;\r\n//struct NsCull_Item {\r\n//\tNsBBox\t\t\tbox;\t\t\t\t// 24\r\n//\tunsigned int\tvisible;\t\t\t// 4\r\n//\tunsigned short\tclipCodeAND;\t\t// 2\r\n//\tunsigned short\tclipCodeOR;\t\t\t// 2\r\n//};\t\t\t\t\t\t\t\t\t\t// Total: 32*/\r\n//\r\n//typedef struct {\r\n//    NsVector\tnormal; /**< Triangle normal */\r\n//    NsVector\tpoint;  /**< First triangle vertex */\r\n//    int\t\t\tindex;  /**< Index of triangle in object (if applicable) */\r\n//    NsVector  * vertices[3]; /**< Pointers to three triangle vertices */\r\n//} NsCollisionTriangle;\r\n//\r\n//class NsDL\r\n//{\r\n//public:\r\n//\ttypedef NsCollisionTriangle *(*Collision_LineCallback)( NsLine * line, NsDL& pDL, NsCollisionTriangle * tri, float distance, void * pData );\r\n//\ttypedef NsCollisionTriangle *(*Collision_SphereCallback)( NsSphere * line, NsDL& pDL, NsCollisionTriangle * tri, float distance, void * pData );\r\n//\r\n//\tunsigned int\tm_id;\t\t\t// 4\r\n//\tunsigned int\tm_size;\t\t\t// 4\r\n//\tNsDL\t\t  * m_pNext;\t\t// 4\r\n//\tunsigned short\tm_flags;\t\t// 2 - Geometry Flags.\r\n//\tunsigned short\tm_rwflags;\t\t// 2 - Renderware Flags.\r\n//\r\n//\tNsVector\t  * m_pVertexPool;\t// 4\r\n//\tunsigned int\tm_numVertex;\t// 4\r\n//\tunsigned short\tm_numPoly;\t\t// 2\r\n//\tunsigned short\tm_numIdx;\t\t// 2 - number of indices in this DL\r\n//\tunsigned char * m_pWibbleData;\t// 4\r\n//\r\n//\tNsDL\t\t  * m_pParent;\t\t// 4 - Next geometry chunk.\r\n//\tNsFrame\t\t  * m_pFrame;\t\t// 4 - Instance information\r\n//\tunsigned short* m_pFaceFlags;\t// 4 - Per polygon flag data.\r\n//\tunsigned short* m_pFaceMaterial;// 4 - Per polygon material number.\r\n//\r\n//\tunsigned short\tm_polyBase;\t\t// 2 - The first poly index in this DL.\r\n//\tunsigned short\tm_vpoolFlags;\t// 2 - describes the vertex pool and following pools\r\n//\tunsigned int\tm_operationID;\t// 4 - Mirrors the NxPlugin data field for world sectors.\t\r\n//\tvoid\t\t  * m_pMaterialMan;\t// 4 - Pointer back to the material manager this DL uses.\r\n////\tNsDL\t\t  * m_pChild;\t\t// 4 - Next geometry chunk.\r\n//\tunsigned short\tm_vertBase;\t\t// 2 - The first vert index in this DL.\r\n//\tunsigned short\tm_vertRange;\t// 2 - The range of verts in this DL.\r\n//\r\n//\tNsCull_Item\t\tm_cull;\t\t\t// 32\r\n//\r\n//\tint\t\t\t\tfindCollision\t( NsLine * pLine, Collision_LineCallback pCb, void * pData );\r\n//\tint\t\t\t\tfindCollision\t( NsSphere * pSphere, Collision_SphereCallback pCb, void * pData );\r\n//\r\n//\tNsVector\t  * getVertexPool\t( void ) { return m_pVertexPool; }\r\n//\tNsVector\t  * getNormalPool\t( void ) { return m_vpoolFlags & (1<<1) ? &m_pVertexPool[1] : NULL; }\r\n//\tunsigned int  * getColorPool\t( void ) { return m_vpoolFlags & (1<<2) ? (unsigned int *)&m_pVertexPool[getStride() * m_numVertex + 1] : NULL; }\r\n//\tfloat\t\t  * getUVPool\t\t( void ) { return m_vpoolFlags & (1<<3) ? getColorPool() ? (float *)&getColorPool()[m_numVertex] : (float *)&m_pVertexPool[getStride() * m_numVertex + 1] : NULL; }\r\n//\tunsigned short* getConnectList\t( void ) { return m_vpoolFlags & (1<<3) ? getUVPool() ? (unsigned short *)&getUVPool()[m_numVertex * 2] : getColorPool() ? (unsigned short *)&getColorPool()[m_numVertex] : (unsigned short *)&m_pVertexPool[getStride() * m_numVertex + 1] : NULL; }\r\n//\tint\t\t\t\tgetStride\t\t( void ) { return ( m_vpoolFlags & (1<<1) ? 2 : 1 ); }\r\n//\r\n//\tNsVector\t  * getVertex\t\t( int index ) { return &getVertexPool()[index*getStride()]; }\r\n//\r\n//\tunsigned int  * getWibbleColor\t( void ) { return (unsigned int *)m_pWibbleData; }\r\n//\tunsigned char * getWibbleIdx\t( void ) { return &m_pWibbleData[m_numVertex*4]; }\r\n//\tunsigned char * getWibbleOff\t( void ) { return &m_pWibbleData[m_numVertex*5]; }\r\n//\r\n//\tint\t\t\t\tcull\t\t\t( NsMatrix * m );\r\n//};\r\n//\r\n//#endif\t\t// _DL_H_\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_dlman.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsDLMan\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tManages a buffer for building display lists to.\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include <math.h>\r\n//#include \"p_dlman.h\"\r\n//#include \"p_assert.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#define DEFAULT_DLMAN_SIZE (1024*1024*2)\t\t// 2mb default.\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsDLMan\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tInstances a Display List manager to the default Display List\t*\r\n// *\t\t\t\tsize of 2mb.\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsDLMan::NsDLMan()\r\n//{\r\n//\tNsDLMan ( DEFAULT_DLMAN_SIZE );\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tTexMan\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tInstances a Display List manager to a user-specified buffer\t\t*\r\n// *\t\t\t\tsize.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsDLMan::NsDLMan ( int size )\r\n//{\r\n//\tchar  * p;\r\n//\r\n//\tm_pDLBufferCurrent = m_pDLBufferStart = new unsigned char[size];\r\n//\r\n//\tm_bufferSize = size;\r\n//\tp = (char *)m_pDLBufferStart;\r\n//\tm_pDLBufferEnd = (void *)&p[size];\r\n//}\r\n//\r\n//NsDL * NsDLMan::open ( void )\r\n//{\r\n//\treturn (NsDL *)(OSRoundUp32B(m_pDLBufferCurrent));\r\n//}\r\n//\r\n//void NsDLMan::close ( NsDL * pDL )\r\n//{\r\n//\tassert ( pDL <= m_pDLBufferEnd );\r\n//\r\n//\tDCFlushRange ( m_pDLBufferCurrent, (OSRoundUp32B(pDL)) - (OSRoundUp32B(m_pDLBufferCurrent)) );\r\n//\r\n//\tm_pDLBufferCurrent = (void *)(OSRoundUp32B(pDL));\r\n//}\r\n//\r\n//void NsDLMan::close ( unsigned int size )\r\n//{\r\n//\tchar  * p8;\r\n//\r\n//\tp8 = (char *)(OSRoundUp32B(m_pDLBufferCurrent));\r\n//\tp8 = &p8[(OSRoundUp32B(size))];\r\n//\r\n//\tassert ( (void *)p8 <= m_pDLBufferEnd );\r\n//\r\n//\tDCFlushRange ( m_pDLBufferCurrent, (OSRoundUp32B(size)) );\r\n//\r\n//\tm_pDLBufferCurrent = (void *)p8;\r\n//}\r\n//\r\n//unsigned int NsDLMan::freeSpace ( void )\r\n//{\r\n//\treturn (unsigned int)m_pDLBufferEnd - (unsigned int)m_pDLBufferCurrent;\r\n//}\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_dlman.h",
    "content": "//#ifndef _DLMAN_H_\r\n//#define _DLMAN_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_dl.h\"\r\n//\r\n//class NsDLMan\r\n//{\r\n//\tvoid\t\t  * m_pDLBufferStart;\r\n//\tvoid\t\t  * m_pDLBufferCurrent;\r\n//\tvoid\t\t  * m_pDLBufferEnd;\r\n//\tunsigned int\tm_bufferSize;\r\n//public:\r\n//\t\t\t\t\tNsDLMan\t\t();\r\n//\t\t\t\t\tNsDLMan\t\t( int size );\r\n//\r\n//\tNsDL\t\t  *\topen\t\t( void );\r\n//\tvoid\t\t\tclose\t\t( NsDL * pDL );\r\n//\tvoid\t\t\tclose\t\t( unsigned int size );\r\n//\tunsigned int\tfreeSpace\t( void );\r\n//\r\n//\tvoid\t\t\treset\t\t( void ) { m_pDLBufferCurrent = m_pDLBufferStart; };\r\n//};\r\n//\r\n//#endif\t\t// _DLMAN_H_\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_dma.cpp",
    "content": "/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsDMA\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tDMAs matrices.\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#include \"p_DMA.h\"\r\n\r\n/********************************************************************************\r\n * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n#define BUFFER_SIZE 16384\r\n \r\n/********************************************************************************\r\n * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nstatic volatile bool\tdmaComplete;\r\n\r\n/********************************************************************************\r\n * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nstatic void arqCallback( u32 pointerToARQRequest )\r\n{\r\n\tdmaComplete = true;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\ttoARAM\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tDeclares a scene object.\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nvoid NsDMA::toARAM( u32 aram, void * p_mram, int size )\r\n{\r\n\tARQRequest\trequest;\r\n\r\n\tif ( ( ( aram & 31 ) == 0 ) && ( ( (u32)p_mram & 31 ) == 0 ) && ( ( size & 31 ) == 0 ) )\r\n\t{\r\n\t\t// Fast version.\r\n\t\tdmaComplete = false;\r\n\t\tDCFlushRange( p_mram, size );\r\n\t\tARQPostRequest\t(\t&request,\r\n\t\t\t\t\t\t\t0,\t\t\t\t\t\t// Owner.\r\n\t\t\t\t\t\t\tARQ_TYPE_MRAM_TO_ARAM,\t// Type.\r\n\t\t\t\t\t\t\tARQ_PRIORITY_HIGH,\t\t// Priority.\r\n\t\t\t\t\t\t\t(u32)p_mram,\t\t\t// Source.\r\n\t\t\t\t\t\t\taram,\t\t\t\t\t// Dest.\r\n\t\t\t\t\t\t\tsize,\t\t\t\t\t// Length.\r\n\t\t\t\t\t\t\tarqCallback );\t\t\t// Callback\r\n\r\n\t\t// Wait for it to complete.\r\n\t\twhile( !dmaComplete );\r\n\r\n\t\tDCFlushRange ( p_mram, size );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tchar s_buf[BUFFER_SIZE+32+32] __attribute__ (( aligned( 32 )));\r\n\t\tchar * p_buffer = (char *)OSRoundUp32B(s_buf);\r\n\r\n\t\t// DMA.\r\n\t\tint address = ( aram & ~31 );\r\n\t\tint remaining = ( ( size + 31 ) & ~31 );\r\n\t\tchar * pLoad = (char *)p_mram;\r\n\t\twhile ( remaining )\r\n\t\t{\r\n\t\t\tint thistime = BUFFER_SIZE;\r\n\t\t\tif ( remaining < BUFFER_SIZE ) thistime = remaining;\r\n\r\n\t\t\tmemcpy( p_buffer, pLoad, thistime );\r\n\r\n\t\t\tdmaComplete = false;\r\n\t\t\tDCFlushRange( p_buffer, thistime );\r\n\t\t\tARQPostRequest\t(\t&request,\r\n\t\t\t\t\t\t\t\t0,\t\t\t\t\t\t// Owner.\r\n\t\t\t\t\t\t\t\tARQ_TYPE_MRAM_TO_ARAM,\t// Type.\r\n\t\t\t\t\t\t\t\tARQ_PRIORITY_HIGH,\t\t// Priority.\r\n\t\t\t\t\t\t\t\t(u32)p_buffer,\t\t\t// Source.\r\n\t\t\t\t\t\t\t\taddress,\t\t\t\t// Dest.\r\n\t\t\t\t\t\t\t\tthistime,\t\t\t\t// Length.\r\n\t\t\t\t\t\t\t\tarqCallback );\t\t\t// Callback\r\n\r\n\t\t\t// Wait for it to complete.\r\n\t\t\twhile( !dmaComplete );\r\n\r\n\t\t\tDCFlushRange ( p_buffer, thistime );\r\n\r\n\t\t\taddress += thistime;\r\n\t\t\tremaining -= thistime;\r\n\t\t\tpLoad += thistime;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid NsDMA::toMRAM( void * p_mram, u32 aram, int size )\r\n{\r\n\tARQRequest\trequest;\r\n\tchar s_buf[BUFFER_SIZE+32+32] __attribute__ (( aligned( 32 )));\r\n\tchar * p_buffer = (char *)OSRoundUp32B(s_buf);\r\n\r\n\tint address = ( aram & ~31 );\r\n\tint adjust = ( aram - address );\r\n\tint remaining = size;\r\n\tchar * pStore = (char *)p_mram;\r\n\twhile ( remaining )\r\n\t{\r\n\t\tint thistime = BUFFER_SIZE - adjust;\r\n\t\tif ( remaining < BUFFER_SIZE ) thistime = remaining;\r\n\r\n\t\tdmaComplete = false;\r\n\t\tDCFlushRange ( p_buffer, (thistime + adjust + 31 ) & ~31 );\r\n//\t\tDCInvalidateRange( p_buffer, thistime ); \r\n\t\tARQPostRequest\t(\t&request,\r\n\t\t\t\t\t\t\t0,\t\t\t\t\t\t// Owner.\r\n\t\t\t\t\t\t\tARQ_TYPE_ARAM_TO_MRAM,\t// Type.\r\n\t\t\t\t\t\t\tARQ_PRIORITY_HIGH,\t\t// Priority.\r\n\t\t\t\t\t\t\taddress,\t\t\t\t// Source.\r\n\t\t\t\t\t\t\t(u32)p_buffer,\t\t\t// Dest.\r\n\t\t\t\t\t\t\t(thistime + adjust + 31 ) & ~31,// Length.\r\n\t\t\t\t\t\t\tarqCallback );\t\t\t// Callback\r\n\r\n\t\t// Wait for it to complete.\r\n\t\twhile( !dmaComplete );\r\n\r\n\t\tDCFlushRange ( p_buffer, (thistime + adjust + 31 ) & ~31 );\r\n//\t\tDCStoreRange( p_buffer, thistime + adjust ); \r\n\r\n\t\t// Copy to actual mram address.\r\n\t\tmemcpy( pStore, &p_buffer[adjust], thistime );\r\n\r\n\t\t// Next chunk.\r\n\t\tpStore += thistime;\r\n\t\taddress += thistime + adjust;\r\n\t\tremaining -= thistime;\r\n\t\tadjust = 0;\r\n\t}\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_dma.h",
    "content": "#ifndef _DMA_H_\r\n#define _DMA_H_\r\n\r\n#include <dolphin.h>\r\n\r\nnamespace NsDMA\r\n{\r\n\tvoid\t\ttoARAM\t\t( u32 aram, void * p_mram, int size );\r\n\tvoid\t\ttoMRAM\t\t( void * p_mram, u32 aram, int size );\r\n};\r\n\r\n#endif\t\t// _DMA_H_\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_dvd.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate3         \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSYS            \t \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_dvd.cpp\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t08/30/2001\tdc     \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGamecube DVD file acceess routines\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//#ifndef __NOPT_FINAL__\r\n//#ifndef DVDETH\r\n//#define __SN_FILE__\r\n//#endif\t\t// DVDETH\r\n//#endif\t\t// __NOPT_FINAL__ \r\n\r\n#include <stdarg.h>\r\n#include <gel/mainloop.h>\r\n#include <sys/sioman.h>\r\n#include <gel/music/music.h>\r\n#include <gel/soundfx/soundfx.h>\r\n#include <engine/sounds.h>\r\n#include <gel/music/ngc/p_music.h>\r\n#include \"p_assert.h\"\r\n#include \"p_dvd.h\"\r\n#include \"p_display.h\"\r\n#include \"p_debugfont.h\"\r\n#include \"p_display.h\"\r\n#include \"p_prim.h\"\r\n#include <gel/scripting/symboltable.h>\r\n#include <gfx/ngc/nx/nx_init.h>\r\n#include <gfx/ngc/nx/render.h>\r\n#include <sys\\ngc\\p_render.h>\r\n#include <sys\\ngc\\p_dma.h>\r\n#include <sys\\ngc\\p_buffer.h>\r\n#include <gel/Scripting/script.h>\r\n#include <gfx/NxLoadScreen.h>\r\n\r\n#ifdef __SN_FILE__\r\n#include \"libsn.h\"\r\nbool sn_init = false;\r\n#endif\t\t// __SN_FILE__\r\n \r\nextern bool gSoundManagerSingletonExists;\r\n\r\nextern char * g_p_buffer;\r\n\r\nextern void*   hwFrameBuffer1;\r\nextern void*   hwFrameBuffer2;\r\nextern bool\tgLoadingScreenActive;\r\nextern bool\tgReload;\r\nextern bool\tgLoadingLoadScreen;\r\nextern GXColor messageColor;\r\n\r\nextern bool g_legal;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\nint _DVDError = 0;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define READ_BLOCK_SIZE\t\t\t32\r\n//#ifdef DVDETH\r\n//#define READ_LARGE_BLOCK_SIZE\t(1024 * 2048)\r\n//#else\r\n#define READ_LARGE_BLOCK_SIZE\t(8 * 1024)\r\n//#endif\t\t// DVDETH\r\n//static char\tbyteData[READ_LARGE_BLOCK_SIZE+32];\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint\tDVDError( void )\r\n{\r\n\treturn _DVDError;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//void dvd_show_error( int error )\r\n//{\r\n//\tNsCamera cam;\r\n//\tcam.orthographic( 0, 0, 640, 448 );\r\n//\r\n//\t// Draw the screen.\r\n//\tNsPrim::begin();\r\n//\r\n//\tcam.begin();\r\n//\r\n//\t// 320x32\r\n//\r\n//\tNsRender::setBlendMode( NsBlendMode_None, NULL, (unsigned char)0 );\r\n////\tNsPrim::box( 64, 64, 640-64, 64+80, (GXColor){0,32,64,128} );\r\n////\tNsDebugFont::printf( 80, 80, NsFontEffect_Bold, 16, (GXColor){255,255,255,128}, \"DVD Error:\\n\\n%s\\n\", error_name[error+1] );\r\n//\r\n//\t#if ENGLISH == 1\r\n//\tNsPrim::box( 80, 48, 640-80, 48+102, (GXColor){0,32,64,128} );\r\n//\t#endif\r\n//\t#if FRENCH == 1\r\n//\tNsPrim::box( 80, 48, 640-80, 48+120, (GXColor){0,32,64,128} );\r\n//\t#endif\r\n//\t#if GERMAN == 1\r\n//\tNsPrim::box( 80, 48, 640-80, 48+138, (GXColor){0,32,64,128} );\r\n//\t#endif\r\n//\tswitch ( error ) {\r\n//\t\tcase DVD_STATE_FATAL_ERROR:\r\n//\t\tcase DVD_STATE_RETRY:\r\n//\t\t\t\r\n//\t\t\t#if ENGLISH == 1\r\n//\t\t\tNsDebugFont::printf( 80+8+8, 48+8, NsFontEffect_None, 16, (GXColor){255,255,255,128}, \"An error has occurred. Turn\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+8+4, 48+8+18, NsFontEffect_None, 16, (GXColor){255,255,255,128}, \"the power off and refer to\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+40+4, 48+8+36, NsFontEffect_None, 16, (GXColor){255,255,255,128}, \"the Nintendo GameCube\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+40, 48+8+54, NsFontEffect_None, 16, (GXColor){255,255,255,128}, \"Instruction Booklet for\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+48, 48+8+72, NsFontEffect_None, 16, (GXColor){255,255,255,128}, \"further instructions.\" );\r\n//\t\t\t#endif\r\n//\t\t\t#if FRENCH == 1\r\n//\t\t\tNsDebugFont::printf( 80+8+24, 48+8,    NsFontEffect_None, 16, (GXColor){255,255,255,128},   \"Une erreur s'est produite.\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+16, 48+8+18, NsFontEffect_None, 16, (GXColor){255,255,255,128},   \"Il faut teindre la console\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+64, 48+8+36, NsFontEffect_None, 16, (GXColor){255,255,255,128},   \"et consulter le guide\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+48, 48+8+54, NsFontEffect_None, 16, (GXColor){255,255,255,128},   \"d'instructions GameCube\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+56, 48+8+72, NsFontEffect_None, 16, (GXColor){255,255,255,128},   \"Nintendo pour plus de\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+168+4, 48+8+90, NsFontEffect_None, 16, (GXColor){255,255,255,128},   \"dtails.\" );\r\n//\t\t\t#endif\r\n//\t\t\t#if GERMAN == 1\r\n//\t\t\tNsDebugFont::printf( 80+8+96, 48+8, NsFontEffect_None, 16, (GXColor){255,255,255,128},      \"Es ist ein Fehler\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+40, 48+8+18, NsFontEffect_None, 16, (GXColor){255,255,255,128},   \"aufgetreten. Schalte die\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+16, 48+8+36, NsFontEffect_None, 16, (GXColor){255,255,255,128},   \"Konsole aus und sieh in der\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+48, 48+8+54, NsFontEffect_None, 16, (GXColor){255,255,255,128},   \"Bedienungsanleitung des\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+16, 48+8+72, NsFontEffect_None, 16, (GXColor){255,255,255,128},   \"Nintendo GameCube nach, um\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+64, 48+8+90, NsFontEffect_None, 16, (GXColor){255,255,255,128},   \"weitere Informationen\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+140, 48+8+108, NsFontEffect_None, 16, (GXColor){255,255,255,128}, \"zu erhalten.\" );\r\n//\t\t\t#endif\r\n//\t\t\tbreak;\r\n//\t\tcase DVD_STATE_COVER_OPEN:\r\n//\t\t\t#if ENGLISH == 1\r\n//\t\t\tNsDebugFont::printf( 80+8+4, 48+8, NsFontEffect_None, 16, (GXColor){255,255,255,128}, \"Please close the Disc Cover.\" );\r\n//\t\t\t#endif\r\n//\t\t\t#if FRENCH == 1\r\n//\t\t\tNsDebugFont::printf( 80+8+4+48, 48+8, NsFontEffect_None, 16, (GXColor){255,255,255,128}, \"Refermer le couvercle.\" );\r\n//\t\t\t#endif\r\n//\t\t\t#if GERMAN == 1\r\n//\t\t\tNsDebugFont::printf( 80+8+60, 48+8, NsFontEffect_None, 16, (GXColor){255,255,255,128},   \"Bitte den Disc-Deckel\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+156, 48+8+18, NsFontEffect_None, 16, (GXColor){255,255,255,128}, \"schlieen.\" );\r\n//\t\t\t#endif\r\n//\t\t\tbreak;\r\n//\t\tcase DVD_STATE_NO_DISK:\r\n//\t\tcase DVD_STATE_WRONG_DISK:\r\n//\t\t\t#if ENGLISH == 1\r\n//\t\t\tNsDebugFont::printf( 80+8,    48+8,    NsFontEffect_None, 16, (GXColor){255,255,255,128}, \"Please insert the Tony Hawk's\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+48, 48+8+18, NsFontEffect_None, 16, (GXColor){255,255,255,128}, \"Pro Skater 3 Game Disc.\" );\r\n//\t\t\t#endif\r\n//\t\t\t#if FRENCH == 1\r\n//\t\t\tNsDebugFont::printf( 80+8+40, 48+8, NsFontEffect_None, 16, (GXColor){255,255,255,128},    \"Insrer le disque de jeu\" );\r\n//\t\t\tNsDebugFont::printf( 80+8+36, 48+8+18, NsFontEffect_None, 16, (GXColor){255,255,255,128}, \"Tony Hawk's Pro Skater 3.\" );\r\n//\t\t\t#endif\r\n//\t\t\t#if GERMAN == 1\r\n//\t\t\tNsDebugFont::printf( 80+8+24, 48+8, NsFontEffect_None, 16, (GXColor){255,255,255,128},    \"Bitte lege die Tony Hawk's\" );\r\n//\t\t\tNsDebugFont::printf( (80+8+24+48)-64, 48+8+18, NsFontEffect_None, 16, (GXColor){255,255,255,128}, \"Pro Skater 3 Spiel-Disc ein.\" );\r\n//\t\t\t#endif\r\n//\t\t\tbreak;\r\n//\t}\r\n//\r\n//\tcam.end();\r\n//\r\n//\tNsPrim::end();\r\n//\r\n//\tif( NsDisplay::shouldReset())\r\n//\t{\r\n//\t\t// Prepare the game side of things for reset.\r\n////\t\tSpt::SingletonPtr< Mlp::Manager > mlp_manager;\r\n////\t\tmlp_manager->PrepareReset();\r\n//\r\n//\t\t// Prepare the system side of things for reset.\r\n//\t\tNsDisplay::doReset();\r\n//\t}\r\n//}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic void dvd_read_safe( DVDFileInfo* fileInfo, void* addr, int length, int offset )\r\n{\r\n#ifdef DVDETH\r\n\tDVDRead( fileInfo, addr, length, offset );\r\n#else\r\n\tDVDReadAsync( fileInfo, addr, length, offset, NULL );\r\n\tDVDWaitAsync();\r\n#endif\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid DVDWaitAsync()\r\n{\r\n#ifndef DVDETH\r\n\tint displayed = 0;\r\n\tint reported = 0;\r\n//\tvoid * _myXFB1;\r\n//\tvoid * _myXFB2;\r\n//\tvoid * _copyXFB;\r\n//\tvoid * _dispXFB;\r\n\t\r\n\twhile ( 1 ) {\r\n\t\ts32 error;\r\n\t\terror = DVDGetDriveStatus();\r\n\r\n\t\tNsDisplay::doReset();\r\n\r\n\t\tif ( error == DVD_STATE_END ) break;\r\n\t\tif ( error == DVD_STATE_BUSY ) continue;\r\n\t\tif ( error == DVD_STATE_CANCELED ) break;\r\n\t\tif ( error == DVD_STATE_PAUSING ) continue;\r\n\t\tif ( error == DVD_STATE_WAITING ) continue;\r\n\r\n\t\t_DVDError = error;\r\n\r\n\t\tif ( DVDError() && Script::GetInteger( \"allow_dvd_errors\" ) )\r\n\t\t{\r\n\t\t\tif ( !displayed )\r\n\t\t\t{\r\n\t\t\t\tNxNgc::EngineGlobals.gpuBusy = true;\r\n\t\t\t\tdisplayed = 1;\r\n\t\t\t\tif ( gLoadingLoadScreen ) gReload = true;\r\n\t\t\t\tSpt::SingletonPtr< SIO::Manager >\tsio_man;\r\n\t\t\t\tsio_man->Pause();\r\n\t\t\t\tSpt::SingletonPtr< Sfx::CSfxManager > sfx_manager;\r\n\t\t\t\tsfx_manager->PauseSounds();\r\n\t\t\t\tPCMAudio_Pause( true, Pcm::EXTRA_CHANNEL );\r\n\t\t\t\tPCMAudio_Pause( true, Pcm::MUSIC_CHANNEL );\r\n\r\n\t\t\t\t// Copy current framebuffer to ARAM (only if it's a loading screen).\r\n//\t\t\t\tNsDisplay::flush();\r\n\t\t\t\tif ( gLoadingScreenActive )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int vv = 0; vv < 2; vv++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tNsDisplay::begin();\r\n\t\t\t\t\t\tNsRender::begin();\r\n\r\n\t\t\t\t\t\tNsRender::end();\r\n\t\t\t\t\t\tNsDisplay::end( false );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// We'll use stream buffer 0 for this.\r\n\t\t\t\t\tuint32 address0 = NxNgc::EngineGlobals.aram_stream0;\r\n\t\t\t\t\tuint32 address1 = NxNgc::EngineGlobals.aram_stream1;\r\n\t\t\t\t\tuint32 address2 = NxNgc::EngineGlobals.aram_stream2;\r\n\t\t\t\t\tuint32 address3 = NxNgc::EngineGlobals.aram_music;\r\n\r\n\t\t\t\t\tint buf0_max = ( NsBuffer::get_size() / ( 640 * 2 ) );\r\n\t\t\t\t\tint buf1_max = buf0_max + ( ( 32 * 1024 ) / ( 640 * 2 ) );\r\n\t\t\t\t\tint buf2_max = buf1_max + ( ( 32 * 1024 ) / ( 640 * 2 ) );\r\n\t\t\t\t\tint buf3_max = buf2_max + ( ( 32 * 1024 ) / ( 640 * 2 ) );\r\n\t\t\t\t\tint buf4_max = buf3_max + ( ( 32 * 1024 ) / ( 640 * 2 ) );\r\n\r\n\t\t\t\t\tu16 line[640];\r\n\t\t\t\t\tfor ( int yy = 0; yy < 448; yy++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfor ( int xx = 0; xx < 640; xx++ )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tu32 pixel;\r\n\t\t\t\t\t\t\tGX::PeekARGB( xx, yy, &pixel );\r\n\t\t\t\t\t\t\tint r = ( pixel >> 0 ) & 255;\r\n\t\t\t\t\t\t\tint g = ( pixel >> 8 ) & 255;\r\n\t\t\t\t\t\t\tint b = ( pixel >> 16 ) & 255;\r\n\t\t\t\t\t\t\tline[xx] = ( ( r >> 3 ) & 0x1f ) | ( ( ( g >> 2 ) & 0x3f ) << 5 ) | ( ( ( b >> 3 ) & 0x1f ) << 11 );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif ( yy < buf0_max )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmemcpy( &g_p_buffer[(yy*640*2)], line, 640 * 2 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( ( yy >= buf0_max ) && ( yy < buf1_max ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tNsDMA::toARAM( ( address0 + ( ( yy - buf0_max ) * 640 * 2 ) ), line, 640 * 2 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( ( yy >= buf1_max ) && ( yy < buf2_max ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tNsDMA::toARAM( ( address1 + ( ( yy - buf1_max ) * 640 * 2 ) ), line, 640 * 2 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( ( yy >= buf2_max ) && ( yy < buf3_max ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tNsDMA::toARAM( ( address2 + ( ( yy - buf2_max ) * 640 * 2 ) ), line, 640 * 2 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( ( yy >= buf3_max ) && ( yy < buf4_max ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tNsDMA::toARAM( ( address3 + ( ( yy - buf3_max ) * 640 * 2 ) ), line, 640 * 2 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t//OSReport( \"We have to reset now.\\n\" );\r\n\r\n\t\t\tNxNgc::EngineGlobals.screen_brightness = 1.0f;\r\n\r\n\t\t\t// Render the text.\r\n\t\t\tNsDisplay::begin();\r\n\t\t\tNsRender::begin();\r\n\r\n\t\t\tNsCamera cam;\r\n\t\t\tcam.orthographic( 0, 0, 640, 448 );\r\n\r\n\t\t\t// Draw the screen.\r\n\t\t\tNsPrim::begin();\r\n\r\n\t\t\tcam.begin();\r\n\r\n\t\t\tGX::SetZMode( GX_FALSE, GX_ALWAYS, GX_TRUE );\r\n\r\n\t\t\tNxNgc::set_blend_mode( NxNgc::vBLEND_MODE_BLEND );\r\n\r\n//\t\t\tif ( NsDisplay::shouldReset() )\r\n//\t\t\t{\r\n//\t\t\t\t// Reset message.\r\n//\t\t\t\tScript::RunScript( \"ngc_reset\" );\r\n//\t\t\t}\r\n//\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// DVD Error message.\r\n\t\t\t\tswitch ( DVDError() )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase DVD_STATE_FATAL_ERROR:\r\n\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_fatal\" );\r\n\t\t\t\t\t\tNxNgc::EngineGlobals.disableReset = true;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase DVD_STATE_RETRY:\r\n\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_retry\" );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase DVD_STATE_COVER_OPEN:\r\n\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_cover_open\" );\r\n\t\t\t\t\t\tNxNgc::EngineGlobals.disableReset = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase DVD_STATE_NO_DISK:\r\n\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_no_disk\" );\r\n\t\t\t\t\t\tNxNgc::EngineGlobals.disableReset = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase DVD_STATE_WRONG_DISK:\r\n\t\t\t\t\t\tScript::RunScript( \"ngc_dvd_wrong_disk\" );\r\n\t\t\t\t\t\tNxNgc::EngineGlobals.disableReset = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tNsDisplay::setBackgroundColor( messageColor );\r\n\r\n\t\t\tcam.end();\r\n\r\n\t\t\tNsPrim::end();\r\n\r\n\t\t\tNsRender::end();\r\n\t\t\tNsDisplay::end( true );\r\n\t\t}\r\n\r\n//\r\n//\t\t_DVDError = 1;\r\n//\t\tif ( error != DVD_STATE_WAITING ) {\r\n//\t\t\tNsDisplay::begin();\r\n//\t\t\tdvd_show_error( error );\r\n//\t\t\tNsDisplay::end( false );\r\n//\t\t\tNsDisplay::flush();\r\n//\t\t}\r\n//\t\tif ( !displayed ) {\r\n#ifndef __NOPT_FINAL__\r\n\t\t\tstatic char * error_name[] = {\r\n\t\t\t\t\"DVD_STATE_FATAL_ERROR\",     // -1\r\n\t\t\t\t\"DVD_STATE_END\",             // 0\r\n\t\t\t\t\"DVD_STATE_BUSY\",            // 1\r\n\t\t\t\t\"DVD_STATE_WAITING\",         // 2\r\n\t\t\t\t\"DVD_STATE_COVER_CLOSED\",    // 3\r\n\t\t\t\t\"DVD_STATE_NO_DISK\",         // 4\r\n\t\t\t\t\"DVD_STATE_COVER_OPEN\",      // 5\r\n\t\t\t\t\"DVD_STATE_WRONG_DISK\",      // 6\r\n\t\t\t\t\"DVD_STATE_MOTOR_STOPPED\",   // 7\r\n\t\t\t\t\"DVD_STATE_PAUSING\",         // 8\r\n\t\t\t\t\"DVD_STATE_IGNORED\",         // 9\r\n\t\t\t\t\"DVD_STATE_CANCELED\",        // 10\r\n\t\t\t\t\"DVD_STATE_RETRY\",           // 11\r\n\t\t\t};\r\n#endif\t\t// __NOPT_FINAL__\r\n\r\n\t\t\tif ( !reported )\r\n\t\t\t{\r\n#ifndef __NOPT_FINAL__\r\n\t\t\t\tif ( ( error >= -1 ) && ( error <= 11 ) ) {\r\n\t\t\t\t\tOSReport( \"Received DVD Error: (%d) %s\\n\", error, error_name[error+1] );\r\n\t\t\t\t} else {\r\n\t\t\t\t\tOSReport( \"Received DVD Error: (%d)\\n\", error );\r\n\t\t\t\t}\r\n#endif\t\t// __NOPT_FINAL__\r\n\t\t\t\treported = 1;\r\n\t\t\t}\r\n//\t\t}\r\n//\r\n//\t\tif( NsDisplay::shouldReset())\r\n//\t\t{\r\n//\t\t\t// Prepare the game side of things for reset.\r\n////\t\t\tSpt::SingletonPtr< Mlp::Manager > mlp_manager;\r\n////\t\t\tmlp_manager->PrepareReset();\r\n//\r\n//\t\t\t// Prepare the system side of things for reset.\r\n//\t\t\tNsDisplay::doReset();\r\n//\t\t}\r\n//\r\n//\t\tdisplayed = 1;\r\n\t}\r\n\r\n\tif ( displayed )\r\n\t{\r\n\t\t// Copy current framebuffer from ARAM (only if it's a loading screen).\r\n\t\tif ( gLoadingScreenActive )\r\n\t\t{\r\n\r\n\t\t\t// We'll use stream buffer 0 for this.\r\n\t\t\tuint32 address0 = NxNgc::EngineGlobals.aram_stream0;\r\n\t\t\tuint32 address1 = NxNgc::EngineGlobals.aram_stream1;\r\n\t\t\tuint32 address2 = NxNgc::EngineGlobals.aram_stream2;\r\n\t\t\tuint32 address3 = NxNgc::EngineGlobals.aram_music;\r\n\r\n\t\t\tint buf0_max = ( NsBuffer::get_size() / ( 640 * 2 ) );\r\n\t\t\tint buf1_max = buf0_max + ( ( 32 * 1024 ) / ( 640 * 2 ) );\r\n\t\t\tint buf2_max = buf1_max + ( ( 32 * 1024 ) / ( 640 * 2 ) );\r\n\t\t\tint buf3_max = buf2_max + ( ( 32 * 1024 ) / ( 640 * 2 ) );\r\n\t\t\tint buf4_max = buf3_max + ( ( 32 * 1024 ) / ( 640 * 2 ) );\r\n\r\n\t\t\tu16 line[640];\r\n\t\t\tfor ( int yy = 0; yy < 448; yy++ )\r\n\t\t\t{\r\n\t\t\t\tif ( yy < buf0_max )\r\n\t\t\t\t{\r\n\t\t\t\t\tmemcpy( line, &g_p_buffer[(yy*640*2)], 640 * 2 );\r\n\t\t\t\t}\r\n\t\t\t\tif ( ( yy >= buf0_max ) && ( yy < buf1_max ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tNsDMA::toMRAM( line, ( address0 + ( ( yy - buf0_max ) * 640 * 2 ) ), 640 * 2 );\r\n\t\t\t\t}\r\n\t\t\t\tif ( ( yy >= buf1_max ) && ( yy < buf2_max ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tNsDMA::toMRAM( line, ( address1 + ( ( yy - buf1_max ) * 640 * 2 ) ), 640 * 2 );\r\n\t\t\t\t}\r\n\t\t\t\tif ( ( yy >= buf2_max ) && ( yy < buf3_max ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tNsDMA::toMRAM( line, ( address2 + ( ( yy - buf2_max ) * 640 * 2 ) ), 640 * 2 );\r\n\t\t\t\t}\r\n\t\t\t\tif ( ( yy >= buf3_max ) && ( yy < buf4_max ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tNsDMA::toMRAM( line, ( address3 + ( ( yy - buf3_max ) * 640 * 2 ) ), 640 * 2 );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( int xx = 0; xx < 640; xx++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tu32 pixel;\r\n\t\t\t\t\tint r = ( ( line[xx] >>  0 ) & 0x1f ) << 3;\r\n\t\t\t\t\tint g = ( ( line[xx] >>  5 ) & 0x3f ) << 2;\r\n\t\t\t\t\tint b = ( ( line[xx] >> 11 ) & 0x1f ) << 3;\r\n\t\t\t\t\tpixel = ( 255 << 24 ) | ( b << 16 ) | ( g << 8 ) | r;\r\n\r\n\t\t\t\t\tGX::PokeARGB( xx, yy, pixel );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor ( int vv = 0; vv < 2; vv++ )\r\n\t\t{\r\n\t\t\t//OSReport( \"We have to reset now.\\n\" );\r\n\r\n\t\t\tNxNgc::EngineGlobals.screen_brightness = 1.0f;\r\n\r\n\t\t\t// Render the text.\r\n\t\t\tNsDisplay::begin();\r\n\t\t\tNsRender::begin();\r\n\r\n\t\t\t// Draw the screen.\r\n\t\t\tNsPrim::begin();\r\n\r\n\t\t\tNsPrim::end();\r\n\r\n\t\t\tNsDisplay::setBackgroundColor( (GXColor){0,0,0,0} );\r\n\r\n\t\t\tNsRender::end();\r\n\t\t\tNsDisplay::end( gLoadingScreenActive ? false : true );\r\n\t\t}\r\n\r\n\t\tif ( g_legal ) display_legal();\r\n\r\n//\t\tNsDisplay::begin();\r\n//\t\tdvd_show_error( DVD_STATE_BUSY );\r\n//\t\tNsDisplay::end( false );\r\n//\t\tNsDisplay::flush();\r\n//\t\t_DVDError = 0;\r\n\t\tPCMAudio_Pause( false, Pcm::MUSIC_CHANNEL );\r\n\t\tPCMAudio_Pause( false, Pcm::EXTRA_CHANNEL );\r\n   \t\tSpt::SingletonPtr< SIO::Manager >\tsio_man;\r\n\t\tsio_man->UnPause();\r\n\t\tNxNgc::EngineGlobals.gpuBusy = false;\r\n\t}\r\n\t_DVDError = 0;\r\n#endif\t\t// DVDETH\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid DVDCheckAsync( void )\r\n{\r\n#ifndef DVDETH\r\n\ts32 error;\r\n\terror = DVDGetDriveStatus();\r\n\r\n\tif ( error == DVD_STATE_END ) return;\r\n\tif ( error == DVD_STATE_BUSY ) return;\r\n\tif ( error == DVD_STATE_CANCELED ) return;\r\n\tif ( error == DVD_STATE_PAUSING ) return;\r\n\r\n\tDVDWaitAsync();\r\n#endif\t\t// DVDETH\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nstatic char* dvd_file_fix_name( const char * pFilename )\r\n{\r\n\tstatic char buffer[256];\r\n\tchar *p;\r\n\r\n\t// Copy to our buffer.\r\n\tstrcpy ( buffer, pFilename );\r\n\r\n\t// Replace \\\\ with /.\r\n\tp = buffer;\r\n\twhile ( *p != '\\0' ) {\r\n\t\tif ( *p == '\\\\' ) *p = '/';\r\n\t\tp++;\r\n\t}\r\n\r\n\t// If this is a .pre file, switch to a .prg file.\r\n\tint idx = strlen( buffer );\r\n\tif((( buffer[idx - 1] ) == 'e' ) &&\r\n\t   (( buffer[idx - 2] ) == 'r' ) &&\r\n\t   (( buffer[idx - 3] ) == 'p' ))\r\n\t{\r\n\t\tbuffer[idx - 1] = 'g';\r\n\t}\r\n\r\n\t// Deal with .prgf & .prgd\r\n\tif((( buffer[idx - 2] ) == 'e' ) &&\r\n\t   (( buffer[idx - 3] ) == 'r' ) &&\r\n\t   (( buffer[idx - 4] ) == 'p' ))\r\n\t{\r\n\t\tbuffer[idx - 2] = buffer[idx - 1];\r\n\t\tbuffer[idx - 1] = buffer[idx];\r\n\t}\r\n\r\n\treturn buffer;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint dvd_file_size( NsFile* p_file )\r\n{\r\n\tif ( !p_file->m_sizeCached ) {\r\n\t    // Get the size of the DVD\r\n\t    p_file->m_cachedSize = DVDGetLength(&p_file->m_FileInfo);\r\n\t\tp_file->m_sizeCached = 1;\r\n\t}\r\n\r\n\treturn p_file->m_cachedSize;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint dvd_file_open( NsFile* p_file, const char* p_filename )\r\n{\r\n\tchar* pFixedName;\r\n\t\r\n\t// Assert if we already have an open NsFile.\r\n\tif( p_file->m_FileOpen ) {\r\n\t\tDbg_MsgAssert( 0, (\"NsFile already open.\\n\"));\r\n\t}\r\n\r\n\tpFixedName = dvd_file_fix_name(p_filename);\r\n\r\n#ifdef DVDETH\r\n\tDVDOpen( pFixedName, &p_file->m_FileInfo );\r\n#else\r\n\tint entry = DVDConvertPathToEntrynum( pFixedName );\r\n\r\n\tif ( entry == -1 ) {\r\n\t\t// File is not present.\r\n\t\tOSReport ( \"NsFile: Open %s does not exist\\n\", pFixedName );\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tOSReport ( \"NsFile: Open %s\\n\", pFixedName );\r\n\r\n\twhile (FALSE == DVDFastOpen( entry, &p_file->m_FileInfo )) {\r\n//\t\tdvd_handle_error( &p_file->m_FileInfo );\r\n//        OSHalt(\"Cannot open NsFile.\\n\");\r\n    }\r\n#endif\t\t// DVDETH\r\n\r\n\tp_file->m_FileOpen\t\t= 1;\r\n\tp_file->m_numCacheBytes\t= 0;\r\n\tp_file->m_seekOffset\t= 0;\r\n\tdvd_file_size( p_file );\r\n\r\n\treturn 1;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint dvd_file_eof( NsFile* p_file )\r\n{\r\n\treturn ( p_file->m_seekOffset >= dvd_file_size( p_file ) ) ? 1 : 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\ns32 dvd_file_read_anywhere( DVDFileInfo* fileInfo, void* addr, s32 length, s32 offset )\r\n{\r\n\tchar\tbyteData[READ_LARGE_BLOCK_SIZE+32];\r\n\tchar  * bytes;\r\n\tint\t\ttoread;\r\n\tchar  * p8;\r\n\tint\t\toff;\r\n\r\n\t// If we're reading to an odd location, or the read offset is not 4-byte\r\n\t// aligned, we need a mis-aligned read.\r\n\tif ( (((int)addr) & 0x0000001f) || (offset & 3) ) {\r\n\t\t// Mis-aligned.\r\n//\t\tprintf ( \"mis-aligned read %d bytes, offset %d\\n\", length, offset );\r\n\t\tbytes = (char *)(OSRoundUp32B(((int)byteData)));\r\n\t\ttoread = length;\r\n\t\tp8 = (char *)addr;\r\n\t\toff = offset;\r\n\t\t// Read odd bytes if any.\r\n\t\tif ( offset & 3 ) {\r\n\t\t\tdvd_read_safe( fileInfo, bytes, offset & 3, off );\r\n\t\t\ttoread -= offset & 3;\r\n\t\t\toff += offset & 3;\r\n\t\t\tmemcpy ( p8, bytes, offset & 3 );\r\n\t\t\tDCFlushRange ( p8, offset & 3 );\r\n\t\t\tp8 += offset & 3;\r\n\t\t}\r\n\t\t// Read as many large blocks as we can.\r\n\t\twhile ( toread > READ_LARGE_BLOCK_SIZE ) {\r\n\t\t\tdvd_read_safe( fileInfo, bytes, READ_LARGE_BLOCK_SIZE, off );\r\n\t\t\ttoread -= READ_LARGE_BLOCK_SIZE;\r\n\t\t\toff += READ_LARGE_BLOCK_SIZE;\r\n\t\t\tmemcpy ( p8, bytes, READ_LARGE_BLOCK_SIZE );\r\n\t\t\tDCFlushRange ( p8, READ_LARGE_BLOCK_SIZE );\r\n\t\t\tp8 += READ_LARGE_BLOCK_SIZE;\r\n\t\t}\r\n\t\t// Read last block.\r\n\t\tif ( toread > 0 ) {\r\n\t\t\tdvd_read_safe( fileInfo, bytes, OSRoundUp32B(toread), off );\r\n\t\t\tmemcpy ( p8, bytes, toread );\r\n\t\t\tDCFlushRange ( p8, toread );\r\n\t\t}\r\n\t\treturn length;\r\n\t} else {\r\n//\t\tprintf ( \"aligned read %d bytes, offset %d\\n\", length, offset );\r\n\t\t// Just do a straight read.\r\n\t\tdvd_read_safe( fileInfo, addr, length, offset );\r\n\t\treturn length;\r\n\t}\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nvoid dvd_file_fill_cache( NsFile* p_file )\r\n{\r\n    int\tbytesRead;\r\n\r\n\tbytesRead = dvd_file_read_anywhere(&p_file->m_FileInfo, &p_file->m_cachedBytes[0], READ_BLOCK_SIZE, p_file->m_seekOffset);\r\n\tp_file->m_seekOffset += bytesRead;\r\n\tDbg_MsgAssert( bytesRead > 0, (\"Error occurred when reading DVD\"));\r\n\tp_file->m_numCacheBytes = bytesRead;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint dvd_file_read( NsFile* p_file, void* pDest, int numBytes )\r\n{\r\n    int\t\tbytesRemaining;\r\n    int\t\ttotalBytesRead;\r\n    int\t\tbytesRead;\r\n    int\t\tbytesRounded;\r\n    int\t\tsaveCacheBytes;\r\n\tchar  * p8;\r\n\r\n\tp8 = (char *)pDest;\r\n\ttotalBytesRead = 0;\r\n\r\n\t// Pull from cache first.\r\n\tif ( p_file->m_numCacheBytes >= numBytes ) {\r\n\t\t// All bytes requested are in the cache - copy what we need.\r\n//\t\tOSReport ( \"All bytes in cache: %d\\n\", numBytes );\r\n\t\tp_file->GetCacheBytes ( p8, numBytes );\r\n\t\treturn ( numBytes );\r\n\t} else {\r\n\t\tif ( p_file->m_numCacheBytes ) {\r\n//\t\t\tOSReport ( \"Emptying cache: %d\\n\", numCacheBytes );\r\n\t\t\t// Set number of bytes remaining.\r\n\t\t\tbytesRemaining = numBytes - p_file->m_numCacheBytes;\r\n\t\t\t//  Empty cache.\r\n\t\t\tsaveCacheBytes = p_file->m_numCacheBytes;\t\t// Must save ast GetCacheBytes will set it to 0, and we need it for the pointer advance.\r\n\t\t\tp_file->GetCacheBytes ( p8, p_file->m_numCacheBytes );\r\n\t\t\tp8 += saveCacheBytes;\r\n\t\t\ttotalBytesRead += saveCacheBytes;\r\n\t\t} else {\r\n\t\t\tbytesRemaining = numBytes;\r\n\t\t}\r\n\t}\r\n\t// Read multiples of READ_BLOCK_SIZE bytes.\r\n\tbytesRounded = ( bytesRemaining / READ_BLOCK_SIZE ) * READ_BLOCK_SIZE;\r\n\tif ( bytesRounded ) {\r\n//\t\tOSReport ( \"Block read: %d\\n\", bytesRounded );\r\n\t\tif ( dvd_file_eof( p_file ) ) return 0;\r\n\t\tbytesRead = dvd_file_read_anywhere(&p_file->m_FileInfo, p8, (s32)bytesRounded, p_file->m_seekOffset);\r\n\t\tp_file->m_seekOffset += bytesRounded;\r\n\t\tDbg_MsgAssert( bytesRead > 0, (\"Error occurred when reading NsFile\"));\r\n\t\ttotalBytesRead += bytesRead;\r\n\t\tp8 += bytesRounded;\r\n\t\tbytesRemaining -= bytesRounded;\r\n\t}\r\n\r\n\t// Cache odd bytes\r\n\tif ( bytesRemaining ) {\r\n\t\t// Fill up the cache.\r\n\t\tif ( dvd_file_eof( p_file ) ) return 0;\r\n\t\tdvd_file_fill_cache( p_file );\r\n\t\t// Pull remaining bytes from cache.\r\n//\t\tOSReport ( \"Cache Copy: %d\\n\", bytesRemaining );\r\n\t\tp_file->GetCacheBytes ( p8, bytesRemaining );\r\n\t\ttotalBytesRead += bytesRemaining;\r\n\t}\r\n\r\n//    OSRestoreInterrupts(enabled);\r\n\r\n\treturn totalBytesRead;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint dvd_file_seek( NsFile* p_file, NsFileSeek type, int offset )\r\n{\r\n\tswitch ( type ) {\r\n\t\tcase NsFileSeek_Start:\r\n\t\t\tp_file->m_seekOffset = offset;\r\n\t\t\tbreak;\r\n\t\tcase NsFileSeek_End:\r\n\t\t\tp_file->m_seekOffset = dvd_file_size( p_file ) - offset;\r\n\t\t\tbreak;\r\n\t\tcase NsFileSeek_Current:\r\n\t\t\tp_file->m_seekOffset += offset;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDbg_MsgAssert( 0, (\"Illegal seek type.\\n\"));\r\n\t\t\tbreak;\r\n\t}\r\n\tp_file->m_numCacheBytes = 0;\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint dvd_file_close( NsFile* p_file )\r\n{\r\n    // Close the DVD\r\n\tDVDClose(&p_file->m_FileInfo);\r\n\r\n\tp_file->m_FileOpen\t\t= 0;\r\n\tp_file->m_sizeCached\t= 0;\r\n\tp_file->m_numCacheBytes\t= 0;\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint dvd_file_exist( const char * pFilename )\r\n{\r\n#ifdef DVDETH\r\n\tDVDFileInfo info;\r\n\tif ( DVDOpen( pFilename, &info ) )\r\n\t{\r\n\t\tDVDClose( &info );\r\n\t\treturn 1;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n#else\r\n\t// Return 0 if file doen't exist, 1 if we found it.\r\n\treturn DVDConvertPathToEntrynum( dvd_file_fix_name( pFilename ) ) == -1 ? 0 : 1;\r\n#endif\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nchar dvd_file_getcharacter( NsFile* p_file )\r\n{\r\n\tchar c = EOF;\r\n\tdvd_file_read( p_file, &c, 1 );\r\n\treturn c;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nchar * dvd_file_gets( NsFile* p_file, char * s, int n )\r\n{\r\n\tregister int c = EOF;\r\n\tregister char * cs;\r\n\r\n\tcs = s;\r\n\twhile ( --n > 0 && (c = dvd_file_getcharacter( p_file )) != EOF ) {\r\n\t\tif ((*cs++ = c) == '\\n') break;\r\n\t}\r\n\t*cs = '\\0';\r\n\treturn (c == EOF && cs == s) ? NULL : s;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint dvd_file_tell( NsFile* p_file )\r\n{\r\n\treturn p_file->m_seekOffset;\r\n}\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\nint DVDFileAccess( NsFile* p_file, NsFileAccessType access_type, ... ) \r\n{\r\n\tDbg_MsgAssert( p_file, (\"NULL pointer.\\n\"));\r\n\r\n#ifdef __SN_FILE__\r\n\tif ( !sn_init )\r\n\t{\r\n\t\tPCinit();\r\n\t\tsn_init = true;\r\n\t}\r\n\r\n\r\n\tswitch( access_type )\r\n\t{\r\n\t\tcase FSIZE:\r\n\t\t{\r\n\t\t\tint current = PClseek( p_file->m_FileOpen, 0, SEEK_CUR );  \r\n\t\t\tint size = PClseek( p_file->m_FileOpen, 0, SEEK_END );  \r\n\t\t\tPClseek( p_file->m_FileOpen, current, SEEK_SET );\r\n\t\t\treturn size;\r\n\t\t}\r\n\r\n\t\tcase FOPEN:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tchar* raw_name\t= va_arg( vl, char* );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\tchar * name = dvd_file_fix_name( raw_name );\r\n\r\n\t\t\treturn ( ( ( p_file->m_FileOpen = PCopen( name, 0, 0 ) ) == SN_ERR ) ? 0 : 1 );\r\n\t\t}\r\n\r\n\t\tcase FREAD:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tvoid*\tdest\t\t= va_arg( vl, void* );\r\n\t\t\tint\t\tnum_bytes\t= va_arg( vl, int );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\treturn ( ( ( PCread( p_file->m_FileOpen, (char*)dest, num_bytes ) ) == SN_ERR ) ? 0 : 1 );\r\n\t\t}\r\n\r\n\t\tcase FSEEK:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tNsFileSeek\ttype\t= va_arg( vl, NsFileSeek );\r\n\t\t\tint\t\t\toffset\t= va_arg( vl, int );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\tswitch ( type )\r\n\t\t\t{\r\n\t\t\t\tcase NsFileSeek_End:\r\n\t\t\t\t\treturn PClseek( p_file->m_FileOpen, offset, SEEK_END );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase NsFileSeek_Current:\r\n\t\t\t\t\treturn PClseek( p_file->m_FileOpen, offset, SEEK_CUR );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\tcase NsFileSeek_Start:\r\n\t\t\t\t\treturn PClseek( p_file->m_FileOpen, offset, SEEK_SET );\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tcase FGETC:\r\n\t\t{\r\n\t\t\tchar c = EOF;\r\n\t\t\tPCread( p_file->m_FileOpen, &c, 1 ); \r\n\t\t\treturn c;\r\n\t\t}\r\n\r\n\t\tcase FGETS:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tchar*\tdest\t\t= va_arg( vl, char* );\r\n\t\t\tint\t\tnum_chars\t= va_arg( vl, int );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\tregister int c = EOF;\r\n\t\t\tregister char * cs;\r\n\r\n\t\t\tcs = dest;\r\n\t\t\tchar ch;\r\n\t\t\tch = EOF;\r\n\t\t\tPCread( p_file->m_FileOpen, &ch, 1 ); \r\n\t\t\twhile ( --num_chars > 0 && c != EOF ) {\r\n\t\t\t\tif ((*cs++ = c) == '\\n') break;\r\n\t\t\t\tch = EOF;\r\n\t\t\t\tPCread( p_file->m_FileOpen, &ch, 1 ); \r\n\t\t\t}\r\n\t\t\t*cs = '\\0';\r\n\t\t\treturn (int)((c == EOF && cs == dest) ? NULL : dest);\r\n\t\t}\r\n\r\n\t\tcase FCLOSE:\r\n\t\t{\r\n\t\t\treturn ( ( ( PCclose( p_file->m_FileOpen ) ) == SN_ERR ) ? 0 : 1 );\r\n\t\t}\r\n\r\n\t\tcase FEOF:\r\n\t\t{\r\n\t\t\tint current = PClseek( p_file->m_FileOpen, 0, SEEK_CUR );  \r\n\t\t\tint end = PClseek( p_file->m_FileOpen, 0, SEEK_END );  \r\n\t\t\tPClseek( p_file->m_FileOpen, current, SEEK_SET );\r\n\t\t\treturn ( current >= end ) ? 1 : 0;\r\n\t\t}\r\n\r\n\t\tcase FTELL:\r\n\t\t{\r\n\t\t\treturn PClseek( p_file->m_FileOpen, 0, SEEK_CUR );   \r\n\t\t}\r\n\r\n\t\tcase FEXIST:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tchar* raw_name\t= va_arg( vl, char* );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\tchar * name = dvd_file_fix_name( raw_name );\r\n\r\n\t\t\tint tag = PCopen( name, 0, 0 );\r\n\t\t\tif ( tag != SN_ERR )\r\n\t\t\t{\r\n\t\t\t\tPCclose( tag );\r\n\t\t\t\treturn 1;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Unknown file access type\" ));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n#else\r\n\r\n#ifdef DVDETH\r\n\tswitch( access_type )\r\n\t{\r\n\t\tcase FSIZE:\r\n\t\t{\r\n\t\t\treturn p_file->m_size;\r\n\t\t}\r\n\r\n\t\tcase FOPEN:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tchar* name\t= va_arg( vl, char* );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\t// Read the whole file.\r\n\t\t\tif ( DVDOpen( dvd_file_fix_name( name ), &p_file->m_FileInfo ) )\r\n\t\t\t{\r\n\t\t\t\tp_file->m_size = DVDGetLength ( &p_file->m_FileInfo );\r\n\t\t\t\tMem::Manager::sHandle().BottomUpHeap()->PushAlign( 32 );\r\n\t\t\t\tp_file->mp_data = new (Mem::Manager::sHandle().TopDownHeap()) char[p_file->m_size];\r\n\t\t\t\tMem::Manager::sHandle().BottomUpHeap()->PopAlign();\r\n\r\n\r\n\t\t\t\tint size = p_file->m_size;\r\n\t\t\t\tint off = 0;\r\n\t\t\t\twhile ( size )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( size > ( 512 * 1024 ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDVDRead( &p_file->m_FileInfo, &p_file->mp_data[off], ( 512 * 1024 ), off );\r\n\t\t\t\t\t\toff += ( 512 * 1024 );\r\n\t\t\t\t\t\tsize -= ( 512 * 1024 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDVDRead( &p_file->m_FileInfo, &p_file->mp_data[off], size, off );\r\n\t\t\t\t\t\tsize = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\r\n\r\n//\t\t\t\tDVDRead( &p_file->m_FileInfo, p_file->mp_data, p_file->m_size, 0 );\r\n\t\t\t\tDVDClose(&p_file->m_FileInfo);\r\n\t\t\t\tp_file->m_offset = 0;\r\n\t\t\t\treturn 1;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tp_file->mp_data = NULL;\r\n\t\t\t\tp_file->m_size = 0;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tcase FREAD:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tvoid*\tdest\t\t= va_arg( vl, void* );\r\n\t\t\tint\t\tnum_bytes\t= va_arg( vl, int );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\tmemcpy( dest, &p_file->mp_data[p_file->m_offset], num_bytes );\r\n\t\t\tp_file->m_offset += num_bytes;\r\n\r\n\t\t\treturn num_bytes;\r\n\t\t}\r\n\r\n\t\tcase FSEEK:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tNsFileSeek\ttype\t= va_arg( vl, NsFileSeek );\r\n\t\t\tint\t\t\toffset\t= va_arg( vl, int );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\tswitch ( type ) {\r\n\t\t\t\tcase NsFileSeek_Start:\r\n\t\t\t\t\tp_file->m_offset = offset;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase NsFileSeek_End:\r\n\r\n\t\t\t\t\tp_file->m_offset = p_file->m_size - offset;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase NsFileSeek_Current:\r\n\t\t\t\t\tp_file->m_offset += offset;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDbg_MsgAssert( 0, (\"Illegal seek type.\\n\"));\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\treturn 1;\r\n\t\t}\r\n\r\n\t\tcase FGETC:\r\n\t\t{\r\n\t\t\tchar character;\r\n\t\t\tmemcpy( &character, &p_file->mp_data[p_file->m_offset], 1 );\r\n\t\t\tp_file->m_offset += 1;\r\n\t\t\treturn (int)character;\r\n\t\t}\r\n\r\n\t\tcase FGETS:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tchar*\tdest\t\t= va_arg( vl, char* );\r\n\t\t\tint\t\tnum_chars\t= va_arg( vl, int );\r\n\t\t\tva_end( vl );\r\n\r\n\r\n\r\n\t\t\tregister int c = EOF;\r\n\t\t\tregister char * cs;\r\n\r\n\t\t\tcs = dest;\r\n\t\t\tmemcpy( &c, &p_file->mp_data[p_file->m_offset], 1 );\r\n\t\t\tp_file->m_offset += 1;\r\n\t\t\twhile ( --num_chars > 0 && c != EOF ) {\r\n\t\t\t\tif ((*cs++ = c) == '\\n') break;\r\n\t\t\t\tmemcpy( &c, &p_file->mp_data[p_file->m_offset], 1 );\r\n\t\t\t\tp_file->m_offset += 1;\r\n\t\t\t}\r\n\t\t\t*cs = '\\0';\r\n\t\t\treturn (c == EOF && cs == dest) ? NULL : (int)dest;\r\n\t\t}\r\n\r\n\t\tcase FCLOSE:\r\n\t\t{\r\n\t\t\tdelete p_file->mp_data;\r\n\t\t\treturn 0;\r\n//\t\t\treturn dvd_file_close( p_file );\r\n\t\t}\r\n\r\n\t\tcase FEOF:\r\n\t\t{\r\n\t\t\treturn ( p_file->m_offset >= p_file->m_size ) ? 1 : 0;\r\n\t\t}\r\n\r\n\t\tcase FTELL:\r\n\t\t{\r\n\t\t\treturn p_file->m_offset;\r\n\t\t}\r\n\r\n\t\tcase FEXIST:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tchar* name\t= va_arg( vl, char* );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\tDVDFileInfo info;\r\n\t\t\tif ( DVDOpen( name, &info ) )\r\n\t\t\t{\r\n\t\t\t\tDVDClose( &info );\r\n\t\t\t\treturn 1;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Unknown file access type\" ));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n#else\r\n//\tif( NsDisplay::shouldReset())\r\n//\t{\r\n//\t\t// Prepare the game side of things for reset.\r\n//\t\tSpt::SingletonPtr< Mlp::Manager > mlp_manager;\r\n//\t\tmlp_manager->PrepareReset();\r\n//\r\n//\t\t// Prepare the system side of things for reset.\r\n//\t\tNsDisplay::doReset();\r\n//\t}\r\n\r\n\tswitch( access_type )\r\n\t{\r\n\t\tcase FSIZE:\r\n\t\t{\r\n\t\t\treturn dvd_file_size( p_file );\t\t\t\r\n\t\t}\r\n\r\n\t\tcase FOPEN:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tchar* name\t= va_arg( vl, char* );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\t// Open mode not actually used in this context.\r\n\t\t\treturn dvd_file_open( p_file, name );\r\n\t\t}\r\n\r\n\t\tcase FREAD:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tvoid*\tdest\t\t= va_arg( vl, void* );\r\n\t\t\tint\t\tnum_bytes\t= va_arg( vl, int );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\treturn dvd_file_read( p_file, dest, num_bytes );\r\n\t\t}\r\n\r\n\t\tcase FSEEK:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tNsFileSeek\ttype\t= va_arg( vl, NsFileSeek );\r\n\t\t\tint\t\t\toffset\t= va_arg( vl, int );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\treturn dvd_file_seek( p_file, type, offset );\r\n\t\t}\r\n\r\n\t\tcase FGETC:\r\n\t\t{\r\n\t\t\treturn (int)dvd_file_getcharacter( p_file );\r\n\t\t}\r\n\r\n\t\tcase FGETS:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tchar*\tdest\t\t= va_arg( vl, char* );\r\n\t\t\tint\t\tnum_chars\t= va_arg( vl, int );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\treturn (int)dvd_file_gets( p_file, dest, num_chars );\r\n\t\t}\r\n\r\n\t\tcase FCLOSE:\r\n\t\t{\r\n\t\t\treturn dvd_file_close( p_file );\r\n\t\t}\r\n\r\n\t\tcase FEOF:\r\n\t\t{\r\n\t\t\treturn dvd_file_eof( p_file );\r\n\t\t}\r\n\r\n\t\tcase FTELL:\r\n\t\t{\r\n\t\t\treturn dvd_file_tell( p_file );\r\n\t\t}\r\n\r\n\t\tcase FEXIST:\r\n\t\t{\r\n\t\t\tva_list\tvl;\r\n\t\t\tva_start( vl, access_type );\r\n\t\t\tchar* name\t= va_arg( vl, char* );\r\n\t\t\tva_end( vl );\r\n\r\n\t\t\treturn dvd_file_exist( name );\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tDbg_MsgAssert( 0, ( \"Unknown file access type\" ));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n#endif\t\t// DVDETH\r\n#endif\t\t// __SN_FILE__\r\n\r\n\treturn 0;\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_dvd.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSkate3      \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSYS\t\t\t  \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t08/30/01\tdc\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tp_dvd.h\t\t               \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tGamecube DVD file acceess routines         \t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __P_DVD_H\r\n#define __P_DVD_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <dolphin.h>\r\n#include \"p_file.h\"\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint DVDFileAccess( NsFile* p_file, NsFileAccessType access_type, ... );\r\nvoid DVDWaitAsync( void );\r\nvoid DVDCheckAsync( void );\r\nint\tDVDError( void );\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#endif // __P_DVD_H\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_file.cpp",
    "content": "#include \"p_assert.h\"\r\n#include \"p_file.h\"\r\n#include \"p_dvd.h\"\r\n\r\n// Default to the DVD file access stuff.\r\nNsFileAccessFunction NsFile::m_file_access_function = DVDFileAccess;\r\n\r\nNsFile::NsFile()\r\n{\r\n\tm_FileOpen = 0;\r\n\tm_sizeCached = 0;\r\n\tm_numCacheBytes = 0;\r\n\tm_seekOffset = 0;\r\n\tm_preHandle = NULL;\r\n\tm_unique_tag = 0x1234ABCD;\r\n}\r\n\r\n\r\nNsFileAccessFunction NsFile::setFileAccessFunction( NsFileAccessFunction file_access_function )\r\n{\r\n\tNsFileAccessFunction old\t= m_file_access_function; \r\n\tm_file_access_function\t\t= file_access_function;\r\n\treturn old;\r\n}\r\n\r\n\r\n\r\nvoid NsFile::GetCacheBytes ( void * pDest, int numBytes )\r\n{\r\n\tmemcpy ( pDest, &m_cachedBytes[0], numBytes );\r\n\tDCFlushRange(pDest, numBytes );\r\n\t// Update the cache.\r\n\tm_numCacheBytes -= numBytes;\r\n\tif ( m_numCacheBytes ) memcpy ( &m_cachedBytes[0], &m_cachedBytes[numBytes], m_numCacheBytes );\r\n}\r\n\r\n\r\nbool NsFile::open ( const char * pFilename )\r\n{\r\n\tassert( m_file_access_function );\r\n\r\n\r\n\treturn (bool)m_file_access_function( this, FOPEN, pFilename, \"rb\" );\r\n}\r\n\r\nint NsFile::size ( void )\r\n{\r\n\tassert( m_file_access_function );\r\n\r\n\treturn m_file_access_function( this, FSIZE );\r\n}\r\n\r\nint NsFile::read ( void *pDest, int numBytes )\r\n{\r\n\tassert( m_file_access_function );\r\n\r\n\treturn m_file_access_function( this, FREAD, pDest, numBytes );\r\n}\r\n\r\nvoid NsFile::seek ( NsFileSeek type, int offset )\r\n{\r\n\tassert( m_file_access_function );\r\n\r\n\t// Horrible hack to fix seek bugs.\r\n\tm_file_access_function( this, FSEEK, type, offset );\r\n}\r\n\r\nvoid NsFile::close ( void )\r\n{\r\n\tassert( m_file_access_function );\r\n\r\n\tm_file_access_function( this, FCLOSE );\r\n}\r\n\r\nint NsFile::exist ( const char * pFilename )\r\n{\r\n\tassert( m_file_access_function );\r\n\r\n\treturn m_file_access_function( this, FEXIST, pFilename );\r\n}\r\n\r\nchar NsFile::getcharacter ( void )\r\n{\r\n\tassert( m_file_access_function );\r\n\r\n\treturn (char)m_file_access_function( this, FGETC );\r\n}\r\n\r\nchar * NsFile::gets ( char * s, int n )\r\n{\r\n\tassert( m_file_access_function );\r\n\r\n\treturn (char*)m_file_access_function( this, FGETS, s, n );\r\n}\r\n\r\nint NsFile::eof ( void )\r\n{\r\n\tassert( m_file_access_function );\r\n\r\n\treturn m_file_access_function( this, FEOF );\r\n}\r\n\r\nint NsFile::tell ( void )\r\n{\r\n\tassert( m_file_access_function );\r\n\r\n\treturn (int)m_file_access_function( this, FTELL );\r\n}\r\n\r\nvoid * NsFile::load ( const char * pFilename )\r\n{\r\n\tbool open_result = open ( pFilename );\r\n\r\n\tif( open_result ) {\r\n\t\tvoid * pDest = new unsigned char[size()];\r\n\t\tread ( pDest, size() );\r\n\r\n\t\tclose();\r\n\r\n\t\treturn pDest;\r\n\t}\r\n\telse {\r\n\t\treturn NULL;\r\n\t}\r\n}\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_file.h",
    "content": "#ifndef _FILE_H_\r\n#define _FILE_H_\r\n\r\n#include <stdarg.h>\r\n#include <dolphin.h>\r\n\r\ntypedef enum {\r\n\tNsFileSeek_Start = 0,\r\n\tNsFileSeek_End,\r\n\tNsFileSeek_Current,\r\n\r\n\tNsFileSeek_Pos = NsFileSeek_Current,\r\n\r\n\tNsFileSeek_Max\r\n} NsFileSeek;\r\n\r\ntypedef enum\r\n{\r\n\tFSIZE,\r\n\tFOPEN,\r\n\tFREAD,\r\n\tFSEEK,\r\n\tFGETC,\r\n\tFGETS,\r\n\tFCLOSE,\r\n\tFEOF,\r\n\tFTELL,\r\n\tFEXIST\r\n} NsFileAccessType;\r\n\r\n\r\n\r\nclass NsFile;\r\ntypedef int (*NsFileAccessFunction)( NsFile* p_file, NsFileAccessType access_type, ... );\r\n\r\n\r\nclass NsFile\r\n{\r\npublic:\r\n\tunsigned int\t\t\t\tm_unique_tag;\r\n\r\n\tchar\t\t\t\t\t\tm_cachedBytes[32];\r\n\tvoid\t\t\t\t\t  *\tm_preHandle;\r\n\r\n\tDVDFileInfo\t\t\t\t\tm_FileInfo;\r\n\r\n\tint\t\t\t\t\t\t\tm_FileOpen;\r\n\tint\t\t\t\t\t\t\tm_sizeCached;\r\n\tint\t\t\t\t\t\t\tm_cachedSize;\r\n\r\n#ifdef DVDETH\r\n\tchar\t\t\t\t\t  * mp_data;\r\n\tint\t\t\t\t\t\t\tm_size;\r\n\tint\t\t\t\t\t\t\tm_offset;\r\n#endif\t\t// DVDETH\r\n\r\n\tint\t\t\t\t\t\t\tm_numCacheBytes;\r\n\tint\t\t\t\t\t\t\tm_seekOffset;\r\n\r\n\tvoid\t\t\t\t\t\tGetCacheBytes\t\t\t( void * pDest, int numBytes );\r\n\tchar\t\t\t\t\t\tgetcharacter\t\t\t( void );\r\n\r\n\t\t\t\t\t\t\t\tNsFile\t\t\t\t\t();\r\n\r\n\tbool\t\t\t\t\t\topen\t\t\t\t\t( const char * pFilename );\r\n\tint\t\t\t\t\t\t\tsize\t\t\t\t\t( void );\r\n\tint\t\t\t\t\t\t\tread\t\t\t\t\t( void *pDest, int numBytes );\r\n//\tchar\t\t\t\t\t\tgetc\t\t\t\t\t( void );\r\n\tchar\t\t\t\t\t  * gets\t\t\t\t\t( char * s, int n );\r\n\tvoid\t\t\t\t\t\tseek\t\t\t\t\t( NsFileSeek type, int offset );\r\n\tvoid\t\t\t\t\t\tclose\t\t\t\t\t( void );\r\n\tint\t\t\t\t\t\t\texist\t\t\t\t\t( const char * pFilename );\r\n\tint\t\t\t\t\t\t\teof\t\t\t\t\t\t( void );\r\n\tint\t\t\t\t\t\t\ttell\t\t\t\t\t( void );\r\n\tvoid\t\t\t\t\t  * load\t\t\t\t\t( const char * pFilename );\r\n\tstatic NsFileAccessFunction\tsetFileAccessFunction\t( NsFileAccessFunction file_access_function );\r\n\r\n\tbool\t\t\t\t\t\tverify\t\t\t\t\t( void )\t\t{ return ( m_unique_tag == 0x1234ABCD ) ? true : false; }\r\n\r\nprivate:\r\n\r\n\tstatic NsFileAccessFunction\tm_file_access_function;\r\n};\r\n\r\n\r\n\r\n\r\n#endif\t\t// _FILE_H_\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_font.cpp",
    "content": "//#define _b(a) (((a>>(0-0))&1)|((a>>(4-1))&2)|((a>>(8-2))&4)|((a>>(12-3))&8)|((a>>(16-4))&16)|((a>>(20-5))&32)|((a>>(24-6))&64)|((a>>(28-7))&128))\r\n//\r\n//unsigned char debugFont[(512/8)*128] = {\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x11100000),_b(0x00000111),_b(0x11100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00011100),_b(0x00000000),_b(0x10000000),\r\n//_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x10000000),_b(0x00000100),_b(0x00010000),_b(0x00000111),_b(0x11110000),_b(0x00000011),_b(0x11111100),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00011000),_b(0x00011000),_b(0x00011111),_b(0x11111000),_b(0x00011110),_b(0x00111100),_b(0x00000001),_b(0x11000000),_b(0x00000111),_b(0x11100000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111110),_b(0x00000000),_b(0x01111100),_b(0x00000000),_b(0x01110000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x11111100),_b(0x00000000),_b(0x10000000),\r\n//_b(0x11100000),_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x00000001),_b(0x11000000),_b(0x00000100),_b(0x00010000),_b(0x00011100),_b(0x10010000),_b(0x00000110),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x11000000),\r\n//_b(0x00000001),_b(0x11000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x01111111),_b(0x11111110),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00110000),_b(0x00001100),_b(0x00111111),_b(0x11111100),_b(0x00111111),_b(0x01111110),_b(0x00000011),_b(0x11100000),_b(0x00001111),_b(0x11110000),_b(0x00000001),_b(0x11000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11000000),_b(0x11111111),_b(0x11111110),_b(0x00000000),_b(0x00101100),_b(0x00000000),_b(0x10001000),_b(0x00000001),_b(0x00000000),_b(0x00000111),_b(0x11100100),_b(0x00100000),_b(0x10000010),\r\n//_b(0x11111000),_b(0x00000000),_b(0x00000000),_b(0x00011111),_b(0x00000011),_b(0x11100000),_b(0x00000100),_b(0x00010000),_b(0x00111000),_b(0x10010000),_b(0x00011100),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11100000),\r\n//_b(0x00000011),_b(0x11100000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x01111111),_b(0x11111110),\r\n//_b(0x00000000),_b(0x00000000),_b(0x01100000),_b(0x00000110),_b(0x01111111),_b(0x11111110),_b(0x00111111),_b(0x01111110),_b(0x00000111),_b(0x11110000),_b(0x00001111),_b(0x11110000),_b(0x00000001),_b(0x11000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01111111),_b(0x11111100),_b(0x00001100),_b(0x00110000),_b(0x11111000),_b(0x00111110),_b(0x00000000),_b(0x01001100),_b(0x00000001),_b(0x00000100),_b(0x00000001),_b(0x10000000),_b(0x00000111),_b(0x00000100),_b(0x00010011),_b(0x11100100),\r\n//_b(0x11111110),_b(0x00000000),_b(0x00000000),_b(0x01111111),_b(0x00000010),_b(0x10100000),_b(0x00000100),_b(0x00010000),_b(0x00110000),_b(0x10010000),_b(0x00110011),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x10100000),\r\n//_b(0x00000110),_b(0x10100000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11000000),_b(0x00111111),_b(0x11111100),\r\n//_b(0x00000000),_b(0x00000000),_b(0x01000000),_b(0x00000010),_b(0x01111111),_b(0x11111110),_b(0x00111111),_b(0x11111110),_b(0x00000111),_b(0x11110000),_b(0x00001111),_b(0x11110000),_b(0x00000011),_b(0x11110000),_b(0x00000001),_b(0x11000000),\r\n//_b(0x01111111),_b(0x11111100),_b(0x00010000),_b(0x00001000),_b(0x11110000),_b(0x00011110),_b(0x00000000),_b(0x10000100),_b(0x00000001),_b(0x00000100),_b(0x00000001),_b(0x11000000),_b(0x00000100),_b(0x01111100),_b(0x00001100),_b(0x00011000),\r\n//_b(0x11111111),_b(0x10000000),_b(0x00000001),_b(0x11111111),_b(0x00000100),_b(0x10010000),_b(0x00000100),_b(0x00010000),_b(0x00110000),_b(0x10010000),_b(0x00100000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x10010000),\r\n//_b(0x00000100),_b(0x10010000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11000000),_b(0x00111111),_b(0x11111100),\r\n//_b(0x00000000),_b(0x00000000),_b(0x10001100),_b(0x00110001),_b(0x11110011),_b(0x11001111),_b(0x00111111),_b(0x11111110),_b(0x00001111),_b(0x11111000),_b(0x00111111),_b(0x11101110),_b(0x00001111),_b(0x11111000),_b(0x00000011),_b(0x11100000),\r\n//_b(0x01111111),_b(0x11111100),_b(0x00010000),_b(0x00001000),_b(0x11100011),_b(0x10001110),_b(0x00001111),_b(0x10000100),_b(0x00000001),_b(0x00000100),_b(0x00000001),_b(0x11100000),_b(0x00000111),_b(0x11111100),_b(0x00001000),_b(0x00001100),\r\n//_b(0x11111111),_b(0x11100000),_b(0x00000111),_b(0x11111111),_b(0x00000000),_b(0x10000000),_b(0x00000100),_b(0x00010000),_b(0x00110000),_b(0x10010000),_b(0x00100000),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x11100000),_b(0x00011111),_b(0x11111000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x10001100),_b(0x00110001),_b(0x11110011),_b(0x11001111),_b(0x00011111),_b(0x11111100),_b(0x00011111),_b(0x11111100),_b(0x01111111),_b(0x11111111),_b(0x00011111),_b(0x11111100),_b(0x00000111),_b(0x11110000),\r\n//_b(0x01111111),_b(0x11111100),_b(0x00100000),_b(0x00000100),_b(0x11000111),_b(0x11000110),_b(0x00010000),_b(0x10000000),_b(0x00000000),_b(0x10001000),_b(0x00000001),_b(0x00110000),_b(0x00000111),_b(0x11000100),_b(0x00010000),_b(0x00000100),\r\n//_b(0x11111111),_b(0x11111000),_b(0x00011111),_b(0x11111111),_b(0x00000000),_b(0x10000000),_b(0x00000100),_b(0x00010000),_b(0x00111000),_b(0x10010000),_b(0x00110000),_b(0x00110000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x11100000),_b(0x00011111),_b(0x11111000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x11111111),_b(0x11111111),_b(0x00011111),_b(0x11111100),_b(0x00111111),_b(0x11111110),_b(0x11111111),_b(0x11111111),_b(0x00111111),_b(0x11111110),_b(0x00000111),_b(0x11110000),\r\n//_b(0x01111100),_b(0x01111100),_b(0x00100000),_b(0x00000100),_b(0x11001111),_b(0x11100110),_b(0x00100000),_b(0x01000000),_b(0x00000000),_b(0x01110000),_b(0x00000001),_b(0x00010000),_b(0x00000100),_b(0x00000100),_b(0x11110000),_b(0x00000111),\r\n//_b(0x11111111),_b(0x11111110),_b(0x01111111),_b(0x11111111),_b(0x00000000),_b(0x10000000),_b(0x00000100),_b(0x00010000),_b(0x00011100),_b(0x10010000),_b(0x00011000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001111),_b(0x11110000),_b(0x00001111),_b(0x11110000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x11111111),_b(0x11111111),_b(0x00001111),_b(0x11111000),_b(0x00011111),_b(0x11111100),_b(0x11111111),_b(0x11111111),_b(0x00111111),_b(0x11111110),_b(0x00000111),_b(0x11110000),\r\n//_b(0x01111000),_b(0x00111100),_b(0x00100000),_b(0x00000100),_b(0x11001111),_b(0x11100110),_b(0x00100000),_b(0x01000000),_b(0x00000000),_b(0x00100000),_b(0x00000001),_b(0x00010000),_b(0x00000100),_b(0x00000100),_b(0x00010000),_b(0x00000100),\r\n//_b(0x11111111),_b(0x11111110),_b(0x01111111),_b(0x11111111),_b(0x00000000),_b(0x10000000),_b(0x00000100),_b(0x00010000),_b(0x00000111),_b(0x10010000),_b(0x00001100),_b(0x00000100),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00001111),_b(0x11110000),_b(0x00001111),_b(0x11110000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x11111111),_b(0x11111111),_b(0x00000111),_b(0x11110000),_b(0x00001111),_b(0x11111000),_b(0x11111111),_b(0x11111111),_b(0x00111111),_b(0x11111110),_b(0x00000011),_b(0x11100000),\r\n//_b(0x01111000),_b(0x00111100),_b(0x00100000),_b(0x00000100),_b(0x11001111),_b(0x11100110),_b(0x00100000),_b(0x01000000),_b(0x00000000),_b(0x00100000),_b(0x00000001),_b(0x00010000),_b(0x00000100),_b(0x00000100),_b(0x00010000),_b(0x00000100),\r\n//_b(0x11111111),_b(0x11111000),_b(0x00011111),_b(0x11111111),_b(0x00000000),_b(0x10000000),_b(0x00000100),_b(0x00010000),_b(0x00000000),_b(0x10010000),_b(0x00000110),_b(0x00000010),_b(0x11111111),_b(0x11111111),_b(0x00000100),_b(0x10010000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00110000),_b(0x00001100),_b(0x00011111),_b(0x11111000),_b(0x00000111),_b(0x11100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x10001100),_b(0x00110001),_b(0x11111011),_b(0x11011111),_b(0x00000111),_b(0x11110000),_b(0x00000111),_b(0x11110000),_b(0x01111110),_b(0x10111110),_b(0x00111111),_b(0x11111110),_b(0x00000001),_b(0x11000000),\r\n//_b(0x01111000),_b(0x00111100),_b(0x00010000),_b(0x00001000),_b(0x11000111),_b(0x11000110),_b(0x00100000),_b(0x01000000),_b(0x00000001),_b(0x11111100),_b(0x00000001),_b(0x00010000),_b(0x00000100),_b(0x00000100),_b(0x00001000),_b(0x00001000),\r\n//_b(0x11111111),_b(0x11100000),_b(0x00000111),_b(0x11111111),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10010000),_b(0x00000001),_b(0x10000010),_b(0x11111111),_b(0x11111111),_b(0x00000010),_b(0x10100000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x01100000),_b(0x00000110),_b(0x00011111),_b(0x11111000),_b(0x00000111),_b(0x11100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x01000100),_b(0x00100010),_b(0x01111000),_b(0x00011110),_b(0x00000011),_b(0x11100000),_b(0x00000111),_b(0x11110000),_b(0x00111100),_b(0x10011100),_b(0x00011110),_b(0x10111100),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01111100),_b(0x01111100),_b(0x00010000),_b(0x00001000),_b(0x11100011),_b(0x10001110),_b(0x00010000),_b(0x10000000),_b(0x00000000),_b(0x00100000),_b(0x00000001),_b(0x00100000),_b(0x00000100),_b(0x00111100),_b(0x00001100),_b(0x00011000),\r\n//_b(0x11111111),_b(0x10000000),_b(0x00000001),_b(0x11111111),_b(0x00000100),_b(0x10010000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10010000),_b(0x00000000),_b(0x01000110),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11100000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000100),_b(0x10010000),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x10000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00111111),_b(0x11111100),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x01100011),_b(0x11000110),_b(0x01111100),_b(0x00111110),_b(0x00000001),_b(0x11000000),_b(0x00000011),_b(0x11100000),_b(0x00000001),_b(0x11000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01111111),_b(0x11111100),_b(0x00001100),_b(0x00110000),_b(0x11110000),_b(0x00011110),_b(0x00001111),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00000111),_b(0x00000000),_b(0x00111100),_b(0x01111100),_b(0x00010011),_b(0x11100100),\r\n//_b(0x11111110),_b(0x00000000),_b(0x00000000),_b(0x01111111),_b(0x00000010),_b(0x10100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10010000),_b(0x00000000),_b(0x00111100),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x11000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000110),_b(0x10100000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x01100000),_b(0x00000110),_b(0x00111111),_b(0x11111100),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00110000),_b(0x00001100),_b(0x00111111),_b(0x11111100),_b(0x00000001),_b(0x11000000),_b(0x00000001),_b(0x11000000),_b(0x00000001),_b(0x11100000),_b(0x00000001),_b(0x11000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01111111),_b(0x11111100),_b(0x00000011),_b(0x11000000),_b(0x11111000),_b(0x00111110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00001111),_b(0x00000000),_b(0x01111100),_b(0x01111000),_b(0x00100000),_b(0x10000010),\r\n//_b(0x11111000),_b(0x00000000),_b(0x00000000),_b(0x00011111),_b(0x00000011),_b(0x11100000),_b(0x00001110),_b(0x00111000),_b(0x00000000),_b(0x10010000),_b(0x00010000),_b(0x00010000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000011),_b(0x11100000),_b(0x00000000),_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00110000),_b(0x00001100),_b(0x01111111),_b(0x11111110),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00011000),_b(0x00011000),_b(0x00011111),_b(0x11111000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000111),_b(0x11111000),_b(0x00000011),_b(0x11110000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01111111),_b(0x11111100),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001111),_b(0x00000000),_b(0x01111000),_b(0x01110000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x11100000),_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x00000001),_b(0x11000000),_b(0x00001110),_b(0x00111000),_b(0x00000000),_b(0x10010000),_b(0x00010000),_b(0x00110000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x11000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x01111111),_b(0x11111110),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x11100000),_b(0x00000111),_b(0x11100000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00011111),_b(0x11111110),_b(0x00011111),_b(0x11111100),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01111111),_b(0x11111100),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001110),_b(0x00000000),_b(0x01110000),_b(0x00000000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x10000000),_b(0x00001110),_b(0x00111000),_b(0x00000111),_b(0x11111100),_b(0x00011111),_b(0x11100000),_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x11110000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00011100),_b(0x01110000),_b(0x00000001),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00000110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00100000),\r\n//_b(0x00000011),_b(0x11000000),_b(0x00000001),_b(0x10000000),_b(0x00000011),_b(0x11000000),_b(0x00000111),_b(0x11000000),_b(0x00000000),_b(0x01100000),_b(0x00011111),_b(0x11100000),_b(0x00000000),_b(0x01111100),_b(0x00011111),_b(0x11110000),\r\n//_b(0x00000011),_b(0x11000000),_b(0x00000011),_b(0x11100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00011100),_b(0x01110000),_b(0x00000001),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00001001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00000000),_b(0x00110000),_b(0x00001100),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00100000),\r\n//_b(0x00000100),_b(0x00100000),_b(0x00000111),_b(0x10000000),_b(0x00001100),_b(0x00110000),_b(0x00001100),_b(0x00100000),_b(0x00000000),_b(0x10100000),_b(0x00010000),_b(0x00000000),_b(0x00000001),_b(0x10000100),_b(0x00010000),_b(0x00010000),\r\n//_b(0x00001100),_b(0x00110000),_b(0x00000110),_b(0x00010000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001100),_b(0x00110000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00011100),_b(0x01110000),_b(0x00000001),_b(0x00010000),_b(0x00000111),_b(0x10000000),_b(0x00010000),_b(0x10000000),_b(0x00000011),_b(0x11100000),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00000000),_b(0x00100000),_b(0x00000100),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x01000000),\r\n//_b(0x00001000),_b(0x00010000),_b(0x00011000),_b(0x10000000),_b(0x00001000),_b(0x00010000),_b(0x00010000),_b(0x00010000),_b(0x00000000),_b(0x10100000),_b(0x00010000),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00010000),_b(0x00010000),\r\n//_b(0x00001000),_b(0x00010000),_b(0x00000100),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00011000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00001100),_b(0x00110000),_b(0x00000010),_b(0x00100000),_b(0x00001000),_b(0x01110000),_b(0x00010000),_b(0x10000000),_b(0x00000110),_b(0x00000000),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00000000),_b(0x01100000),_b(0x00000110),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x01000000),\r\n//_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x00010000),_b(0x00000001),_b(0x00100000),_b(0x00010000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00100000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11000000),_b(0x00000000),_b(0x00001100),_b(0x00000000),_b(0x00000000),_b(0x00110000),_b(0x00000000),_b(0x00001000),_b(0x00001000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00001100),_b(0x00110000),_b(0x00000010),_b(0x00100000),_b(0x00010000),_b(0x00010000),_b(0x00001001),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00000000),_b(0x01000000),_b(0x00000010),_b(0x00000000),_b(0x00011001),_b(0x00011000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x00010000),_b(0x00000001),_b(0x00100000),_b(0x00010000),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00100000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00000100),_b(0x00000001),_b(0x10000000),_b(0x00000011),_b(0x11000000),_b(0x00000000),_b(0x00110000),_b(0x00000000),_b(0x00000000),_b(0x00001100),_b(0x00000000),_b(0x00000000),_b(0x00001000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00001100),_b(0x00110000),_b(0x00011111),_b(0x11111100),_b(0x00010000),_b(0x00010000),_b(0x00000110),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00000000),_b(0x01000000),_b(0x00000010),_b(0x00000000),_b(0x00000111),_b(0x11100000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00010000),_b(0x00000010),_b(0x00100000),_b(0x00010000),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00100000),\r\n//_b(0x00010000),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x00000011),_b(0x11000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x00000000),_b(0x00000000),_b(0x00001000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00001100),_b(0x00110000),_b(0x00000010),_b(0x00100000),_b(0x00010000),_b(0x00000000),_b(0x00000000),_b(0x00111000),_b(0x00000100),_b(0x00000000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00100000),_b(0x00000000),_b(0x00100000),_b(0x00000010),_b(0x00100000),_b(0x00010111),_b(0x11000000),_b(0x00001000),_b(0x11110000),_b(0x00000000),_b(0x00100000),\r\n//_b(0x00001000),_b(0x00010000),_b(0x00000100),_b(0x00001100),_b(0x00000011),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00010000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x00100000),_b(0x00001110),_b(0x00000000),_b(0x00000011),_b(0x11000000),_b(0x00000010),_b(0x00000000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x01000000),_b(0x00000001),_b(0x11000000),_b(0x00000100),_b(0x00100000),_b(0x00011000),_b(0x00110000),_b(0x00001011),_b(0x00001000),_b(0x00000000),_b(0x01000000),\r\n//_b(0x00000111),_b(0x11100000),_b(0x00000110),_b(0x00010100),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x00000000),_b(0x01111111),_b(0x11111100),_b(0x00000000),_b(0x01100000),_b(0x00000000),_b(0x01100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x00100000),_b(0x00000001),_b(0x11100000),_b(0x00011100),_b(0x00000000),_b(0x00000110),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x00000000),_b(0x00000010),_b(0x01000000),_b(0x00000000),_b(0x10000000),_b(0x00000011),_b(0x11000000),_b(0x00111111),_b(0x11111000),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000000),_b(0x00010000),_b(0x00001010),_b(0x00001000),_b(0x00000000),_b(0x01000000),\r\n//_b(0x00001000),_b(0x00010000),_b(0x00000001),_b(0x11100100),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00011000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00011000),_b(0x00000001),_b(0x11000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x00100000),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x11000000),_b(0x00001001),_b(0x00011000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x00000000),_b(0x00000100),_b(0x00100000),_b(0x00111111),_b(0x11111110),_b(0x00000011),_b(0x10000000),_b(0x00111111),_b(0x11111000),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000000),_b(0x00001000),_b(0x00001100),_b(0x00000100),_b(0x00000000),_b(0x01000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11000000),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00011111),_b(0x11111100),_b(0x00000000),_b(0x00001000),_b(0x00000001),_b(0x00100000),_b(0x00010000),_b(0x10010000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x01000000),_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000111),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00100000),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x01000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x10000000),_b(0x00011000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00011000),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x00100000),_b(0x00100000),_b(0x00001000),_b(0x00000010),_b(0x00010000),_b(0x00010000),_b(0x10100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x01000000),_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000111),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00010000),_b(0x00100000),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x00000000),_b(0x00000110),_b(0x00000000),_b(0x01111111),_b(0x11111100),_b(0x00000000),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x00100000),_b(0x00100000),_b(0x00011000),_b(0x00000010),_b(0x00010000),_b(0x00010000),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x01100000),_b(0x00000110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000111),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00001000),_b(0x00000000),\r\n//_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x10000000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00011111),_b(0x11111000),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x00001000),_b(0x00000001),_b(0x10000000),_b(0x00000111),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x01000000),_b(0x00110000),_b(0x00110000),_b(0x00000001),_b(0x00100000),_b(0x00010000),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00100000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00001110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11000000),_b(0x00001000),_b(0x00000000),\r\n//_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00000000),_b(0x00110000),_b(0x00010000),_b(0x00000000),_b(0x00100000),_b(0x00100000),_b(0x00010000),_b(0x00000100),_b(0x00001000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x00010000),_b(0x00000011),_b(0x11000000),_b(0x00000110),_b(0x00000000),_b(0x00000000),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x00000000),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x01000000),_b(0x00101111),_b(0x11000000),_b(0x00000000),_b(0x11000000),_b(0x00001000),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00110000),_b(0x00001100),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00001100),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11000000),_b(0x00010000),_b(0x00000000),\r\n//_b(0x00000100),_b(0x00100000),_b(0x00000000),_b(0x10000000),_b(0x00100000),_b(0x00001000),_b(0x00011000),_b(0x00100000),_b(0x00000000),_b(0x00100000),_b(0x00010000),_b(0x00100000),_b(0x00000010),_b(0x00011000),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00001100),_b(0x00010000),_b(0x00000000),_b(0x01100000),_b(0x00000011),_b(0x11000000),_b(0x00001110),_b(0x00000000),_b(0x00000000),_b(0x00110000),_b(0x00000000),_b(0x00000000),_b(0x00001100),_b(0x00000000),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x01000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x10011000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00001100),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00010000),_b(0x00000000),\r\n//_b(0x00000011),_b(0x11000000),_b(0x00011111),_b(0x11111100),_b(0x00111111),_b(0x11111000),_b(0x00000111),_b(0x11000000),_b(0x00000001),_b(0x11111000),_b(0x00001111),_b(0x11000000),_b(0x00000001),_b(0x11110000),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00000011),_b(0x11100000),_b(0x00001111),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00001100),_b(0x00000000),_b(0x00000000),_b(0x00001100),_b(0x00000000),_b(0x00000000),_b(0x00110000),_b(0x00000000),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00000011),_b(0x11100000),_b(0x00011111),_b(0x10000000),_b(0x00111111),_b(0x11100000),_b(0x00000111),_b(0x11100100),_b(0x00111111),_b(0x11100000),_b(0x00111111),_b(0x11111100),_b(0x00111111),_b(0x11111100),_b(0x00000011),_b(0x11100100),\r\n//_b(0x01111100),_b(0x00111110),_b(0x00111111),_b(0x11111000),_b(0x00000011),_b(0x11111110),_b(0x00111110),_b(0x00001111),_b(0x00111111),_b(0x10000000),_b(0x11110000),_b(0x00001111),_b(0x01110000),_b(0x00111110),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00111111),_b(0x11100000),_b(0x00000011),_b(0x11100000),_b(0x00111111),_b(0x11100000),_b(0x00000111),_b(0x11101000),_b(0x00111111),_b(0x11111110),_b(0x01111100),_b(0x00111110),_b(0x11111000),_b(0x00011111),_b(0x11111100),_b(0x00011111),\r\n//_b(0x01111000),_b(0x00111100),_b(0x00111100),_b(0x00011110),_b(0x00011111),_b(0x11111000),_b(0x00000001),_b(0x11100000),_b(0x00010000),_b(0x00000000),_b(0x00001111),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000100),_b(0x00010000),_b(0x00000001),_b(0x10000000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010100),_b(0x00001000),_b(0x00011000),_b(0x00001000),_b(0x00000100),_b(0x00001000),_b(0x00000100),_b(0x00001100),_b(0x00011100),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x00000100),_b(0x00000000),_b(0x00110000),_b(0x00001100),_b(0x00011000),_b(0x00001000),_b(0x00001100),_b(0x00110000),\r\n//_b(0x00001000),_b(0x00010000),_b(0x00001100),_b(0x00110000),_b(0x00001000),_b(0x00011000),_b(0x00001000),_b(0x00111000),_b(0x00100000),_b(0x10000010),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000010),\r\n//_b(0x00010000),_b(0x00010000),_b(0x00010000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00001000),_b(0x00001000),_b(0x00000010),_b(0x01000000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00001100),_b(0x00001000),_b(0x00001000),_b(0x00001000),_b(0x00000100),_b(0x00001000),_b(0x00000100),_b(0x00010000),_b(0x00000100),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x00101000),_b(0x00010100),_b(0x00011000),_b(0x00001000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00011000),_b(0x00100000),_b(0x10000010),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000010),\r\n//_b(0x00001000),_b(0x00100000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000010),_b(0x01000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000010),_b(0x01000000),_b(0x00001000),_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00001000),_b(0x00000100),_b(0x00001000),_b(0x00000100),_b(0x00001000),_b(0x00000100),_b(0x00010000),_b(0x00000100),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00000100),_b(0x00000000),_b(0x00101000),_b(0x00010100),_b(0x00010100),_b(0x00001000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00001000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00001000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x10000010),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000010),\r\n//_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00010000),_b(0x00100000),_b(0x00000001),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000100),_b(0x00100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x01111000),_b(0x00000010),_b(0x01000000),_b(0x00001000),_b(0x00001000),_b(0x01000000),_b(0x00000100),_b(0x00001000),_b(0x00000010),_b(0x00001000),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00100000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00000000),_b(0x00100100),_b(0x00100100),_b(0x00010110),_b(0x00001000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00001000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00001000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x10000010),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x11000010),\r\n//_b(0x00000100),_b(0x01000000),_b(0x00000100),_b(0x00010000),_b(0x00010000),_b(0x00100000),_b(0x00000001),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x10001000),_b(0x00000100),_b(0x00100000),_b(0x00001000),_b(0x00001000),_b(0x01000000),_b(0x00000000),_b(0x00001000),_b(0x00000010),_b(0x00001000),_b(0x01000000),_b(0x00001000),_b(0x01000000),_b(0x00100000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x11000000),_b(0x00000100),_b(0x00000000),_b(0x00100100),_b(0x00100100),_b(0x00010010),_b(0x00001000),_b(0x01000000),_b(0x00000010),\r\n//_b(0x00001000),_b(0x00000100),_b(0x01000000),_b(0x00000010),_b(0x00001000),_b(0x00000100),_b(0x00011000),_b(0x00000000),_b(0x00100000),_b(0x10000010),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x11000010),\r\n//_b(0x00000010),_b(0x10000000),_b(0x00000010),_b(0x00100000),_b(0x00000000),_b(0x01000000),_b(0x00000001),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010001),_b(0x00001000),_b(0x00000100),_b(0x00100000),_b(0x00001000),_b(0x00010000),_b(0x01000000),_b(0x00000000),_b(0x00001000),_b(0x00000010),_b(0x00001000),_b(0x01000000),_b(0x00001000),_b(0x01000000),_b(0x00100000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00001001),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00100010),_b(0x00100100),_b(0x00010001),_b(0x00001000),_b(0x01000000),_b(0x00000010),\r\n//_b(0x00001000),_b(0x00000100),_b(0x01000000),_b(0x00000010),_b(0x00001000),_b(0x00001000),_b(0x00001100),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00010001),_b(0x00100100),\r\n//_b(0x00000010),_b(0x10000000),_b(0x00000001),_b(0x01000000),_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010001),_b(0x00001000),_b(0x00000100),_b(0x00100000),_b(0x00001111),_b(0x11100000),_b(0x01000000),_b(0x00000000),_b(0x00001000),_b(0x00000010),_b(0x00001111),_b(0x11000000),_b(0x00001111),_b(0x11000000),_b(0x00100000),_b(0x00000000),\r\n//_b(0x00011111),_b(0x11111000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00001011),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00100010),_b(0x01000100),_b(0x00010001),_b(0x00001000),_b(0x01000000),_b(0x00000010),\r\n//_b(0x00001000),_b(0x00001000),_b(0x01000000),_b(0x00000010),_b(0x00001000),_b(0x00011000),_b(0x00000011),_b(0x11000000),_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00010001),_b(0x00100100),\r\n//_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x01000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010001),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x01000000),_b(0x00000000),_b(0x00001000),_b(0x00000010),_b(0x00001000),_b(0x01000000),_b(0x00001000),_b(0x01000000),_b(0x00100000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00001100),_b(0x10000000),_b(0x00000100),_b(0x00000000),_b(0x00100001),_b(0x01000100),_b(0x00010000),_b(0x10001000),_b(0x01000000),_b(0x00000010),\r\n//_b(0x00001000),_b(0x00010000),_b(0x00100000),_b(0x00000100),_b(0x00001111),_b(0x11100000),_b(0x00000000),_b(0x00110000),_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x00100000),_b(0x00010001),_b(0x00100100),\r\n//_b(0x00000010),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x10001000),_b(0x00001111),_b(0x11110000),_b(0x00001000),_b(0x00001000),_b(0x01000000),_b(0x00000000),_b(0x00001000),_b(0x00000010),_b(0x00001000),_b(0x01000000),_b(0x00001000),_b(0x01000000),_b(0x00100000),_b(0x11111111),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00010000),_b(0x00001000),_b(0x01100000),_b(0x00000100),_b(0x00000000),_b(0x00100001),_b(0x10000100),_b(0x00010000),_b(0x10001000),_b(0x01000000),_b(0x00000010),\r\n//_b(0x00001111),_b(0x11100000),_b(0x00100000),_b(0x00000100),_b(0x00001000),_b(0x00100000),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x00100000),_b(0x00010010),_b(0x00100100),\r\n//_b(0x00000100),_b(0x01000000),_b(0x00000000),_b(0x10000000),_b(0x00000010),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x01111100),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x01000000),_b(0x00000000),_b(0x00001000),_b(0x00000010),_b(0x00001000),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00000100),_b(0x00100000),_b(0x10000100),_b(0x00010000),_b(0x01001000),_b(0x01000000),_b(0x00000010),\r\n//_b(0x00001000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x00100000),_b(0x00010010),_b(0x00100100),\r\n//_b(0x00000100),_b(0x01000000),_b(0x00000000),_b(0x10000000),_b(0x00000100),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00000100),_b(0x01000000),_b(0x00000000),_b(0x00001000),_b(0x00000010),_b(0x00001000),_b(0x00000010),_b(0x00001000),_b(0x00000000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00000100),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x01101000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00001000),_b(0x00000000),_b(0x00001100),_b(0x00110000),_b(0x00001000),_b(0x00001000),_b(0x00100000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00001000),_b(0x00000010),_b(0x01000000),_b(0x00010010),_b(0x00010100),\r\n//_b(0x00001000),_b(0x00100000),_b(0x00000000),_b(0x10000000),_b(0x00001000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00001000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00001000),_b(0x00000100),_b(0x00001000),_b(0x00000010),_b(0x00001000),_b(0x00000000),_b(0x00010000),_b(0x00000100),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00000100),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00101000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00001000),_b(0x00000000),_b(0x00000111),_b(0x11000000),_b(0x00001000),_b(0x00000100),_b(0x00100000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00001000),_b(0x00000010),_b(0x01000000),_b(0x00010100),_b(0x00010100),\r\n//_b(0x00010000),_b(0x00010000),_b(0x00000000),_b(0x10000000),_b(0x00001000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x01000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00001000),_b(0x00000000),_b(0x00100000),_b(0x00000100),_b(0x00001000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00001000),_b(0x00001000),_b(0x00000010),_b(0x00001000),_b(0x00000000),_b(0x00010000),_b(0x00000100),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00100000),_b(0x00001000),_b(0x00001000),_b(0x00000100),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00011000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00001000),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00001000),_b(0x00000100),_b(0x00110000),_b(0x00010000),_b(0x00000000),_b(0x10000000),_b(0x00001000),_b(0x00010000),_b(0x00000010),_b(0x01000000),_b(0x00010100),_b(0x00010100),\r\n//_b(0x00010000),_b(0x00010000),_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x01000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000100),_b(0x00010000),_b(0x00100000),_b(0x00000100),_b(0x00001000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00011000),_b(0x00001000),_b(0x00000010),_b(0x00001000),_b(0x00000000),_b(0x00001100),_b(0x00001100),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00011000),_b(0x01100000),_b(0x00001000),_b(0x00001000),_b(0x00000100),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00011000),_b(0x00001100),_b(0x00110000),\r\n//_b(0x00001000),_b(0x00000000),_b(0x00000011),_b(0x11100010),_b(0x00001000),_b(0x00000010),_b(0x00111000),_b(0x00110000),_b(0x00000000),_b(0x10000000),_b(0x00000100),_b(0x00100000),_b(0x00000001),_b(0x10000000),_b(0x00010100),_b(0x00010100),\r\n//_b(0x00100000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00100000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000011),_b(0x11100000),_b(0x11111000),_b(0x00011111),_b(0x00111111),_b(0x11110000),_b(0x00000111),_b(0x11100000),_b(0x00111111),_b(0x11100000),_b(0x00111111),_b(0x11111110),_b(0x00111111),_b(0x11000000),_b(0x00000011),_b(0x11110000),\r\n//_b(0x01111100),_b(0x00111110),_b(0x00111111),_b(0x11111000),_b(0x00000111),_b(0x10000000),_b(0x00111110),_b(0x00001110),_b(0x00111111),_b(0x11111100),_b(0x11111000),_b(0x00011111),_b(0x01111100),_b(0x00001000),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00111111),_b(0x11000000),_b(0x00000100),_b(0x00011100),_b(0x00111110),_b(0x00000011),_b(0x00100111),_b(0x11000000),_b(0x00000111),_b(0x11110000),_b(0x00000011),_b(0x11000000),_b(0x00000001),_b(0x10000000),_b(0x00001000),_b(0x00001000),\r\n//_b(0x01111100),_b(0x00111110),_b(0x00000111),_b(0x11110000),_b(0x00111111),_b(0x11111000),_b(0x00000001),_b(0x11100000),_b(0x00000000),_b(0x00100000),_b(0x00001111),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00111000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111100),_b(0x00000111),_b(0x11001110),\r\n//_b(0x01110000),_b(0x00000000),_b(0x00000011),_b(0x00000000),_b(0x00000000),_b(0x11000000),_b(0x00111000),_b(0x00000000),_b(0x00011111),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11000000),_b(0x00000001),_b(0x00000000),_b(0x00000110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00001000),_b(0x00101000),\r\n//_b(0x00010000),_b(0x00000000),_b(0x00000011),_b(0x00000000),_b(0x00000000),_b(0x11000000),_b(0x00001000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x11100011),_b(0x11000000),_b(0x00000111),_b(0x11001110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00000000),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00010000),_b(0x00011000),\r\n//_b(0x00010000),_b(0x00000000),_b(0x00000011),_b(0x00000000),_b(0x00000000),_b(0x11000000),_b(0x00001000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00101100),_b(0x00110000),_b(0x00001000),_b(0x00101000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00111110),_b(0x00111110),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x11000000),\r\n//_b(0x00000000),_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00100000),_b(0x00011000),\r\n//_b(0x00010000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00110000),_b(0x00001000),_b(0x00010000),_b(0x00011000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x01100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x11000000),_b(0x00100011),_b(0x11000000),_b(0x00000111),_b(0x11101000),_b(0x00000111),_b(0x11001000),_b(0x00000111),_b(0x11100000),_b(0x00000010),_b(0x00000000),_b(0x00100000),_b(0x00001000),\r\n//_b(0x00010011),_b(0x11100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00111110),_b(0x00000001),_b(0x00000000),_b(0x11100110),_b(0x00011000),_b(0x01110011),_b(0x11100000),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00110000),_b(0x00001000),_b(0x00100000),_b(0x00001000),_b(0x00011100),_b(0x01111000),_b(0x00000111),_b(0x11101000),_b(0x00111111),_b(0x11111000),_b(0x01110000),_b(0x00111000),_b(0x01111100),_b(0x00111110),_b(0x11111000),_b(0x00001111),\r\n//_b(0x00111100),_b(0x01111000),_b(0x00001000),_b(0x00010000),_b(0x00011111),_b(0x11111000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x00110000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00011000),_b(0x00100000),_b(0x00101100),_b(0x00110000),_b(0x00001000),_b(0x00011000),_b(0x00001000),_b(0x00101000),_b(0x00001000),_b(0x00010000),_b(0x00011111),_b(0x11111000),_b(0x00100000),_b(0x00001000),\r\n//_b(0x00010100),_b(0x00010000),_b(0x00011111),_b(0x00000000),_b(0x00011111),_b(0x11100000),_b(0x00001000),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00101001),_b(0x00100100),_b(0x00010100),_b(0x00010000),_b(0x00001100),_b(0x00110000),\r\n//_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00001000),_b(0x00000100),_b(0x10000100),_b(0x00001000),_b(0x00011000),_b(0x00000100),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000010),\r\n//_b(0x00010000),_b(0x00010000),_b(0x00000100),_b(0x00010000),_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001100),_b(0x00011000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00110000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00011000),_b(0x00010000),_b(0x00001000),_b(0x00000010),_b(0x00000000),_b(0x00100000),_b(0x00001000),\r\n//_b(0x00011000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x00100000),_b(0x00000001),_b(0x00000000),_b(0x00110000),_b(0x11000010),_b(0x00011000),_b(0x00001000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00001000),_b(0x00000101),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000010),\r\n//_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00010000),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00001110),_b(0x00000000),_b(0x00011000),_b(0x00001100),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00110000),_b(0x00001000),_b(0x00110000),_b(0x00001000),_b(0x00100000),_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00000010),_b(0x00000000),_b(0x00100000),_b(0x00001000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x01000000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x10000010),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00001000),\r\n//_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00001000),_b(0x00000110),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00100000),_b(0x00000010),\r\n//_b(0x00000100),_b(0x01000000),_b(0x00000010),_b(0x00100000),_b(0x00000000),_b(0x00100000),_b(0x00000110),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x11000000),_b(0x00010011),_b(0x00001000),_b(0x00110000),_b(0x00000110),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00000010),_b(0x00000000),_b(0x00100000),_b(0x00011000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00001001),_b(0x10000000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x10000010),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00110000),_b(0x00001000),_b(0x00100000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00100000),_b(0x10000010),\r\n//_b(0x00000010),_b(0x10000000),_b(0x00000010),_b(0x00100000),_b(0x00000000),_b(0x01000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00100001),_b(0x10010000),_b(0x00100000),_b(0x00000010),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x11110000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x00111111),_b(0x11111100),_b(0x00000010),_b(0x00000000),_b(0x00010000),_b(0x00011000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00001010),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x10000010),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00110000),_b(0x00001000),_b(0x00010000),_b(0x00011000),_b(0x00000100),_b(0x00000000),_b(0x00000111),_b(0x11100000),_b(0x00000100),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x00100000),_b(0x00010001),_b(0x01000100),\r\n//_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x01000000),_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x11100000),_b(0x00100000),_b(0x00000010),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00011000),_b(0x00010000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x00100000),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00001000),_b(0x00101000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00001101),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x10000010),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00101100),_b(0x00010000),_b(0x00001000),_b(0x00101000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00000100),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x00100000),_b(0x00010001),_b(0x01000100),\r\n//_b(0x00000010),_b(0x10000000),_b(0x00000001),_b(0x01000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00000010),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00010000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x00100000),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00000111),_b(0x11001000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x10000000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x10000010),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00100011),_b(0x11100000),_b(0x00000111),_b(0x11001000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x01000000),_b(0x00010010),_b(0x00100100),\r\n//_b(0x00000100),_b(0x01000000),_b(0x00000000),_b(0x10000000),_b(0x00000010),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00000010),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00010000),_b(0x00110000),_b(0x00001000),_b(0x00100000),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00001000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x01000000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x10000010),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00001000),\r\n//_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00000010),_b(0x01000000),_b(0x00010100),_b(0x00010100),\r\n//_b(0x00001000),_b(0x00100000),_b(0x00000000),_b(0x10000000),_b(0x00000100),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00000010),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00110000),_b(0x00110000),_b(0x00001000),_b(0x00010000),_b(0x00000100),_b(0x00010000),_b(0x00011000),_b(0x00010000),_b(0x00000100),_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00001000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x00100000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x10000010),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x00010000),_b(0x00011000),_b(0x00000010),_b(0x01000000),_b(0x00010100),_b(0x00010100),\r\n//_b(0x00010000),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00000010),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x01010000),_b(0x00101100),_b(0x00110000),_b(0x00001000),_b(0x00011000),_b(0x00001000),_b(0x00101000),_b(0x00001100),_b(0x00011000),_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00010000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x01000000),_b(0x00001000),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x10000010),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00010000),\r\n//_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x00111000),_b(0x00010000),_b(0x00000010),_b(0x00000110),_b(0x00001000),_b(0x00101000),_b(0x00000001),_b(0x10000000),_b(0x00001000),_b(0x00001000),\r\n//_b(0x00100000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00000010),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00001111),_b(0x10011100),_b(0x11100011),_b(0x11000000),_b(0x00000111),_b(0x11100000),_b(0x00000111),_b(0x11001110),_b(0x00000011),_b(0x11100000),_b(0x00011111),_b(0x11111000),_b(0x00000111),_b(0x11100000),\r\n//_b(0x01111100),_b(0x00111110),_b(0x00111111),_b(0x11111000),_b(0x00111111),_b(0x10000000),_b(0x00111000),_b(0x00111110),_b(0x00111111),_b(0x11111000),_b(0x11111000),_b(0x11100011),_b(0x01111100),_b(0x00111110),_b(0x00000111),_b(0x11100000),\r\n//_b(0x11111100),_b(0x00000000),_b(0x00000000),_b(0x01111110),_b(0x00111111),_b(0x11110000),_b(0x00100111),_b(0x11100000),_b(0x00000001),_b(0x11111000),_b(0x00000111),_b(0x11001110),_b(0x00000001),_b(0x10000000),_b(0x00001000),_b(0x00001000),\r\n//_b(0x01111100),_b(0x01111100),_b(0x00011111),_b(0x11000000),_b(0x00011111),_b(0x11111000),_b(0x00000000),_b(0x11000000),_b(0x00000001),_b(0x00000000),_b(0x00000110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00111111),_b(0x11111110),\r\n//_b(0x00000011),_b(0x11100100),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11000000),_b(0x00000001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x00000000),_b(0x00000011),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00011000),_b(0x01100000),_b(0x00000111),_b(0x00000000),\r\n//_b(0x00000000),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00011111),_b(0x11111110),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000110),_b(0x00000000),\r\n//_b(0x00000110),_b(0x01100000),_b(0x00001100),_b(0x00110000),_b(0x00001100),_b(0x00110000),_b(0x00000000),_b(0x10000000),_b(0x00000011),_b(0x10000000),_b(0x11111000),_b(0x00111110),_b(0x11111111),_b(0x11000000),_b(0x00000000),_b(0x00111110),\r\n//_b(0x00000100),_b(0x00010100),_b(0x00001100),_b(0x00110000),_b(0x00000001),_b(0x10000000),_b(0x00000011),_b(0x10000000),_b(0x00011000),_b(0x01100000),_b(0x00000001),_b(0x10000000),_b(0x00000100),_b(0x01000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000001),_b(0x11000000),_b(0x00001100),_b(0x00110000),_b(0x00000001),_b(0x10000000),_b(0x00110000),_b(0x11000000),_b(0x00000111),_b(0x00000000),_b(0x00001100),_b(0x00000000),_b(0x00011000),_b(0x01100000),_b(0x00001000),_b(0x10000000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x10000010),_b(0x00000001),_b(0x11000000),_b(0x00001100),_b(0x00110000),_b(0x00000001),_b(0x10000000),_b(0x00000011),_b(0x10000000),_b(0x00000011),_b(0x00000000),\r\n//_b(0x00000110),_b(0x01100000),_b(0x00001100),_b(0x00110000),_b(0x00001100),_b(0x00110000),_b(0x00000000),_b(0x10000000),_b(0x00000100),_b(0x01000000),_b(0x00100000),_b(0x00001000),_b(0x00100000),_b(0x00100000),_b(0x00000000),_b(0x01000000),\r\n//_b(0x00001000),_b(0x00001100),_b(0x00001100),_b(0x00110000),_b(0x00000010),_b(0x00000000),_b(0x00000110),_b(0x11000000),_b(0x00011000),_b(0x01100000),_b(0x00000000),_b(0x01000000),_b(0x00000100),_b(0x01000000),_b(0x00000111),_b(0x11101000),\r\n//_b(0x00000011),_b(0x01100000),_b(0x00001100),_b(0x00110000),_b(0x00000000),_b(0x01000000),_b(0x00110000),_b(0x11000000),_b(0x00001101),_b(0x10000000),_b(0x00000110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x00000000),\r\n//_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x10000010),_b(0x00000011),_b(0x01100000),_b(0x00001100),_b(0x00110000),_b(0x00000000),_b(0x01000000),_b(0x00000110),_b(0x11000000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00001000),_b(0x00100000),_b(0x00010000),_b(0x00010000),_b(0x00100000),_b(0x00010000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00010000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x10000000),_b(0x00001000),_b(0x00011000),\r\n//_b(0x00000100),_b(0x00010000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x01000000),_b(0x00000001),_b(0x00000000),_b(0x00011111),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x10000010),_b(0x00000100),_b(0x00010000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01111100),_b(0x01111100),_b(0x00000011),_b(0x11000000),_b(0x01111100),_b(0x00111110),_b(0x00000011),_b(0x11101000),_b(0x00001000),_b(0x00000000),_b(0x00001000),_b(0x00100000),_b(0x00100000),_b(0x00010000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00100000),_b(0x00000100),_b(0x01110000),_b(0x00111000),_b(0x00000111),_b(0x11100000),_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x11000000),_b(0x00000111),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x11100000),_b(0x00000111),_b(0x11100000),_b(0x00011111),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00011111),_b(0x10000000),\r\n//_b(0x00111111),_b(0x11111100),_b(0x00001110),_b(0x00011000),_b(0x00001000),_b(0x10000010),_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11000000),_b(0x00000011),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x01110000),_b(0x00111000),\r\n//_b(0x00010000),_b(0x00010000),_b(0x00001100),_b(0x00110000),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x00011000),_b(0x00001000),_b(0x00000000),_b(0x00001000),_b(0x00100000),_b(0x00100000),_b(0x00010000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00100000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00000111),_b(0x11000000),_b(0x00011000),_b(0x00100000),_b(0x00011000),_b(0x00100000),_b(0x00000111),_b(0x11000000),_b(0x00110000),_b(0x00001000),\r\n//_b(0x00000111),_b(0x11100000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00011111),_b(0x00000000),_b(0x00011111),_b(0x00000000),_b(0x00000010),_b(0x01000000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00001000),_b(0x00000100),_b(0x00110001),_b(0x10100100),_b(0x00001000),_b(0x10010000),_b(0x00000011),_b(0x11000000),_b(0x00001100),_b(0x00110000),_b(0x00001100),_b(0x00110000),_b(0x01110000),_b(0x00111000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00010000),_b(0x00010000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00001000),_b(0x00001000),_b(0x00000000),_b(0x00000100),_b(0x01000000),_b(0x00100000),_b(0x00010000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00100000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00011000),_b(0x00100000),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00010000),_b(0x00011000),_b(0x00100000),_b(0x00100000),_b(0x00000000),\r\n//_b(0x00001000),_b(0x00010000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000010),_b(0x01000000),_b(0x00000010),_b(0x01000000),\r\n//_b(0x00001000),_b(0x00000100),_b(0x00100000),_b(0x11000100),_b(0x00001000),_b(0x10010000),_b(0x00001100),_b(0x00110000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00001000),_b(0x00100000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00000010),_b(0x10000000),_b(0x00100000),_b(0x00100000),_b(0x00000111),_b(0x11110000),\r\n//_b(0x00100000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00010000),_b(0x00100000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000100),_b(0x00100000),_b(0x00000010),_b(0x01000000),\r\n//_b(0x00001000),_b(0x01000000),_b(0x00000000),_b(0x11000010),_b(0x00001000),_b(0x11110000),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00001000),_b(0x00100000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00001000),_b(0x00100000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000010),_b(0x10000000),_b(0x00111111),_b(0x11000000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00010000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00010000),_b(0x00100000),_b(0x00000000),\r\n//_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00100000),\r\n//_b(0x00001000),_b(0x01000000),_b(0x00000000),_b(0x10000010),_b(0x00010000),_b(0x10010000),_b(0x00100000),_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00000100),_b(0x01000000),_b(0x01000000),_b(0x00000010),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x00111111),_b(0x11000000),_b(0x00011111),_b(0x11110000),_b(0x00100100),_b(0x00000000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00111111),_b(0x11111100),_b(0x00000111),_b(0x11110000),_b(0x00000111),_b(0x11110000),_b(0x00000111),_b(0x11110000),_b(0x00000111),_b(0x11110000),_b(0x00010000),_b(0x00000100),\r\n//_b(0x00100000),_b(0x00000100),_b(0x00111111),_b(0x11111100),_b(0x00111111),_b(0x11111100),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00001111),_b(0x11110000),_b(0x00000100),_b(0x00100000),\r\n//_b(0x00001111),_b(0x11000000),_b(0x00011111),_b(0x10000010),_b(0x00010000),_b(0x10010000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00000100),_b(0x01000000),_b(0x01000000),_b(0x00000010),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00101111),_b(0x11011110),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00000100),_b(0x00010000),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000000),_b(0x00011000),_b(0x00010000),_b(0x00011000),_b(0x00010000),_b(0x00011000),_b(0x00010000),_b(0x00011000),_b(0x00010000),_b(0x00001000),_b(0x00011000),\r\n//_b(0x00111111),_b(0x11111100),_b(0x00100000),_b(0x00000000),_b(0x00100000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00001000),_b(0x00010000),_b(0x00001111),_b(0x11110000),\r\n//_b(0x00001000),_b(0x01000000),_b(0x01100000),_b(0x11111110),_b(0x00011111),_b(0x10000000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00000010),_b(0x10000000),_b(0x01000000),_b(0x00000010),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00100100),_b(0x00100110),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00000011),_b(0x11100000),_b(0x00010000),_b(0x00001000),_b(0x00100000),_b(0x00000000),_b(0x00100000),_b(0x00010000),_b(0x00100000),_b(0x00010000),_b(0x00100000),_b(0x00010000),_b(0x00100000),_b(0x00010000),_b(0x00000111),_b(0x11100000),\r\n//_b(0x00100000),_b(0x00000000),_b(0x00100000),_b(0x00000000),_b(0x00100000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00010000),\r\n//_b(0x00001000),_b(0x01000010),_b(0x10000000),_b(0x10000000),_b(0x00010000),_b(0x10000000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00000010),_b(0x10000000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x00011000),_b(0x00000100),_b(0x00000000),_b(0x00011111),_b(0x11110000),_b(0x00100100),_b(0x00100000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x00100000),_b(0x00010000),_b(0x00100000),_b(0x00010000),_b(0x00100000),_b(0x00010000),_b(0x00100000),_b(0x00010000),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00010000),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00001000),_b(0x00000010),_b(0x10000000),_b(0x10000000),_b(0x00010000),_b(0x10000001),_b(0x00100000),_b(0x00001000),_b(0x00100000),_b(0x00001000),_b(0x00100000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00000011),_b(0x11100000),_b(0x00000100),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00100100),_b(0x00011110),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00000000),_b(0x11000000),_b(0x00010000),_b(0x00011000),_b(0x00010000),_b(0x00000100),_b(0x00100000),_b(0x00110000),_b(0x00100000),_b(0x00110000),_b(0x00100000),_b(0x00110000),_b(0x00100000),_b(0x00110000),_b(0x00000000),_b(0x11000000),\r\n//_b(0x00010000),_b(0x00000100),_b(0x00010000),_b(0x00000100),_b(0x00010000),_b(0x00000100),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00001000),_b(0x00000010),_b(0x10000000),_b(0x10000010),_b(0x00100000),_b(0x10000001),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00011000),_b(0x00010000),_b(0x00011000),\r\n//_b(0x00000001),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00000000),_b(0x10000000),_b(0x00001000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00100100),_b(0x00100001),_b(0x00000000),_b(0x10000000),\r\n//_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x00101000),_b(0x00001100),_b(0x00011000),_b(0x00010000),_b(0x01010000),_b(0x00010000),_b(0x01010000),_b(0x00010000),_b(0x01010000),_b(0x00010000),_b(0x01010000),_b(0x00000000),_b(0x00100000),\r\n//_b(0x00001100),_b(0x00011000),_b(0x00001100),_b(0x00011000),_b(0x00001100),_b(0x00011000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00001000),_b(0x00000010),_b(0x01000001),_b(0x11000100),_b(0x00100000),_b(0x10000001),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00101000),_b(0x00001000),_b(0x00101000),\r\n//_b(0x00000010),_b(0x00000000),_b(0x00001100),_b(0x00110000),_b(0x00000100),_b(0x00100000),_b(0x00000000),_b(0x10000000),_b(0x00001000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00100100),_b(0x00100001),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00000011),_b(0x11000000),_b(0x00000111),_b(0x11001110),_b(0x00000011),_b(0x11100000),_b(0x00001111),_b(0x10011100),_b(0x00001111),_b(0x10011100),_b(0x00001111),_b(0x10011100),_b(0x00001111),_b(0x10011100),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00000011),_b(0x11100000),_b(0x00000011),_b(0x11100000),_b(0x00000011),_b(0x11100000),_b(0x00111111),_b(0x11111000),_b(0x00111111),_b(0x11111000),_b(0x00111111),_b(0x11111000),_b(0x11111000),_b(0x00011111),_b(0x11111000),_b(0x00011111),\r\n//_b(0x00111111),_b(0x11111110),_b(0x00111110),_b(0x10111000),_b(0x11111011),_b(0x11111111),_b(0x00000111),_b(0x11100000),_b(0x00000111),_b(0x11100000),_b(0x00000111),_b(0x11100000),_b(0x00000111),_b(0x11001110),_b(0x00000111),_b(0x11001110),\r\n//_b(0x00111111),_b(0x10000000),_b(0x00000011),_b(0x11000000),_b(0x00000011),_b(0x11000000),_b(0x00000000),_b(0x10000000),_b(0x00111111),_b(0x11110000),_b(0x00001111),_b(0x11100000),_b(0x11111011),_b(0x11111110),_b(0x00111110),_b(0x00000000),\r\n//_b(0x00000000),_b(0x11000000),_b(0x00000011),_b(0x00000000),_b(0x00000000),_b(0x11000000),_b(0x00000000),_b(0x11000000),_b(0x00000111),_b(0x00010000),_b(0x00000111),_b(0x00010000),_b(0x00000011),_b(0x11000000),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00110000),_b(0x00000000),_b(0x00110000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00001101),_b(0x10110000),_b(0x00001101),_b(0x10110000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00100000),\r\n//_b(0x00000011),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11010000),_b(0x00000000),_b(0x11010000),_b(0x00000000),_b(0x00000001),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01100001),_b(0x00001100),_b(0x01101001),_b(0x01101101),_b(0x01101001),_b(0x01101101),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000010),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00001000),_b(0x11100000),_b(0x00001000),_b(0x11100000),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x00010000),\r\n//_b(0x00000011),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00000001),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x11100000),_b(0x00001000),_b(0x00010000),\r\n//_b(0x00000011),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00000001),_b(0x00010000),_b(0x00000001),_b(0x00000001),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00001000),_b(0x01100001),_b(0x10010110),_b(0x10010010),_b(0x10010110),_b(0x10010010),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000111),_b(0x11000000),_b(0x00011111),_b(0x00000000),_b(0x00000011),_b(0x11000000),_b(0x01110000),_b(0x00111000),_b(0x01110011),_b(0x11100000),_b(0x01110000),_b(0x00111110),_b(0x00001100),_b(0x00100000),_b(0x00001000),_b(0x00010000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00000110),_b(0x00010000),_b(0x00000110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00011000),_b(0x00100000),_b(0x00000001),_b(0x00000000),_b(0x00001100),_b(0x00110000),_b(0x00010000),_b(0x00001000),_b(0x00010100),_b(0x00010000),_b(0x00011000),_b(0x00001000),_b(0x00001000),_b(0x00100000),_b(0x00001000),_b(0x00010000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x10000000),_b(0x00000010),_b(0x00001000),_b(0x00110000),_b(0x11000000),\r\n//_b(0x01100001),_b(0x00001100),_b(0x01101001),_b(0x01101101),_b(0x01101001),_b(0x01101101),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x11111111),_b(0x10000000),_b(0x11111110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x11111111),_b(0x11100000),_b(0x11111110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x11111111),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00011000),_b(0x00001000),_b(0x00010100),_b(0x00001000),_b(0x00001000),_b(0x01100000),_b(0x00000100),_b(0x00100000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00110000),_b(0x00010000),_b(0x00110000),_b(0x00000000),_b(0x10000000),_b(0x00000110),_b(0x00011000),_b(0x00011000),_b(0x01100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x11111111),_b(0x10000000),_b(0x11111110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x11111111),_b(0x11100000),_b(0x11111110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x11111111),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010110),_b(0x00001000),_b(0x00000111),_b(0x10110000),_b(0x00000011),_b(0x11000000),\r\n//_b(0x00000011),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111110),_b(0x11011110),_b(0x11111110),_b(0x11000110),_b(0x00000000),_b(0x10000000),_b(0x00001100),_b(0x00110000),_b(0x00001100),_b(0x00110000),\r\n//_b(0x00001000),_b(0x01100001),_b(0x10010110),_b(0x10010010),_b(0x10010110),_b(0x10010010),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x11111110),_b(0x01100000),_b(0x11111111),_b(0x11100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x01100000),_b(0x00000000),_b(0x01100000),_b(0x11111111),_b(0x11100000),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x10000000),\r\n//_b(0x00000000),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010010),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00001110),_b(0x00000000),_b(0x00111111),_b(0x11111111),_b(0x11111111),_b(0x11111100),_b(0x00000001),_b(0x11100011),_b(0x00000001),_b(0x00001010),_b(0x00000000),_b(0x10000000),_b(0x00011000),_b(0x01100000),_b(0x00000110),_b(0x00011000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x11111110),_b(0x01100000),_b(0x11111111),_b(0x11100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x01100000),_b(0x00000000),_b(0x01100000),_b(0x11111111),_b(0x11100000),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x10000000),\r\n//_b(0x00000111),_b(0x11110000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010001),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00011000),_b(0x00000000),_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00000110),_b(0x01000001),_b(0x00000110),_b(0x00010010),_b(0x00000000),_b(0x10000000),_b(0x00110000),_b(0x11000000),_b(0x00000011),_b(0x00001100),\r\n//_b(0x01100001),_b(0x00001100),_b(0x01101001),_b(0x01101101),_b(0x01101001),_b(0x01101101),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x11111111),_b(0x10000000),_b(0x11111110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x11111110),_b(0x01100000),_b(0x11111111),_b(0x11100000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x10000000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00011000),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x10001000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00000000),_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00001000),_b(0x00000001),_b(0x00001000),_b(0x00010010),_b(0x00000000),_b(0x10000000),_b(0x01100001),_b(0x10000000),_b(0x00000001),_b(0x10000110),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x11111111),_b(0x10000000),_b(0x11111110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x11111110),_b(0x01100000),_b(0x11111111),_b(0x11100000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x10000000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00100000),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x01001000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00000000),_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00110000),_b(0x00000010),_b(0x00010000),_b(0x00100010),_b(0x00000000),_b(0x10000000),_b(0x00110000),_b(0x11000000),_b(0x00000011),_b(0x00001100),\r\n//_b(0x00001000),_b(0x01100001),_b(0x10010110),_b(0x10010010),_b(0x10010110),_b(0x10010010),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00100000),_b(0x00010000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x01101000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x00010000),_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00001100),_b(0x00000000),_b(0x00111111),_b(0x00000000),_b(0x10000000),_b(0x00011000),_b(0x01100000),_b(0x00000110),_b(0x00011000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00100000),_b(0x00110000),_b(0x00000001),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00011000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00101000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00011000),_b(0x00010000),_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x10000000),_b(0x00001100),_b(0x00110000),_b(0x00001100),_b(0x00110000),\r\n//_b(0x01100001),_b(0x00001100),_b(0x01101001),_b(0x01101101),_b(0x01101001),_b(0x01101101),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00010000),_b(0x01010000),_b(0x00000001),_b(0x00000000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00101000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00011000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00001100),_b(0x00110000),_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00000000),_b(0x00100000),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x10000000),_b(0x00000110),_b(0x00011000),_b(0x00011000),_b(0x01100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00001111),_b(0x10011100),_b(0x00111111),_b(0x11111000),_b(0x00000111),_b(0x11100000),_b(0x00000111),_b(0x11001110),_b(0x01111100),_b(0x00111110),_b(0x01111100),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000111),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x01111111),_b(0x00000000),_b(0x00001111),_b(0x00000000),_b(0x10000000),_b(0x00000010),_b(0x00001000),_b(0x00110000),_b(0x11000000),\r\n//_b(0x00001000),_b(0x01100001),_b(0x10010110),_b(0x10010010),_b(0x10010110),_b(0x10010010),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),\r\n//_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x11111111),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000110),_b(0x01111111),_b(0x00000111),_b(0x11111111),_b(0x11111110),_b(0x01111111),_b(0x11111111),_b(0x11111111),_b(0x00000110),_b(0x01111111),_b(0x11111111),_b(0x11111111),_b(0x11111110),_b(0x01111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000110),_b(0x01100000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x11111111),_b(0x00000001),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x11111111),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000110),_b(0x01111111),_b(0x00000111),_b(0x11111111),_b(0x11111110),_b(0x01111111),_b(0x11111111),_b(0x11111111),_b(0x00000110),_b(0x01111111),_b(0x11111111),_b(0x11111111),_b(0x11111110),_b(0x01111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000110),_b(0x01100000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000001),_b(0x11111111),_b(0x00000001),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000001),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01111111),\r\n//_b(0x00000110),_b(0x00000000),_b(0x00000110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000111),_b(0x11111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x10000000),_b(0x00000001),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000001),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01111111),\r\n//_b(0x00000110),_b(0x00000000),_b(0x00000110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000111),_b(0x11111111),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000111),_b(0x11111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x10000000),_b(0x00000001),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x11111111),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000111),_b(0x11111111),_b(0x00000110),_b(0x01111111),_b(0x11111111),_b(0x11111111),_b(0x11111110),_b(0x01111111),_b(0x00000110),_b(0x01111111),_b(0x11111111),_b(0x11111111),_b(0x11111110),_b(0x01111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x11111111),_b(0x00000001),_b(0x11111111),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x11111111),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000111),_b(0x11111111),_b(0x00000110),_b(0x01111111),_b(0x11111111),_b(0x11111111),_b(0x11111110),_b(0x01111111),_b(0x00000110),_b(0x01111111),_b(0x11111111),_b(0x11111111),_b(0x11111110),_b(0x01111111),_b(0x11111111),_b(0x11111111),\r\n//_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x11111111),_b(0x00000001),_b(0x11111111),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000110),_b(0x01100000),_b(0x00000110),_b(0x01100000),\r\n//_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x10000000),_b(0x00111111),_b(0x11111110),_b(0x00000000),_b(0x00000000),_b(0x00011111),_b(0x11111000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000011),_b(0x11100000),_b(0x00000111),_b(0x11100000),_b(0x00000111),_b(0x11100000),_b(0x00011111),_b(0x11111000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x11100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00110000),_b(0x00000000),_b(0x00000000),_b(0x00001100),_b(0x00000000),_b(0x01111000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000001),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x11000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x01000000),_b(0x00000100),_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00011000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001100),_b(0x00010000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00001100),_b(0x00000000),_b(0x00000000),_b(0x00110000),_b(0x00000000),_b(0x10111000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000010),_b(0x00100000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00000010),_b(0x01100000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00100000),_b(0x00000100),_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00001100),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00001100),_b(0x11110000),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00001000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000011),_b(0x00000000),_b(0x00000000),_b(0x11000000),_b(0x00000000),_b(0x10011000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000100),_b(0x00010000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00000010),_b(0x00001101),_b(0x11000000),_b(0x00000100),_b(0x00100000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00100000),_b(0x00000100),_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00000100),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000111),_b(0x11110000),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00000010),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x10001000),_b(0x00000000),_b(0x00000000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000001),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000100),_b(0x00010000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00011110),_b(0x00000100),_b(0x00000110),_b(0x00100000),_b(0x00000000),_b(0x00100000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00001111),_b(0x00000010),_b(0x00010000),_b(0x00100000),_b(0x00000100),_b(0x00000010),_b(0x00111111),_b(0x11111110),_b(0x00000100),_b(0x00001000),_b(0x00000011),_b(0x11111111),_b(0x01110000),_b(0x00111000),_b(0x00011111),_b(0x11111000),\r\n//_b(0x00011000),_b(0x10001100),_b(0x00100000),_b(0x00000100),_b(0x01000000),_b(0x00000010),_b(0x00000001),_b(0x10000000),_b(0x00111100),_b(0x01111000),_b(0x00010001),_b(0x00000100),_b(0x00000011),_b(0x11101000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x01111111),_b(0x11111110),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x01100000),_b(0x00000110),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00001110),_b(0x00000000),\r\n//_b(0x00000100),_b(0x00010000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00100110),_b(0x00000100),_b(0x00000100),_b(0x00100000),_b(0x00000000),_b(0x01000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x11000010),_b(0x00010000),_b(0x00100000),_b(0x00000100),_b(0x00000010),_b(0x00001000),_b(0x00001000),_b(0x00000010),_b(0x00000000),_b(0x00001100),_b(0x00010000),_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00010000),_b(0x10000100),_b(0x01000000),_b(0x00000010),_b(0x01000000),_b(0x00000010),_b(0x00000000),_b(0x01000000),_b(0x01100110),_b(0x11001100),_b(0x00100001),_b(0x00000010),_b(0x00000100),_b(0x00011000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00011000),_b(0x00011000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00010011),_b(0x00001000),\r\n//_b(0x00000010),_b(0x00100000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000011),_b(0x00000100),_b(0x00000100),_b(0x00100000),_b(0x00000000),_b(0x10000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00100000),_b(0x01000100),_b(0x00010000),_b(0x01000000),_b(0x00000100),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00100000),_b(0x10000010),_b(0x01001000),_b(0x00010010),_b(0x01000000),_b(0x00000010),_b(0x00000011),_b(0x11100000),_b(0x01000001),_b(0x00000100),_b(0x00100001),_b(0x00000010),_b(0x00000100),_b(0x00001000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00111111),_b(0x11111110),_b(0x00000000),_b(0x00000110),_b(0x01100000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00100001),_b(0x10010000),\r\n//_b(0x00000001),_b(0x11000000),_b(0x00000011),_b(0x11000000),_b(0x00000011),_b(0x11000000),_b(0x00000011),_b(0x00000100),_b(0x00000100),_b(0x00100000),_b(0x00000001),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01000000),_b(0x00100100),_b(0x00010001),_b(0x11000000),_b(0x00000100),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00010000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00100000),_b(0x10000010),_b(0x01001000),_b(0x00010010),_b(0x01000000),_b(0x00000010),_b(0x00001100),_b(0x00010000),_b(0x01000001),_b(0x00000100),_b(0x00100001),_b(0x00000010),_b(0x00000100),_b(0x00001000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x00011000),_b(0x00011000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000011),_b(0x11000000),_b(0x00000011),_b(0x11000000),_b(0x00000001),_b(0x10000100),_b(0x00000100),_b(0x00100000),_b(0x00000010),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01000000),_b(0x00101100),_b(0x00010000),_b(0x00100000),_b(0x00000100),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00100000),_b(0x10000010),_b(0x01001111),_b(0x11110010),_b(0x01000000),_b(0x00000010),_b(0x00010000),_b(0x00001000),_b(0x01100110),_b(0x11001100),_b(0x00100001),_b(0x00000010),_b(0x00000010),_b(0x00000000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x01111111),_b(0x11111110),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x01100000),_b(0x00000100),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00111111),_b(0x11111100),_b(0x00001110),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10001000),_b(0x00001110),_b(0x01110000),_b(0x00000111),_b(0x11100000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01000000),_b(0x00011000),_b(0x00010000),_b(0x00010000),_b(0x00000100),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00000001),_b(0x00000000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00100000),_b(0x10000010),_b(0x01001000),_b(0x00010010),_b(0x01000000),_b(0x00000010),_b(0x00100000),_b(0x00000100),_b(0x00111100),_b(0x01111000),_b(0x00100001),_b(0x00000100),_b(0x00000001),_b(0x11000000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000000),_b(0x10000000),_b(0x00000011),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00010011),_b(0x00001000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11001000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01000000),_b(0x00010000),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00000010),_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00001000),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00010000),_b(0x10000100),_b(0x01001000),_b(0x00010010),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00010001),_b(0x00000100),_b(0x00000110),_b(0x00000000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00000011),_b(0x00000000),_b(0x00000000),_b(0x11000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00100001),_b(0x10010000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11001000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01000000),_b(0x00010000),_b(0x00010000),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00000100),_b(0x00001000),_b(0x00100000),_b(0x00000100),_b(0x00010000),_b(0x00011000),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00011000),_b(0x10001100),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00100000),_b(0x00000100),_b(0x00000000),_b(0x00000000),_b(0x00001001),_b(0x00001000),_b(0x00001000),_b(0x00000000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x10000000),_b(0x00001100),_b(0x00000000),_b(0x00000000),_b(0x00110000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11100000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x01101000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x01100000),_b(0x00110000),_b(0x00010001),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00000100),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00011000),_b(0x01101000),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00000111),_b(0x11110000),_b(0x00100000),_b(0x00000100),_b(0x00011000),_b(0x00011000),_b(0x00110000),_b(0x00001100),_b(0x00000000),_b(0x00000000),_b(0x00000111),_b(0x11110000),_b(0x00001000),_b(0x00000000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x01111111),_b(0x11111110),_b(0x00000000),_b(0x10000000),_b(0x00110000),_b(0x00000000),_b(0x00000000),_b(0x00001100),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x01101000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00100000),_b(0x01001000),_b(0x01110001),_b(0x00001000),_b(0x00000100),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00011111),_b(0x10001110),_b(0x00000001),_b(0x00000000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00010000),_b(0x00001000),_b(0x01000110),_b(0x01100010),_b(0x00010000),_b(0x00001000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00001000),_b(0x00000000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000001),_b(0x10000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00110000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00010000),_b(0x10001000),_b(0x00010001),_b(0x10010000),_b(0x00000100),_b(0x00000000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00001000),_b(0x00001000),_b(0x00010000),_b(0x00010000),_b(0x00000000),_b(0x00000001),_b(0x00010000),\r\n//_b(0x00000000),_b(0x10000000),_b(0x00001000),_b(0x00010000),_b(0x01000010),_b(0x01000010),_b(0x00001100),_b(0x00110000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000100),_b(0x00010000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x10000000),_b(0x00011001),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00110000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00001111),_b(0x00001110),_b(0x00011100),_b(0x11100000),_b(0x00111111),_b(0x10000000),_b(0x00111110),_b(0x00111110),_b(0x00011111),_b(0x11111000),_b(0x00000111),_b(0x11100000),_b(0x00010000),_b(0x00000000),_b(0x00000000),_b(0x11100000),\r\n//_b(0x00000011),_b(0x11100000),_b(0x00000111),_b(0x11100000),_b(0x01111110),_b(0x01111110),_b(0x00000011),_b(0x11000000),_b(0x00000000),_b(0x00000000),_b(0x00000001),_b(0x00000000),_b(0x00000011),_b(0x11100000),_b(0x00100000),_b(0x00000100),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00111111),_b(0x11111110),_b(0x00111111),_b(0x11111110),_b(0x01111111),_b(0x11111100),_b(0x00000001),_b(0x10000000),_b(0x00011101),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),\r\n//_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00010000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x00000000),_b(0x11111111),_b(0x11111111),_b(0x00000000),_b(0x00000000),\r\n//};\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_frame.cpp",
    "content": "/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsFrame\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tFunctionality to set up frames and minipulate them.\t\t\t\t*\r\n *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#include <math.h>\r\n#include \"p_frame.h\"\r\n\r\n/********************************************************************************\r\n * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsFrame\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tGenerates a frame object.\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nNsFrame::NsFrame()\r\n{\r\n\t// Default matrix.\r\n\tm_model.identity();\r\n}\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_frame.h",
    "content": "#ifndef _FRAME_H_\r\n#define _FRAME_H_\r\n\r\n#include <dolphin.h>\r\n#include \"p_matrix.h\"\r\n#include \"p_vector.h\"\r\n\r\nclass NsFrame\r\n{\r\n\tNsMatrix\tm_model;\r\npublic:\r\n\t\t\t\tNsFrame\t\t\t();\r\n\r\n\tvoid\t\tsetModelMatrix\t( NsMatrix * m ) { m_model.copy( *m ); };\r\n\tNsMatrix  * getModelMatrix\t( void ) { return &m_model; };\r\n\r\n\tvoid\t\ttranslate\t\t( NsVector * v, NsMatrix_Combine c ) { m_model.translate( v, c ); }\r\n\tvoid\t\trotate\t\t\t( NsVector * axis, float angle, NsMatrix_Combine c ) { m_model.rotate( axis, angle, c ); }\r\n\tvoid\t\tscale\t\t\t( NsVector * v, NsMatrix_Combine c ) { m_model.scale( v, c ); }\r\n\tvoid\t\tidentity\t\t( void ) { m_model.identity(); }\r\n};\r\n\r\n#endif\t\t// _FRAME_H_\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_gx.cpp",
    "content": "/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsGX\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tGXs matrices.\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n#undef __GX_H__\r\n\r\n#ifdef __PLAT_WN32__\r\n\r\n#include <memory.h>\r\n#include <stdlib.h>\r\n#include <stdio.h>\r\n#include <math.h>\r\n#include <assert.h>\r\n#include <Strip/Strip.h>\r\n#include <GC/GameCubeConv.h>\r\n//#include <List/Search.h>\r\n//#include <Util.h>\r\n#include <Misc/GenCRC.h>\r\n#include <windows.h>\r\n\r\n#include \"Utility.h\"\r\n\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n#ifndef __PLAT_WN32__\r\n#define __NO_DEFS__\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n#include <dolphin\\gd.h>\r\n#include \"p_GX.h\"\r\n\r\n#ifndef __PLAT_WN32__\r\n#include <gfx\\ngc\\nx\\render.h>\r\n#endif\t\t// __PLAT_WN32__\r\n\r\nint g_mat_passes = 4;\r\n\r\nnamespace GX\r\n{\r\n\r\n/********************************************************************************\r\n * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n \r\n#define TEV_KSEL_MASK_KCSEL \\\r\n    (( 0x00001F << TEV_KSEL_KCSEL0_SHIFT ) | \\\r\n     ( 0x00001F << TEV_KSEL_KASEL0_SHIFT ) | \\\r\n     ( 0x00001F << TEV_KSEL_KCSEL1_SHIFT ) | \\\r\n     ( 0x00001F << TEV_KSEL_KASEL1_SHIFT ))\r\n\r\n/********************************************************************************\r\n * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Types.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\ntypedef void (*_write_u8  )( u8  data );\r\ntypedef void (*_write_s8  )( s8  data );\r\ntypedef void (*_write_u16 )( u16 data );\r\ntypedef void (*_write_s16 )( s16 data );\r\ntypedef void (*_write_u32 )( u32 data );\r\ntypedef void (*_write_s32 )( s32 data );\r\ntypedef void (*_write_f32 )( f32 data );\r\ntypedef void (*_write_u24 )( u32 data );\r\n\r\ntypedef void (*_write_BPCmd      )( u32 regval                  );\r\ntypedef void (*_write_CPCmd      )( u8  addr, u32 val           );\r\ntypedef void (*_write_XFCmd      )( u16 addr, u32 val           );\r\ntypedef void (*_write_XFCmdHdr   )( u16 addr, u8 len            );\r\ntypedef void (*_write_XFIndxACmd )( u16 addr, u8 len, u16 index );\r\ntypedef void (*_write_XFIndxBCmd )( u16 addr, u8 len, u16 index );\r\ntypedef void (*_write_XFIndxCCmd )( u16 addr, u8 len, u16 index );\r\ntypedef void (*_write_XFIndxDCmd )( u16 addr, u8 len, u16 index );\r\n\r\n/********************************************************************************\r\n * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nGDLObj\t\t\tg_dl;\r\n//float\t\t\tg_projection[7];\r\n\r\nu32 MyTmemRegions[8][2] = {\r\n   // TMEM LO, TMEM HI\r\n    { 0x00000, 0x80000 },  // (default assignment for texmap 0)\r\n    { 0x08000, 0x88000 },  //                                1\r\n    { 0x10000, 0x90000 },  //                                2\r\n    { 0x18000, 0x98000 },  //                                3\r\n    { 0x20000, 0xa0000 },  //                                4\r\n    { 0x28000, 0xa8000 },  //                                5\r\n    { 0x30000, 0xb0000 },  //                                6\r\n    { 0x38000, 0xb8000 }   //                                7\r\n};\r\nint tmem_count = 0;\r\nint tlut_count = 0;\r\n\r\ntypedef enum\r\n{\r\n\tUSE_DIRECT = 0,\r\n\tUSE_DL,\r\n\r\n\tUSE_MAX\r\n} USE;\r\n\r\nUSE\tg_use = USE_MAX;\t\t// Currently set usage.\r\n\r\nstatic _write_u8  _u8 = NULL;\r\nstatic _write_s8  _s8 = NULL;\r\nstatic _write_u16 _u16 = NULL;\r\nstatic _write_s16 _s16 = NULL;\r\nstatic _write_u32 _u32 = NULL;\r\nstatic _write_s32 _s32 = NULL;\r\nstatic _write_f32 _f32 = NULL;\r\nstatic _write_u24 _u24 = NULL;\r\n\r\nstatic _write_BPCmd      _BPCmd = NULL;\r\nstatic _write_CPCmd      _CPCmd = NULL;\r\nstatic _write_XFCmd      _XFCmd = NULL;\r\nstatic _write_XFCmdHdr   _XFCmdHdr = NULL;\r\nstatic _write_XFIndxACmd _XFIndxACmd = NULL;\r\nstatic _write_XFIndxBCmd _XFIndxBCmd = NULL;\r\nstatic _write_XFIndxCCmd _XFIndxCCmd = NULL;\r\nstatic _write_XFIndxDCmd _XFIndxDCmd = NULL;\r\n\r\nu8 GDTexMode0Ids[8] = {\r\n    TX_SETMODE0_I0_ID,\r\n    TX_SETMODE0_I1_ID,\r\n    TX_SETMODE0_I2_ID,\r\n    TX_SETMODE0_I3_ID,\r\n    TX_SETMODE0_I4_ID,\r\n    TX_SETMODE0_I5_ID,\r\n    TX_SETMODE0_I6_ID,\r\n    TX_SETMODE0_I7_ID,\r\n};\r\n\r\nu8 GDTexMode1Ids[8] = {\r\n    TX_SETMODE1_I0_ID,\r\n    TX_SETMODE1_I1_ID,\r\n    TX_SETMODE1_I2_ID,\r\n    TX_SETMODE1_I3_ID,\r\n    TX_SETMODE1_I4_ID,\r\n    TX_SETMODE1_I5_ID,\r\n    TX_SETMODE1_I6_ID,\r\n    TX_SETMODE1_I7_ID,\r\n};\r\n\r\nu8 GDTexImage0Ids[8] = {\r\n    TX_SETIMAGE0_I0_ID,\r\n    TX_SETIMAGE0_I1_ID,\r\n    TX_SETIMAGE0_I2_ID,\r\n    TX_SETIMAGE0_I3_ID,\r\n    TX_SETIMAGE0_I4_ID,\r\n    TX_SETIMAGE0_I5_ID,\r\n    TX_SETIMAGE0_I6_ID,\r\n    TX_SETIMAGE0_I7_ID,\r\n};\r\n\r\nu8 GDTexImage1Ids[8] = {\r\n    TX_SETIMAGE1_I0_ID,\r\n    TX_SETIMAGE1_I1_ID,\r\n    TX_SETIMAGE1_I2_ID,\r\n    TX_SETIMAGE1_I3_ID,\r\n    TX_SETIMAGE1_I4_ID,\r\n    TX_SETIMAGE1_I5_ID,\r\n    TX_SETIMAGE1_I6_ID,\r\n    TX_SETIMAGE1_I7_ID,\r\n};\r\n\r\nu8 GDTexImage2Ids[8] = {\r\n    TX_SETIMAGE2_I0_ID,\r\n    TX_SETIMAGE2_I1_ID,\r\n    TX_SETIMAGE2_I2_ID,\r\n    TX_SETIMAGE2_I3_ID,\r\n    TX_SETIMAGE2_I4_ID,\r\n    TX_SETIMAGE2_I5_ID,\r\n    TX_SETIMAGE2_I6_ID,\r\n    TX_SETIMAGE2_I7_ID,\r\n};\r\n\r\nu8 GDTexImage3Ids[8] = {\r\n    TX_SETIMAGE3_I0_ID,\r\n    TX_SETIMAGE3_I1_ID,\r\n    TX_SETIMAGE3_I2_ID,\r\n    TX_SETIMAGE3_I3_ID,\r\n    TX_SETIMAGE3_I4_ID,\r\n    TX_SETIMAGE3_I5_ID,\r\n    TX_SETIMAGE3_I6_ID,\r\n    TX_SETIMAGE3_I7_ID,\r\n};\r\n\r\nu8 GDTexTlutIds[8] = {\r\n    TX_SETTLUT_I0_ID,\r\n    TX_SETTLUT_I1_ID,\r\n    TX_SETTLUT_I2_ID,\r\n    TX_SETTLUT_I3_ID,\r\n    TX_SETTLUT_I4_ID,\r\n    TX_SETTLUT_I5_ID,\r\n    TX_SETTLUT_I6_ID,\r\n    TX_SETTLUT_I7_ID,\r\n};\r\n\r\nu8 GD2HWFiltConv[] = {\r\n    0, // TX_MIN_NEAREST,                     // GX_NEAR,\r\n    4, // TX_MIN_LINEAR,                      // GX_LINEAR,\r\n    1, // TX_MIN_NEAREST_MIPMAP_NEAREST,      // GX_NEAR_MIP_NEAR,\r\n    5, // TX_MIN_LINEAR_MIPMAP_NEAREST,       // GX_LIN_MIP_NEAR,\r\n    2, // TX_MIN_NEAREST_MIPMAP_LINEAR,       // GX_NEAR_MIP_LIN,\r\n    6, // TX_MIN_LINEAR_MIPMAP_LINEAR,        // GX_LIN_MIP_LIN\r\n};\r\n\r\n#define GX_TMEM_HI  0x80000\r\n#define GX_32k      0x08000\r\n#define GX_8k       0x02000\r\nu32 GXTlutRegions[20] = {\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*0,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*1,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*2,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*3,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*4,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*5,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*6,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*7,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*8,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*9,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*10,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*11,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*12,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*13,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*14,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*15,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*16 + GX_32k*0,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*16 + GX_32k*1,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*16 + GX_32k*2,\r\n    GX_TMEM_HI + GX_32k*8 + GX_8k*16 + GX_32k*3,\r\n};\r\n\r\n/********************************************************************************\r\n * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n#ifndef __PLAT_WN32__\r\nstatic void DirectWrite_u8(u8 data)\r\n{\r\n\tGXWGFifo.u8 = data;\r\n}\r\n\r\nstatic void DirectWrite_s8(s8 data)\r\n{\r\n\tGXWGFifo.s8 = data;\r\n}\r\n\r\nstatic void DirectWrite_u16(u16 data)\r\n{\r\n\tGXWGFifo.u16 = data;\r\n}\r\n\r\nstatic void DirectWrite_s16(s16 data)\r\n{\r\n\tGXWGFifo.s16 = data;\r\n}\r\n\r\nstatic void DirectWrite_u32(u32 data)\r\n{\r\n\tGXWGFifo.u32 = data;\r\n}\r\n\r\nstatic void DirectWrite_s32(s32 data)\r\n{\r\n\tGXWGFifo.s32 = data;\r\n}\r\n\r\nstatic void DirectWrite_f32(f32 data)\r\n{\r\n\tGXWGFifo.f32 = data;\r\n}\r\n\r\nstatic void DirectWrite_u24(u32 data)\r\n{\r\n\tGXWGFifo.u8 = (u8)((data >> 16) & 0xff);\r\n\tGXWGFifo.u8 = (u8)((data >>  8) & 0xff);\r\n\tGXWGFifo.u8 = (u8)((data >>  0) & 0xff);\r\n}\r\n\r\nstatic void DirectWriteBPCmd(u32 regval)\r\n{\r\n\tGXWGFifo.u8 = GX_LOAD_BP_REG;\r\n\tGXWGFifo.u32 = regval;\r\n}\r\n\r\nstatic void DirectWriteCPCmd(u8 addr, u32 val)\r\n{\r\n\tGXWGFifo.u8 = GX_LOAD_CP_REG;\r\n\tGXWGFifo.u8 = addr;\r\n\tGXWGFifo.u32 = val;\r\n}\r\nstatic void DirectWriteXFCmd(u16 addr, u32 val)\r\n{\r\n\tGXWGFifo.u8 = GX_LOAD_XF_REG;\r\n\tGXWGFifo.u16 = 0;\r\n\tGXWGFifo.u16 = addr;\r\n\tGXWGFifo.u32 = val;\r\n}\r\n\r\nstatic void DirectWriteXFCmdHdr(u16 addr, u8 len)\r\n{\r\n\tGXWGFifo.u8 = GX_LOAD_XF_REG;\r\n\tGXWGFifo.u16 = (u16)((len) - 1);\r\n\tGXWGFifo.u16 = addr;\r\n}\r\n\r\nstatic void DirectWriteXFIndxACmd(u16 addr, u8 len, u16 index)\r\n{\r\n\tGXWGFifo.u8 = GX_LOAD_INDX_A;\r\n\tGXWGFifo.u16 = index;\r\n\tGXWGFifo.u16 = __XFAddrLen((addr), ((len)-1));\r\n}\r\n\r\nstatic void DirectWriteXFIndxBCmd(u16 addr, u8 len, u16 index)\r\n{\r\n\tGXWGFifo.u8 = GX_LOAD_INDX_B;\r\n\tGXWGFifo.u16 = index;\r\n\tGXWGFifo.u16 = __XFAddrLen((addr), ((len)-1));\r\n}\r\n\r\nstatic void DirectWriteXFIndxCCmd(u16 addr, u8 len, u16 index)\r\n{\r\n\tGXWGFifo.u8 = GX_LOAD_INDX_C;\r\n\tGXWGFifo.u16 = index;\r\n\tGXWGFifo.u16 = __XFAddrLen((addr), ((len)-1));\r\n}\r\n\r\nstatic void DirectWriteXFIndxDCmd(u16 addr, u8 len, u16 index)\r\n{\r\n\tGXWGFifo.u8 = GX_LOAD_INDX_D;\r\n\tGXWGFifo.u16 = index;\r\n\tGXWGFifo.u16 = __XFAddrLen((addr), ((len)-1));\r\n}\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nvoid begin ( void * p_buffer, int max_size )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tif ( p_buffer && max_size )\r\n\t{\r\n\t\t// We're writing to a display list.\r\n\t\tif ( g_use != USE_DL )\r\n#endif\t\t// __PLAT_WN32__\r\n\t\t{\r\n\t\t\t_u8 = GDWrite_u8;\r\n\t\t\t_s8 = GDWrite_s8;\r\n\t\t\t_u16 = GDWrite_u16;\r\n\t\t\t_s16 = GDWrite_s16;\r\n\t\t\t_u32 = GDWrite_u32;\r\n\t\t\t_s32 = GDWrite_s32;\r\n\t\t\t_f32 = GDWrite_f32;\r\n\t\t\t_u24 = GDWrite_u24;\r\n\r\n\t\t\t_BPCmd = GDWriteBPCmd;\r\n\t\t\t_CPCmd = GDWriteCPCmd;\r\n\t\t\t_XFCmd = GDWriteXFCmd;\r\n\t\t\t_XFCmdHdr = GDWriteXFCmdHdr;\r\n\t\t\t_XFIndxACmd = GDWriteXFIndxACmd;\r\n\t\t\t_XFIndxBCmd = GDWriteXFIndxBCmd;\r\n\t\t\t_XFIndxCCmd = GDWriteXFIndxCCmd;\r\n\t\t\t_XFIndxDCmd = GDWriteXFIndxDCmd;\r\n\t\t\tg_use = USE_DL;\r\n\t\t}\r\n\r\n\t\tGDInitGDLObj( &g_dl, p_buffer, max_size );\r\n\t\tGDSetCurrent( &g_dl );\r\n#ifndef __PLAT_WN32__\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// We're issuing direct commands.\r\n\t\tif ( g_use != USE_DIRECT )\r\n\t\t{\r\n\t\t\t_u8 = DirectWrite_u8;\r\n\t\t\t_s8 = DirectWrite_s8;\r\n\t\t\t_u16 = DirectWrite_u16;\r\n\t\t\t_s16 = DirectWrite_s16;\r\n\t\t\t_u32 = DirectWrite_u32;\r\n\t\t\t_s32 = DirectWrite_s32;\r\n\t\t\t_f32 = DirectWrite_f32;\r\n\t\t\t_u24 = DirectWrite_u24;\r\n\r\n\t\t\t_BPCmd = DirectWriteBPCmd;\r\n\t\t\t_CPCmd = DirectWriteCPCmd;\r\n\t\t\t_XFCmd = DirectWriteXFCmd;\r\n\t\t\t_XFCmdHdr = DirectWriteXFCmdHdr;\r\n\t\t\t_XFIndxACmd = DirectWriteXFIndxACmd;\r\n\t\t\t_XFIndxBCmd = DirectWriteXFIndxBCmd;\r\n\t\t\t_XFIndxCCmd = DirectWriteXFIndxCCmd;\r\n\t\t\t_XFIndxDCmd = DirectWriteXFIndxDCmd;\r\n\t\t\tg_use = USE_DIRECT;\r\n\t\t}\r\n\r\n#ifndef __PLAT_WN32__\r\n//\t\t_BPCmd(TX_SETIMAGE1( MyTmemRegions[7][0] >> 5, 0, 0, 1,  GDTexImage1Ids[GX_TEXMAP7]));\r\n//\t\tif (MyTmemRegions[7][1] < GX_TMEM_MAX) // need to define this!\r\n//\t\t{\r\n//\t\t\t_BPCmd(TX_SETIMAGE2( MyTmemRegions[7][1] >> 5, 0, 0, GDTexImage2Ids[GX_TEXMAP7]));\r\n//\t\t}\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n\t}\r\n#endif\t\t// __PLAT_WN32__\r\n\ttmem_count = 0;\r\n\ttlut_count = 0;\r\n}\r\n\t\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nint end( void )\r\n{\r\n\tint rv;\r\n\r\n\tif ( g_use == USE_DL )\r\n\t{\r\n\t\tGDPadCurr32();\r\n\t\tGDFlushCurrToMem();\r\n\t\trv = GDGetCurrOffset(); \r\n\t}\r\n\telse\r\n\t{\r\n\t\trv = 0;\r\n\t}\r\n\r\n#ifndef __PLAT_WN32__\r\n\t// Usage always goes back to direct after a display list is constructed.\r\n\tif ( g_use != USE_DIRECT )\r\n\t{\r\n\t\t_u8 = DirectWrite_u8;\r\n\t\t_s8 = DirectWrite_s8;\r\n\t\t_u16 = DirectWrite_u16;\r\n\t\t_s16 = DirectWrite_s16;\r\n\t\t_u32 = DirectWrite_u32;\r\n\t\t_s32 = DirectWrite_s32;\r\n\t\t_f32 = DirectWrite_f32;\r\n\t\t_u24 = DirectWrite_u24;\r\n\r\n\t\t_BPCmd = DirectWriteBPCmd;\r\n\t\t_CPCmd = DirectWriteCPCmd;\r\n\t\t_XFCmd = DirectWriteXFCmd;\r\n\t\t_XFCmdHdr = DirectWriteXFCmdHdr;\r\n\t\t_XFIndxACmd = DirectWriteXFIndxACmd;\r\n\t\t_XFIndxBCmd = DirectWriteXFIndxBCmd;\r\n\t\t_XFIndxCCmd = DirectWriteXFIndxCCmd;\r\n\t\t_XFIndxDCmd = DirectWriteXFIndxDCmd;\r\n\t\tg_use = USE_DIRECT;\r\n\t}\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n\treturn rv;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetChanCtrl( GXChannelID\tchan,\r\n\t\t\t\t  GXBool\t\tenable,\r\n\t\t\t\t  GXColorSrc\tamb_src,\r\n\t\t\t\t  GXColorSrc\tmat_src,\r\n\t\t\t\t  u32\t\t\tlight_mask,\r\n\t\t\t\t  GXDiffuseFn\tdiff_fn,\r\n\t\t\t\t  GXAttnFn\t\tattn_fn )\r\n{\r\n    u32 reg;\r\n\r\n    reg =  XF_COLOR0CNTRL_F_PS( mat_src, enable, (light_mask & 0x0f), amb_src,\r\n                                ((attn_fn==GX_AF_SPEC) ? GX_DF_NONE : diff_fn),\r\n                                (attn_fn != GX_AF_NONE),\r\n                                (attn_fn != GX_AF_SPEC),\r\n                                ((light_mask >> 4) & 0x0f) );\r\n    _XFCmd( (u16) (XF_COLOR0CNTRL_ID + (chan & 3)), reg );\r\n\r\n    if (chan == GX_COLOR0A0 || chan == GX_COLOR1A1)\r\n    {\r\n        _XFCmd( (u16) (XF_COLOR0CNTRL_ID + ( chan - 2)), reg );\r\n    }\r\n\r\n//\tGDSetChanCtrl( chan, enable, amb_src, mat_src, light_mask, diff_fn, attn_fn );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetTevOrder( GXTevStageID\tevenStage,\r\n\t\t\t\t  GXTexCoordID\tcoord0,\r\n\t\t\t\t  GXTexMapID\tmap0,\r\n\t\t\t\t  GXChannelID\tcolor0,\r\n\t\t\t\t  GXTexCoordID\tcoord1,\r\n\t\t\t\t  GXTexMapID\tmap1,\r\n\t\t\t\t  GXChannelID\tcolor1 )\r\n{\r\n    static u8 c2r[] = {         // Convert enums to HW values\r\n        RAS1_CC_0,              // GX_COLOR0\r\n        RAS1_CC_1,              // GX_COLOR1\r\n        RAS1_CC_0,              // GX_ALPHA0\r\n        RAS1_CC_1,              // GX_ALPHA1\r\n        RAS1_CC_0,              // GX_COLOR0A0\r\n        RAS1_CC_1,              // GX_COLOR1A1\r\n        RAS1_CC_Z,              // GX_COLOR_ZERO\r\n        RAS1_CC_B,              // GX_COLOR_BUMP\r\n        RAS1_CC_BN,             // GX_COLOR_BUMPN\r\n        0,                      // 9\r\n        0,                      // 10\r\n        0,                      // 11\r\n        0,                      // 12\r\n        0,                      // 13\r\n        0,                      // 14\r\n        RAS1_CC_Z               // 15: GX_COLOR_NULL gets mapped here\r\n    };\r\n\r\n    _BPCmd( RAS1_TREF(\r\n        (map0 & 7),                                             // map 0\r\n        (coord0 & 7),                                           // tc 0\r\n        ((map0 != GX_TEXMAP_NULL) && !(map0 & GX_TEX_DISABLE)), // enable 0\r\n        c2r[ color0 & 0xf ],                                    // color 0\r\n        (map1 & 7),                                             // map 1\r\n        (coord1 & 7),                                           // tc 1\r\n        ((map1 != GX_TEXMAP_NULL) && !(map1 & GX_TEX_DISABLE)), // enable 1\r\n        c2r[ color1 & 0xf ],                                    // color 1\r\n        (RAS1_TREF0_ID + (evenStage/2)) ));\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetTevAlphaInOpSwap( GXTevStageID\tstage,\r\n\t\t\t\t\t\t  GXTevAlphaArg\ta,\r\n\t\t\t\t\t\t  GXTevAlphaArg\tb,\r\n\t\t\t\t\t\t  GXTevAlphaArg\tc,\r\n\t\t\t\t\t\t  GXTevAlphaArg\td,\r\n\t\t\t\t\t\t  GXTevOp\t\top,\r\n\t\t\t\t\t\t  GXTevBias\t\tbias,\r\n\t\t\t\t\t\t  GXTevScale\tscale,\r\n\t\t\t\t\t\t  GXBool\t\tclamp,\r\n\t\t\t\t\t\t  GXTevRegID\tout_reg,\r\n\t\t\t\t\t\t  GXTevSwapSel\tras_sel,\r\n\t\t\t\t\t\t  GXTevSwapSel\ttex_sel )\r\n{\r\n    if (op <= GX_TEV_SUB) \r\n    {\r\n        _BPCmd( TEV_ALPHA_ENV( ras_sel, tex_sel,\r\n                               d, c, b, a, \r\n                               bias, (op & 1), clamp, scale,\r\n                               out_reg,\r\n                               TEV_ALPHA_ENV_0_ID + 2 * (u32) stage ));\r\n    } else {\r\n        _BPCmd( TEV_ALPHA_ENV( ras_sel, tex_sel,\r\n                               d, c, b, a,\r\n                               GX_MAX_TEVBIAS, (op&1), clamp, ((op>>1)&3),\r\n                               out_reg,\r\n                               TEV_ALPHA_ENV_0_ID + 2 * (u32) stage ));\r\n    }\r\n\r\n//\tGDSetTevAlphaCalcAndSwap( stage, a, b, c, d, op, bias, scale, clamp, out_reg, ras_sel, tex_sel );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetTevColorInOp( GXTevStageID\tstage,\r\n\t\t\t\t\t  GXTevColorArg a,\r\n\t\t\t\t\t  GXTevColorArg b,\r\n\t\t\t\t\t  GXTevColorArg c,\r\n\t\t\t\t\t  GXTevColorArg d,\r\n\t\t\t\t\t  GXTevOp       op,\r\n\t\t\t\t\t  GXTevBias     bias,\r\n\t\t\t\t\t  GXTevScale    scale,\r\n\t\t\t\t\t  GXBool        clamp,\r\n\t\t\t\t\t  GXTevRegID    out_reg )\r\n{\r\n    if (op <= GX_TEV_SUB) \r\n    {\r\n        _BPCmd( TEV_COLOR_ENV( d, c, b, a, \r\n                               bias, (op & 1), clamp, scale,\r\n                               out_reg,\r\n                               TEV_COLOR_ENV_0_ID + 2 * (u32) stage ));\r\n    } else {\r\n        _BPCmd( TEV_COLOR_ENV( d, c, b, a,\r\n                               GX_MAX_TEVBIAS, (op&1), clamp, ((op>>1)&3),\r\n                               out_reg,\r\n                               TEV_COLOR_ENV_0_ID + 2 * (u32) stage ));\r\n    }\r\n\t\r\n//\tGDSetTevColorCalc( stage, a, b, c, d, op, bias, scale, clamp, out_reg ); \r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetTevKSel( GXTevStageID\teven_stage,\r\n\t\t\t\t GXTevKColorSel color_even,\r\n\t\t\t\t GXTevKAlphaSel alpha_even,\r\n\t\t\t\t GXTevKColorSel color_odd,\r\n\t\t\t\t GXTevKAlphaSel alpha_odd )\r\n{\r\n\t_BPCmd( SS_MASK( TEV_KSEL_MASK_KCSEL ) );\r\n\t_BPCmd( TEV_KSEL( 0, 0, color_even, alpha_even, color_odd, alpha_odd, TEV_KSEL_0_ID + (even_stage/2) ));\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetTevKColor( GXTevKColorID id,\r\n\t\t\t\t   GXColor color )\r\n{\r\n    u32 regRA, regBG;\r\n\r\n    regRA = TEV_REGISTERL( color.r, color.a, TEV_KONSTANT_REG,\r\n                           TEV_REGISTERL_0_ID + id * 2 );\r\n    regBG = TEV_REGISTERH( color.b, color.g, TEV_KONSTANT_REG, \r\n                           TEV_REGISTERH_0_ID + id * 2 );\r\n    _BPCmd( regRA );\r\n    _BPCmd( regBG );\r\n    // The KColor registers do not have the load delay bug.\r\n\r\n//\tGDSetTevKColor( id, color );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetTevColor( GXTevRegID\treg,\r\n\t\t\t\t  GXColor\t\tcolor )\r\n{\r\n    u32 regRA, regBG;\r\n\r\n    regRA = TEV_REGISTERL( color.r, color.a, TEV_COLOR_REG, \r\n                           TEV_REGISTERL_0_ID + reg * 2 );\r\n    regBG = TEV_REGISTERH( color.b, color.g, TEV_COLOR_REG, \r\n                           TEV_REGISTERH_0_ID + reg * 2 );\r\n    _BPCmd( regRA );\r\n\t_BPCmd( regBG );\r\n    // Due to color load delay bug, must put two more BP commands here...\r\n    _BPCmd( regBG );\r\n    _BPCmd( regBG );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetTexCoordGen( GXTexCoordID\tdst_coord,\r\n\t\t\t\t\t GXTexGenType\tfunc,\r\n\t\t\t\t\t GXTexGenSrc\tsrc_param,\r\n\t\t\t\t\t GXBool\t\t\tnormalize,\r\n\t\t\t\t\t u32\t\t\tpostmtx )\r\n{\r\n    u32     form;\r\n    u32     tgType;\r\n    u32     proj;\r\n    u32     row;\r\n    u32     embossRow;\r\n    u32     embossLit;\r\n    \r\n    form      = XF_TEX_AB11;\r\n    proj      = XF_TEX_ST;\r\n    row       = XF_TEX0_INROW;\r\n    embossRow = XF_TEX0_INROW;\r\n    embossLit = 0;\r\n\r\n#ifndef __PLAT_WN32__\r\n    ASSERTMSG((dst_coord < GX_MAX_TEXCOORD),\r\n              \"GDSetTexCoordGen: invalid texcoord ID\");\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n    switch (src_param) {\r\n      case GX_TG_POS:     row = XF_GEOM_INROW;       form = XF_TEX_ABC1; break;\r\n      case GX_TG_NRM:     row = XF_NORMAL_INROW;     form = XF_TEX_ABC1; break; \r\n      case GX_TG_BINRM:   row = XF_BINORMAL_T_INROW; form = XF_TEX_ABC1; break;\r\n      case GX_TG_TANGENT: row = XF_BINORMAL_B_INROW; form = XF_TEX_ABC1; break;\r\n      case GX_TG_COLOR0:  row = XF_COLORS_INROW; break;\r\n      case GX_TG_COLOR1:  row = XF_COLORS_INROW; break;\r\n      case GX_TG_TEX0:    row = XF_TEX0_INROW;   break;\r\n      case GX_TG_TEX1:    row = XF_TEX1_INROW;   break;\r\n      case GX_TG_TEX2:    row = XF_TEX2_INROW;   break;\r\n      case GX_TG_TEX3:    row = XF_TEX3_INROW;   break;\r\n      case GX_TG_TEX4:    row = XF_TEX4_INROW;   break;\r\n      case GX_TG_TEX5:    row = XF_TEX5_INROW;   break;\r\n      case GX_TG_TEX6:    row = XF_TEX6_INROW;   break;\r\n      case GX_TG_TEX7:    row = XF_TEX7_INROW;   break;\r\n      case GX_TG_TEXCOORD0: embossRow = 0; break;\r\n      case GX_TG_TEXCOORD1: embossRow = 1; break;\r\n      case GX_TG_TEXCOORD2: embossRow = 2; break;\r\n      case GX_TG_TEXCOORD3: embossRow = 3; break;\r\n      case GX_TG_TEXCOORD4: embossRow = 4; break;\r\n      case GX_TG_TEXCOORD5: embossRow = 5; break;\r\n      case GX_TG_TEXCOORD6: embossRow = 6; break;\r\n      default:\r\n#ifndef __PLAT_WN32__\r\n        ASSERTMSG(0, \"GDSetTexCoordGen: invalid texgen source\");\r\n#endif\t\t// __PLAT_WN32__\r\n        break;\r\n    }\r\n\r\n    switch (func) {\r\n      case GX_TG_MTX2x4:\r\n        tgType = XF_TEXGEN_REGULAR;\r\n        break;\r\n        \r\n      case GX_TG_MTX3x4:\r\n        tgType = XF_TEXGEN_REGULAR;\r\n        proj   = XF_TEX_STQ;\r\n        break;\r\n\r\n      case GX_TG_BUMP0:\r\n      case GX_TG_BUMP1:\r\n      case GX_TG_BUMP2:\r\n      case GX_TG_BUMP3:\r\n      case GX_TG_BUMP4:\r\n      case GX_TG_BUMP5:\r\n      case GX_TG_BUMP6:\r\n      case GX_TG_BUMP7:\r\n#ifndef __PLAT_WN32__\r\n        ASSERTMSG((src_param >= GX_TG_TEXCOORD0) && \r\n                  (src_param <= GX_TG_TEXCOORD6),\r\n                  \"GDSetTexCoordGen: invalid emboss source\");\r\n#endif\t\t// __PLAT_WN32__\r\n        tgType = XF_TEXGEN_EMBOSS_MAP;\r\n        embossLit = (u32) (func - GX_TG_BUMP0);\r\n        break;\r\n\r\n      case GX_TG_SRTG:\r\n        if (src_param == GX_TG_COLOR0) {\r\n            tgType = XF_TEXGEN_COLOR_STRGBC0;\r\n        } else {\r\n            tgType = XF_TEXGEN_COLOR_STRGBC1;\r\n        }\r\n        break;\r\n\r\n      default:\r\n#ifndef __PLAT_WN32__\r\n        ASSERTMSG(0, \"GDSetTexCoordGen: invalid texgen function\");\r\n#endif\t\t// __PLAT_WN32__\r\n        tgType = XF_TEXGEN_REGULAR;\r\n        break;\r\n    }\r\n\r\n    _XFCmd( (u16) (XF_TEX0_ID + dst_coord), XF_TEX( proj, form, tgType, row, embossRow, embossLit ));\r\n\r\n    //---------------------------------------------------------------------\r\n    // Update DUALTEX state\r\n    //---------------------------------------------------------------------\r\n\r\n    _XFCmd( (u16) (XF_DUALTEX0_ID + dst_coord), XF_DUALTEX((postmtx - GX_PTTEXMTX0), normalize ));\r\n\r\n//\tGDSetTexCoordGen ( dst_coord, func, src_param, normalize, postmtx ); \r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid UploadTexture( void *\t\t\timage_ptr,\r\n\t\t\t\t\tu16\t\t\t\twidth,\r\n\t\t\t\t\tu16\t\t\t\theight,\r\n\t\t\t\t\tGXTexFmt\t\tformat,\r\n\t\t\t\t\tGXTexWrapMode\twrap_s,\r\n\t\t\t\t\tGXTexWrapMode\twrap_t,\r\n\t\t\t\t\tGXBool\t\t\tmipmap,\r\n\t\t\t\t\tGXTexFilter\t\tmin_filt,\r\n\t\t\t\t\tGXTexFilter\t\tmag_filt,\r\n\t\t\t\t\tf32\t\t\t\tmin_lod,\r\n\t\t\t\t\tf32\t\t\t\tmax_lod,\r\n\t\t\t\t\tf32\t\t\t\tlod_bias,\r\n\t\t\t\t\tGXBool\t\t\tbias_clamp,\r\n\t\t\t\t\tGXBool\t\t\tdo_edge_lod,\r\n\t\t\t\t\tGXAnisotropy\tmax_aniso,\r\n\t\t\t\t\tGXTexMapID\t\tid )\r\n{\r\n#if 0\r\n\tGXTexObj to;\r\n\r\n    GXInitTexObj(\r\n\t\t&to,\r\n\t\timage_ptr,\r\n\t\twidth,\r\n\t\theight,\r\n\t\tformat,\r\n\t\twrap_s,\r\n\t\twrap_t,\r\n\t\tmipmap );\r\n\t\r\n\tGXInitTexObjLOD(\r\n\t\t&to,\r\n\t\tmin_filt,\r\n\t\tmag_filt,\r\n\t\tmin_lod,\r\n\t\tmax_lod,\r\n\t\tlod_bias,\r\n\t\tbias_clamp,\r\n\t\tdo_edge_lod,\r\n\t\tmax_aniso );\r\n\r\n    GXLoadTexObj( &to, id );\r\n#else\r\n\r\n//\tGDSetTexLookupMode(\tid, wrap_s, wrap_t, min_filt, mag_filt, min_lod, max_lod, lod_bias, bias_clamp, do_edge_lod, max_aniso );\r\n\r\n    _BPCmd(TX_SETMODE0(wrap_s,\r\n                       wrap_t,\r\n                       (mag_filt == GX_LINEAR),\r\n                       GD2HWFiltConv[min_filt],\r\n                       !do_edge_lod,\r\n                       (u8)((s8)(lod_bias*32.0f)),\r\n                       max_aniso,\r\n                       bias_clamp,\r\n                       GDTexMode0Ids[id]));\r\n    _BPCmd(TX_SETMODE1((u8)(min_lod*16.0f),\r\n                       (u8)(max_lod*16.0f),\r\n                       GDTexMode1Ids[id]));\r\n\r\n//\tGDSetTexImgAttr(\tid, width, height, format );\r\n\r\n    _BPCmd(TX_SETIMAGE0(width - 1,\r\n                        height - 1,\r\n                        format,\r\n                        GDTexImage0Ids[id]));\r\n\r\n//\tGDSetTexCached(\t\tid, MyTmemRegions[tmem_count][0], GX_TEXCACHE_32K,\r\n//\t\t\t\t\t\t\tMyTmemRegions[tmem_count][1], GX_TEXCACHE_32K );\r\n\r\n    _BPCmd(TX_SETIMAGE1( MyTmemRegions[tmem_count][0] >> 5,\r\n\t\t\t\t\t\t GX_TEXCACHE_32K+3, \r\n\t\t\t\t\t\t GX_TEXCACHE_32K+3, \r\n                         0, \r\n                         GDTexImage1Ids[id]));\r\n    if (GX_TEXCACHE_32K != GX_TEXCACHE_NONE && MyTmemRegions[tmem_count][1] < GX_TMEM_MAX)\r\n    {\r\n        _BPCmd(TX_SETIMAGE2( MyTmemRegions[tmem_count][1] >> 5,\r\n\t\t\t\t\t\t\t GX_TEXCACHE_32K+3,\r\n\t\t\t\t\t\t\t GX_TEXCACHE_32K+3,\r\n                             GDTexImage2Ids[id]));\r\n    }\r\n\r\n\ttmem_count++;\r\n\ttmem_count &= 7;\r\n\r\n#ifdef __PLAT_WN32__\r\n//\t\t\tGDSetTexImgPtrRaw(\tid, (uint32)image_ptr );\r\n\r\n\t\t\t_BPCmd(TX_SETIMAGE3((uint32)image_ptr, GDTexImage3Ids[id]));\r\n\r\n#else\r\n//\t\t\tGDSetTexImgPtr(\t\tid, image_ptr );\r\n\r\n\t\t\t_BPCmd(TX_SETIMAGE3(OSCachedToPhysical(image_ptr)>>5,\r\n\t\t\t\t\t\t\t\t\t  GDTexImage3Ids[id]));\r\n#endif\t\t// __PLAT_WN32__\r\n#endif\r\n}\r\n\r\nvoid UploadTexture( void *\t\t\timage_ptr,\r\n\t\t\t\t\tu16\t\t\t\twidth,\r\n\t\t\t\t\tu16\t\t\t\theight,\r\n\t\t\t\t\tGXCITexFmt\t\tformat,\r\n\t\t\t\t\tGXTexWrapMode\twrap_s,\r\n\t\t\t\t\tGXTexWrapMode\twrap_t,\r\n\t\t\t\t\tGXBool\t\t\tmipmap,\r\n\t\t\t\t\tGXTexFilter\t\tmin_filt,\r\n\t\t\t\t\tGXTexFilter\t\tmag_filt,\r\n\t\t\t\t\tf32\t\t\t\tmin_lod,\r\n\t\t\t\t\tf32\t\t\t\tmax_lod,\r\n\t\t\t\t\tf32\t\t\t\tlod_bias,\r\n\t\t\t\t\tGXBool\t\t\tbias_clamp,\r\n\t\t\t\t\tGXBool\t\t\tdo_edge_lod,\r\n\t\t\t\t\tGXAnisotropy\tmax_aniso,\r\n\t\t\t\t\tGXTexMapID\t\tid )\r\n{\r\n\tUploadTexture( image_ptr,\r\n\t\t\t\t   width,\r\n\t\t\t\t   height,\r\n\t\t\t\t   (GXTexFmt)format,\r\n\t\t\t\t   wrap_s,\r\n\t\t\t\t   wrap_t, \r\n\t\t\t\t   mipmap,\r\n\t\t\t\t   min_filt,\r\n\t\t\t\t   mag_filt,\r\n\t\t\t\t   min_lod,\r\n\t\t\t\t   max_lod,\r\n\t\t\t\t   lod_bias,\r\n\t\t\t\t   bias_clamp,\r\n\t\t\t\t   do_edge_lod,\r\n\t\t\t\t   max_aniso,\r\n\t\t\t\t   id );\r\n};\r\n\t\t\t\t\t\t\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid UploadPalette( void *\t\ttlut_ptr,\r\n\t\t\t\t\tGXTlutFmt\ttlut_format,\r\n\t\t\t\t\tGXTlutSize\ttlut_size,\r\n\t\t\t\t\tGXTexMapID\tid )\r\n{\r\n//    GDSetTexTlut ( GX_TEXMAP0, TLUT0_ADDR, GX_TL_RGB565 );\r\n    _BPCmd(TX_SETTLUT( (GXTlutRegions[tlut_count]-GX_TMEM_HALF) >> 9, tlut_format, GDTexTlutIds[id]));\r\n\r\n//    GDLoadTlutRaw ( 0, TLUT0_ADDR, GX_TLUT_256 );\r\n#ifndef __PLAT_WN32__\r\n    ASSERTMSG((tlut_size <= 1024), \"GDLoadTlut: invalid TLUT size\");\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n    // Flush the texture state (without modifying the indirect mask)\r\n    _BPCmd(SS_MASK(0xffff00));\r\n\t_BPCmd((BU_IMASK_ID << 24));\r\n\r\n#ifdef __PLAT_WN32__\r\n\t_BPCmd(TX_LOADTLUT0( ((uint32)tlut_ptr>>5), TX_LOADTLUT0_ID));\r\n#else\r\n\t_BPCmd(TX_LOADTLUT0( (OSCachedToPhysical(tlut_ptr)>>5), TX_LOADTLUT0_ID));\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n    // Writing to this register will initiate the actual loading:\r\n    _BPCmd(TX_LOADTLUT1( (GXTlutRegions[tlut_count]-GX_TMEM_HALF) >> 9, tlut_size,\r\n                             TX_LOADTLUT1_ID));\r\n\r\n    // Flush the texture state (without modifying the indirect mask)\r\n    _BPCmd(SS_MASK(0xffff00));\r\n    _BPCmd((BU_IMASK_ID << 24));\r\n\r\n\ttlut_count++;\r\n\ttlut_count %= 20;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetTexCoordScale( GXTexCoordID\tcoord,\r\n\t\t\t\t\t   GXBool\t\tenable,\r\n\t\t\t\t\t   u16\t\t\tss,\r\n\t\t\t\t\t   u16\t\t\tts )\r\n{\r\n//\tGDSetTexCoordScaleAndTOEs( coord, ss, GX_DISABLE, GX_DISABLE, ts, GX_DISABLE, GX_DISABLE, GX_FALSE, GX_FALSE );\r\n\r\n    _BPCmd(SU_TS0( ss - 1, GX_DISABLE, GX_DISABLE, GX_TRUE, GX_TRUE,\r\n                         SU_SSIZE0_ID + (u32) coord * 2));\r\n    _BPCmd(SU_TS1( ts - 1, GX_DISABLE, GX_DISABLE,\r\n                         SU_TSIZE0_ID + (u32) coord * 2));\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetBlendMode( GXBlendMode\t\ttype,\r\n                   GXBlendFactor\tsrc_factor,\r\n                   GXBlendFactor\tdst_factor,\r\n                   GXLogicOp\t\top,\r\n\t\t\t\t   GXBool\t\t\tcolor_update_enable,\r\n\t\t\t\t   GXBool\t\t\talpha_update_enable,\r\n\t\t\t\t   GXBool\t\t\tdither_enable )\r\n{\r\n//\tGDSetBlendModeEtc( type, src_factor, dst_factor, op, GX_TRUE, GX_TRUE, GX_TRUE );\r\n\r\n    _BPCmd( PE_CMODE0( \r\n        ((type == GX_BM_BLEND) || (type == GX_BM_SUBTRACT)),\r\n        (type == GX_BM_LOGIC),\r\n\t\tGX_FALSE,\t//dither_enable,\r\n\t\tcolor_update_enable,\r\n\t\tGX_FALSE,\t//alpha_update_enable,\r\n        dst_factor,\r\n        src_factor,\r\n        (type == GX_BM_SUBTRACT),\r\n        op,\r\n        PE_CMODE0_ID ));\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetTexChanTevIndCull( u8\t\t\tnTexGens,\r\n\t\t\t\t\t\t   u8\t\t\tnChans,\r\n\t\t\t\t\t\t   u8\t\t\tnTevs,\r\n\t\t\t\t\t\t   u8\t\t\tnInds,\r\n\t\t\t\t\t\t   GXCullMode\tcm )\r\n{\r\n//\tGDSetGenMode2( nTexGens, nChans, nTevs, nInds, cm );\r\n\r\n\tstatic u8 cm2hw[] = { 0, 2, 1, 3 };\r\n\t_XFCmd( XF_NUMTEX_ID, XF_NUMTEX( nTexGens ));\r\n\t_XFCmd( XF_NUMCOLORS_ID, XF_NUMCOLORS( nChans ));\r\n\t_BPCmd( GEN_MODE( nTexGens, nChans, 0, (nTevs-1), cm2hw[cm], nInds, 0, GEN_MODE_ID ));\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetChanAmbColor( GXChannelID chan,\r\n\t\t\t\t\t  GXColor color )\r\n{\r\n    _XFCmd( (u16) (XF_AMBIENT0_ID + (chan & 1)),\r\n                  (((u32)color.r << 24) | \r\n                   ((u32)color.g << 16) |\r\n                   ((u32)color.b <<  8) | \r\n                   ((u32)color.a)) );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetChanMatColor( GXChannelID chan,\r\n\t\t\t\t\t  GXColor color )\r\n{\r\n    _XFCmd( (u16) (XF_MATERIAL0_ID + (chan & 1)),\r\n                  (((u32)color.r << 24) | \r\n                   ((u32)color.g << 16) |\r\n                   ((u32)color.b <<  8) | \r\n                   ((u32)color.a)) );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetPointSize( u8\t\t\tpointSize,\r\n\t\t\t\t   GXTexOffset\ttexOffsets )\r\n{\r\n\t//GDSetLPSize\r\n    _BPCmd( SU_LPSIZE( pointSize, pointSize, texOffsets, texOffsets, GX_FALSE, SU_LPSIZE_ID ));\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetFog( GXFogType\ttype,\r\n\t\t\t f32\t\tstartz,\r\n\t\t\t f32\t\tendz,\r\n\t\t\t f32\t\tnearz,\r\n\t\t\t f32\t\tfarz,\r\n\t\t\t GXColor\tcolor )\r\n{\r\n#ifndef __PLAT_WN32__\r\n    f32     A, B, B_mant, C, A_f;\r\n    u32     b_expn, b_m, a_hex, c_hex;\r\n    u32     fsel, proj;\r\n\r\n    ASSERTMSG(farz >= 0, \"GDSetFog: The farz should be positive value\");\r\n    ASSERTMSG(farz >= nearz, \"GDSetFog: The farz should be larger than nearz\");\r\n\r\n    fsel = (u32)(type & 0x07);\r\n    proj = (u32)((type >> 3) & 0x01);\r\n\r\n    if ( proj ) // ORTHOGRAPHIC\r\n    {\r\n        // Calculate constants a and c (TEV HW requirements).\r\n        if ((farz == nearz) || (endz == startz))\r\n        {\r\n            // take care of the odd-ball case.\r\n            A_f = 0.0f;\r\n            C   = 0.0f;\r\n        }\r\n        else\r\n        {\r\n            A   = 1.0F / (endz - startz);\r\n            A_f = (farz - nearz) * A;\r\n            C   = (startz - nearz) * A;\r\n        }\r\n\r\n        b_expn = 0;\r\n        b_m    = 0;\r\n    }\r\n    else // PERSPECTIVE\r\n    {\r\n        // Calculate constants a, b, and c (TEV HW requirements).\r\n        if ((farz == nearz) || (endz == startz))\r\n        {\r\n            // take care of the odd-ball case.\r\n            A = 0.0f;\r\n            B = 0.5f;\r\n            C = 0.0f;\r\n        }\r\n        else\r\n        {\r\n            A = (farz * nearz) / ((farz-nearz) * (endz-startz));\r\n            B = farz / (farz-nearz);\r\n            C = startz / (endz-startz);\r\n        }\r\n        \r\n        B_mant = B;\r\n        b_expn = 1;\r\n        while (B_mant > 1.0) \r\n        {\r\n            B_mant /= 2;\r\n            b_expn++;\r\n        }\r\n        while ((B_mant > 0) && (B_mant < 0.5))\r\n        {\r\n            B_mant *= 2;\r\n            b_expn--;\r\n        }\r\n\r\n        A_f   = A / (1 << (b_expn));\r\n        b_m   = (u32)(B_mant * 8388638);\r\n    }\r\n\r\n    a_hex = (* (u32 *) &A_f);\r\n    c_hex = (* (u32 *) &C);\r\n\r\n    // Write out register values.\r\n    _BPCmd( TEV_FOG_PARAM_0_PS( (a_hex >> 12), TEV_FOG_PARAM_0_ID ));\r\n\r\n\t_BPCmd( TEV_FOG_PARAM_1( b_m, TEV_FOG_PARAM_1_ID ));\r\n\t_BPCmd( TEV_FOG_PARAM_2( b_expn, TEV_FOG_PARAM_2_ID ));\r\n\r\n\t_BPCmd( TEV_FOG_PARAM_3_PS( (c_hex >> 12), proj, fsel, \r\n                               TEV_FOG_PARAM_3_ID ));\r\n\r\n\t_BPCmd( TEV_FOG_COLOR( color.b, color.g, color.r, TEV_FOG_COLOR_ID ));\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetFogColor( GXColor color )\r\n{\r\n\t_BPCmd( TEV_FOG_COLOR( color.b, color.g, color.r, TEV_FOG_COLOR_ID ));\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Begin( GXPrimitive type,\r\n\t\t\tGXVtxFmt vtxfmt,\r\n\t\t\tu16 nverts )\r\n{\r\n    _u8((u8) (vtxfmt | type));\r\n    _u16(nverts);\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid End( void )\r\n{\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Position3f32( f32 x,\r\n\t\t\t\t   f32 y,\r\n\t\t\t\t   f32 z )\r\n{\r\n\t_f32( x );\r\n\t_f32( y );\r\n\t_f32( z );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Position3u8( u8 x,\r\n\t\t\t\t  u8 y,\r\n\t\t\t\t  u8 z )\r\n{\r\n\t_u8( x );\r\n\t_u8( y );\r\n\t_u8( z );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Position3s8( s8 x,\r\n\t\t\t\t  s8 y,\r\n\t\t\t\t  s8 z )\r\n{\r\n\t_s8( x );\r\n\t_s8( y );\r\n\t_s8( z );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Position3u16( u16 x,\r\n\t\t\t\t   u16 y,\r\n\t\t\t\t   u16 z )\r\n{\r\n\t_u16( x );\r\n\t_u16( y );\r\n\t_u16( z );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Position3s16( s16 x,\r\n\t\t\t\t   s16 y,\r\n\t\t\t\t   s16 z )\r\n{\r\n\t_s16( x );\r\n\t_s16( y );\r\n\t_s16( z );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Position2f32( f32 x,\r\n\t\t\t\t   f32 y )\r\n{\r\n\t_f32( x );\r\n\t_f32( y );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Position2u8( u8 x,\r\n\t\t\t\t  u8 y )\r\n{\r\n\t_u8( x );\r\n\t_u8( y );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Position2s8( s8 x,\r\n\t\t\t\t  s8 y )\r\n{\r\n\t_s8( x );\r\n\t_s8( y );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Position2u16( u16 x,\r\n\t\t\t\t   u16 y )\r\n{\r\n\t_u16( x );\r\n\t_u16( y );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Position2s16( s16 x,\r\n\t\t\t\t   s16 y )\r\n{\r\n\t_s16( x );\r\n\t_s16( y );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Position1x16( u16 i )\r\n{\r\n\t_u16( i );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Position1x8( u8 i )\r\n{\r\n\t_u8( i );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Normal3f32( f32 x,\r\n\t\t\t\t f32 y,\r\n\t\t\t\t f32 z )\r\n{\r\n\t_f32( x );\r\n\t_f32( y );\r\n\t_f32( z );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Normal3s16( s16 x,\r\n\t\t\t\t s16 y,\r\n\t\t\t\t s16 z )\r\n{\r\n\t_s16( x );\r\n\t_s16( y );\r\n\t_s16( z );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Normal3s8( s8 x,\r\n\t\t\t\ts8 y,\r\n\t\t\t\ts8 z )\r\n{\r\n\t_s8( x );\r\n\t_s8( y );\r\n\t_s8( z );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Normal1x16( u16 i )\r\n{\r\n\t_u16( i );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Normal1x8( u8 i )\r\n{\r\n\t_u8( i );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Color4u8( u8 r,\r\n\t\t\t   u8 g,\r\n\t\t\t   u8 b,\r\n\t\t\t   u8 a )\r\n{\r\n\t_u8( r );\r\n\t_u8( g );\r\n\t_u8( b );\r\n\t_u8( a );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Color1u32( u32 rgba )\r\n{\r\n\t_u32( rgba );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Color1x16( u16 i )\r\n{\r\n\t_u16( i );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Color1x8( u8 i )\r\n{\r\n\t_u8( i );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid TexCoord2f32( f32 s,\r\n\t\t\t\t   f32 t )\r\n{\r\n\t_f32( s );\r\n\t_f32( t );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid TexCoord2s16( s16 s,\r\n\t\t\t\t   s16 t )\r\n{\r\n\t_s16( s );\r\n\t_s16( t );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid TexCoord2u16( u16 s,\r\n\t\t\t\t   u16 t )\r\n{\r\n\t_u16( s );\r\n\t_u16( t );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid TexCoord2s8( s8 s,\r\n\t\t\t\t  s8 t )\r\n{\r\n\t_s8( s );\r\n\t_s8( t );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid TexCoord2u8( u8 s,\r\n\t\t\t\t  u8 t )\r\n{\r\n\t_u8( s );\r\n\t_u8( t );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid TexCoord1f32( f32 s )\r\n{\r\n\t_f32( s );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid TexCoord1s16( s16 s )\r\n{\r\n\t_s16( s );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid TexCoord1u16( u16 s )\r\n{\r\n\t_u16( s );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid TexCoord1s8( s8 s )\r\n{\r\n\t_s8( s );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid TexCoord1u8( u8 s )\r\n{\r\n\t_u8( s );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid TexCoord1x16( u16 i )\r\n{\r\n\t_u16( i );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid TexCoord1x8( u8 i )\r\n{\r\n\t_u8( i );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid MatrixIndex1u8( u8 i )\r\n{\r\n\t_u8( i );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetZMode( GXBool     compare_enable,\r\n\t\t\t   GXCompare  func,\r\n\t\t\t   GXBool     update_enable )\r\n{\r\n    _BPCmd( PE_ZMODE( compare_enable, func, update_enable, PE_ZMODE_ID ));\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetVtxDesc( int items, ... )\r\n{\r\n    u32 nnorms = 0;\r\n    u32 ncols  = 0;\r\n    u32 ntexs  = 0;\r\n\r\n    u32 pnMtxIdx = GX_NONE;\r\n    u32 txMtxIdxMask = 0;\r\n    u32 posn = GX_DIRECT;\r\n    u32 norm = GX_NONE;\r\n    u32 col0 = GX_NONE;\r\n    u32 col1 = GX_NONE;\r\n    u32 tex0 = GX_NONE;\r\n    u32 tex1 = GX_NONE;\r\n    u32 tex2 = GX_NONE;\r\n    u32 tex3 = GX_NONE;\r\n    u32 tex4 = GX_NONE;\r\n    u32 tex5 = GX_NONE;\r\n    u32 tex6 = GX_NONE;\r\n    u32 tex7 = GX_NONE;\r\n\r\n\t// Start the arguments.\r\n\tva_list\tvl;\r\n\tva_start( vl, items );\r\n\r\n\tfor ( int item = 0; item < items; item++ )\r\n\t{\r\n\t\t// Get this item.\r\n\t\tGXAttr\t\tattribute\t= va_arg( vl, GXAttr );\r\n\t\tGXAttrType\ttype\t\t= va_arg( vl, GXAttrType );\r\n\r\n#ifndef __PLAT_WN32__\r\n        ASSERTMSG(((attribute >= GX_VA_PNMTXIDX) && \r\n                   (attribute <= GX_VA_MAX_ATTR)),\r\n                  \"GDSetVtxDescv: invalid attribute\");\r\n\r\n        ASSERTMSG(((type >= GX_NONE) && \r\n                   (type <= GX_INDEX16)),\r\n                  \"GDSetVtxDescv: invalid type\");\r\n\r\n        ASSERTMSG(((attribute >= GX_VA_PNMTXIDX) &&\r\n                   (attribute <= GX_VA_TEX7MTXIDX)) ?\r\n                  ((type == GX_NONE) ||\r\n                   (type == GX_DIRECT)) : 1,\r\n                  \"GDSetVtxDescv: invalid type for given attribute\");\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n        switch (attribute) {\r\n\r\n          case GX_VA_PNMTXIDX: pnMtxIdx = type; break;\r\n\r\n          case GX_VA_TEX0MTXIDX:\r\n            txMtxIdxMask = (txMtxIdxMask &   ~1) | (type << 0); break;\r\n          case GX_VA_TEX1MTXIDX:\r\n            txMtxIdxMask = (txMtxIdxMask &   ~2) | (type << 1); break;\r\n          case GX_VA_TEX2MTXIDX:\r\n            txMtxIdxMask = (txMtxIdxMask &   ~4) | (type << 2); break;\r\n          case GX_VA_TEX3MTXIDX:\r\n            txMtxIdxMask = (txMtxIdxMask &   ~8) | (type << 3); break;\r\n          case GX_VA_TEX4MTXIDX:\r\n            txMtxIdxMask = (txMtxIdxMask &  ~16) | (type << 4); break;\r\n          case GX_VA_TEX5MTXIDX:\r\n            txMtxIdxMask = (txMtxIdxMask &  ~32) | (type << 5); break;\r\n          case GX_VA_TEX6MTXIDX:\r\n            txMtxIdxMask = (txMtxIdxMask &  ~64) | (type << 6); break;\r\n          case GX_VA_TEX7MTXIDX:\r\n            txMtxIdxMask = (txMtxIdxMask & ~128) | (type << 7); break;\r\n\r\n          case GX_VA_POS: posn = type; break;\r\n\r\n          case GX_VA_NRM:\r\n            if (type != GX_NONE)\r\n                { norm = type; nnorms = 1; }\r\n            break;\r\n          case GX_VA_NBT:\r\n            if (type != GX_NONE)\r\n                { norm = type; nnorms = 2; }\r\n            break;\r\n\r\n          case GX_VA_CLR0: col0=type; ncols+=(col0 != GX_NONE); break;\r\n          case GX_VA_CLR1: col1=type; ncols+=(col1 != GX_NONE); break;\r\n\r\n          case GX_VA_TEX0: tex0=type; ntexs+=(tex0 != GX_NONE); break;\r\n          case GX_VA_TEX1: tex1=type; ntexs+=(tex1 != GX_NONE); break;\r\n          case GX_VA_TEX2: tex2=type; ntexs+=(tex2 != GX_NONE); break;\r\n          case GX_VA_TEX3: tex3=type; ntexs+=(tex3 != GX_NONE); break;\r\n          case GX_VA_TEX4: tex4=type; ntexs+=(tex4 != GX_NONE); break;\r\n          case GX_VA_TEX5: tex5=type; ntexs+=(tex5 != GX_NONE); break;\r\n          case GX_VA_TEX6: tex6=type; ntexs+=(tex6 != GX_NONE); break;\r\n          case GX_VA_TEX7: tex7=type; ntexs+=(tex7 != GX_NONE); break;\r\n          default: break;\r\n        }\r\n\t}\r\n\r\n\tva_end( vl );\r\n\r\n\t// Write out the attributes.\r\n    _CPCmd( CP_VCD_LO_ID, CP_VCD_REG_LO_PS( pnMtxIdx, txMtxIdxMask, posn, norm, col0, col1 ));\r\n\r\n    _CPCmd( CP_VCD_HI_ID, CP_VCD_REG_HI( tex0, tex1, tex2, tex3, tex4, tex5, tex6, tex7 ));\r\n\r\n    _XFCmd( XF_INVTXSPEC_ID, XF_INVTXSPEC( ncols, nnorms, ntexs ));\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid LoadPosMtxImm( const f32 mtx[3][4],\r\n\t\t\t\t\tu32 id )\r\n{\r\n    _XFCmdHdr(__PosMtxToXFMem(id), (u8)(3*4));\r\n    \r\n    _f32(mtx[0][0]);\r\n    _f32(mtx[0][1]);\r\n    _f32(mtx[0][2]);\r\n    _f32(mtx[0][3]);\r\n        \r\n    _f32(mtx[1][0]);\r\n    _f32(mtx[1][1]);\r\n    _f32(mtx[1][2]);\r\n    _f32(mtx[1][3]);\r\n        \r\n    _f32(mtx[2][0]);\r\n    _f32(mtx[2][1]);\r\n    _f32(mtx[2][2]);\r\n    _f32(mtx[2][3]);\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid LoadNrmMtxImm ( const f32 mtx[3][4],\r\n\t\t\t\t\t u32 id )\r\n{\r\n    _XFCmdHdr(__NrmMtxToXFMem(id), (u8)(3*3));\r\n\r\n    _f32(mtx[0][0]);\r\n    _f32(mtx[0][1]);\r\n    _f32(mtx[0][2]);\r\n        \r\n    _f32(mtx[1][0]);\r\n    _f32(mtx[1][1]);\r\n    _f32(mtx[1][2]);\r\n        \r\n    _f32(mtx[2][0]);\r\n    _f32(mtx[2][1]);\r\n    _f32(mtx[2][2]);\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid LoadTexMtxImm( const f32 mtx[3][4],\r\n\t\t\t\t\tu32 id,\r\n\t\t\t\t\tGXTexMtxType type )\r\n{\r\n    u16     addr;\r\n    u8      count;\r\n\r\n    if (id >= GX_PTTEXMTX0) \r\n    {\r\n#ifndef __PLAT_WN32__\r\n        ASSERTMSG(type == GX_MTX3x4, \"GDLoadTexMtxImm: invalid matrix type\");\r\n#endif\t\t// __PLAT_WN32__\r\n        addr  = __DTTMtxToXFMem(id);\r\n        count = (u8)(3*4);\r\n    } else {\r\n        addr  = __TexMtxToXFMem(id);\r\n        count = (u8)((type == GX_MTX2x4) ? (2*4) : (3*4));\r\n    }\r\n\r\n    _XFCmdHdr(addr, count);\r\n\r\n    _f32(mtx[0][0]);\r\n    _f32(mtx[0][1]);\r\n    _f32(mtx[0][2]);\r\n    _f32(mtx[0][3]);\r\n        \r\n    _f32(mtx[1][0]);\r\n    _f32(mtx[1][1]);\r\n    _f32(mtx[1][2]);\r\n    _f32(mtx[1][3]);\r\n               \r\n    if (type == GX_MTX3x4) \r\n    {\r\n        _f32(mtx[2][0]);\r\n        _f32(mtx[2][1]);\r\n        _f32(mtx[2][2]);\r\n        _f32(mtx[2][3]);\r\n    }\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetAlphaCompare( GXCompare\tcomp0,\r\n\t\t\t\t\t   u8\t\t\tref0,\r\n\t\t\t\t\t   GXAlphaOp\top,\r\n\t\t\t\t\t   GXCompare\tcomp1,\r\n\t\t\t\t\t   u8\t\t\tref1 )\r\n{\r\n    _BPCmd( TEV_ALPHAFUNC( ref0, ref1, comp0, comp1, op, TEV_ALPHAFUNC_ID ));\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetCurrMtxPosTex03( u32 pn,\r\n\t\t\t\t\t\t u32 t0,\r\n\t\t\t\t\t\t u32 t1,\r\n\t\t\t\t\t\t u32 t2,\r\n\t\t\t\t\t\t u32 t3 )\r\n{\r\n\tu32 regA;\r\n\r\n    regA = MATIDX_REG_A(pn, t0, t1, t2, t3);\r\n\r\n\t_CPCmd( CP_MATINDEX_A, regA ); // W1\r\n\r\n\t_XFCmdHdr( XF_MATINDEX_A, 1 );\r\n\t_u32( regA ); // W1\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetCurrMtxTex47( u32 t4,\r\n\t\t\t\t\t  u32 t5,\r\n\t\t\t\t\t  u32 t6,\r\n\t\t\t\t\t  u32 t7 )\r\n{\r\n    u32 regB;\r\n\r\n    regB = MATIDX_REG_B(t4, t5, t6, t7);\r\n\r\n    _CPCmd( CP_MATINDEX_B, regB ); // W2\r\n\r\n    _XFCmdHdr( XF_MATINDEX_B, 1 );\r\n    _u32( regB ); // W2\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetProjection( const\t\t\t\tf32 mtx[4][4],\r\n\t\t\t\t\tGXProjectionType\ttype )\r\n{\r\n//    u32 c;\r\n//\r\n//    c = ( type == GX_ORTHOGRAPHIC ) ? 3u : 2u;\r\n//\r\n//    GDWriteXFCmdHdr( XF_PROJECTION_ID, 7 );\r\n//    GDWrite_f32( mtx[0][0] );\r\n//    GDWrite_f32( mtx[0][c] );\r\n//    GDWrite_f32( mtx[1][1] );\r\n//    GDWrite_f32( mtx[1][c] );\r\n//    GDWrite_f32( mtx[2][2] );\r\n//    GDWrite_f32( mtx[2][3] );\r\n//    GDWrite_u32( type );\r\n\r\n#ifndef __PLAT_WN32__\r\n\tGXSetProjection( mtx, type );\r\n#endif\t\t// __PLAT_WN32__\r\n//    u32 c;\r\n//\r\n//    c = ( type == GX_ORTHOGRAPHIC ) ? 3u : 2u;\r\n//\r\n//    _XFCmdHdr( XF_PROJECTION_ID, 7 );\r\n//    _f32( mtx[0][0] );\r\n//    _f32( mtx[0][c] );\r\n//    _f32( mtx[1][1] );\r\n//    _f32( mtx[1][c] );\r\n//    _f32( mtx[2][2] );\r\n//    _f32( mtx[2][3] );\r\n//    _u32( type );\r\n//\r\n//\tg_projection[0] = mtx[0][0];\r\n//\tg_projection[1] = mtx[0][c];\r\n//\tg_projection[2] = mtx[1][1];\r\n//\tg_projection[3] = mtx[1][c];\r\n//\tg_projection[4] = mtx[2][2];\r\n//\tg_projection[5] = mtx[2][3];\r\n//\t*((u32 *)&g_projection[6]) = type;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#define TEV_KSEL_MASK_SWAPMODETABLE \\\r\n    (( 0x000003 << TEV_KSEL_XRB_SHIFT ) | \\\r\n     ( 0x000003 << TEV_KSEL_XGA_SHIFT ))\r\n\r\nvoid SetTevSwapModeTable( GXTevSwapSel    table,\r\n\t\t\t\t\t\t  GXTevColorChan  red,\r\n\t\t\t\t\t\t  GXTevColorChan  green,\r\n\t\t\t\t\t\t  GXTevColorChan  blue,\r\n\t\t\t\t\t\t  GXTevColorChan  alpha )\r\n{\r\n    // Mask to avoid touching the konstant-color selects\r\n    _BPCmd( SS_MASK( TEV_KSEL_MASK_SWAPMODETABLE ) );\r\n    _BPCmd( TEV_KSEL( red, green, 0, 0, 0, 0, TEV_KSEL_0_ID + (table * 2) ));\r\n    _BPCmd( SS_MASK( TEV_KSEL_MASK_SWAPMODETABLE ) );\r\n    _BPCmd( TEV_KSEL( blue, alpha, 0, 0, 0, 0, TEV_KSEL_0_ID + (table * 2) + 1 ));\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetScissorBoxOffset( s32\tx_off,\r\n\t\t\t\t\t\t  s32\ty_off )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetScissorBoxOffset( x_off, y_off );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetScissor( u32\tleft,\r\n\t\t\t\t u32\ttop,\r\n\t\t\t\t u32\twd,\r\n\t\t\t\t u32\tht )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetScissor( left, top, wd, ht );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetDispCopyGamma( GXGamma gamma )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetDispCopyGamma( gamma );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n//typedef void (*GXBreakPtCallback)(void);\r\nGXBreakPtCallback SetBreakPtCallback( GXBreakPtCallback cb )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\treturn GXSetBreakPtCallback( cb );\r\n#else\r\n\treturn 0;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Flush( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXFlush();\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid GetFifoPtrs( GXFifoObj*  fifo,\r\n\t\t\t\t  void**      readPtr,\r\n\t\t\t\t  void**      writePtr )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXGetFifoPtrs( fifo, readPtr, writePtr );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nGXFifoObj* GetCPUFifo( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\treturn GXGetCPUFifo();\r\n#else\r\n\treturn 0;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nGXFifoObj* GetGPFifo( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\treturn GXGetGPFifo();\r\n#else\r\n\treturn 0;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid EnableBreakPt( void* breakPtr )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXEnableBreakPt( breakPtr );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid DisableBreakPt( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXDisableBreakPt();\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetGPMetric( GXPerf0\tperf0,\r\n\t\t\t\t  GXPerf1\tperf1 )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetGPMetric( perf0, perf1 );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid ClearGPMetric( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXClearGPMetric();\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid ReadGPMetric( u32 *\tcnt0,\r\n\t\t\t\t   u32 *\tcnt1 )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXReadGPMetric( cnt0, cnt1 );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetDrawSync( u16 token )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetDrawSync( token );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nu16 ReadDrawSync( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\treturn GXReadDrawSync();\r\n#else\r\n\treturn 0;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetCopyFilter( GXBool\t\taa,\r\n\t\t\t\t\tconst u8\tsample_pattern[12][2],\r\n\t\t\t\t\tGXBool\t\tvf,\r\n\t\t\t\t\tconst u8\tvfilter[7] )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetCopyFilter( aa, sample_pattern, vf, vfilter );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid CopyDisp( void *\tdest,\r\n\t\t\t   GXBool\tclear )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXCopyDisp( dest, clear );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetCopyClear( GXColor\tclear_clr,\r\n\t\t\t\t   u32\t\tclear_z )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetCopyClear( clear_clr, clear_z );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid PokeZ( u16 x,\r\n\t\t\tu16 y,\r\n\t\t\tu32 z )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXPokeZ( x, y, z );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid PeekZ( u16 x,\r\n\t\t\tu16 y,\r\n\t\t\tu32* z )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXPeekZ( x, y, z );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid PokeARGB( u16 x,\r\n\t\t\t   u16 y,\r\n\t\t\t   u32 color )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXPokeARGB( x, y, color );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid PeekARGB( u16 x,\r\n\t\t\t   u16 y,\r\n\t\t\t   u32* color )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXPeekARGB( x, y, color );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetClipMode( GXClipMode mode )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetClipMode( mode );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetZCompLoc( GXBool before_tex )\r\n{\r\n//\tstb x61\r\n\r\n//#ifndef __PLAT_WN32__\r\n//\tGXSetZCompLoc( before_tex );\r\n//#else\r\n    _BPCmd( ( PE_CONTROL_ID << 24 ) | GX_PF_RGB8_Z24 | ( before_tex << 6 ) );\r\n//#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetPixelFmt( GXPixelFmt\tpix_fmt,\r\n\t\t\t\t  GXZFmt16\t\tz_fmt )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetPixelFmt( pix_fmt, z_fmt );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nGXFifoObj * Init( void *\tbase,\r\n\t\t\t\t  u32\t\tsize )\r\n{\r\n\tbegin();\r\n#ifndef __PLAT_WN32__\r\n\treturn GXInit( base, size );\r\n#else\r\n\treturn 0;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid AdjustForOverscan( const GXRenderModeObj *\trmin,\r\n\t\t\t\t\t\tGXRenderModeObj *\t\trmout,\r\n\t\t\t\t\t\tu16\t\t\t\t\t\thor,\r\n\t\t\t\t\t\tu16\t\t\t\t\t\tver )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXAdjustForOverscan( rmin, rmout, hor, ver );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetViewport( f32 left,\r\n\t\t\t\t  f32 top,\r\n\t\t\t\t  f32 wd,\r\n\t\t\t\t  f32 ht,\r\n\t\t\t\t  f32 nearz,\r\n\t\t\t\t  f32 farz )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetViewport( left, top, wd, ht, nearz, farz );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetDispCopySrc( u16 left,\r\n\t\t\t\t\t u16 top,\r\n\t\t\t\t\t u16 wd,\r\n\t\t\t\t\t u16 ht )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetDispCopySrc( left, top, wd, ht );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetDispCopyDst( u16 wd,\r\n\t\t\t\t\t u16 ht )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetDispCopyDst( wd, ht );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nu32 SetDispCopyYScale( f32 vscale )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\treturn GXSetDispCopyYScale( vscale );\r\n#else\r\n\treturn 0;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetVtxAttrFmt( GXVtxFmt\tvtxfmt,\r\n\t\t\t\t\tGXAttr\t\tattr,\r\n\t\t\t\t\tGXCompCnt\tcnt,\r\n\t\t\t\t\tGXCompType\ttype,\r\n\t\t\t\t\tu8\t\t\tfrac )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetVtxAttrFmt( vtxfmt, attr, cnt, type, frac );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetViewportJitter( f32 left,\r\n\t\t\t\t\t\tf32 top,\r\n\t\t\t\t\t\tf32 wd,\r\n\t\t\t\t\t\tf32 ht,\r\n\t\t\t\t\t\tf32 nearz,\r\n\t\t\t\t\t\tf32 farz,\r\n\t\t\t\t\t\tu32 field )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetViewportJitter( left,  top, wd, ht, nearz, farz, field );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InvalidateVtxCache( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInvalidateVtxCache();\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InvalidateTexAll( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInvalidateTexAll();\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nGXDrawSyncCallback SetDrawSyncCallback( GXDrawSyncCallback cb )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\treturn GXSetDrawSyncCallback( cb );\r\n#else\r\n\treturn 0;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid DrawDone( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXDrawDone();\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\nvoid AbortFrame( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXAbortFrame();\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetDrawDone( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetDrawDone();\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid WaitDrawDone( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXWaitDrawDone();\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nGXDrawDoneCallback SetDrawDoneCallback( GXDrawDoneCallback cb )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\treturn GXSetDrawDoneCallback( cb );\r\n#else\r\n\treturn 0;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid ReadXfRasMetric( u32 *          xf_wait_in,\r\n\t\t\t\t\t  u32 *          xf_wait_out,\r\n\t\t\t\t\t  u32 *          ras_busy,\r\n\t\t\t\t\t  u32 *          clocks )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXReadXfRasMetric( xf_wait_in, xf_wait_out, ras_busy, clocks );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid GetGPStatus( GXBool * overhi,\r\n\t\t\t\t  GXBool * underlow,\r\n\t\t\t\t  GXBool * readIdle,\r\n\t\t\t\t  GXBool * cmdIdle,\r\n\t\t\t\t  GXBool * brkpt )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXGetGPStatus( overhi, underlow, readIdle, cmdIdle, brkpt);\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n    \r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid GetFifoStatus( GXFifoObj *  fifo,\r\n\t\t\t\t\tGXBool *     overhi,\r\n\t\t\t\t\tGXBool *     underlow,\r\n\t\t\t\t\tu32 *        fifoCount,\r\n\t\t\t\t\tGXBool *     cpu_write,\r\n\t\t\t\t\tGXBool *     gp_read,\r\n\t\t\t\t\tGXBool *     fifowrap )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXGetFifoStatus( fifo, overhi, underlow, fifoCount, cpu_write, gp_read, fifowrap );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid * GetFifoBase( const GXFifoObj * fifo )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\treturn GXGetFifoBase( fifo );\r\n#else\r\n\treturn 0;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nu32 GetFifoSize( const GXFifoObj * fifo )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\treturn GXGetFifoSize( fifo );\r\n#else\r\n\treturn 0;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid GetFifoLimits( const GXFifoObj *\tfifo,\r\n\t\t\t\t\tu32 *\t\t\t\thi,\r\n\t\t\t\t\tu32 *\t\t\t\tlo )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXGetFifoLimits( fifo, hi, lo);\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nu32 GetOverflowCount( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\treturn GXGetOverflowCount();\r\n#else\r\n\treturn 0;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nu32 ResetOverflowCount( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\treturn GXResetOverflowCount();\r\n#else\r\n\treturn 0;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid EnableHang( void )\r\n{\r\n\t// Set up RAS Ready counter\r\n\t_u8( GX_LOAD_BP_REG );\r\n\t_u32( 0x2402c004 ); // ... 101 10000 00000 00100\r\n\r\n\t// Set up SU Ready counter\r\n\t_u8( GX_LOAD_BP_REG );\r\n\t_u32( 0x23000020 ); // ... 100 000\r\n\r\n\t// Set up XF TOP and BOT busy counters\r\n\t_u8( GX_LOAD_XF_REG );\r\n\t_u16( 0x0000 );\r\n\t_u16( 0x1006 );\r\n\t_u32( 0x00084400 ); // 10000 10001 00000 00000\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid DisableHang( void )\r\n{\r\n\t// Disable RAS counters\r\n\t_u8( GX_LOAD_BP_REG );\r\n\t_u32( 0x24000000 );\r\n\r\n\t// Disable SU counters\r\n\t_u8( GX_LOAD_BP_REG );\r\n\t_u32( 0x23000000 );\r\n\r\n\t// Disable XF counters\r\n\t_u8( GX_LOAD_XF_REG );\r\n\t_u16( 0x0000 );\r\n\t_u16( 0x1006 );\r\n\t_u32( 0x00000000 );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid ResolveDLTexAddr( NxNgc::sTextureDL *\t\t\tp_dl,\r\n\t\t\t\t\t   NxNgc::sMaterialPassHeader *\tp_pass,\r\n\t\t\t\t\t   int\t\t\t\t\t\t\tnum_passes )\r\n{\r\n//\t\tGX::begin( p_dl->mp_dl, p_dl->m_dl_size );\r\n//\t\tmulti_mesh( p_mat, p_pass, true, true );\r\n//\t\tp_dl->m_dl_size = GX::end();\r\n\r\n#ifndef __PLAT_WN32__\r\n\tfor ( int layer = 0; layer < num_passes; layer++ )\r\n\t{\r\n\t\t// Offset  0 = mode0  :: wrap, aniso, clamp, lod, filt\r\n\t\t// Offset  5 = mode1  :: lod values\r\n\t\t// Offset 10 = image0 :: width, height, format\r\n\t\t// Offset 15 = image1 :: cache slot\r\n\t\t// Offset 20 = image2 :: cache slot \r\n\t\t// Offset 25 = image3 :: RAM Pointer\r\n\t\t// Offset 30 = SU_TS0 :: Scale (texel only)\r\n\t\t// Offset 35 = SU_TS1 :: Scale (texel only)\r\n\r\n\t\tif ( p_pass[layer].m_texture.p_data )\r\n\t\t{\r\n\t\t\tunsigned char * p8;\r\n\t\t\tuint32 address;\r\n\t\t\tuint8 levels = p_pass[layer].m_texture.p_data->Levels;\r\n\t\t\tu8 min = 0;\r\n\t\t\tu8 max = (u8)( ( levels > 1 ? levels - 1.0f : 0.0f ) * 16.0f ); \r\n\t\t\tif ( p_pass[layer].m_texture.p_data->pTexelData && ( p_dl->m_tex_offset[layer] != -1 ) )\r\n\t\t\t{\r\n\t\t\t\t// Resolve address\r\n\t\t\t\tp8 = &((unsigned char *)p_dl->mp_dl)[p_dl->m_tex_offset[layer]+25];\r\n\t\t\t\taddress = OSCachedToPhysical( p_pass[layer].m_texture.p_data->pTexelData ) >> 5;\r\n\t\t\t\tp8[2] = (uint8)( ( address >> 16 ) & 0xff );\r\n\t\t\t\tp8[3] = (uint8)( ( address >> 8  ) & 0xff );\r\n\t\t\t\tp8[4] = (uint8)( ( address >> 0  ) & 0xff );\r\n\t\t\t\tDCFlushRange ( &p8[2], 3 );\r\n\t\t\t\t// Resolve MIP\r\n\t\t\t\tp8 = &((unsigned char *)p_dl->mp_dl)[p_dl->m_tex_offset[layer]+5];\r\n\t\t\t\tp8[3] = max;\r\n\t\t\t\tp8[4] = min;\r\n\t\t\t\tDCFlushRange ( &p8[2], 3 );\r\n\t\t\t\t// Resolve Width & Height\r\n\t\t\t\tp8 = &((unsigned char *)p_dl->mp_dl)[p_dl->m_tex_offset[layer]+10];\r\n\t\t\t\tint width = p_pass[layer].m_texture.p_data->ActualWidth - 1;\r\n\t\t\t\tint height = p_pass[layer].m_texture.p_data->ActualHeight - 1;\r\n\t\t\t\tuint32 whf = ( width << 0 ) | ( height << 10 ) | ( GX_TF_CMPR << 20 );\r\n\t\t\t\tp8[2] = (uint8)( ( whf >> 16 ) & 0xff );\r\n\t\t\t\tp8[3] = (uint8)( ( whf >> 8  ) & 0xff );\r\n\t\t\t\tp8[4] = (uint8)( ( whf >> 0  ) & 0xff );\r\n\t\t\t\tDCFlushRange ( &p8[2], 3 );\r\n\t\t\t\tp8 = &((unsigned char *)p_dl->mp_dl)[p_dl->m_tex_offset[layer]+30];\r\n\t\t\t\tp8[3] = (uint8)( ( width >> 8  ) & 0xff );\r\n\t\t\t\tp8[4] = (uint8)( ( width >> 0  ) & 0xff );\r\n\t\t\t\tDCFlushRange ( &p8[3], 2 );\r\n\t\t\t\tp8 = &((unsigned char *)p_dl->mp_dl)[p_dl->m_tex_offset[layer]+35];\r\n\t\t\t\tp8[3] = (uint8)( ( height >> 8  ) & 0xff );\r\n\t\t\t\tp8[4] = (uint8)( ( height >> 0  ) & 0xff );\r\n\t\t\t\tDCFlushRange ( &p8[3], 2 );\r\n\t\t\t}\r\n\t\t\tif ( p_pass[layer].m_texture.p_data->pAlphaData && ( p_dl->m_alpha_offset[layer] != -1 ) )\r\n\t\t\t{\r\n\t\t\t\t// Resolve address\r\n\t\t\t\tp8 = &((unsigned char *)p_dl->mp_dl)[p_dl->m_alpha_offset[layer]+25];\r\n\t\t\t\taddress = OSCachedToPhysical( p_pass[layer].m_texture.p_data->pAlphaData ) >> 5;\r\n\t\t\t\tp8[2] = (uint8)( ( address >> 16 ) & 0xff );\r\n\t\t\t\tp8[3] = (uint8)( ( address >> 8  ) & 0xff );\r\n\t\t\t\tp8[4] = (uint8)( ( address >> 0  ) & 0xff );\r\n\t\t\t\tDCFlushRange ( &p8[2], 3 );\r\n\t\t\t\t// Resolve MIP\r\n\t\t\t\tp8 = &((unsigned char *)p_dl->mp_dl)[p_dl->m_alpha_offset[layer]+5];\r\n\t\t\t\tp8[3] = max;\r\n\t\t\t\tp8[4] = min;\r\n\t\t\t\tDCFlushRange ( &p8[3], 2 );\r\n\t\t\t\t// Resolve Width & Height\r\n\t\t\t\tp8 = &((unsigned char *)p_dl->mp_dl)[p_dl->m_tex_offset[layer]+10];\r\n\t\t\t\tint width = p_pass[layer].m_texture.p_data->ActualWidth - 1;\r\n\t\t\t\tint height = p_pass[layer].m_texture.p_data->ActualHeight - 1;\r\n\t\t\t\tuint32 whf = ( width << 0 ) | ( height << 10 ) | ( GX_TF_CMPR << 20 );\r\n\t\t\t\tp8[2] = (uint8)( ( whf >> 16 ) & 0xff );\r\n\t\t\t\tp8[3] = (uint8)( ( whf >> 8  ) & 0xff );\r\n\t\t\t\tp8[4] = (uint8)( ( whf >> 0  ) & 0xff );\r\n\t\t\t\tDCFlushRange ( &p8[2], 3 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tDCFlushRange ( p_dl->mp_dl, p_dl->m_dl_size );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid ChangeMaterialColor( unsigned char *\t\t\t\tp_dl,\r\n\t\t\t\t\t\t  unsigned int\t\t\t\t\tsize,\r\n\t\t\t\t\t\t  GXColor\t\t\t\t\t\tcolor,\r\n\t\t\t\t\t\t  int\t\t\t\t\t\t\tpass )\r\n{\r\n//\tGX::begin( p_dl->mp_dl, p_dl->m_dl_size );\r\n//\tmulti_mesh( p_mat, p_pass, true, true );\r\n//\tp_dl->m_dl_size = GX::end();\r\n\r\n#ifndef __PLAT_WN32__\r\n\tunsigned char * p8 = p_dl;\r\n\tunsigned char * p_end = &p8[size];\r\n\r\n\tbool quit = false;\r\n\r\n\twhile ( !quit )\r\n\t{\r\n\t\tswitch ( p8[0] )\r\n\t\t{\r\n\t\t\tcase GX_LOAD_BP_REG:\r\n\t\t\t\t{\r\n\t\t\t\t\tuint8 reg0 = TEV_REGISTERL_0_ID + ( pass * 2 );\r\n\t\t\t\t\tuint8 reg1 = TEV_REGISTERH_0_ID + ( pass * 2 );\r\n\r\n\t\t\t\t\tif ( ( p8[(0*5)+1] == reg0 ) && ( p8[(1*5)+1] == reg1 ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tu32 regRA, regBG;\r\n\r\n\t\t\t\t\t\tregRA = TEV_REGISTERL( color.r, color.a, TEV_KONSTANT_REG,\r\n\t\t\t\t\t\t\t\t\t\t\t   TEV_REGISTERL_0_ID + pass * 2 );\r\n\t\t\t\t\t\tregBG = TEV_REGISTERH( color.b, color.g, TEV_KONSTANT_REG, \r\n\t\t\t\t\t\t\t\t\t\t\t   TEV_REGISTERH_0_ID + pass * 2 );\r\n\t\t\t\t\t\tp8[(0*5)+1] = ( regRA >> 24 );\r\n\t\t\t\t\t\tp8[(0*5)+2] = ( regRA >> 16 );\r\n\t\t\t\t\t\tp8[(0*5)+3] = ( regRA >>  8 );\r\n\t\t\t\t\t\tp8[(0*5)+4] = ( regRA >>  0 );\r\n\r\n\t\t\t\t\t\tp8[(1*5)+1] = ( regBG >> 24 );\r\n\t\t\t\t\t\tp8[(1*5)+2] = ( regBG >> 16 );\r\n\t\t\t\t\t\tp8[(1*5)+3] = ( regBG >>  8 );\r\n\t\t\t\t\t\tp8[(1*5)+4] = ( regBG >>  0 );\r\n\t\t\t\t\t\tDCFlushRange ( p8, 10 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tp8 += 5;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase GX_LOAD_CP_REG:\r\n\t\t\t\tp8 += 6;\r\n\t\t\t\tbreak;\r\n\t\t\tcase GX_LOAD_XF_REG:\r\n\t\t\t\tp8 += 1 + 2 + 2 + 4 + ( 4 * ( ( p8[1] << 8 ) | p8[2] ) );\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tquit = true;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tif ( p8 >= p_end ) quit = true;\r\n\t}\r\n\tDCFlushRange ( p_dl, size );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetTexCopySrc( u16 left,\r\n\t\t\t\t\tu16 top,\r\n\t\t\t\t\tu16 wd,\r\n\t\t\t\t\tu16 ht )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetTexCopySrc( left, top, wd, ht );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetTexCopyDst( u16 wd,\r\n\t\t\t\t\tu16 ht,\r\n\t\t\t\t\tGXTexFmt fmt,\r\n\t\t\t\t\tGXBool mipmap )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetTexCopyDst( wd, ht, fmt, mipmap );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid CopyTex( void *\tdest,\r\n\t\t\t  GXBool\tclear )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXCopyTex( dest, clear );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid PixModeSync( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXPixModeSync();\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid PokeAlphaUpdate( GXBool update_enable )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXPokeAlphaUpdate( update_enable );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid PokeColorUpdate( GXBool update_enable )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXPokeColorUpdate( update_enable );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid GetProjectionv( f32 * p )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXGetProjectionv( p );\r\n#endif\t\t// __PLAT_WN32__\r\n//\tp[0] = g_projection[0];\r\n//\tp[1] = g_projection[1];\r\n//\tp[2] = g_projection[2];\r\n//\tp[3] = g_projection[3];\r\n//\tp[4] = g_projection[4];\r\n//\tp[5] = g_projection[5];\r\n//\tp[6] = g_projection[6];\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetProjectionv( const f32 * ptr )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXSetProjectionv( ptr );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid GetViewportv( f32 * viewport )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXGetViewportv( viewport );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid GetScissor( u32 *    left,\r\n\t\t\t\t u32 *    top,\r\n\t\t\t\t u32 *    width,\r\n\t\t\t\t u32 *    height )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXGetScissor( left, top, width, height );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid Project( f32\t\t\tx,          // model coordinates\r\n\t\t\t  f32\t\t\ty,\r\n\t\t\t  f32\t\t\tz,\r\n\t\t\t  const f32\t\tmtx[3][4],  // model-view matrix\r\n\t\t\t  const f32 *\tpm,         // projection matrix, as returned by GXGetProjectionv\r\n\t\t\t  const f32 *\tvp,         // viewport, as returned by GXGetViewportv\r\n\t\t\t  f32 *\t\t\tsx,         // screen coordinates\r\n\t\t\t  f32 *\t\t\tsy,\r\n\t\t\t  f32 *\t\t\tsz )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXProject( x, y, z, mtx, pm, vp, sx, sy, sz );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid SetArray( GXAttr \t\tattr,\r\n\t\t\t   const void *\tbase_ptr,\r\n\t\t\t   u8 \t\t\tstride )\r\n{\r\n#ifndef __PLAT_WN32__\r\n//\tGDSetArray( attr, base_ptr, stride );\r\n\r\n    s32 cpAttr;\r\n\r\n    cpAttr = (attr == GX_VA_NBT) ? (GX_VA_NRM - GX_VA_POS) : (attr - GX_VA_POS);\r\n    \r\n    _CPCmd( (u8) (CP_ARRAY_BASE_ID + cpAttr),\r\n                  CP_ARRAY_BASE_REG( OSCachedToPhysical( base_ptr ) ));\r\n\r\n    _CPCmd( (u8) (CP_ARRAY_STRIDE_ID + cpAttr),\r\n                  CP_ARRAY_STRIDE_REG( stride ));\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitLightAttn( GXLightObj*   lt_obj,\r\n\t\t\t\t\tf32           a0,\r\n\t\t\t\t\tf32           a1,\r\n\t\t\t\t\tf32           a2,\r\n\t\t\t\t\tf32           k0,\r\n\t\t\t\t\tf32           k1,\r\n\t\t\t\t\tf32           k2 )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitLightAttn( lt_obj, a0, a1, a2, k0, k1, k2 );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitLightAttnA( GXLightObj *\tlt_obj,\r\n\t\t\t\t\t f32\t\t\ta0,\r\n\t\t\t\t\t f32\t\t\ta1,\r\n\t\t\t\t\t f32\t\t\ta2 )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitLightAttnA( lt_obj, a0, a1, a2);\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitLightAttnK( GXLightObj *\tlt_obj,\r\n\t\t\t\t\t f32\t\t\tk0,\r\n\t\t\t\t\t f32\t\t\tk1,\r\n\t\t\t\t\t f32\t\t\tk2 )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitLightAttnK( lt_obj, k0, k1, k2 );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitLightSpot( GXLightObj *\tlt_obj,\r\n\t\t\t\t\tf32\t\t\t\tcutoff,\r\n\t\t\t\t\tGXSpotFn\t\tspot_func )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitLightSpot( lt_obj, cutoff, spot_func );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitLightDistAttn( GXLightObj *\tlt_obj,\r\n\t\t\t\t\t\tf32\t\t\t\tref_distance,\r\n\t\t\t\t\t\tf32\t\t\t\tref_brightness,\r\n\t\t\t\t\t\tGXDistAttnFn\tdist_func )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitLightDistAttn( lt_obj, ref_distance, ref_brightness, dist_func );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitLightPos( GXLightObj *\tlt_obj,\r\n\t\t\t\t   f32\t\t\tx,\r\n\t\t\t\t   f32\t\t\ty,\r\n\t\t\t\t   f32\t\t\tz )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitLightPos( lt_obj, x, y, z );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitLightColor( GXLightObj *\tlt_obj,\r\n\t\t\t\t\t GXColor\t\tcolor )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitLightColor( lt_obj, color );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid LoadLightObjImm( const GXLightObj *\tlt_obj,\r\n\t\t\t\t\t  GXLightID\t\t\t\tlight )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXLoadLightObjImm( lt_obj, light );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid LoadLightObjIndx( u32\t\t\tlt_obj_indx,\r\n\t\t\t\t\t   GXLightID\tlight )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXLoadLightObjIndx( lt_obj_indx, light );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitLightDir( GXLightObj *\tlt_obj,\r\n\t\t\t\t   f32\t\t\tnx,\r\n\t\t\t\t   f32\t\t\tny,\r\n\t\t\t\t   f32\t\t\tnz )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitLightDir( lt_obj, nx, ny, nz );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitSpecularDir( GXLightObj *\tlt_obj,\r\n\t\t\t\t\t  f32\t\t\tnx,\r\n\t\t\t\t\t  f32\t\t\tny,\r\n\t\t\t\t\t  f32\t\t\tnz )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitSpecularDir( lt_obj, nx, ny, nz );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitSpecularDirHA( GXLightObj *\tlt_obj,\r\n\t\t\t\t\t\tf32\t\t\t\tnx,\r\n\t\t\t\t\t\tf32\t\t\t\tny,\r\n\t\t\t\t\t\tf32\t\t\t\tnz,\r\n\t\t\t\t\t\tf32\t\t\t\thx,\r\n\t\t\t\t\t\tf32\t\t\t\thy,\r\n\t\t\t\t\t\tf32\t\t\t\thz )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitSpecularDirHA( lt_obj, nx, ny, nz, hx, hy, hz );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitLightPosv( GXLightObj *\tlt_obj,\r\n\t\t\t\t\tVec *\t\t\tp )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitLightPos( lt_obj, p->x, p->y, p->z );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitLightDirv( GXLightObj *\tlt_obj,\r\n\t\t\t\t\tVec *\t\t\tn )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitLightDir( lt_obj, n->x, n->y, n->z );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitSpecularDirv( GXLightObj *\tlt_obj,\r\n\t\t\t\t\t   Vec *\t\tn )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitSpecularDir( lt_obj, n->x, n->y, n->z );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitSpecularDirHAv( GXLightObj *\tlt_obj,\r\n\t\t\t\t\t\t Vec *\t\t\tn,\r\n\t\t\t\t\t\t Vec *\t\t\th )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitSpecularDirHA( lt_obj, n->x, n->y, n->z, h->x, h->y, h->z );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid InitLightShininess( GXLightObj *\tlt_obj,\r\n\t\t\t\t\t\t float\t\t\tshininess )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXInitLightAttn( lt_obj, 0.0F, 0.0F, 1.0F, shininess / 2.0F, 0.0F, 1.0F - shininess / 2.0F );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid CallDisplayList( const void *\tlist,\r\n\t\t\t\t\t  u32\t\t\tnbytes )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\tGXCallDisplayList( list, nbytes );\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid ResetGX( void )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\t// Color definitions\r\n\t\r\n\t#define GX_DEFAULT_BG (GXColor){64, 64, 64, 255}\r\n\t#define BLACK (GXColor){0, 0, 0, 0}\r\n\t#define WHITE (GXColor){255, 255, 255, 255}\r\n\t\r\n\t//\r\n\t// Render Mode\r\n\t//\r\n\t// (set 'rmode' based upon VIGetTvFormat(); code not shown)\r\n\t\r\n\t//\r\n\t// Geometry and Vertex\r\n\t//\r\n\tGXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TEX2, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD3, GX_TG_MTX2x4, GX_TG_TEX3, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD4, GX_TG_MTX2x4, GX_TG_TEX4, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD5, GX_TG_MTX2x4, GX_TG_TEX5, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD6, GX_TG_MTX2x4, GX_TG_TEX6, GX_IDENTITY);\r\n\tGXSetTexCoordGen(GX_TEXCOORD7, GX_TG_MTX2x4, GX_TG_TEX7, GX_IDENTITY);\r\n\tGXSetNumTexGens(1);\r\n\tGXClearVtxDesc();\r\n\tGXInvalidateVtxCache();\r\n\t\r\n\tGXSetLineWidth(6, GX_TO_ZERO);\r\n\tGXSetPointSize(6, GX_TO_ZERO);\r\n\tGXEnableTexOffsets( GX_TEXCOORD0, GX_DISABLE, GX_DISABLE );\r\n\tGXEnableTexOffsets( GX_TEXCOORD1, GX_DISABLE, GX_DISABLE );\r\n\tGXEnableTexOffsets( GX_TEXCOORD2, GX_DISABLE, GX_DISABLE );\r\n\tGXEnableTexOffsets( GX_TEXCOORD3, GX_DISABLE, GX_DISABLE );\r\n\tGXEnableTexOffsets( GX_TEXCOORD4, GX_DISABLE, GX_DISABLE );\r\n\tGXEnableTexOffsets( GX_TEXCOORD5, GX_DISABLE, GX_DISABLE );\r\n\tGXEnableTexOffsets( GX_TEXCOORD6, GX_DISABLE, GX_DISABLE );\r\n\tGXEnableTexOffsets( GX_TEXCOORD7, GX_DISABLE, GX_DISABLE );\r\n\t\r\n\t//\r\n\t// Transformation and Matrix\r\n\t//\r\n\t// (initialize 'identity_mtx' to identity; code not shown)\r\n\t\r\n\t// Note: projection matrix is not initialized!\r\n//\tGXLoadPosMtxImm(identity_mtx, GX_PNMTX0);\r\n//\tGXLoadNrmMtxImm(identity_mtx, GX_PNMTX0);\r\n\tGXSetCurrentMtx(GX_PNMTX0);\r\n//\tGXLoadTexMtxImm(identity_mtx, GX_IDENTITY, GX_MTX3x4);\r\n//\tGXLoadTexMtxImm(identity_mtx, GX_PTIDENTITY, GX_MTX3x4);\r\n//\tGXSetViewport(0.0F, // left\r\n//\t0.0F, // top\r\n//\t(float)rmode->fbWidth, // width\r\n//\t(float)rmode->xfbHeight, // height\r\n//\t0.0F, // nearz\r\n//\t1.0F); // farz\r\n\t\r\n\t//\r\n\t// Clipping and Culling\r\n\t//\r\n//\tGXSetCoPlanar(GX_DISABLE);\r\n\tGXSetCullMode(GX_CULL_BACK);\r\n\tGXSetClipMode(GX_CLIP_ENABLE);\r\n//\tGXSetScissor(0, 0, (u32)rmode->fbWidth, (u32)rmode->efbHeight);\r\n//\tGXSetScissorBoxOffset(0, 0);\r\n\t\r\n\t//\r\n\t// Lighting - pass vertex color through\r\n\t//\r\n\tGXSetNumChans(0); // no colors by default\r\n\t\r\n\tGXSetChanCtrl(\r\n\tGX_COLOR0A0,\r\n\tGX_DISABLE,\r\n\tGX_SRC_REG,\r\n\tGX_SRC_VTX,\r\n\tGX_LIGHT_NULL,\r\n\tGX_DF_NONE,\r\n\tGX_AF_NONE );\r\n\t\r\n\tGXSetChanAmbColor(GX_COLOR0A0, BLACK);\r\n\tGXSetChanMatColor(GX_COLOR0A0, WHITE);\r\n\t\r\n\tGXSetChanCtrl(\r\n\tGX_COLOR1A1,\r\n\tGX_DISABLE,\r\n\tGX_SRC_REG,\r\n\tGX_SRC_VTX,\r\n\tGX_LIGHT_NULL,\r\n\tGX_DF_NONE,\r\n\tGX_AF_NONE );\r\n\t\r\n\tGXSetChanAmbColor(GX_COLOR1A1, BLACK);\r\n\tGXSetChanMatColor(GX_COLOR1A1, WHITE);\r\n\t\r\n\t//\r\n\t// Texture\r\n\t//\r\n\tGXInvalidateTexAll();\r\n\t\r\n\t// Allocate 8 32k caches for RGBA texture mipmaps.\r\n\t// Equal size caches to support 32b RGBA textures.\r\n\t//\r\n\t// (code not shown)\r\n\t\r\n\t// Allocate color index caches in low bank of TMEM.\r\n\t// Each cache is 32kB.\r\n\t// Even and odd regions should be allocated on different address.\r\n\t//\r\n\t// (code not shown)\r\n\t\r\n\t// Allocate TLUTs, 16 256-entry TLUTs and 4 1K-entry TLUTs.\r\n\t// 256-entry TLUTs are 8kB, 1k-entry TLUTs are 32kB.\r\n\t//\r\n\t// (code not shown)\r\n\t\r\n\t//\r\n\t// Set texture region and tlut region Callbacks\r\n\t//\r\n//\tGXSetTexRegionCallback(__GXDefaultTexRegionCallback);\r\n//\tGXSetTlutRegionCallback(__GXDefaultTlutRegionCallback);\r\n//\t\r\n\t//\r\n\t// Texture Environment\r\n\t//\r\n\tGXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD2, GX_TEXMAP2, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD3, GX_TEXMAP3, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE4, GX_TEXCOORD4, GX_TEXMAP4, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE5, GX_TEXCOORD5, GX_TEXMAP5, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE6, GX_TEXCOORD6, GX_TEXMAP6, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE7, GX_TEXCOORD7, GX_TEXMAP7, GX_COLOR0A0);\r\n\tGXSetTevOrder(GX_TEVSTAGE8, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE9, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE10,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE11,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE12,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE13,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE14,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetTevOrder(GX_TEVSTAGE15,GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);\r\n\tGXSetNumTevStages(1);\r\n\tGXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);\r\n\tGXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);\r\n//\tGXSetZTexture(GX_ZT_DISABLE, GX_TF_Z8, 0);\r\n//\t\r\n\tfor ( int i = GX_TEVSTAGE0; i < GX_MAX_TEVSTAGE; i++) {\r\n\tGXSetTevKColorSel((GXTevStageID) i, GX_TEV_KCSEL_1_4 );\r\n\tGXSetTevKAlphaSel((GXTevStageID) i, GX_TEV_KASEL_1 );\r\n\tGXSetTevSwapMode ((GXTevStageID) i, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t}\r\n//\tGXSetTevSwapModeTable(GX_TEV_SWAP0,\r\n//\tGX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);\r\n//\tGXSetTevSwapModeTable(GX_TEV_SWAP1,\r\n//\tGX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA);\r\n//\tGXSetTevSwapModeTable(GX_TEV_SWAP2,\r\n//\tGX_CH_GREEN, GX_CH_GREEN, GX_CH_GREEN, GX_CH_ALPHA);\r\n//\tGXSetTevSwapModeTable(GX_TEV_SWAP3,\r\n//\tGX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA);\r\n//\t\r\n//\t// Indirect Textures.\r\n//\tfor (i = GX_TEVSTAGE0; i < GX_MAX_TEVSTAGE; i++) {\r\n//\tGXSetTevDirect((GXTevStageID) i);\r\n//\t}\r\n//\tGXSetNumIndStages(0);\r\n//\tGXSetIndTexCoordScale( GX_INDTEXSTAGE0, GX_ITS_1, GX_ITS_1 );\r\n//\tGXSetIndTexCoordScale( GX_INDTEXSTAGE1, GX_ITS_1, GX_ITS_1 );\r\n//\tGXSetIndTexCoordScale( GX_INDTEXSTAGE2, GX_ITS_1, GX_ITS_1 );\r\n//\tGXSetIndTexCoordScale( GX_INDTEXSTAGE3, GX_ITS_1, GX_ITS_1 );\r\n//\t\r\n\t//\r\n\t// Pixel Processing\r\n\t//\r\n\tGXSetFog(GX_FOG_NONE, 0.0F, 1.0F, 0.1F, 1.0F, BLACK);\r\n\tGXSetFogRangeAdj( GX_DISABLE, 0, 0 );\r\n\tGXSetBlendMode(GX_BM_NONE,\r\n\tGX_BL_SRCALPHA, // src factor\r\n\tGX_BL_INVSRCALPHA, // dst factor\r\n\tGX_LO_CLEAR);\r\n\tGXSetColorUpdate(GX_ENABLE);\r\n\tGXSetAlphaUpdate(GX_ENABLE);\r\n\tGXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);\r\n\tGXSetZCompLoc(GX_TRUE); // before texture\r\n\tGXSetDither(GX_ENABLE);\r\n\tGXSetDstAlpha(GX_DISABLE, 0);\r\n//\tGXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);\r\n//\tGXSetFieldMask( GX_ENABLE, GX_ENABLE );\r\n//\tGXSetFieldMode((GXBool)(rmode->field_rendering),\r\n//\t((rmode->viHeight == 2*rmode->xfbHeight) ?\r\n//\tGX_ENABLE : GX_DISABLE));\r\n//\t\r\n//\t//\r\n//\t// Frame buffer\r\n//\t//\r\n//\tGXSetCopyClear(GX_DEFAULT_BG, GX_MAX_Z24);\r\n//\tGXSetDispCopySrc(0, 0, rmode->fbWidth, rmode->efbHeight);\r\n//\tGXSetDispCopyDst(rmode->fbWidth, rmode->efbHeight);\r\n//\tGXSetDispCopyYScale((f32)(rmode->xfbHeight) / (f32)(rmode->efbHeight));\r\n//\tGXSetCopyClamp((GXFBClamp)(GX_CLAMP_TOP | GX_CLAMP_BOTTOM));\r\n//\tGXSetCopyFilter(rmode->aa, rmode->sample_pattern, GX_TRUE, rmode->vfilter);\r\n//\tGXSetDispCopyGamma( GX_GM_1_0 );\r\n//\tGXSetDispCopyFrame2Field(GX_COPY_PROGRESSIVE);\r\n//\tGXClearBoundingBox();\r\n//\t\r\n//\t//\r\n//\t// CPU direct EFB access\r\n//\t//\r\n//\tGXPokeColorUpdate(GX_TRUE);\r\n//\tGXPokeAlphaUpdate(GX_TRUE);\r\n//\tGXPokeDither(GX_FALSE);\r\n//\tGXPokeBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ONE, GX_LO_SET);\r\n//\tGXPokeAlphaMode(GX_ALWAYS, 0);\r\n//\tGXPokeAlphaRead(GX_READ_FF);\r\n//\tGXPokeDstAlpha(GX_DISABLE, 0);\r\n//\tGXPokeZMode(GX_TRUE, GX_ALWAYS, GX_TRUE);\r\n//\t\r\n//\t//\r\n//\t// Performance Counters\r\n//\t//\r\n//\tGXSetGPMetric(GX_PERF0_NONE, GX_PERF1_NONE);\r\n//\tGXClearGPMetric();\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\t\r\n\t\t\t\t\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nu32 GetTexBufferSize( u16\t\twidth,\r\n\t\t\t\t\t  u16\t\theight,\r\n\t\t\t\t\t  u32\t\tformat,\r\n\t\t\t\t\t  GXBool\tmipmap,\r\n\t\t\t\t\t  u8\t\tmax_lod )\r\n{\r\n#ifndef __PLAT_WN32__\r\n\treturn GXGetTexBufferSize( width, height, format, mipmap, max_lod );\r\n#else\r\n\treturn 0;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\n}\t\t// namespace GX\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#ifdef __PLAT_WN32__\r\nshort\t\t\tg_tex_off[4];\r\nshort\t\t\tg_alpha_off[4];\r\nint\t\t\t\tg_num_tex;\r\n#endif\t\t// __PLAT_WN32__\r\n\r\nnamespace NxNgc\r\n{\r\n\r\nstatic int\tstage_id = 0;\t// 0-15\r\nstatic int\ttev_id = 0;\t\t\t\t\t// 0-3\r\nstatic int\tuv_id = 0;\t\t\t\t\t// 0-7\r\nstatic int\tuv_tex_id = 0;\t\t\t\t\t// 0-7\r\nstatic int\tmap_id = 0;\t\t\t\t\t// 0-3\r\nstatic int\tlayer_id = 0;\t\t\t\t\t// 1-3\r\nstatic bool correct_color = false;\r\n\r\nGXTexCoordID\tordt[16];\r\nGXTexMapID\t\tordm[16];\r\nGXChannelID\t\tordc[16];\r\nbool\t\t\tord[16];\r\n\r\nGXTevKAlphaSel\tasel[16]; \r\nGXTevKColorSel\tcsel[16];\r\nbool\t\t\tsel[16];\r\n\r\nGXTexMtx\t\ttexmtx[8];\r\nbool\t\t\tsettex = false;\r\n\r\nbool\t\t\t_su;\r\nbool\t\t\t_tb;\r\nbool\t\t\t_tc;\r\nbool\t\t\t_ta;\r\n\r\n//typedef struct\r\n//{\r\n//\tGXTexCoordID\tid;\r\n//\tGXTexGenType\ttype;\r\n//\tGXTexGenSrc\t\tsrc;\r\n//} DEFER_GEN;\r\n//\r\n//DEFER_GEN defer_gen[16];\r\n//int num_defer_gen = 0;\r\n\r\nstatic void multi_start ( bool bl, bool tx )\r\n{\r\n\t// Set everything to 0.\r\n\t// Set everything to 0.\r\n\tstage_id\t= 0;\r\n\ttev_id\t\t= 0;\r\n\tuv_id\t\t= 0;\r\n\tuv_tex_id\t\t= 0;\r\n\tmap_id\t\t= 0;\r\n\tlayer_id\t= 0;\r\n\r\n\r\n//\tnum_defer_gen = 0;\r\n\r\n\t// Don't forget these!\r\n//\tGXSetNumChans(2);\r\n//\tGXSetNumTexGens(2);\r\n//\tGXSetNumTevStages(2);\r\n\r\n\t// See if we need to add 2 stages for color correction.\r\n\tif ( correct_color )\r\n\t{\r\n\t\tif(bl && _su)\r\n\t\t{\r\n\t\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE0,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG1,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\r\n\t\t\tGX::SetTevColorInOp( GX_TEVSTAGE0,\t\tGX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG1 );\r\n\t\r\n\t\t\tGX::SetTevAlphaInOpSwap( GX_TEVSTAGE1,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG2,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP1 );\r\n\t\r\n\t\t\tGX::SetTevColorInOp( GX_TEVSTAGE1,\t\tGX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C1,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG2 );\r\n\t\t}\r\n\t\tstage_id += 2;\r\n\t}\r\n\r\n//\t// Create 2 dummy stages.\r\n//\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n//\r\n//\tGXSetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR_NULL );\r\n//\tGXSetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGXSetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\tGXSetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n//\tGXSetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );\r\n//\tGXSetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO );\r\n//\tstage_id++;\r\n//\r\n//\ts_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n//\t\r\n//\tGXSetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR0A0 );\r\n//\tGXSetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\tGXSetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG2 );\r\n//\tGXSetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG2 );\r\n//\tGXSetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n//\tGXSetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n//\tstage_id++;\r\n\r\n//\tif ( !gCorrectColor || !gMeshUseCorrection )\r\n//\t{\r\n////\t\t// Create 2 dummy stages.\r\n////\t\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n////\r\n////\t\tGXSetTevOrder( s_id, GX_TEXCOORD_NULL, GX_TEX_DISABLE, GX_COLOR0A0 );\r\n////\t\tGXSetTevSwapMode( s_id, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n////\t\tGXSetTevAlphaOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG2 );\r\n////\t\tGXSetTevColorOp(s_id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG2 );\r\n////\t\tGXSetTevAlphaIn ( s_id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n////\t\tGXSetTevColorIn ( s_id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n////\t\tstage_id++;\r\n//\t\tcorrect_color = false;\r\n//\t}\r\n\r\n\t// Clear out state settings.\r\n\tint lp;\r\n\tfor ( lp = 0; lp < 16; lp++ )\r\n\t{\r\n\t\tasel[lp] = GX_TEV_KASEL_1;\r\n\t\tcsel[lp] = GX_TEV_KCSEL_1;\r\n\t\tsel[lp] = false;\r\n\r\n\t\tordt[lp] = (GXTexCoordID)(lp&7);\r\n\t\tordm[lp] = (GXTexMapID)(lp&7);\r\n\t\tordc[lp] = GX_COLOR0A0;\r\n\t\tord[lp] = false;\r\n\t}\r\n\r\n\tfor ( lp = 0; lp < 8; lp++ )\r\n\t{\r\n\t\ttexmtx[lp] = GX_IDENTITY;\r\n\t}\r\n\r\n\tsettex = false;\r\n}\r\n\r\nstatic void multi_add_layer ( BlendModes blendmode, int raw_fix, bool bl, bool tx )\r\n{\r\n\t// Set inputs.\r\n\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n\t\r\n//\tint reg_id = 1;\t//layer_id;\t//( layer_id > 1 ) ? 1 : layer_id;\t//( tev_id == 3 ) ? 2 : tev_id;\t\t// CPREV, C0, C1, C0.\r\n  //  int reg_id = layer_id;\t//( layer_id == 3 ) ? 2 : layer_id;\t\t// CPREV, C0, C1, C0.\r\n\tint reg_id = tev_id;\t\t// CPREV, C0, C1, C0.\r\n\r\n//\tGXTevAlphaArg newa= (GXTevAlphaArg)(((int)GX_CA_APREV)+reg_id);\r\n\tGXTevColorArg newc = (GXTevColorArg)(((int)GX_CC_CPREV)+(reg_id*2));\r\n\tGXTevColorArg newca= (GXTevColorArg)(((int)GX_CC_APREV)+(reg_id*2));\r\n\r\n\r\n    // out_reg = (d (op) ((1.0 - c)*a + c*b) + bias) * scale;\r\n\r\n//\tint fix = raw_fix;\t//( raw_fix >= 128 ) ? 255 : raw_fix * 2;\r\n\r\n\tswitch ( blendmode ) {\r\n\t\tcase vBLEND_MODE_ADD:\r\n\t\tcase vBLEND_MODE_ADD_FIXED:\r\n\t\t\t// Add using texture or fixed alpha.\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR_NULL;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\r\n\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, newc, newca, GX_CC_CPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\r\n\t\t\tstage_id++;\r\n\t\t\tbreak;\r\n\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\t\t// Subtract using texture or fixed alpha.\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR_NULL;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SUB, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tif(bl && _su) GX::SetTevColorInOp ( s_id,\t\tGX_CC_ZERO, newc, newca, GX_CC_CPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SUB, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\t\tstage_id++;\r\n\t\t\tbreak;\r\n\t\tcase vBLEND_MODE_BLEND:\r\n\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n\t\t\t// Blend using texture or fixed alpha.\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR_NULL;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tif(bl && _su) GX::SetTevColorInOp ( s_id, \t\tGX_CC_CPREV, newc, newca, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\t\tstage_id++;\r\n\t\t\tbreak;\r\n\t\tcase vBLEND_MODE_MODULATE:\r\n\t\t\t// Modulate current layer with previous layer.\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR_NULL;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, newca, GX_CC_CPREV, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\t\tstage_id++;\r\n\t\t\tbreak;\r\n\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\t// Modulate current layer with fixed alpha.\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tcsel[(int)s_id] = (GXTevKColorSel)(((int)GX_TEV_KCSEL_K0_A)+layer_id);\r\n\t\t\t\tasel[(int)s_id] = GX_TEV_KASEL_1;\r\n\t\t\t\tsel[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR_NULL;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, GX_CC_CPREV, GX_CC_KONST, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\t\tstage_id++;\r\n\t\t\tbreak;\r\n\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\t\t// Modulate current layer with previous layer, & add current layer.\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR_NULL;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, newca, GX_CC_CPREV, GX_CC_CPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\t\tstage_id++;\r\n\t\t\tbreak;\r\n\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\t// Modulate current layer with fixed alpha, & add current layer.\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tcsel[(int)s_id] = (GXTevKColorSel)(((int)GX_TEV_KCSEL_K0_A)+layer_id);\r\n\t\t\t\tasel[(int)s_id] = GX_TEV_KASEL_1;\r\n\t\t\t\tsel[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR_NULL;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, GX_CC_CPREV, GX_CC_KONST, GX_CC_CPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\t\tstage_id++;\r\n\t\t\tbreak;\r\n\t\tcase vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\t\t// Blend using previous alpha value.\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR_NULL;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tif(bl && _su) GX::SetTevColorInOp ( s_id, \t\tGX_CC_CPREV, newc, newca, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\t\tstage_id++;\r\n\t\t\tbreak;\r\n\t\tcase vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\t\t// Blend using previous alpha value.\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR_NULL;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tif(bl && _su) GX::SetTevColorInOp ( s_id, \t\tnewc, GX_CC_CPREV, newca, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\t\tstage_id++;\r\n\t\t\tbreak;\r\n\t\tcase vBLEND_MODE_DIFFUSE:\r\n\t\tdefault:\r\n\t\t\t// Replace with this texture. Shouldn't ever be used, but here for compatibility.\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR_NULL;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tnewc, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\t\tstage_id++;\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\nstatic void multi_add_texture ( sTexture * p_texture, GXColor matcol, GXTexWrapMode umode, GXTexWrapMode vmode, BlendModes blendmode, int fix, float k, float shininess, uint8 flags, int layer, bool ignore_alpha, bool bl, bool tx )\r\n{\r\n\t// Mesh\r\n\tGXTexCoordID u_id = (GXTexCoordID)(((int)GX_TEXCOORD0)+uv_id);\r\n\r\n\tif ( flags & ( (1<<1) | (1<<2) ) )\r\n\t{\r\n\t\t// Environment mapped or UV wibbled.\r\n\t\tGXTexMtx mtx;\r\n\t\tif ( flags & (1<<1) )\r\n\t\t{\r\n\t\t\tswitch ( layer )\r\n\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tmtx = GX_TEXMTX0;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tmtx = GX_TEXMTX1;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tmtx = GX_TEXMTX2;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\tmtx = GX_TEXMTX3;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tmtx = GX_IDENTITY;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\r\n\t\t\t// Force repeat mode for environment mapping & NRM uv generation.\r\n\t\t\tumode = GX_REPEAT;\r\n\t\t\tvmode = GX_REPEAT;\r\n\t\t\tif(tx && _ta)\r\n\t\t\t{\r\n//\t\t\t\tdefer_gen[num_defer_gen].id\t\t= u_id;\r\n//\t\t\t\tdefer_gen[num_defer_gen].type\t= GX_TG_MTX2x4;\r\n//\t\t\t\tdefer_gen[num_defer_gen].src\t= GX_TG_NRM;\r\n//\t\t\t\tnum_defer_gen++;\r\n\t\t\t\tGX::SetTexCoordGen( u_id, GX_TG_MTX2x4, GX_TG_NRM, GX_FALSE, GX_PTIDENTITY );\r\n\t\t\t\ttexmtx[(int)u_id] = mtx;\r\n\t\t\t\tsettex = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tswitch ( layer )\r\n\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tmtx = GX_TEXMTX0;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tmtx = GX_TEXMTX1;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tmtx = GX_TEXMTX2;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\tmtx = GX_TEXMTX3;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tmtx = GX_IDENTITY;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\r\n\t\t\t// Use texcoords for wibbling & offset matrix.\r\n\t\t\tif(tx && _ta)\r\n\t\t\t{\r\n//\t\t\t\tdefer_gen[num_defer_gen].id\t\t= u_id;\r\n//\t\t\t\tdefer_gen[num_defer_gen].type\t= GX_TG_MTX2x4;\r\n//\t\t\t\tdefer_gen[num_defer_gen].src\t= (GXTexGenSrc)(((int)GX_TG_TEX0)+uv_id);\r\n//\t\t\t\tnum_defer_gen++;\r\n\t\t\t\tGX::SetTexCoordGen( u_id, GX_TG_MTX2x4, (GXTexGenSrc)(((int)GX_TG_TEX0)+uv_tex_id), GX_FALSE, GX_PTIDENTITY );\r\n\t\t\t\ttexmtx[(int)u_id] = mtx;\r\n\t\t\t\tsettex = true;\r\n\t\t\t\tuv_tex_id++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Regular mapping.\r\n\t\tif(tx && _ta)\r\n\t\t{\r\n//\t\t\tdefer_gen[num_defer_gen].id\t\t= u_id;\r\n//\t\t\tdefer_gen[num_defer_gen].type\t= GX_TG_MTX2x4;\r\n//\t\t\tdefer_gen[num_defer_gen].src\t= (GXTexGenSrc)(((int)GX_TG_TEX0)+uv_id);\r\n//\t\t\tnum_defer_gen++;\r\n\t\t\tGX::SetTexCoordGen( u_id, GX_TG_MTX2x4, (GXTexGenSrc)(((int)GX_TG_TEX0)+uv_tex_id), GX_FALSE, GX_PTIDENTITY );\r\n\t\t\ttexmtx[(int)u_id] = GX_IDENTITY;\r\n\t\t\tsettex = true;\r\n\t\t\tuv_tex_id++;\r\n\t\t}\r\n\t}\r\n\tuv_id++;\r\n\r\n\t// Mat\r\n\tif ( map_id >= 8 ) return;\r\n\t\r\n#ifdef __PLAT_WN32__\r\n\tunsigned char tb = 1;\t//( 0 << 4 ) | layer;\r\n\tunsigned char ab = 1;   //( 1 << 4 ) | layer; \r\n\r\n\tvoid * p_tex_data = (void *)((tb<<16)|(tb<<8)|tb);\r\n\tvoid * p_alpha_data = (p_texture->m_PaletteFormat & 1) ? (void *)((ab<<16)|(ab<<8)|ab) : NULL;\r\n\tGXTevSwapSel alpha_swap = GX_TEV_SWAP1;\r\n\tif ( (p_texture->m_PaletteFormat & 1) )\r\n\t{\r\n\t\tint channel = ( p_texture->m_PaletteFormat >> 8 ) & 255;\r\n\t\tswitch ( channel )\r\n\t\t{\r\n\t\t\tcase 0:\r\n\t\t\tdefault:\r\n\t\t\t\talpha_swap = GX_TEV_SWAP1;\t\t// Green\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1:\r\n\t\t\t\talpha_swap = GX_TEV_SWAP2;\t\t// Red\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\talpha_swap = GX_TEV_SWAP3;\t\t// Blue\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tint width = p_texture->m_Width[0];\r\n\tint height = p_texture->m_Height[0];\r\n\tint levels = p_texture->m_MipLevels + 1;\r\n#else\r\n\tvoid * p_tex_data = p_texture->pTexelData;\r\n\tbool has_alpha = ( p_texture->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_ALPHA ) ? true : false;\r\n\tvoid * p_alpha_data = has_alpha ? p_texture->pAlphaData : NULL;\r\n\tGXTevSwapSel alpha_swap = GX_TEV_SWAP1;\r\n\tif ( has_alpha )\r\n\t{\r\n\t\tswitch ( ( p_texture->flags & NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_MASK ) )\r\n\t\t{\r\n\t\t\tcase NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_GREEN:\r\n\t\t\tdefault:\r\n\t\t\t\talpha_swap = GX_TEV_SWAP1;\t\t// Green\r\n\t\t\t\tbreak;\r\n\t\t\tcase NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_RED:\r\n\t\t\t\talpha_swap = GX_TEV_SWAP2;\t\t// Red\r\n\t\t\t\tbreak;\r\n\t\t\tcase NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_BLUE:\r\n\t\t\t\talpha_swap = GX_TEV_SWAP3;\t\t// Blue\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tint width = p_texture->ActualWidth;\r\n\tint height = p_texture->ActualHeight;\r\n\tint levels = p_texture->Levels;\r\n#endif\t\t// __PLAT_WN32__\r\n//\tint reg_id = tev_id;\t//( tev_id > 1 ) ? 1 : tev_id;\t//( tev_id == 3 ) ? 2 : tev_id;\t\t// CPREV, C0, C1, C0.\r\n\tint reg_id = tev_id;\t\t// CPREV, C0, C1, C0.\r\n\t\r\n\tGXTevAlphaArg rasa;\r\n\tGXTevColorArg rasc;\r\n\tGXTevColorArg rasca;\r\n\tif ( correct_color )\r\n\t{\r\n\t\trasa = GX_CA_A2;\r\n\t\trasc = GX_CC_C2;\r\n\t\trasca = GX_CC_A2;\r\n\t}\r\n\telse\r\n\t{\r\n\t\trasa = GX_CA_RASA;\r\n\t\trasc = GX_CC_RASC;\r\n\t\trasca = GX_CC_RASA;\r\n\t}\r\n\r\n\tint cur_map = map_id + 1;\r\n\tint alpha_map = -1;\r\n\r\n\tif ( p_alpha_data )\r\n\t{\r\n\t\tswitch ( blendmode )\r\n\t\t{\r\n\t\t\tcase vBLEND_MODE_ADD:\r\n\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\tcase vBLEND_MODE_BLEND:\r\n\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\t\tcase vBLEND_MODE_MODULATE:\r\n\t\t\tcase vBLEND_MODE_DIFFUSE:\r\n\t\t\t\tif ( cur_map < 8 )\r\n\t\t\t\t{\r\n\t\t\t\t\talpha_map = cur_map;\r\n\t\t\t\t\tcur_map++;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n//\tGXTexObj\ttexObj;\r\n//\tGXInitTexObj( &texObj, p_tex_data, width, height, ((GXTexFmt)p_texture->format), umode, vmode, levels > 1 ? GX_TRUE : GX_FALSE );\r\n//\tif ( levels > 1 )\r\n//\t{\r\n////\t\tif ( gMeshUseAniso && ( tev_id == 0 ) )\r\n////\t\t{\r\n////\t\t\t// If we're correcting the color, we also want ANISO_4.\r\n////\t\t\tGXInitTexObjLOD( &texObj, GX_LIN_MIP_LIN, GX_LINEAR, 0.0f, levels - 1, k, GX_FALSE, GX_TRUE, GX_ANISO_4 );\r\n////\t\t}\r\n////\t\telse\r\n////\t\t{\r\n//\t\t\tGXInitTexObjLOD( &texObj, GX_LIN_MIP_LIN, GX_LINEAR, 0.0f, levels - 1, k, GX_FALSE, GX_TRUE, GX_ANISO_1 );\r\n////\t\t}\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tGXInitTexObjLOD( &texObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, k, GX_FALSE, GX_TRUE, GX_ANISO_1 );\r\n//\t}\r\n//\tGXLoadTexObj( &texObj, (GXTexMapID)(((int)GX_TEXMAP0)+map_id) );\r\n//\tGXSetTexCoordScaleManually( u_id, GX_TRUE, width, height );\r\n\r\n\r\n\tif(tx && _su)\r\n\t{\r\n\t\tvoid * p_td;\r\n\t\tif ( blendmode == vBLEND_MODE_BRIGHTEN )\r\n\t\t{\r\n\t\t\tp_td = p_alpha_data;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tp_td = p_tex_data;\r\n\t\t}\r\n\r\n\t\tif ( p_td )\r\n\t\t{\r\n#ifdef __PLAT_WN32__\r\n\t\t\tg_tex_off[layer] = GDGetCurrOffset();\r\n//\t\tprintf( \"\\nAdded tex off: layer %d, off %d - %d %d %d %d\", layer, g_tex_off[layer], _su, _tb, _tc, _ta );\r\n#endif\t\t// __PLAT_WN32__\r\n\t\t\tGX::UploadTexture(\tp_td,\r\n\t\t\t\t\t\t\t\twidth,\r\n\t\t\t\t\t\t\t\theight,\r\n#ifdef __PLAT_WN32__\r\n\t\t\t\t\t\t\t\t/*( p_texture->m_PaletteFormat & 1 ) ? */GX_TF_CMPR/* : GX_TF_RGBA8*/,\r\n#else\r\n\t\t\t\t\t\t\t\t((GXTexFmt)p_texture->format),\r\n#endif\t\t// __PLAT_WN32__\r\n\t\t\t\t\t\t\t\tumode,\r\n\t\t\t\t\t\t\t\tvmode,\r\n\t\t\t\t\t\t\t\t( levels > 1 ? GX_TRUE : GX_FALSE ),\r\n\t\t\t\t\t\t\t\t( levels > 1 ? GX_LIN_MIP_LIN : GX_LINEAR ),\r\n\t\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\t( levels > 1 ? levels - 1.0f : 0.0f ),\r\n\t\t\t\t\t\t\t\tk,\r\n\t\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\t\tGX_TRUE,\r\n\t\t\t\t\t\t\t\t/*( layer == 0 ) ? GX_ANISO_2 :*/ GX_ANISO_1,\r\n\t\t\t\t\t\t\t\t(GXTexMapID)(((int)GX_TEXMAP0)+map_id) ); \r\n\t\t}\r\n\t}\r\n\r\n\tif(tx && _su) GX::SetTexCoordScale( u_id, GX_TRUE, width, height );\r\n\r\n\tif ( alpha_map >= 0 )\r\n\t{\r\n\t\tswitch ( blendmode )\r\n\t\t{\r\n\t\t\tcase vBLEND_MODE_ADD:\r\n\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\tcase vBLEND_MODE_BLEND:\r\n\t\t\tcase vBLEND_MODE_MODULATE:\r\n\t\t\tcase vBLEND_MODE_DIFFUSE:\r\n\t\t\t\tif(tx && _su)\r\n\t\t\t\t{\r\n#ifdef __PLAT_WN32__\r\n\t\t\t\t\tg_alpha_off[layer] = GDGetCurrOffset();\r\n//\t\t\t\t\tprintf( \"\\nAdded alp off %d - %d %d %d %d\", layer, _su, _tb, _tc, _ta );\r\n#endif\t\t// __PLAT_WN32__\r\n\t\t\t\t\tGX::UploadTexture(\tp_alpha_data,\r\n\t\t\t\t\t\t\t\t\t\t\twidth,\r\n\t\t\t\t\t\t\t\t\t\t\theight,\r\n#ifdef __PLAT_WN32__\r\n\t\t\t\t\t\t\t\t\t\t\t/*( p_texture->m_PaletteFormat & 1 ) ? */GX_TF_CMPR/* : GX_TF_RGBA8*/,\r\n#else\r\n\t\t\t\t\t\t\t\t\t\t\t((GXTexFmt)p_texture->format),\r\n#endif\t\t// __PLAT_WN32__\r\n\t\t\t\t\t\t\t\t\t\t\tumode,\r\n\t\t\t\t\t\t\t\t\t\t\tvmode,\r\n\t\t\t\t\t\t\t\t\t\t\t( levels > 1 ? GX_TRUE : GX_FALSE ),\r\n\t\t\t\t\t\t\t\t\t\t\t( levels > 1 ? GX_LIN_MIP_LIN : GX_LINEAR ),\r\n\t\t\t\t\t\t\t\t\t\t\tGX_LINEAR,\r\n\t\t\t\t\t\t\t\t\t\t\t0.0f,\r\n\t\t\t\t\t\t\t\t\t\t\t( levels > 1 ? levels - 1.0f : 0.0f ),\r\n\t\t\t\t\t\t\t\t\t\t\tk,\r\n\t\t\t\t\t\t\t\t\t\t\tGX_FALSE,\r\n\t\t\t\t\t\t\t\t\t\t\tGX_TRUE,\r\n\t\t\t\t\t\t\t\t\t\t\t/*( layer == 0 ) ? GX_ANISO_2 :*/ GX_ANISO_1,\r\n\t\t\t\t\t\t\t\t\t\t\t(GXTexMapID)(((int)GX_TEXMAP0)+alpha_map) );\r\n\t\t\t\t}\r\n\r\n\t\t\t\t//if(tx && _su) GX::SetTexCoordScale( u_id, GX_TRUE, width, height );\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tp_alpha_data = NULL;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tGXTexMapID t_id = (GXTexMapID)(((int)GX_TEXMAP0)+map_id);\r\n\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n\r\n\tGXColor col;\r\n\tif ( blendmode == vBLEND_MODE_BRIGHTEN_FIXED )\r\n\t{\r\n\t\tcol.r = fix;\r\n\t\tcol.g = fix;\r\n\t\tcol.b = fix;\r\n\t\tcol.a = fix;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( ( blendmode == vBLEND_MODE_BRIGHTEN ) & !p_alpha_data )\r\n\t\t{\r\n\t\t\tcol.r = 255;\r\n\t\t\tcol.g = 255;\r\n\t\t\tcol.b = 255;\r\n\t\t\tcol.a = 255;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcol.r = matcol.r;\r\n\t\t\tcol.g = matcol.g;\r\n\t\t\tcol.b = matcol.b;\r\n\t\t\tcol.a = fix;\r\n\t\t}\r\n\t}\r\n\r\n\t// Modulate material color.\r\n\tGXTevColorArg color_source = rasc;\r\n\tGXTevScale color_scale = GX_CS_SCALE_2;\r\n\tswitch ( blendmode )\r\n\t{\r\n\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\tif(tx && _su) GX::SetTevKColor( (GXTevKColorID)(((int)GX_KCOLOR0)+tev_id), col );\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tcsel[(int)s_id] = (GXTevKColorSel)(((int)GX_TEV_KCSEL_K0)+tev_id);\r\n\t\t\t\tasel[(int)s_id] = GX_TEV_KASEL_1;\r\n\t\t\t\tsel[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR0A0;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, rasa, GX_CA_KONST, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, rasca, GX_CC_KONST, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n\t\t\tcolor_source = (GXTevColorArg)(((int)GX_CC_CPREV)+(reg_id*2));\r\n\t\t\tcolor_scale = GX_CS_SCALE_2;\r\n\t\t\tstage_id++;\r\n\t\t\ts_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n\t\t\tbreak;\r\n\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\t\t{\r\n\t\t\t\tGXTevSwapSel aa;\r\n\r\n#ifdef __PLAT_WN32__\r\n\t\t\t\tint channel = ( p_texture->m_PaletteFormat >> 8 ) & 255;\r\n\t\t\t\tswitch ( channel )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase 0:\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\taa = GX_TEV_SWAP1;\t\t// Green\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 1:\r\n\t\t\t\t\t\taa = GX_TEV_SWAP2;\t\t// Blue\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 2:\r\n\t\t\t\t\t\taa = GX_TEV_SWAP3;\t\t// Red\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n#else\r\n\t\t\t\tswitch ( ( p_texture->flags & NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_MASK ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_GREEN:\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\taa = GX_TEV_SWAP1;\t\t// Green\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_RED:\r\n\t\t\t\t\t\taa = GX_TEV_SWAP2;\t\t// Blue\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase NxNgc::sTexture::TEXTURE_FLAG_CHANNEL_BLUE:\r\n\t\t\t\t\t\taa = GX_TEV_SWAP3;\t\t// Red\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n\t\t\t\tif ( p_alpha_data )\r\n\t\t\t\t{\r\n\t\t\t\t\tif(bl && _su)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tordt[(int)s_id] = u_id;\r\n\t\t\t\t\t\tordm[(int)s_id] = t_id;\r\n\t\t\t\t\t\tordc[(int)s_id] = GX_COLOR0A0;\r\n\t\t\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, rasa, GX_CA_TEXA, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, aa );\r\n\t\t\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, rasca, GX_CC_TEXC, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No alpha, need to do same as BRIGHTEN_FIXED, but with a fix of 1.\r\n\t\t\t\t\tif(tx && _su) GX::SetTevKColor( (GXTevKColorID)(((int)GX_KCOLOR0)+tev_id), col );\r\n\t\t\t\t\tif(bl && _su)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcsel[(int)s_id] = (GXTevKColorSel)(((int)GX_TEV_KCSEL_K0)+tev_id);\r\n\t\t\t\t\t\tasel[(int)s_id] = GX_TEV_KASEL_1;\r\n\t\t\t\t\t\tsel[(int)s_id] = true;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif(bl && _su)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\t\t\tordc[(int)s_id] = GX_COLOR0A0;\r\n\t\t\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, rasa, GX_CA_KONST, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, rasca, GX_CC_KONST, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tcolor_source = (GXTevColorArg)(((int)GX_CC_CPREV)+(reg_id*2));\r\n\t\t\tcolor_scale = GX_CS_SCALE_2;\r\n\t\t\tstage_id++;\r\n\t\t\ts_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tif ( alpha_map >= 0 )\r\n\t\t\t{\r\n\t\t\t\tif(tx && _su) GX::SetTevKColor( (GXTevKColorID)(((int)GX_KCOLOR0)+tev_id), col );\r\n\t\t\t\tif(bl && _su)\r\n\t\t\t\t{\r\n\t\t\t\t\tcsel[(int)s_id] = (GXTevKColorSel)(((int)GX_TEV_KCSEL_K0)+tev_id);\r\n\t\t\t\t\tasel[(int)s_id] = GX_TEV_KASEL_1;\r\n\t\t\t\t\tsel[(int)s_id] = true;\r\n\t\t\t\t}\r\n\t\t\t\tGXTexMapID a_id = (GXTexMapID)(((int)GX_TEXMAP0)+alpha_map);\r\n\t\t\t\tif(bl && _su)\r\n\t\t\t\t{\r\n\t\t\t\t\tordt[(int)s_id] = u_id;\r\n\t\t\t\t\tordm[(int)s_id] = a_id;\r\n\t\t\t\t\tordc[(int)s_id] = GX_COLOR0A0;\r\n\t\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id, GX_CA_TEXA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, alpha_swap );\r\n\t\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, rasc, GX_CC_KONST, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n\t\t\t\tcolor_source = (GXTevColorArg)(((int)GX_CC_CPREV)+(reg_id*2));\r\n\t\t\t\tcolor_scale = GX_CS_SCALE_2;\r\n\t\t\t\tstage_id++;\r\n\t\t\t\ts_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( ( col.r != 128 ) || ( col.g != 128 ) || ( col.b != 128 ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t// Unique material color.\r\n\t\t\t\t\tif(tx && _su) GX::SetTevKColor( (GXTevKColorID)(((int)GX_KCOLOR0)+tev_id), col );\r\n\t\t\t\t\tif(bl && _su)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcsel[(int)s_id] = (GXTevKColorSel)(((int)GX_TEV_KCSEL_K0)+tev_id);\r\n\t\t\t\t\t\tasel[(int)s_id] = GX_TEV_KASEL_1;\r\n\t\t\t\t\t\tsel[(int)s_id] = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif(bl && _su)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\t\t\tordc[(int)s_id] = GX_COLOR0A0;\r\n\t\t\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\trasa, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, rasc, GX_CC_KONST, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n\t\t\t\t\tcolor_source = (GXTevColorArg)(((int)GX_CC_CPREV)+(reg_id*2));\r\n\t\t\t\t\tcolor_scale = GX_CS_SCALE_2;\r\n\t\t\t\t\tstage_id++;\r\n\t\t\t\t\ts_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// No need for material color stage.\r\n\t\t\t\t\tcolor_source = rasc;\r\n\t\t\t\t\tcolor_scale = GX_CS_SCALE_4;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n\t\r\n\t// Set texture coordinates. Note: If p_tex is NULL, it means this layer is environment mapped.\r\n//\tif ( !(flags & MATFLAG_ENVIRONMENT) )\r\n//\t{\r\n\t\t//*p_uv_slot = uv_id;\r\n//\t\tuv_id++;\r\n//\t} else {\r\n//\t\t*p_uv_slot = -1;\r\n//\t}\r\n\r\n\t// Load this texture up into a temporary register for use later.\r\n\t// Note: conveniently, the 1st texture ends up in TEVPREV which means it will be fine\r\n\t// if no blends are performed.\r\n\tswitch ( blendmode )\r\n\t{\r\n\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\t// Just pass it on through...\r\n\t\t\tbreak;\r\n\t\tcase vBLEND_MODE_ADD_FIXED:\r\n\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\t// If we didn't upload with the material color, upload here.\r\n\t\t\tif ( color_source == rasc )\r\n\t\t\t{\r\n\t\t\t\tif(tx && _su) GX::SetTevKColor( (GXTevKColorID)(((int)GX_KCOLOR0)+tev_id), col );\r\n\t\t\t}\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tcsel[(int)s_id] = GX_TEV_KCSEL_1;\r\n\t\t\t\tasel[(int)s_id] = (GXTevKAlphaSel)(((int)GX_TEV_KASEL_K0_A)+tev_id);\r\n\t\t\t\tsel[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = u_id;\r\n\t\t\t\tordm[(int)s_id] = t_id;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR0A0;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif ( ignore_alpha )\r\n\t\t\t{\r\n\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_KONST, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_KONST, rasa, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t}\r\n\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, GX_CC_TEXC, color_source, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, color_scale, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n\t\t\tstage_id++;\r\n\t\t\tbreak;\r\n\t\tcase vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\tcase vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = u_id;\r\n\t\t\t\tordm[(int)s_id] = t_id;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR0A0;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, (GXTevAlphaArg)(((int)GX_CA_APREV)+(reg_id-1)),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, GX_CC_TEXC, color_source, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, color_scale, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n\t\t\tstage_id++;\r\n\t\t\tbreak;\r\n\t\tcase vBLEND_MODE_ADD:\r\n\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\tcase vBLEND_MODE_BLEND:\r\n\t\tcase vBLEND_MODE_MODULATE:\r\n\t\tcase vBLEND_MODE_DIFFUSE:\r\n\t\tdefault:\r\n\t\t\t// We need to add a stage, if we have an alpha map.\r\n\t\t\tif ( ( alpha_map >= 0 )/* && ( blendmode != vBLEND_MODE_DIFFUSE )*/ )\r\n\t\t\t{\r\n//\t\t\t\t// Set inputs.\r\n//\t\t\t\tGXTexMapID a_id = (GXTexMapID)(((int)GX_TEXMAP0)+alpha_map);\r\n//\r\n//\t\t\t\tif(bl && _su)\r\n//\t\t\t\t{\r\n//\t\t\t\t\tordt[(int)s_id] = u_id;\r\n//\t\t\t\t\tordm[(int)s_id] = a_id;\r\n//\t\t\t\t\tordc[(int)s_id] = GX_COLOR0A0;\r\n//\t\t\t\t\tord[(int)s_id] = true;\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tif ( ignore_alpha )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_TEXA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, alpha_swap );       // Alpha map is in Green/Red/Blue channel, so use this to swap it to the alpha channel.\r\n//\t\t\t\t}\r\n//\t\t\t\telse\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_TEXA, rasa, GX_CA_ZERO,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, alpha_swap );       // Alpha map is in Green/Red/Blue channel, so use this to swap it to the alpha channel.\r\n//\t\t\t\t}\r\n//\t\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\t(GXTevColorArg)(((int)GX_CC_CPREV)+(reg_id*2)), GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n//\t\t\t\tstage_id++;\r\n//\t\t\t\ts_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n\r\n\t\t\t\tif(bl && _su)\r\n\t\t\t\t{\r\n\t\t\t\t\tordt[(int)s_id] = u_id;\r\n\t\t\t\t\tordm[(int)s_id] = t_id;\r\n\t\t\t\t\tordc[(int)s_id] = GX_COLOR0A0;\r\n\t\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( ignore_alpha )\r\n\t\t\t\t{\r\n\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\t(GXTevAlphaArg)(((int)GX_CA_APREV)+reg_id), GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );       // Alpha map is in Green/Red/Blue channel, so use this to swap it to the alpha channel.\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, (GXTevAlphaArg)(((int)GX_CA_APREV)+reg_id), rasa, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );       // Alpha map is in Green/Red/Blue channel, so use this to swap it to the alpha channel.\r\n\t\t\t\t}\r\n\r\n////\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\t(GXTevAlphaArg)(((int)GX_CA_APREV)+reg_id), GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n////\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, (GXTevAlphaArg)(((int)GX_CA_APREV)+reg_id), GX_CA_TEXA, GX_CA_ZERO,\r\n//\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\t(GXTevAlphaArg)(((int)GX_CA_APREV)+reg_id), GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n//\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, GX_CC_TEXC, color_source, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, color_scale, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n\t\t\t\tstage_id++;\r\n\t\t\t} else {\r\n\t\t\t\tif(bl && _su)\r\n\t\t\t\t{\r\n\t\t\t\t\tordt[(int)s_id] = u_id;\r\n\t\t\t\t\tordm[(int)s_id] = t_id;\r\n\t\t\t\t\tordc[(int)s_id] = GX_COLOR0A0;\r\n\t\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( ignore_alpha )\r\n\t\t\t\t{\r\n\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_TEXA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_TEXA, rasa, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t\t}\r\n\t\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, GX_CC_TEXC, color_source, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, color_scale, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n\t\t\t\tstage_id++;\r\n\t\t\t}\r\n\r\n\t\t\tbreak;\r\n\t}\r\n\r\n//\tif ( shininess > 0 )\r\n//\t{\r\n//\t\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n//\r\n//\t\t// Need to add in specular component.\r\n//\t\tif(bl && _su)\r\n//\t\t{\r\n//\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n//\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n//\t\t\tordc[(int)s_id] = GX_COLOR1A1;\r\n//\t\t\tord[(int)s_id] = true;\r\n//\t\t}\r\n//\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\t(GXTevAlphaArg)(((int)GX_CA_APREV)+reg_id), GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,\r\n//\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id),\r\n//\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\t(GXTevColorArg)(((int)GX_CC_CPREV)+(reg_id*2)), GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC, \r\n//\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+reg_id) );\r\n//\t\tstage_id++;\r\n//\t}\r\n\r\n\tif ( tev_id > 0 ) {\r\n\t\tmulti_add_layer ( blendmode, fix, bl, tx );\r\n\t} else {\r\n\t\t// Set blend mode for base layer.\r\n\t\tswitch ( blendmode )\r\n\t\t{\r\n\t\t\tcase vBLEND_MODE_ADD:\r\n\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n\t\t\t\tif(bl && _su) GX::SetBlendMode( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\t\t\tif(bl && _su) GX::SetBlendMode( GX_BM_SUBTRACT, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase vBLEND_MODE_BLEND:\r\n\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n\t\t\t\tif(bl && _su) GX::SetBlendMode( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\t\tif(bl && _su) GX::SetBlendMode( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\tcase vBLEND_MODE_MODULATE:\r\n\t\t\t\tif(bl && _su) GX::SetBlendMode( GX_BM_BLEND, GX_BL_ZERO, GX_BL_SRCALPHA, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t\tcase vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\t\tcase vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\t\tcase vBLEND_MODE_DIFFUSE:\r\n\t\t\tdefault:\r\n\t\t\t\tif(bl && _su) GX::SetBlendMode( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tlayer_id++;\r\n\r\n\ttev_id++;\r\n\tmap_id = cur_map;\r\n#ifdef __PLAT_WN32__\r\n\tg_num_tex = map_id;\r\n#endif\t\t// __PLAT_WN32__\r\n}\r\n\r\nstatic void multi_end ( BlendModes blendmode, uint8 pass_flags, uint8 has_holes, uint8 alphacutoff, uint8 flags, bool bl, bool tx, bool cull )\r\n{\r\n\tint color_channels;\r\n\tif ( correct_color )\r\n\t{\r\n\t\tGXTexCoordID u_id;\r\n\t\t// Convert color0 to s,t for 2-D texture lookup (RG)\r\n\t\tu_id = (GXTexCoordID)(((int)GX_TEXCOORD0)+uv_id);\r\n\t\tif(tx && _ta) GX::SetTexCoordGen( u_id, GX_TG_SRTG, GX_TG_COLOR0, GX_FALSE, GX_PTIDENTITY );\r\n\t\tif(tx && _su) GX::SetTexCoordScale( u_id, GX_TRUE, 64, 64 );\r\n\r\n\t\tif(bl && _su)\r\n\t\t{\r\n\t\t\tordt[(int)GX_TEVSTAGE0] = u_id;\r\n\t\t\tordm[(int)GX_TEVSTAGE0] = GX_TEXMAP7;\r\n\t\t\tordc[(int)GX_TEVSTAGE0] = GX_COLOR_NULL;\r\n\t\t\tord[(int)GX_TEVSTAGE0] = true;\r\n\t\t}\r\n\r\n\t\tuv_id++;\r\n\t\r\n\t\t// Convert color1 to s,t for 2-D texture lookup (BA)\r\n\t\tu_id = (GXTexCoordID)(((int)GX_TEXCOORD0)+uv_id);\r\n\t\tif(tx && _ta) GX::SetTexCoordGen( u_id, GX_TG_SRTG, GX_TG_COLOR1, GX_FALSE, GX_PTIDENTITY );\r\n\t\tif(tx && _su) GX::SetTexCoordScale( u_id, GX_TRUE, 64, 64 );\r\n\r\n\t\tif(bl && _su)\r\n\t\t{\r\n\t\t\tordt[(int)GX_TEVSTAGE1] = u_id;\r\n\t\t\tordm[(int)GX_TEVSTAGE1] = GX_TEXMAP7;\r\n\t\t\tordc[(int)GX_TEVSTAGE1] = GX_COLOR_NULL;\r\n\t\t\tord[(int)GX_TEVSTAGE1] = true;\r\n\t\t}\r\n\r\n\t\tuv_id++;\r\n\t\tcolor_channels = 2;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcolor_channels = 1;\r\n\t}\r\n\r\n\r\n\r\n\t// Alpha cutoff.\r\n\tif ( tx && _su ) GX::SetAlphaCompare(GX_GEQUAL, alphacutoff, GX_AOP_AND, GX_GEQUAL, alphacutoff );\r\n//\tif ( tx ) GX::SetZCompLoc( has_holes ? GX_FALSE : GX_TRUE );\r\n\r\n\t// Special case. If the base layer uses subtractive mode, we need to add a stage to\r\n\t// modulate the color & alpha.\r\n\tswitch ( blendmode )\r\n\t{\r\n\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\t{\r\n\t\t\t\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n\r\n\t\t\t\tif(bl && _su)\r\n\t\t\t\t{\r\n\t\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\t\tordc[(int)s_id] = GX_COLOR_NULL;\r\n\t\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, GX_CC_CPREV, GX_CC_APREV, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );\r\n\t\t\t\tstage_id++;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\r\n//\tif ( blendmode == vBLEND_MODE_DIFFUSE )\r\n//\t{\r\n//\t\t//Always pass pixels with multi-texturing as the base must be opaque.\r\n//\t\tGXSetAlphaCompare(GX_GEQUAL, 0, GX_AOP_AND, GX_GEQUAL, 0 );\r\n//\t\tGXSetZCompLoc( GX_TRUE );\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t}\r\n\r\n//\tif ( correct_color )\r\n//\t{\r\n//\t\tGXTexCoordID u_id;\r\n//\t\t// Convert color0 to s,t for 2-D texture lookup (RG)\r\n//\t\tu_id = (GXTexCoordID)(((int)GX_TEXCOORD0)+uv_id);\r\n//\t\tGXSetTexCoordGen(u_id, GX_TG_SRTG, GX_TG_COLOR0, GX_IDENTITY);\r\n//\t\tGXSetTevOrder(GX_TEVSTAGE0, u_id, GX_TEXMAP7, GX_COLOR_NULL);\r\n//\t\tuv_id++;\r\n//\t\r\n//\t\t// Convert color1 to s,t for 2-D texture lookup (BA)\r\n//\t\tu_id = (GXTexCoordID)(((int)GX_TEXCOORD0)+uv_id);\r\n//\t\tGXSetTexCoordGen(u_id, GX_TG_SRTG, GX_TG_COLOR1, GX_IDENTITY);\r\n//\t\tGXSetTevOrder(GX_TEVSTAGE1, u_id, GX_TEXMAP7, GX_COLOR_NULL);\r\n//\t\tuv_id++;\r\n//\t\tGXSetNumChans( 2 );\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tGXSetNumChans( 1 );\r\n//\t}\r\n//\r\n//\t// Set final number of textures/stages.\r\n//\tGXSetNumTexGens( uv_id );\r\n//    GXSetNumTevStages( stage_id );\r\n\r\n\tGXCullMode cull_mode;\r\n\tif ( pass_flags & (1<<3) )\r\n\t{\r\n\t\t// Semitransparent.\r\n\t\tif ( flags & (1<<2) )\r\n\t\t{\r\n\t\t\tcull_mode = GX_CULL_FRONT;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcull_mode = GX_CULL_NONE;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Opaque.\r\n\t\tif ( flags & (1<<1) )\r\n\t\t{\r\n\t\t\tcull_mode = GX_CULL_NONE;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcull_mode = GX_CULL_FRONT;\r\n\t\t}\r\n\t}\r\n\tif ( !cull )\r\n\t{\r\n\t\tcull_mode = GX_CULL_NONE; \r\n\t}\r\n\r\n////\tif ( EngineGlobals.poly_culling && ( flags & (1<<1) ) )\r\n//\tif ( flags & (1<<1) )\r\n//\t{\r\n//\t\tcull_mode = GX_CULL_FRONT;\r\n//\t}\r\n\r\n//\tif(bl && _ta) GX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\r\n\r\n\r\n\r\n\r\n\t// Issue buffered commands.\r\n\tint lp;\r\n\tfor ( lp = 0; lp < 16; lp += 2 )\r\n\t{\r\n\t\tif ( sel[lp] || sel[lp+1] )\r\n\t\t{\r\n\t\t\tif ( bl && _su ) GX::SetTevKSel( (GXTevStageID)lp, csel[lp], asel[lp], csel[lp+1], asel[lp+1] );\r\n//\t\t\tGDSetTevKonstantSel( (GXTevStageID)lp, csel[lp], asel[lp], csel[lp+1], asel[lp+1] );\r\n\t\t}\r\n\t\tif ( ord[lp] || ord[lp+1] )\r\n\t\t{\r\n\t\t\tif ( bl && _su ) GX::SetTevOrder( (GXTevStageID)lp, ordt[lp], ordm[lp], ordc[lp], ordt[lp+1], ordm[lp+1], ordc[lp+1] );\r\n//\t\t\tGDSetTevOrder( (GXTevStageID)lp, ordt[lp], ordm[lp], ordc[lp], ordt[lp+1], ordm[lp+1], ordc[lp+1] );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( settex )\r\n\t{\r\n\t\tGX::SetCurrMtxPosTex03( GX_PNMTX0, texmtx[0], texmtx[1], texmtx[2], texmtx[3] );\r\n\t\tGX::SetCurrMtxTex47( GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );\r\n\r\n//\t\tGDSetCurrentMtx( GX_PNMTX0,\t\t\t// Will be overridden.\r\n//\t\t\t\t\t\t texmtx[0],\r\n//\t\t\t\t\t\t texmtx[1],\r\n//\t\t\t\t\t\t texmtx[2],\r\n//\t\t\t\t\t\t texmtx[3],\r\n//\t\t\t\t\t\t texmtx[4],\r\n//\t\t\t\t\t\t texmtx[5],\r\n//\t\t\t\t\t\t texmtx[6],\r\n//\t\t\t\t\t\t texmtx[7] );\r\n\t}\r\n\r\n\r\n\tif(bl && _ta) GX::SetTexChanTevIndCull( uv_id, color_channels, stage_id, 0, cull_mode );\r\n//\tif(bl && _ta) GX::SetTexChanTevIndCull( uv_id, 1, stage_id, 0, GX_CULL_FRONT );\r\n\r\n//\tfor ( int lp = 0; lp < num_defer_gen; lp++ )\r\n//\t{\r\n//\t\tGX::SetTexCoordGen( defer_gen[lp].id, defer_gen[lp].type, defer_gen[lp].src, GX_FALSE, GX_PTIDENTITY );\r\n//\t}\r\n//\tnum_defer_gen = 0;\r\n\r\n\t// Clear so that subsequent flushes do nothing.\r\n\tfor ( lp = 0; lp < 16; lp++ )\r\n\t{\r\n\t\tasel[lp] = GX_TEV_KASEL_1;\r\n\t\tcsel[lp] = GX_TEV_KCSEL_1;\r\n\t\tsel[lp] = false;\r\n\r\n\t\tordt[lp] = (GXTexCoordID)(lp&7);\r\n\t\tordm[lp] = (GXTexMapID)(lp&7);\r\n\t\tordc[lp] = GX_COLOR0A0;\r\n\t\tord[lp] = false;\r\n\t}\r\n\r\n\tfor ( lp = 0; lp < 8; lp++ )\r\n\t{\r\n\t\ttexmtx[lp] = GX_IDENTITY;\r\n\t}\r\n\r\n\tsettex = false;\r\n}\r\n\r\nstatic void _multi_mesh( sMaterialHeader * p_mat, sMaterialPassHeader * p_base_pass, bool bl, bool tx, bool cull )\r\n{\r\n\tuint32 layer;\r\n\r\n\tmulti_start( bl, tx );\r\n\r\n\tsMaterialPassHeader * p_pass = p_base_pass;\r\n\r\n//\tint uv_set = 0;\r\n\r\n\tint passes = p_mat->m_passes;\r\n\tif ( g_mat_passes < passes )\r\n\t{\r\n\t\tif ( g_mat_passes > 0 )\r\n\t\t{\r\n\t\t\tpasses = g_mat_passes;\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( layer = 0; layer < (uint)passes; layer++, p_pass++ )\r\n\t{\r\n\t\tbool ignore_alpha = ( p_pass->m_flags & (1<<7) ) ? true : false;\r\n\r\n\t\tGXTexWrapMode u_mode;\r\n\t\tGXTexWrapMode v_mode;\r\n\r\n\t\tu_mode = p_pass->m_flags & (1<<5) ? GX_CLAMP : GX_REPEAT;\r\n\t\tv_mode = p_pass->m_flags & (1<<6) ? GX_CLAMP : GX_REPEAT;\r\n\r\n\t\tif ( p_pass->m_texture.p_data )\r\n\t\t{\r\n\t\t\tmulti_add_texture ( p_pass->m_texture.p_data,\r\n\t\t\t\t\t\t\t\tp_pass->m_color,\r\n\t\t\t\t\t\t\t\tu_mode,\r\n\t\t\t\t\t\t\t\tv_mode,\r\n\t\t\t\t\t\t\t\t(BlendModes)p_pass->m_blend_mode,\r\n\t\t\t\t\t\t\t\tp_pass->m_alpha_fix,\r\n\t\t\t\t\t\t\t\t(float)(p_pass->m_k) * (1.0f / (float)(1<<8)),\r\n\t\t\t\t\t\t\t\t0.0f,\t//p_mat->m_shininess,\r\n\t\t\t\t\t\t\t\tp_pass->m_flags,\r\n\t\t\t\t\t\t\t\tlayer,\r\n\t\t\t\t\t\t\t\tignore_alpha,\r\n\t\t\t\t\t\t\t\tbl,\r\n\t\t\t\t\t\t\t\ttx );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Untextured.\r\n\t\t\tGXTevStageID s_id = (GXTevStageID)(((int)GX_TEVSTAGE0)+stage_id);\r\n\t\t\tBlendModes blend = (BlendModes)p_pass->m_blend_mode;\r\n\t\t\tuint8 fix = p_pass->m_alpha_fix;\r\n\r\n\t\t\t\r\n\t\t\tGXColor col;\r\n\t\t\tif ( blend == vBLEND_MODE_BRIGHTEN_FIXED )\r\n\t\t\t{\r\n\t\t\t\tcol.r = fix;\r\n\t\t\t\tcol.g = fix;\r\n\t\t\t\tcol.b = fix;\r\n\t\t\t\tcol.a = fix;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tcol.r = p_pass->m_color.r;\r\n\t\t\t\tcol.g = p_pass->m_color.g;\r\n\t\t\t\tcol.b = p_pass->m_color.b;\r\n\t\t\t\tcol.a = fix;\r\n\t\t\t}\r\n\t\t\tif(tx && _su) GX::SetTevKColor(\t\t\t\t(GXTevKColorID)(((int)GX_KCOLOR0)+tev_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tcol ); \r\n\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tcsel[(int)s_id] = (GXTevKColorSel)(((int)GX_TEV_KCSEL_K0)+layer_id); \r\n\t\t\t\tasel[(int)s_id] = (GXTevKAlphaSel)(((int)GX_TEV_KASEL_K0_A)+layer_id);\r\n\t\t\t\tsel[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tif(bl && _su)\r\n\t\t\t{\r\n\t\t\t\tordt[(int)s_id] = GX_TEXCOORD0;\r\n\t\t\t\tordm[(int)s_id] = GX_TEX_DISABLE;\r\n\t\t\t\tordc[(int)s_id] = GX_COLOR0A0;\r\n\t\t\t\tord[(int)s_id] = true;\r\n\t\t\t}\r\n\r\n\t\t\tswitch ( blend )\r\n\t\t\t{\r\n\t\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_KONST, GX_CA_RASA, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, GX_CC_KONST, GX_CC_RASA, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id) );\r\n\t\t\t\t\t\tstage_id++;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ADDHALF, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t\t\tif ( ignore_alpha )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id) );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_RASA, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id) );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tstage_id++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n\t\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n\t\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_KONST, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, GX_CC_RASC, GX_CC_KONST, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id) );\r\n\t\t\t\t\t\tstage_id++;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase vBLEND_MODE_ADD:\r\n\t\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\t\tcase vBLEND_MODE_BLEND:\r\n\t\t\t\tcase vBLEND_MODE_DIFFUSE:\r\n\t\t\t\tcase vBLEND_MODE_MODULATE:\r\n\t\t\t\tcase vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\t\t\tcase vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tif ( ignore_alpha )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ADDHALF, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif(bl && _su) GX::SetTevAlphaInOpSwap( s_id,\tGX_CA_RASA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id),\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif(bl && _su) GX::SetTevColorInOp( s_id,\t\tGX_CC_ZERO, GX_CC_RASC, GX_CC_KONST, GX_CC_ZERO,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tGX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, (GXTevRegID)(((int)GX_TEVPREV)+tev_id) );\r\n\t\t\t\t\tstage_id++;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tif ( tev_id > 0 ) {\r\n\t\t\t\tmulti_add_layer ( blend, fix, bl, tx );\r\n\t\t\t} else {\r\n\t\t\t\t// Set blend mode for base layer.\r\n\t\t\t\tswitch ( blend )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase vBLEND_MODE_ADD:\r\n\t\t\t\t\tcase vBLEND_MODE_ADD_FIXED:\r\n\t\t\t\t\t\tif(bl && _su) GX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase vBLEND_MODE_SUBTRACT:\r\n\t\t\t\t\tcase vBLEND_MODE_SUB_FIXED:\r\n\t\t\t\t\t\tif(bl && _su) GX::SetBlendMode ( GX_BM_SUBTRACT, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND:\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_FIXED:\r\n\t\t\t\t\t\tif(bl && _su) GX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN:\r\n\t\t\t\t\tcase vBLEND_MODE_BRIGHTEN_FIXED:\r\n\t\t\t\t\t\tif(bl && _su) GX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE_FIXED:\r\n\t\t\t\t\tcase vBLEND_MODE_MODULATE:\r\n\t\t\t\t\t\tif(bl && _su) GX::SetBlendMode ( GX_BM_BLEND, GX_BL_ZERO, GX_BL_SRCALPHA, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_PREVIOUS_MASK:\r\n\t\t\t\t\tcase vBLEND_MODE_BLEND_INVERSE_PREVIOUS_MASK:\r\n\t\t\t\t\tcase vBLEND_MODE_DIFFUSE:\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tif(bl && _su) GX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ttev_id++;\r\n\t\t\tlayer_id++;\r\n\t\t}\r\n\t}\r\n\t\r\n#ifdef __PLAT_WN32__\r\n\tuint8 has_holes = p_base_pass->m_texture.p_data ? ( ( p_base_pass->m_texture.p_data->m_PaletteFormat >> 1 ) & 1 ) : 0;\r\n#else\r\n\tuint8 has_holes = p_base_pass->m_texture.p_data ? ( ( p_base_pass->m_texture.p_data->flags & NxNgc::sTexture::TEXTURE_FLAG_HAS_HOLES ) ? 1 : 0 ) : 0;\r\n#endif\r\n\tmulti_end( (BlendModes)p_base_pass->m_blend_mode, p_base_pass->m_flags, has_holes, p_mat->m_alpha_cutoff, p_mat->m_flags, bl, tx, cull );\r\n}\r\n\r\nvoid multi_mesh( sMaterialHeader * p_mat, sMaterialPassHeader * p_base_pass, bool bl, bool tx, bool should_correct_color, bool cull )\r\n{\r\n\tcorrect_color = should_correct_color;\r\n#ifdef __PLAT_WN32__\r\n\tg_tex_off[0] = -1;\r\n\tg_tex_off[1] = -1;\r\n\tg_tex_off[2] = -1;\r\n\tg_tex_off[3] = -1;\r\n\r\n\tg_alpha_off[0] = -1;\r\n\tg_alpha_off[1] = -1;\r\n\tg_alpha_off[2] = -1;\r\n\tg_alpha_off[3] = -1;\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n#ifdef __PLAT_WN32__\r\n\t_su = true;\r\n\t_tb = false;\r\n\t_tc = false;\r\n\t_ta = false;\r\n\t_multi_mesh( p_mat, p_base_pass, bl, tx, cull );\r\n\t_su = false;\r\n\t_tb = true;\r\n\t_tc = false;\r\n\t_ta = false;\r\n\t_multi_mesh( p_mat, p_base_pass, bl, tx, cull );\r\n\t_su = false;\r\n\t_tb = false;\r\n\t_tc = true;\r\n\t_ta = false;\r\n\t_multi_mesh( p_mat, p_base_pass, bl, tx, cull );\r\n\t_su = false;\r\n\t_tb = false;\r\n\t_tc = false;\r\n\t_ta = true;\r\n\t_multi_mesh( p_mat, p_base_pass, bl, tx, cull );\r\n#else\r\n\t_su = true;\r\n\t_tb = true;\r\n\t_tc = true;\r\n\t_ta = true;\r\n\t_multi_mesh( p_mat, p_base_pass, bl, tx, cull );\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n//\tsu = true;\r\n//\ttb = true;\r\n//\ttc = true;\r\n//\tta = true;\r\n//\t_multi_mesh( p_mat, p_base_pass, true, false );\r\n//\t_multi_mesh( p_mat, p_base_pass, false, true );\r\n////\t_multi_mesh( p_mat, p_base_pass, true, true );\r\n}\r\n\r\n}\t\t// namespace NxNgc\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_gx.h",
    "content": "#ifndef _GX_H_\r\n#define _GX_H_\r\n\r\n#ifndef __PLAT_WN32__\r\n#include <dolphin.h>\r\n#include <gfx/ngc/nx/texture.h>\r\n#include <core/math.h>\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n#ifdef __PLAT_WN32__\r\ntypedef struct\r\n{\r\n\r\n\tf32 x, y, z;\r\n\r\n} Vec, *VecPtr, Point3d, *Point3dPtr;\r\n#endif\t\t// __PLAT_WN32__\r\n\r\n// Types we need, taken from gx headers.\r\n#ifndef __NO_DEFS__\r\n\r\n#define GX_FIFO_OBJ_SIZE            128\r\n\r\ntypedef struct{\r\n    u8      pad[GX_FIFO_OBJ_SIZE];\r\n} GXFifoObj;\r\n\r\ntypedef void (*GXBreakPtCallback)(void);\r\ntypedef void (*GXDrawSyncCallback)(u16 token);\r\ntypedef void (*GXDrawDoneCallback)(void);\r\n\r\nextern GXRenderModeObj GXNtsc240Ds;\r\nextern GXRenderModeObj GXNtsc240DsAa;\r\nextern GXRenderModeObj GXNtsc240Int;\r\nextern GXRenderModeObj GXNtsc240IntAa;\r\nextern GXRenderModeObj GXNtsc480IntDf;\r\nextern GXRenderModeObj GXNtsc480Int;\r\nextern GXRenderModeObj GXNtsc480IntAa;\r\nextern GXRenderModeObj GXNtsc480Prog;\r\nextern GXRenderModeObj GXNtsc480ProgAa;\r\nextern GXRenderModeObj GXMpal240Ds;\r\nextern GXRenderModeObj GXMpal240DsAa;\r\nextern GXRenderModeObj GXMpal240Int;\r\nextern GXRenderModeObj GXMpal240IntAa;\r\nextern GXRenderModeObj GXMpal480IntDf;\r\nextern GXRenderModeObj GXMpal480Int;\r\nextern GXRenderModeObj GXMpal480IntAa;\r\nextern GXRenderModeObj GXPal264Ds;\r\nextern GXRenderModeObj GXPal264DsAa;\r\nextern GXRenderModeObj GXPal264Int;\r\nextern GXRenderModeObj GXPal264IntAa;\r\nextern GXRenderModeObj GXPal528IntDf;\r\nextern GXRenderModeObj GXPal528Int;\r\nextern GXRenderModeObj GXPal524IntAa; // Reduced due to overlap requirement!\r\nextern GXRenderModeObj GXEurgb60Hz240Ds;\r\nextern GXRenderModeObj GXEurgb60Hz240DsAa;\r\nextern GXRenderModeObj GXEurgb60Hz240Int;\r\nextern GXRenderModeObj GXEurgb60Hz240IntAa;\r\nextern GXRenderModeObj GXEurgb60Hz480IntDf;\r\nextern GXRenderModeObj GXEurgb60Hz480Int;\r\nextern GXRenderModeObj GXEurgb60Hz480IntAa;\r\n\r\n#define\tGXPackedRGB565(r,g,b)   \\\r\n\t((u16)((((r)&0xf8)<<8)|(((g)&0xfc)<<3)|(((b)&0xf8)>>3)))\r\n#define\tGXPackedRGBA4(r,g,b,a)  \\\r\n\t((u16)((((r)&0xf0)<<8)|(((g)&0xf0)<<4)|(((b)&0xf0)   )|(((a)&0xf0)>>4)))\r\n#define\tGXPackedRGB5A3(r,g,b,a) \\\r\n\t((u16)((a)>=224 ? \\\r\n\t((((r)&0xf8)<<7)|(((g)&0xf8)<<2)|(((b)&0xf8)>>3)|(1<<15)): \\\r\n\t((((r)&0xf0)<<4)|(((g)&0xf0)   )|(((b)&0xf0)>>4)|(((a)&0xe0)<<7))))\r\n\t\r\n// Display list opcodes:\r\n\r\n#define GX_NOP                      0x00\r\n#define GX_DRAW_QUADS               0x80\r\n#define GX_DRAW_TRIANGLES           0x90\r\n#define GX_DRAW_TRIANGLE_STRIP      0x98\r\n#define GX_DRAW_TRIANGLE_FAN        0xA0\r\n#define GX_DRAW_LINES               0xA8\r\n#define GX_DRAW_LINE_STRIP          0xB0\r\n#define GX_DRAW_POINTS              0xB8\r\n\r\n#define GX_LOAD_BP_REG              0x61\r\n#define GX_LOAD_CP_REG              0x08\r\n#define GX_LOAD_XF_REG              0x10\r\n#define GX_LOAD_INDX_A              0x20\r\n#define GX_LOAD_INDX_B              0x28\r\n#define GX_LOAD_INDX_C              0x30\r\n#define GX_LOAD_INDX_D              0x38\r\n\r\n#define GX_CMD_CALL_DL              0x40\r\n#define GX_CMD_INVL_VC              0x48\r\n\r\n#define GX_OPCODE_MASK              0xF8\r\n#define GX_VAT_MASK                 0x07\r\n\r\n#define GX_PROJECTION_SZ  7\r\n#define GX_VIEWPORT_SZ    6\r\n\r\n#endif\t\t// __NO_DEFS__\r\n\r\nnamespace NxNgc\r\n{\r\nstruct sMaterialPassHeader;\t\t// Forward reference.\r\nstruct sTextureDL;\t\t// Forward reference.\r\n}\r\n\r\n// Allows switching between GX & GD.\r\nnamespace GX\r\n{\r\n\tvoid\t\t\t\tbegin\t\t\t\t( void *\t\t\t\t\t\tp_buffer = NULL,\r\n\t\t\t\t\t\t\t\t\t\t\t  int\t\t\t\t\t\t\tmax_size = 0 );\r\n\t\t\t\t\t\t\t\t\r\n\tint\t\t\t\t\tend\t\t\t\t\t( void );           \t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetChanCtrl\t\t\t( GXChannelID\t\t\t\t\tchan,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tenable,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXColorSrc\t\t\t\t\tamb_src,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXColorSrc\t\t\t\t\tmat_src,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tlight_mask,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXDiffuseFn\t\t\t\t\tdiff_fn,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXAttnFn\t\t\t\t\t\tattn_fn );\r\n\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetTevOrder\t\t\t( GXTevStageID\t\t\t\t\tevenStage,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexCoordID\t\t\t\t\tcoord0,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexMapID\t\t\t\t\tmap0,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXChannelID\t\t\t\t\tcolor0,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexCoordID\t\t\t\t\tcoord1,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexMapID\t\t\t\t\tmap1,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXChannelID\t\t\t\t\tcolor1 );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetTevAlphaInOpSwap\t( GXTevStageID\t\t\t\t\tstage,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevAlphaArg\t\t\t\t\ta,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevAlphaArg\t\t\t\t\tb,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevAlphaArg\t\t\t\t\tc,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevAlphaArg\t\t\t\t\td,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevOp\t\t\t\t\t\top,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevBias\t\t\t\t\t\tbias,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevScale\t\t\t\t\tscale,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tclamp,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevRegID\t\t\t\t\tout_reg,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevSwapSel\t\t\t\t\tras_sel,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevSwapSel\t\t\t\t\ttex_sel );\r\n\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetTevColorInOp\t\t( GXTevStageID\t\t\t\t\tstage,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevColorArg \t\t\t\ta,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevColorArg \t\t\t\tb,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevColorArg \t\t\t\tc,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevColorArg \t\t\t\td,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevOp       \t\t\t\top,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevBias     \t\t\t\tbias,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevScale    \t\t\t\tscale,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool        \t\t\t\tclamp,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevRegID    \t\t\t\tout_reg );\r\n\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetTevKSel\t\t\t( GXTevStageID\t\t\t\t\teven_stage,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevKColorSel \t\t\t\tcolor_even,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevKAlphaSel \t\t\t\talpha_even,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevKColorSel \t\t\t\tcolor_odd,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevKAlphaSel \t\t\t\talpha_odd );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetTevKColor\t\t( GXTevKColorID\t\t\t\t\tid,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXColor\t\t\t\t\t\tcolor );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetTevColor\t\t\t( GXTevRegID\t\t\t\t\treg,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXColor\t\t\t\t\t\tcolor );\r\n\r\n\tvoid\t\t\t\tSetTexCoordGen\t\t( GXTexCoordID\t\t\t\t\tdst_coord,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexGenType\t\t\t\t\tfunc,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexGenSrc\t\t\t\t\tsrc_param,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tnormalize,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tpostmtx );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tUploadTexture\t\t( void *\t\t\t\t\t\timage_ptr,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\twidth,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\theight,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexFmt\t\t\t\t\t\tformat,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexWrapMode\t\t\t\t\twrap_s,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexWrapMode\t\t\t\t\twrap_t,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tmipmap,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexFilter\t\t\t\t\tmin_filt,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexFilter\t\t\t\t\tmag_filt,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tmin_lod,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tmax_lod,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tlod_bias,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tbias_clamp,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tdo_edge_lod,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXAnisotropy\t\t\t\t\tmax_aniso,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexMapID\t\t\t\t\tid );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tUploadTexture\t\t( void *\t\t\t\t\t\timage_ptr,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\twidth,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\theight,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXCITexFmt\t\t\t\t\tformat,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexWrapMode\t\t\t\t\twrap_s,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexWrapMode\t\t\t\t\twrap_t,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tmipmap,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexFilter\t\t\t\t\tmin_filt,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexFilter\t\t\t\t\tmag_filt,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tmin_lod,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tmax_lod,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tlod_bias,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tbias_clamp,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tdo_edge_lod,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXAnisotropy\t\t\t\t\tmax_aniso,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexMapID\t\t\t\t\tid );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tUploadPalette\t\t( void *\t\t\t\t\t\ttlut_ptr,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTlutFmt\t\t\t\t\t\ttlut_format,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTlutSize\t\t\t\t\ttlut_size,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexMapID                    id );\r\n\r\n\tvoid\t\t\t\tSetTexCoordScale\t( GXTexCoordID\t\t\t\t\tcoord,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tenable,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\tss,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\tts );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetBlendMode\t\t( GXBlendMode\t\t\t\t\ttype,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBlendFactor\t\t\t\t\tsrc_factor,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBlendFactor\t\t\t\t\tdst_factor,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXLogicOp\t\t\t\t\t\top,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tcolor_update_enable,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\talpha_update_enable,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tdither_enable );\r\n\r\n\tvoid\t\t\t\tSetTexChanTevIndCull( u8 \t\t\t\t\t\t\tnTexGens,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8 \t\t\t\t\t\t\tnChans,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8 \t\t\t\t\t\t\tnTevs,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8 \t\t\t\t\t\t\tnInds,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXCullMode\t\t\t\t\tcm );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetChanAmbColor\t\t( GXChannelID\t\t\t\t\tchan,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXColor\t\t\t\t\t\tcolor );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetChanMatColor\t\t( GXChannelID chan, \t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t  GXColor color );  \t\t\t\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetPointSize\t\t( u8\t\t\t\t\t\t\tpointSize,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexOffset\t\t\t\t\ttexOffsets );\r\n\r\n\tvoid\t\t\t\tSetFog\t\t\t\t( GXFogType\t\t\t\t\t\ttype,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tstartz,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tendz,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tnearz,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tfarz,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXColor\t\t\t\t\t\tcolor );\r\n\r\n\tvoid\t\t\t\tSetFogColor\t\t\t( GXColor\t\t\t\t\t\tcolor );\r\n\r\n\tvoid\t\t\t\tBegin\t\t\t\t( GXPrimitive\t\t\t\t\ttype,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXVtxFmt\t\t\t\t\t\tvtxfmt,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\tnverts );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tEnd\t\t\t\t\t( void );           \t\t\t\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tPosition3f32\t\t( f32\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tz );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tPosition3u8\t\t\t( u8\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8\t\t\t\t\t\t\tz );\r\n\t\t\t\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\tPosition3s8\t\t\t( s8\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  s8\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  s8\t\t\t\t\t\t\tz );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tPosition3u16\t\t( u16\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\tz );\r\n\t\t\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\tPosition3s16\t\t( s16\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  s16\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  s16\t\t\t\t\t\t\tz );\r\n\t\t\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\tPosition2f32\t\t( f32\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\ty );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tPosition2u8\t\t\t( u8\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8\t\t\t\t\t\t\ty );\r\n\t\t\t\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\tPosition2s8\t\t\t( s8\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  s8\t\t\t\t\t\t\ty );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tPosition2u16\t\t( u16\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\ty );\r\n\t\t\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\tPosition2s16\t\t( s16\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  s16\t\t\t\t\t\t\ty );\r\n\t\t\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\tPosition1x16\t\t( u16\t\t\t\t\t\t\ti );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tPosition1x8\t\t\t( u8\t\t\t\t\t\t\ti );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tNormal3f32\t\t\t( f32\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tz );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tNormal3s16\t\t\t( s16\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  s16\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  s16\t\t\t\t\t\t\tz );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tNormal3s8\t\t\t( s8\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  s8\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  s8\t\t\t\t\t\t\tz );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tNormal1x16\t\t\t( u16\t\t\t\t\t\t\ti );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tNormal1x8\t\t\t( u8\t\t\t\t\t\t\ti );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tColor4u8\t\t\t( u8\t\t\t\t\t\t\tr,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8\t\t\t\t\t\t\tg,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8\t\t\t\t\t\t\tb,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8\t\t\t\t\t\t\ta );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tColor1u32\t\t\t( u32\t\t\t\t\t\t\trgba );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tColor1x16\t\t\t( u16\t\t\t\t\t\t\ti );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tColor1x8\t\t\t( u8\t\t\t\t\t\t\ti );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tTexCoord2f32\t\t( f32\t\t\t\t\t\t\ts,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tt );\r\n\t\t\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\tTexCoord2s16\t\t( s16\t\t\t\t\t\t\ts,\r\n\t\t\t\t\t\t\t\t\t\t\t  s16\t\t\t\t\t\t\tt );\r\n\t\t\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\tTexCoord2u16\t\t( u16\t\t\t\t\t\t\ts,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\tt );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tTexCoord2s8\t\t\t( s8\t\t\t\t\t\t\ts,\r\n\t\t\t\t\t\t\t\t\t\t\t  s8\t\t\t\t\t\t\tt );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tTexCoord2u8\t\t\t( u8\t\t\t\t\t\t\ts,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8\t\t\t\t\t\t\tt );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tTexCoord1f32\t\t( f32\t\t\t\t\t\t\ts );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tTexCoord1s16\t\t( s16\t\t\t\t\t\t\ts );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tTexCoord1u16\t\t( u16\t\t\t\t\t\t\ts );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tTexCoord1s8\t\t\t( s8\t\t\t\t\t\t\ts );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tTexCoord1u8\t\t\t( u8\t\t\t\t\t\t\ts );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tTexCoord1x16\t\t( u16\t\t\t\t\t\t\ti );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tTexCoord1x8\t\t\t( u8\t\t\t\t\t\t\ti );\r\n\t\t\t\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\tMatrixIndex1u8\t\t( u8\t\t\t\t\t\t\ti );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetZMode\t\t\t( GXBool\t\t\t\t\t\tcompare_enable,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXCompare\t\t\t\t\t\tfunc,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tupdate_enable );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetVtxDesc\t\t\t( int\t\t\t\t\t\t\titems,\r\n\t\t\t\t\t\t\t\t\t\t\t  ... );            \t\t\t\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tLoadPosMtxImm\t\t( const\t\t\t\t\t\t\tf32 mtx[3][4],\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tid );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tLoadNrmMtxImm\t\t( const\t\t\t\t\t\t\tf32 mtx[3][4],\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tid );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tLoadTexMtxImm\t\t( const\t\t\t\t\t\t\tf32 mtx[3][4],\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tid,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexMtxType\t\t\t\t\ttype );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetAlphaCompare\t\t( GXCompare\t\t\t\t\t\tcomp0,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8\t\t\t\t\t\t\tref0,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXAlphaOp\t\t\t\t\t\top,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXCompare\t\t\t\t\t\tcomp1,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8\t\t\t\t\t\t\tref1 );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetCurrMtxPosTex03\t( u32\t\t\t\t\t\t\tpn,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tt0,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tt1,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tt2,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tt3 );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetCurrMtxTex47\t\t( u32\t\t\t\t\t\t\tt4,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tt5,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tt6,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tt7 );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetProjection\t\t( const\t\t\t\t\t\t\tf32 mtx[4][4],\r\n\t\t\t\t\t\t\t\t\t\t\t  GXProjectionType\t\t\t\ttype );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetTevSwapModeTable\t( GXTevSwapSel\t\t\t\t\ttable,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevColorChan\t\t\t\tred,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevColorChan\t\t\t\tgreen,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevColorChan\t\t\t\tblue,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTevColorChan\t\t\t\talpha );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetScissorBoxOffset\t( s32\t\t\t\t\t\t\tx_off,\r\n\t\t\t\t\t\t\t\t\t\t\t  s32\t\t\t\t\t\t\ty_off );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetScissor\t\t\t( u32\t\t\t\t\t\t\tleft,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\ttop,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\twd,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tht );\r\n\t\t\t\t\t\t\r\n\tvoid\t\t\t\tSetDispCopyGamma\t( GXGamma\t\t\t\t\t\tgamma );\r\n\t\t\t\r\n\tGXBreakPtCallback\tSetBreakPtCallback\t( GXBreakPtCallback\t\t\t\tcb );\r\n\t\t\t\r\n\tvoid\t\t\t\tFlush\t\t\t\t( void );           \t\t\t\r\n\t\t\t\r\n\tvoid\t\t\t\tGetFifoPtrs\t\t\t( GXFifoObj *\t\t\t\t\tfifo,\r\n\t\t\t\t\t\t\t\t\t\t\t  void **\t\t\t\t\t\treadPtr,\r\n\t\t\t\t\t\t\t\t\t\t\t  void **\t\t\t\t\t\twritePtr );\r\n\t\t\t\r\n\tGXFifoObj *\t\t\tGetCPUFifo\t\t\t( void );           \t\t\t\r\n\t\t\t\r\n\tGXFifoObj *\t\t\tGetGPFifo\t\t\t( void );           \t\t\t\r\n\t\t\t\r\n\tvoid\t\t\t\tEnableBreakPt\t\t( void *\t\t\t\t\t\tbreakPtr );\r\n\t\t\t\r\n\tvoid\t\t\t\tDisableBreakPt\t\t( void );           \t\t\t\r\n\t\t\t\r\n\tvoid\t\t\t\tSetGPMetric\t\t\t( GXPerf0\t\t\t\t\t\tperf0,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXPerf1\t\t\t\t\t\tperf1 );\r\n\t\t\t\r\n\tvoid\t\t\t\tClearGPMetric\t\t( void );           \t\t\t\r\n\t\t\t\r\n\tvoid\t\t\t\tReadGPMetric\t\t( u32 *\t\t\t\t\t\t\tcnt0,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32 *\t\t\t\t\t\t\tcnt1 );\r\n\t\t\t\r\n\tvoid\t\t\t\tSetDrawSync\t\t\t( u16\t\t\t\t\t\t\ttoken );\r\n\t\t\t\r\n\tu16\t\t\t\t\tReadDrawSync\t\t( void );           \t\t\t\r\n\t\t\t\r\n\tvoid\t\t\t\tSetCopyFilter\t\t( GXBool\t\t\t\t\t\taa,\r\n\t\t\t\t\t\t\t\t\t\t\t  const u8\t\t\t\t\t\tsample_pattern[12][2],\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tvf,\r\n\t\t\t\t\t\t\t\t\t\t\t  const u8\t\t\t\t\t\tvfilter[7] );\r\n\t\t\t\r\n\tvoid\t\t\t\tCopyDisp\t\t\t( void *\t\t\t\t\t\tdest,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tclear );\r\n\t\t\t\r\n\tvoid\t\t\t\tSetCopyClear\t\t( GXColor\t\t\t\t\t\tclear_clr,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tclear_z );\r\n\t\t\t\r\n\tvoid\t\t\t\tPokeZ\t\t\t\t( u16\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tz );\r\n\t\t\t\r\n\tvoid\t\t\t\tPeekZ\t\t\t\t( u16\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32 *\t\t\t\t\t\t\tz );\r\n\t\t\t\r\n\tvoid\t\t\t\tPokeARGB\t\t\t( u16\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tcolor );\r\n\t\t\t\r\n\tvoid\t\t\t\tPeekARGB\t\t\t( u16\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32 *\t\t\t\t\t\t\tcolor );\r\n\t\t\t\r\n\tvoid\t\t\t\tSetClipMode\t\t\t( GXClipMode\t\t\t\t\tmode );\r\n\t\t\t\r\n\tvoid\t\t\t\tSetZCompLoc\t\t\t( GXBool\t\t\t\t\t\tbefore_tex );\r\n\t\t\t\r\n\tvoid\t\t\t\tSetPixelFmt\t\t\t( GXPixelFmt\t\t\t\t\tpix_fmt,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXZFmt16\t\t\t\t\t\tz_fmt );\r\n\t\t\t\r\n\tGXFifoObj *\t\t\tInit\t\t\t\t( void *\t\t\t\t\t\tbase,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tsize );\r\n\t\r\n\tvoid\t\t\t\tAdjustForOverscan\t( const GXRenderModeObj *\t\trmin,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXRenderModeObj *\t\t\t\trmout,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\thor,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\tver );\r\n\t\r\n\tvoid\t\t\t\tSetViewport\t\t\t( f32\t\t\t\t\t\t\tleft,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\ttop,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\twd,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tht,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tnearz,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tfarz );\r\n\t\r\n\tvoid\t\t\t\tSetDispCopySrc\t\t( u16\t\t\t\t\t\t\tleft,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\ttop,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\twd,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\tht );\r\n\t\r\n\tvoid\t\t\t\tSetDispCopyDst\t\t( u16\t\t\t\t\t\t\twd,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\tht );\r\n\t\r\n\tu32\t\t\t\t\tSetDispCopyYScale\t( f32\t\t\t\t\t\t\tvscale );\r\n\t\r\n\tvoid\t\t\t\tSetVtxAttrFmt\t\t( GXVtxFmt\t\t\t\t\t\tvtxfmt,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXAttr\t\t\t\t\t\tattr,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXCompCnt\t\t\t\t\t\tcnt,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXCompType\t\t\t\t\ttype,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8\t\t\t\t\t\t\tfrac );\r\n\t\r\n\tvoid\t\t\t\tSetViewportJitter\t( f32\t\t\t\t\t\t\tleft,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\ttop,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\twd,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tht,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tnearz,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tfarz,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tfield );\r\n\t\r\n\tvoid\t\t\t\tInvalidateVtxCache\t( void );                   \t\r\n\t\r\n\tvoid\t\t\t\tInvalidateTexAll\t( void );                   \t\r\n\t\r\n\tvoid\t\t\t\tSetDrawSync\t\t\t( u16\t\t\t\t\t\t\ttoken );\r\n\t\r\n\tu16\t\t\t\t\tReadDrawSync\t\t( void );                   \t\r\n\t\r\n\tGXDrawSyncCallback\tSetDrawSyncCallback\t( GXDrawSyncCallback\t\t\tcb );\r\n\t\r\n\tvoid\t\t\t\tDrawDone\t\t\t( void );                   \t\r\n\r\n\tvoid\t\t\t\tAbortFrame\t\t\t( void );\r\n\t\r\n\tvoid\t\t\t\tSetDrawDone\t\t\t( void );                   \t\r\n\t\r\n\tvoid\t\t\t\tWaitDrawDone\t\t( void );                   \t\r\n\t\r\n\tGXDrawDoneCallback\tSetDrawDoneCallback\t( GXDrawDoneCallback\t\t\tcb );\r\n\t\r\n\tvoid\t\t\t\tReadXfRasMetric\t\t( u32 *\t\t\t\t\t\t\txf_wait_in,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32 *\t\t\t\t\t\t\txf_wait_out,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32 *\t\t\t\t\t\t\tras_busy,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32 *\t\t\t\t\t\t\tclocks );\r\n\t\r\n\tvoid\t\t\t\tGetGPStatus\t\t\t( GXBool *\t\t\t\t\t\toverhi,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool *\t\t\t\t\t\tunderlow,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool *\t\t\t\t\t\treadIdle,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool *\t\t\t\t\t\tcmdIdle,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool *\t\t\t\t\t\tbrkpt );\r\n\t\r\n\tvoid\t\t\t\tGetFifoStatus\t\t( GXFifoObj *\t\t\t\t\tfifo,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool *\t\t\t\t\t\toverhi,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool *\t\t\t\t\t\tunderlow,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32 *\t\t\t\t\t\t\tfifoCount,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool *\t\t\t\t\t\tcpu_write,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool *\t\t\t\t\t\tgp_read,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool *\t\t\t\t\t\tfifowrap );\r\n\t\r\n\tvoid *\t\t\t\tGetFifoBase\t\t\t( const GXFifoObj *\t\t\t\tfifo );\r\n\t\r\n\tu32\t\t\t\t\tGetFifoSize\t\t\t( const GXFifoObj *\t\t\t\tfifo );\r\n\t\r\n\tvoid\t\t\t\tGetFifoLimits\t\t( const GXFifoObj *\t\t\t\tfifo,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32 *\t\t\t\t\t\t\thi,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32 *\t\t\t\t\t\t\tlo );\r\n\r\n\tu32\t\t\t\t\tGetOverflowCount\t( void );\r\n\r\n\tu32\t\t\t\t\tResetOverflowCount\t( void );\r\n\r\n\tvoid\t\t\t\tEnableHang\t\t\t( void );\r\n\r\n\tvoid\t\t\t\tDisableHang\t\t\t( void );\r\n\r\n\tvoid\t\t\t\tResolveDLTexAddr\t( NxNgc::sTextureDL *\t\t\tp_dl,\r\n\t\t\t\t\t\t\t\t\t\t\t  NxNgc::sMaterialPassHeader *\tp_pass,\r\n\t\t\t\t\t\t\t\t\t\t\t  int\t\t\t\t\t\t\tnum_passes );\r\n\r\n\tvoid\t\t\t\tChangeMaterialColor\t( unsigned char *\t\t\t\tp_dl,\r\n\t\t\t\t\t\t\t\t\t\t\t  unsigned int\t\t\t\t\tsize,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXColor\t\t\t\t\t\tcolor,\r\n\t\t\t\t\t\t\t\t\t\t\t  int\t\t\t\t\t\t\tpass );\r\n\r\n\tvoid\t\t\t\tSetTexCopySrc\t\t( u16\t\t\t\t\t\t\tleft,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\ttop,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\twd,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\tht );\r\n\r\n\tvoid\t\t\t\tSetTexCopyDst\t\t( u16\t\t\t\t\t\t\twd,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\tht,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXTexFmt\t\t\t\t\t\tfmt,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tmipmap );\r\n\r\n\tvoid\t\t\t\tCopyTex\t\t\t\t( void *\t\t\t\t\t\tdest,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tclear );\r\n\r\n\tvoid\t\t\t\tPixModeSync\t\t\t( void );\r\n\r\n\tvoid\t\t\t\tPokeAlphaUpdate\t\t( GXBool\t\t\t\t\t\tupdate_enable );\r\n\r\n\tvoid\t\t\t\tPokeColorUpdate\t\t( GXBool\t\t\t\t\t\tupdate_enable );\r\n\r\n\tvoid\t\t\t\tGetProjectionv\t\t( f32 *\t\t\t\t\t\t\tp );\r\n\r\n\tvoid\t\t\t\tSetProjectionv\t\t( const f32 *\t\t\t\t\tptr );\r\n\r\n\tvoid\t\t\t\tGetViewportv\t\t( f32 *\t\t\t\t\t\t\tviewport );\r\n\r\n\tvoid\t\t\t\tGetScissor\t\t\t( u32 *\t\t\t\t\t\t\tleft,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32 *\t\t\t\t\t\t\ttop,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32 *\t\t\t\t\t\t\twidth,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32 *\t\t\t\t\t\t\theight );\r\n\r\n\tvoid\t\t\t\tProject\t\t\t\t( f32\t\t\t\t\t\t\tx,          // model coordinates\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tz,\r\n\t\t\t\t\t\t\t\t\t\t\t  const f32\t\t\t\t\t\tmtx[3][4],  // model-view matrix\r\n\t\t\t\t\t\t\t\t\t\t\t  const f32 *\t\t\t\t\tpm,         // projection matrix, as returned by GXGetProjectionv\r\n\t\t\t\t\t\t\t\t\t\t\t  const f32 *\t\t\t\t\tvp,         // viewport, as returned by GXGetViewportv\r\n\t\t\t\t\t\t\t\t\t\t\t  f32 *\t\t\t\t\t\t\tsx,         // screen coordinates\r\n\t\t\t\t\t\t\t\t\t\t\t  f32 *\t\t\t\t\t\t\tsy,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32 *\t\t\t\t\t\t\tsz );\r\n\r\n\tvoid\t\t\t\tSetArray\t\t\t( GXAttr \t\t\t\t\t\tattr,\r\n\t\t\t\t\t\t\t\t\t\t\t  const void *\t\t\t\t\tbase_ptr,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8 \t\t\t\t\t\t\tstride );\r\n\r\n\tvoid\t\t\t\tInitLightAttn\t\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\ta0,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\ta1,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\ta2,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tk0,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tk1,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tk2 );\r\n\r\n\tvoid\t\t\t\tInitLightAttnA\t\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\ta0,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\ta1,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\ta2 );\r\n\r\n\tvoid\t\t\t\tInitLightAttnK\t\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tk0,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tk1,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tk2 );\r\n\r\n\tvoid\t\t\t\tInitLightSpot\t\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tcutoff,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXSpotFn\t\t\t\t\t\tspot_func );\r\n\r\n\tvoid\t\t\t\tInitLightDistAttn\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tref_distance,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tref_brightness,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXDistAttnFn\t\t\t\t\tdist_func );\r\n\r\n\tvoid\t\t\t\tInitLightPos\t\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tx,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\ty,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tz );\r\n\r\n\tvoid\t\t\t\tInitLightColor\t\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXColor\t\t\t\t\t\tcolor );\r\n\r\n\tvoid\t\t\t\tLoadLightObjImm\t\t( const GXLightObj *\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXLightID\t\t\t\t\t\tlight );\r\n\r\n\tvoid\t\t\t\tLoadLightObjIndx\t( u32\t\t\t\t\t\t\tlt_obj_indx,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXLightID\t\t\t\t\t\tlight );\r\n\r\n\tvoid\t\t\t\tInitLightDir\t\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tnx,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tny,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tnz );\r\n\r\n\tvoid\t\t\t\tInitSpecularDir\t\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tnx,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tny,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tnz );\r\n\r\n\tvoid\t\t\t\tInitSpecularDirHA\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tnx,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tny,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\tnz,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\thx,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\thy,\r\n\t\t\t\t\t\t\t\t\t\t\t  f32\t\t\t\t\t\t\thz );\r\n\r\n\tvoid\t\t\t\tInitLightPosv\t\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  Vec *\t\t\t\t\t\t\tp );\r\n\r\n\tvoid\t\t\t\tInitLightDirv\t\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  Vec *\t\t\t\t\t\t\tn );\r\n\r\n\tvoid\t\t\t\tInitSpecularDirv\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  Vec *\t\t\t\t\t\t\tn );\r\n\r\n\tvoid\t\t\t\tInitSpecularDirHAv\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  Vec *\t\t\t\t\t\t\tn,\r\n\t\t\t\t\t\t\t\t\t\t\t  Vec *\t\t\t\t\t\t\th );\r\n\r\n\tvoid\t\t\t\tInitLightShininess\t( GXLightObj *\t\t\t\t\tlt_obj,\r\n\t\t\t\t\t\t\t\t\t\t\t  float\t\t\t\t\t\t\tshininess );\r\n\r\n\tvoid\t\t\t\tCallDisplayList\t\t( const void *\t\t\t\t\tlist,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tnbytes );\r\n\r\n\tvoid\t\t\t\tResetGX\t\t\t\t( void );\r\n\r\n\tu32\t\t\t\t\tGetTexBufferSize\t( u16\t\t\t\t\t\t\twidth,\r\n\t\t\t\t\t\t\t\t\t\t\t  u16\t\t\t\t\t\t\theight,\r\n\t\t\t\t\t\t\t\t\t\t\t  u32\t\t\t\t\t\t\tformat,\r\n\t\t\t\t\t\t\t\t\t\t\t  GXBool\t\t\t\t\t\tmipmap,\r\n\t\t\t\t\t\t\t\t\t\t\t  u8\t\t\t\t\t\t\tmax_lod );\r\n\r\n}\r\n\r\n#endif\t\t// _GX_H_\r\n\r\n#ifndef _GX2_H_\r\n#define _GX2_H_\r\n\r\nnamespace NxNgc\r\n{\r\n\r\n#ifdef __PLAT_WN32__\r\ntypedef NxTexture sTexture;\r\n#endif\t\t// __PLAT_WN32__\r\n\r\nstruct sMaterialDL\r\n{\r\n\tuint32\tm_dl_size;\r\n\tvoid *\tmp_dl;\r\n};\r\n\r\nstruct sMeshMod\r\n{\r\n\tMth::Vector\toffset;\r\n\tMth::Vector\tscale;\r\n};\r\n\r\nstruct sTextureDL\r\n{\r\n\tuint32\tm_dl_size;\r\n\tvoid *\tmp_dl;\r\n\tint16\tm_tex_offset[4];\r\n\tint16\tm_alpha_offset[4];\r\n};\r\n\r\nstruct sMaterialHeader\r\n{\r\n\tuint32\tm_checksum;\r\n\tuint8\tm_passes;\r\n\tuint8\tm_alpha_cutoff;\r\n\tuint8\tm_flags;\r\n\tuint8\tm_base_blend;\t\t//m_material_dl_id;\r\n\tfloat\tm_draw_order;\r\n\tuint16\tm_pass_item;\r\n\tuint16\tm_texture_dl_id;\r\n\tfloat\tm_shininess;\r\n\tGXColor\tm_specular_color;\r\n\r\n\tuint32\tm_materialNameChecksum;\r\n\tuint32\tm_layer_id;\r\n};\r\n\r\nstruct sMaterialUVWibble\r\n{\r\n\tfloat\tm_u_vel;\r\n\tfloat\tm_v_vel;\r\n\tfloat\tm_u_freq;\r\n\tfloat\tm_v_freq;\r\n\tfloat\tm_u_amp;\r\n\tfloat\tm_v_amp;\r\n\tfloat\tm_u_phase;\r\n\tfloat\tm_v_phase;\r\n};\r\n\r\nstruct sMaterialPassHeader\r\n{\r\n\tunion {\r\n\t\tuint32\t\tchecksum;\r\n\t\tsTexture *\tp_data;\r\n\t} m_texture;\r\n\tuint8\tm_flags;\r\n\tuint8\tm_filter;\r\n\tuint8\tm_blend_mode;\r\n\tuint8\tm_alpha_fix;\r\n\tuint32\tm_uv_wibble_index;\r\n\tGXColor\tm_color;\r\n\r\n\ts16\t\tm_k;\t//float\tm_mip_k;\r\n\ts16\t\tm_u_tile;\r\n\ts16\t\tm_v_tile;\r\n\ts8\t\tm_pad;\r\n\ts8\t\tm_uv_enabled;\r\n\r\n\ts16\t\tm_uv_mat[4];\r\n};\r\n\r\nstruct sMaterialVCWibbleKeyHeader\r\n{\r\n\tint\t\tm_num_frames;\r\n\tint\t\tm_phase;\r\n};\r\n\r\nstruct sMaterialVCWibbleKey\r\n{\r\n\tint\t\tm_time;\r\n\tGXColor\tm_color;\r\n};\r\n\r\nstruct sSceneHeader\r\n{\r\n\tuint32 m_num_pos;\r\n\tuint16 m_pad;\r\n\tuint16 m_num_nrm;\r\n\tuint16 m_num_col;\r\n\tuint16 m_num_tex;\r\n\tuint32 m_num_pool_bytes;\r\n\tuint16 m_num_objects;\r\n\tuint16 m_num_materials;\r\n\tuint32 m_num_shadow_faces;\r\n\tuint16 m_num_blend_dls;\r\n\tuint16 m_num_vc_wibbles;\r\n\tuint16 m_num_uv_wibbles;\r\n\tuint16 m_num_pass_items;\r\n};\r\n\r\nstruct sObjectHeader\r\n{\r\n\tuint16\t\tm_num_meshes;                   // 2\r\n\tuint16\t\tm_billboard_type;               // 2\r\n\tunion {                         \t\t\t        \t\r\n\t\tint\t\tnum_bytes;\t\t\t\t\t\t// 4\r\n\t\tvoid *\tp_data;\r\n\t} m_skin;\r\n\tuint16\t\tm_num_skin_verts;\t\t\t\t// 2\r\n\tuint16\t\tm_num_double_lists;\t\t\t\t// 2\r\n\tuint8\t\tm_num_single_lists;\t\t\t\t// 1\r\n\tuint8\t\tm_num_add_lists;\t\t\t\t// 1\r\n\tuint16\t\tm_bone_index;\t\t\t\t\t// 2\r\n\tMth::Vector\tm_origin;                       // 16\r\n\tMth::Vector\tm_axis;                         // 16\r\n\tMth::Vector\tm_sphere;\t\t\t\t\t\t// 16\r\n};\r\n\r\nstruct sShadowEdge\r\n{\r\n\tshort neighbor[3];\r\n};\r\n\r\nstruct sDLHeader\r\n{\r\n\t// 32 bytes.\r\n\tuint32 \t\t\t\t\tm_size;\t\t\t\t// 4\r\n\tunion {                                 \t\r\n\t\tuint32\t\t\t\tchecksum;\t\t\t// 4\r\n\t\tsMaterialHeader *\tp_header;       \t\r\n\t} m_material;                           \t\r\n\tuint32\t\t\t\t\tm_flags;            // 4\r\n\tuint32\t\t\t\t\tm_checksum;         // 4\r\n\t\r\n\t// 32 bytes.                            \t\r\n\tMth::Vector\t\t\t\tm_sphere;\t\t\t// 16\r\n\tNxNgc::sObjectHeader *\tmp_object_header;\t// 4\r\n\tuint16\t\t\t\t\tm_index_offset;\t\t// 2 - Offset into DL where index data starts.\r\n\tuint16\t\t\t\t\tm_index_stride;\t\t// 2 - Stride of index data (pos always 1st).\r\n\tuint16\t\t\t\t\tm_num_indices;\t\t// 2 - Number of indices in this DL.\r\n\tuint8\t\t\t\t\tm_color_offset;\t\t// 1 - Offset of color index.\r\n\tuint8\t\t\t\t\tm_correctable;\t\t// 1 - Mesh is color correctable?\r\n\tuint32\t\t\t\t\tm_mesh_index;\t\t// 4 - Mesh index within object.\r\n\tuint32\t\t\t\t\tm_original_dl_size;\t// 4 - Same as m_size until hide_mesh has been run.\r\n//\tuint32\t\t\t\t\tm_matrix_index;\t\t// 4 - Typically 0 for env. Skinned/hierarchical will use this (skinned will use it if all verts are single weight, single matrix).\r\n\tfloat *\t\t\t\t\tmp_pos_pool;\t\t// 4 - Modified pos pool\r\n\tuint32\t\t\t\t\tm_array_base;\t\t// 4 - 0 unless pool is bigger than 65536.\r\n\tuint32 *\t\t\t\tmp_col_pool;        // 4 - Modified col pool\r\n//\tuint32\t\t\t\t\tm_pad;           \t// 4\r\n//\tuint32\t\t\t\t\tm_pad[2];           // 8\r\n\r\n\r\n\r\n//\tuint32\t\t\t\t\tm_num_skin_verts;\t// 4\r\n//\tunion {                                 \t\r\n//\t\tint\t\t\t\t\tnum_bytes;\t\t\t// 4\r\n//\t\tvoid *\t\t\t\tp_data;\r\n//\t} m_skin;\r\n//\tuint32\t\t\t\t\tm_num_single_lists;\t// 4\r\n//\tuint32\t\t\t\t\tm_num_double_lists;\t// 4\r\n//\tuint32\t\t\t\t\tm_num_add_lists;\t// 4\r\n};\r\n\r\nvoid multi_mesh( NxNgc::sMaterialHeader * p_mat, NxNgc::sMaterialPassHeader * p_base_pass, bool bl = true, bool tx = true, bool should_correct_color = false, bool cull = false );\r\n}\r\n\r\n#endif\t\t// _GX2_H_\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_hashid.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPrim\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tProvides functionality for drawing various types of single\t\t*\r\n// *\t\t\t\tprimitives to the display.\t\t\t\t\t\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include <math.h>\r\n//#include \"p_hashid.h\"\r\n//#include \"p_assert.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n////static u32 crcTable[] =\r\n////{ \r\n////\t0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,\r\n////\t0x076dc419, 0x706af48f,\t0xe963a535, 0x9e6495a3,\r\n////\t0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,\r\n////\t0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,\r\n////\t0x1db71064, 0x6ab020f2,\t0xf3b97148, 0x84be41de,\r\n////\t0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,\r\n////\t0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,\r\n////\t0x14015c4f, 0x63066cd9,\t0xfa0f3d63, 0x8d080df5,\r\n////\t0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,\r\n////\t0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,\r\n////\t0x35b5a8fa, 0x42b2986c,\t0xdbbbc9d6, 0xacbcf940,\r\n////\t0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,\r\n////\t0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,\r\n////\t0x21b4f4b5, 0x56b3c423,\t0xcfba9599, 0xb8bda50f,\r\n////\t0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,\r\n////\t0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,\r\n////\t0x76dc4190, 0x01db7106,\t0x98d220bc, 0xefd5102a,\r\n////\t0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,\r\n////\t0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,\r\n////\t0x7f6a0dbb, 0x086d3d2d,\t0x91646c97, 0xe6635c01,\r\n////\t0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,\r\n////\t0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,\r\n////\t0x65b0d9c6, 0x12b7e950,\t0x8bbeb8ea, 0xfcb9887c,\r\n////\t0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,\r\n////\t0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,\r\n////\t0x4adfa541, 0x3dd895d7,\t0xa4d1c46d, 0xd3d6f4fb,\r\n////\t0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,\r\n////\t0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,\r\n////\t0x5005713c, 0x270241aa,\t0xbe0b1010, 0xc90c2086,\r\n////\t0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\r\n////\t0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,\r\n////\t0x59b33d17, 0x2eb40d81,\t0xb7bd5c3b, 0xc0ba6cad,\r\n////\t0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,\r\n////\t0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,\r\n////\t0xe3630b12, 0x94643b84,\t0x0d6d6a3e, 0x7a6a5aa8,\r\n////\t0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,\r\n////\t0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,\r\n////\t0xf762575d, 0x806567cb,\t0x196c3671, 0x6e6b06e7,\r\n////\t0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,\r\n////\t0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,\r\n////\t0xd6d6a3e8, 0xa1d1937e,\t0x38d8c2c4, 0x4fdff252,\r\n////\t0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\r\n////\t0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,\r\n////\t0xdf60efc3, 0xa867df55,\t0x316e8eef, 0x4669be79,\r\n////\t0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,\r\n////\t0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,\r\n////\t0xc5ba3bbe, 0xb2bd0b28,\t0x2bb45a92, 0x5cb36a04,\r\n////\t0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,\r\n////\t0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,\r\n////\t0x9c0906a9, 0xeb0e363f,\t0x72076785, 0x05005713,\r\n////\t0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,\r\n////\t0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,\r\n////\t0x86d3d2d4, 0xf1d4e242,\t0x68ddb3f8, 0x1fda836e,\r\n////\t0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,\r\n////\t0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,\r\n////\t0x8f659eff, 0xf862ae69,\t0x616bffd3, 0x166ccf45,\r\n////\t0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,\r\n////\t0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,\r\n////\t0xaed16a4a, 0xd9d65adc,\t0x40df0b66, 0x37d83bf0,\r\n////\t0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\r\n////\t0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,\r\n////\t0xbad03605, 0xcdd70693,\t0x54de5729, 0x23d967bf,\r\n////\t0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,\r\n////\t0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d\r\n////};\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tencode\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\ta 32-bit encoded hashID.\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tEncode a hashID from a text string.\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//u32\tNsHashID::encode ( const char * pString )\r\n//{\r\n////\tu32 crc;\r\n////\r\n////\tcrc = 0;\r\n////\r\n////\twhile ( *pString ) crc = crcTable[ ( crc ^ ( *pString++) ) & 0xff ] ^ ( crc >> 8 );\r\n////\r\n////\treturn crc;\r\n//\tassertf( false, ( \"No longer available\" ) );\r\n//\treturn 0;\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tencode\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\ta 32-bit encoded hashID.\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tEncode a hashID from an arbitrary piece of data.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//u32\tNsHashID::encode ( const unsigned char * pData, unsigned int length )\r\n//{\r\n////\tu32 crc;\r\n////\r\n////\tcrc = 0;\r\n////\r\n////\twhile ( length > 0 ) {\r\n////\t\tcrc = crcTable[ ( crc ^ ( *pData++) ) & 0xff ] ^ ( crc >> 8 );\r\n////\t\t--length;\r\n////\t}\r\n////\treturn crc;\r\n//\r\n//\tassertf( false, ( \"No longer available\" ) );\r\n//\treturn 0;\r\n//}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_hashid.h",
    "content": "//#ifndef _HASHID_H_\r\n//#define _HASHID_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//\r\n//namespace NsHashID\r\n//{\r\n//\tu32\tencode ( const char * pString );\r\n//\tu32\tencode ( const unsigned char * pData, unsigned int length );\r\n//};\r\n//\r\n//#endif\t\t// _HASHID_H_\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_hw.h",
    "content": "/*---------------------------------------------------------------------------*\r\n  Project:  Dolphin hw library\r\n  File:     hw.h\r\n\r\n  Copyright 1998-2001 Nintendo.  All rights reserved.\r\n\r\n  These coded instructions, statements, and computer programs contain\r\n  proprietary information of Nintendo of America Inc. and/or Nintendo\r\n  Company Ltd., and are protected by Federal copyright law.  They may\r\n  not be disclosed to third parties or copied or duplicated in any form,\r\n  in whole or in part, without the prior written consent of Nintendo.\r\n\r\n  $Log: /Dolphin/include/hw.h $\r\n    \r\n    27    8/22/01 7:20p Carl\r\n    BypassWorkaround is now GPHangWorkaround.\r\n    Added DEMOSetGPHangMetric for hang diagnosis.\r\n    \r\n    26    5/09/01 10:10p Hirose\r\n    moved hwPad/hwPuts/hwStat definitions into each individual header\r\n    file.\r\n    \r\n    25    5/03/01 4:17p Tian\r\n    Restored static inline changes\r\n    \r\n    24    01/04/25 14:28 Shiki\r\n    Revised ROM font API interface. Added hwGetTextWidth().\r\n\r\n    23    01/04/25 11:28 Shiki\r\n    Added hwSetFontSize().\r\n\r\n    22    01/04/19 13:37 Shiki\r\n    Added ROM font functions.\r\n\r\n    20    3/23/01 12:03p John\r\n    Added stdio.h include to compensate for loss of geoPalette.h.\r\n\r\n    19    3/22/01 2:38p John\r\n    Removed geoPalette.h include (unnecessary).\r\n\r\n    18    01/03/22 21:45 Shiki\r\n    Removed hw_PAD_CHECK_INTERVAL.\r\n\r\n    17    11/28/00 8:18p Hirose\r\n    Enhancement of hwStat library\r\n    Fixed hwSetTevOp definition for the emulator\r\n\r\n    16    11/27/00 4:57p Carl\r\n    Added hwSetTevColorIn and hwSetTevOp.\r\n\r\n    15    10/26/00 10:31a Tian\r\n    Added hwReInit and hwEnableBypassWorkaround.  Automatically repairs\r\n    graphics pipe after a certain framecount based timeout.\r\n\r\n    14    7/21/00 1:48p Carl\r\n    Removed hwDoneRenderBottom.\r\n    Added hwSwapBuffers.\r\n\r\n    13    6/20/00 10:37a Alligator\r\n    added texture bandwidth, texture miss rate calculations\r\n\r\n    12    6/19/00 3:23p Alligator\r\n    added fill rate virtual counter\r\n\r\n    11    6/12/00 4:32p Hirose\r\n    updated hwPad library structures\r\n\r\n    10    6/12/00 1:46p Alligator\r\n    updated hw statistics to support new api\r\n\r\n    9     6/06/00 12:02p Alligator\r\n    made changes to perf counter api\r\n\r\n    8     6/05/00 1:53p Carl\r\n    Added hwDoneRenderBottom\r\n\r\n    7     5/18/00 2:56a Alligator\r\n    added hwStats stuff\r\n\r\n    6     5/02/00 3:28p Hirose\r\n    added prototype of hwGetCurrentBuffer\r\n\r\n    5     3/25/00 12:48a Hirose\r\n    added hw_PAD_CHECK_INTERVAL macro\r\n\r\n    4     3/23/00 1:20a Hirose\r\n    added hwPad stuff\r\n\r\n    3     1/19/00 3:43p Danm\r\n    Added GXRenderModeObj *hwGetRenderModeObj(void) function.\r\n\r\n    2     1/13/00 8:56p Danm\r\n    Added GXRenderModeObj * parameter to hwInit()\r\n\r\n    9     9/30/99 2:13p Ryan\r\n    sweep to remove gxmodels libs\r\n\r\n    8     9/28/99 6:56p Yasu\r\n    Add defines of font type\r\n\r\n    7     9/24/99 6:45p Yasu\r\n    Change type of parameter of hwSetupScrnSpc().\r\n\r\n    6     9/24/99 6:40p Yasu\r\n    Change the number of parameter of hwSetupScrnSpc()\r\n\r\n    5     9/24/99 6:35p Yasu\r\n    Add hwSetupScrnSpc()\r\n\r\n    4     9/23/99 5:35p Yasu\r\n    Change function name cmMtxScreen to hwMtxScreen\r\n\r\n    3     9/17/99 1:33p Ryan\r\n    Added hwBeforeRender and hwDoneRender\r\n\r\n    2     9/14/99 5:08p Yasu\r\n    Add some functions which contained in hwPut.c\r\n\r\n    1     7/23/99 2:36p Ryan\r\n\r\n    1     7/20/99 6:42p Alligator\r\n    new hw lib\r\n  $NoKeywords: $\r\n *---------------------------------------------------------------------------*/\r\n\r\n#ifndef __hw_H__\r\n#define __hw_H__\r\n\r\n/*---------------------------------------------------------------------------*/\r\n#include <dolphin.h>\r\n#include <charPipeline/texPalette.h>\r\n#include <stdio.h>\r\n\r\n#include <dolphin.h>\r\n#include \"p_hwpad.h\"\r\n//#include <hwPuts.h>\r\n//#include <hwStats.h>\r\n/*---------------------------------------------------------------------------*/\r\n\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\n#define DEFAULT_FIFO_SIZE (1024 * 96)\r\n\r\n/*---------------------------------------------------------------------------*\r\n    hwInit.c\r\n *---------------------------------------------------------------------------*/\r\nextern void             hwInit             ( GXRenderModeObj* mode );\r\nextern void             hwBeforeRender     ( void );\r\nextern void             hwDoneRender       ( bool clear = true );\r\nextern int\t\t\t\thwLockBackBuffer   ( void ** buf_addr, unsigned int * width, unsigned int * height );\r\nextern void\t\t\t\thwUnlockBackBuffer ( int updated );\r\nextern void             hwSwapBuffers      ( void );\r\nextern GXRenderModeObj* hwGetRenderModeObj ( void );\r\nextern void*            hwGetCurrentBuffer ( void );\r\n\r\nextern void             hwEnableGPHangWorkaround ( u32 timeoutFrames );\r\nextern void             hwReInit           ( GXRenderModeObj *mode );\r\nextern void             hwSetGPHangMetric  ( GXBool enable );\r\nextern void             hwGXInit           ( void );\r\n\r\n\r\n/*---------------------------------------------------------------------------*\r\n    hw misc\r\n *---------------------------------------------------------------------------*/\r\n\r\n// The hw versions of SetTevColorIn and SetTevOp are backwards compatible\r\n// with the Rev A versions in that the texture swap mode will be set\r\n// appropriately if one of TEXC/TEXRRR/TEXGGG/TEXBBB is selected.\r\n\r\n#if ( GX_REV == 1 || defined(EMU) )\r\nstatic inline void hwSetTevColorIn(GXTevStageID stage,\r\n                              GXTevColorArg a, GXTevColorArg b,\r\n                              GXTevColorArg c, GXTevColorArg d )\r\n    { GXSetTevColorIn(stage, a, b, c, d); }\r\n\r\nstatic inline void hwSetTevOp(GXTevStageID stage, GXTevMode mode)\r\n    { GXSetTevOp(stage, mode); }\r\n#else\r\nvoid hwSetTevColorIn(GXTevStageID stage,\r\n                       GXTevColorArg a, GXTevColorArg b,\r\n                       GXTevColorArg c, GXTevColorArg d );\r\n\r\nvoid hwSetTevOp(GXTevStageID stage, GXTevMode mode);\r\n#endif\r\n\r\n/*---------------------------------------------------------------------------*/\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n#endif // __hw_H__\r\n\r\n/*===========================================================================*/\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_hwinit.cpp",
    "content": "\t/*---------------------------------------------------------------------------*\r\n  Project:  Dolphin hw Library\r\n  File:     hwInit.c\r\n\r\n  Copyright 1998-2001 Nintendo.  All rights reserved.\r\n\r\n  These coded instructions, statements, and computer programs contain\r\n  proprietary information of Nintendo of America Inc. and/or Nintendo\r\n  Company Ltd., and are protected by Federal copyright law.  They may\r\n  not be disclosed to third parties or copied or duplicated in any form,\r\n  in whole or in part, without the prior written consent of Nintendo.\r\n\r\n  $Log: /Dolphin/build/libraries/hw/src/hwInit.c $\r\n    \r\n    52    8/24/01 6:30p Carl\r\n    Added more thorough output for GP hang diagnosis.\r\n    \r\n    51    8/22/01 8:26p Carl\r\n    BypassWorkaround is now GPHangWorkaround.\r\n    Added code for GP hang diagnosis.\r\n    \r\n    50    7/03/01 11:03a Hirose\r\n    Deleted obsolete fragment memory management system. Changed viewport\r\n    parameters to support Y-scaling modes rather than full-frame AA mode\r\n    which requires complicated settings in any case.  \r\n    \r\n    49    5/11/01 5:57p Hirose\r\n    changed default gamma correction back to 1.0.\r\n    \r\n    48    5/10/01 7:06p Carl\r\n    Added comments concerning VI-related settings.\r\n    \r\n    47    11/30/00 6:41p Tian\r\n    Fixed memory leak in hwReInit.\r\n    \r\n    46    11/27/00 4:57p Carl\r\n    Added hwSetTevColorIn and hwSetTevOp.\r\n    \r\n    45    10/28/00 5:57p Hirose\r\n    \r\n    44    10/27/00 1:47a Hirose\r\n    Simplification / Clean up. Removed obsolete flags.\r\n    \r\n    43    10/26/00 10:32a Tian\r\n    Added hwReInit and hwEnableBypassWorkaround.  When used, the\r\n    standard hwBeforeRender and hwDoneRender functions will attempt to\r\n    repair the graphics pipe after a timeout.\r\n    \r\n    42    8/27/00 5:45p Alligator\r\n    print warning messages through a callback function\r\n    \r\n    41    8/18/00 2:44p Dante\r\n    Added !defined(WIN32) directive\r\n    \r\n    40    8/08/00 4:21p Hirose\r\n    moved GXDrawDone call from hwSwapBuffers to hwDoneRender\r\n    \r\n    39    8/02/00 3:06p Tian\r\n    Allocate framebuffers from beginning of heap to avoid VI bug (FB's must\r\n    be in lower 16MB).\r\n    \r\n    38    7/21/00 1:48p Carl\r\n    Removed full-frame aa-specific code\r\n    (moved back to hw; see frb-aa-full.c).\r\n    Added hwSwapBuffers().\r\n    \r\n    37    7/18/00 7:08p Hashida\r\n    Fixed a problem that MAC build failed.\r\n    \r\n    36    7/17/00 11:59a Hashida\r\n    Added bad memory support.\r\n    \r\n    35    7/07/00 7:09p Dante\r\n    PC Compatibility\r\n    \r\n    34    6/26/00 5:43p Alligator\r\n    print stats before copy, but still include copy time, lose first\r\n    counter on first loop.\r\n    \r\n    33    6/13/00 12:03p Alligator\r\n    use hwPrintf *after* sampling stat counters\r\n    \r\n    32    6/12/00 1:46p Alligator\r\n    updated hw statistics to support new api\r\n    \r\n    31    6/07/00 10:38a Howardc\r\n    add comment about gamma correction\r\n    \r\n    30    6/05/00 1:55p Carl\r\n    Added hwDoneRenderBottom\r\n    \r\n    29    5/24/00 3:18a Carl\r\n    OddField is gone; use hwDrawField instead.\r\n    \r\n    28    5/24/00 1:02a Ryan\r\n    added default gamma setting of 1.7\r\n    \r\n    27    5/19/00 1:09p Carl\r\n    GXSetVerifyLevel needed to be #ifdef _DEBUG\r\n    \r\n    26    5/18/00 3:02a Alligator\r\n    add hwStat suff, set verify level to 0\r\n    \r\n    25    5/02/00 4:05p Hirose\r\n    added function descriptions / deleted tabs\r\n    defined some global variables as static\r\n    attached prefix to exported global variables\r\n    \r\n    24    4/07/00 5:57p Carl\r\n    Updated GXSetCopyFilter call.\r\n    \r\n    23    3/24/00 6:48p Carl\r\n    Overscan adjust no longer changes predefined modes.\r\n    \r\n    22    3/23/00 5:26p Carl\r\n    Added code to adjust for overscan.\r\n    \r\n    21    3/23/00 1:22a Hirose\r\n    changed to call hwPadInit instead of PADInit\r\n    \r\n    20    3/16/00 6:14p Danm\r\n    Cleaned up code per code review.\r\n    \r\n    19    2/29/00 5:54p Ryan\r\n    update for dvddata folder rename\r\n    \r\n    18    2/29/00 5:05p Danm\r\n    Select render mode based on TV format.\r\n    \r\n    17    2/21/00 7:56p Tian\r\n    Changed order of PAD and VI init, since PAD requires that VI be\r\n    initialized\r\n    \r\n    16    2/18/00 6:31p Carl\r\n    Changed __SINGLEFRAME #ifdefs to CSIM_OUTPUT\r\n    (__SINGLEFRAME is not applicable to library code, only test code).\r\n    Removed even/odd field #ifdefs; use OddField variable instead.\r\n    \r\n    15    2/17/00 6:08p Carl\r\n    Removed clear from GXCopyDisp at end of single-frame test\r\n    \r\n    14    2/17/00 6:03p Hashida\r\n    Changed the way to allocate frame buffer.\r\n    \r\n    13    2/14/00 6:40p Danm\r\n    Enabled GXCopyDisp in hwDoneRender.\r\n    \r\n    12    2/12/00 5:16p Alligator\r\n    Integrate ArtX source tree changes\r\n    \r\n    11    2/11/00 3:23p Danm\r\n    Chaged dst stride on GXCopyDisp from pixel stride to byte stride.\r\n    \r\n    10    2/08/00 1:50p Alligator\r\n    do copy in hwInit to clear the color and Z buffer prior to rendering\r\n    the first frame.\r\n    \r\n    9     1/28/00 10:55p Hashida\r\n    Added VIFlush().\r\n    Changed to wait for two frames after tv mode is changed.\r\n    \r\n    8     1/26/00 3:59p Hashida\r\n    Changed to use VIConfigure.\r\n    \r\n    7     1/25/00 4:12p Danm\r\n    Changed default render mode for all platforms to GXNtsc480IntDf.\r\n    \r\n    6     1/21/00 4:41p Alligator\r\n    added even/odd field select for __SINGLEFRAME field tests\r\n    \r\n    5     1/19/00 3:43p Danm\r\n    Added GXRenderModeObj *hwGetRenderModeObj(void) function.\r\n    \r\n    4     1/13/00 8:53p Danm\r\n    Added GXRenderModeObj * parameter to hwInit()\r\n    \r\n    3     1/13/00 5:55p Alligator\r\n    integrate with ArtX GX library code\r\n    \r\n    2     1/11/00 3:18p Danm\r\n    Reversed init of VI and GX for single field support\r\n    \r\n    16    11/16/99 9:43a Hashida\r\n    Moved DVDInit before using arenaLo.\r\n    \r\n    15    11/01/99 6:09p Tian\r\n    Framebuffers no longer allocated if generating CSIM output.\r\n    \r\n    14    10/13/99 4:32p Alligator\r\n    change GXSetViewport, GXSetScissor to use xorig, yorig, wd, ht\r\n    \r\n    13    10/07/99 12:14p Alligator\r\n    initialize rmode before using it in BeforeRender\r\n    \r\n    12    10/06/99 10:38a Alligator\r\n    changed enums for compressed Z format\r\n    updated Init functions to make GX_ZC_LINEAR default\r\n    \r\n    11    9/30/99 10:32p Yasu\r\n    Renamed and clean up functions and enums.\r\n    \r\n    10    9/28/99 4:14p Hashida\r\n    Moved GXCopyDisp to GXDoneRender\r\n    \r\n    9     9/23/99 3:23p Tian\r\n    New GXFifo/GXInit APIs, cleanup.\r\n    \r\n    8     9/22/99 7:08p Yasu\r\n    Fixed paramter of GXSetViewPort\r\n    \r\n    7     9/22/99 6:12p Yasu\r\n    Changed the parameters of GXSetDispCopySrc().\r\n    Fixed small bugs.\r\n    \r\n    6     9/21/99 2:33p Alligator\r\n    add aa flag, if aa set 16b pix format\r\n    \r\n    5     9/20/99 11:02a Ryan\r\n    \r\n    4     9/17/99 5:24p Ryan\r\n    commented GXCopy temporarily\r\n    \r\n    3     9/17/99 1:33p Ryan\r\n    update to include new VI API's\r\n    \r\n    2     7/28/99 4:21p Ryan\r\n    Added DVDInit() and DVDSetRoot\r\n    \r\n    1     7/20/99 6:06p Alligator\r\n  $NoKeywords: $\r\n *---------------------------------------------------------------------------*/\r\n\r\n/*---------------------------------------------------------------------------*\r\n    This hw library provides a common application\r\n    framework that is used in all the GX hws distributed\r\n    with the Dolphin SDK.\r\n *---------------------------------------------------------------------------*/\r\n\r\n\r\n#include <dolphin.h>\r\n#include \"p_hw.h\"\r\n#include <charpipeline/GQRSetup.h>\r\n#include \"libsn.h\"\r\n#include \t\"gfx\\ngc\\nx\\nx_init.h\"\r\n#include \"sys\\ngc\\p_aram.h\"\r\n#include \t\"gfx/ngc/nx/mesh.h\"\r\n#include \"sys\\ngc\\p_gx.h\"\r\n#include \"sys\\timer.h\"\r\n\r\n/*---------------------------------------------------------------------------*\r\n    External functions\r\n *---------------------------------------------------------------------------*/\r\n//extern void hwUpdateStats ( GXBool inc );\r\n//extern void hwPrintStats  ( void );\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Global variables\r\n *---------------------------------------------------------------------------*/\r\nvoid*   hwFrameBuffer1;\r\nvoid*   hwFrameBuffer2;\r\nvoid*   hwCurrentBuffer;\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Static variables\r\n *---------------------------------------------------------------------------*/\r\nstatic GXBool  hwFirstFrame = GX_TRUE;\r\n\r\n//static void*        DefaultFifo;\r\nstatic char\t\t\tDefaultFifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN(32);\r\nstatic GXFifoObj*   DefaultFifoObj;\r\n\r\nGXRenderModeObj *rmode;\r\nGXRenderModeObj rmodeobj;\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Automatic frame skipping to work around GP hang condition.\r\n *---------------------------------------------------------------------------*/\r\nstatic BOOL GPHangWorkaround = FALSE;\r\n\r\n// used to count missed frames by VI retrace callback handler\r\nstatic vu32 FrameCount;\r\nstatic u32  FrameMissThreshold; // number of frames to be considered a timeout\r\n\r\n// tokens are used instead of GXDrawDone\r\n#define hw_START_FRAME_TOKEN  0xFEEB\r\n#define hw_END_FRAME_TOKEN    0xB00B\r\n\r\n// we need to create a thread to catch hangs at high watermark (\"overflow\")\r\nstatic OSThread OVThread;               // OS data for overflow thread\r\nstatic u8       OVThreadStack[4096];    // Stack for overflow thread\r\n\r\nstatic u32 fbSize;\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Fragmented memory systems\r\n *---------------------------------------------------------------------------*/\r\ntypedef struct\r\n{\r\n    void*           start;\r\n    void*           end;\r\n} meminfo;\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Foward references\r\n *---------------------------------------------------------------------------*/\r\nstatic void __hwInitRenderMode    ( GXRenderModeObj* mode );\r\nstatic void __hwInitMem           ( void );\r\nstatic void __hwInitGX            ( void );\r\nstatic void __hwInitVI            ( void );\r\n//static void __hwInitForEmu        ( void );\r\n\r\nstatic void __NoHangRetraceCallback ( u32 count );\r\nstatic void __NoHangDoneRender      ( void );\r\n\r\nstatic void  __hwDiagnoseHang     ( void );\r\nstatic void* __hwOverflowThread   ( void* param );\r\n\r\n\r\n/*---------------------------------------------------------------------------*\r\n   Functions\r\n *---------------------------------------------------------------------------*/\r\n\r\n/*===========================================================================*\r\n\r\n\r\n    Initialization\r\n\r\n\r\n *===========================================================================*/\r\n\r\nextern int resetDown;\r\n\r\nvoid reset_callback( void )\r\n{\r\n\tresetDown = 1;\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwInit\r\n    \r\n    Description:    This function initializes the components of\r\n                    the operating system and its device drivers.\r\n                    The mode parameter allows the application to\r\n                    override the default render mode. It then allocates\r\n                    all of main memory except the area for external\r\n                    framebuffer into a heap than can be managed\r\n                    with OSAlloc. This function initializes the video\r\n                    controller to run at 640x480 interlaced display,\r\n                    with 60Hz refresh (actually, 640x448; see below).\r\n    \r\n    Arguments:      mode  : render mode\r\n                            Default render mode will be used when\r\n                            NULL is given as this argument.\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nvoid hwInit( GXRenderModeObj *mode )\r\n{\r\n    /*----------------------------------------------------------------*\r\n     *  Initialize OS                                                 *\r\n     *----------------------------------------------------------------*/\r\n    OSInit();\r\n\r\n    /*----------------------------------------------------------------*\r\n     *  Initialize DVD                                                *\r\n     *   (need to initialize DVD BEFORE program uses                  *\r\n     *   arena because DVDInit might change arena lo.)                *\r\n     *----------------------------------------------------------------*/\r\n    DVDInit();\r\n\r\n    /*----------------------------------------------------------------*\r\n     *  Initialize VI                                                 *\r\n     *----------------------------------------------------------------*/\r\n    VIInit();\r\n\r\n    /*----------------------------------------------------------------*\r\n     *  Initialize game PAD (PADInit is called by hwPadInit)        *\r\n     *----------------------------------------------------------------*/\r\n    hwPadInit();\r\n\r\n    /*----------------------------------------------------------------*\r\n     *  Set up rendering mode                                         *\r\n     *  (which reflects the GX/VI configurations and XFB size below)  *\r\n     *----------------------------------------------------------------*/\r\n    __hwInitRenderMode(mode);\r\n\r\n    /*----------------------------------------------------------------*\r\n     *  Initialize memory configuration (framebuffers / heap)         *\r\n     *----------------------------------------------------------------*/\r\n    __hwInitMem();\r\n\r\n    /*----------------------------------------------------------------*\r\n     *  Configure VI by given render mode                             *\r\n     *----------------------------------------------------------------*/\r\n    VIConfigure(rmode);\r\n\r\n    /*----------------------------------------------------------------*\r\n     *  Initialize Graphics                                           *\r\n     *----------------------------------------------------------------*/\r\n    // Alloc default 256K fifo\r\n//    DefaultFifo     = OSAlloc(DEFAULT_FIFO_SIZE);\r\n    DefaultFifoObj  = GX::Init(DefaultFifo, DEFAULT_FIFO_SIZE);\r\n    \r\n    // Configure GX\r\n    __hwInitGX();\r\n\r\n    /*----------------------------------------------------------------*\r\n     *  Emulator only initialization portion                          *\r\n     *----------------------------------------------------------------*/\r\n#ifdef EMU\r\n    __hwInitForEmu();\r\n#endif\r\n\r\n    /*----------------------------------------------------------------*\r\n     *  Start up VI                                                   *\r\n     *----------------------------------------------------------------*/\r\n    __hwInitVI();\r\n\r\n    // Creates a new thread in order to diagnose hangs during high watermark.\r\n    // The thread is suspended by default.\r\n    OSCreateThread(\r\n        &OVThread,                          // ptr to the thread obj to init\r\n        __hwOverflowThread,                 // ptr to the start routine\r\n        0,                                  // param passed to start routine\r\n        OVThreadStack+sizeof(OVThreadStack),// initial stack address\r\n        sizeof(OVThreadStack),\r\n        31,                                 // scheduling priority (low)\r\n        OS_THREAD_ATTR_DETACH);             // detached by default\r\n\r\n    OSResumeThread(&OVThread);    // Allow the thread to run\r\n\r\n    GQRSetup6( GQR_SCALE_64,\t\t// Pos\r\n               GQR_TYPE_S16,\r\n\t\t\t   GQR_SCALE_64,\r\n               GQR_TYPE_S16 );\r\n    GQRSetup7( 14,\t\t// Normal\r\n               GQR_TYPE_S16,\r\n               14,\r\n               GQR_TYPE_S16 );\r\n\r\n//\thwEnableGPHangWorkaround( 60 );\r\n\r\n\r\n//\tstatic unsigned long profdata[2048]; // long aligned,\r\n//\t// 4K to 64K bytes\r\n//\tif(snProfInit(_4KHZ, profdata, sizeof(profdata)) != 0)\r\n//\tprintf(\"Profiler init failed\\n\"); // see SN_PRF in LIBSN.H\r\n//\t// rest of user code follows on from here...\r\n\r\n\tOSSetResetCallback( reset_callback );\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           __hwInitRenderMode\r\n    \r\n    Description:    This function sets up rendering mode which configures\r\n                    GX and VI. If mode == NULL, this function use a default\r\n                    rendering mode according to the TV format.\r\n    \r\n    Arguments:      None\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nstatic void __hwInitRenderMode( GXRenderModeObj* mode )\r\n{\r\n    // If an application specific render mode is provided,\r\n    // override the default render mode\r\n    if (mode != NULL) \r\n    {\r\n        rmode = mode;\r\n    }\r\n    else\r\n    {\r\n\t\trmode = &GXNtsc480IntDf;\r\n\r\n        // Trim off from top & bottom 16 scanlines (which will be overscanned).\r\n        // So almost all hws actually render only 448 lines (in NTSC case.)\r\n        // Since this setting is just for SDK hws, you can specify this\r\n        // in order to match your application requirements.\r\n        GX::AdjustForOverscan(rmode, &rmodeobj, 0, 16);\r\n        \r\n        rmode = &rmodeobj;\r\n\r\n\t\tOSReport( \"TV format: %d\\n\", VIGetTvFormat() );\r\n\r\n        switch (VIGetTvFormat())\r\n        {\r\n\t\t\tcase VI_NTSC:\r\n\t\t\t\tif ( NxNgc::EngineGlobals.use_480p )\r\n\t\t\t\t{\r\n\t\t\t\t\trmode->viTVmode = VI_TVMODE_NTSC_PROG;\r\n\t\t\t\t\trmode->xFBmode = VI_XFBMODE_SF;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase VI_PAL:\r\n\t\t\tcase VI_EURGB60:\r\n\t\t\tcase VI_DEBUG_PAL:\r\n\t\t\t\tif ( rmode->viTVmode == VI_TVMODE_NTSC_INT )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( NxNgc::EngineGlobals.use_60hz )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\trmode->viTVmode = VI_TVMODE_EURGB60_INT;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\trmode->viTVmode = VI_TVMODE_PAL_INT;\r\n\t\t\t\t\t\trmode->viYOrigin = 23;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( NxNgc::EngineGlobals.use_60hz )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\trmode->viTVmode = VI_TVMODE_EURGB60_DS;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\trmode->viTVmode = VI_TVMODE_PAL_DS;\r\n\t\t\t\t\t\trmode->viYOrigin = 23;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif ( NxNgc::EngineGlobals.use_60hz )\r\n\t\t\t\t{\r\n\t\t\t\t\trmode->xfbHeight = 448;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\trmode->xfbHeight = ( rmode->xfbHeight * 528 ) / 448;\r\n\t\t\t\t\trmode->viHeight = 528;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase VI_MPAL:\r\n\t\t\t\trmode = &GXMpal480IntDf;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\t//OSHalt(\"hwInit: invalid TV format\\n\");\r\n\t\t\t\tbreak;\r\n        }\r\n\r\n\t\t// Nintendo's recommended settings.\r\n\t\trmode->viWidth = 650;\r\n\t\trmode->viXOrigin = 35;\r\n   }\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           __hwInitMem\r\n    \r\n    Description:    This function allocates external framebuffers from\r\n                    arena and sets up a heap\r\n   \r\n    Arguments:      None\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nstatic void __hwInitMem( void )\r\n{\r\n    void*    arenaLo;\r\n    void*    arenaHi;\r\n\r\n    arenaLo = OSGetArenaLo();\r\n    arenaHi = OSGetArenaHi();\r\n\r\n\r\n    /*----------------------------------------------------------------*\r\n     *  Allocate external framebuffers                                *\r\n     *----------------------------------------------------------------*/\r\n\r\n    // In HW1, we should allocate the buffers at the beginning of arena (<16MB)\r\n    // Need to do this before OSInitAlloc is called.\r\n    fbSize = VIPadFrameBufferWidth(rmode->fbWidth) * rmode->xfbHeight * \r\n        (u32)VI_DISPLAY_PIX_SZ;\r\n    hwFrameBuffer1 = (void*)OSRoundUp32B((u32)arenaLo);\r\n    hwFrameBuffer2 = (void*)OSRoundUp32B((u32)hwFrameBuffer1 + fbSize);\r\n    hwCurrentBuffer = hwFrameBuffer2;\r\n    \r\n    arenaLo = (void*)OSRoundUp32B((u32)hwFrameBuffer2 + fbSize);\r\n    OSSetArenaLo(arenaLo);\r\n\r\n//    /*----------------------------------------------------------------*\r\n//     *  Create a heap                                                 *\r\n//     *----------------------------------------------------------------*/\r\n//\r\n//    // OSInitAlloc should only ever be invoked once.\r\n//    arenaLo = OSGetArenaLo();\r\n//    arenaHi = OSGetArenaHi();\r\n//    arenaLo = OSInitAlloc(arenaLo, arenaHi, 1); // 1 heap\r\n//    OSSetArenaLo(arenaLo);\r\n//\r\n//    // Ensure boundaries are 32B aligned\r\n//    arenaLo = (void*)OSRoundUp32B(arenaLo);\r\n//    arenaHi = (void*)OSRoundDown32B(arenaHi);\r\n//\t\t\t\t   \t\r\n//    // The boundaries given to OSCreateHeap should be 32B aligned\r\n//    OSSetCurrentHeap(OSCreateHeap(arenaLo, arenaHi));\r\n//    // From here on out, OSAlloc and OSFree behave like malloc and free\r\n//    // respectively\r\n//    OSSetArenaLo(arenaLo=arenaHi);\r\n\r\n    /*----------------------------------------------------------------*\r\n     *  Allocate ARAM buffers                                         *\r\n     *----------------------------------------------------------------*/\r\n\r\n    ARInit(NULL, 0);\r\n\tARQInit();\r\n\tAIInit( NULL );\r\n\tAXInit();\r\n\tAXSetMode( AX_MODE_DPL2 );\r\n    AXSetCompressor( AX_COMPRESSOR_OFF );\r\n\tNsARAM::init();\r\n\r\n\t// Allocate the 1st 1024 bytes for our own use.\r\n\tNxNgc::EngineGlobals.aram_zero = NsARAM::alloc( aram_zero_size );\r\n\r\n\t// Allocate 2.8mb for the DSP data.\r\n\tNxNgc::EngineGlobals.aram_dsp = NsARAM::alloc( aram_dsp_size );\r\n\r\n\t// Allocate 32k each for the 3 streams.\r\n\tNxNgc::EngineGlobals.aram_stream0 = NsARAM::alloc( aram_stream0_size );\r\n\tNxNgc::EngineGlobals.aram_stream1 = NsARAM::alloc( aram_stream1_size );\r\n\tNxNgc::EngineGlobals.aram_stream2 = NsARAM::alloc( aram_stream2_size );\r\n\r\n\t// Allocate 32k for the music buffer.\r\n\tNxNgc::EngineGlobals.aram_music = NsARAM::alloc( aram_music_size );\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           __hwInitGX\r\n    \r\n    Description:    This function performs GX configuration by using\r\n                    current rendering mode\r\n   \r\n    Arguments:      None\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nstatic void __hwInitGX( void )\r\n{\r\n    /*----------------------------------------------------------------*\r\n     *  GX configuration by a render mode obj                         *\r\n     *----------------------------------------------------------------*/\r\n\r\n    // These are all necessary function calls to take a render mode\r\n    // object and set up the relevant GX configuration.\r\n\r\n    GX::SetViewport(0.0F, 0.0F, (f32)rmode->fbWidth, (f32)rmode->efbHeight, \r\n                  0.0F, 1.0F);\r\n    GX::SetScissor(0, 0, (u32)rmode->fbWidth, (u32)rmode->efbHeight);\r\n    GX::SetDispCopySrc(0, 0, rmode->fbWidth, rmode->efbHeight);\r\n    GX::SetDispCopyDst(rmode->fbWidth, rmode->xfbHeight);\r\n    \r\n\tGX::SetDispCopyYScale((f32)(rmode->xfbHeight) / (f32)(rmode->efbHeight)); \r\n\r\n    GX::SetCopyFilter(rmode->aa, rmode->sample_pattern, GX_TRUE, rmode->vfilter);\r\n\r\n    // Note that following is an appropriate setting for full-frame AA mode.\r\n    // You should use \"xfbHeight\" instead of \"efbHeight\" to specify actual\r\n    // view size. Since this library doesn't support such special case, please\r\n    // call these in each application to override the normal setting.\r\n#if 0\r\n    GX::SetViewport(0.0F, 0.0F, (f32)rmode->fbWidth, (f32)rmode->xfbHeight, \r\n                  0.0F, 1.0F);\r\n    GX::SetDispCopyYScale(1.0F);\r\n#endif\r\n\r\n\tif (rmode->aa)\r\n\t{\r\n        GX::SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR);\r\n\t}\r\n    else\r\n\t{\r\n        GX::SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);\r\n//        GX::SetPixelFmt(/*GX_PF_RGB8_Z24*/GX_PF_RGBA6_Z24, GX_ZC_LINEAR);\r\n//\t\tGXSetPixelFmt(/*GX_PF_RGB8_Z24*/GX_PF_RGBA6_Z24, GX_ZC_LINEAR);\r\n\t}\r\n\r\n\r\n    /*----------------------------------------------------------------*\r\n     *  Miscellaneous GX initialization for hws                     *\r\n     *  (Since these are not actually necessary for all applications, *\r\n     *  you may remove them if you feel they are unnecessary.)        *\r\n     *----------------------------------------------------------------*/\r\n\r\n    // Clear embedded framebuffer for the first frame\r\n    GX::CopyDisp(hwCurrentBuffer, GX_TRUE);\r\n\r\n    // Verify (warning) messages are turned off by default\r\n#ifdef _DEBUG\r\n//    GXSetVerifyLevel(GX_WARN_NONE);\r\n\tGXSetVerifyLevel(GX_WARN_NONE);\r\n#endif\r\n\r\n    // Gamma correction\r\n    //\r\n    // You may want to use 1.7 or 2.2 if all artwork made on PCs\r\n    // become darker. However, recommended setting is 1.0.\r\n    GX::SetDispCopyGamma(GX_GM_1_0);\r\n\r\n\t// 2D Primitives.\r\n    GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );\r\n\r\n\r\n\r\n\r\n//#ifdef SHORT_VERT\r\n//\t// Environment geometry. 1=1.\r\n//\tGX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_S16, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );\r\n//\r\n//\t// Environment geometry. 1=2.\r\n//\tGX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_POS, GX_POS_XYZ, GX_S16, 1 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );\r\n//\r\n//\t// Environment geometry. 1=4.\r\n//\tGX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_S16, 2 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );\r\n//\r\n//\t// Environment geometry. 1=8.\r\n//\tGX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_POS, GX_POS_XYZ, GX_S16, 3 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );\r\n//\r\n//\t// Environment geometry. 1=16.\r\n//\tGX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_POS, GX_POS_XYZ, GX_S16, 4 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );\r\n//\r\n//\t// Environment geometry. 1=32.\r\n//\tGX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_POS, GX_POS_XYZ, GX_S16, 5 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );\r\n//#else\r\n//\t// Environment/skinned geometry. 1=64.\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );\r\n//#endif\t\t// SHORT_VERT\r\n//\t// Environment/skinned geometry. 1=64.\r\n//\tGX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );\r\n//    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );\r\n\tGX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );\r\n\r\n\t// Environment.\r\n    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX1, GX_TEX_ST, GX_S16, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX2, GX_TEX_ST, GX_S16, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX3, GX_TEX_ST, GX_S16, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX4, GX_TEX_ST, GX_S16, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX5, GX_TEX_ST, GX_S16, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX6, GX_TEX_ST, GX_S16, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX7, GX_TEX_ST, GX_S16, 0 );\r\n\r\n    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX0, GX_TEX_ST, GX_S16, 2 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX1, GX_TEX_ST, GX_S16, 2 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX2, GX_TEX_ST, GX_S16, 2 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX3, GX_TEX_ST, GX_S16, 2 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX4, GX_TEX_ST, GX_S16, 2 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX5, GX_TEX_ST, GX_S16, 2 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX6, GX_TEX_ST, GX_S16, 2 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX7, GX_TEX_ST, GX_S16, 2 );\r\n\r\n    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX0, GX_TEX_ST, GX_S16, 4 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX1, GX_TEX_ST, GX_S16, 4 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX2, GX_TEX_ST, GX_S16, 4 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX3, GX_TEX_ST, GX_S16, 4 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX4, GX_TEX_ST, GX_S16, 4 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX5, GX_TEX_ST, GX_S16, 4 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX6, GX_TEX_ST, GX_S16, 4 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX7, GX_TEX_ST, GX_S16, 4 );\r\n\r\n    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX0, GX_TEX_ST, GX_S16, 6 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX1, GX_TEX_ST, GX_S16, 6 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX2, GX_TEX_ST, GX_S16, 6 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX3, GX_TEX_ST, GX_S16, 6 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX4, GX_TEX_ST, GX_S16, 6 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX5, GX_TEX_ST, GX_S16, 6 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX6, GX_TEX_ST, GX_S16, 6 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX7, GX_TEX_ST, GX_S16, 6 );\r\n\r\n    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX0, GX_TEX_ST, GX_S16, 8 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX1, GX_TEX_ST, GX_S16, 8 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX2, GX_TEX_ST, GX_S16, 8 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX3, GX_TEX_ST, GX_S16, 8 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX4, GX_TEX_ST, GX_S16, 8 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX5, GX_TEX_ST, GX_S16, 8 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX6, GX_TEX_ST, GX_S16, 8 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX7, GX_TEX_ST, GX_S16, 8 );\r\n\r\n    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX0, GX_TEX_ST, GX_S16, 10 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX1, GX_TEX_ST, GX_S16, 10 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX2, GX_TEX_ST, GX_S16, 10 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX3, GX_TEX_ST, GX_S16, 10 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX4, GX_TEX_ST, GX_S16, 10 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX5, GX_TEX_ST, GX_S16, 10 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX6, GX_TEX_ST, GX_S16, 10 );\r\n    GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX7, GX_TEX_ST, GX_S16, 10 );\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           __hwInitVI\r\n    \r\n    Description:    This function performs VI start up settings that are\r\n                    necessary at the beginning of each hw\r\n    \r\n    Arguments:      None\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nstatic void __hwInitVI( void )\r\n{\r\n    u32 nin;\r\n\r\n    // Double-buffering initialization\r\n    VISetNextFrameBuffer(hwFrameBuffer1);\r\n    hwCurrentBuffer = hwFrameBuffer2;\r\n\r\n    // Tell VI device driver to write the current VI settings so far\r\n    VIFlush();\r\n    \r\n    // Wait for retrace to start first frame\r\n    VIWaitForRetrace();\r\n\r\n    // Because of hardware restriction, we need to wait one more \r\n    // field to make sure mode is safely changed when we change\r\n    // INT->DS or DS->INT. (VIInit() sets INT mode as a default)\r\n    nin = (u32)rmode->viTVmode & 1;\r\n    if (nin)\r\n        VIWaitForRetrace();\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           __hwInitForEmu\r\n    \r\n    Description:    This function performs emulator only portion of\r\n                    initialization.\r\n    \r\n    Arguments:      None\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\n//static void __hwInitForEmu( void )\r\n//{\r\n//    // Set up DVDRoot\r\n//#ifdef MACOS\r\n//    DVDSetRoot(\"DOLPHIN/dvddata/\");\r\n//#endif\r\n//\r\n//#ifdef WIN32\r\n//\tunsigned char path[270] = \"\";\r\n//\tstrcat(path, installPath);\r\n//\tstrcat(path, \"/dvddata\");\r\n//\tDVDSetRoot(path);\r\n//#endif\r\n//}\r\n\r\n\r\n\r\n/*===========================================================================*\r\n\r\n\r\n    Basic hw framework control functions\r\n\r\n\r\n *===========================================================================*/\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwBeforeRender\r\n    \r\n    Description:    This function sets up the viewport to render the\r\n                    appropriate field if field rendering is enabled.\r\n                    Field rendering is a property of the render mode.\r\n    \r\n    Arguments:      None\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nvoid hwBeforeRender( void )\r\n{\r\n\r\n#ifndef EMU\r\n    if (GPHangWorkaround)\r\n    {\r\n        // This will overwrite the end frame token from the previous frame.\r\n        GX::SetDrawSync( hw_START_FRAME_TOKEN);\r\n\r\n        // Reset the counters for post-hang diagnosis.\r\n        GX::ClearGPMetric();\r\n    }\r\n#endif // !EMU\r\n    \r\n\r\n    // Set up viewport (This is inappropriate for full-frame AA.)\r\n    if (rmode->field_rendering)\r\n    {\r\n        GX::SetViewportJitter(\r\n          0.0F, 0.0F, (float)rmode->fbWidth, (float)rmode->efbHeight, \r\n          0.0F, 1.0F, VIGetNextField());\r\n    }\r\n    else\r\n    {\r\n        GX::SetViewport(\r\n          0.0F, 0.0F, (float)rmode->fbWidth, (float)rmode->efbHeight, \r\n          0.0F, 1.0F);\r\n    }\r\n    \r\n    // Invalidate vertex cache in GP\r\n    GX::InvalidateVtxCache();\r\n\r\n#ifndef EMU\r\n    // Invalidate texture cache in GP\r\n    GX::InvalidateTexAll();\r\n#endif // !EMU\r\n\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwDoneRender\r\n    \r\n    Description:    This function copies the embedded frame buffer (EFB)\r\n                    to the external frame buffer (XFB) via GXCopyDisp,\r\n                    and then calls hwSwapBuffers.\r\n    \r\n    Arguments:      None\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nvoid hwDoneRender( bool clear )\r\n{\r\n    // GP hang workaround version (Turned off by default)\r\n    if (GPHangWorkaround)\r\n    {\r\n//        ASSERTMSG(!hwStatEnable,\r\n//                  \"DEMOStats and GP hang diagnosis are mutually exclusive\");\r\n        __NoHangDoneRender();\r\n        return;\r\n    }\r\n\r\n    // Statistics support (Turned off by default)\r\n//    if (hwStatEnable)\r\n//    {\r\n//        GXDrawDone();             // make sure data through pipe\r\n//        hwUpdateStats(GX_TRUE); // sample counters here\r\n//        hwPrintStats();         // don't include time to print stats\r\n//        GXDrawDone();             // make sure data through pipe\r\n//        hwUpdateStats(GX_FALSE); // reset counters here, include copy time\r\n//    }\r\n\r\n    // Set Z/Color update to make sure eFB will be cleared at GXCopyDisp.\r\n    // (If you want to control these modes by yourself in your application,\r\n    //  please comment out this part.)\r\n    GX::SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);\r\n    \r\n    // Issue display copy command\r\n    GX::CopyDisp( hwCurrentBuffer, ( clear ) ? GX_TRUE : GX_FALSE );\r\n\r\n    // Wait until everything is drawn and copied into XFB.\r\n    GX::DrawDone();        \r\n\r\n    // Set the next frame buffer\r\n    hwSwapBuffers();\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:            RADDEMOLockBackBuffer\r\n\r\n    Description:    This function returns the back buffer info, so that you\r\n                    can write right into it.\r\n *---------------------------------------------------------------------------*/\r\nint hwLockBackBuffer( void ** buf_addr, unsigned int * width, unsigned int * height )\r\n{\r\n  if ( buf_addr )\r\n    *buf_addr = hwCurrentBuffer;\r\n  if ( width )\r\n    *width = rmode->fbWidth;\r\n  if ( height )\r\n    *height = rmode->xfbHeight;\r\n  return( 1 );\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:            RADDEMOUnlockBackBuffer\r\n\r\n    Description:    This function returns the back buffer info, so that you\r\n                    can write right into it.\r\n *---------------------------------------------------------------------------*/\r\nvoid hwUnlockBackBuffer( int updated )\r\n{\r\n  if ( updated )\r\n  {\r\n    DCStoreRange( hwCurrentBuffer, fbSize );\r\n  }\r\n}\r\n\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwSwapBuffers\r\n    \r\n    Description:    This function finishes copying via GXDrawDone, sets\r\n                    the next video frame buffer, waits for vertical\r\n                    retrace, and swaps internal rendering buffers.\r\n    \r\n    Arguments:      None\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nvoid hwSwapBuffers( void )\r\n{\r\n    // Display the buffer which was just filled by GXCopyDisplay\r\n    VISetNextFrameBuffer(hwCurrentBuffer);\r\n\r\n    // If this is the first frame, turn off VIBlack\r\n    if(hwFirstFrame)\r\n    {\r\n        VISetBlack(FALSE);\r\n        hwFirstFrame = GX_FALSE;\r\n    }\r\n    \r\n    // Tell VI device driver to write the current VI settings so far\r\n    VIFlush();\r\n    \r\n    // Wait for vertical retrace.\r\n//    VIWaitForRetrace();\r\n\tTmr::VSync1();\r\n\r\n    // Swap buffers\r\n    if(hwCurrentBuffer == hwFrameBuffer1)\r\n        hwCurrentBuffer = hwFrameBuffer2;\r\n    else\r\n        hwCurrentBuffer = hwFrameBuffer1;\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwSetTevColorIn\r\n    \r\n    Description:    This function is a Rev A compatible version of\r\n                    GXSetTevColorIn.  It will set the swap mode if\r\n                    one of TEXC/TEXRRR/TEXGGG/TEXBBB is selected.\r\n\r\n                    It doesn't error check for multiple swaps, however.\r\n\r\n                    Note that it is available for Rev A or Rev B.\r\n                    For Rev A, it is defined as an inline in hw.h.\r\n    \r\n    Arguments:      Same as GXSetTevColorIn\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\n#if ( GX_REV > 1 )\r\nvoid hwSetTevColorIn(GXTevStageID stage,\r\n                       GXTevColorArg a, GXTevColorArg b,\r\n                       GXTevColorArg c, GXTevColorArg d )\r\n{\r\n//    u32 swap = 0;\r\n//\r\n//    if (a == GX_CC_TEXC)\r\n//        { swap = GX_CC_TEXRRR - 1;  }\r\n//    else if (a >= GX_CC_TEXRRR)\r\n//        { swap = a; a = GX_CC_TEXC; }\r\n//\r\n//    if (b == GX_CC_TEXC)\r\n//        { swap = GX_CC_TEXRRR - 1;  }\r\n//    else if (b >= GX_CC_TEXRRR)\r\n//        { swap = b; b = GX_CC_TEXC; }\r\n//\r\n//    if (c == GX_CC_TEXC)\r\n//        { swap = GX_CC_TEXRRR - 1;  }\r\n//    else if (c >= GX_CC_TEXRRR)\r\n//        { swap = c; c = GX_CC_TEXC; }\r\n//\r\n//    if (d == GX_CC_TEXC)\r\n//        { swap = GX_CC_TEXRRR - 1;  }\r\n//    else if (d >= GX_CC_TEXRRR)\r\n//        { swap = d; d = GX_CC_TEXC; }\r\n//\r\n//    GXSetTevColorIn(stage, a, b, c, d);\r\n//\r\n//    if (swap > 0)\r\n//      GXSetTevSwapMode(stage, GX_TEV_SWAP0,\r\n//                       (GXTevSwapSel)(swap - GX_CC_TEXRRR + 1));\r\n}\r\n#endif\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwSetTevOp\r\n    \r\n    Description:    This function is a Rev-A compatible version of\r\n                    GXSetTevOp.  It will set the swap mode if\r\n                    GX_CC_TEXC is selected for an input.\r\n\r\n                    Note that it is available for Rev A or Rev B.\r\n                    For Rev A, it is defined as an inline in hw.h.\r\n    \r\n    Arguments:      Same as GXSetTevOp\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\n#if ( GX_REV > 1 )\r\n//void hwSetTevOp(GXTevStageID id, GXTevMode mode)\r\n//{\r\n//    GXTevColorArg carg = GX_CC_RASC;\r\n//    GXTevAlphaArg aarg = GX_CA_RASA;\r\n//\r\n//    if (id != GX_TEVSTAGE0) {\r\n//        carg = GX_CC_CPREV;\r\n//        aarg = GX_CA_APREV;\r\n//    }\r\n//\r\n//    switch (mode) {\r\n//      case GX_MODULATE:\r\n//        hwSetTevColorIn(id, GX_CC_ZERO, GX_CC_TEXC, carg, GX_CC_ZERO);\r\n//        GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_TEXA, aarg, GX_CA_ZERO);\r\n//        break;\r\n//      case GX_DECAL:\r\n//        hwSetTevColorIn(id, carg, GX_CC_TEXC, GX_CC_TEXA, GX_CC_ZERO);\r\n//        GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, aarg);\r\n//        break;\r\n//      case GX_BLEND:\r\n//        hwSetTevColorIn(id, carg, GX_CC_ONE, GX_CC_TEXC, GX_CC_ZERO);\r\n//        GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_TEXA, aarg, GX_CA_ZERO);\r\n//        break;\r\n//      case GX_REPLACE:\r\n//        hwSetTevColorIn(id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);\r\n//        GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA);\r\n//        break;\r\n//      case GX_PASSCLR:\r\n//        hwSetTevColorIn(id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, carg);\r\n//        GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, aarg);\r\n//        break;\r\n//      default:\r\n//        ASSERTMSG(0, \"hwSetTevOp: Invalid Tev Mode\");\r\n//        break;\r\n//    }\r\n//\r\n//    GXSetTevColorOp(id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);\r\n//    GXSetTevAlphaOp(id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);\r\n//}\r\n#endif\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwGetRenderModeObj\r\n    \r\n    Description:    This function returns the current rendering mode.\r\n                    It is most useful to inquire what the default\r\n                    rendering mode is.\r\n    \r\n    Arguments:      None\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nGXRenderModeObj* hwGetRenderModeObj( void )\r\n{\r\n    return rmode;\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwGetCurrentBuffer\r\n    \r\n    Description:    This function returns the pointer to external\r\n                    framebuffer currently active. Since this library\r\n                    swiches double buffer hwFrameBuffer1/hwFrameBuffer2,\r\n                    the returned pointer will be one of them.\r\n    \r\n    Arguments:      None\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nvoid* hwGetCurrentBuffer( void )\r\n{\r\n    return hwCurrentBuffer;\r\n}\r\n\r\n\r\n\r\n/*===========================================================================*\r\n\r\n\r\n    GP hang work-around auto-recovery system\r\n\r\n\r\n *===========================================================================*/\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwEnableGPHangWorkaround\r\n    \r\n    Description:    Sets up the DEMO library to skip past any GP hangs and\r\n                    attempt to repair the graphics pipe whenever a timeout\r\n                    of /timeoutFrames/ occurs.  This will serve as a\r\n                    temporary work-around for any GP hangs that may occur.\r\n\r\n    \r\n    Arguments: timeoutFrames        The number of 60hz frames to wait in\r\n                                    hwDoneRender before aborting the\r\n                                    graphics pipe.  Should be at least\r\n                                    equal to your standard frame rate\r\n                                    (e.g. 60hz games should use a value of 1,\r\n                                    30hz games should use a value of 2)\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nvoid hwEnableGPHangWorkaround ( u32 timeoutFrames )\r\n{\r\n#ifdef EMU\r\n    #pragma unused (timeoutFrames)\r\n#else\r\n    if (timeoutFrames)\r\n    {\r\n//        ASSERTMSG(!hwStatEnable,\r\n//                  \"DEMOStats and GP hang diagnosis are mutually exclusive\");\r\n        GPHangWorkaround = TRUE;\r\n        FrameMissThreshold = timeoutFrames;\r\n        VISetPreRetraceCallback( __NoHangRetraceCallback );\r\n\r\n        // Enable counters for post-hang diagnosis\r\n        hwSetGPHangMetric( GX_TRUE );\r\n    }\r\n    else\r\n    {\r\n        GPHangWorkaround = FALSE;\r\n        FrameMissThreshold = 0;\r\n        hwSetGPHangMetric( GX_FALSE );\r\n        VISetPreRetraceCallback( NULL );\r\n    }\r\n#endif\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           __NoHangRetraceCallback\r\n    \r\n    Description:    VI callback to count missed frames for GPHangWorkaround\r\n    \r\n    Arguments:      Unused\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nstatic void __NoHangRetraceCallback ( u32 count )\r\n{\r\n//    #pragma unused (count)\r\n    FrameCount++;\r\n}\r\n\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           __NoHangDoneRender\r\n    \r\n    Description:    Called in lieu of the standard hwDoneRender if \r\n                    GPHangWorkaround == TRUE.\r\n\r\n                    Uses a token to check for end of frame so that we can\r\n                    also count missed frames at the same time.\r\n    \r\n    Arguments:      None\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nstatic void __NoHangDoneRender()\r\n{\r\n    BOOL abort = FALSE;\r\n    GX::CopyDisp(hwCurrentBuffer, GX_TRUE);\r\n    GX::SetDrawSync( hw_END_FRAME_TOKEN );\r\n    \r\n    FrameCount = 0;\r\n\r\n    while( (GX::ReadDrawSync() != hw_END_FRAME_TOKEN ) && !abort )\r\n    {\r\n        if (FrameCount >= FrameMissThreshold)\r\n        {\r\n            OSReport(\"---------WARNING : ABORTING FRAME----------\\n\");\r\n            abort = TRUE;\r\n            __hwDiagnoseHang();\r\n            hwReInit(rmode); // XXX RMODE?\r\n            // re-enable counters for post-hang diagnosis\r\n            hwSetGPHangMetric( GX_TRUE );\r\n        }\r\n    }\r\n    \r\n    hwSwapBuffers();\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwSetGPHangMetric\r\n    \r\n    Description:    Sets up the GP performance counters in such a way to\r\n                    enable us to detect the cause of a GP hang.  Note that\r\n                    this takes over the performance counters, and you cannot\r\n                    use GXSetGPMetric or GXInitXFRasMetric while you have\r\n                    hwSetGPHangMetric enabled.\r\n    \r\n    Arguments:      enable:  set to GX_TRUE to enable the counters.\r\n                             set to GX_FALSE to disable the counters.\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nvoid hwSetGPHangMetric( GXBool enable )\r\n{\r\n#ifdef EMU\r\n    #pragma unused (enable)\r\n#else\r\n    if (enable)\r\n    {\r\n        // Ensure other counters are off\r\n        GX::SetGPMetric( GX_PERF0_NONE, GX_PERF1_NONE );\r\n\r\n\t\tGX::EnableHang();\r\n\t}\r\n    else\r\n    {\r\n\t\tGX::DisableHang();\r\n    }\r\n#endif\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           __hwDiagnoseHang\r\n    \r\n    Description:    Reads performance counters (which should have been set\r\n                    up appropriately already) in order to determine why the\r\n                    GP hung.  The counters must be set as follows:\r\n\r\n                    GXSetGPHangMetric( GX_TRUE );\r\n    \r\n                    The above call actually sets up multiple counters, which\r\n                    are read using a non-standard method.\r\n\r\n    Arguments:      None\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nstatic void __hwDiagnoseHang()\r\n{\r\n    u32 xfTop0, xfBot0, suRdy0, r0Rdy0;\r\n    u32 xfTop1, xfBot1, suRdy1, r0Rdy1;\r\n    u32 xfTopD, xfBotD, suRdyD, r0RdyD;\r\n    GXBool readIdle, cmdIdle, junk;\r\n\r\n    // Read the counters twice in order to see which are changing.\r\n    // This method of reading the counters works in this particular case.\r\n    // You should not use this method to read GPMetric counters.\r\n    GX::ReadXfRasMetric( &xfBot0, &xfTop0, &r0Rdy0, &suRdy0 );\r\n    GX::ReadXfRasMetric( &xfBot1, &xfTop1, &r0Rdy1, &suRdy1 );\r\n\r\n    // XF Top & Bot counters indicate busy, others indicate ready.\r\n    // Convert readings into indications of who is ready/idle.\r\n    xfTopD = (xfTop1 - xfTop0) == 0;\r\n    xfBotD = (xfBot1 - xfBot0) == 0;\r\n    suRdyD = (suRdy1 - suRdy0) > 0;\r\n    r0RdyD = (r0Rdy1 - r0Rdy0) > 0;\r\n\r\n    // Get CP status\r\n    GX::GetGPStatus(&junk, &junk, &readIdle, &cmdIdle, &junk);\r\n\r\n    OSReport(\"GP status %d%d%d%d%d%d --> \",\r\n             readIdle, cmdIdle, xfTopD, xfBotD, suRdyD, r0RdyD);\r\n\r\n    // Depending upon which counters are changing, diagnose the hang.\r\n    // This may not be 100% conclusive, but it's what we've observed so far.\r\n    if (!xfBotD && suRdyD)\r\n    {\r\n        OSReport(\"GP hang due to XF stall bug.\\n\");\r\n    }\r\n    else if (!xfTopD && xfBotD && suRdyD)\r\n    {\r\n        OSReport(\"GP hang due to unterminated primitive.\\n\");\r\n    }\r\n    else if (!cmdIdle && xfTopD && xfBotD && suRdyD)\r\n    {\r\n        OSReport(\"GP hang due to illegal instruction.\\n\");\r\n    }\r\n    else if (readIdle && cmdIdle && xfTopD && xfBotD && suRdyD && r0RdyD)\r\n    {\r\n        OSReport(\"GP appears to be not hung (waiting for input).\\n\");\r\n    }\r\n    else\r\n    {\r\n        OSReport(\"GP is in unknown state.\\n\");\r\n    }\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           __hwOverflowThread\r\n    \r\n    Description:    This thread is designed to detect a hang when the main\r\n                    thread is suspended due to the high watermark interrupt.\r\n                    If the GP hangs during this time, it is not typically\r\n                    recoverable.  However, we can still diagnose it.\r\n    \r\n    Arguments:      None\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nvoid* __hwOverflowThread( void* param )\r\n{\r\n//    #pragma unused (param)\r\n    GXBool overhi, junk;\r\n    u32 count;\r\n    OSTick tick1, tick2;\r\n\r\n    // There are at least two reasons why this thread may run:\r\n    // 1.  Main thread suspended during high watermark.\r\n    // 2.  Main thread suspended during GXDrawDone.\r\n    // Low watermark and GP finish can suspend this thread.\r\n\r\n    while (1)\r\n    {\r\n        // Wait for an overflow (hit to high watermark) to occur.\r\n        do \r\n        {\r\n            GX::GetGPStatus(&overhi, &junk, &junk, &junk, &junk);\r\n        }\r\n        while (!overhi);\r\n        \r\n        // If GP hang workaround is off, don't do anything.\r\n        if (!FrameMissThreshold)\r\n        {\r\n            continue;\r\n        }\r\n\r\n        // Get a reading for this overflow and the current tick.\r\n        count = GX::GetOverflowCount();\r\n        tick1 = OSGetTick();\r\n        \r\n        // Wait until either we time-out or until the next overflow.\r\n        // One frame is approximately 17 milliseconds.\r\n        do {\r\n            tick2 = OSGetTick();\r\n        } while (\r\n            OSTicksToMilliseconds(tick2 - tick1) < FrameMissThreshold * 17 &&\r\n            count == GX::GetOverflowCount() );\r\n\r\n        // Exiting the above loop does not imply a hang.\r\n        // We must check the overflow status once more to be certain.\r\n        GX::GetGPStatus(&overhi, &junk, &junk, &junk, &junk);\r\n\r\n        // If a new overflow started, then start timing again from the top.\r\n        if (!overhi || count != GX::GetOverflowCount())\r\n        {\r\n            continue;\r\n        }\r\n        \r\n        // We timed out.  Report and diagnose the hang.\r\n        OSReport(\"---------WARNING : HANG AT HIGH WATERMARK----------\\n\");\r\n\r\n        __hwDiagnoseHang();\r\n        \r\n        // We cannot easily recover from this situation.  Halt program.\r\n        OSHalt(\"Halting program\");\r\n    }\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwReInit\r\n    \r\n    Description:    Re-initializes the graphics pipe.  Makes no assumptions \r\n                    about the Fifo (allowing you to change it in your program\r\n                    if needed).  \r\n    \r\n    Arguments:      mode   render mode object\r\n    \r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nvoid hwReInit( GXRenderModeObj *mode )\r\n{\r\n    // If an application specific render mode is provided,\r\n    // override the default render mode\r\n    if (mode != NULL) \r\n    {\r\n        rmode = mode;\r\n    }\r\n    else\r\n    {\r\n\t\trmode = &GXNtsc480IntDf;\r\n\r\n        // Trim off from top & bottom 16 scanlines (which will be overscanned).\r\n        // So almost all hws actually render only 448 lines (in NTSC case.)\r\n        // Since this setting is just for SDK hws, you can specify this\r\n        // in order to match your application requirements.\r\n        GX::AdjustForOverscan(rmode, &rmodeobj, 0, 16);\r\n        \r\n        rmode = &rmodeobj;\r\n\r\n\t\tOSReport( \"TV format: %d\\n\", VIGetTvFormat() );\r\n\r\n\t\tswitch (VIGetTvFormat())\r\n\t\t{\r\n\t\t\tcase VI_NTSC:\r\n\t\t\t\tif ( NxNgc::EngineGlobals.use_480p )\r\n\t\t\t\t{\r\n\t\t\t\t\trmode->viTVmode = VI_TVMODE_NTSC_PROG;\r\n\t\t\t\t\trmode->xFBmode = VI_XFBMODE_SF;\r\n\t\t\t\t}\r\n\t\t\tbreak;\r\n\t\t  case VI_PAL:\r\n\t\t\t  if ( rmode->viTVmode == VI_TVMODE_NTSC_INT )\r\n\t\t\t  {\r\n\t\t\t\t  if ( NxNgc::EngineGlobals.use_60hz )\r\n\t\t\t\t  {\r\n\t\t\t\t\t  rmode->viTVmode = VI_TVMODE_EURGB60_INT;\r\n\t\t\t\t  }\r\n\t\t\t\t  else\r\n\t\t\t\t  {\r\n\t\t\t\t\t  rmode->viTVmode = VI_TVMODE_PAL_INT;\r\n\t\t\t\t\t  rmode->viYOrigin = 23;\r\n\t\t\t\t  }\r\n\t\t\t  }\r\n\t\t\t  else\r\n\t\t\t  {\r\n\t\t\t\t  if ( NxNgc::EngineGlobals.use_60hz )\r\n\t\t\t\t  {\r\n\t\t\t\t\t  rmode->viTVmode = VI_TVMODE_EURGB60_DS;\r\n\t\t\t\t  }\r\n\t\t\t\t  else\r\n\t\t\t\t  {\r\n\t\t\t\t\t  rmode->viTVmode = VI_TVMODE_PAL_DS;\r\n\t\t\t\t\t  rmode->viYOrigin = 23;\r\n\t\t\t\t  }\r\n\t\t\t  }\r\n\t\t\t  if ( NxNgc::EngineGlobals.use_60hz )\r\n\t\t\t  {\r\n\t\t\t\t  rmode->xfbHeight = 448;\r\n\t\t\t  }\r\n\t\t\t  else\r\n\t\t\t  {\r\n\t\t\t\t  rmode->xfbHeight = ( rmode->xfbHeight * 528 ) / 448;\r\n\t\t\t\t  rmode->viHeight = 528;\r\n\t\t\t  }\r\n\t\t\tbreak;\r\n\t\t  case VI_MPAL:\r\n\t\t\t  rmode = &GXMpal480IntDf;\r\n\t\t\tbreak;\r\n\t\t  default:\r\n\t\t\tOSHalt(\"hwInit: invalid TV format\\n\");\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\trmode->viWidth = 650;\r\n\t\trmode->viXOrigin = 35;\r\n\t\r\n\t\tVIConfigure(rmode);\r\n\t\t__hwInitVI();\r\n\t}\r\n\r\n\r\n\r\n//    // Create a temporary FIFO while the current one is reset\r\n//    GXFifoObj   tmpobj;\r\n//    char*       tmpFifo = new char[64*1024];\r\n//\r\n//    // Get data on current Fifo.\r\n//    GXFifoObj*  realFifoObj = GXGetCPUFifo();\r\n//    void*   realFifoBase = GXGetFifoBase(realFifoObj);\r\n//    u32     realFifoSize = GXGetFifoSize(realFifoObj);\r\n//    \r\n//    // Abort the GP\r\n//    GXAbortFrame();\r\n//  \r\n//    GXInitFifoBase( &tmpobj, tmpFifo, 64*1024);\r\n//    \r\n//    GXSetCPUFifo(&tmpobj);\r\n//    GXSetGPFifo(&tmpobj);    \r\n//\r\n//    /*----------------------------------------------------------------*\r\n//     *  Initialize Graphics again\r\n//     *----------------------------------------------------------------*/\r\n//    __hwInitRenderMode(mode);\r\n//\r\n//    // This will re-initialize the pointers for the original FIFO.\r\n//    DefaultFifoObj  = GXInit(realFifoBase, realFifoSize);\r\n//\r\n//    __hwInitGX();\r\n//    \r\n//    // NOTE: the VI settings do not necessarily have to be reset, but\r\n//    //       just to be safe, we do so anyway\r\n//    VIConfigure(rmode);\r\n//    __hwInitVI();\r\n//\r\n//    // remove the temporary fifo\r\n//\tdelete tmpFifo;\r\n}\r\n\r\nvoid hwGXInit( void )\r\n{\r\n\t__hwInitGX();\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_hwpad.cpp",
    "content": "/*---------------------------------------------------------------------------*\r\n  Project:  Dolphin hw Library\r\n  File:     hwPad.c\r\n\r\n  Copyright 1998-2001 Nintendo.  All rights reserved.\r\n\r\n  These coded instructions, statements, and computer programs contain\r\n  proprietary information of Nintendo of America Inc. and/or Nintendo\r\n  Company Ltd., and are protected by Federal copyright law.  They may\r\n  not be disclosed to third parties or copied or duplicated in any form,\r\n  in whole or in part, without the prior written consent of Nintendo.\r\n\r\n  $Log: /Dolphin/build/libraries/hw/src/hwPad.c $\r\n    \r\n    10    8/09/01 9:47 Shiki\r\n    Fixed to clear pad delta status if PAD_ERR_TRANSFER is occurred.\r\n\r\n    9     01/03/27 13:21 Shiki\r\n    Detab.\r\n\r\n    8     01/03/23 6:06p Yasu\r\n    Change COMMENTed code to introduce pad-queue.\r\n\r\n    7     01/03/22 21:44 Shiki\r\n    Fixed hwPadRead() to conform to GameCube controller spec.\r\n    Also refer to '/Dolphin/build/hws/padhw/src/cont.c'.\r\n\r\n    6     2/14/01 1:48a Hirose\r\n    Deleted first call check for hwPadInit( ).\r\n    Now PadInit( ) can be called more than once.\r\n\r\n    5     10/27/00 3:47p Hirose\r\n    fixed build flags\r\n\r\n    4     6/12/00 4:39p Hirose\r\n    reconstructed structure and interface\r\n\r\n    3     4/26/00 4:59p Carl\r\n    CallBack -> Callback\r\n\r\n    2     3/25/00 12:50a Hirose\r\n    added some portion from cmn-pad.c\r\n    added pad connection check\r\n\r\n    1     3/23/00 1:21a Hirose\r\n    Initial version\r\n\r\n  $NoKeywords: $\r\n *---------------------------------------------------------------------------*/\r\n\r\n#include <dolphin.h>\r\n#include \"p_hw.h\"\r\n\r\n/*---------------------------------------------------------------------------*\r\n   Global Variables\r\n *---------------------------------------------------------------------------*/\r\nhwPadStatus       hwPad[PAD_MAX_CONTROLLERS];\r\nu32                 hwNumValidPads;\r\n\r\n/*---------------------------------------------------------------------------*\r\n   Local Variables\r\n *---------------------------------------------------------------------------*/\r\nextern PADStatus padData[PAD_MAX_CONTROLLERS]; // internal use only\r\n\r\n/*---------------------------------------------------------------------------*/\r\nstatic u32 PadChanMask[PAD_MAX_CONTROLLERS] =\r\n{\r\n    PAD_CHAN0_BIT, PAD_CHAN1_BIT, PAD_CHAN2_BIT, PAD_CHAN3_BIT\r\n};\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwPadCopy\r\n\r\n    Description:    This function copies informations of PADStatus into\r\n                    hwPadStatus structure. Also attaches some extra\r\n                    informations such as down/up, stick direction.\r\n                    This function is internal use only.\r\n\r\n                    Keeps previous state if PAD_ERR_TRANSFER is returned.\r\n\r\n    Arguments:      pad   : copy source. (PADStatus)\r\n                    dmpad : copy destination. (hwPadStatus)\r\n\r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\n//static void hwPadCopy( PADStatus* pad, hwPadStatus* dmpad )\r\n//{\r\n//    u16  dirs;\r\n//\r\n//    if ( pad->err != PAD_ERR_TRANSFER )\r\n//    {\r\n//        // Detects which direction is the stick(s) pointing.\r\n//        // This can be used when we want to use a stick as direction pad.\r\n//        dirs = 0;\r\n//        if ( pad->stickX    < - hw_STICK_THRESHOLD )\r\n//            dirs |= hw_STICK_LEFT;\r\n//        if ( pad->stickX    >   hw_STICK_THRESHOLD )\r\n//            dirs |= hw_STICK_RIGHT;\r\n//        if ( pad->stickY    < - hw_STICK_THRESHOLD )\r\n//            dirs |= hw_STICK_DOWN;\r\n//        if ( pad->stickY    >   hw_STICK_THRESHOLD )\r\n//            dirs |= hw_STICK_UP;\r\n//        if ( pad->substickX < - hw_STICK_THRESHOLD )\r\n//            dirs |= hw_SUBSTICK_LEFT;\r\n//        if ( pad->substickX >   hw_STICK_THRESHOLD )\r\n//            dirs |= hw_SUBSTICK_RIGHT;\r\n//        if ( pad->substickY < - hw_STICK_THRESHOLD )\r\n//            dirs |= hw_SUBSTICK_DOWN;\r\n//        if ( pad->substickY >   hw_STICK_THRESHOLD )\r\n//            dirs |= hw_SUBSTICK_UP;\r\n//\r\n//        // Get the direction newly detected / released\r\n//        dmpad->dirsNew      = PADButtonDown(dmpad->dirs, dirs);\r\n//        dmpad->dirsReleased = PADButtonUp(dmpad->dirs, dirs);\r\n//        dmpad->dirs         = dirs;\r\n//\r\n//        // Get DOWN/UP status of all buttons\r\n//        dmpad->buttonDown = PADButtonDown(dmpad->pst.button, pad->button);\r\n//        dmpad->buttonUp   = PADButtonUp(dmpad->pst.button, pad->button);\r\n//\r\n//        // Get delta of analogs\r\n//        dmpad->stickDeltaX = (s16)(pad->stickX - dmpad->pst.stickX);\r\n//        dmpad->stickDeltaY = (s16)(pad->stickY - dmpad->pst.stickY);\r\n//        dmpad->substickDeltaX = (s16)(pad->substickX - dmpad->pst.substickX);\r\n//        dmpad->substickDeltaY = (s16)(pad->substickY - dmpad->pst.substickY);\r\n//\r\n//        // Copy current status into DEMOPadStatus field\r\n//        dmpad->pst = *pad;\r\n//    }\r\n//    else\r\n//    {\r\n//        // Get the direction newly detected / released\r\n//        dmpad->dirsNew = dmpad->dirsReleased = 0;\r\n//\r\n//        // Get DOWN/UP status of all buttons\r\n//        dmpad->buttonDown = dmpad->buttonUp = 0;\r\n//\r\n//\r\n//\r\n//\r\n//        // Get delta of analogs\r\n//        dmpad->stickDeltaX =    dmpad->stickDeltaY    = 0;\r\n//        dmpad->substickDeltaX = dmpad->substickDeltaY = 0;\r\n//    }\r\n//}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwPadRead\r\n\r\n    Description:    Calls PADRead() and perform clamping. Get information\r\n                    of button down/up and sets them into extended field.\r\n                    This function also checks whether controllers are\r\n                    actually connected.\r\n\r\n    Arguments:      None\r\n\r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nvoid hwPadRead( void )\r\n{\r\n    s32         i;\r\n    u32         ResetReq = 0; // for error handling\r\n\r\n    // Read current PAD status\r\n    PADRead( padData );\r\n\r\n    // Clamp analog inputs\r\n    PADClamp( padData );\r\n\r\n    hwNumValidPads = 0;\r\n    for ( i = 0 ; i < PAD_MAX_CONTROLLERS ; i++ )\r\n    {\r\n        // Connection check\r\n        if ( padData[i].err == PAD_ERR_NONE ||\r\n\t\t\t padData[i].err == PAD_ERR_TRANSFER )\r\n        {\r\n            ++hwNumValidPads;\r\n        }\r\n        else if ( padData[i].err == PAD_ERR_NO_CONTROLLER )\r\n        {\r\n            ResetReq |= PadChanMask[i];\r\n        }\r\n\r\n//\t\thwPadCopy( &padData[i], &hwPad[i] );\r\n    }\r\n\r\n    // Try resetting pad channels which have been not valid\r\n    if ( ResetReq )\r\n    {\r\n        // Don't care return status\r\n        // If FALSE, then reset again in next hwPadRead.\r\n        PADReset( ResetReq );\r\n    }\r\n\r\n    return;\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwPadInit\r\n\r\n    Description:    Initialize PAD library and exported status\r\n\r\n    Arguments:      None\r\n\r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nvoid hwPadInit( void )\r\n{\r\n    s32         i;\r\n\r\n\t// Set pad analog mode.\r\n\r\n\t// Mode 3:\r\n\t// stickX, stickY\t\t\t\tAll 8 bits are valid. \r\n\t// substickX, substickY\t\t\tAll 8 bits are valid. \r\n\t// triggerLeft, triggerRight\tAll 8 bits are valid. \r\n\t// analogA, analogB\t\t\t\tAll 8 bits are invalid and set to zero. \r\n\r\n\tPADSetAnalogMode( PAD_MODE_3 );\r\n\r\n    // Initialize pad interface\r\n    PADInit();\r\n\r\n    // Reset exported pad status\r\n    for ( i = 0 ; i < PAD_MAX_CONTROLLERS ; i++ )\r\n    {\r\n        hwPad[i].pst.button = 0;\r\n        hwPad[i].pst.stickX = 0;\r\n        hwPad[i].pst.stickY = 0;\r\n        hwPad[i].pst.substickX = 0;\r\n        hwPad[i].pst.substickY = 0;\r\n        hwPad[i].pst.triggerLeft = 0;\r\n        hwPad[i].pst.triggerRight = 0;\r\n        hwPad[i].pst.analogA = 0;\r\n        hwPad[i].pst.analogB = 0;\r\n        hwPad[i].pst.err = 0;\r\n        hwPad[i].buttonDown = 0;\r\n        hwPad[i].buttonUp = 0;\r\n        hwPad[i].dirs = 0;\r\n        hwPad[i].dirsNew = 0;\r\n        hwPad[i].dirsReleased = 0;\r\n        hwPad[i].stickDeltaX = 0;\r\n        hwPad[i].stickDeltaY = 0;\r\n        hwPad[i].substickDeltaX = 0;\r\n        hwPad[i].substickDeltaY = 0;\r\n    }\r\n\r\n}\r\n\r\n#if 0 // Currently this stuff is not used.\r\n//============================================================================\r\n//   PAD-QUEUE Functions: NOW WORKS\r\n//\r\n//   This set of functions helps the game engine with constant animation\r\n//   rate.\r\n//\r\n//   [Sample Code]\r\n//\r\n//       BOOL  isRetraced;\r\n//       while ( !gameDone )\r\n//       {\r\n//           do\r\n//           {\r\n//               isQueued = hwPadQueueRead( OS_MESSAGE_BLOCK );\r\n//               Do_animation( );\r\n//           }\r\n//           while ( isQueued );\r\n//\r\n//           Do_rendering( );\r\n//       }\r\n//\r\n\r\n//============================================================================\r\n#define hw_PADQ_DEPTH    8\r\n\r\nvoid hwPadQueueInit      ( void );\r\nBOOL hwPadQueueRead      ( s32  );\r\nvoid hwPadQueueFlush     ( void );\r\n\r\nstatic  PADStatus       PadQueue[hw_PADQ_DEPTH][PAD_MAX_CONTROLLERS];\r\nstatic  OSMessageQueue  PadValidMsgQ;\r\nstatic  OSMessage       PadValidMsg[hw_PADQ_DEPTH];\r\nstatic  OSMessageQueue  PadEmptyMsgQ;\r\nstatic  OSMessage       PadEmptyMsg[hw_PADQ_DEPTH];\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwPadViCallback\r\n    Description:    This function should be called once every frame.\r\n    Arguments:      None\r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nstatic void hwPadViCallback( u32 retraceCount )\r\n{\r\n#pragma  unused (retraceCount)\r\n\r\n    PADStatus   *padContainer;\r\n#ifdef  _DEBUG\r\n    static BOOL caution = FALSE;\r\n#endif\r\n\r\n    // Get empty container.\r\n    if ( OSReceiveMessage( &PadEmptyMsgQ,\r\n                           (OSMessage *)&padContainer, OS_MESSAGE_NOBLOCK ) )\r\n    {\r\n        // Read the latest pad status into pad container\r\n        PADRead( padContainer );\r\n\r\n        // Send result as message\r\n        if ( !OSSendMessage( &PadValidMsgQ,\r\n                             (OSMessage)padContainer, OS_MESSAGE_NOBLOCK ) )\r\n        {\r\n            // The valid queue never be full.\r\n            ASSERTMSG( 0, \"Logical Error: Valid QUEUE is full.\" );\r\n        }\r\n#ifdef  _DEBUG\r\n        caution = FALSE;\r\n#endif\r\n    }\r\n    else\r\n    {\r\n#ifdef  _DEBUG\r\n        ASSERTMSG( caution, \"Pad Queue is full.\" );\r\n        caution = TRUE;\r\n#endif\r\n    }\r\n\r\n    return;\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwPadQueueRead\r\n    Description:    Read gamepad state and set to hwPad[].\r\n                    No need to care controller error.\r\n                    (When error, PADState is set to zero in PADRead.)\r\n    Arguments:      s32 flag: control block/noblock mode.\r\n                       when flag == OS_MESSAGE_BLOCK,\r\n                              wait next padinput if queue is empty.\r\n                       when flag == OS_MESSAGE_NOBLOCK,\r\n                              return immediately if queue is empty.\r\n\r\n    Returns:        BOOL: FALSE if queue was empty.\r\n                          TRUE  if get queued data.\r\n *---------------------------------------------------------------------------*/\r\nBOOL hwPadQueueRead( s32 flag )\r\n{\r\n    PADStatus   *padContainer;\r\n    BOOL        isQueued;\r\n    u32         i;\r\n\r\n    // Get pad data from valid data queue\r\n    isQueued = OSReceiveMessage( &PadValidMsgQ,\r\n                                 (OSMessage *)&padContainer, OS_MESSAGE_NOBLOCK );\r\n\r\n    // If queue is empty, wait and sleep until coming pad input on v-retrace\r\n    if ( !isQueued )\r\n    {\r\n        if ( flag == OS_MESSAGE_BLOCK )\r\n        {\r\n            OSReceiveMessage( &PadValidMsgQ,\r\n                              (OSMessage *)&padContainer, OS_MESSAGE_BLOCK );\r\n        }\r\n        else\r\n        {\r\n            return FALSE;\r\n        }\r\n    }\r\n\r\n    // Copy status to hwPad\r\n    for ( i = 0 ; i < PAD_MAX_CONTROLLERS ; i ++ )\r\n    {\r\n        hwPadCopy( &padContainer[i], &hwPad[i] );\r\n    }\r\n\r\n    // Release pad container\r\n    if ( !OSSendMessage( &PadEmptyMsgQ,\r\n                         (OSMessage)padContainer, OS_MESSAGE_NOBLOCK ) )\r\n    {\r\n        // The valid queue never be full.\r\n        ASSERTMSG( 0, \"Logical Error: Empty QUEUE is full.\" );\r\n    }\r\n\r\n    return isQueued;\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwPadQueueFlush\r\n    Description:    Flush Pad-Queue\r\n    Arguments:      None\r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nvoid hwPadQueueFlush( void )\r\n{\r\n    OSMessage   msg;\r\n\r\n    while ( OSReceiveMessage( &PadValidMsgQ, &msg, OS_MESSAGE_NOBLOCK ) )\r\n    {\r\n        OSSendMessage( &PadEmptyMsgQ, msg, OS_MESSAGE_BLOCK );\r\n    }\r\n\r\n    return;\r\n}\r\n\r\n/*---------------------------------------------------------------------------*\r\n    Name:           hwPadQueueInit\r\n    Description:    Initialize Pad-Queue utility routines\r\n    Arguments:      None\r\n    Returns:        None\r\n *---------------------------------------------------------------------------*/\r\nvoid hwPadQueueInit( void )\r\n{\r\n    u32         i;\r\n\r\n    // Initialize basic pad function\r\n    hwPadInit();\r\n\r\n    OSInitMessageQueue( &PadValidMsgQ, &PadValidMsg[0], hw_PADQ_DEPTH );\r\n    OSInitMessageQueue( &PadEmptyMsgQ, &PadEmptyMsg[0], hw_PADQ_DEPTH );\r\n\r\n    // Entry pad container\r\n    for ( i = 0; i < hw_PADQ_DEPTH; i ++ )\r\n    {\r\n        if ( !OSSendMessage( &PadEmptyMsgQ,\r\n                             (OSMessage)&PadQueue[i][0], OS_MESSAGE_NOBLOCK ) )\r\n        {\r\n            ASSERTMSG( 0, \"Logical Error: Send Message.\" );\r\n        }\r\n    }\r\n\r\n    // Reset pad queue and initialize pad HW\r\n    hwPadQueueFlush();\r\n\r\n    // Register vi Callback function\r\n    VISetPostRetraceCallback( hwPadViCallback );\r\n\r\n    return;\r\n}\r\n/*---------------------------------------------------------------------------*/\r\n#endif // 0\r\n\r\n\r\n/*===========================================================================*/\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_hwpad.h",
    "content": "/*---------------------------------------------------------------------------*\r\n  Project:  Dolphin hw library\r\n  File:     hwPad.h\r\n\r\n  Copyright 1998-2001 Nintendo.  All rights reserved.\r\n\r\n  These coded instructions, statements, and computer programs contain\r\n  proprietary information of Nintendo of America Inc. and/or Nintendo\r\n  Company Ltd., and are protected by Federal copyright law.  They may\r\n  not be disclosed to third parties or copied or duplicated in any form,\r\n  in whole or in part, without the prior written consent of Nintendo.\r\n\r\n  $Log: /Dolphin/include/hw/hwPad.h $\r\n    \r\n    1     5/09/01 9:37p Hirose\r\n    separated from hw.h\r\n    \r\n  $NoKeywords: $\r\n *---------------------------------------------------------------------------*/\r\n\r\n#ifndef __hwPAD_H__\r\n#define __hwPAD_H__\r\n\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\n/*---------------------------------------------------------------------------*\r\n    hwPad.c\r\n *---------------------------------------------------------------------------*/\r\n// used to detect which direction is the stick(s) pointing\r\n#define hw_STICK_THRESHOLD      48\r\n\r\n#define hw_STICK_UP             0x1000\r\n#define hw_STICK_DOWN           0x2000\r\n#define hw_STICK_LEFT           0x4000\r\n#define hw_STICK_RIGHT          0x8000\r\n#define hw_SUBSTICK_UP          0x0100\r\n#define hw_SUBSTICK_DOWN        0x0200\r\n#define hw_SUBSTICK_LEFT        0x0400\r\n#define hw_SUBSTICK_RIGHT       0x0800\r\n\r\n// extended pad status structure\r\ntypedef struct\r\n{\r\n    // contains PADStatus structure\r\n    PADStatus   pst;\r\n\r\n    // extended field\r\n    u16         buttonDown;\r\n    u16         buttonUp;\r\n    u16         dirs;\r\n    u16         dirsNew;\r\n    u16         dirsReleased;\r\n    s16         stickDeltaX;\r\n    s16         stickDeltaY;\r\n    s16         substickDeltaX;\r\n    s16         substickDeltaY;\r\n} hwPadStatus;\r\n\r\n// the entity which keeps current pad status\r\nextern hwPadStatus    hwPad[PAD_MAX_CONTROLLERS];\r\nextern u32              hwNumValidPads;\r\n\r\n// main function prototypes\r\nextern void     hwPadInit( void );\r\nextern void     hwPadRead( void );\r\n\r\n// inline functions for getting each component\r\nstatic inline u16 hwPadGetButton(u32 i)\r\n    { return hwPad[i].pst.button; }\r\n\r\nstatic inline u16 hwPadGetButtonUp(u32 i)\r\n    { return hwPad[i].buttonUp; }\r\n\r\nstatic inline u16 hwPadGetButtonDown(u32 i)\r\n    { return hwPad[i].buttonDown; }\r\n\r\nstatic inline u16 hwPadGetDirs(u32 i)\r\n    { return hwPad[i].dirs; }\r\n\r\nstatic inline u16 hwPadGetDirsNew(u32 i)\r\n    { return hwPad[i].dirsNew; }\r\n\r\nstatic inline u16 hwPadGetDirsReleased(u32 i)\r\n    { return hwPad[i].dirsReleased; }\r\n\r\nstatic inline s8  hwPadGetStickX(u32 i)\r\n    { return hwPad[i].pst.stickX; }\r\n\r\nstatic inline s8  hwPadGetStickY(u32 i)\r\n    { return hwPad[i].pst.stickY; }\r\n\r\nstatic inline s8  hwPadGetSubStickX(u32 i)\r\n    { return hwPad[i].pst.substickX; }\r\n\r\nstatic inline s8  hwPadGetSubStickY(u32 i)\r\n    { return hwPad[i].pst.substickY; }\r\n\r\nstatic inline u8  hwPadGetTriggerL(u32 i)\r\n    { return hwPad[i].pst.triggerLeft; }\r\n\r\nstatic inline u8  hwPadGetTriggerR(u32 i)\r\n    { return hwPad[i].pst.triggerRight; }\r\n\r\nstatic inline u8  hwPadGetAnalogA(u32 i)\r\n    { return hwPad[i].pst.analogA; }\r\n\r\nstatic inline u8  hwPadGetAnalogB(u32 i)\r\n    { return hwPad[i].pst.analogB; }\r\n\r\nstatic inline s8  hwPadGetErr(u32 i)\r\n    { return hwPad[i].pst.err; }\r\n\r\n/*---------------------------------------------------------------------------*/\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n#endif // __hwPAD_H__\r\n\r\n/*===========================================================================*/\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_light.cpp",
    "content": "//#include \"p_light.h\"\r\n//#include \"p_assert.h\"\r\n//\r\n//unsigned int\tNsLight::m_SlotArray\t\t\t= 0;\r\n//bool\t\t\tNsLight::m_LightingHasChanged\t= true;\r\n//GXLightObj\t\tNsLight::m_LightObj[NSLIGHT_MAX_LIGHTS];\r\n//GXColor\t\t\tNsLight::m_AmbientColor\t\t\t= (GXColor){ 0, 0, 0, 0 };\r\n//\r\n//static GXColor\tColorOff = { 0, 0, 0, 0 };\r\n//\r\n//void NsLight::loadup( void )\r\n//{\r\n//\tif( m_LightingHasChanged )\r\n//\t{\r\n//\t\t// Go through and load up all lights to the hardware.\r\n//\t\tfor( int l = 0; l < NSLIGHT_MAX_LIGHTS; ++l )\r\n//\t\t{\r\n//\t\t\tif( m_SlotArray & ( 1 << l ))\r\n//\t\t\t{\r\n//\t\t\t\tGXLoadLightObjImm( &m_LightObj[l], (enum _GXLightID)( 1 << l ));\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\tm_LightingHasChanged = false;\r\n//}\r\n//\r\n//\r\n//\r\n//void NsLight::loadupAmbient( void )\r\n//{\r\n//\tGX::SetChanAmbColor( GX_COLOR0A0, m_AmbientColor );\r\n//}\r\n//\r\n//\r\n//\r\n//NsLight::NsLight( NsLightType type )\r\n//{\r\n//\tassertp(( type == NSLIGHT_AMBIENT ) || ( type == NSLIGHT_DIRECTIONAL ));\r\n//\r\n//\tm_Type\t\t= type;\r\n//\tm_pFrame\t= NULL;\r\n//\tm_Color.r\t= 0;\r\n//\tm_Color.g\t= 0;\r\n//\tm_Color.b\t= 0;\r\n//\tm_Color.a\t= 0;\r\n//\tm_On\t\t= false;\r\n//\r\n//\tactivate( true );\r\n//}\r\n//\r\n//\r\n//\r\n//NsLight::~NsLight()\r\n//{\r\n//\tactivate( false );\r\n//}\r\n//\r\n//\r\n//void NsLight::setFrame( NsFrame* p_frame )\r\n//{\r\n//\tm_pFrame\t\t\t\t= p_frame;\r\n//\tm_LightingHasChanged\t= true;\r\n//}\r\n//\r\n//\r\n//\r\n//void NsLight::setColor( GXColor color )\r\n//{\r\n//\tm_Color.r = (int)( color.r * 255.0f );\r\n//\tm_Color.g = (int)( color.g * 255.0f );\r\n//\tm_Color.b = (int)( color.b * 255.0f );\r\n//\tm_Color.a = 0xFF;\r\n//\r\n//\tupdateColor();\r\n//}\r\n//\r\n//\r\n//\r\n//void NsLight::updateColor( void )\r\n//{\r\n//\tif( m_On )\r\n//\t{\r\n//\t\tif( m_Type == NSLIGHT_AMBIENT )\r\n//\t\t{\r\n//\t\t\tGX::SetChanAmbColor( GX_COLOR0A0, m_Color );\r\n//\t\t\tm_AmbientColor = m_Color;\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tm_LightingHasChanged = true;\r\n//\t\t\tGXInitLightColor( &m_LightObj[m_Slot], m_Color );\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n//void NsLight::updateOrientation( void )\r\n//{\r\n//\t// Prepares large number (2 pow 20) (taken from Nintendo demo code).\r\n//\t#define LARGE_NUMBER 1048576\r\n//\r\n//\tif( m_pFrame && m_On && ( m_Type == NSLIGHT_DIRECTIONAL ))\r\n//\t{\r\n//\t\tm_LightingHasChanged = true;\r\n//\t\tfloat x_pos = -m_pFrame->getModelMatrix()->getAtX() * LARGE_NUMBER;\r\n//\t\tfloat y_pos = -m_pFrame->getModelMatrix()->getAtY() * LARGE_NUMBER;\r\n//\t\tfloat z_pos = -m_pFrame->getModelMatrix()->getAtZ() * LARGE_NUMBER;\r\n//\t\tGXInitLightPos( &m_LightObj[m_Slot], x_pos, y_pos, z_pos );\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n//void NsLight::activate( bool on )\r\n//{\r\n//\tif( on != m_On )\r\n//\t{\r\n//\t\tm_On = on;\r\n//\r\n//\t\tif( m_Type == NSLIGHT_AMBIENT )\r\n//\t\t{\r\n//\t\t\tif( m_On )\r\n//\t\t\t{\r\n//\t\t\t\tGX::SetChanAmbColor( GX_COLOR0A0, m_Color );\r\n//\t\t\t\tm_AmbientColor = m_Color;\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\tGX::SetChanAmbColor( GX_COLOR0A0, ColorOff );\r\n//\t\t\t\tm_AmbientColor = ColorOff;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tm_LightingHasChanged = true;\r\n//\r\n//\t\t\tif( m_On )\r\n//\t\t\t{\r\n//\t\t\t\t// Find a free slot.\r\n//\t\t\t\tfor( int s = 0; s < NSLIGHT_MAX_LIGHTS; ++s )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tif(( m_SlotArray & ( 1 << s )) == 0 )\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\tm_Slot = s;\r\n//\t\t\t\t\t\tm_SlotArray |= ( 1 << s );\r\n//\r\n//\t\t\t\t\t\t// In case orientation was changed whilst the light was off.\r\n//\t\t\t\t\t\tupdateOrientation();\r\n//\t\t\t\t\t\tupdateColor();\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\t// Turn the light off.\r\n//\t\t\t\tm_SlotArray &= ~( 1 << m_Slot );\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_light.h",
    "content": "//#ifndef _P_LIGHT_H_\r\n//#define _P_LIGHT_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_frame.h\"\r\n//\r\n//enum NsLightType\r\n//{\r\n//\tNSLIGHT_UNKNOWM\t= 0,\r\n//\tNSLIGHT_DIRECTIONAL,\r\n//    NSLIGHT_AMBIENT,\r\n//};\r\n//\r\n//#define NSLIGHT_MAX_LIGHTS\t4\r\n//\r\n//class NsLight\r\n//{\r\n//\tstatic unsigned int\tm_SlotArray;\r\n//\tstatic GXLightObj\tm_LightObj[NSLIGHT_MAX_LIGHTS];\r\n//\tstatic bool\t\t\tm_LightingHasChanged;\r\n//\tstatic GXColor\t\tm_AmbientColor;\r\n//\t\r\n//\tNsLightType\t\t\tm_Type;\r\n//\tNsFrame*\t\t\tm_pFrame;\r\n//\tGXColor\t\t\t\tm_Color;\t\r\n//\tNsFrame\t\t\t\tm_Frame;\r\n//\tbool\t\t\t\tm_On;\r\n//\tint\t\t\t\t\tm_Slot;\r\n//\r\n//\tpublic:\r\n//\r\n//\tstatic void\t\t\tloadup( void );\r\n//\tstatic void\t\t\tloadupAmbient( void );\r\n//\tstatic GXLightID\tgetLightID( void )\t\t\t\t{ return (GXLightID)m_SlotArray; }\r\n//\r\n//\t\t\t\t\t\tNsLight( NsLightType type );\r\n//\t\t\t\t\t\t~NsLight();\r\n//\r\n//\tvoid\t\t\t\tsetFrame( NsFrame* p_frame );\r\n//\tvoid\t\t\t\tsetColor( GXColor color );\r\n//\tvoid\t\t\t\tactivate( bool on );\r\n//\tvoid\t\t\t\tupdateOrientation( void );\r\n//\tvoid\t\t\t\tupdateColor( void );\r\n//};\r\n//\r\n//#endif _P_LIGHT_H_\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_material.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tMaterial\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tA Material.\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include <math.h>\r\n//#include \"p_material.h\"\r\n//#include \"p_model.h\"\r\n//#include \"p_clump.h\"\r\n//#include \"p_scene.h\"\r\n//#include \"p_light.h\"\r\n//#include <gfx/gfxman.h>\r\n//#include <gfx/nxflags.h>\r\n//#include \"p_display.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#define rpWORLDUVS\t\t\t( rpWORLDTEXTURED2 | rpWORLDTEXTURED )\r\n//#define MAX_VC_WIBBLE_VERTS\t2048\r\n//static const float pi_over_180 = 3.1415926535f / 180.0f;\r\n//\r\n//// Treats the VC wibbling as a multiplier from the original PreLitLum, rather than replacing it outright.\r\n//#define NS_SECTOR_FLAGS_VC_PRESERVE_PRELIT\t0x400\r\n//\r\n//// whether the VC wibbling needs to be continually refreshed (if static, then VC doesn't get refreshed unless the mesh's dirty flag is set)\r\n//#define NS_SECTOR_FLAGS_VC_STATIC\t\t\t0x800\r\n//\r\n//enum\r\n//{\r\n//\tmTWO_SIDED\t\t\t= 0x01,\r\n//\tmINVISIBLE\t\t\t= 0x02,\r\n//\tmFRONT_FACING\t\t= 0x04,\r\n//\tmTRANSPARENT\t\t= 0x08,\r\n//\tmDECAL\t\t\t\t= 0x10,\r\n//\tmUV_WIBBLE_SUPPORT\t= 0x20,\t// If these two values change, notify Steve as Rw references \r\n//\tmVC_WIBBLE_SUPPORT\t= 0x40, // these two flags by value.\r\n//};\r\n//\r\n//enum RpWorldFlag\r\n//{\r\n//    rpWORLDTRISTRIP = 0x01,     /**<This world's meshes can be rendered\r\n//                                   as tri strips */\r\n//    rpWORLDTEXTURED = 0x04,     /**<This world has one set of texture coordinates */\r\n//    rpWORLDPRELIT = 0x08,       /**<This world has luminance values */\r\n//    rpWORLDNORMALS = 0x10,      /**<This world has normals */\r\n//    rpWORLDLIGHT = 0x20,        /**<This world will be lit */\r\n//    rpWORLDMODULATEMATERIALCOLOR = 0x40, /**<Modulate material color with\r\n//                                            vertex colors (pre-lit + lit) */\r\n//    rpWORLDTEXTURED2 = 0x80, /**<This world has 2 set of texture coordinates */\r\n//\r\n//    /*\r\n//     * These flags are stored in the flags field in an RwObject, the flag field is 8bit.\r\n//     */\r\n//\r\n//    rpWORLDSECTORSOVERLAP = 0x40000000,\r\n//};\r\n//typedef enum RpWorldFlag RpWorldFlag;\r\n//\r\n//enum\r\n//{\r\n//\tMAX_NUM_SEQUENCES\t= 8\r\n//};\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n//static NsMaterial* lastUVWibbleMaterial = NULL;\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n//float env_map_cam_u_factor = 0.0f;\r\n//float env_map_cam_v_factor = 0.0f;\r\n//\r\n//void NsMaterial::deleteDLs( void )\r\n//{\r\n////\tNsDL\t  * pDL;\r\n////\tNsDL\t  * pKillDL;\r\n////\tint\t\t\tcount = 0;\r\n////\r\n////\tNsDisplay::flush();\r\n////\t\r\n////\t// Remove pools from display lists.\r\n//// \tpDL = m_pDL;\r\n////\twhile ( pDL ) {\r\n////\t\tpKillDL = pDL;\r\n////\t\tpDL = pDL->m_pNext;\r\n////\r\n//////\t\tif ( pKillDL->m_pParent->m_pVertexPool ) {\r\n//////\t\t\tdelete pKillDL->m_pParent->m_pVertexPool;\r\n//////\t\t\tpKillDL->m_pParent->m_pVertexPool = NULL;\r\n//////\t\t}\r\n////\t\tif ( pKillDL->m_pParent->m_pFaceFlags ) {\r\n////\t\t\tdelete pKillDL->m_pParent->m_pFaceFlags;\r\n////\t\t\tpKillDL->m_pParent->m_pFaceFlags = NULL;\r\n////\t\t}\r\n////\t\tif ( pKillDL->m_pParent->m_pFaceMaterial ) {\r\n////\t\t\tdelete pKillDL->m_pParent->m_pFaceMaterial;\r\n////\t\t\tpKillDL->m_pParent->m_pFaceMaterial = NULL;\r\n////\t\t}\r\n////\t}\r\n////\t// Remove all display lists.\r\n//// \tpDL = m_pDL;\r\n////\twhile ( pDL ) {\r\n////\t\tpKillDL = pDL;\r\n////\t\tpDL = pDL->m_pNext;\r\n////\t\tdelete pKillDL;\r\n////\t\tcount++;\r\n////\t}\r\n////\r\n////\tOSReport( \"Killed &%d display lists\\n\", count );\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tinit\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tnumber\tThe material number to create.\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tCreates a material object.\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void NsMaterial::init(unsigned int number)\r\n//{\r\n//\t// Reset material to blank.\r\n//\tm_id\t\t\t=  *((unsigned int *)\"GCMT\");\r\n//\tm_version\t\t= 0;\r\n//\tm_number\t\t= number;\r\n//\tm_pTexture\t= NULL;\r\n//\tm_nDL\t\t\t= 0;\r\n//\tm_pDL\t\t\t= NULL;\r\n//\tm_priority\t= 0;\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\taddDL\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tpDL\tThe display list to add.\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tAdds a display list to this material.\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void NsMaterial::addDL ( NsDL * pDLToAdd )\r\n//{\r\n//\t// Make this DL point to the current DL.\r\n//\tpDLToAdd->m_pNext = m_pDL;\r\n//\t// Point the material at this DL.\r\n//\tm_pDL = pDLToAdd;\r\n//\t// Increment number of DLs.\r\n//\tm_nDL++;\r\n//}\r\n//\r\n//NsBlendMode\tgBlendMode = (NsBlendMode)-1;\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tdraw\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tDraws all display lists assigned to this material.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void NsMaterial::draw ( void )\r\n//{\r\n//\tNsDL\t  * pDLToDraw;\r\n//\tGXLightID\tlight_id;\r\n//\tNsZMode\t\tz_mode;\r\n//\tint\t\t\tz_compare;\r\n//\tint\t\t\tz_update;\r\n//\tint\t\t\tz_reject_before;\r\n//\r\n//\tif ( m_flags & mINVISIBLE ) return;\r\n//\tif( !m_pDL ) return;\r\n//\r\n//\t// See if we're actually going to draw something.\r\n////\tint we_want_to_draw_something = 0;\r\n//// \tpDLToDraw = m_pDL;\r\n////\twhile ( pDLToDraw ) {\r\n////\t\tif (\t(pDLToDraw->m_pParent->m_cull.visible) &&\r\n////\t\t\t\t!(pDLToDraw->m_pParent->m_rwflags & (mSD_INVISIBLE|mSD_KILLED|mSD_NON_COLLIDABLE)) ) {\r\n////\t\t\twe_want_to_draw_something = 1;\r\n////\t\t\tbreak;\r\n////\t\t}\r\n////\t\tpDLToDraw = pDLToDraw->m_pNext;\r\n////\t}\r\n////\tif ( !we_want_to_draw_something ) return;\r\n//\r\n//\t// Set default texture generation matrix.\r\n//\tGXSetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_TEXCOORD0, GX_IDENTITY );\r\n//\r\n//\tif ( m_blendMode == gBlendMode ) {\r\n//\t\treturn;\r\n//\t}\r\n//\r\n////\tif ( m_pTexture ) {\r\n////\t\tif ( strcmp( m_pTexture->m_name, \"cw_ss_floor_decal_32.png\" ) == 0 ) {\r\n////\t\t\tOSReport( \"Suspect material: %s\\n\", m_pTexture->m_name );\r\n////\t\t\tOSReport( \"Dimensions: %dx%d (%d bit)\\n\", m_pTexture->m_width, m_pTexture->m_height, m_pTexture->m_depth );\r\n//////\t\t\t{\r\n//////\t\t\t\tunsigned char * p8 = (unsigned char *)m_pTexture->m_pImage;\r\n//////\t\t\t}\r\n////\t\t\t{\r\n////\t\t\t\tunsigned short * p16 = (unsigned short *)m_pTexture->m_pPalette;\r\n////\t\t\t\tfor ( int lp = 0; lp < 16; lp++ ) {\r\n////\t\t\t\t\tOSReport( \"Palette %2d: 0x%04x\\n\", lp, p16[lp] );\r\n////\t\t\t\t}\r\n////\t\t\t}\r\n////\t\t}\r\n////\t}\r\n//\r\n////\tOSReport ( \"Draw material: %d %s\\n\", number, pTexture ? pTexture->name : \"<no texture\" );\r\n//\r\n//\t// Clear material flag for uv wibble.\r\n//\tlastUVWibbleMaterial = NULL;\r\n//\r\n//\t// Amend z-buffer state for decal materials.\r\n//\tif( m_flags & mDECAL )\r\n//\t{\r\n//\t\tNsRender::getZMode( &z_mode, &z_compare, &z_update, &z_reject_before );\r\n//\t\tNsRender::setZMode( z_mode, z_compare, 0, z_reject_before );\r\n//\t}\r\n//\r\n//\t// Determine whether lighting is required, based on whether the geometry contains normals.\r\n//\tif( m_pDL->m_pParent->m_flags & rpWORLDNORMALS )\r\n//\t{\r\n//\t\tlight_id = NsLight::getLightID();\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tlight_id = GX_LIGHT_NULL;\r\n//\t}\r\n//\r\n//\tGX::SetChanCtrl(\r\n//        GX_ALPHA0,       // color channel 0\r\n//        GX_ENABLE,       // enable channel (use lighting)\r\n//        GX_SRC_VTX,      // use the register as ambient color source\r\n//        GX_SRC_REG,      // use the register as material color source\r\n//        GX_LIGHT_NULL,\t // use GX_LIGHT0, GX_LIGHT1 etc.\r\n//        GX_DF_CLAMP,     // diffuse function (CLAMP = normal setting)\r\n//        GX_AF_NONE );    // attenuation function (this case doesn't use)\r\n//\t// Set alpha operation to scale colors by 2 to match PS2 hardware.\r\n//\tGXSetTevAlphaOp(\r\n//\t    GX_TEVSTAGE0,\r\n//\t    GX_TEV_ADD,\t\t// For modulation, this is irrelevent.\r\n//\t    GX_TB_ZERO,\r\n//\t    GX_CS_SCALE_2,\t// This is the bit that makes it like a PS2.\r\n//\t    GX_ENABLE,\r\n//\t    GX_TEVPREV );\r\n//\tGXSetAlphaCompare(\t// This means only pass the alpha if it is > 0.\r\n//\t    GX_GREATER,\t\t// Which allows cut-out shapes to work, even when\r\n//\t    0,\t\t\t\t// rendered out of order.\r\n//\t    GX_AOP_AND,\r\n//\t    GX_GREATER,\r\n//\t    0 );\r\n//\tGXSetTevColorOp(\r\n//\t    GX_TEVSTAGE0,\r\n//\t    GX_TEV_ADD,\t\t// For modulation, this is irrelevent.\r\n//\t    GX_TB_ZERO,\r\n//\t    GX_CS_SCALE_2,\t// This is the bit that makes it like a PS2.\r\n//\t    GX_ENABLE,\r\n//\t    GX_TEVPREV );\r\n//\r\n//\t// Set color control to combine material color with vertex colors.\r\n//\tif( light_id == GX_LIGHT_NULL )\r\n//\t{\r\n//\t\tGX::SetChanCtrl(\r\n//\t\t\tGX_COLOR0,       // color channel 0\r\n//\t\t\tGX_ENABLE,       // enable channel (use lighting)\r\n//\t\t\tGX_SRC_VTX,      // use the register as ambient color source\r\n//\t\t\tGX_SRC_REG,      // use the register as material color source\r\n//\t\t\tlight_id,\t\t // use GX_LIGHT0, GX_LIGHT1 etc.\r\n//\t\t\tGX_DF_NONE,\t\t // diffuse function (this case doesn't use)\r\n//\t\t\tGX_AF_NONE );    // attenuation function (this case doesn't use)\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tGX::SetChanCtrl(\r\n//\t\t\tGX_COLOR0,       // color channel 0\r\n//\t\t\tGX_ENABLE,       // enable channel (use lighting)\r\n//\t\t\tGX_SRC_REG,      // use the register as ambient color source\r\n//\t\t\tGX_SRC_REG,      // use the register as material color source\r\n//\t\t\tlight_id,\t\t // use GX_LIGHT0, GX_LIGHT1 etc.\r\n//\t\t\tGX_DF_CLAMP,     // diffuse function (CLAMP = normal setting)\r\n//\t\t\tGX_AF_NONE );    // attenuation function (this case doesn't use)\r\n//\r\n//\t\t\t// The primitive code may have changed the ambient register, so ensure it is set here.\r\n//\t\t\tNsLight::loadupAmbient();\r\n//\t}\r\n//\r\n//\tGXSetNumTexGens(1);\r\n//\tGXSetNumTevStages(1);\r\n//\r\n//\t// We don't deal with untextured materials.\r\n////\tif ( !pMat->pTexture ) return;\r\n//\r\n///*\tGX::SetChanCtrl(\r\n//        GX_ALPHA0,       // color channel 0\r\n//        GX_ENABLE,       // enable channel (use lighting)\r\n//        GX_SRC_REG,      // use the register as ambient color source\r\n//        GX_SRC_VTX,      // use the register as material color source\r\n//        GX_LIGHT_NULL,   // use GX_LIGHT0\r\n//        GX_DF_CLAMP,     // diffuse function (CLAMP = normal setting)\r\n//        GX_AF_NONE );    // attenuation function (this case doesn't use)\r\n//\t// Set alpha operation to scale colors by 2 to match PS2 hardware.\r\n//\tGXSetTevAlphaOp(\r\n//\t    GX_TEVSTAGE0,\r\n//\t    GX_TEV_ADD,\t\t// For modulation, this is irrelevent.\r\n//\t    GX_TB_ZERO,\r\n//\t    GX_CS_SCALE_2,\t// This is the bit that makes it like a PS2.\r\n//\t    GX_ENABLE,\r\n//\t    GX_TEVPREV );\r\n//\tGXSetAlphaCompare(\t// This means only pass the alpha if it is > 0.\r\n//\t    GX_GREATER,\t\t// Which allows cut-out shapes to work, even when\r\n//\t    0,\t\t\t\t// rendered out of order.\r\n//\t    GX_AOP_AND,\r\n//\t    GX_GREATER,\r\n//\t    0 );\r\n//*/\r\n//    // Set format of position, color and tex coordinates.\r\n///*    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);\r\n//    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);\r\n//\tGXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);*/\r\n//\t\r\n//\t// Lighting channel control\r\n///*\tGXSetNumChans(1);    // number of active color channels\r\n//\r\n//\t// Sets up vertex descriptors\r\n//\tGXClearVtxDesc();\r\n//\tGXSetVtxDesc(GX_VA_POS, GX_INDEX16);\r\n//\tGXSetVtxDesc(GX_VA_CLR0, GX_INDEX16);\r\n//   \tGXSetVtxDesc(GX_VA_TEX0, GX_INDEX16);\r\n//\t//GXSetVtxDesc(GX_VA_NRM, GX_INDEX8);*/\r\n//\r\n//\t// Upload texture if required.\r\n////\tif ( !pMat->pTexture->uploaded ) {\r\n////\t\tTexMan_Upload ( pTex );\r\n////\t}\r\n////\t// Set hardware to this texture.\r\n////\tGXSetNumTexGens(1);\r\n////\tGXSetNumTevStages(1);\r\n////\tGXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, /*pTex->texID*/GX_TEXMAP0, GX_COLOR0A0);\r\n//\r\n//\tGX::SetChanMatColor( GX_COLOR0A0, m_color );\r\n//\r\n//\t// Textured blend modes.\r\n//\tif ( m_pTexture ) {\r\n//\t\tif ( !m_pTexture->m_uploaded ) {\r\n//\t\t\tm_pTexture->upload( m_wrap );\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t// Draw all display lists for this material.\r\n// \tpDLToDraw = m_pDL;\r\n//\twhile ( pDLToDraw ) {\r\n////\t\tif ( (pDLToDraw->cull.visible) && !(pDLToDraw->rwflags & mSD_INVISIBLE)  ) {\r\n////\t\tif ( (pDLToDraw->cull.visible) && ((pDLToDraw->pParent->rwflags & (mSD_INVISIBLE|mSD_KILLED|mSD_NON_COLLIDABLE)) == 0) ) {\r\n//\t\tif (\t(pDLToDraw->m_pParent->m_cull.visible) &&\r\n//\t\t\t\t!(pDLToDraw->m_pParent->m_rwflags & (mSD_INVISIBLE|mSD_KILLED|mSD_NON_COLLIDABLE)) ) {\r\n//\t\t\tif ( ( pDLToDraw->m_flags & rpWORLDUVS ) && m_pTexture ) {\r\n//\t\t\t\tNsRender::setBlendMode ( m_blendMode, m_pTexture, m_alpha );\r\n//\t\t\t} else {\r\n//\t\t\t\tNsRender::setBlendMode ( m_blendMode, NULL, m_alpha );\r\n//\t\t\t}\r\n////\t\t\t// If model is straddling z, turn on clipping.\r\n////\t\t\tif ( pDLToDraw->cull.clipCodeOR ) {\r\n////\t\t\t\tGXSetClipMode(GX_CLIP_ENABLE);\r\n////\t\t\t} else {\r\n////\t\t\t\tGXSetClipMode(GX_CLIP_DISABLE);\r\n////\t\t\t}\r\n//\r\n////\t\t\tif ( pDLToDraw->m_vpoolFlags & (1<<5) ) {\r\n//\t\t\t\t// It's a tri-strip.\r\n//\t\t\t\tNsRender::setCullMode( NsCullMode_Never );\r\n//\t\t\t\t//GXSetCullMode ( GX_CULL_BACK );\r\n////\t\t\t} else {\r\n////\t\t\t\t// It's a tri-list.\r\n////\t\t\t\tNsRender::setCullMode( NsCullMode_Back );\r\n////\t\t\t}\r\n//\r\n//\t\t\tif( m_flags & mUV_WIBBLE_SUPPORT )\r\n//\t\t\t{\r\n//\t\t\t\twibbleUV( pDLToDraw );\r\n//\t\t\t}\r\n//\t\t\tif( m_flags & mVC_WIBBLE_SUPPORT )\r\n//\t\t\t{\r\n////\t\t\t\tOSReport( \"vc wibble: %x\\n\", pDLToDraw );\r\n//\t\t\t\twibbleVC( pDLToDraw );\r\n//\t\t\t}\r\n//\r\n//\t\t\tif ( pDLToDraw->m_size ) GXCallDisplayList ( &pDLToDraw[1], pDLToDraw->m_size );\r\n//\t\t}\r\n//\t\tpDLToDraw = pDLToDraw->m_pNext;\r\n//\t}\r\n//\r\n//\t// Restore z-buffer state to previous.\r\n//\tif( m_flags & mDECAL )\r\n//\t{\r\n//\t\tNsRender::setZMode( z_mode, z_compare, z_update, z_reject_before );\r\n//\t}\r\n//\r\n//\t// Clear dirty flag for all display lists for this material.\r\n// \tpDLToDraw = m_pDL;\r\n//\twhile ( pDLToDraw ) {\r\n//\t\tpDLToDraw->m_pParent->m_flags &= ~0x200;\r\n//\t\tpDLToDraw = pDLToDraw->m_pNext;\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tgetVCWibbleParameters\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//GXColor* NsMaterial::getVCWibbleParameters( NsDL* p_dl, char** change_mask )\r\n//{\r\n////\tMaterialPluginData* mat_plugin_data;\r\n////\tWorldSectorPluginData* ws_plugin_data;\r\n//\r\n////\tmat_plugin_data = GetMaterialPluginData( material );\r\n////\tif( mat_plugin_data->m_pWibble == NULL )\r\n////\t{\r\n////\t\treturn NULL;\r\n////\t}\r\n//\tif( p_dl->m_pParent->getWibbleColor() == NULL )\r\n//\t{\r\n//\t\treturn NULL;\r\n//\t}\r\n//\r\n////\tws_plugin_data = GetWorldSectorPluginData( sector );\r\n////\tif( ( ws_plugin_data->m_pWibbleSeqIndices == NULL ) || ( ws_plugin_data->m_pWibbleSeqOffsets == NULL ))\r\n////\t{\r\n////\t\treturn NULL;\r\n////\t}\r\n//\r\n//\tSpt::SingletonPtr< Gfx::Manager > gfx_man;\r\n////\tstatic RwRGBA\t\ts_new_colors[MAX_VC_WIBBLE_VERTS];\r\n//\tstatic GXColor\t\ts_new_colors[MAX_VC_WIBBLE_VERTS];\r\n//\tstatic char\t\t\ts_change_mask[MAX_VC_WIBBLE_VERTS];\r\n//\tint\t\t\t\t\ti, j, seq_num, offset, bounded_time;\r\n////\tWibbleSequenceData*\tsequence;\r\n//\tNsWibbleSequence*\tsequence;\r\n//\tTmr::Time\t\t\ttime, last_time;\r\n//\t\r\n//\ttime = gfx_man->GetGfxTime();\r\n////\tDbg_MsgAssert( MAX_VC_WIBBLE_VERTS >= sector->numVertices, (\"Fire somebody -- too many vertices (%d) in sector (max %d).\", sector->numVertices, MAX_VC_WIBBLE_VERTS ) );\r\n//\tDbg_Assert( MAX_VC_WIBBLE_VERTS >= p_dl->m_numVertex );\r\n//\r\n//\tfor( i = p_dl->m_vertBase; i < ( p_dl->m_vertBase + p_dl->m_vertRange ); ++i )\r\n//\t{\r\n//\t\tint num_frames;\r\n//\t\r\n////\t\tseq_num = ws_plugin_data->m_pWibbleSeqIndices[i];\r\n//\t\tseq_num = (int)((char)( p_dl->m_pParent->getWibbleIdx()[i] ));\r\n//\t\t\t\r\n//\t\tDbg_MsgAssert( seq_num >= -1 && seq_num <= MAX_NUM_SEQUENCES, ( \"Out of range seq_num %d\", seq_num ));\r\n//\r\n//\t\t// A sequence of -1 signifies that we should restore the original vertex color.\r\n//\t\tif( seq_num == -1 )\r\n//\t\t{\r\n//\t\t\t// Set the flag to refresh the color pool entry.\r\n//\t\t\t// Xbox needs to differentiate between setting the original vertex color, and setting a wibbled color.\r\n//\t\t\t// This is because we are writing these values back to the instanced data, which expects the vertex\r\n//\t\t\t// color to have already been modulated by the material color, where appropriate.\r\n//\t\t\ts_change_mask[i] = 2;\r\n//\t\t\t\t\r\n//\t\t\t// Restore the original vertex color.\r\n//\t\t\ts_new_colors[i].r = ( p_dl->m_pParent->getWibbleColor()[i] ) & 0xFF;\r\n//\t\t\ts_new_colors[i].g = ( p_dl->m_pParent->getWibbleColor()[i] >> 8 ) & 0xFF;\r\n//\t\t\ts_new_colors[i].b = ( p_dl->m_pParent->getWibbleColor()[i] >> 16 ) & 0xFF;\r\n//\r\n//\t\t\t// As a test, just make it green.\r\n////\t\t\ts_new_colors[i].r = 0;\r\n////\t\t\ts_new_colors[i].g = 255;\r\n////\t\t\ts_new_colors[i].b = 0;\r\n//\r\n//\t\t\t// Clear the seq index so that we don't wibble on the next frame...\r\n////\t\t\tws_plugin_data->m_pWibbleSeqIndices[i] = 0;\r\n//\t\t\t\t\r\n//\t\t\t// If we clear to 0 now, then the rest of the meshes in this world sector will not get colored.  so...\r\n//\t\t\t// leave it at -1...  you might think this would slow things down to have to go through the vertex\r\n//\t\t\t// list over and over, but the \"dirty flag\" already reduces the number of times that this function\r\n//\t\t\t// gets called...\r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\r\n//\t\t// A sequence of 0 signifies no wibble intentions.\r\n//\t\telse if( seq_num == 0 )\r\n//\t\t{\r\n//\t\t\ts_change_mask[i] = 0;\r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\ts_change_mask[i] = 1;\r\n//\t\t}\r\n//\r\n////\t\tsequence\t= &mat_plugin_data->m_pWibble->m_pSequences[seq_num - 1];\t// sequences are 1-based\r\n//\t\tsequence\t= m_pWibbleData + seq_num - 1;\t// sequences are 1-based\r\n//\t\tnum_frames\t= sequence->numKeys;\r\n//\r\n//\t\t// If a vert has only one frame of anim, don't wibble it. The artist should have just used vertex colors instead of vertex wibble.\r\n//\t\tif( num_frames <= 1 )\r\n//\t\t{   \r\n//\t\t\ts_change_mask[i] = 0;\r\n//\t\t\tcontinue;\r\n//\t\t}\r\n//\t\t\t\r\n////\t\toffset = ws_plugin_data->m_pWibbleSeqOffsets[i];\r\n//\t\toffset = p_dl->m_pParent->getWibbleOff()[i];\r\n//\r\n//\t\t// Range check.\r\n////\t\tDbg_MsgAssert( offset >= 0 && offset < sequence->m_NumKeyframes,( \"VC wibbling offset (%d) out of range (0<=x<%d) for %s\", offset, sequence->m_NumKeyframes, Script::FindChecksumName( ws_plugin_data->m_TriggerNode )));\r\n//\t\tDbg_MsgAssert( offset >= 0 && offset < sequence->numKeys,( \"VC wibbling offset (%d) out of range (0<=x<%d)\", offset, sequence->numKeys ));\r\n//\r\n////\t\tlast_time = sequence->m_Keyframes[num_frames - 1].m_Time;\r\n//\t\tlast_time = sequence->pKeys[num_frames - 1].time;\r\n////\t\tDbg_MsgAssert( last_time, ( \"Trying to mod by 0 in world sector %s\", Script::FindChecksumName(ws_plugin_data->m_TriggerNode )));\r\n//\t\tDbg_MsgAssert( last_time, ( \"Trying to mod by 0 in world sector\" ));\r\n//\r\n////\t\tbounded_time = (int)( time + sequence->m_Keyframes[offset].m_Time ) % last_time;\r\n//\t\tbounded_time = (int)( time + sequence->pKeys[offset].time ) % last_time;\r\n//\t\tfor( j = num_frames - 1; j >= 0; j-- )\r\n//\t\t{\r\n////\t\t\tif( bounded_time >= sequence->m_Keyframes[j].m_Time )\r\n//\t\t\tif( bounded_time >= (int)sequence->pKeys[j].time )\r\n//\t\t\t{\r\n////\t\t\t\tfloat ratio =\t(float)( bounded_time - sequence->m_Keyframes[j].m_Time ) / (float)( sequence->m_Keyframes[j + 1].m_Time - sequence->m_Keyframes[j].m_Time );\r\n//\t\t\t\tfloat ratio =\t(float)( bounded_time - sequence->pKeys[j].time ) / (float)( sequence->pKeys[j + 1].time - sequence->pKeys[j].time );\r\n//\t\r\n////\t\t\t\ts_new_colors[i].r\t= (unsigned char)( sequence->m_Keyframes[j].m_Color.r + ( ratio * ( sequence->m_Keyframes[j+1].m_Color.r - sequence->m_Keyframes[j].m_Color.r )));\r\n//\t\t\t\ts_new_colors[i].r\t= (unsigned char)( sequence->pKeys[j].color.r + ( ratio * ( sequence->pKeys[j+1].color.r - sequence->pKeys[j].color.r )));\r\n////\t\t\t\ts_new_colors[i].g\t= (unsigned char)( sequence->m_Keyframes[j].m_Color.g + ( ratio * ( sequence->m_Keyframes[j+1].m_Color.g - sequence->m_Keyframes[j].m_Color.g )));\r\n//\t\t\t\ts_new_colors[i].g\t= (unsigned char)( sequence->pKeys[j].color.g + ( ratio * ( sequence->pKeys[j+1].color.g - sequence->pKeys[j].color.g )));\r\n////\t\t\t\ts_new_colors[i].b\t= (unsigned char)( sequence->m_Keyframes[j].m_Color.b + ( ratio * ( sequence->m_Keyframes[j+1].m_Color.b - sequence->m_Keyframes[j].m_Color.b )));\r\n//\t\t\t\ts_new_colors[i].b\t= (unsigned char)( sequence->pKeys[j].color.b + ( ratio * ( sequence->pKeys[j+1].color.b - sequence->pKeys[j].color.b )));\r\n//\r\n////\t\t\t\tif( sector->flags & NS_SECTOR_FLAGS_VC_PRESERVE_PRELIT )\r\n//\t\t\t\tif( p_dl->m_pParent->m_flags & NS_SECTOR_FLAGS_VC_PRESERVE_PRELIT )\r\n//\t\t\t\t{\r\n//\t\t\t\t\t// Scale the colors by the original pre-lit colors.\r\n//\t\t\t\t\ts_new_colors[i].r = (unsigned char)((( p_dl->m_pParent->getWibbleColor()[i] & 0xFF ) * s_new_colors[i].r ) >> 8 );\r\n//\t\t\t\t\ts_new_colors[i].g = (unsigned char)(((( p_dl->m_pParent->getWibbleColor()[i] >> 8 ) & 0xFF ) * s_new_colors[i].g ) >> 8 );\r\n//\t\t\t\t\ts_new_colors[i].b = (unsigned char)(((( p_dl->m_pParent->getWibbleColor()[i] >> 16 ) & 0xFF ) * s_new_colors[i].b ) >> 8 );\r\n//\t\t\t\t}\r\n//\t\t\t\tbreak;\r\n//\t\t\t}\t\t\t\t\t\t\t\t \r\n//\t\t}\r\n//\t}\r\n//\t*change_mask = s_change_mask;\r\n//\treturn s_new_colors;\r\n//}\r\n//\r\n//\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\twibbleVC\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//bool NsMaterial::wibbleVC( NsDL* p_dl )\r\n//{\r\n//\tchar*\t\t\tchange_mask;\r\n//\r\n//\t// These next two MUST be signed or they'll wrap around causing infinite loops!!\r\n//\tint\t\t\t\ti;\r\n//\tGXColor*\t\tnew_colors;\r\n//\r\n//\t// Dirty flag optimization.\r\n//\tbool\t\t\tvc_mesh_is_dirty;\r\n//\r\n//\t// Check the dirty flag to see whether we need to continue.\r\n////\tvc_mesh_is_dirty = ( !( p_dl->m_pParent->m_flags & NS_SECTOR_FLAGS_VC_STATIC )) || ( vc_mesh_header_dirty );\r\n//\tvc_mesh_is_dirty = ( !( p_dl->m_pParent->m_flags & NS_SECTOR_FLAGS_VC_STATIC )) || ( p_dl->m_pParent->m_flags & 0x200 );\r\n//\tif( !vc_mesh_is_dirty )\r\n//\t{\r\n//\t\treturn false;\r\n//\t}\r\n//\r\n//\tnew_colors = getVCWibbleParameters( p_dl, &change_mask );\r\n//\tif( new_colors == NULL )\r\n//\t{\r\n//\t\treturn false;\r\n//\t}\r\n//\r\n//\t// Basic algorithm appears to be (inefficient!!) scan through all *indices*, updating vertex buffer with color information.\r\n//\tfor( i = p_dl->m_vertBase; i < ( p_dl->m_vertBase + p_dl->m_vertRange ); ++i )\r\n//\t{\r\n//\t\tif( change_mask[i] )\r\n//\t\t{\r\n//\t\t\t// Have to be careful here. Although we are getting a RwRGBA pointer, the actual format of the\r\n//\t\t\t// instanced color data is (bgra), so we need to switch red and blue when writing to the locked\r\n//\t\t\t// vertex buffer.\r\n//\t\t\tGXColor* p_color = (GXColor*)( p_dl->m_pParent->getColorPool() + i );\r\n//\r\n//\t\t\tif( change_mask[i] == 1 )\r\n//\t\t\t{\r\n//\t\t\t\t// Setting a wibbled color, so don't worry about material color modulation.\r\n//\t\t\t\tp_color->b\t= new_colors[i].r;\r\n//\t\t\t\tp_color->g\t= new_colors[i].g;\r\n//\t\t\t\tp_color->r\t= new_colors[i].b;\r\n//\t\t\t}\r\n//\t\t\telse\r\n//\t\t\t{\r\n//\t\t\t\t// Restoring an 'original' color, so consider material color modulation.\r\n////\t\t\t\tif( flags & rxGEOMETRY_MODULATE )\r\n////\t\t\t\t{\r\n////\t\t\t\t\tp_color->blue\t= new_colors[i].red * colorScale.red;\r\n////\t\t\t\t\tp_color->green\t= new_colors[i].green * colorScale.green;\r\n////\t\t\t\t\tp_color->red\t= new_colors[i].blue * colorScale.blue;\r\n////\t\t\t\t}\r\n////\t\t\t\telse\r\n////\t\t\t\t{\r\n//\t\t\t\t\tp_color->b\t= new_colors[i].r;\r\n//\t\t\t\t\tp_color->g\t= new_colors[i].g;\r\n//\t\t\t\t\tp_color->r\t= new_colors[i].b;\r\n////\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\treturn true;\r\n//}\r\n//\r\n//\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tgetUVWibbleParameters\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//bool NsMaterial::getUVWibbleParameters( float* u_offset, float* v_offset, int pass )\r\n//{\r\n//\tfloat uoff, voff;\r\n//\r\n//\t// Need to decide whether to use time based, or camera based, wibble.\r\n//\tif( m_UVWibbleEnabled & 0x80 )\r\n//\t{\r\n//\t\tuoff = env_map_cam_u_factor * m_uvel;\r\n//\t\tvoff = env_map_cam_v_factor * m_vvel;\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\tfloat elapsed_seconds, vel, amp, phase, freq;\r\n//\t\tint whole_offset;\r\n//\t\tSpt::SingletonPtr< Gfx::Manager > gfx_man;\r\n//\t\telapsed_seconds = (float)gfx_man->GetGfxTime() * 0.001f;\r\n//\r\n//\t\tvel\t\t= m_uvel;\r\n//\t\tamp\t\t= m_uamp;\r\n//\t\tphase\t= m_uphase;\r\n//\t\tfreq\t= m_ufreq;\r\n//\t\tuoff\t= elapsed_seconds * vel + ( amp * sinf( pi_over_180 * ( freq * (( elapsed_seconds + phase ) * 360.0f ))));\r\n//\r\n//\t\tif( fabs( uoff ) > 1.0f )\r\n//\t\t{\r\n//\t\t\twhole_offset = (int)uoff;\r\n//\t\t\tuoff -= whole_offset;\r\n//\t\t}\r\n//\t\r\n//\t\tvel\t\t= m_vvel;\r\n//\t\tamp\t\t= m_vamp;\r\n//\t\tphase\t= m_vphase;\r\n//\t\tfreq\t= m_vfreq;\r\n//\t\tvoff\t= elapsed_seconds * vel + ( amp * sinf( pi_over_180 * ( freq * (( elapsed_seconds + phase ) * 360.0f ))));\r\n//\t\t\r\n//\t\tif( fabs( voff ) > 1.0f )\r\n//\t\t{\r\n//\t\t\twhole_offset = (int)voff;\r\n//\t\t\tvoff -= whole_offset;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t*u_offset = uoff;\r\n//\t*v_offset = voff;\r\n//\r\n//\treturn true;\r\n//}\r\n//\r\n//\r\n//\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\twibbleUV\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//bool NsMaterial::wibbleUV( NsDL* p_dl )\r\n//{\r\n//\tstatic float\tu_offset[2]\t= { 0.0f, 0.0f };\r\n//\tstatic float\tv_offset[2]\t= { 0.0f, 0.0f };\r\n//\tstatic bool\t\tdo_wibble[2];\r\n//\r\n//\tif( this != lastUVWibbleMaterial )\r\n//\t{\r\n//\t\tlastUVWibbleMaterial = this;\r\n//\r\n//\t\tdo_wibble[0] = getUVWibbleParameters( &u_offset[0], &v_offset[0], 0 );\r\n//\t}\r\n//\r\n////\tif( !( do_wibble[0] || do_wibble[1] ))\r\n//\tif( !do_wibble[0] )\r\n//\t{\r\n//\t\treturn false;\r\n//\t}\r\n//\t\r\n//\t// Set up the texture generation matrix here.\r\n//\tMtx\tm;\r\n//\tMTXTrans( m, u_offset[0], v_offset[0], 0.0f );\r\n//\tGX::LoadTexMtxImm( m, GX_TEXMTX0, GX_MTX2x4 );\r\n//\tGXSetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEXCOORD0, GX_TEXMTX0 );\r\n//\treturn true;\r\n//}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_material.h",
    "content": "//#ifndef _MATERIAL_H_\r\n//#define _MATERIAL_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_dl.h\"\r\n//#include \"p_render.h\"\r\n//#include \"p_tex.h\"\r\n//\r\n//typedef struct {\r\n//\tunsigned int\ttime;\r\n//\tGXColor\t\t\tcolor;\r\n//} NsWibbleKey;\r\n//\r\n//typedef struct {\r\n//\tNsWibbleKey\t  * pKeys;\r\n//\tint\t\t\t\tnumKeys;\r\n//} NsWibbleSequence;\r\n//\r\n//class NsMaterial\r\n//{\r\n//\tunsigned int\tm_id;\t\t\t\t// 4\r\n//\tunsigned int\tm_version;\t\t\t// 4\r\n//\tunsigned int\tm_number;\t\t\t// 4 - Number instead of hash value.\r\n//\tNsTexture\t  * m_pTexture;\t\t\t// 4\r\n//\tunsigned int\tm_nDL;\t\t\t\t// 4\r\n//\tNsDL\t\t  * m_pDL;\t\t\t\t// 4\r\n//\tNsBlendMode\t\tm_blendMode;\t\t// 4\r\n//\tGXColor\t\t\tm_color;\t\t\t// 4\r\n//\tunsigned char\tm_alpha;\t\t\t// 1\r\n//\tunsigned char\tm_type;\t\t\t\t// 1\r\n//\tunsigned char\tm_flags;\t\t\t// 1\r\n//\tunsigned char\tm_UVWibbleEnabled;\t// 1\r\n//\tunsigned int\tm_priority;\t\t\t// 4\r\n//\tNsWibbleSequence * m_pWibbleData;\t// 4\r\n//\tfloat\t\t\tm_uvel;\t\t\t\t// 4\r\n//\tfloat\t\t\tm_vvel;     \t\t// 4\r\n//\tfloat\t\t\tm_uamp;     \t\t// 4\r\n//\tfloat\t\t\tm_vamp;     \t\t// 4\r\n//\tfloat\t\t\tm_uphase;\t\t\t// 4\r\n//\tfloat\t\t\tm_vphase;\t\t\t// 4\r\n//\tfloat\t\t\tm_ufreq;    \t\t// 4\r\n//\tfloat\t\t\tm_vfreq;    \t\t// 4\r\n//\tNsTexture_Wrap\tm_wrap;\t\t\t\t// 4\r\n//\t\t\t\t\t\t\t\t\t\t// Total: 84\r\n//\r\n//\tbool\t\t\t\tgetUVWibbleParameters\t( float* u_offset, float* v_offset, int pass );\r\n//\tGXColor*\t\t\tgetVCWibbleParameters\t( NsDL* p_dl, char** change_mask );\r\n//\r\n//\tfriend class NsMaterialMan;\r\n//\tfriend class NsModel;\r\n//public:\r\n//\tvoid\t\t\t\tinit\t\t( unsigned int number );\r\n//\r\n//\tvoid\t\t\t\taddDL\t\t( NsDL * pDLToAdd );\r\n//\r\n//\tvoid\t\t\t\tdeleteDLs\t( void );\r\n//\r\n//\tvoid\t\t\t\tdraw\t\t( void );\r\n//\r\n//\tint\t\t\t\t\tnumDL\t\t( void ) { return m_nDL; }\r\n//\tNsDL\t\t\t  * headDL\t\t( void ) { return m_pDL; }\r\n//\r\n//\tunsigned char\t\tgetType\t\t( void ) { return m_type; }\r\n//\tvoid\t\t\t\tsetType\t\t( unsigned char type ) { m_type = type; }\r\n//\r\n//\tunsigned char\t\tgetFlags\t( void ) { return m_flags; }\r\n//\tvoid\t\t\t\tsetFlags\t( unsigned char flags ) { m_flags = flags; }\r\n//\r\n//\t// Note: these were added for fast building of new materials for shadow rendering, and should be used\r\n//\t// with care elsewhere...\r\n//\tvoid\t\t\t\tsetColor\t( GXColor color )\t\t\t{ m_color = color; }\r\n//\tGXColor\t\t\t\tgetColor\t( void )\t\t\t\t\t{ return m_color; }\r\n//\tvoid\t\t\t\tsetTexture\t( NsTexture * pTexture )\t{ m_pTexture = pTexture; }\r\n//\tNsTexture*\t\t\tgetTexture\t( void )\t\t\t\t\t{ return m_pTexture; }\r\n//\tvoid\t\t\t\tsetnDL\t\t( unsigned int nDL )\t\t{ m_nDL = nDL; }\r\n//\tunsigned int\t\tgetnDL\t\t( void )\t\t\t\t\t{ return m_nDL; }\r\n//\tvoid\t\t\t\tsetpDL\t\t( NsDL * pDL )\t\t\t\t{ m_pDL = pDL; }\r\n//\tNsDL*\t\t\t\tgetpDL\t\t( void )\t\t\t\t\t{ return m_pDL; }\r\n//\tNsBlendMode\t\t\tgetBlendMode( void )\t\t\t\t\t{ return m_blendMode; }\r\n//\tvoid\t\t\t\tsetBlendMode( NsBlendMode mode )\t\t{ m_blendMode = mode; }\r\n//\tvoid\t\t\t\tsetAlpha\t( unsigned char alpha )\t\t{ m_alpha = alpha; }\r\n//\tbool\t\t\t\twibbleUV\t( NsDL* p_dl );\r\n//\tbool\t\t\t\twibbleVC\t( NsDL* p_dl );\r\n//\r\n//\tNsWibbleSequence*\tgetWibbleData\t( void )\t\t\t\t\t\t{ return m_pWibbleData; }\r\n//\tvoid\t\t\t\tsetWibbleData\t( NsWibbleSequence* p_data )\t{ m_pWibbleData = p_data; }\r\n//\r\n//\tvoid\t\t\t\tsetWrapMode\t\t( NsTexture_Wrap wrap )\t\t\t{ m_wrap = wrap; }\r\n//\tNsTexture_Wrap\t\tgetWrapMode\t\t( void ) { return m_wrap; }\r\n//};\r\n//\r\n//#endif\t\t// _MATERIAL_H_\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_matman.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tMatMan\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tMaterial Manager.\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include \"core/defines.h\"\r\n//#include <engine/supersector.h>\r\n//#include <engine/collide.h>\r\n//#include <math.h>\r\n//#include <charpipeline.h>\r\n//#include <dolphin/perf.h>\r\n//#include <charpipeline/GQRSetup.h>\r\n//#include \"p_material.h\"\r\n//#include \"p_matman.h\"\r\n//#include \"p_assert.h\"\r\n//#include \"p_bbox.h\"\r\n//#include \"p_scene.h\"\r\n//#include \"p_profile.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#define DEFAULT_MATMAN_SIZE 2048\r\n//\r\n//enum\r\n//{\r\n//\tmTWO_SIDED\t\t\t= 0x01,\r\n//\tmINVISIBLE\t\t\t= 0x02,\r\n//\tmFRONT_FACING\t\t= 0x04,\r\n//\tmTRANSPARENT\t\t= 0x08,\r\n//\tmDECAL\t\t\t\t= 0x10,\r\n//\tmUV_WIBBLE_SUPPORT\t= 0x20,\t// If these two values change, notify Steve as Rw references \r\n//\tmVC_WIBBLE_SUPPORT\t= 0x40, // these two flags by value.\r\n//};\r\n//\r\n//enum RpWorldFlag\r\n//{\r\n//    rpWORLDTRISTRIP = 0x01,     /**<This world's meshes can be rendered\r\n//                                   as tri strips */\r\n//    rpWORLDTEXTURED = 0x04,     /**<This world has one set of texture coordinates */\r\n//    rpWORLDPRELIT = 0x08,       /**<This world has luminance values */\r\n//    rpWORLDNORMALS = 0x10,      /**<This world has normals */\r\n//    rpWORLDLIGHT = 0x20,        /**<This world will be lit */\r\n//    rpWORLDMODULATEMATERIALCOLOR = 0x40, /**<Modulate material color with\r\n//                                            vertex colors (pre-lit + lit) */\r\n//    rpWORLDTEXTURED2 = 0x80, /**<This world has 2 set of texture coordinates */\r\n//\r\n//    /*\r\n//     * These flags are stored in the flags field in an RwObject, the flag field is 8bit.\r\n//     */\r\n//\r\n//    rpWORLDSECTORSOVERLAP = 0x40000000,\r\n//};\r\n//typedef enum RpWorldFlag RpWorldFlag;\r\n//\r\n//enum\r\n//{\r\n//\tMAX_NUM_SEQUENCES\t= 8\r\n//};\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsProfile CollisionTime( \"Collision Time\", 256 );\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tMatMan\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tInstances a material manager to the default table entry size of\t*\r\n// *\t\t\t\t2048 entries.\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsMaterialMan::NsMaterialMan()\r\n//{\r\n//\tNsMaterialMan ( DEFAULT_MATMAN_SIZE );\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tMatMan\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tnumEntries\tHow many entries the material manager should be.\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tInstances a material manager to a user-specified size.\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsMaterialMan::NsMaterialMan ( unsigned int numEntries )\r\n//{\r\n////\tpMaterialList = (NsMaterial *)OSAlloc ( sizeof ( NsMaterial ) * numEntries );\r\n////\tpSortedMaterialList = (NsMaterial **)OSAlloc ( sizeof ( NsMaterial *) * numEntries );\r\n//\tm_pMaterialList = (NsMaterial *)new unsigned char[ sizeof ( NsMaterial ) * numEntries ];\r\n//\tm_pSortedMaterialList = (NsMaterial **)new unsigned char[ sizeof ( NsMaterial *) * numEntries ];\r\n//\r\n//\tassert ( m_pMaterialList );\r\n//\tm_materialListSize = numEntries;\r\n//\r\n//\treset();\r\n//\r\n//\tm_refCount = 0;\r\n//\r\n//\t// Defaults.\r\n//\tfor ( unsigned int lp = 0; lp < numEntries; lp++ ) {\r\n//\t\tm_pMaterialList[lp].m_wrap = NsTexture_Wrap_Repeat;\r\n//\t}\r\n//}\r\n//\r\n//NsMaterialMan::~NsMaterialMan()\r\n//{\r\n//\tint lp;\r\n//\tint count;\r\n//\r\n//\t// Delete display lists from materials.\r\n//\tcount = 0;\r\n//\tfor ( lp = 0; lp < m_materialListSize; lp++ ) {\r\n//\t\t\r\n//\t\t// Remove pools from display lists.\r\n//\t\tNsDL * pDL = m_pSortedMaterialList[lp]->m_pDL;\r\n//\t\tNsDL * pKillDL;\r\n//\t\twhile ( pDL ) {\r\n//\t\t\tpKillDL = pDL;\r\n//\t\t\tpDL = pDL->m_pNext;\r\n//\t\r\n//\t//\t\tif ( pKillDL->m_pParent->m_pVertexPool ) {\r\n//\t//\t\t\tdelete pKillDL->m_pParent->m_pVertexPool;\r\n//\t//\t\t\tpKillDL->m_pParent->m_pVertexPool = NULL;\r\n//\t//\t\t}\r\n//\t\t\tif ( pKillDL->m_pParent->m_pFaceFlags ) {\r\n//\t\t\t\tdelete pKillDL->m_pParent->m_pFaceFlags;\r\n//\t\t\t\tpKillDL->m_pParent->m_pFaceFlags = NULL;\r\n//\t\t\t\tcount++;\r\n//\t\t\t}\r\n//\t\t\tif ( pKillDL->m_pParent->m_pFaceMaterial ) {\r\n//\t\t\t\tdelete pKillDL->m_pParent->m_pFaceMaterial;\r\n//\t\t\t\tpKillDL->m_pParent->m_pFaceMaterial = NULL;\r\n//\t\t\t\tcount++;\r\n//\t\t\t}\r\n//\t\t\tif ( pKillDL->m_pParent->m_pVertexPool && ( ( pKillDL->m_pParent->m_vpoolFlags & (1<<4) ) == 0 ) ) {\r\n//\t\t\t\tdelete pKillDL->m_pParent->m_pVertexPool;\r\n//\t\t\t\tpKillDL->m_pParent->m_pVertexPool = NULL;\r\n//\t\t\t\tcount++;\r\n//\t\t\t}\r\n//\t\t\tif ( pKillDL->m_pParent->m_pWibbleData ) {\r\n//\t\t\t\tdelete pKillDL->m_pParent->m_pWibbleData;\r\n//\t\t\t\tpKillDL->m_pParent->m_pWibbleData = NULL;\r\n//\t\t\t\tcount++;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t// Delete display lists from materials.\r\n//\tcount = 0;\r\n//\tfor ( lp = 0; lp < m_materialListSize; lp++ ) {\r\n//\t\t// Remove all display lists.\r\n//\t\tNsDL * pDL = m_pSortedMaterialList[lp]->m_pDL;\r\n//\t\tNsDL * pKillDL;\r\n//\t\twhile ( pDL ) {\r\n//\t\t\tpKillDL = pDL;\r\n//\t\t\tpDL = pDL->m_pNext;\r\n//\t\t\tdelete pKillDL;\r\n//\t\t\tcount++;\r\n//\t\t}\r\n//\t\t// Delete wibble data.\r\n//\t\tif ( m_pSortedMaterialList[lp] ) {\r\n//\t\t\tif ( m_pSortedMaterialList[lp]->m_pWibbleData ) {\r\n//\t\t\t\tfor ( int kk = 0; kk < 8; kk++ ) {\r\n//\t\t\t\t\tif ( m_pSortedMaterialList[lp]->m_pWibbleData[kk].pKeys ) {\r\n//\t\t\t\t\t\tdelete m_pSortedMaterialList[lp]->m_pWibbleData[kk].pKeys;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t}\r\n//\t\t\t\tdelete m_pSortedMaterialList[lp]->m_pWibbleData;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\t\r\n//\t// Delete display lists from materials.\r\n//\tfor ( lp = 0; lp < m_materialListSize; lp++ ) {\r\n//\t\tif ( m_pSortedMaterialList[lp] ) m_pSortedMaterialList[lp]->deleteDLs();\r\n//\t}\r\n//\r\n//\t// Delete materials and sorted material lists.\r\n//\tassertf( m_refCount == 0, ( \"Tried to delete material manager when reference count was non-zero.\" ) );\r\n//\tif ( m_pMaterialList ) delete m_pMaterialList;\r\n//\tif ( m_pSortedMaterialList ) delete m_pSortedMaterialList;\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tretrieve\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tnumber\tThe material number to retrieve.\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPointer to the requested material. NULL if out of range.\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tRetrieve a material from the material manager.\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsMaterial * NsMaterialMan::retrieve ( unsigned int number )\r\n//{\r\n//\tNsMaterial * rv;\r\n//\r\n//\tif ( ( (int)number < m_materialListSize ) && ( number >= 0 ) ) {\r\n//\t\trv = &m_pMaterialList[number];\r\n//\t} else {\r\n//\t\trv = NULL;\r\n//\t}\r\n//\r\n//\treturn rv;\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tdraw\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tDraws all display lists attached to each material in this\t\t*\r\n// *\t\t\t\tmaterial manager object.\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void NsMaterialMan::draw ( void )\r\n//{\r\n//\tint lp;\r\n//\r\n//\tfor ( lp = 0; lp < m_materialListSize; lp++ ) {\r\n//\t\tif ( m_pSortedMaterialList[lp] ) m_pSortedMaterialList[lp]->draw();\r\n////\t\tpMaterialList[lp].draw();\r\n//\t}\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tcull\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tSets chunks of geometry that aren't visible to invisible.\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//unsigned int NsMaterialMan::cull ( NsMatrix * m )\r\n//{\r\n//\tint\t\t\t\tlp;\r\n//\tint\t\t\t\tlp2;\r\n//\tNsMaterial\t  * pMat;\r\n//\tNsDL\t\t  * pDL;\r\n//\tunsigned int\tcode;\r\n//\tunsigned int\tcodeAND;\r\n////\tunsigned int\tcodeOR;\r\n//\tf32\t\t\t\trx[8], ry[8], rz[8];\r\n//\tf32\t\t\t\tp[GX_PROJECTION_SZ];\r\n//\tf32\t\t\t\tvp[GX_VIEWPORT_SZ];\r\n//\tu32\t\t\t\tclip_x;\r\n//\tu32\t\t\t\tclip_y;\r\n//\tu32\t\t\t\tclip_w;\r\n//\tu32\t\t\t\tclip_h;\r\n//\tfloat\t\t\tclip_l;\r\n//\tfloat\t\t\tclip_t;\r\n//\tfloat\t\t\tclip_r;\r\n//\tfloat\t\t\tclip_b;\r\n//\tMtxPtr\t\t\tview;\r\n//\tfloat\t\t\tminx, miny, minz;\r\n//\tfloat\t\t\tmaxx, maxy, maxz;\r\n//\tunsigned int\trv = 0;\t\t// Invisible until we get a visible code.\r\n//\r\n//\tGXGetProjectionv( p );\r\n//\tGXGetViewportv( vp );\r\n//\tGXGetScissor ( &clip_x, &clip_y, &clip_w, &clip_h );\r\n//\tclip_l = (float)clip_x;\r\n//\tclip_t = (float)clip_y;\r\n//\tclip_r = (float)(clip_x + clip_w);\r\n//\tclip_b = (float)(clip_y + clip_h);\r\n//\r\n//\tview = m->m_matrix;\r\n//\r\n//\tfor ( lp = 0; lp < m_materialListSize; lp++ ) {\r\n//\t\tpMat = &m_pMaterialList[lp];\r\n//\t\tif ( pMat ) {\r\n//\t\t\tif ( !( pMat->m_flags & mINVISIBLE ) && pMat->m_nDL ) {\r\n//\t\t\t\tpDL = pMat->m_pDL;\r\n//\t\t\t\tdo {\r\n//\t\t\t\t\tpDL->m_cull.visible = 1;\r\n//\t\t\t\t\tif ( pDL != pDL->m_pParent ) continue;\r\n//\t\t\t\t\tminx = pDL->m_cull.box.m_min.x;\r\n//\t\t\t\t\tminy = pDL->m_cull.box.m_min.y;\r\n//\t\t\t\t\tminz = pDL->m_cull.box.m_min.z;\r\n//\t\t\t\t\tmaxx = pDL->m_cull.box.m_max.x;\r\n//\t\t\t\t\tmaxy = pDL->m_cull.box.m_max.y;\r\n//\t\t\t\t\tmaxz = pDL->m_cull.box.m_max.z;\r\n//\t\t\t\t\tGXProject ( minx, miny, minz, view, p, vp, &rx[0], &ry[0], &rz[0] );\r\n//\t\t\t\t\tGXProject ( minx, maxy, minz, view, p, vp, &rx[1], &ry[1], &rz[1] );\r\n//\t\t\t\t\tGXProject ( maxx, miny, minz, view, p, vp, &rx[2], &ry[2], &rz[2] );\r\n//\t\t\t\t\tGXProject ( maxx, maxy, minz, view, p, vp, &rx[3], &ry[3], &rz[3] );\r\n//\t\t\t\t\tGXProject ( minx, miny, maxz, view, p, vp, &rx[4], &ry[4], &rz[4] );\r\n//\t\t\t\t\tGXProject ( minx, maxy, maxz, view, p, vp, &rx[5], &ry[5], &rz[5] );\r\n//\t\t\t\t\tGXProject ( maxx, miny, maxz, view, p, vp, &rx[6], &ry[6], &rz[6] );\r\n//\t\t\t\t\tGXProject ( maxx, maxy, maxz, view, p, vp, &rx[7], &ry[7], &rz[7] );\r\n//\r\n//\t\t\t\t\t// Generate clip code. {page 178, Procedural Elements for Computer Graphics}\r\n//\t\t\t\t\t// 1001|1000|1010\r\n//\t\t\t\t\t//     |    |\r\n//\t\t\t\t\t// ----+----+----\r\n//\t\t\t\t\t// 0001|0000|0010\r\n//\t\t\t\t\t//     |    |\r\n//\t\t\t\t\t// ----+----+----\r\n//\t\t\t\t\t// 0101|0100|0110\r\n//\t\t\t\t\t//     |    |\r\n//\t\t\t\t\t//\r\n//\t\t\t\t\t// Addition: Bit 4 is used for z behind.\r\n//\r\n//\t\t\t\t\tcodeAND\t= 0x001f;\r\n////\t\t\t\t\tcodeOR\t= 0x0000;\r\n//\t\t\t\t\tfor ( lp2 = 0; lp2 < 8; lp2++ ) {\r\n//\t\t\t\t\t\t// Only check x/y if z is valid (if z is invalid, the x/y values will be garbage).\r\n//\t\t\t\t\t\tif ( rz[lp2] > 1.0f   ) {\r\n//\t\t\t\t\t\t\tcode = (1<<4);\r\n//\t\t\t\t\t\t} else {\r\n//\t\t\t\t\t\t\tcode = 0;\r\n//\t\t\t\t\t\t\tif ( rx[lp2] < clip_l ) code |= (1<<0);\r\n//\t\t\t\t\t\t\tif ( rx[lp2] > clip_r ) code |= (1<<1);\r\n//\t\t\t\t\t\t\tif ( ry[lp2] > clip_b ) code |= (1<<2);\r\n//\t\t\t\t\t\t\tif ( ry[lp2] < clip_t ) code |= (1<<3);\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t\tcodeAND\t&= code;\r\n////\t\t\t\t\t\tcodeOR\t|= code;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\tpDL->m_cull.clipCodeAND = codeAND;\r\n////\t\t\t\t\tpDL->cull.clipCodeOR = codeOR;\r\n//\t\t\t\t\t// If any bits are set in the AND code, the object is invisible.\r\n//\t\t\t\t\tif ( codeAND ) {\r\n//\t\t\t\t\t\tpDL->m_cull.visible = 0;\r\n//\t\t\t\t\t} else {\r\n//\t\t\t\t\t\trv = 1;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t} while (( pDL = pDL->m_pNext) );\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\treturn rv;\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tcalculateBoundingBox\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tSets chunks of geometry that aren't visible to invisible.\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void NsMaterialMan::calculateBoundingBox ( NsCull_Item * pCull )\r\n//{\r\n//\tint\t\t\t\tlp;\r\n//\tNsMaterial\t  * pMat;\r\n//\tNsDL\t\t  * pDL;\r\n//\tint\t\t\t\tdirty = 1;\r\n//\r\n//\tfor ( lp = 0; lp < m_materialListSize; lp++ ) {\r\n//\t\tpMat = &m_pMaterialList[lp];\r\n//\t\tif ( pMat ) {\r\n//\t\t\tif ( pMat->m_nDL ) {\r\n//\t\t\t\tpDL = pMat->m_pDL;\r\n//\t\t\t\tdo {\r\n//\t\t\t\t\tif ( dirty ) {\r\n//\t\t\t\t\t\tpCull->box.m_min.copy( pDL->m_cull.box.m_min );\r\n//\t\t\t\t\t\tpCull->box.m_max.copy( pDL->m_cull.box.m_max );\r\n//\t\t\t\t\t\tdirty = 0;\r\n//\t\t\t\t\t} else {\r\n//\t\t\t\t\t\tif ( pCull->box.m_min.x < pDL->m_cull.box.m_min.x ) pCull->box.m_min.x = pDL->m_cull.box.m_min.x;\r\n//\t\t\t\t\t\tif ( pCull->box.m_min.y < pDL->m_cull.box.m_min.y ) pCull->box.m_min.y = pDL->m_cull.box.m_min.y;\r\n//\t\t\t\t\t\tif ( pCull->box.m_min.z < pDL->m_cull.box.m_min.z ) pCull->box.m_min.z = pDL->m_cull.box.m_min.z;\r\n//\t\t\t\t\t\tif ( pCull->box.m_max.x > pDL->m_cull.box.m_max.x ) pCull->box.m_max.x = pDL->m_cull.box.m_min.x;\r\n//\t\t\t\t\t\tif ( pCull->box.m_max.y > pDL->m_cull.box.m_max.y ) pCull->box.m_max.y = pDL->m_cull.box.m_min.y;\r\n//\t\t\t\t\t\tif ( pCull->box.m_max.z > pDL->m_cull.box.m_max.z ) pCull->box.m_max.z = pDL->m_cull.box.m_min.z;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t} while (( pDL = pDL->m_pNext) );\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n//int NsMaterialMan::findCollision( NsLine * pLine, NsDL::Collision_LineCallback pCb, void * pData, void * pWorld )\r\n//{\r\n//\tint\t\t\t\tlp;\r\n//\tNsMaterial\t  * pMat;\r\n//\tNsDL\t\t  * pDL;\r\n//\tNsBBox\t\t\tline;\r\n//\tint\t\t\t\trv = 0;\r\n//\r\n//\tCollisionTime.start();\r\n//\t\r\n//\tline.m_min.x = pLine->start.x < pLine->end.x ? pLine->start.x : pLine->end.x;\r\n//\tline.m_min.y = pLine->start.y < pLine->end.y ? pLine->start.y : pLine->end.y;\r\n//\tline.m_min.z = pLine->start.z < pLine->end.z ? pLine->start.z : pLine->end.z;\r\n//\tline.m_max.x = pLine->start.x > pLine->end.x ? pLine->start.x : pLine->end.x;\r\n//\tline.m_max.y = pLine->start.y > pLine->end.y ? pLine->start.y : pLine->end.y;\r\n//\tline.m_max.z = pLine->start.z > pLine->end.z ? pLine->start.z : pLine->end.z;\r\n//\r\n//#\tif 0\r\n//\t// Using the SuperSectors does seem to give a 15 - 20% speed increase.\r\n//\tSSec::Manager* p_ss_man\t= (SSec::Manager*)((NsScene*)pWorld )->m_SSMan;\r\n//\tNsWorldSector**\tpp_sectors = p_ss_man->GetIntersectingWorldSectors( (RwLine*)pLine );\r\n//\tfor( ;; )\r\n//\t{\r\n//\t\tNsWorldSector* pDL = *pp_sectors++;\r\n//\t\tif( pDL == NULL )\r\n//\t\t{\r\n//\t\t\t// Finished.\r\n//\t\t\tbreak;\r\n//\t\t}\r\n//\r\n//\t\tif( pDL->m_numPoly && !( pDL->m_pParent->m_rwflags & ( mSD_NON_COLLIDABLE | mSD_KILLED )))\r\n//\t\t{\r\n//\t\t\tif( Cld::BoxIntersectsBox( &pDL->m_cull.box, &line ))\r\n//\t\t\t{\r\n//\t\t\t\trv |= pDL->findCollision( pLine, pCb, pData );\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//#\telse\r\n//\tfor ( lp = 0; lp < m_materialListSize; lp++ ) {\r\n//\t\tpMat = &m_pMaterialList[lp];\r\n//\t\tif ( pMat ) {\r\n//\t\t\tif ( pMat->m_nDL ) {\r\n//\t\t\t\tpDL = pMat->m_pDL;\r\n//\t\t\t\tdo {\r\n//\t\t\t\t\tif ( pDL->m_numPoly && !( pDL->m_pParent->m_rwflags & ( mSD_NON_COLLIDABLE | mSD_KILLED ) ) ) {\r\n////\t\t                if( Cld::BoxIntersectsBox( &pDL->m_cull.box, &line ) ) {\r\n//\t\t\t\t\t\t\trv |= pDL->findCollision( pLine, pCb, pData );\r\n////\t\t\t\t\t\t}\r\n//\t\t\t\t\t}\r\n//\t\t\t\t} while (( pDL = pDL->m_pNext) );\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//#\tendif\r\n//\r\n//\tCollisionTime.stop();\r\n//\r\n//\treturn rv;\r\n//}\r\n//\r\n//\r\n//\r\n//void NsMaterialMan::reset ( void )\r\n//{\r\n//\tint lp;\r\n//\r\n//\t// Set material list up.\r\n//\tfor ( lp = 0; lp < m_materialListSize; lp++ ) {\r\n//\t\tm_pMaterialList[lp].init ( lp );\r\n//\t\tm_pSortedMaterialList[lp] = NULL;\r\n//\t}\r\n//}\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_matman.h",
    "content": "//#ifndef _MATMAN_H_\r\n//#define _MATMAN_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_material.h\"\r\n//#include \"p_texman.h\"\r\n//#include \"p_collision.h\"\r\n//#include \"p_dl.h\"\r\n//#include \"p_triangle.h\"\r\n//\r\n//class NsMaterialMan\r\n//{\r\n//\tint\t\t\t\tm_refCount;\r\n//public:\r\n//\tNsMaterial\t  * m_pMaterialList;\r\n//\tNsMaterial\t ** m_pSortedMaterialList;\r\n//\tint\t\t\t\tm_materialListSize;\r\n//\tint\t\t\t\tm_numTotal;\r\n//\tint\t\t\t\tm_numCulled;\r\n//\r\n//\tfriend class NsModel;\r\n//\r\n//\t\t\t\t\tNsMaterialMan\t\t\t();\r\n//\t\t\t\t\tNsMaterialMan\t\t\t( unsigned int numEntries );\r\n//\t\t\t\t\t~NsMaterialMan\t\t\t();\r\n//\r\n//\tNsMaterial\t  * retrieve\t\t\t\t( unsigned int number );\r\n//\r\n//\tvoid\t\t\tdraw\t\t\t\t\t( void );\r\n//\r\n//\tunsigned int\tcull\t\t\t\t\t( NsMatrix * m );\r\n//\r\n//\tvoid\t\t\treset\t\t\t\t\t( void );\r\n//\r\n//\tvoid\t\t\tcalculateBoundingBox\t( NsCull_Item * pCull );\r\n//\r\n//\tint\t\t\t\tfindCollision\t\t\t( NsLine * pLine, NsDL::Collision_LineCallback pCb, void * pData, void* pWorld );\r\n//\r\n//\tvoid\t\t\taddReference\t\t\t( void ) { m_refCount++; }\r\n//\tvoid\t\t\tremoveReference\t\t\t( void ) { m_refCount--; }\r\n//\tint\t\t\t\ttotalReferences\t\t\t( void ) { return m_refCount; }\r\n//};\r\n//\r\n//#endif\t\t// _MATMAN_H_\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_matrix.cpp",
    "content": "/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsMatrix\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tMatrix functionality.\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#include <math.h>\r\n#include <string.h>\r\n#include \"p_frame.h\"\r\n#include \"p_matrix.h\"\r\n#include <core/defines.h>\r\n#include <core/math/math.h>\r\n\r\n/********************************************************************************\r\n * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nvoid NsMatrix::translate ( NsVector * v, NsMatrix_Combine c )\r\n{\r\n\tMtx temp;\r\n    switch (c) {\r\n        case NsMatrix_Combine_Replace:\r\n\t\t\tMTXTrans( m_matrix, v->x, v->y, v->z );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Pre:\r\n\t\t\tMTXTrans( temp, v->x, v->y, v->z );\r\n\t\t\tMTXConcat( m_matrix, temp, m_matrix );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Post:\r\n\t\t\tMTXTrans( temp, v->x, v->y, v->z );\r\n\t\t\tMTXConcat( temp, m_matrix, m_matrix );\r\n\t\t\tbreak;\r\n        default:\r\n\t\t\tbreak;\r\n    }\r\n}\r\n\r\nvoid NsMatrix::rotate ( NsVector * axis, float angle, NsMatrix_Combine c )\r\n{\r\n\tMtx temp;\r\n\r\n    switch (c) {\r\n        case NsMatrix_Combine_Replace:\r\n\t\t\tMTXRotAxisDeg( m_matrix, (Vec*)axis, angle );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Pre:\r\n\t\t\tMTXRotAxisDeg( temp, (Vec*)axis, angle );\r\n\t\t\tMTXConcat( m_matrix, temp, m_matrix );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Post:\r\n\t\t\tMTXRotAxisDeg( temp, (Vec*)axis, angle );\r\n\t\t\tMTXConcat( temp, m_matrix, m_matrix );\r\n\t\t\tbreak;\r\n        default:\r\n\t\t\tbreak;\r\n    }\r\n}\r\n\r\nvoid NsMatrix::rotateX( float degrees, NsMatrix_Combine c )\r\n{\r\n\tMtx temp;\r\n\r\n    switch (c) {\r\n        case NsMatrix_Combine_Replace:\r\n\t\t    MTXRotDeg(m_matrix, 'x', degrees );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Pre:\r\n\t\t    MTXRotDeg(temp, 'x', degrees );\r\n\t\t\tMTXConcat( m_matrix, temp, m_matrix );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Post:\r\n\t\t    MTXRotDeg(temp, 'x', degrees );\r\n\t\t\tMTXConcat( temp, m_matrix, m_matrix );\r\n\t\t\tbreak;\r\n        default:\r\n\t\t\tbreak;\r\n    }\r\n}\r\n\r\nvoid NsMatrix::rotateY( float degrees, NsMatrix_Combine c )\r\n{\r\n\tMtx temp;\r\n\r\n    switch (c) {\r\n        case NsMatrix_Combine_Replace:\r\n\t\t    MTXRotDeg(m_matrix, 'y', degrees );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Pre:\r\n\t\t    MTXRotDeg(temp, 'y', degrees );\r\n\t\t\tMTXConcat( m_matrix, temp, m_matrix );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Post:\r\n\t\t    MTXRotDeg(temp, 'y', degrees );\r\n\t\t\tMTXConcat( temp, m_matrix, m_matrix );\r\n\t\t\tbreak;\r\n        default:\r\n\t\t\tbreak;\r\n    }\r\n}\r\n\r\nvoid NsMatrix::rotateZ( float degrees, NsMatrix_Combine c )\r\n{\r\n\tMtx temp;\r\n\r\n    switch (c) {\r\n        case NsMatrix_Combine_Replace:\r\n\t\t    MTXRotDeg(m_matrix, 'z', degrees );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Pre:\r\n\t\t    MTXRotDeg(temp, 'z', degrees );\r\n\t\t\tMTXConcat( m_matrix, temp, m_matrix );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Post:\r\n\t\t    MTXRotDeg(temp, 'z', degrees );\r\n\t\t\tMTXConcat( temp, m_matrix, m_matrix );\r\n\t\t\tbreak;\r\n        default:\r\n\t\t\tbreak;\r\n    }\r\n}\r\n\r\nvoid NsMatrix::scale ( NsVector * v, NsMatrix_Combine c )\r\n{\r\n\tMtx temp;\r\n    switch (c) {\r\n        case NsMatrix_Combine_Replace:\r\n\t\t\tMTXScale( m_matrix, v->x, v->y, v->z );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Pre:\r\n\t\t\tMTXScale( temp, v->x, v->y, v->z );\r\n\t\t\tMTXConcat( m_matrix, temp, m_matrix );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Post:\r\n\t\t\tMTXScale( temp, v->x, v->y, v->z );\r\n\t\t\tMTXConcat( temp, m_matrix, m_matrix );\r\n\t\t\tbreak;\r\n        default:\r\n\t\t\tbreak;\r\n    }\r\n}\r\n\r\nvoid NsMatrix::identity ( void )\r\n{\r\n\tMTXIdentity( m_matrix );\r\n}\r\n\r\nvoid NsMatrix::getRotation( NsVector * axis, float * angle, NsVector * center )\r\n{\r\n    float\t\tnTwoSinTheta, nTwoCosTheta;\r\n    NsVector\tvTwoSinThetaAxis;\r\n    float\t\tnRadians;\r\n//    Mtx\t\tmISubMat;\r\n//    Mtx\t\tmISubMatInverse;\r\n\r\n\r\n    nTwoCosTheta = getRight()->x + getUp()->y + getAt()->z - 1.0f;\r\n\r\n\t//\tDave 08/07/01 - Unsure as to exactly why the negation of the axis fixes the slerping problem\r\n\t// (getRotation() is called from NsSlerp::SetMatrices(), but it does. Investigate further at some point...\r\n//\tvTwoSinThetaAxis.x = getUp()->z - getAt()->y;\r\n//\tvTwoSinThetaAxis.y = getAt()->x - getRight()->z;\r\n//\tvTwoSinThetaAxis.z = getRight()->y - getUp()->x;\r\n    vTwoSinThetaAxis.x = getAt()->y - getUp()->z;\r\n    vTwoSinThetaAxis.y = getRight()->z - getAt()->x;\r\n    vTwoSinThetaAxis.z = getUp()->x - getRight()->y;\r\n\r\n\tnTwoSinTheta = vTwoSinThetaAxis.length();\r\n    if (nTwoSinTheta > 0.0f)\r\n    {\r\n        float  recipLength = (1.0f / (nTwoSinTheta));\r\n\r\n\t\taxis->scale( vTwoSinThetaAxis, recipLength );\r\n    }\r\n    else\r\n    {\r\n        axis->set( 0.0f, 0.0f, 0.0f );\r\n    }\r\n    nRadians = atan2(nTwoSinTheta, nTwoCosTheta);\r\n    (*angle) = nRadians * (((float) 180) / ((float) Mth::PI));\r\n    if ((nTwoSinTheta <= 0.01f) && (nTwoCosTheta <= 0.0f))\r\n    {\r\n        /*\r\n         * sin theta is 0; cos theta is -1; theta is 180 degrees\r\n         * vTwoSinThetaAxis was degenerate\r\n         * axis will have to be found another way.\r\n         */\r\n\r\n\t\tNsVector\tvTwoSinThetaAxis;\r\n\r\n\t\t/*\r\n\t\t * Matrix is:\r\n\t\t * [ [ 2 a_x^2 - 1,  2 a_x a_y,   2 a_x a_z,  0 ]\r\n\t\t *   [  2 a_x a_y,  2 a_y^2 - 1,  2 a_y a_z,  0 ]\r\n\t\t *   [  2 a_x a_z,   2 a_y a_z,  2 a_z^2 - 1, 0 ]\r\n\t\t *   [      0,           0,           0,      1 ] ]\r\n\t\t * Build axis scaled by 4 * component of maximum absolute value\r\n\t\t */\r\n\t    if (getRight()->x > getUp()->y)\r\n\t    {\r\n\t        if (getRight()->x > getAt()->z)\r\n\t        {\r\n\t            vTwoSinThetaAxis.x = 1.0f + getRight()->x;\r\n\t            vTwoSinThetaAxis.x = vTwoSinThetaAxis.x + vTwoSinThetaAxis.x;\r\n\t            vTwoSinThetaAxis.y = getRight()->y + getUp()->x;\r\n\t            vTwoSinThetaAxis.z = getRight()->z + getAt()->x;\r\n\t        }\r\n\t        else\r\n\t        {\r\n\t            vTwoSinThetaAxis.z = 1.0f + getAt()->z;\r\n\t            vTwoSinThetaAxis.z = vTwoSinThetaAxis.z + vTwoSinThetaAxis.z;\r\n\t            vTwoSinThetaAxis.x = getAt()->x + getRight()->z;\r\n\t            vTwoSinThetaAxis.y = getAt()->y + getUp()->z;\r\n\t        }\r\n\t    }\r\n\t    else\r\n\t    {\r\n\t        if (getUp()->y > getAt()->z)\r\n\t        {\r\n\t            vTwoSinThetaAxis.y = 1.0f + getUp()->y;\r\n\t            vTwoSinThetaAxis.y = vTwoSinThetaAxis.y + vTwoSinThetaAxis.y;\r\n\t            vTwoSinThetaAxis.z = getUp()->z + getAt()->y;\r\n\t            vTwoSinThetaAxis.x = getUp()->x + getRight()->y;\r\n\t        }\r\n\t        else\r\n\t        {\r\n\t            vTwoSinThetaAxis.z = 1.0f + getAt()->z;\r\n\t            vTwoSinThetaAxis.z = (vTwoSinThetaAxis.z + vTwoSinThetaAxis.z);\r\n\t            vTwoSinThetaAxis.x = getAt()->x + getRight()->z;\r\n\t            vTwoSinThetaAxis.y = getAt()->y + getUp()->z;\r\n\t        }\r\n\t    }\r\n\r\n\t\t/*\r\n\t\t * and normalize the axis\r\n\t\t */\r\n\r\n\t\taxis->normalize( vTwoSinThetaAxis );\r\n    }\r\n\r\n//    /*\r\n//     * Find center of line of rotation:\r\n//     * [ v - c ] * R + c   = v * R + s\r\n//     * -> v * R + c - c *  R = v * R + s\r\n//     * -> c * [ I - R ]      = s\r\n//     * -> c                  = s * [ I - R ] ^ -1\r\n//     */\r\n//\r\n//    MtxSetIdentity(&mISubMat);\r\n//    /*\r\n//     * Find [ I - R ] ^ -1\r\n//     */\r\n//    VecSubMacro(&mISubMat.right, &mISubMat.right, &matrix->right);\r\n//    VecSubMacro(&mISubMat.up, &mISubMat.up, &matrix->up);\r\n//    VecSubMacro(&mISubMat.at, &mISubMat.at, &matrix->at);\r\n//    MtxSetFlags(&mISubMat, GENERIC_FLAGS(&mISubMatInverse));\r\n//    MtxSetFlags(&mISubMatInverse, GENERIC_FLAGS(&mISubMatInverse));\r\n//    /* MatrixInvertOrthoNormalized(&mISubMatInverse, &mISubMat); */\r\n//    MatrixInvertGeneric(&mISubMatInverse, &mISubMat);\r\n//    /*\r\n//     * Find s * [ I - R ] ^ -1\r\n//     */\r\n//    *center = mISubMatInverse.pos;\r\n//    VecIncrementScaledMacro(center, &mISubMatInverse.right, m[0][3]);\r\n//    VecIncrementScaledMacro(center, &mISubMatInverse.up, m[1][3]);\r\n//    VecIncrementScaledMacro(center, &mISubMatInverse.at, m[2][3]);\r\n//\r\n//    RWRETURN(matrix);\r\n}\r\n\r\nvoid NsMatrix::transform ( NsMatrix& a, NsMatrix_Combine c )\r\n{\r\n    switch (c) {\r\n        case NsMatrix_Combine_Replace:\r\n\t\t\tcopy( a );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Pre:\r\n\t\t\tMTXConcat( m_matrix, a.m_matrix, m_matrix );\r\n\t\t\tbreak;\r\n        case NsMatrix_Combine_Post:\r\n\t\t\tMTXConcat( a.m_matrix, m_matrix, m_matrix );\r\n\t\t\tbreak;\r\n        default:\r\n\t\t\tbreak;\r\n    }\r\n}\r\n\r\nvoid NsMatrix::cat ( NsMatrix& a, NsMatrix& b )\r\n{\r\n\tMTXConcat( a.m_matrix, b.m_matrix, m_matrix );\r\n}\r\n\r\nvoid NsMatrix::invert( void )\r\n{\r\n\tMTXInverse( m_matrix, m_matrix );\r\n}\r\n\r\nvoid NsMatrix::invert( NsMatrix& source )\r\n{\r\n\tMTXInverse( source.m_matrix, m_matrix );\r\n}\r\n\r\nvoid NsMatrix::copy( NsMatrix& source )\r\n{\r\n\tmemcpy( this, &source, sizeof( NsMatrix ) );\r\n}\r\n\r\nvoid NsMatrix::lookAt ( NsVector * pPos, NsVector * pUp, NsVector * pTarget )\r\n{\r\n\tMTXLookAt( m_matrix, (Vec*)pPos, (Vec*)pUp, (Vec*)pTarget );\r\n}\r\n\r\n//void NsMatrix::fromQuat ( NsQuat * pQuat )\r\n//{\r\n//\tMTXQuat ( m_matrix, &pQuat->m_quat );\r\n//}\r\n\r\nvoid NsMatrix::multiply( NsVector * pSourceBase, NsVector * pDestBase )\r\n{\r\n\tMTXMultVec( m_matrix, (Vec*)pSourceBase, (Vec*)pDestBase );\r\n}\r\n\r\nvoid NsMatrix::multiply( NsVector * pSourceBase, NsVector * pDestBase, int count )\r\n{\r\n\tMTXMultVecArray( m_matrix, (Vec*)pSourceBase, (Vec*)pDestBase, count );\r\n}\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_matrix.h",
    "content": "#ifndef _MATRIX_H_\r\n#define _MATRIX_H_\r\n\r\n#include <dolphin.h>\r\n#include \"p_vector.h\"\r\n//#include \"p_quat.h\"\r\n\r\ntypedef enum {\r\n\tNsMatrix_Combine_Replace,\r\n\tNsMatrix_Combine_Pre,\r\n\tNsMatrix_Combine_Post,\r\n\r\n\tNsMatrix_Combine_Max\r\n} NsMatrix_Combine;\r\n\r\nclass NsMatrix\r\n{\r\n\tMtx\t\t\tm_matrix;\r\npublic:\r\n\tfriend class NsVector;\r\n\tfriend class NsCamera;\r\n\tfriend class NsMaterialMan;\r\n\tfriend class NsClump;\r\n\tfriend class NsDL;\r\n\r\n\tvoid\t\ttranslate\t\t( NsVector * v, NsMatrix_Combine c );\r\n\tvoid\t\trotate\t\t\t( NsVector * axis, float angle, NsMatrix_Combine c );\r\n\tvoid\t\trotateX\t\t\t( float degrees, NsMatrix_Combine c );\r\n\tvoid\t\trotateY\t\t\t( float degrees, NsMatrix_Combine c );\r\n\tvoid\t\trotateZ\t\t\t( float degrees, NsMatrix_Combine c );\r\n\tvoid\t\tscale\t\t\t( NsVector * v, NsMatrix_Combine c );\r\n\tvoid\t\tinvert\t\t\t( void );\r\n\tvoid\t\tinvert\t\t\t( NsMatrix& source );\r\n\tvoid\t\tidentity\t\t( void );\r\n\tvoid\t\ttransform\t\t( NsMatrix& a, NsMatrix_Combine c );\r\n\tvoid\t\tcat\t\t\t\t( NsMatrix& a, NsMatrix& b );\r\n\r\n\tvoid\t\tcopy\t\t\t( NsMatrix& source );\r\n\r\n\tvoid\t\tgetRotation\t\t( NsVector * axis, float * angle, NsVector * center );\r\n\r\n\tvoid\t\tlookAt\t\t\t( NsVector * pPos, NsVector * pUp, NsVector * pTarget );\r\n\r\n//\tvoid\t\tfromQuat\t\t( NsQuat * pQuat );\r\n\r\n\tNsVector  * getRight\t\t( void ) { return (NsVector *)&m_matrix[0][0]; }\r\n\tNsVector  * getUp\t\t\t( void ) { return (NsVector *)&m_matrix[1][0]; }\r\n\tNsVector  * getAt\t\t\t( void ) { return (NsVector *)&m_matrix[2][0]; }\r\n\r\n\tfloat\t\tgetRightX\t\t( void ) { return m_matrix[0][0]; }\r\n\tfloat\t\tgetRightY\t\t( void ) { return m_matrix[0][1]; }\r\n\tfloat\t\tgetRightZ\t\t( void ) { return m_matrix[0][2]; }\r\n\r\n\tfloat\t\tgetUpX\t\t\t( void ) { return m_matrix[1][0]; }\r\n\tfloat\t\tgetUpY\t\t\t( void ) { return m_matrix[1][1]; }\r\n\tfloat\t\tgetUpZ\t\t\t( void ) { return m_matrix[1][2]; }\r\n\r\n\tfloat\t\tgetAtX\t\t\t( void ) { return m_matrix[2][0]; }\r\n\tfloat\t\tgetAtY\t\t\t( void ) { return m_matrix[2][1]; }\r\n\tfloat\t\tgetAtZ\t\t\t( void ) { return m_matrix[2][2]; }\r\n\r\n\tfloat\t\tgetPosX\t\t\t( void ) { return m_matrix[0][3]; }\r\n\tfloat\t\tgetPosY\t\t\t( void ) { return m_matrix[1][3]; }\r\n\tfloat\t\tgetPosZ\t\t\t( void ) { return m_matrix[2][3]; }\r\n\r\n\tvoid\t\tsetRight\t\t( NsVector * p ) { m_matrix[0][0] = p->x; m_matrix[0][1] = p->y; m_matrix[0][2] = p->z; }\r\n\tvoid\t\tsetUp\t\t\t( NsVector * p ) { m_matrix[1][0] = p->x; m_matrix[1][1] = p->y; m_matrix[1][2] = p->z; }\r\n\tvoid\t\tsetAt\t\t\t( NsVector * p ) { m_matrix[2][0] = p->x; m_matrix[2][1] = p->y; m_matrix[2][2] = p->z; }\r\n\tvoid\t\tsetPos\t\t\t( NsVector * p ) { m_matrix[0][3] = p->x; m_matrix[1][3] = p->y; m_matrix[2][3] = p->z; }\r\n\r\n\tvoid\t\tsetRight\t\t( float x, float y, float z ) { m_matrix[0][0] = x; m_matrix[0][1] = y; m_matrix[0][2] = z; }\r\n\tvoid\t\tsetUp\t\t\t( float x, float y, float z ) { m_matrix[1][0] = x; m_matrix[1][1] = y; m_matrix[1][2] = z; }\r\n\tvoid\t\tsetAt\t\t\t( float x, float y, float z ) { m_matrix[2][0] = x; m_matrix[2][1] = y; m_matrix[2][2] = z; }\r\n\tvoid\t\tsetPos\t\t\t( float x, float y, float z ) { m_matrix[0][3] = x; m_matrix[1][3] = y; m_matrix[2][3] = z; }\r\n\r\n\tvoid\t\tsetRightX\t\t( float f ) { m_matrix[0][0] = f; }\r\n\tvoid\t\tsetUpX\t\t\t( float f ) { m_matrix[1][0] = f; }\r\n\tvoid\t\tsetAtX\t\t\t( float f ) { m_matrix[2][0] = f; }\r\n\tvoid\t\tsetPosX\t\t\t( float f ) { m_matrix[0][3] = f; }\r\n\r\n\tvoid\t\tsetRightY\t\t( float f ) { m_matrix[0][1] = f; }\r\n\tvoid\t\tsetUpY\t\t\t( float f ) { m_matrix[1][1] = f; }\r\n\tvoid\t\tsetAtY\t\t\t( float f ) { m_matrix[2][1] = f; }\r\n\tvoid\t\tsetPosY\t\t\t( float f ) { m_matrix[1][3] = f; }\r\n\r\n\tvoid\t\tsetRightZ\t\t( float f ) { m_matrix[0][2] = f; }\r\n\tvoid\t\tsetUpZ\t\t\t( float f ) { m_matrix[1][2] = f; }\r\n\tvoid\t\tsetAtZ\t\t\t( float f ) { m_matrix[2][2] = f; }\r\n\tvoid\t\tsetPosZ\t\t\t( float f ) { m_matrix[2][3] = f; }\r\n\r\n\tvoid\t\tmultiply\t\t( NsVector * pSourceBase, NsVector * pDestBase );\r\n\tvoid\t\tmultiply\t\t( NsVector * pSourceBase, NsVector * pDestBase, int count );\r\n};\r\n\r\n#endif\t\t// _MATRIX_H_\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_model.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tRender\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tAllows a rendering context to be opened and modified as desired\t*\r\n// *\t\t\t\tby the user. A rendering context must be open before Prim or\t*\r\n// *\t\t\t\tModel commands can be issued.\t\t\t\t\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include \"p_clump.h\"\r\n//#include \"p_scene.h\"\r\n//#ifndef __BSP_UTILS_H__\r\n//#include <sk/engine/bsputils.h>\r\n//#endif\r\n//#include <math.h>\r\n//#include \"p_model.h\"\r\n//#include \"p_assert.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#define rpWORLDUVS ( rpWORLDTEXTURED2 | rpWORLDTEXTURED )\r\n//#define DL_BUILD_SIZE (32*1024)\r\n//\r\n//enum\r\n//{\r\n//\tmTWO_SIDED\t\t\t= 0x01,\r\n//\tmINVISIBLE\t\t\t= 0x02,\r\n//\tmFRONT_FACING\t\t= 0x04,\r\n//\tmTRANSPARENT\t\t= 0x08,\r\n//\tmDECAL\t\t\t\t= 0x10,\r\n//\tmUV_WIBBLE_SUPPORT\t= 0x20,\t// If these two values change, notify Steve as Rw references \r\n//\tmVC_WIBBLE_SUPPORT\t= 0x40, // these two flags by value.\r\n//};\r\n//\r\n//enum RpWorldFlag\r\n//{\r\n//    rpWORLDTRISTRIP = 0x01,     /**<This world's meshes can be rendered\r\n//                                   as tri strips */\r\n//    rpWORLDTEXTURED = 0x04,     /**<This world has one set of texture coordinates */\r\n//    rpWORLDPRELIT = 0x08,       /**<This world has luminance values */\r\n//    rpWORLDNORMALS = 0x10,      /**<This world has normals */\r\n//    rpWORLDLIGHT = 0x20,        /**<This world will be lit */\r\n//    rpWORLDMODULATEMATERIALCOLOR = 0x40, /**<Modulate material color with\r\n//                                            vertex colors (pre-lit + lit) */\r\n//    rpWORLDTEXTURED2 = 0x80, /**<This world has 2 set of texture coordinates */\r\n//\r\n//    /*\r\n//     * These flags are stored in the flags field in an RwObject, the flag field is 8bit.\r\n//     */\r\n//\r\n//    rpWORLDSECTORSOVERLAP = 0x40000000,\r\n//};\r\n//typedef enum RpWorldFlag RpWorldFlag;\r\n//\r\n//enum\r\n//{\r\n//\tmSD_INVISIBLE\t\t\t= 0x0001,\t// Invisible in primary viewport\r\n//\tmSD_NON_COLLIDABLE\t\t= 0x0002,\r\n//\tmSD_KILLED\t\t\t\t= 0x0004,\r\n//\tmSD_DONT_FOG\t\t\t= 0x0008,\r\n//\tmSD_ALWAYS_FACE\t\t\t= 0x0010,\r\n//\tmSD_NO_SKATER_SHADOW\t= 0x0020,\t// This is set at runtime for sectors with every face flagged mFD_SKATER_SHADOW.\r\n//\tmSD_INVISIBLE2\t\t\t= 0x0040,\t// Invisible in secondary viewport (Mick)\r\n//};\r\n//\r\n//enum\r\n//{\r\n//\tMAX_NUM_SEQUENCES\t= 8\r\n//};\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///*---------------------------------------------------------------------------*\r\n//    Name:           BuildMaterials\r\n//    \r\n//    Description:    Builds a material entry for each material.\r\n// \r\n//    Arguments:      pModel\tThe Model data.\r\n//    \r\n//    Returns:        Head of sorted material list.\r\n// \r\n// *---------------------------------------------------------------------------*/\r\n//void NsModel::buildMaterials ( NsMaterialMan * pMaterialList, NsTextureMan * pTexMan )\r\n//{\r\n//\tint\t\t\t\tlp, it;\r\n//\tNsMaterialInfo* pMaterial;\r\n////\tchar\t\t\tbuf[40];\r\n//\tNsTexture\t  * pTex;\r\n//\tNsMaterial\t  *\tpBest;\r\n//\tNsMaterial\t  * pML;\r\n//\r\n//\t// Sanity.\r\n//\tassertf ( (int)m_numMaterials <= pMaterialList->m_materialListSize, ( \"Material list too small.\" ) );\r\n//\r\n// \t// Point up stuff we're interested in.\t\r\n// \tpMaterial = (NsMaterialInfo *)&this[1];\r\n//\tpML = pMaterialList->m_pMaterialList;\r\n//\r\n//\t// Add each material in turn.\r\n//\tfor ( lp = 0; lp < (int)m_numMaterials; lp++ ) {\r\n//\t\tpTex = pTexMan->retrieve ( (const char *)&pMaterial->name );\r\n//\t\tpML->init ( lp );\r\n//\t\tpML->m_pTexture\t\t= pTex;\r\n//\t\tpML->m_blendMode\t= (NsBlendMode)pMaterial->blendmode;\r\n//\t\tpML->m_color\t\t= pMaterial->color;\r\n//\t\tpML->m_alpha\t\t= pMaterial->alpha;\r\n//\t\tpML->m_type\t\t\t= pMaterial->type;\r\n//\t\tpML->m_flags\t\t= pMaterial->flags;\r\n//\t\tpML->m_priority\t\t= pMaterial->priority;\r\n//\t\tpML->m_pWibbleData\t= NULL;\r\n//\t\t\r\n//\t\tNsMaterialInfo* pLastMaterial = pMaterial;\r\n//\t\tpMaterial++;\r\n//\r\n//\t\t// Deal with wibble data if we have it.\r\n//\t\tpML->m_UVWibbleEnabled = pLastMaterial->uvwibble;\r\n//\t\tif ( pLastMaterial->uvwibble ) {\r\n//\t\t\tpML->setFlags( pML->getFlags() | mUV_WIBBLE_SUPPORT );\r\n//\r\n//\t\t\tfloat * pf = (float *)pMaterial;\r\n//\t\t\tpML->m_uvel\t\t= *pf++;\r\n//\t\t\tpML->m_vvel     = *pf++;\r\n//\t\t\tpML->m_uamp     = *pf++;\r\n//\t\t\tpML->m_vamp     = *pf++;\r\n//\t\t\tpML->m_uphase   = *pf++;\r\n//\t\t\tpML->m_vphase   = *pf++;\r\n//\t\t\tpML->m_ufreq    = *pf++;\r\n//\t\t\tpML->m_vfreq    = *pf++;\r\n//\t\t\tpMaterial = (NsMaterialInfo *)pf;\r\n//\t\t}\r\n//\t\tif ( pLastMaterial->vcwibble ) {\r\n//\t\t\tpML->setFlags( pML->getFlags() | mVC_WIBBLE_SUPPORT );\r\n//\r\n//\t\t\t// Set up all sequences.\r\n//\t\t\tunsigned int * p32 = (unsigned int *)pMaterial;\r\n//\t\t\tpML->m_pWibbleData = new NsWibbleSequence[8];\r\n//\t\t\tfor ( int kk = 0; kk < 8; kk++ ) {\r\n//\t\t\t\tpML->m_pWibbleData[kk].numKeys = *p32++;\r\n//\t\t\t\tpML->m_pWibbleData[kk].pKeys = NULL;\r\n//\t\t\t\tif ( pML->m_pWibbleData[kk].numKeys ) {\r\n//\t\t\t\t\tpML->m_pWibbleData[kk].pKeys = new NsWibbleKey[pML->m_pWibbleData[kk].numKeys];\r\n//\t\t\t\t\tmemcpy( pML->m_pWibbleData[kk].pKeys, p32, sizeof( NsWibbleKey ) * pML->m_pWibbleData[kk].numKeys );\r\n//\t\t\t\t\tp32 += pML->m_pWibbleData[kk].numKeys * ( sizeof( NsWibbleKey ) / 4 );\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\tpMaterial = (NsMaterialInfo *)p32;\r\n//\t\t}\r\n//\t\tpML++;\r\n//\t}\r\n//\r\n//\t// Sort the materials. This is slow, but it works, and it only took me 15 minutes to write...\r\n//\tfor ( lp = 0; lp < (int)m_numMaterials; lp++ ) {\r\n//\t\tpBest = &pMaterialList->m_pMaterialList[0];\r\n//\t\tfor ( it = 0; it < (int)m_numMaterials; it++ ) {\r\n//\t\t\tif ( pMaterialList->m_pMaterialList[it].m_priority < pBest->m_priority ) pBest = &pMaterialList->m_pMaterialList[it];\r\n//\t\t}\r\n//\t\tpBest->m_priority |= 0x40000000;\t\t// Force this not to be used again.\r\n//\t\tpMaterialList->m_pSortedMaterialList[lp] = pBest;\r\n//\t}\r\n//\t// Restore priority.\r\n//\tfor ( lp = 0; lp < (int)m_numMaterials; lp++ ) {\r\n//\t\tpMaterialList->m_pMaterialList[lp].m_priority &= ~0x40000000;\r\n//\t}\r\n////\t// Set up the linked list.\r\n////\tpFirstMaterial = SortedMaterialList[0];\r\n////\tfor ( lp = 0; lp < ( numMaterials - 1 ); lp++ ) {\r\n////\t\tSortedMaterialList[lp]->pNextSorted = SortedMaterialList[lp+1];\r\n////\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n////\t\tSortedMaterialList[numMaterials-1]->pNextSorted = NULL;\r\n///*\r\n//\t// Set up the linked list.\r\n//\tpHead = &pMaterialList[0];\r\n//\tfor ( lp = 0; lp < ( numMaterials - 1 ); lp++ ) {\r\n//\t\tpMaterialList[lp].pNextSorted = &pMaterialList[lp+1];\r\n//\t}\r\n//\tpMaterialList[numMaterials-1].pNextSorted = NULL;\r\n//*/\r\n////\tOSFree ( SortedMaterialList );\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tdraw\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tpMaterialList\tThe list of materials this model uses.\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tDraws the specified model.\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void * NsModel::draw ( NsMaterialMan * pMaterialList, NsCollision * pCollision, int stripNormals, int addToHashTable )\r\n//{\r\n//    int\t\t\t\tit;   // index of triangle\r\n//\tNsTexture\t  * pTex;\r\n////\tunsigned int\tnumPoly;\r\n//\tunsigned int\tmaterial;\r\n//\tunsigned short\tc0;\t//, c1, c2;\r\n//\r\n//\tNsGeometry\t  * pGeom;\r\n//\tNsMaterialInfo* pMaterial;\r\n//\tfloat\t\t  * pVertex;\r\n//\tfloat\t\t  * pNormal;\r\n//\tunsigned int  * pColor;\r\n//\tunsigned int  * pPoly;\r\n//\tunsigned short* pConnect;\r\n//\tunsigned short* pFlags;\r\n//\tunsigned short* pFaceFlags;\r\n//\tunsigned short* pFaceMaterial;\r\n//\tfloat\t\t  * pUV;\r\n//\tint\t\t\t\tlp;\r\n//\tunsigned int\tlp2;\r\n//\tunsigned int\tgeomflags;\r\n//\tint\t\t\t\tmesh;\r\n//\r\n//\tint\t\t\t\tflags;\r\n//\tint\t\t\t\tnumMesh;\r\n//\tint\t\t\t\ttotalIdx;\r\n//\tint\t\t\t\tnumIdx;\r\n//\tint\t\t\t\tnumFlags;\r\n//\r\n//\tNsMaterial\t  * pMat;\r\n//\r\n//\tNsDL\t\t  * pDL = NULL;\t\t// To fix warning\r\n//\tNsDL\t\t  * pParentDL = NULL;\r\n//\tchar\t\t  * p8;\r\n//\tchar\t\t  * pPoolStart;\r\n//\tint\t\t\t\tstride;\r\n//\r\n//\tint\t\t\t\tpolybase;\r\n//\r\n//\t// pModel[0] = int numMat\r\n//\t// pModel[1] = int numWorld\r\n//\t// pModel[2] = float invOrigin.x\r\n//\t// pModel[3] = float invOrigin.y\r\n//\t// pModel[4] = float invOrigin.z\r\n//\r\n// \t// Point up stuff we're interested in.\t\r\n// \tpMaterial = (NsMaterialInfo *)&this[1];\r\n//\r\n//\t// Skip material data.\r\n//\tfor ( lp = 0; lp < (int)m_numMaterials; lp++ ) {\r\n//\t\tNsMaterialInfo* pLastMaterial = pMaterial;\r\n//\t\tpMaterial++;\r\n//\t\t// Deal with wibble data if we have it.\r\n//\t\tif ( pLastMaterial->uvwibble ) {\r\n//\t\t\tunsigned int * p32 = (unsigned int *)pMaterial;\r\n//\t\t\tp32 += 8;\r\n//\t\t\tpMaterial = (NsMaterialInfo *)p32;\r\n//\t\t}\r\n//\t\tif ( pLastMaterial->vcwibble ) {\r\n//\t\t\tunsigned int * p32 = (unsigned int *)pMaterial;\r\n//\t\t\tfor ( int kk = 0; kk < 8; kk++ ) {\r\n//\t\t\t\tunsigned int numWibbleKeys = *p32++;\r\n//\t\t\t\tp32 += numWibbleKeys * ( sizeof( NsWibbleKey ) / 4 );\r\n//\t\t\t}\r\n//\t\t\tpMaterial = (NsMaterialInfo *)p32;\r\n//\t\t}\r\n//\t}\r\n//\tpGeom = (NsGeometry *)pMaterial;\r\n//\r\n//\t//\tpTex = TexMan_Retrieve ( \"SUB_AS_satellite_01.png\" );\r\n//\tfor ( lp = 0; lp < (int)m_numGeom; lp++ ) {\r\n//\t\t// Point to various pools we need.\r\n//\t\tpVertex = (float *)&pGeom[1];\r\n//\t\tm_frameNumber = pGeom->frameNumber;\r\n//\t\t\t\t\t\t\t\t\t\t\r\n//\t\tgeomflags = pGeom->flags;\r\n//\r\n//\t\tswitch ( geomflags & ( rpWORLDPRELIT | rpWORLDTEXTURED | rpWORLDTEXTURED2 | rpWORLDNORMALS ) ) {\r\n//\t\t\tcase rpWORLDPRELIT:\r\n//\t\t\t\tpColor\t= (unsigned int *)&pVertex[pGeom->numVertices*3];\r\n//\t\t\t\tpUV\t\t= NULL;\r\n//\t\t\t\tpNormal\t= NULL;\r\n//\t\t\t\tpConnect= (unsigned short *)&pColor[pGeom->numVertices];\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase rpWORLDPRELIT |\t\t\t\t\t\trpWORLDNORMALS:\r\n//\t\t\t\tpColor\t= (unsigned int *)&pVertex[pGeom->numVertices*3];\r\n//\t\t\t\tpUV\t\t= NULL;\r\n//\t\t\t\tpNormal = (float *)&pColor[pGeom->numVertices];\r\n//\t\t\t\tpConnect= (unsigned short *)&pNormal[pGeom->numVertices*3];\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase rpWORLDPRELIT |\trpWORLDTEXTURED:\r\n//\t\t\tcase rpWORLDPRELIT |\trpWORLDTEXTURED2:\r\n//\t\t\t\tpColor\t= (unsigned int *)&pVertex[pGeom->numVertices*3];\r\n//\t\t\t\tpUV\t\t= (float *)&pColor[pGeom->numVertices];\r\n//\t\t\t\tpNormal\t= NULL;\r\n//\t\t\t\tpConnect= (unsigned short *)&pUV[pGeom->numVertices*2];\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase rpWORLDPRELIT |\trpWORLDTEXTURED |\trpWORLDNORMALS:\r\n//\t\t\tcase rpWORLDPRELIT |\trpWORLDTEXTURED2 |\trpWORLDNORMALS:\r\n//\t\t\t\tpColor\t= (unsigned int *)&pVertex[pGeom->numVertices*3];\r\n//\t\t\t\tpUV\t\t= (float *)&pColor[pGeom->numVertices];\r\n//\t\t\t\tpNormal\t= (float *)&pUV[pGeom->numVertices*2];\r\n//\t\t\t\tpConnect= (unsigned short *)&pNormal[pGeom->numVertices*3];\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase 0:\r\n//\t\t\t\tpColor\t= NULL;\r\n//\t\t\t\tpUV\t\t= NULL;\r\n//\t\t\t\tpNormal\t= NULL;\r\n//\t\t\t\tpConnect= (unsigned short *)&pVertex[pGeom->numVertices*3];\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase\t\t\t\t\t\t\t\t\t\trpWORLDNORMALS:\r\n//\t\t\t\tpColor\t= NULL;\r\n//\t\t\t\tpUV\t\t= NULL;\r\n//\t\t\t\tpNormal\t= (float *)&pVertex[pGeom->numVertices*3];\r\n//\t\t\t\tpConnect= (unsigned short *)&pNormal[pGeom->numVertices*3];\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase \t\t\t\t\trpWORLDTEXTURED:\r\n//\t\t\tcase \t\t\t\t\trpWORLDTEXTURED2:\r\n//\t\t\t\tpColor\t= NULL;\r\n//\t\t\t\tpUV\t\t= (float *)&pVertex[pGeom->numVertices*3];\r\n//\t\t\t\tpNormal\t= NULL;\r\n//\t\t\t\tpConnect= (unsigned short *)&pUV[pGeom->numVertices*2];\r\n//\t\t\t\tbreak;\r\n//\t\t\tcase \t\t\t\t\trpWORLDTEXTURED |\trpWORLDNORMALS:\r\n//\t\t\tcase \t\t\t\t\trpWORLDTEXTURED2 |\trpWORLDNORMALS:\r\n//\t\t\t\tpColor\t= NULL;\r\n//\t\t\t\tpUV\t\t= (float *)&pVertex[pGeom->numVertices*3];\r\n//\t\t\t\tpNormal\t= (float *)&pUV[pGeom->numVertices*2];\r\n//\t\t\t\tpConnect= (unsigned short *)&pNormal[pGeom->numVertices*3];\r\n//\t\t\t\tbreak;\r\n//\t\t\tdefault:\r\n//\t\t\t\tpColor\t= NULL;\r\n//\t\t\t\tpUV\t\t= NULL;\r\n//\t\t\t\tpNormal\t= NULL;\r\n//\t\t\t\tpConnect= (unsigned short *)&pVertex[pGeom->numVertices*3];\r\n//\t\t\t\tbreak;\r\n//\t\t}\r\n//\t\t// We always have these.\r\n//\t\tnumFlags = pGeom->numPolygons + ( pGeom->numPolygons & 1 );\r\n//\t\tpFlags  = (unsigned short *)&pConnect[pGeom->numPolygons*4];\r\n//\t\tpPoly\t= (unsigned int *)&pFlags[numFlags];\r\n//\r\n//\t\t// Strip normals if requested.\r\n//\t\tif ( stripNormals ) {\r\n//\t\t\tif ( geomflags & rpWORLDNORMALS ) {\r\n//\t\t\t\tgeomflags &= ~rpWORLDNORMALS;\r\n//\t\t\t\tpNormal\t= NULL;\r\n//\t\t\t}\r\n//\t\t}\r\n//\r\n//\t\t// Set stride.\r\n//\t\tif ( pNormal ) {\r\n//\t\t\t// We have vertices and normals, we have to adjust the stride.\r\n//\t\t\tstride = 6 * sizeof ( float );\r\n//\t\t} else {\r\n//\t\t\t// We only have vertices, set standard stride.\r\n//\t\t\tstride = 3 * sizeof ( float );\r\n//\t\t}\r\n//\r\n//\t\t// If the header says no polys, don't do anything.\r\n//\t\tif ( pGeom->numPolygons ) {\r\n//\r\n//\t\t\t// Re-calculate bounding box.\r\n//\t\t\tpGeom->infx = pVertex[0];\r\n//\t\t\tpGeom->infy = pVertex[1];\r\n//\t\t\tpGeom->infz = pVertex[2];\r\n//\t\t\tpGeom->supx = pVertex[0];\r\n//\t\t\tpGeom->supy = pVertex[1];\r\n//\t\t\tpGeom->supz = pVertex[2];\r\n//\t\t\tfor ( unsigned int i = 0; i < pGeom->numVertices; i++ )\r\n//\t\t\t{\r\n//\t\t\t\tif ( pVertex[(i*3)+0] < pGeom->infx ) pGeom->infx = pVertex[(i*3)+0];\r\n//\t\t\t\tif ( pVertex[(i*3)+1] < pGeom->infy ) pGeom->infy = pVertex[(i*3)+1];\r\n//\t\t\t\tif ( pVertex[(i*3)+2] < pGeom->infz ) pGeom->infz = pVertex[(i*3)+2];\r\n//\t\t\t\tif ( pVertex[(i*3)+0] > pGeom->supx ) pGeom->supx = pVertex[(i*3)+0];\r\n//\t\t\t\tif ( pVertex[(i*3)+1] > pGeom->supy ) pGeom->supy = pVertex[(i*3)+1];\r\n//\t\t\t\tif ( pVertex[(i*3)+2] > pGeom->supz ) pGeom->supz = pVertex[(i*3)+2];\r\n//\t\t\t}\r\n//\r\n//\t\t\t// Copy face flags.\r\n//\t\t\tpFaceFlags = new unsigned short[pGeom->numPolygons];\r\n//\t\t\tmemcpy( pFaceFlags, pFlags, pGeom->numPolygons * sizeof ( unsigned short ) );\r\n//\t\r\n//\t\t\tint size = 0;\r\n//\t\t\tif ( pVertex ) {\r\n//\t\t\t\tsize += ( pGeom->numVertices + 1 ) * sizeof ( float ) * 3;\r\n//\t\t\t}\r\n//\t\t\tif ( pNormal ) {\r\n//\t\t\t\tsize += ( pGeom->numVertices + 1 ) * sizeof ( float ) * 3;\r\n//\t\t\t}\r\n//\t\t\tif ( pColor ) {\r\n//\t\t\t\tsize += sizeof ( unsigned int ) * pGeom->numVertices;\r\n//\t\t\t}\r\n//\t\t\tif ( pUV ) {\r\n//\t\t\t\tsize += sizeof ( float ) * 2 * pGeom->numVertices;\r\n//\t\t\t}\t\t\r\n//\t\t\tsize += pGeom->numPolygons * sizeof ( unsigned short ) * 3;\r\n//\r\n//\t\t\tp8 = new char[size];\r\n//\t\t\tpPoolStart = p8;\r\n//\r\n//\t\t\t// Positions and normals should be doubled up (so that the\r\n//\t\t\t// animation system can directly set in this format).\r\n//\t\t\t// PJR - Note: +1 for blend error.\r\n//\t\t\tfor ( lp2 = 0; lp2 < pGeom->numVertices; lp2++ ) {\r\n//\t\t\t\tif ( pVertex ) {\r\n//\t\t\t\t\tmemcpy ( p8, &pVertex[lp2*3], sizeof ( float ) * 3 );\r\n//\t\t\t\t\tp8 += sizeof ( float ) * 3;\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tif ( pNormal ) {\r\n//\t\t\t\t\tmemcpy ( p8, &pNormal[lp2*3], sizeof ( float ) * 3 );\r\n//\t\t\t\t\tp8 += sizeof ( float ) * 3;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\r\n//\t\t\tif ( pVertex ) {\r\n//\t\t\t\tpVertex = (float *)pPoolStart;\r\n//\t\t\t\tp8 += sizeof ( float ) * 3;\r\n//\t\t\t}\r\n//\r\n//\t\t\tif ( pNormal ) {\r\n//\t\t\t\tpNormal = (float *)pPoolStart;\r\n//\t\t\t\tp8 += sizeof ( float ) * 3;\r\n//\t\t\t}\r\n//\r\n//\t\t\t// Copy the colors and UVs (not doubled up).\r\n//\t\t\tif ( pColor ) {\r\n//\t\t\t\tmemcpy ( p8, pColor, sizeof ( unsigned int ) * pGeom->numVertices );\r\n//\t\t\t\tpColor = (unsigned int *)p8;\r\n//\t\t\t\tp8 += sizeof ( unsigned int ) * pGeom->numVertices;\r\n//\t\t\t}\r\n//\r\n//\t\t\tif ( pUV ) {\r\n//\t\t\t\tmemcpy ( p8, pUV, sizeof ( float ) * 2 * pGeom->numVertices );\r\n//\t\t\t\tpUV = (float *)p8;\r\n//\t\t\t\tp8 += sizeof ( float ) * 2 * pGeom->numVertices;\r\n//\t\t\t}\r\n//\r\n//\t\t\t// Copy connect information.\r\n//\t\t\tfor ( lp2 = 0; lp2 < pGeom->numPolygons; lp2++ ) {\r\n//\t\t\t\tmemcpy ( p8, &pConnect[(lp2*4)+1], sizeof ( unsigned short ) * 3 );\r\n//\t\t\t\tp8 += sizeof ( unsigned short ) * 3;\r\n//\t\t\t}\r\n//\r\n//\t\t\tm_numVertex = pGeom->numVertices;\r\n//\t\t\tm_pVertexPool = (NsVector *)pVertex;\r\n//\t\t\tm_flags  = pVertex ? (1<<0) : 0;\r\n//\t\t\tm_flags |= pNormal ? (1<<1) : 0;\r\n//\t\t\tm_flags |= pColor  ? (1<<2) : 0;\r\n//\t\t\tm_flags |= pUV     ? (1<<3) : 0;\r\n//\r\n//\t\t\tflags = pPoly[0];\r\n//\t\t\tnumMesh = pPoly[1];\r\n//\t\t\ttotalIdx = pPoly[2];\r\n//\t\t\tpPoly += 3;\r\n//\t\t\tpolybase = 0;\r\n//\r\n//\t\t\t// Setup face material list.\r\n//\t\t\tpFaceMaterial = new unsigned short[pGeom->numPolygons];\r\n//\t\t    for ( it = 0 ; it < (int)pGeom->numPolygons; ++it ) {\r\n//\t\t\t\tpFaceMaterial[it] = pConnect[(it*4)+0];\r\n//\t\t\t}\r\n//\r\n//\t\t\t// Draw each chunk of polygons.\r\n//\t\t\tfor ( mesh = 0; mesh < numMesh; mesh++ ) {\r\n//\t\t\t\t// Get number of polys and advance to poly list.\r\n//\t/*\t\t\tnumPoly = pPoly[0];\r\n//\t\t\t\tmaterial = pPoly[1];\r\n//\t\t\t    pPoly += 2;*/\r\n//\r\n//\t\t\t\tnumIdx = pPoly[0];\r\n//\t\t\t\tmaterial = pPoly[1];\r\n//\t\t\t\tpPoly += 2;\r\n//\r\n//\t\t\t\tpMat = pMaterialList->retrieve ( material );\r\n//\t\t\t\tassertf ( material < m_numMaterials, ( \"Material too high: %d - max: %d\\n\", material, m_numMaterials ) );\r\n//\r\n//\t\t\t\t// Clear the decal flag if not static environment.\r\n//\t\t\t\tif( !addToHashTable )\r\n//\t\t\t\t{\r\n//\t\t\t\t\tpMat->setFlags( pMat->getFlags() & ~mDECAL );\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t    // Only attempt to upload/draw if we have polygons.\r\n//\t//\t\t\tif ( numPoly ) {\r\n//\t\t\t\tif ( numIdx ) {\r\n//\t\t\t\r\n//\t\t\t\t\t// Setup display list header & open display list context.\r\n//\t\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n//\t\t\t\t\tpDL = (NsDL *)new char[DL_BUILD_SIZE];\r\n//\t\t\t\t\tDCFlushRange ( &pDL[1], DL_BUILD_SIZE );\r\n//\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n//\t\r\n//\t\t\t\t\tGXBeginDisplayList ( &pDL[1], DL_BUILD_SIZE );\r\n//\t\t\t\t\tGXResetWriteGatherPipe();\r\n//\r\n//\t\t\t\t\t// Set cull item.\r\n//\t\t\t\t\tpDL->m_cull.box.m_min.x = pGeom->infx;\r\n//\t\t\t\t\tpDL->m_cull.box.m_min.y = pGeom->infy;\r\n//\t\t\t\t\tpDL->m_cull.box.m_min.z = pGeom->infz;\r\n//\t\t\t\t\tpDL->m_cull.box.m_max.x = pGeom->supx;\r\n//\t\t\t\t\tpDL->m_cull.box.m_max.y = pGeom->supy;\r\n//\t\t\t\t\tpDL->m_cull.box.m_max.z = pGeom->supz;\r\n//\t\t\t\t\tpDL->m_cull.visible = 1;\r\n//\r\n//\t\t\t\t\tpDL->m_id = pGeom->checksum;\t\t// Checksum.\r\n////\t\t\t\t\tpDL->version = 0;\r\n////\t\t\t\t\tpDL->cullIdx = lp;\r\n//\t\t\t\t\tpDL->m_flags = geomflags;\r\n//\t\t\t\t\tpDL->m_rwflags = pGeom->rflags;\r\n//\t\t\t\t\tpDL->m_numIdx = numIdx;\r\n//\t\t\t\t\tpDL->m_polyBase = polybase;\r\n//\t\t\t\t\tpDL->m_pVertexPool = (NsVector *)pVertex;\r\n//\t\t\t\t\tpDL->m_numVertex = pGeom->numVertices;\r\n//\t\t\t\t\tpDL->m_numPoly = pGeom->numPolygons;\r\n//\t\t\t\t\tpDL->m_vpoolFlags = m_flags;\r\n//\t\t\t\t\tpDL->m_operationID = 0;\r\n//\r\n//\t\t\t\t    // Set format of position, color and tex coordinates.\r\n//\t\t\t\t    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);\r\n//\t\t\t\t    if ( geomflags & rpWORLDPRELIT ) GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);\r\n//\t\t\t\t\tif ( geomflags & rpWORLDUVS ) GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);\r\n//\t\t\t\t\tif ( geomflags & rpWORLDNORMALS ) GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);\r\n//\r\n//\t\t\t\t\t// Set collision.\r\n////\t\t\t\t\tif ( m_numGeom > 1 ) {\r\n////\t\t\t\t\t\tpDL->m_pCollision = new NsCollision( pGeom->numPolygons );\r\n////\t\t\t\t\t    for ( it = 0 ; it < (int)pGeom->numPolygons; ++it ) {\r\n////\t\t\t\t\t\t\tc0 = pConnect[(it*4)+1]*(stride/4);\r\n////\t\t\t\t\t\t\tc1 = pConnect[(it*4)+2]*(stride/4);\r\n////\t\t\t\t\t\t\tc2 = pConnect[(it*4)+3]*(stride/4);\r\n////\t\t\t\t\t\t\tpDL->m_pCollision->addTriangle(\r\n////\t\t\t\t\t\t\t\tpVertex[c0+0], pVertex[c0+1], pVertex[c0+2],\r\n////\t\t\t\t\t\t\t\tpVertex[c1+0], pVertex[c1+1], pVertex[c1+2],\r\n////\t\t\t\t\t\t\t\tpVertex[c2+0], pVertex[c2+1], pVertex[c2+2] );\r\n////\t\t\t\t\t\t}\r\n////\t\t\t\t\t}\r\n//\t\t\t\t\t// Face flags.\r\n//\t\t\t\t\tpDL->m_pFaceFlags = pFaceFlags;\r\n//\r\n//\t\t\t\t\t// Material Indices.\r\n//\t\t\t\t\tpDL->m_pFaceMaterial = pFaceMaterial;\r\n//\r\n//\t\t\t\t    // Sets up vertex descriptors\r\n//\t\t\t\t    GXClearVtxDesc();\r\n//\t\t\t\t    GXSetVtxDesc(GX_VA_POS, GX_INDEX16);\r\n//\t\t\t\t\tif ( geomflags & rpWORLDPRELIT ) GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16);\r\n//\t\t\t\t\tif ( geomflags & rpWORLDNORMALS ) GXSetVtxDesc(GX_VA_NRM, GX_INDEX16);\r\n//\t\t\t\t\tif ( geomflags & rpWORLDUVS ) GXSetVtxDesc(GX_VA_TEX0, GX_INDEX16);\r\n//\t\t\t\t\t//GXSetVtxDesc(GX_VA_NRM, GX_INDEX8);\r\n//\r\n//\t\t\t\t\t// Point the hardware at these pools.\r\n//\t\t\t\t\tif ( m_numGeom > 1 ) {\r\n//\t\t\t\t\t    GXSetArray(GX_VA_POS, pVertex, stride);\r\n//\t\t\t\t\t    if ( geomflags & rpWORLDNORMALS ) GXSetArray(GX_VA_NRM, pNormal, stride);\r\n//\t\t\t\t\t}\r\n//\t\t\t\t    if ( geomflags & rpWORLDPRELIT ) GXSetArray(GX_VA_CLR0, pColor, 4*sizeof(u8));\r\n//\t\t\t\t\t\r\n//\t\t\t\t\t// If this texture exists, and it isn't already uploaded, upload it.\r\n//\t\t\t\t\tpTex = pMat->m_pTexture;\r\n////\t\t\t\t\tpTex = TexMan_Retrieve ( (char *)&pMaterial[material*64] );\r\n//\t\t\t\t\t//if ( !pTex ) pTex = TexMan_Retrieve ( \"\" );\r\n//\r\n//\t\t\t\t\tif ( geomflags & rpWORLDUVS ) GXSetArray(GX_VA_TEX0, pUV, 8);\r\n//\r\n//\t\t\t\t\tswitch ( flags ) {\r\n//\t\t\t\t\t\tcase 1:\t\t// Tri-strip\r\n//\t\t\t\t\t\t\t// Open drawing context.\r\n//\t\t\t\t\t\t\t//GXSetCullMode ( GX_CULL_NONE );\r\n//\t\t\t\t\t\t    GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, (unsigned short)numIdx );\r\n//\t\t\t\t\t\t\tpDL->m_vpoolFlags |= (1<<5);\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t\tdefault:\r\n//\t\t\t\t\t\tcase 0:\t\t// Regular\r\n//\t\t\t\t\t\t\t// Open drawing context.\r\n//\t\t\t\t\t\t\t//GXSetCullMode ( GX_CULL_BACK );\r\n//\t\t\t\t\t\t    GXBegin(GX_TRIANGLES, GX_VTXFMT0, (unsigned short)numIdx );\r\n//\t\t\t\t\t\t\tpolybase += numIdx / 3;\t\t// Note: can only calculate this for trilists. Will be 0 for tristrips.\r\n//\t\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\t}\r\n//\r\n//\t\t\t\t\tunsigned short vertMin\t= 0xFFFFU;\r\n//\t\t\t\t\tunsigned short vertMax\t= 0x0000U;\r\n//\t\t\t\t    for ( it = 0 ; it < numIdx; ++it ) {\r\n//\t\t\t\t\t\tc0 = (unsigned short )*pPoly;\r\n//\t\t\t\t    \tGXPosition1x16(c0);\r\n//\t\t\t\t\t\tif ( geomflags & rpWORLDNORMALS ) GXNormal1x16(c0);\r\n//\t\t\t\t\t    if ( geomflags & rpWORLDPRELIT ) GXColor1x16(c0);\r\n//\t\t\t\t\t\tif ( geomflags & rpWORLDUVS ) GXTexCoord1x16(c0);\r\n//\t\t\t\t\t\tif ( c0 < vertMin ) {\r\n//\t\t\t\t\t\t\tvertMin = c0;\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t\tif ( c0 > vertMax ) {\r\n//\t\t\t\t\t\t\tvertMax = c0;\r\n//\t\t\t\t\t\t}\r\n//\t\t\t\t\t\tpPoly++;\r\n//\t\t\t\t\t}\r\n//\r\n//\t\t\t\t    // Close drawing context.\r\n//\t\t\t\t    GXEnd();\r\n//\r\n//\t\t\t\t\t// Set vertex ranges.\r\n//\t\t\t\t\tpDL->m_vertBase\t\t= vertMin;\r\n//\t\t\t\t\tpDL->m_vertRange\t= ( vertMax - vertMin ) + 1;\r\n//\r\n//\t\t\t\t\t// Close display list context, assign it to the correct material & advance to next one.\r\n//\t\t\t\t\tpDL->m_size = GXEndDisplayList();\r\n//\t\t\t\t\tassert( pDL->m_size );\r\n//\r\n//\t\t\t\t\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());\r\n////\t\t\t\t\tpDL = (NsDL *)Mem::Realloc( pDL, pDL->m_size + sizeof( NsDL ) );\r\n//\t\t\t\t\tNsDL * pOldDL = pDL;\r\n//\t\t\t\t\tpDL = (NsDL *)new char[pOldDL->m_size + sizeof( NsDL )];\r\n//\t\t\t\t\tmemcpy ( pDL, pOldDL, pOldDL->m_size + sizeof( NsDL ) );\r\n//\t\t\t\t\tdelete pOldDL;\r\n//\t\t\t\t\tMem::Manager::sHandle().PopContext();\r\n//\t\t\t\t\tDCFlushRange ( &pDL[1], pDL->m_size );\r\n//\r\n//\t\t\t\t\tpMat->addDL ( pDL );\r\n//\t\t\t\t\t// If this is the first mesh in this sector, add it to the\r\n//\t\t\t\t\t// hash table. If not, link it to the head DL.\r\n//\t\t\t\t\tif ( mesh == 0 ) {\r\n//\t\t\t\t\t\t// Hook into skate3...\r\n//\t\t\t\t\t\t//if ( addToHashTable ) Bsp::AddToHashTable( pDL, NULL );\r\n//\t\t\t\t\t\tpDL->m_pParent = pDL;\r\n////\t\t\t\t\t\tpDL->m_pChild = NULL;\r\n//\t\t\t\t\t\tpParentDL = pDL;\r\n//\t\t\t\t\t} else {\r\n//\t\t\t\t\t\t// Hook this to the parent DL.\r\n//\t\t\t\t\t\tpDL->m_pParent = pParentDL;\r\n//\t\t\t\t\t\t// Set this DL's child to be the parent's child.\r\n////\t\t\t\t\t\tpDL->m_pChild = pParentDL->m_pChild;\r\n//\t\t\t\t\t\t// Set the parent's child to be this dl.\r\n////\t\t\t\t\t\tpParentDL->m_pChild = pDL;\r\n//\t\t\t\t\t}\r\n//\t\t\t\t\t// Point up the material manager.\r\n//\t\t\t\t\tpDL->m_pMaterialMan = pMaterialList;\r\n//\t\t\t    } else {\r\n//\t\t\t\t\t// Skip.\r\n//\t\t\t\t\tpPoly += numIdx;\r\n//\t\t\t\t}\r\n//\t\t    }\r\n//\t\t}\r\n//\r\n//\t\t// Pull skin plugin data out.\r\n//\t\tNsBBox\t\t\t  * pSkinBox;\r\n//\t\tunsigned short\t  * pCAS16;\r\n//\t\tunsigned int\t  * pFlipPairs;\r\n//\t\tunsigned int\t  * pCAS32;\r\n//\t\tunsigned int\t  * pPartChecksums;\r\n//\r\n//\t\tm_pSkinData = (NsSkinData *)pPoly;\r\n//\t\tpSkinBox = (NsBBox *)&m_pSkinData[1];\r\n//\t\tpCAS16 = (unsigned short *)&pSkinBox[m_pSkinData->numSkinBoxes];\r\n//\t\tpFlipPairs = (unsigned int *)&pCAS16[m_pSkinData->numCAS16+(m_pSkinData->numCAS16&1)];\r\n//\t\tpCAS32 = (unsigned int *)&pFlipPairs[m_pSkinData->numFlipPairs * 2];\r\n//\t\tpPartChecksums = (unsigned int *)&pCAS32[m_pSkinData->numCAS32];\r\n//\r\n//\t\t// Copy wibble data.\r\n//\t\tunsigned char * pWibble = (unsigned char *)&pPartChecksums[m_pSkinData->numPartChecksums];\r\n//\t\tpParentDL->m_pWibbleData = NULL;\r\n//\t\tif ( pGeom->wibbleDataFollows ) {\r\n//\t\t\tpParentDL->m_pWibbleData = new unsigned char[pParentDL->m_numVertex * 6];\r\n//\t\t\tmemcpy( pParentDL->m_pWibbleData, pParentDL->getColorPool(), pParentDL->m_numVertex * 4 );\r\n//\t\t\tmemcpy( &pParentDL->m_pWibbleData[pParentDL->m_numVertex * 4], pWibble, pParentDL->m_numVertex * 2 );\r\n//\t\t\tpWibble += ( pParentDL->m_numVertex * 2 ) + ( ( pParentDL->m_numVertex & 1 ) * 2 );\r\n//\t\t}\r\n//\t\t\r\n//\t\t// Skip bsp tree data.\r\n//\t\tNsBranch\t  * pBranches;\r\n//\t\tNsLeaf\t\t  * pLeaves;\r\n//\t\tunsigned int  * pTriangles;\r\n//\r\n//\t\tpBranches = (NsBranch *)pWibble;\r\n//\t\tpLeaves = (NsLeaf *)&pBranches[m_pSkinData->numLeaf ? m_pSkinData->numLeaf-1 : 0];\r\n//\t\tpTriangles = (unsigned int *)&pLeaves[m_pSkinData->numLeaf];\r\n//\r\n//\t    // Onto next geometry chunk.\r\n//\t\tpGeom = (NsGeometry *)&pTriangles[m_pSkinData->numTri];\r\n////\t\tpGeom = (NsGeometry *)pPoly;\r\n//\r\n//\t\t// Add BSP tree.\r\n//\t\tif ( pCollision && ( m_pSkinData->numLeaf > 0 ) && ( m_pSkinData->numTri > 0 ) ) {\r\n//\t\t\tpCollision->addTree( pBranches, m_pSkinData->numLeaf, m_pSkinData->numTri, pParentDL );\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t// Set extra data pointer up.\r\n//\tm_pExtraData = (unsigned int *)pGeom;\r\n//\r\n//\treturn m_pExtraData;\r\n//}\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_model.h",
    "content": "//#ifndef _MODEL_H_\r\n//#define _MODEL_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_matman.h\"\r\n//#include \"p_dlman.h\"\r\n//#include \"p_texman.h\"\r\n//#include \"p_camera.h\"\r\n//#include \"p_frame.h\"\r\n//#include \"p_anim.h\"\r\n//#include \"p_collision.h\"\r\n//\r\n////typedef enum\r\n////{\r\n////    rpWORLDTRISTRIP = 0x01,     /**<This world's meshes can be rendered\r\n////                                   as tri strips */\r\n////    rpWORLDTEXTURED = 0x04,     /**<This world has one set of texture coordinates */\r\n////    rpWORLDPRELIT = 0x08,       /**<This world has luminance values */\r\n////    rpWORLDNORMALS = 0x10,      /**<This world has normals */\r\n////    rpWORLDLIGHT = 0x20,        /**<This world will be lit */\r\n////    rpWORLDMODULATEMATERIALCOLOR = 0x40, /**<Modulate material color with\r\n////                                            vertex colors (pre-lit + lit) */\r\n////    rpWORLDTEXTURED2 = 0x80, /**<This world has 2 set of texture coordinates */\r\n////\r\n////    rpWORLDUVS = ( rpWORLDTEXTURED2 | rpWORLDTEXTURED ),\r\n////    /*\r\n////     * These flags are stored in the flags field in an RwObject, the flag field is 8bit.\r\n////     */\r\n////\r\n////    rpWORLDSECTORSOVERLAP = 0x40000000,\r\n////    //rpWORLDFLAGFORCEENUMSIZEINT = RWFORCEENUMSIZEINT\r\n////} RWFlags;\r\n//\r\n//typedef struct {\r\n//\tunsigned int\tid;\r\n//\tunsigned short\tnumSkinBoxes;\r\n//\tunsigned short\tnumCAS16;\r\n//\tunsigned short\tnumFlipPairs;\r\n//\tunsigned short\tnumCAS32;\r\n//\tunsigned int\tnumPartChecksums;\r\n//\tunsigned int\tremoveCAS32;\r\n//\tunsigned short\tremoveCAS16;\r\n//\tunsigned short\tpad;\r\n//\tunsigned int\tnumLeaf;\r\n//\tunsigned int\tnumTri;\r\n//} NsSkinData;\r\n//\r\n//class NsModel\r\n//{\r\n//\ttypedef struct {\r\n//\t\tunsigned int\tnumPolygons;\r\n//\t\tunsigned int\tnumVertices;\r\n//\t\tunsigned int\tnumMorphTargets;\r\n//\t\tunsigned int\tflags;\r\n//\t\tfloat\t\t\tinfx;\r\n//\t\tfloat\t\t\tinfy;\r\n//\t\tfloat\t\t\tinfz;\r\n//\t\tfloat\t\t\tsupx;\r\n//\t\tfloat\t\t\tsupy;\r\n//\t\tfloat\t\t\tsupz;\r\n//\t\tunsigned int\tpad0;\r\n//\t\tunsigned int\tpad1;\r\n//\t\tunsigned int\tpad2;\r\n//\t\tunsigned int\twibbleDataFollows;\r\n//\t\tunsigned int\tchecksum;\r\n//\t \tunsigned short\trflags;\r\n//\t\tunsigned short\tframeNumber;\r\n//\t} NsGeometry;\r\n//\ttypedef struct {\r\n//\t\tchar\t\t\tname[52];\r\n//\t\tunsigned char\tuvwibble;\r\n//\t\tunsigned char\tvcwibble;\r\n//\t\tunsigned short\tpriority;\r\n//\t\tunsigned char\ttype;\r\n//\t\tunsigned char\tflags;\r\n//\t\tunsigned char\talpha;\r\n//\t\tunsigned char\tblendmode;\r\n//\t\tGXColor\t\t\tcolor;\r\n//\t} NsMaterialInfo;\r\n//\r\n//\r\n//public:\r\n//\tunsigned int\tm_numMaterials;\r\n//\tunsigned int\tm_numGeom;\r\n//\tunsigned int\tm_numVertex;\r\n//\tNsVector\t  * m_pVertexPool;\t\t// Could be interleaved with normals (use getStride to step).\r\n//\tunsigned short\tm_flags;\r\n//\tunsigned short\tm_frameNumber;\r\n//\tunsigned int\tm_checksum;\r\n//\tNsSkinData\t  * m_pSkinData;\r\n//\tunsigned int  * m_pExtraData;\r\n//\r\n//\tvoid\t\t  * draw\t\t\t( NsMaterialMan * pMaterialList, NsCollision * pCollision, int stripNormals, int addToHashTable );\r\n//\tvoid\t\t\tbuildMaterials\t( NsMaterialMan * pMaterialList, NsTextureMan * pTexMan );\r\n//\r\n//\tNsVector\t  * getVertexPool\t( void ) { return m_pVertexPool; }\r\n//\tNsVector\t  * getNormalPool\t( void ) { return m_flags & (1<<1) ? &m_pVertexPool[1] : NULL; }\r\n//\tunsigned int  * getColorPool\t( void ) { return m_flags & (1<<2) ? (unsigned int *)&m_pVertexPool[getStride() * m_numVertex + 1] : NULL; }\r\n//\tfloat\t\t  * getUVPool\t\t( void ) { return m_flags & (1<<3) ? getColorPool() ? (float *)&getColorPool()[m_numVertex] : (float *)&m_pVertexPool[getStride() * m_numVertex + 1] : NULL; }\r\n//\tunsigned short* getConnectList\t( void ) { return m_flags & (1<<3) ? getUVPool() ? (unsigned short *)&getUVPool()[m_numVertex * 2] : getColorPool() ? (unsigned short *)&getColorPool()[m_numVertex] : (unsigned short *)&m_pVertexPool[getStride() * m_numVertex + 1] : NULL; }\r\n//\tint\t\t\t\tgetStride\t\t( void ) { return ( m_flags & (1<<1) ? 2 : 1 ); }\r\n//};\r\n//\r\n//#endif\t\t// _MODEL_H_\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_particle.cpp",
    "content": "///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n//**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//******************************************************************************\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tProject:\t\tSkate3         \t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tModule:\t\t\tGFX            \t \t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tFile name:\t\tp_particle.cpp \t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tCreated:\t\t08/16/2001\tdc     \t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tDescription:\tNGC particle system interface\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n// \r\n//#include <sys/ngc/p_vector.h>\r\n//#include \"p_particle.h\"\r\n//#include \"p_prim.h\"\r\n//\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//namespace Particle\r\n//{\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//#define fmin2f( a, b )\t((( a ) < ( b )) ? ( a ) : ( b ))\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//static NsVector\t\tscreen_right;\r\n//static NsVector\t\tscreen_up;\r\n//static NsCamera*\tp_current_cam\t= NULL;\r\n//\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void NsParticleAtomic::seedParticle( int p, float t_max )\r\n//{\r\n//\tDbg_Assert(( t_max >= 0.0f ) && ( t_max <= 1.0f ));\r\n//\r\n//\tparametric_particle* p_part = mp_particles + p;\r\n//\r\n//\t// Figure current parametric parameter.\r\n//\tp_part->t = t_max;\r\n//\r\n//\t// Figure intial velocity.\r\n//\tfloat angle_range_x\t= (((float)rand() / RAND_MAX ) * 2.0f ) - 1.0f;\r\n//\tfloat angle_range_y\t= (((float)rand() / RAND_MAX ) * 2.0f ) - 1.0f;\r\n//\r\n//\tNsVector vel;\r\n//\tvel.x\t\t\t\t= m_emitter_angle * angle_range_x;\r\n//\tvel.y\t\t\t\t= m_emitter_angle * angle_range_y;\r\n//\tvel.z\t\t\t\t= 1.0f - (( vel.x * vel.x ) + ( vel.y * vel.y ));\r\n//\r\n//\tfloat speed\t\t\t= m_min_speed - ( m_variation_speed * 0.5f ) + ( m_variation_speed * ((float)rand() / RAND_MAX ));\r\n//\tspeed\t\t\t   *= 1.0f - fmin2f(( angle_range_x * angle_range_x ) + ( angle_range_y * angle_range_y ), -1.0f * m_damping );\r\n//\tp_part->initial_velocity.scale( vel, speed );\r\n//\r\n//\t// Figure initial position.\r\n//\tp_part->start_pos.x\t\t\t= -m_emitter_width + ( 2.0f * m_emitter_width * ((float)rand() / RAND_MAX ));\r\n//\tp_part->start_pos.y\t\t\t= -m_emitter_height + ( 2.0f * m_emitter_height * ((float)rand() / RAND_MAX ));\r\n//\tp_part->start_pos.z\t\t\t= 0.0f;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//bool NsParticleAtomic::cull( void )\r\n//{\r\n//\tint\t\t\t\tlp;\r\n//\tunsigned int\tcode;\r\n//\tunsigned int\tcodeAND;\r\n//\tf32\t\t\t\trx[8], ry[8], rz[8];\r\n//\tf32\t\t\t\tp[GX_PROJECTION_SZ];\r\n//\tf32\t\t\t\tvp[GX_VIEWPORT_SZ];\r\n//\tu32\t\t\t\tclip_x;\r\n//\tu32\t\t\t\tclip_y;\r\n//\tu32\t\t\t\tclip_w;\r\n//\tu32\t\t\t\tclip_h;\r\n//\tfloat\t\t\tclip_l;\r\n//\tfloat\t\t\tclip_t;\r\n//\tfloat\t\t\tclip_r;\r\n//\tfloat\t\t\tclip_b;\r\n//\tMtxPtr\t\t\tview;\r\n//\tfloat\t\t\tminx, miny, minz;\r\n//\tfloat\t\t\tmaxx, maxy, maxz;\r\n//\r\n//\tGXGetProjectionv( p );\r\n//\tGXGetViewportv( vp );\r\n//\tGXGetScissor( &clip_x, &clip_y, &clip_w, &clip_h );\r\n//\tclip_l = (float)clip_x;\r\n//\tclip_t = (float)clip_y;\r\n//\tclip_r = (float)( clip_x + clip_w );\r\n//\tclip_b = (float)( clip_y + clip_h );\r\n//\r\n//\tview = (MtxPtr)( p_current_cam->getCurrent()->getRight());\r\n//\r\n//\tNsMatrix* p_matrix = m_frame.getModelMatrix();\r\n//\r\n//\tminx = m_bbox.m_min.x + p_matrix->getPosX();\r\n//\tminy = m_bbox.m_min.y + p_matrix->getPosY();\r\n//\tminz = m_bbox.m_min.z + p_matrix->getPosZ();\r\n//\tmaxx = m_bbox.m_max.x + p_matrix->getPosX();\r\n//\tmaxy = m_bbox.m_max.y + p_matrix->getPosY();\r\n//\tmaxz = m_bbox.m_max.z + p_matrix->getPosZ();\r\n//\r\n//\tGXProject ( minx, miny, minz, view, p, vp, &rx[0], &ry[0], &rz[0] );\r\n//\tGXProject ( minx, maxy, minz, view, p, vp, &rx[1], &ry[1], &rz[1] );\r\n//\tGXProject ( maxx, miny, minz, view, p, vp, &rx[2], &ry[2], &rz[2] );\r\n//\tGXProject ( maxx, maxy, minz, view, p, vp, &rx[3], &ry[3], &rz[3] );\r\n//\tGXProject ( minx, miny, maxz, view, p, vp, &rx[4], &ry[4], &rz[4] );\r\n//\tGXProject ( minx, maxy, maxz, view, p, vp, &rx[5], &ry[5], &rz[5] );\r\n//\tGXProject ( maxx, miny, maxz, view, p, vp, &rx[6], &ry[6], &rz[6] );\r\n//\tGXProject ( maxx, maxy, maxz, view, p, vp, &rx[7], &ry[7], &rz[7] );\r\n//\tbool visible = true;\r\n//\r\n//\t// Generate clip code. {page 178, Procedural Elements for Computer Graphics}\r\n//\t// 1001|1000|1010\r\n//\t//     |    |\r\n//\t// ----+----+----\r\n//\t// 0001|0000|0010\r\n//\t//     |    |\r\n//\t// ----+----+----\r\n//\t// 0101|0100|0110\r\n//\t//     |    |\r\n//\t//\r\n//\t// Addition: Bit 4 is used for z behind.\r\n//\r\n//\tcodeAND\t= 0x001f;\r\n//\r\n//\tfor ( lp = 0; lp < 8; lp++ ) {\r\n//\t\t// Only check x/y if z is valid (if z is invalid, the x/y values will be garbage).\r\n//\t\tif ( rz[lp] > 1.0f   ) {\r\n//\t\t\tcode = (1<<4);\r\n//\t\t} else {\r\n//\t\t\tcode = 0;\r\n//\t\t\tif ( rx[lp] < clip_l ) code |= (1<<0);\r\n//\t\t\tif ( rx[lp] > clip_r ) code |= (1<<1);\r\n//\t\t\tif ( ry[lp] > clip_b ) code |= (1<<2);\r\n//\t\t\tif ( ry[lp] < clip_t ) code |= (1<<3);\r\n//\t\t}\r\n//\t\tcodeAND\t&= code;\r\n//\t}\r\n//\r\n//\t// If any bits are set in the AND code, the object is invisible.\r\n//\tif ( codeAND ) {\r\n//\t\tvisible = false;\r\n//\t}\r\n//\t\r\n//\treturn !visible;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void NsParticleAtomic::figureBoundingBox( void )\r\n//{\r\n//\t// Cheesy, but it works reasonably well. Pass 1 particle through the system n times, sampling it's\r\n//\t// position at various intervals.\r\n//\tNsMatrix*\t\t\t\t\tp_matrix\t= m_frame.getModelMatrix();\r\n//\tstruct parametric_particle*\tp_part\t\t= mp_particles;\r\n//\r\n//\tm_bbox.m_min.x = m_bbox.m_max.x = 0.0f;\r\n//\tm_bbox.m_min.y = m_bbox.m_max.y = 0.0f;\r\n//\tm_bbox.m_min.z = m_bbox.m_max.z = 0.0f;\r\n//\r\n//\tfor( int pass = 0; pass < 16; ++pass )\r\n//\t{\r\n//\t\tfor( ;; )\r\n//\t\t{\r\n//\t\t\tp_part->t += 0.11945f;\r\n//\r\n//\t\t\t// First deal with reseeding any particles that have exceeded their lifetime.\r\n//\t\t\tif( p_part->t > 1.0f )\r\n//\t\t\t{\r\n//\t\t\t\tseedParticle( 0, p_part->t - 1.0f );\r\n//\t\t\t\tbreak;\r\n//\t\t\t}\r\n//\r\n//\t\t\t// Now figure current position.\r\n//\t\t\tfloat time\t\t\t\t= p_part->t * m_flight_time;\r\n//\r\n//\t\t\t// The 0.5 multiply is already done when the force is set.\r\n//\t\t\tfloat half_time_squared\t= time * time;\r\n//\t\t\tNsVector\tpos, ut, at, temp;\r\n//\r\n//\t\t\tut.scale( *p_matrix->getRight(), p_part->initial_velocity.x * time );\r\n//\t\t\ttemp.scale( *p_matrix->getUp(), p_part->initial_velocity.y * time );\r\n//\t\t\tut.add( temp );\r\n//\t\t\ttemp.scale( *p_matrix->getAt(), p_part->initial_velocity.z * time );\r\n//\t\t\tut.add( temp );\r\n//\r\n//\t\t\tat.scale( *p_matrix->getRight(), m_force.x * half_time_squared );\r\n//\t\t\ttemp.scale( *p_matrix->getUp(), m_force.y * half_time_squared );\r\n//\t\t\tat.add( temp );\r\n//\t\t\ttemp.scale( *p_matrix->getAt(), m_force.z * half_time_squared );\r\n//\t\t\tat.add( temp );\r\n//\r\n//\t\t\tpos.set( ut.x + at.x, ut.y + at.y, ut.z + at.z );\r\n//\r\n//\t\t\tif( pos.x < m_bbox.m_min.x )\r\n//\t\t\t\tm_bbox.m_min.x\t= pos.x;\r\n//\t\t\telse if( pos.x > m_bbox.m_max.x )\r\n//\t\t\t\tm_bbox.m_max.x\t= pos.x;\r\n//\r\n//\t\t\tif( pos.y < m_bbox.m_min.y )\r\n//\t\t\t\tm_bbox.m_min.y\t= pos.y;\r\n//\t\t\telse if( pos.y > m_bbox.m_max.y )\r\n//\t\t\t\tm_bbox.m_max.y\t= pos.y;\r\n//\r\n//\t\t\tif( pos.z < m_bbox.m_min.z )\r\n//\t\t\t\tm_bbox.m_min.z\t= pos.z;\r\n//\t\t\telse if( pos.z > m_bbox.m_max.z )\r\n//\t\t\t\tm_bbox.m_max.z\t= pos.z;\r\n//\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tm_flags &= ~PARTICLE_FLAG_BBOX_DIRTY;\r\n//}\r\n//\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void SetParticleAtomicCamera( NsCamera* p_cam )\r\n//{\r\n//\t// Used to figure the right and up vectors for creating screen-aligned particle quads.\r\n//\tNsFrame*\tp_frame\t\t= p_cam->getFrame();\r\n//\tNsMatrix*\tp_matrix\t= p_frame->getModelMatrix();\r\n//\r\n//\tNsVector\tup( 0.0f, 1.0f, 0.0f );\r\n//\r\n//\t// Get the 'right' vector as the cross product of camera 'at and world 'up'.\r\n//\tscreen_right.cross( *p_matrix->getAt(), up );\r\n//\tscreen_up.cross( screen_right, *p_matrix->getAt());\r\n//\r\n//\tscreen_right.normalize();\r\n//\tscreen_up.normalize();\r\n//\r\n//\tp_current_cam\t= p_cam;\r\n//}\r\n//\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//NsParticleAtomic::NsParticleAtomic( int num_particles, NsMaterial* p_material )\r\n//{\r\n//\tm_visible\t\t\t\t= true;\r\n//\tm_num_particles\t\t\t= num_particles;\r\n//\tm_initial_num_particles\t= num_particles;\r\n//\r\n//\tmp_particles = new struct parametric_particle[num_particles];\r\n//\r\n//\tfor( int i = 0; i < num_particles; ++i )\r\n//\t{\r\n//\t\tseedParticle( i, (float)rand() / (float)RAND_MAX );\r\n//\t}\r\n//\r\n//\t// Flag to indicate the bounding box needs calculating.\r\n//\tm_flags |= PARTICLE_FLAG_BBOX_DIRTY;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//NsParticleAtomic::~NsParticleAtomic()\r\n//{\r\n//\tif( mp_material )\r\n//\t{\r\n//\t\tdelete mp_material;\r\n//\t}\r\n//\r\n//\tdelete [] mp_particles;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void NsParticleAtomic::SetNumParticles( int num )\r\n//{\r\n//\tDbg_Assert( num <= m_initial_num_particles );\r\n//\r\n//\t// This value can only be set to less than it was initially.\r\n//\tif( num <= m_initial_num_particles )\r\n//\t{\r\n//\t\tm_num_particles = num;\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void NsParticleAtomic::update( float delta_t )\r\n//{\r\n//\t// If time since last draw is increasing, probably not being drawn currently, so\r\n//\t// pointless letting it get beyond 1.0f.\r\n//\tm_time_since_last_draw += delta_t;\r\n//\r\n//\tif( m_time_since_last_draw > m_flight_time )\r\n//\t{\r\n//\t\tm_time_since_last_draw -= m_flight_time;\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void NsParticleAtomic::draw( void )\r\n//{\r\n//\tif( m_visible )\r\n//\t{\r\n//\t\t// Reseed particles if dirty.\r\n//\t\tif( m_flags & PARTICLE_FLAG_DIRTY )\r\n//\t\t{\r\n//\t\t\tfor( int i = 0; i < m_initial_num_particles; ++i )\r\n//\t\t\t{\r\n//\t\t\t\tseedParticle( i, (float)rand() / (float)RAND_MAX );\r\n//\t\t\t}\r\n//\t\t\tm_flags &= ~PARTICLE_FLAG_DIRTY;\r\n//\t\t}\r\n//\r\n//\t\t// Refigure bounding box if required.\r\n//\t\tif( m_flags & PARTICLE_FLAG_BBOX_DIRTY )\r\n//\t\t{\r\n//\t\t\tfigureBoundingBox();\r\n//\t\t}\r\n//\r\n//\t\t// Test bounding box against view frustum.\r\n//\t\tif( cull() )\r\n//\t\t{\r\n//\t\t\treturn;\r\n//\t\t}\r\n//\r\n//\t\t// Figure time since last draw as a ratio of flight time.\r\n//\t\tfloat t_delta = m_time_since_last_draw * m_inv_flight_time;\r\n//\r\n//\t\tNsRender::begin();\r\n//\t\tNsRender::setZMode( NsZMode_LessEqual, 1, 0, 0 );\r\n//\r\n//\t    // Set current vertex descriptor to enable position and color0. Both use 8b index to access their data arrays.\r\n//\t\tGXClearVtxDesc();\r\n//\t\tGXSetVtxDesc( GX_VA_POS, GX_DIRECT );\r\n//\t    GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );\r\n//\t\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\r\n//\t\t// Upload texture if present.\r\n//\t\tNsTexture* p_texture = ( mp_material ) ? ( mp_material->getTexture() ) : NULL;\r\n//\t\tif( p_texture )\r\n//\t\t{\r\n//\t\t\tp_texture->upload( NsTexture_Wrap_Clamp );\r\n//\t\t}\r\n//\r\n//\t\tNsMatrix*\tp_matrix\t= m_frame.getModelMatrix();\r\n//\t\tVec\t\t\tmat_pos\t\t= (Vec){ p_matrix->getPosX(), p_matrix->getPosY(), p_matrix->getPosZ()};\r\n//\r\n//\t\tfor( int i = 0; i < m_num_particles; ++i )\r\n//\t\t{\r\n//\t\t\tstruct parametric_particle* p_part = mp_particles + i;\r\n//\r\n//\t\t\t// First deal with reseeding any particles that have exceeded their lifetime.\r\n//\t\t\tif(( p_part->t += t_delta ) > 1.0f )\r\n//\t\t\t{\r\n//\t\t\t\tseedParticle( i, p_part->t - 1.0f );\r\n//\t\t\t}\r\n//\r\n//\t\t\tDbg_Assert( p_part->t <= 1.0f );\r\n//\r\n//\t\t\t// Now figure current position.\r\n//\t\t\tfloat time\t\t\t\t= p_part->t * m_flight_time;\r\n//\r\n//\t\t\t// The 0.5 multiply is already done when the force is set.\r\n//\t\t\tfloat half_time_squared\t= time * time;\r\n//\t\t\tNsVector\tpos;\r\n//\t\t\tNsVector\tp, ut, at, temp;\r\n//\r\n//\t\t\tVec*\t\tp_mat_right = (Vec*)p_matrix->getRight();\r\n//\t\t\tVec*\t\tp_mat_up\t= (Vec*)p_matrix->getUp();\r\n//\t\t\tVec*\t\tp_mat_at\t= (Vec*)p_matrix->getAt();\r\n//\r\n//\t\t\tp.scale( *p_matrix->getRight(), p_part->start_pos.x );\r\n//\t\t\ttemp.scale( *p_matrix->getUp(), p_part->start_pos.y );\r\n//\t\t\tp.add( temp );\r\n//\t\t\tVECScale( p_mat_right, (Vec*)&p, p_part->start_pos.x );\r\n//\t\t\tVECScale( p_mat_up, (Vec*)&temp, p_part->start_pos.y );\r\n//\t\t\tVECAdd( (Vec*)&p, (Vec*)&temp, (Vec*)&p );\r\n//\r\n//\t\t\tut.scale( *p_matrix->getRight(), p_part->initial_velocity.x * time );\r\n//\t\t\ttemp.scale( *p_matrix->getUp(), p_part->initial_velocity.y * time );\r\n//\t\t\tut.add( temp );\r\n//\t\t\ttemp.scale( *p_matrix->getAt(), p_part->initial_velocity.z * time );\r\n//\t\t\tut.add( temp );\r\n//\t\t\tVECScale( p_mat_right, (Vec*)&ut, p_part->initial_velocity.x * time );\r\n//\t\t\tVECScale( p_mat_up, (Vec*)&temp, p_part->initial_velocity.y * time );\r\n//\t\t\tVECAdd( (Vec*)&ut, (Vec*)&temp, (Vec*)&ut );\r\n//\t\t\tVECScale( p_mat_at, (Vec*)&temp, p_part->initial_velocity.z * time );\r\n//\t\t\tVECAdd( (Vec*)&ut, (Vec*)&temp, (Vec*)&ut );\r\n//\r\n//\t\t\tat.scale( *p_matrix->getRight(), m_force.x * half_time_squared );\r\n//\t\t\ttemp.scale( *p_matrix->getUp(), m_force.y * half_time_squared );\r\n//\t\t\tat.add( temp );\r\n//\t\t\ttemp.scale( *p_matrix->getAt(), m_force.z * half_time_squared );\r\n//\t\t\tat.add( temp );\r\n//\t\t\tVECScale( p_mat_right, (Vec*)&at, m_force.x * half_time_squared );\r\n//\t\t\tVECScale( p_mat_up, (Vec*)&temp, m_force.y * half_time_squared );\r\n//\t\t\tVECAdd( (Vec*)&at, (Vec*)&temp, (Vec*)&at );\r\n//\t\t\tVECScale( p_mat_at, (Vec*)&temp, m_force.z * half_time_squared );\r\n//\t\t\tVECAdd( (Vec*)&at, (Vec*)&temp, (Vec*)&at );\r\n//\r\n//\t\t\tpos.set( p_matrix->getPosX() + p.x + ut.x + at.x, p_matrix->getPosY() + p.y + ut.y + at.y, p_matrix->getPosZ() + p.z + ut.z + at.z );\r\n//\t\t\tVECAdd((Vec*)&p, (Vec*)&ut, (Vec*)&pos );\r\n//\t\t\tVECAdd((Vec*)&pos, (Vec*)&mat_pos, (Vec*)&pos );\r\n//\t\t\tVECAdd((Vec*)&pos, (Vec*)&at, (Vec*)&pos );\r\n//\r\n//\t\t\t// Deal with color change.\r\n//\t\t\tGXColor color;\r\n//\t\t\tcolor.r = (int)( m_gx_start_color_r + ( m_gx_delta_color_r * p_part->t ));\r\n//\t\t\tcolor.g = (int)( m_gx_start_color_g + ( m_gx_delta_color_g * p_part->t ));\r\n//\t\t\tcolor.b = (int)( m_gx_start_color_b + ( m_gx_delta_color_b * p_part->t ));\r\n//\t\t\tcolor.a = ((int)( m_gx_start_color_a + ( m_gx_delta_color_a * p_part->t ))) / 2;\r\n//\r\n//\t\t\tif( mp_material )\r\n//\t\t\t{\r\n//\t\t\t\tNsRender::setBlendMode(\tmp_material->getBlendMode(), p_texture, color.a );\r\n//\t\t\t}\r\n//\r\n//\t\t\t// Deal with particle growth.\r\n//\t\t\tfloat\t\twidth\t= ( m_size + ( m_size * m_growth * p_part->t )) * 0.5f;\r\n//\t\t\tfloat\t\theight\t= width * m_aspect_ratio;\r\n//\t\t\tNsVector\tss_right, ss_up, ss_pos;\r\n//\t\t\tss_right.scale( screen_right, width );\r\n//\t\t\tss_up.scale( screen_up, height );\r\n//\t\t\tVECScale((Vec*)&screen_right, (Vec*)&ss_right, width );\r\n//\t\t\tVECScale((Vec*)&screen_up, (Vec*)&ss_up, height );\r\n//\r\n//\t\t\t// Set material color.\r\n//\t\t\tGX::SetChanMatColor( GX_COLOR0A0, color );\r\n//\r\n//\t\t\t// Send coordinates.\r\n//\t\t    GXBegin( GX_QUADS, GX_VTXFMT3, 4 ); \r\n//\t\t\tss_pos.sub( pos, ss_right );\r\n//\t\t\tss_pos.sub( ss_up );\r\n//\t\t\tVECSubtract((Vec*)&pos, (Vec*)&ss_right, (Vec*)&ss_pos );\r\n//\t\t\tVECSubtract((Vec*)&ss_pos, (Vec*)&ss_up, (Vec*)&ss_pos );\r\n//\t\t\tGXPosition3f32( ss_pos.x, ss_pos.y, ss_pos.z );\r\n//\t\t\tGXTexCoord2f32( 0.0f, 0.0f );\r\n//\r\n//\t\t\tss_pos.add( pos, ss_right );\r\n//\t\t\tss_pos.sub( ss_up );\r\n//\t\t\tVECAdd((Vec*)&pos, (Vec*)&ss_right, (Vec*)&ss_pos );\r\n//\t\t\tVECSubtract((Vec*)&ss_pos, (Vec*)&ss_up, (Vec*)&ss_pos );\r\n//\t\t\tGXPosition3f32( ss_pos.x, ss_pos.y, ss_pos.z );\r\n//\t\t\tGXTexCoord2f32( 1.0f, 0.0f);\r\n//\r\n//\t\t\tss_pos.add( pos, ss_right );\r\n//\t\t\tss_pos.add( ss_up );\r\n//\t\t\tVECAdd((Vec*)&pos, (Vec*)&ss_right, (Vec*)&ss_pos );\r\n//\t\t\tVECAdd((Vec*)&ss_pos, (Vec*)&ss_up, (Vec*)&ss_pos );\r\n//\t\t\tGXPosition3f32( ss_pos.x, ss_pos.y, ss_pos.z );\r\n//\t\t\tGXTexCoord2f32( 1.0f, 1.0f);\r\n//\r\n//\t\t\tss_pos.sub( pos, ss_right );\r\n//\t\t\tss_pos.add( ss_up );\r\n//\t\t\tVECSubtract((Vec*)&pos, (Vec*)&ss_right, (Vec*)&ss_pos );\r\n//\t\t\tVECAdd((Vec*)&ss_pos, (Vec*)&ss_up, (Vec*)&ss_pos );\r\n//\t\t\tGXPosition3f32( ss_pos.x, ss_pos.y, ss_pos.z );\r\n//\t\t\tGXTexCoord2f32( 0.0f, 1.0f);\r\n//\t\t\tGXEnd();\r\n//\t\t}\r\n//\t\tNsRender::end();\r\n//\t}\r\n//\tm_time_since_last_draw = 0.0f;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void NsParticleAtomic::setMaterial( NsMaterial* p_material )\r\n//{\r\n//\tif( mp_material )\r\n//\t{\r\n//\t\tdelete mp_material;\r\n//\t}\r\n//\r\n//\tmp_material = new NsMaterial;\r\n//\tmemcpy( mp_material, p_material, sizeof( NsMaterial ));\t\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void NsParticleAtomic::SetEmitterSize( float w, float h )\r\n//{\r\n//\tm_emitter_width\t\t= w * 0.5f;\r\n//\tm_emitter_height\t= h * 0.5f;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void NsParticleAtomic::SetEmitterAngle( float angle )\r\n//{\r\n//\t// Convert to radians.\r\n//\tangle *= Mth::PI / 180.0f;\r\n//\r\n//\t// Convert to range [0, 1].\r\n//    m_emitter_angle = angle / ( Mth::PI * 0.5f );\r\n//\r\n//\tm_flags |= ( PARTICLE_FLAG_DIRTY | PARTICLE_FLAG_BBOX_DIRTY );\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void NsParticleAtomic::setParticleColors( uint32* start, uint32* end )\r\n//{\r\n//\tm_start_color\t= *start;\r\n//\tm_end_color\t\t= *end;\r\n//\r\n//\tm_gx_start_color_r\t= (float)((int)( m_start_color & 0xFF ));\r\n//\tm_gx_start_color_g\t= (float)((int)(( m_start_color >> 8 ) & 0xFF ));\r\n//\tm_gx_start_color_b\t= (float)((int)(( m_start_color >> 16 ) & 0xFF ));\r\n//\tm_gx_start_color_a\t= (float)((int)(( m_start_color >> 24 ) & 0xFF ));\r\n//\r\n//\tm_gx_delta_color_r\t= (float)((int)( m_end_color & 0xFF )) - m_gx_start_color_r;\r\n//\tm_gx_delta_color_g\t= (float)((int)(( m_end_color >> 8 ) & 0xFF )) - m_gx_start_color_g;\r\n//\tm_gx_delta_color_b\t= (float)((int)(( m_end_color >> 16 ) & 0xFF )) - m_gx_start_color_b;\r\n//\tm_gx_delta_color_a\t= (float)((int)(( m_end_color >> 24 ) & 0xFF )) - m_gx_start_color_a;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//uint32 NsParticleAtomic::getParticleColors( uint32 index )\r\n//{\r\n//\tif( index == 0 )\r\n//\t\treturn m_start_color;\r\n//\telse\r\n//\t\treturn m_end_color;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void NsParticleAtomic::setParticleSpeed( float min, float max, float damping )\r\n//{\r\n//\tm_min_speed\t\t\t= ( min + max ) * 0.5f;\r\n//\tm_variation_speed\t= max - m_min_speed;\r\n//\tm_damping\t\t\t= -damping;\r\n//\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void NsParticleAtomic::setParticleFlightTime( float t )\r\n//{\r\n//\tm_flight_time\t\t= t;\r\n//\tm_inv_flight_time\t= 1.0f / t;\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void NsParticleAtomic::setParticleForce( NsVector& f )\r\n//{\r\n//\t// Scaled here for the 1/2at^2 calc.\r\n//\tm_force.scale( f, 0.5f );\r\n//}\r\n//\r\n//\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n//void NsParticleAtomic::setParticleSize( float size, float growth, float aspect_ratio )\r\n//{\r\n//\tm_size\t\t\t= size;\r\n//\tm_growth\t\t= growth;\r\n//\tm_aspect_ratio\t= aspect_ratio;\r\n//}\r\n//\r\n//} // namespace NsParticle\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_particle.h",
    "content": "///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n//**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//******************************************************************************\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tProject:\t\tSkate3      \t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tModule:\t\t\tGFX\t\t\t  \t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tCreated:\t\t08/16/01\tdc\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tFile name:\t\tp_particle.h               \t\t\t\t\t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//**\tDescription:\tBGC particle system interface              \t\t\t\t**\r\n//**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//#ifndef __P_PARTICLE_H\r\n//#define __P_PARTICLE_H\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//#ifndef __CORE_DEFINES_H\r\n//#include <core/defines.h>\r\n//#endif\r\n//\r\n//#include <core/lookuptable.h>\r\n//\r\n//namespace Particle\r\n//{\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//struct parametric_particle\r\n//{\r\n//\tNsVector\tstart_pos;\r\n//\tNsVector\tinitial_velocity;\r\n//\tfloat\t\tt;\t\t\t// [0.0, 1.0]\r\n//};\r\n//\r\n//nBaseClass( NsParticleAtomic )\r\n//{\r\n//\tDbg_BaseClass( NsParticleAtomic );\r\n//\r\n//\tpublic:\r\n//\r\n//\t\t\t\t\t\t\t\tNsParticleAtomic( int num_particle, NsMaterial* p_material );\r\n//\t\t\t\t\t\t\t\t~NsParticleAtomic();\r\n//\r\n//\tvoid\t\t\t\t\t\tupdate( float delta_t );\r\n//\tvoid\t\t\t\t\t\tSetNumParticles( int num );\r\n//\tvoid\t\t\t\t\t\tsetMaterial( NsMaterial* p_material );\r\n//\tvoid\t\t\t\t\t\tSetEmitterSize( float w, float h );\r\n//\tvoid\t\t\t\t\t\tSetEmitterAngle( float angle );\r\n//\tvoid\t\t\t\t\t\tsetParticleColors( uint32* start, uint32* end );\r\n//\tuint32\t\t\t\t\t\tgetParticleColors( uint32 index );\r\n//\tvoid\t\t\t\t\t\tsetParticleSpeed( float min, float max, float damping );\r\n//\tvoid\t\t\t\t\t\tsetParticleFlightTime( float t );\r\n//\tvoid\t\t\t\t\t\tsetParticleForce( NsVector& f );\r\n//\tvoid\t\t\t\t\t\tsetParticleSize( float size, float growth, float aspect_ratio );\r\n//\tvoid\t\t\t\t\t\tdraw( void );\r\n//\tNsFrame*\t\t\t\t\tgetFrame( void )\t\t{ return &m_frame; }\r\n//\tvoid\t\t\t\t\t\tsetVisible( bool vis )\t{ m_visible = vis; }\r\n//\r\n//\tenum EParticleFlags\r\n//\t{\r\n//\t\tPARTICLE_FLAG_DIRTY\t\t\t= 0x01,\r\n//\t\tPARTICLE_FLAG_BBOX_DIRTY\t= 0x02\r\n//\t};\r\n//\r\n//\r\n//\tprivate:\r\n//\r\n//\tunsigned int\t\t\t\tm_flags;\r\n//\tNsBBox\t\t\t\t\t\tm_bbox;\r\n//\tNsMaterial*\t\t\t\t\tmp_material;\r\n//\tNsFrame\t\t\t\t\t\tm_frame;\r\n//\tstruct parametric_particle*\tmp_particles;\r\n//\tint\t\t\t\t\t\t\tm_initial_num_particles;\r\n//\tint\t\t\t\t\t\t\tm_num_particles;\t\t\t// This can be set dynamically to *less* than the initial number.\r\n//\tbool\t\t\t\t\t\tm_visible;\r\n//\tfloat\t\t\t\t\t\tm_time_since_last_draw;\r\n//\tfloat\t\t\t\t\t\tm_emitter_width;\r\n//\tfloat\t\t\t\t\t\tm_emitter_height;\r\n//\tfloat\t\t\t\t\t\tm_emitter_angle;\r\n//\tuint32\t\t\t\t\t\tm_start_color;\r\n//\tuint32\t\t\t\t\t\tm_end_color;\r\n//\tfloat\t\t\t\t\t\tm_gx_start_color_r, m_gx_start_color_g, m_gx_start_color_b, m_gx_start_color_a;\r\n//\tfloat\t\t\t\t\t\tm_gx_delta_color_r, m_gx_delta_color_g, m_gx_delta_color_b, m_gx_delta_color_a;\r\n//\tfloat\t\t\t\t\t\tm_min_speed;\r\n//\tfloat\t\t\t\t\t\tm_variation_speed;\r\n//\tfloat\t\t\t\t\t\tm_damping;\r\n//\tfloat\t\t\t\t\t\tm_flight_time;\r\n//\tfloat\t\t\t\t\t\tm_inv_flight_time;\r\n//\tNsVector\t\t\t\t\tm_force;\r\n//\tfloat\t\t\t\t\t\tm_size;\r\n//\tfloat\t\t\t\t\t\tm_growth;\r\n//\tfloat\t\t\t\t\t\tm_aspect_ratio;\r\n//\r\n//\tvoid\t\t\t\t\t\tseedParticle( int p, float t_max );\r\n//\tvoid\t\t\t\t\t\tfigureBoundingBox( void );\r\n//\tbool\t\t\t\t\t\tcull( void );\r\n//};\r\n//\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//void SetParticleAtomicCamera( NsCamera* p_cam );\r\n//\r\n//\r\n//\r\n///*****************************************************************************\r\n//**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n//*****************************************************************************/\r\n//\r\n//} // namespace Particle\r\n//\r\n//#endif // __P_PARTICLE_H\r\n//\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_ppcwgpipe.h",
    "content": "/*---------------------------------------------------------------------------*\r\n  Project: Write gather pipe definitions\r\n  File:    PPCWGPipe.h\r\n\r\n  Copyright 1998, 1999 Nintendo.  All rights reserved.\r\n\r\n  These coded instructions, statements, and computer programs contain\r\n  proprietary information of Nintendo of America Inc. and/or Nintendo\r\n  Company Ltd., and are protected by Federal copyright law.  They may\r\n  not be disclosed to third parties or copied or duplicated in any form,\r\n  in whole or in part, without the prior written consent of Nintendo.\r\n\r\n  $Log: /Dolphin/include/dolphin/base/PPCWGPipe.h $\r\n    \r\n    2     11/01/00 3:55p Shiki\r\n    Removed #ifdef EPPC.\r\n\r\n    1     7/14/99 6:59p Yoshya01\r\n    Initial version.\r\n  $NoKeywords: $\r\n *---------------------------------------------------------------------------*/\r\n#ifndef __PPCWGPIPE_H__\r\n#define __PPCWGPIPE_H__\r\n\r\n#ifdef  __cplusplus\r\nextern  \"C\" {\r\n#endif\r\n\r\n#include <dolphin/types.h>\r\n\r\n/*---------------------------------------------------------------------------*\r\n    PPC Write Gather Pipe\r\n\r\n    Write Gather Pipe is defined as:\r\n        PPCWGPipe wgpipe : <Write Gathered Address>;\r\n\r\n    Then, used as:\r\n        wgpipe.u8  = 0xff;\r\n        wgpipe.s16 = -5;\r\n        wgpipe.f32 = 0.10f;\r\n *---------------------------------------------------------------------------*/\r\n\r\n#ifdef __SN__\r\n\r\ntypedef  s8 ts8;\r\ntypedef  s16 ts16;\r\ntypedef  s32 ts32;\r\ntypedef  s64 ts64;\r\ntypedef  u8 tu8;\r\ntypedef  u16 tu16;\r\ntypedef  u32 tu32;\r\ntypedef  u64 tu64;\r\ntypedef  f32 tf32;\r\ntypedef  f64 tf64;\r\n\r\ntypedef volatile union u_PPCWGPipe\r\n{\r\n    tu8  u8;\r\n    tu16 u16;\r\n    tu32 u32;\r\n    tu64 u64;\r\n    ts8  s8;\r\n    ts16 s16;\r\n    ts32 s32;\r\n    ts64 s64;\r\n    tf32 f32;\r\n    tf64 f64;\r\n} PPCWGPipe;\r\n\r\n#else\r\n\r\ntypedef volatile union PPCWGPipe\r\n{\r\n    u8  u8;\r\n    u16 u16;\r\n    u32 u32;\r\n    u64 u64;\r\n    s8  s8;\r\n    s16 s16;\r\n    s32 s32;\r\n    s64 s64;\r\n    f32 f32;\r\n    f64 f64;\r\n} PPCWGPipe;\r\n\r\n#endif\r\n\r\n\r\n#ifdef  __cplusplus\r\n}\r\n#endif\r\n\r\n#endif  //__PPCWGPIPE_H__\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_prim.cpp",
    "content": "/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsPrim\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tProvides functionality for drawing various types of single\t\t*\r\n *\t\t\t\tprimitives to the display.\t\t\t\t\t\t\t\t\t\t*\r\n *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#include <math.h>\r\n#include \"p_prim.h\"\r\n#include \"p_assert.h\"\r\n#include \"p_render.h\"\r\n//#include \"p_tex.h\"\r\n#include \t\"gfx/ngc/nx/mesh.h\"\r\n#include <sys/ngc/p_gx.h>\r\n\r\n/********************************************************************************\r\n * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nint inDrawingContext = 0;\r\n\r\n/********************************************************************************\r\n * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tbegin\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tOpens the drawing context. This must be called before any\t\t*\r\n *\t\t\t\tprimitives can be built. Sets up an orthogonal viewport.\t\t*\r\n *\t\t\t\tThe viewport is set to 0.0f,0.0f at the top-left corner, and\t*\r\n *\t\t\t\t640.0f,480.0f at the bottom-right corner.\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::begin ( void )\r\n{\r\n\tinDrawingContext = 1;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tpoint\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx, y, z\t\tcoordinate of point.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor\t\tcolor of the point.\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a point primitive.\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::point ( float x, float y, float z, GXColor color )\r\n{\r\n//\tassert ( inDrawingContext );\r\n\r\n    // Set current vertex descriptor to enable position and color0.\r\n    // Both use 8b index to access their data arrays.\r\n    GX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n\r\n    // Set material color.\r\n    GX::SetChanMatColor( GX_COLOR0A0, color );\r\n    GX::SetChanAmbColor( GX_COLOR0A0, (GXColor){128,128,128,255} );\r\n\r\n    GX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\r\n\t// Send coordinates.\r\n    GX::Begin( GX_POINTS, GX_VTXFMT0, 1 ); \r\n        GX::Position3f32(x, y, z);\r\n    GX::End();\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tpoint\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx, y\t\tcoordinate of point.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor\t\tcolor of the point.\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a point primitive.\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::point ( float x, float y, GXColor color )\r\n{\r\n\tpoint ( x, y, -1.0f, color );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tline\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx0, y0, z0\tcoordinates of end 0.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx1, y1, z0\tcoordinates of end 1.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor\t\tcolor of the primitive.\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a flat color line primitive.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::line ( float x0, float y0, float z0, float x1, float y1, float z1, GXColor color )\r\n{\r\n//\tassert ( inDrawingContext );\r\n\r\n    // Set current vertex descriptor to enable position and color0.\r\n    // Both use 8b index to access their data arrays.\r\n    GX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n\r\n    // Set material color.\r\n    GX::SetChanMatColor( GX_COLOR0A0, color );\r\n    GX::SetChanAmbColor( GX_COLOR0A0, (GXColor){128,128,128,255} );\r\n\r\n    GX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\r\n\t// Send coordinates.\r\n    GX::Begin( GX_LINES, GX_VTXFMT0, 2 ); \r\n        GX::Position3f32(x0, y0, z0);\r\n        GX::Position3f32(x1, y1, z1);\r\n    GX::End();\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tline\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx0, y0\t\tcoordinates of end 0.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx1, y1\t\tcoordinates of end 1.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor\t\tcolor of the primitive.\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a flat color line primitive.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::line ( float x0, float y0, float x1, float y1, GXColor color )\r\n{\r\n\tline ( x0, y0, -1.0f, x1, y1, -1.0f, color );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tline\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx0, y0, z0\tcoordinates of end 0.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx1, y1, z0\tcoordinates of end 1.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor0\t\tcolor of the primitive at corner 0.\t\t\t\t\t*\r\n *\t\t\t\tcolor1\t\tcolor of the primitive at corner 1.\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a flat color line primitive.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::line ( float x0, float y0, float z0, float x1, float y1, float z1, GXColor color0, GXColor color1 )\r\n{\r\n//\tassert ( inDrawingContext );\r\n\r\n    // Set current vertex descriptor to enable position and color0.\r\n    // Both use 8b index to access their data arrays.\r\n    GX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\r\n    GX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\r\n\t// Send coordinates.\r\n    GX::Begin( GX_LINES, GX_VTXFMT0, 2 ); \r\n        GX::Position3f32(x0, y0, z0);\r\n\t\tGX::Color1u32(*((u32*)&color0));\r\n        GX::Position3f32(x1, y1, z1);\r\n\t\tGX::Color1u32(*((u32*)&color1));\r\n    GX::End();\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tline\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx0, y0\t\tcoordinates of end 0.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx1, y1\t\tcoordinates of end 1.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor0\t\tcolor of the primitive at corner 0.\t\t\t\t\t*\r\n *\t\t\t\tcolor1\t\tcolor of the primitive at corner 1.\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a flat color line primitive.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::line ( float x0, float y0, float x1, float y1, GXColor color0, GXColor color1 )\r\n{\r\n\tline ( x0, y0, -1.0f, x1, y1, -1.0f, color0, color1 );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\ttri\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx0, y0, z0\tcoordinates of corner 0.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx1, y1, z1\tcoordinates of corner 1.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx2, y2, z2\tcoordinates of corner 2.\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor\t\tcolor of the primitive.\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a flat color triangle primitive.\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::tri ( float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2, GXColor color )\r\n{\r\n//\tassert ( inDrawingContext );\r\n\r\n    // Set current vertex descriptor to enable position and color0.\r\n    // Both use 8b index to access their data arrays.\r\n    GX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n\r\n    // Set material color.\r\n    GX::SetChanMatColor( GX_COLOR0A0, color );\r\n    GX::SetChanAmbColor( GX_COLOR0A0, (GXColor){128,128,128,255} );\r\n\r\n    GX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\r\n\t// Send coordinates.\r\n    GX::Begin( GX_TRIANGLES, GX_VTXFMT0, 3 ); \r\n        GX::Position3f32(x0, y0, z0);\r\n        GX::Position3f32(x1, y1, z1);\r\n        GX::Position3f32(x2, y2, z2);\r\n    GX::End();\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\ttri\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx0, y0\t\tcoordinates of corner 0.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx1, y1\t\tcoordinates of corner 1.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx2, y2\t\tcoordinates of corner 2.\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor\t\tcolor of the primitive.\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a flat color triangle primitive.\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::tri ( float x0, float y0, float x1, float y1, float x2, float y2, GXColor color )\r\n{\r\n\ttri ( x0, y0, -1.0f, x1, y1, -1.0f, x2, y2, -1.0f, color );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\ttri\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx0, y0, z0\tcoordinates of corner 0.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx1, y1, z1\tcoordinates of corner 1.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx2, y2, z2\tcoordinates of corner 2.\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor0\t\tcolor of the primitive at corner 0.\t\t\t\t\t*\r\n *\t\t\t\tcolor1\t\tcolor of the primitive at corner 1.\t\t\t\t\t*\r\n *\t\t\t\tcolor2\t\tcolor of the primitive at corner 2.\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a gouraud-shaded triangle primitive.\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::tri ( float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2, GXColor color0, GXColor color1, GXColor color2 )\r\n{\r\n//\tassert ( inDrawingContext );\r\n\r\n    // Set current vertex descriptor to enable position and color0.\r\n    // Both use 8b index to access their data arrays.\r\n    GX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\r\n    GX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE );\r\n\r\n\t// Send coordinates.\r\n    GX::Begin( GX_TRIANGLES, GX_VTXFMT0, 3 ); \r\n        GX::Position3f32(x0, y0, z0);\r\n\t\tGX::Color1u32(*((u32*)&color0));\r\n        GX::Position3f32(x1, y1, z1);\r\n\t\tGX::Color1u32(*((u32*)&color1));\r\n        GX::Position3f32(x2, y2, z2);\r\n\t\tGX::Color1u32(*((u32*)&color2));\r\n    GX::End();\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\ttri\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx0, y0\t\tcoordinates of corner 0.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx1, y1\t\tcoordinates of corner 1.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx2, y2\t\tcoordinates of corner 2.\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor0\t\tcolor of the primitive at corner 0.\t\t\t\t\t*\r\n *\t\t\t\tcolor1\t\tcolor of the primitive at corner 1.\t\t\t\t\t*\r\n *\t\t\t\tcolor2\t\tcolor of the primitive at corner 2.\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a gouraud-shaded triangle primitive.\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::tri ( float x0, float y0, float x1, float y1, float x2, float y2, GXColor color0, GXColor color1, GXColor color2 )\r\n{\r\n\ttri ( x0, y0, -1.0f, x1, y1, -1.0f, x2, y2, -1.0f, color0, color1, color2 );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tquad\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx0, y0, z0\tcoordinates of corner 0.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx1, y1, z1\tcoordinates of corner 1.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx2, y2, z2\tcoordinates of corner 2.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx3, y3, z3\tcoordinates of corner 3.\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor\t\tcolor of the primitive.\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a flat color quad primitive.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::quad ( float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, GXColor color )\r\n{\r\n//\tassert ( inDrawingContext );\r\n\r\n    // Set current vertex descriptor to enable position and color0.\r\n    // Both use 8b index to access their data arrays.\r\n    GX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );\r\n\r\n    // Set material color.\r\n    GX::SetChanMatColor( GX_COLOR0A0, color );\r\n    GX::SetChanAmbColor( GX_COLOR0A0, (GXColor){128,128,128,255} );\r\n\r\n    GX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\r\n\t// Send coordinates.\r\n    GX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n        GX::Position3f32(x0, y0, z0);\r\n        GX::Position3f32(x1, y1, z1);\r\n        GX::Position3f32(x2, y2, z2);\r\n        GX::Position3f32(x3, y3, z3);\r\n    GX::End();\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tquad\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx0, y0\t\tcoordinates of corner 0.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx1, y1\t\tcoordinates of corner 1.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx2, y2\t\tcoordinates of corner 2.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx3, y3\t\tcoordinates of corner 3.\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor\t\tcolor of the primitive.\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a flat color quad primitive.\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::quad ( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, GXColor color )\r\n{\r\n\tquad ( x0, y0, -1.0f, x1, y1, -1.0f, x2, y2, -1.0f, x3, y3, -1.0f, color );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tquad\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx0, y0, z0\tcoordinates of corner 0.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx1, y1, z1\tcoordinates of corner 1.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx2, y2, z2\tcoordinates of corner 2.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx3, y3, z3\tcoordinates of corner 3.\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor0\t\tcolor of the primitive at corner 0.\t\t\t\t\t*\r\n *\t\t\t\tcolor1\t\tcolor of the primitive at corner 1.\t\t\t\t\t*\r\n *\t\t\t\tcolor2\t\tcolor of the primitive at corner 2.\t\t\t\t\t*\r\n *\t\t\t\tcolor3\t\tcolor of the primitive at corner 3.\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a gouraud-shaded quad primitive.\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::quad ( float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, GXColor color0, GXColor color1, GXColor color2, GXColor color3 )\r\n{\r\n//\tassert ( inDrawingContext );\r\n\r\n    // Set current vertex descriptor to enable position and color0.\r\n    // Both use 8b index to access their data arrays.\r\n    GX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_CLR0, GX_DIRECT );\r\n\r\n    GX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\r\n\t// Send coordinates.\r\n    GX::Begin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n        GX::Position3f32(x0, y0, z0);\r\n\t\tGX::Color1u32(*((u32*)&color0));\r\n        GX::Position3f32(x1, y1, z1);\r\n\t\tGX::Color1u32(*((u32*)&color1));\r\n        GX::Position3f32(x2, y2, z2);\r\n\t\tGX::Color1u32(*((u32*)&color2));\r\n        GX::Position3f32(x3, y3, z3);\r\n\t\tGX::Color1u32(*((u32*)&color3));\r\n    GX::End();\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tquad\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tx0, y0\t\tcoordinates of corner 0.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx1, y1\t\tcoordinates of corner 1.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx2, y2\t\tcoordinates of corner 2.\t\t\t\t\t\t\t*\r\n *\t\t\t\tx3, y3\t\tcoordinates of corner 3.\t\t\t\t\t\t\t*\r\n *\t\t\t\tcolor0\t\tcolor of the primitive at corner 0.\t\t\t\t\t*\r\n *\t\t\t\tcolor1\t\tcolor of the primitive at corner 1.\t\t\t\t\t*\r\n *\t\t\t\tcolor2\t\tcolor of the primitive at corner 2.\t\t\t\t\t*\r\n *\t\t\t\tcolor3\t\tcolor of the primitive at corner 3.\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tBuilds a gouraud-shaded quad primitive.\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::quad ( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, GXColor color0, GXColor color1, GXColor color2, GXColor color3 )\r\n{\r\n\tquad ( x0, y0, -1.0f, x1, y1, -1.0f, x2, y2, -1.0f, x3, y3, -1.0f, color0, color1, color2, color3 );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tframe\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tleft\tleft side position of the orthogonal region.\t\t\t*\r\n *\t\t\t\tright\tright side position of the orthogonal region.\t\t\t*\r\n *\t\t\t\ttop\t\ttop side position of the orthogonal region.\t\t\t\t*\r\n *\t\t\t\tbottom\tbottom side position of the orthogonal region.\t\t\t*\r\n *\t\t\t\tcolor\tcolor of the lines.\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tDraws the perimiter lines to an orthogonal region.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::frame ( float left, float top, float right, float bottom, GXColor color )\r\n{\r\n\tline ( left,  top,    right, top,    color );\r\n\tline ( left,  bottom, right, bottom, color );\r\n\tline ( left,  top,    left,  bottom, color );\r\n\tline ( right, top,    right, bottom, color );\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tbox\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tleft\tleft side position of the orthogonal region.\t\t\t*\r\n *\t\t\t\tright\tright side position of the orthogonal region.\t\t\t*\r\n *\t\t\t\ttop\t\ttop side position of the orthogonal region.\t\t\t\t*\r\n *\t\t\t\tbottom\tbottom side position of the orthogonal region.\t\t\t*\r\n *\t\t\t\tcolor\tcolor of the box.\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tDraws a solid box representing an orthogonal region.\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::box ( float left, float top, float right, float bottom, GXColor color )\r\n{\r\n\tquad ( left, top, right, top, right, bottom, left, bottom, color );\r\n}\r\n\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tquad\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tx0, y0, z0\tcoordinates of corner 0.\t\t\t\t\t\t\t*\r\n// *\t\t\t\tx1, y1, z1\tcoordinates of corner 1.\t\t\t\t\t\t\t*\r\n// *\t\t\t\tx2, y2, z2\tcoordinates of corner 2.\t\t\t\t\t\t\t*\r\n// *\t\t\t\tx3, y3, z3\tcoordinates of corner 3.\t\t\t\t\t\t\t*\r\n// *\t\t\t\tcolor\t\tcolor of the primitive.\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tBuilds a flat color quad primitive.\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void NsPrim::sprite ( NsTexture * pTexture, float x0, float y0, float z0, float x1, float y1, float z1 )\r\n//{\r\n//\tint\t\tupheight;\r\n//\r\n//\tassert ( inDrawingContext );\r\n//\r\n//    // Set current vertex descriptor to enable position and color0.\r\n//    // Both use 8b index to access their data arrays.\r\n//    GXClearVtxDesc();\r\n//    GXSetVtxDesc( GX_VA_POS, GX_DIRECT );\r\n//    GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );\r\n//\r\n//    // Set material color.\r\n//    GX::SetChanMatColor( GX_COLOR0A0, (GXColor){128,128,128,128} );\r\n//    GX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\r\n//    GX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\r\n////\tif ( (pTexture->width > 512) || (pTexture->height > 512) ) {\r\n//\t\tint\t\tlp, lp2;\r\n//\t\tint\t\tw, h;\r\n//\t\tchar  * p8;\r\n//\t\tfloat\tfx0, fy0;\r\n//\t\tfloat\tfx1, fy1;\r\n//\t\tfloat\tbv;\r\n//\r\n//\t\tp8 = (char *)pTexture->m_pImage;\r\n//\t\tfor ( lp2 = 0; lp2 < pTexture->m_height; lp2 += 512 ) {\r\n//\t\t\th = (pTexture->m_height - lp2) < 512 ? (pTexture->m_height - lp2) : 512;\r\n//\t\t\tupheight = (h&(h-1)) ? ((~((h>>1)|(h>>2)|(h>>3)|(h>>4)|(h>>5)|(h>>6)|(h>>7)|(h>>8)|(h>>9)))&h)<<1 : h;\r\n//\t\t\tfor ( lp = 0; lp < pTexture->m_width; lp += 512 ) {\r\n//\t\t\t\tw = (pTexture->m_width - lp) < 512 ? (pTexture->m_width - lp) : 512;\r\n//\t\t\t\t// Upload this segment.\r\n//\t\t\t\tpTexture->upload( NsTexture_Wrap_Clamp, (void *)p8, w, upheight );\r\n//\t\t\t\tp8 += ( w * h * pTexture->m_depth ) / 8;\r\n//\r\n//\t\t\t\t// Calculate coordinates.\r\n//\t\t\t\tfx0 = ( lp        * ( x1 - x0 ) ) / pTexture->m_width;\r\n//\t\t\t\tfx1 = ( (lp + w)  * ( x1 - x0 ) ) / pTexture->m_width;\r\n//\t\t\t\tfy0 = ( lp2       * ( y1 - y0 ) ) / pTexture->m_height;\r\n//\t\t\t\tfy1 = ( (lp2 + h) * ( y1 - y0 ) ) / pTexture->m_height;\r\n////\t\t\t\tOSReport ( \"Upload: %4d,%4d %4dx%4d   Draw: %6.1f,%6.1f %6.1f,%6.1f\\n\", lp, lp2, w, h, fx0, fy0, fx1, fy1 );\r\n//\r\n//\t\t\t\tbv = (float)h / (float)upheight;\r\n//\t\t\t\t// Send coordinates.\r\n//\t\t\t    GXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//\t\t\t        GXPosition3f32(fx0, fy0, -1.0f);\r\n//\t\t\t\t\tGXTexCoord2f32(0.0f, 0.0f);\r\n//\t\t\t        GXPosition3f32(fx1, fy0, -1.0f);\r\n//\t\t\t\t\tGXTexCoord2f32(1.0f, 0.0f);\r\n//\t\t\t        GXPosition3f32(fx1, fy1, -1.0f);\r\n//\t\t\t\t\tGXTexCoord2f32(1.0f, bv);\r\n//\t\t\t        GXPosition3f32(fx0, fy1, -1.0f);\r\n//\t\t\t\t\tGXTexCoord2f32(0.0f, bv);\r\n//\t\t\t    GXEnd();\r\n//\t\t\t}\r\n//\t\t}\r\n////\t} else {\r\n////\t\tint h;\r\n////\t\tfloat\tbu;\r\n////\t\tfloat\tbv;\r\n////\t\th = pTexture->m_height;\r\n////\t\tupheight = (h&(h-1)) ? ((~((h>>1)|(h>>2)|(h>>3)|(h>>4)|(h>>5)|(h>>6)|(h>>7)|(h>>8)|(h>>9)))&h)<<1 : h;\r\n////\r\n////\t\tpTexture->upload( NsTexture_Wrap_Clamp, pTexture->m_pImage, pTexture->m_width, upheight );\r\n//////\t\tpTexture->upload( NsTexture_Wrap_Clamp );\r\n////\r\n////\t\tNsRender::setBlendMode ( NsBlendMode_Blend, pTexture, (unsigned char)128 );\r\n////\r\n////\r\n////\r\n////\t\tbu = 1.0f;\r\n////\t\tbv = (float)h / (float)upheight;\r\n////\t\t// Send coordinates.\r\n////\t    GXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n////\t        GXPosition3f32(x0, y0, -1.0f);\r\n////\t\t\tGXTexCoord2f32(0.0f, 0.0f);\r\n////\t        GXPosition3f32(x1, y0, -1.0f);\r\n////\t\t\tGXTexCoord2f32(bu, 0.0f);\r\n////\t        GXPosition3f32(x1, y1, -1.0f);\r\n////\t\t\tGXTexCoord2f32(bu, bv);\r\n////\t        GXPosition3f32(x0, y1, -1.0f);\r\n////\t\t\tGXTexCoord2f32(0.0f, bv);\r\n////\t    GXEnd();\r\n////\t}\r\n//}\r\n//\r\n//void NsPrim::sprite ( NsTexture * pTexture, float x, float y, float z )\r\n//{\r\n//\tsprite ( pTexture, x, y, z, x + (float)pTexture->m_width, y + (float)pTexture->m_height, z );\r\n//}\r\n//\r\n////void sprite ( Tex * pTexture, float x, float y )\r\n////{\r\n////\tsprite ( pTexture, x, y, -1.0f, x + (float)pTexture->m_width, y + (float)pTexture->m_height, -1.0f );\r\n////}\r\n////\r\n////void sprite ( Tex * pTexture, float x0, float y0, float x1, float y1 )\r\n////{\r\n////\tsprite ( pTexture, x0, y0, -1.0f, x1, y1, -1.0f );\r\n////}\r\n//\r\n////void sprite ( const char * pName, float x0, float y0, float z0, float x1, float y1, float z1 )\r\n////{\r\n////\tTex\r\n////}\r\n//\r\n//void NsPrim::subsprite ( NsTexture * pTexture, float x, float y, short sx, short sy, short sw, short sh )\r\n//{\r\n//\tfloat x0, y0, x1, y1;\r\n//\r\n//\tassert ( inDrawingContext );\r\n//\r\n//\tx0 = x;\r\n//\ty0 = y;\r\n//\tx1 = x + (float)sw;\r\n//\ty1 = y + (float)sh;\r\n//\r\n//\tpTexture->upload( NsTexture_Wrap_Clamp );\r\n//\r\n//    // Set current vertex descriptor to enable position and color0.\r\n//    // Both use 8b index to access their data arrays.\r\n//    GXClearVtxDesc();\r\n//    GXSetVtxDesc( GX_VA_POS, GX_DIRECT );\r\n//    GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );\r\n//\r\n//    // Set material color.\r\n//    GX::SetChanMatColor( GX_COLOR0A0, (GXColor){128,128,128,128} );\r\n//    GX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\r\n//    GX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\r\n//\t// Send coordinates.\r\n//    GXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//        GXPosition3f32(x0, y0, -1.0f);\r\n//\t\tGXTexCoord2f32((float)sx/(float)pTexture->m_width, (float)sy/(float)pTexture->m_height);\r\n//        GXPosition3f32(x1, y0, -1.0f);\r\n//\t\tGXTexCoord2f32(((float)sx+(float)sw)/(float)pTexture->m_width, (float)sy/(float)pTexture->m_height);\r\n//        GXPosition3f32(x1, y1, -1.0f);\r\n//\t\tGXTexCoord2f32(((float)sx+(float)sw)/(float)pTexture->m_width, ((float)sy+(float)sh)/(float)pTexture->m_height);\r\n//        GXPosition3f32(x0, y1, -1.0f);\r\n//\t\tGXTexCoord2f32((float)sx/(float)pTexture->m_width, ((float)sy+(float)sh)/(float)pTexture->m_height);\r\n//    GXEnd();\r\n//}\r\n//\r\n//void NsPrim::subsprite ( NsTexture * pTexture, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1 )\r\n//{\r\n//\tassert ( inDrawingContext );\r\n//\r\n//\tpTexture->upload( NsTexture_Wrap_Clamp );\r\n//\r\n//    // Set current vertex descriptor to enable position and color0.\r\n//    // Both use 8b index to access their data arrays.\r\n//    GXClearVtxDesc();\r\n//    GXSetVtxDesc( GX_VA_POS, GX_DIRECT );\r\n//    GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );\r\n//\r\n//    // Set material color.\r\n//    GX::SetChanMatColor( GX_COLOR0A0, (GXColor){128,128,128,128} );\r\n//    GX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\r\n//    GX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\r\n//\t// Send coordinates.\r\n//    GXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//        GXPosition3f32(x0, y0, -1.0f);\r\n//\t\tGXTexCoord2f32(u0, v0);\r\n//        GXPosition3f32(x1, y0, -1.0f);\r\n//\t\tGXTexCoord2f32(u1, v0);\r\n//        GXPosition3f32(x1, y1, -1.0f);\r\n//\t\tGXTexCoord2f32(u1, v1);\r\n//        GXPosition3f32(x0, y1, -1.0f);\r\n//\t\tGXTexCoord2f32(u0, v1);\r\n//    GXEnd();\r\n//}\r\n//\r\n//void NsPrim::subsprite ( NsTexture * pTexture, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3, float z, GXColor color )\r\n//{\r\n//\tassert ( inDrawingContext );\r\n//\r\n//\tpTexture->upload( NsTexture_Wrap_Clamp );\r\n//\r\n//    // Set current vertex descriptor to enable position and color0.\r\n//    // Both use 8b index to access their data arrays.\r\n//    GXClearVtxDesc();\r\n//    GXSetVtxDesc( GX_VA_POS, GX_DIRECT );\r\n//    GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );\r\n//\r\n//    // Set material color.\r\n//    GX::SetChanMatColor( GX_COLOR0A0, color );\r\n//    GX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255} );\r\n//\r\n//    GX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n//\r\n//\t// Send coordinates.\r\n//    GXBegin( GX_QUADS, GX_VTXFMT0, 4 ); \r\n//        GXPosition3f32(x0, y0, z);\r\n//\t\tGXTexCoord2f32(u0, v0);\r\n//        GXPosition3f32(x1, y1, z);\r\n//\t\tGXTexCoord2f32(u1, v1);\r\n//        GXPosition3f32(x2, y2, z);\r\n//\t\tGXTexCoord2f32(u2, v2);\r\n//        GXPosition3f32(x3, y3, z);\r\n//\t\tGXTexCoord2f32(u3, v3);\r\n//    GXEnd();\r\n//}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tend\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tCloses the drawing context. This must be called after you are\t*\r\n *\t\t\t\tfinished building primitives. Restores the viewport which was\t*\r\n *\t\t\t\tcurrent at the time of the call to begin().\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsPrim::end ( void )\r\n{\r\n//\tassert ( inDrawingContext );\r\n\r\n\tinDrawingContext = 0;\r\n}\r\n\r\nint NsPrim::begun ( void )\r\n{\r\n\treturn inDrawingContext;\r\n}\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_prim.h",
    "content": "#ifndef _PRIM_H_\r\n#define _PRIM_H_\r\n\r\n#include <dolphin.h>\r\n\r\nnamespace NsPrim\r\n{\r\n\tvoid begin ( void );\r\n\r\n\tvoid point ( float x, float y, float z, GXColor color );\r\n\tvoid point ( float x, float y, GXColor color );\r\n\r\n\tvoid line ( float x0, float y0, float x1, float y1, GXColor color );\r\n\tvoid line ( float x0, float y0, float x1, float y1, GXColor color0, GXColor color1 );\r\n\tvoid line ( float x0, float y0, float z0, float x1, float y1, float z1, GXColor color );\r\n\tvoid line ( float x0, float y0, float z0, float x1, float y1, float z1, GXColor color0, GXColor color1 );\r\n\r\n\tvoid tri ( float x0, float y0, float x1, float y1, float x2, float y2, GXColor color );\r\n\tvoid tri ( float x0, float y0, float x1, float y1, float x2, float y2, GXColor color0, GXColor color1, GXColor color2 );\r\n\tvoid tri ( float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2, GXColor color );\r\n\tvoid tri ( float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2, GXColor color0, GXColor color1, GXColor color2 );\r\n\r\n\tvoid quad ( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, GXColor color );\r\n\tvoid quad ( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, GXColor color0, GXColor color1, GXColor color2, GXColor color3 );\r\n\tvoid quad ( float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, GXColor color );\r\n\tvoid quad ( float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, GXColor color0, GXColor color1, GXColor color2, GXColor color3 );\r\n\r\n\tvoid frame ( float left, float top, float right, float bottom, GXColor color );\r\n\tvoid box ( float left, float top, float right, float bottom, GXColor color );\r\n\r\n//\tvoid sprite ( const char * pName, float x, float y );\r\n//\tvoid sprite ( const char * pName, float x0, float y0, float x1, float y1 );\r\n//\tvoid sprite ( const char * pName, float x0, float y0, float z0, float x1, float y1, float z1 );\r\n\r\n//\tvoid sprite ( NsTexture * pTexture, float x, float y );\r\n//\tvoid sprite ( NsTexture * pTexture, float x, float y, float z );\r\n//\tvoid sprite ( NsTexture * pTexture, float x0, float y0, float x1, float y1 );\r\n//\tvoid sprite ( NsTexture * pTexture, float x0, float y0, float z0, float x1, float y1, float z1 );\r\n//\r\n//\tvoid subsprite ( NsTexture * pTexture, float x, float y, short sx, short sy, short sw, short sh );\r\n//\tvoid subsprite ( NsTexture * pTexture, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1 );\r\n//\tvoid subsprite ( NsTexture * pTexture, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3, float z, GXColor color );\r\n\r\n\tvoid end ( void );\r\n\r\n\tint\t begun ( void );\r\n};\r\n\r\n#endif\t\t// _PRIM_H_\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_profile.cpp",
    "content": "/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsProfile\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tCode used to profile how much time something takes.\t\t\t\t*\r\n *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#include <math.h>\r\n#include \"p_profile.h\"\r\n#include \"p_assert.h\"\r\n\r\n/********************************************************************************\r\n * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nstatic float\tlast_x0, last_y0, last_x1, last_y1;\r\nstatic float\tlast_bar[256];\r\n\r\n\r\n/********************************************************************************\r\n * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsProfile\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tInitializes a profile object.\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nNsProfile::NsProfile ( char * pName )\r\n{\r\n\tOSInitStopwatch ( &m_watch, pName );\r\n\tm_accumulated = 0;\r\n\tm_pHistoryBuffer = NULL;\r\n}\r\n\r\nNsProfile::NsProfile()\r\n{\r\n\tNsProfile ( \"<no name given>\" );\r\n}\r\n\r\nNsProfile::NsProfile ( char * pName, unsigned int historySize )\r\n{\r\n\tunsigned int lp;\r\n\r\n\tOSInitStopwatch ( &m_watch, pName );\r\n\tm_accumulated = 0;\r\n\r\n\tm_pHistoryBuffer = new float[historySize];\r\n\tfor ( lp = 0; lp < historySize; lp++ ) {\r\n\t\tm_pHistoryBuffer[lp] = 0.0f;\r\n\t}\r\n\tm_historyBufferSize = historySize;\r\n\tm_historyEntry = 0;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tstart\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tStart recording how much time something takes.\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsProfile::start ( void )\r\n{\r\n\tOSStartStopwatch ( &m_watch );\r\n\tm_latch = m_watch.total;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tstop\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tStop recording how much time something takes.\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsProfile::stop ( void )\r\n{\r\n\tOSStopStopwatch ( &m_watch );\r\n\tm_accumulated += m_watch.total - m_latch;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tdraw\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tDraw a bar representing how much time something takes.\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsProfile::draw ( float x0, float y0, float x1, float y1, GXColor color )\r\n{\r\n\tfloat\tms;\r\n\tfloat\tbar;\r\n\r\n\tms = (float)OSTicksToMilliseconds( ((float)m_accumulated) );   \r\n\r\n\tbar = ms * ( x1 - x0 ) / ( 1000.0f / 60.0f );\r\n\r\n\tNsPrim::box ( x0-1.0f, y0-1.0f, x1 + 1.0f, y1 + 1.0f, (GXColor){255,255,255,128} );\r\n\tNsPrim::box ( x0, y0, x1, y1, (GXColor){0,0,0,128} );\r\n\tNsPrim::box ( x0, y0, x0 + bar, y1, color );\r\n\r\n\t// Reset the stopwatch.\r\n\tm_accumulated = 0;\r\n}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\thistogram\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tDraw a histogram chart representing how much time something\t\t*\r\n *\t\t\t\ttakes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid NsProfile::histogram ( float x0, float y0, float x1, float y1, GXColor color )\r\n{\r\n\tfloat\t\t\tms;\r\n\tfloat\t\t\tbar;\r\n\tfloat\t\t\txpos;\r\n\tunsigned int\tlp;\r\n\tint\t\t\t\the;\r\n\r\n\t// Quick reject test.\r\n\tassertf ( m_pHistoryBuffer, ( \"No history buffer set up.\" ) );\r\n\r\n\t// Update history buffer.\r\n\tms = (float)OSTicksToMilliseconds( ((float)m_accumulated) );   \r\n//\tif ( ms > ( 1000.0f / 60.0f ) ) ms = ( 1000.0f / 60.0f );\r\n\tm_pHistoryBuffer[m_historyEntry] = ms;\r\n\tm_historyEntry++;\r\n\tm_historyEntry %= m_historyBufferSize;\r\n\r\n\t// Draw background.\r\n\tNsPrim::box ( x0-1.0f, y0-1.0f, x1 + 1.0f, y1 + 1.0f, (GXColor){255,255,255,128} );\r\n\tNsPrim::box ( x0, y0, x1, y1, (GXColor){0,0,0,128} );\r\n\r\n\t// Draw bars.\r\n\the = m_historyEntry;\r\n\tfor ( lp = 0; lp < m_historyBufferSize; lp++ ) {\r\n\t\tms = m_pHistoryBuffer[he];\r\n\t\tbar = ms * ( y1 - y0 ) / ( 1000.0f / 60.0f );\r\n\t\tlast_bar[lp] = bar;\r\n\t\txpos = x0 + ( ( (float)lp * ( x1 - x0 ) ) / (float)m_historyBufferSize );\r\n\t\tNsPrim::line ( xpos, y1, xpos, y1 - bar, color );\r\n\t\the++;\r\n\t\the %= m_historyBufferSize;\r\n\t}\r\n\r\n\t// Reset the stopwatch.\r\n\tm_accumulated = 0;\r\n\r\n\t// Save for appends.\r\n\tlast_x0 = x0;\r\n\tlast_x1 = x1;\r\n\tlast_y0 = y0;\r\n\tlast_y1 = y1;\r\n}\r\n\r\nvoid NsProfile::append ( GXColor color, bool update )\r\n{\r\n\tfloat\t\t\tms;\r\n\tfloat\t\t\tbar;\r\n\tfloat\t\t\txpos;\r\n\tunsigned int\tlp;\r\n\tint\t\t\t\the;\r\n\tfloat\t\t\tx0 = last_x0;\r\n\tfloat\t\t\tx1 = last_x1;\r\n\tfloat\t\t\ty0 = last_y0;\r\n\tfloat\t\t\ty1 = last_y1;\r\n\r\n\t// Quick reject test.\r\n\tassertf ( m_pHistoryBuffer, ( \"No history buffer set up.\" ) );\r\n\r\n\t// Update history buffer.\r\n\tms = (float)OSTicksToMilliseconds( ((float)m_accumulated) );   \r\n//\tif ( ms > ( 1000.0f / 60.0f ) ) ms = ( 1000.0f / 60.0f );\r\n\tm_pHistoryBuffer[m_historyEntry] = ms;\r\n\tm_historyEntry++;\r\n\tm_historyEntry %= m_historyBufferSize;\r\n\r\n\t// Draw bars.\r\n\the = m_historyEntry;\r\n\tfor ( lp = 0; lp < m_historyBufferSize; lp++ ) {\r\n\t\tms = m_pHistoryBuffer[he];\r\n\t\tbar = ms * ( y1 - y0 ) / ( 1000.0f / 60.0f );\r\n\t\txpos = x0 + ( ( (float)lp * ( x1 - x0 ) ) / (float)m_historyBufferSize );\r\n\t\tNsPrim::line ( xpos, y1 - ( bar + last_bar[lp] ), xpos, y1 - last_bar[lp], color );\r\n\t\the++;\r\n\t\the %= m_historyBufferSize;\r\n\t\tif ( update  ) last_bar[lp] += bar;\r\n\t}\r\n\r\n\t// Reset the stopwatch.\r\n\tm_accumulated = 0;\r\n}\r\n\r\n\r\n\r\n\r\n//`\tfloat\ttime;\r\n//static OSStopwatch  SwMsec;         // stopwatch for single frame render time\r\n//static volatile f32 MSecGX  = 0.0f; // volatile since it is during drawdone callback\r\n//    OSInitStopwatch( &SwMsec, \"render\" );    // time to render single frame\r\n//        OSStartStopwatch( &SwMsec ); // SwMsec measure single frame render time for CPU and GP;\r\n//\t    swTime  = OSCheckStopwatch( &SwMsec );\r\n//\t    MSecCPU2 = (f32)OSTicksToMilliseconds( ((f32)swTime) );\r\n//        OSStopStopwatch(  &SwMsec ); // reset SwMsec for next frame\r\n//        OSResetStopwatch( &SwMsec );\r\n//    OSTime        swTime;             // current stopwatch time in 'OSTime' format. \r\n//\t    swTime  = OSCheckStopwatch( &SwMsec );\r\n//\t    MSecCPU = (f32)OSTicksToMilliseconds( ((f32)swTime) );   \r\n//typedef struct OSStopwatch\r\n//{\r\n//    char*       name;       // name of this stopwatch\r\n//    OSTime      total;      // total time running\r\n//    u32         hits;       // number of times turned on and off\r\n//    OSTime      min;        // smallest time measured\r\n//    OSTime      max;        // longest time measured\r\n//\r\n//    OSTime      last;       // time at which this sw was last started\r\n//    BOOL        running;    // TRUE if sw is running\r\n//} OSStopwatch;\r\n//\r\n//\r\n//void    OSInitStopwatch     ( OSStopwatch* sw, char* name );\r\n//void    OSStartStopwatch    ( OSStopwatch* sw );\r\n//void    OSStopStopwatch     ( OSStopwatch* sw );\r\n//OSTime  OSCheckStopwatch    ( OSStopwatch* sw );\r\n//void    OSResetStopwatch    ( OSStopwatch* sw );\r\n//void    OSDumpStopwatch     ( OSStopwatch* sw );\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_profile.h",
    "content": "#ifndef _PROFILE_H_\r\n#define _PROFILE_H_\r\n\r\n#include <dolphin.h>\r\n#include \"p_prim.h\"\r\n\r\nclass NsProfile\r\n{\r\n\tOSStopwatch\t\tm_watch;\r\n\tOSTime\t\t\tm_latch;\r\n\tOSTime\t\t\tm_accumulated;\r\n\tfloat\t\t  *\tm_pHistoryBuffer;\r\n\tunsigned int\tm_historyBufferSize;\r\n\tunsigned int\tm_historyEntry;\r\npublic:\r\n\t\t\tNsProfile\t();\r\n\t\t\tNsProfile\t( char * pName );\r\n\t\t\tNsProfile\t( char * pName, unsigned int historySize );\r\n\r\n\tvoid\tstart\t\t( void );\r\n\tvoid\tstop\t\t( void );\r\n\tvoid\tdraw\t\t( float x0, float y0, float x1, float y1, GXColor color );\r\n\tvoid\thistogram\t( float x0, float y0, float x1, float y1, GXColor color );\r\n\tvoid\tappend\t\t( GXColor color, bool update );\r\n};\r\n\r\n#endif\t\t// _PROFILE_H_\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_quat.cpp",
    "content": "//#include <math.h>\r\n//#include \"p_quat.h\"\r\n//\r\n//NsQuat::NsQuat()\r\n//{\r\n//\tm_quat.x = 0;\r\n//\tm_quat.y = 0;\r\n//\tm_quat.z = 0;\r\n//\tm_quat.w = 0;\r\n//}\r\n//\r\n////***************************************************************************\r\n////* Slerp 2 quaternions 0.0 = all of quat0, 1.0 = all of quat1.\r\n////***************************************************************************\r\n//\r\n//#define _EPSILON          ((float)(0.001))\r\n//#define _TOL_COS_ZERO     (((float)1) - _EPSILON)\r\n//\r\n//#define RwV3dDotProduct(a, b)                              \\\r\n//    ((((( (((a).m_quat.x) * ((b).m_quat.x))) +                              \\\r\n//        ( (((a).m_quat.y) * ((b).m_quat.y))))) +                            \\\r\n//        ( (((a).m_quat.z) * ((b).m_quat.z)))))\r\n//\r\n//void NsQuat::slerp ( NsQuat& pQ0, NsQuat& pQ1, float time )\r\n//{\r\n//\t// Compute dot product (equal to cosine of the angle between quaternions).\r\n//\tfloat              fCosTheta = (RwV3dDotProduct(pQ0, pQ1) + pQ0.m_quat.w * pQ1.m_quat.w);\r\n//\tfloat              fAlphaQ = (float)time;\r\n//    float              fBeta;\r\n//    unsigned int       bObtuseTheta;\r\n//    unsigned int       bNearlyZeroTheta;\r\n//\r\n//\t// Check angle to see if quaternions are in opposite hemispheres.\r\n//    bObtuseTheta = (fCosTheta < ((float)0.0f ));\r\n//\r\n//    if (bObtuseTheta)\r\n//    {\r\n//        // If so, flip one of the quaterions.\r\n//\t\tfCosTheta = ( fCosTheta < ((float) - 1.0f )) ? ((float)1.0f ) : -fCosTheta;\r\n//\r\n//\t\tpQ1.m_quat.x\t= -pQ1.m_quat.x;\r\n//\t\tpQ1.m_quat.y\t= -pQ1.m_quat.y;\r\n//\t\tpQ1.m_quat.z\t= -pQ1.m_quat.z;\r\n//\t\tpQ1.m_quat.w\t= -pQ1.m_quat.w;\r\n//    }\r\n//    else\r\n//    {\r\n//\t\tfCosTheta = ( fCosTheta > ((float) 1.0f )) ? ((float)1.0f ) : fCosTheta;\r\n//    }\r\n//\r\n//\t// Set factors to do linear interpolation, as a special case where the\r\n//\t// quaternions are close together.\r\n//\tfBeta = ((float)1.0f ) - fAlphaQ;\r\n//\r\n//\t// If the quaternions aren't close, proceed with spherical interpolation.\r\n//    bNearlyZeroTheta = ( fCosTheta >= _TOL_COS_ZERO );\r\n//\r\n//    if ( !bNearlyZeroTheta )\r\n//    {\r\n//        const float fTheta\t\t\t= acosf( fCosTheta );\r\n//\t\tconst float fCosecTheta\t= 1.0f / sinf( fTheta );\r\n//        fBeta\t\t\t\t\t\t= (float)( sinf( fTheta * fBeta ) * fCosecTheta );\r\n//        fAlphaQ\t\t\t\t\t\t= (float)( sinf( fTheta * fAlphaQ ) * fCosecTheta );\r\n//    }\r\n//\r\n//\t// Do the interpolation.\r\n//\tm_quat.x\t= fBeta * pQ0.m_quat.x + fAlphaQ * pQ1.m_quat.x;\r\n//\tm_quat.y\t= fBeta * pQ0.m_quat.y + fAlphaQ * pQ1.m_quat.y;\r\n//\tm_quat.z\t= fBeta * pQ0.m_quat.z + fAlphaQ * pQ1.m_quat.z;\r\n//\tm_quat.w\t= fBeta * pQ0.m_quat.w + fAlphaQ * pQ1.m_quat.w;\r\n//}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_quat.h",
    "content": "//#ifndef _QUAT_H_\r\n//#define _QUAT_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//\r\n//class NsQuat\r\n//{\r\n//\tQuaternion m_quat;\r\n//public:\r\n//\tfriend class NsMatrix;\r\n//\r\n//\t\t\tNsQuat\t();\r\n//\r\n//\tvoid\tslerp\t( NsQuat& pQ0, NsQuat& pQ1, float time );\r\n//\r\n//\tfloat\tgetX\t( void ) { return m_quat.x; };\r\n//\tfloat\tgetY\t( void ) { return m_quat.y; };\r\n//\tfloat\tgetZ\t( void ) { return m_quat.z; };\r\n//\tfloat\tgetW\t( void ) { return m_quat.w; };\r\n//\r\n//\tvoid\tsetX\t( float x ) { m_quat.x = x; };\r\n//\tvoid\tsetY\t( float y ) { m_quat.y = y; };\r\n//\tvoid\tsetZ\t( float z ) { m_quat.z = z; };\r\n//\tvoid\tsetW\t( float w ) { m_quat.w = w; };\r\n//};\r\n//\r\n//#endif\t\t// _QUAT_H_\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_reftypes.h",
    "content": "#ifndef _REFTYPES_H_\r\n#define _REFTYPES_H_\r\n\r\n#include <dolphin.h>\r\n\r\n////////////////////////////////////////////////////////////\r\n\r\nclass NsRefDoubleData\r\n{\r\n\tint\t\t\t\tm_refCount;\r\npublic:\r\n\tunsigned int  * m_pDoubleData;\r\n\r\n\t\t\t\t\tNsRefDoubleData\t\t( unsigned int * p ) { m_refCount = 0; m_pDoubleData = p; }\r\n\t\t\t\t\t~NsRefDoubleData\t() { if ( m_pDoubleData ) delete m_pDoubleData; }\r\n\r\n\tvoid\t\t\taddReference\t\t( void ) { m_refCount++; }\r\n\tvoid\t\t\tremoveReference\t\t( void ) { m_refCount--; }\r\n\tint\t\t\t\ttotalReferences\t\t( void ) { return m_refCount; }\r\n};\r\n\r\n////////////////////////////////////////////////////////////\r\n\r\nclass NsRefAccData\r\n{\r\n\tint\t\t\t\tm_refCount;\r\npublic:\r\n\tunsigned int  * m_pAccData;\r\n\r\n\t\t\t\t\tNsRefAccData\t( unsigned int * p ) { m_refCount = 0; m_pAccData = p; }\r\n\t\t\t\t\t~NsRefAccData\t() { if ( m_pAccData ) delete m_pAccData; }\r\n\r\n\tvoid\t\t\taddReference\t( void ) { m_refCount++; }\r\n\tvoid\t\t\tremoveReference\t( void ) { m_refCount--; }\r\n\tint\t\t\t\ttotalReferences\t( void ) { return m_refCount; }\r\n};\r\n\r\n////////////////////////////////////////////////////////////\r\n\r\nclass NsRefTransformedVertices\r\n{\r\n\tint\t\t\t\t\t\tm_refCount;\r\npublic:\r\n\tNsAnim_PosNormPair\t  * m_pTransformedVertices;\r\n\r\n\t\t\t\t\t\t\tNsRefTransformedVertices\t( NsAnim_PosNormPair * p ) { m_refCount = 0; m_pTransformedVertices = p; }\r\n\t\t\t\t\t\t\t~NsRefTransformedVertices\t() { if ( m_pTransformedVertices ) delete m_pTransformedVertices; }\r\n\r\n\tvoid\t\t\t\t\taddReference\t\t\t\t( void ) { m_refCount++; }\r\n\tvoid\t\t\t\t\tremoveReference\t\t\t\t( void ) { m_refCount--; }\r\n\tint\t\t\t\t\t\ttotalReferences\t\t\t\t( void ) { return m_refCount; }\r\n};\r\n\r\n////////////////////////////////////////////////////////////\r\n\r\nclass NsRefSkinBox\r\n{\r\n\tint\t\t\t\tm_refCount;\r\npublic:\r\n\tNsBBox\t\t  * m_pSkinBox;\r\n\r\n\t\t\t\t\tNsRefSkinBox\t( NsBBox * p ) { m_refCount = 0; m_pSkinBox = p; }\r\n\t\t\t\t\t~NsRefSkinBox\t() { if ( m_pSkinBox ) delete m_pSkinBox; }\r\n\r\n\tvoid\t\t\taddReference\t( void ) { m_refCount++; }\r\n\tvoid\t\t\tremoveReference\t( void ) { m_refCount--; }\r\n\tint\t\t\t\ttotalReferences\t( void ) { return m_refCount; }\r\n};\r\n\r\n////////////////////////////////////////////////////////////\r\n\r\nclass NsRefCAS16\r\n{\r\n\tint\t\t\t\t\tm_refCount;\r\npublic:\r\n\tunsigned short\t  * m_pCAS16;\r\n\r\n\t\t\t\t\t\tNsRefCAS16\t\t( unsigned short * p ) { m_refCount = 0; m_pCAS16 = p; }\r\n\t\t\t\t\t\t~NsRefCAS16\t\t() { if ( m_pCAS16 ) delete m_pCAS16; }\r\n\r\n\tvoid\t\t\t\taddReference\t( void ) { m_refCount++; }\r\n\tvoid\t\t\t\tremoveReference\t( void ) { m_refCount--; }\r\n\tint\t\t\t\t\ttotalReferences\t( void ) { return m_refCount; }\r\n};\r\n\r\n////////////////////////////////////////////////////////////\r\n\r\nclass NsRefFlipPairs\r\n{\r\n\tint\t\t\t\tm_refCount;\r\npublic:\r\n\tunsigned int  * m_pFlipPairs;\r\n\r\n\t\t\t\t\tNsRefFlipPairs\t( unsigned int * p ) { m_refCount = 0; m_pFlipPairs = p; }\r\n\t\t\t\t\t~NsRefFlipPairs\t\t() { if ( m_pFlipPairs ) delete m_pFlipPairs; }\r\n\r\n\tvoid\t\t\taddReference\t( void ) { m_refCount++; }\r\n\tvoid\t\t\tremoveReference\t( void ) { m_refCount--; }\r\n\tint\t\t\t\ttotalReferences\t( void ) { return m_refCount; }\r\n};\r\n\r\n////////////////////////////////////////////////////////////\r\n\r\nclass NsRefCAS32\r\n{\r\n\tint\t\t\t\tm_refCount;\r\npublic:\r\n\tunsigned int  * m_pCAS32;\r\n\r\n\t\t\t\t\tNsRefCAS32\t\t( unsigned int * p ) { m_refCount = 0; m_pCAS32 = p; }\r\n\t\t\t\t\t~NsRefCAS32\t\t() { if ( m_pCAS32 ) delete m_pCAS32; }\r\n\r\n\tvoid\t\t\taddReference\t( void ) { m_refCount++; }\r\n\tvoid\t\t\tremoveReference\t( void ) { m_refCount--; }\r\n\tint\t\t\t\ttotalReferences\t( void ) { return m_refCount; }\r\n};\r\n\r\n////////////////////////////////////////////////////////////\r\n\r\nclass NsRefPartChecksums\r\n{\r\n\tint\t\t\t\tm_refCount;\r\npublic:\r\n\tunsigned int  * m_pPartChecksums;\r\n\r\n\t\t\t\t\tNsRefPartChecksums\t( unsigned int * p ) { m_refCount = 0; m_pPartChecksums = p; }\r\n\t\t\t\t\t~NsRefPartChecksums\t() { if ( m_pPartChecksums ) delete m_pPartChecksums; }\r\n\r\n\tvoid\t\t\taddReference\t\t( void ) { m_refCount++; }\r\n\tvoid\t\t\tremoveReference\t\t( void ) { m_refCount--; }\r\n\tint\t\t\t\ttotalReferences\t\t( void ) { return m_refCount; }\r\n};\r\n\r\n////////////////////////////////////////////////////////////\r\n\r\nclass NsRefBoneData\r\n{\r\n\tint\t\t\t\t\tm_refCount;\r\npublic:\r\n\tNsAnim_BoneData\t  * m_pBoneData;\r\n\r\n\t\t\t\t\t\tNsRefBoneData\t( NsAnim_BoneData * p ) { m_refCount = 0; m_pBoneData = p; }\r\n\t\t\t\t\t\t~NsRefBoneData\t() { if ( m_pBoneData ) delete m_pBoneData; }\r\n\r\n\tvoid\t\t\t\taddReference\t( void ) { m_refCount++; }\r\n\tvoid\t\t\t\tremoveReference\t( void ) { m_refCount--; }\r\n\tint\t\t\t\t\ttotalReferences\t( void ) { return m_refCount; }\r\n};\r\n\r\n////////////////////////////////////////////////////////////\r\n\r\nclass NsRefBranchNodes\r\n{\r\n\tint\t\t\t\tm_refCount;\r\npublic:\r\n\tNsBranch\t  * m_pBranchNodes;\r\n\r\n\t\t\t\t\tNsRefBranchNodes\t( NsBranch * p ) { m_refCount = 0; m_pBranchNodes = p; }\r\n\t\t\t\t\t~NsRefBranchNodes\t() { if ( m_pBranchNodes ) delete m_pBranchNodes; }\r\n\r\n\tvoid\t\t\taddReference\t\t( void ) { m_refCount++; }\r\n\tvoid\t\t\tremoveReference\t\t( void ) { m_refCount--; }\r\n\tint\t\t\t\ttotalReferences\t\t( void ) { return m_refCount; }\r\n};\r\n\r\n////////////////////////////////////////////////////////////\r\n\r\nclass NsRefLeafNodes\r\n{\r\n\tint\t\t\t\tm_refCount;\r\npublic:\r\n\tNsLeaf\t\t  * m_pLeafNodes;\r\n\r\n\t\t\t\t\tNsRefLeafNodes\t( NsLeaf * p ) { m_refCount = 0; m_pLeafNodes = p; }\r\n\t\t\t\t\t~NsRefLeafNodes\t() { if ( m_pLeafNodes ) delete m_pLeafNodes; }\r\n\r\n\tvoid\t\t\taddReference\t\t( void ) { m_refCount++; }\r\n\tvoid\t\t\tremoveReference\t\t( void ) { m_refCount--; }\r\n\tint\t\t\t\ttotalReferences\t\t( void ) { return m_refCount; }\r\n};\r\n\r\n////////////////////////////////////////////////////////////\r\n\r\nclass NsRefTriangleMap\r\n{\r\n\tint\t\t\t\tm_refCount;\r\npublic:\r\n\tunsigned int  * m_pTriangleMap;\r\n\r\n\t\t\t\t\tNsRefTriangleMap\t( unsigned int * p ) { m_refCount = 0; m_pTriangleMap = p; }\r\n\t\t\t\t\t~NsRefTriangleMap\t() { if ( m_pTriangleMap ) delete m_pTriangleMap; }\r\n\r\n\tvoid\t\t\taddReference\t\t( void ) { m_refCount++; }\r\n\tvoid\t\t\tremoveReference\t\t( void ) { m_refCount--; }\r\n\tint\t\t\t\ttotalReferences\t\t( void ) { return m_refCount; }\r\n};\r\n\r\n////////////////////////////////////////////////////////////\r\n\r\n#endif\t\t// _REFTYPES_H_\r\n\r\n/*\r\nNsRefDouble\r\nNsRefAcc\r\nNsRefPair\r\nNsRefSkinBox\r\nNsRefCAS16\r\nNsRefCAS32\r\nNsRefFlipPairs\r\nNsRefPartChecksums\r\nNsRefBoneData\r\nNsRefTexMan\r\n*/"
  },
  {
    "path": "Code/Sys/ngc/p_render.cpp",
    "content": "/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tRender\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tAllows a rendering context to be opened and modified as desired\t*\r\n *\t\t\t\tby the user. A rendering context must be open before Prim or\t*\r\n *\t\t\t\tModel commands can be issued.\t\t\t\t\t\t\t\t\t*\r\n *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#include <math.h>\r\n#include \"p_render.h\"\r\n#include \"p_assert.h\"\r\n#include \"p_gx.h\"\r\n\r\n/********************************************************************************\r\n * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n//static int tx = -1;\r\n//static int bm = -1;\r\n//static int km = -1;\r\n//static int ai = -1;\r\n//static int ci = -1;\r\n\r\nstatic int\t\tinRenderingContext\t= 0;\r\n//static bool\t\tfogEnabled\t\t\t= false;\r\n//static GXColor\tfogColor\t\t\t= (GXColor){ 0, 0, 0, 0 };\r\n//static float\tfogNear\t\t\t\t= 0.0f;\r\n//static float\tfogFar\t\t\t\t= 0.0f;\r\n//static NsZMode\tzMode;\r\n//static int\t\tzCompare;\r\n//static int\t\tzUpdate;\r\n//static int\t\tzRejectBeforeTexture;\r\n\r\n//u16 colorMap[(4*4)*2] __attribute__ (( aligned( 32 ))) =\r\n//{\r\n//\t0x0000, 0x0055, 0x00aa, 0x00ff, \r\n//\t0x0000, 0x0055, 0x00aa, 0x00ff, \r\n//\t0x0000, 0x0055, 0x00aa, 0x00ff, \r\n//\t0x0000, 0x0055, 0x00aa, 0x00ff, \r\n//\t0x0000, 0x0000, 0x0000, 0x0000, \r\n//\t0x5500, 0x5500, 0x5500, 0x5500, \r\n//\t0xaa00, 0xaa00, 0xaa00, 0xaa00, \r\n//\t0xff00, 0xff00, 0xff00, 0xff00  \r\n//};\r\n\r\n//u16 colorMap[(256*256)*2] __attribute__ (( aligned( 32 )));\r\n//\r\n//static bool colorMapMade = false;\r\n//\r\n//static void makeColorMap( void )\r\n//{\r\n//\tfor ( int y = 0; y < 256; y++ )\r\n//\t{\r\n//\t\tfor ( int x = 0; x < 256; x++ )\r\n//\t\t{\r\n//\t\t\tint r;\r\n//\t\t\tint g;\r\n//\r\n//\t\t\tr = 0;\r\n//\t\t\tr += ( x / 4 ) * 32;\r\n//\t\t\tr += ( x & 3 );\r\n//\t\t\tr += ( ( y / 4 ) * ( 256 * 4 * 2 ) );\r\n//\t\t\tr += ( ( y & 3 ) * 4 );\r\n//\r\n//\t\t\tg = 16;\r\n//\t\t\tg += ( x / 4 ) * 32;\r\n//\t\t\tg += ( x & 3 );\r\n//\t\t\tg += ( ( y / 4 ) * ( 256 * 4 * 2 ) );\r\n//\t\t\tg += ( ( y & 3 ) * 4 );\r\n//\r\n//\t\t\t// Red across.\r\n//\t\t\tcolorMap[r] = x;\r\n//\t\t\t// Green down.\r\n//\t\t\tcolorMap[g] = ( y << 8 );\r\n//\t\t}\r\n//\t}\r\n//}\r\n\r\n\r\n/********************************************************************************\r\n * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nnamespace NsRender\r\n{\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tRender\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tGenerates a rendering context.\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n//Render::Render()\r\n//{\r\n//\tinRenderingContext = 0;\r\n//\r\n//\ttx = -1;\r\n//\tbm = -1;\r\n//\tkm = -1;\r\n//\tai = -1;\r\n//\tci = -1;\r\n//}\r\n\r\n/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tbegin\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tOpens the drawing context. This must be called before any\t\t*\r\n *\t\t\t\tprimitives can be built. Sets up an orthogonal viewport.\t\t*\r\n *\t\t\t\tThe viewport is set to 0.0f,0.0f at the top-left corner, and\t*\r\n *\t\t\t\t640.0f,480.0f at the bottom-right corner.\t\t\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\nvoid begin ( void )\r\n{\r\n//\tif ( !colorMapMade )\r\n//\t{\r\n//\t\tmakeColorMap();\r\n//\t\tcolorMapMade = true;\r\n//\t}\r\n\r\n\tGX::begin();\r\n\r\n//\tMtx44\tmProj;\t\t\t\t\t\t\t\t// projection matrix:\r\n//    Mtx\t\tmID;\t\t\t\t\t\t\t\t// transformation matrix (set to identity)\r\n\r\n//\tassert ( !inRenderingContext );\r\n\tif ( inRenderingContext ) return;\r\n\r\n    // disable lighting - use register color only\r\n\tGX::SetTexChanTevIndCull( 0, 2, 1, 0, GX_CULL_NONE );\r\n\tGX::SetClipMode(GX_CLIP_ENABLE);\r\n\tGX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\tGX::SetChanCtrl( GX_COLOR1A1, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );\r\n\r\n    GX::SetTevSwapModeTable( GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA );\r\n    GX::SetTevSwapModeTable( GX_TEV_SWAP1, GX_CH_BLUE, GX_CH_BLUE, GX_CH_RED, GX_CH_GREEN );\r\n    GX::SetTevSwapModeTable( GX_TEV_SWAP2, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE );\r\n    GX::SetTevSwapModeTable( GX_TEV_SWAP3, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_RED );\r\n    \r\n//\tGX::SetTevSwapModeTable( GX_TEV_SWAP2, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_BLUE );\r\n//\tGX::SetTevSwapModeTable( GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_RED, GX_CH_GREEN );\r\n\r\n//\t// Make sure color texture is uploaded.\r\n//\tGXTexObj\ttexObj;\r\n////\tGXInitTexObj( &texObj, colorMap, 4, 4, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE );\r\n//\tGXInitTexObj( &texObj, colorMap, 256, 256, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE );\r\n//\tGXLoadTexObj( &texObj, GX_TEXMAP7 );\r\n}\r\n\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tsetBlendMode\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tblendMode\tThe blend mode to set.\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tpTex\t\tThe texture to set up.\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tfixAlpha\tThe fixed alpha value to use for fixed alpha modes.\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tProvides a mechanism to set a variety of blend modes for flat\t*\r\n// *\t\t\t\tor textured primitives. State is maintained between blend\t\t*\r\n// *\t\t\t\tmodes, so the fewest amount of state changes are made.\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void setBlendMode ( NsBlendMode blendMode, /*NsTexture*/void * pTex, unsigned char fixAlpha )\r\n//{\r\n//\tint\t\t\t\ttexval;\r\n//\r\n////\ttx = -1;\r\n//// \tbm = -1;\r\n//// \tkm = -1;\r\n//// \tai = -1;\r\n//// \tci = -1;\r\n//\r\n//\t// PJR - Note: This should probably be in Tex::upload().\r\n//\tif ( pTex ) {\r\n//\t\tif ( tx != ( 1 | ( pTex->m_texID << 8 ) ) ) {\r\n//\t\t\tGXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, pTex->m_texID, GX_COLOR0A0);\r\n//\t\t\tGXSetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t    if ( (tx & 255) != 1 ) {\r\n//\t\t    \tGXSetNumTexGens( 1 );\r\n//\t\t\t\tGXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\t\tGXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\t\tGXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t\t\t}\r\n//\t\t\ttx = ( 1 | ( pTex->m_texID << 8 ) );\r\n//\t\t}\r\n//\t\ttexval = ( 1 << 8 );\r\n//\t} else {\r\n//\t\tif ( tx != 0 ) {\r\n//\t\t    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);\r\n//\t\t\tGXSetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );\r\n//\t\t    GXSetNumTexGens( 0 );\r\n//\t\t\tGXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );\r\n//\t\t\tGXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );\r\n//\t\t\ttx = 0;\r\n//\t\t}\r\n//\t\ttexval = ( 0 << 8 );\r\n//\t}\r\n//\t// Set Blend Mode.\r\n//\tswitch ( blendMode ) {\r\n//\t\tcase NsBlendMode_Sub:\t\t// Subtractive, using texture alpha\r\n//\t\tcase NsBlendMode_SubAlpha:\t\t// Subtractive, using constant alpha\r\n//\t\t\tif ( bm != 0 ) {\r\n//\t\t\t\tGXSetBlendMode ( GX_BM_SUBTRACT, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR );\r\n//\t\t\t\tbm = 0;\r\n//\t\t\t}\r\n//\t\t    break;\r\n//\t\tcase NsBlendMode_Blend:\t\t// Blend, using texture alpha\r\n//\t\tcase NsBlendMode_BlendAlpha:\t\t// Blend, using constant alpha\r\n//\t\t\tif ( bm != 1 ) {\r\n//\t\t\t\tGXSetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR );\r\n//\t\t\t\tbm = 1;\r\n//\t\t\t}\r\n//\t\t\tbreak;\r\n//\t\tcase NsBlendMode_AddAlpha:\t\t// Additive, using constant alpha\r\n//\t\t\tif ( bm != 2 ) {\r\n//\t\t\t\tGXSetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR );\r\n//\t\t\t\tbm = 2;\r\n//\t\t\t}\r\n//\t\t\tbreak;\r\n//\t\tcase NsBlendMode_AlphaTex:\t\t// Blend framebuffer color and texture alpha.\r\n//\t\t\tif ( bm != 3 ) {\r\n//\t\t\t\tGXSetBlendMode ( GX_BM_BLEND, GX_BL_ZERO, GX_BL_SRCALPHA, GX_LO_CLEAR );\r\n//\t\t\t\tbm = 3;\r\n//\t\t\t}\r\n//\t\t    break;\r\n//\t\tcase NsBlendMode_AlphaFB:\t\t// Blend framebuffer color and texture alpha, plus framebuffer color.\r\n//\t\t\tif ( bm != 4 ) {\t\t\r\n//\t\t\t\tGXSetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_SRCALPHA, GX_LO_CLEAR );\r\n//\t\t\t\tbm = 4;\r\n//\t\t\t}\r\n//\t\t    break;\r\n//\t\tcase NsBlendMode_Add:\t\t// Additive, using texture alpha\r\n//\t\t\tif ( bm != 5 ) {\r\n//\t\t\t\tGXSetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR );\r\n//\t\t\t\tbm = 5;\r\n//\t\t\t}\r\n//\t\t\tbreak;\r\n//\t\tcase NsBlendMode_None:\t\t// Do nothing. No cut-out, no blend.\r\n//\t\tdefault:\r\n//\t\t\tif ( bm != 6 ) {\r\n//\t\t\t\tGXSetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );\r\n//\t\t\t\tbm = 6;\r\n//\t\t\t}\r\n//\t\t\tbreak;\r\n//\t}\r\n//\t// Set Konstant.\r\n//\tswitch ( blendMode ) {\r\n//\t\tcase NsBlendMode_SubAlpha:\t\t// Subtractive, using constant alpha\r\n//\t\t\tif ( km != ( 0 | ( fixAlpha << 8 ) ) ) {\r\n//\t\t\t\tGXSetTevKColorSel( GX_TEVSTAGE0, GX_TEV_KCSEL_K0_A );\r\n//\t\t\t\tGXSetTevKColor( GX_KCOLOR0, (GXColor){128,128,128,fixAlpha} );\r\n//\t\t\t\tkm = 0 | ( fixAlpha << 8 );\r\n//\t\t\t}\r\n//\t\tcase NsBlendMode_BlendAlpha:\t\t// Blend, using constant alpha\r\n//\t\tcase NsBlendMode_AddAlpha:\t\t// Additive, using constant alpha\r\n//\t\t\tif ( km != ( 1 | ( fixAlpha << 8 ) ) ) {\r\n//\t\t\t\tGXSetTevKAlphaSel( GX_TEVSTAGE0, GX_TEV_KASEL_K0_A );\r\n//\t\t\t\tGXSetTevKColor( GX_KCOLOR0, (GXColor){128,128,128,fixAlpha} );\r\n//\t\t\t\tkm = 1 | ( fixAlpha << 8 );\r\n//\t\t\t}\r\n//\t\tcase NsBlendMode_None:\t\t// Do nothing. No cut-out, no blend.\r\n//\t\tcase NsBlendMode_Sub:\t\t// Subtractive, using texture alpha\r\n//\t\tcase NsBlendMode_Blend:\t\t// Blend, using texture alpha\r\n//\t\tcase NsBlendMode_Add:\t\t// Additive, using texture alpha\r\n//\t\tcase NsBlendMode_AlphaTex:\t\t// Blend framebuffer color and texture alpha.\r\n//\t\tcase NsBlendMode_AlphaFB:\t\t// Blend framebuffer color and texture alpha, plus framebuffer color.\r\n//\t\tdefault:\r\n//\t\t\tbreak;\r\n//\t}\r\n//\t// Set Alpha input.\r\n//\tswitch ( blendMode ) {\r\n//\t\tcase NsBlendMode_BlendAlpha:\t\t// Blend, using constant alpha\r\n//\t\tcase NsBlendMode_AddAlpha:\t\t// Additive, using constant alpha\r\n//\t\t\tif ( ai != 1 ) {\r\n//\t\t\t\tGXSetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_KONST, GX_CA_RASA, GX_CA_ZERO );\r\n//\t\t\t\tai = 1;\r\n//\t\t\t}\r\n//\t\t\tbreak;\r\n//\t\tcase NsBlendMode_Sub:\t\t// Subtractive, using texture alpha\r\n//\t\tcase NsBlendMode_SubAlpha:\t\t// Subtractive, using constant alpha\r\n//\t\t\tbreak;\r\n//\t\tcase NsBlendMode_None:\t\t// Do nothing. No cut-out, no blend.\r\n//\t\tcase NsBlendMode_Blend:\t\t// Blend, using texture alpha\r\n//\t\tcase NsBlendMode_Add:\t\t// Additive, using texture alpha\r\n//\t\tcase NsBlendMode_AlphaTex:\t\t// Blend framebuffer color and texture alpha.\r\n//\t\tcase NsBlendMode_AlphaFB:\t\t// Blend framebuffer color and texture alpha, plus framebuffer color.\r\n//\t\tdefault:\r\n//\t\t\tif ( ai != ( 2 | texval ) ) {\r\n//\t\t\t\tif ( tx == 0 ) {\r\n////\t\t\t\t\tGXSetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ONE, GX_CA_RASA, GX_CA_ZERO );\r\n//\t\t\t\t\tGXSetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );\r\n//\t\t\t\t} else {\r\n//\t\t\t\t\tGXSetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO );\r\n//\t\t\t\t}\r\n//\t\t\t\tai = 2 | texval;\r\n//\t\t\t}\r\n//\t\t\tbreak;\r\n//\t}\r\n//\t// Set Color input.\r\n//\tswitch ( blendMode ) {\r\n//\t\tcase NsBlendMode_Sub:\t\t// Subtractive, using texture alpha\r\n//\t\t\tif ( ci != ( 0 | texval ) ) {\r\n//\t\t\t\tif ( tx == 0 ) {\r\n//\t\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASA, GX_CC_RASC, GX_CC_ZERO );\r\n//\t\t\t\t} else {\r\n//\r\n////out_reg = (d (op) ((1.0 - c)*a + c*b) + bias) * scale;\r\n////\r\n////dst_pix_clr = dst_pix_clr - src_pix_clr [clamped to zero]\r\n////\r\n////We want: dst-(texc*texa)\r\n//\r\n//\r\n////out_reg = (0 + ((1.0 - TEXC)*0 + TEXA*RASC) + 0) * 2;\r\n//\r\n////out_reg = (d (op) ((1.0 - c)*a + c*b) + bias) * scale;\r\n////out_reg = (d (op) ((1.0 - TEXA)*1 + TEXA*0) + bias) * scale;\r\n//\r\n////\t\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXA, GX_CC_RASC, GX_CC_ZERO );\r\n//\t\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXA, GX_CC_TEXC, GX_CC_ZERO );\r\n//\t\t\t\t}\r\n//\t\t\t\tci = 0 | texval;\r\n//\t\t\t}\r\n//\t\t    break;\r\n//\t\tcase NsBlendMode_SubAlpha:\t\t// Subtractive, using constant alpha\r\n//\t\t\tif ( ci != ( 1 | texval ) ) {\r\n//\t\t\t\tif ( tx == 0 ) {\r\n//\t\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_KONST, GX_CC_RASC, GX_CC_ZERO );\r\n//\t\t\t\t} else {\r\n//\t\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_KONST, GX_CC_TEXC, GX_CC_ZERO );\r\n//\t\t\t\t}\r\n//\t\t\t\tci = 1 | texval;\r\n//\t\t\t}\r\n//\t\t\tbreak;\r\n//\t\tcase NsBlendMode_AlphaTex:\t\t// Blend framebuffer color and texture alpha.\r\n//\t\t    break;\r\n//\t\tcase NsBlendMode_AlphaFB:\t\t// Blend framebuffer color and texture alpha, plus framebuffer color.\r\n//\t\t\tif ( ci != 2 ) {\r\n//\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ONE, GX_CC_ONE, GX_CC_ONE, GX_CC_ONE );\r\n//\t\t\t\tci = 2;\r\n//\t\t\t}\r\n//\t\t    break;\r\n//\t\tcase NsBlendMode_None:\t\t// Do nothing. No cut-out, no blend.\r\n//\t\tcase NsBlendMode_Blend:\t\t// Blend, using texture alpha\r\n//\t\tcase NsBlendMode_Add:\t\t// Additive, using texture alpha\r\n//\t\tcase NsBlendMode_BlendAlpha:\t\t// Blend, using constant alpha\r\n//\t\tcase NsBlendMode_AddAlpha:\t\t// Additive, using constant alpha\r\n//\t\tdefault:\r\n//\t\t\tif ( ci != ( 3 | texval ) ) {\r\n//\t\t\t\tif ( tx == 0 ) {\r\n////\t\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASA, GX_CC_RASC, GX_CC_ZERO );\r\n//\t\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );\r\n//\t\t\t\t} else {\r\n//\t\t\t\t\tGXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO );\r\n//\t\t\t\t}\r\n//\r\n//\t\t\t\tci = 3 | texval;\r\n//\t\t\t}\r\n//\t\t\tbreak;\r\n//\t}\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tsetBlendMode\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tblendMode\tThe blend mode to set.\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tpTex\t\tThe texture to set up.\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tfixAlpha\tThe fixed alpha value to use for fixed alpha modes.\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tProvides a mechanism to set a variety of blend modes for flat\t*\r\n// *\t\t\t\tor textured primitives. State is maintained between blend\t\t*\r\n// *\t\t\t\tmodes, so the fewest amount of state changes are made.\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void setBlendMode ( NsBlendMode blendMode, /*NsTexture*/void * pTex, float fixAlpha )\r\n//{\r\n//\tsetBlendMode ( blendMode, pTex, (u8)(fixAlpha * 128.0f ) );\r\n//}\r\n\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tsetZMode\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tmode\t\t\t\tThe z compare mode to use.\t\t\t\t\t*\r\n// *\t\t\t\tzcompare\t\t\tSets whether the z compare happens.\t\t\t*\r\n// *\t\t\t\tzupdate\t\t\t\tSets whether z buffer updating happens.\t\t*\r\n// *\t\t\t\trejectBeforeTexture\tSets where the z compare happens - if\t\t*\r\n// *\t\t\t\t\t\t\t\t\tbefore texturing, all pixels will be\t\t*\r\n// *\t\t\t\t\t\t\t\t\ttested. If after, only pixels that pass\t\t*\r\n// *\t\t\t\t\t\t\t\t\tthrough the TEV stages will be tested.\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tSets the hardware Z compare hardware to the specified values.\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void setZMode ( NsZMode mode, int zcompare, int zupdate, int rejectBeforeTexture )\r\n//{\r\n//\tGXSetZMode ( zcompare ? GX_TRUE : GX_FALSE, (GXCompare)mode, zupdate ? GX_TRUE : GX_FALSE );\r\n//\tGXSetZCompLoc( rejectBeforeTexture ? GX_TRUE : GX_FALSE );\r\n//\r\n//\tzMode\t\t\t\t\t= mode;\r\n//\tzCompare\t\t\t\t= zcompare;\r\n//\tzUpdate\t\t\t\t\t= zupdate;\r\n//\tzRejectBeforeTexture\t= rejectBeforeTexture;\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tgetZMode\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tmode\t\t\t\tThe z compare mode to use.\t\t\t\t\t*\r\n// *\t\t\t\tzcompare\t\t\tSets whether the z compare happens.\t\t\t*\r\n// *\t\t\t\tzupdate\t\t\t\tSets whether z buffer updating happens.\t\t*\r\n// *\t\t\t\trejectBeforeTexture\tSets where the z compare happens - if\t\t*\r\n// *\t\t\t\t\t\t\t\t\tbefore texturing, all pixels will be\t\t*\r\n// *\t\t\t\t\t\t\t\t\ttested. If after, only pixels that pass\t\t*\r\n// *\t\t\t\t\t\t\t\t\tthrough the TEV stages will be tested.\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tSets the hardware Z compare hardware to the specified values.\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void getZMode ( NsZMode* mode, int* zcompare, int* zupdate, int* rejectBeforeTexture )\r\n//{\r\n//\t*mode\t\t\t\t\t= zMode;\r\n//\t*zcompare\t\t\t\t= zCompare;\r\n//\t*zupdate\t\t\t\t= zUpdate;\r\n//\t*rejectBeforeTexture\t= zRejectBeforeTexture;\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tsetCullMode\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tmode\tThe polygon cull mode to use.\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tSets the hardware polygon culling mode.\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void setCullMode ( NsCullMode cullMode )\r\n//{\r\n//\tGXSetCullMode ( (GXCullMode)cullMode );\r\n//}\r\n//\r\n//\r\n//\r\n//bool enableFog( bool enable )\r\n//{\r\n//\t// Return what state fog was in prior to this call.\r\n//\tbool rv = fogEnabled;\r\n//\tif( enable != fogEnabled )\r\n//\t{\r\n//\t\tfogEnabled = enable;\r\n//\t\tif( fogEnabled )\r\n//\t\t{\r\n//\t\t\tGXSetFog( GX_FOG_LIN, fogNear, fogFar, 0.1f, 100000.0f, fogColor );\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tGXSetFog( GX_FOG_NONE, 0.0f, 0.0f, 0.0f, 0.0f, fogColor );\r\n//\t\t}\r\n//\t}\r\n//\treturn rv;\r\n//}\r\n//\r\n//\r\n//\r\n//void setFogColor( int r, int g, int b )\r\n//{\r\n//\tfogColor.r = r;\r\n//\tfogColor.g = g;\r\n//\tfogColor.b = b;\r\n//\tfogColor.a = 0;\r\n//\tif( fogEnabled )\r\n//\t{\r\n//\t\tGXSetFog( GX_FOG_LIN, fogNear, fogFar, 0.1f, 100000.0f, fogColor );\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n//void setFogNear( float near )\r\n//{\r\n//\tfogNear = near;\r\n//\tif( fogEnabled )\r\n//\t{\r\n//\t\tGXSetFog( GX_FOG_LIN, fogNear, fogFar, 0.1f, 100000.0f, fogColor );\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n//void setFogFar( float far )\r\n//{\r\n//\tfogFar = far;\r\n//\tif( fogEnabled )\r\n//\t{\r\n//\t\tGXSetFog( GX_FOG_LIN, fogNear, fogFar, 0.1f, 100000.0f, fogColor );\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n//NsBlendMode\tgetBlendMode( unsigned int blend0 )\r\n//{\r\n//\t// Same functionality as in CRW, convert PS2 style blend mode to Gamecube.\r\n//\t// Useful in cases such as the terrain particles.\r\n//\r\n//\tNsBlendMode\tresult;\r\n//\r\n//\tswitch( blend0 )\r\n//\t{\r\n//\t\tcase 0x00000000:\r\n//\t\tcase 0x0000000a:\r\n//\t\tcase 0x0000001a:\r\n//\t\tcase 0x0000002a:\r\n//\t\t\t// Direct write.\r\n//\t\t\tresult = NsBlendMode_None;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x00000042:\r\n//\t\t\t// Subtractive fb/texel.\r\n//\t\t\tresult = NsBlendMode_Sub;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x00000044:\r\n//\t\t\t// Blend fb/texel.\r\n//\t\t\tresult = NsBlendMode_Blend;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x00000048:\r\n//\t\t\t// Additive fb/texel.\r\n//\t\t\tresult = NsBlendMode_Add;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x00000062:\r\n//\t\t\t// Constant subtractive.\r\n//\t\t\tresult\t\t= NsBlendMode_SubAlpha;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x00000064:\r\n//\t\t\t// Constant blend.\r\n//\t\t\tresult = NsBlendMode_BlendAlpha;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x00000068:\r\n//\t\t\t// Constant additive.\r\n//\t\t\tresult = NsBlendMode_AddAlpha;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x00000089:\r\n//\t\t\t// Blend fb * texture alpha.\r\n//\t\t\tresult = NsBlendMode_AlphaTex;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x00000046:\r\n//\t\t\t// Blend fb * inv(texture alpha).\r\n//\t\t\tresult = NsBlendMode_InvAlphaTex;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x00000049:\r\n//\t\t\t// Blend ( fbRGB * texture alpha ) + fbRGB.\r\n//\t\t\tresult = NsBlendMode_AlphaFB;\r\n//\t\t\tbreak;\r\n//\t\tcase 0x00000080:\r\n//\t\tcase 0x000000A0:\r\n//\t\t\t// Output RGB 0,0,0.\r\n//\t\t\tresult = NsBlendMode_Black;\r\n//\t\t\tbreak;\r\n//\t\tdefault:\r\n//\t\t\t// Default: Direct write.\r\n//\t\t\tresult = NsBlendMode_None;\r\n////\t\t\tprintf ( \"\\n+++++ Unknown blend mode %08x,%08x\", blend0, blend1 );\r\n//\t\t\tbreak;\r\n//\t}\r\n//\treturn result;\r\n//}\r\n//\r\n//\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tend\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tCloses the rendering context. Prim and Model commands can no\t*\r\n// *\t\t\t\tlonger be issued.\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\nvoid end ( void )\r\n{\r\n//\tassert ( inRenderingContext );\r\n\r\n   //=========================================================\r\n\r\n    // restore previous state\r\n    GX::SetZMode( GX_TRUE, GX_LEQUAL, GX_TRUE );\r\n\r\n\tinRenderingContext = 0;\r\n\r\n\tGX::end();\r\n}\r\n\r\n}\t\t// namespace Render\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_render.h",
    "content": "#ifndef _RENDER_H_\r\n#define _RENDER_H_\r\n\r\n#include <dolphin.h>\r\n\r\ntypedef enum {\r\n\tNsBlendMode_None = 0,\t\t// 0:  Do nothing. No cut-out, no blend.\r\n\tNsBlendMode_Sub,\t\t\t// 1:  Subtractive, using texture alpha\r\n\tNsBlendMode_Blend,\t\t\t// 2:  Blend, using texture alpha\r\n\tNsBlendMode_Add,\t\t\t// 3:  Additive, using texture alpha\r\n\tNsBlendMode_SubAlpha,\t\t// 4:  Subtractive, using constant alpha\r\n\tNsBlendMode_BlendAlpha,\t\t// 5:  Blend, using constant alpha\r\n\tNsBlendMode_AddAlpha,\t\t// 6:  Additive, using constant alpha\r\n\tNsBlendMode_AlphaTex,\t\t// 7:  Blend framebuffer color and texture alpha.\r\n\tNsBlendMode_InvAlphaTex,\t// 8:  Blend framebuffer color and inverse texture alpha.\r\n\tNsBlendMode_AlphaFB,\t\t// 9:  Blend ( fbRGB * texture alpha ) + fbRGB.\r\n\tNsBlendMode_Black,\t\t\t// 10: \tOutput RGB 0,0,0.\r\n\r\n\tNsBlendMode_Max\r\n} NsBlendMode;\r\n\r\ntypedef enum {\r\n\tNsZMode_Never\t\t\t= GX_NEVER,\r\n\tNsZMode_Less\t\t\t= GX_LESS,\r\n\tNsZMode_LessEqual\t\t= GX_LEQUAL,\r\n\tNsZMode_Equal\t\t\t= GX_EQUAL,\r\n\tNsZMode_NotEqual\t\t= GX_NEQUAL,\r\n\tNsZMode_Greater\t\t= GX_GREATER,\r\n\tNsZMode_GreaterEqual\t= GX_GEQUAL,\r\n\tNsZMode_Always\t\t= GX_ALWAYS,\r\n\r\n\tNsZMode_Max\r\n} NsZMode;\r\n\r\ntypedef enum {\r\n\tNsCullMode_Never\t= GX_CULL_NONE,\r\n\tNsCullMode_Front\t= GX_CULL_FRONT,\r\n\tNsCullMode_Back\t= GX_CULL_BACK,\r\n\tNsCullMode_Always\t= GX_CULL_ALL,\r\n\r\n\tNsCullMode_Max\r\n} NsCullMode;\r\n\r\nnamespace NsRender\r\n{\r\n\tvoid\t\tbegin\t\t\t( void );\r\n\r\n////\tvoid\t\tsetBlendMode\t( NsBlendMode blendMode, /*NsTexture*/void * pTex, float fixAlpha );\r\n////\tvoid\t\tsetBlendMode\t( NsBlendMode blendMode, /*NsTexture*/void * pTex, unsigned char fixAlpha );\r\n//\tvoid\t\tgetZMode\t\t( NsZMode* mode, int* zcompare, int* zupdate, int* rejectBeforeTexture );\r\n//\tvoid\t\tsetZMode\t\t( NsZMode mode, int zcompare, int zupdate, int rejectBeforeTexture );\r\n//\tvoid\t\tsetCullMode\t\t( NsCullMode cullMode );\r\n//\tbool\t\tenableFog\t\t( bool enable );\r\n//\tvoid\t\tsetFogColor\t\t( int r, int g, int b );\r\n//\tvoid\t\tsetFogNear\t\t( float near );\r\n//\tvoid\t\tsetFogFar\t\t( float far );\r\n//\tNsBlendMode\tgetBlendMode\t( unsigned int blend0 );\r\n\r\n\tvoid\t\tend\t\t\t\t( void );\r\n};\r\n\r\n#endif\t\t// _RENDER_H_\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_scene.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsScene\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tHolds scene data & draws it.\t\t\t\t\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include <math.h>\r\n//#include <string.h>\r\n//#include \"p_scene.h\"\r\n//#include \"p_file.h\"\r\n//#include \"p_prim.h\"\r\n//#include \"p_light.h\"\r\n//#include \"gfx\\nxflags.h\"\r\n//#ifndef __GFX_MODEL_H\r\n//#include <gfx/model.h>\r\n//#endif\r\n//#ifndef\t__SYS_MEM_MEMMAN_H\r\n//#include <sys/mem/memman.h>\r\n//#endif\r\n//#include \"p_profile.h\"\r\n//\r\n//\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsProfile ClumpTime( \"Clump Time\", 256 );\r\n//NsProfile BSPTime( \"BSP Time\", 256 );\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsScene\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tDeclares a scene object.\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n//NsScene::NsScene()\r\n//{\r\n//\tm_view.identity();\r\n//\r\n//\tm_pMaterial\t\t= NULL;\r\n//\tm_pCameraData\t= NULL;\r\n//\tm_pClumpHead\t= NULL;\r\n//\tm_SSMan\t\t\t= NULL;\r\n//\tm_pTexMan\t\t= NULL;\r\n//\tm_numParticles\t= 0;\r\n//\tm_pParticleData\t= NULL;\r\n//\tm_pCollision\t= new NsCollision;\r\n//}\r\n//\r\n//NsScene::~NsScene()\r\n//{\r\n//\tif ( m_pMaterial ) delete m_pMaterial;\r\n//\tif ( m_pCameraData ) delete m_pCameraData;\r\n////\tif ( m_pTexMan ) delete m_pTexMan;\r\n//\tif ( m_pCollision ) delete m_pCollision;\r\n//\tif ( m_pParticleData ) delete m_pParticleData;\r\n//\r\n//\tNsClump * pClump = m_pClumpHead;\r\n//\twhile ( pClump ) {\r\n//\t\tNsClump * pDelete = pClump;\r\n//\t\tpClump = pClump->m_pNext;\r\n//\t\tdelete pDelete;\r\n//\t}\r\n//}\r\n//\r\n//void NsScene::loadBSP( const char * pFilename )\r\n//{\r\n//\tNsFile\t\t\tf;\r\n//\tNsModel\t\t  * pModel;\r\n//\r\n//\t// Load model data.\r\n//\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n//\tpModel\t= (NsModel *)f.load ( pFilename );\r\n//\tMem::Manager::sHandle().PopContext();\r\n//\r\n//\t// Build materials and display lists.\r\n//\tm_pMaterial = new NsMaterialMan( pModel->m_numMaterials );\r\n//\tif ( pModel ) pModel->buildMaterials ( m_pMaterial, m_pTexMan );\r\n//\tif ( pModel ) pModel->draw ( m_pMaterial, m_pCollision, 1, 1 );\r\n//\r\n//\t// Copy particle data.\r\n//\tunsigned int * p32 = pModel->m_pExtraData;\r\n//\tm_numParticles = *p32++;\r\n//\tif ( m_numParticles ) {\r\n//\t\tm_pParticleData = new NsParticle[m_numParticles];\r\n//\t\tmemcpy ( m_pParticleData, p32, sizeof( NsParticle ) * m_numParticles );\r\n//\t\tp32 += (sizeof( NsParticle ) * m_numParticles) / 4;\r\n//\t} else {\r\n//\t\tm_pParticleData = NULL;\r\n//\t}\r\n//\r\n//\t// Copy camera data.\r\n//\tunsigned int * pCameraData = p32;\r\n//\tint numCamera = p32[0];\r\n//\tp32 = &p32[(numCamera*3)+1];\r\n//\tint numCameraPackets = p32[0];\r\n//\tp32 = &p32[(numCameraPackets*16)+1];\r\n//\tint\tsize = ((int)p32) - ((int)pCameraData);\r\n//\tm_pCameraData = new unsigned int[size / 4];\r\n//\tmemcpy ( m_pCameraData, pCameraData, size );\r\n//\r\n//\t// Generate world bounding box information.\r\n//\tm_pMaterial->calculateBoundingBox ( &m_cull );\r\n//\r\n//\t// Delete the original, we're done with it.\r\n//\tdelete pModel;\r\n//}\r\n//\r\n//void NsScene::draw( NsCamera * camera )\r\n//{\r\n//\tNsClump * pClump = m_pClumpHead;\r\n//\r\n//\tNsVector _v( 0.5, 0.5, 0.5 );\r\n//\tcamera->getViewMatrix()->scale( &_v, NsMatrix_Combine_Post );\r\n//\r\n//\r\n//\t// Render the clumps attached to this world.\r\n//\tClumpTime.start();\r\n//\twhile ( pClump ) {\r\n//\r\n//\t\t// If the clump user data field is set, this indicates an owner Gfx::Model, which\r\n//\t\t// expects it's render callback to be called at this point, for tasks such as setting\r\n//\t\t// up lighting etc.\r\n//\t\tvoid* p_user_data = pClump->getUserData();\r\n//\t\tif( p_user_data )\r\n//\t\t{\r\n//\t\t\tif((((Gfx::Model*)p_user_data )->m_model_flags & MODELFLAG_HIDE ) == 0 )\r\n//\t\t\t{\r\n//\t\t\t\t// Dirty dirty dirty.\r\n////\t\t\t\t((Gfx::Model*)p_user_data )->RenderCallback();\r\n//\r\n//\t\t\t\t// Upload any lighting info that has changed.\r\n//\t\t\t\tNsLight::loadup();\r\n//\r\n//\t\t\t\tpClump->draw( camera, 1 );\r\n//\r\n////\t\t\t\t((Gfx::Model*)p_user_data )->PostRenderCallback();\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\telse\r\n//\t\t{\r\n//\t\t\tpClump->draw( camera, 1 );\r\n//\t\t}\r\n//\t\tpClump = pClump->m_pNext;\r\n//\t}\r\n//\tClumpTime.stop();\r\n//\r\n//\t// Render the BSP.\r\n//\tBSPTime.start();\r\n//\tcamera->begin();\r\n//\tm_pMaterial->cull( camera->getCurrent() );\r\n//\tm_pMaterial->draw();\r\n//\tcamera->end();\r\n//\tBSPTime.stop();\r\n//}\r\n//\r\n//void NsScene::addClump( NsClump * pClumpToAdd )\r\n//{\r\n//\tpClumpToAdd->m_pNext = m_pClumpHead;\r\n//\tm_pClumpHead = pClumpToAdd;\r\n//\r\n//\tpClumpToAdd->m_pWorld = this;\r\n//}\r\n//\r\n//void NsScene::removeClump( NsClump * pClumpToRemove )\r\n//{\r\n//\tNsClump *  pSearchClump;\r\n//\tNsClump ** ppLastClump;\r\n//\r\n//\tpSearchClump = m_pClumpHead;\r\n//\tppLastClump = &m_pClumpHead;\r\n//\twhile ( pSearchClump ) {\r\n//\t\t// See if this is the one.\r\n//\t\tif ( pSearchClump == pClumpToRemove ) {\r\n//\t\t\t// Link over this clump.\r\n//\t\t\t*ppLastClump = pSearchClump->m_pNext;\r\n//\t\t\t// Set world to NULL.\r\n//\t\t\tpSearchClump->m_pWorld = NULL;\r\n//\t\t\tbreak;\r\n//\t\t}\r\n//\t\t// No match, point up the last clump pointer to pointer.\r\n//\t\tppLastClump = &pSearchClump->m_pNext;\r\n//\t\t// Onto the next one.\r\n//\t\tpSearchClump = pSearchClump->m_pNext;\r\n//\t}\r\n//}\r\n//\r\n//void NsScene::forAllClumps ( NsScene_Callback pCB, void * pData )\r\n//{\r\n//\tNsClump * pClump = m_pClumpHead;\r\n//\twhile ( pClump ) {\r\n//\t\tif ( pCB ) pCB( pClump, pData );\r\n//\t\tpClump = pClump->m_pNext;\r\n//\t}\r\n//}\r\n//\r\n////void NsScene::forAllAtomics ( NsClump_Callback pCB, void * pData )\r\n////{\r\n////\tNsClump * pClump = m_pClumpHead;\r\n////\twhile ( pClump ) {\r\n////\t\tpClump->forAllAtomics( pCB, pData );\r\n////\t\tpClump = pClump->m_pNext;\r\n////\t}\r\n////}\r\n//\r\n//int NsScene::findCollision( NsLine * pLine, NsDL::Collision_LineCallback pCb, void * pData )\r\n//{\r\n//\treturn m_pCollision->findCollision( pLine, pCb, pData );\r\n//}\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_scene.h",
    "content": "//#ifndef _SCENE_H_\r\n//#define _SCENE_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_camera.h\"\r\n//#include \"p_texman.h\"\r\n//#include \"p_matman.h\"\r\n//#include \"p_dlman.h\"\r\n//#include \"p_model.h\"\r\n//#include \"p_clump.h\"\r\n//#include \"p_matrix.h\"\r\n//\r\n//typedef struct {\r\n//\tNsVector\t\temPos;\r\n//\r\n//\tNsVector\t\temRotRight;\t\t// Same as RwMatrix\r\n//\tunsigned int\temRotFlags;\r\n//\tNsVector\t\temRotUp;\r\n//\tunsigned int\temRotPad1;\r\n//\tNsVector\t\temRotAt;\r\n//\tunsigned int\temRotPad2;\r\n//\tNsVector\t\temRotPos;\r\n//\tunsigned int\temRotPad3;\r\n//\r\n//\tfloat\t\t\temWidth;\r\n//\tfloat\t\t\temHeight;\r\n//\tfloat\t\t\temAngle;\r\n//\tunsigned int\temNumParticles;\r\n//\r\n//\tfloat\t\t\tpartLifeMin;\r\n//\tfloat\t\t\tpartLifeRange;\r\n//\tunsigned int\tpartStartColor;\r\n//\tunsigned int\tpartEndColor;\r\n//\tfloat\t\t\tpartAR;\r\n//\tfloat\t\t\tpartWidth;\r\n//\tNsVector\t\tpartForce;\r\n//\tfloat\t\t\tpartGrowth;\r\n//\tfloat\t\t\tpartSpeedMin;\r\n//\tfloat\t\t\tpartSpeedRange;\r\n//\tfloat\t\t\tpartSpeedDamping;\r\n//\r\n//\tchar\t\t\ttextureName[64-8];\r\n//\tunsigned char\ttype;\r\n//\tunsigned char\tflags;\r\n//\tunsigned char\talpha;\r\n//\tunsigned char\tblendmode;\r\n//\tunsigned int\tcolor;\r\n//\tunsigned int\tnameChecksum;\r\n//} NsParticle;\r\n//\r\n//typedef NsClump * (*NsScene_Callback)( NsClump * clump, void * data );\r\n//\r\n//class NsScene\r\n//{\r\n//\tNsMatrix\t\tm_view;\r\n//\r\n//\tNsClump\t\t  * m_pClumpHead;\r\n//\tunsigned int  * m_pCameraData;\r\n//\tunsigned int\tm_numParticles;\r\n//\tNsParticle\t  * m_pParticleData;\r\n//\r\n//\tNsTextureMan  * m_pTexMan;\r\n//\r\n//\tNsCollision\t  * m_pCollision;\r\n//public:\r\n//\tvoid\t\t  * m_SSMan;\r\n//\tNsCull_Item\t\tm_cull;\t\t\t// Describes size of world.\r\n//\tNsMaterialMan *\tm_pMaterial;\r\n//\r\n//\t\t\t\t\tNsScene\t\t\t();\r\n//\t\t\t\t\t~NsScene\t\t();\r\n//\r\n//\tvoid\t\t\tloadBSP\t\t\t( const char * pFilename );\r\n//\r\n//\tvoid\t\t\tdraw\t\t\t( NsCamera * camera );\r\n//\r\n//\tvoid\t\t\taddClump\t\t( NsClump * pClumpToAdd );\r\n//\tvoid\t\t\tremoveClump\t\t( NsClump * pClumpToRemove );\r\n//\r\n//\tunsigned int  *\tgetCameraData\t( void ) { return m_pCameraData; };\r\n//\r\n//\tvoid\t\t\tforAllClumps\t( NsScene_Callback pCB, void * pData );\r\n//\r\n//\tvoid\t\t\tsetTexMan\t\t( NsTextureMan * pTexMan ) { m_pTexMan = pTexMan; }\r\n//\tNsTextureMan  * getTexMan\t\t( void ) { return m_pTexMan; }\r\n//\r\n//\tvoid\t\t\tsetParticleData\t( NsParticle * pParticleData ) { m_pParticleData = pParticleData; }\r\n//\tunsigned int\tgetNumParticles ( void ) { return m_numParticles; }\r\n//\tNsParticle\t  * getParticleData ( void ) { return m_pParticleData; }\r\n//\r\n//\tint\t\t\t\tfindCollision\t( NsLine * pLine, NsDL::Collision_LineCallback pCb, void * pData );\r\n//};\r\n//\r\n//#endif\t\t// _SCENE_H_\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_screenshot.cpp",
    "content": "/*---------------------------------------------------------------------------*\r\n  Project:  onetri\r\n  File:     screenshot.h\r\n\r\n  Copyright 1998, 1999, 2000 Nintendo.  All rights reserved.\r\n\r\n  These coded instructions, statements, and computer programs contain\r\n  proprietary information of Nintendo of America Inc. and/or Nintendo\r\n  Company Ltd., and are protected by Federal copyright law.  They may\r\n  not be disclosed to third parties or copied or duplicated in any form,\r\n  in whole or in part, without the prior written consent of Nintendo.\r\n\r\n  Created 05-25-01 by Steve Rabin\r\n  \r\n *---------------------------------------------------------------------------*/\r\n\r\n#include <sys/ngc/p_screenshot.h>\r\n#include <dolphin/hio.h>\r\n#include <string.h>\r\n#include <sys/ngc/p_gx.h>\r\n\r\n\r\n#define WIDTH_SCREENSHOT 640\r\n#define HEIGHT_SCREENSHOT 480\r\n#define SIZE_SCREENSHOT_RGB WIDTH_SCREENSHOT*HEIGHT_SCREENSHOT*3\r\n#define SIZE_SCREENSHOT_YUV WIDTH_SCREENSHOT*HEIGHT_SCREENSHOT*2\r\n\r\n#define XFB_BASE 1\r\n#define XFB_RANGE 6\r\n#define EFB_BASE 11\r\n#define EFB_RANGE 9\r\n#define PING_BASE 20\r\n#define PING_RANGE 9\r\n#define MINIMIZE_BUFFER_TRUE 35\r\n#define MINIMIZE_BUFFER_FALSE 36\r\n\r\n\r\ntypedef enum  { \r\n\t\t\t\tGRAB_NOT_TRANSFERRING, \r\n\t\t\t\tGRAB_TRANSFERRING \r\n} GRAB_STATUS;\r\n\r\n\r\n//Globals\r\nBOOL g_connected = FALSE;\r\nBOOL g_ping_received = FALSE;\r\nu32 g_received_signal = 0;\r\nBOOL g_mail_waiting = FALSE;\r\nBOOL g_minimize_buffer = FALSE;\r\ns32 g_usb_channel = -1;\r\nu8* g_data;\r\n\r\n\r\nstatic BOOL HostIOEnumCallback( s32 chan )\r\n{\r\n\tg_usb_channel = chan;\r\n\treturn( FALSE );\r\n}\r\n\r\nstatic void HostIOCallback( void )\r\n{\t\r\n\t//Mail is waiting for us - don't look at it yet\r\n\tg_mail_waiting = TRUE;\r\n}\r\n\r\n\r\n\r\nstatic void CopyoutEFB( u8* image_buffer, u32 width, u32 height )\r\n{\r\n\tu16 i, j;\r\n\tu32 color;\r\n\t\r\n\tfor( j=0; j<height; j++ ) {\r\n\t\tfor( i=0; i<width; i++ ) {\r\n\t\t\tGX::PeekARGB( i, j, &color );\r\n\t\t\timage_buffer[2] = (u8)(color & 0x000000FF);\r\n\t\t\timage_buffer[1] = (u8)((color & 0x0000FF00) >> 8);\r\n\t\t\timage_buffer[0] = (u8)((color & 0x00FF0000) >> 16);\r\n\t\t\timage_buffer += 3;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\nstatic void CopyoutPortionEFB( u8* image_buffer, u32 width, u32 startByte, u32 totalBytes )\r\n{\r\n\tu32 color;\r\n\t\r\n\tu16 x = (u16)((u32)(startByte/3) % width);\r\n\tu16 y = (u16)((u32)(startByte/3) / width);\r\n\tu32 component = startByte%3;\r\n\t\r\n\tu32 count = 0;\r\n\twhile( count < totalBytes )\r\n\t{\r\n\t\tGX::PeekARGB( x, y, &color );\r\n\t\t\r\n\t\tif( component == 0 ) {\r\n\t\t\tcount++;\r\n\t\t\timage_buffer[0] = (u8)((color & 0x00FF0000) >> 16);\r\n\t\t}\r\n\t\tif( component <= 1 && count < totalBytes ) {\r\n\t\t\tcount++;\r\n\t\t\timage_buffer[1 - component] = (u8)((color & 0x0000FF00) >> 8);\r\n\t\t}\r\n\t\tif( component <= 2 && count < totalBytes ) {\r\n\t\t\tcount++;\r\n\t\t\timage_buffer[2 - component] = (u8)(color & 0x000000FF);\r\n\t\t}\r\n\t\timage_buffer += 3 - component;\r\n\t\tcomponent = 0;\r\n\t\t\r\n\t\tx++;\r\n\t\tif( x >= width ) {\r\n\t\t\tx = 0;\r\n\t\t\ty++;\r\n\t\t}\r\n\t}\r\n\t\r\n\r\n}\r\n\r\n\r\n\r\nstatic void TakeScreenshotEFB( SCREENSHOTAllocator allocator )\r\n{\r\n\tif( g_data == 0 ) {\r\n\t\tg_data = (u8*)allocator( SIZE_SCREENSHOT_RGB );\r\n\t}\r\n\tCopyoutEFB( g_data, WIDTH_SCREENSHOT, HEIGHT_SCREENSHOT );\r\n\tDCFlushRange( &g_data[0], SIZE_SCREENSHOT_RGB );\r\n\tOSReport( \"SCREENSHOT: Saved off screenshot to local memory.\\n\" );\r\n}\r\n\r\n\r\n\r\nstatic void TakeScreenshotXFB( void* bufferXFB, SCREENSHOTAllocator allocator )\r\n{\r\n\tvoid* buffer = bufferXFB;\r\n\tif( g_data == 0 ) {\r\n\t\tg_data = (u8*)allocator( SIZE_SCREENSHOT_YUV );\r\n\t}\r\n\tmemcpy( g_data, buffer, SIZE_SCREENSHOT_YUV );\r\n\tDCFlushRange( &g_data[0], SIZE_SCREENSHOT_YUV );\r\n\tOSReport( \"SCREENSHOT: Saved off screenshot to local memory.\\n\" );\r\n}\r\n\r\n\r\n\r\nstatic void WriteScreenshotPortionEFBtoUSB( u32 chunk, SCREENSHOTAllocator allocator )\r\n{\r\n\tu32 i;\r\n\tu32 size1K = 1024;\r\n\tu32 size100K = size1K*100;\r\n\tif( g_data == 0 ) {\r\n\t\tg_data = (u8*)allocator( size1K );\r\n\t}\r\n\tfor( i=0; i<100; i++ )\r\n\t{\r\n\t\tCopyoutPortionEFB( g_data, WIDTH_SCREENSHOT, (chunk*size100K)+(i*size1K), size1K );\r\n\t\tDCFlushRange( &g_data[0], size1K );\r\n\t\twhile( !HIOWrite( 0x00000500 + (i*size1K), g_data, (s32)size1K ) ) {\r\n\t\t\t//Spin until communication is successful\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\nstatic GRAB_STATUS GrabChunk( u32 chunk, \r\n\t\t\t\t\t\t\t  void* bufferXFB,\r\n\t\t\t\t\t\t\t  SCREENSHOTAllocator allocator, \r\n\t\t\t\t\t\t\t  SCREENSHOTDeallocator deallocator )\r\n{\r\n\tif( chunk >= XFB_BASE && chunk < XFB_BASE + XFB_RANGE )\r\n\t{\r\n\t\tvoid* buffer = 0;\r\n\t\t\r\n\t\tif( chunk == XFB_BASE )\r\n\t\t{\t//save off XFB screenshot\r\n\t\t\tif( !g_minimize_buffer ) {\r\n\t\t\t\tTakeScreenshotXFB( bufferXFB, allocator );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\t\r\n\t\t//transfer chunk\r\n\t\tif( g_minimize_buffer ) {\t\r\n\t\t\tu8* fb = (u8*)bufferXFB;\r\n\t\t\tbuffer = (void*)( &fb[100*1024*(chunk - XFB_BASE)] );\r\n\t\t}\r\n\t\telse {\r\n\t\t\tbuffer = (void*)( &g_data[100*1024*(chunk - XFB_BASE)] );\r\n\t\t}\r\n\t\t\r\n\t\twhile( !HIOWrite( 0x00000500, buffer, 100*1024 ) ) {\r\n\t\t\t//Spin until communication is successful\r\n\t\t}\r\n\t\tOSReport( \"SCREENSHOT: Wrote chunk #%d.\\n\", chunk );\r\n\t\t\t\t\r\n\t\t//communicate that the chunk is ready to be read\r\n\t\twhile( !HIOWriteMailbox( chunk ) ) {\r\n\t\t\t//Spin until communication is successful\r\n\t\t}\r\n\t\tOSReport( \"SCREENSHOT: Notify of write chunk #%d put in mailbox.\\n\", g_received_signal );\r\n\t}\r\n\telse if( chunk >= EFB_BASE && chunk < EFB_BASE + EFB_RANGE )\r\n\t{\r\n\t\tvoid* buffer;\r\n\t\t\r\n\t\tif( chunk == EFB_BASE )\r\n\t\t{\t//save off EFB screenshot\r\n\t\t\tif( !g_minimize_buffer ) {\r\n\t\t\t\tTakeScreenshotEFB( allocator );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( g_minimize_buffer )\r\n\t\t{\r\n\t\t\tWriteScreenshotPortionEFBtoUSB( chunk - EFB_BASE, allocator );\r\n\t\t}\r\n\t\telse\r\n\t\t{\t//transfer chunk\r\n\t\t\tbuffer = (void*)( &g_data[100*1024*(chunk - EFB_BASE)] );\r\n\t\t\twhile( !HIOWrite( 0x00000500, buffer, 100*1024 ) ) {\r\n\t\t\t\t//Spin until communication is successful\r\n\t\t\t}\r\n\t\t}\r\n\t\tOSReport( \"SCREENSHOT: Wrote chunk #%d.\\n\", chunk );\r\n\t\t\r\n\t\t//communicate that the chunk is ready to be read\r\n\t\twhile( !HIOWriteMailbox( chunk ) ) {\r\n\t\t\t//Spin until communication is successful\r\n\t\t}\r\n\t\tOSReport( \"SCREENSHOT: Notify of write chunk #%d put in mailbox.\\n\", g_received_signal );\r\n\t\t\r\n\t}\r\n\t\r\n\tif( chunk == XFB_BASE + XFB_RANGE - 1 || \r\n\t\tchunk == EFB_BASE + EFB_RANGE - 1 )\r\n\t{\t//free screenshot buffer space\r\n\t\tif( g_data ) {\r\n\t\t\tdeallocator( g_data );\r\n\t\t\tg_data = 0;\r\n\t\t}\r\n\t\treturn( GRAB_NOT_TRANSFERRING );\r\n\t}\r\n\telse {\r\n\t\treturn( GRAB_TRANSFERRING );\r\n\t}\r\n\r\n}\r\n\r\n\r\n\r\nstatic void CheckMail( void* bufferXFB,\r\n\t\t\t\t\t   SCREENSHOTAllocator allocator, \r\n\t\t\t\t\t   SCREENSHOTDeallocator deallocator )\r\n{\r\n\tu32 temp = 0;\r\n\tu32 escapeCount = 0;\r\n\tGRAB_STATUS status = GRAB_TRANSFERRING;\r\n\twhile( status == GRAB_TRANSFERRING )\r\n\t{\r\n\t\tescapeCount++;\r\n\t\tif( g_mail_waiting )\r\n\t\t{\r\n\t\t\tif( HIOReadMailbox( &temp ) ) {\r\n\t\t\t\tg_mail_waiting = FALSE;\r\n\t\t\t\tstatus = GRAB_NOT_TRANSFERRING;\r\n\t\t\t\tif( temp >= PING_BASE && temp < PING_BASE + PING_RANGE )\r\n\t\t\t\t{\t//ping message received\r\n\t\t\t\t\twhile( !HIOWriteMailbox( temp ) ) {\r\n\t\t\t\t\t\t//Spin until communication is successful\r\n\t\t\t\t\t}\r\n\t\t\t\t\tOSReport( \"SCREENSHOT: Sent ping back.\\n\" );\r\n\t\t\t\t}\r\n\t\t\t\telse if( (temp >= XFB_BASE && temp < XFB_BASE + XFB_RANGE) || \r\n\t\t\t\t\t\t (temp >= EFB_BASE && temp < EFB_BASE + EFB_RANGE) )\r\n\t\t\t\t{\t//request for screen capture\r\n\t\t\t\t\tescapeCount = 0;\r\n\t\t\t\t\tg_received_signal = temp;\r\n\t\t\t\t\tOSReport( \"SCREENSHOT: Grab screenshot request.\\n\" );\r\n\t\t\t\t\tstatus = GrabChunk( g_received_signal, bufferXFB, allocator, deallocator );\r\n\t\t\t\t}\r\n\t\t\t\telse if( temp == MINIMIZE_BUFFER_TRUE )\r\n\t\t\t\t{\t//request to use minimal memory (100K), however game pauses\r\n\t\t\t\t\tg_minimize_buffer = TRUE;\r\n\t\t\t\t}\r\n\t\t\t\telse if( temp == MINIMIZE_BUFFER_FALSE )\r\n\t\t\t\t{\t//request to not use minimal memory and keep game running\r\n\t\t\t\t\tg_minimize_buffer = FALSE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif( !g_minimize_buffer )\r\n\t\t{\t//Escape loop since were not pausing the game to transfer\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif( g_minimize_buffer && escapeCount > 150000000 )\r\n\t\t{\t//The PC screenshot app has died - escape\r\n\t\t\tif( g_data ) {\r\n\t\t\t\tdeallocator( g_data );\r\n\t\t\t\tg_data = 0;\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n}\r\n\r\n\r\n\r\nstatic BOOL ConnectToUSB( void )\r\n{\r\n\tif( !g_connected )\r\n\t{\r\n\t\tif( HIOEnumDevices( HostIOEnumCallback ) ) {\r\n\t\t\tif( g_usb_channel >= 0 ) {\r\n\t\t\t\tif( HIOInit( g_usb_channel, HostIOCallback ) ) {\r\n\t\t\t\t\tu32 temp = 0;\r\n\t\t\t\t\tHIOReadMailbox( &temp );\r\n\t\t\t\t\tg_connected = TRUE;\r\n\t\t\t\t\tOSReport( \"SCREENSHOT: USB connected\\n\" );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn( g_connected );\r\n}\r\n\r\n\r\n\r\nvoid SCREENSHOTService( void* bufferXFB,\r\n\t\t\t\t\t\tSCREENSHOTAllocator allocator, \r\n\t\t\t\t\t\tSCREENSHOTDeallocator deallocator )\r\n{\r\n\tif( !g_connected ) {\r\n\t\tConnectToUSB();\r\n\t}\r\n\telse if( g_mail_waiting ) {\r\n\t\tCheckMail( bufferXFB, allocator, deallocator );\r\n\t}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_screenshot.h",
    "content": "/*---------------------------------------------------------------------------*\r\n  Project:  onetri\r\n  File:     screenshot.h\r\n\r\n  Copyright 1998, 1999, 2000 Nintendo.  All rights reserved.\r\n\r\n  These coded instructions, statements, and computer programs contain\r\n  proprietary information of Nintendo of America Inc. and/or Nintendo\r\n  Company Ltd., and are protected by Federal copyright law.  They may\r\n  not be disclosed to third parties or copied or duplicated in any form,\r\n  in whole or in part, without the prior written consent of Nintendo.\r\n\r\n  Created 05-25-01 by Steve Rabin\r\n  \r\n *---------------------------------------------------------------------------*/\r\n\r\n\r\n#ifndef __SCREENSHOT_H__\r\n#define __SCREENSHOT_H__\r\n\r\n#include \"dolphin.h\"\r\n\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\n// access to the memory allocator of choice\r\ntypedef void*(*SCREENSHOTAllocator)   ( u32 size      );\r\ntypedef void (*SCREENSHOTDeallocator) ( void* block   );\r\n\r\n\r\nvoid SCREENSHOTService( void* bufferXFB, \r\n\t\t\t\t\t\tSCREENSHOTAllocator allocator, \r\n\t\t\t\t\t\tSCREENSHOTDeallocator deallocator );\r\n\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n\r\n#endif\t// __SCREENSHOT_H__\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_slerp.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsSlerp\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tSlerps matrices.\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include <math.h>\r\n//#include <string.h>\r\n//#include \"p_slerp.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsSlerp\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tDeclares a scene object.\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n//NsSlerp::NsSlerp()\r\n//{\r\n//}\r\n//\r\n//NsSlerp::NsSlerp( NsMatrix * start, NsMatrix * end )\r\n//{\r\n//\tsetMatrices( start, end );\r\n//}\r\n//\r\n//void NsSlerp::setMatrices( NsMatrix * start, NsMatrix * end )\r\n//{\r\n//\tNsMatrix\tinv;\r\n//\tNsVector\tcenter;\r\n//\r\n//\tm_start.copy( *start );\r\n//\tm_end.copy( *end );\r\n//\r\n//\t// Calculate the inverse transformation.\r\n//\tinv.invert( *start );\r\n//\tinv.transform( *end, NsMatrix_Combine_Post );\r\n//\r\n//\t// Get the axis and angle.\r\n//\tinv.getRotation( &m_axis, &m_angle, &center );\r\n//\r\n//\t// If angle is too small, use lerp.\r\n//\tm_lerp = ( m_angle < 2.0f );\r\n//}\r\n//\t\r\n//void NsSlerp::getMatrix( NsMatrix * result, float delta )\r\n//{\r\n//    /* Cap and floor the delta */\r\n//    /* If we are at one end the solution is easy */\r\n//    if (delta <= 0.0f)\r\n//    {\r\n//        delta = 0.0f;\r\n//\t\tresult->copy( m_start );\r\n//    }\r\n//    else if (delta >= 1.0f)\r\n//    {\r\n//        delta = 1.0f;\r\n//\t\tresult->copy( m_end );\r\n//    }\r\n//\r\n//    /* Do the lerp if we are, else... */\r\n//    if ( m_lerp )\r\n//    {\r\n//        /* Get the lerp matrix */\r\n//\t\tNsMatrix\tlerp;\r\n//\t\tNsVector\tlpos;\r\n//\t\tNsVector\tspos;\r\n//\t\tNsVector\tepos;\r\n//\t\tNsVector\trpos;\r\n//\r\n//\t\tlerp.identity();\r\n//\t\tspos.set( m_start.getPosX(), m_start.getPosY(), m_start.getPosZ() );\r\n//\t\tepos.set( m_end.getPosX(), m_end.getPosY(), m_end.getPosZ() );\r\n//\r\n//\t\tlerp.getRight()->sub( *m_end.getRight(), *m_start.getRight() );\r\n//\t\tlerp.getUp()->sub( *m_end.getUp(), *m_start.getUp() );\r\n//\t\tlerp.getAt()->sub( *m_end.getAt(), *m_start.getAt() );\r\n//\t\tlpos.sub( epos, spos );\r\n//\r\n//        /* Do lerp */\r\n//\t\tlerp.getRight()->scale( delta );\r\n//\t\tlerp.getUp()->scale( delta );\r\n//\t\tlerp.getAt()->scale( delta );\r\n//\t\tlpos.scale( delta );\r\n//\r\n//\t\tresult->getRight()->add( *m_start.getRight(), *lerp.getRight() );\r\n//\t\tresult->getUp()->add( *m_start.getUp(), *lerp.getUp() );\r\n//\t\tresult->getAt()->add( *m_start.getAt(), *lerp.getAt() );\r\n//\t\trpos.add( spos, lpos );\r\n//\r\n//\t\tresult->getRight()->normalize();\r\n//\t\tresult->getUp()->normalize();\r\n//\t\tresult->getAt()->normalize();\r\n//\r\n//\t\tresult->setPosX( rpos.x );\r\n//\t\tresult->setPosY( rpos.y );\r\n//\t\tresult->setPosZ( rpos.z );\r\n//    }\r\n//    else\r\n//    {\r\n//\t\tNsVector\trpos;\r\n//\t\tNsVector\tspos;\r\n//\t\tNsVector\tepos;\r\n//\r\n//\t\tspos.set( m_start.getPosX(), m_start.getPosY(), m_start.getPosZ() );\r\n//\t\tepos.set( m_end.getPosX(), m_end.getPosY(), m_end.getPosZ() );\r\n//\r\n//        /* Remove the translation for now */\r\n//\t\tresult->copy( m_start );\r\n//\t\tresult->setPos( 0.0f, 0.0f, 0.0f );\r\n//\r\n//        /* Rotate the new matrix */\r\n//\t\tresult->rotate( &m_axis, m_angle * delta, NsMatrix_Combine_Post );\r\n//\r\n//        /* Do linear interpolation on position */\r\n//\t\trpos.set( result->getPosX(), result->getPosY(), result->getPosZ() );\r\n//\t\trpos.sub( epos, spos );\r\n//\t\trpos.scale( delta );\r\n//\t\trpos.sub( spos );\r\n//\t\tresult->setPos( &rpos );\r\n//    }\r\n////\tresult->copy( m_end );\r\n//}\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_slerp.h",
    "content": "//#ifndef _SLERP_H_\r\n//#define _SLERP_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_matrix.h\"\r\n//\r\n//class NsSlerp\r\n//{\r\n//\tNsMatrix\tm_start;\r\n//\tNsMatrix\tm_end;\r\n//\tNsVector\tm_axis;\r\n//\tfloat\t\tm_angle;\r\n//\tint\t\t\tm_lerp;\t\t// 1=use lerp, 0=use slerp.\r\n//public:\r\n//\t\t\t\tNsSlerp\t\t();\r\n//\t\t\t\tNsSlerp\t\t( NsMatrix * start, NsMatrix * end );\r\n//\r\n//\tvoid\t\tsetMatrices\t( NsMatrix * start, NsMatrix * end );\r\n//\tvoid\t\tsetMatrices\t( MtxPtr start, MtxPtr end );\r\n//\t\r\n//\tvoid\t\tgetMatrix\t( NsMatrix * result, float delta );\r\n//};\r\n//\r\n//#endif\t\t// _SLERP_H_\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_tex.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPrim\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tProvides functionality for drawing various types of single\t\t*\r\n// *\t\t\t\tprimitives to the display.\t\t\t\t\t\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include <math.h>\r\n//#include \"p_tex.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#define NUM_TEX_SLOTS 1\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n//NsTexture::NsTexture()\r\n//{\r\n//}\r\n//\r\n//NsTexture::~NsTexture()\r\n//{\r\n//\tif ( m_pImage != &this[1] ) {\r\n//\t\t// Image and palette are separate from header.\r\n//\t\tif ( m_pImage ) delete (unsigned char *)m_pImage;\r\n//\t}\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tupload\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tpTex\tPointer to the texture to upload.\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tUploads the specified texture.\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void NsTexture::upload ( NsTexture_Wrap wrap )\r\n//{\r\n//\tGXTexObj\ttexObj;\r\n//\tGXTlutObj\tpalObj;\r\n//\r\n//\t// Set up texture based on depth.\r\n//\tswitch ( m_depth ) {\r\n//\t\tcase 4:\r\n//\t\t\tGXInitTexObjCI(\t&texObj, m_pImage, m_width, m_height,\r\n//\t\t\t\t\t\t    GX_TF_C4, (GXTexWrapMode)wrap, (GXTexWrapMode)wrap, GX_FALSE, GX_TLUT0 );\r\n//\t\t\tGXInitTlutObj( &palObj, m_pPalette, GX_TL_RGB5A3, 16 );\r\n//\t\t\tGXLoadTlut ( &palObj, GX_TLUT0 );\r\n//\t\t\tGXLoadTexObj ( &texObj, GX_TEXMAP0 );\r\n//\t\t\t// Set this texture as uploaded, and add to our list.\r\n//\t\t\tm_texID = GX_TEXMAP0;\r\n//\t\t\tbreak;\r\n//\t\tcase 8:\r\n//\t\t\tGXInitTexObjCI(\t&texObj, m_pImage, m_width, m_height,\r\n//\t\t\t\t\t\t    GX_TF_C8, (GXTexWrapMode)wrap, (GXTexWrapMode)wrap, GX_FALSE, GX_TLUT0 );\r\n//\t\t\tGXInitTlutObj( &palObj, m_pPalette, GX_TL_RGB5A3, 256 );\r\n//\t\t\tGXLoadTlut ( &palObj, GX_TLUT0 );\r\n//\t\t\tGXLoadTexObj ( &texObj, GX_TEXMAP0 );\r\n//\t\t\t// Set this texture as uploaded, and add to our list.\r\n//\t\t\tm_texID = GX_TEXMAP0;\r\n//\t\t\tbreak;\r\n//\t\tcase 16:\r\n//\t\t\tGXInitTexObj(\t&texObj, m_pImage, m_width, m_height,\r\n//\t\t\t\t\t\t    GX_TF_RGB5A3, (GXTexWrapMode)wrap, (GXTexWrapMode)wrap, GX_FALSE );\r\n//\t\t\tGXLoadTexObj ( &texObj, GX_TEXMAP0 );\r\n//\t\t\t// Set this texture as uploaded, and add to our list.\r\n//\t\t\tm_texID = GX_TEXMAP0;\r\n//\t\t\tbreak;\r\n//\t\tcase 32:\r\n//\t\t\tGXInitTexObj(\t&texObj, /*genTex32, 64, 64,*/\tm_pImage, m_width, m_height,\r\n//\t\t\t\t\t\t    GX_TF_RGBA8, (GXTexWrapMode)wrap, (GXTexWrapMode)wrap, GX_FALSE );\r\n//\t\t\tGXLoadTexObj ( &texObj, GX_TEXMAP0 );\r\n//\t\t\t// Set this texture as uploaded, and add to our list.\r\n//\t\t\tm_texID = GX_TEXMAP0;\r\n//\t\t\tbreak;\r\n//\t\tdefault:\r\n//\t\t\tbreak;\r\n//\t}\r\n////\tGXInitTexObjLOD( &pTex->texObj, GX_NEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_TRUE, GX_TRUE, GX_ANISO_4 );\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tupload\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tpTex\tPointer to the texture to upload.\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tUploads the specified texture.\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void NsTexture::upload ( NsTexture_Wrap wrap, void * force_pImage, unsigned short force_width, unsigned short force_height )\r\n//{\r\n//\tGXTexObj\ttexObj;\r\n//\tGXTlutObj\tpalObj;\r\n//\r\n//\t// Set up texture based on depth.\r\n//\tswitch ( m_depth ) {\r\n//\t\tcase 4:\r\n//\t\t\tGXInitTexObjCI(\t&texObj, force_pImage, force_width, force_height,\r\n//\t\t\t\t\t\t    GX_TF_C4, (GXTexWrapMode)wrap, (GXTexWrapMode)wrap, GX_FALSE, GX_TLUT0 );\r\n//\t\t\tGXInitTlutObj( &palObj, m_pPalette, GX_TL_RGB5A3, 16 );\r\n//\t\t\tGXLoadTlut ( &palObj, GX_TLUT0 );\r\n//\t\t\tGXLoadTexObj ( &texObj, GX_TEXMAP0 );\r\n//\t\t\t// Set this texture as uploaded, and add to our list.\r\n//\t\t\tm_texID = GX_TEXMAP0;\r\n//\t\t\tbreak;\r\n//\t\tcase 8:\r\n//\t\t\tGXInitTexObjCI(\t&texObj, force_pImage, force_width, force_height,\r\n//\t\t\t\t\t\t    GX_TF_C8, (GXTexWrapMode)wrap, (GXTexWrapMode)wrap, GX_FALSE, GX_TLUT0 );\r\n//\t\t\tGXInitTlutObj( &palObj, m_pPalette, GX_TL_RGB5A3, 256 );\r\n//\t\t\tGXLoadTlut ( &palObj, GX_TLUT0 );\r\n//\t\t\tGXLoadTexObj ( &texObj, GX_TEXMAP0 );\r\n//\t\t\t// Set this texture as uploaded, and add to our list.\r\n//\t\t\tm_texID = GX_TEXMAP0;\r\n//\t\t\tbreak;\r\n//\t\tcase 16:\r\n//\t\t\tGXInitTexObj(\t&texObj, force_pImage, force_width, force_height,\r\n//\t\t\t\t\t\t    GX_TF_RGB5A3, (GXTexWrapMode)wrap, (GXTexWrapMode)wrap, GX_FALSE );\r\n//\t\t\tGXLoadTexObj ( &texObj, GX_TEXMAP0 );\r\n//\t\t\t// If current texture in this slot, flag that it is no longer uploaded.\r\n//\t\t\tm_texID = GX_TEXMAP0;\r\n//\t\t\tbreak;\r\n//\t\tcase 32:\r\n//\t\t\tGXInitTexObj(\t&texObj, /*genTex32, 64, 64,*/\tforce_pImage, force_width, force_height,\r\n//\t\t\t\t\t\t    GX_TF_RGBA8, (GXTexWrapMode)wrap, (GXTexWrapMode)wrap, GX_FALSE );\r\n//\t\t\tGXLoadTexObj ( &texObj, GX_TEXMAP0 );\r\n//\t\t\t// Set this texture as uploaded, and add to our list.\r\n//\t\t\tm_texID = GX_TEXMAP0;\r\n//\t\t\tbreak;\r\n//\t\tdefault:\r\n//\t\t\tbreak;\r\n//\t}\r\n////\tGXInitTexObjLOD( &pTex->texObj, GX_NEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_TRUE, GX_TRUE, GX_ANISO_4 );\r\n//}\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_tex.h",
    "content": "//#ifndef _TEX_H_\r\n//#define _TEX_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_quat.h\"\r\n//\r\n//typedef enum {\r\n//\tNsTexture_Wrap_Clamp = GX_CLAMP,\r\n//\tNsTexture_Wrap_Repeat = GX_REPEAT,\r\n//\tNsTexture_Wrap_Mirror = GX_MIRROR\r\n//} NsTexture_Wrap;\r\n//\r\n//class NsTexture\r\n//{\r\n//public:\r\n//\tunsigned int\tm_id;\t\t// 4\r\n//\tunsigned int\tm_version;\t// 4\r\n//\tunsigned short\tm_width;\t// 2\r\n//\tunsigned short\tm_height;\t// 2\r\n//\tunsigned int\tm_depth;\t// 4\r\n//\tunsigned int\tm_uploaded;\t// 4\r\n//\tGXTexMapID\t\tm_texID;\t// 4\r\n//\tunsigned int\tm_unused;\t// 4\r\n//\tvoid\t\t  * m_pImage;\t// 4\r\n//\tvoid\t\t  * m_pPalette;\t// 4\r\n//\tchar\t\t\tm_name[60];\t// 60\r\n//\r\n//\t\t\t\t\tNsTexture\t();\r\n//\t\t\t\t\t~NsTexture\t();\r\n//\r\n//\tvoid\t\t\tupload\t\t( NsTexture_Wrap wrap );\r\n//\tvoid\t\t\tupload\t\t( NsTexture_Wrap wrap, void * force_pImage, unsigned short force_width, unsigned short force_height );\r\n//};\r\n//\r\n//#endif\t\t// _TEX_H_\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_texman.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPrim\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tProvides functionality for drawing various types of single\t\t*\r\n// *\t\t\t\tprimitives to the display.\t\t\t\t\t\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include <core/defines.h>\r\n//#include <core/crc.h>\r\n//#include <gel/scripting/script.h>\r\n//#include <math.h>\r\n//#include \"p_texman.h\"\r\n//#include \"p_hashid.h\"\r\n//#include \"p_assert.h\"\r\n//#include \"p_file.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n//#define DEFAULT_TEXMAN_HASH_SIZE 2048\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n////static NsTexture *htab[2048];\r\n////static NsTexture *ltab[2048];\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsTextureMan\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tInstances a texture manager to the default hash table size of\t*\r\n// *\t\t\t\t2048 entries.\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsTextureMan::NsTextureMan()\r\n//{\r\n//\tNsTextureMan ( DEFAULT_TEXMAN_HASH_SIZE );\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsTextureMan\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tInstances a texture manager to a user-specified size.\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsTextureMan::NsTextureMan ( int hashTableSize )\r\n//{\r\n////\tm_pHashTable = (NsTexture **)new unsigned char[ sizeof ( NsTexture ) * hashTableSize];\r\n////\tassert ( m_pHashTable );\r\n////\tm_tableSize = hashTableSize;\r\n////\r\n////\treset();\r\n//\r\n//\tassertf( false, ( \"No longer used...\\n\" ) );\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t~NsTextureMan\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tDestroys a texture manager.\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsTextureMan::~NsTextureMan()\r\n//{\r\n//\tint lp;\r\n//\r\n//\t// Destroy all textures.\r\n//\tfor ( lp = 0; lp < (int)m_tableSize; lp++ ) {\r\n//\t\tif ( m_pHashTable[lp] ) delete m_pHashTable[lp];\r\n//\t}\r\n//\tdelete (unsigned int *)m_pHashTable;\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tNsTextureMan\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tInstances a texture manager big enough to hold the specified\t*\r\n// *\t\t\t\tfile, loads and adds it.\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsTextureMan::NsTextureMan ( const char * pFilename )\r\n//{\r\n//\tNsFile\t\t\tfile;\r\n//\tunsigned int  * p32;\r\n//\tunsigned int\thashTableSize;\r\n//\r\n//\t// Load the texture binary.\r\n//\tMem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());\r\n//\tp32 = (unsigned int *)file.load( pFilename );\r\n//\tMem::Manager::sHandle().PopContext();\r\n//\r\n//\t// Calculate size of hash table.\r\n//\thashTableSize = p32[0] * 2;\r\n//\r\n//\t// Create space for hash table.\r\n//\tm_pHashTable = (NsTexture **)new unsigned int[hashTableSize];\r\n//\tassert ( m_pHashTable );\r\n//\tm_tableSize = hashTableSize;\r\n//\treset();\r\n//\r\n//\t// Add texture to hash table.\r\n//\taddList ( p32 );\r\n//\r\n//\t// Delete the original.\r\n//\tdelete p32;\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tmerge\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tMerges the specified texture manager into the current one.\t\t*\r\n// *\t\t\t\tBasically, it creates a new texture has array big enough for\t*\r\n// *\t\t\t\tboth lists and re-adds everything.\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void NsTextureMan::merge ( NsTextureMan& source )\r\n//{\r\n////\tNsTexture\t ** pOldTable;\r\n////\tunsigned int\toldTableSize;\r\n////\tunsigned int\tnewTableSize;\r\n//\tunsigned int\tlp;\r\n//\r\n////\t// Calculate size of new hash table.\r\n////\tnewTableSize = m_tableSize + source.m_tableSize;\r\n////\r\n////\t// Save old table information.\r\n////\toldTableSize = m_tableSize;\r\n////\tpOldTable = m_pHashTable;\r\n////\r\n////\t// Create space for new hash table.\r\n////\tm_pHashTable = (NsTexture **)new unsigned int[newTableSize];\r\n////\tassert ( m_pHashTable );\r\n////\tm_tableSize = newTableSize;\r\n////\treset();\r\n////\r\n////\t// Add each texture in turn from the old table.\r\n////\tfor ( lp = 0; lp < oldTableSize; lp++ ) {\r\n////\t\tif ( pOldTable[lp] ) {\r\n////\t\t\t// This should turn into a 'move' command.\r\n////\t\t\t{\r\n////\t\t\t\tunsigned int\thashValue;\r\n////\t\t\t\tunsigned int\thashSearch;\r\n////\t\t\t\t\r\n////\t\t\t\thashValue = Script::GenerateCRC ( pOldTable[lp]->m_name );\r\n////\t\t\t\thashValue %= m_tableSize;\r\n////\t\t\t\thashSearch = hashValue;\r\n////\t\t\t\t\r\n////\t\t\t\tdo {\r\n////\t\t\t\t\t// See if this hash slot is empty.\r\n////\t\t\t\t\tif ( !m_pHashTable[hashSearch] ) {\r\n////\t\t\t\t\t\t// Copy the pointer to the new hash table.\r\n////\t\t\t\t\t\tm_pHashTable[hashSearch] = pOldTable[lp];\r\n////\t\t\t\t\t\tbreak;\r\n////\t\t\t\t\t}\r\n////\t\t\t\t\t// Next hash entry.\r\n////\t\t\t\t\thashSearch = ( hashSearch + 1 ) % m_tableSize;\r\n////\t\t\t\t} while ( hashValue != hashSearch );\r\n////\t\t\t}\r\n////\t\t}\r\n////\t}\r\n////\r\n//\t// Add each texture in turn from the new table (cloned as the source table will\r\n//\t// almost certainly be deleted).\r\n//\tfor ( lp = 0; lp < source.m_tableSize; lp++ ) {\r\n//\t\tif ( source.m_pHashTable[lp] ) {\r\n//\t\t\tadd( source.m_pHashTable[lp] );\r\n//\t\t\tsource.m_pHashTable[lp] = NULL;\r\n//\t\t}\r\n//\t}\r\n//\r\n////\t// Delete old hash table.\r\n////\tdelete pOldTable;\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tadd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tpTexture\tThe texture to add.\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tAdds the specified texture to the texture manager.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsTexture * NsTextureMan::_add( NsTexture * pTexture, unsigned int copy )\r\n//{\r\n//\tunsigned int\thashValue;\r\n//\tunsigned int\thashSearch;\r\n//\tchar\t\t  * p8;\r\n//\tNsTexture\t  * pTex;\r\n//\r\n//\tpTex = pTexture;\r\n//\r\n//\tassert ( m_allocatedCount < m_tableSize );\r\n//\t\r\n//\t// Set the texture name checksum.\r\n//\tpTexture->m_id = Script::GenerateCRC ( pTexture->m_name );\r\n//\r\n//\thashValue = pTexture->m_id;\r\n//\thashValue %= m_tableSize;\r\n//\thashSearch = hashValue;\r\n//\t\r\n//\tdo {\r\n//\t\t// See if this hash slot is empty.\r\n//\t\tif ( !m_pHashTable[hashSearch] ) {\r\n//\t\t\t// Set palette if required & point past end.\r\n//\t\t\tp8 = (char *)&pTexture[1];\r\n//\t\t\tswitch ( pTexture->m_depth ) {\r\n//\t\t\t\tcase 4:\r\n//\t\t\t\t\tp8 += ( pTexture->m_width * pTexture->m_height ) / 2;\r\n//\t\t\t\t\tpTex = (NsTexture *)&p8[16*2];\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\tcase 8:\r\n//\t\t\t\t\tp8 += pTexture->m_width * pTexture->m_height;\r\n//\t\t\t\t\tpTex = (NsTexture *)&p8[256*2];\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\tcase 16:\r\n//\t\t\t\t\tp8 += pTexture->m_width * pTexture->m_height * 2;\r\n//\t\t\t\t\tpTex = (NsTexture *)p8;\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\tcase 32:\r\n//\t\t\t\t\tp8 += pTexture->m_width * pTexture->m_height * 4;\r\n//\t\t\t\t\tpTex = (NsTexture *)p8;\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t\tdefault:\r\n//\t\t\t\t\tbreak;\r\n//\t\t\t}\r\n//\t\t\tNsTexture\t  * newTex;\r\n//\t\t\tif ( copy ) {\r\n//\t\t\t\t// Copy the texture header.\r\n//\t\t\t\tnewTex = new NsTexture;\r\n//\t\t\t\tmemcpy ( newTex, pTexture, sizeof( NsTexture ) );\r\n//\t\t\t\t// Copy the texture data.\r\n//\t\t\t\tint size = (((int)pTex)-((int)&pTexture[1]));\r\n//\t\t\t\tnewTex->m_pImage = new unsigned char[size];\r\n//\t\t\t\tmemcpy ( newTex->m_pImage, &pTexture[1], size );\r\n//\t\t\t} else {\r\n//\t\t\t\tnewTex = pTexture;\r\n//\t\t\t\tif ( !newTex->m_pImage ) newTex->m_pImage = &newTex[1];\r\n//\t\t\t}\r\n//\r\n//\t\t\t// Set texture parameters.\r\n//\t\t\tnewTex->m_uploaded = 0;\r\n//\r\n//\t\t\t// Point to the palette.\r\n//\t\t\tif ( !newTex->m_pPalette ) {\r\n//\t\t\t\tp8 = (char *)newTex->m_pImage;\r\n//\t\t\t\tswitch ( newTex->m_depth ) {\r\n//\t\t\t\t\tcase 4:\r\n//\t\t\t\t\t\tp8 += ( newTex->m_width * newTex->m_height ) / 2;\r\n//\t\t\t\t\t\tnewTex->m_pPalette = p8;\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tcase 8:\r\n//\t\t\t\t\t\tp8 += newTex->m_width * newTex->m_height;\r\n//\t\t\t\t\t\tnewTex->m_pPalette = p8;\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t\tdefault:\r\n//\t\t\t\t\t\tbreak;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\t// Found an empty slot, point it up.\r\n//\t\t\tm_pHashTable[hashSearch] = newTex;\r\n//\r\n//\t\t\t// We're done.\r\n//\t\t\tm_allocatedCount++;\r\n//\t\t\tbreak;\r\n//\t\t}\r\n//\t\t// Next hash entry.\r\n//\t\thashSearch = ( hashSearch + 1 ) % m_tableSize;\r\n//\t} while ( hashValue != hashSearch );\r\n//\r\n//\treturn pTex;\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tadd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tpTexture\tThe texture to add.\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tAdds the specified texture to the texture manager.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsTexture * NsTextureMan::add( NsTexture * pTexture )\r\n//{\r\n//\treturn _add( pTexture, 0 );\r\n//}\r\n//\r\n//NsTexture * NsTextureMan::addClone( NsTexture * pTexture )\r\n//{\r\n//\treturn _add( pTexture, 1 );\r\n//}\r\n//\r\n//void NsTextureMan::remove ( const char * pName )\r\n//{\r\n//\tunsigned int\thashID;\r\n//\tunsigned int\thashValue;\r\n//\tunsigned int\thashSearch;\r\n//\t\r\n//\thashID = Script::GenerateCRC ( pName );\r\n//\thashValue = hashID % m_tableSize;\r\n//\thashSearch = hashValue;\r\n//\t\r\n//\tif ( !m_tableSize || !m_pHashTable ) return;\r\n//\r\n//\tdo {\r\n//\t\t// See if this hash slot matches.\r\n//\t\tif ( m_pHashTable[hashSearch] ) {\r\n//\t\t\tif ( m_pHashTable[hashSearch]->m_id == hashID ) {\r\n//\t\t\t\t// Found the matching item.\r\n//\t\t\t\tdelete m_pHashTable[hashSearch];\r\n//\t\t\t\tm_pHashTable[hashSearch] = NULL;\r\n//\t\t\t\tbreak;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\t// Next hash entry.\r\n//\t\thashSearch = ( hashSearch + 1 ) % m_tableSize;\r\n//\t} while ( hashValue != hashSearch );\r\n//}\r\n//\r\n//void NsTextureMan::replace ( const char * pName, NsTexture *pReplacement )\r\n//{\r\n//\tunsigned int\thashID;\r\n//\tunsigned int\thashValue;\r\n//\tunsigned int\thashSearch;\r\n//\t\r\n//\thashID = Script::GenerateCRC ( pName );\r\n//\thashValue = hashID % m_tableSize;\r\n//\thashSearch = hashValue;\r\n//\r\n//\tif ( !m_tableSize || !m_pHashTable ) return;\r\n//\r\n//\tdo {\r\n//\t\t// See if this hash slot matches.\r\n//\t\tif ( m_pHashTable[hashSearch] ) {\r\n//\t\t\tif ( m_pHashTable[hashSearch]->m_id == hashID ) {\r\n//\t\t\t\t// Found the matching item.\r\n//\r\n//\t\t\t\t// Delete the old image.\r\n//\t\t\t\tdelete (unsigned char *)m_pHashTable[hashSearch]->m_pImage;\r\n//\r\n//\t\t\t\t// Copy the new texture details over (only the dimensions).\r\n//\t\t\t\tm_pHashTable[hashSearch]->m_width\t= pReplacement->m_width;\r\n//\t\t\t\tm_pHashTable[hashSearch]->m_height\t= pReplacement->m_height;\r\n//\t\t\t\tm_pHashTable[hashSearch]->m_depth\t= pReplacement->m_depth;\r\n//\r\n//\t\t\t\t// Copy new image data & assign.\r\n//\t\t\t\tint size = ( pReplacement->m_width * pReplacement->m_height * pReplacement->m_depth ) / 8;\r\n//\t\t\t\tint palsize = ( pReplacement->m_depth < 16 ) ? ( 2 << pReplacement->m_depth ) : 0;\r\n//\t\t\t\tm_pHashTable[hashSearch]->m_pImage = new unsigned char[(size+palsize)];\r\n//\t\t\t\tmemcpy( m_pHashTable[hashSearch]->m_pImage, &pReplacement[1], (size+palsize) );\r\n//\r\n//\t\t\t\t// Set palette pointer.\r\n//\t\t\t\tunsigned char * p8 = (unsigned char *)m_pHashTable[hashSearch]->m_pImage;\r\n//\t\t\t\tm_pHashTable[hashSearch]->m_pPalette = &p8[size];\r\n//\t\t\t\tbreak;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\t// Next hash entry.\r\n//\t\thashSearch = ( hashSearch + 1 ) % m_tableSize;\r\n//\t} while ( hashValue != hashSearch );\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tretrieve\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tpName\tThe name of the texture to retrieve.\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tA pointer to the requested texture. NULL if not found.\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tRetrieves the specified texture from the texture manager.\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//NsTexture * NsTextureMan::retrieve ( const char * pName )\r\n//{\r\n//\tunsigned int\thashID;\r\n//\tunsigned int\thashValue;\r\n//\tunsigned int\thashSearch;\r\n//\tNsTexture\t  * pHeader;\r\n//\t\r\n//\thashID = Script::GenerateCRC ( pName );\r\n//\thashValue = hashID % m_tableSize;\r\n//\thashSearch = hashValue;\r\n//\tpHeader = NULL;\r\n//\t\r\n//\tif ( !m_tableSize || !m_pHashTable ) return NULL;\r\n//\r\n//\tdo {\r\n//\t\t// See if this hash slot matches.\r\n//\t\tif ( m_pHashTable[hashSearch] ) {\r\n//\t\t\tif ( m_pHashTable[hashSearch]->m_id == hashID ) {\r\n//\t\t\t\t// Found the matching item.\r\n//\t\t\t\tpHeader = m_pHashTable[hashSearch];\r\n//\t\t\t\tbreak;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\t// Next hash entry.\r\n//\t\thashSearch = ( hashSearch + 1 ) % m_tableSize;\r\n//\t} while ( hashValue != hashSearch );\r\n//\t\r\n//\treturn pHeader;\r\n//}\r\n//\r\n///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tMethod:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\taddList\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tInputs:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tpTexList\tPointer to a list of textures to add to the texture\t*\r\n// *\t\t\t\t\t\t\tmanager.\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tOutput:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t<none>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tAdds the specified list of textures to the texture manager.\t\t*\r\n// *\t\t\t\tThe data passed to this function corresponds to the binary data\t*\r\n// *\t\t\t\toutput of CRW.\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//void NsTextureMan::addList ( void * pTexList )\r\n//{\r\n//\tunsigned int\tnumTex;\r\n//\tunsigned int\ttex;\r\n//\tNsTexture\t  *\tpTex;\r\n////\tchar\t\t  * p8;\r\n//\tunsigned int  * p32;\r\n//\t\r\n//\t// Go through texture file, adding all textures to texture manager.\r\n//\tp32 = (unsigned int *)pTexList;\r\n//\tnumTex = p32[0];\r\n//\tpTex = (NsTexture *)&p32[8];\r\n//\tfor ( tex = 0; tex < numTex; tex++ ) {\r\n//\t\tassert ( pTex->m_id == *((unsigned int *)\"GCTX\") );\r\n//\t\tpTex = addClone ( pTex );\r\n//\t}\r\n//}\r\n//\r\n//void NsTextureMan::reset ( void )\r\n//{\r\n//\tint lp;\r\n//\r\n//\t// NULL the hashtable out.\r\n//\tfor ( lp = 0; lp < (int)m_tableSize; lp++ ) {\r\n//\t\tm_pHashTable[lp] = NULL;\r\n//\t}\r\n//\t// Set number of textures to 0.\r\n//\tm_allocatedCount = 0;\r\n//}\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_texman.h",
    "content": "//#ifndef _TEXMAN_H_\r\n//#define _TEXMAN_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_tex.h\"\r\n//\r\n//class NsTextureMan\r\n//{\r\n//\tNsTexture\t  * _add\t\t\t( NsTexture * pTexture, unsigned int copy );\r\n//\r\n//\tNsTexture\t ** m_pHashTable;\r\n//\tunsigned int\tm_tableSize;\r\n//\tunsigned int\tm_allocatedCount;\r\n//public:\r\n//\t\t\t\t\tNsTextureMan\t();\r\n//\t\t\t\t\tNsTextureMan\t( int hashTableSize );\r\n//\t\t\t\t\tNsTextureMan\t( const char * pFilename );\r\n//\t\t\t\t\t~NsTextureMan\t();\r\n//\r\n//\tNsTexture\t  * add\t\t\t\t( NsTexture * pTexture );\r\n//\tNsTexture\t  * addClone\t\t( NsTexture * pTexture );\r\n//\tvoid\t\t\tremove\t\t\t( const char * pName );\r\n//\tvoid\t\t\treplace\t\t\t( const char * pName, NsTexture *pReplacement );\r\n//\tNsTexture\t  * retrieve\t\t( const char * pName );\r\n//\tvoid\t\t\taddList\t\t\t( void * pTexList );\r\n//\r\n//\tunsigned int\tcount\t\t\t( void ) { return m_allocatedCount; };\r\n//\r\n//\tvoid\t\t\treset\t\t\t( void );\r\n//\r\n//\tvoid\t\t\tmerge\t\t\t( NsTextureMan& source );\r\n//};\r\n//\r\n//#endif\t\t// _TEXMAN_H_\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_timer.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTimer (TMR)\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tngps/p_timer.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t01/13/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNGPS System Timer\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <dolphin.h>\r\n#include <sys/timer.h>\r\n#include <sys/profiler.h>\r\n#include <gel/scripting/script.h>\r\n#include <sys/config/config.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Tmr \r\n{\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define vHIREZ_CMP 15000\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic \t\t\tsint \ts_timer_handler_id = -1;\r\nstatic volatile uint64\ts_count;\r\n\r\n#define\tvSMOOTH_N  4\t\r\n\r\nstatic volatile uint64  s_vblank = 0;\r\nstatic volatile uint64 s_total_vblanks = 0;\r\nstatic float s_slomo = 1.0f;\r\nstatic  uint64\ts_render_frame = 0;\t\r\nstatic uint64 s_stored_vblank = 0;\r\n\r\nstatic uint64 GetGameVblanks();\r\n\r\nstruct STimerInfo\r\n{\r\n\tfloat\trender_length;\r\n\tfloat\tframe_length;\r\n\tdouble\tuncapped_render_length;\r\n\tint\t\trender_buffer[vSMOOTH_N];\r\n\tuint64\trender_vblank;\r\n\tuint64\trender_last_vblank;\t\r\n\tint\t\trender_index;\r\n};\r\n\r\nstatic STimerInfo gTimerInfo;\r\nstatic STimerInfo gStoredTimerInfo;\r\n\r\nstatic void InitTimerInfo( void )\r\n{\r\n\tgTimerInfo.render_length\t\t\t= 0.01666666f;\t\t// defualt to 1/60th\r\n\tgTimerInfo.frame_length \t\t\t= 1.0f/60.0f;\t\t// default to 1/60th, will be correct after first frame is rendered\r\n\tgTimerInfo.uncapped_render_length\t= 0.01666666f;\t\t// defualt to 1/60th\r\n\tfor( int i = 0; i < vSMOOTH_N; i++ )\r\n\t{\r\n\t\tgTimerInfo.render_buffer[ i ] = 1;\r\n\t}\r\n\tgTimerInfo.render_vblank\t\t\t= 0;\t\r\n\tgTimerInfo.render_last_vblank\t\t= 0;\r\n\tgTimerInfo.render_index\t\t\t\t= 0;\r\n\r\n\tgStoredTimerInfo\t\t\t\t\t= gTimerInfo;\r\n\r\n\ts_stored_vblank\t\t\t\t\t\t= 0;\r\n\ts_vblank\t\t\t\t\t\t\t= 0;\r\n}\r\n\r\nTime  \t\t\t\t\t\t\ts_milliseconds = 0;\t\t\t// updated every call to VSync() or VSync1()\r\n\r\n#ifdef __NOPT_PROFILE__\r\n\r\n//Sys::ProfileData\tDMAProfileData;\r\n//Sys::ProfileData\tVU1ProfileData;\r\n\r\n#endif // __NOPT_PROFILE__\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n//static sint timer_handler ( sint ca )\r\n//{\r\n//\r\n//#ifdef __NOPT_PROFILE__\r\n//    if (( ca == INTC_TIM0 ) && ( *T0_MODE & 0x400 ))  // compare interrupt\r\n//    {\r\n//        *T0_COUNT\t= 0;\t\t// reset s_count\r\n//        *T0_MODE\t|= 0x400; \t// clear compare flag\r\n//\t\ts_count++;\r\n//#if 0\r\n//\t\tSys::ProfileData\t*prof;\r\n//\t\t \r\n//\t\tprof = &DMAProfileData;\r\n//\t\t\r\n//\t\tprof->read_state = (( (*D1_CHCR) & D_CHCR_STR_M ) >> 8 ) & 0x000000ff;\r\n//\t\t\r\n//\t\tif( prof->current_state[prof->flip] != prof->read_state )\r\n//\t\t{\r\n//\t\t\tprof->time[prof->flip][prof->current_offset[prof->flip]] = s_count*(vHIREZ_CMP/150); \r\n//\t\t\tprof->current_state[prof->flip] = prof->read_state;\r\n//\t\t\tprof->state[prof->flip][prof->current_offset[prof->flip]++] = prof->read_state;\r\n//\t\t}\r\n//\t\r\n//\t\tprof = &VU1ProfileData;\r\n//\t\t\r\n//\t\tuint32 vpustat;\r\n//\t\tasm volatile (\" cfc2 %0, $29 \" : \"=r\" (vpustat));\r\n//\t\tprof->read_state = (vpustat >> 8) & 0x000000ff;\r\n//\t\r\n//\t\tif( prof->current_state[prof->flip] != prof->read_state )\r\n//\t\t{\r\n//\t\t\tprof->time[prof->flip][prof->current_offset[prof->flip]] = s_count*(vHIREZ_CMP/150); \r\n//\t\t\tprof->current_state[prof->flip] = prof->read_state;\r\n//\t\t\tprof->state[prof->flip][prof->current_offset[prof->flip]++] = prof->read_state;\r\n//\t\t}\r\n//#endif\r\n//    }\r\n//#else\r\n//    if (( ca == INTC_TIM0 ) && ( *T0_MODE & 0x800 ))  // overflow interrupt\r\n//    {\r\n//        *T0_MODE \t |= 0x800; \t// clear overflow\r\n//        s_count += 0x10000;\r\n//    }\r\n//#endif\r\n//\r\n//\r\n//    ExitHandler();\t\t\t// Mick: Sony requires interrupts to end with an ExitHandler() call\r\n//\t\t\t\t\t\t\t// this enables interrupts\r\n//    return 0;\r\n//}\r\n//\r\nstatic \tsint \ts_vsync_handler_id = -1;\r\n\r\n// This is called from the NGC post vblank callback, installed in p_display.cpp.\r\nvoid IncrementVblankCounters( void )\r\n{\r\n\t// inc vblanks    \r\n\ts_vblank++;\r\n\ts_total_vblanks++;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Init( void )\r\n{\r\n\tInitTimerInfo();\r\n\t\r\n//\ts_timer_handler_id = AddIntcHandler ( INTC_TIM0, timer_handler, 0 );\r\n\ts_timer_handler_id = 0;\r\n\tDbg_MsgAssert (( s_timer_handler_id >= 0 ),( \"Failed to add timer handler\" )); \r\n\r\n\t// The vsync callback is actually set up in p_display.cpp.\r\n//\ts_vsync_handler_id = AddIntcHandler ( INTC_VBLANK_S, s_vsync_handler, 0 );\r\n\ts_vsync_handler_id = 1;\r\n\tDbg_MsgAssert (( s_vsync_handler_id >= 0 ),( \"Failed to add vsync handler\" )); \r\n\t\t\r\n\ts_count\t= 0;\r\n//\t*T0_COUNT \t= 0;\r\n//\t*T0_COMP \t= vHIREZ_CMP;\t// used for hi-res counter (micro-second interrupt)\r\n//\t*T0_HOLD \t= 0;\r\n    \r\n#\tifdef __NOPT_PROFILE__\r\n\ts_count = 0;\r\n//    *T0_MODE \t= 0xc80; // clear overflow and equal flag\r\n//    *T0_MODE \t= 0x180; // compare int enabled, start clock, speed 150MHz\r\n#\telse\r\n//    *T0_MODE \t= 0xc81; // clear overflow and equal flag\r\n//    *T0_MODE \t= 0x281; // overflow int enabled, start clock, speed 150Mhz/16\r\n#\tendif\r\n\r\n//\tEnableIntc ( INTC_TIM0 );\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid DeInit(void)\r\n{\r\n\tDbg_MsgAssert (( s_timer_handler_id >= 0 ),( \"Invalid Timer Handler (%d)\", s_timer_handler_id )); \r\n\t\r\n//\tDisableIntc ( INTC_TIM0 );\r\n//    RemoveIntcHandler ( INTC_TIM0, s_timer_handler_id );\r\n//\r\n//\tDbg_MsgAssert (( s_vsync_handler_id >= 0 ),( \"Invalid VSync Handler (%d)\", s_vsync_handler_id )); \r\n//    RemoveIntcHandler ( INTC_VBLANK_S, s_vsync_handler_id );\r\n\r\n\ts_timer_handler_id = -1;\r\n\ts_vsync_handler_id = -1;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// when pausing the game, call this to store the current state of OncePerRender( ) (only essential in replay mode)\r\nvoid StoreTimerInfo( void )\r\n{\r\n\t//if ( Replay::GetReplayMode( ) == Replay::REPLAY_MODE_OFF )\r\n\t//{\r\n\t//\treturn;\r\n\t//}\r\n\t//gStoredTimerInfo = gTimerInfo;\r\n\t//s_stored_vblank = s_vblank;\r\n}\r\n\r\n\r\n\r\nvoid RecallTimerInfo( void )\r\n{\r\n\t/*if ( Replay::GetReplayMode( ) == Replay::REPLAY_MODE_OFF )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tgTimerInfo = gStoredTimerInfo;\r\n\ts_vblank = s_stored_vblank;\r\n\tif ( Replay::GetReplayMode( ) & ( Replay::REPLAY_MODE_PLAY_SAVED | Replay::REPLAY_MODE_PLAY_AFTER_RUN ) )\r\n\t{\r\n\t\ts_vblank += Replay::GetLastFrameLength();\r\n\t}*/\r\n}\r\n\r\n// Call this function once per rendering loop, to increment the \r\n// m_render_frame variable\r\n// This function should be synchronized in some way to the vblank, so that it is called \r\n// directly after the vblank that rendering starts on\r\nvoid OncePerRender()\r\n{\r\n//\tVblank();\r\n\r\n\ts_render_frame++;\r\n\t\r\n\t#ifdef STOPWATCH_STUFF\r\n\tScript::IncrementStopwatchFrameIndices();\r\n\tScript::DumpFunctionTimes();\r\n\tScript::ResetFunctionCounts();\t\r\n\t#endif\r\n\t\r\n\tint diff;\r\n\tgTimerInfo.render_last_vblank = gTimerInfo.render_vblank;\r\n\t\r\n\t/*\r\n\tReplay::ReplayMode replayMode;\r\n\treplayMode = Replay::GetReplayMode( );\r\n\tif ( replayMode & ( Replay::REPLAY_MODE_PLAY_SAVED | Replay::REPLAY_MODE_PLAY_AFTER_RUN ) )\r\n\t{\r\n\t\tdiff = Replay::GetFrameLength( );\r\n\t\tgTimerInfo.render_vblank += diff;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgTimerInfo.render_vblank = GetGameVblanks();\r\n\t\tdiff = (int)(gTimerInfo.render_vblank - gTimerInfo.render_last_vblank);\r\n\t\tif ( Replay::REPLAY_MODE_RECORD == replayMode )\r\n\t\t{\r\n\t\t\tif ( Replay::FixSmoothing( ) ) // the 'smoothing' feature will fuck up our logic if,\r\n\t\t\t\t\t\t\t\t\t\t\t// during replay, there is a framerate difference\r\n\t\t\t\t\t\t\t\t\t\t\t// between the initial frames of play/record before\r\n\t\t\t\t\t\t\t\t\t\t\t// getting our data synced up.\r\n\t\t\t{\r\n\t\t\t\tdiff = 1;  // keep it at 60 hz before synchronization.\r\n\t\t\t}\r\n\t\t\tReplay::StoreFrameLength( diff );\r\n\t\t}\r\n\t}\r\n\t*/\r\n\tgTimerInfo.render_vblank = GetGameVblanks();\r\n\tdiff = (int)(gTimerInfo.render_vblank - gTimerInfo.render_last_vblank);\r\n\r\n\t\r\n\tgTimerInfo.render_buffer[ gTimerInfo.render_index++] = diff;\r\n\tif ( gTimerInfo.render_index == vSMOOTH_N)\r\n\t{\r\n\t\tgTimerInfo.render_index = 0;\t\t\r\n\t}\r\n\tint total = 0;\r\n\tint uncapped_total = 0;\r\n\tfor (int i=0;i<vSMOOTH_N;i++)\r\n\t{\r\n\t\t\r\n\t\tdiff = gTimerInfo.render_buffer[i];\r\n\t\tuncapped_total += diff;\r\n\t\tif (diff > 10 || diff <= 1)\t\t// handle very bad values\r\n\t\t{\r\n\t\t\tdiff = 1;\r\n\t\t}\r\n\t\tif (diff >4) \t\t\t\t\t// limit to 4\r\n\t\t{\r\n\t\t\tdiff = 4;\r\n\t\t}\t\t\r\n\t\ttotal += diff;\r\n\t}\r\n\tgTimerInfo.render_length = (float)total/(float)vSMOOTH_N; \r\n\tgTimerInfo.uncapped_render_length = (double)uncapped_total/(double)vSMOOTH_N; \r\n\tgTimerInfo.frame_length = gTimerInfo.render_length/(float)Config::FPS()*GetSlomo();\r\n\t\r\n\t\r\n//\tprintf (\"%d:  %d, %f\\n\",(int)GetRenderFrame(),diff, gTimerInfo.render_length);\r\n\t\r\n}\r\n\r\n\r\n\r\nuint64 GetRenderFrame()\r\n{\r\n\treturn s_render_frame;\r\n}\r\n\r\n\r\nvoid Vblank()\r\n{\r\n\ts_total_vblanks++;\r\n\ts_vblank++;\r\n}\r\n\r\nstatic uint64 GetGameVblanks()\r\n{\r\n\treturn s_vblank;\r\n}\r\n\r\nuint64 GetVblanks( void )\r\n{\r\n\treturn ( s_total_vblanks );\r\n}\r\n\r\n// call \"StartLogic\" when all the logic functions are going to be called  \r\n//void Manager::StartLogic()\r\n//{\r\n//}\r\n\r\n// returns the PROJECTED length of the next frame, for use in logic calculations\r\n// done by averaging the frame lengths of the last N frames (default N = 4)\r\n// at 60fps (NTSC), this would return 1/60\r\n// at 50fps (PAL), this would return 1/50\t\t   \r\n// complications arise when the framerate changes\r\n// we want the physics to move smoothly and consistently at all framerates\r\n// however, all we know is the number of ticks the last frames took\r\n// we also need to ensure that the total of all the \"FrameLength\" calls will\r\n// reflect the actual time that has passed\r\n//\t\t\t\t |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |   |    |   \r\n// say we have   1    1    1    .    2    1    1    1    .    2    1    .    2    1    1    1   .    2 \r\n//    (10x1 + 4x2  = 18 frames\r\n//\r\n//\r\n// now, let's work in 1/60ths of a second for now....\r\n// let's take the average of the last 4 frames, as the logic time we will return for this frame\r\n//\r\n//               1    1    1         1.25 1.25 1.25 1.25     1.25 1.25      1.5  1.5  1.25 1.25     1.25\r\n//\r\n// the reason we do the averaging is to smooth out discontinuities\r\n// if we simply use the length of the previous frame, then if we were to be alternating between 1 and 2 frames\r\n// then the logic would move 2 on frames of length 1, and move 1 on frames of length 2\r\n// this would essentially make the skater visually move alternately .5x and 2x his actual speed\r\n// this looks incredibly jerky, as there is a 4x difference per frame   \r\n// by smoothing it out, you would move 1.5 on every frame, giving relative motion of 0.6666 and 1.3333, \r\n// this is still jerky, but half as much as the unsmoothed version.\r\n \r\nfloat FrameLength()\r\n{\r\n\r\n\treturn gTimerInfo.frame_length;\r\n\r\n//\tif ( VIGetTvFormat() == VI_PAL ) {\r\n//\t\treturn gTimerInfo.render_length / 50.0f * GetSlomo();\r\n//\t} else {\r\n//\t\treturn gTimerInfo.render_length / 60.0f * GetSlomo();\r\n//\t}\r\n}\r\n\r\n\r\nfloat GetSlomo()\r\n{\r\n\treturn s_slomo;\r\n}\r\n\r\nvoid SetSlomo(float slomo)\r\n{\r\n\ts_slomo = slomo;\r\n}\r\n\r\ndouble UncappedFrameLength()\r\n{\r\n\treturn gTimerInfo.uncapped_render_length/(float)Config::FPS();\r\n\r\n\r\n//\tif ( VIGetTvFormat() == VI_PAL ) {\r\n//\t\treturn gTimerInfo.uncapped_render_length / 50.0f;\r\n//\t} else {\r\n//\t\treturn gTimerInfo.uncapped_render_length / 60.0f;\r\n//\t}\r\n}\r\n\r\n\r\n\r\nuint64 now;\r\n\r\nvoid VSync()\r\n{\r\n\tnow = GetVblanks();\r\n\twhile (now == GetVblanks());\t\r\n}\r\n \r\n\r\n// wait until VSync changes from what it was\r\n// (Might return immediately, if it's already changed)\r\nvoid VSync1()\r\n{\r\n\twhile (now == GetVblanks());\t\r\n\tnow = GetVblanks();\r\n\ts_milliseconds = (Time) (((float)(uint32)s_vblank)*(1000.0f / (float)Config::FPS()));\r\n}\r\n\r\n//#ifdef __NOPT_PROFILE__\r\n\r\nMicroSeconds \tGetTimeInUSeconds ( void )\r\n{\r\n//\tuint64\thigh0, low0, high1, low1;\r\n//\r\n//    high0 = s_count;\r\n//    low0  = 0;\t//*T0_COUNT;\r\n//    high1 = s_count;\r\n//    low1  = 0;\t//*T0_COUNT;\r\n//\r\n//\r\n//    if ( high0 == high1 )\r\n//    {\r\n//\t\treturn ((high0 * vHIREZ_CMP) + low0)/150;\r\n//    }\r\n//    else\r\n//    {\r\n//\t\treturn ((high1 * vHIREZ_CMP) + low1)/150;\r\n//    }\r\n//\r\n\r\n\tOSTime time = OSGetTime();\r\n\treturn OSTicksToMicroseconds(time);\r\n}\r\n\r\n// Added by Ken, to get higher resolution when timing Script::Update, which needs to\r\n// subtract out the time spent in calling C-functions to get an accurate measurement\r\n// of how long the actual script interpretation is taking.\r\nCPUCycles \tGetTimeInCPUCycles ( void )\r\n{\r\n\tuint64\thigh0, low0, high1, low1;\r\n\r\n    high0 = s_count;\r\n    low0  = 0;\t//*T0_COUNT;\r\n    high1 = s_count;\r\n    low1  = 0;\t//*T0_COUNT;\r\n\r\n\r\n    if ( high0 == high1 )\r\n    {\r\n\t\treturn ((high0 * vHIREZ_CMP) + low0);\r\n    }\r\n    else\r\n    {\r\n\t\treturn ((high1 * vHIREZ_CMP) + low1);\r\n    }\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid RestartClock( void )\r\n{\r\n\tInitTimerInfo( );\r\n}\r\n\r\n\r\nTime\tGetTime ( void )\r\n{\r\n\t//return ( GetTimeInUSeconds() / 1000 );\r\n\t//return s_count;\r\n\t// A less accurate time, but much faster than doing a 64 bit divide.\r\n\t//return ((int)s_vblank)*1000/60;\r\n\t\r\n\t// E3 fix by Ken: Changed to do it this way because otherwise the multiply by 1000 overflows after a day or so.\r\n\t// By using 50/3 instead, and using a float, means it'll overflow after about 50 days instead.\r\n\t// The accuracy will slowly degrade over time. Stays accurate to within a few milliseconds after a week though.\r\n\t// Note: The casting of s_vblank (which is a uint64) to a uint32 before casting to a float is important. If the\r\n\t// uint64 is cast straight to a float it will do tons of floating point stuff which take ages.\r\n\treturn (int) (((float)(uint32)s_vblank)*(1000.0f / (float)Config::FPS()));\r\n\t/*\r\n\tif ( Replay::UseNormalClock( ) )\r\n\t{\r\n\t\treturn (uint32) (((float)(uint32)s_vblank)*50.0f/3.0f);\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn (uint32) (((float)(uint32)gTimerInfo.render_vblank )*50.0f/3.0f);\r\n\t}*/\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n//#else // __NOPT_PROFILE__\r\n//\r\n//#ifdef __USER_MATT__\r\n//#error Wrong Motherfuckin Timer\r\n//#endif\r\n//\r\n//Time\tManager::GetTime ( void )\r\n//{\r\n//\tuint64\thigh0, low0, high1, low1;\r\n//\r\n//    high0 = s_count;\r\n//    low0  = *T0_COUNT;\r\n//    high1 = s_count;\r\n//    low1  = *T0_COUNT;\r\n//\r\n//    if ( high0 == high1 )\r\n//    {\r\n//\t\treturn static_cast<uint64>(( high0 | ( low0 & 0xffff )) / 9375 );\r\n//    }\r\n//    else\r\n//    {\r\n//\t\treturn static_cast<uint64>(( high1 | ( low1 & 0xffff )) / 9375 );\r\n//    }\r\n//}\r\n//\r\n///******************************************************************/\r\n///*                                                                */\r\n///*                                                                */\r\n///******************************************************************/\r\n// \r\n//Time\tGetTimeInUSeconds ( void )\t   // remove ?\r\n//{\r\n//\tuint64\thigh0, low0, high1, low1;\r\n//\r\n//    high0 = s_count;\r\n//    low0  = *T0_COUNT;\r\n//    high1 = s_count;\r\n//    low1  = *T0_COUNT;\r\n//\r\n//    if ( high0 == high1 )\r\n//    {\r\n//\t\treturn static_cast<uint64>(( high0 + ( low0 & 0xffff )) / 9 );\r\n//    }\r\n//    else\r\n//    {\r\n//\t\treturn static_cast<uint64>(( high1 + ( low1 & 0xffff )) / 9 );\r\n//    }\r\n//}\r\n//#endif // __NOPT_PROFILE__\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Tmr\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_triangle.cpp",
    "content": "///********************************************************************************\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tnsTriangle\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tMatrix functionality.\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n// *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//#include <math.h>\r\n//#include <string.h>\r\n//#include \"p_triangle.h\"\r\n//\r\n///********************************************************************************\r\n// * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n///********************************************************************************\r\n// * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n// ********************************************************************************/\r\n//\r\n//NsTriangle::NsTriangle()\r\n//{\r\n//\tm_corner[0].set( 0.0f, 0.0f, 0.0f );\r\n//\tm_corner[1].set( 0.0f, 0.0f, 0.0f );\r\n//\tm_corner[2].set( 0.0f, 0.0f, 0.0f );\r\n//}\r\n//\r\n//NsTriangle::NsTriangle( NsVector * pCorner0, NsVector * pCorner1, NsVector * pCorner2 )\r\n//{\r\n//\tset( pCorner0, pCorner1, pCorner2 );\r\n//}\r\n//\r\n//void NsTriangle::set( NsVector * pCorner0, NsVector * pCorner1, NsVector * pCorner2 )\r\n//{\r\n//\tm_corner[0].copy( *pCorner0 );\r\n//\tm_corner[1].copy( *pCorner1 );\r\n//\tm_corner[2].copy( *pCorner2 );\r\n//}\r\n//\r\n//NsTriangle::NsTriangle( float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2 )\r\n//{\r\n//\tset( x0, y0, z0, x1, y1, z1, x2, y2, z2 );\r\n//}\r\n//\r\n//void NsTriangle::set( float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2 )\r\n//{\r\n//\tm_corner[0].set( x0, y0, z0 );\r\n//\tm_corner[1].set( x1, y1, z1 );\r\n//\tm_corner[2].set( x2, y2, z2 );\r\n//}\r\n//\r\n//void NsTriangle::translate ( NsVector * pTrans )\r\n//{\r\n//\tm_corner[0].add( *pTrans );\r\n//\tm_corner[1].add( *pTrans );\r\n//\tm_corner[2].add( *pTrans );\r\n//}\r\n//\r\n//int NsLine::intersectTriangle( float * distance, NsTriangle * pTriangle )\r\n//{\r\n//#define INTERSECT_EPSILON (float)(1e-8)\r\n//#define INTERSECT_EDGE (float)(1e-5)\r\n//\r\n//    NsVector\tedge1, edge2, tVec, pVec, qVec;\r\n//    float\t\tdet;\r\n//\tNsVector\tlinedelta;\r\n//\tbool\t\tresult;\r\n//\r\n//\t// Generate line delta\r\n//\tlinedelta.sub( end, start );\r\n//\r\n//    /* Find vectors for two edges sharing vert0 */\r\n//\tedge1.sub( *pTriangle->corner(1), *pTriangle->corner(0) );\r\n//\tedge2.sub( *pTriangle->corner(2), *pTriangle->corner(0) );\r\n//\r\n//    /* Begin calculating determinant\r\n//     * - also used to calculate U parameter */\r\n//\tpVec.cross( linedelta, edge2 );\r\n//\r\n//    /* If determinant is\r\n//     * + near zero, ray lies in plane of\r\n//     *   triangle\r\n//     * + negative, triangle is backfacing\r\n//     */\r\n//    det = edge1.dot( pVec );\r\n//    result = (det > INTERSECT_EPSILON);\r\n//\r\n//    if ( result )\r\n//    {\r\n//        float  lo, hi, u;\r\n//\r\n//        /* Calculate bounds for parameters with tolerance */\r\n//        lo = - det*INTERSECT_EDGE;\r\n//        hi = det - lo;\r\n//\r\n//        /* Calculate U parameter and test bounds */\r\n//\t\ttVec.sub( start, *pTriangle->corner(0) );\r\n//\t    u = tVec.dot( pVec );\r\n//        result =  (u >= lo && u <= hi);\r\n//\r\n//        if ( result )\r\n//        {\r\n//            float  v;\r\n//\r\n//            /* Calculate V parameter and test bounds */\r\n//\t\t\tqVec.cross( tVec, edge1 );\r\n//\t\t    v = qVec.dot( linedelta );\r\n//            result = (v >= lo && (u + v) <= hi);\r\n//\r\n//            if ( result )\r\n//            {\r\n//                /* Calculate t,\r\n//                 * and make sure intersection is in bounds of line */\r\n//                *distance = qVec.dot( edge2 );\r\n//\r\n//                /* Within bounds of line? */\r\n//                result = (*distance >= lo && *distance <= hi);\r\n//\r\n//                if ( result )\r\n//                {\r\n//                    *distance = *distance / det;\r\n//                }\r\n//            }\r\n//        }\r\n//    }\r\n//\treturn result;\r\n//}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_triangle.h",
    "content": "//#ifndef _TRIANGLE_H_\r\n//#define _TRIANGLE_H_\r\n//\r\n//#include \"p_hw.h\"\r\n//#include \"p_matrix.h\"\r\n//\r\n//class NsTriangle\r\n//{\r\n//\tNsVector\tm_corner[3];\r\n//public:\r\n//\t\t\t\tNsTriangle\t();\r\n//\t\t\t\tNsTriangle\t( NsVector * pCorner0, NsVector * pCorner1, NsVector * pCorner2 );\r\n//\t\t\t\tNsTriangle\t( float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2 );\r\n//\r\n//\tvoid\t\ttranslate\t( NsVector * pTrans );\r\n//\r\n//\tvoid\t\tset\t\t\t( NsVector * pCorner0, NsVector * pCorner1, NsVector * pCorner2 );\r\n//\tvoid\t\tset\t\t\t( float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2 );\r\n//\r\n//\tNsVector  * corner\t\t( int c ) { return &m_corner[c]; }\r\n//};\r\n//\r\n//class NsLine\r\n//{\r\n//public:\r\n//\tNsVector\tstart;\r\n//\tNsVector\tend;\r\n//\r\n//\tint\t\tintersectTriangle\t( float * distance, NsTriangle * pTriangle );\r\n//};\r\n//\r\n//typedef struct {\r\n//\tNsVector\tcenter;\r\n//\tfloat\t\tradius;\r\n//} NsSphere;\r\n//\r\n//#endif\t\t// _TRIANGLE_H_\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_vector.cpp",
    "content": "/********************************************************************************\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tModule:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tNsVector\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tDescription:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tMatrix functionality.\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tWritten by:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\tPaul Robinson\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\tCopyright:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n *\t\t\t\t2001 Neversoft Entertainment - All rights reserved.\t\t\t\t*\r\n *\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Includes.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n#include <math.h>\r\n#include <string.h>\r\n#include \"p_matrix.h\"\r\n\r\n/********************************************************************************\r\n * Defines.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Structures.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Local variables.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Forward references.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\n/********************************************************************************\r\n * Externs.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\r\n ********************************************************************************/\r\n\r\nNsVector::NsVector()\r\n{\r\n\tset( 0.0f, 0.0f, 0.0f );\r\n}\r\n\r\nNsVector::NsVector( float sx, float sy, float sz )\r\n{\r\n\tset( sx, sy, sz );\r\n}\r\n\r\nvoid NsVector::add ( NsVector& a )\r\n{\r\n\tVECAdd( (Vec*)this, (Vec*)&a, (Vec*)this );\r\n}\r\n\r\nvoid NsVector::add ( NsVector& a, NsVector& b )\r\n{\r\n\tVECAdd( (Vec*)&a, (Vec*)&b, (Vec*)this );\r\n}\r\n\r\nvoid NsVector::cross ( NsVector& a )\r\n{\r\n\tVECCrossProduct( (Vec*)this, (Vec*)&a, (Vec*)this );\r\n}\r\n\r\nvoid NsVector::cross ( NsVector& a, NsVector& b )\r\n{\r\n\tVECCrossProduct( (Vec*)&a, (Vec*)&b, (Vec*)this );\r\n}\r\n\r\nfloat NsVector::length ( void )\r\n{\r\n\treturn VECMag( (Vec*)this );\r\n}\r\n\r\nfloat NsVector::distance ( NsVector& a )\r\n{\r\n\treturn VECDistance( (Vec*)this, (Vec*)&a );\r\n}\r\n\r\nfloat NsVector::dot ( NsVector& a )\r\n{\r\n\treturn VECDotProduct( (Vec*)this, (Vec*)&a );\r\n}\r\n\r\nvoid NsVector::normalize ( void )\r\n{\r\n\tVECNormalize( (Vec*)this, (Vec*)this );\r\n}\r\n\r\nvoid NsVector::normalize ( NsVector& a )\r\n{\r\n\tVECNormalize( (Vec*)&a, (Vec*)this );\r\n}\r\n\r\nvoid NsVector::reflect ( NsVector& normal )\r\n{\r\n\tVECReflect( (Vec*)this, (Vec*)&normal, (Vec*)this );\r\n}\r\n\r\nvoid NsVector::reflect ( NsVector& a, NsVector& normal )\r\n{\r\n\tVECReflect( (Vec*)&a, (Vec*)&normal, (Vec*)this );\r\n}\r\n\r\nvoid NsVector::scale ( float scale )\r\n{\r\n\tVECScale( (Vec*)this, (Vec*)this, scale );\r\n}\r\n\r\nvoid NsVector::scale ( NsVector& a, float scale )\r\n{\r\n\tVECScale( (Vec*)&a, (Vec*)this, scale );\r\n}\r\n\r\nvoid NsVector::sub ( NsVector& a )\r\n{\r\n\tVECSubtract( (Vec*)this, (Vec*)&a, (Vec*)this );\r\n}\r\n\r\nvoid NsVector::sub ( NsVector& a, NsVector& b )\r\n{\r\n\tVECSubtract( (Vec*)&a, (Vec*)&b, (Vec*)this );\r\n}\r\n\r\nvoid NsVector::lerp\t( NsVector& a, NsVector& b, float t )\r\n{\r\n\tNsVector res;\r\n\tres.sub( b, a );\r\n\tres.scale( t );\r\n\tres.add( a );\r\n\tset( res.x, res.y, res.z );\r\n}\r\n"
  },
  {
    "path": "Code/Sys/ngc/p_vector.h",
    "content": "#ifndef _VECTOR_H_\r\n#define _VECTOR_H_\r\n\r\n#include <dolphin.h>\r\n\r\nclass NsVector\r\n{\r\npublic:\r\n\tfloat\tx;\r\n\tfloat\ty;\r\n\tfloat\tz;\r\n\r\n\t\t\tNsVector\t();\r\n\t\t\tNsVector\t( float sx, float sy, float sz );\r\n\r\n\tvoid\tadd\t\t\t( NsVector& a );\r\n\tvoid\tadd\t\t\t( NsVector& a, NsVector& b );\r\n\tvoid\tcross\t\t( NsVector& a );\r\n\tvoid\tcross\t\t( NsVector& a, NsVector& b );\r\n\tfloat\tlength\t\t( void );\r\n\tfloat\tdistance\t( NsVector& a );\r\n\tfloat\tdot\t\t\t( NsVector& a );\r\n\tvoid\tnormalize\t( void );\r\n\tvoid\tnormalize\t( NsVector& a );\r\n\tvoid\treflect\t\t( NsVector& normal );\r\n\tvoid\treflect\t\t( NsVector& a, NsVector& normal );\r\n\tvoid\tscale\t\t( float scale );\r\n\tvoid\tscale\t\t( NsVector& a, float scale );\r\n\tvoid\tsub\t\t\t( NsVector& a );\r\n\tvoid\tsub\t\t\t( NsVector& a, NsVector& b );\r\n\tvoid\tlerp\t\t( NsVector& a, NsVector& b, float t );\r\n\r\n\tvoid\tset\t\t\t( float sx, float sy, float sz ) { x = sx; y = sy; z = sz; }\r\n\r\n\tvoid\tcopy\t\t( NsVector& pSource ) { x = pSource.x; y = pSource.y; z = pSource.z; }\r\n};\r\n\r\n#endif\t\t// _VECTOR_H_\r\n"
  },
  {
    "path": "Code/Sys/ngps/p_timer.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTimer (TMR)\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tngps/p_timer.cpp\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t01/13/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tNGPS System Timer\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <eeregs.h>\r\n#include <sys/timer.h>\r\n#include <sys/profiler.h>\r\n#include <gel/scripting/script.h>\r\n#include <sys/config/config.h>\r\n\r\n\r\n#ifdef TESTING_REPLAY\r\nstatic volatile uint64 s_num_game_renders = 0;\r\nuint64 GameRenders( void )\r\n{\r\n\treturn ( s_num_game_renders );\r\n}\r\n#endif\r\n\r\n\r\n//uint32\ts_ints;\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Tmr \r\n{\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nstatic \t\t\tsint \ts_timer_handler_id = -1;\r\n\r\n\r\n#ifdef\t\t__USE_PROFILER__\t\t\t\r\nstatic volatile uint64\ts_count;\r\n// K: This is a uint32 version of s_count, used by the now inline function GetTimeInCPUCycles\r\n// defined in timer.h\r\nvolatile uint32\tgCPUTimeCount;\r\n#endif\r\n\r\nstatic uint64 GetGameVblanks( void );\r\n\r\n#define\tvSMOOTH_N  4\t\r\n\r\nvolatile uint32  \t\t\t\ts_vblank = 0;\t\t\t\t// updated every vblanks under intrrupts\r\nTime  \t\t\t\t\t\t\ts_milliseconds = 0;\t\t\t// updated every call to VSync() or VSync1()\r\nstatic volatile uint64 \t\t\ts_total_vblanks = 0;\r\n\r\nstatic float s_slomo = 1.0f;\r\nstatic  uint64\ts_render_frame = 0;\t\r\nstatic uint64 s_stored_vblank = 0;\r\n\r\nstruct STimerInfo\r\n{\r\n\tfloat\trender_length;\r\n\tfloat\tframe_length;\r\n\tdouble\tuncapped_render_length;\r\n\tint\t\trender_buffer[vSMOOTH_N];\r\n\tuint32\trender_vblank;\r\n\tuint32\trender_last_vblank;\t\r\n\tint\t\trender_index;\r\n};\r\n\r\nstatic STimerInfo gTimerInfo;\r\nstatic STimerInfo gStoredTimerInfo;\r\n\r\nstatic void InitTimerInfo( void )\r\n{\r\n\tint i;\r\n\tgTimerInfo.render_length \t\t\t= 1;\t\t\t\t// defualt to 1 frame, so 60/50 fps\r\n\tgTimerInfo.frame_length \t\t\t= 1.0f/60.0f;\t\t// default to 1/60th, will be correct after first frame is rendered\r\n\tgTimerInfo.uncapped_render_length \t= 1;\t\t\t\t// default to 1 (uncappe is used by network code)\r\n\tfor ( i = 0; i < vSMOOTH_N; i++ )\r\n\t{\r\n\t\tgTimerInfo.render_buffer[ i ] = 1;\r\n\t}\r\n\tgTimerInfo.render_vblank = 0;\t\r\n\tgTimerInfo.render_last_vblank = 0;\r\n\tgTimerInfo.render_index = 0;\r\n\r\n\tgStoredTimerInfo = gTimerInfo;\r\n\r\n\ts_stored_vblank = 0;\r\n\ts_vblank = 0;\r\n#ifdef TESTING_REPLAY\t\r\n\ts_num_game_renders = 0;\r\n#endif\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef\t\t__USE_PROFILER__\t\t\t\r\n\r\nstatic sint timer_handler ( sint ca )\r\n{\r\n\r\n//\ts_ints++;\r\n\r\n#if 1\r\n    if (( ca == INTC_TIM0 ) && ( *T0_MODE & 0x400 ))  // compare interrupt\r\n    {\r\n        *T0_COUNT\t= 0;\t\t// reset s_count\r\n        *T0_MODE\t|= 0x400; \t// clear compare flag\r\n\t\ts_count++;\r\n\t\t++gCPUTimeCount;\r\n    }\r\n#else\r\n    if (( ca == INTC_TIM0 ) && ( *T0_MODE & 0x800 ))  // overflow interrupt\r\n    {\r\n        *T0_MODE \t |= 0x800; \t// clear overflow\r\n        s_count += 0x10000;\r\n    }\r\n#endif\r\n\r\n\r\n    ExitHandler();\t\t\t// Mick: Sony requires interrupts to end with an ExitHandler() call\r\n\t\t\t\t\t\t\t// this enables interrupts\r\n    return 0;\r\n}\r\n#endif\r\n\r\nstatic \tsint \ts_vsync_handler_id = -1;\r\n\r\nstatic sint s_vsync_handler ( sint ca )\r\n{\r\n\t// Warning! Don't do any floating point calculations here, or game will crash,\r\n\t// cos interrupt handlers are strange that way.\r\n\t// Also, if writing to a variable, make sure it is volatile (or game will crash)\r\n\t\r\n\t// inc vblanks    \r\n\ts_vblank++;\r\n\ts_total_vblanks++;\r\n\r\n\tExitHandler();\t\t\t// Mick: Sony requires interrupts to end with an ExitHandler() call\r\n\t\t\t\t\t\t\t// this enables interrupts\t\r\n\treturn 0;\r\n}\r\n\r\n\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid Init( void )\r\n{\r\n\t\r\n\t\t  \r\n\t\t  \r\n\t\r\n\tInitTimerInfo( );\r\n\r\n\t\r\n#ifdef\t\t__USE_PROFILER__\t\t\t\r\n\ts_timer_handler_id = AddIntcHandler ( INTC_TIM0, timer_handler, 0 );\r\n\tDbg_MsgAssert (( s_timer_handler_id >= 0 ),( \"Failed to add timer handler\" )); \r\n#endif\r\n\r\n\ts_vsync_handler_id = AddIntcHandler ( INTC_VBLANK_S, s_vsync_handler, 0 );\r\n\tDbg_MsgAssert (( s_vsync_handler_id >= 0 ),( \"Failed to add vsync handler\" )); \r\n\r\n\t\t\r\n#ifdef\t\t__USE_PROFILER__\t\t\t\r\n\ts_count\t= 0;\r\n    *T0_COUNT \t= 0;\r\n\t*T0_COMP \t= vHIREZ_CMP;\t// used for hi-res counter (milli-second interrupt)\r\n\t*T0_HOLD \t= 0;\r\n #if\t1\r\n\ts_count = 0;\r\n\tgCPUTimeCount = 0;\r\n    *T0_MODE \t= 0xc80; // clear overflow and equal flag\r\n    *T0_MODE \t= 0x180; // compare int enabled, start clock, speed 150MHz\r\n #else\r\n    *T0_MODE \t= 0xc81; // clear overflow and equal flag\r\n    *T0_MODE \t= 0x281; // overflow int enabled, start clock, speed 150Mhz/16\r\n #endif\r\n    EnableIntc ( INTC_TIM0 );\r\n#endif\r\n    \r\n\tEnableIntc ( INTC_VBLANK_S );\r\n\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid DeInit(void)\r\n{\r\n\t\r\n   \r\n#ifdef\t\t__USE_PROFILER__\t\t\t\r\n\tDbg_MsgAssert (( s_timer_handler_id >= 0 ),( \"Invalid Timer Handler (%d)\", s_timer_handler_id )); \r\n\tDisableIntc ( INTC_TIM0 );\r\n    RemoveIntcHandler ( INTC_TIM0, s_timer_handler_id );\r\n#endif\r\n\r\n\tDbg_MsgAssert (( s_vsync_handler_id >= 0 ),( \"Invalid VSync Handler (%d)\", s_vsync_handler_id )); \r\n    RemoveIntcHandler ( INTC_VBLANK_S, s_vsync_handler_id );\r\n\r\n\ts_timer_handler_id = -1;\r\n}\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// when pausing the game, call this to store the current state\r\n// of OncePerRender( ) (only essential in replay mode)\r\nvoid StoreTimerInfo( void )\r\n{\r\n\t//if ( Replay::GetReplayMode( ) == Replay::REPLAY_MODE_OFF )\r\n\t//{\r\n\t//\treturn;\r\n\t//}\r\n\t\r\n\t//gStoredTimerInfo = gTimerInfo;\r\n\t//s_stored_vblank = s_vblank;\r\n}\r\n\r\nvoid RecallTimerInfo( void )\r\n{\r\n\t/*if ( Replay::GetReplayMode( ) == Replay::REPLAY_MODE_OFF )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tgTimerInfo = gStoredTimerInfo;\r\n\ts_vblank = s_stored_vblank;\r\n\tif ( Replay::GetReplayMode( ) & ( Replay::REPLAY_MODE_PLAY_SAVED | Replay::REPLAY_MODE_PLAY_AFTER_RUN ) )\r\n\t{\r\n\t\ts_vblank += Replay::GetLastFrameLength( );\r\n\t}*/\r\n}\r\n\r\n// Call this function once per rendering loop, to increment the \r\n// m_render_frame variable\r\n// This function should be synchronized in some way to the vblank, so that it is called \r\n// directly after the vblank that rendering starts on\r\nvoid\tOncePerRender()\r\n{\r\n\t\r\n\ts_render_frame++;\r\n\t\r\n//\tprintf (\"%d ints/second\\n\", s_ints * 60 / s_vblank);\r\n\t\r\n\t\r\n\t#ifdef TESTING_REPLAY\r\n\tif ( s_num_game_renders < 5 )\r\n\t{\r\n\t\tDbg_Message( \"** OncePerRender %d **\", s_num_game_renders );\r\n\t}\r\n\ts_num_game_renders++;\r\n\t#endif\r\n\t\r\n\t#ifdef STOPWATCH_STUFF\r\n\tScript::IncrementStopwatchFrameIndices();\r\n\tScript::DumpFunctionTimes();\r\n\tScript::ResetFunctionCounts();\t\r\n\t#endif\r\n\t\r\n\tint diff;\r\n\tgTimerInfo.render_last_vblank = gTimerInfo.render_vblank;\r\n\r\n\t/*\t\r\n\tReplay::ReplayMode replayMode;\r\n\treplayMode = Replay::GetReplayMode( );\r\n\tif ( replayMode & ( Replay::REPLAY_MODE_PLAY_SAVED | Replay::REPLAY_MODE_PLAY_AFTER_RUN ) )\r\n\t{\r\n\t\tdiff = Replay::GetFrameLength( );\r\n\t\tgTimerInfo.render_vblank += diff;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgTimerInfo.render_vblank = GetGameVblanks();\r\n\t\tdiff = (int)(gTimerInfo.render_vblank - gTimerInfo.render_last_vblank);\r\n\t\tif ( Replay::REPLAY_MODE_RECORD == replayMode )\r\n\t\t{\r\n\t\t\tif ( Replay::FixSmoothing( ) ) // the 'smoothing' feature will fuck up our logic if,\r\n\t\t\t\t\t\t\t\t\t\t\t// during replay, there is a framerate difference\r\n\t\t\t\t\t\t\t\t\t\t\t// between the initial frames of play/record before\r\n\t\t\t\t\t\t\t\t\t\t\t// getting our data synced up.\r\n\t\t\t{\r\n\t\t\t\tdiff = 1;  // keep it at 60 hz before synchronization.\r\n\t\t\t}\r\n\t\t\tReplay::StoreFrameLength( diff );\r\n\t\t}\r\n\t}\r\n\t*/\r\n\tgTimerInfo.render_vblank = GetGameVblanks();\r\n\tdiff = (int)(gTimerInfo.render_vblank - gTimerInfo.render_last_vblank);\r\n\r\n\r\n\tgTimerInfo.render_buffer[ gTimerInfo.render_index++] = diff;\r\n\tif ( gTimerInfo.render_index == vSMOOTH_N)\r\n\t{\r\n\t\tgTimerInfo.render_index = 0;\t\t\r\n\t}\r\n\tint total = 0;\r\n\tint uncapped_total = 0;\r\n\tfor (int i=0;i<vSMOOTH_N;i++)\r\n\t{\r\n\t\t\r\n\t\tdiff = gTimerInfo.render_buffer[i];\r\n\t\tuncapped_total += diff;\r\n\t\tif (diff > 10 || diff <= 1)\t\t// handle very bad values\r\n\t\t{\r\n\t\t\tdiff = 1;\r\n\t\t}\r\n\t\tif (diff >4) \t\t\t\t\t// limit to 4\r\n\t\t{\r\n\t\t\tdiff = 4;\r\n\t\t}\t\t\r\n\t\ttotal += diff;\r\n\t}\r\n\tgTimerInfo.render_length = (float)total/(float)vSMOOTH_N; \r\n\tgTimerInfo.uncapped_render_length = (double)uncapped_total/(double)vSMOOTH_N; \r\n\tgTimerInfo.frame_length = gTimerInfo.render_length/(float)Config::FPS()*GetSlomo();\r\n\t\r\n//\tprintf (\"%d:  %d, %f\\n\",(int)GetRenderFrame(),diff, gTimerInfo.render_length);\r\n\t\r\n}\r\n\r\nuint64\tGetRenderFrame( void )\r\n{\r\n\t\r\n\t\r\n\treturn s_render_frame;\r\n}\r\n\r\n\r\nvoid Vblank( void )\r\n{\r\n\t\r\n\ts_total_vblanks++;\r\n\ts_vblank++;\r\n}\r\n\r\nstatic uint64 GetGameVblanks( void )\r\n{\r\n\t\r\n\t\r\n\treturn s_vblank;\r\n}\r\n\r\nuint64 GetVblanks( void )\r\n{\r\n\treturn ( s_total_vblanks );\r\n}\r\n\r\n\r\n// float FrameLength()\r\n// returns the PROJECTED length of the next frame, for use in logic calculations\r\n// This time is in SECONDS, so typically will be 0.016666 if running at 1 60th\r\n// done by averaging the frame lengths of the last N frames (default N = 4)\r\n// at 60fps (NTSC), this would return 1/60\r\n// at 50fps (PAL), this would return 1/50\t\t   \r\n// complications arise when the framerate changes\r\n// we want the physics to move smoothly and consistently at all framerates\r\n// however, all we know is the number of ticks the last frames took\r\n// we also need to ensure that the total of all the \"FrameLength\" calls will\r\n// reflect the actual time that has passed\r\n//\t\t\t\t |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |   |    |   \r\n// say we have   1    1    1    .    2    1    1    1    .    2    1    .    2    1    1    1   .    2 \r\n//    (10x1 + 4x2  = 18 frames\r\n//\r\n//\r\n// now, let's work in 1/60ths of a second for now....\r\n// let's take the average of the last 4 frames, as the logic time we will return for this frame\r\n//\r\n//               1    1    1         1.25 1.25 1.25 1.25     1.25 1.25      1.5  1.5  1.25 1.25     1.25\r\n//\r\n// the reason we do the averaging is to smooth out discontinuities\r\n// if we simply use the length of the previous frame, then if we were to be alternating between 1 and 2 frames\r\n// then the logic would move 2 on frames of length 1, and move 1 on frames of length 2\r\n// this would essentially make the skater visually move alternately .5x and 2x his actual speed\r\n// this looks incredibly jerky, as there is a 4x difference per frame   \r\n// by smoothing it out, you would move 1.5 on every frame, giving relative motion of 0.6666 and 1.3333, \r\n// this is still jerky, but half as much as the unsmoothed version.\r\n\r\n\r\nvoid SetSlomo(float slomo)\r\n{\r\n\ts_slomo = slomo;\r\n}\r\n\r\nfloat GetSlomo()\r\n{\r\n\treturn s_slomo;\r\n}\r\n \r\nfloat FrameLength()\r\n{\r\n\r\n\treturn gTimerInfo.frame_length;\r\n//\treturn gTimerInfo.render_length/(float)Config::FPS()*GetSlomo();\r\n}\r\n\r\n\r\n\r\ndouble UncappedFrameLength()\r\n{\r\n\r\n\r\n\treturn gTimerInfo.uncapped_render_length/(float)Config::FPS();\r\n}\r\n\r\n\r\n\r\nuint64 now;\r\n\r\n// wait until Vsyncs changes \t\t  \r\nvoid VSync()\r\n{\r\n\tnow = GetVblanks();\r\n\twhile (now == GetVblanks());\t\r\n\tnow = GetVblanks();\r\n\t\r\n\ts_milliseconds = (Time) (((float)(uint32)s_vblank)*(1000.0f / (float)Config::FPS()));\r\n\t\r\n}\r\n\r\n// wait until VSync changes from what it was\r\n// (Might return immediately, if it's already changed)\r\nvoid VSync1()\r\n{\r\n\twhile (now == GetVblanks());\t\r\n\tnow = GetVblanks();\r\n\ts_milliseconds = (Time) (((float)(uint32)s_vblank)*(1000.0f / (float)Config::FPS()));\r\n}\r\n\r\n \r\n\r\n#if 1\r\n\r\n// K: These are now inline in timer.h\r\n/*\r\nMicroSeconds \tGetTimeInUSeconds ( void )\r\n{\r\n\t\r\n    \r\n\tuint64\thigh0, low0, high1, low1;\r\n\r\n    high0 = s_count;\r\n    low0  = *T0_COUNT;\r\n    high1 = s_count;\r\n    low1  = *T0_COUNT;\r\n\r\n\r\n    if ( high0 == high1 )\r\n    {\r\n\t\treturn ((high0 * vHIREZ_CMP) + low0)/150;\r\n    }\r\n    else\r\n    {\r\n\t\treturn ((high1 * vHIREZ_CMP) + low1)/150;\r\n    }\r\n\r\n}\r\n\r\n// Added by Ken, to get higher resolution when timing Script::Update, which needs to\r\n// subtract out the time spent in calling C-functions to get an accurate measurement\r\n// of how long the actual script interpretation is taking.\r\nCPUCycles \tGetTimeInCPUCycles ( void )\r\n{\r\n\t\r\n    \r\n\tuint64\thigh0, low0, high1, low1;\r\n\r\n    high0 = s_count;\r\n    low0  = *T0_COUNT;\r\n    high1 = s_count;\r\n    low1  = *T0_COUNT;\r\n\r\n\r\n    if ( high0 == high1 )\r\n    {\r\n\t\treturn ((high0 * vHIREZ_CMP) + low0);\r\n    }\r\n    else\r\n    {\r\n\t\treturn ((high1 * vHIREZ_CMP) + low1);\r\n    }\r\n\r\n}\r\n*/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nvoid RestartClock( void )\r\n{\r\n\tInitTimerInfo( );\r\n}\r\n\r\n\r\nTime\tGetTime ( void )\r\n{\r\n\t\r\n    \r\n\t//return ( GetTimeInUSeconds() / 1000 );\r\n\t//return s_count;\r\n\t// A less accurate time, but much faster than doing a 64 bit divide.\r\n\t//return ((int)s_vblank)*1000/60;\r\n\t\r\n\t// Ken Note: The casting of s_vblank (which is a uint64) to a uint32 before casting to a float is important. If the\r\n\t// uint64 is cast straight to a float it will do tons of floating point stuff which take ages.\r\n\t//\r\n\t// (Mick:  updated to use vVBLANK_HZ)\r\n//\tif ( Replay::UseNormalClock( ) )\r\n//\t{\r\n\t\treturn (int) (((float)(uint32)s_vblank)*(1000.0f / (float)Config::FPS()));\r\n//\t\treturn (int) s_milliseconds;\r\n//\t}\r\n//\telse\r\n//\t{\r\n//\t\treturn (int) (((float)(uint32)gTimerInfo.render_vblank )*(1000.0f/ (float)Config::FPS()));\r\n//\t}\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n#else // __NOPT_PROFILE__\r\n\r\n#ifdef __USER_MATT__\r\n#error Wrong Motherfuckin Timer\r\n#endif\r\n\r\nTime\tManager::GetTime ( void )\r\n{\r\n\t\r\n    \r\n\tuint64\thigh0, low0, high1, low1;\r\n\r\n    high0 = s_count;\r\n    low0  = *T0_COUNT;\r\n    high1 = s_count;\r\n    low1  = *T0_COUNT;\r\n\r\n    if ( high0 == high1 )\r\n    {\r\n\t\treturn static_cast<uint64>(( high0 | ( low0 & 0xffff )) / 9375 );\r\n    }\r\n    else\r\n    {\r\n\t\treturn static_cast<uint64>(( high1 | ( low1 & 0xffff )) / 9375 );\r\n    }\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n// K: This is now inline in timer.h\r\n/*\r\nMicroSeconds\tGetTimeInUSeconds ( void )\t   // remove ?\r\n{\r\n\t\r\n    \r\n\tuint64\thigh0, low0, high1, low1;\r\n\r\n    high0 = s_count;\r\n    low0  = *T0_COUNT;\r\n    high1 = s_count;\r\n    low1  = *T0_COUNT;\r\n\r\n    if ( high0 == high1 )\r\n    {\r\n\t\treturn static_cast<uint64>(( high0 + ( low0 & 0xffff )) / 9 );\r\n    }\r\n    else\r\n    {\r\n\t\treturn static_cast<uint64>(( high1 + ( low1 & 0xffff )) / 9 );\r\n    }\r\n}\r\n*/\r\n\r\n#endif // \r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace Tmr\r\n"
  },
  {
    "path": "Code/Sys/siodev.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSIO\t    \t\t\t\t\t\t\t\t\t\t        **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/26/2000\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsys/siodev.h    \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __SYS_SIODEV_H\r\n#define __SYS_SIODEV_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/list.h>\r\n#include <core/task.h>\r\n#include <core/support/ref.h>\r\n\r\n#ifdef __PLAT_NGPS__\r\n#include <libpad.h>\r\n#endif\r\n\r\n#ifdef __PLAT_XBOX__\r\n#include <xtl.h>\r\n#endif\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace SIO\r\n{\r\n\r\n\r\n\r\n#define CTRL_BUFFER_LENGTH      32\r\n#define ACTUATOR_BUFFER_LENGTH  32\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nenum Capabilities\r\n{\r\n    mANALOG         = 0x0001,\r\n    mACTUATORS      = 0x0002,\r\n    mANALOG_BUTTONS = 0x0004,\r\n};\r\n\r\nenum ButtonMode\r\n{\r\n\tvDIGITAL,\r\n\tvANALOG\r\n};\r\n\r\nclass  Data  : public Spt::Class\r\n{\r\n    \r\n\r\n    friend class Device;\r\n    friend class Search;\r\n\r\nprivate :\r\n    int                 m_type;     // controller type ( dual shock(2)/digital/analog/neGcon )\r\n    int                 m_port;     // one of two standard ps2 controller ports\r\n    int                 m_slot;     // (in context of multitap) which slot on that port\r\n    bool                m_valid;    // is its control data valid?\r\n    unsigned char*\t\tm_dma_buff;\r\n    unsigned char       m_control_data[CTRL_BUFFER_LENGTH];                        \r\n    unsigned char       m_actuator_align[ACTUATOR_BUFFER_LENGTH];\r\n    unsigned char       m_actuator_direct[ACTUATOR_BUFFER_LENGTH];\r\n    unsigned char       m_actuator_max[ACTUATOR_BUFFER_LENGTH];\r\n\t\r\n#\tifdef __PLAT_XBOX__\r\n\tHANDLE\t\t\t\tm_handle;\r\n#\tendif\r\n\r\n\t// Ken: Stores the m_actuator_direct values when the game is paused.\r\n\tunsigned char       m_actuator_old_direct[ACTUATOR_BUFFER_LENGTH];\r\n\tSpt::Ref\t\t\tm_paused_ref;\r\n\t\r\n\t// K: Whether the actuators are disabled.\r\n\tbool\t\t\t\tm_actuators_disabled;\r\n\t\r\n    Flags<Capabilities> m_caps;     // device capabilities\r\n\tint\t\t\t\t\tm_button_mode;\r\n    int                 m_num_actuators;\r\n\tvoid*\t\t\t\tm_prealbuffer;\r\n};\r\n\r\nclass  Device  : public Spt::Class\r\n{\r\n\t\r\n\r\n\tfriend class Manager;\r\n    friend class Search;\r\n    \r\npublic :\r\n    \r\n    enum Type\r\n    {\r\n        vNEGI_COM = 2,\r\n        vKONAMI_GUN = 3,\r\n        vDIGITAL_CTRL = 4,\r\n        vJOYSTICK = 5,\r\n        vNAMCO_GUN = 6,\r\n        vANALOG_CTRL = 7,\r\n        vFISHING_CTRL = 0x100,\r\n        vJOG_CTRL = 0x300\r\n    };\r\n\r\n\r\n\t\t\t\t\t\t\tDevice( int index, int port, int slot );\r\n\tvirtual\t\t\t\t\t~Device();\r\n\r\n\tvoid\t\t\t        Acquire ( void );\r\n\tvoid\t\t\t        Unacquire ( void );           \r\n    void                    ActivateActuator( int act_num, int percent );\r\n    void                    ActivatePressureSensitiveMode( void );\r\n    void                    DeactivatePressureSensitiveMode( void );\r\n    \r\n    int                     GetType( void );\r\n    int                     GetPort( void );\r\n    int                     GetSlot( void );\r\n    int                     GetIndex( void );\r\n\tvoid\t\t\t\t\tSetPort( int port );\r\n    unsigned char           *GetControlData( void );\r\n    Flags<Capabilities>     GetCapabilities( void );\r\n\tint\t\t\t\t\t\tGetButtonMode( void );\r\n    bool                    HasValidControlData( void );\r\n\tbool\t\t\t\t\tIsPluggedIn();\r\n\tbool\t\t\t\t\tEnabled() {return !m_data.m_actuators_disabled;}\r\n\t\r\n\t\t\t\t\t\t\t\t\t\r\n\tvoid\t\t\t\t\tPause(); \t// K: Called when game is paused, so that the pad temporarily stops vibrating.\r\n\tvoid\t\t\t\t\tUnPause();\t// K: Called when game is unpaused.\r\n\tvoid\t\t\t\t\tDisableActuators();\t// K: Disables vibration\r\n\tvoid\t\t\t\t\tEnableActuators();\t// K: Enables vibration\r\n\tvoid\t\t\t\t\tResetActuators();\t// Mick: Stops any vibration by disabling, then enabling (or vice versa)\r\n\r\n\t\t\t\t\t\t\t// K: Stops vibration, and ensures it won't get turned on again when\r\n\t\t\t\t\t\t\t// the game is unpaused.\r\n\tvoid\t\t\t\t\tStopAllVibrationIncludingSaved(); \r\n\r\nprivate :\r\n\r\n    enum State\r\n    {   \r\n        vIDLE,\r\n        vACQUIRING,\r\n        vACQUIRED,\r\n\t\tvPRESS_MODE_ON_COMPLETE,\r\n\t\tvPRESS_MODE_OFF_COMPLETE,\r\n        vBUSY,\r\n        vNUM_STATES\r\n    };\r\n\r\n    enum Status\r\n    {\r\n        vREADY,\r\n\t\tvCONNECTED,\r\n        vDISCONNECTED,\r\n        vNOTREADY\r\n    };\r\n    \r\n\tLst::Node<Device>*\t    m_node;\r\n    Data                    m_data;\r\n    State                   m_state;\r\n    State                   m_next_state;\r\n    int                     m_index;\r\n    \r\n\tbool\t\t\t\t\tm_plugged_in; // K: True if the pad is plugged in & acquired, false otherwise.\r\n\t\r\n#\tifdef __PLAT_XBOX__\r\n\tunsigned int\t\t\tm_unplugged_counter;\r\n\tunsigned int\t\t\tm_unplugged_retry;\r\n\tbool \t\t\t\t\tm_pressed;\r\n\tbool\t\t\t\t\tm_start_or_a_pressed;\r\n#\tendif // __PLAT_XBOX__\r\n\r\n    void                    process( void );\r\n    void\t\t\t        read_data ( void );         \r\n    void                    wait( void );\r\n    void                    acquisition_pending( void );\r\n    void                    query_capabilities( void );\r\n    \r\n    int                     get_status( void );\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline  int     Device::GetType( void )\r\n{\r\n    \r\n\r\n    return m_data.m_type;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline  int     Device::GetIndex( void )\r\n{\r\n    \r\n\r\n    return m_index;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline  int     Device::GetPort( void )\r\n{\r\n    \r\n\r\n    return m_data.m_port;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tvoid\tDevice::SetPort( int port )\r\n{\r\n\r\n\tm_data.m_port = port;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline  int     Device::GetSlot( void )\r\n{\r\n    \r\n\r\n    return m_data.m_slot;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline  unsigned char    *Device::GetControlData( void )\r\n{\r\n    \r\n\r\n    return m_data.m_control_data;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline  Flags<Capabilities>    Device::GetCapabilities( void )\r\n{\r\n    return m_data.m_caps;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline\tint\t\tDevice::GetButtonMode( void )\r\n{\r\n\treturn m_data.m_button_mode;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\ninline  bool    Device::HasValidControlData( void )\r\n{\r\n    \r\n\r\n    return m_data.m_valid;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace SIO\r\n\r\n#endif\t// __SYS_SIODEV_H\r\n\r\n"
  },
  {
    "path": "Code/Sys/sioman.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSIO (SIO_)   \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/26/2000\t-\tspg\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsys/sioman.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __SYS_SIOMAN_H\r\n#define __SYS_SIOMAN_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/singleton.h>\r\n#include <core/list.h>\r\n#include <core/task.h>\r\n\r\n#include <sys/siodev.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace SIO\r\n{\r\n\r\n    \r\n\r\n\tenum\r\n\t{\r\n\t\t\r\n#\t\tif defined( __PLAT_XBOX__ )\r\n\t\tvMAX_PORT = 4,\r\n#\t\telif defined( __PLAT_NGC__ )\r\n\t\tvMAX_PORT = 4,\r\n#\t\telse\r\n\t\tvMAX_PORT = 2,\r\n#\t\tendif\r\n\t\tvMAX_SLOT = 1,\r\n\t\tvMAX_DEVICES = ( vMAX_PORT * vMAX_SLOT )\r\n\t};   \r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nclass  Manager  : public Spt::Class\r\n{\r\n\t\r\n\r\n\ttypedef Lst::Head< Device >\t\t\tDeviceList;         \r\n\r\npublic :\r\n\t\r\n\tTsk::BaseTask&\t\t\t\tGetProcessDevicesTask ( void );\r\n    Device*                     GetDeviceByIndex( int index );\r\n    Device*                     GetDevice( int port, int slot );\r\n\tvoid\t\t\t\t\t\tPause();\r\n\tvoid\t\t\t\t\t\tUnPause();\r\n\t\r\n#\tif defined( __PLAT_XBOX__ )\r\n\tvoid\t\t\t\t\t\tProcessDevices();\r\n#\tendif\r\n\r\nprivate : \r\n\tvirtual\t\t\t\t\t\t~Manager();\r\n\t\t\t\t\t\t\t\tManager();                                              \r\n    \r\n    Device*\t\t\t\t\t    create_device( int index, int port, int slot );\r\n        \r\n    static\tTsk::Task< DeviceList >::Code\tprocess_devices;    \r\n    \r\n    DeviceList\t\t\t\t\tm_devices;\r\n    \r\n    Tsk::Task< DeviceList >*\tm_process_devices_task; \r\n    \r\n\tDeclareSingletonClass( Manager );\r\n};\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\nclass  Search : public  Lst::Search< Device >\r\n{\r\n\t\r\n\r\npublic :\r\n\t\t\t\t\tSearch (void) {} \r\n\t\t\t\t\t~Search (void) {} \r\nprivate :\r\n\t\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nint LoadIRX(const char *pName, int num_args = 0, char* args = NULL, bool assert_on_fail = true);\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\ninline\tTsk::BaseTask&\tManager::GetProcessDevicesTask ( void )\r\n{\r\n\t\r\n\t\r\n\tDbg_AssertType ( m_process_devices_task, Tsk::BaseTask );\r\n\r\n\treturn *m_process_devices_task;\r\n}\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace SIO\r\n\r\n#endif\t// __SYS_SIOMAN__H\r\n\r\n"
  },
  {
    "path": "Code/Sys/sys.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSys \t\t \t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsys.cpp\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t05/27/99\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSYS Debug symbols \t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <sys/profiler.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nDbg_DefineProject ( SysLib, \"System Library\")\r\n\r\n\r\nnamespace Sys\r\n{\r\n\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Externals\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Sys\r\n"
  },
  {
    "path": "Code/Sys/sys.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t    **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tSystem Header\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t10/26/99\tmjb\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\tsys/sys.h\t\t\t\t\t\t\t\t\t\t\t    **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __SYS_SYS_H\r\n#define __SYS_SYS_H\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n#ifdef __PLAT_WN32__\r\n\r\n#else\r\n#ifdef __PLAT_NGPS__\r\n\r\n#else\r\n#ifdef __PLAT_XBOX__\r\n\r\n#else\r\n#ifdef __PLAT_NGC__\r\n\r\n#else\r\n#error Unsupported Platform\r\n#endif\r\n#endif\r\n#endif\r\n#endif\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace Sys\r\n{\r\n \r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Sys\r\n\r\n#endif\t// __SYS_SYS_H\r\n"
  },
  {
    "path": "Code/Sys/timer.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTimer (TMR)\t\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\ttimer.cpp\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t01/13/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\tSystem Timer\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n#include <sys/timer.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  DBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n\r\nnamespace Tmr\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Private Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n} // namespace Tmr\r\n"
  },
  {
    "path": "Code/Sys/timer.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t   \t  Neversoft Entertainment\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 1999 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\tSYS Library\t\t   \t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\tTimer (TMR)\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated:\t\t01/13/00\t-\tmjb\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\ttimer.h\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __SYS_TIMER_H\r\n#define __SYS_TIMER_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifdef __PLAT_NGPS__\r\n#include <eeregs.h> // Needed for T0_COUNT\r\n#endif\r\n\r\n#ifndef __CORE_DEFINES_H\r\n#include <core/defines.h>\r\n#endif\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n// Ken: This declaration is to avoid having to include config.h, to reduce dependencies.\r\nnamespace Config\r\n{\r\nextern int gFPS;\r\n}\r\n\r\nnamespace Tmr\r\n{\r\n\r\nenum \r\n{\r\n\tvRESOLUTION\t\t= 1000,\t\t// timer resolution in milliseconds\r\n\tvMAX_TIME\t\t= vUINT_MAX,\r\n};\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t     Type Defines\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#define vHIREZ_CMP 15000\t\t\t// 15000\r\n\r\ntypedef uint32\tTime;\t\t\t\t\t// Milliseconds (so wraps after 49 days)\r\n\r\n#ifdef __PLAT_NGPS__\r\ntypedef uint32\tMicroSeconds;\t\t\t// MicroSeconds\r\ntypedef uint32\tCPUCycles;\r\n#else\r\ntypedef uint64\tCPUCycles;\t\t\t\t// CPUCycles, also needs higher resolution\r\ntypedef uint64\tMicroSeconds;\t\t\t// MicroSeconds\r\n#endif\r\n\r\nTime\t\t\t\t\tGetTime( void );  // GetTimeInMSeconds\r\n\r\n#ifdef __PLAT_NGPS__\r\nextern volatile uint32 gCPUTimeCount;\r\ninline CPUCycles GetTimeInCPUCycles ( void ) {return gCPUTimeCount* vHIREZ_CMP + *T0_COUNT;}\r\ninline MicroSeconds GetTimeInUSeconds( void ) {return GetTimeInCPUCycles() / 150; }\r\n#else\r\nCPUCycles\t\t\t\tGetTimeInCPUCycles( void );\r\nMicroSeconds\t\t\tGetTimeInUSeconds( void );\r\n#endif\r\n\r\nvoid\tOncePerRender();\r\nuint64\tGetRenderFrame();\r\nvoid \tVblank();\r\n\r\n// total vblanks from bootup... be careful not to use this for anything that would affect replay!\r\nuint64 \tGetVblanks();\r\n\r\nfloat \tFrameLength();\r\ndouble \tUncappedFrameLength();\r\nvoid \tVSync();\r\nvoid \tVSync1();\r\nfloat \tGetSlomo();\r\nvoid \tSetSlomo(float slomo);\r\nvoid\tRestartClock( void );\r\n\r\nvoid\tStoreTimerInfo( void );\r\nvoid\tRecallTimerInfo( void );\r\n\r\nvoid\tInit(void);\r\nvoid\tDeInit(void);\r\n\r\n#ifdef __PLAT_NGC__\r\nvoid\tIncrementVblankCounters( void );\r\n#endif\r\n\r\n#ifdef __PLAT_XBOX__\r\nvoid\tInstallVSyncHandlers( void );\r\n#endif\r\n\r\n#ifdef\t__PLAT_NGPS__\r\nextern Time  s_milliseconds;\r\ninline Time\tGetQuickTime ( void ) {return s_milliseconds;}\r\n#endif\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\n/*************************************************************************\r\n**\t\t\t\t\t\t\t\tMacros\t\t\t\t\t\t\t\t\t**\r\n**************************************************************************/\r\n\r\ninline \tTime\tElapsedTime( Time time )\r\n{\r\n\treturn ( GetTime() - ( time ));\r\n}\r\n\r\ninline \tfloat\tFrameRatio()\r\n{\t\t\t\t\t\t\t\t\r\n\treturn ( FrameLength() * 60.0f);\t  \t// note this is 60 regardless of NTSC/PAL\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t// as we want it to return 1.2 for pal\r\n}\r\n\r\ninline \tTime\tInVBlanks( Time time )\r\n{\r\n\treturn ( time / ( vRESOLUTION / Config::gFPS ));\r\n}\r\n\r\ninline \tTime\tInMSeconds( Time time )\r\n{\r\n\treturn ( time / ( vRESOLUTION / 1000 ));\r\n}\r\n\r\ninline \tTime\tInHSeconds( Time time )\r\n{\r\n\treturn ( time / ( vRESOLUTION / 100 ));\r\n}\r\n\r\ninline \tTime\tInTSeconds( Time time )\r\n{\r\n\treturn ( time / ( vRESOLUTION / 10 ));\r\n}\r\n\r\ninline \tTime\tInSeconds( Time time )\r\n{\r\n\treturn ( time /   vRESOLUTION );\r\n}\r\n\r\ninline \tTime\tInMinutes( Time time )\r\n{\r\n\treturn ( time / ( vRESOLUTION * 60 ));\r\n}\r\n\r\ninline \tTime\tInHours( Time time )\r\n{\r\n\treturn ( time / ( vRESOLUTION * 60 * 60 ));\r\n}\r\n\r\ninline\tTime\tVBlanks( int time )\r\n{\r\n\treturn ( time * ( vRESOLUTION / Config::gFPS ));\r\n}\r\n\r\ninline\tTime\tVBlanksF( float time )\r\n{\r\n\treturn (Time) ( time * ((float) vRESOLUTION / (float) Config::gFPS ));\r\n}\r\n\r\ninline\tTime\tMSeconds( Time time )\r\n{\r\n\treturn ( time * ( vRESOLUTION / 1000 ));\r\n}\r\n\r\ninline\tTime\tHSeconds( Time time )\r\n{\r\n\treturn ( time * ( vRESOLUTION / 100 ));\r\n}\r\n\r\ninline\tTime\tTSeconds( Time time )\r\n{\r\n\treturn ( time * ( vRESOLUTION / 10 ));\r\n}\r\n\r\ninline\tTime\tSeconds( Time time )\r\n{\r\n\treturn ( time * vRESOLUTION );\r\n}\r\n\r\ninline\tTime\tMinutes( Time time )\r\n{\r\n\treturn ( time * ( vRESOLUTION * 60 ));\r\n}\r\n\r\ninline\tTime\tHours( Time time )\r\n{\r\n\treturn ( time * ( vRESOLUTION * 60 * 60 ));\r\n}\r\n\r\n\r\n} // namespace Tmr\r\n\r\n#endif\t// __SYS_TIMER_H\r\n"
  },
  {
    "path": "Code/standard.cpp",
    "content": "/******************************************************************\r\n Standard.cpp - sample file illustrating and documenting the \r\n Neversoft coding standards, such as they are.\r\n This file is initially offered up as a guideline, and is open to change\r\n It is intended to be short\r\n*****************************************************************/\r\n\r\n// Tabs set to four.  Tabs do not expand to spaces.\r\n//  +\t+\t+\t+\t+\t+\t+\t+\t+\t+\t+\t+\r\n//  +...+...+...+...+...+...+...+...+...+...+...+\r\n// (the above two lines should line up)\r\n\r\n// Note, this (interface) section should be in a .H file, it is presented here for clarity\r\n\r\nconst \t\tint vMAGIC_NUMBER = 100;\t \t\t\t\t// const values in UPPER_CASE, prepended by v (for value)\r\n// OR const int\tMAGIC_NUMBER = 100;\t \t\t\t\t\t// do we need the v?  \r\n\r\n#define\tSKATER_GRAVITY\t(2.0f * Script::GetFloat(\"skt_g\"))\t//\t#define macro is UPPER_CASE \r\n\r\nenum EDialogBoxResult\t\t\t   \t\t\t\t\t// Enums start with 'E'\r\n{\r\n\tDB_YES \t=\t\t\t0x00000001,\t\t\t \t\t// Do we need a v here? or is it clear?\r\n\tDB_NO   =\t\t\t0x00000002,\r\n};\r\n\r\n// Note: type, member name and comments all line up in columns\r\n \r\nclass CTallTree\t\t\t\t\t\t\t\t\t\t// Classes start with 'C', and are CamelBack\r\n{\t\t\t\t\t\t\t\t\t\t\t\t\t// '{' and '}' line up like this\r\npublic:\t\t\t\t\t\t\t\t\t\t\t\t// public members come first, in CamelBack\t  \t\r\n\tint\t\t\t\t\tGetSomething();\t\t\t\t// public member function\r\n\tvoid\t\t\t\tDoSomething(int numberOfItems, char *p_items = NULL); \t\t// function parameters\r\n\tstatic int\t\t\tsGetNumberOfTrees();\t\t// static member function\r\n\tint\t\t\t\t\tmSomeNumber; \t\t\t\t// public member variable (not recommended)\r\n\tint\t*\t\t\t\tmpSomethingElse;\t\t\t// public member pointer\r\n\tint\t**\t\t\t\tmppSomethingElse;\t\t\t// public member pointer to pointer\r\n\r\nprivate:\t\t\t\t\t\t\t\t\t\t\t\t// private members come last, in lower_case_underscored\r\n\tint\t\t\t\t\tget_another();\t\t\t\t// private member function\r\n\tstatic int\t\t\ts_get_xxx();\t\t\t\t// private static function\r\n\tint\t\t\t\t\tm_another_number;\t\t\t// private member variable  \t\r\n\tchar *\t\t\t\tmp_letters_to_use;\t\t\t// private member pointer \r\n\tchar **\t\t\t\tmpp_thing_to_use;\t\t\t// private member pointer to pointer\r\n\tstatic int\t\t\ts_number_of_trees;\t\t\t// static member variable \r\n}\r\n\r\n/////////////////////////////////////////////////////////////\r\n// the following (implementation) section is the .CPP portion\r\n\r\nint\tGNumberOfCallsToSomeFunction;\t\t\t\t\t// Global, 'G'Prefix, CamelBack, not recommended\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t// usually for temporary debugging hacks   \r\n\r\nint\tCTallTree::s_number_of_trees;\t\t\t\t\t// instance of static variable\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\n\r\n////////////////////////////////////////////////////////////////////////\tfunction seperator\t\t\t\t\t\t\t\t\t\t\t\t  \r\n// Returns the number of trees inexistance\t\t    // function comment\r\nint CTallTree::sGetNumberOfTrees()\t \t\t\t\t// instance of static function\r\n{\r\n\treturn s_number_of_trees;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////\t\t\t\t\t\t\t\t\t\t\t\t\t  \r\nvoid CTallTree::DoSomething(int numberOfItems, char *p_itemsInList); \t\t// instance of member function \r\n{\r\n\tint\t\ttemp_value;\t\t\t\t\t\t\t\t// local variable in lower_case\r\n\t\r\n\tif (numberOfItems)\r\n\t{\t\t\t\t\t\t\t\t\t\t\t\t// note lining up of { and }\r\n\t\tp_itemsInList++;\t\t\t  \t\t\t\t// (reccomended) single line statement in curly brackets\r\n\t}\r\n\telse\t\t\t\t\t\t\t\t\t\t\t// 'else' on seperate line\r\n\t{\r\n\t\tprintf (\"%d\\n\",numberOfItems);\r\n\t\tprintf (\"%c\\n\",*p_itemsInList);\r\n\t}\r\n\t// TODO:  write more code\t\t\t\t\t\t// comment telling me what TODO\r\n}\r\n\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////\r\n// Cross platform compiling compatibility rules\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////////////\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \r\n// #1 Do Not initialize non-integral const static data members inside the class declaration.\r\n\r\nclass CScreenElement : public Obj::CObject\r\n{\r\n//\tstatic const float vJUST_LEFT = -1.0f;\t\t\t// WRONG!!\r\n\tstatic const float vJUST_LEFT;\t\t\t\t\t// Correct, value is defined below\r\n}\r\n\r\nconst float CScreenElement::vJUST_LEFT\t= -1.0f;\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n// #2 Do not redefine default parameters in the implementation of a function\r\n\r\n// e.g\r\nvoid  DoSomething(int numberOfItems, char *p_items = NULL); \t\t// wrong! should only be in .h declaration\r\n{\r\n // ...\r\n}\r\n\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n// #3 Alignment requires different code on different platforms\r\n//The __attribute__ aligned ((aligned(n))) compiler directive is GNU specific.\r\n//So the following class member (taken from sk\\gamenet\\gamenet.h) will cause\r\n//VC7 to crap out:\r\n\r\nchar m_net_thread_stack[ vNET_THREAD_STACK_SIZE ] __attribute__\r\n((aligned(16)));\r\n\r\n//The equivalent alignment directive for Xbox would be as follows:\r\n\r\n#pragma pack( 16 )\r\nchar m_net_thread_stack[ vNET_THREAD_STACK_SIZE ];\r\n#pragma pack()\r\n\r\n//So please conditionalise alignment directives for all platforms.\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n// #4 - \"far\" is a reserved keyword in VC++ (harkening back 16 bit memory models)\r\n//\r\n\r\n// bool far;   //  <<<<<<<<<<< wrong, will crap in VC++\r\n\r\n\tbool\tfind_far_collision;\t\t// correct, and more meaningful too!!\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n////////////////////////////////////////////////////////////////////////////\r\n// #5 - every #if.... directive must have a matching #endif\r\n// in GNU, you can just reach the end of a file, but VC++\r\n// with throw an error\r\n\r\n#ifdef __PLAT_NGPS__\r\n... some code\r\n... end of file     <<<<<<<<<<<<< wrong, needs #endif for VC++, but will compile fine in GNU\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n                                              \r\n"
  },
  {
    "path": "Code/template.cpp",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t<project name>\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t<module name>\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t<filename>.cpp\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t00/00/00\t-\tinitials\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t<description>\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#include <core/defines.h>\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tDBG Information\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\nnamespace <module name>\r\n{\r\n\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t  Externals\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tPrivate Types\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Private Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t Public Data\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Functions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace <module name>\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Code/template.h",
    "content": "/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t              Neversoft Entertainment.\t\t\t                **\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \t**\r\n**\t\t\t\t   Copyright (C) 2000 - All Rights Reserved\t\t\t\t   \t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n******************************************************************************\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tProject:\t\t<project name>\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tModule:\t\t\t<module name>\t\t\t \t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tFile name:\t\t<filename>.h\t\t\t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tCreated by:\t\t00/00/00\t-\tinitials\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n**\tDescription:\t<description>\t\t \t\t\t\t\t\t\t\t\t**\r\n**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n#ifndef __DIR_SUBDIR_FILE_H\r\n#define __DIR_SUBDIR_FILE_H\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  \t  Includes\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\t   Defines\t\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n\r\nnamespace <module-name>\r\n{\r\n\r\n\t\t\t\t\t\t\r\n\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\tClass Definitions\t\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t Private Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Private Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t  Public Declarations\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t   Public Prototypes\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/*****************************************************************************\r\n**\t\t\t\t\t\t\t\tInline Functions\t\t\t\t\t\t\t**\r\n*****************************************************************************/\r\n\r\n/******************************************************************/\r\n/*                                                                */\r\n/*                                                                */\r\n/******************************************************************/\r\n\r\n} // namespace <module-name>\r\n\r\n#endif\t// __DIR_SUBDIR_FILE_H\r\n\r\n\r\n"
  }
]